diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2010-2014, Galois, Inc.
+
+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 names of the authors nor the names of other
+      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.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,146 @@
+import Distribution.Simple
+import Distribution.Simple.Setup
+import Distribution.Simple.Utils (rawSystemExit, rawSystemExitWithEnv, installOrdinaryFile,
+        installExecutableFile, copyFileVerbose, createDirectoryIfMissingVerbose)
+import Distribution.Simple.LocalBuildInfo (
+        LocalBuildInfo(..), InstallDirs(..), absoluteInstallDirs)
+import Distribution.PackageDescription (PackageDescription(..),
+        HookedBuildInfo(..), BuildInfo(..), emptyBuildInfo,
+        updatePackageDescription, FlagAssignment(..), FlagName(..))
+import Distribution.Verbosity (verbose, Verbosity(..))
+import Distribution.System (OS(..), Arch(..), Platform (..), buildOS, buildPlatform)
+import System.Directory
+import System.FilePath
+import System.Environment( getEnvironment )
+import Control.Monad(when)
+
+-- Here we install custom hooks to deal with fetching and building the ABC
+-- sources.  This mostly involves calling into the "scripts/setup-abc.sh"
+-- and "scripts/build-abc.sh" scripts at the proper times.
+-- 
+-- The other thing we must do is automagically munge the cabal description
+-- to handle the ABC source tree.  We do this by editing, at runtime, the
+-- cabal package description to include the ABC sources files to `extra-source-files`
+-- (so `cabal sdist` works as expected), and to add the ABC source tree directories
+-- to `include-dirs`.  This is done by reading the files `scripts/abc-sources.txt`
+-- and `scripts/abc-incl-dirs.txt`, which are set up by `scripts/setup-abc.sh`.
+--
+-- Finally, we must also include some information about where do find the libabc.a
+-- and libabc.dll files.
+--
+-- The way we have to do this is sort of nasty, but implementing the "readDesc" user
+-- hook doesn't seem to work the way I expect, so we have to modify the package description
+-- "in flight" inside each of the various hooks.
+
+main = defaultMainWithHooks simpleUserHooks
+    { preConf  = \a f -> let v = fromFlag $ configVerbosity f
+                             fs = configConfigurationsFlags f
+                          in setupAbc v >> buildAbc v fs >> preConf simpleUserHooks a f
+
+    , preSDist = \a f -> let v = fromFlag $ sDistVerbosity f
+                          in setupAbc v >> preSDist simpleUserHooks a f
+
+    , postConf = \a f pkg_desc lbi -> do
+                    pkg_desc' <- abcPkgDesc pkg_desc
+                    postConf simpleUserHooks a f pkg_desc' lbi
+    , buildHook = \pkg_desc lbi h f -> do
+                    pkg_desc' <- abcPkgDesc pkg_desc
+                    buildHook simpleUserHooks pkg_desc' lbi h f
+    , sDistHook = \pkg_desc lbi h f -> do
+                    pkg_desc' <- abcPkgDesc pkg_desc
+                    sDistHook simpleUserHooks pkg_desc' lbi h f
+    , haddockHook = \pkg_desc lbi h f -> do
+                    pkg_desc' <- abcPkgDesc pkg_desc
+                    haddockHook simpleUserHooks pkg_desc' lbi h f
+    , copyHook = \pkg_desc lbi h f -> do
+                    pkg_desc' <- abcPkgDesc pkg_desc
+                    copyHook simpleUserHooks pkg_desc' lbi h f
+    , instHook = \pkg_desc lbi h f -> do
+                    pkg_desc' <- abcPkgDesc pkg_desc
+                    instHook simpleUserHooks pkg_desc' lbi h f
+    , regHook = \pkg_desc lbi h f -> do
+                    pkg_desc' <- abcPkgDesc pkg_desc
+                    regHook simpleUserHooks pkg_desc' lbi h f
+    , unregHook = \pkg_desc lbi h f -> do
+                    pkg_desc' <- abcPkgDesc pkg_desc
+                    unregHook simpleUserHooks pkg_desc' lbi h f
+    , hscolourHook = \pkg_desc lbi h f -> do
+                    pkg_desc' <- abcPkgDesc pkg_desc
+                    hscolourHook simpleUserHooks pkg_desc' lbi h f
+    , testHook = \pkg_desc lbi h f -> do
+                    pkg_desc' <- abcPkgDesc pkg_desc
+                    testHook simpleUserHooks pkg_desc' lbi h f
+
+    , postCopy = postCopyAbc
+    , postInst = postInstAbc
+    }
+
+-- This is where we stash the static compiled ABC libraries
+static_dir = "dist"</>"build"
+
+-- Edit the package description to include the ABC source files,
+-- ABC include directories, and static library directories.
+abcPkgDesc :: PackageDescription -> IO PackageDescription
+abcPkgDesc pkg_desc = do
+  cwd <- getCurrentDirectory
+  abcSrcFiles <- fmap lines $ readFile "scripts/abc-sources.txt"
+  abcInclDirs <- fmap lines $ readFile "scripts/abc-incl-dirs.txt"
+  let pg' = updatePackageDescription (libDirAbc cwd abcInclDirs) pkg_desc
+  return pg'{ extraSrcFiles = extraSrcFiles pg' ++ abcSrcFiles 
+            }
+
+libDirAbc :: FilePath -> [FilePath] -> HookedBuildInfo
+libDirAbc cwd abcInclDirs = (Just buildinfo, [])
+    where buildinfo = emptyBuildInfo 
+                      { includeDirs = abcInclDirs
+                      , extraLibDirs = [cwd </> static_dir]
+                      }
+
+onWindows :: Monad m => m () -> m ()
+onWindows act = case buildPlatform of
+                  Platform _ Windows -> act
+                  _                  -> return ()
+
+-- If necessary, fetch the ABC sources and prepare for building
+setupAbc :: Verbosity -> IO ()
+setupAbc verbosity = do
+    env <- getEnvironment
+    rawSystemExitWithEnv verbosity "sh"
+        ("scripts/setup-abc.sh" : (tail . words . show $ buildPlatform))
+        env
+
+-- Build the ABC library and put the files in the expected places
+buildAbc :: Verbosity -> FlagAssignment -> IO ()
+buildAbc verbosity fs = do
+    let pthreads = maybe "0" (\x -> if x then "1" else "0") $ lookup (FlagName "enable-pthreads") fs
+    env <- getEnvironment
+    rawSystemExitWithEnv verbosity "sh"
+        ("scripts/build-abc.sh" : (tail . words . show $ buildPlatform))
+        ([("PTHREADS",pthreads)] ++ filter ((/="PTHREADS") . fst) env)
+    createDirectoryIfMissingVerbose verbosity True static_dir
+    copyFileVerbose verbosity "abc-build/libabc.a" (static_dir</>"libabc.a")
+    onWindows $ copyFileVerbose verbosity "abc-build/libabc.dll" (static_dir</>"abc.dll")
+
+-- Make sure the ABC libraries are installed in the appropriate places
+postInstAbc :: Args -> InstallFlags -> PackageDescription -> LocalBuildInfo -> IO ()
+postInstAbc _ flags pkg_descr lbi = do
+    let copyflags = defaultCopyFlags {
+                          copyDistPref  = installDistPref flags
+                        , copyDest      = toFlag NoCopyDest
+                        , copyVerbosity = installVerbosity flags
+                        }
+    postCopyAbc undefined copyflags pkg_descr lbi
+
+postCopyAbc :: Args -> CopyFlags -> PackageDescription -> LocalBuildInfo -> IO ()
+postCopyAbc _ flags pkg_descr lbi = do
+    let installDirs = absoluteInstallDirs pkg_descr lbi
+                . fromFlag . copyDest
+                $ flags
+        libPref = libdir installDirs
+        binPref = bindir installDirs
+        verbosity = fromFlag $ copyVerbosity flags
+        outDir  = libPref
+        copy dest f = installOrdinaryFile verbosity (static_dir</>f) (dest</>f)
+    createDirectoryIfMissingVerbose verbosity True binPref
+    copy libPref "libabc.a"
+    onWindows $ copy libPref "abc.dll"
diff --git a/abc-build/.hg_archival.txt b/abc-build/.hg_archival.txt
new file mode 100644
--- /dev/null
+++ b/abc-build/.hg_archival.txt
@@ -0,0 +1,5 @@
+repo: 27f68cec826fd69da083a19ad1384a074eb56f73
+node: 87fc2c2ca39f02ddd3bd204aba4cad4ea201c9e5
+branch: galois-abcBridge
+latesttag: null
+latesttagdistance: 2427
diff --git a/abc-build/.hgignore b/abc-build/.hgignore
new file mode 100644
--- /dev/null
+++ b/abc-build/.hgignore
@@ -0,0 +1,58 @@
+syntax:glob
+
+DebugLib/
+DebugExe/
+DebugExt/
+
+ReleaseLib/
+ReleaseExe/
+ReleaseExt/
+
+_TEST/
+lib/abc*
+lib/m114*
+lib/bip*
+docs/
+
+src/ext/
+src/xxx/
+src/aig/au/
+src/aig/ssm/
+src/aig/ddb/
+
+src/base/abc2/
+src/base/abc2d/
+
+*~
+*.orig
+
+*.[od]
+
+*.ncb
+*.opt
+*.plg
+
+*.zip
+
+abcspaceext.dsw
+abcext.dsp
+
+abcexe.vcproj*
+abclib.vcproj*
+abcspace.sln
+abcspace.suo
+
+*.pyc
+
+src/python/build
+src/python/bdist
+src/python/pyabc.py
+src/python/pyabc_wrap.*
+
+syntax: regexp
+
+^libabc.a$
+^abc$
+
+^arch_flags$
+
diff --git a/abc-build/Makefile b/abc-build/Makefile
new file mode 100644
--- /dev/null
+++ b/abc-build/Makefile
@@ -0,0 +1,149 @@
+
+CC   := gcc
+CXX  := g++
+LD   := $(CXX)
+
+MSG_PREFIX ?=
+
+$(info $(MSG_PREFIX)Using CC=$(CC))
+$(info $(MSG_PREFIX)Using CXX=$(CXX))
+$(info $(MSG_PREFIX)Using LD=$(LD))
+
+PROG := abc
+
+MODULES := \
+	$(wildcard src/ext) src/misc/ext \
+	src/base/abc src/base/abci src/base/cmd src/base/io \
+	src/base/main src/base/ver src/base/test \
+	src/bdd/cudd src/bdd/dsd src/bdd/epd src/bdd/mtr src/bdd/parse \
+	src/bdd/reo src/bdd/cas \
+	src/map/mapper src/map/mio src/map/super src/map/if \
+	src/map/amap src/map/cov src/map/scl src/map/mpm \
+	src/misc/extra src/misc/mvc src/misc/st src/misc/util src/misc/nm \
+	src/misc/vec src/misc/hash src/misc/tim src/misc/bzlib src/misc/zlib \
+	src/misc/mem src/misc/bar src/misc/bbl \
+	src/opt/cut src/opt/fxu src/opt/rwr src/opt/mfs src/opt/sim \
+	src/opt/ret src/opt/res src/opt/lpk src/opt/nwk src/opt/rwt \
+	src/opt/cgt src/opt/csw src/opt/dar src/opt/dau src/opt/sfm \
+	src/sat/bsat src/sat/csat src/sat/msat src/sat/psat src/sat/cnf src/sat/bmc \
+	src/bool/bdc src/bool/deco src/bool/dec src/bool/kit src/bool/lucky \
+	src/bool/rsb src/bool/rpo \
+	src/proof/pdr src/proof/abs src/proof/bbr src/proof/llb src/proof/live \
+	src/proof/cec src/proof/dch src/proof/fraig src/proof/fra src/proof/ssw \
+	src/proof/ssc src/proof/int \
+	src/aig/aig src/aig/saig src/aig/gia src/aig/ioa src/aig/ivy src/aig/hop \
+	src/aig/miniaig \
+	src/python 
+
+all: $(PROG)
+default: $(PROG)
+
+arch_flags : arch_flags.c
+	$(CC) arch_flags.c -o arch_flags
+
+ARCHFLAGS ?= $(shell $(CC) arch_flags.c -o arch_flags && ./arch_flags)
+OPTFLAGS  ?= -g -O #-DABC_NAMESPACE=xxx
+
+CFLAGS   += -Wall -Wno-unused-function -Wno-write-strings -Wno-sign-compare $(OPTFLAGS) $(ARCHFLAGS) -Isrc
+
+# Set -Wno-unused-bug-set-variable for GCC 4.6.0 and greater only
+ifneq ($(or $(findstring gcc,$(CC)),$(findstring g++,$(CC))),)
+empty:=
+space:=$(empty) $(empty)
+
+GCC_VERSION=$(shell $(CC) -dumpversion)
+GCC_MAJOR=$(word 1,$(subst .,$(space),$(GCC_VERSION)))
+GCC_MINOR=$(word 2,$(subst .,$(space),$(GCC_VERSION)))
+
+$(info $(MSG_PREFIX)Found GCC_VERSION $(GCC_VERSION))
+ifeq ($(findstring $(GCC_MAJOR),0 1 2 3),)
+$(info $(MSG_PREFIX)Found GCC_MAJOR>=4)
+ifeq ($(findstring $(GCC_MINOR),0 1 2 3 4 5),)
+$(info $(MSG_PREFIX)Found GCC_MINOR>=6)
+CFLAGS += -Wno-unused-but-set-variable
+endif
+endif
+
+endif
+
+# LIBS := -ldl -lrt
+LIBS := -ldl
+ifneq ($(findstring Darwin, $(shell uname)), Darwin)
+   LIBS += -lrt
+endif
+
+ifneq ($(READLINE),0)
+CFLAGS += -DABC_USE_READLINE
+LIBS += -lreadline
+endif
+
+ifneq ($(PTHREADS),0)
+CFLAGS += -DABC_USE_PTHREADS
+LIBS += -lpthread
+endif
+
+$(info $(MSG_PREFIX)Using CFLAGS=$(CFLAGS))
+CXXFLAGS += $(CFLAGS) 
+
+SRC  := 
+GARBAGE := core core.* *.stackdump ./tags $(PROG) arch_flags
+
+.PHONY: all default tags clean docs
+
+include $(patsubst %, %/module.make, $(MODULES))
+
+OBJ := \
+	$(patsubst %.cc, %.o, $(filter %.cc, $(SRC))) \
+	$(patsubst %.c, %.o,  $(filter %.c, $(SRC)))  \
+	$(patsubst %.y, %.o,  $(filter %.y, $(SRC))) 
+
+DEP := $(OBJ:.o=.d)
+
+# implicit rules
+
+%.o: %.c
+	@echo "$(MSG_PREFIX)\`\` Compiling:" $(LOCAL_PATH)/$<
+	@$(CC) -c $(CFLAGS) $< -o $@
+	@$(REMOVE_DRECTVE) $@
+
+%.o: %.cc
+	@echo "$(MSG_PREFIX)\`\` Compiling:" $(LOCAL_PATH)/$<
+	@$(CXX) -c $(CXXFLAGS) $< -o $@
+	@$(REMOVE_DRECTVE) $@
+
+%.d: %.c
+	@echo "$(MSG_PREFIX)\`\` Dependency:" $(LOCAL_PATH)/$<
+	@./depends.sh $(CC) `dirname $*.c` $(CFLAGS) $*.c > $@
+
+%.d: %.cc
+	@echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$<
+	@./depends.sh $(CXX) `dirname $*.cc` $(CXXFLAGS) $*.cc > $@
+
+#-include $(DEP)
+
+# Actual targets
+
+#depend: $(DEP)
+
+clean: 
+	@echo "$(MSG_PREFIX)\`\` Cleaning up..."
+	@rm -rvf $(PROG) lib$(PROG).a $(OBJ) $(GARBAGE) $(OBJ:.o=.d) 
+
+tags:
+	etags `find . -type f -regex '.*\.\(c\|h\)'`
+
+$(PROG): $(OBJ)
+	@echo "$(MSG_PREFIX)\`\` Building binary:" $(notdir $@)
+	@$(LD) -o $@ $^ $(LIBS)
+
+lib$(PROG).a: $(OBJ)
+	@echo "$(MSG_PREFIX)\`\` Linking:" $(notdir $@)
+	@ar rv $@ $?
+	@ranlib $@
+
+lib$(PROG).dll: $(OBJ)
+	$(CC) $(CFLAGS) -shared -lm -o $@ $?
+
+docs:
+	@echo "$(MSG_PREFIX)\`\` Building documentation." $(notdir $@)
+	@doxygen doxygen.conf
diff --git a/abc-build/abc.rc b/abc-build/abc.rc
new file mode 100644
--- /dev/null
+++ b/abc-build/abc.rc
@@ -0,0 +1,146 @@
+# global parameters
+set check         # checks intermediate networks
+#set checkfio      # prints warnings when fanins/fanouts are duplicated
+#unset checkread   # does not check new networks after reading from file
+#set backup        # saves backup networks retrived by "undo" and "recall"
+#set savesteps 1   # sets the maximum number of backup networks to save 
+#set progressbar   # display the progress bar
+
+# program names for internal calls
+set dotwin dot.exe
+set dotunix dot
+set gsviewwin gsview32.exe
+set gsviewunix gv
+set siswin sis.exe
+set sisunix sis
+set mvsiswin mvsis.exe
+set mvsisunix mvsis
+set capowin MetaPl-Capo10.1-Win32.exe
+set capounix MetaPl-Capo10.1
+set gnuplotwin wgnuplot.exe
+set gnuplotunix gnuplot
+
+# Niklas Een's commands
+load_plugin C:\_projects\abc\lib\bip_win.exe "BIP"
+
+# standard aliases
+alias hi history
+alias b balance
+alias cg clockgate
+alias cl cleanup
+alias clp collapse
+alias cs care_set
+alias el eliminate
+alias esd ext_seq_dcs
+alias f fraig
+alias fs fraig_sweep
+alias fsto fraig_store
+alias fres fraig_restore
+alias fr fretime
+alias ft fraig_trust
+alias ic indcut
+alias lp lutpack
+alias pcon print_cone
+alias pd print_dsd
+alias pex print_exdc -d
+alias pf print_factor
+alias pfan print_fanio
+alias pg print_gates
+alias pl print_level
+alias plat print_latch
+alias pio print_io
+alias pk print_kmap
+alias pm print_miter
+alias ps print_stats 
+alias psb print_stats -b
+alias psu print_supp
+alias psy print_symm
+alias pun print_unate
+alias q quit
+alias r read
+alias ra read_aiger
+alias r3 retime -M 3
+alias r3f retime -M 3 -f
+alias r3b retime -M 3 -b
+alias ren renode
+alias rh read_hie
+alias ri read_init
+alias rl read_blif
+alias rb read_bench
+alias ret retime
+alias dret dretime
+alias rp read_pla
+alias rt read_truth
+alias rv read_verilog
+alias rvl read_verlib
+alias rsup read_super mcnc5_old.super
+alias rlib read_library
+alias rlibc read_library cadence.genlib
+alias rty read_liberty
+alias rlut read_lut
+alias rw rewrite
+alias rwz rewrite -z
+alias rf refactor
+alias rfz refactor -z
+alias re restructure
+alias rez restructure -z
+alias rs resub
+alias rsz resub -z
+alias sa set autoexec ps
+alias scl scleanup
+alias sif if -s
+alias so source -x
+alias st strash
+alias sw sweep
+alias ssw ssweep
+alias tr0 trace_start
+alias tr1 trace_check
+alias trt "r c.blif; st; tr0; b; tr1"
+alias u undo
+alias w write
+alias wa write_aiger
+alias wb write_bench
+alias wc write_cnf
+alias wh write_hie
+alias wl write_blif
+alias wp write_pla
+alias wv write_verilog
+
+# standard scripts
+alias resyn       "b; rw; rwz; b; rwz; b"
+alias resyn2      "b; rw; rf; b; rw; rwz; b; rfz; rwz; b"
+alias resyn2a     "b; rw; b; rw; rwz; b; rwz; b"
+alias resyn3      "b; rs; rs -K 6; b; rsz; rsz -K 6; b; rsz -K 5; b"
+alias compress    "b -l; rw -l; rwz -l; b -l; rwz -l; b -l"
+alias compress2   "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l"
+alias choice      "fraig_store; resyn; fraig_store; resyn2; fraig_store; fraig_restore"
+alias choice2     "fraig_store; balance; fraig_store; resyn; fraig_store; resyn2; fraig_store; resyn2; fraig_store; fraig_restore"
+alias rwsat       "st; rw -l; b -l; rw -l; rf -l"
+alias drwsat2     "st; drw; b -l; drw; drf; ifraig -C 20; drw; b -l; drw; drf"
+alias share       "st; multi -m; fx; resyn2"
+alias addinit     "read_init; undc; strash; zero"
+alias blif2aig    "undc; strash; zero"
+alias v2p         "&vta_gla; &ps; &gla_derive; &put; w 1.aig; pdr -v"
+alias g2p         "&ps; &gla_derive; &put; w 2.aig; pdr -v"
+alias &sw_        "&put; sweep; st; &get"
+alias &fx_        "&put; sweep; sop; fx; st; &get"
+alias &dc3        "&b; &jf -K 6; &b; &jf -K 4; &b"
+alias &dc4        "&b; &jf -K 7; &fx; &b; &jf -K 5; &fx; &b"
+
+# resubstitution scripts for the IWLS paper
+alias src_rw      "st; rw -l; rwz -l; rwz -l" 
+alias src_rs      "st; rs -K 6 -N 2 -l; rs -K 9 -N 2 -l; rs -K 12 -N 2 -l" 
+alias src_rws     "st; rw -l; rs -K 6 -N 2 -l; rwz -l; rs -K 9 -N 2 -l; rwz -l; rs -K 12 -N 2 -l" 
+alias resyn2rs    "b; rs -K 6; rw; rs -K 6 -N 2; rf; rs -K 8; b; rs -K 8 -N 2; rw; rs -K 10; rwz; rs -K 10 -N 2; b; rs -K 12; rfz; rs -K 12 -N 2; rwz; b"
+alias compress2rs "b -l; rs -K 6 -l; rw -l; rs -K 6 -N 2 -l; rf -l; rs -K 8 -l; b -l; rs -K 8 -N 2 -l; rw -l; rs -K 10 -l; rwz -l; rs -K 10 -N 2 -l; b -l; rs -K 12 -l; rfz -l; rs -K 12 -N 2 -l; rwz -l; b -l"
+
+# use this script to convert 1-valued and DC-valued flops for an AIG
+alias fix_aig     "logic; undc; strash; zero"
+
+# use this script to convert 1-valued and DC-valued flops for a logic network coming from BLIF
+alias fix_blif    "undc; strash; zero"
+
+# lazy man's synthesis
+alias recadd3     "st; rec_add3; b; rec_add3; dc2; rec_add3; if -K 8; bidec; st; rec_add3; dc2; rec_add3; if -g -K 6; st; rec_add3"
+
+
diff --git a/abc-build/abcexe.dsp b/abc-build/abcexe.dsp
new file mode 100644
--- /dev/null
+++ b/abc-build/abcexe.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="abcexe" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=abcexe - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "abcexe.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "abcexe.mak" CFG="abcexe - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "abcexe - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "abcexe - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "abcexe - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ReleaseExe"
+# PROP BASE Intermediate_Dir "ReleaseExe"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseExe"
+# PROP Intermediate_Dir "ReleaseExe"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "src" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /FR /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib lib\abcr.lib lib\x86\pthreadVC2.lib /nologo /subsystem:console /incremental:yes /debug /machine:I386 /out:"_TEST/abc.exe"
+# SUBTRACT LINK32 /profile
+
+!ELSEIF  "$(CFG)" == "abcexe - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "DebugExe"
+# PROP BASE Intermediate_Dir "DebugExe"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "DebugExe"
+# PROP Intermediate_Dir "DebugExe"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib lib\abcd.lib lib\x86\pthreadVC2.lib /nologo /subsystem:console /debug /machine:I386 /out:"_TEST/abc.exe"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "abcexe - Win32 Release"
+# Name "abcexe - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\src\base\main\main.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/abc-build/abclib.dsp b/abc-build/abclib.dsp
new file mode 100644
--- /dev/null
+++ b/abc-build/abclib.dsp
@@ -0,0 +1,4920 @@
+# Microsoft Developer Studio Project File - Name="abclib" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=abclib - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "abclib.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "abclib.mak" CFG="abclib - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "abclib - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "abclib - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "abclib - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ReleaseLib"
+# PROP BASE Intermediate_Dir "ReleaseLib"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseLib"
+# PROP Intermediate_Dir "ReleaseLib"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "src" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /FR /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"lib\abcr.lib"
+
+!ELSEIF  "$(CFG)" == "abclib - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "DebugLib"
+# PROP BASE Intermediate_Dir "DebugLib"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "DebugLib"
+# PROP Intermediate_Dir "DebugLib"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"lib\abcd.lib"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "abclib - Win32 Release"
+# Name "abclib - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Group "base"
+
+# PROP Default_Filter ""
+# Begin Group "abc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\base\abc\abc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcAig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcBarBuf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcBlifMv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcCheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcDfs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcFanio.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcFanOrder.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcFunc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcHie.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcHieCec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcHieNew.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcLatch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcLib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcMinBase.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcNames.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcNetlist.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcNtk.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcObj.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcRefs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcShow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcSop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcUtil.c
+# End Source File
+# End Group
+# Begin Group "abci"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\base\abci\abc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcAttach.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcAuto.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcBalance.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcBidec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcBm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcBmc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcCas.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcCascade.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcCollapse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcDar.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcDebug.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcDec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcDress.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcDress2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcDsd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcExtract.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcFraig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcFx.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcFxu.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcGen.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcHaig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcIf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcIfif.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcIfMux.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcIvy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcLog.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcLut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcLutmin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcMap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcMeasure.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcMerge.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcMffc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcMfs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcMini.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcMiter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcMulti.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcMv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcNpn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcNpnSave.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcNtbdd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcOdc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcOrder.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcPart.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcPrint.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcProve.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcQbf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcQuant.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcReach.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcRec3.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcReconv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcRefactor.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcRenode.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcReorder.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcRestruct.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcResub.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcRewrite.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcRpo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcRr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcSaucy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcScorr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcSense.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcSpeedup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcStrash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcSweep.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcSymm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcTim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcTiming.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcUnate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcUnreach.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcVerify.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcXsim.c
+# End Source File
+# End Group
+# Begin Group "cmd"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmdAlias.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmdApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmdFlag.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmdHist.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmdInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmdLoad.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmdPlugin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmdStarter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmdUtils.c
+# End Source File
+# End Group
+# Begin Group "io"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\base\io\io.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioabc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadAiger.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadBaf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadBblif.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadBench.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadBlif.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadBlifAig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadBlifMv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadDsd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadEdif.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadEqn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadPla.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadVerilog.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteAiger.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteBaf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteBblif.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteBench.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteBlif.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteBlifMv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteBook.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteCnf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteDot.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteEqn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteGml.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteList.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWritePla.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteSmv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteVerilog.c
+# End Source File
+# End Group
+# Begin Group "main"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\base\main\libSupport.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\main\main.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\main\mainFrame.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\main\mainInit.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\main\mainInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\main\mainLib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\main\mainUtils.c
+# End Source File
+# End Group
+# Begin Group "ver"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\base\ver\ver.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\ver\verCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\ver\verFormula.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\ver\verParse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\ver\verStream.c
+# End Source File
+# End Group
+# Begin Group "test"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\base\test\test.c
+# End Source File
+# End Group
+# Begin Group "abc2"
+
+# PROP Default_Filter ""
+# End Group
+# Begin Group "abc2d"
+
+# PROP Default_Filter ""
+# End Group
+# End Group
+# Begin Group "bdd"
+
+# PROP Default_Filter ""
+# Begin Group "cudd"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cudd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAddAbs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAddApply.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAddFind.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAddInv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAddIte.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAddNeg.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAddWalsh.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAndAbs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAnneal.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddApa.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAPI.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddApprox.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddBddAbs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddBddCorr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddBddIte.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddBridge.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddCache.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddCheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddClip.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddCof.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddCompose.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddDecomp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddEssent.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddExact.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddExport.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddGenCof.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddGenetic.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddGroup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddHarwell.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddInit.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddInteract.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddLCache.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddLevelQ.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddLinear.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddLiteral.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddMatMult.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddPriority.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddRead.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddRef.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddReorder.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddSign.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddSolve.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddSplit.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddSubsetHB.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddSubsetSP.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddSymmetry.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddTable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddWindow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddCount.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddFuncs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddGroup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddIsop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddLin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddMisc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddPort.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddReord.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddSetop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddSymm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddUtil.c
+# End Source File
+# End Group
+# Begin Group "epd"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bdd\epd\epd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\epd\epd.h
+# End Source File
+# End Group
+# Begin Group "mtr"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bdd\mtr\mtr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\mtr\mtrBasic.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\mtr\mtrGroup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\mtr\mtrInt.h
+# End Source File
+# End Group
+# Begin Group "parse"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bdd\parse\parse.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\parse\parseCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\parse\parseEqn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\parse\parseInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\parse\parseStack.c
+# End Source File
+# End Group
+# Begin Group "dsd"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bdd\dsd\dsd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\dsd\dsdApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\dsd\dsdCheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\dsd\dsdInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\dsd\dsdLocal.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\dsd\dsdMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\dsd\dsdProc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\dsd\dsdTree.c
+# End Source File
+# End Group
+# Begin Group "reo"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reo.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reoApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reoCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reoProfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reoShuffle.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reoSift.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reoSwap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reoTest.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reoTransfer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reoUnits.c
+# End Source File
+# End Group
+# Begin Group "cas"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bdd\cas\cas.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cas\casCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cas\casDec.c
+# End Source File
+# End Group
+# End Group
+# Begin Group "sat"
+
+# PROP Default_Filter ""
+# Begin Group "msat"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msat.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatActivity.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatClause.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatClauseVec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatMem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatOrderH.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatQueue.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatRead.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatSolverApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatSolverCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatSolverIo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatSolverSearch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatSort.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatVec.c
+# End Source File
+# End Group
+# Begin Group "csat"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\sat\csat\csat_apis.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\csat\csat_apis.h
+# End Source File
+# End Group
+# Begin Group "bsat"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satClause.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satInter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satInterA.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satInterB.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satInterP.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satMem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satMem.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satProof.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satProof2.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satSolver.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satSolver.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satSolver2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satSolver2.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satSolver2i.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satStore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satStore.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satTrace.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satTruth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satTruth.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satVec.h
+# End Source File
+# End Group
+# Begin Group "proof"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\sat\proof\pr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\proof\pr.h
+# End Source File
+# End Group
+# Begin Group "psat"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\sat\psat\m114p.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\psat\m114p_types.h
+# End Source File
+# End Group
+# Begin Group "lsat"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\sat\lsat\solver.h
+# End Source File
+# End Group
+# Begin Group "cnf"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\sat\cnf\cnf.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\cnf\cnfCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\cnf\cnfCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\cnf\cnfData.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\cnf\cnfFast.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\cnf\cnfMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\cnf\cnfMap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\cnf\cnfPost.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\cnf\cnfUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\cnf\cnfWrite.c
+# End Source File
+# End Group
+# Begin Group "bmc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcBCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcBmc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcBmc2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcBmc3.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcBmcAnd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcBmci.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcCexCare.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcCexCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcCexDepth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcCexMin1.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcCexMin2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcCexTools.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcEco.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcFault.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcICheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcInse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcLoad.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcMaxi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcMulti.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bmc\bmcUnroll.c
+# End Source File
+# End Group
+# End Group
+# Begin Group "opt"
+
+# PROP Default_Filter ""
+# Begin Group "fxu"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxu.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxu.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuCreate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuHeapD.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuHeapS.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuList.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuMatrix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuPair.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuPrint.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuReduce.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuSelect.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuSingle.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuUpdate.c
+# End Source File
+# End Group
+# Begin Group "rwr"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwrDec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwrEva.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwrExp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwrLib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwrMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwrPrint.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwrTemp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwrUtil.c
+# End Source File
+# End Group
+# Begin Group "cut"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cut.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutExpand.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutList.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutMerge.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutNode.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutOracle.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutPre22.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutSeq.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutTruth.c
+# End Source File
+# End Group
+# Begin Group "sim"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\sim\sim.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simSeq.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simSupp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simSwitch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simSym.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simSymSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simSymSim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simSymStr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simUtils.c
+# End Source File
+# End Group
+# Begin Group "ret"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retArea.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retDelay.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retFlow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retIncrem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retInit.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retLvalue.c
+# End Source File
+# End Group
+# Begin Group "res"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\res\res.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resDivs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resFilter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resSim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resStrash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resWin.c
+# End Source File
+# End Group
+# Begin Group "lpk"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpk.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkAbcDec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkAbcDsd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkAbcMux.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkAbcUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkMap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkMulti.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkMux.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkSets.c
+# End Source File
+# End Group
+# Begin Group "mfs"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\mfs\mfs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\mfs\mfsCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\mfs\mfsDiv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\mfs\mfsInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\mfs\mfsInter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\mfs\mfsMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\mfs\mfsResub.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\mfs\mfsSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\mfs\mfsStrash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\mfs\mfsWin.c
+# End Source File
+# End Group
+# Begin Group "cgt"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\cgt\cgt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cgt\cgtAig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cgt\cgtCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cgt\cgtDecide.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cgt\cgtInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cgt\cgtMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cgt\cgtSat.c
+# End Source File
+# End Group
+# Begin Group "csw"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\csw\csw.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\csw\cswCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\csw\cswCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\csw\cswInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\csw\cswMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\csw\cswTable.c
+# End Source File
+# End Group
+# Begin Group "dar"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\dar\dar.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dar\darBalance.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dar\darCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dar\darCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dar\darData.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dar\darInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dar\darLib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dar\darMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dar\darPrec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dar\darRefact.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dar\darResub.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dar\darScript.c
+# End Source File
+# End Group
+# Begin Group "rwt"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\rwt\rwt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwt\rwtDec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwt\rwtMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwt\rwtUtil.c
+# End Source File
+# End Group
+# Begin Group "nwk"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\nwk\ntlnwk.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\nwk\nwk.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\nwk\nwkAig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\nwk\nwkBidec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\nwk\nwkCheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\nwk\nwkDfs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\nwk\nwkFanio.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\nwk\nwkFlow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\nwk\nwkMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\nwk\nwkMap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\nwk\nwkMerge.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\nwk\nwkMerge.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\nwk\nwkObj.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\nwk\nwkSpeedup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\nwk\nwkStrash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\nwk\nwkTiming.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\nwk\nwkUtil.c
+# End Source File
+# End Group
+# Begin Group "dau"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\dau\dau.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dau\dau.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dau\dauCanon.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dau\dauCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dau\dauDivs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dau\dauDsd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dau\dauEnum.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dau\dauGia.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dau\dauInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dau\dauMerge.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dau\dauNonDsd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dau\dauTree.c
+# End Source File
+# End Group
+# Begin Group "sfm"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\sfm\sfm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sfm\sfmCnf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sfm\sfmCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sfm\sfmInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sfm\sfmNtk.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sfm\sfmSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sfm\sfmWin.c
+# End Source File
+# End Group
+# End Group
+# Begin Group "map"
+
+# PROP Default_Filter ""
+# Begin Group "mapper"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapper.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapper.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperCanon.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperCreate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperCutUtils.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperFanout.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperLib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperMatch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperRefs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperSuper.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperSwitch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperTable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperTime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperTree.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperTruth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperUtils.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperVec.c
+# End Source File
+# End Group
+# Begin Group "mio"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\map\mio\exp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mio\mio.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mio\mio.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mio\mioApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mio\mioFunc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mio\mioInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mio\mioParse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mio\mioRead.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mio\mioSop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mio\mioUtils.c
+# End Source File
+# End Group
+# Begin Group "super"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\map\super\super.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\super\super.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\super\superAnd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\super\superGate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\super\superInt.h
+# End Source File
+# End Group
+# Begin Group "if"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\map\if\if.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifCache.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifCom.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifCount.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifDec07.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifDec08.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifDec10.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifDec16.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifDec75.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifDelay.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifDsd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifLibBox.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifLibLut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifMap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifReduce.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifSelect.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifSeq.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifTest.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifTime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifTruth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifTune.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifUtil.c
+# End Source File
+# End Group
+# Begin Group "amap"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\map\amap\amap.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\amap\amapCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\amap\amapGraph.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\amap\amapInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\amap\amapLib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\amap\amapLiberty.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\amap\amapMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\amap\amapMatch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\amap\amapMerge.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\amap\amapOutput.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\amap\amapParse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\amap\amapPerm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\amap\amapRead.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\amap\amapRule.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\amap\amapUniq.c
+# End Source File
+# End Group
+# Begin Group "cov"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\map\cov\cov.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\cov\covBuild.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\cov\covCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\cov\covInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\cov\covMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\cov\covMinEsop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\cov\covMinMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\cov\covMinSop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\cov\covMinUtil.c
+# End Source File
+# End Group
+# Begin Group "scl"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\map\scl\scl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\scl\scl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\scl\sclBuffer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\scl\sclBufSize.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\scl\sclDnsize.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\scl\sclLib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\scl\sclLiberty.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\scl\sclLibScl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\scl\sclLibUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\scl\sclLoad.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\scl\sclSize.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\scl\sclSize.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\scl\sclTime.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\scl\sclUpsize.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\scl\sclUtil.c
+# End Source File
+# End Group
+# Begin Group "mpm"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\map\mpm\mpm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mpm\mpm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mpm\mpmAbc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mpm\mpmCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mpm\mpmDsd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mpm\mpmGates.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mpm\mpmInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mpm\mpmLib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mpm\mpmMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mpm\mpmMap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mpm\mpmMig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mpm\mpmMig.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mpm\mpmPre.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mpm\mpmTruth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mpm\mpmUtil.c
+# End Source File
+# End Group
+# End Group
+# Begin Group "misc"
+
+# PROP Default_Filter ""
+# Begin Group "extra"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extra.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraBdd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraBddAuto.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraBddCas.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraBddImage.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraBddKmap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraBddMisc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraBddSymm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraBddTime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraBddUnate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilBitMatrix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilCanon.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilCube.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilDsd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilEnum.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilFile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilMemory.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilMisc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilPerm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilProgress.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilReader.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilSupp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilTruth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilUtil.c
+# End Source File
+# End Group
+# Begin Group "st"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\st\st.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\st\st.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\st\stmm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\st\stmm.h
+# End Source File
+# End Group
+# Begin Group "mvc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcCompare.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcContain.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcCover.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcCube.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcDivide.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcDivisor.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcList.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcLits.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcOpAlg.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcOpBool.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcPrint.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcSort.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcUtils.c
+# End Source File
+# End Group
+# Begin Group "vec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vec.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecAtt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecBit.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecFlt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecHash.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecHsh.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecMem.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecPtr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecQue.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecSet.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecStr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecVec.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecWec.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecWrd.h
+# End Source File
+# End Group
+# Begin Group "util"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\util\abc_global.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\util\util_hack.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\util\utilBridge.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\util\utilCex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\util\utilCex.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\util\utilColor.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\util\utilFile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\util\utilMem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\util\utilMem.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\util\utilNam.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\util\utilNam.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\util\utilSignal.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\util\utilSignal.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\util\utilSort.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\util\utilTruth.h
+# End Source File
+# End Group
+# Begin Group "nm"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\nm\nm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\nm\nmApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\nm\nmInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\nm\nmTable.c
+# End Source File
+# End Group
+# Begin Group "hash"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\hash\hash.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\hash\hashFlt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\hash\hashInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\hash\hashPtr.h
+# End Source File
+# End Group
+# Begin Group "bzlib"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\bzlib\blocksort.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\bzlib\bzlib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\bzlib\bzlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\bzlib\bzlib_private.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\bzlib\compress.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\bzlib\crctable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\bzlib\decompress.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\bzlib\huffman.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\bzlib\randtable.c
+# End Source File
+# End Group
+# Begin Group "zlib"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\adler32.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\compress_.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\crc32.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\crc32.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\deflate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\deflate.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\gzclose.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\gzguts.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\gzlib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\gzread.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\gzwrite.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\infback.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\inffast.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\inffast.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\inffixed.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\inflate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\inflate.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\inftrees.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\inftrees.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\trees.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\trees.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\uncompr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\zconf.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\zlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\zutil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\zlib\zutil.h
+# End Source File
+# End Group
+# Begin Group "bar"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\bar\bar.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\bar\bar.h
+# End Source File
+# End Group
+# Begin Group "bbl"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\bbl\bblif.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\bbl\bblif.h
+# End Source File
+# End Group
+# Begin Group "mem"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\mem\mem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mem\mem.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mem\mem2.h
+# End Source File
+# End Group
+# Begin Group "tim"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\tim\tim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\tim\tim.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\tim\timBox.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\tim\timDump.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\tim\timInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\tim\timMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\tim\timTime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\tim\timTrav.c
+# End Source File
+# End Group
+# End Group
+# Begin Group "ai"
+
+# PROP Default_Filter ""
+# Begin Group "hop"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hop.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopBalance.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopCheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopDfs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopMem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopObj.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopOper.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopTable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopTruth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopUtil.c
+# End Source File
+# End Group
+# Begin Group "ivy"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivy.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyBalance.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyCanon.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyCheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyCutTrav.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyDfs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyDsd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyFanout.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyFastMap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyFraig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyHaig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyMem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyMulti.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyObj.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyOper.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyResyn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyRwr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivySeq.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyShow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyTable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyUtil.c
+# End Source File
+# End Group
+# Begin Group "ioa"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\ioa\ioa.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ioa\ioaReadAig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ioa\ioaUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ioa\ioaWriteAig.c
+# End Source File
+# End Group
+# Begin Group "aig"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aig.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigCanon.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigCheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigCuts.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigDfs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigDoms.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigDup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigFact.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigFanout.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigFrames.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigInter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigJust.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigMem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigMffc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigObj.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigOper.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigOrder.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigPack.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigPart.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigPartReg.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigPartSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigRepr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigRet.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigRetF.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigScl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigShow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigSplit.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigTable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigTiming.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigTruth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigTsim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigWin.c
+# End Source File
+# End Group
+# Begin Group "saig"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saig.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigCone.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigConstr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigConstr2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigDual.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigDup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigInd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigIoa.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigIso.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigIsoFast.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigIsoSlow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigMiter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigOutDec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigPhase.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigRetFwd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigRetMin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigRetStep.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigScl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigSimFast.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigSimMv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigSimSeq.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigStrSim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigSwitch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigSynch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigTempor.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigTrans.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\saig\saigWnd.c
+# End Source File
+# End Group
+# Begin Group "gia"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\gia\gia.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\gia.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaAig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaAig.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaAiger.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaAigerExt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaBalance.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaBalance2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaBidec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaCCof.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaCex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaCof.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaCone.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaCSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaCSatOld.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaCTas.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaDfs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaDup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaEmbed.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaEnable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaEquiv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaEra.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaEra2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaFalse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaFanout.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaForce.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaFrames.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaFront.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaFx.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaGig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaGlitch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaHash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaIf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaIff.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaIso.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaIso2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaIso3.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaJf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaKf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaLf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaMem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaMf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaMfs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaMini.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaMuxes.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaNf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaPat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaResub.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaRetime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaScl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaShrink.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaShrink6.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaShrink7.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaSim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaSim2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaSopb.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaSort.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaSpeedup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaStg.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaStr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaSupMin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaSweep.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaSweeper.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaSwitch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaTim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaTis.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaTruth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaTsim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\gia\giaUtil.c
+# End Source File
+# End Group
+# Begin Group "miniaig"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\miniaig\miniaig.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "bool"
+
+# PROP Default_Filter ""
+# Begin Group "bdc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bool\bdc\bdc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\bdc\bdcCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\bdc\bdcDec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\bdc\bdcInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\bdc\bdcSpfd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\bdc\bdcTable.c
+# End Source File
+# End Group
+# Begin Group "dec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bool\dec\dec.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\dec\decAbc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\dec\decFactor.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\dec\decMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\dec\decPrint.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\dec\decUtil.c
+# End Source File
+# End Group
+# Begin Group "deco"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bool\deco\deco.h
+# End Source File
+# End Group
+# Begin Group "kit"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bool\kit\cloud.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\kit\cloud.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\kit\kit.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\kit\kit_.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\kit\kitAig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\kit\kitBdd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\kit\kitCloud.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\kit\kitDec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\kit\kitDsd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\kit\kitFactor.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\kit\kitGraph.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\kit\kitHop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\kit\kitIsop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\kit\kitPerm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\kit\kitPla.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\kit\kitSop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\kit\kitTruth.c
+# End Source File
+# End Group
+# Begin Group "lucky"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bool\lucky\lucky.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\lucky\lucky.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\lucky\luckyFast16.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\lucky\luckyFast6.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\lucky\luckyInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\lucky\luckyRead.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\lucky\luckySimple.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\lucky\luckySwap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\lucky\luckySwapIJ.c
+# End Source File
+# End Group
+# Begin Group "rsb"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bool\rsb\rsb.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\rsb\rsbDec6.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\rsb\rsbInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\rsb\rsbMan.c
+# End Source File
+# End Group
+# Begin Group "rpo"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bool\rpo\literal.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\rpo\rpo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bool\rpo\rpo.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "prove"
+
+# PROP Default_Filter ""
+# Begin Group "bbr"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\proof\bbr\bbr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\bbr\bbrCex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\bbr\bbrImage.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\bbr\bbrNtbdd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\bbr\bbrReach.c
+# End Source File
+# End Group
+# Begin Group "cec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\proof\cec\cec.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\cec\cecCec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\cec\cecChoice.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\cec\cecClass.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\cec\cecCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\cec\cecCorr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\cec\cecInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\cec\cecIso.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\cec\cecMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\cec\cecPat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\cec\cecSeq.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\cec\cecSolve.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\cec\cecSplit.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\cec\cecSweep.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\cec\cecSynth.c
+# End Source File
+# End Group
+# Begin Group "dch"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\proof\dch\dch.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\dch\dchAig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\dch\dchChoice.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\dch\dchClass.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\dch\dchCnf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\dch\dchCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\dch\dchInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\dch\dchMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\dch\dchSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\dch\dchSim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\dch\dchSimSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\dch\dchSweep.c
+# End Source File
+# End Group
+# Begin Group "fra"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fra.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fraBmc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fraCec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fraClass.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fraClau.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fraClaus.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fraCnf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fraCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fraHot.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fraImp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fraInd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fraIndVer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fraLcr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fraMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fraPart.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fraSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fraSec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fra\fraSim.c
+# End Source File
+# End Group
+# Begin Group "fraig"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\proof\fraig\fraig.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fraig\fraigApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fraig\fraigCanon.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fraig\fraigChoice.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fraig\fraigFanout.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fraig\fraigFeed.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fraig\fraigInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fraig\fraigMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fraig\fraigMem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fraig\fraigNode.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fraig\fraigPrime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fraig\fraigSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fraig\fraigTable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fraig\fraigUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\fraig\fraigVec.c
+# End Source File
+# End Group
+# Begin Group "int"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\proof\int\int.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\int\intCheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\int\intContain.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\int\intCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\int\intCtrex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\int\intDup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\int\intFrames.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\int\intInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\int\intInter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\int\intM114.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\int\intMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\int\intUtil.c
+# End Source File
+# End Group
+# Begin Group "live"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\proof\live\arenaViolation.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\live\combination.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\live\disjunctiveMonotone.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\live\kLiveConstraints.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\live\kliveness.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\live\liveness.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\live\liveness_sim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\live\ltl_parser.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\live\monotone.c
+# End Source File
+# End Group
+# Begin Group "llb"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb1Cluster.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb1Constr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb1Core.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb1Group.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb1Hint.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb1Man.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb1Matrix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb1Pivot.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb1Reach.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb1Sched.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb2Bad.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb2Core.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb2Driver.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb2Dump.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb2Flow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb2Image.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb3Image.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb3Nonlin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb4Cex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb4Cluster.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb4Image.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb4Map.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb4Nonlin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llb4Sweep.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\llb\llbInt.h
+# End Source File
+# End Group
+# Begin Group "pdr"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\proof\pdr\pdr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\pdr\pdrClass.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\pdr\pdrCnf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\pdr\pdrCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\pdr\pdrInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\pdr\pdrInv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\pdr\pdrMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\pdr\pdrSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\pdr\pdrTsim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\pdr\pdrUtil.c
+# End Source File
+# End Group
+# Begin Group "ssw"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\ssw.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswAig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswBmc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswClass.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswCnf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswConstr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswDyn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswFilter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswIslands.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswLcorr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswPairs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswPart.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswRarity.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswRarity2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswSemi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswSim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswSimSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswSweep.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssw\sswUnique.c
+# End Source File
+# End Group
+# Begin Group "abs"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\proof\abs\abs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\abs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\absDup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\absGla.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\absGlaOld.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\absIter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\absOldCex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\absOldRef.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\absOldSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\absOldSim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\absOut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\absPth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\absRef.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\absRef.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\absRefSelect.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\absRpm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\absRpmOld.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\absUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\abs\absVta.c
+# End Source File
+# End Group
+# Begin Group "ssc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\proof\ssc\ssc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssc\sscClass.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssc\sscCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssc\sscInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssc\sscSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssc\sscSim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\proof\ssc\sscUtil.c
+# End Source File
+# End Group
+# Begin Group "int2"
+
+# PROP Default_Filter ""
+# End Group
+# End Group
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# End Target
+# End Project
diff --git a/abc-build/abcspace.dsw b/abc-build/abcspace.dsw
new file mode 100644
--- /dev/null
+++ b/abc-build/abcspace.dsw
@@ -0,0 +1,44 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "abcexe"=.\abcexe.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name abclib
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "abclib"=.\abclib.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/abc-build/arch_flags.c b/abc-build/arch_flags.c
new file mode 100644
--- /dev/null
+++ b/abc-build/arch_flags.c
@@ -0,0 +1,17 @@
+#include <stdio.h>
+
+int main()
+{
+    if (sizeof(void*) == 8)     // Assume 64-bit Linux if pointers are 8 bytes.
+        printf("-DLIN64 ");
+    else
+        printf("-DLIN ");
+
+    printf("-DSIZEOF_VOID_P=%d -DSIZEOF_LONG=%d -DSIZEOF_INT=%d\n",
+           (int)sizeof(void*),
+           (int)sizeof(long),
+           (int)sizeof(int) );
+
+
+    return 0;
+}
diff --git a/abc-build/copyright.txt b/abc-build/copyright.txt
new file mode 100644
--- /dev/null
+++ b/abc-build/copyright.txt
@@ -0,0 +1,23 @@
+ABC: System for Sequential Synthesis and Verification
+
+http://www.eecs.berkeley.edu/~alanmi/abc/
+
+
+Copyright (c) The Regents of the University 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.
+
diff --git a/abc-build/depends.sh b/abc-build/depends.sh
new file mode 100644
--- /dev/null
+++ b/abc-build/depends.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+#echo "## Got: $*"
+CC="$1"
+DIR="$2"
+shift 2
+case "$DIR" in
+	"" | ".")
+	$CC -MM -MG "$@" | sed -e 's@^\(.*\)\.o:@\1.d \1.o:@'
+	;;
+	*)
+	$CC -MM -MG "$@" | sed -e "s@^\(.*\)\.o:@$DIR/\1.d $DIR/\1.o:@"
+	;;
+esac
diff --git a/abc-build/i10.aig b/abc-build/i10.aig
new file mode 100644
Binary files /dev/null and b/abc-build/i10.aig differ
diff --git a/abc-build/lib/pthread.h b/abc-build/lib/pthread.h
new file mode 100644
--- /dev/null
+++ b/abc-build/lib/pthread.h
@@ -0,0 +1,1369 @@
+/* This is an implementation of the threads API of POSIX 1003.1-2001.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 Pthreads-win32 contributors
+ * 
+ *      Contact Email: rpj@callisto.canberra.edu.au
+ * 
+ *      The current list of contributors is contained
+ *      in the file CONTRIBUTORS included with the source
+ *      code distribution. The list can also be seen at the
+ *      following World Wide Web location:
+ *      http://sources.redhat.com/pthreads-win32/contributors.html
+ * 
+ *      This library is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU Lesser General Public
+ *      License as published by the Free Software Foundation; either
+ *      version 2 of the License, or (at your option) any later version.
+ * 
+ *      This library 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
+ *      Lesser General Public License for more details.
+ * 
+ *      You should have received a copy of the GNU Lesser General Public
+ *      License along with this library in the file COPYING.LIB;
+ *      if not, write to the Free Software Foundation, Inc.,
+ *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#if !defined( PTHREAD_H )
+#define PTHREAD_H
+
+/*
+ * See the README file for an explanation of the pthreads-win32 version
+ * numbering scheme and how the DLL is named etc.
+ */
+#define PTW32_VERSION 2,8,0,0
+#define PTW32_VERSION_STRING "2, 8, 0, 0\0"
+
+/* There are three implementations of cancel cleanup.
+ * Note that pthread.h is included in both application
+ * compilation units and also internally for the library.
+ * The code here and within the library aims to work
+ * for all reasonable combinations of environments.
+ *
+ * The three implementations are:
+ *
+ *   WIN32 SEH
+ *   C
+ *   C++
+ *
+ * Please note that exiting a push/pop block via
+ * "return", "exit", "break", or "continue" will
+ * lead to different behaviour amongst applications
+ * depending upon whether the library was built
+ * using SEH, C++, or C. For example, a library built
+ * with SEH will call the cleanup routine, while both
+ * C++ and C built versions will not.
+ */
+
+/*
+ * Define defaults for cleanup code.
+ * Note: Unless the build explicitly defines one of the following, then
+ * we default to standard C style cleanup. This style uses setjmp/longjmp
+ * in the cancelation and thread exit implementations and therefore won't
+ * do stack unwinding if linked to applications that have it (e.g.
+ * C++ apps). This is currently consistent with most/all commercial Unix
+ * POSIX threads implementations.
+ */
+#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C )
+# define __CLEANUP_C
+#endif
+
+#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC))
+#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler.
+#endif
+
+/*
+ * Stop here if we are being included by the resource compiler.
+ */
+#ifndef RC_INVOKED
+
+#undef PTW32_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_LEVEL_MAX 3
+
+#if !defined(PTW32_LEVEL)
+#define PTW32_LEVEL PTW32_LEVEL_MAX
+/* Include everything */
+#endif
+
+#ifdef _UWIN
+#   define HAVE_STRUCT_TIMESPEC 1
+#   define HAVE_SIGNAL_H        1
+#   undef HAVE_CONFIG_H
+#   pragma comment(lib, "pthread")
+#endif
+
+/*
+ * -------------------------------------------------------------
+ *
+ *
+ * Module: pthread.h
+ *
+ * Purpose:
+ *      Provides an implementation of PThreads based upon the
+ *      standard:
+ *
+ *              POSIX 1003.1-2001
+ *  and
+ *    The Single Unix Specification version 3
+ *
+ *    (these two are equivalent)
+ *
+ *      in order to enhance code portability between Windows,
+ *  various commercial Unix implementations, and Linux.
+ *
+ *      See the ANNOUNCE file for a full list of conforming
+ *      routines and defined constants, and a list of missing
+ *      routines and constants not defined in this implementation.
+ *
+ * Authors:
+ *      There have been many contributors to this library.
+ *      The initial implementation was contributed by
+ *      John Bossom, and several others have provided major
+ *      sections or revisions of parts of the implementation.
+ *      Often significant effort has been contributed to
+ *      find and fix important bugs and other problems to
+ *      improve the reliability of the library, which sometimes
+ *      is not reflected in the amount of code which changed as
+ *      result.
+ *      As much as possible, the contributors are acknowledged
+ *      in the ChangeLog file in the source code distribution
+ *      where their changes are noted in detail.
+ *
+ *      Contributors are listed in the CONTRIBUTORS file.
+ *
+ *      As usual, all bouquets go to the contributors, and all
+ *      brickbats go to the project maintainer.
+ *
+ * Maintainer:
+ *      The code base for this project is coordinated and
+ *      eventually pre-tested, packaged, and made available by
+ *
+ *              Ross Johnson <rpj@callisto.canberra.edu.au>
+ *
+ * QA Testers:
+ *      Ultimately, the library is tested in the real world by
+ *      a host of competent and demanding scientists and
+ *      engineers who report bugs and/or provide solutions
+ *      which are then fixed or incorporated into subsequent
+ *      versions of the library. Each time a bug is fixed, a
+ *      test case is written to prove the fix and ensure
+ *      that later changes to the code don't reintroduce the
+ *      same error. The number of test cases is slowly growing
+ *      and therefore so is the code reliability.
+ *
+ * Compliance:
+ *      See the file ANNOUNCE for the list of implemented
+ *      and not-implemented routines and defined options.
+ *      Of course, these are all defined is this file as well.
+ *
+ * Web site:
+ *      The source code and other information about this library
+ *      are available from
+ *
+ *              http://sources.redhat.com/pthreads-win32/
+ *
+ * -------------------------------------------------------------
+ */
+
+/* Try to avoid including windows.h */
+#if defined(__MINGW32__) && defined(__cplusplus)
+#define PTW32_INCLUDE_WINDOWS_H
+#endif
+
+#ifdef PTW32_INCLUDE_WINDOWS_H
+#include <windows.h>
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__)
+/*
+ * VC++6.0 or early compiler's header has no DWORD_PTR type.
+ */
+typedef unsigned long DWORD_PTR;
+#endif
+/*
+ * -----------------
+ * autoconf switches
+ * -----------------
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#ifndef NEED_FTIME
+#include <time.h>
+#else /* NEED_FTIME */
+/* use native WIN32 time API */
+#endif /* NEED_FTIME */
+
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#endif /* HAVE_SIGNAL_H */
+
+#include <setjmp.h>
+#include <limits.h>
+
+/*
+ * Boolean values to make us independent of system includes.
+ */
+enum {
+  PTW32_FALSE = 0,
+  PTW32_TRUE = (! PTW32_FALSE)
+};
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#ifndef PTW32_CONFIG_H
+#  if defined(WINCE)
+#    define NEED_ERRNO
+#    define NEED_SEM
+#  endif
+#  if defined(_UWIN) || defined(__MINGW32__)
+#    define HAVE_MODE_T
+#  endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+#ifdef NEED_ERRNO
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Several systems don't define some error numbers.
+ */
+#ifndef ENOTSUP
+#  define ENOTSUP 48   /* This is the value in Solaris. */
+#endif
+
+#ifndef ETIMEDOUT
+#  define ETIMEDOUT 10060     /* This is the value in winsock.h. */
+#endif
+
+#ifndef ENOSYS
+#  define ENOSYS 140     /* Semi-arbitrary value */
+#endif
+
+#ifndef EDEADLK
+#  ifdef EDEADLOCK
+#    define EDEADLK EDEADLOCK
+#  else
+#    define EDEADLK 36     /* This is the value in MSVC. */
+#  endif
+#endif
+
+//#include <sched.h>   -- changed by alanmi
+#include "sched.h"
+
+/*
+ * To avoid including windows.h we define only those things that we
+ * actually need from it.
+ */
+#ifndef PTW32_INCLUDE_WINDOWS_H
+#ifndef HANDLE
+# define PTW32__HANDLE_DEF
+# define HANDLE void *
+#endif
+#ifndef DWORD
+# define PTW32__DWORD_DEF
+# define DWORD unsigned long
+#endif
+#endif
+
+#ifndef HAVE_STRUCT_TIMESPEC
+#define HAVE_STRUCT_TIMESPEC 1
+struct timespec {
+        long tv_sec;
+        long tv_nsec;
+};
+#endif /* HAVE_STRUCT_TIMESPEC */
+
+#ifndef SIG_BLOCK
+#define SIG_BLOCK 0
+#endif /* SIG_BLOCK */
+
+#ifndef SIG_UNBLOCK 
+#define SIG_UNBLOCK 1
+#endif /* SIG_UNBLOCK */
+
+#ifndef SIG_SETMASK
+#define SIG_SETMASK 2
+#endif /* SIG_SETMASK */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif                          /* __cplusplus */
+
+/*
+ * -------------------------------------------------------------
+ *
+ * POSIX 1003.1-2001 Options
+ * =========================
+ *
+ * Options are normally set in <unistd.h>, which is not provided
+ * with pthreads-win32.
+ *
+ * For conformance with the Single Unix Specification (version 3), all of the
+ * options below are defined, and have a value of either -1 (not supported)
+ * or 200112L (supported).
+ *
+ * These options can neither be left undefined nor have a value of 0, because
+ * either indicates that sysconf(), which is not implemented, may be used at
+ * runtime to check the status of the option.
+ *
+ * _POSIX_THREADS (== 200112L)
+ *                      If == 200112L, you can use threads
+ *
+ * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L)
+ *                      If == 200112L, you can control the size of a thread's
+ *                      stack
+ *                              pthread_attr_getstacksize
+ *                              pthread_attr_setstacksize
+ *
+ * _POSIX_THREAD_ATTR_STACKADDR (== -1)
+ *                      If == 200112L, you can allocate and control a thread's
+ *                      stack. If not supported, the following functions
+ *                      will return ENOSYS, indicating they are not
+ *                      supported:
+ *                              pthread_attr_getstackaddr
+ *                              pthread_attr_setstackaddr
+ *
+ * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1)
+ *                      If == 200112L, you can use realtime scheduling.
+ *                      This option indicates that the behaviour of some
+ *                      implemented functions conforms to the additional TPS
+ *                      requirements in the standard. E.g. rwlocks favour
+ *                      writers over readers when threads have equal priority.
+ *
+ * _POSIX_THREAD_PRIO_INHERIT (== -1)
+ *                      If == 200112L, you can create priority inheritance
+ *                      mutexes.
+ *                              pthread_mutexattr_getprotocol +
+ *                              pthread_mutexattr_setprotocol +
+ *
+ * _POSIX_THREAD_PRIO_PROTECT (== -1)
+ *                      If == 200112L, you can create priority ceiling mutexes
+ *                      Indicates the availability of:
+ *                              pthread_mutex_getprioceiling
+ *                              pthread_mutex_setprioceiling
+ *                              pthread_mutexattr_getprioceiling
+ *                              pthread_mutexattr_getprotocol     +
+ *                              pthread_mutexattr_setprioceiling
+ *                              pthread_mutexattr_setprotocol     +
+ *
+ * _POSIX_THREAD_PROCESS_SHARED (== -1)
+ *                      If set, you can create mutexes and condition
+ *                      variables that can be shared with another
+ *                      process.If set, indicates the availability
+ *                      of:
+ *                              pthread_mutexattr_getpshared
+ *                              pthread_mutexattr_setpshared
+ *                              pthread_condattr_getpshared
+ *                              pthread_condattr_setpshared
+ *
+ * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L)
+ *                      If == 200112L you can use the special *_r library
+ *                      functions that provide thread-safe behaviour
+ *
+ * _POSIX_READER_WRITER_LOCKS (== 200112L)
+ *                      If == 200112L, you can use read/write locks
+ *
+ * _POSIX_SPIN_LOCKS (== 200112L)
+ *                      If == 200112L, you can use spin locks
+ *
+ * _POSIX_BARRIERS (== 200112L)
+ *                      If == 200112L, you can use barriers
+ *
+ *      + These functions provide both 'inherit' and/or
+ *        'protect' protocol, based upon these macro
+ *        settings.
+ *
+ * -------------------------------------------------------------
+ */
+
+/*
+ * POSIX Options
+ */
+#undef _POSIX_THREADS
+#define _POSIX_THREADS 200112L
+
+#undef _POSIX_READER_WRITER_LOCKS
+#define _POSIX_READER_WRITER_LOCKS 200112L
+
+#undef _POSIX_SPIN_LOCKS
+#define _POSIX_SPIN_LOCKS 200112L
+
+#undef _POSIX_BARRIERS
+#define _POSIX_BARRIERS 200112L
+
+#undef _POSIX_THREAD_SAFE_FUNCTIONS
+#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L
+
+#undef _POSIX_THREAD_ATTR_STACKSIZE
+#define _POSIX_THREAD_ATTR_STACKSIZE 200112L
+
+/*
+ * The following options are not supported
+ */
+#undef _POSIX_THREAD_ATTR_STACKADDR
+#define _POSIX_THREAD_ATTR_STACKADDR -1
+
+#undef _POSIX_THREAD_PRIO_INHERIT
+#define _POSIX_THREAD_PRIO_INHERIT -1
+
+#undef _POSIX_THREAD_PRIO_PROTECT
+#define _POSIX_THREAD_PRIO_PROTECT -1
+
+/* TPS is not fully supported.  */
+#undef _POSIX_THREAD_PRIORITY_SCHEDULING
+#define _POSIX_THREAD_PRIORITY_SCHEDULING -1
+
+#undef _POSIX_THREAD_PROCESS_SHARED
+#define _POSIX_THREAD_PROCESS_SHARED -1
+
+
+/*
+ * POSIX 1003.1-2001 Limits
+ * ===========================
+ *
+ * These limits are normally set in <limits.h>, which is not provided with
+ * pthreads-win32.
+ *
+ * PTHREAD_DESTRUCTOR_ITERATIONS
+ *                      Maximum number of attempts to destroy
+ *                      a thread's thread-specific data on
+ *                      termination (must be at least 4)
+ *
+ * PTHREAD_KEYS_MAX
+ *                      Maximum number of thread-specific data keys
+ *                      available per process (must be at least 128)
+ *
+ * PTHREAD_STACK_MIN
+ *                      Minimum supported stack size for a thread
+ *
+ * PTHREAD_THREADS_MAX
+ *                      Maximum number of threads supported per
+ *                      process (must be at least 64).
+ *
+ * SEM_NSEMS_MAX
+ *                      The maximum number of semaphores a process can have.
+ *                      (must be at least 256)
+ *
+ * SEM_VALUE_MAX
+ *                      The maximum value a semaphore can have.
+ *                      (must be at least 32767)
+ *
+ */
+#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS
+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS     4
+
+#undef PTHREAD_DESTRUCTOR_ITERATIONS
+#define PTHREAD_DESTRUCTOR_ITERATIONS           _POSIX_THREAD_DESTRUCTOR_ITERATIONS
+
+#undef _POSIX_THREAD_KEYS_MAX
+#define _POSIX_THREAD_KEYS_MAX                  128
+
+#undef PTHREAD_KEYS_MAX
+#define PTHREAD_KEYS_MAX                        _POSIX_THREAD_KEYS_MAX
+
+#undef PTHREAD_STACK_MIN
+#define PTHREAD_STACK_MIN                       0
+
+#undef _POSIX_THREAD_THREADS_MAX
+#define _POSIX_THREAD_THREADS_MAX               64
+
+  /* Arbitrary value */
+#undef PTHREAD_THREADS_MAX
+#define PTHREAD_THREADS_MAX                     2019
+
+#undef _POSIX_SEM_NSEMS_MAX
+#define _POSIX_SEM_NSEMS_MAX                    256
+
+  /* Arbitrary value */
+#undef SEM_NSEMS_MAX
+#define SEM_NSEMS_MAX                           1024
+
+#undef _POSIX_SEM_VALUE_MAX
+#define _POSIX_SEM_VALUE_MAX                    32767
+
+#undef SEM_VALUE_MAX
+#define SEM_VALUE_MAX                           INT_MAX
+
+
+#if __GNUC__ && ! defined (__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the DLL code, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the DLL,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#ifndef PTW32_STATIC_LIB
+#  ifdef PTW32_BUILD
+#    define PTW32_DLLPORT __declspec (dllexport)
+#  else
+#    define PTW32_DLLPORT __declspec (dllimport)
+#  endif
+#else
+#  define PTW32_DLLPORT
+#endif
+
+/*
+ * The Open Watcom C/C++ compiler uses a non-standard calling convention
+ * that passes function args in registers unless __cdecl is explicitly specified
+ * in exposed function prototypes.
+ *
+ * We force all calls to cdecl even though this could slow Watcom code down
+ * slightly. If you know that the Watcom compiler will be used to build both
+ * the DLL and application, then you can probably define this as a null string.
+ * Remember that pthread.h (this file) is used for both the DLL and application builds.
+ */
+#define PTW32_CDECL __cdecl
+
+#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX
+#   include     <sys/types.h>
+#else
+/*
+ * Generic handle type - intended to extend uniqueness beyond
+ * that available with a simple pointer. It should scale for either
+ * IA-32 or IA-64.
+ */
+typedef struct {
+    void * p;                   /* Pointer to actual object */
+    unsigned int x;             /* Extra information - reuse count etc */
+} ptw32_handle_t;
+
+typedef ptw32_handle_t pthread_t;
+typedef struct pthread_attr_t_ * pthread_attr_t;
+typedef struct pthread_once_t_ pthread_once_t;
+typedef struct pthread_key_t_ * pthread_key_t;
+typedef struct pthread_mutex_t_ * pthread_mutex_t;
+typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t;
+typedef struct pthread_cond_t_ * pthread_cond_t;
+typedef struct pthread_condattr_t_ * pthread_condattr_t;
+#endif
+typedef struct pthread_rwlock_t_ * pthread_rwlock_t;
+typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t;
+typedef struct pthread_spinlock_t_ * pthread_spinlock_t;
+typedef struct pthread_barrier_t_ * pthread_barrier_t;
+typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t;
+
+/*
+ * ====================
+ * ====================
+ * POSIX Threads
+ * ====================
+ * ====================
+ */
+
+enum {
+/*
+ * pthread_attr_{get,set}detachstate
+ */
+  PTHREAD_CREATE_JOINABLE       = 0,  /* Default */
+  PTHREAD_CREATE_DETACHED       = 1,
+
+/*
+ * pthread_attr_{get,set}inheritsched
+ */
+  PTHREAD_INHERIT_SCHED         = 0,
+  PTHREAD_EXPLICIT_SCHED        = 1,  /* Default */
+
+/*
+ * pthread_{get,set}scope
+ */
+  PTHREAD_SCOPE_PROCESS         = 0,
+  PTHREAD_SCOPE_SYSTEM          = 1,  /* Default */
+
+/*
+ * pthread_setcancelstate paramters
+ */
+  PTHREAD_CANCEL_ENABLE         = 0,  /* Default */
+  PTHREAD_CANCEL_DISABLE        = 1,
+
+/*
+ * pthread_setcanceltype parameters
+ */
+  PTHREAD_CANCEL_ASYNCHRONOUS   = 0,
+  PTHREAD_CANCEL_DEFERRED       = 1,  /* Default */
+
+/*
+ * pthread_mutexattr_{get,set}pshared
+ * pthread_condattr_{get,set}pshared
+ */
+  PTHREAD_PROCESS_PRIVATE       = 0,
+  PTHREAD_PROCESS_SHARED        = 1,
+
+/*
+ * pthread_barrier_wait
+ */
+  PTHREAD_BARRIER_SERIAL_THREAD = -1
+};
+
+/*
+ * ====================
+ * ====================
+ * Cancelation
+ * ====================
+ * ====================
+ */
+#define PTHREAD_CANCELED       ((void *) -1)
+
+
+/*
+ * ====================
+ * ====================
+ * Once Key
+ * ====================
+ * ====================
+ */
+#define PTHREAD_ONCE_INIT       { PTW32_FALSE, 0, 0, 0}
+
+struct pthread_once_t_
+{
+  int          done;        /* indicates if user function has been executed */
+  void *       lock;
+  int          reserved1;
+  int          reserved2;
+};
+
+
+/*
+ * ====================
+ * ====================
+ * Object initialisers
+ * ====================
+ * ====================
+ */
+#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1)
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2)
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3)
+
+/*
+ * Compatibility with LinuxThreads
+ */
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
+
+#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1)
+
+#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1)
+
+#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1)
+
+
+/*
+ * Mutex types.
+ */
+enum
+{
+  /* Compatibility with LinuxThreads */
+  PTHREAD_MUTEX_FAST_NP,
+  PTHREAD_MUTEX_RECURSIVE_NP,
+  PTHREAD_MUTEX_ERRORCHECK_NP,
+  PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP,
+  PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP,
+  /* For compatibility with POSIX */
+  PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP,
+  PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
+  PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
+  PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
+};
+
+
+typedef struct ptw32_cleanup_t ptw32_cleanup_t;
+
+#if defined(_MSC_VER)
+/* Disable MSVC 'anachronism used' warning */
+#pragma warning( disable : 4229 )
+#endif
+
+typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *);
+
+#if defined(_MSC_VER)
+#pragma warning( default : 4229 )
+#endif
+
+struct ptw32_cleanup_t
+{
+  ptw32_cleanup_callback_t routine;
+  void *arg;
+  struct ptw32_cleanup_t *prev;
+};
+
+#ifdef __CLEANUP_SEH
+        /*
+         * WIN32 SEH version of cancel cleanup.
+         */
+
+#define pthread_cleanup_push( _rout, _arg ) \
+        { \
+            ptw32_cleanup_t     _cleanup; \
+            \
+        _cleanup.routine        = (ptw32_cleanup_callback_t)(_rout); \
+            _cleanup.arg        = (_arg); \
+            __try \
+              { \
+
+#define pthread_cleanup_pop( _execute ) \
+              } \
+            __finally \
+                { \
+                    if( _execute || AbnormalTermination()) \
+                      { \
+                          (*(_cleanup.routine))( _cleanup.arg ); \
+                      } \
+                } \
+        }
+
+#else /* __CLEANUP_SEH */
+
+#ifdef __CLEANUP_C
+
+        /*
+         * C implementation of PThreads cancel cleanup
+         */
+
+#define pthread_cleanup_push( _rout, _arg ) \
+        { \
+            ptw32_cleanup_t     _cleanup; \
+            \
+            ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \
+
+#define pthread_cleanup_pop( _execute ) \
+            (void) ptw32_pop_cleanup( _execute ); \
+        }
+
+#else /* __CLEANUP_C */
+
+#ifdef __CLEANUP_CXX
+
+        /*
+         * C++ version of cancel cleanup.
+         * - John E. Bossom.
+         */
+
+        class PThreadCleanup {
+          /*
+           * PThreadCleanup
+           *
+           * Purpose
+           *      This class is a C++ helper class that is
+           *      used to implement pthread_cleanup_push/
+           *      pthread_cleanup_pop.
+           *      The destructor of this class automatically
+           *      pops the pushed cleanup routine regardless
+           *      of how the code exits the scope
+           *      (i.e. such as by an exception)
+           */
+      ptw32_cleanup_callback_t cleanUpRout;
+          void    *       obj;
+          int             executeIt;
+
+        public:
+          PThreadCleanup() :
+            cleanUpRout( 0 ),
+            obj( 0 ),
+            executeIt( 0 )
+            /*
+             * No cleanup performed
+             */
+            {
+            }
+
+          PThreadCleanup(
+             ptw32_cleanup_callback_t routine,
+                         void    *       arg ) :
+            cleanUpRout( routine ),
+            obj( arg ),
+            executeIt( 1 )
+            /*
+             * Registers a cleanup routine for 'arg'
+             */
+            {
+            }
+
+          ~PThreadCleanup()
+            {
+              if ( executeIt && ((void *) cleanUpRout != (void *) 0) )
+                {
+                  (void) (*cleanUpRout)( obj );
+                }
+            }
+
+          void execute( int exec )
+            {
+              executeIt = exec;
+            }
+        };
+
+        /*
+         * C++ implementation of PThreads cancel cleanup;
+         * This implementation takes advantage of a helper
+         * class who's destructor automatically calls the
+         * cleanup routine if we exit our scope weirdly
+         */
+#define pthread_cleanup_push( _rout, _arg ) \
+        { \
+            PThreadCleanup  cleanup((ptw32_cleanup_callback_t)(_rout), \
+                                    (void *) (_arg) );
+
+#define pthread_cleanup_pop( _execute ) \
+            cleanup.execute( _execute ); \
+        }
+
+#else
+
+#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* __CLEANUP_C */
+
+#endif /* __CLEANUP_SEH */
+
+/*
+ * ===============
+ * ===============
+ * Methods
+ * ===============
+ * ===============
+ */
+
+/*
+ * PThread Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr,
+                                         int *detachstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr,
+                                       void **stackaddr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr,
+                                       size_t * stacksize);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr,
+                                         int detachstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr,
+                                       void *stackaddr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr,
+                                       size_t stacksize);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr,
+                                        struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr,
+                                        const struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *,
+                                         int);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *,
+                                         int *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr,
+                                         int inheritsched);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr,
+                                         int * inheritsched);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *,
+                                   int);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *,
+                                   int *);
+
+/*
+ * PThread Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid,
+                            const pthread_attr_t * attr,
+                            void *(*start) (void *),
+                            void *arg);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1,
+                           pthread_t t2);
+
+PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread,
+                          void **value_ptr);
+
+PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state,
+                                    int *oldstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type,
+                                   int *oldtype);
+
+PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control,
+                          void (*init_routine) (void));
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute);
+
+PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup,
+                                 void (*routine) (void *),
+                                 void *arg);
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Thread Specific Data Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key,
+                                void (*destructor) (void *));
+
+PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key,
+                                 const void *value);
+
+PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key);
+
+
+/*
+ * Mutex Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t
+                                          * attr,
+                                          int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr,
+                                          int pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind);
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind);
+
+/*
+ * Barrier Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t
+                                            * attr,
+                                            int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr,
+                                            int pshared);
+
+/*
+ * Mutex Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex,
+                                const pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t *mutex,
+                                    const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex);
+
+/*
+ * Spinlock Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock);
+
+/*
+ * Barrier Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier,
+                                  const pthread_barrierattr_t * attr,
+                                  unsigned int count);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier);
+
+/*
+ * Condition Variable Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr,
+                                         int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr,
+                                         int pshared);
+
+/*
+ * Condition Variable Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond,
+                               const pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond,
+                               pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond,
+                                    pthread_mutex_t * mutex,
+                                    const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond);
+
+/*
+ * Scheduling
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread,
+                                   int policy,
+                                   const struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread,
+                                   int *policy,
+                                   struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int);
+ 
+PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void);
+
+/*
+ * Read-Write Lock Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock,
+                                const pthread_rwlockattr_t *attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock,
+                                       const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock,
+                                       const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr,
+                                           int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr,
+                                           int pshared);
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1
+
+/*
+ * Signal Functions. Should be defined in <signal.h> but MSVC and MinGW32
+ * already have signal.h that don't define these.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig);
+
+/*
+ * Non-portable functions
+ */
+
+/*
+ * Compatibility with Linux.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr,
+                                         int kind);
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr,
+                                         int *kind);
+
+/*
+ * Possibly supported by other POSIX threads implementations
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval);
+PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void);
+
+/*
+ * Useful if an application wants to statically link
+ * the lib rather than load the DLL at run-time.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void);
+
+/*
+ * Features that are auto-detected at load/run time.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int);
+enum ptw32_features {
+  PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */
+  PTW32_ALERTABLE_ASYNC_CANCEL              = 0x0002  /* Can cancel blocked threads. */
+};
+
+/*
+ * Register a system time change with the library.
+ * Causes the library to perform various functions
+ * in response to the change. Should be called whenever
+ * the application's top level window receives a
+ * WM_TIMECHANGE message. It can be passed directly to
+ * pthread_create() as a new thread if desired.
+ */
+PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *);
+
+#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+
+/*
+ * Returns the Win32 HANDLE for the POSIX thread.
+ */
+PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread);
+
+
+/*
+ * Protected Methods
+ *
+ * This function blocks until the given WIN32 handle
+ * is signaled or pthread_cancel had been called.
+ * This function allows the caller to hook into the
+ * PThreads cancel mechanism. It is implemented using
+ *
+ *              WaitForMultipleObjects
+ *
+ * on 'waitHandle' and a manually reset WIN32 Event
+ * used to implement pthread_cancel. The 'timeout'
+ * argument to TimedWait is simply passed to
+ * WaitForMultipleObjects.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle);
+PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle,
+                                        DWORD timeout);
+
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Thread-Safe C Runtime Library Mappings.
+ */
+#ifndef _UWIN
+#  if defined(NEED_ERRNO)
+     PTW32_DLLPORT int * PTW32_CDECL _errno( void );
+#  else
+#    ifndef errno
+#      if (defined(_MT) || defined(_DLL))
+         __declspec(dllimport) extern int * __cdecl _errno(void);
+#        define errno   (*_errno())
+#      endif
+#    endif
+#  endif
+#endif
+
+/*
+ * WIN32 C runtime library had been made thread-safe
+ * without affecting the user interface. Provide
+ * mappings from the UNIX thread-safe versions to
+ * the standard C runtime library calls.
+ * Only provide function mappings for functions that
+ * actually exist on WIN32.
+ */
+
+#if !defined(__MINGW32__)
+#define strtok_r( _s, _sep, _lasts ) \
+        ( *(_lasts) = strtok( (_s), (_sep) ) )
+#endif /* !__MINGW32__ */
+
+#define asctime_r( _tm, _buf ) \
+        ( strcpy( (_buf), asctime( (_tm) ) ), \
+          (_buf) )
+
+#define ctime_r( _clock, _buf ) \
+        ( strcpy( (_buf), ctime( (_clock) ) ),  \
+          (_buf) )
+
+#define gmtime_r( _clock, _result ) \
+        ( *(_result) = *gmtime( (_clock) ), \
+          (_result) )
+
+#define localtime_r( _clock, _result ) \
+        ( *(_result) = *localtime( (_clock) ), \
+          (_result) )
+
+#define rand_r( _seed ) \
+        ( _seed == _seed? rand() : rand() )
+
+
+/*
+ * Some compiler environments don't define some things.
+ */
+#if defined(__BORLANDC__)
+#  define _ftime ftime
+#  define _timeb timeb
+#endif
+
+#ifdef __cplusplus
+
+/*
+ * Internal exceptions
+ */
+class ptw32_exception {};
+class ptw32_exception_cancel : public ptw32_exception {};
+class ptw32_exception_exit   : public ptw32_exception {};
+
+#endif
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+
+/* FIXME: This is only required if the library was built using SEH */
+/*
+ * Get internal SEH tag
+ */
+PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void);
+
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#ifndef PTW32_BUILD
+
+#ifdef __CLEANUP_SEH
+
+/*
+ * Redefine the SEH __except keyword to ensure that applications
+ * propagate our internal exceptions up to the library's internal handlers.
+ */
+#define __except( E ) \
+        __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \
+                 ? EXCEPTION_CONTINUE_SEARCH : ( E ) )
+
+#endif /* __CLEANUP_SEH */
+
+#ifdef __CLEANUP_CXX
+
+/*
+ * Redefine the C++ catch keyword to ensure that applications
+ * propagate our internal exceptions up to the library's internal handlers.
+ */
+#ifdef _MSC_VER
+        /*
+         * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll'
+         * if you want Pthread-Win32 cancelation and pthread_exit to work.
+         */
+
+#ifndef PtW32NoCatchWarn
+
+#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.")
+#pragma message("------------------------------------------------------------------")
+#pragma message("When compiling applications with MSVC++ and C++ exception handling:")
+#pragma message("  Replace any 'catch( ... )' in routines called from POSIX threads")
+#pragma message("  with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread")
+#pragma message("  cancelation and pthread_exit to work. For example:")
+#pragma message("")
+#pragma message("    #ifdef PtW32CatchAll")
+#pragma message("      PtW32CatchAll")
+#pragma message("    #else")
+#pragma message("      catch(...)")
+#pragma message("    #endif")
+#pragma message("        {")
+#pragma message("          /* Catchall block processing */")
+#pragma message("        }")
+#pragma message("------------------------------------------------------------------")
+
+#endif
+
+#define PtW32CatchAll \
+        catch( ptw32_exception & ) { throw; } \
+        catch( ... )
+
+#else /* _MSC_VER */
+
+#define catch( E ) \
+        catch( ptw32_exception & ) { throw; } \
+        catch( E )
+
+#endif /* _MSC_VER */
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* ! PTW32_BUILD */
+
+#ifdef __cplusplus
+}                               /* End of extern "C" */
+#endif                          /* __cplusplus */
+
+#ifdef PTW32__HANDLE_DEF
+# undef HANDLE
+#endif
+#ifdef PTW32__DWORD_DEF
+# undef DWORD
+#endif
+
+#undef PTW32_LEVEL
+#undef PTW32_LEVEL_MAX
+
+#endif /* ! RC_INVOKED */
+
+#endif /* PTHREAD_H */
diff --git a/abc-build/lib/sched.h b/abc-build/lib/sched.h
new file mode 100644
--- /dev/null
+++ b/abc-build/lib/sched.h
@@ -0,0 +1,178 @@
+/*
+ * Module: sched.h
+ *
+ * Purpose:
+ *      Provides an implementation of POSIX realtime extensions
+ *      as defined in 
+ *
+ *              POSIX 1003.1b-1993      (POSIX.1b)
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 Pthreads-win32 contributors
+ * 
+ *      Contact Email: rpj@callisto.canberra.edu.au
+ * 
+ *      The current list of contributors is contained
+ *      in the file CONTRIBUTORS included with the source
+ *      code distribution. The list can also be seen at the
+ *      following World Wide Web location:
+ *      http://sources.redhat.com/pthreads-win32/contributors.html
+ * 
+ *      This library is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU Lesser General Public
+ *      License as published by the Free Software Foundation; either
+ *      version 2 of the License, or (at your option) any later version.
+ * 
+ *      This library 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
+ *      Lesser General Public License for more details.
+ * 
+ *      You should have received a copy of the GNU Lesser General Public
+ *      License along with this library in the file COPYING.LIB;
+ *      if not, write to the Free Software Foundation, Inc.,
+ *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+#ifndef _SCHED_H
+#define _SCHED_H
+
+#undef PTW32_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_LEVEL_MAX 3
+
+#if !defined(PTW32_LEVEL)
+#define PTW32_LEVEL PTW32_LEVEL_MAX
+/* Include everything */
+#endif
+
+
+#if __GNUC__ && ! defined (__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the DLL code, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the DLL,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#ifndef PTW32_STATIC_LIB
+#  ifdef PTW32_BUILD
+#    define PTW32_DLLPORT __declspec (dllexport)
+#  else
+#    define PTW32_DLLPORT __declspec (dllimport)
+#  endif
+#else
+#  define PTW32_DLLPORT
+#endif
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#ifndef PTW32_CONFIG_H
+#  if defined(WINCE)
+#    define NEED_ERRNO
+#    define NEED_SEM
+#  endif
+#  if defined(_UWIN) || defined(__MINGW32__)
+#    define HAVE_MODE_T
+#  endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+#ifdef NEED_ERRNO
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#if defined(__MINGW32__) || defined(_UWIN)
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+/* For pid_t */
+#  include <sys/types.h>
+/* Required by Unix 98 */
+#  include <time.h>
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+#else
+typedef int pid_t;
+#endif
+
+/* Thread scheduling policies */
+
+enum {
+  SCHED_OTHER = 0,
+  SCHED_FIFO,
+  SCHED_RR,
+  SCHED_MIN   = SCHED_OTHER,
+  SCHED_MAX   = SCHED_RR
+};
+
+struct sched_param {
+  int sched_priority;
+};
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif                          /* __cplusplus */
+
+PTW32_DLLPORT int __cdecl sched_yield (void);
+
+PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy);
+
+PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy);
+
+PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy);
+
+PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid);
+
+/*
+ * Note that this macro returns ENOTSUP rather than
+ * ENOSYS as might be expected. However, returning ENOSYS
+ * should mean that sched_get_priority_{min,max} are
+ * not implemented as well as sched_rr_get_interval.
+ * This is not the case, since we just don't support
+ * round-robin scheduling. Therefore I have chosen to
+ * return the same value as sched_setscheduler when
+ * SCHED_RR is passed to it.
+ */
+#define sched_rr_get_interval(_pid, _interval) \
+  ( errno = ENOTSUP, (int) -1 )
+
+
+#ifdef __cplusplus
+}                               /* End of extern "C" */
+#endif                          /* __cplusplus */
+
+#undef PTW32_LEVEL
+#undef PTW32_LEVEL_MAX
+
+#endif                          /* !_SCHED_H */
+
diff --git a/abc-build/lib/semaphore.h b/abc-build/lib/semaphore.h
new file mode 100644
--- /dev/null
+++ b/abc-build/lib/semaphore.h
@@ -0,0 +1,166 @@
+/*
+ * Module: semaphore.h
+ *
+ * Purpose:
+ *	Semaphores aren't actually part of the PThreads standard.
+ *	They are defined by the POSIX Standard:
+ *
+ *		POSIX 1003.1b-1993	(POSIX.1b)
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 Pthreads-win32 contributors
+ * 
+ *      Contact Email: rpj@callisto.canberra.edu.au
+ * 
+ *      The current list of contributors is contained
+ *      in the file CONTRIBUTORS included with the source
+ *      code distribution. The list can also be seen at the
+ *      following World Wide Web location:
+ *      http://sources.redhat.com/pthreads-win32/contributors.html
+ * 
+ *      This library is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU Lesser General Public
+ *      License as published by the Free Software Foundation; either
+ *      version 2 of the License, or (at your option) any later version.
+ * 
+ *      This library 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
+ *      Lesser General Public License for more details.
+ * 
+ *      You should have received a copy of the GNU Lesser General Public
+ *      License along with this library in the file COPYING.LIB;
+ *      if not, write to the Free Software Foundation, Inc.,
+ *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+#if !defined( SEMAPHORE_H )
+#define SEMAPHORE_H
+
+#undef PTW32_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_LEVEL_MAX 3
+
+#if !defined(PTW32_LEVEL)
+#define PTW32_LEVEL PTW32_LEVEL_MAX
+/* Include everything */
+#endif
+
+#if __GNUC__ && ! defined (__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the DLL code, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the DLL,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#ifndef PTW32_STATIC_LIB
+#  ifdef PTW32_BUILD
+#    define PTW32_DLLPORT __declspec (dllexport)
+#  else
+#    define PTW32_DLLPORT __declspec (dllimport)
+#  endif
+#else
+#  define PTW32_DLLPORT
+#endif
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#ifndef PTW32_CONFIG_H
+#  if defined(WINCE)
+#    define NEED_ERRNO
+#    define NEED_SEM
+#  endif
+#  if defined(_UWIN) || defined(__MINGW32__)
+#    define HAVE_MODE_T
+#  endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+#ifdef NEED_ERRNO
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#define _POSIX_SEMAPHORES
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif				/* __cplusplus */
+
+#ifndef HAVE_MODE_T
+typedef unsigned int mode_t;
+#endif
+
+
+typedef struct sem_t_ * sem_t;
+
+PTW32_DLLPORT int __cdecl sem_init (sem_t * sem,
+			    int pshared,
+			    unsigned int value);
+
+PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem,
+				 const struct timespec * abstime);
+
+PTW32_DLLPORT int __cdecl sem_post (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem,
+				     int count);
+
+PTW32_DLLPORT int __cdecl sem_open (const char * name,
+			    int oflag,
+			    mode_t mode,
+			    unsigned int value);
+
+PTW32_DLLPORT int __cdecl sem_close (sem_t * sem);
+
+PTW32_DLLPORT int __cdecl sem_unlink (const char * name);
+
+PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem,
+				int * sval);
+
+#ifdef __cplusplus
+}				/* End of extern "C" */
+#endif				/* __cplusplus */
+
+#undef PTW32_LEVEL
+#undef PTW32_LEVEL_MAX
+
+#endif				/* !SEMAPHORE_H */
diff --git a/abc-build/lib/x64/pthreadVC2.dll b/abc-build/lib/x64/pthreadVC2.dll
new file mode 100644
Binary files /dev/null and b/abc-build/lib/x64/pthreadVC2.dll differ
diff --git a/abc-build/lib/x64/pthreadVC2.lib b/abc-build/lib/x64/pthreadVC2.lib
new file mode 100644
Binary files /dev/null and b/abc-build/lib/x64/pthreadVC2.lib differ
diff --git a/abc-build/lib/x86/pthreadVC2.dll b/abc-build/lib/x86/pthreadVC2.dll
new file mode 100644
Binary files /dev/null and b/abc-build/lib/x86/pthreadVC2.dll differ
diff --git a/abc-build/lib/x86/pthreadVC2.lib b/abc-build/lib/x86/pthreadVC2.lib
new file mode 100644
Binary files /dev/null and b/abc-build/lib/x86/pthreadVC2.lib differ
diff --git a/abc-build/readme.md b/abc-build/readme.md
new file mode 100644
--- /dev/null
+++ b/abc-build/readme.md
@@ -0,0 +1,106 @@
+# ABC: System for Sequential Logic Synthesis and Formal Verification
+
+ABC is always changing but the current snapshot is believed to be stable. 
+
+## Compiling:
+
+To compile ABC as a binary, download and unzip the code, then type `make`.
+
+To compile ABC as a static library, comment out `#define ABC_LIB` in file 
+"src/base/main/main.c", then type `make libabc.a`.
+
+When ABC is used as a static library, two additional procedures, `Abc_Start()` 
+and `Abc_Stop()`, are provided for starting and quitting the ABC framework in 
+the calling application. A simple demo program (file src/demo.c) shows how to 
+create a stand-alone program performing DAG-aware AIG rewriting, by calling 
+APIs of ABC compiled as a static library.
+
+To build the demo program
+
+ * Copy demo.cc and libabc.a to the working directory
+ * Run `gcc -Wall -g -c demo.c -o demo.o`
+ * Run `gcc -g -o demo demo.o libabc.a -lm -ldl -rdynamic -lreadline -ltermcap -lpthread`
+
+To run the demo program, give it a file with the logic network in AIGER or BLIF. For example:
+
+    [...] ~/abc> demo i10.aig
+    i10          : i/o =  257/  224  lat =    0  and =   2396  lev = 37
+    i10          : i/o =  257/  224  lat =    0  and =   1851  lev = 35
+    Networks are equivalent.
+    Reading =   0.00 sec   Rewriting =   0.18 sec   Verification =   0.41 sec
+
+The same can be produced by running the binary in the command-line mode:
+
+    [...] ~/abc> ./abc
+    UC Berkeley, ABC 1.01 (compiled Oct  6 2012 19:05:18)
+    abc 01> r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec
+    i10          : i/o =  257/  224  lat =    0  and =   2396  lev = 37
+    i10          : i/o =  257/  224  lat =    0  and =   1851  lev = 35
+    Networks are equivalent.
+
+or in the batch mode:
+
+    [...] ~/abc> ./abc -c "r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec"
+    ABC command line: "r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec".
+    i10          : i/o =  257/  224  lat =    0  and =   2396  lev = 37
+    i10          : i/o =  257/  224  lat =    0  and =   1851  lev = 35
+    Networks are equivalent.
+
+## Compiling as C or C++
+
+The current version of ABC can be compiled with C compiler or C++ compiler.
+
+ * To compile as C code (default): make sure that `CC=gcc` and `ABC_NAMESPACE` is not defined.
+ * To compile as C++ code without namespaces: make sure that `CC=g++` and `ABC_NAMESPACE` is not defined.
+ * To compile as C++ code with namespaces: make sure that `CC=g++` and `ABC_NAMESPACE` is set to
+   the name of the requested namespace. For example, add `-DABC_NAMESPACE=xxx` to OPTFLAGS.
+
+## Bug reporting:
+
+Please try to reproduce all the reported bugs and unexpected features using the latest 
+version of ABC available from https://bitbucket.org/alanmi/abc/
+
+If the bug still persists, please provide the following information:    
+
+ 1. ABC version (when it was downloaded from BitBucket)
+ 1. Linux distribution and version (32-bit or 64-bit)
+ 1. The exact command-line and error message when trying to run the tool
+ 1. The output of the `ldd` command run on the exeutable (e.g. `ldd abc`).
+ 1. Versions of relevant tools or packages used.
+
+
+## Troubleshooting:
+
+ 1. If compilation does not start because of the cyclic dependency check, 
+try touching all files as follows: `find ./ -type f -exec touch "{}" \;`
+ 1. If compilation fails because readline is missing, install 'readline' library or
+compile with `make READLINE=0`
+ 1. If compilation fails because pthreads are missing, install 'pthread' library or
+compile with `make PTHREADS=0`
+    * See http://sourceware.org/pthreads-win32/ for pthreads on Windows
+    * Precompiled DLLs are available from ftp://sourceware.org/pub/pthreads-win32/dll-latest
+ 1. If compilation fails in file "src/base/main/libSupport.c", try the following:
+    * Remove "src/base/main/libSupport.c" from "src/base/main/module.make"
+    * Comment out calls to `Libs_Init()` and `Libs_End()` in "src/base/main/mainInit.c"
+ 1. On some systems, readline requires adding '-lcurses' to Makefile.
+
+The following comment was added by Krish Sundaresan:
+
+"I found that the code does compile correctly on Solaris if gcc is used (instead of 
+g++ that I was using for some reason). Also readline which is not available by default 
+on most Sol10 systems, needs to be installed. I downloaded the readline-5.2 package 
+from sunfreeware.com and installed it locally. Also modified CFLAGS to add the local 
+include files for readline and LIBS to add the local libreadline.a. Perhaps you can 
+add these steps in the readme to help folks compiling this on Solaris."
+
+The following tutorial is kindly offered by Ana Petkovska from EPFL:
+https://www.dropbox.com/s/qrl9svlf0ylxy8p/ABC_GettingStarted.pdf
+
+## Final remarks:
+
+Unfortunately, there is no comprehensive regression test. Good luck!                                
+
+This system is maintained by Alan Mishchenko <alanmi@berkeley.edu>. Consider also 
+using ZZ framework developed by Niklas Een: https://bitbucket.org/niklaseen/abc-zz
+
+This file was last modified on June 18, 2014
diff --git a/abc-build/readmeaig b/abc-build/readmeaig
new file mode 100644
--- /dev/null
+++ b/abc-build/readmeaig
@@ -0,0 +1,47 @@
+Using AIG Package in ABC
+
+- Download the latest snapshot of ABC
+- Compile the code found in "abc\src\aig\aig", "abc\src\aig\saig", and "abc\src\misc\vec" as a static library.
+- Link the library to the project.
+- Add #include "saig.h".
+- Start the AIG package using Aig_ManStart().
+- Assign primary inputs using Aig_ObjCreateCi().
+- Assign register outputs using Aig_ObjCreateCi().
+(it is important to create all PIs first, before creating register outputs).
+- Construct AIG in the topological order using Aig_And(), Aig_Or(), Aig_Not(), etc.
+- If constant-0/1 AIG nodes are needed, use Aig_ManConst0() or Aig_ManConst1()
+- Create primary outputs using Aig_ObjCreateCo().
+- Create register inputs using Aig_ObjCreateCo().
+(it is important to create all POs first, before creating register inputs).
+- Set the number of registers by calling Aig_ManSetRegNum().
+- Remove dangling AIG nodes (produced by structural hashing) using Aig_ManCleanup().
+- Call the consistency checking procedure Aig_ManCheck().
+- Dump AIG into a file using the new BLIF dumper Saig_ManDumpBlif().
+- For each object in the design annotated with the constructed AIG node (pNode), remember its AIG node ID by calling Aig_ObjId( Aig_Regular(pNode) ). To check whether the corresponding AIG node is complemented use Aig_IsComplement(pNode).
+- Quit the AIG package using Aig_ManStop().
+The above process should not produce memory leaks.
+
+
+
+Using GIA Package in ABC
+
+- Add #include "gia.h".
+- Start the AIG package using Gia_ManStart( int nObjMax ).
+(Parameter 'nNodeMax' should approximately reflect the expected number of objects, including PIs, POs, flop inputs, and flop outputs.  If the number of objects is more, memory will be automatically reallocated.)
+- If structural hashing is to be used, start hash table by calling Gia_ManHashStart().
+- Similarly, whenever structural hashingn is no longer needed, deallocate hash table by calling Gia_ManHashStop().
+- Assign primary inputs using Gia_ManAppendCi().
+- Assign flop outputs using Gia_ManAppendCi().
+(It is important to create all PIs first, before creating flop outputs).
+(Flop control logic, if present, should be elaborated into AND gates.  For example, to represent a flop enable, create the driver of enable signal, which can be a PI or an internal node, and then add logic for <flop_input_new> = MUX( <enable>, <flop_input>, <flop_output> ).  The output of this logic feeds into the flop.
+- Construct AIG in the topological order using Gia_ManHashAnd(), Gia_ManHashOr(), Gia_Not(), etc.
+- If constant-0/1 AIG nodes are needed, use Gia_ManConst0() or Gia_ManConst1()
+- Create primary outputs using Gia_ManAppendCo().
+- Create flop inputs using Gia_ManAppendCo().
+(it is important to create all POs first, before creating register inputs).
+- Set the number of flops by calling Gia_ManSetRegNum().
+- Remove dangling AIG nodes (produced by structural hashing) by running Gia_ManCleanup(), which will return a new AIG.  If object mapping is defined for the original AIG, it should be remapped into the new AIG.
+- Dump AIG into an AIGER file use Gia_DumpAiger().
+- For each object in the design annotated with the constructed AIG node (pNode), remember its AIG node ID by calling Gia_ObjId(pMan,pNode).
+- Quit the AIG package using Gia_ManStop().
+The above process should not produce memory leaks.
diff --git a/abc-build/scripts/abc.rc b/abc-build/scripts/abc.rc
new file mode 100644
--- /dev/null
+++ b/abc-build/scripts/abc.rc
@@ -0,0 +1,147 @@
+# reachx
+python new_abc_commands.py
+python -c "import reachx_cmd"
+
+
+# global parameters
+set check         # checks intermediate networks
+#set checkfio      # prints warnings when fanins/fanouts are duplicated
+#unset checkread   # does not check new networks after reading from file
+#set backup        # saves backup networks retrived by "undo" and "recall"
+#set savesteps 1   # sets the maximum number of backup networks to save 
+#set progressbar   # display the progress bar
+
+# program names for internal calls
+set dotwin dot.exe
+set dotunix dot
+set gsviewwin gsview32.exe
+set gsviewunix gv
+set siswin sis.exe
+set sisunix sis
+set mvsiswin mvsis.exe
+set mvsisunix mvsis
+set capowin MetaPl-Capo10.1-Win32.exe
+set capounix MetaPl-Capo10.1
+set gnuplotwin wgnuplot.exe
+set gnuplotunix gnuplot
+
+# Niklas Een's commands
+#load_plugin C:\_projects\abc\lib\bip_win.exe "BIP"
+#load_plugin /hd/common/pyabc/bip "BIP"
+
+# standard aliases
+alias hi history
+alias b balance
+alias cg clockgate
+alias cl cleanup
+alias clp collapse
+alias cs care_set
+alias esd ext_seq_dcs
+alias f fraig
+alias fs fraig_sweep
+alias fsto fraig_store
+alias fres fraig_restore
+alias fr fretime
+alias ft fraig_trust
+alias ic indcut
+alias lp lutpack
+alias pcon print_cone
+alias pd print_dsd
+alias pex print_exdc -d
+alias pf print_factor
+alias pfan print_fanio
+alias pg print_gates
+alias pl print_level
+alias plat print_latch
+alias pio print_io
+alias pk print_kmap
+alias pm print_miter
+alias ps print_stats 
+alias psb print_stats -b
+alias psu print_supp
+alias psy print_symm
+alias pun print_unate
+alias q quit
+alias r read
+alias ra read_aiger
+alias r3 retime -M 3
+alias r3f retime -M 3 -f
+alias r3b retime -M 3 -b
+alias ren renode
+alias rh read_hie
+alias ri read_init
+alias rl read_blif
+alias rb read_bench
+alias ret retime
+alias dret dretime
+alias rp read_pla
+alias rt read_truth
+alias rv read_verilog
+alias rvl read_verlib
+alias rsup read_super mcnc5_old.super
+alias rlib read_library
+alias rlibc read_library cadence.genlib
+alias rty read_liberty
+alias rlut read_lut
+alias rw rewrite
+alias rwz rewrite -z
+alias rf refactor
+alias rfz refactor -z
+alias re restructure
+alias rez restructure -z
+alias rs resub
+alias rsz resub -z
+alias sa set autoexec ps
+alias scl scleanup
+alias sif if -s
+alias so source -x
+alias st strash
+alias sw sweep
+alias ssw ssweep
+alias tr0 trace_start
+alias tr1 trace_check
+alias trt "r c.blif; st; tr0; b; tr1"
+alias u undo
+alias w write
+alias wa write_aiger
+alias wb write_bench
+alias wc write_cnf
+alias wh write_hie
+alias wl write_blif
+alias wp write_pla
+alias wv write_verilog
+
+# standard scripts
+alias resyn       "b; rw; rwz; b; rwz; b"
+alias resyn2      "b; rw; rf; b; rw; rwz; b; rfz; rwz; b"
+alias resyn2a     "b; rw; b; rw; rwz; b; rwz; b"
+alias resyn3      "b; rs; rs -K 6; b; rsz; rsz -K 6; b; rsz -K 5; b"
+alias compress    "b -l; rw -l; rwz -l; b -l; rwz -l; b -l"
+alias compress2   "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l"
+alias choice      "fraig_store; resyn; fraig_store; resyn2; fraig_store; fraig_restore"
+alias choice2     "fraig_store; balance; fraig_store; resyn; fraig_store; resyn2; fraig_store; resyn2; fraig_store; fraig_restore"
+alias rwsat       "st; rw -l; b -l; rw -l; rf -l"
+alias drwsat2     "st; drw; b -l; drw; drf; ifraig -C 20; drw; b -l; drw; drf"
+alias share       "st; multi -m; fx; resyn2"
+alias addinit     "read_init; undc; strash; zero"
+alias blif2aig    "undc; strash; zero"
+alias v2p         "&vta_gla; &ps; &gla_derive; &put; w 1.aig; pdr -v"
+alias g2p         "&ps; &gla_derive; &put; w 2.aig; pdr -v"
+
+# resubstitution scripts for the IWLS paper
+alias src_rw      "st; rw -l; rwz -l; rwz -l" 
+alias src_rs      "st; rs -K 6 -N 2 -l; rs -K 9 -N 2 -l; rs -K 12 -N 2 -l" 
+alias src_rws     "st; rw -l; rs -K 6 -N 2 -l; rwz -l; rs -K 9 -N 2 -l; rwz -l; rs -K 12 -N 2 -l" 
+alias resyn2rs    "b; rs -K 6; rw; rs -K 6 -N 2; rf; rs -K 8; b; rs -K 8 -N 2; rw; rs -K 10; rwz; rs -K 10 -N 2; b; rs -K 12; rfz; rs -K 12 -N 2; rwz; b"
+alias compress2rs "b -l; rs -K 6 -l; rw -l; rs -K 6 -N 2 -l; rf -l; rs -K 8 -l; b -l; rs -K 8 -N 2 -l; rw -l; rs -K 10 -l; rwz -l; rs -K 10 -N 2 -l; b -l; rs -K 12 -l; rfz -l; rs -K 12 -N 2 -l; rwz -l; b -l"
+
+# use this script to convert 1-valued and DC-valued flops for an AIG
+alias fix_aig     "logic; undc; strash; zero"
+
+# use this script to convert 1-valued and DC-valued flops for a logic network coming from BLIF
+alias fix_blif    "undc; strash; zero"
+
+# lazy man's synthesis
+alias recadd3     "st; rec_add3; b; rec_add3; dc2; rec_add3; if -K 8; bidec; st; rec_add3; dc2; rec_add3; if -g -K 6; st; rec_add3"
+
+
diff --git a/abc-build/scripts/abc_common.py b/abc-build/scripts/abc_common.py
new file mode 100644
--- /dev/null
+++ b/abc-build/scripts/abc_common.py
@@ -0,0 +1,2007 @@
+from pyabc import *
+import pyabc_split
+import par
+import redirect
+import sys
+import os
+import time
+import math
+
+
+global G_C,G_T,latches_before_abs,latches_before_pba,n_pos_before,x_factor
+
+"""
+The functions that are currently available from module _abc are:
+
+int n_ands();
+int n_pis();
+int n_pos();
+int n_latches();
+int n_bmc_frames();
+int prob_status(); 1 = unsat, 0 = sat, -1 = unsolved
+
+int run_command(char* cmd);
+
+bool has_comb_model();
+bool has_seq_model();
+bool is_true_cex();
+bool is_valid_cex();
+  return 1 if the number of PIs in the current network and in the current counter-example are equal
+int  n_cex_pis();
+  return the number of PIs in the current counter-example
+int  n_cex_regs();
+  return the number of flops in the current counter-example
+int  cex_po();
+  returns the zero-based output PO number that is SAT by cex
+int  cex_frame();
+  return the zero-based frame number where the outputs is SAT
+The last four APIs return -1, if the counter-example is not defined. 
+"""
+
+#global variables
+
+stackno_gabs = stackno_gore = stackno_greg= 0
+STATUS_UNKNOWN = -1
+STATUS_SAT = 0
+STATUS_UNSAT = 1
+RESULT = ('SAT' , 'SAT', 'UNSAT', 'UNDECIDED', 'UNDECIDED,', 'UNDCIDED'  )
+Sat_reg = 0
+Sat_true = 1
+Unsat = 2
+Undecided_reduction = 3
+Undecided_no_reduction = 4
+Error = 5
+Restart = 6
+xfi = x_factor = 1  #set this to higher for larger problems or if you want to try harder during abstraction
+max_bmc = -1
+last_time = 0
+
+# Function definitions:
+# simple functions: ________________________________________________________________________
+# set_globals, abc, q, x, has_any_model, is_sat, is_unsat, push, pop
+
+# ALIASES
+def p():
+    return prove()
+
+def ps():
+    print_circuit_stats()
+
+def n_real_inputs():
+    """This gives the number of 'real' inputs. This is determined by trimming away inputs that
+    have no connection to the logic. This is done by the ABC alias 'trm', which changes the current
+    circuit. In some applications we do not want to change the circuit, but just to know how may inputs
+    would go away if we did this. So the current circuit is saved and then restored afterwards."""
+    abc('w %s_savetempreal.aig; logic; trim; st'%f_name)
+    n = n_pis()
+    abc('r %s_savetempreal.aig'%f_name)
+    return n
+
+def long(t):
+    if t<20:
+        t = t
+    else:
+        t = 20+(t-20)/3
+    return max(10,t)
+
+def rif():
+    """Not used"""
+    global f_name
+    print 'Type in the name of the aig file to be read in'
+    s = raw_input()
+    if s[-5:] == '.blif':
+        f_name = s[:-5]
+    else:
+        f_name = s
+        s = s+'.blif'
+    run_command(s)
+    x('st;constr -i')
+    print_circuit_stats()
+    a = n_ands()
+    f = max(1,30000/a)
+    f = min (f,16)
+    x('scorr -c -F %d'%f)
+    x('fold')
+    print_circuit_stats()
+    x('w %s_c.aig'%f_name)
+
+def abc(cmd):
+    abc_redirect_all(cmd)
+    
+
+def abc_redirect( cmd, dst = redirect.null_file, src = sys.stdout ):
+    """This is our main way of calling an ABC function. Redirect, means that we suppress any output from ABC"""
+    with redirect.redirect( dst, src ):
+        return run_command( cmd )
+
+
+def abc_redirect_all( cmd ):
+    """This is our main way of calling an ABC function. Redirect, means that we suppress any output from ABC, including error printouts"""
+    with redirect.redirect( redirect.null_file, sys.stdout ):
+        with redirect.redirect( redirect.null_file, sys.stderr ):
+            return run_command( cmd )
+
+def set_globals():
+    """This sets global parameters that are used to limit the resources used by all the operations
+    bmc, interpolation BDDs, abstract etc. There is a global factor 'x_factor' that can
+    control all of the various resource limiting parameters"""
+    global G_C,G_T,x_factor
+    nl=n_latches()
+    na=n_ands()
+    np = n_pis()
+    #G_C = min(500000,(3*na+500*(nl+np)))
+    G_C = x_factor * min(100000,(3*na+500*(nl+np)))
+    #G_T = min(250,G_C/2000)
+    G_T = x_factor * min(75,G_C/2000)
+    G_T = max(1,G_T)
+    #print('Global values: BMC conflicts = %d, Max time = %d sec.'%(G_C,G_T))
+    
+def a():
+    """this puts the system into direct abc input mode"""
+    print "Entering ABC direct-input mode. Type q to quit ABC-mode"
+    n = 0
+    while True:
+        print '     abc %d> '%n,
+        n = n+1
+        s = raw_input()
+        if s == "q":
+            break
+        run_command(s) 
+
+def set_fname(name):
+    """ Another way to set an f_name, but currently this is not used"""
+    global f_name
+    s = name
+    if s[-4:] == '.aig':
+        f_name = s[:-4]
+    else:
+        f_name = s
+        s = s+'.aig'
+    #read in file
+    run_command(s)
+    #print_circuit_stats()
+
+def read_file_quiet(fname=None):
+    """This is the main program used for reading in a new circuit. The global file name is stored (f_name)
+    Sometimes we want to know the initial starting name. The file name can have the .aig extension left off
+    and it will assume that the .aig extension is implied. This should not be used for .blif files.
+    Any time we want to process a new circuit, we should use this since otherwise we would not have the
+    correct f_name."""
+    global max_bmc,  f_name, d_name, initial_f_name, x_factor, init_initial_f_name
+    x_factor = 1
+    max_bmc = -1
+    
+    if fname is None:
+        print 'Type in the name of the aig file to be read in'
+        s = raw_input()
+    else:
+        s = fname
+        
+    if s[-4:] == '.aig':
+        f_name = s[:-4]
+    else:
+        f_name = s
+        s = s+'.aig'
+        
+    run_command(s)
+    initial_f_name = f_name
+    init_initial_f_name = f_name
+    
+def read_file():
+    read_file_quiet()
+    print_circuit_stats()
+
+def rf():
+    read_file()
+
+
+def write_file(s):
+    """this is the main method for writing the current circuit to an AIG file on disk.
+    It manages the name of the file, by giving an extension (s). The file name 'f_name'
+    keeps increasing as more extensions are written. A typical sequence is
+    name, name_smp, name_smp_abs, name_smp_abs_spec, name_smp_abs_spec_final"""
+    global f_name
+    """Writes out the current file as an aig file using f_name appended with argument"""
+    f_name = '%s_%s'%(f_name,s)
+    ss = '%s.aig'%(f_name)
+    print 'WRITING %s: '%ss,
+    print_circuit_stats()
+    abc('w '+ss)
+    
+def wf():
+    """Not used"""
+    print 'input type of file to be written'
+    s = raw_input()
+    write_file(s)
+
+def bmc_depth():
+    """ Finds the number of BMC frames that the latest operation has used. The operation could be BMC, reachability
+    interpolation, abstract, speculate. max_bmc is continually increased. It reflects the maximum depth of any version of the circuit
+    including g ones, for which it is known that there is not cex out to that depth."""
+    global max_bmc
+    b = n_bmc_frames()
+    max_bmc = max(b,max_bmc)
+    return max_bmc
+
+def set_max_bmc(b):
+    """ Keeps increasing max_bmc which is the maximum number of time frames for
+    which the current circuit is known to be UNSAT for"""
+    global max_bmc
+    max_bmc = max(b,max_bmc)
+
+def print_circuit_stats():
+    """Stardard way of outputting statistice about the current circuit"""
+    global max_bmc
+    i = n_pis()
+    o = n_pos()
+    l = n_latches()
+    a = n_ands()
+    b = max(max_bmc,bmc_depth())
+    c = cex_frame()
+    if b>= 0:
+        if c>=0:
+            print 'PIs = %d, POs = %d, FF = %d, ANDs = %d, max depth = %d, CEX depth = %d'%(i,o,l,a,b,c)
+        else:
+            print 'PIs = %d, POs = %d, FF = %d, ANDs = %d, max depth = %d'%(i,o,l,a,b)
+    else:
+        if c>=0:
+            print 'PIs = %d, POs = %d, FF = %d, ANDs = %d, CEX depth = %d'%(i,o,l,a,c)
+        else:
+            print 'PIs = %d, POs = %d, FF = %d, ANDs = %d'%(i,o,l,a)
+
+def q():
+    exit()
+
+def x(s):
+    """execute an ABC command"""
+    print "RUNNING: ", s
+    run_command(s)
+
+def has_any_model():
+    """ check if a satisfying assignment has been found"""
+    res = has_comb_model() or has_seq_model()
+    return res
+
+def is_unsat():
+    if prob_status() == 1:
+        return True
+    else:
+        return False
+
+def is_sat():
+    if prob_status() == 0:
+        return True
+    else:
+        return False
+
+def wc(file):
+    """writes <file> so that costraints are preserved explicitly"""
+    abc('&get;&w %s'%file)
+
+def rc(file):
+    """reads <file> so that if constraints are explicit, it will preserve them"""
+    abc('&r %s;&put'%file)                         
+
+
+
+def fast_int(n):
+    """This is used to eliminate easy-to-prove outputs. Arg n is conflict limit to be used
+    in the interpolation routine. Typically n = 1 or 10"""
+    n_po = n_pos()
+    abc('int -k -C %d'%n)
+    print 'Reduced POs from %d to %d'%(n_po,n_pos())
+
+def refine_with_cex():
+    """Refines the greg (which contains the original problem with the set of FF's that have been abstracted).
+    This generates a new abstraction (gabs) and modifies the greg file to reflect which regs are in the
+    current abstraction"""
+    global f_name
+    print 'CEX in frame %d for output %d'%(cex_frame(),cex_po())
+    abc('&r %s_greg.aig; &abs_refine; &w %s_greg.aig'%(f_name,f_name))
+    return
+
+def generate_abs(n):
+    """generates an abstracted  model (gabs) from the greg file. The gabs file is automatically
+    generated in the & space by &abs_derive. We store it away using the f_name of the problem
+    being solved at the moment. The f_name keeps changing with an extension given by the latest
+    operation done - e.g. smp, abs, spec, final, group. """
+    global f_name
+    #we have a cex and we use this generate a new gabs file
+    abc('&r %s_greg.aig; &abs_derive; &put; w %s_gabs.aig'%(f_name,f_name)) # do we still need the gabs file
+    if n == 1:
+        print 'New abstraction: ',
+        print_circuit_stats()
+    return   
+
+    
+#more complex functions: ________________________________________________________
+#, abstract, pba, speculate, final_verify, dprove3
+
+
+def simplify():
+    """Our standard simplification of logic routine. What it does depende on the problem size.
+    For large problems, we use the &methods which use a simple circuit based SAT solver. Also problem
+    size dictates the level of k-step induction done in 'scorr' The stongest simplification is done if
+    n_ands < 20000. Then it used the clause based solver and k-step induction where |k| depends
+    on the problem size """
+    # set_globals()
+##    print 'simplify initial ',
+##    ps()
+    #abc('w t.aig')
+    n=n_ands()
+    abc('scl')
+    if n > 40000:
+        abc('&get;&scl;&put')
+        n = n_ands()
+        if n < 100000:
+            abc("&dc2;&put;dr;&get;&lcorr;&dc2;&put;dr;&get;&scorr;&fraig;&dc2;&put;dr")
+            run_command('ps')
+            print '.',
+            n = n_ands()
+            if n<60000:
+                abc("&get;&scorr -F 2;&put;dc2rs")
+                print '.',
+                #ps()
+            else:
+                abc("dc2rs")
+                print '.',
+                #ps()
+            n = n_ands()
+    n = n_ands()
+    if n <= 40000:
+        print '.',
+        #ps()
+        if n > 30000:
+            abc("dc2rs")
+            print '.',
+##        else:
+##            abc("scorr -F 2;dc2rs")
+##            print '.',
+##            ps()
+    n = max(1,n_ands())
+    #ps()
+    if n < 30000:
+        abc('scl;rw;dr;lcorr;rw;dr')
+        m = int(min( 60000/n, 16))
+        #print 'm = %d'%m
+        if m >= 1:
+            j = 1
+            while j <= m:
+                set_size()
+                #print 'j - %d'%j
+                #abc('scl;dr;dc2;scorr -C 5000 -F %d'%j)
+                if j<8:
+                    abc('dc2')
+                else:
+                    abc('dc2rs')
+                abc('scorr -C 5000 -F %d'%j)
+                if check_size():
+                    break
+                j = 2*j
+                #ps()
+                continue
+            print '.',
+
+
+def iterate_simulation(latches_before):
+    """Subroutine of 'abstract' which does the refinement of the abstracted model,
+    using counterexamples found by simulation. Simulation is controlled by the amount
+    of memory it might use. At first wide but shallow simulation is done, bollowed by
+    successively more narrow but deeper simulation"""
+    global x_factor, f_name
+##    print 'RUNNING simulation iteratively'
+    f = 5
+    w = 255
+    for k in range(9):
+        f = min(f *2, 3500)
+        w = max(((w+1)/2)-1,1)
+        print '.',
+        abc('sim -m -F %d -W %d'%(f,w))
+        if not is_sat():
+            continue
+        while True:
+            refine_with_cex()
+            if is_sat():
+                print 'cex failed to refine abstraction '
+                return Sat_true
+            generate_abs(0)
+            latches_after = n_latches()
+            print 'Latches increased to %d'%latches_after
+            if latches_after >= .99*latches_before:
+                abc('r %s_savetempabs.aig'%f_name)
+                print "No reduction!."
+                return Undecided_no_reduction
+            abc('sim -m -F %d -W %d'%(f,w))
+            if not is_sat():
+                break
+
+def simulate():
+    """Simulation is controlled by the amount
+    of memory it might use. At first wide but shallow simulation is done, bollowed by
+    successively more narrow but deeper simulation"""
+    global x_factor, f_name
+##    print 'RUNNING simulation iteratively'
+    f = 5
+    w = 255
+    for k in range(9):
+        f = min(f *2, 3500)
+        w = max(((w+1)/2)-1,1)
+        print '.',
+        abc('sim -m -F %d -W %d'%(f,w))
+        if is_sat():
+            print 'cex found in frame %d'%cex_frame()
+            return 'SAT'
+    return 'UNDECIDED'
+        
+
+def iterate_abstraction_refinement(latches_before,NBF):
+    """Subroutine of 'abstract' which does the refinement of the abstracted model,
+    using counterexamples found by BMC or BDD reachability"""
+    global x_factor, f_name
+    if NBF == -1:
+        F = 2000
+    else:
+        F = 2*NBF
+    print '\nIterating BMC/PDR'
+    always_reach = 0
+    cexf = 0
+    reach_failed = 0
+    while True:
+        #print 'Generating problem abstraction'
+        generate_abs(1)
+        set_globals()
+        latches_after = n_latches()
+        if latches_after >= .98*latches_before:
+##            print 'No reduction'
+##            abc('r &s_savetemp.aig'%f_name)
+            break
+        ri = n_real_inputs() # No. of inputs after trm
+        nlri = n_latches()+ri
+        #reach_allowed = ((nlri<150) or (((cexf>250))&(nlri<300)))
+        reach_allowed = ((nlri<75) or (((cexf>250))&(nlri<300)))
+        pdr_allowed  = True
+        bmc = False
+        t = max(1,G_T)
+        if not F == -1:
+            F = int(1.5*max_bmc)
+        if (((reach_allowed  or pdr_allowed ) and not reach_failed)):
+            #cmd = 'reach -B 200000 -F 3500 -T %f'%t
+            #cmd = 'reachx -e %d -t %d'%(int(long(t)),max(10,int(t)))
+            #cmd = 'reachx -t %d'%max(10,int(t))
+            cmd = '&get;,pdr -vt=%f'%t
+        else:
+            #cmd = 'bmc3 -C %d -T %f -F %d'%(G_C,t,F)
+            bmc = True
+            cmd = '&get;,bmc -vt=%f'%(t)
+            #cmd = '&get;,pdr -vt=%f'%(t)
+        print '\n***RUNNING %s'%cmd
+        #run_command(cmd)
+        last_bmc = max_bmc
+        abc(cmd)
+        if prob_status() == 1:
+            #print 'Depth reached %d frames, '%n_bmc_frames()
+            print 'UNSAT'
+            return Unsat
+        cexf = cex_frame()
+        #print 'cex depth = %d'%cexf
+        #set_max_bmc(cexf -1)
+        if ((not is_sat()) ):
+            reach_failed = 1 # if ever reach failed, then we should not try it again on more refined models
+        if is_sat():
+            #print 'CEX in frame %d for output %d'%(cex_frame(),cex_po())
+            #set_max_bmc(cexf-1)
+            refine_with_cex() # if cex can't refine, status is set to Sat_true
+            if is_sat():
+                print 'cex did not refine. Implies true_sat'
+                return Sat_true
+        else:
+            print "No CEX found in %d frames"%n_bmc_frames()
+            set_max_bmc(n_bmc_frames())
+            if bmc:
+                break
+            elif max_bmc> 1.2*last_bmc: # if pdr increased significantly over abs, the assume OK
+                break
+            else:
+                continue
+    latches_after = n_latches()
+    if latches_after >= .98*latches_before:
+        abc('r %s_savetempabs.aig'%f_name)
+        print "No reduction!"
+        return Undecided_no_reduction
+    else:
+        print 'Latches reduced from %d to %d'%(latches_before, n_latches())
+        return Undecided_reduction
+
+
+def abstract():
+    """ abstracts using N Een's method 3 - cex/proof based abstraction. The result is further refined using
+    simulation, BMC or BDD reachability"""
+    global G_C, G_T, latches_before_abs, x_factor
+    set_globals()
+    latches_before_abs = n_latches()
+    abc('w %s_savetempabs.aig'%f_name)
+    print 'Start: ',
+    print_circuit_stats()
+    c = 1.5*G_C
+    #t = max(1,1.25*G_T)
+    t = 2*max(1,1.25*G_T)
+    s = min(max(3,c/30000),10) # stability between 3 and 10
+    time = max(1,.01*G_T)
+    abc('&get;,bmc -vt=%f'%time)
+    print 'BMC went %d frames'%n_bmc_frames()
+    set_max_bmc(bmc_depth())
+    f = max(2*max_bmc,20)
+    b = min(max(10,max_bmc),200)
+    cmd = '&get;,abs -bob=%d -stable=%d -timeout=%f -vt=%f -depth=%d'%(b,s,t,t,f)
+    print '     Running %s'%cmd
+    run_command(cmd)
+    if is_sat():
+        print 'Found true counterexample in frame %d'%cex_frame()
+        return Sat_true
+    NBF = bmc_depth()
+    print 'Abstraction good to %d frames'%n_bmc_frames()
+    set_max_bmc(NBF)
+    abc('&w %s_greg.aig; &abs_derive; &put; w %s_gabs.aig'%(f_name,f_name))
+##    print 'First abstraction: ',
+##    print_circuit_stats()
+    latches_after = n_latches()
+    #if latches_before_abs == latches_after:
+    if latches_after >= .98*latches_before_abs:
+        abc('r %s_savetempabs.aig'%f_name)
+        print "No reduction!"
+        return Undecided_no_reduction    
+    # refinement loop
+    if (n_ands() + n_latches() + n_pis()) < 15000:
+        print '\n***Running simulation iteratively'
+        for i in range(5):
+            result = iterate_simulation(latches_before_abs)
+            if result == Restart:
+                return result
+            if result == Sat_true:
+                return result
+    result = iterate_abstraction_refinement(latches_before_abs, NBF)
+    #if the result is 'Restart' we return and the calling routine increase
+    #x_factor to try one more time.
+    return result
+
+def absv(n,v):
+    """This is a version of 'abstract' which can control the methods used in Een's abstraction code (method = n)
+    as well as whether we want to view the output of this (v = 1)"""
+    global G_C, G_T, latches_before_abs, x_factor
+    #input_x_factor()
+    #x_factor = 3
+    set_globals()
+    latches_before_abs = n_latches()
+    print 'Start: ',
+    print_circuit_stats()
+    c = 1.5*G_C
+    t = max(1,1.25*G_T)
+    s = min(max(3,c/30000),10) # stability between 3 and 10
+    if max_bmc == -1:
+        time = max(1,.01*G_T)
+        #abc('bmc3 -C %d -T %f -F 165'%(.01*G_C, time))
+        abc('&get;,bmc -vt=%f'%time)
+        set_max_bmc(bmc_depth())
+    f = min(250,1.5*max_bmc)
+    f = max(20, f)
+    f = 10*f
+    b = x_factor*20
+    if not n == 0:
+        b = 10
+        b = max(b,max_bmc+2)
+        b = b*2**(x_factor-1)
+        b = 2*b
+    print 'Neen abstraction params: Method #%d, %d conflicts, %d stable, %f sec.'%(n,c/3,s,t)
+    if v == 1:
+        run_command('&get; &abs_newstart -v -B %f -A %d -C %d -S %d -V %f'%(b,n,c/3,s,t))
+    else:
+        abc('&get; &abs_newstart -v -B %f -A %d -C %d -S %d -T %f'%(b,n,c/3,s,t))
+    set_max_bmc(n_bmc_frames())
+    print 'Abstraction good to %d'%n_bmc_frames()
+    abc('&w %s_greg.aig; &abs_derive; &put; w %s_gabs.aig'%(f_name,f_name))
+    print 'Final abstraction: ',
+    print_circuit_stats()
+    latches_after = n_latches()    
+    if latches_after >= .98*latches_before_abs:
+        print "No reduction!"
+        return Undecided_no_reduction
+    return Undecided_reduction
+
+def spec():
+    """Main speculative reduction routine. Finds candidate sequential equivalences and refines them by simulation, BMC, or reachability
+    using any cex found. """
+    input_x_factor()
+    global G_C,G_T,n_pos_before, x_factor, n_latches_before
+    set_globals()
+    n_pos_before = n_pos()
+    n_latches_before = n_latches()    
+    set_globals()
+    t = max(1,.5*G_T)
+    r = max(1,int(t))
+    print '\n***Running &equiv2 with C = %d, T = %f sec., F = %d -S 1 -R %d'%(G_C,t,200,r)
+    abc("&get; &equiv2 -C %d -F 200 -T %f -S 1 -R %d; &semi -F 50; &speci -F 20 -C 1000;&srm; r gsrm.aig; w %s_gsrm.aig; &w %s_gore.aig"%((G_C),t,r,f_name,f_name))
+    print 'Initial speculation: ',
+    print_circuit_stats()
+    print 'Speculation good to %d frames'%n_bmc_frames()
+    return
+
+def speculate():
+    """Main speculative reduction routine. Finds candidate sequential equivalences and refines them by simulation, BMC, or reachability
+    using any cex found. """
+    
+    global G_C,G_T,n_pos_before, x_factor, n_latches_before
+    set_globals()
+    n_pos_before = n_pos()
+    
+    def refine_with_cex():
+        """Refines the gore file to reflect equivalences that go away because of cex"""
+        global f_name
+        print 'CEX in frame %d for output %d'%(cex_frame(),cex_po())
+        abc('&r %s_gore.aig; &resim -m; &w %s_gore.aig'%(f_name,f_name))
+        #abc('&r %s_gore.aig; &equiv2 -vx ; &w %s_gore.aig'%(f_name,f_name))
+        return
+    
+    def generate_srm(n):
+        """generates a speculated reduced model (srm) from the gore file"""
+        global f_name
+        pos = n_pos()
+        ab = n_ands()
+        abc('&r %s_gore.aig; &srm ; r gsrm.aig; w %s_gsrm.aig'%(f_name,f_name)) #do we still need to write the gsrm file
+        if n == 0:
+            if ((pos == n_pos()) and (ab == n_ands())):
+                print 'Failed to refine'
+                return 'failed'
+        if n == 1:
+            print 'Spec. Red. Miter: ',
+            print_circuit_stats()
+        return 'OK'
+
+    def run_simulation(n):
+        f = 5
+        w = (256/n)-1
+        for k in range(9):
+            f = min(f * 2, 3500)
+            w = max(((w+1)/2)-1,1)
+            print '.',
+            #generate_srm(0)
+            abc('sim -m -F %d -W %d'%(f,w))
+            if not is_sat():
+                continue                
+            if cex_po() < n_pos_before:
+                print 'Sim found true cex: Output = %d, Frame = %d'%(cex_po(),cex_frame())
+                return Sat_true                    
+            refine_with_cex()
+            if n_pos_before == n_pos():            
+                return Undecided_no_reduction
+            while True:
+                result = generate_srm(0)
+                if result == 'failed':
+                    return Sat_true
+                abc('sim -m -F %d -W %d'%(f,w))
+                if not is_sat():
+                    break                
+                if cex_po() < n_pos_before:
+                    print 'Sim found true cex: Output = %d, Frame = %d'%(cex_po(),cex_frame())
+                    return Sat_true                    
+                refine_with_cex()
+                if n_pos_before == n_pos():            
+                    return Undecided_no_reduction
+        return Undecided_no_reduction
+    
+    n_pos_before = n_pos()
+    n_latches_before = n_latches()    
+    set_globals()
+    t = max(1,.5*G_T)
+    r = max(1,int(t))
+    abc('write spec_temp.aig')
+    print '\n***Running &equiv2 with C = %d, T = %f sec., F = %d -S 1 -R %d'%(G_C,t,200,r)
+##    abc("&get; &equiv2 -C %d -F 200 -T %f -S 1 -R %d; &semi -F 50; &speci -F 20 -C 1000;&srm; r gsrm.aig; w %s_gsrm.aig; &w %s_gore.aig"%((G_C),t,r,f_name,f_name))
+    abc("&get; &equiv2 -C %d -F 200 -T %f -S 1 -R %d; &semi -W 63 -S 5 -C 500 -F 500; &speci -F 200 -C 5000;&srm; r gsrm.aig; w %s_gsrm.aig; &w %s_gore.aig"%((G_C),t,r,f_name,f_name))
+    print 'Initial speculation: ',
+    print_circuit_stats()
+    #print 'Speculation good to %d frames'%n_bmc_frames()
+    #simplify()
+    if n_pos_before == n_pos():
+        print 'No new outputs. Quitting speculate'
+        return Undecided_no_reduction # return result is unknown
+    if is_sat():
+        #print '\nWARNING: if an abstraction was done, need to refine it further\n'
+        return Sat_true
+    if n_latches() > .98*n_latches_before:
+        pre_simp()
+        if n_latches() > .98*n_latches_before:
+            print 'Quitting speculation - not enough gain'
+            abc('r spec_temp.aig')
+            return Undecided_no_reduction # not worth it
+    k = n_ands() + n_latches() + n_pis()
+    n = 0
+    if k < 15000:
+        n = 1
+    elif k < 30000:
+        n = 2
+    elif k < 60000:
+        n = 4
+    elif k < 120000:
+        n = 8
+    if n > 0: # simulation can run out of memory for too large designs, so be careful
+        print '\n***RUNNING simulation iteratively'          
+        for i in range(5):
+            result = run_simulation(n)
+            if result == Sat_true:
+                return result
+    simp_sw = 1
+    int_sw = 1
+    reach_sw = 0
+    cexf = 0
+    reach_failed = 0
+    init = 1
+    run_command('write temptemp.aig')
+    print '\nIterating BMC or BDD reachability'
+    while True: # now try real hard to get the last cex.
+        set_globals()
+        if not init:
+            set_size()
+            result = generate_srm(1)
+            if check_size() == True:
+                print 'Failed to refine'
+                return Error
+            if result == 'failed':
+                return Sat_true
+            if simp_sw == 1:
+                na = n_ands()
+                simplify()
+                if n_ands() > .7*na: #if not significant reduction, stop simplification
+                    simp_sw = 0
+            if n_latches() == 0:
+                return check_sat()
+        init = 0 # make it so that next time it is not the first time through
+        time = max(1,G_T/(5*n_pos()))
+        if int_sw ==1:
+            npo = n_pos()
+            if n_pos() > .5*npo:  # if not sufficient reduction, turn this off
+                int_sw = 0
+        if is_sat():        #if fast interpolation found a cex
+            cexf = cex_frame()
+            set_max_bmc(cexf - 1)
+            if cex_po() < n_pos_before:
+                print 'Int found true cex: Output = %d, Frame = %d'%(cex_po(),cex_frame())
+                return Sat_true
+            refine_with_cex()
+            if ((n_pos_before == n_pos()) or (n_latches_before == n_latches())):            
+                abc('r temp_spec.aig')
+                return Undecided_no_reduction
+            if is_sat():
+                print '1. cex failed to refine abstraction'
+                return Sat_true
+            continue
+        else:
+            if n_latches() == 0:
+                return check_sat()
+            ri = n_real_inputs()  #seeing how many inputs would trm get rid of
+            nlri = n_latches() + ri
+            reach_allowed = ((nlri<75) or (((cexf>250)) and (nlri<300)))
+            pdr_allowed = True
+            bmc = False
+            if (((reach_allowed  or pdr_allowed ) and not reach_failed)):
+                t = max(1,1.2*G_T)
+                f = max(3500, 2*max_bmc)
+                #cmd = 'reachx -t %d'%max(10,int(t))
+                cmd ='&get;,pdr -vt=%f'%t
+            else:
+                t = max(1,1.5*G_T)
+                if max_bmc == -1:
+                    f = 200
+                else:
+                    f = max_bmc
+                f = int(1.5*f)
+                #cmd = 'bmc3 -C %d -T %f -F %f'%(1.5*G_C,1.2*t,f)
+                bmc = True
+                cmd = '&get;,bmc -vt=%f'%(1.2*t)
+            print '\n***Running %s'%cmd
+            last_bmc = max_bmc
+            abc(cmd)
+            #run_command(cmd)
+            if is_sat():
+                cexf = cex_frame()
+                #set_max_bmc(cexf  - 1)
+                #This is a temporary fix since reachx always reports cex_ps = 0
+                if ((cex_po() < n_pos_before) and (cmd[:4] == '&get')):
+                    print 'BMC/PDR found true cex: Output = %d, Frame = %d'%(cex_po(),cex_frame())
+                    return Sat_true
+                #End of temporary fix
+                refine_with_cex()#change the number of equivalences
+                if n_pos_before == n_pos():            
+                    return Undecided_no_reduction
+                continue
+            else:
+                set_max_bmc(n_bmc_frames())
+                if prob_status() == 1:
+                        #print 'Convergence reached in %d frames'%n_bmc_frames()
+                        return Unsat
+                print 'No cex found in %d frames'%n_bmc_frames()
+                if bmc:
+                    break
+                elif max_bmc > 1.2*last_bmc:
+                    break
+                else:
+                    reach_failed = 1
+                    init = 1
+                    continue
+    if n_pos_before == n_pos():
+        return Undecided_no_reduction 
+    else:
+        return Undecided_reduction
+
+def set_size():
+    """Stores  the problem size of the current design. Size is defined as (PIs, POs, ANDS, FF, max_bmc)""" 
+    global npi, npo, nands, nff, nmd
+    npi = n_pis()
+    npo = n_pos()
+    nands = n_ands()
+    nff = n_latches()
+    nmd = max_bmc
+
+def check_size():
+    """Assumes the problem size has been set by set_size before some operation. This checks if the size was changed
+    Size is defined as (PIs, POs, ANDS, FF, max_bmc)
+    Returns TRUE is size is the same""" 
+    global npi, npo, nands, nff, nmd
+    result = ((npi == n_pis()) and (npo == n_pos()) and (nands == n_ands()) and (nff == n_latches()) and (nmd == max_bmc))
+##    if result == 1:
+##        print 'Size unchanged'
+    return result
+
+def inferior_size():
+    """Assumes the problem size has been set by set_size beore some operation.
+    This checks if the new size is inferior (larger) to the old one 
+    Size is defined as (PIs, POs, ANDS, FF)""" 
+    global npi, npo, nands, nff
+    result = ((npi < n_pis()) or (npo < n_pos()) or (nands < n_ands()) )
+    return result
+
+def quick_verify(n):
+    """Low resource version of final_verify n = 1 means to do an initial simplification first"""
+    abc('trm')
+    if n == 1:
+        simplify()
+        if n_latches == 0:
+            return check_sat()
+        abc('trm')
+        if is_sat():
+            return Sat_true
+    print 'After trimming: ',
+    print_circuit_stats()
+    #try_rpm()
+    set_globals()
+    t = max(1,.4*G_T)
+    print '    Running PDR for %d sec '%(t)
+    abc('&get;,pdr -vt=%f'%(t*.8))
+    status = get_status()
+    if not status == Unsat:
+        print 'PDR went to %d frames, '%n_bmc_frames(),
+    print RESULT[status]
+    return status #temporary
+    if status <= Unsat:
+        return status
+    N = bmc_depth()
+    c = max(G_C/10, 1000)
+    t = max(1,.4*G_T)
+    print '    RUNNING interpolation with %d conflicts, max %d sec and 100 frames'%(c,t)
+    #abc('int -v -F 100 -C %d -T %f'%(c,t))
+    abc(',imc -vt=%f '%t)
+    status = get_status()
+    if status <= Unsat:
+        print 'Interpolation went to %d frames, '%n_bmc_frames(),
+        print RESULT[status]
+        return status
+    L = n_latches()
+    I = n_real_inputs()
+    if ( ((I+L<200)&(N>100))  or  (I+L<125)  or  L < 51 ): #heuristic that if bmc went deep, then reachability might also
+        t = max(1,.4*G_T)
+        cmd = 'reachx -t %d'%max(10,int(t))
+        print '    Running %s'%cmd
+        abc(cmd)        
+        status = get_status()
+        if status <= Unsat:
+            print 'Reachability went to %d frames, '%n_bmc_frames()
+            print RESULT[status]
+            return status
+        print 'BDD reachability aborted'
+    simplify() #why is this here
+    if n_latches() == 0:
+        print 'Simplified to 0 FF'
+        return check_sat()
+    set_max_bmc(bmc_depth()) # doesn't do anything
+    print 'No success, max_depth = %d'%max_bmc
+    return Undecided_reduction
+
+def get_status():
+    """this simply translates the problem status encoding done by ABC (-1,0,1)=(undecided,SAT,UNSAT) into the status code used by our python code."""
+    status = prob_status() #interrogates ABC for the current status of the problem.
+    # 0 = SAT
+    if status == 1:
+        status = Unsat
+    if status == -1: #undecided
+        status = Undecided_no_reduction
+    return status
+
+def try_rpm():
+    """rpm is a cheap way of doing reparameterization and is an abstraction method, so may introduce false cex's.
+    It finds a minimum cut between the PIs and the main sequential logic and replaces this cut by free inputs.
+    A quick BMC is then done, and if no cex is found, we assume the abstraction is valid. Otherwise we revert back
+    to the original problem before rpm was tried."""
+    global x_factor
+    if n_ands() > 30000:
+        return
+    set_globals()
+    pis_before = n_pis()
+    abc('w %s_savetemp.aig'%f_name)
+    abc('rpm')
+    result = 0
+    if n_pis() < .5*pis_before:
+        bmc_before = bmc_depth()
+        #print 'running quick bmc to see if rpm is OK'
+        t = max(1,.1*G_T)
+        #abc('bmc3 -C %d, -T %f'%(.1*G_C, t))
+        abc('&get;,bmc -vt=%f'%t)
+        if is_sat(): #rpm made it sat by bmc test, so undo rpm
+            abc('r %s_savetemp.aig'%f_name)
+        else:
+            abc('trm')
+            print 'WARNING: rpm reduced PIs to %d. May make SAT.'%n_pis()
+            result = 1
+    else:
+        abc('r %s_savetemp.aig'%f_name)
+    return result
+            
+def final_verify():
+    """This is the final method for verifying anything is nothing else has worked. It first tries BDD reachability
+    if the problem is small enough. If this aborts or if the problem is too large, then interpolation is called."""
+    global x_factor
+    set_globals()
+##    simplify()
+##    if n_latches() == 0:
+##        return check_sat()
+##    abc('trm')
+    #rpm_result = try_rpm()
+    set_globals()
+    N = bmc_depth()
+    L = n_latches()
+    I = n_real_inputs()
+    #try_induction(G_C)
+    c = max(G_C/5, 1000)
+    t = max(1,G_T)
+    print '\n***Running PDR for %d sec'%(t)
+    abc('&get;,pdr -vt=%f'%(t*.8))
+    status = get_status()
+    if status <= Unsat:
+        print 'PDR went to %d frames, '%n_bmc_frames(),
+        print RESULT[status]
+        return status
+    if ( ((I+L<250)&(N>100))  or  (I+L<200) or (L<51) ): #heuristic that if bmc went deep, then reachability might also
+        t = max(1,1.5*G_T)
+        #cmd = 'reach -v -B 1000000 -F 10000 -T %f'%t
+        #cmd = 'reachx -e %d'%int(long(t))
+        #cmd = 'reachx -e %d -t %d'%(int(long(t)),max(10,int(t)))
+        cmd = 'reachx -t %d'%max(10,int(t))
+        print '\n***Running %s'%cmd
+        abc(cmd)        
+        status = get_status()
+        if status <= Unsat:
+            print 'Reachability went to %d frames, '%n_bmc_frames(),
+            print RESULT[status]
+            return status
+        print 'BDD reachability aborted'          
+    return status #temporary
+    #f = max(100, bmc_depth())
+    print '\n***RUNNING interpolation with %d conflicts, %d sec, max 100 frames'%(c,t)
+    #abc('int -v -F 100 -C %d -T %f'%(c,t))
+    abc(',imc -vt=%f '%t)
+    status = get_status()
+    if status <= Unsat:
+        print 'Interpolation went to %d frames, '%n_bmc_frames(),
+        print RESULT[status]
+        return status
+    t = max(1,G_T)
+    simplify()
+    if n_latches() == 0:
+        return check_sat()
+    print 'Undecided'
+    return Undecided_reduction
+
+def check_sat():
+    """This is called if all the FF have disappeared, but there is still some logic left. In this case,
+    the remaining logic may be UNSAT, which is usually the case, but this has to be proved. The ABC command 'dsat' is used fro combinational problems"""
+##    if n_ands() == 0:
+##        return Unsat
+    abc('orpos;dsat -C %d'%G_C)
+    if is_sat():
+        return Sat_true
+    elif is_unsat():
+        return Unsat
+    else:
+        return Undecided_no_reduction
+
+def try_era(s):
+    """era is explicit state enumeration that ABC has. It only works if the number of PIs is small,
+    but there are cases where it works and nothing else does"""
+    if n_pis() > 12:
+        return
+    cmd = '&get;&era -mv -S %d;&put'%s
+    print 'Running %s'%cmd
+    run_command(cmd)
+
+def try_induction(C):
+    """Sometimes proving the property directly using induction works but not very often.
+    For 'ind' to work, it must have only 1 output, so all outputs are or'ed together temporarily"""
+    return Undecided_reduction
+    print '\n***Running induction'
+    abc('w %s_temp.aig'%f_name)
+    abc('orpos; ind -uv -C %d -F 10'%C)
+    abc('r %s_savetemp.aig'%f_name)
+    status = prob_status()
+    if not status == 1:
+        return Undecided_reduction
+    print 'Induction succeeded'
+    return Unsat
+
+def final_verify_recur(K):
+    """During prove we make backups as we go. These backups have increasing abstractions done, which can cause
+    non-verification by allowing false counterexamples. If an abstraction fails with a cex, we can back up to
+    the previous design before the last abstraction and try to proceed from there. K is the backup number we
+    start with and this decreases as the backups fails. For each backup, we just try final_verify.
+    If ever we back up to 0, which is the backup just after simplify, we then try speculate on this. This often works
+    well if the problem is a SEC problem where there are a lot of equivalences across the two designs."""
+    for j in range(K):
+        i = K-(j+1)
+        if i == 0: #don't try final verify on original
+            status = 3
+            break
+        print '\nVerifying backup number %d:'%i,
+        abc('r %s_backup_%d.aig'%(initial_f_name,i))
+        print_circuit_stats()
+        status = final_verify()
+        if status >= Unsat:
+            return status
+        if  i > 0:
+            print 'SAT returned, Running less abstract backup'
+            continue
+        break
+    if ((i == 0) and (status > Unsat) and (n_ands() > 0)):
+        print '\n***Running speculate on initial backup number %d:'%i,
+        abc('r %s_backup_%d.aig'%(initial_f_name,i))
+        ps()
+        if n_ands() < 20000:
+            status = speculate()
+            if ((status <= Unsat) or (status == Error)):
+                return status
+        status = final_verify()
+    if status == Unsat:
+        return status
+    else:
+        return Undecided_reduction
+        
+
+def smp():
+    pre_simp()
+    write_file('smp')
+
+def pre_simp():
+    """This uses a set of simplification algorithms which preprocesses a design.
+    Includes forward retiming, quick simp, signal correspondence with constraints, trimming away
+    PIs, and strong simplify"""
+##    print "Trying BMC for 2 sec."
+##    abc("&get; ,bmc -vt=2")
+##    if is_sat():
+##        return Sat_true
+    set_globals()
+    if n_latches == 0:
+        return check_sat()
+    #print '\n*** Running forward'
+    try_forward()
+    #print \n*** Running quick simp'
+    quick_simp()
+    #print 'Running_scorr_constr'
+    status = try_scorr_constr()
+    #status = 3
+    #print 'Running trm'
+    if ((n_ands() > 0) or (n_latches()>0)):
+        abc('trm')
+    print 'Forward, quick_simp, scorr_constr,: ',
+    print_circuit_stats()
+    if n_latches() == 0:
+        return check_sat()
+    status = process_status(status)
+    if status <= Unsat:
+        return status
+    simplify()
+    print 'Simplify: ',
+    print_circuit_stats()
+    #abc('w temp_simp.aig')
+    if n_latches() == 0:
+        return check_sat()
+    try_phase()
+    if n_latches() == 0:
+        return check_sat()
+    #abc('trm')
+    if ((n_ands() > 0) or (n_latches()>0)):
+        abc('trm')
+    status = process_status(status)
+    if status <= Unsat:
+        return status
+    status = try_scorr_constr()
+    abc('trm')
+    return process_status(status)
+
+def try_scorr_constr():
+    set_size()
+    abc('w %s_savetemp.aig'%f_name)
+    status = scorr_constr()
+    if inferior_size():
+        abc('r %s_savetemp.aig'%f_name)
+    return status
+
+def process(status):
+    """Checks if there are no FF and if so checks if the remaining combinational
+    problem is UNSAT"""
+    if n_latches() == 0:
+        return check_sat()
+    return status
+
+def try_phase():
+    """Tries phase abstraction. ABC returns the maximum clock phase it found using n_phases.
+    Then unnrolling is tried up to that phase and the unrolled model is quickly
+    simplified (with retiming to see if there is a significant reduction.
+    If not, then revert back to original""" 
+    n = n_phases()
+    if ((n == 1) or (n_ands() > 40000)):
+        return
+    print 'Number of possible phases = %d'%n
+    abc('w %s_savetemp.aig'%f_name)
+    na = n_ands()
+    nl = n_latches()
+    ni = n_pis()
+    no = n_pos()
+    cost_init = (1*n_pis())+(2*n_latches())+1*n_ands()
+    cost_min = cost_init
+    cost = cost_init
+    abc('w %s_best.aig'%f_name)
+    for j in range(4):
+        abc('r %s_savetemp.aig'%f_name)
+        p = 2**(j+1)
+        if p > n:
+            break
+        abc('phase -F %d'%p)
+        if na == n_ands():
+            break
+        abc('scl;rw')
+        if n_latches() > nl: #why would this ever happen
+            break
+        #print_circuit_stats()
+        abc('rw;lcorr;trm')
+        #print_circuit_stats()
+        cost = (1*n_pis())+(2*n_latches())+1*n_ands()
+        if cost < cost_min:
+            cost_min = cost
+            abc('w %s_best.aig'%f_name)
+        else:
+            break
+    if cost < cost_init:
+        abc('r %s_best.aig'%f_name)
+        simplify()
+        abc('trm')
+        print 'Phase abstraction obtained :',
+        print_circuit_stats()
+        return
+    abc('r %s_savetemp.aig'%f_name)
+    return       
+
+def try_forward():
+    """Attempts most forward retiming, and latch correspondence there. If attempt fails to help simplify, then we revert back to the original design
+    This can be effective for equivalence checking problems where synthesis used retiming"""
+    abc('w %s_savetemp.aig'%f_name)
+    if n_ands() < 30000:
+        abc('dr')
+        abc('lcorr')
+        nl = n_latches()
+        na = n_ands()
+        abc('w %s_savetemp0.aig'%f_name)
+        abc('r %s_savetemp.aig'%f_name) 
+        abc('dr -m')
+        abc('lcorr')
+        abc('dr')
+        if ((n_latches() <= nl) and (n_ands() < na)):
+            print 'Forward retiming reduced size to: ',
+            print_circuit_stats()
+            return
+        else:
+            abc('r %s_savetemp0.aig'%f_name)
+            return
+    return       
+
+def quick_simp():
+    """A few quick ways to simplify a problem before more expensive methods are applied.
+    Uses & commands if problem is large. These commands use the new circuit based SAT solver"""
+    na = n_ands()
+    if na < 30000:
+        abc('scl;rw')
+    elif na < 80000:
+        abc('&get;&scl;&put;rw')
+
+def scorr_constr():
+    """Extracts implicit constraints and uses them in signal correspondence
+    Constraints that are found are folded back when done"""
+    na = max(1,n_ands())
+    if ((na > 40000) or n_pos()>1):
+        return Undecided_no_reduction
+    f = 40000/na
+    f = min(f,16)
+    n_pos_before = n_pos()
+    f = 1 #temporary until bug fixed.
+    abc('w %s_savetemp.aig'%f_name)
+    if n_ands() < 3000:
+        cmd = 'unfold -a -F 2'
+    else:
+        cmd = 'unfold'
+    abc(cmd)
+    if ((n_ands() > na) or (n_pos() == n_pos_before)):
+        abc('r %s_savetemp.aig'%f_name)
+        return Undecided_no_reduction
+    print_circuit_stats()
+    print 'Number of constraints = %d'%(n_pos() - n_pos_before)
+    abc('scorr -c -F %d'%f)
+    abc('fold')
+    return Undecided_no_reduction
+
+def process_status(status):
+    """ if there are no FF, the problem is combinational and we still have to check if UNSAT"""
+    if n_latches() == 0:
+        return check_sat()
+    return status
+
+def input_x_factor():
+    """Sets the global x_factor according to user input"""
+    global x_factor, xfi
+    print 'Type in x_factor:',
+    xfi = x_factor = input()
+    print 'x_factor set to %f'%x_factor
+
+def prove(a):
+    """Proves all the outputs together. If ever an abstraction was done then if SAT is returned,
+        we make RESULT return "undecided".
+        If a == 1 do not run speculate"""
+    global x_factor,xfi,f_name
+    x = time.clock()
+    max_bmc = -1
+    K = 0
+    print 'Initial: ',
+    print_circuit_stats()
+    x_factor = xfi
+    print 'x_factor = %f'%x_factor
+    print '\n***Running pre_simp'
+    set_globals()
+    if n_latches() > 0:
+        status = pre_simp()
+    else:
+        status = check_sat()
+    if ((status <= Unsat) or (n_latches() == 0)):
+        print 'Time for proof = %f sec.'%(time.clock() - x)
+        return RESULT[status]
+    if n_ands() == 0:
+        #abc('bmc3 -T 2')
+        abc('&get;,bmc -vt=2')
+        if is_sat():
+            return 'SAT'
+    abc('trm')
+    write_file('smp')
+    abc('w %s_backup_%d.aig'%(initial_f_name,K))
+    K = K +1
+    set_globals()
+##    if ((n_ands() < 30000) and (a == 1) and (n_latches() < 300)):
+    if ((n_ands() < 30000) and (n_latches() < 300)):
+        print '\n***Running quick_verify'
+        status = quick_verify(0)
+        if status <= Unsat:
+            if not status == Unsat:
+                print 'CEX in frame %d'%cex_frame()
+            print 'Time for proof = %f sec.'%(time.clock() - x)
+            return RESULT[status]
+        if n_ands() == 0:
+            #abc('bmc3 -T 2')
+            abc('&get;,bmc -vt=2')
+            if is_sat():
+                return 'SAT'
+    print'\n***Running abstract'
+    nl_b = n_latches()
+    status = abstract()
+    abc('trm')
+    write_file('abs')
+    status = process_status(status)
+    if ((status <= Unsat)  or  status == Error):
+        if  status < Unsat:
+            print 'CEX in frame %d'%cex_frame()
+##            status = final_verify_recur(K)
+##            write_file('final')
+            print 'Time for proof = %f sec.'%(time.clock() - x)
+            return RESULT[status]
+        print 'Time for proof = %f sec.'%(time.clock() - x)
+        return RESULT[status]
+    abc('w %s_backup_%d.aig'%(initial_f_name,K))
+    K = K +1
+    if ((n_ands() > 20000) or (a == 1)):
+        print 'Speculation skipped because either too large or already done'
+        K = 2
+    elif n_ands() == 0:
+        print 'Speculation skipped because no AND nodes'
+        K = 2
+    else:
+        print '\n***Running speculate'
+        status = speculate()
+        abc('trm')
+        write_file('spec')
+        status = process_status(status)
+        if status == Unsat:
+            print 'Time for proof = %f sec.'%(time.clock() - x)
+            return RESULT[status]
+        if ((status < Unsat) or (status == Error)):
+            print 'CEX in frame %d'%cex_frame()
+            K = K-1 #if spec found a true cex, then result of abstract was wrong
+        else:
+            abc('w %s_backup_%d.aig'%(initial_f_name,K))
+            K = K +1
+    status = final_verify_recur(K)
+    abc('trm')
+    write_file('final')
+    print 'Time for proof = %f sec.'%(time.clock() - x)
+    return RESULT[status]
+
+def prove_g_pos(a):
+    """Proves the outputs clustered by a parameter a. 
+    a is the disallowed increase in latch support Clusters must be contiguous
+    If a = 0 then outputs are proved individually. Clustering is done from last to first
+    Output 0 is attempted to be proved inductively using other outputs as constraints.
+    Proved outputs are removed if all the outputs have not been proved.
+    If ever one of the proofs returns SAT, we stop and do not try any other outputs."""
+    global f_name, max_bmc,x_factor
+    x = time.clock()
+    #input_x_factor()
+    init_f_name = f_name
+    #fast_int(1)
+    print 'Beginning prove_g_pos'
+    prove_all_ind()
+    print 'Number of outputs reduced to %d by induction and fast interpolation'%n_pos()
+    print '\n************Running second level prove****************\n'
+    try_rpm()
+    result = prove(1) # 1 here means do not try speculate.
+    #result = prove_0_ind()
+    if result == 'UNSAT':
+        print 'Second prove returned UNSAT'
+        return result
+    if result == 'SAT':
+        print 'CEX found'
+        return result
+    print '\n********** Proving each output separately ************'
+    prove_all_ind()
+    print 'Number of outputs reduced to %d by induction and fast interpolation'%n_pos()
+    f_name = init_f_name
+    abc('w %s_osavetemp.aig'%f_name)
+    n = n_pos()
+    print 'Number of outputs = %d'%n
+    #count = 0
+    pos_proved = []
+    J = 0
+    jnext = n-1
+    while jnext >= 0:
+        max_bmc = -1
+        f_name = init_f_name
+        abc('r %s_osavetemp.aig'%f_name)
+        #Do in reverse order
+        jnext_old = jnext
+        if a == 0: # do not group
+            extract(jnext,jnext)
+            jnext = jnext -1 
+        else:
+            jnext = group(a,jnext)
+        if jnext_old > jnext+1:
+            print '\nProving outputs [%d-%d]'%(jnext + 1,jnext_old)
+        else:
+            print '\nProving output %d'%(jnext_old)
+        #ps()
+        #fast_int(1)
+        f_name = f_name + '_%d'%jnext_old
+        result = prove_1()
+        if result == 'UNSAT':
+            if jnext_old > jnext+1:
+                print '\n********  PROVED OUTPUTS [%d-%d]  ******** \n\n'%(jnext+1,jnext_old)
+            else:
+                print '\n********  PROVED OUTPUT %d  ******** \n\n'%(jnext_old)
+            pos_proved = pos_proved + range(jnext +1,jnext_old+1)
+            continue
+        if result == 'SAT':
+            print 'One of output in (%d to %d) is SAT'%(jnext + 1,jnext_old)
+            return result
+        else:
+            print '\n********  UNDECIDED on OUTPUTS %d thru %d  ******** \n\n'%(jnext+1,jnext_old)
+    f_name = init_f_name
+    abc('r %s_osavetemp.aig'%f_name)
+    if not len(pos_proved) == n:
+        print 'Eliminating %d proved outputs'%(len(pos_proved))
+        remove(pos_proved)
+        abc('trm')
+        write_file('group')
+        result = 'UNDECIDED'
+    else:
+        print 'Proved all outputs. The problem is proved UNSAT'
+        result = 'UNSAT'
+    print 'Total time for prove_g_pos = %f sec.'%(time.clock() - x)
+    return result
+
+def prove_pos():
+    """
+    Proved outputs are removed if all the outputs have not been proved.
+    If ever one of the proofs returns SAT, we stop and do not try any other outputs."""
+    global f_name, max_bmc,x_factor
+    x = time.clock()
+    #input_x_factor()
+    init_f_name = f_name
+    #fast_int(1)
+    print 'Beginning prove_pos'
+    prove_all_ind()
+    print 'Number of outputs reduced to %d by induction and fast interpolation'%n_pos()
+    print '\n********** Proving each output separately ************'
+    f_name = init_f_name
+    abc('w %s_osavetemp.aig'%f_name)
+    n = n_pos()
+    print 'Number of outputs = %d'%n
+    #count = 0
+    pos_proved = []
+    pos_disproved = []
+    J = 0
+    jnext = n-1
+    while jnext >= 0:
+        max_bmc = -1
+        f_name = init_f_name
+        abc('r %s_osavetemp.aig'%f_name)
+        #Do in reverse order
+        jnext_old = jnext
+        extract(jnext,jnext)
+        jnext = jnext -1 
+        print '\nProving output %d'%(jnext_old)
+        f_name = f_name + '_%d'%jnext_old
+        result = prove_1()
+        if result == 'UNSAT':
+            print '\n********  PROVED OUTPUT %d  ******** \n\n'%(jnext_old)
+            pos_proved = pos_proved + range(jnext +1,jnext_old+1)
+            continue
+        if result == 'SAT':
+            print '\n********  DISPROVED OUTPUT %d  ******** \n\n'%(jnext_old)
+            pos_disproved = pos_disproved + range(jnext +1,jnext_old+1)
+            continue
+        else:
+            print '\n********  UNDECIDED on OUTPUT %d  ******** \n\n'%(jnext_old)
+    f_name = init_f_name
+    abc('r %s_osavetemp.aig'%f_name)
+    list = pos_proved + pos_disproved
+    print 'Proved the following outputs: %s'%pos_proved
+    print 'Disproved the following outputs: %s'%pos_disproved
+    if not len(list) == n:
+        print 'Eliminating %d resolved outputs'%(len(list))
+        remove(list)
+        abc('trm')
+        write_file('group')
+        result = 'UNRESOLVED'
+    else:
+        print 'Proved or disproved all outputs. The problem is proved RESOLVED'
+        result = 'RESOLVED'
+    print 'Total time for prove_pos = %f sec.'%(time.clock() - x)
+    return result
+
+
+def prove_g_pos_split():
+    """like prove_g_pos but quits when any output is undecided"""
+    global f_name, max_bmc,x_factor
+    x = time.clock()
+    #input_x_factor()
+    init_f_name = f_name
+    #fast_int(1)
+    print 'Beginning prove_g_pos_split'
+    prove_all_ind()
+    print 'Number of outputs reduced to %d by induction and fast interpolation'%n_pos()
+    try_rpm()
+    print '\n********** Proving each output separately ************'  
+    f_name = init_f_name
+    abc('w %s_osavetemp.aig'%f_name)
+    n = n_pos()
+    print 'Number of outputs = %d'%n
+    pos_proved = []
+    J = 0
+    jnext = n-1
+    while jnext >= 0:
+        max_bmc = -1
+        f_name = init_f_name
+        abc('r %s_osavetemp.aig'%f_name)
+        jnext_old = jnext
+        extract(jnext,jnext)
+        jnext = jnext -1
+        print '\nProving output %d'%(jnext_old)
+        f_name = f_name + '_%d'%jnext_old
+        result = prove_1()
+        if result == 'UNSAT':
+            if jnext_old > jnext+1:
+                print '\n********  PROVED OUTPUTS [%d-%d]  ******** \n\n'%(jnext+1,jnext_old)
+            else:
+                print '\n********  PROVED OUTPUT %d  ******** \n\n'%(jnext_old)
+            pos_proved = pos_proved + range(jnext +1,jnext_old+1)
+            continue
+        if result == 'SAT':
+            print 'One of output in (%d to %d) is SAT'%(jnext + 1,jnext_old)
+            return result
+        else:
+            print '\n********  UNDECIDED on OUTPUTS %d thru %d  ******** \n\n'%(jnext+1,jnext_old)
+            print 'Eliminating %d proved outputs'%(len(pos_proved))
+            # remove outputs proved and return
+            f_name = init_f_name
+            abc('r %s_osavetemp.aig'%f_name)
+            remove(pos_proved)
+            abc('trm')
+            write_file('group')            
+            return 'UNDECIDED'
+    f_name = init_f_name
+    abc('r %s_osavetemp.aig'%f_name)
+    if not len(pos_proved) == n:
+        print 'Eliminating %d proved outputs'%(len(pos_proved))
+        remove(pos_proved)
+        abc('trm')
+        write_file('group')
+        result = 'UNDECIDED'
+    else:
+        print 'Proved all outputs. The problem is proved UNSAT'
+        result = 'UNSAT'
+    print 'Total time = %f sec.'%(time.clock() - x)
+    return result
+
+
+
+def group(a,n):
+    """Groups together outputs beginning at output n and any contiguous preceeding output
+    that does not increase the latch support by a or more"""
+    global f_name, max_bmc
+    nlt = n_latches()
+    extract(n,n)
+    nli = n_latches()
+    if n == 0:
+        return n-1
+    for J in range(1,n+1):
+        abc('r %s_osavetemp.aig'%f_name)
+        j = n-J
+        #print 'Running %d to %d'%(j,n)
+        extract(j,n)
+        #print 'n_latches = %d'%n_latches()
+        #if n_latches() >= nli + (nlt - nli)/2:
+        if n_latches() == nli:
+            continue
+        if n_latches() > nli+a:
+            break
+    abc('r %s_osavetemp.aig'%f_name)
+##    if j == 1:
+##        j = j-1
+    print 'extracting [%d-%d]'%(j,n)
+    extract(j,n)
+    ps()
+    return j-1
+        
+def extract(n1,n2):
+    """Extracts outputs n1 through n2"""
+    no = n_pos()
+    if n2 > no:
+        return 'range exceeds number of POs'
+    abc('cone -s -O %d -R %d'%(n1, 1+n2-n1))
+    abc('scl')
+
+def prove_0_ind():
+    """Uses all other outputs as constraints to try to prove output 0 by induction"""
+    abc('w %s_osavetemp.aig'%f_name)
+    #ps()
+    abc('constr -N %d'%(n_pos()-1))
+    #ps()
+    abc('fold')
+    #ps()
+    abc('ind -u -C 1000000 -F 20')
+    status = get_status()
+    abc('r %s_osavetemp.aig'%f_name)
+    return status
+
+def remove(list):
+    """Removes outputs in list"""
+    zero(list)
+    abc('&get;&trim;&put')
+    #fast_int(1)
+
+def zero(list):
+    """Zeros out POs in list"""
+    for j in list:
+        run_command('zeropo -N %d'%j)
+
+def sp():
+    """Alias for super_prove"""
+    print 'Executing super_prove'
+    result = super_prove()
+    return result
+
+def super_prove():
+    """Main proof technique now. Does original prove and if after speculation there are multiple output left
+    if will try to prove each output separately, in reverse order. It will quit at the first output that fails
+    to be proved, or any output that is proved SAT"""
+    global max_bmc, init_initial_f_name, initial_f_name
+    init_initial_f_name = initial_f_name
+    if x_factor > 1:
+        print 'x_factor = %d'%x_factor
+        input_x_factor()
+    max_bmc = -1
+    x = time.clock()
+    print "Trying BMC for 2 sec."
+    abc("&get; ,bmc -vt=2")
+    if is_sat():
+        print 'Total time taken by super_prove = %f sec.'%(time.clock() - x)
+        return 'SAT'
+    result = prove(0)
+    if ((result[:3] == 'UND') and (n_latches() == 0)):
+        return result
+    k = 1
+    print result
+    if not result[:3] == 'UND':
+        print 'Total time taken by super_prove = %f sec.'%(time.clock() - x)
+        return result
+    if n_pos() > 1:
+        result = prove_g_pos(0)
+        print result
+        if result == 'UNSAT':
+            print 'Total time taken by super_prove = %f sec.'%(time.clock() - x)
+            return result
+        if result == 'SAT':
+            k = 0 #Don't try to prove UNSAT on an abstraction that had SAT
+                    # should go back to backup 1 since probably spec was bad.
+    y = time.clock()
+    result = BMC_VER_result(k)
+    print 'Total time taken by last gasp verification = %f sec.'%(time.clock() - y)
+    print 'Total time for %s = %f sec.'%(init_initial_f_name,(time.clock() - x))
+    return result
+
+def reachm(t):
+    x = time.clock()
+    run_command('&get;&reach -vcs -T %d;&put'%t)
+    print 'Time = %f'%(time.clock() - x)
+    
+def reachx(t):
+    x = time.clock()
+    run_command('reachx -t %d'%t)
+    print 'Time = %f'%(time.clock() - x)
+
+def BMC_VER_result(n):
+    global init_initial_f_name
+    #print init_initial_f_name
+    xt = time.clock()
+    result = 5
+    T = 150
+    if n == 0:
+        abc('r %s_smp.aig'%init_initial_f_name)
+        print '\n***Running proof on initial simplified circuit\n',
+        ps()
+    else:
+        print '\n***Running proof on final unproved circuit'
+        ps()
+    print '    Running PDR for %d sec'%T
+    abc('&get;,pdr -vt=%d'%(T*.8))
+    result = get_status()
+    if result == Unsat:
+        return 'UNSAT'
+    if result > Unsat: #still undefined
+        if (n_pis()+n_latches() < 250):
+            print '    Running Reachability for 150 sec.'
+            abc('reachx -t 150')
+            #run_command('&get;&reach -vcs -T %d'%T)
+            result = get_status()
+            if result == Unsat:
+                return 'UNSAT'
+        if ((result > Unsat) and n ==1):
+            print '    Running interpolation for %f sec.'%T
+            abc(',imc -vt=%f'%T)
+            result = get_status()
+            if result == Unsat:
+                return 'UNSAT'
+    # if n=1 we are trying to prove result on abstracted circuit. If still undefined, then probably does
+    # not make sense to try pdr, reach, int on original simplified circuit, only BMC here.
+    if n == 1:
+        abc('r %s_smp.aig'%init_initial_f_name) #check if the initial circuit was SAT
+        #print 'Reading %s_smp'%init_initial_f_name,
+    #run_command('bmc3 -v -T %d -F 200000 -C 1000000'%T)
+    print '***Running BMC on initial simplified circuit'
+    ps()
+    print '\n'
+    abc('&get;,bmc -vt=%f'%T)
+    result = get_status()
+    if result < Unsat:
+        result = 'SAT'
+        print ' CEX found in frame %d'%cex_frame()
+    else:
+        result = 'UNDECIDED'
+    print 'Additional time taken by BMC/PDR/Reach = %f sec.'%(time.clock() - xt)
+    return result
+
+def try_split():
+    abc('w %s_savetemp.aig'%f_name)
+    na = n_ands()
+    split(3)
+    if n_ands()> 2*na:
+        abc('r %s_savetemp.aig'%f_name)
+    
+
+def time_diff():
+    global last_time
+    new_time = time.clock()
+    diff = new_time - last_time
+    last_time = new_time
+    result = 'Lapsed time = %.2f sec.'%diff
+    return result
+
+def prove_all_ind():
+    """Tries to prove output k by induction, using other outputs as constraints. If ever an output is proved
+    it is set to 0 so it can't be used in proving another output to break circularity.
+    Finally all zero'ed ooutputs are removed. """
+    N = n_pos()
+    remove_0_pos()
+    print '0 valued output removal changed POs from %d to %d'%(N,n_pos())
+    abc('w %s_osavetemp.aig'%f_name)
+    list = range(n_pos())
+    for j in list:
+        #abc('r %s_osavetemp.aig'%f_name)
+        abc('swappos -N %d'%j)
+        remove_0_pos() #may not have to do this if constr works well with 0'ed outputs
+        abc('constr -N %d'%(n_pos()-1))
+        abc('fold')
+        n = max(1,n_ands())
+        f = max(1,min(40000/n,16))
+        f = int(f)
+        abc('ind -u -C 10000 -F %d'%f)
+        status = get_status()
+        abc('r %s_osavetemp.aig'%f_name)
+        if status == Unsat:
+            print '+',
+            abc('zeropo -N %d'%j)
+            abc('w %s_osavetemp.aig'%f_name) #if changed, store it permanently
+        print '%d'%j,
+    remove_0_pos()
+    print '\nThe number of POs reduced from %d to %d'%(N,n_pos())
+    #return status
+
+def prove_all_pdr(t):
+    """Tries to prove output k by PDR. If ever an output is proved
+    it is set to 0. Finally all zero'ed ooutputs are removed. """
+    N = n_pos()
+    remove_0_pos()
+    print '0 valued output removal changed POs from %d to %d'%(N,n_pos())
+    abc('w %s_osavetemp.aig'%f_name)
+    list = range(n_pos())
+    for j in list:
+        #abc('r %s_osavetemp.aig'%f_name)
+        abc('cone -O %d -s'%j)
+        abc('scl')
+        abc('&get;,pdr -vt=%d'%t)
+        status = get_status()
+        abc('r %s_osavetemp.aig'%f_name)
+        if status == Unsat:
+            print '+',
+            abc('zeropo -N %d'%j)
+            abc('w %s_osavetemp.aig'%f_name) #if changed, store it permanently
+        print '%d'%j,
+    remove_0_pos()
+    print '\nThe number of POs reduced from %d to %d'%(N,n_pos())
+    #return status
+
+
+def remove_0_pos():
+    abc('&get; &trim; &put')
+
+    
+def prove_all_ind2():
+    """Tries to prove output k by induction, using outputs > k as constraints. Removes proved outputs from POs."""
+    abc('w %s_osavetemp.aig'%f_name)
+    plist = []
+    list = range(n_pos())
+##    if r == 1:
+##        list.reverse()
+    for j in list:
+        abc('r %s_osavetemp.aig'%f_name)
+        extract(j,n_pos())
+        abc('constr -N %d'%(n_pos()-1))
+        abc('fold')
+        n = max(1,n_ands())
+        f = max(1,min(40000/n,16))
+        f = int(f)
+        abc('ind -u -C 10000 -F %d'%f)
+        status = get_status()
+        if status == Unsat:
+            plist = plist + [j]
+            print '-',
+##        else:
+##            status = pdr(1)
+##            if status == Unsat:
+##                print '+',
+##                plist = plist + [j]
+        print '%d'%j,
+    print '\nOutputs proved = ',
+    print plist
+    abc('r %s_osavetemp.aig'%f_name)
+    remove(plist) #remove the outputs proved
+##    #the following did not work because abc command constr, allows only  last set of outputs to be constraints
+##    abc('w %s_osavetemp.aig'%f_name)
+##    plist = []
+##    list = range(n_pos())
+##    list.reverse()
+##    for j in list:
+##        abc('r %s_osavetemp.aig'%f_name)
+##        extract(j,n_pos())
+##        abc('constr -N %d'%(n_pos()-1))
+##        abc('fold')
+##        n = max(1,n_ands())
+##        f = max(1,min(40000/n,16))
+##        f = int(f)
+##        abc('ind -u -C 10000 -F %d'%f)
+##        status = get_status()
+##        if status == Unsat:
+##            plist = plist + [j]
+##            print '-',
+####        else:
+####            status = pdr(1)
+####            if status == Unsat:
+####                print '+',
+####                plist = plist + [j]
+##        print '%d'%j,
+##    print '\nOutputs proved = ',
+##    print plist.reverse
+##    abc('r %s_osavetemp.aig'%f_name)
+##    remove(plist) #remove the outputs proved
+##    return status
+
+def pdr(t):
+    abc('&get; ,pdr -vt=%f'%t)
+    result = get_status()
+
+def split(n):
+    abc('orpos;&get')
+    abc('&posplit -v -N %d;&put;dc2;trm'%n)
+
+def keep_splitting():
+    for j in range(5):
+        split(5+j)
+        no = n_pos()
+        status = prove_g_pos_split(0)
+        if status <= Unsat:
+            return status
+        if no == n_pos():
+            return Undecided
+
+def drill(n):
+    run_command('&get; &reach -vcs -H 5 -S %d -T 50 -C 40'%n)
+
+def prove_1():
+    """Proves all the outputs together. If ever an abstraction was done then if SAT is returned,
+        we make RESULT return "undecided".
+        """
+    a = 1
+    global x_factor,xfi,f_name
+    x = time.clock()
+    max_bmc = -1
+    K = 0
+    print 'Initial: ',
+    print_circuit_stats()
+    x_factor = xfi
+    print 'x_factor = %f'%x_factor
+    print '\n***Running pre_simp'
+    set_globals()
+    status = pre_simp()
+    if ((status <= Unsat) or (n_latches == 0)):
+        print 'Time for proof = %f sec.'%(time.clock() - x)
+        return RESULT[status]
+    abc('trm')
+    write_file('smp')
+    abc('w %s_backup_%d.aig'%(initial_f_name,K))
+    K = K +1
+    set_globals()
+    if ((n_ands() < 30000) and (a == 1) and (n_latches() < 300)):
+        print '\n***Running quick_verify'
+        status = quick_verify(0)
+        if status <= Unsat:
+            if not status == Unsat:
+                print 'CEX in frame %d'%cex_frame()
+            print 'Time for proof = %f sec.'%(time.clock() - x)
+            return RESULT[status]
+    print'\n***Running abstract'
+    nl_b = n_latches()
+    status = abstract()
+    abc('trm')
+    write_file('abs')
+    status = process_status(status)
+    if ((status <= Unsat)  or  status == Error):
+        if  status < Unsat:
+            print 'CEX in frame %d'%cex_frame()
+            print 'Time for proof = %f sec.'%(time.clock() - x)
+            return RESULT[status]
+        print 'Time for proof = %f sec.'%(time.clock() - x)
+        return RESULT[status]
+    abc('w %s_backup_%d.aig'%(initial_f_name,K))
+    status = final_verify_recur(2)
+    abc('trm')
+    write_file('final')
+    print 'Time for proof = %f sec.'%(time.clock() - x)
+    return RESULT[status]
+
+def qprove():
+    global x_factor
+    x = time.clock()
+    x_factor = 3
+    print '\n*********pre_simp**********\n'
+    pre_simp()
+    print '\n*********absv**********\n'
+    result = absv(3,1)
+    x_factor = 2
+    print '\n*********absv**********\n'
+    result = absv(3,1)
+    print '\n*********speculate**********\n'
+    result = speculate()
+    if result <= Unsat:
+        return RESULT[result]
+    print '\n*********absv**********\n'
+    result = absv(3,1)
+    print '\n*********prove_pos**********\n'
+    result = prove_pos()
+    if result == 'UNDECIDED':
+        print '\n*********BMC_VER_result**********\n'
+        result = BMC_VER_result(1)
+    print 'Time for proof = %f sec.'%(time.clock() - x)
+    return result
+    
+def pre_reduce():
+    x = time.clock()
+    pre_simp()
+    write_file('smp')
+    abstract()
+    write_file('abs')
+    print 'Time = %f'%(time.clock() - x)
+
+
+#PARALLEL FUNCTIONS
+"""  funcs should look like
+funcs = [defer(abc)('&get;,bmc -vt=50;&put'),defer(super_prove)()]
+After this is executed funcs becomes a special list of lambda functions
+which are given to abc_split_all to be executed as in fork below.
+It has been set up so that each of the functions works on the current aig and
+possibly transforms it. The new aig and status is always read into the master when done
+
+"""
+
+def fork(funcs):
+    """ runs funcs in parallel"""
+    for i,res in pyabc_split.abc_split_all(funcs):
+        status = prob_status()
+        if not status == -1:
+            print i,status
+            ps()
+            break
+        else:
+            print i,status
+            ps()
+            continue
+    return status
+
+def handler_s(res):
+    """ This serial handler returns True if the problem is solved by the first returning function,
+    in which case, the problem is replaced by the new aig and status.
+    """
+    if not res == -1:
+        #replace_prob()
+        print ('UNSAT','SAT')[res]
+        return True
+    else:
+        return False
+    
diff --git a/abc-build/scripts/main.py b/abc-build/scripts/main.py
new file mode 100644
--- /dev/null
+++ b/abc-build/scripts/main.py
@@ -0,0 +1,431 @@
+import os
+import time
+from datetime import *
+##import par
+##from abc_common import *
+import abc_common
+
+#this makes par the dominant module insteat of abc_common
+from par import *
+
+import sys
+import math
+import time
+from  pyabc_split import *
+##import pdb
+##from IPython.Debugger import Tracer; debug_here = Tracer()
+
+
+#x('source ../../abc.rc')
+#abc_common.x('source ../../abc.rc')
+
+def scorriter():
+    """ apply scorr with increasing conflicts up to 100"""
+    x('time')
+    run_command('r p_0.aig')
+    n = 20
+    while n < 1000:
+        print_circuit_stats()
+        run_command('scorr -C %d'%n)
+        x('ind -C %d'%1000)
+        if is_unsat():
+            print 'n = %d'%n
+            break
+        n = 2*n
+    x('time')
+     
+def simplifyq():
+    # set_globals()
+    n=n_ands()
+    if n > 30000:
+        if n<45000:
+            abc("&get;&scl;&dc2;&put;dr;&get;&lcorr;&dc2;&put;dr;&get;&scorr;&fraig;&dc2;&put;dr;&get;&scorr -F 2;&dc2;&put;w temp.aig")
+        else:
+            abc("&get;&scl;&dc2;&put;dr;&get;&lcorr;&dc2;&put;dr;&get;&scorr;&fraig;&dc2;&put;dr;&get;&dc2;&put;w temp.aig")
+    n = n_ands()
+    if n < 30000:
+        if n > 15000:
+            abc("scl;rw;dr;lcorr;rw;dr;scorr;fraig;dc2;dr;dc2rs;w temp.aig")
+        else:
+            abc("scl;rw;dr;lcorr;rw;dr;scorr;fraig;dc2;dr;scorr -F 2;dc2rs;w temp.aig")    
+    if n < 10000:
+        m = min( 30000/n, 8 )
+        if m > 2:
+            abc( "scorr -F %d"%m)
+    run_command("ps")
+
+def constraints():
+    """Determine if a set of files in a set of
+    directories has constraints and print out the results."""
+    for s in directories:
+        print("\ndirectory is "+s)
+        jj=eval(s)
+        print(jj)
+        for j in range(len(jj)):
+            x("\nr ../DIR/%s/p_%smp.aig"%(s,jj[j]))
+            print("structural:")
+            x('constr -s')
+            print("inductive constraints:")
+            x('constr ')
+
+def help(s):
+    run_command('%s -h'%s)
+
+def strip():
+    """Strip out each output of a multi-output example and write it
+    into a separate file"""
+    os.chdir('../DIR')
+    abc('r p_all_smp.aig')
+    po = n_pos()
+    print_circuit_stats()
+    for j in range(po):
+        abc('r p_all_smp.aig')
+        abc('cone -s -O %d'%j)
+        abc('scl;rw;trm')
+        abc('w p_%d.aig'%j)
+        print_circuit_stats()
+
+def fn_def(f,n):
+    filename = f.__code__.co_filename
+    firstline = f.__code__.co_firstlineno
+    lines = open(filename, "r").readlines()
+    print "".join(lines[firstline : n+firstline])
+
+def lst(list,match):
+    result = []
+    for j in range(len(list)):
+        if list[j][-len(match):] == match:
+            result.append(list[j])
+    return result
+
+def lste(list,match,excp):
+    result = []
+    for j in range(len(list)):
+        if list[j][-len(match):] == match:
+            if excp in list[j]:
+                continue
+            result.append(list[j])
+    return result
+
+def blif2aig():
+    """ converts blif files into aig files"""
+    #os.chdir('../ibm-web')
+    list_all = os.listdir('.')
+    l_blif = lst(list_all,'.blif')
+    for j in range(len(l_blif)):
+        name = l_blif[j][:-5]
+        print '%s '%name,
+        abc('r %s.blif'%name)
+        abc('st')
+        abc('fold')
+        abc('w %s.aig'%name)
+        ps()
+
+def la():
+    return list_aig('')
+
+def list_aig(s=''):
+    """ prnts out the sizes of aig files"""
+    #os.chdir('../ibm-web')
+    list_all = os.listdir('.')
+    dir = lst(list_all,'.aig')
+    dir.sort()
+    result = []
+    for j in range(len(dir)):
+        name = dir[j][:-4]
+        if not s_in_s(s,name):
+            continue
+        print '%s '%name,
+        abc('r %s.aig'%name)
+        ps()
+        result = result + [name]
+    return result
+
+def list_original():
+    list_dir = os.listdir('.')
+    list_dir.sort()
+    out = []
+    for i in range(len(list_dir)):
+        name = '%s/original.aig'%list_dir[i]
+        if os.access('%s'%name,os.R_OK):
+            abc('r %s;&ps'%name)
+            if n_latches() > 0 and n_pos() > 1:
+                size = str(sizeof())
+                print list_dir[i],
+                ps()
+                out = out + ['%s: %s'%(list_dir[i],size)]
+    return out
+
+def list_size(s=''):
+    """ prnts out the sizes of aig files. Leaves .aig as part of name"""
+    #os.chdir('../ibm-web')
+    list_all = os.listdir('.')
+    dir = lst(list_all,'.aig')
+    dir.sort()
+    result = []
+    for j in range(len(dir)):
+##        name = dir[j][:-4]
+        name = dir[j] #leaves .aig as part of name
+        if not s_in_s(s,name):
+            continue
+        print '%s '%name,
+##        abc('r %s.aig'%name)
+        abc('r %s'%name)
+        ps()
+        result = result + [name[:-4]] #takes .aig off of name
+    return result
+
+def rename(l=[]):
+    for j in range(len(l)):
+        name = l[j]
+        name1 = name +'.aig'
+        name2 = name[:-4]+'simp.aig' #take off _smp and put on simp
+        os.rename(name1,name2)
+    
+
+def list_blif(s=''):
+    """ prnts out the sizes of aig files"""
+    #os.chdir('../ibm-web')
+    list_all = os.listdir('.')
+    dir = lst(list_all,'.blif')
+    dir.sort()
+    result = []
+    for j in range(len(dir)):
+        name = dir[j][:-5]
+        if not s_in_s(s,name):
+            continue
+        print '%s: '%name,
+        abc('read_blif %s.blif'%name)
+        run_command('ps')
+        abc('st;zero;w %s.aig'%name)
+        result = result + [name]
+    return result
+
+def s_in_s(s1,s2):
+    ls1 = len(s1)
+    l = 1+len(s2)- ls1
+    if l< 0:
+        return False
+    else:
+        for j in range(l):
+            if s1 == s2[j:j+ls1]:
+                return True
+            else:
+                continue
+        return False
+            
+
+def convert_ibm():
+    """ converts blif files (with constraints?) into aig files"""
+    os.chdir('../ibm-web')
+    list_ibm = os.listdir('.')
+    l_blif = lst(list_ibm,'.blif')
+    for j in range(len(l_blif)):
+        name = l_blif[j][:-5]
+        run_command('read_blif %s.blif'%name)
+        abc('undc')
+        abc('st -i')
+        abc('zero')
+        run_command('w %s.aig'%name)
+        """if a<100000000:
+            f = min(8,max(1,40000/a))
+            #run_command('scorr -c -F %d'%f)
+            #print 'Result of scorr -F %d: '%f,
+            print_circuit_stats()
+            run_command('w p_%d.aig'%j)"""
+
+def cl():
+    cleanup()
+
+def cleanup():
+    list = os.listdir('.') 
+    for j in range(len(list)):
+        name = list[j]
+        if ((s_in_s('_smp',name)) or (s_in_s('_save', name)) or (s_in_s('_backup', name)) or (s_in_s('_osave', name))
+            or (s_in_s('_best', name)) or (s_in_s('_gsrm', name)) or (s_in_s('gore', name)) or 
+            (s_in_s('_bip', name)) or (s_in_s('sm0', name)) or (s_in_s('gabs', name)) 
+            or (s_in_s('temp', name)) or (s_in_s('__', name)) or (s_in_s('greg', name)) or (s_in_s('tf2', name))
+            or (s_in_s('gsrm', name)) or (s_in_s('_rpm', name )) or (s_in_s('gsyn', name)) or (s_in_s('beforerpm', name))
+            or (s_in_s('afterrpm', name)) or (s_in_s('initabs', name)) or (s_in_s('_init', name))
+            or (s_in_s('_osave', name)) or (s_in_s('tt_', name)) or (s_in_s('_before', name)) or (s_in_s('_after', name))
+            or (s_in_s('_and', name)) or (s_in_s('_spec', name)) or (s_in_s('temp.a', name))
+            or (s_in_s('_sync', name)) or (s_in_s('_old', name)) or (s_in_s('_cone_', name)) or (s_in_s('_abs', name))
+            or (s_in_s('_vabs', name)) or (s_in_s('_gla', name)) or (s_in_s('vabs', name)) or (s_in_s('_mp2', name))
+            or (s_in_s('_sc1', name)) or (s_in_s('_sc2', name)) or (s_in_s('_after', name))
+            or (s_in_s('_before', name)) or (s_in_s('_aigs_', name)) or (s_in_s('_cex.', name))
+            or (s_in_s('_bmc1', name)) or (s_in_s('_p0_', name)) or (s_in_s('_p1_', name))
+            or (s_in_s('_unsolv', name)) or (s_in_s('_iso1', name))
+            ):
+            os.remove(name)
+        
+def simp_mbi():
+    os.chdir('../mbi')
+    list_ibm = os.listdir('.')
+    l_aig = lst(list_ibm,'.aig')
+    for j in range(len(l_aig)):
+        name = l_aig[j][:-4]
+        run_command('r %s.aig'%name)
+        run_command('st')
+        print '\n%s: '%name
+        print_circuit_stats()
+        quick_simp()
+        scorr_comp()
+        simplify()
+        run_command('w %s_smp.aig'%name)
+
+def strip_names():
+    os.chdir('../mbi')
+    list_ibm = os.listdir('.')
+    l_aig = lst(list_ibm,'.aig')
+    for j in range(len(l_aig)):
+        name = l_aig[j][:-4]
+        run_command('r %s.aig'%name)
+        run_command('st')
+        print '\n%s: '%name
+        print_circuit_stats()
+        quick_simp()
+        scorr_comp()
+        simplify()
+        run_command('w %s_smp.aig'%name)
+
+
+def map_ibm():
+    os.chdir('../ibmmike2')
+    list_ibm = os.listdir('.')
+    l_blif = lst(list_ibm,'.blif')
+    result = []
+    print len(l_blif)
+    for j in range(len(l_blif)):
+        name = l_blif[j][:-5]
+        result.append('%s = %d'%(name,j))
+    return result
+
+
+def absn(a,c,s):
+    """ testing Niklas abstraction with various conflict limits
+    a= method (0 - regular cba,
+               1 - pure pba,
+               2 - cba with pba at the end,
+               3 cba and pba interleaved at each step
+    c = conflict limit
+    s = No. of stable steps without cex"""
+    global G_C, G_T, latches_before_abs, x_factor, f_name
+    set_globals()
+    latches_before_abs = n_latches()
+    print 'Start: ',
+    print_circuit_stats()
+    print 'Een abstraction params: Method #%d, %d conflicts, %d stable'%(a,c,s)
+    run_command('&get; &abs_newstart -v -A %d -C %d -S %d'%(a,c,s))
+    bmcdepth = n_bmc_frames()
+    print 'BMC depth = %d'%n_bmc_frames()
+    abc('&w absn_greg.aig; &abs_derive; &put; w absn_gabs.aig')
+    print 'Final abstraction: ',
+    print_circuit_stats()
+    write_file('absn')
+    return "Done"
+
+def time_stamp():
+    d=datetime.today()
+    s = d.strftime('%m.%d.%y-%X')
+    return s
+
+def apply_sp(list):
+    global m_trace
+    s = time_stamp()
+    out_name = "%s-traces.txt"%s
+    print out_name
+    if os.access(out_name,os.R_OK):
+        os.remove(out_name)
+    f = open(out_name,'w')
+    print f
+    for j in range(len(list)):
+        name = list[j]
+        print '\n\n**** %s ****\n'%name
+        f.write('\n\n****%s ****'%name)
+        read_file_quiet(name)
+        result = super_prove()
+        trace = result[1]
+        s = str(trace)
+        f.write('\n\n')
+        f.write(s)
+        f.flush()
+    f.close()
+         
+def xfiles():
+    global f_name
+    #output = sys.stdout
+    #iterate over all ESS files
+    #saveout = sys.stdout
+    #output = open("ibm_log.txt",'w')
+    # sys.stdout = output
+    os.chdir('../ess/f58m')
+    print 'Directories are %s'%directories
+    for s in directories:
+        sss=  '../%s'%s
+        os.chdir(sss)
+        print "\nDirectory is %s\n"%s
+        jj=eval(s)
+        print (jj)
+        run_command('time')
+        for j in range(len(jj)):
+            print ' '
+            set_fname('p_%dsmp23'%jj[j])#file f_name.aig is read in
+            print 'p_%dsmp23'%jj[j]
+            run_command('time')
+            result = dprove3(1)
+            print result
+            run_command('time')
+        run_command('time')
+    os.chdir('../../python')
+    #sys.stdout = saveout
+    #output.close()
+
+def sublist(L,I):
+    z = []
+    for i in range(len(I)):
+        s = L[I[i]],
+        s = list(s)
+        z = z + s
+    return z
+
+def s2l(s):
+    """ takes the string s divided by '\n' and makess a list of items"""
+    result = []
+    while len(s)>2:
+        j = s.find('\n')
+        result.append(s[:j])
+        s = s[j+1:]
+    return result
+
+def select(lst, s):
+    result = []
+    print lst
+    for j in range(len(lst)):
+        if s in lst[j]:
+            s1 = lst[j]
+            k = s1.find(':')
+            s1 = s1[:k]
+            result.append(s1)
+    return result
+
+def process_result(name):
+    f = open(name,'r')
+    s = f.read()
+    f.close()
+    lst = s2l(s)
+    result = select(lst,'Timeout')
+    return result
+
+
+def main():
+    stackno = 0
+    if len(sys.argv) != 2:
+        print "usage: %s <aig filename>"%sys.argv[0]
+        sys.exit(1)
+    aig_filename = sys.argv[1]
+    x("source ../../abc.rc")
+    read(aig_filename)
+    dprove3(1)
+# a test to  whether the script is being called from the command line
+if __name__=="__main__":
+    main()
diff --git a/abc-build/scripts/multi_prove.sh b/abc-build/scripts/multi_prove.sh
new file mode 100644
--- /dev/null
+++ b/abc-build/scripts/multi_prove.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+abc_root()
+{
+    cwd="$(pwd)"
+    cd $(dirname "$1")
+    echo $(dirname "$(pwd)")
+    cd "${cwd}"
+}
+
+abc_dir=$(abc_root "$0")
+bin_dir="${abc_dir}"/bin
+
+exec ${bin_dir}/abc -q "/multi_prove_aiger $*"
diff --git a/abc-build/scripts/new_abc_commands.py b/abc-build/scripts/new_abc_commands.py
new file mode 100644
--- /dev/null
+++ b/abc-build/scripts/new_abc_commands.py
@@ -0,0 +1,257 @@
+import sys
+import os
+import pyabc
+import par
+import tempfile
+import shutil
+import redirect
+import optparse
+
+from contextlib import contextmanager
+
+def read_cmd(args):
+    if len(args)==2:
+        par.read_file_quiet(args[1])
+    else:
+        par.read_file()
+    return 0
+
+pyabc.add_abc_command(read_cmd, "ZPython", "/rf", 0)
+
+def chdir_cmd(args):
+    os.chdir( args[1] )
+    return 0
+
+pyabc.add_abc_command(chdir_cmd, "ZPython", "/cd", 0)
+
+def pwd_cmd(args):
+    print os.getcwd()
+    return 0
+
+pyabc.add_abc_command(pwd_cmd, "ZPython", "/pwd", 0)
+
+def ls_cmd(args):
+    os.system("ls " + " ".join(args[1:]))
+    return 0
+
+pyabc.add_abc_command(ls_cmd, "ZPython", "/ls", 0)
+
+pushd_temp_stack = []
+
+def pushdtemp_cmd(args):
+    tmpdir = tempfile.mkdtemp()
+    pushd_temp_stack.append( (os.getcwd(), tmpdir) )
+    os.chdir(tmpdir)
+    return 0
+    
+pyabc.add_abc_command(pushdtemp_cmd, "ZPython", "/pushdtemp", 0)
+
+def popdtemp_cmd(args):
+    prev, temp = pushd_temp_stack.pop()
+    os.chdir(prev)
+    shutil.rmtree(temp, ignore_errors=True)
+    return 0
+    
+pyabc.add_abc_command(popdtemp_cmd, "ZPython", "/popdtemp", 0)
+
+pushredirect_stack = []
+
+def push_redirect_cmd(args):
+    fdout = redirect.start_redirect( redirect.null_file, sys.stdout)
+    pushredirect_stack.append( (sys.stdout, fdout) )
+    
+    fderr = redirect.start_redirect( redirect.null_file, sys.stderr)
+    pushredirect_stack.append( (sys.stderr, fderr) )
+    
+    return 0
+    
+pyabc.add_abc_command(push_redirect_cmd, "ZPython", "/pushredirect", 0)
+
+def pop_redirect_cmd(args):
+    err, fderr = pushredirect_stack.pop()
+    redirect.end_redirect(err, fderr)
+ 
+    out, fdout = pushredirect_stack.pop()
+    redirect.end_redirect(out, fdout)
+    
+    return 0
+    
+pyabc.add_abc_command(pop_redirect_cmd, "ZPython", "/popredirect", 0)
+
+def print_aiger_result(args):
+    status = pyabc.prob_status()
+    
+    if status==1:
+        print 0
+    elif status==0:
+        print 1
+    else:
+        print 2
+    
+    return 0
+    
+pyabc.add_abc_command(print_aiger_result, "ZPython", "/print_aiger_result", 0)
+
+@contextmanager
+def replace_report_result(multi):
+    
+    def report_result(po, result):
+        
+        print "REPORT RESULT: ", po, result
+        
+        print >> stdout, "%d"%result
+        print >> stdout, "b%d"%po
+        print >> stdout, "."
+        
+    def report_liveness_result(po, result):
+        
+        print "REPORT RESULT: ", po, result
+        
+        print >> stdout, "%d"%result
+        print >> stdout, "j%d"%po
+        print >> stdout, "."
+
+    def report_bmc_depth(depth):
+        
+        if not multi:
+            print "REPORT BMC DEPTH:", depth
+            print >> stdout, "u%d"%depth
+    
+    with redirect.save_stdout() as stdout:
+        
+        old_report_result = par.report_result
+        par.report_result = report_result
+        
+        #old_report_liveness_result = par.report_liveness_result
+        par.report_liveness_result = report_liveness_result
+
+        old_report_bmc_depth = par.report_bmc_depth
+        par.report_bmc_depth = report_bmc_depth
+        
+        try:
+            yield
+        finally:
+            par.report_result = old_report_result
+            #~ par.report_liveness_result = report_liveness_result
+            par.report_bmc_depth = old_report_bmc_depth
+
+def proof_command_wrapper_internal(prooffunc, category_name, command_name, change, multi=False):
+
+    def wrapper(argv):
+        
+        usage = "usage: %prog [options] <aig_file>"
+    
+        parser = optparse.OptionParser(usage, prog=command_name)
+    
+        parser.add_option("-n", "--no_redirect", dest="noisy", action="store_true", default=False, help="don't redirect output")
+        parser.add_option("-d", "--current_dir", dest="current_dir", action="store_true", default=False, help="stay in current directory")
+
+        options, args = parser.parse_args(argv)
+        
+        if len(args) != 2:
+            parser.print_usage()
+            return 0
+            
+        aig_filename = os.path.abspath(args[1])
+
+        with replace_report_result(multi):
+
+            if not options.noisy:
+                pyabc.run_command('/pushredirect')
+                
+            if not options.current_dir:
+                pyabc.run_command('/pushdtemp')
+                
+            try:
+                for d in os.environ['PATH'].split(':'):
+                    bip = os.path.join(d, 'bip')
+                    if os.path.exists(bip):
+                        pyabc.run_command("load_plugin %s Bip"%bip)
+                        break
+
+                basename = os.path.basename( aig_filename )
+                shutil.copyfile(aig_filename, basename)
+                aig_filename = basename
+
+                result = prooffunc(aig_filename)
+                
+                par.cex_list = []
+            except:
+                result = None
+
+            if not multi:
+                
+                if result=="SAT":
+                    par.report_result(0,1)
+                elif result=="UNSAT":
+                    par.report_result(0,0)
+                elif type(result)==list and len(result)>0 and result[0] == "SAT":
+                    par.report_result(0,1)
+                elif type(result)==list and len(result)>0 and result[0] == "UNSAT":
+                    par.report_result(0,0)
+                else:
+                    par.report_result(0,2)
+
+            if not options.current_dir:
+                pyabc.run_command('/popdtemp')
+
+            if not options.noisy:
+                pyabc.run_command('/popredirect')
+
+        return 0
+    
+    pyabc.add_abc_command(wrapper, category_name, command_name, change)
+
+def proof_command_wrapper(prooffunc, category_name, command_name, change, multi=False):
+    def pf(aig_filename):
+        par.read_file_quiet(aig_filename)
+        return prooffunc()
+    return proof_command_wrapper_internal(pf, category_name, command_name, change, multi)
+
+proof_command_wrapper(par.sp,  'HWMCC13', '/super_prove_aiger',  0)
+proof_command_wrapper(par.simple,  'HWMCC13', '/simple_aiger',  0)
+proof_command_wrapper(par.simple_bip,  'HWMCC13', '/simple_bip_aiger',  0)
+proof_command_wrapper(par.simple_sat,  'HWMCC13', '/simple_sat_aiger',  0)
+proof_command_wrapper(par.mp,  'HWMCC13', '/multi_prove_aiger',  0, multi=True)
+
+def simple_liveness_prooffunc(aig_filename):
+    
+    import niklas
+    from pyaig import utils
+
+    def simplify(aiger_in, aiger_out):
+        
+        with niklas.temp_file_names(2, suffix='.aig') as tmp:
+
+            saved = utils.save_po_info(aiger_in, tmp[0])
+            
+            par.read_file_quiet(tmp[0])
+            
+            par.pre_simp()
+            
+            pyabc.run_command( 'write_aiger %s'%tmp[1] )
+
+            utils.restore_po_info( saved, tmp[1], aiger_out )
+            
+            return True
+        
+    def report_result(id, res):
+        
+        if res and 'result' in res:
+            result = res['result']
+            if result=='proved':
+                par.report_liveness_result(id, 0)
+                return True
+            elif result=='failed':
+                par.report_liveness_result(id, 1)
+                return True
+            
+        return False
+
+    try:
+        niklas.run_niklas_multi(aig_filename, simplify=simplify, report_result=report_result)
+    except:
+        import traceback
+        traceback.print_exc()
+
+proof_command_wrapper_internal( simple_liveness_prooffunc, "HWMCC13", "/simple_liveness_aiger", 0, multi=True)
diff --git a/abc-build/scripts/niklas.py b/abc-build/scripts/niklas.py
new file mode 100644
--- /dev/null
+++ b/abc-build/scripts/niklas.py
@@ -0,0 +1,191 @@
+import os
+import sys
+import time
+import tempfile
+import subprocess
+
+from contextlib import contextmanager
+
+import pyabc
+import pyabc_split
+
+@contextmanager
+def temp_file_names(N, suffix=""):
+    
+    files = []
+    
+    try:
+        
+        for i in xrange(N):
+            files.append( tempfile.NamedTemporaryFile(suffix=suffix) )
+            
+        yield [ f.name for f in files ]
+    
+    finally:
+        for f in files:
+            f.close()
+        
+def parse_bip_status(status):
+    
+    res = {}
+    
+    for line in open(status, 'r'):
+        
+        line = line.strip()
+        
+        colon = line.find(':')
+        
+        if colon < 0:
+            continue
+            
+        field = line[:colon]
+        data = line[colon+2:]
+        
+        res[field] = data
+    
+    return res
+
+def run_bip(args, aiger):
+
+    import redirect
+    with redirect.redirect():
+
+        with temp_file_names(1) as tmpnames:
+
+            args = [
+                'bip',
+                '-abc',
+                '-input=%s'%aiger,
+                '-output=%s'%tmpnames[0],
+            ] + args;
+            
+            rc = subprocess.call(args, preexec_fn=pyabc._set_death_signal)
+            
+            if rc!=0:
+                return None
+                
+            return parse_bip_status(tmpnames[0])
+
+from pyaig import AIG, read_aiger, write_aiger, utils
+
+def run_niklas_single(aiger, simplify, report_result, timeout=None):
+    
+    orig_args = [
+        [ ',live', '-k=l2s', '-eng=treb-abs' ],
+        [ ',live', '-k=inc' ],
+        [ ',live', '-k=l2s', '-eng=bmc' ],
+    ]
+    
+    simplified_args = [
+        [ ',live', '-k=inc' ],
+        [ ',live', '-k=l2s', '-eng=bmc' ],
+        [ ',live', '-k=l2s', '-eng=treb' ],
+    ]
+    
+    with temp_file_names(1, suffix='.aig') as simple_aiger:
+
+        orig_funcs = [ pyabc_split.defer(run_bip)(a, aiger) for a in orig_args ]
+        simplified_funcs = [ pyabc_split.defer(run_bip)(a, simple_aiger[0]) for a in simplified_args ]
+
+        with pyabc_split.make_splitter() as splitter:
+
+            sleep_id = splitter.fork_one( lambda : time.sleep(timeout ) ) if timeout else None
+            
+            ids = splitter.fork_all( orig_funcs )
+            kill_if_simplified = ids[1:]
+            
+            simplifier_id = splitter.fork_one( pyabc_split.defer(simplify)(aiger, simple_aiger[0]) )
+            
+            for id, res in splitter:
+                
+                print 'NIKLAS: process %d finished with'%id, res
+                
+                if id == sleep_id:
+                    print 'NIKLAS: timeout'
+                    return False
+                
+                elif id == simplifier_id:
+                    print 'NIKLAS: simplify ended'
+                    if not res:
+                        continue
+                    print 'NIKLAS: killing'
+                    splitter.kill(kill_if_simplified)
+                    splitter.fork_all( simplified_funcs )
+                    continue
+                    
+                elif report_result(res):
+                    print 'NIKLAS: RESULT'
+                    return True
+
+    return False
+
+def run_niklas_multi(aiger, simplify, report_result):
+    
+    with open(aiger, 'r') as fin:
+        aig = read_aiger( fin )
+        
+    n_j_pos = aig.n_justice()
+    assert n_j_pos > 0
+    
+    if n_j_pos==1:
+        return run_niklas_single( aiger, simplify, report_result=lambda res: report_result(0, res) )
+    
+    with temp_file_names(n_j_pos, suffix='.aig') as single_aiger:
+        
+        def extract(j_po):
+            with open(single_aiger[j_po], 'w') as fout:
+                write_aiger(utils.extract_justice_po(aig, j_po), fout)
+                
+        for _ in pyabc_split.split_all_full( [pyabc_split.defer(extract)(i) for i in xrange(n_j_pos) ] ):
+            pass
+            
+        unsolved = set( xrange(n_j_pos) )
+        
+        timeout = 1
+        
+        while unsolved:
+            for j_po in sorted(unsolved):
+                if run_niklas_single( single_aiger[j_po], simplify, report_result=lambda res: report_result(j_po, res), timeout=timeout ):
+                    unsolved.remove(j_po)
+            timeout *= 2
+        
+    return not unsolved
+    
+if __name__ == "__main__":    
+
+    def simplify(aiger_in, aiger_out):
+
+        with temp_file_names(2, suffix='.aig') as tmp:
+
+            saved = utils.save_po_info(aiger_in, tmp[0])
+
+            pyabc.run_command( 'read_aiger %s'%tmp[0] )
+            pyabc.run_command( 'dc2 ; dc2 ; dc2 ; dc2' )
+            pyabc.run_command( 'write_aiger %s'%tmp[1] )
+
+            utils.restore_po_info( saved, tmp[1], aiger_out )
+            
+        return True
+
+    def report_result(id, res):
+        
+        if res and 'result' in res:
+            result = res['result']
+            if result=='proved':
+                print "PROVED: ", id
+                return True
+            elif result=='failed':
+                print "FAILED:", id
+                return True
+            
+        return False
+        
+    aiger = "test.aig"
+
+    while True:
+        try:
+            run_niklas_multi(aiger, simplify=simplify, report_result=report_result)
+        except:
+            import traceback
+            traceback.print_exc()
+
diff --git a/abc-build/scripts/par.py b/abc-build/scripts/par.py
new file mode 100644
--- /dev/null
+++ b/abc-build/scripts/par.py
@@ -0,0 +1,8151 @@
+from pyabc import *
+import pyabc_split
+import redirect
+import sys
+import os
+import time
+import math
+import main
+import filecmp
+
+
+global G_C,G_T,latches_before_abs,latches_before_pba,n_pos_before,x_factor,methods,last_winner
+global last_cex,JV,JP, cex_list,max_bmc, last_cx, pord_on, trim_allowed, temp_dec, abs_ratio, ifbip
+global if_no_bip, gabs, gla, sec_options,last_gasp_time, abs_ref_time, bmcs1, total_spec_refine_time
+global last_gap
+
+"""
+The functions that are currently available from module _abc are:
+
+int n_ands();
+int n_pis();
+int n_pos();
+int n_latches();
+int n_bmc_frames();
+int prob_status(); 1 = unsat, 0 = sat, -1 = unsolved
+int cex_get()
+int cex_put()
+int run_command(char* cmd);
+int n_nodes();
+int n_levels();
+
+bool has_comb_model();
+bool has_seq_model();
+bool is_true_cex();
+bool is_valid_cex();
+  return 1 if the number of PIs in the current network and in the current counter-example are equal
+int  n_cex_pis();
+  return the number of PIs in the current counter-example
+int  n_cex_regs();
+  return the number of flops in the current counter-example
+int  cex_po();
+  returns the zero-based output PO number that is SAT by cex
+int  cex_frame();
+  return the zero-based frame number where the outputs is SAT
+The last four APIs return -1, if the counter-example is not defined. 
+""" 
+#global variables
+#________________________________________________
+stackno_gabs = stackno_gore = stackno_greg= 0
+STATUS_UNKNOWN = -1
+STATUS_SAT = 0
+STATUS_UNSAT = 1
+RESULT = ('SAT', 'SAT', 'UNSAT', 'UNDECIDED', 'UNDECIDED', 'ERROR')
+Sat = Sat_reg = 0
+Sat_true = 1
+Unsat = 2
+Undecided = Undecided_reduction = 3
+Undecided_no_reduction = 4
+Error = 5
+Restart = 6
+xfi = x_factor = 1  #set this to higher for larger problems or if you want to try harder during abstraction
+max_bmc = -1
+last_time = 0
+j_last = 0
+seed = 113
+init_simp = 1
+temp_dec = True
+ifpord1 = 1
+K_backup = init_time = 0
+last_verify_time = 20
+last_cex = last_winner = 'None'
+last_cx = 0
+trim_allowed = True
+pord_on = False
+sec_sw = False
+sec_options = ''
+cex_list = []
+TERM = 'USL'
+last_gasp_time = 10000
+last_gasp_time = 500
+last_gasp_time = 900 #set to conform to hwmcc12
+use_pms = True
+
+#gabs = False #use the gate refinement method after vta
+#abs_time = 100
+
+####################################
+#default abstraction methods
+gabs = False #False = use gla refinement, True = use reg refinement.
+gla = True #use gla_abs instead of vta_abs
+##abs_time = 10000 #number of sec before initial abstraction terminates.
+abs_time = 150
+abs_time = 5000
+abs_time = 500
+abs_time = 100
+abs_ref_time = 50 #number of sec. allowed for abstraction refinement.
+total_spec_refine_time = 150
+ifbip = 0 # sets the abtraction method to vta or gla, If = 1 then uses ,abs
+if_no_bip = False #True sets it up so it can't use bip and reachx commands.
+abs_ratio = .5 #this controls when abstraction is too big and gives up
+#####################################
+
+def abstr_a(t1=200,t2=200,absr=0):
+    global abs_time, abs_ref_time, abs_ratio
+    if not absr == 0:
+        abs_ratio_old = abs_ratio
+        abs_ratio = absr
+    abs_time = t1
+    abs_ref_time = t2
+    abstracta(False)
+    if not absr == 0:
+        abs_ratio = abs_ratio_old
+
+t_init = 2 #initial time for poor man's concurrency.
+
+def set_global(s=''):
+    global G_C,G_T,latches_before_abs,latches_before_pba,n_pos_before,x_factor,methods,last_winner
+    global last_cex,JV,JP, cex_list,max_bmc, last_cx, pord_on, trim_allowed, temp_dec, abs_ratio, ifbip
+    global if_no_bip, gabs, gla, sec_options,last_gasp_time,abs_ref_time, abs_time,use_pms
+    exec(s)
+
+
+methods = ['PDR', 'INTRP', 'BMC', 'SIM', 'REACHX',
+           'PRE_SIMP', 'simple', 'PDRM', 'REACHM', 'BMC3','Min_Retime',
+           'For_Retime','REACHP','REACHN','PDR_sd','prove_part_2',
+           'prove_part_3','verify','sleep','PDRM_sd','prove_part_1',
+           'run_parallel','INTRPb', 'INTRPm', 'REACHY', 'REACHYc','RareSim','simplify', 'speculate',
+           'quick_sec', 'BMC_J', 'BMC2', 'extract -a', 'extract', 'PDRa', 'par_scorr', 'dsat', 'iprove']
+#'0.PDR', '1.INTERPOLATION', '2.BMC', '3.SIMULATION',
+#'4.REACHX', '5.PRE_SIMP', '6.simple', '7.PDRM', '8.REACHM', 9.BMC3'
+# 10. Min_ret, 11. For_ret, 12. REACHP, 13. REACHN 14. PDRseed 15.prove_part_2,
+#16.prove_part_3, 17.verify, 18.sleep, 19.PDRMm, 20.prove_part_1,
+#21.run_parallel, 22.INTRP_bwd, 23. Interp_m 24. REACHY 25. REACHYc 26. Rarity Sim 27. simplify
+#28. speculate, 29. quick_sec, 30 bmc3 -S, 31. BMC2 32. extract -a 33. extract 34. pdr_abstract
+#35 par_scorr, 36. dsat, 37. iprove
+win_list = [(0,.1),(1,.1),(2,.1),(3,.1),(4,.1),(5,-1),(6,-1),(7,.1)]
+FUNCS = ["(pyabc_split.defer(pdr)(t))",
+##         "(pyabc_split.defer(abc)('&get;,pdr -vt=%f'%t))",
+         "(pyabc_split.defer(intrp)(t))",
+##         "(pyabc_split.defer(abc)('&get;,imc -vt=%f'%(t)))",
+##         "(pyabc_split.defer(abc)('&get;,imc-sofa -vt=%f'%(t)))",
+         "(pyabc_split.defer(bmc)(t))",
+##         "(pyabc_split.defer(abc)('&get;,bmc -vt=%f'%t))",
+         "(pyabc_split.defer(simulate)(t))",
+         "(pyabc_split.defer(reachx)(t))",
+##         "(pyabc_split.defer(abc)('reachx -t %d'%t))",
+         "(pyabc_split.defer(pre_simp)())",
+##         "(pyabc_split.defer(super_prove)(2))",
+         "(pyabc_split.defer(simple)(t))",
+         "(pyabc_split.defer(pdrm)(t))",
+         "(pyabc_split.defer(abc)('&get;&reachm -vcs -T %d'%t))",
+         "(pyabc_split.defer(bmc3)(t))",
+##         "(pyabc_split.defer(abc)('bmc3 -C 1000000 -T %f'%t))",
+         "(pyabc_split.defer(abc)('dretime;&get;&lcorr;&dc2;&scorr;&put;dretime'))",
+         "(pyabc_split.defer(abc)('dretime -m;&get;&lcorr;&dc2;&scorr;&put;dretime'))",
+         "(pyabc_split.defer(abc)('&get;&reachp -vr -T %d'%t))",
+         "(pyabc_split.defer(abc)('&get;&reachn -vr -T %d'%t))",
+##         "(pyabc_split.defer(abc)('&get;,pdr -vt=%f -seed=521'%t))",
+         "(pyabc_split.defer(pdrseed)(t))",
+         "(pyabc_split.defer(prove_part_2)())",
+         "(pyabc_split.defer(prove_part_3)())",
+         "(pyabc_split.defer(verify)(JV,t))",
+         "(pyabc_split.defer(sleep)(t))",
+         "(pyabc_split.defer(pdrmm)(t))",
+         "(pyabc_split.defer(prove_part_1)())",
+         "(pyabc_split.defer(run_parallel)(JP,t,'TERM'))",
+         "(pyabc_split.defer(abc)('&get;,imc -bwd -vt=%f'%t))",
+##         "(pyabc_split.defer(abc)('int -C 1000000 -F 10000 -K 2 -T %f'%t))",
+         "(pyabc_split.defer(intrpm)(t))",
+##         "(pyabc_split.defer(abc)('int -C 1000000 -F 10000 -K 1 -T %f'%t))",
+         "(pyabc_split.defer(reachy)(t))",
+##         "(pyabc_split.defer(abc)('&get;&reachy -v -T %d'%t))",
+         "(pyabc_split.defer(abc)('&get;&reachy -cv -T %d'%t))",
+         "(pyabc_split.defer(simulate2)(t))",
+         "(pyabc_split.defer(simplify)())",
+         "(pyabc_split.defer(speculate)())",
+         "(pyabc_split.defer(quick_sec)(t))",
+         "(pyabc_split.defer(bmc_j)(t))",
+##         "(pyabc_split.defer(abc)('bmc2 -C 1000000 -T %f'%t))",
+         "(pyabc_split.defer(bmc2)(t))",
+         "(pyabc_split.defer(extractax)('a'))",
+         "(pyabc_split.defer(extractax)())",
+         "(pyabc_split.defer(pdra)(t))",
+         "(pyabc_split.defer(pscorr)(t))",
+         "(pyabc_split.defer(dsat)(t))",
+         "(pyabc_split.defer(iprove)(t))"
+         ]
+##         "(pyabc_split.defer(abc)('bmc3 -C 1000000 -T %f -S %d'%(t,int(1.5*max_bmc))))"
+#note: interp given 1/2 the time.
+
+## Similar engines below listed in the order of priority, high to low.
+allreachs = [4,8,12,13,24,25]
+allreachs = [24,4]
+reachs = [24]
+##allpdrs = [14,7,34,19,0]
+allpdrs = [34,7,14,19,0]
+allpdrs2 = [34,7,14,19,0]
+pdrs = [34,7,14,0]
+allbmcs = [9,30,2,31]
+exbmcs = [2,9,31]
+bmcs = [9,30]
+bmcs1 = [9]
+allintrps = [23,1,22]
+bestintrps = [23]
+##intrps = [23,1]
+intrps = [23,1] #putting ,imc-sofa first for now to test
+allsims = [26,3]
+sims = [26] 
+allslps = [18]
+slps = [18]
+imc1 = [1]
+pre = [5]
+combs = [36,37]
+
+JVprove = [7,23,4,24]
+JV = pdrs+intrps+bmcs+sims #sets what is run in parallel '17. verify' above
+JP = JV + [27] # sets what is run in  '21. run_parallel' above 27 simplify should be last because it can't time out.
+#_____________________________________________________________
+
+
+# Function definitions:
+# simple functions: ________________________________________________________________________
+# set_globals, abc, q, x, has_any_model, is_sat, is_unsat, push, pop
+
+# ALIASES
+
+def initialize():
+    global xfi, max_bmc, last_time,j_last, seed, init_simp, K_backup, last_verify_time
+    global init_time, last_cex, last_winner, trim_allowed, t_init, sec_options, sec_sw
+    global n_pos_before, n_pos_proved, last_cx, pord_on, temp_dec, abs_time, gabs, gla,m_trace
+    global smp_trace,hist,init_initial_f_name, skip_spec, t_iter_start,last_simp, final_all, scorr_T_done
+    global last_gap
+    xfi = x_factor = 1  #set this to higher for larger problems or if you want to try harder during abstraction
+    max_bmc = -1
+    last_time = 0
+    j_last = 0
+    seed = 113
+    init_simp = 1
+    temp_dec = True
+    K_backup = init_time = 0
+    last_verify_time = 20
+    last_cex = last_winner = 'None'
+    last_cx = 0
+    trim_allowed = True
+    pord_on = False
+    t_init = 2 #this will start sweep time in find_cex_par to 2*t_init here
+    sec_sw = False
+    sec_options = ''
+    smp_trace = m_trace = []
+    cex_list = []
+    n_pos_before = n_pos()
+    n_pos_proved = 0
+    abs_time = 150
+    abs_ref_time = 50 #number of sec. allowed for abstraction refinement.
+    total_spec_refine_time = 150
+    abs_ratio = .5
+    hist = []
+    skip_spec = False
+    t_iter_start = 0
+    inf = 10000000
+    last_simp = [inf,inf,inf,inf]
+    final_all = 1
+    scorr_T_done = 0
+    last_gap = 0
+##    abs_time = 100
+##    gabs = False
+##    abs_time = 500
+##    gabs = True
+
+    
+
+def set_abs_method():
+    """ controls the way we do abstraction, 0 = no bip, 1 = old way, 2 use new bip and -dwr
+    see absab()
+    """
+    global ifbip, abs_time,gabs,gla,if_no_bip
+    print 'current values ifbip = %d, abs_time = %d'%(ifbip,abs_time)
+    print 'Set method of abstraction: \n0 = vta for 500 and gla refin., \n1 = old way, \n2 = ,abs and -dwr, \n3 = vta for 100 followed by gla refine.,\n4 = vta for 500 then gla refine. but no bip methods gla refine., \n5 = gla and gla refine.'
+    s = raw_input()
+    s = remove_spaces(s)
+    if s == '1': #use the old way with ,abs but no dwr
+        ifbip = 1 #old way
+        abs_time = 100
+        if_no_bip = False
+        gabs = True
+        gla = False
+    elif s == '0':#use vta and gla refinement
+        ifbip = 0 
+        abs_time = 500
+        if_no_bip = False
+        gabs = False
+        gla = False
+    elif s == '2':  #use ,abc -dwr
+        ifbip = 2 
+        abs_time = 100
+        if_no_bip = False
+        gabs = True #use register refinement
+        gla = False
+    elif s == '3': #use vta and gla refinement
+        ifbip = 0
+        abs_time = 100
+        if_no_bip = False
+        gabs = False
+        gla = False
+    elif s == '4': #use vta, gla refine. and no bip
+        ifbip = 0
+        abs_time = 100
+        if_no_bip = True
+        gabs = True
+        gla = False
+    elif s == '5': #use gla and gla_refinement
+        ifbip = 0
+        abs_time = 100
+        if_no_bip = False
+        gabs = False
+        gla = True
+    #should make any of the methods able to us no bip
+    print 'ifbip = %d, abs_time = %d, gabs = %d, if_no_bip = %d, gla = %d'%(ifbip,abs_time,gabs,if_no_bip,gla)
+    
+def ps():
+    print_circuit_stats()
+
+def iprove(t=100):
+    abc('iprove')
+
+def dsat(t=100):
+    abc('dsat')
+
+def n_real_inputs():
+    """This gives the number of 'real' inputs. This is determined by trimming away inputs that
+    have no connection to the logic. This is done by the ABC alias 'trm', which changes the current
+    circuit. In some applications we do not want to change the circuit, but just to know how may inputs
+    would go away if we did this. So the current circuit is saved and then restored afterwards."""
+##    abc('w %s_savetempreal.aig; logic; trim; st ;addpi'%f_name)
+    abc('w %s_savetempreal.aig'%f_name)
+    with redirect.redirect( redirect.null_file, sys.stdout ):
+##        with redirect.redirect( redirect.null_file, sys.stderr ):
+        reparam()
+    n = n_pis()
+    abc('r %s_savetempreal.aig'%f_name)
+    return n
+
+def timer(t):
+    btime = time.clock()
+    time.sleep(t)
+    print t
+    return time.clock() - btime
+
+def sleep(t):
+##    print 'Sleep time = %d'%t
+    time.sleep(t)
+    return Undecided
+        
+def abc(cmd):
+    abc_redirect_all(cmd)
+
+def abc_redirect( cmd, dst = redirect.null_file, src = sys.stdout ):
+    """This is our main way of calling an ABC function. Redirect, means that we suppress any output from ABC"""
+    with redirect.redirect( dst, src ):
+        return run_command( cmd )
+
+def abc_redirect_all( cmd ):
+    """This is our main way of calling an ABC function. Redirect, means that we suppress any output from ABC, including error printouts"""
+    with redirect.redirect( redirect.null_file, sys.stdout ):
+        with redirect.redirect( redirect.null_file, sys.stderr ):
+            return run_command( cmd )
+
+##def convert(t):
+##    t = int(t*100)
+##    return str(float(t)/100)
+
+def set_engines(N=0):
+    """
+    Called only when read_file is called.
+    Sets the MC engines that are used in verification according to
+    if there are 4 or 8 processors. if if_no_bip = 1, we will not use any bip and reachx engines
+    """
+    global reachs,pdrs,sims,intrps,bmcs,n_proc,abs_ratio,ifbip,bmcs1, if_no_bip, allpdrs,allbmcs
+    bmcs1 = [9] #BMC3
+    #for HWMCC we want to set N = 8
+    N = 8
+    if N == 0:
+        N = n_proc = 1+os.sysconf(os.sysconf_names["SC_NPROCESSORS_ONLN"])
+##        N = n_proc = 8 ### simulate 4 processors for HWMCC - turn this off a hwmcc.
+    else:
+        n_proc = N
+##    print 'n_proc = %d'%n_proc
+    if N <= 1:
+        reachs = [24]
+        pdrs = [7]
+##        bmcs = [30]
+        bmcs = [9]
+        intrps = []
+        sims = []
+        slps = [18]
+    elif N <= 2:
+        reachs = [24]
+        pdrs = [7]
+        bmcs = [30]
+        intrps = []
+        sims = []
+        slps = [18]
+    elif N <= 4:
+        reachs = [24] #reachy
+        pdrs = [7,34] #prdm pdr_abstract
+        if if_no_bip:
+            allpdrs = pdrs = [7,19] #pdrm pdrmm
+        bmcs = [9,30] #bmc3 bmc3 -S
+        intrps = [23] #unterp_m
+        sims = [26] #Rarity_sim
+        slps = [18] #sleep
+# 0.PDR, 1.INTERPOLATION, 2.BMC, 3.SIMULATION,
+# 4.REACHX, 5.PRE_SIMP, 6.simple, 7.PDRM, 8.REACHM, 9.BMC3
+# 10.Min_ret, 11.For_ret, 12.REACHP, 13.REACHN 14.PDRseed 15.prove_part_2,
+# 16.prove_part_3, 17.verify, 18.sleep, 19.PDRMm, 20.prove_part_1,
+# 21.run_parallel, 22.INTRP_bwd, 23.Interp_m 24.REACHY 25.REACHYc 26.Rarity Sim 27.simplify
+# 28.speculate, 29.quick_sec, 30.bmc3 -S, 31.BMC2 32.extract -a 33.extract 34.pdr_abstract
+# 35.par_scorr, 36.dsat, 37.iprove
+
+# BIPS = 0.PDR, 1.INTERPOLATION, 2.BMC, 14.PDRseed, 22.INTRP_bwd, 34.pdr_abstract
+#       also  reparam which uses ,reparam 
+
+    elif N <= 8: #used for HWMCC
+        reachs = [24] #REACHY
+        allpdrs = pdrs = [7,34,14] #PDRM pdr_abstract PDR_seed
+        intrps = [23,1] #Interp_m
+        allbmcs = bmcs = [9,30,31] #BMC3 bmc3 -S 
+        if if_no_bip:
+            allpdrs = pdrs = [7,19] #PDRM PDRMm
+            intrps = allintrps = [23] #Interp_m
+            bmcs = allbmcs = [2]
+        sims = [26] #Rarity_Sim
+        slps = [18] #sleep
+    else:
+        reachs = [24,4] #REACHY REACHX
+        pdrs = [7,34,14,19,0] #PDRM pdr_abstract PDR_seed PDRMm PDR
+        intrps = [23,1] #Interp_m INTERPOLATION
+        bmcs = allbmcs
+        if if_no_bip:
+            allpdrs = pdrs = [7,19] #PDRM PDRMm
+            intrps = allintrps = [23] #Interp_m
+            reachs = [24] #REACHY
+            bmcs = [9,30] #BMC3 bmc3 -S 
+        sims = [26] #Rarity_Sim
+        slps = [18] #sleep
+        
+def set_globals():
+    """This sets global parameters that are used to limit the resources used by all the operations
+    bmc, interpolation BDDs, abstract etc. There is a global factor 'x_factor' that can
+    control all of the various resource limiting parameters"""
+    global G_C,G_T,x_factor
+    nl=n_latches()
+    na=n_ands()
+    np = n_pis()
+    #G_C = min(500000,(3*na+500*(nl+np)))
+    G_C = x_factor * min(100000,(3*na+500*(nl+np)))
+    #G_T = min(250,G_C/2000)
+    G_T = x_factor * min(75,G_C/2000)
+    G_T = max(1,G_T)
+    #print('Global values: BMC conflicts = %d, Max time = %d sec.'%(G_C,G_T))
+    
+def a():
+    """this puts the system into direct abc input mode"""
+    print "Entering ABC direct-input mode. Type q to quit ABC-mode"
+    n = 0
+    while True:
+        print '     abc %d> '%n,
+        n = n+1
+        s = raw_input()
+        if s == "q":
+            break
+        run_command(s)
+
+def remove_spaces(s):
+    y = ''
+    for t in s:
+        if not t == ' ':
+            y = y + t
+    return y
+
+def seq_name(f):
+    names = []
+    f = f + '_'
+    names = []
+    while len(f)>0:
+        j = f.find('_')
+        if j == -1:
+            break
+        names = names + [f[:j]]
+##        print names
+        f = f[j+1:]
+##        print f
+    return names
+
+def revert(f,n):
+    l = seq_name(f)
+    for j in range(n):
+        if len(l)>0:
+            l.pop()
+    name = construct(l)
+    return name
+
+def n_eff_pos():
+    N=n_pos()
+    l=len(list_0_pos())
+    return N-l
+
+def construct(l):
+    ll = l
+    name = ''
+    while len(l)>0:
+        name = '_'+ll.pop()+name
+    return name[1:]
+
+def process_sat():
+    l = seq_name(f_name)
+
+def add_trace(s):
+    global m_trace
+    m_trace = m_trace + [s] 
+
+def read_file_quiet_i(fname=None):
+    """ this preserves t_inter_start and is called internally by some functons."""
+    global t_iter_start
+    ts = t_iter_start
+    read_file_quiet(fname)
+    t_iter_start = ts
+
+def read_file_quiet(fname=None):
+    """This is the main program used for reading in a new circuit. The global file name is stored (f_name)
+    Sometimes we want to know the initial starting name. The file name can have the .aig extension left off
+    and it will assume that the .aig extension is implied. This should not be used for .blif files.
+    Any time we want to process a new circuit, we should use this since otherwise we would not have the
+    correct f_name."""
+    global max_bmc,  f_name, d_name, initial_f_name, x_factor, init_initial_f_name, win_list,seed, sec_options
+    global win_list, init_simp, po_map, aigs, hist, init_initial_f_name
+    abc('fraig_restore') #clear out any residual fraig_store
+    set_engines() #temporary
+    init_simp = 1
+    win_list = [(0,.1),(1,.1),(2,.1),(3,.1),(4,.1),(5,-1),(6,-1),(7,.1)] #initialize winning engine list
+    po_map = range(n_pos())
+    initialize()
+##    x_factor = 1
+##    seed = 223
+##    max_bmc = -1
+    if fname is None:
+        print 'Type in the name of the aig file to be read in'
+        s = raw_input()
+        s = remove_spaces(s)
+##        print s
+    else:
+        s = fname
+    if s[-4:] == '.aig':
+        f_name = s[:-4]
+    elif s[-5:] == '.blif':
+        f_name = s[:-5]
+    else:
+        f_name = s
+        s = s+'.aig'
+##    run_command(s)
+##    print s
+    if s[-4:] == '.aig':
+##        run_command('&r %s;&put'%s) #warning: changes names to generic ones.
+        run_command('r %s'%s)
+        run_command('zero')
+    else: #this is a blif file
+        run_command('r %s'%s)
+        abc('st;&get;&put') #changes names to generic ones for doing cec later.
+        run_command('zero;w %s.aig'%f_name)
+    set_globals()
+    hist = []
+    init_initial_f_name = initial_f_name = f_name
+    run_command('fold') #only does something if some of the outputs are constraints.
+    aigs_pp('push','initial')
+    #aigs = create push/pop history of aigs
+    #aigs.push() put the initial aig on the aig list.
+    print 'Initial f_name = %s'%f_name
+    abc('addpi') #only does something if there are no PIs
+    #check_pos() #this removes constant outputs with a warning -
+    #needed when using iso. Need another fix for using iso.
+    ps()
+    return
+
+def aigs_pp(op='push', typ='reparam'):
+    global hist,init_initial_f_name
+##    print hist
+    if op == 'push':
+        hist.append(typ)
+        abc('w %s_aigs_%d.aig'%(init_initial_f_name,len(hist)))
+    if op == 'pop':
+        abc('cexsave') #protect current cex from a read
+        abc('r %s_aigs_%d.aig'%(init_initial_f_name,len(hist)))
+        abc('cexload')
+        typ = hist.pop()
+##    print hist
+    return typ
+
+def scl():
+    abc('&get;&scl;&put')
+    ps()
+
+def cex_trim_g(F_init=0,tail=0,m=''):
+    abc('w %s_cex.aig'%f_name)
+    N=cex_frame()
+    G = N - tail
+    F = F_init
+    abc('cexsave')
+    while True:
+        print 'F = %d, G = %d'%(F,G)
+        abc('r %s_cex.aig'%f_name)
+        abc('cexload')
+        if m == '':
+            abc('cexcut -F %d -G %d'%(F,G))
+        else:
+            abc('cexcut -m -F %d -G %d'%(F,G))
+##        abc('drw')
+##        ps()
+        res = run_parallel(slps+bmcs,20)
+##        run_command('bmc2 -v -T 20')
+##        if is_sat(): #got a shortening of cex
+        if not res == Undecided:
+            Nb = cex_frame() #size of shortcut
+            abc('cexmerge -F %d -G %d'%(F,G))
+            abc('r %s_cex.aig'%f_name)
+            abc('cexload')
+            abc('testcex -a')
+            if cex_po() <0:
+                return 'ERROR2'
+            Nt=cex_frame() #current cex length
+            print 'Cex length reduced from %d to %d'%(N,Nt)
+            return
+        F = F + (G-F)/2
+##        G = N - i*delta
+        if F >= G:
+           return
+
+def cex_trim(factor=1):
+    t_begin = time.time()
+    abc('w %s_cex.aig'%f_name)
+    N=cex_frame()
+    inc = min(N/10,100)
+    F = 0
+    G = inc
+    abc('cexsave')
+    abc('cexcut -n -F %d -G %d'%(F,G))
+    run_command('bmc2 -v -F %d -T 5'%(.9*inc))
+    inc = max(int(factor*n_bmc_frames()),2)
+    F = N - inc
+    G = N
+    print 'inc = %d'%inc
+    while True:
+        abc('r %s_cex.aig'%f_name)
+        abc('cexload')
+        abc('cexcut -n -F %d -G %d'%(F,G))
+##        abc('drw')
+##        ps()
+##        run_command('bmc2 -v -F %d -T 20'%(.9*inc))
+        run_parallel(slps+bmcs,10)
+        if not is_sat():
+            abc('cex_load') #leave current cex in buffer
+            Nb = inc
+        else:
+            Nb = cex_frame() #size of shortcut
+            abc('cexmerge -F %d -G %d'%(F,G))
+        abc('r %s_cex.aig'%f_name)
+        abc('cexload')
+        abc('testcex -a')
+        if cex_po() <0:
+            return 'ERROR2'
+##        abc('cexload')
+        Nt=cex_frame() #current cex length
+        print 'Cex length = %d'%Nt
+        G=F
+        F = max(0,F - inc)
+        print 'F = %d, G = %d'%(F,G)
+        if G <= 2:
+            abc('cexload')
+            print 'Time: %0.2f'%(time.time() - t_begin) 
+            return
+    
+        
+def read_file():
+    global win_list, init_simp, po_map
+    read_file_quiet()
+##    ps()
+##    init_simp = 1
+##    win_list = [(0,.1),(1,.1),(2,.1),(3,.1),(4,.1),(5,-1),(6,-1),(7,.1)] #initialize winning engine list
+##    po_map = range(n_pos())
+
+def rf():
+##    set_engines(4) #temporary
+    read_file()
+    abc('zero')
+
+def write_file(s):
+    """this is the main method for writing the current circuit to an AIG file on disk.
+    It manages the name of the file, by giving an extension (s). The file name 'f_name'
+    keeps increasing as more extensions are written. A typical sequence is
+    name, name_smp, name_smp_abs, name_smp_abs_spec, name_smp_abs_spec_final"""
+    global f_name
+    """Writes out the current file as an aig file using f_name appended with argument"""
+    f_name = '%s_%s'%(f_name,s)
+    ss = '%s.aig'%(f_name)
+    print 'WRITING %s: '%ss,
+    ps()
+    abc('w '+ss)
+
+def bmc_depth():
+    """ Finds the number of BMC frames that the latest operation has used. The operation could be BMC, reachability
+    interpolation, abstract, speculate. max_bmc is continually increased. It reflects the maximum depth of any version of the circuit
+    including g ones, for which it is known that there is not cex out to that depth."""
+    global max_bmc
+    c = cex_frame()
+    if c > 0:
+        b = c-1
+    else:
+        b = n_bmc_frames()
+    if b > max_bmc:
+        max_bmc = b
+        report_bmc_depth(max_bmc)
+    return max_bmc
+
+def null_status():
+    """ resets the status to the default values but note that the &space is changed"""
+    abc('&get;&put')
+
+def set_max_bmc(b):
+    """ Keeps increasing max_bmc which is the maximum number of time frames for
+    which the current circuit is known to be UNSAT for"""
+    global max_bmc
+    if b > max_bmc:
+        max_bmc = b
+        report_bmc_depth(max_bmc)
+
+def report_bmc_depth(m):
+    print 'u%d'%m
+
+def print_circuit_stats():
+    """Stardard way of outputting statistice about the current circuit"""
+    global max_bmc
+    i = n_pis()
+    o = n_pos()
+    l = n_latches()
+    a = n_ands()
+    s='ANDs'
+    if a == -1:
+        a = n_nodes()
+        s = 'Nodes'
+##    b = max(max_bmc,bmc_depth()) # don't want to do this because bmc_depth can change max_bmc
+    b = max_bmc
+    c = cex_frame()
+    if b>= 0:
+        if c>=0:
+            print 'PIs=%d,POs=%d,FF=%d,%s=%d,max depth=%d,CEX depth=%d'%(i,o,l,s,a,b,c)
+        elif is_unsat():
+            print 'PIs=%d,POs=%d,FF=%d,%s=%d,max depth = infinity'%(i,o,l,s,a)
+        else:
+            print 'PIs=%d,POs=%d,FF=%d,%s=%d,max depth=%d'%(i,o,l,s,a,b)            
+    else:
+        if c>=0:
+            print 'PIs=%d,POs=%d,FF=%d,%s=%d,CEX depth=%d'%(i,o,l,s,a,c)
+        else:
+            print 'PIs=%d,POs=%d,FF=%d,%s=%d'%(i,o,l,s,a)
+
+def is_unsat():
+    if prob_status() == 1:
+        return True
+    else:
+        return False
+
+def is_sat():
+    if prob_status() == 0:
+        return True
+    else:
+        return False
+
+def wc(file):
+    """writes <file> so that costraints are preserved explicitly"""
+    abc('&get;&w %s'%file)
+
+def rc(file):
+    """reads <file> so that if constraints are explicit, it will preserve them"""
+    abc('&r -s %s;&put'%file)                         
+
+#more complex functions: ________________________________________________________
+#, abstract, pba, speculate, final_verify, dprove3
+
+def timer(s):
+    btime = time.clock()
+    abc(s)
+    print 'time = %0.2f'%(time.clock() - btime)
+
+def med_simp():
+    x = time.time()
+    abc("&get;&scl;&dc2;&lcorr;&dc2;&scorr;&fraig;&dc2;&put;dretime")
+    #abc("dc2rs")
+    ps()
+    print 'time = %0.2f'%(time.time() - x)
+
+def simplify_old(M=0):
+    """Our standard simplification of logic routine. What it does depende on the problem size.
+    For large problems, we use the &methods which use a simple circuit based SAT solver. Also problem
+    size dictates the level of k-step induction done in 'scorr' The stongest simplification is done if
+    n_ands < 20000. Then it used the clause based solver and k-step induction where |k| depends
+    on the problem size """
+    set_globals()
+    abc('&get;&scl;&lcorr;&put')
+    p_40 = False
+    n =n_ands()
+    if n >= 70000 and not '_smp' in f_name:
+##        abc('&get;&scorr -C 0;&put')
+        scorr_T(30)
+        ps()
+    n =n_ands()
+    if n >= 100000:
+        abc('&get;&scorr -k;&put')
+        ps()
+    if (70000 < n and n < 150000):
+##        print '1'
+        p_40 = True
+        abc("&get;&dc2;&put;dretime;&get;&lcorr;&dc2;&put;dretime;&get;&scorr;&fraig;&dc2;&put;dretime")
+##        print 2'
+        ps()
+        n = n_ands()
+##        if n<60000:
+        if n < 80000:
+            abc("&get;&scorr -F 2;&put;dc2rs")
+            ps()
+        else: # n between 60K and 100K
+            abc("dc2rs")
+            ps()
+    n = n_ands()
+##    if (30000 < n  and n <= 40000):
+    if (60000 < n  and n <= 70000):
+        if not p_40:
+            abc("&get;&dc2;&put;dretime;&get;&lcorr;&dc2;&put;dretime;&get;&scorr;&fraig;&dc2;&put;dretime")
+            abc("&get;&scorr -F 2;&put;dc2rs")
+            ps()
+        else:
+            abc("dc2rs")
+            ps()
+    n = n_ands()
+##    if n <= 60000:
+    if n <= 70000:
+        abc('scl -m;drw;dretime;lcorr;drw;dretime')
+        ps()
+        nn = max(1,n)
+        m = int(min( 70000/nn, 16))
+        if M > 0:
+            m = M
+        if m >= 1:
+            j = 1
+            while j <= m:
+                set_size()
+                if j<8:
+                    abc('dc2')
+                else:
+                    abc('dc2rs')
+                abc('scorr -C 1000 -F %d'%j) #was 5000 temporarily 1000
+                if check_size():
+                    break
+                j = 2*j
+                print 'ANDs=%d,'%n_ands(),
+                if n_ands() >= .98 * nands:
+                     break
+                continue
+            if not check_size():
+                print '\n'
+    return get_status()
+
+def simplify(M=0,N=0):
+    """Our standard simplification of logic routine. What it does depende on the problem size.
+    For large problems, we use the &methods which use a simple circuit based SAT solver. Also problem
+    size dictates the level of k-step induction done in 'scorr' The stongest simplification is done if
+    n_ands < 20000. Then it used the clause based solver and k-step induction where |k| depends
+    on the problem size
+    Does not change #PIs.
+    """
+    global smp_trace
+    set_globals()
+    smp_trace = smp_trace + ['&scl;&lcorr']
+    abc('&get;&scl;&lcorr;&put')
+    p_40 = False
+    n =n_ands()
+    if N == 0 and n >= 70000 and not '_smp' in f_name:
+##        abc('&get;&scorr -C 0;&put')
+##        print 'Trying scorr_T'
+        scorr_T(30)
+        ps()
+    n =n_ands()
+    if n >= 100000:
+        smp_trace = smp_trace + ['&scorr']
+        abc('&get;&scorr -k;&put')
+        ps()
+    if (70000 < n and n < 150000):
+        p_40 = True
+        smp_trace = smp_trace + ['&dc2;dretime;&lcorr;&dc2;dretime;&scorr;&fraig;&dc2;dretime']
+        abc("&get;&dc2;&put;dretime;&get;&lcorr;&dc2;&put;dretime;&get;&scorr;&fraig;&dc2;&put;dretime")
+        ps()
+    n = n_ands()
+##    if (30000 < n  and n <= 40000):
+    if (60000 < n  and n <= 70000):
+        if not p_40:
+            smp_trace = smp_trace + ['&dc2;dretime;&lcorr;&dc2;dretime;&scorr;&fraig;&dc2;dretime']
+            abc("&get;&dc2;&put;dretime;&get;&lcorr;&dc2;&put;dretime;&get;&scorr;&fraig;&dc2;&put;dretime")
+            smp_trace = smp_trace + ['&scorr -F 2;dc2rs']
+            abc("&get;&scorr -F 2;&put;dc2rs")
+            ps()
+        else:
+            abc("dc2rs")
+            smp_trace = smp_trace + ['dc2rs']
+            ps()
+    n = n_ands()
+##    if n <= 60000:
+    if n <= 70000:
+        smp_trace = smp_trace + ['scl -m;drw;dretime;lcorr;drw;dretime']
+        abc('scl -m;drw;dretime;lcorr;drw;dretime')
+        ps()
+        nn = max(1,n)
+        m = int(min( 70000/nn, 16))
+        if M > 0:
+            m = M
+        if N == 0 and m >= 1:
+            j = 1
+            while j <= m:
+                set_size()
+                if j<8:
+                    abc('dc2')
+                else:
+                    abc('dc2rs')
+                smp_trace = smp_trace + ['scorr -F %d'%j]
+                abc('scorr -C 1000 -F %d'%j) #was 5000 temporarily 1000
+                if check_size():
+                    break
+                j = 2*j
+                print 'ANDs=%d,'%n_ands(),
+                if n_ands() >= .98 * nands:
+                     break
+                continue
+            if not check_size():
+                print '\n'
+    return get_status()
+            
+def simulate2(t=900):
+    """Does rarity simulation. Simulation is restricted by the amount
+    of memory it might use. At first wide but shallow simulation is done, followed by
+    successively more narrow but deeper simulation. 
+    seed is globally initiallized to 113 when a new design is read in"""
+    global x_factor, f_name, tme, seed
+    btime = time.clock()
+    tt = time.time()
+    diff = 0
+    while True:
+        f = 20
+        w = 64
+        b = 16
+        r = 700
+        for k in range(9): #this controls how deep we go
+            f = min(f*2, 3500)
+            w = max(((w+1)/2)-1,1)
+            abc('sim3 -F %d -W %d -N %d -R %d -B %d'%(f,w,seed,r,b))
+            seed = seed+23
+            if is_sat():
+##                print 'RareSim time = %0.2f at frame %d'%((time.time() - tt),cex_frame())
+                return 'SAT'
+            if ((time.clock()-btime) > t):
+                return 'UNDECIDED'
+
+def simulate(t=900):
+    abc('&get')
+    result = eq_simulate(t)
+    return result
+
+def eq_simulate(t):
+    """Simulation is restricted by the amount
+    of memory it might use. At first wide but shallow simulation is done, followed by
+    successively more narrow but deeper simulation. The aig to be simulated must be in the & space
+    If there are equivalences, it will refine them. Otherwise it is a normal similation
+    seed is globally initiallized to 113 when a new design is read in"""
+    global x_factor, f_name, tme, seed
+    btime = time.clock()
+    diff = 0
+    while True:
+        f = 5
+        w = 255
+        for k in range(9):
+            f = min(f *2, 3500)
+            r = f/20
+            w = max(((w+1)/2)-1,1)
+##            abc('&sim3 -R %d -W %d -N %d'%(r,w,seed))
+            abc('&sim -F %d -W %d -N %d'%(f,w,seed))
+            seed = seed+23
+            if is_sat():
+                return 'SAT'
+            if ((time.clock()-btime) > t):
+                return 'UNDECIDED'
+
+def generate_abs(n):
+    """generates an abstracted  model (gabs) from the greg file or gla. The gabs file is automatically
+    generated in the & space by &abs_derive or gla_derive. We store it away using the f_name of the problem
+    being solved at the moment. The f_name keeps changing with an extension given by the latest
+    operation done - e.g. smp, abs, spec, final, group. """
+    global f_name
+    #we have a cex and we use this generate a new gabs (gla) file
+    if gabs: #use the register refinement method
+        abc('&r -s %s_greg.aig; &abs_derive; &put; w %s_gabs.aig'%(f_name,f_name)) # do we still need the gabs file
+    else: #use the gate refinement method
+        run_command('&r -s %s_gla.aig; &gla_derive; &put'%f_name)
+        if n_ands() < 2000:
+            run_command('scl;scorr;dretime')
+        run_command('w %s_gabs.aig'%f_name)
+    if n == 1:
+        #print 'New abstraction: ',
+        ps()
+    return   
+
+def refine_with_cex():
+    """Refines the greg or gla file (which contains the original problem with the set of FF's or gates
+    that have been abstracted).
+    This uses the current cex to modify the greg or gla file to reflect which regs(gates) are in the
+    new current abstraction"""
+    global f_name
+    if gabs:
+        abc('&r -s %s_greg.aig;&w %s_greg_before.aig'%(f_name,f_name))
+        run_command('&abs_refine -s; &w %s_greg.aig'%f_name)
+    else:
+        run_command('&r -s %s_gla.aig;&w %s_gla_before.aig'%(f_name,f_name))
+        run_command('&gla_refine; &w %s_gla.aig'%f_name)
+    return
+
+def refine_with_cex_suffix():
+    """Refines the greg or gla file (which contains the original problem with the set of FF's or gates
+    that have been abstracted).
+    This uses the current cex to modify the greg or gla file to reflect which regs(gates) are in the
+    new current abstraction"""
+    global f_name
+    return Undecided_no_reduction
+    t = 5
+    cexf = cex_frame()
+    suf = .9*cexf
+    run_command('write_status %s_temp.status'%f_name)
+    ub = int(cexf -min(10, .02*cexf))
+    lb = int(min(10,.02*cexf))
+    suf = int(.5*(ub-lb))
+    if_last = 0
+    N = 0
+    while True:
+        N = N+1
+        tt = time.time()
+        run_command('read_status %s_temp.status'%f_name)
+        print 'Refining using suffix %d with time = %d'%(suf,t)
+        run_command('&r -s %s_gla.aig;&w %s_gla_before.aig'%(f_name,f_name))
+        F = create_funcs([18],t) #create a timer function with timeout = t
+        F = F + [eval('(pyabc_split.defer(abc)("&gla_refine -F %d; &w %s_gla.aig"))'%(suf,f_name))]
+        for i,res in pyabc_split.abc_split_all(F): #need to do a binary search
+            if i == 0:  #timeout
+                lb = int(suf)
+                dec = 'increasing'
+                break
+            elif same_abs(): #suffix did not refine - need to decrease suf
+                ub = int(suf)
+                dec = 'decreasing'
+                break
+            else: #refinement happened
+                print 'refinement happened.'
+                return
+        print 'ub = %.2f, lb = %.2f, suf = %.2f'%(ub,lb,suf)
+        suf = int(lb+.5*(ub-lb))
+        if (ub-lb)< (max(1.1,min(10,.02*cexf))) or if_last or N >=4: # not refining in time allowed, give up
+            print '(ub-lb) = %0.2f'%(ub-lb)
+            print 'could not refine in resources allowed'
+            return Undecided_no_reduction
+    
+def same_abs():
+    run_command('r %s_gabs.aig'%f_name)
+    set_size()
+##    ps()
+    run_command('&r -s %s_gla.aig; &gla_derive; &put'%f_name)
+    if n_ands() < 2000:
+        run_command('scl;scorr;dretime')
+##    ps()
+    return check_size()
+
+def abstraction_refinement(latches_before,NBF,ratio=.75):
+    """Subroutine of 'abstract' which does the refinement of the abstracted model,
+    using counterexamples found by BMC, BDD reachability, etc"""
+    global x_factor, f_name, last_verify_time, x, win_list, last_winner, last_cex, t_init, j_last, sweep_time
+    global cex_list, last_cx, abs_ref_time
+    sweep_time = 2
+    T1 = time.time()
+    if NBF == -1:
+        F = 2000
+    else:
+        F = 2*NBF
+    print '\nIterating abstraction refinement'
+    add_trace('abstraction refinement')
+    J = slps+intrps+pdrs+bmcs+sims
+    J=modify_methods(J)
+    print sublist(methods,J)
+    last_verify_time = t = x_factor*max(50,max(1,2.5*G_T))
+##    t = 1000 #temporary
+    t = abs_time
+    initial_verify_time = last_verify_time = t
+    reg_verify = True
+    print 'Verify time set to %d'%last_verify_time
+    while True: #cex based refinement
+        generate_abs(1) #generate new gabs file from refined greg or gla file
+        set_globals()
+        latches_after = n_latches()
+        if small_abs(ratio):
+            print 'abstraction too large'
+            return Undecided_no_reduction
+        if (time.time() - T1)> abs_ref_time:
+            print 'abstraction time ran out'
+            break
+        t = last_verify_time
+        yy = time.time()
+        abc('w %s_beforerpm.aig'%f_name)
+        rep_change = reparam() #new - must do reconcile after to make cex compatible
+##        if rep_change:
+##            add_trace('reparam')
+        abc('w %s_afterrpm.aig'%f_name)
+##        if reg_verify:
+        status = verify(J,t)
+        print 'status = ',
+        print status
+##        else:
+##            status = pord_1_2(t)
+###############
+        if status[0] == Sat_true:
+            print 'Found true cex'
+            reconcile_a(rep_change)
+##            add_trace('SAT by %s'%status[1])
+            return Sat_true
+        if status[0] == Unsat:
+##            add_trace('UNSAT by %s'%status[1])      
+            return Unsat
+        if status[0] == Sat:
+##            add_trace('SAT by %s'%status[1])
+            abc('write_status %s_after.status'%f_name)
+            reconcile_a(rep_change) # makes the cex compatible with original before reparam and puts original in work space
+            abc('write_status %s_before.status'%f_name)
+            if gabs: #global variable
+                refine_with_cex()
+            else:
+                result = refine_with_cex_suffix()
+                if result == Sat:
+                    return Sat
+##                result = refine_with_cex()
+                if result == Undecided_no_reduction:
+                    return result
+            if is_sat(): # if cex can't refine, status is set to Sat_true
+                print 'Found true cex in output %d'%cex_po()
+                return Sat_true
+            else:
+                continue
+        else:
+            break
+    print '**** Latches reduced from %d to %d'%(latches_before, n_latches())
+    return Undecided_reduction
+
+def small_abs(ratio=.75):
+    """ tests is the abstraction is too large"""
+##    return ((rel_cost_t([pis_before_abs,latches_before_abs, ands_before_abs])> -.1)
+##           or (n_latches() >= ratio*latches_before_abs))
+    return (n_latches() >= ratio*latches_before_abs)
+
+##def abstract(if_bip=True):
+##    global ratio
+##    if if_bip:
+##        return abstractb(True) #old method using abstraction refinement
+##    else:
+##        return abstractb(False) #not using bip and reachx
+
+def abstractb():
+    """ abstracts using N Een's method 3 - cex/proof based abstraction. The result is further refined using
+    simulation, BMC or BDD reachability. abs_ratio is the the limit for accepting an abstraction"""
+    global G_C, G_T, latches_before_abs, x_factor, last_verify_time, x, win_list, j_last, sims
+    global latches_before_abs, ands_before_abs, pis_before_abs, abs_ratio
+    if ifbip < 1:
+        print 'using ,abs in old way'
+    tt = time.time()
+    j_last = 0
+    set_globals()
+    #win_list = []
+    latches_before_abs = n_latches()
+    ands_before_abs = n_ands()
+    pis_before_abs = n_real_inputs()
+    abc('w %s_before_abs.aig'%f_name)
+    print 'Start: ',
+    ps()
+    funcs = [eval('(pyabc_split.defer(initial_abstract)())')]
+    # fork off BMC3 and PDRm along with initial abstraction
+    t = 10000 #want to run as long as initial abstract takes.
+##    J = sims+pdrs+bmcs+intrps
+    J = slps+pdrs+bmcs+intrps
+    J = modify_methods(J,1)
+##    if n_latches() < 80:
+##        J = J + [4]
+    funcs = create_funcs(J,t) + funcs
+    mtds = sublist(methods,J) + ['initial_abstract'] #important that initial_abstract goes last
+    m,result = fork_last(funcs,mtds)
+    if is_sat():
+        print 'Found true counterexample in frame %d'%cex_frame()
+        return Sat_true
+    if is_unsat():
+        return Unsat
+##    set_max_bmc(NBF)
+    NBF = bmc_depth()
+    print 'Abstraction good to %d frames'%max_bmc
+    #note when things are done in parallel, the &aig is not restored!!!
+    abc('&r -s %s_greg.aig; &w initial_greg.aig; &abs_derive; &put; w initial_gabs.aig; w %s_gabs.aig'%(f_name,f_name))
+    set_max_bmc(NBF)
+    print 'Initial abstraction: ',
+    ps()
+    abc('w %s_init_abs.aig'%f_name)
+    latches_after = n_latches()
+##    if latches_after >= .90*latches_before_abs: #the following should match similar statement
+##    if ((rel_cost_t([pis_before_abs, latches_before_abs, ands_before_abs])> -.1) or
+##        (latches_after >= .75*latches_before_abs)):
+    if small_abs(abs_ratio):
+        abc('r %s_before_abs.aig'%f_name)
+        print "Too little reduction!"
+        print 'Abstract time wasted = %0.2f'%(time.time()-tt)
+        return Undecided_no_reduction
+    sims_old = sims
+    sims=sims[:1] #make it so that rarity sim is not used since it can't find a cex
+    result = abstraction_refinement(latches_before_abs, NBF,abs_ratio)
+    sims = sims_old
+    if result <= Unsat:
+        return result
+##    if n_latches() >= .90*latches_before_abs:
+##    if ((rel_cost_t([pis_before_abs, latches_before_abs, ands_before_abs])> -.1) or (latches_after >= .90*latches_before_abs)):
+##    if rel_cost_t([pis_before_abs,latches_before_abs, ands_before_abs])> -.1:
+    if small_abs(abs_ratio) or result == Undecided_no_reduction: #r is ratio of final to initial latches in abstraction. If greater then True
+        abc('r %s_before_abs.aig'%f_name) #restore original file before abstract.
+        print "Too little reduction!  ",
+        print 'Abstract time wasted = %0.2f'%(time.time()-tt)
+        result = Undecided_no_reduction
+        return result
+    #new
+    else:
+        write_file('abs') #this is only written if it was not solved and some change happened.
+    print 'Abstract time = %0.2f'%(time.time()-tt)
+    return result
+
+def initial_abstract_old():
+    global G_C, G_T, latches_before_abs, x_factor, last_verify_time, x, win_list
+    set_globals()
+    time = max(1,.1*G_T)
+    abc('&get;,bmc -vt=%f'%time)
+    set_max_bmc(bmc_depth())
+    c = 2*G_C
+    f = max(2*max_bmc,20)
+    b = min(max(10,max_bmc),200)
+    t = x_factor*max(1,2*G_T)
+    s = min(max(3,c/30000),10) # stability between 3 and 10 
+    cmd = '&get;,abs -bob=%d -stable=%d -timeout=%d -vt=%d -depth=%d'%(b,s,t,t,f)
+##    print cmd
+    print 'Running initial_abstract with bob=%d,stable=%d,time=%d,depth=%d'%(b,s,t,f)
+    abc(cmd)
+    abc('&w %s_greg.aig'%f_name)
+##    ps()
+
+def initial_abstract(t=100):
+    global G_C, G_T, latches_before_abs, x_factor, last_verify_time, x, win_list, max_bmc, ifbip
+    set_globals()
+    time = max(1,.1*G_T)
+    time = min(time,t)
+    abc('&get;,bmc -vt=%f'%time)
+    set_max_bmc(bmc_depth())
+    c = 2*G_C
+    f = max(2*max_bmc,20)
+    b = min(max(10,max_bmc),200)
+    t1 = x_factor*max(1,2*G_T)
+    t = max(t1,t)
+    s = min(max(3,c/30000),10) # stability between 3 and 10
+    cmd = '&get;,abs -bob=%d -stable=%d -timeout=%d -vt=%d -depth=%d'%(b,s,t,t,f)
+    if ifbip == 2:
+        cmd = '&get;,abs -bob=%d -stable=%d -timeout=%d -vt=%d -depth=%d -dwr=%s_vabs'%(b,s,t,t,f,f_name)
+        print 'Using -dwr=%s_vabs'%f_name
+##    print cmd
+    print 'Running initial_abstract with bob=%d,stable=%d,time=%d,depth=%d'%(b,s,t,f)
+    abc(cmd)
+    bmc_depth()
+##    pba_loop(max_bmc+1)
+    abc('&w %s_greg.aig'%f_name)
+    return max_bmc
+
+def abs_m():
+    set_globals()
+    y = time.time()
+    nl = n_abs_latches() #initial set of latches
+    c = 2*G_C
+    t = x_factor*max(1,2*G_T) #total time
+    bmd = bmc_depth()
+    if bmd < 0:
+        abc('bmc3 -T 2') #get initial depth estimate
+        bmd = bmc_depth()
+    f = bmd
+    abc('&get')
+    y = time.time()
+    cmd = '&abs_cba -v -C %d -T %0.2f -F %d'%(c,.8*t,bmd) #initial absraction
+##    print '\n%s'%cmd
+    abc(cmd)
+    b_old = b = n_bmc_frames()
+    f = min(2*bmd,max(bmd,1.6*b))
+    print 'cba: latches = %d, depth = %d'%(n_abs_latches(),b)
+##    print n_bmc_frames()
+    while True:
+        if (time.time() - y) > .9*t:
+            break
+        nal = n_abs_latches()
+        cmd = '&abs_cba -v -C %d -T %0.2f -F %d'%(c,.8*t,f) #f is 2*bmd and is the maximum number of frames allowed
+##        print '\n%s'%cmd
+        abc(cmd)
+##        print n_bmc_frames()
+        b_old = b
+        b = n_bmc_frames() 
+        nal_old = nal 
+        nal = n_abs_latches() #nal - nal_old is the number of latches added by cba
+        #b - b_old is the additional time frames added by cba
+        f = min(2*bmd,max(bmd,1.6*b))   #may be this should just be bmd
+        f = max(f,1.5*bmd)
+        print 'cba: latches = %d, depth = %d'%(nal,b)
+        if ((nal == nal_old) and (b >= 1.5*b_old) and b >= 1.5*bmd):
+            """
+            Went at least bmd depth and saw too many frames without a cex
+            (ideally should know how many frames without a cex)
+            """
+            print 'Too many frames without cex'
+            break
+        if b > b_old: #if increased depth
+            continue
+        if nal > .9*nl: # try to minimize latches
+##            cmd = '&abs_pba -v -S %d -F %d -T %0.2f'%(b,b+2,.2*t)
+            cmd = '&abs_pba -v -F %d -T %0.2f'%(b+2,.2*t)
+##            print '\n%s'%cmd
+            abc(cmd)
+            b = n_bmc_frames()
+            nal_old = nal
+            nal = n_abs_latches()
+            print 'pba: latches = %d, depth = %d'%(nal,b)
+##            print n_bmc_frames()
+            if nal_old < nal: #if latches increased there was a cex
+                continue
+            if nal > .9*nl: # if still too big 
+                return
+        continue 
+##    b = n_bmc_frames()
+    cmd = '&abs_pba -v -F %d -T %0.2f'%(b+2,.2*t)
+##    print '\n%s'%cmd
+    abc(cmd)
+    b = n_bmc_frames()
+    print 'pba: latches = %d, depth = %d'%(n_abs_latches(),b)
+##    print n_bmc_frames()
+    print 'Total time = %0.2f'%(time.time()-y)
+
+def n_abs_latches():
+    abc('&w pba_temp.aig') #save the &space
+    abc('&abs_derive;&put')
+    abc('&r -s pba_temp.aig')
+    return n_latches()
+        
+def pba_loop(F):
+    n = n_abs_latches()
+    while True:
+        run_command('&abs_pba -v -C 0 -F %d'%F)
+        abc('&w pba_temp.aig')
+        abc('&abs_derive;&put')
+        abc('&r -s pba_temp.aig')
+        N = n_latches()
+##        if n == N or n == N+1:
+##            break
+##        elif N > n:
+        if N > n:
+            print 'cex found'
+        break
+
+def ssm(options=''):
+    """ Now this should be the same as super_prove(1) """
+    y = time.time()
+    result = prove_part_1() # simplify first
+    if result == 'UNDECIDED':
+        result = ss(options)
+    print 'Total time taken on file %s by function ssm(%s) = %d sec.'%(initial_f_name,options,(time.time() - y))
+    return result
+
+def ssmg():
+    return ssm('g')
+def ssmf():
+    return ssm('f')
+
+
+def ss(options=''):
+    """
+    Alias for super_sec
+    This is the preferred command if the problem (miter) is suspected to be a SEC problem
+    """
+    global max_bmc, init_initial_f_name, initial_f_name,win_list, last_verify_time, sec_options
+    sec_options = options
+    print '\n*************Executing speculate************'
+    y = time.time()
+    abc('scl')
+    result = speculate()
+    # if result is 1 then it is a real SAT since we did not do anything before
+    if result > 2: #save the result and read in with /rf so that files are initialized correctly
+        if not '_spec' in f_name:
+            write_file('spec') #make sure we do not overwrite original file
+        read_file_quiet_i('%s'%f_name) #this resets f_name and initial_f_name etc.
+        print '\n*************Executing super_prove ************'
+        print 'New f_name = %s'%f_name
+        result = sp()
+        if result[0] == 'SAT':
+            result = 'UNDECIDED' #because speculation was done initially.
+    elif result[0] == 1:
+        result = 'SAT'
+    else:
+        result = RESULT[result]
+    print 'Total time taken on file %s by function ss(%s) = %d sec.'%(initial_f_name,options,(time.time() - y))
+    return result
+
+def quick_sec(t):
+##    fb_name = f_name[:-3]+'New'
+##    abc('&get;&miter -s %s.aig;&put'%fb_name)
+##    abc('w %s.%s_miter.aig'%(f_name,fb_name))
+    quick_simp()
+    verify(slps+ pdrs+bmcs+intrps,t)
+    if is_unsat():
+        return 'UNSAT'
+    if is_sat():
+        return 'SAT'
+    else:
+        return'UNDECIDED'
+
+def pre_sec():
+    """ put files to be compared into Old and New aigs. Simplify, but
+    turn off reparameterization so that PIs in Old and New match after simplification.
+    """
+    global trim_allowed
+##    trim_allowed = False
+##    print 'trim allowed = ',trim_allowed
+    print 'First file: ',
+    read_file_quiet_i() #note - reads into & space and then does &put
+    ps()
+    prs(False)
+    ps()
+    abc('&w Old.aig')
+    print 'Second file: ',
+    read_file_quiet_i()
+    ps()
+    prs(False)
+    ps()
+    abc('&w New.aig')
+        
+def cec():
+    print 'Type in the name of the aig file to be compared against'
+    s = raw_input()
+    s = remove_spaces(s)
+    if not 'aig' in s:
+        s = s+'.aig'
+    run_command("&get;&cec -v %s"%s)
+
+def sec(B_part,options):
+    """
+    Use this for AB filtering and not sup_sec
+    Use pp_sec to make easy names for A and B, namely Old and New.
+    This assumes that the original aig (renamed A_name below) is already read into the working space.
+    Then we form a miter using &miter between two circuits, A_name, and B_name.
+    We then do speculate immediately. Optionally we could simplify A and B
+    and then form the miter and start from there. The only difference in speculate
+    is that &srm2 is used, which only looks at equivalences where one comes from A and
+    one from B. Options are -a and -b which says use only flops in A or in B or both. The
+    switch sec_sw controls what speculate does when it generates the SRM.
+    """
+    global f_name,sec_sw, A_name, B_name, sec_options
+    yy = time.time()
+    A_name = f_name # Just makes it so that we can refer to A_name later in &srm2
+    B_name = B_part
+    run_command('&get; &miter -s %s.aig; &put'%B_name)
+##    abc('orpos')
+    f_name = A_name+'_'+B_name+'_miter' # reflect that we are working on a miter.
+    abc('w %s.aig'%f_name)
+    print 'Miter = ',
+    ps()
+    sec_options = options
+    if sec_options == 'ab':
+        sec_options = 'l' #it will be changed to 'ab' after &equiv
+    sec_sw = True 
+    result = speculate() 
+    sec_options = ''
+    sec_sw = False
+    if result <= Unsat:
+        result = RESULT[result]
+    else:
+        result = sp()
+        if result[0] == 'SAT':
+            result = 'UNDECIDED'
+    print 'Total time = %d'%(time.time() - yy)
+    return result
+
+def filter(opts):
+    global A_name,B_name
+##    print 'Filtering with options = %s'%opts
+    """ This is for filter which effectively only recognizes options -f -g"""
+    if (opts == '' or opts == 'l'): #if 'l' this is used only for initial &equiv2 to get initial equiv creation
+        return
+    print 'filter = %s  '%opts,
+    if opts == 'ab':
+        print A_name ,
+        print B_name
+##        run_command('&ps')
+        run_command('&filter -f %s.aig %s.aig'%(A_name,B_name))
+        return
+####    if not opts == 'f':
+####        opts = 'g'
+##    print 'filter = %
+    run_command('&filter -%s'%opts)
+
+def check_if_spec_first():
+    global sec_sw, A_name, B_name, sec_options, po_map
+    set_globals()
+    t = max(1,.5*G_T)
+    r = max(1,int(t))
+    abc('w check_save.aig')
+    abc('&w check_and.aig')
+    abc("&get; &equiv3 -v -F 20 -T %f -R %d"%(t,5*r))
+    filter('g')
+    abc("&srm -A %s_gsrm.aig; r %s_gsrm.aig"%(f_name,f_name))
+    print 'Estimated # POs = %d for initial speculation'%n_pos()
+    result = n_pos() > max(50,.25*n_latches())
+    abc('r check_save.aig')
+    abc('&r -s check_and.aig')
+    return result
+
+def initial_speculate(sec_opt=''):
+    global sec_sw, A_name, B_name, sec_options, po_map
+    set_globals()
+    if sec_options == '':
+        sec_options = sec_opt
+    # 1000 - 15, 5000 - 25, 10000 - 30, 50000 - 50
+    na = n_ands()
+##    t = max(1,G_T)
+    if na < 1000:
+        t =20
+    elif na < 5000:
+        t = 20 + ((na-1000)/4000)*20
+    elif na < 10000:
+        t = 40 + ((na-5000)/5000)*20
+    elif na < 50000:
+        t = 60 + ((na-40000)/40000)*15
+    else:
+        t = 75
+    r = max(1,int(t))
+    rounds = 30*r
+    print 'Initial sec_options = %s'%sec_options
+##    if sec_options == 'l':
+##        cmd = "&get; &equiv3 -lv -F 20 -T %f -R %d -S %d"%(3*t,rounds,rounds/20)
+##    else:
+##        cmd = "&get; &equiv3 -v -F 20 -T %f -R %d -S %d"%(3*t,rounds,rounds/20)
+    cmd = "&get; &equiv3 -v -F 20 -T %d -R %d -S %d"%(int(t),0,0) #####XXX
+    print cmd
+    abc(cmd)
+##    print 'AND space after &equiv3: ',
+##    run_command('&ps')
+    if (sec_options == 'l'):
+        if sec_sw:
+            sec_options = 'ab'
+        else:
+            sec_options = 'f'
+##    print 'A_name: ',
+##    run_command('r %s.aig;ps'%A_name)
+##    print 'B_name: ',
+##    run_command('r %s.aig;ps'%B_name)
+    print 'filtering'
+    filter(sec_options)
+    abc('&w initial_gore.aig')
+##    print 'Running &srm'
+    if sec_sw:
+        print 'miter: ',
+        run_command('&ps')
+        print 'A_name: ',
+        run_command('r %s.aig;ps'%A_name)
+        print 'B_name: ',
+        run_command('r %s.aig;ps'%B_name)
+        cmd = "&srm2 -%s %s.aig %s.aig; r gsrm.aig; w %s_gsrm.aig; &w %s_gore.aig"%(sec_options,A_name,B_name,f_name,f_name)
+        abc(cmd)
+        po_map = range(n_pos())
+        return sec_options
+    else:
+##        abc('&r %s_gore.aig; &srm ; r gsrm.aig; w %s_gsrm.aig'%(f_name,f_name))
+        cmd = "&srm -A %s_gsrm.aig; r %s_gsrm.aig; &w %s_gore.aig"%(f_name,f_name,f_name)
+        print 'Running %s'%cmd
+        abc(cmd)
+        print 'done with &srm'
+        po_map = range(n_pos())
+        if sec_options == '' or sec_options == 'g':
+##            if n_pos() > 10000:###temp
+            if n_eff_pos() > 1000: ##### Temporary
+                sec_options = 'g'
+                print 'sec_options set to %s'%'g'
+                abc('&r -s %s_gore.aig'%f_name)
+                filter(sec_options)
+##                print 'Running &srm'
+                cmd = "&srm -A %s_gsrm.aig; r %s_gsrm.aig; &w %s_gore.aig"%(f_name,f_name,f_name)
+##                print 'Running %s'%cmd
+                abc(cmd)
+                po_map = range(n_pos())
+                if n_eff_pos() > 500:
+##                if n_pos() > 20000:####temp
+                    sec_options = 'f'
+                    print 'sec_options set to %s'%'f'
+                    abc('&r -s %s_gore.aig'%f_name)
+                    filter(sec_options)
+                    print 'Running &srm'
+                    cmd = "&srm -A %s_gsrm.aig; r %s_gsrm.aig; &w %s_gore.aig"%(f_name,f_name,f_name)
+                    print 'Running %s'%cmd
+                    abc(cmd)
+                    po_map = range(n_pos())
+    return sec_options
+                
+##                    if n_pos() > 2000:
+##                        return sec_options
+                        
+        
+def test_against_original():
+    '''tests whether we have a cex hitting an original PO'''
+    abc('&w %s_save.aig'%f_name) #we preserve whatever was in the & space
+    abc('&r -s %s_gore.aig'%f_name) #This is the original
+    abc('testcex') #test the cex against the &space
+    PO = cex_po()
+##    print 'test_against original gives PO = %d'%PO 
+    abc('&r -s %s_save.aig'%f_name)
+    if PO > -1:
+##        print 'cex fails an original PO'
+        return True
+    else:
+        abc('write_status %s_status.status'%f_name)
+        return False
+
+def set_cex_po(n=0):
+    """
+    if cex falsifies a non-real PO return that PO first,
+    else see if cex_po is one of the original, then take it next
+    else return -1 which means that the cex is not valid and hence an error.
+    parameter n = 1 means test the &-space
+    """
+    global n_pos_before, n_pos_proved #these refer to real POs
+    if n == 0:
+        abc('testcex -a -O %d'%(n_pos_before-n_pos_proved)) #test regular AIG space
+    else:
+        abc('testcex -O %d'%(n_pos_before-n_pos_proved)) #test the &-AIG
+    PO = cex_po()
+##    print 'cex_po = %d, n_pos_before = %d, n_pos_proved = %d'%(PO, n_pos_before, n_pos_proved)
+    if PO >= (n_pos_before - n_pos_proved): #cex_po is not an original
+##        print '1. cex PO = %d'%PO
+        return PO # after original so take it.
+    if n == 0:
+        abc('testcex -a') #test regular
+    else:
+        abc('testcex')  #test &space
+    PO = cex_po()
+    print '2. cex PO = %d'%PO
+    cx = cex_get()
+    if PO > -1:
+        if test_against_original(): #this double checks that it is really an original PO
+            cex_put(cx)
+            print 'test_against_original was valid'
+            return PO
+        else:
+            print '1. PO is not valid'
+            return -1 #error
+    if PO < 0 or PO >= (n_pos_before - n_pos_proved): # not a valid cex because already tested outside original.
+##        print 'cex_po = %d, n_pos_before = %d, n_pos_proved = %d'%(PO, n_pos_before, n_pos_proved)
+        print '2. PO is not valid'
+        PO = -1 #error
+##    print '3. cex PO = %d'%PO
+    return PO
+
+def cex_stats():
+    print 'cex_pis = %d, cex_regs = %d, cex_po = %d, cex_frame = %d'%(n_cex_pis(),n_cex_regs(),cex_po(),cex_frame())
+
+def speculate(t=0):
+    """Main speculative reduction routine. Finds candidate sequential equivalences and refines them by simulation, BMC, or reachability
+    using any cex found. """    
+    global G_C,G_T,n_pos_before, x_factor, n_latches_before, last_verify_time, trim_allowed, n_pos_before
+    global t_init, j_last, sec_sw, A_name, B_name, sec_options, po_map, sweep_time, sims, cex_list, n_pos_proved,ifpord1
+    global last_cx, total_spec_refine_time, skip_spec
+##    print 'sec_options = %s'%sec_options
+    if skip_spec:
+        return Undecided_no_reduction
+    add_trace('speculate')
+    if t > 0:
+        total_spec_refine_time = t
+    abc('scl') #make sure no dangling flops
+    abc('orpos')
+    last_cx = 0
+    ifpord1 = 1
+    initial_po_size = last_srm_po_size = n_pos()
+    initial_sizes = [n_pis(),n_pos(),n_latches(),n_ands()]
+    if sec_sw:
+        print 'A_name = %s, B_name = %s, f_name = %s, sec_options = %s'%(A_name, B_name, f_name, sec_options)
+    elif n_ands()> 36000 and sec_options == '':
+##        add_trace('sec options g')
+        sec_options = 'g'
+        print 'sec_options set to "g"'
+##        add_trace('sec_options ="g"')
+        
+    def refine_with_cex():
+        """Refines the gore file to reflect equivalences that go away because of cex"""
+        global f_name
+        abc('write_status %s_before_refine.status'%f_name)
+        abc('&r -s %s_gore.aig; &resim -m'%f_name)
+##        run_command('&ps')
+##        cex_stats()
+        filter(sec_options)
+        run_command('&w %s_gore.aig'%f_name)
+        return
+
+    def refine_without_cex(L=[]):
+        """removes the POs in the current SRM in the list L. Alters the equivalence classes in the
+            gore file accordingly.
+        """
+        global f_name
+        if L == []:
+            return
+        print 'Entered refine_without_cex'
+        abc('write_status %s_before_refine.status'%f_name)
+        create_abc_array(L)
+        print 'wrote array'
+        abc('&r -s %s_gore.aig; &equiv_filter'%f_name)
+        print 'filtered gore using L'
+        filter(sec_options)
+        print 'filtered with %s'%sec_options
+        run_command('&w %s_gore.aig'%f_name)
+        return
+
+    
+    def set_cex(lst):
+        """ assumes only one in lst """
+        for j in range(len(lst)):
+            cx = lst[j]
+            if cx == None:
+                continue
+            else:
+                cex_put(cx)
+                break
+    def retry(t):
+        add_trace('retrying')
+        print 'retrying winner cex which did not refine'
+        abc('r %s_gsrm_before.aig'%f_name) #restore previous gsrm
+        abc('w %s_beforerpm.aig'%f_name)
+        rep_change = reparam() #must be paired with reconcile below if cex
+        if rep_change:
+            add_trace('reparam')
+        abc('w %s_afterrpm.aig'%f_name)
+        if last_winner == 'RareSim':
+            simulate2(t)
+        elif last_winner == 'PDR':
+            pdr(t)
+        elif last_winner == 'BMC':
+            bmc(t)
+        elif last_winner == 'INTRP':
+            intrp(t)
+        elif last_winner == 'PDRM':
+            pdrm(t)
+        elif last_winner == 'BMC3':
+            bmc3(t)
+        elif last_winner == 'PDR_sd':
+            pdrseed(t)
+        elif last_winner == 'PDRM_sd':
+            pdrmm(t)
+        elif last_winner == 'INTRPm':
+            intrpm(t)
+        elif last_winner == 'REACHY':
+            reachy(t)
+        elif last_winner == 'BMC_J':
+            bmc_j(t)
+        elif last_winner == 'PDRa':
+            pdra(t)
+        else:
+            reconcile(rep_change)
+            return False
+        reconcile(rep_change)
+        if not is_sat():
+            return False
+        abc('&r -s %s_gore_before.aig ;&w %s_gore.aig'%(f_name,f_name)) #restore old gore file
+        return True
+    
+    def generate_srm():
+        """generates a speculated reduced model (srm) from the gore file"""
+        global f_name, po_map, sec_sw, A_name, B_name, sec_options, n_pos_proved
+##        print 'Generating'
+        pos = n_pos()
+        ab = n_ands()
+        abc('w %s_oldsrm.aig'%f_name) #save for later purposes
+        if sec_sw:
+            run_command('&r -s %s_gore.aig; &srm2 -%s %s.aig %s.aig; r gsrm.aig; w %s_gsrm.aig'%(f_name,sec_options,A_name,B_name,f_name))
+        else:
+            abc('&r -s %s_gore.aig; &srm -A %s_gsrm.aig ; r %s_gsrm.aig'%(f_name,f_name,f_name)) #do we still need to write the gsrm file
+##        ps()
+        po_map = range(n_pos())
+        ps()
+        n_pos_proved = 0
+        return 'OK'
+
+    n_pos_before = n_pos()
+    n_pos_proved = 0
+    n_latches_before = n_latches()    
+    set_globals()
+##    t = max(1,.5*G_T)#irrelevant
+##    r = max(1,int(t))
+    t = 1000
+    j_last = 0
+    J = slps+sims+pdrs+bmcs+intrps
+    J = modify_methods(J,1)
+    print 'sec_options = %s'%sec_options 
+    funcs = [eval('(pyabc_split.defer(initial_speculate)("%s"))'%sec_options)]
+    funcs = create_funcs(J,10000)+funcs #want other functins to run until initial speculate stops
+    mtds = sublist(methods,J) + ['initial_speculate'] #important that initial_speculate goes last
+    print mtds
+    res = fork_last(funcs,mtds)
+    print 'init_spec return = ',
+    print res
+    if res[1] in ['f','g','']:
+        sec_options = res[1]
+    add_trace('sec_options = %s'%sec_options)
+    add_trace('Number of POs: %d'%n_pos())
+##    ps()
+    if is_unsat():
+        return Unsat
+    if is_sat():
+        return Sat_true
+    if n_pos_before == n_pos():
+        print 'No new outputs. Quitting speculate'
+        add_trace('de_speculate')
+        return Undecided_no_reduction # return result is unknown
+    if n_eff_pos() > 1999000:
+        print 'Too many POs'
+        add_trace('de_speculate')
+        return Undecided_no_reduction
+    print 'Initial speculation: ',
+    ps()
+    abc('w %s_initial_gsrm.aig'%f_name)
+    if n_pos() > 1000:
+        print 'Too many new outputs. Quitting speculate'
+        add_trace('de_speculate')
+        return Undecided_no_reduction # return result is unknown
+    if n_pos() <= n_pos_before + 2:
+        print 'Too few new outputs. Quitting speculate'
+        add_trace('de_speculate')
+        return Undecided_no_reduction # return result is unknown
+    if n_latches() == 0:
+        return check_sat()
+    if use_pms:
+        p,q,r=par_multi_sat(0)
+        q = indices(r,1)
+        print sumsize(r)
+        if count_less(r,1) < .25*len(r):
+            print 'too many POs are already SAT'
+            add_trace('de_speculate')
+            return Undecided_no_reduction
+    if sec_options == 'l' and sec_sw:
+        sec_options = 'ab' #finished with initial speculate with the 'l' option
+        print "sec_options set to 'ab'"
+    elif sec_options == 'l':
+        sec_options = 'f'
+        print "sec_options set to 'f'"
+    po_map = range(n_pos()) #we need this because the initial_speculate is done in parallel and po_map is not passed back.
+    npi = n_pis()
+    set_globals()
+    if is_sat():
+        return Sat_true
+    simp_sw = init = True
+    add_trace('speculative refinement')
+    print '\nIterating speculation refinement'
+    sims_old = sims
+    sims = sims[:1] 
+    J = slps+sims+pdrs+intrps+bmcs
+    J = modify_methods(J)
+##    print sublist(methods,J)
+    t = max(50,max(1,2*G_T))
+    last_verify_time = t
+    ### temp
+    last_verify_time = total_spec_refine_time
+    ###
+    print 'Verify time set to %d'%last_verify_time
+    reg_verify = True
+    ref_time = time.time()
+    sweep_time = 2
+    ifpord1=1
+    par_verify = re_try = False
+##    total_spec_refine_time = 150
+    while True: ##################### refinement loop
+        set_globals()
+        yy = time.time()
+        time_used = (yy-ref_time)
+        print 'Time_used = %0.2f'%time_used
+        if time_used > total_spec_refine_time:
+            print 'Allotted speculation refinement time is exceeded'
+            add_trace('de_speculate')
+            return Undecided_no_reduction
+        if not init:
+            abc('r %s_gsrm.aig'%f_name) #this is done only to set the size of the previous gsrm.
+            abc('w %s_gsrm_before.aig'%f_name)
+            set_size()
+            result = generate_srm()
+            if n_pos() <= n_pos_before + 1: #heuristic that if only have one equivalence, then not worth it
+                abc('r %s.aig'%f_name) #revert to previous aig
+                sims = sims_old
+                print 'UNDECIDED'
+                print 'Refinement time = %0.2f'%(time.time() - ref_time)
+                add_trace('de_speculate')
+                return Undecided_no_reduction 
+            last_srm_po_size = n_pos()
+            yy = time.time()
+            # if the size of the gsrm did not change after generating a new gsrm
+            # and if the cex is valid for the gsrm, then the only way this can happen is if
+            # the cex_po is an original one.
+            if check_size(): #same size before and after
+                if check_cex(): #valid cex failed to refine possibly
+                    if 0 <= cex_po() and cex_po() < (n_pos_before - n_pos_proved): #original PO
+                        print 'Found cex in original output number = %d'%cex_po()
+                        print 'Refinement time = %0.2f'%(time.time() - ref_time)
+                        return Sat_true
+                    elif check_same_gsrm(f_name): #if two gsrms are same, then failed to refine
+                        print 'CEX failed to refine'
+                        add_trace('de_speculate')
+                        return Error
+                else:
+                    print 'not a valid cex'
+                    print 'Last winner = %s'%last_winner
+                    print 're_try = %d'%re_try
+                    if re_try:
+                        add_trace('de_speculate')
+                        return Error #abort speculation
+                    re_try = True
+            else:
+                re_try = False # just got a valid refinement so reset.
+            if n_latches() == 0:
+                print 'Number of latches reduced to 0'
+                print 'CEX refined incorrectly'
+                abc('r %s.aig'%f_name) #revert to previous aig
+                sims = sims_old
+                add_trace('de_speculate')
+                return Error
+        init = False # make it so that next time it is not the first time through
+        if not t == last_verify_time: # heuristic that if increased last verify time,
+                                      # then try pord_all 
+            t = last_verify_time
+            if reg_verify:
+                t_init = (time.time() - yy)/2 #start poor man's concurrency at last cex fime found
+                t_init = min(10,t_init)
+                t = last_verify_time
+                print 'Verify time set to %d'%t
+        if not re_try:
+##            abc('w %s_beforerpm.aig'%f_name)
+##            rep_change = reparam() #must be paired with reconcile below if cex
+####            if rep_change:
+####                add_trace('reparam')
+##            abc('w %s_afterrpm.aig'%f_name)
+            rep_change = False #TEMP
+            if reg_verify:
+                if par_verify:
+                    S,L_sat_POs,s = par_multi_sat(120)
+                    L_sat_POs = indices(s,1)
+##                    L_sat_POs = L[1]
+                    L=[]
+                    for j in range(len(L_sat_POs)): #eliminate any of the original POs
+                        if L_sat_POs[j] >= (n_pos_before-n_pos_proved):
+                            L=L+[L_sat_POs[j]]
+                    L_sat_POs = L
+                    print L
+                    if not L_sat_POs == []:
+                        ress = [1,[['multi_sat']]]
+                        add_trace(['multi_sat'])
+                    else:
+                        reg_verify = False
+                        ress = pord_1_2(t)
+                        add_trace(ress[1])
+                else:
+                    ttt = time.time() #find time it takes to find a cex
+                    ress = verify(J,t)
+                    t_last_verify = time.time() - ttt
+            else:
+                ress = pord_1_2(t)
+##                print ress
+                add_trace(ress[1])
+            result = ress[0]
+##            add_trace(ress[1])
+        else:
+            if not retry(100):
+                add_trace('de_speculate')
+                return Error
+            result = get_status()
+##        print result
+        if result == Unsat:
+            add_trace('UNSAT by %s'%ress[1])
+            print 'UNSAT'
+            print 'Refinement time = %0.2f'%(time.time() - ref_time)
+            return Unsat
+        if result < Unsat:
+            abc('&r -s %s_gore.aig;&w %s_gore_before.aig'%(f_name,f_name)) #we are making sure that none of the original POs fail
+            if par_verify:
+                refine_without_cex(L_sat_POs)
+                print 'refining without cex done'
+                continue
+            if not reg_verify:
+                set_cex(cex_list)
+##            if not re_try:
+####                rec = reconcile(rep_change) #end of pairing with reparam()TEMP
+####                if rec == 'error':
+####                    add_trace('de_speculate')
+####                    return Error
+##                assert (npi == n_cex_pis()),'ERROR: #pi = %d, #cex_pi = %d'%(npi,n_cex_pis())
+            abc('&r -s %s_gore.aig;&w %s_gore_before.aig'%(f_name,f_name)) #we are making sure that none of the original POs fail
+            if reg_verify:
+                PO = set_cex_po(0) #testing the regular space
+            else:
+                abc('&r -s %s_gsrm.aig'%f_name)
+                PO = set_cex_po(1) # test against the &space.
+            print 'cex_PO is %d,  '%PO,
+            if (-1 < PO and PO < (n_pos_before-n_pos_proved)):
+                print 'Found cex in original output = %d'%cex_po()
+                print 'Refinement time = %0.2f'%(time.time() - ref_time)
+                return Sat_true
+            if PO == -1:
+                add_trace('de_speculate')
+                return Error
+            refine_with_cex()    #change the number of equivalences
+            if not par_verify and t_last_verify > 2500:
+                par_verify = True #switch to finding many POs at a time
+            continue
+        elif (is_unsat() or n_pos() == 0):
+            print 'UNSAT'
+            print 'Refinement time = %0.2f'%(time.time() - ref_time)
+            return Unsat
+        else: #if undecided, record last verification time
+            print 'Refinement returned undecided in %d sec.'%t
+            last_verify_time = t
+            #########################added
+            if reg_verify: #try one last time with parallel POs cex detection (find_cex_par) if not already tried
+                abc('r %s_beforerpm.aig'%f_name) # to continue refinement, need to restore original
+                t_init = min(last_verify_time,(time.time() - yy)/2) #start poor man's concurrency at last cex fime found
+                t_init = min(10,t_init)
+                reg_verify = False
+                t = last_verify_time # = 2*last_verify_time
+                abc('w %s_beforerpm.aig'%f_name)
+                rep_change = reparam() #must be paired with reconcile()below
+                abc('w %s_afterrpm.aig'%f_name)
+                ress = pord_1_2(t) #main call to verification
+                print ress
+                result = ress[0]
+                add_trace(ress[1])
+                if result == Unsat:
+                    print 'UNSAT'
+                    print 'Refinement time = %0.2f'%(time.time() - ref_time)
+                    return Unsat
+                if is_sat() or result == Sat:
+##                    assert result == get_status(),'result: %d, status: %d'%(result,get_status())
+                    print 'result: %d, status: %d'%(result,get_status())
+                    set_cex(cex_list)
+                    rec = reconcile(rep_change)
+                    if rec == 'error':
+                        add_trace('de_speculate')
+                        return Error
+                    abc('&r -s %s_gsrm.aig'%f_name)
+                    PO = set_cex_po(1) #testing the & space
+                    if (-1 < PO and PO < (n_pos_before-n_pos_proved)):
+                        print 'Found cex in original output = %d'%cex_po()
+                        print 'Refinement time = %0.2f'%(time.time() - ref_time)
+                        return Sat_true
+                    if PO == -1:
+                        add_trace('de_speculate')
+                        return Error
+                    refine_with_cex()    #change the number of equivalences
+                    continue
+                else: #if undecided, record last verification time
+                    last_verify_time = t
+                    print 'UNDECIDED'
+                    break
+            ################### added
+            else:
+                break
+    sims = sims_old
+    print 'UNDECIDED'
+    print 'Refinement time = %0.2f'%(time.time() - ref_time)
+##    if last_srm_po_size == initial_po_size: #essentially nothing happened. last_srm_po_size will be # POs in last srm.
+    if initial_sizes == [n_pis(),n_pos(),n_latches(),n_ands()]:
+        abc('r %s.aig'%f_name)
+        add_trace('de_speculate')
+        return Undecided_no_reduction #thus do not write spec file
+    else: #file was changed, so some speculation happened. If we find a cex later, need to know this.
+        write_file('spec')
+        return Undecided_reduction
+
+def simple_sat(t=900):
+    """
+    aimed at trying harder to prove SAT
+    """
+    y = time.time()
+    bmcs2 = [9,31]
+    bmcs2 = [9,30]
+    J = allbmcs+pdrs+sims+[5]
+##    J = modify_methods(J)
+##    J = [14,2,7,9,30,31,26,5] #5 is pre_simp
+    funcs = create_funcs(J,t)
+    mtds =sublist(methods,J)
+    print mtds
+    fork_last(funcs,mtds)
+    result = get_status()
+    if result > Unsat:
+        write_file('smp')
+        result = verify(slps+allbmcs+pdrs+sims,t)
+    print 'Time for simple_sat = %0.2f'%(time.time()-y)
+    report_bmc_depth(max(max_bmc,n_bmc_frames()))
+    return [RESULT[result[0]]] + [result[1]]
+
+def simple(t=10000,no_simp=0):
+    y = time.time()
+##    pre_simp()
+    if not no_simp:
+        prove_part_1()
+        if is_sat():
+            return ['SAT']+['pre_simp']
+        if is_unsat():
+            return ['UNSAT']+['pre_simp']
+        if n_latches() == 0:
+            return [RESULT[check_sat()]]+['pre_simp']
+##    J = slps+sims+bmcs+pdrs+intrps+pre
+    J = slps+sims+allbmcs+allpdrs+intrps
+    J = modify_methods(J)
+    result = verify(J,t)
+##    add_pord('%s by %s'%(result[0],result[1])
+    return [RESULT[result[0]]] + [result[1]]
+
+def simple_bip(t=1000):
+    y = time.time()
+    J = [0,14,1,2,30,5] #5 is pre_simp
+    funcs = create_funcs(J,t)
+    mtds =sublist(methods,J)
+    fork_last(funcs,mtds)
+    result = get_status()
+    if result > Unsat:
+        write_file('smp')
+        result = verify(slps+[0,14,1,2,30],t)
+    print 'Time for simple_bip = %0.2f'%(time.time()-y)
+    return RESULT[result] 
+
+def check_same_gsrm(f):
+##    return False #disable the temporarily until can figure out why this is there
+    """checks gsrm miters before and after refinement and if equal there is an error"""
+    global f_name
+    abc('r %s_gsrm.aig'%f)
+##    ps()
+    run_command('miter -c %s_gsrm_before.aig'%f)
+##    ps()
+    abc('&get; ,bmc -timeout=5')
+    result = True #if the same
+    if is_sat(): #if different
+        result = False
+    abc('r %s_gsrm.aig'%f)
+##    ps()
+    return result
+
+def check_cex():
+    """ check if the last cex still asserts one of the outputs.
+    If it does then we have an error"""
+    global f_name
+    abc('read_status %s_before_refine.status'%f_name)
+    abc('&r -s %s_gsrm_before.aig'%f_name)
+##    abc('&r %s_gsrm.aig'%f_name)
+    run_command('testcex') #test the cex against the &-space aig.
+##    print 'cex po = %d'%cex_po()
+    return cex_po() >=0
+
+def set_size():
+    """Stores  the problem size of the current design.
+    Size is defined as (PIs, POs, ANDS, FF)""" 
+    global npi, npo, nands, nff, nmd
+    npi = n_pis()
+    npo = n_pos()
+    nands = n_ands()
+    nff = n_latches()
+    nmd = max_bmc
+    #print npi,npo,nands,nff
+
+def check_size():
+    """Assumes the problem size has been set by set_size before some operation.
+    This checks if the size was changed
+    Size is defined as (PIs, POs, ANDS, FF, max_bmc)
+    Returns TRUE is size is the same""" 
+    global npi, npo, nands, nff, nmd
+    #print n_pis(),n_pos(),n_ands(),n_latches()
+    result = ((npi == n_pis()) and (npo == n_pos()) and (nands == n_ands()) and (nff == n_latches()) )
+    return result
+
+def inferior_size():
+    """Assumes the problem size has been set by set_size beore some operation.
+    This checks if the new size is inferior (larger) to the old one 
+    Size is defined as (PIs, POs, ANDS, FF)""" 
+    global npi, npo, nands, nff
+    result = ((npi < n_pis()) or (npo < n_pos()) or (nands < n_ands()) )
+    return result
+
+##def quick_verify(n):
+##    """Low resource version of final_verify n = 1 means to do an initial
+##    simplification first. Also more time is allocated if n =1"""
+##    global last_verify_time
+##    trim()
+##    if n == 1:
+##        simplify()
+##        if n_latches == 0:
+##            return check_sat()
+##        trim()
+##        if is_sat():
+##            return Sat_true
+##    #print 'After trimming: ',
+##    #ps()
+##    set_globals()
+##    last_verify_time = t = max(1,.4*G_T)
+##    if n == 1:
+##        last_verify_time = t = max(1,2*G_T)
+##    print 'Verify time set to %d '%last_verify_time
+##    J = [18] + intrps+bmcs+pdrs+sims
+##    status = verify(J,t)
+##    return status
+
+def process_status(status):
+    """ if there are no FF, the problem is combinational and we still have to check if UNSAT"""
+    if n_latches() == 0:
+        return check_sat()
+    return status
+    
+def get_status():
+    """this simply translates the problem status encoding done by ABC
+    (-1,0,1)=(undecided,SAT,UNSAT) into the status code used by our
+    python code. -1,0,1 => 3,0,2
+    """
+    if n_latches() == 0:
+        return check_sat()
+    status = prob_status() #interrogates ABC for the current status of the problem.
+    # 0 = SAT i.e. Sat_reg = 0 so does not have to be changed.
+    if status == 1:
+        status = Unsat
+    if status == -1: #undecided
+        status = Undecided
+    return status
+
+def two_temp(t=20):
+    tt = time.time()
+    abc('tempor;scl;drw;&get;&rpm;&put;tempor;scl;drw;&get;&rpm;&put;scorr')
+    print 'Time for two_temp = %.2f'%(time.time()-tt)
+    return get_status()
+
+def reparam_m():
+    """eliminates PIs which if used in abstraction or speculation must be restored by
+    reconcile and the cex made compatible with file beforerpm
+    Uses the &-space
+    """
+    abc('w %s_temp.aig'%f_name)
+    n = n_pis()
+    t1 = time.time()
+##    abc('&get;,reparam -aig=%s_rpm.aig; r %s_rpm.aig'%(f_name,f_name))
+    abc('&get;&rpm;&put')
+    tm = (time.time() - t1)
+    if n_pis() == 0:
+        print 'Number of PIs reduced to 0. Added a dummy PI'
+        abc('addpi')
+    nn = n_pis()
+    if nn < n:
+        print 'Reparam_m: PIs %d => %d, time = %.2f'%(n,nn,tm)
+        rep_change = True
+    else:
+        abc('r %s_temp.aig'%f_name)
+        rep_change = False
+    return rep_change
+
+def reparam_e():
+    """eliminates PIs which if used in abstraction or speculation must be restored by
+    reconcile and the cex made compatible with file beforerpm
+    Uses the &-space
+    """
+    abc('w %s_temp.aig'%f_name)
+    n = n_pis()
+    t1 = time.time()
+    abc('&get;,reparam -aig=%s_rpm.aig; r %s_rpm.aig'%(f_name,f_name))
+##    abc('&get;&rpm;&put')
+    tm =(time.time() - t1)
+    if n_pis() == 0:
+        print 'Number of PIs reduced to 0. Added a dummy PI'
+        abc('addpi')
+    nn = n_pis()
+    if nn < n:
+        print 'Reparam_e: PIs %d => %d, time = %.2f'%(n,nn,tm)
+        rep_change = True
+    else:
+        abc('r %s_temp.aig'%f_name)
+        rep_change = False
+    return rep_change
+
+def reparam():
+##    abc('w %s_temp.aig'%f_name)
+##    res = reparam_e()
+##    res = reparam_m()
+    res = reparam_e()
+    return res
+
+##def try_and_rpm():
+##    abc('w %s_temp.aig'%f_name)
+##    n = n_pis()
+##    t1 = time.time()
+##    abc('&get;&rpm;&put')
+##    print 'time &rpm = %.2f'%(time.time() - t1)
+##    if n_pis() == 0:
+##        print '&rpm: Number of PIs reduced to 0. Added a dummy PI'
+##        abc('addpi')
+##    nn = n_pis()
+##    if nn < n:
+##        print '&rpm: Reparam: PIs %d => %d'%(n,nn)
+####        rep_change = True
+##    abc('r %s_temp.aig'%f_name)
+####    else:
+####        abc('r %s_temp.aig'%f_name)
+####        return False
+
+def reconcile(rep_change):
+    """used to make current cex compatible with file before reparam() was done.
+    However, the cex may have come
+    from extracting a single output and verifying this.
+    Then the cex_po is 0 but the PO it fails could be anything.
+    So testcex rectifies this."""
+    global n_pos_before, n_pos_proved
+##    print 'rep_change = %s'%rep_change
+    if rep_change == False:
+        return
+    abc('&r -s %s_beforerpm.aig; &w tt_before.aig'%f_name)
+    abc('write_status %s_after.status;write_status tt_after.status'%f_name)
+    abc('&r -s %s_afterrpm.aig;&w tt_after.aig'%f_name)
+    POa = set_cex_po(1)   #this should set cex_po() to correct PO. A 1 here means it uses &space to check
+    abc('reconcile %s_beforerpm.aig %s_afterrpm.aig'%(f_name,f_name))
+    # reconcile modifies cex and restores work AIG to beforerpm
+    abc('write_status %s_before.status;write_status tt_before.status'%f_name)
+    POb = set_cex_po()#does not make sense if we are in absstraction refinement
+    if POa != POb:
+        abc('&r -s %s_beforerpm.aig; &w tt_before.aig'%f_name)
+        abc('&r -s %s_afterrpm.aig; &w tt_after.aig'%f_name)
+        print 'cex PO afterrpm = %d not = cex PO beforerpm = %d'%(POa,POb)
+    if POa < 0: #'cex did not assert any output'
+        return 'error'
+
+def reconcile_a(rep_change):
+    """ This is the reconcile used in abstraction refinement
+    used to make current cex compatible with file before reparam() was done.
+    However, the cex may have come
+    from extracting a single output and verifying this.
+    Then the cex_po is 0 but the PO it fails could be anything.
+    So testcex rectifies this."""
+    global n_pos_before, n_pos_proved
+##    print 'rep_change = %s'%rep_change
+    if rep_change == False:
+        return
+    abc('&r -s %s_beforerpm.aig; &w tt_before.aig'%f_name)
+    abc('write_status %s_after.status;write_status tt_after.status'%f_name)
+    abc('&r -s %s_afterrpm.aig;&w tt_after.aig'%f_name)
+    POa = set_cex_po(1)   #this should set cex_po() to correct PO. A 1 here means it uses &space to check
+    abc('reconcile %s_beforerpm.aig %s_afterrpm.aig'%(f_name,f_name))
+    # reconcile modifies cex and restores work AIG to beforerpm
+    abc('write_status %s_before.status;write_status tt_before.status'%f_name)
+    if POa < 0: #'cex did not assert any output'
+        return 'error'
+
+def reconcile_all(lst, rep_change):
+    """reconciles the list of cex's"""
+    global f_name, n_pos_before, n_pos_proved
+    if rep_change == False:
+        return lst
+    list = []
+    for j in range(len(lst)):
+        cx = lst[j]
+        if cx == None:
+            continue
+        cex_put(cx)
+        reconcile(rep_change)
+        list = list + [cex_get()]
+    return list
+    
+
+##def try_rpm():
+##    """rpm is a cheap way of doing reparameterization and is an abstraction method, so may introduce false cex's.
+##    It finds a minimum cut between the PIs and the main sequential logic and replaces this cut by free inputs.
+##    A quick BMC is then done, and if no cex is found, we assume the abstraction is valid. Otherwise we revert back
+##    to the original problem before rpm was tried."""
+##    global x_factor
+##    if n_ands() > 30000:
+##        return
+##    set_globals()
+##    pis_before = n_pis()
+##    abc('w %s_savetemp.aig'%f_name)
+##    abc('rpm')
+##    result = 0
+##    if n_pis() < .5*pis_before:
+##        bmc_before = bmc_depth()
+##        #print 'running quick bmc to see if rpm is OK'
+##        t = max(1,.1*G_T)
+##        #abc('bmc3 -C %d, -T %f'%(.1*G_C, t))
+##        abc('&get;,bmc -vt=%f'%t)
+##        if is_sat(): #rpm made it sat by bmc test, so undo rpm
+##            abc('r %s_savetemp.aig'%f_name)
+##        else:
+##            trim()
+##            print 'WARNING: rpm reduced PIs to %d. May make SAT.'%n_pis()
+##            result = 1
+##    else:
+##        abc('r %s_savetemp.aig'%f_name)
+##    return result
+            
+def verify(J,t):
+    """This method is used for finding a cex during refinement, but can also
+    be used for proving the property. t is the maximum time to be used by
+    each engine J is the list of methods to run in parallel. See FUNCS for list"""
+    global x_factor, final_verify_time, last_verify_time, methods
+    set_globals()
+    t = int(max(1,t))
+    J = modify_methods(J)
+    mtds = sublist(methods,J)
+    print mtds
+    #print J,t
+    F = create_funcs(J,t)
+    (m,result) = fork_break(F,mtds,'US') #FORK here
+##    result = fork_break(F,mtds,'US') #FORK here
+    print result
+##    assert result[0] == get_status(),'result: %d, status: %d'%(result[0],get_status())
+    return result
+
+def dsat_all(t=100,c=100000):
+    print 't=%d,c=%d'%(t,c)
+    N = n_pos()
+    abc('&get')
+    J = range(N)
+    ttt = time.time()
+    J.reverse()
+    abc('w %s_temp.aig'%f_name)
+    for j in J:
+        tt = time.time()
+        abc('r %s.aig'%f_name)
+        run_command('cone -O %d; dc2; dsat -C %d'%(j,c))
+        if is_unsat():
+            print 'Output %d is %s'%(j,RESULT[2]),
+        else:
+            print 'Output %d is %s'%(j,RESULT[3]),
+        T = time.time() -tt
+        print 'time = %0.2f'%T
+        if time.time() - tt > t:
+            break
+    print 'Total time = %0.2f'%(time.time() - ttt)
+            
+def check_sat(t=900):
+    """This is called if all the FF have disappeared, but there is still some logic left. In this case,
+    the remaining logic may be UNSAT, which is usually the case, but this has to be proved. The ABC command 'dsat' is used fro combinational problems"""
+    global smp_trace
+    if not n_latches() == 0:
+        print 'circuit is not combinational'
+        return Undecided
+##    print 'Circuit is combinational - checking with dsat'
+    abc('&get') #save the current circuit
+    abc('orpos')
+    J = combs+slps
+    mtds = sublist(methods,J)
+##    print mtds
+    F = create_funcs(J,t)
+    (m,result) = fork_last(F,mtds) #FORK here
+##    print '%s: '%mtds[m],
+##    smp_trace = smp_trace + ['%s'%mtds[m]]
+    if is_sat():
+        abc('&put')
+        if n_pos() == 1:
+            return Sat_true
+        else:
+            return Undecided_no_reduction #some POs could be unsat.
+    elif is_unsat():
+        return Unsat
+    else:
+        abc('&put') #restore
+        return Undecided_no_reduction
+
+def try_era(s):
+    """era is explicit state enumeration that ABC has. It only works if the number of PIs is small,
+    but there are cases where it works and nothing else does"""
+    if n_pis() > 12:
+        return
+    cmd = '&get;&era -mv -S %d;&put'%s
+    print 'Running %s'%cmd
+    run_command(cmd)
+
+def try_induction(C):
+    """Sometimes proving the property directly using induction works but not very often.
+    For 'ind' to work, it must have only 1 output, so all outputs are or'ed together temporarily"""
+    return Undecided_reduction
+    print '\n***Running induction'
+    abc('w %s_temp.aig'%f_name)
+    abc('orpos; ind -uv -C %d -F 10'%C)
+    abc('r %s_savetemp.aig'%f_name)
+    status = prob_status()
+    if not status == 1:
+        return Undecided_reduction
+    print 'Induction succeeded'
+    return Unsat
+        
+def smp():
+    abc('smp')
+    write_file('smp')
+
+def dprove():
+    abc('dprove -cbjupr')
+
+def trim():
+    global trim_allowed,smp_trace
+    if not trim_allowed:
+        return False
+    result = reparam()
+    return result
+
+def prs(x=True):
+    global trim_allowed, smp_trace
+    """ If x is set to False, no reparameterization will be done in pre_simp"""
+    global smp_trace
+    smp_trace = []
+    trim_allowed = x
+    print 'trim_allowed = ',trim_allowed
+    y = time.time()
+    result = pre_simp()
+    print 'Time = %0.2f'%(time.time() - y)
+    write_file('smp')
+    return RESULT[result[0]]
+
+def check_push():
+    """save the current aig if it has a different number of latches from last aig on lst"""
+    result = False
+    n = n_latches()
+##    ps()
+    abc('&get;cexsave') #save the current aig
+##    typ = hist[-1:]
+##    print hist
+    run_command('r %s_aigs_%d.aig'%(init_initial_f_name,len(hist)))
+##    typ = aigs_pp('pop')
+##    aigs.pop() #check latches in last aig.
+    nn = n_latches()
+##    ps()
+##    aigs.push() # put back last aig.
+##    aigs_pp('push',typ)
+    abc('&put;cexload') # restore current aig
+##    print 'check_push: current n=%d, previous nn=%d'%(n,nn)
+    if not n == nn: #if number of latches changes need to push the current aig so that reconcile can work.
+##        aigs.push()
+##        print 'n /= nn'
+        aigs_pp('push','reparam0') #default is push,reparam
+        result = True
+    return result
+
+def dump():
+    """ get rid of the last aig on the list"""
+    abc('&get')
+##    aigs.pop()
+    aigs_pp('pop')
+    abc('&put')
+
+def test_no_simp():
+    global last_simp
+    ri = float(n_pis())/float(last_simp[0])
+    ro = float(n_pos())/float(last_simp[1])
+    rl = float(n_latches())/float(last_simp[2])
+    ra = float(n_ands())/float(last_simp[3])
+    val = min(ri,ro,rl,ra)
+    if val < .95:
+        print 'simplification worthwhile'
+        return False
+    print 'simplification not worthwhile'
+    return True
+        
+def pre_simp(n=0,N=0):
+    """This uses a set of simplification algorithms which preprocesses a design.
+    Includes forward retiming, quick simp, signal correspondence with constraints, trimming away
+    PIs, and strong simplify. If n not 0, then do not do phase abs"""
+    global trim_allowed, temp_dec
+    global smp_trace, aigs, last_simp
+    chk_sat = 0
+    smp_trace = []
+    while True:
+        if n_latches() == 0:
+            print 'Circuit is combinational'
+            chk_sat = 1
+            break
+        if test_no_simp():
+            break
+        ttime = time.time()
+        set_globals()
+        smp_trace = smp_trace + ['&scl']
+        abc('&get; &scl; &put')
+        if (n_ands() > 200000 or n_latches() > 50000 or n_pis() > 40000):
+            smp_trace = smp_trace + ['scorr_T']
+            scorr_T(50)
+            ps()
+        if ((n_ands() > 0) or (n_latches()>0)):
+            res =a_trim()
+        if n_latches() == 0:
+            break
+        status = get_status()
+        if (n == 0 and (not '_smp' in f_name) or '_cone' in f_name):
+            best_fwrd_min([10,11])
+            ps()
+            status = try_scorr_constr()
+        if ((n_ands() > 0) or (n_latches()>0)):
+            res = a_trim()
+        if n_latches() == 0:
+            break
+        status = process_status(status)
+        if status <= Unsat:
+            last_simp = [n_pis(),n_pos(),n_latches(),n_ands()]
+            return [status,smp_trace,hist]
+        print 'Starting simplify ',
+        simplify(n,N)
+        print 'Simplify: ',
+        ps()
+        if n_latches() == 0:
+            break
+        if trim_allowed and n == 0:
+            t = min(15,.3*G_T)
+            if (not '_smp' in f_name) or '_cone' in f_name: #try this only once on a design
+                tt = 25
+                if n_ands() > 500000:
+                    tt = 30
+                res,F = try_temps(tt) 
+                if res:
+                    aigs_pp('push','tempor')
+                if n_latches() == 0:
+                    break
+                if n == 0: 
+                    res,N = try_phases()
+                    if res:
+                        aigs_pp('push','phase')
+                if n_latches() == 0:
+                    break
+            if ((n_ands() > 0) or (n_latches()>0)):
+                res = a_trim()
+        status = process_status(status)
+        print 'Simplification time = %0.2f'%(time.time()-ttime)
+        last_simp = [n_pis(),n_pos(),n_latches(),n_ands()]
+        return [status, smp_trace,hist]
+    last_simp = [n_pis(),n_pos(),n_latches(),n_ands()]
+    return [check_sat(),smp_trace,hist]
+
+
+def try_scorr_constr():
+    set_size()
+    abc('w %s_savetemp.aig'%f_name)
+    status = scorr_constr()
+    if inferior_size():
+        abc('r %s_savetemp.aig'%f_name)
+    return status
+
+def factors(n):
+    l = [1,]
+    nn = n
+    while n > 1:
+        for i in (2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53):
+            if not i <nn:
+                break
+            if n%i == 0:
+                l = l + [i,]
+                n = n/i
+        if not n == 1:
+            l = l + [n,]
+        break
+    return sorted(l)
+
+def select(x,y):
+    z = []
+    for i in range(len(x)):
+        if x[i]:
+            z = z + [y[i],]
+    return z
+    
+def ok_phases(n):
+    """ only try those where the resulting n_ands does not exceed 60000"""
+    f = factors(n)
+    sp = subproducts(f)
+    s = map(lambda m:m*n_ands()< 120000,sp)
+    z = select(s,sp)
+    return z
+
+def subproducts(ll):
+    ss = (product(ll),)
+    #print ll
+    n = len(ll)
+    if n == 1:
+        return ss
+    for i in range(n):
+        kk = drop(i,ll)
+        #print kk
+        ss = ss+(product(kk),)
+        #print ss
+        ss = ss+subproducts(kk)
+        #print ss
+    result =tuple(set(ss))
+    #result.sort()
+    return tuple(sorted(result))
+
+def product(ll):
+    n = len(ll)
+    p = 1
+    if n == 1:
+        return ll[0]
+    for i in range(n):
+        p = p*ll[i]
+    return p
+
+def drop(i,ll):
+    return ll[:i]+ll[i+1:]
+
+def try_phases():
+####    print 'entered try_phases ',
+##    ps()
+    no = n_pos()
+    res = try_phase()
+##    print 'after try_phase ',
+##    ps()
+    N = n_pos()/no
+    if N > 1:
+        res = True
+    else:
+        res = False
+    return res,N
+
+def try_phase():
+    """Tries phase abstraction. ABC returns the maximum clock phase it found using n_phases.
+    Then unnrolling is tried up to that phase and the unrolled model is quickly
+    simplified (with retiming to see if there is a significant reduction.
+    If not, then revert back to original"""
+    global init_simp, smp_trace,aigs
+    n = n_phases()
+##    if ((n == 1) or (n_ands() > 45000) or init_simp == 0):
+    if ((n == 1) or (n_ands() > 60000)):
+        return False
+##    init_simp = 0
+    res = a_trim()
+    print 'Trying phase abstraction - Max phase = %d'%n,
+    abc('w %s_phase_temp.aig'%f_name)
+    na = n_ands()
+    nl = n_latches()
+    ni = n_pis()
+    no = n_pos()
+    z = ok_phases(n)
+    print z,
+    if len(z) == 1:
+        return False
+    #p = choose_phase()
+    p = z[1]
+    abc('phase -F %d'%p)
+    if no == n_pos(): #nothing happened because p is not mod period
+        print 'Phase %d is incompatible'%p
+        abc('r %s_phase_temp.aig'%f_name)
+        if len(z)< 3:
+            return False
+        else:
+            p = z[2]
+            #print 'Trying phase = %d:  '%p,
+            abc('phase -F %d'%p)
+            if no == n_pos(): #nothing happened because p is not mod period
+                print 'Phase %d is incompatible'%p
+                abc('r %s_phase_temp.aig'%f_name)
+                return False
+            else:
+                smp_trace = smp_trace + ['phase -F %d'%p]
+                abc('r %s_phase_temp.aig'%f_name)
+                abc('&get;&frames -o -F %d;&scl;&put'%p)
+    else:
+        abc('r %s_phase_temp.aig'%f_name)
+        abc('&get;&frames -o -F %d;&scl;&put'%p)
+        smp_trace = smp_trace + ['phase -F %d'%p]
+    print 'Simplifying with %d phases: => '%p,
+    smp_trace = smp_trace + ['simplify(1)']
+    simplify(1)
+##    res = a_trim() #maybe we don't need this because rel_cost uses n_real_inputs
+    ps()
+    cost = rel_cost([ni,nl,na])
+    print 'New relative cost = %f'%(cost)
+    if cost <  -.01:
+        abc('w %s_phase_temp.aig'%f_name)
+        if ((n_latches() == 0) or (n_ands() == 0)):
+            return True
+        if n_phases() == 1: #this bombs out if no latches
+            return False
+        else:
+            result = try_phase()
+            return result
+    elif len(z)>2: #Try the next eligible phase.
+        abc('r %s_phase_temp.aig'%f_name)
+        if p == z[2]: #already tried this
+            return False
+        p = z[2]
+        print 'Trying phase = %d: => '%p,
+        abc('phase -F %d'%p)
+        if no == n_pos(): #nothing happened because p is not mod period
+            print 'Phase = %d is not compatible'%p
+            return False
+        abc('r %s_phase_temp.aig'%f_name)
+        abc('&get;&frames -o -F %d;&scl;&put'%p)
+        smp_trace = smp_trace + ['phase -F %d'%p]
+        print 'Simplify with %d phases: '%p,
+        simplify(1)
+##        res =a_trim() #maybe we don't need this because rel_cost uses n_real_inputs
+        cost = rel_cost([ni,nl,na])
+        print 'New relative cost = %f'%(cost)
+        if cost < -.01:
+            print 'Phase abstraction with %d phases obtained:'%p,
+            print_circuit_stats()
+            abc('w %s_phase_temp.aig'%f_name)
+            if ((n_latches() == 0) or (n_ands() == 0)):
+                return True
+            if n_phases() == 1: # this bombs out if no latches
+                return True
+            else:
+                result = try_phase()
+                return result
+        else:
+            smp_trace = smp_trace + ['de_phase']
+    abc('r %s_phase_temp.aig'%f_name)
+    return False
+
+def try_temp(t=15):
+    global smp_trace,aigs
+    btime = time.clock()
+##    res = a_trim() #maybe we don't want this here.
+    print'Trying temporal decomposition - for max %0.2f sec. '%(t),
+    abc('w %s_best_temp.aig'%f_name)
+##    ni = n_pis()
+    ni = n_real_inputs()
+    nl = n_latches()
+    na = n_ands()
+    best = [ni,nl,na]
+    cost_best = 0
+    i_best = 0
+    n_done = 0
+    print 'best = ',
+    print best
+    F = create_funcs([18],t) #create a timer function
+    F = F + [eval('(pyabc_split.defer(struc_temp)())')]
+    F = F + [eval('(pyabc_split.defer(full_temp)())')]
+    F = F + [eval('(pyabc_split.defer(two_temp)())')]
+    for i,res in pyabc_split.abc_split_all(F):
+##        print i,res
+        if i == 0:
+            break
+        if n_latches() == 0:
+            return True
+        n_done = n_done+1
+        cost = rel_cost(best)
+        if cost<0:
+            nri=n_real_inputs()
+            best = (nri,n_latches(),n_ands())
+            abc('w %s_best_temp.aig'%f_name)
+            i_best = i
+            cost_best = cost
+            print 'cost = %.2f, best = '%cost,
+            print best
+##            if i == 1:
+##                smp_trace = smp_trace + ['tempor -s']
+##            if i == 2:
+##                smp_trace = smp_trace + ['tempor']
+##        if n_latches == 0:
+##            break
+        if n_done > 2:
+            break
+##    cost = rel_cost(best)
+    cost = cost_best
+    print 'cost = %0.2f'%cost
+    abc('r %s_best_temp.aig'%f_name)
+##    if cost < -.01:
+    if cost<0:
+        ps()
+        return True
+    else:
+##        smp_trace = smp_trace + ['de_tempor']
+##        abc('r %s_best_temp.aig'%f_name)
+        return False
+
+def struc_temp():
+    abc('tempor -s;scr')
+    result = quick_simp()
+    if result == 'UNSAT':
+        return Unsat
+    elif result == 'SAT':
+        return Sat
+    return Undecided
+
+def full_temp():
+    abc('tempor')
+    return simplify()
+
+def try_temps(t=20):
+    """ need to modify something to be able to update cex"""
+    global smp_trace
+    abc('w %s_try_temps.aig'%f_name)
+    best = (n_pis(),n_latches(),n_ands())
+    npi = n_pis()
+    F = 1
+    while True:
+        res = try_temp(t)
+        ps()
+        if n_latches() == 0:
+            break
+        if res == False:
+            return False,F
+        if ((best == (n_pis(),n_latches(),n_ands())) or n_ands() > .9 * best[2] ):
+            break
+        else:
+            smp_trace = smp_trace + ['tempor']
+            best = (n_pis(),n_latches(),n_ands())
+    return True,n_pis()/npi
+        
+def rel_cost_t(J):
+    """ weighted relative costs versus previous stats."""
+    if (n_latches() == 0 and J[1]>0):
+        return -10
+    nli = J[0]+J[1]
+    na = J[2]
+    if ((nli == 0) or (na == 0)):
+        return 100
+    nri = n_real_inputs()
+    #ri = (float(nri)-float(ni))/float(ni)
+    rli = (float(n_latches()+nri)-float(nli))/float(nli)
+    ra = (float(n_ands())-float(na))/float(na)
+    cost = 10*rli + 1*ra #changed from .5 to 1 on ra
+    return cost    
+
+def rel_cost(J):
+    """ weighted relative costs versus previous stats."""
+    global f_name
+    if (n_latches() == 0 and J[1]>0):
+        return -10
+    nri = n_real_inputs()
+    ni = J[0]
+    nl = J[1]
+    na = J[2]
+    if (ni == 0 or na == 0 or nl == 0):
+        return 100
+    ri = (float(nri)-float(ni))/float(ni)
+    rl = (float(n_latches())-float(nl))/float(nl)
+    ra = (float(n_ands())-float(na))/float(na)
+    cost = 1*ri + 5*rl + .25*ra
+##    print 'Relative cost = %0.2f'%cost
+    return cost
+
+def best_fwrd_min(J,t=30):
+    global f_name, methods,smp_trace
+    J=[18]+J
+    mtds = sublist(methods,J)
+    F = create_funcs(J,t)
+    (m,result) = fork_best(F,mtds) #FORK here
+    print '%s: '%mtds[m],
+    smp_trace = smp_trace + ['%s'%mtds[m]]
+    
+def try_forward():
+    """Attempts most forward retiming, and latch correspondence there. If attempt fails to help simplify, then we revert back to the original design
+    This can be effective for equivalence checking problems where synthesis used retiming"""
+    abc('w %s_savetemp.aig'%f_name)
+    if n_ands() < 30000:
+        abc('dr')
+        abc('lcorr')
+        nl = n_latches()
+        na = n_ands()
+        abc('w %s_savetemp0.aig'%f_name)
+        abc('r %s_savetemp.aig'%f_name) 
+        abc('dretime -m')
+        abc('lcorr')
+        abc('dr')
+        if ((n_latches() <= nl) and (n_ands() < na)):
+            print 'Forward retiming reduced size to: ',
+            print_circuit_stats()
+            return
+        else:
+            abc('r %s_savetemp0.aig'%f_name)
+            return
+    return
+
+def qqsimp():
+    abc('&get;&scl;,reparam;&scorr -C 0;&scl;,reparam;&put')
+    shrink()
+    abc('w %ssimp.aig'%f_name)
+    ps()
+
+
+def quick_simp():
+    """A few quick ways to simplify a problem before more expensive methods are applied.
+    Uses & commands if problem is large. These commands use the new circuit based SAT solver"""
+    na = n_ands()
+    if na < 60000:
+        abc('scl -m;lcorr;drw')
+    else:
+        abc('&get;&scl;&lcorr;&put')
+    if n_ands() < 500000:
+        abc('drw')
+    print 'Using quick simplification',
+    status = process_status(get_status())
+    if status <= Unsat:
+        result = RESULT[status]
+    else:
+        ps()
+        result = 'UNDECIDED'
+    return result
+
+def scorr_constr():
+    """Extracts implicit constraints and uses them in signal correspondence
+    Constraints that are found are folded back when done"""
+    global aigs
+    na = max(1,n_ands())
+    n_pos_before = n_pos()
+    if ((na > 40000) or n_pos()>1):
+        return Undecided_no_reduction
+    abc('w %s_savetemp.aig'%f_name)
+    na = max(1,n_ands())
+##    f = 1
+    f = 18000/na  #**** THIS can create a bug 10/15/11. see below
+    f = min(f,4)
+    f = max(1,f)
+    print 'Looking for constraints - ',
+    if n_ands() > 18000:
+        cmd = 'unfold -s -F 2'
+    else:
+        cmd = 'unfold -F %d -C 5000'%f
+    abc(cmd)
+    if n_pos() == n_pos_before:
+        print 'none found'
+        return Undecided_no_reduction
+    if (n_ands() > na): #no constraints found
+        abc('r %s_savetemp.aig'%f_name)
+        return Undecided_no_reduction
+    na = max(1,n_ands())
+    f = 1 #put here until bug is fixed.
+    print 'found %d constraints'%((n_pos() - n_pos_before))
+    abc('scorr -c -F %d'%f)
+    abc('fold')
+    res = a_trim()
+    print 'Constrained simplification: ',
+    ps()
+    return Undecided_no_reduction
+
+def a_trim():
+    """ this is set up to put the aig on the aigs list if trim was successful"""
+##    print 'trimming'
+##    print 5.1
+    pushed = check_push() #checking if a push is needed and if so do it.
+                        #It is not needed if flops match previous aig
+##    print 5.2
+    res = trim()
+##    print 5.3
+    if res:
+        aigs_pp()
+##        aigs.push() #store the aig after rpm if it did something
+    elif pushed: #since trim did not do anything, we don't need the last push done by check push
+        dump() #dump the last aig on the list
+##    print 5.4
+    return res
+
+def try_scorr_c(f):
+    """ Trying multiple frames because current version has a bug."""
+    global aigs
+    set_globals()
+    abc('unfold -F %d'%f)
+    abc('scorr -c -F %d'%f)
+    abc('fold')
+    t = max(1,.1*G_T)
+    abc('&get;,bmc3 -vt=%f'%t)
+    if is_sat(): 
+        return 0
+    else:
+        res = a_trim()
+        return 1
+    
+
+def input_x_factor():
+    """Sets the global x_factor according to user input"""
+    global x_factor, xfi
+    print 'Type in x_factor:',
+    xfi = x_factor = input()
+    print 'x_factor set to %f'%x_factor
+
+
+def prove(a=0,abs_tried = False):
+    """Proves all the outputs together. If ever an abstraction
+        was done then if SAT is returned,
+        we make RESULT return "undecided".
+        is a == 0 do smp and abs first
+        If a == 1 do smp and spec first 
+        if a == 2 do quick simplification instead of full simplification, then abs first, spec second"""
+    global x_factor,xfi,f_name, last_verify_time,K_backup, t_init, sec_options, spec_found_cex
+    spec_first = False
+    max_bmc = -1
+    abs_found_cex_after_spec = spec_found_cex_after_abs = False
+    if not '_smp' in f_name: #if already simplified, then don't do again
+        if a == 2 : #do quick simplification
+            result = quick_simp() #does not write 'smp' file
+##            print result
+        else :
+            result = prove_part_1() #do full simplification here
+        if ((result == 'SAT') or (result == 'UNSAT')):
+            return result
+    if n_latches() == 0:
+        return 'UNDECIDED'
+    if a == 1:
+        spec_first = True
+    t_init = 2
+    abs_found_cex_before_spec = spec_found_cex_before_abs = False
+##    First phase
+    if spec_first:
+        result = prove_part_3() #speculation done here first
+        if result == 'UNDECIDED' and abs_tried and n_pos() <= 2:
+            add_trace('de_speculate')
+            return result
+    else:
+        abs_tried = True
+        result = prove_part_2() #abstraction done here first
+    if ((result == 'SAT') or (result == 'UNSAT')):
+        return result
+##    Second phase
+    if spec_first: #did spec already in first phase
+        t_init = 2
+        abs_tried = True
+        result = prove_part_2() #abstraction done here second
+        if result == 'SAT':
+            abs_found_cex_after_spec = True
+    else:
+        result = prove_part_3()  #speculation done here second
+        if result == 'SAT':
+            if '_abs' in f_name:
+                spec_found_cex_after_abs = True
+            else:
+                return result
+    if result == 'UNSAT': 
+        return result
+    status = get_status()
+    if result == 'ERROR':
+        status = Error
+    if ('_abs' in f_name and spec_found_cex_after_abs): #spec file should not have been written in speculate
+        f_name = revert(f_name,1) #it should be as if we never did abstraction.
+        add_trace('de_abstract')
+        print 'f_name = %s'%f_name
+        abc('r %s.aig'%f_name) #restore previous
+        t_init = 2
+        if not '_rev' in f_name:
+            print 'proving speculation first'
+            write_file('rev') #maybe can get by with just changing f_name
+            print 'f_name = %s'%f_name
+            result = prove(1,True) #1 here means do smp and then spec 
+            if ((result == 'SAT') or (result == 'UNSAT')):
+                return result
+    elif ('_spec' in f_name and abs_found_cex_after_spec): #abs file should not have been written in abstract
+        f_name = revert(f_name,1) #it should be as if we never did speculation.
+        add_trace('de_speculate')
+        abc('r %s.aig'%f_name) #restore previous 
+        t_init = 2
+        if not '_rev' in f_name:
+            print 'proving abstraction first'
+            write_file('rev') #maybe can get by with just changing f_name
+            result = prove(0)
+            if ((result == 'SAT') or (result == 'UNSAT')):
+                return result
+    else:
+        return 'UNDECIDED'
+
+def prove_part_1():
+    global x_factor,xfi,f_name, last_verify_time,K_backup,aigs
+    print 'Initial: ',
+    ps()
+    x_factor = xfi
+    set_globals()
+    if n_latches() > 0:
+##        ps()
+        res = try_frames_2()
+        if res:
+            print 'frames_2: ',
+            ps()
+            aigs_pp('push','phase')
+        print '\n***Running pre_simp'
+        add_trace('pre_simp')
+        result = run_par_simplify()
+        status = result[0]
+        method = result[1]
+        if 'scorr' in method:
+            add_trace(method)
+    else:
+        print '\n***Circuit is combinational, running check_sat'
+        add_trace('comb_check')
+        status = check_sat()
+    if ((status <= Unsat) or (n_latches() == 0)):
+        return RESULT[status]
+    res =a_trim()
+    if not '_smp' in f_name:
+        write_file('smp') #need to check that this was not written in pre_simp
+    set_globals()
+    return RESULT[status]
+
+def run_par_simplify():
+    set_globals()
+    t = 1000
+    funcs = [eval('(pyabc_split.defer(pre_simp)())')]
+    J = [35]+pdrs[:3]+bmcs[:3]+intrps[:1]+sims  # 35 is par_scorr
+    J = modify_methods(J,1)
+##    J = J + bestintrps
+    funcs = create_funcs(J,t)+ funcs #important that pre_simp goes last
+    mtds =sublist(methods,J) + ['pre_simp']
+    print mtds
+    result = fork_last(funcs,mtds)
+    status = get_status()
+    return [status] + [result]
+
+def try_frames_2():
+    abc('scl')
+    nl = n_latches()
+    if n_ands()> 35000:
+        return
+    abc('w %s_temp.aig'%f_name)
+    abc('&get;&frames -o -F 2;&scl;&put')
+    if n_latches() < .75*nl:
+        print 'frames_2: Number of latches reduced to %d'%n_latches()
+        add_trace('frames_2')
+##        res = reparam()
+##        xxxxx handle this
+##        if res:
+##            aigs.push()
+        return True
+    abc('r %s_temp.aig'%f_name)
+    return False
+    
+def prove_part_2(ratio=.75):
+    """does the abstraction part of prove"""
+    global x_factor,xfi,f_name, last_verify_time,K_backup, trim_allowed,ifbip
+    print'\n***Running abstract'
+##    print 'ifbip = %d'%ifbip
+    status = abstract(ifbip) #ABSTRACTION done here
+    status = process_status(status)
+    print 'abstract done, status is %s'%str(status)
+    result = RESULT[status]
+    if status < Unsat:
+        print 'CEX in frame %d'%cex_frame()
+        return result #if we found a cex we do not want to trim.
+    return result
+    
+def prove_part_3():
+    """does the speculation part of prove"""
+    global x_factor,xfi,f_name, last_verify_time,init_initial_f_name
+    global max_bmc, sec_options
+##    if ((n_ands() > 36000) and sec_options == ''):
+##        sec_options = 'g'
+##        print 'sec_options set to "g"'
+    print '\n***Running speculate on %s: '%f_name,
+    ps()
+##    add_trace('speculate')
+    status = speculate() #SPECULATION done here
+    status = process_status(status)
+##    print 'speculate done, status is %d'%status
+    result = RESULT[status]
+    if status < Unsat:
+        print 'CEX in frame %d'%cex_frame()
+        return result
+    return result
+
+def prove_all(dir,t):
+    """Prove all aig files in this directory using super_prove and record the results in results.txt
+    Not called from any subroutine
+    """
+##    t = 1000 #This is the timeoout value
+    xtime = time.time()
+##    dir = main.list_aig('')
+    results = []
+    f =open('results_%d.txt'%len(dir), 'w')
+    for name in dir:
+        read_file_quiet_i(name)
+        print '\n         **** %s:'%name,
+        ps()
+        F = create_funcs([18,6],t) #create timer function as i = 0 Here is the timer
+        for i,res in pyabc_split.abc_split_all(F):
+            break
+        tt = time.time()
+        if i == 0:
+            res = 'Timeout'
+        str = '%s: %s, time = %0.2f'%(name,res,(tt-xtime))
+        if res == 'SAT':
+            str = str + ', cex_frame = %d'%cex_frame()
+        str = str +'\n'
+        f.write(str)
+        f.flush()
+        results = results + ['%s: %s, time = %0.2f'%(name,res,(tt-xtime))]
+        xtime = tt
+##    print results
+    f.close()
+    return results  
+
+def remove_pos(lst):
+    """Takes a list of pairs where the first part of a pair is the PO number and
+    the second is the result 1 = disproved, 2 = proved, 3 = unresolved. Then removes
+    the proved and disproved outputs and returns the aig with the unresolved
+    outputs"""
+    proved = disproved = unresolved = []
+    for j in range(len(lst)):
+        jj = lst[j]
+        if jj[1] == 2:
+            proved = proved + [jj[0]]
+        if (jj[1] == 1 or (jj[1] == 0)):
+            disproved = disproved +[jj[0]]
+        if jj[1] > 2:
+            unresolved = unresolved +[jj[0]]
+    print '%d outputs proved'%len(proved)
+    if not proved == []:
+        if ((max(proved)>n_pos()-1) or min(proved)< 0):
+            print proved
+        remove(proved,0)
+            
+
+#functions for proving multiple outputs in parallel
+#__________________________________________________
+
+def prove_only(j):
+    """ extract the jth output and try to prove it"""
+    global max_bmc, init_initial_f_name, initial_f_name, f_name,x
+    #abc('w %s__xsavetemp.aig'%f_name)
+    extract(j,j)
+    set_globals()
+    ps()
+    print '\nProving output %d'%(j)
+    f_name = f_name + '_%d'%j
+    result = prove_1()
+    #abc('r %s__xsavetemp.aig'%f_name)
+    if result == 'UNSAT':
+        print '********  PROVED OUTPUT %d  ******** '%(j)
+        return Unsat
+    if result == 'SAT':
+        print '********  DISPROVED OUTPUT %d  ******** '%(j)
+        return Sat
+    else:
+        print '********  UNDECIDED on OUTPUT %d  ******** '%(j)
+        return Undecided
+
+def verify_only(j,t):
+    """ extract the jth output and try to prove it"""
+    global max_bmc, init_initial_f_name, initial_f_name, f_name,x, reachs, last_cex, last_winner, methods
+##    ps()
+##    print 'Output = %d'%j
+    extract(j,j)
+##    ps()
+    set_globals()
+    if n_latches() == 0:
+        result = check_sat()
+    else:
+        f_name = f_name + '_%d'%j
+        # make it so that jabc is not used here
+        reachs_old = reachs
+        reachs = reachs[1:] #just remove jabc from this.
+        res = verify(slps+sims+pdrs+bmcs+intrps,t) #keep the number running at the same time as small as possible.
+##        res = verify(sims+pdrs+bmcs+intrps,t) #keep the number running at the same time as small as possible.
+        reachs = reachs_old
+        result = get_status()
+        assert res == result,'result: %d, status: %d'%(res,get_status())
+    if result > Unsat:
+##        print result
+##        print '******* %d is undecided ***********'%j
+        return result
+    elif result == Unsat:
+##        print '******** PROVED OUTPUT %d  ******** '%(j)
+        return result
+    elif ((result < Unsat) and (not result == None)):
+        print '******** %s DISPROVED OUTPUT %d  ******** '%(last_cex,j)
+##        print ('writing %d.status'%j), result, get_status()
+        abc('write_status %d.status'%j)
+        last_winner = last_cex
+        return result
+    else:
+        print '****** %d result is %d'%(j,result) 
+        return result
+
+def verify_range(j,k,t):
+    """ extract the jth thru kth output and try to prove their OR"""
+    global max_bmc, init_initial_f_name, initial_f_name, f_name,x, reachs, last_cex, last_winner, methods
+    extract(j,k)
+    abc('orpos')
+    set_globals()
+    if n_latches() == 0:
+        result = check_sat()
+    else:
+        f_name = f_name + '_%d'%j
+        # make it so that jabc is not used here
+        reachs_old = reachs
+        reachs = reachs[1:] #just remove jabc from this.
+        res = verify(sims+pdrs+bmcs+intrps,t) #keep the number running at the sme time as small as possible.
+        reachs = reachs_old
+        result = get_status()
+        assert res == result,'result: %d, status: %d'%(res,get_status())
+    if result > Unsat:
+##        print result
+##        print '******* %d is undecided ***********'%j
+        return result
+    elif result == Unsat:
+##        print '******** PROVED OUTPUT %d  ******** '%(j)
+        return result
+    elif ((result < Unsat) and (not result == None)):
+        print '******** %s DISPROVED OUTPUT %d  ******** '%(last_cex,j)
+##        print ('writing %d.status'%j), result, get_status()
+        abc('write_status %d.status'%j)
+        last_winner = last_cex
+        return result
+    else:
+        print '****** %d result is %d'%(j,result) 
+        return result
+
+def prove_n_par(n,j):
+    """prove n outputs in parallel starting at j"""
+    F = []
+    for i in range(n):
+        F = F + [eval('(pyabc_split.defer(prove_only)(%s))'%(j+i))]
+    #print S
+    #F = eval(S)
+    result = []
+    print 'Proving outputs %d thru %d in parallel'%(j,j+n-1)
+    for i,res in pyabc_split.abc_split_all(F):
+        result = result +[(j+i,res)]
+    #print result
+    return result
+
+def prove_pos_par(t,BREAK):
+    """Prove all outputs in parallel and break on BREAK"""
+    return run_parallel([],t,BREAK)
+
+def prove_pos_par0(n):
+    """ Group n POs grouped and prove in parallel until all outputs have been proved"""
+    f_name = initial_f_name
+    abc('w %s__xsavetemp.aig'%f_name)
+    result = []
+    j = 0
+    N = n_pos()
+    while j < N-n:
+        abc('r %s__xsavetemp.aig'%f_name)
+        result = result + prove_n_par(n,j)
+        j = j+n
+    if N > j:
+        result = result + prove_n_par(N-j,j)
+    abc('r %s__xsavetemp.aig'%initial_f_name)
+    ps()
+##    print result
+    remove_pos(result)
+    write_file('group')
+    return
+
+def prop_decomp():
+    """decompose a single property into multiple ones (only for initial single output),
+    by finding single and double literal primes of the outputs."""
+    if n_pos()>1:
+        return
+    run_command('outdec -v -L 2')
+    if n_pos()>1:
+        ps()
+
+
+def distribute(N,div):
+    """
+    we are going to verify outputs in groups
+    """
+    n = N/div
+    rem = N - (div * (N/div))
+    result = []
+    for j in range(div):
+        if rem >0:
+            result = result +[n+1]
+            rem = rem -1
+        else:
+            result = result + [n]
+    return result    
+
+        
+def extract(n1,n2):
+    """Extracts outputs n1 through n2"""
+    no = n_pos()
+    if n2 > no:
+        return 'range exceeds number of POs'
+    abc('cone -s -O %d -R %d'%(n1, 1+n2-n1))
+
+def remove_intrps(J):
+    global n_proc,ifbip
+##    print J
+    npr = n_proc
+    if 18 in J:
+        npr = npr+1
+    if len(J) <= npr:
+##        print J
+        return J
+    JJ = []
+    alli = [23,1,22] # if_no_bip, then this might need to be changed
+    l = len(J)-npr
+    alli = alli[l:]
+##    J.reverse() #strip off in reverse order.
+    for i in J:
+        if i in alli: 
+            continue
+        else:
+            JJ = JJ+[i]
+##    print JJ
+    return JJ
+
+def restrict(lst,v=0):
+    '''restricts the aig to the POs in the list'''
+    #this assumes that there are no const-1 POs. Warning, this will not remove any const-0 POs
+    N = n_pos()
+    lst1 = lst + [N]
+    r_lst = gaps(lst1) #finds POs not in lst
+    if len(r_lst) == N:
+        return
+    remove(r_lst,v)
+        
+def remove(lst,v=0):
+    """Removes outputs in list
+    WARNING will not remove all POs even if in lst
+    """
+    global po_map
+    n_before = n_pos()
+    zero(lst,v)
+    l=remove_const_pos(v)
+    assert len(lst) == (n_before - n_pos()),'Inadvertantly removed some const-0 POs.\nPO_before = %d, n_removed = %d, PO_after = %d'%(n_before, len(lst), n_pos())
+    print 'PO_before = %d, n_removed = %d, PO_after = %d'%(n_before, len(lst), n_pos())
+
+
+def zero(list,v=0):
+    """Zeros out POs in list"""
+    if v == 0:
+        cmd = 'zeropo -s -N ' #puts const-0 in PO
+    else:
+        cmd = 'zeropo -so -N ' #puts const-1 in PO
+    for j in list:
+        run_command('%s%d'%(cmd,j)) #-s prevents the strash after every zeropo
+    abc('st')
+
+def listr_0_pos():
+    """ returns a list of const-0 pos and removes them
+    """  
+    L = range(n_pos())
+    L.reverse()
+    ll = []
+    for j in L:
+        i = is_const_po(j)
+        if i == 0:
+            abc('removepo -N %d'%j) #removes const-0 output
+##            print 'removed PO %d'%j
+            ll = [j] + ll
+    return ll
+
+def list_0_pos():
+    """ returns a list of const-0 pos and removes them
+    """
+    abc('w %s_savetemp.aig'%f_name)
+    L = range(n_pos())
+    L.reverse()
+    ll = []
+    for j in L:
+        i = is_const_po(j)
+        if i == 0:
+            abc('removepo -N %d'%j) #removes const-0 output
+##            print 'removed PO %d'%j
+            ll = [j] + ll
+    abc('r %s_savetemp.aig'%f_name)
+    return ll
+
+def listr_1_pos():
+    """ returns a list of const-1 pos and removes them
+    """  
+    L = range(n_pos())
+    L.reverse()
+    ll = []
+    for j in L:
+        i = is_const_po(j)
+        if i == 1:
+            abc('removepo -z -N %d'%j) #removes const-1 output
+##            print n_pos()
+            ll = [j] + ll
+    return ll
+
+
+def mark_const_pos(ll=[]):
+    """ creates an indicator of which PO are const-0 and which are const-1
+        does not change number of POs
+    """
+    n=n_pos()
+    L = range(n)
+    ll = [-1]*n
+    for j in L:
+        ll[j] = is_const_po(j)
+    print sumsize(ind)
+    return ind
+
+def remove_const_pos(n=-1):
+    global po_map
+    """removes the const 0  or 1 pos according to n, but no pis because we might
+    get cexs and need the correct number of pis
+    """
+    if n > -1:
+        run_command('&get; &trim -i -V %d; &put'%n) #V is 0 or 1
+    else:
+        run_command('&get; &trim -i; &put') #removes both constants
+
+def unmap_cex():
+    """ aig before trim is put in reg-space and after trim in the &space
+        Before and after need to have same number of flops in order o reconcile
+        aigs list should be such that if before and after don't match in number of latches,
+        then some operation changed the flops and we just update the aig with the new number
+        reconcile leaves before aig in reg-space after cex has been updated so cex and aig
+        always match
+    """
+    global aigs,hist
+    print hist
+##    while not aigs == []:
+    while not len(hist) == 0:
+        n = n_latches()
+        abc('&get') #save the current aig in &-space
+        print 'Number of PIs in cex = %d'%n_cex_pis()
+        typ = aigs_pp('pop')
+        print typ,
+        ps()
+        if typ == 'phase':
+            typ2 =aigs_pp('pop') #gets the aig before phase
+            abc('phase -c')
+            print 'Number of PIs in cex = %d, Number of frames = %d'%(n_cex_pis(),cex_frame())
+            run_command('testcex -a')
+            hist = hist + [typ2]
+            continue
+        if typ == 'tempor':
+            typ2 = aigs_pp('pop') #gets the aig before tempor
+            abc('tempor -c')
+            print 'Number of PIs in cex = %d, Number of frames = %d'%(n_cex_pis(),cex_frame())
+            run_command('testcex -a')
+            hist = hist + [typ2]
+            continue
+        if typ == 'reparam':
+            nn = n_latches()
+            abc('&get') #put 'after' in &space
+            typ2 = aigs_pp('pop') #get previous to put before in reg-space
+            run_command('reconcile')
+            print 'Number of PIs in cex = %d'%n_cex_pis()
+##                reconcile(True) #maps the cex from &-space aig to current aig
+            run_command('testcex -a')
+            if not typ2 == 'reparam0':
+                hist = hist + [typ2] #put back (aig iss still there so just have to restore hist
+            continue
+            #else we just leave the aig updated
+        else:
+            assert typ == 'initial','type is not initial'
+            size = str([n_pis(),n_pos(),n_latches(),n_ands()])
+            print 'cex length = %d'%cex_frame()
+            tr = ['cex length = %d'%cex_frame()] + ['cex matches original aig = %s'%size]
+            print 'cex matches original aig'
+            return tr
+##    print 'cex matches original aig'
+    
+                                  
+def sp(n=0,t=900,check_trace=False):
+    """Alias for super_prove, but also resolves cex to initial aig"""
+    global initial_f_name
+    print 'Executing super_prove'
+    result = super_prove(n,t)
+    print '%s is done and is %s'%(initial_f_name,result[0])
+    print 'sp: ',
+    print result
+    if result[0] == 'SAT' and check_trace:
+        res = unmap_cex()
+        result1 = result[1]+ res
+        result = ['SAT'] + result1
+        report_cex()
+    report_bmc_depth(max(max_bmc,n_bmc_frames()))
+    return result
+
+def mp():
+    multi_prove_iter()
+
+def report_cex():
+    abc('write_status %s_cex.status'%init_initial_f_name)
+
+def sumsize(L):
+    d = count_less(L,0)
+    u = count_less(L,1)-d
+    s = count_less(L,2) - (d+u)
+    return 'SAT = %d, UNSAT = %d, UNDECIDED = %d'%(s,u,d)
+
+def unmap(L,L2,map):
+    mx = max(list(map))
+    assert mx <= len(L2),'max of map = %d, length of L2 = %d'%(mx,len(L))
+    for j in range(len(map)):
+        L[j] = L2[map[j]] #expand results of L2 into L
+    return L
+
+def unmap2(L2,map):
+    mx = max(list(map))
+    assert mx <= len(L2),'max of map = %d, length of L2 = %d'%(mx,len(L))
+    L=[-1]*len(map)
+    for j in range(len(map)):
+        L[j] = L2[map[j]] #expand results of L2 into L
+    return L 
+
+def create_map(L,N):
+    """ map equivalence classes into their representative."""
+##    print L
+    mapp = [-1]*N
+    m = -1
+    error = False
+    for j in range(len(L)):
+        lj = L[j]
+        for k in range(len(lj)):
+            mapp[lj[k]] = j
+##        print lj
+        mm = min(lj)
+##        print mm
+        if not mm == lj[0]: #check if rep is not first on list
+            print 'ERROR: rep is not first, mm = %d, lj[0] = %d'%(mm,lj[0])
+            error = True
+        if mm <= m: #check if iso_classes are in increasing order of representatives.
+            print 'ERROR: in iso map mm < m, mm = %d, m = %d'%(mm,m)
+            error = True
+        m = mm
+    assert not error,'ERROR'
+    return mapp
+
+
+def weave(L1,lst0,lst1):
+    """ interleave values of L1 and with 1's in positions given in lst1,
+        and 0's in lst0. It is assumed that these lists are in num order..
+        Final list has len = len(L1)+len(lst0)+len(lst1)"""
+    L = [-1]*(len(L1)+len(lst0)+len(lst1))
+##    print len(L)
+    if lst0 == []:
+        if lst1 == []:
+            return L1
+        lst = lst1
+        v = 1
+    if lst1 == []:
+        lst = lst0
+        v = 0
+    l = k = 0
+    for j in range(len(L)):
+##        print L
+        if j == lst[l]:
+            L[j] = v
+            if l+1 < len(lst):
+                l = l+1
+        else: #put in value in L1
+            L[j] = L1[k]
+            if k+1 < len(L1):
+                k = k+1
+    return L
+
+def quick_mp(t):
+    t1 =time.time()
+    l1 = list_0_pos()
+    S,l2,s = par_multi_sat(t)
+    l2 = indices(s,1)
+    remove(l2,1)
+    abc('scl')
+    simple()
+    ps()
+    print'time = %0.2f'%(time.time() - t1)
+
+def indices(s,v):
+    """return in indices of s that have value v"""
+    L = []
+    for i in range(len(s)):
+        if s[i]== v:
+            L = L+[i]
+    return L
+
+def expand(s,ind,v):
+    """expand s by inserting value v at indices ind"""
+    N = len(s)+len(ind)
+    ind1 = ind+[N]
+    g = gaps(ind1)
+    ss = [-1]*N
+    for i in ind:
+        ss[i] = v
+    j = 0
+    for i in g: #put original values in ss
+        ss[i] = s[j]
+        j = j+1
+    for j in ind:
+        assert ss[j] == v, 'ss = %s, ind = %s'%(str(ss),str(ind))
+    return ss
+
+def remove_v(ss,v):
+    s = []
+    for i in range(len(ss)):
+        if ss[i] == v:
+            continue
+        else:
+            s = s + [ss[i]]
+    return s
+                 
+def multi_prove(op='simple',tt=900,n_fast=0, final_map=[]):
+    """two phase prove process for multiple output functions"""
+    global max_bmc, init_initial_f_name, initial_f_name,win_list, last_verify_time
+    global f_name_save,nam_save,_L_last,file_out
+    x_init = time.time()
+    abc('&get;&scl;,reparam -aig=%s_rpm.aig; r %s_rpm.aig')
+    print 'Initial after &scl and reparam = ',
+    ps()
+    abc('w %s_initial_save.aig'%init_initial_f_name)
+    #handle single output case differently
+    _L_last = [-1]*n_pos()
+    if n_pos() == 1:
+        result = sp(2000)
+##        abc('w %s_unsolved.aig'%init_initial_f_name)
+        rs=result[0]
+        if rs == 'SAT':
+            report_result(0,1)
+            L = [1]
+        elif rs == 'UNSAT':
+            report_result(0,0)
+            L = [0]
+        elif rs == 'UNDECIDED':
+            report_result(0,-1)
+            L = [-1]
+        else: #error
+            L = [2]
+        res = sumsize(L)
+        rr = '\n@@@@ Time =  %d '%(time.time() - t_iter_start) + res
+        print rr
+        file_out.write(rr+ '\n')
+        file_out.flush()
+        return L
+##    print 'Removing const-0 POs'
+    NNN = n_pos()
+    lst0 = listr_0_pos() #remove const-0 POs and record
+##    print lst0
+    lst0.sort()
+    N = n_pos()
+    L = [-1]*N
+    print 'Removed %d const-0 POs'%len(lst0)
+    res = 'SAT = 0, UNSAT = %d, UNDECIDED = %d'%(len(lst0),N)
+    rr = '\n@@@@ Time =  %.2f: '%(time.time() - t_iter_start)
+    report_L(lst0,0) ##########
+    rr = rr + res
+    print rr
+    file_out.write(rr + '\n')
+    file_out.flush()
+    ttt = n_ands()/1000
+    if ttt < 10:
+        ttt=10
+    elif ttt<20:
+        ttt = 20
+    elif ttt< 30:
+        ttt = 30
+    else:
+        ttt = 50
+    S,lst1,s = par_multi_sat(ttt,1,1,1) #run engines in parallel looking for SAT outputs
+    lst1 = indices(s,1)
+##    print S,lst1
+    #put 0 values into lst0
+    lst10 = indices(s,0) #new unsat POs in local indices (with lst0 removed)
+    if not lst10 == []:
+        print 'lst10 = %s'%str(lst10)
+    lst11 = indices(s,1) #local variables
+    ss = expand(s,lst0,0) #ss will reflect original indices
+    report_s(ss)
+    lst0_old = lst0
+    lst0 = indices(ss,0) #additional unsat POs added to initial lst0 (in original indices)
+    print 'lst0 = %s'%str(lst0)
+    assert len(lst0) == len(lst0_old)+len(lst10), 'lst0 = %s, lst0_old = %s, lst10 = %s'%(str(lst0),str(lst0_old),str(lst10))
+    sss = remove_v(ss,0) #remove the 0's from ss
+    assert len(sss) == len(ss)-len(lst0), 'len(sss) = %d, len(ss) = %d, len(lst0) = %d'%(len(sss),len(ss),len(lst0))
+    lst1_1 = indices(sss,1) #The sats now reflect the new local indices.
+                #It makes it as if the newly found unsat POs were removed initially
+                #done with new code
+    assert len(lst1_1) == len(lst1), 'mismatch, lst1 = %d, lst1_1 = %d'%(len(lst1),len(lst1_1))
+    lst1 = lst1_1 #lst1 should be in original minus lst0
+    print 'Found %d SAT POs'%len(lst1)
+    print 'Found %d UNSAT POs'%len(lst10)
+    res = 'SAT = %d, UNSAT = %d, UNDECIDED = %d'%(len(lst1),len(lst0),NNN-(len(lst1)+len(lst0)))
+    rr = '\n@@@@ Time =  %.2f: '%(time.time() - t_iter_start)
+    rr = rr + res
+    print rr
+    file_out.write(rr + '\n')
+    file_out.flush()
+    N = n_pos()
+    print len(lst10),n_pos()
+    if not len(lst10) == n_pos() and len(lst10) > 0:
+        remove(lst10,1) #remove 0 POs
+        print 'Removed %d UNSAT POs'%len(lst10)
+        N = n_pos()
+    elif len(lst10) == n_pos():
+        N = 0 #can't remove all POs. Must proceed as if there are no POs. But all POs are UNSAT.
+    print len(lst1),N,S #note: have not removed the lst1 POs.
+    if len(lst1) == N or S == 'UNSAT' or N == 0: #all POs are SAT
+        L = [0]*N #could just put L as all 1's. If N = 0, all POs are UNSAT and lst1 = []
+        for i in range(len(lst1)): #put 1's in SAT POs
+            L[lst1[i]]=1
+        L = weave(L,lst0,[]) #expand L, and put back 0 in L. 
+        report_results(L)
+        print sumsize(L)
+        print 'Time = %.2f'%(time.time() - x_init) 
+        return L
+##    print 'removing them'
+    if not len(lst1)== n_pos():
+        remove(lst1,1) #here we removed all POs in lst1 (local indices)
+        abc('&get;&scl;&put')
+    ##    lst1 = bmcj_ss_r(2) #find easy cex outputs
+    ##    write_file('bmc1')
+        print 'Removed %d SAT POs'%len(lst1)
+        N = n_pos()
+    else:
+        N = 0
+    if N == 1: #this was wrong. Need to report in original indices???
+        result = sp(2000)
+        rs=result[0]
+        #need to find out original index of remaining PO
+        if rs == 'SAT':
+            v = 1
+        elif rs == 'UNSAT':
+            v = 0
+        elif rs == 'UNDECIDED':
+            v = -1
+        else: #error should not happen, but be conservative
+            v = -1
+        L = [v]*N
+        L = weave(list(L),[],lst1) #put back 1 in L
+        L = weave(list(L),lst0,[]) #put back 0 in L
+        report_results(L)
+        res = sumsize(L)
+        rr = '\n@@@@ Time =  %d '%(time.time() - t_iter_start) + res
+        print rr
+        file_out.write(rr+ '\n')
+        file_out.flush()
+        return L
+    L1 =L = [-1]*N
+    if N > 1 and N < 10000 and n_ands() < 500000: #keeps iso in
+##    if N > 1 and N < 10000 and False: #temporarily disable iso
+        print 'Mapping for first isomorphism: '
+        res = iso() #reduces number of POs
+        if res == True:
+            abc('&get;&scl;&put')
+            write_file('iso1')
+            leq = eq_classes()
+##        print leq
+            map1 = create_map(leq,N) #creates map into original
+##        print map1
+            if not count_less(L,0) == N:
+                print L
+            L1 = [-1]*n_pos()
+##        L1 = pass_down(L,list(L1),map1) # no need to pass down because L will have no values at this point.
+        else:
+            map1 =range(N)
+    else:
+        map1 = range(N)
+    N = n_pos()
+##    print 4
+    r = pre_simp() #pre_simp
+    write_file('smp1')
+    NP = n_pos()/N #if NP > 1 then NP unrollings were done in pre_simp.
+    if NP > 1:
+        L1 = duplicate_values(L1,NP) # L1 has only -1s here. Put in same valuess for iso POs
+    if n_pos() > N:
+        assert NP>=2, 'NP not 2, n_pos = %d, N = %d, NP = %d'%(n_pos(),N,NP)
+    print 'pre_simp done. NP = %d\n\n'%NP
+    #WARNING: if phase abstraction done, then number of POs changed.
+    if r[0] == Unsat:
+        print 'example is UNSAT'
+        L1 = [0]*N #all outputs are UNSAT
+        print sumsize(L1)
+        print 'unmapping for iso'
+        L = unmap(list(L),L1,map1)
+        print "putting in easy cex's and easy unsat's"
+        L = weave(list(L),[],lst1) #put back 1 in L
+        L = weave(list(L),lst0,[]) #put back 0 in L
+        print sumsize(L)
+        print 'Time = %.2f'%(time.time() - x_init)
+        report_results(L)
+        return L
+    f_name_save = f_name
+    nam_save = '%s_initial_save.aig'%f_name
+    #########do second iso here
+    N = n_pos()
+    if N == 1:
+        map2 = [0]
+        L2=[-1]
+##        write_file('1')
+##        L = output(list(L),list(L1),L2,map1,map2,lst0,lst1,NP)
+        L = output2(list(L2),map1,map2,lst0,lst1,NP)
+        result = simple(2000,1)
+        Ss = rs = result[0]
+        if rs == 'SAT':
+            L2 = [1]
+        if rs == 'UNSAT':
+            L2 = [0]
+    else:
+##        if False and N < 10000: #temp disable iso
+        if N < 10000 and n_ands() < 500000: 
+            print 'Mapping for second isomorphism: '
+            res = iso() #second iso - changes number of POs
+            if res == True:
+                abc('&get;&scl;&put')
+                map2 = create_map(eq_classes(),N) #creates map into previous
+            else:
+                map2 = range(n_pos())
+        else:
+            map2 = range(n_pos())
+        write_file('iso2')
+        print 'entering par_multi_sat'
+        S,lbmc,s = par_multi_sat(2*ttt,1,1,1) #look for SAT POs
+        lmbc = indices(s,1)
+        print 'par_multi_sat ended'
+        if len(lmbc)>0:
+            print 'found %d SAT POs'%len(lmbc)
+        L2 = s
+##        #first mprove for 10-20 sec.
+        ps()
+        print 'Before first mprove2, L2 = %s'%sumsize(L2)
+        DL = output2(list(L2),map1,map2,lst0,lst1,NP) #reporting intermediate results
+##        DDL = output3(range(len(L2)),map1,map2,lst0,lst1,NP)
+##        print 'DDL = %s'%str(DDL)
+        if n_fast == 1:
+            abc('w %s_unsolved.aig'%init_initial_f_name)
+            return DL
+        NN=n_ands()
+        #create timeout time for first mprove2
+        ttt = 10
+        if NN >30000:
+            ttt = 15
+        if NN > 50000:
+            ttt = 20
+        abc('w %s_before_mprove2.aig'%f_name)
+        print '%s_before_mprove2.aig written'%f_name
+        print 'L2 = %s'%str(L2)
+        print 'Entering first mprove2 for %d sec.'%ttt,
+        Ss,L2 = mprove2(list(L2),op,ttt,1) #populates L2 with results
+##        print Ss,L2
+        if Ss == 'SAT':
+            print 'At least one PO is SAT'
+        if Ss == 'ALL_SOLVED':
+            if count_less(L2,0)>0:
+                print 'ERROR'
+##            L = output(list(L),list(L1),L2,map1,map2,lst0,lst1,NP) # final report of results.
+            L = output2(list(L2),map1,map2,lst0,lst1,NP)
+            return L
+        print 'After first mprove2: %s'%sumsize(L2)
+    time_left = tt - (time.time()-x_init)
+    N = count_less(L2,0)
+    if N > 0 and n_fast == 0:
+##        output(list(L),list(L1),L2,map1,map2,lst0,lst1,NP) #reporting new intermediate results
+        L = output2(list(L2),map1,map2,lst0,lst1,NP)
+        t = max(100,time_left/N)
+        t_all = 100
+    S = sumsize(L2)
+    T = '%.2f'%(time.time() - x_init)
+    print '%s in time = %s'%(S,T)
+    abc('w %s_unsolved.aig'%init_initial_f_name)
+    N = n_pos()
+    ttime = 100
+    J = slps+intrps+pdrs+bmcs+sims
+    #do each output for ttime sec.
+    Nn = count_less(L2,0)
+##    assert N == len(L2),'n_pos() = %d, len(L2) = %d'%(N,len(L2))
+    if Nn > 0:
+        found_sat = 0
+        print 'final_all = %d, Ss = %s'%(final_all,str(Ss))
+        if final_all and not Ss == 'SAT':
+            print 'Trying to prove all %d remaining POs at once with super_prove'%Nn
+            remove_proved_pos(L2)
+            result = super_prove()
+            if result[0] == 'UNSAT': #all remaining POs are UNSAT
+                for i in range(len(L2)):
+                    if L2[i] < 0:
+                        L2[i] = 0
+##                L = output(list(L),list(L1),L2,map1,map2,lst0,lst1,NP) # final report of results. 
+                L = output2(list(L2),map1,map2,lst0,lst1,NP)
+                return L
+            if result == 'SAT':
+                found_sat = 1
+        if found_sat or not final_all or Ss == 'SAT':
+            print 'Trying each remaining PO for %d sec.'%ttime
+            found_sat = 0
+##            ttime = 10
+            for i in range(N):
+                if L2[i] > -1:
+                    continue
+                print '\n**** cone %d ****'%i
+                abc('r %s_unsolved.aig'%init_initial_f_name)
+                abc('cone -s -O %d'%i)
+                abc('&get;&scl;&lcorr;&put')
+                result = verify(J,ttime)
+                r = result[0]
+                if r > 2:
+                    continue
+                elif r == 2:
+                    L2[i] = 0
+                else:
+                    L2[i] = 1
+                    found_sat = 1
+##                output(list(L),list(L1),L2,map1,map2,lst0,lst1,NP)
+                L = output2(list(L2),map1,map2,lst0,lst1,NP)
+            if Ss == 'SAT' and found_sat: #previous solve_all was SAT and found at least 1 PO SAT
+                abc('r %s_unsolved.aig'%init_initial_f_name)
+                if not count_less(L2,0) == 0:
+                    remove_proved_pos(L2)
+                    simplify()
+                    write_file('save')
+                    result = simple(2000,1)
+                    if_found = False
+                    if result[0] == 'UNSAT':
+                        for i in range(N):
+                            if L2[i] == -1:
+                                L2[i] = 0
+                    elif result[0] == 'SAT' and n_pos() == 1:
+                        for i in range(N):
+                            if L2[i] == -1:
+                                if if_found == True:
+                                    print 'Error: more that 1 UNDECIDED remained in L2'
+                                    break
+                                L2[i] = 1
+                                if_found = True
+                    else:
+                        if result[0] == 'SAT':
+                            print 'at least 1 unsolved PO is SAT'
+##    L = output(list(L),list(L1),L2,map1,map2,lst0,lst1,NP) # final report of results.
+    L = output2(list(L2),map1,map2,lst0,lst1,NP)
+    return L
+
+def create_unsolved(L):
+    abc('r %s_initial_save.aig'%init_initial_f_name) 
+    lst = []
+    assert len(L) == n_pos(),'lengths of L and n_pos = %d,%d'%(len(L),n_pos())
+    for i in range(len(L)):
+        if L[i] > -1: #solved PO
+            lst = lst + [i]
+    assert max(lst) < n_pos(), 'error in lengths'
+    assert count_less(L,0) == n_pos() - len(lst),'mismatch'
+    remove(lst,-1) # remove solved
+    
+def multi_prove_iter():
+    global t_iter_start,file_out,ff_name
+    ff_name = init_initial_f_name
+    file_out = open('%s_time_results.txt'%init_initial_f_name, 'w') #
+    t_iter_start = time.time()
+    L = multi_prove()
+    d = count_less(L,0)
+    u = count_less(L,1)-d
+    s = count_less(L,2) - (d+u)
+    rr =  '\n@@@@@ %s: Final time =  %.2f '%(init_initial_f_name,(time.time() - t_iter_start))
+    rr = rr + 'SAT = %d, UNSAT = %d, UNDECIDED = %d '%(s,u,d)
+    print rr
+    file_out.write(rr)
+    res = PO_results(L)
+    file_out.write(res)
+##    print res
+    file_out.flush()
+    file_out.close()
+    #at this point could restrict to SAT(UNSAT) POs and invoke solver to verify all POs are SAT(UNSAT)
+    return
+
+def restrict_v(L,v):
+    """ L is a list of 0,1,-1"""
+    lst = []
+    for j in range(len(L)):
+        if L[j] == v:
+            lst = lst + [j]
+    restrict(lst)
+    return lst
+
+def PO_results(L):
+    global ff_name
+    S=U=UD=[]
+    for j in range(len(L)):
+        ll = L[j]
+        if ll == -1:
+            UD = UD + [j]
+        elif ll == 0:
+            U = U + [j]
+        elif ll == 1:
+            S = S + [j]
+        else:
+            print 'error, L contains a non -1,0,1'
+    res = "[[SAT = %s], [UNSAT = %s], [UNDECIDED = %s]"%(str(S),str(U),str(UD))
+    #restore initial unsolved POs
+    abc('r %s.aig'%ff_name)
+    if not UD == []:
+        restrict(UD,0)
+        abc('w %s_UNSOLVED.aig'%ff_name)
+        print 'Unsolved POs restored as %s_UNSOLVED.aig'%ff_name
+    else:
+        print 'All POs were solved'
+    abc('r %s.aig'%ff_name) #what if original had constraints.
+    abc('fold')
+    if not U == []: 
+        restrict(U,1) #we use 1 here because do not want to remove const-0 POs which should be in U
+        abc('w %s_UNSAT.aig'%ff_name)
+        print 'Unsat POs restored as %s_UNSAT.aig'%ff_name
+    abc('r %s.aig'%ff_name)
+    abc('fold')
+    if not S == []:
+        restrict(S,0)
+        abc('w %s_SAT.aig'%ff_name)
+        print 'Sat POs restored as %s_SAT.aig'%ff_name
+    return res
+
+def syn3():
+    t = time.clock()
+    run_command('&get;&b; &jf -K 6; &b; &jf -K 4; &b;&put')
+    ps()
+    print 'time = %.2f'%(time.clock() - t)
+
+def syn4():
+    t = time.clock()
+    abc('&get;&b; &jf -K 7; &fx; &b; &jf -K 5; &fx; &b;&put')
+    ps()
+    print 'time = %.2f'%(time.clock() - t)
+
+
+def solve_parts(n):
+    global t_iter_start,file_out
+    r=range(n)
+    r.reverse()
+    name = init_initial_f_name
+    results = []
+    for i in r:
+        file_out.write('\n@@@@ Starting part%d: \n'%i)
+        file_out.flush()
+        abc('r %s_part%d.aig'%(name,i))
+        print '\nPart%d: '%i
+        L = multi_prove()
+        rr =  '\n@@@@ Time =  %.2f '%(time.time() - t_iter_start)
+        rr = rr + 'Part%d: '%i
+        ssl = sumsize(L)
+        rr = rr + ssl
+        results = results + [[ssl]]
+        print rr
+        file_out.write(rr + '\n')
+        file_out.flush()
+    return results
+
+def cp(n=10):
+    return chop_prove(n)
+
+def chop_prove(n=10,t=100):
+    global t_iter_start,file_out
+    tm = time.time()
+    abc('w %s_chop_temp.aig'%f_name)
+    N = max(5,n_pos()/n)
+    J = 0
+    total = []
+    np = n_pos()
+    while J < np:
+        abc('r %s_chop_temp.aig'%f_name)
+        E = J+N-1
+        R = N
+        if E > np-1:
+            R = N - (E - (np -1))
+        abc('cone -s -O %d -R %d'%(J,R))
+        npp = n_pos()
+        print '\n\n*****     solving outputs %d to %d     *****'%(J,(J+R-1))
+        f_map = str([J]*R + range(R))
+        funcs = create_funcs(slps,t)
+        funcs = funcs + [eval('(pyabc_split.defer(mp)(simple,%s,1,%s))'%(t,f_map))] #1 means do fast mp
+##        funcs = funcs + [eval('(pyabc_split.defer(sp)())')]
+        for i,res in pyabc_split.abc_split_all(funcs):
+            print 'Method %d returned first with result = %s'%(i,res)
+            if i == 0:
+                res = 'SAT = 0, UNSAT = 0, UNDECIDED = %d'%npp
+                rr = '\n@@@@ Time =  %.2f: '%(time.time() - t_iter_start)
+                rr = rr + 'chop%d: '%i
+                rr = rr + res
+                print rr
+                file_out.write(rr + '\n')
+                file_out.flush()
+                break
+            if i == 1:
+                rr = '\n@@@@ Time =  %.2f: '%(time.time() - t_iter_start)
+                rr = rr + 'chop%d: '%i
+                rr = rr + res
+                file_out.write(rr + '\n')
+                file_out.flush()
+##                print res
+                break
+            else:
+                if res == 'UNSAT':
+                    res = 'SAT = 0, UNSAT = %d, UNDECIDED = 0'%npp
+                    rr = '\n@@@@ Time =  %.2f: '%(time.time() - t_iter_start)
+                    rr = rr + 'chop%d: '%i
+                    rr = rr + res
+                    print rr
+                    file_out.write(rr + '\n')
+                    file_out.flush()
+                    break
+                else:
+                    res = 'SAT = 0, UNSAT = 0, UNDECIDED = %d'%npp
+                    rr = '\n@@@@ Time =  %.2f: '%(time.time() - t_iter_start)
+                    rr = rr + 'chop%d: '%i
+                    rr = rr + res
+                    print rr
+                    file_out.write(rr + '\n')
+                    file_out.flush()
+                    break
+##        print res
+        total = total + [[res]]
+        print total
+        J = J + R
+    c = get_counts(total)
+    tm = time.time() - tm
+    rr = '\n@@@@ Total time for chop = %.2f, SAT = %d, UNSAT = %d, UNDECIDED = %d'%(tm,c[0],c[1],c[2])
+    file_out.write(rr + '\n')
+    file_out.flush()
+    print rr
+    return total
+
+def get_counts(L):
+    s=u=d=0
+    for i in range(len(L)):
+        li = L[i][0]
+##        print li
+        j1=li.find('=')
+        j2 = li.find(',')
+        num = int(li[j1+1:j2])
+        s = s+num
+        li = li[j2+1:]
+        j1=li.find('=')
+        j2 = li.find(',')
+        num = int(li[j1+1:j2])
+        u = u+num
+        li = li[j2+1:]
+        j1=li.find('=')
+        j2 = li.find(',')
+        num = int(li[j1+1:])
+        d = d+num
+    return [s,u,d]
+        
+
+def output(L,L1,L2,map1,map2,lst0,lst1,NP,final_map=[]):
+    global t_iter_start
+    print_all(L,L1,L2,map1,map2,lst0,lst1,NP,final_map=[])
+    #print 'L = %s, L1 = %s, L2 = %s'%(sumsize(L),sumsize(L1),sumsize(L2))
+    L1 = unmap(list(L1),L2,map2)
+    print 'L1 after map2 = %s'%sumsize(L1)
+    if NP > 1: #an unrolling was done
+        L1 = check_and_trim_L(NP,list(L1))#map into reduced size before unrolling was done by phase.
+        print 'L1 = %s'%sumsize(L1)
+    L = unmap(list(L),L1,map1)
+    print 'L after map1 = %s'%sumsize(L)
+    L = weave(list(L),[],lst1) #put back 1 in L
+    print 'L after lst1 = %s'%sumsize(L)
+    L = weave(list(L),lst0,[]) #put back 0 in L
+    print 'L after lst0= %s'%sumsize(L) 
+    report_results(list(L),final_map)
+    return L
+
+def output2(L2,map1,map2,lst0,lst1,NP,final_map=[]):
+    global t_iter_start
+##    print_all(L,L1,L2,map1,map2,lst0,lst1,NP,final_map=[])
+    #print 'L = %s, L1 = %s, L2 = %s'%(sumsize(L),sumsize(L1),sumsize(L2))
+    L1 = unmap2(L2,map2)
+    print 'L1 after map2 = %s'%sumsize(L1)
+##    if NP > 1: #an unrolling was done
+##        L1 = check_and_trim_L(NP,list(L1))#map into reduced size before unrolling was done by phase.
+##        print 'L1 = %s'%sumsize(L1)
+    L = unmap2(L1,map1)
+    print 'L after map1 = %s'%sumsize(L)
+    L = weave(list(L),[],lst1) #put back 1 in L
+    print 'L after lst1 = %s'%sumsize(L)
+    L = weave(list(L),lst0,[]) #put back 0 in L
+    print 'L after lst0= %s'%sumsize(L) 
+    report_results(list(L),final_map)
+    return L
+
+def output3(L2,map1,map2,lst0,lst1,NP,final_map=[]):
+    """ find out where results came from"""
+    global t_iter_start
+    L1 = unmap2(L2,map2)
+    L = unmap2(L1,map1)
+    L = weave(list(L),[],lst1) #put back 1 in L
+    L = weave(list(L),lst0,[]) #put back 0 in L
+    return L
+
+def print_all(L,L1,L2,map1,map2,lst0,lst1,NP,final_map=[]):
+##    return
+    print 'L = ',
+    print L
+    print 'L1 = ',
+    print L1
+    print 'L2 = ',
+    print L2
+    print 'map1 = ',
+    print map1
+    print 'map2 = ',
+    print map2
+    print 'lst0 = ',
+    print lst0
+    print 'lst1 = ',
+    print lst1
+
+
+def rnge(n,m):
+    """ return interval n+range(m)"""
+    N = []
+    for j in range(m):
+        N = N + [n + j]
+    return N
+
+def create_cluster(n=0,p=1,L=100):
+    """n is the start node and p is the multiplier on the # of POs to extract
+        ll is the limit on the number of latches to include"""
+    clstr=rem = [] #make a list of nodes to remove because not compatible
+    N = 0 #number of end skips
+    init = False
+    skip=0 #number of initial skips
+    abc('w temp.aig')
+    np = n_pos()
+    for i in range(np):
+        if n + p*(i+1-skip) > np:
+            if n_latches() > L:
+                bp = n_pos()-p 
+                remove(rnge(bp,p),1) #remove last p
+                abc('scl')
+            return clstr
+        abc('r temp.aig')
+        abc('cone -s -O %d -R %d;scl'%(n,p*(i+1-skip)))
+        xx = n_pos()
+        if n_latches() > L:
+            if not init: #have not found start point yet
+                n=n+p #increase start point
+                print 'n,FF = %d,%d'%(n,n_latches())
+                skip = skip + 1
+                continue
+        else:
+            if not init:
+##                nn=p*(i-skip)
+##                clstr = clstr + rnge(nn,p*(i+1-skip))
+##                print clstr #initial cluster
+                init = True
+##        abc('w old.aig')
+        remove(rem,1)
+        abc('scl')
+        ps()
+        if n_latches() > L:
+            x = xx - p #remove last p POs
+            rem = rem + rnge(x,p)
+##            print len(rem)
+            print 'x,len(rem) = %d,%d,%d'%(x,len(rem))
+            N = N+1
+        else:
+            bn=p*(i-skip)
+            nr=rnge(bn,p)
+            clstr = clstr + nr
+        if N > 100: #don't do more than 10 end-skips
+            bp = n_pos()-p 
+            remove(rnge(bp,p),1) #put last p on remove list
+            abc('scl')
+            return clstr
+
+def generate_clusters(b=0,inc=10,end=100):
+    abc('w temp_gen_clstr.aig')
+    abc('w t_gen_cl.aig')
+    clusters = []
+    while True:
+        abc('r t_gen_cl.aig')
+        clstr = create_cluster(b,inc,end)
+        clusters = clusters + [clstr]
+        abc('r t_gen_cl.aig')
+        if clstr == []:
+            return clusters
+        remove(clstr,1)
+        abc('w t_gen_cl.aig')
+
+def map_clusters_to_original(cl):
+    L = range(n_pos())
+    Clstrs = []
+    k = 0
+    for j in range(len(cl)):
+        c = cl[j]
+        cc = pick(L,c)
+        Clstrs = Clstrs + [cc]
+        L = pick_not(L,cc)
+    return Clstrs
+
+def pick(L,c):
+    """ computes L(c) """
+    x=[]
+    for i in range(len(c)):
+        x = x + [L[c[i]]]
+    return x
+
+def pick_not(L,c):
+    """ computes L(~c)"""
+    x = []
+    for i in range(len(L)):
+        if not i in c:
+            x = x + [L[i]]
+    return x
+
+def report_L(lst=[],v=0):
+    """lst must refer to original PO numbering"""
+    global _L_last
+    if lst == []:
+        return
+    for j in lst:
+        if _L_last[j] == -1: #means not reported yet
+            _L_last[j] = v
+            report_result(j,v)
+
+def report_s(s):
+    """s must refer to original PO numbering
+    Differs from above """
+    global _L_last
+    assert len(s) == len(_L_last), 'two lengths are not equal'
+    if s == []:
+        return
+    for j in range(len(s)):
+        if not _L_last[j] == s[j]: #means not reported yet
+            assert _L_last[j] == -1, 'j = %d, _L_last[j] = %d, s[j] = %d'%(j,_L_last[j],s[j])
+            if _L_last[j] == -1:
+                _L_last[j] = s[j]
+                report_result(j,s[j])
+    
+
+def report_results(L,final_map=[],if_final=False):
+    global _L_last,t_iter_start,file_out
+    out = '\n@@@@ Time = %.2f: results = %s'%((time.time()- t_iter_start),sumsize(L))
+    print out
+    file_out.write(out + '\n')
+    file_out.flush()
+    for j in range(len(L)):
+        if not L[j] == _L_last [j]:
+            assert _L_last[j] == -1, '_L_last[j] = %d, L[j] = %d'%(_L_last[j],L[j])
+            report_result(j,L[j])
+    _L_last = list(L) #update _L_last
+##    print 'report: _L_last = %s'%sumsize(_L_last)
+    print '\n'
+
+def report_result(POn, REn, final_map=[]):
+    if final_map == []:
+        print 'PO = %d, Result = %d:  '%(POn, REn),
+    else:
+        print 'PO = %d, Result = %d:  '%(final_map[POn], REn),
+
+
+def scorr_T(t=10000):
+    global smp_trace, scorr_T_done
+    if scorr_T_done:
+        return
+    scorr_T_done = 1
+    print 'Trying scorr_T (scorr -C 2, &scorr, &scorr -C 0)'
+    funcs = [eval('(pyabc_split.defer(abc)("scorr -C 2"))')]
+    funcs = funcs + [eval('(pyabc_split.defer(abc)("&get;&scorr;&put"))')]
+    funcs = funcs + [eval('(pyabc_split.defer(abc)("&get;&scorr -C 0;&put"))')]
+    funcs = create_funcs(slps,t)+funcs
+    mtds = sublist(methods,slps) + ['scorr2','&scorr','&scorr0']
+    best = n_ands()
+    abc('w %s_best_T.aig'%f_name)
+    name1 = '%s_sc1.aig'%f_name
+    if os.access(name1,os.R_OK):
+        os.remove(name1)
+    name2 = '%s_sc2.aig'%f_name
+    if os.access(name2,os.R_OK):
+        os.remove(name2)
+    name3 = '%s_sc3.aig'%f_name
+    if os.access(name3,os.R_OK):
+        os.remove(name3)
+    N=m_best = 0
+    for i,res in pyabc_split.abc_split_all(funcs):
+        if i == 0:
+            break
+        if i == 1:
+            abc('w %s_sc1.aig'%f_name)
+            print 'scorr: ',
+            ps()
+            N=N+1
+        if N == 3 or n_latches() == 0:
+                break
+        if i == 2 or n_latches() == 0:
+            abc('w %s_sc2.aig'%f_name)
+            print '&scorr: ',
+            ps()
+            N=N+1
+            if N == 3:
+                break
+        if i == 3 or n_latches() == 0:
+            abc('w %s_sc3.aig'%f_name)
+            print '&scorr0: ',
+            ps()
+            N=N+1
+            if N == 3:
+                break
+    if os.access(name1,os.R_OK):
+        abc('r %s'%name1)
+        if n_ands() < best:
+            best = n_ands()
+            m_best = 1
+            abc('w %s_best_T.aig'%f_name)
+    if os.access(name2,os.R_OK):
+        abc('r %s'%name2)
+        if n_ands() < best:
+            m_best = 2
+            best = n_ands()
+            abc('w %s_best_T.aig'%f_name)
+    if os.access(name3,os.R_OK):
+        abc('r %s'%name3)
+        if n_ands() < best:
+            m_best = 3
+            best = n_ands()
+            abc('w %s_best_T.aig'%f_name)
+    smp_trace = smp_trace + ['%s'%mtds[m_best]]
+    abc('r %s_best_T.aig'%f_name)
+
+def pscorr(t=900):
+    result = par_scorr(t)
+    if n_ands() == 0:
+        return result
+    else:
+        return 'UNDECIDED'
+
+def par_scorr(t=30,ratio = 1):
+    t_init = time.time()
+##    abc('dr -m;drw')
+    abc('dretime;dc2')
+    funcs = [eval('(pyabc_split.defer(abc)("scorr -vq -F 1"))')]
+    funcs = funcs + [eval('(pyabc_split.defer(abc)("scorr -vq -F 2"))')]
+    funcs = funcs + [eval('(pyabc_split.defer(abc)("scorr -vq -F 4"))')]
+    funcs = funcs + [eval('(pyabc_split.defer(abc)("scorr -vq -F 8"))')]
+    funcs = funcs + [eval('(pyabc_split.defer(abc)("scorr -vq -F 16"))')]
+    funcs = create_funcs(slps,t)+funcs
+    mtds = sublist(methods,slps) + ['scorr1','scorr2', 'scorr4', 'scorr8', 'scorr16']
+    best = n_ands()
+    print 'par_scorr: best = %d'%best
+    abc('w %s_best.aig'%f_name)
+    idone = []
+    for i,res in pyabc_split.abc_split_all(funcs):
+##        print i,res
+        if i == 0: #timeout
+            break
+        else:
+            idone = idone + [i]
+            if n_ands() <= ratio * best:
+                best = n_ands()
+##                print 'par_scorr: best = %d, method = %s'%(best, mtds[i])
+                abc('w %s_best.aig'%f_name)
+                if best == 0 or len(idone) >= 5:
+                    mtd = mtds[i]
+                    break
+            else:
+                break
+##    print 'Time: %.2f'%(time.time() - t_init)
+    abc('r %s_best.aig'%f_name)
+##    if best == 0:
+##        print mtd
+    return mtd
+
+def par_scorr_q(t=10000,ratio = 1):
+    abc('dretime;dc2')
+    abc('bmc2 -T 5')
+    depth = n_bmc_frames()
+    mtds = funcs = []
+    n=1
+    while True:
+        funcs = funcs + [eval('(pyabc_split.defer(abc)("scorr -vq -F %d"))'%n)]
+        mtds = mtds + ['scorr%d'%n]
+        n = 2* n
+        if n > max(1,min(depth,16)):
+            break
+    funcs = create_funcs(slps,t)+funcs
+    mtds = sublist(methods,slps) + mtds
+    best = n_ands()
+    print 'best = %d'%best
+    abc('w %s_best.aig'%f_name)
+    idone = []
+    for i,res in pyabc_split.abc_split_all(funcs):
+##        print i,res
+        if i == 0:
+            break
+        else:
+            idone = idone + [i]
+            if n_ands() <= ratio * best:
+                best = n_ands()
+                print 'best = %d, method = %s'%(best, mtds[i])
+                abc('w %s_best.aig'%f_name)
+                if best == 0 or len(idone) >= len(mtds)-1:
+                    break
+            else:
+                break
+    abc('r %s_best.aig'%f_name)
+
+
+def indicate_0_pos(L2):
+    """
+    puts 0's in L2 where the corresponding output is driven by a const-0
+    """
+##    assert n_pos() == len(L2), 'list L2=%d and n_pos=%d in current AIG dont match'%(len(L2),n_pos())
+    for j in range(n_pos()):
+        i=is_const_po(j)
+        if i == 0:
+            L2[j]=0
+    return L2
+
+def list_0_pos():
+    """
+    returns indices of outputs driven by  const-0
+    """
+    L = []
+    for j in range(n_pos()):
+        i=is_const_po(j) #returns const value of PO if const. Else -1
+        if i == 0:
+            L = L + [j]
+    return L
+
+def mprove2(L=0,op='simple',t=100,nn=0):
+    global _L_last, f_name, skip_spec
+    print 'mprove2 entered' ,
+    if L == 0:
+        L = [-1]*n_pos()
+    ps()
+    print 'mprove2 entered with L = ',
+    print sumsize(L)
+    abc('w %s_mp2.aig'%f_name) #save aig before pos removed
+    old_f_name = f_name #we may call sp() which can change f_name
+    n = count_less(L,0)
+    ind = []
+    for j in range(len(L)):
+        if L[j] > -1:
+            ind = ind +[j]
+    if len(ind) == n_pos(): #all POs already solved
+        return 'ALL_SOLVED',L
+    remove(ind,-1) #remove solved POs
+    if len(ind)>0:
+        print 'Removed %d proved POs'%len(ind)
+    if n_pos() == 0:
+        f_name = old_f_name
+        abc('r %s_mp2.aig'%f_name)
+        return 'ALL_SOLVED',L
+    ps()
+    N = n_pos()
+    if N == 1: #only one PO left
+        v = -1
+        skip_spec_old = skip_spec
+        skip_spec = True
+        result = simple(2000,1)
+        ff_name == f_name
+        result = sp(0,2000) #warning sp() can change f_name. 0 means simplify
+        f_name = ff_name
+        skip_spec = skip_spec_old
+        res = result[0]
+        print 'result of sp = ',
+        print res
+####        print result
+        if res == 'SAT':
+            v = 1
+        if res == 'UNSAT':
+            v = 0
+        i = L.index(-1)
+##        print 'i=%d,v=%d,L=%s'%(i,v,str(L))
+        L[i] = v
+        f_name = old_f_name #if sp() changed f_name need to revert to old f_name
+        abc('r %s_mp2.aig'%f_name)
+        print 'reverting %s_mp2.aig'%f_name,
+        ps()
+        print sumsize(L)
+        if v > -1:
+            res = 'ALL_SOLVED'
+        return res,L
+    r = pre_simp()
+    NP = n_pos()/N
+    L1 = [-1]*n_pos()
+    Llst0 = []
+    if r[0] == Unsat:
+        L1 = [0]*N
+    else:
+        Llst0 = list_0_pos()
+        Llst0.sort()
+        print 'Llst0 = %s'%str(Llst0)
+        n_0 = len(Llst0)
+        if n_0 > 0:
+##            print 'Found %d const-0 POs'%n_0
+            remove(Llst0,0)
+            print 'Removed %d const-0 POs'%len(Llst0)
+        if NP > 1: # we want to do iso here because more than one phase was found.
+            iso()  # additional iso - changes number of POs
+            map3 = create_map(eq_classes(),N) #creates map into previous
+##        tb = min(n_pos(),20)
+        N = n_pos()
+        tb = min(N,50)
+##        print 'Trying par_multi_sat for %d sec.'%tb
+        S,lst1,s = par_multi_sat(tb,1,1,0) #this gives a list of SAT POs
+        L2 = s10 = s
+        n_solved = n_pos() - count_less(s10,0)
+        if 1 in s10 or 0 in s10: #something solved 
+            if n_solved < N: #not all solved
+                rem = indices(s,0)+indices(s,1)
+                rem.sort()
+                remove(rem,1)
+                """ if lst1 > 1 element, simplify and run par_multi_sat again to get lst2
+                      then merge lst1 and lst2 appropriately to create new lst1 for below.
+                """
+                tb = tb+25
+                gap = max(15,.2*tb)
+                if len(rem) > 0:
+                    s210 = s10
+                    #iterate here as long as more than 1 PO is found SAT
+                    n_solved = n_pos() - count_less(s210,0) 
+                    while n_solved > 0:
+                        gap = int(1+1.2*gap)
+                        print 'gap = %.2f'%gap
+                        pre_simp(1) #warning this may create const-0 pos
+                        S,lst2,s = par_multi_sat(tb,gap,1,0) #this can find UNSAT POs
+                        s210 = s
+                        n_solved = n_pos() - count_less(s210,0)
+                        s10 = put(s210,list(s10)) #put the new values found into s10
+                        if count_less(s10,0) == 0 or n_solved == 0: #all solved or nothing solved
+                            break #s10 has the results
+                        else:
+                            out = '\n@@@@ Time = %.2f: additional POs found SAT = %d'%((time.time()- t_iter_start),len(lst2))
+                            print out
+                            file_out.write(out + '\n')
+                            file_out.flush()
+                            rem = indices(s210,0)+indices(s210,1)
+                            rem.sort()
+                            remove(rem,1) #this zeros the l210 and then removes ALL const-1 POs.
+                                            #If there are more than lst2 removed, it fires an assertion.
+                            continue
+                    L2 = s10 #put results in s10
+                else: #lst1 is empty or S == SAT'
+                    print 'no cex found or S = UNSAT'
+            else: #all solved
+                print 'all POs solved'
+            print 'Removed %d solved POs'%(len(s10) - count_less(s10,0))
+        else:
+            print 'nothing solved'
+        write_file('bmc2')
+        if -1 in s10:
+            print 'Entering solve_all ',
+            ps()
+            S,s210 = solve_all([-1]*n_pos(),900) #solve_all calls sp() or simple but preserves the aig and f_name
+##            else: zzz
+            if -1 in s210: #then no POs were solved by solve_all
+##                abc('r %s_smp2_2.aig'%f_name)
+                if n_pos() < 50:
+                    print 'Entering mprove with %d sec. for each cone'%t,
+                    ps()
+                    print 'L2 before mprove: %s'%sumsize(L2)
+                    s210 = mprove([-1]*n_pos(),op,t) #proving each output separately
+                else:
+                    s210 = [-1]*n_pos()
+            print 's210 after mprove and before inject 1 %s:'%sumsize(s210)
+            L2 = put(s210,s10) 
+            print 'L2 after inject 1 %s:'%sumsize(L2)
+        else: #all POs solved
+            L2 = s10
+        assert NP == 1, 'NP > 1: ERROR'
+        if NP>1: 
+            print 'NP = %d'%NP
+            print 'L1 before unmap3: %s'%sumsize(L1)  #L1 should be all -1's of length before iso 
+            L1 = unmap(list(L1),L2,map3)
+            print 'L1 after unmap of map3: ',
+            print sumsize(L1)
+        else:
+            print 'L2 = %s'%str(L2)
+            L1 = L2
+        L1 = inject(list(L1),Llst0,0)
+        print 'L1 after inject of Llst0 0s: %s:'%sumsize(L1)
+    if NP >1:
+        L1 = check_and_trim_L(NP,L1)
+    assert len(L1)<=len(L),"L1 = %d larger than L = %d"%(len(L1),len(L))
+##    print 'L = %s'%str(L)
+    L = insert(L1,list(L)) # replace -1s in L with values in L1. Size of L1<=L L is really L2
+    print sumsize(L)
+    f_name = old_f_name
+    abc('r %s_mp2.aig'%f_name) #restore aig
+    if 1 in L:
+        S = 'SAT'
+    if not -1 in L:
+        S = 'ALL_PROVED'
+    return S,L
+
+def merge(L1,L2,n=0):
+    """L2 refers to POs that were solved after POs in L1 were removed
+    modifies L2 to refer to the original POs.
+    if n=0 adds in L1 and sorts
+    """
+    if L1 == []:
+        return L2
+    if L2 == []:
+        if n == 0:
+            return L1
+        else:
+            return [] 
+    m = max(L1)
+    LL1 = L1 + [3+m+max(L2)] #this makes sure that there are enough gaps
+    g = gaps(LL1)
+##    print g
+    L = []
+    for i in range(len(L2)):
+        l2i=L2[i]
+        assert  l2i < len(g),'ERROR, L2 = %s,g = %s'%(str(L2),str(g))
+        L = L + [g[l2i]]
+##        print L
+    if n == 0:
+        L = L + L1
+        L.sort()        
+    return L            #L is already sorted
+
+def put(s2,s11):
+    """ put in the values of s2 into where there are -1's in s1 into s1
+    return s2 """
+    s1 = list(s11)
+    k = 0
+    assert len(s2) == count_less(s1,0),'mismatch in put'
+    for j in range(len(s1)):
+        if s1[j] == -1:
+            s1[j] = s2[k]
+            k=k+1
+    return s1
+
+def gaps(L1):
+    """L2 refers to POs that were solved after POs in L1 were removed
+    modifies L2 to refer to the original POs.
+    if n=0 adds in L1 and sorts
+    """
+    if L1 == [] or max(L1)+1 == len(L1):
+        return []
+    L1_gaps = []
+    i=0
+    for j in range(len(L1)):
+        lj=L1[j]
+##        print lj,i
+        if lj == i:
+            i = i+1
+            continue
+        assert lj > i,'Error'
+        while  lj > i:
+            L1_gaps = L1_gaps + [i]
+            i = i+1
+##            print L1_gaps
+        i=i+1
+    return L1_gaps
+
+##    j=i=0
+##    L = []
+##    L1.sort()
+##    L2.sort()
+##    LL1 = L1 + [10000000] #make sure list L2 is processed to the end
+####    print 'L1 and L2 is sorted %d, %d: '%(len(L1),len(L2))
+##    if not L2 == []:
+##        while True:
+##    ##        print i,j
+##            if LL1[i] <= L2[j]:
+##                i = i+1
+##            else:
+##                L= L + [L2[j] + i]
+##    ##            print L
+##                j = j+1
+##                if j == len(L2):
+##                    break
+##    if n == 0:
+##        L = L + L1
+##        L.sort()        
+##    return L            #L is already sorted
+    
+
+def solve_all(L2,t):
+    global f_name, skip_spec
+    abc('w %s_solve_all.aig'%f_name)
+    old_f_name = f_name
+##    abc('orpos')
+##    print 'solve_all for %.2f sec.: '%t,
+##    ps()
+    skip_spec_old = skip_spec
+    skip_spec = True
+    tt = max(t,900)
+    print 'Entering simple for %d sec.'%tt
+    result = simple(tt,1) #### temporary 1 means do not simplify
+##    result = sp(0,t) #warning sp() may change f_name
+    skip_spec = skip_spec_old
+##    print 'solve_all: result = %s'%result
+    if result[0] == 'UNSAT':
+        L2 = [0]*len(L2)
+    f_name = old_f_name
+    abc('r %s_solve_all.aig'%f_name)
+    return result[0],L2
+
+def inject(L,lst,v):
+    """
+    expends the len(L) by len(lst). puts value v in expanded position
+    Preserves values in L
+    """
+    k = i = j = 0 #i indexes L, j indexes lst, and k is total length of LL
+    if lst == []:
+        return L
+    LL = []
+    N = len(L) + len(lst)
+    while True:
+        if lst[j] == k:
+            LL= LL + [v]
+            if j < len(lst)-1:
+                j = j+1
+        else:
+            LL = LL + [L[i]]
+            if i < len(L)-1:
+                i = i+1
+        k = k+1
+        if k >= N:
+            break
+    return LL
+
+def insert(L1,L):
+    """ insert L1 in L and return L"""
+    k=0
+    for j in range(len(L)):
+        if L[j] > -1:
+            continue
+        else:
+            L[j] = L1[k]
+            k = k+1
+            if k >= len(L1):
+                break
+    return L
+                   
+    
+
+def duplicate_values(L1,NP):
+    """ append values """
+##    L=L1*NP
+    L = L1
+    for j in range(NP-1):
+        L = L+[-1]*len(L1)
+    return L
+
+##def duplicate_values2(L1,NP):
+##    """ interleave values """
+##    L = []
+##    for j in range(len(L1)):
+##        v = L1[j]
+##        L = L + [v]*NP
+##    return L
+
+def check_and_trim_L(NP,L):
+    """This happens when an unrolling creates additional POs
+    We want to check that L[j] = L[j+kN] etc to make sure the PO results agree
+    in all phases, i.e. sat, unsat, or undecided. if one is sat then make all L[j+kN] sat,
+    If one is unsat, then all L[j+kN] must be unsat. If not then make L[j]=-1.
+    Return first N of L.
+    """
+    N = len(L)/NP #original number of POs
+    for j in range(N):
+        if L[j] == 1:
+            continue
+        for k in range(NP)[1:]: #k = 1,2,...,NP-1
+            if L[j+k*N] == 1:
+                L[j] = 1
+                break
+            elif L[j] == -1:
+                continue #we have to continue to look for a 1
+            elif L[j] == 0:
+                if L[j+k*N] == -1:
+                    print 'some copies of PO unsat and some undecided'
+                    L[j] = -1
+                    break
+            continue #have to make sure that all phases are 0
+    return L[:N]
+
+def pass_down(L,L1,map):
+    """map maps L into L1.Populate L1 with values in L"""
+##    print len(L),len(L1),len(map),max(map)
+##    print sumsize(L)
+##    print sumsize(L1)              
+    for j in range(len(map)):
+        if L[j] == -1:
+            continue
+        assert L1[map[j]] == -1 or L1[map[j]] == L[j], 'L1=%d, L = %d'%(L1[map[j]],L[j]) 
+        L1[map[j]] = max(L[j],L1[map[j]])
+    return L1
+
+def mpr():
+    tt = time.time()
+    N=n_pos()
+    r = pre_simp()
+    if r == Unsat:
+        L = [0]*N
+    else:
+        L = mprove([-1]*n_pos(),'simple',100)
+    L = L[:N]
+    print sumsize(L)
+    print 'Time = %.2f'%(time.time() - tt)
+    return L
+                
+
+def mprove(L,op='simple',tt=1000):
+    """ 0 = unsat, 1 = sat, -1 = undecided"""
+    global max_bmc, init_initial_f_name, initial_f_name,win_list, last_verify_time
+    global f_name_save, nam_save, temp_dec, f_name
+    f_name_save = f_name
+    nam_save = '%s_mp_save.aig'%f_name
+    abc('w %s'%nam_save)
+    N = len(L)
+    print 'Length L = %d, n_pos() = %d'%(len(L),n_pos())
+    t = tt #controls the amount of time spent on each cone
+    funcs = [eval('(pyabc_split.defer(%s)())'%op)]
+    funcs = create_funcs(slps,t)+funcs
+    mtds = sublist(methods,slps) + [op]
+    res = L
+    NN = count_less(L,0)
+    rr = range(N)
+    rr.reverse()
+    init_name = init_initial_f_name
+    for j in rr:
+        if L[j] > -1:
+            continue #already solved
+        print '\n************** No. Outputs = %d ******************************'%NN
+        abc('r %s'%nam_save) #restore original function
+##        ps()
+        x = time.time()
+        name = '%s_cone_%d.aig'%(f_name,j)
+        print '________%s(%s)__________'%(op,name)
+        abc('cone -s -O %d;scl'%j)
+        abc('w %s_cone.aig'%f_name)
+##        ps()
+        read_file_quiet_i('%s_cone.aig'%f_name) #needed to reset initial settings
+##        ps()
+        temp_dec = False
+        i,result = fork_last(funcs,mtds)
+##        print '\ni = %d, result = %s'%(i,str(result))
+        f_name = f_name_save #restore original f_name
+        T = '%.2f'%(time.time() - x)
+        out = get_status()
+##        print '\nout= %d, result = %s'%(out,str(result))
+        rslt = Undecided
+        if not out == result:
+            print 'out = %d, result = %d'%(out,result)
+##        assert out == result,'out = %d, result = %d'%(out,result)
+        if out == Unsat or result == 'UNSAT' or result == Unsat:
+            res[j] = 0
+            rslt = Unsat
+        if out < Unsat:
+            res[j] = 1
+            rslt = Sat
+        print '\n%s: %s in time = %s'%(name,RESULT[rslt],T)
+    abc('r %s'%nam_save) #final restore of original function for second mprove if necessary.
+    init_initial_f_name = init_name
+##    print res
+    return res
+
+##def sp1(options = ''):
+##    global sec_options
+##    sec_options = options
+##    return super_prove(1)
+
+def super_prove(n=0,t=900):
+    """Main proof technique now. Does original prove and if after speculation there are multiple output left
+    if will try to prove each output separately, in reverse order. It will quit at the first output that fails
+    to be proved, or any output that is proved SAT
+    n controls call to prove(n)
+    is n == 0 do smp and abs first, then spec
+    if n == 1 do smp and spec first then abs
+    if n == 2 just do quick simplification instead of full simplification, then abs first, spec second
+    """
+    global max_bmc, init_initial_f_name, initial_f_name,win_list, last_verify_time, f_name
+##    print 'sec_options = %s'%sec_options
+##    init_initial_f_name = initial_f_name
+    size = str([n_pis(),n_pos(),n_latches(),n_ands()])
+    add_trace('[%s: size = %s ]'%(f_name,size))
+    if x_factor > 1:
+        print 'x_factor = %f'%x_factor
+        input_x_factor()
+    max_bmc = -1
+    x = time.time()
+    add_trace('prove')
+    result = prove(n)
+    print 'prove result = ',
+    print result
+    tt = time.time() - x
+    if ((result == 'SAT') or (result == 'UNSAT')):
+        print '%s: total clock time taken by super_prove = %0.2f sec.'%(result,tt)
+        add_trace('%s'%result)
+        add_trace('Total time = %.2f'%tt)
+        print m_trace
+        return [result]+[m_trace]
+    elif ((result == 'UNDECIDED') and (n_latches() == 0)):
+        add_trace('%s'%result)
+        add_trace('Total time = %.2f'%tt)
+        print m_trace
+        return [result]+[m_trace]
+    print '%s: total clock time taken by super_prove so far = %0.2f sec.'%(result,(time.time() - x))
+    y = time.time()
+    print 'Entering BMC_VER_result'
+    add_trace('BMC_VER_result')
+    result = BMC_VER_result() #this does backing up if cex is found
+    print 'Total clock time taken by last gasp verification = %0.2f sec.'%(time.time() - y)
+    tt = time.time() - x
+    print 'Total clock time for %s = %0.2f sec.'%(init_initial_f_name,tt)
+    add_trace('%s'%result)
+    add_trace('Total time for %s = %.2f'%(init_initial_f_name,tt))
+##    print m_trace
+    return [result]+[m_trace]
+
+def reachm(t):
+    x = time.clock()
+    abc('&get;&reachm -vcs -T %d'%t)
+    print 'reachm done in time = %f'%(time.clock() - x)
+    return get_status()
+
+def reachp(t):
+    x = time.clock()
+    abc('&get;&reachp -rv -T %d'%t)
+    print 'reachm2 done in time = %f'%(time.clock() - x)
+    return get_status()
+
+def scorr():
+    run_command('scorr')
+    ps()
+
+def select_undecided(L):
+    res = []
+    for j in range(len(L)):
+        l = L[j]
+        if l[1] == 'UNDECIDED':
+            res = res + [l[0]]
+    return res
+        
+####def execute(L,t):
+####    """
+####    run the files in the list L using ss, sp, ssm each for max time = t
+####    """
+####    funcs1 = [eval('(pyabc_split.defer(ss)())')]
+####    funcs1 = create_funcs(slps,t)+funcs1
+####    mtds1 =sublist(methods,slps) + ['ss']
+####    funcs2 = [eval('(pyabc_split.defer(sp)())')]
+####    funcs2 = create_funcs(slps,t)+funcs2
+####    mtds2 =sublist(methods,slps) + ['sp']
+####    funcs3 = [eval('(pyabc_split.defer(ssm)())')]
+####    funcs3 = create_funcs(slps,t)+funcs3
+####    mtds3 =sublist(methods,slps) + ['ssm']
+####    for j in range(len(L)):
+####        name = L[j]
+####        print '\n\n\n\n________ss__________'
+####        read_file_quiet(name)
+####        print '****ss****'
+####        fork_last(funcs1,mtds1)
+####        print '***Done with ss on %s\n'%name
+####        print '\n\n******ssm************'
+####        read_file_quiet(name)
+####        print '****ssm****'
+####        fork_last(funcs3,mtds3)
+####        print '***Done with ssm on %s \n'%name
+
+def execute_op(op,L,t):
+    """
+    run the files in the list L using operation "op", each for max time = t
+    """
+    global res
+    funcs = [eval('(pyabc_split.defer(%s)())'%op)]
+    funcs = create_funcs(slps,t)+funcs
+    mtds =sublist(methods,slps) + [op]
+    res = []
+    for j in range(len(L)):
+        x = time.time()
+        name = L[j]
+        print '\n\n\n\n________%s__________'%op
+        read_file_quiet_i(name)
+        m,result = fork_last(funcs,mtds)
+        if result == Undecided:
+            result = RESULT[result]
+        T = '%.2f'%(time.time() - x)
+        new_res = [name,result,T]
+        res = res + [new_res]
+        print '\n%s'%new_res
+    return res
+
+def x_ops(ops,L,t):
+    """ execute each op in the set of ops on each file in the set of files of L, each for time t"""
+    result = []
+    for j in range(len(ops)):
+        op = ops[j]
+        result.append('Result of %s'%op)
+        result.append(execute_op(op,L,t))
+    return result
+
+def iso(n=0):
+    if n_ands() > 500000:
+        return False
+    if n_pos() < 2:
+        print 'no more than 1 output'
+        return False
+    npos=n_pos()
+    if n == 0:
+        abc('&get;&iso -q;&put')
+        if n_pos() == npos:
+            print 'no reduction'
+            return False
+    else:
+        run_command('&get;&iso;iso;&put')
+        if n_pos() == npos:
+            print 'no reduction'
+            return False
+    print 'Reduced n_pos from %d to %d'%(npos,n_pos())
+    return True
+
+def check_iso(N):
+    ans = get_large_po()
+    if ans == -1:
+        return 'no output found'
+    n_iso = count_iso(N)
+    return n_iso
+
+def count_iso(N):
+    abc('&get;write_aiger -u file1.aig') #put this cone in & space and write file1
+##    print 'PO %d is used'%i
+    n_iso = 0 #start count
+    for i in range(N):
+        abc('permute;write_aiger -u file2.aig')
+        n = filecmp.cmp('file1.aig','file2.aig')
+        print n,
+        n_iso = n_iso+n
+    print 'the number of isomorphisms was %d out of %d'%(n_iso,N)
+    return n_iso
+
+def get_large_po():
+##    remove_const_pos() #get rid of constant POs
+    NL = n_latches()
+    NO = n_pos()
+    abc('&get') #put the in & space
+    n_latches_max = 0
+    nl = imax = -1
+    for i in range(NO): #look for a big enough PO
+        abc('&put;cone -s -O %d;scl'%i)
+        nl = n_latches()
+        if nl >.15*NL:
+            imax = i
+##            print 'cone %d has %d FF'%(i,nl)
+            break
+        if nl> n_latches_max:
+            n_latches_max = nl
+            imax = i
+            print i,nl
+        if i == NO-1:
+            print 'no PO is big enough'
+            return -1
+    print 'PO_cone = %d, n_latches = %d'%(imax,nl)
+
+def scorro():
+    run_command('scorr -o')
+    l = remove_const_pos(0)
+    ps()
+
+def drw():
+    run_command('drw')
+    ps()
+
+def dc2rs():
+    abc('dc2rs')
+    ps()
+
+def reachn(t):
+    x = time.clock()
+    abc('&get;&reachn -rv -T %d'%t)
+    print 'reachm3 done in time = %f'%(time.clock() - x)
+    return get_status()
+    
+def reachx(t=900):
+    x = time.time()
+    abc('reachx -t %d'%t)
+    print 'reachx  done in time = %f'%(time.time() - x)
+    return get_status()
+
+def reachy(t=900):
+    x = time.clock()
+    abc('&get;&reachy -v -T %d'%t)
+##    print 'reachy done in time = %f'%(time.clock() - x)
+    return get_status()
+    
+def create_funcs(J,t):
+    """evaluates strings indexed by J in methods given by FUNCS
+    Returns a list of lambda functions for the strings in FUNCs
+    If J = [], then create provers for all POs"""
+    funcs = []
+    for j in range(len(J)):
+        k=J[j]
+        funcs = funcs + [eval(FUNCS[k])]
+    return funcs
+
+def check_abs():
+    global init_initial_f_name
+    abc('w %s_save.aig'%init_initial_f_name)
+    ni = n_pis()
+    nl = n_latches()
+    na = n_ands()
+    abc('r %s_smp_abs.aig'%init_initial_f_name)
+    if ((ni == n_pis()) and (nl == n_latches()) and (na == n_ands())):
+        return True
+    else:
+        abc('r %s_save.aig'%init_initial_f_name)
+        return False
+
+def modify_methods(J,dec=0):
+    """ adjusts the engines to reflect number of processors"""
+    N = bmc_depth()
+    L = n_latches()
+    I = n_real_inputs()
+    npr = n_proc - dec
+    reachi = reachs
+    if 18 in J: #if sleep in J add 1 more processor
+        npr = npr+1
+    if ( ((I+L<550)&(N>100))  or  (I+L<400) or (L<80) ):
+        if not 24 in J: #24 is reachy
+            if L < 70 and not 4 in reachs:
+                reachi = [4]+reachs #[4] = reachx
+            J = reachi+J # add all reach methods
+            if len(J)>npr:
+                J = remove_intrps(J) #removes only if len(J)<n_processes
+    if len(J)< npr: #if not using all processors, add in pdrs
+        for j in range(len(allpdrs)):
+            if allpdrs[j] in J: #leave it in
+                continue
+            else: #add it in
+                J = J + [allpdrs[j]]
+                if len(J) == npr:
+                    break            
+    if len(J)>npr:
+        J = remove_intrps(J)
+    return J
+
+def BMC_VER():
+    """ a special version of BMC_VER_result that just works on the current network
+    Just runs engines in parallel - no backing up
+    """
+    global init_initial_f_name, methods, last_verify_time, n_proc,last_gasp_time
+    xt = time.time()
+    result = 5
+    t = max(2*last_verify_time,last_gasp_time)  ####
+    print 'Verify time set to %d'%t
+    J = slps + pdrs + bmcs + intrps
+    J = modify_methods(J)
+    F = create_funcs(J,t)
+    mtds = sublist(methods,J)
+    print mtds
+    (m,result) = fork_break(F,mtds,'US')
+    result = RESULT[result]
+    print 'BMC_VER result = %s'%result
+    return result
+
+def BMC_VER_result(t=0):
+##    return 'UNDECIDED'   #TEMP
+    global init_initial_f_name, methods, last_verify_time,f_name,last_gasp_time
+    xt = time.time()
+    result = 5
+    abc('r %s.aig'%f_name)
+    abc('scl')
+    print '\n***Running proof on %s after scl:'%f_name,
+    ps()
+    if t == 0:
+        t = max(2*last_verify_time,last_gasp_time) #each time a new time-out is set t at least 1000 sec.
+    print 'Verify time set to %d'%t
+    J = slps + allpdrs2 + bmcs + intrps + sims
+    last_name = seq_name(f_name).pop()
+    if not last_name in ['abs','spec']:
+        J = slps +allpdrs2 +bmcs + intrps + sims
+##    if 'smp' == last_name or last_name == f_name: # then we try harder to prove it.
+    J = modify_methods(J) #if # processors is enough and problem is small enough then add in reachs
+    F = create_funcs(J,t)
+    mtds = sublist(methods,J)
+    print '%s'%mtds
+    (m,result) = fork(F,mtds)
+    result = get_status()
+    if result == Unsat:
+        return 'UNSAT'
+##    if last_name == 'smp' or last_name == f_name:   # can't backup so just return result
+    if not last_name in ['abs','spec']:
+        if result < Unsat:
+            return 'SAT'
+        if result > Unsat: #still undecided
+            return 'UNDECIDED'
+    else:    # (last_name == 'spec' or last_name == 'abs') - the last thing we did was an "abstraction"
+        if result < Unsat:
+            if last_name == 'abs':
+                add_trace('de_abstract')
+            if last_name == 'spec':
+                add_trace('de_speculate')
+            f_name = revert(f_name,1) # revert the f_name back to previous
+            abc('r %s.aig'%f_name)
+            abc('scl')
+            return BMC_VER_result() #recursion here.
+        else:
+            return 'UNDECIDED'
+            
+def try_split():
+    abc('w %s_savetemp.aig'%f_name)
+    na = n_ands()
+    split(3)
+    if n_ands()> 2*na:
+        abc('r %s_savetemp.aig'%f_name)
+    
+def time_diff():
+    global last_time
+    new_time = time.clock()
+    diff = new_time - last_time
+    last_time = new_time
+    result = 'Lapsed time = %.2f sec.'%diff
+    return result
+
+def prove_all_ind():
+    """Tries to prove output k by induction, using other outputs as constraints.
+    If ever an output is proved
+    it is set to 0 so it can't be used in proving another output to break circularity.
+    Finally all zero'ed outputs are removed.
+    Prints out unproved outputs Finally removes 0 outputs
+    """
+    global n_pos_proved, n_pos_before
+    print 'n_pos_proved = %d'%n_pos_proved
+    n_proved = 0
+    N = n_pos()
+##    l=remove_const_pos()
+##    print '0 valued output removal changed POs from %d to %d'%(N,n_pos())
+    if n_pos() == 1:
+        return
+    abc('w %s_osavetemp.aig'%f_name)
+    lst = range(n_pos())
+##    lst.reverse()
+##    list.reverse()
+##    for j in list[1:]:
+    for j in lst:
+##        abc('zeropo -N 0')
+        abc('swappos -N %d'%j)
+##        l=remove_const_pos() #may not have to do this if constr works well with 0'ed outputs
+        abc('constr -N %d'%(n_pos()-1))
+        abc('fold')
+        n = max(1,n_ands())
+        f = max(1,min(40000/n,16))
+        f = int(f)
+##        abc('ind -C 10000 -F %d'%f)
+        abc('ind -C 1000 -F %d'%f)
+##        run_command('print_status')
+        status = get_status()
+        abc('r %s_osavetemp.aig'%f_name) #have to restore original here
+        if status == Unsat:
+##            print '+',
+            abc('zeropo -N %d'%j)
+            abc('w %s_osavetemp.aig'%f_name) #if changed, store it permanently
+            if j < n_pos_before - n_pos_proved:
+                n_proved = n_proved + 1 # keeps track of real POs proved.
+        elif status < Unsat:
+            print '-%d'%j,
+        else:
+            print '*%d'%j,
+    l=remove_const_pos(0)
+    n_pos_proved = n_pos_proved + n_proved 
+    print '\nThe number of POs reduced from %d to %d'%(N,n_pos())
+    print 'n_pos_proved = %d'%n_pos_proved
+    #return status
+
+def remove_iso(L):
+    global n_pos_proved, n_pos_before
+    lst = []
+    for j in range(len(L)):
+        ll = L[j][1:]
+        if len(ll) == 0:
+            continue
+        else:
+            lst = lst + ll
+    zero(lst)
+    n_pos_proved = n_pos_proved + count_less(lst,n_pos_before - n_pos_proved)
+    print 'The number of POs removed by iso was %d'%len(lst)
+    l=remove_const_pos(0) #can an original PO be zero?
+
+def prove_all_iso():
+    """Tries to prove output k by isomorphism. Gets number of iso-eq_classes as an array of lists.
+    Updates n_pos_proved
+    """
+    global n_pos_proved, n_pos_before
+    n_proved = 0
+    N = n_pos()
+    if n_pos() == 1:
+        return
+    print 'n_pos_proved = %d'%n_pos_proved
+##    run_command('&get;&iso;&put')
+    abc('&get;&iso')
+    L = eq_classes()
+##    print L
+    remove_iso(L)
+    print '\nThe number of POs reduced by iso was from %d to %d'%(N,n_pos())
+
+def count_less(L,n):
+    count = 0
+    for j in range(len(L)):
+        if L[j] < n:
+            count = count + 1
+    return count
+
+def prove_all_mtds(t):
+    """
+    Tries to prove output k  with multiple methods in parallel,
+    using other outputs as constraints. If ever an output is proved
+    it is set to 0 so it can't be used in proving another output to break circularity.
+    Finally all zero'ed ooutputs are removed.
+    """
+    N = n_pos()
+##    l=remove_const_pos()
+##    print '0 valued output removal changed POs from %d to %d'%(N,n_pos())
+    abc('w %s_osavetemp.aig'%f_name)
+    list = range(n_pos())
+    for j in list:
+        run_command('swappos -N %d'%j)
+##        l=remove_const_pos() #may not have to do this if constr works well with 0'ed outputs
+        abc('constr -N %d'%(n_pos()-1))
+        abc('fold')
+##        cmd = '&get;,pdr -vt=%d'%t #put in parallel.
+##        abc(cmd)
+        verify(pdrs+bmcs+intrps+sims,t)
+        status = get_status()
+        abc('r %s_osavetemp.aig'%f_name)
+        if status == Unsat:
+            print '+',
+            abc('zeropo -N %d'%j)
+            abc('w %s_osavetemp.aig'%f_name) #if changed, store it permanently
+        print '%d'%j,
+    assert not is_sat(), 'one of the POs is SAT' #we can do better than this
+    l=remove_const_pos(0)
+    print '\nThe number of POs reduced from %d to %d'%(N,n_pos())
+    #return status
+
+def prove_all_pdr(t):
+    """Tries to prove output k by pdr, using other outputs as constraints. If ever an output is proved
+    it is set to 0 so it can't be used in proving another output to break circularity.
+    Finally all zero'ed outputs are removed. """
+    N = n_pos()
+##    l=remove_const_pos()
+    print '0 valued output removal changed POs from %d to %d'%(N,n_pos())
+    abc('w %s_osavetemp.aig'%f_name)
+    list = range(n_pos())
+    for j in list:
+        abc('swappos -N %d'%j)
+##        l=remove_const_pos() #may not have to do this if constr works well with 0'ed outputs
+        abc('constr -N %d'%(n_pos()-1))
+        abc('fold')
+        cmd = '&get;,pdr -vt=%d'%t #put in parallel.
+        abc(cmd)
+        status = get_status()
+        abc('r %s_osavetemp.aig'%f_name)
+        if status == Unsat:
+            print '+',
+            abc('zeropo -N %d'%j)
+            abc('w %s_osavetemp.aig'%f_name) #if changed, store it permanently
+        print '%d'%j,
+    l=remove_const_pos(0)
+    print '\nThe number of POs reduced from %d to %d'%(N,n_pos())
+    #return status
+
+def prove_each_ind():
+    """Tries to prove output k by induction,  """
+    N = n_pos()
+    l=remove_const_pos(0)
+    print '0 valued output removal changed POs from %d to %d'%(N,n_pos())
+    abc('w %s_osavetemp.aig'%f_name)
+    list = range(n_pos())
+    for j in list:
+        abc('cone -s -O %d'%j)
+        n = max(1,n_ands())
+        f = max(1,min(40000/n,16))
+        f = int(f)
+        abc('ind -u -C 10000 -F %d'%f)
+        status = get_status()
+        abc('r %s_osavetemp.aig'%f_name)
+        if status == Unsat:
+            print '+',
+            abc('zeropo -N %d'%j)
+            abc('w %s_osavetemp.aig'%f_name) #if changed, store it permanently
+        print '%d'%j,
+    l=remove_const_pos(0)
+    print '\nThe number of POs reduced from %d to %d'%(N,n_pos())
+    #return status
+
+def prove_each_pdr(t):
+    """Tries to prove output k by PDR. If ever an output is proved
+    it is set to 0. Finally all zero'ed ooutputs are removed. """
+    N = n_pos()
+    l=remove_const_pos(0)
+    print '0 valued output removal changed POs from %d to %d'%(N,n_pos())
+    abc('w %s_osavetemp.aig'%f_name)
+    list = range(n_pos())
+    for j in list:
+        abc('cone -O %d -s'%j)
+        abc('scl -m')
+        abc('&get;,pdr -vt=%d'%t)
+        status = get_status()
+        abc('r %s_osavetemp.aig'%f_name)
+        if status == Unsat:
+            print '+',
+            abc('zeropo -N %d'%j)
+            abc('w %s_osavetemp.aig'%f_name) #if changed, store it permanently
+        print '%d'%j,
+    l=remove_const_pos(0)
+    print '\nThe number of POs reduced from %d to %d'%(N,n_pos())
+    #return status
+
+def disprove_each_bmc(t):
+    """Tries to prove output k by PDR. If ever an output is proved
+    it is set to 0. Finally all zero'ed ooutputs are removed. """
+    N = n_pos()
+    l=remove_const_pos(0)
+    print '0 valued output removal changed POs from %d to %d'%(N,n_pos())
+    abc('w %s_osavetemp.aig'%f_name)
+    list = range(n_pos())
+    for j in list:
+        abc('cone -O %d -s'%j)
+        abc('scl -m')
+        abc('bmc3 -T %d'%t)
+        status = get_status()
+        abc('r %s_osavetemp.aig'%f_name)
+        if status == Sat:
+            print '+',
+            abc('zeropo -N %d'%j)
+            abc('w %s_osavetemp.aig'%f_name) #if changed, store it permanently
+        print '%d'%j,
+    l=remove_const_pos(0)
+    print '\nThe number of POs reduced from %d to %d'%(N,n_pos())
+    #return status
+
+def add_pord(s):
+    global pord_trace
+    pord_trace = pord_trace + [s]
+
+def pord_1_2(t):
+    """ two phase pord. First one tries with 10% of the time. If not solved then try with full time"""
+    global n_pos_proved, ifpord1, pord_on, pord_trace
+    #first eliminate easy POs
+    ttt = n_ands()/1000
+    if ttt < 100:
+        ttt=100
+    elif ttt<200:
+        ttt = 200
+    elif ttt< 300:
+        ttt = 300
+    else:
+        ttt = 500
+    S,lst,L = par_multi_sat(ttt,1,1,1)
+    lst = indices(L,1)
+    if 1 in L:
+        return [Sat]+[['par_multi_sat: SAT']]
+    if -1 in L:
+        restrict_v(L,-1)
+    else: return [Unsat] + [['par_multi_sat: UNSAT']]
+    pord_trace = []
+    pord_on = True # make sure that we do not reparameterize after abstract in prove_2
+    n_pos_proved = 0
+    if n_pos()<4:
+        return [Undecided] +[pord_trace]
+    if ifpord1:
+        add_pord('pord1')
+        t_time = .1*t
+        print 'Trying each output for %0.2f sec'%(.1*t)
+        result = pord_all(.1*t) #we want to make sure that there is no easy cex.
+        if (result <= Unsat):
+            return [result] + [pord_trace]
+    return [Undecided] + [pord_trace]
+        
+def pord_all(t,n=4):
+    """Tries to prove or disprove each output j by PDRM BMC3 or SIM. in time t"""
+    global cex_list, n_pos_proved, last_cx, pord_on, ifpord1,pord_trace
+    print 'last_cx = %d, time = %0.2f'%(last_cx,t)
+    btime = time.time()
+    N = n_pos()
+    prove_all_ind() ############ change this to keep track of n_pos_proved
+    nn = n_pos()
+    abc('w %s_osavetemp.aig'%f_name)    
+    if nn < n or nn*t > 300: #Just cut to the chase immediately.
+        return Undecided
+    lst = range(n_pos())
+    proved = disproved = []
+    abc('&get') #using this space to save original file.
+    ### Be careful that & space is not changed.
+    cx_list = []
+    n_proved = 0
+    lcx = last_cx + 1
+    lst = lst[lcx:]+lst[:lcx]
+    lst.reverse()
+    n_und = 0
+    for j in lst:
+        print '\ncone %s. '%j,
+        abc('&r -s %s_osavetemp.aig'%f_name) #for safety
+        abc('&put; cone -s -O %d'%j) #puts the &space into reg-space and extracts cone j
+        #requires that &space is not changed. &put resets status. Use &put -s to keep status
+        abc('scl -m')
+        ps()
+##        print 'running sp2'
+        ###
+        result = run_sp2_par(t)
+        if result == 'UNDECIDED':
+            n_und = n_und + 1
+            status = Undecided
+            if ((n_und > 1) and not ifpord1):
+                break
+        elif result == 'SAT':
+            status = Sat
+            disproved = disproved + [j]
+            last_cx = j
+            cx = cex_get()
+            cx_list = cx_list + [cx]
+            assert len(cx_list) == len(disproved), cx_list
+            if len(cx_list) > 0:
+                break
+        else: #is unsat here
+            status = Unsat
+            proved = proved + [j]
+            if j < n_pos_before - n_pos_proved:
+                n_proved = n_proved +1
+##    n_pos_proved = n_pos_proved + n_proved. #this should not be here because we should start fresh
+    print '\nProved %d outputs'%len(proved)
+    print 'Disproved %d outputs'%len(disproved)
+    print 'Time for pord_all was %0.2f'%(time.time() - btime)
+    NN = len(proved+disproved)
+    cex_list = cx_list
+    if len(disproved)>0:
+        assert status == Sat, 'status = %d'%status
+        n_pos_proved = 0 #we want to reset this because of a bad speculation
+        return Sat
+    else:
+        n_pos_proved = n_pos_proved + n_proved
+        if nn == n_pos_proved:
+            return Unsat
+        abc('r %s_osavetemp.aig'%f_name)
+##        abc('&put') # returning original to work spece
+        remove(proved,0)
+        print '\nThe number of unproved POs reduced from %d to %d'%(N,n_pos()),
+        ps()
+        if n_pos() > 0:
+            return Undecided
+        else:
+            return Unsat
+
+def bmc_ss(t):
+    """
+    finds a set cexs in t seconds starting at 2*N where N is depth of bmc -T 1
+    The cexs are put in the global cex_list
+    """
+    global cex_list
+    x = time.time()
+    abc('bmc3 -a -C 1000000 -T %f'%(t))
+    if is_sat():
+        cex_list = cex_get_vector() #does this get returned from a concurrent process?
+        n = count_non_None(cex_list)
+        L = list_non_None(cex_list)
+        print '%d cexs found in %0.2f sec'%(n,(time.time()-x))
+##        remove_disproved_pos(cex_list)
+    else:
+        L = []
+    return L
+
+def iso_slp(t=30):
+    F = [eval('pyabc_split.defer(sleep)(t))')]
+    F = F = F+[eval('(pyabc_split.defer(iso)())')]
+    for i,res in pyabc_split.abc_split_all(F):
+        if i == 0:
+            return 
+
+##def iter_par_multi_sat(t=10,m=1):
+##    while True:
+##        abc('w %s_save.aig'%f_name)
+##        S,lst1 = par_multi_sat(t,m) #run 3 engines in parallel looking for SAT outputs
+##        lst1.sort()
+##        print 'Found %d SAT POs'%len(lst1)
+##        abc('r %s_save.aig'%f_name)
+##        if len(lst1)==0:
+##            break
+##        remove(lst1,1)
+##        pre_simp(1,1)
+##        iso()
+
+def show_partitions(L):
+    for i in range(len(L)):
+        abc('&r -s %s.aig'%L[i])
+        print '\nSize = ',
+        run_command('&ps')
+        abc('&popart')
+        eqs = eq_classes()
+        N = len(eqs)
+        print 'No. of partitions = %d'%N
+        if N == 1:
+            continue
+        l = []
+        for j in range(N):
+            l=l + [len(eqs[j])]
+        print l
+
+
+def r_part(name):
+    read_file_quiet_i(name)
+    abc('&get;&scl;&scorr -C 2;&put')
+    res1 = reparam()
+    res2 = False
+    npos = n_pos()
+##    if n_pos() < 100:
+##        res2 = iso()
+##    ps()
+    if n_pos() < 1000:
+        iso()
+    if n_pos() < 500:
+        abc('r %s.aig'%name)
+        abc('w %s_leaf.aig'%name)
+        return 
+##        abc('w %s_leaf.aig'%name)
+##        return 
+    res = two_eq_part()
+    if res == False:
+        abc('r %s.aig'%name)
+        abc('w %s_leaf.aig'%name)
+        return
+    elif min(res) < .2*max(res) and min(res) < 500:
+        abc('r %s.aig'%name)
+        abc('w %s_leaf.aig'%name)
+        return
+    else:                           #recur
+        r_part('%s_p0'%name)
+        r_part('%s_p1'%name)
+        return
+
+def two_eq_part():
+    abc('&get;&popart')
+    part = eq_classes()
+    if len(part) == 1:
+        print 'Partition has only one part'
+        return False
+    abc('w %s_save.aig'%f_name)
+    nn = n_pos()
+    p1=p0 = []
+    init = True
+    for i in range(len(part)): #union first half together together
+        if init == True:
+            p0=p0 + part[i]
+            if len(p0)>nn/2:
+                init = False
+        else:
+            p1 = p1 + part[i]
+    p0.sort()
+    p1.sort()
+    abc('&get')
+    remove(p1,1)
+    n0=n_pos()
+##    print 'writing %s_p0.aig'%f_name
+    abc('w %s_p0.aig'%f_name)
+    abc('r %s_save.aig'%f_name)
+    remove(p0,1)
+##    print 'writing %s_p1.aig'%f_name
+    n1=n_pos()
+    abc('w %s_p1.aig'%f_name)
+    return [n0,n1]
+
+def merge_parts(p,n):
+    parts = []
+    end = []
+    for i in range(len(p)):
+        if len(p[i]) > n:
+            parts = parts + [p[i]]
+        else:
+            end =end + p[i]
+    parts = parts + [end]
+    return parts
+        
+
+def extract_parts(S=11):
+    abc('&get;&popart -S %d'%S)
+    part = eq_classes()
+    if len(part) == 1:
+        print 'Partition has only one part'
+        return 1
+    parts = merge_parts(part,2)
+    lp=len(parts)
+    print 'Found %d parts'%lp
+    abc('w %s_save.aig'%f_name)
+    for i in range(lp):
+        abc('r %s_save.aig'%f_name)
+        p=[]
+        for j in range(lp):
+            if i == j:
+                continue
+            else:
+                p = p + parts[j]
+        remove(p,1)
+        abc('&get;&scl;&lcorr;&put')
+        abc('w %s_part%d.aig'%(f_name,i))
+    return len(parts)
+
+def two_part():
+    abc('&get;&popart')
+    part = eq_classes()
+    if len(part) == 1:
+        print 'Partition has only one part'
+        return False
+    part1 = part[1:] #all but the 0th
+    p1=[]
+    for i in range(len(part1)): #union together
+        p1=p1 + part1[i]
+    p1.sort()
+    abc('w %s_p.aig'%f_name)
+    remove(p1,1)
+##    print 'writing %s_p0.aig'%f_name
+    abc('w %s_p0.aig'%f_name)
+    n0=n_pos()
+    abc('r %s_p.aig'%f_name)
+    p0 = part[0]
+    p0.sort()
+    remove(p0,1)
+##    print 'writing %s_p1.aig'%f_name
+    n1=n_pos()
+    abc('w %s_p1.aig'%f_name)
+    return [n0,n1]
+
+def set_t_gap(t1,t2):
+    nam = max(30000,n_ands())
+    ratio = 1+float(nam-30000)/float(70000)
+    gp = .5*ratio*t2
+    gp = min(100,gp)
+    t = min(100,ratio*t1)
+    return (t,gp)
+    
+def par_multi_sat(t=10,gap=0,m=1,H=0):
+    """ m = 1 means multiple of 1000 to increment offset"""
+    global last_gap
+    abc('w %s_save.aig'%f_name)
+    if not t == 0:
+        if gap == 0:
+            gap = max(.2,.2*t)
+            gap = max(15,gap)
+        if gap > t:
+            t=gap
+        t,gt = set_t_gap(t,gap)
+        gt = max(15,gt)
+        if gt <= last_gap:
+            gt = 1.2*last_gap
+    else:
+        t = gt = 5
+    if gt > t:
+        t = gt
+    last_gap = gt
+##    H = max(100, t/n_pos()+1)
+    if not H == 0:
+        H = (gt*1000)/n_pos()
+        H = max(min(H,1000*gt),100)
+    tme = time.time()
+    list0 = listr_0_pos() #reduces POs
+    list0.sort()
+##    print 'list0 = %s'%str(list0)
+    if len(list0)>0:
+        print 'temporarily removed %d cost-0 POs'%len(list0)
+    ps()
+    if len(list0)> 0:
+        print 'Found %d const-0 POs, but not removed'%len(list0)
+##        print ll
+    print 'par_multi_sat entered for %.2f sec. and gap = %.2f  sec., H = %.2f'%(t,gt,H)
+    base = m*1000
+    if not m == 1:
+        offset = (m-1)*32000
+        abc('&get;&cycle -F %d;&put'%offset)
+    mx = 1000000000/max(1,n_latches())
+    N = n_pos()
+    na = n_ands()
+    F = [eval('(pyabc_split.defer(bmc3az)(t,gt,%d,H))'%(0*base))]
+##    if na < 50000:
+    F = F + [eval('(pyabc_split.defer(pdraz)(t,gt,H))')] #need pdr in??
+    F = F + [eval('(pyabc_split.defer(sim3az)(t,gt,%d,4,0))'%(0*base))]
+    F = F + [eval('(pyabc_split.defer(sleep)(t))')]
+    F = F + [eval('(pyabc_split.defer(sim3az)(t,gt,%d,4,0))'%(100))]
+    F = F + [eval('(pyabc_split.defer(bmc3az)(t,gt,%d,0))'%(100))]
+    if mx > 1*base:      
+        F = F + [eval('(pyabc_split.defer(sim3az)(t,gt,%d,1,97))'%(1*base))]
+        F = F + [eval('(pyabc_split.defer(bmc3az)(t,gt,%d,0))'%(1*base))]
+##    if mx > 2*base:
+##        F = F + [eval('(pyabc_split.defer(sim3az)(t,gt,%d))'%(2*base))]
+##        F = F + [eval('(pyabc_split.defer(bmc3az)(t,gt,%d,0))'%(2*base))]
+    if mx > 4*base and na < 400000:
+        F = F + [eval('(pyabc_split.defer(sim3az)(t,gt,%d,4,23))'%(4*base))]
+        F = F + [eval('(pyabc_split.defer(bmc3az)(t,gt,%d,0))'%(4*base))]
+##    if mx > 8*base and na < 300000:
+##        F = F + [eval('(pyabc_split.defer(sim3az)(t,gt,%d,3,53))'%(8*base))]
+##        F = F + [eval('(pyabc_split.defer(bmc3az)(t,gt,%d,0))'%(8*base))]
+##    if mx > 16*base and na < 200000 :
+##        F = F + [eval('(pyabc_split.defer(sim3az)(t,gt,%d,2,79))'%(16*base))]
+##        F = F + [eval('(pyabc_split.defer(bmc3az)(t,gt,%d,0))'%(16*base))]
+##    if mx > 32*base and na < 100000:      
+##        F = F + [eval('(pyabc_split.defer(sim3az)(t,gt,%d,1,97))'%(32*base))]
+##        F = F + [eval('(pyabc_split.defer(bmc3az)(t,gt,%d,0))'%(32*base))]
+    ss=LL=L = [] 
+    S = 'UNDECIDED'
+    zero_done = two_done = False
+    s=ss = [-1]*n_pos()
+    ii = []
+    nn = len(F)
+    for i,res in pyabc_split.abc_split_all(F):
+        ii = ii + [i]
+        if len(ii) == len(F)-1: #all done but sleep
+            break
+        if i == 3: #sleep timeout
+            print 'sleep timeout'
+            break
+##        if i == 1:
+##            print 'PDR produced: %s'%str(res)
+####        print i
+        if i == 0:
+            zero_done = True # bmc with start at 0 is done
+        if i == 2:
+            two_done = True
+        if res == None: #this can happen if one of the methods bombs out
+            print 'Method %d returned None'%i
+            continue
+##        print res
+        s1 = switch(res[1]) #res[1]= s
+        s = merge_s(list(s),s1)
+        print sumsize(s)
+        ss = ss + [s1]
+##        LL = LL + [res[0]]
+##        L = L + res[0]
+##        L = [x for x in set(L)] #uniquefy
+        if count_less(s,0) == 0:
+            S = 'UNSAT'
+            break
+ #        if i == 1 and is_unsat() and na < 50000: #pdr can return unsat.
+##        if i == 1 and is_unsat(): #pdr can return unsat.
+##            print 'Method pdr proved remaining POs UNSAT'
+##            S = 'UNSAT'
+##            L = res[0]
+##            break
+##        if not -1 in s:
+##            S = 'UNSAT'
+##            break
+        if len(ss)>1 and zero_done and two_done:
+            ss2 = ss[-2:] #checking if last 2 results agree
+            r = ss2[0]
+            if r == ss2[1] and count_less(r,1) < len(r): #at least 1 SAT PO found
+                break
+##        if len(LL) > 1 and zero_done and two_done:
+##            ll2 = LL[-2:] #checking if last 2 results agree
+##            if ll2[0] == ll2[1] and ll2[0] > 0:
+##                break
+    print 'Found %d SAT POs in '%(len(L)),
+    print 'time = %.2f'%(time.time()-tme)
+    print sumsize(s)
+##    L.sort()
+##    print 'L_before = %s'%(str(L))
+####    check_None_status(L,s,1) #now 1 in s means sat. s can have 0 in it, meaning it found some POs unsat.
+##    L = merge(list(list0),list(L),1) #shift L according to list0 but do not include list0.
+##    print 'L_shifted = %s'%(str(L))
+##    # Need to return only SAT POs have to do the same for s
+    print 'len(s) = %d, len(list0) = %d'%(len(s),len(list0))
+    ss = expand(s,list0,0)
+##    assert list0 == indices(ss,0)
+    print sumsize(ss)
+##    assert check_consistancy(L,ss), 'inconsistant'
+    abc('r %s_save.aig'%f_name)
+    return S,[],ss
+
+
+def check_consistancy(L,s):
+    """ L is list of SAT's found. s is index of all"""
+    consistant = True
+    print 'checking s[L]'
+    for j in L: #make sure that s[L] = 1
+##        print j,
+##        print s[j]
+        if not s[j] == 1:
+            print j,
+            consistant = False
+    print 'checking s=1 => L'
+    for j in range(len(s)): #make sure that there are no other 1's
+        if s[j] == 1:
+            if not j in L:
+                print j,
+                consistant = False
+    return consistant
+        
+
+def check_s(s1,s2):
+    assert len(s1) == len(s2),'lengths do not match'
+    miss = []
+    for i in range(len(s1)):
+        if (s1[i] == 0 and s2[i] == 1) or (s1[i] == 1 and s2[i] == 0):
+            miss = miss + [i]
+    print miss
+        
+
+def merge_s(s1,s2):
+    assert len(s1) == len(s2), 'error in lengths, s1 = %s, s2 = %s'%(str(s1),str(s2))
+    s = [-1]*len(s1)
+    for i in range(len(s1)):
+        if not s1[i] == s2[i]:
+            if s1[i] == -1 or s2[i] == -1:
+                s[i] = max(s1[i],s2[i])
+            else:
+                print 'error: conflict in values at i = %d'%i
+                print 's1[i]=%d,s2[i]=%d'%(s1[i],s2[i])
+        else: #put in common value
+            s[i] = s1[i]
+    return s
+
+def switch(ss):
+    """ This changes the convention of SAT and UNSAT to SAT = 1, UNSAT = 0"""
+    s1 = ss
+    for i in range(len(ss)):
+        si = ss[i]
+        if si == 0:
+            s1[i] = 1
+        elif si == 1:
+            s1[i] = 0
+    return s1
+        
+
+def pdr_ss_r(t):
+    """
+    assumes that 0 POs have been removed
+    finds a set cexs in t seconds. Returns list of SAT POs found
+    """
+    global cex_list
+    x = time.time()
+    abc('pdr -az -T %f'%(t))
+    if is_sat():
+        print 'entering cex  get vector'
+        cex_list = cex_get_vector() #does this get returned from a concurrent process?
+##        n = count_non_None(cex_list)
+        print len(cex_list)
+        L = list_non_None(cex_list)
+        n = len(L)
+        print '%d cexs found in %0.2f sec.'%(n,(time.time()-x))
+        if n == len(cex_list):
+            print 'all remaining POs are SAT'
+##            return L
+        else:
+            remove_disproved_pos(cex_list) #note that this will not remove all POs
+    else:
+        L = []
+    print 'T = %0.2f'%(time.time()-x)
+    return L
+
+def bmc_ss_r(t):
+    """
+    assumes that 0 POs have been removed
+    finds a set cexs in t seconds. Returns list of SAT POs found
+    """
+    global cex_list
+    x = time.time()
+    abc('bmc3 -az -C 1000000 -T %f'%(t))
+    if is_sat():
+        print 'entering cex  get vector'
+        cex_list = cex_get_vector() #does this get returned from a concurrent process?
+##        n = count_non_None(cex_list)
+        L = list_non_None(cex_list)
+        n= len(L)
+        print '%d cexs found in %0.2f sec.'%(n,(time.time()-x))
+        if n == len(cex_list):
+            print 'all remaining POs are SAT'
+##            return L
+        else:
+            remove_disproved_pos(cex_list) #note that this will not remove all POs
+    else:
+        L = []
+    print 'T = %0.2f'%(time.time()-x)
+    return L
+
+def sim_ss_r(t):
+    """
+    assumes that 0 POs have been removed
+    finds a set cexs in t seconds. Returns list of SAT POs found
+    """
+    global cex_list
+    x = time.time()
+    run_command('sim3 -az -T %f'%(t))
+    if is_sat():
+        print 'entering cex  get vector'
+        cex_list = cex_get_vector() #does this get returned from a concurrent process?
+##        n = count_non_None(cex_list)
+        L = list_non_None(cex_list)
+        n = len(L)
+        print '%d cexs found in %0.2f sec.'%(n,(time.time()-x))
+        if n == len(cex_list):
+            print 'all remaining POs are SAT'
+##            return L
+        else:
+            remove_disproved_pos(cex_list) #note that this will not remove all POs
+    else:
+        L = []
+    print 'T = %0.2f'%(time.time()-x)
+    return L
+
+def check_None_status(L,s=[],v=0):
+    """ L is the PO numbers that had non_None in
+    0 means sat and 1 means unsat is
+    v tells which value means sat"""
+    if s == []:
+        s = status_get_vector()
+    error = False
+    for j in L:
+        if s[j] == v:
+            continue
+        else:
+            error = True
+    for i in range(len(s)):
+        if s[i] == v:
+            if i in L:
+                continue
+        else:
+            error = True
+    if error:
+        print 'status and non_None do not agree'
+        print 'L = %d'%L
+        print 'SAT and UNSAT counts switched'
+        print sumsize(s)
+
+
+def list_non_None(lst):
+    """ return [i for i,s in enumerate(cex_list) if not s == None]"""
+    L = []
+    for i in range(len(lst)):
+        if not lst[i] == None:
+            L = L + [i]
+    return L
+
+def count_non_None(lst):
+    #return len([i for i,s in enumerate(cex_list) if not s == None]
+    count = 0
+    for i in range(len(lst)):
+        if not lst[i] == None:
+            count = count + 1
+    return count
+
+def remove_disproved_pos(lst):
+    for i in range(len(lst)):
+        if not lst[i] == None:
+            abc('zeropo -N %d'%i)
+    l=remove_const_pos(0)
+
+def remove_proved_pos(lst):
+    for i in range(len(lst)):
+        if  lst[i] > -1:
+            abc('zeropo -N %d'%i)
+    remove_const_pos(0)
+
+
+        
+def bmc_j(t=900):
+    """ finds a cex in t seconds starting at 2*N where N is depth of bmc -T 1"""
+    x = time.time()
+    tt = min(5,max(1,.05*t))
+    abc('bmc3 -T %0.2f'%tt)
+    if is_sat():
+##        print 'cex found in %0.2f sec at frame %d'%((time.time()-x),cex_frame())
+        return get_status()
+##    abc('bmc3 -T 1')
+    N = n_bmc_frames()
+    N = max(1,N)
+##    print bmc_depth()
+##    abc('bmc3 -C 1000000 -T %f -S %d'%(t,int(1.5*max(3,max_bmc))))
+    cmd = 'bmc3 -J 2 -D 4000 -C 1000000 -T %f -S %d'%(t,2*N)
+##    print cmd
+    abc(cmd)
+##    if is_sat():
+##        print 'cex found in %0.2f sec at frame %d'%((time.time()-x),cex_frame())
+    return RESULT[get_status()]
+
+def pdrseed(t=900):
+    """uses the abstracted version now"""
+##    abc('&get;,treb -rlim=60 -coi=3 -te=1 -vt=%f -seed=521'%t)
+    abc('&get;,treb -rlim=100 -vt=%f -seed=521'%t)
+    return RESULT[get_status()]
+
+def pdrold(t):
+    abc('&get; ,pdr -vt=%f'%t)
+    return RESULT[get_status()]
+
+def pdr(t=900):
+    abc('&get; ,treb -vt=%f'%t)
+    return RESULT[get_status()]
+
+def pdr0(t=900):
+    abc('&get; ,pdr -rlim=100 -vt=%f'%t)
+    return RESULT[get_status()]
+
+def pdra(t=900):
+##    abc('&get; ,treb -rlim=100 -ssize -pre-cubes=3 -vt=%f'%t)
+    abc('&get; ,treb -abs -rlim=100 -sat=abc -vt=%f'%t)
+    return RESULT[get_status()]
+
+def pdrm(t=900):
+    abc('pdr -C 0 -T %f'%t)
+    return RESULT[get_status()]
+
+def pdrmm(t):
+    abc('pdr -C 0 -M 298 -T %f'%t)
+    return RESULT[get_status()]
+
+def bmc2(t):
+   abc('bmc2 -C 1000000 -T %f'%t)
+   return RESULT[get_status()]
+
+def bmc(t=900):
+    abc('&get; ,bmc -vt=%d'%t)
+    return RESULT[get_status()]
+
+def intrp(t=900):
+    abc('&get; ,imc -vt=%d'%t)
+    return RESULT[get_status()]
+
+def bmc3az(t=900,gt=10,C=999,H=0):
+    t_init = time.time()
+    if  C > 999:
+        abc('&get; &cycle -F %d; &put'%C) 
+    abc('bmc3 -az -C 1000000 -T %d -G %d -H %.2f'%(t,gt,H))
+    cex_list = cex_get_vector()
+    L = list_non_None(cex_list)
+##    check_None_status(L)
+    print 'bmc3az(%.2f,%.2f,%d,%d): CEXs = %d, time = %.2f'%(t,gt,C,H,len(L),(time.time()-t_init))
+##    s = status_get_vector()
+    s = [-1]*n_pos()
+    for j in L:
+        s[j]=0 #0 here means SAT. It will be switched in par_multi_sat
+    return L,s
+
+def pdraz(t=900,gt=10,H=0):
+    print 'pdraz entered with t = %.2f, gt = %.2f, H = %.2f'%(t,gt,H)
+    t_init = time.time()
+    run_command('pdr -az -T %d -G %d -H %.2f'%(t,gt,H))
+    cex_list = cex_get_vector()
+    L = list_non_None(cex_list)
+##    check_None_status(L)
+    s = status_get_vector()
+    if s == None:
+        print "status_get_vector returned None"
+    else:
+        print 'Number of UNSAT POs = %d'%(len(s) - count_less(s,1))
+    print 'pdraz(%.2f,%.2f,%d): CEXs = %d, time = %.2f'%(t,gt,H,len(L),(time.time()-t_init))
+    return L,s
+
+def sim3az(t=900,gt=10,C=1000,W=5,N=0):
+    """ N = random seed, gt is gap time, W = # words, F = #frames"""
+    t_init = time.time()
+    if  C > 1000:
+        abc('&get; &cycle -F %d; &put'%C) 
+    abc('sim3 -az -T %.2f -G %.2f -F 40 -W %d -N %d'%(t,gt,W,N))
+    cex_list = cex_get_vector()
+    L = list_non_None(cex_list)
+##    check_None_status(L)
+    s = [-1]*n_pos()
+    for i in L:
+        s[i] = 0 #0 indicates SAT here
+    print 'sim3az(%.2f,%.2f,%d,%d,%d): CEXs=%d, time = %.2f'%(t,gt,C,W,N,len(L),(time.time()-t_init))
+    return L,s
+    
+def bmc3(t=900):
+    abc('bmc3 -C 1000000 -T %d'%t)
+    return RESULT[get_status()]
+
+def intrpm(t=900):
+    abc('int -C 1000000 -F 10000 -K 1 -T %d'%t)
+    print 'intrpm: status = %d'%get_status() 
+    return RESULT[get_status()]
+
+def split(n):
+    global aigs
+    abc('orpos;&get')
+    abc('&posplit -v -N %d;&put;dc2'%n)
+    res =a_trim()
+
+def keep_splitting():
+    for j in range(5):
+        split(5+j)
+        no = n_pos()
+        status = prove_g_pos_split()
+        if status <= Unsat:
+            return status
+        if no == n_pos():
+            return Undecided
+
+def drill(n):
+    run_command('&get; &reachm -vcs -H 5 -S %d -T 50 -C 40'%n)
+
+
+def pre_reduce():
+    x = time.clock()
+    pre_simp()
+    write_file('smp')
+    abstract(ifbip)
+####    write_file('abs')
+    print 'Time = %0.2f'%(time.clock() - x)
+
+def sublist(L,I):
+    # return [s for i,s in enumerate(L) if i in I]
+    z = []
+    for i in range(len(I)):
+        s = L[I[i]],
+        s = list(s)
+        z = z + s
+    return z
+
+#PARALLEL FUNCTIONS
+"""  funcs should look like
+funcs = [pyabc_split.defer(abc)('&get;,bmc -vt=50;&put'),pyabc_split.defer(super_prove)()]
+After this is executed funcs becomes a special list of lambda functions
+which are given to abc_split_all to be executed as in below.
+It has been set up so that each of the functions works on the current aig and
+possibly transforms it. The new aig and status is always read into the master when done
+"""
+
+def tf():
+    result = top_fork()
+    return result
+
+def top_fork(J,t):
+    global x_factor, final_verify_time, last_verify_time, methods
+    set_globals()
+    mtds = sublist(methods,J)
+    F = create_funcs(J,t)
+    print 'Running %s in parallel for max %d sec.'%(mtds,t)
+    (m,result) = fork_last(F,mtds) #FORK here
+    return get_status()
+
+def run_sp2_par(t):
+    """ Runs the single method simple, timed for t seconds."""
+    global cex_list,methods, pord_trace
+    J = slps+[6] #6 is the 'simple' method
+##    mtds = sublist(methods,J)
+##    print mtds,
+    print 'time = %0.2f'%t
+    funcs = create_funcs(J,t) 
+    y = time.time()
+    for i,res in pyabc_split.abc_split_all(funcs):
+##        print 'i,res = %d,%s'%(i,res)
+        T = time.time()-y
+        if i == 0:
+            print 'Timer expired in %0.2f'%T
+            return 'UNDECIDED'
+        else:
+##            print i,res
+            #note simple returns a vector
+            mtd = res[1]
+            ress = res[0]
+            if ress == 'UNSAT':
+                print 'simple proved UNSAT in %0.2f sec.'%T
+                add_pord('UNSAT by %s'%mtd)
+                return 'UNSAT'
+            elif ress == 'UNDECIDED':
+                print 'simple returned UNDECIDED in %0.2f sec.'%T
+                return 'UNDECIDED'
+            if ress == 'SAT':
+                print 'simple found cex in %0.2f sec.'%T
+                add_pord('SAT by %s'%mtd)
+                return 'SAT'
+            else:
+                assert False, 'ress = %s'%ress
+
+def run_parallel(J,t,BREAK='US'):
+    """ Runs the listed methods J, each for time = t, in parallel and
+    breaks according to BREAK = subset of '?USLB'"""
+    global cex_list,  methods
+    mtds = sublist(methods,J)
+    F = create_funcs(J,t) #if J = [] we are going to create functions that process each output separately.
+                            #if 18, then these are run in parallel with sleep
+    if ((J == []) ):
+        result = fork_break(F,mtds,BREAK)
+##        #redirect here to suppress printouts.
+##        with redirect.redirect( redirect.null_file, sys.stdout ):
+##            with redirect.redirect( redirect.null_file, sys.stderr ):
+##                result = fork_break(F,mtds,BREAK)
+    elif 'L' in BREAK:
+        result = fork_last(F,mtds)
+    elif 'B' in BREAK:
+        result = fork_best(F,mtds)
+    else:
+        result = fork_break(F,mtds,BREAK)
+    return result
+
+def fork_all(funcs,mtds):
+    """Runs funcs in parallel and continue running until all are done"""
+    global methods
+    y = time.time()
+    for i,res in pyabc_split.abc_split_all(funcs):
+        status = prob_status()
+        t = time.time()-y
+        if not status == -1: #solved here
+            if status == 1: #unsat
+                print '%s proved UNSAT in %f sec.'%(mtds[i],t)
+            else:
+                print '%s found cex in %f sec. - '%(mtds[i],t),
+                if not mtds[i] == 'REACHM':
+                    print 'cex depth at %d'%cex_frame()
+                else:
+                    print ' '
+            continue
+        else:
+            print '%s was undecided in %f sec. '%(mtds[i],t)
+    return i,res
+
+def fork_break(funcs,mtds,BREAK):
+    """
+    Runs funcs in parallel and breaks according to BREAK <= '?US'
+    If mtds = 'sleep' or [], we are proving outputs in parallel
+    Saves cex's found in cex_list in case we are proving POs.
+    """
+    global methods,last_verify_time,seed,cex_list,last_winner,last_cex
+    seed = seed + 3 # since parallel processes do not chenge the seed in the prime process, we need to change it here
+    cex_list = lst = []
+    y = time.time() #use wall clock time because parent fork process does not use up compute time.
+    for i,res in pyabc_split.abc_split_all(funcs):
+        status = get_status()
+        t = time.time()-y
+        lm = len(mtds)
+        if ((lm < 2) and not i == 0): # the only single mtds case is where it is 'sleep'
+            M = 'Output %d'%(i-lm)
+        else:
+            M = mtds[i]
+            last_winner = M
+        if M == 'sleep':
+            print 'sleep: time expired in %0.2f sec.'%(t)
+##            return 0,[Undecided]+[M]
+##            assert status >= Unsat,'status = %d'%status
+            break
+        if ((status > Unsat) and '?' in BREAK): #undecided
+            break
+        elif status == Unsat or res == 'UNSAT': #unsat
+            print '%s: UNSAT in %0.2f sec.'%(M,(t))
+            status = Unsat
+            if 'U' in BREAK:
+                break
+        elif status < Unsat or res == 'SAT': #status == 0 - cex found
+            status = Sat
+            if M in methods:                
+                if methods.index(M) in exbmcs+allreachs+allpdrs+[1]: #set the known best depth so far. [1] is interp
+                    set_max_bmc(n_bmc_frames())
+            last_cex = M
+            print '%s: -- cex in %0.2f sec. at depth %d => '%(M,t,cex_frame()),
+            cex_list = cex_list+[cex_get()] #accumulates multiple cex's and puts them on list.
+            if len(cex_list)>1:
+                print 'len(cex_list): %d'%len(cex_list)
+            if 'S' in BREAK:
+                break
+        else:
+            continue
+    add_trace('%s by %s'%(RESULT[status],M))
+    return i,[status]+[M]
+
+def fork_best(funcs,mts):
+    """ fork the functions, If not solved, take the best result in terms of AIG size"""
+    global f_name
+    n = len(mts)-1
+    r = range(len(mts))
+    y = time.time()
+    m_best = -1
+    best_size = [n_pis(),n_latches(),n_ands()]
+##    print best_size
+    abc('w %s_best_aig.aig'%f_name)
+    for i,res in pyabc_split.abc_split_all(funcs):
+        if mts[i] == 'sleep':
+            m_best = i
+            break
+        r = delete(r,i)
+        if len(r) == 1:
+            if mts[r[0]] == 'sleep':
+                break
+        status = prob_status()
+        if not status == -1: #solved here
+            m = i
+            t = time.time()-y
+            if status == 1: #unsat
+                print '%s proved UNSAT in %f sec.'%(mts[i],t)
+            else:
+                print '%s found cex in %f sec. - '%(mts[i],t),
+            break
+        else:
+            cost = rel_cost(best_size)
+            if cost < 0:
+                best_size = [n_pis(),n_latches(),n_ands()]
+                m_best = i
+                abc('w %s_best_aig.aig'%f_name)
+    abc('r %s_best_aig.aig'%f_name)
+    add_trace('%s'%mts[m_best])
+    return m_best,res
+
+def delete(r,i):
+    """ remove element in the list r that corresponds to i """
+    ii = r.index(i)
+    z = []
+    for i in range(len(r)):
+        if i == ii:
+            continue
+        else:
+            z = z + [r[i]]
+    return z
+    
+
+def take_best(funcs,mts):
+    """ fork the functions, If not solved, take the best result in terms of AIG size"""
+    global f_name
+    n = len(mts)-1
+    y = time.time()
+    m_best = -1
+    best_size = 1000000
+    abc('w %s_best_aig.aig'%f_name)
+    for i,res in pyabc_split.abc_split_all(funcs):
+        if n_ands() < best_size:
+            best_size = n_ands()
+            m_best = i
+            abc('w %s_best_aig.aig'%f_name)
+    abc('r %s_best_aig.aig'%f_name)
+    return m_best,res
+
+def fork_last(funcs,mtds):
+    """ fork the functions, and take first definitive answer, but
+    if last method ends first, then kill others"""
+    global m_trace,hist,sec_options
+    n = len(mtds)-1
+    m = -1
+    y = time.time()
+    sres =lst = ''
+##    print mtds
+    #print 'starting fork_last'
+    for i,res in pyabc_split.abc_split_all(funcs):
+##        print i,res
+        status = prob_status()
+        if mtds[i] == 'par_scorr' and n_ands() == 0:
+            add_trace('UNSAT by %s'%res)
+            return i,Unsat
+        if not status == -1 or res in ['SAT','UNSAT']: #solved here
+            m = i
+            t = int(time.time()-y)
+            if status == 1 or res == 'UNSAT': #unsat
+                sres = str(res)
+                res = Unsat
+                print '%s proved UNSAT in %d sec.'%(mtds[i],t)
+            else:
+                res = Sat
+                print '%s found cex in %0.2f sec. - '%(mtds[i],(t)),
+            break
+        elif i == n:
+##            print res
+            if mtds[i] == 'pre_simp':
+                m_trace = m_trace + [res[1]]
+                hist = res[2]
+            t = int(time.time()-y)
+            m = i
+            if mtds[i] == 'initial_speculate':
+                return m,res
+            else:
+                print '%s: UNDECIDED in %d sec.'%(mtds[i],t)
+                res = Undecided
+                ps()                
+                break
+        elif mtds[i] == 'sleep':
+            res = Undecided
+            t = time.time()-y
+            print 'Timer expired in %0.2f'%t
+            break
+        lst = lst + ', '+mtds[i]
+##    sres = str(res)
+    if sres[:5] == 'scorr':
+        add_trace('UNSAT by %s'%sres)
+        return m,Unsat
+    add_trace('%s by %s'%(RESULT[res],mtds[i]))
+    return m,res
+
+def fork(funcs,mtds):
+    """ runs funcs in parallel This keeps track of the verify time
+    when a cex was found, and if the time to find
+    the cex was > 1/2 allowed time, then last_verify_time is increased by 2"""
+    global win_list, methods, last_verify_time,seed
+    beg_time = time.time()
+    i,res = fork_break(funcs,mtds,'US') #break on Unsat of Sat.
+    t = time.time()-beg_time        #wall clock time because fork does not take any compute time.
+    if t > .4*last_verify_time:
+##    if t > .15*last_verify_time: ##### temp
+        t = last_verify_time = last_verify_time + .1*t
+        #print 'verify time increased to %s'%convert(t)
+    assert res[0] == get_status(),'res: %d, status: %d'%(res,get_status())
+##    add_trace('%s by %s'%(RESULT[res[0]],mtds[i]))
+    return i,res
+
+def save_time(M,t):
+    global win_list,methods
+    j = methods.index(M)
+    win_list = win_list + [(j,t)]
+    #print win_list
+
+def summarize(lst):
+    result = [0]*10
+    for j in range(len(lst)):
+        k = lst[j]
+        result[k[0]]=result[k[0]]+k[1]
+    return result
+
+def top_n(lst,n):
+    result = []
+    ll = list(lst) #makes a copy
+    m = min(n,len(ll))
+    for i in range(m):
+        mx_index = ll.index(max(ll))
+        result = result + [mx_index]
+        ll[mx_index] = -1
+    return result
+
+def super_pre_simp():
+    while True:
+        nff = n_latches()
+        print 'Calling pre_simp'
+        pre_simp()
+        if n_latches() == nff:
+            break
+
+#______________________________
+#new synthesis command
+
+####def synculate(t):
+####    """
+####    Finds candidate sequential equivalences and refines them by simulation, BMC, or reachability
+####    using any cex found. If any are proved, then they are used to reduce the circuit. The final aig
+####    is a new synthesized circuit where all the proved equivalences are merged.
+####    If we put this in a loop with increasing verify times, then each time we work with a simpler model
+####    and new equivalences. Should approach srm. If in a loop, we can remember the cex_list so that we don't
+####    have to deal with disproved equivalences. Then use refine_with_cexs to trim the initial equivalences.
+####    If used in synthesis, need to distinguish between
+####    original outputs and new ones. Things to take care of: 1. a PO should not go away until it has been processes by merged_proved_equivalences
+####    2. Note that &resim does not use the -m option where as in speculation - m is used. It means that if
+####    an original PO isfound to be SAT, the computation quits becasue one of the output
+####    miters has been disproved.
+####    """    
+####    global G_C,G_T,n_pos_before, x_factor, n_latches_before, last_verify_time, f_name,cex_list, max_verify_time
+####    
+####    
+####    def refine_with_cexs():
+####        """Refines the gores file to reflect equivalences that go away because of cexs in cex_list"""
+####        global f_name
+####        abc('&r %s_gores.aig'%f_name)
+####        for j in range(len(cex_list)):
+####            cex_put(cex_list[j])
+####            run_command('&resim') #put the jth cex into the cex space and use it to refine the equivs
+####        abc('&w %s_gores.aig'%f_name)
+####        return
+####    
+####    def generate_srms():
+####        """generates a synthesized reduced model (srms) from the gores file"""
+####        global f_name, po_map
+####        abc('&r %s_gores.aig; &srm -sf; r gsrms.aig; w %s_gsrms.aig'%(f_name,f_name))
+####        print 'New srms = ',ps()
+####        po_map = range(n_pos())
+####        return 'OK'
+####
+####    def merge_proved_equivalences():
+####        #this only changes the gores file.
+####        run_command('&r %s_gores.aig; &equiv_mark -vf %s_gsrms.aig; &reduce -v; &w %s_gores.aig'%(f_name,f_name,f_name))
+####        return
+####
+####    def generate_equivalences():
+####        set_globals()
+####        t = max(1,.5*G_T)
+####        r = max(1,int(t))
+####        cmd = "&get; &equiv2 -C %d -F 200 -T %f -S 1 -R %d"%((G_C),t,r)
+####        abc(cmd)
+####        #run_command('&ps')
+####        eq_simulate(.5*t)
+####        #run_command('&ps')
+####        cmd = '&semi -W 63 -S 5 -C 500 -F 20 -T %d'%(.5*t)
+####        abc(cmd)
+####        #run_command('&ps')
+####        run_command('&w %s_gores.aig'%f_name)
+####
+####    l=remove_const_pos() #makes sure no 0 pos to start
+####    cex_list = []
+####    n_pos_before = n_pos()
+####    n_latches_before = n_latches()
+######    print 'Generating equivalences'
+####    generate_equivalences()
+######    print 'Generating srms file'
+####    generate_srms() #this should not create new 0 pos
+######    if n_pos()>100:
+######        removed
+####    l=remove_const_pos()
+####    n_pos_last = n_pos()
+####    if n_pos_before == n_pos():
+####        print 'No equivalences found. Quitting synculate'
+####        return Undecided_no_reduction
+####    print 'Initial synculation: ',ps()
+######    ps()
+####    set_globals()
+####    simp_sw = init = True
+####    simp_sw = False #temporary
+####    print '\nIterating synculation refinement'
+####    abc('w initial_sync.aig')
+####    max_verify_time = t
+####    print 'max_verify_time = %d'%max_verify_time
+####    """
+####        in the following loop we increase max_verify_time by twice time spent to find last cexs or Unsat's
+####        We iterate only when we have proved cex + unsat > 1/2 n_pos. Then we update srms and repeat.        
+####    """
+####    while True:                 # refinement loop
+####        t = max_verify_time     #this may have been increased since the last loop
+######        print 'max_verify_time = %d'%max_verify_time
+####        set_globals()
+####        if not init:
+####            generate_srms()     #generates a new gsrms file and leaves it in workspace
+######            print 'generate_srms done'
+####            if n_pos() == n_pos_before:
+####                break
+####            if n_pos() == n_pos_last:   #if nothing new, then quit if max_verification time is reached.
+####                if t > max_verify_time:
+####                    break
+####            if simp_sw:                     #Warning: If this holds then simplify could create some 0 pos
+####                na = n_ands()
+####                simplify()
+####                while True:
+####                    npo = n_pos()
+######                    print 'npos = %d'%npo
+####                    merge_proved_equivalences() #So we need to merge them here. Can merging create more???
+####                    generate_srms()
+####                    if npo == n_pos():
+####                        break
+####                if n_ands() > .7*na:            #if not significant reduction, stop simplification
+####                    simp_sw = False             #simplify only once.
+####            if n_latches() == 0:
+####                return check_sat()
+####        n_pos_last = n_pos()
+####        init = False                        # make it so that next time it is not the first time through
+####        syn_par(t)
+####        if (len(cex_list)+len(result)) == 0: #nothing happened aand ran out of time.
+####            break
+####        abc('w %s_gsrms.aig'%f_name)
+####        #print 'No. of cexs after syn_parallel = %d'%len(cex_list)
+####        merge_proved_equivalences()         #changes the underlying gores file by merging fanouts of proved eqs
+####        #print 'merge done'
+####        refine_with_cexs()                  #changes the gores file by refining the equivalences in it using cex_list.
+####        #print 'refine_with_cexs done'
+####        continue
+####    extract(0,n_pos_before) #get rid of unproved outputs
+####    return
+####
+####def syn_par(t):
+####    """prove n outputs at once and quit at first cex. Otherwise if no cex found return aig
+####    with the unproved outputs"""
+####    global trim_allowed,max_verify_time, n_pos_before
+####    global cex_list, result
+####    b_time = time.time()
+####    n = n_pos()
+####    if n == n_pos_before:
+####        return
+####    mx = n_pos()
+####    if n_pos() - n_pos_before > 50:
+####        mx = n_pos_before + 50
+####    r = range(n_pos_before, mx)     
+####    N = max(1,(mx-n_pos_before)/2)
+####    abc('w %s__ysavetemp.aig'%f_name) 
+####    F = [eval(FUNCS[18])] #create a timer function
+####    #print r
+####    for i in r:
+####        F = F + [eval('(pyabc_split.defer(verify_only)(%d,%d))'%(i,t))]
+####    cex_list = result = []
+####    outcome = ''
+####    #redirect printout here
+######    with redirect.redirect( redirect.null_file, sys.stdout ):
+######        with redirect.redirect( redirect.null_file, sys.stderr ):
+####    for i,res in pyabc_split.abc_split_all(F):
+####        status = get_status()
+######        print i
+####        if i == 0:          #timed out
+####            outcome = 'time expired after = %d'%(time.time() - b_time)
+####            break
+####        if status < Unsat:
+####            cex_list = cex_list + [cex_get()]                    
+####        if status == Unsat:
+####            result = result + [r[i-1]]
+####        if (len(result)+len(cex_list))>= N:
+####            T = time.time() - b_time
+####            if T > max_verify_time/2:
+####                max_verify_time = 2*T
+####            break
+####        continue
+####    if not outcome == '':
+####        print outcome
+######    print 'cex_list,prove_list = ',cex_list,result
+####    abc('r %s__ysavetemp.aig'%f_name) #restore initial aig so that pos can be 0'ed out
+####    if not result == []: # found some unsat's
+######        min_r = min(result)
+######        max_r = max(result)
+######        no = n_pos()
+######        assert (0 <= min_r and max_r < no), 'min_r, max_r, length = %d, %d, %d'%(min_r,max_r,len(result))
+####        zero(result)
+####    return
+####    #print "Number PO's proved = %d"%len(result)
+####
+####def absec(n):
+####    #abc('w t.aig')
+####    for j in range(n):
+####        print '\nFrame %d'%(j+1)
+####        run_command('absec -F %d'%(j+1))
+####        if is_unsat():
+####            print 'UNSAT'
+####            break
+####    
+####
+####"""
+####    we might be proving some original pos as we go, and on the other hand we might have some equivalences that we
+####    can't prove. There are two uses, in verification
+####    verification - we want to remove the proved pos whether they are original or not. But if a cex for an original, then need to
+####                    remember this.
+####    synthesis - the original outputs need to be kept and ignored in terms of cex's - supposedly they can't be proved.
+####"""
+####
+####""" Experimental"""
+####
+####def csec():
+####    global f_name
+####    if os.path.exists('%s_part0.aig'%f_name):
+####        os.remove('%s_part0.aig'%f_name)
+####    run_command('demiter')
+####    if not os.path.exists('%s_part0.aig'%f_name):
+####        return
+####    run_command('r %s_part0.aig'%f_name)
+####    ps()
+####    run_command('comb')
+####    ps()
+####    abc('w %s_part0comb.aig'%f_name)
+####    run_command('r %s_part1.aig'%f_name)
+####    ps()
+####    run_command('comb')
+####    ps()
+####    abc('w %s_part1comb.aig'%f_name)
+####    run_command('&get; &cec %s_part0comb.aig'%(f_name))
+####    if is_sat():
+####        return 'SAT'
+####    if is_unsat():
+####        return 'UNSAT'
+####    else:
+####        return 'UNDECIDED'
+
+    ###########################
+####        we will verify outputs ORed in groups of g[i]
+####        here we take div = N so no ORing
+##        div = max(1,N/1)
+##        g = distribute(N,div)
+##        if len(g) <= 1:
+##            t = tt
+##        g.reverse()
+####        print g
+##        x = 0
+##        G = []
+##        for i in range(div):
+##            y = x+g[i]
+##            F = F + [eval('(pyabc_split.defer(verify_range)(%d,%d,%s))'%(x,y,convert(t)))]
+##            G = G + [range(x,y)]
+##            x = y
+####        print G
+###########################
+
+
+""" These commands map into luts and leave the result in mapped format. To return to aig format, you
+have to do 'st'
+"""
+def sop_balance(k=4):
+    '''minimizes LUT logic levels '''
+##    kmax = k
+    kmax=min(k+2,15)
+    abc('st; if -K %d;ps'%kmax)
+    print nl(),
+##    for i in range(1):
+##        abc('st; if -K %d;ps'%kmax)
+##        run_command('ps')
+    kmax=min(k+2,15)
+    abc('st; if  -g -C %d -K %d -F 2;ps'%(10,kmax)) #balance
+    print nl(),
+    for i in range(1):
+        abc('st;dch; if -C %d -K %d;ps'%(10,kmax))
+        print nl(),
+
+def speedup(k=4):
+    run_command('speedup;if -K %d'%k)
+    print nl()
+
+def speed_tradeoff(k=4):
+    print nl(),
+    best = n_nodes()
+    abc('write_blif %s_bestsp.blif'%f_name)
+    L_init = n_levels()
+    while True:
+        L_old = n_levels()
+        L = L_old -1
+        abc('speedup;if -D %d -F 2 -K %d -C 11'%(L,k))
+        if n_nodes() < best:
+            best = n_nodes()
+            abc('write_blif %s_bestsp.blif'%f_name)
+        if n_levels() == L_old:
+            break
+        print nl(),
+        continue
+    abc('r %s_bestsp.blif'%f_name)
+    return
+
+def area_tradeoff(k=4):
+    print nl(),
+    best = n_nodes()
+    abc('write_blif %s_bestsp.blif'%f_name)
+    L_init = n_levels()
+    while True:
+        L_old = n_levels()
+        L = L_old +1
+        n_nodes_old = n_nodes()
+        abc('speedup;if -a -D %d -F 2 -K %d -C 11'%(L,k))
+        if n_nodes() < best:
+            best = n_nodes()
+            abc('write_blif %s_bestsp.blif'%f_name)
+##        if n_levels() == L_old:
+        if n_nodes == n_nodes_old:
+            break
+        print nl(),
+        continue
+    abc('r %s_bestar.blif'%f_name)
+    return
+
+
+def map_lut_dch(k=4):
+    '''minimizes area '''
+    abc('st; dch; if -a  -F 2 -K %d -C 11; mfs2 -a -L 50 ; lutpack -L 50'%k)
+    
+def map_lut_dch_iter(k=8):
+##    print 'entering map_lut_dch_iter with k = %d'%k
+    best = n_nodes()
+    abc('write_blif %s_best.blif'%f_name)
+##    abc('st;dch;if -a -K %d -F 2 -C 11; mfs -a -L 1000; lutpack -L 1000'%k)
+##    if n_nodes() < best:
+##        abc('write_blif %s_best.blif'%f_name)
+##        best = n_nodes()
+##        print nl(),
+##    else:
+##        abc('r %s_best.blif'%f_name)
+##    best = n_nodes()
+##    abc('write_blif %s_best.blif'%f_name)
+##    print 'best = %d'%best
+    n=0
+    while True:
+        map_lut_dch(k)
+        if n_nodes()< best:
+            best = n_nodes()
+##            print 'best=%d'%best
+            n = 0
+            abc('write_blif %s_best.blif'%f_name)
+            print nl(),
+            continue
+        else:
+            n = n+1
+            if n>2:
+                break    
+    abc('r %s_best.blif'%f_name)
+
+def dmitri_iter(k=8):
+    best = 100000
+    n=0
+    while True:
+        dmitri(k)
+        if n_nodes()< best:
+            best = n_nodes()
+##            print '\nbest=%d'%best
+            n = 0
+            abc('write_blif %s_best.blif'%f_name)
+            continue
+        else:
+            n = n+1
+        if n>2:
+            break
+    abc('r %s_best.blif'%f_name)
+##    run_command('cec -n %s.aig'%f_name)
+    print nl()
+
+def shrink():
+    tm = time.time()
+    best = n_ands()
+    while True:
+        abc('&get;&if -K 4 -F 1 -A 0 -a;&shrink;&put')
+        print n_ands(),
+        if n_ands()< .99*best:
+            best = n_ands()
+            continue
+        break
+    print 't = %.2f, '%(time.time()-tm),
+    ps()
+
+def shrink_lut():
+    tm = time.time()
+    abc('&get;&if -K 4 -F 1 -A 0 -a;&put')
+    best = n_nodes()
+    print best,
+    abc('&shrink')
+    while True:
+        abc('&if -K 4 -F 1 -A 0 -a;&put')
+        print n_nodes(),
+        if n_nodes() < .99*best:
+            best = n_nodes()
+            abc('&shrink')
+            continue
+        break
+    abc('&put')
+    print 'time = %.2f, '%(time.time()-tm),
+    ps()
+
+
+def map_lut(k=4):
+    '''minimizes edge count'''
+    for i in range(5):
+        abc('st; if -e -K %d; ps;  mfs ;ps; lutpack -L 50; ps'%(k))
+        print nl(),
+
+def extractax(o=''):
+    abc('extract -%s'%o)
+
+def nl():
+    return [n_nodes(),n_levels()]
+
+def dc2_iter(th=.999):
+    abc('st')
+    tm = time.time()
+    while True:
+        na=n_ands()
+        abc('dc2')
+        print n_ands(),
+##        print nl(),
+        if n_ands() > th*na:
+            break
+    print 't = %.2f, '%(time.time()-tm),
+    ps()
+##    print n_ands()
+
+def drw_iter(th=.999):
+    abc('st')
+    tm = time.time()
+    while True:
+        na=n_ands()
+        abc('drw')
+        print n_ands(),
+##        print nl(),
+        if n_ands() > th*na:
+            break
+    print 't = %.2f, '%(time.time()-tm),
+    ps()
+##    print n_ands()
+
+def adc2_iter(th=.999):
+    abc('st;&get')
+    while True:  
+        na=n_ands()
+        abc('&dc2;&put')
+##        print n_ands(),
+        if n_ands() > th*na:
+            break
+    print n_ands()
+        
+def try_extract():
+##    abc('dc2;dc2')
+    print 'Initial: ',
+    ps()
+    na = n_ands()
+##    abc('w %s_savetemp.aig'%f_name)
+    #no need to save initial aig since fork_best will return initial if best.
+    J = [32,33]
+    mtds = sublist(methods,J)
+    F = create_funcs(J,0)
+    (m,result) = take_best(F,mtds) #FORK here
+    if not m == -1:
+        print 'Best extract is %s: '%mtds[m],
+        ps()
+##    if (n_ands() < na):
+##        return
+##    else:
+##        abc('r %s_savetemp.aig'%f_name)
+
+def speedup_iter(k=8):
+    abc('st;if -K %d'%k)
+    run_command('ps')
+    abc('write_blif %s_bests.blif'%f_name)
+    run_command('ps')
+    best = n_levels()
+    print 'n_levels before speedup = %d'%n_levels()
+    n=0
+    while True:
+        nl()
+        abc('speedup;if -K %d'%k)
+        if n_levels() < best:
+            best = n_levels()
+            abc('write_blif %s_bests.blif'%f_name)
+            n=0
+        else:
+            n = n+1
+        if n>2:
+            break
+    abc('r %s_bests.blif'%f_name)
+    print 'n_levels = %d'%n_levels()
+
+def jog(n=16):
+    """ applies to a mapped blif file"""
+    run_command('eliminate -N %d;fx'%n)
+    run_command('if -K %d'%(n/2))
+    run_command('fx')
+
+def perturb_f(k=4):
+    abc('st;dch;if -g -K %d'%(k))
+##    snap()
+    abc('speedup;if -K %d -C 10'%(k))
+    jog(5*k)
+##    snap()
+##    abc('if -a -K %d -C 11 -F 2;mfs -a -L 50;lutpack -L 50'%k
+
+def perturb(k=4):
+    abc('st;dch;if -g -K %d'%k)
+##    snap()
+    abc('speedup;if -K %d -C 10'%(k))
+    
+def preprocess(k=4):
+    n_initial = n_nodes()
+    abc('write_blif %s_temp_initial.blif'%f_name)
+##    abc('st;dc2')
+    abc('w %s_temp_initial.aig'%f_name)
+    ni = n_pis() + n_latches()
+    res = 1
+    if ni >= 101:
+        abc('st;if -a -F 2 -K %d'%k)
+        return res
+##    dc2_iter()
+    abc('st;if -a -K %d'%k) # to get plain direct map
+    if n_nodes() > n_initial:
+        abc('r %s_temp_initial.blif'%f_name)
+        res = 1
+    #plain
+    n_plain = n_nodes()
+##    print nl()
+    abc('write_blif %s_temp_plain.blif'%f_name)
+    #clp
+    abc('st;clp; if -a -K %d'%k)
+##    print nl()
+    abc('write_blif %s_temp_clp.blif'%f_name)
+    n_clp = n_nodes()
+    #clp_lutmin
+    abc('r %s_temp_initial.blif'%f_name)
+    abc('st;clp;lutmin -K %d;'%k)
+    abc('write_blif %s_temp_clp_lut.blif'%f_name)
+    n_clp_lut = n_nodes()
+##    print nl()
+    if n_plain <= min(n_clp,n_clp_lut):
+        abc('r %s_temp_plain.blif'%f_name)
+        res = 1
+    elif n_clp < n_clp_lut:
+        abc('r %s_temp_clp.blif'%f_name)
+        res = 1
+    else:
+        abc('r %s_temp_clp_lut.blif'%f_name)
+        res = 1
+##    print nl()
+    return res
+
+def snap():
+##    abc('fraig;fraig_store')
+    abc('fraig_store')
+
+def snap_bestk(k):
+    abc('write_blif %s_temp.blif'%f_name)
+    unsave_bestk(k)
+    snap()
+    abc('r %s_temp.blif'%f_name)
+
+def cec_it():
+    """ done because &r changes the names. Can't use -n because rfraig_store reorders pis and pos."""
+    abc('write_blif %s_temp.blif'%f_name)
+    abc('&r -s %s.aig;&put'%f_name)
+    run_command('cec %s_temp.blif'%f_name)
+    abc('r %s_temp.blif'%f_name)
+
+def save_bestk(b,k):
+##    if os.access('%s_best%d.blif'%(f_name,k),os.R_OK):
+##        res = get_bestk(k)
+##    else:
+    """ saves the best, returns bestk and if not best, leaves blif unchanged""" 
+    res = b
+    if n_nodes() < res:
+        res = n_nodes()
+        abc('write_blif %s_best%d.blif'%(f_name,k))
+        print 'best%d = %d'%(k,res)
+    return res
+##    unsave_bestk(k)
+
+def unsave_bestk(k):
+    abc('r %s_best%d.blif'%(f_name,k))
+        
+def unsnap(k=4):
+##    snap()
+    abc('fraig_restore')
+    map_lut_dch(k)
+##    abc('fraig_restore;if -a -F 2 -C 11 -K %d'%k)
+
+def map_until_conv(k=4):
+    kk = 2*k
+    # make sure that no residual results are left over.
+    if os.access('%s_best%d.blif'%(f_name,k),os.R_OK):
+        os.remove('%s_best%d.blif'%(f_name,k))
+    if os.access('%s_best%d.blif'%(f_name,kk),os.R_OK):
+        os.remove('%s_best%d.blif'%(f_name,kk))
+    tt = time.time()
+    #get initial map and save
+    map_lut_dch(k)
+    bestk = save_bestk(100000,k)
+    print nl()
+##    snap()
+    res = preprocess() #get best of initial, clp, and lutmin versions
+    print nl()
+##    map_lut_dch(k)
+##    ###
+##    bestk = save_bestk(bestk,k)
+##    map_iter(k)
+##    bestk = save_bestk(bestk,k)
+##    ###
+    map_lut_dch_iter(kk) #initialize with mapping with 2k input LUTs
+    bestkk = save_bestk(100000,kk)
+    snap()
+    unsnap(k) #have to do snap first if want current result snapped in.
+        # unsnap fraigs snapshots and does map_lut_dch at end
+    print nl()
+    bestk = save_bestk(bestk,k)
+    abc('r %s_bestk%d.blif'%(f_name,k))
+    map_iter(k) #1
+    bestk = save_bestk(bestk,k)
+    while True:
+        print 'Perturbing with %d-Lut'%kk
+##        snap()
+        map_lut_dch_iter(kk)
+##        snap()
+        bestkk_old = bestkk
+        bestkk = save_bestk(bestkk,kk)
+        if bestkk >= bestkk_old:
+            break
+##        snap()
+##        jog(kk)
+##        perturb_f(k)
+##        snap()
+##        perturb_f(k)
+##        snap()
+##        unsave_bestk(k)
+##        map_lut_dch(k+1)
+##        snap()
+##        snap_bestk(k)
+        snap()
+        unsnap(k) #fraig restore and map
+##        bestk = save_bestk(bestk,k)
+##        snap()
+        bestk_old = bestk
+        map_iter(k)
+        bestk = save_bestk(bestk,k)
+        if bestk >= bestk_old:
+            break
+        continue
+    abc('fraig_restore') #dump what is left in fraig_store
+    unsave_bestk(k)
+    print '\nFinal size = ',
+    print nl()
+    print 'time for %s = %.02f'%(f_name,(time.time()-tt))
+##    cec_it()
+
+def get_bestk(k=4):
+    abc('write_blif %s_temp.blif'%f_name)
+    unsave_bestk(k)
+    res = n_nodes()
+    abc('r %s_temp.blif'%f_name)
+    return res
+
+def map_iter(k=4):
+    tt = time.time()
+    bestk = get_bestk(k)
+##    bestk = n_nodes()
+##    bestk = save_bestk(bestk,k)
+##    abc('st;dch;if -a -F 2 -K %d -C 11; mfs -a -L 1000; lutpack -L 1000'%k)#should be same as Initial
+##    map_lut_dch_iter(k) ####
+    map_lut_dch(k)
+    bestk = save_bestk(bestk,k)
+    n=0
+    unsave_bestk(k)
+    while True:
+##        snap()
+        perturb(k) #
+##        snap()
+        perturb(k)
+##        snap_bestk(k)
+##        unsnap(k)
+##        bestk = save_bestk(bestk,k)
+##        snap()
+##        map_lut_dch(k+1)
+##        abc('if -K %d'%(k+1))
+##        snap()
+##        unsnap(k)
+        old_bestk = bestk
+##        print old_bestk
+        map_lut_dch_iter(k)
+        bestk = save_bestk(bestk,k)
+        print bestk
+        if bestk < old_bestk:
+            n=0 # keep it up
+            continue
+        elif n == 2: #perturb 
+            break
+        else:
+            n = n+1
+            print '%d-perturb'%n
+##            snap()
+##            unsave_bestk(k)
+    unsave_bestk(k)
+
+def map_star(k=4):
+    tt = time.time()
+    map_until_conv(k)
+    abc('write_blif %s_best_star.blif'%f_name)
+    best = n_nodes()
+    while True:
+        jog(2*k)
+        map_until_conv(k)
+        if n_nodes() >= best:
+            break
+        else:
+            best = n_nodes()
+            abc('write_blif %s_best_star.blif'%f_name)
+    abc('r %s_best_star.blif'%f_name)
+    print 'SIZE = %d, TIME = %.2f for %s'%(n_nodes(),(time.time() - tt),f_name)
+
+def decomp_444():
+    abc('st; dch; if -K 10 -S 444')
+    abc('write_blif -S 444 %s_temp.blif; r %s_temp.blif'%(f_name,f_name)) 
+
+def dmitri(k=8):
+##    abc('w t.aig')
+##    dc2_iter()
+##    print 'first iter done:  %d'%n_ands()
+##    abc('dc2rs')
+####    dc2_iter()
+##    print 'second iter done:  %d'%n_ands()
+##    sop_balance(k)
+##    abc('w t_before.aig')
+##    run_command('cec -n t.aig')
+##    speedup_iter(k)
+##    print 'n_levels after speedup = %d'%n_levels()
+##    abc('write_blif %s_save.blif'%f_name)
+##    nn=n_levels()
+    abc('st;dch; if -g -K %d'%(k))
+##    print 'n_levels after sop balance = %d'%n_levels()
+##    if n_levels() > nn:
+##        run_command('r %s_save.blif'%f_name)
+##        print 'n_levels = %d'%n_levels()
+##    print 'final n_levels = %d'%n_levels()
+##    print 'sop_balance done:  ',
+##    print nl()
+##    run_command('st;w t_after.aig')
+##    run_command('cec -n t.aig')
+    abc('if -G %d '%k)
+##    print 'after if -G %d:  '%k,
+##    print nl()
+##    run_command('cec -n t.aig')
+    abc('cubes')
+##    print 'after cubes:  ',
+##    print nl()
+##    run_command('cec -n t.aig')
+    abc('addbuffs -v')
+##    print 'after addbuffs:  ',
+    print nl(),
+##    run_command('cec -n t.aig')
+
+def lut():
+    dc2_iter()
+    abc('extract -a')
+    print nl()
+    dc2_iter()
+##    ps()
+    sop_balance(6)
+    map_lut_dch()
+    map_lut()
+    print nl()
+##    run_command('ps')
+
+################################## gate level abstraction
+    """
+    Code for using
+    for abstraction
+    """
+
+def bip_abs(t=100):
+    """ t is ignored here"""
+    set_globals()
+    time = max(1,.1*G_T)
+    abc('&get;,bmc -vt=%f'%time)
+    set_max_bmc(bmc_depth())
+    c = 2*G_C
+    f = max(2*max_bmc,20)
+    b = min(max(10,max_bmc),200)
+    t1 = x_factor*max(1,2*G_T)
+    t = max(t1,t)
+    s = min(max(3,c/30000),10) # stability between 3 and 10 
+##    cmd = '&get;,abs -bob=%d -stable=%d -timeout=%d -vt=%d -depth=%d -dwr=vabs'%(b,s,t,t,f)
+    cmd = '&get;,abs -timeout=%d -vt=%d -dwr=%s_vabs'%(t,t,f_name)
+    print 'Running %s'%cmd
+##    abc(cmd)
+    run_command(cmd)
+    bmc_depth()
+    abc('&w %s_greg.aig'%f_name)
+    return max_bmc
+
+def check_frames():
+    abc('read_status vta.status')
+    return n_bmc_frames()
+
+def vta_abs(t):
+    """ Do gate-level abstraction for F frames """
+    r = 100 *(1 - abs_ratio)
+##    abc('orpos; &get;&vta -dv -A %s_vabs.aig -P 2 -T %d -R %d; &vta_gla;&w %s_gla.aig;&gla_derive; &put; w %s_gabs.aig'%(f_name,t,r,f_name,f_name))
+    abc('orpos; &get;&vta -dv -A %s_vabs.aig -P 2 -T %d -R %d; &vta_gla;&w %s_gla.aig'%(f_name,t,r,f_name))
+    
+##    write_file('abs')
+    
+
+def sizeof():
+    return [n_pis(),n_pos(),n_latches(),n_ands()]
+
+def abstract(ifb=2):
+    global abs_ratio
+##    print 'ifb = %d'%ifb
+    if ifb == 0: #new way using vta_abs and no bip
+        add_trace('abstracta')
+        return abstracta(False)
+    elif ifb == 1: #old way using ,abs
+        assert ifb == ifbip, 'call to abstract has ifb not = global ifbip'
+        add_trace('abstractb')
+        return abstractb()
+    else:
+        #new way using ,abs -dwr -- (bip_abs)
+        add_trace('abstracta')
+        return abstracta(True)
+
+def abstracta(if_bip=True):
+    """
+    if_bip = 0 it uses a new abstraction based on &vta (gate level abstraction) and no bip operations
+    Right now, if we do not prove it with abstraction in the time allowed,
+    we abandon abstraction and go on with speculation
+    if_bip = 1, we use ,abs -dwr
+    """
+    global G_C, G_T, latches_before_abs, x_factor, last_verify_time, x, win_list, j_last, sims
+    global latches_before_abs, ands_before_abs, pis_before_abs, abs_ratio
+##    n_vabs = 0
+    latches_before_abs = n_latches()
+    ands_before_abs = n_ands()
+    pis_before_abs = n_real_inputs()
+    tt = time.time()
+    print 'using abstracta, ',
+##    print 'if_bip = %d'%if_bip
+##    latch_ratio = abs_ratio
+##    t = 100
+    t = 1000 #temporary
+    t = abs_time
+    if if_bip == 0:
+        t = 1000 #timeout on vta
+        t = abs_time
+    tt = time.time()
+    if n_pos() > 1 and if_bip == 0:
+        abc('orpos')
+        print 'POs ORed together, ',
+    initial_size = sizeof()
+    abc('w %s_before_abs.aig'%f_name)
+    # 25 below means that it will quit if #FF+#ANDS > 75% of original
+##    funcs = [eval("(pyabc_split.defer(abc)('orpos;&get;&vta -d -R 25'))")] #right now we need orpos
+    if if_bip:
+        print 'using bip_abs'
+        mtds = ['bip_abs']
+        funcs = [eval('(pyabc_split.defer(bip_abs)(t))')]
+    else:
+        if gla:
+            print 'using gla_abs_iter for %0.2f sec.'%(t-2)
+            mtds = ['gla_abs_iter']
+            add_trace('gla_abs')
+            funcs = [eval('(pyabc_split.defer(gla_abs_iter)(t-2))')]
+        else:
+            print 'using vta_abs for %0.2f sec.'%(t-2)
+            mtds = ['vta_abs']
+            funcs = [eval('(pyabc_split.defer(vta_abs)(t-2))')]
+    funcs = funcs + [eval('(pyabc_split.defer(monitor_and_prove)())')]
+##    J = [34,30]
+    J = pdrs[:1]+bmcs[:1] #just use one pdr and one bmc here.
+##    J = pdrs+bmcs
+##    J = modify_methods(J,2)
+    funcs = funcs + create_funcs(J,1000)
+    mtds = mtds + ['monitor_and_prove'] + sublist(methods,J)
+    print 'methods = ',
+    print mtds
+    vta_term_by_time=0
+    for i,res in pyabc_split.abc_split_all(funcs):
+##        print i,res
+        if i == 0: #vta or gla ended first
+            print 'time taken = %0.2f'%(time.time() - tt)
+            if is_sat():
+                print 'vta/gla abstraction found cex in frame %d'%cex_frame()
+                add_trace('SAT by gla')
+                return Sat
+            if is_unsat():
+                print 'vta/gla abstraction proved UNSAT'
+                add_trace('UNSAT by gla')
+                return Unsat
+            else: #undecided
+                if if_bip:
+                    abc('&r -s %s_greg.aig; &abs_derive; &put; w %s_gabs.aig'%(f_name,f_name))
+                else:
+                    abc('&r -s %s_gla.aig;&gla_derive; &put; w %s_gabs.aig'%(f_name,f_name))   
+                if time.time() - tt < .95*t:
+                    print 'abstraction terminated but not by timeout'
+                    vta_term_by_time = 0
+                    break
+                else:
+                    print 'abstraction terminated by a timeout of %0.2f'%t
+##                    print 'final abstraction: ',
+##                    ps()
+                    vta_term_by_time=1
+                    break
+        if i == 1: #monitor and prove ended first (sleep timed out)
+            print 'monitor_and_prove: '
+##            print i,res
+            if res == None:
+                print 'monitor and prove had an error'
+                continue
+            result = res[0]
+            if res[0] > Undecided: #we abandon abstraction
+                add_trace('de_abstract')
+                print 'monitor and prove timed out or too little reduction'
+                abc('r %s_before_abs.aig'%f_name)
+                return Undecided_no_reduction
+            if res[0] == Undecided:
+                break
+            else: 
+                if not initial_size == sizeof(): #monitor and prove should not return SAT in this case'
+                    assert not is_sat(), 'monitor_and_prove returned SAT on abstraction!' 
+                print 'time taken = %0.2f'%(time.time() - tt)
+                if is_unsat() or res[0] == 'UNSAT' or res[0] == Unsat:
+                    add_trace('UNSAT by %s'%res[1])
+                    return Unsat
+                elif is_sat() or res[0] < Unsat:
+                    add_trace('SAT by %s'%res[1])
+                    return Sat
+                else:
+                    abc('r %s_before_abs.aig'%f_name)
+                    return Undecided_no_reduction
+        else: #one of the engines got an answer
+            print 'time taken = %0.2f'%(time.time() - tt)
+##            add_trace('initial %s'%mtds[i])
+            if is_unsat():
+                print 'Initial %s proved UNSAT'%mtds[i]
+                add_trace('UNSAT by initial %s'%mtds[i])
+                return Unsat
+            if is_sat():
+                print 'Initial %s proved SAT'%mtds[i]
+                add_trace('SAT by initial %s'%mtds[i])
+                return Sat
+            else: # an engine failed here
+                print 'Initial %s terminated without result'%mtds[i]
+                add_trace('method %s failed'%mtds[i])
+##                return Undecided
+                continue
+    if  vta_term_by_time == 0 and if_bip == 0 and gabs: #vta timed out itself
+        print 'Trying to verify final abstraction',
+        ps()
+        result = verify([7,9,19,23,24,30],100)
+        if result[0] == Unsat:
+            add_trace('UNSAT by %s'%result[1])
+            print 'Abstraction proved valid'
+            return result[0]
+    # should do abstraction refinement here if if_bip==1
+    if if_bip == 0 and gabs: # thus using vta or gla abstraction and no refinement
+        print 'abstraction no good - restoring initial simplified AIG',
+        abc('r %s_before_abs.aig'%f_name)
+        add_trace('de_abstract')
+        ps()
+        return Undecided_no_reduction
+    else: # thus using bip_abs (ifbip=1) or gate abstraction (ifbip=0&gabs=False) and refinement
+        if is_sat():
+            print 'Found true counterexample in frame %d'%cex_frame()
+            add_trace('SAT')
+            return Sat_true
+        if is_unsat():
+            add_trace('UNSAT')
+            return Unsat
+    ##    set_max_bmc(NBF)
+        NBF = bmc_depth()
+        print 'Abstraction good to %d frames'%max_bmc
+        #note when things are done in parallel, the &aig is not restored!!!
+        if if_bip:
+            abc('&r -s %s_greg.aig; &w initial_greg.aig; &abs_derive; &put; w initial_gabs.aig; w %s_gabs.aig'%(f_name,f_name))
+        else:
+            run_command('&r -s %s_gla.aig; &w initial_gla.aig; &gla_derive; &put; w initial_gabs.aig; w %s_gabs.aig'%(f_name,f_name))
+        set_max_bmc(NBF)
+        print 'Initial abstraction: ',
+        ps()
+        abc('w %s_init_abs.aig'%f_name)
+        latches_after = n_latches()
+    ##    if latches_after >= .90*latches_before_abs: #the following should match similar statement
+    ##    if ((rel_cost_t([pis_before_abs, latches_before_abs, ands_before_abs])> -.1) or
+    ##        (latches_after >= .75*latches_before_abs)):
+        if small_abs(abs_ratio):
+            abc('r %s_before_abs.aig'%f_name)
+            print "Too little reduction!"
+            print 'Abstract time wasted = %0.2f'%(time.time()-tt)
+            add_trace('de_abstract')
+            return Undecided_no_reduction
+        sims_old = sims
+        sims=sims[:1] #make it so that rarity sim is not used since it can't find a cex
+##        result = Undecided_no_reduction
+        print 'small_abs = %.2f, vta_term_by_time = %d'%(small_abs(abs_ratio),vta_term_by_time)
+        if not vta_term_by_time:
+            print 'Entering abstraction_refinement'
+            result = abstraction_refinement(latches_before_abs, NBF,abs_ratio)
+            sims = sims_old
+            if result <= Unsat:
+                return result
+        if small_abs(abs_ratio): #r is ratio of final to initial latches in absstraction. If greater then True
+##        if small_abs(abs_ratio) or result == Undecided_no_reduction or vta_term_by_time: #r is ratio of final to initial latches in absstraction. If greater then True
+            abc('r %s_before_abs.aig'%f_name) #restore original file before abstract.
+            print "Too little reduction!  ",
+            print 'Abstract time wasted = %0.2f'%(time.time()-tt)
+            add_trace('de_abstract')
+            return Undecided_no_reduction
+        elif vta_term_by_time:
+            abc('r %s_gabs.aig'%f_name)
+            print 'Simplifying and testing abstraction'
+            reparam()
+            result = simplify()
+            assert result >= Unsat, 'simplify returned SAT'
+            if result > Unsat: #test if abstraction is unsat
+                result = simple()
+                res = result[0]
+                if res == 'UNSAT':
+                    return Unsat
+                else:
+                    abc('r %s_before_abs.aig'%f_name) #restore original file before abstract.
+                    print "Timed out with bad abstraction",
+                    print 'Abstract time wasted = %0.2f'%(time.time()-tt)
+                    add_trace('de_abstract')
+                    return Undecided_no_reduction
+##                if res == 'SAT':
+####                    result = Sat #this was an error
+##                    result = Undecided_no_reduction
+##                elif res == 'UNSAT':
+##                    result = Unsat
+##                else:
+##                    result = Undecided_no_reduction
+##                return result
+        else:
+            write_file('abs') #this is only written if it was not solved and some change happened.
+        print 'Abstract time = %0.2f'%(time.time()-tt)
+    return result
+
+def gla_abs_iter(t):
+    """ this iterates &gla every x sec and checks if it should be stopped or continued.
+        Uses the fact that when &gla ends
+        it leaves the result in the &-space showing which elements are abstracted.
+        cex_abs_depth, time_abs_prev and time_abs come from monitor_and_prove
+        gla_abs_iter and monitor_and_prove are run in parallel
+        """
+    global cex_abs_depth, abs_depth, abs_depth_prev, time_abs_prev, time_abs
+    it_interval = 10000 
+    total = t
+    tt = time.time()
+    run_command('orpos;&get')
+##    run_command('&w %s_gla.aig'%f_name)
+    abs_depth = abs_depth_prev = 0
+##    while True:
+    r = 100 *(1 - abs_ratio)
+    q = 99 #############TEMP
+##    run_command('&r %s_gla.aig'%f_name)
+    time_remain = total - (time.time() - tt) #time remaining
+    it = min(it_interval,time_remain)
+##    if it < 2:
+##        break
+    #gla and vabs are the file with the abstraction info and gabs is the derived file.
+    cmd = '&gla -mvs -B 1 -A %s_vabs.aig -T %d -R %d -Q %d -S %d'%(f_name,it,r,q,abs_depth)
+    print 'Executing %s'%cmd
+    name = '%s_vabs.aig'%f_name
+    run_command(cmd)
+    if os.access(name,os.R_OK):
+        run_command('&r -s %s_vabs.aig'%f_name) #get the last abstraction result
+        run_command('&w %s_gla.aig'%f_name) #saves the result of abstraction.
+    else:
+        run_command('&r -s %s_abs_old.aig'%f_name) #get the last abstraction result
+        run_command('&w %s_gla.aig'%f_name) #saves the result of abstraction.
+    print 'wrote %s_gla file'%f_name
+    run_command('&gla_derive;&put')
+    run_command('w %s_gabs.aig'%f_name)
+##        break
+##        abs_depth_prev = abs_depth
+##        abs_depth = n_bmc_frames()
+##        print 'abs_depth = %d'%abs_depth
+##        #test here if done
+##        if (time.time()-tt) > total:
+##            break
+##        print 'reading abs_values'
+##        read_abs_values()
+##        print 'values read'
+##        if abs_done(time_remain):
+##            print 'abs_done'
+##            break
+##        else:
+##            continue
+    
+def read_abs_values():
+    """here we read in the abs values written by monitor and prove"""
+    global cex_abs_depth, abs_depth, abs_depth_prev, time_abs_prev, time_abs
+    if not os.access('%s_ab.txt'%f_name,os.R_OK):
+        print '%s_ab.txt does not exist'%f_name
+        return #file does not exist so do nochange values
+##    print '%s_ab.txt file exists and is readable'%f_name
+    ab = open('%s_ab.txt'%f_name,'r')
+    print '%s_ab.txt is opened'%f_name
+    s = ab.readline()
+##    print s
+    cex_abs_depth = int(s)
+    s = ab.readline()
+##    print s
+    time_abs_prev = float(s)
+    s = ab.readline()
+##    print s
+    time_abs = float(s)
+    s = ab.readline()
+##    print s
+    abs_depth_prev = float(s)
+    s = ab.readline()
+##    print s
+    abs_depth = float(s)
+    ab.close()
+##    print 'read: ',
+##    print cex_abs_depth,time_abs_prev,time_abs,abs_depth_prev,abs_depth
+##    print 'it is closed'
+
+def write_abs_values():
+    global cex_abs_depth, abs_depth, abs_depth_prev, time_abs_prev, time_abs
+    """here we write in the abs values written by monitor and prove"""
+##    print 'write: ',
+##    print cex_abs_depth,time_abs_prev,time_abs,abs_depth_prev,abs_depth
+    ab = open('%s_ab.txt'%f_name,'w')
+    ab.write(str(cex_abs_depth)+'\n')
+    ab.write(str(time_abs_prev)+'\n')
+    ab.write(str(time_abs)+'\n')
+    ab.write(str(abs_depth_prev)+'\n')
+    ab.write(str(abs_depth))
+    ab.close()
+
+def abs_done(time_remain):
+    """ heuristic to see if we are not making any progress and should quit
+        look at frame of last cex found (cex_abs_depth)  for current abstraction using a parallel engine
+        look at depth of current abstraction (abs_depth) and last abstraction (abs_deptth_prev)
+        look at time between new abstractions time_abs - time_abs_prev.
+        compute approximate frames_per_sec
+        if  frames_to_next_cex > frames_per_sec * time_remain
+        then won't get there is the time allowed.
+        We have to pass all the information along when we are doing things in parallel by writing a file
+        with this info in it and reading it in later. This is because monitor_and prove
+        runs in parallel and global variables are not passed around.
+    """
+    global cex_abs_depth, abs_depth, abs_depth_prev, time_abs_prev, time_abs
+##    print 'checking if abs has enough time to next cex'
+    frames_to_next_cex = cex_abs_depth - abs_depth
+    div = time_abs - time_abs_prev
+    div = max(.1,div)
+    frames_per_sec = (abs_depth - abs_depth_prev)/div
+    if frames_per_sec <= 0:
+        return False #something wrong 
+    print 'frames_per_sec = %0.2f, frames_to_next_cex = %d, time remaining = %0.2f'%(frames_per_sec, frames_to_next_cex, time_remain)
+    if frames_to_next_cex > 0.2*(frames_per_sec * time_remain): #later frames will take longer so factor of 5 here
+        print 'not enough abs time to next cex'
+        return True
+    return False
+
+##def gla_abs(t): 
+##    """ Do gate-level abstraction for F frames """
+##    r = 100 *(1 - abs_ratio)
+##    run_command('orpos; &get;&gla -dv -A %s_vabs.aig -T %d -R %d; &w %s_gla.aig'%(f_name,t,r,f_name))
+    
+        
+def monitor_and_prove():
+    """
+    monitor and prove. Runs in parallel with abstraction method.
+    It looks for a new vabs and if found, will try to verify it in parallel
+    We want to write a file that has variables
+    cex_abs_depth, abs_depth, abs_depth_prev, time_abs_prev, time_abs
+    which will be used by abs_done called by gla_abs_iter which is to replace gla_abs
+    """
+    global ifbip
+    global cex_abs_depth, abs_depth, abs_depth_prev, time_abs_prev, time_abs
+    #write the current aig as vabs.aig so it will be regularly verified at the beginning.
+    name = '%s_vabs.aig'%f_name
+    if os.access('%s'%name,os.R_OK): #make it so that there is no initial abstraction
+        os.remove('%s'%name)
+    initial_size = sizeof()
+    print 'initial size = ',
+    print initial_size
+    time_abs = time_abs_prev = time.time()
+    cex_abs_depth = 0
+    abs_depth = abs_depth_prev = 0
+    write_abs_values()
+##    if read_and_sleep(5): # wait until first abstraction when res is False
+##        #time has run out as controlled by abs_time
+##        return [Undecided_no_reduction] + ['read_and_sleep']
+    t = abs_time +10
+    tt = time.time()
+##    print 'first read and sleep done'
+    #a return of Undecided means that abstraction might be good and calling routine will check this
+    while True: #here we iterate looking for a new abstraction and trying to prove it
+        time_done = abs_bad = 0
+        funcs = [eval('(pyabc_split.defer(read_and_sleep)())')]
+        J = sims+intrps+pdrs+bmcs
+        J = modify_methods(J,1)
+        funcs = funcs + create_funcs(J,t) 
+        mtds = ['read_and_sleep'] + sublist(methods,J)
+        print 'methods = %s'%mtds
+        for i,res in pyabc_split.abc_split_all(funcs):
+##            print 'Mon. & Pr.: ,
+##            print i,res
+            if i == 0: # read_and_sleep terminated
+                if res == False: #found new abstraction
+                    read_abs_values()
+                    time_abs_prev = time_abs
+                    time_abs = time.time()
+                    print 'time between new abstractions = %0.2f'%(time_abs - time_abs_prev)
+                    write_abs_values()
+                    abs_bad = 0 #new abs starts out good.
+                    if not initial_size == sizeof() and n_latches() > abs_ratio * initial_size[2]:
+                        return [Undecided_no_reduction]+['read_and_sleep']
+                    else:
+                        break
+                elif res == True: # read and sleep timed out
+                    time_done = 1
+                    print 'read_and_sleep timed out'
+                    if abs_bad:
+                        return [Undecided_no_reduction]+['read_and_sleep']
+                    else: #abs is still good. Let other engines continue
+                        return [Undecided]+['read_and_sleep'] #calling routine handles >Unsat all the same right now.
+                else:
+                    assert False, 'something wrong. read and sleep did not return right thing'
+            if i > 0: #got result from one of the verify engines
+                print 'monitor_and_prove: Method %s terminated'%mtds[i],
+##                print i,res
+                if res == None:
+                    print 'Method %s failed'%mtds[i]
+                    continue
+##                print 'method %s found SAT in frame %d'%(mtds[i],cex_frame())
+                if is_unsat() or res == Unsat or res == 'UNSAT':
+                    print '\nParallel %s proved UNSAT on current abstr\n'%mtds[i]
+                    return [Unsat] + [mtds[i]]
+                elif is_sat() or res < Unsat or res == 'SAT': #abstraction is not good yet.
+                    print 'method = %s'%mtds[i]
+                    if not mtds[i] == 'RareSim': #the other engines give a better estimate of true cex depth
+                        read_abs_values()
+                        cex_abs_depth = cex_frame()
+                        write_abs_values()
+                    print '\nParallel %s found SAT on current abstr in frame %d\n'%(mtds[i],cex_frame())
+##                    print 'n_vabs = %d'%n_vabs
+                    if initial_size == sizeof():# the first time we were working on an aig before abstraction
+                        print initial_size == abstraction_size
+                        return [Sat]+[mtds[i]]
+##                    print 'current abstraction invalid'
+                    abs_bad = 1 
+                    break #this kills off other verification engines working on bad abstraction
+                else: #one of the engines undecided for some reason - failed?
+                    print '\nParallel %s terminated without result on current abstr\n'%mtds[i]
+                    continue
+        if abs_bad and not time_done: #here we wait until have a new vabs.
+            time_remain = t -(time.time() - tt)
+            abc('r %s_abs.aig'%f_name) #read in the abstraction to destroy is_sat().
+            if abs_done(time_remain):
+                return [Undecided]+['timeout']
+            res = read_and_sleep(5) #this will check every 5 sec, until abs_time sec has passed without new abs            
+            if res == False: #found new vabs. Now continue if vabs small enough
+##                print 'n_vabs = %d'%n_vabs
+                if (not initial_size == sizeof()) and n_latches() > abs_ratio * initial_size[2]:
+                    return [Undecided_no_reduction]+['no reduction']
+                else:
+                    continue
+            elif res ==True: #read_and_sleep timed out
+##                print 'read_and_sleep timed out'
+                return [Undecided_no_reduction]+['no reduction']
+            else:
+                break #this should not happen
+        elif abs_bad and time_done:
+##            print 'current abstraction bad, time has run out'
+            return [Undecided_no_reduction]+['no reduction']
+        elif time_done: #abs is good here
+##            print 'current abstraction still good, time has run out'
+            return [Undecided]+['reduction'] #this will cause calling routine to try to verify the final abstraction
+                            #right now handles the same as Undecided_no_reduction-if time runs out we quit abstraction
+        else: #abs good and time not done
+            continue
+##            print 'current abstraction still good, time has not run out'
+    return [len(funcs)]+['error']
+
+def read_and_sleep(t=5):
+    """
+    keep looking for a new vabs every 5 seconds. This is usually run in parallel with
+    &vta -d or &gla
+    Returns False when new abstraction is found, and True when time runs out.
+    """
+    global cex_abs_depth, abs_depth, abs_depth_prev, time_abs_prev, time_abs
+    #t is not used at present
+    tt = time.time()
+    T = 1000 #if after the last abstraction, no answer, then terminate
+    T = abs_time + 10
+    set_size()
+    name = '%s_vabs.aig'%f_name
+##    if ifbip > 0:
+##        name = '%s_vabs.aig'%f_name
+##    print 'name = %s'%name
+    sleep(5)
+    while True:
+        if time.time() - tt > T: #too much time between abstractions
+##            print 'read_and_sleep timed out in %d sec.'%T
+            return True
+        if os.access(name,os.R_OK):
+            #possible race condition
+            run_command('&r -s %s; &w %s_vabs_old.aig'%(name,f_name))
+##            print '%s exists'%name
+            if not os.access(name,os.R_OK): #if not readable now then what was read in might not be OK.
+                print '%s does not exist'%name
+                continue
+##            print '%s is read'%name
+##            run_command('&r %s;read_status %s_vabs.status'%(name,f_name)) #need to use & space to keep the abstraction information
+            os.remove(name)
+            run_command('read_status %s_vabs.status'%f_name)
+##            print '%s and %s_vabs.status have been read'%(name,f_name)
+##            print 'reading %s_vabs.status'%f_name
+            #name is the derived model (not the model with abstraction info
+            run_command('&r -s %s_vabs_old.aig'%f_name)
+            run_command('&w %s_gla.aig'%f_name)
+            run_command('&gla_derive;&put')
+            run_command('w %s_gabs.aig'%f_name)
+##            print '%s is removed'%name
+            read_abs_values()
+            time_abs_prev = time_abs
+            time_abs = time.time()
+##            print 'abs values has been read'
+            run_command('read_status %s_vabs.status'%f_name) 
+            abs_depth_prev = abs_depth
+            abs_depth = n_bmc_frames()
+            write_abs_values()
+##            print 'abs values has been written'
+            time_remain = T - (time.time() - tt)
+            if abs_done(time_remain):
+            	return True
+##            if not check_size():
+            if True:
+                print '\nNew abstraction: ',
+                ps()
+##                print 'Time = %0.2f'%(time.time() - tt)
+                set_size()
+                abc('w %s_abs.aig'%f_name)
+                return False
+            #if same size, keep going.
+        print '.',
+        sleep(5)
+####################################################
diff --git a/abc-build/scripts/simple.sh b/abc-build/scripts/simple.sh
new file mode 100644
--- /dev/null
+++ b/abc-build/scripts/simple.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+abc_root()
+{
+    cwd="$(pwd)"
+    cd $(dirname "$1")
+    echo $(dirname "$(pwd)")
+    cd "${cwd}"
+}
+
+abc_dir=$(abc_root "$0")
+bin_dir="${abc_dir}"/bin
+
+exec ${bin_dir}/abc -q "/simple_aiger $*"
diff --git a/abc-build/scripts/simple_bip.sh b/abc-build/scripts/simple_bip.sh
new file mode 100644
--- /dev/null
+++ b/abc-build/scripts/simple_bip.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+abc_root()
+{
+    cwd="$(pwd)"
+    cd $(dirname "$1")
+    echo $(dirname "$(pwd)")
+    cd "${cwd}"
+}
+
+abc_dir=$(abc_root "$0")
+bin_dir="${abc_dir}"/bin
+
+exec ${bin_dir}/abc -q "/simple_bip_aiger $*"
diff --git a/abc-build/scripts/simple_liveness.sh b/abc-build/scripts/simple_liveness.sh
new file mode 100644
--- /dev/null
+++ b/abc-build/scripts/simple_liveness.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+abc_root()
+{
+    cwd="$(pwd)"
+    cd $(dirname "$1")
+    echo $(dirname "$(pwd)")
+    cd "${cwd}"
+}
+
+abc_dir=$(abc_root "$0")
+bin_dir="${abc_dir}"/bin
+
+exec ${bin_dir}/abc -q "/simple_liveness_aiger $*"
diff --git a/abc-build/scripts/simple_sat.sh b/abc-build/scripts/simple_sat.sh
new file mode 100644
--- /dev/null
+++ b/abc-build/scripts/simple_sat.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+abc_root()
+{
+    cwd="$(pwd)"
+    cd $(dirname "$1")
+    echo $(dirname "$(pwd)")
+    cd "${cwd}"
+}
+
+abc_dir=$(abc_root "$0")
+bin_dir="${abc_dir}"/bin
+
+exec ${bin_dir}/abc -q "/simple_sat_aiger $*"
diff --git a/abc-build/scripts/super_prove.sh b/abc-build/scripts/super_prove.sh
new file mode 100644
--- /dev/null
+++ b/abc-build/scripts/super_prove.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+abc_root()
+{
+    cwd="$(pwd)"
+    cd $(dirname "$1")
+    echo $(dirname "$(pwd)")
+    cd "${cwd}"
+}
+
+abc_dir=$(abc_root "$0")
+bin_dir="${abc_dir}"/bin
+
+exec ${bin_dir}/abc -q "/super_prove_aiger $*"
diff --git a/abc-build/src/aig/aig/aig.h b/abc-build/src/aig/aig/aig.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aig.h
@@ -0,0 +1,713 @@
+/**CFile****************************************************************
+
+  FileName    [aig.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aig.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__aig__aig_h
+#define ABC__aig__aig__aig_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+#include "misc/util/utilCex.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Aig_Man_t_            Aig_Man_t;
+typedef struct Aig_Obj_t_            Aig_Obj_t;
+typedef struct Aig_MmFixed_t_        Aig_MmFixed_t;    
+typedef struct Aig_MmFlex_t_         Aig_MmFlex_t;     
+typedef struct Aig_MmStep_t_         Aig_MmStep_t;     
+
+// object types
+typedef enum { 
+    AIG_OBJ_NONE,                    // 0: non-existent object
+    AIG_OBJ_CONST1,                  // 1: constant 1 
+    AIG_OBJ_CI,                      // 2: combinational input
+    AIG_OBJ_CO,                      // 3: combinational output
+    AIG_OBJ_BUF,                     // 4: buffer node
+    AIG_OBJ_AND,                     // 5: AND node
+    AIG_OBJ_EXOR,                    // 6: EXOR node
+    AIG_OBJ_VOID                     // 7: unused object
+} Aig_Type_t;
+
+// the AIG node
+struct Aig_Obj_t_  // 8 words
+{
+    union {                         
+        Aig_Obj_t *  pNext;          // strashing table
+        int          CioId;          // 0-based number of CI/CO
+    };
+    Aig_Obj_t *      pFanin0;        // fanin
+    Aig_Obj_t *      pFanin1;        // fanin
+    unsigned int     Type    :  3;   // object type
+    unsigned int     fPhase  :  1;   // value under 000...0 pattern
+    unsigned int     fMarkA  :  1;   // multipurpose mask
+    unsigned int     fMarkB  :  1;   // multipurpose mask
+    unsigned int     nRefs   : 26;   // reference count 
+    unsigned         Level   : 24;   // the level of this node
+    unsigned         nCuts   :  8;   // the number of cuts
+    int              TravId;         // unique ID of last traversal involving the node
+    int              Id;             // unique ID of the node
+    union {                          // temporary store for user's data
+        void *       pData;
+        int          iData;
+        float        dData;
+    };
+};
+
+// the AIG manager
+struct Aig_Man_t_
+{
+    char *           pName;          // the design name
+    char *           pSpec;          // the input file name
+    // AIG nodes
+    Vec_Ptr_t *      vCis;           // the array of PIs
+    Vec_Ptr_t *      vCos;           // the array of POs
+    Vec_Ptr_t *      vObjs;          // the array of all nodes (optional)
+    Vec_Ptr_t *      vBufs;          // the array of buffers
+    Aig_Obj_t *      pConst1;        // the constant 1 node
+    Aig_Obj_t        Ghost;          // the ghost node
+    int              nRegs;          // the number of registers (registers are last POs)
+    int              nTruePis;       // the number of true primary inputs
+    int              nTruePos;       // the number of true primary outputs
+    int              nAsserts;       // the number of asserts among POs (asserts are first POs)
+    int              nConstrs;       // the number of constraints (model checking only)
+    int              nBarBufs;       // the number of barrier buffers
+    // AIG node counters
+    int              nObjs[AIG_OBJ_VOID];// the number of objects by type
+    int              nDeleted;       // the number of deleted objects
+    // structural hash table
+    Aig_Obj_t **     pTable;         // structural hash table
+    int              nTableSize;     // structural hash table size
+    // representation of fanouts
+    int *            pFanData;       // the database to store fanout information
+    int              nFansAlloc;     // the size of fanout representation
+    Vec_Vec_t *      vLevels;        // used to update timing information
+    int              nBufReplaces;   // the number of times replacement led to a buffer
+    int              nBufFixes;      // the number of times buffers were propagated
+    int              nBufMax;        // the maximum number of buffers during computation
+    // topological order
+    unsigned *       pOrderData;
+    int              nOrderAlloc;
+    int              iPrev;
+    int              iNext;
+    int              nAndTotal;
+    int              nAndPrev;
+    // representatives
+    Aig_Obj_t **     pEquivs;        // linked list of equivalent nodes (when choices are used)
+    Aig_Obj_t **     pReprs;         // representatives of each node
+    int              nReprsAlloc;    // the number of allocated representatives
+    // various data members
+    Aig_MmFixed_t *  pMemObjs;       // memory manager for objects
+    Vec_Int_t *      vLevelR;        // the reverse level of the nodes
+    int              nLevelMax;      // maximum number of levels
+    void *           pData;          // the temporary data
+    void *           pData2;         // the temporary data
+    int              nTravIds;       // the current traversal ID
+    int              fCatchExor;     // enables EXOR nodes
+    int              fAddStrash;     // performs additional strashing
+    Aig_Obj_t **     pObjCopies;     // mapping of AIG nodes into FRAIG nodes
+    void (*pImpFunc) (void*, void*); // implication checking precedure
+    void *           pImpData;       // implication checking data
+    void *           pManTime;       // the timing manager
+    void *           pManCuts;
+    int *            pFastSim; 
+    unsigned *       pTerSimData;    // ternary simulation data
+    Vec_Ptr_t *      vMapped;
+    Vec_Int_t *      vFlopNums;      
+    Vec_Int_t *      vFlopReprs;      
+    Abc_Cex_t *      pSeqModel;
+    Vec_Ptr_t *      vSeqModelVec;   // vector of counter-examples (for sequential miters)
+    Aig_Man_t *      pManExdc;
+    Vec_Ptr_t *      vOnehots;
+    int              fCreatePios;
+    Vec_Int_t *      vEquPairs;   
+    Vec_Vec_t *      vClockDoms; 
+    Vec_Int_t *      vProbs;         // probability of node being 1 
+    Vec_Int_t *      vCiNumsOrig;    // original CI names
+    int              nComplEdges;    // complemented edges
+    abctime          Time2Quit;
+    // timing statistics
+    abctime          time1;
+    abctime          time2;
+  //-- jlong -- begin
+  Vec_Ptr_t *      unfold2_type_I;
+  Vec_Ptr_t *      unfold2_type_II;
+  //-- jlong -- end
+};
+
+// cut computation
+typedef struct Aig_ManCut_t_         Aig_ManCut_t;
+typedef struct Aig_Cut_t_            Aig_Cut_t;
+
+// the cut used to represent node in the AIG
+struct Aig_Cut_t_
+{
+    Aig_Cut_t *     pNext;           // the next cut in the table 
+    int             Cost;            // the cost of the cut
+    unsigned        uSign;           // cut signature
+    int             iNode;           // the node, for which it is the cut
+    short           nCutSize;        // the number of bytes in the cut
+    char            nLeafMax;        // the maximum number of fanins
+    char            nFanins;         // the current number of fanins
+    int             pFanins[0];      // the fanins (followed by the truth table)
+};
+
+// the CNF computation manager
+struct Aig_ManCut_t_
+{
+    // AIG manager
+    Aig_Man_t *     pAig;            // the input AIG manager
+    Aig_Cut_t **    pCuts;           // the cuts for each node in the output manager
+    // parameters
+    int             nCutsMax;        // the max number of cuts at the node
+    int             nLeafMax;        // the max number of leaves of a cut
+    int             fTruth;          // enables truth table computation
+    int             fVerbose;        // enables verbose output
+    // internal variables
+    int             nCutSize;        // the number of bytes needed to store one cut
+    int             nTruthWords;     // the number of truth table words
+    Aig_MmFixed_t * pMemCuts;        // memory manager for cuts
+    unsigned *      puTemp[4];       // used for the truth table computation
+};
+
+static inline Aig_Cut_t *  Aig_ObjCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj )                         { return p->pCuts[pObj->Id];  }
+static inline void         Aig_ObjSetCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj, Aig_Cut_t * pCuts )   { p->pCuts[pObj->Id] = pCuts; }
+
+static inline int          Aig_CutLeaveNum( Aig_Cut_t * pCut )          { return pCut->nFanins;                                    }
+static inline int *        Aig_CutLeaves( Aig_Cut_t * pCut )            { return pCut->pFanins;                                    }
+static inline unsigned *   Aig_CutTruth( Aig_Cut_t * pCut )             { return (unsigned *)(pCut->pFanins + pCut->nLeafMax);     }
+static inline Aig_Cut_t *  Aig_CutNext( Aig_Cut_t * pCut )              { return (Aig_Cut_t *)(((char *)pCut) + pCut->nCutSize);   }
+
+// iterator over cuts of the node
+#define Aig_ObjForEachCut( p, pObj, pCut, i )                           \
+    for ( i = 0, pCut = Aig_ObjCuts(p, pObj); i < p->nCutsMax; i++, pCut = Aig_CutNext(pCut) ) 
+// iterator over leaves of the cut
+#define Aig_CutForEachLeaf( p, pCut, pLeaf, i )                         \
+    for ( i = 0; (i < (int)(pCut)->nFanins) && ((pLeaf) = Aig_ManObj(p, (pCut)->pFanins[i])); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline unsigned     Aig_ObjCutSign( unsigned ObjId )       { return (1 << (ObjId & 31));                            }
+static inline int          Aig_WordCountOnes( unsigned uWord )
+{
+    uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555);
+    uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333);
+    uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F);
+    uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF);
+    return  (uWord & 0x0000FFFF) + (uWord>>16);
+}
+static inline int          Aig_WordFindFirstBit( unsigned uWord )
+{
+    int i;
+    for ( i = 0; i < 32; i++ )
+        if ( uWord & (1 << i) )
+            return i;
+    return -1;
+}
+
+static inline Aig_Obj_t *  Aig_Regular( Aig_Obj_t * p )           { return (Aig_Obj_t *)((ABC_PTRUINT_T)(p) & ~01);  }
+static inline Aig_Obj_t *  Aig_Not( Aig_Obj_t * p )               { return (Aig_Obj_t *)((ABC_PTRUINT_T)(p) ^  01);  }
+static inline Aig_Obj_t *  Aig_NotCond( Aig_Obj_t * p, int c )    { return (Aig_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c));  }
+static inline int          Aig_IsComplement( Aig_Obj_t * p )      { return (int)((ABC_PTRUINT_T)(p) & 01);           }
+
+static inline int          Aig_ManCiNum( Aig_Man_t * p )          { return p->nObjs[AIG_OBJ_CI];                     }
+static inline int          Aig_ManCoNum( Aig_Man_t * p )          { return p->nObjs[AIG_OBJ_CO];                     }
+static inline int          Aig_ManBufNum( Aig_Man_t * p )         { return p->nObjs[AIG_OBJ_BUF];                    }
+static inline int          Aig_ManAndNum( Aig_Man_t * p )         { return p->nObjs[AIG_OBJ_AND];                    }
+static inline int          Aig_ManExorNum( Aig_Man_t * p )        { return p->nObjs[AIG_OBJ_EXOR];                   }
+static inline int          Aig_ManNodeNum( Aig_Man_t * p )        { return p->nObjs[AIG_OBJ_AND]+p->nObjs[AIG_OBJ_EXOR];   }
+static inline int          Aig_ManGetCost( Aig_Man_t * p )        { return p->nObjs[AIG_OBJ_AND]+3*p->nObjs[AIG_OBJ_EXOR]; }
+static inline int          Aig_ManObjNum( Aig_Man_t * p )         { return Vec_PtrSize(p->vObjs) - p->nDeleted;      }
+static inline int          Aig_ManObjNumMax( Aig_Man_t * p )      { return Vec_PtrSize(p->vObjs);                    }
+static inline int          Aig_ManRegNum( Aig_Man_t * p )         { return p->nRegs;                                 }
+static inline int          Aig_ManConstrNum( Aig_Man_t * p )      { return p->nConstrs;                              }
+
+static inline Aig_Obj_t *  Aig_ManConst0( Aig_Man_t * p )         { return Aig_Not(p->pConst1);                      }
+static inline Aig_Obj_t *  Aig_ManConst1( Aig_Man_t * p )         { return p->pConst1;                               }
+static inline Aig_Obj_t *  Aig_ManGhost( Aig_Man_t * p )          { return &p->Ghost;                                }
+static inline Aig_Obj_t *  Aig_ManCi( Aig_Man_t * p, int i )      { return (Aig_Obj_t *)Vec_PtrEntry(p->vCis, i);    }
+static inline Aig_Obj_t *  Aig_ManCo( Aig_Man_t * p, int i )      { return (Aig_Obj_t *)Vec_PtrEntry(p->vCos, i);    }
+static inline Aig_Obj_t *  Aig_ManLo( Aig_Man_t * p, int i )      { return (Aig_Obj_t *)Vec_PtrEntry(p->vCis, Aig_ManCiNum(p)-Aig_ManRegNum(p)+i);   }
+static inline Aig_Obj_t *  Aig_ManLi( Aig_Man_t * p, int i )      { return (Aig_Obj_t *)Vec_PtrEntry(p->vCos, Aig_ManCoNum(p)-Aig_ManRegNum(p)+i);   }
+static inline Aig_Obj_t *  Aig_ManObj( Aig_Man_t * p, int i )     { return p->vObjs ? (Aig_Obj_t *)Vec_PtrEntry(p->vObjs, i) : NULL;  }
+
+static inline Aig_Type_t   Aig_ObjType( Aig_Obj_t * pObj )        { return (Aig_Type_t)pObj->Type;       }
+static inline int          Aig_ObjIsNone( Aig_Obj_t * pObj )      { return pObj->Type == AIG_OBJ_NONE;   }
+static inline int          Aig_ObjIsConst1( Aig_Obj_t * pObj )    { assert(!Aig_IsComplement(pObj)); return pObj->Type == AIG_OBJ_CONST1; }
+static inline int          Aig_ObjIsCi( Aig_Obj_t * pObj )        { return pObj->Type == AIG_OBJ_CI;     }
+static inline int          Aig_ObjIsCo( Aig_Obj_t * pObj )        { return pObj->Type == AIG_OBJ_CO;     }
+static inline int          Aig_ObjIsBuf( Aig_Obj_t * pObj )       { return pObj->Type == AIG_OBJ_BUF;    }
+static inline int          Aig_ObjIsAnd( Aig_Obj_t * pObj )       { return pObj->Type == AIG_OBJ_AND;    }
+static inline int          Aig_ObjIsExor( Aig_Obj_t * pObj )      { return pObj->Type == AIG_OBJ_EXOR;   }
+static inline int          Aig_ObjIsNode( Aig_Obj_t * pObj )      { return pObj->Type == AIG_OBJ_AND || pObj->Type == AIG_OBJ_EXOR;   }
+static inline int          Aig_ObjIsTerm( Aig_Obj_t * pObj )      { return pObj->Type == AIG_OBJ_CI  || pObj->Type == AIG_OBJ_CO || pObj->Type == AIG_OBJ_CONST1;   }
+static inline int          Aig_ObjIsHash( Aig_Obj_t * pObj )      { return pObj->Type == AIG_OBJ_AND || pObj->Type == AIG_OBJ_EXOR;                                 }
+static inline int          Aig_ObjIsChoice( Aig_Man_t * p, Aig_Obj_t * pObj )    { return p->pEquivs && p->pEquivs[pObj->Id] && pObj->nRefs > 0;                    }
+static inline int          Aig_ObjIsCand( Aig_Obj_t * pObj )      { return pObj->Type == AIG_OBJ_CI || pObj->Type == AIG_OBJ_AND || pObj->Type == AIG_OBJ_EXOR;     }
+static inline int          Aig_ObjCioId( Aig_Obj_t * pObj )       { assert( !Aig_ObjIsNode(pObj) ); return pObj->CioId;                                            }
+static inline int          Aig_ObjId( Aig_Obj_t * pObj )          { return pObj->Id;                     }
+
+static inline int          Aig_ObjIsMarkA( Aig_Obj_t * pObj )     { return pObj->fMarkA;  }
+static inline void         Aig_ObjSetMarkA( Aig_Obj_t * pObj )    { pObj->fMarkA = 1;     }
+static inline void         Aig_ObjClearMarkA( Aig_Obj_t * pObj )  { pObj->fMarkA = 0;     }
+ 
+static inline void         Aig_ObjSetTravId( Aig_Obj_t * pObj, int TravId )                { pObj->TravId = TravId;                         }
+static inline void         Aig_ObjSetTravIdCurrent( Aig_Man_t * p, Aig_Obj_t * pObj )      { pObj->TravId = p->nTravIds;                    }
+static inline void         Aig_ObjSetTravIdPrevious( Aig_Man_t * p, Aig_Obj_t * pObj )     { pObj->TravId = p->nTravIds - 1;                }
+static inline int          Aig_ObjIsTravIdCurrent( Aig_Man_t * p, Aig_Obj_t * pObj )       { return (int)(pObj->TravId == p->nTravIds);     }
+static inline int          Aig_ObjIsTravIdPrevious( Aig_Man_t * p, Aig_Obj_t * pObj )      { return (int)(pObj->TravId == p->nTravIds - 1); }
+
+static inline int          Aig_ObjPhase( Aig_Obj_t * pObj )       { return pObj->fPhase;                           }
+static inline int          Aig_ObjPhaseReal( Aig_Obj_t * pObj )   { return pObj? Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) : 1;                              }
+static inline int          Aig_ObjRefs( Aig_Obj_t * pObj )        { return pObj->nRefs;                            }
+static inline void         Aig_ObjRef( Aig_Obj_t * pObj )         { pObj->nRefs++;                                 }
+static inline void         Aig_ObjDeref( Aig_Obj_t * pObj )       { assert( pObj->nRefs > 0 ); pObj->nRefs--;      }
+static inline void         Aig_ObjClearRef( Aig_Obj_t * pObj )    { pObj->nRefs = 0;                               }
+static inline int          Aig_ObjFaninId0( Aig_Obj_t * pObj )    { return pObj->pFanin0? Aig_Regular(pObj->pFanin0)->Id : -1; }
+static inline int          Aig_ObjFaninId1( Aig_Obj_t * pObj )    { return pObj->pFanin1? Aig_Regular(pObj->pFanin1)->Id : -1; }
+static inline int          Aig_ObjFaninC0( Aig_Obj_t * pObj )     { return Aig_IsComplement(pObj->pFanin0);        }
+static inline int          Aig_ObjFaninC1( Aig_Obj_t * pObj )     { return Aig_IsComplement(pObj->pFanin1);        }
+static inline Aig_Obj_t *  Aig_ObjFanin0( Aig_Obj_t * pObj )      { return Aig_Regular(pObj->pFanin0);             }
+static inline Aig_Obj_t *  Aig_ObjFanin1( Aig_Obj_t * pObj )      { return Aig_Regular(pObj->pFanin1);             }
+static inline Aig_Obj_t *  Aig_ObjChild0( Aig_Obj_t * pObj )      { return pObj->pFanin0;                          }
+static inline Aig_Obj_t *  Aig_ObjChild1( Aig_Obj_t * pObj )      { return pObj->pFanin1;                          }
+static inline Aig_Obj_t *  Aig_ObjChild0Copy( Aig_Obj_t * pObj )  { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj)) : NULL;  }
+static inline Aig_Obj_t *  Aig_ObjChild1Copy( Aig_Obj_t * pObj )  { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj)) : NULL;  }
+static inline Aig_Obj_t *  Aig_ObjChild0Next( Aig_Obj_t * pObj )  { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj)->pNext, Aig_ObjFaninC0(pObj)) : NULL;  }
+static inline Aig_Obj_t *  Aig_ObjChild1Next( Aig_Obj_t * pObj )  { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin1(pObj)->pNext, Aig_ObjFaninC1(pObj)) : NULL;  }
+static inline void         Aig_ObjChild0Flip( Aig_Obj_t * pObj )  { assert( !Aig_IsComplement(pObj) ); pObj->pFanin0 = Aig_Not(pObj->pFanin0);        }
+static inline void         Aig_ObjChild1Flip( Aig_Obj_t * pObj )  { assert( !Aig_IsComplement(pObj) ); pObj->pFanin1 = Aig_Not(pObj->pFanin1);        }
+static inline Aig_Obj_t *  Aig_ObjCopy( Aig_Obj_t * pObj )        { assert( !Aig_IsComplement(pObj) ); return (Aig_Obj_t *)pObj->pData;               } 
+static inline void         Aig_ObjSetCopy( Aig_Obj_t * pObj, Aig_Obj_t * pCopy )     {  assert( !Aig_IsComplement(pObj) ); pObj->pData = pCopy;       } 
+static inline Aig_Obj_t *  Aig_ObjRealCopy( Aig_Obj_t * pObj )    { return Aig_NotCond((Aig_Obj_t *)Aig_Regular(pObj)->pData, Aig_IsComplement(pObj));}
+static inline int          Aig_ObjToLit( Aig_Obj_t * pObj )       { return Abc_Var2Lit( Aig_ObjId(Aig_Regular(pObj)), Aig_IsComplement(pObj) );       }
+static inline Aig_Obj_t *  Aig_ObjFromLit( Aig_Man_t * p,int iLit){ return Aig_NotCond( Aig_ManObj(p, Abc_Lit2Var(iLit)), Abc_LitIsCompl(iLit) );     }
+static inline int          Aig_ObjLevel( Aig_Obj_t * pObj )       { assert( !Aig_IsComplement(pObj) ); return pObj->Level;                            }
+static inline int          Aig_ObjLevelNew( Aig_Obj_t * pObj )    { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? 1 + Aig_ObjIsExor(pObj) + Abc_MaxInt(Aig_ObjFanin0(pObj)->Level, Aig_ObjFanin1(pObj)->Level) : Aig_ObjFanin0(pObj)->Level; }
+static inline int          Aig_ObjSetLevel( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return pObj->Level = i;                    }
+static inline void         Aig_ObjClean( Aig_Obj_t * pObj )       { memset( pObj, 0, sizeof(Aig_Obj_t) );                                                             }
+static inline Aig_Obj_t *  Aig_ObjFanout0( Aig_Man_t * p, Aig_Obj_t * pObj )  { assert(p->pFanData && pObj->Id < p->nFansAlloc); return Aig_ManObj(p, p->pFanData[5*pObj->Id] >> 1); } 
+static inline Aig_Obj_t *  Aig_ObjEquiv( Aig_Man_t * p, Aig_Obj_t * pObj )    { return p->pEquivs? p->pEquivs[pObj->Id] : NULL;           } 
+static inline void         Aig_ObjSetEquiv( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pEqu ) { assert(p->pEquivs); p->pEquivs[pObj->Id] = pEqu;                  }
+static inline Aig_Obj_t *  Aig_ObjRepr( Aig_Man_t * p, Aig_Obj_t * pObj )     { return p->pReprs? p->pReprs[pObj->Id] : NULL;             } 
+static inline void         Aig_ObjSetRepr( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr )     { assert(p->pReprs); p->pReprs[pObj->Id] = pRepr;                                } 
+static inline int          Aig_ObjWhatFanin( Aig_Obj_t * pObj, Aig_Obj_t * pFanin )    
+{ 
+    if ( Aig_ObjFanin0(pObj) == pFanin ) return 0; 
+    if ( Aig_ObjFanin1(pObj) == pFanin ) return 1; 
+    assert(0); return -1; 
+}
+static inline int          Aig_ObjFanoutC( Aig_Obj_t * pObj, Aig_Obj_t * pFanout )    
+{ 
+    if ( Aig_ObjFanin0(pFanout) == pObj ) return Aig_ObjFaninC0(pObj); 
+    if ( Aig_ObjFanin1(pFanout) == pObj ) return Aig_ObjFaninC1(pObj); 
+    assert(0); return -1; 
+}
+
+// create the ghost of the new node
+static inline Aig_Obj_t *  Aig_ObjCreateGhost( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type )    
+{
+    Aig_Obj_t * pGhost;
+    assert( Type != AIG_OBJ_AND || !Aig_ObjIsConst1(Aig_Regular(p0)) );
+    assert( p1 == NULL || !Aig_ObjIsConst1(Aig_Regular(p1)) );
+    assert( Type == AIG_OBJ_CI || Aig_Regular(p0) != Aig_Regular(p1) );
+    pGhost = Aig_ManGhost(p);
+    pGhost->Type = Type;
+    if ( p1 == NULL || Aig_Regular(p0)->Id < Aig_Regular(p1)->Id )
+    {
+        pGhost->pFanin0 = p0;
+        pGhost->pFanin1 = p1;
+    }
+    else
+    {
+        pGhost->pFanin0 = p1;
+        pGhost->pFanin1 = p0;
+    }
+    return pGhost;
+}
+
+// internal memory manager
+static inline Aig_Obj_t * Aig_ManFetchMemory( Aig_Man_t * p )  
+{
+    extern char * Aig_MmFixedEntryFetch( Aig_MmFixed_t * p );
+    Aig_Obj_t * pTemp;
+    pTemp = (Aig_Obj_t *)Aig_MmFixedEntryFetch( p->pMemObjs );
+    memset( pTemp, 0, sizeof(Aig_Obj_t) ); 
+    pTemp->Id = Vec_PtrSize(p->vObjs);
+    Vec_PtrPush( p->vObjs, pTemp );
+    return pTemp;
+}
+static inline void Aig_ManRecycleMemory( Aig_Man_t * p, Aig_Obj_t * pEntry )
+{
+    extern void Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry );
+    assert( pEntry->nRefs == 0 );
+    pEntry->Type = AIG_OBJ_NONE; // distinquishes a dead node from a live node
+    Aig_MmFixedEntryRecycle( p->pMemObjs, (char *)pEntry );
+    p->nDeleted++;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                             ITERATORS                            ///
+////////////////////////////////////////////////////////////////////////
+
+// iterator over the combinational inputs
+#define Aig_ManForEachCi( p, pObj, i )                                          \
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vCis, pObj, i )
+#define Aig_ManForEachCiReverse( p, pObj, i )                                   \
+    Vec_PtrForEachEntryReverse( Aig_Obj_t *, p->vCis, pObj, i )
+// iterator over the combinational outputs
+#define Aig_ManForEachCo( p, pObj, i )                                          \
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vCos, pObj, i )
+#define Aig_ManForEachCoReverse( p, pObj, i )                                   \
+    Vec_PtrForEachEntryReverse( Aig_Obj_t *, p->vCos, pObj, i )
+// iterators over all objects, including those currently not used
+#define Aig_ManForEachObj( p, pObj, i )                                         \
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else
+#define Aig_ManForEachObjReverse( p, pObj, i )                                  \
+    Vec_PtrForEachEntryReverse( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else
+// iterators over the objects whose IDs are stored in an array
+#define Aig_ManForEachObjVec( vIds, p, pObj, i )                                \
+    for ( i = 0; i < Vec_IntSize(vIds) && (((pObj) = Aig_ManObj(p, Vec_IntEntry(vIds,i))), 1); i++ )
+#define Aig_ManForEachObjVecReverse( vIds, p, pObj, i )                         \
+    for ( i = Vec_IntSize(vIds) - 1; i >= 0 && (((pObj) = Aig_ManObj(p, Vec_IntEntry(vIds,i))), 1); i-- )
+// iterators over all nodes
+#define Aig_ManForEachNode( p, pObj, i )                                        \
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL || !Aig_ObjIsNode(pObj) ) {} else
+#define Aig_ManForEachNodeReverse( p, pObj, i )                                 \
+    Vec_PtrForEachEntryReverse( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL || !Aig_ObjIsNode(pObj) ) {} else
+// iterator over all nodes
+#define Aig_ManForEachExor( p, pObj, i )                                        \
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL || !Aig_ObjIsExor(pObj) ) {} else
+#define Aig_ManForEachExorReverse( p, pObj, i )                                 \
+    Vec_PtrForEachEntryReverse( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL || !Aig_ObjIsExor(pObj) ) {} else
+
+// these two procedures are only here for the use inside the iterator
+static inline int     Aig_ObjFanout0Int( Aig_Man_t * p, int ObjId )  { assert(ObjId < p->nFansAlloc);  return p->pFanData[5*ObjId];                         }
+static inline int     Aig_ObjFanoutNext( Aig_Man_t * p, int iFan )   { assert(iFan/2 < p->nFansAlloc); return p->pFanData[5*(iFan >> 1) + 3 + (iFan & 1)];  }
+// iterator over the fanouts
+#define Aig_ObjForEachFanout( p, pObj, pFanout, iFan, i )                       \
+    for ( assert(p->pFanData), i = 0; (i < (int)(pObj)->nRefs) &&               \
+          (((iFan) = i? Aig_ObjFanoutNext(p, iFan) : Aig_ObjFanout0Int(p, pObj->Id)), 1) && \
+          (((pFanout) = Aig_ManObj(p, iFan>>1)), 1); i++ )
+
+
+////////////////////////////////////////////////////////////////////////
+///                     SEQUENTIAL ITERATORS                         ///
+////////////////////////////////////////////////////////////////////////
+
+// iterator over the primary inputs
+#define Aig_ManForEachPiSeq( p, pObj, i )                                       \
+    Vec_PtrForEachEntryStop( Aig_Obj_t *, p->vCis, pObj, i, Aig_ManCiNum(p)-Aig_ManRegNum(p) )
+// iterator over the latch outputs
+#define Aig_ManForEachLoSeq( p, pObj, i )                                       \
+    Vec_PtrForEachEntryStart( Aig_Obj_t *, p->vCis, pObj, i, Aig_ManCiNum(p)-Aig_ManRegNum(p) )
+// iterator over the primary outputs
+#define Aig_ManForEachPoSeq( p, pObj, i )                                       \
+    Vec_PtrForEachEntryStop( Aig_Obj_t *, p->vCos, pObj, i, Aig_ManCoNum(p)-Aig_ManRegNum(p) )
+// iterator over the latch inputs
+#define Aig_ManForEachLiSeq( p, pObj, i )                                       \
+    Vec_PtrForEachEntryStart( Aig_Obj_t *, p->vCos, pObj, i, Aig_ManCoNum(p)-Aig_ManRegNum(p) )
+// iterator over the latch input and outputs
+#define Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, k )                           \
+    for ( k = 0; (k < Aig_ManRegNum(p)) && (((pObjLi) = Aig_ManLi(p, k)), 1)    \
+        && (((pObjLo)=Aig_ManLo(p, k)), 1); k++ )
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== aigCheck.c ========================================================*/
+extern ABC_DLL int     Aig_ManCheck( Aig_Man_t * p );
+extern void            Aig_ManCheckMarkA( Aig_Man_t * p );
+extern void            Aig_ManCheckPhase( Aig_Man_t * p );
+/*=== aigCuts.c ========================================================*/
+extern Aig_ManCut_t *  Aig_ComputeCuts( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fTruth, int fVerbose );
+extern void            Aig_ManCutStop( Aig_ManCut_t * p );
+/*=== aigDfs.c ==========================================================*/
+extern int             Aig_ManVerifyTopoOrder( Aig_Man_t * p );
+extern Vec_Ptr_t *     Aig_ManDfs( Aig_Man_t * p, int fNodesOnly );
+extern Vec_Ptr_t *     Aig_ManDfsAll( Aig_Man_t * p );
+extern Vec_Ptr_t *     Aig_ManDfsPreorder( Aig_Man_t * p, int fNodesOnly );
+extern Vec_Vec_t *     Aig_ManLevelize( Aig_Man_t * p );
+extern Vec_Ptr_t *     Aig_ManDfsNodes( Aig_Man_t * p, Aig_Obj_t ** ppNodes, int nNodes );
+extern Vec_Ptr_t *     Aig_ManDfsChoices( Aig_Man_t * p );
+extern Vec_Ptr_t *     Aig_ManDfsReverse( Aig_Man_t * p );
+extern int             Aig_ManLevelNum( Aig_Man_t * p );
+extern int             Aig_ManChoiceLevel( Aig_Man_t * p );
+extern int             Aig_DagSize( Aig_Obj_t * pObj );
+extern int             Aig_SupportSize( Aig_Man_t * p, Aig_Obj_t * pObj );
+extern Vec_Ptr_t *     Aig_Support( Aig_Man_t * p, Aig_Obj_t * pObj );
+extern void            Aig_SupportNodes( Aig_Man_t * p, Aig_Obj_t ** ppObjs, int nObjs, Vec_Ptr_t * vSupp );
+extern void            Aig_ConeUnmark_rec( Aig_Obj_t * pObj );
+extern Aig_Obj_t *     Aig_Transfer( Aig_Man_t * pSour, Aig_Man_t * pDest, Aig_Obj_t * pObj, int nVars );
+extern Aig_Obj_t *     Aig_Compose( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Obj_t * pFunc, int iVar );
+extern void            Aig_ObjCollectCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes );
+extern int             Aig_ObjCollectSuper( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper );
+/*=== aigDup.c ==========================================================*/
+extern Aig_Obj_t *     Aig_ManDupSimpleDfs_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj );
+extern Aig_Man_t *     Aig_ManDupSimple( Aig_Man_t * p );
+extern Aig_Man_t *     Aig_ManDupSimpleWithHints( Aig_Man_t * p, Vec_Int_t * vHints );
+extern Aig_Man_t *     Aig_ManDupSimpleDfs( Aig_Man_t * p );
+extern Aig_Man_t *     Aig_ManDupSimpleDfsPart( Aig_Man_t * p, Vec_Ptr_t * vPis, Vec_Ptr_t * vCos );
+extern Aig_Man_t *     Aig_ManDupOrdered( Aig_Man_t * p );
+extern Aig_Man_t *     Aig_ManDupCof( Aig_Man_t * p, int iInput, int Value );
+extern Aig_Man_t *     Aig_ManDupTrim( Aig_Man_t * p );
+extern Aig_Man_t *     Aig_ManDupExor( Aig_Man_t * p );
+extern Aig_Man_t *     Aig_ManDupDfs( Aig_Man_t * p );
+extern Vec_Ptr_t *     Aig_ManOrderPios( Aig_Man_t * p, Aig_Man_t * pOrder );
+extern Aig_Man_t *     Aig_ManDupDfsGuided( Aig_Man_t * p, Vec_Ptr_t * vPios );
+extern Aig_Man_t *     Aig_ManDupLevelized( Aig_Man_t * p );
+extern Aig_Man_t *     Aig_ManDupWithoutPos( Aig_Man_t * p );
+extern Aig_Man_t *     Aig_ManDupFlopsOnly( Aig_Man_t * p );
+extern Aig_Man_t *     Aig_ManDupRepres( Aig_Man_t * p );
+extern Aig_Man_t *     Aig_ManDupRepresDfs( Aig_Man_t * p );
+extern Aig_Man_t *     Aig_ManCreateMiter( Aig_Man_t * p1, Aig_Man_t * p2, int fImpl );
+extern Aig_Man_t *     Aig_ManDupOrpos( Aig_Man_t * p, int fAddRegs );
+extern Aig_Man_t *     Aig_ManDupOneOutput( Aig_Man_t * p, int iPoNum, int fAddRegs );
+extern Aig_Man_t *     Aig_ManDupUnsolvedOutputs( Aig_Man_t * p, int fAddRegs );
+extern Aig_Man_t *     Aig_ManDupArray( Vec_Ptr_t * vArray );
+extern Aig_Man_t *     Aig_ManDupNodes( Aig_Man_t * pMan, Vec_Ptr_t * vArray );
+/*=== aigFanout.c ==========================================================*/
+extern void            Aig_ObjAddFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout );
+extern void            Aig_ObjRemoveFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout );
+extern void            Aig_ManFanoutStart( Aig_Man_t * p );
+extern void            Aig_ManFanoutStop( Aig_Man_t * p );
+/*=== aigFrames.c ==========================================================*/
+extern Aig_Man_t *     Aig_ManFrames( Aig_Man_t * pAig, int nFs, int fInit, int fOuts, int fRegs, int fEnlarge, Aig_Obj_t *** ppObjMap );
+/*=== aigMan.c ==========================================================*/
+extern Aig_Man_t *     Aig_ManStart( int nNodesMax );
+extern Aig_Man_t *     Aig_ManStartFrom( Aig_Man_t * p );
+extern Aig_Man_t *     Aig_ManExtractMiter( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 );
+extern void            Aig_ManStop( Aig_Man_t * p );
+extern void            Aig_ManStopP( Aig_Man_t ** p );
+extern int             Aig_ManCleanup( Aig_Man_t * p );
+extern int             Aig_ManAntiCleanup( Aig_Man_t * p );
+extern int             Aig_ManCiCleanup( Aig_Man_t * p );
+extern int             Aig_ManCoCleanup( Aig_Man_t * p );
+extern void            Aig_ManPrintStats( Aig_Man_t * p );
+extern void            Aig_ManReportImprovement( Aig_Man_t * p, Aig_Man_t * pNew );
+extern void            Aig_ManSetRegNum( Aig_Man_t * p, int nRegs );
+extern void            Aig_ManFlipFirstPo( Aig_Man_t * p );
+extern void *          Aig_ManReleaseData( Aig_Man_t * p );
+/*=== aigMem.c ==========================================================*/
+extern void            Aig_ManStartMemory( Aig_Man_t * p );
+extern void            Aig_ManStopMemory( Aig_Man_t * p );
+/*=== aigMffc.c ==========================================================*/
+extern int             Aig_NodeRef_rec( Aig_Obj_t * pNode, unsigned LevelMin );
+extern int             Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin, float * pPower, float * pProbs );
+extern int             Aig_NodeMffcSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t * vSupp );
+extern int             Aig_NodeMffcLabel( Aig_Man_t * p, Aig_Obj_t * pNode, float * pPower );
+extern int             Aig_NodeMffcLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves );
+extern int             Aig_NodeMffcExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vResult );
+/*=== aigObj.c ==========================================================*/
+extern Aig_Obj_t *     Aig_ObjCreateCi( Aig_Man_t * p );
+extern Aig_Obj_t *     Aig_ObjCreateCo( Aig_Man_t * p, Aig_Obj_t * pDriver );
+extern Aig_Obj_t *     Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost );
+extern void            Aig_ObjConnect( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFan0, Aig_Obj_t * pFan1 );
+extern void            Aig_ObjDisconnect( Aig_Man_t * p, Aig_Obj_t * pObj );
+extern void            Aig_ObjDelete( Aig_Man_t * p, Aig_Obj_t * pObj );
+extern void            Aig_ObjDelete_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int fFreeTop );
+extern void            Aig_ObjDeletePo( Aig_Man_t * p, Aig_Obj_t * pObj );
+extern void            Aig_ObjPrint( Aig_Man_t * p, Aig_Obj_t * pObj );
+extern void            Aig_ObjPatchFanin0( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFaninNew );
+extern void            Aig_ObjReplace( Aig_Man_t * p, Aig_Obj_t * pObjOld, Aig_Obj_t * pObjNew, int fUpdateLevel );
+/*=== aigOper.c =========================================================*/
+extern Aig_Obj_t *     Aig_IthVar( Aig_Man_t * p, int i );
+extern Aig_Obj_t *     Aig_Oper( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type );
+extern Aig_Obj_t *     Aig_And( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 );
+extern Aig_Obj_t *     Aig_Or( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 );
+extern Aig_Obj_t *     Aig_Exor( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 );
+extern Aig_Obj_t *     Aig_Mux( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 );
+extern Aig_Obj_t *     Aig_Maj( Aig_Man_t * p, Aig_Obj_t * pA, Aig_Obj_t * pB, Aig_Obj_t * pC );
+extern Aig_Obj_t *     Aig_Multi( Aig_Man_t * p, Aig_Obj_t ** pArgs, int nArgs, Aig_Type_t Type );
+extern Aig_Obj_t *     Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs );
+extern Aig_Obj_t *     Aig_MiterTwo( Aig_Man_t * p, Vec_Ptr_t * vNodes1, Vec_Ptr_t * vNodes2 );
+extern Aig_Obj_t *     Aig_CreateAnd( Aig_Man_t * p, int nVars );
+extern Aig_Obj_t *     Aig_CreateOr( Aig_Man_t * p, int nVars );
+extern Aig_Obj_t *     Aig_CreateExor( Aig_Man_t * p, int nVars );
+/*=== aigOrder.c =========================================================*/
+extern void            Aig_ManOrderStart( Aig_Man_t * p );
+extern void            Aig_ManOrderStop( Aig_Man_t * p );
+extern void            Aig_ObjOrderInsert( Aig_Man_t * p, int ObjId );
+extern void            Aig_ObjOrderRemove( Aig_Man_t * p, int ObjId );
+extern void            Aig_ObjOrderAdvance( Aig_Man_t * p );
+/*=== aigPart.c =========================================================*/
+extern Vec_Ptr_t *     Aig_ManSupports( Aig_Man_t * p );
+extern Vec_Ptr_t *     Aig_ManSupportsInverse( Aig_Man_t * p );
+extern Vec_Ptr_t *     Aig_ManSupportsRegisters( Aig_Man_t * p );
+extern Vec_Ptr_t *     Aig_ManPartitionSmart( Aig_Man_t * p, int nPartSizeLimit, int fVerbose, Vec_Ptr_t ** pvPartSupps );
+extern Vec_Ptr_t *     Aig_ManPartitionSmartRegisters( Aig_Man_t * pAig, int nSuppSizeLimit, int fVerbose );
+extern Vec_Ptr_t *     Aig_ManPartitionNaive( Aig_Man_t * p, int nPartSize );
+extern Vec_Ptr_t *     Aig_ManMiterPartitioned( Aig_Man_t * p1, Aig_Man_t * p2, int nPartSize, int fSmart );
+extern Aig_Man_t *     Aig_ManChoicePartitioned( Vec_Ptr_t * vAigs, int nPartSize, int nConfMax, int nLevelMax, int fVerbose );
+extern Aig_Man_t *     Aig_ManFraigPartitioned( Aig_Man_t * pAig, int nPartSize, int nConfMax, int nLevelMax, int fVerbose );
+extern Aig_Man_t *     Aig_ManChoiceConstructive( Vec_Ptr_t * vAigs, int fVerbose );
+/*=== aigPartReg.c =========================================================*/
+extern Vec_Ptr_t *     Aig_ManRegPartitionSimple( Aig_Man_t * pAig, int nPartSize, int nOverSize );
+extern void            Aig_ManPartDivide( Vec_Ptr_t * vResult, Vec_Int_t * vDomain, int nPartSize, int nOverSize );
+extern Vec_Ptr_t *     Aig_ManRegPartitionSmart( Aig_Man_t * pAig, int nPartSize );
+extern Aig_Man_t *     Aig_ManRegCreatePart( Aig_Man_t * pAig, Vec_Int_t * vPart, int * pnCountPis, int * pnCountRegs, int ** ppMapBack );
+extern Vec_Ptr_t *     Aig_ManRegProjectOnehots( Aig_Man_t * pAig, Aig_Man_t * pPart, Vec_Ptr_t * vOnehots, int fVerbose );
+/*=== aigRepr.c =========================================================*/
+extern void            Aig_ManReprStart( Aig_Man_t * p, int nIdMax );
+extern void            Aig_ManReprStop( Aig_Man_t * p );
+extern void            Aig_ObjCreateRepr( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 );
+extern void            Aig_ManTransferRepr( Aig_Man_t * pNew, Aig_Man_t * p );
+extern Aig_Man_t *     Aig_ManDupRepr( Aig_Man_t * p, int fOrdered );
+extern Aig_Man_t *     Aig_ManDupReprBasic( Aig_Man_t * p );
+extern int             Aig_ManCountReprs( Aig_Man_t * p );
+extern Aig_Man_t *     Aig_ManRehash( Aig_Man_t * p );
+extern int             Aig_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pNew, Aig_Obj_t * pOld );
+extern void            Aig_ManMarkValidChoices( Aig_Man_t * p );
+extern int             Aig_TransferMappedClasses( Aig_Man_t * pAig, Aig_Man_t * pPart, int * pMapBack );
+/*=== aigRet.c ========================================================*/
+extern Aig_Man_t *     Rtm_ManRetime( Aig_Man_t * p, int fForward, int nStepsMax, int fVerbose );
+/*=== aigRetF.c ========================================================*/
+extern Aig_Man_t *     Aig_ManRetimeFrontier( Aig_Man_t * p, int nStepsMax );
+/*=== aigScl.c ==========================================================*/
+extern Aig_Man_t *     Aig_ManRemap( Aig_Man_t * p, Vec_Ptr_t * vMap );
+extern int             Aig_ManSeqCleanup( Aig_Man_t * p );
+extern int             Aig_ManSeqCleanupBasic( Aig_Man_t * p );
+extern int             Aig_ManCountMergeRegs( Aig_Man_t * p );
+extern Aig_Man_t *     Aig_ManReduceLaches( Aig_Man_t * p, int fVerbose );
+extern void            Aig_ManComputeSccs( Aig_Man_t * p ); 
+extern Aig_Man_t *     Aig_ManScl( Aig_Man_t * pAig, int fLatchConst, int fLatchEqual, int fUseMvSweep, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose );
+/*=== aigShow.c ========================================================*/
+extern void            Aig_ManShow( Aig_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold );
+/*=== aigTable.c ========================================================*/
+extern Aig_Obj_t *     Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost );
+extern Aig_Obj_t *     Aig_TableLookupTwo( Aig_Man_t * p, Aig_Obj_t * pFanin0, Aig_Obj_t * pFanin1 );
+extern void            Aig_TableInsert( Aig_Man_t * p, Aig_Obj_t * pObj );
+extern void            Aig_TableDelete( Aig_Man_t * p, Aig_Obj_t * pObj );
+extern int             Aig_TableCountEntries( Aig_Man_t * p );
+extern void            Aig_TableProfile( Aig_Man_t * p );
+extern void            Aig_TableClear( Aig_Man_t * p );
+/*=== aigTiming.c ========================================================*/
+extern void            Aig_ObjClearReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj );
+extern int             Aig_ObjRequiredLevel( Aig_Man_t * p, Aig_Obj_t * pObj );
+extern void            Aig_ManStartReverseLevels( Aig_Man_t * p, int nMaxLevelIncrease );
+extern void            Aig_ManStopReverseLevels( Aig_Man_t * p );
+extern void            Aig_ManUpdateLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew );
+extern void            Aig_ManUpdateReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew );
+extern void            Aig_ManVerifyLevel( Aig_Man_t * p );
+extern void            Aig_ManVerifyReverseLevel( Aig_Man_t * p );
+/*=== aigTruth.c ========================================================*/
+extern unsigned *      Aig_ManCutTruth( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore );
+/*=== aigTsim.c ========================================================*/
+extern Aig_Man_t *     Aig_ManConstReduce( Aig_Man_t * p, int fUseMvSweep, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose );
+/*=== aigUtil.c =========================================================*/
+extern void            Aig_ManIncrementTravId( Aig_Man_t * p );
+extern char *          Aig_TimeStamp();
+extern int             Aig_ManHasNoGaps( Aig_Man_t * p );
+extern int             Aig_ManLevels( Aig_Man_t * p );
+extern void            Aig_ManResetRefs( Aig_Man_t * p );
+extern void            Aig_ManCleanMarkA( Aig_Man_t * p );
+extern void            Aig_ManCleanMarkB( Aig_Man_t * p );
+extern void            Aig_ManCleanMarkAB( Aig_Man_t * p );
+extern void            Aig_ManCleanData( Aig_Man_t * p );
+extern void            Aig_ObjCleanData_rec( Aig_Obj_t * pObj );
+extern void            Aig_ManCleanNext( Aig_Man_t * p );
+extern void            Aig_ObjCollectMulti( Aig_Obj_t * pFunc, Vec_Ptr_t * vSuper );
+extern int             Aig_ObjIsMuxType( Aig_Obj_t * pObj );
+extern int             Aig_ObjRecognizeExor( Aig_Obj_t * pObj, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 );
+extern Aig_Obj_t *     Aig_ObjRecognizeMux( Aig_Obj_t * pObj, Aig_Obj_t ** ppObjT, Aig_Obj_t ** ppObjE );
+extern Aig_Obj_t *     Aig_ObjReal_rec( Aig_Obj_t * pObj );
+extern int             Aig_ObjCompareIdIncrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 );
+extern void            Aig_ObjPrintEqn( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level );
+extern void            Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level );
+extern void            Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig );
+extern void            Aig_ManPrintVerbose( Aig_Man_t * p, int fHaig );
+extern void            Aig_ManDump( Aig_Man_t * p );
+extern void            Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName, Vec_Ptr_t * vPiNames, Vec_Ptr_t * vPoNames );
+extern void            Aig_ManDumpVerilog( Aig_Man_t * p, char * pFileName );
+extern void            Aig_ManSetCioIds( Aig_Man_t * p );
+extern void            Aig_ManCleanCioIds( Aig_Man_t * p );
+extern int             Aig_ManChoiceNum( Aig_Man_t * p );
+extern char *          Aig_FileNameGenericAppend( char * pBase, char * pSuffix );
+extern unsigned        Aig_ManRandom( int fReset );
+extern word            Aig_ManRandom64( int fReset );
+extern void            Aig_ManRandomInfo( Vec_Ptr_t * vInfo, int iInputStart, int iWordStart, int iWordStop );
+extern void            Aig_NodeUnionLists( Vec_Ptr_t * vArr1, Vec_Ptr_t * vArr2, Vec_Ptr_t * vArr );
+extern void            Aig_NodeIntersectLists( Vec_Ptr_t * vArr1, Vec_Ptr_t * vArr2, Vec_Ptr_t * vArr );
+extern void            Aig_ManSetPhase( Aig_Man_t * pAig );
+extern Vec_Ptr_t *     Aig_ManMuxesCollect( Aig_Man_t * pAig );
+extern void            Aig_ManMuxesDeref( Aig_Man_t * pAig, Vec_Ptr_t * vMuxes );
+extern void            Aig_ManMuxesRef( Aig_Man_t * pAig, Vec_Ptr_t * vMuxes );
+extern void            Aig_ManInvertConstraints( Aig_Man_t * pAig );
+
+/*=== aigWin.c =========================================================*/
+extern void            Aig_ManFindCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit );
+ 
+/*=== aigMem.c ===========================================================*/
+// fixed-size-block memory manager
+extern Aig_MmFixed_t * Aig_MmFixedStart( int nEntrySize, int nEntriesMax );
+extern void            Aig_MmFixedStop( Aig_MmFixed_t * p, int fVerbose );
+extern char *          Aig_MmFixedEntryFetch( Aig_MmFixed_t * p );
+extern void            Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry );
+extern void            Aig_MmFixedRestart( Aig_MmFixed_t * p );
+extern int             Aig_MmFixedReadMemUsage( Aig_MmFixed_t * p );
+extern int             Aig_MmFixedReadMaxEntriesUsed( Aig_MmFixed_t * p );
+// flexible-size-block memory manager
+extern Aig_MmFlex_t *  Aig_MmFlexStart();
+extern void            Aig_MmFlexStop( Aig_MmFlex_t * p, int fVerbose );
+extern char *          Aig_MmFlexEntryFetch( Aig_MmFlex_t * p, int nBytes );
+extern void            Aig_MmFlexRestart( Aig_MmFlex_t * p );
+extern int             Aig_MmFlexReadMemUsage( Aig_MmFlex_t * p );
+// hierarchical memory manager
+extern Aig_MmStep_t *  Aig_MmStepStart( int nSteps );
+extern void            Aig_MmStepStop( Aig_MmStep_t * p, int fVerbose );
+extern char *          Aig_MmStepEntryFetch( Aig_MmStep_t * p, int nBytes );
+extern void            Aig_MmStepEntryRecycle( Aig_MmStep_t * p, char * pEntry, int nBytes );
+extern int             Aig_MmStepReadMemUsage( Aig_MmStep_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/aig/aig/aigCanon.c b/abc-build/src/aig/aig/aigCanon.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigCanon.c
@@ -0,0 +1,701 @@
+/**CFile****************************************************************
+
+  FileName    [aigCanon.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Processing the library of semi-canonical AIGs.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigCanon.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+#include "bool/kit/kit.h"
+#include "bool/bdc/bdc.h"
+#include "aig/ioa/ioa.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define RMAN_MAXVARS  12
+#define RMAX_MAXWORD  (RMAN_MAXVARS <= 5 ? 1 : (1 << (RMAN_MAXVARS - 5)))
+
+typedef struct Aig_VSig_t_ Aig_VSig_t;
+struct Aig_VSig_t_
+{
+    int           nOnes;
+    int           nCofOnes[RMAN_MAXVARS];
+};
+
+typedef struct Aig_Tru_t_ Aig_Tru_t;
+struct Aig_Tru_t_
+{
+    Aig_Tru_t *   pNext;
+    int           Id;    
+    unsigned      nVisits : 27;
+    unsigned      nVars   :  5;
+    unsigned      pTruth[0];
+};
+
+typedef struct Aig_RMan_t_ Aig_RMan_t;
+struct Aig_RMan_t_
+{
+    int           nVars;       // the largest variable number
+    Aig_Man_t *   pAig;        // recorded subgraphs
+    // hash table
+    int           nBins;
+    Aig_Tru_t **  pBins;
+    int           nEntries;
+    Aig_MmFlex_t* pMemTrus;
+    // bidecomposion
+    Bdc_Man_t *   pBidec;
+    // temporaries
+    unsigned      pTruthInit[RMAX_MAXWORD]; // canonical truth table
+    unsigned      pTruth[RMAX_MAXWORD];     // current truth table
+    unsigned      pTruthC[RMAX_MAXWORD];    // canonical truth table
+    unsigned      pTruthTemp[RMAX_MAXWORD]; // temporary truth table
+    Aig_VSig_t    pMints[2*RMAN_MAXVARS];   // minterm count
+    char          pPerm[RMAN_MAXVARS];      // permutation
+    char          pPermR[RMAN_MAXVARS];     // reverse permutation
+    // statistics
+    int           nVarFuncs[RMAN_MAXVARS+1];
+    int           nTotal;
+    int           nTtDsd;
+    int           nTtDsdPart;
+    int           nTtDsdNot;
+    int           nUniqueVars;
+};
+
+static Aig_RMan_t * s_pRMan = NULL;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates recording manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_RMan_t * Aig_RManStart()
+{
+    static Bdc_Par_t Pars = {0}, * pPars = &Pars;
+    Aig_RMan_t * p;
+    p = ABC_ALLOC( Aig_RMan_t, 1 );
+    memset( p, 0, sizeof(Aig_RMan_t) );
+    p->nVars = RMAN_MAXVARS;
+    p->pAig  = Aig_ManStart( 1000000 );
+    Aig_IthVar( p->pAig, p->nVars-1 );
+    // create hash table
+    p->nBins = Abc_PrimeCudd(5000);
+    p->pBins = ABC_CALLOC( Aig_Tru_t *, p->nBins );
+    p->pMemTrus = Aig_MmFlexStart();
+    // bi-decomposition manager
+    pPars->nVarsMax = p->nVars;
+    pPars->fVerbose = 0;
+    p->pBidec = Bdc_ManAlloc( pPars );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the hash key.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_RManTableHash( unsigned * pTruth, int nVars, int nBins, int * pPrimes )
+{
+    int i, nWords = Kit_TruthWordNum( nVars );
+    unsigned uHash = 0;
+    for ( i = 0; i < nWords; i++ )
+        uHash ^= pTruth[i] * pPrimes[i & 0xf];
+    return (int)(uHash % nBins);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the given record.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Tru_t ** Aig_RManTableLookup( Aig_RMan_t * p, unsigned * pTruth, int nVars )
+{
+    static int s_Primes[16] = { 
+        1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, 
+        4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 };
+    Aig_Tru_t ** ppSpot, * pEntry;
+    ppSpot = p->pBins + Aig_RManTableHash( pTruth, nVars, p->nBins, s_Primes );
+    for ( pEntry = *ppSpot; pEntry; ppSpot = &pEntry->pNext, pEntry = pEntry->pNext )
+        if ( Kit_TruthIsEqual( pEntry->pTruth, pTruth, nVars ) )
+            return ppSpot;
+    return ppSpot;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find or add new entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_RManTableResize( Aig_RMan_t * p )
+{
+    Aig_Tru_t * pEntry, * pNext;
+    Aig_Tru_t ** pBinsOld, ** ppPlace;
+    int nBinsOld, Counter, i;
+    abctime clk;
+    assert( p->pBins != NULL );
+clk = Abc_Clock();
+    // save the old Bins
+    pBinsOld = p->pBins;
+    nBinsOld = p->nBins;
+    // get the new Bins
+    p->nBins = Abc_PrimeCudd( 3 * nBinsOld ); 
+    p->pBins = ABC_CALLOC( Aig_Tru_t *, p->nBins );
+    // rehash the entries from the old table
+    Counter = 0;
+    for ( i = 0; i < nBinsOld; i++ )
+    for ( pEntry = pBinsOld[i], pNext = pEntry? pEntry->pNext : NULL; 
+          pEntry; pEntry = pNext, pNext = pEntry? pEntry->pNext : NULL )
+    {
+        // get the place where this entry goes in the Bins 
+        ppPlace = Aig_RManTableLookup( p, pEntry->pTruth, pEntry->nVars );
+        assert( *ppPlace == NULL ); // should not be there
+        // add the entry to the list
+        *ppPlace = pEntry;
+        pEntry->pNext = NULL;
+        Counter++;
+    }
+    assert( Counter == p->nEntries );
+//    ABC_PRT( "Time", Abc_Clock() - clk );
+    ABC_FREE( pBinsOld );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find or add new entry.]
+
+  Description [Returns 1 if this is a new entry.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_RManTableFindOrAdd( Aig_RMan_t * p, unsigned * pTruth, int nVars )
+{
+    Aig_Tru_t ** ppSpot, * pEntry;
+    int nBytes;
+    ppSpot = Aig_RManTableLookup( p, pTruth, nVars );
+    if ( *ppSpot )
+    {
+        (*ppSpot)->nVisits++;
+        return 0;
+    }
+    nBytes = sizeof(Aig_Tru_t) + sizeof(unsigned) * Kit_TruthWordNum(nVars);
+    if ( p->nEntries == 3*p->nBins )
+        Aig_RManTableResize( p );
+    pEntry = (Aig_Tru_t *)Aig_MmFlexEntryFetch( p->pMemTrus, nBytes );
+    pEntry->Id = p->nEntries++;
+    pEntry->nVars = nVars;
+    pEntry->nVisits = 1;
+    pEntry->pNext = NULL;
+    memcpy( pEntry->pTruth, pTruth, sizeof(unsigned) * Kit_TruthWordNum(nVars) );
+    *ppSpot = pEntry;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates recording manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_RManStop( Aig_RMan_t * p )
+{
+    int i;
+    printf( "Total funcs    = %10d\n", p->nTotal );
+    printf( "Full DSD funcs = %10d\n", p->nTtDsd );
+    printf( "Part DSD funcs = %10d\n", p->nTtDsdPart );
+    printf( "Non- DSD funcs = %10d\n", p->nTtDsdNot );
+    printf( "Uniq-var funcs = %10d\n", p->nUniqueVars );
+    printf( "Unique   funcs = %10d\n", p->nEntries );
+    printf( "Distribution of functions:\n" );
+    for ( i = 5; i <= p->nVars; i++ )
+        printf( "%2d = %8d\n", i, p->nVarFuncs[i] );
+    Aig_MmFlexStop( p->pMemTrus, 0 );
+    Aig_ManStop( p->pAig );
+    Bdc_ManFree( p->pBidec );
+    ABC_FREE( p->pBins );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Stops recording.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_RManQuit()
+{
+//    extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact );
+    char Buffer[20];
+    if ( s_pRMan == NULL )
+        return;
+    // dump the library file
+    sprintf( Buffer, "aiglib%02d.aig", s_pRMan->nVars );
+    Ioa_WriteAiger( s_pRMan->pAig, Buffer, 0, 1 );
+    // quit the manager
+    Aig_RManStop( s_pRMan );
+    s_pRMan = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if all variables are unique.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_RManPrintVarProfile( unsigned * pTruth, int nVars,  unsigned * pTruthAux )
+{
+    int pStore2[32];
+    int i;
+    Kit_TruthCountOnesInCofsSlow( pTruth, nVars, pStore2, pTruthAux );
+    for ( i = 0; i < nVars; i++ )
+        printf( "%2d/%2d ", pStore2[2*i], pStore2[2*i+1] );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts numbers in the increasing order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_RManSortNums( int * pArray, int nVars )
+{
+    int i, j, best_i, tmp;
+    for ( i = 0; i < nVars-1; i++ )
+    {
+        best_i = i;
+        for ( j = i+1; j < nVars; j++ )
+            if ( pArray[j] > pArray[best_i] )
+                best_i = j;
+        tmp = pArray[i]; pArray[i] = pArray[best_i]; pArray[best_i] = tmp;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints signatures for all variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_RManPrintSigs( Aig_VSig_t * pSigs, int nVars )
+{
+    int v, i, k;
+    for ( v = 0; v < nVars; v++ )
+    {
+        printf( "%2d : ", v );
+        for ( k = 0; k < 2; k++ )
+        {
+            printf( "%5d  ", pSigs[2*v+k].nOnes );
+            printf( "(" );
+            for ( i = 0; i < nVars; i++ )
+                printf( "%4d ", pSigs[2*v+k].nCofOnes[i] );
+            printf( ")  " );
+        }
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes signatures for all variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_RManComputeVSigs( unsigned * pTruth, int nVars, Aig_VSig_t * pSigs, unsigned * pAux )
+{
+    int v;
+    for ( v = 0; v < nVars; v++ )
+    {
+        Kit_TruthCofactor0New( pAux, pTruth, nVars, v );
+        pSigs[2*v+0].nOnes = Kit_TruthCountOnes( pAux, nVars );
+        Kit_TruthCountOnesInCofs0( pAux, nVars, pSigs[2*v+0].nCofOnes );
+        Aig_RManSortNums( pSigs[2*v+0].nCofOnes, nVars );
+
+        Kit_TruthCofactor1New( pAux, pTruth, nVars, v );
+        pSigs[2*v+1].nOnes = Kit_TruthCountOnes( pAux, nVars );
+        Kit_TruthCountOnesInCofs0( pAux, nVars, pSigs[2*v+1].nCofOnes );
+        Aig_RManSortNums( pSigs[2*v+1].nCofOnes, nVars );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computs signatures for all variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_RManCompareSigs( Aig_VSig_t * p0, Aig_VSig_t * p1, int nVars )
+{
+//    return memcmp( p0, p1, sizeof(int) + sizeof(int) * nVars );
+    return memcmp( p0, p1, sizeof(int) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if all variables are unique.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_RManVarsAreUnique( Aig_VSig_t * pMints, int nVars )
+{
+    int i;
+    for ( i = 0; i < nVars - 1; i++ )
+        if ( Aig_RManCompareSigs( &pMints[2*i], &pMints[2*(i+1)], nVars ) == 0 )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if all variables are unique.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_RManPrintUniqueVars( Aig_VSig_t * pMints, int nVars )
+{
+    int i;
+    for ( i = 0; i < nVars; i++ )
+        if ( Aig_RManCompareSigs( &pMints[2*i], &pMints[2*i+1], nVars ) == 0 )
+            printf( "=" );
+        else 
+            printf( "x" );
+    printf( "\n" );
+
+    printf( "0" );
+    for ( i = 1; i < nVars; i++ )
+        if ( Aig_RManCompareSigs( &pMints[2*(i-1)], &pMints[2*i], nVars ) == 0 )
+            printf( "-" );
+        else if ( i < 10 )
+            printf( "%c", '0' + i );
+        else 
+            printf( "%c", 'A' + i-10 );
+    printf( "\n" );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Canonicize the truth table.]
+
+  Description [Returns the phase. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Aig_RManSemiCanonicize( unsigned * pOut, unsigned * pIn, int nVars, char * pCanonPerm, Aig_VSig_t * pSigs, int fReturnIn )
+{
+    Aig_VSig_t TempSig;
+    int i, Temp, fChange, Counter;
+    unsigned * pTemp, uCanonPhase = 0;
+    // collect signatures 
+    Aig_RManComputeVSigs( pIn, nVars, pSigs, pOut );
+    // canonicize phase
+    for ( i = 0; i < nVars; i++ )
+    {
+//        if ( pStore[2*i+0] <= pStore[2*i+1] )
+        if ( Aig_RManCompareSigs( &pSigs[2*i+0], &pSigs[2*i+1], nVars ) <= 0 )
+            continue;
+        uCanonPhase |= (1 << i);
+        TempSig = pSigs[2*i+0];
+        pSigs[2*i+0] = pSigs[2*i+1];
+        pSigs[2*i+1] = TempSig;
+        Kit_TruthChangePhase( pIn, nVars, i );
+    }
+    // permute
+    Counter = 0;
+    do {
+        fChange = 0;
+        for ( i = 0; i < nVars-1; i++ )
+        {
+//            if ( pStore[2*i] <= pStore[2*(i+1)] )
+            if ( Aig_RManCompareSigs( &pSigs[2*i], &pSigs[2*(i+1)], nVars ) <= 0 )
+                continue;
+            Counter++;
+            fChange = 1;
+
+            Temp = pCanonPerm[i];
+            pCanonPerm[i] = pCanonPerm[i+1];
+            pCanonPerm[i+1] = Temp;
+
+            TempSig = pSigs[2*i];
+            pSigs[2*i] = pSigs[2*(i+1)];
+            pSigs[2*(i+1)] = TempSig;
+
+            TempSig = pSigs[2*i+1];
+            pSigs[2*i+1] = pSigs[2*(i+1)+1];
+            pSigs[2*(i+1)+1] = TempSig;
+
+            Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i );
+            pTemp = pIn; pIn = pOut; pOut = pTemp;
+        }
+    } while ( fChange );
+
+    // swap if it was moved an even number of times
+    if ( fReturnIn ^ !(Counter & 1) )
+        Kit_TruthCopy( pOut, pIn, nVars );
+    return uCanonPhase;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Aig_Obj_t * Bdc_FunCopyHop( Bdc_Fun_t * pObj )  
+{ return Aig_NotCond( (Aig_Obj_t *)Bdc_FuncCopy(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) );  }
+
+/**Function*************************************************************
+
+  Synopsis    [Records one function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_RManSaveOne( Aig_RMan_t * p, unsigned * pTruth, int nVars )
+{
+    int i, nNodes, RetValue;
+    Bdc_Fun_t * pFunc;
+    Aig_Obj_t * pTerm;
+    // perform decomposition
+    RetValue = Bdc_ManDecompose( p->pBidec, pTruth, NULL, nVars, NULL, 1000 );
+    if ( RetValue < 0 )
+    {
+        printf( "Decomposition failed.\n" );
+        return;
+    }
+    // convert back into HOP
+    Bdc_FuncSetCopy( Bdc_ManFunc( p->pBidec, 0 ), Aig_ManConst1(p->pAig) );
+    for ( i = 0; i < nVars; i++ )
+        Bdc_FuncSetCopy( Bdc_ManFunc( p->pBidec, i+1 ), Aig_IthVar(p->pAig, i) );
+    nNodes = Bdc_ManNodeNum(p->pBidec);
+    for ( i = nVars + 1; i < nNodes; i++ )
+    {
+        pFunc = Bdc_ManFunc( p->pBidec, i );
+        Bdc_FuncSetCopy( pFunc, Aig_And( p->pAig, 
+            Bdc_FunCopyHop(Bdc_FuncFanin0(pFunc)), 
+            Bdc_FunCopyHop(Bdc_FuncFanin1(pFunc)) ) );
+    }
+    pTerm = Bdc_FunCopyHop( Bdc_ManRoot(p->pBidec) );
+    pTerm = Aig_ObjCreateCo( p->pAig, pTerm );
+//    assert( pTerm->fPhase == 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records one function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_RManRecord( unsigned * pTruth, int nVarsInit )
+{
+    int fVerify = 1;
+    Kit_DsdNtk_t * pNtk;
+    Kit_DsdObj_t * pObj;
+    unsigned uPhaseC;
+    int i, nVars, nWords;
+    int fUniqueVars;
+
+    if ( nVarsInit > RMAN_MAXVARS )
+    {
+        printf( "The number of variables in too large.\n" );
+        return;
+    }
+
+    if ( s_pRMan == NULL )
+        s_pRMan = Aig_RManStart();
+    s_pRMan->nTotal++;
+    // canonicize the function
+    pNtk = Kit_DsdDecompose( pTruth, nVarsInit );
+    pObj = Kit_DsdNonDsdPrimeMax( pNtk );
+    if ( pObj == NULL || pObj->nFans == 3 )
+    {
+        s_pRMan->nTtDsd++;
+        Kit_DsdNtkFree( pNtk );
+        return;
+    }
+    nVars = pObj->nFans;
+    s_pRMan->nVarFuncs[nVars]++;
+    if ( nVars < nVarsInit )
+        s_pRMan->nTtDsdPart++;
+    else
+        s_pRMan->nTtDsdNot++;
+    // compute the number of words
+    nWords = Abc_TruthWordNum( nVars );
+    // copy the function
+    memcpy( s_pRMan->pTruthInit, Kit_DsdObjTruth(pObj), 4*nWords );
+    Kit_DsdNtkFree( pNtk );
+    // canonicize the output
+    if ( s_pRMan->pTruthInit[0] & 1 )
+        Kit_TruthNot( s_pRMan->pTruthInit, s_pRMan->pTruthInit, nVars );
+    memcpy( s_pRMan->pTruth, s_pRMan->pTruthInit, 4*nWords );
+
+    // canonize the function
+    for ( i = 0; i < nVars; i++ )
+        s_pRMan->pPerm[i] = i;
+    uPhaseC = Aig_RManSemiCanonicize( s_pRMan->pTruthTemp, s_pRMan->pTruth, nVars, s_pRMan->pPerm, s_pRMan->pMints, 1 );
+    // check unique variables
+    fUniqueVars = Aig_RManVarsAreUnique( s_pRMan->pMints, nVars );
+    s_pRMan->nUniqueVars += fUniqueVars;
+
+/*
+    printf( "%4d : ", s_pRMan->nTotal );
+    printf( "%2d %2d  ", nVarsInit, nVars );
+    Extra_PrintBinary( stdout, &uPhaseC, nVars );
+    printf( "  " );
+    for ( i = 0; i < nVars; i++ )
+        printf( "%2d/%2d ", s_pRMan->pMints[2*i], s_pRMan->pMints[2*i+1] );
+    printf( "\n" );
+    Aig_RManPrintUniqueVars( s_pRMan->pMints, nVars );
+Extra_PrintBinary( stdout, s_pRMan->pTruth, 1<<nVars ); printf( "\n\n" );
+*/
+/*
+    printf( "\n" );
+    printf( "%4d : ", s_pRMan->nTotal );
+    printf( "%2d %2d  ", nVarsInit, nVars );
+    printf( "   " );
+    printf( "\n" );
+    Aig_RManPrintUniqueVars( s_pRMan->pMints, nVars );
+//    Aig_RManPrintSigs( s_pRMan->pMints, nVars );
+*/
+
+//Extra_PrintBinary( stdout, s_pRMan->pTruth, 1<<nVars ); printf( "\n\n" );
+
+    if ( Aig_RManTableFindOrAdd( s_pRMan, s_pRMan->pTruth, nVars ) )
+        Aig_RManSaveOne( s_pRMan, s_pRMan->pTruth, nVars );
+
+    if ( fVerify )
+    {
+        // derive reverse permutation
+        for ( i = 0; i < nVars; i++ )
+            s_pRMan->pPermR[i] = s_pRMan->pPerm[i];
+        // implement permutation
+        Kit_TruthPermute( s_pRMan->pTruthTemp, s_pRMan->pTruth, nVars, s_pRMan->pPermR, 1 );
+        // implement polarity
+        for ( i = 0; i < nVars; i++ )
+            if ( uPhaseC & (1 << i) )
+                Kit_TruthChangePhase( s_pRMan->pTruth, nVars, i );
+
+        // perform verification
+        if ( fUniqueVars && !Kit_TruthIsEqual( s_pRMan->pTruth, s_pRMan->pTruthInit, nVars ) )
+            printf( "Verification failed.\n" );
+    }
+//Aig_RManPrintVarProfile( s_pRMan->pTruth, nVars, s_pRMan->pTruthTemp );
+//Extra_PrintBinary( stdout, s_pRMan->pTruth, 1<<nVars ); printf( "\n" );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigCheck.c b/abc-build/src/aig/aig/aigCheck.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigCheck.c
@@ -0,0 +1,168 @@
+/**CFile****************************************************************
+ 
+  FileName    [aigCheck.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [AIG checking procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigCheck.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the consistency of the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManCheck( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pObj2;
+    int i;
+    // check primary inputs
+    Aig_ManForEachCi( p, pObj, i )
+    {
+        if ( Aig_ObjFanin0(pObj) || Aig_ObjFanin1(pObj) )
+        {
+            printf( "Aig_ManCheck: The PI node \"%p\" has fanins.\n", pObj );
+            return 0;
+        }
+    }
+    // check primary outputs
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        if ( !Aig_ObjFanin0(pObj) )
+        {
+            printf( "Aig_ManCheck: The PO node \"%p\" has NULL fanin.\n", pObj );
+            return 0;
+        }
+        if ( Aig_ObjFanin1(pObj) )
+        {
+            printf( "Aig_ManCheck: The PO node \"%p\" has second fanin.\n", pObj );
+            return 0;
+        }
+    }
+    // check internal nodes
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( !Aig_ObjIsNode(pObj) )
+            continue;
+        if ( !Aig_ObjFanin0(pObj) || !Aig_ObjFanin1(pObj) )
+        {
+            printf( "Aig_ManCheck: The AIG has internal node \"%p\" with a NULL fanin.\n", pObj );
+            return 0;
+        }
+        if ( Aig_ObjFanin0(pObj)->Id >= Aig_ObjFanin1(pObj)->Id )
+        {
+            printf( "Aig_ManCheck: The AIG has node \"%p\" with a wrong ordering of fanins.\n", pObj );
+            return 0;
+        }
+        pObj2 = Aig_TableLookup( p, pObj );
+        if ( pObj2 != pObj )
+        {
+            printf( "Aig_ManCheck: Node \"%p\" is not in the structural hashing table.\n", pObj );
+            return 0;
+        }
+    }
+    // count the total number of nodes
+    if ( Aig_ManObjNum(p) != 1 + Aig_ManCiNum(p) + Aig_ManCoNum(p) + 
+        Aig_ManBufNum(p) + Aig_ManAndNum(p) + Aig_ManExorNum(p) )
+    {
+        printf( "Aig_ManCheck: The number of created nodes is wrong.\n" );
+        printf( "C1 = %d. Pi = %d. Po = %d. Buf = %d. And = %d. Xor = %d. Total = %d.\n",
+            1, Aig_ManCiNum(p), Aig_ManCoNum(p), Aig_ManBufNum(p), Aig_ManAndNum(p), Aig_ManExorNum(p), 
+            1 + Aig_ManCiNum(p) + Aig_ManCoNum(p) + Aig_ManBufNum(p) + Aig_ManAndNum(p) + Aig_ManExorNum(p) );
+        printf( "Created = %d. Deleted = %d. Existing = %d.\n",
+            Aig_ManObjNumMax(p), p->nDeleted, Aig_ManObjNum(p) );
+        return 0;
+    }
+    // count the number of nodes in the table
+    if ( Aig_TableCountEntries(p) != Aig_ManAndNum(p) + Aig_ManExorNum(p) )
+    {
+        printf( "Aig_ManCheck: The number of nodes in the structural hashing table is wrong.\n" );
+        printf( "Entries = %d. And = %d. Xor = %d. Total = %d.\n", 
+            Aig_TableCountEntries(p), Aig_ManAndNum(p), Aig_ManExorNum(p), 
+            Aig_ManAndNum(p) + Aig_ManExorNum(p) );
+
+        return 0;
+    }
+//    if ( !Aig_ManIsAcyclic(p) )
+//        return 0;
+    return 1; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the markA is reset.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManCheckMarkA( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachObj( p, pObj, i )
+        assert( pObj->fMarkA == 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the consistency of phase assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManCheckPhase( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachObj( p, pObj, i )
+        if ( Aig_ObjIsCi(pObj) )
+            assert( (int)pObj->fPhase == 0 );
+        else
+            assert( (int)pObj->fPhase == (Aig_ObjPhaseReal(Aig_ObjChild0(pObj)) & Aig_ObjPhaseReal(Aig_ObjChild1(pObj))) );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigCuts.c b/abc-build/src/aig/aig/aigCuts.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigCuts.c
@@ -0,0 +1,673 @@
+/**CFile****************************************************************
+
+  FileName    [aigCuts.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Computation of K-feasible priority cuts.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigCuts.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the cut sweeping manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_ManCut_t * Aig_ManCutStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, int fTruth, int fVerbose )
+{
+    Aig_ManCut_t * p;
+    assert( nCutsMax >= 2  );
+    assert( nLeafMax <= 16 );
+    // allocate the fraiging manager
+    p = ABC_ALLOC( Aig_ManCut_t, 1 );
+    memset( p, 0, sizeof(Aig_ManCut_t) );
+    p->nCutsMax = nCutsMax;
+    p->nLeafMax = nLeafMax;
+    p->fTruth   = fTruth;
+    p->fVerbose = fVerbose;
+    p->pAig     = pMan;
+    p->pCuts    = ABC_CALLOC( Aig_Cut_t *, Aig_ManObjNumMax(pMan) );
+    // allocate memory manager
+    p->nTruthWords = Abc_TruthWordNum(nLeafMax);
+    p->nCutSize = sizeof(Aig_Cut_t) + sizeof(int) * nLeafMax + fTruth * sizeof(unsigned) * p->nTruthWords;
+    p->pMemCuts = Aig_MmFixedStart( p->nCutSize * p->nCutsMax, 512 );
+    // room for temporary truth tables
+    if ( fTruth )
+    {
+        p->puTemp[0] = ABC_ALLOC( unsigned, 4 * p->nTruthWords );
+        p->puTemp[1] = p->puTemp[0] + p->nTruthWords;
+        p->puTemp[2] = p->puTemp[1] + p->nTruthWords;
+        p->puTemp[3] = p->puTemp[2] + p->nTruthWords;
+    }
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the fraiging manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManCutStop( Aig_ManCut_t * p )
+{
+    Aig_MmFixedStop( p->pMemCuts, 0 );
+    ABC_FREE( p->puTemp[0] );
+    ABC_FREE( p->pCuts );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints one cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_CutPrint( Aig_Cut_t * pCut )
+{
+    int i;
+    printf( "{" );
+    for ( i = 0; i < pCut->nFanins; i++ )
+        printf( " %d", pCut->pFanins[i] );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints one cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjCutPrint( Aig_ManCut_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Cut_t * pCut;
+    int i;
+    printf( "Cuts for node %d:\n", pObj->Id );
+    Aig_ObjForEachCut( p, pObj, pCut, i )
+        if ( pCut->nFanins )
+            Aig_CutPrint( pCut );
+//    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the total number of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManCutCount( Aig_ManCut_t * p, int * pnCutsK )
+{
+    Aig_Cut_t * pCut;
+    Aig_Obj_t * pObj;
+    int i, k, nCuts = 0, nCutsK = 0;
+    Aig_ManForEachNode( p->pAig, pObj, i )
+        Aig_ObjForEachCut( p, pObj, pCut, k )
+        {
+            if ( pCut->nFanins == 0 )
+                continue;
+            nCuts++;
+            if ( pCut->nFanins == p->nLeafMax )
+                nCutsK++;
+        }
+    if ( pnCutsK )
+        *pnCutsK = nCutsK;
+    return nCuts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the cost of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_CutFindCost( Aig_ManCut_t * p, Aig_Cut_t * pCut )
+{
+    Aig_Obj_t * pLeaf;
+    int i, Cost = 0;
+    assert( pCut->nFanins > 0 );
+    Aig_CutForEachLeaf( p->pAig, pCut, pLeaf, i )
+        Cost += pLeaf->nRefs;
+    return Cost * 1000 / pCut->nFanins;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the cost of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline float Aig_CutFindCost2( Aig_ManCut_t * p, Aig_Cut_t * pCut )
+{
+    Aig_Obj_t * pLeaf;
+    float Cost = 0.0;
+    int i;
+    assert( pCut->nFanins > 0 );
+    Aig_CutForEachLeaf( p->pAig, pCut, pLeaf, i )
+        Cost += (float)1.0/pLeaf->nRefs;
+    return 1/Cost;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the next free cut to use.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Aig_Cut_t * Aig_CutFindFree( Aig_ManCut_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Cut_t * pCut, * pCutMax;
+    int i;
+    pCutMax = NULL;
+    Aig_ObjForEachCut( p, pObj, pCut, i )
+    {
+        if ( pCut->nFanins == 0 )
+            return pCut;
+        if ( pCutMax == NULL || pCutMax->Cost < pCut->Cost )
+            pCutMax = pCut;
+    }
+    assert( pCutMax != NULL );
+    pCutMax->nFanins = 0;
+    return pCutMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the stretching phase of the cut w.r.t. the merged cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Aig_CutTruthPhase( Aig_Cut_t * pCut, Aig_Cut_t * pCut1 )
+{
+    unsigned uPhase = 0;
+    int i, k;
+    for ( i = k = 0; i < pCut->nFanins; i++ )
+    {
+        if ( k == pCut1->nFanins )
+            break;
+        if ( pCut->pFanins[i] < pCut1->pFanins[k] )
+            continue;
+        assert( pCut->pFanins[i] == pCut1->pFanins[k] );
+        uPhase |= (1 << i);
+        k++;
+    }
+    return uPhase;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs truth table computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Aig_CutComputeTruth( Aig_ManCut_t * p, Aig_Cut_t * pCut, Aig_Cut_t * pCut0, Aig_Cut_t * pCut1, int fCompl0, int fCompl1 )
+{
+    // permute the first table
+    if ( fCompl0 ) 
+        Kit_TruthNot( p->puTemp[0], Aig_CutTruth(pCut0), p->nLeafMax );
+    else
+        Kit_TruthCopy( p->puTemp[0], Aig_CutTruth(pCut0), p->nLeafMax );
+    Kit_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nFanins, p->nLeafMax, Aig_CutTruthPhase(pCut, pCut0), 0 );
+    // permute the second table
+    if ( fCompl1 ) 
+        Kit_TruthNot( p->puTemp[1], Aig_CutTruth(pCut1), p->nLeafMax );
+    else
+        Kit_TruthCopy( p->puTemp[1], Aig_CutTruth(pCut1), p->nLeafMax );
+    Kit_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nFanins, p->nLeafMax, Aig_CutTruthPhase(pCut, pCut1), 0 );
+    // produce the resulting table
+    Kit_TruthAnd( Aig_CutTruth(pCut), p->puTemp[2], p->puTemp[3], p->nLeafMax );
+//    assert( pCut->nFanins >= Kit_TruthSupportSize( Aig_CutTruth(pCut), p->nLeafMax ) );
+    return Aig_CutTruth(pCut);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs support minimization for the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_CutSupportMinimize( Aig_ManCut_t * p, Aig_Cut_t * pCut )
+{
+    unsigned * pTruth;
+    int uSupp, nFansNew, i, k;
+    // get truth table
+    pTruth = Aig_CutTruth( pCut );
+    // get support 
+    uSupp = Kit_TruthSupport( pTruth, p->nLeafMax );
+    // get the new support size
+    nFansNew = Kit_WordCountOnes( uSupp );
+    // check if there are redundant variables
+    if ( nFansNew == pCut->nFanins )
+        return nFansNew;
+    assert( nFansNew < pCut->nFanins );
+    // minimize support
+    Kit_TruthShrink( p->puTemp[0], pTruth, nFansNew, p->nLeafMax, uSupp, 1 );
+    for ( i = k = 0; i < pCut->nFanins; i++ )
+        if ( uSupp & (1 << i) )
+            pCut->pFanins[k++] = pCut->pFanins[i];
+    assert( k == nFansNew );
+    pCut->nFanins = nFansNew;
+//    assert( nFansNew == Kit_TruthSupportSize( pTruth, p->nLeafMax ) );
+//Extra_PrintBinary( stdout, pTruth, (1<<p->nLeafMax) ); printf( "\n" );
+    return nFansNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pDom is contained in pCut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_CutCheckDominance( Aig_Cut_t * pDom, Aig_Cut_t * pCut )
+{
+    int i, k;
+    for ( i = 0; i < (int)pDom->nFanins; i++ )
+    {
+        for ( k = 0; k < (int)pCut->nFanins; k++ )
+            if ( pDom->pFanins[i] == pCut->pFanins[k] )
+                break;
+        if ( k == (int)pCut->nFanins ) // node i in pDom is not contained in pCut
+            return 0;
+    }
+    // every node in pDom is contained in pCut
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the cut is contained.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_CutFilter( Aig_ManCut_t * p, Aig_Obj_t * pObj, Aig_Cut_t * pCut )
+{ 
+    Aig_Cut_t * pTemp;
+    int i;
+    // go through the cuts of the node
+    Aig_ObjForEachCut( p, pObj, pTemp, i )
+    {
+        if ( pTemp->nFanins < 2 )
+            continue;
+        if ( pTemp == pCut )
+            continue;
+        if ( pTemp->nFanins > pCut->nFanins )
+        {
+            // skip the non-contained cuts
+            if ( (pTemp->uSign & pCut->uSign) != pCut->uSign )
+                continue;
+            // check containment seriously
+            if ( Aig_CutCheckDominance( pCut, pTemp ) )
+            {
+                // remove contained cut
+                pTemp->nFanins = 0;
+            }
+         }
+        else
+        {
+            // skip the non-contained cuts
+            if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign )
+                continue;
+            // check containment seriously
+            if ( Aig_CutCheckDominance( pTemp, pCut ) )
+            {
+                // remove the given
+                pCut->nFanins = 0;
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_CutMergeOrdered( Aig_ManCut_t * p, Aig_Cut_t * pC0, Aig_Cut_t * pC1, Aig_Cut_t * pC )
+{ 
+    int i, k, c;
+    assert( pC0->nFanins >= pC1->nFanins );
+    // the case of the largest cut sizes
+    if ( pC0->nFanins == p->nLeafMax && pC1->nFanins == p->nLeafMax )
+    {
+        for ( i = 0; i < pC0->nFanins; i++ )
+            if ( pC0->pFanins[i] != pC1->pFanins[i] )
+                return 0;
+        for ( i = 0; i < pC0->nFanins; i++ )
+            pC->pFanins[i] = pC0->pFanins[i];
+        pC->nFanins = pC0->nFanins;
+        return 1;
+    }
+    // the case when one of the cuts is the largest
+    if ( pC0->nFanins == p->nLeafMax )
+    {
+        for ( i = 0; i < pC1->nFanins; i++ )
+        {
+            for ( k = pC0->nFanins - 1; k >= 0; k-- )
+                if ( pC0->pFanins[k] == pC1->pFanins[i] )
+                    break;
+            if ( k == -1 ) // did not find
+                return 0;
+        }
+        for ( i = 0; i < pC0->nFanins; i++ )
+            pC->pFanins[i] = pC0->pFanins[i];
+        pC->nFanins = pC0->nFanins;
+        return 1;
+    }
+
+    // compare two cuts with different numbers
+    i = k = 0;
+    for ( c = 0; c < p->nLeafMax; c++ )
+    {
+        if ( k == pC1->nFanins )
+        {
+            if ( i == pC0->nFanins )
+            {
+                pC->nFanins = c;
+                return 1;
+            }
+            pC->pFanins[c] = pC0->pFanins[i++];
+            continue;
+        }
+        if ( i == pC0->nFanins )
+        {
+            if ( k == pC1->nFanins )
+            {
+                pC->nFanins = c;
+                return 1;
+            }
+            pC->pFanins[c] = pC1->pFanins[k++];
+            continue;
+        }
+        if ( pC0->pFanins[i] < pC1->pFanins[k] )
+        {
+            pC->pFanins[c] = pC0->pFanins[i++];
+            continue;
+        }
+        if ( pC0->pFanins[i] > pC1->pFanins[k] )
+        {
+            pC->pFanins[c] = pC1->pFanins[k++];
+            continue;
+        }
+        pC->pFanins[c] = pC0->pFanins[i++]; 
+        k++;
+    }
+    if ( i < pC0->nFanins || k < pC1->nFanins )
+        return 0;
+    pC->nFanins = c;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the object for FPGA mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_CutMerge( Aig_ManCut_t * p, Aig_Cut_t * pCut0, Aig_Cut_t * pCut1, Aig_Cut_t * pCut )
+{ 
+    assert( p->nLeafMax > 0 );
+    // merge the nodes
+    if ( pCut0->nFanins < pCut1->nFanins )
+    {
+        if ( !Aig_CutMergeOrdered( p, pCut1, pCut0, pCut ) )
+            return 0;
+    }
+    else
+    {
+        if ( !Aig_CutMergeOrdered( p, pCut0, pCut1, pCut ) )
+            return 0;
+    }
+    pCut->uSign = pCut0->uSign | pCut1->uSign;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Cut_t * Aig_ObjPrepareCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj, int fTriv )
+{
+    Aig_Cut_t * pCutSet, * pCut;
+    int i;
+    // create the cutset of the node
+    pCutSet = (Aig_Cut_t *)Aig_MmFixedEntryFetch( p->pMemCuts );
+    Aig_ObjSetCuts( p, pObj, pCutSet );
+    Aig_ObjForEachCut( p, pObj, pCut, i )
+    {
+        pCut->nFanins  = 0;
+        pCut->iNode    = pObj->Id;
+        pCut->nCutSize = p->nCutSize;
+        pCut->nLeafMax = p->nLeafMax;
+    }
+    // add unit cut if needed
+    if ( fTriv )
+    {
+        pCut = pCutSet;
+        pCut->Cost = 0;
+        pCut->iNode = pObj->Id;
+        pCut->nFanins = 1;
+        pCut->pFanins[0] = pObj->Id;
+        pCut->uSign = Aig_ObjCutSign( pObj->Id );
+        if ( p->fTruth )
+        memset( Aig_CutTruth(pCut), 0xAA, sizeof(unsigned) * p->nTruthWords );
+    }
+    return pCutSet;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives cuts for one node and sweeps this node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjComputeCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj, int fTriv )
+{
+    Aig_Cut_t * pCut0, * pCut1, * pCut, * pCutSet;
+    Aig_Obj_t * pFanin0 = Aig_ObjFanin0(pObj);
+    Aig_Obj_t * pFanin1 = Aig_ObjFanin1(pObj);
+    int i, k;
+    // the node is not processed yet
+    assert( Aig_ObjIsNode(pObj) );
+    assert( Aig_ObjCuts(p, pObj) == NULL );
+    // set up the first cut
+    pCutSet = Aig_ObjPrepareCuts( p, pObj, fTriv );
+    // compute pair-wise cut combinations while checking table
+    Aig_ObjForEachCut( p, pFanin0, pCut0, i )
+    if ( pCut0->nFanins > 0 )
+    Aig_ObjForEachCut( p, pFanin1, pCut1, k )
+    if ( pCut1->nFanins > 0 )
+    {
+        // make sure K-feasible cut exists
+        if ( Kit_WordCountOnes(pCut0->uSign | pCut1->uSign) > p->nLeafMax )
+            continue;
+        // get the next cut of this node
+        pCut = Aig_CutFindFree( p, pObj );
+        // assemble the new cut
+        if ( !Aig_CutMerge( p, pCut0, pCut1, pCut ) )
+        {
+            assert( pCut->nFanins == 0 );
+            continue;
+        }
+        // check containment
+        if ( Aig_CutFilter( p, pObj, pCut ) )
+        {
+            assert( pCut->nFanins == 0 );
+            continue;
+        }
+        // create its truth table
+        if ( p->fTruth )
+            Aig_CutComputeTruth( p, pCut, pCut0, pCut1, Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) );
+        // assign the cost
+        pCut->Cost = Aig_CutFindCost( p, pCut );
+        assert( pCut->nFanins > 0 );
+        assert( pCut->Cost > 0 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for all nodes in the static AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_ManCut_t * Aig_ComputeCuts( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fTruth, int fVerbose )
+{
+    Aig_ManCut_t * p;
+    Aig_Obj_t * pObj;
+    int i;
+    abctime clk = Abc_Clock();
+    assert( pAig->pManCuts == NULL );
+    // start the manager
+    p = Aig_ManCutStart( pAig, nCutsMax, nLeafMax, fTruth, fVerbose );
+    // set elementary cuts at the PIs
+    Aig_ManForEachCi( pAig, pObj, i )
+        Aig_ObjPrepareCuts( p, pObj, 1 );
+    // process the nodes
+    Aig_ManForEachNode( pAig, pObj, i )
+        Aig_ObjComputeCuts( p, pObj, 1 );
+    // print stats
+    if ( fVerbose )
+    {
+        int nCuts, nCutsK;
+        nCuts = Aig_ManCutCount( p, &nCutsK );
+        printf( "Nodes = %6d. Total cuts = %6d. %d-input cuts = %6d.\n",
+            Aig_ManObjNum(pAig), nCuts, nLeafMax, nCutsK );
+        printf( "Cut size = %2d. Truth size = %2d. Total mem = %5.2f MB  ",
+            p->nCutSize, 4*p->nTruthWords, 1.0*Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) );
+        ABC_PRT( "Runtime", Abc_Clock() - clk );
+/*
+        Aig_ManForEachNode( pAig, pObj, i )
+            if ( i % 300 == 0 )
+                Aig_ObjCutPrint( p, pObj );
+*/
+    }
+    // remember the cut manager
+    pAig->pManCuts = p;
+    return p;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigDfs.c b/abc-build/src/aig/aig/aigDfs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigDfs.c
@@ -0,0 +1,1122 @@
+/**CFile****************************************************************
+
+  FileName    [aigDfs.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [DFS traversal procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigDfs.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+#include "misc/tim/tim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies that the objects are in a topo order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManVerifyTopoOrder( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pNext;
+    int i, k, iBox, iTerm1, nTerms;
+    Aig_ManSetCioIds( p );
+    Aig_ManIncrementTravId( p );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( Aig_ObjIsNode(pObj) )
+        {
+            pNext = Aig_ObjFanin0(pObj);
+            if ( !Aig_ObjIsTravIdCurrent(p,pNext) )
+            {
+                printf( "Node %d has fanin %d that is not in a topological order.\n", pObj->Id, pNext->Id );
+                return 0;
+            }
+            pNext = Aig_ObjFanin1(pObj);
+            if ( !Aig_ObjIsTravIdCurrent(p,pNext) )
+            {
+                printf( "Node %d has fanin %d that is not in a topological order.\n", pObj->Id, pNext->Id );
+                return 0;
+            }
+        }
+        else if ( Aig_ObjIsCo(pObj) || Aig_ObjIsBuf(pObj) )
+        {
+            pNext = Aig_ObjFanin0(pObj);
+            if ( !Aig_ObjIsTravIdCurrent(p,pNext) )
+            {
+                printf( "Node %d has fanin %d that is not in a topological order.\n", pObj->Id, pNext->Id );
+                return 0;
+            }
+        }
+        else if ( Aig_ObjIsCi(pObj) )
+        {
+            if ( p->pManTime )
+            {
+                iBox = Tim_ManBoxForCi( (Tim_Man_t *)p->pManTime, Aig_ObjCioId(pObj) );
+                if ( iBox >= 0 ) // this is not a true PI
+                {
+                    iTerm1 = Tim_ManBoxInputFirst( (Tim_Man_t *)p->pManTime, iBox );
+                    nTerms = Tim_ManBoxInputNum( (Tim_Man_t *)p->pManTime, iBox );
+                    for ( k = 0; k < nTerms; k++ )
+                    {
+                        pNext = Aig_ManCo( p, iTerm1 + k );
+                        assert( Tim_ManBoxForCo( (Tim_Man_t *)p->pManTime, Aig_ObjCioId(pNext) ) == iBox ); 
+                        if ( !Aig_ObjIsTravIdCurrent(p,pNext) )
+                        {
+                            printf( "Box %d has input %d that is not in a topological order.\n", iBox, pNext->Id );
+                            return 0;
+                        }
+                    }
+                }
+            }
+        }
+        else if ( !Aig_ObjIsConst1(pObj) )
+            assert( 0 );
+        Aig_ObjSetTravIdCurrent( p, pObj );
+    }
+    Aig_ManCleanCioIds( p );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManDfs_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    if ( pObj == NULL )
+        return;
+    assert( !Aig_IsComplement(pObj) );
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( p->pEquivs && Aig_ObjEquiv(p, pObj) )
+        Aig_ManDfs_rec( p, Aig_ObjEquiv(p, pObj), vNodes );
+    Aig_ManDfs_rec( p, Aig_ObjFanin0(pObj), vNodes );
+    Aig_ManDfs_rec( p, Aig_ObjFanin1(pObj), vNodes );
+    Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects objects of the AIG in the DFS order.]
+
+  Description [Works with choice nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p, int fNodesOnly )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManIncrementTravId( p );
+    Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
+    // start the array of nodes
+    vNodes = Vec_PtrAlloc( Aig_ManObjNumMax(p) );
+    // mark PIs if they should not be collected
+    if ( fNodesOnly )
+        Aig_ManForEachCi( p, pObj, i )
+            Aig_ObjSetTravIdCurrent( p, pObj );
+    else
+        Vec_PtrPush( vNodes, Aig_ManConst1(p) );
+    // collect nodes reachable in the DFS order
+    Aig_ManForEachCo( p, pObj, i )
+        Aig_ManDfs_rec( p, fNodesOnly? Aig_ObjFanin0(pObj): pObj, vNodes );
+    if ( fNodesOnly )
+        assert( Vec_PtrSize(vNodes) == Aig_ManNodeNum(p) );
+    else
+        assert( Vec_PtrSize(vNodes) == Aig_ManObjNum(p) );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManDfsAll_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        Vec_PtrPush( vNodes, pObj );
+        return;
+    }
+    if ( Aig_ObjIsCo(pObj) )
+    {
+        Aig_ManDfsAll_rec( p, Aig_ObjFanin0(pObj), vNodes );
+        Vec_PtrPush( vNodes, pObj );
+        return;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    Aig_ManDfsAll_rec( p, Aig_ObjFanin0(pObj), vNodes );
+    Aig_ManDfsAll_rec( p, Aig_ObjFanin1(pObj), vNodes );
+    Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects objects of the AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManDfsAll( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManIncrementTravId( p );
+    vNodes = Vec_PtrAlloc( Aig_ManObjNumMax(p) );
+    // add constant
+    Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
+    Vec_PtrPush( vNodes, Aig_ManConst1(p) );
+    // collect nodes reachable in the DFS order
+    Aig_ManForEachCo( p, pObj, i )
+        Aig_ManDfsAll_rec( p, pObj, vNodes );
+    Aig_ManForEachCi( p, pObj, i )
+        if ( !Aig_ObjIsTravIdCurrent(p, pObj) )
+            Vec_PtrPush( vNodes, pObj );
+    assert( Vec_PtrSize(vNodes) == Aig_ManObjNum(p) );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManDfsPreorder_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    if ( pObj == NULL )
+        return;
+    assert( !Aig_IsComplement(pObj) );
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    Vec_PtrPush( vNodes, pObj );
+    if ( p->pEquivs && Aig_ObjEquiv(p, pObj) )
+        Aig_ManDfs_rec( p, Aig_ObjEquiv(p, pObj), vNodes );
+    Aig_ManDfsPreorder_rec( p, Aig_ObjFanin0(pObj), vNodes );
+    Aig_ManDfsPreorder_rec( p, Aig_ObjFanin1(pObj), vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects objects of the AIG in the DFS order.]
+
+  Description [Works with choice nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManDfsPreorder( Aig_Man_t * p, int fNodesOnly )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManIncrementTravId( p );
+    Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
+    // start the array of nodes
+    vNodes = Vec_PtrAlloc( Aig_ManObjNumMax(p) );
+    // mark PIs if they should not be collected
+    if ( fNodesOnly )
+        Aig_ManForEachCi( p, pObj, i )
+            Aig_ObjSetTravIdCurrent( p, pObj );
+    else
+        Vec_PtrPush( vNodes, Aig_ManConst1(p) );
+    // collect nodes reachable in the DFS order
+    Aig_ManForEachCo( p, pObj, i )
+        Aig_ManDfsPreorder_rec( p, fNodesOnly? Aig_ObjFanin0(pObj): pObj, vNodes );
+    if ( fNodesOnly )
+        assert( Vec_PtrSize(vNodes) == Aig_ManNodeNum(p) );
+    else
+        assert( Vec_PtrSize(vNodes) == Aig_ManObjNum(p) );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Levelizes the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Aig_ManLevelize( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    Vec_Vec_t * vLevels;
+    int nLevels, i;
+    nLevels = Aig_ManLevelNum( p );
+    vLevels = Vec_VecStart( nLevels + 1 );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        assert( (int)pObj->Level <= nLevels );
+        Vec_VecPush( vLevels, pObj->Level, pObj );
+    }
+    return vLevels;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes and PIs in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManDfsNodes( Aig_Man_t * p, Aig_Obj_t ** ppNodes, int nNodes )
+{
+    Vec_Ptr_t * vNodes;
+//    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManIncrementTravId( p );
+    // mark constant and PIs
+    Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
+//    Aig_ManForEachCi( p, pObj, i )
+//        Aig_ObjSetTravIdCurrent( p, pObj );
+    // go through the nodes
+    vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) );
+    for ( i = 0; i < nNodes; i++ )
+        if ( Aig_ObjIsCo(ppNodes[i]) )
+            Aig_ManDfs_rec( p, Aig_ObjFanin0(ppNodes[i]), vNodes );
+        else
+            Aig_ManDfs_rec( p, ppNodes[i], vNodes );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManDfsChoices_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    if ( pObj == NULL )
+        return;
+    assert( !Aig_IsComplement(pObj) );
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    assert( Aig_ObjIsNode(pObj) );
+    Aig_ManDfsChoices_rec( p, Aig_ObjFanin0(pObj), vNodes );
+    Aig_ManDfsChoices_rec( p, Aig_ObjFanin1(pObj), vNodes );
+    Aig_ManDfsChoices_rec( p, Aig_ObjEquiv(p, pObj), vNodes );
+    assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManDfsChoices( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        if ( Aig_ObjEquiv(p, pObj) == NULL )
+            continue;
+        Counter = 0;
+        for ( pObj = Aig_ObjEquiv(p, pObj) ; pObj; pObj = Aig_ObjEquiv(p, pObj) )
+            Counter++;
+//        printf( "%d ", Counter );
+    }
+//    printf( "\n" );
+
+    assert( p->pEquivs != NULL );
+    Aig_ManIncrementTravId( p );
+    // mark constant and PIs
+    Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
+    Aig_ManForEachCi( p, pObj, i )
+        Aig_ObjSetTravIdCurrent( p, pObj );
+    // go through the nodes
+    vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) );
+    Aig_ManForEachCo( p, pObj, i )
+        Aig_ManDfsChoices_rec( p, Aig_ObjFanin0(pObj), vNodes );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes in the reverse DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManDfsReverse_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    Aig_Obj_t * pFanout;
+    int iFanout = -1, i;
+    assert( !Aig_IsComplement(pObj) );
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) );
+    Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
+        Aig_ManDfsReverse_rec( p, pFanout, vNodes );
+    assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes in the reverse DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManDfsReverse( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManIncrementTravId( p );
+    // mark POs
+    Aig_ManForEachCo( p, pObj, i )
+        Aig_ObjSetTravIdCurrent( p, pObj );
+    // go through the nodes
+    vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) );
+    Aig_ManForEachObj( p, pObj, i )
+        if ( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) )
+            Aig_ManDfsReverse_rec( p, pObj, vNodes );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the max number of levels in the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManLevelNum( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, LevelsMax;
+    LevelsMax = 0;
+    Aig_ManForEachCo( p, pObj, i )
+        LevelsMax = Abc_MaxInt( LevelsMax, (int)Aig_ObjFanin0(pObj)->Level );
+    return LevelsMax;
+}
+
+//#if 0
+
+/**Function*************************************************************
+
+  Synopsis    [Computes levels for AIG with choices and white boxes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManChoiceLevel_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pNext;
+    int i, iBox, iTerm1, nTerms, LevelMax = 0;
+    if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
+        return;
+    Aig_ObjSetTravIdCurrent( p, pObj );
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        if ( p->pManTime )
+        {
+            iBox = Tim_ManBoxForCi( (Tim_Man_t *)p->pManTime, Aig_ObjCioId(pObj) );
+            if ( iBox >= 0 ) // this is not a true PI
+            {
+                iTerm1 = Tim_ManBoxInputFirst( (Tim_Man_t *)p->pManTime, iBox );
+                nTerms = Tim_ManBoxInputNum( (Tim_Man_t *)p->pManTime, iBox );
+                for ( i = 0; i < nTerms; i++ )
+                {
+                    pNext = Aig_ManCo(p, iTerm1 + i);
+                    Aig_ManChoiceLevel_rec( p, pNext );
+                    if ( LevelMax < Aig_ObjLevel(pNext) )
+                        LevelMax = Aig_ObjLevel(pNext);
+                }
+                LevelMax++;
+            }
+        }
+//        printf( "%d ", pObj->Level );
+    }
+    else if ( Aig_ObjIsCo(pObj) )
+    {
+        pNext = Aig_ObjFanin0(pObj);
+        Aig_ManChoiceLevel_rec( p, pNext );
+        if ( LevelMax < Aig_ObjLevel(pNext) )
+            LevelMax = Aig_ObjLevel(pNext);
+    }
+    else if ( Aig_ObjIsNode(pObj) )
+    { 
+        // get the maximum level of the two fanins
+        pNext = Aig_ObjFanin0(pObj);
+        Aig_ManChoiceLevel_rec( p, pNext );
+        if ( LevelMax < Aig_ObjLevel(pNext) )
+            LevelMax = Aig_ObjLevel(pNext);
+        pNext = Aig_ObjFanin1(pObj);
+        Aig_ManChoiceLevel_rec( p, pNext );
+        if ( LevelMax < Aig_ObjLevel(pNext) )
+            LevelMax = Aig_ObjLevel(pNext);
+        LevelMax++;
+
+        // get the level of the nodes in the choice node
+        if ( p->pEquivs && (pNext = Aig_ObjEquiv(p, pObj)) )
+        {
+            Aig_ManChoiceLevel_rec( p, pNext );
+            if ( LevelMax < Aig_ObjLevel(pNext) )
+                LevelMax = Aig_ObjLevel(pNext);
+        }
+    }
+    else if ( !Aig_ObjIsConst1(pObj) )
+        assert( 0 );
+    Aig_ObjSetLevel( pObj, LevelMax );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes levels for AIG with choices and white boxes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManChoiceLevel( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, LevelMax = 0;
+    Aig_ManForEachObj( p, pObj, i )
+        Aig_ObjSetLevel( pObj, 0 );
+    Aig_ManSetCioIds( p );
+    Aig_ManIncrementTravId( p );
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        Aig_ManChoiceLevel_rec( p, pObj );
+        if ( LevelMax < Aig_ObjLevel(pObj) )
+            LevelMax = Aig_ObjLevel(pObj);
+    }
+    // account for dangling boxes
+    Aig_ManForEachCi( p, pObj, i )
+    {
+        Aig_ManChoiceLevel_rec( p, pObj );
+        if ( LevelMax < Aig_ObjLevel(pObj) )
+            LevelMax = Aig_ObjLevel(pObj);
+    }
+    Aig_ManCleanCioIds( p );
+//    Aig_ManForEachNode( p, pObj, i )
+//        assert( Aig_ObjLevel(pObj) > 0 );
+    return LevelMax;
+} 
+
+//#endif
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of AIG nodes rooted at this cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ConeMark_rec( Aig_Obj_t * pObj )
+{
+    assert( !Aig_IsComplement(pObj) );
+    if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) )
+        return;
+    Aig_ConeMark_rec( Aig_ObjFanin0(pObj) );
+    Aig_ConeMark_rec( Aig_ObjFanin1(pObj) );
+    assert( !Aig_ObjIsMarkA(pObj) ); // loop detection
+    Aig_ObjSetMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of AIG nodes rooted at this cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ConeCleanAndMark_rec( Aig_Obj_t * pObj )
+{
+    assert( !Aig_IsComplement(pObj) );
+    if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) )
+        return;
+    Aig_ConeCleanAndMark_rec( Aig_ObjFanin0(pObj) );
+    Aig_ConeCleanAndMark_rec( Aig_ObjFanin1(pObj) );
+    assert( !Aig_ObjIsMarkA(pObj) ); // loop detection
+    Aig_ObjSetMarkA( pObj );
+    pObj->pData = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of AIG nodes rooted at this cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ConeCountAndMark_rec( Aig_Obj_t * pObj )
+{
+    int Counter;
+    assert( !Aig_IsComplement(pObj) );
+    if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) )
+        return 0;
+    Counter = 1 + Aig_ConeCountAndMark_rec( Aig_ObjFanin0(pObj) ) + 
+        Aig_ConeCountAndMark_rec( Aig_ObjFanin1(pObj) );
+    assert( !Aig_ObjIsMarkA(pObj) ); // loop detection
+    Aig_ObjSetMarkA( pObj );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of AIG nodes rooted at this cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ConeUnmark_rec( Aig_Obj_t * pObj )
+{
+    assert( !Aig_IsComplement(pObj) );
+    if ( !Aig_ObjIsNode(pObj) || !Aig_ObjIsMarkA(pObj) )
+        return;
+    Aig_ConeUnmark_rec( Aig_ObjFanin0(pObj) ); 
+    Aig_ConeUnmark_rec( Aig_ObjFanin1(pObj) );
+    assert( Aig_ObjIsMarkA(pObj) ); // loop detection
+    Aig_ObjClearMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of AIG nodes rooted at this cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_DagSize( Aig_Obj_t * pObj )
+{
+    int Counter;
+    Counter = Aig_ConeCountAndMark_rec( Aig_Regular(pObj) );
+    Aig_ConeUnmark_rec( Aig_Regular(pObj) );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the support size of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_SupportSize_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int * pCounter )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        (*pCounter)++;
+        return;
+    }
+    assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) );
+    Aig_SupportSize_rec( p, Aig_ObjFanin0(pObj), pCounter );
+    if ( Aig_ObjFanin1(pObj) )
+        Aig_SupportSize_rec( p, Aig_ObjFanin1(pObj), pCounter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the support size of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_SupportSize( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    int Counter = 0;
+    assert( !Aig_IsComplement(pObj) );
+    assert( !Aig_ObjIsCo(pObj) );
+    Aig_ManIncrementTravId( p );
+    Aig_SupportSize_rec( p, pObj, &Counter );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the support size of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_SupportSizeTest( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    abctime clk = Abc_Clock();
+    Aig_ManForEachObj( p, pObj, i )
+        if ( Aig_ObjIsNode(pObj) )
+            Counter += (Aig_SupportSize(p, pObj) <= 16);
+    printf( "Nodes with small support %d (out of %d)\n", Counter, Aig_ManNodeNum(p) );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the support size of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_Support_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vSupp )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Aig_ObjIsConst1(pObj) )
+        return;
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        Vec_PtrPush( vSupp, pObj );
+        return;
+    }
+    assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) );
+    Aig_Support_rec( p, Aig_ObjFanin0(pObj), vSupp );
+    if ( Aig_ObjFanin1(pObj) )
+        Aig_Support_rec( p, Aig_ObjFanin1(pObj), vSupp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the support size of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_Support( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Vec_Ptr_t * vSupp;
+    assert( !Aig_IsComplement(pObj) );
+    assert( !Aig_ObjIsCo(pObj) );
+    Aig_ManIncrementTravId( p );
+    vSupp = Vec_PtrAlloc( 100 );
+    Aig_Support_rec( p, pObj, vSupp );
+    return vSupp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the support size of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_SupportNodes( Aig_Man_t * p, Aig_Obj_t ** ppObjs, int nObjs, Vec_Ptr_t * vSupp )
+{
+    int i;
+    Vec_PtrClear( vSupp );
+    Aig_ManIncrementTravId( p );
+    Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
+    for ( i = 0; i < nObjs; i++ )
+    {
+        assert( !Aig_IsComplement(ppObjs[i]) );
+        if ( Aig_ObjIsCo(ppObjs[i]) )
+            Aig_Support_rec( p, Aig_ObjFanin0(ppObjs[i]), vSupp );
+        else
+            Aig_Support_rec( p, ppObjs[i], vSupp );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the AIG from one manager into another.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_Transfer_rec( Aig_Man_t * pDest, Aig_Obj_t * pObj )
+{
+    assert( !Aig_IsComplement(pObj) );
+    if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) )
+        return;
+    Aig_Transfer_rec( pDest, Aig_ObjFanin0(pObj) ); 
+    Aig_Transfer_rec( pDest, Aig_ObjFanin1(pObj) );
+    pObj->pData = Aig_And( pDest, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    assert( !Aig_ObjIsMarkA(pObj) ); // loop detection
+    Aig_ObjSetMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the AIG from one manager into another.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_Transfer( Aig_Man_t * pSour, Aig_Man_t * pDest, Aig_Obj_t * pRoot, int nVars )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    // solve simple cases
+    if ( pSour == pDest )
+        return pRoot;
+    if ( Aig_ObjIsConst1( Aig_Regular(pRoot) ) )
+        return Aig_NotCond( Aig_ManConst1(pDest), Aig_IsComplement(pRoot) );
+    // set the PI mapping
+    Aig_ManForEachCi( pSour, pObj, i )
+    {
+        if ( i == nVars )
+           break;
+        pObj->pData = Aig_IthVar(pDest, i);
+    }
+    // transfer and set markings
+    Aig_Transfer_rec( pDest, Aig_Regular(pRoot) );
+    // clear the markings
+    Aig_ConeUnmark_rec( Aig_Regular(pRoot) );
+    return Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_Compose_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFunc, Aig_Obj_t * pVar )
+{
+    assert( !Aig_IsComplement(pObj) );
+    if ( Aig_ObjIsMarkA(pObj) )
+        return;
+    if ( Aig_ObjIsConst1(pObj) || Aig_ObjIsCi(pObj) )
+    {
+        pObj->pData = pObj == pVar ? pFunc : pObj;
+        return;
+    }
+    Aig_Compose_rec( p, Aig_ObjFanin0(pObj), pFunc, pVar ); 
+    Aig_Compose_rec( p, Aig_ObjFanin1(pObj), pFunc, pVar );
+    pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    assert( !Aig_ObjIsMarkA(pObj) ); // loop detection
+    Aig_ObjSetMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_Compose( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Obj_t * pFunc, int iVar )
+{
+    // quit if the PI variable is not defined
+    if ( iVar >= Aig_ManCiNum(p) )
+    {
+        printf( "Aig_Compose(): The PI variable %d is not defined.\n", iVar );
+        return NULL;
+    }
+    // recursively perform composition
+    Aig_Compose_rec( p, Aig_Regular(pRoot), pFunc, Aig_ManCi(p, iVar) );
+    // clear the markings
+    Aig_ConeUnmark_rec( Aig_Regular(pRoot) );
+    return Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the internal nodes of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjCollectCut_rec( Aig_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+//    Aig_Obj_t * pFan0 = Aig_ObjFanin0(pNode);
+//    Aig_Obj_t * pFan1 = Aig_ObjFanin1(pNode);
+    if ( pNode->fMarkA )
+        return;
+    pNode->fMarkA = 1;
+    assert( Aig_ObjIsNode(pNode) );
+    Aig_ObjCollectCut_rec( Aig_ObjFanin0(pNode), vNodes );
+    Aig_ObjCollectCut_rec( Aig_ObjFanin1(pNode), vNodes );
+    Vec_PtrPush( vNodes, pNode );
+//printf( "added %d  ", pNode->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the internal nodes of the cut.]
+
+  Description [Does not include the leaves of the cut.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjCollectCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    // collect and mark the leaves
+    Vec_PtrClear( vNodes );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i )
+    {
+        assert( pObj->fMarkA == 0 );
+        pObj->fMarkA = 1;
+//        printf( "%d " , pObj->Id );
+    }
+//printf( "\n" );
+    // collect and mark the nodes
+    Aig_ObjCollectCut_rec( pRoot, vNodes );
+    // clean the nodes
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        pObj->fMarkA = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i )
+        pObj->fMarkA = 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the nodes of the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjCollectSuper_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper )
+{
+    int RetValue1, RetValue2, i;
+    // check if the node is visited
+    if ( Aig_Regular(pObj)->fMarkA )
+    {
+        // check if the node occurs in the same polarity
+        for ( i = 0; i < vSuper->nSize; i++ )
+            if ( vSuper->pArray[i] == pObj )
+                return 1;
+        // check if the node is present in the opposite polarity
+        for ( i = 0; i < vSuper->nSize; i++ )
+            if ( vSuper->pArray[i] == Aig_Not(pObj) )
+                return -1;
+        assert( 0 );
+        return 0;
+    }
+    // if the new node is complemented or a PI, another gate begins
+    if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1) )
+    {
+        Vec_PtrPush( vSuper, pObj );
+        Aig_Regular(pObj)->fMarkA = 1;
+        return 0;
+    }
+    assert( !Aig_IsComplement(pObj) );
+    assert( Aig_ObjIsNode(pObj) );
+    // go through the branches
+    RetValue1 = Aig_ObjCollectSuper_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild0(pObj) ), vSuper );
+    RetValue2 = Aig_ObjCollectSuper_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild1(pObj) ), vSuper );
+    if ( RetValue1 == -1 || RetValue2 == -1 )
+        return -1;
+    // return 1 if at least one branch has a duplicate
+    return RetValue1 || RetValue2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the nodes of the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjCollectSuper( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper )
+{
+    int RetValue, i;
+    assert( !Aig_IsComplement(pObj) );
+    assert( Aig_ObjIsNode(pObj) );
+    // collect the nodes in the implication supergate
+    Vec_PtrClear( vSuper );
+    RetValue = Aig_ObjCollectSuper_rec( pObj, pObj, vSuper );
+    assert( Vec_PtrSize(vSuper) > 1 );
+    // unmark the visited nodes
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pObj, i )
+        Aig_Regular(pObj)->fMarkA = 0;
+    // if we found the node and its complement in the same implication supergate, 
+    // return empty set of nodes (meaning that we should use constant-0 node)
+    if ( RetValue == -1 )
+        vSuper->nSize = 0;
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigDoms.c b/abc-build/src/aig/aig/aigDoms.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigDoms.c
@@ -0,0 +1,1154 @@
+/**CFile****************************************************************
+
+  FileName    [aigDoms.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Computing multi-output dominators.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigDoms.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+#include "aig/saig/saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Aig_Sto_t_ Aig_Sto_t;
+typedef struct Aig_Dom_t_ Aig_Dom_t;
+
+struct Aig_Dom_t_
+{
+    int             uSign;         // signature
+    int             nNodes;        // the number of nodes
+    int             pNodes[0];     // the nodes
+};
+
+struct Aig_Sto_t_
+{
+    int             Limit;
+    Aig_Man_t *     pAig;          // user's AIG
+    Aig_MmFixed_t * pMem;          // memory manager for dominators
+    Vec_Ptr_t *     vDoms;         // dominators
+    Vec_Int_t *     vFans;         // temporary fanouts
+    Vec_Int_t *     vTimes;        // the number of times each appears
+    int             nDomNodes;     // nodes with dominators
+    int             nDomsTotal;    // total dominators
+    int             nDomsFilter1;  // filtered dominators
+    int             nDomsFilter2;  // filtered dominators
+};
+
+#define Aig_DomForEachNode( pAig, pDom, pNode, i )                         \
+    for ( i = 0; (i < pDom->nNodes) && ((pNode) = Aig_ManObj(pAig, (pDom)->pNodes[i])); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates dominator manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Sto_t * Aig_ManDomStart( Aig_Man_t * pAig, int Limit )
+{
+    Aig_Sto_t * pSto;
+    pSto = ABC_CALLOC( Aig_Sto_t, 1 );
+    pSto->pAig     = pAig;
+    pSto->Limit    = Limit;
+    pSto->pMem     = Aig_MmFixedStart( sizeof(Aig_Dom_t) + sizeof(int) * Limit, 10000 );
+    pSto->vDoms    = Vec_PtrStart( Aig_ManObjNumMax(pAig) );
+    pSto->vFans    = Vec_IntAlloc( 100 );
+    pSto->vTimes   = Vec_IntStart( Aig_ManObjNumMax(pAig) );
+    return pSto;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds trivial dominator.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjAddTriv( Aig_Sto_t * pSto, int Id, Vec_Ptr_t * vDoms )
+{
+    Aig_Dom_t * pDom;
+    pDom = (Aig_Dom_t *)Aig_MmFixedEntryFetch( pSto->pMem );
+    pDom->uSign     = (1 << (Id % 63));
+    pDom->nNodes    = 1;
+    pDom->pNodes[0] = Id;
+    Vec_PtrPushFirst( vDoms, pDom );
+    assert( Vec_PtrEntry( pSto->vDoms, Id ) == NULL );
+    Vec_PtrWriteEntry( pSto->vDoms, Id, vDoms );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates vector of doms.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ObjDomVecDup( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms, int fSkip1 )
+{
+    Vec_Ptr_t * vDoms2;
+    Aig_Dom_t * pDom, * pDom2;
+    int i;
+    vDoms2 = Vec_PtrAlloc( 0 );
+    Vec_PtrForEachEntryStart( Aig_Dom_t *, vDoms, pDom, i, fSkip1 )
+    {
+        pDom2 = (Aig_Dom_t *)Aig_MmFixedEntryFetch( pSto->pMem );
+        memcpy( pDom2, pDom, sizeof(Aig_Dom_t) + sizeof(int) * pSto->Limit );
+        Vec_PtrPush( vDoms2, pDom2 );
+    }
+    return vDoms2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles vector of doms.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjDomVecRecycle( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms )
+{
+    Aig_Dom_t * pDom;
+    int i;
+    Vec_PtrForEachEntry( Aig_Dom_t *, vDoms, pDom, i )
+        Aig_MmFixedEntryRecycle( pSto->pMem, (char *)pDom );
+    Vec_PtrFree( vDoms );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the vector of doms.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjDomPrint( Aig_Sto_t * pSto, Aig_Dom_t * pDom, int Num )
+{
+    int k;
+    printf( "%4d : {", Num );
+    for ( k = 0; k < pDom->nNodes; k++ )
+        printf( " %4d", pDom->pNodes[k] );
+    for ( ; k < pSto->Limit; k++ )
+        printf( "     " );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the vector of doms.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjDomVecPrint( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms )
+{
+    Aig_Dom_t * pDom;
+    int i;
+    Vec_PtrForEachEntry( Aig_Dom_t *, vDoms, pDom, i )
+        Aig_ObjDomPrint( pSto, pDom, i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes multi-node dominators.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManDomPrint( Aig_Sto_t * pSto )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Saig_ManForEachPi( pSto->pAig, pObj, i )
+    {
+        printf( "*** PI %4d %4d :\n", i, pObj->Id );
+        Aig_ObjDomVecPrint( pSto, (Vec_Ptr_t *)Vec_PtrEntry(pSto->vDoms, pObj->Id) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Divides the circuit into well-balanced parts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManDomStop( Aig_Sto_t * pSto )
+{
+    Vec_Ptr_t * vDoms;
+    int i;
+    Vec_PtrForEachEntry( Vec_Ptr_t *, pSto->vDoms, vDoms, i )
+        if ( vDoms )
+            Aig_ObjDomVecRecycle( pSto, vDoms );
+    Vec_PtrFree( pSto->vDoms );
+    Vec_IntFree( pSto->vFans );
+    Vec_IntFree( pSto->vTimes );
+    Aig_MmFixedStop( pSto->pMem, 0 );
+    ABC_FREE( pSto );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks correctness of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjDomCheck( Aig_Dom_t * pDom )
+{
+    int i;
+    for ( i = 1; i < pDom->nNodes; i++ )
+    {
+        if ( pDom->pNodes[i-1] >= pDom->pNodes[i] )
+        {
+            Abc_Print( -1, "Aig_ObjDomCheck(): Cut has wrong ordering of inputs.\n" );
+            return 0;
+        }
+        assert( pDom->pNodes[i-1] < pDom->pNodes[i] );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pDom is contained in pCut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_ObjDomCheckDominance( Aig_Dom_t * pDom, Aig_Dom_t * pCut )
+{
+    int i, k;
+    for ( i = 0; i < pDom->nNodes; i++ )
+    {
+        for ( k = 0; k < (int)pCut->nNodes; k++ )
+            if ( pDom->pNodes[i] == pCut->pNodes[k] )
+                break;
+        if ( k == (int)pCut->nNodes ) // node i in pDom is not contained in pCut
+            return 0;
+    }
+    // every node in pDom is contained in pCut
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the cut is contained.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjDomFilter( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms, Aig_Dom_t * pDom )
+{ 
+    Aig_Dom_t * pTemp;
+    int i;
+    Vec_PtrForEachEntry( Aig_Dom_t *, vDoms, pTemp, i )
+    {
+        if ( pTemp->nNodes > pDom->nNodes )
+        {
+            // do not fiter the first cut
+            if ( i == 0 )
+                continue;
+            // skip the non-contained cuts
+            if ( (pTemp->uSign & pDom->uSign) != pDom->uSign )
+                continue;
+            // check containment seriously
+            if ( Aig_ObjDomCheckDominance( pDom, pTemp ) )
+            {
+                Vec_PtrRemove( vDoms, pTemp );
+                Aig_MmFixedEntryRecycle( pSto->pMem, (char *)pTemp );
+                i--;
+                pSto->nDomsFilter1++;
+            }
+         }
+        else
+        {
+            // skip the non-contained cuts
+            if ( (pTemp->uSign & pDom->uSign) != pTemp->uSign )
+                continue;
+            // check containment seriously
+            if ( Aig_ObjDomCheckDominance( pTemp, pDom ) )
+            {
+                pSto->nDomsFilter2++;
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_ObjDomMergeOrdered( Aig_Dom_t * pD0, Aig_Dom_t * pD1, Aig_Dom_t * pD, int Limit )
+{ 
+    int i, k, c;
+    assert( pD0->nNodes >= pD1->nNodes );
+    // the case of the largest cut sizes
+    if ( pD0->nNodes == Limit && pD1->nNodes == Limit )
+    {
+        for ( i = 0; i < pD0->nNodes; i++ )
+            if ( pD0->pNodes[i] != pD1->pNodes[i] )
+                return 0;
+        for ( i = 0; i < pD0->nNodes; i++ )
+            pD->pNodes[i] = pD0->pNodes[i];
+        pD->nNodes = pD0->nNodes;
+        return 1;
+    }
+    // the case when one of the cuts is the largest
+    if ( pD0->nNodes == Limit )
+    {
+        for ( i = 0; i < pD1->nNodes; i++ )
+        {
+            for ( k = pD0->nNodes - 1; k >= 0; k-- )
+                if ( pD0->pNodes[k] == pD1->pNodes[i] )
+                    break;
+            if ( k == -1 ) // did not find
+                return 0;
+        }
+        for ( i = 0; i < pD0->nNodes; i++ )
+            pD->pNodes[i] = pD0->pNodes[i];
+        pD->nNodes = pD0->nNodes;
+        return 1;
+    }
+
+    // compare two cuts with different numbers
+    i = k = 0;
+    for ( c = 0; c < (int)Limit; c++ )
+    {
+        if ( k == pD1->nNodes )
+        {
+            if ( i == pD0->nNodes )
+            {
+                pD->nNodes = c;
+                return 1;
+            }
+            pD->pNodes[c] = pD0->pNodes[i++];
+            continue;
+        }
+        if ( i == pD0->nNodes )
+        {
+            if ( k == pD1->nNodes )
+            {
+                pD->nNodes = c;
+                return 1;
+            }
+            pD->pNodes[c] = pD1->pNodes[k++];
+            continue;
+        }
+        if ( pD0->pNodes[i] < pD1->pNodes[k] )
+        {
+            pD->pNodes[c] = pD0->pNodes[i++];
+            continue;
+        }
+        if ( pD0->pNodes[i] > pD1->pNodes[k] )
+        {
+            pD->pNodes[c] = pD1->pNodes[k++];
+            continue;
+        }
+        pD->pNodes[c] = pD0->pNodes[i++]; 
+        k++;
+    }
+    if ( i < pD0->nNodes || k < pD1->nNodes )
+        return 0;
+    pD->nNodes = c;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the object for FPGA mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjDomMergeTwo( Aig_Dom_t * pDom0, Aig_Dom_t * pDom1, Aig_Dom_t * pDom, int Limit )
+{ 
+    assert( Limit > 0 );
+    if ( pDom0->nNodes < pDom1->nNodes )
+    {
+        if ( !Aig_ObjDomMergeOrdered( pDom1, pDom0, pDom, Limit ) )
+            return 0;
+    }
+    else
+    {
+        if ( !Aig_ObjDomMergeOrdered( pDom0, pDom1, pDom, Limit ) )
+            return 0;
+    }
+    pDom->uSign = pDom0->uSign | pDom1->uSign;
+    assert( pDom->nNodes <= Limit );
+    assert( Aig_ObjDomCheck( pDom ) );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merge two arrays of dominators.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ObjDomMerge( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms0, Vec_Ptr_t * vDoms1 )
+{
+    Vec_Ptr_t * vDoms;
+    Aig_Dom_t * pDom0, * pDom1, * pDom;
+    int i, k;
+    vDoms = Vec_PtrAlloc( 16 );
+    Vec_PtrForEachEntry( Aig_Dom_t *, vDoms0, pDom0, i )
+    Vec_PtrForEachEntry( Aig_Dom_t *, vDoms1, pDom1, k )
+    {
+        if ( Aig_WordCountOnes( pDom0->uSign | pDom1->uSign ) > pSto->Limit )
+            continue;
+        // check if the cut exists
+        pDom = (Aig_Dom_t *)Aig_MmFixedEntryFetch( pSto->pMem );
+        if ( !Aig_ObjDomMergeTwo( pDom0, pDom1, pDom, pSto->Limit ) )
+        {
+            Aig_MmFixedEntryRecycle( pSto->pMem, (char *)pDom );
+            continue;
+        }
+        // check if this cut is contained in any of the available cuts
+        if ( Aig_ObjDomFilter( pSto, vDoms, pDom ) )
+        {
+            Aig_MmFixedEntryRecycle( pSto->pMem, (char *)pDom );
+            continue;
+        }
+        Vec_PtrPush( vDoms, pDom );
+    }
+    return vDoms;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Union two arrays of dominators.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjDomUnion( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms2, Vec_Ptr_t * vDoms1 )
+{
+    Aig_Dom_t * pDom1, * pDom2;
+    int i;
+    Vec_PtrForEachEntry( Aig_Dom_t *, vDoms1, pDom1, i )
+    {
+        if ( i == 0 )
+            continue;
+        if ( Aig_ObjDomFilter( pSto, vDoms2, pDom1 ) )
+            continue;
+        pDom2 = (Aig_Dom_t *)Aig_MmFixedEntryFetch( pSto->pMem );
+        memcpy( pDom2, pDom1, sizeof(Aig_Dom_t) + sizeof(int) * pSto->Limit );
+        Vec_PtrPush( vDoms2, pDom2 );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes multi-node dominators.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjDomCompute( Aig_Sto_t * pSto, Aig_Obj_t * pObj )
+{
+    Vec_Ptr_t * vDoms0, * vDoms1, * vDoms2, * vDomsT;
+    Aig_Obj_t * pFanout;
+    int i, iFanout;
+    pSto->nDomNodes += Aig_ObjIsNode(pObj);
+    Vec_IntClear( pSto->vFans );
+    Aig_ObjForEachFanout( pSto->pAig, pObj, pFanout, iFanout, i )
+        if ( Aig_ObjIsTravIdCurrent(pSto->pAig, pFanout) )
+            Vec_IntPush( pSto->vFans, iFanout>>1 );
+    if ( Vec_IntSize(pSto->vFans) == 0 )
+        return;
+    vDoms0 = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, Vec_IntEntry(pSto->vFans, 0) );
+    vDoms2 = Aig_ObjDomVecDup( pSto, vDoms0, 0 );
+    Vec_IntForEachEntryStart( pSto->vFans, iFanout, i, 1 )
+    {
+        vDoms1 = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, iFanout );
+        vDoms2 = Aig_ObjDomMerge( pSto, vDomsT = vDoms2, vDoms1 );
+        Aig_ObjDomVecRecycle( pSto, vDomsT );
+    }
+    Aig_ObjAddTriv( pSto, pObj->Id, vDoms2 );
+    pSto->nDomsTotal += Vec_PtrSize(vDoms2);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the flop TFI with the current traversal ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManMarkFlopTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    int Count;
+    assert( !Aig_IsComplement(pObj) );
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return 0;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) )
+        return 1;
+    Count = Aig_ManMarkFlopTfi_rec( p, Aig_ObjFanin0(pObj) );
+    if ( Aig_ObjIsNode(pObj) )
+        Count += Aig_ManMarkFlopTfi_rec( p, Aig_ObjFanin1(pObj) );
+    return Count;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the flop TFI with the current traversal ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManMarkFlopTfi( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManIncrementTravId( p );
+    Saig_ManForEachLi( p, pObj, i )
+        Aig_ManMarkFlopTfi_rec( p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes multi-node dominators.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Sto_t * Aig_ManComputeDomsFlops( Aig_Man_t * pAig, int Limit )
+{
+    Aig_Sto_t * pSto;
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i;
+    abctime clk = Abc_Clock();
+    pSto = Aig_ManDomStart( pAig, Limit );
+    // initialize flop inputs
+    Saig_ManForEachLi( pAig, pObj, i )
+        Aig_ObjAddTriv( pSto, pObj->Id, Vec_PtrAlloc(1) );
+    // compute internal nodes
+    vNodes = Aig_ManDfsReverse( pAig );
+    Aig_ManMarkFlopTfi( pAig );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        if ( Aig_ObjIsTravIdCurrent(pSto->pAig, pObj) )
+            Aig_ObjDomCompute( pSto, pObj );
+    Vec_PtrFree( vNodes );
+    // compute combinational inputs
+    Aig_ManForEachCi( pAig, pObj, i )
+        Aig_ObjDomCompute( pSto, pObj );
+    // print statistics
+    printf( "Nodes =%4d. Flops =%4d. Doms =%9d. Ave =%8.2f.   ", 
+        pSto->nDomNodes, Aig_ManRegNum(pSto->pAig), pSto->nDomsTotal, 
+//        pSto->nDomsFilter1, pSto->nDomsFilter2,
+        1.0 * pSto->nDomsTotal / (pSto->nDomNodes + Aig_ManRegNum(pSto->pAig)) );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return pSto;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes multi-node dominators.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Sto_t * Aig_ManComputeDomsPis( Aig_Man_t * pAig, int Limit )
+{
+    Aig_Sto_t * pSto;
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i;
+    abctime clk = Abc_Clock();
+    pSto = Aig_ManDomStart( pAig, Limit );
+    // initialize flop inputs
+    Aig_ManForEachCo( pAig, pObj, i )
+        Aig_ObjAddTriv( pSto, pObj->Id, Vec_PtrAlloc(1) );
+    // compute internal nodes
+    vNodes = Aig_ManDfsReverse( pAig );
+    Aig_ManMarkFlopTfi( pAig );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        if ( Aig_ObjIsTravIdCurrent(pSto->pAig, pObj) )
+            Aig_ObjDomCompute( pSto, pObj );
+    Vec_PtrFree( vNodes );
+    // compute combinational inputs
+    Saig_ManForEachPi( pAig, pObj, i )
+        Aig_ObjDomCompute( pSto, pObj );
+    // print statistics
+    printf( "Nodes =%4d. PIs =%4d. Doms =%9d. Ave =%8.2f.   ", 
+        pSto->nDomNodes, Saig_ManPiNum(pSto->pAig), pSto->nDomsTotal, 
+//        pSto->nDomsFilter1, pSto->nDomsFilter2,
+        1.0 * pSto->nDomsTotal / (pSto->nDomNodes + Saig_ManPiNum(pSto->pAig)) );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return pSto;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes multi-node dominators.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Sto_t * Aig_ManComputeDomsNodes( Aig_Man_t * pAig, int Limit )
+{
+    Aig_Sto_t * pSto;
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i;
+    abctime clk = Abc_Clock();
+    pSto = Aig_ManDomStart( pAig, Limit );
+    // initialize flop inputs
+    Aig_ManForEachCo( pAig, pObj, i )
+        Aig_ObjAddTriv( pSto, pObj->Id, Vec_PtrAlloc(1) );
+    // compute internal nodes
+    vNodes = Aig_ManDfsReverse( pAig );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        Aig_ObjDomCompute( pSto, pObj );
+    Vec_PtrFree( vNodes );
+    // compute combinational inputs
+    Aig_ManForEachCi( pAig, pObj, i )
+        Aig_ObjDomCompute( pSto, pObj );
+    // print statistics
+    printf( "Nodes =%6d. Doms =%9d. Ave =%8.2f.   ", 
+        pSto->nDomNodes, pSto->nDomsTotal, 
+//        pSto->nDomsFilter1, pSto->nDomsFilter2,
+        1.0 * pSto->nDomsTotal / pSto->nDomNodes );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return pSto;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects dominators from the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ObjDomCollect( Aig_Sto_t * pSto, Vec_Int_t * vCut )
+{
+    Vec_Ptr_t * vDoms0, * vDoms1, * vDoms2;
+    int i, ObjId;
+    vDoms0 = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, Vec_IntEntry(vCut, 0) );
+    vDoms2 = Aig_ObjDomVecDup( pSto, vDoms0, 1 );
+    Vec_IntForEachEntryStart( vCut, ObjId, i, 1 )
+    {
+        vDoms1 = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, ObjId );
+        if ( vDoms1 == NULL )
+            continue;
+        Aig_ObjDomUnion( pSto, vDoms2, vDoms1 );
+    }
+    return vDoms2;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the flop TFI with the current traversal ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjDomVolume_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    int Count;
+    assert( !Aig_IsComplement(pObj) );
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return 0;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( pObj->fMarkA )
+        return 1;
+//    assert( !Aig_ObjIsCi(pObj) && !Aig_ObjIsConst1(pObj) );
+    if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) )
+        return 1;
+    Count = Aig_ObjDomVolume_rec( p, Aig_ObjFanin0(pObj) );
+    if ( Aig_ObjIsNode(pObj) )
+        Count += Aig_ObjDomVolume_rec( p, Aig_ObjFanin1(pObj) );
+    return Count;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of nodes in the dominator.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjDomVolume( Aig_Sto_t * pSto, Aig_Dom_t * pDom )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    Aig_ManIncrementTravId( pSto->pAig );
+    Aig_DomForEachNode( pSto->pAig, pDom, pObj, i )
+        Counter += Aig_ObjDomVolume_rec( pSto->pAig, pObj );
+    return Counter;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences the node's MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjDomDeref_rec( Aig_Obj_t * pNode )
+{
+    int Counter = 0;
+    assert( pNode->nRefs > 0 );
+    if ( --pNode->nRefs > 0 )
+        return 0;
+    assert( pNode->nRefs == 0 );
+    if ( pNode->fMarkA )
+        return 1;
+    if ( Aig_ObjIsCi(pNode) )
+        return 0;
+    Counter += Aig_ObjDomDeref_rec( Aig_ObjFanin0(pNode) );
+    if ( Aig_ObjIsNode(pNode) )
+    Counter += Aig_ObjDomDeref_rec( Aig_ObjFanin1(pNode) );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [References the node's MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjDomRef_rec( Aig_Obj_t * pNode )
+{
+    int Counter = 0;
+    assert( pNode->nRefs >= 0 );
+    if ( pNode->nRefs++ > 0 )
+        return 0;
+    assert( pNode->nRefs == 1 );
+    if ( pNode->fMarkA )
+        return 1;
+    if ( Aig_ObjIsCi(pNode) )
+        return 0;
+    Counter += Aig_ObjDomRef_rec( Aig_ObjFanin0(pNode) );
+    if ( Aig_ObjIsNode(pNode) )
+    Counter += Aig_ObjDomRef_rec( Aig_ObjFanin1(pNode) );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of nodes in the dominator.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjDomDomed( Aig_Sto_t * pSto, Aig_Dom_t * pDom )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter0, Counter1;
+    Counter0 = 0;
+    Aig_DomForEachNode( pSto->pAig, pDom, pObj, i )
+    {
+        assert( !Aig_ObjIsCi(pObj) );
+        Counter0 += Aig_ObjDomDeref_rec( Aig_ObjFanin0(pObj) );
+        if ( Aig_ObjIsNode(pObj) )
+        Counter0 += Aig_ObjDomDeref_rec( Aig_ObjFanin1(pObj) );
+    }
+    Counter1 = 0;
+    Aig_DomForEachNode( pSto->pAig, pDom, pObj, i )
+    {
+        assert( !Aig_ObjIsCi(pObj) );
+        Counter1 += Aig_ObjDomRef_rec( Aig_ObjFanin0(pObj) );
+        if ( Aig_ObjIsNode(pObj) )
+        Counter1 += Aig_ObjDomRef_rec( Aig_ObjFanin1(pObj) );
+    }
+    assert( Counter0 == Counter1 );
+    return Counter0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects dominators from the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Aig_ObjDomCollectLos( Aig_Sto_t * pSto )
+{
+    Vec_Int_t * vCut;
+    Aig_Obj_t * pObj;
+    int i;
+    vCut = Vec_IntAlloc( Aig_ManRegNum(pSto->pAig) );
+    Saig_ManForEachLo( pSto->pAig, pObj, i )
+    {
+        Vec_IntPush( vCut, pObj->Id );
+        pObj->fMarkA = 1;
+    }
+    return vCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjPoLogicDeref( Aig_Sto_t * pSto )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Saig_ManForEachPo( pSto->pAig, pObj, i )
+        Aig_ObjDomDeref_rec( Aig_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjPoLogicRef( Aig_Sto_t * pSto )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Saig_ManForEachPo( pSto->pAig, pObj, i )
+        Aig_ObjDomRef_rec( Aig_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects dominators from the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjDomFindGood( Aig_Sto_t * pSto )
+{
+    Aig_Dom_t * pDom; 
+    Vec_Int_t * vCut;
+    Vec_Ptr_t * vDoms;
+    int i;
+    vCut  = Aig_ObjDomCollectLos( pSto );
+    vDoms = Aig_ObjDomCollect( pSto, vCut );
+    Vec_IntFree( vCut );
+    printf( "The cut has %d non-trivial %d-dominators.\n", Vec_PtrSize(vDoms), pSto->Limit );
+
+    Aig_ObjPoLogicDeref( pSto );
+    Vec_PtrForEachEntry( Aig_Dom_t *, vDoms, pDom, i )
+    {
+//        if ( Aig_ObjDomDomed(pSto, pDom) <= 1 )
+//            continue;
+        printf( "Vol =%3d.  ", Aig_ObjDomVolume(pSto, pDom) );
+        printf( "Dom =%3d.  ", Aig_ObjDomDomed(pSto, pDom) );
+        Aig_ObjDomPrint( pSto, pDom, i );
+    }
+    Aig_ObjPoLogicRef( pSto );
+
+    Aig_ObjDomVecRecycle( pSto, vDoms );
+    Aig_ManCleanMarkA( pSto->pAig );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes multi-node dominators.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManComputeDomsTest2( Aig_Man_t * pAig, int Num )
+{
+    Aig_Sto_t * pSto;
+//    int i;
+//Aig_ManShow( pAig, 0, NULL );
+    Aig_ManFanoutStart( pAig );
+//    for ( i = 1; i < 9; i++ )
+    {
+        printf( "ITERATION %d:\n", Num );
+        pSto = Aig_ManComputeDomsFlops( pAig, Num );
+        Aig_ObjDomFindGood( pSto );
+//        Aig_ManDomPrint( pSto );
+        Aig_ManDomStop( pSto );
+    }
+    Aig_ManFanoutStop( pAig );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes multi-node dominators.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManComputeDomsTest( Aig_Man_t * pAig )
+{
+    Aig_Sto_t * pSto;
+    Aig_ManFanoutStart( pAig );
+    pSto = Aig_ManComputeDomsPis( pAig, 1 );
+    Aig_ManDomPrint( pSto );
+    Aig_ManDomStop( pSto );
+    Aig_ManFanoutStop( pAig );
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects dominators from the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjDomCount( Aig_Sto_t * pSto, Aig_Obj_t * pObj )
+{
+    Aig_Dom_t * pDom;
+    Aig_Obj_t * pFanout;
+    Vec_Int_t * vSingles;
+    Vec_Ptr_t * vDoms;
+    int i, k, Entry, iFanout, fPrint = 0;
+    vSingles = Vec_IntAlloc( 100 );
+    // for each dominator of a fanout, count how many fanouts have it as a dominator
+    Aig_ObjForEachFanout( pSto->pAig, pObj, pFanout, iFanout, i )
+    {
+        vDoms = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, Aig_ObjId(pFanout) );
+        Vec_PtrForEachEntryStart( Aig_Dom_t *, vDoms, pDom, k, 1 )
+        {
+//            printf( "Fanout %d  Dominator %d\n", Aig_ObjId(pFanout), pDom->pNodes[0] );
+            Vec_IntAddToEntry( pSto->vTimes, pDom->pNodes[0], 1 );
+            Vec_IntPushUnique( vSingles, pDom->pNodes[0] );
+        }
+    }
+    // clear storage
+    Vec_IntForEachEntry( vSingles, Entry, i )
+    {
+        if ( Vec_IntEntry(pSto->vTimes, Entry) > 5 )
+        {
+            if ( fPrint == 0 )
+            {
+                printf( "%6d : Level =%4d. Fanout =%6d.\n", 
+                    Aig_ObjId(pObj), Aig_ObjLevel(pObj), Aig_ObjRefs(pObj) );
+            }
+            fPrint = 1;
+            printf( "%d(%d) ", Entry, Vec_IntEntry(pSto->vTimes, Entry) );
+        }
+        Vec_IntWriteEntry( pSto->vTimes, Entry, 0);
+    }
+    if ( fPrint )
+        printf( "\n" );
+    Vec_IntFree( vSingles );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes multi-node dominators.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManComputeDomsForCofactoring( Aig_Man_t * pAig )
+{
+    Vec_Ptr_t * vDoms;
+    Aig_Sto_t * pSto;
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManFanoutStart( pAig );
+    pSto = Aig_ManComputeDomsNodes( pAig, 1 );
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+        if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) )
+            continue;
+        if ( Aig_ObjRefs(pObj) < 10 )
+            continue;
+        vDoms = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, Aig_ObjId(pObj) );
+//        printf( "%6d : Level =%4d. Fanout =%6d.\n", 
+//            Aig_ObjId(pObj), Aig_ObjLevel(pObj), Aig_ObjRefs(pObj) );
+
+        Aig_ObjDomCount( pSto, pObj );
+    }
+    Aig_ManDomStop( pSto );
+    Aig_ManFanoutStop( pAig );
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigDup.c b/abc-build/src/aig/aig/aigDup.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigDup.c
@@ -0,0 +1,1335 @@
+/**CFile****************************************************************
+
+  FileName    [aigDup.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [AIG duplication (re-strashing).]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigDup.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig/saig/saig.h"
+#include "misc/tim/tim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager.]
+
+  Description [Orders nodes as follows: PIs, ANDs, POs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupSimple( Aig_Man_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i;
+    assert( p->pManTime == NULL );
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nAsserts = p->nAsserts;
+    pNew->nConstrs = p->nConstrs;
+    pNew->nBarBufs = p->nBarBufs;
+    if ( p->vFlopNums )
+        pNew->vFlopNums = Vec_IntDup( p->vFlopNums );
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+    {
+        pObjNew = Aig_ObjCreateCi( pNew );
+        pObjNew->Level = pObj->Level;
+        pObj->pData = pObjNew;
+    }
+    // duplicate internal nodes
+    Aig_ManForEachObj( p, pObj, i )
+        if ( Aig_ObjIsBuf(pObj) )
+        {
+            pObjNew = Aig_ObjChild0Copy(pObj);
+            pObj->pData = pObjNew;
+        }
+        else if ( Aig_ObjIsNode(pObj) )
+        {
+            pObjNew = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+            pObj->pData = pObjNew;
+        }
+    // add the POs
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+        pObj->pData = pObjNew;
+    }
+    assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // check the resulting network
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManDupSimple(): The check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives AIG with hints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupSimpleWithHints( Aig_Man_t * p, Vec_Int_t * vHints )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i, Entry;
+    assert( p->nAsserts == 0 || p->nConstrs == 0 );
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+    {
+        pObj->pData = Aig_ObjCreateCi( pNew );
+        Entry = Vec_IntEntry( vHints, Aig_ObjId(pObj) );
+        if ( Entry == 0 || Entry == 1 )
+            pObj->pData = Aig_NotCond( Aig_ManConst1(pNew), Entry ); // restrict to the complement of constraint!!!
+    }
+    // duplicate internal nodes
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+        Entry = Vec_IntEntry( vHints, Aig_ObjId(pObj) );
+        if ( Entry == 0 || Entry == 1 )
+            pObj->pData = Aig_NotCond( Aig_ManConst1(pNew), Entry ); // restrict to the complement of constraint!!!
+    }
+    // add the POs
+    Aig_ManForEachCo( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    Aig_ManCleanup( pNew );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // check the resulting network
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Llb_ManDeriveAigWithHints(): The check has failed.\n" );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager recursively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_ManDupSimpleDfs_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    if ( pObj->pData )
+        return (Aig_Obj_t *)pObj->pData;
+    Aig_ManDupSimpleDfs_rec( pNew, p, Aig_ObjFanin0(pObj) );
+    if ( Aig_ObjIsBuf(pObj) )
+        return (Aig_Obj_t *)(pObj->pData = Aig_ObjChild0Copy(pObj));
+    Aig_ManDupSimpleDfs_rec( pNew, p, Aig_ObjFanin1(pObj) );
+    pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    return (Aig_Obj_t *)pObj->pData;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager.]
+
+  Description [Orders nodes as follows: PIs, ANDs, POs.]
+               
+  SideEffects [This procedure assumes that buffers are not used during
+  HAIG recording. This way, each HAIG node is in one-to-one correspondence 
+  with old HAIG node. There is no need to create new nodes, just reassign 
+  the pointers. If it were not the case, we would need to create HAIG nodes 
+  for each new node duplicated. ]
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupSimpleDfs( Aig_Man_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i;
+    assert( p->pManTime == NULL );
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nAsserts = p->nAsserts;
+    pNew->nConstrs = p->nConstrs;
+    pNew->nBarBufs = p->nBarBufs;
+    if ( p->vFlopNums )
+        pNew->vFlopNums = Vec_IntDup( p->vFlopNums );
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+    {
+        pObjNew = Aig_ObjCreateCi( pNew );
+        pObjNew->Level = pObj->Level;
+        pObj->pData = pObjNew;
+    }
+    // duplicate internal nodes
+    Aig_ManForEachObj( p, pObj, i )
+        if ( !Aig_ObjIsCo(pObj) )
+        {
+            Aig_ManDupSimpleDfs_rec( pNew, p, pObj );        
+            assert( pObj->Level == ((Aig_Obj_t*)pObj->pData)->Level );
+        }
+    // add the POs
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+        pObj->pData = pObjNew;
+    }
+    assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // check the resulting network
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManDupSimple(): The check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates part of the AIG manager.]
+
+  Description [Orders nodes as follows: PIs, ANDs, POs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupSimpleDfsPart( Aig_Man_t * p, Vec_Ptr_t * vPis, Vec_Ptr_t * vPos )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i;
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1( pNew );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vPis, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    // duplicate internal nodes
+    Vec_PtrForEachEntry( Aig_Obj_t *, vPos, pObj, i )
+    {
+        pObjNew = Aig_ManDupSimpleDfs_rec( pNew, p, Aig_ObjFanin0(pObj) );        
+        pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) );
+        Aig_ObjCreateCo( pNew, pObjNew );
+    }
+    Aig_ManSetRegNum( pNew, 0 );
+    // check the resulting network
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManDupSimple(): The check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager.]
+
+  Description [Assumes topological ordering of the nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupOrdered( Aig_Man_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i, nNodes;
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nAsserts = p->nAsserts;
+    pNew->nConstrs = p->nConstrs;
+    pNew->nBarBufs = p->nBarBufs;
+    if ( p->vFlopNums )
+        pNew->vFlopNums = Vec_IntDup( p->vFlopNums );
+    // create the PIs
+    Aig_ManCleanData( p );
+    // duplicate internal nodes
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( Aig_ObjIsBuf(pObj) )
+        {
+            pObjNew = Aig_ObjChild0Copy(pObj);
+        }
+        else if ( Aig_ObjIsNode(pObj) )
+        {
+            pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) );
+        }
+        else if ( Aig_ObjIsCi(pObj) )
+        {
+            pObjNew = Aig_ObjCreateCi( pNew );
+            pObjNew->Level = pObj->Level;
+        }
+        else if ( Aig_ObjIsCo(pObj) )
+        {
+            pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+        }
+        else if ( Aig_ObjIsConst1(pObj) )
+        {
+            pObjNew = Aig_ManConst1(pNew);
+        }
+        else
+            assert( 0 );
+        pObj->pData = pObjNew;
+    }
+    assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) );
+    if ( (nNodes = Aig_ManCleanup( pNew )) )
+        printf( "Aig_ManDupOrdered(): Cleanup after AIG duplication removed %d nodes.\n", nNodes );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // duplicate the timing manager
+    if ( p->pManTime )
+        pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 );
+    // check the resulting network
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManDupOrdered(): The check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager.]
+
+  Description [Orders nodes as follows: PIs, ANDs, POs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupCof( Aig_Man_t * p, int iInput, int Value )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i;
+    assert( p->pManTime == NULL );
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nAsserts = p->nAsserts;
+    pNew->nConstrs = p->nConstrs;
+    pNew->nBarBufs = p->nBarBufs;
+    if ( p->vFlopNums )
+        pNew->vFlopNums = Vec_IntDup( p->vFlopNums );
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+    {
+        if ( i == iInput )
+            pObjNew = Value ? Aig_ManConst1(pNew) : Aig_ManConst0(pNew);
+        else
+        {
+            pObjNew = Aig_ObjCreateCi( pNew );
+            pObjNew->Level = pObj->Level;
+        }
+        pObj->pData = pObjNew;
+    }
+    // duplicate internal nodes
+    Aig_ManForEachObj( p, pObj, i )
+        if ( Aig_ObjIsBuf(pObj) )
+        {
+            pObjNew = Aig_ObjChild0Copy(pObj);
+            pObj->pData = pObjNew;
+        }
+        else if ( Aig_ObjIsNode(pObj) )
+        {
+            pObjNew = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+            pObj->pData = pObjNew;
+        }
+    // add the POs
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+        pObj->pData = pObjNew;
+    }
+//    assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) );
+    Aig_ManCleanup( pNew );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // check the resulting network
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManDupSimple(): The check has failed.\n" );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager.]
+
+  Description [Assumes topological ordering of the nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupTrim( Aig_Man_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i, nNodes;
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nConstrs = p->nConstrs;
+    pNew->nBarBufs = p->nBarBufs;
+    // create the PIs
+    Aig_ManCleanData( p );
+    // duplicate internal nodes
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( Aig_ObjIsNode(pObj) )
+            pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) );
+        else if ( Aig_ObjIsCi(pObj) )
+            pObjNew = (Aig_ObjRefs(pObj) > 0 || Saig_ObjIsLo(p, pObj)) ? Aig_ObjCreateCi(pNew) : NULL;
+        else if ( Aig_ObjIsCo(pObj) )
+            pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+        else if ( Aig_ObjIsConst1(pObj) )
+            pObjNew = Aig_ManConst1(pNew);
+        else
+            assert( 0 );
+        pObj->pData = pObjNew;
+    }
+    assert( Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) );
+    if ( (nNodes = Aig_ManCleanup( pNew )) )
+        printf( "Aig_ManDupTrim(): Cleanup after AIG duplication removed %d nodes.\n", nNodes );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // check the resulting network
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManDupTrim(): The check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager to have EXOR gates.]
+
+  Description [Assumes topological ordering of the nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupExor( Aig_Man_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i;
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->fCatchExor = 1;
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nAsserts = p->nAsserts;
+    pNew->nConstrs = p->nConstrs;
+    pNew->nBarBufs = p->nBarBufs;
+    if ( p->vFlopNums )
+        pNew->vFlopNums = Vec_IntDup( p->vFlopNums );
+    // create the PIs
+    Aig_ManCleanData( p );
+    // duplicate internal nodes
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( Aig_ObjIsBuf(pObj) )
+        {
+            pObjNew = Aig_ObjChild0Copy(pObj);
+        }
+        else if ( Aig_ObjIsNode(pObj) )
+        {
+            pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) );
+        }
+        else if ( Aig_ObjIsCi(pObj) )
+        {
+            pObjNew = Aig_ObjCreateCi( pNew );
+            pObjNew->Level = pObj->Level;
+        }
+        else if ( Aig_ObjIsCo(pObj) )
+        {
+            pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+        }
+        else if ( Aig_ObjIsConst1(pObj) )
+        {
+            pObjNew = Aig_ManConst1(pNew);
+        }
+        else
+            assert( 0 );
+        pObj->pData = pObjNew;
+    }
+    Aig_ManCleanup( pNew );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // duplicate the timing manager
+    if ( p->pManTime )
+        pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 );
+    // check the resulting network
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManDupExor(): The check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager recursively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_ManDupDfs_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pObjNew, * pEquivNew = NULL;
+    if ( pObj->pData )
+        return (Aig_Obj_t *)pObj->pData;
+    if ( p->pEquivs && Aig_ObjEquiv(p, pObj) )
+        pEquivNew = Aig_ManDupDfs_rec( pNew, p, Aig_ObjEquiv(p, pObj) );
+    Aig_ManDupDfs_rec( pNew, p, Aig_ObjFanin0(pObj) );
+    if ( Aig_ObjIsBuf(pObj) )
+        return (Aig_Obj_t *)(pObj->pData = Aig_ObjChild0Copy(pObj));
+    Aig_ManDupDfs_rec( pNew, p, Aig_ObjFanin1(pObj) );
+    pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) );
+    if ( pEquivNew )
+    {
+        assert( Aig_Regular(pEquivNew)->Id < Aig_Regular(pObjNew)->Id );
+        if ( pNew->pEquivs )
+            pNew->pEquivs[Aig_Regular(pObjNew)->Id] = Aig_Regular(pEquivNew);        
+        if ( pNew->pReprs )
+            pNew->pReprs[Aig_Regular(pEquivNew)->Id] = Aig_Regular(pObjNew);
+    }
+    return (Aig_Obj_t *)(pObj->pData = pObjNew);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager.]
+
+  Description [This duplicator works for AIGs with choices.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupDfs( Aig_Man_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i, nNodes;
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nAsserts = p->nAsserts;
+    pNew->nConstrs = p->nConstrs;
+    pNew->nBarBufs = p->nBarBufs;
+    if ( p->vFlopNums )
+        pNew->vFlopNums = Vec_IntDup( p->vFlopNums );
+    // duplicate representation of choice nodes
+    if ( p->pEquivs )
+        pNew->pEquivs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) );
+    if ( p->pReprs )
+        pNew->pReprs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) );
+    // create the PIs
+    Aig_ManCleanData( p );
+    // duplicate internal nodes
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( Aig_ObjIsCi(pObj) )
+        {
+            pObjNew = Aig_ObjCreateCi( pNew );
+            pObjNew->Level = pObj->Level;
+            pObj->pData = pObjNew;
+        }
+        else if ( Aig_ObjIsCo(pObj) )
+        {
+            Aig_ManDupDfs_rec( pNew, p, Aig_ObjFanin0(pObj) );        
+//            assert( pObj->Level == ((Aig_Obj_t*)pObj->pData)->Level );
+            pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+            pObj->pData = pObjNew;
+        }
+    }
+    assert( p->pEquivs != NULL || Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) );
+    if ( p->pEquivs == NULL && p->pReprs == NULL && (nNodes = Aig_ManCleanup( pNew )) )
+        printf( "Aig_ManDupDfs(): Cleanup after AIG duplication removed %d nodes.\n", nNodes );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // duplicate the timing manager
+    if ( p->pManTime )
+        pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 );
+    // check the resulting network
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManDupDfs(): The check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager.]
+
+  Description [This duplicator works for AIGs with choices.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManOrderPios( Aig_Man_t * p, Aig_Man_t * pOrder )
+{
+    Vec_Ptr_t * vPios;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( Aig_ManCiNum(p) == Aig_ManCiNum(pOrder) );
+    assert( Aig_ManCoNum(p) == Aig_ManCoNum(pOrder) );
+    Aig_ManSetCioIds( pOrder );
+    vPios = Vec_PtrAlloc( Aig_ManCiNum(p) + Aig_ManCoNum(p) );
+    Aig_ManForEachObj( pOrder, pObj, i )
+    {
+        if ( Aig_ObjIsCi(pObj) )
+            Vec_PtrPush( vPios, Aig_ManCi(p, Aig_ObjCioId(pObj)) );
+        else if ( Aig_ObjIsCo(pObj) )
+            Vec_PtrPush( vPios, Aig_ManCo(p, Aig_ObjCioId(pObj)) );
+    }
+    Aig_ManCleanCioIds( pOrder );
+    return vPios;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager recursively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_ManDupDfsGuided_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pObjNew, * pEquivNew = NULL;
+    if ( pObj->pData )
+        return (Aig_Obj_t *)pObj->pData;
+    if ( Aig_ObjIsCi(pObj) )
+        return NULL;
+    if ( p->pEquivs && Aig_ObjEquiv(p, pObj) )
+        pEquivNew = Aig_ManDupDfsGuided_rec( pNew, p, Aig_ObjEquiv(p, pObj) );
+    if ( !Aig_ManDupDfsGuided_rec( pNew, p, Aig_ObjFanin0(pObj) ) )
+        return NULL;
+    if ( Aig_ObjIsBuf(pObj) )
+        return (Aig_Obj_t *)(pObj->pData = Aig_ObjChild0Copy(pObj));
+    if ( !Aig_ManDupDfsGuided_rec( pNew, p, Aig_ObjFanin1(pObj) ) )
+        return NULL;
+    pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) );
+    if ( pEquivNew )
+    {
+        if ( pNew->pEquivs )
+            pNew->pEquivs[Aig_Regular(pObjNew)->Id] = Aig_Regular(pEquivNew);        
+        if ( pNew->pReprs )
+            pNew->pReprs[Aig_Regular(pEquivNew)->Id] = Aig_Regular(pObjNew);
+    }
+    return (Aig_Obj_t *)(pObj->pData = pObjNew);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager.]
+
+  Description [This duplicator works for AIGs with choices.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupDfsGuided( Aig_Man_t * p, Vec_Ptr_t * vPios )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i, nNodes;
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nAsserts = p->nAsserts;
+    pNew->nConstrs = p->nConstrs;
+    pNew->nBarBufs = p->nBarBufs;
+    if ( p->vFlopNums )
+        pNew->vFlopNums = Vec_IntDup( p->vFlopNums );
+    // duplicate representation of choice nodes
+    if ( p->pEquivs )
+    {
+        pNew->pEquivs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) );
+        memset( pNew->pEquivs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p) );
+    }
+    if ( p->pReprs )
+    {
+        pNew->pReprs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) );
+        memset( pNew->pReprs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p) );
+    }
+    // create the PIs
+    Aig_ManCleanData( p );
+    // duplicate internal nodes
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Vec_PtrForEachEntry( Aig_Obj_t *, vPios, pObj, i )
+    {
+        if ( Aig_ObjIsCi(pObj) )
+        {
+            pObjNew = Aig_ObjCreateCi( pNew );
+            pObjNew->Level = pObj->Level;
+            pObj->pData = pObjNew;
+        }
+        else if ( Aig_ObjIsCo(pObj) )
+        {
+            Aig_ManDupDfsGuided_rec( pNew, p, Aig_ObjFanin0(pObj) );        
+//            assert( pObj->Level == ((Aig_Obj_t*)pObj->pData)->Level );
+            pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+            pObj->pData = pObjNew;
+        }
+    }
+//    assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) );
+    if ( p->pEquivs == NULL && p->pReprs == NULL && (nNodes = Aig_ManCleanup( pNew )) )
+        printf( "Aig_ManDupDfs(): Cleanup after AIG duplication removed %d nodes.\n", nNodes );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // duplicate the timing manager
+    if ( p->pManTime )
+        pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 );
+    // check the resulting network
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManDupDfs(): The check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager.]
+
+  Description [This duplicator works for AIGs with choices.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupLevelized( Aig_Man_t * p )
+{
+    Vec_Vec_t * vLevels;
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i, k;
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nAsserts = p->nAsserts;
+    pNew->nConstrs = p->nConstrs;
+    pNew->nBarBufs = p->nBarBufs;
+    if ( p->vFlopNums )
+        pNew->vFlopNums = Vec_IntDup( p->vFlopNums );
+    // duplicate representation of choice nodes
+    if ( p->pEquivs )
+    {
+        pNew->pEquivs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) );
+        memset( pNew->pEquivs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p) );
+    }
+    if ( p->pReprs )
+    {
+        pNew->pReprs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) );
+        memset( pNew->pReprs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p) );
+    }
+    // create the PIs
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+    {
+        pObjNew = Aig_ObjCreateCi( pNew );
+        pObjNew->Level = pObj->Level;
+        pObj->pData = pObjNew;
+    }
+    // duplicate internal nodes
+    vLevels = Aig_ManLevelize( p );
+    Vec_VecForEachEntry( Aig_Obj_t *, vLevels, pObj, i, k )
+    {
+        pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) );
+        pObj->pData = pObjNew;
+    }
+    Vec_VecFree( vLevels );
+    // duplicate POs
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+        pObj->pData = pObjNew;
+    }
+    assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) );
+//    if ( (nNodes = Aig_ManCleanup( pNew )) )
+//        printf( "Aig_ManDupLevelized(): Cleanup after AIG duplication removed %d nodes.\n", nNodes );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // duplicate the timing manager
+    if ( p->pManTime )
+        pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 );
+    // check the resulting network
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManDupLevelized(): The check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager.]
+
+  Description [Assumes topological ordering of nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupWithoutPos( Aig_Man_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    // duplicate internal nodes
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        assert( !Aig_ObjIsBuf(pObj) );
+        if ( Aig_ObjIsNode(pObj) )
+            pObj->pData = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) );
+    }
+    assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager.]
+
+  Description [Assumes topological ordering of nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupFlopsOnly( Aig_Man_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    pNew = Aig_ManDupWithoutPos( p );
+    Saig_ManForEachLi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    Aig_ManCleanup( pNew );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManDupFlopsOnly(): The check has failed.\n" );
+    return pNew;
+
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns representatives of fanin in approapriate polarity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Aig_Obj_t * Aig_ObjGetRepres( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pRepr;
+    if ( (pRepr = Aig_ObjRepr(p, pObj)) )
+        return Aig_NotCond( (Aig_Obj_t *)pRepr->pData, pObj->fPhase ^ pRepr->fPhase );
+    return (Aig_Obj_t *)pObj->pData;
+}
+static inline Aig_Obj_t * Aig_ObjChild0Repres( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjGetRepres(p, Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) ); }
+static inline Aig_Obj_t * Aig_ObjChild1Repres( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjGetRepres(p, Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) ); }
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG while substituting representatives.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupRepres( Aig_Man_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    // start the HOP package
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nConstrs = p->nConstrs;
+    pNew->nBarBufs = p->nBarBufs;
+    if ( p->vFlopNums )
+        pNew->vFlopNums = Vec_IntDup( p->vFlopNums );
+    // map the const and primary inputs
+    Aig_ManCleanData( p );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( Aig_ObjIsNode(pObj) )
+            pObj->pData = Aig_And( pNew, Aig_ObjChild0Repres(p, pObj), Aig_ObjChild1Repres(p, pObj) );
+        else if ( Aig_ObjIsCi(pObj) )
+        {
+            pObj->pData = Aig_ObjCreateCi(pNew);
+            pObj->pData = Aig_ObjGetRepres( p, pObj );
+        }
+        else if ( Aig_ObjIsCo(pObj) )
+            pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Repres(p, pObj) );
+        else if ( Aig_ObjIsConst1(pObj) )
+            pObj->pData = Aig_ManConst1(pNew);
+        else
+            assert( 0 );
+    }
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // check the new manager
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManDupRepres: Check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager recursively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_ManDupRepres_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pRepr;
+    if ( pObj->pData )
+        return (Aig_Obj_t *)pObj->pData;
+    if ( (pRepr = Aig_ObjRepr(p, pObj)) )
+    {
+        Aig_ManDupRepres_rec( pNew, p, pRepr );
+        return (Aig_Obj_t *)(pObj->pData = Aig_NotCond( (Aig_Obj_t *)pRepr->pData, pRepr->fPhase ^ pObj->fPhase ));
+    }
+    Aig_ManDupRepres_rec( pNew, p, Aig_ObjFanin0(pObj) );
+    Aig_ManDupRepres_rec( pNew, p, Aig_ObjFanin1(pObj) );
+    return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Repres(p, pObj), Aig_ObjChild1Repres(p, pObj) ));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG while substituting representatives.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupRepresDfs( Aig_Man_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    // start the HOP package
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nConstrs = p->nConstrs;
+    pNew->nBarBufs = p->nBarBufs;
+    if ( p->vFlopNums )
+        pNew->vFlopNums = Vec_IntDup( p->vFlopNums );
+    // map the const and primary inputs
+    Aig_ManCleanData( p );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( Aig_ObjIsNode(pObj) )
+            continue;
+        if ( Aig_ObjIsCi(pObj) )
+            pObj->pData = Aig_ObjCreateCi(pNew);
+        else if ( Aig_ObjIsCo(pObj) )
+        {
+            Aig_ManDupRepres_rec( pNew, p, Aig_ObjFanin0(pObj) );
+            pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Repres(p, pObj) );
+        }
+        else if ( Aig_ObjIsConst1(pObj) )
+            pObj->pData = Aig_ManConst1(pNew);
+        else 
+            assert( 0 );
+    }
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // check the new manager
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManDupRepresDfs: Check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the miter of the two AIG managers.]
+
+  Description [Oper is the operation to perform on the outputs of the miter.
+  Oper == 0 is XOR
+  Oper == 1 is complemented implication (p1 => p2)
+  Oper == 2 is OR
+  Oper == 3 is AND
+  ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManCreateMiter( Aig_Man_t * p1, Aig_Man_t * p2, int Oper )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( Aig_ManRegNum(p1) == 0 );
+    assert( Aig_ManRegNum(p2) == 0 );
+    assert( Aig_ManCoNum(p1) == 1 );
+    assert( Aig_ManCoNum(p2) == 1 );
+    assert( Aig_ManCiNum(p1) == Aig_ManCiNum(p2) );
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p1) + Aig_ManObjNumMax(p2) );
+    // add first AIG
+    Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p1, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    Aig_ManForEachNode( p1, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // add second AIG
+    Aig_ManConst1(p2)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p2, pObj, i )
+        pObj->pData = Aig_ManCi( pNew, i );
+    Aig_ManForEachNode( p2, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // add the output
+    if ( Oper == 0 ) // XOR
+        pObj = Aig_Exor( pNew, Aig_ObjChild0Copy(Aig_ManCo(p1,0)), Aig_ObjChild0Copy(Aig_ManCo(p2,0)) );
+    else if ( Oper == 1 ) // implication is PO(p1) -> PO(p2)  ...  complement is PO(p1) & !PO(p2) 
+        pObj = Aig_And( pNew, Aig_ObjChild0Copy(Aig_ManCo(p1,0)), Aig_Not(Aig_ObjChild0Copy(Aig_ManCo(p2,0))) );
+    else if ( Oper == 2 ) // OR
+        pObj = Aig_Or( pNew, Aig_ObjChild0Copy(Aig_ManCo(p1,0)), Aig_ObjChild0Copy(Aig_ManCo(p2,0)) );
+    else if ( Oper == 3 ) // AND
+        pObj = Aig_And( pNew, Aig_ObjChild0Copy(Aig_ManCo(p1,0)), Aig_ObjChild0Copy(Aig_ManCo(p2,0)) );
+    else
+        assert( 0 );
+    Aig_ObjCreateCo( pNew, pObj );
+    Aig_ManCleanup( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG with only one primary output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupOrpos( Aig_Man_t * p, int fAddRegs )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pMiter;
+    int i;
+    assert( Aig_ManRegNum(p) > 0 );
+    if ( p->nConstrs > 0 )
+    {
+        printf( "The AIG manager should have no constraints.\n" );
+        return NULL;
+    }
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    // set registers
+    pNew->nRegs    = fAddRegs? p->nRegs : 0;
+    pNew->nTruePis = fAddRegs? p->nTruePis : p->nTruePis + p->nRegs;
+    pNew->nTruePos = 1;
+    // duplicate internal nodes
+    Aig_ManForEachNode( p, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // create the PO
+    pMiter = Aig_ManConst0(pNew);
+    Aig_ManForEachPoSeq( p, pObj, i )
+        pMiter = Aig_Or( pNew, pMiter, Aig_ObjChild0Copy(pObj) ); 
+    Aig_ObjCreateCo( pNew, pMiter );
+    // create register inputs with MUXes
+    if ( fAddRegs )
+    {
+        Aig_ManForEachLiSeq( p, pObj, i )
+            Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    }
+    Aig_ManCleanup( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG with only one primary output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupOneOutput( Aig_Man_t * p, int iPoNum, int fAddRegs )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( Aig_ManRegNum(p) > 0 );
+    assert( iPoNum < Aig_ManCoNum(p)-Aig_ManRegNum(p) );
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    // set registers
+    pNew->nRegs    = fAddRegs? p->nRegs : 0;
+    pNew->nTruePis = fAddRegs? p->nTruePis : p->nTruePis + p->nRegs;
+    pNew->nTruePos = 1;
+    // duplicate internal nodes
+    Aig_ManForEachNode( p, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // create the PO
+    pObj = Aig_ManCo( p, iPoNum );
+    Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    // create register inputs with MUXes
+    if ( fAddRegs )
+    {
+        Aig_ManForEachLiSeq( p, pObj, i )
+            Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    }
+    Aig_ManCleanup( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG with only one primary output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupUnsolvedOutputs( Aig_Man_t * p, int fAddRegs )
+{ 
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i, nOuts = 0;
+    assert( Aig_ManRegNum(p) > 0 );
+    if ( p->nConstrs > 0 )
+    {
+        printf( "The AIG manager should have no constraints.\n" );
+        return NULL;
+    }
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    // create the POs
+    nOuts = 0;
+    Aig_ManForEachPoSeq( p, pObj, i )
+        nOuts += ( Aig_ObjFanin0(pObj) != Aig_ManConst1(p) );
+    // set registers
+    pNew->nRegs    = fAddRegs? p->nRegs : 0;
+    pNew->nTruePis = fAddRegs? p->nTruePis : p->nTruePis + p->nRegs;
+    pNew->nTruePos = nOuts;
+    // duplicate internal nodes
+    Aig_ManForEachNode( p, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // create the PO
+    Aig_ManForEachPoSeq( p, pObj, i )
+        if ( Aig_ObjFanin0(pObj) != Aig_ManConst1(p) )
+            Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    // create register inputs with MUXes
+    if ( fAddRegs )
+    {
+        Aig_ManForEachLiSeq( p, pObj, i )
+            Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    }
+    Aig_ManCleanup( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG with only one primary output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupArray( Vec_Ptr_t * vArray )
+{
+    Aig_Man_t * p, * pNew;
+    Aig_Obj_t * pObj;
+    int i, k;
+    if ( Vec_PtrSize(vArray) == 0 )
+        return NULL;
+    p = (Aig_Man_t *)Vec_PtrEntry( vArray, 0 );
+    Vec_PtrForEachEntry( Aig_Man_t *, vArray, pNew, k )
+    {
+        assert( Aig_ManRegNum(pNew) == 0 );
+        assert( Aig_ManCiNum(pNew) == Aig_ManCiNum(p) );
+    }
+    // create the new manager
+    pNew = Aig_ManStart( 10000 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Aig_ManForEachCi( p, pObj, i )
+        Aig_ObjCreateCi(pNew);
+    // create the PIs
+    Vec_PtrForEachEntry( Aig_Man_t *, vArray, p, k )
+    {
+        Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+        Aig_ManForEachCi( p, pObj, i )
+            pObj->pData = Aig_ManCi( pNew, i );
+        Aig_ManForEachNode( p, pObj, i )
+            pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+        Aig_ManForEachCo( p, pObj, i )
+            Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    }
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // check the resulting network
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManDupSimple(): The check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG with only one primary output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupNodes( Aig_Man_t * pMan, Vec_Ptr_t * vArray )
+{
+    Aig_Man_t * pNew;
+    Vec_Ptr_t * vObjs;
+    Aig_Obj_t * pObj;
+    int i;
+    if ( Vec_PtrSize(vArray) == 0 )
+        return NULL;
+    vObjs = Aig_ManDfsNodes( pMan, (Aig_Obj_t **)Vec_PtrArray(vArray), Vec_PtrSize(vArray) );
+    // create the new manager
+    pNew = Aig_ManStart( 10000 );
+    pNew->pName = Abc_UtilStrsav( pMan->pName );
+    Aig_ManConst1(pMan)->pData = Aig_ManConst1(pNew);
+    Vec_PtrForEachEntry( Aig_Obj_t *, vObjs, pObj, i )
+        if ( Aig_ObjIsCi(pObj) )
+            pObj->pData = Aig_ObjCreateCi(pNew);
+    Vec_PtrForEachEntry( Aig_Obj_t *, vObjs, pObj, i )
+        if ( Aig_ObjIsNode(pObj) )
+            pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vArray, pObj, i )
+            Aig_ObjCreateCo( pNew, (Aig_Obj_t *)pObj->pData );
+    Aig_ManSetRegNum( pNew, 0 );
+    Vec_PtrFree( vObjs );
+    return pNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigFact.c b/abc-build/src/aig/aig/aigFact.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigFact.c
@@ -0,0 +1,734 @@
+/**CFile****************************************************************
+
+  FileName    [aigFactor.c]
+
+  SystemName  []
+
+  PackageName []
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation []
+
+  Date        [Ver. 1.0. Started - April 17, 2009.]
+
+  Revision    [$Id: aigFactor.c,v 1.00 2009/04/17 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Detects multi-input AND gate rooted at this node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManFindImplications_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vImplics )
+{
+    if ( Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) )
+    {
+        Vec_PtrPushUnique( vImplics, pObj );
+        return;
+    }
+    Aig_ManFindImplications_rec( Aig_ObjChild0(pObj), vImplics );
+    Aig_ManFindImplications_rec( Aig_ObjChild1(pObj), vImplics );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the nodes whose values are implied by pNode.]
+
+  Description [Attention!  Both pNode and results can be complemented!
+  Also important: Currently, this procedure only does backward propagation. 
+  In general, it may find more implications if forward propagation is enabled.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManFindImplications( Aig_Man_t * p, Aig_Obj_t * pNode )
+{
+    Vec_Ptr_t * vImplics;
+    vImplics = Vec_PtrAlloc( 100 );
+    Aig_ManFindImplications_rec( pNode, vImplics );
+    return vImplics;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the cone of the node overlaps with the vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManFindConeOverlap_rec( Aig_Man_t * p, Aig_Obj_t * pNode )
+{
+    if ( Aig_ObjIsTravIdPrevious( p, pNode ) )
+        return 1;
+    if ( Aig_ObjIsTravIdCurrent( p, pNode ) )
+        return 0;
+    Aig_ObjSetTravIdCurrent( p, pNode );
+    if ( Aig_ObjIsCi(pNode) )
+        return 0;
+    if ( Aig_ManFindConeOverlap_rec( p, Aig_ObjFanin0(pNode) ) )
+        return 1;
+    if ( Aig_ManFindConeOverlap_rec( p, Aig_ObjFanin1(pNode) ) )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the cone of the node overlaps with the vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManFindConeOverlap( Aig_Man_t * p, Vec_Ptr_t * vImplics, Aig_Obj_t * pNode )
+{
+    Aig_Obj_t * pTemp;
+    int i;
+    assert( !Aig_IsComplement(pNode) );
+    assert( !Aig_ObjIsConst1(pNode) );
+    Aig_ManIncrementTravId( p );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vImplics, pTemp, i )
+        Aig_ObjSetTravIdCurrent( p, Aig_Regular(pTemp) );
+    Aig_ManIncrementTravId( p );
+    return Aig_ManFindConeOverlap_rec( p, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the cone of the node overlaps with the vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_ManDeriveNewCone_rec( Aig_Man_t * p, Aig_Obj_t * pNode )
+{
+    if ( Aig_ObjIsTravIdCurrent( p, pNode ) )
+        return (Aig_Obj_t *)pNode->pData;
+    Aig_ObjSetTravIdCurrent( p, pNode );
+    if ( Aig_ObjIsCi(pNode) )
+        return (Aig_Obj_t *)(pNode->pData = pNode);
+    Aig_ManDeriveNewCone_rec( p, Aig_ObjFanin0(pNode) );
+    Aig_ManDeriveNewCone_rec( p, Aig_ObjFanin1(pNode) );
+    return (Aig_Obj_t *)(pNode->pData = Aig_And( p, Aig_ObjChild0Copy(pNode), Aig_ObjChild1Copy(pNode) ));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the cone of the node overlaps with the vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_ManDeriveNewCone( Aig_Man_t * p, Vec_Ptr_t * vImplics, Aig_Obj_t * pNode )
+{
+    Aig_Obj_t * pTemp;
+    int i;
+    assert( !Aig_IsComplement(pNode) );
+    assert( !Aig_ObjIsConst1(pNode) );
+    Aig_ManIncrementTravId( p );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vImplics, pTemp, i )
+    {
+        Aig_ObjSetTravIdCurrent( p, Aig_Regular(pTemp) );
+        Aig_Regular(pTemp)->pData = Aig_NotCond( Aig_ManConst1(p), Aig_IsComplement(pTemp) );
+    }
+    return Aig_ManDeriveNewCone_rec( p, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns algebraic factoring of B in terms of A.]
+
+  Description [Returns internal node C (an AND gate) that is equal to B 
+  under assignment A = 'Value', or NULL if there is no such node C. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_ManFactorAlgebraic_int( Aig_Man_t * p, Aig_Obj_t * pPoA, Aig_Obj_t * pPoB, int Value )
+{
+    Aig_Obj_t * pNodeA, * pNodeC;
+    Vec_Ptr_t * vImplics;
+    int RetValue;
+    if ( Aig_ObjIsConst1(Aig_ObjFanin0(pPoA)) || Aig_ObjIsConst1(Aig_ObjFanin0(pPoB)) )
+        return NULL;
+    if ( Aig_ObjIsCi(Aig_ObjFanin0(pPoB)) )
+        return NULL;
+    // get the internal node representing function of A under assignment A = 'Value'
+    pNodeA = Aig_ObjChild0( pPoA );
+    pNodeA = Aig_NotCond( pNodeA, Value==0 );
+    // find implications of this signal (nodes whose value is fixed under assignment A = 'Value')
+    vImplics = Aig_ManFindImplications( p, pNodeA );
+    // check if the TFI cone of B overlaps with the implied nodes
+    RetValue = Aig_ManFindConeOverlap( p, vImplics, Aig_ObjFanin0(pPoB) );
+    if ( RetValue == 0 ) // no overlap
+    {
+        Vec_PtrFree( vImplics );
+        return NULL;
+    }
+    // there is overlap - derive node representing value of B under assignment A = 'Value'
+    pNodeC = Aig_ManDeriveNewCone( p, vImplics, Aig_ObjFanin0(pPoB) );
+    pNodeC = Aig_NotCond( pNodeC, Aig_ObjFaninC0(pPoB) );
+    Vec_PtrFree( vImplics );
+    return pNodeC;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns algebraic factoring of B in terms of A.]
+
+  Description [Returns internal node C (an AND gate) that is equal to B 
+  under assignment A = 'Value', or NULL if there is no such node C. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_ManFactorAlgebraic( Aig_Man_t * p, int iPoA, int iPoB, int Value )
+{
+    assert( iPoA >= 0 && iPoA < Aig_ManCoNum(p) );
+    assert( iPoB >= 0 && iPoB < Aig_ManCoNum(p) );
+    assert( Value == 0 || Value == 1 );
+    return Aig_ManFactorAlgebraic_int( p, Aig_ManCo(p, iPoA), Aig_ManCo(p, iPoB), Value ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Testing procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManFactorAlgebraicTest( Aig_Man_t * p )
+{
+    int iPoA  = 0;
+    int iPoB  = 1;
+    int Value = 0;
+    Aig_Obj_t * pRes;
+//    Aig_Obj_t * pObj;
+//    int i;
+    pRes = Aig_ManFactorAlgebraic( p, iPoA, iPoB, Value );
+    Aig_ManShow( p, 0, NULL );
+    Aig_ObjPrint( p, pRes );
+    printf( "\n" );
+/*
+    printf( "Results:\n" );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        printf( "Object = %d.\n", i );
+        Aig_ObjPrint( p, pObj );
+        printf( "\n" );
+        Aig_ObjPrint( p, pObj->pData );
+        printf( "\n" );
+    }
+*/
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Determines what support variables can be cofactored.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_SuppMinPerform( Aig_Man_t * p, Vec_Ptr_t * vOrGate, Vec_Ptr_t * vNodes, Vec_Ptr_t * vSupp )
+{
+    Aig_Obj_t * pObj;
+    Vec_Ptr_t * vTrSupp, * vTrNode, * vCofs;
+    unsigned * uFunc = NULL, * uCare, * uFunc0, * uFunc1;
+    unsigned * uCof0, * uCof1, * uCare0, * uCare1;
+    int i, nWords = Abc_TruthWordNum( Vec_PtrSize(vSupp) );
+    // assign support nodes
+    vTrSupp = Vec_PtrAllocTruthTables( Vec_PtrSize(vSupp) );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSupp, pObj, i )
+        pObj->pData = Vec_PtrEntry( vTrSupp, i );
+    // compute internal nodes
+    vTrNode = Vec_PtrAllocSimInfo( Vec_PtrSize(vNodes) + 5, nWords );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        pObj->pData = uFunc = (unsigned *)Vec_PtrEntry( vTrNode, i );
+        uFunc0 = (unsigned *)Aig_ObjFanin0(pObj)->pData;
+        uFunc1 = (unsigned *)Aig_ObjFanin1(pObj)->pData;
+        Kit_TruthAndPhase( uFunc, uFunc0, uFunc1, Vec_PtrSize(vSupp), Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) );
+    }
+    // uFunc contains the result of computation
+    // compute care set
+    uCare = (unsigned *)Vec_PtrEntry( vTrNode, Vec_PtrSize(vNodes) );
+    Kit_TruthClear( uCare, Vec_PtrSize(vSupp) );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vOrGate, pObj, i )
+        Kit_TruthOrPhase( uCare, uCare, (unsigned *)Aig_Regular(pObj)->pData, Vec_PtrSize(vSupp), 0, Aig_IsComplement(pObj) );
+    // try cofactoring each variable in both polarities
+    vCofs = Vec_PtrAlloc( 10 );
+    uCof0  = (unsigned *)Vec_PtrEntry( vTrNode, Vec_PtrSize(vNodes)+1 );
+    uCof1  = (unsigned *)Vec_PtrEntry( vTrNode, Vec_PtrSize(vNodes)+2 );
+    uCare0 = (unsigned *)Vec_PtrEntry( vTrNode, Vec_PtrSize(vNodes)+3 );
+    uCare1 = (unsigned *)Vec_PtrEntry( vTrNode, Vec_PtrSize(vNodes)+4 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSupp, pObj, i )
+    {
+        Kit_TruthCofactor0New( uCof0, uFunc, Vec_PtrSize(vSupp), i );
+        Kit_TruthCofactor1New( uCof1, uFunc, Vec_PtrSize(vSupp), i );
+        Kit_TruthCofactor0New( uCare0, uCare, Vec_PtrSize(vSupp), i );
+        Kit_TruthCofactor1New( uCare1, uCare, Vec_PtrSize(vSupp), i );
+        if ( Kit_TruthIsEqualWithCare( uCof0, uCof1, uCare1, Vec_PtrSize(vSupp) ) )
+            Vec_PtrPush( vCofs, Aig_Not(pObj) );
+        else if ( Kit_TruthIsEqualWithCare( uCof0, uCof1, uCare0, Vec_PtrSize(vSupp) ) )
+            Vec_PtrPush( vCofs, pObj );
+    }
+    Vec_PtrFree( vTrNode );
+    Vec_PtrFree( vTrSupp );
+    return vCofs;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the new node after cofactoring.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_SuppMinReconstruct( Aig_Man_t * p, Vec_Ptr_t * vCofs, Vec_Ptr_t * vNodes, Vec_Ptr_t * vSupp )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    // set the value of the support variables
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSupp, pObj, i )
+        assert( !Aig_IsComplement(pObj) );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSupp, pObj, i )
+        pObj->pData = pObj;
+    // set the value of the cofactoring variables
+    Vec_PtrForEachEntry( Aig_Obj_t *, vCofs, pObj, i )
+        Aig_Regular(pObj)->pData = Aig_NotCond( Aig_ManConst1(p), Aig_IsComplement(pObj) );
+    // reconstruct the node
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    return (Aig_Obj_t *)pObj->pData;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if all nodes of vOrGate are in vSupp.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_SuppMinGateIsInSupport( Aig_Man_t * p, Vec_Ptr_t * vOrGate, Vec_Ptr_t * vSupp )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManIncrementTravId( p );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSupp, pObj, i )
+        Aig_ObjSetTravIdCurrent( p, pObj );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vOrGate, pObj, i )
+        if ( !Aig_ObjIsTravIdCurrent( p, Aig_Regular(pObj) ) )
+            return 0;
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects fanins of the marked nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_SuppMinCollectSupport( Aig_Man_t * p, Vec_Ptr_t * vNodes )
+{
+    Vec_Ptr_t * vSupp;
+    Aig_Obj_t * pObj, * pFanin;
+    int i;
+    vSupp = Vec_PtrAlloc( 4 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        assert( Aig_ObjIsTravIdCurrent(p, pObj) );
+        assert( Aig_ObjIsNode(pObj) );
+        pFanin = Aig_ObjFanin0( pObj );
+        if ( !Aig_ObjIsTravIdCurrent(p, pFanin) )
+        {
+            Aig_ObjSetTravIdCurrent( p, pFanin );
+            Vec_PtrPush( vSupp, pFanin );
+        }
+        pFanin = Aig_ObjFanin1( pObj );
+        if ( !Aig_ObjIsTravIdCurrent(p, pFanin) )
+        {
+            Aig_ObjSetTravIdCurrent( p, pFanin );
+            Vec_PtrPush( vSupp, pFanin );
+        }
+    }
+    return vSupp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the nodes in the cone with current trav ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_SuppMinCollectCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) // visited
+        return;
+    if ( !Aig_ObjIsTravIdPrevious( p, pObj ) ) // not visited, but outside
+        return;
+    assert( Aig_ObjIsTravIdPrevious(p, pObj) ); // not visited, inside
+    assert( Aig_ObjIsNode(pObj) );
+    Aig_ObjSetTravIdCurrent( p, pObj );
+    Aig_SuppMinCollectCone_rec( p, Aig_ObjFanin0(pObj), vNodes );
+    Aig_SuppMinCollectCone_rec( p, Aig_ObjFanin1(pObj), vNodes );
+    Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes with the current trav ID rooted in the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_SuppMinCollectCone( Aig_Man_t * p, Aig_Obj_t * pRoot )
+{
+    Vec_Ptr_t * vNodes;
+    assert( !Aig_IsComplement(pRoot) ); 
+//    assert( Aig_ObjIsTravIdCurrent( p, pRoot ) );
+    vNodes = Vec_PtrAlloc( 4 );
+    Aig_ManIncrementTravId( p );
+    Aig_SuppMinCollectCone_rec( p, Aig_Regular(pRoot), vNodes );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the nodes in the cone with current trav ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_SuppMinHighlightCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    int RetValue;
+    if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) // visited, marks there
+        return 1;
+    if ( Aig_ObjIsTravIdPrevious( p, pObj ) ) // visited, no marks there
+        return 0;
+    Aig_ObjSetTravIdPrevious( p, pObj );
+    if ( Aig_ObjIsCi(pObj) )
+        return 0;
+    RetValue = Aig_SuppMinHighlightCone_rec( p, Aig_ObjFanin0(pObj) ) |
+               Aig_SuppMinHighlightCone_rec( p, Aig_ObjFanin1(pObj) );
+//    printf( "%d %d\n", Aig_ObjId(pObj), RetValue );
+    if ( RetValue )
+        Aig_ObjSetTravIdCurrent( p, pObj );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the nodes in the cone with current trav ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_SuppMinHighlightCone( Aig_Man_t * p, Aig_Obj_t * pRoot, Vec_Ptr_t * vOrGate )
+{
+    Aig_Obj_t * pLeaf;
+    int i, RetValue;
+    assert( !Aig_IsComplement(pRoot) );
+    Aig_ManIncrementTravId( p );
+    Aig_ManIncrementTravId( p );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vOrGate, pLeaf, i )
+        Aig_ObjSetTravIdCurrent( p, Aig_Regular(pLeaf) );
+    RetValue = Aig_SuppMinHighlightCone_rec( p, pRoot );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vOrGate, pLeaf, i )
+        Aig_ObjSetTravIdPrevious( p, Aig_Regular(pLeaf) );
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_SuppMinCollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper )
+{
+    // if the new node is complemented or a PI, another gate begins
+    if ( Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) ) // || (Aig_ObjRefs(pObj) > 1) )
+    {
+        Vec_PtrPushUnique( vSuper, Aig_Not(pObj) );
+        return;
+    }
+    // go through the branches
+    Aig_SuppMinCollectSuper_rec( Aig_ObjChild0(pObj), vSuper );
+    Aig_SuppMinCollectSuper_rec( Aig_ObjChild1(pObj), vSuper );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_SuppMinCollectSuper( Aig_Obj_t * pObj )
+{
+    Vec_Ptr_t * vSuper;
+    assert( !Aig_IsComplement(pObj) );
+    assert( !Aig_ObjIsCi(pObj) );
+    vSuper = Vec_PtrAlloc( 4 );
+    Aig_SuppMinCollectSuper_rec( Aig_ObjChild0(pObj), vSuper );
+    Aig_SuppMinCollectSuper_rec( Aig_ObjChild1(pObj), vSuper );
+    return vSuper;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the result of support minimization.]
+
+  Description [Returns internal AIG node that is equal to pFunc under 
+  assignment pCond == 1, or NULL if there is no such node. status is 
+  -1 if condition is not OR; 
+  -2 if cone is too large or no cone; 
+  -3 if no support reduction is possible.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_ManSupportMinimization( Aig_Man_t * p, Aig_Obj_t * pCond, Aig_Obj_t * pFunc, int * pStatus )
+{
+    int nSuppMax = 16;
+    Vec_Ptr_t * vOrGate, * vNodes, * vSupp, * vCofs;
+    Aig_Obj_t * pResult;
+    int RetValue;
+    *pStatus = 0;
+    // if pCond is not OR
+    if ( !Aig_IsComplement(pCond) || Aig_ObjIsCi(Aig_Regular(pCond)) || Aig_ObjIsConst1(Aig_Regular(pCond)) )
+    {
+        *pStatus = -1;
+        return NULL;
+    }
+    // if pFunc is not a node
+    if ( !Aig_ObjIsNode(Aig_Regular(pFunc)) )
+    {
+        *pStatus = -2;
+        return NULL;
+    }
+    // collect the multi-input OR gate rooted in the condition
+    vOrGate = Aig_SuppMinCollectSuper( Aig_Regular(pCond) );
+    if ( Vec_PtrSize(vOrGate) > nSuppMax )
+    {
+        Vec_PtrFree( vOrGate );
+        *pStatus = -2;
+        return NULL;
+    }
+    // highlight the cone limited by these gates
+    RetValue = Aig_SuppMinHighlightCone( p, Aig_Regular(pFunc), vOrGate );
+    if ( RetValue == 0 ) // no overlap
+    {
+        Vec_PtrFree( vOrGate );
+        *pStatus = -2;
+        return NULL;
+    }
+    // collect the cone rooted in pFunc limited by vOrGate
+    vNodes = Aig_SuppMinCollectCone( p, Aig_Regular(pFunc) );
+    // collect the support nodes reachable from the cone
+    vSupp = Aig_SuppMinCollectSupport( p, vNodes );
+    if ( Vec_PtrSize(vSupp) > nSuppMax )
+    {
+        Vec_PtrFree( vOrGate );
+        Vec_PtrFree( vNodes );
+        Vec_PtrFree( vSupp );
+        *pStatus = -2;
+        return NULL;
+    }
+    // check if all nodes belonging to OR gate are included in the support
+    // (if this is not the case, don't-care minimization is not possible)
+    if ( !Aig_SuppMinGateIsInSupport( p, vOrGate, vSupp ) )
+    {
+        Vec_PtrFree( vOrGate );
+        Vec_PtrFree( vNodes );
+        Vec_PtrFree( vSupp );
+        *pStatus = -3;
+        return NULL;
+    }
+    // create truth tables of all nodes and find the maximal number
+    // of support varialbles that can be replaced by constants
+    vCofs = Aig_SuppMinPerform( p, vOrGate, vNodes, vSupp );
+    if ( Vec_PtrSize(vCofs) == 0 )
+    {
+        Vec_PtrFree( vCofs );
+        Vec_PtrFree( vOrGate );
+        Vec_PtrFree( vNodes );
+        Vec_PtrFree( vSupp );
+        *pStatus = -3;
+        return NULL;
+    }
+    // reconstruct the cone
+    pResult = Aig_SuppMinReconstruct( p, vCofs, vNodes, vSupp );
+    pResult = Aig_NotCond( pResult, Aig_IsComplement(pFunc) );
+    Vec_PtrFree( vCofs );
+    Vec_PtrFree( vOrGate );
+    Vec_PtrFree( vNodes );
+    Vec_PtrFree( vSupp );
+    return pResult;
+}
+/**Function*************************************************************
+
+  Synopsis    [Testing procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManSupportMinimizationTest()
+{
+    Aig_Man_t * p;
+    Aig_Obj_t * pFunc, * pCond, * pRes;
+    int i, Status;
+    p = Aig_ManStart( 100 );
+    for ( i = 0; i < 5; i++ )
+        Aig_IthVar(p,i);
+    pFunc = Aig_Mux( p, Aig_IthVar(p,3), Aig_IthVar(p,1), Aig_IthVar(p,0) );
+    pFunc = Aig_Mux( p, Aig_IthVar(p,4), Aig_IthVar(p,2), pFunc );
+    pCond = Aig_Or( p, Aig_IthVar(p,3), Aig_IthVar(p,4) );
+    pRes  = Aig_ManSupportMinimization( p, pCond, pFunc, &Status );
+    assert( Status == 0 );
+
+    Aig_ObjPrint( p, Aig_Regular(pRes) );                printf( "\n" );
+    Aig_ObjPrint( p, Aig_ObjFanin0(Aig_Regular(pRes)) ); printf( "\n" );
+    Aig_ObjPrint( p, Aig_ObjFanin1(Aig_Regular(pRes)) ); printf( "\n" );
+
+    Aig_ManStop( p );
+}
+void Aig_ManSupportMinimizationTest2()
+{
+    Aig_Man_t * p;
+    Aig_Obj_t * node09, * node10, * node11, * node12, * node13, * pRes;
+    int i, Status;
+    p = Aig_ManStart( 100 );
+    for ( i = 0; i < 3; i++ )
+        Aig_IthVar(p,i);
+
+    node09 = Aig_And( p, Aig_IthVar(p,0), Aig_Not(Aig_IthVar(p,1)) );
+    node10 = Aig_And( p, Aig_Not(node09), Aig_Not(Aig_IthVar(p,2)) );
+    node11 = Aig_And( p, node10, Aig_IthVar(p,1) );
+
+    node12 = Aig_Or( p, Aig_IthVar(p,1), Aig_IthVar(p,2) );
+    node13 = Aig_Or( p, node12, Aig_IthVar(p,0) );
+
+    pRes  = Aig_ManSupportMinimization( p, node13, node11, &Status );
+    assert( Status == 0 );
+
+    printf( "Compl = %d  ", Aig_IsComplement(pRes) );
+    Aig_ObjPrint( p, Aig_Regular(pRes) );                printf( "\n" );
+    if ( Aig_ObjIsNode(Aig_Regular(pRes)) )
+    {
+        Aig_ObjPrint( p, Aig_ObjFanin0(Aig_Regular(pRes)) ); printf( "\n" );
+        Aig_ObjPrint( p, Aig_ObjFanin1(Aig_Regular(pRes)) ); printf( "\n" );
+    }
+
+    Aig_ManStop( p );
+}
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigFanout.c b/abc-build/src/aig/aig/aigFanout.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigFanout.c
@@ -0,0 +1,194 @@
+/**CFile****************************************************************
+
+  FileName    [aigFanout.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Fanout manipulation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigFanout.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+// 0: first iFan
+// 1: prev iFan0
+// 2: prev iFan1
+// 3: next iFan0
+// 4: next iFan1
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int   Aig_FanoutCreate( int FanId, int Num )    { assert( Num < 2 ); return (FanId << 1) | Num;   } 
+static inline int * Aig_FanoutObj( int * pData, int ObjId )   { return pData + 5*ObjId;                         }
+static inline int * Aig_FanoutPrev( int * pData, int iFan )   { return pData + 5*(iFan >> 1) + 1 + (iFan & 1);  }
+static inline int * Aig_FanoutNext( int * pData, int iFan )   { return pData + 5*(iFan >> 1) + 3 + (iFan & 1);  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Create fanout for all objects in the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManFanoutStart( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    assert( Aig_ManBufNum(p) == 0 );
+    // allocate fanout datastructure
+    assert( p->pFanData == NULL );
+    p->nFansAlloc = 2 * Aig_ManObjNumMax(p);
+    if ( p->nFansAlloc < (1<<12) )
+        p->nFansAlloc = (1<<12);
+    p->pFanData = ABC_ALLOC( int, 5 * p->nFansAlloc );
+    memset( p->pFanData, 0, sizeof(int) * 5 * p->nFansAlloc );
+    // add fanouts for all objects
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( Aig_ObjChild0(pObj) )
+            Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj );
+        if ( Aig_ObjChild1(pObj) )
+            Aig_ObjAddFanout( p, Aig_ObjFanin1(pObj), pObj );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes fanout for all objects in the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManFanoutStop( Aig_Man_t * p )
+{
+    assert( p->pFanData != NULL );
+    ABC_FREE( p->pFanData );
+    p->nFansAlloc = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds fanout (pFanout) of node (pObj).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjAddFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout )
+{
+    int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext;
+    assert( p->pFanData );
+    assert( !Aig_IsComplement(pObj) && !Aig_IsComplement(pFanout) );
+    assert( pFanout->Id > 0 );
+    if ( pObj->Id >= p->nFansAlloc || pFanout->Id >= p->nFansAlloc )
+    {
+        int nFansAlloc = 2 * Abc_MaxInt( pObj->Id, pFanout->Id ); 
+        p->pFanData = ABC_REALLOC( int, p->pFanData, 5 * nFansAlloc );
+        memset( p->pFanData + 5 * p->nFansAlloc, 0, sizeof(int) * 5 * (nFansAlloc - p->nFansAlloc) );
+        p->nFansAlloc = nFansAlloc;
+    }
+    assert( pObj->Id < p->nFansAlloc && pFanout->Id < p->nFansAlloc );
+    iFan   = Aig_FanoutCreate( pFanout->Id, Aig_ObjWhatFanin(pFanout, pObj) );
+    pPrevC = Aig_FanoutPrev( p->pFanData, iFan );
+    pNextC = Aig_FanoutNext( p->pFanData, iFan );
+    pFirst = Aig_FanoutObj( p->pFanData, pObj->Id );
+    if ( *pFirst == 0 )
+    {
+        *pFirst = iFan;
+        *pPrevC = iFan;
+        *pNextC = iFan;
+    }
+    else
+    {
+        pPrev = Aig_FanoutPrev( p->pFanData, *pFirst );
+        pNext = Aig_FanoutNext( p->pFanData, *pPrev );
+        assert( *pNext == *pFirst );
+        *pPrevC = *pPrev;
+        *pNextC = *pFirst;
+        *pPrev  = iFan;
+        *pNext  = iFan;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes fanout (pFanout) of node (pObj).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjRemoveFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout )
+{
+    int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext;
+    assert( p->pFanData && pObj->Id < p->nFansAlloc && pFanout->Id < p->nFansAlloc );
+    assert( !Aig_IsComplement(pObj) && !Aig_IsComplement(pFanout) );
+    assert( pFanout->Id > 0 );
+    iFan   = Aig_FanoutCreate( pFanout->Id, Aig_ObjWhatFanin(pFanout, pObj) );
+    pPrevC = Aig_FanoutPrev( p->pFanData, iFan );
+    pNextC = Aig_FanoutNext( p->pFanData, iFan );
+    pPrev  = Aig_FanoutPrev( p->pFanData, *pNextC );
+    pNext  = Aig_FanoutNext( p->pFanData, *pPrevC );
+    assert( *pPrev == iFan );
+    assert( *pNext == iFan );
+    pFirst = Aig_FanoutObj( p->pFanData, pObj->Id );
+    assert( *pFirst > 0 );
+    if ( *pFirst == iFan )
+    {
+        if ( *pNextC == iFan )
+        {
+            *pFirst = 0;
+            *pPrev  = 0;
+            *pNext  = 0;
+            *pPrevC = 0;
+            *pNextC = 0;
+            return;
+        }
+        *pFirst = *pNextC;
+    }
+    *pPrev  = *pPrevC;
+    *pNext  = *pNextC;
+    *pPrevC = 0;
+    *pNextC = 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigFrames.c b/abc-build/src/aig/aig/aigFrames.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigFrames.c
@@ -0,0 +1,140 @@
+/**CFile****************************************************************
+
+  FileName    [aigFrames.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Performs timeframe expansion of the AIG.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigFrames.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline Aig_Obj_t * Aig_ObjFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i )                       { return pObjMap[nFs*pObj->Id + i];  }
+static inline void        Aig_ObjSetFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { pObjMap[nFs*pObj->Id + i] = pNode; }
+
+static inline Aig_Obj_t * Aig_ObjChild0Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin0(pObj)? Aig_NotCond(Aig_ObjFrames(pObjMap,nFs,Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL;  }
+static inline Aig_Obj_t * Aig_ObjChild1Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin1(pObj)? Aig_NotCond(Aig_ObjFrames(pObjMap,nFs,Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL;  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs timeframe expansion of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManFrames( Aig_Man_t * pAig, int nFs, int fInit, int fOuts, int fRegs, int fEnlarge, Aig_Obj_t *** ppObjMap )
+{
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew;
+    Aig_Obj_t ** pObjMap;
+    int i, f;
+
+    // create mapping for the frames nodes
+    pObjMap  = ABC_ALLOC( Aig_Obj_t *, nFs * Aig_ManObjNumMax(pAig) );
+    memset( pObjMap, 0, sizeof(Aig_Obj_t *) * nFs * Aig_ManObjNumMax(pAig) );
+
+    // start the fraig package
+    pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFs );
+    pFrames->pName = Abc_UtilStrsav( pAig->pName );
+    pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec );
+    // map constant nodes
+    for ( f = 0; f < nFs; f++ )
+        Aig_ObjSetFrames( pObjMap, nFs, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) );
+    // create PI nodes for the frames
+    for ( f = 0; f < nFs; f++ )
+        Aig_ManForEachPiSeq( pAig, pObj, i )
+            Aig_ObjSetFrames( pObjMap, nFs, pObj, f, Aig_ObjCreateCi(pFrames) );
+    // set initial state for the latches
+    if ( fInit )
+    {
+        Aig_ManForEachLoSeq( pAig, pObj, i )
+            Aig_ObjSetFrames( pObjMap, nFs, pObj, 0, Aig_ManConst0(pFrames) );
+    }
+    else 
+    {
+        Aig_ManForEachLoSeq( pAig, pObj, i )
+            Aig_ObjSetFrames( pObjMap, nFs, pObj, 0, Aig_ObjCreateCi(pFrames) );
+    }
+
+    // add timeframes
+    for ( f = 0; f < nFs; f++ )
+    {
+//        printf( "Frame = %d.\n", f );
+        // add internal nodes of this frame
+        Aig_ManForEachNode( pAig, pObj, i )
+        {
+//            Aig_Obj_t * pFanin0 = Aig_ObjChild0Frames(pObjMap,nFs,pObj,f);
+//            Aig_Obj_t * pFanin1 = Aig_ObjChild1Frames(pObjMap,nFs,pObj,f);
+//            printf( "Node = %3d.  Fanin0 = %3d. Fanin1 = %3d.\n", pObj->Id, Aig_Regular(pFanin0)->Id, Aig_Regular(pFanin1)->Id );
+            pObjNew = Aig_And( pFrames, Aig_ObjChild0Frames(pObjMap,nFs,pObj,f), Aig_ObjChild1Frames(pObjMap,nFs,pObj,f) );
+            Aig_ObjSetFrames( pObjMap, nFs, pObj, f, pObjNew );
+        }
+        // set the latch inputs and copy them into the latch outputs of the next frame
+        Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i )
+        {
+            pObjNew = Aig_ObjChild0Frames(pObjMap,nFs,pObjLi,f);
+            if ( f < nFs - 1 )
+                Aig_ObjSetFrames( pObjMap, nFs, pObjLo, f+1, pObjNew );
+        }
+    }
+    if ( fOuts )
+    {
+        for ( f = fEnlarge?nFs-1:0; f < nFs; f++ )
+            Aig_ManForEachPoSeq( pAig, pObj, i )
+            {
+                pObjNew = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Frames(pObjMap,nFs,pObj,f) );
+                Aig_ObjSetFrames( pObjMap, nFs, pObj, f, pObjNew );
+            }
+    }
+    if ( fRegs )
+    {
+        pFrames->nRegs = pAig->nRegs;
+        Aig_ManForEachLiSeq( pAig, pObj, i )
+        {
+            pObjNew = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Frames(pObjMap,nFs,pObj,fEnlarge?0:nFs-1) );
+            Aig_ObjSetFrames( pObjMap, nFs, pObj, nFs-1, pObjNew );
+        }
+        Aig_ManSetRegNum( pFrames, Aig_ManRegNum(pAig) );
+    }
+    Aig_ManCleanup( pFrames );
+    // return the new manager
+    if ( ppObjMap )
+        *ppObjMap = pObjMap;
+    else
+        ABC_FREE( pObjMap );
+    return pFrames;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigInter.c b/abc-build/src/aig/aig/aigInter.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigInter.c
@@ -0,0 +1,301 @@
+/**CFile****************************************************************
+
+  FileName    [aigInter.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Interpolate two AIGs.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigInter.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satStore.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern abctime timeCnf;
+extern abctime timeSat;
+extern abctime timeInt;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManInterFast( Aig_Man_t * pManOn, Aig_Man_t * pManOff, int fVerbose )
+{
+    sat_solver * pSat;
+    Cnf_Dat_t * pCnfOn, * pCnfOff;
+    Aig_Obj_t * pObj, * pObj2;
+    int Lits[3], status, i;
+//    abctime clk = Abc_Clock();
+
+    assert( Aig_ManCiNum(pManOn) == Aig_ManCiNum(pManOff) );
+    assert( Aig_ManCoNum(pManOn) == Aig_ManCoNum(pManOff) );
+
+    // derive CNFs
+    pManOn->nRegs = Aig_ManCoNum(pManOn);
+    pCnfOn  = Cnf_Derive( pManOn, Aig_ManCoNum(pManOn) );
+    pManOn->nRegs = 0;
+
+    pManOff->nRegs = Aig_ManCoNum(pManOn);
+    pCnfOff = Cnf_Derive( pManOff, Aig_ManCoNum(pManOff) );
+    pManOff->nRegs = 0;
+
+//    pCnfOn  = Cnf_DeriveSimple( pManOn, Aig_ManCoNum(pManOn) );
+//    pCnfOff = Cnf_DeriveSimple( pManOff, Aig_ManCoNum(pManOn) );
+    Cnf_DataLift( pCnfOff, pCnfOn->nVars );
+
+    // start the solver
+    pSat = sat_solver_new();
+    sat_solver_setnvars( pSat, pCnfOn->nVars + pCnfOff->nVars );
+
+    // add clauses of A
+    for ( i = 0; i < pCnfOn->nClauses; i++ )
+    {
+        if ( !sat_solver_addclause( pSat, pCnfOn->pClauses[i], pCnfOn->pClauses[i+1] ) )
+        {
+            Cnf_DataFree( pCnfOn );
+            Cnf_DataFree( pCnfOff );
+            sat_solver_delete( pSat );
+            return;
+        }
+    }
+
+    // add clauses of B
+    for ( i = 0; i < pCnfOff->nClauses; i++ )
+    {
+        if ( !sat_solver_addclause( pSat, pCnfOff->pClauses[i], pCnfOff->pClauses[i+1] ) )
+        {
+            Cnf_DataFree( pCnfOn );
+            Cnf_DataFree( pCnfOff );
+            sat_solver_delete( pSat );
+            return;
+        }
+    }
+
+    // add PI clauses
+    // collect the common variables
+    Aig_ManForEachCi( pManOn, pObj, i )
+    {
+        pObj2 = Aig_ManCi( pManOff, i );
+
+        Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 0 );
+        Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 1 );
+        if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+            assert( 0 );
+        Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 1 );
+        Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 0 );
+        if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+            assert( 0 );
+    }
+    status = sat_solver_simplify( pSat );
+    assert( status != 0 );
+
+    // solve incremental SAT problems
+    Aig_ManForEachCo( pManOn, pObj, i )
+    {
+        pObj2 = Aig_ManCo( pManOff, i );
+
+        Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 0 );
+        Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 0 );
+        status = sat_solver_solve( pSat, Lits, Lits+2, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        if ( status != l_False )
+            printf( "The incremental SAT problem is not UNSAT.\n" );
+    }
+    Cnf_DataFree( pCnfOn );
+    Cnf_DataFree( pCnfOff );
+    sat_solver_delete( pSat );
+//    ABC_PRT( "Fast interpolation time", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManInter( Aig_Man_t * pManOn, Aig_Man_t * pManOff, int fRelation, int fVerbose )
+{
+    void * pSatCnf = NULL;
+    Inta_Man_t * pManInter; 
+    Aig_Man_t * pRes;
+    sat_solver * pSat;
+    Cnf_Dat_t * pCnfOn, * pCnfOff;
+    Vec_Int_t * vVarsAB;
+    Aig_Obj_t * pObj, * pObj2;
+    int Lits[3], status, i;
+    abctime clk;
+    int iLast = -1; // Suppress "might be used uninitialized"
+
+    assert( Aig_ManCiNum(pManOn) == Aig_ManCiNum(pManOff) );
+
+clk = Abc_Clock();
+    // derive CNFs
+//    pCnfOn  = Cnf_Derive( pManOn, 0 );
+//    pCnfOff = Cnf_Derive( pManOff, 0 );
+    pCnfOn  = Cnf_DeriveSimple( pManOn, 0 );
+    pCnfOff = Cnf_DeriveSimple( pManOff, 0 );
+    Cnf_DataLift( pCnfOff, pCnfOn->nVars );
+timeCnf += Abc_Clock() - clk;
+
+clk = Abc_Clock();
+    // start the solver
+    pSat = sat_solver_new();
+    sat_solver_store_alloc( pSat );
+    sat_solver_setnvars( pSat, pCnfOn->nVars + pCnfOff->nVars );
+
+    // add clauses of A
+    for ( i = 0; i < pCnfOn->nClauses; i++ )
+    {
+        if ( !sat_solver_addclause( pSat, pCnfOn->pClauses[i], pCnfOn->pClauses[i+1] ) )
+        {
+            Cnf_DataFree( pCnfOn );
+            Cnf_DataFree( pCnfOff );
+            sat_solver_delete( pSat );
+            return NULL;
+        }
+    }
+    sat_solver_store_mark_clauses_a( pSat );
+
+    // update the last clause
+    if ( fRelation )
+    {
+        extern int sat_solver_store_change_last( sat_solver * pSat );
+        iLast = sat_solver_store_change_last( pSat );
+    }
+
+    // add clauses of B
+    for ( i = 0; i < pCnfOff->nClauses; i++ )
+    {
+        if ( !sat_solver_addclause( pSat, pCnfOff->pClauses[i], pCnfOff->pClauses[i+1] ) )
+        {
+            Cnf_DataFree( pCnfOn );
+            Cnf_DataFree( pCnfOff );
+            sat_solver_delete( pSat );
+            return NULL;
+        }
+    }
+
+    // add PI clauses
+    // collect the common variables
+    vVarsAB = Vec_IntAlloc( Aig_ManCiNum(pManOn) );
+    if ( fRelation )
+        Vec_IntPush( vVarsAB, iLast );
+
+    Aig_ManForEachCi( pManOn, pObj, i )
+    {
+        Vec_IntPush( vVarsAB, pCnfOn->pVarNums[pObj->Id] );
+        pObj2 = Aig_ManCi( pManOff, i );
+
+        Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 0 );
+        Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 1 );
+        if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+            assert( 0 );
+        Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 1 );
+        Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 0 );
+        if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+            assert( 0 );
+    }
+    Cnf_DataFree( pCnfOn );
+    Cnf_DataFree( pCnfOff );
+    sat_solver_store_mark_roots( pSat );
+
+/*
+    status = sat_solver_simplify(pSat);
+    if ( status == 0 )
+    {
+        Vec_IntFree( vVarsAB );
+        Cnf_DataFree( pCnfOn );
+        Cnf_DataFree( pCnfOff );
+        sat_solver_delete( pSat );
+        return NULL;
+    }
+*/
+
+    // solve the problem
+    status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+timeSat += Abc_Clock() - clk;
+    if ( status == l_False )
+    {
+        pSatCnf = sat_solver_store_release( pSat );
+//        printf( "unsat\n" );
+    }
+    else if ( status == l_True )
+    {
+//        printf( "sat\n" );
+    }
+    else
+    {
+//        printf( "undef\n" );
+    }
+    sat_solver_delete( pSat );
+    if ( pSatCnf == NULL )
+    {
+        printf( "The SAT problem is not unsat.\n" );
+        Vec_IntFree( vVarsAB );
+        return NULL;
+    }
+
+    // create the resulting manager
+clk = Abc_Clock();
+    pManInter = Inta_ManAlloc();
+    pRes = (Aig_Man_t *)Inta_ManInterpolate( pManInter, (Sto_Man_t *)pSatCnf, 0, vVarsAB, fVerbose );
+    Inta_ManFree( pManInter );
+timeInt += Abc_Clock() - clk;
+/*
+    // test UNSAT core computation
+    {
+        Intp_Man_t * pManProof;
+        Vec_Int_t * vCore;
+        pManProof = Intp_ManAlloc();
+        vCore = Intp_ManUnsatCore( pManProof, pSatCnf, 0 );
+        Intp_ManFree( pManProof );
+        Vec_IntFree( vCore );
+    }
+*/
+    Vec_IntFree( vVarsAB );
+    Sto_ManFree( (Sto_Man_t *)pSatCnf );
+
+//    Ioa_WriteAiger( pRes, "inter2.aig", 0, 0 );
+    return pRes;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigJust.c b/abc-build/src/aig/aig/aigJust.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigJust.c
@@ -0,0 +1,316 @@
+/**CFile****************************************************************
+ 
+  FileName    [aigJust.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Justification of node values.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigJust.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define AIG_VAL0  1
+#define AIG_VAL1  2
+#define AIG_VALX  3
+
+// storing ternary values
+static inline int Aig_ObjSetTerValue( Aig_Obj_t * pNode, int Value )
+{
+    assert( Value );
+    pNode->fMarkA = (Value & 1);
+    pNode->fMarkB = ((Value >> 1) & 1);
+    return Value;
+}
+static inline int Aig_ObjGetTerValue( Aig_Obj_t * pNode )
+{
+    return (pNode->fMarkB << 1) | pNode->fMarkA;
+}
+
+// working with ternary values
+static inline int Aig_ObjNotTerValue( int Value )
+{
+    if ( Value == AIG_VAL1 )
+        return AIG_VAL0;
+    if ( Value == AIG_VAL0 )
+        return AIG_VAL1;
+    return AIG_VALX;
+}
+static inline int Aig_ObjAndTerValue( int Value0, int Value1 )
+{
+    if ( Value0 == AIG_VAL0 || Value1 == AIG_VAL0 )
+        return AIG_VAL0;
+    if ( Value0 == AIG_VAL1 && Value1 == AIG_VAL1 )
+        return AIG_VAL1;
+    return AIG_VALX;
+}
+static inline int Aig_ObjNotCondTerValue( int Value, int Cond )
+{
+    return Cond ? Aig_ObjNotTerValue( Value ) : Value;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns value (0 or 1) or X if unassigned.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_ObjSatValue( Aig_Man_t * pAig, Aig_Obj_t * pNode, int fCompl )
+{
+    if ( Aig_ObjIsTravIdCurrent(pAig, pNode) )
+        return (pNode->fMarkA ^ fCompl) ? AIG_VAL1 : AIG_VAL0;
+    return AIG_VALX;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively searched for a satisfying assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_NtkFindSatAssign_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode, int Value, Vec_Int_t * vSuppLits, int Heur )
+{
+    int Value0, Value1;
+//    ++Heur;
+    if ( Aig_ObjIsConst1(pNode) )
+        return 1;
+    if ( Aig_ObjIsTravIdCurrent(pAig, pNode) )
+        return ((int)pNode->fMarkA == Value);
+    Aig_ObjSetTravIdCurrent(pAig, pNode);
+    pNode->fMarkA = Value;
+    if ( Aig_ObjIsCi(pNode) )
+    {
+//        if ( Aig_ObjId(pNode) % 1000 == 0 )
+//            Value ^= 1;
+        if ( vSuppLits )
+            Vec_IntPush( vSuppLits, Abc_Var2Lit( Aig_ObjCioId(pNode), !Value ) );
+        return 1;
+    }
+    assert( Aig_ObjIsNode(pNode) );
+    // propagation
+    if ( Value ) 
+    {
+        if ( !Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), !Aig_ObjFaninC0(pNode), vSuppLits, Heur) )
+            return 0;
+        return Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), !Aig_ObjFaninC1(pNode), vSuppLits, Heur);
+    }
+    // justification
+    Value0 = Aig_ObjSatValue( pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode) );
+    if ( Value0 == AIG_VAL0 )
+        return 1;
+    Value1 = Aig_ObjSatValue( pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode) );
+    if ( Value1 == AIG_VAL0 )
+        return 1;
+    if ( Value0 == AIG_VAL1 && Value1 == AIG_VAL1 )
+        return 0;
+    if ( Value0 == AIG_VAL1 )
+        return Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode), vSuppLits, Heur);
+    if ( Value1 == AIG_VAL1 )
+        return Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode), vSuppLits, Heur);
+    assert( Value0 == AIG_VALX && Value1 == AIG_VALX );
+    // decision making
+//    if ( rand() % 10 == Heur )
+//    if ( Aig_ObjId(pNode) % 8 == Heur )
+    if ( ++Heur % 8 == 0 )
+        return Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode), vSuppLits, Heur);
+    else
+        return Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode), vSuppLits, Heur);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if SAT assignment is found; 0 otherwise.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjFindSatAssign( Aig_Man_t * pAig, Aig_Obj_t * pNode, int Value, Vec_Int_t * vSuppLits )
+{
+    int i;
+    if ( Aig_ObjIsCo(pNode) )
+        return Aig_ObjFindSatAssign( pAig, Aig_ObjFanin0(pNode), Value ^ Aig_ObjFaninC0(pNode), vSuppLits );
+    for ( i = 0; i < 8; i++ )
+    {
+        Vec_IntClear( vSuppLits );
+        Aig_ManIncrementTravId( pAig );
+        if ( Aig_NtkFindSatAssign_rec( pAig, pNode, Value, vSuppLits, i ) )
+            return 1;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjTerSimulate_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode )
+{
+    int Value0, Value1;
+    if ( Aig_ObjIsConst1(pNode) )
+        return AIG_VAL1;
+    if ( Aig_ObjIsTravIdCurrent(pAig, pNode) )
+        return Aig_ObjGetTerValue( pNode );
+    Aig_ObjSetTravIdCurrent( pAig, pNode );
+    if ( Aig_ObjIsCi(pNode) )
+        return Aig_ObjSetTerValue( pNode, AIG_VALX );
+    Value0 = Aig_ObjNotCondTerValue( Aig_ObjTerSimulate_rec(pAig, Aig_ObjFanin0(pNode)), Aig_ObjFaninC0(pNode) );
+    if ( Aig_ObjIsCo(pNode) || Value0 == AIG_VAL0 )
+        return Aig_ObjSetTerValue( pNode, Value0 );
+    assert( Aig_ObjIsNode(pNode) );
+    Value1 = Aig_ObjNotCondTerValue( Aig_ObjTerSimulate_rec(pAig, Aig_ObjFanin1(pNode)), Aig_ObjFaninC1(pNode) );
+    return Aig_ObjSetTerValue( pNode, Aig_ObjAndTerValue(Value0, Value1) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns value of the object under input assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjTerSimulate( Aig_Man_t * pAig, Aig_Obj_t * pNode, Vec_Int_t * vSuppLits )
+{
+    Aig_Obj_t * pObj;
+    int i, Entry;
+    Aig_ManIncrementTravId( pAig );
+    Vec_IntForEachEntry( vSuppLits, Entry, i )
+    {
+        pObj = Aig_ManCi( pAig, Abc_Lit2Var(Entry) );
+        Aig_ObjSetTerValue( pObj, Abc_LitIsCompl(Entry) ? AIG_VAL0 : AIG_VAL1 );
+        Aig_ObjSetTravIdCurrent( pAig, pObj );
+//printf( "%d ", Entry );
+    }
+//printf( "\n" );
+    return Aig_ObjTerSimulate_rec( pAig, pNode );
+}
+
+
+typedef struct Aig_ManPack_t_ Aig_ManPack_t;
+extern Aig_ManPack_t *        Aig_ManPackStart( Aig_Man_t * pAig );
+extern void                   Aig_ManPackStop( Aig_ManPack_t * p );
+extern void                   Aig_ManPackAddPattern( Aig_ManPack_t * p, Vec_Int_t * vLits );
+extern Vec_Int_t *            Aig_ManPackConstNodes( Aig_ManPack_t * p );
+
+/**Function*************************************************************
+
+  Synopsis    [Testing of the framework.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManJustExperiment( Aig_Man_t * pAig )
+{
+    Aig_ManPack_t * pPack;
+    Vec_Int_t * vSuppLits, * vNodes;
+    Aig_Obj_t * pObj;
+    int i;
+    abctime clk = Abc_Clock();
+    int Count0 = 0, Count0f = 0, Count1 = 0, Count1f = 0;
+    int nTotalLits = 0;
+    vSuppLits = Vec_IntAlloc( 100 );
+    pPack = Aig_ManPackStart( pAig );
+    vNodes = Aig_ManPackConstNodes( pPack );
+//    Aig_ManForEachCo( pAig, pObj, i )
+    Aig_ManForEachObjVec( vNodes, pAig, pObj, i )
+    {
+        if ( pObj->fPhase ) // const 1
+        {
+            if ( Aig_ObjFindSatAssign(pAig, pObj, 0, vSuppLits) )
+            {
+//                assert( Aig_ObjTerSimulate(pAig, pObj, vSuppLits) == AIG_VAL0 );
+//                if ( Aig_ObjTerSimulate(pAig, pObj, vSuppLits) != AIG_VAL0 )
+//                    printf( "Justification error!\n" );
+                Count0++;
+                nTotalLits += Vec_IntSize(vSuppLits);
+                Aig_ManPackAddPattern( pPack, vSuppLits );
+            }
+            else
+                Count0f++;
+        }
+        else
+        {
+            if ( Aig_ObjFindSatAssign(pAig, pObj, 1, vSuppLits) )
+            {
+//                assert( Aig_ObjTerSimulate(pAig, pObj, vSuppLits) == AIG_VAL1 );
+//                if ( Aig_ObjTerSimulate(pAig, pObj, vSuppLits) != AIG_VAL1 )
+//                    printf( "Justification error!\n" );
+                Count1++;
+                nTotalLits += Vec_IntSize(vSuppLits);
+                Aig_ManPackAddPattern( pPack, vSuppLits );
+            }
+            else
+                Count1f++;
+        }
+    }
+    Vec_IntFree( vSuppLits );
+    printf( "PO =%6d. C0 =%6d. C0f =%6d. C1 =%6d. C1f =%6d. (%6.2f %%) Ave =%4.1f ", 
+        Aig_ManCoNum(pAig), Count0, Count0f, Count1, Count1f, 100.0*(Count0+Count1)/Aig_ManCoNum(pAig), 1.0*nTotalLits/(Count0+Count1) );
+    Abc_PrintTime( 1, "T", Abc_Clock() - clk );
+    Aig_ManCleanMarkAB( pAig );
+    Aig_ManPackStop( pPack );
+    Vec_IntFree( vNodes );
+}
+
+
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigMan.c b/abc-build/src/aig/aig/aigMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigMan.c
@@ -0,0 +1,486 @@
+/**CFile****************************************************************
+
+  FileName    [aigMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [AIG manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+#include "misc/tim/tim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the AIG manager.]
+
+  Description [The argument of this procedure is a soft limit on the
+  the number of nodes, or 0 if the limit is unknown.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManStart( int nNodesMax )
+{
+    Aig_Man_t * p;
+    if ( nNodesMax <= 0 )
+        nNodesMax = 10007;
+    // start the manager
+    p = ABC_ALLOC( Aig_Man_t, 1 );
+    memset( p, 0, sizeof(Aig_Man_t) );
+    // perform initializations
+    p->nTravIds = 1;
+    p->fCatchExor = 0;
+    // allocate arrays for nodes
+    p->vCis  = Vec_PtrAlloc( 100 );
+    p->vCos  = Vec_PtrAlloc( 100 );
+    p->vObjs = Vec_PtrAlloc( 1000 );
+    p->vBufs = Vec_PtrAlloc( 100 );
+    //--jlong -- begin
+       p->unfold2_type_I = Vec_PtrAlloc( 4);
+       p->unfold2_type_II = Vec_PtrAlloc( 4);
+       //--jlong -- end
+    // prepare the internal memory manager
+    p->pMemObjs = Aig_MmFixedStart( sizeof(Aig_Obj_t), nNodesMax );
+    // create the constant node
+    p->pConst1 = Aig_ManFetchMemory( p );
+    p->pConst1->Type = AIG_OBJ_CONST1;
+    p->pConst1->fPhase = 1;
+    p->nObjs[AIG_OBJ_CONST1]++;
+    // start the table
+    p->nTableSize = Abc_PrimeCudd( nNodesMax );
+    p->pTable = ABC_ALLOC( Aig_Obj_t *, p->nTableSize );
+    memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManStartFrom( Aig_Man_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i;
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // create the PIs
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+    {
+        pObjNew = Aig_ObjCreateCi( pNew );
+        pObjNew->Level = pObj->Level;
+        pObj->pData = pObjNew;
+    }
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager recursively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_ManDup_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pObjNew;
+    if ( pObj->pData )
+        return (Aig_Obj_t *)pObj->pData;
+    Aig_ManDup_rec( pNew, p, Aig_ObjFanin0(pObj) );
+    if ( Aig_ObjIsBuf(pObj) )
+        return (Aig_Obj_t *)(pObj->pData = Aig_ObjChild0Copy(pObj));
+    Aig_ManDup_rec( pNew, p, Aig_ObjFanin1(pObj) );
+    pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) );
+    return (Aig_Obj_t *)(pObj->pData = pObjNew);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Extracts the miter composed of XOR of the two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManExtractMiter( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCi(pNew);
+    // dump the nodes
+    Aig_ManDup_rec( pNew, p, pNode1 );   
+    Aig_ManDup_rec( pNew, p, pNode2 );   
+    // construct the EXOR
+    pObj = Aig_Exor( pNew, (Aig_Obj_t *)pNode1->pData, (Aig_Obj_t *)pNode2->pData ); 
+    pObj = Aig_NotCond( pObj, Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) );
+    // add the PO
+    Aig_ObjCreateCo( pNew, pObj );
+    // check the resulting network
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManExtractMiter(): The check has failed.\n" );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManStop( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    if ( p->time1 ) { ABC_PRT( "time1", p->time1 ); }
+    if ( p->time2 ) { ABC_PRT( "time2", p->time2 ); }
+    // make sure the nodes have clean marks
+    Aig_ManForEachObj( p, pObj, i )
+        assert( !pObj->fMarkA && !pObj->fMarkB );
+    Tim_ManStopP( (Tim_Man_t **)&p->pManTime );
+    if ( p->pFanData ) 
+        Aig_ManFanoutStop( p );
+    if ( p->pManExdc )  
+        Aig_ManStop( p->pManExdc );
+//    Aig_TableProfile( p );
+    Aig_MmFixedStop( p->pMemObjs, 0 );
+    Vec_PtrFreeP( &p->vCis );
+    Vec_PtrFreeP( &p->vCos );
+    Vec_PtrFreeP( &p->vObjs );
+    Vec_PtrFreeP( &p->vBufs );
+    //--jlong -- begin
+    Vec_PtrFreeP( &p->unfold2_type_I );
+    Vec_PtrFreeP( &p->unfold2_type_II );
+    //--jlong -- end
+    Vec_IntFreeP( &p->vLevelR );
+    Vec_VecFreeP( &p->vLevels );
+    Vec_IntFreeP( &p->vFlopNums );
+    Vec_IntFreeP( &p->vFlopReprs );
+    Vec_VecFreeP( (Vec_Vec_t **)&p->vOnehots );
+    Vec_VecFreeP( &p->vClockDoms );
+    Vec_IntFreeP( &p->vProbs );
+    Vec_IntFreeP( &p->vCiNumsOrig );
+    Vec_PtrFreeP( &p->vMapped );
+    if ( p->vSeqModelVec )
+        Vec_PtrFreeFree( p->vSeqModelVec );
+    ABC_FREE( p->pTerSimData );
+    ABC_FREE( p->pFastSim );
+    ABC_FREE( p->pData );
+    ABC_FREE( p->pSeqModel );
+    ABC_FREE( p->pName );
+    ABC_FREE( p->pSpec );
+    ABC_FREE( p->pObjCopies );
+    ABC_FREE( p->pReprs );
+    ABC_FREE( p->pEquivs );
+    ABC_FREE( p->pTable );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManStopP( Aig_Man_t ** p )
+{
+    if ( *p == NULL )
+        return;
+    Aig_ManStop( *p );
+    *p = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes combinational logic that does not feed into POs.]
+
+  Description [Returns the number of dangling nodes removed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManCleanup( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vObjs;
+    Aig_Obj_t * pNode;
+    int i, nNodesOld = Aig_ManNodeNum(p);
+    // collect roots of dangling nodes
+    vObjs = Vec_PtrAlloc( 100 );
+    Aig_ManForEachObj( p, pNode, i )
+        if ( Aig_ObjIsNode(pNode) && Aig_ObjRefs(pNode) == 0 )
+            Vec_PtrPush( vObjs, pNode );
+    // recursively remove dangling nodes
+    Vec_PtrForEachEntry( Aig_Obj_t *, vObjs, pNode, i )
+        Aig_ObjDelete_rec( p, pNode, 1 );
+    Vec_PtrFree( vObjs );
+    return nNodesOld - Aig_ManNodeNum(p);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds POs for the nodes that otherwise would be dangling.]
+
+  Description [Returns the number of POs added.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManAntiCleanup( Aig_Man_t * p )
+{
+    Aig_Obj_t * pNode;
+    int i, nNodesOld = Aig_ManCoNum(p);
+    Aig_ManForEachObj( p, pNode, i )
+        if ( Aig_ObjIsNode(pNode) && Aig_ObjRefs(pNode) == 0 )
+            Aig_ObjCreateCo( p, pNode );
+    return nNodesOld - Aig_ManCoNum(p);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes PIs without fanouts.]
+
+  Description [Returns the number of PIs removed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManCiCleanup( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, k = 0, nPisOld = Aig_ManCiNum(p);
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vCis, pObj, i )
+    {
+        if ( i >= Aig_ManCiNum(p) - Aig_ManRegNum(p) )
+            Vec_PtrWriteEntry( p->vCis, k++, pObj );
+        else if ( Aig_ObjRefs(pObj) > 0 )
+            Vec_PtrWriteEntry( p->vCis, k++, pObj );
+        else
+            Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL );
+    }
+    Vec_PtrShrink( p->vCis, k );
+    p->nObjs[AIG_OBJ_CI] = Vec_PtrSize( p->vCis );
+    if ( Aig_ManRegNum(p) )
+        p->nTruePis = Aig_ManCiNum(p) - Aig_ManRegNum(p);
+    return nPisOld - Aig_ManCiNum(p);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes POs with constant input.]
+
+  Description [Returns the number of POs removed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManCoCleanup( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, k = 0, nPosOld = Aig_ManCoNum(p);
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vCos, pObj, i )
+    {
+        if ( i >= Aig_ManCoNum(p) - Aig_ManRegNum(p) )
+            Vec_PtrWriteEntry( p->vCos, k++, pObj );
+        else if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) || !Aig_ObjFaninC0(pObj) ) // non-const or const1
+            Vec_PtrWriteEntry( p->vCos, k++, pObj );
+        else
+        {
+            Aig_ObjDisconnect( p, pObj );
+            Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL );
+        }
+    }
+    Vec_PtrShrink( p->vCos, k );
+    p->nObjs[AIG_OBJ_CO] = Vec_PtrSize( p->vCos );
+    if ( Aig_ManRegNum(p) )
+        p->nTruePos = Aig_ManCoNum(p) - Aig_ManRegNum(p);
+    return nPosOld - Aig_ManCoNum(p);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManPrintStats( Aig_Man_t * p )
+{
+    int nChoices = Aig_ManChoiceNum(p);
+    printf( "%-15s : ",      p->pName );
+    printf( "pi = %5d  ",    Aig_ManCiNum(p)-Aig_ManRegNum(p) );
+    printf( "po = %5d  ",    Aig_ManCoNum(p)-Aig_ManRegNum(p) );
+    if ( Aig_ManRegNum(p) )
+    printf( "lat = %5d  ", Aig_ManRegNum(p) );
+    printf( "and = %7d  ",   Aig_ManAndNum(p) );
+//    printf( "Eq = %7d  ",     Aig_ManHaigCounter(p) );
+    if ( Aig_ManExorNum(p) )
+    printf( "xor = %5d  ",    Aig_ManExorNum(p) );
+    if ( nChoices )
+    printf( "ch = %5d  ",  nChoices );
+    if ( Aig_ManBufNum(p) )
+    printf( "buf = %5d  ",    Aig_ManBufNum(p) );
+//    printf( "Cre = %6d  ",  p->nCreated );
+//    printf( "Del = %6d  ",  p->nDeleted );
+//    printf( "Lev = %3d  ",  Aig_ManLevelNum(p) );
+//    printf( "Max = %7d  ",  Aig_ManObjNumMax(p) );
+    printf( "lev = %3d",  Aig_ManLevels(p) );
+    printf( "\n" );
+    fflush( stdout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports the reduction of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManReportImprovement( Aig_Man_t * p, Aig_Man_t * pNew )
+{
+    printf( "REG: Beg = %5d. End = %5d. (R =%5.1f %%)  ",
+        Aig_ManRegNum(p), Aig_ManRegNum(pNew), 
+        Aig_ManRegNum(p)? 100.0*(Aig_ManRegNum(p)-Aig_ManRegNum(pNew))/Aig_ManRegNum(p) : 0.0 );
+    printf( "AND: Beg = %6d. End = %6d. (R =%5.1f %%)",
+        Aig_ManNodeNum(p), Aig_ManNodeNum(pNew), 
+        Aig_ManNodeNum(p)? 100.0*(Aig_ManNodeNum(p)-Aig_ManNodeNum(pNew))/Aig_ManNodeNum(p) : 0.0 );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the number of registers in the AIG manager.]
+
+  Description [This procedure should be called after the manager is 
+  fully constructed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManSetRegNum( Aig_Man_t * p, int nRegs )
+{
+    p->nRegs = nRegs;
+    p->nTruePis = Aig_ManCiNum(p) - nRegs;
+    p->nTruePos = Aig_ManCoNum(p) - nRegs;
+    Aig_ManSetCioIds( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManFlipFirstPo( Aig_Man_t * p )
+{
+    Aig_ObjChild0Flip( Aig_ManCo(p, 0) ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Aig_ManReleaseData( Aig_Man_t * p )
+{ 
+    void * pD = p->pData; 
+    p->pData = NULL; 
+    return pD;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigMem.c b/abc-build/src/aig/aig/aigMem.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigMem.c
@@ -0,0 +1,598 @@
+/**CFile****************************************************************
+
+  FileName    [aigMem.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Memory managers.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigMem.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+struct Aig_MmFixed_t_
+{
+    // information about individual entries
+    int           nEntrySize;    // the size of one entry
+    int           nEntriesAlloc; // the total number of entries allocated
+    int           nEntriesUsed;  // the number of entries in use
+    int           nEntriesMax;   // the max number of entries in use
+    char *        pEntriesFree;  // the linked list of free entries
+
+    // this is where the memory is stored
+    int           nChunkSize;    // the size of one chunk
+    int           nChunksAlloc;  // the maximum number of memory chunks 
+    int           nChunks;       // the current number of memory chunks 
+    char **       pChunks;       // the allocated memory
+
+    // statistics
+    int           nMemoryUsed;   // memory used in the allocated entries
+    int           nMemoryAlloc;  // memory allocated
+};
+
+struct Aig_MmFlex_t_
+{
+    // information about individual entries
+    int           nEntriesUsed;  // the number of entries allocated
+    char *        pCurrent;      // the current pointer to free memory
+    char *        pEnd;          // the first entry outside the free memory
+
+    // this is where the memory is stored
+    int           nChunkSize;    // the size of one chunk
+    int           nChunksAlloc;  // the maximum number of memory chunks 
+    int           nChunks;       // the current number of memory chunks 
+    char **       pChunks;       // the allocated memory
+
+    // statistics
+    int           nMemoryUsed;   // memory used in the allocated entries
+    int           nMemoryAlloc;  // memory allocated
+};
+
+struct Aig_MmStep_t_
+{
+    int               nMems;    // the number of fixed memory managers employed
+    Aig_MmFixed_t **  pMems;    // memory managers: 2^1 words, 2^2 words, etc
+    int               nMapSize; // the size of the memory array
+    Aig_MmFixed_t **  pMap;     // maps the number of bytes into its memory manager
+    // additional memory chunks
+    int           nChunksAlloc;  // the maximum number of memory chunks 
+    int           nChunks;       // the current number of memory chunks 
+    char **       pChunks;       // the allocated memory
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates memory pieces of fixed size.]
+
+  Description [The size of the chunk is computed as the minimum of
+  1024 entries and 64K. Can only work with entry size at least 4 byte long.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_MmFixed_t * Aig_MmFixedStart( int nEntrySize, int nEntriesMax )
+{
+    Aig_MmFixed_t * p;
+
+    p = ABC_ALLOC( Aig_MmFixed_t, 1 );
+    memset( p, 0, sizeof(Aig_MmFixed_t) );
+
+    p->nEntrySize    = nEntrySize;
+    p->nEntriesAlloc = 0;
+    p->nEntriesUsed  = 0;
+    p->pEntriesFree  = NULL;
+
+    p->nChunkSize = nEntriesMax / 8;
+    if ( p->nChunkSize < 8 )
+        p->nChunkSize = 8;
+
+    p->nChunksAlloc  = 64;
+    p->nChunks       = 0;
+    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
+
+    p->nMemoryUsed   = 0;
+    p->nMemoryAlloc  = 0;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_MmFixedStop( Aig_MmFixed_t * p, int fVerbose )
+{
+    int i;
+    if ( p == NULL )
+        return;
+    if ( fVerbose )
+    {
+        printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n",
+            p->nEntrySize, p->nChunkSize, p->nChunks );
+        printf( "   Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n",
+            p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc );
+    }
+    for ( i = 0; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    ABC_FREE( p->pChunks );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Aig_MmFixedEntryFetch( Aig_MmFixed_t * p )
+{
+    char * pTemp;
+    int i;
+
+    // check if there are still free entries
+    if ( p->nEntriesUsed == p->nEntriesAlloc )
+    { // need to allocate more entries
+        assert( p->pEntriesFree == NULL );
+        if ( p->nChunks == p->nChunksAlloc )
+        {
+            p->nChunksAlloc *= 2;
+            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
+        }
+        p->pEntriesFree = ABC_ALLOC( char, p->nEntrySize * p->nChunkSize );
+        p->nMemoryAlloc += p->nEntrySize * p->nChunkSize;
+        // transform these entries into a linked list
+        pTemp = p->pEntriesFree;
+        for ( i = 1; i < p->nChunkSize; i++ )
+        {
+            *((char **)pTemp) = pTemp + p->nEntrySize;
+            pTemp += p->nEntrySize;
+        }
+        // set the last link
+        *((char **)pTemp) = NULL;
+        // add the chunk to the chunk storage
+        p->pChunks[ p->nChunks++ ] = p->pEntriesFree;
+        // add to the number of entries allocated
+        p->nEntriesAlloc += p->nChunkSize;
+    }
+    // incrememt the counter of used entries
+    p->nEntriesUsed++;
+    if ( p->nEntriesMax < p->nEntriesUsed )
+        p->nEntriesMax = p->nEntriesUsed;
+    // return the first entry in the free entry list
+    pTemp = p->pEntriesFree;
+    p->pEntriesFree = *((char **)pTemp);
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry )
+{
+    // decrement the counter of used entries
+    p->nEntriesUsed--;
+    // add the entry to the linked list of free entries
+    *((char **)pEntry) = p->pEntriesFree;
+    p->pEntriesFree = pEntry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description [Relocates all the memory except the first chunk.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_MmFixedRestart( Aig_MmFixed_t * p )
+{
+    int i;
+    char * pTemp;
+    if ( p->nChunks == 0 )
+        return;
+    // deallocate all chunks except the first one
+    for ( i = 1; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    p->nChunks = 1;
+    // transform these entries into a linked list
+    pTemp = p->pChunks[0];
+    for ( i = 1; i < p->nChunkSize; i++ )
+    {
+        *((char **)pTemp) = pTemp + p->nEntrySize;
+        pTemp += p->nEntrySize;
+    }
+    // set the last link
+    *((char **)pTemp) = NULL;
+    // set the free entry list
+    p->pEntriesFree  = p->pChunks[0];
+    // set the correct statistics
+    p->nMemoryAlloc  = p->nEntrySize * p->nChunkSize;
+    p->nMemoryUsed   = 0;
+    p->nEntriesAlloc = p->nChunkSize;
+    p->nEntriesUsed  = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_MmFixedReadMemUsage( Aig_MmFixed_t * p )
+{
+    return p->nMemoryAlloc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_MmFixedReadMaxEntriesUsed( Aig_MmFixed_t * p )
+{
+    return p->nEntriesMax;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates entries of flexible size.]
+
+  Description [Can only work with entry size at least 4 byte long.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_MmFlex_t * Aig_MmFlexStart()
+{
+    Aig_MmFlex_t * p;
+
+    p = ABC_ALLOC( Aig_MmFlex_t, 1 );
+    memset( p, 0, sizeof(Aig_MmFlex_t) );
+
+    p->nEntriesUsed  = 0;
+    p->pCurrent      = NULL;
+    p->pEnd          = NULL;
+
+    p->nChunkSize    = (1 << 18);
+    p->nChunksAlloc  = 64;
+    p->nChunks       = 0;
+    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
+
+    p->nMemoryUsed   = 0;
+    p->nMemoryAlloc  = 0;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_MmFlexStop( Aig_MmFlex_t * p, int fVerbose )
+{
+    int i;
+    if ( p == NULL )
+        return;
+    if ( fVerbose )
+    {
+        printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n",
+            p->nChunkSize, p->nChunks );
+        printf( "   Entries used = %d. Memory used = %d. Memory alloc = %d.\n",
+            p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc );
+    }
+    for ( i = 0; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    ABC_FREE( p->pChunks );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Aig_MmFlexEntryFetch( Aig_MmFlex_t * p, int nBytes )
+{
+    char * pTemp;
+    // check if there are still free entries
+    if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd )
+    { // need to allocate more entries
+        if ( p->nChunks == p->nChunksAlloc )
+        {
+            p->nChunksAlloc *= 2;
+            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
+        }
+        if ( nBytes > p->nChunkSize )
+        {
+            // resize the chunk size if more memory is requested than it can give
+            // (ideally, this should never happen)
+            p->nChunkSize = 2 * nBytes;
+        }
+        p->pCurrent = ABC_ALLOC( char, p->nChunkSize );
+        p->pEnd     = p->pCurrent + p->nChunkSize;
+        p->nMemoryAlloc += p->nChunkSize;
+        // add the chunk to the chunk storage
+        p->pChunks[ p->nChunks++ ] = p->pCurrent;
+    }
+    assert( p->pCurrent + nBytes <= p->pEnd );
+    // increment the counter of used entries
+    p->nEntriesUsed++;
+    // keep track of the memory used
+    p->nMemoryUsed += nBytes;
+    // return the next entry
+    pTemp = p->pCurrent;
+    p->pCurrent += nBytes;
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description [Relocates all the memory except the first chunk.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_MmFlexRestart( Aig_MmFlex_t * p )
+{
+    int i;
+    if ( p->nChunks == 0 )
+        return;
+    // deallocate all chunks except the first one
+    for ( i = 1; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    p->nChunks  = 1;
+    p->nMemoryAlloc = p->nChunkSize;
+    // transform these entries into a linked list
+    p->pCurrent = p->pChunks[0];
+    p->pEnd     = p->pCurrent + p->nChunkSize;
+    p->nEntriesUsed = 0;
+    p->nMemoryUsed = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_MmFlexReadMemUsage( Aig_MmFlex_t * p )
+{
+    return p->nMemoryUsed;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the hierarchical memory manager.]
+
+  Description [This manager can allocate entries of any size.
+  Iternally they are mapped into the entries with the number of bytes
+  equal to the power of 2. The smallest entry size is 8 bytes. The
+  next one is 16 bytes etc. So, if the user requests 6 bytes, he gets 
+  8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc.
+  The input parameters "nSteps" says how many fixed memory managers
+  are employed internally. Calling this procedure with nSteps equal
+  to 10 results in 10 hierarchically arranged internal memory managers, 
+  which can allocate up to 4096 (1Kb) entries. Requests for larger 
+  entries are handed over to malloc() and then ABC_FREE()ed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_MmStep_t * Aig_MmStepStart( int nSteps )
+{
+    Aig_MmStep_t * p;
+    int i, k;
+    p = ABC_ALLOC( Aig_MmStep_t, 1 );
+    memset( p, 0, sizeof(Aig_MmStep_t) );
+    p->nMems = nSteps;
+    // start the fixed memory managers
+    p->pMems = ABC_ALLOC( Aig_MmFixed_t *, p->nMems );
+    for ( i = 0; i < p->nMems; i++ )
+        p->pMems[i] = Aig_MmFixedStart( (8<<i), (1<<13) );
+    // set up the mapping of the required memory size into the corresponding manager
+    p->nMapSize = (4<<p->nMems);
+    p->pMap = ABC_ALLOC( Aig_MmFixed_t *, p->nMapSize+1 );
+    p->pMap[0] = NULL;
+    for ( k = 1; k <= 4; k++ )
+        p->pMap[k] = p->pMems[0];
+    for ( i = 0; i < p->nMems; i++ )
+        for ( k = (4<<i)+1; k <= (8<<i); k++ )
+            p->pMap[k] = p->pMems[i];
+//for ( i = 1; i < 100; i ++ )
+//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize );
+    p->nChunksAlloc  = 64;
+    p->nChunks       = 0;
+    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_MmStepStop( Aig_MmStep_t * p, int fVerbose )
+{
+    int i;
+    for ( i = 0; i < p->nMems; i++ )
+        Aig_MmFixedStop( p->pMems[i], fVerbose );
+    if ( p->nChunksAlloc )
+    {
+        for ( i = 0; i < p->nChunks; i++ )
+            ABC_FREE( p->pChunks[i] );
+        ABC_FREE( p->pChunks );
+    }
+    ABC_FREE( p->pMems );
+    ABC_FREE( p->pMap );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Aig_MmStepEntryFetch( Aig_MmStep_t * p, int nBytes )
+{
+    if ( nBytes == 0 )
+        return NULL;
+    if ( nBytes > p->nMapSize )
+    {
+        if ( p->nChunks == p->nChunksAlloc )
+        {
+            p->nChunksAlloc *= 2;
+            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
+        }
+        p->pChunks[ p->nChunks++ ] = ABC_ALLOC( char, nBytes );
+        return p->pChunks[p->nChunks-1];
+    }
+    return Aig_MmFixedEntryFetch( p->pMap[nBytes] );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_MmStepEntryRecycle( Aig_MmStep_t * p, char * pEntry, int nBytes )
+{
+    if ( nBytes == 0 )
+        return;
+    if ( nBytes > p->nMapSize )
+    {
+//        ABC_FREE( pEntry );
+        return;
+    }
+    Aig_MmFixedEntryRecycle( p->pMap[nBytes], pEntry );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_MmStepReadMemUsage( Aig_MmStep_t * p )
+{
+    int i, nMemTotal = 0;
+    for ( i = 0; i < p->nMems; i++ )
+        nMemTotal += p->pMems[i]->nMemoryAlloc;
+    return nMemTotal;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigMffc.c b/abc-build/src/aig/aig/aigMffc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigMffc.c
@@ -0,0 +1,316 @@
+/**CFile****************************************************************
+
+  FileName    [aigMffc.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Computation of MFFCs.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigMffc.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences the node's MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin, float * pPower, float * pProbs )
+{
+    float Power0 = 0.0, Power1 = 0.0;
+    Aig_Obj_t * pFanin;
+    int Counter = 0;
+    if ( pProbs )
+        *pPower = 0.0;
+    if ( Aig_ObjIsCi(pNode) )
+        return 0;
+    // consider the first fanin
+    pFanin = Aig_ObjFanin0(pNode);
+    assert( pFanin->nRefs > 0 );
+    if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) )
+        Counter += Aig_NodeDeref_rec( pFanin, LevelMin, &Power0, pProbs );
+    if ( pProbs )
+        *pPower += Power0 + 2.0 * pProbs[pFanin->Id] * (1.0 - pProbs[pFanin->Id]);
+    // skip the buffer
+    if ( Aig_ObjIsBuf(pNode) )
+        return Counter;
+    assert( Aig_ObjIsNode(pNode) );
+    // consider the second fanin
+    pFanin = Aig_ObjFanin1(pNode);
+    assert( pFanin->nRefs > 0 );
+    if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) )
+        Counter += Aig_NodeDeref_rec( pFanin, LevelMin, &Power1, pProbs );
+    if ( pProbs )
+        *pPower += Power1 + 2.0 * pProbs[pFanin->Id] * (1.0 - pProbs[pFanin->Id]);
+    return Counter + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [References the node's MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_NodeRef_rec( Aig_Obj_t * pNode, unsigned LevelMin )
+{
+    Aig_Obj_t * pFanin;
+    int Counter = 0;
+    if ( Aig_ObjIsCi(pNode) )
+        return 0;
+    // consider the first fanin
+    pFanin = Aig_ObjFanin0(pNode);
+    if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) )
+        Counter += Aig_NodeRef_rec( pFanin, LevelMin );
+    // skip the buffer
+    if ( Aig_ObjIsBuf(pNode) )
+        return Counter;
+    assert( Aig_ObjIsNode(pNode) );
+    // consider the second fanin
+    pFanin = Aig_ObjFanin1(pNode);
+    if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) )
+        Counter += Aig_NodeRef_rec( pFanin, LevelMin );
+    return Counter + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [References the node's MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_NodeRefLabel_rec( Aig_Man_t * p, Aig_Obj_t * pNode, unsigned LevelMin )
+{
+    Aig_Obj_t * pFanin;
+    int Counter = 0;
+    if ( Aig_ObjIsCi(pNode) )
+        return 0;
+    Aig_ObjSetTravIdCurrent( p, pNode );
+    // consider the first fanin
+    pFanin = Aig_ObjFanin0(pNode);
+    if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) )
+        Counter += Aig_NodeRefLabel_rec( p, pFanin, LevelMin );
+    if ( Aig_ObjIsBuf(pNode) )
+        return Counter;
+    assert( Aig_ObjIsNode(pNode) );
+    // consider the second fanin
+    pFanin = Aig_ObjFanin1(pNode);
+    if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) )
+        Counter += Aig_NodeRefLabel_rec( p, pFanin, LevelMin );
+    return Counter + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the internal and boundary nodes in the derefed MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_NodeMffcSupp_rec( Aig_Man_t * p, Aig_Obj_t * pNode, unsigned LevelMin, Vec_Ptr_t * vSupp, int fTopmost, Aig_Obj_t * pObjSkip )
+{
+    // skip visited nodes
+    if ( Aig_ObjIsTravIdCurrent(p, pNode) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pNode);
+    // add to the new support nodes
+    if ( !fTopmost && pNode != pObjSkip && (Aig_ObjIsCi(pNode) || pNode->nRefs > 0 || pNode->Level <= LevelMin) )
+    {
+        if ( vSupp ) Vec_PtrPush( vSupp, pNode );
+        return;
+    }
+    assert( Aig_ObjIsNode(pNode) );
+    // recur on the children
+    Aig_NodeMffcSupp_rec( p, Aig_ObjFanin0(pNode), LevelMin, vSupp, 0, pObjSkip );
+    Aig_NodeMffcSupp_rec( p, Aig_ObjFanin1(pNode), LevelMin, vSupp, 0, pObjSkip );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the support of depth-limited MFFC.]
+
+  Description [Returns the number of internal nodes in the MFFC.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_NodeMffcSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t * vSupp )
+{
+    int ConeSize1, ConeSize2;
+    if ( vSupp ) Vec_PtrClear( vSupp );
+    if ( !Aig_ObjIsNode(pNode) )
+    {
+        if ( Aig_ObjIsCi(pNode) && vSupp )
+            Vec_PtrPush( vSupp, pNode );
+        return 0;
+    }
+    assert( !Aig_IsComplement(pNode) );
+    assert( Aig_ObjIsNode(pNode) );
+    Aig_ManIncrementTravId( p );
+    ConeSize1 = Aig_NodeDeref_rec( pNode, LevelMin, NULL, NULL );
+    Aig_NodeMffcSupp_rec( p, pNode, LevelMin, vSupp, 1, NULL );
+    ConeSize2 = Aig_NodeRef_rec( pNode, LevelMin );
+    assert( ConeSize1 == ConeSize2 );
+    assert( ConeSize1 > 0 );
+    return ConeSize1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Labels the nodes in the MFFC.]
+
+  Description [Returns the number of internal nodes in the MFFC.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_NodeMffcLabel( Aig_Man_t * p, Aig_Obj_t * pNode, float * pPower )
+{
+    int ConeSize1, ConeSize2;
+    assert( (pPower != NULL) == (p->vProbs != NULL) );
+    assert( !Aig_IsComplement(pNode) );
+    assert( Aig_ObjIsNode(pNode) );
+    Aig_ManIncrementTravId( p );
+    ConeSize1 = Aig_NodeDeref_rec( pNode, 0, pPower, p->vProbs? (float *)p->vProbs->pArray : NULL );
+    ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 );
+    assert( ConeSize1 == ConeSize2 );
+    assert( ConeSize1 > 0 );
+    return ConeSize1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Labels the nodes in the MFFC.]
+
+  Description [Returns the number of internal nodes in the MFFC.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_NodeMffcLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves )
+{
+    Aig_Obj_t * pObj;
+    int i, ConeSize1, ConeSize2;
+    assert( !Aig_IsComplement(pNode) );
+    assert( Aig_ObjIsNode(pNode) );
+    Aig_ManIncrementTravId( p );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i )
+        pObj->nRefs++;
+    ConeSize1 = Aig_NodeDeref_rec( pNode, 0, NULL, NULL );
+    ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i )
+        pObj->nRefs--;
+    assert( ConeSize1 == ConeSize2 );
+    assert( ConeSize1 > 0 );
+    return ConeSize1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Expands the cut by adding the most closely related node.]
+
+  Description [Returns 1 if the cut exists.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_NodeMffcExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vResult )
+{
+    Aig_Obj_t * pObj, * pLeafBest;
+    int i, LevelMax, ConeSize1, ConeSize2, ConeCur1, ConeCur2, ConeBest;
+    // dereference the current cut
+    LevelMax = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i )
+        LevelMax = Abc_MaxInt( LevelMax, (int)pObj->Level );
+    if ( LevelMax == 0 )
+        return 0;
+    // dereference the cut
+    ConeSize1 = Aig_NodeDeref_rec( pNode, 0, NULL, NULL );
+    // try expanding each node in the boundary
+    ConeBest = ABC_INFINITY;
+    pLeafBest = NULL;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i )
+    {
+        if ( (int)pObj->Level != LevelMax )
+            continue;
+        ConeCur1 = Aig_NodeDeref_rec( pObj, 0, NULL, NULL );
+        if ( ConeBest > ConeCur1 )
+        {
+            ConeBest = ConeCur1;
+            pLeafBest = pObj;
+        }
+        ConeCur2 = Aig_NodeRef_rec( pObj, 0 );
+        assert( ConeCur1 == ConeCur2 );
+    }
+    assert( pLeafBest != NULL );
+    assert( Aig_ObjIsNode(pLeafBest) );
+    // deref the best leaf
+    ConeCur1 = Aig_NodeDeref_rec( pLeafBest, 0, NULL, NULL );
+    // collect the cut nodes
+    Vec_PtrClear( vResult );
+    Aig_ManIncrementTravId( p );
+    Aig_NodeMffcSupp_rec( p, pNode, 0, vResult, 1, pLeafBest );
+    // ref the nodes
+    ConeCur2 = Aig_NodeRef_rec( pLeafBest, 0 );
+    assert( ConeCur1 == ConeCur2 );
+    // ref the original node
+    ConeSize2 = Aig_NodeRef_rec( pNode, 0 );
+    assert( ConeSize1 == ConeSize2 );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigObj.c b/abc-build/src/aig/aig/aigObj.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigObj.c
@@ -0,0 +1,536 @@
+/**CFile****************************************************************
+
+  FileName    [aigObj.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Adding/removing objects.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigObj.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates primary input.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_ObjCreateCi( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    pObj = Aig_ManFetchMemory( p );
+    pObj->Type = AIG_OBJ_CI;
+    Vec_PtrPush( p->vCis, pObj );
+    p->nObjs[AIG_OBJ_CI]++;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates primary output with the given driver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_ObjCreateCo( Aig_Man_t * p, Aig_Obj_t * pDriver )
+{
+    Aig_Obj_t * pObj;
+    pObj = Aig_ManFetchMemory( p );
+    pObj->Type = AIG_OBJ_CO;
+    Vec_PtrPush( p->vCos, pObj );
+    Aig_ObjConnect( p, pObj, pDriver, NULL );
+    p->nObjs[AIG_OBJ_CO]++;
+    return pObj;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Create the new node assuming it does not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost )
+{
+    Aig_Obj_t * pObj;
+    assert( !Aig_IsComplement(pGhost) );
+    assert( Aig_ObjIsHash(pGhost) );
+//    assert( pGhost == &p->Ghost );
+    // get memory for the new object
+    pObj = Aig_ManFetchMemory( p );
+    pObj->Type = pGhost->Type;
+    // add connections
+    Aig_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 );
+    // update node counters of the manager
+    p->nObjs[Aig_ObjType(pObj)]++;
+    assert( pObj->pData == NULL );
+    // create the power counter
+    if ( p->vProbs )
+    {
+        float Prob0 = Abc_Int2Float( Vec_IntEntry( p->vProbs, Aig_ObjFaninId0(pObj) ) );
+        float Prob1 = Abc_Int2Float( Vec_IntEntry( p->vProbs, Aig_ObjFaninId1(pObj) ) );
+        Prob0 = Aig_ObjFaninC0(pObj)? 1.0 - Prob0 : Prob0;
+        Prob1 = Aig_ObjFaninC1(pObj)? 1.0 - Prob1 : Prob1;
+        Vec_IntSetEntry( p->vProbs, pObj->Id, Abc_Float2Int(Prob0 * Prob1) );
+    }
+    return pObj;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Connect the object to the fanin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjConnect( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFan0, Aig_Obj_t * pFan1 )
+{
+    assert( !Aig_IsComplement(pObj) );
+    assert( !Aig_ObjIsCi(pObj) );
+    // add the first fanin
+    pObj->pFanin0 = pFan0;
+    pObj->pFanin1 = pFan1;
+    // increment references of the fanins and add their fanouts
+    if ( pFan0 != NULL )
+    {
+        assert( Aig_ObjFanin0(pObj)->Type > 0 );
+        Aig_ObjRef( Aig_ObjFanin0(pObj) );
+        if ( p->pFanData )
+            Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj );
+    }
+    if ( pFan1 != NULL )
+    {
+        assert( Aig_ObjFanin1(pObj)->Type > 0 );
+        Aig_ObjRef( Aig_ObjFanin1(pObj) );
+        if ( p->pFanData )
+            Aig_ObjAddFanout( p, Aig_ObjFanin1(pObj), pObj );
+    }
+    // set level and phase
+    pObj->Level = Aig_ObjLevelNew( pObj );
+    pObj->fPhase = Aig_ObjPhaseReal(pFan0) & Aig_ObjPhaseReal(pFan1);
+    // add the node to the structural hash table
+    if ( p->pTable && Aig_ObjIsHash(pObj) )
+        Aig_TableInsert( p, pObj );
+    // add the node to the dynamically updated topological order
+//    if ( p->pOrderData && Aig_ObjIsNode(pObj) )
+//        Aig_ObjOrderInsert( p, pObj->Id );
+    assert( !Aig_ObjIsNode(pObj) || pObj->Level > 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Disconnects the object from the fanins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjDisconnect( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    assert( !Aig_IsComplement(pObj) );
+    // remove connections
+    if ( pObj->pFanin0 != NULL )
+    {
+        if ( p->pFanData )
+            Aig_ObjRemoveFanout( p, Aig_ObjFanin0(pObj), pObj );
+        Aig_ObjDeref(Aig_ObjFanin0(pObj));
+    }
+    if ( pObj->pFanin1 != NULL )
+    {
+        if ( p->pFanData )
+            Aig_ObjRemoveFanout( p, Aig_ObjFanin1(pObj), pObj );
+        Aig_ObjDeref(Aig_ObjFanin1(pObj));
+    }
+    // remove the node from the structural hash table
+    if ( p->pTable && Aig_ObjIsHash(pObj) )
+        Aig_TableDelete( p, pObj );
+    // add the first fanin
+    pObj->pFanin0 = NULL;
+    pObj->pFanin1 = NULL;
+    // remove the node from the dynamically updated topological order
+//    if ( p->pOrderData && Aig_ObjIsNode(pObj) )
+//        Aig_ObjOrderRemove( p, pObj->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjDelete( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    assert( !Aig_IsComplement(pObj) );
+    assert( !Aig_ObjIsTerm(pObj) );
+    assert( Aig_ObjRefs(pObj) == 0 );
+    if ( p->pFanData && Aig_ObjIsBuf(pObj) )
+        Vec_PtrRemove( p->vBufs, pObj );
+    p->nObjs[pObj->Type]--;
+    Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL );
+    Aig_ManRecycleMemory( p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the MFFC of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjDelete_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int fFreeTop )
+{
+    Aig_Obj_t * pFanin0, * pFanin1;
+    assert( !Aig_IsComplement(pObj) );
+    if ( Aig_ObjIsConst1(pObj) || Aig_ObjIsCi(pObj) )
+        return;
+    assert( !Aig_ObjIsCo(pObj) );
+    pFanin0 = Aig_ObjFanin0(pObj);
+    pFanin1 = Aig_ObjFanin1(pObj);
+    Aig_ObjDisconnect( p, pObj );
+    if ( fFreeTop )
+        Aig_ObjDelete( p, pObj );
+    if ( pFanin0 && !Aig_ObjIsNone(pFanin0) && Aig_ObjRefs(pFanin0) == 0 )
+        Aig_ObjDelete_rec( p, pFanin0, 1 );
+    if ( pFanin1 && !Aig_ObjIsNone(pFanin1) && Aig_ObjRefs(pFanin1) == 0 )
+        Aig_ObjDelete_rec( p, pFanin1, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjDeletePo( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    assert( Aig_ObjIsCo(pObj) );
+    Aig_ObjDeref(Aig_ObjFanin0(pObj));
+    pObj->pFanin0 = NULL;
+    p->nObjs[pObj->Type]--;
+    Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL );
+    Aig_ManRecycleMemory( p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces the first fanin of the node by the new fanin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjPatchFanin0( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFaninNew )
+{
+    Aig_Obj_t * pFaninOld;
+    assert( !Aig_IsComplement(pObj) );
+    assert( Aig_ObjIsCo(pObj) );
+    pFaninOld = Aig_ObjFanin0(pObj);
+    // decrement ref and remove fanout
+    if ( p->pFanData )
+        Aig_ObjRemoveFanout( p, pFaninOld, pObj );
+    Aig_ObjDeref( pFaninOld );
+    // update the fanin
+    pObj->pFanin0 = pFaninNew;
+    pObj->Level = Aig_ObjLevelNew( pObj );
+    pObj->fPhase = Aig_ObjPhaseReal(pObj->pFanin0);
+    // increment ref and add fanout
+    if ( p->pFanData )
+        Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj );
+    Aig_ObjRef( Aig_ObjFanin0(pObj) );
+    // get rid of old fanin
+    if ( !Aig_ObjIsCi(pFaninOld) && !Aig_ObjIsConst1(pFaninOld) && Aig_ObjRefs(pFaninOld) == 0 )
+        Aig_ObjDelete_rec( p, pFaninOld, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verbose printing of the AIG node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjPrint( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    int fShowFanouts = 0;
+    Aig_Obj_t * pTemp;
+    if ( pObj == NULL )
+    {
+        printf( "Object is NULL." );
+        return;
+    }
+    if ( Aig_IsComplement(pObj) )
+    {
+        printf( "Compl " );
+        pObj = Aig_Not(pObj);
+    }
+    assert( !Aig_IsComplement(pObj) );
+    printf( "Node %4d : ", Aig_ObjId(pObj) );
+    if ( Aig_ObjIsConst1(pObj) )
+        printf( "constant 1" );
+    else if ( Aig_ObjIsCi(pObj) )
+        printf( "PI" );
+    else if ( Aig_ObjIsCo(pObj) )
+        printf( "PO( %4d%s )", Aig_ObjFanin0(pObj)->Id, (Aig_ObjFaninC0(pObj)? "\'" : " ") );
+    else if ( Aig_ObjIsBuf(pObj) )
+        printf( "BUF( %d%s )", Aig_ObjFanin0(pObj)->Id, (Aig_ObjFaninC0(pObj)? "\'" : " ") );
+    else
+        printf( "AND( %4d%s, %4d%s )", 
+            Aig_ObjFanin0(pObj)->Id, (Aig_ObjFaninC0(pObj)? "\'" : " "), 
+            Aig_ObjFanin1(pObj)->Id, (Aig_ObjFaninC1(pObj)? "\'" : " ") );
+    printf( " (refs = %3d)", Aig_ObjRefs(pObj) );
+    if ( fShowFanouts && p->pFanData )
+    {
+        Aig_Obj_t * pFanout;
+        int i;
+        int iFan = -1; // Suppress "might be used uninitialized"
+        printf( "\nFanouts:\n" );
+        Aig_ObjForEachFanout( p, pObj, pFanout, iFan, i )
+        {
+            printf( "    " );
+            printf( "Node %4d : ", Aig_ObjId(pFanout) );
+            if ( Aig_ObjIsCo(pFanout) )
+                printf( "PO( %4d%s )", Aig_ObjFanin0(pFanout)->Id, (Aig_ObjFaninC0(pFanout)? "\'" : " ") );
+            else if ( Aig_ObjIsBuf(pFanout) )
+                printf( "BUF( %d%s )", Aig_ObjFanin0(pFanout)->Id, (Aig_ObjFaninC0(pFanout)? "\'" : " ") );
+            else
+                printf( "AND( %4d%s, %4d%s )", 
+                    Aig_ObjFanin0(pFanout)->Id, (Aig_ObjFaninC0(pFanout)? "\'" : " "), 
+                    Aig_ObjFanin1(pFanout)->Id, (Aig_ObjFaninC1(pFanout)? "\'" : " ") );
+            printf( "\n" );
+        }
+        return;
+    }
+    // there are choices
+    if ( p->pEquivs && p->pEquivs[pObj->Id] )
+    {
+        // print equivalence class
+        printf( "  { %4d ", pObj->Id );
+        for ( pTemp = p->pEquivs[pObj->Id]; pTemp; pTemp = p->pEquivs[pTemp->Id] )
+            printf( " %4d%s", pTemp->Id, (pTemp->fPhase != pObj->fPhase)? "\'" : " " );
+        printf( " }" );
+        return;
+    }
+    // this is a secondary node
+    if ( p->pReprs && p->pReprs[pObj->Id] )
+        printf( "  class of %d", pObj->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces node with a buffer fanin by a node without them.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_NodeFixBufferFanins( Aig_Man_t * p, Aig_Obj_t * pObj, int fUpdateLevel )
+{
+    Aig_Obj_t * pFanReal0, * pFanReal1, * pResult;
+    p->nBufFixes++;
+    if ( Aig_ObjIsCo(pObj) )
+    {
+        assert( Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) );
+        pFanReal0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
+        assert( Aig_ObjPhaseReal(Aig_ObjChild0(pObj)) == Aig_ObjPhaseReal(pFanReal0) );
+        Aig_ObjPatchFanin0( p, pObj, pFanReal0 );
+        return;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    assert( Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) || Aig_ObjIsBuf(Aig_ObjFanin1(pObj)) );
+    // get the real fanins
+    pFanReal0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
+    pFanReal1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) );
+    // get the new node
+    if ( Aig_ObjIsNode(pObj) )
+        pResult = Aig_Oper( p, pFanReal0, pFanReal1, Aig_ObjType(pObj) );
+//    else if ( Aig_ObjIsLatch(pObj) )
+//        pResult = Aig_Latch( p, pFanReal0, Aig_ObjInit(pObj) );
+    else 
+        assert( 0 );
+    // replace the node with buffer by the node without buffer
+    Aig_ObjReplace( p, pObj, pResult, fUpdateLevel );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of dangling nodes removed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+int Aig_ManPropagateBuffers( Aig_Man_t * p, int fUpdateLevel )
+{
+    Aig_Obj_t * pObj;
+    int nSteps;
+    assert( p->pFanData );
+    for ( nSteps = 0; Vec_PtrSize(p->vBufs) > 0; nSteps++ )
+    {
+        // get the node with a buffer fanin
+        for ( pObj = (Aig_Obj_t *)Vec_PtrEntryLast(p->vBufs); Aig_ObjIsBuf(pObj); pObj = Aig_ObjFanout0(p, pObj) );
+        // replace this node by a node without buffer
+        Aig_NodeFixBufferFanins( p, pObj, fUpdateLevel );
+        // stop if a cycle occured
+        if ( nSteps > 1000000 )
+        {
+            printf( "Error: A cycle is encountered while propagating buffers.\n" );
+            break;
+        }
+    }
+    return nSteps;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces one object by another.]
+
+  Description [The new object (pObjNew) should be used instead of the old 
+  object (pObjOld). If the new object is complemented or used, the buffer 
+  is added and the new object remains in the manager; otherwise, the new
+  object is deleted.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjReplace( Aig_Man_t * p, Aig_Obj_t * pObjOld, Aig_Obj_t * pObjNew, int fUpdateLevel )
+{
+    Aig_Obj_t * pObjNewR = Aig_Regular(pObjNew);
+    // the object to be replaced cannot be complemented
+    assert( !Aig_IsComplement(pObjOld) );
+    // the object to be replaced cannot be a terminal
+    assert( !Aig_ObjIsCi(pObjOld) && !Aig_ObjIsCo(pObjOld) );
+    // the object to be used cannot be a buffer or a PO
+    assert( !Aig_ObjIsBuf(pObjNewR) && !Aig_ObjIsCo(pObjNewR) );
+    // the object cannot be the same
+    assert( pObjOld != pObjNewR );
+    // make sure object is not pointing to itself
+    assert( pObjOld != Aig_ObjFanin0(pObjNewR) );
+    assert( pObjOld != Aig_ObjFanin1(pObjNewR) );
+    if ( pObjOld == Aig_ObjFanin0(pObjNewR) || pObjOld == Aig_ObjFanin1(pObjNewR) )
+    {
+        printf( "Aig_ObjReplace(): Internal error!\n" );
+        exit(1);
+    }
+    // recursively delete the old node - but leave the object there
+    pObjNewR->nRefs++;
+    Aig_ObjDelete_rec( p, pObjOld, 0 );
+    pObjNewR->nRefs--;
+    // if the new object is complemented or already used, create a buffer
+    p->nObjs[pObjOld->Type]--;
+    if ( Aig_IsComplement(pObjNew) || Aig_ObjRefs(pObjNew) > 0 || !Aig_ObjIsNode(pObjNew) )
+    {
+        pObjOld->Type = AIG_OBJ_BUF;
+        Aig_ObjConnect( p, pObjOld, pObjNew, NULL );
+        p->nBufReplaces++;
+    }
+    else
+    {
+        Aig_Obj_t * pFanin0 = pObjNew->pFanin0;
+        Aig_Obj_t * pFanin1 = pObjNew->pFanin1;
+        int LevelOld = pObjOld->Level;
+        pObjOld->Type = pObjNew->Type;
+        Aig_ObjDisconnect( p, pObjNew );
+        Aig_ObjConnect( p, pObjOld, pFanin0, pFanin1 );
+        // delete the new object
+        Aig_ObjDelete( p, pObjNew );
+        // update levels
+        if ( p->pFanData )
+        {
+            pObjOld->Level = LevelOld;
+            Aig_ManUpdateLevel( p, pObjOld );
+        }
+        if ( fUpdateLevel )
+        {
+            Aig_ObjClearReverseLevel( p, pObjOld );
+            Aig_ManUpdateReverseLevel( p, pObjOld );
+        }
+    }
+    p->nObjs[pObjOld->Type]++;
+    // store buffers if fanout is allocated
+    if ( p->pFanData && Aig_ObjIsBuf(pObjOld) )
+    {
+        Vec_PtrPush( p->vBufs, pObjOld );
+        p->nBufMax = Abc_MaxInt( p->nBufMax, Vec_PtrSize(p->vBufs) );
+        Aig_ManPropagateBuffers( p, fUpdateLevel );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigOper.c b/abc-build/src/aig/aig/aigOper.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigOper.c
@@ -0,0 +1,606 @@
+/**CFile****************************************************************
+
+  FileName    [aigOper.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [AIG operations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigOper.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// procedure to detect an EXOR gate
+static inline int Aig_ObjIsExorType( Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 )
+{
+    if ( !Aig_IsComplement(p0) || !Aig_IsComplement(p1) )
+        return 0;
+    p0 = Aig_Regular(p0);
+    p1 = Aig_Regular(p1);
+    if ( !Aig_ObjIsAnd(p0) || !Aig_ObjIsAnd(p1) )
+        return 0;
+    if ( Aig_ObjFanin0(p0) != Aig_ObjFanin0(p1) || Aig_ObjFanin1(p0) != Aig_ObjFanin1(p1) )
+        return 0;
+    if ( Aig_ObjFaninC0(p0) == Aig_ObjFaninC0(p1) || Aig_ObjFaninC1(p0) == Aig_ObjFaninC1(p1) )
+        return 0;
+    *ppFan0 = Aig_ObjChild0(p0);
+    *ppFan1 = Aig_ObjChild1(p0);
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns i-th elementary variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_IthVar( Aig_Man_t * p, int i )
+{
+    int v;
+    for ( v = Aig_ManCiNum(p); v <= i; v++ )
+        Aig_ObjCreateCi( p );
+    assert( i < Vec_PtrSize(p->vCis) );
+    return Aig_ManCi( p, i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform one operation.]
+
+  Description [The argument nodes can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_Oper( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type )
+{
+    if ( Type == AIG_OBJ_AND )
+        return Aig_And( p, p0, p1 );
+    if ( Type == AIG_OBJ_EXOR )
+        return Aig_Exor( p, p0, p1 );
+    assert( 0 );
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs canonicization step.]
+
+  Description [The argument nodes can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_And( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 )
+{
+    Aig_Obj_t * pGhost, * pResult;
+    Aig_Obj_t * pFan0, * pFan1;
+    // check trivial cases
+    if ( p0 == p1 )
+        return p0;
+    if ( p0 == Aig_Not(p1) )
+        return Aig_Not(p->pConst1);
+    if ( Aig_Regular(p0) == p->pConst1 )
+        return p0 == p->pConst1 ? p1 : Aig_Not(p->pConst1);
+    if ( Aig_Regular(p1) == p->pConst1 )
+        return p1 == p->pConst1 ? p0 : Aig_Not(p->pConst1);
+    // check not so trivial cases
+    if ( p->fAddStrash && (Aig_ObjIsNode(Aig_Regular(p0)) || Aig_ObjIsNode(Aig_Regular(p1))) )
+    { // http://fmv.jku.at/papers/BrummayerBiere-MEMICS06.pdf
+        Aig_Obj_t * pFanA, * pFanB, * pFanC, * pFanD;
+        pFanA = Aig_ObjChild0(Aig_Regular(p0));
+        pFanB = Aig_ObjChild1(Aig_Regular(p0));
+        pFanC = Aig_ObjChild0(Aig_Regular(p1));
+        pFanD = Aig_ObjChild1(Aig_Regular(p1));
+        if ( Aig_IsComplement(p0) )
+        {
+            if ( pFanA == Aig_Not(p1) || pFanB == Aig_Not(p1) )
+                return p1;
+            if ( pFanB == p1 )
+                return Aig_And( p, Aig_Not(pFanA), pFanB );
+            if ( pFanA == p1 )
+                return Aig_And( p, Aig_Not(pFanB), pFanA );
+        }
+        else
+        {
+            if ( pFanA == Aig_Not(p1) || pFanB == Aig_Not(p1) )
+                return Aig_Not(p->pConst1);
+            if ( pFanA == p1 || pFanB == p1 )
+                return p0;
+        }
+        if ( Aig_IsComplement(p1) )
+        {
+            if ( pFanC == Aig_Not(p0) || pFanD == Aig_Not(p0) )
+                return p0;
+            if ( pFanD == p0 )
+                return Aig_And( p, Aig_Not(pFanC), pFanD );
+            if ( pFanC == p0 )
+                return Aig_And( p, Aig_Not(pFanD), pFanC );
+        }
+        else
+        {
+            if ( pFanC == Aig_Not(p0) || pFanD == Aig_Not(p0) )
+                return Aig_Not(p->pConst1);
+            if ( pFanC == p0 || pFanD == p0 )
+                return p1;
+        }
+        if ( !Aig_IsComplement(p0) && !Aig_IsComplement(p1) ) 
+        {
+            if ( pFanA == Aig_Not(pFanC) || pFanA == Aig_Not(pFanD) || pFanB == Aig_Not(pFanC) || pFanB == Aig_Not(pFanD) )
+                return Aig_Not(p->pConst1);
+            if ( pFanA == pFanC || pFanB == pFanC )
+                return Aig_And( p, p0, pFanD );
+            if ( pFanB == pFanC || pFanB == pFanD )
+                return Aig_And( p, pFanA, p1 );
+            if ( pFanA == pFanD || pFanB == pFanD )
+                return Aig_And( p, p0, pFanC );
+            if ( pFanA == pFanC || pFanA == pFanD )
+                return Aig_And( p, pFanB, p1 );
+        }
+        else if ( Aig_IsComplement(p0) && !Aig_IsComplement(p1) )
+        {
+            if ( pFanA == Aig_Not(pFanC) || pFanA == Aig_Not(pFanD) || pFanB == Aig_Not(pFanC) || pFanB == Aig_Not(pFanD) )
+                return p1;
+            if ( pFanB == pFanC || pFanB == pFanD )
+                return Aig_And( p, Aig_Not(pFanA), p1 );
+            if ( pFanA == pFanC || pFanA == pFanD )
+                return Aig_And( p, Aig_Not(pFanB), p1 );
+        }
+        else if ( !Aig_IsComplement(p0) && Aig_IsComplement(p1) )
+        {
+            if ( pFanC == Aig_Not(pFanA) || pFanC == Aig_Not(pFanB) || pFanD == Aig_Not(pFanA) || pFanD == Aig_Not(pFanB) )
+                return p0;
+            if ( pFanD == pFanA || pFanD == pFanB )
+                return Aig_And( p, Aig_Not(pFanC), p0 );
+            if ( pFanC == pFanA || pFanC == pFanB )
+                return Aig_And( p, Aig_Not(pFanD), p0 );
+        }
+        else // if ( Aig_IsComplement(p0) && Aig_IsComplement(p1) )
+        {
+            if ( pFanA == pFanD && pFanB == Aig_Not(pFanC) )
+                return Aig_Not(pFanA);
+            if ( pFanB == pFanC && pFanA == Aig_Not(pFanD) )
+                return Aig_Not(pFanB);
+            if ( pFanA == pFanC && pFanB == Aig_Not(pFanD) )
+                return Aig_Not(pFanA);
+            if ( pFanB == pFanD && pFanA == Aig_Not(pFanC) )
+                return Aig_Not(pFanB);
+        }
+    }
+    // check if it can be an EXOR gate
+    if ( p->fCatchExor && Aig_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) )
+        return Aig_Exor( p, pFan0, pFan1 );
+    pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_OBJ_AND );
+    if ( (pResult = Aig_TableLookup( p, pGhost )) )
+        return pResult;
+    return Aig_ObjCreate( p, pGhost );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs canonicization step.]
+
+  Description [The argument nodes can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_Exor( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 )
+{
+    Aig_Obj_t * pGhost, * pResult;
+    int fCompl;
+    // check trivial cases
+    if ( p0 == p1 )
+        return Aig_Not(p->pConst1);
+    if ( p0 == Aig_Not(p1) )
+        return p->pConst1;
+    if ( Aig_Regular(p0) == p->pConst1 )
+        return Aig_NotCond( p1, p0 == p->pConst1 );
+    if ( Aig_Regular(p1) == p->pConst1 )
+        return Aig_NotCond( p0, p1 == p->pConst1 );
+    // when there is no special XOR gates
+    if ( !p->fCatchExor )
+        return Aig_Or( p, Aig_And(p, p0, Aig_Not(p1)), Aig_And(p, Aig_Not(p0), p1) );
+    // canonicize
+    fCompl = Aig_IsComplement(p0) ^ Aig_IsComplement(p1);
+    p0 = Aig_Regular(p0);
+    p1 = Aig_Regular(p1);
+    pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_OBJ_EXOR );
+    // check the table
+    if ( (pResult = Aig_TableLookup( p, pGhost )) )
+        return Aig_NotCond( pResult, fCompl );
+    pResult = Aig_ObjCreate( p, pGhost );
+    return Aig_NotCond( pResult, fCompl );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements Boolean OR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_Or( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 )
+{
+    return Aig_Not( Aig_And( p, Aig_Not(p0), Aig_Not(p1) ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements ITE operation.]
+
+  Description [] 
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_TableLookupInt( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 )
+{
+    if ( p0 == p1 )
+        return p0;
+    if ( p0 == Aig_ManConst0(p) || p1 == Aig_ManConst0(p) || p0 == Aig_Not(p1) )
+        return Aig_ManConst0(p);
+    if ( p0 == Aig_ManConst1(p) )
+        return p1;
+    if ( p1 == Aig_ManConst1(p) )
+        return p0;
+    if ( Aig_Regular(p0)->Id < Aig_Regular(p1)->Id )
+        return Aig_TableLookup( p, Aig_ObjCreateGhost(p, p0, p1, AIG_OBJ_AND) );
+    return Aig_TableLookup( p, Aig_ObjCreateGhost(p, p1, p0, AIG_OBJ_AND) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements ITE operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_Mux2( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 )
+{
+    return Aig_Or( p, Aig_And(p, pC, p1), Aig_And(p, Aig_Not(pC), p0) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements ITE operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_Mux( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 )
+{
+    int fUseMuxCanon = 0;
+    Aig_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp;
+    int Count0, Count1;
+    if ( !fUseMuxCanon )
+        return Aig_Mux2( p, pC, p1, p0 );
+    if ( p0 == p1 )
+        return p0;
+    if ( p1 == Aig_Not(p0) )
+        return Aig_Exor( p, pC, p0 );
+    if ( pC == Aig_ManConst0(p) )
+        return p0;
+    if ( pC == Aig_ManConst1(p) )
+        return p1;
+    if ( p0 == Aig_ManConst0(p) )
+        return Aig_And( p, pC, p1 );
+    if ( p0 == Aig_ManConst1(p) )
+        return Aig_Or( p, Aig_Not(pC), p1 );
+    if ( p1 == Aig_ManConst0(p) )
+        return Aig_And( p, Aig_Not(pC), p0 );
+    if ( p1 == Aig_ManConst1(p) )
+        return Aig_Or( p, pC, p0 );
+    // implement the first MUX (F = C * x1 + C' * x0)
+    pTempA1 = Aig_TableLookupInt( p, pC,          p1 );
+    pTempA2 = Aig_TableLookupInt( p, Aig_Not(pC), p0 );
+    if ( pTempA1 && pTempA2 )
+    {
+        pTemp = Aig_TableLookupInt( p, Aig_Not(pTempA1), Aig_Not(pTempA2) );
+        if ( pTemp ) return Aig_Not(pTemp);
+    }
+    Count0 = (pTempA1 != NULL) + (pTempA2 != NULL);
+    // implement the second MUX (F' = C * x1' + C' * x0')
+    pTempB1 = Aig_TableLookupInt( p, pC,          Aig_Not(p1) );
+    pTempB2 = Aig_TableLookupInt( p, Aig_Not(pC), Aig_Not(p0) );
+    if ( pTempB1 && pTempB2 )
+    {
+        pTemp = Aig_TableLookupInt( p, Aig_Not(pTempB1), Aig_Not(pTempB2) );
+        if ( pTemp ) return pTemp;
+    }
+    Count1 = (pTempB1 != NULL) + (pTempB2 != NULL);
+    // compare and decide which one to implement
+    if ( Count0 >= Count1 )
+        return Aig_Or( p, Aig_And(p, pC, p1), Aig_And(p, Aig_Not(pC), p0) );
+    return Aig_Not( Aig_Or( p, Aig_And(p, pC, Aig_Not(p1)), Aig_And(p, Aig_Not(pC), Aig_Not(p0)) ) );
+//    return Aig_Or( p, Aig_And(p, pC, p1), Aig_And(p, Aig_Not(pC), p0) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements ITE operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_Maj( Aig_Man_t * p, Aig_Obj_t * pA, Aig_Obj_t * pB, Aig_Obj_t * pC )
+{
+    return Aig_Or( p, Aig_Or(p, Aig_And(p, pA, pB), Aig_And(p, pA, pC)), Aig_And(p, pB, pC) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs the well-balanced tree of gates.]
+
+  Description [Disregards levels and possible logic sharing.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_Multi_rec( Aig_Man_t * p, Aig_Obj_t ** ppObjs, int nObjs, Aig_Type_t Type )
+{
+    Aig_Obj_t * pObj1, * pObj2;
+    if ( nObjs == 1 )
+        return ppObjs[0];
+    pObj1 = Aig_Multi_rec( p, ppObjs,           nObjs/2,         Type );
+    pObj2 = Aig_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type );
+    return Aig_Oper( p, pObj1, pObj2, Type );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Old code.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_Multi( Aig_Man_t * p, Aig_Obj_t ** pArgs, int nArgs, Aig_Type_t Type )
+{
+    assert( Type == AIG_OBJ_AND || Type == AIG_OBJ_EXOR );
+    assert( nArgs > 0 );
+    return Aig_Multi_rec( p, pArgs, nArgs, Type );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs )
+{
+    int i;
+    assert( vPairs->nSize > 0 );
+    assert( vPairs->nSize % 2 == 0 );
+    for ( i = 0; i < vPairs->nSize; i += 2 )
+        vPairs->pArray[i/2] = Aig_Not( Aig_Exor( p, (Aig_Obj_t *)vPairs->pArray[i], (Aig_Obj_t *)vPairs->pArray[i+1] ) );
+    vPairs->nSize = vPairs->nSize/2;
+    return Aig_Not( Aig_Multi_rec( p, (Aig_Obj_t **)vPairs->pArray, vPairs->nSize, AIG_OBJ_AND ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_MiterTwo( Aig_Man_t * p, Vec_Ptr_t * vNodes1, Vec_Ptr_t * vNodes2 )
+{
+    int i;
+    assert( vNodes1->nSize > 0 && vNodes1->nSize > 0 );
+    assert( vNodes1->nSize == vNodes2->nSize );
+    for ( i = 0; i < vNodes1->nSize; i++ )
+        vNodes1->pArray[i] = Aig_Not( Aig_Exor( p, (Aig_Obj_t *)vNodes1->pArray[i], (Aig_Obj_t *)vNodes2->pArray[i] ) );
+    return Aig_Not( Aig_Multi_rec( p, (Aig_Obj_t **)vNodes1->pArray, vNodes1->nSize, AIG_OBJ_AND ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates AND function with nVars inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_CreateAnd( Aig_Man_t * p, int nVars )
+{
+    Aig_Obj_t * pFunc;
+    int i;
+    pFunc = Aig_ManConst1( p );
+    for ( i = 0; i < nVars; i++ )
+        pFunc = Aig_And( p, pFunc, Aig_IthVar(p, i) );
+    return pFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates AND function with nVars inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_CreateOr( Aig_Man_t * p, int nVars )
+{
+    Aig_Obj_t * pFunc;
+    int i;
+    pFunc = Aig_ManConst0( p );
+    for ( i = 0; i < nVars; i++ )
+        pFunc = Aig_Or( p, pFunc, Aig_IthVar(p, i) );
+    return pFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates AND function with nVars inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_CreateExor( Aig_Man_t * p, int nVars )
+{
+    Aig_Obj_t * pFunc;
+    int i;
+    pFunc = Aig_ManConst0( p );
+    for ( i = 0; i < nVars; i++ )
+        pFunc = Aig_Exor( p, pFunc, Aig_IthVar(p, i) );
+    return pFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements ITE operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_MuxTest()
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Man_t * p;
+    Aig_Obj_t * pObj, * pFanin0, * pFanin1, * pCtrl;    
+    int nNodes  = 2000;
+    int i,nPIs  =   20;
+//    srand( time(NULL) );
+    srand( 321 );
+    vNodes = Vec_PtrAlloc( 100 );
+    // create a bunch of random MUXes
+    p = Aig_ManStart( 10000 );
+    for ( i = 0; i < nPIs; i++ )
+        Aig_IthVar(p,i);
+    for ( i = 0; i < nNodes; i++ )
+    {
+        if ( rand() % 10 == 0 )
+            pCtrl = Aig_ManConst0(p);
+        else if ( rand() % 10 == 0 )
+            pCtrl = Aig_ManConst1(p);
+        else if ( rand() % 3 == 0 || i < nPIs )
+            pCtrl = Aig_IthVar( p, rand() % nPIs );
+        else
+            pCtrl = (Aig_Obj_t *)Vec_PtrEntry(vNodes, rand() % i);
+        if ( rand() % 2 == 0 )
+            pCtrl = Aig_Not( pCtrl );
+
+        if ( rand() % 10 == 0 )
+            pFanin1 = Aig_ManConst0(p);
+        else if ( rand() % 10 == 0 )
+            pFanin1 = Aig_ManConst1(p);
+        else if ( rand() % 3 == 0 || i < nPIs )
+            pFanin1 = Aig_IthVar( p, rand() % nPIs );
+        else
+            pFanin1 = (Aig_Obj_t *)Vec_PtrEntry(vNodes, rand() % i);
+        if ( rand() % 2 == 0 )
+            pFanin1 = Aig_Not( pFanin1 );
+
+        if ( rand() % 10 == 0 )
+            pFanin0 = Aig_ManConst0(p);
+        else if ( rand() % 10 == 0 )
+            pFanin0 = Aig_ManConst1(p);
+        else if ( rand() % 3 == 0 || i < nPIs )
+            pFanin0 = Aig_IthVar( p, rand() % nPIs );
+        else
+            pFanin0 = (Aig_Obj_t *)Vec_PtrEntry(vNodes, rand() % i);
+        if ( rand() % 2 == 0 )
+            pFanin0 = Aig_Not( pFanin0 );
+
+        pObj = Aig_Mux( p, pCtrl, pFanin1, pFanin0 );
+        Vec_PtrPush( vNodes, pObj );
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        Aig_ObjCreateCo( p, pObj );
+    Vec_PtrFree( vNodes );
+
+    printf( "Number of nodes = %6d.\n", Aig_ManObjNum(p) );
+    Aig_ManCleanup( p );
+    printf( "Number of nodes = %6d.\n", Aig_ManObjNum(p) );
+    Aig_ManDumpBlif( p, "test1.blif", NULL, NULL );
+    Aig_ManStop( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigOrder.c b/abc-build/src/aig/aig/aigOrder.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigOrder.c
@@ -0,0 +1,176 @@
+/**CFile****************************************************************
+
+  FileName    [aigOrder.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Dynamically updated topological order.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigOrder.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Initializes the order datastructure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManOrderStart( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    assert( Aig_ManBufNum(p) == 0 );
+    // allocate order datastructure
+    assert( p->pOrderData == NULL );
+    p->nOrderAlloc = 2 * Aig_ManObjNumMax(p);
+    if ( p->nOrderAlloc < (1<<12) )
+        p->nOrderAlloc = (1<<12);
+    p->pOrderData = ABC_ALLOC( unsigned, 2 * p->nOrderAlloc );
+    memset( p->pOrderData, 0xFF, sizeof(unsigned) * 2 * p->nOrderAlloc );
+    // add the constant node
+    p->pOrderData[0] = p->pOrderData[1] = 0;
+    p->iPrev = p->iNext = 0;
+    // add the internal nodes
+    Aig_ManForEachNode( p, pObj, i )
+        Aig_ObjOrderInsert( p, pObj->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the order datastructure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManOrderStop( Aig_Man_t * p )
+{
+    assert( p->pOrderData );
+    ABC_FREE( p->pOrderData );
+    p->nOrderAlloc = 0;
+    p->iPrev = p->iNext = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts an entry before iNext.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjOrderInsert( Aig_Man_t * p, int ObjId )
+{
+    int iPrev;
+    assert( ObjId != 0 );
+    assert( Aig_ObjIsNode( Aig_ManObj(p, ObjId) ) );
+    if ( ObjId >= p->nOrderAlloc )
+    {
+        int nOrderAlloc = 2 * ObjId; 
+        p->pOrderData = ABC_REALLOC( unsigned, p->pOrderData, 2 * nOrderAlloc );
+        memset( p->pOrderData + 2 * p->nOrderAlloc, 0xFF, sizeof(unsigned) * 2 * (nOrderAlloc - p->nOrderAlloc) );
+        p->nOrderAlloc = nOrderAlloc;
+    }
+    assert( p->pOrderData[2*ObjId] == 0xFFFFFFFF );   // prev
+    assert( p->pOrderData[2*ObjId+1] == 0xFFFFFFFF ); // next
+    iPrev = p->pOrderData[2*p->iNext];
+    assert( p->pOrderData[2*iPrev+1] == (unsigned)p->iNext );
+    p->pOrderData[2*ObjId] = iPrev;
+    p->pOrderData[2*iPrev+1] = ObjId;
+    p->pOrderData[2*p->iNext] = ObjId;
+    p->pOrderData[2*ObjId+1] = p->iNext;
+    p->nAndTotal++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes the entry.]
+
+  Description [If iPrev is removed, it slides backward. 
+  If iNext is removed, it slides forward.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjOrderRemove( Aig_Man_t * p, int ObjId )
+{
+    int iPrev, iNext;
+    assert( ObjId != 0 );
+    assert( Aig_ObjIsNode( Aig_ManObj(p, ObjId) ) );
+    iPrev = p->pOrderData[2*ObjId];
+    iNext = p->pOrderData[2*ObjId+1];
+    p->pOrderData[2*ObjId] = 0xFFFFFFFF;
+    p->pOrderData[2*ObjId+1] = 0xFFFFFFFF;
+    p->pOrderData[2*iNext] = iPrev;
+    p->pOrderData[2*iPrev+1] = iNext;
+    if ( p->iPrev == ObjId )
+    {
+        p->nAndPrev--;
+        p->iPrev = iPrev;
+    }
+    if ( p->iNext == ObjId )
+        p->iNext = iNext;
+    p->nAndTotal--;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Advances the order forward.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjOrderAdvance( Aig_Man_t * p )
+{
+    assert( p->pOrderData );
+    assert( p->pOrderData[2*p->iPrev+1] == (unsigned)p->iNext );
+    p->iPrev = p->iNext;
+    p->nAndPrev++;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigPack.c b/abc-build/src/aig/aig/aigPack.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigPack.c
@@ -0,0 +1,404 @@
+/**CFile****************************************************************
+ 
+  FileName    [aigPack.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Bit-packing code.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigPack.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// resubstitution manager
+typedef struct Aig_ManPack_t_ Aig_ManPack_t;
+struct Aig_ManPack_t_
+{
+    Aig_Man_t *        pAig;        // working manager 
+    Vec_Wrd_t *        vSigns;      // object signatures
+    Vec_Wrd_t *        vPiPats;     // PI assignments
+    Vec_Wrd_t *        vPiCare;     // PI care set
+    int                iPatCur;     // current pattern
+    int                fVerbose;    // verbosiness flag
+    // statistics
+    int                nPatTotal;   // number of all patterns
+    int                nPatSkip;    // number of skipped patterns
+    int                nPatRepeat;  // number of repeated patterns
+};
+
+static inline int Aig_Word6CountOnes( word t )  { return Aig_WordCountOnes( (unsigned)(t >> 32) ) + Aig_WordCountOnes( (unsigned)(t & 0xFFFFFFFF) ); }
+static inline int Aig_Word6HasOneBit( word t )  { return (t & (t-1)) == 0; }
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_ManPack_t * Aig_ManPackAlloc( Aig_Man_t * pAig )
+{
+    Aig_ManPack_t * p;
+    p = ABC_CALLOC( Aig_ManPack_t, 1 );
+    p->pAig    = pAig;
+    p->vSigns  = Vec_WrdStart( Aig_ManObjNumMax(pAig) );
+    p->vPiPats = Vec_WrdStart( Aig_ManCiNum(pAig) );
+    p->vPiCare = Vec_WrdStart( Aig_ManCiNum(pAig) );
+    p->iPatCur = 1;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManPackCountCares( Aig_ManPack_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, Total = 0;
+    Aig_ManForEachCi( p->pAig, pObj, i )
+        Total += Aig_Word6CountOnes( Vec_WrdEntry(p->vPiCare, i) );
+    return Total;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManPackPrintCare( Aig_ManPack_t * p )
+{
+    Aig_Obj_t * pObj;
+    word Sign;
+    int i;
+    Aig_ManForEachCi( p->pAig, pObj, i )
+    {
+        Sign = Vec_WrdEntry( p->vPiCare, i );
+//        Extra_PrintBinary( stdout, (unsigned *)&Sign, 64 );
+//        printf( "\n" );
+    }
+//    printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManPackFree( Aig_ManPack_t * p )
+{
+//    Aig_ManPackPrintCare( p );
+    printf( "Patterns: " );
+    printf( "Total = %6d. ",   p->nPatTotal );
+    printf( "Skipped = %6d. ", p->nPatSkip );
+    printf( "Cares = %6.2f %%  ", 100.0*Aig_ManPackCountCares(p)/Aig_ManCiNum(p->pAig)/64 );
+    printf( "\n" );
+    Vec_WrdFree( p->vSigns );
+    Vec_WrdFree( p->vPiPats );
+    Vec_WrdFree( p->vPiCare );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManPackSetRandom( Aig_ManPack_t * p )
+{
+    Aig_Obj_t * pObj;
+    word Sign;
+    int i;
+    Aig_ManForEachCi( p->pAig, pObj, i )
+    {
+        Sign = (((word)Aig_ManRandom(0)) << 32) | ((word)Aig_ManRandom(0));
+        Vec_WrdWriteEntry( p->vPiPats, i, Sign << 1 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManPackSimulate( Aig_ManPack_t * p )
+{
+    Aig_Obj_t * pObj;
+    word Sign, Sign0, Sign1;
+    int i;
+    // set the constant
+    Vec_WrdWriteEntry( p->vSigns, 0, ~(word)0 );
+    // transfer into the array
+    Aig_ManForEachCi( p->pAig, pObj, i )
+        Vec_WrdWriteEntry( p->vSigns, Aig_ObjId(pObj), Vec_WrdEntry(p->vPiPats, i) );
+    // simulate internal nodes
+    Aig_ManForEachNode( p->pAig, pObj, i )
+    {
+        Sign0 = Vec_WrdEntry( p->vSigns, Aig_ObjFaninId0(pObj) );
+        Sign1 = Vec_WrdEntry( p->vSigns, Aig_ObjFaninId1(pObj) );
+        if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) )
+            Sign = ~(Sign0 | Sign1);
+        else if ( Aig_ObjFaninC0(pObj) )
+            Sign = ~Sign0 &  Sign1;
+        else if ( Aig_ObjFaninC1(pObj) )
+            Sign =  Sign0 & ~Sign1;
+        else
+            Sign =  Sign0 &  Sign1;
+        Vec_WrdWriteEntry( p->vSigns, Aig_ObjId(pObj), Sign );
+    }
+    // set the outputs
+    Aig_ManForEachCo( p->pAig, pObj, i )
+    {
+        Sign0 = Vec_WrdEntry( p->vSigns, Aig_ObjFaninId0(pObj) );
+        Sign  = Aig_ObjFaninC0(pObj) ? ~Sign0 : Sign0;
+        Vec_WrdWriteEntry( p->vSigns, Aig_ObjId(pObj), Sign );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManPackPrintStats( Aig_ManPack_t * p )
+{
+    word Sign;
+    Aig_Obj_t * pObj;
+    int i, Total, Count, Counts[33] = {0}; // the number of nodes having that many patterns
+    Aig_ManForEachNode( p->pAig, pObj, i )
+    {
+        Sign  = Vec_WrdEntry( p->vSigns, Aig_ObjId(pObj) );
+        Count = Aig_Word6CountOnes( Sign );
+        if ( Count > 32 )
+            Count = 64 - Count;
+        Counts[Count]++;        
+    }
+    // print statistics
+    Total = 0;
+    for ( i = 0; i <= 32; i++ )
+    {
+        Total += Counts[i];
+        printf( "%2d : ", i );
+        printf( "%6d  ", Counts[i] );
+        printf( "%6.1f %%", 100.0*Counts[i]/Aig_ManNodeNum(p->pAig) );
+        printf( "%6.1f %%", 100.0*Total/Aig_ManNodeNum(p->pAig) );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Aig_ManPackConstNodes( Aig_ManPack_t * p )
+{
+    Vec_Int_t * vNodes;
+    Aig_Obj_t * pObj;
+    word Sign;
+    int i;
+    vNodes = Vec_IntAlloc( 1000 );
+    Aig_ManForEachNode( p->pAig, pObj, i )
+    {
+        Sign  = Vec_WrdEntry( p->vSigns, Aig_ObjId(pObj) );
+        if ( Sign == 0 || ~Sign == 0 || Aig_Word6HasOneBit(Sign) || Aig_Word6HasOneBit(~Sign) )
+            Vec_IntPush( vNodes, Aig_ObjId(pObj) );
+    }
+    return vNodes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Packs patterns into array of simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+*************************************`**********************************/
+int Aig_ManPackAddPatternTry( Aig_ManPack_t * p, int iBit, Vec_Int_t * vLits )
+{
+    word * pInfo, * pPres;
+    int i, Lit;
+    Vec_IntForEachEntry( vLits, Lit, i )
+    {
+        pInfo = Vec_WrdEntryP( p->vPiPats, Abc_Lit2Var(Lit) );
+        pPres = Vec_WrdEntryP( p->vPiCare, Abc_Lit2Var(Lit) );
+        if ( Abc_InfoHasBit( (unsigned *)pPres, iBit ) && 
+             Abc_InfoHasBit( (unsigned *)pInfo, iBit ) == Abc_LitIsCompl(Lit) )
+             return 0;
+    }
+    Vec_IntForEachEntry( vLits, Lit, i )
+    {
+        pInfo = Vec_WrdEntryP( p->vPiPats, Abc_Lit2Var(Lit) );
+        pPres = Vec_WrdEntryP( p->vPiCare, Abc_Lit2Var(Lit) );
+        Abc_InfoSetBit( (unsigned *)pPres, iBit );
+        if ( Abc_InfoHasBit( (unsigned *)pInfo, iBit ) == Abc_LitIsCompl(Lit) )
+             Abc_InfoXorBit( (unsigned *)pInfo, iBit );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManPackAddPattern( Aig_ManPack_t * p, Vec_Int_t * vLits )
+{
+    int k;
+    for ( k = 1; k < 64; k++ )
+        if ( Aig_ManPackAddPatternTry( p, k, vLits ) )
+            break;
+    if ( k == 64 )
+    {
+/*
+        word * pInfo, * pPres;
+        int i, Lit;
+        Vec_IntForEachEntry( vLits, Lit, i )
+            printf( "%d", Abc_LitIsCompl(Lit) );
+        printf( "\n\n" );
+        for ( k = 1; k < 64; k++ )
+        {
+            Vec_IntForEachEntry( vLits, Lit, i )
+            {
+                pInfo = Vec_WrdEntryP( p->vPiPats, Abc_Lit2Var(Lit) );
+                pPres = Vec_WrdEntryP( p->vPiCare, Abc_Lit2Var(Lit) );
+                if ( Abc_InfoHasBit( (unsigned *)pPres, k ) )
+                    printf( "%d", Abc_InfoHasBit( (unsigned *)pInfo, k ) );
+                else
+                    printf( "-" );
+            }
+            printf( "\n" );
+        }
+*/
+        p->nPatSkip++;
+    }
+    p->nPatTotal++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_ManPack_t * Aig_ManPackStart( Aig_Man_t * pAig )
+{
+    Aig_ManPack_t * p;
+    p = Aig_ManPackAlloc( pAig );
+    Aig_ManPackSetRandom( p );
+    Aig_ManPackSimulate( p );
+    Aig_ManPackPrintStats( p );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManPackStop( Aig_ManPack_t * p )
+{
+    Aig_ManPackSimulate( p );
+    Aig_ManPackPrintStats( p );
+    Aig_ManPackFree( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigPart.c b/abc-build/src/aig/aig/aigPart.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigPart.c
@@ -0,0 +1,1613 @@
+/**CFile****************************************************************
+
+  FileName    [aigPart.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [AIG partitioning package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigPart.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+#include "misc/tim/tim.h"
+#include "proof/fra/fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Part_Man_t_     Part_Man_t;
+struct Part_Man_t_
+{
+    int              nChunkSize;    // the size of one chunk of memory (~1 MB)
+    int              nStepSize;     // the step size in saving memory (~64 bytes)
+    char *           pFreeBuf;      // the pointer to free memory
+    int              nFreeSize;     // the size of remaining free memory
+    Vec_Ptr_t *      vMemory;       // the memory allocated
+    Vec_Ptr_t *      vFree;         // the vector of free pieces of memory
+};
+
+typedef struct Part_One_t_     Part_One_t;
+struct Part_One_t_
+{
+    int              nRefs;         // the number of references
+    int              nOuts;         // the number of outputs
+    int              nOutsAlloc;    // the array size
+    int              pOuts[0];      // the array of outputs
+};
+
+static inline int    Part_SizeType( int nSize, int nStepSize )     { return nSize / nStepSize + ((nSize % nStepSize) > 0); }
+static inline char * Part_OneNext( char * pPart )                  { return *((char **)pPart);                             }
+static inline void   Part_OneSetNext( char * pPart, char * pNext ) { *((char **)pPart) = pNext;                            }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Start the memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Part_Man_t * Part_ManStart( int nChunkSize, int nStepSize )
+{
+    Part_Man_t * p;
+    p = ABC_ALLOC( Part_Man_t, 1 );
+    memset( p, 0, sizeof(Part_Man_t) );
+    p->nChunkSize = nChunkSize;
+    p->nStepSize  = nStepSize;
+    p->vMemory    = Vec_PtrAlloc( 1000 );
+    p->vFree      = Vec_PtrAlloc( 1000 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Part_ManStop( Part_Man_t * p )
+{
+    void * pMemory;
+    int i;
+    Vec_PtrForEachEntry( void *, p->vMemory, pMemory, i )
+        ABC_FREE( pMemory );
+    Vec_PtrFree( p->vMemory );
+    Vec_PtrFree( p->vFree );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fetches the memory entry of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Part_ManFetch( Part_Man_t * p, int nSize )
+{
+    int Type, nSizeReal;
+    char * pMemory;
+    assert( nSize > 0 );
+    Type = Part_SizeType( nSize, p->nStepSize );
+    Vec_PtrFillExtra( p->vFree, Type + 1, NULL );
+    if ( (pMemory = (char *)Vec_PtrEntry( p->vFree, Type )) )
+    {
+        Vec_PtrWriteEntry( p->vFree, Type, Part_OneNext(pMemory) );
+        return pMemory;
+    }
+    nSizeReal = p->nStepSize * Type;
+    if ( p->nFreeSize < nSizeReal )
+    {
+        p->pFreeBuf = ABC_ALLOC( char, p->nChunkSize );
+        p->nFreeSize = p->nChunkSize;
+        Vec_PtrPush( p->vMemory, p->pFreeBuf );
+    }
+    assert( p->nFreeSize >= nSizeReal );
+    pMemory = p->pFreeBuf;
+    p->pFreeBuf  += nSizeReal;
+    p->nFreeSize -= nSizeReal;
+    return pMemory;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the memory entry of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Part_ManRecycle( Part_Man_t * p, char * pMemory, int nSize )
+{
+    int Type;
+    Type = Part_SizeType( nSize, p->nStepSize );
+    Vec_PtrFillExtra( p->vFree, Type + 1, NULL );
+    Part_OneSetNext( pMemory, (char *)Vec_PtrEntry(p->vFree, Type) );
+    Vec_PtrWriteEntry( p->vFree, Type, pMemory );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fetches the memory entry of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Part_One_t * Part_ManFetchEntry( Part_Man_t * p, int nWords, int nRefs )
+{
+    Part_One_t * pPart;
+    pPart = (Part_One_t *)Part_ManFetch( p, sizeof(Part_One_t) + sizeof(int) * nWords );
+    pPart->nRefs = nRefs;
+    pPart->nOuts = 0;
+    pPart->nOutsAlloc = nWords;
+    return pPart;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the memory entry of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Part_ManRecycleEntry( Part_Man_t * p, Part_One_t * pEntry )
+{
+    assert( pEntry->nOuts <= pEntry->nOutsAlloc );
+    assert( pEntry->nOuts >= pEntry->nOutsAlloc/2 );
+    Part_ManRecycle( p, (char *)pEntry, sizeof(Part_One_t) + sizeof(int) * pEntry->nOutsAlloc );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Part_One_t * Part_ManMergeEntry( Part_Man_t * pMan, Part_One_t * p1, Part_One_t * p2, int nRefs )
+{
+    Part_One_t * p = Part_ManFetchEntry( pMan, p1->nOuts + p2->nOuts, nRefs );
+    int * pBeg1 = p1->pOuts;
+    int * pBeg2 = p2->pOuts;
+    int * pBeg  = p->pOuts;
+    int * pEnd1 = p1->pOuts + p1->nOuts;
+    int * pEnd2 = p2->pOuts + p2->nOuts;
+    while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+    {
+        if ( *pBeg1 == *pBeg2 )
+            *pBeg++ = *pBeg1++, pBeg2++;
+        else if ( *pBeg1 < *pBeg2 )
+            *pBeg++ = *pBeg1++;
+        else 
+            *pBeg++ = *pBeg2++;
+    }
+    while ( pBeg1 < pEnd1 )
+        *pBeg++ = *pBeg1++;
+    while ( pBeg2 < pEnd2 )
+        *pBeg++ = *pBeg2++;
+    p->nOuts = pBeg - p->pOuts;
+    assert( p->nOuts <= p->nOutsAlloc );
+    assert( p->nOuts >= p1->nOuts );
+    assert( p->nOuts >= p2->nOuts );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tranfers the entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Part_ManTransferEntry( Part_One_t * p )
+{
+    Vec_Int_t * vSupp;
+    int i;
+    vSupp = Vec_IntAlloc( p->nOuts );
+    for ( i = 0; i < p->nOuts; i++ )
+        Vec_IntPush( vSupp, p->pOuts[i] );
+    return vSupp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes supports of the POs in the multi-output AIG.]
+
+  Description [Returns the array of integer arrays containing indices
+  of the primary inputs for each primary output.]
+               
+  SideEffects [Adds the integer PO number at end of each array.]
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManSupports( Aig_Man_t * pMan )
+{
+    Vec_Ptr_t * vSupports;
+    Vec_Int_t * vSupp;
+    Part_Man_t * p;
+    Part_One_t * pPart0, * pPart1;
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    // set the number of PIs/POs
+    Aig_ManForEachCi( pMan, pObj, i )
+        pObj->pNext = (Aig_Obj_t *)(long)i;
+    Aig_ManForEachCo( pMan, pObj, i )
+        pObj->pNext = (Aig_Obj_t *)(long)i;
+    // start the support computation manager
+    p = Part_ManStart( 1 << 20, 1 << 6 );
+    // consider objects in the topological order
+    vSupports = Vec_PtrAlloc( Aig_ManCoNum(pMan) );
+    Aig_ManCleanData(pMan);
+    Aig_ManForEachObj( pMan, pObj, i )
+    {
+        if ( Aig_ObjIsNode(pObj) )
+        {
+            pPart0 = (Part_One_t *)Aig_ObjFanin0(pObj)->pData;
+            pPart1 = (Part_One_t *)Aig_ObjFanin1(pObj)->pData;
+            pObj->pData = Part_ManMergeEntry( p, pPart0, pPart1, pObj->nRefs );
+            assert( pPart0->nRefs > 0 );
+            if ( --pPart0->nRefs == 0 )
+                Part_ManRecycleEntry( p, pPart0 );
+            assert( pPart1->nRefs > 0 );
+            if ( --pPart1->nRefs == 0 )
+                Part_ManRecycleEntry( p, pPart1 );
+            if ( ((Part_One_t *)pObj->pData)->nOuts <= 16 )
+                Counter++;
+            continue;
+        }
+        if ( Aig_ObjIsCo(pObj) )
+        {
+            pPart0 = (Part_One_t *)Aig_ObjFanin0(pObj)->pData;
+            vSupp = Part_ManTransferEntry(pPart0);
+            Vec_IntPush( vSupp, (int)(long)pObj->pNext );
+            Vec_PtrPush( vSupports, vSupp );
+            assert( pPart0->nRefs > 0 );
+            if ( --pPart0->nRefs == 0 )
+                Part_ManRecycleEntry( p, pPart0 );
+            continue;
+        }
+        if ( Aig_ObjIsCi(pObj) )
+        {
+            if ( pObj->nRefs )
+            {
+                pPart0 = Part_ManFetchEntry( p, 1, pObj->nRefs );
+                pPart0->pOuts[ pPart0->nOuts++ ] = (int)(long)pObj->pNext;
+                pObj->pData = pPart0;
+            }
+            continue;
+        }
+        if ( Aig_ObjIsConst1(pObj) )
+        {
+            if ( pObj->nRefs )
+                pObj->pData = Part_ManFetchEntry( p, 0, pObj->nRefs );
+            continue;
+        }
+        assert( 0 );
+    }
+//printf( "Memory usage = %d MB.\n", Vec_PtrSize(p->vMemory) * p->nChunkSize / (1<<20) );
+    Part_ManStop( p );
+    // sort supports by size
+    Vec_VecSort( (Vec_Vec_t *)vSupports, 1 );
+    // clear the number of PIs/POs
+    Aig_ManForEachCi( pMan, pObj, i )
+        pObj->pNext = NULL;
+    Aig_ManForEachCo( pMan, pObj, i )
+        pObj->pNext = NULL;
+/*
+    Aig_ManForEachCo( pMan, pObj, i )
+        printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vSupports, i) ) );
+    printf( "\n" );
+*/
+//    printf( "%d \n", Counter );
+    return vSupports;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManSupportsTest( Aig_Man_t * pMan )
+{
+    Vec_Ptr_t * vSupps;
+    vSupps = Aig_ManSupports( pMan );
+    Vec_VecFree( (Vec_Vec_t *)vSupps );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the set of outputs for each input.]
+
+  Description [Returns the array of integer arrays containing indices
+  of the primary outputsf for each primary input.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManSupportsInverse( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vSupps, * vSuppsInv;
+    Vec_Int_t * vSupp;
+    int i, k, iIn, iOut;
+    // get structural supports for each output
+    vSupps = Aig_ManSupports( p );
+    // start the inverse supports
+    vSuppsInv = Vec_PtrAlloc( Aig_ManCiNum(p) );
+    for ( i = 0; i < Aig_ManCiNum(p); i++ )
+        Vec_PtrPush( vSuppsInv, Vec_IntAlloc(8) );
+    // transforms the supports into the inverse supports
+    Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vSupp, i )
+    {
+        iOut = Vec_IntPop( vSupp );
+        Vec_IntForEachEntry( vSupp, iIn, k )
+            Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vSuppsInv, iIn), iOut );
+    }
+    Vec_VecFree( (Vec_Vec_t *)vSupps );
+    return vSuppsInv;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the register dependency matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManSupportsRegisters( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vSupports, * vMatrix;
+    Vec_Int_t * vSupp;
+    int iOut, iIn, k, m, i;
+    // get structural supports for each output
+    vSupports = Aig_ManSupports( p );
+    // transforms the supports into the latch dependency matrix
+    vMatrix = Vec_PtrStart( Aig_ManRegNum(p) );
+    Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vSupp, i )
+    {
+        // skip true POs
+        iOut = Vec_IntPop( vSupp );
+        iOut -= Aig_ManCoNum(p) - Aig_ManRegNum(p);
+        if ( iOut < 0 )
+        {
+            Vec_IntFree( vSupp );
+            continue;
+        }
+        // remove PIs
+        m = 0;
+        Vec_IntForEachEntry( vSupp, iIn, k )
+        {
+            iIn -= Aig_ManCiNum(p) - Aig_ManRegNum(p);
+            if ( iIn < 0 )
+                continue;
+            assert( iIn < Aig_ManRegNum(p) );
+            Vec_IntWriteEntry( vSupp, m++, iIn );
+        }
+        Vec_IntShrink( vSupp, m );
+        // store support in the matrix
+        assert( iOut < Aig_ManRegNum(p) );
+        Vec_PtrWriteEntry( vMatrix, iOut, vSupp );
+    }
+    Vec_PtrFree( vSupports );
+    // check that all supports are used
+    Vec_PtrForEachEntry( Vec_Int_t *, vMatrix, vSupp, i )
+        assert( vSupp != NULL );
+    return vMatrix;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Start char-bases support representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Aig_ManSuppCharStart( Vec_Int_t * vOne, int nPis )
+{
+    unsigned * pBuffer;
+    int i, Entry;
+    int nWords = Abc_BitWordNum(nPis);
+    pBuffer = ABC_ALLOC( unsigned, nWords );
+    memset( pBuffer, 0, sizeof(unsigned) * nWords );
+    Vec_IntForEachEntry( vOne, Entry, i )
+    {
+        assert( Entry < nPis );
+        Abc_InfoSetBit( pBuffer, Entry );
+    }
+    return pBuffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add to char-bases support representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManSuppCharAdd( unsigned * pBuffer, Vec_Int_t * vOne, int nPis )
+{
+    int i, Entry;
+    Vec_IntForEachEntry( vOne, Entry, i )
+    {
+        assert( Entry < nPis );
+        Abc_InfoSetBit( pBuffer, Entry );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the common variables using char-bases support representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManSuppCharCommon( unsigned * pBuffer, Vec_Int_t * vOne )
+{
+    int i, Entry, nCommon = 0;
+    Vec_IntForEachEntry( vOne, Entry, i )
+        nCommon += Abc_InfoHasBit(pBuffer, Entry);
+    return nCommon;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the best partition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsBit, int nSuppSizeLimit, Vec_Int_t * vOne )
+{
+    Vec_Int_t * vPartSupp;//, * vPart;
+    int Attract, Repulse, Value, ValueBest;
+    int i, nCommon, iBest;
+    iBest = -1;
+    ValueBest = 0;
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vPartSupp, i )
+    {
+//        vPart = Vec_PtrEntry( vPartsAll, i );
+//        if ( nSuppSizeLimit > 0 && Vec_IntSize(vPart) >= nSuppSizeLimit )
+//            continue;
+//        nCommon = Vec_IntTwoCountCommon( vPartSupp, vOne );
+        nCommon = Aig_ManSuppCharCommon( (unsigned *)Vec_PtrEntry(vPartSuppsBit, i), vOne );
+        if ( nCommon == 0 )
+            continue;
+        if ( nCommon == Vec_IntSize(vOne) )
+            return i;
+        // skip partitions whose size exceeds the limit
+        if ( nSuppSizeLimit > 0 && Vec_IntSize(vPartSupp) >= 2 * nSuppSizeLimit )
+            continue;
+        Attract = 1000 * nCommon / Vec_IntSize(vOne);
+        if ( Vec_IntSize(vPartSupp) < 100 )
+            Repulse = 1;
+        else
+            Repulse = 1+Abc_Base2Log(Vec_IntSize(vPartSupp)-100);
+        Value = Attract/Repulse;
+        if ( ValueBest < Value )
+        {
+            ValueBest = Value;
+            iBest = i;
+        }
+    }
+    if ( ValueBest < 75 )
+        return -1;
+    return iBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform the smart partitioning.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManPartitionPrint( Aig_Man_t * p, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll )
+{
+    Vec_Int_t * vOne;
+    int i, nOutputs, Counter;
+
+    Counter = 0;
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i )
+    {
+        nOutputs = Vec_IntSize((Vec_Int_t *)Vec_PtrEntry(vPartsAll, i));
+        printf( "%d=(%d,%d) ", i, Vec_IntSize(vOne), nOutputs );
+        Counter += nOutputs;
+        if ( i == Vec_PtrSize(vPartsAll) - 1 )
+            break;
+    }
+    assert( Counter == Aig_ManCoNum(p) );
+//    printf( "\nTotal = %d. Outputs = %d.\n", Counter, Aig_ManCoNum(p) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform the smart partitioning.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, int nSuppSizeLimit )
+{
+    Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp;
+    int i, iPart;
+
+    if ( nSuppSizeLimit == 0 )
+        nSuppSizeLimit = 200;
+
+    // pack smaller partitions into larger blocks
+    iPart = 0;
+    vPart = vPartSupp = NULL;
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i )
+    {
+        if ( Vec_IntSize(vOne) < nSuppSizeLimit )
+        {
+            if ( vPartSupp == NULL )
+            {
+                assert( vPart == NULL );
+                vPartSupp = Vec_IntDup(vOne);
+                vPart = (Vec_Int_t *)Vec_PtrEntry(vPartsAll, i);
+            }
+            else
+            {
+                vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne );
+                Vec_IntFree( vTemp );
+                vPart = Vec_IntTwoMerge( vTemp = vPart, (Vec_Int_t *)Vec_PtrEntry(vPartsAll, i) );
+                Vec_IntFree( vTemp );
+                Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vPartsAll, i) );
+            }
+            if ( Vec_IntSize(vPartSupp) < nSuppSizeLimit )
+                continue;
+        }
+        else
+            vPart = (Vec_Int_t *)Vec_PtrEntry(vPartsAll, i);
+        // add the partition 
+        Vec_PtrWriteEntry( vPartsAll, iPart, vPart );  
+        vPart = NULL;
+        if ( vPartSupp ) 
+        {
+            Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vPartSuppsAll, iPart) );
+            Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp );  
+            vPartSupp = NULL;
+        }
+        iPart++;
+    }
+    // add the last one
+    if ( vPart )
+    {
+        Vec_PtrWriteEntry( vPartsAll, iPart, vPart );  
+        vPart = NULL;
+
+        assert( vPartSupp != NULL );
+        Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vPartSuppsAll, iPart) );
+        Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp );  
+        vPartSupp = NULL;
+        iPart++;
+    }
+    Vec_PtrShrink( vPartsAll, iPart );
+    Vec_PtrShrink( vPartsAll, iPart );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform the smart partitioning.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManPartitionSmart( Aig_Man_t * p, int nSuppSizeLimit, int fVerbose, Vec_Ptr_t ** pvPartSupps )
+{
+    Vec_Ptr_t * vPartSuppsBit;
+    Vec_Ptr_t * vSupports, * vPartsAll, * vPartsAll2, * vPartSuppsAll;//, * vPartPtr;
+    Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp;
+    int i, iPart, iOut;
+    abctime clk;
+
+    // compute the supports for all outputs
+clk = Abc_Clock();
+    vSupports = Aig_ManSupports( p );
+if ( fVerbose )
+{
+ABC_PRT( "Supps", Abc_Clock() - clk );
+}
+    // start char-based support representation
+    vPartSuppsBit = Vec_PtrAlloc( 1000 );
+
+    // create partitions
+clk = Abc_Clock();
+    vPartsAll = Vec_PtrAlloc( 256 );
+    vPartSuppsAll = Vec_PtrAlloc( 256 );
+    Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vOne, i )
+    {
+        // get the output number
+        iOut = Vec_IntPop(vOne);
+        // find closely matching part
+        iPart = Aig_ManPartitionSmartFindPart( vPartSuppsAll, vPartsAll, vPartSuppsBit, nSuppSizeLimit, vOne );
+        if ( iPart == -1 )
+        {
+            // create new partition
+            vPart = Vec_IntAlloc( 32 );
+            Vec_IntPush( vPart, iOut );
+            // create new partition support
+            vPartSupp = Vec_IntDup( vOne );
+            // add this partition and its support
+            Vec_PtrPush( vPartsAll, vPart );
+            Vec_PtrPush( vPartSuppsAll, vPartSupp );
+
+            Vec_PtrPush( vPartSuppsBit, Aig_ManSuppCharStart(vOne, Aig_ManCiNum(p)) );
+        }
+        else
+        {
+            // add output to this partition
+            vPart = (Vec_Int_t *)Vec_PtrEntry( vPartsAll, iPart );
+            Vec_IntPush( vPart, iOut );
+            // merge supports
+            vPartSupp = (Vec_Int_t *)Vec_PtrEntry( vPartSuppsAll, iPart );
+            vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne );
+            Vec_IntFree( vTemp );
+            // reinsert new support
+            Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp );
+
+            Aig_ManSuppCharAdd( (unsigned *)Vec_PtrEntry(vPartSuppsBit, iPart), vOne, Aig_ManCiNum(p) );
+        }
+    }
+
+    // stop char-based support representation
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsBit, vTemp, i )
+        ABC_FREE( vTemp );
+    Vec_PtrFree( vPartSuppsBit );
+
+//printf( "\n" );
+if ( fVerbose )
+{
+ABC_PRT( "Parts", Abc_Clock() - clk );
+}
+
+clk = Abc_Clock();
+    // reorder partitions in the decreasing order of support sizes
+    // remember partition number in each partition support
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i )
+        Vec_IntPush( vOne, i );
+    // sort the supports in the decreasing order
+    Vec_VecSort( (Vec_Vec_t *)vPartSuppsAll, 1 );
+    // reproduce partitions
+    vPartsAll2 = Vec_PtrAlloc( 256 );
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i )
+        Vec_PtrPush( vPartsAll2, Vec_PtrEntry(vPartsAll, Vec_IntPop(vOne)) );
+    Vec_PtrFree( vPartsAll );
+    vPartsAll = vPartsAll2;
+
+    // compact small partitions
+//    Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll );
+    Aig_ManPartitionCompact( vPartsAll, vPartSuppsAll, nSuppSizeLimit );
+    if ( fVerbose )
+//    Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll );
+    printf( "Created %d partitions.\n", Vec_PtrSize(vPartsAll) );
+
+if ( fVerbose )
+{
+//ABC_PRT( "Comps", Abc_Clock() - clk );
+}
+
+    // cleanup
+    Vec_VecFree( (Vec_Vec_t *)vSupports );
+    if ( pvPartSupps == NULL )
+        Vec_VecFree( (Vec_Vec_t *)vPartSuppsAll );
+    else
+        *pvPartSupps = vPartSuppsAll;
+/*
+    // converts from intergers to nodes
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartsAll, vPart, iPart )
+    {
+        vPartPtr = Vec_PtrAlloc( Vec_IntSize(vPart) );
+        Vec_IntForEachEntry( vPart, iOut, i )
+            Vec_PtrPush( vPartPtr, Aig_ManCo(p, iOut) );
+        Vec_IntFree( vPart );
+        Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr );
+    }
+*/
+    return vPartsAll;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform the smart partitioning.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManPartitionSmartRegisters( Aig_Man_t * pAig, int nSuppSizeLimit, int fVerbose )
+{
+    Vec_Ptr_t * vPartSuppsBit;
+    Vec_Ptr_t * vSupports, * vPartsAll, * vPartsAll2, * vPartSuppsAll;
+    Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp;
+    int i, iPart, iOut;
+    abctime clk;
+
+    // add output number to each
+clk = Abc_Clock();
+    vSupports = Aig_ManSupportsRegisters( pAig );
+    assert( Vec_PtrSize(vSupports) == Aig_ManRegNum(pAig) );
+    Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vOne, i )
+        Vec_IntPush( vOne, i );
+if ( fVerbose )
+{
+ABC_PRT( "Supps", Abc_Clock() - clk );
+}
+
+    // start char-based support representation
+    vPartSuppsBit = Vec_PtrAlloc( 1000 );
+
+    // create partitions
+clk = Abc_Clock();
+    vPartsAll = Vec_PtrAlloc( 256 );
+    vPartSuppsAll = Vec_PtrAlloc( 256 );
+    Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vOne, i )
+    {
+        // get the output number
+        iOut = Vec_IntPop(vOne);
+        // find closely matching part
+        iPart = Aig_ManPartitionSmartFindPart( vPartSuppsAll, vPartsAll, vPartSuppsBit, nSuppSizeLimit, vOne );
+        if ( iPart == -1 )
+        {
+            // create new partition
+            vPart = Vec_IntAlloc( 32 );
+            Vec_IntPush( vPart, iOut );
+            // create new partition support
+            vPartSupp = Vec_IntDup( vOne );
+            // add this partition and its support
+            Vec_PtrPush( vPartsAll, vPart );
+            Vec_PtrPush( vPartSuppsAll, vPartSupp );
+
+            Vec_PtrPush( vPartSuppsBit, Aig_ManSuppCharStart(vOne, Vec_PtrSize(vSupports)) );
+        }
+        else
+        {
+            // add output to this partition
+            vPart = (Vec_Int_t *)Vec_PtrEntry( vPartsAll, iPart );
+            Vec_IntPush( vPart, iOut );
+            // merge supports
+            vPartSupp = (Vec_Int_t *)Vec_PtrEntry( vPartSuppsAll, iPart );
+            vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne );
+            Vec_IntFree( vTemp );
+            // reinsert new support
+            Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp );
+
+            Aig_ManSuppCharAdd( (unsigned *)Vec_PtrEntry(vPartSuppsBit, iPart), vOne, Vec_PtrSize(vSupports) );
+        }
+    }
+
+    // stop char-based support representation
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsBit, vTemp, i )
+        ABC_FREE( vTemp );
+    Vec_PtrFree( vPartSuppsBit );
+
+//printf( "\n" );
+if ( fVerbose )
+{
+ABC_PRT( "Parts", Abc_Clock() - clk );
+}
+
+clk = Abc_Clock();
+    // reorder partitions in the decreasing order of support sizes
+    // remember partition number in each partition support
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i )
+        Vec_IntPush( vOne, i );
+    // sort the supports in the decreasing order
+    Vec_VecSort( (Vec_Vec_t *)vPartSuppsAll, 1 );
+    // reproduce partitions
+    vPartsAll2 = Vec_PtrAlloc( 256 );
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i )
+        Vec_PtrPush( vPartsAll2, Vec_PtrEntry(vPartsAll, Vec_IntPop(vOne)) );
+    Vec_PtrFree( vPartsAll );
+    vPartsAll = vPartsAll2;
+
+    // compact small partitions
+//    Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll );
+    Aig_ManPartitionCompact( vPartsAll, vPartSuppsAll, nSuppSizeLimit );
+    if ( fVerbose )
+//    Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll );
+    printf( "Created %d partitions.\n", Vec_PtrSize(vPartsAll) );
+
+if ( fVerbose )
+{
+//ABC_PRT( "Comps", Abc_Clock() - clk );
+}
+
+    // cleanup
+    Vec_VecFree( (Vec_Vec_t *)vSupports );
+//    if ( pvPartSupps == NULL )
+        Vec_VecFree( (Vec_Vec_t *)vPartSuppsAll );
+//    else
+//        *pvPartSupps = vPartSuppsAll;
+
+/*
+    // converts from intergers to nodes
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartsAll, vPart, iPart )
+    {
+        vPartPtr = Vec_PtrAlloc( Vec_IntSize(vPart) );
+        Vec_IntForEachEntry( vPart, iOut, i )
+            Vec_PtrPush( vPartPtr, Aig_ManCo(p, iOut) );
+        Vec_IntFree( vPart );
+        Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr );
+    }
+*/
+    return vPartsAll;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform the naive partitioning.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManPartitionNaive( Aig_Man_t * p, int nPartSize )
+{
+    Vec_Ptr_t * vParts;
+    Aig_Obj_t * pObj;
+    int nParts, i;
+    nParts = (Aig_ManCoNum(p) / nPartSize) + ((Aig_ManCoNum(p) % nPartSize) > 0);
+    vParts = (Vec_Ptr_t *)Vec_VecStart( nParts );
+    Aig_ManForEachCo( p, pObj, i )
+        Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vParts, i / nPartSize), i );
+    return vParts;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Adds internal nodes in the topological order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_ManDupPart_rec( Aig_Man_t * pNew, Aig_Man_t * pOld, Aig_Obj_t * pObj, Vec_Int_t * vSuppMap )
+{
+    assert( !Aig_IsComplement(pObj) );
+    if ( Aig_ObjIsTravIdCurrent(pOld, pObj) )
+        return (Aig_Obj_t *)pObj->pData;
+    Aig_ObjSetTravIdCurrent(pOld, pObj);
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        assert( Vec_IntSize(vSuppMap) == Aig_ManCiNum(pNew) );
+        Vec_IntPush( vSuppMap, (int)(long)pObj->pNext );
+        return (Aig_Obj_t *)(pObj->pData = Aig_ObjCreateCi(pNew));
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin0(pObj), vSuppMap );
+    Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin1(pObj), vSuppMap );
+    return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds internal nodes in the topological order.]
+
+  Description [Returns the array of new outputs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManDupPart( Aig_Man_t * pNew, Aig_Man_t * pOld, Vec_Int_t * vPart, Vec_Int_t * vSuppMap, int fInverse )
+{
+    Vec_Ptr_t * vOutsTotal;
+    Aig_Obj_t * pObj;
+    int Entry, i;
+    // create the PIs
+    Aig_ManIncrementTravId( pOld );
+    Aig_ManConst1(pOld)->pData = Aig_ManConst1(pNew);
+    Aig_ObjSetTravIdCurrent( pOld, Aig_ManConst1(pOld) );
+    if ( !fInverse )
+    {
+        Vec_IntForEachEntry( vSuppMap, Entry, i )
+        {
+            pObj = Aig_ManCi( pOld, Entry );
+            pObj->pData = Aig_ManCi( pNew, i );
+            Aig_ObjSetTravIdCurrent( pOld, pObj );
+        }
+    }
+    else
+    {
+        Vec_IntForEachEntry( vSuppMap, Entry, i )
+        {
+            pObj = Aig_ManCi( pOld, i );
+            pObj->pData = Aig_ManCi( pNew, Entry );
+            Aig_ObjSetTravIdCurrent( pOld, pObj );
+        }
+        vSuppMap = NULL; // should not be useful
+    }
+    // create the internal nodes
+    vOutsTotal = Vec_PtrAlloc( Vec_IntSize(vPart) );
+    if ( !fInverse )
+    {
+        Vec_IntForEachEntry( vPart, Entry, i )
+        {
+            pObj = Aig_ManCo( pOld, Entry );
+            Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin0(pObj), vSuppMap );
+            Vec_PtrPush( vOutsTotal, Aig_ObjChild0Copy(pObj) );
+        }
+    }
+    else
+    {
+        Aig_ManForEachObj( pOld, pObj, i )
+        {
+            if ( Aig_ObjIsCo(pObj) )
+            {
+                Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin0(pObj), vSuppMap );
+                Vec_PtrPush( vOutsTotal, Aig_ObjChild0Copy(pObj) );
+            }
+            else if ( Aig_ObjIsNode(pObj) && pObj->nRefs == 0 )
+                Aig_ManDupPart_rec( pNew, pOld, pObj, vSuppMap );
+            
+        }
+    }
+    return vOutsTotal; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds internal nodes in the topological order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManDupPartAll_rec( Aig_Man_t * pNew, Aig_Man_t * pOld, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pObjNew;
+    assert( !Aig_IsComplement(pObj) );
+    if ( Aig_ObjIsTravIdCurrent(pOld, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(pOld, pObj);
+    if ( Aig_ObjIsCi(pObj) )
+        pObjNew = Aig_ObjCreateCi(pNew);
+    else if ( Aig_ObjIsCo(pObj) )
+    {
+        Aig_ManDupPartAll_rec( pNew, pOld, Aig_ObjFanin0(pObj) );
+        pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    }
+    else
+    {
+        assert( Aig_ObjIsNode(pObj) );
+        Aig_ManDupPartAll_rec( pNew, pOld, Aig_ObjFanin0(pObj) );
+        Aig_ManDupPartAll_rec( pNew, pOld, Aig_ObjFanin1(pObj) );
+        pObjNew = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    }
+    pObj->pData = pObjNew;
+    pObjNew->pData = pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds internal nodes in the topological order.]
+
+  Description [Returns the array of new outputs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupPartAll( Aig_Man_t * pOld, Vec_Int_t * vPart )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i, Entry;
+    Aig_ManIncrementTravId( pOld );
+    pNew = Aig_ManStart( 5000 );
+    // map constant nodes
+    pObj = Aig_ManConst1(pOld);
+    pObjNew = Aig_ManConst1(pNew);
+    pObj->pData = pObjNew;
+    pObjNew->pData = pObj;
+    Aig_ObjSetTravIdCurrent(pOld, pObj);
+    // map all other nodes
+    Vec_IntForEachEntry( vPart, Entry, i )
+    {
+        pObj = Aig_ManCo( pOld, Entry );
+        Aig_ManDupPartAll_rec( pNew, pOld, pObj );
+    }
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManSupportNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vSupport )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        Vec_IntPush( vSupport, Aig_ObjCioId(pObj) );
+        return;
+    }
+    Aig_ManSupportNodes_rec( p, Aig_ObjFanin0(pObj), vSupport );
+    Aig_ManSupportNodes_rec( p, Aig_ObjFanin1(pObj), vSupport );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes and PIs in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManSupportNodes( Aig_Man_t * p, Vec_Ptr_t * vParts )
+{
+    Vec_Ptr_t * vPartSupps;
+    Vec_Int_t * vPart, * vSupport;
+    int i, k, iOut;
+    Aig_ManSetCioIds( p );
+    vPartSupps = Vec_PtrAlloc( Vec_PtrSize(vParts) );
+    Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i )
+    {
+        vSupport = Vec_IntAlloc( 100 );
+        Aig_ManIncrementTravId( p );
+        Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
+        Vec_IntForEachEntry( vPart, iOut, k )
+            Aig_ManSupportNodes_rec( p, Aig_ObjFanin0(Aig_ManCo(p, iOut)), vSupport );
+//        Vec_IntSort( vSupport, 0 );
+        Vec_PtrPush( vPartSupps, vSupport );
+    }
+    Aig_ManCleanCioIds( p );
+    return vPartSupps;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create partitioned miter of the two AIGs.]
+
+  Description [Assumes that each output in the second AIG cannot have 
+  more supp vars than the same output in the first AIG.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManMiterPartitioned( Aig_Man_t * p1, Aig_Man_t * p2, int nPartSize, int fSmart )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pMiter;
+    Vec_Ptr_t * vMiters, * vNodes1, * vNodes2;
+    Vec_Ptr_t * vParts, * vPartSupps;
+    Vec_Int_t * vPart, * vPartSupp;
+    int i, k;
+    // partition the first manager
+    if ( fSmart )
+        vParts = Aig_ManPartitionSmart( p1, nPartSize, 0, &vPartSupps );
+    else
+    {
+        vParts = Aig_ManPartitionNaive( p1, nPartSize );
+        vPartSupps = Aig_ManSupportNodes( p1, vParts );
+    }
+    // derive miters
+    vMiters = Vec_PtrAlloc( Vec_PtrSize(vParts) );
+    for ( i = 0; i < Vec_PtrSize(vParts); i++ )
+    {
+        // get partition and its support
+        vPart     = (Vec_Int_t *)Vec_PtrEntry( vParts, i );
+        vPartSupp = (Vec_Int_t *)Vec_PtrEntry( vPartSupps, i );
+        // create the new miter
+        pNew = Aig_ManStart( 1000 );
+        // create the PIs
+        for ( k = 0; k < Vec_IntSize(vPartSupp); k++ )
+            Aig_ObjCreateCi( pNew );
+        // copy the components
+        vNodes1 = Aig_ManDupPart( pNew, p1, vPart, vPartSupp, 0 );
+        vNodes2 = Aig_ManDupPart( pNew, p2, vPart, vPartSupp, 0 );
+        // create the miter
+        pMiter = Aig_MiterTwo( pNew, vNodes1, vNodes2 );
+        Vec_PtrFree( vNodes1 );
+        Vec_PtrFree( vNodes2 );
+        // create the output
+        Aig_ObjCreateCo( pNew, pMiter );
+        // clean up
+        Aig_ManCleanup( pNew );
+        Vec_PtrPush( vMiters, pNew );
+    }
+    Vec_VecFree( (Vec_Vec_t *)vParts );
+    Vec_VecFree( (Vec_Vec_t *)vPartSupps );
+    return vMiters;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs partitioned choice computation.]
+
+  Description [Assumes that each output in the second AIG cannot have 
+  more supp vars than the same output in the first AIG.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManChoicePartitioned( Vec_Ptr_t * vAigs, int nPartSize, int nConfMax, int nLevelMax, int fVerbose )
+{
+//    extern int Cmd_CommandExecute( void * pAbc, char * sCommand );
+//    extern void * Abc_FrameGetGlobalFrame();
+//    extern Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax, int nLevelMax );
+
+    Vec_Ptr_t * vPios;
+    Vec_Ptr_t * vOutsTotal, * vOuts;
+    Aig_Man_t * pAigTotal, * pAigPart, * pAig, * pTemp;
+    Vec_Int_t * vPart, * vPartSupp;
+    Vec_Ptr_t * vParts;
+    Aig_Obj_t * pObj;
+    void ** ppData;
+    int i, k, m, nIdMax;
+    assert( Vec_PtrSize(vAigs) > 1 );
+
+    // compute the total number of IDs
+    nIdMax = 0;
+    Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, i )
+        nIdMax += Aig_ManObjNumMax(pAig);
+
+    // partition the first AIG in the array
+    pAig = (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 );
+    vParts = Aig_ManPartitionSmart( pAig, nPartSize, 0, NULL );
+
+    // start the total fraiged AIG
+    pAigTotal = Aig_ManStartFrom( pAig );
+    Aig_ManReprStart( pAigTotal, nIdMax );
+    vOutsTotal = Vec_PtrStart( Aig_ManCoNum(pAig) );
+
+    // set the PI numbers
+    Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, i )
+        Aig_ManForEachCi( pAig, pObj, k )
+            pObj->pNext = (Aig_Obj_t *)(long)k;
+
+//    Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" );
+
+    // create the total fraiged AIG
+    vPartSupp = Vec_IntAlloc( 100 ); // maps part PI num into total PI num
+    Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i )
+    {
+        // derive the partition AIG
+        pAigPart = Aig_ManStart( 5000 );
+//        pAigPart->pName = Extra_UtilStrsav( pAigPart->pName );
+        Vec_IntClear( vPartSupp );
+        Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, k )
+        {
+            vOuts = Aig_ManDupPart( pAigPart, pAig, vPart, vPartSupp, 0 );
+            if ( k == 0 )
+            {
+                Vec_PtrForEachEntry( Aig_Obj_t *, vOuts, pObj, m )
+                    Aig_ObjCreateCo( pAigPart, pObj );
+            }
+            Vec_PtrFree( vOuts );
+        }
+        // derive the total AIG from the partitioned AIG
+        vOuts = Aig_ManDupPart( pAigTotal, pAigPart, vPart, vPartSupp, 1 );
+        // add to the outputs
+        Vec_PtrForEachEntry( Aig_Obj_t *, vOuts, pObj, k )
+        {
+            assert( Vec_PtrEntry( vOutsTotal, Vec_IntEntry(vPart,k) ) == NULL );
+            Vec_PtrWriteEntry( vOutsTotal, Vec_IntEntry(vPart,k), pObj );
+        }
+        Vec_PtrFree( vOuts );
+        // store contents of pData pointers
+        ppData = ABC_ALLOC( void *, Aig_ManObjNumMax(pAigPart) );
+        Aig_ManForEachObj( pAigPart, pObj, k )
+            ppData[k] = pObj->pData;
+        // report the process
+        if ( fVerbose )
+        printf( "Part %4d  (out of %4d)  PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", 
+            i+1, Vec_PtrSize(vParts), Aig_ManCiNum(pAigPart), Aig_ManCoNum(pAigPart), 
+            Aig_ManNodeNum(pAigPart), Aig_ManLevelNum(pAigPart) );
+        // compute equivalence classes (to be stored in pNew->pReprs)
+        pAig = Fra_FraigChoice( pAigPart, nConfMax, nLevelMax );
+        Aig_ManStop( pAig );
+        // reset the pData pointers
+        Aig_ManForEachObj( pAigPart, pObj, k )
+            pObj->pData = ppData[k];
+        ABC_FREE( ppData );
+        // transfer representatives to the total AIG
+        if ( pAigPart->pReprs )
+            Aig_ManTransferRepr( pAigTotal, pAigPart );
+        Aig_ManStop( pAigPart );
+    }
+    if ( fVerbose )
+    printf( "                                                                                          \r" );
+    Vec_VecFree( (Vec_Vec_t *)vParts );
+    Vec_IntFree( vPartSupp );
+
+//    Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" );
+
+    // clear the PI numbers
+    Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, i )
+        Aig_ManForEachCi( pAig, pObj, k )
+            pObj->pNext = NULL;
+
+    // add the outputs in the same order
+    Vec_PtrForEachEntry( Aig_Obj_t *, vOutsTotal, pObj, i )
+        Aig_ObjCreateCo( pAigTotal, pObj );
+    Vec_PtrFree( vOutsTotal );
+
+    // derive the result of choicing
+    pAig = Aig_ManRehash( pAigTotal );
+    // create the equivalent nodes lists
+    Aig_ManMarkValidChoices( pAig );
+    // reconstruct the network
+    vPios = Aig_ManOrderPios( pAig, (Aig_Man_t *)Vec_PtrEntry(vAigs,0) );
+    pAig = Aig_ManDupDfsGuided( pTemp = pAig, vPios );
+    Aig_ManStop( pTemp );
+    Vec_PtrFree( vPios );
+    // duplicate the timing manager
+    pTemp = (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 );
+    if ( pTemp->pManTime )
+        pAig->pManTime = Tim_ManDup( (Tim_Man_t *)pTemp->pManTime, 0 );
+    // reset levels
+    Aig_ManChoiceLevel( pAig );
+    return pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs partitioned choice computation.]
+
+  Description [Assumes that each output in the second AIG cannot have 
+  more supp vars than the same output in the first AIG.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManFraigPartitioned( Aig_Man_t * pAig, int nPartSize, int nConfMax, int nLevelMax, int fVerbose )
+{
+//    extern Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax, int nLevelMax );
+
+    Aig_Man_t * pAigPart, * pAigTemp;
+    Vec_Int_t * vPart;
+    Vec_Ptr_t * vParts;
+    Aig_Obj_t * pObj;
+    void ** ppData;
+    int i, k;
+
+    // partition the outputs of the AIG
+    vParts = Aig_ManPartitionNaive( pAig, nPartSize );
+
+    // start the equivalence classes
+    Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) );
+
+    // set the PI numbers
+    Aig_ManSetCioIds( pAig );
+
+    // create the total fraiged AIG
+    Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i )
+    {
+        // derive the partition AIG
+        pAigPart = Aig_ManDupPartAll( pAig, vPart );
+        // store contents of pData pointers
+        ppData = ABC_ALLOC( void *, Aig_ManObjNumMax(pAigPart) );
+        Aig_ManForEachObj( pAigPart, pObj, k )
+            ppData[k] = pObj->pData;
+        // report the process
+        if ( fVerbose )
+        printf( "Part %4d  (out of %4d)  PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", 
+            i+1, Vec_PtrSize(vParts), Aig_ManCiNum(pAigPart), Aig_ManCoNum(pAigPart), 
+            Aig_ManNodeNum(pAigPart), Aig_ManLevelNum(pAigPart) );
+        // compute equivalence classes (to be stored in pNew->pReprs)
+        pAigTemp = Fra_FraigChoice( pAigPart, nConfMax, nLevelMax );
+        Aig_ManStop( pAigTemp );
+        // reset the pData pointers
+        Aig_ManForEachObj( pAigPart, pObj, k )
+            pObj->pData = ppData[k];
+        ABC_FREE( ppData );
+        // transfer representatives to the total AIG
+        if ( pAigPart->pReprs )
+            Aig_ManTransferRepr( pAig, pAigPart );
+        Aig_ManStop( pAigPart );
+    }
+    if ( fVerbose )
+    printf( "                                                                                          \r" );
+    Vec_VecFree( (Vec_Vec_t *)vParts );
+
+    // clear the PI numbers
+    Aig_ManCleanCioIds( pAig );
+
+    // derive the result of choicing
+    return Aig_ManDupRepr( pAig, 0 );
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Set the representative.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Aig_ObjSetRepr_( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 )
+{
+    assert( p->pReprs != NULL );
+    assert( !Aig_IsComplement(pNode1) );
+    assert( !Aig_IsComplement(pNode2) );
+    assert( pNode1->Id < p->nReprsAlloc );
+    assert( pNode2->Id < p->nReprsAlloc );
+    if ( pNode1 == pNode2 )
+        return;
+    if ( pNode1->Id < pNode2->Id )
+        p->pReprs[pNode2->Id] = pNode1;
+    else
+        p->pReprs[pNode1->Id] = pNode2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constructively accumulates choices.]
+
+  Description [pNew is a new AIG with choices under construction.
+  pPrev is the AIG preceding pThis in the order of deriving choices.
+  pThis is the current AIG to be added to pNew while creating choices.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManChoiceConstructiveOne( Aig_Man_t * pNew, Aig_Man_t * pPrev, Aig_Man_t * pThis )
+{
+    Aig_Obj_t * pObj, * pObjNew;
+    int i;
+    assert( Aig_ManCiNum(pNew) == Aig_ManCiNum(pPrev) );
+    assert( Aig_ManCiNum(pNew) == Aig_ManCiNum(pThis) );
+    assert( Aig_ManCoNum(pNew) == Aig_ManCoNum(pPrev) );
+    assert( Aig_ManCoNum(pNew) == Aig_ManCoNum(pThis) );
+    // make sure the nodes of pPrev point to pNew
+    Aig_ManForEachObj( pNew, pObj, i )
+        pObj->fMarkB = 1;
+    Aig_ManForEachObj( pPrev, pObj, i )
+        assert( Aig_Regular((Aig_Obj_t *)pObj->pData)->fMarkB );
+    Aig_ManForEachObj( pNew, pObj, i )
+        pObj->fMarkB = 0;
+    // make sure the nodes of pThis point to pPrev
+    Aig_ManForEachObj( pPrev, pObj, i )
+        pObj->fMarkB = 1;
+    Aig_ManForEachObj( pPrev, pObj, i )
+        pObj->fMarkB = 0;
+    // remap nodes of pThis on top of pNew using pPrev
+    pObj = Aig_ManConst1(pThis);
+    pObj->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( pThis, pObj, i )
+        pObj->pData = Aig_ManCi(pNew, i);
+    Aig_ManForEachCo( pThis, pObj, i )
+        pObj->pData = Aig_ManCo(pNew, i);
+    // go through the nodes in the topological order
+    Aig_ManForEachNode( pThis, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // set the inputs of POs as equivalent
+    Aig_ManForEachCo( pThis, pObj, i )
+    {
+        pObjNew = Aig_ObjFanin0( Aig_ManCo(pNew,i) );
+        // pObjNew and Aig_ObjFanin0(pObj)->pData are equivalent
+        Aig_ObjSetRepr_( pNew, pObjNew, Aig_Regular((Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constructively accumulates choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManChoiceEval( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vSupp;
+    Aig_Obj_t * pNode, * pTemp;
+    int i, Counter;
+
+    vSupp = Vec_PtrAlloc( 100 );
+    Aig_ManForEachNode( p, pNode, i )
+    {
+        if ( !Aig_ObjIsChoice(p, pNode) )
+            continue; 
+        Counter = 0;
+        for ( pTemp = pNode; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) )
+            Counter++;
+        printf( "Choice node = %5d. Level = %2d. Choices = %d. { ", pNode->Id, pNode->Level, Counter );
+        for ( pTemp = pNode; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) )
+        {
+            Counter = Aig_NodeMffcSupp( p, pTemp, 0, vSupp );
+            printf( "S=%d N=%d L=%d  ", Vec_PtrSize(vSupp), Counter, pTemp->Level );
+        }
+        printf( "}\n" );
+    }
+    Vec_PtrFree( vSupp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constructively accumulates choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManChoiceConstructive( Vec_Ptr_t * vAigs, int fVerbose )
+{
+    Vec_Ptr_t * vPios;
+    Aig_Man_t * pNew, * pThis, * pPrev, * pTemp;
+    int i;
+    // start AIG with choices
+    pPrev = (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 );
+    pNew = Aig_ManDupOrdered( pPrev );
+    // create room for equivalent nodes and representatives
+    assert( pNew->pReprs == NULL );
+    pNew->nReprsAlloc = Vec_PtrSize(vAigs) * Aig_ManObjNumMax(pNew);
+    pNew->pReprs = ABC_ALLOC( Aig_Obj_t *, pNew->nReprsAlloc );
+    memset( pNew->pReprs, 0, sizeof(Aig_Obj_t *) * pNew->nReprsAlloc );
+    // add other AIGs one by one
+    Vec_PtrForEachEntryStart( Aig_Man_t *, vAigs, pThis, i, 1 )
+    {
+        Aig_ManChoiceConstructiveOne( pNew, pPrev, pThis );
+        pPrev = pThis;
+    }
+    // derive the result of choicing
+    pNew = Aig_ManRehash( pNew );
+    // create the equivalent nodes lists
+    Aig_ManMarkValidChoices( pNew );
+    // reconstruct the network
+    vPios = Aig_ManOrderPios( pNew, (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 ) );
+    pNew = Aig_ManDupDfsGuided( pTemp = pNew, vPios );
+    Aig_ManStop( pTemp );
+    Vec_PtrFree( vPios );
+    // duplicate the timing manager
+    pTemp = (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 );
+    if ( pTemp->pManTime )
+        pNew->pManTime = Tim_ManDup( (Tim_Man_t *)pTemp->pManTime, 0 );
+    // reset levels
+    Aig_ManChoiceLevel( pNew );
+    return pNew;
+}
+
+/*
+    Vec_Ptr_t * vPios;
+    vPios = Aig_ManOrderPios( pMan, pAig );
+    Vec_PtrFree( vPios );
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigPartReg.c b/abc-build/src/aig/aig/aigPartReg.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigPartReg.c
@@ -0,0 +1,629 @@
+/**CFile****************************************************************
+
+  FileName    [aigPartReg.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Register partitioning algorithm.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigPartReg.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+//#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Aig_ManPre_t_         Aig_ManPre_t;
+
+struct Aig_ManPre_t_
+{
+    // input data    
+    Aig_Man_t *     pAig;            // seq AIG manager 
+    Vec_Ptr_t *     vMatrix;         // register dependency
+    int             nRegsMax;        // the max number of registers in the cluster
+    // information about partitions
+    Vec_Ptr_t *     vParts;          // the partitions
+    char *          pfUsedRegs;      // the registers already included in the partitions
+    // info about the current partition
+    Vec_Int_t *     vRegs;           // registers of this partition
+    Vec_Int_t *     vUniques;        // unique registers of this partition
+    Vec_Int_t *     vFreeVars;       // free variables of this partition
+    Vec_Flt_t *     vPartCost;       // costs of adding each variable
+    char *          pfPartVars;      // input/output registers of the partition
+};
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes partitioning of registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_ManPre_t * Aig_ManRegManStart( Aig_Man_t * pAig, int nPartSize )
+{
+    Aig_ManPre_t * p;
+    p = ABC_ALLOC( Aig_ManPre_t, 1 );
+    memset( p, 0, sizeof(Aig_ManPre_t) );
+    p->pAig      = pAig;
+    p->vMatrix   = Aig_ManSupportsRegisters( pAig );
+    p->nRegsMax  = nPartSize;
+    p->vParts    = Vec_PtrAlloc(256);
+    p->vRegs     = Vec_IntAlloc(256);
+    p->vUniques  = Vec_IntAlloc(256);
+    p->vFreeVars = Vec_IntAlloc(256);
+    p->vPartCost = Vec_FltAlloc(256);
+    p->pfUsedRegs = ABC_ALLOC( char, Aig_ManRegNum(p->pAig) );
+    memset( p->pfUsedRegs, 0, sizeof(char) * Aig_ManRegNum(p->pAig) );
+    p->pfPartVars  = ABC_ALLOC( char, Aig_ManRegNum(p->pAig) );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes partitioning of registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManRegManStop( Aig_ManPre_t * p )
+{
+    Vec_VecFree( (Vec_Vec_t *)p->vMatrix );
+    if ( p->vParts )
+        Vec_VecFree( (Vec_Vec_t *)p->vParts );
+    Vec_IntFree( p->vRegs );
+    Vec_IntFree( p->vUniques );
+    Vec_IntFree( p->vFreeVars );
+    Vec_FltFree( p->vPartCost );
+    ABC_FREE( p->pfUsedRegs );
+    ABC_FREE( p->pfPartVars );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determines what register to use as the seed.]
+
+  Description [The register is selected as the one having the largest
+  number of non-taken registers in its support.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManRegFindSeed( Aig_ManPre_t * p )
+{
+    Vec_Int_t * vRegs;
+    int i, k, iReg;
+    int iMax = -1; // Suppress "might be used uninitialized"
+    int nRegsCur, nRegsMax = -1;
+    for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ )
+    {
+        if ( p->pfUsedRegs[i] )
+            continue;
+        nRegsCur = 0;
+        vRegs = (Vec_Int_t *)Vec_PtrEntry( p->vMatrix, i );
+        Vec_IntForEachEntry( vRegs, iReg, k )
+            nRegsCur += !p->pfUsedRegs[iReg];
+        if ( nRegsMax < nRegsCur )
+        {
+            nRegsMax = nRegsCur;
+            iMax = i;
+        }
+    }
+    return iMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the next register to be added to the set.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManRegFindBestVar( Aig_ManPre_t * p )
+{
+    Vec_Int_t * vSupp;
+    int nNewVars, nNewVarsBest = ABC_INFINITY;
+    int iVarFree, iVarSupp, iVarBest = -1, i, k;
+    // go through the free variables
+    Vec_IntForEachEntry( p->vFreeVars, iVarFree, i )
+    {
+//        if ( p->pfUsedRegs[iVarFree] )
+//            continue;
+        // get support of this variable
+        vSupp = (Vec_Int_t *)Vec_PtrEntry( p->vMatrix, iVarFree );
+        // count the number of new vars
+        nNewVars = 0;
+        Vec_IntForEachEntry( vSupp, iVarSupp, k )
+        {
+            if ( p->pfPartVars[iVarSupp] )
+                continue;
+            nNewVars += 1 + 3 * p->pfUsedRegs[iVarSupp];
+        }
+        // quit if there is no new variables
+        if ( nNewVars == 0 )
+            return iVarFree;
+        // compare the cost of this
+        if ( nNewVarsBest > nNewVars )
+        {
+            nNewVarsBest = nNewVars;
+            iVarBest = iVarFree;
+        }
+    }
+    return iVarBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes partitioning of registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManRegPartitionAdd( Aig_ManPre_t * p, int iReg )
+{
+    Vec_Int_t * vSupp;
+    int RetValue, iVar, i;
+    // make sure this is a new variable
+//    assert( !p->pfUsedRegs[iReg] );
+    if ( !p->pfUsedRegs[iReg] )
+    {
+        p->pfUsedRegs[iReg] = 1;
+        Vec_IntPush( p->vUniques, iReg );
+    }
+    // remove it from the free variables
+    if ( Vec_IntSize(p->vFreeVars) > 0 )
+    {
+        assert( p->pfPartVars[iReg] );
+        RetValue = Vec_IntRemove( p->vFreeVars, iReg );
+        assert( RetValue );
+    }
+    else
+        assert( !p->pfPartVars[iReg] );
+    // add it to the partition
+    p->pfPartVars[iReg] = 1;
+    Vec_IntPush( p->vRegs, iReg );
+    // add new variables
+    vSupp = (Vec_Int_t *)Vec_PtrEntry( p->vMatrix, iReg );
+    Vec_IntForEachEntry( vSupp, iVar, i )
+    {
+        if ( p->pfPartVars[iVar] )
+            continue;
+        p->pfPartVars[iVar] = 1;
+        Vec_IntPush( p->vFreeVars, iVar );
+    }
+    // add it to the cost
+    Vec_FltPush( p->vPartCost, 1.0*Vec_IntSize(p->vFreeVars)/Vec_IntSize(p->vRegs) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates projection of 1-hot registers onto the given partition.]
+
+  Description [Assumes that the relevant register outputs are labeled with
+  the current traversal ID.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManRegProjectOnehots( Aig_Man_t * pAig, Aig_Man_t * pPart, Vec_Ptr_t * vOnehots, int fVerbose )
+{
+    Vec_Ptr_t * vOnehotsPart = NULL;
+    Vec_Int_t * vGroup, * vGroupNew;
+    Aig_Obj_t * pObj, * pObjNew;
+    int nOffset, iReg, i, k;
+    // set the PI numbers
+    Aig_ManForEachCi( pPart, pObj, i )
+        pObj->iData = i;
+    // go through each group and check if registers are involved in this one
+    nOffset = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig);
+    Vec_PtrForEachEntry( Vec_Int_t *, vOnehots, vGroup, i )
+    {
+        vGroupNew = NULL;
+        Vec_IntForEachEntry( vGroup, iReg, k )
+        {
+            pObj = Aig_ManCi( pAig, nOffset+iReg );
+            if ( !Aig_ObjIsTravIdCurrent(pAig, pObj) )
+                continue;
+            if ( vGroupNew == NULL )
+                vGroupNew = Vec_IntAlloc( Vec_IntSize(vGroup) );
+            pObjNew = (Aig_Obj_t *)pObj->pData;
+            Vec_IntPush( vGroupNew, pObjNew->iData );
+        }
+        if ( vGroupNew == NULL )
+            continue;
+        if ( Vec_IntSize(vGroupNew) > 1 )
+        {
+            if ( vOnehotsPart == NULL )
+                vOnehotsPart = Vec_PtrAlloc( 100 );
+            Vec_PtrPush( vOnehotsPart, vGroupNew );
+        }
+        else
+            Vec_IntFree( vGroupNew );
+    }
+    // clear the PI numbers
+    Aig_ManForEachCi( pPart, pObj, i )
+        pObj->iData = 0;
+    // print out
+    if ( vOnehotsPart && fVerbose )
+    {
+        printf( "Partition contains %d groups of 1-hot registers: { ", Vec_PtrSize(vOnehotsPart) );
+        Vec_PtrForEachEntry( Vec_Int_t *, vOnehotsPart, vGroup, k )
+            printf( "%d ", Vec_IntSize(vGroup) );
+        printf( "}\n" );
+    }
+    return vOnehotsPart;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes partitioning of registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManRegCreatePart( Aig_Man_t * pAig, Vec_Int_t * vPart, int * pnCountPis, int * pnCountRegs, int ** ppMapBack )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjNew;
+    Vec_Ptr_t * vNodes;
+    Vec_Ptr_t * vRoots;
+    int nOffset, iOut, i;
+    int nCountPis, nCountRegs;
+    int * pMapBack;
+    // collect roots
+    vRoots = Vec_PtrAlloc( Vec_IntSize(vPart) );
+    nOffset = Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig);
+    Vec_IntForEachEntry( vPart, iOut, i )
+    {
+        pObj = Aig_ManCo(pAig, nOffset+iOut);
+        Vec_PtrPush( vRoots, Aig_ObjFanin0(pObj) );
+    }
+    // collect/mark nodes/PIs in the DFS order
+    vNodes = Aig_ManDfsNodes( pAig, (Aig_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) );
+    Vec_PtrFree( vRoots );
+    // unmark register outputs
+    nOffset = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig);
+    Vec_IntForEachEntry( vPart, iOut, i )
+    {
+        pObj = Aig_ManCi(pAig, nOffset+iOut);
+        Aig_ObjSetTravIdPrevious( pAig, pObj );
+    }
+    // count pure PIs
+    nCountPis = nCountRegs = 0;
+    Aig_ManForEachPiSeq( pAig, pObj, i )
+        nCountPis += Aig_ObjIsTravIdCurrent(pAig, pObj);
+    // count outputs of other registers
+    Aig_ManForEachLoSeq( pAig, pObj, i )
+        nCountRegs += Aig_ObjIsTravIdCurrent(pAig, pObj); 
+    if ( pnCountPis )
+        *pnCountPis = nCountPis;
+    if ( pnCountRegs )
+        *pnCountRegs = nCountRegs;
+    // create the new manager
+    pNew = Aig_ManStart( Vec_PtrSize(vNodes) );
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1(pNew);
+    // create the PIs
+    Aig_ManForEachCi( pAig, pObj, i )
+        if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+            pObj->pData = Aig_ObjCreateCi(pNew);
+    // add variables for the register outputs
+    // create fake POs to hold the register outputs
+    nOffset = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig);
+    Vec_IntForEachEntry( vPart, iOut, i )
+    {
+        pObj = Aig_ManCi(pAig, nOffset+iOut);
+        pObj->pData = Aig_ObjCreateCi(pNew);
+        Aig_ObjCreateCo( pNew, (Aig_Obj_t *)pObj->pData );
+        Aig_ObjSetTravIdCurrent( pAig, pObj ); // added
+    }
+    // create the nodes
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        if ( Aig_ObjIsNode(pObj) )
+            pObj->pData = Aig_And(pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // add real POs for the registers
+    nOffset = Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig);
+    Vec_IntForEachEntry( vPart, iOut, i )
+    {
+        pObj = Aig_ManCo( pAig, nOffset+iOut );
+        Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    }
+    pNew->nRegs = Vec_IntSize(vPart);
+    // create map
+    if ( ppMapBack )
+    {
+        pMapBack = ABC_ALLOC( int, Aig_ManObjNumMax(pNew) );
+        memset( pMapBack, 0xff, sizeof(int) * Aig_ManObjNumMax(pNew) );
+        // map constant nodes
+        pMapBack[0] = 0;
+        // logic cones of register outputs
+        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        {
+            pObjNew = Aig_Regular((Aig_Obj_t *)pObj->pData);
+            pMapBack[pObjNew->Id] = pObj->Id;
+        }
+        // map register outputs
+        nOffset = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig);
+        Vec_IntForEachEntry( vPart, iOut, i )
+        {
+            pObj = Aig_ManCi(pAig, nOffset+iOut);
+            pObjNew = (Aig_Obj_t *)pObj->pData;
+            pMapBack[pObjNew->Id] = pObj->Id;
+        }
+        *ppMapBack = pMapBack;
+    }
+    Vec_PtrFree( vNodes );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes partitioning of registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManRegPartitionSmart( Aig_Man_t * pAig, int nPartSize )
+{
+    extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact );
+
+    Aig_ManPre_t * p;
+    Vec_Ptr_t * vResult;
+    int iSeed, iNext, i, k;
+    // create the manager
+    p = Aig_ManRegManStart( pAig, nPartSize );
+    // add partitions as long as registers remain
+    for ( i = 0; (iSeed = Aig_ManRegFindSeed(p)) >= 0; i++ )
+    {
+//printf( "Seed variable = %d.\n", iSeed );
+        // clean the current partition information
+        Vec_IntClear( p->vRegs );
+        Vec_IntClear( p->vUniques );
+        Vec_IntClear( p->vFreeVars );
+        Vec_FltClear( p->vPartCost );
+        memset( p->pfPartVars, 0, sizeof(char) * Aig_ManRegNum(p->pAig) );
+        // add the register and its partition support
+        Aig_ManRegPartitionAdd( p, iSeed );
+        // select the best var to add
+        for ( k = 0; Vec_IntSize(p->vRegs) < p->nRegsMax; k++ )
+        {
+            // get the next best variable
+            iNext = Aig_ManRegFindBestVar( p );
+            if ( iNext == -1 )
+                break;
+            // add the register to the support of the partition
+            Aig_ManRegPartitionAdd( p, iNext );
+            // report the result
+//printf( "Part %3d  Reg %3d : Free = %4d. Total = %4d. Ratio = %6.2f. Unique = %4d.\n", i, k, 
+//                Vec_IntSize(p->vFreeVars), Vec_IntSize(p->vRegs), 
+//                1.0*Vec_IntSize(p->vFreeVars)/Vec_IntSize(p->vRegs), Vec_IntSize(p->vUniques) );
+            // quit if there are not free variables
+            if ( Vec_IntSize(p->vFreeVars) == 0 )
+                break;
+        }
+        // add this partition to the set
+        Vec_PtrPush( p->vParts, Vec_IntDup(p->vRegs) );        
+printf( "Part %3d  SUMMARY:  Free = %4d. Total = %4d. Ratio = %6.2f. Unique = %4d.\n", i,
+                Vec_IntSize(p->vFreeVars), Vec_IntSize(p->vRegs), 
+                1.0*Vec_IntSize(p->vFreeVars)/Vec_IntSize(p->vRegs), Vec_IntSize(p->vUniques) );
+//printf( "\n" ); 
+    }
+    vResult = p->vParts; p->vParts = NULL;
+    Aig_ManRegManStop( p );
+    return vResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes partitioning of registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManRegPartitionSimple( Aig_Man_t * pAig, int nPartSize, int nOverSize )
+{
+    Vec_Ptr_t * vResult;
+    Vec_Int_t * vPart;
+    int i, Counter;
+    if ( nOverSize >= nPartSize )
+    {
+        printf( "Overlap size (%d) is more or equal than the partition size (%d).\n", nOverSize, nPartSize );
+        printf( "Adjusting it to be equal to half of the partition size.\n" );
+        nOverSize = nPartSize/2;
+    }
+    assert( nOverSize < nPartSize );
+    vResult = Vec_PtrAlloc( 100 );
+    for ( Counter = 0; Counter < Aig_ManRegNum(pAig); Counter -= nOverSize )
+    {
+        vPart = Vec_IntAlloc( nPartSize );
+        for ( i = 0; i < nPartSize; i++, Counter++ )
+            if ( Counter < Aig_ManRegNum(pAig) )
+                Vec_IntPush( vPart, Counter );
+        if ( Vec_IntSize(vPart) <= nOverSize )
+            Vec_IntFree(vPart);
+        else
+            Vec_PtrPush( vResult, vPart );
+    }
+    return vResult;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Divides a large partition into several ones.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManPartDivide( Vec_Ptr_t * vResult, Vec_Int_t * vDomain, int nPartSize, int nOverSize )
+{
+    Vec_Int_t * vPart;
+    int i, Counter;
+    assert( nPartSize && Vec_IntSize(vDomain) > nPartSize );
+    if ( nOverSize >= nPartSize )
+    {
+        printf( "Overlap size (%d) is more or equal than the partition size (%d).\n", nOverSize, nPartSize );
+        printf( "Adjusting it to be equal to half of the partition size.\n" );
+        nOverSize = nPartSize/2;
+    }
+    assert( nOverSize < nPartSize );
+    for ( Counter = 0; Counter < Vec_IntSize(vDomain); Counter -= nOverSize )
+    {
+        vPart = Vec_IntAlloc( nPartSize );
+        for ( i = 0; i < nPartSize; i++, Counter++ )
+            if ( Counter < Vec_IntSize(vDomain) )
+                Vec_IntPush( vPart, Vec_IntEntry(vDomain, Counter) );
+        if ( Vec_IntSize(vPart) <= nOverSize )
+            Vec_IntFree(vPart);
+        else
+            Vec_PtrPush( vResult, vPart );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes partitioning of registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManRegPartitionTraverse_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vLos )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent( p, pObj );
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        if ( pObj->iData >= Aig_ManCiNum(p) - Aig_ManRegNum(p) )
+        {
+            Vec_PtrPush( vLos, pObj );
+            printf( "%d ", pObj->iData - (Aig_ManCiNum(p) - Aig_ManRegNum(p)) );
+        }
+        return;
+    }
+    Aig_ManRegPartitionTraverse_rec( p, Aig_ObjFanin0(pObj), vLos );
+    Aig_ManRegPartitionTraverse_rec( p, Aig_ObjFanin1(pObj), vLos );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes partitioning of registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManRegPartitionTraverse( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vLos;
+    Aig_Obj_t * pObj;
+    int i, nPrev, Counter;
+    // mark the registers
+    Aig_ManForEachCi( p, pObj, i )
+       pObj->iData = i; 
+    // collect registers
+    vLos = Vec_PtrAlloc( Aig_ManRegNum(p) );
+    nPrev = 0;
+    Counter = 0;
+    Aig_ManIncrementTravId( p );
+    Aig_ManForEachLiSeq( p, pObj, i )
+    {
+        ++Counter;
+        printf( "Latch %d: ", Counter );
+        Aig_ManRegPartitionTraverse_rec( p, Aig_ObjFanin0(pObj), vLos );
+printf( "%d=%d \n", Counter, Vec_PtrSize(vLos)-nPrev );
+        nPrev = Vec_PtrSize(vLos);
+    }
+    printf( "Total collected = %d. Total regs = %d.\n", Vec_PtrSize(vLos), Aig_ManRegNum(p) );
+    return vLos;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes partitioning of registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManRegPartitionLinear( Aig_Man_t * pAig, int nPartSize )
+{
+    Vec_Ptr_t * vLos;
+    vLos = Aig_ManRegPartitionTraverse( pAig );
+    Vec_PtrFree( vLos );
+    return NULL;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigPartSat.c b/abc-build/src/aig/aig/aigPartSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigPartSat.c
@@ -0,0 +1,618 @@
+/**CFile****************************************************************
+
+  FileName    [aigPartSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Partitioning for SAT solving.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigPartSat.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+#include "sat/bsat/satSolver.h"
+#include "sat/cnf/cnf.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/* 
+
+The node partitioners defined in this file return array of intergers 
+mapping each AND node's ID into the 0-based number of its partition.
+The mapping of PIs/POs will be derived automatically in Aig_ManPartSplit().
+
+The partitions can be ordered in any way, but the recommended ordering
+is to first include partitions whose nodes are closer to the outputs.
+
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern Aig_Man_t * Dar_ManRwsat( Aig_Man_t * pAig, int fBalance, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [No partitioning.]
+
+  Description [The partitioner ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Aig_ManPartitionMonolithic( Aig_Man_t * p )
+{
+    Vec_Int_t * vId2Part;
+    vId2Part = Vec_IntStart( Aig_ManObjNumMax(p) );
+    return vId2Part;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Partitioning using levelized order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Aig_ManPartitionLevelized( Aig_Man_t * p, int nPartSize )
+{
+    Vec_Int_t * vId2Part;
+    Vec_Vec_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i, k, Counter = 0;
+    vNodes = Aig_ManLevelize( p );
+    vId2Part = Vec_IntStart( Aig_ManObjNumMax(p) );
+    Vec_VecForEachEntryReverseReverse( Aig_Obj_t *, vNodes, pObj, i, k )
+        Vec_IntWriteEntry( vId2Part, Aig_ObjId(pObj), Counter++/nPartSize );
+    Vec_VecFree( vNodes );
+    return vId2Part;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Partitioning using DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Aig_ManPartitionDfs( Aig_Man_t * p, int nPartSize, int fPreorder )
+{
+    Vec_Int_t * vId2Part; 
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    vId2Part = Vec_IntStart( Aig_ManObjNumMax(p) );
+    if ( fPreorder )
+    {
+        vNodes = Aig_ManDfsPreorder( p, 1 );
+        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+            Vec_IntWriteEntry( vId2Part, Aig_ObjId(pObj), Counter++/nPartSize );
+    }
+    else
+    {
+        vNodes = Aig_ManDfs( p, 1 );
+        Vec_PtrForEachEntryReverse( Aig_Obj_t *, vNodes, pObj, i )
+            Vec_IntWriteEntry( vId2Part, Aig_ObjId(pObj), Counter++/nPartSize );
+    }
+    Vec_PtrFree( vNodes );
+    return vId2Part;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively constructs the partition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManPartSplitOne_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vPio2Id )
+{
+    if ( !Aig_ObjIsTravIdCurrent( p, pObj ) )
+    { // new PI
+        Aig_ObjSetTravIdCurrent( p, pObj );
+/*
+        if ( pObj->fMarkA ) // const0
+            pObj->pData = Aig_ManConst0( pNew );
+        else if ( pObj->fMarkB ) // const1
+            pObj->pData = Aig_ManConst1( pNew );
+        else
+*/
+        {
+            pObj->pData = Aig_ObjCreateCi( pNew );
+            if ( pObj->fMarkA ) // const0
+                ((Aig_Obj_t *)pObj->pData)->fMarkA = 1;
+            else if ( pObj->fMarkB ) // const1
+                ((Aig_Obj_t *)pObj->pData)->fMarkB = 1;
+            Vec_IntPush( vPio2Id, Aig_ObjId(pObj) );
+        }
+        return;
+    }
+    if ( pObj->pData ) 
+        return;
+    Aig_ManPartSplitOne_rec( pNew, p, Aig_ObjFanin0(pObj), vPio2Id );
+    Aig_ManPartSplitOne_rec( pNew, p, Aig_ObjFanin1(pObj), vPio2Id );
+    pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Carves out one partition of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManPartSplitOne( Aig_Man_t * p, Vec_Ptr_t * vNodes, Vec_Int_t ** pvPio2Id )
+{
+    Vec_Int_t * vPio2Id;
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    // mark these nodes
+    Aig_ManIncrementTravId( p );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        Aig_ObjSetTravIdCurrent( p, pObj );
+        pObj->pData = NULL;
+    }
+    // add these nodes in a DFS order
+    pNew = Aig_ManStart( Vec_PtrSize(vNodes) );
+    vPio2Id = Vec_IntAlloc( 100 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        Aig_ManPartSplitOne_rec( pNew, p, pObj, vPio2Id );
+    // add the POs
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        if ( Aig_ObjRefs((Aig_Obj_t *)pObj->pData) != Aig_ObjRefs(pObj) )
+        {
+            assert( Aig_ObjRefs((Aig_Obj_t *)pObj->pData) < Aig_ObjRefs(pObj) );
+            Aig_ObjCreateCo( pNew, (Aig_Obj_t *)pObj->pData );
+            Vec_IntPush( vPio2Id, Aig_ObjId(pObj) );
+        }
+    assert( Aig_ManNodeNum(pNew) == Vec_PtrSize(vNodes) );
+    *pvPio2Id = vPio2Id;
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives AIGs for each partition.]
+
+  Description [The first argument is a original AIG. The second argument
+  is the array mapping each AND-node's ID into the 0-based number of its
+  partition. The last argument is the array of arrays (one for each new AIG) 
+  mapping the index of each terminal in the new AIG (the index of each 
+  terminal is derived by ordering PIs followed by POs in their natural order) 
+  into the ID of the corresponding node in the original AIG. The returned 
+  value is the array of AIGs representing the partitions.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManPartSplit( Aig_Man_t * p, Vec_Int_t * vNode2Part, Vec_Ptr_t ** pvPio2Id, Vec_Ptr_t ** pvPart2Pos )
+{
+    Vec_Vec_t * vGroups, * vPart2Pos;
+    Vec_Ptr_t * vAigs, * vPio2Id, * vNodes;
+    Vec_Int_t * vPio2IdOne;
+    Aig_Man_t * pAig;
+    Aig_Obj_t * pObj, * pDriver;
+    int i, nodePart, nParts;
+    vAigs = Vec_PtrAlloc( 100 );
+    vPio2Id = Vec_PtrAlloc( 100 );
+    // put all nodes into levels according to their partition
+    nParts = Vec_IntFindMax(vNode2Part) + 1;
+    assert( nParts > 0 );
+    vGroups = Vec_VecAlloc( nParts );
+    Vec_IntForEachEntry( vNode2Part, nodePart, i )
+    {
+        pObj = Aig_ManObj( p, i );
+        if ( Aig_ObjIsNode(pObj) )
+            Vec_VecPush( vGroups, nodePart, pObj );
+    }
+
+    // label PIs that should be restricted to some values
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        pDriver = Aig_ObjFanin0(pObj);
+        if ( Aig_ObjIsCi(pDriver) )
+        {
+            if ( Aig_ObjFaninC0(pObj) )
+                pDriver->fMarkA = 1; // const0 PI
+            else
+                pDriver->fMarkB = 1; // const1 PI
+        }
+    }
+
+    // create partitions
+    Vec_VecForEachLevel( vGroups, vNodes, i )
+    {
+        if ( Vec_PtrSize(vNodes) == 0 )
+        {
+            printf( "Aig_ManPartSplit(): Skipping partition # %d without nodes (warning).\n", i );
+            continue;
+        }
+        pAig = Aig_ManPartSplitOne( p, vNodes, &vPio2IdOne );
+        Vec_PtrPush( vPio2Id, vPio2IdOne );
+        Vec_PtrPush( vAigs, pAig );
+    }
+    Vec_VecFree( vGroups );
+
+    // divide POs according to their partitions
+    vPart2Pos = Vec_VecStart( Vec_PtrSize(vAigs) );
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        pDriver = Aig_ObjFanin0(pObj);
+        if ( Aig_ObjIsCi(pDriver) )
+            pDriver->fMarkA = pDriver->fMarkB = 0;
+        else
+            Vec_VecPush( vPart2Pos, Vec_IntEntry(vNode2Part, Aig_ObjFaninId0(pObj)), pObj );
+    }
+
+    *pvPio2Id = vPio2Id;
+    *pvPart2Pos = (Vec_Ptr_t *)vPart2Pos;
+    return vAigs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resets node polarity to unbias the polarity of CNF variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManPartResetNodePolarity( Aig_Man_t * pPart )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachObj( pPart, pObj, i )
+        pObj->fPhase = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets polarity according to the original nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManPartSetNodePolarity( Aig_Man_t * p, Aig_Man_t * pPart, Vec_Int_t * vPio2Id )
+{
+    Aig_Obj_t * pObj, * pObjInit;
+    int i;
+    Aig_ManConst1(pPart)->fPhase = 1;
+    Aig_ManForEachCi( pPart, pObj, i )
+    {
+        pObjInit = Aig_ManObj( p, Vec_IntEntry(vPio2Id, i) );
+        pObj->fPhase = pObjInit->fPhase;
+    }
+    Aig_ManForEachNode( pPart, pObj, i )
+        pObj->fPhase = (Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj)) & (Aig_ObjFanin1(pObj)->fPhase ^ Aig_ObjFaninC1(pObj));
+    Aig_ManForEachCo( pPart, pObj, i )
+    {
+        pObjInit = Aig_ManObj( p, Vec_IntEntry(vPio2Id, Aig_ManCiNum(pPart) + i) );
+        pObj->fPhase = (Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj));
+        assert( pObj->fPhase == pObjInit->fPhase );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets polarity according to the original nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManDeriveCounterExample( Aig_Man_t * p, Vec_Int_t * vNode2Var, sat_solver * pSat )
+{ 
+    Vec_Int_t * vPisIds;
+    Aig_Obj_t * pObj;
+    int i;
+    // collect IDs of PI variables
+    // (fanoutless PIs have SAT var 0, which is an unused in the SAT solver -> has value 0)
+    vPisIds = Vec_IntAlloc( Aig_ManCiNum(p) );
+    Aig_ManForEachCi( p, pObj, i )
+        Vec_IntPush( vPisIds, Vec_IntEntry(vNode2Var, Aig_ObjId(pObj)) );
+    // derive the SAT assignment
+    p->pData = Sat_SolverGetModel( pSat, vPisIds->pArray, vPisIds->nSize );
+    Vec_IntFree( vPisIds );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CNF for the partition (pAig) and adds it to solver.]
+
+  Description [Array vPio2Id contains mapping of the PI/PO terminal of pAig
+  into the IDs of the corresponding original nodes. Array vNode2Var contains
+  mapping of the original nodes into their SAT variable numbers.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManAddNewCnfToSolver( sat_solver * pSat, Aig_Man_t * pAig, Vec_Int_t * vNode2Var, 
+                             Vec_Int_t * vPioIds, Vec_Ptr_t * vPartPos, int fAlignPol )
+{
+    Cnf_Dat_t * pCnf;
+    Aig_Obj_t * pObj;
+    int * pBeg, * pEnd;
+    int i, Lits[2], iSatVarOld, iNodeIdOld;
+    // derive CNF and express it using new SAT variables
+    pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) );
+    Cnf_DataTranformPolarity( pCnf, 1 );
+    Cnf_DataLift( pCnf, sat_solver_nvars(pSat) );
+    // create new variables in the SAT solver
+    sat_solver_setnvars( pSat, sat_solver_nvars(pSat) + pCnf->nVars );
+    // add clauses for this CNF
+    Cnf_CnfForClause( pCnf, pBeg, pEnd, i )
+        if ( !sat_solver_addclause( pSat, pBeg, pEnd ) )
+        {
+            assert( 0 ); // if it happens, can return 1 (unsatisfiable)
+            return 1;
+        }
+    // derive the connector clauses
+    Aig_ManForEachCi( pAig, pObj, i )
+    {
+        iNodeIdOld = Vec_IntEntry( vPioIds, i );
+        iSatVarOld = Vec_IntEntry( vNode2Var, iNodeIdOld );
+        if ( iSatVarOld == 0 ) // iNodeIdOld in the original AIG has no SAT var
+        { 
+            // map the corresponding original AIG node into this SAT var
+            Vec_IntWriteEntry( vNode2Var, iNodeIdOld, pCnf->pVarNums[Aig_ObjId(pObj)] );
+            continue;
+        }
+        // add connector clauses 
+        Lits[0] = toLitCond( iSatVarOld, 0 );
+        Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 1 );
+        if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+            assert( 0 );
+        Lits[0] = toLitCond( iSatVarOld, 1 );
+        Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 );
+        if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+            assert( 0 );
+    }
+    // derive the connector clauses
+    Aig_ManForEachCo( pAig, pObj, i )
+    {
+        iNodeIdOld = Vec_IntEntry( vPioIds, Aig_ManCiNum(pAig) + i );
+        iSatVarOld = Vec_IntEntry( vNode2Var, iNodeIdOld );
+        if ( iSatVarOld == 0 ) // iNodeIdOld in the original AIG has no SAT var
+        { 
+            // map the corresponding original AIG node into this SAT var
+            Vec_IntWriteEntry( vNode2Var, iNodeIdOld, pCnf->pVarNums[Aig_ObjId(pObj)] );
+            continue;
+        }
+        // add connector clauses 
+        Lits[0] = toLitCond( iSatVarOld, 0 );
+        Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 1 );
+        if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+            assert( 0 );
+        Lits[0] = toLitCond( iSatVarOld, 1 );
+        Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 );
+        if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+            assert( 0 );
+    }
+    // transfer the ID of constant 1 node
+    if ( Vec_IntEntry( vNode2Var, 0 ) == 0 )
+        Vec_IntWriteEntry( vNode2Var, 0, pCnf->pVarNums[0] );
+    // remove the CNF
+    Cnf_DataFree( pCnf );
+    // constrain the solver with the literals corresponding to the original POs
+    Vec_PtrForEachEntry( Aig_Obj_t *, vPartPos, pObj, i )
+    {
+        iNodeIdOld = Aig_ObjFaninId0( pObj );
+        iSatVarOld = Vec_IntEntry( vNode2Var, iNodeIdOld );
+        assert( iSatVarOld != 0 );
+        // assert the original PO to be 1
+        Lits[0] = toLitCond( iSatVarOld, Aig_ObjFaninC0(pObj) );
+        // correct the polarity if polarity alignment is enabled
+        if ( fAlignPol && Aig_ObjFanin0(pObj)->fPhase ) 
+            Lits[0] = lit_neg( Lits[0] );
+        if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) )
+        {
+            assert( 0 ); // if it happens, can return 1 (unsatisfiable)
+            return 1;
+        }
+    }
+    // constrain some the primary inputs to constant values
+    Aig_ManForEachCi( pAig, pObj, i )
+    {
+        if ( !pObj->fMarkA && !pObj->fMarkB )
+            continue;
+        iNodeIdOld = Vec_IntEntry( vPioIds, i );
+        iSatVarOld = Vec_IntEntry( vNode2Var, iNodeIdOld );
+        Lits[0] = toLitCond( iSatVarOld, pObj->fMarkA );
+        if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) )
+        {
+            assert( 0 ); // if it happens, can return 1 (unsatisfiable)
+            return 1;
+        }
+        pObj->fMarkA = pObj->fMarkB = 0;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs partitioned SAT solving.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManPartitionedSat( Aig_Man_t * p, int nAlgo, int nPartSize, 
+    int nConfPart, int nConfTotal, int fAlignPol, int fSynthesize, int fVerbose )
+{
+    sat_solver * pSat;
+    Vec_Ptr_t * vAigs;
+    Vec_Vec_t * vPio2Id, * vPart2Pos;
+    Aig_Man_t * pAig, * pTemp;
+    Vec_Int_t * vNode2Part, * vNode2Var;
+    int nConfRemaining = nConfTotal, nNodes = 0;
+    int i, status, RetValue = -1;
+    abctime clk;
+
+    // perform partitioning according to the selected algorithm
+    clk = Abc_Clock();
+    switch ( nAlgo )
+    {
+    case 0: 
+        vNode2Part = Aig_ManPartitionMonolithic( p );
+        break;
+    case 1: 
+        vNode2Part = Aig_ManPartitionLevelized( p, nPartSize );
+        break;
+    case 2: 
+        vNode2Part = Aig_ManPartitionDfs( p, nPartSize, 0 );
+        break;
+    case 3: 
+        vNode2Part = Aig_ManPartitionDfs( p, nPartSize, 1 );
+        break;
+    default:
+        printf( "Unknown partitioning algorithm.\n" );
+        return -1;
+    }
+
+    if ( fVerbose )
+    {
+    printf( "Partitioning derived %d partitions. ", Vec_IntFindMax(vNode2Part) + 1 );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+
+    // split the original AIG into partition AIGs (vAigs)
+    // also, derives mapping of PIs/POs of partition AIGs into original nodes
+    // also, derives mapping of POs of the original AIG into partitions
+    vAigs = Aig_ManPartSplit( p, vNode2Part, (Vec_Ptr_t **)&vPio2Id, (Vec_Ptr_t **)&vPart2Pos );
+    Vec_IntFree( vNode2Part );
+
+    if ( fVerbose )
+    {
+    printf( "Partions were transformed into AIGs. " );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+
+    // synthesize partitions
+    if ( fSynthesize )
+    Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, i )
+    {
+        pAig = Dar_ManRwsat( pTemp = pAig, 0, 0 );
+        Vec_PtrWriteEntry( vAigs, i, pAig );
+        Aig_ManStop( pTemp );
+    }
+
+    // start the SAT solver
+    pSat = sat_solver_new();
+//    pSat->verbosity = fVerbose;
+    // start mapping of the original AIG IDs into their SAT variable numbers
+    vNode2Var = Vec_IntStart( Aig_ManObjNumMax(p) );
+
+    // add partitions, one at a time, and run the SAT solver 
+    Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, i )
+    {
+clk = Abc_Clock();
+        // transform polarity of the AIG
+        if ( fAlignPol )
+            Aig_ManPartSetNodePolarity( p, pAig, Vec_VecEntryInt(vPio2Id,i) );
+        else
+            Aig_ManPartResetNodePolarity( pAig );
+        // add CNF of this partition to the SAT solver
+        if ( Aig_ManAddNewCnfToSolver( pSat, pAig, vNode2Var, 
+            Vec_VecEntryInt(vPio2Id,i), Vec_VecEntry(vPart2Pos,i), fAlignPol ) )
+        {
+            RetValue = 1;
+            break;
+        }
+        // call the SAT solver
+        status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfRemaining, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        if ( fVerbose )
+        {
+            printf( "%4d : Aig = %6d. Vs = %7d. RootCs = %7d. LearnCs = %6d. ",
+                i, nNodes += Aig_ManNodeNum(pAig), sat_solver_nvars(pSat), 
+                (int)pSat->stats.clauses, (int)pSat->stats.learnts );
+ABC_PRT( "Time", Abc_Clock() - clk );
+        }
+        // analize the result
+        if ( status == l_False )
+        {
+            RetValue = 1;
+            break;
+        }
+        else if ( status == l_True )
+            RetValue = 0;
+        else
+            RetValue = -1;
+        nConfRemaining -= pSat->stats.conflicts;
+        if ( nConfRemaining <= 0 )
+        {
+            printf( "Exceeded the limit on the total number of conflicts (%d).\n", nConfTotal );
+            break;
+        }
+    }
+    if ( RetValue == 0 )
+        Aig_ManDeriveCounterExample( p, vNode2Var, pSat );
+    // cleanup
+    sat_solver_delete( pSat );
+    Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, i )
+        Aig_ManStop( pTemp );
+    Vec_PtrFree( vAigs );
+    Vec_VecFree( vPio2Id );
+    Vec_VecFree( vPart2Pos );
+    Vec_IntFree( vNode2Var );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigRepar.c b/abc-build/src/aig/aig/aigRepar.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigRepar.c
@@ -0,0 +1,403 @@
+/**CFile****************************************************************
+
+  FileName    [aigRepar.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Interpolation-based reparametrization.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigRepar.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver2.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Adds buffer to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Aig_ManInterAddBuffer( sat_solver2 * pSat, int iVarA, int iVarB, int fCompl, int fMark )
+{
+    lit Lits[2];
+    int Cid;
+    assert( iVarA >= 0 && iVarB >= 0 );
+
+    Lits[0] = toLitCond( iVarA, 0 );
+    Lits[1] = toLitCond( iVarB, !fCompl );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 2, 0 );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+
+    Lits[0] = toLitCond( iVarA, 1 );
+    Lits[1] = toLitCond( iVarB, fCompl );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 2, 0 );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds constraints for the two-input AND-gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Aig_ManInterAddXor( sat_solver2 * pSat, int iVarA, int iVarB, int iVarC, int fCompl, int fMark )
+{
+    lit Lits[3];
+    int Cid;
+    assert( iVarA >= 0 && iVarB >= 0 && iVarC >= 0 );
+
+    Lits[0] = toLitCond( iVarA, !fCompl );
+    Lits[1] = toLitCond( iVarB, 1 );
+    Lits[2] = toLitCond( iVarC, 1 );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, 0 );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+
+    Lits[0] = toLitCond( iVarA, !fCompl );
+    Lits[1] = toLitCond( iVarB, 0 );
+    Lits[2] = toLitCond( iVarC, 0 );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, 0 );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+
+    Lits[0] = toLitCond( iVarA, fCompl );
+    Lits[1] = toLitCond( iVarB, 1 );
+    Lits[2] = toLitCond( iVarC, 0 );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, 0 );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+
+    Lits[0] = toLitCond( iVarA, fCompl );
+    Lits[1] = toLitCond( iVarB, 0 );
+    Lits[2] = toLitCond( iVarC, 1 );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, 0 );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManInterTest( Aig_Man_t * pMan, int fVerbose )
+{
+    sat_solver2 * pSat;
+//    Aig_Man_t * pInter;
+    word * pInter;
+    Vec_Int_t * vVars;
+    Cnf_Dat_t * pCnf;
+    Aig_Obj_t * pObj;
+    int Lit, Cid, Var, status, i;
+    clock_t clk = clock();
+    assert( Aig_ManRegNum(pMan) == 0 );
+    assert( Aig_ManCoNum(pMan) == 1 );
+
+    // derive CNFs
+    pCnf = Cnf_Derive( pMan, 1 );
+
+    // start the solver
+    pSat = sat_solver2_new();
+    sat_solver2_setnvars( pSat, 2*pCnf->nVars+1 );
+    // set A-variables (all used except PI/PO)
+    Aig_ManForEachObj( pMan, pObj, i )
+    {
+        if ( pCnf->pVarNums[pObj->Id] < 0 )
+            continue;
+        if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsCo(pObj) )
+            var_set_partA( pSat, pCnf->pVarNums[pObj->Id], 1 );
+    }
+
+    // add clauses of A
+    for ( i = 0; i < pCnf->nClauses; i++ )
+    {
+        Cid = sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], 0 );
+        clause2_set_partA( pSat, Cid, 1 );
+    }
+
+    // add clauses of B
+    Cnf_DataLift( pCnf, pCnf->nVars );
+    for ( i = 0; i < pCnf->nClauses; i++ )
+        sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], 0 );
+    Cnf_DataLift( pCnf, -pCnf->nVars );
+
+    // add PI equality clauses
+    vVars = Vec_IntAlloc( Aig_ManCoNum(pMan)+1 );
+    Aig_ManForEachCi( pMan, pObj, i )
+    {
+        if ( Aig_ObjRefs(pObj) == 0 )
+            continue;
+        Var = pCnf->pVarNums[pObj->Id];
+        Aig_ManInterAddBuffer( pSat, Var, pCnf->nVars + Var, 0, 0 );
+        Vec_IntPush( vVars, Var );
+    }
+
+    // add an XOR clause in the end
+    Var = pCnf->pVarNums[Aig_ManCo(pMan,0)->Id];
+    Aig_ManInterAddXor( pSat, Var, pCnf->nVars + Var, 2*pCnf->nVars, 0, 0 );
+    Vec_IntPush( vVars, Var );
+
+    // solve the problem
+    Lit = toLitCond( 2*pCnf->nVars, 0 );
+    status = sat_solver2_solve( pSat, &Lit, &Lit + 1, 0, 0, 0, 0 );
+    assert( status == l_False );
+    Sat_Solver2PrintStats( stdout, pSat );
+
+    // derive interpolant
+//    pInter = Sat_ProofInterpolant( pSat, vVars );
+//    Aig_ManPrintStats( pInter );
+//    Aig_ManDumpBlif( pInter, "int.blif", NULL, NULL );
+//pInter = Sat_ProofInterpolantTruth( pSat, vVars );
+    pInter = NULL;
+//    Extra_PrintHex( stdout, pInter, Vec_IntSize(vVars) ); printf( "\n" );
+
+    // clean up
+//    Aig_ManStop( pInter );
+    ABC_FREE( pInter );
+
+    Vec_IntFree( vVars );
+    Cnf_DataFree( pCnf );
+    sat_solver2_delete( pSat );
+    ABC_PRT( "Total interpolation time", clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG while mapping PIs into the given array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManAppend( Aig_Man_t * pBase, Aig_Man_t * pNew )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    assert( Aig_ManCoNum(pNew) == 1 );
+    assert( Aig_ManCiNum(pNew) == Aig_ManCiNum(pBase) );
+    // create the PIs
+    Aig_ManCleanData( pNew );
+    Aig_ManConst1(pNew)->pData = Aig_ManConst1(pBase);
+    Aig_ManForEachCi( pNew, pObj, i )
+        pObj->pData = Aig_IthVar(pBase, i);
+    // duplicate internal nodes
+    Aig_ManForEachNode( pNew, pObj, i )
+        pObj->pData = Aig_And( pBase, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // add one PO to base
+    pObj = Aig_ManCo( pNew, 0 );
+    Aig_ObjCreateCo( pBase, Aig_ObjChild0Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManInterRepar( Aig_Man_t * pMan, int fVerbose )
+{
+    Aig_Man_t * pAigTemp, * pInter, * pBase = NULL;
+    sat_solver2 * pSat;
+    Vec_Int_t * vVars;
+    Cnf_Dat_t * pCnf, * pCnfInter;
+    Aig_Obj_t * pObj;
+    int nOuts = Aig_ManCoNum(pMan);
+    int ShiftP[2], ShiftCnf[2], ShiftOr[2], ShiftAssume;
+    int Cid, Lit, status, i, k, c;
+    clock_t clk = clock();
+    assert( Aig_ManRegNum(pMan) == 0 );
+
+    // derive CNFs
+    pCnf = Cnf_Derive( pMan, nOuts );
+
+    // start the solver
+    pSat = sat_solver2_new();
+    sat_solver2_setnvars( pSat, 4*pCnf->nVars + 6*nOuts );
+    // vars: pGlobal + (p0 + A1 + A2 + or0) + (p1 + B1 + B2 + or1) + pAssume;
+    ShiftP[0] = nOuts;
+    ShiftP[1] = 2*pCnf->nVars + 3*nOuts;
+    ShiftCnf[0] = ShiftP[0] + nOuts;
+    ShiftCnf[1] = ShiftP[1] + nOuts;
+    ShiftOr[0] = ShiftCnf[0] + 2*pCnf->nVars;
+    ShiftOr[1] = ShiftCnf[1] + 2*pCnf->nVars;
+    ShiftAssume = ShiftOr[1] + nOuts;
+    assert( ShiftAssume + nOuts == pSat->size );
+
+    // mark variables of A
+    for ( i = ShiftCnf[0]; i < ShiftP[1]; i++ )
+        var_set_partA( pSat, i, 1 );
+
+    // add clauses of A, then B
+    vVars = Vec_IntAlloc( 2*nOuts );
+    for ( k = 0; k < 2; k++ )
+    {
+        // copy A1
+        Cnf_DataLift( pCnf, ShiftCnf[k] );
+        for ( i = 0; i < pCnf->nClauses; i++ )
+        {
+            Cid = sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], 0 );
+            clause2_set_partA( pSat, Cid, k==0 );
+        }
+        // add equality p[k] == A1/B1
+        Aig_ManForEachCo( pMan, pObj, i )
+            Aig_ManInterAddBuffer( pSat, ShiftP[k] + i, pCnf->pVarNums[pObj->Id], k==1, k==0 );
+        // copy A2
+        Cnf_DataLift( pCnf, pCnf->nVars );
+        for ( i = 0; i < pCnf->nClauses; i++ )
+        {
+            Cid = sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], 0 );
+            clause2_set_partA( pSat, Cid, k==0 );
+        }
+        // add comparator (!p[k] ^ A2/B2) == or[k]
+        Vec_IntClear( vVars );
+        Aig_ManForEachCo( pMan, pObj, i )
+        {
+            Aig_ManInterAddXor( pSat, ShiftP[k] + i, pCnf->pVarNums[pObj->Id], ShiftOr[k] + i, k==1, k==0 );
+            Vec_IntPush( vVars, toLitCond(ShiftOr[k] + i, 1) );
+        }
+        Cid = sat_solver2_addclause( pSat, Vec_IntArray(vVars), Vec_IntArray(vVars) + Vec_IntSize(vVars), 0 );
+        clause2_set_partA( pSat, Cid, k==0 );
+        // return to normal
+        Cnf_DataLift( pCnf, -ShiftCnf[k]-pCnf->nVars );
+    }
+    // add clauses to constrain p[0] and p[1]
+    for ( k = 0; k < nOuts; k++ )
+        Aig_ManInterAddXor( pSat, ShiftP[0] + k, ShiftP[1] + k, ShiftAssume + k, 0, 0 );
+
+    // start the interpolant
+    pBase = Aig_ManStart( 1000 );
+    pBase->pName = Abc_UtilStrsav( "repar" );
+    for ( k = 0; k < 2*nOuts; k++ )
+        Aig_IthVar(pBase, i);
+
+    // start global variables (pGlobal and p[0])
+    Vec_IntClear( vVars );
+    for ( k = 0; k < 2*nOuts; k++ )
+        Vec_IntPush( vVars, k );
+
+    // perform iterative solving
+    // vars: pGlobal + (p0 + A1 + A2 + or0) + (p1 + B1 + B2 + or1) + pAssume;
+    for ( k = 0; k < nOuts; k++ )
+    {
+        // swap k-th variables
+        int Temp = Vec_IntEntry( vVars, k );
+        Vec_IntWriteEntry( vVars, k, Vec_IntEntry(vVars, nOuts+k) );
+        Vec_IntWriteEntry( vVars, nOuts+k, Temp );
+
+        // solve incrementally 
+        Lit = toLitCond( ShiftAssume + k, 1 ); // XOR output is 0 ==> p1 == p2
+        status = sat_solver2_solve( pSat, &Lit, &Lit + 1, 0, 0, 0, 0 );
+        assert( status == l_False );
+        Sat_Solver2PrintStats( stdout, pSat );
+
+        // derive interpolant
+        pInter = (Aig_Man_t *)Sat_ProofInterpolant( pSat, vVars );
+        Aig_ManPrintStats( pInter );
+        // make sure interpolant does not depend on useless vars
+        Aig_ManForEachCi( pInter, pObj, i )
+            assert( i <= k || Aig_ObjRefs(pObj) == 0 );
+
+        // simplify
+        pInter = Dar_ManRwsat( pAigTemp = pInter, 1, 0 );
+        Aig_ManStop( pAigTemp );
+
+        // add interpolant to the solver
+        pCnfInter = Cnf_Derive( pInter, 1 );
+        Cnf_DataLift( pCnfInter, pSat->size );
+        sat_solver2_setnvars( pSat, pSat->size + 2*pCnfInter->nVars );
+        for ( i = 0; i < pCnfInter->nVars; i++ )
+            var_set_partA( pSat, pSat->size-2*pCnfInter->nVars + i, 1 );
+        for ( c = 0; c < 2; c++ )
+        {
+            if ( c == 1 )
+                Cnf_DataLift( pCnfInter, pCnfInter->nVars );
+            // add to A
+            for ( i = 0; i < pCnfInter->nClauses; i++ )
+            {
+                Cid = sat_solver2_addclause( pSat, pCnfInter->pClauses[i], pCnfInter->pClauses[i+1], 0 );
+                clause2_set_partA( pSat, Cid, c==0 );
+            }
+            // connect to the inputs
+            Aig_ManForEachCi( pInter, pObj, i )
+                if ( i <= k )
+                    Aig_ManInterAddBuffer( pSat, i, pCnf->pVarNums[pObj->Id], 0, c==0 );
+            // connect to the outputs
+            pObj = Aig_ManCo(pInter, 0);
+            Aig_ManInterAddBuffer( pSat, ShiftP[c] + k, pCnf->pVarNums[pObj->Id], 0, c==0 );
+            if ( c == 1 )
+                Cnf_DataLift( pCnfInter, -pCnfInter->nVars );
+        }
+        Cnf_DataFree( pCnfInter );
+
+        // accumulate
+        Aig_ManAppend( pBase, pInter );
+        Aig_ManStop( pInter );
+
+        // update global variables
+        Temp = Vec_IntEntry( vVars, k );
+        Vec_IntWriteEntry( vVars, k, Vec_IntEntry(vVars, nOuts+k) );
+        Vec_IntWriteEntry( vVars, nOuts+k, Temp );
+    }
+
+    Vec_IntFree( vVars );
+    Cnf_DataFree( pCnf );
+    sat_solver2_delete( pSat );
+    ABC_PRT( "Reparameterization time", clock() - clk );
+    return pBase;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigRepr.c b/abc-build/src/aig/aig/aigRepr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigRepr.c
@@ -0,0 +1,559 @@
+/**CFile****************************************************************
+
+  FileName    [aigRepr.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Handing node representatives.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigRepr.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the array of representatives.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManReprStart( Aig_Man_t * p, int nIdMax )
+{
+    assert( Aig_ManBufNum(p) == 0 );
+    assert( p->pReprs == NULL );
+    p->nReprsAlloc = nIdMax;
+    p->pReprs = ABC_ALLOC( Aig_Obj_t *, p->nReprsAlloc );
+    memset( p->pReprs, 0, sizeof(Aig_Obj_t *) * p->nReprsAlloc );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop the array of representatives.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManReprStop( Aig_Man_t * p )
+{
+    assert( p->pReprs != NULL );
+    ABC_FREE( p->pReprs );
+    p->nReprsAlloc = 0;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Set the representative.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjCreateRepr( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 )
+{
+    assert( p->pReprs != NULL );
+    assert( !Aig_IsComplement(pNode1) );
+    assert( !Aig_IsComplement(pNode2) );
+    assert( pNode1->Id < p->nReprsAlloc );
+    assert( pNode2->Id < p->nReprsAlloc );
+    assert( pNode1->Id < pNode2->Id );
+    p->pReprs[pNode2->Id] = pNode1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Set the representative.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Aig_ObjSetRepr_( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 )
+{
+    assert( p->pReprs != NULL );
+    assert( !Aig_IsComplement(pNode1) );
+    assert( !Aig_IsComplement(pNode2) );
+    assert( pNode1->Id < p->nReprsAlloc );
+    assert( pNode2->Id < p->nReprsAlloc );
+    if ( pNode1 == pNode2 )
+        return;
+    if ( pNode1->Id < pNode2->Id )
+        p->pReprs[pNode2->Id] = pNode1;
+    else
+        p->pReprs[pNode1->Id] = pNode2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find representative.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Aig_Obj_t * Aig_ObjFindRepr( Aig_Man_t * p, Aig_Obj_t * pNode )
+{
+    assert( p->pReprs != NULL );
+    assert( !Aig_IsComplement(pNode) );
+    assert( pNode->Id < p->nReprsAlloc );
+//    assert( !p->pReprs[pNode->Id] || p->pReprs[pNode->Id]->Id < pNode->Id );
+    return p->pReprs[pNode->Id];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Clears the representative.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Aig_ObjClearRepr( Aig_Man_t * p, Aig_Obj_t * pNode )
+{
+    assert( p->pReprs != NULL );
+    assert( !Aig_IsComplement(pNode) );
+    assert( pNode->Id < p->nReprsAlloc );
+    p->pReprs[pNode->Id] = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find representative transitively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Aig_Obj_t * Aig_ObjFindReprTransitive( Aig_Man_t * p, Aig_Obj_t * pNode )
+{
+    Aig_Obj_t * pNext, * pRepr;
+    if ( (pRepr = Aig_ObjFindRepr(p, pNode)) )
+        while ( (pNext = Aig_ObjFindRepr(p, pRepr)) )
+            pRepr = pNext;
+    return pRepr;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns representatives of fanin in approapriate polarity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Aig_Obj_t * Aig_ObjGetRepr( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pRepr;
+    if ( (pRepr = Aig_ObjFindRepr(p, pObj)) )
+        return Aig_NotCond( (Aig_Obj_t *)pRepr->pData, pObj->fPhase ^ pRepr->fPhase );
+    return (Aig_Obj_t *)pObj->pData;
+}
+static inline Aig_Obj_t * Aig_ObjChild0Repr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjGetRepr(p, Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) ); }
+static inline Aig_Obj_t * Aig_ObjChild1Repr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjGetRepr(p, Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) ); }
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG while substituting representatives.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManTransferRepr( Aig_Man_t * pNew, Aig_Man_t * pOld )
+{
+    Aig_Obj_t * pObj, * pRepr;
+    int k;
+    assert( pNew->pReprs != NULL );
+    // extend storage to fix pNew
+    if ( pNew->nReprsAlloc < Aig_ManObjNumMax(pNew) )
+    {
+        int nReprsAllocNew = 2 * Aig_ManObjNumMax(pNew);
+        pNew->pReprs = ABC_REALLOC( Aig_Obj_t *, pNew->pReprs, nReprsAllocNew );
+        memset( pNew->pReprs + pNew->nReprsAlloc, 0, sizeof(Aig_Obj_t *) * (nReprsAllocNew-pNew->nReprsAlloc) );
+        pNew->nReprsAlloc = nReprsAllocNew;
+    }
+    // go through the nodes which have representatives
+    Aig_ManForEachObj( pOld, pObj, k )
+        if ( (pRepr = Aig_ObjFindRepr(pOld, pObj)) )
+            Aig_ObjSetRepr_( pNew, Aig_Regular((Aig_Obj_t *)pRepr->pData), Aig_Regular((Aig_Obj_t *)pObj->pData) ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager recursively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_ManDupRepr_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pRepr;
+    if ( pObj->pData )
+        return (Aig_Obj_t *)pObj->pData;
+    if ( (pRepr = Aig_ObjFindRepr(p, pObj)) )
+    {
+        Aig_ManDupRepr_rec( pNew, p, pRepr );
+        return (Aig_Obj_t *)(pObj->pData = Aig_NotCond( (Aig_Obj_t *)pRepr->pData, pRepr->fPhase ^ pObj->fPhase ));
+    }
+    Aig_ManDupRepr_rec( pNew, p, Aig_ObjFanin0(pObj) );
+    Aig_ManDupRepr_rec( pNew, p, Aig_ObjFanin1(pObj) );
+    return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Repr(p, pObj), Aig_ObjChild1Repr(p, pObj) ));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG while substituting representatives.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupRepr( Aig_Man_t * p, int fOrdered )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    // start the HOP package
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nConstrs = p->nConstrs;
+    pNew->nBarBufs = p->nBarBufs;
+    if ( p->vFlopNums )
+        pNew->vFlopNums = Vec_IntDup( p->vFlopNums );
+    // map the const and primary inputs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCi(pNew);
+//    Aig_ManForEachCi( p, pObj, i )
+//        pObj->pData = Aig_ObjGetRepr( p, pObj );
+    // map the internal nodes
+    if ( fOrdered )
+    {
+        Aig_ManForEachNode( p, pObj, i )
+            pObj->pData = Aig_And( pNew, Aig_ObjChild0Repr(p, pObj), Aig_ObjChild1Repr(p, pObj) );
+    }
+    else
+    {
+//        Aig_ManForEachObj( p, pObj, i )
+//            if ( p->pReprs[i] )
+//                printf( "Substituting %d for %d.\n", p->pReprs[i]->Id, pObj->Id );
+
+        Aig_ManForEachCo( p, pObj, i )
+            Aig_ManDupRepr_rec( pNew, p, Aig_ObjFanin0(pObj) );
+    }
+    // transfer the POs
+    Aig_ManForEachCo( p, pObj, i )
+        Aig_ObjCreateCo( pNew, Aig_ObjChild0Repr(p, pObj) );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // check the new manager
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManDupRepr: Check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG with representatives without removing registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupReprBasic( Aig_Man_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( p->pReprs != NULL );
+    // reconstruct AIG with representatives
+    pNew = Aig_ManDupRepr( p, 0 );
+    // perfrom sequential cleanup but do not remove registers
+    Aig_ManSeqCleanupBasic( pNew );
+    // remove pointers to the dead nodes
+    Aig_ManForEachObj( p, pObj, i )
+        if ( pObj->pData && Aig_ObjIsNone((Aig_Obj_t *)pObj->pData) )
+            pObj->pData = NULL;
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfer representatives and return the number of critical fanouts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManRemapRepr( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pRepr;
+    int i, nFanouts = 0;
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        pRepr = Aig_ObjFindReprTransitive( p, pObj );
+        if ( pRepr == NULL )
+            continue;
+        assert( pRepr->Id < pObj->Id );
+        Aig_ObjSetRepr_( p, pObj, pRepr );
+        nFanouts += (pObj->nRefs > 0);
+    }
+    return nFanouts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfer representatives and return the number of critical fanouts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManCountReprs( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    if ( p->pReprs == NULL )
+        return 0;
+    Aig_ManForEachObj( p, pObj, i )
+        Counter += (p->pReprs[i] != NULL);
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pOld is in the TFI of pNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjCheckTfi_rec( Aig_Man_t * p, Aig_Obj_t * pNode, Aig_Obj_t * pOld )
+{
+    // check the trivial cases
+    if ( pNode == NULL )
+        return 0;
+    if ( Aig_ObjIsCi(pNode) )
+        return 0;
+//    if ( pNode->Id < pOld->Id ) // cannot use because of choices of pNode
+//        return 0;
+    if ( pNode == pOld )
+        return 1;
+    // skip the visited node
+    if ( Aig_ObjIsTravIdCurrent( p, pNode ) )
+        return 0;
+    Aig_ObjSetTravIdCurrent( p, pNode );
+    // check the children
+    if ( Aig_ObjCheckTfi_rec( p, Aig_ObjFanin0(pNode), pOld ) )
+        return 1;
+    if ( Aig_ObjCheckTfi_rec( p, Aig_ObjFanin1(pNode), pOld ) )
+        return 1;
+    // check equivalent nodes
+    return Aig_ObjCheckTfi_rec( p, Aig_ObjEquiv(p, pNode), pOld );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pOld is in the TFI of pNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pNew, Aig_Obj_t * pOld )
+{
+    assert( !Aig_IsComplement(pNew) );
+    assert( !Aig_IsComplement(pOld) );
+    Aig_ManIncrementTravId( p );
+    return Aig_ObjCheckTfi_rec( p, pNew, pOld );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Iteratively rehashes the AIG.]
+
+  Description [The input AIG is assumed to have representatives assigned.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManRehash( Aig_Man_t * p )
+{
+    Aig_Man_t * pTemp;
+    int i, nFanouts;
+    assert( p->pReprs != NULL );
+    for ( i = 0; (nFanouts = Aig_ManRemapRepr( p )); i++ )
+    {
+//        printf( "Iter = %3d. Fanouts = %6d. Nodes = %7d.\n", i+1, nFanouts, Aig_ManNodeNum(p) );
+        p = Aig_ManDupRepr( pTemp = p, 1 );
+        Aig_ManReprStart( p, Aig_ManObjNumMax(p) );
+        Aig_ManTransferRepr( p, pTemp );
+        Aig_ManStop( pTemp );
+    }
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the nodes that are Creates choices.]
+
+  Description [The input AIG is assumed to have representatives assigned.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManMarkValidChoices( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pRepr;
+    int i;
+    assert( p->pReprs != NULL );
+    // create equivalent nodes in the manager
+    assert( p->pEquivs == NULL );
+    p->pEquivs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) );
+    memset( p->pEquivs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p) );
+    // make the choice nodes
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        pRepr = Aig_ObjFindRepr( p, pObj );
+        if ( pRepr == NULL )
+            continue;
+        // skip constant and PI classes
+        if ( !Aig_ObjIsNode(pRepr) )
+        {
+            Aig_ObjClearRepr( p, pObj );
+            continue;
+        }
+        // skip choices with combinatinal loops
+        if ( Aig_ObjCheckTfi( p, pObj, pRepr ) )
+        {
+            Aig_ObjClearRepr( p, pObj );
+            continue;
+        }
+//printf( "Node %d is represented by node %d.\n", pObj->Id, pRepr->Id );
+        // add choice to the choice node
+        if ( pObj->nRefs > 0 )
+        {
+            Aig_ObjClearRepr( p, pObj );
+            continue;
+        }
+        assert( pObj->nRefs == 0 );
+        p->pEquivs[pObj->Id] = p->pEquivs[pRepr->Id];
+        p->pEquivs[pRepr->Id] = pObj;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_TransferMappedClasses( Aig_Man_t * pAig, Aig_Man_t * pPart, int * pMapBack )
+{
+    Aig_Obj_t * pObj;
+    int nClasses, k;
+    nClasses = 0;
+    if ( pPart->pReprs ) {
+      Aig_ManForEachObj( pPart, pObj, k )
+      {
+          if ( pPart->pReprs[pObj->Id] == NULL )
+              continue;
+          nClasses++;
+          Aig_ObjSetRepr_( pAig,
+              Aig_ManObj(pAig, pMapBack[pObj->Id]),
+              Aig_ManObj(pAig, pMapBack[pPart->pReprs[pObj->Id]->Id]) );
+      }
+    }
+    return nClasses;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigRet.c b/abc-build/src/aig/aig/aigRet.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigRet.c
@@ -0,0 +1,975 @@
+/**CFile****************************************************************
+
+  FileName    [aigRet.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Retiming of AIGs.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigRet.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// init values
+typedef enum { 
+    RTM_VAL_NONE,                    // 0: non-existent value
+    RTM_VAL_ZERO,                    // 1: initial value 0
+    RTM_VAL_ONE,                     // 2: initial value 1
+    RTM_VAL_VOID                     // 3: unused value
+} Rtm_Init_t;
+
+typedef struct Rtm_Man_t_    Rtm_Man_t;
+struct Rtm_Man_t_
+{
+    // network representation
+    Vec_Ptr_t *      vObjs;          // retiming objects
+    Vec_Ptr_t *      vPis;           // PIs only
+    Vec_Ptr_t *      vPos;           // POs only
+    Aig_MmFlex_t *   pMem;           // the memory manager
+    // autonomous components after cutting off
+    // storage for overflow latches
+    unsigned *       pExtra;   
+    int              nExtraCur;
+    int              nExtraAlloc;
+};
+
+typedef struct Rtm_Edg_t_    Rtm_Edg_t;
+struct Rtm_Edg_t_
+{
+    unsigned long    nLats   :  12;  // the number of latches
+    unsigned long    LData   :  20;  // the latches themselves
+};
+
+typedef struct Rtm_Obj_t_    Rtm_Obj_t;
+struct Rtm_Obj_t_
+{
+    void *           pCopy;          // the copy of this object
+    unsigned long    Type    :  3;   // object type
+    unsigned long    fMark   :  1;   // multipurpose mark
+    unsigned long    fAuto   :  1;   // this object belongs to an autonomous component
+    unsigned long    fCompl0 :  1;   // complemented attribute of the first edge
+    unsigned long    fCompl1 :  1;   // complemented attribute of the second edge
+    unsigned long    nFanins :  8;   // the number of fanins
+    unsigned         Num     : 17;   // the retiming number of this node
+    int              Id;             // ID of this object
+    int              Temp;           // temporary usage
+    int              nFanouts;       // the number of fanouts
+    void *           pFanio[0];      // fanins and their edges (followed by fanouts and pointers to their edges)
+};
+
+static inline Rtm_Obj_t * Rtm_ObjFanin( Rtm_Obj_t * pObj, int i )        { return (Rtm_Obj_t *)pObj->pFanio[2*i];                     }
+static inline Rtm_Obj_t * Rtm_ObjFanout( Rtm_Obj_t * pObj, int i )       { return (Rtm_Obj_t *)pObj->pFanio[2*(pObj->nFanins+i)];     }
+static inline Rtm_Edg_t * Rtm_ObjEdge( Rtm_Obj_t * pObj, int i )         { return (Rtm_Edg_t *)(pObj->pFanio + 2*i + 1);              }
+static inline Rtm_Edg_t * Rtm_ObjFanoutEdge( Rtm_Obj_t * pObj, int i )   { return (Rtm_Edg_t *)pObj->pFanio[2*(pObj->nFanins+i) + 1]; }
+
+static inline Rtm_Init_t  Rtm_InitNot( Rtm_Init_t Val )                  { if ( Val == RTM_VAL_ZERO ) return (Rtm_Init_t)RTM_VAL_ONE; if ( Val == RTM_VAL_ONE ) return (Rtm_Init_t)RTM_VAL_ZERO; assert( 0 ); return (Rtm_Init_t)-1; }
+static inline Rtm_Init_t  Rtm_InitNotCond( Rtm_Init_t Val, int c )       { return c ? Rtm_InitNot(Val) : Val;                         }
+static inline Rtm_Init_t  Rtm_InitAnd(Rtm_Init_t ValA, Rtm_Init_t ValB ) { if ( ValA == RTM_VAL_ONE && ValB == RTM_VAL_ONE ) return (Rtm_Init_t)RTM_VAL_ONE;  if ( ValA == RTM_VAL_ZERO || ValB == RTM_VAL_ZERO ) return (Rtm_Init_t)RTM_VAL_ZERO; assert( 0 ); return (Rtm_Init_t)-1;   }
+
+static inline int         Rtm_InitWordsNum( int nLats )                  { return (nLats >> 4) + ((nLats & 15) > 0); }
+static inline int         Rtm_InitGetTwo( unsigned * p, int i )          { return (p[i>>4] >> ((i & 15)<<1)) & 3;    }
+static inline void        Rtm_InitSetTwo( unsigned * p, int i, int val ) { p[i>>4] |= (val << ((i & 15)<<1));        }
+static inline void        Rtm_InitXorTwo( unsigned * p, int i, int val ) { p[i>>4] ^= (val << ((i & 15)<<1));        }
+
+static inline Rtm_Init_t  Rtm_ObjGetFirst1( Rtm_Edg_t * pEdge )          { return (Rtm_Init_t)(pEdge->LData & 3);                                    }
+static inline Rtm_Init_t  Rtm_ObjGetLast1( Rtm_Edg_t * pEdge )           { return (Rtm_Init_t)((pEdge->LData >> ((pEdge->nLats-1)<<1)) & 3);         }
+static inline Rtm_Init_t  Rtm_ObjGetOne1( Rtm_Edg_t * pEdge, int i )     { assert( i < (int)pEdge->nLats ); return (Rtm_Init_t)((pEdge->LData >> (i << 1)) & 3);  }
+static inline Rtm_Init_t  Rtm_ObjRemFirst1( Rtm_Edg_t * pEdge )          { int Val = pEdge->LData & 3; pEdge->LData >>= 2; assert(pEdge->nLats > 0); pEdge->nLats--; return (Rtm_Init_t)Val;  }
+static inline Rtm_Init_t  Rtm_ObjRemLast1( Rtm_Edg_t * pEdge )           { int Val = (pEdge->LData >> ((pEdge->nLats-1)<<1)) & 3; pEdge->LData ^= Val << ((pEdge->nLats-1)<<1); assert(pEdge->nLats > 0); pEdge->nLats--; return (Rtm_Init_t)Val;  }
+static inline void        Rtm_ObjAddFirst1( Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { assert( Val > 0 ); pEdge->LData = (pEdge->LData << 2) | Val;  pEdge->nLats++;   }
+static inline void        Rtm_ObjAddLast1( Rtm_Edg_t * pEdge, Rtm_Init_t Val )  { assert( Val > 0 ); pEdge->LData |= Val << (pEdge->nLats<<1);  pEdge->nLats++;   }
+
+static inline Rtm_Init_t  Rtm_ObjGetFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge )                 { return (Rtm_Init_t)Rtm_InitGetTwo( p->pExtra + pEdge->LData, 0 );                }
+static inline Rtm_Init_t  Rtm_ObjGetLast2( Rtm_Man_t * p, Rtm_Edg_t * pEdge )                  { return (Rtm_Init_t)Rtm_InitGetTwo( p->pExtra + pEdge->LData, pEdge->nLats - 1 ); }
+static inline Rtm_Init_t  Rtm_ObjGetOne2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, int i )            { return (Rtm_Init_t)Rtm_InitGetTwo( p->pExtra + pEdge->LData, i );                }
+static        Rtm_Init_t  Rtm_ObjRemFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge );
+static inline Rtm_Init_t  Rtm_ObjRemLast2( Rtm_Man_t * p, Rtm_Edg_t * pEdge )                  { Rtm_Init_t Val = Rtm_ObjGetLast2( p, pEdge );    Rtm_InitXorTwo( p->pExtra + pEdge->LData, pEdge->nLats - 1, Val ); pEdge->nLats--; return (Rtm_Init_t)Val; }
+static        void        Rtm_ObjAddFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val );
+static inline void        Rtm_ObjAddLast2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val )  { Rtm_InitSetTwo( p->pExtra + pEdge->LData, pEdge->nLats, Val );  pEdge->nLats++;  }
+
+static        void        Rtm_ObjTransferToSmall( Rtm_Man_t * p, Rtm_Edg_t * pEdge );
+static        void        Rtm_ObjTransferToBig( Rtm_Man_t * p, Rtm_Edg_t * pEdge ); 
+static        void        Rtm_ObjTransferToBigger( Rtm_Man_t * p, Rtm_Edg_t * pEdge );
+
+static inline Rtm_Init_t  Rtm_ObjGetFirst( Rtm_Man_t * p, Rtm_Edg_t * pEdge )                  { return pEdge->nLats > 10? Rtm_ObjGetFirst2(p, pEdge)  : Rtm_ObjGetFirst1(pEdge);   }
+static inline Rtm_Init_t  Rtm_ObjGetLast( Rtm_Man_t * p, Rtm_Edg_t * pEdge )                   { return pEdge->nLats > 10? Rtm_ObjGetLast2(p, pEdge)   : Rtm_ObjGetLast1(pEdge);    }
+static inline Rtm_Init_t  Rtm_ObjGetOne( Rtm_Man_t * p, Rtm_Edg_t * pEdge, int i )             { return pEdge->nLats > 10? Rtm_ObjGetOne2(p, pEdge, i) : Rtm_ObjGetOne1(pEdge, i);  }
+static        Rtm_Init_t  Rtm_ObjRemFirst( Rtm_Man_t * p, Rtm_Edg_t * pEdge )                  { Rtm_Init_t Res = pEdge->nLats > 10 ? Rtm_ObjRemFirst2(p, pEdge) : Rtm_ObjRemFirst1(pEdge); if ( pEdge->nLats == 10 ) Rtm_ObjTransferToSmall(p, pEdge); return Res; }
+static        Rtm_Init_t  Rtm_ObjRemLast( Rtm_Man_t * p, Rtm_Edg_t * pEdge )                   { Rtm_Init_t Res = pEdge->nLats > 10 ? Rtm_ObjRemLast2(p, pEdge)  : Rtm_ObjRemLast1(pEdge);  if ( pEdge->nLats == 10 ) Rtm_ObjTransferToSmall(p, pEdge); return Res; }
+static        void        Rtm_ObjAddFirst( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val )  { if ( pEdge->nLats == 10 ) Rtm_ObjTransferToBig(p, pEdge); else if ( (pEdge->nLats & 15) == 15 ) Rtm_ObjTransferToBigger(p, pEdge); if ( pEdge->nLats >= 10 ) Rtm_ObjAddFirst2(p, pEdge, Val); else Rtm_ObjAddFirst1(pEdge, Val); }
+static        void        Rtm_ObjAddLast( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val )   { if ( pEdge->nLats == 10 ) Rtm_ObjTransferToBig(p, pEdge); else if ( (pEdge->nLats & 15) == 15 ) Rtm_ObjTransferToBigger(p, pEdge); if ( pEdge->nLats >= 10 ) Rtm_ObjAddLast2(p, pEdge, Val);  else Rtm_ObjAddLast1(pEdge, Val);  }
+
+
+// iterator over the primary inputs
+#define Rtm_ManForEachPi( p, pObj, i )                                          \
+    Vec_PtrForEachEntry( Rtm_Obj_t *, p->vPis, pObj, i )
+// iterator over the primary outputs
+#define Rtm_ManForEachPo( p, pObj, i )                                          \
+    Vec_PtrForEachEntry( Rtm_Obj_t *, p->vPos, pObj, i )
+// iterator over all objects, including those currently not used
+#define Rtm_ManForEachObj( p, pObj, i )                                         \
+    Vec_PtrForEachEntry( Rtm_Obj_t *, p->vObjs, pObj, i ) 
+// iterate through the fanins
+#define Rtm_ObjForEachFanin( pObj, pFanin, i )                                  \
+    for ( i = 0; i < (int)(pObj)->nFanins && ((pFanin = Rtm_ObjFanin(pObj, i)), 1); i++ )
+// iterate through the fanouts
+#define Rtm_ObjForEachFanout( pObj, pFanout, i )                                \
+    for ( i = 0; i < (int)(pObj)->nFanouts && ((pFanout = Rtm_ObjFanout(pObj, i)), 1); i++ )
+// iterate through the fanin edges
+#define Rtm_ObjForEachFaninEdge( pObj, pEdge, i )                               \
+    for ( i = 0; i < (int)(pObj)->nFanins && ((pEdge = Rtm_ObjEdge(pObj, i)), 1); i++ )
+// iterate through the fanout edges
+#define Rtm_ObjForEachFanoutEdge( pObj, pEdge, i )                              \
+    for ( i = 0; i < (int)(pObj)->nFanouts && ((pEdge = Rtm_ObjFanoutEdge(pObj, i)), 1); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers from big to small storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rtm_ObjTransferToSmall( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) 
+{
+    assert( pEdge->nLats == 10 );
+    pEdge->LData = p->pExtra[pEdge->LData];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers from small to big storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rtm_ObjTransferToBig( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) 
+{
+    assert( pEdge->nLats == 10 );
+    if ( p->nExtraCur + 1 > p->nExtraAlloc )
+    {
+        int nExtraAllocNew = Abc_MaxInt( 2 * p->nExtraAlloc, 1024 );
+        p->pExtra = ABC_REALLOC( unsigned, p->pExtra, nExtraAllocNew );
+        p->nExtraAlloc = nExtraAllocNew;
+    }
+    p->pExtra[p->nExtraCur] = pEdge->LData;
+    pEdge->LData = p->nExtraCur++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers to bigger storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rtm_ObjTransferToBigger( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) 
+{
+    int nWords;
+    assert( (pEdge->nLats & 15) == 15 );
+    nWords = (pEdge->nLats + 1) >> 4;
+    if ( p->nExtraCur + nWords + 1 > p->nExtraAlloc )
+    {
+        int nExtraAllocNew = Abc_MaxInt( 2 * p->nExtraAlloc, 1024 );
+        p->pExtra = ABC_REALLOC( unsigned, p->pExtra, nExtraAllocNew );
+        p->nExtraAlloc = nExtraAllocNew;
+    }
+    memcpy( p->pExtra + p->nExtraCur, p->pExtra + pEdge->LData, sizeof(unsigned) * nWords );
+    p->pExtra[p->nExtraCur + nWords] = 0;
+    pEdge->LData = p->nExtraCur;
+    p->nExtraCur += nWords + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Rtm_Init_t  Rtm_ObjRemFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge )                 
+{ 
+    Rtm_Init_t Val = (Rtm_Init_t)0, Temp;   
+    unsigned * pB = p->pExtra + pEdge->LData, * pE = pB + Rtm_InitWordsNum( pEdge->nLats-- ) - 1;  
+    while ( pE >= pB ) 
+    {
+        Temp = (Rtm_Init_t)(*pE & 3);
+        *pE = (*pE >> 2) | (Val << 30);
+        Val = Temp;
+        pE--;
+    }
+    assert( Val != 0 );
+    return Val;  
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rtm_ObjAddFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ) 
+{
+    unsigned * pB = p->pExtra + pEdge->LData, * pE = pB + Rtm_InitWordsNum( ++pEdge->nLats ); 
+    Rtm_Init_t Temp;
+    assert( Val != 0 );
+    while ( pB < pE ) 
+    {
+        Temp = (Rtm_Init_t)(*pB >> 30);
+        *pB = (*pB << 2) | Val;
+        Val = Temp;
+        pB++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rtm_PrintEdge( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) 
+{
+//    unsigned LData = pEdge->LData;
+    printf( "%d : ", (int)pEdge->nLats );
+/*
+    if ( pEdge->nLats > 10 )
+        Extra_PrintBinary( stdout, p->pExtra + pEdge->LData, 2*(pEdge->nLats+1) );
+    else
+        Extra_PrintBinary( stdout, &LData, 2*(pEdge->nLats+1) );
+*/
+    printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the retiming manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Rtm_Man_t * Rtm_ManAlloc( Aig_Man_t * p )
+{
+    Rtm_Man_t * pRtm;
+    // start the manager
+    pRtm = ABC_ALLOC( Rtm_Man_t, 1 );
+    memset( pRtm, 0, sizeof(Rtm_Man_t) );
+    // perform initializations
+    pRtm->vObjs = Vec_PtrAlloc( Aig_ManObjNum(p) );
+    pRtm->vPis  = Vec_PtrAlloc( Aig_ManCiNum(p) );
+    pRtm->vPos  = Vec_PtrAlloc( Aig_ManCoNum(p) );
+    pRtm->pMem  = Aig_MmFlexStart();
+    return pRtm;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the retiming manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rtm_ManFree( Rtm_Man_t * p )
+{
+    Vec_PtrFree( p->vObjs );
+    Vec_PtrFree( p->vPis );
+    Vec_PtrFree( p->vPos );
+    Aig_MmFlexStop( p->pMem, 0 );
+    ABC_FREE( p->pExtra );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the maximum number of latches on an edge.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rtm_ManLatchMax( Rtm_Man_t * p )
+{
+    Rtm_Obj_t * pObj;
+    Rtm_Edg_t * pEdge;
+    int nLatchMax = 0, i, k;//, c, Val;
+    Rtm_ManForEachObj( p, pObj, i )
+    Rtm_ObjForEachFaninEdge( pObj, pEdge, k )
+    {
+/*
+        for ( c = 0; c < (int)pEdge->nLats; c++ )
+        {
+            Val = Rtm_ObjGetOne( p, pEdge, c );
+            assert( Val == 1 || Val == 2 );
+        }
+*/
+        nLatchMax = Abc_MaxInt( nLatchMax, (int)pEdge->nLats );
+    }
+    return nLatchMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the retiming object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Rtm_Obj_t * Rtm_ObjAlloc( Rtm_Man_t * pRtm, int nFanins, int nFanouts )
+{
+    Rtm_Obj_t * pObj;
+    int Size = sizeof(Rtm_Obj_t) + sizeof(Rtm_Obj_t *) * (nFanins + nFanouts) * 2;
+    pObj = (Rtm_Obj_t *)Aig_MmFlexEntryFetch( pRtm->pMem, Size );
+    memset( pObj, 0, sizeof(Rtm_Obj_t) );
+    pObj->Type = (int)(nFanins == 1 && nFanouts == 0); // mark PO
+    pObj->Num  = nFanins;  // temporary
+    pObj->Temp = nFanouts;
+    pObj->Id = Vec_PtrSize(pRtm->vObjs);
+    Vec_PtrPush( pRtm->vObjs, pObj );
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the retiming object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rtm_ObjAddFanin( Rtm_Obj_t * pObj, Rtm_Obj_t * pFanin, int fCompl )
+{
+    pObj->pFanio[ 2*pObj->nFanins ] = pFanin;
+    pObj->pFanio[ 2*pObj->nFanins + 1 ] = NULL;
+    pFanin->pFanio[ 2*(pFanin->Num + pFanin->nFanouts) ] = pObj;
+    pFanin->pFanio[ 2*(pFanin->Num + pFanin->nFanouts) + 1 ] = pObj->pFanio + 2*pObj->nFanins + 1;
+    if ( pObj->nFanins == 0 )
+        pObj->fCompl0 = fCompl;
+    else if ( pObj->nFanins == 1 )
+        pObj->fCompl1 = fCompl;
+    else
+        assert( 0 );
+    pObj->nFanins++;
+    pFanin->nFanouts++;
+    assert( pObj->nFanins <= pObj->Num );
+    assert( pFanin->nFanouts <= pFanin->Temp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check the possibility of forward retiming.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rtm_ObjCheckRetimeFwd( Rtm_Obj_t * pObj )
+{
+    Rtm_Edg_t * pEdge;
+    int i;
+    Rtm_ObjForEachFaninEdge( pObj, pEdge, i )
+        if ( pEdge->nLats == 0 )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check the possibility of forward retiming.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rtm_ObjCheckRetimeBwd( Rtm_Obj_t * pObj )
+{
+    Rtm_Edg_t * pEdge;
+    int i;
+    Rtm_ObjForEachFanoutEdge( pObj, pEdge, i )
+        if ( pEdge->nLats == 0 )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check the possibility of forward retiming.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rtm_ObjGetDegreeFwd( Rtm_Obj_t * pObj )
+{
+    Rtm_Obj_t * pFanin;
+    int i, Degree = 0;
+    Rtm_ObjForEachFanin( pObj, pFanin, i )
+        Degree = Abc_MaxInt( Degree, (int)pFanin->Num );
+    return Degree + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check the possibility of forward retiming.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rtm_ObjGetDegreeBwd( Rtm_Obj_t * pObj )
+{
+    Rtm_Obj_t * pFanout;
+    int i, Degree = 0;
+    Rtm_ObjForEachFanout( pObj, pFanout, i )
+        Degree = Abc_MaxInt( Degree, (int)pFanout->Num );
+    return Degree + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs forward retiming.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rtm_ObjRetimeFwd( Rtm_Man_t * pRtm, Rtm_Obj_t * pObj )
+{
+    Rtm_Init_t ValTotal, ValCur;
+    Rtm_Edg_t * pEdge;
+    int i;
+    assert( Rtm_ObjCheckRetimeFwd(pObj) );
+    // extract values and compute the result
+    ValTotal = RTM_VAL_ONE;
+    Rtm_ObjForEachFaninEdge( pObj, pEdge, i )
+    {
+        ValCur = Rtm_ObjRemFirst( pRtm, pEdge );
+        ValCur = Rtm_InitNotCond( ValCur, i? pObj->fCompl1 : pObj->fCompl0 );
+        ValTotal = Rtm_InitAnd( ValTotal, ValCur );
+    }
+    // insert the result in the fanout values
+    Rtm_ObjForEachFanoutEdge( pObj, pEdge, i )
+        Rtm_ObjAddLast( pRtm, pEdge, ValTotal );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs forward retiming.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rtm_ObjRetimeBwd( Rtm_Man_t * pRtm, Rtm_Obj_t * pObj )
+{
+    Rtm_Edg_t * pEdge;
+    int i;
+    assert( Rtm_ObjCheckRetimeBwd(pObj) );
+    // extract values and compute the result
+    Rtm_ObjForEachFanoutEdge( pObj, pEdge, i )
+        Rtm_ObjRemLast( pRtm, pEdge );
+    // insert the result in the fanout values
+    Rtm_ObjForEachFaninEdge( pObj, pEdge, i )
+        Rtm_ObjAddFirst( pRtm, pEdge, RTM_VAL_VOID );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rtm_ObjMarkAutoFwd_rec( Rtm_Obj_t * pObj )
+{
+    Rtm_Obj_t * pFanout;
+    int i;
+    if ( pObj->fAuto )
+        return;
+    pObj->fAuto = 1;
+    Rtm_ObjForEachFanout( pObj, pFanout, i )
+        Rtm_ObjMarkAutoFwd_rec( pFanout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the nodes unreachable from the PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rtm_ManMarkAutoFwd( Rtm_Man_t * pRtm )
+{
+    Rtm_Obj_t * pObjRtm;
+    int i, Counter = 0;
+    // mark nodes reachable from the PIs
+    pObjRtm = (Rtm_Obj_t *)Vec_PtrEntry( pRtm->vObjs, 0 );
+    Rtm_ObjMarkAutoFwd_rec( pObjRtm );
+    Rtm_ManForEachPi( pRtm, pObjRtm, i )
+        Rtm_ObjMarkAutoFwd_rec( pObjRtm );
+    // count the number of autonomous nodes
+    Rtm_ManForEachObj( pRtm, pObjRtm, i )
+    {
+        pObjRtm->fAuto = !pObjRtm->fAuto;
+        Counter += pObjRtm->fAuto;
+    }
+    // mark the fanins of the autonomous nodes
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rtm_ObjMarkAutoBwd_rec( Rtm_Obj_t * pObj )
+{
+    Rtm_Obj_t * pFanin;
+    int i;
+    if ( pObj->fAuto )
+        return;
+    pObj->fAuto = 1;
+    Rtm_ObjForEachFanin( pObj, pFanin, i )
+        Rtm_ObjMarkAutoBwd_rec( pFanin );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the nodes unreachable from the POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rtm_ManMarkAutoBwd( Rtm_Man_t * pRtm )
+{
+    Rtm_Obj_t * pObjRtm;
+    int i, Counter = 0;
+    // mark nodes reachable from the PIs
+    pObjRtm = (Rtm_Obj_t *)Vec_PtrEntry( pRtm->vObjs, 0 );
+    pObjRtm->fAuto = 1;
+    Rtm_ManForEachPi( pRtm, pObjRtm, i )
+        pObjRtm->fAuto = 1;
+    Rtm_ManForEachPo( pRtm, pObjRtm, i )
+        Rtm_ObjMarkAutoBwd_rec( pObjRtm );
+    // count the number of autonomous nodes
+    Rtm_ManForEachObj( pRtm, pObjRtm, i )
+    {
+        pObjRtm->fAuto = !pObjRtm->fAuto;
+        Counter += pObjRtm->fAuto;
+    }
+    // mark the fanins of the autonomous nodes
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive retiming manager from the given AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Rtm_Man_t * Rtm_ManFromAig( Aig_Man_t * p )
+{
+    Rtm_Man_t * pRtm;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i;
+    assert( Aig_ManRegNum(p) > 0 );
+    assert( Aig_ManBufNum(p) == 0 );
+    // allocate the manager
+    pRtm = Rtm_ManAlloc( p );
+    // allocate objects
+    pObj = Aig_ManConst1(p);
+    pObj->pData = Rtm_ObjAlloc( pRtm, 0, pObj->nRefs );
+    Aig_ManForEachPiSeq( p, pObj, i )
+    {
+        pObj->pData = Rtm_ObjAlloc( pRtm, 0, pObj->nRefs );
+        Vec_PtrPush( pRtm->vPis, pObj->pData );
+    }
+    Aig_ManForEachPoSeq( p, pObj, i )
+    {
+        pObj->pData = Rtm_ObjAlloc( pRtm, 1, 0 );
+        Vec_PtrPush( pRtm->vPos, pObj->pData );
+    }
+    Aig_ManForEachLoSeq( p, pObj, i )
+        pObj->pData = Rtm_ObjAlloc( pRtm, 1, pObj->nRefs );
+    Aig_ManForEachLiSeq( p, pObj, i )
+        pObj->pData = Rtm_ObjAlloc( pRtm, 1, 1 );
+    Aig_ManForEachNode( p, pObj, i )
+        pObj->pData = Rtm_ObjAlloc( pRtm, 2, pObj->nRefs );
+    // connect objects
+    Aig_ManForEachPoSeq( p, pObj, i )
+        Rtm_ObjAddFanin( (Rtm_Obj_t *)pObj->pData, (Rtm_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+    Aig_ManForEachLiSeq( p, pObj, i )
+        Rtm_ObjAddFanin( (Rtm_Obj_t *)pObj->pData, (Rtm_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+    Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+        Rtm_ObjAddFanin( (Rtm_Obj_t *)pObjLo->pData, (Rtm_Obj_t *)pObjLi->pData, 0 );
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        Rtm_ObjAddFanin( (Rtm_Obj_t *)pObj->pData, (Rtm_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+        Rtm_ObjAddFanin( (Rtm_Obj_t *)pObj->pData, (Rtm_Obj_t *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+    }
+    return pRtm;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive AIG manager after retiming.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Rtm_ManToAig_rec( Aig_Man_t * pNew, Rtm_Man_t * pRtm, Rtm_Obj_t * pObjRtm, int * pLatches )
+{
+    Rtm_Edg_t * pEdge;
+    Aig_Obj_t * pRes, * pFanin;
+    int k, Val;
+    if ( pObjRtm->pCopy )
+        return (Aig_Obj_t *)pObjRtm->pCopy;
+    // get the inputs
+    pRes = Aig_ManConst1( pNew );
+    Rtm_ObjForEachFaninEdge( pObjRtm, pEdge, k )
+    {
+        if ( pEdge->nLats == 0 )
+            pFanin = Rtm_ManToAig_rec( pNew, pRtm, Rtm_ObjFanin(pObjRtm, k), pLatches );
+        else
+        {
+            Val = Rtm_ObjGetFirst( pRtm, pEdge );
+            pFanin = Aig_ManCi( pNew, pLatches[2*pObjRtm->Id + k] + pEdge->nLats - 1 );
+            pFanin = Aig_NotCond( pFanin, Val == RTM_VAL_ONE );
+        }
+        pFanin = Aig_NotCond( pFanin, k ? pObjRtm->fCompl1 : pObjRtm->fCompl0 );
+        pRes = Aig_And( pNew, pRes, pFanin );
+    }
+    return (Aig_Obj_t *)(pObjRtm->pCopy = pRes);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive AIG manager after retiming.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Rtm_ManToAig( Rtm_Man_t * pRtm )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObjNew;
+    Rtm_Obj_t * pObjRtm;
+    Rtm_Edg_t * pEdge;
+    int i, k, m, Val, nLatches, * pLatches;
+    // count latches and mark the first latch on each edge
+    pLatches = ABC_ALLOC( int, 2 * Vec_PtrSize(pRtm->vObjs) );
+    nLatches = 0;
+    Rtm_ManForEachObj( pRtm, pObjRtm, i )
+    Rtm_ObjForEachFaninEdge( pObjRtm, pEdge, k )
+    {
+        pLatches[2*pObjRtm->Id + k] = Vec_PtrSize(pRtm->vPis) + nLatches;
+        nLatches += pEdge->nLats;
+    }
+    // create the new manager
+    pNew = Aig_ManStart( Vec_PtrSize(pRtm->vObjs) + nLatches );
+    // create PIs/POs and latches
+    pObjRtm = (Rtm_Obj_t *)Vec_PtrEntry( pRtm->vObjs, 0 );
+    pObjRtm->pCopy = Aig_ManConst1(pNew);
+    Rtm_ManForEachPi( pRtm, pObjRtm, i )
+        pObjRtm->pCopy = Aig_ObjCreateCi(pNew);
+    for ( i = 0; i < nLatches; i++ )
+        Aig_ObjCreateCi(pNew);
+    // create internal nodes
+    Rtm_ManForEachObj( pRtm, pObjRtm, i )
+        Rtm_ManToAig_rec( pNew, pRtm, pObjRtm, pLatches );
+    // create POs
+    Rtm_ManForEachPo( pRtm, pObjRtm, i )
+        Aig_ObjCreateCo( pNew, (Aig_Obj_t *)pObjRtm->pCopy );
+    // connect latches 
+    Rtm_ManForEachObj( pRtm, pObjRtm, i )
+    Rtm_ObjForEachFaninEdge( pObjRtm, pEdge, k )
+    {
+        if ( pEdge->nLats == 0 )
+            continue;
+        pObjNew = (Aig_Obj_t *)Rtm_ObjFanin( pObjRtm, k )->pCopy;
+        for ( m = 0; m < (int)pEdge->nLats; m++ )
+        {
+            Val = Rtm_ObjGetOne( pRtm, pEdge, pEdge->nLats - 1 - m );
+            assert( Val == RTM_VAL_ZERO || Val == RTM_VAL_ONE || Val == RTM_VAL_VOID );
+            pObjNew = Aig_NotCond( pObjNew, Val == RTM_VAL_ONE );
+            Aig_ObjCreateCo( pNew, pObjNew );
+            pObjNew = Aig_ManCi( pNew, pLatches[2*pObjRtm->Id + k] + m );
+            pObjNew = Aig_NotCond( pObjNew, Val == RTM_VAL_ONE );
+        }
+//        assert( Aig_Regular(pObjNew)->nRefs > 0 );
+    }
+    ABC_FREE( pLatches );
+    Aig_ManSetRegNum( pNew, nLatches );
+    // remove useless nodes
+    Aig_ManCleanup( pNew );
+    if ( !Aig_ManCheck( pNew ) )
+        printf( "Rtm_ManToAig: The network check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs forward retiming with the given limit on depth.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Rtm_ManRetime( Aig_Man_t * p, int fForward, int nStepsMax, int fVerbose )
+{
+    Vec_Ptr_t * vQueue;
+    Aig_Man_t * pNew;
+    Rtm_Man_t * pRtm;
+    Rtm_Obj_t * pObj, * pNext;
+    Aig_Obj_t * pObjAig;
+    int i, k, nAutos, Degree, DegreeMax = 0; 
+    abctime clk;
+
+    // create the retiming manager
+clk = Abc_Clock();
+    pRtm = Rtm_ManFromAig( p );
+    // set registers
+    Aig_ManForEachLoSeq( p, pObjAig, i )
+        Rtm_ObjAddFirst( pRtm, Rtm_ObjEdge((Rtm_Obj_t *)pObjAig->pData, 0), fForward? RTM_VAL_ZERO : RTM_VAL_VOID );
+    // detect and mark the autonomous components
+    if ( fForward )
+        nAutos = Rtm_ManMarkAutoFwd( pRtm );
+    else
+        nAutos = Rtm_ManMarkAutoBwd( pRtm );
+    if ( fVerbose )
+    {
+        printf( "Detected %d autonomous objects. ", nAutos );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+
+    // set the current retiming number
+    Rtm_ManForEachObj( pRtm, pObj, i )
+    {
+        assert( pObj->nFanins == pObj->Num );
+        assert( pObj->nFanouts == pObj->Temp );
+        pObj->Num = 0;
+    }
+
+clk = Abc_Clock();
+    // put the LOs on the queue
+    vQueue = Vec_PtrAlloc( 1000 );
+    if ( fForward )
+    {
+        Aig_ManForEachLoSeq( p, pObjAig, i )
+        {
+            pObj = (Rtm_Obj_t *)pObjAig->pData;
+            if ( pObj->fAuto )
+                continue;
+            pObj->fMark = 1;
+            Vec_PtrPush( vQueue, pObj );
+        }
+    }
+    else
+    {
+        Aig_ManForEachLiSeq( p, pObjAig, i )
+        {
+            pObj = (Rtm_Obj_t *)pObjAig->pData;
+            if ( pObj->fAuto )
+                continue;
+            pObj->fMark = 1;
+            Vec_PtrPush( vQueue, pObj );
+        }
+    }
+    // perform retiming 
+    DegreeMax = 0;
+    Vec_PtrForEachEntry( Rtm_Obj_t *, vQueue, pObj, i )
+    {
+        pObj->fMark = 0;
+        // retime the node 
+        if ( fForward )
+        {
+            Rtm_ObjRetimeFwd( pRtm, pObj );
+            // check if its fanouts should be retimed
+            Rtm_ObjForEachFanout( pObj, pNext, k )
+            {
+                if ( pNext->fMark ) // skip aleady scheduled
+                    continue;
+                if ( pNext->Type ) // skip POs
+                    continue;
+                if ( !Rtm_ObjCheckRetimeFwd( pNext ) ) // skip non-retimable
+                    continue;
+                Degree = Rtm_ObjGetDegreeFwd( pNext );
+                DegreeMax = Abc_MaxInt( DegreeMax, Degree );
+                if ( Degree > nStepsMax ) // skip nodes with high degree
+                    continue;
+                pNext->fMark = 1;
+                pNext->Num = Degree;
+                Vec_PtrPush( vQueue, pNext );
+            }
+        }
+        else
+        {
+            Rtm_ObjRetimeBwd( pRtm, pObj );
+            // check if its fanouts should be retimed
+            Rtm_ObjForEachFanin( pObj, pNext, k )
+            {
+                if ( pNext->fMark ) // skip aleady scheduled
+                    continue;
+                if ( pNext->nFanins == 0 ) // skip PIs
+                    continue;
+                if ( !Rtm_ObjCheckRetimeBwd( pNext ) ) // skip non-retimable
+                    continue;
+                Degree = Rtm_ObjGetDegreeBwd( pNext );
+                DegreeMax = Abc_MaxInt( DegreeMax, Degree );
+                if ( Degree > nStepsMax ) // skip nodes with high degree
+                    continue;
+                pNext->fMark = 1;
+                pNext->Num = Degree;
+                Vec_PtrPush( vQueue, pNext );
+            }
+        }
+    }
+
+    if ( fVerbose )
+    {
+        printf( "Performed %d %s latch moves of max depth %d and max latch count %d.\n", 
+            Vec_PtrSize(vQueue), fForward? "fwd":"bwd", DegreeMax, Rtm_ManLatchMax(pRtm) );
+        printf( "Memory usage = %d.  ", pRtm->nExtraCur );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    Vec_PtrFree( vQueue );
+
+    // get the new manager
+    pNew = Rtm_ManToAig( pRtm );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Rtm_ManFree( pRtm );
+    // group the registers
+clk = Abc_Clock();
+    pNew = Aig_ManReduceLaches( pNew, fVerbose );
+    if ( fVerbose )
+    {
+        ABC_PRT( "Register sharing time", Abc_Clock() - clk );
+    }
+    return pNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigRetF.c b/abc-build/src/aig/aig/aigRetF.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigRetF.c
@@ -0,0 +1,214 @@
+/**CFile****************************************************************
+
+  FileName    [aigRetF.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Retiming frontier.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigRetF.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Mark the nodes reachable from the PIs in the reverse order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManRetimeMark_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    if ( pObj->fMarkB )
+        return 1;
+    if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) )
+        return 0;
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return pObj->fMarkB;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Aig_ManRetimeMark_rec( p, Aig_ObjFanin0(pObj) ) )
+        return pObj->fMarkB = 1;
+    if ( Aig_ObjIsNode(pObj) && Aig_ManRetimeMark_rec( p, Aig_ObjFanin1(pObj) ) )
+        return pObj->fMarkB = 1;
+    assert( pObj->fMarkB == 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Mark the nodes reachable from the true PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManRetimeMark( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int fChange, i;
+    // mark the PIs
+    Aig_ManForEachObj( p, pObj, i )
+        assert( pObj->fMarkB == 0 );
+    Aig_ManForEachPiSeq( p, pObj, i )
+        pObj->fMarkB = 1;
+    // map registers into each other
+    Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+    {
+        assert( pObjLo->pNext == NULL );
+        assert( pObjLi->pNext == NULL );
+        pObjLo->pNext = pObjLi;
+        pObjLi->pNext = pObjLo;
+    }
+    // iterativively mark the logic reachable from PIs
+    fChange = 1;
+    while ( fChange )
+    {
+        fChange = 0;
+        Aig_ManIncrementTravId( p );
+        Aig_ManForEachCo( p, pObj, i )
+        {
+            if ( pObj->fMarkB )
+                continue;
+            if ( Aig_ManRetimeMark_rec( p, pObj ) )
+            {
+                if ( pObj->pNext )
+                    pObj->pNext->fMarkB = 1;
+                fChange = 1;
+            }
+        }
+    }
+    // clean register mapping
+    Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+        pObjLo->pNext = pObjLi->pNext = NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs forward retiming.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManRetimeFrontier( Aig_Man_t * p, int nStepsMax )
+{
+    Aig_Obj_t * pObj, * pObjNew, * pObjLo, * pObjLo0, * pObjLo1, * pObjLi, * pObjLi0, * pObjLi1;//, * pObjLi0_, * pObjLi1_, * pObjLi0__, * pObjLi1__;
+    int i, Counter, fCompl, fChange;
+    assert( Aig_ManRegNum(p) > 0 );
+    // remove structural hashing table
+    Aig_TableClear( p );
+    // mark the retimable nodes
+    Aig_ManRetimeMark( p );
+    // mark the register outputs
+    Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+    {
+        pObjLo->fMarkA = 1;
+        pObjLo->pNext = pObjLi;
+        pObjLi->pNext = pObjLo;
+    }
+    // go through the nodes and find retimable ones
+    Counter = 0;
+    fChange = 1;
+    while ( fChange )
+    {
+        fChange = 0;
+        Aig_ManForEachNode( p, pObj, i )
+        {
+            if ( !pObj->fMarkB )
+                continue;
+            if ( Aig_ObjIsBuf(pObj) )
+                continue;
+            // get the real inputs of the node (skipping the buffers)
+            pObjLo0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
+            pObjLo1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) );
+            if ( !Aig_Regular(pObjLo0)->fMarkA || !Aig_Regular(pObjLo1)->fMarkA )
+                continue;
+            // remember complemented attribute
+            fCompl = Aig_IsComplement(pObjLo0) & Aig_IsComplement(pObjLo1);
+            // get the register inputs
+//            pObjLi0_ = Aig_Regular(pObjLo0)->pNext;
+//            pObjLi1_ = Aig_Regular(pObjLo1)->pNext;
+//            pObjLi0__ = Aig_ObjChild0(Aig_Regular(pObjLo0)->pNext);
+//            pObjLi1__ = Aig_ObjChild0(Aig_Regular(pObjLo1)->pNext);
+            pObjLi0 = Aig_NotCond( Aig_ObjChild0(Aig_Regular(pObjLo0)->pNext), Aig_IsComplement(pObjLo0) );
+            pObjLi1 = Aig_NotCond( Aig_ObjChild0(Aig_Regular(pObjLo1)->pNext), Aig_IsComplement(pObjLo1) );
+            // create new node
+            pObjNew = Aig_And( p, pObjLi0, pObjLi1 );
+            pObjNew->fMarkB = 1;
+            // create new register
+            pObjLo = Aig_ObjCreateCi(p);
+            pObjLo->fMarkA = 1;
+            pObjLi = Aig_ObjCreateCo( p, Aig_NotCond(pObjNew, fCompl) );
+            p->nRegs++;
+            pObjLo->pNext = pObjLi;
+            pObjLi->pNext = pObjLo;
+            // add the buffer
+            Aig_ObjDisconnect( p, pObj );
+            pObj->Type = AIG_OBJ_BUF;
+            p->nObjs[AIG_OBJ_AND]--;
+            p->nObjs[AIG_OBJ_BUF]++;
+            Aig_ObjConnect( p, pObj, Aig_NotCond(pObjLo, fCompl), NULL );
+            // create HAIG if defined
+            // mark the change
+            fChange = 1;
+            // check the limit
+            if ( ++Counter >= nStepsMax )
+            {
+                fChange = 0;
+                break;
+            }
+        }
+    }
+    // clean the markings
+    Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+    {
+        pObjLo->fMarkA = 0;
+        pObjLo->pNext = pObjLi->pNext = NULL;
+    }
+    Aig_ManForEachObj( p, pObj, i )
+        pObj->fMarkB = 0;
+    // remove useless registers
+    Aig_ManSeqCleanup( p );
+    // rehash the nodes
+    return Aig_ManDupOrdered( p ); 
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigScl.c b/abc-build/src/aig/aig/aigScl.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigScl.c
@@ -0,0 +1,708 @@
+/**CFile****************************************************************
+
+  FileName    [aigScl.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Sequential cleanup.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigScl.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Remaps the manager.]
+
+  Description [Map in the array specifies for each CI node the node that
+  should be used after remapping.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManRemap( Aig_Man_t * p, Vec_Ptr_t * vMap )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjMapped;
+    int i, nTruePis;
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nAsserts = p->nAsserts;
+    pNew->nConstrs = p->nConstrs;
+    pNew->nBarBufs = p->nBarBufs;
+    assert( p->vFlopNums == NULL || Vec_IntSize(p->vFlopNums) == p->nRegs );
+    if ( p->vFlopNums )
+        pNew->vFlopNums = Vec_IntDup( p->vFlopNums );
+    if ( p->vFlopReprs )
+        pNew->vFlopReprs = Vec_IntDup( p->vFlopReprs );
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCi(pNew);
+    // implement the mapping
+    nTruePis = Aig_ManCiNum(p)-Aig_ManRegNum(p);
+    if ( p->vFlopReprs )
+    {
+        Aig_ManForEachLoSeq( p, pObj, i )
+            pObj->pNext = (Aig_Obj_t *)(long)Vec_IntEntry( p->vFlopNums, i-nTruePis );
+    }
+    Aig_ManForEachCi( p, pObj, i )
+    {
+        pObjMapped = (Aig_Obj_t *)Vec_PtrEntry( vMap, i );
+        pObj->pData = Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pObjMapped)->pData, Aig_IsComplement(pObjMapped) );
+        if ( pNew->vFlopReprs && i >= nTruePis && pObj != pObjMapped )
+        {
+            Vec_IntPush( pNew->vFlopReprs, Aig_ObjCioId(pObj) );
+            if ( Aig_ObjIsConst1( Aig_Regular(pObjMapped) ) )
+                Vec_IntPush( pNew->vFlopReprs, -1 );
+            else
+            {
+                assert( !Aig_IsComplement(pObjMapped) );
+                assert( Aig_ObjIsCi(pObjMapped) );
+                assert( Aig_ObjCioId(pObj) != Aig_ObjCioId(pObjMapped) );
+                Vec_IntPush( pNew->vFlopReprs, Aig_ObjCioId(pObjMapped) );
+            }
+        }
+    }
+    if ( p->vFlopReprs )
+    {
+        Aig_ManForEachLoSeq( p, pObj, i )
+            pObj->pNext = NULL;
+    }
+    // duplicate internal nodes
+    Aig_ManForEachObj( p, pObj, i )
+        if ( Aig_ObjIsBuf(pObj) )
+            pObj->pData = Aig_ObjChild0Copy(pObj);
+        else if ( Aig_ObjIsNode(pObj) )
+            pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // add the POs
+    Aig_ManForEachCo( p, pObj, i )
+        Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    assert( Aig_ManNodeNum(p) >= Aig_ManNodeNum(pNew) );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // check the resulting network
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManRemap(): The check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of dangling nodes removed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManSeqCleanup_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    // collect latch input corresponding to unmarked PI (latch output)
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        Vec_PtrPush( vNodes, pObj->pNext );
+        return;
+    }
+    if ( Aig_ObjIsCo(pObj) || Aig_ObjIsBuf(pObj) )
+    {
+        Aig_ManSeqCleanup_rec( p, Aig_ObjFanin0(pObj), vNodes );
+        return;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    Aig_ManSeqCleanup_rec( p, Aig_ObjFanin0(pObj), vNodes );
+    Aig_ManSeqCleanup_rec( p, Aig_ObjFanin1(pObj), vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of dangling nodes removed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManSeqCleanup( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vNodes, * vCis, * vCos;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i, nTruePis, nTruePos;
+//    assert( Aig_ManBufNum(p) == 0 );
+
+    // mark the PIs
+    Aig_ManIncrementTravId( p );
+    Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
+    Aig_ManForEachPiSeq( p, pObj, i )
+        Aig_ObjSetTravIdCurrent( p, pObj );
+
+    // prepare to collect nodes reachable from POs
+    vNodes = Vec_PtrAlloc( 100 );
+    Aig_ManForEachPoSeq( p, pObj, i )
+        Vec_PtrPush( vNodes, pObj );
+
+    // remember latch inputs in latch outputs
+    Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+        pObjLo->pNext = pObjLi;
+    // mark the nodes reachable from these nodes
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        Aig_ManSeqCleanup_rec( p, pObj, vNodes );
+    assert( Vec_PtrSize(vNodes) <= Aig_ManCoNum(p) );
+    // clean latch output pointers
+    Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+        pObjLo->pNext = NULL;
+
+    // if some latches are removed, update PIs/POs
+    if ( Vec_PtrSize(vNodes) < Aig_ManCoNum(p) )
+    {
+        if ( p->vFlopNums )
+        {
+            int nTruePos = Aig_ManCoNum(p)-Aig_ManRegNum(p);
+            int iNum, k = 0;
+            Aig_ManForEachCo( p, pObj, i )
+                if ( i >= nTruePos && Aig_ObjIsTravIdCurrent(p, pObj) )
+                {
+                    iNum = Vec_IntEntry( p->vFlopNums, i - nTruePos );
+                    Vec_IntWriteEntry( p->vFlopNums, k++, iNum );
+                }
+            assert( k == Vec_PtrSize(vNodes) - nTruePos );
+            Vec_IntShrink( p->vFlopNums, k );
+        }
+        // collect new CIs/COs
+        vCis = Vec_PtrAlloc( Aig_ManCiNum(p) );
+        Aig_ManForEachCi( p, pObj, i )
+            if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+                Vec_PtrPush( vCis, pObj );
+            else
+            {
+                Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL );
+//                Aig_ManRecycleMemory( p, pObj );
+            }
+        vCos = Vec_PtrAlloc( Aig_ManCoNum(p) );
+        Aig_ManForEachCo( p, pObj, i )
+            if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+                Vec_PtrPush( vCos, pObj );
+            else
+            {
+                Aig_ObjDisconnect( p, pObj );
+                Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL );
+//                Aig_ManRecycleMemory( p, pObj );
+            }
+        // remember the number of true PIs/POs
+        nTruePis = Aig_ManCiNum(p) - Aig_ManRegNum(p);
+        nTruePos = Aig_ManCoNum(p) - Aig_ManRegNum(p);
+        // set the new number of registers
+        p->nRegs -= Aig_ManCoNum(p) - Vec_PtrSize(vNodes);
+        // create new PIs/POs
+        assert( Vec_PtrSize(vCis) == nTruePis + p->nRegs );
+        assert( Vec_PtrSize(vCos) == nTruePos + p->nRegs );
+        Vec_PtrFree( p->vCis );    p->vCis = vCis;
+        Vec_PtrFree( p->vCos );    p->vCos = vCos;
+        p->nObjs[AIG_OBJ_CI] = Vec_PtrSize( p->vCis );
+        p->nObjs[AIG_OBJ_CO] = Vec_PtrSize( p->vCos );
+                
+    }
+    Vec_PtrFree( vNodes );
+    p->nTruePis = Aig_ManCiNum(p) - Aig_ManRegNum(p); 
+    p->nTruePos = Aig_ManCoNum(p) - Aig_ManRegNum(p); 
+    Aig_ManSetCioIds( p );
+    // remove dangling nodes
+    return Aig_ManCleanup( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of dangling nodes removed.]
+
+  Description [This cleanup procedure is different in that 
+  it removes logic but does not remove the dangling latches.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManSeqCleanupBasic( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i;
+//    assert( Aig_ManBufNum(p) == 0 );
+
+    // mark the PIs
+    Aig_ManIncrementTravId( p );
+    Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
+    Aig_ManForEachPiSeq( p, pObj, i )
+        Aig_ObjSetTravIdCurrent( p, pObj );
+
+    // prepare to collect nodes reachable from POs
+    vNodes = Vec_PtrAlloc( 100 );
+    Aig_ManForEachPoSeq( p, pObj, i )
+        Vec_PtrPush( vNodes, pObj );
+
+    // remember latch inputs in latch outputs
+    Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+        pObjLo->pNext = pObjLi;
+    // mark the nodes reachable from these nodes
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        Aig_ManSeqCleanup_rec( p, pObj, vNodes );
+    assert( Vec_PtrSize(vNodes) <= Aig_ManCoNum(p) );
+    // clean latch output pointers
+    Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+        pObjLo->pNext = NULL;
+
+    // if some latches are removed, update PIs/POs
+    if ( Vec_PtrSize(vNodes) < Aig_ManCoNum(p) )
+    {
+        // add constant drivers to the dangling latches
+        Aig_ManForEachCo( p, pObj, i )
+            if ( !Aig_ObjIsTravIdCurrent(p, pObj) )
+                Aig_ObjPatchFanin0( p, pObj, Aig_ManConst0(p) );
+    }
+    Vec_PtrFree( vNodes );
+    // remove dangling nodes
+    return Aig_ManCleanup( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of dangling nodes removed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManCountMergeRegs( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pFanin;
+    int i, Counter = 0, Const0 = 0, Const1 = 0;
+    Aig_ManIncrementTravId( p );
+    Aig_ManForEachLiSeq( p, pObj, i )
+    {
+        pFanin = Aig_ObjFanin0(pObj);
+        if ( Aig_ObjIsConst1(pFanin) )
+        {
+            if ( Aig_ObjFaninC0(pObj) )
+                Const0++;
+            else
+                Const1++;
+        }
+        if ( Aig_ObjIsTravIdCurrent(p, pFanin) )
+            continue;
+        Aig_ObjSetTravIdCurrent(p, pFanin);
+        Counter++;
+    }
+    printf( "Regs = %d. Fanins = %d. Const0 = %d. Const1 = %d.\n", 
+        Aig_ManRegNum(p), Counter, Const0, Const1 );
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks how many latches can be reduced.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManReduceLachesCount( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pFanin;
+    int i, Counter = 0, Diffs = 0;
+    assert( Aig_ManRegNum(p) > 0 );
+    Aig_ManForEachObj( p, pObj, i )
+        assert( !pObj->fMarkA && !pObj->fMarkB );
+    Aig_ManForEachLiSeq( p, pObj, i )
+    {
+        pFanin = Aig_ObjFanin0(pObj);
+        if ( Aig_ObjFaninC0(pObj) )
+        {
+            if ( pFanin->fMarkB )
+                Counter++;
+            else
+                pFanin->fMarkB = 1;
+        }
+        else
+        {
+            if ( pFanin->fMarkA )
+                Counter++;
+            else
+                pFanin->fMarkA = 1;
+        }
+    }
+    // count fanins that have both attributes
+    Aig_ManForEachLiSeq( p, pObj, i )
+    {
+        pFanin = Aig_ObjFanin0(pObj);
+        Diffs += pFanin->fMarkA && pFanin->fMarkB;
+        pFanin->fMarkA = pFanin->fMarkB = 0;
+    }
+//    printf( "Diffs = %d.\n", Diffs );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces the latches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManReduceLachesOnce( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vMap;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pFanin;
+    int * pMapping, i;
+    // start mapping by adding the true PIs
+    vMap = Vec_PtrAlloc( Aig_ManCiNum(p) );
+    Aig_ManForEachPiSeq( p, pObj, i )
+        Vec_PtrPush( vMap, pObj );
+    // create mapping of fanin nodes into the corresponding latch outputs
+    pMapping = ABC_FALLOC( int, 2 * Aig_ManObjNumMax(p) );
+    Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+    {
+        pFanin = Aig_ObjFanin0(pObjLi);
+        if ( Aig_ObjFaninC0(pObjLi) )
+        {
+            if ( pFanin->fMarkB )
+            {
+                Vec_PtrPush( vMap, Aig_ManLo(p, pMapping[2*pFanin->Id + 1]) );
+            }
+            else
+            {
+                pFanin->fMarkB = 1;
+                pMapping[2*pFanin->Id + 1] = i;
+                Vec_PtrPush( vMap, pObjLo );
+            }
+        }
+        else
+        {
+            if ( pFanin->fMarkA )
+            {
+                Vec_PtrPush( vMap, Aig_ManLo(p, pMapping[2*pFanin->Id]) );
+            }
+            else
+            {
+                pFanin->fMarkA = 1;
+                pMapping[2*pFanin->Id] = i;
+                Vec_PtrPush( vMap, pObjLo );
+            }
+        }
+    }
+    ABC_FREE( pMapping );
+    Aig_ManForEachLiSeq( p, pObj, i )
+    {
+        pFanin = Aig_ObjFanin0(pObj);
+        pFanin->fMarkA = pFanin->fMarkB = 0;
+    }
+    return vMap;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces the latches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManReduceLaches( Aig_Man_t * p, int fVerbose )
+{
+    Aig_Man_t * pTemp;
+    Vec_Ptr_t * vMap;
+    int nSaved, nCur;
+    if ( fVerbose )
+        printf( "Performing combinational register sweep:\n" );
+    for ( nSaved = 0; (nCur = Aig_ManReduceLachesCount(p)); nSaved += nCur )
+    {
+//        printf( "Reducible = %d\n", nCur );
+        vMap = Aig_ManReduceLachesOnce( p );
+        p = Aig_ManRemap( pTemp = p, vMap );
+        Vec_PtrFree( vMap );
+        Aig_ManSeqCleanup( p );
+        if ( fVerbose )
+            Aig_ManReportImprovement( pTemp, p );
+        Aig_ManStop( pTemp );
+        if ( p->nRegs == 0 )
+            break;
+    }
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes strongly connected components of registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManComputeSccs( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vSupports, * vMatrix, * vMatrix2;
+    Vec_Int_t * vSupp, * vSupp2, * vComp;
+    char * pVarsTot;
+    int i, k, m, iOut, iIn, nComps;
+    if ( Aig_ManRegNum(p) == 0 )
+    {
+        printf( "The network is combinational.\n" );
+        return;
+    }
+    // get structural supports for each output
+    vSupports = Aig_ManSupports( p );
+    // transforms the supports into the latch dependency matrix
+    vMatrix = Vec_PtrStart( Aig_ManRegNum(p) );
+    Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vSupp, i )
+    {
+        // skip true POs
+        iOut = Vec_IntPop( vSupp );
+        iOut -= Aig_ManCoNum(p) - Aig_ManRegNum(p);
+        if ( iOut < 0 )
+            continue;
+        // remove PIs
+        m = 0;
+        Vec_IntForEachEntry( vSupp, iIn, k )
+        {
+            iIn -= Aig_ManCiNum(p) - Aig_ManRegNum(p);
+            if ( iIn < 0 )
+                continue;
+            assert( iIn < Aig_ManRegNum(p) );
+            Vec_IntWriteEntry( vSupp, m++, iIn );
+        }
+        Vec_IntShrink( vSupp, m );
+        // store support in the matrix
+        assert( iOut < Aig_ManRegNum(p) );
+        Vec_PtrWriteEntry( vMatrix, iOut, vSupp );
+    }
+    // create the reverse matrix
+    vMatrix2 = Vec_PtrAlloc( Aig_ManRegNum(p) );
+    for ( i = 0; i < Aig_ManRegNum(p); i++ )
+        Vec_PtrPush( vMatrix2, Vec_IntAlloc(8) );
+    Vec_PtrForEachEntry( Vec_Int_t *, vMatrix, vSupp, i )
+    {
+        Vec_IntForEachEntry( vSupp, iIn, k )
+        {
+            vSupp2 = (Vec_Int_t *)Vec_PtrEntry( vMatrix2, iIn );
+            Vec_IntPush( vSupp2, i );
+        }
+    } 
+
+    // detect strongly connected components
+    vComp = Vec_IntAlloc( Aig_ManRegNum(p) );
+    pVarsTot = ABC_ALLOC( char, Aig_ManRegNum(p) );
+    memset( pVarsTot, 0, Aig_ManRegNum(p) * sizeof(char) );
+    for ( nComps = 0; ; nComps++ )
+    {
+        Vec_IntClear( vComp );
+        // get the first support
+        for ( iOut = 0; iOut < Aig_ManRegNum(p); iOut++ )
+            if ( pVarsTot[iOut] == 0 )
+                break;
+        if ( iOut == Aig_ManRegNum(p) )
+            break;
+        pVarsTot[iOut] = 1;
+        Vec_IntPush( vComp, iOut );
+        Vec_IntForEachEntry( vComp, iOut, i )
+        {
+            vSupp = (Vec_Int_t *)Vec_PtrEntry( vMatrix, iOut );
+            Vec_IntForEachEntry( vSupp, iIn, k )
+            {
+                if ( pVarsTot[iIn] )
+                    continue;
+                pVarsTot[iIn] = 1;
+                Vec_IntPush( vComp, iIn );
+            }
+            vSupp2 = (Vec_Int_t *)Vec_PtrEntry( vMatrix2, iOut );
+            Vec_IntForEachEntry( vSupp2, iIn, k )
+            {
+                if ( pVarsTot[iIn] )
+                    continue;
+                pVarsTot[iIn] = 1;
+                Vec_IntPush( vComp, iIn );
+            }
+        }
+        if ( Vec_IntSize(vComp) == Aig_ManRegNum(p) )
+        {
+            printf( "There is only one SCC of registers in this network.\n" );
+            break;
+        }
+        printf( "SCC #%d contains %5d registers.\n", nComps+1, Vec_IntSize(vComp) );
+    }
+    ABC_FREE( pVarsTot );
+    Vec_IntFree( vComp );
+    Vec_PtrFree( vMatrix );
+    Vec_VecFree( (Vec_Vec_t *)vMatrix2 );
+    Vec_VecFree( (Vec_Vec_t *)vSupports );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs partitioned register sweep.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManSclPart( Aig_Man_t * pAig, int fLatchConst, int fLatchEqual, int fVerbose ) 
+{
+    Vec_Ptr_t * vResult;
+    Vec_Int_t * vPart;
+    int i, nCountPis, nCountRegs;
+    int * pMapBack;
+    Aig_Man_t * pTemp, * pNew;
+    int nClasses;
+
+    if ( pAig->vClockDoms ) 
+    {
+        vResult = Vec_PtrAlloc( 100 );
+        Vec_PtrForEachEntry( Vec_Int_t *, (Vec_Ptr_t *)pAig->vClockDoms, vPart, i )
+            Vec_PtrPush( vResult, Vec_IntDup(vPart) );
+    } 
+    else
+        vResult = Aig_ManRegPartitionSimple( pAig, 0, 0 );
+
+    Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) );
+    Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i ) 
+    {
+        pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, &pMapBack );
+        Aig_ManSetRegNum( pTemp, pTemp->nRegs );
+        if (nCountPis>0) 
+        {
+            pNew = Aig_ManScl( pTemp, fLatchConst, fLatchEqual, 0, -1, -1, fVerbose, 0 );
+            nClasses = Aig_TransferMappedClasses( pAig, pTemp, pMapBack );
+            if ( fVerbose )
+                printf( "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. It = %3d. Cl = %5d\n",
+                        i, Vec_IntSize(vPart), Aig_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp), 0, nClasses );
+            Aig_ManStop( pNew );
+        }
+        Aig_ManStop( pTemp );
+        ABC_FREE( pMapBack );
+    }
+    pNew = Aig_ManDupRepr( pAig, 0 );
+    Aig_ManSeqCleanup( pNew );
+    Vec_VecFree( (Vec_Vec_t*)vResult );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManScl( Aig_Man_t * pAig, int fLatchConst, int fLatchEqual, int fUseMvSweep, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose )
+{
+    extern void Saig_ManReportUselessRegisters( Aig_Man_t * pAig );
+    extern int Saig_ManReportComplements( Aig_Man_t * p );
+
+    Aig_Man_t * pAigInit, * pAigNew;
+    Aig_Obj_t * pFlop1, * pFlop2;
+    int i, Entry1, Entry2, nTruePis;//, nRegs;
+
+    if ( pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0 )
+        return Aig_ManSclPart( pAig, fLatchConst, fLatchEqual, fVerbose);
+
+    // store the original AIG
+    assert( pAig->vFlopNums == NULL );
+    pAigInit = pAig;
+    pAig = Aig_ManDupSimple( pAig );
+    // create storage for latch numbers
+    pAig->vFlopNums = Vec_IntStartNatural( pAig->nRegs );
+    pAig->vFlopReprs = Vec_IntAlloc( 100 );
+    Aig_ManSeqCleanup( pAig );
+    if ( fLatchConst && pAig->nRegs )
+        pAig = Aig_ManConstReduce( pAig, fUseMvSweep, nFramesSymb, nFramesSatur, fVerbose, fVeryVerbose );
+    if ( fLatchEqual && pAig->nRegs )
+        pAig = Aig_ManReduceLaches( pAig, fVerbose );
+    // translate pairs into reprs
+    nTruePis = Aig_ManCiNum(pAigInit)-Aig_ManRegNum(pAigInit);
+    Aig_ManReprStart( pAigInit, Aig_ManObjNumMax(pAigInit) );
+    Vec_IntForEachEntry( pAig->vFlopReprs, Entry1, i )
+    {
+        Entry2 = Vec_IntEntry( pAig->vFlopReprs, ++i ); 
+        pFlop1 = Aig_ManCi( pAigInit, nTruePis + Entry1 );
+        pFlop2 = (Entry2 == -1)? Aig_ManConst1(pAigInit) : Aig_ManCi( pAigInit, nTruePis + Entry2 );
+        assert( pFlop1 != pFlop2 );
+        if ( pFlop1->Id > pFlop2->Id )
+            pAigInit->pReprs[pFlop1->Id] = pFlop2;
+        else
+            pAigInit->pReprs[pFlop2->Id] = pFlop1;
+    }
+    Aig_ManStop( pAig );
+//    Aig_ManSeqCleanup( pAigInit );
+    pAigNew = Aig_ManDupRepr( pAigInit, 0 );
+    Aig_ManSeqCleanup( pAigNew );
+
+//    Saig_ManReportUselessRegisters( pAigNew );
+    if ( Aig_ManRegNum(pAigNew) == 0 )
+        return pAigNew;
+//    nRegs = Saig_ManReportComplements( pAigNew );
+//    if ( nRegs ) 
+//    printf( "The number of complemented registers = %d.\n", nRegs );
+    return pAigNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigShow.c b/abc-build/src/aig/aig/aigShow.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigShow.c
@@ -0,0 +1,369 @@
+/**CFile****************************************************************
+
+  FileName    [ivyShow.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Visualization of HAIG.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyShow.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the graph structure of AIG for DOT.]
+
+  Description [Useful for graph visualization using tools such as GraphViz: 
+  http://www.graphviz.org/]
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_WriteDotAig( Aig_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold )
+{
+    FILE * pFile;
+    Aig_Obj_t * pNode;//, * pTemp, * pPrev;
+    int LevelMax, Prev, Level, i;
+
+    if ( Aig_ManNodeNum(pMan) > 200 )
+    {
+        fprintf( stdout, "Cannot visualize AIG with more than 200 nodes.\n" );
+        return;
+    }
+    if ( (pFile = fopen( pFileName, "w" )) == NULL )
+    {
+        fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName );
+        return;
+    }
+
+    // mark the nodes
+    if ( vBold )
+        Vec_PtrForEachEntry( Aig_Obj_t *, vBold, pNode, i )
+            pNode->fMarkB = 1;
+
+    // compute levels
+//    LevelMax = 1 + Aig_ManSetLevels( pMan, fHaig );
+    LevelMax = 1 + Aig_ManLevels( pMan );
+    Aig_ManForEachCo( pMan, pNode, i )
+        pNode->Level = LevelMax;
+
+    // write the DOT header
+    fprintf( pFile, "# %s\n",  "AIG structure generated by IVY package" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "digraph AIG {\n" );
+    fprintf( pFile, "size = \"7.5,10\";\n" );
+//  fprintf( pFile, "ranksep = 0.5;\n" );
+//  fprintf( pFile, "nodesep = 0.5;\n" );
+    fprintf( pFile, "center = true;\n" );
+//  fprintf( pFile, "orientation = landscape;\n" );
+//  fprintf( pFile, "edge [fontsize = 10];\n" );
+//  fprintf( pFile, "edge [dir = none];\n" );
+    fprintf( pFile, "edge [dir = back];\n" );
+    fprintf( pFile, "\n" );
+
+    // labels on the left of the picture
+    fprintf( pFile, "{\n" );
+    fprintf( pFile, "  node [shape = plaintext];\n" );
+    fprintf( pFile, "  edge [style = invis];\n" );
+    fprintf( pFile, "  LevelTitle1 [label=\"\"];\n" );
+    fprintf( pFile, "  LevelTitle2 [label=\"\"];\n" );
+    // generate node names with labels
+    for ( Level = LevelMax; Level >= 0; Level-- )
+    {
+        // the visible node name
+        fprintf( pFile, "  Level%d", Level );
+        fprintf( pFile, " [label = " );
+        // label name
+        fprintf( pFile, "\"" );
+        fprintf( pFile, "\"" );
+        fprintf( pFile, "];\n" );
+    }
+
+    // genetate the sequence of visible/invisible nodes to mark levels
+    fprintf( pFile, "  LevelTitle1 ->  LevelTitle2 ->" );
+    for ( Level = LevelMax; Level >= 0; Level-- )
+    {
+        // the visible node name
+        fprintf( pFile, "  Level%d",  Level );
+        // the connector
+        if ( Level != 0 )
+            fprintf( pFile, " ->" );
+        else
+            fprintf( pFile, ";" );
+    }
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    // generate title box on top
+    fprintf( pFile, "{\n" );
+    fprintf( pFile, "  rank = same;\n" );
+    fprintf( pFile, "  LevelTitle1;\n" );
+    fprintf( pFile, "  title1 [shape=plaintext,\n" );
+    fprintf( pFile, "          fontsize=20,\n" );
+    fprintf( pFile, "          fontname = \"Times-Roman\",\n" );
+    fprintf( pFile, "          label=\"" );
+    fprintf( pFile, "%s", "AIG structure visualized by ABC" );
+    fprintf( pFile, "\\n" );
+    fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" );
+//    fprintf( pFile, "Time was %s. ",  Extra_TimeStamp() );
+    fprintf( pFile, "\"\n" );
+    fprintf( pFile, "         ];\n" );
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    // generate statistics box
+    fprintf( pFile, "{\n" );
+    fprintf( pFile, "  rank = same;\n" );
+    fprintf( pFile, "  LevelTitle2;\n" );
+    fprintf( pFile, "  title2 [shape=plaintext,\n" );
+    fprintf( pFile, "          fontsize=18,\n" );
+    fprintf( pFile, "          fontname = \"Times-Roman\",\n" );
+    fprintf( pFile, "          label=\"" );
+    fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Aig_ManNodeNum(pMan), LevelMax );
+    fprintf( pFile, "\\n" );
+    fprintf( pFile, "\"\n" );
+    fprintf( pFile, "         ];\n" );
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    // generate the COs
+    fprintf( pFile, "{\n" );
+    fprintf( pFile, "  rank = same;\n" );
+    // the labeling node of this level
+    fprintf( pFile, "  Level%d;\n",  LevelMax );
+    // generate the CO nodes
+    Aig_ManForEachCo( pMan, pNode, i )
+    {
+/*
+        if ( fHaig || pNode->pEquiv == NULL )
+            fprintf( pFile, "  Node%d%s [label = \"%d%s\"", pNode->Id, 
+                (Aig_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":"") );
+        else
+            fprintf( pFile, "  Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, 
+                (Aig_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":""), 
+                    Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" );
+*/
+        fprintf( pFile, "  Node%d [label = \"%d\"", pNode->Id, pNode->Id ); 
+
+        fprintf( pFile, ", shape = %s", "invtriangle" );
+        fprintf( pFile, ", color = coral, fillcolor = coral" );
+        fprintf( pFile, "];\n" );
+    }
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    // generate nodes of each rank
+    for ( Level = LevelMax - 1; Level > 0; Level-- )
+    {
+        fprintf( pFile, "{\n" );
+        fprintf( pFile, "  rank = same;\n" );
+        // the labeling node of this level
+        fprintf( pFile, "  Level%d;\n",  Level );
+        Aig_ManForEachObj( pMan, pNode, i )
+        {
+            if ( (int)pNode->Level != Level )
+                continue;
+/*
+            if ( fHaig || pNode->pEquiv == NULL )
+                fprintf( pFile, "  Node%d [label = \"%d\"", pNode->Id, pNode->Id );
+            else 
+                fprintf( pFile, "  Node%d [label = \"%d(%d%s)\"", pNode->Id, pNode->Id, 
+                    Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" );
+*/
+            fprintf( pFile, "  Node%d [label = \"%d\"", pNode->Id, pNode->Id ); 
+
+            fprintf( pFile, ", shape = ellipse" );
+            if ( vBold && pNode->fMarkB )
+                fprintf( pFile, ", style = filled" );
+            fprintf( pFile, "];\n" );
+        }
+        fprintf( pFile, "}" );
+        fprintf( pFile, "\n" );
+        fprintf( pFile, "\n" );
+    }
+
+    // generate the CI nodes
+    fprintf( pFile, "{\n" );
+    fprintf( pFile, "  rank = same;\n" );
+    // the labeling node of this level
+    fprintf( pFile, "  Level%d;\n",  0 );
+    // generate constant node
+    if ( Aig_ObjRefs(Aig_ManConst1(pMan)) > 0 )
+    {
+        pNode = Aig_ManConst1(pMan);
+        // check if the costant node is present
+        fprintf( pFile, "  Node%d [label = \"Const1\"", pNode->Id );
+        fprintf( pFile, ", shape = ellipse" );
+        fprintf( pFile, ", color = coral, fillcolor = coral" );
+        fprintf( pFile, "];\n" );
+    }
+    // generate the CI nodes
+    Aig_ManForEachCi( pMan, pNode, i )
+    {
+/*
+        if ( fHaig || pNode->pEquiv == NULL )
+            fprintf( pFile, "  Node%d%s [label = \"%d%s\"", pNode->Id, 
+                (Aig_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_out":"") );
+        else
+            fprintf( pFile, "  Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, 
+                (Aig_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_out":""), 
+                    Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" );
+*/
+        fprintf( pFile, "  Node%d [label = \"%d\"", pNode->Id, pNode->Id ); 
+
+        fprintf( pFile, ", shape = %s", "triangle" );
+        fprintf( pFile, ", color = coral, fillcolor = coral" );
+        fprintf( pFile, "];\n" );
+    }
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    // generate invisible edges from the square down
+    fprintf( pFile, "title1 -> title2 [style = invis];\n" );
+    Aig_ManForEachCo( pMan, pNode, i )
+        fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id );
+    // generate invisible edges among the COs
+    Prev = -1;
+    Aig_ManForEachCo( pMan, pNode, i )
+    {
+        if ( i > 0 )
+            fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, pNode->Id );
+        Prev = pNode->Id;
+    }
+
+    // generate edges
+    Aig_ManForEachObj( pMan, pNode, i )
+    {
+        if ( !Aig_ObjIsNode(pNode) && !Aig_ObjIsCo(pNode) && !Aig_ObjIsBuf(pNode) )
+            continue;
+        // generate the edge from this node to the next
+        fprintf( pFile, "Node%d",  pNode->Id );
+        fprintf( pFile, " -> " );
+        fprintf( pFile, "Node%d",  Aig_ObjFaninId0(pNode) );
+        fprintf( pFile, " [" );
+        fprintf( pFile, "style = %s", Aig_ObjFaninC0(pNode)? "dotted" : "bold" );
+//        if ( Aig_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL0(pNode) > 0 )
+//        fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) );
+        fprintf( pFile, "]" );
+        fprintf( pFile, ";\n" );
+        if ( !Aig_ObjIsNode(pNode) )
+            continue;
+        // generate the edge from this node to the next
+        fprintf( pFile, "Node%d",  pNode->Id );
+        fprintf( pFile, " -> " );
+        fprintf( pFile, "Node%d",  Aig_ObjFaninId1(pNode) );
+        fprintf( pFile, " [" );
+        fprintf( pFile, "style = %s", Aig_ObjFaninC1(pNode)? "dotted" : "bold" );
+//        if ( Aig_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL1(pNode) > 0 )
+//        fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) );
+        fprintf( pFile, "]" );
+        fprintf( pFile, ";\n" );
+/*
+        // generate the edges between the equivalent nodes
+        if ( fHaig && pNode->pEquiv && Aig_ObjRefs(pNode) > 0 )
+        {
+            pPrev = pNode;
+            for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Aig_Regular(pTemp->pEquiv) )
+            {
+                fprintf( pFile, "Node%d",  pPrev->Id );
+                fprintf( pFile, " -> " );
+                fprintf( pFile, "Node%d",  pTemp->Id );
+                fprintf( pFile, " [style = %s]", Aig_IsComplement(pTemp->pEquiv)? "dotted" : "bold" );
+                fprintf( pFile, ";\n" );
+                pPrev = pTemp;
+            }
+            // connect the last node with the first
+            fprintf( pFile, "Node%d",  pPrev->Id );
+            fprintf( pFile, " -> " );
+            fprintf( pFile, "Node%d",  pNode->Id );
+            fprintf( pFile, " [style = %s]", Aig_IsComplement(pPrev->pEquiv)? "dotted" : "bold" );
+            fprintf( pFile, ";\n" );
+        }
+*/
+    }
+
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+    fclose( pFile );
+
+    // unmark nodes
+    if ( vBold )
+        Vec_PtrForEachEntry( Aig_Obj_t *, vBold, pNode, i )
+            pNode->fMarkB = 0;
+
+    Aig_ManForEachCo( pMan, pNode, i )
+        pNode->Level = Aig_ObjFanin0(pNode)->Level;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManShow( Aig_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold )
+{
+    extern void Abc_ShowFile( char * FileNameDot );
+    static int Counter = 0;
+    char FileNameDot[200];
+    FILE * pFile;
+    // create the file name
+//    Aig_ShowGetFileName( pMan->pName, FileNameDot );
+    sprintf( FileNameDot, "temp%02d.dot", Counter++ );
+    // check that the file can be opened
+    if ( (pFile = fopen( FileNameDot, "w" )) == NULL )
+    {
+        fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot );
+        return;
+    }
+    fclose( pFile );
+    // generate the file
+    Aig_WriteDotAig( pMan, FileNameDot, fHaig, vBold );
+    // visualize the file 
+    Abc_ShowFile( FileNameDot );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigSplit.c b/abc-build/src/aig/aig/aigSplit.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigSplit.c
@@ -0,0 +1,316 @@
+/**CFile****************************************************************
+
+  FileName    [aigSplit.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Splits the property output cone into a set of cofactor properties.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigSplit.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+#include "aig/saig/saig.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the node to MUXes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Aig_Man_t * pNew, st__table * tBdd2Node )
+{
+    Aig_Obj_t * pNode, * pNode0, * pNode1, * pNodeC;
+    assert( !Cudd_IsComplement(bFunc) );
+    if ( st__lookup( tBdd2Node, (char *)bFunc, (char **)&pNode ) )
+        return pNode;
+    // solve for the children nodes
+    pNode0 = Aig_NodeBddToMuxes_rec( dd, Cudd_Regular(cuddE(bFunc)), pNew, tBdd2Node );
+    pNode0 = Aig_NotCond( pNode0, Cudd_IsComplement(cuddE(bFunc)) );
+    pNode1 = Aig_NodeBddToMuxes_rec( dd, cuddT(bFunc), pNew, tBdd2Node );
+    if ( ! st__lookup( tBdd2Node, (char *)Cudd_bddIthVar(dd, bFunc->index), (char **)&pNodeC ) )
+        assert( 0 );
+    // create the MUX node
+    pNode = Aig_Mux( pNew, pNodeC, pNode1, pNode0 );
+    st__insert( tBdd2Node, (char *)bFunc, (char *)pNode );
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives AIG for the BDDs of the cofactors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManConvertBddsToAigs( Aig_Man_t * p, DdManager * dd, Vec_Ptr_t * vCofs )
+{
+    DdNode * bFunc;
+    st__table * tBdd2Node;
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManCleanData( p );
+    // generate AIG for BDD
+    pNew = Aig_ManStart( Aig_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    // create the table mapping BDD nodes into the ABC nodes
+    tBdd2Node = st__init_table( st__ptrcmp, st__ptrhash );
+    // add the constant and the elementary vars
+    st__insert( tBdd2Node, (char *)Cudd_ReadOne(dd), (char *)Aig_ManConst1(pNew) );
+    Aig_ManForEachCi( p, pObj, i )
+        st__insert( tBdd2Node, (char *)Cudd_bddIthVar(dd, i), (char *)pObj->pData );
+    // build primary outputs for the cofactors
+    Vec_PtrForEachEntry( DdNode *, vCofs, bFunc, i )
+    {
+        if ( bFunc == Cudd_ReadLogicZero(dd) )
+            continue;
+        pObj = Aig_NodeBddToMuxes_rec( dd, Cudd_Regular(bFunc), pNew, tBdd2Node );
+        pObj = Aig_NotCond( pObj, Cudd_IsComplement(bFunc) );
+        Aig_ObjCreateCo( pNew, pObj );
+    }
+    st__free_table( tBdd2Node );
+
+    // duplicate the rest of the AIG
+    // add the POs
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        if ( i == 0 )
+            continue;
+        Aig_ManDupSimpleDfs_rec( pNew, p, Aig_ObjFanin0(pObj) );
+        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    }
+    Aig_ManCleanup( pNew );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // check the resulting network
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManConvertBddsToAigs(): The check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of constraint candidates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Aig_ManBuildPoBdd_rec( Aig_Man_t * p, Aig_Obj_t * pObj, DdManager * dd )
+{
+    DdNode * bBdd0, * bBdd1;
+    if ( pObj->pData != NULL )
+        return (DdNode *)pObj->pData;
+    assert( Aig_ObjIsNode(pObj) );
+    bBdd0 = Aig_ManBuildPoBdd_rec( p, Aig_ObjFanin0(pObj), dd ); 
+    bBdd1 = Aig_ManBuildPoBdd_rec( p, Aig_ObjFanin1(pObj), dd ); 
+    bBdd0 = Cudd_NotCond( bBdd0, Aig_ObjFaninC0(pObj) );
+    bBdd1 = Cudd_NotCond( bBdd1, Aig_ObjFaninC1(pObj) );
+    pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 );  Cudd_Ref( (DdNode *)pObj->pData );
+    return (DdNode *)pObj->pData;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive BDDs for the cofactors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManCofactorBdds( Aig_Man_t * p, Vec_Ptr_t * vSubset, DdManager * dd, DdNode * bFunc )
+{
+    Vec_Ptr_t * vCofs;
+    DdNode * bCube, * bTemp, * bCof, ** pbVars;
+    int i;
+    vCofs = Vec_PtrAlloc( 100 );
+    pbVars = (DdNode **)Vec_PtrArray(vSubset);
+    for ( i = 0; i < (1 << Vec_PtrSize(vSubset)); i++ )
+    {
+        bCube = Extra_bddBitsToCube( dd, i, Vec_PtrSize(vSubset), pbVars, 1 );  Cudd_Ref( bCube );
+        bCof  = Cudd_Cofactor( dd, bFunc, bCube );        Cudd_Ref( bCof );
+        bCof  = Cudd_bddAnd( dd, bTemp = bCof, bCube );   Cudd_Ref( bCof );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bCube );
+        Vec_PtrPush( vCofs, bCof );
+    }
+    return vCofs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Construct BDDs for the primary output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdManager * Aig_ManBuildPoBdd( Aig_Man_t * p, DdNode ** pbFunc )
+{
+    DdManager * dd;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( Saig_ManPoNum(p) == 1 );
+    Aig_ManCleanData( p );
+    dd = Cudd_Init( Aig_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    Cudd_AutodynEnable( dd,  CUDD_REORDER_SYMM_SIFT );
+    pObj = Aig_ManConst1(p);
+    pObj->pData = Cudd_ReadOne(dd);  Cudd_Ref( (DdNode *)pObj->pData );
+    Aig_ManForEachCi( p, pObj, i )
+    {
+        pObj->pData = Cudd_bddIthVar(dd, i);  Cudd_Ref( (DdNode *)pObj->pData );
+    }
+    pObj = Aig_ManCo( p, 0 );
+    *pbFunc = Aig_ManBuildPoBdd_rec( p, Aig_ObjFanin0(pObj), dd );  Cudd_Ref( *pbFunc );
+    *pbFunc = Cudd_NotCond( *pbFunc, Aig_ObjFaninC0(pObj) );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( pObj->pData )
+            Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+    }
+    Cudd_ReduceHeap( dd,  CUDD_REORDER_SYMM_SIFT, 1 );
+    return dd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Randomly selects a random subset of inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManVecRandSubset( Vec_Ptr_t * vVec, int nVars )
+{
+    Vec_Ptr_t * vRes;
+    void * pEntry;
+    unsigned Rand; 
+    vRes = Vec_PtrDup(vVec);
+    while ( Vec_PtrSize(vRes) > nVars )
+    {
+        Rand   = Aig_ManRandom( 0 );
+        pEntry = Vec_PtrEntry( vRes, Rand % Vec_PtrSize(vRes) );
+        Vec_PtrRemove( vRes, pEntry );
+    }
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManSplit( Aig_Man_t * p, int nVars, int fVerbose )
+{
+    Aig_Man_t * pRes;
+    Aig_Obj_t * pNode;
+    DdNode * bFunc;
+    DdManager * dd;
+    Vec_Ptr_t * vSupp, * vSubs, * vCofs;
+    int i;
+    abctime clk = Abc_Clock();
+    if ( Saig_ManPoNum(p) != 1 )
+    {
+        printf( "Currently works only for one primary output.\n" );
+        return NULL;
+    }
+    if ( nVars < 1 )
+    {
+        printf( "The number of cofactoring variables should be a positive number.\n" );
+        return NULL;
+    }
+    if ( nVars > 16 )
+    {
+        printf( "The number of cofactoring variables should be less than 17.\n" );
+        return NULL;
+    }
+    vSupp = Aig_Support( p, Aig_ObjFanin0(Aig_ManCo(p,0)) );
+    if ( Vec_PtrSize(vSupp) == 0 )
+    {
+        printf( "Property output function is a constant.\n" );
+        Vec_PtrFree( vSupp );
+        return NULL;
+    }
+    dd    = Aig_ManBuildPoBdd( p, &bFunc ); // bFunc is referenced
+    if ( fVerbose )
+        printf( "Support =%5d.  BDD size =%6d.  ", Vec_PtrSize(vSupp), Cudd_DagSize(bFunc) );
+    vSubs = Aig_ManVecRandSubset( vSupp, nVars );
+    // replace nodes by their BDD variables
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSubs, pNode, i )
+        Vec_PtrWriteEntry( vSubs, i, pNode->pData );
+    // derive cofactors and functions
+    vCofs = Aig_ManCofactorBdds( p, vSubs, dd, bFunc );
+    pRes  = Aig_ManConvertBddsToAigs( p, dd, vCofs );
+    Vec_PtrFree( vSupp );
+    Vec_PtrFree( vSubs );
+    if ( fVerbose )
+        printf( "Created %d cofactors (out of %d).  ", Saig_ManPoNum(pRes), Vec_PtrSize(vCofs) );
+    if ( fVerbose )
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    // dereference
+    Cudd_RecursiveDeref( dd, bFunc );
+    Vec_PtrForEachEntry( DdNode *, vCofs, bFunc, i )
+        Cudd_RecursiveDeref( dd, bFunc );
+    Vec_PtrFree( vCofs );
+    Extra_StopManager( dd );
+    return pRes;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigTable.c b/abc-build/src/aig/aig/aigTable.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigTable.c
@@ -0,0 +1,277 @@
+/**CFile****************************************************************
+
+  FileName    [aigTable.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Structural hashing table.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigTable.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// hashing the node
+static unsigned long Aig_Hash( Aig_Obj_t * pObj, int TableSize ) 
+{
+    unsigned long Key = Aig_ObjIsExor(pObj) * 1699;
+    Key ^= Aig_ObjFanin0(pObj)->Id * 7937;
+    Key ^= Aig_ObjFanin1(pObj)->Id * 2971;
+    Key ^= Aig_ObjFaninC0(pObj) * 911;
+    Key ^= Aig_ObjFaninC1(pObj) * 353;
+    return Key % TableSize;
+}
+
+// returns the place where this node is stored (or should be stored)
+static Aig_Obj_t ** Aig_TableFind( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t ** ppEntry;
+    assert( Aig_ObjChild0(pObj) && Aig_ObjChild1(pObj) );
+    assert( Aig_ObjFanin0(pObj)->Id < Aig_ObjFanin1(pObj)->Id );
+    for ( ppEntry = p->pTable + Aig_Hash(pObj, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext )
+        if ( *ppEntry == pObj )
+            return ppEntry;
+    assert( *ppEntry == NULL );
+    return ppEntry;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    [Resizes the table.]
+
+  Description [Typically this procedure should not be called.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_TableResize( Aig_Man_t * p )
+{
+    Aig_Obj_t * pEntry, * pNext;
+    Aig_Obj_t ** pTableOld, ** ppPlace;
+    int nTableSizeOld, Counter, i;
+    abctime clk;
+    assert( p->pTable != NULL );
+clk = Abc_Clock();
+    // save the old table
+    pTableOld = p->pTable;
+    nTableSizeOld = p->nTableSize;
+    // get the new table
+    p->nTableSize = Abc_PrimeCudd( 2 * Aig_ManNodeNum(p) ); 
+    p->pTable = ABC_ALLOC( Aig_Obj_t *, p->nTableSize );
+    memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize );
+    // rehash the entries from the old table
+    Counter = 0;
+    for ( i = 0; i < nTableSizeOld; i++ )
+    for ( pEntry = pTableOld[i], pNext = pEntry? pEntry->pNext : NULL; 
+          pEntry; pEntry = pNext, pNext = pEntry? pEntry->pNext : NULL )
+    {
+        // get the place where this entry goes in the table 
+        ppPlace = Aig_TableFind( p, pEntry );
+        assert( *ppPlace == NULL ); // should not be there
+        // add the entry to the list
+        *ppPlace = pEntry;
+        pEntry->pNext = NULL;
+        Counter++;
+    }
+    assert( Counter == Aig_ManNodeNum(p) );
+//    printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize );
+//    ABC_PRT( "Time", Abc_Clock() - clk );
+    // replace the table and the parameters
+    ABC_FREE( pTableOld );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if node with the given attributes is in the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost )
+{
+    Aig_Obj_t * pEntry;
+    assert( !Aig_IsComplement(pGhost) );
+    assert( Aig_ObjIsNode(pGhost) );
+    assert( Aig_ObjChild0(pGhost) && Aig_ObjChild1(pGhost) );
+    assert( Aig_ObjFanin0(pGhost)->Id < Aig_ObjFanin1(pGhost)->Id );
+    if ( p->pTable == NULL || !Aig_ObjRefs(Aig_ObjFanin0(pGhost)) || !Aig_ObjRefs(Aig_ObjFanin1(pGhost)) )
+        return NULL;
+    for ( pEntry = p->pTable[Aig_Hash(pGhost, p->nTableSize)]; pEntry; pEntry = pEntry->pNext )
+    {
+        if ( Aig_ObjChild0(pEntry) == Aig_ObjChild0(pGhost) && 
+             Aig_ObjChild1(pEntry) == Aig_ObjChild1(pGhost) && 
+             Aig_ObjType(pEntry) == Aig_ObjType(pGhost) )
+            return pEntry;
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if node with the given attributes is in the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_TableLookupTwo( Aig_Man_t * p, Aig_Obj_t * pFanin0, Aig_Obj_t * pFanin1 )
+{
+    Aig_Obj_t * pGhost;
+    // consider simple cases
+    if ( pFanin0 == pFanin1 )
+        return pFanin0;
+    if ( pFanin0 == Aig_Not(pFanin1) )
+        return Aig_ManConst0(p);
+    if ( Aig_Regular(pFanin0) == Aig_ManConst1(p) )
+        return pFanin0 == Aig_ManConst1(p) ? pFanin1 : Aig_ManConst0(p);
+    if ( Aig_Regular(pFanin1) == Aig_ManConst1(p) )
+        return pFanin1 == Aig_ManConst1(p) ? pFanin0 : Aig_ManConst0(p);
+    pGhost = Aig_ObjCreateGhost( p, pFanin0, pFanin1, AIG_OBJ_AND );
+    return Aig_TableLookup( p, pGhost );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the new node to the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_TableInsert( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t ** ppPlace;
+    assert( !Aig_IsComplement(pObj) );
+    assert( Aig_TableLookup(p, pObj) == NULL );
+    if ( (pObj->Id & 0xFF) == 0 && 2 * p->nTableSize < Aig_ManNodeNum(p) )
+        Aig_TableResize( p );
+    ppPlace = Aig_TableFind( p, pObj );
+    assert( *ppPlace == NULL );
+    *ppPlace = pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the node from the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_TableDelete( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t ** ppPlace;
+    assert( !Aig_IsComplement(pObj) );
+    ppPlace = Aig_TableFind( p, pObj );
+    assert( *ppPlace == pObj ); // node should be in the table
+    // remove the node
+    *ppPlace = pObj->pNext;
+    pObj->pNext = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of nodes in the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_TableCountEntries( Aig_Man_t * p )
+{
+    Aig_Obj_t * pEntry;
+    int i, Counter = 0;
+    for ( i = 0; i < p->nTableSize; i++ )
+        for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext )
+            Counter++;
+    return Counter;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Profiles the hash table.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Aig_TableProfile( Aig_Man_t * p )
+{
+    Aig_Obj_t * pEntry;
+    int i, Counter;
+    printf( "Table size = %d. Entries = %d.\n", p->nTableSize, Aig_ManNodeNum(p) );
+    for ( i = 0; i < p->nTableSize; i++ )
+    {
+        Counter = 0;
+        for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext )
+            Counter++;
+        if ( Counter ) 
+            printf( "%d ", Counter );
+    }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Profiles the hash table.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Aig_TableClear( Aig_Man_t * p )
+{
+    ABC_FREE( p->pTable );
+    p->nTableSize = 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigTest.c b/abc-build/src/aig/aig/aigTest.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigTest.c
@@ -0,0 +1,39 @@
+
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+void Aig_ProcedureTest()
+{
+    Aig_Man_t * p;
+    Aig_Obj_t * pA, * pB, * pC;
+    Aig_Obj_t * pFunc;
+    Aig_Obj_t * pFunc2;
+
+    p = Aig_ManStart( 1000 );
+
+    pA = Aig_IthVar( p, 0 );
+    pB = Aig_IthVar( p, 1 );
+    pC = Aig_IthVar( p, 2 );
+
+    pFunc = Aig_Mux( p, pA, pB, pC );
+    pFunc2 = Aig_And( p, pA, pB );
+
+    Aig_ObjCreatePo( p, pFunc );
+    Aig_ObjCreatePo( p, pFunc2 );
+
+    Aig_ManSetRegNum( p, 1 );
+
+    Aig_ManCleanup( p );
+
+    if ( !Aig_ManCheck( p ) )
+    {
+        printf( "Check has failed\n" );
+    }
+
+    Aig_ManDumpBlif( p, "aig_test_file.blif", NULL, NULL );
+    Aig_ManStop( p );
+}ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigTiming.c b/abc-build/src/aig/aig/aigTiming.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigTiming.c
@@ -0,0 +1,356 @@
+/**CFile****************************************************************
+
+  FileName    [aigTiming.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Incremental updating of direct/reverse AIG levels.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigTiming.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the reverse level of the node.]
+
+  Description [The reverse level is the level of the node in reverse
+  topological order, starting from the COs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_ObjReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    assert( p->vLevelR );
+    Vec_IntFillExtra( p->vLevelR, pObj->Id + 1, 0 );
+    return Vec_IntEntry(p->vLevelR, pObj->Id);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the reverse level of the node.]
+
+  Description [The reverse level is the level of the node in reverse
+  topological order, starting from the COs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Aig_ObjSetReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj, int LevelR )
+{
+    assert( p->vLevelR );
+    Vec_IntFillExtra( p->vLevelR, pObj->Id + 1, 0 );
+    Vec_IntWriteEntry( p->vLevelR, pObj->Id, LevelR );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resets reverse level of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjClearReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_ObjSetReverseLevel( p, pObj, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns required level of the node.]
+
+  Description [Converts the reverse levels of the node into its required 
+  level as follows: ReqLevel(Node) = MaxLevels(Ntk) + 1 - LevelR(Node).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjRequiredLevel( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    assert( p->vLevelR );
+    return p->nLevelMax + 1 - Aig_ObjReverseLevel(p, pObj);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the reverse level of the node using its fanout levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjReverseLevelNew( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pFanout;
+    int i, iFanout = -1, LevelCur, Level = 0;
+    Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
+    {
+        LevelCur = Aig_ObjReverseLevel( p, pFanout );
+        Level = Abc_MaxInt( Level, LevelCur );
+    }
+    return Level + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares for the computation of required levels.]
+
+  Description [This procedure should be called before the required times
+  are used. It starts internal data structures, which records the level 
+  from the COs of the network nodes in reverse topologogical order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManStartReverseLevels( Aig_Man_t * p, int nMaxLevelIncrease )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( p->pFanData != NULL );
+    assert( p->vLevelR == NULL );
+    // remember the maximum number of direct levels
+    p->nLevelMax = Aig_ManLevels(p) + nMaxLevelIncrease;
+    // start the reverse levels
+    p->vLevelR = Vec_IntAlloc( 0 );
+    Vec_IntFill( p->vLevelR, Aig_ManObjNumMax(p), 0 );
+    // compute levels in reverse topological order
+    vNodes = Aig_ManDfsReverse( p );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        assert( pObj->fMarkA == 0 );
+        Aig_ObjSetReverseLevel( p, pObj, Aig_ObjReverseLevelNew(p, pObj) );
+    }
+    Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the data structures used to compute required levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManStopReverseLevels( Aig_Man_t * p )
+{
+    assert( p->vLevelR != NULL );
+    Vec_IntFree( p->vLevelR );
+    p->vLevelR = NULL;
+    p->nLevelMax = 0;
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Incrementally updates level of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManUpdateLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew )
+{
+    Aig_Obj_t * pFanout, * pTemp;
+    int iFanout = -1, LevelOld, Lev, k, m;
+    assert( p->pFanData != NULL );
+    assert( Aig_ObjIsNode(pObjNew) );
+    // allocate level if needed
+    if ( p->vLevels == NULL )
+        p->vLevels = Vec_VecAlloc( Aig_ManLevels(p) + 8 );
+    // check if level has changed
+    LevelOld = Aig_ObjLevel(pObjNew);
+    if ( LevelOld == Aig_ObjLevelNew(pObjNew) )
+        return;
+    // start the data structure for level update
+    // we cannot fail to visit a node when using this structure because the 
+    // nodes are stored by their _old_ levels, which are assumed to be correct
+    Vec_VecClear( p->vLevels );
+    Vec_VecPush( p->vLevels, LevelOld, pObjNew );
+    pObjNew->fMarkA = 1;
+    // recursively update level
+    Vec_VecForEachEntryStart( Aig_Obj_t *, p->vLevels, pTemp, Lev, k, LevelOld )
+    {
+        pTemp->fMarkA = 0;
+        assert( Aig_ObjLevel(pTemp) == Lev );
+        pTemp->Level = Aig_ObjLevelNew(pTemp);
+        // if the level did not change, no need to check the fanout levels
+        if ( Aig_ObjLevel(pTemp) == Lev )
+            continue;
+        // schedule fanout for level update
+        Aig_ObjForEachFanout( p, pTemp, pFanout, iFanout, m )
+        {
+            if ( Aig_ObjIsNode(pFanout) && !pFanout->fMarkA )
+            {
+                assert( Aig_ObjLevel(pFanout) >= Lev );
+                Vec_VecPush( p->vLevels, Aig_ObjLevel(pFanout), pFanout );
+                pFanout->fMarkA = 1;
+            }
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Incrementally updates level of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManUpdateReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew )
+{
+    Aig_Obj_t * pFanin, * pTemp;
+    int LevelOld, LevFanin, Lev, k;
+    assert( p->vLevelR != NULL );
+    assert( Aig_ObjIsNode(pObjNew) );
+    // allocate level if needed
+    if ( p->vLevels == NULL )
+        p->vLevels = Vec_VecAlloc( Aig_ManLevels(p) + 8 );
+    // check if level has changed
+    LevelOld = Aig_ObjReverseLevel(p, pObjNew);
+    if ( LevelOld == Aig_ObjReverseLevelNew(p, pObjNew) )
+        return;
+    // start the data structure for level update
+    // we cannot fail to visit a node when using this structure because the 
+    // nodes are stored by their _old_ levels, which are assumed to be correct
+    Vec_VecClear( p->vLevels );
+    Vec_VecPush( p->vLevels, LevelOld, pObjNew );
+    pObjNew->fMarkA = 1;
+    // recursively update level
+    Vec_VecForEachEntryStart( Aig_Obj_t *, p->vLevels, pTemp, Lev, k, LevelOld )
+    {
+        pTemp->fMarkA = 0;
+        LevelOld = Aig_ObjReverseLevel(p, pTemp); 
+        assert( LevelOld == Lev );
+        Aig_ObjSetReverseLevel( p, pTemp, Aig_ObjReverseLevelNew(p, pTemp) );
+        // if the level did not change, to need to check the fanout levels
+        if ( Aig_ObjReverseLevel(p, pTemp) == Lev )
+            continue;
+        // schedule fanins for level update
+        pFanin = Aig_ObjFanin0(pTemp);
+        if ( Aig_ObjIsNode(pFanin) && !pFanin->fMarkA )
+        {
+            LevFanin = Aig_ObjReverseLevel( p, pFanin );
+            assert( LevFanin >= Lev );
+            Vec_VecPush( p->vLevels, LevFanin, pFanin );
+            pFanin->fMarkA = 1;
+        }
+        pFanin = Aig_ObjFanin1(pTemp);
+        if ( Aig_ObjIsNode(pFanin) && !pFanin->fMarkA )
+        {
+            LevFanin = Aig_ObjReverseLevel( p, pFanin );
+            assert( LevFanin >= Lev );
+            Vec_VecPush( p->vLevels, LevFanin, pFanin );
+            pFanin->fMarkA = 1;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies direct level of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManVerifyLevel( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    assert( p->pFanData );
+    Aig_ManForEachNode( p, pObj, i )
+        if ( Aig_ObjLevel(pObj) != Aig_ObjLevelNew(pObj) )
+        {
+            printf( "Level of node %6d should be %4d instead of %4d.\n", 
+                pObj->Id, Aig_ObjLevelNew(pObj), Aig_ObjLevel(pObj) );
+            Counter++;
+        }
+    if ( Counter )
+    printf( "Levels of %d nodes are incorrect.\n", Counter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies reverse level of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManVerifyReverseLevel( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    assert( p->vLevelR );
+    Aig_ManForEachNode( p, pObj, i )
+        if ( Aig_ObjLevel(pObj) != Aig_ObjLevelNew(pObj) )
+        {
+            printf( "Reverse level of node %6d should be %4d instead of %4d.\n", 
+                pObj->Id, Aig_ObjReverseLevelNew(p, pObj), Aig_ObjReverseLevel(p, pObj) );
+            Counter++;
+        }
+    if ( Counter )
+    printf( "Reverse levels of %d nodes are incorrect.\n", Counter );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigTruth.c b/abc-build/src/aig/aig/aigTruth.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigTruth.c
@@ -0,0 +1,103 @@
+/**CFile****************************************************************
+
+  FileName    [aigTruth.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Computes truth table for the cut.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigTruth.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Aig_ManCutTruthOne( Aig_Obj_t * pNode, unsigned * pTruth, int nWords )
+{
+    unsigned * pTruth0, * pTruth1;
+    int i;
+    pTruth0 = (unsigned *)Aig_ObjFanin0(pNode)->pData;
+    pTruth1 = (unsigned *)Aig_ObjFanin1(pNode)->pData;
+    if ( Aig_ObjIsExor(pNode) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = pTruth0[i] ^ pTruth1[i];
+    else if ( !Aig_ObjFaninC0(pNode) && !Aig_ObjFaninC1(pNode) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = pTruth0[i] & pTruth1[i];
+    else if ( !Aig_ObjFaninC0(pNode) && Aig_ObjFaninC1(pNode) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = pTruth0[i] & ~pTruth1[i];
+    else if ( Aig_ObjFaninC0(pNode) && !Aig_ObjFaninC1(pNode) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ~pTruth0[i] & pTruth1[i];
+    else // if ( Aig_ObjFaninC0(pNode) && Aig_ObjFaninC1(pNode) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ~pTruth0[i] & ~pTruth1[i];
+    return pTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table of the cut.]
+
+  Description [The returned pointer should be used immediately.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Aig_ManCutTruth( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore )
+{
+    Aig_Obj_t * pObj;
+    int i, nWords;
+    assert( Vec_PtrSize(vLeaves) <= Vec_PtrSize(vTruthElem) );
+    assert( Vec_PtrSize(vNodes) <= Vec_PtrSize(vTruthStore) );
+    assert( Vec_PtrSize(vNodes) == 0 || pRoot == Vec_PtrEntryLast(vNodes) );  
+    // assign elementary truth tables
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i )
+        pObj->pData = Vec_PtrEntry( vTruthElem, i );
+    // compute truths for other nodes
+    nWords = Abc_TruthWordNum( Vec_PtrSize(vLeaves) );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        pObj->pData = Aig_ManCutTruthOne( pObj, (unsigned *)Vec_PtrEntry(vTruthStore, i), nWords );
+    return (unsigned *)pRoot->pData;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigTsim.c b/abc-build/src/aig/aig/aigTsim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigTsim.c
@@ -0,0 +1,526 @@
+/**CFile****************************************************************
+
+  FileName    [aigTsim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Ternary simulation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigTsim.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+#include "aig/saig/saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define TSI_MAX_ROUNDS    1000
+#define TSI_ONE_SERIES     300
+
+#define AIG_XVS0   1
+#define AIG_XVS1   2
+#define AIG_XVSX   3
+
+static inline void Aig_ObjSetXsim( Aig_Obj_t * pObj, int Value )  { pObj->nCuts = Value;  }
+static inline int  Aig_ObjGetXsim( Aig_Obj_t * pObj )             { return pObj->nCuts;   }
+static inline int  Aig_XsimInv( int Value )   
+{ 
+    if ( Value == AIG_XVS0 )
+        return AIG_XVS1;
+    if ( Value == AIG_XVS1 )
+        return AIG_XVS0;
+    assert( Value == AIG_XVSX );       
+    return AIG_XVSX;
+}
+static inline int  Aig_XsimAnd( int Value0, int Value1 )   
+{ 
+    if ( Value0 == AIG_XVS0 || Value1 == AIG_XVS0 )
+        return AIG_XVS0;
+    if ( Value0 == AIG_XVSX || Value1 == AIG_XVSX )
+        return AIG_XVSX;
+    assert( Value0 == AIG_XVS1 && Value1 == AIG_XVS1 );
+    return AIG_XVS1;
+}
+static inline int  Aig_XsimRand2()   
+{
+    return (Aig_ManRandom(0) & 1) ? AIG_XVS1 : AIG_XVS0;
+}
+static inline int  Aig_XsimRand3()   
+{
+    int RetValue;
+    do { 
+        RetValue = Aig_ManRandom(0) & 3; 
+    } while ( RetValue == 0 );
+    return RetValue;
+}
+static inline int  Aig_ObjGetXsimFanin0( Aig_Obj_t * pObj )       
+{ 
+    int RetValue;
+    RetValue = Aig_ObjGetXsim(Aig_ObjFanin0(pObj));
+    return Aig_ObjFaninC0(pObj)? Aig_XsimInv(RetValue) : RetValue;
+}
+static inline int  Aig_ObjGetXsimFanin1( Aig_Obj_t * pObj )       
+{ 
+    int RetValue;
+    RetValue = Aig_ObjGetXsim(Aig_ObjFanin1(pObj));
+    return Aig_ObjFaninC1(pObj)? Aig_XsimInv(RetValue) : RetValue;
+}
+static inline void Aig_XsimPrint( FILE * pFile, int Value )   
+{ 
+    if ( Value == AIG_XVS0 )
+    {
+        fprintf( pFile, "0" );
+        return;
+    }
+    if ( Value == AIG_XVS1 )
+    {
+        fprintf( pFile, "1" );
+        return;
+    }
+    assert( Value == AIG_XVSX );       
+    fprintf( pFile, "x" );
+}
+
+// simulation manager
+typedef struct Aig_Tsi_t_ Aig_Tsi_t;
+struct Aig_Tsi_t_
+{
+    Aig_Man_t *      pAig;              // the original AIG manager
+    // ternary state representation
+    int              nWords;            // the number of words in the states
+    Vec_Ptr_t *      vStates;           // the collection of ternary states
+    Aig_MmFixed_t *  pMem;              // memory for ternary states
+    // hash table for terminary states
+    unsigned **      pBins;
+    int              nBins;
+};
+
+static inline unsigned * Aig_TsiNext( unsigned * pState, int nWords )                      { return *((unsigned **)(pState + nWords));  }
+static inline void       Aig_TsiSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Tsi_t * Aig_TsiStart( Aig_Man_t * pAig )
+{
+    Aig_Tsi_t * p;
+    p = ABC_ALLOC( Aig_Tsi_t, 1 );
+    memset( p, 0, sizeof(Aig_Tsi_t) );
+    p->pAig    = pAig;
+    p->nWords  = Abc_BitWordNum( 2*Aig_ManRegNum(pAig) );
+    p->vStates = Vec_PtrAlloc( 1000 );
+    p->pMem    = Aig_MmFixedStart( sizeof(unsigned) * p->nWords + sizeof(unsigned *), 10000 );
+    p->nBins   = Abc_PrimeCudd(TSI_MAX_ROUNDS/2);
+    p->pBins   = ABC_ALLOC( unsigned *, p->nBins );
+    memset( p->pBins, 0, sizeof(unsigned *) * p->nBins );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_TsiStop( Aig_Tsi_t * p )
+{
+    Aig_MmFixedStop( p->pMem, 0 );
+    Vec_PtrFree( p->vStates );
+    ABC_FREE( p->pBins );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash value of the node using its simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_TsiStateHash( unsigned * pState, int nWords, int nTableSize )
+{
+    static int s_FPrimes[128] = { 
+        1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 
+        1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 
+        2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 
+        2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 
+        3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 
+        3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 
+        4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 
+        4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 
+        5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 
+        6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 
+        6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 
+        7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 
+        8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+    };
+    unsigned uHash;
+    int i;
+    uHash = 0;
+    for ( i = 0; i < nWords; i++ )
+        uHash ^= pState[i] * s_FPrimes[i & 0x7F];
+    return uHash % nTableSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts value into the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_TsiStateLookup( Aig_Tsi_t * p, unsigned * pState, int nWords )
+{
+    unsigned * pEntry;
+    int Hash;
+    Hash = Aig_TsiStateHash( pState, nWords, p->nBins );
+    for ( pEntry = p->pBins[Hash]; pEntry; pEntry = Aig_TsiNext(pEntry, nWords) )
+        if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts value into the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_TsiStateInsert( Aig_Tsi_t * p, unsigned * pState, int nWords )
+{
+    int Hash = Aig_TsiStateHash( pState, nWords, p->nBins );
+    assert( !Aig_TsiStateLookup( p, pState, nWords ) );
+    Aig_TsiSetNext( pState, nWords, p->pBins[Hash] );
+    p->pBins[Hash] = pState;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts value into the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Aig_TsiStateNew( Aig_Tsi_t * p )
+{
+    unsigned * pState;
+    pState = (unsigned *)Aig_MmFixedEntryFetch( p->pMem );
+    memset( pState, 0, sizeof(unsigned) * p->nWords );
+    Vec_PtrPush( p->vStates, pState );
+    return pState;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts value into the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_TsiStatePrint( Aig_Tsi_t * p, unsigned * pState )
+{
+    int i, Value, nZeros = 0, nOnes = 0, nDcs = 0;
+    for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ )
+    {
+        Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i );
+        if ( Value == 1 )
+            printf( "0" ), nZeros++;
+        else if ( Value == 2 )
+            printf( "1" ), nOnes++;
+        else if ( Value == 3 )
+            printf( "x" ), nDcs++;
+        else
+            assert( 0 );
+    }
+    printf( " (0=%5d, 1=%5d, x=%5d)\n", nZeros, nOnes, nDcs );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count constant values in the state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_TsiStateCount( Aig_Tsi_t * p, unsigned * pState )
+{
+    Aig_Obj_t * pObjLi, * pObjLo;
+    int i, Value, nCounter = 0;
+    Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i )
+    {
+        Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i );
+        nCounter += (Value == 1 || Value == 2);
+    }
+    return nCounter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count constant values in the state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_TsiStateOrAll( Aig_Tsi_t * pTsi, unsigned * pState )
+{
+    unsigned * pPrev;
+    int i, k;
+    Vec_PtrForEachEntry( unsigned *, pTsi->vStates, pPrev, i )
+    {
+        for ( k = 0; k < pTsi->nWords; k++ )
+            pState[k] |= pPrev[k];
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Cycles the circuit to create a new initial state.]
+
+  Description [Simulates the circuit with random input for the given 
+  number of timeframes to get a better initial state.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManTernarySimulate( Aig_Man_t * p, int fVerbose, int fVeryVerbose )
+{
+    Aig_Tsi_t * pTsi;
+    Vec_Ptr_t * vMap;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    unsigned * pState;//, * pPrev;
+    int i, f, fConstants, Value, nCounter, nRetired;
+    // allocate the simulation manager
+    pTsi = Aig_TsiStart( p );
+    // initialize the values
+    Aig_ObjSetXsim( Aig_ManConst1(p), AIG_XVS1 );
+    Aig_ManForEachPiSeq( p, pObj, i )
+        Aig_ObjSetXsim( pObj, AIG_XVSX );
+    Aig_ManForEachLoSeq( p, pObj, i )
+        Aig_ObjSetXsim( pObj, AIG_XVS0 );
+    // simulate for the given number of timeframes
+    for ( f = 0; f < TSI_MAX_ROUNDS; f++ )
+    {
+        // collect this state
+        pState = Aig_TsiStateNew( pTsi );
+        Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+        {
+            Value = Aig_ObjGetXsim(pObjLo);
+            if ( Value & 1 )
+                Abc_InfoSetBit( pState, 2 * i );
+            if ( Value & 2 )
+                Abc_InfoSetBit( pState, 2 * i + 1 );
+        }
+
+//        printf( "%d ", Aig_TsiStateCount(pTsi, pState) );
+if ( fVeryVerbose )
+{
+printf( "%3d : ", f );
+Aig_TsiStatePrint( pTsi, pState );
+}
+        // check if this state exists
+        if ( Aig_TsiStateLookup( pTsi, pState, pTsi->nWords ) )
+            break;
+//        nCounter = 0;
+//        Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+//            nCounter += (Aig_ObjGetXsim(pObjLo) == AIG_XVS0);
+//printf( "%d -> ", nCounter );
+        // insert this state
+        Aig_TsiStateInsert( pTsi, pState, pTsi->nWords );
+        // simulate internal nodes
+        Aig_ManForEachNode( p, pObj, i )
+        {
+            Aig_ObjSetXsim( pObj, Aig_XsimAnd(Aig_ObjGetXsimFanin0(pObj), Aig_ObjGetXsimFanin1(pObj)) );
+//            printf( "%d %d    Id = %2d.  Value = %d.\n", 
+//                Aig_ObjGetXsimFanin0(pObj), Aig_ObjGetXsimFanin1(pObj),
+//                i, Aig_XsimAnd(Aig_ObjGetXsimFanin0(pObj), Aig_ObjGetXsimFanin1(pObj)) );
+        }
+        // transfer the latch values
+        Aig_ManForEachLiSeq( p, pObj, i )
+            Aig_ObjSetXsim( pObj, Aig_ObjGetXsimFanin0(pObj) );
+        nCounter = 0;
+        nRetired = 0;
+        Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+        {
+            if ( f < TSI_ONE_SERIES )
+                Aig_ObjSetXsim( pObjLo, Aig_ObjGetXsim(pObjLi) );
+            else
+            {
+                if ( Aig_ObjGetXsim(pObjLi) != Aig_ObjGetXsim(pObjLo) )
+                {
+                    Aig_ObjSetXsim( pObjLo, AIG_XVSX );
+                    nRetired++;
+                }
+            }
+            nCounter += (Aig_ObjGetXsim(pObjLo) == AIG_XVS0);
+        }
+//        if ( nRetired )
+//        printf( "Retired %d registers.\n", nRetired );
+
+//        if ( f && (f % 1000 == 0) )
+//            printf( "%d \n", f );
+//printf( "%d  ", nCounter );
+    }
+//printf( "\n" );
+    if ( f == TSI_MAX_ROUNDS )
+    {
+        printf( "Aig_ManTernarySimulate(): Did not reach a fixed point after %d iterations (not a bug).\n", TSI_MAX_ROUNDS );
+        Aig_TsiStop( pTsi );
+        return NULL;
+    }
+    // OR all the states
+    pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, 0 );
+    Aig_TsiStateOrAll( pTsi, pState );
+    // check if there are constants
+    fConstants = 0;
+    if ( 2*Aig_ManRegNum(p) == 32*pTsi->nWords )
+    {
+        for ( i = 0; i < pTsi->nWords; i++ )
+            if ( pState[i] != ~0 )
+                fConstants = 1;
+    }
+    else
+    {
+        for ( i = 0; i < pTsi->nWords - 1; i++ )
+            if ( pState[i] != ~0 )
+                fConstants = 1;
+        if ( pState[i] != Abc_InfoMask( 2*Aig_ManRegNum(p) - 32*(pTsi->nWords-1) ) )
+            fConstants = 1;
+    }
+    if ( fConstants == 0 )
+    {
+        if ( fVerbose )
+        printf( "Detected 0 constants after %d iterations of ternary simulation.\n", f );
+        Aig_TsiStop( pTsi );
+        return NULL;
+    }
+
+    // start mapping by adding the true PIs
+    vMap = Vec_PtrAlloc( Aig_ManCiNum(p) );
+    Aig_ManForEachPiSeq( p, pObj, i )
+        Vec_PtrPush( vMap, pObj );
+    // find constant registers
+    nCounter = 0;
+    Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+    {
+        Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i );
+        nCounter += (Value == 1 || Value == 2);
+        if ( Value == 1 )
+            Vec_PtrPush( vMap, Aig_ManConst0(p) );
+        else if ( Value == 2 )
+            Vec_PtrPush( vMap, Aig_ManConst1(p) );
+        else if ( Value == 3 )
+            Vec_PtrPush( vMap, pObjLo );
+        else
+            assert( 0 );
+//        Aig_XsimPrint( stdout, Value );
+    }
+//    printf( "\n" );
+    Aig_TsiStop( pTsi );
+    if ( fVerbose )
+    printf( "Detected %d constants after %d iterations of ternary simulation.\n", nCounter, f );
+    return vMap;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces the circuit using ternary simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManConstReduce( Aig_Man_t * p, int fUseMvSweep, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose )
+{
+    Aig_Man_t * pTemp;
+    Vec_Ptr_t * vMap;
+    while ( Aig_ManRegNum(p) > 0 )
+    {
+        if ( fUseMvSweep )
+            vMap = Saig_MvManSimulate( p, nFramesSymb, nFramesSatur, fVerbose, fVeryVerbose );
+        else
+            vMap = Aig_ManTernarySimulate( p, fVerbose, fVeryVerbose );
+        if ( vMap == NULL )
+            break;
+        p = Aig_ManRemap( pTemp = p, vMap );
+        Vec_PtrFree( vMap );
+        Aig_ManSeqCleanup( p );
+        if ( fVerbose )
+            Aig_ManReportImprovement( pTemp, p );
+        Aig_ManStop( pTemp );
+    }
+    return p;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigUtil.c b/abc-build/src/aig/aig/aigUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigUtil.c
@@ -0,0 +1,1562 @@
+/**CFile****************************************************************
+
+  FileName    [aigUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Various procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigUtil.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Increments the current traversal ID of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManIncrementTravId( Aig_Man_t * p )
+{
+    if ( p->nTravIds >= (1<<30)-1 )
+        Aig_ManCleanData( p );
+    p->nTravIds++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the time stamp.]
+
+  Description [The file should be closed.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Aig_TimeStamp()
+{
+    static char Buffer[100];
+	char * TimeStamp;
+	time_t ltime;
+    // get the current time
+	time( &ltime );
+	TimeStamp = asctime( localtime( &ltime ) );
+	TimeStamp[ strlen(TimeStamp) - 1 ] = 0;
+    strcpy( Buffer, TimeStamp );
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Make sure AIG has not gaps in the numeric order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManHasNoGaps( Aig_Man_t * p )
+{
+    return (int)(Aig_ManObjNum(p) == Aig_ManCiNum(p) + Aig_ManCoNum(p) + Aig_ManNodeNum(p) + 1);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect the latches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManLevels( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, LevelMax = 0;
+    Aig_ManForEachCo( p, pObj, i )
+        LevelMax = Abc_MaxInt( LevelMax, (int)Aig_ObjFanin0(pObj)->Level );
+    return LevelMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reset reference counters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManResetRefs( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachObj( p, pObj, i )
+        pObj->nRefs = 0;
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( Aig_ObjFanin0(pObj) )
+            Aig_ObjFanin0(pObj)->nRefs++;
+        if ( Aig_ObjFanin1(pObj) )
+            Aig_ObjFanin1(pObj)->nRefs++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans fMarkA.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManCleanMarkA( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachObj( p, pObj, i )
+        pObj->fMarkA = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans fMarkB.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManCleanMarkB( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachObj( p, pObj, i )
+        pObj->fMarkB = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans fMarkB.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManCleanMarkAB( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachObj( p, pObj, i )
+        pObj->fMarkA = pObj->fMarkB = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the data pointers for the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManCleanData( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachObj( p, pObj, i )
+        pObj->pData = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the data pointers for the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManCleanNext( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachObj( p, pObj, i )
+        pObj->pNext = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively cleans the data pointers in the cone of the node.]
+
+  Description [Applicable to small AIGs only because no caching is performed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjCleanData_rec( Aig_Obj_t * pObj )
+{
+    assert( !Aig_IsComplement(pObj) );
+    assert( !Aig_ObjIsCo(pObj) );
+    if ( Aig_ObjIsAnd(pObj) )
+    {
+        Aig_ObjCleanData_rec( Aig_ObjFanin0(pObj) );
+        Aig_ObjCleanData_rec( Aig_ObjFanin1(pObj) );
+    }
+    pObj->pData = NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Detects multi-input gate rooted at this node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjCollectMulti_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper )
+{
+    if ( pRoot != pObj && (Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) || Aig_ObjType(pRoot) != Aig_ObjType(pObj)) )
+    {
+        Vec_PtrPushUnique(vSuper, pObj);
+        return;
+    }
+    Aig_ObjCollectMulti_rec( pRoot, Aig_ObjChild0(pObj), vSuper );
+    Aig_ObjCollectMulti_rec( pRoot, Aig_ObjChild1(pObj), vSuper );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detects multi-input gate rooted at this node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjCollectMulti( Aig_Obj_t * pRoot, Vec_Ptr_t * vSuper )
+{
+    assert( !Aig_IsComplement(pRoot) );
+    Vec_PtrClear( vSuper );
+    Aig_ObjCollectMulti_rec( pRoot, pRoot, vSuper );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node is the root of MUX or EXOR/NEXOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjIsMuxType( Aig_Obj_t * pNode )
+{
+    Aig_Obj_t * pNode0, * pNode1;
+    // check that the node is regular
+    assert( !Aig_IsComplement(pNode) );
+    // if the node is not AND, this is not MUX
+    if ( !Aig_ObjIsAnd(pNode) )
+        return 0;
+    // if the children are not complemented, this is not MUX
+    if ( !Aig_ObjFaninC0(pNode) || !Aig_ObjFaninC1(pNode) )
+        return 0;
+    // get children
+    pNode0 = Aig_ObjFanin0(pNode);
+    pNode1 = Aig_ObjFanin1(pNode);
+    // if the children are not ANDs, this is not MUX
+    if ( !Aig_ObjIsAnd(pNode0) || !Aig_ObjIsAnd(pNode1) )
+        return 0;
+    // otherwise the node is MUX iff it has a pair of equal grandchildren
+    return (Aig_ObjFanin0(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC0(pNode1))) || 
+           (Aig_ObjFanin0(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC1(pNode1))) ||
+           (Aig_ObjFanin1(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC0(pNode1))) ||
+           (Aig_ObjFanin1(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC1(pNode1)));
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recognizes what nodes are inputs of the EXOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjRecognizeExor( Aig_Obj_t * pObj, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 )
+{
+    Aig_Obj_t * p0, * p1;
+    assert( !Aig_IsComplement(pObj) );
+    if ( !Aig_ObjIsNode(pObj) )
+        return 0;
+    if ( Aig_ObjIsExor(pObj) )
+    {
+        *ppFan0 = Aig_ObjChild0(pObj);
+        *ppFan1 = Aig_ObjChild1(pObj);
+        return 1;
+    }
+    assert( Aig_ObjIsAnd(pObj) );
+    p0 = Aig_ObjChild0(pObj);
+    p1 = Aig_ObjChild1(pObj);
+    if ( !Aig_IsComplement(p0) || !Aig_IsComplement(p1) )
+        return 0;
+    p0 = Aig_Regular(p0);
+    p1 = Aig_Regular(p1);
+    if ( !Aig_ObjIsAnd(p0) || !Aig_ObjIsAnd(p1) )
+        return 0;
+    if ( Aig_ObjFanin0(p0) != Aig_ObjFanin0(p1) || Aig_ObjFanin1(p0) != Aig_ObjFanin1(p1) )
+        return 0;
+    if ( Aig_ObjFaninC0(p0) == Aig_ObjFaninC0(p1) || Aig_ObjFaninC1(p0) == Aig_ObjFaninC1(p1) )
+        return 0;
+    *ppFan0 = Aig_ObjChild0(p0);
+    *ppFan1 = Aig_ObjChild1(p0);
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recognizes what nodes are control and data inputs of a MUX.]
+
+  Description [If the node is a MUX, returns the control variable C.
+  Assigns nodes T and E to be the then and else variables of the MUX. 
+  Node C is never complemented. Nodes T and E can be complemented.
+  This function also recognizes EXOR/NEXOR gates as MUXes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_ObjRecognizeMux( Aig_Obj_t * pNode, Aig_Obj_t ** ppNodeT, Aig_Obj_t ** ppNodeE )
+{
+    Aig_Obj_t * pNode0, * pNode1;
+    assert( !Aig_IsComplement(pNode) );
+    assert( Aig_ObjIsMuxType(pNode) );
+    // get children
+    pNode0 = Aig_ObjFanin0(pNode);
+    pNode1 = Aig_ObjFanin1(pNode);
+
+    // find the control variable
+    if ( Aig_ObjFanin1(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC1(pNode1)) )
+    {
+//        if ( Fraig_IsComplement(pNode1->p2) )
+        if ( Aig_ObjFaninC1(pNode0) )
+        { // pNode2->p2 is positive phase of C
+            *ppNodeT = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1);
+            *ppNodeE = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1);
+            return Aig_ObjChild1(pNode1);//pNode2->p2;
+        }
+        else
+        { // pNode1->p2 is positive phase of C
+            *ppNodeT = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1);
+            *ppNodeE = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1);
+            return Aig_ObjChild1(pNode0);//pNode1->p2;
+        }
+    }
+    else if ( Aig_ObjFanin0(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC0(pNode1)) )
+    {
+//        if ( Fraig_IsComplement(pNode1->p1) )
+        if ( Aig_ObjFaninC0(pNode0) )
+        { // pNode2->p1 is positive phase of C
+            *ppNodeT = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2);
+            *ppNodeE = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2);
+            return Aig_ObjChild0(pNode1);//pNode2->p1;
+        }
+        else
+        { // pNode1->p1 is positive phase of C
+            *ppNodeT = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2);
+            *ppNodeE = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2);
+            return Aig_ObjChild0(pNode0);//pNode1->p1;
+        }
+    }
+    else if ( Aig_ObjFanin0(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC1(pNode1)) )
+    {
+//        if ( Fraig_IsComplement(pNode1->p1) )
+        if ( Aig_ObjFaninC0(pNode0) )
+        { // pNode2->p2 is positive phase of C
+            *ppNodeT = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1);
+            *ppNodeE = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2);
+            return Aig_ObjChild1(pNode1);//pNode2->p2;
+        }
+        else
+        { // pNode1->p1 is positive phase of C
+            *ppNodeT = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2);
+            *ppNodeE = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1);
+            return Aig_ObjChild0(pNode0);//pNode1->p1;
+        }
+    }
+    else if ( Aig_ObjFanin1(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC0(pNode1)) )
+    {
+//        if ( Fraig_IsComplement(pNode1->p2) )
+        if ( Aig_ObjFaninC1(pNode0) )
+        { // pNode2->p1 is positive phase of C
+            *ppNodeT = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2);
+            *ppNodeE = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1);
+            return Aig_ObjChild0(pNode1);//pNode2->p1;
+        }
+        else
+        { // pNode1->p2 is positive phase of C
+            *ppNodeT = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1);
+            *ppNodeE = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2);
+            return Aig_ObjChild1(pNode0);//pNode1->p2;
+        }
+    }
+    assert( 0 ); // this is not MUX
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Aig_ObjReal_rec( Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pObjNew, * pObjR = Aig_Regular(pObj);
+    if ( !Aig_ObjIsBuf(pObjR) )
+        return pObj;
+    pObjNew = Aig_ObjReal_rec( Aig_ObjChild0(pObjR) );
+    return Aig_NotCond( pObjNew, Aig_IsComplement(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure used for sorting the nodes in increasing order of IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ObjCompareIdIncrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 )
+{
+    int Diff = Aig_ObjId(*pp1) - Aig_ObjId(*pp2);
+    if ( Diff < 0 )
+        return -1;
+    if ( Diff > 0 ) 
+        return 1;
+    return 0; 
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints Eqn formula for the AIG rooted at this node.]
+
+  Description [The formula is in terms of PIs, which should have
+  their names assigned in pObj->pData fields.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjPrintEqn( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level )
+{
+    Vec_Ptr_t * vSuper;
+    Aig_Obj_t * pFanin;
+    int fCompl, i;
+    // store the complemented attribute
+    fCompl = Aig_IsComplement(pObj);
+    pObj = Aig_Regular(pObj);
+    // constant case
+    if ( Aig_ObjIsConst1(pObj) )
+    {
+        fprintf( pFile, "%d", !fCompl );
+        return;
+    }
+    // PI case
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        fprintf( pFile, "%s%s", fCompl? "!" : "", (char*)pObj->pData );
+        return;
+    }
+    // AND case
+    Vec_VecExpand( vLevels, Level );
+    vSuper = Vec_VecEntry(vLevels, Level);
+    Aig_ObjCollectMulti( pObj, vSuper );
+    fprintf( pFile, "%s", (Level==0? "" : "(") );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i )
+    {
+        Aig_ObjPrintEqn( pFile, Aig_NotCond(pFanin, fCompl), vLevels, Level+1 );
+        if ( i < Vec_PtrSize(vSuper) - 1 )
+            fprintf( pFile, " %s ", fCompl? "+" : "*" );
+    }
+    fprintf( pFile, "%s", (Level==0? "" : ")") );
+    return;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints Verilog formula for the AIG rooted at this node.]
+
+  Description [The formula is in terms of PIs, which should have
+  their names assigned in pObj->pData fields.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level )
+{
+    Vec_Ptr_t * vSuper;
+    Aig_Obj_t * pFanin, * pFanin0, * pFanin1, * pFaninC;
+    int fCompl, i;
+    // store the complemented attribute
+    fCompl = Aig_IsComplement(pObj);
+    pObj = Aig_Regular(pObj);
+    // constant case
+    if ( Aig_ObjIsConst1(pObj) )
+    {
+        fprintf( pFile, "1\'b%d", !fCompl );
+        return;
+    }
+    // PI case
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        fprintf( pFile, "%s%s", fCompl? "~" : "", (char*)pObj->pData );
+        return;
+    }
+    // EXOR case
+    if ( Aig_ObjIsExor(pObj) )
+    {
+        Vec_VecExpand( vLevels, Level );
+        vSuper = Vec_VecEntry( vLevels, Level );
+        Aig_ObjCollectMulti( pObj, vSuper );
+        fprintf( pFile, "%s", (Level==0? "" : "(") );
+        Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i )
+        {
+            Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin, (fCompl && i==0)), vLevels, Level+1 );
+            if ( i < Vec_PtrSize(vSuper) - 1 )
+                fprintf( pFile, " ^ " );
+        }
+        fprintf( pFile, "%s", (Level==0? "" : ")") );
+        return;
+    }
+    // MUX case
+    if ( Aig_ObjIsMuxType(pObj) )
+    {
+        if ( Aig_ObjRecognizeExor( pObj, &pFanin0, &pFanin1 ) )
+        {
+            fprintf( pFile, "%s", (Level==0? "" : "(") );
+            Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin0, fCompl), vLevels, Level+1 );
+            fprintf( pFile, " ^ " );
+            Aig_ObjPrintVerilog( pFile, pFanin1, vLevels, Level+1 );
+            fprintf( pFile, "%s", (Level==0? "" : ")") );
+        }
+        else 
+        {
+            pFaninC = Aig_ObjRecognizeMux( pObj, &pFanin1, &pFanin0 );
+            fprintf( pFile, "%s", (Level==0? "" : "(") );
+            Aig_ObjPrintVerilog( pFile, pFaninC, vLevels, Level+1 );
+            fprintf( pFile, " ? " );
+            Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin1, fCompl), vLevels, Level+1 );
+            fprintf( pFile, " : " );
+            Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin0, fCompl), vLevels, Level+1 );
+            fprintf( pFile, "%s", (Level==0? "" : ")") );
+        }
+        return;
+    }
+    // AND case
+    Vec_VecExpand( vLevels, Level );
+    vSuper = Vec_VecEntry(vLevels, Level);
+    Aig_ObjCollectMulti( pObj, vSuper );
+    fprintf( pFile, "%s", (Level==0? "" : "(") );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i )
+    {
+        Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin, fCompl), vLevels, Level+1 );
+        if ( i < Vec_PtrSize(vSuper) - 1 )
+            fprintf( pFile, " %s ", fCompl? "|" : "&" );
+    }
+    fprintf( pFile, "%s", (Level==0? "" : ")") );
+    return;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints node in HAIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig )
+{
+    assert( !Aig_IsComplement(pObj) );
+    printf( "Node %p : ", pObj );
+    if ( Aig_ObjIsConst1(pObj) )
+        printf( "constant 1" );
+    else if ( Aig_ObjIsCi(pObj) )
+        printf( "PI" );
+    else if ( Aig_ObjIsCo(pObj) )
+    {
+        printf( "PO" );
+        printf( "%p%s", 
+            Aig_ObjFanin0(pObj), (Aig_ObjFaninC0(pObj)? "\'" : " ") );
+    }
+    else
+        printf( "AND( %p%s, %p%s )", 
+            Aig_ObjFanin0(pObj), (Aig_ObjFaninC0(pObj)? "\'" : " "), 
+            Aig_ObjFanin1(pObj), (Aig_ObjFaninC1(pObj)? "\'" : " ") );
+    printf( " (refs = %3d)", Aig_ObjRefs(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints node in HAIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManPrintVerbose( Aig_Man_t * p, int fHaig )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i;
+    printf( "PIs: " );
+    Aig_ManForEachCi( p, pObj, i )
+        printf( " %p", pObj );
+    printf( "\n" );
+    vNodes = Aig_ManDfs( p, 0 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        Aig_ObjPrintVerbose( pObj, fHaig ), printf( "\n" );
+    printf( "\n" );
+    Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write speculative miter for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManDump( Aig_Man_t * p )
+{ 
+    static int Counter = 0;
+    char FileName[20];
+    // dump the logic into a file
+    sprintf( FileName, "aigbug\\%03d.blif", ++Counter );
+    Aig_ManDumpBlif( p, FileName, NULL, NULL );
+    printf( "Intermediate AIG with %d nodes was written into file \"%s\".\n", Aig_ManNodeNum(p), FileName );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG into a BLIF file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName, Vec_Ptr_t * vPiNames, Vec_Ptr_t * vPoNames )
+{
+    FILE * pFile;
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pConst1 = NULL;
+    int i, nDigits, Counter = 0;
+    if ( Aig_ManCoNum(p) == 0 )
+    {
+        printf( "Aig_ManDumpBlif(): AIG manager does not have POs.\n" );
+        return;
+    }
+    // check if constant is used
+    Aig_ManForEachCo( p, pObj, i )
+        if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) )
+            pConst1 = Aig_ManConst1(p);
+    // collect nodes in the DFS order
+    vNodes = Aig_ManDfs( p, 1 );
+    // assign IDs to objects
+    Aig_ManConst1(p)->iData = Counter++;
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->iData = Counter++;
+    Aig_ManForEachCo( p, pObj, i )
+        pObj->iData = Counter++;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        pObj->iData = Counter++;
+    nDigits = Abc_Base10Log( Counter );
+    // write the file 
+    pFile = fopen( pFileName, "w" );
+    fprintf( pFile, "# BLIF file written by procedure Aig_ManDumpBlif()\n" );
+//    fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" );
+    fprintf( pFile, ".model %s\n", p->pName );
+    // write PIs
+    fprintf( pFile, ".inputs" );
+    Aig_ManForEachPiSeq( p, pObj, i )
+        if ( vPiNames )
+            fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, i) );
+        else
+            fprintf( pFile, " n%0*d", nDigits, pObj->iData );
+    fprintf( pFile, "\n" );
+    // write POs
+    fprintf( pFile, ".outputs" );
+    Aig_ManForEachPoSeq( p, pObj, i )
+        if ( vPoNames )
+            fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPoNames, i) );
+        else
+            fprintf( pFile, " n%0*d", nDigits, pObj->iData );
+    fprintf( pFile, "\n" );
+    // write latches
+    if ( Aig_ManRegNum(p) )
+    {
+        fprintf( pFile, "\n" );
+        Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+        {
+            fprintf( pFile, ".latch" );
+            if ( vPoNames )
+                fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPoNames, Aig_ManCoNum(p)-Aig_ManRegNum(p)+i) );
+            else
+                fprintf( pFile, " n%0*d", nDigits, pObjLi->iData );
+            if ( vPiNames )
+                fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Aig_ManCiNum(p)-Aig_ManRegNum(p)+i) );
+            else
+                fprintf( pFile, " n%0*d", nDigits, pObjLo->iData );
+            fprintf( pFile, " 0\n" );
+        }
+        fprintf( pFile, "\n" );
+    } 
+    // write nodes
+    if ( pConst1 )
+        fprintf( pFile, ".names n%0*d\n 1\n", nDigits, pConst1->iData );
+    Aig_ManSetCioIds( p );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        fprintf( pFile, ".names" );
+        if ( vPiNames && Aig_ObjIsCi(Aig_ObjFanin0(pObj)) )
+            fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Aig_ObjCioId(Aig_ObjFanin0(pObj))) );
+        else
+            fprintf( pFile, " n%0*d", nDigits, Aig_ObjFanin0(pObj)->iData );
+        if ( vPiNames && Aig_ObjIsCi(Aig_ObjFanin1(pObj)) )
+            fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Aig_ObjCioId(Aig_ObjFanin1(pObj))) );
+        else
+            fprintf( pFile, " n%0*d", nDigits, Aig_ObjFanin1(pObj)->iData );
+        fprintf( pFile, " n%0*d\n", nDigits, pObj->iData );
+        fprintf( pFile, "%d%d 1\n", !Aig_ObjFaninC0(pObj), !Aig_ObjFaninC1(pObj) );
+    }
+    // write POs
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        fprintf( pFile, ".names" );
+        if ( vPiNames && Aig_ObjIsCi(Aig_ObjFanin0(pObj)) )
+            fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Aig_ObjCioId(Aig_ObjFanin0(pObj))) );
+        else
+            fprintf( pFile, " n%0*d", nDigits, Aig_ObjFanin0(pObj)->iData );
+        if ( vPoNames )
+            fprintf( pFile, " %s\n", (char*)Vec_PtrEntry(vPoNames, Aig_ObjCioId(pObj)) );
+        else
+            fprintf( pFile, " n%0*d\n", nDigits, pObj->iData );
+        fprintf( pFile, "%d 1\n", !Aig_ObjFaninC0(pObj) );
+    }
+    Aig_ManCleanCioIds( p );
+    fprintf( pFile, ".end\n\n" );
+    fclose( pFile );
+    Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG into a Verilog file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManDumpVerilog( Aig_Man_t * p, char * pFileName )
+{
+    FILE * pFile;
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pConst1 = NULL;
+    int i, nDigits, Counter = 0;
+    if ( Aig_ManCoNum(p) == 0 )
+    {
+        printf( "Aig_ManDumpBlif(): AIG manager does not have POs.\n" );
+        return;
+    }
+    // check if constant is used
+    Aig_ManForEachCo( p, pObj, i )
+        if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) )
+            pConst1 = Aig_ManConst1(p);
+    // collect nodes in the DFS order
+    vNodes = Aig_ManDfs( p, 1 );
+    // assign IDs to objects
+    Aig_ManConst1(p)->iData = Counter++;
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->iData = Counter++;
+    Aig_ManForEachCo( p, pObj, i )
+        pObj->iData = Counter++;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        pObj->iData = Counter++;
+    nDigits = Abc_Base10Log( Counter );
+    // write the file
+    pFile = fopen( pFileName, "w" );
+    fprintf( pFile, "// Verilog file written by procedure Aig_ManDumpVerilog()\n" );
+//    fprintf( pFile, "// http://www.eecs.berkeley.edu/~alanmi/abc/\n" );
+    if ( Aig_ManRegNum(p) )
+        fprintf( pFile, "module %s ( clock", p->pName? p->pName: "test" );
+    else
+        fprintf( pFile, "module %s (", p->pName? p->pName: "test" );
+    Aig_ManForEachPiSeq( p, pObj, i )
+        fprintf( pFile, "%s n%0*d", ((Aig_ManRegNum(p) || i)? ",":""), nDigits, pObj->iData );
+    Aig_ManForEachPoSeq( p, pObj, i )
+        fprintf( pFile, ", n%0*d", nDigits, pObj->iData );
+    fprintf( pFile, " );\n" );
+
+    // write PIs
+    if ( Aig_ManRegNum(p) )
+        fprintf( pFile, "input clock;\n" );
+    Aig_ManForEachPiSeq( p, pObj, i )
+        fprintf( pFile, "input n%0*d;\n", nDigits, pObj->iData );
+    // write POs
+    Aig_ManForEachPoSeq( p, pObj, i )
+        fprintf( pFile, "output n%0*d;\n", nDigits, pObj->iData );
+    // write latches
+    if ( Aig_ManRegNum(p) )
+    {
+    Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+        fprintf( pFile, "reg n%0*d;\n", nDigits, pObjLo->iData );
+    Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+        fprintf( pFile, "wire n%0*d;\n", nDigits, pObjLi->iData );
+    }
+    // write nodes
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        fprintf( pFile, "wire n%0*d;\n", nDigits, pObj->iData );
+    if ( pConst1 )
+        fprintf( pFile, "wire n%0*d;\n", nDigits, pConst1->iData );
+    // write nodes
+    if ( pConst1 )
+        fprintf( pFile, "assign n%0*d = 1\'b1;\n", nDigits, pConst1->iData );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        fprintf( pFile, "assign n%0*d = %sn%0*d & %sn%0*d;\n", 
+            nDigits, pObj->iData,
+            !Aig_ObjFaninC0(pObj) ? " " : "~", nDigits, Aig_ObjFanin0(pObj)->iData, 
+            !Aig_ObjFaninC1(pObj) ? " " : "~", nDigits, Aig_ObjFanin1(pObj)->iData
+            );
+    }
+    // write POs
+    Aig_ManForEachPoSeq( p, pObj, i )
+    {
+        fprintf( pFile, "assign n%0*d = %sn%0*d;\n", 
+            nDigits, pObj->iData,
+            !Aig_ObjFaninC0(pObj) ? " " : "~", nDigits, Aig_ObjFanin0(pObj)->iData );
+    }
+    if ( Aig_ManRegNum(p) )
+    {
+        Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+        {
+            fprintf( pFile, "assign n%0*d = %sn%0*d;\n", 
+                nDigits, pObjLi->iData,
+                !Aig_ObjFaninC0(pObjLi) ? " " : "~", nDigits, Aig_ObjFanin0(pObjLi)->iData );
+        }
+    }
+
+    // write initial state
+    if ( Aig_ManRegNum(p) )
+    {
+        Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+            fprintf( pFile, "always @ (posedge clock) begin n%0*d <= n%0*d; end\n", 
+                 nDigits, pObjLo->iData,
+                 nDigits, pObjLi->iData );
+        Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+            fprintf( pFile, "initial begin n%0*d <= 1\'b0; end\n", 
+                 nDigits, pObjLo->iData );
+    }
+
+    fprintf( pFile, "endmodule\n\n" );
+    fclose( pFile );
+    Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the PI/PO numbers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManSetCioIds( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->CioId = i;
+    Aig_ManForEachCo( p, pObj, i )
+        pObj->CioId = i;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the PI/PO numbers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManCleanCioIds( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->pNext = NULL;
+    Aig_ManForEachCo( p, pObj, i )
+        pObj->pNext = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the PI/PO numbers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManChoiceNum( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    Aig_ManForEachNode( p, pObj, i )
+        Counter += Aig_ObjIsChoice( p, pObj );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the fanouts of the control register.]
+
+  Description [Useful only for Intel MC benchmarks.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManPrintControlFanouts( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pFanin0, * pFanin1, * pCtrl;
+    int i;
+
+    pCtrl = Aig_ManCi( p, Aig_ManCiNum(p) - 1 );
+
+    printf( "Control signal:\n" );
+    Aig_ObjPrint( p, pCtrl ); printf( "\n\n" );
+
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( !Aig_ObjIsNode(pObj) )
+            continue;
+        assert( pObj != pCtrl );
+        pFanin0 = Aig_ObjFanin0(pObj);
+        pFanin1 = Aig_ObjFanin1(pObj);
+        if ( pFanin0 == pCtrl && Aig_ObjIsCi(pFanin1) )
+        {
+            Aig_ObjPrint( p, pObj ); printf( "\n" );
+            Aig_ObjPrint( p, pFanin1 ); printf( "\n" );
+            printf( "\n" );
+        }
+        if ( pFanin1 == pCtrl && Aig_ObjIsCi(pFanin0) )
+        {
+            Aig_ObjPrint( p, pObj ); printf( "\n" );
+            Aig_ObjPrint( p, pFanin0 ); printf( "\n" );
+            printf( "\n" );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the composite name of the file.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Aig_FileNameGenericAppend( char * pBase, char * pSuffix )
+{
+    static char Buffer[1000];
+    char * pDot;
+    strcpy( Buffer, pBase );
+    if ( (pDot = strrchr( Buffer, '.' )) )
+        *pDot = 0;
+    strcat( Buffer, pSuffix );
+    if ( (pDot = strrchr( Buffer, '\\' )) || (pDot = strrchr( Buffer, '/' )) )
+        return pDot+1;
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a sequence of random numbers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [http://en.wikipedia.org/wiki/LFSR]
+
+***********************************************************************/
+void Aig_ManRandomTest2()
+{
+    FILE * pFile;
+    unsigned int lfsr = 1;
+    unsigned int period = 0; 
+    pFile = fopen( "rand.txt", "w" );
+    do {
+//        lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u); // taps 32 31 29 1 
+        lfsr = 1; // to prevent the warning
+        ++period;
+        fprintf( pFile, "%10d : %10d ", period, lfsr );
+//        Extra_PrintBinary( pFile, &lfsr, 32 );
+        fprintf( pFile, "\n" );
+        if ( period == 20000 )
+            break;
+    } while(lfsr != 1u);
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a sequence of random numbers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [http://www.codeproject.com/KB/recipes/SimpleRNG.aspx]
+
+***********************************************************************/
+void Aig_ManRandomTest1()
+{
+    FILE * pFile;
+    unsigned int lfsr;
+    unsigned int period = 0; 
+    pFile = fopen( "rand.txt", "w" );
+    do {
+        lfsr = Aig_ManRandom( 0 );
+        ++period;
+        fprintf( pFile, "%10d : %10d ", period, lfsr );
+//        Extra_PrintBinary( pFile, &lfsr, 32 );
+        fprintf( pFile, "\n" );
+        if ( period == 20000 )
+            break;
+    } while(lfsr != 1u);
+    fclose( pFile );
+}
+
+ 
+#define NUMBER1  3716960521u
+#define NUMBER2  2174103536u
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a sequence of random numbers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [http://www.codeproject.com/KB/recipes/SimpleRNG.aspx]
+
+***********************************************************************/
+unsigned Aig_ManRandom( int fReset )
+{
+    static unsigned int m_z = NUMBER1;
+    static unsigned int m_w = NUMBER2;
+    if ( fReset )
+    {
+        m_z = NUMBER1;
+        m_w = NUMBER2;
+    }
+    m_z = 36969 * (m_z & 65535) + (m_z >> 16);
+    m_w = 18000 * (m_w & 65535) + (m_w >> 16);
+    return (m_z << 16) + m_w;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a sequence of random numbers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word Aig_ManRandom64( int fReset )
+{
+    word Res = (word)Aig_ManRandom(fReset);
+    return Res | ((word)Aig_ManRandom(0) << 32);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates random info for the primary inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManRandomInfo( Vec_Ptr_t * vInfo, int iInputStart, int iWordStart, int iWordStop )
+{
+    unsigned * pInfo;
+    int i, w;
+    Vec_PtrForEachEntryStart( unsigned *, vInfo, pInfo, i, iInputStart )
+        for ( w = iWordStart; w < iWordStop; w++ )
+            pInfo[w] = Aig_ManRandom(0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the result of merging the two vectors.]
+
+  Description [Assumes that the vectors are sorted in the increasing order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_NodeUnionLists( Vec_Ptr_t * vArr1, Vec_Ptr_t * vArr2, Vec_Ptr_t * vArr )
+{
+    Aig_Obj_t ** pBeg  = (Aig_Obj_t **)vArr->pArray;
+    Aig_Obj_t ** pBeg1 = (Aig_Obj_t **)vArr1->pArray;
+    Aig_Obj_t ** pBeg2 = (Aig_Obj_t **)vArr2->pArray;
+    Aig_Obj_t ** pEnd1 = (Aig_Obj_t **)vArr1->pArray + vArr1->nSize;
+    Aig_Obj_t ** pEnd2 = (Aig_Obj_t **)vArr2->pArray + vArr2->nSize;
+    Vec_PtrGrow( vArr, Vec_PtrSize(vArr1) + Vec_PtrSize(vArr2) );
+    pBeg  = (Aig_Obj_t **)vArr->pArray;
+    while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+    {
+        if ( (*pBeg1)->Id == (*pBeg2)->Id )
+            *pBeg++ = *pBeg1++, pBeg2++;
+        else if ( (*pBeg1)->Id < (*pBeg2)->Id )
+            *pBeg++ = *pBeg1++;
+        else 
+            *pBeg++ = *pBeg2++;
+    }
+    while ( pBeg1 < pEnd1 )
+        *pBeg++ = *pBeg1++;
+    while ( pBeg2 < pEnd2 )
+        *pBeg++ = *pBeg2++;
+    vArr->nSize = pBeg - (Aig_Obj_t **)vArr->pArray;
+    assert( vArr->nSize <= vArr->nCap );
+    assert( vArr->nSize >= vArr1->nSize );
+    assert( vArr->nSize >= vArr2->nSize );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the result of intersecting the two vectors.]
+
+  Description [Assumes that the vectors are sorted in the increasing order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_NodeIntersectLists( Vec_Ptr_t * vArr1, Vec_Ptr_t * vArr2, Vec_Ptr_t * vArr )
+{
+    Aig_Obj_t ** pBeg  = (Aig_Obj_t **)vArr->pArray;
+    Aig_Obj_t ** pBeg1 = (Aig_Obj_t **)vArr1->pArray;
+    Aig_Obj_t ** pBeg2 = (Aig_Obj_t **)vArr2->pArray;
+    Aig_Obj_t ** pEnd1 = (Aig_Obj_t **)vArr1->pArray + vArr1->nSize;
+    Aig_Obj_t ** pEnd2 = (Aig_Obj_t **)vArr2->pArray + vArr2->nSize;
+    Vec_PtrGrow( vArr, Abc_MaxInt( Vec_PtrSize(vArr1), Vec_PtrSize(vArr2) ) );
+    pBeg  = (Aig_Obj_t **)vArr->pArray;
+    while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+    {
+        if ( (*pBeg1)->Id == (*pBeg2)->Id )
+            *pBeg++ = *pBeg1++, pBeg2++;
+        else if ( (*pBeg1)->Id < (*pBeg2)->Id )
+//            *pBeg++ = *pBeg1++;
+            pBeg1++;
+        else 
+//            *pBeg++ = *pBeg2++;
+            pBeg2++;
+    }
+//    while ( pBeg1 < pEnd1 )
+//        *pBeg++ = *pBeg1++;
+//    while ( pBeg2 < pEnd2 )
+//        *pBeg++ = *pBeg2++;
+    vArr->nSize = pBeg - (Aig_Obj_t **)vArr->pArray;
+    assert( vArr->nSize <= vArr->nCap );
+    assert( vArr->nSize <= vArr1->nSize );
+    assert( vArr->nSize <= vArr2->nSize );
+}
+
+ABC_NAMESPACE_IMPL_END
+
+#include "proof/fra/fra.h"
+#include "aig/saig/saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+extern void Aig_ManCounterExampleValueStart( Aig_Man_t * pAig, Abc_Cex_t * pCex );
+extern void Aig_ManCounterExampleValueStop( Aig_Man_t * pAig );
+extern int Aig_ManCounterExampleValueLookup(  Aig_Man_t * pAig, int Id, int iFrame );
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the process of retuning values for internal nodes.]
+
+  Description [Should be called when pCex is available, before probing 
+  any object for its value using Aig_ManCounterExampleValueLookup().]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManCounterExampleValueStart( Aig_Man_t * pAig, Abc_Cex_t * pCex )
+{
+    Aig_Obj_t * pObj, * pObjRi, * pObjRo;
+    int Val0, Val1, nObjs, i, k, iBit = 0;
+    assert( Aig_ManRegNum(pAig) > 0 ); // makes sense only for sequential AIGs
+    assert( pAig->pData2 == NULL );    // if this fail, there may be a memory leak
+    // allocate memory to store simulation bits for internal nodes
+    pAig->pData2 = ABC_CALLOC( unsigned, Abc_BitWordNum( (pCex->iFrame + 1) * Aig_ManObjNumMax(pAig) ) );
+    // the register values in the counter-example should be zero
+    Saig_ManForEachLo( pAig, pObj, k )
+        assert( Abc_InfoHasBit(pCex->pData, iBit++) == 0 );
+    // iterate through the timeframes
+    nObjs = Aig_ManObjNumMax(pAig);
+    for ( i = 0; i <= pCex->iFrame; i++ )
+    {
+        // set constant 1 node
+        Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + 0 );
+        // set primary inputs according to the counter-example
+        Saig_ManForEachPi( pAig, pObj, k )
+            if ( Abc_InfoHasBit(pCex->pData, iBit++) )
+                Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObj) );
+        // compute values for each node
+        Aig_ManForEachNode( pAig, pObj, k )
+        {
+            Val0 = Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjFaninId0(pObj) );
+            Val1 = Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjFaninId1(pObj) );
+            if ( (Val0 ^ Aig_ObjFaninC0(pObj)) & (Val1 ^ Aig_ObjFaninC1(pObj)) )
+                Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObj) );
+        }
+        // derive values for combinational outputs
+        Aig_ManForEachCo( pAig, pObj, k )
+        {
+            Val0 = Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjFaninId0(pObj) );
+            if ( Val0 ^ Aig_ObjFaninC0(pObj) )
+                Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObj) );
+        }
+        if ( i == pCex->iFrame )
+            continue;
+        // transfer values to the register output of the next frame
+        Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k )
+            if ( Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObjRi) ) )
+                Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * (i+1) + Aig_ObjId(pObjRo) );
+    }
+    assert( iBit == pCex->nBits );
+    // check that the counter-example is correct, that is, the corresponding output is asserted
+    assert( Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * pCex->iFrame + Aig_ObjId(Aig_ManCo(pAig, pCex->iPo)) ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the process of retuning values for internal nodes.]
+
+  Description [Should be called when probing is no longer needed]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManCounterExampleValueStop( Aig_Man_t * pAig )
+{
+    assert( pAig->pData2 != NULL );    // if this fail, we try to call this procedure more than once
+    free( pAig->pData2 );
+    pAig->pData2 = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the value of the given object in the given timeframe.]
+
+  Description [Should be called to probe the value of an object with 
+  the given ID (iFrame is a 0-based number of a time frame - should not 
+  exceed the number of timeframes in the original counter-example).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManCounterExampleValueLookup(  Aig_Man_t * pAig, int Id, int iFrame )
+{
+    assert( Id >= 0 && Id < Aig_ManObjNumMax(pAig) );
+    return Abc_InfoHasBit( (unsigned *)pAig->pData2, Aig_ManObjNumMax(pAig) * iFrame + Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure to test the above code.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManCounterExampleValueTest( Aig_Man_t * pAig, Abc_Cex_t * pCex )
+{
+    Aig_Obj_t * pObj = Aig_ManObj( pAig, Aig_ManObjNumMax(pAig)/2 );
+    int iFrame = Abc_MaxInt( 0, pCex->iFrame - 1 );
+    printf( "\nUsing counter-example, which asserts output %d in frame %d.\n", pCex->iPo, pCex->iFrame );
+    Aig_ManCounterExampleValueStart( pAig, pCex );
+    printf( "Value of object %d in frame %d is %d.\n", Aig_ObjId(pObj), iFrame,
+        Aig_ManCounterExampleValueLookup(pAig, Aig_ObjId(pObj), iFrame) );
+    Aig_ManCounterExampleValueStop( pAig );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Handle the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManSetPhase( Aig_Man_t * pAig )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    // set the PI simulation information
+    Aig_ManConst1( pAig )->fPhase = 1;
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->fPhase = 0;
+    // simulate internal nodes
+    Aig_ManForEachNode( pAig, pObj, i )
+        pObj->fPhase = ( Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj) )
+                     & ( Aig_ObjFanin1(pObj)->fPhase ^ Aig_ObjFaninC1(pObj) );
+    // simulate PO nodes
+    Aig_ManForEachCo( pAig, pObj, i )
+        pObj->fPhase = Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects muxes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManMuxesCollect( Aig_Man_t * pAig )
+{
+    Vec_Ptr_t * vMuxes;
+    Aig_Obj_t * pObj;
+    int i;
+    vMuxes = Vec_PtrAlloc( 100 );
+    Aig_ManForEachNode( pAig, pObj, i )
+        if ( Aig_ObjIsMuxType(pObj) )
+            Vec_PtrPush( vMuxes, pObj );
+    return vMuxes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences muxes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManMuxesDeref( Aig_Man_t * pAig, Vec_Ptr_t * vMuxes )
+{
+    Aig_Obj_t * pObj, * pNodeT, * pNodeE, * pNodeC;
+    int i;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vMuxes, pObj, i )
+    {
+        if ( Aig_ObjRecognizeExor( pObj, &pNodeT, &pNodeE ) )
+        {
+            pNodeT->nRefs--;
+            pNodeE->nRefs--;
+        }
+        else
+        {
+            pNodeC = Aig_ObjRecognizeMux( pObj, &pNodeT, &pNodeE );
+            pNodeC->nRefs--;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [References muxes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManMuxesRef( Aig_Man_t * pAig, Vec_Ptr_t * vMuxes )
+{
+    Aig_Obj_t * pObj, * pNodeT, * pNodeE, * pNodeC;
+    int i;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vMuxes, pObj, i )
+    {
+        if ( Aig_ObjRecognizeExor( pObj, &pNodeT, &pNodeE ) )
+        {
+            pNodeT->nRefs++;
+            pNodeE->nRefs++;
+        }
+        else
+        {
+            pNodeC = Aig_ObjRecognizeMux( pObj, &pNodeT, &pNodeE );
+            pNodeC->nRefs++;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Complements the constraint outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManInvertConstraints( Aig_Man_t * pAig )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    if ( Aig_ManConstrNum(pAig) == 0 )
+        return;
+    Saig_ManForEachPo( pAig, pObj, i )
+    {
+        if ( i >= Saig_ManPoNum(pAig) - Aig_ManConstrNum(pAig) )
+            Aig_ObjChild0Flip( pObj );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aigWin.c b/abc-build/src/aig/aig/aigWin.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aigWin.c
@@ -0,0 +1,189 @@
+/**CFile****************************************************************
+
+  FileName    [aigWin.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Window computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigWin.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluate the cost of removing the node from the set of leaves.]
+
+  Description [Returns the number of new leaves that will be brought in.
+  Returns large number if the node cannot be removed from the set of leaves.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_NodeGetLeafCostOne( Aig_Obj_t * pNode, int nFanoutLimit )
+{
+    int Cost;
+    // make sure the node is in the construction zone
+    assert( pNode->fMarkA );  
+    // cannot expand over the PI node
+    if ( Aig_ObjIsCi(pNode) )
+        return 999;
+    // get the cost of the cone
+    Cost = (!Aig_ObjFanin0(pNode)->fMarkA) + (!Aig_ObjFanin1(pNode)->fMarkA);
+    // always accept if the number of leaves does not increase
+    if ( Cost < 2 )
+        return Cost;
+    // skip nodes with many fanouts
+    if ( (int)pNode->nRefs > nFanoutLimit )
+        return 999;
+    // return the number of nodes that will be on the leaves if this node is removed
+    return Cost;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Builds reconvergence-driven cut by changing one leaf at a time.]
+
+  Description [This procedure looks at the current leaves and tries to change 
+  one leaf at a time in such a way that the cut grows as little as possible.
+  In evaluating the fanins, this procedure looks only at their immediate 
+  predecessors (this is why it is called a one-level construction procedure).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManFindCut_int( Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit )
+{
+    Aig_Obj_t * pNode, * pFaninBest, * pNext;
+    int CostBest, CostCur, i;
+    // find the best fanin
+    CostBest   = 100;
+    pFaninBest = NULL;
+//printf( "Evaluating fanins of the cut:\n" );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vFront, pNode, i )
+    {
+        CostCur = Aig_NodeGetLeafCostOne( pNode, nFanoutLimit );
+//printf( "    Fanin %s has cost %d.\n", Aig_ObjName(pNode), CostCur );
+        if ( CostBest > CostCur ||
+            (CostBest == CostCur && pNode->Level > pFaninBest->Level) )
+        {
+            CostBest   = CostCur;
+            pFaninBest = pNode;
+        }
+        if ( CostBest == 0 )
+            break;
+    }
+    if ( pFaninBest == NULL )
+        return 0;
+    assert( CostBest < 3 );
+    if ( Vec_PtrSize(vFront) - 1 + CostBest > nSizeLimit )
+        return 0;
+    assert( Aig_ObjIsNode(pFaninBest) );
+    // remove the node from the array
+    Vec_PtrRemove( vFront, pFaninBest );
+//printf( "Removing fanin %s.\n", Aig_ObjName(pFaninBest) );
+
+    // add the left child to the fanins
+    pNext = Aig_ObjFanin0(pFaninBest);
+    if ( !pNext->fMarkA )
+    {
+//printf( "Adding fanin %s.\n", Aig_ObjName(pNext) );
+        pNext->fMarkA = 1;
+        Vec_PtrPush( vFront, pNext );
+        Vec_PtrPush( vVisited, pNext );
+    }
+    // add the right child to the fanins
+    pNext = Aig_ObjFanin1(pFaninBest);
+    if ( !pNext->fMarkA )
+    {
+//printf( "Adding fanin %s.\n", Aig_ObjName(pNext) );
+        pNext->fMarkA = 1;
+        Vec_PtrPush( vFront, pNext );
+        Vec_PtrPush( vVisited, pNext );
+    }
+    assert( Vec_PtrSize(vFront) <= nSizeLimit );
+    // keep doing this
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes one sequential cut of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManFindCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit )
+{
+    Aig_Obj_t * pNode;
+    int i;
+
+    assert( !Aig_IsComplement(pRoot) );
+    assert( Aig_ObjIsNode(pRoot) );
+    assert( Aig_ObjChild0(pRoot) );
+    assert( Aig_ObjChild1(pRoot) );
+
+    // start the cut 
+    Vec_PtrClear( vFront );
+    Vec_PtrPush( vFront, Aig_ObjFanin0(pRoot) );
+    Vec_PtrPush( vFront, Aig_ObjFanin1(pRoot) );
+
+    // start the visited nodes
+    Vec_PtrClear( vVisited );
+    Vec_PtrPush( vVisited, pRoot );
+    Vec_PtrPush( vVisited, Aig_ObjFanin0(pRoot) );
+    Vec_PtrPush( vVisited, Aig_ObjFanin1(pRoot) );
+
+    // mark these nodes
+    assert( !pRoot->fMarkA );
+    assert( !Aig_ObjFanin0(pRoot)->fMarkA );
+    assert( !Aig_ObjFanin1(pRoot)->fMarkA );
+    pRoot->fMarkA = 1;
+    Aig_ObjFanin0(pRoot)->fMarkA = 1;
+    Aig_ObjFanin1(pRoot)->fMarkA = 1;
+
+    // compute the cut
+    while ( Aig_ManFindCut_int( vFront, vVisited, nSizeLimit, nFanoutLimit ) );
+    assert( Vec_PtrSize(vFront) <= nSizeLimit );
+
+    // clean the visit markings
+    Vec_PtrForEachEntry( Aig_Obj_t *, vVisited, pNode, i )
+        pNode->fMarkA = 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/aig_.c b/abc-build/src/aig/aig/aig_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/aig_.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+  FileName    [aig_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aig_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/aig/module.make b/abc-build/src/aig/aig/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/aig/module.make
@@ -0,0 +1,31 @@
+SRC +=	src/aig/aig/aigCheck.c \
+	src/aig/aig/aigCanon.c \
+	src/aig/aig/aigCuts.c \
+	src/aig/aig/aigDfs.c \
+	src/aig/aig/aigDup.c \
+	src/aig/aig/aigFanout.c \
+	src/aig/aig/aigFrames.c \
+	src/aig/aig/aigInter.c \
+	src/aig/aig/aigJust.c \
+	src/aig/aig/aigMan.c \
+	src/aig/aig/aigMem.c \
+	src/aig/aig/aigMffc.c \
+	src/aig/aig/aigObj.c \
+	src/aig/aig/aigOper.c \
+	src/aig/aig/aigOrder.c \
+	src/aig/aig/aigPack.c \
+	src/aig/aig/aigPart.c \
+	src/aig/aig/aigPartReg.c \
+	src/aig/aig/aigPartSat.c \
+	src/aig/aig/aigRepr.c \
+	src/aig/aig/aigRet.c \
+	src/aig/aig/aigRetF.c \
+	src/aig/aig/aigScl.c \
+	src/aig/aig/aigShow.c \
+	src/aig/aig/aigSplit.c \
+	src/aig/aig/aigTable.c \
+	src/aig/aig/aigTiming.c \
+	src/aig/aig/aigTruth.c \
+	src/aig/aig/aigTsim.c \
+	src/aig/aig/aigUtil.c \
+	src/aig/aig/aigWin.c
diff --git a/abc-build/src/aig/gia/gia.c b/abc-build/src/aig/gia/gia.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/gia.c
@@ -0,0 +1,52 @@
+/**CFile****************************************************************
+
+  FileName    [gia.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/gia.h b/abc-build/src/aig/gia/gia.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/gia.h
@@ -0,0 +1,1398 @@
+/**CFile****************************************************************
+
+  FileName    [gia.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: gia.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__gia__gia_h
+#define ABC__aig__gia__gia_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+#include "misc/util/utilCex.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_HEADER_START
+
+#define GIA_NONE 0x1FFFFFFF
+#define GIA_VOID 0x0FFFFFFF
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Gia_MmFixed_t_        Gia_MmFixed_t;    
+typedef struct Gia_MmFlex_t_         Gia_MmFlex_t;     
+typedef struct Gia_MmStep_t_         Gia_MmStep_t;     
+
+typedef struct Gia_Rpr_t_ Gia_Rpr_t;
+struct Gia_Rpr_t_
+{
+    unsigned       iRepr   : 28;  // representative node
+    unsigned       fProved :  1;  // marks the proved equivalence
+    unsigned       fFailed :  1;  // marks the failed equivalence
+    unsigned       fColorA :  1;  // marks cone of A
+    unsigned       fColorB :  1;  // marks cone of B
+};
+
+typedef struct Gia_Plc_t_ Gia_Plc_t;
+struct Gia_Plc_t_
+{
+    unsigned       fFixed  :  1;  // the placement of this object is fixed
+    unsigned       xCoord  : 15;  // x-ooordinate of the placement
+    unsigned       fUndef  :  1;  // the placement of this object is not assigned
+    unsigned       yCoord  : 15;  // y-ooordinate of the placement
+};
+
+typedef struct Gia_Obj_t_ Gia_Obj_t;
+struct Gia_Obj_t_
+{
+    unsigned       iDiff0 :  29;  // the diff of the first fanin
+    unsigned       fCompl0:   1;  // the complemented attribute
+    unsigned       fMark0 :   1;  // first user-controlled mark
+    unsigned       fTerm  :   1;  // terminal node (CI/CO)
+
+    unsigned       iDiff1 :  29;  // the diff of the second fanin
+    unsigned       fCompl1:   1;  // the complemented attribute
+    unsigned       fMark1 :   1;  // second user-controlled mark
+    unsigned       fPhase :   1;  // value under 000 pattern
+
+    unsigned       Value;         // application-specific value
+};
+// Value is currently used to store several types of information
+// - pointer to the next node in the hash table during structural hashing
+// - pointer to the node copy during duplication 
+
+// new AIG manager
+typedef struct Gia_Man_t_ Gia_Man_t;
+struct Gia_Man_t_
+{
+    char *         pName;         // name of the AIG
+    char *         pSpec;         // name of the input file
+    int            nRegs;         // number of registers
+    int            nRegsAlloc;    // number of allocated registers
+    int            nObjs;         // number of objects
+    int            nObjsAlloc;    // number of allocated objects
+    Gia_Obj_t *    pObjs;         // the array of objects
+    unsigned *     pMuxes;        // control signals of MUXes
+    int            nXors;         // the number of XORs
+    int            nMuxes;        // the number of MUXes 
+    int            nBufs;         // the number of buffers
+    Vec_Int_t *    vCis;          // the vector of CIs (PIs + LOs)
+    Vec_Int_t *    vCos;          // the vector of COs (POs + LIs)
+    int *          pHTable;       // hash table
+    int            nHTable;       // hash table size 
+    int            fAddStrash;    // performs additional structural hashing
+    int            fSweeper;      // sweeper is running
+    int *          pRefs;         // the reference count
+    Vec_Int_t *    vLevels;       // levels of the nodes
+    int            nLevels;       // the mamixum level
+    int            nConstrs;      // the number of constraints
+    int            nTravIds;      // the current traversal ID
+    int            nFront;        // frontier size 
+    int *          pReprsOld;     // representatives (for CIs and ANDs)
+    Gia_Rpr_t *    pReprs;        // representatives (for CIs and ANDs)
+    int *          pNexts;        // next nodes in the equivalence classes
+    int *          pSibls;        // next nodes in the choice nodes
+    int *          pIso;          // pairs of structurally isomorphic nodes
+    int            nTerLoop;      // the state where loop begins  
+    int            nTerStates;    // the total number of ternary states
+    int *          pFanData;      // the database to store fanout information
+    int            nFansAlloc;    // the size of fanout representation
+    Vec_Int_t *    vFanoutNums;   // static fanout
+    Vec_Int_t *    vFanout;       // static fanout
+    Vec_Int_t *    vMapping;      // mapping for each node
+    Vec_Int_t *    vCellMapping;  // mapping for each node
+    Vec_Int_t *    vPacking;      // packing information
+    Vec_Int_t *    vLutConfigs;   // LUT configurations
+    Abc_Cex_t *    pCexComb;      // combinational counter-example
+    Abc_Cex_t *    pCexSeq;       // sequential counter-example
+    Vec_Ptr_t *    vSeqModelVec;  // sequential counter-examples
+    int *          pCopies;       // intermediate copies
+    Vec_Int_t *    vTruths;       // used for truth table computation
+    Vec_Int_t *    vFlopClasses;  // classes of flops for retiming/merging/etc
+    Vec_Int_t *    vGateClasses;  // classes of gates for abstraction
+    Vec_Int_t *    vObjClasses;   // classes of objects for abstraction
+    Vec_Int_t *    vInitClasses;  // classes of flops for retiming/merging/etc
+    Vec_Int_t *    vDoms;         // dominators
+    unsigned char* pSwitching;    // switching activity for each object
+    Gia_Plc_t *    pPlacement;    // placement of the objects
+    Gia_Man_t *    pAigExtra;     // combinational logic of holes
+    Vec_Flt_t *    vInArrs;       // PI arrival times
+    Vec_Flt_t *    vOutReqs;      // PO required times
+    Vec_Int_t *    vSwitching;    // switching activity
+    int *          pTravIds;      // separate traversal ID representation
+    int            nTravIdsAlloc; // the number of trav IDs allocated
+    Vec_Ptr_t *    vNamesIn;      // the input names 
+    Vec_Ptr_t *    vNamesOut;     // the output names
+    Vec_Int_t *    vUserPiIds;    // numbers assigned to PIs by the user
+    Vec_Int_t *    vUserPoIds;    // numbers assigned to POs by the user
+    Vec_Int_t *    vUserFfIds;    // numbers assigned to FFs by the user
+    Vec_Int_t *    vCiNumsOrig;   // original CI names
+    Vec_Int_t *    vCoNumsOrig;   // original CO names
+    Vec_Int_t *    vCofVars;      // cofactoring variables
+    Vec_Vec_t *    vClockDoms;    // clock domains
+    Vec_Flt_t *    vTiming;       // arrival/required/slack
+    void *         pManTime;      // the timing manager
+    void *         pLutLib;       // LUT library
+    word           nHashHit;      // hash table hit
+    word           nHashMiss;     // hash table miss
+    void *         pData;         // various user data
+    unsigned *     pData2;        // various user data
+    int            iData;         // various user data
+    int            iData2;        // various user data
+    int            nAnd2Delay;    // AND2 delay scaled to match delay numbers used
+    int            fVerbose;      // verbose reports
+    // bit-parallel simulation
+    int            iPatsPi;
+    Vec_Wrd_t *    vSims;
+    Vec_Wrd_t *    vSimsPi;
+    Vec_Int_t *    vClassOld;
+    Vec_Int_t *    vClassNew;
+    // truth table computation for small functions
+    int            nTtVars;       // truth table variables
+    int            nTtWords;      // truth table words
+    Vec_Int_t *    vTtNums;       // object numbers
+    Vec_Int_t *    vTtNodes;      // internal nodes
+    Vec_Ptr_t *    vTtInputs;     // truth tables for constant and primary inputs
+    Vec_Wrd_t *    vTtMemory;     // truth tables for internal nodes
+    // balancing
+    Vec_Int_t *    vSuper;        // supergate
+    Vec_Int_t *    vStore;        // node storage  
+};
+
+
+
+typedef struct Gps_Par_t_ Gps_Par_t;
+struct Gps_Par_t_
+{
+    int            fTents;
+    int            fSwitch;
+    int            fCut;
+    int            fNpn;
+    int            fLutProf;
+    int            fMuxXor;
+    int            fMiter;
+    int            fSkipMap;
+    char *         pDumpFile;
+};
+
+typedef struct Emb_Par_t_ Emb_Par_t;
+struct Emb_Par_t_
+{
+    int            nDims;         // the number of dimension
+    int            nSols;         // the number of solutions (typically, 2)
+    int            nIters;        // the number of iterations of FORCE
+    int            fRefine;       // use refinement by FORCE
+    int            fCluster;      // use clustered representation 
+    int            fDump;         // dump Gnuplot file
+    int            fDumpLarge;    // dump Gnuplot file for large benchmarks
+    int            fShowImage;    // shows image if Gnuplot is installed
+    int            fVerbose;      // verbose flag  
+};
+
+
+// frames parameters
+typedef struct Gia_ParFra_t_ Gia_ParFra_t;
+struct Gia_ParFra_t_
+{
+    int            nFrames;       // the number of frames to unroll
+    int            fInit;         // initialize the timeframes
+    int            fSaveLastLit;  // adds POs for outputs of each frame
+    int            fDisableSt;    // disables strashing
+    int            fOrPos;        // ORs respective POs in each timeframe
+    int            fVerbose;      // enables verbose output
+};
+
+
+// simulation parameters
+typedef struct Gia_ParSim_t_ Gia_ParSim_t;
+struct Gia_ParSim_t_
+{
+    // user-controlled parameters
+    int            nWords;        // the number of machine words
+    int            nIters;        // the number of timeframes
+    int            RandSeed;      // seed to generate random numbers
+    int            TimeLimit;     // time limit in seconds
+    int            fCheckMiter;   // check if miter outputs are non-zero
+    int            fVerbose;      // enables verbose output
+    int            iOutFail;      // index of the failed output
+};
+
+typedef struct Jf_Par_t_ Jf_Par_t; 
+struct Jf_Par_t_
+{
+    int            nLutSize;
+    int            nCutNum;
+    int            nProcNum;
+    int            nRounds;
+    int            nRoundsEla;
+    int            nRelaxRatio;
+    int            nCoarseLimit;
+    int            nAreaTuner;
+    int            nVerbLimit;
+    int            DelayTarget;
+    int            fAreaOnly;
+    int            fOptEdge;
+    int            fUseMux7;
+    int            fPower;
+    int            fCoarsen;
+    int            fCutMin;
+    int            fFuncDsd;
+    int            fGenCnf;
+    int            fCnfObjIds;
+    int            fAddOrCla;
+    int            fPureAig;
+    int            fDoAverage;
+    int            fCutHashing;
+    int            fCutSimple;
+    int            fVerbose;
+    int            fVeryVerbose;
+    int            nLutSizeMax;
+    int            nCutNumMax;
+    int            nProcNumMax;
+    word           Delay;
+    word           Area;
+    word           Edge;
+    word           Clause;
+    word           Mux7;
+    float          MapDelay;
+    float          MapArea;
+    float          MapDelayTarget;
+    float          Epsilon;
+    float *        pTimesArr;
+    float *        pTimesReq;
+};
+
+static inline unsigned     Gia_ObjCutSign( unsigned ObjId )       { return (1 << (ObjId & 31));                                 }
+static inline int          Gia_WordHasOneBit( unsigned uWord )    { return (uWord & (uWord-1)) == 0;                            }
+static inline int          Gia_WordHasOnePair( unsigned uWord )   { return Gia_WordHasOneBit(uWord & (uWord>>1) & 0x55555555);  }
+static inline int          Gia_WordCountOnes( unsigned uWord )
+{
+    uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555);
+    uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333);
+    uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F);
+    uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF);
+    return  (uWord & 0x0000FFFF) + (uWord>>16);
+}
+static inline int Gia_WordFindFirstBit( unsigned uWord )
+{
+    int i;
+    for ( i = 0; i < 32; i++ )
+        if ( uWord & (1 << i) )
+            return i;
+    return -1;
+}
+
+static inline int Gia_ManTruthIsConst0( unsigned * pIn, int nVars )
+{
+    int w;
+    for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- )
+        if ( pIn[w] )
+            return 0;
+    return 1;
+}
+static inline int Gia_ManTruthIsConst1( unsigned * pIn, int nVars )
+{
+    int w;
+    for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- )
+        if ( pIn[w] != ~(unsigned)0 )
+            return 0;
+    return 1;
+}
+static inline void Gia_ManTruthCopy( unsigned * pOut, unsigned * pIn, int nVars )
+{
+    int w;
+    for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = pIn[w];
+}
+static inline void Gia_ManTruthClear( unsigned * pOut, int nVars )
+{
+    int w;
+    for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = 0;
+}
+static inline void Gia_ManTruthFill( unsigned * pOut, int nVars )
+{
+    int w;
+    for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = ~(unsigned)0;
+}
+static inline void Gia_ManTruthNot( unsigned * pOut, unsigned * pIn, int nVars )
+{
+    int w;
+    for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = ~pIn[w];
+}
+
+static inline int          Gia_ManConst0Lit()                  { return 0; }
+static inline int          Gia_ManConst1Lit()                  { return 1; }
+static inline int          Gia_ManIsConst0Lit( int iLit )      { return (iLit == 0); }
+static inline int          Gia_ManIsConst1Lit( int iLit )      { return (iLit == 1); }
+static inline int          Gia_ManIsConstLit( int iLit )       { return (iLit <= 1); }
+
+static inline Gia_Obj_t *  Gia_Regular( Gia_Obj_t * p )        { return (Gia_Obj_t *)((ABC_PTRUINT_T)(p) & ~01);                           }
+static inline Gia_Obj_t *  Gia_Not( Gia_Obj_t * p )            { return (Gia_Obj_t *)((ABC_PTRUINT_T)(p) ^  01);                           }
+static inline Gia_Obj_t *  Gia_NotCond( Gia_Obj_t * p, int c ) { return (Gia_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c));                           }
+static inline int          Gia_IsComplement( Gia_Obj_t * p )   { return (int)((ABC_PTRUINT_T)(p) & 01);                                    }
+
+static inline char *       Gia_ManName( Gia_Man_t * p )        { return p->pName;                                                          }
+static inline int          Gia_ManCiNum( Gia_Man_t * p )       { return Vec_IntSize(p->vCis);                                              }
+static inline int          Gia_ManCoNum( Gia_Man_t * p )       { return Vec_IntSize(p->vCos);                                              }
+static inline int          Gia_ManPiNum( Gia_Man_t * p )       { return Vec_IntSize(p->vCis) - p->nRegs;                                   }
+static inline int          Gia_ManPoNum( Gia_Man_t * p )       { return Vec_IntSize(p->vCos) - p->nRegs;                                   }
+static inline int          Gia_ManRegNum( Gia_Man_t * p )      { return p->nRegs;                                                          }
+static inline int          Gia_ManObjNum( Gia_Man_t * p )      { return p->nObjs;                                                          }
+static inline int          Gia_ManAndNum( Gia_Man_t * p )      { return p->nObjs - Vec_IntSize(p->vCis) - Vec_IntSize(p->vCos) - 1;        }
+static inline int          Gia_ManXorNum( Gia_Man_t * p )      { return p->nXors;                                                          }
+static inline int          Gia_ManMuxNum( Gia_Man_t * p )      { return p->nMuxes;                                                         }
+static inline int          Gia_ManBufNum( Gia_Man_t * p )      { return p->nBufs;                                                          }
+static inline int          Gia_ManCandNum( Gia_Man_t * p )     { return Gia_ManCiNum(p) + Gia_ManAndNum(p);                                }
+static inline int          Gia_ManConstrNum( Gia_Man_t * p )   { return p->nConstrs;                                                       }
+static inline void         Gia_ManFlipVerbose( Gia_Man_t * p ) { p->fVerbose ^= 1;                                                         } 
+static inline int          Gia_ManHasChoices( Gia_Man_t * p )  { return p->pSibls != NULL;                                                 } 
+static inline int          Gia_ManChoiceNum( Gia_Man_t * p )   { int c = 0; if (p->pSibls) { int i; for (i = 0; i < p->nObjs; i++) c += (int)(p->pSibls[i] > 0); } return c; } 
+
+static inline Gia_Obj_t *  Gia_ManConst0( Gia_Man_t * p )      { return p->pObjs;                                                          }
+static inline Gia_Obj_t *  Gia_ManConst1( Gia_Man_t * p )      { return Gia_Not(Gia_ManConst0(p));                                         }
+static inline Gia_Obj_t *  Gia_ManObj( Gia_Man_t * p, int v )  { assert( v >= 0 && v < p->nObjs ); return p->pObjs + v;                    }
+static inline Gia_Obj_t *  Gia_ManCi( Gia_Man_t * p, int v )   { return Gia_ManObj( p, Vec_IntEntry(p->vCis,v) );                          }
+static inline Gia_Obj_t *  Gia_ManCo( Gia_Man_t * p, int v )   { return Gia_ManObj( p, Vec_IntEntry(p->vCos,v) );                          }
+static inline Gia_Obj_t *  Gia_ManPi( Gia_Man_t * p, int v )   { assert( v < Gia_ManPiNum(p) );  return Gia_ManCi( p, v );                 }
+static inline Gia_Obj_t *  Gia_ManPo( Gia_Man_t * p, int v )   { assert( v < Gia_ManPoNum(p) );  return Gia_ManCo( p, v );                 }
+static inline Gia_Obj_t *  Gia_ManRo( Gia_Man_t * p, int v )   { assert( v < Gia_ManRegNum(p) ); return Gia_ManCi( p, Gia_ManPiNum(p)+v ); }
+static inline Gia_Obj_t *  Gia_ManRi( Gia_Man_t * p, int v )   { assert( v < Gia_ManRegNum(p) ); return Gia_ManCo( p, Gia_ManPoNum(p)+v ); }
+
+static inline int          Gia_ObjId( Gia_Man_t * p, Gia_Obj_t * pObj )        { assert( p->pObjs <= pObj && pObj < p->pObjs + p->nObjs ); return pObj - p->pObjs; }
+static inline int          Gia_ObjCioId( Gia_Obj_t * pObj )                    { assert( pObj->fTerm ); return pObj->iDiff1;                 }
+static inline void         Gia_ObjSetCioId( Gia_Obj_t * pObj, int v )          { assert( pObj->fTerm ); pObj->iDiff1 = v;                    }
+static inline int          Gia_ObjValue( Gia_Obj_t * pObj )                    { return pObj->Value;                                         }
+static inline void         Gia_ObjSetValue( Gia_Obj_t * pObj, int i )          { pObj->Value = i;                                            }
+static inline int          Gia_ObjPhase( Gia_Obj_t * pObj )                    { return pObj->fPhase;                                        }
+static inline int          Gia_ObjPhaseReal( Gia_Obj_t * pObj )                { return Gia_Regular(pObj)->fPhase ^ Gia_IsComplement(pObj);  }
+
+static inline int          Gia_ObjIsTerm( Gia_Obj_t * pObj )                   { return pObj->fTerm;                             } 
+static inline int          Gia_ObjIsAndOrConst0( Gia_Obj_t * pObj )            { return!pObj->fTerm;                             } 
+static inline int          Gia_ObjIsCi( Gia_Obj_t * pObj )                     { return pObj->fTerm && pObj->iDiff0 == GIA_NONE; } 
+static inline int          Gia_ObjIsCo( Gia_Obj_t * pObj )                     { return pObj->fTerm && pObj->iDiff0 != GIA_NONE; } 
+static inline int          Gia_ObjIsAnd( Gia_Obj_t * pObj )                    { return!pObj->fTerm && pObj->iDiff0 != GIA_NONE; } 
+static inline int          Gia_ObjIsXor( Gia_Obj_t * pObj )                    { return Gia_ObjIsAnd(pObj) && pObj->iDiff0 < pObj->iDiff1; } 
+static inline int          Gia_ObjIsMuxId( Gia_Man_t * p, int iObj )           { return p->pMuxes && p->pMuxes[iObj] > 0;        } 
+static inline int          Gia_ObjIsMux( Gia_Man_t * p, Gia_Obj_t * pObj )     { return Gia_ObjIsMuxId( p, Gia_ObjId(p, pObj) ); } 
+static inline int          Gia_ObjIsAndReal( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjIsAnd(pObj) && pObj->iDiff0 > pObj->iDiff1 && !Gia_ObjIsMux(p, pObj); } 
+static inline int          Gia_ObjIsBuf( Gia_Obj_t * pObj )                    { return pObj->iDiff0 == pObj->iDiff1 && pObj->iDiff0 != GIA_NONE; } 
+static inline int          Gia_ObjIsCand( Gia_Obj_t * pObj )                   { return Gia_ObjIsAnd(pObj) || Gia_ObjIsCi(pObj); } 
+static inline int          Gia_ObjIsConst0( Gia_Obj_t * pObj )                 { return pObj->iDiff0 == GIA_NONE && pObj->iDiff1 == GIA_NONE;     } 
+static inline int          Gia_ManObjIsConst0( Gia_Man_t * p, Gia_Obj_t * pObj){ return pObj == p->pObjs;                        } 
+
+static inline int          Gia_Obj2Lit( Gia_Man_t * p, Gia_Obj_t * pObj )      { return Abc_Var2Lit(Gia_ObjId(p, Gia_Regular(pObj)), Gia_IsComplement(pObj)); }
+static inline Gia_Obj_t *  Gia_Lit2Obj( Gia_Man_t * p, int iLit )              { return Gia_NotCond(Gia_ManObj(p, Abc_Lit2Var(iLit)), Abc_LitIsCompl(iLit));  }
+static inline int          Gia_ManCiLit( Gia_Man_t * p, int CiId )             { return Gia_Obj2Lit( p, Gia_ManCi(p, CiId) );                }
+
+static inline int          Gia_ManIdToCioId( Gia_Man_t * p, int Id )           { return Gia_ObjCioId( Gia_ManObj(p, Id) );                   }
+static inline int          Gia_ManCiIdToId( Gia_Man_t * p, int CiId )          { return Gia_ObjId( p, Gia_ManCi(p, CiId) );                  }
+static inline int          Gia_ManCoIdToId( Gia_Man_t * p, int CoId )          { return Gia_ObjId( p, Gia_ManCo(p, CoId) );                  }
+
+static inline int          Gia_ObjIsPi( Gia_Man_t * p, Gia_Obj_t * pObj )      { return Gia_ObjIsCi(pObj) && Gia_ObjCioId(pObj) < Gia_ManPiNum(p);   } 
+static inline int          Gia_ObjIsPo( Gia_Man_t * p, Gia_Obj_t * pObj )      { return Gia_ObjIsCo(pObj) && Gia_ObjCioId(pObj) < Gia_ManPoNum(p);   } 
+static inline int          Gia_ObjIsRo( Gia_Man_t * p, Gia_Obj_t * pObj )      { return Gia_ObjIsCi(pObj) && Gia_ObjCioId(pObj) >= Gia_ManPiNum(p);  } 
+static inline int          Gia_ObjIsRi( Gia_Man_t * p, Gia_Obj_t * pObj )      { return Gia_ObjIsCo(pObj) && Gia_ObjCioId(pObj) >= Gia_ManPoNum(p);  } 
+
+static inline Gia_Obj_t *  Gia_ObjRoToRi( Gia_Man_t * p, Gia_Obj_t * pObj )    { assert( Gia_ObjIsRo(p, pObj) ); return Gia_ManCo(p, Gia_ManCoNum(p) - Gia_ManCiNum(p) + Gia_ObjCioId(pObj)); } 
+static inline Gia_Obj_t *  Gia_ObjRiToRo( Gia_Man_t * p, Gia_Obj_t * pObj )    { assert( Gia_ObjIsRi(p, pObj) ); return Gia_ManCi(p, Gia_ManCiNum(p) - Gia_ManCoNum(p) + Gia_ObjCioId(pObj)); } 
+
+static inline int          Gia_ObjDiff0( Gia_Obj_t * pObj )                    { return pObj->iDiff0;         }
+static inline int          Gia_ObjDiff1( Gia_Obj_t * pObj )                    { return pObj->iDiff1;         }
+static inline int          Gia_ObjFaninC0( Gia_Obj_t * pObj )                  { return pObj->fCompl0;        }
+static inline int          Gia_ObjFaninC1( Gia_Obj_t * pObj )                  { return pObj->fCompl1;        }
+static inline int          Gia_ObjFaninC2( Gia_Man_t * p, Gia_Obj_t * pObj )   { return p->pMuxes && Abc_LitIsCompl(p->pMuxes[Gia_ObjId(p, pObj)]);  }
+static inline Gia_Obj_t *  Gia_ObjFanin0( Gia_Obj_t * pObj )                   { return pObj - pObj->iDiff0;  }
+static inline Gia_Obj_t *  Gia_ObjFanin1( Gia_Obj_t * pObj )                   { return pObj - pObj->iDiff1;  }
+static inline Gia_Obj_t *  Gia_ObjFanin2( Gia_Man_t * p, Gia_Obj_t * pObj )    { return p->pMuxes ? Gia_ManObj(p, Abc_Lit2Var(p->pMuxes[Gia_ObjId(p, pObj)])) : NULL;  }
+static inline Gia_Obj_t *  Gia_ObjChild0( Gia_Obj_t * pObj )                   { return Gia_NotCond( Gia_ObjFanin0(pObj), Gia_ObjFaninC0(pObj) ); }
+static inline Gia_Obj_t *  Gia_ObjChild1( Gia_Obj_t * pObj )                   { return Gia_NotCond( Gia_ObjFanin1(pObj), Gia_ObjFaninC1(pObj) ); }
+static inline Gia_Obj_t *  Gia_ObjChild2( Gia_Man_t * p, Gia_Obj_t * pObj )    { return Gia_NotCond( Gia_ObjFanin2(p, pObj), Gia_ObjFaninC2(p, pObj) ); }
+static inline int          Gia_ObjFaninId0( Gia_Obj_t * pObj, int ObjId )      { return ObjId - pObj->iDiff0;    }
+static inline int          Gia_ObjFaninId1( Gia_Obj_t * pObj, int ObjId )      { return ObjId - pObj->iDiff1;    }
+static inline int          Gia_ObjFaninId2( Gia_Man_t * p, int ObjId )         { return (p->pMuxes && p->pMuxes[ObjId]) ? Abc_Lit2Var(p->pMuxes[ObjId]) : -1; }
+static inline int          Gia_ObjFaninId0p( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjFaninId0( pObj, Gia_ObjId(p, pObj) );              }
+static inline int          Gia_ObjFaninId1p( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjFaninId1( pObj, Gia_ObjId(p, pObj) );              }
+static inline int          Gia_ObjFaninId2p( Gia_Man_t * p, Gia_Obj_t * pObj ) { return (p->pMuxes && p->pMuxes[Gia_ObjId(p, pObj)]) ? Abc_Lit2Var(p->pMuxes[Gia_ObjId(p, pObj)]) : -1; }
+static inline int          Gia_ObjFaninLit0( Gia_Obj_t * pObj, int ObjId )     { return Abc_Var2Lit( Gia_ObjFaninId0(pObj, ObjId), Gia_ObjFaninC0(pObj) ); }
+static inline int          Gia_ObjFaninLit1( Gia_Obj_t * pObj, int ObjId )     { return Abc_Var2Lit( Gia_ObjFaninId1(pObj, ObjId), Gia_ObjFaninC1(pObj) ); }
+static inline int          Gia_ObjFaninLit2( Gia_Man_t * p, int ObjId )        { return (p->pMuxes && p->pMuxes[ObjId]) ? p->pMuxes[ObjId] : -1;           }
+static inline int          Gia_ObjFaninLit0p( Gia_Man_t * p, Gia_Obj_t * pObj) { return Abc_Var2Lit( Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninC0(pObj) );    }
+static inline int          Gia_ObjFaninLit1p( Gia_Man_t * p, Gia_Obj_t * pObj) { return Abc_Var2Lit( Gia_ObjFaninId1p(p, pObj), Gia_ObjFaninC1(pObj) );    }
+static inline int          Gia_ObjFaninLit2p( Gia_Man_t * p, Gia_Obj_t * pObj) { return (p->pMuxes && p->pMuxes[Gia_ObjId(p, pObj)]) ? p->pMuxes[Gia_ObjId(p, pObj)] : -1;    }
+static inline void         Gia_ObjFlipFaninC0( Gia_Obj_t * pObj )              { assert( Gia_ObjIsCo(pObj) ); pObj->fCompl0 ^= 1;          }
+static inline int          Gia_ObjWhatFanin( Gia_Obj_t * pObj, Gia_Obj_t * pFanin )  { return Gia_ObjFanin0(pObj) == pFanin ? 0 : (Gia_ObjFanin1(pObj) == pFanin ? 1 : -1); }
+
+static inline int          Gia_ManPoIsConst0( Gia_Man_t * p, int iPoIndex )    { return Gia_ManIsConst0Lit( Gia_ObjFaninLit0p(p, Gia_ManPo(p, iPoIndex)) ); }
+static inline int          Gia_ManPoIsConst1( Gia_Man_t * p, int iPoIndex )    { return Gia_ManIsConst1Lit( Gia_ObjFaninLit0p(p, Gia_ManPo(p, iPoIndex)) ); }
+
+static inline Gia_Obj_t *  Gia_ObjCopy( Gia_Man_t * p, Gia_Obj_t * pObj )      { return Gia_ManObj( p, Abc_Lit2Var(pObj->Value) );                              }
+static inline int          Gia_ObjLitCopy( Gia_Man_t * p, int iLit )           { return Abc_LitNotCond( Gia_ManObj(p, Abc_Lit2Var(iLit))->Value, Abc_LitIsCompl(iLit));     }
+
+static inline int          Gia_ObjFanin0Copy( Gia_Obj_t * pObj )               { return Abc_LitNotCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) );     }
+static inline int          Gia_ObjFanin1Copy( Gia_Obj_t * pObj )               { return Abc_LitNotCond( Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC1(pObj) );     }
+static inline int          Gia_ObjFanin2Copy( Gia_Man_t * p, Gia_Obj_t * pObj ){ return Abc_LitNotCond(Gia_ObjFanin2(p, pObj)->Value, Gia_ObjFaninC2(p, pObj)); }
+
+static inline int          Gia_ObjCopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj )               { return p->pCopies[Gia_ManObjNum(p) * f + Gia_ObjId(p,pObj)];  }
+static inline void         Gia_ObjSetCopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj, int iLit )  { p->pCopies[Gia_ManObjNum(p) * f + Gia_ObjId(p,pObj)] = iLit;  }
+
+static inline int          Gia_ObjFanin0CopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj )         { return Abc_LitNotCond(Gia_ObjCopyF(p, f, Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj));  }
+static inline int          Gia_ObjFanin1CopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj )         { return Abc_LitNotCond(Gia_ObjCopyF(p, f, Gia_ObjFanin1(pObj)), Gia_ObjFaninC1(pObj));  }
+
+static inline Gia_Obj_t *  Gia_ObjFromLit( Gia_Man_t * p, int iLit )           { return Gia_NotCond( Gia_ManObj(p, Abc_Lit2Var(iLit)), Abc_LitIsCompl(iLit) );  }
+static inline int          Gia_ObjToLit( Gia_Man_t * p, Gia_Obj_t * pObj )     { return Abc_Var2Lit( Gia_ObjId(p, Gia_Regular(pObj)), Gia_IsComplement(pObj) ); }
+static inline int          Gia_ObjPhaseRealLit( Gia_Man_t * p, int iLit )      { return Gia_ObjPhaseReal( Gia_ObjFromLit(p, iLit) );                            }
+
+static inline int          Gia_ObjLevelId( Gia_Man_t * p, int Id )             { return Vec_IntGetEntry(p->vLevels, Id);                    }
+static inline int          Gia_ObjLevel( Gia_Man_t * p, Gia_Obj_t * pObj )     { return Gia_ObjLevelId( p, Gia_ObjId(p,pObj) );             }
+static inline void         Gia_ObjSetLevelId( Gia_Man_t * p, int Id, int l )   { Vec_IntSetEntry(p->vLevels, Id, l);                        }
+static inline void         Gia_ObjSetLevel( Gia_Man_t * p, Gia_Obj_t * pObj, int l )  { Gia_ObjSetLevelId( p, Gia_ObjId(p,pObj), l );       }
+static inline void         Gia_ObjSetCoLevel( Gia_Man_t * p, Gia_Obj_t * pObj )  { assert( Gia_ObjIsCo(pObj)  ); Gia_ObjSetLevel( p, pObj, Gia_ObjLevel(p,Gia_ObjFanin0(pObj)) );                                                }
+static inline void         Gia_ObjSetAndLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsAnd(pObj) ); Gia_ObjSetLevel( p, pObj, 1+Abc_MaxInt(Gia_ObjLevel(p,Gia_ObjFanin0(pObj)),Gia_ObjLevel(p,Gia_ObjFanin1(pObj))) ); }
+static inline void         Gia_ObjSetXorLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsXor(pObj) ); Gia_ObjSetLevel( p, pObj, 2+Abc_MaxInt(Gia_ObjLevel(p,Gia_ObjFanin0(pObj)),Gia_ObjLevel(p,Gia_ObjFanin1(pObj))) ); }
+static inline void         Gia_ObjSetMuxLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsMux(p,pObj) ); Gia_ObjSetLevel( p, pObj, 2+Abc_MaxInt( Abc_MaxInt(Gia_ObjLevel(p,Gia_ObjFanin0(pObj)),Gia_ObjLevel(p,Gia_ObjFanin1(pObj))), Gia_ObjLevel(p,Gia_ObjFanin2(p,pObj))) ); }
+static inline void         Gia_ObjSetGateLevel( Gia_Man_t * p, Gia_Obj_t * pObj ){ if ( Gia_ObjIsMux(p,pObj) ) Gia_ObjSetMuxLevel(p, pObj); else if ( Gia_ObjIsXor(pObj) ) Gia_ObjSetXorLevel(p, pObj); else if ( Gia_ObjIsAnd(pObj) ) Gia_ObjSetAndLevel(p, pObj); }
+
+static inline int          Gia_ObjHasNumId( Gia_Man_t * p, int Id )                { return Vec_IntEntry(p->vTtNums, Id) > -ABC_INFINITY;     }
+static inline int          Gia_ObjNumId( Gia_Man_t * p, int Id )                   { return Vec_IntEntry(p->vTtNums, Id);                     }
+static inline int          Gia_ObjNum( Gia_Man_t * p, Gia_Obj_t * pObj )           { return Vec_IntEntry(p->vTtNums, Gia_ObjId(p,pObj));      }
+static inline void         Gia_ObjSetNumId( Gia_Man_t * p, int Id, int n )         { Vec_IntWriteEntry(p->vTtNums, Id, n);                    }
+static inline void         Gia_ObjSetNum( Gia_Man_t * p, Gia_Obj_t * pObj, int n ) { Vec_IntWriteEntry(p->vTtNums, Gia_ObjId(p,pObj), n);     }
+static inline void         Gia_ObjResetNumId( Gia_Man_t * p, int Id )              { Vec_IntWriteEntry(p->vTtNums, Id, -ABC_INFINITY);        }
+
+static inline int          Gia_ObjRefNumId( Gia_Man_t * p, int Id )            { return p->pRefs[Id];                              }
+static inline int          Gia_ObjRefIncId( Gia_Man_t * p, int Id )            { return p->pRefs[Id]++;                            }
+static inline int          Gia_ObjRefDecId( Gia_Man_t * p, int Id )            { return --p->pRefs[Id];                            }
+static inline int          Gia_ObjRefNum( Gia_Man_t * p, Gia_Obj_t * pObj )    { return Gia_ObjRefNumId( p, Gia_ObjId(p, pObj) );  }
+static inline int          Gia_ObjRefInc( Gia_Man_t * p, Gia_Obj_t * pObj )    { return Gia_ObjRefIncId( p, Gia_ObjId(p, pObj) );  }
+static inline int          Gia_ObjRefDec( Gia_Man_t * p, Gia_Obj_t * pObj )    { return Gia_ObjRefDecId( p, Gia_ObjId(p, pObj) );  }
+static inline void         Gia_ObjRefFanin0Inc(Gia_Man_t * p, Gia_Obj_t * pObj){ Gia_ObjRefInc(p, Gia_ObjFanin0(pObj));            }
+static inline void         Gia_ObjRefFanin1Inc(Gia_Man_t * p, Gia_Obj_t * pObj){ Gia_ObjRefInc(p, Gia_ObjFanin1(pObj));            }
+static inline void         Gia_ObjRefFanin2Inc(Gia_Man_t * p, Gia_Obj_t * pObj){ Gia_ObjRefInc(p, Gia_ObjFanin2(p, pObj));         }
+static inline void         Gia_ObjRefFanin0Dec(Gia_Man_t * p, Gia_Obj_t * pObj){ Gia_ObjRefDec(p, Gia_ObjFanin0(pObj));            }
+static inline void         Gia_ObjRefFanin1Dec(Gia_Man_t * p, Gia_Obj_t * pObj){ Gia_ObjRefDec(p, Gia_ObjFanin1(pObj));            }
+static inline void         Gia_ObjRefFanin2Dec(Gia_Man_t * p, Gia_Obj_t * pObj){ Gia_ObjRefDec(p, Gia_ObjFanin2(p, pObj));         }
+
+static inline void         Gia_ObjSetTravIdCurrent( Gia_Man_t * p, Gia_Obj_t * pObj )         { assert( Gia_ObjId(p, pObj) < p->nTravIdsAlloc ); p->pTravIds[Gia_ObjId(p, pObj)] = p->nTravIds;                    }
+static inline void         Gia_ObjSetTravIdPrevious( Gia_Man_t * p, Gia_Obj_t * pObj )        { assert( Gia_ObjId(p, pObj) < p->nTravIdsAlloc ); p->pTravIds[Gia_ObjId(p, pObj)] = p->nTravIds - 1;                }
+static inline int          Gia_ObjIsTravIdCurrent( Gia_Man_t * p, Gia_Obj_t * pObj )          { assert( Gia_ObjId(p, pObj) < p->nTravIdsAlloc ); return (p->pTravIds[Gia_ObjId(p, pObj)] == p->nTravIds);          }
+static inline int          Gia_ObjIsTravIdPrevious( Gia_Man_t * p, Gia_Obj_t * pObj )         { assert( Gia_ObjId(p, pObj) < p->nTravIdsAlloc ); return (p->pTravIds[Gia_ObjId(p, pObj)] == p->nTravIds - 1);      }
+static inline void         Gia_ObjSetTravIdCurrentId( Gia_Man_t * p, int Id )                 { assert( Id < p->nTravIdsAlloc ); p->pTravIds[Id] = p->nTravIds;                     }
+static inline int          Gia_ObjIsTravIdCurrentId( Gia_Man_t * p, int Id )                  { assert( Id < p->nTravIdsAlloc ); return (p->pTravIds[Id] == p->nTravIds);           }
+
+static inline void         Gia_ManTimeClean( Gia_Man_t * p )                                  { int i; assert( p->vTiming != NULL ); Vec_FltFill(p->vTiming, 3*Gia_ManObjNum(p), 0); for ( i = 0; i < Gia_ManObjNum(p); i++ )  Vec_FltWriteEntry( p->vTiming, 3*i+1, (float)(ABC_INFINITY) ); }
+static inline void         Gia_ManTimeStart( Gia_Man_t * p )                                  { assert( p->vTiming == NULL ); p->vTiming = Vec_FltAlloc(0); Gia_ManTimeClean( p );  }
+static inline void         Gia_ManTimeStop( Gia_Man_t * p )                                   { assert( p->vTiming != NULL ); Vec_FltFreeP(&p->vTiming);                            }
+static inline float        Gia_ObjTimeArrival( Gia_Man_t * p, int Id )                        { return Vec_FltEntry(p->vTiming, 3*Id+0);                                            }
+static inline float        Gia_ObjTimeRequired( Gia_Man_t * p, int Id )                       { return Vec_FltEntry(p->vTiming, 3*Id+1);                                            }
+static inline float        Gia_ObjTimeSlack( Gia_Man_t * p, int Id )                          { return Vec_FltEntry(p->vTiming, 3*Id+2);                                            }
+static inline float        Gia_ObjTimeArrivalObj( Gia_Man_t * p, Gia_Obj_t * pObj )           { return Gia_ObjTimeArrival( p, Gia_ObjId(p, pObj) );                                 }
+static inline float        Gia_ObjTimeRequiredObj( Gia_Man_t * p, Gia_Obj_t * pObj )          { return Gia_ObjTimeRequired( p, Gia_ObjId(p, pObj) );                                }
+static inline float        Gia_ObjTimeSlackObj( Gia_Man_t * p, Gia_Obj_t * pObj )             { return Gia_ObjTimeSlack( p, Gia_ObjId(p, pObj) );                                   }
+static inline void         Gia_ObjSetTimeArrival( Gia_Man_t * p, int Id, float t )            { Vec_FltWriteEntry( p->vTiming, 3*Id+0, t );                                         }
+static inline void         Gia_ObjSetTimeRequired( Gia_Man_t * p, int Id, float t )           { Vec_FltWriteEntry( p->vTiming, 3*Id+1, t );                                         }
+static inline void         Gia_ObjSetTimeSlack( Gia_Man_t * p, int Id, float t )              { Vec_FltWriteEntry( p->vTiming, 3*Id+2, t );                                         }
+static inline void         Gia_ObjSetTimeArrivalObj( Gia_Man_t * p, Gia_Obj_t * pObj, float t )  { Gia_ObjSetTimeArrival( p, Gia_ObjId(p, pObj), t );                               }
+static inline void         Gia_ObjSetTimeRequiredObj( Gia_Man_t * p, Gia_Obj_t * pObj, float t ) { Gia_ObjSetTimeRequired( p, Gia_ObjId(p, pObj), t );                              }
+static inline void         Gia_ObjSetTimeSlackObj( Gia_Man_t * p, Gia_Obj_t * pObj, float t )    { Gia_ObjSetTimeSlack( p, Gia_ObjId(p, pObj), t );                                 }
+
+static inline int          Gia_ObjSimWords( Gia_Man_t * p )                    { return Vec_WrdSize( p->vSimsPi ) / Gia_ManPiNum( p );          }
+static inline word *       Gia_ObjSimPi( Gia_Man_t * p, int PiId )             { return Vec_WrdEntryP( p->vSimsPi, PiId * Gia_ObjSimWords(p) ); }
+static inline word *       Gia_ObjSim( Gia_Man_t * p, int Id )                 { return Vec_WrdEntryP( p->vSims, Id * Gia_ObjSimWords(p) );     }
+static inline word *       Gia_ObjSimObj( Gia_Man_t * p, Gia_Obj_t * pObj )    { return Gia_ObjSim( p, Gia_ObjId(p, pObj) );                    }
+
+// AIG construction
+extern void Gia_ObjAddFanout( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanout );
+static inline Gia_Obj_t * Gia_ManAppendObj( Gia_Man_t * p )  
+{ 
+    if ( p->nObjs == p->nObjsAlloc )
+    {
+        int nObjNew = Abc_MinInt( 2 * p->nObjsAlloc, (1 << 29) );
+        if ( p->nObjs == (1 << 29) )
+            printf( "Hard limit on the number of nodes (2^29) is reached. Quitting...\n" ), exit(1);
+        assert( p->nObjs < nObjNew );
+        if ( p->fVerbose )
+            printf("Extending GIA object storage: %d -> %d.\n", p->nObjsAlloc, nObjNew );
+        assert( p->nObjsAlloc > 0 );
+        p->pObjs = ABC_REALLOC( Gia_Obj_t, p->pObjs, nObjNew );
+        memset( p->pObjs + p->nObjsAlloc, 0, sizeof(Gia_Obj_t) * (nObjNew - p->nObjsAlloc) );
+        if ( p->pMuxes )
+        {
+            p->pMuxes = ABC_REALLOC( unsigned, p->pMuxes, nObjNew );
+            memset( p->pMuxes + p->nObjsAlloc, 0, sizeof(unsigned) * (nObjNew - p->nObjsAlloc) );
+        }
+        p->nObjsAlloc = nObjNew;
+    }
+    return Gia_ManObj( p, p->nObjs++ );
+}
+static inline int Gia_ManAppendCi( Gia_Man_t * p )  
+{ 
+    Gia_Obj_t * pObj = Gia_ManAppendObj( p );
+    pObj->fTerm = 1;
+    pObj->iDiff0 = GIA_NONE;
+    pObj->iDiff1 = Vec_IntSize( p->vCis );
+    Vec_IntPush( p->vCis, Gia_ObjId(p, pObj) );
+    return Gia_ObjId( p, pObj ) << 1;
+}
+static inline int Gia_ManAppendAnd( Gia_Man_t * p, int iLit0, int iLit1 )  
+{ 
+    Gia_Obj_t * pObj = Gia_ManAppendObj( p );
+    assert( iLit0 >= 0 && Abc_Lit2Var(iLit0) < Gia_ManObjNum(p) );
+    assert( iLit1 >= 0 && Abc_Lit2Var(iLit1) < Gia_ManObjNum(p) );
+    assert( Abc_Lit2Var(iLit0) != Abc_Lit2Var(iLit1) );
+    if ( iLit0 < iLit1 )
+    {
+        pObj->iDiff0  = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0);
+        pObj->fCompl0 = Abc_LitIsCompl(iLit0);
+        pObj->iDiff1  = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1);
+        pObj->fCompl1 = Abc_LitIsCompl(iLit1);
+    }
+    else
+    {
+        pObj->iDiff1  = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0);
+        pObj->fCompl1 = Abc_LitIsCompl(iLit0);
+        pObj->iDiff0  = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1);
+        pObj->fCompl0 = Abc_LitIsCompl(iLit1);
+    }
+    if ( p->pFanData )
+    {
+        Gia_ObjAddFanout( p, Gia_ObjFanin0(pObj), pObj );
+        Gia_ObjAddFanout( p, Gia_ObjFanin1(pObj), pObj );
+    }
+    if ( p->fSweeper )
+    {
+        Gia_Obj_t * pFan0 = Gia_ObjFanin0(pObj);
+        Gia_Obj_t * pFan1 = Gia_ObjFanin1(pObj);
+        if ( pFan0->fMark0 ) pFan0->fMark1 = 1; else pFan0->fMark0 = 1;
+        if ( pFan1->fMark0 ) pFan1->fMark1 = 1; else pFan1->fMark0 = 1;
+        pObj->fPhase = (Gia_ObjPhase(pFan0) ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjPhase(pFan1) ^ Gia_ObjFaninC1(pObj));
+    }
+    return Gia_ObjId( p, pObj ) << 1;
+}
+static inline int Gia_ManAppendAnd2( Gia_Man_t * p, int iLit0, int iLit1 )  
+{ 
+    if ( iLit0 < 2 )
+        return iLit0 ? iLit1 : 0;
+    if ( iLit1 < 2 )
+        return iLit1 ? iLit0 : 0;
+    if ( iLit0 == iLit1 )
+        return iLit1;
+    if ( iLit0 == Abc_LitNot(iLit1) )
+        return 0;
+    return Gia_ManAppendAnd( p, iLit0, iLit1 );
+}
+static inline int Gia_ManAppendXorReal( Gia_Man_t * p, int iLit0, int iLit1 )  
+{ 
+    Gia_Obj_t * pObj = Gia_ManAppendObj( p );
+    assert( iLit0 >= 0 && Abc_Lit2Var(iLit0) < Gia_ManObjNum(p) );
+    assert( iLit1 >= 0 && Abc_Lit2Var(iLit1) < Gia_ManObjNum(p) );
+    assert( Abc_Lit2Var(iLit0) != Abc_Lit2Var(iLit1) );
+    assert( !Abc_LitIsCompl(iLit0) );
+    assert( !Abc_LitIsCompl(iLit1) );
+    if ( Abc_Lit2Var(iLit0) > Abc_Lit2Var(iLit1) )
+    {
+        pObj->iDiff0  = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0);
+        pObj->fCompl0 = Abc_LitIsCompl(iLit0);
+        pObj->iDiff1  = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1);
+        pObj->fCompl1 = Abc_LitIsCompl(iLit1);
+    }
+    else
+    {
+        pObj->iDiff1  = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0);
+        pObj->fCompl1 = Abc_LitIsCompl(iLit0);
+        pObj->iDiff0  = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1);
+        pObj->fCompl0 = Abc_LitIsCompl(iLit1);
+    }
+    p->nXors++;
+    return Gia_ObjId( p, pObj ) << 1;
+}
+static inline int Gia_ManAppendMuxReal( Gia_Man_t * p, int iLitC, int iLit1, int iLit0 )  
+{ 
+    Gia_Obj_t * pObj = Gia_ManAppendObj( p );
+    assert( p->pMuxes != NULL );
+    assert( iLit0 >= 0 && Abc_Lit2Var(iLit0) < Gia_ManObjNum(p) );
+    assert( iLit1 >= 0 && Abc_Lit2Var(iLit1) < Gia_ManObjNum(p) );
+    assert( iLitC >= 0 && Abc_Lit2Var(iLitC) < Gia_ManObjNum(p) );
+    assert( Abc_Lit2Var(iLit0) != Abc_Lit2Var(iLit1) );
+    assert( Abc_Lit2Var(iLitC) != Abc_Lit2Var(iLit0) );
+    assert( Abc_Lit2Var(iLitC) != Abc_Lit2Var(iLit1) );
+    assert( !p->pHTable || !Abc_LitIsCompl(iLit1) );
+    if ( Abc_Lit2Var(iLit0) < Abc_Lit2Var(iLit1) )
+    {
+        pObj->iDiff0  = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0);
+        pObj->fCompl0 = Abc_LitIsCompl(iLit0);
+        pObj->iDiff1  = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1);
+        pObj->fCompl1 = Abc_LitIsCompl(iLit1);
+        p->pMuxes[Gia_ObjId(p, pObj)] = iLitC;
+    }
+    else
+    {
+        pObj->iDiff1  = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0);
+        pObj->fCompl1 = Abc_LitIsCompl(iLit0);
+        pObj->iDiff0  = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1);
+        pObj->fCompl0 = Abc_LitIsCompl(iLit1);
+        p->pMuxes[Gia_ObjId(p, pObj)] = Abc_LitNot(iLitC);
+    }
+    p->nMuxes++;
+    return Gia_ObjId( p, pObj ) << 1;
+}
+static inline int Gia_ManAppendBuf( Gia_Man_t * p, int iLit )  
+{ 
+    Gia_Obj_t * pObj = Gia_ManAppendObj( p );
+    assert( iLit >= 0 && Abc_Lit2Var(iLit) < Gia_ManObjNum(p) );
+    pObj->iDiff0  = pObj->iDiff1  = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit);
+    pObj->fCompl0 = pObj->fCompl1 = Abc_LitIsCompl(iLit);
+    p->nBufs++;
+    return Gia_ObjId( p, pObj ) << 1;
+}
+static inline int Gia_ManAppendCo( Gia_Man_t * p, int iLit0 )  
+{ 
+    Gia_Obj_t * pObj;
+    assert( iLit0 >= 0 && Abc_Lit2Var(iLit0) < Gia_ManObjNum(p) );
+    assert( !Gia_ObjIsCo(Gia_ManObj(p, Abc_Lit2Var(iLit0))) );
+    pObj = Gia_ManAppendObj( p );    
+    pObj->fTerm = 1;
+    pObj->iDiff0  = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0);
+    pObj->fCompl0 = Abc_LitIsCompl(iLit0);
+    pObj->iDiff1  = Vec_IntSize( p->vCos );
+    Vec_IntPush( p->vCos, Gia_ObjId(p, pObj) );
+    if ( p->pFanData )
+        Gia_ObjAddFanout( p, Gia_ObjFanin0(pObj), pObj );
+    return Gia_ObjId( p, pObj ) << 1;
+}
+static inline int Gia_ManAppendOr( Gia_Man_t * p, int iLit0, int iLit1 )
+{
+    return Abc_LitNot(Gia_ManAppendAnd( p, Abc_LitNot(iLit0), Abc_LitNot(iLit1) ));
+}
+static inline int Gia_ManAppendMux( Gia_Man_t * p, int iCtrl, int iData1, int iData0 )  
+{ 
+    int iTemp0 = Gia_ManAppendAnd( p, Abc_LitNot(iCtrl), iData0 );
+    int iTemp1 = Gia_ManAppendAnd( p, iCtrl, iData1 );
+    return Abc_LitNotCond( Gia_ManAppendAnd( p, Abc_LitNot(iTemp0), Abc_LitNot(iTemp1) ), 1 );
+}
+static inline int Gia_ManAppendXor( Gia_Man_t * p, int iLit0, int iLit1 )  
+{ 
+    return Gia_ManAppendMux( p, iLit0, Abc_LitNot(iLit1), iLit1 );
+}
+static inline void Gia_ManPatchCoDriver( Gia_Man_t * p, int iCoIndex, int iLit0 )  
+{
+    Gia_Obj_t * pObjCo  = Gia_ManCo( p, iCoIndex );
+    assert( Gia_ObjId(p, pObjCo) > Abc_Lit2Var(iLit0) );
+    pObjCo->iDiff0  = Gia_ObjId(p, pObjCo) - Abc_Lit2Var(iLit0);
+    pObjCo->fCompl0 = Abc_LitIsCompl(iLit0);
+}
+
+#define GIA_ZER 1
+#define GIA_ONE 2
+#define GIA_UND 3
+
+static inline int Gia_XsimNotCond( int Value, int fCompl )   
+{ 
+    if ( Value == GIA_UND )
+        return GIA_UND;
+    if ( Value == GIA_ZER + fCompl )
+        return GIA_ZER;
+    return GIA_ONE;
+}
+static inline int Gia_XsimAndCond( int Value0, int fCompl0, int Value1, int fCompl1 )   
+{ 
+    if ( Value0 == GIA_ZER + fCompl0 || Value1 == GIA_ZER + fCompl1 )
+        return GIA_ZER;
+    if ( Value0 == GIA_UND || Value1 == GIA_UND )
+        return GIA_UND;
+    return GIA_ONE;
+}
+
+
+static inline void Gia_ObjTerSimSetC( Gia_Obj_t * pObj ) { pObj->fMark0 = 0; pObj->fMark1 = 0;    }
+static inline void Gia_ObjTerSimSet0( Gia_Obj_t * pObj ) { pObj->fMark0 = 1; pObj->fMark1 = 0;    }
+static inline void Gia_ObjTerSimSet1( Gia_Obj_t * pObj ) { pObj->fMark0 = 0; pObj->fMark1 = 1;    }
+static inline void Gia_ObjTerSimSetX( Gia_Obj_t * pObj ) { pObj->fMark0 = 1; pObj->fMark1 = 1;    }
+
+static inline int  Gia_ObjTerSimGetC( Gia_Obj_t * pObj ) { return !pObj->fMark0 && !pObj->fMark1; }
+static inline int  Gia_ObjTerSimGet0( Gia_Obj_t * pObj ) { return  pObj->fMark0 && !pObj->fMark1; }
+static inline int  Gia_ObjTerSimGet1( Gia_Obj_t * pObj ) { return !pObj->fMark0 &&  pObj->fMark1; }
+static inline int  Gia_ObjTerSimGetX( Gia_Obj_t * pObj ) { return  pObj->fMark0 &&  pObj->fMark1; }
+
+static inline int  Gia_ObjTerSimGet0Fanin0( Gia_Obj_t * pObj ) { return (Gia_ObjTerSimGet1(Gia_ObjFanin0(pObj)) && Gia_ObjFaninC0(pObj)) || (Gia_ObjTerSimGet0(Gia_ObjFanin0(pObj)) && !Gia_ObjFaninC0(pObj)); }
+static inline int  Gia_ObjTerSimGet1Fanin0( Gia_Obj_t * pObj ) { return (Gia_ObjTerSimGet0(Gia_ObjFanin0(pObj)) && Gia_ObjFaninC0(pObj)) || (Gia_ObjTerSimGet1(Gia_ObjFanin0(pObj)) && !Gia_ObjFaninC0(pObj)); }
+
+static inline int  Gia_ObjTerSimGet0Fanin1( Gia_Obj_t * pObj ) { return (Gia_ObjTerSimGet1(Gia_ObjFanin1(pObj)) && Gia_ObjFaninC1(pObj)) || (Gia_ObjTerSimGet0(Gia_ObjFanin1(pObj)) && !Gia_ObjFaninC1(pObj)); }
+static inline int  Gia_ObjTerSimGet1Fanin1( Gia_Obj_t * pObj ) { return (Gia_ObjTerSimGet0(Gia_ObjFanin1(pObj)) && Gia_ObjFaninC1(pObj)) || (Gia_ObjTerSimGet1(Gia_ObjFanin1(pObj)) && !Gia_ObjFaninC1(pObj)); }
+
+static inline void Gia_ObjTerSimAnd( Gia_Obj_t * pObj )
+{
+    assert( Gia_ObjIsAnd(pObj) );
+    assert( !Gia_ObjTerSimGetC( Gia_ObjFanin0(pObj) ) );
+    assert( !Gia_ObjTerSimGetC( Gia_ObjFanin1(pObj) ) );
+    if ( Gia_ObjTerSimGet0Fanin0(pObj) || Gia_ObjTerSimGet0Fanin1(pObj) )
+        Gia_ObjTerSimSet0( pObj );
+    else if ( Gia_ObjTerSimGet1Fanin0(pObj) && Gia_ObjTerSimGet1Fanin1(pObj) )
+        Gia_ObjTerSimSet1( pObj );
+    else 
+        Gia_ObjTerSimSetX( pObj );
+}
+static inline void Gia_ObjTerSimCo( Gia_Obj_t * pObj )
+{
+    assert( Gia_ObjIsCo(pObj) );
+    assert( !Gia_ObjTerSimGetC( Gia_ObjFanin0(pObj) ) );
+    if ( Gia_ObjTerSimGet0Fanin0(pObj) )
+        Gia_ObjTerSimSet0( pObj );
+    else if ( Gia_ObjTerSimGet1Fanin0(pObj) )
+        Gia_ObjTerSimSet1( pObj );
+    else 
+        Gia_ObjTerSimSetX( pObj );
+}
+static inline void Gia_ObjTerSimRo( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    Gia_Obj_t * pTemp = Gia_ObjRoToRi(p, pObj);
+    assert( Gia_ObjIsRo(p, pObj) );
+    assert( !Gia_ObjTerSimGetC( pTemp ) );
+    pObj->fMark0 = pTemp->fMark0;
+    pObj->fMark1 = pTemp->fMark1;
+}
+
+static inline void Gia_ObjTerSimPrint( Gia_Obj_t * pObj )
+{
+    if ( Gia_ObjTerSimGet0(pObj) )
+        printf( "0" );
+    else if ( Gia_ObjTerSimGet1(pObj) )
+        printf( "1" );
+    else if ( Gia_ObjTerSimGetX(pObj) )
+        printf( "X" );
+}
+
+static inline int Gia_AigerReadInt( unsigned char * pPos )
+{
+    int i, Value = 0;
+    for ( i = 0; i < 4; i++ )
+        Value = (Value << 8) | *pPos++;
+    return Value;
+}
+static inline void Gia_AigerWriteInt( unsigned char * pPos, int Value )
+{
+    int i;
+    for ( i = 3; i >= 0; i-- )
+        *pPos++ = (Value >> (8*i)) & 255;
+}
+static inline unsigned Gia_AigerReadUnsigned( unsigned char ** ppPos )
+{
+    unsigned x = 0, i = 0;
+    unsigned char ch;
+    while ((ch = *(*ppPos)++) & 0x80)
+        x |= (ch & 0x7f) << (7 * i++);
+    return x | (ch << (7 * i));
+}
+static inline void Gia_AigerWriteUnsigned( Vec_Str_t * vStr, unsigned x )
+{
+    unsigned char ch;
+    while (x & ~0x7f)
+    {
+        ch = (x & 0x7f) | 0x80;
+        Vec_StrPush( vStr, ch );
+        x >>= 7;
+    }
+    ch = x;
+    Vec_StrPush( vStr, ch );
+}
+static inline void Gia_AigerWriteUnsignedFile( FILE * pFile, unsigned x )
+{
+    unsigned char ch;
+    while (x & ~0x7f)
+    {
+        ch = (x & 0x7f) | 0x80;
+        fputc( ch, pFile );
+        x >>= 7;
+    }
+    ch = x;
+    fputc( ch, pFile );
+}
+static inline int Gia_AigerWriteUnsignedBuffer( unsigned char * pBuffer, int Pos, unsigned x )
+{
+    unsigned char ch;
+    while (x & ~0x7f)
+    {
+        ch = (x & 0x7f) | 0x80;
+        pBuffer[Pos++] = ch;
+        x >>= 7;
+    }
+    ch = x;
+    pBuffer[Pos++] = ch;
+    return Pos;
+}
+
+static inline Gia_Obj_t * Gia_ObjReprObj( Gia_Man_t * p, int Id )            { return p->pReprs[Id].iRepr == GIA_VOID ? NULL : Gia_ManObj( p, p->pReprs[Id].iRepr );                  }
+static inline int         Gia_ObjRepr( Gia_Man_t * p, int Id )               { return p->pReprs[Id].iRepr;                                                }
+static inline void        Gia_ObjSetRepr( Gia_Man_t * p, int Id, int Num )   { assert( Num == GIA_VOID || Num < Id ); p->pReprs[Id].iRepr = Num;          }
+static inline void        Gia_ObjSetReprRev( Gia_Man_t * p, int Id, int Num ){ assert( Num == GIA_VOID || Num > Id ); p->pReprs[Id].iRepr = Num;          }
+static inline void        Gia_ObjUnsetRepr( Gia_Man_t * p, int Id )          { p->pReprs[Id].iRepr = GIA_VOID;                                            }
+static inline int         Gia_ObjHasRepr( Gia_Man_t * p, int Id )            { return p->pReprs[Id].iRepr != GIA_VOID;                                    }
+static inline int         Gia_ObjReprSelf( Gia_Man_t * p, int Id )           { return Gia_ObjHasRepr(p, Id) ? Gia_ObjRepr(p, Id) : Id;                    }
+static inline int         Gia_ObjSibl( Gia_Man_t * p, int Id )               { return p->pSibls ? p->pSibls[Id] : 0;                                      }
+static inline Gia_Obj_t * Gia_ObjSiblObj( Gia_Man_t * p, int Id )            { return (p->pSibls && p->pSibls[Id]) ? Gia_ManObj(p, p->pSibls[Id]) : NULL; }
+
+static inline int         Gia_ObjProved( Gia_Man_t * p, int Id )             { return p->pReprs[Id].fProved;       }
+static inline void        Gia_ObjSetProved( Gia_Man_t * p, int Id )          { p->pReprs[Id].fProved = 1;          }
+static inline void        Gia_ObjUnsetProved( Gia_Man_t * p, int Id )        { p->pReprs[Id].fProved = 0;          }
+
+static inline int         Gia_ObjFailed( Gia_Man_t * p, int Id )             { return p->pReprs[Id].fFailed;       }
+static inline void        Gia_ObjSetFailed( Gia_Man_t * p, int Id )          { p->pReprs[Id].fFailed = 1;          }
+
+static inline int         Gia_ObjColor( Gia_Man_t * p, int Id, int c )       { return c? p->pReprs[Id].fColorB : p->pReprs[Id].fColorA;          }
+static inline int         Gia_ObjColors( Gia_Man_t * p, int Id )             { return p->pReprs[Id].fColorB * 2 + p->pReprs[Id].fColorA;         }
+static inline void        Gia_ObjSetColor( Gia_Man_t * p, int Id, int c )    { if (c) p->pReprs[Id].fColorB = 1; else p->pReprs[Id].fColorA = 1; }
+static inline void        Gia_ObjSetColors( Gia_Man_t * p, int Id )          { p->pReprs[Id].fColorB = p->pReprs[Id].fColorA = 1;                }
+static inline int         Gia_ObjVisitColor( Gia_Man_t * p, int Id, int c )  { int x; if (c) { x = p->pReprs[Id].fColorB; p->pReprs[Id].fColorB = 1; } else { x = p->pReprs[Id].fColorA; p->pReprs[Id].fColorA = 1; } return x; }
+static inline int         Gia_ObjDiffColors( Gia_Man_t * p, int i, int j )   { return (p->pReprs[i].fColorA ^ p->pReprs[j].fColorA) && (p->pReprs[i].fColorB ^ p->pReprs[j].fColorB); }
+static inline int         Gia_ObjDiffColors2( Gia_Man_t * p, int i, int j )  { return (p->pReprs[i].fColorA ^ p->pReprs[j].fColorA) || (p->pReprs[i].fColorB ^ p->pReprs[j].fColorB); }
+
+static inline Gia_Obj_t * Gia_ObjNextObj( Gia_Man_t * p, int Id )            { return p->pNexts[Id] == 0 ? NULL : Gia_ManObj( p, p->pNexts[Id] );}
+static inline int         Gia_ObjNext( Gia_Man_t * p, int Id )               { return p->pNexts[Id];                                             }
+static inline void        Gia_ObjSetNext( Gia_Man_t * p, int Id, int Num )   { p->pNexts[Id] = Num;                                              }
+
+static inline int         Gia_ObjIsConst( Gia_Man_t * p, int Id )            { return Gia_ObjRepr(p, Id) == 0;                                   }
+static inline int         Gia_ObjIsHead( Gia_Man_t * p, int Id )             { return Gia_ObjRepr(p, Id) == GIA_VOID && Gia_ObjNext(p, Id) > 0;  }
+static inline int         Gia_ObjIsNone( Gia_Man_t * p, int Id )             { return Gia_ObjRepr(p, Id) == GIA_VOID && Gia_ObjNext(p, Id) == 0; }
+static inline int         Gia_ObjIsTail( Gia_Man_t * p, int Id )             { return (Gia_ObjRepr(p, Id) > 0 && Gia_ObjRepr(p, Id) != GIA_VOID) && Gia_ObjNext(p, Id) == 0;                  }
+static inline int         Gia_ObjIsClass( Gia_Man_t * p, int Id )            { return (Gia_ObjRepr(p, Id) > 0 && Gia_ObjRepr(p, Id) != GIA_VOID) || Gia_ObjNext(p, Id) > 0;                   }
+static inline int         Gia_ObjHasSameRepr( Gia_Man_t * p, int i, int k )  { assert( k ); return i? (Gia_ObjRepr(p, i) == Gia_ObjRepr(p, k) && Gia_ObjRepr(p, i) != GIA_VOID) : Gia_ObjRepr(p, k) == 0;  }
+static inline int         Gia_ObjIsFailedPair( Gia_Man_t * p, int i, int k ) { assert( k ); return i? (Gia_ObjFailed(p, i) || Gia_ObjFailed(p, k)) : Gia_ObjFailed(p, k);                     }
+static inline int         Gia_ClassIsPair( Gia_Man_t * p, int i )            { assert( Gia_ObjIsHead(p, i) ); assert( Gia_ObjNext(p, i) ); return Gia_ObjNext(p, Gia_ObjNext(p, i)) == 0;     }
+static inline void        Gia_ClassUndoPair( Gia_Man_t * p, int i )          { assert( Gia_ClassIsPair(p,i) ); Gia_ObjSetRepr(p, Gia_ObjNext(p, i), GIA_VOID); Gia_ObjSetNext(p, i, 0);       }
+
+#define Gia_ManForEachConst( p, i )                            \
+    for ( i = 1; i < Gia_ManObjNum(p); i++ ) if ( !Gia_ObjIsConst(p, i) ) {} else
+#define Gia_ManForEachClass( p, i )                            \
+    for ( i = 1; i < Gia_ManObjNum(p); i++ ) if ( !Gia_ObjIsHead(p, i) ) {} else
+#define Gia_ManForEachClassReverse( p, i )                     \
+    for ( i = Gia_ManObjNum(p) - 1; i > 0; i-- ) if ( !Gia_ObjIsHead(p, i) ) {} else
+#define Gia_ClassForEachObj( p, i, iObj )                      \
+    for ( assert(Gia_ObjIsHead(p, i)), iObj = i; iObj; iObj = Gia_ObjNext(p, iObj) )
+#define Gia_ClassForEachObj1( p, i, iObj )                     \
+    for ( assert(Gia_ObjIsHead(p, i)), iObj = Gia_ObjNext(p, i); iObj; iObj = Gia_ObjNext(p, iObj) )
+
+
+static inline int         Gia_ObjFoffsetId( Gia_Man_t * p, int Id )                { return Vec_IntEntry( p->vFanout, Id );                                 }
+static inline int         Gia_ObjFoffset( Gia_Man_t * p, Gia_Obj_t * pObj )        { return Gia_ObjFoffsetId( p, Gia_ObjId(p, pObj) );                      }
+static inline int         Gia_ObjFanoutNumId( Gia_Man_t * p, int Id )              { return Vec_IntEntry( p->vFanoutNums, Id );                             }
+static inline int         Gia_ObjFanoutNum( Gia_Man_t * p, Gia_Obj_t * pObj )      { return Gia_ObjFanoutNumId( p, Gia_ObjId(p, pObj) );                    }
+static inline int         Gia_ObjFanoutId( Gia_Man_t * p, int Id, int i )          { return Vec_IntEntry( p->vFanout, Gia_ObjFoffsetId(p, Id) + i );        }
+static inline Gia_Obj_t * Gia_ObjFanout0( Gia_Man_t * p, Gia_Obj_t * pObj )        { return Gia_ManObj( p, Gia_ObjFanoutId(p, Gia_ObjId(p, pObj), 0) );     }
+static inline Gia_Obj_t * Gia_ObjFanout( Gia_Man_t * p, Gia_Obj_t * pObj, int i )  { return Gia_ManObj( p, Gia_ObjFanoutId(p, Gia_ObjId(p, pObj), i) );     }
+static inline void        Gia_ObjSetFanout( Gia_Man_t * p, Gia_Obj_t * pObj, int i, Gia_Obj_t * pFan )   { Vec_IntWriteEntry( p->vFanout, Gia_ObjFoffset(p, pObj) + i, Gia_ObjId(p, pFan) ); }
+
+#define Gia_ObjForEachFanoutStatic( p, pObj, pFanout, i )      \
+    for ( i = 0; (i < Gia_ObjFanoutNum(p, pObj))   && (((pFanout) = Gia_ObjFanout(p, pObj, i)), 1); i++ )
+#define Gia_ObjForEachFanoutStaticId( p, Id, FanId, i )      \
+    for ( i = 0; (i < Gia_ObjFanoutNumId(p, Id))   && (((FanId) = Gia_ObjFanoutId(p, Id, i)), 1); i++ )
+
+static inline int         Gia_ManHasMapping( Gia_Man_t * p )                { return p->vMapping != NULL;                                                   }
+static inline int         Gia_ObjIsLut( Gia_Man_t * p, int Id )             { return Vec_IntEntry(p->vMapping, Id) != 0;                                    }
+static inline int         Gia_ObjLutSize( Gia_Man_t * p, int Id )           { return Vec_IntEntry(p->vMapping, Vec_IntEntry(p->vMapping, Id));              }
+static inline int *       Gia_ObjLutFanins( Gia_Man_t * p, int Id )         { return Vec_IntEntryP(p->vMapping, Vec_IntEntry(p->vMapping, Id)) + 1;         }
+static inline int         Gia_ObjLutFanin( Gia_Man_t * p, int Id, int i )   { return Gia_ObjLutFanins(p, Id)[i];                                            }
+static inline int         Gia_ObjLutIsMux( Gia_Man_t * p, int Id )          { return (int)(Gia_ObjLutFanins(p, Id)[Gia_ObjLutSize(p, Id)] == -Id);          }
+
+static inline int         Gia_ManHasCellMapping( Gia_Man_t * p )            { return p->vCellMapping != NULL;                                               }
+static inline int         Gia_ObjIsCell( Gia_Man_t * p, int iLit )          { return Vec_IntEntry(p->vCellMapping, iLit) != 0;                              }
+static inline int         Gia_ObjCellSize( Gia_Man_t * p, int iLit )        { return Vec_IntEntry(p->vCellMapping, Vec_IntEntry(p->vCellMapping, iLit));    }
+static inline int *       Gia_ObjCellFanins( Gia_Man_t * p, int iLit )      { return Vec_IntEntryP(p->vCellMapping, Vec_IntEntry(p->vCellMapping, iLit))+1; }
+static inline int         Gia_ObjCellFanin( Gia_Man_t * p, int iLit, int i ){ return Gia_ObjCellFanins(p, iLit)[i];                                         }
+static inline int         Gia_ObjCellId( Gia_Man_t * p, int iLit )          { return Gia_ObjCellFanins(p, iLit)[Gia_ObjCellSize(p, iLit)];                  }
+
+#define Gia_ManForEachLut( p, i )                                       \
+    for ( i = 1; i < Gia_ManObjNum(p); i++ ) if ( !Gia_ObjIsLut(p, i) ) {} else
+#define Gia_LutForEachFanin( p, i, iFan, k )                            \
+    for ( k = 0; k < Gia_ObjLutSize(p,i) && ((iFan = Gia_ObjLutFanins(p,i)[k]),1); k++ )
+#define Gia_LutForEachFaninObj( p, i, pFanin, k )                       \
+    for ( k = 0; k < Gia_ObjLutSize(p,i) && ((pFanin = Gia_ManObj(p, Gia_ObjLutFanins(p,i)[k])),1); k++ )
+
+#define Gia_ManForEachCell( p, i )                                      \
+    for ( i = 2; i < 2*Gia_ManObjNum(p); i++ ) if ( !Gia_ObjIsCell(p, i) ) {} else
+#define Gia_CellForEachFanin( p, i, iFanLit, k )                        \
+    for ( k = 0; k < Gia_ObjCellSize(p,i) && ((iFanLit = Gia_ObjCellFanins(p,i)[k]),1); k++ )
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define Gia_ManForEachObj( p, pObj, i )                                 \
+    for ( i = 0; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ )
+#define Gia_ManForEachObj1( p, pObj, i )                                \
+    for ( i = 1; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ )
+#define Gia_ManForEachObjVec( vVec, p, pObj, i )                        \
+    for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i++ )
+#define Gia_ManForEachObjVecReverse( vVec, p, pObj, i )                        \
+    for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i-- )
+#define Gia_ManForEachObjVecLit( vVec, p, pObj, fCompl, i )             \
+    for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManObj(p, Abc_Lit2Var(Vec_IntEntry(vVec,i)))) && (((fCompl) = Abc_LitIsCompl(Vec_IntEntry(vVec,i))),1); i++ )
+#define Gia_ManForEachObjReverse( p, pObj, i )                          \
+    for ( i = p->nObjs - 1; (i >= 0) && ((pObj) = Gia_ManObj(p, i)); i-- )
+#define Gia_ManForEachObjReverse1( p, pObj, i )                         \
+    for ( i = p->nObjs - 1; (i > 0) && ((pObj) = Gia_ManObj(p, i)); i-- )
+#define Gia_ManForEachAnd( p, pObj, i )                                 \
+    for ( i = 0; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ )      if ( !Gia_ObjIsAnd(pObj) ) {} else
+#define Gia_ManForEachAndId( p, i )                                     \
+    for ( i = 0; (i < p->nObjs); i++ )                                     if ( !Gia_ObjIsAnd(Gia_ManObj(p, i)) ) {} else
+#define Gia_ManForEachMuxId( p, i )                                     \
+    for ( i = 0; (i < p->nObjs); i++ )                                     if ( !Gia_ObjIsMuxId(p, i) ) {} else
+#define Gia_ManForEachCand( p, pObj, i )                                \
+    for ( i = 0; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ )      if ( !Gia_ObjIsCand(pObj) ) {} else
+#define Gia_ManForEachAndReverse( p, pObj, i )                          \
+    for ( i = p->nObjs - 1; (i > 0) && ((pObj) = Gia_ManObj(p, i)); i-- )  if ( !Gia_ObjIsAnd(pObj) ) {} else
+#define Gia_ManForEachAndReverseId( p, i )                              \
+    for ( i = p->nObjs - 1; (i > 0); i-- )                                 if ( !Gia_ObjIsAnd(Gia_ManObj(p, i)) ) {} else
+#define Gia_ManForEachMux( p, pObj, i )                                 \
+    for ( i = 0; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ )      if ( !Gia_ObjIsMuxId(p, i) ) {} else
+#define Gia_ManForEachCi( p, pObj, i )                                  \
+    for ( i = 0; (i < Vec_IntSize(p->vCis)) && ((pObj) = Gia_ManCi(p, i)); i++ )
+#define Gia_ManForEachCiId( p, Id, i )                                  \
+    for ( i = 0; (i < Vec_IntSize(p->vCis)) && ((Id) = Gia_ObjId(p, Gia_ManCi(p, i))); i++ )
+#define Gia_ManForEachCiReverse( p, pObj, i )                           \
+    for ( i = Vec_IntSize(p->vCis) - 1; (i >= 0) && ((pObj) = Gia_ManCi(p, i)); i-- )
+#define Gia_ManForEachCo( p, pObj, i )                                  \
+    for ( i = 0; (i < Vec_IntSize(p->vCos)) && ((pObj) = Gia_ManCo(p, i)); i++ )
+#define Gia_ManForEachCoVec( vVec, p, pObj, i )                         \
+    for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManCo(p, Vec_IntEntry(vVec,i))); i++ )
+#define Gia_ManForEachCoId( p, Id, i )                                  \
+    for ( i = 0; (i < Vec_IntSize(p->vCos)) && ((Id) = Gia_ObjId(p, Gia_ManCo(p, i))); i++ )
+#define Gia_ManForEachCoReverse( p, pObj, i )                           \
+    for ( i = Vec_IntSize(p->vCos) - 1; (i >= 0) && ((pObj) = Gia_ManCo(p, i)); i-- )
+#define Gia_ManForEachCoDriver( p, pObj, i )                            \
+    for ( i = 0; (i < Vec_IntSize(p->vCos)) && ((pObj) = Gia_ObjFanin0(Gia_ManCo(p, i))); i++ )
+#define Gia_ManForEachCoDriverId( p, DriverId, i )                      \
+    for ( i = 0; (i < Vec_IntSize(p->vCos)) && (((DriverId) = Gia_ObjFaninId0p(p, Gia_ManCo(p, i))), 1); i++ )
+#define Gia_ManForEachPi( p, pObj, i )                                  \
+    for ( i = 0; (i < Gia_ManPiNum(p)) && ((pObj) = Gia_ManCi(p, i)); i++ )
+#define Gia_ManForEachPo( p, pObj, i )                                  \
+    for ( i = 0; (i < Gia_ManPoNum(p)) && ((pObj) = Gia_ManCo(p, i)); i++ )
+#define Gia_ManForEachRo( p, pObj, i )                                  \
+    for ( i = 0; (i < Gia_ManRegNum(p)) && ((pObj) = Gia_ManCi(p, Gia_ManPiNum(p)+i)); i++ )
+#define Gia_ManForEachRi( p, pObj, i )                                  \
+    for ( i = 0; (i < Gia_ManRegNum(p)) && ((pObj) = Gia_ManCo(p, Gia_ManPoNum(p)+i)); i++ )
+#define Gia_ManForEachRiRo( p, pObjRi, pObjRo, i )                      \
+    for ( i = 0; (i < Gia_ManRegNum(p)) && ((pObjRi) = Gia_ManCo(p, Gia_ManPoNum(p)+i)) && ((pObjRo) = Gia_ManCi(p, Gia_ManPiNum(p)+i)); i++ )
+ 
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== giaAiger.c ===========================================================*/
+extern int                 Gia_FileSize( char * pFileName );
+extern Gia_Man_t *         Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fSkipStrash, int fCheck );
+extern Gia_Man_t *         Gia_AigerRead( char * pFileName, int fSkipStrash, int fCheck );
+extern void                Gia_AigerWrite( Gia_Man_t * p, char * pFileName, int fWriteSymbols, int fCompact );
+extern void                Gia_DumpAiger( Gia_Man_t * p, char * pFilePrefix, int iFileNum, int nFileNumDigits );
+extern Vec_Str_t *         Gia_AigerWriteIntoMemoryStr( Gia_Man_t * p );
+extern Vec_Str_t *         Gia_AigerWriteIntoMemoryStrPart( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, int nRegs );
+extern void                Gia_AigerWriteSimple( Gia_Man_t * pInit, char * pFileName );
+/*=== giaBalance.c ===========================================================*/
+extern Gia_Man_t *         Gia_ManBalance( Gia_Man_t * p, int fSimpleAnd, int fVerbose );
+extern Gia_Man_t *         Gia_ManAreaBalance( Gia_Man_t * p, int fSimpleAnd, int nNewNodesMax, int fVerbose, int fVeryVerbose );
+extern Gia_Man_t *         Gia_ManAigSyn2( Gia_Man_t * p, int fOldAlgo, int fCoarsen, int fCutMin, int nRelaxRatio, int fVerbose, int fVeryVerbose );
+extern Gia_Man_t *         Gia_ManAigSyn3( Gia_Man_t * p, int fVerbose, int fVeryVerbose );
+extern Gia_Man_t *         Gia_ManAigSyn4( Gia_Man_t * p, int fVerbose, int fVeryVerbose );
+/*=== giaBidec.c ===========================================================*/
+extern unsigned *          Gia_ManConvertAigToTruth( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vTruth, Vec_Int_t * vVisited );
+extern Gia_Man_t *         Gia_ManPerformBidec( Gia_Man_t * p, int fVerbose );
+/*=== giaCex.c ============================================================*/
+extern int                 Gia_ManVerifyCex( Gia_Man_t * pAig, Abc_Cex_t * p, int fDualOut );
+extern int                 Gia_ManFindFailedPoCex( Gia_Man_t * pAig, Abc_Cex_t * p, int nOutputs );
+extern int                 Gia_ManSetFailedPoCex( Gia_Man_t * pAig, Abc_Cex_t * p );
+extern void                Gia_ManCounterExampleValueStart( Gia_Man_t * pGia, Abc_Cex_t * pCex );
+extern void                Gia_ManCounterExampleValueStop( Gia_Man_t * pGia );
+extern int                 Gia_ManCounterExampleValueLookup( Gia_Man_t * pGia, int Id, int iFrame );
+extern Abc_Cex_t *         Gia_ManCexExtendToIncludeCurrentStates( Gia_Man_t * p, Abc_Cex_t * pCex );
+extern Abc_Cex_t *         Gia_ManCexExtendToIncludeAllObjects( Gia_Man_t * p, Abc_Cex_t * pCex );
+/*=== giaCsatOld.c ============================================================*/
+extern Vec_Int_t *         Cbs_ManSolveMiter( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int fVerbose );
+/*=== giaCsat.c ============================================================*/
+extern Vec_Int_t *         Cbs_ManSolveMiterNc( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int fVerbose );
+/*=== giaCTas.c ============================================================*/
+extern Vec_Int_t *         Tas_ManSolveMiterNc( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int fVerbose );
+/*=== giaCof.c =============================================================*/
+extern void                Gia_ManPrintFanio( Gia_Man_t * pGia, int nNodes );
+extern Gia_Man_t *         Gia_ManDupCof( Gia_Man_t * p, int iVar );
+extern Gia_Man_t *         Gia_ManDupCofAllInt( Gia_Man_t * p, Vec_Int_t * vSigs, int fVerbose );
+extern Gia_Man_t *         Gia_ManDupCofAll( Gia_Man_t * p, int nFanLim, int fVerbose );
+/*=== giaDfs.c ============================================================*/
+extern void                Gia_ManCollectCis( Gia_Man_t * p, int * pNodes, int nNodes, Vec_Int_t * vSupp );
+extern void                Gia_ManCollectAnds( Gia_Man_t * p, int * pNodes, int nNodes, Vec_Int_t * vNodes );
+extern Vec_Int_t *         Gia_ManCollectNodesCis( Gia_Man_t * p, int * pNodes, int nNodes );
+extern int                 Gia_ManSuppSize( Gia_Man_t * p, int * pNodes, int nNodes );
+extern int                 Gia_ManConeSize( Gia_Man_t * p, int * pNodes, int nNodes );
+extern Vec_Vec_t *         Gia_ManLevelize( Gia_Man_t * p );
+extern Vec_Int_t *         Gia_ManOrderReverse( Gia_Man_t * p );
+/*=== giaDup.c ============================================================*/
+extern void                Gia_ManDupRemapEquiv( Gia_Man_t * pNew, Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManDupOrderDfs( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManDupOrderDfsChoices( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManDupOrderDfsReverse( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManDupOutputGroup( Gia_Man_t * p, int iOutStart, int iOutStop );
+extern Gia_Man_t *         Gia_ManDupOutputVec( Gia_Man_t * p, Vec_Int_t * vOutPres );
+extern Gia_Man_t *         Gia_ManDupOrderAiger( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManDupLastPis( Gia_Man_t * p, int nLastPis );
+extern Gia_Man_t *         Gia_ManDupFlip( Gia_Man_t * p, int * pInitState );
+extern Gia_Man_t *         Gia_ManDupCycled( Gia_Man_t * pAig, Abc_Cex_t * pCex, int nFrames );
+extern Gia_Man_t *         Gia_ManDup( Gia_Man_t * p );  
+extern Gia_Man_t *         Gia_ManDupZero( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManDupPerm( Gia_Man_t * p, Vec_Int_t * vPiPerm );
+extern Gia_Man_t *         Gia_ManDupPermFlop( Gia_Man_t * p, Vec_Int_t * vFfPerm );
+extern Gia_Man_t *         Gia_ManDupPermFlopGap( Gia_Man_t * p, Vec_Int_t * vFfPerm );
+extern void                Gia_ManDupAppend( Gia_Man_t * p, Gia_Man_t * pTwo );
+extern void                Gia_ManDupAppendShare( Gia_Man_t * p, Gia_Man_t * pTwo );
+extern Gia_Man_t *         Gia_ManDupAppendNew( Gia_Man_t * pOne, Gia_Man_t * pTwo );
+extern Gia_Man_t *         Gia_ManDupAppendCones( Gia_Man_t * p, Gia_Man_t ** ppCones, int nCones, int fOnlyRegs );
+extern Gia_Man_t *         Gia_ManDupSelf( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManDupFlopClass( Gia_Man_t * p, int iClass );
+extern Gia_Man_t *         Gia_ManDupMarked( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManDupTimes( Gia_Man_t * p, int nTimes );  
+extern Gia_Man_t *         Gia_ManDupDfs( Gia_Man_t * p );  
+extern Gia_Man_t *         Gia_ManDupCofactorVar( Gia_Man_t * p, int iVar, int Value );  
+extern Gia_Man_t *         Gia_ManDupCofactorObj( Gia_Man_t * p, int iObj, int Value );  
+extern Gia_Man_t *         Gia_ManDupExist( Gia_Man_t * p, int iVar );
+extern Gia_Man_t *         Gia_ManDupDfsSkip( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManDupDfsCone( Gia_Man_t * p, Gia_Obj_t * pObj );
+extern Gia_Man_t *         Gia_ManDupDfsNode( Gia_Man_t * p, Gia_Obj_t * pObj );
+extern Gia_Man_t *         Gia_ManDupDfsLitArray( Gia_Man_t * p, Vec_Int_t * vLits );
+extern Gia_Man_t *         Gia_ManDupTrimmed( Gia_Man_t * p, int fTrimCis, int fTrimCos, int fDualOut, int OutValue );
+extern Gia_Man_t *         Gia_ManDupOntop( Gia_Man_t * p, Gia_Man_t * p2 );
+extern Gia_Man_t *         Gia_ManDupWithNewPo( Gia_Man_t * p1, Gia_Man_t * p2 );
+extern Gia_Man_t *         Gia_ManDupDfsCiMap( Gia_Man_t * p, int * pCi2Lit, Vec_Int_t * vLits );
+extern Gia_Man_t *         Gia_ManDupDfsClasses( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManDupTopAnd( Gia_Man_t * p, int fVerbose );
+extern Gia_Man_t *         Gia_ManMiter( Gia_Man_t * pAig0, Gia_Man_t * pAig1, int nInsDup, int fDualOut, int fSeq, int fImplic, int fVerbose );
+extern Gia_Man_t *         Gia_ManDupAndOr( Gia_Man_t * p, int nOuts, int fUseOr, int fCompl );
+extern Gia_Man_t *         Gia_ManDupZeroUndc( Gia_Man_t * p, char * pInit, int fVerbose );
+extern Gia_Man_t *         Gia_ManMiter2( Gia_Man_t * p, char * pInit, int fVerbose );
+extern Gia_Man_t *         Gia_ManTransformMiter( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManChoiceMiter( Vec_Ptr_t * vGias );
+extern Gia_Man_t *         Gia_ManDupWithConstraints( Gia_Man_t * p, Vec_Int_t * vPoTypes );
+extern Gia_Man_t *         Gia_ManDupCones( Gia_Man_t * p, int * pPos, int nPos, int fTrimPis );
+extern Gia_Man_t *         Gia_ManDupOneHot( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManDupLevelized( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManDupFromVecs( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, int nRegs );
+extern Gia_Man_t *         Gia_ManDupSliced( Gia_Man_t * p, int nSuppMax );
+/*=== giaEnable.c ==========================================================*/
+extern void                Gia_ManDetectSeqSignals( Gia_Man_t * p, int fSetReset, int fVerbose );
+extern Gia_Man_t *         Gia_ManUnrollAndCofactor( Gia_Man_t * p, int nFrames, int nFanMax, int fVerbose );
+extern Gia_Man_t *         Gia_ManRemoveEnables( Gia_Man_t * p );
+/*=== giaEquiv.c ==========================================================*/
+extern void                Gia_ManEquivFixOutputPairs( Gia_Man_t * p );
+extern int                 Gia_ManCheckTopoOrder( Gia_Man_t * p );
+extern int *               Gia_ManDeriveNexts( Gia_Man_t * p );
+extern void                Gia_ManDeriveReprs( Gia_Man_t * p );
+extern int                 Gia_ManEquivCountLits( Gia_Man_t * p );
+extern int                 Gia_ManEquivCountLitsAll( Gia_Man_t * p );
+extern int                 Gia_ManEquivCountClasses( Gia_Man_t * p );
+extern void                Gia_ManEquivPrintOne( Gia_Man_t * p, int i, int Counter );
+extern void                Gia_ManEquivPrintClasses( Gia_Man_t * p, int fVerbose, float Mem );
+extern Gia_Man_t *         Gia_ManEquivReduce( Gia_Man_t * p, int fUseAll, int fDualOut, int fSkipPhase, int fVerbose );
+extern Gia_Man_t *         Gia_ManEquivReduceAndRemap( Gia_Man_t * p, int fSeq, int fMiterPairs );
+extern int                 Gia_ManEquivSetColors( Gia_Man_t * p, int fVerbose );
+extern Gia_Man_t *         Gia_ManSpecReduce( Gia_Man_t * p, int fDualOut, int fSynthesis, int fReduce, int fSkipSome, int fVerbose );
+extern Gia_Man_t *         Gia_ManSpecReduceInit( Gia_Man_t * p, Abc_Cex_t * pInit, int nFrames, int fDualOut );
+extern Gia_Man_t *         Gia_ManSpecReduceInitFrames( Gia_Man_t * p, Abc_Cex_t * pInit, int nFramesMax, int * pnFrames, int fDualOut, int nMinOutputs );
+extern void                Gia_ManEquivTransform( Gia_Man_t * p, int fVerbose );
+extern void                Gia_ManEquivImprove( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManEquivToChoices( Gia_Man_t * p, int nSnapshots );
+extern int                 Gia_ManCountChoiceNodes( Gia_Man_t * p );
+extern int                 Gia_ManCountChoices( Gia_Man_t * p );
+extern int                 Gia_ManFilterEquivsForSpeculation( Gia_Man_t * pGia, char * pName1, char * pName2, int fLatchA, int fLatchB );
+extern int                 Gia_ManFilterEquivsUsingParts( Gia_Man_t * pGia, char * pName1, char * pName2 );
+extern void                Gia_ManFilterEquivsUsingLatches( Gia_Man_t * pGia, int fFlopsOnly, int fFlopsWith );
+/*=== giaFanout.c =========================================================*/
+extern void                Gia_ObjAddFanout( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanout );
+extern void                Gia_ObjRemoveFanout( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanout );
+extern void                Gia_ManFanoutStart( Gia_Man_t * p );
+extern void                Gia_ManFanoutStop( Gia_Man_t * p );
+extern void                Gia_ManStaticFanoutStart( Gia_Man_t * p );
+extern void                Gia_ManStaticFanoutStop( Gia_Man_t * p );
+/*=== giaForce.c =========================================================*/
+extern void                For_ManExperiment( Gia_Man_t * pGia, int nIters, int fClustered, int fVerbose );
+/*=== giaFrames.c =========================================================*/
+extern Gia_Man_t *         Gia_ManUnrollDup( Gia_Man_t * p, Vec_Int_t * vLimit );
+extern Vec_Ptr_t *         Gia_ManUnrollAbs( Gia_Man_t * p, int nFrames );
+extern void *              Gia_ManUnrollStart( Gia_Man_t * pAig, Gia_ParFra_t * pPars );
+extern void *              Gia_ManUnrollAdd( void * pMan, int fMax );
+extern void                Gia_ManUnrollStop( void * pMan );
+extern int                 Gia_ManUnrollLastLit( void * pMan );
+extern void                Gia_ManFraSetDefaultParams( Gia_ParFra_t * p );
+extern Gia_Man_t *         Gia_ManFrames( Gia_Man_t * pAig, Gia_ParFra_t * pPars );  
+extern Gia_Man_t *         Gia_ManFramesInitSpecial( Gia_Man_t * pAig, int nFrames, int fVerbose );
+/*=== giaFront.c ==========================================================*/
+extern Gia_Man_t *         Gia_ManFront( Gia_Man_t * p );
+extern void                Gia_ManFrontTest( Gia_Man_t * p );
+/*=== giaFx.c ==========================================================*/
+extern Gia_Man_t *         Gia_ManPerformFx( Gia_Man_t * p, int nNewNodesMax, int LitCountMax, int fReverse, int fVerbose, int fVeryVerbose );
+/*=== giaHash.c ===========================================================*/
+extern void                Gia_ManHashAlloc( Gia_Man_t * p ); 
+extern void                Gia_ManHashStart( Gia_Man_t * p ); 
+extern void                Gia_ManHashStop( Gia_Man_t * p );
+extern int                 Gia_ManHashXorReal( Gia_Man_t * p, int iLit0, int iLit1 );
+extern int                 Gia_ManHashMuxReal( Gia_Man_t * p, int iLitC, int iLit1, int iLit0 );
+extern int                 Gia_ManHashAnd( Gia_Man_t * p, int iLit0, int iLit1 ); 
+extern int                 Gia_ManHashOr( Gia_Man_t * p, int iLit0, int iLit1 ); 
+extern int                 Gia_ManHashXor( Gia_Man_t * p, int iLit0, int iLit1 ); 
+extern int                 Gia_ManHashMux( Gia_Man_t * p, int iCtrl, int iData1, int iData0 );
+extern int                 Gia_ManHashAndTry( Gia_Man_t * p, int iLit0, int iLit1 );
+extern Gia_Man_t *         Gia_ManRehash( Gia_Man_t * p, int fAddStrash );
+extern void                Gia_ManHashProfile( Gia_Man_t * p );
+extern int                 Gia_ManHashLookup( Gia_Man_t * p, Gia_Obj_t * p0, Gia_Obj_t * p1 );
+extern int                 Gia_ManHashAndMulti( Gia_Man_t * p, Vec_Int_t * vLits );
+/*=== giaIf.c ===========================================================*/
+extern void                Gia_ManPrintMappingStats( Gia_Man_t * p, char * pDumpFile );
+extern void                Gia_ManPrintPackingStats( Gia_Man_t * p );
+extern void                Gia_ManPrintLutStats( Gia_Man_t * p );
+extern int                 Gia_ManLutFaninCount( Gia_Man_t * p );
+extern int                 Gia_ManLutSizeMax( Gia_Man_t * p );
+extern int                 Gia_ManLutNum( Gia_Man_t * p );
+extern int                 Gia_ManLutLevel( Gia_Man_t * p );
+extern void                Gia_ManSetRefsMapped( Gia_Man_t * p );
+extern void                Gia_ManSetIfParsDefault( void * pIfPars );
+extern void                Gia_ManMappingVerify( Gia_Man_t * p );
+extern void                Gia_ManTransferMapping( Gia_Man_t * pGia, Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManPerformMapping( Gia_Man_t * p, void * pIfPars, int fNormalized );
+extern Gia_Man_t *         Gia_ManPerformSopBalance( Gia_Man_t * p, int nCutNum, int nRelaxRatio, int fVerbose );
+/*=== giaJf.c ===========================================================*/
+extern void                Jf_ManSetDefaultPars( Jf_Par_t * pPars );
+extern Gia_Man_t *         Jf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars );
+extern Gia_Man_t *         Jf_ManDeriveCnf( Gia_Man_t * p, int fCnfObjIds );
+/*=== giaIso.c ===========================================================*/
+extern Gia_Man_t *         Gia_ManIsoCanonicize( Gia_Man_t * p, int fVerbose );
+extern Gia_Man_t *         Gia_ManIsoReduce( Gia_Man_t * p, Vec_Ptr_t ** pvPosEquivs, Vec_Ptr_t ** pvPiPerms, int fEstimate, int fDualOut, int fVerbose, int fVeryVerbose );
+extern Gia_Man_t *         Gia_ManIsoReduce2( Gia_Man_t * p, Vec_Ptr_t ** pvPosEquivs, Vec_Ptr_t ** pvPiPerms, int fEstimate, int fBetterQual, int fDualOut, int fVerbose, int fVeryVerbose );
+/*=== giaLf.c ===========================================================*/
+extern void                Lf_ManSetDefaultPars( Jf_Par_t * pPars );
+extern Gia_Man_t *         Lf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars );
+extern Gia_Man_t *         Gia_ManPerformLfMapping( Gia_Man_t * p, Jf_Par_t * pPars, int fNormalized );
+/*=== giaLogic.c ===========================================================*/
+extern void                Gia_ManTestDistance( Gia_Man_t * p );
+extern void                Gia_ManSolveProblem( Gia_Man_t * pGia, Emb_Par_t * pPars );
+ /*=== giaMan.c ===========================================================*/
+extern Gia_Man_t *         Gia_ManStart( int nObjsMax ); 
+extern void                Gia_ManStop( Gia_Man_t * p );  
+extern void                Gia_ManStopP( Gia_Man_t ** p );  
+extern double              Gia_ManMemory( Gia_Man_t * p );
+extern void                Gia_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars ); 
+extern void                Gia_ManPrintStatsShort( Gia_Man_t * p ); 
+extern void                Gia_ManPrintMiterStatus( Gia_Man_t * p ); 
+extern void                Gia_ManPrintStatsMiter( Gia_Man_t * p, int fVerbose );
+extern void                Gia_ManSetRegNum( Gia_Man_t * p, int nRegs );
+extern void                Gia_ManReportImprovement( Gia_Man_t * p, Gia_Man_t * pNew );
+extern void                Gia_ManPrintNpnClasses( Gia_Man_t * p );
+/*=== giaMem.c ===========================================================*/
+extern Gia_MmFixed_t *     Gia_MmFixedStart( int nEntrySize, int nEntriesMax );
+extern void                Gia_MmFixedStop( Gia_MmFixed_t * p, int fVerbose );
+extern char *              Gia_MmFixedEntryFetch( Gia_MmFixed_t * p );
+extern void                Gia_MmFixedEntryRecycle( Gia_MmFixed_t * p, char * pEntry );
+extern void                Gia_MmFixedRestart( Gia_MmFixed_t * p );
+extern int                 Gia_MmFixedReadMemUsage( Gia_MmFixed_t * p );
+extern int                 Gia_MmFixedReadMaxEntriesUsed( Gia_MmFixed_t * p );
+extern Gia_MmFlex_t *      Gia_MmFlexStart();
+extern void                Gia_MmFlexStop( Gia_MmFlex_t * p, int fVerbose );
+extern char *              Gia_MmFlexEntryFetch( Gia_MmFlex_t * p, int nBytes );
+extern void                Gia_MmFlexRestart( Gia_MmFlex_t * p );
+extern int                 Gia_MmFlexReadMemUsage( Gia_MmFlex_t * p );
+extern Gia_MmStep_t *      Gia_MmStepStart( int nSteps );
+extern void                Gia_MmStepStop( Gia_MmStep_t * p, int fVerbose );
+extern char *              Gia_MmStepEntryFetch( Gia_MmStep_t * p, int nBytes );
+extern void                Gia_MmStepEntryRecycle( Gia_MmStep_t * p, char * pEntry, int nBytes );
+extern int                 Gia_MmStepReadMemUsage( Gia_MmStep_t * p );
+/*=== giaMf.c ===========================================================*/
+extern void                Mf_ManSetDefaultPars( Jf_Par_t * pPars );
+extern Gia_Man_t *         Mf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars );
+/*=== giaMini.c ===========================================================*/
+extern Gia_Man_t *         Gia_ManReadMiniAig( char * pFileName );
+extern void                Gia_ManWriteMiniAig( Gia_Man_t * pGia, char * pFileName );
+/*=== giaMuxes.c ===========================================================*/
+extern void                Gia_ManCountMuxXor( Gia_Man_t * p, int * pnMuxes, int * pnXors );
+extern void                Gia_ManPrintMuxStats( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManDupMuxes( Gia_Man_t * p, int Limit );
+extern Gia_Man_t *         Gia_ManDupNoMuxes( Gia_Man_t * p );
+/*=== giaPat.c ===========================================================*/
+extern void                Gia_SatVerifyPattern( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vCex, Vec_Int_t * vVisit );
+/*=== giaRetime.c ===========================================================*/
+extern Gia_Man_t *         Gia_ManRetimeForward( Gia_Man_t * p, int nMaxIters, int fVerbose );
+/*=== giaSat.c ============================================================*/
+extern int                 Sat_ManTest( Gia_Man_t * pGia, Gia_Obj_t * pObj, int nConfsMax );
+/*=== giaScl.c ============================================================*/
+extern int                 Gia_ManSeqMarkUsed( Gia_Man_t * p );
+extern int                 Gia_ManCombMarkUsed( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManCleanup( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManCleanupOutputs( Gia_Man_t * p, int nOutputs );
+extern Gia_Man_t *         Gia_ManSeqCleanup( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManSeqStructSweep( Gia_Man_t * p, int fConst, int fEquiv, int fVerbose );
+/*=== giaShrink.c ===========================================================*/
+extern Gia_Man_t *         Gia_ManMapShrink4( Gia_Man_t * p, int fKeepLevel, int fVerbose );
+extern Gia_Man_t *         Gia_ManMapShrink6( Gia_Man_t * p, int nFanoutMax, int fKeepLevel, int fVerbose );
+/*=== giaSopb.c ============================================================*/
+extern Gia_Man_t *         Gia_ManPerformSopBalanceWin( Gia_Man_t * p, int LevelMax, int nLevelRatio, int nCutNum, int nRelaxRatio, int fVerbose );
+/*=== giaSort.c ============================================================*/
+extern int *               Gia_SortFloats( float * pArray, int * pPerm, int nSize );
+/*=== giaSim.c ============================================================*/
+extern void                Gia_ManSimSetDefaultParams( Gia_ParSim_t * p );
+extern int                 Gia_ManSimSimulate( Gia_Man_t * pAig, Gia_ParSim_t * pPars );
+/*=== giaSpeedup.c ============================================================*/
+extern float               Gia_ManDelayTraceLut( Gia_Man_t * p );
+extern float               Gia_ManDelayTraceLutPrint( Gia_Man_t * p, int fVerbose );
+extern Gia_Man_t *         Gia_ManSpeedup( Gia_Man_t * p, int Percentage, int Degree, int fVerbose, int fVeryVerbose );
+/*=== giaStg.c ============================================================*/
+extern void                Gia_ManStgPrint( FILE * pFile, Vec_Int_t * vLines, int nIns, int nOuts, int nStates );
+extern Gia_Man_t *         Gia_ManStgRead( char * pFileName, int kHot, int fVerbose );
+/*=== giaSweep.c ============================================================*/
+extern Gia_Man_t *         Gia_ManFraigSweep( Gia_Man_t * p, void * pPars );
+/*=== giaSweeper.c ============================================================*/
+extern Gia_Man_t *         Gia_SweeperStart( Gia_Man_t * p );
+extern void                Gia_SweeperStop( Gia_Man_t * p );
+extern int                 Gia_SweeperIsRunning( Gia_Man_t * p );
+extern void                Gia_SweeperPrintStats( Gia_Man_t * p );
+extern void                Gia_SweeperSetConflictLimit( Gia_Man_t * p, int nConfMax );
+extern void                Gia_SweeperSetRuntimeLimit( Gia_Man_t * p, int nSeconds );
+extern Vec_Int_t *         Gia_SweeperGetCex( Gia_Man_t * p );
+extern int                 Gia_SweeperProbeCreate( Gia_Man_t * p, int iLit );
+extern int                 Gia_SweeperProbeDelete( Gia_Man_t * p, int ProbeId );
+extern int                 Gia_SweeperProbeUpdate( Gia_Man_t * p, int ProbeId, int iLitNew );
+extern int                 Gia_SweeperProbeLit( Gia_Man_t * p, int ProbeId );
+extern Vec_Int_t *         Gia_SweeperCollectValidProbeIds( Gia_Man_t * p );
+extern int                 Gia_SweeperCondPop( Gia_Man_t * p );
+extern void                Gia_SweeperCondPush( Gia_Man_t * p, int ProbeId );
+extern Vec_Int_t *         Gia_SweeperCondVector( Gia_Man_t * p );
+extern int                 Gia_SweeperCondCheckUnsat( Gia_Man_t * p );
+extern int                 Gia_SweeperCheckEquiv( Gia_Man_t * p, int ProbeId1, int ProbeId2 );
+extern Gia_Man_t *         Gia_SweeperExtractUserLogic( Gia_Man_t * p, Vec_Int_t * vProbeIds, Vec_Ptr_t * vInNames, Vec_Ptr_t * vOutNames );
+extern void                Gia_SweeperLogicDump( Gia_Man_t * p, Vec_Int_t * vProbeIds, int fDumpConds, char * pFileName );
+extern Gia_Man_t *         Gia_SweeperCleanup( Gia_Man_t * p, char * pCommLime );
+extern Vec_Int_t *         Gia_SweeperGraft( Gia_Man_t * pDst, Vec_Int_t * vProbes, Gia_Man_t * pSrc );
+extern int                 Gia_SweeperFraig( Gia_Man_t * p, Vec_Int_t * vProbeIds, char * pCommLime, int nWords, int nConfs, int fVerify, int fVerbose );
+extern int                 Gia_SweeperRun( Gia_Man_t * p, Vec_Int_t * vProbeIds, char * pCommLime, int fVerbose );
+/*=== giaSwitch.c ============================================================*/
+extern float               Gia_ManEvaluateSwitching( Gia_Man_t * p );
+extern float               Gia_ManComputeSwitching( Gia_Man_t * p, int nFrames, int nPref, int fProbOne );
+extern Vec_Int_t *         Gia_ManComputeSwitchProbs( Gia_Man_t * pGia, int nFrames, int nPref, int fProbOne );
+extern Vec_Flt_t *         Gia_ManPrintOutputProb( Gia_Man_t * p );
+/*=== giaTim.c ===========================================================*/
+extern Gia_Man_t *         Gia_ManDupNormalize( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManDupUnnormalize( Gia_Man_t * p );
+extern Gia_Man_t *         Gia_ManDupCollapse( Gia_Man_t * p, Gia_Man_t * pBoxes, Vec_Int_t * vBoxPres );
+extern int                 Gia_ManLevelWithBoxes( Gia_Man_t * p );
+extern int                 Gia_ManVerifyWithBoxes( Gia_Man_t * pGia, void * pParsInit );
+extern void *              Gia_ManUpdateTimMan( Gia_Man_t * p, Vec_Int_t * vBoxPres );
+extern Gia_Man_t *         Gia_ManUpdateExtraAig( void * pTime, Gia_Man_t * pAig, Vec_Int_t * vBoxPres );
+/*=== giaTruth.c ===========================================================*/
+extern word                Gia_ObjComputeTruthTable6Lut( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTemp );
+extern word                Gia_ObjComputeTruthTable6( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp, Vec_Wrd_t * vTruths );
+extern void                Gia_ObjCollectInternal( Gia_Man_t * p, Gia_Obj_t * pObj );
+extern word *              Gia_ObjComputeTruthTable( Gia_Man_t * p, Gia_Obj_t * pObj );
+extern void                Gia_ObjComputeTruthTableStart( Gia_Man_t * p, int nVarsMax );
+extern void                Gia_ObjComputeTruthTableStop( Gia_Man_t * p );
+extern word *              Gia_ObjComputeTruthTableCut( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves );
+/*=== giaTsim.c ============================================================*/
+extern Gia_Man_t *         Gia_ManReduceConst( Gia_Man_t * pAig, int fVerbose );
+/*=== giaUtil.c ===========================================================*/
+extern unsigned            Gia_ManRandom( int fReset );
+extern word                Gia_ManRandomW( int fReset );
+extern void                Gia_ManRandomInfo( Vec_Ptr_t * vInfo, int iInputStart, int iWordStart, int iWordStop );
+extern char *              Gia_TimeStamp();
+extern char *              Gia_FileNameGenericAppend( char * pBase, char * pSuffix );
+extern void                Gia_ManIncrementTravId( Gia_Man_t * p );
+extern void                Gia_ManCleanMark01( Gia_Man_t * p );
+extern void                Gia_ManSetMark0( Gia_Man_t * p );
+extern void                Gia_ManCleanMark0( Gia_Man_t * p );
+extern void                Gia_ManCheckMark0( Gia_Man_t * p );
+extern void                Gia_ManSetMark1( Gia_Man_t * p );
+extern void                Gia_ManCleanMark1( Gia_Man_t * p );
+extern void                Gia_ManCheckMark1( Gia_Man_t * p );
+extern void                Gia_ManCleanValue( Gia_Man_t * p );
+extern void                Gia_ManCleanLevels( Gia_Man_t * p, int Size );
+extern void                Gia_ManCleanTruth( Gia_Man_t * p );
+extern void                Gia_ManFillValue( Gia_Man_t * p );
+extern void                Gia_ObjSetPhase( Gia_Man_t * p, Gia_Obj_t * pObj );
+extern void                Gia_ManSetPhase( Gia_Man_t * p );
+extern void                Gia_ManSetPhasePattern( Gia_Man_t * p, Vec_Int_t * vCiValues );
+extern void                Gia_ManSetPhase1( Gia_Man_t * p );
+extern void                Gia_ManCleanPhase( Gia_Man_t * p );
+extern int                 Gia_ManCheckCoPhase( Gia_Man_t * p );
+extern int                 Gia_ManLevelNum( Gia_Man_t * p );
+extern Vec_Int_t *         Gia_ManGetCiLevels( Gia_Man_t * p );
+extern int                 Gia_ManSetLevels( Gia_Man_t * p, Vec_Int_t * vCiLevels );
+extern Vec_Int_t *         Gia_ManReverseLevel( Gia_Man_t * p );
+extern Vec_Int_t *         Gia_ManRequiredLevel( Gia_Man_t * p );
+extern void                Gia_ManCreateValueRefs( Gia_Man_t * p );
+extern void                Gia_ManCreateRefs( Gia_Man_t * p );
+extern int *               Gia_ManCreateMuxRefs( Gia_Man_t * p );
+extern int                 Gia_ManCrossCut( Gia_Man_t * p, int fReverse );
+extern int                 Gia_ManIsNormalized( Gia_Man_t * p );
+extern Vec_Int_t *         Gia_ManCollectPoIds( Gia_Man_t * p );
+extern int                 Gia_ObjIsMuxType( Gia_Obj_t * pNode );
+extern int                 Gia_ObjRecognizeExor( Gia_Obj_t * pObj, Gia_Obj_t ** ppFan0, Gia_Obj_t ** ppFan1 );
+extern Gia_Obj_t *         Gia_ObjRecognizeMux( Gia_Obj_t * pNode, Gia_Obj_t ** ppNodeT, Gia_Obj_t ** ppNodeE );
+extern int                 Gia_ObjRecognizeMuxLits( Gia_Man_t * p, Gia_Obj_t * pNode, int * iLitT, int * iLitE );
+extern int                 Gia_NodeMffcSize( Gia_Man_t * p, Gia_Obj_t * pNode );
+extern int                 Gia_ManHasDangling( Gia_Man_t * p );
+extern int                 Gia_ManMarkDangling( Gia_Man_t * p );
+extern Vec_Int_t *         Gia_ManGetDangling( Gia_Man_t * p );
+extern void                Gia_ObjPrint( Gia_Man_t * p, Gia_Obj_t * pObj );
+extern void                Gia_ManPrint( Gia_Man_t * p );
+extern void                Gia_ManPrintCo( Gia_Man_t * p, Gia_Obj_t * pObj );
+extern void                Gia_ManPrintCone( Gia_Man_t * p, Gia_Obj_t * pObj, int * pLeaves, int nLeaves, Vec_Int_t * vNodes );
+extern void                Gia_ManPrintCone2( Gia_Man_t * p, Gia_Obj_t * pObj );
+extern void                Gia_ManInvertConstraints( Gia_Man_t * pAig );
+extern void                Gia_ManInvertPos( Gia_Man_t * pAig );
+extern int                 Gia_ManCompare( Gia_Man_t * p1, Gia_Man_t * p2 );
+extern void                Gia_ManMarkFanoutDrivers( Gia_Man_t * p );
+extern void                Gia_ManSwapPos( Gia_Man_t * p, int i );
+extern Vec_Int_t *         Gia_ManSaveValue( Gia_Man_t * p );
+extern void                Gia_ManLoadValue( Gia_Man_t * p, Vec_Int_t * vValues );
+extern Vec_Int_t *         Gia_ManFirstFanouts( Gia_Man_t * p );
+
+/*=== giaCTas.c ===========================================================*/
+typedef struct Tas_Man_t_  Tas_Man_t;
+extern Tas_Man_t *         Tas_ManAlloc( Gia_Man_t * pAig, int nBTLimit );
+extern void                Tas_ManStop( Tas_Man_t * p );
+extern Vec_Int_t *         Tas_ReadModel( Tas_Man_t * p );
+extern void                Tas_ManSatPrintStats( Tas_Man_t * p );
+extern int                 Tas_ManSolve( Tas_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 );
+extern int                 Tas_ManSolveArray( Tas_Man_t * p, Vec_Ptr_t * vObjs );
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/aig/gia/giaAgi.c b/abc-build/src/aig/gia/giaAgi.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaAgi.c
@@ -0,0 +1,238 @@
+/**CFile****************************************************************
+
+  FileName    [giaAig.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define AGI_PI ABC_CONST(0xFFFFFFFF00000000) 
+#define AGI_RO ABC_CONST(0xFFFFFFFE00000000) 
+#define AGI_PO ABC_CONST(0xFFFFFFFD00000000) 
+#define AGI_RI ABC_CONST(0xFFFFFFFC00000000) 
+#define AGI_C0 ABC_CONST(0xFFFFFFFBFFFFFFFA) 
+#define AGI_M0 ABC_CONST(0x00000000FFFFFFFF) 
+#define AGI_M1 ABC_CONST(0xFFFFFFFF00000000) 
+
+typedef struct Agi_Man_t_ Agi_Man_t;
+struct Agi_Man_t_
+{
+    char *             pName;       // name of the AIG
+    char *             pSpec;       // name of the input file
+    int                nCap;        // number of objects
+    int                nObjs;       // number of objects
+    int                nNodes;      // number of objects
+    int                nRegs;       // number of registers
+    unsigned           nTravIds;    // number of objects
+    Vec_Int_t          vCis;        // comb inputs
+    Vec_Int_t          vCos;        // comb outputs
+    word *             pObjs;       // objects
+    unsigned *         pThird;      // third input
+    unsigned *         pTravIds;    // traversal IDs
+    unsigned *         pNext;       // next values
+    unsigned *         pTable;      // hash table
+    unsigned *         pCopy;       // hash table
+};
+
+static inline int      Agi_ManObjNum( Agi_Man_t * p )                      { return p->nObjs;                                        } 
+static inline int      Agi_ManCiNum( Agi_Man_t * p )                       { return Vec_IntSize( &p->vCis );                         } 
+static inline int      Agi_ManCoNum( Agi_Man_t * p )                       { return Vec_IntSize( &p->vCos );                         } 
+static inline int      Agi_ManNodeNum( Agi_Man_t * p )                     { return p->nNodes;                                       } 
+
+static inline unsigned Agi_ObjLit0( Agi_Man_t * p, int i )                 { return (unsigned)(p->pObjs[i]);                         } 
+static inline unsigned Agi_ObjLit1( Agi_Man_t * p, int i )                 { return (unsigned)(p->pObjs[i] >> 32);                   } 
+static inline unsigned Agi_ObjLit2( Agi_Man_t * p, int i )                 { return p->pThird[i];                                    } 
+static inline int      Agi_ObjVar0( Agi_Man_t * p, int i )                 { return Agi_ObjLit0(p, i) >> 1;                          } 
+static inline int      Agi_ObjVar1( Agi_Man_t * p, int i )                 { return Agi_ObjLit1(p, i) >> 1;                          } 
+static inline int      Agi_ObjVar2( Agi_Man_t * p, int i )                 { return Agi_ObjLit2(p, i) >> 1;                          } 
+static inline void     Agi_ObjSetLit0( Agi_Man_t * p, int i, unsigned l )  { p->pObjs[i] = (p->pObjs[i] & AGI_M1) | (word)l;         } 
+static inline void     Agi_ObjSetLit1( Agi_Man_t * p, int i, unsigned l )  { p->pObjs[i] = (p->pObjs[i] & AGI_M0) | ((word)l << 32); } 
+static inline void     Agi_ObjSetLit2( Agi_Man_t * p, int i, unsigned l )  { p->pThird[i] = l;                                       }  
+
+static inline int      Agi_ObjIsC0( Agi_Man_t * p, int i )                 { return (i == 0);                                        } 
+static inline int      Agi_ObjIsPi( Agi_Man_t * p, int i )                 { return (p->pObjs[i] & AGI_PI) == AGI_PI;                } 
+static inline int      Agi_ObjIsRo( Agi_Man_t * p, int i )                 { return (p->pObjs[i] & AGI_PI) == AGI_RO;                } 
+static inline int      Agi_ObjIsPo( Agi_Man_t * p, int i )                 { return (p->pObjs[i] & AGI_PI) == AGI_PO;                } 
+static inline int      Agi_ObjIsRi( Agi_Man_t * p, int i )                 { return (p->pObjs[i] & AGI_PI) == AGI_RI;                } 
+static inline int      Agi_ObjIsCi( Agi_Man_t * p, int i )                 { return (p->pObjs[i] & AGI_RO) == AGI_RO;                } 
+static inline int      Agi_ObjIsCo( Agi_Man_t * p, int i )                 { return (p->pObjs[i] & AGI_RO) == AGI_PO;                } 
+static inline int      Agi_ObjIsNode( Agi_Man_t * p, int i )               { return p->pObjs[i] < AGI_C0;                            } 
+static inline int      Agi_ObjIsBuf( Agi_Man_t * p, int i )                { return Agi_ObjLit0(p, i) == Agi_ObjLit1(p, i);          } 
+static inline int      Agi_ObjIsAnd( Agi_Man_t * p, int i )                { return Agi_ObjIsNode(p, i) && Agi_ObjLit0(p, i) < Agi_ObjLit1(p, i);  } 
+static inline int      Agi_ObjIsXor( Agi_Man_t * p, int i )                { return Agi_ObjIsNode(p, i) && Agi_ObjLit0(p, i) > Agi_ObjLit1(p, i);  } 
+static inline int      Agi_ObjIsMux( Agi_Man_t * p, int i )                { return Agi_ObjIsAnd(p, i) && ~Agi_ObjLit2(p, i);        }
+static inline int      Agi_ObjIsMaj( Agi_Man_t * p, int i )                { return Agi_ObjIsXor(p, i) && ~Agi_ObjLit2(p, i);        } 
+
+static inline int Agi_ManAppendObj( Agi_Man_t * p )
+{
+    assert( p->nObjs < p->nCap );
+    return p->nObjs++; // return var
+}
+static inline int Agi_ManAppendCi( Agi_Man_t * p )
+{
+    int iObj = Agi_ManAppendObj( p );
+    p->pObjs[iObj] = AGI_PI | (word)Vec_IntSize(&p->vCis);
+    Vec_IntPush( &p->vCis, iObj );
+    return Abc_Var2Lit( iObj, 0 ); // return lit
+}
+static inline int Agi_ManAppendCo( Agi_Man_t * p, int iLit0 )
+{
+    int iObj = Agi_ManAppendObj( p );
+    p->pObjs[iObj] = AGI_PO | (word)iLit0;
+    Vec_IntPush( &p->vCos, iObj );
+    return Abc_Var2Lit( iObj, 0 ); // return lit
+}
+static inline int Agi_ManAppendAnd( Agi_Man_t * p, int iLit0, int iLit1 )
+{
+    int iObj = Agi_ManAppendObj( p );
+    assert( iLit0 < iLit1 );
+    p->pObjs[iObj] = ((word)iLit1 << 32) | (word)iLit0;
+    p->nNodes++;
+    return Abc_Var2Lit( iObj, 0 ); // return lit
+}
+
+#define Agi_ManForEachCi( p, iCi, i )   Vec_IntForEachEntry( &p->vCis, iCi, i )
+#define Agi_ManForEachCo( p, iCo, i )   Vec_IntForEachEntry( &p->vCos, iCo, i )
+#define Agi_ManForEachObj( p, i )       for ( i = 0; i < Agi_ManObjNum(p); i++ )
+#define Agi_ManForEachObj1( p, i )      for ( i = 1; i < Agi_ManObjNum(p); i++ )
+#define Agi_ManForEachNode( p, i )      for ( i = 1; i < Agi_ManObjNum(p); i++ ) if ( !Agi_ObjIsNode(p, i) ) {} else
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Agi_Man_t * Agi_ManAlloc( int nCap )
+{
+    Agi_Man_t * p;
+    nCap = Abc_MaxInt( nCap, 16 );
+    p = ABC_CALLOC( Agi_Man_t, 1 );
+    p->nCap     = nCap;
+    p->pObjs    = ABC_CALLOC( word, nCap );
+    p->pTravIds = ABC_CALLOC( unsigned, nCap );
+    p->pObjs[0] = AGI_C0;
+    p->nObjs    = 1;
+    return p;
+}
+void Agi_ManFree( Agi_Man_t * p )
+{
+    ABC_FREE( p->pObjs );
+    ABC_FREE( p->pTravIds );
+    ABC_FREE( p->vCis.pArray );
+    ABC_FREE( p->vCos.pArray );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Agi_Man_t * Agi_ManFromGia( Gia_Man_t * p )
+{
+    Agi_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    pNew = Agi_ManAlloc( Gia_ManObjNum(p) );
+    Gia_ManForEachObj1( p, pObj, i )
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Agi_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Agi_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+        else if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Agi_ManAppendCi( pNew );
+        else assert( 0 );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Agi_ManSuppSize_rec( Agi_Man_t * p, int i )
+{
+    if ( p->pTravIds[i] == p->nTravIds )
+        return 0;
+    p->pTravIds[i] = p->nTravIds;
+    if ( Agi_ObjIsCi(p, i) )
+        return 1;
+    assert( Agi_ObjIsAnd(p, i) );
+    return Agi_ManSuppSize_rec( p, Agi_ObjVar0(p, i) ) +  Agi_ManSuppSize_rec( p, Agi_ObjVar1(p, i) );
+}
+int Agi_ManSuppSizeOne( Agi_Man_t * p, int i )
+{
+    p->nTravIds++;
+    return Agi_ManSuppSize_rec( p, i );
+}
+int Agi_ManSuppSizeTest( Agi_Man_t * p )
+{
+    abctime clk = Abc_Clock();
+    int i, Counter = 0;
+    Agi_ManForEachNode( p, i )
+        Counter += (Agi_ManSuppSizeOne(p, i) <= 16);
+    printf( "Nodes with small support %d (out of %d)\n", Counter, Agi_ManNodeNum(p) );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return Counter;
+
+}
+void Agi_ManTest( Gia_Man_t * pGia )
+{
+    extern int Gia_ManSuppSizeTest( Gia_Man_t * p );
+    Agi_Man_t * p;
+    Gia_ManSuppSizeTest( pGia );
+    p = Agi_ManFromGia( pGia );
+    Agi_ManSuppSizeTest( p );
+    Agi_ManFree( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaAig.c b/abc-build/src/aig/gia/giaAig.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaAig.c
@@ -0,0 +1,673 @@
+/**CFile****************************************************************
+
+  FileName    [giaAig.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Transformation between AIG manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "giaAig.h"
+#include "proof/fra/fra.h"
+#include "proof/dch/dch.h"
+#include "opt/dar/dar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Gia_ObjChild0Copy( Aig_Obj_t * pObj )  { return Abc_LitNotCond( Aig_ObjFanin0(pObj)->iData, Aig_ObjFaninC0(pObj) ); }
+static inline int Gia_ObjChild1Copy( Aig_Obj_t * pObj )  { return Abc_LitNotCond( Aig_ObjFanin1(pObj)->iData, Aig_ObjFaninC1(pObj) ); }
+
+static inline Aig_Obj_t * Gia_ObjChild0Copy2( Aig_Obj_t ** ppNodes, Gia_Obj_t * pObj, int Id )  { return Aig_NotCond( ppNodes[Gia_ObjFaninId0(pObj, Id)], Gia_ObjFaninC0(pObj) ); }
+static inline Aig_Obj_t * Gia_ObjChild1Copy2( Aig_Obj_t ** ppNodes, Gia_Obj_t * pObj, int Id )  { return Aig_NotCond( ppNodes[Gia_ObjFaninId1(pObj, Id)], Gia_ObjFaninC1(pObj) ); }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFromAig_rec( Gia_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pNext;
+    if ( pObj->iData )
+        return;
+    assert( Aig_ObjIsNode(pObj) );
+    Gia_ManFromAig_rec( pNew, p, Aig_ObjFanin0(pObj) );
+    Gia_ManFromAig_rec( pNew, p, Aig_ObjFanin1(pObj) );
+    pObj->iData = Gia_ManAppendAnd( pNew, Gia_ObjChild0Copy(pObj), Gia_ObjChild1Copy(pObj) );
+    if ( p->pEquivs && (pNext = Aig_ObjEquiv(p, pObj)) )
+    {
+        int iObjNew, iNextNew;
+        Gia_ManFromAig_rec( pNew, p, pNext );
+        iObjNew  = Abc_Lit2Var(pObj->iData);
+        iNextNew = Abc_Lit2Var(pNext->iData);
+        if ( pNew->pNexts )
+            pNew->pNexts[iObjNew] = iNextNew;        
+    }
+}
+Gia_Man_t * Gia_ManFromAig( Aig_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    // create the new manager
+    pNew = Gia_ManStart( Aig_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nConstrs = p->nConstrs;
+    // create room to store equivalences
+    if ( p->pEquivs )
+        pNew->pNexts = ABC_CALLOC( int, Aig_ManObjNum(p) );
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->iData = 1;
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->iData = Gia_ManAppendCi( pNew );
+    // add logic for the POs
+    Aig_ManForEachCo( p, pObj, i )
+        Gia_ManFromAig_rec( pNew, p, Aig_ObjFanin0(pObj) );        
+    Aig_ManForEachCo( p, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjChild0Copy(pObj) );
+    Gia_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    if ( pNew->pNexts )
+        Gia_ManDeriveReprs( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFromAigChoices_rec( Gia_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    if ( pObj == NULL || pObj->iData )
+        return;
+    assert( Aig_ObjIsNode(pObj) );
+    Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjFanin0(pObj) );
+    Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjFanin1(pObj) );
+    Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjEquiv(p, pObj) );
+    pObj->iData = Gia_ManAppendAnd( pNew, Gia_ObjChild0Copy(pObj), Gia_ObjChild1Copy(pObj) );
+    if ( Aig_ObjEquiv(p, pObj) )
+    {
+        int iObjNew, iNextNew;
+        iObjNew  = Abc_Lit2Var(pObj->iData);
+        iNextNew = Abc_Lit2Var(Aig_ObjEquiv(p, pObj)->iData);
+        assert( iObjNew > iNextNew );
+        assert( Gia_ObjIsAnd(Gia_ManObj(pNew, iNextNew)) );
+        pNew->pSibls[iObjNew] = iNextNew;        
+    }
+}
+Gia_Man_t * Gia_ManFromAigChoices( Aig_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( p->pEquivs != NULL );
+    // create the new manager
+    pNew = Gia_ManStart( Aig_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nConstrs = p->nConstrs;
+    // create room to store equivalences
+    pNew->pSibls = ABC_CALLOC( int, Aig_ManObjNum(p) );
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->iData = 1;
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->iData = Gia_ManAppendCi( pNew );
+    // add logic for the POs
+    Aig_ManForEachCo( p, pObj, i )
+        Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjFanin0(pObj) );        
+    Aig_ManForEachCo( p, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjChild0Copy(pObj) );
+    Gia_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    assert( Gia_ManObjNum(pNew) == Aig_ManObjNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFromAigSimple( Aig_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    // create the new manager
+    pNew = Gia_ManStart( Aig_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nConstrs = p->nConstrs;
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( Aig_ObjIsAnd(pObj) )
+            pObj->iData = Gia_ManAppendAnd( pNew, Gia_ObjChild0Copy(pObj), Gia_ObjChild1Copy(pObj) );
+        else if ( Aig_ObjIsCi(pObj) )
+            pObj->iData = Gia_ManAppendCi( pNew );
+        else if ( Aig_ObjIsCo(pObj) )
+            pObj->iData = Gia_ManAppendCo( pNew, Gia_ObjChild0Copy(pObj) );
+        else if ( Aig_ObjIsConst1(pObj) )
+            pObj->iData = 1;
+        else
+            assert( 0 );
+    }
+    Gia_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Handles choices as additional combinational outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFromAigSwitch( Aig_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    // create the new manager
+    pNew = Gia_ManStart( Aig_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nConstrs = p->nConstrs;
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->iData = 1;
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->iData = Gia_ManAppendCi( pNew );
+    // add POs corresponding to the nodes with choices
+    Aig_ManForEachNode( p, pObj, i )
+        if ( Aig_ObjRefs(pObj) == 0 )
+        {
+            Gia_ManFromAig_rec( pNew, p, pObj );        
+            Gia_ManAppendCo( pNew, pObj->iData );
+        }
+    // add logic for the POs
+    Aig_ManForEachCo( p, pObj, i )
+        Gia_ManFromAig_rec( pNew, p, Aig_ObjFanin0(pObj) );        
+    Aig_ManForEachCo( p, pObj, i )
+        pObj->iData = Gia_ManAppendCo( pNew, Gia_ObjChild0Copy(pObj) );
+    Gia_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManToAig_rec( Aig_Man_t * pNew, Aig_Obj_t ** ppNodes, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    Gia_Obj_t * pNext;
+    if ( ppNodes[Gia_ObjId(p, pObj)] )
+        return;
+    if ( Gia_ObjIsCi(pObj) )
+        ppNodes[Gia_ObjId(p, pObj)] = Aig_ObjCreateCi( pNew );
+    else
+    {
+        assert( Gia_ObjIsAnd(pObj) );
+        Gia_ManToAig_rec( pNew, ppNodes, p, Gia_ObjFanin0(pObj) );
+        Gia_ManToAig_rec( pNew, ppNodes, p, Gia_ObjFanin1(pObj) );
+        ppNodes[Gia_ObjId(p, pObj)] = Aig_And( pNew, Gia_ObjChild0Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)), Gia_ObjChild1Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)) );
+    }
+    if ( pNew->pEquivs && (pNext = Gia_ObjNextObj(p, Gia_ObjId(p, pObj))) )
+    {
+        Aig_Obj_t * pObjNew, * pNextNew;
+        Gia_ManToAig_rec( pNew, ppNodes, p, pNext );
+        pObjNew  = ppNodes[Gia_ObjId(p, pObj)];
+        pNextNew = ppNodes[Gia_ObjId(p, pNext)];
+        if ( pNew->pEquivs )
+            pNew->pEquivs[Aig_Regular(pObjNew)->Id] = Aig_Regular(pNextNew);        
+    }
+}
+Aig_Man_t * Gia_ManToAig( Gia_Man_t * p, int fChoices )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t ** ppNodes;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( !fChoices || (p->pNexts && p->pReprs) );
+    // create the new manager
+    pNew = Aig_ManStart( Gia_ManAndNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nConstrs = p->nConstrs;
+//    pNew->pSpec = Abc_UtilStrsav( p->pName );
+    // duplicate representation of choice nodes
+    if ( fChoices )
+        pNew->pEquivs = ABC_CALLOC( Aig_Obj_t *, Gia_ManObjNum(p) );
+    // create the PIs
+    ppNodes = ABC_CALLOC( Aig_Obj_t *, Gia_ManObjNum(p) );
+    ppNodes[0] = Aig_ManConst0(pNew);
+    Gia_ManForEachCi( p, pObj, i )
+        ppNodes[Gia_ObjId(p, pObj)] = Aig_ObjCreateCi( pNew );
+    // transfer level
+    if ( p->vLevels )
+    Gia_ManForEachCi( p, pObj, i )
+        Aig_ObjSetLevel( ppNodes[Gia_ObjId(p, pObj)], Gia_ObjLevel(p, pObj) );
+    // add logic for the POs
+    Gia_ManForEachCo( p, pObj, i )
+    {
+        Gia_ManToAig_rec( pNew, ppNodes, p, Gia_ObjFanin0(pObj) );        
+        ppNodes[Gia_ObjId(p, pObj)] = Aig_ObjCreateCo( pNew, Gia_ObjChild0Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)) );
+    }
+    Aig_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    ABC_FREE( ppNodes );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Gia_ManToAigSkip( Gia_Man_t * p, int nOutDelta )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t ** ppNodes;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( p->pNexts == NULL && p->pReprs == NULL );
+    assert( nOutDelta > 0 && Gia_ManCoNum(p) % nOutDelta == 0 );
+    // create the new manager
+    pNew = Aig_ManStart( Gia_ManAndNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nConstrs = p->nConstrs;
+//    pNew->pSpec = Abc_UtilStrsav( p->pName );
+    // create the PIs
+    ppNodes = ABC_CALLOC( Aig_Obj_t *, Gia_ManObjNum(p) );
+    ppNodes[0] = Aig_ManConst0(pNew);
+    Gia_ManForEachCi( p, pObj, i )
+        ppNodes[Gia_ObjId(p, pObj)] = Aig_ObjCreateCi( pNew );
+    // add logic for the POs
+    Gia_ManForEachCo( p, pObj, i )
+    {
+        Gia_ManToAig_rec( pNew, ppNodes, p, Gia_ObjFanin0(pObj) );        
+        if ( i % nOutDelta != 0 )
+            continue;
+        ppNodes[Gia_ObjId(p, pObj)] = Aig_ObjCreateCo( pNew, Gia_ObjChild0Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)) );
+    }
+    Aig_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    ABC_FREE( ppNodes );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Gia_ManToAigSimple( Gia_Man_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t ** ppNodes;
+    Gia_Obj_t * pObj;
+    int i;
+    ppNodes = ABC_FALLOC( Aig_Obj_t *, Gia_ManObjNum(p) );
+    // create the new manager
+    pNew = Aig_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nConstrs = p->nConstrs;
+    // create the PIs
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            ppNodes[i] = Aig_And( pNew, Gia_ObjChild0Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)), Gia_ObjChild1Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)) );
+        else if ( Gia_ObjIsCi(pObj) )
+            ppNodes[i] = Aig_ObjCreateCi( pNew );
+        else if ( Gia_ObjIsCo(pObj) )
+            ppNodes[i] = Aig_ObjCreateCo( pNew, Gia_ObjChild0Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)) );
+        else if ( Gia_ObjIsConst0(pObj) )
+            ppNodes[i] = Aig_ManConst0(pNew);
+        else
+            assert( 0 );
+        pObj->Value = Abc_Var2Lit( Aig_ObjId(Aig_Regular(ppNodes[i])), Aig_IsComplement(ppNodes[i]) );
+        assert( i == 0 || Aig_ObjId(ppNodes[i]) == i );
+    }
+    Aig_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    ABC_FREE( ppNodes );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Gia_ManCofactorAig( Aig_Man_t * p, int nFrames, int nCofFanLit )
+{
+    Aig_Man_t * pMan;
+    Gia_Man_t * pGia, * pTemp;
+    pGia = Gia_ManFromAig( p );
+    pGia = Gia_ManUnrollAndCofactor( pTemp = pGia, nFrames, nCofFanLit, 1 );
+    Gia_ManStop( pTemp );
+    pMan = Gia_ManToAig( pGia, 0 );
+    Gia_ManStop( pGia );
+    return pMan;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers representatives from pGia to pAig.]
+
+  Description [Assumes that pGia was created from pAig.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManReprToAigRepr( Aig_Man_t * pAig, Gia_Man_t * pGia )
+{
+    Aig_Obj_t * pObj;
+    Gia_Obj_t * pGiaObj, * pGiaRepr;
+    int i;
+    assert( pAig->pReprs == NULL );
+    assert( pGia->pReprs != NULL );
+    // move pointers from AIG to GIA
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+        assert( i == 0 || !Abc_LitIsCompl(pObj->iData) );
+        pGiaObj = Gia_ManObj( pGia, Abc_Lit2Var(pObj->iData) );
+        pGiaObj->Value = i;
+    }
+    // set the pointers to the nodes in AIG
+    Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) );
+    Gia_ManForEachObj( pGia, pGiaObj, i )
+    {
+        pGiaRepr = Gia_ObjReprObj( pGia, i );
+        if ( pGiaRepr == NULL )
+            continue;
+        Aig_ObjCreateRepr( pAig, Aig_ManObj(pAig, pGiaRepr->Value), Aig_ManObj(pAig, pGiaObj->Value) );
+    }
+}
+void Gia_ManReprToAigRepr2( Aig_Man_t * pAig, Gia_Man_t * pGia )
+{
+    Gia_Obj_t * pGiaObj, * pGiaRepr;
+    int i;
+    assert( pAig->pReprs == NULL );
+    assert( pGia->pReprs != NULL );
+    // set the pointers to the nodes in AIG
+    Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) );
+    Gia_ManForEachObj( pGia, pGiaObj, i )
+    {
+        pGiaRepr = Gia_ObjReprObj( pGia, i );
+        if ( pGiaRepr == NULL )
+            continue;
+        Aig_ObjCreateRepr( pAig, Aig_ManObj(pAig, Abc_Lit2Var(pGiaRepr->Value)), Aig_ManObj(pAig, Abc_Lit2Var(pGiaObj->Value)) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers representatives from pAig to pGia.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManReprFromAigRepr( Aig_Man_t * pAig, Gia_Man_t * pGia )
+{
+    Gia_Obj_t * pObjGia; 
+    Aig_Obj_t * pObjAig, * pReprAig;
+    int i;
+    assert( pAig->pReprs != NULL );
+    assert( pGia->pReprs == NULL );
+    assert( Gia_ManObjNum(pGia) - Gia_ManCoNum(pGia) == Aig_ManObjNum(pAig) - Aig_ManCoNum(pAig) );
+    pGia->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pGia) );
+    for ( i = 0; i < Gia_ManObjNum(pGia); i++ )
+        Gia_ObjSetRepr( pGia, i, GIA_VOID );
+    // move pointers from GIA to AIG
+    Gia_ManForEachObj( pGia, pObjGia, i )
+    {
+        if ( Gia_ObjIsCo(pObjGia) )
+            continue;
+        assert( i == 0 || !Abc_LitIsCompl(Gia_ObjValue(pObjGia)) );
+        pObjAig  = Aig_ManObj( pAig, Abc_Lit2Var(Gia_ObjValue(pObjGia)) );
+        pObjAig->iData = i;
+    }
+    Aig_ManForEachObj( pAig, pObjAig, i )
+    {
+        if ( Aig_ObjIsCo(pObjAig) )
+            continue;
+        if ( pAig->pReprs[i] == NULL )
+            continue;
+        pReprAig = pAig->pReprs[i];
+        Gia_ObjSetRepr( pGia, pObjAig->iData, pReprAig->iData );
+    }
+    pGia->pNexts = Gia_ManDeriveNexts( pGia );
+}
+void Gia_ManReprFromAigRepr2( Aig_Man_t * pAig, Gia_Man_t * pGia )
+{
+    Aig_Obj_t * pObjAig, * pReprAig;
+    int i;
+    assert( pAig->pReprs != NULL );
+    assert( pGia->pReprs == NULL );
+    assert( Gia_ManObjNum(pGia) - Gia_ManCoNum(pGia) == Aig_ManObjNum(pAig) - Aig_ManCoNum(pAig) );
+    pGia->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pGia) );
+    for ( i = 0; i < Gia_ManObjNum(pGia); i++ )
+        Gia_ObjSetRepr( pGia, i, GIA_VOID );
+    Aig_ManForEachObj( pAig, pObjAig, i )
+    {
+        if ( Aig_ObjIsCo(pObjAig) )
+            continue;
+        if ( pAig->pReprs[i] == NULL )
+            continue;
+        pReprAig = pAig->pReprs[i];
+        Gia_ObjSetRepr( pGia, Abc_Lit2Var(pObjAig->iData), Abc_Lit2Var(pReprAig->iData) );
+    }
+    pGia->pNexts = Gia_ManDeriveNexts( pGia );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Applies DC2 to the GIA manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManCompress2( Gia_Man_t * p, int fUpdateLevel, int fVerbose )
+{
+    Gia_Man_t * pGia;
+    Aig_Man_t * pNew, * pTemp;
+    if ( p->pManTime && p->vLevels == NULL )
+        Gia_ManLevelWithBoxes( p );
+    pNew = Gia_ManToAig( p, 0 );
+    pNew = Dar_ManCompress2( pTemp = pNew, 1, fUpdateLevel, 1, 0, fVerbose );
+    Aig_ManStop( pTemp );
+    pGia = Gia_ManFromAig( pNew );
+    Aig_ManStop( pNew );
+    pGia->pManTime   = p->pManTime;   p->pManTime   = NULL;
+    pGia->pAigExtra  = p->pAigExtra;  p->pAigExtra  = NULL;
+    pGia->nAnd2Delay = p->nAnd2Delay; p->nAnd2Delay = 0;
+    return pGia;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManPerformDch( Gia_Man_t * p, void * pPars )
+{
+    Gia_Man_t * pGia;
+    Aig_Man_t * pNew;
+    if ( p->pManTime && p->vLevels == NULL )
+        Gia_ManLevelWithBoxes( p );
+    pNew = Gia_ManToAig( p, 0 );
+    pNew = Dar_ManChoiceNew( pNew, (Dch_Pars_t *)pPars );
+//    pGia = Gia_ManFromAig( pNew );
+    pGia = Gia_ManFromAigChoices( pNew );
+    Aig_ManStop( pNew );
+    pGia->pManTime   = p->pManTime;   p->pManTime   = NULL;
+    pGia->pAigExtra  = p->pAigExtra;  p->pAigExtra  = NULL;
+    pGia->nAnd2Delay = p->nAnd2Delay; p->nAnd2Delay = 0;
+    return pGia;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes equivalences after structural sequential cleanup.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSeqCleanupClasses( Gia_Man_t * p, int fConst, int fEquiv, int fVerbose )
+{
+    Aig_Man_t * pNew, * pTemp;
+    pNew  = Gia_ManToAigSimple( p );
+    pTemp = Aig_ManScl( pNew, fConst, fEquiv, 0, -1, -1, fVerbose, 0 );
+    Gia_ManReprFromAigRepr( pNew, p );
+    Aig_ManStop( pTemp );
+    Aig_ManStop( pNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Solves SAT problem.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManSolveSat( Gia_Man_t * p )
+{
+//    extern int Fra_FraigSat( Aig_Man_t * pMan, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose );
+    Aig_Man_t * pNew;
+    int RetValue;//, clk = Abc_Clock();
+    pNew = Gia_ManToAig( p, 0 );
+    RetValue = Fra_FraigSat( pNew, 10000000, 0, 0, 0, 0, 1, 1, 0, 0 );
+    if ( RetValue == 0 )
+    {
+        Gia_Obj_t * pObj;
+        int i, * pInit = (int *)pNew->pData;
+        Gia_ManConst0(p)->fMark0 = 0;
+        Gia_ManForEachPi( p, pObj, i )
+            pObj->fMark0 = pInit[i];
+        Gia_ManForEachAnd( p, pObj, i )
+            pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & 
+                           (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+        Gia_ManForEachPo( p, pObj, i )
+            pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj));
+        Gia_ManForEachPo( p, pObj, i )
+            if ( pObj->fMark0 != 1 )
+                break;
+        if ( i != Gia_ManPoNum(p) )
+            Abc_Print( 1, "Counter-example verification has failed.  " );
+//        else
+//            Abc_Print( 1, "Counter-example verification succeeded.  " );
+    }
+/*
+    else if ( RetValue == 1 )
+        Abc_Print( 1, "The SAT problem is unsatisfiable.  " );
+    else if ( RetValue == -1 )
+        Abc_Print( 1, "The SAT problem is undecided.  " );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+*/
+    Aig_ManStop( pNew );
+    return RetValue;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaAig.h b/abc-build/src/aig/gia/giaAig.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaAig.h
@@ -0,0 +1,78 @@
+/**CFile****************************************************************
+
+  FileName    [giaAig.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaAig.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__gia__giaAig_h
+#define ABC__aig__gia__giaAig_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "aig/aig/aig.h"
+#include "gia.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+ 
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== giaAig.c =============================================================*/
+extern Gia_Man_t *         Gia_ManFromAig( Aig_Man_t * p );
+extern Gia_Man_t *         Gia_ManFromAigChoices( Aig_Man_t * p );
+extern Gia_Man_t *         Gia_ManFromAigSimple( Aig_Man_t * p );
+extern Gia_Man_t *         Gia_ManFromAigSwitch( Aig_Man_t * p );
+extern Aig_Man_t *         Gia_ManToAig( Gia_Man_t * p, int fChoices );
+extern Aig_Man_t *         Gia_ManToAigSkip( Gia_Man_t * p, int nOutDelta );
+extern Aig_Man_t *         Gia_ManToAigSimple( Gia_Man_t * p );
+extern void                Gia_ManReprToAigRepr( Aig_Man_t * pAig, Gia_Man_t * pGia );
+extern void                Gia_ManReprToAigRepr2( Aig_Man_t * pAig, Gia_Man_t * pGia );
+extern void                Gia_ManReprFromAigRepr( Aig_Man_t * pAig, Gia_Man_t * pGia );
+extern void                Gia_ManReprFromAigRepr2( Aig_Man_t * pAig, Gia_Man_t * pGia );
+extern Gia_Man_t *         Gia_ManCompress2( Gia_Man_t * p, int fUpdateLevel, int fVerbose );
+extern Gia_Man_t *         Gia_ManPerformDch( Gia_Man_t * p, void * pPars );
+extern Gia_Man_t *         Gia_ManAbstraction( Gia_Man_t * p, Vec_Int_t * vFlops );
+extern void                Gia_ManSeqCleanupClasses( Gia_Man_t * p, int fConst, int fEquiv, int fVerbose );
+extern int                 Gia_ManSolveSat( Gia_Man_t * p );
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/aig/gia/giaAiger.c b/abc-build/src/aig/gia/giaAiger.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaAiger.c
@@ -0,0 +1,1364 @@
+/**CFile****************************************************************
+
+  FileName    [giaAiger.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Procedures to read/write binary AIGER format developed by
+  Armin Biere, Johannes Kepler University (http://fmv.jku.at/)]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaAiger.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/tim/tim.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+#define XAIG_VERBOSE 0
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_FileFixName( char * pFileName )
+{
+    char * pName;
+    for ( pName = pFileName; *pName; pName++ )
+        if ( *pName == '>' )
+            *pName = '\\';
+}
+char * Gia_FileNameGeneric( char * FileName )
+{
+    char * pDot, * pRes;
+    pRes = Abc_UtilStrsav( FileName );
+    if ( (pDot = strrchr( pRes, '.' )) )
+        *pDot = 0;
+    return pRes;
+}
+int Gia_FileSize( char * pFileName )
+{
+    FILE * pFile;
+    int nFileSize;
+    pFile = fopen( pFileName, "r" );
+    if ( pFile == NULL )
+    {
+        printf( "Gia_FileSize(): The file is unavailable (absent or open).\n" );
+        return 0;
+    }
+    fseek( pFile, 0, SEEK_END );  
+    nFileSize = ftell( pFile ); 
+    fclose( pFile );
+    return nFileSize;
+}
+void Gia_FileWriteBufferSize( FILE * pFile, int nSize )
+{
+    unsigned char Buffer[5];
+    Gia_AigerWriteInt( Buffer, nSize );
+    fwrite( Buffer, 1, 4, pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the array of literals to be written.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_AigerCollectLiterals( Gia_Man_t * p )
+{
+    Vec_Int_t * vLits;
+    Gia_Obj_t * pObj;
+    int i;
+    vLits = Vec_IntAlloc( Gia_ManPoNum(p) );
+    Gia_ManForEachRi( p, pObj, i )
+        Vec_IntPush( vLits, Gia_ObjFaninLit0p(p, pObj) );
+    Gia_ManForEachPo( p, pObj, i )
+        Vec_IntPush( vLits, Gia_ObjFaninLit0p(p, pObj) );
+    return vLits;
+}
+Vec_Int_t * Gia_AigerReadLiterals( unsigned char ** ppPos, int nEntries )
+{
+    Vec_Int_t * vLits;
+    int Lit, LitPrev, Diff, i;
+    vLits = Vec_IntAlloc( nEntries );
+    LitPrev = Gia_AigerReadUnsigned( ppPos );
+    Vec_IntPush( vLits, LitPrev );
+    for ( i = 1; i < nEntries; i++ )
+    {
+//        Diff = Lit - LitPrev;
+//        Diff = (Lit < LitPrev)? -Diff : Diff;
+//        Diff = ((2 * Diff) << 1) | (int)(Lit < LitPrev);
+        Diff = Gia_AigerReadUnsigned( ppPos );
+        Diff = (Diff & 1)? -(Diff >> 1) : Diff >> 1;
+        Lit  = Diff + LitPrev;
+        Vec_IntPush( vLits, Lit );
+        LitPrev = Lit;
+    }
+    return vLits;
+}
+Vec_Str_t * Gia_AigerWriteLiterals( Vec_Int_t * vLits )
+{
+    Vec_Str_t * vBinary;
+    int Pos = 0, Lit, LitPrev, Diff, i;
+    vBinary = Vec_StrAlloc( 2 * Vec_IntSize(vLits) );
+    LitPrev = Vec_IntEntry( vLits, 0 );
+    Pos = Gia_AigerWriteUnsignedBuffer( (unsigned char *)Vec_StrArray(vBinary), Pos, LitPrev ); 
+    Vec_IntForEachEntryStart( vLits, Lit, i, 1 )
+    {
+        Diff = Lit - LitPrev;
+        Diff = (Lit < LitPrev)? -Diff : Diff;
+        Diff = (Diff << 1) | (int)(Lit < LitPrev);
+        Pos = Gia_AigerWriteUnsignedBuffer( (unsigned char *)Vec_StrArray(vBinary), Pos, Diff );
+        LitPrev = Lit;
+        if ( Pos + 10 > vBinary->nCap )
+            Vec_StrGrow( vBinary, vBinary->nCap+1 );
+    }
+    vBinary->nSize = Pos;
+/*
+    // verify
+    {
+        extern Vec_Int_t * Gia_AigerReadLiterals( char ** ppPos, int nEntries );
+        char * pPos = Vec_StrArray( vBinary );
+        Vec_Int_t * vTemp = Gia_AigerReadLiterals( &pPos, Vec_IntSize(vLits) );
+        for ( i = 0; i < Vec_IntSize(vLits); i++ )
+        {
+            int Entry1 = Vec_IntEntry(vLits,i);
+            int Entry2 = Vec_IntEntry(vTemp,i);
+            assert( Entry1 == Entry2 );
+        }
+        Vec_IntFree( vTemp );
+    }
+*/
+    return vBinary;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the AIG in the binary AIGER format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fSkipStrash, int fCheck )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Vec_Int_t * vLits = NULL, * vPoTypes = NULL;
+    Vec_Int_t * vNodes, * vDrivers, * vInits = NULL;
+    int iObj, iNode0, iNode1, fHieOnly = 0;
+    int nTotal, nInputs, nOutputs, nLatches, nAnds, i;
+    int nBad = 0, nConstr = 0, nJust = 0, nFair = 0;
+    unsigned char * pDrivers, * pSymbols, * pCur;
+    unsigned uLit0, uLit1, uLit;
+
+    // read the parameters (M I L O A + B C J F)
+    pCur = (unsigned char *)pContents;         while ( *pCur != ' ' ) pCur++; pCur++;
+    // read the number of objects
+    nTotal = atoi( (const char *)pCur );    while ( *pCur != ' ' ) pCur++; pCur++;
+    // read the number of inputs
+    nInputs = atoi( (const char *)pCur );   while ( *pCur != ' ' ) pCur++; pCur++;
+    // read the number of latches
+    nLatches = atoi( (const char *)pCur );  while ( *pCur != ' ' ) pCur++; pCur++;
+    // read the number of outputs
+    nOutputs = atoi( (const char *)pCur );  while ( *pCur != ' ' ) pCur++; pCur++;
+    // read the number of nodes
+    nAnds = atoi( (const char *)pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
+    if ( *pCur == ' ' )
+    {
+//        assert( nOutputs == 0 );
+        // read the number of properties
+        pCur++;
+        nBad = atoi( (const char *)pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
+        nOutputs += nBad;
+    }
+    if ( *pCur == ' ' )
+    {
+        // read the number of properties
+        pCur++;
+        nConstr = atoi( (const char *)pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
+        nOutputs += nConstr;
+    }
+    if ( *pCur == ' ' )
+    {
+        // read the number of properties
+        pCur++;
+        nJust = atoi( (const char *)pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
+        nOutputs += nJust;
+    }
+    if ( *pCur == ' ' )
+    {
+        // read the number of properties
+        pCur++;
+        nFair = atoi( (const char *)pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
+        nOutputs += nFair;
+    }
+    if ( *pCur != '\n' )
+    {
+        fprintf( stdout, "The parameter line is in a wrong format.\n" );
+        return NULL;
+    }
+    pCur++;
+
+    // check the parameters
+    if ( nTotal != nInputs + nLatches + nAnds )
+    {
+        fprintf( stdout, "The number of objects does not match.\n" );
+        return NULL;
+    }
+    if ( nJust || nFair )
+    {
+        fprintf( stdout, "Reading AIGER files with liveness properties is currently not supported.\n" );
+        return NULL;
+    }
+
+    if ( nConstr )
+    {
+        if ( nConstr == 1 )
+            fprintf( stdout, "Warning: The last output is interpreted as a constraint.\n" );
+        else
+            fprintf( stdout, "Warning: The last %d outputs are interpreted as constraints.\n", nConstr );
+    }
+
+    // allocate the empty AIG
+    pNew = Gia_ManStart( nTotal + nLatches + nOutputs + 1 );
+    pNew->nConstrs = nConstr;
+
+    // prepare the array of nodes
+    vNodes = Vec_IntAlloc( 1 + nTotal );
+    Vec_IntPush( vNodes, 0 );
+
+    // create the PIs
+    for ( i = 0; i < nInputs + nLatches; i++ )
+    {
+        iObj = Gia_ManAppendCi(pNew);    
+        Vec_IntPush( vNodes, iObj );
+    }
+
+    // remember the beginning of latch/PO literals
+    pDrivers = pCur;
+    if ( pContents[3] == ' ' ) // standard AIGER
+    {
+        // scroll to the beginning of the binary data
+        for ( i = 0; i < nLatches + nOutputs; )
+            if ( *pCur++ == '\n' )
+                i++;
+    }
+    else // modified AIGER
+    {
+        vLits = Gia_AigerReadLiterals( &pCur, nLatches + nOutputs );
+    }
+
+    // create the AND gates
+    if ( !fSkipStrash )
+        Gia_ManHashAlloc( pNew );
+    for ( i = 0; i < nAnds; i++ )
+    {
+        uLit = ((i + 1 + nInputs + nLatches) << 1);
+        uLit1 = uLit  - Gia_AigerReadUnsigned( &pCur );
+        uLit0 = uLit1 - Gia_AigerReadUnsigned( &pCur );
+//        assert( uLit1 > uLit0 );
+        iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), uLit0 & 1 );
+        iNode1 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit1 >> 1), uLit1 & 1 );
+        assert( Vec_IntSize(vNodes) == i + 1 + nInputs + nLatches );
+        if ( fSkipStrash )
+            Vec_IntPush( vNodes, Gia_ManAppendAnd(pNew, iNode0, iNode1) );
+        else
+            Vec_IntPush( vNodes, Gia_ManHashAnd(pNew, iNode0, iNode1) );
+    }
+    if ( !fSkipStrash )
+        Gia_ManHashStop( pNew );
+
+    // remember the place where symbols begin
+    pSymbols = pCur;
+
+    // read the latch driver literals
+    vDrivers = Vec_IntAlloc( nLatches + nOutputs );
+    if ( pContents[3] == ' ' ) // standard AIGER
+    {
+        vInits = Vec_IntAlloc( nLatches );
+        pCur = pDrivers;
+        for ( i = 0; i < nLatches; i++ )
+        {
+            uLit0 = atoi( (char *)pCur );   
+            while ( *pCur != ' ' && *pCur != '\n' ) 
+                pCur++;
+            if ( *pCur == ' ' )
+            {
+                pCur++;
+                Vec_IntPush( vInits, atoi( (char *)pCur ) );
+                while ( *pCur++ != '\n' );
+            }
+            else
+            {
+                pCur++;
+                Vec_IntPush( vInits, 0 );
+            }
+            iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );
+            Vec_IntPush( vDrivers, iNode0 );
+        }
+        // read the PO driver literals
+        for ( i = 0; i < nOutputs; i++ )
+        {
+            uLit0 = atoi( (char *)pCur );   while ( *pCur++ != '\n' );
+            iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );
+            Vec_IntPush( vDrivers, iNode0 );
+        }
+
+    }
+    else
+    {
+        // read the latch driver literals
+        for ( i = 0; i < nLatches; i++ )
+        {
+            uLit0 = Vec_IntEntry( vLits, i );
+            iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );
+            Vec_IntPush( vDrivers, iNode0 );
+        }
+        // read the PO driver literals
+        for ( i = 0; i < nOutputs; i++ )
+        {
+            uLit0 = Vec_IntEntry( vLits, i+nLatches );
+            iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );
+            Vec_IntPush( vDrivers, iNode0 );
+        }
+        Vec_IntFree( vLits );
+    }
+
+    // create the POs
+    for ( i = 0; i < nOutputs; i++ )
+        Gia_ManAppendCo( pNew, Vec_IntEntry(vDrivers, nLatches + i) );
+    for ( i = 0; i < nLatches; i++ )
+        Gia_ManAppendCo( pNew, Vec_IntEntry(vDrivers, i) );
+    Vec_IntFree( vDrivers );
+
+    // create the latches
+    Gia_ManSetRegNum( pNew, nLatches );
+
+    // read signal names if they are of the special type
+    pCur = pSymbols;
+    if ( *pCur != 'c' )
+    {
+        int fBreakUsed = 0;
+        unsigned char * pCurOld = pCur;
+        pNew->vUserPiIds = Vec_IntStartFull( nInputs );
+        pNew->vUserPoIds = Vec_IntStartFull( nOutputs );
+        pNew->vUserFfIds = Vec_IntStartFull( nLatches );
+        while ( pCur < (unsigned char *)pContents + nFileSize && *pCur != 'c' )
+        {
+            int iTerm;
+            char * pType = (char *)pCur;
+            // check terminal type
+            if ( *pCur != 'i' && *pCur != 'o' && *pCur != 'l'  )
+            {
+//                fprintf( stdout, "Wrong terminal type.\n" );
+                fBreakUsed = 1;
+                break;
+            }
+            // get terminal number
+            iTerm = atoi( (char *)++pCur );  while ( *pCur++ != ' ' );
+            // skip spaces
+            while ( *pCur == ' ' )
+                pCur++;
+            // decode the user numbers:
+            // flops are named: @l<num>
+            // PIs are named: @i<num>
+            // POs are named: @o<num>
+            if ( *pCur++ != '@' )
+            {
+                fBreakUsed = 1;
+                break;
+            }
+            if ( *pCur == 'i' && *pType == 'i' )
+                Vec_IntWriteEntry( pNew->vUserPiIds, iTerm, atoi((char *)pCur+1) );
+            else if ( *pCur == 'o' && *pType == 'o' )
+                Vec_IntWriteEntry( pNew->vUserPoIds, iTerm, atoi((char *)pCur+1) );
+            else if ( *pCur == 'l' && *pType == 'l' )
+                Vec_IntWriteEntry( pNew->vUserFfIds, iTerm, atoi((char *)pCur+1) );
+            else
+            {
+                fprintf( stdout, "Wrong name format.\n" );
+                fBreakUsed = 1;
+                break;
+            }
+            // skip digits
+            while ( *pCur++ != '\n' );
+        }
+        // in case of abnormal termination, remove the arrays
+        if ( fBreakUsed )
+        {
+            unsigned char * pName;
+            int Entry, nInvars, nConstr, iTerm;
+
+            Vec_Int_t * vPoNames = Vec_IntStartFull( nOutputs );
+
+            Vec_IntFreeP( &pNew->vUserPiIds );
+            Vec_IntFreeP( &pNew->vUserPoIds );
+            Vec_IntFreeP( &pNew->vUserFfIds );
+
+            // try to figure out signal names
+            fBreakUsed = 0;
+            pCur = (unsigned char *)pCurOld;
+            while ( pCur < (unsigned char *)pContents + nFileSize && *pCur != 'c' )
+            {
+                // get the terminal type
+                if ( *pCur == 'i' || *pCur == 'l' )
+                {
+                    // skip till the end of the line
+                    while ( *pCur++ != '\n' );
+                    *(pCur-1) = 0;
+                    continue;
+                }
+                if ( *pCur != 'o' )
+                {
+//                    fprintf( stdout, "Wrong terminal type.\n" );
+                    fBreakUsed = 1;
+                    break;
+                }
+                // get the terminal number
+                iTerm = atoi( (char *)++pCur );  while ( *pCur++ != ' ' );
+                // get the node
+                if ( iTerm < 0 || iTerm >= nOutputs )
+                {
+                    fprintf( stdout, "The output number (%d) is out of range.\n", iTerm );
+                    fBreakUsed = 1;
+                    break;
+                }
+                if ( Vec_IntEntry(vPoNames, iTerm) != ~0 )
+                {
+                    fprintf( stdout, "The output number (%d) is listed twice.\n", iTerm );
+                    fBreakUsed = 1;
+                    break;
+                }
+
+                // get the name
+                pName = pCur;          while ( *pCur++ != '\n' );
+                *(pCur-1) = 0;
+                // assign the name
+                Vec_IntWriteEntry( vPoNames, iTerm, pName - (unsigned char *)pContents );
+            } 
+
+            // check that all names are assigned
+            if ( !fBreakUsed )
+            {
+                nInvars = nConstr = 0;
+                vPoTypes = Vec_IntStart( Gia_ManPoNum(pNew) );
+                Vec_IntForEachEntry( vPoNames, Entry, i )
+                {
+                    if ( Entry == ~0 )
+                        continue;
+                    if ( strncmp( pContents+Entry, "constraint:", 11 ) == 0 )
+                    {
+                        Vec_IntWriteEntry( vPoTypes, i, 1 );
+                        nConstr++;
+                    }
+                    if ( strncmp( pContents+Entry, "invariant:", 10 ) == 0 )
+                    {
+                        Vec_IntWriteEntry( vPoTypes, i, 2 );
+                        nInvars++;
+                    }
+                }
+                if ( nConstr )
+                    fprintf( stdout, "Recognized and added %d constraints.\n", nConstr );
+                if ( nInvars )
+                    fprintf( stdout, "Recognized and skipped %d invariants.\n", nInvars );
+                if ( nConstr == 0 && nInvars == 0 )
+                    Vec_IntFreeP( &vPoTypes );
+            }
+            Vec_IntFree( vPoNames );
+        }
+    }
+
+
+    // check if there are other types of information to read
+    if ( pCur + 1 < (unsigned char *)pContents + nFileSize && *pCur == 'c' )
+    {
+        int fVerbose = XAIG_VERBOSE;
+        Vec_Str_t * vStr;
+        unsigned char * pCurTemp;
+        pCur++;
+        // skip new line if present
+//        if ( *pCur == '\n' )
+//            pCur++;
+        while ( pCur < (unsigned char *)pContents + nFileSize )
+        {
+            // read extra AIG
+            if ( *pCur == 'a' )
+            {
+                pCur++;
+                vStr = Vec_StrStart( Gia_AigerReadInt(pCur) );             pCur += 4;
+                memcpy( Vec_StrArray(vStr), pCur, Vec_StrSize(vStr) );
+                pCur += Vec_StrSize(vStr);
+                pNew->pAigExtra = Gia_AigerReadFromMemory( Vec_StrArray(vStr), Vec_StrSize(vStr), 0, 0 );
+                Vec_StrFree( vStr );
+                if ( fVerbose ) printf( "Finished reading extension \"a\".\n" );
+            }
+            // read number of constraints
+            else if ( *pCur == 'c' )
+            {
+                pCur++;
+                assert( Gia_AigerReadInt(pCur) == 4 );                     pCur += 4;
+                pNew->nConstrs = Gia_AigerReadInt( pCur );                 pCur += 4;
+                if ( fVerbose ) printf( "Finished reading extension \"c\".\n" );
+            }
+            // read delay information
+            else if ( *pCur == 'd' )
+            {
+                pCur++;
+                assert( Gia_AigerReadInt(pCur) == 4 );                     pCur += 4;
+                pNew->nAnd2Delay = Gia_AigerReadInt(pCur);                 pCur += 4;
+                if ( fVerbose ) printf( "Finished reading extension \"d\".\n" );
+            }
+            else if ( *pCur == 'i' )
+            {
+                pCur++;
+                nInputs = Gia_AigerReadInt(pCur)/4;                        pCur += 4;
+                pNew->vInArrs  = Vec_FltStart( nInputs );
+                memcpy( Vec_FltArray(pNew->vInArrs),  pCur, 4*nInputs );   pCur += 4*nInputs;
+                if ( fVerbose ) printf( "Finished reading extension \"i\".\n" );
+            }
+            else if ( *pCur == 'o' )
+            {
+                pCur++;
+                nOutputs = Gia_AigerReadInt(pCur)/4;                       pCur += 4;
+                pNew->vOutReqs  = Vec_FltStart( nOutputs );
+                memcpy( Vec_FltArray(pNew->vOutReqs),  pCur, 4*nOutputs ); pCur += 4*nOutputs;
+                if ( fVerbose ) printf( "Finished reading extension \"o\".\n" );
+            }
+            // read equivalence classes
+            else if ( *pCur == 'e' )
+            {
+                extern Gia_Rpr_t * Gia_AigerReadEquivClasses( unsigned char ** ppPos, int nSize );
+                pCur++;
+                pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4;              pCur += 4;
+                pNew->pReprs = Gia_AigerReadEquivClasses( &pCur, Gia_ManObjNum(pNew) );
+                pNew->pNexts = Gia_ManDeriveNexts( pNew );
+                assert( pCur == pCurTemp );
+                if ( fVerbose ) printf( "Finished reading extension \"e\".\n" );
+            }
+            // read flop classes
+            else if ( *pCur == 'f' )
+            {
+                pCur++;
+                assert( Gia_AigerReadInt(pCur) == 4*Gia_ManRegNum(pNew) );   pCur += 4;
+                pNew->vFlopClasses  = Vec_IntStart( Gia_ManRegNum(pNew) );
+                memcpy( Vec_IntArray(pNew->vFlopClasses),  pCur, 4*Gia_ManRegNum(pNew) );   pCur += 4*Gia_ManRegNum(pNew);
+                if ( fVerbose ) printf( "Finished reading extension \"f\".\n" );
+            }
+            // read gate classes
+            else if ( *pCur == 'g' )
+            {
+                pCur++;
+                assert( Gia_AigerReadInt(pCur) == 4*Gia_ManObjNum(pNew) );   pCur += 4;
+                pNew->vGateClasses  = Vec_IntStart( Gia_ManObjNum(pNew) );
+                memcpy( Vec_IntArray(pNew->vGateClasses),  pCur, 4*Gia_ManObjNum(pNew) );   pCur += 4*Gia_ManObjNum(pNew);
+                if ( fVerbose ) printf( "Finished reading extension \"g\".\n" );
+            }
+            // read hierarchy information
+            else if ( *pCur == 'h' )
+            {
+                pCur++;
+                vStr = Vec_StrStart( Gia_AigerReadInt(pCur) );          pCur += 4;
+                memcpy( Vec_StrArray(vStr), pCur, Vec_StrSize(vStr) );
+                pCur += Vec_StrSize(vStr);
+                pNew->pManTime = Tim_ManLoad( vStr, 1 );
+                Vec_StrFree( vStr );
+                fHieOnly = 1;
+                if ( fVerbose ) printf( "Finished reading extension \"h\".\n" );
+            }
+            // read packing
+            else if ( *pCur == 'k' )
+            {
+                extern Vec_Int_t * Gia_AigerReadPacking( unsigned char ** ppPos, int nSize );
+                int nSize;
+                pCur++;
+                nSize = Gia_AigerReadInt(pCur);
+                pCurTemp = pCur + nSize + 4;                            pCur += 4;
+                pNew->vPacking = Gia_AigerReadPacking( &pCur, nSize ); 
+                assert( pCur == pCurTemp );
+                if ( fVerbose ) printf( "Finished reading extension \"k\".\n" );
+            }
+            // read mapping
+            else if ( *pCur == 'm' )
+            {
+                extern int * Gia_AigerReadMapping( unsigned char ** ppPos, int nSize );
+                extern int * Gia_AigerReadMappingSimple( unsigned char ** ppPos, int nSize );
+                extern Vec_Int_t * Gia_AigerReadMappingDoc( unsigned char ** ppPos, int nObjs );
+                int nSize;
+                pCur++;
+                nSize = Gia_AigerReadInt(pCur);
+                pCurTemp = pCur + nSize + 4;           pCur += 4;
+                pNew->vMapping = Gia_AigerReadMappingDoc( &pCur, Gia_ManObjNum(pNew) );
+                assert( pCur == pCurTemp );
+                if ( fVerbose ) printf( "Finished reading extension \"m\".\n" );
+            }
+            // read model name
+            else if ( *pCur == 'n' )
+            {
+                pCur++;
+                if ( (*pCur >= 'a' && *pCur <= 'z') || (*pCur >= 'A' && *pCur <= 'Z') || (*pCur >= '0' && *pCur <= '9') )
+                {
+                    pNew->pName = Abc_UtilStrsav( (char *)pCur );       pCur += strlen(pNew->pName) + 1;
+                }
+                else
+                {
+                    pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4;       pCur += 4;
+                    ABC_FREE( pNew->pName );
+                    pNew->pName = Abc_UtilStrsav( (char *)pCur );       pCur += strlen(pNew->pName) + 1;
+                    assert( pCur == pCurTemp );
+                }
+            }
+            // read placement
+            else if ( *pCur == 'p' )
+            {
+                Gia_Plc_t * pPlacement;
+                pCur++;
+                pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4;           pCur += 4;
+                pPlacement = ABC_ALLOC( Gia_Plc_t, Gia_ManObjNum(pNew) );
+                memcpy( pPlacement, pCur, 4*Gia_ManObjNum(pNew) );      pCur += 4*Gia_ManObjNum(pNew);
+                assert( pCur == pCurTemp );
+                pNew->pPlacement = pPlacement;
+                if ( fVerbose ) printf( "Finished reading extension \"p\".\n" );
+            }
+            // read choices
+            else if ( *pCur == 'q' )
+            {
+                int i, nPairs, iRepr, iNode;
+                assert( !Gia_ManHasChoices(pNew) );
+                pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(pNew) );
+                pCur++;
+                pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4;           pCur += 4;
+                nPairs = Gia_AigerReadInt(pCur);                        pCur += 4;
+                for ( i = 0; i < nPairs; i++ )
+                {
+                    iRepr = Gia_AigerReadInt(pCur);                     pCur += 4;
+                    iNode = Gia_AigerReadInt(pCur);                     pCur += 4;
+                    pNew->pSibls[iRepr] = iNode;
+                    assert( iRepr > iNode );
+                }
+                assert( pCur == pCurTemp );
+                if ( fVerbose ) printf( "Finished reading extension \"q\".\n" );
+            }
+            // read switching activity
+            else if ( *pCur == 'u' )
+            { 
+                unsigned char * pSwitching;
+                pCur++;
+                pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4;           pCur += 4;
+                pSwitching = ABC_ALLOC( unsigned char, Gia_ManObjNum(pNew) );
+                memcpy( pSwitching, pCur, Gia_ManObjNum(pNew) );        pCur += Gia_ManObjNum(pNew);
+                assert( pCur == pCurTemp );
+                if ( fVerbose ) printf( "Finished reading extension \"s\".\n" );
+            }
+            // read timing manager
+            else if ( *pCur == 't' )
+            {
+                pCur++;
+                vStr = Vec_StrStart( Gia_AigerReadInt(pCur) );          pCur += 4;
+                memcpy( Vec_StrArray(vStr), pCur, Vec_StrSize(vStr) );  pCur += Vec_StrSize(vStr);
+                pNew->pManTime = Tim_ManLoad( vStr, 0 );
+                Vec_StrFree( vStr );
+                if ( fVerbose ) printf( "Finished reading extension \"t\".\n" );
+            }
+            // read object classes
+            else if ( *pCur == 'v' )
+            {
+                pCur++;
+                pNew->vObjClasses = Vec_IntStart( Gia_AigerReadInt(pCur)/4 ); pCur += 4;
+                memcpy( Vec_IntArray(pNew->vObjClasses), pCur, 4*Vec_IntSize(pNew->vObjClasses) );
+                pCur += 4*Vec_IntSize(pNew->vObjClasses);
+                if ( fVerbose ) printf( "Finished reading extension \"v\".\n" );
+            }
+            else break;
+        }
+    }
+
+    // skipping the comments
+    Vec_IntFree( vNodes );
+
+    // update polarity of the additional outputs
+    if ( nBad || nConstr || nJust || nFair )
+        Gia_ManInvertConstraints( pNew );
+
+    // clean the PO drivers
+    if ( vPoTypes )
+    {
+        pNew = Gia_ManDupWithConstraints( pTemp = pNew, vPoTypes );
+        Gia_ManStop( pTemp );
+        Vec_IntFreeP( &vPoTypes );
+    }
+
+    if ( !fSkipStrash && Gia_ManHasDangling(pNew) )
+    {
+        Tim_Man_t * pManTime;
+        Vec_Int_t * vFlopMap, * vGateMap, * vObjMap;
+        vFlopMap = pNew->vFlopClasses; pNew->vFlopClasses = NULL;
+        vGateMap = pNew->vGateClasses; pNew->vGateClasses = NULL;
+        vObjMap  = pNew->vObjClasses;  pNew->vObjClasses  = NULL;
+        pManTime = (Tim_Man_t *)pNew->pManTime; pNew->pManTime     = NULL;
+        pNew = Gia_ManCleanup( pTemp = pNew );
+        if ( (vGateMap || vObjMap) && (Gia_ManObjNum(pNew) < Gia_ManObjNum(pTemp)) )
+            printf( "Cleanup removed objects after reading. Old gate/object abstraction maps are invalid!\n" );
+        Gia_ManStop( pTemp );
+        pNew->vFlopClasses = vFlopMap;
+        pNew->vGateClasses = vGateMap;
+        pNew->vObjClasses  = vObjMap;
+        pNew->pManTime     = pManTime;
+    }
+
+    if ( fHieOnly )
+    {
+//        Tim_ManPrint( (Tim_Man_t *)pNew->pManTime );
+        if ( Abc_FrameReadLibBox() == NULL )
+            printf( "Cannot create TIM manager because box library is not available.\n" );
+        else
+            Tim_ManCreate( (Tim_Man_t *)pNew->pManTime, Abc_FrameReadLibBox(), pNew->vInArrs, pNew->vOutReqs );
+    }
+    Vec_FltFreeP( &pNew->vInArrs );
+    Vec_FltFreeP( &pNew->vOutReqs );
+/*
+    // check the result
+    if ( fCheck && !Gia_ManCheck( pNew ) )
+    {
+        printf( "Gia_AigerRead: The network check has failed.\n" );
+        Gia_ManStop( pNew );
+        return NULL;
+    }
+*/
+
+    if ( vInits && Vec_IntSum(vInits) )
+    {
+        char * pInit = ABC_ALLOC( char, Vec_IntSize(vInits) + 1 );
+        Gia_Obj_t * pObj;
+        int i;
+        assert( Vec_IntSize(vInits) == Gia_ManRegNum(pNew) );
+        Gia_ManForEachRo( pNew, pObj, i )
+        {
+            if ( Vec_IntEntry(vInits, i) == 0 )
+                pInit[i] = '0';
+            else if ( Vec_IntEntry(vInits, i) == 1 )
+                pInit[i] = '1';
+            else 
+            {
+                assert( Vec_IntEntry(vInits, i) == Abc_Var2Lit(Gia_ObjId(pNew, pObj), 0) );
+                // unitialized value of the latch is the latch literal according to http://fmv.jku.at/hwmcc11/beyond1.pdf
+                pInit[i] = 'X';
+            }
+        }
+        pInit[i] = 0;
+        pNew = Gia_ManDupZeroUndc( pTemp = pNew, pInit, 1 );
+        pNew->nConstrs = pTemp->nConstrs; pTemp->nConstrs = 0;
+        Gia_ManStop( pTemp );
+        ABC_FREE( pInit );
+    }
+    Vec_IntFreeP( &vInits );
+    if ( !fSkipStrash && pNew->vMapping )
+        Abc_Print( 0, "Structural hashing enabled while reading AIGER may have invalidated the mapping.  Consider using \"&r -s\".\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the AIG in the binary AIGER format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_AigerRead( char * pFileName, int fSkipStrash, int fCheck )
+{
+    FILE * pFile;
+    Gia_Man_t * pNew;
+    char * pName, * pContents;
+    int nFileSize;
+    int RetValue;
+
+    // read the file into the buffer
+    Gia_FileFixName( pFileName );
+    nFileSize = Gia_FileSize( pFileName );
+    pFile = fopen( pFileName, "rb" );
+    pContents = ABC_ALLOC( char, nFileSize );
+    RetValue = fread( pContents, nFileSize, 1, pFile );
+    fclose( pFile );
+
+    pNew = Gia_AigerReadFromMemory( pContents, nFileSize, fSkipStrash, fCheck );
+    ABC_FREE( pContents );
+    if ( pNew )
+    {
+        ABC_FREE( pNew->pName );
+        pName = Gia_FileNameGeneric( pFileName );
+        pNew->pName = Abc_UtilStrsav( pName );
+        ABC_FREE( pName );
+
+        assert( pNew->pSpec == NULL );
+        pNew->pSpec = Abc_UtilStrsav( pFileName );
+    }
+    return pNew;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG in into the memory buffer.]
+
+  Description [The resulting buffer constains the AIG in AIGER format. 
+  The resulting buffer should be deallocated by the user.]
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Gia_AigerWriteIntoMemoryStr( Gia_Man_t * p )
+{
+    Vec_Str_t * vBuffer;
+    Gia_Obj_t * pObj;
+    int nNodes = 0, i, uLit, uLit0, uLit1; 
+    // set the node numbers to be used in the output file
+    Gia_ManConst0(p)->Value = nNodes++;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = nNodes++;
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = nNodes++;
+
+    // write the header "M I L O A" where M = I + L + A
+    vBuffer = Vec_StrAlloc( 3*Gia_ManObjNum(p) );
+    Vec_StrPrintStr( vBuffer, "aig " );
+    Vec_StrPrintNum( vBuffer, Gia_ManCandNum(p) );
+    Vec_StrPrintStr( vBuffer, " " );
+    Vec_StrPrintNum( vBuffer, Gia_ManPiNum(p) );
+    Vec_StrPrintStr( vBuffer, " " );
+    Vec_StrPrintNum( vBuffer, Gia_ManRegNum(p) );
+    Vec_StrPrintStr( vBuffer, " " );
+    Vec_StrPrintNum( vBuffer, Gia_ManPoNum(p) );
+    Vec_StrPrintStr( vBuffer, " " );
+    Vec_StrPrintNum( vBuffer, Gia_ManAndNum(p) );
+    Vec_StrPrintStr( vBuffer, "\n" );
+
+    // write latch drivers
+    Gia_ManForEachRi( p, pObj, i )
+    {
+        uLit = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) );
+        Vec_StrPrintNum( vBuffer, uLit );
+        Vec_StrPrintStr( vBuffer, "\n" );
+    }
+
+    // write PO drivers
+    Gia_ManForEachPo( p, pObj, i )
+    {
+        uLit = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) );
+        Vec_StrPrintNum( vBuffer, uLit );
+        Vec_StrPrintStr( vBuffer, "\n" );
+    }
+    // write the nodes into the buffer
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        uLit  = Abc_Var2Lit( Gia_ObjValue(pObj), 0 );
+        uLit0 = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) );
+        uLit1 = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin1(pObj)), Gia_ObjFaninC1(pObj) );
+        assert( uLit0 != uLit1 );
+        if ( uLit0 > uLit1 )
+        {
+            int Temp = uLit0;
+            uLit0 = uLit1;
+            uLit1 = Temp;
+        }
+        Gia_AigerWriteUnsigned( vBuffer, uLit  - uLit1 );
+        Gia_AigerWriteUnsigned( vBuffer, uLit1 - uLit0 );
+    }
+    Vec_StrPrintStr( vBuffer, "c" );
+    return vBuffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG in into the memory buffer.]
+
+  Description [The resulting buffer constains the AIG in AIGER format.
+  The CI/CO/AND nodes are assumed to be ordered according to some rule.
+  The resulting buffer should be deallocated by the user.]
+  
+  SideEffects [Note that in vCos, PIs are order first, followed by latches!]
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Gia_AigerWriteIntoMemoryStrPart( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, int nRegs )
+{
+    Vec_Str_t * vBuffer;
+    Gia_Obj_t * pObj;
+    int nNodes = 0, i, uLit, uLit0, uLit1; 
+    // set the node numbers to be used in the output file
+    Gia_ManConst0(p)->Value = nNodes++;
+    Gia_ManForEachObjVec( vCis, p, pObj, i )
+    {
+        assert( Gia_ObjIsCi(pObj) );
+        pObj->Value = nNodes++;
+    }
+    Gia_ManForEachObjVec( vAnds, p, pObj, i )
+    {
+        assert( Gia_ObjIsAnd(pObj) );
+        pObj->Value = nNodes++;
+    }
+
+    // write the header "M I L O A" where M = I + L + A
+    vBuffer = Vec_StrAlloc( 3*Gia_ManObjNum(p) );
+    Vec_StrPrintStr( vBuffer, "aig " );
+    Vec_StrPrintNum( vBuffer, Vec_IntSize(vCis) + Vec_IntSize(vAnds) );
+    Vec_StrPrintStr( vBuffer, " " );
+    Vec_StrPrintNum( vBuffer, Vec_IntSize(vCis) - nRegs );
+    Vec_StrPrintStr( vBuffer, " " );
+    Vec_StrPrintNum( vBuffer, nRegs );
+    Vec_StrPrintStr( vBuffer, " " );
+    Vec_StrPrintNum( vBuffer, Vec_IntSize(vCos) - nRegs );
+    Vec_StrPrintStr( vBuffer, " " );
+    Vec_StrPrintNum( vBuffer, Vec_IntSize(vAnds) );
+    Vec_StrPrintStr( vBuffer, "\n" );
+
+    // write latch drivers
+    Gia_ManForEachObjVec( vCos, p, pObj, i )
+    {
+        assert( Gia_ObjIsCo(pObj) );
+        if ( i < Vec_IntSize(vCos) - nRegs )
+            continue;
+        uLit = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) );
+        Vec_StrPrintNum( vBuffer, uLit );
+        Vec_StrPrintStr( vBuffer, "\n" );
+    }
+    // write output drivers
+    Gia_ManForEachObjVec( vCos, p, pObj, i )
+    {
+        assert( Gia_ObjIsCo(pObj) );
+        if ( i >= Vec_IntSize(vCos) - nRegs )
+            continue;
+        uLit = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) );
+        Vec_StrPrintNum( vBuffer, uLit );
+        Vec_StrPrintStr( vBuffer, "\n" );
+    }
+
+    // write the nodes into the buffer
+    Gia_ManForEachObjVec( vAnds, p, pObj, i )
+    {
+        uLit  = Abc_Var2Lit( Gia_ObjValue(pObj), 0 );
+        uLit0 = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) );
+        uLit1 = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin1(pObj)), Gia_ObjFaninC1(pObj) );
+        assert( uLit0 != uLit1 );
+        if ( uLit0 > uLit1 )
+        {
+            int Temp = uLit0;
+            uLit0 = uLit1;
+            uLit1 = Temp;
+        }
+        Gia_AigerWriteUnsigned( vBuffer, uLit  - uLit1 );
+        Gia_AigerWriteUnsigned( vBuffer, uLit1 - uLit0 );
+    }
+    Vec_StrPrintStr( vBuffer, "c" );
+    return vBuffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG in the binary AIGER format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fCompact )
+{
+    int fVerbose = XAIG_VERBOSE;
+    FILE * pFile;
+    Gia_Man_t * p;
+    Gia_Obj_t * pObj;
+    Vec_Str_t * vStrExt;
+    int i, nBufferSize, Pos;
+    unsigned char * pBuffer;
+    unsigned uLit0, uLit1, uLit;
+//    assert( Gia_ManIsNormalized(pInit) );
+    assert( pInit->nXors == 0 && pInit->nMuxes == 0 );
+
+    if ( Gia_ManCoNum(pInit) == 0 )
+    {
+        printf( "AIG cannot be written because it has no POs.\n" );
+        return;
+    }
+
+    // start the output stream
+    pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Gia_AigerWrite(): Cannot open the output file \"%s\".\n", pFileName );
+        return;
+    }
+
+    // create normalized AIG
+    if ( !Gia_ManIsNormalized(pInit) )
+    {
+//        printf( "Gia_AigerWrite(): Normalizing AIG for writing.\n" );
+        p = Gia_ManDupNormalize( pInit );
+        p->pManTime   = pInit->pManTime;   pInit->pManTime   = NULL;
+        p->vNamesIn   = pInit->vNamesIn;   pInit->vNamesIn   = NULL;
+        p->vNamesOut  = pInit->vNamesOut;  pInit->vNamesOut  = NULL;
+        p->pAigExtra  = pInit->pAigExtra;  pInit->pAigExtra  = NULL;
+        p->nAnd2Delay = pInit->nAnd2Delay; pInit->nAnd2Delay = 0;
+        p->nConstrs   = pInit->nConstrs;   pInit->nConstrs   = 0;
+    }
+    else
+        p = pInit;
+
+    // write the header "M I L O A" where M = I + L + A
+    fprintf( pFile, "aig%s %u %u %u %u %u", 
+        fCompact? "2" : "",
+        Gia_ManCiNum(p) + Gia_ManAndNum(p), 
+        Gia_ManPiNum(p),
+        Gia_ManRegNum(p),
+        Gia_ManConstrNum(p) ? 0 : Gia_ManPoNum(p),
+        Gia_ManAndNum(p) );
+    // write the extended header "B C J F"
+    if ( Gia_ManConstrNum(p) )
+        fprintf( pFile, " %u %u", Gia_ManPoNum(p) - Gia_ManConstrNum(p), Gia_ManConstrNum(p) );
+    fprintf( pFile, "\n" ); 
+
+    Gia_ManInvertConstraints( p );
+    if ( !fCompact ) 
+    {
+        // write latch drivers
+        Gia_ManForEachRi( p, pObj, i )
+            fprintf( pFile, "%u\n", Gia_ObjFaninLit0p(p, pObj) );
+        // write PO drivers
+        Gia_ManForEachPo( p, pObj, i )
+            fprintf( pFile, "%u\n", Gia_ObjFaninLit0p(p, pObj) );
+    }
+    else
+    {
+        Vec_Int_t * vLits = Gia_AigerCollectLiterals( p );
+        Vec_Str_t * vBinary = Gia_AigerWriteLiterals( vLits );
+        fwrite( Vec_StrArray(vBinary), 1, Vec_StrSize(vBinary), pFile );
+        Vec_StrFree( vBinary );
+        Vec_IntFree( vLits );
+    }
+    Gia_ManInvertConstraints( p );
+
+    // write the nodes into the buffer
+    Pos = 0;
+    nBufferSize = 8 * Gia_ManAndNum(p) + 100; // skeptically assuming 3 chars per one AIG edge
+    pBuffer = ABC_ALLOC( unsigned char, nBufferSize );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        uLit  = Abc_Var2Lit( i, 0 );
+        uLit0 = Gia_ObjFaninLit0( pObj, i );
+        uLit1 = Gia_ObjFaninLit1( pObj, i );
+        assert( uLit0 < uLit1 );
+        Pos = Gia_AigerWriteUnsignedBuffer( pBuffer, Pos, uLit  - uLit1 );
+        Pos = Gia_AigerWriteUnsignedBuffer( pBuffer, Pos, uLit1 - uLit0 );
+        if ( Pos > nBufferSize - 10 )
+        {
+            printf( "Gia_AigerWrite(): AIGER generation has failed because the allocated buffer is too small.\n" );
+	        fclose( pFile );
+            if ( p != pInit )
+                Gia_ManStop( p );
+            return;
+        }
+    }
+    assert( Pos < nBufferSize );
+
+    // write the buffer
+    fwrite( pBuffer, 1, Pos, pFile );
+    ABC_FREE( pBuffer );
+
+    // write the symbol table
+    if ( p->vNamesIn && p->vNamesOut )
+    {
+        assert( Vec_PtrSize(p->vNamesIn)  == Gia_ManCiNum(p) );
+        assert( Vec_PtrSize(p->vNamesOut) == Gia_ManCoNum(p) );
+        // write PIs
+        Gia_ManForEachPi( p, pObj, i )
+            fprintf( pFile, "i%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesIn, i) );
+        // write latches
+        Gia_ManForEachRo( p, pObj, i )
+            fprintf( pFile, "l%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesIn, Gia_ManPiNum(p) + i) );
+        // write POs
+        Gia_ManForEachPo( p, pObj, i )
+            fprintf( pFile, "o%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesOut, i) );
+    }
+
+    // write the comment
+//    fprintf( pFile, "c\n" );
+    fprintf( pFile, "c" );
+
+    // write additional AIG
+    if ( p->pAigExtra )
+    {
+        fprintf( pFile, "a" );
+        vStrExt = Gia_AigerWriteIntoMemoryStr( p->pAigExtra );
+        Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) );
+        fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile );
+        Vec_StrFree( vStrExt );
+        if ( fVerbose ) printf( "Finished writing extension \"a\".\n" );
+    }
+    // write constraints
+    if ( p->nConstrs )
+    {
+        fprintf( pFile, "c" );
+        Gia_FileWriteBufferSize( pFile, 4 );
+        Gia_FileWriteBufferSize( pFile, p->nConstrs );
+    }
+    // write timing information
+    if ( p->nAnd2Delay )
+    {
+        fprintf( pFile, "d" );
+        Gia_FileWriteBufferSize( pFile, 4 );
+        Gia_FileWriteBufferSize( pFile, p->nAnd2Delay );
+    }
+    if ( p->pManTime )
+    {
+        float * pTimes;
+        pTimes = Tim_ManGetArrTimes( (Tim_Man_t *)p->pManTime );
+        if ( pTimes )
+        {
+            fprintf( pFile, "i" );
+            Gia_FileWriteBufferSize( pFile, 4*Tim_ManPiNum((Tim_Man_t *)p->pManTime) );
+            fwrite( pTimes, 1, 4*Tim_ManPiNum((Tim_Man_t *)p->pManTime), pFile );
+            ABC_FREE( pTimes );
+            if ( fVerbose ) printf( "Finished writing extension \"i\".\n" );
+        }
+        pTimes = Tim_ManGetReqTimes( (Tim_Man_t *)p->pManTime );
+        if ( pTimes )
+        {
+            fprintf( pFile, "o" );
+            Gia_FileWriteBufferSize( pFile, 4*Tim_ManPoNum((Tim_Man_t *)p->pManTime) );
+            fwrite( pTimes, 1, 4*Tim_ManPoNum((Tim_Man_t *)p->pManTime), pFile );
+            ABC_FREE( pTimes );
+            if ( fVerbose ) printf( "Finished writing extension \"o\".\n" );
+        }
+    }
+    // write equivalences
+    if ( p->pReprs && p->pNexts )
+    {
+        extern Vec_Str_t * Gia_WriteEquivClasses( Gia_Man_t * p );
+        fprintf( pFile, "e" );
+        vStrExt = Gia_WriteEquivClasses( p );
+        Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) );
+        fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile );
+        Vec_StrFree( vStrExt );
+    }
+    // write flop classes
+    if ( p->vFlopClasses )
+    {
+        fprintf( pFile, "f" );
+        Gia_FileWriteBufferSize( pFile, 4*Gia_ManRegNum(p) );
+        assert( Vec_IntSize(p->vFlopClasses) == Gia_ManRegNum(p) );
+        fwrite( Vec_IntArray(p->vFlopClasses), 1, 4*Gia_ManRegNum(p), pFile );
+    }
+    // write gate classes
+    if ( p->vGateClasses )
+    {
+        fprintf( pFile, "g" );
+        Gia_FileWriteBufferSize( pFile, 4*Gia_ManObjNum(p) );
+        assert( Vec_IntSize(p->vGateClasses) == Gia_ManObjNum(p) );
+        fwrite( Vec_IntArray(p->vGateClasses), 1, 4*Gia_ManObjNum(p), pFile );
+    }
+    // write hierarchy info
+    if ( p->pManTime )
+    {
+        fprintf( pFile, "h" );
+        vStrExt = Tim_ManSave( (Tim_Man_t *)p->pManTime, 1 );
+        Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) );
+        fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile );
+        Vec_StrFree( vStrExt );
+        if ( fVerbose ) printf( "Finished writing extension \"h\".\n" );
+    }
+    // write packing
+    if ( p->vPacking )
+    {
+        extern Vec_Str_t * Gia_WritePacking( Vec_Int_t * vPacking );
+        fprintf( pFile, "k" );
+        vStrExt = Gia_WritePacking( p->vPacking );
+        Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) );
+        fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile );
+        Vec_StrFree( vStrExt );
+        if ( fVerbose ) printf( "Finished writing extension \"k\".\n" );
+    }
+    // write mapping
+    if ( Gia_ManHasMapping(p) )
+    {
+        extern Vec_Str_t * Gia_AigerWriteMapping( Gia_Man_t * p );
+        extern Vec_Str_t * Gia_AigerWriteMappingSimple( Gia_Man_t * p );
+        extern Vec_Str_t * Gia_AigerWriteMappingDoc( Gia_Man_t * p );
+        fprintf( pFile, "m" );
+        vStrExt = Gia_AigerWriteMappingDoc( p );
+        Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) );
+        fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile );
+        Vec_StrFree( vStrExt );
+        if ( fVerbose ) printf( "Finished writing extension \"m\".\n" );
+    }
+    // write placement
+    if ( p->pPlacement )
+    {
+        fprintf( pFile, "p" );
+        Gia_FileWriteBufferSize( pFile, 4*Gia_ManObjNum(p) );
+        fwrite( p->pPlacement, 1, 4*Gia_ManObjNum(p), pFile );
+    }
+    // write choices
+    if ( Gia_ManHasChoices(p) )
+    {
+        int i, nPairs = 0;
+        fprintf( pFile, "q" );
+        for ( i = 0; i < Gia_ManObjNum(p); i++ )
+            nPairs += (Gia_ObjSibl(p, i) > 0);
+        Gia_FileWriteBufferSize( pFile, 4*(nPairs * 2 + 1) );
+        Gia_FileWriteBufferSize( pFile, nPairs );
+        for ( i = 0; i < Gia_ManObjNum(p); i++ )
+            if ( Gia_ObjSibl(p, i) )
+            {
+                assert( i > Gia_ObjSibl(p, i) );
+                Gia_FileWriteBufferSize( pFile, i );
+                Gia_FileWriteBufferSize( pFile, Gia_ObjSibl(p, i) );
+            }
+        if ( fVerbose ) printf( "Finished writing extension \"q\".\n" );
+    }
+    // write switching activity
+    if ( p->pSwitching )
+    {
+        fprintf( pFile, "u" );
+        Gia_FileWriteBufferSize( pFile, Gia_ManObjNum(p) );
+        fwrite( p->pSwitching, 1, Gia_ManObjNum(p), pFile );
+    }
+/*
+    // write timing information
+    if ( p->pManTime )
+    {
+        fprintf( pFile, "t" );
+        vStrExt = Tim_ManSave( (Tim_Man_t *)p->pManTime, 0 );
+        Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) );
+        fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile );
+        Vec_StrFree( vStrExt );
+    }
+*/
+    // write object classes
+    if ( p->vObjClasses )
+    {
+        fprintf( pFile, "v" );
+        Gia_FileWriteBufferSize( pFile, 4*Gia_ManObjNum(p) );
+        assert( Vec_IntSize(p->vObjClasses) == Gia_ManObjNum(p) );
+        fwrite( Vec_IntArray(p->vObjClasses), 1, 4*Gia_ManObjNum(p), pFile );
+    }
+    // write name
+    if ( p->pName )
+    {
+        fprintf( pFile, "n" );
+        Gia_FileWriteBufferSize( pFile, strlen(p->pName)+1 );
+        fwrite( p->pName, 1, strlen(p->pName), pFile );
+        fprintf( pFile, "%c", '\0' );
+    }
+    // write comments
+    fprintf( pFile, "\nThis file was produced by the GIA package in ABC on %s\n", Gia_TimeStamp() );
+    fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" );
+	fclose( pFile );
+    if ( p != pInit )
+    {
+        pInit->pManTime  = p->pManTime;  p->pManTime = NULL;
+        pInit->vNamesIn  = p->vNamesIn;  p->vNamesIn = NULL;
+        pInit->vNamesOut = p->vNamesOut; p->vNamesOut = NULL;
+        Gia_ManStop( p );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG in the binary AIGER format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_DumpAiger( Gia_Man_t * p, char * pFilePrefix, int iFileNum, int nFileNumDigits )
+{
+    char Buffer[100];
+    sprintf( Buffer, "%s%0*d.aig", pFilePrefix, nFileNumDigits, iFileNum );
+    Gia_AigerWrite( p, Buffer, 0, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG in the binary AIGER format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_AigerWriteSimple( Gia_Man_t * pInit, char * pFileName )
+{
+    FILE * pFile;
+    Vec_Str_t * vStr;
+    if ( Gia_ManPoNum(pInit) == 0 )
+    {
+        printf( "Gia_AigerWriteSimple(): AIG cannot be written because it has no POs.\n" );
+        return;
+    }
+    // start the output stream
+    pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Gia_AigerWriteSimple(): Cannot open the output file \"%s\".\n", pFileName );
+        return;
+    }
+    // write the buffer
+    vStr = Gia_AigerWriteIntoMemoryStr( pInit );
+    fwrite( Vec_StrArray(vStr), 1, Vec_StrSize(vStr), pFile );
+    Vec_StrFree( vStr );
+	fclose( pFile );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaAigerExt.c b/abc-build/src/aig/gia/giaAigerExt.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaAigerExt.c
@@ -0,0 +1,326 @@
+/**CFile****************************************************************
+
+  FileName    [giaAigerExt.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Custom AIGER extensions.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaAigerExt.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Read/write equivalence classes information.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Rpr_t * Gia_AigerReadEquivClasses( unsigned char ** ppPos, int nSize )
+{
+    Gia_Rpr_t * pReprs;
+    unsigned char * pStop;
+    int i, Item, fProved, iRepr, iNode;
+    pStop = *ppPos;
+    pStop += Gia_AigerReadInt( *ppPos ); *ppPos += 4;
+    pReprs = ABC_CALLOC( Gia_Rpr_t, nSize );
+    for ( i = 0; i < nSize; i++ )
+        pReprs[i].iRepr = GIA_VOID;
+    iRepr = iNode = 0;
+    while ( *ppPos < pStop )
+    {
+        Item = Gia_AigerReadUnsigned( ppPos );
+        if ( Item & 1 )
+        {
+            iRepr += (Item >> 1);
+            iNode = iRepr;
+            continue;
+        }
+        Item >>= 1;
+        fProved = (Item & 1);
+        Item >>= 1;
+        iNode += Item;
+        pReprs[iNode].fProved = fProved;
+        pReprs[iNode].iRepr = iRepr;
+        assert( iRepr < iNode );
+    }
+    return pReprs;
+}
+unsigned char * Gia_WriteEquivClassesInt( Gia_Man_t * p, int * pEquivSize )
+{
+    unsigned char * pBuffer;
+    int iRepr, iNode, iPrevRepr, iPrevNode, iLit, nItems, iPos;
+    assert( p->pReprs && p->pNexts );
+    // count the number of entries to be written
+    nItems = 0;
+    for ( iRepr = 1; iRepr < Gia_ManObjNum(p); iRepr++ )
+    {
+        nItems += Gia_ObjIsConst( p, iRepr );
+        if ( !Gia_ObjIsHead(p, iRepr) )
+            continue;
+        Gia_ClassForEachObj( p, iRepr, iNode )
+            nItems++;
+    }
+    pBuffer = ABC_ALLOC( unsigned char, sizeof(int) * (nItems + 10) );
+    // write constant class
+    iPos = Gia_AigerWriteUnsignedBuffer( pBuffer, 4, Abc_Var2Lit(0, 1) );
+    iPrevNode = 0;
+    for ( iNode = 1; iNode < Gia_ManObjNum(p); iNode++ )
+        if ( Gia_ObjIsConst(p, iNode) )
+        {
+            iLit = Abc_Var2Lit( iNode - iPrevNode, Gia_ObjProved(p, iNode) );
+            iPrevNode = iNode;
+            iPos = Gia_AigerWriteUnsignedBuffer( pBuffer, iPos, Abc_Var2Lit(iLit, 0) );
+        }
+    // write non-constant classes
+    iPrevRepr = 0;
+    Gia_ManForEachClass( p, iRepr )
+    {
+        iPos = Gia_AigerWriteUnsignedBuffer( pBuffer, iPos, Abc_Var2Lit(iRepr - iPrevRepr, 1) );
+        iPrevRepr = iPrevNode = iRepr;
+        Gia_ClassForEachObj1( p, iRepr, iNode )
+        {
+            iLit = Abc_Var2Lit( iNode - iPrevNode, Gia_ObjProved(p, iNode) );
+            iPrevNode = iNode;
+            iPos = Gia_AigerWriteUnsignedBuffer( pBuffer, iPos, Abc_Var2Lit(iLit, 0) );
+        }
+    }
+    Gia_AigerWriteInt( pBuffer, iPos );
+    *pEquivSize = iPos;
+    return pBuffer;
+}
+Vec_Str_t * Gia_WriteEquivClasses( Gia_Man_t * p )
+{
+    int nEquivSize;
+    unsigned char * pBuffer = Gia_WriteEquivClassesInt( p, &nEquivSize );
+    return Vec_StrAllocArray( (char *)pBuffer, nEquivSize );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read/write mapping information.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Gia_AigerReadDiffValue( unsigned char ** ppPos, int iPrev )
+{
+    int Item = Gia_AigerReadUnsigned( ppPos );
+    if ( Item & 1 )
+        return iPrev + (Item >> 1);
+    return iPrev - (Item >> 1);
+}
+int * Gia_AigerReadMapping( unsigned char ** ppPos, int nSize )
+{
+    int * pMapping;
+    unsigned char * pStop;
+    int k, j, nFanins, nAlloc, iNode = 0, iOffset = nSize;
+    pStop = *ppPos;
+    pStop += Gia_AigerReadInt( *ppPos ); *ppPos += 4;
+    nAlloc = nSize + pStop - *ppPos;
+    pMapping = ABC_CALLOC( int, nAlloc );
+    while ( *ppPos < pStop )
+    {
+        k = iOffset;
+        pMapping[k++] = nFanins = Gia_AigerReadUnsigned( ppPos );
+        for ( j = 0; j <= nFanins; j++ )
+            pMapping[k++] = iNode = Gia_AigerReadDiffValue( ppPos, iNode );
+        pMapping[iNode] = iOffset;
+        iOffset = k;
+    }
+    assert( iOffset <= nAlloc );
+    return pMapping;
+}
+static inline int Gia_AigerWriteDiffValue( unsigned char * pPos, int iPos, int iPrev, int iThis )
+{
+    if ( iPrev < iThis )
+        return Gia_AigerWriteUnsignedBuffer( pPos, iPos, Abc_Var2Lit(iThis - iPrev, 1) );
+    return Gia_AigerWriteUnsignedBuffer( pPos, iPos, Abc_Var2Lit(iPrev - iThis, 0) );
+}
+unsigned char * Gia_AigerWriteMappingInt( Gia_Man_t * p, int * pMapSize )
+{
+    unsigned char * pBuffer;
+    int i, k, iPrev, iFan, nItems, iPos = 4;
+    assert( Gia_ManHasMapping(p) );
+    // count the number of entries to be written
+    nItems = 0;
+    Gia_ManForEachLut( p, i )
+        nItems += 2 + Gia_ObjLutSize( p, i );
+    pBuffer = ABC_ALLOC( unsigned char, sizeof(int) * (nItems + 1) );
+    // write non-constant classes
+    iPrev = 0;
+    Gia_ManForEachLut( p, i )
+    {
+//printf( "\nSize = %d ", Gia_ObjLutSize(p, i) );
+        iPos = Gia_AigerWriteUnsignedBuffer( pBuffer, iPos, Gia_ObjLutSize(p, i) );
+        Gia_LutForEachFanin( p, i, iFan, k )
+        {
+//printf( "Fan = %d ", iFan );
+            iPos = Gia_AigerWriteDiffValue( pBuffer, iPos, iPrev, iFan );
+            iPrev = iFan;
+        }
+        iPos = Gia_AigerWriteDiffValue( pBuffer, iPos, iPrev, i );
+        iPrev = i;
+//printf( "Node = %d ", i );
+    }
+//printf( "\n" );
+    Gia_AigerWriteInt( pBuffer, iPos );
+    *pMapSize = iPos;
+    return pBuffer;
+}
+Vec_Str_t * Gia_AigerWriteMapping( Gia_Man_t * p )
+{
+    int nMapSize;
+    unsigned char * pBuffer = Gia_AigerWriteMappingInt( p, &nMapSize );
+    return Vec_StrAllocArray( (char *)pBuffer, nMapSize );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read/write mapping information.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Gia_AigerReadMappingSimple( unsigned char ** ppPos, int nSize )
+{
+    int * pMapping = ABC_ALLOC( int, nSize/4 );
+    memcpy( pMapping, *ppPos, nSize );
+    assert( nSize % 4 == 0 );
+    return pMapping;
+}
+Vec_Str_t * Gia_AigerWriteMappingSimple( Gia_Man_t * p )
+{
+    unsigned char * pBuffer = ABC_ALLOC( unsigned char, 4*Vec_IntSize(p->vMapping) );
+    memcpy( pBuffer, Vec_IntArray(p->vMapping), 4*Vec_IntSize(p->vMapping) );
+    assert( Vec_IntSize(p->vMapping) >= Gia_ManObjNum(p) );
+    return Vec_StrAllocArray( (char *)pBuffer, 4*Vec_IntSize(p->vMapping) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read/write mapping information.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_AigerReadMappingDoc( unsigned char ** ppPos, int nObjs )
+{
+    int * pMapping, nLuts, LutSize, iRoot, nFanins, i, k, nOffset;
+    nLuts    = Gia_AigerReadInt( *ppPos ); *ppPos += 4;
+    LutSize  = Gia_AigerReadInt( *ppPos ); *ppPos += 4;
+    pMapping = ABC_CALLOC( int, nObjs + (LutSize + 2) * nLuts );
+    nOffset = nObjs;
+    for ( i = 0; i < nLuts; i++ )
+    {
+        iRoot   = Gia_AigerReadInt( *ppPos ); *ppPos += 4;
+        nFanins = Gia_AigerReadInt( *ppPos ); *ppPos += 4;
+        pMapping[iRoot] = nOffset;
+        // write one
+        pMapping[ nOffset++ ] = nFanins; 
+        for ( k = 0; k < nFanins; k++ )
+        {
+            pMapping[ nOffset++ ] = Gia_AigerReadInt( *ppPos ); *ppPos += 4;
+        }
+        pMapping[ nOffset++ ] = iRoot; 
+    }
+    return Vec_IntAllocArray( pMapping, nOffset );
+}
+Vec_Str_t * Gia_AigerWriteMappingDoc( Gia_Man_t * p )
+{
+    unsigned char * pBuffer;
+    int i, k, iFan, nLuts = 0, LutSize = 0, nSize = 2, nSize2 = 0;
+    Gia_ManForEachLut( p, i )
+    {
+        nLuts++;
+        nSize += Gia_ObjLutSize(p, i) + 2;
+        LutSize = Abc_MaxInt( LutSize, Gia_ObjLutSize(p, i) );
+    }
+    pBuffer = ABC_ALLOC( unsigned char, 4 * nSize );
+    Gia_AigerWriteInt( pBuffer + 4 * nSize2++, nLuts );  
+    Gia_AigerWriteInt( pBuffer + 4 * nSize2++, LutSize );
+    Gia_ManForEachLut( p, i )
+    {
+        Gia_AigerWriteInt( pBuffer + 4 * nSize2++, i );
+        Gia_AigerWriteInt( pBuffer + 4 * nSize2++, Gia_ObjLutSize(p, i) );
+        Gia_LutForEachFanin( p, i, iFan, k )
+            Gia_AigerWriteInt( pBuffer + 4 * nSize2++, iFan );
+    }
+    assert( nSize2 == nSize );
+    return Vec_StrAllocArray( (char *)pBuffer, 4*nSize );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read/write packing information.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_AigerReadPacking( unsigned char ** ppPos, int nSize )
+{
+    Vec_Int_t * vPacking = Vec_IntAlloc( nSize/4 );
+    int i;
+    assert( nSize % 4 == 0 );
+    for ( i = 0; i < nSize/4; i++, *ppPos += 4 )
+        Vec_IntPush( vPacking, Gia_AigerReadInt( *ppPos ) );
+    return vPacking;
+}
+Vec_Str_t * Gia_WritePacking( Vec_Int_t * vPacking )
+{
+    unsigned char * pBuffer = ABC_ALLOC( unsigned char, 4*Vec_IntSize(vPacking) );
+    int i, Entry, nSize = 0;
+    Vec_IntForEachEntry( vPacking, Entry, i )
+        Gia_AigerWriteInt( pBuffer + 4 * nSize++, Entry );
+    return Vec_StrAllocArray( (char *)pBuffer, 4*Vec_IntSize(vPacking) );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaBalance.c b/abc-build/src/aig/gia/giaBalance.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaBalance.c
@@ -0,0 +1,1151 @@
+/**CFile****************************************************************
+
+  FileName    [giaBalance.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [AIG balancing.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaBalance.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/vec/vecHash.h"
+#include "misc/vec/vecQue.h"
+#include "opt/dau/dau.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// operation manager
+typedef struct Dam_Man_t_ Dam_Man_t;
+struct Dam_Man_t_
+{
+    Gia_Man_t *      pGia;      // user's AIG
+    Vec_Int_t *      vNod2Set;  // node ID into fanin set
+    Vec_Int_t *      vDiv2Nod;  // div ID into root node set
+    Vec_Int_t *      vSetStore; // fanin set storage
+    Vec_Int_t *      vNodStore; // root node set storage
+    Vec_Flt_t *      vCounts;   // occur counts
+    Vec_Int_t *      vNodLevR;  // node reverse level
+    Vec_Int_t *      vDivLevR;  // divisor reverse level
+    Vec_Int_t *      vVisit;    // visited MUXes
+    Vec_Que_t *      vQue;      // pairs by their weight
+    Hash_IntMan_t *  vHash;     // pair hash table
+    abctime          clkStart;  // starting the clock
+    int              nLevelMax; // maximum level
+    int              nDivs;     // extracted divisor count
+    int              nAnds;     // total AND node count
+    int              nGain;     // total gain in AND nodes
+    int              nGainX;    // gain from XOR nodes
+};
+
+static inline int    Dam_ObjHand( Dam_Man_t * p, int i )     { return i < Vec_IntSize(p->vNod2Set) ? Vec_IntEntry(p->vNod2Set, i) : 0;                      }
+static inline int *  Dam_ObjSet( Dam_Man_t * p, int i )      { int h = Dam_ObjHand(p, i); if ( h == 0 ) return NULL; return Vec_IntEntryP(p->vSetStore, h); }
+
+static inline int    Dam_DivHand( Dam_Man_t * p, int d )     { return d < Vec_IntSize(p->vDiv2Nod) ? Vec_IntEntry(p->vDiv2Nod, d) : 0;                      }
+static inline int *  Dam_DivSet( Dam_Man_t * p, int d )      { int h = Dam_DivHand(p, d); if ( h == 0 ) return NULL; return Vec_IntEntryP(p->vNodStore, h); }
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Simplify multi-input AND/XOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSimplifyXor( Vec_Int_t * vSuper )
+{
+    int i, k = 0, Prev = -1, This, fCompl = 0;
+    Vec_IntForEachEntry( vSuper, This, i )
+    {
+        if ( This == 0 )
+            continue;
+        if ( This == 1 )
+            fCompl ^= 1; 
+        else if ( Prev != This )
+            Vec_IntWriteEntry( vSuper, k++, This ), Prev = This;
+        else
+            Prev = -1, k--;
+    }
+    Vec_IntShrink( vSuper, k );
+    if ( Vec_IntSize( vSuper ) == 0 )
+        Vec_IntPush( vSuper, fCompl );
+    else if ( fCompl )
+        Vec_IntWriteEntry( vSuper, 0, Abc_LitNot(Vec_IntEntry(vSuper, 0)) );
+}
+void Gia_ManSimplifyAnd( Vec_Int_t * vSuper )
+{
+    int i, k = 0, Prev = -1, This;
+    Vec_IntForEachEntry( vSuper, This, i )
+    {
+        if ( This == 0 )
+            { Vec_IntFill(vSuper, 1, 0); return; }
+        if ( This == 1 )
+            continue;
+        if ( Prev == -1 || Abc_Lit2Var(Prev) != Abc_Lit2Var(This) )
+            Vec_IntWriteEntry( vSuper, k++, This ), Prev = This;
+        else if ( Prev != This )
+            { Vec_IntFill(vSuper, 1, 0); return; }
+    }
+    Vec_IntShrink( vSuper, k );
+    if ( Vec_IntSize( vSuper ) == 0 )
+        Vec_IntPush( vSuper, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect multi-input AND/XOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSuperCollectXor_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    assert( !Gia_IsComplement(pObj) );
+    if ( !Gia_ObjIsXor(pObj) || 
+//        Gia_ObjRefNum(p, pObj) > 1 || 
+        Gia_ObjRefNum(p, pObj) > 2 || 
+        (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || 
+        Vec_IntSize(p->vSuper) > 100 )
+    {
+        Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) );
+        return;
+    }
+    assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) );
+    Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj) );
+    Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj) );
+}
+void Gia_ManSuperCollectAnd_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( Gia_IsComplement(pObj) || 
+        !Gia_ObjIsAndReal(p, pObj) || 
+//        Gia_ObjRefNum(p, pObj) > 1 || 
+        Gia_ObjRefNum(p, pObj) > 2 || 
+        (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || 
+        Vec_IntSize(p->vSuper) > 100 )
+    {
+        Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) );
+        return;
+    }
+    Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj) );
+    Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj) );
+}
+void Gia_ManSuperCollect( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+//    int nSize;
+    if ( p->vSuper == NULL )
+        p->vSuper = Vec_IntAlloc( 1000 );
+    else
+        Vec_IntClear( p->vSuper );
+    if ( Gia_ObjIsXor(pObj) )
+    {
+        assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) );
+        Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj) );
+        Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj) );
+//        nSize = Vec_IntSize(vSuper);
+        Vec_IntSort( p->vSuper, 0 );
+        Gia_ManSimplifyXor( p->vSuper );
+//        if ( nSize != Vec_IntSize(vSuper) )
+//            printf( "X %d->%d  ", nSize, Vec_IntSize(vSuper) );
+    }
+    else if ( Gia_ObjIsAndReal(p, pObj) )
+    {
+        Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj) );
+        Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj) );
+//        nSize = Vec_IntSize(vSuper);
+        Vec_IntSort( p->vSuper, 0 );
+        Gia_ManSimplifyAnd( p->vSuper );
+//        if ( nSize != Vec_IntSize(vSuper) )
+//            printf( "A %d->%d  ", nSize, Vec_IntSize(vSuper) );
+    }
+    else assert( 0 );
+//    if ( nSize > 10 )
+//        printf( "%d ", nSize );
+    assert( Vec_IntSize(p->vSuper) > 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCreateGate( Gia_Man_t * pNew, Gia_Obj_t * pObj, Vec_Int_t * vSuper )
+{
+    int iLit0 = Vec_IntPop(vSuper);
+    int iLit1 = Vec_IntPop(vSuper);
+    int iLit, i;
+    if ( !Gia_ObjIsXor(pObj) )
+        iLit = Gia_ManHashAnd( pNew, iLit0, iLit1 );
+    else if ( pNew->pMuxes )
+        iLit = Gia_ManHashXorReal( pNew, iLit0, iLit1 );
+    else 
+        iLit = Gia_ManHashXor( pNew, iLit0, iLit1 );
+    Vec_IntPush( vSuper, iLit );
+    Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(iLit)) );
+    // shift to the corrent location
+    for ( i = Vec_IntSize(vSuper)-1; i > 0; i-- )
+    {
+        int iLit1 = Vec_IntEntry(vSuper, i);
+        int iLit2 = Vec_IntEntry(vSuper, i-1);
+        if ( Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit1)) <= Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit2)) )
+            break;
+        Vec_IntWriteEntry( vSuper, i,   iLit2 );
+        Vec_IntWriteEntry( vSuper, i-1, iLit1 );
+    }
+}
+int Gia_ManBalanceGate( Gia_Man_t * pNew, Gia_Obj_t * pObj, Vec_Int_t * vSuper, int * pLits, int nLits )
+{
+    Vec_IntClear( vSuper );
+    if ( nLits == 1 )
+        Vec_IntPush( vSuper, pLits[0] );
+    else if ( nLits == 2 )
+    {
+        Vec_IntPush( vSuper, pLits[0] );
+        Vec_IntPush( vSuper, pLits[1] );
+        Gia_ManCreateGate( pNew, pObj, vSuper );
+    }
+    else if ( nLits > 2 )
+    {
+        // collect levels
+        int i, * pArray, * pPerm;
+        for ( i = 0; i < nLits; i++ )
+            Vec_IntPush( vSuper, Gia_ObjLevelId(pNew, Abc_Lit2Var(pLits[i])) );
+        // sort by level
+        Vec_IntGrow( vSuper, 4 * nLits );        
+        pArray = Vec_IntArray( vSuper );
+        pPerm = pArray + nLits;
+        Abc_QuickSortCostData( pArray, nLits, 1, (word *)(pArray + 2 * nLits), pPerm );
+        // collect in the increasing order of level
+        for ( i = 0; i < nLits; i++ )
+            Vec_IntWriteEntry( vSuper, i, pLits[pPerm[i]] );
+        Vec_IntShrink( vSuper, nLits );
+//        Vec_IntForEachEntry( vSuper, iLit, i )
+//            printf( "%d ", Gia_ObjLevel(pNew, Gia_ManObj( pNew, Abc_Lit2Var(iLit) )) );
+//        printf( "\n" );
+        // perform incremental extraction
+        while ( Vec_IntSize(vSuper) > 1 )
+            Gia_ManCreateGate( pNew, pObj, vSuper );
+    }
+    // consider trivial case
+    assert( Vec_IntSize(vSuper) == 1 );
+    return Vec_IntEntry(vSuper, 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManBalance_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    int i, iLit, iBeg, iEnd;
+    if ( ~pObj->Value )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    // handle MUX
+    if ( Gia_ObjIsMux(p, pObj) )
+    {
+        Gia_ManBalance_rec( pNew, p, Gia_ObjFanin0(pObj) );
+        Gia_ManBalance_rec( pNew, p, Gia_ObjFanin1(pObj) );
+        Gia_ManBalance_rec( pNew, p, Gia_ObjFanin2(p, pObj) );
+        pObj->Value = Gia_ManHashMuxReal( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) );
+        Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value)) );
+        return;
+    }
+    // find supergate
+    Gia_ManSuperCollect( p, pObj );
+    // save entries
+    if ( p->vStore == NULL )
+        p->vStore = Vec_IntAlloc( 1000 );
+    iBeg = Vec_IntSize( p->vStore );
+    Vec_IntAppend( p->vStore, p->vSuper );
+    iEnd = Vec_IntSize( p->vStore );
+    // call recursively
+    Vec_IntForEachEntryStartStop( p->vStore, iLit, i, iBeg, iEnd )
+    {
+        Gia_Obj_t * pTemp = Gia_ManObj( p, Abc_Lit2Var(iLit) );
+        Gia_ManBalance_rec( pNew, p, pTemp );
+        Vec_IntWriteEntry( p->vStore, i, Abc_LitNotCond(pTemp->Value, Abc_LitIsCompl(iLit)) );
+    }
+    assert( Vec_IntSize(p->vStore) == iEnd );
+    // consider general case
+    pObj->Value = Gia_ManBalanceGate( pNew, pObj, p->vSuper, Vec_IntEntryP(p->vStore, iBeg), iEnd-iBeg );
+    Vec_IntShrink( p->vStore, iBeg );
+}
+Gia_Man_t * Gia_ManBalanceInt( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManFillValue( p );
+    Gia_ManCreateRefs( p ); 
+    // start the new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc );
+    pNew->vLevels = Vec_IntStart( pNew->nObjsAlloc );
+    // create constant and inputs
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    // create internal nodes
+    Gia_ManHashStart( pNew );
+    Gia_ManForEachCo( p, pObj, i )
+    {
+        Gia_ManBalance_rec( pNew, p, Gia_ObjFanin0(pObj) );
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+    assert( Gia_ManObjNum(pNew) <= Gia_ManObjNum(p) );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    // perform cleanup
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManBalance( Gia_Man_t * p, int fSimpleAnd, int fVerbose )
+{
+    Gia_Man_t * pNew, * pNew1, * pNew2;
+    if ( fVerbose )      Gia_ManPrintStats( p, NULL );
+    pNew = fSimpleAnd ? Gia_ManDup( p ) : Gia_ManDupMuxes( p, 2 );
+    if ( fVerbose )      Gia_ManPrintStats( pNew, NULL );
+    pNew1 = Gia_ManBalanceInt( pNew );
+    if ( fVerbose )      Gia_ManPrintStats( pNew1, NULL );
+    Gia_ManStop( pNew );
+    pNew2 = Gia_ManDupNoMuxes( pNew1 );
+    if ( fVerbose )      Gia_ManPrintStats( pNew2, NULL );
+    Gia_ManStop( pNew1 );
+    return pNew2;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dam_Man_t * Dam_ManAlloc( Gia_Man_t * pGia )
+{
+    Dam_Man_t * p;
+    p = ABC_CALLOC( Dam_Man_t, 1 );
+    p->clkStart = Abc_Clock();
+    p->vVisit = Vec_IntAlloc( 1000 );
+    p->pGia = pGia;
+    return p;
+}
+void Dam_ManFree( Dam_Man_t * p )
+{   
+    Vec_IntFreeP( &p->vVisit );
+    Vec_IntFreeP( &p->vDivLevR );
+    Vec_IntFreeP( &p->vNodLevR );
+    Vec_IntFreeP( &p->vNod2Set );
+    Vec_IntFreeP( &p->vDiv2Nod );
+    Vec_IntFreeP( &p->vSetStore );
+    Vec_IntFreeP( &p->vNodStore );
+    Vec_FltFreeP( &p->vCounts );
+    Vec_QueFreeP( &p->vQue );
+    Hash_IntManStop( p->vHash );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect initial multi-input gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dam_ManCollectSets_rec( Dam_Man_t * p, int Id )
+{
+    Gia_Obj_t * pObj;
+    int i, iBeg, iEnd, iLit;
+    if ( Dam_ObjHand(p, Id) || Id == 0 )
+        return;
+    pObj = Gia_ManObj(p->pGia, Id);
+    if ( Gia_ObjIsCi(pObj) )
+        return;
+    if ( Gia_ObjIsMux(p->pGia, pObj) )
+    {
+        if ( pObj->fMark0 )
+            return;
+        pObj->fMark0 = 1;
+        Vec_IntPush( p->vVisit, Id );
+        Dam_ManCollectSets_rec( p, Gia_ObjFaninId0(pObj, Id) );
+        Dam_ManCollectSets_rec( p, Gia_ObjFaninId1(pObj, Id) );
+        Dam_ManCollectSets_rec( p, Gia_ObjFaninId2(p->pGia, Id) );
+        p->nAnds += 3;
+        return;
+    }
+    Gia_ManSuperCollect( p->pGia, pObj );
+    Vec_IntWriteEntry( p->vNod2Set, Id, Vec_IntSize(p->vSetStore) );
+    Vec_IntPush( p->vSetStore, Vec_IntSize(p->pGia->vSuper) );
+    p->nAnds += (1 + 2 * Gia_ObjIsXor(pObj)) * (Vec_IntSize(p->pGia->vSuper) - 1);
+    // save entries
+    iBeg = Vec_IntSize( p->vSetStore );
+    Vec_IntAppend( p->vSetStore, p->pGia->vSuper );
+    iEnd = Vec_IntSize( p->vSetStore );
+    // call recursively
+    Vec_IntForEachEntryStartStop( p->vSetStore, iLit, i, iBeg, iEnd )
+        Dam_ManCollectSets_rec( p, Abc_Lit2Var(iLit) );
+}
+void Dam_ManCollectSets( Dam_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManCreateRefs( p->pGia );
+    p->vNod2Set  = Vec_IntStart( Gia_ManObjNum(p->pGia) );
+    p->vSetStore = Vec_IntAlloc( Gia_ManObjNum(p->pGia) );
+    Vec_IntPush( p->vSetStore, -1 );
+    Vec_IntClear( p->vVisit );
+    Gia_ManForEachCo( p->pGia, pObj, i )
+        Dam_ManCollectSets_rec( p, Gia_ObjFaninId0p(p->pGia, pObj) );
+    ABC_FREE( p->pGia->pRefs );
+    Gia_ManForEachObjVec( p->vVisit, p->pGia, pObj, i )
+        pObj->fMark0 = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create divisors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dam_ManDivSlack( Dam_Man_t * p, int iLit0, int iLit1, int LevR )
+{
+    int Lev0 = Gia_ObjLevel(p->pGia, Gia_ManObj(p->pGia, Abc_Lit2Var(iLit0)));
+    int Lev1 = Gia_ObjLevel(p->pGia, Gia_ManObj(p->pGia, Abc_Lit2Var(iLit1)));
+    int Slack = p->nLevelMax - LevR - Abc_MaxInt(Lev0, Lev1) - 1 - (int)(iLit0 > iLit1);
+    return Abc_MinInt( Slack, 100 );
+}
+void Dam_ManCreateMultiRefs( Dam_Man_t * p, Vec_Int_t ** pvRefsAnd, Vec_Int_t ** pvRefsXor )  
+{
+    Vec_Int_t * vRefsAnd, * vRefsXor;
+    Gia_Obj_t * pObj;
+    int i, k, * pSet;
+    vRefsAnd = Vec_IntStart( 2 * Gia_ManObjNum(p->pGia) );
+    vRefsXor = Vec_IntStart( Gia_ManObjNum(p->pGia) );
+    Gia_ManForEachAnd( p->pGia, pObj, i )
+    {
+        if ( !Dam_ObjHand(p, i) )
+            continue;
+        pSet = Dam_ObjSet(p, i);
+        if ( Gia_ObjIsXor(pObj) )
+            for ( k = 1; k <= pSet[0]; k++ )
+            {
+                assert( !Abc_LitIsCompl(pSet[k]) );
+                Vec_IntAddToEntry( vRefsXor, Abc_Lit2Var(pSet[k]), 1 );
+            }
+        else if ( Gia_ObjIsAndReal(p->pGia, pObj) )
+            for ( k = 1; k <= pSet[0]; k++ )
+                Vec_IntAddToEntry( vRefsAnd, pSet[k], 1 );
+        else assert( 0 );
+    }
+    *pvRefsAnd = vRefsAnd;
+    *pvRefsXor = vRefsXor;
+}
+void Dam_ManCreatePairs( Dam_Man_t * p, int fVerbose )
+{
+    Gia_Obj_t * pObj;
+    Hash_IntMan_t * vHash;
+    Vec_Int_t * vRefsAnd, * vRefsXor, * vSuper, * vDivs, * vRemap, * vLevRMax;
+    int i, j, k, Num, FanK, FanJ, nRefs, iNode, iDiv, * pSet;
+    int nPairsAll = 0, nPairsTried = 0, nPairsUsed = 0, nPairsXor = 0;
+    int nDivsAll = 0, nDivsUsed = 0, nDivsXor = 0;
+    Dam_ManCollectSets( p );
+    vSuper = p->pGia->vSuper;
+    vDivs  = Vec_IntAlloc( Gia_ManObjNum(p->pGia) );
+    vHash  = Hash_IntManStart( Gia_ManObjNum(p->pGia)/2 );
+    vLevRMax = Vec_IntStart( 1000 );
+    Dam_ManCreateMultiRefs( p, &vRefsAnd, &vRefsXor );
+    Gia_ManForEachAnd( p->pGia, pObj, i )
+    {
+        if ( !Dam_ObjHand(p, i) )
+            continue;
+        pSet = Dam_ObjSet(p, i);
+        nPairsAll += pSet[0] * (pSet[0] - 1) / 2;
+        Vec_IntClear(vSuper);
+        if ( Gia_ObjIsXor(pObj) )
+        {
+            for ( k = 1; k <= pSet[0]; k++ )
+                if ( Vec_IntEntry(vRefsXor, Abc_Lit2Var(pSet[k])) > 1 )
+                    Vec_IntPush( vSuper, pSet[k] );
+        }
+        else if ( Gia_ObjIsAndReal(p->pGia, pObj) )
+        {
+            for ( k = 1; k <= pSet[0]; k++ )
+                if ( Vec_IntEntry(vRefsAnd, pSet[k]) > 1 )
+                    Vec_IntPush( vSuper, pSet[k] );
+        }
+        else assert( 0 );
+        if ( Vec_IntSize(vSuper) < 2 )
+            continue;
+        // enumerate pairs
+        nPairsTried += Vec_IntSize(vSuper) * (Vec_IntSize(vSuper) - 1) / 2;
+        Vec_IntPush( vDivs, -i ); // remember node
+        Vec_IntForEachEntry( vSuper, FanK, k )
+        Vec_IntForEachEntryStart( vSuper, FanJ, j, k+1 )
+        {
+            if ( (FanK > FanJ) ^ Gia_ObjIsXor(pObj) )
+                Num = Hash_Int2ManInsert( vHash, FanJ, FanK, 0 );
+            else
+                Num = Hash_Int2ManInsert( vHash, FanK, FanJ, 0 );
+            if ( Hash_Int2ObjInc( vHash, Num ) == 1 )
+            {
+                nDivsUsed++;
+                nDivsXor += Gia_ObjIsXor(pObj);
+            }
+            Vec_IntPush( vDivs, Num ); // remember devisor
+            // update reverse level
+            if ( Num >= Vec_IntSize(vLevRMax) )
+                Vec_IntFillExtra( vLevRMax, 3 * Vec_IntSize(vLevRMax) / 2, 0 );
+            Vec_IntUpdateEntry( vLevRMax, Num, Vec_IntEntry(p->vNodLevR, i) );
+        }
+    }
+    Vec_IntFree( vRefsAnd );
+    Vec_IntFree( vRefsXor );
+//    Hash_IntManProfile( vHash );
+    // remove entries that appear only once
+    p->vHash     = Hash_IntManStart( 3 * nDivsUsed /2 );
+    p->vCounts   = Vec_FltAlloc( 2 * nDivsUsed );           Vec_FltPush( p->vCounts, ABC_INFINITY );
+    p->vQue      = Vec_QueAlloc( Vec_FltCap(p->vCounts) );
+    Vec_QueSetPriority( p->vQue, Vec_FltArrayP(p->vCounts) );
+    // mapping div to node
+    p->vDiv2Nod  = Vec_IntAlloc( 2 * nDivsUsed );           Vec_IntPush( p->vDiv2Nod, ABC_INFINITY );
+    p->vNodStore = Vec_IntAlloc( Gia_ManObjNum(p->pGia) );  Vec_IntPush( p->vNodStore, -1 );
+    nDivsAll     = Hash_IntManEntryNum(vHash);
+    vRemap       = Vec_IntStartFull( nDivsAll+1 );
+    for ( i = 1; i <= nDivsAll; i++ )
+    {
+        nRefs = Hash_IntObjData2(vHash, i);
+        if ( nRefs < 2 )
+            continue;
+        nPairsUsed += nRefs;
+        if ( Hash_IntObjData0(vHash, i) > Hash_IntObjData1(vHash, i) )
+            nPairsXor += nRefs; 
+        Num = Hash_Int2ManInsert( p->vHash, Hash_IntObjData0(vHash, i), Hash_IntObjData1(vHash, i), 0 );
+        assert( Num == Hash_IntManEntryNum(p->vHash) );
+        assert( Num == Vec_FltSize(p->vCounts) );
+        Vec_FltPush( p->vCounts, nRefs + 0.005*Dam_ManDivSlack(p, Hash_IntObjData0(vHash, i), Hash_IntObjData1(vHash, i), Vec_IntEntry(vLevRMax, i)) );
+        Vec_QuePush( p->vQue, Num );
+        // remember divisors
+        assert( Num == Vec_IntSize(p->vDiv2Nod) );
+        Vec_IntPush( p->vDiv2Nod, Vec_IntSize(p->vNodStore) );
+        Vec_IntPush( p->vNodStore, 0 );
+        Vec_IntFillExtra( p->vNodStore, Vec_IntSize(p->vNodStore) + nRefs, -1 );
+        // remember entry
+        Vec_IntWriteEntry( vRemap, i, Num );
+    }
+    assert( Vec_FltSize(p->vCounts) == Hash_IntManEntryNum(p->vHash)+1 );
+    assert( Vec_IntSize(p->vDiv2Nod) == nDivsUsed+1 );
+    Hash_IntManStop( vHash );
+    Vec_IntFree( vLevRMax );
+    // fill in the divisors
+    iNode = -1;
+    Vec_IntForEachEntry( vDivs, iDiv, i )
+    {
+        if ( iDiv < 0 )
+        {
+            iNode = -iDiv;
+            continue;
+        }
+        Num = Vec_IntEntry( vRemap, iDiv );
+        if ( Num == -1 )
+            continue;
+        pSet = Dam_DivSet( p, Num );
+        pSet[++pSet[0]] = iNode;
+    }
+    Vec_IntFree( vRemap );
+    Vec_IntFree( vDivs );
+    // create storage for reverse level of divisor during update
+    p->vDivLevR = Vec_IntStart( 2 * nDivsUsed );
+    // make sure divisors are added correctly
+//    for ( i = 1; i <= nDivsUsed; i++ )
+//        assert( Dam_DivSet(p, i)[0] == Vec_FltEntry(p->vCounts, i)+1 );
+    if ( !fVerbose )
+        return;
+    // print stats
+    printf( "Pairs:" );
+    printf( "  Total =%9d (%6.2f %%)", nPairsAll,   100.0 * nPairsAll   / Abc_MaxInt(nPairsAll, 1) );
+    printf( "  Tried =%9d (%6.2f %%)", nPairsTried, 100.0 * nPairsTried / Abc_MaxInt(nPairsAll, 1) );
+    printf( "  Used =%9d (%6.2f %%)",  nPairsUsed,  100.0 * nPairsUsed  / Abc_MaxInt(nPairsAll, 1) );
+    printf( "  Xor =%9d (%6.2f %%)",   nPairsXor,   100.0 * nPairsXor   / Abc_MaxInt(nPairsAll, 1) );
+    printf( "\n" );
+    printf( "Div:  " );
+    printf( "  Total =%9d (%6.2f %%)", nDivsAll,    100.0 * nDivsAll    / Abc_MaxInt(nDivsAll, 1) );
+    printf( "  Tried =%9d (%6.2f %%)", nDivsAll,    100.0 * nDivsAll    / Abc_MaxInt(nDivsAll, 1) );
+    printf( "  Used =%9d (%6.2f %%)",  nDivsUsed,   100.0 * nDivsUsed   / Abc_MaxInt(nDivsAll, 1) );
+    printf( "  Xor =%9d (%6.2f %%)",   nDivsXor,    100.0 * nDivsXor    / Abc_MaxInt(nDivsAll, 1) );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives new AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dam_ManMultiAig_rec( Dam_Man_t * pMan, Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    int i, * pSet;
+    if ( ~pObj->Value )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    pSet = Dam_ObjSet(pMan, Gia_ObjId(p, pObj));
+    if ( pSet == NULL )
+    {
+        Dam_ManMultiAig_rec( pMan, pNew, p, Gia_ObjFanin0(pObj) );
+        Dam_ManMultiAig_rec( pMan, pNew, p, Gia_ObjFanin1(pObj) );
+        if ( Gia_ObjIsMux(p, pObj) )
+        {
+            Dam_ManMultiAig_rec( pMan, pNew, p, Gia_ObjFanin2(p, pObj) );
+            pObj->Value = Gia_ManHashMuxReal( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) );
+        }
+        else if ( Gia_ObjIsXor(pObj) )
+            pObj->Value = Gia_ManHashXorReal( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else 
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value)) );
+        return;
+    }
+    assert( Gia_ObjIsXor(pObj) || Gia_ObjIsAndReal(p, pObj) );
+    // call recursively
+    for ( i = 1; i <= pSet[0]; i++ )
+    {
+        Gia_Obj_t * pTemp = Gia_ManObj( p, Abc_Lit2Var(pSet[i]) );
+        Dam_ManMultiAig_rec( pMan, pNew, p, pTemp );
+        pSet[i] = Abc_LitNotCond( pTemp->Value, Abc_LitIsCompl(pSet[i]) );
+    }
+    // create balanced gate
+    pObj->Value = Gia_ManBalanceGate( pNew, pObj, p->vSuper, pSet + 1, pSet[0] );
+}
+Gia_Man_t * Dam_ManMultiAig( Dam_Man_t * pMan )
+{
+    Gia_Man_t * p = pMan->pGia;
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i;
+    // start the new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc );
+    pNew->vLevels = Vec_IntStart( pNew->nObjsAlloc );
+    // create constant and inputs
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+    {
+        pObj->Value = Gia_ManAppendCi( pNew );
+        Vec_IntWriteEntry( pNew->vLevels, Abc_Lit2Var(pObj->Value), Gia_ObjLevel(p, pObj) );
+    }
+    // create internal nodes
+    Gia_ManHashStart( pNew );
+    Gia_ManForEachCo( p, pObj, i )
+    {
+        Dam_ManMultiAig_rec( pMan, pNew, p, Gia_ObjFanin0(pObj) );
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+    assert( Gia_ManObjNum(pNew) <= Gia_ManObjNum(p) );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    // perform cleanup
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the data-structure after extracting one divisor.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dam_PrintDiv( Dam_Man_t * p, int iDiv )
+{
+    if ( iDiv == 0 )
+        printf( "Final statistics after extracting %6d divisors:          ", p->nDivs );
+    else
+    {
+        char Buffer[100];
+        int iData0 = Hash_IntObjData0(p->vHash, iDiv);
+        int iData1 = Hash_IntObjData1(p->vHash, iDiv);
+        printf( "Div%5d : ",  p->nDivs+1 );
+        printf( "D%-8d = ",   iDiv );
+        sprintf( Buffer, "%c%d", Abc_LitIsCompl(iData0)? '!':' ', Abc_Lit2Var(iData0) );
+        printf( "%8s ",   Buffer );
+        printf( "%c  ",     (iData0 < iData1) ? '*' : '+' );
+        sprintf( Buffer, "%c%d", Abc_LitIsCompl(iData1)? '!':' ', Abc_Lit2Var(iData1) );
+        printf( "%8s   ", Buffer );
+        printf( "Weight %9.2f  ", Vec_FltEntry(p->vCounts, iDiv) );
+    }
+    printf( "Divs =%8d  ",  Hash_IntManEntryNum(p->vHash) );
+    printf( "Ands =%8d  ",  p->nAnds - p->nGain );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
+}
+void Dam_PrintQue( Dam_Man_t * p )
+{
+    int i;
+    printf( "Divisor queue: \n" );
+    for ( i = 1; i <= Hash_IntManEntryNum(p->vHash); i++ )
+    {
+        int iLit0 = Hash_IntObjData0(p->vHash, i);
+        int iLit1 = Hash_IntObjData1(p->vHash, i);
+        printf( "Div %7d : ",     i );
+        printf( "Weight %9.2f  ", Vec_FltEntry(p->vCounts, i) );
+        printf( "F = %c%c ",      Abc_LitIsCompl(iLit0) ? '!': ' ', 'a' + Abc_Lit2Var(iLit0)-1 );
+        printf( "%c ",            (Hash_IntObjData0(p->vHash, i) < Hash_IntObjData1(p->vHash, i)) ? '*':'+' );
+        printf( "%c%c   ",        Abc_LitIsCompl(iLit1) ? '!': ' ', 'a' + Abc_Lit2Var(iLit1)-1 );
+        printf( "\n" );
+    }
+}
+int Dam_ManUpdateNode( Dam_Man_t * p, int iObj, int iLit0, int iLit1, int iLitNew, Vec_Int_t * vDivs )
+{
+    int * pSet = Dam_ObjSet( p, iObj );
+    int i, k, c, Num, iLit, iLit2, fPres;
+    // check if literal can be found
+    for ( i = 1; i <= pSet[0]; i++ )
+        if ( pSet[i] == iLit0 )
+            break;
+    if ( i > pSet[0] )
+        return 0;
+    // check if literal can be found
+    for ( i = 1; i <= pSet[0]; i++ )
+        if ( pSet[i] == iLit1 )
+            break;
+    if ( i > pSet[0] )
+        return 0;
+    // compact literals
+    Vec_IntPush( vDivs, -iObj );
+    for ( k = i = 1; i <= pSet[0]; i++ )
+    {
+        if ( iLit0 == pSet[i] || iLit1 == pSet[i] )
+            continue;
+        pSet[k++] = iLit = pSet[i];
+        // reduce weights of the divisors
+        fPres = 0;
+        for ( c = 0; c < 2; c++ )
+        {
+            iLit2 = c ? iLit1 : iLit0;
+            if ( (iLit > iLit2) ^ (iLit0 > iLit1) )
+                Num = *Hash_Int2ManLookup( p->vHash, iLit2, iLit );
+            else
+                Num = *Hash_Int2ManLookup( p->vHash, iLit, iLit2 );
+            if ( Num > 0 )
+            {
+                Vec_FltAddToEntry( p->vCounts, Num, -1 );
+                if ( Vec_QueIsMember(p->vQue, Num) )
+                {
+                    Vec_QueUpdate( p->vQue, Num );
+                    fPres |= (1 << c);
+                }
+            }
+        }
+        if ( fPres != 3 )
+            continue;
+        if ( (iLit > iLitNew) ^ (iLit0 > iLit1) )
+            Num = Hash_Int2ManInsert( p->vHash, iLitNew, iLit, 0 );
+        else
+            Num = Hash_Int2ManInsert( p->vHash, iLit, iLitNew, 0 );
+        Hash_Int2ObjInc( p->vHash, Num );
+        Vec_IntPush( vDivs, Num );
+        // update reverse level
+        if ( Num >= Vec_IntSize(p->vDivLevR) )
+            Vec_IntFillExtra( p->vDivLevR, 3 * Vec_IntSize(p->vDivLevR) / 2, 0 );
+        Vec_IntUpdateEntry( p->vDivLevR, Num, Vec_IntEntry(p->vNodLevR, iObj) );
+    }
+    pSet[k] = iLitNew;
+    pSet[0] = k;
+    return 1;
+}
+void Dam_ManUpdate( Dam_Man_t * p, int iDiv )
+{
+    Vec_Int_t * vDivs = p->pGia->vSuper;
+    int iLit0 = Hash_IntObjData0(p->vHash, iDiv);
+    int iLit1 = Hash_IntObjData1(p->vHash, iDiv);
+    int i, iLitNew, * pSet, * pNods = Dam_DivSet( p, iDiv );
+    int nPresent = 0, nPairsStart, nPairsStop, pPairsNew, nRefs;
+    int fThisIsXor = (iLit0 > iLit1), iDivTemp, iNode;
+//    Dam_PrintQue( p );
+    if ( fThisIsXor )
+        iLitNew = Gia_ManAppendXorReal( p->pGia, iLit0, iLit1 );
+    else
+        iLitNew = Gia_ManAppendAnd( p->pGia, iLit0, iLit1 );
+    Gia_ObjSetGateLevel( p->pGia, Gia_ManObj(p->pGia, Abc_Lit2Var(iLitNew)) );
+//    printf( "%d ", Gia_ObjLevel(p->pGia, Gia_ManObj(p->pGia, Abc_Lit2Var(iLitNew))) );
+    // replace entries
+    assert( pNods[0] >= 2 );
+    nPairsStart = Hash_IntManEntryNum(p->vHash) + 1;
+    Vec_IntClear( vDivs );
+    for ( i = 1; i <= pNods[0]; i++ )
+        nPresent += Dam_ManUpdateNode( p, pNods[i], iLit0, iLit1, iLitNew, vDivs );
+    nPairsStop = Hash_IntManEntryNum(p->vHash) + 1;
+    // extend arrayvs
+    pPairsNew = 0;
+    Vec_FltFillExtra( p->vCounts, nPairsStop, 0 );
+    Vec_IntFillExtra( p->vDiv2Nod, nPairsStop, -1 );
+    for ( i = nPairsStart; i < nPairsStop; i++ )
+    {
+        nRefs = Hash_IntObjData2(p->vHash, i);
+        if ( nRefs < 2 )
+            continue;
+        Vec_FltWriteEntry( p->vCounts, i, nRefs + 0.001*Dam_ManDivSlack(p, Hash_IntObjData0(p->vHash, i), Hash_IntObjData1(p->vHash, i), Vec_IntEntry(p->vDivLevR, i)) );
+        Vec_QuePush( p->vQue, i );
+        // remember divisors
+        Vec_IntWriteEntry( p->vDiv2Nod, i, Vec_IntSize(p->vNodStore) );
+        Vec_IntPush( p->vNodStore, 0 );
+        Vec_IntFillExtra( p->vNodStore, Vec_IntSize(p->vNodStore) + nRefs, -1 );
+        pPairsNew++;
+    }
+//    printf( "Added %d new pairs\n", pPairsNew );
+    // fill in the divisors
+    iNode = -1;
+    Vec_IntForEachEntry( vDivs, iDivTemp, i )
+    {
+        if ( iDivTemp < 0 )
+        {
+            iNode = -iDivTemp;
+            continue;
+        }
+        if ( Vec_IntEntry(p->vDiv2Nod, iDivTemp) == -1 )
+            continue;
+        pSet = Dam_DivSet( p, iDivTemp );
+        pSet[++pSet[0]] = iNode;
+    }
+    // make sure divisors are added correctly
+    for ( i = nPairsStart; i < nPairsStop; i++ )
+        if ( Vec_IntEntry(p->vDiv2Nod, i) > 0 )
+            assert( Dam_DivSet(p, i)[0] == Hash_IntObjData2(p->vHash, i) );
+    // update costs
+    Vec_FltWriteEntry( p->vCounts, iDiv, 0 );
+    p->nGain += (1 + 2 * fThisIsXor) * (nPresent - 1);
+    p->nGainX += 3 * fThisIsXor * (nPresent - 1);
+    p->nDivs++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform extraction for multi-input AND/XOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Dam_ManAreaBalanceInt( Gia_Man_t * pGia, Vec_Int_t * vCiLevels, int nNewNodesMax, int fVerbose, int fVeryVerbose )
+{
+    Gia_Man_t * pNew;
+    Dam_Man_t * p;
+    int i, iDiv;
+    p = Dam_ManAlloc( pGia );
+    p->nLevelMax = Gia_ManSetLevels( p->pGia, vCiLevels );
+    p->vNodLevR = Gia_ManReverseLevel( p->pGia );
+    Vec_IntFillExtra( p->pGia->vLevels, 3*Gia_ManObjNum(p->pGia)/2, 0 );
+    Dam_ManCreatePairs( p, fVerbose );
+    for ( i = 0; i < nNewNodesMax && Vec_QueTopPriority(p->vQue) >= 2; i++ )
+    {
+        iDiv = Vec_QuePop(p->vQue);
+        if ( fVeryVerbose )
+            Dam_PrintDiv( p, iDiv );
+        Dam_ManUpdate( p, iDiv );
+    }
+    if ( fVeryVerbose )
+        Dam_PrintDiv( p, 0 );
+    pNew = Dam_ManMultiAig( p );
+    if ( fVerbose )
+    {
+        int nDivsAll = Hash_IntManEntryNum(p->vHash);
+        int nDivsUsed = p->nDivs;
+        printf( "Div:  " );
+        printf( "  Total =%9d (%6.2f %%) ",   nDivsAll,   100.0 * nDivsAll    / Abc_MaxInt(nDivsAll, 1) );
+        printf( "  Used =%9d (%6.2f %%)",     nDivsUsed,  100.0 * nDivsUsed   / Abc_MaxInt(nDivsAll, 1) );
+        printf( "  Gain =%6d (%6.2f %%)",     p->nGain,   100.0 * p->nGain / Abc_MaxInt(p->nAnds, 1) );
+        printf( "  GainX = %d  ",             p->nGainX  );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
+    }
+    Dam_ManFree( p );
+    return pNew;
+}
+Gia_Man_t * Gia_ManAreaBalance( Gia_Man_t * p, int fSimpleAnd, int nNewNodesMax, int fVerbose, int fVeryVerbose )
+{
+    Gia_Man_t * pNew0, * pNew, * pNew1, * pNew2;
+    Vec_Int_t * vCiLevels;
+    // determine CI levels
+    if ( p->pManTime && p->vLevels == NULL )
+        Gia_ManLevelWithBoxes( p );
+    vCiLevels = Gia_ManGetCiLevels( p );
+    // get the starting manager
+    pNew0 = Gia_ManHasMapping(p) ? (Gia_Man_t *)Dsm_ManDeriveGia(p, 0) : p;
+    if ( fVerbose )     Gia_ManPrintStats( pNew0, NULL );
+    // derive internal manager
+    pNew = fSimpleAnd ? Gia_ManDup( pNew0 ) : Gia_ManDupMuxes( pNew0, 2 );
+    if ( fVerbose )     Gia_ManPrintStats( pNew, NULL );
+    if ( pNew0 != p ) Gia_ManStop( pNew0 );
+    // perform the operation
+    pNew1 = Dam_ManAreaBalanceInt( pNew, vCiLevels, nNewNodesMax, fVerbose, fVeryVerbose );
+    if ( fVerbose )     Gia_ManPrintStats( pNew1, NULL );
+    Gia_ManStop( pNew );
+    Vec_IntFreeP( &vCiLevels );
+    // derive the final result
+    pNew2 = Gia_ManDupNoMuxes( pNew1 );
+    if ( fVerbose )     Gia_ManPrintStats( pNew2, NULL );
+    Gia_ManStop( pNew1 );
+    return pNew2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Synthesis script.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManAigPrintPiLevels( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachPi( p, pObj, i )
+        printf( "%d ", Gia_ObjLevel(p, pObj) );
+    printf( "\n" );
+}
+void Gia_ManAigTransferPiLevels( Gia_Man_t * pNew, Gia_Man_t * p )
+{
+/*
+    Gia_Obj_t * pObj;
+    int i;
+    if ( p->vLevels == NULL )
+        return;
+    Gia_ManCleanLevels( pNew, Gia_ManObjNum(pNew) );
+    Gia_ManForEachCi( pNew, pObj, i )
+        Gia_ObjSetLevel( pNew, pObj, Gia_ObjLevel(p, Gia_ManCi(p, i)) );
+*/
+    if ( p->pManTime ) pNew->pManTime = p->pManTime, p->pManTime = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Synthesis script.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManAigSyn2( Gia_Man_t * p, int fOldAlgo, int fCoarsen, int fCutMin, int nRelaxRatio, int fVerbose, int fVeryVerbose )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Jf_Par_t Pars, * pPars = &Pars;
+    if ( fOldAlgo )
+    {
+        Jf_ManSetDefaultPars( pPars );
+        pPars->fCutMin     = fCutMin;
+    }
+    else
+    {
+        Lf_ManSetDefaultPars( pPars );
+        pPars->fCoarsen    = fCoarsen;
+        pPars->fCutMin     = fCutMin;
+        pPars->nRelaxRatio = nRelaxRatio;
+        pPars->nAreaTuner  = 1;
+    }
+    if ( fVerbose )     Gia_ManPrintStats( p, NULL );
+    if ( Gia_ManAndNum(p) == 0 )
+        return Gia_ManDup(p);
+    // perform balancing
+    pNew = Gia_ManAreaBalance( p, 0, ABC_INFINITY, fVeryVerbose, 0 );
+    if ( fVerbose )     Gia_ManPrintStats( pNew, NULL );
+    Gia_ManAigTransferPiLevels( pNew, p );
+    // perform mapping
+    if ( fOldAlgo )
+        pNew = Jf_ManPerformMapping( pTemp = pNew, pPars );
+    else
+        pNew = Lf_ManPerformMapping( pTemp = pNew, pPars );
+    if ( fVerbose )     Gia_ManPrintStats( pNew, NULL );
+    if ( pTemp != pNew )
+    {
+        Gia_ManAigTransferPiLevels( pNew, pTemp );
+        Gia_ManStop( pTemp );
+    }
+    // perform balancing
+    pNew = Gia_ManAreaBalance( pTemp = pNew, 0, ABC_INFINITY, fVeryVerbose, 0 );
+    if ( fVerbose )     Gia_ManPrintStats( pNew, NULL );
+    Gia_ManAigTransferPiLevels( pNew, pTemp );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+Gia_Man_t * Gia_ManAigSyn3( Gia_Man_t * p, int fVerbose, int fVeryVerbose )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Jf_Par_t Pars, * pPars = &Pars;
+    Jf_ManSetDefaultPars( pPars );
+    pPars->nRelaxRatio = 40;
+    if ( fVerbose )     Gia_ManPrintStats( p, NULL );
+    if ( Gia_ManAndNum(p) == 0 )
+        return Gia_ManDup(p);
+    // perform balancing
+    pNew = Gia_ManAreaBalance( p, 0, ABC_INFINITY, fVeryVerbose, 0 );
+    if ( fVerbose )     Gia_ManPrintStats( pNew, NULL );
+    Gia_ManAigTransferPiLevels( pNew, p );
+    // perform mapping
+    pPars->nLutSize = 6;
+    pNew = Jf_ManPerformMapping( pTemp = pNew, pPars );
+    if ( fVerbose )     Gia_ManPrintStats( pNew, NULL );
+//    Gia_ManStop( pTemp );
+    // perform balancing
+    pNew = Gia_ManAreaBalance( pTemp = pNew, 0, ABC_INFINITY, fVeryVerbose, 0 );
+    if ( fVerbose )     Gia_ManPrintStats( pNew, NULL );
+    Gia_ManAigTransferPiLevels( pNew, pTemp );
+    Gia_ManStop( pTemp );
+    // perform mapping
+    pPars->nLutSize = 4;
+    pNew = Jf_ManPerformMapping( pTemp = pNew, pPars );
+    if ( fVerbose )     Gia_ManPrintStats( pNew, NULL );
+//    Gia_ManStop( pTemp );
+    // perform balancing
+    pNew = Gia_ManAreaBalance( pTemp = pNew, 0, ABC_INFINITY, fVeryVerbose, 0 );
+    if ( fVerbose )     Gia_ManPrintStats( pNew, NULL );
+    Gia_ManAigTransferPiLevels( pNew, pTemp );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+Gia_Man_t * Gia_ManAigSyn4( Gia_Man_t * p, int fVerbose, int fVeryVerbose )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Jf_Par_t Pars, * pPars = &Pars;
+    Jf_ManSetDefaultPars( pPars );
+    pPars->nRelaxRatio = 40;
+    if ( fVerbose )     Gia_ManPrintStats( p, NULL );
+    if ( Gia_ManAndNum(p) == 0 )
+        return Gia_ManDup(p);
+//Gia_ManAigPrintPiLevels( p );
+    // perform balancing
+    pNew = Gia_ManAreaBalance( p, 0, ABC_INFINITY, fVeryVerbose, 0 );
+    if ( fVerbose )     Gia_ManPrintStats( pNew, NULL );
+    Gia_ManAigTransferPiLevels( pNew, p );
+    // perform mapping
+    pPars->nLutSize = 7;
+    pNew = Jf_ManPerformMapping( pTemp = pNew, pPars );
+    if ( fVerbose )     Gia_ManPrintStats( pNew, NULL );
+//    Gia_ManStop( pTemp );
+    // perform extraction
+    pNew = Gia_ManPerformFx( pTemp = pNew, ABC_INFINITY, 0, 0, fVeryVerbose, 0 );
+    if ( fVerbose )     Gia_ManPrintStats( pNew, NULL );
+    Gia_ManAigTransferPiLevels( pNew, pTemp );
+    Gia_ManStop( pTemp );
+    // perform balancing
+    pNew = Gia_ManAreaBalance( pTemp = pNew, 0, ABC_INFINITY, fVeryVerbose, 0 );
+    if ( fVerbose )     Gia_ManPrintStats( pNew, NULL );
+    Gia_ManAigTransferPiLevels( pNew, pTemp );
+    Gia_ManStop( pTemp );
+    // perform mapping
+    pPars->nLutSize = 5;
+    pNew = Jf_ManPerformMapping( pTemp = pNew, pPars );
+    if ( fVerbose )     Gia_ManPrintStats( pNew, NULL );
+//    Gia_ManStop( pTemp );
+    // perform extraction
+    pNew = Gia_ManPerformFx( pTemp = pNew, ABC_INFINITY, 0, 0, fVeryVerbose, 0 );
+    if ( fVerbose )     Gia_ManPrintStats( pNew, NULL );
+    Gia_ManAigTransferPiLevels( pNew, pTemp );
+    Gia_ManStop( pTemp );
+    // perform balancing
+    pNew = Gia_ManAreaBalance( pTemp = pNew, 0, ABC_INFINITY, fVeryVerbose, 0 );
+    if ( fVerbose )     Gia_ManPrintStats( pNew, NULL );
+    Gia_ManAigTransferPiLevels( pNew, pTemp );
+    Gia_ManStop( pTemp );
+//Gia_ManAigPrintPiLevels( pNew );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaBalance2.c b/abc-build/src/aig/gia/giaBalance2.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaBalance2.c
@@ -0,0 +1,981 @@
+/**CFile****************************************************************
+
+  FileName    [giaBalance.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [AIG balancing.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaBalance.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/vec/vecHash.h"
+#include "misc/vec/vecQue.h"
+#include "opt/dau/dau.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define BAL_LEAF_MAX    6
+#define BAL_CUT_MAX     8
+#define BAL_SUPER      50
+#define BAL_NO_LEAF    31
+
+typedef struct Bal_Cut_t_ Bal_Cut_t; 
+struct Bal_Cut_t_
+{
+    word             Sign;           // signature
+    int              Delay;          // delay
+    unsigned         iFunc   : 27;   // function
+    unsigned         nLeaves :  5;   // leaf number (Bal_NO_LEAF)
+    int              pLeaves[BAL_LEAF_MAX]; // leaves
+};
+
+// operation manager
+typedef struct Bal_Man_t_ Bal_Man_t;
+struct Bal_Man_t_
+{
+    Gia_Man_t *      pGia;           // user AIG
+    int              nLutSize;       // LUT size
+    int              nCutNum;        // cut number
+    int              fCutMin;        // cut minimization
+    int              fVerbose;       // verbose
+    Gia_Man_t *      pNew;           // derived AIG
+    Vec_Int_t *      vCosts;         // cost of supergate nodes
+    Vec_Ptr_t *      vCutSets;       // object cutsets
+    abctime          clkStart;       // starting the clock
+};
+
+static inline Bal_Man_t * Bal_GiaMan( Gia_Man_t * p )                   { return (Bal_Man_t *)p->pData;           }
+
+static inline int         Bal_ObjCost( Bal_Man_t * p, int i )           { return Vec_IntEntry(p->vCosts, i);      }
+static inline int         Bal_LitCost( Bal_Man_t * p, int i )           { return Bal_ObjCost(p, Abc_Lit2Var(i));  }
+static inline int         Bal_ObjDelay( Bal_Man_t * p, int i )          { return Bal_ObjCost(p, i) >> 4;          }
+static inline int         Bal_LitDelay( Bal_Man_t * p, int i )          { return Bal_ObjDelay(p, Abc_Lit2Var(i)); }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bal_Man_t * Bal_ManAlloc( Gia_Man_t * pGia, Gia_Man_t * pNew, int nLutSize, int nCutNum, int fVerbose )
+{
+    Bal_Man_t * p;
+    p = ABC_CALLOC( Bal_Man_t, 1 );
+    p->clkStart = Abc_Clock();
+    p->pGia     = pGia;
+    p->pNew     = pNew;
+    p->nLutSize = nLutSize;
+    p->nCutNum  = nCutNum;
+    p->fVerbose = fVerbose;
+    p->vCosts   = Vec_IntAlloc( 3 * Gia_ManObjNum(pGia) / 2 );
+    p->vCutSets = Vec_PtrAlloc( 3 * Gia_ManObjNum(pGia) / 2 );
+    Vec_IntFill( p->vCosts, Gia_ManObjNum(pNew), 0 );
+    Vec_PtrFill( p->vCutSets, Gia_ManObjNum(pNew), NULL );
+    pNew->pData = p;
+    return p;
+}
+void Bal_ManFree( Bal_Man_t * p )
+{
+    Vec_PtrFreeFree( p->vCutSets );
+    Vec_IntFree( p->vCosts );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Bal_CutCountBits( word i )
+{
+    i = i - ((i >> 1) & 0x5555555555555555);
+    i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333);
+    i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F);
+    return (i*(0x0101010101010101))>>56;
+}
+static inline word Bal_CutGetSign( int * pLeaves, int nLeaves )
+{
+    word Sign = 0; int i; 
+    for ( i = 0; i < nLeaves; i++ )
+        Sign |= ((word)1) << (pLeaves[i] & 0x3F);
+    return Sign;
+}
+static inline int Bal_CutCreateUnit( Bal_Cut_t * p, int i, int Delay )
+{
+    p->iFunc = 2;
+    p->Delay = Delay;
+    p->nLeaves = 1;
+    p->pLeaves[0] = i;
+    p->Sign = ((word)1) << (i & 0x3F);
+    return 1;
+}
+static inline int Bal_ManPrepareSet( Bal_Man_t * p, int iObj, int Index, int fUnit, Bal_Cut_t ** ppCutSet )
+{
+    static Bal_Cut_t CutTemp[3]; int i;
+    if ( Vec_PtrEntry(p->vCutSets, iObj) == NULL || fUnit )
+        return Bal_CutCreateUnit( (*ppCutSet = CutTemp + Index), iObj, Bal_ObjDelay(p, iObj)+1 );
+    *ppCutSet = (Bal_Cut_t *)Vec_PtrEntry(p->vCutSets, iObj);
+    for ( i = 0; i < p->nCutNum; i++ ) 
+        if ( (*ppCutSet)[i].nLeaves == BAL_NO_LEAF )
+            return i;
+    return i;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Check correctness of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Bal_CutCheck( Bal_Cut_t * pBase, Bal_Cut_t * pCut ) // check if pCut is contained in pBase
+{
+    int nSizeB = pBase->nLeaves;
+    int nSizeC = pCut->nLeaves;
+    int i, * pB = pBase->pLeaves;
+    int k, * pC = pCut->pLeaves;
+    for ( i = 0; i < nSizeC; i++ )
+    {
+        for ( k = 0; k < nSizeB; k++ )
+            if ( pC[i] == pB[k] )
+                break;
+        if ( k == nSizeB )
+            return 0;
+    }
+    return 1;
+}
+static inline int Bal_SetCheckArray( Bal_Cut_t ** ppCuts, int nCuts )
+{
+    Bal_Cut_t * pCut0, * pCut1; 
+    int i, k, m, n, Value;
+    assert( nCuts > 0 );
+    for ( i = 0; i < nCuts; i++ )
+    {
+        pCut0 = ppCuts[i];
+        assert( pCut0->nLeaves <= BAL_LEAF_MAX );
+        assert( pCut0->Sign == Bal_CutGetSign(pCut0->pLeaves, pCut0->nLeaves) );
+        // check duplicates
+        for ( m = 0; m < (int)pCut0->nLeaves; m++ )
+        for ( n = m + 1; n < (int)pCut0->nLeaves; n++ )
+            assert( pCut0->pLeaves[m] < pCut0->pLeaves[n] );
+        // check pairs
+        for ( k = 0; k < nCuts; k++ )
+        {
+            pCut1 = ppCuts[k];
+            if ( pCut0 == pCut1 )
+                continue;
+            // check containments
+            Value = Bal_CutCheck( pCut0, pCut1 );
+            assert( Value == 0 );
+        }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Bal_CutMergeOrder( Bal_Cut_t * pCut0, Bal_Cut_t * pCut1, Bal_Cut_t * pCut, int nLutSize )
+{ 
+    int nSize0   = pCut0->nLeaves;
+    int nSize1   = pCut1->nLeaves;
+    int i, * pC0 = pCut0->pLeaves;
+    int k, * pC1 = pCut1->pLeaves;
+    int c, * pC  = pCut->pLeaves;
+    // the case of the largest cut sizes
+    if ( nSize0 == nLutSize && nSize1 == nLutSize )
+    {
+        for ( i = 0; i < nSize0; i++ )
+        {
+            if ( pC0[i] != pC1[i] )  return 0;
+            pC[i] = pC0[i];
+        }
+        pCut->nLeaves = nLutSize;
+        pCut->iFunc = -1;
+        pCut->Sign = pCut0->Sign | pCut1->Sign;
+        pCut->Delay = Abc_MaxInt( pCut0->Delay, pCut1->Delay );
+        return 1;
+    }
+    // compare two cuts with different numbers
+    i = k = c = 0;
+    while ( 1 )
+    {
+        if ( c == nLutSize ) return 0;
+        if ( pC0[i] < pC1[k] )
+        {
+            pC[c++] = pC0[i++];
+            if ( i >= nSize0 ) goto FlushCut1;
+        }
+        else if ( pC0[i] > pC1[k] )
+        {
+            pC[c++] = pC1[k++];
+            if ( k >= nSize1 ) goto FlushCut0;
+        }
+        else
+        {
+            pC[c++] = pC0[i++]; k++;
+            if ( i >= nSize0 ) goto FlushCut1;
+            if ( k >= nSize1 ) goto FlushCut0;
+        }
+    }
+
+FlushCut0:
+    if ( c + nSize0 > nLutSize + i ) return 0;
+    while ( i < nSize0 )
+        pC[c++] = pC0[i++];
+    pCut->nLeaves = c;
+    pCut->iFunc = -1;
+    pCut->Sign = pCut0->Sign | pCut1->Sign;
+    pCut->Delay = Abc_MaxInt( pCut0->Delay, pCut1->Delay );
+    return 1;
+
+FlushCut1:
+    if ( c + nSize1 > nLutSize + k ) return 0;
+    while ( k < nSize1 )
+        pC[c++] = pC1[k++];
+    pCut->nLeaves = c;
+    pCut->iFunc = -1;
+    pCut->Sign = pCut0->Sign | pCut1->Sign;
+    pCut->Delay = Abc_MaxInt( pCut0->Delay, pCut1->Delay );
+    return 1;
+}
+static inline int Bal_CutMergeOrderMux( Bal_Cut_t * pCut0, Bal_Cut_t * pCut1, Bal_Cut_t * pCut2, Bal_Cut_t * pCut, int nLutSize )
+{ 
+    int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves;
+    int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves;
+    int x2, i2 = 0, nSize2 = pCut2->nLeaves, * pC2 = pCut2->pLeaves;
+    int xMin, c = 0, * pC  = pCut->pLeaves;
+    while ( 1 )
+    {
+        x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0];
+        x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1];
+        x2 = (i2 == nSize2) ? ABC_INFINITY : pC2[i2];
+        xMin = Abc_MinInt( Abc_MinInt(x0, x1), x2 );
+        if ( xMin == ABC_INFINITY ) break;
+        if ( c == nLutSize ) return 0;
+        pC[c++] = xMin;
+        if (x0 == xMin) i0++;
+        if (x1 == xMin) i1++;
+        if (x2 == xMin) i2++;
+    }
+    pCut->nLeaves = c;
+    pCut->iFunc = -1;
+    pCut->Sign = pCut0->Sign | pCut1->Sign | pCut2->Sign;
+    pCut->Delay = Abc_MaxInt( pCut0->Delay, Abc_MaxInt(pCut1->Delay, pCut2->Delay) );
+    return 1;
+}
+static inline int Bal_SetCutIsContainedOrder( Bal_Cut_t * pBase, Bal_Cut_t * pCut ) // check if pCut is contained in pBase
+{
+    int i, nSizeB = pBase->nLeaves;
+    int k, nSizeC = pCut->nLeaves;
+    if ( nSizeB == nSizeC )
+    {
+        for ( i = 0; i < nSizeB; i++ )
+            if ( pBase->pLeaves[i] != pCut->pLeaves[i] )
+                return 0;
+        return 1;
+    }
+    assert( nSizeB > nSizeC ); 
+    if ( nSizeC == 0 )
+        return 1;
+    for ( i = k = 0; i < nSizeB; i++ )
+    {
+        if ( pBase->pLeaves[i] > pCut->pLeaves[k] )
+            return 0;
+        if ( pBase->pLeaves[i] == pCut->pLeaves[k] )
+        {
+            if ( ++k == nSizeC )
+                return 1;
+        }
+    }
+    return 0;
+}
+static inline int Bal_SetLastCutIsContained( Bal_Cut_t ** pCuts, int nCuts )
+{
+    int i;
+    for ( i = 0; i < nCuts; i++ )
+        if ( pCuts[i]->nLeaves <= pCuts[nCuts]->nLeaves && (pCuts[i]->Sign & pCuts[nCuts]->Sign) == pCuts[i]->Sign && Bal_SetCutIsContainedOrder(pCuts[nCuts], pCuts[i]) )
+            return 1;
+    return 0;
+}
+static inline int Bal_SetLastCutContains( Bal_Cut_t ** pCuts, int nCuts )
+{
+    int i, k, fChanges = 0;
+    for ( i = 0; i < nCuts; i++ )
+        if ( pCuts[nCuts]->nLeaves < pCuts[i]->nLeaves && (pCuts[nCuts]->Sign & pCuts[i]->Sign) == pCuts[nCuts]->Sign && Bal_SetCutIsContainedOrder(pCuts[i], pCuts[nCuts]) )
+            pCuts[i]->nLeaves = BAL_NO_LEAF, fChanges = 1;
+    if ( !fChanges )
+        return nCuts;
+    for ( i = k = 0; i <= nCuts; i++ )
+    {
+        if ( pCuts[i]->nLeaves == BAL_NO_LEAF )
+            continue;
+        if ( k < i )
+            ABC_SWAP( Bal_Cut_t *, pCuts[k], pCuts[i] );
+        k++;
+    }
+    return k - 1;
+}
+static inline int Bal_CutCompareArea( Bal_Cut_t * pCut0, Bal_Cut_t * pCut1 )
+{
+    if ( pCut0->Delay   < pCut1->Delay   )  return -1;
+    if ( pCut0->Delay   > pCut1->Delay   )  return  1;
+    if ( pCut0->nLeaves < pCut1->nLeaves )  return -1;
+    if ( pCut0->nLeaves > pCut1->nLeaves )  return  1;
+    return 0;
+}
+static inline void Bal_SetSortByDelay( Bal_Cut_t ** pCuts, int nCuts )
+{
+    int i;
+    for ( i = nCuts; i > 0; i-- )
+    {
+        if ( Bal_CutCompareArea(pCuts[i - 1], pCuts[i]) < 0 )//!= 1 )
+            return;
+        ABC_SWAP( Bal_Cut_t *, pCuts[i - 1], pCuts[i] );
+    }
+}
+static inline int Bal_SetAddCut( Bal_Cut_t ** pCuts, int nCuts, int nCutNum )
+{
+    if ( nCuts == 0 )
+        return 1;
+    nCuts = Bal_SetLastCutContains(pCuts, nCuts);
+    Bal_SetSortByDelay( pCuts, nCuts );
+    return Abc_MinInt( nCuts + 1, nCutNum - 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bal_ManDeriveCuts( Bal_Man_t * p, int iFan0, int iFan1, int iFan2, int fCompl0, int fCompl1, int fCompl2, int fUnit0, int fUnit1, int fUnit2, int fIsXor, int Target, int fSave )
+{
+    Bal_Cut_t pCutSet[BAL_CUT_MAX], * pCutsR[BAL_CUT_MAX];
+    Bal_Cut_t * pCutSet0, * pCutSet1, * pCutSet2;
+    int nCuts0 = Bal_ManPrepareSet( p, iFan0, 0, fUnit0, &pCutSet0 );
+    int nCuts1 = Bal_ManPrepareSet( p, iFan1, 1, fUnit1, &pCutSet1 );
+    Bal_Cut_t * pCut0, * pCut0Lim = pCutSet0 + nCuts0;
+    Bal_Cut_t * pCut1, * pCut1Lim = pCutSet1 + nCuts1;
+    int i, Cost, nCutsR = 0;
+    memset( pCutSet, 0, sizeof(Bal_Cut_t) * p->nCutNum );
+    for ( i = 0; i < p->nCutNum; i++ )
+        pCutsR[i] = pCutSet + i;
+    // enumerate cuts
+    if ( iFan2 > 0 )
+    {
+        int nCuts2 = Bal_ManPrepareSet( p, iFan2, 2, fUnit2, &pCutSet2 );
+        Bal_Cut_t * pCut2, * pCut2Lim = pCutSet2 + nCuts2;
+        for ( pCut0 = pCutSet0; pCut0 < pCut0Lim; pCut0++ )
+        for ( pCut1 = pCutSet1; pCut1 < pCut1Lim; pCut1++ )
+        for ( pCut2 = pCutSet2; pCut2 < pCut2Lim; pCut2++ )
+        {
+            if ( Bal_CutCountBits(pCut0->Sign | pCut1->Sign | pCut2->Sign) > p->nLutSize )
+                continue;
+            if ( !Bal_CutMergeOrderMux(pCut0, pCut1, pCut2, pCutsR[nCutsR], p->nLutSize) )
+                continue;
+            assert( pCutsR[nCutsR]->Delay == Target );
+            if ( Bal_SetLastCutIsContained(pCutsR, nCutsR) )
+                continue;
+//            if ( p->fCutMin && Bal_CutComputeTruthMux(p, pCut0, pCut1, pCut2, fCompl0, fCompl1, fCompl2, pCutsR[nCutsR]) )
+//                pCutsR[nCutsR]->Sign = Bal_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves);
+            nCutsR = Bal_SetAddCut( pCutsR, nCutsR, p->nCutNum );
+        }
+    }
+    else
+    {
+        for ( pCut0 = pCutSet0; pCut0 < pCut0Lim; pCut0++ )
+        for ( pCut1 = pCutSet1; pCut1 < pCut1Lim; pCut1++ )
+        {
+            if ( Bal_CutCountBits(pCut0->Sign | pCut1->Sign) > p->nLutSize )
+                continue;
+            if ( !Bal_CutMergeOrder(pCut0, pCut1, pCutsR[nCutsR], p->nLutSize) )
+                continue;
+            assert( pCutsR[nCutsR]->Delay == Target );
+            if ( Bal_SetLastCutIsContained(pCutsR, nCutsR) )
+                continue;
+//            if ( p->fCutMin && Bal_CutComputeTruth(p, pCut0, pCut1, fCompl0, fCompl1, pCutsR[nCutsR], fIsXor) )
+//                pCutsR[nCutsR]->Sign = Bal_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves);
+            nCutsR = Bal_SetAddCut( pCutsR, nCutsR, p->nCutNum );
+        }
+    }
+    if ( nCutsR == 0 )
+        return -1;
+//printf( "%d ", nCutsR );
+    Cost = ((pCutsR[0]->Delay << 4) | pCutsR[0]->nLeaves);
+    // verify
+    assert( nCutsR > 0 && nCutsR < p->nCutNum );
+    assert( Bal_SetCheckArray(pCutsR, nCutsR) );
+    // save cuts
+    if ( fSave && Cost >= 0 )
+    {
+        pCutSet0 = ABC_CALLOC( Bal_Cut_t, p->nCutNum );
+        Vec_PtrPush( p->vCutSets, pCutSet0 );
+        assert( Vec_PtrSize(p->vCutSets) == Gia_ManObjNum(p->pNew) );
+        for ( i = 0; i < nCutsR; i++ )
+            pCutSet0[i] = *pCutsR[i];        
+        for ( ; i < p->nCutNum; i++ )
+            pCutSet0[i].nLeaves = BAL_NO_LEAF;
+        Vec_IntPush( p->vCosts, Cost );
+        assert( Vec_IntSize(p->vCosts) == Gia_ManObjNum(p->pNew) );
+    }
+    return Cost;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bal_ManSetGateLevel( Bal_Man_t * p, Gia_Obj_t * pObjOld, int iLitNew )
+{
+    int iFan0, iFan1, iFan2, Cost;
+    int fCompl0, fCompl1, fCompl2;
+    int fUnit0, fUnit1, fUnit2;
+    int Delay0, Delay1, Delay2, DelayMax;
+    int iObjNew = Abc_Lit2Var(iLitNew);
+    Gia_Obj_t * pObjNew = Gia_ManObj( p->pNew, iObjNew );
+    int fMux = Gia_ObjIsMux(p->pNew, pObjNew);
+    if ( iObjNew < Vec_PtrSize(p->vCutSets) )
+        return -1;
+    iFan0    = Gia_ObjFaninId0( pObjNew, iObjNew );
+    iFan1    = Gia_ObjFaninId1( pObjNew, iObjNew );
+    iFan2    = fMux ? Gia_ObjFaninId2(p->pNew, iObjNew) : 0;
+    fCompl0  = Gia_ObjFaninC0( pObjNew );
+    fCompl1  = Gia_ObjFaninC1( pObjNew );
+    fCompl2  = fMux ? Gia_ObjFaninC2(p->pNew, pObjNew) : 0;
+    Delay0   = Bal_ObjDelay( p, iFan0 );
+    Delay1   = Bal_ObjDelay( p, iFan1 );
+    Delay2   = Bal_ObjDelay( p, iFan2 );
+    DelayMax = Abc_MaxInt( Delay0, Abc_MaxInt(Delay1, Delay2) );
+    fUnit0   = (int)(Delay0 != DelayMax); 
+    fUnit1   = (int)(Delay1 != DelayMax); 
+    fUnit2   = (int)(Delay2 != DelayMax); 
+    if ( DelayMax > 0 )
+    {
+//printf( "A" );
+        Cost = Bal_ManDeriveCuts(p, iFan0, iFan1, iFan2, fCompl0, fCompl1, fCompl2, fUnit0, fUnit1, fUnit2, Gia_ObjIsXor(pObjNew), DelayMax, 1 );
+//printf( "B" );
+        if ( Cost >= 0 )
+            return Cost;
+    }
+    DelayMax++;
+    fUnit0 = fUnit1 = fUnit2 = 1;
+//printf( "A" );
+    Cost = Bal_ManDeriveCuts(p, iFan0, iFan1, iFan2, fCompl0, fCompl1, fCompl2, fUnit0, fUnit1, fUnit2, Gia_ObjIsXor(pObjNew), DelayMax, 1 );
+//printf( "B" );
+    assert( Cost >= 0 );
+    return Cost;
+}
+int Bal_ManEvalTwo( Bal_Man_t * p, int iLitNew0, int iLitNew1, int iLitNew2, int fIsXor )
+{
+    int iFan0    = Abc_Lit2Var( iLitNew0 );
+    int iFan1    = Abc_Lit2Var( iLitNew1 );
+    int iFan2    = Abc_Lit2Var( iLitNew2 );
+    int fCompl0  = Abc_LitIsCompl( iLitNew0 );
+    int fCompl1  = Abc_LitIsCompl( iLitNew1 );
+    int fCompl2  = Abc_LitIsCompl( iLitNew2 );
+    int Delay0   = Bal_ObjDelay( p, iFan0 );
+    int Delay1   = Bal_ObjDelay( p, iFan1 );
+    int Delay2   = Bal_ObjDelay( p, iFan2 );
+    int DelayMax = Abc_MaxInt( Delay0, Abc_MaxInt(Delay1, Delay2) );
+    int fUnit0   = (int)(Delay0 != DelayMax); 
+    int fUnit1   = (int)(Delay1 != DelayMax); 
+    int fUnit2   = (int)(Delay2 != DelayMax); 
+    if ( DelayMax == 0 )
+        return -1;
+    return Bal_ManDeriveCuts(p, iFan0, iFan1, iFan2, fCompl0, fCompl1, fCompl2, fUnit0, fUnit1, fUnit2, fIsXor, DelayMax, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sort literals by their cost.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntSelectSortCostLit( Vec_Int_t * vSuper, Vec_Int_t * vCosts )
+{
+    int * pArray = Vec_IntArray(vSuper);
+    int nSize = Vec_IntSize(vSuper);
+    int i, j, best_i;
+    for ( i = 0; i < nSize-1; i++ )
+    {
+        best_i = i;
+        for ( j = i+1; j < nSize; j++ )
+            if ( Vec_IntEntry(vCosts, Abc_Lit2Var(pArray[j])) > Vec_IntEntry(vCosts, Abc_Lit2Var(pArray[best_i])) )
+                best_i = j;
+        ABC_SWAP( int, pArray[i], pArray[best_i] );
+    }
+}
+static inline void Vec_IntPushOrderCost( Vec_Int_t * vSuper, Vec_Int_t * vCosts, int iLit )
+{
+    int i, nSize, * pArray;
+    Vec_IntPush( vSuper, iLit );
+    pArray = Vec_IntArray(vSuper);
+    nSize = Vec_IntSize(vSuper);
+    for ( i = nSize-1; i > 0; i-- )
+    {
+        if ( Vec_IntEntry(vCosts, Abc_Lit2Var(pArray[i])) <= Vec_IntEntry(vCosts, Abc_Lit2Var(pArray[i - 1])) )
+            return;
+        ABC_SWAP( int, pArray[i], pArray[i - 1] );
+    }
+}
+static inline int Vec_IntFindFirstSameDelayAsLast( Bal_Man_t * p, Vec_Int_t * vSuper )
+{
+    int i, DelayCur, Delay = Bal_LitDelay( p, Vec_IntEntryLast(vSuper) );
+    assert( Vec_IntSize(vSuper) > 1 );
+    for ( i = Vec_IntSize(vSuper)-1; i > 0; i-- )
+    {
+        DelayCur = Bal_LitDelay( p, Vec_IntEntry(vSuper, i-1) );
+        assert( DelayCur >= Delay );
+        if ( DelayCur > Delay )
+            return i;
+    }
+    return i;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Select the best pair to merge.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Bal_ManFindBestPair( Bal_Man_t * p, Vec_Int_t * vSuper, Gia_Obj_t * pObj )
+{
+    int * pSuper = Vec_IntArray(vSuper);
+    int iBeg = Vec_IntFindFirstSameDelayAsLast( p, vSuper );
+    int iEnd = Vec_IntSize(vSuper)-1;
+    int i, k, iBest = -1, kBest = -1, BestCost = ABC_INFINITY, Cost;
+    assert( iBeg <= iEnd );
+    // check if we can add to the higher levels without increasing cost
+    for ( k = iBeg-1; k >= 0; k-- )
+    for ( i = iEnd; i >= iBeg; i-- )
+    {
+        Cost = Bal_ManEvalTwo( p, pSuper[i], pSuper[k], 0, Gia_ObjIsXor(pObj) );
+        if ( Cost == -1 )
+            continue;
+        if ( Cost == Bal_LitCost(p, pSuper[k]) )
+        {
+//            printf( "A" );
+            return (k << 16)|i;
+        }
+        if ( BestCost > Cost )
+            BestCost = Cost, iBest = i, kBest = k;
+    }
+    if ( BestCost != ABC_INFINITY && (BestCost >> 4) == Bal_LitDelay(p, pSuper[kBest]) )
+    {
+//        printf( "B" );
+        return (kBest << 16)|iBest;
+    }
+    // check if some can be added to lowest level without increasing cost
+    BestCost = ABC_INFINITY;
+    for ( i = iBeg; i <= iEnd; i++ )
+    for ( k = i+1;  k <= iEnd; k++ )
+    {
+        Cost = Bal_ManEvalTwo( p, pSuper[i], pSuper[k], 0, Gia_ObjIsXor(pObj) );
+        if ( Cost == -1 )
+            continue;
+        if ( Cost == Abc_MaxInt(Bal_LitCost(p, pSuper[i]), Bal_LitCost(p, pSuper[k])) )
+        {
+//            printf( "C" );
+            return (k << 16)|i;
+        }
+        if ( BestCost > Cost )
+            BestCost = Cost, iBest = i, kBest = k;
+    }
+    if ( BestCost != ABC_INFINITY )
+    {
+//        printf( "D" );
+        return (kBest << 16)|iBest;
+    }
+//    printf( "E" );
+    // group pairs from lowest level based on proximity
+    return (iEnd << 16)|(iEnd-1);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simplify multi-input AND/XOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSimplifyXor( Vec_Int_t * vSuper )
+{
+    int i, k = 0, Prev = -1, This, fCompl = 0;
+    Vec_IntForEachEntry( vSuper, This, i )
+    {
+        if ( This == 0 )
+            continue;
+        if ( This == 1 )
+            fCompl ^= 1; 
+        else if ( Prev != This )
+            Vec_IntWriteEntry( vSuper, k++, This ), Prev = This;
+        else
+            Prev = -1, k--;
+    }
+    Vec_IntShrink( vSuper, k );
+    if ( Vec_IntSize( vSuper ) == 0 )
+        Vec_IntPush( vSuper, fCompl );
+    else if ( fCompl )
+        Vec_IntWriteEntry( vSuper, 0, Abc_LitNot(Vec_IntEntry(vSuper, 0)) );
+}
+static inline void Gia_ManSimplifyAnd( Vec_Int_t * vSuper )
+{
+    int i, k = 0, Prev = -1, This;
+    Vec_IntForEachEntry( vSuper, This, i )
+    {
+        if ( This == 0 )
+            { Vec_IntFill(vSuper, 1, 0); return; }
+        if ( This == 1 )
+            continue;
+        if ( Prev == -1 || Abc_Lit2Var(Prev) != Abc_Lit2Var(This) )
+            Vec_IntWriteEntry( vSuper, k++, This ), Prev = This;
+        else if ( Prev != This )
+            { Vec_IntFill(vSuper, 1, 0); return; }
+    }
+    Vec_IntShrink( vSuper, k );
+    if ( Vec_IntSize( vSuper ) == 0 )
+        Vec_IntPush( vSuper, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect multi-input AND/XOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSuperCollectXor_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    assert( !Gia_IsComplement(pObj) );
+    if ( !Gia_ObjIsXor(pObj) || 
+//        Gia_ObjRefNum(p, pObj) > 1 || 
+        Gia_ObjRefNum(p, pObj) > 3 || 
+//        (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || 
+        Vec_IntSize(p->vSuper) > BAL_SUPER )
+    {
+        Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) );
+        return;
+    }
+    assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) );
+    Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj) );
+    Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj) );
+}
+static inline void Gia_ManSuperCollectAnd_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( Gia_IsComplement(pObj) || 
+        !Gia_ObjIsAndReal(p, pObj) || 
+//        Gia_ObjRefNum(p, pObj) > 1 || 
+        Gia_ObjRefNum(p, pObj) > 3 || 
+//        (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || 
+        Vec_IntSize(p->vSuper) > BAL_SUPER )
+    {
+        Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) );
+        return;
+    }
+    Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj) );
+    Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj) );
+}
+static inline void Gia_ManSuperCollect( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+//    int nSize;
+    if ( p->vSuper == NULL )
+        p->vSuper = Vec_IntAlloc( 1000 );
+    else
+        Vec_IntClear( p->vSuper );
+    if ( Gia_ObjIsXor(pObj) )
+    {
+        assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) );
+        Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj) );
+        Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj) );
+//        nSize = Vec_IntSize(vSuper);
+        Vec_IntSort( p->vSuper, 0 );
+        Gia_ManSimplifyXor( p->vSuper );
+//        if ( nSize != Vec_IntSize(vSuper) )
+//            printf( "X %d->%d  ", nSize, Vec_IntSize(vSuper) );
+    }
+    else if ( Gia_ObjIsAndReal(p, pObj) )
+    {
+        Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj) );
+        Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj) );
+//        nSize = Vec_IntSize(vSuper);
+        Vec_IntSort( p->vSuper, 0 );
+        Gia_ManSimplifyAnd( p->vSuper );
+//        if ( nSize != Vec_IntSize(vSuper) )
+//            printf( "A %d->%d  ", nSize, Vec_IntSize(vSuper) );
+    }
+    else assert( 0 );
+//    if ( nSize > 10 )
+//        printf( "%d ", nSize );
+    assert( Vec_IntSize(p->vSuper) > 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManCreateGate( Gia_Man_t * pNew, Gia_Obj_t * pObj, Vec_Int_t * vSuper )
+{
+    int iLit0 = Vec_IntPop(vSuper);
+    int iLit1 = Vec_IntPop(vSuper);
+    int iLit, i;
+    if ( !Gia_ObjIsXor(pObj) )
+        iLit = Gia_ManHashAnd( pNew, iLit0, iLit1 );
+    else if ( pNew->pMuxes )
+        iLit = Gia_ManHashXorReal( pNew, iLit0, iLit1 );
+    else 
+        iLit = Gia_ManHashXor( pNew, iLit0, iLit1 );
+    Vec_IntPush( vSuper, iLit );
+    Bal_ManSetGateLevel( Bal_GiaMan(pNew), pObj, iLit );
+//    Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(iLit)) );
+    // shift to the corrent location
+    for ( i = Vec_IntSize(vSuper)-1; i > 0; i-- )
+    {
+        int iLit1 = Vec_IntEntry(vSuper, i);
+        int iLit2 = Vec_IntEntry(vSuper, i-1);
+        if ( Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit1)) <= Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit2)) )
+            break;
+        Vec_IntWriteEntry( vSuper, i,   iLit2 );
+        Vec_IntWriteEntry( vSuper, i-1, iLit1 );
+    }
+}
+static inline int Gia_ManBalanceGate( Gia_Man_t * pNew, Gia_Obj_t * pObj, Vec_Int_t * vSuper, int * pLits, int nLits )
+{
+    Vec_IntClear( vSuper );
+    if ( nLits == 1 )
+        Vec_IntPush( vSuper, pLits[0] );
+    else if ( nLits == 2 )
+    {
+        Vec_IntPush( vSuper, pLits[0] );
+        Vec_IntPush( vSuper, pLits[1] );
+        Gia_ManCreateGate( pNew, pObj, vSuper );
+    }
+    else if ( nLits > 2 )
+    {
+        Bal_Man_t * p = Bal_GiaMan(pNew); int i;
+        for ( i = 0; i < nLits; i++ )
+            Vec_IntPush( vSuper, pLits[i] );
+        // sort by level/cut-size
+        Vec_IntSelectSortCostLit( vSuper, p->vCosts );
+        // iterate till everything is grouped
+        while ( Vec_IntSize(vSuper) > 1 )
+        {
+            int iLit, Res = Bal_ManFindBestPair( p, vSuper, pObj );
+            int iBest = Vec_IntEntry( vSuper, Res >> 16 );
+            int kBest = Vec_IntEntry( vSuper, Res & 0xFFFF );
+            Vec_IntRemove( vSuper, iBest );
+            Vec_IntRemove( vSuper, kBest );
+            if ( Gia_ObjIsXor(pObj) )
+                iLit = Gia_ManHashXorReal( pNew, iBest, kBest );
+            else 
+                iLit = Gia_ManHashAnd( pNew, iBest, kBest );
+            Bal_ManSetGateLevel( p, pObj, iLit );
+            Vec_IntPushOrderCost( vSuper, p->vCosts, iLit );
+        }
+    }
+    // consider trivial case
+    assert( Vec_IntSize(vSuper) == 1 );
+    return Vec_IntEntry(vSuper, 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManBalance_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    int i, iLit, iBeg, iEnd;
+    if ( ~pObj->Value )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    // handle MUX
+    if ( Gia_ObjIsMux(p, pObj) )
+    {
+        Gia_ManBalance_rec( pNew, p, Gia_ObjFanin0(pObj) );
+        Gia_ManBalance_rec( pNew, p, Gia_ObjFanin1(pObj) );
+        Gia_ManBalance_rec( pNew, p, Gia_ObjFanin2(p, pObj) );
+        pObj->Value = Gia_ManHashMuxReal( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) );
+        Bal_ManSetGateLevel( Bal_GiaMan(pNew), pObj, pObj->Value );
+//        Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value)) );
+        return;
+    }
+    // find supergate
+    Gia_ManSuperCollect( p, pObj );
+    // save entries
+    if ( p->vStore == NULL )
+        p->vStore = Vec_IntAlloc( 1000 );
+    iBeg = Vec_IntSize( p->vStore );
+    Vec_IntAppend( p->vStore, p->vSuper );
+    iEnd = Vec_IntSize( p->vStore );
+    // call recursively
+    Vec_IntForEachEntryStartStop( p->vStore, iLit, i, iBeg, iEnd )
+    {
+        Gia_Obj_t * pTemp = Gia_ManObj( p, Abc_Lit2Var(iLit) );
+        Gia_ManBalance_rec( pNew, p, pTemp );
+        Vec_IntWriteEntry( p->vStore, i, Abc_LitNotCond(pTemp->Value, Abc_LitIsCompl(iLit)) );
+    }
+    assert( Vec_IntSize(p->vStore) == iEnd );
+    // consider general case
+    pObj->Value = Gia_ManBalanceGate( pNew, pObj, p->vSuper, Vec_IntEntryP(p->vStore, iBeg), iEnd-iBeg );
+    Vec_IntShrink( p->vStore, iBeg );
+}
+static inline Gia_Man_t * Gia_ManBalanceInt( Gia_Man_t * p, int nLutSize, int nCutNum, int fVerbose )
+{
+    Bal_Man_t * pMan;
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManFillValue( p );
+    Gia_ManCreateRefs( p ); 
+    // start the new manager
+    pNew = Gia_ManStart( 3*Gia_ManObjNum(p)/2 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc );
+    pNew->vLevels = Vec_IntStart( pNew->nObjsAlloc );
+    // create constant and inputs
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    // create balancing manager
+    pMan = Bal_ManAlloc( p, pNew, nLutSize, nCutNum, fVerbose );
+    // create internal nodes
+    Gia_ManHashStart( pNew );
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManBalance_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+//    if ( fVerbose )
+    {
+        int nLevelMax = 0;
+        Gia_ManForEachCo( pNew, pObj, i )
+        {
+            nLevelMax = Abc_MaxInt( nLevelMax, Bal_ObjDelay(pMan, Gia_ObjFaninId0p(pNew, pObj)) );
+//            printf( "%d=%d ", i, Bal_ObjDelay(pMan, Gia_ObjFaninId0p(pNew, pObj)) );
+        }
+        printf( "Best delay = %d\n", nLevelMax );
+    }
+
+//    assert( Gia_ManObjNum(pNew) <= Gia_ManObjNum(p) );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    // delete manager
+    Bal_ManFree( pMan );
+    // perform cleanup
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+Gia_Man_t * Gia_ManBalanceLut( Gia_Man_t * p, int nLutSize, int nCutNum, int fVerbose )
+{
+    Gia_Man_t * pNew, * pNew1, * pNew2;
+    if ( fVerbose )      Gia_ManPrintStats( p, NULL );
+    pNew = Gia_ManDupMuxes( p, 2 );
+    if ( fVerbose )      Gia_ManPrintStats( pNew, NULL );
+    pNew1 = Gia_ManBalanceInt( pNew, nLutSize, nCutNum, fVerbose );
+    if ( fVerbose )      Gia_ManPrintStats( pNew1, NULL );
+    Gia_ManStop( pNew );
+    pNew2 = Gia_ManDupNoMuxes( pNew1 );
+    if ( fVerbose )      Gia_ManPrintStats( pNew2, NULL );
+    Gia_ManStop( pNew1 );
+    return pNew2;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaBidec.c b/abc-build/src/aig/gia/giaBidec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaBidec.c
@@ -0,0 +1,305 @@
+/**CFile****************************************************************
+
+  FileName    [giaBidec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Application of bi-decomposition to AIG minimization.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaBidec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "bool/bdc/bdc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Gia_ManConvertAigToTruth_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vTruth, int nWords, Vec_Int_t * vVisited )
+{
+    unsigned * pTruth, * pTruth0, * pTruth1;
+    int i;
+    assert( !Gia_IsComplement(pObj) );
+    if ( Vec_IntGetEntry(p->vTruths, Gia_ObjId(p, pObj)) != -1 )
+        return (unsigned *)Vec_IntEntryP( vTruth, nWords * Vec_IntGetEntry(p->vTruths, Gia_ObjId(p, pObj)) );
+    // compute the truth tables of the fanins
+    pTruth0 = Gia_ManConvertAigToTruth_rec( p, Gia_ObjFanin0(pObj), vTruth, nWords, vVisited );
+    pTruth1 = Gia_ManConvertAigToTruth_rec( p, Gia_ObjFanin1(pObj), vTruth, nWords, vVisited );
+    // get room for the truth table
+    pTruth = Vec_IntFetch( vTruth, nWords );
+    // create the truth table of the node
+    if ( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = pTruth0[i] & pTruth1[i];
+    else if ( !Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = pTruth0[i] & ~pTruth1[i];
+    else if ( Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ~pTruth0[i] & pTruth1[i];
+    else // if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ~pTruth0[i] & ~pTruth1[i];
+    // save the visited node
+    Vec_IntSetEntry( p->vTruths, Gia_ObjId(p, pObj), Vec_IntSize(vVisited) );
+    Vec_IntPush( vVisited, Gia_ObjId(p, pObj) );
+    return pTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table of the node.]
+
+  Description [Assumes that the structural support is no more than 8 inputs.
+  Uses array vTruth to store temporary truth tables. The returned pointer should 
+  be used immediately.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Gia_ManConvertAigToTruth( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vTruth, Vec_Int_t * vVisited )
+{
+    static unsigned uTruths[8][8] = { // elementary truth tables
+        { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA },
+        { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC },
+        { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 },
+        { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 },
+        { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, 
+        { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, 
+        { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, 
+        { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } 
+    };
+    Gia_Obj_t * pObj;
+    Vec_Ptr_t * vTtElems = NULL;
+    unsigned * pTruth;//, * pTruth2;
+    int i, nWords, nVars;
+    // get the number of variables and words
+    nVars  = Vec_IntSize( vLeaves );
+    nWords = Abc_TruthWordNum( nVars );
+    // check the case of a constant
+    if ( Gia_ObjIsConst0( Gia_Regular(pRoot) ) )
+    {
+        Vec_IntClear( vTruth );
+        // get room for the truth table
+        pTruth = Vec_IntFetch( vTruth, nWords );
+        if ( !Gia_IsComplement(pRoot) )
+            Gia_ManTruthClear( pTruth, nVars );
+        else
+            Gia_ManTruthFill( pTruth, nVars );
+        return pTruth;
+    }
+    // if the number of variables is more than 8, allocate truth tables
+    if ( nVars > 8 )
+        vTtElems = Vec_PtrAllocTruthTables( nVars );
+    // assign elementary truth tables
+    Vec_IntClear( vTruth );
+    Vec_IntClear( vVisited );
+    Gia_ManForEachObjVec( vLeaves, p, pObj, i )
+    {
+        // get room for the truth table
+        pTruth = Vec_IntFetch( vTruth, nWords );
+        // assign elementary variable
+        if ( vTtElems )
+            Gia_ManTruthCopy( pTruth, (unsigned *)Vec_PtrEntry(vTtElems, i), nVars );
+        else
+            Gia_ManTruthCopy( pTruth, uTruths[i], nVars );
+        // save the visited node
+        Vec_IntSetEntry( p->vTruths, Gia_ObjId(p, pObj), Vec_IntSize(vVisited) );
+        Vec_IntPush( vVisited, Gia_ObjId(p, pObj) );
+    }
+    if ( vTtElems )
+        Vec_PtrFree( vTtElems );
+    // clear the marks and compute the truth table
+//    pTruth2 = Gia_ManConvertAigToTruth_rec( p, Gia_Regular(pRoot), vTruth, nWords, vVisited );
+    pTruth = Gia_ManConvertAigToTruth_rec( p, Gia_Regular(pRoot), vTruth, nWords, vVisited );
+    // copy the result
+//    Gia_ManTruthCopy( pTruth, pTruth2, nVars );
+    if ( Gia_IsComplement(pRoot) )
+        Gia_ManTruthNot( pTruth, pTruth, nVars );
+    // clean truth tables
+    Gia_ManForEachObjVec( vVisited, p, pObj, i )
+        Vec_IntSetEntry( p->vTruths, Gia_ObjId(p, pObj), -1 );
+    return pTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resynthesizes nodes using bi-decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ObjPerformBidec( Bdc_Man_t * pManDec, 
+        Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pRoot, 
+        Vec_Int_t * vLeaves, Vec_Int_t * vTruth, Vec_Int_t * vVisited )
+{
+    unsigned * pTruth;
+    Bdc_Fun_t * pFunc;
+    Gia_Obj_t * pFanin;
+    int i, iFan, nVars, nNodes;
+    // collect leaves of this gate
+    Vec_IntClear( vLeaves );
+    Gia_LutForEachFanin( p, Gia_ObjId(p, pRoot), iFan, i )
+        Vec_IntPush( vLeaves, iFan );
+    nVars = Vec_IntSize( vLeaves );
+    assert( nVars < 16 );
+    // derive truth table
+    pTruth = Gia_ManConvertAigToTruth( p, pRoot, vLeaves, vTruth, vVisited );
+//Extra_PrintBinary( stdout, pTruth, (1<<nVars) ); printf( "\n" );
+    if ( Gia_ManTruthIsConst0(pTruth, nVars) )
+    {
+//printf( "Node %d is const0\n", Gia_ObjId(p, pRoot) );
+        return 0;
+    }
+    if ( Gia_ManTruthIsConst1(pTruth, nVars) )
+    {
+//printf( "Node %d is const1\n", Gia_ObjId(p, pRoot) );
+        return 1;
+    }
+    // decompose truth table
+    Bdc_ManDecompose( pManDec, pTruth, NULL, nVars, NULL, 1000 );
+/*
+if ( Bdc_ManNodeNum(pManDec) == 0 )
+    printf( "Node %d has 0 bidec nodes\n", Gia_ObjId(p, pRoot) );
+if ( Kit_TruthSupportSize(pTruth, nVars) != nVars )
+{
+    printf( "Node %d has %d fanins and %d supp size\n", Gia_ObjId(p, pRoot), nVars, Kit_TruthSupportSize(pTruth, nVars) );
+    Gia_LutForEachFanin( p, Gia_ObjId(p, pRoot), iFan, i )
+    {
+        printf( "%d  ", Kit_TruthVarInSupport(pTruth, nVars, i) );
+        Gia_ObjPrint( p, Gia_ManObj(p, iFan) );
+    }
+//    Gia_ManPrintStats( p, 0 );
+}
+*/
+    // convert back into HOP
+    Bdc_FuncSetCopy( Bdc_ManFunc( pManDec, 0 ), Gia_ManConst1(pNew) );
+    Gia_ManForEachObjVec( vLeaves, p, pFanin, i )
+        Bdc_FuncSetCopyInt( Bdc_ManFunc( pManDec, i+1 ), Gia_ObjValue(pFanin) );
+    nNodes = Bdc_ManNodeNum( pManDec );
+    for ( i = nVars + 1; i < nNodes; i++ )
+    {
+        pFunc = Bdc_ManFunc( pManDec, i );
+        Bdc_FuncSetCopyInt( pFunc, Gia_ManHashAnd( pNew, Bdc_FunFanin0Copy(pFunc), Bdc_FunFanin1Copy(pFunc) ) );
+    }
+    return Bdc_FunObjCopy( Bdc_ManRoot(pManDec) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManPerformBidec( Gia_Man_t * p, int fVerbose )
+{
+    Bdc_Man_t * pManDec;
+    Bdc_Par_t Pars = {0}, * pPars = &Pars;
+    Vec_Int_t * vLeaves, * vTruth, * vVisited;
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i;//, clk = Abc_Clock();
+    pPars->nVarsMax = Gia_ManLutSizeMax( p );
+    pPars->fVerbose = fVerbose;
+    if ( pPars->nVarsMax < 2 )
+    {
+        printf( "Resynthesis is not performed when nodes have less than 2 inputs.\n" );
+        return NULL;
+    }
+    if ( pPars->nVarsMax > 15 )
+    {
+        printf( "Resynthesis is not performed when nodes have more than 15 inputs.\n" );
+        return NULL;
+    }
+    vLeaves  = Vec_IntAlloc( 0 );
+    vTruth   = Vec_IntAlloc( (1<<16) );
+    vVisited = Vec_IntAlloc( 0 );
+    // clean the old manager
+    Gia_ManCleanTruth( p );
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    // start the new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+//    Gia_ManCleanLevels( pNew, Gia_ManObjNum(p) );
+    pManDec = Bdc_ManAlloc( pPars );
+    Gia_ManForEachObj1( p, pObj, i )
+    {        
+        if ( Gia_ObjIsCi(pObj) ) // transfer the CI level (is it needed?)
+            pObj->Value = Gia_ManAppendCi( pNew );
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+        else if ( Gia_ObjIsLut(p, i) )
+            pObj->Value = Gia_ObjPerformBidec( pManDec, pNew, p, pObj, vLeaves, vTruth, vVisited );
+    }
+    Bdc_ManFree( pManDec );
+    // cleanup the AIG
+    Gia_ManHashStop( pNew );
+    // check the presence of dangling nodes
+    if ( Gia_ManHasDangling(pNew) )
+    {
+        pNew = Gia_ManCleanup( pTemp = pNew );
+        if ( Gia_ManAndNum(pNew) != Gia_ManAndNum(pTemp) )
+            printf( "Gia_ManPerformBidec() node count before and after: %6d and %6d.\n", Gia_ManAndNum(pNew), Gia_ManAndNum(pTemp) );
+        Gia_ManStop( pTemp );
+    }
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    Vec_IntFree( vLeaves );
+    Vec_IntFree( vTruth );
+    Vec_IntFree( vVisited );
+    if ( fVerbose )
+    {
+//        printf( "Total gain in AIG nodes = %d.  ", Gia_ManObjNum(p)-Gia_ManObjNum(pNew) );
+//        ABC_PRT( "Total runtime", Abc_Clock() - clk );
+    }
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaCCof.c b/abc-build/src/aig/gia/giaCCof.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaCCof.c
@@ -0,0 +1,349 @@
+/**CFile****************************************************************
+
+  FileName    [giaCCof.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Backward reachability using circuit cofactoring.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaCCof.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ccf_Man_t_ Ccf_Man_t; // manager
+struct Ccf_Man_t_
+{
+    // user data
+    Gia_Man_t *  pGia;       // single-output AIG manager
+    int          nFrameMax;  // maximum number of frames
+    int          nConfMax;   // maximum number of conflicts
+    int          nTimeMax;   // maximum runtime in seconds
+    int          fVerbose;   // verbose flag
+    // internal data
+    void *       pUnr;       // unrolling manager
+    Gia_Man_t *  pFrames;    // unrolled timeframes
+    Vec_Int_t *  vCopies;    // copy pointers of the AIG
+    sat_solver * pSat;       // SAT solver
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Create manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ccf_Man_t * Ccf_ManStart( Gia_Man_t * pGia, int nFrameMax, int nConfMax, int nTimeMax, int fVerbose )
+{
+    static Gia_ParFra_t Pars, * pPars = &Pars;
+    Ccf_Man_t * p;
+    assert( nFrameMax > 0 );
+    p = ABC_CALLOC( Ccf_Man_t, 1 );
+    p->pGia      = pGia;
+    p->nFrameMax = nFrameMax;    
+    p->nConfMax  = nConfMax;
+    p->nTimeMax  = nTimeMax;
+    p->fVerbose  = fVerbose;
+    // create unrolling manager
+    memset( pPars, 0, sizeof(Gia_ParFra_t) );
+    pPars->fVerbose     = fVerbose;
+    pPars->nFrames      = nFrameMax;
+    pPars->fSaveLastLit = 1;
+    p->pUnr = Gia_ManUnrollStart( pGia, pPars );
+    p->vCopies = Vec_IntAlloc( 1000 );
+    // internal data
+    p->pSat = sat_solver_new();
+//    sat_solver_setnvars( p->pSat, 10000 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Delete manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ccf_ManStop( Ccf_Man_t * p )
+{
+    Vec_IntFree( p->vCopies );
+    Gia_ManUnrollStop( p->pUnr );
+    sat_solver_delete( p->pSat );
+    Gia_ManStopP( &p->pFrames );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Extends the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCofExtendSolver( Ccf_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    // add SAT clauses
+    for ( i = sat_solver_nvars(p->pSat); i < Gia_ManObjNum(p->pFrames); i++ )
+    {
+        pObj = Gia_ManObj( p->pFrames, i );
+        if ( Gia_ObjIsAnd(pObj) )
+            sat_solver_add_and( p->pSat, i, 
+                Gia_ObjFaninId0(pObj, i), 
+                Gia_ObjFaninId1(pObj, i), 
+                Gia_ObjFaninC0(pObj), 
+                Gia_ObjFaninC1(pObj), 0 ); 
+    }
+    sat_solver_setnvars( p->pSat, Gia_ManObjNum(p->pFrames) );
+}
+
+static inline int Gia_Obj0Copy( Vec_Int_t * vCopies, int Fan0, int fCompl0 )  
+{ return Abc_LitNotCond( Vec_IntEntry(vCopies, Fan0), fCompl0 ); }
+
+static inline int Gia_Obj1Copy( Vec_Int_t * vCopies, int Fan1, int fCompl1 )  
+{ return Abc_LitNotCond( Vec_IntEntry(vCopies, Fan1), fCompl1 ); }
+ 
+/**Function*************************************************************
+
+  Synopsis    [Cofactor the circuit w.r.t. the given assignment.]
+
+  Description [Assumes that the solver has just returned SAT.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCofOneDerive_rec( Ccf_Man_t * p, int Id )
+{
+    Gia_Obj_t * pObj;
+    int Res;
+    if ( Vec_IntEntry(p->vCopies, Id) != -1 )
+        return;
+    pObj = Gia_ManObj(p->pFrames, Id);
+    assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) );
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        int fCompl0 = Gia_ObjFaninC0(pObj);
+        int fCompl1 = Gia_ObjFaninC1(pObj);
+        int Fan0 = Gia_ObjFaninId0p(p->pFrames, pObj);
+        int Fan1 = Gia_ObjFaninId1p(p->pFrames, pObj);
+        Gia_ManCofOneDerive_rec( p, Fan0 );
+        Gia_ManCofOneDerive_rec( p, Fan1 );
+        Res = Gia_ManHashAnd( p->pFrames, 
+            Gia_Obj0Copy(p->vCopies, Fan0, fCompl0), 
+            Gia_Obj1Copy(p->vCopies, Fan1, fCompl1) );
+    }
+    else if ( Gia_ObjCioId(pObj) >= Gia_ManRegNum(p->pGia) ) // PI
+        Res = sat_solver_var_value( p->pSat, Id );
+    else
+        Res = Abc_Var2Lit( Id, 0 );
+    Vec_IntWriteEntry( p->vCopies, Id, Res );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cofactor the circuit w.r.t. the given assignment.]
+
+  Description [Assumes that the solver has just returned SAT.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCofOneDerive( Ccf_Man_t * p, int LitProp )
+{
+    int LitOut;
+    // derive the cofactor of the property node
+    Vec_IntFill( p->vCopies, Gia_ManObjNum(p->pFrames), -1 );
+    Gia_ManCofOneDerive_rec( p, Abc_Lit2Var(LitProp) );
+    LitOut = Vec_IntEntry( p->vCopies, Abc_Lit2Var(LitProp) );
+    LitOut = Abc_LitNotCond( LitOut, Abc_LitIsCompl(LitProp) );
+    // add new PO for the cofactor
+    Gia_ManAppendCo( p->pFrames, LitOut );
+    // add SAT clauses
+    Gia_ManCofExtendSolver( p );
+    // return negative literal of the cofactor
+    return Abc_LitNot(LitOut);
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Enumerates backward reachable states.]
+
+  Description [Return -1 if resource limit is reached. Returns 1 
+  if computation converged (there is no more reachable states).
+  Returns 0 if no more states to enumerate.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCofGetReachable( Ccf_Man_t * p, int Lit )
+{
+    int ObjPrev = 0, ConfPrev = 0;
+    int Count = 0, LitOut, RetValue;
+    abctime clk;
+    // try solving for the first time and quit if converged
+    RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, p->nConfMax, 0, 0, 0 );
+    if ( RetValue == l_False )
+        return 1;
+    // iterate circuit cofactoring
+    while ( RetValue == l_True )
+    {
+        clk = Abc_Clock();
+        // derive cofactor
+        LitOut = Gia_ManCofOneDerive( p, Lit );
+        // add the blocking clause
+        RetValue = sat_solver_addclause( p->pSat, &LitOut, &LitOut + 1 );
+        assert( RetValue );
+        // try solving again
+        RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, p->nConfMax, 0, 0, 0 );
+        // derive cofactors
+        if ( p->fVerbose ) 
+        {
+            printf( "%3d : AIG =%7d  Conf =%7d.  ", Count++, 
+                Gia_ManObjNum(p->pFrames) - ObjPrev, sat_solver_nconflicts(p->pSat) - ConfPrev );
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+            ObjPrev = Gia_ManObjNum(p->pFrames);
+            ConfPrev = sat_solver_nconflicts(p->pSat);
+        }
+    }
+    if ( RetValue == l_Undef )
+        return -1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManCofTest( Gia_Man_t * pGia, int nFrameMax, int nConfMax, int nTimeMax, int fVerbose )
+{ 
+    Gia_Man_t * pNew;
+    Ccf_Man_t * p;
+    Gia_Obj_t * pObj;
+    int f, i, Lit, RetValue = -1, fFailed = 0;
+    abctime nTimeToStop = Abc_Clock() + nTimeMax * CLOCKS_PER_SEC;
+    abctime clk = Abc_Clock();
+    assert( Gia_ManPoNum(pGia) == 1 );
+
+    // create reachability manager
+    p = Ccf_ManStart( pGia, nFrameMax, nConfMax, nTimeMax, fVerbose );
+
+    // set runtime limit
+    if ( nTimeMax )
+        sat_solver_set_runtime_limit( p->pSat, nTimeToStop );
+
+    // perform backward image computation
+    for ( f = 0; f < nFrameMax; f++ )
+    {
+        if ( fVerbose ) 
+            printf( "ITER %3d :\n", f );
+        // add to the mapping of nodes
+        p->pFrames = (Gia_Man_t *)Gia_ManUnrollAdd( p->pUnr, f+1 );
+        // add SAT clauses
+        Gia_ManCofExtendSolver( p );
+        // return output literal
+        Lit = Gia_ManUnrollLastLit( p->pUnr );
+        // derives cofactors of the property literal till all states are blocked
+        RetValue = Gia_ManCofGetReachable( p, Lit );
+        if ( RetValue )
+            break;
+
+        // check the property output
+        Gia_ManSetPhase( p->pFrames );
+        Gia_ManForEachPo( p->pFrames, pObj, i )
+            if ( pObj->fPhase )
+            {
+                printf( "Property failed in frame %d.\n", f );
+                fFailed = 1;
+                break;
+            }
+        if ( i < Gia_ManPoNum(p->pFrames) )
+            break;
+    }
+
+    // report the result
+    if ( nTimeToStop && Abc_Clock() > nTimeToStop )
+        printf( "Runtime limit (%d sec) is reached after %d frames.  ", nTimeMax, f );
+    else if ( f == nFrameMax )
+        printf( "Completed %d frames without converging.  ", f );
+    else if ( RetValue == 1 )
+        printf( "Backward reachability converged after %d iterations.  ", f-1 );
+    else if ( RetValue == -1 )
+        printf( "Conflict limit or timeout is reached after %d frames.  ", f-1 );
+    Abc_PrintTime( 1, "Runtime", Abc_Clock() - clk );
+
+    if ( !fFailed && RetValue == 1 )
+        printf( "Property holds.\n" );
+    else if ( !fFailed )
+        printf( "Property is undecided.\n" );
+
+    // get the resulting AIG manager
+    Gia_ManHashStop( p->pFrames );
+    pNew = p->pFrames;  p->pFrames = NULL;
+    Ccf_ManStop( p );
+
+    // cleanup
+//    if ( fVerbose )
+//        Gia_ManPrintStats( pNew, 0 );
+    pNew = Gia_ManCleanup( pGia = pNew );
+    Gia_ManStop( pGia );
+//    if ( fVerbose )
+//        Gia_ManPrintStats( pNew, 0 );
+    return pNew;   
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaCSat.c b/abc-build/src/aig/gia/giaCSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaCSat.c
@@ -0,0 +1,1103 @@
+/**CFile****************************************************************
+
+  FileName    [giaCSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [A simple circuit-based solver.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaCSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+//#define gia_assert(exp)     ((void)0)
+//#define gia_assert(exp)     (assert(exp))
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Cbs_Par_t_ Cbs_Par_t;
+struct Cbs_Par_t_
+{
+    // conflict limits
+    int           nBTLimit;     // limit on the number of conflicts
+    int           nJustLimit;   // limit on the size of justification queue
+    // current parameters
+    int           nBTThis;      // number of conflicts
+    int           nBTThisNc;    // number of conflicts
+    int           nJustThis;    // max size of the frontier
+    int           nBTTotal;     // total number of conflicts
+    int           nJustTotal;   // total size of the frontier
+    // decision heuristics
+    int           fUseHighest;  // use node with the highest ID
+    int           fUseLowest;   // use node with the highest ID
+    int           fUseMaxFF;    // use node with the largest fanin fanout
+    // other
+    int           fVerbose;
+};
+
+typedef struct Cbs_Que_t_ Cbs_Que_t;
+struct Cbs_Que_t_
+{
+    int           iHead;        // beginning of the queue
+    int           iTail;        // end of the queue
+    int           nSize;        // allocated size
+    Gia_Obj_t **  pData;        // nodes stored in the queue
+};
+ 
+typedef struct Cbs_Man_t_ Cbs_Man_t;
+struct Cbs_Man_t_
+{
+    Cbs_Par_t     Pars;         // parameters
+    Gia_Man_t *   pAig;         // AIG manager
+    Cbs_Que_t     pProp;        // propagation queue
+    Cbs_Que_t     pJust;        // justification queue
+    Cbs_Que_t     pClauses;     // clause queue
+    Gia_Obj_t **  pIter;        // iterator through clause vars
+    Vec_Int_t *   vLevReas;     // levels and decisions
+    Vec_Int_t *   vModel;       // satisfying assignment
+    Vec_Ptr_t *   vTemp;        // temporary storage
+    // SAT calls statistics
+    int           nSatUnsat;    // the number of proofs
+    int           nSatSat;      // the number of failure
+    int           nSatUndec;    // the number of timeouts
+    int           nSatTotal;    // the number of calls
+    // conflicts
+    int           nConfUnsat;   // conflicts in unsat problems
+    int           nConfSat;     // conflicts in sat problems
+    int           nConfUndec;   // conflicts in undec problems
+    // runtime stats
+    abctime       timeSatUnsat; // unsat
+    abctime       timeSatSat;   // sat
+    abctime       timeSatUndec; // undecided
+    abctime       timeTotal;    // total runtime
+};
+
+static inline int   Cbs_VarIsAssigned( Gia_Obj_t * pVar )      { return pVar->fMark0;                        }
+static inline void  Cbs_VarAssign( Gia_Obj_t * pVar )          { assert(!pVar->fMark0); pVar->fMark0 = 1;    }
+static inline void  Cbs_VarUnassign( Gia_Obj_t * pVar )        { assert(pVar->fMark0);  pVar->fMark0 = 0; pVar->fMark1 = 0; pVar->Value = ~0; }
+static inline int   Cbs_VarValue( Gia_Obj_t * pVar )           { assert(pVar->fMark0);  return pVar->fMark1; }
+static inline void  Cbs_VarSetValue( Gia_Obj_t * pVar, int v ) { assert(pVar->fMark0);  pVar->fMark1 = v;    }
+static inline int   Cbs_VarIsJust( Gia_Obj_t * pVar )          { return Gia_ObjIsAnd(pVar) && !Cbs_VarIsAssigned(Gia_ObjFanin0(pVar)) && !Cbs_VarIsAssigned(Gia_ObjFanin1(pVar)); } 
+static inline int   Cbs_VarFanin0Value( Gia_Obj_t * pVar )     { return !Cbs_VarIsAssigned(Gia_ObjFanin0(pVar)) ? 2 : (Cbs_VarValue(Gia_ObjFanin0(pVar)) ^ Gia_ObjFaninC0(pVar)); }
+static inline int   Cbs_VarFanin1Value( Gia_Obj_t * pVar )     { return !Cbs_VarIsAssigned(Gia_ObjFanin1(pVar)) ? 2 : (Cbs_VarValue(Gia_ObjFanin1(pVar)) ^ Gia_ObjFaninC1(pVar)); }
+
+static inline int         Cbs_VarDecLevel( Cbs_Man_t * p, Gia_Obj_t * pVar )  { assert( pVar->Value != ~0 ); return Vec_IntEntry(p->vLevReas, 3*pVar->Value);          }
+static inline Gia_Obj_t * Cbs_VarReason0( Cbs_Man_t * p, Gia_Obj_t * pVar )   { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+1); }
+static inline Gia_Obj_t * Cbs_VarReason1( Cbs_Man_t * p, Gia_Obj_t * pVar )   { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+2); }
+static inline int         Cbs_ClauseDecLevel( Cbs_Man_t * p, int hClause )    { return Cbs_VarDecLevel( p, p->pClauses.pData[hClause] );                               }
+
+#define Cbs_QueForEachEntry( Que, pObj, i )                         \
+    for ( i = (Que).iHead; (i < (Que).iTail) && ((pObj) = (Que).pData[i]); i++ )
+
+#define Cbs_ClauseForEachVar( p, hClause, pObj )                    \
+    for ( (p)->pIter = (p)->pClauses.pData + hClause; (pObj = *pIter); (p)->pIter++ )
+#define Cbs_ClauseForEachVar1( p, hClause, pObj )                   \
+    for ( (p)->pIter = (p)->pClauses.pData+hClause+1; (pObj = *pIter); (p)->pIter++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Sets default values of the parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cbs_SetDefaultParams( Cbs_Par_t * pPars )
+{
+    memset( pPars, 0, sizeof(Cbs_Par_t) );
+    pPars->nBTLimit    =  1000;   // limit on the number of conflicts
+    pPars->nJustLimit  =   100;   // limit on the size of justification queue
+    pPars->fUseHighest =     1;   // use node with the highest ID
+    pPars->fUseLowest  =     0;   // use node with the highest ID
+    pPars->fUseMaxFF   =     0;   // use node with the largest fanin fanout
+    pPars->fVerbose    =     1;   // print detailed statistics
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cbs_Man_t * Cbs_ManAlloc()
+{
+    Cbs_Man_t * p;
+    p = ABC_CALLOC( Cbs_Man_t, 1 );
+    p->pProp.nSize = p->pJust.nSize = p->pClauses.nSize = 10000;
+    p->pProp.pData = ABC_ALLOC( Gia_Obj_t *, p->pProp.nSize );
+    p->pJust.pData = ABC_ALLOC( Gia_Obj_t *, p->pJust.nSize );
+    p->pClauses.pData = ABC_ALLOC( Gia_Obj_t *, p->pClauses.nSize );
+    p->pClauses.iHead = p->pClauses.iTail = 1;
+    p->vModel   = Vec_IntAlloc( 1000 );
+    p->vLevReas = Vec_IntAlloc( 1000 );
+    p->vTemp    = Vec_PtrAlloc( 1000 );
+    Cbs_SetDefaultParams( &p->Pars );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cbs_ManStop( Cbs_Man_t * p )
+{
+    Vec_IntFree( p->vLevReas );
+    Vec_IntFree( p->vModel );
+    Vec_PtrFree( p->vTemp );
+    ABC_FREE( p->pClauses.pData );
+    ABC_FREE( p->pProp.pData );
+    ABC_FREE( p->pJust.pData );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns satisfying assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Cbs_ReadModel( Cbs_Man_t * p )
+{
+    return p->vModel;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the solver is out of limits.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cbs_ManCheckLimits( Cbs_Man_t * p )
+{
+    return p->Pars.nJustThis > p->Pars.nJustLimit || p->Pars.nBTThis > p->Pars.nBTLimit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Saves the satisfying assignment as an array of literals.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cbs_ManSaveModel( Cbs_Man_t * p, Vec_Int_t * vCex )
+{
+    Gia_Obj_t * pVar;
+    int i;
+    Vec_IntClear( vCex );
+    p->pProp.iHead = 0;
+    Cbs_QueForEachEntry( p->pProp, pVar, i )
+        if ( Gia_ObjIsCi(pVar) )
+//            Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !Cbs_VarValue(pVar)) );
+            Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjCioId(pVar), !Cbs_VarValue(pVar)) );
+} 
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cbs_QueIsEmpty( Cbs_Que_t * p )
+{
+    return p->iHead == p->iTail;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cbs_QuePush( Cbs_Que_t * p, Gia_Obj_t * pObj )
+{
+    if ( p->iTail == p->nSize )
+    {
+        p->nSize *= 2;
+        p->pData = ABC_REALLOC( Gia_Obj_t *, p->pData, p->nSize ); 
+    }
+    p->pData[p->iTail++] = pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the object in the queue.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cbs_QueHasNode( Cbs_Que_t * p, Gia_Obj_t * pObj )
+{
+    Gia_Obj_t * pTemp;
+    int i;
+    Cbs_QueForEachEntry( *p, pTemp, i )
+        if ( pTemp == pObj )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cbs_QueStore( Cbs_Que_t * p, int * piHeadOld, int * piTailOld )
+{
+    int i;
+    *piHeadOld = p->iHead;
+    *piTailOld = p->iTail;
+    for ( i = *piHeadOld; i < *piTailOld; i++ )
+        Cbs_QuePush( p, p->pData[i] );
+    p->iHead = *piTailOld;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cbs_QueRestore( Cbs_Que_t * p, int iHeadOld, int iTailOld )
+{
+    p->iHead = iHeadOld;
+    p->iTail = iTailOld;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finalized the clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cbs_QueFinish( Cbs_Que_t * p )
+{
+    int iHeadOld = p->iHead;
+    assert( p->iHead < p->iTail );
+    Cbs_QuePush( p, NULL );
+    p->iHead = p->iTail;
+    return iHeadOld;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Max number of fanins fanouts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cbs_VarFaninFanoutMax( Cbs_Man_t * p, Gia_Obj_t * pObj )
+{
+    int Count0, Count1;
+    assert( !Gia_IsComplement(pObj) );
+    assert( Gia_ObjIsAnd(pObj) );
+    Count0 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin0(pObj) );
+    Count1 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin1(pObj) );
+    return Abc_MaxInt( Count0, Count1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find variable with the highest ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Cbs_ManDecideHighest( Cbs_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pObjMax = NULL;
+    int i;
+    Cbs_QueForEachEntry( p->pJust, pObj, i )
+        if ( pObjMax == NULL || pObjMax < pObj )
+            pObjMax = pObj;
+    return pObjMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find variable with the lowest ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Cbs_ManDecideLowest( Cbs_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pObjMin = NULL;
+    int i;
+    Cbs_QueForEachEntry( p->pJust, pObj, i )
+        if ( pObjMin == NULL || pObjMin > pObj )
+            pObjMin = pObj;
+    return pObjMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find variable with the maximum number of fanin fanouts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Cbs_ManDecideMaxFF( Cbs_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pObjMax = NULL;
+    int i, iMaxFF = 0, iCurFF;
+    assert( p->pAig->pRefs != NULL );
+    Cbs_QueForEachEntry( p->pJust, pObj, i )
+    {
+        iCurFF = Cbs_VarFaninFanoutMax( p, pObj );
+        assert( iCurFF > 0 );
+        if ( iMaxFF < iCurFF )
+        {
+            iMaxFF = iCurFF;
+            pObjMax = pObj;
+        }
+    }
+    return pObjMax; 
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cbs_ManCancelUntil( Cbs_Man_t * p, int iBound )
+{
+    Gia_Obj_t * pVar;
+    int i;
+    assert( iBound <= p->pProp.iTail );
+    p->pProp.iHead = iBound;
+    Cbs_QueForEachEntry( p->pProp, pVar, i )
+        Cbs_VarUnassign( pVar );
+    p->pProp.iTail = iBound;
+    Vec_IntShrink( p->vLevReas, 3*iBound );
+}
+
+int s_Counter = 0;
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns the variables a value.]
+
+  Description [Returns 1 if conflict; 0 if no conflict.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cbs_ManAssign( Cbs_Man_t * p, Gia_Obj_t * pObj, int Level, Gia_Obj_t * pRes0, Gia_Obj_t * pRes1 )
+{
+    Gia_Obj_t * pObjR = Gia_Regular(pObj);
+    assert( Gia_ObjIsCand(pObjR) );
+    assert( !Cbs_VarIsAssigned(pObjR) );
+    Cbs_VarAssign( pObjR );
+    Cbs_VarSetValue( pObjR, !Gia_IsComplement(pObj) );
+    assert( pObjR->Value == ~0 );
+    pObjR->Value = p->pProp.iTail;
+    Cbs_QuePush( &p->pProp, pObjR );
+    Vec_IntPush( p->vLevReas, Level );
+    Vec_IntPush( p->vLevReas, pRes0 ? pRes0-pObjR : 0 );
+    Vec_IntPush( p->vLevReas, pRes1 ? pRes1-pObjR : 0 );
+    assert( Vec_IntSize(p->vLevReas) == 3 * p->pProp.iTail );
+//    s_Counter++;
+//    s_Counter = Abc_MaxIntInt( s_Counter, Vec_IntSize(p->vLevReas)/3 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns clause size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cbs_ManClauseSize( Cbs_Man_t * p, int hClause )
+{
+    Cbs_Que_t * pQue = &(p->pClauses);
+    Gia_Obj_t ** pIter;
+    for ( pIter = pQue->pData + hClause; *pIter; pIter++ );
+    return pIter - pQue->pData - hClause ;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints conflict clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cbs_ManPrintClause( Cbs_Man_t * p, int Level, int hClause )
+{
+    Cbs_Que_t * pQue = &(p->pClauses);
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Cbs_QueIsEmpty( pQue ) );
+    printf( "Level %2d : ", Level );
+    for ( i = hClause; (pObj = pQue->pData[i]); i++ )
+        printf( "%d=%d(%d) ", Gia_ObjId(p->pAig, pObj), Cbs_VarValue(pObj), Cbs_VarDecLevel(p, pObj) );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints conflict clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cbs_ManPrintClauseNew( Cbs_Man_t * p, int Level, int hClause )
+{
+    Cbs_Que_t * pQue = &(p->pClauses);
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Cbs_QueIsEmpty( pQue ) );
+    printf( "Level %2d : ", Level );
+    for ( i = hClause; (pObj = pQue->pData[i]); i++ )
+        printf( "%c%d ", Cbs_VarValue(pObj)? '+':'-', Gia_ObjId(p->pAig, pObj) );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns conflict clause.]
+
+  Description [Performs conflict analysis.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cbs_ManDeriveReason( Cbs_Man_t * p, int Level )
+{
+    Cbs_Que_t * pQue = &(p->pClauses);
+    Gia_Obj_t * pObj, * pReason;
+    int i, k, iLitLevel;
+    assert( pQue->pData[pQue->iHead] == NULL );
+    assert( pQue->iHead + 1 < pQue->iTail );
+/*
+    for ( i = pQue->iHead + 1; i < pQue->iTail; i++ )
+    {
+        pObj = pQue->pData[i];
+        assert( pObj->fMark0 == 1 );
+    }
+*/
+    // compact literals
+    Vec_PtrClear( p->vTemp );
+    for ( i = k = pQue->iHead + 1; i < pQue->iTail; i++ )
+    {
+        pObj = pQue->pData[i];
+        if ( !pObj->fMark0 ) // unassigned - seen again
+            continue;
+        // assigned - seen first time
+        pObj->fMark0 = 0;
+        Vec_PtrPush( p->vTemp, pObj );
+        // check decision level
+        iLitLevel = Cbs_VarDecLevel( p, pObj );
+        if ( iLitLevel < Level )
+        {
+            pQue->pData[k++] = pObj;
+            continue;
+        }
+        assert( iLitLevel == Level );
+        pReason = Cbs_VarReason0( p, pObj );
+        if ( pReason == pObj ) // no reason
+        {
+            assert( pQue->pData[pQue->iHead] == NULL );
+            pQue->pData[pQue->iHead] = pObj;
+            continue;
+        }
+        Cbs_QuePush( pQue, pReason );
+        pReason = Cbs_VarReason1( p, pObj );
+        if ( pReason != pObj ) // second reason
+            Cbs_QuePush( pQue, pReason );
+    }
+    assert( pQue->pData[pQue->iHead] != NULL );
+    pQue->iTail = k;
+    // clear the marks
+    Vec_PtrForEachEntry( Gia_Obj_t *, p->vTemp, pObj, i )
+        pObj->fMark0 = 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns conflict clause.]
+
+  Description [Performs conflict analysis.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cbs_ManAnalyze( Cbs_Man_t * p, int Level, Gia_Obj_t * pVar, Gia_Obj_t * pFan0, Gia_Obj_t * pFan1 )
+{
+    Cbs_Que_t * pQue = &(p->pClauses);
+    assert( Cbs_VarIsAssigned(pVar) );
+    assert( Cbs_VarIsAssigned(pFan0) );
+    assert( pFan1 == NULL || Cbs_VarIsAssigned(pFan1) );
+    assert( Cbs_QueIsEmpty( pQue ) );
+    Cbs_QuePush( pQue, NULL );
+    Cbs_QuePush( pQue, pVar );
+    Cbs_QuePush( pQue, pFan0 );
+    if ( pFan1 )
+        Cbs_QuePush( pQue, pFan1 );
+    Cbs_ManDeriveReason( p, Level );
+    return Cbs_QueFinish( pQue );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs resolution of two clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cbs_ManResolve( Cbs_Man_t * p, int Level, int hClause0, int hClause1 )
+{
+    Cbs_Que_t * pQue = &(p->pClauses);
+    Gia_Obj_t * pObj;
+    int i, LevelMax = -1, LevelCur;
+    assert( pQue->pData[hClause0] != NULL );
+    assert( pQue->pData[hClause0] == pQue->pData[hClause1] );
+/*
+    for ( i = hClause0 + 1; (pObj = pQue->pData[i]); i++ )
+        assert( pObj->fMark0 == 1 );
+    for ( i = hClause1 + 1; (pObj = pQue->pData[i]); i++ )
+        assert( pObj->fMark0 == 1 );
+*/
+    assert( Cbs_QueIsEmpty( pQue ) );
+    Cbs_QuePush( pQue, NULL );
+    for ( i = hClause0 + 1; (pObj = pQue->pData[i]); i++ )
+    {
+        if ( !pObj->fMark0 ) // unassigned - seen again
+            continue;
+        // assigned - seen first time
+        pObj->fMark0 = 0;
+        Cbs_QuePush( pQue, pObj );
+        LevelCur = Cbs_VarDecLevel( p, pObj );
+        if ( LevelMax < LevelCur )
+            LevelMax = LevelCur;
+    }
+    for ( i = hClause1 + 1; (pObj = pQue->pData[i]); i++ )
+    {
+        if ( !pObj->fMark0 ) // unassigned - seen again
+            continue;
+        // assigned - seen first time
+        pObj->fMark0 = 0;
+        Cbs_QuePush( pQue, pObj );
+        LevelCur = Cbs_VarDecLevel( p, pObj );
+        if ( LevelMax < LevelCur )
+            LevelMax = LevelCur;
+    }
+    for ( i = pQue->iHead + 1; i < pQue->iTail; i++ )
+        pQue->pData[i]->fMark0 = 1;
+    Cbs_ManDeriveReason( p, LevelMax );
+    return Cbs_QueFinish( pQue );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagates a variable.]
+
+  Description [Returns clause handle if conflict; 0 if no conflict.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cbs_ManPropagateOne( Cbs_Man_t * p, Gia_Obj_t * pVar, int Level )
+{
+    int Value0, Value1;
+    assert( !Gia_IsComplement(pVar) );
+    assert( Cbs_VarIsAssigned(pVar) );
+    if ( Gia_ObjIsCi(pVar) )
+        return 0;
+    assert( Gia_ObjIsAnd(pVar) );
+    Value0 = Cbs_VarFanin0Value(pVar);
+    Value1 = Cbs_VarFanin1Value(pVar);
+    if ( Cbs_VarValue(pVar) )
+    { // value is 1
+        if ( Value0 == 0 || Value1 == 0 ) // one is 0
+        {
+            if ( Value0 == 0 && Value1 != 0 )
+                return Cbs_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), NULL );
+            if ( Value0 != 0 && Value1 == 0 )
+                return Cbs_ManAnalyze( p, Level, pVar, Gia_ObjFanin1(pVar), NULL );
+            assert( Value0 == 0 && Value1 == 0 );
+            return Cbs_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) );
+        }
+        if ( Value0 == 2 ) // first is unassigned
+            Cbs_ManAssign( p, Gia_ObjChild0(pVar), Level, pVar, NULL );
+        if ( Value1 == 2 ) // first is unassigned
+            Cbs_ManAssign( p, Gia_ObjChild1(pVar), Level, pVar, NULL );
+        return 0;
+    }
+    // value is 0
+    if ( Value0 == 0 || Value1 == 0 ) // one is 0
+        return 0;
+    if ( Value0 == 1 && Value1 == 1 ) // both are 1
+        return Cbs_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) );
+    if ( Value0 == 1 || Value1 == 1 ) // one is 1 
+    {
+        if ( Value0 == 2 ) // first is unassigned
+            Cbs_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)), Level, pVar, Gia_ObjFanin1(pVar) );
+        if ( Value1 == 2 ) // second is unassigned
+            Cbs_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)), Level, pVar, Gia_ObjFanin0(pVar) );
+        return 0;
+    }
+    assert( Cbs_VarIsJust(pVar) );
+    assert( !Cbs_QueHasNode( &p->pJust, pVar ) );
+    Cbs_QuePush( &p->pJust, pVar );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagates a variable.]
+
+  Description [Returns 1 if conflict; 0 if no conflict.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cbs_ManPropagateTwo( Cbs_Man_t * p, Gia_Obj_t * pVar, int Level )
+{
+    int Value0, Value1;
+    assert( !Gia_IsComplement(pVar) );
+    assert( Gia_ObjIsAnd(pVar) );
+    assert( Cbs_VarIsAssigned(pVar) );
+    assert( !Cbs_VarValue(pVar) );
+    Value0 = Cbs_VarFanin0Value(pVar);
+    Value1 = Cbs_VarFanin1Value(pVar);
+    // value is 0
+    if ( Value0 == 0 || Value1 == 0 ) // one is 0
+        return 0;
+    if ( Value0 == 1 && Value1 == 1 ) // both are 1
+        return Cbs_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) );
+    assert( Value0 == 1 || Value1 == 1 );
+    if ( Value0 == 2 ) // first is unassigned
+        Cbs_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)), Level, pVar, Gia_ObjFanin1(pVar) );
+    if ( Value1 == 2 ) // first is unassigned
+        Cbs_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)), Level, pVar, Gia_ObjFanin0(pVar) );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagates all variables.]
+
+  Description [Returns 1 if conflict; 0 if no conflict.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cbs_ManPropagate( Cbs_Man_t * p, int Level )
+{
+    int hClause;
+    Gia_Obj_t * pVar;
+    int i, k;
+    while ( 1 )
+    {
+        Cbs_QueForEachEntry( p->pProp, pVar, i )
+        {
+            if ( (hClause = Cbs_ManPropagateOne( p, pVar, Level )) )
+                return hClause;
+        }
+        p->pProp.iHead = p->pProp.iTail;
+        k = p->pJust.iHead;
+        Cbs_QueForEachEntry( p->pJust, pVar, i )
+        {
+            if ( Cbs_VarIsJust( pVar ) )
+                p->pJust.pData[k++] = pVar;
+            else if ( (hClause = Cbs_ManPropagateTwo( p, pVar, Level )) )
+                return hClause;
+        }
+        if ( k == p->pJust.iTail )
+            break;
+        p->pJust.iTail = k;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Solve the problem recursively.]
+
+  Description [Returns learnt clause if unsat, NULL if sat or undecided.]
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+int Cbs_ManSolve_rec( Cbs_Man_t * p, int Level )
+{ 
+    Cbs_Que_t * pQue = &(p->pClauses);
+    Gia_Obj_t * pVar, * pDecVar;
+    int hClause, hLearn0, hLearn1;
+    int iPropHead, iJustHead, iJustTail;
+    // propagate assignments
+    assert( !Cbs_QueIsEmpty(&p->pProp) );
+    if ( (hClause = Cbs_ManPropagate( p, Level )) )
+        return hClause;
+    // check for satisfying assignment
+    assert( Cbs_QueIsEmpty(&p->pProp) );
+    if ( Cbs_QueIsEmpty(&p->pJust) )
+        return 0;
+    // quit using resource limits
+    p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead );
+    if ( Cbs_ManCheckLimits( p ) )
+        return 0;
+    // remember the state before branching
+    iPropHead = p->pProp.iHead;
+    Cbs_QueStore( &p->pJust, &iJustHead, &iJustTail );
+    // find the decision variable
+    if ( p->Pars.fUseHighest )
+        pVar = Cbs_ManDecideHighest( p );
+    else if ( p->Pars.fUseLowest )
+        pVar = Cbs_ManDecideLowest( p );
+    else if ( p->Pars.fUseMaxFF )
+        pVar = Cbs_ManDecideMaxFF( p );
+    else assert( 0 );
+    assert( Cbs_VarIsJust( pVar ) );
+    // chose decision variable using fanout count
+    if ( Gia_ObjRefNum(p->pAig, Gia_ObjFanin0(pVar)) > Gia_ObjRefNum(p->pAig, Gia_ObjFanin1(pVar)) )
+        pDecVar = Gia_Not(Gia_ObjChild0(pVar));
+    else
+        pDecVar = Gia_Not(Gia_ObjChild1(pVar));
+//    pDecVar = Gia_NotCond( Gia_Regular(pDecVar), Gia_Regular(pDecVar)->fPhase );
+//    pDecVar = Gia_Not(pDecVar);
+    // decide on first fanin
+    Cbs_ManAssign( p, pDecVar, Level+1, NULL, NULL );
+    if ( !(hLearn0 = Cbs_ManSolve_rec( p, Level+1 )) )
+        return 0;
+    if ( pQue->pData[hLearn0] != Gia_Regular(pDecVar) )
+        return hLearn0;
+    Cbs_ManCancelUntil( p, iPropHead );
+    Cbs_QueRestore( &p->pJust, iJustHead, iJustTail );
+    // decide on second fanin
+    Cbs_ManAssign( p, Gia_Not(pDecVar), Level+1, NULL, NULL );
+    if ( !(hLearn1 = Cbs_ManSolve_rec( p, Level+1 )) )
+        return 0;
+    if ( pQue->pData[hLearn1] != Gia_Regular(pDecVar) )
+        return hLearn1;
+    hClause = Cbs_ManResolve( p, Level, hLearn0, hLearn1 );
+//    Cbs_ManPrintClauseNew( p, Level, hClause );
+//    if ( Level > Cbs_ClauseDecLevel(p, hClause) )
+//        p->Pars.nBTThisNc++;
+    p->Pars.nBTThis++;
+    return hClause;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Looking for a satisfying assignment of the node.]
+
+  Description [Assumes that each node has flag pObj->fMark0 set to 0.
+  Returns 1 if unsatisfiable, 0 if satisfiable, and -1 if undecided.
+  The node may be complemented. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cbs_ManSolve( Cbs_Man_t * p, Gia_Obj_t * pObj )
+{
+    int RetValue = 0;
+    s_Counter = 0;
+    assert( !p->pProp.iHead && !p->pProp.iTail );
+    assert( !p->pJust.iHead && !p->pJust.iTail );
+    assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 );
+    p->Pars.nBTThis = p->Pars.nJustThis = p->Pars.nBTThisNc = 0;
+    Cbs_ManAssign( p, pObj, 0, NULL, NULL );
+    if ( !Cbs_ManSolve_rec(p, 0) && !Cbs_ManCheckLimits(p) )
+        Cbs_ManSaveModel( p, p->vModel );
+    else
+        RetValue = 1;
+    Cbs_ManCancelUntil( p, 0 );
+    p->pJust.iHead = p->pJust.iTail = 0;
+    p->pClauses.iHead = p->pClauses.iTail = 1;
+    p->Pars.nBTTotal += p->Pars.nBTThis;
+    p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis );
+    if ( Cbs_ManCheckLimits( p ) )
+        RetValue = -1;
+
+//    printf( "%d ", s_Counter );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints statistics of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cbs_ManSatPrintStats( Cbs_Man_t * p )
+{
+    printf( "CO = %8d  ", Gia_ManCoNum(p->pAig) );
+    printf( "AND = %8d  ", Gia_ManAndNum(p->pAig) );
+    printf( "Conf = %6d  ", p->Pars.nBTLimit );
+    printf( "JustMax = %5d  ", p->Pars.nJustLimit );
+    printf( "\n" );
+    printf( "Unsat calls %6d  (%6.2f %%)   Ave conf = %8.1f   ", 
+        p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal :0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 );
+    ABC_PRTP( "Time", p->timeSatUnsat, p->timeTotal );
+    printf( "Sat   calls %6d  (%6.2f %%)   Ave conf = %8.1f   ", 
+        p->nSatSat,   p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal :0.0, p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 );
+    ABC_PRTP( "Time", p->timeSatSat,   p->timeTotal );
+    printf( "Undef calls %6d  (%6.2f %%)   Ave conf = %8.1f   ", 
+        p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal :0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 );
+    ABC_PRTP( "Time", p->timeSatUndec, p->timeTotal );
+    ABC_PRT( "Total time", p->timeTotal );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure to test the new SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose )
+{
+    extern void Gia_ManCollectTest( Gia_Man_t * pAig );
+    extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out );
+    Cbs_Man_t * p; 
+    Vec_Int_t * vCex, * vVisit, * vCexStore;
+    Vec_Str_t * vStatus;
+    Gia_Obj_t * pRoot; 
+    int i, status;
+    abctime clk, clkTotal = Abc_Clock();
+    assert( Gia_ManRegNum(pAig) == 0 );
+//    Gia_ManCollectTest( pAig );
+    // prepare AIG
+    Gia_ManCreateRefs( pAig );
+    Gia_ManCleanMark0( pAig );
+    Gia_ManCleanMark1( pAig );
+    Gia_ManFillValue( pAig ); // maps nodes into trail ids
+    Gia_ManSetPhase( pAig ); // maps nodes into trail ids
+    // create logic network
+    p = Cbs_ManAlloc();
+    p->Pars.nBTLimit = nConfs;
+    p->pAig   = pAig;
+    // create resulting data-structures
+    vStatus   = Vec_StrAlloc( Gia_ManPoNum(pAig) );
+    vCexStore = Vec_IntAlloc( 10000 );
+    vVisit    = Vec_IntAlloc( 100 );
+    vCex      = Cbs_ReadModel( p );
+    // solve for each output
+    Gia_ManForEachCo( pAig, pRoot, i )
+    {
+//        printf( "\n" );
+
+        Vec_IntClear( vCex );
+        if ( Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) )
+        {
+            if ( Gia_ObjFaninC0(pRoot) )
+            {
+//                printf( "Constant 1 output of SRM!!!\n" );
+                Cec_ManSatAddToStore( vCexStore, vCex, i ); // trivial counter-example
+                Vec_StrPush( vStatus, 0 );
+            }
+            else
+            {
+//                printf( "Constant 0 output of SRM!!!\n" );
+                Vec_StrPush( vStatus, 1 );
+            }
+            continue;
+        }
+        clk = Abc_Clock();
+        p->Pars.fUseHighest = 1;
+        p->Pars.fUseLowest  = 0;
+        status = Cbs_ManSolve( p, Gia_ObjChild0(pRoot) );
+//        printf( "\n" );
+/*
+        if ( status == -1 )
+        {
+            p->Pars.fUseHighest = 0;
+            p->Pars.fUseLowest  = 1;
+            status = Cbs_ManSolve( p, Gia_ObjChild0(pRoot) );
+        }
+*/
+        Vec_StrPush( vStatus, (char)status );
+        if ( status == -1 )
+        {
+            p->nSatUndec++;
+            p->nConfUndec += p->Pars.nBTThis;
+            Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout
+            p->timeSatUndec += Abc_Clock() - clk;
+            continue;
+        }
+        if ( status == 1 )
+        {
+            p->nSatUnsat++;
+            p->nConfUnsat += p->Pars.nBTThis;
+            p->timeSatUnsat += Abc_Clock() - clk;
+            continue;
+        }
+        p->nSatSat++;
+        p->nConfSat += p->Pars.nBTThis;
+//        Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit );
+        Cec_ManSatAddToStore( vCexStore, vCex, i );
+        p->timeSatSat += Abc_Clock() - clk;
+    }
+    Vec_IntFree( vVisit );
+    p->nSatTotal = Gia_ManPoNum(pAig);
+    p->timeTotal = Abc_Clock() - clkTotal;
+    if ( fVerbose )
+        Cbs_ManSatPrintStats( p );
+//    printf( "RecCalls = %8d.  RecClause = %8d.  RecNonChro = %8d.\n", p->nRecCall, p->nRecClause, p->nRecNonChro );
+    Cbs_ManStop( p );
+    *pvStatus = vStatus;
+
+//    printf( "Total number of cex literals = %d. (Ave = %d)\n", 
+//         Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat, 
+//        (Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat)/p->nSatSat );
+    return vCexStore;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaCSatOld.c b/abc-build/src/aig/gia/giaCSatOld.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaCSatOld.c
@@ -0,0 +1,804 @@
+/**CFile****************************************************************
+
+  FileName    [giaCSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [A simple circuit-based solver.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaCSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Cbs0_Par_t_ Cbs0_Par_t;
+struct Cbs0_Par_t_
+{
+    // conflict limits
+    int           nBTLimit;     // limit on the number of conflicts
+    int           nJustLimit;   // limit on the size of justification queue
+    // current parameters
+    int           nBTThis;      // number of conflicts
+    int           nJustThis;    // max size of the frontier
+    int           nBTTotal;     // total number of conflicts
+    int           nJustTotal;   // total size of the frontier
+    // decision heuristics
+    int           fUseHighest;  // use node with the highest ID
+    int           fUseLowest;   // use node with the highest ID
+    int           fUseMaxFF;    // use node with the largest fanin fanout
+    // other
+    int           fVerbose;
+};
+
+typedef struct Cbs0_Que_t_ Cbs0_Que_t;
+struct Cbs0_Que_t_
+{
+    int           iHead;        // beginning of the queue
+    int           iTail;        // end of the queue
+    int           nSize;        // allocated size
+    Gia_Obj_t **  pData;        // nodes stored in the queue
+};
+ 
+typedef struct Cbs0_Man_t_ Cbs0_Man_t;
+struct Cbs0_Man_t_
+{
+    Cbs0_Par_t    Pars;         // parameters
+    Gia_Man_t *   pAig;         // AIG manager
+    Cbs0_Que_t    pProp;        // propagation queue
+    Cbs0_Que_t    pJust;        // justification queue
+    Vec_Int_t *   vModel;       // satisfying assignment
+    // SAT calls statistics
+    int           nSatUnsat;    // the number of proofs
+    int           nSatSat;      // the number of failure
+    int           nSatUndec;    // the number of timeouts
+    int           nSatTotal;    // the number of calls
+    // conflicts
+    int           nConfUnsat;   // conflicts in unsat problems
+    int           nConfSat;     // conflicts in sat problems
+    int           nConfUndec;   // conflicts in undec problems
+    // runtime stats
+    abctime       timeSatUnsat; // unsat
+    abctime       timeSatSat;   // sat
+    abctime       timeSatUndec; // undecided
+    abctime       timeTotal;    // total runtime
+};
+
+static inline int   Cbs0_VarIsAssigned( Gia_Obj_t * pVar )      { return pVar->fMark0;                        }
+static inline void  Cbs0_VarAssign( Gia_Obj_t * pVar )          { assert(!pVar->fMark0); pVar->fMark0 = 1;    }
+static inline void  Cbs0_VarUnassign( Gia_Obj_t * pVar )        { assert(pVar->fMark0);  pVar->fMark0 = 0; pVar->fMark1 = 0;         }
+static inline int   Cbs0_VarValue( Gia_Obj_t * pVar )           { assert(pVar->fMark0);  return pVar->fMark1; }
+static inline void  Cbs0_VarSetValue( Gia_Obj_t * pVar, int v ) { assert(pVar->fMark0);  pVar->fMark1 = v;    }
+static inline int   Cbs0_VarIsJust( Gia_Obj_t * pVar )          { return Gia_ObjIsAnd(pVar) && !Cbs0_VarIsAssigned(Gia_ObjFanin0(pVar)) && !Cbs0_VarIsAssigned(Gia_ObjFanin1(pVar)); } 
+static inline int   Cbs0_VarFanin0Value( Gia_Obj_t * pVar )     { return !Cbs0_VarIsAssigned(Gia_ObjFanin0(pVar)) ? 2 : (Cbs0_VarValue(Gia_ObjFanin0(pVar)) ^ Gia_ObjFaninC0(pVar)); }
+static inline int   Cbs0_VarFanin1Value( Gia_Obj_t * pVar )     { return !Cbs0_VarIsAssigned(Gia_ObjFanin1(pVar)) ? 2 : (Cbs0_VarValue(Gia_ObjFanin1(pVar)) ^ Gia_ObjFaninC1(pVar)); }
+
+#define Cbs0_QueForEachEntry( Que, pObj, i )                    \
+    for ( i = (Que).iHead; (i < (Que).iTail) && ((pObj) = (Que).pData[i]); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Sets default values of the parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cbs0_SetDefaultParams( Cbs0_Par_t * pPars )
+{
+    memset( pPars, 0, sizeof(Cbs0_Par_t) );
+    pPars->nBTLimit    =  1000;   // limit on the number of conflicts
+    pPars->nJustLimit  =   100;   // limit on the size of justification queue
+    pPars->fUseHighest =     1;   // use node with the highest ID
+    pPars->fUseLowest  =     0;   // use node with the highest ID
+    pPars->fUseMaxFF   =     0;   // use node with the largest fanin fanout
+    pPars->fVerbose    =     1;   // print detailed statistics
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cbs0_Man_t * Cbs0_ManAlloc()
+{
+    Cbs0_Man_t * p;
+    p = ABC_CALLOC( Cbs0_Man_t, 1 );
+    p->pProp.nSize = p->pJust.nSize = 10000;
+    p->pProp.pData = ABC_ALLOC( Gia_Obj_t *, p->pProp.nSize );
+    p->pJust.pData = ABC_ALLOC( Gia_Obj_t *, p->pJust.nSize );
+    p->vModel = Vec_IntAlloc( 1000 );
+    Cbs0_SetDefaultParams( &p->Pars );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cbs0_ManStop( Cbs0_Man_t * p )
+{
+    Vec_IntFree( p->vModel );
+    ABC_FREE( p->pProp.pData );
+    ABC_FREE( p->pJust.pData );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns satisfying assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Cbs0_ReadModel( Cbs0_Man_t * p )
+{
+    return p->vModel;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the solver is out of limits.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cbs0_ManCheckLimits( Cbs0_Man_t * p )
+{
+    return p->Pars.nJustThis > p->Pars.nJustLimit || p->Pars.nBTThis > p->Pars.nBTLimit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Saves the satisfying assignment as an array of literals.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cbs0_ManSaveModel( Cbs0_Man_t * p, Vec_Int_t * vCex )
+{
+    Gia_Obj_t * pVar;
+    int i;
+    Vec_IntClear( vCex );
+    p->pProp.iHead = 0;
+    Cbs0_QueForEachEntry( p->pProp, pVar, i )
+        if ( Gia_ObjIsCi(pVar) )
+//            Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !Cbs0_VarValue(pVar)) );
+            Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjCioId(pVar), !Cbs0_VarValue(pVar)) );
+} 
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cbs0_QueIsEmpty( Cbs0_Que_t * p )
+{
+    return p->iHead == p->iTail;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cbs0_QuePush( Cbs0_Que_t * p, Gia_Obj_t * pObj )
+{
+    if ( p->iTail == p->nSize )
+    {
+        p->nSize *= 2;
+        p->pData = ABC_REALLOC( Gia_Obj_t *, p->pData, p->nSize ); 
+    }
+    p->pData[p->iTail++] = pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the object in the queue.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cbs0_QueHasNode( Cbs0_Que_t * p, Gia_Obj_t * pObj )
+{
+    Gia_Obj_t * pTemp;
+    int i;
+    Cbs0_QueForEachEntry( *p, pTemp, i )
+        if ( pTemp == pObj )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cbs0_QueStore( Cbs0_Que_t * p, int * piHeadOld, int * piTailOld )
+{
+    int i;
+    *piHeadOld = p->iHead;
+    *piTailOld = p->iTail;
+    for ( i = *piHeadOld; i < *piTailOld; i++ )
+        Cbs0_QuePush( p, p->pData[i] );
+    p->iHead = *piTailOld;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cbs0_QueRestore( Cbs0_Que_t * p, int iHeadOld, int iTailOld )
+{
+    p->iHead = iHeadOld;
+    p->iTail = iTailOld;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Max number of fanins fanouts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cbs0_VarFaninFanoutMax( Cbs0_Man_t * p, Gia_Obj_t * pObj )
+{
+    int Count0, Count1;
+    assert( !Gia_IsComplement(pObj) );
+    assert( Gia_ObjIsAnd(pObj) );
+    Count0 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin0(pObj) );
+    Count1 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin1(pObj) );
+    return Abc_MaxInt( Count0, Count1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find variable with the highest ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Cbs0_ManDecideHighest( Cbs0_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pObjMax = NULL;
+    int i;
+    Cbs0_QueForEachEntry( p->pJust, pObj, i )
+        if ( pObjMax == NULL || pObjMax < pObj )
+            pObjMax = pObj;
+    return pObjMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find variable with the lowest ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Cbs0_ManDecideLowest( Cbs0_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pObjMin = NULL;
+    int i;
+    Cbs0_QueForEachEntry( p->pJust, pObj, i )
+        if ( pObjMin == NULL || pObjMin > pObj )
+            pObjMin = pObj;
+    return pObjMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find variable with the maximum number of fanin fanouts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Cbs0_ManDecideMaxFF( Cbs0_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pObjMax = NULL;
+    int i, iMaxFF = 0, iCurFF;
+    assert( p->pAig->pRefs != NULL );
+    Cbs0_QueForEachEntry( p->pJust, pObj, i )
+    {
+        iCurFF = Cbs0_VarFaninFanoutMax( p, pObj );
+        assert( iCurFF > 0 );
+        if ( iMaxFF < iCurFF )
+        {
+            iMaxFF = iCurFF;
+            pObjMax = pObj;
+        }
+    }
+    return pObjMax;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cbs0_ManCancelUntil( Cbs0_Man_t * p, int iBound )
+{
+    Gia_Obj_t * pVar;
+    int i;
+    assert( iBound <= p->pProp.iTail );
+    p->pProp.iHead = iBound;
+    Cbs0_QueForEachEntry( p->pProp, pVar, i )
+        Cbs0_VarUnassign( pVar );
+    p->pProp.iTail = iBound;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns the variables a value.]
+
+  Description [Returns 1 if conflict; 0 if no conflict.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cbs0_ManAssign( Cbs0_Man_t * p, Gia_Obj_t * pObj )
+{
+    Gia_Obj_t * pObjR = Gia_Regular(pObj);
+    assert( Gia_ObjIsCand(pObjR) );
+    assert( !Cbs0_VarIsAssigned(pObjR) );
+    Cbs0_VarAssign( pObjR );
+    Cbs0_VarSetValue( pObjR, !Gia_IsComplement(pObj) );
+    Cbs0_QuePush( &p->pProp, pObjR );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagates a variable.]
+
+  Description [Returns 1 if conflict; 0 if no conflict.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cbs0_ManPropagateOne( Cbs0_Man_t * p, Gia_Obj_t * pVar )
+{
+    int Value0, Value1;
+    assert( !Gia_IsComplement(pVar) );
+    assert( Cbs0_VarIsAssigned(pVar) );
+    if ( Gia_ObjIsCi(pVar) )
+        return 0;
+    assert( Gia_ObjIsAnd(pVar) );
+    Value0 = Cbs0_VarFanin0Value(pVar);
+    Value1 = Cbs0_VarFanin1Value(pVar);
+    if ( Cbs0_VarValue(pVar) )
+    { // value is 1
+        if ( Value0 == 0 || Value1 == 0 ) // one is 0
+            return 1;
+        if ( Value0 == 2 ) // first is unassigned
+            Cbs0_ManAssign( p, Gia_ObjChild0(pVar) );
+        if ( Value1 == 2 ) // first is unassigned
+            Cbs0_ManAssign( p, Gia_ObjChild1(pVar) );
+        return 0;
+    }
+    // value is 0
+    if ( Value0 == 0 || Value1 == 0 ) // one is 0
+        return 0;
+    if ( Value0 == 1 && Value1 == 1 ) // both are 1
+        return 1;
+    if ( Value0 == 1 || Value1 == 1 ) // one is 1 
+    {
+        if ( Value0 == 2 ) // first is unassigned
+            Cbs0_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)) );
+        if ( Value1 == 2 ) // first is unassigned
+            Cbs0_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)) );
+        return 0;
+    }
+    assert( Cbs0_VarIsJust(pVar) );
+    assert( !Cbs0_QueHasNode( &p->pJust, pVar ) );
+    Cbs0_QuePush( &p->pJust, pVar );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagates a variable.]
+
+  Description [Returns 1 if conflict; 0 if no conflict.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cbs0_ManPropagateTwo( Cbs0_Man_t * p, Gia_Obj_t * pVar )
+{
+    int Value0, Value1;
+    assert( !Gia_IsComplement(pVar) );
+    assert( Gia_ObjIsAnd(pVar) );
+    assert( Cbs0_VarIsAssigned(pVar) );
+    assert( !Cbs0_VarValue(pVar) );
+    Value0 = Cbs0_VarFanin0Value(pVar);
+    Value1 = Cbs0_VarFanin1Value(pVar);
+    // value is 0
+    if ( Value0 == 0 || Value1 == 0 ) // one is 0
+        return 0;
+    if ( Value0 == 1 && Value1 == 1 ) // both are 1
+        return 1;
+    assert( Value0 == 1 || Value1 == 1 );
+    if ( Value0 == 2 ) // first is unassigned
+        Cbs0_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)) );
+    if ( Value1 == 2 ) // first is unassigned
+        Cbs0_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)) );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagates all variables.]
+
+  Description [Returns 1 if conflict; 0 if no conflict.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cbs0_ManPropagate( Cbs0_Man_t * p )
+{
+    Gia_Obj_t * pVar;
+    int i, k;
+    while ( 1 )
+    {
+        Cbs0_QueForEachEntry( p->pProp, pVar, i )
+        {
+            if ( Cbs0_ManPropagateOne( p, pVar ) )
+                return 1;
+        }
+        p->pProp.iHead = p->pProp.iTail;
+        k = p->pJust.iHead;
+        Cbs0_QueForEachEntry( p->pJust, pVar, i )
+        {
+            if ( Cbs0_VarIsJust( pVar ) )
+                p->pJust.pData[k++] = pVar;
+            else if ( Cbs0_ManPropagateTwo( p, pVar ) )
+                return 1;
+        }
+        if ( k == p->pJust.iTail )
+            break;
+        p->pJust.iTail = k;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Solve the problem recursively.]
+
+  Description [Returns 1 if unsat or undecided; 0 if satisfiable.]
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+int Cbs0_ManSolve_rec( Cbs0_Man_t * p )
+{
+    Gia_Obj_t * pVar, * pDecVar;
+    int iPropHead, iJustHead, iJustTail;
+    // propagate assignments
+    assert( !Cbs0_QueIsEmpty(&p->pProp) );
+    if ( Cbs0_ManPropagate( p ) )
+        return 1;
+    // check for satisfying assignment
+    assert( Cbs0_QueIsEmpty(&p->pProp) );
+    if ( Cbs0_QueIsEmpty(&p->pJust) )
+        return 0;
+    // quit using resource limits
+    p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead );
+    if ( Cbs0_ManCheckLimits( p ) )
+        return 0;
+    // remember the state before branching
+    iPropHead = p->pProp.iHead;
+    Cbs0_QueStore( &p->pJust, &iJustHead, &iJustTail );
+    // find the decision variable
+    if ( p->Pars.fUseHighest )
+        pVar = Cbs0_ManDecideHighest( p );
+    else if ( p->Pars.fUseLowest )
+        pVar = Cbs0_ManDecideLowest( p );
+    else if ( p->Pars.fUseMaxFF )
+        pVar = Cbs0_ManDecideMaxFF( p );
+    else assert( 0 );
+    assert( Cbs0_VarIsJust( pVar ) );
+    // chose decision variable using fanout count
+    if ( Gia_ObjRefNum(p->pAig, Gia_ObjFanin0(pVar)) > Gia_ObjRefNum(p->pAig, Gia_ObjFanin1(pVar)) )
+        pDecVar = Gia_Not(Gia_ObjChild0(pVar));
+    else
+        pDecVar = Gia_Not(Gia_ObjChild1(pVar));
+    // decide on first fanin
+    Cbs0_ManAssign( p, pDecVar );
+    if ( !Cbs0_ManSolve_rec( p ) )
+        return 0;
+    Cbs0_ManCancelUntil( p, iPropHead );
+    Cbs0_QueRestore( &p->pJust, iJustHead, iJustTail );
+    // decide on second fanin
+    Cbs0_ManAssign( p, Gia_Not(pDecVar) );
+    if ( !Cbs0_ManSolve_rec( p ) )
+        return 0;
+    p->Pars.nBTThis++;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Looking for a satisfying assignment of the node.]
+
+  Description [Assumes that each node has flag pObj->fMark0 set to 0.
+  Returns 1 if unsatisfiable, 0 if satisfiable, and -1 if undecided.
+  The node may be complemented. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cbs0_ManSolve( Cbs0_Man_t * p, Gia_Obj_t * pObj )
+{
+    int RetValue;
+    assert( !p->pProp.iHead && !p->pProp.iTail );
+    assert( !p->pJust.iHead && !p->pJust.iTail );
+    p->Pars.nBTThis = p->Pars.nJustThis = 0;
+    Cbs0_ManAssign( p, pObj );
+    RetValue = Cbs0_ManSolve_rec( p );
+    if ( RetValue == 0 && !Cbs0_ManCheckLimits(p) )
+        Cbs0_ManSaveModel( p, p->vModel );
+    Cbs0_ManCancelUntil( p, 0 );
+    p->pJust.iHead = p->pJust.iTail = 0;
+    p->Pars.nBTTotal += p->Pars.nBTThis;
+    p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis );
+    if ( Cbs0_ManCheckLimits( p ) )
+        RetValue = -1;
+//    printf( "Outcome = %2d.  Confs = %6d.  Decision level max = %3d.\n", 
+//        RetValue, p->Pars.nBTThis, p->DecLevelMax );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints statistics of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cbs0_ManSatPrintStats( Cbs0_Man_t * p )
+{
+    printf( "CO = %8d  ", Gia_ManCoNum(p->pAig) );
+    printf( "AND = %8d  ", Gia_ManAndNum(p->pAig) );
+    printf( "Conf = %6d  ", p->Pars.nBTLimit );
+    printf( "JustMax = %5d  ", p->Pars.nJustLimit );
+    printf( "\n" );
+    printf( "Unsat calls %6d  (%6.2f %%)   Ave conf = %8.1f   ", 
+        p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal :0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 );
+    ABC_PRTP( "Time", p->timeSatUnsat, p->timeTotal );
+    printf( "Sat   calls %6d  (%6.2f %%)   Ave conf = %8.1f   ", 
+        p->nSatSat,   p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal :0.0, p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 );
+    ABC_PRTP( "Time", p->timeSatSat,   p->timeTotal );
+    printf( "Undef calls %6d  (%6.2f %%)   Ave conf = %8.1f   ", 
+        p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal :0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 );
+    ABC_PRTP( "Time", p->timeSatUndec, p->timeTotal );
+    ABC_PRT( "Total time", p->timeTotal );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure to test the new SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Cbs_ManSolveMiter( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose )
+{
+    extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out );
+    Cbs0_Man_t * p; 
+    Vec_Int_t * vCex, * vVisit, * vCexStore;
+    Vec_Str_t * vStatus;
+    Gia_Obj_t * pRoot; 
+    int i, status;
+    abctime clk, clkTotal = Abc_Clock();
+    assert( Gia_ManRegNum(pAig) == 0 );
+    // prepare AIG
+    Gia_ManCreateRefs( pAig );
+    Gia_ManCleanMark0( pAig );
+    Gia_ManCleanMark1( pAig );
+    // create logic network
+    p = Cbs0_ManAlloc();
+    p->Pars.nBTLimit = nConfs;
+    p->pAig   = pAig;
+    // create resulting data-structures
+    vStatus   = Vec_StrAlloc( Gia_ManPoNum(pAig) );
+    vCexStore = Vec_IntAlloc( 10000 );
+    vVisit    = Vec_IntAlloc( 100 );
+    vCex      = Cbs0_ReadModel( p );
+    // solve for each output
+    Gia_ManForEachCo( pAig, pRoot, i )
+    {
+        Vec_IntClear( vCex );
+        if ( Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) )
+        {
+            if ( Gia_ObjFaninC0(pRoot) )
+            {
+                printf( "Constant 1 output of SRM!!!\n" );
+                Cec_ManSatAddToStore( vCexStore, vCex, i ); // trivial counter-example
+                Vec_StrPush( vStatus, 0 );
+            }
+            else
+            {
+//                printf( "Constant 0 output of SRM!!!\n" );
+                Vec_StrPush( vStatus, 1 );
+            }
+            continue;
+        }
+        clk = Abc_Clock();
+        p->Pars.fUseHighest = 1;
+        p->Pars.fUseLowest  = 0;
+        status = Cbs0_ManSolve( p, Gia_ObjChild0(pRoot) );
+/*
+        if ( status == -1 )
+        {
+            p->Pars.fUseHighest = 0;
+            p->Pars.fUseLowest  = 1;
+            status = Cbs0_ManSolve( p, Gia_ObjChild0(pRoot) );
+        }
+*/
+        Vec_StrPush( vStatus, (char)status );
+        if ( status == -1 )
+        {
+            p->nSatUndec++;
+            p->nConfUndec += p->Pars.nBTThis;
+            Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout
+            p->timeSatUndec += Abc_Clock() - clk;
+            continue;
+        }
+        if ( status == 1 )
+        {
+            p->nSatUnsat++;
+            p->nConfUnsat += p->Pars.nBTThis;
+            p->timeSatUnsat += Abc_Clock() - clk;
+            continue;
+        }
+        p->nSatSat++;
+        p->nConfSat += p->Pars.nBTThis;
+//        Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit );
+        Cec_ManSatAddToStore( vCexStore, vCex, i );
+        p->timeSatSat += Abc_Clock() - clk;
+    }
+    Vec_IntFree( vVisit );
+    p->nSatTotal = Gia_ManPoNum(pAig);
+    p->timeTotal = Abc_Clock() - clkTotal;
+    if ( fVerbose )
+        Cbs0_ManSatPrintStats( p );
+    Cbs0_ManStop( p );
+    *pvStatus = vStatus;
+//    printf( "Total number of cex literals = %d. (Ave = %d)\n", 
+//         Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat, 
+//        (Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat)/p->nSatSat );
+    return vCexStore;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaCTas.c b/abc-build/src/aig/gia/giaCTas.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaCTas.c
@@ -0,0 +1,1790 @@
+/**CFile****************************************************************
+
+  FileName    [giaCSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [A simple circuit-based solver.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaCSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+//#define gia_assert(exp)     ((void)0)
+//#define gia_assert(exp)     (assert(exp))
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Tas_Par_t_ Tas_Par_t;
+struct Tas_Par_t_
+{
+    // conflict limits
+    int           nBTLimit;     // limit on the number of conflicts
+    int           nJustLimit;   // limit on the size of justification queue
+    // current parameters
+    int           nBTThis;      // number of conflicts
+    int           nBTThisNc;    // number of conflicts
+    int           nJustThis;    // max size of the frontier
+    int           nBTTotal;     // total number of conflicts
+    int           nJustTotal;   // total size of the frontier
+    // activity
+    float         VarDecay;     // variable activity decay
+    int           VarInc;       // variable increment
+    // decision heuristics
+    int           fUseActive;   // use most active
+    int           fUseHighest;  // use node with the highest ID
+    int           fUseLowest;   // use node with the highest ID
+    int           fUseMaxFF;    // use node with the largest fanin fanout
+    // other
+    int           fVerbose;
+};
+
+typedef struct Tas_Cls_t_ Tas_Cls_t;
+struct Tas_Cls_t_
+{
+    int           iNext[2];     // beginning of the queue
+    int           nLits;        // the number of literals
+    int           pLits[0];     // clause literals
+};
+
+typedef struct Tas_Sto_t_ Tas_Sto_t;
+struct Tas_Sto_t_
+{
+    int           iCur;         // current position
+    int           nSize;        // allocated size
+    int *         pData;        // clause information
+};
+
+typedef struct Tas_Que_t_ Tas_Que_t;
+struct Tas_Que_t_
+{
+    int           iHead;        // beginning of the queue
+    int           iTail;        // end of the queue
+    int           nSize;        // allocated size
+    Gia_Obj_t **  pData;        // nodes stored in the queue
+};
+ 
+struct Tas_Man_t_
+{
+    Tas_Par_t     Pars;         // parameters
+    Gia_Man_t *   pAig;         // AIG manager
+    Tas_Que_t     pProp;        // propagation queue
+    Tas_Que_t     pJust;        // justification queue
+    Tas_Que_t     pClauses;     // clause queue
+    Gia_Obj_t **  pIter;        // iterator through clause vars
+    Vec_Int_t *   vLevReas;     // levels and decisions
+    Vec_Int_t *   vModel;       // satisfying assignment
+    Vec_Ptr_t *   vTemp;        // temporary storage
+    // watched clauses
+    Tas_Sto_t     pStore;       // storage for watched clauses
+    int *         pWatches;     // watched lists for each literal
+    Vec_Int_t *   vWatchLits;   // lits whose watched are assigned
+    int           nClauses;     // the counter of clauses
+    // activity
+    float *       pActivity;    // variable activity
+    Vec_Int_t *   vActiveVars;  // variables with activity
+    // SAT calls statistics
+    int           nSatUnsat;    // the number of proofs
+    int           nSatSat;      // the number of failure
+    int           nSatUndec;    // the number of timeouts
+    int           nSatTotal;    // the number of calls
+    // conflicts
+    int           nConfUnsat;   // conflicts in unsat problems
+    int           nConfSat;     // conflicts in sat problems
+    int           nConfUndec;   // conflicts in undec problems
+    // runtime stats
+    abctime       timeSatUnsat; // unsat
+    abctime       timeSatSat;   // sat
+    abctime       timeSatUndec; // undecided
+    abctime       timeTotal;    // total runtime
+};
+
+static inline int   Tas_VarIsAssigned( Gia_Obj_t * pVar )      { return pVar->fMark0;                        }
+static inline void  Tas_VarAssign( Gia_Obj_t * pVar )          { assert(!pVar->fMark0); pVar->fMark0 = 1;    }
+static inline void  Tas_VarUnassign( Gia_Obj_t * pVar )        { assert(pVar->fMark0);  pVar->fMark0 = 0; pVar->fMark1 = 0; pVar->Value = ~0; }
+static inline int   Tas_VarValue( Gia_Obj_t * pVar )           { assert(pVar->fMark0);  return pVar->fMark1; }
+static inline void  Tas_VarSetValue( Gia_Obj_t * pVar, int v ) { assert(pVar->fMark0);  pVar->fMark1 = v;    }
+static inline int   Tas_VarIsJust( Gia_Obj_t * pVar )          { return Gia_ObjIsAnd(pVar) && !Tas_VarIsAssigned(Gia_ObjFanin0(pVar)) && !Tas_VarIsAssigned(Gia_ObjFanin1(pVar)); } 
+static inline int   Tas_VarFanin0Value( Gia_Obj_t * pVar )     { return !Tas_VarIsAssigned(Gia_ObjFanin0(pVar)) ? 2 : (Tas_VarValue(Gia_ObjFanin0(pVar)) ^ Gia_ObjFaninC0(pVar)); }
+static inline int   Tas_VarFanin1Value( Gia_Obj_t * pVar )     { return !Tas_VarIsAssigned(Gia_ObjFanin1(pVar)) ? 2 : (Tas_VarValue(Gia_ObjFanin1(pVar)) ^ Gia_ObjFaninC1(pVar)); }
+static inline int   Tas_VarToLit( Tas_Man_t * p, Gia_Obj_t * pObj ) { assert( Tas_VarIsAssigned(pObj) ); return Abc_Var2Lit( Gia_ObjId(p->pAig, pObj), !Tas_VarValue(pObj) );     }
+static inline int   Tas_LitIsTrue( Gia_Obj_t * pObj, int Lit ) { assert( Tas_VarIsAssigned(pObj) ); return Tas_VarValue(pObj) != Abc_LitIsCompl(Lit);                             }
+
+static inline int         Tas_ClsHandle( Tas_Man_t * p, Tas_Cls_t * pClause ) { return ((int *)pClause) - p->pStore.pData;   }
+static inline Tas_Cls_t * Tas_ClsFromHandle( Tas_Man_t * p, int h )           { return (Tas_Cls_t *)(p->pStore.pData + h);   }
+
+static inline int         Tas_VarDecLevel( Tas_Man_t * p, Gia_Obj_t * pVar )  { assert( pVar->Value != ~0 ); return Vec_IntEntry(p->vLevReas, 3*pVar->Value);          }
+static inline Gia_Obj_t * Tas_VarReason0( Tas_Man_t * p, Gia_Obj_t * pVar )   { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+1); }
+static inline Gia_Obj_t * Tas_VarReason1( Tas_Man_t * p, Gia_Obj_t * pVar )   { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+2); }
+static inline int         Tas_ClauseDecLevel( Tas_Man_t * p, int hClause )    { return Tas_VarDecLevel( p, p->pClauses.pData[hClause] );                               }
+
+static inline int         Tas_VarHasReasonCls( Tas_Man_t * p, Gia_Obj_t * pVar ) { assert( pVar->Value != ~0 ); return Vec_IntEntry(p->vLevReas, 3*pVar->Value+1) == 0 && Vec_IntEntry(p->vLevReas, 3*pVar->Value+2) != 0; }
+static inline Tas_Cls_t * Tas_VarReasonCls( Tas_Man_t * p, Gia_Obj_t * pVar )    { assert( pVar->Value != ~0 ); return Tas_ClsFromHandle( p, Vec_IntEntry(p->vLevReas, 3*pVar->Value+2) );                                 }
+
+#define Tas_QueForEachEntry( Que, pObj, i )                         \
+    for ( i = (Que).iHead; (i < (Que).iTail) && ((pObj) = (Que).pData[i]); i++ )
+
+#define Tas_ClauseForEachVar( p, hClause, pObj )                    \
+    for ( (p)->pIter = (p)->pClauses.pData + hClause; (pObj = *pIter); (p)->pIter++ )
+#define Tas_ClauseForEachVar1( p, hClause, pObj )                   \
+    for ( (p)->pIter = (p)->pClauses.pData+hClause+1; (pObj = *pIter); (p)->pIter++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Sets default values of the parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tas_SetDefaultParams( Tas_Par_t * pPars )
+{
+    memset( pPars, 0, sizeof(Tas_Par_t) );
+    pPars->nBTLimit    =        2000;   // limit on the number of conflicts
+    pPars->nJustLimit  =        2000;   // limit on the size of justification queue
+    pPars->fUseActive  =           0;   // use node with the highest activity
+    pPars->fUseHighest =           1;   // use node with the highest ID
+    pPars->fUseLowest  =           0;   // use node with the lowest ID
+    pPars->fUseMaxFF   =           0;   // use node with the largest fanin fanout
+    pPars->fVerbose    =           1;   // print detailed statistics
+    pPars->VarDecay    = (float)0.95;   // variable decay
+    pPars->VarInc      =         1.0;   // variable increment
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Tas_Man_t * Tas_ManAlloc( Gia_Man_t * pAig, int nBTLimit )
+{
+    Tas_Man_t * p;
+    p = ABC_CALLOC( Tas_Man_t, 1 );
+    Tas_SetDefaultParams( &p->Pars );
+    p->pAig           = pAig;
+    p->Pars.nBTLimit  = nBTLimit;
+    p->pProp.nSize    = p->pJust.nSize = p->pClauses.nSize = 10000;
+    p->pProp.pData    = ABC_ALLOC( Gia_Obj_t *, p->pProp.nSize );
+    p->pJust.pData    = ABC_ALLOC( Gia_Obj_t *, p->pJust.nSize );
+    p->pClauses.pData = ABC_ALLOC( Gia_Obj_t *, p->pClauses.nSize );
+    p->pClauses.iHead = p->pClauses.iTail = 1;
+    p->vModel         = Vec_IntAlloc( 1000 );
+    p->vLevReas       = Vec_IntAlloc( 1000 );
+    p->vTemp          = Vec_PtrAlloc( 1000 );
+    p->pStore.iCur    = 16;
+    p->pStore.nSize   = 10000;
+    p->pStore.pData   = ABC_ALLOC( int, p->pStore.nSize );
+    p->pWatches       = ABC_CALLOC( int, 2 * Gia_ManObjNum(pAig) );
+    p->vWatchLits     = Vec_IntAlloc( 100 );
+    p->pActivity      = ABC_CALLOC( float, Gia_ManObjNum(pAig) );
+    p->vActiveVars    = Vec_IntAlloc( 100 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tas_ManStop( Tas_Man_t * p )
+{
+    Vec_IntFree( p->vActiveVars );
+    Vec_IntFree( p->vWatchLits );
+    Vec_IntFree( p->vLevReas );
+    Vec_IntFree( p->vModel );
+    Vec_PtrFree( p->vTemp );
+    ABC_FREE( p->pActivity );
+    ABC_FREE( p->pWatches );
+    ABC_FREE( p->pStore.pData );
+    ABC_FREE( p->pClauses.pData );
+    ABC_FREE( p->pProp.pData );
+    ABC_FREE( p->pJust.pData );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns satisfying assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Tas_ReadModel( Tas_Man_t * p )
+{
+    return p->vModel;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the solver is out of limits.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Tas_ManCheckLimits( Tas_Man_t * p )
+{
+    return p->Pars.nJustThis > p->Pars.nJustLimit || p->Pars.nBTThis > p->Pars.nBTLimit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Saves the satisfying assignment as an array of literals.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Tas_ManSaveModel( Tas_Man_t * p, Vec_Int_t * vCex )
+{
+    Gia_Obj_t * pVar;
+    int i;
+    Vec_IntClear( vCex );
+    p->pProp.iHead = 0;
+//    printf( "\n" );
+    Tas_QueForEachEntry( p->pProp, pVar, i )
+    {
+        if ( Gia_ObjIsCi(pVar) )
+//            Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !Tas_VarValue(pVar)) );
+            Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjCioId(pVar), !Tas_VarValue(pVar)) );
+/*
+        printf( "%5d(%d) = ", Gia_ObjId(p->pAig, pVar), Tas_VarValue(pVar) );
+        if ( Gia_ObjIsCi(pVar) )
+            printf( "pi %d\n", Gia_ObjCioId(pVar) );
+        else
+        {
+            printf( "%5d %d  &  ", Gia_ObjFaninId0p(p->pAig, pVar), Gia_ObjFaninC0(pVar) );
+            printf( "%5d %d     ", Gia_ObjFaninId1p(p->pAig, pVar), Gia_ObjFaninC1(pVar) );
+            printf( "\n" );
+        }
+*/
+    }
+} 
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Tas_QueIsEmpty( Tas_Que_t * p )
+{
+    return p->iHead == p->iTail;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Tas_QuePush( Tas_Que_t * p, Gia_Obj_t * pObj )
+{
+    if ( p->iTail == p->nSize )
+    {
+        p->nSize *= 2;
+        p->pData = ABC_REALLOC( Gia_Obj_t *, p->pData, p->nSize ); 
+    }
+    p->pData[p->iTail++] = pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the object in the queue.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Tas_QueHasNode( Tas_Que_t * p, Gia_Obj_t * pObj )
+{
+    Gia_Obj_t * pTemp;
+    int i;
+    Tas_QueForEachEntry( *p, pTemp, i )
+        if ( pTemp == pObj )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Tas_QueStore( Tas_Que_t * p, int * piHeadOld, int * piTailOld )
+{
+    int i;
+    *piHeadOld = p->iHead;
+    *piTailOld = p->iTail;
+    for ( i = *piHeadOld; i < *piTailOld; i++ )
+        Tas_QuePush( p, p->pData[i] );
+    p->iHead = *piTailOld;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Tas_QueRestore( Tas_Que_t * p, int iHeadOld, int iTailOld )
+{
+    p->iHead = iHeadOld;
+    p->iTail = iTailOld;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finalized the clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Tas_QueFinish( Tas_Que_t * p )
+{
+    int iHeadOld = p->iHead;
+    assert( p->iHead < p->iTail );
+    Tas_QuePush( p, NULL );
+    p->iHead = p->iTail;
+    return iHeadOld;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Max number of fanins fanouts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Tas_VarFaninFanoutMax( Tas_Man_t * p, Gia_Obj_t * pObj )
+{
+    int Count0, Count1;
+    assert( !Gia_IsComplement(pObj) );
+    assert( Gia_ObjIsAnd(pObj) );
+    Count0 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin0(pObj) );
+    Count1 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin1(pObj) );
+    return Abc_MaxInt( Count0, Count1 );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Find variable with the highest activity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Tas_ManFindActive( Tas_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pObjMax = NULL;
+    float BestCost = 0.0;
+    int i, ObjId;
+    Tas_QueForEachEntry( p->pJust, pObj, i )
+    {
+        assert( Gia_ObjIsAnd(pObj) );
+        ObjId = Gia_ObjId( p->pAig, pObj );
+        if ( pObjMax == NULL || 
+             p->pActivity[Gia_ObjFaninId0(pObj,ObjId)] > BestCost || 
+            (p->pActivity[Gia_ObjFaninId0(pObj,ObjId)] == BestCost && pObjMax < Gia_ObjFanin0(pObj)) )
+        {
+            pObjMax  = Gia_ObjFanin0(pObj);
+            BestCost = p->pActivity[Gia_ObjFaninId0(pObj,ObjId)];
+        }
+        if ( p->pActivity[Gia_ObjFaninId1(pObj,ObjId)] > BestCost || 
+            (p->pActivity[Gia_ObjFaninId1(pObj,ObjId)] == BestCost && pObjMax < Gia_ObjFanin1(pObj)) )
+        {
+            pObjMax  = Gia_ObjFanin1(pObj);
+            BestCost = p->pActivity[Gia_ObjFaninId1(pObj,ObjId)];
+        }
+    }
+    return pObjMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find variable with the highest activity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Tas_ManDecideHighestFanin( Tas_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pObjMax = NULL;
+    int i, ObjId;
+    Tas_QueForEachEntry( p->pJust, pObj, i )
+    {
+        assert( Gia_ObjIsAnd(pObj) );
+        ObjId = Gia_ObjId( p->pAig, pObj );
+        if ( pObjMax == NULL || pObjMax < Gia_ObjFanin0(pObj) )
+            pObjMax  = Gia_ObjFanin0(pObj);
+        if ( pObjMax < Gia_ObjFanin1(pObj) )
+            pObjMax  = Gia_ObjFanin1(pObj);
+    }
+    return pObjMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find variable with the highest ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Tas_ManDecideHighest( Tas_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pObjMax = NULL;
+    int i;
+    Tas_QueForEachEntry( p->pJust, pObj, i )
+    {
+//printf( "%d %6.2f   ", Gia_ObjId(p->pAig, pObj), p->pActivity[Gia_ObjId(p->pAig, pObj)] );
+        if ( pObjMax == NULL || pObjMax < pObj )
+            pObjMax = pObj;
+    }
+//printf( "\n" );
+    return pObjMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find variable with the highest ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Tas_ManDecideHighestA( Tas_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pObjMax = NULL;
+    int i;
+    Tas_QueForEachEntry( p->pJust, pObj, i )
+    {
+        if ( pObjMax == NULL || 
+             p->pActivity[Gia_ObjId(p->pAig, pObjMax)] < p->pActivity[Gia_ObjId(p->pAig, pObj)] )
+            pObjMax = pObj;
+    }
+    return pObjMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find variable with the lowest ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Tas_ManDecideLowest( Tas_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pObjMin = NULL;
+    int i;
+    Tas_QueForEachEntry( p->pJust, pObj, i )
+        if ( pObjMin == NULL || pObjMin > pObj )
+            pObjMin = pObj;
+    return pObjMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find variable with the maximum number of fanin fanouts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Tas_ManDecideMaxFF( Tas_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pObjMax = NULL;
+    int i, iMaxFF = 0, iCurFF;
+    assert( p->pAig->pRefs != NULL );
+    Tas_QueForEachEntry( p->pJust, pObj, i )
+    {
+        iCurFF = Tas_VarFaninFanoutMax( p, pObj );
+        assert( iCurFF > 0 );
+        if ( iMaxFF < iCurFF )
+        {
+            iMaxFF = iCurFF;
+            pObjMax = pObj;
+        }
+    }
+    return pObjMax; 
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Tas_ManCancelUntil( Tas_Man_t * p, int iBound )
+{
+    Gia_Obj_t * pVar;
+    int i;
+    assert( iBound <= p->pProp.iTail );
+    p->pProp.iHead = iBound;
+    Tas_QueForEachEntry( p->pProp, pVar, i )
+        Tas_VarUnassign( pVar );
+    p->pProp.iTail = iBound;
+    Vec_IntShrink( p->vLevReas, 3*iBound );
+}
+
+int s_Counter2 = 0;
+int s_Counter3 = 0;
+int s_Counter4 = 0;
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns the variables a value.]
+
+  Description [Returns 1 if conflict; 0 if no conflict.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Tas_ManAssign( Tas_Man_t * p, Gia_Obj_t * pObj, int Level, Gia_Obj_t * pRes0, Gia_Obj_t * pRes1 )
+{
+    Gia_Obj_t * pObjR = Gia_Regular(pObj);
+    assert( Gia_ObjIsCand(pObjR) );
+    assert( !Tas_VarIsAssigned(pObjR) );
+    Tas_VarAssign( pObjR );
+    Tas_VarSetValue( pObjR, !Gia_IsComplement(pObj) );
+    assert( pObjR->Value == ~0 );
+    pObjR->Value = p->pProp.iTail;
+    Tas_QuePush( &p->pProp, pObjR );
+    Vec_IntPush( p->vLevReas, Level );
+    if ( pRes0 == NULL && pRes1 != 0 ) // clause
+    {
+        Vec_IntPush( p->vLevReas, 0 );
+        Vec_IntPush( p->vLevReas, Tas_ClsHandle( p, (Tas_Cls_t *)pRes1 ) );
+    }
+    else
+    {
+        Vec_IntPush( p->vLevReas, pRes0 ? pRes0-pObjR : 0 );
+        Vec_IntPush( p->vLevReas, pRes1 ? pRes1-pObjR : 0 );
+    }
+    assert( Vec_IntSize(p->vLevReas) == 3 * p->pProp.iTail );
+    s_Counter2++;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns clause size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Tas_ManClauseSize( Tas_Man_t * p, int hClause )
+{
+    Tas_Que_t * pQue = &(p->pClauses);
+    Gia_Obj_t ** pIter;
+    for ( pIter = pQue->pData + hClause; *pIter; pIter++ );
+    return pIter - pQue->pData - hClause ;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints conflict clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Tas_ManPrintClause( Tas_Man_t * p, int Level, int hClause )
+{
+    Tas_Que_t * pQue = &(p->pClauses);
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Tas_QueIsEmpty( pQue ) );
+    printf( "Level %2d : ", Level );
+    for ( i = hClause; (pObj = pQue->pData[i]); i++ )
+        printf( "%d=%d(%d) ", Gia_ObjId(p->pAig, pObj), Tas_VarValue(pObj), Tas_VarDecLevel(p, pObj) );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints conflict clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Tas_ManPrintClauseNew( Tas_Man_t * p, int Level, int hClause )
+{
+    Tas_Que_t * pQue = &(p->pClauses);
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Tas_QueIsEmpty( pQue ) );
+    printf( "Level %2d : ", Level );
+    for ( i = hClause; (pObj = pQue->pData[i]); i++ )
+        printf( "%c%d ", Tas_VarValue(pObj)? '+':'-', Gia_ObjId(p->pAig, pObj) );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns conflict clause.]
+
+  Description [Performs conflict analysis.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Tas_ManDeriveReason( Tas_Man_t * p, int Level )
+{
+    Tas_Que_t * pQue = &(p->pClauses);
+    Gia_Obj_t * pObj, * pReason;
+    int i, k, j, iLitLevel, iLitLevel2;//, Id;
+    assert( pQue->pData[pQue->iHead] == NULL );
+    assert( pQue->iHead + 1 < pQue->iTail );
+/*
+    for ( i = pQue->iHead + 1; i < pQue->iTail; i++ )
+    {
+        pObj = pQue->pData[i];
+        assert( pObj->fPhase == 0 );
+    }
+*/
+    // compact literals
+    Vec_PtrClear( p->vTemp );
+    for ( i = k = pQue->iHead + 1; i < pQue->iTail; i++ )
+    {
+        pObj = pQue->pData[i];
+        if ( pObj->fPhase ) // unassigned - seen again
+            continue;
+        // assigned - seen first time
+        pObj->fPhase = 1;
+        Vec_PtrPush( p->vTemp, pObj );
+        // bump activity
+//        Id = Gia_ObjId( p->pAig, pObj );
+//        if ( p->pActivity[Id] == 0.0 )
+//            Vec_IntPush( p->vActiveVars, Id );
+//        p->pActivity[Id] += p->Pars.VarInc;
+        // check decision level
+        iLitLevel = Tas_VarDecLevel( p, pObj );
+        if ( iLitLevel < Level )
+        {
+            pQue->pData[k++] = pObj;
+            continue;
+        }
+        assert( iLitLevel == Level );
+        if ( Tas_VarHasReasonCls( p, pObj ) )
+        {
+            Tas_Cls_t * pCls = Tas_VarReasonCls( p, pObj );
+            pReason = Gia_ManObj( p->pAig, Abc_Lit2Var(pCls->pLits[0]) );
+            assert( pReason == pObj );
+            for ( j = 1; j < pCls->nLits; j++ )
+            {
+                pReason = Gia_ManObj( p->pAig, Abc_Lit2Var(pCls->pLits[j]) );
+                iLitLevel2 = Tas_VarDecLevel( p, pReason );
+                assert( Tas_VarIsAssigned( pReason ) );
+                assert( !Tas_LitIsTrue( pReason, pCls->pLits[j] ) );
+                Tas_QuePush( pQue, pReason );
+            }
+        }
+        else
+        {
+            pReason = Tas_VarReason0( p, pObj );
+            if ( pReason == pObj ) // no reason
+            {
+                assert( pQue->pData[pQue->iHead] == NULL || Level == 0 );
+                if ( pQue->pData[pQue->iHead] == NULL )
+                    pQue->pData[pQue->iHead] = pObj;
+                else
+                    Tas_QuePush( pQue, pObj );
+                continue;
+            }
+            Tas_QuePush( pQue, pReason );
+            pReason = Tas_VarReason1( p, pObj );
+            if ( pReason != pObj ) // second reason
+                Tas_QuePush( pQue, pReason );
+        }
+    }
+    assert( pQue->pData[pQue->iHead] != NULL );
+    if ( pQue->pData[pQue->iHead] == NULL )
+        printf( "Tas_ManDeriveReason(): Failed to derive the clause!!!\n" );
+    pQue->iTail = k;
+    // clear the marks
+    Vec_PtrForEachEntry( Gia_Obj_t *, p->vTemp, pObj, i )
+        pObj->fPhase = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns conflict clause.]
+
+  Description [Performs conflict analysis.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Tas_ManAnalyze( Tas_Man_t * p, int Level, Gia_Obj_t * pVar, Gia_Obj_t * pFan0, Gia_Obj_t * pFan1 )
+{
+    Tas_Que_t * pQue = &(p->pClauses);
+    assert( Tas_VarIsAssigned(pVar) );
+    assert( Tas_VarIsAssigned(pFan0) );
+    assert( pFan1 == NULL || Tas_VarIsAssigned(pFan1) );
+    assert( Tas_QueIsEmpty( pQue ) );
+    Tas_QuePush( pQue, NULL );
+    Tas_QuePush( pQue, pVar );
+    Tas_QuePush( pQue, pFan0 );
+    if ( pFan1 )
+        Tas_QuePush( pQue, pFan1 );
+    Tas_ManDeriveReason( p, Level );
+    return Tas_QueFinish( pQue );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs resolution of two clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Tas_ManResolve( Tas_Man_t * p, int Level, int hClause0, int hClause1 )
+{
+    Tas_Que_t * pQue = &(p->pClauses);
+    Gia_Obj_t * pObj;
+    int i, LevelMax = -1, LevelCur;
+    assert( pQue->pData[hClause0] != NULL );
+    assert( pQue->pData[hClause0] == pQue->pData[hClause1] );
+/*
+    for ( i = hClause0 + 1; (pObj = pQue->pData[i]); i++ )
+        assert( pObj->fPhase == 0 );
+    for ( i = hClause1 + 1; (pObj = pQue->pData[i]); i++ )
+        assert( pObj->fPhase == 0 );
+*/
+    assert( Tas_QueIsEmpty( pQue ) );
+    Tas_QuePush( pQue, NULL );
+    for ( i = hClause0 + 1; (pObj = pQue->pData[i]); i++ )
+    {
+        if ( pObj->fPhase ) // unassigned - seen again
+            continue;
+        // assigned - seen first time
+        pObj->fPhase = 1;
+        Tas_QuePush( pQue, pObj );
+        LevelCur = Tas_VarDecLevel( p, pObj );
+        if ( LevelMax < LevelCur )
+            LevelMax = LevelCur;
+    }
+    for ( i = hClause1 + 1; (pObj = pQue->pData[i]); i++ )
+    {
+        if ( pObj->fPhase ) // unassigned - seen again
+            continue;
+        // assigned - seen first time
+        pObj->fPhase = 1;
+        Tas_QuePush( pQue, pObj );
+        LevelCur = Tas_VarDecLevel( p, pObj );
+        if ( LevelMax < LevelCur )
+            LevelMax = LevelCur;
+    }
+    for ( i = pQue->iHead + 1; i < pQue->iTail; i++ )
+        pQue->pData[i]->fPhase = 0;
+    Tas_ManDeriveReason( p, LevelMax );
+    return Tas_QueFinish( pQue );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates clause of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Tas_Cls_t * Tas_ManAllocCls( Tas_Man_t * p, int nSize )
+{
+    Tas_Cls_t * pCls;
+    if ( p->pStore.iCur + nSize > p->pStore.nSize )
+    {
+        p->pStore.nSize *= 2;
+        p->pStore.pData  = ABC_REALLOC( int, p->pStore.pData, p->pStore.nSize ); 
+    }
+    pCls = Tas_ClsFromHandle( p, p->pStore.iCur ); p->pStore.iCur += nSize;
+    memset( pCls, 0, sizeof(int) * nSize );
+    p->nClauses++;
+    return pCls;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one clause to the watcher list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Tas_ManWatchClause( Tas_Man_t * p, Tas_Cls_t * pClause, int Lit )
+{
+    assert( Abc_Lit2Var(Lit) < Gia_ManObjNum(p->pAig) );
+    assert( pClause->nLits >= 2 );
+    assert( pClause->pLits[0] == Lit || pClause->pLits[1] == Lit );
+    if ( pClause->pLits[0] == Lit )
+        pClause->iNext[0] = p->pWatches[Abc_LitNot(Lit)];  
+    else
+        pClause->iNext[1] = p->pWatches[Abc_LitNot(Lit)];  
+    if ( p->pWatches[Abc_LitNot(Lit)] == 0 )
+        Vec_IntPush( p->vWatchLits, Abc_LitNot(Lit) );
+    p->pWatches[Abc_LitNot(Lit)] = Tas_ClsHandle( p, pClause );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates clause of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Tas_Cls_t * Tas_ManCreateCls( Tas_Man_t * p, int hClause )
+{
+    Tas_Cls_t * pClause;
+    Tas_Que_t * pQue = &(p->pClauses);
+    Gia_Obj_t * pObj;
+    int i, nLits = 0;
+    assert( Tas_QueIsEmpty( pQue ) );
+    assert( pQue->pData[hClause] != NULL );
+    for ( i = hClause; (pObj = pQue->pData[i]); i++ )
+        nLits++;
+    if ( nLits == 1 )
+        return NULL;
+    // create this clause
+    pClause = Tas_ManAllocCls( p, nLits + 3 );
+    pClause->nLits = nLits;
+    for ( i = hClause; (pObj = pQue->pData[i]); i++ )
+    {
+        assert( Tas_VarIsAssigned( pObj ) );
+        pClause->pLits[i-hClause] = Abc_LitNot( Tas_VarToLit(p, pObj) );
+    }
+    // add the clause as watched one
+    if ( nLits >= 2 )
+    {
+        Tas_ManWatchClause( p, pClause, pClause->pLits[0] );
+        Tas_ManWatchClause( p, pClause, pClause->pLits[1] );
+    }
+    // increment activity
+//    p->Pars.VarInc /= p->Pars.VarDecay;
+    return pClause;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates clause of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Tas_ManCreateFromCls( Tas_Man_t * p, Tas_Cls_t * pCls, int Level )
+{
+    Tas_Que_t * pQue = &(p->pClauses);
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Tas_QueIsEmpty( pQue ) );
+    Tas_QuePush( pQue, NULL );
+    for ( i = 0; i < pCls->nLits; i++ )
+    {
+        pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCls->pLits[i]) );
+        assert( Tas_VarIsAssigned(pObj) );
+        assert( !Tas_LitIsTrue( pObj, pCls->pLits[i] ) );
+        Tas_QuePush( pQue, pObj );
+    }
+    Tas_ManDeriveReason( p, Level );
+    return Tas_QueFinish( pQue );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagate one assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Tas_ManPropagateWatch( Tas_Man_t * p, int Level, int Lit )
+{
+    Gia_Obj_t * pObj;
+    Tas_Cls_t * pCur;
+    int * piPrev, iCur, iTemp;
+    int i, LitF = Abc_LitNot(Lit);
+    // iterate through the clauses
+    piPrev = p->pWatches + Lit;
+    for ( iCur = p->pWatches[Lit]; iCur; iCur = *piPrev )
+    {
+        pCur = Tas_ClsFromHandle( p, iCur );
+        // make sure the false literal is in the second literal of the clause
+        if ( pCur->pLits[0] == LitF )
+        {
+            pCur->pLits[0] = pCur->pLits[1];
+            pCur->pLits[1] = LitF;
+            iTemp = pCur->iNext[0];
+            pCur->iNext[0] = pCur->iNext[1];
+            pCur->iNext[1] = iTemp;
+        }
+        assert( pCur->pLits[1] == LitF );
+
+        // if the first literal is true, the clause is satisfied
+//        if ( pCur->pLits[0] == p->pAssigns[Abc_Lit2Var(pCur->pLits[0])] )
+        pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCur->pLits[0]) );
+        if ( Tas_VarIsAssigned(pObj) && Tas_LitIsTrue( pObj, pCur->pLits[0] ) )
+        {
+            piPrev = &pCur->iNext[1];
+            continue;
+        }
+
+        // look for a new literal to watch
+        for ( i = 2; i < (int)pCur->nLits; i++ )
+        {
+            // skip the case when the literal is false
+//            if ( Abc_LitNot(pCur->pLits[i]) == p->pAssigns[Abc_Lit2Var(pCur->pLits[i])] )
+            pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCur->pLits[i]) );
+            if ( Tas_VarIsAssigned(pObj) && !Tas_LitIsTrue( pObj, pCur->pLits[i] ) )
+                continue;
+            // the literal is either true or unassigned - watch it
+            pCur->pLits[1] = pCur->pLits[i];
+            pCur->pLits[i] = LitF;
+            // remove this clause from the watch list of Lit
+            *piPrev = pCur->iNext[1];
+            // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1])
+            Tas_ManWatchClause( p, pCur, pCur->pLits[1] );
+            break;
+        }
+        if ( i < (int)pCur->nLits ) // found new watch
+            continue;
+
+        // clause is unit - enqueue new implication
+        pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCur->pLits[0]) );
+        if ( !Tas_VarIsAssigned(pObj) )
+        {
+/*
+            {
+                int iLitLevel, iPlace;
+                for ( i = 1; i < (int)pCur->nLits; i++ )
+                {
+                    pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCur->pLits[i]) );
+                    iLitLevel = Tas_VarDecLevel( p, pObj );
+                    iPlace = pObj->Value;
+                    printf( "Lit = %d. Level = %d. Place = %d.\n", pCur->pLits[i], iLitLevel, iPlace );
+                    i = i;
+                }
+            }
+*/
+            Tas_ManAssign( p, Gia_ObjFromLit(p->pAig, pCur->pLits[0]), Level, NULL, (Gia_Obj_t *)pCur );
+            piPrev = &pCur->iNext[1];
+            continue;
+        }
+        // conflict detected - return the conflict clause
+        assert( !Tas_LitIsTrue( pObj, pCur->pLits[0] ) );
+        return Tas_ManCreateFromCls( p, pCur, Level );
+    }
+    return 0;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Propagates a variable.]
+
+  Description [Returns clause handle if conflict; 0 if no conflict.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Tas_ManPropagateOne( Tas_Man_t * p, Gia_Obj_t * pVar, int Level )
+{
+    int Value0, Value1, hClause;
+    assert( !Gia_IsComplement(pVar) );
+    assert( Tas_VarIsAssigned(pVar) );
+    s_Counter3++;
+    if ( (hClause = Tas_ManPropagateWatch( p, Level, Tas_VarToLit(p, pVar) )) )
+        return hClause;
+    if ( Gia_ObjIsCi(pVar) )
+        return 0;
+/*
+    if ( pVar->iDiff0 == 570869 && pVar->iDiff1 == 546821 && Level == 3 )
+    {
+        Gia_Obj_t * pFan0 = Gia_ObjFanin0(pVar);
+        Gia_Obj_t * pFan1 = Gia_ObjFanin1(pVar);
+        int s = 0;
+    }
+*/
+    assert( Gia_ObjIsAnd(pVar) );
+    Value0 = Tas_VarFanin0Value(pVar);
+    Value1 = Tas_VarFanin1Value(pVar);
+    if ( Tas_VarValue(pVar) )
+    { // value is 1
+        if ( Value0 == 0 || Value1 == 0 ) // one is 0
+        {
+            if ( Value0 == 0 && Value1 != 0 )
+                return Tas_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), NULL );
+            if ( Value0 != 0 && Value1 == 0 )
+                return Tas_ManAnalyze( p, Level, pVar, Gia_ObjFanin1(pVar), NULL );
+            assert( Value0 == 0 && Value1 == 0 );
+            return Tas_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) );
+        }
+        if ( Value0 == 2 ) // first is unassigned
+            Tas_ManAssign( p, Gia_ObjChild0(pVar), Level, pVar, NULL );
+        if ( Value1 == 2 ) // first is unassigned
+            Tas_ManAssign( p, Gia_ObjChild1(pVar), Level, pVar, NULL );
+        return 0;
+    }
+    // value is 0
+    if ( Value0 == 0 || Value1 == 0 ) // one is 0
+        return 0;
+    if ( Value0 == 1 && Value1 == 1 ) // both are 1
+        return Tas_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) );
+    if ( Value0 == 1 || Value1 == 1 ) // one is 1 
+    {
+        if ( Value0 == 2 ) // first is unassigned
+            Tas_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)), Level, pVar, Gia_ObjFanin1(pVar) );
+        if ( Value1 == 2 ) // second is unassigned
+            Tas_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)), Level, pVar, Gia_ObjFanin0(pVar) );
+        return 0;
+    }
+    assert( Tas_VarIsJust(pVar) );
+    assert( !Tas_QueHasNode( &p->pJust, pVar ) );
+    Tas_QuePush( &p->pJust, pVar );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagates a variable.]
+
+  Description [Returns 1 if conflict; 0 if no conflict.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Tas_ManPropagateTwo( Tas_Man_t * p, Gia_Obj_t * pVar, int Level )
+{
+    int Value0, Value1;
+    s_Counter4++;
+    assert( !Gia_IsComplement(pVar) );
+    assert( Gia_ObjIsAnd(pVar) );
+    assert( Tas_VarIsAssigned(pVar) );
+    assert( !Tas_VarValue(pVar) );
+    Value0 = Tas_VarFanin0Value(pVar);
+    Value1 = Tas_VarFanin1Value(pVar);
+    // value is 0
+    if ( Value0 == 0 || Value1 == 0 ) // one is 0
+        return 0;
+    if ( Value0 == 1 && Value1 == 1 ) // both are 1
+        return Tas_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) );
+    assert( Value0 == 1 || Value1 == 1 );
+    if ( Value0 == 2 ) // first is unassigned
+        Tas_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)), Level, pVar, Gia_ObjFanin1(pVar) );
+    if ( Value1 == 2 ) // first is unassigned
+        Tas_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)), Level, pVar, Gia_ObjFanin0(pVar) );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagates all variables.]
+
+  Description [Returns 1 if conflict; 0 if no conflict.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tas_ManPropagate( Tas_Man_t * p, int Level )
+{
+    int hClause;
+    Gia_Obj_t * pVar;
+    int i, k;//, nIter = 0;
+    while ( 1 )
+    {
+//        nIter++;
+        Tas_QueForEachEntry( p->pProp, pVar, i )
+        {
+            if ( (hClause = Tas_ManPropagateOne( p, pVar, Level )) )
+                return hClause;
+        }
+        p->pProp.iHead = p->pProp.iTail;
+        k = p->pJust.iHead;
+        Tas_QueForEachEntry( p->pJust, pVar, i )
+        {
+            if ( Tas_VarIsJust( pVar ) )
+                p->pJust.pData[k++] = pVar;
+            else if ( (hClause = Tas_ManPropagateTwo( p, pVar, Level )) )
+                return hClause;
+        }
+        if ( k == p->pJust.iTail )
+            break;
+        p->pJust.iTail = k;
+    }
+//    printf( "%d ", nIter );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Solve the problem recursively.]
+
+  Description [Returns learnt clause if unsat, NULL if sat or undecided.]
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+int Tas_ManSolve_rec( Tas_Man_t * p, int Level )
+{ 
+    Tas_Que_t * pQue = &(p->pClauses);
+    Gia_Obj_t * pVar, * pDecVar = NULL;
+    int hClause, hLearn0, hLearn1;
+    int iPropHead, iJustHead, iJustTail;
+    // propagate assignments
+    assert( !Tas_QueIsEmpty(&p->pProp) );
+    if ( (hClause = Tas_ManPropagate( p, Level )) )
+    {
+        Tas_ManCreateCls( p, hClause );
+        return hClause;
+    }
+    // check for satisfying assignment
+    assert( Tas_QueIsEmpty(&p->pProp) );
+    if ( Tas_QueIsEmpty(&p->pJust) )
+        return 0;
+    // quit using resource limits
+    p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead );
+    if ( Tas_ManCheckLimits( p ) )
+        return 0;
+    // remember the state before branching
+    iPropHead = p->pProp.iHead;
+    Tas_QueStore( &p->pJust, &iJustHead, &iJustTail );
+    // find the decision variable
+    if ( p->Pars.fUseActive )
+        pVar = NULL, pDecVar = Tas_ManFindActive( p );
+    else if ( p->Pars.fUseHighest )
+//        pVar = NULL, pDecVar = Tas_ManDecideHighestFanin( p );
+        pVar = Tas_ManDecideHighest( p );
+    else if ( p->Pars.fUseLowest )
+        pVar = Tas_ManDecideLowest( p );
+    else if ( p->Pars.fUseMaxFF )
+        pVar = Tas_ManDecideMaxFF( p );
+    else assert( 0 );
+    // chose decision variable using fanout count
+    if ( pVar != NULL )
+    {
+        assert( Tas_VarIsJust( pVar ) );
+        if ( Gia_ObjRefNum(p->pAig, Gia_ObjFanin0(pVar)) > Gia_ObjRefNum(p->pAig, Gia_ObjFanin1(pVar)) )
+            pDecVar = Gia_Not(Gia_ObjChild0(pVar));
+        else
+            pDecVar = Gia_Not(Gia_ObjChild1(pVar));
+//        pDecVar = Gia_NotCond( pDecVar, Gia_Regular(pDecVar)->fMark1 ^ !Gia_IsComplement(pDecVar) );
+    }
+    // decide on first fanin
+    Tas_ManAssign( p, pDecVar, Level+1, NULL, NULL );
+    if ( !(hLearn0 = Tas_ManSolve_rec( p, Level+1 )) )
+        return 0;
+    if ( pQue->pData[hLearn0] != Gia_Regular(pDecVar) )
+        return hLearn0;
+    Tas_ManCancelUntil( p, iPropHead );
+    Tas_QueRestore( &p->pJust, iJustHead, iJustTail );
+    // decide on second fanin
+    Tas_ManAssign( p, Gia_Not(pDecVar), Level+1, NULL, NULL );
+    if ( !(hLearn1 = Tas_ManSolve_rec( p, Level+1 )) )
+        return 0;
+    if ( pQue->pData[hLearn1] != Gia_Regular(pDecVar) )
+        return hLearn1;
+    hClause = Tas_ManResolve( p, Level, hLearn0, hLearn1 );
+    Tas_ManCreateCls( p, hClause );
+//    Tas_ManPrintClauseNew( p, Level, hClause );
+//    if ( Level > Tas_ClauseDecLevel(p, hClause) )
+//        p->Pars.nBTThisNc++;
+    p->Pars.nBTThis++;
+    return hClause;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Looking for a satisfying assignment of the node.]
+
+  Description [Assumes that each node has flag pObj->fMark0 set to 0.
+  Returns 1 if unsatisfiable, 0 if satisfiable, and -1 if undecided.
+  The node may be complemented. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tas_ManSolve( Tas_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 )
+{
+    int i, Entry, RetValue = 0;
+    s_Counter2 = 0;
+    Vec_IntClear( p->vModel );
+    if ( pObj == Gia_ManConst0(p->pAig) || pObj2 == Gia_ManConst0(p->pAig) || pObj == Gia_Not(pObj2) )
+        return 1;
+    if ( pObj == Gia_ManConst1(p->pAig) && (pObj2 == NULL || pObj2 == Gia_ManConst1(p->pAig)) )
+        return 0;
+    assert( !p->pProp.iHead && !p->pProp.iTail );
+    assert( !p->pJust.iHead && !p->pJust.iTail );
+    assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 );
+    p->Pars.nBTThis = p->Pars.nJustThis = p->Pars.nBTThisNc = 0;
+    Tas_ManAssign( p, pObj, 0, NULL, NULL );
+    if ( pObj2 && !Tas_VarIsAssigned(Gia_Regular(pObj2)) )
+        Tas_ManAssign( p, pObj2, 0, NULL, NULL );
+    if ( !Tas_ManSolve_rec(p, 0) && !Tas_ManCheckLimits(p) )
+        Tas_ManSaveModel( p, p->vModel );
+    else
+        RetValue = 1;
+    Tas_ManCancelUntil( p, 0 );
+    p->pJust.iHead = p->pJust.iTail = 0;
+    p->pClauses.iHead = p->pClauses.iTail = 1;
+    // clauses
+    if ( p->nClauses > 0 )
+    {
+        p->pStore.iCur = 16;
+        Vec_IntForEachEntry( p->vWatchLits, Entry, i )
+            p->pWatches[Entry] = 0;
+        Vec_IntClear( p->vWatchLits );
+        p->nClauses = 0;
+    }
+    // activity
+    Vec_IntForEachEntry( p->vActiveVars, Entry, i )
+        p->pActivity[Entry] = 0.0;
+    Vec_IntClear( p->vActiveVars );
+    // statistics
+    p->Pars.nBTTotal += p->Pars.nBTThis;
+    p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis );
+    if ( Tas_ManCheckLimits( p ) )
+        RetValue = -1;
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Looking for a satisfying assignment of the node.]
+
+  Description [Assumes that each node has flag pObj->fMark0 set to 0.
+  Returns 1 if unsatisfiable, 0 if satisfiable, and -1 if undecided.
+  The node may be complemented. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tas_ManSolveArray( Tas_Man_t * p, Vec_Ptr_t * vObjs )
+{
+    Gia_Obj_t * pObj;
+    int i, Entry, RetValue = 0;
+    s_Counter2 = 0;
+    s_Counter3 = 0;
+    s_Counter4 = 0;
+    Vec_IntClear( p->vModel );
+    Vec_PtrForEachEntry( Gia_Obj_t *, vObjs, pObj, i )
+        if ( pObj == Gia_ManConst0(p->pAig) )
+            return 1;
+    assert( !p->pProp.iHead && !p->pProp.iTail );
+    assert( !p->pJust.iHead && !p->pJust.iTail );
+    assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 );
+    p->Pars.nBTThis = p->Pars.nJustThis = p->Pars.nBTThisNc = 0;
+    Vec_PtrForEachEntry( Gia_Obj_t *, vObjs, pObj, i )
+        if ( pObj != Gia_ManConst1(p->pAig) && !Tas_VarIsAssigned(Gia_Regular(pObj)) )
+            Tas_ManAssign( p, pObj, 0, NULL, NULL );
+    if ( !Tas_ManSolve_rec(p, 0) && !Tas_ManCheckLimits(p) )
+        Tas_ManSaveModel( p, p->vModel );
+    else
+        RetValue = 1;
+    Tas_ManCancelUntil( p, 0 );
+    p->pJust.iHead = p->pJust.iTail = 0;
+    p->pClauses.iHead = p->pClauses.iTail = 1;
+    // clauses
+    if ( p->nClauses > 0 )
+    {
+        p->pStore.iCur = 16;
+        Vec_IntForEachEntry( p->vWatchLits, Entry, i )
+            p->pWatches[Entry] = 0;
+        Vec_IntClear( p->vWatchLits );
+        p->nClauses = 0;
+    }
+    // activity
+    Vec_IntForEachEntry( p->vActiveVars, Entry, i )
+        p->pActivity[Entry] = 0.0;
+    Vec_IntClear( p->vActiveVars );
+    // statistics
+    p->Pars.nBTTotal += p->Pars.nBTThis;
+    p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis );
+    if ( Tas_ManCheckLimits( p ) )
+        RetValue = -1;
+
+//    printf( "%d ", Gia_ManObjNum(p->pAig) );
+//    printf( "%d ", p->Pars.nBTThis );
+//    printf( "%d ", p->Pars.nJustThis );
+//    printf( "%d ", s_Counter2 );
+//    printf( "%d ", s_Counter3 );
+//    printf( "%d  ", s_Counter4 );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints statistics of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tas_ManSatPrintStats( Tas_Man_t * p )
+{
+    printf( "CO = %8d  ", Gia_ManCoNum(p->pAig) );
+    printf( "AND = %8d  ", Gia_ManAndNum(p->pAig) );
+    printf( "Conf = %6d  ", p->Pars.nBTLimit );
+    printf( "JustMax = %5d  ", p->Pars.nJustLimit );
+    printf( "\n" );
+    printf( "Unsat calls %6d  (%6.2f %%)   Ave conf = %8.1f   ", 
+        p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal :0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 );
+    ABC_PRTP( "Time", p->timeSatUnsat, p->timeTotal );
+    printf( "Sat   calls %6d  (%6.2f %%)   Ave conf = %8.1f   ", 
+        p->nSatSat,   p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal :0.0, p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 );
+    ABC_PRTP( "Time", p->timeSatSat,   p->timeTotal );
+    printf( "Undef calls %6d  (%6.2f %%)   Ave conf = %8.1f   ", 
+        p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal :0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 );
+    ABC_PRTP( "Time", p->timeSatUndec, p->timeTotal );
+    ABC_PRT( "Total time", p->timeTotal );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure to test the new SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Tas_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose )
+{
+    extern void Gia_ManCollectTest( Gia_Man_t * pAig );
+    extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out );
+    Tas_Man_t * p; 
+    Vec_Int_t * vCex, * vVisit, * vCexStore;
+    Vec_Str_t * vStatus;
+    Gia_Obj_t * pRoot;//, * pRootCopy; 
+//    Gia_Man_t * pAigCopy = Gia_ManDup( pAig ), * pAigTemp;
+
+    int i, status;
+    abctime clk, clkTotal = Abc_Clock();
+    assert( Gia_ManRegNum(pAig) == 0 );
+//    Gia_ManCollectTest( pAig );
+    // prepare AIG
+    Gia_ManCreateRefs( pAig );
+    Gia_ManCleanMark0( pAig );
+    Gia_ManCleanMark1( pAig );
+    Gia_ManFillValue( pAig ); // maps nodes into trail ids
+    Gia_ManCleanPhase( pAig ); // maps nodes into trail ids
+    // create logic network
+    p = Tas_ManAlloc( pAig, nConfs );
+    p->pAig   = pAig;
+    // create resulting data-structures
+    vStatus   = Vec_StrAlloc( Gia_ManPoNum(pAig) );
+    vCexStore = Vec_IntAlloc( 10000 );
+    vVisit    = Vec_IntAlloc( 100 );
+    vCex      = Tas_ReadModel( p );
+    // solve for each output
+    Gia_ManForEachCo( pAig, pRoot, i )
+    {
+//        printf( "%d=", i );
+
+        Vec_IntClear( vCex );
+        if ( Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) )
+        {
+            if ( Gia_ObjFaninC0(pRoot) )
+            {
+//                printf( "Constant 1 output of SRM!!!\n" );
+                Cec_ManSatAddToStore( vCexStore, vCex, i ); // trivial counter-example
+                Vec_StrPush( vStatus, 0 );
+            }
+            else
+            {
+//                printf( "Constant 0 output of SRM!!!\n" );
+                Vec_StrPush( vStatus, 1 );
+            }
+            continue;
+        } 
+        clk = Abc_Clock();
+//        p->Pars.fUseActive  = 1;
+        p->Pars.fUseHighest = 1;
+        p->Pars.fUseLowest  = 0;
+        status = Tas_ManSolve( p, Gia_ObjChild0(pRoot), NULL );
+//        printf( "\n" );
+/*
+        if ( status == -1 )
+        {
+            p->Pars.fUseHighest = 0;
+            p->Pars.fUseLowest  = 1;
+            status = Tas_ManSolve( p, Gia_ObjChild0(pRoot) );
+        }
+*/
+        Vec_StrPush( vStatus, (char)status );
+        if ( status == -1 )
+        {
+//            printf( "Unsolved %d.\n", i );
+
+            p->nSatUndec++;
+            p->nConfUndec += p->Pars.nBTThis;
+            Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout
+            p->timeSatUndec += Abc_Clock() - clk;
+            continue;
+        }
+
+//        pRootCopy = Gia_ManCo( pAigCopy, i );
+//        pRootCopy->iDiff0 = Gia_ObjId( pAigCopy, pRootCopy );
+//        pRootCopy->fCompl0 = 0;
+
+        if ( status == 1 )
+        {
+            p->nSatUnsat++;
+            p->nConfUnsat += p->Pars.nBTThis;
+            p->timeSatUnsat += Abc_Clock() - clk;
+            continue;
+        }
+        p->nSatSat++;
+        p->nConfSat += p->Pars.nBTThis;
+//        Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit );
+        Cec_ManSatAddToStore( vCexStore, vCex, i );
+        p->timeSatSat += Abc_Clock() - clk;
+
+//        printf( "%d ", Vec_IntSize(vCex) );
+    }
+//    pAigCopy = Gia_ManCleanup( pAigTemp = pAigCopy );
+//    Gia_ManStop( pAigTemp );
+//    Gia_DumpAiger( pAigCopy, "test", 0, 2 );
+//    Gia_ManStop( pAigCopy );
+
+    Vec_IntFree( vVisit );
+    p->nSatTotal = Gia_ManPoNum(pAig);
+    p->timeTotal = Abc_Clock() - clkTotal;
+    if ( fVerbose )
+        Tas_ManSatPrintStats( p );
+//    printf( "RecCalls = %8d.  RecClause = %8d.  RecNonChro = %8d.\n", p->nRecCall, p->nRecClause, p->nRecNonChro );
+    Tas_ManStop( p );
+    *pvStatus = vStatus;
+
+//    printf( "Total number of cex literals = %d. (Ave = %d)\n", 
+//         Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat, 
+//        (Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat)/p->nSatSat );
+    return vCexStore;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Packs patterns into array of simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+*************************************`**********************************/
+int Tas_StorePatternTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * pLits, int nLits )
+{
+    unsigned * pInfo, * pPres;
+    int i;
+    for ( i = 0; i < nLits; i++ )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i]));
+        pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i]));
+        if ( Abc_InfoHasBit( pPres, iBit ) && 
+             Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) )
+             return 0;
+    }
+    for ( i = 0; i < nLits; i++ )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i]));
+        pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i]));
+        Abc_InfoSetBit( pPres, iBit );
+        if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) )
+            Abc_InfoXorBit( pInfo, iBit );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure to test the new SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tas_StorePattern( Vec_Ptr_t * vSimInfo, Vec_Ptr_t * vPres, Vec_Int_t * vCex )
+{
+    int k;
+    for ( k = 1; k < 32; k++ )
+        if ( Tas_StorePatternTry( vSimInfo, vPres, k, (int *)Vec_IntArray(vCex), Vec_IntSize(vCex) ) )
+            break;
+    return (int)(k < 32);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure to test the new SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tas_ManSolveMiterNc2( Gia_Man_t * pAig, int nConfs, Gia_Man_t * pAigOld, Vec_Ptr_t * vOldRoots, Vec_Ptr_t * vSimInfo )
+{
+    int nPatMax = 1000;
+    int fVerbose = 1;
+    extern void Gia_ManCollectTest( Gia_Man_t * pAig );
+    extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out );
+    Tas_Man_t * p; 
+    Vec_Ptr_t * vPres;
+    Vec_Int_t * vCex, * vVisit, * vCexStore;
+    Vec_Str_t * vStatus;
+    Gia_Obj_t * pRoot, * pOldRoot; 
+    int i, status;
+    abctime clk, clkTotal = Abc_Clock();
+    int Tried = 0, Stored = 0, Step = Gia_ManCoNum(pAig) / nPatMax;
+    assert( Gia_ManRegNum(pAig) == 0 );
+//    Gia_ManCollectTest( pAig );
+    // prepare AIG
+    Gia_ManCreateRefs( pAig );
+    Gia_ManCleanMark0( pAig );
+    Gia_ManCleanMark1( pAig );
+    Gia_ManFillValue( pAig ); // maps nodes into trail ids
+    Gia_ManCleanPhase( pAig ); // maps nodes into trail ids
+    // create logic network
+    p = Tas_ManAlloc( pAig, nConfs );
+    p->pAig   = pAig;
+    // create resulting data-structures
+    vStatus   = Vec_StrAlloc( Gia_ManPoNum(pAig) );
+    vCexStore = Vec_IntAlloc( 10000 );
+    vVisit    = Vec_IntAlloc( 100 );
+    vCex      = Tas_ReadModel( p );
+    // solve for each output
+    vPres = Vec_PtrAllocSimInfo( Gia_ManCiNum(pAig), 1 );
+    Vec_PtrCleanSimInfo( vPres, 0, 1 );
+    
+    Gia_ManForEachCo( pAig, pRoot, i )
+    {
+        assert( !Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) );
+        Vec_IntClear( vCex );
+        clk = Abc_Clock();
+        p->Pars.fUseHighest = 1;
+        p->Pars.fUseLowest  = 0;
+        status = Tas_ManSolve( p, Gia_ObjChild0(pRoot), NULL );
+        Vec_StrPush( vStatus, (char)status );
+        if ( status == -1 )
+        {
+            p->nSatUndec++;
+            p->nConfUndec += p->Pars.nBTThis;
+//            Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout
+            p->timeSatUndec += Abc_Clock() - clk;
+
+            i += Step;
+            continue;
+        }
+        if ( status == 1 )
+        {
+            p->nSatUnsat++;
+            p->nConfUnsat += p->Pars.nBTThis;
+            p->timeSatUnsat += Abc_Clock() - clk;
+            // record proved
+            pOldRoot = (Gia_Obj_t *)Vec_PtrEntry( vOldRoots, i );
+            assert( !Gia_ObjProved( pAigOld, Gia_ObjId(pAigOld, pOldRoot) ) );
+            Gia_ObjSetProved( pAigOld, Gia_ObjId(pAigOld, pOldRoot) );
+
+            i += Step;
+            continue;
+        }
+        p->nSatSat++;
+        p->nConfSat += p->Pars.nBTThis;
+//        Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit );
+//        Cec_ManSatAddToStore( vCexStore, vCex, i );
+
+        // save pattern
+        Tried++;
+        Stored += Tas_StorePattern( vSimInfo, vPres, vCex );
+        p->timeSatSat += Abc_Clock() - clk;
+        i += Step;
+    }
+    printf( "Tried = %d  Stored = %d\n", Tried, Stored );
+    Vec_IntFree( vVisit );
+    p->nSatTotal = Gia_ManPoNum(pAig);
+    p->timeTotal = Abc_Clock() - clkTotal;
+    if ( fVerbose )
+        Tas_ManSatPrintStats( p );
+    Tas_ManStop( p );
+    Vec_PtrFree( vPres );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaCTas2.c b/abc-build/src/aig/gia/giaCTas2.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaCTas2.c
@@ -0,0 +1,208 @@
+/**CFile****************************************************************
+
+  FileName    [giaCSat2.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Circuit-based SAT solver.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaCSat2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Tas_Par_t_ Tas_Par_t;
+struct Tas_Par_t_
+{
+    // conflict limits
+    int           nBTLimit;     // limit on the number of conflicts
+    // current parameters
+    int           nBTThis;      // number of conflicts
+    int           nBTTotal;     // total number of conflicts
+    // decision heuristics
+    int           fUseHighest;  // use node with the highest ID
+    // other parameters
+    int           fVerbose;
+};
+
+typedef struct Tas_Sto_t_ Tas_Sto_t;
+struct Tas_Sto_t_
+{
+    int           iCur;         // currently used
+    int           nSize;        // allocated size
+    char *        pBuffer;      // handles of objects stored in the queue
+};
+
+typedef struct Tas_Que_t_ Tas_Que_t;
+struct Tas_Que_t_
+{
+    int           iHead;        // beginning of the queue
+    int           iTail;        // end of the queue
+    int           nSize;        // allocated size
+    int *         pData;        // handles of objects stored in the queue
+};
+
+typedef struct Tas_Var_t_ Tas_Var_t;
+struct Tas_Var_t_
+{
+    unsigned      fTerm   :  1; // terminal node
+    unsigned      fVal    :  1; // current value
+    unsigned      fValOld :  1; // previous value
+    unsigned      fAssign :  1; // assigned status
+    unsigned      fJQueue :  1; // part of J-frontier
+    unsigned      fCompl0 :  1; // complemented attribute
+    unsigned      fCompl1 :  1; // complemented attribute
+    unsigned      fMark0  :  1; // multi-purpose mark
+    unsigned      fMark1  :  1; // multi-purpose mark
+    unsigned      fPhase  :  1; // polarity
+    unsigned      Level   : 22; // decision level 
+    int           Id;           // unique ID of this variable
+    int           IdAig;        // original ID of this variable
+    int           Reason0;      // reason of this variable
+    int           Reason1;      // reason of this variable
+    int           Diff0;        // difference for the first fanin 
+    int           Diff1;        // difference for the second fanin 
+    int           Watch0;       // handle of first watch
+    int           Watch1;       // handle of second watch   
+};
+
+typedef struct Tas_Cls_t_ Tas_Cls_t;
+struct Tas_Cls_t_
+{
+    int           Watch0;       // next clause to watch
+    int           Watch1;       // next clause to watch
+    int           pVars[0];     // variable handles
+};
+ 
+typedef struct Tas_Man_t_ Tas_Man_t;
+struct Tas_Man_t_
+{
+    // user data
+    Gia_Man_t *   pAig;         // AIG manager
+    Tas_Par_t     Pars;         // parameters
+    // solver data
+    Tas_Sto_t *   pVars;        // variables
+    Tas_Sto_t *   pClauses;     // clauses
+    // state representation
+    Tas_Que_t     pProp;        // propagation queue
+    Tas_Que_t     pJust;        // justification queue
+    Vec_Int_t *   vModel;       // satisfying assignment
+    Vec_Ptr_t *   vTemp;        // temporary storage
+    // SAT calls statistics
+    int           nSatUnsat;    // the number of proofs
+    int           nSatSat;      // the number of failure
+    int           nSatUndec;    // the number of timeouts
+    int           nSatTotal;    // the number of calls
+    // conflicts
+    int           nConfUnsat;   // conflicts in unsat problems
+    int           nConfSat;     // conflicts in sat problems
+    int           nConfUndec;   // conflicts in undec problems
+    int           nConfTotal;   // total conflicts
+    // runtime stats
+    clock_t       timeSatUnsat; // unsat
+    clock_t       timeSatSat;   // sat
+    clock_t       timeSatUndec; // undecided
+    clock_t       timeTotal;    // total runtime
+};
+
+static inline int         Tas_VarIsAssigned( Tas_Var_t * pVar )        { return pVar->fAssign;                                      }
+static inline void        Tas_VarAssign( Tas_Var_t * pVar )            { assert(!pVar->fAssign); pVar->fAssign = 1;                 }
+static inline void        Tas_VarUnassign( Tas_Var_t * pVar )          { assert(pVar->fAssign);  pVar->fAssign = 0; pVar->fVal = 0; }
+static inline int         Tas_VarValue( Tas_Var_t * pVar )             { assert(pVar->fAssign);  return pVar->fVal;                 }
+static inline void        Tas_VarSetValue( Tas_Var_t * pVar, int v )   { assert(pVar->fAssign);  pVar->fVal = v;                    }
+static inline int         Tas_VarIsJust( Tas_Var_t * pVar )            { return Gia_ObjIsAnd(pVar) && !Tas_VarIsAssigned(Gia_ObjFanin0(pVar)) && !Tas_VarIsAssigned(Gia_ObjFanin1(pVar)); } 
+static inline int         Tas_VarFanin0Value( Tas_Var_t * pVar )       { return !Tas_VarIsAssigned(Gia_ObjFanin0(pVar)) ? 2 : (Tas_VarValue(Gia_ObjFanin0(pVar)) ^ Gia_ObjFaninC0(pVar)); }
+static inline int         Tas_VarFanin1Value( Tas_Var_t * pVar )       { return !Tas_VarIsAssigned(Gia_ObjFanin1(pVar)) ? 2 : (Tas_VarValue(Gia_ObjFanin1(pVar)) ^ Gia_ObjFaninC1(pVar)); }
+
+static inline int         Tas_VarDecLevel( Tas_Man_t * p, Tas_Var_t * pVar )  { assert( pVar->Value != ~0 ); return Vec_IntEntry(p->vLevReas, 3*pVar->Value);          }
+static inline Tas_Var_t * Tas_VarReason0( Tas_Man_t * p, Tas_Var_t * pVar )   { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+1); }
+static inline Tas_Var_t * Tas_VarReason1( Tas_Man_t * p, Tas_Var_t * pVar )   { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+2); }
+static inline int         Tas_ClauseDecLevel( Tas_Man_t * p, int hClause )    { return Tas_VarDecLevel( p, p->pClauses.pData[hClause] );                               }
+
+static inline Tas_Var_t * Tas_ManVar( Tas_Man_t * p, int h )           { return (Tas_Var_t *)(p->pVars->pBuffer + h);               }
+static inline Tas_Cls_t * Tas_ManClause( Tas_Man_t * p, int h )        { return (Tas_Cls_t *)(p->pClauses->pBuffer + h);            }
+
+#define Tas_ClaForEachVar( p, pClause, pVar, i )          \
+    for ( pVar = Tas_ManVar(p, pClause->pVars[(i=0)]); pClause->pVars[i]; pVar = (Tas_Var_t *)(((char *)pVar + pClause->pVars[++i])) )
+
+#define Tas_QueForEachVar( p, pQue, pVar, i )             \
+    for ( pVar = Tas_ManVar(p, pQue->pVars[(i=pQue->iHead)]); i < pQue->iTail; pVar = Tas_ManVar(p, pQue->pVars[i++]) )
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Tas_Var_t * Tas_ManCreateVar( Tas_Man_t * p )
+{
+    Tas_Var_t * pVar;
+    if ( p->pVars->iCur + sizeof(Tas_Var_t) > p->pVars->nSize )
+    {
+        p->pVars->nSize *= 2;
+        p->pVars->pData = ABC_REALLOC( char, p->pVars->pData, p->pVars->nSize ); 
+    }
+    pVar = p->pVars->pData + p->pVars->iCur;
+    p->pVars->iCur += sizeof(Tas_Var_t);
+    memset( pVar, 0, sizeof(Tas_Var_t) );
+    pVar->Id = pVar - ((Tas_Var_t *)p->pVars->pData);
+    return pVar;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Tas_Var_t * Tas_ManObj2Var( Tas_Man_t * p, Gia_Obj_t * pObj )
+{
+    Tas_Var_t * pVar;
+    assert( !Gia_ObjIsComplement(pObj) );
+    if ( pObj->Value == 0 )
+    {
+        pVar = Tas_ManCreateVar( p );
+        pVar->
+
+    }
+    return Tas_ManVar( p, pObj->Value );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaCex.c b/abc-build/src/aig/gia/giaCex.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaCex.c
@@ -0,0 +1,392 @@
+/**CFile****************************************************************
+
+  FileName    [giaAbs.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Counter-example-guided abstraction refinement.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaAbs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulates the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManVerifyCex( Gia_Man_t * pAig, Abc_Cex_t * p, int fDualOut )
+{
+    Gia_Obj_t * pObj, * pObjRi, * pObjRo;
+    int RetValue, i, k, iBit = 0;
+    Gia_ManCleanMark0(pAig);
+    Gia_ManForEachRo( pAig, pObj, i )
+        pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++);
+    for ( i = 0; i <= p->iFrame; i++ )
+    {
+        Gia_ManForEachPi( pAig, pObj, k )
+            pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++);
+        Gia_ManForEachAnd( pAig, pObj, k )
+            pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & 
+                           (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+        Gia_ManForEachCo( pAig, pObj, k )
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+        if ( i == p->iFrame )
+            break;
+        Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, k )
+        {
+            pObjRo->fMark0 = pObjRi->fMark0;
+        }
+    }
+    assert( iBit == p->nBits );
+    if ( fDualOut )
+        RetValue = Gia_ManPo(pAig, 2*p->iPo)->fMark0 ^ Gia_ManPo(pAig, 2*p->iPo+1)->fMark0;
+    else
+        RetValue = Gia_ManPo(pAig, p->iPo)->fMark0;
+    Gia_ManCleanMark0(pAig);
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulates the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManFindFailedPoCex( Gia_Man_t * pAig, Abc_Cex_t * p, int nOutputs )
+{
+    Gia_Obj_t * pObj, * pObjRi, * pObjRo;
+    int RetValue, i, k, iBit = 0;
+    assert( Gia_ManPiNum(pAig) == p->nPis );
+    Gia_ManCleanMark0(pAig);
+//    Gia_ManForEachRo( pAig, pObj, i )
+//       pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++);
+    iBit = p->nRegs;
+    for ( i = 0; i <= p->iFrame; i++ )
+    {
+        Gia_ManForEachPi( pAig, pObj, k )
+            pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++);
+        Gia_ManForEachAnd( pAig, pObj, k )
+            pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & 
+                           (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+        Gia_ManForEachCo( pAig, pObj, k )
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+        Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, k )
+            pObjRo->fMark0 = pObjRi->fMark0;
+    }
+    assert( iBit == p->nBits );
+    // figure out the number of failed output
+    RetValue = -1;
+//	for ( i = Gia_ManPoNum(pAig) - 1; i >= nOutputs; i-- )
+	for ( i = nOutputs; i < Gia_ManPoNum(pAig); i++ )
+	{
+        if ( Gia_ManPo(pAig, i)->fMark0 )
+        {
+            RetValue = i;
+            break;
+        }
+	}
+    Gia_ManCleanMark0(pAig);
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determines the failed PO when its exact frame is not known.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManSetFailedPoCex( Gia_Man_t * pAig, Abc_Cex_t * p )
+{
+    Gia_Obj_t * pObj, * pObjRi, * pObjRo;
+    int i, k, iBit = 0;
+    assert( Gia_ManPiNum(pAig) == p->nPis );
+    Gia_ManCleanMark0(pAig);
+    p->iPo = -1;
+//    Gia_ManForEachRo( pAig, pObj, i )
+//       pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++);
+    iBit = p->nRegs;
+    for ( i = 0; i <= p->iFrame; i++ )
+    {
+        Gia_ManForEachPi( pAig, pObj, k )
+            pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++);
+        Gia_ManForEachAnd( pAig, pObj, k )
+            pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & 
+                           (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+        Gia_ManForEachCo( pAig, pObj, k )
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+        Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, k )
+            pObjRo->fMark0 = pObjRi->fMark0;
+        // check the POs
+        Gia_ManForEachPo( pAig, pObj, k )
+	    {
+            if ( !pObj->fMark0 )
+                continue;
+            p->iPo = k;
+            p->iFrame = i;
+            p->nBits = iBit;
+            break;
+	    }
+    }
+    Gia_ManCleanMark0(pAig);
+    return p->iPo;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the process of returning values for internal nodes.]
+
+  Description [Should be called when pCex is available, before probing 
+  any object for its value using Gia_ManCounterExampleValueLookup().]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCounterExampleValueStart( Gia_Man_t * pGia, Abc_Cex_t * pCex )
+{
+    Gia_Obj_t * pObj, * pObjRi, * pObjRo;
+    int Val0, Val1, nObjs, i, k, iBit = 0;
+    assert( Gia_ManRegNum(pGia) > 0 ); // makes sense only for sequential AIGs
+    assert( pGia->pData2 == NULL );    // if this fail, there may be a memory leak
+    // allocate memory to store simulation bits for internal nodes
+    pGia->pData2 = ABC_CALLOC( unsigned, Abc_BitWordNum( (pCex->iFrame + 1) * Gia_ManObjNum(pGia) ) );
+    // the register values in the counter-example should be zero
+    Gia_ManForEachRo( pGia, pObj, k )
+        assert( Abc_InfoHasBit(pCex->pData, iBit++) == 0 );
+    // iterate through the timeframes
+    nObjs = Gia_ManObjNum(pGia);
+    for ( i = 0; i <= pCex->iFrame; i++ )
+    {
+        // no need to set constant-0 node
+        // set primary inputs according to the counter-example
+        Gia_ManForEachPi( pGia, pObj, k )
+            if ( Abc_InfoHasBit(pCex->pData, iBit++) )
+                Abc_InfoSetBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjId(pGia, pObj) );
+        // compute values for each node
+        Gia_ManForEachAnd( pGia, pObj, k )
+        {
+            Val0 = Abc_InfoHasBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjFaninId0p(pGia, pObj) );
+            Val1 = Abc_InfoHasBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjFaninId1p(pGia, pObj) );
+            if ( (Val0 ^ Gia_ObjFaninC0(pObj)) & (Val1 ^ Gia_ObjFaninC1(pObj)) )
+                Abc_InfoSetBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjId(pGia, pObj) );
+        }
+        // derive values for combinational outputs
+        Gia_ManForEachCo( pGia, pObj, k )
+        {
+            Val0 = Abc_InfoHasBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjFaninId0p(pGia, pObj) );
+            if ( Val0 ^ Gia_ObjFaninC0(pObj) )
+                Abc_InfoSetBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjId(pGia, pObj) );
+        }
+        if ( i == pCex->iFrame )
+            continue;
+        // transfer values to the register output of the next frame
+        Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, k )
+            if ( Abc_InfoHasBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjId(pGia, pObjRi) ) )
+                Abc_InfoSetBit( (unsigned *)pGia->pData2, nObjs * (i+1) + Gia_ObjId(pGia, pObjRo) );
+    }
+    assert( iBit == pCex->nBits );
+    // check that the counter-example is correct, that is, the corresponding output is asserted
+    assert( Abc_InfoHasBit( (unsigned *)pGia->pData2, nObjs * pCex->iFrame + Gia_ObjId(pGia, Gia_ManCo(pGia, pCex->iPo)) ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the process of returning values for internal nodes.]
+
+  Description [Should be called when probing is no longer needed]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCounterExampleValueStop( Gia_Man_t * pGia )
+{
+    assert( pGia->pData2 != NULL );    // if this fail, we try to call this procedure more than once
+    ABC_FREE( pGia->pData2 );
+    pGia->pData2 = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the value of the given object in the given timeframe.]
+
+  Description [Should be called to probe the value of an object with 
+  the given ID (iFrame is a 0-based number of a time frame - should not 
+  exceed the number of timeframes in the original counter-example).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCounterExampleValueLookup(  Gia_Man_t * pGia, int Id, int iFrame )
+{
+    assert( Id >= 0 && Id < Gia_ManObjNum(pGia) );
+    return Abc_InfoHasBit( (unsigned *)pGia->pData2, Gia_ManObjNum(pGia) * iFrame + Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure to test the above code.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCounterExampleValueTest( Gia_Man_t * pGia, Abc_Cex_t * pCex )
+{
+    Gia_Obj_t * pObj = Gia_ManObj( pGia, Gia_ManObjNum(pGia)/2 );
+    int iFrame = Abc_MaxInt( 0, pCex->iFrame - 1 );
+    printf( "\nUsing counter-example, which asserts output %d in frame %d.\n", pCex->iPo, pCex->iFrame );
+    Gia_ManCounterExampleValueStart( pGia, pCex );
+    printf( "Value of object %d in frame %d is %d.\n", Gia_ObjId(pGia, pObj), iFrame,
+        Gia_ManCounterExampleValueLookup(pGia, Gia_ObjId(pGia, pObj), iFrame) );
+    Gia_ManCounterExampleValueStop( pGia );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns CEX containing PI+CS values for each timeframe.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Gia_ManCexExtendToIncludeCurrentStates( Gia_Man_t * p, Abc_Cex_t * pCex )
+{
+    Abc_Cex_t * pNew;
+    Gia_Obj_t * pObj, * pObjRo, * pObjRi;
+    int i, k, iBit = 0;
+    assert( pCex->nRegs > 0 );
+    // start the counter-example
+    pNew = Abc_CexAlloc( 0, Gia_ManCiNum(p), pCex->iFrame + 1 );
+    pNew->iFrame = pCex->iFrame;
+    pNew->iPo    = pCex->iPo;
+    // set const0
+    Gia_ManConst0(p)->fMark0 = 0;
+    // set init state
+    Gia_ManForEachRi( p, pObjRi, k )
+        pObjRi->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++);
+    assert( iBit == pCex->nRegs );
+    for ( i = 0; i <= pCex->iFrame; i++ )
+    {
+        Gia_ManForEachPi( p, pObj, k )
+            pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++);
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
+            pObjRo->fMark0 = pObjRi->fMark0;
+        Gia_ManForEachCi( p, pObj, k )
+            if ( pObj->fMark0 )
+                Abc_InfoSetBit( pNew->pData, pNew->nPis * i + k );
+        Gia_ManForEachAnd( p, pObj, k )
+            pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+        Gia_ManForEachCo( p, pObj, k )
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+    }
+    assert( iBit == pCex->nBits );
+    assert( Gia_ManPo(p, pCex->iPo)->fMark0 == 1 );
+    Gia_ManCleanMark0(p);
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns CEX containing all object valuess for each timeframe.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Gia_ManCexExtendToIncludeAllObjects( Gia_Man_t * p, Abc_Cex_t * pCex )
+{
+    Abc_Cex_t * pNew;
+    Gia_Obj_t * pObj, * pObjRo, * pObjRi;
+    int i, k, iBit = 0;
+    assert( pCex->nRegs > 0 );
+    // start the counter-example
+    pNew = Abc_CexAlloc( 0, Gia_ManObjNum(p), pCex->iFrame + 1 );
+    pNew->iFrame = pCex->iFrame;
+    pNew->iPo    = pCex->iPo;
+    // set const0
+    Gia_ManConst0(p)->fMark0 = 0;
+    // set init state
+    Gia_ManForEachRi( p, pObjRi, k )
+        pObjRi->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++);
+    assert( iBit == pCex->nRegs );
+    for ( i = 0; i <= pCex->iFrame; i++ )
+    {
+        Gia_ManForEachPi( p, pObj, k )
+            pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++);
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
+            pObjRo->fMark0 = pObjRi->fMark0;
+        Gia_ManForEachObj( p, pObj, k )
+            if ( pObj->fMark0 )
+                Abc_InfoSetBit( pNew->pData, pNew->nPis * i + k );
+        Gia_ManForEachAnd( p, pObj, k )
+            pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+        Gia_ManForEachCo( p, pObj, k )
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+    }
+    assert( iBit == pCex->nBits );
+    assert( Gia_ManPo(p, pCex->iPo)->fMark0 == 1 );
+    Gia_ManCleanMark0(p);
+    return pNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaCof.c b/abc-build/src/aig/gia/giaCof.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaCof.c
@@ -0,0 +1,1002 @@
+/**CFile****************************************************************
+
+  FileName    [giaCof.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Cofactor estimation procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaCof.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <math.h>
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Cof_Fan_t_ Cof_Fan_t;
+struct Cof_Fan_t_
+{
+    unsigned       iFan     : 31;    // ID of the fanin/fanout
+    unsigned       fCompl   :  1;    // complemented attribute
+};
+
+typedef struct Cof_Obj_t_ Cof_Obj_t;
+struct Cof_Obj_t_
+{
+    unsigned       fTerm    :  1;    // terminal node (CI/CO)
+    unsigned       fPhase   :  1;    // value under 000 pattern
+    unsigned       fMark0   :  1;    // first user-controlled mark
+    unsigned       fMark1   :  1;    // second user-controlled mark
+    unsigned       nFanins  :  4;    // the number of fanins
+    unsigned       nFanouts : 24;    // total number of fanouts
+    unsigned       nFanoutsM;        // total number of MUX ctrl fanouts
+    unsigned       Value;            // application specific data
+    int            Id;               // ID of the node
+    int            iNext;            // next one in the linked list
+    int            iLit;             // literal of the node after rehashing
+    Cof_Fan_t      Fanios[0];        // the array of fanins/fanouts
+};
+
+typedef struct Cof_Man_t_ Cof_Man_t;
+struct Cof_Man_t_
+{
+    Gia_Man_t *    pGia;             // the original AIG manager
+    Vec_Int_t *    vCis;             // the vector of CIs (PIs + LOs)
+    Vec_Int_t *    vCos;             // the vector of COs (POs + LIs)
+    int            nObjs;            // the number of objects
+    int            nNodes;           // the number of nodes
+    int            nTravIds;         // traversal ID of the network
+    int *          pObjData;         // the logic network defined for the AIG
+    int            nObjData;         // the size of array to store the logic network
+    int *          pLevels;          // the linked lists of levels
+    int            nLevels;          // the max number of logic levels
+};
+
+static inline unsigned    Gia_ObjHandle( Gia_Obj_t * pObj )                           { return pObj->Value;                                 } 
+
+static inline int         Cof_ObjLevel( Cof_Man_t * p, Cof_Obj_t * pObj )             { return Gia_ObjLevel(p->pGia, Gia_ManObj(p->pGia,pObj->Id)); } 
+
+static inline unsigned    Cof_ObjHandle( Cof_Man_t * p, Cof_Obj_t * pObj )            { return (unsigned)(((int *)pObj) - p->pObjData);     } 
+static inline unsigned    Cof_ObjHandleDiff( Cof_Obj_t * pObj, Cof_Obj_t * pFanin )   { return (unsigned)(((int *)pObj) - ((int *)pFanin)); } 
+
+static inline int         Cof_ObjIsTerm( Cof_Obj_t * pObj )                           { return pObj->fTerm;                                 } 
+static inline int         Cof_ObjIsCi( Cof_Obj_t * pObj )                             { return pObj->fTerm && pObj->nFanins == 0;           } 
+static inline int         Cof_ObjIsCo( Cof_Obj_t * pObj )                             { return pObj->fTerm && pObj->nFanins == 1;           } 
+static inline int         Cof_ObjIsNode( Cof_Obj_t * pObj )                           { return!pObj->fTerm && pObj->nFanins > 0;            } 
+static inline int         Cof_ObjIsConst0( Cof_Obj_t * pObj )                         { return!pObj->fTerm && pObj->nFanins == 0;           } 
+
+static inline int         Cof_ObjFaninNum( Cof_Obj_t * pObj )                         { return pObj->nFanins;                               } 
+static inline int         Cof_ObjFanoutNum( Cof_Obj_t * pObj )                        { return pObj->nFanouts;                              } 
+static inline int         Cof_ObjSize( Cof_Obj_t * pObj )                             { return sizeof(Cof_Obj_t) / 4 + pObj->nFanins + pObj->nFanouts;  } 
+
+static inline Cof_Obj_t * Cof_ManObj( Cof_Man_t * p, unsigned iHandle )               { return (Cof_Obj_t *)(p->pObjData + iHandle);        } 
+static inline Cof_Obj_t * Cof_ObjFanin( Cof_Obj_t * pObj, int i )                     { return (Cof_Obj_t *)(((int *)pObj) - pObj->Fanios[i].iFan);               } 
+static inline Cof_Obj_t * Cof_ObjFanout( Cof_Obj_t * pObj, int i )                    { return (Cof_Obj_t *)(((int *)pObj) + pObj->Fanios[pObj->nFanins+i].iFan); } 
+
+static inline int         Cof_ManObjNum( Cof_Man_t * p )                              { return p->nObjs;                                    } 
+static inline int         Cof_ManNodeNum( Cof_Man_t * p )                             { return p->nNodes;                                   } 
+
+static inline void        Cof_ManResetTravId( Cof_Man_t * p )                         { extern void Cof_ManCleanValue( Cof_Man_t * p ); Cof_ManCleanValue( p ); p->nTravIds = 1;  }
+static inline void        Cof_ManIncrementTravId( Cof_Man_t * p )                     { p->nTravIds++;                                      }
+static inline void        Cof_ObjSetTravId( Cof_Obj_t * pObj, int TravId )            { pObj->Value = TravId;                               }
+static inline void        Cof_ObjSetTravIdCurrent( Cof_Man_t * p, Cof_Obj_t * pObj )  { pObj->Value = p->nTravIds;                          }
+static inline void        Cof_ObjSetTravIdPrevious( Cof_Man_t * p, Cof_Obj_t * pObj ) { pObj->Value = p->nTravIds - 1;                      }
+static inline int         Cof_ObjIsTravIdCurrent( Cof_Man_t * p, Cof_Obj_t * pObj )   { return ((int)pObj->Value == p->nTravIds);           }
+static inline int         Cof_ObjIsTravIdPrevious( Cof_Man_t * p, Cof_Obj_t * pObj )  { return ((int)pObj->Value == p->nTravIds - 1);       }
+
+#define Cof_ManForEachObj( p, pObj, i )               \
+    for ( i = 0; (i < p->nObjData) && (pObj = Cof_ManObj(p,i)); i += Cof_ObjSize(pObj) )
+#define Cof_ManForEachNode( p, pObj, i )              \
+    for ( i = 0; (i < p->nObjData) && (pObj = Cof_ManObj(p,i)); i += Cof_ObjSize(pObj) ) if ( Cof_ObjIsTerm(pObj) ) {} else
+#define Cof_ObjForEachFanin( pObj, pNext, i )         \
+    for ( i = 0; (i < (int)pObj->nFanins) && (pNext = Cof_ObjFanin(pObj,i)); i++ )
+#define Cof_ObjForEachFanout( pObj, pNext, i )        \
+    for ( i = 0; (i < (int)pObj->nFanouts) && (pNext = Cof_ObjFanout(pObj,i)); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates logic network isomorphic to the given AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cof_Man_t * Cof_ManCreateLogicSimple( Gia_Man_t * pGia )
+{
+    Cof_Man_t * p;
+    Cof_Obj_t * pObjLog, * pFanLog;
+    Gia_Obj_t * pObj;
+    int * pMuxRefs;
+    int i, iHandle = 0;
+    p = ABC_CALLOC( Cof_Man_t, 1 );
+    p->pGia = pGia;
+    p->vCis = Vec_IntAlloc( Gia_ManCiNum(pGia) );
+    p->vCos = Vec_IntAlloc( Gia_ManCoNum(pGia) );
+    p->nObjData = (sizeof(Cof_Obj_t) / 4) * Gia_ManObjNum(pGia) + 4 * Gia_ManAndNum(pGia) + 2 * Gia_ManCoNum(pGia);
+    p->pObjData = ABC_CALLOC( int, p->nObjData );
+    ABC_FREE( pGia->pRefs );
+    Gia_ManCreateRefs( pGia );
+    Gia_ManForEachObj( pGia, pObj, i )
+    {
+        pObj->Value = iHandle;
+        pObjLog = Cof_ManObj( p, iHandle );
+        pObjLog->nFanins  = 0;
+        pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj );
+        pObjLog->Id       = i;
+        pObjLog->Value    = 0;
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            pFanLog = Cof_ManObj( p, Gia_ObjHandle(Gia_ObjFanin0(pObj)) ); 
+            pFanLog->Fanios[pFanLog->nFanins + pFanLog->Value++].iFan = 
+                pObjLog->Fanios[pObjLog->nFanins].iFan = Cof_ObjHandleDiff( pObjLog, pFanLog );
+            pObjLog->Fanios[pObjLog->nFanins++].fCompl = Gia_ObjFaninC0(pObj);
+
+            pFanLog = Cof_ManObj( p, Gia_ObjHandle(Gia_ObjFanin1(pObj)) ); 
+            pFanLog->Fanios[pFanLog->nFanins + pFanLog->Value++].iFan = 
+                pObjLog->Fanios[pObjLog->nFanins].iFan = Cof_ObjHandleDiff( pObjLog, pFanLog );
+            pObjLog->Fanios[pObjLog->nFanins++].fCompl = Gia_ObjFaninC1(pObj);
+            p->nNodes++;
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+        {
+            pFanLog = Cof_ManObj( p, Gia_ObjHandle(Gia_ObjFanin0(pObj)) ); 
+            pFanLog->Fanios[pFanLog->nFanins + pFanLog->Value++].iFan = 
+                pObjLog->Fanios[pObjLog->nFanins].iFan = Cof_ObjHandleDiff( pObjLog, pFanLog );
+            pObjLog->Fanios[pObjLog->nFanins++].fCompl = Gia_ObjFaninC0(pObj);
+
+            pObjLog->fTerm = 1;
+            Vec_IntPush( p->vCos, iHandle );
+        }
+        else if ( Gia_ObjIsCi(pObj) )
+        {
+            pObjLog->fTerm = 1;
+            Vec_IntPush( p->vCis, iHandle );
+        }
+        iHandle += Cof_ObjSize( pObjLog );
+        p->nObjs++;
+    }
+    assert( iHandle == p->nObjData );
+    pMuxRefs = Gia_ManCreateMuxRefs( pGia );
+    Gia_ManForEachObj( pGia, pObj, i )
+    {
+        pObjLog = Cof_ManObj( p, Gia_ObjHandle(pObj) );
+        assert( pObjLog->nFanouts == pObjLog->Value );
+        pObjLog->nFanoutsM = pMuxRefs[i];
+    }
+    ABC_FREE( pMuxRefs );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates logic network isomorphic to the given AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cof_ManStop( Cof_Man_t * p )
+{
+    Vec_IntFree( p->vCis );
+    Vec_IntFree( p->vCos );
+    ABC_FREE( p->pObjData );
+    ABC_FREE( p->pLevels );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects support nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cof_ManTfoSize_rec( Cof_Man_t * p, Cof_Obj_t * pObj )
+{
+    Cof_Obj_t * pNext;
+    unsigned i, Counter = 0;
+    if ( Cof_ObjIsTravIdCurrent(p, pObj) )
+        return 0;
+    Cof_ObjSetTravIdCurrent(p, pObj);
+    if ( Cof_ObjIsCo(pObj) )
+        return 0;
+    assert( Cof_ObjIsCi(pObj) || Cof_ObjIsNode(pObj) );
+    Cof_ObjForEachFanout( pObj, pNext, i )
+        Counter += Cof_ManTfoSize_rec( p, pNext );
+    return 1 + Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects support nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cof_ManTfoSize( Cof_Man_t * p, Cof_Obj_t ** ppObjs, int nObjs )
+{
+    int i, Counter = 0; 
+    Cof_ManIncrementTravId( p );
+    for ( i = 0; i < nObjs; i++ )
+        Counter += Cof_ManTfoSize_rec( p, ppObjs[i] ) - 1;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects support nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cof_ManTfiSize_rec( Cof_Man_t * p, Cof_Obj_t * pObj )
+{
+    Cof_Obj_t * pNext;
+    unsigned i, Counter = 0;
+    if ( Cof_ObjIsTravIdCurrent(p, pObj) )
+        return 0;
+    Cof_ObjSetTravIdCurrent(p, pObj);
+    if ( Cof_ObjIsCi(pObj) )
+        return 0;
+    assert( Cof_ObjIsNode(pObj) );
+    Cof_ObjForEachFanin( pObj, pNext, i )
+        Counter += Cof_ManTfiSize_rec( p, pNext );
+    return 1 + Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects support nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cof_ManTfiSize( Cof_Man_t * p, Cof_Obj_t ** ppObjs, int nObjs )
+{
+    int i, Counter = 0; 
+    Cof_ManIncrementTravId( p );
+    for ( i = 0; i < nObjs; i++ )
+        if ( Cof_ObjIsCo(ppObjs[i]) )
+            Counter += Cof_ManTfiSize_rec( p, Cof_ObjFanin(ppObjs[i],0) );
+        else
+            Counter += Cof_ManTfiSize_rec( p, ppObjs[i] );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects support nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cof_ManSuppSize_rec( Cof_Man_t * p, Cof_Obj_t * pObj )
+{
+    Cof_Obj_t * pNext;
+    unsigned i, Counter = 0;
+    if ( Cof_ObjIsTravIdCurrent(p, pObj) )
+        return 0;
+    Cof_ObjSetTravIdCurrent(p, pObj);
+    if ( Cof_ObjIsCi(pObj) )
+        return 1;
+    assert( Cof_ObjIsNode(pObj) );
+    Cof_ObjForEachFanin( pObj, pNext, i )
+        Counter += Cof_ManSuppSize_rec( p, pNext );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects support nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cof_ManSuppSize( Cof_Man_t * p, Cof_Obj_t ** ppObjs, int nObjs )
+{
+    int i, Counter = 0; 
+    Cof_ManIncrementTravId( p );
+    for ( i = 0; i < nObjs; i++ )
+        if ( Cof_ObjIsCo(ppObjs[i]) )
+            Counter += Cof_ManSuppSize_rec( p, Cof_ObjFanin(ppObjs[i],0) );
+        else
+            Counter += Cof_ManSuppSize_rec( p, ppObjs[i] );
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cof_ManCleanValue( Cof_Man_t * p )  
+{
+    Cof_Obj_t * pObj;
+    int i;
+    Cof_ManForEachObj( p, pObj, i )
+        pObj->Value = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns sorted array of node handles with largest fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cof_ManInsertEntry_rec( Vec_Ptr_t * vNodes, Cof_Obj_t * pNode, int nNodeMax )
+{
+    Cof_Obj_t * pLast;
+    if ( Vec_PtrSize(vNodes) == 0 )
+    {
+        Vec_PtrPush(vNodes, pNode);
+        return;
+    }
+    pLast = (Cof_Obj_t *)Vec_PtrPop(vNodes);
+    if ( Cof_ObjFanoutNum(pLast) < Cof_ObjFanoutNum(pNode) )
+    {
+        Cof_ManInsertEntry_rec( vNodes, pNode, nNodeMax );
+        if ( Vec_PtrSize(vNodes) < nNodeMax )
+            Vec_PtrPush( vNodes, pLast );
+    }
+    else
+    {
+        Vec_PtrPush( vNodes, pLast );
+        if ( Vec_PtrSize(vNodes) < nNodeMax )
+            Vec_PtrPush( vNodes, pNode );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns sorted array of node handles with largest fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Cof_ManCollectHighFanout( Cof_Man_t * p, int nNodes )
+{
+    Vec_Ptr_t * vNodes;
+    Cof_Obj_t * pObj;
+    int i;
+    vNodes = Vec_PtrAlloc( nNodes );
+    Cof_ManForEachObj( p, pObj, i )
+        if ( Cof_ObjIsCi(pObj) || Cof_ObjIsNode(pObj) )
+            Cof_ManInsertEntry_rec( vNodes, pObj, nNodes );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns sorted array of node handles with largest fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cof_ManCountRemoved( Cof_Man_t * p, Cof_Obj_t * pRoot, int fConst1 )
+{
+    Gia_Obj_t * pNextGia;
+    Cof_Obj_t * pTemp, * pNext, * pFanin0, * pFanin1;
+    int Counter = 0, LevelStart, LevelNext;
+    int i, k, iHandle, iLit0, iLit1, iNextNew;
+    // restart the trav ids
+    Cof_ManIncrementTravId( p );
+    Cof_ObjSetTravIdCurrent( p, pRoot );
+    // add the node to the queue
+    LevelStart = Cof_ObjLevel(p, pRoot);
+    assert( p->pLevels[LevelStart] == 0 );
+    pRoot->iNext = 0;
+    p->pLevels[LevelStart] = Cof_ObjHandle( p, pRoot );
+    // set the new literal
+    pRoot->iLit = Abc_Var2Lit( 0, fConst1 );
+    // process nodes in the levelized order
+    for ( i = LevelStart; i < p->nLevels; i++ )
+    {
+        for ( iHandle = p->pLevels[i]; 
+              iHandle && (pTemp = Cof_ManObj(p, iHandle)); 
+              iHandle = pTemp->iNext )
+        {
+            assert( pTemp->Id != Abc_Lit2Var(pTemp->iLit) );
+            Cof_ObjForEachFanout( pTemp, pNext, k )
+            {
+                if ( Cof_ObjIsCo(pNext) )
+                    continue;
+                if ( Cof_ObjIsTravIdCurrent(p, pNext) )
+                    continue;
+                pFanin0 = Cof_ObjFanin( pNext, 0 );
+                pFanin1 = Cof_ObjFanin( pNext, 1 );
+                assert( pFanin0 == pTemp || pFanin1 == pTemp );
+                pNextGia = Gia_ManObj( p->pGia, pNext->Id );
+                if ( Cof_ObjIsTravIdCurrent(p, pFanin0) )
+                    iLit0 = Abc_LitNotCond( pFanin0->iLit, Gia_ObjFaninC0(pNextGia) );
+                else
+                    iLit0 = Gia_ObjFaninLit0( pNextGia, pNext->Id );
+                if ( Cof_ObjIsTravIdCurrent(p, pFanin1) )
+                    iLit1 = Abc_LitNotCond( pFanin1->iLit, Gia_ObjFaninC1(pNextGia) );
+                else
+                    iLit1 = Gia_ObjFaninLit1( pNextGia, pNext->Id );
+                iNextNew = Gia_ManHashAndTry( p->pGia, iLit0, iLit1 );
+                if ( iNextNew == -1 )
+                    continue;
+                Cof_ObjSetTravIdCurrent(p, pNext);
+                // set the new literal
+                pNext->iLit = iNextNew;
+                // add it to be processed
+                LevelNext = Cof_ObjLevel( p, pNext );
+                assert( LevelNext > i && LevelNext < p->nLevels );
+                pNext->iNext = p->pLevels[LevelNext];
+                p->pLevels[LevelNext] = Cof_ObjHandle( p, pNext );
+                Counter++;
+            }
+        }
+        p->pLevels[i] = 0;
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns sorted array of node handles with largest fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cof_ManPrintHighFanoutOne( Cof_Man_t * p, Cof_Obj_t * pObj )
+{
+    printf( "%7d : ",     pObj->Id );
+    printf( "i/o/c =%2d %5d %5d  ",  Cof_ObjFaninNum(pObj), Cof_ObjFanoutNum(pObj), 2*pObj->nFanoutsM );
+    printf( "l =%4d  ",   Cof_ObjLevel(p, pObj) );
+    printf( "s =%5d  ",   Cof_ManSuppSize(p, &pObj, 1) );
+    printf( "TFI =%7d  ", Cof_ManTfiSize(p, &pObj, 1) );
+    printf( "TFO =%7d  ", Cof_ManTfoSize(p, &pObj, 1) );
+    printf( "C0 =%6d  ",  Cof_ManCountRemoved(p, pObj, 0) );
+    printf( "C1 =%6d",    Cof_ManCountRemoved(p, pObj, 1) );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns sorted array of node handles with largest fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cof_ManPrintHighFanout( Cof_Man_t * p, int nNodes )
+{
+    Vec_Ptr_t * vNodes;
+    Cof_Obj_t * pObj;
+    int i;
+    vNodes = Cof_ManCollectHighFanout( p, nNodes );
+    Vec_PtrForEachEntry( Cof_Obj_t *, vNodes, pObj, i )
+        Cof_ManPrintHighFanoutOne( p, pObj );
+    Vec_PtrFree( vNodes );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compute MFFC size of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cof_NodeDeref_rec( Cof_Obj_t * pNode )
+{
+    if ( pNode->nFanins == 0 )
+        return 0;
+    if ( --pNode->nFanouts > 0 )
+        return 0;
+    return 1 + Cof_NodeDeref_rec( Cof_ObjFanin(pNode, 0) )
+             + Cof_NodeDeref_rec( Cof_ObjFanin(pNode, 1) );
+}
+int Cof_NodeRef_rec( Cof_Obj_t * pNode )
+{
+    if ( pNode->nFanins == 0 )
+        return 0;
+    if ( pNode->nFanouts++ > 0 )
+        return 0;
+    return 1 + Cof_NodeRef_rec( Cof_ObjFanin(pNode, 0) )
+             + Cof_NodeRef_rec( Cof_ObjFanin(pNode, 1) );
+}
+static inline int Cof_ObjMffcSize( Cof_Obj_t * pNode )
+{
+    int Count1, Count2, nFanout;
+    nFanout = pNode->nFanouts;
+    pNode->nFanouts = 1;
+    Count1 = Cof_NodeDeref_rec( pNode );
+    Count2 = Cof_NodeRef_rec( pNode );
+    pNode->nFanouts = nFanout;
+    assert( Count1 == Count2 );
+    return Count1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the distribution of fanins/fanouts in the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cof_ManPrintFanio( Cof_Man_t * p )
+{
+    char Buffer[100];
+    Cof_Obj_t * pNode;
+    Vec_Int_t * vFanins, * vFanouts, * vMffcs;
+    int nFanins, nFanouts, nMffcs, nFaninsMax, nFanoutsMax, nMffcsMax, nFaninsAll, nFanoutsAll, nMffcsAll;
+    int i, k, nSizeMax, nMffcNodes = 0;
+
+    // determine the largest fanin and fanout
+    nFaninsMax = nFanoutsMax = nMffcsMax = 0;
+    nFaninsAll = nFanoutsAll = nMffcsAll = 0;
+    Cof_ManForEachNode( p, pNode, i )
+    {
+        if ( i == 0 ) continue;
+        nFanins  = Cof_ObjFaninNum(pNode);
+        nFanouts = Cof_ObjFanoutNum(pNode);
+        nMffcs   = pNode->nFanouts > 1 ? Cof_ObjMffcSize(pNode) : 0;
+        nFaninsAll  += nFanins;
+        nFanoutsAll += nFanouts;
+        nMffcsAll   += nMffcs;
+        nFaninsMax   = Abc_MaxInt( nFaninsMax,  nFanins );
+        nFanoutsMax  = Abc_MaxInt( nFanoutsMax, nFanouts );
+        nMffcsMax    = Abc_MaxInt( nMffcsMax,   nMffcs );
+    }
+
+    // allocate storage for fanin/fanout numbers
+    nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nFaninsMax) + 1), 10 * (Abc_Base10Log(nFanoutsMax) + 1) );
+    nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nMffcsMax) + 1),  nSizeMax );
+    vFanins  = Vec_IntStart( nSizeMax );
+    vFanouts = Vec_IntStart( nSizeMax );
+    vMffcs   = Vec_IntStart( nSizeMax );
+
+    // count the number of fanins and fanouts
+    Cof_ManForEachNode( p, pNode, i )
+    {
+        if ( i == 0 ) continue;
+        nFanins  = Cof_ObjFaninNum(pNode);
+        nFanouts = Cof_ObjFanoutNum(pNode);
+        nMffcs   = pNode->nFanouts > 1 ? Cof_ObjMffcSize(pNode) : 0;
+
+        if ( nFanins < 10 )
+            Vec_IntAddToEntry( vFanins, nFanins, 1 );
+        else if ( nFanins < 100 )
+            Vec_IntAddToEntry( vFanins, 10 + nFanins/10, 1 );
+        else if ( nFanins < 1000 )
+            Vec_IntAddToEntry( vFanins, 20 + nFanins/100, 1 );
+        else if ( nFanins < 10000 )
+            Vec_IntAddToEntry( vFanins, 30 + nFanins/1000, 1 );
+        else if ( nFanins < 100000 )
+            Vec_IntAddToEntry( vFanins, 40 + nFanins/10000, 1 );
+        else if ( nFanins < 1000000 )
+            Vec_IntAddToEntry( vFanins, 50 + nFanins/100000, 1 );
+        else if ( nFanins < 10000000 )
+            Vec_IntAddToEntry( vFanins, 60 + nFanins/1000000, 1 );
+
+        if ( nFanouts < 10 )
+            Vec_IntAddToEntry( vFanouts, nFanouts, 1 );
+        else if ( nFanouts < 100 )
+            Vec_IntAddToEntry( vFanouts, 10 + nFanouts/10, 1 );
+        else if ( nFanouts < 1000 )
+            Vec_IntAddToEntry( vFanouts, 20 + nFanouts/100, 1 );
+        else if ( nFanouts < 10000 )
+            Vec_IntAddToEntry( vFanouts, 30 + nFanouts/1000, 1 );
+        else if ( nFanouts < 100000 )
+            Vec_IntAddToEntry( vFanouts, 40 + nFanouts/10000, 1 );
+        else if ( nFanouts < 1000000 )
+            Vec_IntAddToEntry( vFanouts, 50 + nFanouts/100000, 1 );
+        else if ( nFanouts < 10000000 )
+            Vec_IntAddToEntry( vFanouts, 60 + nFanouts/1000000, 1 );
+       
+        if ( nMffcs == 0 )
+            continue;
+        nMffcNodes++;
+
+        if ( nMffcs < 10 )
+            Vec_IntAddToEntry( vMffcs, nMffcs, 1 );
+        else if ( nMffcs < 100 )
+            Vec_IntAddToEntry( vMffcs, 10 + nMffcs/10, 1 );
+        else if ( nMffcs < 1000 )
+            Vec_IntAddToEntry( vMffcs, 20 + nMffcs/100, 1 );
+        else if ( nMffcs < 10000 )
+            Vec_IntAddToEntry( vMffcs, 30 + nMffcs/1000, 1 );
+        else if ( nMffcs < 100000 )
+            Vec_IntAddToEntry( vMffcs, 40 + nMffcs/10000, 1 );
+        else if ( nMffcs < 1000000 )
+            Vec_IntAddToEntry( vMffcs, 50 + nMffcs/100000, 1 );
+        else if ( nMffcs < 10000000 )
+            Vec_IntAddToEntry( vMffcs, 60 + nMffcs/1000000, 1 );
+    }
+
+    printf( "The distribution of fanins, fanouts. and MFFCs in the network:\n" );
+    printf( "         Number    Nodes with fanin   Nodes with fanout   Nodes with MFFC\n" );
+
+    for ( k = 0; k < nSizeMax; k++ )
+    {
+        if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 && vMffcs->pArray[k] == 0 )
+            continue;
+        if ( k < 10 )
+            printf( "%15d : ", k );
+        else
+        {
+            sprintf( Buffer, "%d - %d", (int)pow((double)10, k/10) * (k%10), (int)pow((double)10, k/10) * (k%10+1) - 1 ); 
+            printf( "%15s : ", Buffer );
+        }
+        if ( vFanins->pArray[k] == 0 )
+            printf( "              " );
+        else
+            printf( "%11d   ", vFanins->pArray[k] );
+        printf( "    " );
+        if ( vFanouts->pArray[k] == 0 )
+            printf( "              " );
+        else
+            printf( "%12d  ", vFanouts->pArray[k] );
+        printf( "    " );
+        if ( vMffcs->pArray[k] == 0 )
+            printf( "               " );
+        else
+            printf( "  %12d  ", vMffcs->pArray[k] );
+        printf( "\n" );
+    }
+    Vec_IntFree( vFanins );
+    Vec_IntFree( vFanouts );
+    Vec_IntFree( vMffcs );
+
+    printf( "Fanins: Max = %d. Ave = %.2f.  Fanouts: Max = %d. Ave =  %.2f.  MFFCs: Max = %d. Ave =  %.2f.\n", 
+        nFaninsMax,  1.0*nFaninsAll /Cof_ManNodeNum(p), 
+        nFanoutsMax, 1.0*nFanoutsAll/Cof_ManNodeNum(p), 
+        nMffcsMax,   1.0*nMffcsAll  /nMffcNodes  );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns sorted array of node handles with largest fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintFanio( Gia_Man_t * pGia, int nNodes )
+{
+    Cof_Man_t * p;
+    abctime clk = Abc_Clock();
+    p = Cof_ManCreateLogicSimple( pGia );
+    p->nLevels = 1 + Gia_ManLevelNum( pGia );
+    p->pLevels = ABC_CALLOC( int, p->nLevels );
+    Cof_ManPrintFanio( p );
+
+    if ( nNodes > 0 )
+    {
+    Cof_ManResetTravId( p );
+    Gia_ManHashStart( pGia );
+    Cof_ManPrintHighFanout( p, nNodes );
+    Gia_ManHashStop( pGia );
+ABC_PRMn( "Memory for logic network", 4*p->nObjData );
+ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+
+    Cof_ManStop( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order while putting CIs first.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupCofInt( Gia_Man_t * p, int iVar )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj, * pPivot;
+    int i, iCofVar = -1;
+    if ( !(iVar > 0 && iVar < Gia_ManObjNum(p)) )
+    {
+        printf( "Gia_ManDupCof(): Variable %d is out of range (%d; %d).\n", iVar, 0, Gia_ManObjNum(p) );
+        return NULL;
+    }
+    // find the cofactoring variable
+    pPivot = Gia_ManObj( p, iVar );
+    if ( !Gia_ObjIsCand(pPivot) )
+    {
+        printf( "Gia_ManDupCof(): Variable %d should be a CI or an AND node.\n", iVar );
+        return NULL;
+    }
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    // compute negative cofactor
+    Gia_ManForEachCi( p, pObj, i )
+    {
+        pObj->Value = Gia_ManAppendCi(pNew);
+        if ( pObj == pPivot )
+        {
+            iCofVar = pObj->Value;
+            pObj->Value = Abc_Var2Lit( 0, 0 );
+        }
+    }
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        if ( pObj == pPivot )
+        {
+            iCofVar = pObj->Value;
+            pObj->Value = Abc_Var2Lit( 0, 0 );
+        }
+    }
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->Value = Gia_ObjFanin0Copy(pObj);
+    // compute the positive cofactor
+    Gia_ManForEachCi( p, pObj, i )
+    {
+        pObj->Value = Abc_Var2Lit( Gia_ObjId(pNew, Gia_ManCi(pNew, i)), 0 );
+        if ( pObj == pPivot )
+            pObj->Value = Abc_Var2Lit( 0, 1 );
+    }
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        if ( pObj == pPivot )
+            pObj->Value = Abc_Var2Lit( 0, 1 );
+    }
+    // create MUXes
+    assert( iCofVar > 0 );
+    Gia_ManForEachCo( p, pObj, i )
+    {
+        if ( pObj->Value == (unsigned)Gia_ObjFanin0Copy(pObj) )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+        else
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ManHashMux(pNew, iCofVar, Gia_ObjFanin0Copy(pObj), pObj->Value) );
+    }
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order while putting CIs first.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupCof( Gia_Man_t * p, int iVar )
+{
+    Gia_Man_t * pNew, * pTemp;
+    pNew = Gia_ManDupCofInt( p, iVar );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Determines variables whose fanout count is higher than this.]
+
+  Description [Variables are returned in a reverse topological order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManCofVars( Gia_Man_t * p, int nFanLim )
+{
+    Vec_Int_t * vVars;
+    Gia_Obj_t * pObj;
+    int i;
+    ABC_FREE( p->pRefs );
+    Gia_ManCreateRefs( p );
+    vVars = Vec_IntAlloc( 100 );
+    Gia_ManForEachObj( p, pObj, i )
+        if ( Gia_ObjIsCand(pObj) && Gia_ObjRefNum(p, pObj) >= nFanLim )
+            Vec_IntPush( vVars, i );
+    ABC_FREE( p->pRefs );
+    return vVars;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers attributes from the original one to the final one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManTransfer( Gia_Man_t * pAig, Gia_Man_t * pCof, Gia_Man_t * pNew, Vec_Int_t * vSigs )
+{
+    Vec_Int_t * vSigsNew;
+    Gia_Obj_t * pObj, * pObjF;
+    int i;
+    vSigsNew = Vec_IntAlloc( 100 );
+    Gia_ManForEachObjVec( vSigs, pAig, pObj, i )
+    {
+        assert( Gia_ObjIsCand(pObj) );
+        pObjF = Gia_ManObj( pCof, Abc_Lit2Var(pObj->Value) );
+        if ( pObjF->Value && ~pObjF->Value )
+            Vec_IntPushUnique( vSigsNew, Abc_Lit2Var(pObjF->Value) );
+    }
+    return vSigsNew;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cofactors selected variables (should be in reverse topo order).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupCofAllInt( Gia_Man_t * p, Vec_Int_t * vSigs, int fVerbose )
+{
+    Vec_Int_t * vSigsNew, * vTemp;
+    Gia_Man_t * pAig, * pCof, * pNew;
+    int iVar;
+    if ( fVerbose )
+    { 
+        printf( "Cofactoring %d signals.\n", Vec_IntSize(vSigs) );
+        Gia_ManPrintStats( p, NULL );
+    }
+    if ( Vec_IntSize( vSigs ) > 200 )
+    {
+        printf( "Too many signals to cofactor.\n" );
+        return NULL;
+    }
+    pAig = Gia_ManDup( p );
+    vSigsNew = Vec_IntDup( vSigs );
+    while ( Vec_IntSize(vSigsNew) > 0 )
+    {
+        Vec_IntSort( vSigsNew, 0 );
+        iVar = Vec_IntPop( vSigsNew );
+//        Gia_ManCreateRefs( pAig );
+//        printf( "ref count = %d\n", Gia_ObjRefNum( pAig, Gia_ManObj(pAig, iVar) ) );
+//        ABC_FREE( pAig->pRefs );
+        pCof = Gia_ManDupCofInt( pAig, iVar );
+        pNew = Gia_ManCleanup( pCof );
+        vSigsNew = Gia_ManTransfer( pAig, pCof, pNew, vTemp = vSigsNew );
+        Vec_IntFree( vTemp );
+        Gia_ManStop( pAig );
+        Gia_ManStop( pCof );
+        pAig = pNew;
+        if ( fVerbose )
+            printf( "Cofactored variable %d.\n", iVar );
+        if ( fVerbose )
+            Gia_ManPrintStats( pAig, NULL );
+    }
+    Vec_IntFree( vSigsNew );
+    return pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cofactors all variables whose fanout is higher than this.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupCofAll( Gia_Man_t * p, int nFanLim, int fVerbose )
+{
+    Gia_Man_t * pNew;
+    Vec_Int_t * vSigs = Gia_ManCofVars( p, nFanLim );
+    pNew = Gia_ManDupCofAllInt( p, vSigs, fVerbose );
+    Vec_IntFree( vSigs );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaCone.c b/abc-build/src/aig/gia/giaCone.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaCone.c
@@ -0,0 +1,590 @@
+/**CFile****************************************************************
+
+  FileName    [giaCone.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaCone.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/extra/extra.h"
+#include "misc/vec/vecHsh.h"
+#include "misc/vec/vecWec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Opa_Man_t_ Opa_Man_t;
+struct Opa_Man_t_
+{
+    Gia_Man_t *    pGia;
+    Vec_Int_t *    vFront;
+    Vec_Int_t *    pvParts;
+    int *          pId2Part; 
+    int            nParts;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+    
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Opa_Man_t * Opa_ManStart( Gia_Man_t * pGia)
+{
+    Opa_Man_t * p;
+    Gia_Obj_t * pObj;
+    int i;
+    p = ABC_CALLOC( Opa_Man_t, 1 );
+    p->pGia = pGia;
+    p->pvParts  = ABC_CALLOC( Vec_Int_t, Gia_ManPoNum(pGia) );
+    p->pId2Part = ABC_FALLOC( int, Gia_ManObjNum(pGia) );
+    p->vFront   = Vec_IntAlloc( 100 );
+    Gia_ManForEachPo( pGia, pObj, i )
+    {
+        Vec_IntPush( p->pvParts + i, Gia_ObjId(pGia, pObj) );
+        p->pId2Part[Gia_ObjId(pGia, pObj)] = i;
+        Vec_IntPush( p->vFront, Gia_ObjId(pGia, pObj) );
+    }
+    p->nParts = Gia_ManPoNum(pGia);
+    return p;
+}
+static inline void Opa_ManStop( Opa_Man_t * p )
+{
+    int i;
+    Vec_IntFree( p->vFront );
+    for ( i = 0; i < Gia_ManPoNum(p->pGia); i++ )
+        ABC_FREE( p->pvParts[i].pArray );
+    ABC_FREE( p->pvParts );
+    ABC_FREE( p->pId2Part );
+    ABC_FREE( p );
+}
+static inline void Opa_ManPrint( Opa_Man_t * p )
+{
+    int i, k;
+    printf( "Groups:\n" );
+    for ( i = 0; i < Gia_ManPoNum(p->pGia); i++ )
+    {
+        if ( p->pvParts[i].nSize == 0 )
+            continue;
+        printf( "%3d : ", i );
+        for ( k = 0; k < p->pvParts[i].nSize; k++ )
+            printf( "%d ", p->pvParts[i].pArray[k] );
+        printf( "\n" );
+    }
+}
+static inline void Opa_ManPrint2( Opa_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, k, Count;
+    printf( "Groups %d: ", p->nParts );
+    for ( i = 0; i < Gia_ManPoNum(p->pGia); i++ )
+    {
+        if ( p->pvParts[i].nSize == 0 )
+            continue;
+        // count POs in this group
+        Count = 0;
+        Gia_ManForEachObjVec( p->pvParts + i, p->pGia, pObj, k )
+            Count += Gia_ObjIsPo(p->pGia, pObj);
+        printf( "%d ", Count );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Opa_ManMoveOne( Opa_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanin )
+{
+    int iObj   = Gia_ObjId(p->pGia, pObj);
+    int iFanin = Gia_ObjId(p->pGia, pFanin);
+    if ( iFanin == 0 )
+        return;
+    assert( p->pId2Part[ iObj ] >= 0 );
+    if ( p->pId2Part[ iFanin ] == -1 )
+    {
+        p->pId2Part[ iFanin ] = p->pId2Part[ iObj ];
+        Vec_IntPush( p->pvParts + p->pId2Part[ iObj ], iFanin );
+        assert( Gia_ObjIsCi(pFanin) || Gia_ObjIsAnd(pFanin) );
+        if ( Gia_ObjIsAnd(pFanin) )
+            Vec_IntPush( p->vFront, iFanin );
+        else if ( Gia_ObjIsRo(p->pGia, pFanin) )
+        {
+            pFanin = Gia_ObjRoToRi(p->pGia, pFanin);
+            iFanin = Gia_ObjId(p->pGia, pFanin);
+            assert( p->pId2Part[ iFanin ] == -1 );
+            p->pId2Part[ iFanin ] = p->pId2Part[ iObj ];
+            Vec_IntPush( p->pvParts + p->pId2Part[ iObj ], iFanin );
+            Vec_IntPush( p->vFront, iFanin );
+        }
+    }
+    else if ( p->pId2Part[ iObj ] != p->pId2Part[ iFanin ] )
+    {
+        Vec_Int_t * vPartObj = p->pvParts + p->pId2Part[ iObj ];
+        Vec_Int_t * vPartFan = p->pvParts + p->pId2Part[ iFanin ];
+        int iTemp, i;
+//        printf( "Moving %d to %d (%d -> %d)\n", iObj, iFanin, Vec_IntSize(vPartObj), Vec_IntSize(vPartFan) );
+        // add group of iObj to group of iFanin
+        assert( Vec_IntSize(vPartObj) > 0 );
+        Vec_IntForEachEntry( vPartObj, iTemp, i )
+        {
+            Vec_IntPush( vPartFan, iTemp );
+            p->pId2Part[ iTemp ] = p->pId2Part[ iFanin ];
+        }
+        Vec_IntShrink( vPartObj, 0 );
+        p->nParts--;
+    }
+}
+void Opa_ManPerform( Gia_Man_t * pGia )
+{
+    Opa_Man_t * p;
+    Gia_Obj_t * pObj;
+    int i, Limit, Count = 0;
+ 
+    p = Opa_ManStart( pGia );
+    Limit = Vec_IntSize(p->vFront);
+//Opa_ManPrint2( p );
+    Gia_ManForEachObjVec( p->vFront, pGia, pObj, i )
+    {
+        if ( i == Limit )
+        {
+            printf( "%6d : %6d -> %6d\n", ++Count, i, p->nParts );
+            Limit = Vec_IntSize(p->vFront);
+            if ( Count > 1 )
+                Opa_ManPrint2( p );
+        }
+//        printf( "*** Object %d  ", Gia_ObjId(pGia, pObj) );
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            Opa_ManMoveOne( p, pObj, Gia_ObjFanin0(pObj) );
+            Opa_ManMoveOne( p, pObj, Gia_ObjFanin1(pObj) );
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+            Opa_ManMoveOne( p, pObj, Gia_ObjFanin0(pObj) );
+        else assert( 0 );
+//        if ( i % 10 == 0 )
+//            printf( "%d   ", p->nParts );
+        if ( p->nParts == 1 )
+            break;
+        if ( Count == 5 )
+            break;
+    }
+    printf( "\n" );
+    Opa_ManStop( p );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManConeMark_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vRoots, int nLimit )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return 0;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        if ( Gia_ManConeMark_rec( p, Gia_ObjFanin0(pObj), vRoots, nLimit ) )
+            return 1;
+        if ( Gia_ManConeMark_rec( p, Gia_ObjFanin1(pObj), vRoots, nLimit ) )
+            return 1;
+    }
+    else if ( Gia_ObjIsCo(pObj) )
+    {
+        if ( Gia_ManConeMark_rec( p, Gia_ObjFanin0(pObj), vRoots, nLimit ) )
+            return 1;
+    }
+    else if ( Gia_ObjIsRo(p, pObj) )
+        Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) );
+    else if ( Gia_ObjIsPi(p, pObj) )
+    {}
+    else assert( 0 );
+    return (int)(Vec_IntSize(vRoots) > nLimit);
+}
+int Gia_ManConeMark( Gia_Man_t * p, int iOut, int Limit )
+{
+    Vec_Int_t * vRoots;
+    Gia_Obj_t * pObj;
+    int i, RetValue;
+    // start the outputs
+    pObj = Gia_ManPo( p, iOut );
+    vRoots = Vec_IntAlloc( 100 );
+    Vec_IntPush( vRoots, Gia_ObjId(p, pObj) );
+    // mark internal nodes
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+    Gia_ManForEachObjVec( vRoots, p, pObj, i )
+        if ( Gia_ManConeMark_rec( p, pObj, vRoots, Limit ) )
+            break;
+    RetValue = Vec_IntSize( vRoots ) - 1;
+    Vec_IntFree( vRoots );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCountFlops( Gia_Man_t * p, Vec_Int_t * vOuts )
+{
+    int Limit = ABC_INFINITY;
+    Vec_Int_t * vRoots;
+    Gia_Obj_t * pObj;
+    int i, RetValue, iOut;
+    // start the outputs
+    vRoots = Vec_IntAlloc( 100 );
+    Vec_IntForEachEntry( vOuts, iOut, i )
+    {
+        pObj = Gia_ManPo( p, iOut );
+        Vec_IntPush( vRoots, Gia_ObjId(p, pObj) );
+    }
+    // mark internal nodes
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+    Gia_ManForEachObjVec( vRoots, p, pObj, i )
+        if ( Gia_ManConeMark_rec( p, pObj, vRoots, Limit ) )
+            break;
+    RetValue = Vec_IntSize( vRoots ) - Vec_IntSize(vOuts);
+    Vec_IntFree( vRoots );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFindPoPartition3( Gia_Man_t * p, int iOut, int nDelta, int nOutsMin, int nOutsMax, int fVerbose, Vec_Ptr_t ** pvPosEquivs )
+{
+/*
+    int i, Count = 0;
+    // mark nodes belonging to output 'iOut'
+    for ( i = 0; i < Gia_ManPoNum(p); i++ )
+        Count += (Gia_ManConeMark(p, i, 10000) < 10000);
+     //   printf( "%d ", Gia_ManConeMark(p, i, 1000) );
+    printf( "%d out of %d\n", Count, Gia_ManPoNum(p) );
+
+    // add other outputs as long as they are nDelta away
+*/
+//    Opa_ManPerform( p );
+
+    return NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManFindPivots( Gia_Man_t * p, int SelectShift, int fOnlyCis, int fVerbose )
+{
+    Vec_Int_t * vPivots, * vWeights;
+    Vec_Int_t * vCount, * vResult;
+    int i, j, Count, * pPerm, Limit;
+/*
+    Gia_Obj_t * pObj;
+    // count MUX controls
+    vCount = Vec_IntStart( Gia_ManObjNum(p) );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        Gia_Obj_t * pNodeC, * pNodeT, * pNodeE;
+        if ( !Gia_ObjIsMuxType(pObj) ) 
+            continue;
+        pNodeC = Gia_ObjRecognizeMux( pObj, &pNodeT, &pNodeE );
+        Vec_IntAddToEntry( vCount, Gia_ObjId(p, Gia_Regular(pNodeC)), 1 );
+    }
+*/
+    // count references
+    Gia_ManCreateRefs( p );
+    vCount = Vec_IntAllocArray( p->pRefs, Gia_ManObjNum(p) ); p->pRefs = NULL;
+
+    // collect nodes 
+    vPivots  = Vec_IntAlloc( 100 );
+    vWeights = Vec_IntAlloc( 100 );
+    Vec_IntForEachEntry( vCount, Count, i )
+    {
+        if ( Count < 2 ) continue;
+        if ( fOnlyCis && !Gia_ObjIsCi(Gia_ManObj(p, i)) )
+            continue;
+        Vec_IntPush( vPivots, i );
+        Vec_IntPush( vWeights, Count );
+    }
+    Vec_IntFree( vCount );
+
+    if ( fVerbose )
+        printf( "Selected %d pivots with more than one fanout (out of %d CIs and ANDs).\n", Vec_IntSize(vWeights), Gia_ManCiNum(p) + Gia_ManAndNum(p) );
+
+    // permute
+    Gia_ManRandom(1);
+    Gia_ManRandom(0);
+    for ( i = 0; i < Vec_IntSize(vWeights); i++ )
+    {
+        j = (Gia_ManRandom(0) >> 1) % Vec_IntSize(vWeights);
+        ABC_SWAP( int, vPivots->pArray[i], vPivots->pArray[j] );
+        ABC_SWAP( int, vWeights->pArray[i], vWeights->pArray[j] );
+    }
+    // sort
+    if ( SelectShift == 0 )
+        pPerm = Abc_QuickSortCost( Vec_IntArray(vWeights), Vec_IntSize(vWeights), 1 );
+    else
+    {
+        Vec_Int_t * vTemp = Vec_IntStartNatural( Vec_IntSize(vWeights) );
+        pPerm = Vec_IntReleaseArray( vTemp );
+        Vec_IntFree( vTemp );
+    }
+
+    // select    
+    Limit = Abc_MinInt( 64, Vec_IntSize(vWeights) );
+    vResult = Vec_IntAlloc( Limit );
+    for ( i = 0; i < Limit; i++ )
+    {
+        j = (i + SelectShift) % Vec_IntSize(vWeights);
+        if ( fVerbose )
+            printf( "%2d : Pivot =%7d  Fanout =%7d\n", j, Vec_IntEntry(vPivots, pPerm[j]), Vec_IntEntry(vWeights, pPerm[j]) );
+        Vec_IntPush( vResult, Vec_IntEntry(vPivots, pPerm[j]) );
+    }
+
+    Vec_IntFree( vPivots );
+    Vec_IntFree( vWeights );
+    ABC_FREE( pPerm );
+
+    return vResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Wrd_t * Gia_ManDeriveSigns( Gia_Man_t * p, Vec_Int_t * vPivots, int fVerbose )
+{
+    Vec_Wrd_t * vSigns;
+    Gia_Obj_t * pObj, * pObjRi;
+    int i, fChange = 1, Counter;
+
+    Gia_ManFillValue( p );
+    Gia_ManForEachObjVec( vPivots, p, pObj, i )
+        pObj->Value = i;
+
+    if ( fVerbose )
+        printf( "Signature propagation: " );
+    vSigns = Vec_WrdStart( Gia_ManObjNum(p) );
+    while ( fChange )
+    {
+        fChange = 0;
+        Gia_ManForEachObj( p, pObj, i )
+        {
+            if ( ~pObj->Value )
+            {
+                assert( pObj->Value >= 0 && pObj->Value < 64 );
+                *Vec_WrdEntryP( vSigns, i ) |= ( (word)1 << pObj->Value );
+            }
+            if ( Gia_ObjIsAnd(pObj) )
+                *Vec_WrdEntryP( vSigns, i ) |= Vec_WrdEntry(vSigns, Gia_ObjFaninId0(pObj, i)) | Vec_WrdEntry(vSigns, Gia_ObjFaninId1(pObj, i));
+            else if ( Gia_ObjIsCo(pObj) )
+                *Vec_WrdEntryP( vSigns, i ) |= Vec_WrdEntry(vSigns, Gia_ObjFaninId0(pObj, i));
+        }
+        Counter = 0;
+        Gia_ManForEachRiRo( p, pObjRi, pObj, i )
+        {
+            word Value = Vec_WrdEntry(vSigns, Gia_ObjId(p, pObj));
+            *Vec_WrdEntryP( vSigns, Gia_ObjId(p, pObj) ) |= Vec_WrdEntry(vSigns, Gia_ObjId(p, pObjRi));
+            if ( Value != Vec_WrdEntry(vSigns, Gia_ObjId(p, pObj)) )
+                fChange = 1, Counter++;
+        }
+        if ( fVerbose )
+            printf( "%d ", Counter );
+    }
+    if ( fVerbose )
+       printf( "\n" );
+    return vSigns;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Gia_ManHashOutputs( Gia_Man_t * p, Vec_Wrd_t * vSigns, int fVerbose )
+{
+    Vec_Ptr_t * vBins;
+    Vec_Wec_t * vClasses;
+    Vec_Wrd_t * vSignsPo;
+    Vec_Int_t * vPriority, * vBin;
+    Gia_Obj_t * pObj;
+    int i;
+    // collect PO signatures
+    vSignsPo = Vec_WrdAlloc( Gia_ManPoNum(p) );
+    Gia_ManForEachPo( p, pObj, i )
+        Vec_WrdPush( vSignsPo, Vec_WrdEntry(vSigns, Gia_ObjId(p, pObj)) );
+    // find equivalence classes
+    vPriority = Hsh_WrdManHashArray( vSignsPo, 1 );
+    Vec_WrdFree( vSignsPo );
+    vClasses = Vec_WecCreateClasses( vPriority );
+    Vec_IntFree( vPriority );
+    vBins = (Vec_Ptr_t *)Vec_WecConvertToVecPtr( vClasses );
+    Vec_WecFree( vClasses );
+    Vec_VecSort( (Vec_Vec_t *)vBins, 1 );
+
+    if ( fVerbose )
+        printf( "Computed %d partitions:\n", Vec_PtrSize(vBins) );
+    if ( !fVerbose )
+        printf( "Listing partitions with more than 100 outputs:\n" );
+    Vec_PtrForEachEntry( Vec_Int_t *, vBins, vBin, i )
+    {
+        assert( Vec_IntSize(vBin) > 0 );
+        if ( fVerbose || Vec_IntSize(vBin) > 100 )
+        {
+            int PoNum = Vec_IntEntry( vBin, 0 );
+            Gia_Obj_t * pObj = Gia_ManPo( p, PoNum );
+            word Sign = Vec_WrdEntry( vSigns, Gia_ObjId(p, pObj) );
+            // print
+            printf( "%3d ", i );
+            Extra_PrintBinary( stdout, (unsigned *)&Sign, 64 );
+            printf( "  " );
+            printf( "PO =%7d  ", Vec_IntSize(vBin) );
+            printf( "FF =%7d", Gia_ManCountFlops(p, vBin) );
+            printf( "\n" );
+        }
+    }
+    return vBins;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFindPoPartition2( Gia_Man_t * p, int iStartNum, int nDelta, int nOutsMin, int nOutsMax, int fSetLargest, int fVerbose, Vec_Ptr_t ** pvPosEquivs )
+{
+    return NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFindPoPartition( Gia_Man_t * p, int SelectShift, int fOnlyCis, int fSetLargest, int fVerbose, Vec_Ptr_t ** pvPosEquivs )
+{
+    Gia_Man_t * pGia = NULL;
+    Vec_Int_t * vPivots;
+    Vec_Wrd_t * vSigns;
+    Vec_Ptr_t * vParts;
+    Vec_Int_t * vPart;
+    abctime clk = Abc_Clock();
+    vPivots = Gia_ManFindPivots( p, SelectShift, fOnlyCis, fVerbose );
+    vSigns = Gia_ManDeriveSigns( p, vPivots, fVerbose );
+    Vec_IntFree( vPivots );
+    vParts = Gia_ManHashOutputs( p, vSigns, fVerbose );
+    Vec_WrdFree( vSigns );
+    if ( fSetLargest )
+    {
+        vPart = Vec_VecEntryInt( (Vec_Vec_t *)vParts, 0 );
+        pGia = Gia_ManDupCones( p, Vec_IntArray(vPart), Vec_IntSize(vPart), 1 );
+    }
+    if ( pvPosEquivs )
+    {
+        *pvPosEquivs = vParts;
+        printf( "The algorithm divided %d POs into %d partitions.   ", Gia_ManPoNum(p), Vec_PtrSize(vParts) );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    else
+        Vec_VecFree( (Vec_Vec_t *)vParts );
+    return pGia;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaConstr.c b/abc-build/src/aig/gia/giaConstr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaConstr.c
@@ -0,0 +1,52 @@
+/**CFile****************************************************************
+
+  FileName    [giaConstr.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Constraint propagation in CNF-based solver.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaConstr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaDfs.c b/abc-build/src/aig/gia/giaDfs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaDfs.c
@@ -0,0 +1,510 @@
+/**CFile****************************************************************
+
+  FileName    [giaDfs.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [DFS procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaDfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the support size of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCollectCis_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+    {
+        Vec_IntPush( vSupp, Gia_ObjId(p, pObj) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManCollectCis_rec( p, Gia_ObjFanin0(pObj), vSupp );
+    Gia_ManCollectCis_rec( p, Gia_ObjFanin1(pObj), vSupp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects support nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCollectCis( Gia_Man_t * p, int * pNodes, int nNodes, Vec_Int_t * vSupp )
+{
+    Gia_Obj_t * pObj;
+    int i; 
+    Vec_IntClear( vSupp );
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+    for ( i = 0; i < nNodes; i++ )
+    {
+        pObj = Gia_ManObj( p, pNodes[i] );
+        if ( Gia_ObjIsCo(pObj) )
+            Gia_ManCollectCis_rec( p, Gia_ObjFanin0(pObj), vSupp );
+        else
+            Gia_ManCollectCis_rec( p, pObj, vSupp );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the support size of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCollectAnds_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManCollectAnds_rec( p, Gia_ObjFanin0(pObj), vNodes );
+    Gia_ManCollectAnds_rec( p, Gia_ObjFanin1(pObj), vNodes );
+    Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects support nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCollectAnds( Gia_Man_t * p, int * pNodes, int nNodes, Vec_Int_t * vNodes )
+{
+    Gia_Obj_t * pObj;
+    int i; 
+    Vec_IntClear( vNodes );
+//    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+    for ( i = 0; i < nNodes; i++ )
+    {
+        pObj = Gia_ManObj( p, pNodes[i] );
+        if ( Gia_ObjIsCo(pObj) )
+            Gia_ManCollectAnds_rec( p, Gia_ObjFanin0(pObj), vNodes );
+        else
+            Gia_ManCollectAnds_rec( p, pObj, vNodes );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the support size of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCollectNodesCis_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+    {
+        Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManCollectNodesCis_rec( p, Gia_ObjFanin0(pObj), vNodes );
+    Gia_ManCollectNodesCis_rec( p, Gia_ObjFanin1(pObj), vNodes );
+    Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects support nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManCollectNodesCis( Gia_Man_t * p, int * pNodes, int nNodes )
+{
+    Vec_Int_t * vNodes;
+    Gia_Obj_t * pObj;
+    int i; 
+    vNodes = Vec_IntAlloc( 10000 );
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+    for ( i = 0; i < nNodes; i++ )
+    {
+        pObj = Gia_ManObj( p, pNodes[i] );
+        if ( Gia_ObjIsCo(pObj) )
+            Gia_ManCollectNodesCis_rec( p, Gia_ObjFanin0(pObj), vNodes );
+        else
+            Gia_ManCollectNodesCis_rec( p, pObj, vNodes );
+    }
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects support nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCollectTest( Gia_Man_t * p )
+{
+    Vec_Int_t * vNodes;
+    Gia_Obj_t * pObj;
+    int i, iNode;
+    abctime clk = Abc_Clock();
+    vNodes = Vec_IntAlloc( 100 );
+    Gia_ManIncrementTravId( p );
+    Gia_ManForEachCo( p, pObj, i )
+    {
+        iNode = Gia_ObjId(p, pObj);
+        Gia_ManCollectAnds( p, &iNode, 1, vNodes );
+    }
+    Vec_IntFree( vNodes );
+    ABC_PRT( "DFS from each output", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects support nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManSuppSize_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return 0;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+        return 1;
+    assert( Gia_ObjIsAnd(pObj) );
+    return Gia_ManSuppSize_rec( p, Gia_ObjFanin0(pObj) ) +
+        Gia_ManSuppSize_rec( p, Gia_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes support size of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManSuppSizeOne( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    Gia_ManIncrementTravId( p );
+    return Gia_ManSuppSize_rec( p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes support size of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManSuppSizeTest( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, Counter = 0;
+    abctime clk = Abc_Clock();
+    Gia_ManForEachObj( p, pObj, i )
+        if ( Gia_ObjIsAnd(pObj) )
+            Counter += (Gia_ManSuppSizeOne(p, pObj) <= 16);
+    printf( "Nodes with small support %d (out of %d)\n", Counter, Gia_ManAndNum(p) );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects support nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManSuppSize( Gia_Man_t * p, int * pNodes, int nNodes )
+{
+    Gia_Obj_t * pObj;
+    int i, Counter = 0; 
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+    for ( i = 0; i < nNodes; i++ )
+    {
+        pObj = Gia_ManObj( p, pNodes[i] );
+        if ( Gia_ObjIsCo(pObj) )
+            Counter += Gia_ManSuppSize_rec( p, Gia_ObjFanin0(pObj) );
+        else
+            Counter += Gia_ManSuppSize_rec( p, pObj );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects support nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManConeSize_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return 0;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+        return 0;
+    assert( Gia_ObjIsAnd(pObj) );
+    return 1 + Gia_ManConeSize_rec( p, Gia_ObjFanin0(pObj) ) +
+        Gia_ManConeSize_rec( p, Gia_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects support nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManConeSize( Gia_Man_t * p, int * pNodes, int nNodes )
+{
+    Gia_Obj_t * pObj;
+    int i, Counter = 0; 
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+    for ( i = 0; i < nNodes; i++ )
+    {
+        pObj = Gia_ManObj( p, pNodes[i] );
+        if ( Gia_ObjIsCo(pObj) )
+            Counter += Gia_ManConeSize_rec( p, Gia_ObjFanin0(pObj) );
+        else
+            Counter += Gia_ManConeSize_rec( p, pObj );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Levelizes the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Gia_ManLevelize( Gia_Man_t * p )
+{ 
+    Gia_Obj_t * pObj;
+    Vec_Vec_t * vLevels;
+    int nLevels, Level, i;
+    nLevels = Gia_ManLevelNum( p );
+    vLevels = Vec_VecStart( nLevels + 1 );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        Level = Gia_ObjLevel( p, pObj );
+        assert( Level <= nLevels );
+        Vec_VecPush( vLevels, Level, pObj );
+    }
+    return vLevels;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes reverse topological order.]
+
+  Description [Assumes that levels are already assigned.
+  The levels of CO nodes may not be assigned.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManOrderReverse( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    Vec_Vec_t * vLevels;
+    Vec_Ptr_t * vLevel;
+    Vec_Int_t * vResult;
+    int i, k;
+    vLevels = Vec_VecStart( 100 );
+    // make sure levels are assigned
+    Gia_ManForEachAnd( p, pObj, i )
+        assert( Gia_ObjLevel(p, pObj) > 0 );
+    // add CO nodes based on the level of their fanin
+    Gia_ManForEachCo( p, pObj, i )
+        Vec_VecPush( vLevels, Gia_ObjLevel(p, Gia_ObjFanin0(pObj)), pObj );
+    // add other nodes based on their level
+    Gia_ManForEachObj( p, pObj, i )
+        if ( !Gia_ObjIsCo(pObj) )
+            Vec_VecPush( vLevels, Gia_ObjLevel(p, pObj), pObj );
+    // put the nodes in the reverse topological order
+    vResult = Vec_IntAlloc( Gia_ManObjNum(p) );
+    Vec_VecForEachLevelReverse( vLevels, vLevel, i )
+        Vec_PtrForEachEntry( Gia_Obj_t *, vLevel, pObj, k )
+            Vec_IntPush( vResult, Gia_ObjId(p, pObj) );
+    Vec_VecFree( vLevels );
+    return vResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCollectSeq_rec( Gia_Man_t * p, int Id, Vec_Int_t * vRoots, Vec_Int_t * vObjs )
+{
+    Gia_Obj_t * pObj;
+    if ( Gia_ObjIsTravIdCurrentId( p, Id ) )
+        return;
+    Gia_ObjSetTravIdCurrentId( p, Id );
+    pObj = Gia_ManObj( p, Id );
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        Gia_ManCollectSeq_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vObjs );
+        Gia_ManCollectSeq_rec( p, Gia_ObjFaninId1(pObj, Id), vRoots, vObjs );
+    }
+    else if ( Gia_ObjIsCi(pObj) )
+    {
+        if ( Gia_ObjIsRo(p, pObj) )
+            Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) );
+    }
+    else if ( Gia_ObjIsCo(pObj) )
+        Gia_ManCollectSeq_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vObjs );
+    else assert( 0 );
+    Vec_IntPush( vObjs, Id );
+}
+Vec_Int_t * Gia_ManCollectSeq( Gia_Man_t * p, int * pPos, int nPos )
+{
+    Vec_Int_t * vObjs, * vRoots;
+    int i, iRoot;
+    // collect roots
+    vRoots = Vec_IntAlloc( 100 );
+    for ( i = 0; i < nPos; i++ )
+        Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ManPo(p, pPos[i])) );
+    // start trav IDs
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrentId( p, 0 );
+    // collect objects
+    vObjs = Vec_IntAlloc( 1000 );
+    Vec_IntPush( vObjs, 0 );
+    Vec_IntForEachEntry( vRoots, iRoot, i )
+        Gia_ManCollectSeq_rec( p, iRoot, vRoots, vObjs );
+    Vec_IntFree( vRoots );
+    return vObjs;
+}
+void Gia_ManCollectSeqTest( Gia_Man_t * p )
+{
+    Vec_Int_t * vObjs;
+    int i;
+    abctime clk = Abc_Clock();
+    for ( i = 0; i < Gia_ManPoNum(p); i++ )
+    {
+        if ( i % 10000 == 0 )
+            printf( "%8d finished...\r", i );
+
+        vObjs = Gia_ManCollectSeq( p, &i, 1 );
+//        printf( "%d ", Vec_IntSize(vObjs) );
+        Vec_IntFree( vObjs );
+    }
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaDup.c b/abc-build/src/aig/gia/giaDup.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaDup.c
@@ -0,0 +1,3015 @@
+/**CFile****************************************************************
+
+  FileName    [giaDup.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Duplication procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaDup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/tim/tim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Removes pointers to the unmarked nodes..]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManDupRemapEquiv( Gia_Man_t * pNew, Gia_Man_t * p )
+{
+    Vec_Int_t * vClass;
+    int i, k, iNode, iRepr, iPrev;
+    if ( p->pReprs == NULL )
+        return;
+    assert( pNew->pReprs == NULL && pNew->pNexts == NULL );
+    // start representatives
+    pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pNew) );
+    for ( i = 0; i < Gia_ManObjNum(pNew); i++ )
+        Gia_ObjSetRepr( pNew, i, GIA_VOID );
+    // iterate over constant candidates
+    Gia_ManForEachConst( p, i )
+        Gia_ObjSetRepr( pNew, Abc_Lit2Var(Gia_ManObj(p, i)->Value), 0 );
+    // iterate over class candidates
+    vClass = Vec_IntAlloc( 100 );
+    Gia_ManForEachClass( p, i )
+    {
+        Vec_IntClear( vClass );
+        Gia_ClassForEachObj( p, i, k )
+            Vec_IntPushUnique( vClass, Abc_Lit2Var(Gia_ManObj(p, k)->Value) );
+        assert( Vec_IntSize( vClass ) > 1 );
+        Vec_IntSort( vClass, 0 );
+        iRepr = iPrev = Vec_IntEntry( vClass, 0 );
+        Vec_IntForEachEntryStart( vClass, iNode, k, 1 )
+        {
+            Gia_ObjSetRepr( pNew, iNode, iRepr );
+            assert( iPrev < iNode );
+            iPrev = iNode;
+        }
+    }
+    Vec_IntFree( vClass );
+    pNew->pNexts = Gia_ManDeriveNexts( pNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Remaps combinational inputs when objects are DFS ordered.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManDupRemapCis( Gia_Man_t * pNew, Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pObjNew;
+    int i;
+    assert( Vec_IntSize(p->vCis) == Vec_IntSize(pNew->vCis) );
+    Gia_ManForEachCi( p, pObj, i )
+    {
+        assert( Gia_ObjCioId(pObj) == i );
+        pObjNew = Gia_ObjFromLit( pNew, pObj->Value );
+        assert( !Gia_IsComplement(pObjNew) );
+        Vec_IntWriteEntry( pNew->vCis, i, Gia_ObjId(pNew, pObjNew) );
+        Gia_ObjSetCioId( pObjNew, i );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Remaps combinational outputs when objects are DFS ordered.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManDupRemapCos( Gia_Man_t * pNew, Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pObjNew;
+    int i;
+    assert( Vec_IntSize(p->vCos) == Vec_IntSize(pNew->vCos) );
+    Gia_ManForEachCo( p, pObj, i )
+    {
+        assert( Gia_ObjCioId(pObj) == i );
+        pObjNew = Gia_ObjFromLit( pNew, pObj->Value );
+        assert( !Gia_IsComplement(pObjNew) );
+        Vec_IntWriteEntry( pNew->vCos, i, Gia_ObjId(pNew, pObjNew) );
+        Gia_ObjSetCioId( pObjNew, i );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManDupOrderDfs_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( ~pObj->Value )
+        return pObj->Value;
+    if ( Gia_ObjIsCi(pObj) )
+        return pObj->Value = Gia_ManAppendCi(pNew);
+//    if ( p->pNexts && Gia_ObjNext(p, Gia_ObjId(p, pObj)) )
+//        Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjNextObj(p, Gia_ObjId(p, pObj)) );
+    Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    if ( Gia_ObjIsCo(pObj) )
+        return pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin1(pObj) );
+    return pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG while putting objects in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupOrderDfs( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManDupOrderDfs_rec( pNew, p, pObj );
+    Gia_ManForEachCi( p, pObj, i )
+        if ( !~pObj->Value )
+            pObj->Value = Gia_ManAppendCi(pNew);
+    assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) );
+    Gia_ManDupRemapCis( pNew, p );
+    Gia_ManDupRemapEquiv( pNew, p );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG while putting objects in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupOutputGroup( Gia_Man_t * p, int iOutStart, int iOutStop )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    for ( i = iOutStart; i < iOutStop; i++ )
+    {
+        pObj = Gia_ManCo( p, i );
+        Gia_ManDupOrderDfs_rec( pNew, p, pObj );
+    }
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG while putting objects in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupOutputVec( Gia_Man_t * p, Vec_Int_t * vOutPres )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Gia_ManRegNum(p) == 0 );
+    assert( Gia_ManPoNum(p) == Vec_IntSize(vOutPres) );
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManForEachPo( p, pObj, i )
+        if ( Vec_IntEntry(vOutPres, i) )
+            Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    Gia_ManForEachPo( p, pObj, i )
+        if ( Vec_IntEntry(vOutPres, i) )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManDupOrderDfsChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    Gia_Obj_t * pNext;
+    if ( ~pObj->Value )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    pNext = Gia_ObjNextObj( p, Gia_ObjId(p, pObj) );
+    if ( pNext )
+        Gia_ManDupOrderDfsChoices_rec( pNew, p, pNext );
+    Gia_ManDupOrderDfsChoices_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    Gia_ManDupOrderDfsChoices_rec( pNew, p, Gia_ObjFanin1(pObj) );
+    pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    if ( pNext )
+    {
+        pNew->pNexts[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var( Abc_Lit2Var(pNext->Value) );
+        assert( Abc_Lit2Var(pObj->Value) > Abc_Lit2Var(pNext->Value) );
+    }
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG while putting objects in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupOrderDfsChoices( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( p->pReprs && p->pNexts );
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManForEachCo( p, pObj, i )
+    {
+        Gia_ManDupOrderDfsChoices_rec( pNew, p, Gia_ObjFanin0(pObj) );
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+//    Gia_ManDeriveReprs( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG while putting objects in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupOrderDfsReverse( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCoReverse( p, pObj, i )
+        Gia_ManDupOrderDfs_rec( pNew, p, pObj );
+    Gia_ManForEachCi( p, pObj, i )
+        if ( !~pObj->Value )
+            pObj->Value = Gia_ManAppendCi(pNew);
+    assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) );
+    Gia_ManDupRemapCis( pNew, p );
+    Gia_ManDupRemapCos( pNew, p );
+    Gia_ManDupRemapEquiv( pNew, p );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG while putting first PIs, then nodes, then POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupOrderAiger( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManDupRemapEquiv( pNew, p );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    assert( Gia_ManIsNormalized(pNew) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG while putting first PIs, then nodes, then POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupLastPis( Gia_Man_t * p, int nLastPis )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Gia_ManRegNum(p) == 0 );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = (i < Gia_ManCiNum(p) - nLastPis) ? ~0 : Gia_ManAppendCi(pNew);
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG while complementing the flops.]
+
+  Description [The array of initial state contains the init state
+  for each state bit of the flops in the design.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupFlip( Gia_Man_t * p, int * pInitState )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjIsCi(pObj) )
+        {
+            pObj->Value = Gia_ManAppendCi( pNew );
+            if ( Gia_ObjCioId(pObj) >= Gia_ManPiNum(p) )
+                pObj->Value = Abc_LitNotCond( pObj->Value, Abc_InfoHasBit((unsigned *)pInitState, Gia_ObjCioId(pObj) - Gia_ManPiNum(p)) );
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+        {
+            pObj->Value = Gia_ObjFanin0Copy(pObj);
+            if ( Gia_ObjCioId(pObj) >= Gia_ManPoNum(p) )
+                pObj->Value = Abc_LitNotCond( pObj->Value, Abc_InfoHasBit((unsigned *)pInitState, Gia_ObjCioId(pObj) - Gia_ManPoNum(p)) );
+            pObj->Value = Gia_ManAppendCo( pNew, pObj->Value );
+        }
+    }
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Cycles AIG using random input.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCycle( Gia_Man_t * p, Abc_Cex_t * pCex, int nFrames )
+{
+    Gia_Obj_t * pObj, * pObjRi, * pObjRo;
+    int i, k;
+    Gia_ManRandom( 1 );
+    assert( pCex == NULL || nFrames <= pCex->iFrame );
+    // iterate for the given number of frames
+    for ( i = 0; i < nFrames; i++ )
+    {
+        Gia_ManForEachPi( p, pObj, k )
+            pObj->fMark0 = pCex ? Abc_InfoHasBit(pCex->pData, pCex->nRegs+i*pCex->nPis+k) : (1 & Gia_ManRandom(0));
+        Gia_ManForEachAnd( p, pObj, k )
+            pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & 
+                           (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+        Gia_ManForEachCo( p, pObj, k )
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
+            pObjRo->fMark0 = pObjRi->fMark0;
+    }
+}
+Gia_Man_t * Gia_ManDupCycled( Gia_Man_t * p, Abc_Cex_t * pCex, int nFrames )
+{
+    Gia_Man_t * pNew;
+    Vec_Bit_t * vInits;
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManCleanMark0(p);
+    Gia_ManCycle( p, pCex, nFrames );
+    vInits = Vec_BitAlloc( Gia_ManRegNum(p) );
+    Gia_ManForEachRo( p, pObj, i )
+        Vec_BitPush( vInits, pObj->fMark0 );
+    pNew = Gia_ManDupFlip( p, Vec_BitArray(vInits) );
+    Vec_BitFree( vInits );
+    Gia_ManCleanMark0(p);
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG without any changes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDup( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    if ( Gia_ManHasChoices(p) )
+        pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+            if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) )
+                pNew->pSibls[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var(Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))->Value);  
+        }
+        else if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Gia_ManAppendCi( pNew );
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    if ( p->pCexSeq )
+        pNew->pCexSeq = Abc_CexDup( p->pCexSeq, Gia_ManRegNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG without any changes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupZero( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew; int i;
+    pNew = Gia_ManStart( 1 + Gia_ManCiNum(p) + Gia_ManCoNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    for ( i = 0; i < Gia_ManCiNum(p); i++ )
+        Gia_ManAppendCi( pNew );
+    for ( i = 0; i < Gia_ManCoNum(p); i++ )
+        Gia_ManAppendCo( pNew, 0 );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG without any changes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupPerm( Gia_Man_t * p, Vec_Int_t * vPiPerm )
+{
+//    Vec_Int_t * vPiPermInv;
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Vec_IntSize(vPiPerm) == Gia_ManPiNum(p) );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+//    vPiPermInv = Vec_IntInvert( vPiPerm, -1 );
+    Gia_ManForEachPi( p, pObj, i )
+//        Gia_ManPi(p, Vec_IntEntry(vPiPermInv,i))->Value = Gia_ManAppendCi( pNew );
+        Gia_ManPi(p, Vec_IntEntry(vPiPerm,i))->Value = Gia_ManAppendCi( pNew );
+//    Vec_IntFree( vPiPermInv );
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjIsCi(pObj) )
+        {
+            if ( Gia_ObjIsRo(p, pObj) )
+                pObj->Value = Gia_ManAppendCi( pNew );
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    return pNew;
+}
+Gia_Man_t * Gia_ManDupPermFlop( Gia_Man_t * p, Vec_Int_t * vFfPerm )
+{
+    Vec_Int_t * vPermInv;
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Vec_IntSize(vFfPerm) == Gia_ManRegNum(p) );
+    vPermInv = Vec_IntInvert( vFfPerm, -1 );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManForEachRo( p, pObj, i )
+        Gia_ManRo(p, Vec_IntEntry(vPermInv, i))->Value = Gia_ManAppendCi(pNew);
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachPo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManForEachRi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy( Gia_ManRi(p, Vec_IntEntry(vPermInv, i)) ) );
+    Vec_IntFree( vPermInv );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    return pNew;
+}
+Gia_Man_t * Gia_ManDupSpreadFlop( Gia_Man_t * p, Vec_Int_t * vFfMask )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i, k, Entry;
+    assert( Vec_IntSize(vFfMask) >= Gia_ManRegNum(p) );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    k = 0;
+    Vec_IntForEachEntry( vFfMask, Entry, i )
+        if ( Entry == -1 )
+            Gia_ManAppendCi(pNew);
+        else
+            Gia_ManRo(p, k++)->Value = Gia_ManAppendCi(pNew);
+    assert( k == Gia_ManRegNum(p) );
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachPo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    k = 0;
+    Vec_IntForEachEntry( vFfMask, Entry, i )
+        if ( Entry == -1 )
+            Gia_ManAppendCo( pNew, 0 );
+        else
+        {
+            pObj = Gia_ManRi( p, k++ );
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+        }
+    assert( k == Gia_ManRegNum(p) );
+    Gia_ManSetRegNum( pNew, Vec_IntSize(vFfMask) );
+    return pNew;
+}
+Gia_Man_t * Gia_ManDupPermFlopGap( Gia_Man_t * p, Vec_Int_t * vFfMask )
+{
+    Vec_Int_t * vPerm = Vec_IntCondense( vFfMask, -1 );
+    Gia_Man_t * pPerm = Gia_ManDupPermFlop( p, vPerm );
+    Gia_Man_t * pSpread = Gia_ManDupSpreadFlop( pPerm, vFfMask );
+    Vec_IntFree( vPerm );
+    Gia_ManStop( pPerm );
+    return pSpread;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Appends second AIG without any changes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManDupAppend( Gia_Man_t * pNew, Gia_Man_t * pTwo )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    if ( pNew->nRegs > 0 )
+        pNew->nRegs = 0;
+    if ( pNew->pHTable == NULL )
+        Gia_ManHashStart( pNew );
+    Gia_ManConst0(pTwo)->Value = 0;
+    Gia_ManForEachObj1( pTwo, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Gia_ManAppendCi( pNew );
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+}
+void Gia_ManDupAppendShare( Gia_Man_t * pNew, Gia_Man_t * pTwo )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(pTwo) );
+    if ( pNew->pHTable == NULL )
+        Gia_ManHashStart( pNew );
+    Gia_ManConst0(pTwo)->Value = 0;
+    Gia_ManForEachObj1( pTwo, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Gia_Obj2Lit( pNew, Gia_ManCi( pNew, Gia_ObjCioId(pObj) ) );
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+}
+Gia_Man_t * Gia_ManDupAppendNew( Gia_Man_t * pOne, Gia_Man_t * pTwo )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    pNew = Gia_ManStart( Gia_ManObjNum(pOne) + Gia_ManObjNum(pTwo) );
+    pNew->pName = Abc_UtilStrsav( pOne->pName );
+    pNew->pSpec = Abc_UtilStrsav( pOne->pSpec );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManConst0(pOne)->Value = 0;
+    Gia_ManForEachObj1( pOne, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Gia_ManAppendCi( pNew );
+    }
+    Gia_ManConst0(pTwo)->Value = 0;
+    Gia_ManForEachObj1( pTwo, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjIsPi(pTwo, pObj) )
+            pObj->Value = Gia_ManPi(pOne, Gia_ObjCioId(pObj))->Value;
+        else if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Gia_ManAppendCi( pNew );
+    }
+    Gia_ManHashStop( pNew );
+    // primary outputs
+    Gia_ManForEachPo( pOne, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManForEachPo( pTwo, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    // flop inputs
+    Gia_ManForEachRi( pOne, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManForEachRi( pTwo, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(pOne) + Gia_ManRegNum(pTwo) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Appends logic cones as additional property outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupAppendCones( Gia_Man_t * p, Gia_Man_t ** ppCones, int nCones, int fOnlyRegs )
+{
+    Gia_Man_t * pNew, * pOne;
+    Gia_Obj_t * pObj;
+    int i, k;
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachPo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    for ( k = 0; k < nCones; k++ )
+    {
+        pOne = ppCones[k];
+        assert( Gia_ManPoNum(pOne) == 1 );
+        assert( Gia_ManRegNum(pOne) == 0 );
+        if ( fOnlyRegs )
+            assert( Gia_ManPiNum(pOne) == Gia_ManRegNum(p) );
+        else
+            assert( Gia_ManPiNum(pOne) == Gia_ManCiNum(p) );
+        Gia_ManConst0(pOne)->Value = 0;
+        Gia_ManForEachPi( pOne, pObj, i )
+            pObj->Value = Gia_ManCiLit( pNew, fOnlyRegs ? Gia_ManPiNum(p) + i : i );
+        Gia_ManForEachAnd( pOne, pObj, i )
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        Gia_ManForEachPo( pOne, pObj, i )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+    Gia_ManForEachRi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    pNew = Gia_ManCleanup( pOne = pNew );
+    Gia_ManStop( pOne );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates while adding self-loops to the registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupSelf( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew, * pTemp; 
+    Gia_Obj_t * pObj;
+    int i, iCtrl;
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    iCtrl = Gia_ManAppendCi( pNew );
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachPo( p, pObj, i )
+        pObj->Value = Gia_ObjFanin0Copy(pObj);
+    Gia_ManForEachRi( p, pObj, i )
+        pObj->Value = Gia_ManHashMux( pNew, iCtrl, Gia_ObjFanin0Copy(pObj), Gia_ObjRiToRo(p, pObj)->Value );
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManAppendCo( pNew, pObj->Value );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates while adding self-loops to the registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupFlopClass( Gia_Man_t * p, int iClass )
+{
+    Gia_Man_t * pNew; 
+    Gia_Obj_t * pObj;
+    int i, Counter1 = 0, Counter2 = 0;
+    assert( p->vFlopClasses != NULL );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachRo( p, pObj, i )
+        if ( Vec_IntEntry(p->vFlopClasses, i) != iClass )
+            pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachRo( p, pObj, i )
+        if ( Vec_IntEntry(p->vFlopClasses, i) == iClass )
+            pObj->Value = Gia_ManAppendCi( pNew ), Counter1++;
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachPo( p, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManForEachRi( p, pObj, i )
+        if ( Vec_IntEntry(p->vFlopClasses, i) != iClass )
+            Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManForEachRi( p, pObj, i )
+        if ( Vec_IntEntry(p->vFlopClasses, i) == iClass )
+            Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ), Counter2++;
+    assert( Counter1 == Counter2 );
+    Gia_ManSetRegNum( pNew, Counter1 );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG without any changes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupMarked( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i, nRos = 0, nRis = 0;
+    int CountMarked = 0;
+    Gia_ManForEachObj( p, pObj, i )
+        CountMarked += pObj->fMark0;
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) - CountMarked );
+    if ( p->pMuxes )
+        pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc );
+    pNew->nConstrs = p->nConstrs;
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( pObj->fMark0 )
+        {
+            pObj->fMark0 = 0;
+            continue;
+        }
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            if ( Gia_ObjIsXor(pObj) )
+                pObj->Value = Gia_ManAppendXorReal( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+            else if ( Gia_ObjIsMux(p, pObj) )
+                pObj->Value = Gia_ManAppendMuxReal( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) );
+            else
+                pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        }
+        else if ( Gia_ObjIsCi(pObj) )
+        {
+            pObj->Value = Gia_ManAppendCi( pNew );
+            nRos += Gia_ObjIsRo(p, pObj);
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+        {
+//            Gia_Obj_t * pFanin = Gia_ObjFanin0(pObj);
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+            nRis += Gia_ObjIsRi(p, pObj);
+        }
+    }
+    assert( pNew->nObjsAlloc == pNew->nObjs );
+    assert( nRos == nRis );
+    Gia_ManSetRegNum( pNew, nRos );
+    if ( p->pReprs && p->pNexts )
+    {
+        Gia_Obj_t * pRepr;
+        pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pNew) );
+        for ( i = 0; i < Gia_ManObjNum(p); i++ )
+            Gia_ObjSetRepr( pNew, i, GIA_VOID );
+        Gia_ManForEachObj1( p, pObj, i )
+        {
+            if ( !~pObj->Value )
+                continue;
+            pRepr = Gia_ObjReprObj( p, i );
+            if ( pRepr == NULL )
+                continue;
+            if ( !~pRepr->Value )
+                continue;
+            if ( Abc_Lit2Var(pObj->Value) != Abc_Lit2Var(pRepr->Value) )
+                Gia_ObjSetRepr( pNew, Abc_Lit2Var(pObj->Value), Abc_Lit2Var(pRepr->Value) ); 
+        }
+        pNew->pNexts = Gia_ManDeriveNexts( pNew );
+    }
+    if ( Gia_ManHasChoices(p) )
+    {
+        Gia_Obj_t * pSibl;
+        pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(pNew) );
+        Gia_ManForEachObj1( p, pObj, i )
+        {
+            if ( !~pObj->Value )
+                continue;
+            pSibl = Gia_ObjSiblObj( p, i );
+            if ( pSibl == NULL )
+                continue;
+            if ( !~pSibl->Value )
+                continue;
+            assert( Abc_Lit2Var(pObj->Value) > Abc_Lit2Var(pSibl->Value) );
+            pNew->pSibls[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var(pSibl->Value);
+        }
+    }
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG while creating "parallel" copies.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupTimes( Gia_Man_t * p, int nTimes )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vPis, * vPos, * vRis, * vRos;
+    int i, t, Entry;
+    assert( nTimes > 0 );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    vPis = Vec_IntAlloc( Gia_ManPiNum(p) * nTimes );
+    vPos = Vec_IntAlloc( Gia_ManPoNum(p) * nTimes );
+    vRis = Vec_IntAlloc( Gia_ManRegNum(p) * nTimes );
+    vRos = Vec_IntAlloc( Gia_ManRegNum(p) * nTimes );
+    for ( t = 0; t < nTimes; t++ )
+    {
+        Gia_ManForEachObj1( p, pObj, i )
+        {
+            if ( Gia_ObjIsAnd(pObj) )
+                pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+            else if ( Gia_ObjIsCi(pObj) )
+            {
+                pObj->Value = Gia_ManAppendCi( pNew );
+                if ( Gia_ObjIsPi(p, pObj) )
+                    Vec_IntPush( vPis, Abc_Lit2Var(pObj->Value) );
+                else
+                    Vec_IntPush( vRos, Abc_Lit2Var(pObj->Value) );
+            }
+            else if ( Gia_ObjIsCo(pObj) )
+            {
+                pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+                if ( Gia_ObjIsPo(p, pObj) )
+                    Vec_IntPush( vPos, Abc_Lit2Var(pObj->Value) );
+                else
+                    Vec_IntPush( vRis, Abc_Lit2Var(pObj->Value) );
+            }
+        }
+    }
+    Vec_IntClear( pNew->vCis );
+    Vec_IntForEachEntry( vPis, Entry, i )
+    {
+        Gia_ObjSetCioId( Gia_ManObj(pNew, Entry), Vec_IntSize(pNew->vCis) );
+        Vec_IntPush( pNew->vCis, Entry );
+    }
+    Vec_IntForEachEntry( vRos, Entry, i )
+    {
+        Gia_ObjSetCioId( Gia_ManObj(pNew, Entry), Vec_IntSize(pNew->vCis) );
+        Vec_IntPush( pNew->vCis, Entry );
+    }
+    Vec_IntClear( pNew->vCos );
+    Vec_IntForEachEntry( vPos, Entry, i )
+    {
+        Gia_ObjSetCioId( Gia_ManObj(pNew, Entry), Vec_IntSize(pNew->vCos) );
+        Vec_IntPush( pNew->vCos, Entry );
+    }
+    Vec_IntForEachEntry( vRis, Entry, i )
+    {
+        Gia_ObjSetCioId( Gia_ManObj(pNew, Entry), Vec_IntSize(pNew->vCos) );
+        Vec_IntPush( pNew->vCos, Entry );
+    }
+    Vec_IntFree( vPis );
+    Vec_IntFree( vPos );
+    Vec_IntFree( vRis );
+    Vec_IntFree( vRos );
+    Gia_ManSetRegNum( pNew, nTimes * Gia_ManRegNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManDupDfs2_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( ~pObj->Value )
+        return pObj->Value;
+    if ( p->pReprsOld && ~p->pReprsOld[Gia_ObjId(p, pObj)] )
+    {
+        Gia_Obj_t * pRepr = Gia_ManObj( p, p->pReprsOld[Gia_ObjId(p, pObj)] );
+        pRepr->Value = Gia_ManDupDfs2_rec( pNew, p, pRepr );
+        return pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) );
+    }
+    if ( Gia_ObjIsCi(pObj) )
+        return pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManDupDfs2_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    if ( Gia_ObjIsCo(pObj) )
+        return pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManDupDfs2_rec( pNew, p, Gia_ObjFanin1(pObj) );
+    if ( pNew->pHTable )
+        return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    return pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupDfs2( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj, * pObjNew;
+    int i;
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManDupDfs2_rec( pNew, p, pObj );
+    Gia_ManForEachCi( p, pObj, i )
+        if ( ~pObj->Value == 0 )
+            pObj->Value = Gia_ManAppendCi(pNew);
+    assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) );
+    // remap combinational inputs
+    Gia_ManForEachCi( p, pObj, i )
+    {
+        pObjNew = Gia_ObjFromLit( pNew, pObj->Value );
+        assert( !Gia_IsComplement(pObjNew) );
+        Vec_IntWriteEntry( pNew->vCis, Gia_ObjCioId(pObj), Gia_ObjId(pNew, pObjNew) );
+        Gia_ObjSetCioId( pObjNew, Gia_ObjCioId(pObj) );
+    }
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManDupDfs_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( ~pObj->Value )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManDupDfs_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    Gia_ManDupDfs_rec( pNew, p, Gia_ObjFanin1(pObj) );
+    pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+}
+Gia_Man_t * Gia_ManDupDfs( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManDupDfs_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    pNew->nConstrs = p->nConstrs;
+    if ( p->pCexSeq )
+        pNew->pCexSeq = Abc_CexDup( p->pCexSeq, Gia_ManRegNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cofactors w.r.t. a primary input variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManDupCofactorVar_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( ~pObj->Value )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManDupCofactorVar_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    Gia_ManDupCofactorVar_rec( pNew, p, Gia_ObjFanin1(pObj) );
+    pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+}
+Gia_Man_t * Gia_ManDupCofactorVar( Gia_Man_t * p, int iVar, int Value )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( iVar >= 0 && iVar < Gia_ManPiNum(p) );
+    assert( Value == 0 || Value == 1 );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManPi( p, iVar )->Value = Value; // modification!
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManDupCofactorVar_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    pNew->nConstrs = p->nConstrs;
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cofactors w.r.t. an internal node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupCofactorObj( Gia_Man_t * p, int iObj, int Value )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, iObjValue = -1;
+    assert( Gia_ManRegNum(p) == 0 );
+    assert( iObj > 0 && iObj < Gia_ManObjNum(p) );
+    assert( Gia_ObjIsCand(Gia_ManObj(p, iObj)) );
+    assert( Value == 0 || Value == 1 );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Gia_ManAppendCi( pNew );
+        else if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ManHashAnd(pNew, Gia_ObjFanin0Copy(pObj), iObjValue) );
+        if ( i == iObj )
+            iObjValue = Abc_LitNotCond(pObj->Value, !Value), pObj->Value = Value;
+    }
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Existentially quantified given variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupExist( Gia_Man_t * p, int iVar )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( iVar >= 0 && iVar < Gia_ManPiNum(p) );
+    assert( Gia_ManPoNum(p) == 1 );
+    assert( Gia_ManRegNum(p) == 0 );
+    Gia_ManFillValue( p );
+    // find the cofactoring variable
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+    // compute negative cofactor
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManPi( p, iVar )->Value = Abc_Var2Lit( 0, 0 );
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachPo( p, pObj, i )
+        pObj->Value = Gia_ObjFanin0Copy(pObj);
+    // compute the positive cofactor
+    Gia_ManPi( p, iVar )->Value = Abc_Var2Lit( 0, 1 );
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    // create OR gate
+    Gia_ManForEachPo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ManHashOr(pNew, Gia_ObjFanin0Copy(pObj), pObj->Value) );
+    Gia_ManHashStop( pNew );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Existentially quantifies the given variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupExist2( Gia_Man_t * p, int iVar )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( iVar >= 0 && iVar < Gia_ManPiNum(p) );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManFillValue( p );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    // first part
+    Gia_ManPi( p, iVar )->Value = 0; // modification!
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManDupCofactorVar_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->Value = Gia_ObjFanin0Copy(pObj);
+    // second part
+    Gia_ManPi( p, iVar )->Value = 1; // modification!
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = ~0;
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManDupCofactorVar_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    // combination
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ManHashOr(pNew, Gia_ObjFanin0Copy(pObj), pObj->Value) );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    pNew->nConstrs = p->nConstrs;
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order while putting CIs first.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupDfsSkip( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManForEachCo( p, pObj, i )
+        if ( pObj->fMark1 == 0 )
+            Gia_ManDupDfs_rec( pNew, p, pObj );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order while putting CIs first.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupDfsCone( Gia_Man_t * p, Gia_Obj_t * pRoot )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Gia_ObjIsCo(pRoot) );
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManDupDfs_rec( pNew, p, Gia_ObjFanin0(pRoot) );
+    Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pRoot) );
+    Gia_ManSetRegNum( pNew, 0 );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order while putting CIs first.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManDupDfs3_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( ~pObj->Value )
+        return;
+    if ( Gia_ObjIsCi(pObj) )
+    {
+        pObj->Value = Gia_ManAppendCi(pNew);
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManDupDfs3_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    Gia_ManDupDfs3_rec( pNew, p, Gia_ObjFanin1(pObj) );
+    pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+}
+Gia_Man_t * Gia_ManDupDfsNode( Gia_Man_t * p, Gia_Obj_t * pRoot )
+{
+    Gia_Man_t * pNew;
+    assert( Gia_ObjIsAnd(pRoot) );
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManDupDfs3_rec( pNew, p, pRoot );
+    Gia_ManAppendCo( pNew, pRoot->Value );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order while putting CIs first.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupDfsLitArray( Gia_Man_t * p, Vec_Int_t * vLits )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i, iLit, iLitRes;
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Vec_IntForEachEntry( vLits, iLit, i )
+    {
+        iLitRes = Gia_ManDupDfs2_rec( pNew, p, Gia_ManObj(p, Abc_Lit2Var(iLit)) );
+        Gia_ManAppendCo( pNew, Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iLit)) );
+    }
+    Gia_ManSetRegNum( pNew, 0 );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of non-const-0 POs of the dual-output miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManDupTrimmedNonZero( Gia_Man_t * p )
+{
+    Vec_Int_t * vNonZero;
+    Gia_Man_t * pTemp, * pNonDual;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( (Gia_ManPoNum(p) & 1) == 0 );
+    pNonDual = Gia_ManTransformMiter( p );
+    pNonDual = Gia_ManSeqStructSweep( pTemp = pNonDual, 1, 1, 0 );
+    Gia_ManStop( pTemp );
+    assert( Gia_ManPiNum(pNonDual) > 0 );
+    assert( 2 * Gia_ManPoNum(pNonDual) == Gia_ManPoNum(p) );
+    // skip PO pairs corresponding to const0 POs of the non-dual miter
+    vNonZero = Vec_IntAlloc( 100 );
+    Gia_ManForEachPo( pNonDual, pObj, i )
+        if ( !Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) )
+            Vec_IntPush( vNonZero, i );
+    Gia_ManStop( pNonDual );
+    return vNonZero;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if PO can be removed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManPoIsToRemove( Gia_Man_t * p, Gia_Obj_t * pObj, int Value )
+{
+    assert( Gia_ObjIsCo(pObj) );
+    if ( Value == -1 )
+        return Gia_ObjIsConst0(Gia_ObjFanin0(pObj));
+    assert( Value == 0 || Value == 1 );
+    return Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) && Value == Gia_ObjFaninC0(pObj);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order while putting CIs first.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupTrimmed( Gia_Man_t * p, int fTrimCis, int fTrimCos, int fDualOut, int OutValue )
+{
+    Vec_Int_t * vNonZero = NULL;
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, Entry;
+    // collect non-zero
+    if ( fDualOut && fTrimCos )
+        vNonZero = Gia_ManDupTrimmedNonZero( p );
+    // start new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // check if there are PIs to be added
+    Gia_ManCreateRefs( p );
+    Gia_ManForEachPi( p, pObj, i )
+        if ( !fTrimCis || Gia_ObjRefNum(p, pObj) )
+            break;
+    if ( i == Gia_ManPiNum(p) ) // there is no PIs - add dummy PI
+        Gia_ManAppendCi(pNew);
+    // add the ROs
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        if ( !fTrimCis || Gia_ObjRefNum(p, pObj) || Gia_ObjIsRo(p, pObj) )
+            pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    if ( fDualOut && fTrimCos )
+    {
+        Vec_IntForEachEntry( vNonZero, Entry, i )
+        {
+            Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p, 2*Entry+0)) );
+            Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p, 2*Entry+1)) );
+        }
+        if ( Gia_ManPoNum(pNew) == 0 ) // nothing - add dummy PO
+        {
+//            Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p, 0)) );
+//            Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p, 1)) );
+            Gia_ManAppendCo( pNew, 0 );
+            Gia_ManAppendCo( pNew, 0 );
+        }
+        Gia_ManForEachRi( p, pObj, i )
+            Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+        Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+        // cleanup
+        pNew = Gia_ManSeqStructSweep( pTemp = pNew, 1, 1, 0 );
+        Gia_ManStop( pTemp );
+        // trim the PIs
+//        pNew = Gia_ManDupTrimmed( pTemp = pNew, 1, 0, 0 );
+//        Gia_ManStop( pTemp );
+    }
+    else
+    {
+        // check if there are POs to be added
+        Gia_ManForEachPo( p, pObj, i )
+            if ( !fTrimCos || !Gia_ManPoIsToRemove(p, pObj, OutValue) )
+                break;
+        if ( i == Gia_ManPoNum(p) ) // there is no POs - add dummy PO
+            Gia_ManAppendCo( pNew, 0 );
+        Gia_ManForEachCo( p, pObj, i )
+            if ( !fTrimCos || !Gia_ManPoIsToRemove(p, pObj, OutValue) || Gia_ObjIsRi(p, pObj) )
+                Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+        Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    }
+    Vec_IntFreeP( &vNonZero );
+    assert( !Gia_ManHasDangling( pNew ) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes POs driven by PIs and PIs without fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupTrimmed2( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    // start new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // check if there are PIs to be added
+    Gia_ManCreateRefs( p );
+    // discount references of POs
+    Gia_ManForEachPo( p, pObj, i )
+        Gia_ObjRefFanin0Dec( p, pObj );
+    // check if PIs are left
+    Gia_ManForEachPi( p, pObj, i )
+        if ( Gia_ObjRefNum(p, pObj) )
+            break;
+    if ( i == Gia_ManPiNum(p) ) // there is no PIs - add dummy PI
+        Gia_ManAppendCi(pNew);
+    // add the ROs
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        if ( Gia_ObjRefNum(p, pObj) || Gia_ObjIsRo(p, pObj) )
+            pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    // check if there are POs to be added
+    Gia_ManForEachPo( p, pObj, i )
+        if ( !Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) && !Gia_ObjIsPi(p, Gia_ObjFanin0(pObj)) )
+            break;
+    if ( i == Gia_ManPoNum(p) ) // there is no POs - add dummy PO
+        Gia_ManAppendCo( pNew, 0 );
+    Gia_ManForEachCo( p, pObj, i )
+        if ( (!Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) && !Gia_ObjIsPi(p, Gia_ObjFanin0(pObj))) || Gia_ObjIsRi(p, pObj) )
+            Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    assert( !Gia_ManHasDangling( pNew ) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order while putting CIs first.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupOntop( Gia_Man_t * p, Gia_Man_t * p2 )
+{
+    Gia_Man_t * pTemp, * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Gia_ManPoNum(p) == Gia_ManPiNum(p2) );
+    assert( Gia_ManRegNum(p) == 0 );
+    assert( Gia_ManRegNum(p2) == 0 );
+    pNew = Gia_ManStart( Gia_ManObjNum(p)+Gia_ManObjNum(p2) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+    // dup first AIG
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    // dup second AIG
+    Gia_ManConst0(p2)->Value = 0;
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManPi(p2, i)->Value = Gia_ObjFanin0Copy(pObj);
+    Gia_ManForEachAnd( p2, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachCo( p2, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManHashStop( pNew );
+//    Gia_ManPrintStats( pGiaNew, 0 );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates transition relation from p1 and property from p2.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupWithNewPo( Gia_Man_t * p1, Gia_Man_t * p2 )
+{
+    Gia_Man_t * pTemp, * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    // there is no flops in p2
+    assert( Gia_ManRegNum(p2) == 0 );
+    // there is only one PO in p2
+//    assert( Gia_ManPoNum(p2) == 1 );
+    // input count of p2 is equal to flop count of p1 
+    assert( Gia_ManPiNum(p2) == Gia_ManRegNum(p1) );
+
+    // start new AIG
+    pNew = Gia_ManStart( Gia_ManObjNum(p1)+Gia_ManObjNum(p2) );
+    pNew->pName = Abc_UtilStrsav( p1->pName );
+    pNew->pSpec = Abc_UtilStrsav( p1->pSpec );
+    Gia_ManHashAlloc( pNew );
+    // dup first AIG
+    Gia_ManConst0(p1)->Value = 0;
+    Gia_ManForEachCi( p1, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManForEachAnd( p1, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    // dup second AIG
+    Gia_ManConst0(p2)->Value = 0;
+    Gia_ManForEachPi( p2, pObj, i )
+        pObj->Value = Gia_ManRo(p1, i)->Value;
+    Gia_ManForEachAnd( p2, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    // add property output
+    Gia_ManForEachPo( p2, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    // add flop inputs
+    Gia_ManForEachRi( p1, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p1) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print representatives.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintRepr( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+        if ( ~p->pReprsOld[i] )
+            printf( "%d->%d ", i, p->pReprs[i].iRepr );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupDfsCiMap( Gia_Man_t * p, int * pCi2Lit, Vec_Int_t * vLits )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+    {
+        pObj->Value = Gia_ManAppendCi(pNew);
+        if ( ~pCi2Lit[i] )
+            pObj->Value = Abc_LitNotCond( Gia_ManObj(p, Abc_Lit2Var(pCi2Lit[i]))->Value, Abc_LitIsCompl(pCi2Lit[i]) );
+    }
+    Gia_ManHashAlloc( pNew );
+    if ( vLits )
+    {
+        int iLit, iLitRes;
+        Vec_IntForEachEntry( vLits, iLit, i )
+        {
+            iLitRes = Gia_ManDupDfs2_rec( pNew, p, Gia_ManObj(p, Abc_Lit2Var(iLit)) );
+            Gia_ManAppendCo( pNew, Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iLit)) );
+        }
+    }
+    else
+    {
+        Gia_ManForEachCo( p, pObj, i )
+        {
+            Gia_ManDupDfs2_rec( pNew, p, Gia_ObjFanin0(pObj) );
+            Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+        }
+    }
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupDfsClasses( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( p->pReprsOld != NULL );
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManDupDfs_rec( pNew, p, pObj );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detect topmost gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupTopAnd_iter( Gia_Man_t * p, int fVerbose )  
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vFront, * vLeaves;
+    int i, iLit, iObjId, nCiLits, * pCi2Lit;
+    char * pVar2Val;
+    // collect the frontier
+    vFront = Vec_IntAlloc( 1000 );
+    vLeaves = Vec_IntAlloc( 1000 );
+    Gia_ManForEachCo( p, pObj, i )
+    {
+        if ( Gia_ObjIsConst0( Gia_ObjFanin0(pObj) ) )
+            continue;
+        if ( Gia_ObjFaninC0(pObj) )
+            Vec_IntPush( vLeaves, Gia_ObjFaninLit0p(p, pObj) );
+        else
+            Vec_IntPush( vFront, Gia_ObjFaninId0p(p, pObj) );
+    }
+    if ( Vec_IntSize(vFront) == 0 )
+    {
+        if ( fVerbose )
+            printf( "The AIG cannot be decomposed using AND-decomposition.\n" );
+        Vec_IntFree( vFront );
+        Vec_IntFree( vLeaves );
+        return Gia_ManDupNormalize( p );
+    }
+    // expand the frontier
+    Gia_ManForEachObjVec( vFront, p, pObj, i )
+    {
+        if ( Gia_ObjIsCi(pObj) )
+        {
+            Vec_IntPush( vLeaves, Abc_Var2Lit( Gia_ObjId(p, pObj), 0 ) );
+            continue;
+        }
+        assert( Gia_ObjIsAnd(pObj) );
+        if ( Gia_ObjFaninC0(pObj) )
+            Vec_IntPush( vLeaves, Gia_ObjFaninLit0p(p, pObj) );
+        else
+            Vec_IntPush( vFront, Gia_ObjFaninId0p(p, pObj) );
+        if ( Gia_ObjFaninC1(pObj) )
+            Vec_IntPush( vLeaves, Gia_ObjFaninLit1p(p, pObj) );
+        else
+            Vec_IntPush( vFront, Gia_ObjFaninId1p(p, pObj) );
+    }
+    Vec_IntFree( vFront );
+    // sort the literals
+    nCiLits = 0;
+    pCi2Lit = ABC_FALLOC( int, Gia_ManObjNum(p) );
+    pVar2Val = ABC_FALLOC( char, Gia_ManObjNum(p) );
+    Vec_IntForEachEntry( vLeaves, iLit, i )
+    {
+        iObjId = Abc_Lit2Var(iLit);
+        pObj = Gia_ManObj(p, iObjId);
+        if ( Gia_ObjIsCi(pObj) )
+        {
+            pCi2Lit[Gia_ObjCioId(pObj)] = !Abc_LitIsCompl(iLit);
+            nCiLits++;
+        }
+        if ( pVar2Val[iObjId] != 0 && pVar2Val[iObjId] != 1 )
+            pVar2Val[iObjId] = Abc_LitIsCompl(iLit);
+        else if ( pVar2Val[iObjId] != Abc_LitIsCompl(iLit) )
+            break;
+    }
+    if ( i < Vec_IntSize(vLeaves) )
+    {
+        printf( "Problem is trivially UNSAT.\n" );
+        ABC_FREE( pCi2Lit );
+        ABC_FREE( pVar2Val );
+        Vec_IntFree( vLeaves );
+        return Gia_ManDupNormalize( p );
+    }
+    // create array of input literals
+    Vec_IntClear( vLeaves );
+    Gia_ManForEachObj( p, pObj, i )
+        if ( !Gia_ObjIsCi(pObj) && (pVar2Val[i] == 0 || pVar2Val[i] == 1) )
+            Vec_IntPush( vLeaves, Abc_Var2Lit(i, pVar2Val[i]) );
+    if ( fVerbose )
+        printf( "Detected %6d AND leaves and %6d CI leaves.\n", Vec_IntSize(vLeaves), nCiLits );
+    // create the input map
+    if ( nCiLits == 0 )
+        pNew = Gia_ManDupDfsLitArray( p, vLeaves );
+    else
+        pNew = Gia_ManDupDfsCiMap( p, pCi2Lit, vLeaves );
+    ABC_FREE( pCi2Lit );
+    ABC_FREE( pVar2Val );
+    Vec_IntFree( vLeaves );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detect topmost gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupTopAnd( Gia_Man_t * p, int fVerbose )  
+{
+    Gia_Man_t * pNew, * pTemp;
+    int fContinue, iIter = 0;
+    pNew = Gia_ManDupNormalize( p );
+    for ( fContinue = 1; fContinue; )
+    {
+        pNew = Gia_ManDupTopAnd_iter( pTemp = pNew, fVerbose );
+        if ( Gia_ManCoNum(pNew) == Gia_ManCoNum(pTemp) && Gia_ManAndNum(pNew) == Gia_ManAndNum(pTemp) )
+            fContinue = 0;
+        Gia_ManStop( pTemp );
+        if ( fVerbose )
+        {
+            printf( "Iter %2d : ", ++iIter );
+            Gia_ManPrintStatsShort( pNew );
+        }
+    }
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManMiter_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( ~pObj->Value )
+        return pObj->Value;
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManMiter_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    Gia_ManMiter_rec( pNew, p, Gia_ObjFanin1(pObj) );
+    return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates miter of two designs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManMiter( Gia_Man_t * p0, Gia_Man_t * p1, int nInsDup, int fDualOut, int fSeq, int fImplic, int fVerbose )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, iLit;
+    if ( fSeq )
+    {
+        if ( Gia_ManPiNum(p0) != Gia_ManPiNum(p1) )
+        {
+            printf( "Gia_ManMiter(): Designs have different number of PIs.\n" );
+            return NULL;
+        }
+        if ( Gia_ManPoNum(p0) != Gia_ManPoNum(p1) )
+        {
+            printf( "Gia_ManMiter(): Designs have different number of POs.\n" );
+            return NULL;
+        }
+        if ( Gia_ManRegNum(p0) == 0 || Gia_ManRegNum(p1) == 0 )
+        {
+            printf( "Gia_ManMiter(): At least one of the designs has no registers.\n" );
+            return NULL;
+        }
+    }
+    else
+    {
+        if ( Gia_ManCiNum(p0) != Gia_ManCiNum(p1) )
+        {
+            printf( "Gia_ManMiter(): Designs have different number of CIs.\n" );
+            return NULL;
+        }
+        if ( Gia_ManCoNum(p0) != Gia_ManCoNum(p1) )
+        {
+            printf( "Gia_ManMiter(): Designs have different number of COs.\n" );
+            return NULL;
+        }
+    }
+    // start the manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p0) + Gia_ManObjNum(p1) );
+    pNew->pName = Abc_UtilStrsav( "miter" );
+    // map combinational inputs
+    Gia_ManFillValue( p0 );
+    Gia_ManFillValue( p1 );
+    Gia_ManConst0(p0)->Value = 0;
+    Gia_ManConst0(p1)->Value = 0;
+    // map internal nodes and outputs
+    Gia_ManHashAlloc( pNew );
+    if ( fSeq )
+    {
+        // create primary inputs
+        Gia_ManForEachPi( p0, pObj, i )
+            pObj->Value = Gia_ManAppendCi( pNew );
+        Gia_ManForEachPi( p1, pObj, i )
+            if ( i < Gia_ManPiNum(p1) - nInsDup )
+                pObj->Value = Gia_ObjToLit( pNew, Gia_ManPi(pNew, i) );
+            else
+                pObj->Value = Gia_ManAppendCi( pNew );
+        // create latch outputs
+        Gia_ManForEachRo( p0, pObj, i )
+            pObj->Value = Gia_ManAppendCi( pNew );
+        Gia_ManForEachRo( p1, pObj, i )
+            pObj->Value = Gia_ManAppendCi( pNew );
+        // create primary outputs
+        Gia_ManForEachPo( p0, pObj, i )
+        {
+            Gia_ManMiter_rec( pNew, p0, Gia_ObjFanin0(pObj) );
+            Gia_ManMiter_rec( pNew, p1, Gia_ObjFanin0(Gia_ManPo(p1,i)) );
+            if ( fDualOut )
+            {
+                Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+                Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p1,i)) );
+            }
+            else if ( fImplic )
+            {
+                iLit = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Abc_LitNot(Gia_ObjFanin0Copy(Gia_ManPo(p1,i))) );
+                Gia_ManAppendCo( pNew, iLit );
+            }
+            else 
+            {
+                iLit = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(Gia_ManPo(p1,i)) );
+                Gia_ManAppendCo( pNew, iLit );
+            }
+        }
+        // create register inputs
+        Gia_ManForEachRi( p0, pObj, i )
+        {
+            Gia_ManMiter_rec( pNew, p0, Gia_ObjFanin0(pObj) );
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+        }
+        Gia_ManForEachRi( p1, pObj, i )
+        {
+            Gia_ManMiter_rec( pNew, p1, Gia_ObjFanin0(pObj) );
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+        }
+        Gia_ManSetRegNum( pNew, Gia_ManRegNum(p0) + Gia_ManRegNum(p1) );
+    }
+    else
+    {
+        // create combinational inputs
+        Gia_ManForEachCi( p0, pObj, i )
+            pObj->Value = Gia_ManAppendCi( pNew );
+        Gia_ManForEachCi( p1, pObj, i )
+            if ( i < Gia_ManCiNum(p1) - nInsDup )
+                pObj->Value = Gia_ObjToLit( pNew, Gia_ManCi(pNew, i) );
+            else
+                pObj->Value = Gia_ManAppendCi( pNew );
+        // create combinational outputs
+        Gia_ManForEachCo( p0, pObj, i )
+        {
+            Gia_ManMiter_rec( pNew, p0, Gia_ObjFanin0(pObj) );
+            Gia_ManMiter_rec( pNew, p1, Gia_ObjFanin0(Gia_ManCo(p1,i)) );
+            if ( fDualOut )
+            {
+                Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+                Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManCo(p1,i)) );
+            }
+            else if ( fImplic )
+            {
+                iLit = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Abc_LitNot(Gia_ObjFanin0Copy(Gia_ManPo(p1,i))) );
+                Gia_ManAppendCo( pNew, iLit );
+            }
+            else
+            {
+                iLit = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(Gia_ManCo(p1,i)) );
+                Gia_ManAppendCo( pNew, iLit );
+            }
+        }
+    }
+    Gia_ManHashStop( pNew );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+
+    pNew = Gia_ManDupNormalize( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the AND of all POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupAndOr( Gia_Man_t * p, int nOuts, int fUseOr, int fCompl )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, iResult;
+    assert( Gia_ManRegNum(p) == 0 );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    if ( fUseOr ) // construct OR of all POs
+    {
+        iResult = 0;
+        Gia_ManForEachPo( p, pObj, i )
+            iResult = Gia_ManHashOr( pNew, iResult, Gia_ObjFanin0Copy(pObj) );
+    }
+    else // construct AND of all POs
+    {
+        iResult = 1;
+        Gia_ManForEachPo( p, pObj, i )
+            iResult = Gia_ManHashAnd( pNew, iResult, Gia_ObjFanin0Copy(pObj) );
+    }
+    iResult = Abc_LitNotCond( iResult, (int)(fCompl > 0) );
+//    Gia_ManForEachPo( p, pObj, i )
+//        pObj->Value = Gia_ManAppendCo( pNew, iResult );
+    for ( i = 0; i < nOuts; i++ )
+        Gia_ManAppendCo( pNew, iResult );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the circuit into a regular miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManTransformMiter( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pObj2;
+    int i, iLit;
+    assert( (Gia_ManPoNum(p) & 1) == 0 );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachPo( p, pObj, i )
+    {
+        pObj2 = Gia_ManPo( p, ++i );
+        iLit = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(pObj2) );
+        Gia_ManAppendCo( pNew, iLit );
+    }
+    Gia_ManForEachRi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs 'zero' and 'undc' operation.]
+
+  Description [The init string specifies 0/1/X for each flop.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupZeroUndc( Gia_Man_t * p, char * pInit, int fVerbose )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int CountPis = Gia_ManPiNum(p), * pPiLits;
+    int i, iResetFlop = -1, Count1 = 0;
+    // map X-valued flops into new PIs
+    assert( (int)strlen(pInit) == Gia_ManRegNum(p) );
+    pPiLits = ABC_FALLOC( int, Gia_ManRegNum(p) );
+    for ( i = 0; i < Gia_ManRegNum(p); i++ )
+        if ( pInit[i] == 'x' || pInit[i] == 'X' )
+            pPiLits[i] = CountPis++;
+    // create new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    // create primary inputs
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    // create additional primary inputs
+    for ( i = Gia_ManPiNum(p); i < CountPis; i++ )
+        Gia_ManAppendCi( pNew );
+    // create flop outputs
+    Gia_ManForEachRo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    // create reset flop output
+    if ( CountPis > Gia_ManPiNum(p) )
+        iResetFlop = Gia_ManAppendCi( pNew );
+    // update flop outputs
+    Gia_ManForEachRo( p, pObj, i )
+    {
+        if ( pInit[i] == '1' )
+            pObj->Value = Abc_LitNot(pObj->Value), Count1++;
+        else if ( pInit[i] == 'x' || pInit[i] == 'X' )
+            pObj->Value = Gia_ManAppendMux( pNew, iResetFlop, pObj->Value, Gia_Obj2Lit(pNew, Gia_ManPi(pNew, pPiLits[i])) );
+        else if ( pInit[i] != '0' )
+            assert( 0 );
+    }
+    ABC_FREE( pPiLits );
+    // build internal nodes
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    // create POs
+    Gia_ManForEachPo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    // create flop inputs
+    Gia_ManForEachRi( p, pObj, i )
+        if ( pInit[i] == '1' )
+            pObj->Value = Gia_ManAppendCo( pNew, Abc_LitNot(Gia_ObjFanin0Copy(pObj)) );
+        else
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    // create reset flop input
+    if ( CountPis > Gia_ManPiNum(p) )
+        Gia_ManAppendCo( pNew, 1 );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) + (int)(CountPis > Gia_ManPiNum(p)) );
+    if ( fVerbose )
+        printf( "Converted %d 1-valued FFs and %d DC-valued FFs.\n", Count1, CountPis-Gia_ManPiNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates miter of two designs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManMiter2( Gia_Man_t * pStart, char * pInit, int fVerbose )
+{
+    Vec_Int_t * vCiValues, * vCoValues0, * vCoValues1;
+    Gia_Man_t * pNew, * pUndc, * pTemp;
+    Gia_Obj_t * pObj;
+    char * pInitNew;
+    int i, k;
+    // check PI values
+    for ( i = 0; i < Gia_ManPiNum(pStart); i++ )
+        assert( pInit[i] == 'x' || pInit[i] == 'X' );
+    // normalize the manager
+    pUndc = Gia_ManDupZeroUndc( pStart, pInit + Gia_ManPiNum(pStart), fVerbose );
+    // create new init string
+    pInitNew = ABC_ALLOC( char, Gia_ManPiNum(pUndc)+1 );
+    for ( i = 0; i < Gia_ManPiNum(pStart); i++ )
+        pInitNew[i] = pInit[i];
+    for ( i = k = Gia_ManPiNum(pStart); i < Gia_ManCiNum(pStart); i++ )
+        if ( pInit[i] == 'x' || pInit[i] == 'X' )
+            pInitNew[k++] = pInit[i];
+    pInitNew[k] = 0;
+    assert( k == Gia_ManPiNum(pUndc) );
+    // derive miter
+    pNew = Gia_ManStart( Gia_ManObjNum(pUndc) );
+    pNew->pName = Abc_UtilStrsav( pUndc->pName );
+    pNew->pSpec = Abc_UtilStrsav( pUndc->pSpec );
+    Gia_ManConst0(pUndc)->Value = 0;
+    Gia_ManHashAlloc( pNew );
+    // add PIs of the first side
+    Gia_ManForEachPi( pUndc, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    // add PIs of the second side
+    vCiValues = Vec_IntAlloc( Gia_ManPiNum(pUndc) );
+    Gia_ManForEachPi( pUndc, pObj, i )
+        if ( pInitNew[i] == 'x' )
+            Vec_IntPush( vCiValues, Gia_Obj2Lit( pNew, Gia_ManPi(pNew, i) ) );
+        else if ( pInitNew[i] == 'X' ) 
+            Vec_IntPush( vCiValues, Gia_ManAppendCi( pNew ) );
+        else assert( 0 );
+    // build flops and internal nodes
+    Gia_ManForEachRo( pUndc, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachAnd( pUndc, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    // collect CO values
+    vCoValues0 = Vec_IntAlloc( Gia_ManPoNum(pUndc) );
+    Gia_ManForEachCo( pUndc, pObj, i )
+        Vec_IntPush( vCoValues0, Gia_ObjFanin0Copy(pObj) );
+    // build the other side
+    Gia_ManForEachPi( pUndc, pObj, i )
+        pObj->Value = Vec_IntEntry( vCiValues, i );
+    Gia_ManForEachRo( pUndc, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachAnd( pUndc, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    // collect CO values
+    vCoValues1 = Vec_IntAlloc( Gia_ManPoNum(pUndc) );
+    Gia_ManForEachCo( pUndc, pObj, i )
+        Vec_IntPush( vCoValues1, Gia_ObjFanin0Copy(pObj) );
+    // create POs
+    Gia_ManForEachPo( pUndc, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ManHashXor( pNew, Vec_IntEntry(vCoValues0, i), Vec_IntEntry(vCoValues1, i) ) );
+    // create flop inputs
+    Gia_ManForEachRi( pUndc, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Vec_IntEntry(vCoValues0, Gia_ManPoNum(pUndc)+i) );
+    Gia_ManForEachRi( pUndc, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Vec_IntEntry(vCoValues1, Gia_ManPoNum(pUndc)+i) );
+    Vec_IntFree( vCoValues0 );
+    Vec_IntFree( vCoValues1 );
+    Vec_IntFree( vCiValues );
+    ABC_FREE( pInitNew );
+    // cleanup
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, 2*Gia_ManRegNum(pUndc) );
+    Gia_ManStop( pUndc );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManChoiceMiter_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( ~pObj->Value )
+        return pObj->Value;
+    Gia_ManChoiceMiter_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    if ( Gia_ObjIsCo(pObj) )
+        return pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManChoiceMiter_rec( pNew, p, Gia_ObjFanin1(pObj) );
+    return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the miter of several AIGs for choice computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManChoiceMiter( Vec_Ptr_t * vGias )
+{
+    Gia_Man_t * pNew, * pGia, * pGia0;
+    int i, k, iNode, nNodes;
+    // make sure they have equal parameters
+    assert( Vec_PtrSize(vGias) > 0 );
+    pGia0 = (Gia_Man_t *)Vec_PtrEntry( vGias, 0 );
+    Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i )
+    {
+        assert( Gia_ManCiNum(pGia)  == Gia_ManCiNum(pGia0) );
+        assert( Gia_ManCoNum(pGia)  == Gia_ManCoNum(pGia0) );
+        assert( Gia_ManRegNum(pGia) == Gia_ManRegNum(pGia0) );
+        Gia_ManFillValue( pGia );
+        Gia_ManConst0(pGia)->Value = 0;
+    }
+    // start the new manager
+    pNew = Gia_ManStart( Vec_PtrSize(vGias) * Gia_ManObjNum(pGia0) );
+    pNew->pName = Abc_UtilStrsav( pGia0->pName );
+    pNew->pSpec = Abc_UtilStrsav( pGia0->pSpec );
+    // create new CIs and assign them to the old manager CIs
+    for ( k = 0; k < Gia_ManCiNum(pGia0); k++ )
+    {
+        iNode = Gia_ManAppendCi(pNew);
+        Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i )
+            Gia_ManCi( pGia, k )->Value = iNode; 
+    }
+    // create internal nodes
+    Gia_ManHashAlloc( pNew );
+    for ( k = 0; k < Gia_ManCoNum(pGia0); k++ )
+    {
+        Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i )
+            Gia_ManChoiceMiter_rec( pNew, pGia, Gia_ManCo( pGia, k ) );
+    }
+    Gia_ManHashStop( pNew );
+    // check the presence of dangling nodes
+    nNodes = Gia_ManHasDangling( pNew );
+    assert( nNodes == 0 );
+    // finalize
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia0) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG while putting first PIs, then nodes, then POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupWithConstraints( Gia_Man_t * p, Vec_Int_t * vPoTypes )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i, nConstr = 0;
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachPo( p, pObj, i )
+        if ( Vec_IntEntry(vPoTypes, i) == 0 ) // regular PO
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManForEachPo( p, pObj, i )
+        if ( Vec_IntEntry(vPoTypes, i) == 1 ) // constraint (should be complemented!)
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ^ 1 ), nConstr++;
+    Gia_ManForEachRi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+//    Gia_ManDupRemapEquiv( pNew, p );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    pNew->nConstrs = nConstr;
+    assert( Gia_ManIsNormalized(pNew) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Copy an AIG structure related to the selected POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ObjCompareByCioId( Gia_Obj_t ** pp1, Gia_Obj_t ** pp2 )
+{
+    Gia_Obj_t * pObj1 = *pp1;
+    Gia_Obj_t * pObj2 = *pp2;
+    return Gia_ObjCioId(pObj1) - Gia_ObjCioId(pObj2);
+}
+void Gia_ManDupCones_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vRoots )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        Gia_ManDupCones_rec( p, Gia_ObjFanin0(pObj), vLeaves, vNodes, vRoots );
+        Gia_ManDupCones_rec( p, Gia_ObjFanin1(pObj), vLeaves, vNodes, vRoots );
+        Vec_PtrPush( vNodes, pObj );
+    }
+    else if ( Gia_ObjIsCo(pObj) )
+        Gia_ManDupCones_rec( p, Gia_ObjFanin0(pObj), vLeaves, vNodes, vRoots );
+    else if ( Gia_ObjIsRo(p, pObj) )
+        Vec_PtrPush( vRoots, Gia_ObjRoToRi(p, pObj) );
+    else if ( Gia_ObjIsPi(p, pObj) )
+        Vec_PtrPush( vLeaves, pObj );
+    else assert( 0 );
+}
+Gia_Man_t * Gia_ManDupCones( Gia_Man_t * p, int * pPos, int nPos, int fTrimPis )
+{
+    Gia_Man_t * pNew;
+    Vec_Ptr_t * vLeaves, * vNodes, * vRoots;
+    Gia_Obj_t * pObj;
+    int i;
+
+    // collect initial POs
+    vLeaves = Vec_PtrAlloc( 100 );
+    vNodes = Vec_PtrAlloc( 100 );
+    vRoots = Vec_PtrAlloc( 100 );
+    for ( i = 0; i < nPos; i++ )
+        Vec_PtrPush( vRoots, Gia_ManPo(p, pPos[i]) );
+
+    // mark internal nodes
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+    Vec_PtrForEachEntry( Gia_Obj_t *, vRoots, pObj, i )
+        Gia_ManDupCones_rec( p, pObj, vLeaves, vNodes, vRoots );
+    Vec_PtrSort( vLeaves, (int (*)(void))Gia_ObjCompareByCioId );
+
+    // start the new manager
+//    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Vec_PtrSize(vLeaves) + Vec_PtrSize(vNodes) + Vec_PtrSize(vRoots) + 1);
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // map the constant node
+    Gia_ManConst0(p)->Value = 0;
+    // create PIs
+    if ( fTrimPis )
+    {
+        Vec_PtrForEachEntry( Gia_Obj_t *, vLeaves, pObj, i )
+            pObj->Value = Gia_ManAppendCi( pNew );
+    }
+    else
+    {
+        Gia_ManForEachPi( p, pObj, i )
+            pObj->Value = Gia_ManAppendCi( pNew );
+    }
+    // create LOs
+    Vec_PtrForEachEntryStart( Gia_Obj_t *, vRoots, pObj, i, nPos )
+        Gia_ObjRiToRo(p, pObj)->Value = Gia_ManAppendCi( pNew );
+    // create internal nodes
+    Vec_PtrForEachEntry( Gia_Obj_t *, vNodes, pObj, i )
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    // create COs
+    Vec_PtrForEachEntry( Gia_Obj_t *, vRoots, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    // finalize
+    Gia_ManSetRegNum( pNew, Vec_PtrSize(vRoots)-nPos );
+    Vec_PtrFree( vLeaves );
+    Vec_PtrFree( vNodes );
+    Vec_PtrFree( vRoots );
+    return pNew;
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generates AIG representing 1-hot condition for N inputs.]
+
+  Description [The condition is true of all POs are 0.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManOneHot( int nSkips, int nVars )
+{
+    Gia_Man_t * p;
+    int i, b, Shift, iGiaLit, nLogVars = Abc_Base2Log( nVars );
+    int * pTemp = ABC_CALLOC( int, (1 << nLogVars) );
+    p = Gia_ManStart( nSkips + 4 * nVars + 1 );
+    p->pName = Abc_UtilStrsav( "onehot" );
+    for ( i = 0; i < nSkips; i++ )
+        Gia_ManAppendCi( p );
+    for ( i = 0; i < nVars; i++ )
+        pTemp[i] = Gia_ManAppendCi( p );
+    Gia_ManHashStart( p );
+    for ( b = 0; b < nLogVars; b++ )
+        for ( i = 0, Shift = (1<<b); i < (1 << nLogVars); i += 2*Shift )
+        {
+            iGiaLit = Gia_ManHashAnd( p, pTemp[i], pTemp[i + Shift] );
+            if ( iGiaLit )
+                Gia_ManAppendCo( p, iGiaLit );
+            pTemp[i] = Gia_ManHashOr( p, pTemp[i], pTemp[i + Shift] );
+        }
+    Gia_ManHashStop( p );
+    Gia_ManAppendCo( p, Abc_LitNot(pTemp[0]) );
+    ABC_FREE( pTemp );
+    assert( Gia_ManObjNum(p) <= nSkips + 4 * nVars + 1 );
+    return p;
+}
+Gia_Man_t * Gia_ManDupOneHot( Gia_Man_t * p )
+{
+    Gia_Man_t * pOneHot, * pNew = Gia_ManDup( p );
+    if ( Gia_ManRegNum(pNew) == 0 )
+    {
+        Abc_Print( 0, "Appending 1-hotness constraints to the PIs.\n" );
+        pOneHot = Gia_ManOneHot( 0, Gia_ManCiNum(pNew) );
+    }
+    else
+        pOneHot = Gia_ManOneHot( Gia_ManPiNum(pNew), Gia_ManRegNum(pNew) );
+    Gia_ManDupAppendShare( pNew, pOneHot );
+    pNew->nConstrs += Gia_ManPoNum(pOneHot);
+    Gia_ManStop( pOneHot );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG with nodes ordered by level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupLevelized( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i, nLevels = Gia_ManLevelNum( p );
+    int * pCounts = ABC_CALLOC( int, nLevels + 1 );
+    int * pNodes = ABC_ALLOC( int, Gia_ManAndNum(p) );
+    Gia_ManForEachAnd( p, pObj, i )
+        pCounts[Gia_ObjLevel(p, pObj)]++;
+    for ( i = 1; i <= nLevels; i++ )
+        pCounts[i] += pCounts[i-1];
+    Gia_ManForEachAnd( p, pObj, i )
+        pNodes[pCounts[Gia_ObjLevel(p, pObj)-1]++] = i;
+    // duplicate
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    for ( i = 0; i < Gia_ManAndNum(p) && (pObj = Gia_ManObj(p, pNodes[i])); i++ )
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    ABC_FREE( pCounts );
+    ABC_FREE( pNodes );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupFromVecs( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, int nRegs )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    // start the new manager
+    pNew = Gia_ManStart( 5000 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // create constant
+    Gia_ManConst0(p)->Value = 0;
+    // create PIs
+    Gia_ManForEachObjVec( vCis, p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    // create internal nodes
+    Gia_ManForEachObjVec( vAnds, p, pObj, i )
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    // create ROs
+    Gia_ManForEachObjVec( vCos, p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManSetRegNum( pNew, nRegs );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupSliced( Gia_Man_t * p, int nSuppMax )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    // start the new manager
+    pNew = Gia_ManStart( 5000 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    // create constant and PIs
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    // create internal nodes
+    Gia_ManCleanMark01(p);
+    Gia_ManForEachAnd( p, pObj, i )
+        if ( Gia_ManSuppSize(p, &i, 1) <= nSuppMax )
+        {
+            pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+            pObj->fMark0 = 1;
+        }
+        else 
+        {
+            Gia_ObjFanin0(pObj)->fMark1 = 1;
+            Gia_ObjFanin1(pObj)->fMark1 = 1;
+        }
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ObjFanin0(pObj)->fMark1 = 1;
+    // add POs for the nodes pointed to
+    Gia_ManForEachAnd( p, pObj, i )
+        if ( pObj->fMark0 && pObj->fMark1 )
+            Gia_ManAppendCo( pNew, pObj->Value );
+    // cleanup and leave
+    Gia_ManCleanMark01(p);
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Extract constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManDupWithConstrCollectAnd_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper, int fFirst )
+{
+    if ( (Gia_IsComplement(pObj) || !Gia_ObjIsAnd(pObj)) && !fFirst )
+    {
+        Vec_IntPushUnique( vSuper, Gia_ObjToLit(p, pObj) );
+        return;
+    }
+    Gia_ManDupWithConstrCollectAnd_rec( p, Gia_ObjChild0(pObj), vSuper, 0 );
+    Gia_ManDupWithConstrCollectAnd_rec( p, Gia_ObjChild1(pObj), vSuper, 0 );
+}
+Gia_Man_t * Gia_ManDupWithConstr( Gia_Man_t * p )
+{
+    Vec_Int_t * vSuper;
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, iDriver, iLit, iLitBest = -1, LevelBest = -1;
+    assert( Gia_ManPoNum(p) == 1 );
+    assert( Gia_ManRegNum(p) == 0 );
+    pObj = Gia_ManPo( p, 0 );
+    if ( Gia_ObjFaninC0(pObj) )
+    {
+        printf( "The miter's output is not AND-decomposable.\n" );
+        return NULL;
+    }
+    vSuper = Vec_IntAlloc( 100 );
+    Gia_ManDupWithConstrCollectAnd_rec( p, Gia_ObjChild0(pObj), vSuper, 1 );
+    assert( Vec_IntSize(vSuper) > 1 );
+    // find the highest level
+    Gia_ManLevelNum( p );
+    Vec_IntForEachEntry( vSuper, iLit, i )
+        if ( LevelBest < Gia_ObjLevelId(p, Abc_Lit2Var(iLit)) )
+            LevelBest = Gia_ObjLevelId(p, Abc_Lit2Var(iLit)), iLitBest = iLit;
+    assert( iLitBest != -1 );
+    // create new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Gia_ManAppendCi( pNew );
+    }
+    // create AND of nodes
+    iDriver = -1;
+    Vec_IntForEachEntry( vSuper, iLit, i )
+    {
+        if ( iLit == iLitBest )
+            continue;
+        if ( iDriver == -1 )
+            iDriver = Gia_ObjLitCopy(p, iLit);
+        else
+            iDriver = Gia_ManHashAnd( pNew, iDriver, Gia_ObjLitCopy(p, iLit) );
+    }
+    // create the main PO
+    Gia_ManAppendCo( pNew, Gia_ObjLitCopy(p, iLitBest) );
+    // create the constraint PO
+    Gia_ManAppendCo( pNew, Abc_LitNot(iDriver) );
+    pNew->nConstrs = 1;
+    // rehash
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    Vec_IntFree( vSuper );
+    return pNew;
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares two objects by their distance.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManSortByValue( Gia_Obj_t ** pp1, Gia_Obj_t ** pp2 )
+{
+    int Diff = Gia_Regular(*pp1)->Value - Gia_Regular(*pp2)->Value;
+    if ( Diff < 0 )
+        return -1;
+    if ( Diff > 0 ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Decomposes the miter outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupDemiter( Gia_Man_t * p, int fVerbose )
+{
+    Vec_Int_t * vSuper;
+    Vec_Ptr_t * vSuperPtr;
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pObjPo;
+    int i, iLit;
+    assert( Gia_ManPoNum(p) == 1 );
+    // decompose
+    pObjPo = Gia_ManPo( p, 0 );
+    vSuper = Vec_IntAlloc( 100 );
+    Gia_ManDupWithConstrCollectAnd_rec( p, Gia_ObjFanin0(pObjPo), vSuper, 1 );
+    assert( Vec_IntSize(vSuper) > 1 );
+    // report the result
+    printf( "The miter is %s-decomposable into %d parts.\n", Gia_ObjFaninC0(pObjPo) ? "OR":"AND", Vec_IntSize(vSuper) );
+    // create levels
+    Gia_ManLevelNum( p );
+    Vec_IntForEachEntry( vSuper, iLit, i )
+        Gia_ManObj(p, Abc_Lit2Var(iLit))->Value = Gia_ObjLevelId(p, Abc_Lit2Var(iLit));
+    // create pointer array
+    vSuperPtr = Vec_PtrAlloc( Vec_IntSize(vSuper) );
+    Vec_IntForEachEntry( vSuper, iLit, i )
+        Vec_PtrPush( vSuperPtr, Gia_Lit2Obj(p, iLit) );
+    Vec_PtrSort( vSuperPtr, (int (*)(void))Gia_ManSortByValue );
+    // create new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    // create the outputs
+    Vec_PtrForEachEntry( Gia_Obj_t *, vSuperPtr, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjLitCopy(p, Gia_Obj2Lit(p, pObj)) ^ Gia_ObjFaninC0(pObjPo) );
+    Gia_ManForEachRi( p, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    // rehash
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    Vec_IntFree( vSuper );
+    Vec_PtrFree( vSuperPtr );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaEmbed.c b/abc-build/src/aig/gia/giaEmbed.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaEmbed.c
@@ -0,0 +1,1876 @@
+/**CFile****************************************************************
+
+  FileName    [giaEmbed.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Logic network derived from AIG.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaEmbed.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <math.h>
+#include "gia.h"
+#include "aig/ioa/ioa.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/* 
+    The code is based on the paper by D. Harel and Y. Koren, 
+    "Graph drawing by high-dimensional embedding", 
+    J. Graph Algs & Apps, Vol 8(2), pp. 195-217 (2004).
+    http://www.emis.de/journals/JGAA/accepted/2004/HarelKoren2004.8.2.pdf 
+
+    Iterative refinement is described in the paper: F. A. Aloul, I. L. Markov, and K. A. Sakallah.
+    "FORCE: A Fast and Easy-To-Implement Variable-Ordering Heuristic", Proc. GLSVLSI03.
+    http://www.eecs.umich.edu/~imarkov/pubs/conf/glsvlsi03-force.pdf
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define GIA_PLACE_SIZE 0x7fff 
+// objects will be placed in box [0, GIA_PLACE_SIZE] x [0, GIA_PLACE_SIZE]
+
+typedef float  Emb_Dat_t;
+
+typedef struct Emb_Obj_t_ Emb_Obj_t;
+struct Emb_Obj_t_
+{
+    unsigned       fCi      :  1;    // terminal node CI
+    unsigned       fCo      :  1;    // terminal node CO
+    unsigned       fMark0   :  1;    // first user-controlled mark
+    unsigned       fMark1   :  1;    // second user-controlled mark
+    unsigned       nFanins  : 28;    // the number of fanins
+    unsigned       nFanouts;         // the number of fanouts
+    int            hHandle;          // the handle of the node
+    union {
+    unsigned       TravId;           // user-specified value
+    unsigned       iFanin; 
+    };
+    union {
+    unsigned       Value;            // user-specified value
+    unsigned       iFanout; 
+    };
+    int            Fanios[0];        // the array of fanins/fanouts
+};
+
+typedef struct Emb_Man_t_ Emb_Man_t;
+struct Emb_Man_t_
+{
+    Gia_Man_t *    pGia;             // the original AIG manager
+    Vec_Int_t *    vCis;             // the vector of CIs (PIs + LOs)
+    Vec_Int_t *    vCos;             // the vector of COs (POs + LIs)
+    int            nObjs;            // the number of objects
+    int            nRegs;            // the number of registers
+    int            nTravIds;         // traversal ID of the network
+    int *          pObjData;         // the array containing data for objects
+    int            nObjData;         // the size of array to store the logic network
+    int            fVerbose;         // verbose output flag
+    Emb_Dat_t *    pVecs;            // array of vectors of size nObjs * nDims
+    int            nReached;         // the number of nodes reachable from the pivot
+    int            nDistMax;         // the maximum distance from the node
+    float **       pMatr;            // covariance matrix nDims * nDims
+    float **       pEigen;           // the first several eigen values of the matrix
+    float *        pSols;            // solutions to the problem nObjs * nSols;
+    unsigned short*pPlacement;       // (x,y) coordinates for each cell
+};
+
+static inline int         Emb_ManRegNum( Emb_Man_t * p )                              { return p->nRegs;                                    }
+static inline int         Emb_ManCiNum( Emb_Man_t * p )                               { return Vec_IntSize(p->vCis);                        }
+static inline int         Emb_ManCoNum( Emb_Man_t * p )                               { return Vec_IntSize(p->vCos);                        }
+static inline int         Emb_ManPiNum( Emb_Man_t * p )                               { return Vec_IntSize(p->vCis) - p->nRegs;             }
+static inline int         Emb_ManPoNum( Emb_Man_t * p )                               { return Vec_IntSize(p->vCos) - p->nRegs;             }
+static inline int         Emb_ManObjNum( Emb_Man_t * p )                              { return p->nObjs;                                    } 
+static inline int         Emb_ManNodeNum( Emb_Man_t * p )                             { return p->nObjs - Vec_IntSize(p->vCis) - Vec_IntSize(p->vCos); } 
+
+static inline Emb_Obj_t * Emb_ManObj( Emb_Man_t * p, unsigned hHandle )               { return (Emb_Obj_t *)(p->pObjData + hHandle);        } 
+static inline Emb_Obj_t * Emb_ManCi( Emb_Man_t * p, int i )                           { return Emb_ManObj( p, Vec_IntEntry(p->vCis,i) );    }
+static inline Emb_Obj_t * Emb_ManCo( Emb_Man_t * p, int i )                           { return Emb_ManObj( p, Vec_IntEntry(p->vCos,i) );    }
+
+static inline int         Emb_ObjIsTerm( Emb_Obj_t * pObj )                           { return pObj->fCi || pObj->fCo;                      } 
+static inline int         Emb_ObjIsCi( Emb_Obj_t * pObj )                             { return pObj->fCi;                                   } 
+static inline int         Emb_ObjIsCo( Emb_Obj_t * pObj )                             { return pObj->fCo;                                   } 
+//static inline int         Emb_ObjIsPi( Emb_Obj_t * pObj )                             { return pObj->fCi && pObj->nFanins == 0;             } 
+//static inline int         Emb_ObjIsPo( Emb_Obj_t * pObj )                             { return pObj->fCo && pObj->nFanouts == 0;            } 
+static inline int         Emb_ObjIsNode( Emb_Obj_t * pObj )                           { return!Emb_ObjIsTerm(pObj) && pObj->nFanins > 0;    } 
+//static inline int         Emb_ObjIsConst0( Emb_Obj_t * pObj )                         { return!Emb_ObjIsTerm(pObj) && pObj->nFanins == 0;   } 
+
+static inline int         Emb_ObjSize( Emb_Obj_t * pObj )                             { return sizeof(Emb_Obj_t) / 4 + pObj->nFanins + pObj->nFanouts;  } 
+static inline int         Emb_ObjFaninNum( Emb_Obj_t * pObj )                         { return pObj->nFanins;                               } 
+static inline int         Emb_ObjFanoutNum( Emb_Obj_t * pObj )                        { return pObj->nFanouts;                              } 
+static inline Emb_Obj_t * Emb_ObjFanin( Emb_Obj_t * pObj, int i )                     { return (Emb_Obj_t *)(((int *)pObj) - pObj->Fanios[i]);               } 
+static inline Emb_Obj_t * Emb_ObjFanout( Emb_Obj_t * pObj, int i )                    { return (Emb_Obj_t *)(((int *)pObj) + pObj->Fanios[pObj->nFanins+i]); } 
+
+static inline void        Emb_ManResetTravId( Emb_Man_t * p )                         { extern void Emb_ManCleanTravId( Emb_Man_t * p ); Emb_ManCleanTravId( p ); p->nTravIds = 1;  }
+static inline void        Emb_ManIncrementTravId( Emb_Man_t * p )                     { p->nTravIds++;                                      }
+static inline void        Emb_ObjSetTravId( Emb_Obj_t * pObj, int TravId )            { pObj->TravId = TravId;                              }
+static inline void        Emb_ObjSetTravIdCurrent( Emb_Man_t * p, Emb_Obj_t * pObj )  { pObj->TravId = p->nTravIds;                         }
+static inline void        Emb_ObjSetTravIdPrevious( Emb_Man_t * p, Emb_Obj_t * pObj ) { pObj->TravId = p->nTravIds - 1;                     }
+static inline int         Emb_ObjIsTravIdCurrent( Emb_Man_t * p, Emb_Obj_t * pObj )   { return ((int)pObj->TravId == p->nTravIds);          }
+static inline int         Emb_ObjIsTravIdPrevious( Emb_Man_t * p, Emb_Obj_t * pObj )  { return ((int)pObj->TravId == p->nTravIds - 1);      }
+
+static inline Emb_Dat_t * Emb_ManVec( Emb_Man_t * p, int v )                          { return p->pVecs + v * p->nObjs;                     }
+static inline float *     Emb_ManSol( Emb_Man_t * p, int v )                          { return p->pSols + v * p->nObjs;                     }
+
+#define Emb_ManForEachObj( p, pObj, i )               \
+    for ( i = 0; (i < p->nObjData) && (pObj = Emb_ManObj(p,i)); i += Emb_ObjSize(pObj) )
+#define Emb_ManForEachNode( p, pObj, i )              \
+    for ( i = 0; (i < p->nObjData) && (pObj = Emb_ManObj(p,i)); i += Emb_ObjSize(pObj) ) if ( Emb_ObjIsTerm(pObj) ) {} else
+#define Emb_ManForEachObjVec( vVec, p, pObj, i )                        \
+    for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Emb_ManObj(p, Vec_IntEntry(vVec,i))); i++ )
+#define Emb_ObjForEachFanin( pObj, pNext, i )         \
+    for ( i = 0; (i < (int)pObj->nFanins) && (pNext = Emb_ObjFanin(pObj,i)); i++ )
+#define Emb_ObjForEachFanout( pObj, pNext, i )        \
+    for ( i = 0; (i < (int)pObj->nFanouts) && (pNext = Emb_ObjFanout(pObj,i)); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates fanin/fanout pair.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ObjAddFanin( Emb_Obj_t * pObj, Emb_Obj_t * pFanin )
+{ 
+    assert( pObj->iFanin < pObj->nFanins );
+    assert( pFanin->iFanout < pFanin->nFanouts );
+    pFanin->Fanios[pFanin->nFanins + pFanin->iFanout++] = 
+    pObj->Fanios[pObj->iFanin++] = pObj->hHandle - pFanin->hHandle;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates logic network isomorphic to the given AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Emb_Man_t * Emb_ManStartSimple( Gia_Man_t * pGia )
+{
+    Emb_Man_t * p;
+    Emb_Obj_t * pObjLog, * pFanLog;
+    Gia_Obj_t * pObj, * pObjRi, * pObjRo;
+    int i, nNodes, hHandle = 0;
+    // prepare the AIG
+    Gia_ManCreateRefs( pGia );
+    // create logic network
+    p = ABC_CALLOC( Emb_Man_t, 1 );
+    p->pGia  = pGia;
+    p->nRegs = Gia_ManRegNum(pGia);
+    p->vCis  = Vec_IntAlloc( Gia_ManCiNum(pGia) );
+    p->vCos  = Vec_IntAlloc( Gia_ManCoNum(pGia) );
+    p->nObjData = (sizeof(Emb_Obj_t) / 4) * Gia_ManObjNum(pGia) + 2 * (2 * Gia_ManAndNum(pGia) + Gia_ManCoNum(pGia) + Gia_ManRegNum(pGia) + Gia_ManCoNum(pGia));
+    p->pObjData = ABC_CALLOC( int, p->nObjData );
+    // create constant node
+    Gia_ManConst0(pGia)->Value = hHandle;
+    pObjLog = Emb_ManObj( p, hHandle );
+    pObjLog->hHandle  = hHandle;
+    pObjLog->nFanins  = Gia_ManCoNum(pGia);  //0;
+    pObjLog->nFanouts = Gia_ObjRefNum( pGia, Gia_ManConst0(pGia) );
+    // count objects
+    hHandle += Emb_ObjSize( pObjLog );
+    nNodes = 1;
+    p->nObjs++;
+    // create the PIs
+    Gia_ManForEachCi( pGia, pObj, i )
+    {
+        // create PI object
+        pObj->Value = hHandle;
+        Vec_IntPush( p->vCis, hHandle );
+        pObjLog = Emb_ManObj( p, hHandle );
+        pObjLog->hHandle  = hHandle;
+        pObjLog->nFanins  = Gia_ObjIsRo( pGia, pObj );
+        pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj );
+        pObjLog->fCi = 1;
+        // count objects
+        hHandle += Emb_ObjSize( pObjLog );
+        p->nObjs++;
+    }
+    // create internal nodes
+    Gia_ManForEachAnd( pGia, pObj, i )
+    {
+        assert( Gia_ObjRefNum( pGia, pObj ) > 0 );
+        // create node object
+        pObj->Value = hHandle;
+        pObjLog = Emb_ManObj( p, hHandle );
+        pObjLog->hHandle  = hHandle;
+        pObjLog->nFanins  = 2;
+        pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj );
+        // add fanins
+        pFanLog = Emb_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) ); 
+        Emb_ObjAddFanin( pObjLog, pFanLog );
+        pFanLog = Emb_ManObj( p, Gia_ObjValue(Gia_ObjFanin1(pObj)) ); 
+        Emb_ObjAddFanin( pObjLog, pFanLog );
+        // count objects
+        hHandle += Emb_ObjSize( pObjLog );
+        nNodes++;
+        p->nObjs++;
+    }
+    // create the POs
+    Gia_ManForEachCo( pGia, pObj, i )
+    {
+        // create PO object
+        pObj->Value = hHandle;
+        Vec_IntPush( p->vCos, hHandle );
+        pObjLog = Emb_ManObj( p, hHandle );
+        pObjLog->hHandle  = hHandle;
+        pObjLog->nFanins  = 1;
+        pObjLog->nFanouts = 1 + Gia_ObjIsRi( pGia, pObj );
+        pObjLog->fCo = 1;
+        // add fanins
+        pFanLog = Emb_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) );
+        Emb_ObjAddFanin( pObjLog, pFanLog );
+        // count objects
+        hHandle += Emb_ObjSize( pObjLog );
+        p->nObjs++;
+    }
+    // connect registers
+    Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, i )
+        Emb_ObjAddFanin( Emb_ManObj(p,Gia_ObjValue(pObjRo)), Emb_ManObj(p,Gia_ObjValue(pObjRi)) );
+    assert( nNodes  == Emb_ManNodeNum(p) );
+    assert( hHandle == p->nObjData );
+    assert( p->nObjs == Gia_ManObjNum(pGia) );
+    if ( hHandle != p->nObjData )
+        printf( "Emb_ManStartSimple(): Fatal error in internal representation.\n" );
+    // make sure the fanin/fanout counters are correct
+    Gia_ManForEachObj( pGia, pObj, i )
+    {
+        if ( !~Gia_ObjValue(pObj) )
+            continue;
+        pObjLog = Emb_ManObj( p, Gia_ObjValue(pObj) );
+        assert( pObjLog->nFanins  == pObjLog->iFanin || Gia_ObjIsConst0(pObj) );
+        assert( pObjLog->nFanouts == pObjLog->iFanout || Gia_ObjIsCo(pObj) );
+        pObjLog->iFanin = pObjLog->iFanout = 0;
+    }
+    ABC_FREE( pGia->pRefs );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect the fanin IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManCollectSuper_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper, Vec_Int_t * vVisit )  
+{
+    if ( pObj->fMark1 )
+        return;
+    pObj->fMark1 = 1;
+    Vec_IntPush( vVisit, Gia_ObjId(p, pObj) );
+    if ( pObj->fMark0 )
+    {
+        Vec_IntPush( vSuper, Gia_ObjId(p, pObj) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Emb_ManCollectSuper_rec( p, Gia_ObjFanin0(pObj), vSuper, vVisit );
+    Emb_ManCollectSuper_rec( p, Gia_ObjFanin1(pObj), vSuper, vVisit );
+    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect the fanin IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+void Emb_ManCollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper, Vec_Int_t * vVisit )  
+{
+    int Entry, i;
+    Vec_IntClear( vSuper );
+    Vec_IntClear( vVisit );
+    assert( pObj->fMark0 == 1 );
+    pObj->fMark0 = 0;
+    Emb_ManCollectSuper_rec( p, pObj, vSuper, vVisit );
+    pObj->fMark0 = 1;
+    Vec_IntForEachEntry( vVisit, Entry, i )
+        Gia_ManObj(p, Entry)->fMark1 = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns references while removing the MUX/XOR ones.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManCreateRefsSpecial( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj, * pFan0, * pFan1;
+    Gia_Obj_t * pObjC, * pObjD0, * pObjD1;
+    int i;
+    assert( p->pRefs == NULL );
+    Gia_ManCleanMark0( p );
+    Gia_ManCreateRefs( p );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        assert( pObj->fMark0 == 0 );
+        pFan0 = Gia_ObjFanin0(pObj);
+        pFan1 = Gia_ObjFanin1(pObj);
+        // skip nodes whose fanins are PIs or are already marked
+        if ( Gia_ObjIsCi(pFan0) || pFan0->fMark0 || 
+             Gia_ObjIsCi(pFan1) || pFan1->fMark0 )
+             continue;
+        // skip nodes that are not MUX type
+        if ( !Gia_ObjIsMuxType(pObj) )
+            continue;
+        // the node is MUX type, mark it and its fanins
+        pObj->fMark0  = 1;
+        pFan0->fMark0 = 1;
+        pFan1->fMark0 = 1;
+        // deref the control 
+        pObjC = Gia_ObjRecognizeMux( pObj, &pObjD1, &pObjD0 );
+        Gia_ObjRefDec( p, Gia_Regular(pObjC) );
+        if ( Gia_Regular(pObjD0) == Gia_Regular(pObjD1) )
+            Gia_ObjRefDec( p, Gia_Regular(pObjD0) );
+    }
+    Gia_ManForEachAnd( p, pObj, i )
+        assert( Gia_ObjRefNum(p, pObj) > 0 );
+    Gia_ManCleanMark0( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns references while removing the MUX/XOR ones.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManTransformRefs( Gia_Man_t * p, int * pnObjs, int * pnFanios )  
+{
+    Vec_Int_t * vSuper, * vVisit;
+    Gia_Obj_t * pObj, * pFanin;
+    int i, k, Counter;
+    assert( p->pRefs != NULL );
+
+    // mark nodes to be used in the logic network
+    Gia_ManCleanMark0( p );
+    Gia_ManConst0(p)->fMark0 = 1;
+    // mark the inputs
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->fMark0 = 1;
+    // mark those nodes that have ref count more than 1
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->fMark0 = (Gia_ObjRefNum(p, pObj) > 1);
+    // mark the output drivers
+    Gia_ManForEachCoDriver( p, pObj, i )
+        pObj->fMark0 = 1;
+
+    // count the number of nodes
+    Counter = 0;
+    Gia_ManForEachObj( p, pObj, i )
+        Counter += pObj->fMark0;
+    *pnObjs = Counter + Gia_ManCoNum(p);
+
+    // reset the references
+    ABC_FREE( p->pRefs );
+    p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    // reference from internal nodes
+    Counter = 0;
+    vSuper = Vec_IntAlloc( 100 );
+    vVisit = Vec_IntAlloc( 100 );
+    Gia_ManCleanMark1( p );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        if ( pObj->fMark0 == 0 )
+            continue;
+        Emb_ManCollectSuper( p, pObj, vSuper, vVisit );
+        Gia_ManForEachObjVec( vSuper, p, pFanin, k )
+        {
+            assert( pFanin->fMark0 );
+            Gia_ObjRefInc( p, pFanin );
+        }
+        Counter += Vec_IntSize( vSuper );
+    }
+    Gia_ManCheckMark1( p );
+    Vec_IntFree( vSuper );
+    Vec_IntFree( vVisit );
+    // reference from outputs
+    Gia_ManForEachCoDriver( p, pObj, i )
+    {
+        assert( pObj->fMark0 );
+        Gia_ObjRefInc( p, pObj );
+    }
+    *pnFanios = Counter + Gia_ManCoNum(p);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManCleanTravId( Emb_Man_t * p )  
+{
+    Emb_Obj_t * pObj;
+    int i;
+    Emb_ManForEachObj( p, pObj, i )
+        pObj->TravId = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManSetValue( Emb_Man_t * p )  
+{
+    Emb_Obj_t * pObj;
+    int i, Counter = 0;
+    Emb_ManForEachObj( p, pObj, i )
+    {
+        pObj->Value = Counter++;
+//        if ( pObj->fCi && pObj->nFanins == 0 ) 
+//            printf( "CI:  Handle = %8d.  Value = %6d. Fanins = %d.\n", pObj->hHandle, pObj->Value, pObj->nFanins );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates logic network isomorphic to the given AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Emb_Man_t * Emb_ManStart( Gia_Man_t * pGia )
+{
+    Emb_Man_t * p;
+    Emb_Obj_t * pObjLog, * pFanLog;
+    Gia_Obj_t * pObj, * pObjRi, * pObjRo, * pFanin;
+    Vec_Int_t * vSuper, * vVisit;
+    int nObjs, nFanios, nNodes = 0;
+    int i, k, hHandle = 0;
+    // prepare the AIG
+//    Gia_ManCreateRefs( pGia );
+    Emb_ManCreateRefsSpecial( pGia );
+    Emb_ManTransformRefs( pGia, &nObjs, &nFanios );
+    Gia_ManFillValue( pGia );
+    // create logic network
+    p = ABC_CALLOC( Emb_Man_t, 1 );
+    p->pGia  = pGia;
+    p->nRegs = Gia_ManRegNum(pGia);
+    p->vCis  = Vec_IntAlloc( Gia_ManCiNum(pGia) );
+    p->vCos  = Vec_IntAlloc( Gia_ManCoNum(pGia) );
+    p->nObjData = (sizeof(Emb_Obj_t) / 4) * nObjs + 2 * (nFanios + Gia_ManRegNum(pGia) + Gia_ManCoNum(pGia));
+    p->pObjData = ABC_CALLOC( int, p->nObjData );
+    // create constant node
+    Gia_ManConst0(pGia)->Value = hHandle;
+    pObjLog = Emb_ManObj( p, hHandle );
+    pObjLog->hHandle  = hHandle;
+    pObjLog->nFanins  = Gia_ManCoNum(pGia);  //0;
+    pObjLog->nFanouts = Gia_ObjRefNum( pGia, Gia_ManConst0(pGia) );
+    // count objects
+    hHandle += Emb_ObjSize( pObjLog );
+    nNodes++;
+    p->nObjs++;
+    // create the PIs
+    Gia_ManForEachCi( pGia, pObj, i )
+    {
+        // create PI object
+        pObj->Value = hHandle;
+        Vec_IntPush( p->vCis, hHandle );
+        pObjLog = Emb_ManObj( p, hHandle );
+        pObjLog->hHandle  = hHandle;
+        pObjLog->nFanins  = Gia_ObjIsRo( pGia, pObj );
+        pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj );
+        pObjLog->fCi = 1;
+        // count objects
+        hHandle += Emb_ObjSize( pObjLog );
+        p->nObjs++;
+    }
+    // create internal nodes
+    vSuper = Vec_IntAlloc( 100 );
+    vVisit = Vec_IntAlloc( 100 );
+    Gia_ManForEachAnd( pGia, pObj, i )
+    {
+        if ( pObj->fMark0 == 0 )
+        {
+            assert( Gia_ObjRefNum( pGia, pObj ) == 0 );
+            continue;
+        }
+        assert( Gia_ObjRefNum( pGia, pObj ) > 0 );
+        Emb_ManCollectSuper( pGia, pObj, vSuper, vVisit );
+        // create node object
+        pObj->Value = hHandle;
+        pObjLog = Emb_ManObj( p, hHandle );
+        pObjLog->hHandle  = hHandle;
+        pObjLog->nFanins  = Vec_IntSize( vSuper );
+        pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj );
+        // add fanins
+        Gia_ManForEachObjVec( vSuper, pGia, pFanin, k )
+        {
+            pFanLog = Emb_ManObj( p, Gia_ObjValue(pFanin) ); 
+            Emb_ObjAddFanin( pObjLog, pFanLog );
+        }
+        // count objects
+        hHandle += Emb_ObjSize( pObjLog );
+        nNodes++;
+        p->nObjs++;
+    }
+    Vec_IntFree( vSuper );
+    Vec_IntFree( vVisit );
+    // create the POs
+    Gia_ManForEachCo( pGia, pObj, i )
+    {
+        // create PO object
+        pObj->Value = hHandle;
+        Vec_IntPush( p->vCos, hHandle );
+        pObjLog = Emb_ManObj( p, hHandle );
+        pObjLog->hHandle  = hHandle;
+        pObjLog->nFanins  = 1;
+        pObjLog->nFanouts = 1 + Gia_ObjIsRi( pGia, pObj );
+        pObjLog->fCo = 1;
+        // add fanins
+        pFanLog = Emb_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) );
+        Emb_ObjAddFanin( pObjLog, pFanLog );
+        // count objects
+        hHandle += Emb_ObjSize( pObjLog );
+        p->nObjs++;
+    }
+    // connect registers
+    Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, i )
+        Emb_ObjAddFanin( Emb_ManObj(p,Gia_ObjValue(pObjRo)), Emb_ManObj(p,Gia_ObjValue(pObjRi)) );
+    Gia_ManCleanMark0( pGia );
+    assert( nNodes  == Emb_ManNodeNum(p) );
+    assert( nObjs   == p->nObjs );
+    assert( hHandle == p->nObjData );
+    if ( hHandle != p->nObjData )
+        printf( "Emb_ManStart(): Fatal error in internal representation.\n" );
+    // make sure the fanin/fanout counters are correct
+    Gia_ManForEachObj( pGia, pObj, i )
+    {
+        if ( !~Gia_ObjValue(pObj) )
+            continue;
+        pObjLog = Emb_ManObj( p, Gia_ObjValue(pObj) );
+        assert( pObjLog->nFanins  == pObjLog->iFanin || Gia_ObjIsConst0(pObj) );
+        assert( pObjLog->nFanouts == pObjLog->iFanout || Gia_ObjIsCo(pObj) );
+        pObjLog->iFanin = pObjLog->iFanout = 0;
+    }
+    ABC_FREE( pGia->pRefs );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates logic network isomorphic to the given AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManPrintStats( Emb_Man_t * p )
+{
+//    if ( p->pName )
+//        printf( "%8s : ", p->pName );
+    printf( "i/o =%7d/%7d  ", Emb_ManPiNum(p), Emb_ManPoNum(p) );
+    if ( Emb_ManRegNum(p) )
+        printf( "ff =%7d  ", Emb_ManRegNum(p) );
+    printf( "node =%8d  ", Emb_ManNodeNum(p) );
+    printf( "obj =%8d  ", Emb_ManObjNum(p) );
+//    printf( "lev =%5d  ", Emb_ManLevelNum(p) );
+//    printf( "cut =%5d  ", Emb_ManCrossCut(p) );
+    printf( "mem =%5.2f MB", 4.0*p->nObjData/(1<<20) );
+//    printf( "obj =%5d  ", Emb_ManObjNum(p) );
+    printf( "\n" );
+
+//    Emb_ManSatExperiment( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates logic network isomorphic to the given AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManStop( Emb_Man_t * p )
+{
+    Vec_IntFree( p->vCis );
+    Vec_IntFree( p->vCos );
+    ABC_FREE( p->pPlacement );
+    ABC_FREE( p->pVecs );
+    ABC_FREE( p->pSols );
+    ABC_FREE( p->pMatr );
+    ABC_FREE( p->pEigen );
+    ABC_FREE( p->pObjData );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the distribution of fanins/fanouts in the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManPrintFanio( Emb_Man_t * p )
+{
+    char Buffer[100];
+    Emb_Obj_t * pNode;
+    Vec_Int_t * vFanins, * vFanouts;
+    int nFanins, nFanouts, nFaninsMax, nFanoutsMax, nFaninsAll, nFanoutsAll;
+    int i, k, nSizeMax;
+
+    // determine the largest fanin and fanout
+    nFaninsMax = nFanoutsMax = 0;
+    nFaninsAll = nFanoutsAll = 0;
+    Emb_ManForEachNode( p, pNode, i )
+    {
+        if ( i == 0 ) continue; // skip const 0 obj
+        nFanins  = Emb_ObjFaninNum(pNode);
+        nFanouts = Emb_ObjFanoutNum(pNode);
+        nFaninsAll  += nFanins;
+        nFanoutsAll += nFanouts;
+        nFaninsMax   = Abc_MaxInt( nFaninsMax, nFanins );
+        nFanoutsMax  = Abc_MaxInt( nFanoutsMax, nFanouts );
+    }
+
+    // allocate storage for fanin/fanout numbers
+    nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nFaninsMax) + 1), 10 * (Abc_Base10Log(nFanoutsMax) + 1) );
+    vFanins  = Vec_IntStart( nSizeMax );
+    vFanouts = Vec_IntStart( nSizeMax );
+
+    // count the number of fanins and fanouts
+    Emb_ManForEachNode( p, pNode, i )
+    {
+        if ( i == 0 ) continue; // skip const 0 obj
+        nFanins  = Emb_ObjFaninNum(pNode);
+        nFanouts = Emb_ObjFanoutNum(pNode);
+
+        if ( nFanins < 10 )
+            Vec_IntAddToEntry( vFanins, nFanins, 1 );
+        else if ( nFanins < 100 )
+            Vec_IntAddToEntry( vFanins, 10 + nFanins/10, 1 );
+        else if ( nFanins < 1000 )
+            Vec_IntAddToEntry( vFanins, 20 + nFanins/100, 1 );
+        else if ( nFanins < 10000 )
+            Vec_IntAddToEntry( vFanins, 30 + nFanins/1000, 1 );
+        else if ( nFanins < 100000 )
+            Vec_IntAddToEntry( vFanins, 40 + nFanins/10000, 1 );
+        else if ( nFanins < 1000000 )
+            Vec_IntAddToEntry( vFanins, 50 + nFanins/100000, 1 );
+        else if ( nFanins < 10000000 )
+            Vec_IntAddToEntry( vFanins, 60 + nFanins/1000000, 1 );
+
+        if ( nFanouts < 10 )
+            Vec_IntAddToEntry( vFanouts, nFanouts, 1 );
+        else if ( nFanouts < 100 )
+            Vec_IntAddToEntry( vFanouts, 10 + nFanouts/10, 1 );
+        else if ( nFanouts < 1000 )
+            Vec_IntAddToEntry( vFanouts, 20 + nFanouts/100, 1 );
+        else if ( nFanouts < 10000 )
+            Vec_IntAddToEntry( vFanouts, 30 + nFanouts/1000, 1 );
+        else if ( nFanouts < 100000 )
+            Vec_IntAddToEntry( vFanouts, 40 + nFanouts/10000, 1 );
+        else if ( nFanouts < 1000000 )
+            Vec_IntAddToEntry( vFanouts, 50 + nFanouts/100000, 1 );
+        else if ( nFanouts < 10000000 )
+            Vec_IntAddToEntry( vFanouts, 60 + nFanouts/1000000, 1 );
+    }
+
+    printf( "The distribution of fanins and fanouts in the network:\n" );
+    printf( "         Number   Nodes with fanin  Nodes with fanout\n" );
+    for ( k = 0; k < nSizeMax; k++ )
+    {
+        if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 )
+            continue;
+        if ( k < 10 )
+            printf( "%15d : ", k );
+        else
+        {
+            sprintf( Buffer, "%d - %d", (int)pow((double)10, k/10) * (k%10), (int)pow((double)10, k/10) * (k%10+1) - 1 ); 
+            printf( "%15s : ", Buffer );
+        }
+        if ( vFanins->pArray[k] == 0 )
+            printf( "              " );
+        else
+            printf( "%12d  ", vFanins->pArray[k] );
+        printf( "    " );
+        if ( vFanouts->pArray[k] == 0 )
+            printf( "              " );
+        else
+            printf( "%12d  ", vFanouts->pArray[k] );
+        printf( "\n" );
+    }
+    Vec_IntFree( vFanins );
+    Vec_IntFree( vFanouts );
+
+    printf( "Fanins: Max = %d. Ave = %.2f.  Fanouts: Max = %d. Ave =  %.2f.\n", 
+        nFaninsMax,  1.0*nFaninsAll/Emb_ManNodeNum(p), 
+        nFanoutsMax, 1.0*nFanoutsAll/Emb_ManNodeNum(p)  );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the distance from the given object]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Emb_ManComputeDistance_old( Emb_Man_t * p, Emb_Obj_t * pPivot )
+{
+    Vec_Int_t * vThis, * vNext, * vTemp;
+    Emb_Obj_t * pThis, * pNext;
+    int i, k, d, nVisited = 0;
+//    assert( Emb_ObjIsTerm(pPivot) );
+    vThis = Vec_IntAlloc( 1000 );
+    vNext = Vec_IntAlloc( 1000 );
+    Emb_ManIncrementTravId( p );
+    Emb_ObjSetTravIdCurrent( p, pPivot );
+    Vec_IntPush( vThis, pPivot->hHandle );
+    for ( d = 0; Vec_IntSize(vThis) > 0; d++ )
+    {
+        nVisited += Vec_IntSize(vThis);
+        Vec_IntClear( vNext );
+        Emb_ManForEachObjVec( vThis, p, pThis, i )
+        {
+            Emb_ObjForEachFanin( pThis, pNext, k )
+            {
+                if ( Emb_ObjIsTravIdCurrent(p, pNext) )
+                    continue;
+                Emb_ObjSetTravIdCurrent(p, pNext);
+                Vec_IntPush( vNext, pNext->hHandle );
+                nVisited += !Emb_ObjIsTerm(pNext);
+            }
+            Emb_ObjForEachFanout( pThis, pNext, k )
+            {
+                if ( Emb_ObjIsTravIdCurrent(p, pNext) )
+                    continue;
+                Emb_ObjSetTravIdCurrent(p, pNext);
+                Vec_IntPush( vNext, pNext->hHandle );
+                nVisited += !Emb_ObjIsTerm(pNext);
+            }
+        }
+        vTemp = vThis; vThis = vNext; vNext = vTemp;
+    }
+    Vec_IntFree( vThis );
+    Vec_IntFree( vNext );
+    // check if there are several strongly connected components
+//    if ( nVisited < Emb_ManNodeNum(p) )
+//        printf( "Visited less nodes (%d) than present (%d).\n", nVisited, Emb_ManNodeNum(p) );
+    return d;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Traverses from the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+void Gia_ManTestDistanceInternal( Emb_Man_t * p )
+{
+    int nAttempts = 20;
+    int i, iNode, Dist;
+    abctime clk;
+    Emb_Obj_t * pPivot, * pNext;
+    Gia_ManRandom( 1 );
+    Emb_ManResetTravId( p );
+    // compute distances from several randomly selected PIs
+    clk = Abc_Clock();
+    printf( "From inputs: " );
+    for ( i = 0; i < nAttempts; i++ )
+    {
+        iNode = Gia_ManRandom( 0 ) % Emb_ManCiNum(p);
+        pPivot = Emb_ManCi( p, iNode );
+        if ( Emb_ObjFanoutNum(pPivot) == 0 )
+            { i--; continue; }
+        pNext = Emb_ObjFanout( pPivot, 0 );
+        if ( !Emb_ObjIsNode(pNext) )
+            { i--; continue; }
+        Dist = Emb_ManComputeDistance_old( p, pPivot );
+        printf( "%d ", Dist );
+    }
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    // compute distances from several randomly selected POs
+    clk = Abc_Clock();
+    printf( "From outputs: " );
+    for ( i = 0; i < nAttempts; i++ )
+    {
+        iNode = Gia_ManRandom( 0 ) % Emb_ManCoNum(p);
+        pPivot = Emb_ManCo( p, iNode );
+        pNext = Emb_ObjFanin( pPivot, 0 );
+        if ( !Emb_ObjIsNode(pNext) )
+            { i--; continue; }
+        Dist = Emb_ManComputeDistance_old( p, pPivot );
+        printf( "%d ", Dist );
+    }
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    // compute distances from several randomly selected nodes
+    clk = Abc_Clock();
+    printf( "From nodes: " );
+    for ( i = 0; i < nAttempts; i++ )
+    {
+        iNode = Gia_ManRandom( 0 ) % Gia_ManObjNum(p->pGia);
+        if ( !~Gia_ManObj(p->pGia, iNode)->Value )
+            { i--; continue; }
+        pPivot = Emb_ManObj( p, Gia_ManObj(p->pGia, iNode)->Value );
+        if ( !Emb_ObjIsNode(pPivot) )
+            { i--; continue; }
+        Dist = Emb_ManComputeDistance_old( p, pPivot );
+        printf( "%d ", Dist );
+    }
+    ABC_PRT( "Time", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns sorted array of node handles with largest fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManTestDistance( Gia_Man_t * pGia )
+{
+    Emb_Man_t * p;
+    abctime clk = Abc_Clock();
+    p = Emb_ManStart( pGia );
+//    Emb_ManPrintFanio( p );
+    Emb_ManPrintStats( p );
+ABC_PRT( "Time", Abc_Clock() - clk );
+    Gia_ManTestDistanceInternal( p );
+    Emb_ManStop( p );
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Perform BFS from the set of nodes.]
+
+  Description [Returns one of the most distant objects.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Emb_Obj_t * Emb_ManPerformBfs( Emb_Man_t * p, Vec_Int_t * vThis, Vec_Int_t * vNext, Emb_Dat_t * pDist )
+{
+    Vec_Int_t * vTemp;
+    Emb_Obj_t * pThis, * pNext, * pResult;
+    int i, k;
+    assert( Vec_IntSize(vThis) > 0 );
+    for ( p->nDistMax = 0; Vec_IntSize(vThis) > 0; p->nDistMax++ )
+    {
+        p->nReached += Vec_IntSize(vThis);
+        Vec_IntClear( vNext );
+        Emb_ManForEachObjVec( vThis, p, pThis, i )
+        {
+            if ( pDist ) pDist[pThis->Value] = p->nDistMax;
+            Emb_ObjForEachFanin( pThis, pNext, k )
+            {
+                if ( Emb_ObjIsTravIdCurrent(p, pNext) )
+                    continue;
+                Emb_ObjSetTravIdCurrent(p, pNext);
+                Vec_IntPush( vNext, pNext->hHandle );
+            }
+            Emb_ObjForEachFanout( pThis, pNext, k )
+            {
+                if ( Emb_ObjIsTravIdCurrent(p, pNext) )
+                    continue;
+                Emb_ObjSetTravIdCurrent(p, pNext);
+                Vec_IntPush( vNext, pNext->hHandle );
+            }
+        }
+        vTemp = vThis; vThis = vNext; vNext = vTemp;
+    }
+    assert( Vec_IntSize(vNext) > 0 );
+    pResult = Emb_ManObj( p, Vec_IntEntry(vNext, 0) );
+    assert( pDist == NULL || pDist[pResult->Value] == p->nDistMax - 1 );
+    return pResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the distances from the given set of objects.]
+
+  Description [Returns one of the most distant objects.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Emb_ManConnectedComponents( Emb_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vThis, * vNext, * vResult;
+    Emb_Obj_t * pThis;
+    int i;
+    vResult = Vec_IntAlloc( 1000 );
+    vThis   = Vec_IntAlloc( 1000 );
+    vNext   = Vec_IntAlloc( 1000 );
+    p->nReached = 0;
+    Emb_ManIncrementTravId( p );
+    Gia_ManForEachCo( p->pGia, pObj, i )
+    {
+        pThis = Emb_ManObj( p, Gia_ObjValue(pObj) );
+        if ( Emb_ObjIsTravIdCurrent(p, pThis) )
+            continue;
+        Emb_ObjSetTravIdCurrent( p, pThis );
+        Vec_IntPush( vResult, pThis->hHandle );
+        // perform BFS from this node
+        Vec_IntClear( vThis );
+        Vec_IntPush( vThis, pThis->hHandle );
+        Emb_ManPerformBfs( p, vThis, vNext, NULL ); 
+    }
+    Vec_IntFree( vThis );
+    Vec_IntFree( vNext );
+    return vResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the distances from the given set of objects.]
+
+  Description [Returns one of the most distant objects.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Emb_Obj_t * Emb_ManFindDistances( Emb_Man_t * p, Vec_Int_t * vStart, Emb_Dat_t * pDist )
+{
+    Vec_Int_t * vThis, * vNext;
+    Emb_Obj_t * pThis, * pResult;
+    int i;
+    p->nReached = p->nDistMax = 0;
+    vThis = Vec_IntAlloc( 1000 );
+    vNext = Vec_IntAlloc( 1000 );
+    Emb_ManIncrementTravId( p );
+    Emb_ManForEachObjVec( vStart, p, pThis, i )
+    {
+        Emb_ObjSetTravIdCurrent( p, pThis );
+        Vec_IntPush( vThis, pThis->hHandle );
+    }
+    pResult = Emb_ManPerformBfs( p, vThis, vNext, pDist );
+    Vec_IntFree( vThis );
+    Vec_IntFree( vNext );
+    return pResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Traverses from the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+Emb_Obj_t * Emb_ManRandomVertex( Emb_Man_t * p )
+{
+    Emb_Obj_t * pPivot;
+    do {
+        int iNode = (911 * Gia_ManRandom(0)) % Gia_ManObjNum(p->pGia);
+        if ( ~Gia_ManObj(p->pGia, iNode)->Value )
+            pPivot = Emb_ManObj( p, Gia_ManObj(p->pGia, iNode)->Value );
+        else
+            pPivot = NULL;
+    }
+    while ( pPivot == NULL || !Emb_ObjIsNode(pPivot) );
+    return pPivot;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the distances from the given set of objects.]
+
+  Description [Returns one of the most distant objects.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_DumpGraphIntoFile( Emb_Man_t * p )
+{
+    FILE * pFile;
+    Emb_Obj_t * pThis, * pNext;
+    int i, k;
+    pFile = fopen( "1.g", "w" );
+    Emb_ManForEachObj( p, pThis, i )
+    {
+        if ( !Emb_ObjIsTravIdCurrent(p, pThis) )
+            continue;
+        Emb_ObjForEachFanout( pThis, pNext, k )
+        {
+            assert( Emb_ObjIsTravIdCurrent(p, pNext) );
+            fprintf( pFile, "%d %d\n", pThis->Value, pNext->Value );
+        }
+    }
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes dimentions of the graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManComputeDimensions( Emb_Man_t * p, int nDims )
+{
+    Emb_Obj_t * pRandom, * pPivot;
+    Vec_Int_t * vStart, * vComps;
+    int d, nReached;
+    int i;//, Counter;
+    // connect unconnected components
+    vComps = Emb_ManConnectedComponents( p );
+//    printf( "Components = %d. Considered %d objects (out of %d).\n", Vec_IntSize(vComps), p->nReached, Emb_ManObjNum(p) );
+    if ( Vec_IntSize(vComps) > 1 )
+    {
+        Emb_Obj_t * pFanin, * pObj = Emb_ManObj( p, 0 );
+        Emb_ManForEachObjVec( vComps, p, pFanin, i )
+        {
+            assert( Emb_ObjIsCo(pFanin) );
+            pFanin->Fanios[pFanin->nFanins + pFanin->nFanouts-1] = 
+                pObj->Fanios[i] = pObj->hHandle - pFanin->hHandle;
+        }
+    }
+    Vec_IntFree( vComps );
+    // allocate memory for vectors
+    assert( p->pVecs == NULL );
+    p->pVecs = ABC_CALLOC( Emb_Dat_t, p->nObjs * nDims );
+//    for ( i = 0; i < p->nObjs * nDims; i++ )
+//        p->pVecs[i] = ABC_INFINITY;
+    vStart = Vec_IntAlloc( nDims );
+    // get the pivot vertex
+    pRandom = Emb_ManRandomVertex( p );
+    Vec_IntPush( vStart, pRandom->hHandle );
+    // get the most distant vertex from the pivot
+    pPivot = Emb_ManFindDistances( p, vStart, NULL );
+//    Emb_DumpGraphIntoFile( p );
+    nReached = p->nReached;
+    if ( nReached < Emb_ManObjNum(p) )
+    {
+//        printf( "Considering a connected component with %d objects (out of %d).\n", p->nReached, Emb_ManObjNum(p) );
+    }
+    // start dimensions with this vertex
+    Vec_IntClear( vStart );
+    for ( d = 0; d < nDims; d++ )
+    {
+//        printf( "%3d : Adding vertex %7d with distance %3d.\n", d+1, pPivot->Value, p->nDistMax ); 
+        Vec_IntPush( vStart, pPivot->hHandle );
+        if ( d+1 == nReached )
+            break;
+        pPivot = Emb_ManFindDistances( p, vStart, Emb_ManVec(p, d) );
+        assert( nReached == p->nReached );
+    }
+    Vec_IntFree( vStart );
+    // make sure the number of reached objects is correct
+//    Counter = 0;
+//    for ( i = 0; i < p->nObjs; i++ )
+//        if ( p->pVecs[i] < ABC_INFINITY )
+//            Counter++;
+//    assert( Counter == nReached );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocated square matrix of floats.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float ** Emb_ManMatrAlloc( int nDims )
+{
+    int i;
+    float ** pMatr = (float **)ABC_ALLOC( char, sizeof(float *) * nDims + sizeof(float) * nDims * nDims );
+    pMatr[0] = (float *)(pMatr + nDims);
+    for ( i = 1; i < nDims; i++ )
+        pMatr[i] = pMatr[i-1] + nDims;
+    return pMatr;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes covariance matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManComputeCovariance( Emb_Man_t * p, int nDims )
+{
+    Emb_Dat_t * pOne, * pTwo;
+    double Ave;
+    float * pRow;
+    int d, i, k, v;
+    // average vectors
+    for ( d = 0; d < nDims; d++ )
+    {
+        // compute average
+        Ave = 0.0;
+        pOne = Emb_ManVec( p, d );
+        for ( v = 0; v < p->nObjs; v++ )
+            if ( pOne[v] < ABC_INFINITY )
+                Ave += pOne[v];
+        Ave /= p->nReached;
+        // update the vector
+        for ( v = 0; v < p->nObjs; v++ )
+            if ( pOne[v] < ABC_INFINITY )
+                pOne[v] -= Ave;
+            else
+                pOne[v] = 0.0;        
+    }
+    // compute the matrix
+    assert( p->pMatr == NULL );
+    assert( p->pEigen == NULL );
+    p->pMatr = Emb_ManMatrAlloc( nDims );
+    p->pEigen = Emb_ManMatrAlloc( nDims );
+    for ( i = 0; i < nDims; i++ )
+    {
+        pOne = Emb_ManVec( p, i );
+        pRow = p->pMatr[i];
+        for ( k = 0; k < nDims; k++ )
+        {
+            pTwo = Emb_ManVec( p, k );
+            pRow[k] = 0.0;
+            for ( v = 0; v < p->nObjs; v++ )
+                pRow[k] += pOne[v]*pTwo[v];
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns random vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManVecRandom( float * pVec, int nDims )
+{
+    int i;
+    for ( i = 0; i < nDims; i++ )
+        pVec[i] = Gia_ManRandom( 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns normalized vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManVecNormal( float * pVec, int nDims )
+{
+    int i;
+    double Norm = 0.0;
+    for ( i = 0; i < nDims; i++ )
+        Norm += pVec[i] * pVec[i];
+    Norm = pow( Norm, 0.5 );
+    for ( i = 0; i < nDims; i++ )
+        pVec[i] /= Norm;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Multiplies vector by vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Emb_ManVecMultiplyOne( float * pVec0, float * pVec1, int nDims )
+{
+    float Res = 0.0;
+    int i;
+    for ( i = 0; i < nDims; i++ )
+        Res += pVec0[i] * pVec1[i];
+    return Res;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Copies the vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManVecCopyOne( float * pVecDest, float * pVecSour, int nDims )
+{
+    int i;
+    for ( i = 0; i < nDims; i++ )
+        pVecDest[i] = pVecSour[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Multiplies matrix by vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManVecMultiply( float ** pMatr, float * pVec, int nDims, float * pRes )
+{
+    int k;
+    for ( k = 0; k < nDims; k++ )
+        pRes[k] = Emb_ManVecMultiplyOne( pMatr[k], pVec, nDims );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Multiplies vector by matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManVecOrthogonolizeOne( float * pEigen, float * pVecI, int nDims, float * pVecRes )
+{
+    int k;
+    for ( k = 0; k < nDims; k++ )
+        pVecRes[k] = pVecI[k] - pEigen[k] * Emb_ManVecMultiplyOne( pVecI, pEigen, nDims );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the first nSols eigen-vectors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManComputeEigenvectors( Emb_Man_t * p, int nDims, int nSols )
+{
+    float * pVecUiHat, * pVecUi;
+    int i, j, k;
+    assert( nSols < nDims );
+    pVecUiHat = p->pEigen[nSols];
+    for ( i = 0; i < nSols; i++ )
+    {
+        pVecUi = p->pEigen[i];
+        Emb_ManVecRandom( pVecUiHat, nDims );
+        Emb_ManVecNormal( pVecUiHat, nDims );
+        k = 0;
+        do {
+            k++;
+            Emb_ManVecCopyOne( pVecUi, pVecUiHat, nDims );
+            for ( j = 0; j < i; j++ )
+            {
+                Emb_ManVecOrthogonolizeOne( p->pEigen[j], pVecUi, nDims, pVecUiHat );
+                Emb_ManVecCopyOne( pVecUi, pVecUiHat, nDims );
+            }
+            Emb_ManVecMultiply( p->pMatr, pVecUi, nDims, pVecUiHat );
+            Emb_ManVecNormal( pVecUiHat, nDims );
+        } while ( Emb_ManVecMultiplyOne( pVecUiHat, pVecUi, nDims ) < 0.999 && k < 100 );
+        Emb_ManVecCopyOne( pVecUi, pVecUiHat, nDims );
+//        printf( "Converged after %d iterations.\n", k );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives solutions from original vectors and eigenvectors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManComputeSolutions( Emb_Man_t * p, int nDims, int nSols )
+{
+    Emb_Dat_t * pX;
+    float * pY;
+    int i, j, k;
+    assert( p->pSols == NULL );
+    p->pSols = ABC_CALLOC( float, p->nObjs * nSols );
+    for ( i = 0; i < nDims; i++ )
+    {
+        pX = Emb_ManVec( p, i );
+        for ( j = 0; j < nSols; j++ )
+        {
+            pY = Emb_ManSol( p, j );
+            for ( k = 0; k < p->nObjs; k++ )
+                pY[k] += pX[k] * p->pEigen[j][i];
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Projects into square of size [0;GIA_PLACE_SIZE] x [0;GIA_PLACE_SIZE].]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManDerivePlacement( Emb_Man_t * p, int nSols )
+{
+    float * pY0, * pY1, Max0, Max1, Min0, Min1, Str0, Str1;
+    int * pPerm0, * pPerm1;
+    int k;
+    if ( nSols != 2 )
+        return;
+    // compute intervals
+    Min0 =  ABC_INFINITY;
+    Max0 = -ABC_INFINITY;
+    pY0 = Emb_ManSol( p, 0 );
+    for ( k = 0; k < p->nObjs; k++ )
+    {
+        Min0 = Abc_MinInt( Min0, pY0[k] );
+        Max0 = Abc_MaxInt( Max0, pY0[k] );
+    }
+    Str0 = 1.0*GIA_PLACE_SIZE/(Max0 - Min0);
+    // update the coordinates
+    for ( k = 0; k < p->nObjs; k++ )
+        pY0[k] = (pY0[k] != 0.0) ? ((pY0[k] - Min0) * Str0) : 0.0;
+
+    // compute intervals
+    Min1 =  ABC_INFINITY;
+    Max1 = -ABC_INFINITY;
+    pY1 = Emb_ManSol( p, 1 );
+    for ( k = 0; k < p->nObjs; k++ )
+    {
+        Min1 = Abc_MinInt( Min1, pY1[k] );
+        Max1 = Abc_MaxInt( Max1, pY1[k] );
+    }
+    Str1 = 1.0*GIA_PLACE_SIZE/(Max1 - Min1);
+    // update the coordinates
+    for ( k = 0; k < p->nObjs; k++ )
+        pY1[k] = (pY1[k] != 0.0) ? ((pY1[k] - Min1) * Str1) : 0.0;
+
+    // derive the order of these numbers
+    pPerm0 = Gia_SortFloats( pY0, NULL, p->nObjs );
+    pPerm1 = Gia_SortFloats( pY1, NULL, p->nObjs );
+
+    // average solutions and project them into square [0;GIA_PLACE_SIZE] x [0;GIA_PLACE_SIZE]
+    p->pPlacement = ABC_ALLOC( unsigned short, 2 * p->nObjs );
+    for ( k = 0; k < p->nObjs; k++ )
+    {
+        p->pPlacement[2*pPerm0[k]+0] = (unsigned short)(int)(1.0 * k * GIA_PLACE_SIZE / p->nObjs);
+        p->pPlacement[2*pPerm1[k]+1] = (unsigned short)(int)(1.0 * k * GIA_PLACE_SIZE / p->nObjs);
+    }
+    ABC_FREE( pPerm0 );
+    ABC_FREE( pPerm1 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes wire-length.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+double Emb_ManComputeHPWL( Emb_Man_t * p )
+{
+    double Result = 0.0;
+    Emb_Obj_t * pThis, * pNext;
+    int i, k, iMinX, iMaxX, iMinY, iMaxY;
+    if ( p->pPlacement == NULL )
+        return 0.0;
+    Emb_ManForEachObj( p, pThis, i )
+    {
+        iMinX = iMaxX = p->pPlacement[2*pThis->Value+0];
+        iMinY = iMaxY = p->pPlacement[2*pThis->Value+1];
+        Emb_ObjForEachFanout( pThis, pNext, k )
+        {
+            iMinX = Abc_MinInt( iMinX, p->pPlacement[2*pNext->Value+0] );
+            iMaxX = Abc_MaxInt( iMaxX, p->pPlacement[2*pNext->Value+0] );
+            iMinY = Abc_MinInt( iMinY, p->pPlacement[2*pNext->Value+1] );
+            iMaxY = Abc_MaxInt( iMaxY, p->pPlacement[2*pNext->Value+1] );
+        }
+        Result += (iMaxX - iMinX) + (iMaxY - iMinY);
+    }
+    return Result;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs iterative refinement of the given placement.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManPlacementRefine( Emb_Man_t * p, int nIters, int fVerbose )
+{
+    Emb_Obj_t * pThis, * pNext;
+    double CostThis, CostPrev;
+    float * pEdgeX, * pEdgeY;
+    float * pVertX, * pVertY;
+    float VertX, VertY;
+    int * pPermX, * pPermY;
+    int i, k, Iter, iMinX, iMaxX, iMinY, iMaxY;
+    abctime clk = Abc_Clock();
+    if ( p->pPlacement == NULL )
+        return;
+    pEdgeX = ABC_ALLOC( float, p->nObjs );
+    pEdgeY = ABC_ALLOC( float, p->nObjs );
+    pVertX = ABC_ALLOC( float, p->nObjs );
+    pVertY = ABC_ALLOC( float, p->nObjs );
+    // refine placement
+    CostPrev = 0.0;
+    for ( Iter = 0; Iter < nIters; Iter++ )
+    {
+        // compute centers of hyperedges
+        CostThis = 0.0;
+        Emb_ManForEachObj( p, pThis, i )
+        {
+            iMinX = iMaxX = p->pPlacement[2*pThis->Value+0];
+            iMinY = iMaxY = p->pPlacement[2*pThis->Value+1];
+            Emb_ObjForEachFanout( pThis, pNext, k )
+            {
+                iMinX = Abc_MinInt( iMinX, p->pPlacement[2*pNext->Value+0] );
+                iMaxX = Abc_MaxInt( iMaxX, p->pPlacement[2*pNext->Value+0] );
+                iMinY = Abc_MinInt( iMinY, p->pPlacement[2*pNext->Value+1] );
+                iMaxY = Abc_MaxInt( iMaxY, p->pPlacement[2*pNext->Value+1] );
+            }
+            pEdgeX[pThis->Value] = 0.5 * (iMaxX + iMinX);
+            pEdgeY[pThis->Value] = 0.5 * (iMaxY + iMinY);
+            CostThis += (iMaxX - iMinX) + (iMaxY - iMinY);
+        }
+        // compute new centers of objects
+        Emb_ManForEachObj( p, pThis, i )
+        {
+            VertX = pEdgeX[pThis->Value];
+            VertY = pEdgeY[pThis->Value];
+            Emb_ObjForEachFanin( pThis, pNext, k )
+            {
+                VertX += pEdgeX[pNext->Value];
+                VertY += pEdgeY[pNext->Value];
+            }
+            pVertX[pThis->Value] = VertX / (Emb_ObjFaninNum(pThis) + 1);
+            pVertY[pThis->Value] = VertY / (Emb_ObjFaninNum(pThis) + 1);
+        }
+        // sort these numbers
+        pPermX = Gia_SortFloats( pVertX, NULL, p->nObjs );
+        pPermY = Gia_SortFloats( pVertY, NULL, p->nObjs );
+        for ( k = 0; k < p->nObjs; k++ )
+        {
+            p->pPlacement[2*pPermX[k]+0] = (unsigned short)(int)(1.0 * k * GIA_PLACE_SIZE / p->nObjs);
+            p->pPlacement[2*pPermY[k]+1] = (unsigned short)(int)(1.0 * k * GIA_PLACE_SIZE / p->nObjs);
+        }
+        ABC_FREE( pPermX );
+        ABC_FREE( pPermY );
+        // evaluate cost
+        if ( fVerbose )
+        {
+        printf( "%2d : HPWL = %e  ", Iter+1, CostThis );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+        }
+    }
+    ABC_FREE( pEdgeX );
+    ABC_FREE( pEdgeY );
+    ABC_FREE( pVertX );
+    ABC_FREE( pVertY );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives solutions from original vectors and eigenvectors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManPrintSolutions( Emb_Man_t * p, int nSols )
+{
+    float * pSol;
+    int i, k;
+    for ( i = 0; i < nSols; i++ )
+    {
+        pSol = Emb_ManSol( p, i );
+        for ( k = 0; k < p->nObjs; k++ )
+            printf( "%4d ", (int)(100 * pSol[k]) );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares image for dumping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Emb_ManDumpGnuplotPrepare( Emb_Man_t * p )
+{
+//    int nRows = 496;
+//    int nCols = 710;
+    int nRows = 500;
+    int nCols = 700;
+    Vec_Int_t * vLines;
+    Emb_Obj_t * pThis;
+    char * pBuffer, ** ppRows;
+    int i, k, placeX, placeY;
+    int fStart;
+    // alloc memory
+    pBuffer = ABC_CALLOC( char, nRows * (nCols+1) );
+    ppRows  = ABC_ALLOC( char *, nRows );
+    for ( i = 0; i < nRows; i++ )
+        ppRows[i] = pBuffer + i*(nCols+1);
+    // put data into them
+    Emb_ManForEachObj( p, pThis, i )
+    {
+        placeX = p->pPlacement[2*pThis->Value+0] * nCols / (1<<16);
+        placeY = p->pPlacement[2*pThis->Value+1] * nRows / (1<<16);
+        assert( placeX < nCols && placeY < nRows );
+        ppRows[placeY][placeX] = 1;
+    }
+    // select lines
+    vLines = Vec_IntAlloc( 1000 );
+    for ( i = 0; i < nRows; i++ )
+    {
+        fStart = 0;
+        for ( k = 0; k <= nCols; k++ )
+        {
+            if ( ppRows[i][k] && !fStart )
+            {
+                Vec_IntPush( vLines, k );
+                Vec_IntPush( vLines, i );
+                fStart = 1;
+            }
+            if ( !ppRows[i][k] && fStart )
+            {
+                Vec_IntPush( vLines, k-1 );
+                Vec_IntPush( vLines, i );
+                fStart = 0;
+            }
+        }
+        assert( fStart == 0 );
+    }
+    ABC_FREE( pBuffer );
+    ABC_FREE( ppRows );
+    return vLines;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives solutions from original vectors and eigenvectors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Emb_ManDumpGnuplot( Emb_Man_t * p, char * pName, int fDumpLarge, int fShowImage )
+{
+    extern void Gia_ManGnuplotShow( char * pPlotFileName );
+//    char * pDirectory = "place\\";
+    char * pDirectory = "";
+//    extern char * Ioa_TimeStamp();
+    FILE * pFile;
+    char Buffer[1000];
+    Emb_Obj_t * pThis, * pNext;
+    int i, k;
+    if ( p->pPlacement == NULL )
+    {
+        printf( "Emb_ManDumpGnuplot(): Placement is not available.\n" );
+        return;
+    }
+    sprintf( Buffer, "%s%s", pDirectory, Gia_FileNameGenericAppend(pName, ".plt") ); 
+    pFile = fopen( Buffer, "w" );
+    fprintf( pFile, "# This Gnuplot file was produced by ABC on %s\n", Ioa_TimeStamp() );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "set nokey\n" );
+    fprintf( pFile, "\n" );
+    if ( !fShowImage )
+    {
+//    fprintf( pFile, "set terminal postscript\n" );
+    fprintf( pFile, "set terminal gif font \'arial\' 10 size 800,600 xffffff x000000 x000000 x000000\n" );
+    fprintf( pFile, "set output \'%s\'\n", Gia_FileNameGenericAppend(pName, ".gif") );
+    fprintf( pFile, "\n" );
+    }
+    fprintf( pFile, "set title \"%s :  PI = %d   PO = %d   FF = %d   Node = %d   Obj = %d  HPWL = %.2e\\n", 
+        pName, Emb_ManPiNum(p), Emb_ManPoNum(p), Emb_ManRegNum(p), Emb_ManNodeNum(p), Emb_ManObjNum(p), Emb_ManComputeHPWL(p) );
+    fprintf( pFile, "(image generated by ABC and Gnuplot on %s)\"", Ioa_TimeStamp() );
+    fprintf( pFile, "font \"Times, 12\"\n" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "plot [:] '-' w l\n" );
+    fprintf( pFile, "\n" );
+    if ( fDumpLarge )
+    {
+        int begX, begY, endX, endY;
+        Vec_Int_t * vLines = Emb_ManDumpGnuplotPrepare( p );
+        Vec_IntForEachEntry( vLines, begX, i )
+        {
+            begY = Vec_IntEntry( vLines, i+1 );
+            endX = Vec_IntEntry( vLines, i+2 );
+            endY = Vec_IntEntry( vLines, i+3 );
+            i += 3;
+            fprintf( pFile, "%5d %5d\n", begX, begY );
+            fprintf( pFile, "%5d %5d\n", endX, endY );
+            fprintf( pFile, "\n" );
+        }
+        Vec_IntFree( vLines );
+    }
+    else
+    {
+        Emb_ManForEachObj( p, pThis, i )
+        {
+            if ( !Emb_ObjIsTravIdCurrent(p, pThis) )
+                continue;
+            Emb_ObjForEachFanout( pThis, pNext, k )
+            {
+                assert( Emb_ObjIsTravIdCurrent(p, pNext) );
+                fprintf( pFile, "%5d %5d\n", p->pPlacement[2*pThis->Value+0], p->pPlacement[2*pThis->Value+1] );
+                fprintf( pFile, "%5d %5d\n", p->pPlacement[2*pNext->Value+0], p->pPlacement[2*pNext->Value+1] );
+                fprintf( pFile, "\n" );
+            }
+        }
+    }
+    fprintf( pFile, "EOF\n" );
+    fprintf( pFile, "\n" );
+    if ( fShowImage )
+    {
+    fprintf( pFile, "pause -1 \"Close window\"\n" );  // Hit return to continue
+    fprintf( pFile, "reset\n" );
+    fprintf( pFile, "\n" );
+    }
+    else
+    {
+    fprintf( pFile, "# pause -1 \"Close window\"\n" );  // Hit return to continue
+    fprintf( pFile, "# reset\n" );
+    fprintf( pFile, "\n" );
+    }
+    fclose( pFile );
+    if ( fShowImage )
+        Gia_ManGnuplotShow( Buffer );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes dimentions of the graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSolveProblem( Gia_Man_t * pGia, Emb_Par_t * pPars )
+{
+    Emb_Man_t * p;
+    int i;
+    abctime clkSetup;
+    abctime clk;
+//   Gia_ManTestDistance( pGia );
+
+    // transform AIG into internal data-structure
+clk = Abc_Clock();
+    if ( pPars->fCluster )
+    {
+        p = Emb_ManStart( pGia );
+        if ( pPars->fVerbose )
+        {
+            printf( "Clustered: " );
+            Emb_ManPrintStats( p );
+        }
+    }
+    else
+        p = Emb_ManStartSimple( pGia );
+    p->fVerbose = pPars->fVerbose;
+//    Emb_ManPrintFanio( p );
+
+    // prepare data-structure
+    Gia_ManRandom( 1 );  // reset random numbers for deterministic behavior
+    Emb_ManResetTravId( p );
+    Emb_ManSetValue( p );
+clkSetup = Abc_Clock() - clk;
+
+clk = Abc_Clock();
+    Emb_ManComputeDimensions( p, pPars->nDims );
+if ( pPars->fVerbose )
+ABC_PRT( "Setup     ", clkSetup );
+if ( pPars->fVerbose )
+ABC_PRT( "Dimensions", Abc_Clock() - clk );
+
+clk = Abc_Clock();
+    Emb_ManComputeCovariance( p, pPars->nDims );
+if ( pPars->fVerbose )
+ABC_PRT( "Matrix    ", Abc_Clock() - clk );
+
+clk = Abc_Clock();
+    Emb_ManComputeEigenvectors( p, pPars->nDims, pPars->nSols );
+    Emb_ManComputeSolutions( p, pPars->nDims, pPars->nSols );
+    Emb_ManDerivePlacement( p, pPars->nSols );
+if ( pPars->fVerbose )
+ABC_PRT( "Eigenvecs ", Abc_Clock() - clk );
+
+    if ( pPars->fRefine )
+    {
+clk = Abc_Clock();
+    Emb_ManPlacementRefine( p, pPars->nIters, pPars->fVerbose );
+if ( pPars->fVerbose )
+ABC_PRT( "Refinement", Abc_Clock() - clk );
+    }
+
+    if ( (pPars->fDump || pPars->fDumpLarge) && pPars->nSols == 2 )
+    {
+clk = Abc_Clock();
+        Emb_ManDumpGnuplot( p, pGia->pName, pPars->fDumpLarge, pPars->fShowImage );
+if ( pPars->fVerbose )
+ABC_PRT( "Image dump", Abc_Clock() - clk );
+    }
+
+    // transfer placement
+    if ( Gia_ManObjNum(pGia) == p->nObjs )
+    {
+        // assuming normalized ordering of the AIG
+        pGia->pPlacement = ABC_CALLOC( Gia_Plc_t, p->nObjs );
+        for ( i = 0; i < p->nObjs; i++ ) 
+        {
+            pGia->pPlacement[i].xCoord = p->pPlacement[2*i+0];
+            pGia->pPlacement[i].yCoord = p->pPlacement[2*i+1];
+        }
+    }
+    Emb_ManStop( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaEnable.c b/abc-build/src/aig/gia/giaEnable.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaEnable.c
@@ -0,0 +1,651 @@
+/**CFile****************************************************************
+
+  FileName    [gia.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Structural detection of enables, sets and resets.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_CollectSuper_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper )
+{
+    // if the new node is complemented or a PI, another gate begins
+    if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) )
+    {
+        Vec_IntPushUnique( vSuper, Gia_ObjId(p, Gia_Regular(pObj)) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    // go through the branches
+    Gia_CollectSuper_rec( p, Gia_ObjChild0(pObj), vSuper );
+    Gia_CollectSuper_rec( p, Gia_ObjChild1(pObj), vSuper );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_CollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper )
+{
+    assert( !Gia_IsComplement(pObj) );
+    Vec_IntClear( vSuper );
+//    Gia_CollectSuper_rec( p, pObj, vSuper );
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        Vec_IntPushUnique( vSuper, Gia_ObjId(p, Gia_ObjFanin0(pObj)) );
+        Vec_IntPushUnique( vSuper, Gia_ObjId(p, Gia_ObjFanin1(pObj)) );
+    }
+    else
+        Vec_IntPushUnique( vSuper, Gia_ObjId(p, Gia_Regular(pObj)) );
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintSignals( Gia_Man_t * p, int * pFreq, char * pStr )
+{
+    Vec_Int_t * vObjs;
+    int i, Counter = 0, nTotal = 0;
+    vObjs = Vec_IntAlloc( 100 );
+    for ( i = 0; i < Gia_ManObjNum(p); i++ )
+        if ( pFreq[i] > 1 )
+        {
+            nTotal += pFreq[i];
+            Counter++;
+        }
+    printf( "%s (total = %d  driven = %d)\n", pStr, Counter, nTotal );
+    Counter = 0;
+    for ( i = 0; i < Gia_ManObjNum(p); i++ )
+        if ( pFreq[i] > 10 )
+        {
+            printf( "%3d :   Obj = %6d   Refs = %6d   Freq = %6d\n", 
+                ++Counter, i, Gia_ObjRefNum(p, Gia_ManObj(p,i)), pFreq[i] );
+            Vec_IntPush( vObjs, i );
+        }
+    Vec_IntFree( vObjs );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManDetectSeqSignals( Gia_Man_t * p, int fSetReset, int fVerbose )
+{
+    Vec_Int_t * vSuper;
+    Gia_Obj_t * pFlop, * pObjC, * pObj0, * pObj1, * pNode, * pTemp;
+    int i, k, Ent, * pSets, * pResets, * pEnables;
+    int nHaveSetReset = 0, nHaveEnable = 0;
+    assert( Gia_ManRegNum(p) > 0 );
+    pSets    = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    pResets  = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    pEnables = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    vSuper   = Vec_IntAlloc( 100 );
+    Gia_ManForEachRi( p, pFlop, i )
+    {
+        pNode = Gia_ObjFanin0(pFlop);
+        if ( !Gia_ObjIsAnd(pNode) )
+            continue;
+        // detect sets/resets
+        Gia_CollectSuper( p, pNode, vSuper );
+        if ( Gia_ObjFaninC0(pFlop) )
+            Vec_IntForEachEntry( vSuper, Ent, k )
+                pSets[Ent]++;
+        else
+            Vec_IntForEachEntry( vSuper, Ent, k )
+                pResets[Ent]++;
+        // detect enables
+        if ( !Gia_ObjIsMuxType(pNode) )
+            continue;
+        pObjC = Gia_ObjRecognizeMux( pNode, &pObj0, &pObj1 );
+        pTemp = Gia_ObjRiToRo( p, pFlop );
+        if ( Gia_Regular(pObj0) != pTemp && Gia_Regular(pObj1) != pTemp )
+            continue;
+        if ( !Gia_ObjFaninC0(pFlop) )
+        {
+            pObj0 = Gia_Not(pObj0);
+            pObj1 = Gia_Not(pObj1);
+        }
+        if ( Gia_IsComplement(pObjC) )
+        {
+            pObjC = Gia_Not(pObjC);
+            pTemp = pObj0;
+            pObj0 = pObj1;
+            pObj1 = pTemp;
+        }
+        // detect controls
+//        Gia_CollectSuper( p, pObjC, vSuper );
+//        Vec_IntForEachEntry( vSuper, Ent, k )
+//            pEnables[Ent]++;
+        pEnables[Gia_ObjId(p, pObjC)]++;
+        nHaveEnable++;
+    }
+    Gia_ManForEachRi( p, pFlop, i )
+    {
+        pNode = Gia_ObjFanin0(pFlop);
+        if ( !Gia_ObjIsAnd(pNode) )
+            continue;
+        // detect sets/resets
+        Gia_CollectSuper( p, pNode, vSuper );
+        Vec_IntForEachEntry( vSuper, Ent, k )
+            if ( pSets[Ent] > 1 || pResets[Ent] > 1 )
+            {
+                nHaveSetReset++;
+                break;
+            }
+    }
+    Vec_IntFree( vSuper );
+    ABC_FREE( p->pRefs );
+    Gia_ManCreateRefs( p );
+    if ( fVerbose )
+    {
+        printf( "Flops with set/reset = %6d. Flops with enable = %6d.\n", nHaveSetReset, nHaveEnable );
+        if ( fSetReset )
+        {
+            Gia_ManPrintSignals( p, pSets, "Set signals" );
+            Gia_ManPrintSignals( p, pResets, "Reset signals" );
+        }
+        Gia_ManPrintSignals( p, pEnables, "Enable signals" );
+    }
+    ABC_FREE( p->pRefs );
+    ABC_FREE( pSets );
+    ABC_FREE( pResets );
+    ABC_FREE( pEnables );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManDetectSeqSignalsWithFanout( Gia_Man_t * p, int nFanMax, int fVerbose )
+{
+    Vec_Int_t * vResult;
+    Vec_Int_t * vSuper;
+    Gia_Obj_t * pFlop, * pObjC, * pObj0, * pObj1, * pNode, * pTemp;
+    int i, k, Ent, * pSets, * pResets, * pEnables;
+    int nHaveSetReset = 0, nHaveEnable = 0;
+    assert( Gia_ManRegNum(p) > 0 );
+    pSets    = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    pResets  = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    pEnables = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    vSuper   = Vec_IntAlloc( 100 );
+    Gia_ManForEachRi( p, pFlop, i )
+    {
+        pNode = Gia_ObjFanin0(pFlop);
+        if ( !Gia_ObjIsAnd(pNode) )
+            continue;
+        // detect sets/resets
+        Gia_CollectSuper( p, pNode, vSuper );
+        if ( Gia_ObjFaninC0(pFlop) )
+            Vec_IntForEachEntry( vSuper, Ent, k )
+                pSets[Ent]++;
+        else
+            Vec_IntForEachEntry( vSuper, Ent, k )
+                pResets[Ent]++;
+        // detect enables
+        if ( !Gia_ObjIsMuxType(pNode) )
+            continue;
+        pObjC = Gia_ObjRecognizeMux( pNode, &pObj0, &pObj1 );
+        pTemp = Gia_ObjRiToRo( p, pFlop );
+        if ( Gia_Regular(pObj0) != pTemp && Gia_Regular(pObj1) != pTemp )
+            continue;
+        if ( !Gia_ObjFaninC0(pFlop) )
+        {
+            pObj0 = Gia_Not(pObj0);
+            pObj1 = Gia_Not(pObj1);
+        }
+        if ( Gia_IsComplement(pObjC) )
+        {
+            pObjC = Gia_Not(pObjC);
+            pTemp = pObj0;
+            pObj0 = pObj1;
+            pObj1 = pTemp;
+        }
+        // detect controls
+//        Gia_CollectSuper( p, pObjC, vSuper );
+//        Vec_IntForEachEntry( vSuper, Ent, k )
+//            pEnables[Ent]++;
+        pEnables[Gia_ObjId(p, pObjC)]++;
+        nHaveEnable++;
+    }
+    Gia_ManForEachRi( p, pFlop, i )
+    {
+        pNode = Gia_ObjFanin0(pFlop);
+        if ( !Gia_ObjIsAnd(pNode) )
+            continue;
+        // detect sets/resets
+        Gia_CollectSuper( p, pNode, vSuper );
+        Vec_IntForEachEntry( vSuper, Ent, k )
+            if ( pSets[Ent] > 1 || pResets[Ent] > 1 )
+            {
+                nHaveSetReset++;
+                break;
+            }
+    }
+    Vec_IntFree( vSuper );
+    vResult  = Vec_IntAlloc( 100 );
+    for ( i = 1; i < Gia_ManObjNum(p); i++ )
+        if ( pSets[i] > nFanMax )
+        {
+            if ( fVerbose )
+                printf( "Adding set signal %d related to %d flops.\n", i, pSets[i] );
+            Vec_IntPushUnique( vResult, i );
+        }
+    for ( i = 1; i < Gia_ManObjNum(p); i++ )
+        if ( pResets[i] > nFanMax )
+        {
+            if ( fVerbose )
+                printf( "Adding reset signal %d related to %d flops.\n", i, pResets[i] );
+            Vec_IntPushUnique( vResult, i );
+        }
+    for ( i = 1; i < Gia_ManObjNum(p); i++ )
+        if ( pEnables[i] > nFanMax )
+        {
+            if ( fVerbose )
+                printf( "Adding enable signal %d related to %d flops.\n", i, pEnables[i] );
+            Vec_IntPushUnique( vResult, i );
+        }
+    ABC_FREE( pSets );
+    ABC_FREE( pResets );
+    ABC_FREE( pEnables );
+    return vResult;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers attributes from the original one to the final one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManTransferFrames( Gia_Man_t * pAig, Gia_Man_t * pFrames, int nFrames, Gia_Man_t * pNew, Vec_Int_t * vSigs )
+{
+    Vec_Int_t * vSigsNew;
+    Gia_Obj_t * pObj, * pObjF;
+    int k, f;
+    vSigsNew = Vec_IntAlloc( 100 );
+    Gia_ManForEachObjVec( vSigs, pAig, pObj, k )
+    {
+        assert( Gia_ObjIsCand(pObj) );
+        for ( f = 0; f < nFrames; f++ )
+        {
+            pObjF = Gia_ManObj( pFrames, Abc_Lit2Var(Gia_ObjCopyF( pAig, f, pObj )) );
+            if ( pObjF->Value && ~pObjF->Value )
+                Vec_IntPushUnique( vSigsNew, Abc_Lit2Var(pObjF->Value) );
+        }
+    }
+    return vSigsNew;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManUnrollInit( Gia_Man_t * p, int nFrames )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj, * pObjRi, * pObjRo;
+    int f, i;
+    ABC_FREE( p->pCopies );
+    p->pCopies = ABC_FALLOC( int, nFrames * Gia_ManObjNum(p) );
+    pNew = Gia_ManStart( nFrames * Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachRo( p, pObj, i )
+        Gia_ObjSetCopyF( p, 0, pObj, 0 );
+    for ( f = 0; f < nFrames; f++ )
+    {
+        Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 );
+        Gia_ManForEachPi( p, pObj, i )
+            Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) );
+        Gia_ManForEachAnd( p, pObj, i )
+            Gia_ObjSetCopyF( p, f, pObj, Gia_ManHashAnd(pNew, Gia_ObjFanin0CopyF(p, f, pObj), Gia_ObjFanin1CopyF(p, f, pObj)) );
+        Gia_ManForEachCo( p, pObj, i )
+            Gia_ObjSetCopyF( p, f, pObj, Gia_ObjFanin0CopyF(p, f, pObj) );
+        Gia_ManForEachPo( p, pObj, i )
+            Gia_ManAppendCo( pNew, Gia_ObjCopyF(p, f, pObj) );
+        if ( f == nFrames - 1 )
+            break;
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, i )
+            Gia_ObjSetCopyF( p, f+1, pObjRo, Gia_ObjCopyF(p, f, pObjRi) );
+    }
+    Gia_ManHashStop( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Unrolls initialized timeframes while cofactoring some vars.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManUnrollAndCofactor( Gia_Man_t * p, int nFrames, int nFanMax, int fVerbose )
+{
+    Vec_Int_t * vCofSigs, * vTemp;
+    Gia_Man_t * pAig, * pFrames, * pNew;
+    // compute initialized timeframes
+    pFrames  = Gia_ManUnrollInit( p, nFrames );
+    pAig     = Gia_ManCleanup( pFrames );
+    // compute and remap set/reset/enable signals
+    vCofSigs = Gia_ManDetectSeqSignalsWithFanout( p, nFanMax, fVerbose );
+    vCofSigs = Gia_ManTransferFrames( p, pFrames, nFrames, pAig, vTemp = vCofSigs );
+    Vec_IntFree( vTemp );
+    Gia_ManStop( pFrames );
+    ABC_FREE( p->pCopies );
+    // cofactor all these variables
+    pNew = Gia_ManDupCofAllInt( pAig, vCofSigs, fVerbose );
+    Vec_IntFree( vCofSigs );
+    Gia_ManStop( pAig );
+    return pNew;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transform seq circuits with enables by removing enables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManRemoveEnables2( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew, * pAux; 
+    Gia_Obj_t * pTemp, * pObjC, * pObj0, * pObj1, * pFlopIn, * pFlopOut;
+    Gia_Obj_t * pThis, * pNode;
+    int i;
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pThis, i )
+        pThis->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachAnd( p, pThis, i )
+        pThis->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pThis), Gia_ObjFanin1Copy(pThis) );
+    Gia_ManForEachPo( p, pThis, i )
+        pThis->Value = Gia_ObjFanin0Copy(pThis);
+    Gia_ManForEachRi( p, pFlopIn, i )
+    {
+        pNode = Gia_ObjFanin0(pFlopIn);
+        if ( !Gia_ObjIsMuxType(pNode) )
+        {
+            printf( "Cannot recognize enable of flop %d.\n", i );
+            continue;
+        }
+        pObjC = Gia_ObjRecognizeMux( pNode, &pObj1, &pObj0 );
+        pFlopOut = Gia_ObjRiToRo( p, pFlopIn );
+        if ( Gia_Regular(pObj0) != pFlopOut && Gia_Regular(pObj1) != pFlopOut )
+        {
+            printf( "Cannot recognize self-loop of enable flop %d.\n", i );
+            continue;
+        }
+        if ( !Gia_ObjFaninC0(pFlopIn) )
+        {
+            pObj0 = Gia_Not(pObj0);
+            pObj1 = Gia_Not(pObj1);
+        }
+        if ( Gia_IsComplement(pObjC) )
+        {
+            pObjC = Gia_Not(pObjC);
+            pTemp = pObj0;
+            pObj0 = pObj1;
+            pObj1 = pTemp;
+        }
+        if ( Gia_Regular(pObj0) == pFlopOut )
+        {
+//            printf( "FlopIn compl = %d. FlopOut is d0. Complement = %d.\n", 
+//                Gia_ObjFaninC0(pFlopIn), Gia_IsComplement(pObj0) );
+            pFlopIn->Value = Abc_LitNotCond(Gia_Regular(pObj1)->Value, !Gia_IsComplement(pObj1));
+        }
+        else if ( Gia_Regular(pObj1) == pFlopOut )
+        {
+//            printf( "FlopIn compl = %d. FlopOut is d1. Complement = %d.\n", 
+//                Gia_ObjFaninC0(pFlopIn), Gia_IsComplement(pObj1) );
+            pFlopIn->Value = Abc_LitNotCond(Gia_Regular(pObj0)->Value, !Gia_IsComplement(pObj0));
+        }
+    }
+    Gia_ManForEachCo( p, pThis, i )
+        Gia_ManAppendCo( pNew, pThis->Value );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    pNew = Gia_ManCleanup( pAux = pNew );
+    Gia_ManStop( pAux );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transform seq circuits with enables by removing enables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManRemoveEnables( Gia_Man_t * p )
+{
+    Vec_Ptr_t * vCtrls, * vDatas;
+    Vec_Int_t * vFlopClasses;
+    Gia_Man_t * pNew, * pAux; 
+    Gia_Obj_t * pFlopIn, * pFlopOut, * pDriver, * pFan0, * pFan1, * pCtrl, * pData, * pObj;
+    int i, iClass, fCompl, Counter = 0;
+    vCtrls = Vec_PtrAlloc( 100 );
+    Vec_PtrPush( vCtrls, NULL );
+    vDatas = Vec_PtrAlloc( Gia_ManRegNum(p) );
+    vFlopClasses = Vec_IntAlloc( Gia_ManRegNum(p) );
+    Gia_ManForEachRi( p, pFlopIn, i )
+    {
+        fCompl = Gia_ObjFaninC0(pFlopIn);
+        pDriver = Gia_ObjFanin0(pFlopIn);
+        if ( !Gia_ObjIsAnd(pDriver) )
+        {
+            printf( "The flop driver %d is not a node.\n", i );
+            Vec_PtrPush( vDatas, NULL );
+            Vec_IntPush( vFlopClasses, 0 );
+            Counter++;
+            continue;
+        }
+        if ( !Gia_ObjFaninC0(pDriver) || !Gia_ObjFaninC1(pDriver) )
+        {
+            printf( "The flop driver %d is not an OR gate.\n", i );
+            Vec_PtrPush( vDatas, NULL );
+            Vec_IntPush( vFlopClasses, 0 );
+            Counter++;
+            continue;
+        }
+        pFan0 = Gia_ObjFanin0(pDriver);
+        pFan1 = Gia_ObjFanin1(pDriver);
+        if ( !Gia_ObjIsAnd(pFan0) || !Gia_ObjIsAnd(pFan1) )
+        {
+            printf( "The flop driver fanin %d is not a node.\n", i );
+            Vec_PtrPush( vDatas, NULL );
+            Vec_IntPush( vFlopClasses, 0 );
+            Counter++;
+            continue;
+        }
+        pFlopOut = Gia_ObjRiToRo( p, pFlopIn );
+        pFlopOut = Gia_NotCond( pFlopOut, !fCompl );
+        if ( Gia_ObjChild0(pFan0) != pFlopOut && Gia_ObjChild1(pFan0) != pFlopOut && 
+             Gia_ObjChild0(pFan1) != pFlopOut && Gia_ObjChild1(pFan1) != pFlopOut )
+        {
+            printf( "The flop %d does not have a self-loop.\n", i );
+            Vec_PtrPush( vDatas, NULL );
+            Vec_IntPush( vFlopClasses, 0 );
+            Counter++;
+            continue;
+        }
+        pData = NULL;
+        if ( Gia_ObjChild0(pFan0) == pFlopOut )
+        {
+            pCtrl = Gia_Not( Gia_ObjChild1(pFan0) );
+            if ( Gia_ObjFanin0(pFan1) == Gia_Regular(pCtrl) )
+                pData = Gia_ObjChild1(pFan1);
+            else
+                pData = Gia_ObjChild0(pFan1);
+        }
+        else if ( Gia_ObjChild1(pFan0) == pFlopOut )
+        {
+            pCtrl = Gia_Not( Gia_ObjChild0(pFan0) );
+            if ( Gia_ObjFanin0(pFan1) == Gia_Regular(pCtrl) )
+                pData = Gia_ObjChild1(pFan1);
+            else
+                pData = Gia_ObjChild0(pFan1);
+        }
+        else if ( Gia_ObjChild0(pFan1) == pFlopOut )
+        {
+            pCtrl = Gia_Not( Gia_ObjChild1(pFan1) );
+            if ( Gia_ObjFanin0(pFan0) == Gia_Regular(pCtrl) )
+                pData = Gia_ObjChild1(pFan0);
+            else
+                pData = Gia_ObjChild0(pFan0);
+        }
+        else if ( Gia_ObjChild1(pFan1) == pFlopOut )
+        {
+            pCtrl = Gia_Not( Gia_ObjChild0(pFan1) );
+            if ( Gia_ObjFanin0(pFan0) == Gia_Regular(pCtrl) )
+                pData = Gia_ObjChild1(pFan0);
+            else
+                pData = Gia_ObjChild0(pFan0);
+        }
+        else assert( 0 );
+        if ( Vec_PtrFind( vCtrls, pCtrl ) == -1 )
+            Vec_PtrPush( vCtrls, pCtrl );
+        iClass = Vec_PtrFind( vCtrls, pCtrl );
+        pData = Gia_NotCond( pData, !fCompl );
+        Vec_PtrPush( vDatas, pData );
+        Vec_IntPush( vFlopClasses, iClass );
+    }
+    assert( Vec_PtrSize( vDatas ) == Gia_ManRegNum(p) );
+    assert( Vec_IntSize( vFlopClasses ) == Gia_ManRegNum(p) );
+    printf( "Detected %d classes.\n", Vec_PtrSize(vCtrls) - (Counter == 0) );
+    Vec_PtrFree( vCtrls );
+    
+
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Gia_ManAppendCi( pNew );
+        else if ( Gia_ObjIsPo(p, pObj) )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+    Gia_ManForEachRi( p, pObj, i )
+    {
+        pData = (Gia_Obj_t *)Vec_PtrEntry(vDatas, i);
+        if ( pData == NULL )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+        else
+            pObj->Value = Gia_ManAppendCo( pNew, Abc_LitNotCond(Gia_Regular(pData)->Value, Gia_IsComplement(pData)) );
+    }
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    Vec_PtrFree( vDatas );
+
+
+    pNew = Gia_ManCleanup( pAux = pNew );
+    Gia_ManStop( pAux );
+    pNew->vFlopClasses = vFlopClasses;
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaEquiv.c b/abc-build/src/aig/gia/giaEquiv.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaEquiv.c
@@ -0,0 +1,2241 @@
+/**CFile****************************************************************
+
+  FileName    [giaEquiv.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Manipulation of equivalence classes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaEquiv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "proof/cec/cec.h"
+#include "sat/bmc/bmc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if AIG is not in the required topo order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCheckTopoOrder_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    Gia_Obj_t * pRepr;
+    if ( pObj->Value == 0 )
+        return 1;
+    pObj->Value = 0;
+    assert( Gia_ObjIsAnd(pObj) );
+    if ( !Gia_ManCheckTopoOrder_rec( p, Gia_ObjFanin0(pObj) ) )
+        return 0;
+    if ( !Gia_ManCheckTopoOrder_rec( p, Gia_ObjFanin1(pObj) ) )
+        return 0;
+    pRepr = p->pReprs ? Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ) : NULL;
+    return pRepr == NULL || pRepr->Value == 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 0 if AIG is not in the required topo order.]
+
+  Description [AIG should be in such an order that the representative
+  is always traversed before the node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCheckTopoOrder( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, RetValue = 1;
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = 0;
+    Gia_ManForEachCo( p, pObj, i )
+        RetValue &= Gia_ManCheckTopoOrder_rec( p, Gia_ObjFanin0(pObj) );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Given representatives, derives pointers to the next objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Gia_ManDeriveNexts( Gia_Man_t * p )
+{
+    unsigned * pNexts, * pTails;
+    int i;
+    assert( p->pReprs != NULL );
+    assert( p->pNexts == NULL );
+    pNexts = ABC_CALLOC( unsigned, Gia_ManObjNum(p) );
+    pTails = ABC_ALLOC( unsigned, Gia_ManObjNum(p) );
+    for ( i = 0; i < Gia_ManObjNum(p); i++ )
+        pTails[i] = i;
+    for ( i = 0; i < Gia_ManObjNum(p); i++ )
+    {
+        if ( !p->pReprs[i].iRepr || p->pReprs[i].iRepr == GIA_VOID )
+            continue;
+        pNexts[ pTails[p->pReprs[i].iRepr] ] = i;
+        pTails[p->pReprs[i].iRepr] = i;
+    }
+    ABC_FREE( pTails );
+    return (int *)pNexts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Given points to the next objects, derives representatives.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManDeriveReprs( Gia_Man_t * p )
+{
+    int i, iObj;
+    assert( p->pReprs == NULL );
+    assert( p->pNexts != NULL );
+    p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) );
+    for ( i = 0; i < Gia_ManObjNum(p); i++ )
+        Gia_ObjSetRepr( p, i, GIA_VOID );
+    for ( i = 0; i < Gia_ManObjNum(p); i++ )
+    {
+        if ( p->pNexts[i] == 0 )
+            continue;
+        if ( p->pReprs[i].iRepr != GIA_VOID )
+            continue;
+        // next is set, repr is not set
+        for ( iObj = p->pNexts[i]; iObj; iObj = p->pNexts[iObj] )
+            p->pReprs[iObj].iRepr = i;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManEquivCountLitsAll( Gia_Man_t * p )
+{
+    int i, nLits = 0;
+    for ( i = 0; i < Gia_ManObjNum(p); i++ )
+        nLits += (Gia_ObjRepr(p, i) != GIA_VOID);
+    return nLits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManEquivCountClasses( Gia_Man_t * p )
+{
+    int i, Counter = 0;
+    if ( p->pReprs == NULL )
+        return 0;
+    for ( i = 1; i < Gia_ManObjNum(p); i++ )
+        Counter += Gia_ObjIsHead(p, i);
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManEquivCheckLits( Gia_Man_t * p, int nLits )
+{
+    int nLitsReal = Gia_ManEquivCountLitsAll( p );
+    if ( nLitsReal != nLits )
+        Abc_Print( 1, "Detected a mismatch in counting equivalence classes (%d).\n", nLitsReal - nLits );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintStatsClasses( Gia_Man_t * p )
+{
+    int i, Counter = 0, Counter0 = 0, CounterX = 0, Proved = 0, nLits;
+    for ( i = 1; i < Gia_ManObjNum(p); i++ )
+    {
+        if ( Gia_ObjIsHead(p, i) )
+            Counter++;
+        else if ( Gia_ObjIsConst(p, i) )
+            Counter0++;
+        else if ( Gia_ObjIsNone(p, i) )
+            CounterX++;
+        if ( Gia_ObjProved(p, i) )
+            Proved++;
+    }
+    CounterX -= Gia_ManCoNum(p);
+    nLits = Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX;
+
+//    Abc_Print( 1, "i/o/ff =%5d/%5d/%5d  ", Gia_ManPiNum(p), Gia_ManPoNum(p), Gia_ManRegNum(p) );
+//    Abc_Print( 1, "and =%5d  ", Gia_ManAndNum(p) );
+//    Abc_Print( 1, "lev =%3d  ", Gia_ManLevelNum(p) );
+    Abc_Print( 1, "cst =%3d  cls =%6d  lit =%8d\n", Counter0, Counter, nLits );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManEquivCountLits( Gia_Man_t * p )
+{
+    int i, Counter = 0, Counter0 = 0, CounterX = 0;
+    if ( p->pReprs == NULL || p->pNexts == NULL )
+        return 0;
+    for ( i = 1; i < Gia_ManObjNum(p); i++ )
+    {
+        if ( Gia_ObjIsHead(p, i) )
+            Counter++;
+        else if ( Gia_ObjIsConst(p, i) )
+            Counter0++;
+        else if ( Gia_ObjIsNone(p, i) )
+            CounterX++;
+    }
+    CounterX -= Gia_ManCoNum(p);
+    return Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManEquivCountOne( Gia_Man_t * p, int i )
+{
+    int Ent, nLits = 1;
+    Gia_ClassForEachObj1( p, i, Ent )
+    {
+        assert( Gia_ObjRepr(p, Ent) == i );
+        nLits++;
+    }
+    return nLits;
+}
+void Gia_ManEquivPrintOne( Gia_Man_t * p, int i, int Counter )
+{
+    int Ent;
+    Abc_Print( 1, "Class %4d :  Num = %2d  {", Counter, Gia_ManEquivCountOne(p, i) );
+    Gia_ClassForEachObj( p, i, Ent )
+    {
+        Abc_Print( 1," %d", Ent );
+        if ( p->pReprs[Ent].fColorA || p->pReprs[Ent].fColorB )
+            Abc_Print( 1," <%d%d>", p->pReprs[Ent].fColorA, p->pReprs[Ent].fColorB );
+    }
+    Abc_Print( 1, " }\n" );
+}
+void Gia_ManEquivPrintClasses( Gia_Man_t * p, int fVerbose, float Mem )
+{
+    int i, Counter = 0, Counter0 = 0, CounterX = 0, Proved = 0, nLits;
+    for ( i = 1; i < Gia_ManObjNum(p); i++ )
+    {
+        if ( Gia_ObjIsHead(p, i) )
+            Counter++;
+        else if ( Gia_ObjIsConst(p, i) )
+            Counter0++;
+        else if ( Gia_ObjIsNone(p, i) )
+            CounterX++;
+        if ( Gia_ObjProved(p, i) )
+            Proved++;
+    }
+    CounterX -= Gia_ManCoNum(p);
+    nLits = Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX;
+    Abc_Print( 1, "cst =%8d  cls =%7d  lit =%8d  unused =%8d  proof =%6d  mem =%5.2f MB\n",
+        Counter0, Counter, nLits, CounterX, Proved, (Mem == 0.0) ? 8.0*Gia_ManObjNum(p)/(1<<20) : Mem );
+    assert( Gia_ManEquivCheckLits( p, nLits ) );
+    if ( fVerbose )
+    {
+//        int Ent;
+        Abc_Print( 1, "Const0 = " );
+        Gia_ManForEachConst( p, i )
+            Abc_Print( 1, "%d ", i );
+        Abc_Print( 1, "\n" );
+        Counter = 0;
+        Gia_ManForEachClass( p, i )
+            Gia_ManEquivPrintOne( p, i, ++Counter );
+/*
+        Gia_ManLevelNum( p );
+        Gia_ManForEachClass( p, i )
+            if ( i % 100 == 0 )
+            {
+//                Abc_Print( 1, "%d ", Gia_ManEquivCountOne(p, i) );
+                Gia_ClassForEachObj( p, i, Ent )
+                {
+                    Abc_Print( 1, "%d ", Gia_ObjLevel( p, Gia_ManObj(p, Ent) ) );
+                }
+                Abc_Print( 1, "\n" );
+            }
+*/
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns representative node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Gia_ManEquivRepr( Gia_Man_t * p, Gia_Obj_t * pObj, int fUseAll, int fDualOut )
+{
+    if ( fUseAll )
+    {
+        if ( Gia_ObjRepr(p, Gia_ObjId(p,pObj)) == GIA_VOID )
+            return NULL;
+    }
+    else
+    {
+        if ( !Gia_ObjProved(p, Gia_ObjId(p,pObj)) )
+            return NULL;
+    }
+//    if ( fDualOut && !Gia_ObjDiffColors( p, Gia_ObjId(p, pObj), Gia_ObjRepr(p, Gia_ObjId(p,pObj)) ) )
+    if ( fDualOut && !Gia_ObjDiffColors2( p, Gia_ObjId(p, pObj), Gia_ObjRepr(p, Gia_ObjId(p,pObj)) ) )
+        return NULL;
+    return Gia_ManObj( p, Gia_ObjRepr(p, Gia_ObjId(p,pObj)) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManEquivReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int fUseAll, int fDualOut )
+{
+    Gia_Obj_t * pRepr;
+    if ( (pRepr = Gia_ManEquivRepr(p, pObj, fUseAll, fDualOut)) )
+    {
+        Gia_ManEquivReduce_rec( pNew, p, pRepr, fUseAll, fDualOut );
+        pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) );
+        return;
+    }
+    if ( ~pObj->Value )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManEquivReduce_rec( pNew, p, Gia_ObjFanin0(pObj), fUseAll, fDualOut );
+    Gia_ManEquivReduce_rec( pNew, p, Gia_ObjFanin1(pObj), fUseAll, fDualOut );
+    pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces AIG using equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManEquivReduce( Gia_Man_t * p, int fUseAll, int fDualOut, int fSkipPhase, int fVerbose )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    if ( !p->pReprs )
+    {
+        Abc_Print( 1, "Gia_ManEquivReduce(): Equivalence classes are not available.\n" );
+        return NULL;
+    }
+    if ( fDualOut && (Gia_ManPoNum(p) & 1) )
+    {
+        Abc_Print( 1, "Gia_ManEquivReduce(): Dual-output miter should have even number of POs.\n" );
+        return NULL;
+    }
+    // check if there are any equivalences defined
+    Gia_ManForEachObj( p, pObj, i )
+        if ( Gia_ObjReprObj(p, i) != NULL )
+            break;
+    if ( i == Gia_ManObjNum(p) )
+    {
+//        Abc_Print( 1, "Gia_ManEquivReduce(): There are no equivalences to reduce.\n" );
+        return NULL;
+    }
+/*
+    if ( !Gia_ManCheckTopoOrder( p ) )
+    {
+        Abc_Print( 1, "Gia_ManEquivReduce(): AIG is not in a correct topological order.\n" );
+        return NULL;
+    }
+*/
+    if ( !fSkipPhase )
+        Gia_ManSetPhase( p );
+    if ( fDualOut )
+        Gia_ManEquivSetColors( p, fVerbose );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManEquivReduce_rec( pNew, p, Gia_ObjFanin0(pObj), fUseAll, fDualOut );
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces AIG using equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManEquivFixOutputPairs( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj0, * pObj1;
+    int i;
+    assert( (Gia_ManPoNum(p) & 1) == 0 );
+    Gia_ManForEachPo( p, pObj0, i )
+    {
+        pObj1 = Gia_ManPo( p, ++i );
+        if ( Gia_ObjChild0(pObj0) != Gia_ObjChild0(pObj1) )
+            continue;
+        pObj0->iDiff0  = Gia_ObjId(p, pObj0);
+        pObj0->fCompl0 = 0;
+        pObj1->iDiff0  = Gia_ObjId(p, pObj1);
+        pObj1->fCompl0 = 0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes pointers to the unmarked nodes..]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManEquivUpdatePointers( Gia_Man_t * p, Gia_Man_t * pNew )
+{
+    Gia_Obj_t * pObj, * pObjNew;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( !~pObj->Value )
+            continue;
+        pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) );
+        if ( pObjNew->fMark0 )
+            pObj->Value = ~0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes pointers to the unmarked nodes..]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManEquivDeriveReprs( Gia_Man_t * p, Gia_Man_t * pNew, Gia_Man_t * pFinal )
+{
+    Vec_Int_t * vClass;
+    Gia_Obj_t * pObj, * pObjNew;
+    int i, k, iNode, iRepr, iPrev;
+    // start representatives
+    pFinal->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pFinal) );
+    for ( i = 0; i < Gia_ManObjNum(pFinal); i++ )
+        Gia_ObjSetRepr( pFinal, i, GIA_VOID );
+    // iterate over constant candidates
+    Gia_ManForEachConst( p, i )
+    {
+        pObj = Gia_ManObj( p, i );
+        if ( !~pObj->Value )
+            continue;
+        pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) );
+        if ( Abc_Lit2Var(pObjNew->Value) == 0 )
+            continue;
+        Gia_ObjSetRepr( pFinal, Abc_Lit2Var(pObjNew->Value), 0 );
+    }
+    // iterate over class candidates
+    vClass = Vec_IntAlloc( 100 );
+    Gia_ManForEachClass( p, i )
+    {
+        Vec_IntClear( vClass );
+        Gia_ClassForEachObj( p, i, k )
+        {
+            pObj = Gia_ManObj( p, k );
+            if ( !~pObj->Value )
+                continue;
+            pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) );
+            Vec_IntPushUnique( vClass, Abc_Lit2Var(pObjNew->Value) );
+        }
+        if ( Vec_IntSize( vClass ) < 2 )
+            continue;
+        Vec_IntSort( vClass, 0 );
+        iRepr = iPrev = Vec_IntEntry( vClass, 0 );
+        Vec_IntForEachEntryStart( vClass, iNode, k, 1 )
+        {
+            Gia_ObjSetRepr( pFinal, iNode, iRepr );
+            assert( iPrev < iNode );
+            iPrev = iNode;
+        }
+    }
+    Vec_IntFree( vClass );
+    pFinal->pNexts = Gia_ManDeriveNexts( pFinal );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes pointers to the unmarked nodes..]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManEquivRemapDfs( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Vec_Int_t * vClass;
+    int i, k, iNode, iRepr, iPrev;
+    pNew = Gia_ManDupDfs( p );
+    // start representatives
+    pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pNew) );
+    for ( i = 0; i < Gia_ManObjNum(pNew); i++ )
+        Gia_ObjSetRepr( pNew, i, GIA_VOID );
+    // iterate over constant candidates
+    Gia_ManForEachConst( p, i )
+        Gia_ObjSetRepr( pNew, Abc_Lit2Var(Gia_ManObj(p, i)->Value), 0 );
+    // iterate over class candidates
+    vClass = Vec_IntAlloc( 100 );
+    Gia_ManForEachClass( p, i )
+    {
+        Vec_IntClear( vClass );
+        Gia_ClassForEachObj( p, i, k )
+            Vec_IntPushUnique( vClass, Abc_Lit2Var(Gia_ManObj(p, k)->Value) );
+        assert( Vec_IntSize( vClass ) > 1 );
+        Vec_IntSort( vClass, 0 );
+        iRepr = iPrev = Vec_IntEntry( vClass, 0 );
+        Vec_IntForEachEntryStart( vClass, iNode, k, 1 )
+        {
+            Gia_ObjSetRepr( pNew, iNode, iRepr );
+            assert( iPrev < iNode );
+            iPrev = iNode;
+        }
+    }
+    Vec_IntFree( vClass );
+    pNew->pNexts = Gia_ManDeriveNexts( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces AIG while remapping equivalence classes.]
+
+  Description [Drops the pairs of outputs if they are proved equivalent.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManEquivReduceAndRemap( Gia_Man_t * p, int fSeq, int fMiterPairs )
+{
+    Gia_Man_t * pNew, * pFinal;
+    pNew = Gia_ManEquivReduce( p, 0, 0, 0, 0 );
+    if ( pNew == NULL )
+        return NULL;
+    if ( fMiterPairs )
+        Gia_ManEquivFixOutputPairs( pNew );
+    if ( fSeq )
+        Gia_ManSeqMarkUsed( pNew );
+    else
+        Gia_ManCombMarkUsed( pNew );
+    Gia_ManEquivUpdatePointers( p, pNew );
+    pFinal = Gia_ManDupMarked( pNew );
+    Gia_ManEquivDeriveReprs( p, pNew, pFinal );
+    Gia_ManStop( pNew );
+    pFinal = Gia_ManEquivRemapDfs( pNew = pFinal );
+    Gia_ManStop( pNew );
+    return pFinal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks CIs/COs/ANDs unreachable from POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManEquivSetColor_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int fOdds )
+{
+    if ( Gia_ObjVisitColor( p, Gia_ObjId(p,pObj), fOdds ) )
+        return 0;
+    if ( Gia_ObjIsRo(p, pObj) )
+        return 1 + Gia_ManEquivSetColor_rec( p, Gia_ObjFanin0(Gia_ObjRoToRi(p, pObj)), fOdds );
+    assert( Gia_ObjIsAnd(pObj) );
+    return 1 + Gia_ManEquivSetColor_rec( p, Gia_ObjFanin0(pObj), fOdds )
+             + Gia_ManEquivSetColor_rec( p, Gia_ObjFanin1(pObj), fOdds );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks CIs/COs/ANDs unreachable from POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManEquivSetColors( Gia_Man_t * p, int fVerbose )
+{
+    Gia_Obj_t * pObj;
+    int i, nNodes[2], nDiffs[2];
+    assert( (Gia_ManPoNum(p) & 1) == 0 );
+    Gia_ObjSetColors( p, 0 );
+    Gia_ManForEachPi( p, pObj, i )
+        Gia_ObjSetColors( p, Gia_ObjId(p,pObj) );
+    nNodes[0] = nNodes[1] = Gia_ManPiNum(p);
+    Gia_ManForEachPo( p, pObj, i )
+        nNodes[i&1] += Gia_ManEquivSetColor_rec( p, Gia_ObjFanin0(pObj), i&1 );
+//    Gia_ManForEachObj( p, pObj, i )
+//        if ( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) )
+//            assert( Gia_ObjColors(p, i) );
+    nDiffs[0] = Gia_ManCandNum(p) - nNodes[0];
+    nDiffs[1] = Gia_ManCandNum(p) - nNodes[1];
+    if ( fVerbose )
+    {
+        Abc_Print( 1, "CI+AND = %7d  A = %7d  B = %7d  Ad = %7d  Bd = %7d  AB = %7d.\n",
+            Gia_ManCandNum(p), nNodes[0], nNodes[1], nDiffs[0], nDiffs[1],
+            Gia_ManCandNum(p) - nDiffs[0] - nDiffs[1] );
+    }
+    return (nDiffs[0] + nDiffs[1]) / 2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSpecBuild( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vXorLits, int fDualOut, int fSpeculate, Vec_Int_t * vTrace, Vec_Int_t * vGuide, Vec_Int_t * vMap )
+{
+    Gia_Obj_t * pRepr;
+    unsigned iLitNew;
+    pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) );
+    if ( pRepr == NULL )
+        return;
+//    if ( fDualOut && !Gia_ObjDiffColors( p, Gia_ObjId(p, pObj), Gia_ObjId(p, pRepr) ) )
+    if ( fDualOut && !Gia_ObjDiffColors2( p, Gia_ObjId(p, pObj), Gia_ObjId(p, pRepr) ) )
+        return;
+    iLitNew = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) );
+    if ( pObj->Value != iLitNew && !Gia_ObjProved(p, Gia_ObjId(p,pObj)) )
+    {
+        if ( vTrace )
+            Vec_IntPush( vTrace, 1 );
+        if ( vGuide == NULL || Vec_IntEntry( vGuide, Vec_IntSize(vTrace)-1 ) )
+        {
+            if ( vMap )  
+                Vec_IntPush( vMap, Gia_ObjId(p, pObj) );
+            Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, pObj->Value, iLitNew) );
+        }
+    }
+    else
+    {
+        if ( vTrace )
+            Vec_IntPush( vTrace, 0 );
+    }
+    if ( fSpeculate )
+        pObj->Value = iLitNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vXorLits, int fDualOut, int fSpeculate, Vec_Int_t * vTrace, Vec_Int_t * vGuide, Vec_Int_t * vMap )
+{
+    if ( ~pObj->Value )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), vXorLits, fDualOut, fSpeculate, vTrace, vGuide, vMap );
+    Gia_ManSpecReduce_rec( pNew, p, Gia_ObjFanin1(pObj), vXorLits, fDualOut, fSpeculate, vTrace, vGuide, vMap );
+    pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManSpecBuild( pNew, p, pObj, vXorLits, fDualOut, fSpeculate, vTrace, vGuide, vMap );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces AIG using equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManSpecReduceTrace( Gia_Man_t * p, Vec_Int_t * vTrace, Vec_Int_t * vMap )
+{
+    Vec_Int_t * vXorLits;
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, iLitNew;
+    if ( !p->pReprs )
+    {
+        Abc_Print( 1, "Gia_ManSpecReduce(): Equivalence classes are not available.\n" );
+        return NULL;
+    }
+    Vec_IntClear( vTrace );
+    vXorLits = Vec_IntAlloc( 1000 );
+    Gia_ManSetPhase( p );
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManForEachRo( p, pObj, i )
+        Gia_ManSpecBuild( pNew, p, pObj, vXorLits, 0, 1, vTrace, NULL, vMap );
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), vXorLits, 0, 1, vTrace, NULL, vMap );
+    Gia_ManForEachPo( p, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Vec_IntForEachEntry( vXorLits, iLitNew, i )
+        Gia_ManAppendCo( pNew, iLitNew );
+    if ( Vec_IntSize(vXorLits) == 0 )
+    {
+        Abc_Print( 1, "Speculatively reduced model has no primary outputs.\n" );
+        Gia_ManAppendCo( pNew, 0 );
+    }
+    Gia_ManForEachRi( p, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManHashStop( pNew );
+    Vec_IntFree( vXorLits );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces AIG using equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManSpecReduce( Gia_Man_t * p, int fDualOut, int fSynthesis, int fSpeculate, int fSkipSome, int fVerbose )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vXorLits;
+    int i, iLitNew;
+    Vec_Int_t * vTrace = NULL, * vGuide = NULL;
+    if ( !p->pReprs )
+    {
+        Abc_Print( 1, "Gia_ManSpecReduce(): Equivalence classes are not available.\n" );
+        return NULL;
+    }
+    if ( fDualOut && (Gia_ManPoNum(p) & 1) )
+    {
+        Abc_Print( 1, "Gia_ManSpecReduce(): Dual-output miter should have even number of POs.\n" );
+        return NULL;
+    }
+    if ( fSkipSome )
+    {
+        vGuide = Vec_IntAlloc( 100 );
+        pTemp  = Gia_ManSpecReduceTrace( p, vGuide, NULL );
+        Gia_ManStop( pTemp );
+        assert( Vec_IntSize(vGuide) == Gia_ManEquivCountLitsAll(p) );
+        vTrace = Vec_IntAlloc( 100 );
+    }
+    vXorLits = Vec_IntAlloc( 1000 );
+    Gia_ManSetPhase( p );
+    Gia_ManFillValue( p );
+    if ( fDualOut )
+        Gia_ManEquivSetColors( p, fVerbose );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManForEachRo( p, pObj, i )
+        Gia_ManSpecBuild( pNew, p, pObj, vXorLits, fDualOut, fSpeculate, vTrace, vGuide, NULL );
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), vXorLits, fDualOut, fSpeculate, vTrace, vGuide, NULL );
+    if ( !fSynthesis )
+    {
+        Gia_ManForEachPo( p, pObj, i )
+            Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+    Vec_IntForEachEntry( vXorLits, iLitNew, i )
+        Gia_ManAppendCo( pNew, iLitNew );
+    if ( Vec_IntSize(vXorLits) == 0 )
+    {
+        Abc_Print( 1, "Speculatively reduced model has no primary outputs.\n" );
+        Gia_ManAppendCo( pNew, 0 );
+    }
+    Gia_ManForEachRi( p, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManHashStop( pNew );
+    Vec_IntFree( vXorLits );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+
+    // update using trace
+    if ( fSkipSome )
+    {
+        // count the number of non-zero entries
+        int iLit, nAddPos = 0;
+        Vec_IntForEachEntry( vGuide, iLit, i )
+            if ( iLit )
+                nAddPos++;
+        if ( nAddPos )
+            assert( Gia_ManPoNum(pNew) == Gia_ManPoNum(p) + nAddPos );
+    }
+    Vec_IntFreeP( &vTrace );
+    Vec_IntFreeP( &vGuide );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG in the DFS order.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSpecBuildInit( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vXorLits, int f, int fDualOut )
+{
+    Gia_Obj_t * pRepr;
+    int iLitNew;
+    pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) );
+    if ( pRepr == NULL )
+        return;
+//    if ( fDualOut && !Gia_ObjDiffColors( p, Gia_ObjId(p, pObj), Gia_ObjId(p, pRepr) ) )
+    if ( fDualOut && !Gia_ObjDiffColors2( p, Gia_ObjId(p, pObj), Gia_ObjId(p, pRepr) ) )
+        return;
+    iLitNew = Abc_LitNotCond( Gia_ObjCopyF(p, f, pRepr), Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) );
+    if ( Gia_ObjCopyF(p, f, pObj) != iLitNew && !Gia_ObjProved(p, Gia_ObjId(p,pObj)) )
+        Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, Gia_ObjCopyF(p, f, pObj), iLitNew) );
+    Gia_ObjSetCopyF( p, f, pObj, iLitNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSpecReduceInit_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vXorLits, int f, int fDualOut )
+{
+    if ( ~Gia_ObjCopyF(p, f, pObj) )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManSpecReduceInit_rec( pNew, p, Gia_ObjFanin0(pObj), vXorLits, f, fDualOut );
+    Gia_ManSpecReduceInit_rec( pNew, p, Gia_ObjFanin1(pObj), vXorLits, f, fDualOut );
+    Gia_ObjSetCopyF( p, f, pObj, Gia_ManHashAnd(pNew, Gia_ObjFanin0CopyF(p, f, pObj), Gia_ObjFanin1CopyF(p, f, pObj)) );
+    Gia_ManSpecBuildInit( pNew, p, pObj, vXorLits, f, fDualOut );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates initialized SRM with the given number of frames.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManSpecReduceInit( Gia_Man_t * p, Abc_Cex_t * pInit, int nFrames, int fDualOut )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pObjRi, * pObjRo;
+    Vec_Int_t * vXorLits;
+    int f, i, iLitNew;
+    if ( !p->pReprs )
+    {
+        Abc_Print( 1, "Gia_ManSpecReduceInit(): Equivalence classes are not available.\n" );
+        return NULL;
+    }
+    if ( Gia_ManRegNum(p) == 0 )
+    {
+        Abc_Print( 1, "Gia_ManSpecReduceInit(): Circuit is not sequential.\n" );
+        return NULL;
+    }
+    if ( Gia_ManRegNum(p) != pInit->nRegs )
+    {
+        Abc_Print( 1, "Gia_ManSpecReduceInit(): Mismatch in the number of registers.\n" );
+        return NULL;
+    }
+    if ( fDualOut && (Gia_ManPoNum(p) & 1) )
+    {
+        Abc_Print( 1, "Gia_ManSpecReduceInit(): Dual-output miter should have even number of POs.\n" );
+        return NULL;
+    }
+
+/*
+    if ( !Gia_ManCheckTopoOrder( p ) )
+    {
+        Abc_Print( 1, "Gia_ManSpecReduceInit(): AIG is not in a correct topological order.\n" );
+        return NULL;
+    }
+*/
+    assert( pInit->nRegs == Gia_ManRegNum(p) && pInit->nPis == 0 );
+    p->pCopies = ABC_FALLOC( int, nFrames * Gia_ManObjNum(p) );
+    vXorLits = Vec_IntAlloc( 1000 );
+    Gia_ManSetPhase( p );
+    if ( fDualOut )
+        Gia_ManEquivSetColors( p, 0 );
+    pNew = Gia_ManStart( nFrames * Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachRo( p, pObj, i )
+        Gia_ObjSetCopyF( p, 0, pObj, Abc_InfoHasBit(pInit->pData, i) );
+    for ( f = 0; f < nFrames; f++ )
+    {
+        Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 );
+        Gia_ManForEachPi( p, pObj, i )
+            Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) );
+        Gia_ManForEachRo( p, pObj, i )
+            Gia_ManSpecBuildInit( pNew, p, pObj, vXorLits, f, fDualOut );
+        Gia_ManForEachCo( p, pObj, i )
+        {
+            Gia_ManSpecReduceInit_rec( pNew, p, Gia_ObjFanin0(pObj), vXorLits, f, fDualOut );
+            Gia_ObjSetCopyF( p, f, pObj, Gia_ObjFanin0CopyF(p, f, pObj) );
+        }
+        if ( f == nFrames - 1 )
+            break;
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, i )
+            Gia_ObjSetCopyF( p, f+1, pObjRo, Gia_ObjCopyF(p, f, pObjRi) );
+    }
+    Vec_IntForEachEntry( vXorLits, iLitNew, i )
+        Gia_ManAppendCo( pNew, iLitNew );
+    if ( Vec_IntSize(vXorLits) == 0 )
+    {
+//        Abc_Print( 1, "Speculatively reduced model has no primary outputs.\n" );
+        Gia_ManAppendCo( pNew, 0 );
+    }
+    ABC_FREE( p->pCopies );
+    Vec_IntFree( vXorLits );
+    Gia_ManHashStop( pNew );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates initialized SRM with the given number of frames.]
+
+  Description [Uses as many frames as needed to create the number of 
+  output not less than the number of equivalence literals.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManSpecReduceInitFrames( Gia_Man_t * p, Abc_Cex_t * pInit, int nFramesMax, int * pnFrames, int fDualOut, int nMinOutputs )
+{
+    Gia_Man_t * pFrames;
+    int f, nLits;
+    nLits = Gia_ManEquivCountLits( p );
+    for ( f = 1; ; f++ )
+    {
+        pFrames = Gia_ManSpecReduceInit( p, pInit, f, fDualOut );
+        if ( (nMinOutputs == 0 && Gia_ManPoNum(pFrames) >= nLits/2+1) ||
+             (nMinOutputs != 0 && Gia_ManPoNum(pFrames) >= nMinOutputs) )
+            break;
+        if ( f == nFramesMax )
+            break;
+        if ( Gia_ManAndNum(pFrames) > 500000 )
+        {
+            Gia_ManStop( pFrames );
+            return NULL;
+        }
+        Gia_ManStop( pFrames );
+        pFrames = NULL;
+    }
+    if ( f == nFramesMax )
+        Abc_Print( 1, "Stopped unrolling after %d frames.\n", nFramesMax );
+    if ( pnFrames )
+        *pnFrames = f;
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms equiv classes by removing the AB nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManEquivTransform( Gia_Man_t * p, int fVerbose )
+{
+    extern void Cec_ManSimClassCreate( Gia_Man_t * p, Vec_Int_t * vClass );
+    Vec_Int_t * vClass, * vClassNew;
+    int iRepr, iNode, Ent, k;
+    int nRemovedLits = 0, nRemovedClas = 0;
+    int nTotalLits = 0, nTotalClas = 0;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( p->pReprs && p->pNexts );
+    vClass = Vec_IntAlloc( 100 );
+    vClassNew = Vec_IntAlloc( 100 );
+    Gia_ManForEachObj( p, pObj, i )
+        if ( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) )
+            assert( Gia_ObjColors(p, i) );
+    Gia_ManForEachClassReverse( p, iRepr )
+    {
+        nTotalClas++;
+        Vec_IntClear( vClass );
+        Vec_IntClear( vClassNew );
+        Gia_ClassForEachObj( p, iRepr, iNode )
+        {
+            nTotalLits++;
+            Vec_IntPush( vClass, iNode );
+            assert( Gia_ObjColors(p, iNode) );
+            if ( Gia_ObjColors(p, iNode) != 3 )
+                Vec_IntPush( vClassNew, iNode );
+            else
+                nRemovedLits++;
+        }
+        Vec_IntForEachEntry( vClass, Ent, k )
+        {
+            p->pReprs[Ent].fFailed = p->pReprs[Ent].fProved = 0;
+            p->pReprs[Ent].iRepr = GIA_VOID;
+            p->pNexts[Ent] = 0;
+        }
+        if ( Vec_IntSize(vClassNew) < 2 )
+        {
+            nRemovedClas++;
+            continue;
+        }
+        Cec_ManSimClassCreate( p, vClassNew );
+    }
+    Vec_IntFree( vClass );
+    Vec_IntFree( vClassNew );
+    if ( fVerbose )
+    Abc_Print( 1, "Removed classes = %6d (out of %6d). Removed literals = %6d (out of %6d).\n",
+        nRemovedClas, nTotalClas, nRemovedLits, nTotalLits );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks proved equivalences.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManEquivMark( Gia_Man_t * p, char * pFileName, int fSkipSome, int fVerbose )
+{
+    Gia_Man_t * pMiter, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, iLit, nAddPos, nLits = 0;
+    int nLitsAll, Counter = 0;
+    nLitsAll = Gia_ManEquivCountLitsAll( p );
+    if ( nLitsAll == 0 )
+    {
+        Abc_Print( 1, "Gia_ManEquivMark(): Current AIG does not have equivalences.\n" );
+        return;
+    }
+    // read AIGER file
+    pMiter = Gia_AigerRead( pFileName, 0, 0 );
+    if ( pMiter == NULL )
+    {
+        Abc_Print( 1, "Gia_ManEquivMark(): Input file %s could not be read.\n", pFileName );
+        return;
+    }
+    if ( fSkipSome )
+    {
+        Vec_Int_t * vTrace = Vec_IntAlloc( 100 );
+        pTemp = Gia_ManSpecReduceTrace( p, vTrace, NULL );
+        Gia_ManStop( pTemp );
+        assert( Vec_IntSize(vTrace) == nLitsAll );
+        // count the number of non-zero entries
+        nAddPos = 0;
+        Vec_IntForEachEntry( vTrace, iLit, i )
+            if ( iLit )
+                nAddPos++;
+        // check the number
+        if ( Gia_ManPoNum(pMiter) != Gia_ManPoNum(p) + nAddPos )
+        {
+            Abc_Print( 1, "Gia_ManEquivMark(): The number of POs is not correct: MiterPONum(%d) != AIGPONum(%d) + AIGFilteredEquivNum(%d).\n",
+                Gia_ManPoNum(pMiter), Gia_ManPoNum(p), nAddPos );
+            Gia_ManStop( pMiter );
+            Vec_IntFreeP( &vTrace );
+            return;
+        }
+        // mark corresponding POs as solved
+        nLits = iLit = Counter = 0;
+        for ( i = 0; i < Gia_ManObjNum(p); i++ )
+        {
+            if ( Gia_ObjRepr(p, i) == GIA_VOID )
+                continue;
+            if ( Vec_IntEntry( vTrace, nLits++ ) == 0 )
+                continue;
+            pObj = Gia_ManPo( pMiter, Gia_ManPoNum(p) + iLit++ );
+            if ( Gia_ObjFaninLit0p(pMiter, pObj) == 0 ) // const 0 - proven
+            {
+                Gia_ObjSetProved(p, i);
+                Counter++;
+            }
+        }
+        assert( nLits == nLitsAll );
+        assert( iLit == nAddPos );
+        Vec_IntFreeP( &vTrace );
+    }
+    else
+    {
+        if ( Gia_ManPoNum(pMiter) != Gia_ManPoNum(p) + nLitsAll )
+        {
+            Abc_Print( 1, "Gia_ManEquivMark(): The number of POs is not correct: MiterPONum(%d) != AIGPONum(%d) + AIGEquivNum(%d).\n",
+                Gia_ManPoNum(pMiter), Gia_ManPoNum(p), nLitsAll );
+            Gia_ManStop( pMiter );
+            return;
+        }
+        // mark corresponding POs as solved
+        nLits = 0;
+        for ( i = 0; i < Gia_ManObjNum(p); i++ )
+        {
+            if ( Gia_ObjRepr(p, i) == GIA_VOID )
+                continue;
+            pObj = Gia_ManPo( pMiter, Gia_ManPoNum(p) + nLits++ );
+            if ( Gia_ObjFaninLit0p(pMiter, pObj) == 0 ) // const 0 - proven
+            {
+                Gia_ObjSetProved(p, i);
+                Counter++;
+            }
+        }
+        assert( nLits == nLitsAll );
+    }
+    if ( fVerbose )
+        Abc_Print( 1, "Set %d equivalences as proved.\n", Counter );
+    Gia_ManStop( pMiter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms equiv classes by filtering those that correspond to disproved outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManEquivFilter( Gia_Man_t * p, Vec_Int_t * vPoIds, int fVerbose )
+{
+    Gia_Man_t * pSrm;
+    Vec_Int_t * vTrace, * vMap;
+    int i, iObjId, Entry, Prev = -1;
+    // check if there are equivalences
+    if ( p->pReprs == NULL || p->pNexts == NULL )
+    {
+        Abc_Print( 1, "Gia_ManEquivFilter(): Equivalence classes are not defined.\n" );
+        return;
+    }
+    // check if PO indexes are available
+    if ( vPoIds == NULL )
+    {
+        Abc_Print( 1, "Gia_ManEquivFilter(): Array of disproved POs is not available.\n" );
+        return;
+    }
+    if ( Vec_IntSize(vPoIds) == 0 )
+        return;
+    // create SRM with mapping into POs
+    vMap = Vec_IntAlloc( 1000 );
+    vTrace = Vec_IntAlloc( 1000 );
+    pSrm = Gia_ManSpecReduceTrace( p, vTrace, vMap );
+    Vec_IntFree( vTrace );
+    // the resulting array (vMap) maps PO indexes of the SRM into object IDs
+    assert( Gia_ManPoNum(pSrm) == Gia_ManPoNum(p) + Vec_IntSize(vMap) );
+    Gia_ManStop( pSrm );
+    if ( fVerbose )
+        printf( "Design POs = %d. SRM POs = %d. Spec POs = %d. Disproved POs = %d.\n", 
+            Gia_ManPoNum(p), Gia_ManPoNum(p) + Vec_IntSize(vMap), Vec_IntSize(vMap), Vec_IntSize(vPoIds) );
+    // check if disproved POs satisfy the range
+    Vec_IntSort( vPoIds, 0 );
+    Vec_IntForEachEntry( vPoIds, Entry, i )
+    {
+        if ( Entry < 0 || Entry >= Gia_ManPoNum(p) + Vec_IntSize(vMap) )
+        {
+            Abc_Print( 1, "Gia_ManEquivFilter(): Array of disproved POs contains PO index (%d),\n", Entry );
+            Abc_Print( 1, "which does not fit into the range of available PO indexes of the SRM: [%d; %d].\n", 0, Gia_ManPoNum(p) + Vec_IntSize(vMap)-1 );
+            Vec_IntFree( vMap );
+            return;
+        }
+        if ( Entry < Gia_ManPoNum(p) )
+            Abc_Print( 0, "Gia_ManEquivFilter(): One of the original POs (%d) have failed.\n", Entry );
+        if ( Prev == Entry )
+        {
+            Abc_Print( 1, "Gia_ManEquivFilter(): Array of disproved POs contains at least one duplicate entry (%d),\n", Entry );
+            Vec_IntFree( vMap );
+            return;
+        }
+        Prev = Entry;
+    }
+    // perform the reduction of the equivalence classes
+    Vec_IntForEachEntry( vPoIds, Entry, i )
+    {
+        if ( Entry < Gia_ManPoNum(p) )
+            continue;
+        iObjId = Vec_IntEntry( vMap, Entry - Gia_ManPoNum(p) );
+        Gia_ObjUnsetRepr( p, iObjId );
+//        Gia_ObjSetNext( p, iObjId, 0 );
+    }
+    Vec_IntFree( vMap );
+    ABC_FREE( p->pNexts );
+    p->pNexts = Gia_ManDeriveNexts( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms equiv classes by filtering those that correspond to disproved outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManEquivFilterTest( Gia_Man_t * p )
+{
+    Vec_Int_t * vPoIds;
+    int i;
+    vPoIds = Vec_IntAlloc( 1000 );
+    for ( i = 0; i < 10; i++ )
+    {
+        Vec_IntPush( vPoIds, Gia_ManPoNum(p) + 2 * i + 2 );
+        printf( "%d ", Gia_ManPoNum(p) + 2*i + 2 );
+    }
+    printf( "\n" );
+    Gia_ManEquivFilter( p, vPoIds, 1 );
+    Vec_IntFree( vPoIds );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms equiv classes by setting a good representative.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManEquivImprove( Gia_Man_t * p )
+{
+    Vec_Int_t * vClass;
+    int i, k, iNode, iRepr;
+    int iReprBest, iLevelBest, iLevelCur, iMffcBest, iMffcCur;
+    assert( p->pReprs != NULL && p->pNexts != NULL );
+    Gia_ManLevelNum( p );
+    Gia_ManCreateRefs( p );
+    // iterate over class candidates
+    vClass = Vec_IntAlloc( 100 );
+    Gia_ManForEachClass( p, i )
+    {
+        Vec_IntClear( vClass );
+        iReprBest = -1;
+        iLevelBest = iMffcBest = ABC_INFINITY;
+        Gia_ClassForEachObj( p, i, k )
+        {
+            iLevelCur = Gia_ObjLevel( p,Gia_ManObj(p, k) );
+            iMffcCur  = Gia_NodeMffcSize( p, Gia_ManObj(p, k) );
+            if ( iLevelBest > iLevelCur || (iLevelBest == iLevelCur && iMffcBest > iMffcCur) )
+            {
+                iReprBest  = k;
+                iLevelBest = iLevelCur;
+                iMffcBest  = iMffcCur;
+            }
+            Vec_IntPush( vClass, k );
+        }
+        assert( Vec_IntSize( vClass ) > 1 );
+        assert( iReprBest > 0 );
+        if ( i == iReprBest )
+            continue;
+/*
+        Abc_Print( 1, "Repr/Best = %6d/%6d. Lev = %3d/%3d. Mffc = %3d/%3d.\n", 
+            i, iReprBest, Gia_ObjLevel( p,Gia_ManObj(p, i) ), Gia_ObjLevel( p,Gia_ManObj(p, iReprBest) ),
+            Gia_NodeMffcSize( p, Gia_ManObj(p, i) ), Gia_NodeMffcSize( p, Gia_ManObj(p, iReprBest) ) );
+*/
+        iRepr = iReprBest;
+        Gia_ObjSetRepr( p, iRepr, GIA_VOID );
+        Gia_ObjSetProved( p, i );
+        Gia_ObjUnsetProved( p, iRepr );
+        Vec_IntForEachEntry( vClass, iNode, k )
+            if ( iNode != iRepr )
+                Gia_ObjSetRepr( p, iNode, iRepr );
+    }
+    Vec_IntFree( vClass );
+    ABC_FREE( p->pNexts );
+//    p->pNexts = Gia_ManDeriveNexts( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pOld is in the TFI of pNode.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ObjCheckTfi_rec( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode, Vec_Ptr_t * vVisited )
+{
+    // check the trivial cases
+    if ( pNode == NULL )
+        return 0;
+    if ( Gia_ObjIsCi(pNode) )
+        return 0;
+//    if ( pNode->Id < pOld->Id ) // cannot use because of choices of pNode
+//        return 0;
+    if ( pNode == pOld )
+        return 1;
+    // skip the visited node
+    if ( pNode->fMark0 )
+        return 0;
+    pNode->fMark0 = 1;
+    Vec_PtrPush( vVisited, pNode );
+    // check the children
+    if ( Gia_ObjCheckTfi_rec( p, pOld, Gia_ObjFanin0(pNode), vVisited ) )
+        return 1;
+    if ( Gia_ObjCheckTfi_rec( p, pOld, Gia_ObjFanin1(pNode), vVisited ) )
+        return 1;
+    // check equivalent nodes
+    return Gia_ObjCheckTfi_rec( p, pOld, Gia_ObjNextObj(p, Gia_ObjId(p, pNode)), vVisited );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pOld is in the TFI of pNode.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ObjCheckTfi( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode )
+{
+    Vec_Ptr_t * vVisited;
+    Gia_Obj_t * pObj;
+    int RetValue, i;
+    assert( !Gia_IsComplement(pOld) );
+    assert( !Gia_IsComplement(pNode) );
+    vVisited = Vec_PtrAlloc( 100 );
+    RetValue = Gia_ObjCheckTfi_rec( p, pOld, pNode, vVisited );
+    Vec_PtrForEachEntry( Gia_Obj_t *, vVisited, pObj, i )
+        pObj->fMark0 = 0;
+    Vec_PtrFree( vVisited );
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the next entry while making choices.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManAddNextEntry_rec( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode )
+{
+    if ( Gia_ObjNext(p, Gia_ObjId(p, pOld)) == 0 )
+    {
+        Gia_ObjSetNext( p, Gia_ObjId(p, pOld), Gia_ObjId(p, pNode) );
+        return;
+    }
+    Gia_ManAddNextEntry_rec( p, Gia_ObjNextObj(p, Gia_ObjId(p, pOld)), pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG in the DFS order.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManEquivToChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    Gia_Obj_t * pRepr, * pReprNew, * pObjNew;
+    if ( ~pObj->Value )
+        return;
+    if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+    {
+        if ( Gia_ObjIsConst0(pRepr) )
+        {
+            pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) );
+            return;
+        }
+        Gia_ManEquivToChoices_rec( pNew, p, pRepr );
+        assert( Gia_ObjIsAnd(pObj) );
+        Gia_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) );
+        Gia_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin1(pObj) );
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        if ( Abc_LitRegular(pObj->Value) == Abc_LitRegular(pRepr->Value) )
+        {
+            assert( (int)pObj->Value == Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ) );
+            return;
+        }
+        if ( pRepr->Value > pObj->Value ) // should never happen with high resource limit
+            return;
+        assert( pRepr->Value < pObj->Value );
+        pReprNew = Gia_ManObj( pNew, Abc_Lit2Var(pRepr->Value) );
+        pObjNew  = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) );
+        if ( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) )
+        {
+//            assert( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) == pReprNew );
+            if ( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) != pReprNew )
+                return;
+            pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) );
+            return;
+        }
+        if ( !Gia_ObjCheckTfi( pNew, pReprNew, pObjNew ) )
+        {
+            assert( Gia_ObjNext(pNew, Gia_ObjId(pNew, pObjNew)) == 0 );
+            Gia_ObjSetRepr( pNew, Gia_ObjId(pNew, pObjNew), Gia_ObjId(pNew, pReprNew) );
+            Gia_ManAddNextEntry_rec( pNew, pReprNew, pObjNew );
+        }
+        pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    Gia_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin1(pObj) );
+    pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes choices, which contain fanouts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManRemoveBadChoices( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, iObj, iPrev, Counter = 0;
+    // mark nodes with fanout
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        pObj->fMark0 = 0;
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            Gia_ObjFanin0(pObj)->fMark0 = 1;
+            Gia_ObjFanin1(pObj)->fMark0 = 1;
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+            Gia_ObjFanin0(pObj)->fMark0 = 1;
+    }
+    // go through the classes and remove 
+    Gia_ManForEachClass( p, i )
+    {
+        for ( iPrev = i, iObj = Gia_ObjNext(p, i); iObj; iObj = Gia_ObjNext(p, iPrev) )
+        {
+            if ( !Gia_ManObj(p, iObj)->fMark0 )
+            {
+                iPrev = iObj;
+                continue;
+            }
+            Gia_ObjSetRepr( p, iObj, GIA_VOID );
+            Gia_ObjSetNext( p, iPrev, Gia_ObjNext(p, iObj) );
+            Gia_ObjSetNext( p, iObj, 0 );
+            Counter++;
+        }
+    }
+    // remove the marks
+    Gia_ManCleanMark0( p );
+//    Abc_Print( 1, "Removed %d bad choices.\n", Counter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces AIG using equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManEquivToChoices( Gia_Man_t * p, int nSnapshots )
+{
+    Vec_Int_t * vNodes;
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pRepr;
+    int i;
+//Gia_ManEquivPrintClasses( p, 0, 0 );
+    assert( (Gia_ManCoNum(p) % nSnapshots) == 0 );
+    Gia_ManSetPhase( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) );
+    pNew->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    for ( i = 0; i < Gia_ManObjNum(p); i++ )
+        Gia_ObjSetRepr( pNew, i, GIA_VOID );
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManForEachRo( p, pObj, i )
+        if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+        {
+            assert( Gia_ObjIsConst0(pRepr) || Gia_ObjIsRo(p, pRepr) );
+            pObj->Value = pRepr->Value;
+        }
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    vNodes = Gia_ManGetDangling( p );
+    Gia_ManForEachObjVec( vNodes, p, pObj, i )
+        Gia_ManEquivToChoices_rec( pNew, p, pObj );
+    Vec_IntFree( vNodes );
+    Gia_ManForEachCo( p, pObj, i )
+        if ( i % nSnapshots == 0 )
+            Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    Gia_ManRemoveBadChoices( pNew );
+//Gia_ManEquivPrintClasses( pNew, 0, 0 );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+//Gia_ManEquivPrintClasses( pNew, 0, 0 );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of choice nodes]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCountChoiceNodes( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, Counter = 0;
+    if ( p->pReprs == NULL || p->pNexts == NULL )
+        return 0;
+    Gia_ManForEachObj( p, pObj, i )
+        Counter += Gia_ObjIsHead( p, i );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of choices]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCountChoices( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, Counter = 0;
+    if ( p->pReprs == NULL || p->pNexts == NULL )
+        return 0;
+    Gia_ManForEachObj( p, pObj, i )
+        Counter += (int)(Gia_ObjNext( p, i ) > 0);
+    return Counter;
+}
+
+ABC_NAMESPACE_IMPL_END
+
+#include "aig/aig/aig.h"
+#include "aig/saig/saig.h"
+#include "proof/cec/cec.h"
+#include "giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if AIG has dangling nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManHasNoEquivs( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    if ( p->pReprs == NULL )
+        return 1;
+    Gia_ManForEachObj( p, pObj, i )
+        if ( Gia_ObjReprObj(p, i) != NULL )
+            break;
+    return i == Gia_ManObjNum(p);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements iteration during speculation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_CommandSpecI( Gia_Man_t * pGia, int nFramesInit, int nBTLimitInit, int fStart, int fCheckMiter, int fVerbose )
+{
+//    extern int Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig );
+    Aig_Man_t * pTemp;
+    Gia_Man_t * pSrm, * pReduce, * pAux;
+    int nIter, nStart = 0;
+    if ( pGia->pReprs == NULL || pGia->pNexts == NULL )
+    {
+        Abc_Print( 1, "Gia_CommandSpecI(): Equivalence classes are not defined.\n" );
+        return 0;
+    }
+    // (spech)*  where spech = &srm; restore save3; bmc2 -F 100 -C 25000; &resim
+    Gia_ManCleanMark0( pGia );
+    Gia_ManPrintStats( pGia, NULL );
+    for ( nIter = 0; ; nIter++ )
+    {
+        if ( Gia_ManHasNoEquivs(pGia) )
+        {
+            Abc_Print( 1, "Gia_CommandSpecI: No equivalences left.\n" );
+            break;
+        }
+        Abc_Print( 1, "ITER %3d : ", nIter );
+//      if ( fVerbose )
+//            Abc_Print( 1, "Starting BMC from frame %d.\n", nStart );
+//      if ( fVerbose )
+//            Gia_ManPrintStats( pGia, 0 );
+            Gia_ManPrintStatsClasses( pGia );
+        // perform speculative reduction
+//        if ( Gia_ManPoNum(pSrm) <= Gia_ManPoNum(pGia) )
+        if ( !Cec_ManCheckNonTrivialCands(pGia) )
+        {
+            Abc_Print( 1, "Gia_CommandSpecI: There are only trivial equiv candidates left (PO drivers). Quitting.\n" );
+            break;
+        }
+        pSrm = Gia_ManSpecReduce( pGia, 0, 0, 1, 0, 0 );
+        // bmc2 -F 100 -C 25000
+        {
+            Abc_Cex_t * pCex;
+            int nFrames     = nFramesInit; // different from default
+            int nNodeDelta  = 2000;
+            int nBTLimit    = nBTLimitInit; // different from default
+            int nBTLimitAll = 2000000;
+            pTemp = Gia_ManToAig( pSrm, 0 );
+//            Aig_ManPrintStats( pTemp );
+            Gia_ManStop( pSrm );
+            Saig_BmcPerform( pTemp, nStart, nFrames, nNodeDelta, 0, nBTLimit, nBTLimitAll, fVerbose, 0, NULL, 0 );
+            pCex = pTemp->pSeqModel; pTemp->pSeqModel = NULL;
+            Aig_ManStop( pTemp );
+            if ( pCex == NULL )
+            {
+                Abc_Print( 1, "Gia_CommandSpecI(): Internal BMC could not find a counter-example.\n" );
+                break;
+            }
+            if ( fStart )
+                nStart = pCex->iFrame;
+            // perform simulation
+            {
+                Cec_ParSim_t Pars, * pPars = &Pars;
+                Cec_ManSimSetDefaultParams( pPars );
+                pPars->fCheckMiter = fCheckMiter;
+                if ( Cec_ManSeqResimulateCounter( pGia, pPars, pCex ) )
+                {
+                    ABC_FREE( pCex );
+                    break;
+                }
+                ABC_FREE( pCex );
+            }
+        }
+        // write equivalence classes
+        Gia_AigerWrite( pGia, "gore.aig", 0, 0 );
+        // reduce the model
+        pReduce = Gia_ManSpecReduce( pGia, 0, 0, 1, 0, 0 );
+        if ( pReduce )
+        {
+            pReduce = Gia_ManSeqStructSweep( pAux = pReduce, 1, 1, 0 );
+            Gia_ManStop( pAux );
+            Gia_AigerWrite( pReduce, "gsrm.aig", 0, 0 );
+//            Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", "gsrm.aig" );
+//          Gia_ManPrintStatsShort( pReduce );
+            Gia_ManStop( pReduce );
+        }
+    }
+    return 1;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces AIG using equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManFilterEquivsForSpeculation( Gia_Man_t * pGia, char * pName1, char * pName2, int fLatchA, int fLatchB )
+{
+    Gia_Man_t * pGia1, * pGia2, * pMiter;
+    Gia_Obj_t * pObj1, * pObj2, * pObjM, * pObj;
+    int i, iObj, iNext, Counter = 0;
+    if ( pGia->pReprs == NULL || pGia->pNexts == NULL )
+    {
+        Abc_Print( 1, "Equivalences are not defined.\n" );
+        return 0;
+    }
+    pGia1 = Gia_AigerRead( pName1, 0, 0 );
+    if ( pGia1 == NULL )
+    {
+        Abc_Print( 1, "Cannot read first file %s.\n", pName1 );
+        return 0;
+    }
+    pGia2 = Gia_AigerRead( pName2, 0, 0 );
+    if ( pGia2 == NULL )
+    {
+        Gia_ManStop( pGia2 );
+        Abc_Print( 1, "Cannot read second file %s.\n", pName2 );
+        return 0;
+    }
+    pMiter = Gia_ManMiter( pGia1, pGia2, 0, 0, 1, 0, 0 );
+    if ( pMiter == NULL )
+    {
+        Gia_ManStop( pGia1 );
+        Gia_ManStop( pGia2 );
+        Abc_Print( 1, "Cannot create sequential miter.\n" );
+        return 0;
+    }
+    // make sure the miter is isomorphic
+    if ( Gia_ManObjNum(pGia) != Gia_ManObjNum(pMiter) )
+    {
+        Gia_ManStop( pGia1 );
+        Gia_ManStop( pGia2 );
+        Gia_ManStop( pMiter );
+        Abc_Print( 1, "The number of objects in different.\n" );
+        return 0;
+    }
+    if ( memcmp( pGia->pObjs, pMiter->pObjs, sizeof(Gia_Obj_t) *  Gia_ManObjNum(pGia) ) )
+    {
+        Gia_ManStop( pGia1 );
+        Gia_ManStop( pGia2 );
+        Gia_ManStop( pMiter );
+        Abc_Print( 1, "The AIG structure of the miter does not match.\n" );
+        return 0;
+    }
+    // transfer copies
+    Gia_ManCleanMark0( pGia );
+    Gia_ManForEachObj( pGia1, pObj1, i )
+    {
+        if ( pObj1->Value == ~0 )
+            continue;
+        pObjM = Gia_ManObj( pMiter, Abc_Lit2Var(pObj1->Value) );
+        pObj = Gia_ManObj( pGia, Gia_ObjId(pMiter, pObjM) );
+        pObj->fMark0 = 1;
+    }
+    Gia_ManCleanMark1( pGia );
+    Gia_ManForEachObj( pGia2, pObj2, i )
+    {
+        if ( pObj2->Value == ~0 )
+            continue;
+        pObjM = Gia_ManObj( pMiter, Abc_Lit2Var(pObj2->Value) );
+        pObj = Gia_ManObj( pGia, Gia_ObjId(pMiter, pObjM) );
+        pObj->fMark1 = 1;
+    }
+
+    // filter equivalences
+    Gia_ManForEachConst( pGia, i )
+    {
+        Gia_ObjUnsetRepr( pGia, i );
+        assert( pGia->pNexts[i] == 0 );
+    }
+    Gia_ManForEachClass( pGia, i )
+    {
+        // find the first colorA and colorB
+        int ClassA = -1, ClassB = -1;
+        Gia_ClassForEachObj( pGia, i, iObj )
+        {
+            pObj = Gia_ManObj( pGia, iObj );
+            if ( ClassA == -1 && pObj->fMark0 && !pObj->fMark1 )
+            {
+                if ( fLatchA && !Gia_ObjIsRo(pGia, pObj) )
+                    continue;
+                ClassA = iObj;
+            }
+            if ( ClassB == -1 && pObj->fMark1 && !pObj->fMark0 )
+            {
+                if ( fLatchB && !Gia_ObjIsRo(pGia, pObj) )
+                    continue;
+                ClassB = iObj;
+            }
+        }
+        // undo equivalence classes
+        for ( iObj = i, iNext = Gia_ObjNext(pGia, iObj); iObj;
+              iObj = iNext, iNext = Gia_ObjNext(pGia, iObj) )
+        {
+            Gia_ObjUnsetRepr( pGia, iObj );
+            Gia_ObjSetNext( pGia, iObj, 0 );
+        }
+        assert( !Gia_ObjIsHead(pGia, i) );
+        if ( ClassA > 0 && ClassB > 0 )
+        {
+            if ( ClassA > ClassB )
+            {
+                ClassA ^= ClassB;
+                ClassB ^= ClassA;
+                ClassA ^= ClassB;
+            }
+            assert( ClassA < ClassB );
+            Gia_ObjSetNext( pGia, ClassA, ClassB );
+            Gia_ObjSetRepr( pGia, ClassB, ClassA );
+            Counter++;
+            assert( Gia_ObjIsHead(pGia, ClassA) );
+        }
+    }
+    Abc_Print( 1, "The number of two-node classes after filtering = %d.\n", Counter );
+//Gia_ManEquivPrintClasses( pGia, 1, 0 );
+
+    Gia_ManCleanMark0( pGia );
+    Gia_ManCleanMark1( pGia );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces AIG using equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManFilterEquivsUsingParts( Gia_Man_t * pGia, char * pName1, char * pName2 )
+{
+    Vec_Int_t * vNodes;
+    Gia_Man_t * pGia1, * pGia2, * pMiter;
+    Gia_Obj_t * pObj1, * pObj2, * pObjM, * pObj = NULL;
+    int i, k, iObj, iNext, iPrev, iRepr;
+    int iLitsOld, iLitsNew;
+    if ( pGia->pReprs == NULL || pGia->pNexts == NULL )
+    {
+        Abc_Print( 1, "Equivalences are not defined.\n" );
+        return 0;
+    }
+    pGia1 = Gia_AigerRead( pName1, 0, 0 );
+    if ( pGia1 == NULL )
+    {
+        Abc_Print( 1, "Cannot read first file %s.\n", pName1 );
+        return 0;
+    }
+    pGia2 = Gia_AigerRead( pName2, 0, 0 );
+    if ( pGia2 == NULL )
+    {
+        Gia_ManStop( pGia2 );
+        Abc_Print( 1, "Cannot read second file %s.\n", pName2 );
+        return 0;
+    }
+    pMiter = Gia_ManMiter( pGia1, pGia2, 0, 0, 1, 0, 0 );
+    if ( pMiter == NULL )
+    {
+        Gia_ManStop( pGia1 );
+        Gia_ManStop( pGia2 );
+        Abc_Print( 1, "Cannot create sequential miter.\n" );
+        return 0;
+    }
+    // make sure the miter is isomorphic
+    if ( Gia_ManObjNum(pGia) != Gia_ManObjNum(pMiter) )
+    {
+        Gia_ManStop( pGia1 );
+        Gia_ManStop( pGia2 );
+        Gia_ManStop( pMiter );
+        Abc_Print( 1, "The number of objects in different.\n" );
+        return 0;
+    }
+    if ( memcmp( pGia->pObjs, pMiter->pObjs, sizeof(Gia_Obj_t) *  Gia_ManObjNum(pGia) ) )
+    {
+        Gia_ManStop( pGia1 );
+        Gia_ManStop( pGia2 );
+        Gia_ManStop( pMiter );
+        Abc_Print( 1, "The AIG structure of the miter does not match.\n" );
+        return 0;
+    }
+    // transfer copies
+    Gia_ManCleanMark0( pGia );
+    Gia_ManForEachObj( pGia1, pObj1, i )
+    {
+        if ( pObj1->Value == ~0 )
+            continue;
+        pObjM = Gia_ManObj( pMiter, Abc_Lit2Var(pObj1->Value) );
+        pObj = Gia_ManObj( pGia, Gia_ObjId(pMiter, pObjM) );
+        pObj->fMark0 = 1;
+    }
+    Gia_ManCleanMark1( pGia );
+    Gia_ManForEachObj( pGia2, pObj2, i )
+    {
+        if ( pObj2->Value == ~0 )
+            continue;
+        pObjM = Gia_ManObj( pMiter, Abc_Lit2Var(pObj2->Value) );
+        pObj = Gia_ManObj( pGia, Gia_ObjId(pMiter, pObjM) );
+        pObj->fMark1 = 1;
+    }
+
+    // filter equivalences
+    iLitsOld = iLitsNew = 0;
+    Gia_ManForEachConst( pGia, i )
+    {
+        iLitsOld++;
+        pObj = Gia_ManObj( pGia, i );
+        assert( pGia->pNexts[i] == 0 );
+        assert( pObj->fMark0 || pObj->fMark1 );
+        if ( pObj->fMark0 && pObj->fMark1 ) // belongs to both A and B
+            Gia_ObjUnsetRepr( pGia, i );
+        else
+            iLitsNew++;
+    }
+    // filter equivalences
+    vNodes = Vec_IntAlloc( 100 );
+    Gia_ManForEachClass( pGia, i )
+    {
+        int fSeenA = 0, fSeenB = 0;
+        assert( pObj->fMark0 || pObj->fMark1 );
+        Vec_IntClear( vNodes );
+        Gia_ClassForEachObj( pGia, i, iObj )
+        {
+            pObj = Gia_ManObj( pGia, iObj );
+            if ( pObj->fMark0 && !pObj->fMark1 )
+            {
+                fSeenA = 1;
+                Vec_IntPush( vNodes, iObj );
+            }
+            if ( !pObj->fMark0 && pObj->fMark1 )
+            {
+                fSeenB = 1;
+                Vec_IntPush( vNodes, iObj );
+            }
+            iLitsOld++;
+        }
+        iLitsOld--;
+        // undo equivalence classes
+        for ( iObj = i, iNext = Gia_ObjNext(pGia, iObj); iObj;
+              iObj = iNext, iNext = Gia_ObjNext(pGia, iObj) )
+        {
+            Gia_ObjUnsetRepr( pGia, iObj );
+            Gia_ObjSetNext( pGia, iObj, 0 );
+        }
+        assert( !Gia_ObjIsHead(pGia, i) );
+        if ( fSeenA && fSeenB && Vec_IntSize(vNodes) > 1 )
+        {
+            // create new class
+            iPrev = iRepr = Vec_IntEntry( vNodes, 0 );
+            Vec_IntForEachEntryStart( vNodes, iObj, k, 1 )
+            {
+                Gia_ObjSetRepr( pGia, iObj, iRepr );
+                Gia_ObjSetNext( pGia, iPrev, iObj );
+                iPrev = iObj;
+                iLitsNew++;
+            }
+            assert( Gia_ObjNext(pGia, iPrev) == 0 );
+        }
+    }
+    Vec_IntFree( vNodes );
+    Abc_Print( 1, "The number of literals: Before = %d. After = %d.\n", iLitsOld, iLitsNew );
+//Gia_ManEquivPrintClasses( pGia, 1, 0 );
+
+    Gia_ManCleanMark0( pGia );
+    Gia_ManCleanMark1( pGia );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFilterEquivsUsingLatches( Gia_Man_t * pGia, int fFlopsOnly, int fFlopsWith )
+{
+    Vec_Int_t * vNodes;
+    Gia_Obj_t * pObj;
+    int i, k, iObj, iNext, iPrev, iRepr;
+    int iLitsOld = 0, iLitsNew = 0;
+    assert( fFlopsOnly ^ fFlopsWith );
+    vNodes = Vec_IntAlloc( 100 );
+    // remove all noo-flop constants
+    Gia_ManForEachConst( pGia, i )
+    {
+        iLitsOld++;
+        pObj = Gia_ManObj( pGia, i );
+        assert( pGia->pNexts[i] == 0 );
+        if ( !Gia_ObjIsRo(pGia, pObj) )
+            Gia_ObjUnsetRepr( pGia, i );
+        else
+            iLitsNew++;
+    }
+    // clear the classes
+    if ( fFlopsOnly )
+    {
+        Gia_ManForEachClass( pGia, i )
+        {
+            Vec_IntClear( vNodes );
+            Gia_ClassForEachObj( pGia, i, iObj )
+            {
+                pObj = Gia_ManObj( pGia, iObj );
+                if ( Gia_ObjIsRo(pGia, pObj) )
+                    Vec_IntPush( vNodes, iObj );
+                iLitsOld++;
+            }
+            iLitsOld--;
+            // undo equivalence classes
+            for ( iObj = i, iNext = Gia_ObjNext(pGia, iObj); iObj;
+                  iObj = iNext, iNext = Gia_ObjNext(pGia, iObj) )
+            {
+                Gia_ObjUnsetRepr( pGia, iObj );
+                Gia_ObjSetNext( pGia, iObj, 0 );
+            }
+            assert( !Gia_ObjIsHead(pGia, i) );
+            if ( Vec_IntSize(vNodes) > 1 )
+            {
+                // create new class
+                iPrev = iRepr = Vec_IntEntry( vNodes, 0 );
+                Vec_IntForEachEntryStart( vNodes, iObj, k, 1 )
+                {
+                    Gia_ObjSetRepr( pGia, iObj, iRepr );
+                    Gia_ObjSetNext( pGia, iPrev, iObj );
+                    iPrev = iObj;
+                    iLitsNew++;
+                }
+                assert( Gia_ObjNext(pGia, iPrev) == 0 );
+            }
+        }
+    }
+    else
+    {
+        Gia_ManForEachClass( pGia, i )
+        {
+            int fSeenFlop = 0;
+            Gia_ClassForEachObj( pGia, i, iObj )
+            {
+                pObj = Gia_ManObj( pGia, iObj );
+                if ( Gia_ObjIsRo(pGia, pObj) )
+                    fSeenFlop = 1;
+                iLitsOld++;
+                iLitsNew++;
+            }
+            iLitsOld--;
+            iLitsNew--;
+            if ( fSeenFlop )
+                continue;
+            // undo equivalence classes
+            for ( iObj = i, iNext = Gia_ObjNext(pGia, iObj); iObj;
+                  iObj = iNext, iNext = Gia_ObjNext(pGia, iObj) )
+            {
+                Gia_ObjUnsetRepr( pGia, iObj );
+                Gia_ObjSetNext( pGia, iObj, 0 );
+                iLitsNew--;
+            }
+            iLitsNew++;
+            assert( !Gia_ObjIsHead(pGia, i) );
+        }
+    }
+    Vec_IntFree( vNodes );
+    Abc_Print( 1, "The number of literals: Before = %d. After = %d.\n", iLitsOld, iLitsNew );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/aig/gia/giaEra.c b/abc-build/src/aig/gia/giaEra.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaEra.c
@@ -0,0 +1,602 @@
+/**CFile****************************************************************
+
+  FileName    [giaEra.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Explicit reachability analysis.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaEra.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/mem/mem.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// explicit state representation
+typedef struct Gia_ObjEra_t_ Gia_ObjEra_t;
+struct Gia_ObjEra_t_
+{
+    int            Num;          // ID of this state
+    int            Cond;         // input condition
+    int            iPrev;        // previous state
+    int            iNext;        // next state in the hash table
+    unsigned       pData[0];     // state bits
+};
+
+// explicit state reachability
+typedef struct Gia_ManEra_t_ Gia_ManEra_t;
+struct Gia_ManEra_t_
+{
+    Gia_Man_t *    pAig;         // user's AIG manager
+    int            nWordsSim;       // 2^(PInum)
+    int            nWordsDat;   // Abc_BitWordNum
+    unsigned *     pDataSim;     // simulation data
+    Mem_Fixed_t *  pMemory;      // memory manager
+    Vec_Ptr_t *    vStates;      // reached states
+    Gia_ObjEra_t * pStateNew;    // temporary state
+    int            iCurState;    // the current state
+    Vec_Int_t *    vBugTrace;    // the sequence of transitions
+    Vec_Int_t *    vStgDump;     // STG written into a file
+    // hash table for states
+    int            nBins;         
+    unsigned *     pBins;
+};
+
+static inline unsigned *     Gia_ManEraData( Gia_ManEra_t * p, int i )    { return p->pDataSim + i * p->nWordsSim;  }
+static inline Gia_ObjEra_t * Gia_ManEraState( Gia_ManEra_t * p, int i )   { return (Gia_ObjEra_t *)Vec_PtrEntry(p->vStates, i);  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates reachability manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_ManEra_t * Gia_ManEraCreate( Gia_Man_t * pAig )
+{
+    Vec_Ptr_t * vTruths;
+    Gia_ManEra_t * p;
+    unsigned * pTruth, * pSimInfo;
+    int i;
+    p = ABC_CALLOC( Gia_ManEra_t, 1 );
+    p->pAig      = pAig;
+    p->nWordsSim = Abc_TruthWordNum( Gia_ManPiNum(pAig) );
+    p->nWordsDat = Abc_BitWordNum( Gia_ManRegNum(pAig) );
+    p->pDataSim  = ABC_ALLOC( unsigned, p->nWordsSim*Gia_ManObjNum(pAig) );
+    p->pMemory   = Mem_FixedStart( sizeof(Gia_ObjEra_t) + sizeof(unsigned) * p->nWordsDat );
+    p->vStates   = Vec_PtrAlloc( 100000 );
+    p->nBins     = Abc_PrimeCudd( 100000 );
+    p->pBins     = ABC_CALLOC( unsigned, p->nBins );
+    Vec_PtrPush( p->vStates, NULL );
+    // assign primary input values
+    vTruths = Vec_PtrAllocTruthTables( Gia_ManPiNum(pAig) );
+    Vec_PtrForEachEntry( unsigned *, vTruths, pTruth, i )
+    {
+        pSimInfo = Gia_ManEraData( p, Gia_ObjId(pAig, Gia_ManPi(pAig, i)) );
+        memcpy( pSimInfo, pTruth, sizeof(unsigned) * p->nWordsSim );
+    }
+    Vec_PtrFree( vTruths );
+    // assign constant zero node
+    pSimInfo = Gia_ManEraData( p, 0 );
+    memset( pSimInfo, 0, sizeof(unsigned) * p->nWordsSim );
+    p->vStgDump = Vec_IntAlloc( 1000 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes reachability manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManEraFree( Gia_ManEra_t * p )
+{
+    Mem_FixedStop( p->pMemory, 0 );
+    Vec_IntFree( p->vStgDump );
+    Vec_PtrFree( p->vStates );
+    if ( p->vBugTrace ) Vec_IntFree( p->vBugTrace );
+    ABC_FREE( p->pDataSim );
+    ABC_FREE( p->pBins );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates new state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_ObjEra_t * Gia_ManEraCreateState( Gia_ManEra_t * p )
+{
+    Gia_ObjEra_t * pNew;
+    pNew = (Gia_ObjEra_t *)Mem_FixedEntryFetch( p->pMemory );
+    pNew->Num = Vec_PtrSize( p->vStates );
+    pNew->iPrev = 0;
+    Vec_PtrPush( p->vStates, pNew );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash value of the node using its simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManEraStateHash( unsigned * pState, int nWordsSim, int nTableSize )
+{
+    static int s_FPrimes[128] = { 
+        1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 
+        1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 
+        2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 
+        2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 
+        3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 
+        3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 
+        4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 
+        4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 
+        5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 
+        6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 
+        6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 
+        7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 
+        8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+    };
+    unsigned uHash;
+    int i;
+    uHash = 0;
+    for ( i = 0; i < nWordsSim; i++ )
+        uHash ^= pState[i] * s_FPrimes[i & 0x7F];
+    return uHash % nTableSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the place of this state in the table or NULL if it exists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned * Gia_ManEraHashFind( Gia_ManEra_t * p, Gia_ObjEra_t * pState, int * pStateNum )
+{
+    Gia_ObjEra_t * pThis;
+    unsigned * pPlace = p->pBins + Gia_ManEraStateHash( pState->pData, p->nWordsDat, p->nBins );
+    for ( pThis = (*pPlace)? Gia_ManEraState(p, *pPlace) : NULL; pThis; 
+          pPlace = (unsigned *)&pThis->iNext, pThis = (*pPlace)? Gia_ManEraState(p, *pPlace) : NULL )
+              if ( !memcmp( pState->pData, pThis->pData, sizeof(unsigned) * p->nWordsDat ) )
+              {
+                  if ( pStateNum )
+                      *pStateNum = pThis->Num;
+                  return NULL;
+              }
+    if ( pStateNum )
+      *pStateNum = -1;
+    return pPlace;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManEraHashResize( Gia_ManEra_t * p )
+{
+    Gia_ObjEra_t * pThis;
+    unsigned * pBinsOld, * piPlace;
+    int nBinsOld, iNext, Counter, i;
+    assert( p->pBins != NULL );
+    // replace the table
+    pBinsOld = p->pBins;
+    nBinsOld = p->nBins;
+    p->nBins = Abc_PrimeCudd( 3 * p->nBins ); 
+    p->pBins = ABC_CALLOC( unsigned, p->nBins );
+    // rehash the entries from the old table
+    Counter = 0;
+    for ( i = 0; i < nBinsOld; i++ )
+    for ( pThis = (pBinsOld[i]? Gia_ManEraState(p, pBinsOld[i]) : NULL),
+          iNext = (pThis? pThis->iNext : 0);  
+          pThis;  pThis = (iNext? Gia_ManEraState(p, iNext) : NULL),   
+          iNext = (pThis? pThis->iNext : 0)  )
+    {
+        assert( pThis->Num );
+        pThis->iNext = 0;
+        piPlace = Gia_ManEraHashFind( p, pThis, NULL );
+        assert( *piPlace == 0 ); // should not be there
+        *piPlace = pThis->Num;
+        Counter++;
+    }
+    assert( Counter == Vec_PtrSize( p->vStates ) - 1 );
+    ABC_FREE( pBinsOld );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Initialize register output to the given state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManInsertState( Gia_ManEra_t * p, Gia_ObjEra_t * pState )
+{
+    Gia_Obj_t * pObj;
+    unsigned * pSimInfo;
+    int i;
+    Gia_ManForEachRo( p->pAig, pObj, i )
+    {
+        pSimInfo = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) );
+        if ( Abc_InfoHasBit(pState->pData, i) )
+            memset( pSimInfo, 0xff, sizeof(unsigned) * p->nWordsSim );
+        else
+            memset( pSimInfo, 0, sizeof(unsigned) * p->nWordsSim );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns -1 if outputs are not asserted.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManOutputAsserted( Gia_ManEra_t * p, Gia_Obj_t * pObj )
+{
+    unsigned * pInfo  = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) );
+    int w;
+    for ( w = 0; w < p->nWordsSim; w++ )
+        if ( pInfo[w] )
+            return 32*w + Gia_WordFindFirstBit( pInfo[w] );
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSimulateCo( Gia_ManEra_t * p, Gia_Obj_t * pObj )
+{
+    int Id = Gia_ObjId(p->pAig, pObj);
+    unsigned * pInfo  = Gia_ManEraData( p, Id );
+    unsigned * pInfo0 = Gia_ManEraData( p, Gia_ObjFaninId0(pObj, Id) );
+    int w;
+    if ( Gia_ObjFaninC0(pObj) )
+        for ( w = p->nWordsSim-1; w >= 0; w-- )
+            pInfo[w] = ~pInfo0[w];
+    else 
+        for ( w = p->nWordsSim-1; w >= 0; w-- )
+            pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSimulateNode( Gia_ManEra_t * p, Gia_Obj_t * pObj )
+{
+    int Id = Gia_ObjId(p->pAig, pObj);
+    unsigned * pInfo  = Gia_ManEraData( p, Id );
+    unsigned * pInfo0 = Gia_ManEraData( p, Gia_ObjFaninId0(pObj, Id) );
+    unsigned * pInfo1 = Gia_ManEraData( p, Gia_ObjFaninId1(pObj, Id) );
+    int w;
+    if ( Gia_ObjFaninC0(pObj) )
+    {
+        if (  Gia_ObjFaninC1(pObj) )
+            for ( w = p->nWordsSim-1; w >= 0; w-- )
+                pInfo[w] = ~(pInfo0[w] | pInfo1[w]);
+        else 
+            for ( w = p->nWordsSim-1; w >= 0; w-- )
+                pInfo[w] = ~pInfo0[w] & pInfo1[w];
+    }
+    else 
+    {
+        if (  Gia_ObjFaninC1(pObj) )
+            for ( w = p->nWordsSim-1; w >= 0; w-- )
+                pInfo[w] = pInfo0[w] & ~pInfo1[w];
+        else 
+            for ( w = p->nWordsSim-1; w >= 0; w-- )
+                pInfo[w] = pInfo0[w] & pInfo1[w];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one iteration of reachability analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPerformOneIter( Gia_ManEra_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj1( p->pAig, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            Gia_ManSimulateNode( p, pObj );
+        else if ( Gia_ObjIsCo(pObj) )
+            Gia_ManSimulateCo( p, pObj );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one iteration of reachability analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManCollectBugTrace( Gia_ManEra_t * p, Gia_ObjEra_t * pState, int iCond )
+{
+    Vec_Int_t * vTrace;
+    vTrace = Vec_IntAlloc( 10 );
+    Vec_IntPush( vTrace, iCond );
+    for ( ; pState; pState = pState->iPrev ? Gia_ManEraState(p, pState->iPrev) : NULL )
+        Vec_IntPush( vTrace, pState->Cond );
+    Vec_IntReverseOrder( vTrace );
+    return vTrace;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the depth of state transitions leading ot this state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCountDepth( Gia_ManEra_t * p )
+{
+    Gia_ObjEra_t * pState;
+    int Counter = 0;
+    pState = (Gia_ObjEra_t *)Vec_PtrEntryLast( p->vStates );
+    if ( pState->iPrev == 0 && Vec_PtrSize(p->vStates) > 3 )
+        pState = (Gia_ObjEra_t *)Vec_PtrEntry( p->vStates, Vec_PtrSize(p->vStates) - 2 );
+    for ( ; pState; pState = pState->iPrev ? Gia_ManEraState(p, pState->iPrev) : NULL )
+        Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Analized reached states.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManAnalyzeResult( Gia_ManEra_t * p, Gia_ObjEra_t * pState, int fMiter, int fStgDump )
+{
+    Gia_Obj_t * pObj;
+    unsigned * pSimInfo, * piPlace, uOutput = 0;
+    int i, k, iCond, nMints, iNextState;
+    // check if the miter is asserted
+    if ( fMiter )
+    {
+        Gia_ManForEachPo( p->pAig, pObj, i )
+        {
+            iCond = Gia_ManOutputAsserted( p, pObj );
+            if ( iCond >= 0 )
+            {
+                p->vBugTrace = Gia_ManCollectBugTrace( p, pState, iCond );
+                return 1;
+            }
+        }
+    }
+    // collect reached states 
+    nMints = (1 << Gia_ManPiNum(p->pAig));
+    for ( k = 0; k < nMints; k++ )
+    {
+        if ( p->pStateNew == NULL )
+            p->pStateNew = Gia_ManEraCreateState( p );
+        p->pStateNew->pData[p->nWordsDat-1] = 0;
+        Gia_ManForEachRi( p->pAig, pObj, i )
+        {
+            pSimInfo = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) );
+            if ( Abc_InfoHasBit(p->pStateNew->pData, i) != Abc_InfoHasBit(pSimInfo, k) )
+                Abc_InfoXorBit( p->pStateNew->pData, i );
+        }
+        if ( fStgDump )
+        {
+            uOutput = 0;
+            Gia_ManForEachPo( p->pAig, pObj, i )
+            {
+                pSimInfo = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) );
+                if ( Abc_InfoHasBit(pSimInfo, k) && i < 32 )
+                    Abc_InfoXorBit( &uOutput, i );
+            }
+        }
+        piPlace = Gia_ManEraHashFind( p, p->pStateNew, &iNextState );
+        if ( fStgDump ) Vec_IntPush( p->vStgDump, k );
+        if ( fStgDump ) Vec_IntPush( p->vStgDump, pState->Num );
+        if ( piPlace == NULL )
+        {
+            if ( fStgDump ) Vec_IntPush( p->vStgDump, iNextState );
+            if ( fStgDump ) Vec_IntPush( p->vStgDump, uOutput );
+            continue;
+        }
+        if ( fStgDump ) Vec_IntPush( p->vStgDump, p->pStateNew->Num );
+        if ( fStgDump ) Vec_IntPush( p->vStgDump, uOutput );
+//printf( "Inserting %d ", Vec_PtrSize(p->vStates) );
+//Extra_PrintBinary( stdout, p->pStateNew->pData, Gia_ManRegNum(p->pAig) );  printf( "\n" );
+        assert( *piPlace == 0 );
+        *piPlace = p->pStateNew->Num;
+        p->pStateNew->Cond = k;
+        p->pStateNew->iPrev = pState->Num;
+        p->pStateNew->iNext = 0;
+        p->pStateNew = NULL;
+        // expand hash table if needed
+        if ( Vec_PtrSize(p->vStates) > 2 * p->nBins )
+            Gia_ManEraHashResize( p );
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCollectReachable( Gia_Man_t * pAig, int nStatesMax, int fMiter, int fDumpFile, int fVerbose )
+{ 
+    Gia_ManEra_t * p;
+    Gia_ObjEra_t * pState;
+    int Hash;
+    abctime clk = Abc_Clock();
+    int RetValue = 1;
+    assert( Gia_ManPiNum(pAig) <= 12 );
+    assert( Gia_ManRegNum(pAig) > 0 );
+    p = Gia_ManEraCreate( pAig );
+    // create init state
+    pState = Gia_ManEraCreateState( p );
+    pState->Cond  = 0; 
+    pState->iPrev = 0;
+    pState->iNext = 0; 
+    memset( pState->pData, 0, sizeof(unsigned) * p->nWordsDat );
+    Hash = Gia_ManEraStateHash(pState->pData, p->nWordsDat, p->nBins);
+    p->pBins[ Hash ] = pState->Num;
+    // process reachable states
+    while ( p->iCurState < Vec_PtrSize( p->vStates ) - 1 )
+    {
+        if ( Vec_PtrSize(p->vStates) >= nStatesMax )
+        {
+            printf( "Reached the limit on states traversed (%d).  ", nStatesMax );
+            RetValue = -1;
+            break;
+        }
+        pState = Gia_ManEraState( p, ++p->iCurState );
+        if ( p->iCurState > 1 && pState->iPrev == 0 )
+            continue;
+//printf( "Extracting %d  ", p->iCurState );
+//Extra_PrintBinary( stdout, p->pStateNew->pData, Gia_ManRegNum(p->pAig) );  printf( "\n" );
+        Gia_ManInsertState( p, pState );
+        Gia_ManPerformOneIter( p );
+        if ( Gia_ManAnalyzeResult( p, pState, fMiter, fDumpFile ) && fMiter )
+        {
+            RetValue = 0;
+            printf( "Miter failed in state %d after %d transitions.  ", 
+                p->iCurState, Vec_IntSize(p->vBugTrace)-1 );
+            break;
+        }
+        if ( fVerbose && p->iCurState % 5000 == 0 )
+        {
+            printf( "States =%10d. Reached =%10d. R = %5.3f. Depth =%6d. Mem =%9.2f MB.  ", 
+                p->iCurState, Vec_PtrSize(p->vStates), 1.0*p->iCurState/Vec_PtrSize(p->vStates), Gia_ManCountDepth(p), 
+                (1.0/(1<<20))*(1.0*Vec_PtrSize(p->vStates)*(sizeof(Gia_ObjEra_t) + sizeof(unsigned) * p->nWordsDat) + 
+                   1.0*p->nBins*sizeof(unsigned) + 1.0*p->vStates->nCap * sizeof(void*)) );
+            ABC_PRT( "Time", Abc_Clock() - clk );
+        }
+    }
+    printf( "Reachability analysis traversed %d states with depth %d.  ", p->iCurState-1, Gia_ManCountDepth(p) );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    if ( fDumpFile )
+    {
+        char * pFileName = "test.stg";
+        FILE * pFile = fopen( pFileName, "wb" );
+        if ( pFile == NULL )
+            printf( "Cannot open file \"%s\" for writing.\n", pFileName );
+        else
+        {
+            Gia_ManStgPrint( pFile, p->vStgDump, Gia_ManPiNum(pAig), Gia_ManPoNum(pAig), p->iCurState-1 );
+            fclose( pFile );
+            printf( "Extracted STG was written into file \"%s\".\n", pFileName );
+        }
+    }
+    Gia_ManEraFree( p );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaEra2.c b/abc-build/src/aig/gia/giaEra2.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaEra2.c
@@ -0,0 +1,1956 @@
+/**CFile****************************************************************
+
+  FileName    [gia.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/*
+    Limitations of this package:
+    - no more than (1<<31)-1 state cubes and internal nodes
+    - no more than MAX_VARS_NUM state variables
+    - no more than MAX_CALL_NUM transitions from a state
+    - cube list rebalancing happens when cube count reaches MAX_CUBE_NUM
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define MAX_CALL_NUM    (1000000)  // the max number of recursive calls
+#define MAX_ITEM_NUM      (1<<20)  // the number of items on a page
+#define MAX_PAGE_NUM      (1<<11)  // the max number of memory pages
+#define MAX_VARS_NUM      (1<<14)  // the max number of state vars allowed
+#define MAX_CUBE_NUM          63   // the max number of cubes before rebalancing
+
+// pointer to the tree node or state cube
+typedef struct Gia_PtrAre_t_ Gia_PtrAre_t;
+struct Gia_PtrAre_t_
+{
+    unsigned       nItem    : 20;  // item number (related to MAX_ITEM_NUM)
+    unsigned       nPage    : 11;  // page number (related to MAX_PAGE_NUM)
+    unsigned       fMark    :  1;  // user mark
+};
+
+// tree nodes
+typedef struct Gia_ObjAre_t_ Gia_ObjAre_t;
+struct Gia_ObjAre_t_
+{
+    unsigned       iVar     : 14;  // variable     (related to MAX_VARS_NUM)
+    unsigned       nStas0   :  6;  // cube counter (related to MAX_CUBE_NUM)
+    unsigned       nStas1   :  6;  // cube counter (related to MAX_CUBE_NUM)
+    unsigned       nStas2   :  6;  // cube counter (related to MAX_CUBE_NUM)
+    Gia_PtrAre_t   F[3];           // branches
+};
+
+// state cube
+typedef struct Gia_StaAre_t_ Gia_StaAre_t;
+struct Gia_StaAre_t_
+{
+    Gia_PtrAre_t   iPrev;          // previous state
+    Gia_PtrAre_t   iNext;          // next cube in the list
+    unsigned       pData[0];       // state bits
+};
+
+// explicit state reachability manager
+typedef struct Gia_ManAre_t_ Gia_ManAre_t;
+struct Gia_ManAre_t_
+{
+    Gia_Man_t *    pAig;           // user's AIG manager
+    Gia_Man_t *    pNew;           // temporary AIG manager
+    unsigned **    ppObjs;         // storage for objects (MAX_PAGE_NUM pages)
+    unsigned **    ppStas;         // storage for states  (MAX_PAGE_NUM pages)
+//    unsigned *     pfUseless;      // to label useless cubes
+//    int            nUselessAlloc;  // the number of useless alloced
+    // internal flags
+    int            fMiter;         // stops when a bug is discovered
+    int            fStopped;       // set high when reachability is stopped
+    int            fTree;          // working in the tree mode
+    // internal parametesr
+    int            nWords;         // the size of bit info in words
+    int            nSize;          // the size of state structure in words
+    int            nObjPages;      // the number of pages used for objects
+    int            nStaPages;      // the number of pages used for states
+    int            nObjs;          // the number of objects 
+    int            nStas;          // the number of states  
+    int            iStaCur;        // the next state to be explored
+    Gia_PtrAre_t   Root;           // root of the tree
+    Vec_Vec_t *    vCiTfos;        // storage for nodes in the CI TFOs
+    Vec_Vec_t *    vCiLits;        // storage for literals of these nodes
+    Vec_Int_t *    vCubesA;        // checked cubes
+    Vec_Int_t *    vCubesB;        // unchecked cubes
+    // deriving counter-example
+    void *         pSat;           // SAT solver
+    Vec_Int_t *    vSatNumCis;     // SAT variables for CIs
+    Vec_Int_t *    vSatNumCos;     // SAT variables for COs 
+    Vec_Int_t *    vCofVars;       // variables used to cofactor
+    Vec_Int_t *    vAssumps;       // temporary storage for assumptions
+    Gia_StaAre_t * pTarget;        // state that needs to be reached
+    int            iOutFail;       // the number of the failed output
+    // statistics
+    int            nChecks;        // the number of timea cube was checked
+    int            nEquals;        // total number of equal
+    int            nCompares;      // the number of compares
+    int            nRecCalls;      // the number of rec calls
+    int            nDisjs;         // the number of disjoint cube pairs
+    int            nDisjs2;        // the number of disjoint cube pairs
+    int            nDisjs3;        // the number of disjoint cube pairs
+    // time
+    int            timeAig;        // AIG cofactoring time
+    int            timeCube;       // cube checking time 
+}; 
+
+static inline Gia_PtrAre_t    Gia_Int2Ptr( unsigned n )                               { return *(Gia_PtrAre_t *)(&n);                            }
+static inline unsigned        Gia_Ptr2Int( Gia_PtrAre_t n )                           { return (*(int *)(&n)) & 0x7fffffff;                      }
+
+static inline int             Gia_ObjHasBranch0( Gia_ObjAre_t * q )                   { return !q->nStas0 && (q->F[0].nPage || q->F[0].nItem);   }
+static inline int             Gia_ObjHasBranch1( Gia_ObjAre_t * q )                   { return !q->nStas1 && (q->F[1].nPage || q->F[1].nItem);   }
+static inline int             Gia_ObjHasBranch2( Gia_ObjAre_t * q )                   { return !q->nStas2 && (q->F[2].nPage || q->F[2].nItem);   }
+
+static inline Gia_ObjAre_t *  Gia_ManAreObj( Gia_ManAre_t * p, Gia_PtrAre_t n )       { return (Gia_ObjAre_t *)(p->ppObjs[n.nPage] + (n.nItem << 2));      }
+static inline Gia_StaAre_t *  Gia_ManAreSta( Gia_ManAre_t * p, Gia_PtrAre_t n )       { return (Gia_StaAre_t *)(p->ppStas[n.nPage] +  n.nItem * p->nSize); }
+static inline Gia_ObjAre_t *  Gia_ManAreObjInt( Gia_ManAre_t * p, int n )             { return Gia_ManAreObj( p, Gia_Int2Ptr(n) );               }
+static inline Gia_StaAre_t *  Gia_ManAreStaInt( Gia_ManAre_t * p, int n )             { return Gia_ManAreSta( p, Gia_Int2Ptr(n) );               }
+static inline Gia_ObjAre_t *  Gia_ManAreObjLast( Gia_ManAre_t * p )                   { return Gia_ManAreObjInt( p, p->nObjs-1 );                }
+static inline Gia_StaAre_t *  Gia_ManAreStaLast( Gia_ManAre_t * p )                   { return Gia_ManAreStaInt( p, p->nStas-1 );                }
+
+static inline Gia_ObjAre_t *  Gia_ObjNextObj0( Gia_ManAre_t * p, Gia_ObjAre_t * q )   { return Gia_ManAreObj( p, q->F[0] );                      }
+static inline Gia_ObjAre_t *  Gia_ObjNextObj1( Gia_ManAre_t * p, Gia_ObjAre_t * q )   { return Gia_ManAreObj( p, q->F[1] );                      }
+static inline Gia_ObjAre_t *  Gia_ObjNextObj2( Gia_ManAre_t * p, Gia_ObjAre_t * q )   { return Gia_ManAreObj( p, q->F[2] );                      }
+
+static inline int             Gia_StaHasValue0( Gia_StaAre_t * p, int iReg )          { return Abc_InfoHasBit( p->pData,  iReg << 1 );           }
+static inline int             Gia_StaHasValue1( Gia_StaAre_t * p, int iReg )          { return Abc_InfoHasBit( p->pData, (iReg << 1) + 1 );      }
+
+static inline void            Gia_StaSetValue0( Gia_StaAre_t * p, int iReg )          { Abc_InfoSetBit( p->pData,  iReg << 1 );                  }
+static inline void            Gia_StaSetValue1( Gia_StaAre_t * p, int iReg )          { Abc_InfoSetBit( p->pData, (iReg << 1) + 1 );             }
+
+static inline Gia_StaAre_t *  Gia_StaPrev( Gia_ManAre_t * p, Gia_StaAre_t * pS )      { return Gia_ManAreSta(p, pS->iPrev);                      }
+static inline Gia_StaAre_t *  Gia_StaNext( Gia_ManAre_t * p, Gia_StaAre_t * pS )      { return Gia_ManAreSta(p, pS->iNext);                      }
+static inline int             Gia_StaIsGood( Gia_ManAre_t * p, Gia_StaAre_t * pS )    { return ((unsigned *)pS) != p->ppStas[0];                         }
+
+static inline void            Gia_StaSetUnused( Gia_StaAre_t * pS )                   { pS->iPrev.fMark = 1;                                     }
+static inline int             Gia_StaIsUnused( Gia_StaAre_t * pS )                    { return  pS->iPrev.fMark;                                 }
+static inline int             Gia_StaIsUsed( Gia_StaAre_t * pS )                      { return !pS->iPrev.fMark;                                 }
+
+#define Gia_ManAreForEachCubeList( p, pList, pCube )                         \
+    for ( pCube = pList; Gia_StaIsGood(p, pCube); pCube = Gia_StaNext(p, pCube) )
+#define Gia_ManAreForEachCubeList2( p, iList, pCube, iCube )                 \
+    for ( iCube = Gia_Ptr2Int(iList), pCube = Gia_ManAreSta(p, iList);       \
+          Gia_StaIsGood(p, pCube);                                           \
+          iCube = Gia_Ptr2Int(pCube->iNext), pCube = Gia_StaNext(p, pCube) )
+#define Gia_ManAreForEachCubeStore( p, pCube, i )                            \
+    for ( i = 1; i < p->nStas && (pCube = Gia_ManAreStaInt(p, i)); i++ )
+#define Gia_ManAreForEachCubeVec( vVec, p, pCube, i )                        \
+    for ( i = 0; i < Vec_IntSize(vVec) && (pCube = Gia_ManAreStaInt(p, Vec_IntEntry(vVec,i))); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Count state minterms contained in a cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCountMintermsInCube( Gia_StaAre_t * pCube, int nVars, unsigned * pStore )
+{
+    unsigned Mint, Mask = 0;
+    int i, m, nMints, nDashes = 0, Dashes[32];
+    // count the number of dashes
+    for ( i = 0; i < nVars; i++ )
+    {
+        if ( Gia_StaHasValue0( pCube, i ) )
+            continue;
+        if ( Gia_StaHasValue1( pCube, i ) )
+            Mask |= (1 << i);
+        else
+            Dashes[nDashes++] = i;
+    }
+    // fill in the miterms
+    nMints = (1 << nDashes);
+    for ( m = 0; m < nMints; m++ )
+    {
+        Mint = Mask;
+        for ( i = 0; i < nVars; i++ )
+            if ( m & (1 << i) )
+                Mint |= (1 << Dashes[i]);
+        Abc_InfoSetBit( pStore, Mint );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count state minterms contains in the used cubes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCountMinterms( Gia_ManAre_t * p )
+{
+    Gia_StaAre_t * pCube;
+    unsigned * pMemory;
+    int i, nMemSize, Counter = 0;
+    if ( Gia_ManRegNum(p->pAig) > 30 )
+        return -1;
+    nMemSize = Abc_BitWordNum( 1 << Gia_ManRegNum(p->pAig) );
+    pMemory  = ABC_CALLOC( unsigned, nMemSize );
+    Gia_ManAreForEachCubeStore( p, pCube, i )
+        if ( Gia_StaIsUsed(pCube) )
+            Gia_ManCountMintermsInCube( pCube, Gia_ManRegNum(p->pAig), pMemory );
+    for ( i = 0; i < nMemSize; i++ )
+        Counter += Gia_WordCountOnes( pMemory[i] );
+    ABC_FREE( pMemory );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the TFO of one CI.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManDeriveCiTfo_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vRes )
+{
+    if ( Gia_ObjIsCi(pObj) )
+        return pObj->fMark0;
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return pObj->fMark0;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManDeriveCiTfo_rec( p, Gia_ObjFanin0(pObj), vRes );
+    Gia_ManDeriveCiTfo_rec( p, Gia_ObjFanin1(pObj), vRes );
+    pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 | Gia_ObjFanin1(pObj)->fMark0;
+    if ( pObj->fMark0 )
+        Vec_IntPush( vRes, Gia_ObjId(p, pObj) );
+    return pObj->fMark0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the TFO of one CI.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManDeriveCiTfoOne( Gia_Man_t * p, Gia_Obj_t * pPivot )
+{
+    Vec_Int_t * vRes;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( pPivot->fMark0 == 0 );
+    pPivot->fMark0 = 1;
+    vRes = Vec_IntAlloc( 100 );
+    Vec_IntPush( vRes, Gia_ObjId(p, pPivot) );
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+    Gia_ManForEachCo( p, pObj, i )
+    {
+        Gia_ManDeriveCiTfo_rec( p, Gia_ObjFanin0(pObj), vRes );
+        if ( Gia_ObjFanin0(pObj)->fMark0 )
+            Vec_IntPush( vRes, Gia_ObjId(p, pObj) );
+    }
+    pPivot->fMark0 = 0;
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the TFO of each CI.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Gia_ManDeriveCiTfo( Gia_Man_t * p )
+{
+    Vec_Ptr_t * vRes;
+    Gia_Obj_t * pPivot;
+    int i;
+    Gia_ManCleanMark0( p );
+    Gia_ManIncrementTravId( p );
+    vRes = Vec_PtrAlloc( Gia_ManCiNum(p) );
+    Gia_ManForEachCi( p, pPivot, i )
+        Vec_PtrPush( vRes, Gia_ManDeriveCiTfoOne(p, pPivot) );
+    Gia_ManCleanMark0( p );
+    return (Vec_Vec_t *)vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if states are equal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_StaAreEqual( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        if ( p1->pData[w] != p2->pData[w] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if states are disjoint.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_StaAreDisjoint( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        if ( ((p1->pData[w] ^ p2->pData[w]) >> 1) & (p1->pData[w] ^ p2->pData[w]) & 0x55555555 )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if cube p1 contains cube p2.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_StaAreContain( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        if ( (p1->pData[w] | p2->pData[w]) != p2->pData[w] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of dashes in p1 that are non-dashes in p2.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_StaAreDashNum( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords )
+{
+    int w, Counter = 0;
+    for ( w = 0; w < nWords; w++ )
+        Counter += Gia_WordCountOnes( (~(p1->pData[w] ^ (p1->pData[w] >> 1))) & (p2->pData[w] ^ (p2->pData[w] >> 1)) & 0x55555555 );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of a variable for sharping the cube.]
+
+  Description [Counts the number of variables that have dash in p1 and 
+  non-dash in p2. If there is exactly one such variable, returns its index.
+  Otherwise returns -1.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_StaAreSharpVar( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords )
+{
+    unsigned Word;
+    int w, iVar = -1;
+    for ( w = 0; w < nWords; w++ )
+    {
+        Word = (~(p1->pData[w] ^ (p1->pData[w] >> 1))) & (p2->pData[w] ^ (p2->pData[w] >> 1)) & 0x55555555;
+        if ( Word == 0 )
+            continue;
+        if ( !Gia_WordHasOneBit(Word) )
+            return -1;
+        // has exactly one bit
+        if ( iVar >= 0 )
+            return -1;
+        // the first variable of this type
+        iVar = 16 * w + Gia_WordFindFirstBit( Word ) / 2;
+    }
+    return iVar;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of a variable for merging the cubes.]
+
+  Description [If there is exactly one such variable, returns its index.
+  Otherwise returns -1.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_StaAreDisjointVar( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords )
+{
+    unsigned Word;
+    int w, iVar = -1;
+    for ( w = 0; w < nWords; w++ )
+    {
+        Word = (p1->pData[w] ^ p2->pData[w]) & ((p1->pData[w] ^ p2->pData[w]) >> 1) & 0x55555555;
+        if ( Word == 0 )
+            continue;
+        if ( !Gia_WordHasOneBit(Word) )
+            return -1;
+        // has exactly one bit
+        if ( iVar >= 0 )
+            return -1;
+        // the first variable of this type
+        iVar = 16 * w + Gia_WordFindFirstBit( Word ) / 2;
+    }
+    return iVar;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates reachability manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_ManAre_t * Gia_ManAreCreate( Gia_Man_t * pAig )
+{
+    Gia_ManAre_t * p;
+    assert( sizeof(Gia_ObjAre_t) == 16 );
+    p = ABC_CALLOC( Gia_ManAre_t, 1 );
+    p->pAig       = pAig;
+    p->nWords     = Abc_BitWordNum( 2 * Gia_ManRegNum(pAig) );
+    p->nSize      = sizeof(Gia_StaAre_t)/4 + p->nWords;
+    p->ppObjs     = ABC_CALLOC( unsigned *, MAX_PAGE_NUM );
+    p->ppStas     = ABC_CALLOC( unsigned *, MAX_PAGE_NUM );
+    p->vCiTfos    = Gia_ManDeriveCiTfo( pAig );
+    p->vCiLits    = Vec_VecDupInt( p->vCiTfos );
+    p->vCubesA    = Vec_IntAlloc( 100 );
+    p->vCubesB    = Vec_IntAlloc( 100 );
+    p->iOutFail   = -1;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes reachability manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManAreFree( Gia_ManAre_t * p )
+{
+    int i;
+    Gia_ManStop( p->pAig );
+    if ( p->pNew )
+        Gia_ManStop( p->pNew );
+    Vec_IntFree( p->vCubesA );
+    Vec_IntFree( p->vCubesB );
+    Vec_VecFree( p->vCiTfos );
+    Vec_VecFree( p->vCiLits );
+    for ( i = 0; i < p->nObjPages; i++ )
+        ABC_FREE( p->ppObjs[i] );
+    ABC_FREE( p->ppObjs );
+    for ( i = 0; i < p->nStaPages; i++ )
+        ABC_FREE( p->ppStas[i] );
+    ABC_FREE( p->ppStas );
+//    ABC_FREE( p->pfUseless );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns new object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_ObjAre_t * Gia_ManAreCreateObj( Gia_ManAre_t * p )
+{
+    if ( p->nObjs == p->nObjPages * MAX_ITEM_NUM )
+    {
+        if ( p->nObjPages == MAX_PAGE_NUM )
+        {
+            printf( "ERA manager has run out of memory after allocating 2B internal nodes.\n" );
+            return NULL;
+        }
+        p->ppObjs[p->nObjPages++] = ABC_CALLOC( unsigned, MAX_ITEM_NUM * 4 );
+        if ( p->nObjs == 0 )
+            p->nObjs = 1;
+    }
+    return Gia_ManAreObjInt( p, p->nObjs++ );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns new state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_StaAre_t * Gia_ManAreCreateSta( Gia_ManAre_t * p )
+{
+    if ( p->nStas == p->nStaPages * MAX_ITEM_NUM )
+    {
+        if ( p->nStaPages == MAX_PAGE_NUM )
+        {
+            printf( "ERA manager has run out of memory after allocating 2B state cubes.\n" );
+            return NULL;
+        }
+        if ( p->ppStas[p->nStaPages] == NULL )
+            p->ppStas[p->nStaPages] = ABC_CALLOC( unsigned, MAX_ITEM_NUM * p->nSize );
+        p->nStaPages++;
+        if ( p->nStas == 0 )
+        {
+            p->nStas = 1;
+//            p->nUselessAlloc = (1 << 18);
+//            p->pfUseless = ABC_CALLOC( unsigned, p->nUselessAlloc );
+        }
+//        if ( p->nStas == p->nUselessAlloc * 32 )
+//        {
+//            p->nUselessAlloc *= 2;
+//            p->pfUseless = ABC_REALLOC( unsigned, p->pfUseless, p->nUselessAlloc );
+//            memset( p->pfUseless + p->nUselessAlloc/2, 0, sizeof(unsigned) * p->nUselessAlloc/2 );
+//        }
+    }
+    return Gia_ManAreStaInt( p, p->nStas++ );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles new state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManAreRycycleSta( Gia_ManAre_t * p, Gia_StaAre_t * pSta )
+{
+    memset( pSta, 0, p->nSize << 2 );
+    if ( pSta == Gia_ManAreStaLast(p) )
+    {
+        p->nStas--;
+        if ( p->nStas == (p->nStaPages-1) * MAX_ITEM_NUM )
+            p->nStaPages--;
+    }
+    else
+    {
+//        Gia_StaSetUnused( pSta );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates new state state from the latch values.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_StaAre_t * Gia_ManAreCreateStaNew( Gia_ManAre_t * p )
+{
+    Gia_StaAre_t * pSta;
+    Gia_Obj_t * pObj;
+    int i;
+    pSta = Gia_ManAreCreateSta( p );
+    Gia_ManForEachRi( p->pAig, pObj, i )
+    {
+        if ( pObj->Value == 0 )
+            Gia_StaSetValue0( pSta, i );
+        else if ( pObj->Value == 1 )
+            Gia_StaSetValue1( pSta, i );
+    }
+    return pSta;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates new state state with latch init values.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_StaAre_t * Gia_ManAreCreateStaInit( Gia_ManAre_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachRi( p->pAig, pObj, i )
+        pObj->Value = 0;
+    return Gia_ManAreCreateStaNew( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the state cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManArePrintCube( Gia_ManAre_t * p, Gia_StaAre_t * pSta )
+{
+    Gia_Obj_t * pObj;
+    int i, Count0 = 0, Count1 = 0, Count2 = 0;
+    printf( "%4d %4d :  ", p->iStaCur, p->nStas-1 );
+    printf( "Prev %4d   ", Gia_Ptr2Int(pSta->iPrev) );
+    printf( "%p   ", pSta );
+    Gia_ManForEachRi( p->pAig, pObj, i )
+    {
+        if ( Gia_StaHasValue0(pSta, i) )
+            printf( "0" ), Count0++;
+        else if ( Gia_StaHasValue1(pSta, i) )
+            printf( "1" ), Count1++;
+        else
+            printf( "-" ), Count2++;
+    }
+    printf( "  0 =%3d", Count0 );
+    printf( "  1 =%3d", Count1 );
+    printf( "  - =%3d", Count2 );
+    printf( "\n" );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Counts the depth of state transitions leading ot this state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManAreDepth( Gia_ManAre_t * p, int iState )
+{
+    Gia_StaAre_t * pSta;
+    int Counter = 0;
+    for ( pSta = Gia_ManAreStaInt(p, iState); Gia_StaIsGood(p, pSta); pSta = Gia_StaPrev(p, pSta) )
+        Counter++;
+    return Counter;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of cubes in the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManAreListCountListUsed( Gia_ManAre_t * p, Gia_PtrAre_t Root )
+{
+    Gia_StaAre_t * pCube;
+    int Counter = 0;
+    Gia_ManAreForEachCubeList( p, Gia_ManAreSta(p, Root), pCube )
+        Counter += Gia_StaIsUsed(pCube);
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of used cubes in the tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManAreListCountUsed_rec( Gia_ManAre_t * p, Gia_PtrAre_t Root, int fTree )
+{
+    Gia_ObjAre_t * pObj;
+    if ( !fTree )
+        return Gia_ManAreListCountListUsed( p, Root );
+    pObj = Gia_ManAreObj(p, Root);
+    return Gia_ManAreListCountUsed_rec( p, pObj->F[0], Gia_ObjHasBranch0(pObj) ) +
+           Gia_ManAreListCountUsed_rec( p, pObj->F[1], Gia_ObjHasBranch1(pObj) ) +
+           Gia_ManAreListCountUsed_rec( p, pObj->F[2], Gia_ObjHasBranch2(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of used cubes in the tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManAreListCountUsed( Gia_ManAre_t * p )
+{
+    return Gia_ManAreListCountUsed_rec( p, p->Root, p->fTree );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints used cubes in the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManArePrintListUsed( Gia_ManAre_t * p, Gia_PtrAre_t Root )
+{
+    Gia_StaAre_t * pCube;
+    Gia_ManAreForEachCubeList( p, Gia_ManAreSta(p, Root), pCube )
+        if ( Gia_StaIsUsed(pCube) )
+            Gia_ManArePrintCube( p, pCube );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints used cubes in the tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManArePrintUsed_rec( Gia_ManAre_t * p, Gia_PtrAre_t Root, int fTree )
+{
+    Gia_ObjAre_t * pObj;
+    if ( !fTree )
+        return Gia_ManArePrintListUsed( p, Root );
+    pObj = Gia_ManAreObj(p, Root);
+    return Gia_ManArePrintUsed_rec( p, pObj->F[0], Gia_ObjHasBranch0(pObj) ) +
+           Gia_ManArePrintUsed_rec( p, pObj->F[1], Gia_ObjHasBranch1(pObj) ) +
+           Gia_ManArePrintUsed_rec( p, pObj->F[2], Gia_ObjHasBranch2(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints used cubes in the tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManArePrintUsed( Gia_ManAre_t * p )
+{
+    return Gia_ManArePrintUsed_rec( p, p->Root, p->fTree );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Best var has max weight.]
+
+  Description [Weight is defined as the number of 0/1-lits minus the 
+  absolute value of the diff between the number of 0-lits and 1-lits.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManAreFindBestVar( Gia_ManAre_t * p, Gia_PtrAre_t List )
+{
+    Gia_StaAre_t * pCube;
+    int Count0, Count1, Count2;
+    int iVarThis, iVarBest = -1, WeightThis, WeightBest = -1;
+    for ( iVarThis = 0; iVarThis < Gia_ManRegNum(p->pAig); iVarThis++ )
+    {
+        Count0 = Count1 = Count2 = 0;
+        Gia_ManAreForEachCubeList( p, Gia_ManAreSta(p, List), pCube )
+        {
+            if ( Gia_StaIsUnused(pCube) )
+                continue;
+            if ( Gia_StaHasValue0(pCube, iVarThis) )
+                Count0++;
+            else if ( Gia_StaHasValue1(pCube, iVarThis) )
+                Count1++;
+            else
+                Count2++;
+        }
+//        printf( "%4d : %5d  %5d  %5d   Weight = %5d\n", iVarThis, Count0, Count1, Count2, 
+//            Count0 + Count1 - (Count0 > Count1 ? Count0 - Count1 : Count1 - Count0) );
+        if ( (!Count0 && !Count1) || (!Count0 && !Count2) || (!Count1 && !Count2) )
+            continue;
+        WeightThis = Count0 + Count1 - (Count0 > Count1 ? Count0 - Count1 : Count1 - Count0);
+        if ( WeightBest < WeightThis ) 
+        {
+            WeightBest = WeightThis;
+            iVarBest = iVarThis;
+        }
+    }
+    if ( iVarBest == -1 )
+    {
+        Gia_ManArePrintListUsed( p, List );
+        printf( "Error: Best variable not found!!!\n" );
+    }
+    assert( iVarBest != -1 );
+    return iVarBest;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Rebalances the tree when cubes exceed the limit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManAreRebalance( Gia_ManAre_t * p, Gia_PtrAre_t * pRoot )
+{
+    Gia_ObjAre_t * pNode;
+    Gia_StaAre_t * pCube;
+    Gia_PtrAre_t iCube, iNext;
+    assert( pRoot->nItem || pRoot->nPage );
+    pNode = Gia_ManAreCreateObj( p );
+    pNode->iVar = Gia_ManAreFindBestVar( p, *pRoot );
+    for ( iCube = *pRoot, pCube = Gia_ManAreSta(p, iCube), iNext = pCube->iNext; 
+          Gia_StaIsGood(p, pCube); 
+          iCube = iNext,  pCube = Gia_ManAreSta(p, iCube), iNext = pCube->iNext )
+    {
+        if ( Gia_StaIsUnused(pCube) )
+            continue;
+        if ( Gia_StaHasValue0(pCube, pNode->iVar) )
+            pCube->iNext = pNode->F[0], pNode->F[0] = iCube, pNode->nStas0++;
+        else if ( Gia_StaHasValue1(pCube, pNode->iVar) )
+            pCube->iNext = pNode->F[1], pNode->F[1] = iCube, pNode->nStas1++;
+        else
+            pCube->iNext = pNode->F[2], pNode->F[2] = iCube, pNode->nStas2++;
+    }
+    *pRoot = Gia_Int2Ptr(p->nObjs - 1);
+    assert( pNode == Gia_ManAreObj(p, *pRoot) );
+    p->fTree = 1;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Compresses the list by removing unused cubes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManAreCompress( Gia_ManAre_t * p, Gia_PtrAre_t * pRoot )
+{
+    Gia_StaAre_t * pCube;
+    Gia_PtrAre_t iList = *pRoot;
+    Gia_PtrAre_t iCube, iNext;
+    assert( pRoot->nItem || pRoot->nPage );
+    pRoot->nItem = 0; 
+    pRoot->nPage = 0;
+    for ( iCube = iList, pCube = Gia_ManAreSta(p, iCube), iNext = pCube->iNext; 
+          Gia_StaIsGood(p, pCube); 
+          iCube = iNext, pCube = Gia_ManAreSta(p, iCube), iNext = pCube->iNext )
+    {
+        if ( Gia_StaIsUnused(pCube) )
+            continue;
+        pCube->iNext = *pRoot;
+        *pRoot = iCube;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the state exists in the list.]
+
+  Description [The state may be sharped.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManAreCubeCheckList( Gia_ManAre_t * p, Gia_PtrAre_t * pRoot, Gia_StaAre_t * pSta )
+{
+    int fVerbose = 0;
+    Gia_StaAre_t * pCube;
+    int iVar;
+if ( fVerbose )
+{
+printf( "Trying cube: " );
+Gia_ManArePrintCube( p, pSta );
+}
+    Gia_ManAreForEachCubeList( p, Gia_ManAreSta(p, *pRoot), pCube )
+    {
+        p->nChecks++;
+        if ( Gia_StaIsUnused( pCube ) )
+            continue;
+        if ( Gia_StaAreDisjoint( pSta, pCube, p->nWords ) )
+            continue;
+        if ( Gia_StaAreContain( pCube, pSta, p->nWords ) )
+        {
+if ( fVerbose )
+{
+printf( "Contained in " );
+Gia_ManArePrintCube( p, pCube );
+}
+            Gia_ManAreRycycleSta( p, pSta );
+            return 0;
+        }
+        if ( Gia_StaAreContain( pSta, pCube, p->nWords ) )
+        {
+if ( fVerbose )
+{
+printf( "Contains     " );
+Gia_ManArePrintCube( p, pCube );
+}
+            Gia_StaSetUnused( pCube );
+            continue;
+        }
+        iVar = Gia_StaAreSharpVar( pSta, pCube, p->nWords );
+        if ( iVar == -1 )
+            continue;
+if ( fVerbose )
+{
+printf( "Sharped by   " );
+Gia_ManArePrintCube( p, pCube );
+Gia_ManArePrintCube( p, pSta );
+}
+//        printf( "%d  %d\n", Gia_StaAreDashNum( pSta, pCube, p->nWords ), Gia_StaAreSharpVar( pSta, pCube, p->nWords ) );
+        assert( !Gia_StaHasValue0(pSta, iVar) && !Gia_StaHasValue1(pSta, iVar) );
+        assert(  Gia_StaHasValue0(pCube, iVar) ^  Gia_StaHasValue1(pCube, iVar) );
+        if ( Gia_StaHasValue0(pCube, iVar) )
+            Gia_StaSetValue1( pSta, iVar );
+        else
+            Gia_StaSetValue0( pSta, iVar );
+//        return Gia_ManAreCubeCheckList( p, pRoot, pSta );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds new state to the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManAreCubeAddToList( Gia_ManAre_t * p, Gia_PtrAre_t * pRoot, Gia_StaAre_t * pSta )
+{
+    int fVerbose = 0;
+    pSta->iNext = *pRoot;
+    *pRoot = Gia_Int2Ptr( p->nStas - 1 );
+    assert( pSta == Gia_ManAreSta(p, *pRoot) );
+if ( fVerbose )
+{
+printf( "Adding cube: " );
+Gia_ManArePrintCube( p, pSta );
+//printf( "\n" );
+}
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Checks if the cube like this exists in the tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManAreCubeCheckTree_rec( Gia_ManAre_t * p, Gia_ObjAre_t * pObj, Gia_StaAre_t * pSta )
+{
+    int RetValue;
+    if ( Gia_StaHasValue0(pSta, pObj->iVar) )
+    {
+        if ( Gia_ObjHasBranch0(pObj) )
+            RetValue = Gia_ManAreCubeCheckTree_rec( p, Gia_ObjNextObj0(p, pObj), pSta );
+        else
+            RetValue = Gia_ManAreCubeCheckList( p, pObj->F, pSta );
+        if ( RetValue == 0 )
+            return 0;
+    }
+    else if ( Gia_StaHasValue1(pSta, pObj->iVar) )
+    {
+        if ( Gia_ObjHasBranch1(pObj) )
+            RetValue = Gia_ManAreCubeCheckTree_rec( p, Gia_ObjNextObj1(p, pObj), pSta );
+        else
+            RetValue = Gia_ManAreCubeCheckList( p, pObj->F + 1, pSta );
+        if ( RetValue == 0 )
+            return 0;
+    }
+    if ( Gia_ObjHasBranch2(pObj) )
+        return Gia_ManAreCubeCheckTree_rec( p, Gia_ObjNextObj2(p, pObj), pSta );
+    return Gia_ManAreCubeCheckList( p, pObj->F + 2, pSta );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds new cube to the tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManAreCubeAddToTree_rec( Gia_ManAre_t * p, Gia_ObjAre_t * pObj, Gia_StaAre_t * pSta )
+{
+    if ( Gia_StaHasValue0(pSta, pObj->iVar) )
+    {
+        if ( Gia_ObjHasBranch0(pObj) )
+            Gia_ManAreCubeAddToTree_rec( p, Gia_ObjNextObj0(p, pObj), pSta );
+        else
+        {
+            Gia_ManAreCubeAddToList( p, pObj->F, pSta );
+            if ( ++pObj->nStas0 == MAX_CUBE_NUM )
+            {
+                pObj->nStas0 = Gia_ManAreListCountListUsed( p, pObj->F[0] );
+                if ( pObj->nStas0 < MAX_CUBE_NUM/2 )
+                    Gia_ManAreCompress( p, pObj->F );
+                else
+                {
+                    Gia_ManAreRebalance( p, pObj->F );
+                    pObj->nStas0 = 0;
+                }
+            }
+        }
+    }
+    else if ( Gia_StaHasValue1(pSta, pObj->iVar) )
+    {
+        if ( Gia_ObjHasBranch1(pObj) )
+            Gia_ManAreCubeAddToTree_rec( p, Gia_ObjNextObj1(p, pObj), pSta );
+        else
+        {
+            Gia_ManAreCubeAddToList( p, pObj->F+1, pSta );
+            if ( ++pObj->nStas1 == MAX_CUBE_NUM )
+            {
+                pObj->nStas1 = Gia_ManAreListCountListUsed( p, pObj->F[1] );
+                if ( pObj->nStas1 < MAX_CUBE_NUM/2 )
+                    Gia_ManAreCompress( p, pObj->F+1 );
+                else
+                {
+                    Gia_ManAreRebalance( p, pObj->F+1 );
+                    pObj->nStas1 = 0;
+                }
+            }
+        }
+    }
+    else
+    {
+        if ( Gia_ObjHasBranch2(pObj) )
+            Gia_ManAreCubeAddToTree_rec( p, Gia_ObjNextObj2(p, pObj), pSta );
+        else
+        {
+            Gia_ManAreCubeAddToList( p, pObj->F+2, pSta );
+            if ( ++pObj->nStas2 == MAX_CUBE_NUM )
+            {
+                pObj->nStas2 = Gia_ManAreListCountListUsed( p, pObj->F[2] );
+                if ( pObj->nStas2 < MAX_CUBE_NUM/2 )
+                    Gia_ManAreCompress( p, pObj->F+2 );
+                else
+                {
+                    Gia_ManAreRebalance( p, pObj->F+2 );
+                    pObj->nStas2 = 0;
+                }
+            }
+        }
+    }
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects overlapping cubes in the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManAreCubeCollectList( Gia_ManAre_t * p, Gia_PtrAre_t * pRoot, Gia_StaAre_t * pSta )
+{
+    Gia_StaAre_t * pCube;
+    int iCube;
+    Gia_ManAreForEachCubeList2( p, *pRoot, pCube, iCube )
+    {
+        if ( Gia_StaIsUnused( pCube ) )
+            continue;
+        if ( Gia_StaAreDisjoint( pSta, pCube, p->nWords ) )
+        {
+/*
+            int iVar;
+            p->nDisjs++;
+            iVar = Gia_StaAreDisjointVar( pSta, pCube, p->nWords );
+            if ( iVar >= 0 )
+            {
+                p->nDisjs2++;
+                if ( iCube > p->iStaCur )
+                    p->nDisjs3++;
+            }
+*/
+            continue;
+        }
+//        p->nCompares++;
+//        p->nEquals += Gia_StaAreEqual( pSta, pCube, p->nWords );
+        if ( iCube <= p->iStaCur )
+            Vec_IntPush( p->vCubesA, iCube );
+        else
+            Vec_IntPush( p->vCubesB, iCube );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects overlapping cubes in the tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManAreCubeCollectTree_rec( Gia_ManAre_t * p, Gia_ObjAre_t * pObj, Gia_StaAre_t * pSta )
+{
+    int RetValue;
+    if ( Gia_StaHasValue0(pSta, pObj->iVar) )
+    {
+        if ( Gia_ObjHasBranch0(pObj) )
+            RetValue = Gia_ManAreCubeCollectTree_rec( p, Gia_ObjNextObj0(p, pObj), pSta );
+        else
+            RetValue = Gia_ManAreCubeCollectList( p, pObj->F, pSta );
+        if ( RetValue == 0 )
+            return 0;
+    }
+    else if ( Gia_StaHasValue1(pSta, pObj->iVar) )
+    {
+        if ( Gia_ObjHasBranch1(pObj) )
+            RetValue = Gia_ManAreCubeCollectTree_rec( p, Gia_ObjNextObj1(p, pObj), pSta );
+        else
+            RetValue = Gia_ManAreCubeCollectList( p, pObj->F + 1, pSta );
+        if ( RetValue == 0 )
+            return 0;
+    }
+    if ( Gia_ObjHasBranch2(pObj) )
+        return Gia_ManAreCubeCollectTree_rec( p, Gia_ObjNextObj2(p, pObj), pSta );
+    return Gia_ManAreCubeCollectList( p, pObj->F + 2, pSta );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Checks if the cube like this exists in the tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManAreCubeCheckTree( Gia_ManAre_t * p, Gia_StaAre_t * pSta )
+{
+    Gia_StaAre_t * pCube;
+    int i, iVar;
+    assert( p->fTree );
+    Vec_IntClear( p->vCubesA );
+    Vec_IntClear( p->vCubesB );
+    Gia_ManAreCubeCollectTree_rec( p, Gia_ManAreObj(p, p->Root), pSta );
+//    if ( p->nStas > 3000 )
+//        printf( "%d %d  \n", Vec_IntSize(p->vCubesA), Vec_IntSize(p->vCubesB) );
+//    Vec_IntSort( p->vCubesA, 0 );
+//    Vec_IntSort( p->vCubesB, 0 );
+    Gia_ManAreForEachCubeVec( p->vCubesA, p, pCube, i )
+    {
+        if ( Gia_StaIsUnused( pCube ) )
+            continue;
+        if ( Gia_StaAreDisjoint( pSta, pCube, p->nWords ) )
+            continue;
+        if ( Gia_StaAreContain( pCube, pSta, p->nWords ) )
+        {
+            Gia_ManAreRycycleSta( p, pSta );
+            return 0;
+        }
+        if ( Gia_StaAreContain( pSta, pCube, p->nWords ) )
+        {
+            Gia_StaSetUnused( pCube );
+            continue;
+        }
+        iVar = Gia_StaAreSharpVar( pSta, pCube, p->nWords );
+        if ( iVar == -1 )
+            continue;
+        assert( !Gia_StaHasValue0(pSta, iVar) && !Gia_StaHasValue1(pSta, iVar) );
+        assert(  Gia_StaHasValue0(pCube, iVar) ^  Gia_StaHasValue1(pCube, iVar) );
+        if ( Gia_StaHasValue0(pCube, iVar) )
+            Gia_StaSetValue1( pSta, iVar );
+        else
+            Gia_StaSetValue0( pSta, iVar );
+        return Gia_ManAreCubeCheckTree( p, pSta );
+    }
+    Gia_ManAreForEachCubeVec( p->vCubesB, p, pCube, i )
+    {
+        if ( Gia_StaIsUnused( pCube ) )
+            continue;
+        if ( Gia_StaAreDisjoint( pSta, pCube, p->nWords ) )
+            continue;
+        if ( Gia_StaAreContain( pCube, pSta, p->nWords ) )
+        {
+            Gia_ManAreRycycleSta( p, pSta );
+            return 0;
+        }
+        if ( Gia_StaAreContain( pSta, pCube, p->nWords ) )
+        {
+            Gia_StaSetUnused( pCube );
+            continue;
+        }
+        iVar = Gia_StaAreSharpVar( pSta, pCube, p->nWords );
+        if ( iVar == -1 )
+            continue;
+        assert( !Gia_StaHasValue0(pSta, iVar) && !Gia_StaHasValue1(pSta, iVar) );
+        assert(  Gia_StaHasValue0(pCube, iVar) ^  Gia_StaHasValue1(pCube, iVar) );
+        if ( Gia_StaHasValue0(pCube, iVar) )
+            Gia_StaSetValue1( pSta, iVar );
+        else
+            Gia_StaSetValue0( pSta, iVar );
+        return Gia_ManAreCubeCheckTree( p, pSta );
+    }
+/*
+    if ( p->nStas > 3000 )
+    {
+printf( "Trying cube:       " );
+Gia_ManArePrintCube( p, pSta );
+    Gia_ManAreForEachCubeVec( p->vCubesA, p, pCube, i )
+    {
+printf( "aaaaaaaaaaaa %5d ", Vec_IntEntry(p->vCubesA,i) );
+Gia_ManArePrintCube( p, pCube );
+    }
+    Gia_ManAreForEachCubeVec( p->vCubesB, p, pCube, i )
+    {
+printf( "bbbbbbbbbbbb %5d ", Vec_IntEntry(p->vCubesB,i) );
+Gia_ManArePrintCube( p, pCube );
+    }
+    }
+*/
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Processes the new cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManAreCubeProcess( Gia_ManAre_t * p, Gia_StaAre_t * pSta )
+{
+    int RetValue;
+    p->nChecks = 0;
+    if ( !p->fTree && p->nStas == MAX_CUBE_NUM )
+        Gia_ManAreRebalance( p, &p->Root );
+    if ( p->fTree )
+    {
+//        RetValue = Gia_ManAreCubeCheckTree_rec( p, Gia_ManAreObj(p, p->Root), pSta );
+        RetValue = Gia_ManAreCubeCheckTree( p, pSta );
+        if ( RetValue )
+            Gia_ManAreCubeAddToTree_rec( p, Gia_ManAreObj(p, p->Root), pSta );
+    }
+    else
+    {
+        RetValue = Gia_ManAreCubeCheckList( p, &p->Root, pSta );
+        if ( RetValue )
+            Gia_ManAreCubeAddToList( p, &p->Root, pSta );
+    }
+//    printf( "%d ", p->nChecks );
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the most used CI, or NULL if condition is met.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManAreMostUsedPi_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+    {
+        pObj->Value++;
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManAreMostUsedPi_rec( p, Gia_ObjFanin0(pObj) );
+    Gia_ManAreMostUsedPi_rec( p, Gia_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the most used CI, or NULL if condition is met.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Gia_ManAreMostUsedPi( Gia_ManAre_t * p )
+{
+    Gia_Obj_t * pObj, * pObjMax = NULL;
+    int i;
+    // clean CI counters
+    Gia_ManForEachCi( p->pNew, pObj, i )
+        pObj->Value = 0;
+    // traverse from each register output
+    Gia_ManForEachRi( p->pAig, pObj, i )
+    {
+        if ( pObj->Value <= 1 )
+            continue;
+        Gia_ManIncrementTravId( p->pNew );
+        Gia_ManAreMostUsedPi_rec( p->pNew, Gia_ManObj(p->pNew, Abc_Lit2Var(pObj->Value)) );
+    }
+    // check the CI counters
+    Gia_ManForEachCi( p->pNew, pObj, i )
+        if ( pObjMax == NULL || pObjMax->Value < pObj->Value )
+            pObjMax = pObj;
+    // return the result
+    return pObjMax->Value > 1 ? pObjMax : NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts maximum support of primary outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCheckPOs_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return 0;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+        return 1;
+    assert( Gia_ObjIsAnd(pObj) );
+    return Gia_ManCheckPOs_rec( p, Gia_ObjFanin0(pObj) ) +
+           Gia_ManCheckPOs_rec( p, Gia_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts maximum support of primary outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManCheckPOs( Gia_ManAre_t * p )
+{
+    Gia_Obj_t * pObj, * pObjNew;
+    int i, CountCur, CountMax = 0;
+    Gia_ManForEachPo( p->pAig, pObj, i )
+    {
+        pObjNew = Gia_ManObj( p->pNew, Abc_Lit2Var(pObj->Value) );
+        if ( Gia_ObjIsConst0(pObjNew) )
+            CountCur = 0;
+        else 
+        {
+            Gia_ManIncrementTravId( p->pNew );
+            CountCur = Gia_ManCheckPOs_rec( p->pNew, pObjNew );
+        }
+        CountMax = Abc_MaxInt( CountMax, CountCur );
+    }
+    return CountMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the status of the primary outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManCheckPOstatus( Gia_ManAre_t * p )
+{
+    Gia_Obj_t * pObj, * pObjNew;
+    int i;
+    Gia_ManForEachPo( p->pAig, pObj, i )
+    {
+        pObjNew = Gia_ManObj( p->pNew, Abc_Lit2Var(pObj->Value) );
+        if ( Gia_ObjIsConst0(pObjNew) )
+        {
+            if ( Abc_LitIsCompl(pObj->Value) )
+            {
+                p->iOutFail = i;
+                return 1;
+            }
+        }
+        else 
+        {
+            p->iOutFail = i;
+//            printf( "To fix later:  PO may be assertable.\n" );
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives next state cubes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManAreDeriveNexts_rec( Gia_ManAre_t * p, Gia_PtrAre_t Sta )
+{
+    Gia_Obj_t * pPivot;
+    Vec_Int_t * vLits, * vTfos;
+    Gia_Obj_t * pObj;
+    int i;
+    abctime clk;
+    if ( ++p->nRecCalls == MAX_CALL_NUM )
+        return 0;
+    if ( (pPivot = Gia_ManAreMostUsedPi(p)) == NULL )
+    {
+        Gia_StaAre_t * pNew;
+        clk = Abc_Clock();
+        pNew = Gia_ManAreCreateStaNew( p );
+        pNew->iPrev = Sta;
+        p->fStopped = (p->fMiter && (Gia_ManCheckPOstatus(p) & 1));
+        if ( p->fStopped )
+        {
+            assert( p->pTarget == NULL );
+            p->pTarget = pNew;
+            return 1;
+        }
+        Gia_ManAreCubeProcess( p, pNew );
+        p->timeCube += Abc_Clock() - clk;
+        return p->fStopped;
+    }
+    // remember values in the cone and perform update
+    vTfos = Vec_VecEntryInt( p->vCiTfos, Gia_ObjCioId(pPivot) );
+    vLits = Vec_VecEntryInt( p->vCiLits, Gia_ObjCioId(pPivot) );
+    assert( Vec_IntSize(vTfos) == Vec_IntSize(vLits) );
+    Gia_ManForEachObjVec( vTfos, p->pAig, pObj, i )
+    {
+        Vec_IntWriteEntry( vLits, i, pObj->Value );
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Gia_ManHashAnd( p->pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Gia_ObjFanin0Copy(pObj);
+        else 
+        {
+            assert( Gia_ObjIsCi(pObj) );
+            pObj->Value = 0;
+        }
+    }
+    if ( Gia_ManAreDeriveNexts_rec( p, Sta ) )
+        return 1;
+    // compute different values
+    Gia_ManForEachObjVec( vTfos, p->pAig, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Gia_ManHashAnd( p->pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Gia_ObjFanin0Copy(pObj);
+        else 
+        {
+            assert( Gia_ObjIsCi(pObj) );
+            pObj->Value = 1;
+        }
+    }
+    if ( Gia_ManAreDeriveNexts_rec( p, Sta ) )
+        return 1;
+    // reset the original values
+    Gia_ManForEachObjVec( vTfos, p->pAig, pObj, i )
+        pObj->Value = Vec_IntEntry( vLits, i );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives next state cubes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManAreDeriveNexts( Gia_ManAre_t * p, Gia_PtrAre_t Sta )
+{
+    Gia_StaAre_t * pSta;
+    Gia_Obj_t * pObj;
+    int i, RetValue;
+    abctime clk = Abc_Clock();
+    pSta = Gia_ManAreSta( p, Sta );
+    if ( Gia_StaIsUnused(pSta) )
+        return 0;
+    // recycle the manager
+    if ( p->pNew && Gia_ManObjNum(p->pNew) > 1000000 )
+    {
+        Gia_ManStop( p->pNew );
+        p->pNew = NULL;
+    }
+    // allocate the manager
+    if ( p->pNew == NULL )
+    {
+        p->pNew = Gia_ManStart( 10 * Gia_ManObjNum(p->pAig) );
+        Gia_ManIncrementTravId( p->pNew );
+        Gia_ManHashAlloc( p->pNew );
+        Gia_ManConst0(p->pAig)->Value = 0;
+        Gia_ManForEachCi( p->pAig, pObj, i )
+            pObj->Value = Gia_ManAppendCi(p->pNew);
+    }
+    Gia_ManForEachRo( p->pAig, pObj, i )
+    {
+        if ( Gia_StaHasValue0( pSta, i ) )
+            pObj->Value = 0;
+        else if ( Gia_StaHasValue1( pSta, i ) )
+            pObj->Value = 1;
+        else // don't-care literal
+            pObj->Value = Abc_Var2Lit( Gia_ObjId( p->pNew, Gia_ManCi(p->pNew, Gia_ObjCioId(pObj)) ), 0 );
+    }
+    Gia_ManForEachAnd( p->pAig, pObj, i )
+        pObj->Value = Gia_ManHashAnd( p->pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachCo( p->pAig, pObj, i )
+        pObj->Value = Gia_ObjFanin0Copy(pObj);
+
+    // perform case-splitting
+    p->nRecCalls = 0;
+    RetValue = Gia_ManAreDeriveNexts_rec( p, Sta );
+    if ( p->nRecCalls >= MAX_CALL_NUM )
+    {
+        printf( "Exceeded the limit on the number of transitions from a state cube (%d).\n", MAX_CALL_NUM );
+        p->fStopped = 1;
+    }
+//    printf( "%d ", p->nRecCalls );
+//printf( "%d ", Gia_ManObjNum(p->pNew) );
+    p->timeAig += Abc_Clock() - clk;
+    return RetValue;
+}
+
+ 
+/**Function*************************************************************
+
+  Synopsis    [Prints the report]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManArePrintReport( Gia_ManAre_t * p, abctime Time, int fFinal )
+{
+    printf( "States =%10d. Reached =%10d. R = %5.3f. Depth =%6d. Mem =%9.2f MB.  ", 
+        p->iStaCur, p->nStas, 1.0*p->iStaCur/p->nStas, Gia_ManAreDepth(p, p->iStaCur), 
+        (sizeof(Gia_ManAre_t) + 4.0*Gia_ManRegNum(p->pAig) + 8.0*MAX_PAGE_NUM + 
+         4.0*p->nStaPages*p->nSize*MAX_ITEM_NUM + 16.0*p->nObjPages*MAX_ITEM_NUM)/(1<<20) );
+    if ( fFinal )
+    {
+        ABC_PRT( "Time", Abc_Clock() - Time );
+    }
+    else
+    {
+        ABC_PRTr( "Time", Abc_Clock() - Time );
+    }
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Performs explicit reachability.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManArePerform( Gia_Man_t * pAig, int nStatesMax, int fMiter, int fVerbose )
+{
+//    extern Gia_Man_t * Gia_ManCompress2( Gia_Man_t * p, int fUpdateLevel, int fVerbose );
+    extern Abc_Cex_t * Gia_ManAreDeriveCex( Gia_ManAre_t * p, Gia_StaAre_t * pLast );
+    Gia_ManAre_t * p;
+    abctime clk = Abc_Clock();
+    int RetValue = 1;
+    if ( Gia_ManRegNum(pAig) > MAX_VARS_NUM )
+    {
+        printf( "Currently can only handle circuit with up to %d registers.\n", MAX_VARS_NUM );
+        return -1;
+    }
+    ABC_FREE( pAig->pCexSeq );
+//    p = Gia_ManAreCreate( Gia_ManCompress2(pAig, 0, 0) );
+    p = Gia_ManAreCreate( Gia_ManDup(pAig) );
+    p->fMiter = fMiter;
+    Gia_ManAreCubeProcess( p, Gia_ManAreCreateStaInit(p) );
+    for ( p->iStaCur = 1; p->iStaCur < p->nStas; p->iStaCur++ )
+    {
+//        printf( "Explored state %d. Total cubes %d.\n", p->iStaCur, p->nStas-1 );
+        if ( Gia_ManAreDeriveNexts( p, Gia_Int2Ptr(p->iStaCur) ) || p->nStas > nStatesMax )
+            pAig->pCexSeq = Gia_ManAreDeriveCex( p, p->pTarget );
+        if ( p->fStopped )
+        {
+            RetValue = -1;
+            break;
+        }
+        if ( fVerbose )//&& p->iStaCur % 5000 == 0 )
+            Gia_ManArePrintReport( p, clk, 0 );
+    }
+    Gia_ManArePrintReport( p, clk, 1 );
+    printf( "%s after finding %d state cubes (%d not contained) with depth %d.  ", 
+        p->fStopped ? "Stopped" : "Completed", 
+        p->nStas, Gia_ManAreListCountUsed(p), 
+        Gia_ManAreDepth(p, p->iStaCur-1) );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    if ( pAig->pCexSeq != NULL )
+        Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.\n", 
+            p->iStaCur, pAig->pName, Gia_ManAreDepth(p, p->iStaCur)-1 );
+    if ( fVerbose )
+    {
+        ABC_PRTP( "Cofactoring", p->timeAig - p->timeCube,    Abc_Clock() - clk );
+        ABC_PRTP( "Containment", p->timeCube,                 Abc_Clock() - clk );
+        ABC_PRTP( "Other      ", Abc_Clock() - clk - p->timeAig,  Abc_Clock() - clk );
+        ABC_PRTP( "TOTAL      ", Abc_Clock() - clk,               Abc_Clock() - clk );
+    }
+    if ( Gia_ManRegNum(pAig) <= 30 )
+    {
+        clk = Abc_Clock();
+        printf( "The number of unique state minterms in computed state cubes is %d.   ", Gia_ManCountMinterms(p) );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+//    printf( "Compares = %d.  Equals = %d.  Disj = %d.  Disj2 = %d.  Disj3 = %d.\n", 
+//        p->nCompares, p->nEquals, p->nDisjs, p->nDisjs2, p->nDisjs3 );
+//    Gia_ManAreFindBestVar( p, Gia_ManAreSta(p, p->Root) );
+//    Gia_ManArePrintUsed( p );
+    Gia_ManAreFree( p );
+    // verify
+    if ( pAig->pCexSeq )
+    {
+        if ( !Gia_ManVerifyCex( pAig, pAig->pCexSeq, 0 ) )
+            printf( "Generated counter-example is INVALID.                       \n" );
+        else
+            printf( "Generated counter-example verified correctly.               \n" );
+        return 0;
+    }
+    return RetValue;
+}
+
+ABC_NAMESPACE_IMPL_END
+
+#include "giaAig.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManAreDeriveCexSatStart( Gia_ManAre_t * p )
+{
+    Aig_Man_t * pAig2;
+    Cnf_Dat_t * pCnf;
+    assert( p->pSat == NULL );
+    pAig2 = Gia_ManToAig( p->pAig, 0 );
+    Aig_ManSetRegNum( pAig2, 0 );
+    pCnf = Cnf_Derive( pAig2, Gia_ManCoNum(p->pAig) );
+    p->pSat = Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+    p->vSatNumCis = Cnf_DataCollectCiSatNums( pCnf, pAig2 );
+    p->vSatNumCos = Cnf_DataCollectCoSatNums( pCnf, pAig2 );
+    Cnf_DataFree( pCnf );
+    Aig_ManStop( pAig2 );
+    p->vAssumps = Vec_IntAlloc( 100 );
+    p->vCofVars = Vec_IntAlloc( 100 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManAreDeriveCexSatStop( Gia_ManAre_t * p )
+{
+    assert( p->pSat != NULL );
+    assert( p->pTarget != NULL );
+    sat_solver_delete( (sat_solver *)p->pSat );
+    Vec_IntFree( p->vSatNumCis );
+    Vec_IntFree( p->vSatNumCos );
+    Vec_IntFree( p->vAssumps );
+    Vec_IntFree( p->vCofVars );
+    p->pTarget = NULL;
+    p->pSat = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes satisfying assignment in one timeframe.]
+
+  Description [Returns the vector of integers represeting PIO ids
+  of the primary inputs that should be 1 in the counter-example.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManAreDeriveCexSat( Gia_ManAre_t * p, Gia_StaAre_t * pCur, Gia_StaAre_t * pNext, int iOutFailed )
+{
+    int i, status;
+    // make assuptions
+    Vec_IntClear( p->vAssumps );
+    for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ )
+    {
+        if ( Gia_StaHasValue0(pCur, i) )
+            Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i), 1 ) );
+        else if ( Gia_StaHasValue1(pCur, i) )
+            Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i), 0 ) );
+    }
+    if ( pNext )
+    for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ )
+    {
+        if ( Gia_StaHasValue0(pNext, i) )
+            Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCos, Gia_ManPoNum(p->pAig)+i), 1 ) );
+        else if ( Gia_StaHasValue1(pNext, i) )
+            Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCos, Gia_ManPoNum(p->pAig)+i), 0 ) );
+    }
+    if ( iOutFailed >= 0 )
+    {
+        assert( iOutFailed < Gia_ManPoNum(p->pAig) );
+        Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCos, iOutFailed), 0 ) );
+    }
+    // solve SAT
+    status = sat_solver_solve( (sat_solver *)p->pSat, (int *)Vec_IntArray(p->vAssumps), (int *)Vec_IntArray(p->vAssumps) + Vec_IntSize(p->vAssumps), 
+        (ABC_INT64_T)1000000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( status != l_True )
+    {
+        printf( "SAT problem is not satisfiable. Failure...\n" );
+        return;
+    }
+    assert( status == l_True );
+    // check the model
+    Vec_IntClear( p->vCofVars );
+    for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ )
+    {
+        if ( sat_solver_var_value( (sat_solver *)p->pSat, Vec_IntEntry(p->vSatNumCis, i) ) )
+            Vec_IntPush( p->vCofVars, i );
+    }
+    // write the current state
+    for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ )
+    {
+        if ( Gia_StaHasValue0(pCur, i) )
+            assert( sat_solver_var_value( (sat_solver *)p->pSat, Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i) ) == 0 );
+        else if ( Gia_StaHasValue1(pCur, i) )
+            assert( sat_solver_var_value( (sat_solver *)p->pSat, Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i) ) == 1 );
+        // set don't-care value
+        if ( sat_solver_var_value( (sat_solver *)p->pSat, Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i) ) == 0 )
+            Gia_StaSetValue0( pCur, i );
+        else
+            Gia_StaSetValue1( pCur, i );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the status of the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Gia_ManAreDeriveCex( Gia_ManAre_t * p, Gia_StaAre_t * pLast )
+{
+    Abc_Cex_t * pCex;
+    Vec_Ptr_t * vStates;
+    Gia_StaAre_t * pSta, * pPrev;
+    int Var, i, v;
+    assert( p->iOutFail >= 0 );
+    Gia_ManAreDeriveCexSatStart( p );
+    // compute the trace
+    vStates = Vec_PtrAlloc( 1000 );
+    for ( pSta = pLast; Gia_StaIsGood(p, pSta); pSta = Gia_StaPrev(p, pSta) )
+        if ( pSta != pLast )
+            Vec_PtrPush( vStates, pSta );
+    assert( Vec_PtrSize(vStates) >= 1 );
+    // start the counter-example
+    pCex = Abc_CexAlloc( Gia_ManRegNum(p->pAig), Gia_ManPiNum(p->pAig), Vec_PtrSize(vStates) );
+    pCex->iFrame = Vec_PtrSize(vStates)-1;
+    pCex->iPo = p->iOutFail;
+    // compute states
+    pPrev = NULL;
+    Vec_PtrForEachEntry( Gia_StaAre_t *, vStates, pSta, i )
+    {
+        Gia_ManAreDeriveCexSat( p, pSta, pPrev, (i == 0) ? p->iOutFail : -1 ); 
+        pPrev = pSta;
+        // create the counter-example
+        Vec_IntForEachEntry( p->vCofVars, Var, v )
+        {
+            assert( Var < Gia_ManPiNum(p->pAig) );
+            Abc_InfoSetBit( pCex->pData, Gia_ManRegNum(p->pAig) + (Vec_PtrSize(vStates)-1-i) * Gia_ManPiNum(p->pAig) + Var );
+        }
+    }
+    // free temporary things
+    Vec_PtrFree( vStates );
+    Gia_ManAreDeriveCexSatStop( p );
+    return pCex;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaFalse.c b/abc-build/src/aig/gia/giaFalse.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaFalse.c
@@ -0,0 +1,552 @@
+/**CFile****************************************************************
+
+  FileName    [giaFalse.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Detection and elimination of false paths.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaFalse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/vec/vecQue.h"
+#include "misc/vec/vecWec.h"
+#include "sat/bsat/satStore.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reconstruct the AIG after detecting false paths.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFalseRebuildOne( Gia_Man_t * pNew, Gia_Man_t * p, Vec_Int_t * vHook, int fVerbose, int fVeryVerbose )
+{
+    Gia_Obj_t * pObj, * pObj1, * pPrev = NULL;
+    int i, CtrlValue = 0, iPrevValue = -1;
+    pObj = Gia_ManObj( p, Vec_IntEntry(vHook, 0) );
+    if ( Vec_IntSize(vHook) == 1 )
+    {
+        pObj->Value = 0; // what if stuck at 1???
+        return;
+    }
+    assert( Vec_IntSize(vHook) >= 2 );
+    // find controlling value
+    pObj1 = Gia_ManObj( p, Vec_IntEntry(vHook, 1) );
+    if ( Gia_ObjFanin0(pObj1) == pObj )
+        CtrlValue = Gia_ObjFaninC0(pObj1);
+    else if ( Gia_ObjFanin1(pObj1) == pObj )
+        CtrlValue = Gia_ObjFaninC1(pObj1);
+    else assert( 0 );
+//    printf( "%d ", CtrlValue );
+    // rewrite the path
+    Gia_ManForEachObjVec( vHook, p, pObj, i )
+    {
+        int iObjValue = pObj->Value;
+        pObj->Value = i ? Gia_ManHashAnd(pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj)) : CtrlValue;
+        if ( pPrev )
+            pPrev->Value = iPrevValue;
+        iPrevValue = iObjValue;
+        pPrev = pObj;
+    }
+    if ( fVeryVerbose )
+    {
+        printf( "Eliminated path: " );
+        Vec_IntPrint( vHook );
+        Gia_ManForEachObjVec( vHook, p, pObj, i )
+        {
+            printf( "Level %3d : ", Gia_ObjLevel(p, pObj) );
+            Gia_ObjPrint( p, pObj );
+        }
+    }
+}
+Gia_Man_t * Gia_ManFalseRebuild( Gia_Man_t * p, Vec_Wec_t * vHooks, int fVerbose, int fVeryVerbose )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, Counter = 0;
+    pNew = Gia_ManStart( 4 * Gia_ManObjNum(p) / 3 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            if ( Vec_WecLevelSize(vHooks, i) > 0 )
+            {
+                if ( fVeryVerbose )
+                    printf( "Path %d : ", Counter++ );
+                Gia_ManFalseRebuildOne( pNew, p, Vec_WecEntry(vHooks, i), fVerbose, fVeryVerbose );
+            }
+            else
+                pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        }
+        else if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Gia_ManAppendCi( pNew );
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive critical path by following minimum slacks.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCollectPath_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPath )
+{
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        if ( Gia_ObjLevel(p, Gia_ObjFanin0(pObj)) > Gia_ObjLevel(p, Gia_ObjFanin1(pObj)) )
+            Gia_ManCollectPath_rec( p, Gia_ObjFanin0(pObj), vPath );
+        else if ( Gia_ObjLevel(p, Gia_ObjFanin0(pObj)) < Gia_ObjLevel(p, Gia_ObjFanin1(pObj)) )
+            Gia_ManCollectPath_rec( p, Gia_ObjFanin1(pObj), vPath );
+//        else if ( rand() & 1 )
+//            Gia_ManCollectPath_rec( p, Gia_ObjFanin0(pObj), vPath );
+        else
+            Gia_ManCollectPath_rec( p, Gia_ObjFanin1(pObj), vPath );
+    }
+    Vec_IntPush( vPath, Gia_ObjId(p, pObj) );
+}
+Vec_Int_t * Gia_ManCollectPath( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    Vec_Int_t * vPath = Vec_IntAlloc( p->nLevels );
+    Gia_ManCollectPath_rec( p, Gia_ObjIsCo(pObj) ? Gia_ObjFanin0(pObj) : pObj, vPath );
+    return vPath;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCheckFalseOne( Gia_Man_t * p, int iOut, int nTimeOut, Vec_Wec_t * vHooks, int fVerbose, int fVeryVerbose )
+{
+    sat_solver * pSat;
+    Gia_Obj_t * pObj, * pFanin;
+    Gia_Obj_t * pPivot = Gia_ManCo( p, iOut );
+    Vec_Int_t * vLits = Vec_IntAlloc( p->nLevels );
+    Vec_Int_t * vPath = Gia_ManCollectPath( p, pPivot );
+    int nLits = 0, * pLits = NULL;
+    int i, Shift[2], status;
+    abctime clkStart = Abc_Clock();
+    // collect objects and assign SAT variables
+    int iFanin = Gia_ObjFaninId0p( p, pPivot );
+    Vec_Int_t * vObjs = Gia_ManCollectNodesCis( p, &iFanin, 1 );
+    Gia_ManForEachObjVec( vObjs, p, pObj, i )
+        pObj->Value = Vec_IntSize(vObjs) - 1 - i;
+    assert( Gia_ObjIsCo(pPivot) );
+    // create SAT solver
+    pSat = sat_solver_new();
+    sat_solver_set_runtime_limit( pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 );
+    sat_solver_setnvars( pSat, 3 * Vec_IntSize(vPath) + 2 * Vec_IntSize(vObjs) );
+    Shift[0] = 3 * Vec_IntSize(vPath);
+    Shift[1] = 3 * Vec_IntSize(vPath) + Vec_IntSize(vObjs);
+    // add CNF for the cone
+    Gia_ManForEachObjVec( vObjs, p, pObj, i )
+    {
+        if ( !Gia_ObjIsAnd(pObj) )
+            continue;
+        sat_solver_add_and( pSat, pObj->Value + Shift[0], 
+            Gia_ObjFanin0(pObj)->Value + Shift[0], Gia_ObjFanin1(pObj)->Value + Shift[0], 
+            Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); 
+        sat_solver_add_and( pSat, pObj->Value + Shift[1], 
+            Gia_ObjFanin0(pObj)->Value + Shift[1], Gia_ObjFanin1(pObj)->Value + Shift[1], 
+            Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); 
+    }
+    // add CNF for the path
+    Gia_ManForEachObjVec( vPath, p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            assert( i > 0 );
+            pFanin = Gia_ManObj( p, Vec_IntEntry(vPath, i-1) );
+            if ( pFanin == Gia_ObjFanin0(pObj) )
+            {
+                sat_solver_add_and( pSat, i + 1*Vec_IntSize(vPath), 
+                    i-1 + 1*Vec_IntSize(vPath), Gia_ObjFanin1(pObj)->Value + Shift[0], 
+                    Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); 
+                sat_solver_add_and( pSat, i + 2*Vec_IntSize(vPath), 
+                    i-1 + 2*Vec_IntSize(vPath), Gia_ObjFanin1(pObj)->Value + Shift[1], 
+                    Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); 
+            }
+            else if ( pFanin == Gia_ObjFanin1(pObj) )
+            {
+                sat_solver_add_and( pSat, i + 1*Vec_IntSize(vPath), 
+                    Gia_ObjFanin0(pObj)->Value + Shift[0], i-1 + 1*Vec_IntSize(vPath), 
+                    Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); 
+                sat_solver_add_and( pSat, i + 2*Vec_IntSize(vPath), 
+                    Gia_ObjFanin0(pObj)->Value + Shift[1], i-1 + 2*Vec_IntSize(vPath), 
+                    Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); 
+            }
+            else assert( 0 );
+            sat_solver_add_xor( pSat, i, i + 1*Vec_IntSize(vPath), i + 2*Vec_IntSize(vPath), 0 );
+        }
+        else if ( Gia_ObjIsCi(pObj) )
+            sat_solver_add_xor( pSat, i, pObj->Value + Shift[0], pObj->Value + Shift[1], 0 );
+        else assert( 0 );
+        Vec_IntPush( vLits, Abc_Var2Lit(i, 0) );
+    }
+    // call the SAT solver
+    status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), (ABC_INT64_T)nTimeOut, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( status == l_False )
+    {
+        int iBeg, iEnd;
+        nLits = sat_solver_final( pSat, &pLits );
+        iBeg  = Abc_Lit2Var(pLits[nLits-1]);
+        iEnd  = Abc_Lit2Var(pLits[0]);
+        if ( iEnd - iBeg < 20 )
+        {
+            // check if nodes on the path are already used
+            for ( i = Abc_MaxInt(iBeg-1, 0); i <= iEnd; i++ )
+                if ( Vec_WecLevelSize(vHooks, Vec_IntEntry(vPath, i)) > 0 )
+                    break;
+            if ( i > iEnd )
+            {
+                Vec_Int_t * vHook = Vec_WecEntry(vHooks, Vec_IntEntry(vPath, iEnd));
+                for ( i = Abc_MaxInt(iBeg-1, 0); i <= iEnd; i++ )
+                    Vec_IntPush( vHook, Vec_IntEntry(vPath, i) );
+            }
+        }
+    }
+    if ( fVerbose )
+    {
+        printf( "PO %6d : Level = %3d  ", iOut, Gia_ObjLevel(p, pPivot) );
+        if ( status == l_Undef )
+            printf( "Timeout reached after %d seconds. ", nTimeOut );
+        else if ( status == l_True )
+            printf( "There is no false path. " );
+        else
+        {
+            printf( "False path contains %d nodes (out of %d):  ", nLits, Vec_IntSize(vPath) );
+            printf( "top = %d  ", Vec_IntEntry(vPath, Abc_Lit2Var(pLits[0])) );
+            if ( fVeryVerbose )
+                for ( i = 0; i < nLits; i++ )
+                    printf( "%d ", Abc_Lit2Var(pLits[i]) );
+            printf( "  " );
+        }
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart );
+    }
+    sat_solver_delete( pSat );
+    Vec_IntFree( vObjs );
+    Vec_IntFree( vPath );
+    Vec_IntFree( vLits );
+}
+Gia_Man_t * Gia_ManCheckFalse2( Gia_Man_t * p, int nSlackMax, int nTimeOut, int fVerbose, int fVeryVerbose )
+{
+    Gia_Man_t * pNew;
+    Vec_Wec_t * vHooks;
+    Vec_Que_t * vPrio;
+    Vec_Flt_t * vWeights;
+    Gia_Obj_t * pObj;
+    int i;
+//    srand( 111 );
+    Gia_ManLevelNum( p );
+    // create PO weights
+    vWeights = Vec_FltAlloc( Gia_ManCoNum(p) );
+    Gia_ManForEachCo( p, pObj, i )
+        Vec_FltPush( vWeights, Gia_ObjLevel(p, pObj) );
+    // put POs into the queue
+    vPrio = Vec_QueAlloc( Gia_ManCoNum(p) );
+    Vec_QueSetPriority( vPrio, Vec_FltArrayP(vWeights) );
+    Gia_ManForEachCo( p, pObj, i )
+        Vec_QuePush( vPrio, i );
+    // work on each PO in the queue
+    vHooks = Vec_WecStart( Gia_ManObjNum(p) );
+    while ( Vec_QueTopPriority(vPrio) >= p->nLevels - nSlackMax )
+        Gia_ManCheckFalseOne( p, Vec_QuePop(vPrio), nTimeOut, vHooks, fVerbose, fVeryVerbose );
+    if ( fVerbose )
+    printf( "Collected %d non-overlapping false paths.\n", Vec_WecSizeUsed(vHooks) );
+    // reconstruct the AIG
+    pNew = Gia_ManFalseRebuild( p, vHooks, fVerbose, fVeryVerbose );
+    // cleanup
+    Vec_WecFree( vHooks );
+    Vec_FltFree( vWeights );
+    Vec_QueFree( vPrio );
+    return pNew;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFalseRebuildPath( Gia_Man_t * p, Vec_Int_t * vHooks, int fVerbose, int fVeryVerbose )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, iPathEnd = Vec_IntEntryLast(vHooks);
+    pNew = Gia_ManStart( 4 * Gia_ManObjNum(p) / 3 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManFillValue(p);
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            if ( iPathEnd == i )
+                Gia_ManFalseRebuildOne( pNew, p, vHooks, fVerbose, fVeryVerbose );
+            else
+                pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        }
+        else if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Gia_ManAppendCi( pNew );
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+Gia_Man_t * Gia_ManCheckOne( Gia_Man_t * p, int iOut, int iObj, int nTimeOut, int fVerbose, int fVeryVerbose )
+{
+    sat_solver * pSat;
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj, * pFanin;
+    Vec_Int_t * vLits = Vec_IntAlloc( p->nLevels );
+    Vec_Int_t * vPath = Gia_ManCollectPath( p, Gia_ManObj(p, iObj) );
+    int nLits = 0, * pLits = NULL;
+    int i, Shift[2], status;
+    abctime clkStart = Abc_Clock();
+    // collect objects and assign SAT variables
+    Vec_Int_t * vObjs = Gia_ManCollectNodesCis( p, &iObj, 1 );
+    Gia_ManForEachObjVec( vObjs, p, pObj, i )
+        pObj->Value = Vec_IntSize(vObjs) - 1 - i;
+    // create SAT solver
+    pSat = sat_solver_new();
+    sat_solver_set_runtime_limit( pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 );
+    sat_solver_setnvars( pSat, 3 * Vec_IntSize(vPath) + 2 * Vec_IntSize(vObjs) );
+    Shift[0] = 3 * Vec_IntSize(vPath);
+    Shift[1] = 3 * Vec_IntSize(vPath) + Vec_IntSize(vObjs);
+    // add CNF for the cone
+    Gia_ManForEachObjVec( vObjs, p, pObj, i )
+    {
+        if ( !Gia_ObjIsAnd(pObj) )
+            continue;
+        sat_solver_add_and( pSat, pObj->Value + Shift[0], 
+            Gia_ObjFanin0(pObj)->Value + Shift[0], Gia_ObjFanin1(pObj)->Value + Shift[0], 
+            Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); 
+        sat_solver_add_and( pSat, pObj->Value + Shift[1], 
+            Gia_ObjFanin0(pObj)->Value + Shift[1], Gia_ObjFanin1(pObj)->Value + Shift[1], 
+            Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); 
+    }
+    // add CNF for the path
+    Gia_ManForEachObjVec( vPath, p, pObj, i )
+    {
+        if ( !Gia_ObjIsAnd(pObj) )
+            continue;
+        assert( i > 0 );
+        pFanin = Gia_ManObj( p, Vec_IntEntry(vPath, i-1) );
+        if ( pFanin == Gia_ObjFanin0(pObj) )
+        {
+            sat_solver_add_and( pSat, i + 1*Vec_IntSize(vPath), 
+                i-1 + 1*Vec_IntSize(vPath), Gia_ObjFanin1(pObj)->Value + Shift[0], 
+                Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); 
+            sat_solver_add_and( pSat, i + 2*Vec_IntSize(vPath), 
+                i-1 + 2*Vec_IntSize(vPath), Gia_ObjFanin1(pObj)->Value + Shift[1], 
+                Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); 
+        }
+        else if ( pFanin == Gia_ObjFanin1(pObj) )
+        {
+            sat_solver_add_and( pSat, i + 1*Vec_IntSize(vPath), 
+                Gia_ObjFanin0(pObj)->Value + Shift[0], i-1 + 1*Vec_IntSize(vPath), 
+                Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); 
+            sat_solver_add_and( pSat, i + 2*Vec_IntSize(vPath), 
+                Gia_ObjFanin0(pObj)->Value + Shift[1], i-1 + 2*Vec_IntSize(vPath), 
+                Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); 
+        }
+        else assert( 0 );
+        sat_solver_add_xor( pSat, i, i + 1*Vec_IntSize(vPath), i + 2*Vec_IntSize(vPath), 0 );
+        Vec_IntPush( vLits, Abc_Var2Lit(i, 0) );
+    }
+    // call the SAT solver
+    status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), (ABC_INT64_T)nTimeOut, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    Vec_IntClear( vLits );
+    if ( status == l_False )
+    {
+        int iBeg, iEnd;
+        nLits = sat_solver_final( pSat, &pLits );
+        iBeg  = Abc_Lit2Var(pLits[nLits-1]);
+        iEnd  = Abc_Lit2Var(pLits[0]);
+        assert( iBeg <= iEnd );
+        // collect path
+        for ( i = Abc_MaxInt(iBeg-1, 0); i <= iEnd; i++ )
+//        for ( i = 0; i < Vec_IntSize(vPath); i++ )
+            Vec_IntPush( vLits, Vec_IntEntry(vPath, i) );
+    }
+    if ( fVerbose )
+    {
+        printf( "PO %6d : Level = %3d  ", iOut, Gia_ObjLevelId(p, iObj) );
+        if ( status == l_Undef )
+            printf( "Timeout reached after %d seconds. ", nTimeOut );
+        else if ( status == l_True )
+            printf( "There is no false path. " );
+        else
+        {
+            printf( "False path contains %d nodes (out of %d):  ", Vec_IntSize(vLits), Vec_IntSize(vPath) );
+            if ( fVeryVerbose )
+                for ( i = nLits-1; i >= 0; i-- )
+                    printf( "%d ", Vec_IntEntry(vPath, Abc_Lit2Var(pLits[i])) );
+            printf( "  " );
+        }
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart );
+    }
+    sat_solver_delete( pSat );
+    Vec_IntFree( vObjs );
+    Vec_IntFree( vPath );
+    // update the AIG
+    pNew = Vec_IntSize(vLits) ? Gia_ManFalseRebuildPath( p, vLits, fVerbose, fVeryVerbose ) : NULL;
+    Vec_IntFree( vLits );
+/*
+    if ( pNew )
+    {
+        Gia_Man_t * pTemp = Gia_ManDupDfsNode( p, Gia_ManObj(p, iObj) );
+        Gia_AigerWrite( pTemp, "false.aig", 0, 0 );
+        Abc_Print( 1, "Dumping cone with %d nodes into file \"%s\".\n", Gia_ManAndNum(pTemp), "false.aig" );
+        Gia_ManStop( pTemp );
+    }
+*/
+    return pNew;
+}
+Gia_Man_t * Gia_ManCheckFalseAll( Gia_Man_t * p, int nSlackMax, int nTimeOut, int fVerbose, int fVeryVerbose )
+{
+    int Tried = 0, Changed = 0;
+    p = Gia_ManDup( p );
+    while ( 1 )
+    {
+        Gia_Man_t * pNew;
+        Gia_Obj_t * pObj;
+        int i, LevelMax, Changed0 = Changed;
+        LevelMax = Gia_ManLevelNum( p );
+        Gia_ManForEachAnd( p, pObj, i )
+        {
+            if ( Gia_ObjLevel(p, pObj) > nSlackMax )
+                continue;
+            Tried++;
+            pNew = Gia_ManCheckOne( p, -1, i, nTimeOut, fVerbose, fVeryVerbose );
+            if ( pNew == NULL )
+                continue;
+            Changed++;
+            Gia_ManStop( p );
+            p = pNew;
+            LevelMax = Gia_ManLevelNum( p );
+        }
+        if ( Changed0 == Changed )
+            break;
+    }
+//    if ( fVerbose )
+        printf( "Performed %d attempts and %d changes.\n", Tried, Changed );
+    return p;
+}
+Gia_Man_t * Gia_ManCheckFalse( Gia_Man_t * p, int nSlackMax, int nTimeOut, int fVerbose, int fVeryVerbose )
+{
+    int Tried = 0, Changed = 0;
+    Vec_Int_t * vTried;
+//    srand( 111 );
+    p = Gia_ManDup( p );
+    vTried = Vec_IntStart( Gia_ManCoNum(p) );
+    while ( 1 )
+    {
+        Gia_Man_t * pNew;
+        Gia_Obj_t * pObj;
+        int i, LevelMax, Changed0 = Changed;
+        LevelMax = Gia_ManLevelNum( p );
+        Gia_ManForEachCo( p, pObj, i )
+        {
+            if ( !Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) )
+                continue;
+            if ( Gia_ObjLevel(p, Gia_ObjFanin0(pObj)) < LevelMax - nSlackMax )
+                continue;
+            if ( Vec_IntEntry( vTried, i ) )
+                continue;
+            Tried++;
+            pNew = Gia_ManCheckOne( p, i, Gia_ObjFaninId0p(p, pObj), nTimeOut, fVerbose, fVeryVerbose );
+/*
+            if ( i != 126 && pNew )
+            {
+                Gia_ManStop( pNew );
+                pNew = NULL;
+            }
+*/
+            if ( pNew == NULL )
+            {
+                Vec_IntWriteEntry( vTried, i, 1 );
+                continue;
+            }
+            Changed++;
+            Gia_ManStop( p );
+            p = pNew;
+            LevelMax = Gia_ManLevelNum( p );
+        }
+        if ( Changed0 == Changed )
+            break;
+    }
+//    if ( fVerbose )
+        printf( "Performed %d attempts and %d changes.\n", Tried, Changed );
+    Vec_IntFree( vTried );
+    return p;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaFanout.c b/abc-build/src/aig/gia/giaFanout.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaFanout.c
@@ -0,0 +1,330 @@
+/**CFile****************************************************************
+
+  FileName    [giaFanout.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaFanout.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// 0: first iFan
+// 1: prev iFan0
+// 2: prev iFan1
+// 3: next iFan0
+// 4: next iFan1
+
+static inline int   Gia_FanoutCreate( int FanId, int Num )    { assert( Num < 2 ); return (FanId << 1) | Num;   } 
+static inline int * Gia_FanoutObj( int * pData, int ObjId )   { return pData + 5*ObjId;                         }
+static inline int * Gia_FanoutPrev( int * pData, int iFan )   { return pData + 5*(iFan >> 1) + 1 + (iFan & 1);  }
+static inline int * Gia_FanoutNext( int * pData, int iFan )   { return pData + 5*(iFan >> 1) + 3 + (iFan & 1);  }
+
+// these two procedures are only here for the use inside the iterator
+static inline int     Gia_ObjFanout0Int( Gia_Man_t * p, int ObjId )  { assert(ObjId < p->nFansAlloc);  return p->pFanData[5*ObjId];                         }
+static inline int     Gia_ObjFanoutNext( Gia_Man_t * p, int iFan )   { assert(iFan/2 < p->nFansAlloc); return p->pFanData[5*(iFan >> 1) + 3 + (iFan & 1)];  }
+
+// iterator over the fanouts
+#define Gia_ObjForEachFanout( p, pObj, pFanout, iFan, i )                       \
+    for ( assert(p->pFanData), i = 0; (i < (int)(pObj)->nRefs) &&               \
+          (((iFan) = i? Gia_ObjFanoutNext(p, iFan) : Gia_ObjFanout0Int(p, Gia_ObjId(p, pObj))), 1) && \
+          (((pFanout) = Gia_ManObj(p, iFan>>1)), 1); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Create fanout for all objects in the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFanoutStart( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    // allocate fanout datastructure
+    assert( p->pFanData == NULL );
+    p->nFansAlloc = 2 * Gia_ManObjNum(p);
+    if ( p->nFansAlloc < (1<<12) )
+        p->nFansAlloc = (1<<12);
+    p->pFanData = ABC_ALLOC( int, 5 * p->nFansAlloc );
+    memset( p->pFanData, 0, sizeof(int) * 5 * p->nFansAlloc );
+    // add fanouts for all objects
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjChild0(pObj) )
+            Gia_ObjAddFanout( p, Gia_ObjFanin0(pObj), pObj );
+        if ( Gia_ObjChild1(pObj) )
+            Gia_ObjAddFanout( p, Gia_ObjFanin1(pObj), pObj );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes fanout for all objects in the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFanoutStop( Gia_Man_t * p )
+{
+    assert( p->pFanData != NULL );
+    ABC_FREE( p->pFanData );
+    p->nFansAlloc = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds fanout (pFanout) of node (pObj).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ObjAddFanout( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanout )
+{
+    int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext;
+    assert( p->pFanData );
+    assert( !Gia_IsComplement(pObj) && !Gia_IsComplement(pFanout) );
+    assert( Gia_ObjId(p, pFanout) > 0 );
+    if ( Gia_ObjId(p, pObj) >= p->nFansAlloc || Gia_ObjId(p, pFanout) >= p->nFansAlloc )
+    {
+        int nFansAlloc = 2 * Abc_MaxInt( Gia_ObjId(p, pObj), Gia_ObjId(p, pFanout) ); 
+        p->pFanData = ABC_REALLOC( int, p->pFanData, 5 * nFansAlloc );
+        memset( p->pFanData + 5 * p->nFansAlloc, 0, sizeof(int) * 5 * (nFansAlloc - p->nFansAlloc) );
+        p->nFansAlloc = nFansAlloc;
+    }
+    assert( Gia_ObjId(p, pObj) < p->nFansAlloc && Gia_ObjId(p, pFanout) < p->nFansAlloc );
+    iFan   = Gia_FanoutCreate( Gia_ObjId(p, pFanout), Gia_ObjWhatFanin(pFanout, pObj) );
+    pPrevC = Gia_FanoutPrev( p->pFanData, iFan );
+    pNextC = Gia_FanoutNext( p->pFanData, iFan );
+    pFirst = Gia_FanoutObj( p->pFanData, Gia_ObjId(p, pObj) );
+    if ( *pFirst == 0 )
+    {
+        *pFirst = iFan;
+        *pPrevC = iFan;
+        *pNextC = iFan;
+    }
+    else
+    {
+        pPrev = Gia_FanoutPrev( p->pFanData, *pFirst );
+        pNext = Gia_FanoutNext( p->pFanData, *pPrev );
+        assert( *pNext == *pFirst );
+        *pPrevC = *pPrev;
+        *pNextC = *pFirst;
+        *pPrev  = iFan;
+        *pNext  = iFan;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes fanout (pFanout) of node (pObj).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ObjRemoveFanout( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanout )
+{
+    int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext;
+    assert( p->pFanData && Gia_ObjId(p, pObj) < p->nFansAlloc && Gia_ObjId(p, pFanout) < p->nFansAlloc );
+    assert( !Gia_IsComplement(pObj) && !Gia_IsComplement(pFanout) );
+    assert( Gia_ObjId(p, pFanout) > 0 );
+    iFan   = Gia_FanoutCreate( Gia_ObjId(p, pFanout), Gia_ObjWhatFanin(pFanout, pObj) );
+    pPrevC = Gia_FanoutPrev( p->pFanData, iFan );
+    pNextC = Gia_FanoutNext( p->pFanData, iFan );
+    pPrev  = Gia_FanoutPrev( p->pFanData, *pNextC );
+    pNext  = Gia_FanoutNext( p->pFanData, *pPrevC );
+    assert( *pPrev == iFan );
+    assert( *pNext == iFan );
+    pFirst = Gia_FanoutObj( p->pFanData, Gia_ObjId(p, pObj) );
+    assert( *pFirst > 0 );
+    if ( *pFirst == iFan )
+    {
+        if ( *pNextC == iFan )
+        {
+            *pFirst = 0;
+            *pPrev  = 0;
+            *pNext  = 0;
+            *pPrevC = 0;
+            *pNextC = 0;
+            return;
+        }
+        *pFirst = *pNextC;
+    }
+    *pPrev  = *pPrevC;
+    *pNext  = *pNextC;
+    *pPrevC = 0;
+    *pNextC = 0;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the map of all edges.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManStartFanoutMap( Gia_Man_t * p, Vec_Int_t * vFanoutNums )
+{
+    Vec_Int_t * vEdgeMap;
+    Gia_Obj_t * pObj;
+    int i, iOffset;
+    iOffset  = Gia_ManObjNum(p);
+    vEdgeMap = Vec_IntStart( iOffset + 2 * Gia_ManAndNum(p) + Gia_ManCoNum(p) );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        Vec_IntWriteEntry( vEdgeMap, i, iOffset );
+        iOffset += Vec_IntEntry( vFanoutNums, Gia_ObjId(p, pObj) );
+    }
+    assert( iOffset <= Vec_IntSize(vEdgeMap) );
+    return vEdgeMap;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates static fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManStaticFanoutStart( Gia_Man_t * p )
+{
+    Vec_Int_t * vCounts;
+    int * pRefsOld;
+    Gia_Obj_t * pObj, * pFanin;
+    int i, iFanout;
+    assert( p->vFanoutNums == NULL );
+    assert( p->vFanout == NULL );
+    // recompute reference counters
+    pRefsOld = p->pRefs; p->pRefs = NULL;
+    Gia_ManCreateRefs(p);
+    p->vFanoutNums = Vec_IntAllocArray( p->pRefs, Gia_ManObjNum(p) );
+    p->pRefs = pRefsOld;
+    // start the fanout maps
+    p->vFanout = Gia_ManStartFanoutMap( p, p->vFanoutNums );
+    // incrementally add fanouts
+    vCounts = Vec_IntStart( Gia_ManObjNum(p) );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) )
+        {
+            pFanin = Gia_ObjFanin0(pObj);
+            iFanout = Vec_IntEntry( vCounts, Gia_ObjId(p, pFanin) );
+            Gia_ObjSetFanout( p, pFanin, iFanout, pObj );
+            Vec_IntAddToEntry( vCounts, Gia_ObjId(p, pFanin), 1 );
+        }
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+
+            pFanin = Gia_ObjFanin1(pObj);
+            iFanout = Vec_IntEntry( vCounts, Gia_ObjId(p, pFanin) );
+            Gia_ObjSetFanout( p, pFanin, iFanout, pObj );
+            Vec_IntAddToEntry( vCounts, Gia_ObjId(p, pFanin), 1 );
+        }
+    }
+    // double-check the current number of fanouts added
+    Gia_ManForEachObj( p, pObj, i )
+        assert( Vec_IntEntry(vCounts, i) == Gia_ObjFanoutNum(p, pObj) );
+    Vec_IntFree( vCounts );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates static fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManStaticFanoutStop( Gia_Man_t * p )
+{
+    Vec_IntFreeP( &p->vFanoutNums );
+    Vec_IntFreeP( &p->vFanout );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Tests static fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManStaticFanoutTest( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pFanout;
+    int i, k;
+    Gia_ManStaticFanoutStart( p );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        Gia_ObjPrint( p, pObj );
+        printf( "   Fanouts : " );
+        Gia_ObjForEachFanoutStatic( p, pObj, pFanout, k )
+            printf( "%5d ", Gia_ObjId(p, pFanout) );
+        printf( "\n" );
+    }
+    Gia_ManStaticFanoutStop( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaForce.c b/abc-build/src/aig/gia/giaForce.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaForce.c
@@ -0,0 +1,1106 @@
+/**CFile****************************************************************
+
+  FileName    [gia.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/* 
+    The code is based on the paper by F. A. Aloul, I. L. Markov, and K. A. Sakallah.
+    "FORCE: A Fast and Easy-To-Implement Variable-Ordering Heuristic", Proc. GLSVLSI�03.
+    http://www.eecs.umich.edu/~imarkov/pubs/conf/glsvlsi03-force.pdf
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Frc_Obj_t_ Frc_Obj_t;
+struct Frc_Obj_t_
+{
+    unsigned       fCi      :  1;    // terminal node CI
+    unsigned       fCo      :  1;    // terminal node CO
+    unsigned       fMark0   :  1;    // first user-controlled mark
+    unsigned       fMark1   :  1;    // second user-controlled mark
+    unsigned       nFanins  : 28;    // the number of fanins
+    unsigned       nFanouts;         // the number of fanouts
+    unsigned       iFanout;          // the current number of fanouts
+    int            hHandle;          // the handle of the node
+    int            pPlace;           // the placement of each node
+    union {
+    float          fEdgeCenter;      // center-of-gravity of the edge
+    unsigned       iFanin; 
+    };
+    int            Fanios[0];        // the array of fanins/fanouts
+};
+
+typedef struct Frc_Man_t_ Frc_Man_t;
+struct Frc_Man_t_
+{
+    Gia_Man_t *    pGia;             // the original AIG manager
+    Vec_Int_t *    vCis;             // the vector of CIs (PIs + LOs)
+    Vec_Int_t *    vCos;             // the vector of COs (POs + LIs)
+    int            nObjs;            // the number of objects
+    int            nRegs;            // the number of registers
+    int *          pObjData;         // the array containing data for objects
+    int            nObjData;         // the size of array to store the logic network
+    int            fVerbose;         // verbose output flag
+    int            nCutCur;          // current cut 
+    int            nCutMax;          // max cut seen
+};
+
+static inline int         Frc_ManRegNum( Frc_Man_t * p )              { return p->nRegs;                                                     }
+static inline int         Frc_ManCiNum( Frc_Man_t * p )               { return Vec_IntSize(p->vCis);                                         }
+static inline int         Frc_ManCoNum( Frc_Man_t * p )               { return Vec_IntSize(p->vCos);                                         }
+static inline int         Frc_ManPiNum( Frc_Man_t * p )               { return Vec_IntSize(p->vCis) - p->nRegs;                              }
+static inline int         Frc_ManPoNum( Frc_Man_t * p )               { return Vec_IntSize(p->vCos) - p->nRegs;                              }
+static inline int         Frc_ManObjNum( Frc_Man_t * p )              { return p->nObjs;                                                     } 
+static inline int         Frc_ManNodeNum( Frc_Man_t * p )             { return p->nObjs - Vec_IntSize(p->vCis) - Vec_IntSize(p->vCos);       } 
+
+static inline Frc_Obj_t * Frc_ManObj( Frc_Man_t * p, int hHandle )    { return (Frc_Obj_t *)(p->pObjData + hHandle);                         } 
+static inline Frc_Obj_t * Frc_ManCi( Frc_Man_t * p, int i )           { return Frc_ManObj( p, Vec_IntEntry(p->vCis,i) );                     }
+static inline Frc_Obj_t * Frc_ManCo( Frc_Man_t * p, int i )           { return Frc_ManObj( p, Vec_IntEntry(p->vCos,i) );                     }
+
+static inline int         Frc_ObjIsTerm( Frc_Obj_t * pObj )           { return pObj->fCi || pObj->fCo;                                       } 
+static inline int         Frc_ObjIsCi( Frc_Obj_t * pObj )             { return pObj->fCi;                                                    } 
+static inline int         Frc_ObjIsCo( Frc_Obj_t * pObj )             { return pObj->fCo;                                                    } 
+static inline int         Frc_ObjIsPi( Frc_Obj_t * pObj )             { return pObj->fCi && pObj->nFanins == 0;                              } 
+static inline int         Frc_ObjIsPo( Frc_Obj_t * pObj )             { return pObj->fCo && pObj->nFanouts == 0;                             } 
+static inline int         Frc_ObjIsNode( Frc_Obj_t * pObj )           { return!Frc_ObjIsTerm(pObj) && pObj->nFanins > 0;                     } 
+static inline int         Frc_ObjIsConst0( Frc_Obj_t * pObj )         { return!Frc_ObjIsTerm(pObj) && pObj->nFanins == 0;                    } 
+
+static inline int         Frc_ObjSize( Frc_Obj_t * pObj )             { return sizeof(Frc_Obj_t) / 4 + pObj->nFanins + pObj->nFanouts;       } 
+static inline int         Frc_ObjFaninNum( Frc_Obj_t * pObj )         { return pObj->nFanins;                                                } 
+static inline int         Frc_ObjFanoutNum( Frc_Obj_t * pObj )        { return pObj->nFanouts;                                               } 
+static inline Frc_Obj_t * Frc_ObjFanin( Frc_Obj_t * pObj, int i )     { return (Frc_Obj_t *)(((int *)pObj) - pObj->Fanios[i]);               } 
+static inline Frc_Obj_t * Frc_ObjFanout( Frc_Obj_t * pObj, int i )    { return (Frc_Obj_t *)(((int *)pObj) + pObj->Fanios[pObj->nFanins+i]); } 
+
+#define Frc_ManForEachObj( p, pObj, i )               \
+    for ( i = 0; (i < p->nObjData) && (pObj = Frc_ManObj(p,i)); i += Frc_ObjSize(pObj) )
+#define Frc_ManForEachObjVec( vVec, p, pObj, i )                        \
+    for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Frc_ManObj(p, Vec_IntEntry(vVec,i))); i++ )
+
+#define Frc_ManForEachNode( p, pObj, i )              \
+    for ( i = 0; (i < p->nObjData) && (pObj = Frc_ManObj(p,i)); i += Frc_ObjSize(pObj) ) if ( Frc_ObjIsTerm(pObj) ) {} else
+#define Frc_ManForEachCi( p, pObj, i )                  \
+    for ( i = 0; (i < Vec_IntSize(p->vCis)) && (pObj = Frc_ManObj(p,Vec_IntEntry(p->vCis,i))); i++ )
+#define Frc_ManForEachCo( p, pObj, i )                  \
+    for ( i = 0; (i < Vec_IntSize(p->vCos)) && (pObj = Frc_ManObj(p,Vec_IntEntry(p->vCos,i))); i++ )
+
+#define Frc_ObjForEachFanin( pObj, pNext, i )         \
+    for ( i = 0; (i < (int)pObj->nFanins) && (pNext = Frc_ObjFanin(pObj,i)); i++ )
+#define Frc_ObjForEachFaninReverse( pObj, pNext, i )  \
+    for ( i = (int)pObj->nFanins - 1; (i >= 0) && (pNext = Frc_ObjFanin(pObj,i)); i-- )
+#define Frc_ObjForEachFanout( pObj, pNext, i )        \
+    for ( i = 0; (i < (int)pObj->nFanouts) && (pNext = Frc_ObjFanout(pObj,i)); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates fanin/fanout pair.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Frc_ObjAddFanin( Frc_Obj_t * pObj, Frc_Obj_t * pFanin )
+{ 
+    assert( pObj->iFanin < pObj->nFanins );
+    assert( pFanin->iFanout < pFanin->nFanouts );
+    pFanin->Fanios[pFanin->nFanins + pFanin->iFanout++] = 
+        pObj->Fanios[pObj->iFanin++] = pObj->hHandle - pFanin->hHandle;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates logic network isomorphic to the given AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Frc_Man_t * Frc_ManStartSimple( Gia_Man_t * pGia )
+{
+    Frc_Man_t * p;
+    Frc_Obj_t * pObjLog, * pFanLog;
+    Gia_Obj_t * pObj;//, * pObjRi, * pObjRo;
+    int i, nNodes, hHandle = 0;
+    // prepare the AIG
+    Gia_ManCreateRefs( pGia );
+    // create logic network
+    p = ABC_CALLOC( Frc_Man_t, 1 );
+    p->pGia  = pGia;
+    p->nRegs = Gia_ManRegNum(pGia);
+    p->vCis  = Vec_IntAlloc( Gia_ManCiNum(pGia) );
+    p->vCos  = Vec_IntAlloc( Gia_ManCoNum(pGia) );
+    p->nObjData = (sizeof(Frc_Obj_t) / 4) * Gia_ManObjNum(pGia) + 2 * (2 * Gia_ManAndNum(pGia) + Gia_ManCoNum(pGia));
+    p->pObjData = ABC_CALLOC( int, p->nObjData );
+    // create constant node
+    Gia_ManConst0(pGia)->Value = hHandle;
+    pObjLog = Frc_ManObj( p, hHandle );
+    pObjLog->hHandle  = hHandle;
+    pObjLog->nFanins  = 0;
+    pObjLog->nFanouts = Gia_ObjRefNum( pGia, Gia_ManConst0(pGia) );
+    // count objects
+    hHandle += Frc_ObjSize( pObjLog );
+    nNodes = 1;
+    p->nObjs++;
+    // create the PIs
+    Gia_ManForEachCi( pGia, pObj, i )
+    {
+        // create PI object
+        pObj->Value = hHandle;
+        Vec_IntPush( p->vCis, hHandle );
+        pObjLog = Frc_ManObj( p, hHandle );
+        pObjLog->hHandle  = hHandle;
+        pObjLog->nFanins  = 0;
+        pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj );
+        pObjLog->fCi = 0;
+        // count objects
+        hHandle += Frc_ObjSize( pObjLog );
+        p->nObjs++;
+    }
+    // create internal nodes
+    Gia_ManForEachAnd( pGia, pObj, i )
+    {
+        assert( Gia_ObjRefNum( pGia, pObj ) > 0 );
+        // create node object
+        pObj->Value = hHandle;
+        pObjLog = Frc_ManObj( p, hHandle );
+        pObjLog->hHandle  = hHandle;
+        pObjLog->nFanins  = 2;
+        pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj );
+        // add fanins
+        pFanLog = Frc_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) ); 
+        Frc_ObjAddFanin( pObjLog, pFanLog );
+        pFanLog = Frc_ManObj( p, Gia_ObjValue(Gia_ObjFanin1(pObj)) ); 
+        Frc_ObjAddFanin( pObjLog, pFanLog );
+        // count objects
+        hHandle += Frc_ObjSize( pObjLog );
+        nNodes++;
+        p->nObjs++;
+    }
+    // create the POs
+    Gia_ManForEachCo( pGia, pObj, i )
+    {
+        // create PO object
+        pObj->Value = hHandle;
+        Vec_IntPush( p->vCos, hHandle );
+        pObjLog = Frc_ManObj( p, hHandle );
+        pObjLog->hHandle  = hHandle;
+        pObjLog->nFanins  = 1;
+        pObjLog->nFanouts = 0;
+        pObjLog->fCo = 1;
+        // add fanins
+        pFanLog = Frc_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) );
+        Frc_ObjAddFanin( pObjLog, pFanLog );
+        // count objects
+        hHandle += Frc_ObjSize( pObjLog );
+        p->nObjs++;
+    }
+    // connect registers
+//    Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, i )
+//        Frc_ObjAddFanin( Frc_ManObj(p,Gia_ObjValue(pObjRo)), Frc_ManObj(p,Gia_ObjValue(pObjRi)) );
+    assert( nNodes  == Frc_ManNodeNum(p) );
+    assert( hHandle == p->nObjData );
+    if ( hHandle != p->nObjData )
+        printf( "Frc_ManStartSimple(): Fatal error in internal representation.\n" );
+    // make sure the fanin/fanout counters are correct
+    Gia_ManForEachObj( pGia, pObj, i )
+    {
+        if ( !~Gia_ObjValue(pObj) )
+            continue;
+        pObjLog = Frc_ManObj( p, Gia_ObjValue(pObj) );
+        assert( pObjLog->nFanins  == pObjLog->iFanin );
+        assert( pObjLog->nFanouts == pObjLog->iFanout );
+        pObjLog->iFanin = pObjLog->iFanout = 0;
+    }
+    ABC_FREE( pGia->pRefs );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect the fanin IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Frc_ManCollectSuper_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper, Vec_Int_t * vVisit )  
+{
+    if ( pObj->fMark1 )
+        return;
+    pObj->fMark1 = 1;
+    Vec_IntPush( vVisit, Gia_ObjId(p, pObj) );
+    if ( pObj->fMark0 )
+    {
+        Vec_IntPush( vSuper, Gia_ObjId(p, pObj) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Frc_ManCollectSuper_rec( p, Gia_ObjFanin0(pObj), vSuper, vVisit );
+    Frc_ManCollectSuper_rec( p, Gia_ObjFanin1(pObj), vSuper, vVisit );
+    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect the fanin IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+void Frc_ManCollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper, Vec_Int_t * vVisit )  
+{
+    int Entry, i;
+    Vec_IntClear( vSuper );
+    Vec_IntClear( vVisit );
+    assert( pObj->fMark0 == 1 );
+    pObj->fMark0 = 0;
+    Frc_ManCollectSuper_rec( p, pObj, vSuper, vVisit );
+    pObj->fMark0 = 1;
+    Vec_IntForEachEntry( vVisit, Entry, i )
+        Gia_ManObj(p, Entry)->fMark1 = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns references while removing the MUX/XOR ones.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Frc_ManCreateRefsSpecial( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj, * pFan0, * pFan1;
+    Gia_Obj_t * pObjC, * pObjD0, * pObjD1;
+    int i;
+    assert( p->pRefs == NULL );
+    Gia_ManCleanMark0( p );
+    Gia_ManCreateRefs( p );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        assert( pObj->fMark0 == 0 );
+        pFan0 = Gia_ObjFanin0(pObj);
+        pFan1 = Gia_ObjFanin1(pObj);
+        // skip nodes whose fanins are PIs or are already marked
+        if ( Gia_ObjIsCi(pFan0) || pFan0->fMark0 || 
+             Gia_ObjIsCi(pFan1) || pFan1->fMark0 )
+             continue;
+        // skip nodes that are not MUX type
+        if ( !Gia_ObjIsMuxType(pObj) )
+            continue;
+        // the node is MUX type, mark it and its fanins
+        pObj->fMark0  = 1;
+        pFan0->fMark0 = 1;
+        pFan1->fMark0 = 1;
+        // deref the control 
+        pObjC = Gia_ObjRecognizeMux( pObj, &pObjD1, &pObjD0 );
+        Gia_ObjRefDec( p, Gia_Regular(pObjC) );
+        if ( Gia_Regular(pObjD0) == Gia_Regular(pObjD1) )
+            Gia_ObjRefDec( p, Gia_Regular(pObjD0) );
+    }
+    Gia_ManForEachAnd( p, pObj, i )
+        assert( Gia_ObjRefNum(p, pObj) > 0 );
+    Gia_ManCleanMark0( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns references while removing the MUX/XOR ones.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Frc_ManTransformRefs( Gia_Man_t * p, int * pnObjs, int * pnFanios )  
+{
+    Vec_Int_t * vSuper, * vVisit;
+    Gia_Obj_t * pObj, * pFanin;
+    int i, k, Counter;
+    assert( p->pRefs != NULL );
+
+    // mark nodes to be used in the logic network
+    Gia_ManCleanMark0( p );
+    Gia_ManConst0(p)->fMark0 = 1;
+    // mark the inputs
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->fMark0 = 1;
+    // mark those nodes that have ref count more than 1
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->fMark0 = (Gia_ObjRefNum(p, pObj) > 1);
+    // mark the output drivers
+    Gia_ManForEachCoDriver( p, pObj, i )
+        pObj->fMark0 = 1;
+
+    // count the number of nodes
+    Counter = 0;
+    Gia_ManForEachObj( p, pObj, i )
+        Counter += pObj->fMark0;
+    *pnObjs = Counter + Gia_ManCoNum(p);
+
+    // reset the references
+    ABC_FREE( p->pRefs );
+    p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    // reference from internal nodes
+    Counter = 0;
+    vSuper = Vec_IntAlloc( 100 );
+    vVisit = Vec_IntAlloc( 100 );
+    Gia_ManCleanMark1( p );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        if ( pObj->fMark0 == 0 )
+            continue;
+        Frc_ManCollectSuper( p, pObj, vSuper, vVisit );
+        Gia_ManForEachObjVec( vSuper, p, pFanin, k )
+        {
+            assert( pFanin->fMark0 );
+            Gia_ObjRefInc( p, pFanin );
+        }
+        Counter += Vec_IntSize( vSuper );
+    }
+    Gia_ManCheckMark1( p );
+    Vec_IntFree( vSuper );
+    Vec_IntFree( vVisit );
+    // reference from outputs
+    Gia_ManForEachCoDriver( p, pObj, i )
+    {
+        assert( pObj->fMark0 );
+        Gia_ObjRefInc( p, pObj );
+    }
+    *pnFanios = Counter + Gia_ManCoNum(p);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates logic network isomorphic to the given AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Frc_Man_t * Frc_ManStart( Gia_Man_t * pGia )
+{
+    Frc_Man_t * p;
+    Frc_Obj_t * pObjLog, * pFanLog;
+    Gia_Obj_t * pObj, * pFanin;//, * pObjRi, * pObjRo;
+    Vec_Int_t * vSuper, * vVisit;
+    int nObjs, nFanios, nNodes = 0;
+    int i, k, hHandle = 0;
+    // prepare the AIG
+//    Gia_ManCreateRefs( pGia );
+    Frc_ManCreateRefsSpecial( pGia );
+    Frc_ManTransformRefs( pGia, &nObjs, &nFanios );
+    Gia_ManFillValue( pGia );
+    // create logic network
+    p = ABC_CALLOC( Frc_Man_t, 1 );
+    p->pGia  = pGia;
+    p->nRegs = Gia_ManRegNum(pGia);
+    p->vCis  = Vec_IntAlloc( Gia_ManCiNum(pGia) );
+    p->vCos  = Vec_IntAlloc( Gia_ManCoNum(pGia) );
+    p->nObjData = (sizeof(Frc_Obj_t) / 4) * nObjs + 2 * nFanios;
+    p->pObjData = ABC_CALLOC( int, p->nObjData );
+    // create constant node
+    Gia_ManConst0(pGia)->Value = hHandle;
+    pObjLog = Frc_ManObj( p, hHandle );
+    pObjLog->hHandle  = hHandle;
+    pObjLog->nFanins  = 0;
+    pObjLog->nFanouts = Gia_ObjRefNum( pGia, Gia_ManConst0(pGia) );
+    // count objects
+    hHandle += Frc_ObjSize( pObjLog );
+    nNodes++;
+    p->nObjs++;
+    // create the PIs
+    Gia_ManForEachCi( pGia, pObj, i )
+    {
+        // create PI object
+        pObj->Value = hHandle;
+        Vec_IntPush( p->vCis, hHandle );
+        pObjLog = Frc_ManObj( p, hHandle );
+        pObjLog->hHandle  = hHandle;
+        pObjLog->nFanins  = 0;
+        pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj );
+        pObjLog->fCi = 1;
+        // count objects
+        hHandle += Frc_ObjSize( pObjLog );
+        p->nObjs++;
+    }
+    // create internal nodes
+    vSuper = Vec_IntAlloc( 100 );
+    vVisit = Vec_IntAlloc( 100 );
+    Gia_ManForEachAnd( pGia, pObj, i )
+    {
+        if ( pObj->fMark0 == 0 )
+        {
+            assert( Gia_ObjRefNum( pGia, pObj ) == 0 );
+            continue;
+        }
+        assert( Gia_ObjRefNum( pGia, pObj ) > 0 );
+        Frc_ManCollectSuper( pGia, pObj, vSuper, vVisit );
+        // create node object
+        pObj->Value = hHandle;
+        pObjLog = Frc_ManObj( p, hHandle );
+        pObjLog->hHandle  = hHandle;
+        pObjLog->nFanins  = Vec_IntSize( vSuper );
+        pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj );
+        // add fanins
+        Gia_ManForEachObjVec( vSuper, pGia, pFanin, k )
+        {
+            pFanLog = Frc_ManObj( p, Gia_ObjValue(pFanin) ); 
+            Frc_ObjAddFanin( pObjLog, pFanLog );
+        }
+        // count objects
+        hHandle += Frc_ObjSize( pObjLog );
+        nNodes++;
+        p->nObjs++;
+    }
+    Vec_IntFree( vSuper );
+    Vec_IntFree( vVisit );
+    // create the POs
+    Gia_ManForEachCo( pGia, pObj, i )
+    {
+        // create PO object
+        pObj->Value = hHandle;
+        Vec_IntPush( p->vCos, hHandle );
+        pObjLog = Frc_ManObj( p, hHandle );
+        pObjLog->hHandle  = hHandle;
+        pObjLog->nFanins  = 1;
+        pObjLog->nFanouts = 0;
+        pObjLog->fCo = 1;
+        // add fanins
+        pFanLog = Frc_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) );
+        Frc_ObjAddFanin( pObjLog, pFanLog );
+        // count objects
+        hHandle += Frc_ObjSize( pObjLog );
+        p->nObjs++;
+    }
+    // connect registers
+//    Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, i )
+//        Frc_ObjAddFanin( Frc_ManObj(p,Gia_ObjValue(pObjRo)), Frc_ManObj(p,Gia_ObjValue(pObjRi)) );
+    Gia_ManCleanMark0( pGia );
+    assert( nNodes  == Frc_ManNodeNum(p) );
+    assert( nObjs   == p->nObjs );
+    assert( hHandle == p->nObjData );
+    if ( hHandle != p->nObjData )
+        printf( "Frc_ManStart(): Fatal error in internal representation.\n" );
+    // make sure the fanin/fanout counters are correct
+    Gia_ManForEachObj( pGia, pObj, i )
+    {
+        if ( !~Gia_ObjValue(pObj) )
+            continue;
+        pObjLog = Frc_ManObj( p, Gia_ObjValue(pObj) );
+        assert( pObjLog->nFanins  == pObjLog->iFanin );
+        assert( pObjLog->nFanouts == pObjLog->iFanout );
+        pObjLog->iFanin = pObjLog->iFanout = 0;
+    }
+    ABC_FREE( pGia->pRefs );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates logic network isomorphic to the given AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Frc_ManPrintStats( Frc_Man_t * p )
+{
+//    if ( p->pName )
+//        printf( "%8s : ", p->pName );
+    printf( "i/o =%7d/%7d  ", Frc_ManPiNum(p), Frc_ManPoNum(p) );
+    if ( Frc_ManRegNum(p) )
+        printf( "ff =%7d  ", Frc_ManRegNum(p) );
+    printf( "node =%8d  ", Frc_ManNodeNum(p) );
+    printf( "obj =%8d  ", Frc_ManObjNum(p) );
+//    printf( "lev =%5d  ", Frc_ManLevelNum(p) );
+//    printf( "cut =%5d  ", Frc_ManCrossCut(p) );
+    printf( "mem =%5.2f MB", 4.0*p->nObjData/(1<<20) );
+//    printf( "obj =%5d  ", Frc_ManObjNum(p) );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates logic network isomorphic to the given AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Frc_ManStop( Frc_Man_t * p )
+{
+    Vec_IntFree( p->vCis );
+    Vec_IntFree( p->vCos );
+    ABC_FREE( p->pObjData );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes cross cut size for the given order of POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Frc_ManCrossCut_rec( Frc_Man_t * p, Frc_Obj_t * pObj )
+{
+    assert( pObj->iFanout > 0 );
+    if ( pObj->iFanout-- == pObj->nFanouts )
+    {
+        Frc_Obj_t * pFanin;
+        int i;
+        p->nCutCur++;
+        p->nCutMax = Abc_MaxInt( p->nCutMax, p->nCutCur );
+        if ( !Frc_ObjIsCi(pObj) )
+            Frc_ObjForEachFanin( pObj, pFanin, i )
+                p->nCutCur -= Frc_ManCrossCut_rec( p, pFanin );
+    }
+    return pObj->iFanout == 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes cross cut size for the given order of POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Frc_ManCrossCut2_rec( Frc_Man_t * p, Frc_Obj_t * pObj )
+{
+    assert( pObj->iFanout > 0 );
+    if ( pObj->iFanout-- == pObj->nFanouts )
+    {
+        Frc_Obj_t * pFanin;
+        int i;
+        p->nCutCur++;
+        p->nCutMax = Abc_MaxInt( p->nCutMax, p->nCutCur );
+        if ( !Frc_ObjIsCi(pObj) )
+            Frc_ObjForEachFaninReverse( pObj, pFanin, i )
+                p->nCutCur -= Frc_ManCrossCut2_rec( p, pFanin );
+    }
+    return pObj->iFanout == 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes cross cut size for the given order of POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Frc_ManCrossCut( Frc_Man_t * p, Vec_Int_t * vOrder, int fReverse )
+{
+    Frc_Obj_t * pObj;
+    int i;
+    assert( Vec_IntSize(vOrder) == Frc_ManCoNum(p) );
+    p->nCutCur = 0;
+    p->nCutMax = 0;
+    Frc_ManForEachObj( p, pObj, i )
+        pObj->iFanout = pObj->nFanouts;
+    Frc_ManForEachObjVec( vOrder, p, pObj, i )
+    {
+        assert( Frc_ObjIsCo(pObj) );
+        if ( fReverse )
+            p->nCutCur -= Frc_ManCrossCut2_rec( p, Frc_ObjFanin(pObj,0) );
+        else
+            p->nCutCur -= Frc_ManCrossCut_rec( p, Frc_ObjFanin(pObj,0) );
+    }
+    assert( p->nCutCur == 0 );
+//    Frc_ManForEachObj( p, pObj, i )
+//        assert( pObj->iFanout == 0 );
+    return p->nCutMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects CO handles.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Frc_ManCollectCos( Frc_Man_t * p )
+{
+    Vec_Int_t * vCoOrder;
+    Frc_Obj_t * pObj;
+    int i;
+    vCoOrder = Vec_IntAlloc( Frc_ManCoNum(p) );
+    Frc_ManForEachCo( p, pObj, i )
+        Vec_IntPush( vCoOrder, pObj->hHandle );
+    return vCoOrder;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes cross cut size for the given order of POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Frc_ManCrossCutTest( Frc_Man_t * p, Vec_Int_t * vOrderInit )
+{
+    Vec_Int_t * vOrder;
+//    abctime clk = Abc_Clock();
+    vOrder = vOrderInit? vOrderInit : Frc_ManCollectCos( p );
+    printf( "CrossCut = %6d\n", Frc_ManCrossCut( p, vOrder, 0 ) );
+    printf( "CrossCut = %6d\n", Frc_ManCrossCut( p, vOrder, 1 ) );
+    Vec_IntReverseOrder( vOrder );
+    printf( "CrossCut = %6d\n", Frc_ManCrossCut( p, vOrder, 0 ) );
+    printf( "CrossCut = %6d\n", Frc_ManCrossCut( p, vOrder, 1 ) );
+    Vec_IntReverseOrder( vOrder );
+    if ( vOrder != vOrderInit )
+        Vec_IntFree( vOrder );
+//    ABC_PRT( "Time", Abc_Clock() - clk );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Generates random placement.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Frc_ManPlaceRandom( Frc_Man_t * p )
+{
+    Frc_Obj_t * pThis;
+    int * pPlacement;
+    int i, h, Temp, iNext, Counter;
+    pPlacement = ABC_ALLOC( int, p->nObjs );
+    for ( i = 0; i < p->nObjs; i++ )
+        pPlacement[i] = i;
+    for ( i = 0; i < p->nObjs; i++ )
+    {
+        iNext = Gia_ManRandom( 0 ) % p->nObjs;
+        Temp = pPlacement[i];
+        pPlacement[i] = pPlacement[iNext];
+        pPlacement[iNext] = Temp;
+    }
+    Counter = 0;
+    Frc_ManForEachObj( p, pThis, h )
+        pThis->pPlace = pPlacement[Counter++];
+    ABC_FREE( pPlacement );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Shuffles array of random integers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Frc_ManArrayShuffle( Vec_Int_t * vArray )
+{
+    int i, iNext, Temp;
+    for ( i = 0; i < vArray->nSize; i++ )
+    {
+        iNext = Gia_ManRandom( 0 ) % vArray->nSize;
+        Temp = vArray->pArray[i];
+        vArray->pArray[i] = vArray->pArray[iNext];
+        vArray->pArray[iNext] = Temp;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes cross cut size for the given order of POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Frc_ManPlaceDfs_rec( Frc_Man_t * p, Frc_Obj_t * pObj, int * piPlace )
+{
+    assert( pObj->iFanout > 0 );
+    if ( pObj->iFanout-- == pObj->nFanouts )
+    {
+        Frc_Obj_t * pFanin;
+        int i;
+        if ( !Frc_ObjIsCi(pObj) )
+            Frc_ObjForEachFanin( pObj, pFanin, i )
+                Frc_ManPlaceDfs_rec( p, pFanin, piPlace );
+        pObj->pPlace = (*piPlace)++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generates DFS placement.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Frc_ManPlaceDfs( Frc_Man_t * p, Vec_Int_t * vCoOrder )
+{
+    Frc_Obj_t * pObj;
+    int i, nPlaces = 0;
+    Frc_ManForEachObj( p, pObj, i )
+    {
+        pObj->iFanout = pObj->nFanouts;
+        if ( pObj->nFanouts == 0 && !Frc_ObjIsCo(pObj) )
+            pObj->pPlace = nPlaces++;
+    }
+    Frc_ManForEachObjVec( vCoOrder, p, pObj, i )
+    {
+        assert( Frc_ObjIsCo(pObj) );
+        Frc_ManPlaceDfs_rec( p, Frc_ObjFanin(pObj,0), &nPlaces );
+        pObj->pPlace = nPlaces++;
+    }
+    assert( nPlaces == p->nObjs );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generates DFS placement by trying both orders.]
+
+  Description [Returns the cross cut size of the best order. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Frc_ManPlaceDfsBoth( Frc_Man_t * p, Vec_Int_t * vCoOrder, int * piCutSize2 )
+{
+    int nCutStart1, nCutStart2;
+    nCutStart1 = Frc_ManCrossCut( p, vCoOrder, 0 );
+    Vec_IntReverseOrder( vCoOrder );
+    nCutStart2 = Frc_ManCrossCut( p, vCoOrder, 0 );
+    if ( nCutStart1 <= nCutStart2 )
+    {
+        Vec_IntReverseOrder( vCoOrder ); // undo
+        Frc_ManPlaceDfs( p, vCoOrder );
+        *piCutSize2 = nCutStart2;
+        return nCutStart1;
+    }
+    else
+    {
+        Frc_ManPlaceDfs( p, vCoOrder );
+        Vec_IntReverseOrder( vCoOrder ); // undo
+        *piCutSize2 = nCutStart1;
+        return nCutStart2;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs iterative refinement of the given placement.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Frc_ManPlacementRefine( Frc_Man_t * p, int nIters, int fVerbose )
+{
+    int fRandomize = 0;
+    Vec_Int_t * vCoOrder;
+    Frc_Obj_t * pThis, * pNext;
+    double CostThis, CostPrev;
+    float * pVertX, VertX;
+    int * pPermX, * pHandles;
+    int k, h, Iter, iMinX, iMaxX, Counter, nCutStart, nCutCur, nCutCur2, nCutPrev;
+    abctime clk = Abc_Clock(), clk2, clk2Total = 0;
+    // create starting one-dimensional placement
+    vCoOrder = Frc_ManCollectCos( p );
+    if ( fRandomize )
+        Frc_ManArrayShuffle( vCoOrder );
+    nCutStart = Frc_ManPlaceDfsBoth( p, vCoOrder, &nCutCur2 );
+    // refine placement
+    CostPrev = 0.0;
+    nCutPrev = nCutStart;
+    pHandles = ABC_ALLOC( int, p->nObjs );
+    pVertX   = ABC_ALLOC( float, p->nObjs );
+    for ( Iter = 0; Iter < nIters; Iter++ )
+    {
+        // compute centers of hyperedges
+        CostThis = 0.0;
+        Frc_ManForEachObj( p, pThis, h )
+        {
+            iMinX = iMaxX = pThis->pPlace;
+            Frc_ObjForEachFanout( pThis, pNext, k )
+            {
+                iMinX = Abc_MinInt( iMinX, pNext->pPlace );
+                iMaxX = Abc_MaxInt( iMaxX, pNext->pPlace );
+            }
+            pThis->fEdgeCenter = 0.5 * (iMaxX + iMinX);
+            CostThis += (iMaxX - iMinX);
+        }
+        // compute new centers of objects
+        Counter = 0;
+        Frc_ManForEachObj( p, pThis, h )
+        {
+            VertX = pThis->fEdgeCenter;
+            Frc_ObjForEachFanin( pThis, pNext, k )
+                VertX += pNext->fEdgeCenter;
+            pVertX[Counter] = VertX / (Frc_ObjFaninNum(pThis) + 1);
+            pHandles[Counter++] = h;
+        }
+        assert( Counter == Frc_ManObjNum(p) );
+        // sort these numbers
+        clk2 = Abc_Clock();
+        pPermX = Gia_SortFloats( pVertX, pHandles, p->nObjs );
+        clk2Total += Abc_Clock() - clk2;
+        assert( pPermX == pHandles );
+        Vec_IntClear( vCoOrder );
+        for ( k = 0; k < p->nObjs; k++ )
+        {
+            pThis = Frc_ManObj( p, pPermX[k] );
+            pThis->pPlace = k;
+            if ( Frc_ObjIsCo(pThis) )
+                Vec_IntPush( vCoOrder, pThis->hHandle );
+        }
+/*
+        printf( "Ordering of PIs:\n" );
+        Frc_ManForEachCi( p, pThis, k )
+            printf( "PI number = %7d.  Object handle = %7d,  Coordinate = %7d.\n", 
+                k, pThis->hHandle, pThis->pPlace );
+*/
+        nCutCur = Frc_ManPlaceDfsBoth( p, vCoOrder, &nCutCur2 );
+        // evaluate cost
+        if ( fVerbose )
+        {
+            printf( "%2d : Span = %e  ", Iter+1, CostThis );
+            printf( "Cut = %6d  (%5.2f %%)  CutR = %6d  ", nCutCur, 100.0*(nCutStart-nCutCur)/nCutStart, nCutCur2 );
+            ABC_PRTn( "Total", Abc_Clock() - clk );
+            ABC_PRT( "Sort", clk2Total );
+//        Frc_ManCrossCutTest( p, vCoOrder );
+        }
+//        if ( 1.0 * nCutPrev / nCutCur < 1.001 )
+//            break;
+        nCutPrev = nCutCur;
+    }
+    ABC_FREE( pHandles );
+    ABC_FREE( pVertX );
+    Vec_IntFree( vCoOrder );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if all fanouts are COsw.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Frc_ObjFanoutsAreCos( Frc_Obj_t * pThis )
+{
+    Frc_Obj_t * pNext;
+    int i;
+    Frc_ObjForEachFanout( pThis, pNext, i )
+        if ( !Frc_ObjIsCo(pNext) )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the distances from the given set of objects.]
+
+  Description [Returns one of the most distant objects.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Frc_DumpGraphIntoFile( Frc_Man_t * p )
+{
+    FILE * pFile;
+    Frc_Obj_t * pThis, * pNext;
+    int i, k, Counter = 0;
+    // assign numbers to CIs and internal nodes
+    Frc_ManForEachObj( p, pThis, i )
+    {
+        if ( i && ((Frc_ObjIsCi(pThis) && !Frc_ObjFanoutsAreCos(pThis)) || Frc_ObjIsNode(pThis)) )
+            pThis->iFanin = Counter++;
+        else
+            pThis->iFanin = ~0;
+    }
+    // assign numbers to all other nodes
+    pFile = fopen( "x\\large\\aig\\dg1.g", "w" );
+    Frc_ManForEachObj( p, pThis, i )
+    {
+        Frc_ObjForEachFanout( pThis, pNext, k )
+        {
+            if ( ~pThis->iFanin && ~pNext->iFanin )
+                fprintf( pFile, "%d %d\n", pThis->iFanin, pNext->iFanin );
+        }
+    }
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Experiment with the FORCE algorithm.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void For_ManExperiment( Gia_Man_t * pGia, int nIters, int fClustered, int fVerbose )
+{
+    Frc_Man_t * p;
+    Gia_ManRandom( 1 );
+    if ( fClustered )
+        p = Frc_ManStart( pGia );
+    else
+        p = Frc_ManStartSimple( pGia );
+//    Frc_DumpGraphIntoFile( p );
+    if ( fVerbose )
+        Frc_ManPrintStats( p );
+//    Frc_ManCrossCutTest( p, NULL );
+    Frc_ManPlacementRefine( p, nIters, fVerbose );
+    Frc_ManStop( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Experiment with the FORCE algorithm.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void For_ManFileExperiment()
+{
+    FILE * pFile;
+    int * pBuffer;
+    int i, Size, Exp = 25;
+    abctime clk = Abc_Clock();
+    int RetValue;
+
+    Size = (1 << Exp);
+    printf( "2^%d machine words (%d bytes).\n", Exp, (int)sizeof(int) * Size );
+
+    pBuffer = ABC_ALLOC( int, Size );
+    for ( i = 0; i < Size; i++ )
+        pBuffer[i] = i;
+ABC_PRT( "Fillup", Abc_Clock() - clk );
+
+clk = Abc_Clock();
+    pFile = fopen( "test.txt", "rb" );
+    RetValue = fread( pBuffer, 1, sizeof(int) * Size, pFile );
+    fclose( pFile );
+ABC_PRT( "Read  ", Abc_Clock() - clk );
+
+clk = Abc_Clock();
+    pFile = fopen( "test.txt", "wb" );
+    fwrite( pBuffer, 1, sizeof(int) * Size, pFile );
+    fclose( pFile );
+ABC_PRT( "Write ", Abc_Clock() - clk );
+/*
+2^25 machine words (134217728 bytes).
+Fillup =    0.06 sec
+Read   =    0.08 sec
+Write  =    1.81 sec
+*/
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaFrames.c b/abc-build/src/aig/gia/giaFrames.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaFrames.c
@@ -0,0 +1,996 @@
+/**CFile****************************************************************
+
+  FileName    [giaFrames.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Timeframe unrolling.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaFrames.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Gia_ManFra_t_ Gia_ManFra_t;
+struct Gia_ManFra_t_
+{
+    Gia_ParFra_t *  pPars;    // parameters
+    Gia_Man_t *     pAig;     // AIG to unroll
+    Vec_Ptr_t *     vIns;     // inputs of each timeframe    
+    Vec_Ptr_t *     vAnds;    // nodes of each timeframe    
+    Vec_Ptr_t *     vOuts;    // outputs of each timeframe    
+};
+
+
+typedef struct Gia_ManUnr_t_ Gia_ManUnr_t;
+struct Gia_ManUnr_t_
+{
+    Gia_ParFra_t *  pPars;    // parameters
+    Gia_Man_t *     pAig;     // AIG to unroll (points to pOrder)
+    // internal data 
+    Gia_Man_t *     pOrder;   // AIG reordered (points to pAig)
+    Vec_Int_t *     vLimit;   // limits of each timeframe
+    // data for each ordered node
+    Vec_Int_t *     vRank;    // rank of each node
+    Vec_Int_t *     vDegree;  // degree of each node
+    Vec_Int_t *     vDegDiff; // degree of each node
+    Vec_Int_t *     vFirst;   // first entry in the store
+    Vec_Int_t *     vStore;   // store for saved data
+    // the resulting AIG
+    Gia_Man_t *     pNew;     // the resulting AIG
+    int             LastLit;  // the place to store the last literal
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG for unrolling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManUnrollDup_rec( Gia_Man_t * pNew, Gia_Obj_t * pObj, int Id ) 
+{
+    if ( ~pObj->Value )
+        return;
+    if ( Gia_ObjIsCi(pObj) )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    else if ( Gia_ObjIsCo(pObj) )
+    {
+        Gia_ManUnrollDup_rec( pNew, Gia_ObjFanin0(pObj), Gia_ObjFaninId0(pObj, Id) );
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+    else if ( Gia_ObjIsAnd(pObj) )
+    {
+        Gia_ManUnrollDup_rec( pNew, Gia_ObjFanin0(pObj), Gia_ObjFaninId0(pObj, Id) );
+        Gia_ManUnrollDup_rec( pNew, Gia_ObjFanin1(pObj), Gia_ObjFaninId1(pObj, Id) );
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    }
+    else assert( 0 );
+    Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value))->Value = Id;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG for unrolling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManUnrollDup( Gia_Man_t * p, Vec_Int_t * vLimit )  
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Vec_IntSize(vLimit) == 0 );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+
+    // save constant class
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    Vec_IntPush( vLimit, Gia_ManObjNum(pNew) );
+ 
+    // create first class
+    Gia_ManForEachPo( p, pObj, i )
+        Gia_ManUnrollDup_rec( pNew, pObj, Gia_ObjId(p, pObj) );
+    Vec_IntPush( vLimit, Gia_ManObjNum(pNew) );
+
+    // create next classes
+    for ( i = 1; i < Gia_ManObjNum(pNew); i++ )
+    {
+        if ( i == Vec_IntEntryLast(vLimit) )
+            Vec_IntPush( vLimit, Gia_ManObjNum(pNew) );
+        pObj = Gia_ManObj( p, Gia_ManObj(pNew, i)->Value );
+        if ( Gia_ObjIsRo(p, pObj) )
+        {
+            pObj = Gia_ObjRoToRi(p, pObj);
+            assert( !~pObj->Value );
+            Gia_ManUnrollDup_rec( pNew, pObj, Gia_ObjId(p, pObj) );
+        }
+    }
+    Gia_ManSetRegNum( pNew, 0 );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG for unrolling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Gia_ManUnrollAbs( Gia_Man_t * p, int nFrames )  
+{
+    int fVerbose = 0;
+    Vec_Ptr_t * vFrames;
+    Vec_Int_t * vLimit, * vOne;
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int nObjBits, nObjMask;
+    int f, fMax, k, Entry, Prev, iStart, iStop, Size;
+    // get the bitmasks
+    nObjBits = Abc_Base2Log( Gia_ManObjNum(p) );
+    nObjMask = (1 << nObjBits) - 1;
+    assert( Gia_ManObjNum(p) <= nObjMask );
+    // derive the tents
+    vLimit = Vec_IntAlloc( 1000 );
+    pNew = Gia_ManUnrollDup( p, vLimit );
+    // debug printout
+    if ( fVerbose )
+    {
+        Prev = 1;
+        printf( "Tents: " );
+        Vec_IntForEachEntryStart( vLimit, Entry, k, 1 )
+            printf( "%d=%d ", k, Entry-Prev ), Prev = Entry;
+        printf( "  Unused=%d", Gia_ManObjNum(p) - Gia_ManObjNum(pNew) );
+        printf( "\n" );
+    }
+    // create abstraction
+    vFrames = Vec_PtrAlloc( Vec_IntSize(vLimit) );
+    for ( fMax = 0; fMax < nFrames; fMax++ )
+    {
+        Size = (fMax+1 < Vec_IntSize(vLimit)) ? Vec_IntEntry(vLimit, fMax+1) : Gia_ManObjNum(pNew);
+        vOne = Vec_IntAlloc( Size );
+        for ( f = 0; f <= fMax; f++ )
+        {
+            iStart = (f   < Vec_IntSize(vLimit)) ? Vec_IntEntry(vLimit, f  ) : 0;
+            iStop  = (f+1 < Vec_IntSize(vLimit)) ? Vec_IntEntry(vLimit, f+1) : 0;
+            for ( k = iStop - 1; k >= iStart; k-- )
+            {
+                assert( Gia_ManObj(pNew, k)->Value > 0 );
+                pObj  = Gia_ManObj(p, Gia_ManObj(pNew, k)->Value);
+                if ( Gia_ObjIsCo(pObj) || Gia_ObjIsPi(p, pObj) )
+                    continue;
+                assert( Gia_ObjIsRo(p, pObj) || Gia_ObjIsAnd(pObj) );
+                Entry = ((fMax-f) << nObjBits) | Gia_ObjId(p, pObj);
+                Vec_IntPush( vOne, Entry );
+//                printf( "%d ", Gia_ManObj(pNew, k)->Value );
+            }
+//            printf( "\n" );
+        }
+        // add in reverse topological order
+        Vec_IntSort( vOne, 1 );
+        Vec_PtrPush( vFrames, vOne );
+        assert( Vec_IntSize(vOne) <= Size - 1 );
+    }
+    Vec_IntFree( vLimit );
+    Gia_ManStop( pNew );
+    return vFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_ManUnr_t * Gia_ManUnrStart( Gia_Man_t * pAig, Gia_ParFra_t * pPars )  
+{ 
+    Gia_ManUnr_t * p;
+    Gia_Obj_t * pObj;
+    int i, k, iRank, iFanin, Degree, Shift;
+    abctime clk = Abc_Clock();
+
+    p = ABC_CALLOC( Gia_ManUnr_t, 1 );
+    p->pAig   = pAig;
+    p->pPars  = pPars;
+    // create order
+    p->vLimit = Vec_IntAlloc( 0 );
+    p->pOrder = Gia_ManUnrollDup( pAig, p->vLimit );
+/*
+    Vec_IntForEachEntryStart( p->vLimit, Shift, i, 1 )
+        printf( "%d=%d ", i, Shift-Vec_IntEntry(p->vLimit, i-1) );
+    printf( "\n" );
+*/
+    // assign rank
+    p->vRank  = Vec_IntAlloc( Gia_ManObjNum(p->pOrder) );
+    for ( iRank = i = 0; i < Gia_ManObjNum(p->pOrder); Vec_IntPush(p->vRank, iRank), i++ )
+        if ( Vec_IntEntry(p->vLimit, iRank) == i )
+            iRank++;
+    assert( iRank == Vec_IntSize(p->vLimit)-1 );
+    assert( Vec_IntSize(p->vRank) == Gia_ManObjNum(p->pOrder) );
+    // assign degree
+    p->vDegree = Vec_IntStart( Gia_ManObjNum(p->pOrder) );
+    p->vDegDiff= Vec_IntStart( 2* Gia_ManObjNum(p->pOrder) );
+    Gia_ManForEachAnd( p->pOrder, pObj, i )
+    {
+        for ( k = 0; k < 2; k++ )
+        {
+            iFanin = k ? Gia_ObjFaninId1(pObj, i) : Gia_ObjFaninId0(pObj, i);
+            Degree = Vec_IntEntry(p->vRank, i) - Vec_IntEntry(p->vRank, iFanin);
+            Vec_IntWriteEntry( p->vDegDiff, 2*i + k, Degree );
+            if ( Vec_IntEntry(p->vDegree, iFanin) < Degree )
+                Vec_IntWriteEntry( p->vDegree, iFanin, Degree );
+        }
+    }
+    Gia_ManForEachCo( p->pOrder, pObj, k )
+    {
+        i      = Gia_ObjId( p->pOrder, pObj );
+        iFanin = Gia_ObjFaninId0(pObj, i);
+        Degree = Vec_IntEntry(p->vRank, i) - Vec_IntEntry(p->vRank, iFanin);
+        Vec_IntWriteEntry( p->vDegDiff, 2*i, Degree );
+        if ( Vec_IntEntry(p->vDegree, iFanin) < Degree )
+            Vec_IntWriteEntry( p->vDegree, iFanin, Degree );
+    }
+    // assign first
+    p->vFirst = Vec_IntAlloc( Gia_ManObjNum(p->pOrder) );
+    p->vStore = Vec_IntStartFull( 2* Gia_ManObjNum(p->pOrder) + Vec_IntSum(p->vDegree) );
+    for ( Shift = i = 0; i < Gia_ManObjNum(p->pOrder); i++ )
+    {
+        Vec_IntPush( p->vFirst, Shift );
+        Vec_IntWriteEntry( p->vStore, Shift, 1 + Vec_IntEntry(p->vDegree, i) ); 
+        Shift += 2 + Vec_IntEntry(p->vDegree, i);
+    }
+    assert( Shift == Vec_IntSize(p->vStore) );
+    // cleanup
+    Vec_IntFreeP( &p->vRank );
+    Vec_IntFreeP( &p->vDegree );
+
+    // print verbose output
+    if ( pPars->fVerbose )
+    {
+        printf( "Convergence = %d.  Dangling objects = %d.  Average degree = %.3f   ", 
+            Vec_IntSize(p->vLimit) - 1,
+            Gia_ManObjNum(pAig) - Gia_ManObjNum(p->pOrder),
+            1.0*Vec_IntSize(p->vStore)/Gia_ManObjNum(p->pOrder) - 1.0  );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManUnrollStop( void * pMan )  
+{
+    Gia_ManUnr_t * p = (Gia_ManUnr_t *)pMan;
+    Gia_ManStopP( &p->pOrder );
+    Vec_IntFreeP( &p->vLimit );
+    Vec_IntFreeP( &p->vRank );
+    Vec_IntFreeP( &p->vDegree );
+    Vec_IntFreeP( &p->vDegDiff );
+    Vec_IntFreeP( &p->vFirst );
+    Vec_IntFreeP( &p->vStore );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reading/writing entry from storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ObjUnrWrite( Gia_ManUnr_t * p, int Id, int Entry )  
+{
+    int i, * pArray = Vec_IntEntryP( p->vStore, Vec_IntEntry(p->vFirst, Id) );
+    for ( i = pArray[0]; i > 1; i-- )
+        pArray[i] = pArray[i-1];
+    pArray[1] = Entry;
+}
+static inline int Gia_ObjUnrRead( Gia_ManUnr_t * p, int Id, int Degree )  
+{
+    int * pArray = Vec_IntEntryP( p->vStore, Vec_IntEntry(p->vFirst, Id) );
+    if ( Id == 0 )
+        return 0;
+    assert( Degree >= 0 && Degree < pArray[0] );
+    if ( Degree )
+        Degree--;
+    return pArray[Degree + 1];
+}
+static inline int Gia_ObjUnrReadCopy0( Gia_ManUnr_t * p, Gia_Obj_t * pObj, int Id )  
+{
+    int Lit = Gia_ObjUnrRead(p, Gia_ObjFaninId0(pObj, Id), Vec_IntEntry(p->vDegDiff, 2*Id));
+    return Abc_LitNotCond( Lit, Gia_ObjFaninC0(pObj) );
+}
+static inline int Gia_ObjUnrReadCopy1( Gia_ManUnr_t * p, Gia_Obj_t * pObj, int Id )  
+{
+    int Lit = Gia_ObjUnrRead(p, Gia_ObjFaninId1(pObj, Id), Vec_IntEntry(p->vDegDiff, 2*Id+1));
+    return Abc_LitNotCond( Lit, Gia_ObjFaninC1(pObj) );
+}
+static inline int Gia_ObjUnrReadCi( Gia_ManUnr_t * p, int Id, int f, Gia_Man_t * pNew )  
+{
+    Gia_Obj_t * pObj = Gia_ManObj( p->pOrder, Id );
+    Gia_Obj_t * pObjReal = Gia_ManObj( p->pAig, pObj->Value );
+    assert( Gia_ObjIsCi(pObjReal) );
+    if ( Gia_ObjIsPi(p->pAig, pObjReal) )
+    {
+        if ( !p->pPars->fSaveLastLit ) 
+            pObj = Gia_ManPi( pNew, Gia_ManPiNum(p->pAig) * f + Gia_ObjCioId(pObjReal) );
+        else
+            pObj = Gia_ManPi( pNew, Gia_ManRegNum(p->pAig) + Gia_ManPiNum(p->pAig) * f + Gia_ObjCioId(pObjReal) );
+        return Abc_Var2Lit( Gia_ObjId(pNew, pObj), 0 );
+    }
+    if ( f == 0 ) // initialize!
+    {
+        if ( p->pPars->fInit )
+            return 0;
+        assert( Gia_ObjCioId(pObjReal) >= Gia_ManPiNum(p->pAig) );
+        if ( !p->pPars->fSaveLastLit ) 
+            pObj = Gia_ManPi( pNew, Gia_ManPiNum(p->pAig) * p->pPars->nFrames + Gia_ObjCioId(pObjReal)-Gia_ManPiNum(p->pAig) );
+        else
+            pObj = Gia_ManPi( pNew, Gia_ObjCioId(pObjReal)-Gia_ManPiNum(p->pAig) );
+        return Abc_Var2Lit( Gia_ObjId(pNew, pObj), 0 );
+    }
+    pObj = Gia_ManObj( p->pOrder, Abc_Lit2Var(Gia_ObjRoToRi(p->pAig, pObjReal)->Value) );
+    assert( Gia_ObjIsCo(pObj) );
+    return Gia_ObjUnrRead( p, Gia_ObjId(p->pOrder, pObj), 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes init/non-init unrolling without flops.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Gia_ManUnrollStart( Gia_Man_t * pAig, Gia_ParFra_t * pPars )
+{
+    Gia_ManUnr_t * p;
+    int f, i;
+    // start 
+    p = Gia_ManUnrStart( pAig, pPars );
+    // start timeframes
+    assert( p->pNew == NULL );
+    p->pNew = Gia_ManStart( 10000 );
+    p->pNew->pName = Abc_UtilStrsav( p->pAig->pName );
+    p->pNew->pSpec = Abc_UtilStrsav( p->pAig->pSpec );
+    Gia_ManHashAlloc( p->pNew );
+    // create combinational inputs
+    if ( !p->pPars->fSaveLastLit ) // only in the case when unrolling depth is known
+        for ( f = 0; f < p->pPars->nFrames; f++ )
+            for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ )
+                Gia_ManAppendCi(p->pNew);
+    // create flop outputs
+    if ( !p->pPars->fInit ) // only in the case when initialization is not performed
+        for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ )
+            Gia_ManAppendCi(p->pNew);
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes init/non-init unrolling without flops.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Gia_ManUnrollAdd( void * pMan, int fMax )
+{
+    Gia_ManUnr_t * p = (Gia_ManUnr_t *)pMan;
+    Gia_Obj_t * pObj;
+    int f, i, Lit, Beg, End;
+    // create PIs on demand
+    if ( p->pPars->fSaveLastLit ) 
+        for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ )
+            Gia_ManAppendCi(p->pNew);
+    // unroll another timeframe
+    for ( f = 0; f < fMax; f++ )
+    {
+        if ( Vec_IntSize(p->vLimit) <= fMax-f )
+            continue;
+        Beg = Vec_IntEntry( p->vLimit, fMax-f-1 );
+        End = Vec_IntEntry( p->vLimit, fMax-f );
+        for ( i = Beg; i < End; i++ )
+        {
+            pObj = Gia_ManObj( p->pOrder, i );
+            if ( Gia_ObjIsAnd(pObj) )
+                Lit = Gia_ManHashAnd( p->pNew, Gia_ObjUnrReadCopy0(p, pObj, i), Gia_ObjUnrReadCopy1(p, pObj, i) );
+            else if ( Gia_ObjIsCo(pObj) )
+            {
+                Lit = Gia_ObjUnrReadCopy0(p, pObj, i);
+                if ( f == fMax-1 )
+                {
+                    if ( p->pPars->fSaveLastLit )
+                        p->LastLit = Lit;
+                    else
+                        Gia_ManAppendCo( p->pNew, Lit );
+                }
+            }
+            else if ( Gia_ObjIsCi(pObj) )
+                Lit = Gia_ObjUnrReadCi( p, i, f, p->pNew );
+            else assert( 0 );
+            assert( Lit >= 0 );
+            Gia_ObjUnrWrite( p, i, Lit ); // should be exactly one call for each obj!
+        }
+    }
+    return p->pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read the last literal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManUnrollLastLit( void * pMan )
+{
+    Gia_ManUnr_t * p = (Gia_ManUnr_t *)pMan;
+    return p->LastLit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes init/non-init unrolling without flops.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManUnroll( Gia_Man_t * pAig, Gia_ParFra_t * pPars )
+{
+    Gia_ManUnr_t * p;
+    Gia_Man_t * pNew, * pTemp;
+    int fMax;
+    p = (Gia_ManUnr_t *)Gia_ManUnrollStart( pAig, pPars );
+    for ( fMax = 1; fMax <= p->pPars->nFrames; fMax++ )
+        Gia_ManUnrollAdd( p, fMax );
+    assert( Gia_ManPoNum(p->pNew) == p->pPars->nFrames * Gia_ManPoNum(p->pAig) );
+    Gia_ManHashStop( p->pNew );
+    Gia_ManSetRegNum( p->pNew, 0 );
+//    Gia_ManPrintStats( pNew, 0 );
+    // cleanup
+    p->pNew = Gia_ManCleanup( pTemp = p->pNew );
+    Gia_ManStop( pTemp );
+//    Gia_ManPrintStats( pNew, 0 );
+    pNew = p->pNew;  p->pNew = NULL;
+    Gia_ManUnrollStop( p );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes init/non-init unrolling without flops.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+Gia_Man_t * Gia_ManUnroll( Gia_ManUnr_t * p )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int fMax, f, i, Lit, Beg, End;
+    // start timeframes
+    pNew = Gia_ManStart( 10000 );
+    pNew->pName = Abc_UtilStrsav( p->pAig->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pAig->pSpec );
+    Gia_ManHashAlloc( pNew );
+    // create combinational inputs
+    for ( f = 0; f < p->pPars->nFrames; f++ )
+        for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ )
+            Gia_ManAppendCi(pNew);
+    if ( !p->pPars->fInit )
+        for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ )
+            Gia_ManAppendCi(pNew);
+    // add nodes to each time-frame
+//    Gia_ObjUnrWrite( p, 0, 0 );
+    for ( fMax = 1; fMax <= p->pPars->nFrames; fMax++ )
+        for ( f = 0; f < fMax; f++ )
+        {
+            if ( Vec_IntSize(p->vLimit) <= fMax-f )
+                continue;
+            Beg = Vec_IntEntry( p->vLimit, fMax-f-1 );
+            End = Vec_IntEntry( p->vLimit, fMax-f );
+            for ( i = Beg; i < End; i++ )
+            {
+                pObj = Gia_ManObj( p->pOrder, i );
+                if ( Gia_ObjIsAnd(pObj) )
+                    Lit = Gia_ManHashAnd( pNew, Gia_ObjUnrReadCopy0(p, pObj, i), Gia_ObjUnrReadCopy1(p, pObj, i) );
+                else if ( Gia_ObjIsCo(pObj) )
+                {
+                    Lit = Gia_ObjUnrReadCopy0(p, pObj, i);
+                    if ( f == fMax-1 )
+                        Gia_ManAppendCo( pNew, Lit );
+                }
+                else if ( Gia_ObjIsCi(pObj) )
+                    Lit = Gia_ObjUnrReadCi( p, i, f, pNew );
+                else assert( 0 );
+                assert( Lit >= 0 );
+                Gia_ObjUnrWrite( p, i, Lit ); // should be exactly one call for each obj!
+            }
+        }
+    assert( Gia_ManPoNum(pNew) == p->pPars->nFrames * Gia_ManPoNum(p->pAig) );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, 0 );
+//    Gia_ManPrintStats( pNew, 0 );
+    // cleanup
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+//    Gia_ManPrintStats( pNew, 0 );
+    return pNew;
+} 
+*/
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFrames2( Gia_Man_t * pAig, Gia_ParFra_t * pPars )
+{
+    Gia_Man_t * pNew;
+    abctime clk = Abc_Clock();
+    pNew = Gia_ManUnroll( pAig, pPars );
+    if ( pPars->fVerbose )
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return pNew;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFraSetDefaultParams( Gia_ParFra_t * p )
+{
+    memset( p, 0, sizeof(Gia_ParFra_t) );
+    p->nFrames      =  32;    // the number of frames to unroll
+    p->fInit        =   0;    // initialize the timeframes
+    p->fVerbose     =   0;    // enables verbose output
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_ManFra_t * Gia_ManFraStart( Gia_Man_t * pAig, Gia_ParFra_t * pPars )  
+{ 
+    Gia_ManFra_t * p;
+    p = ABC_ALLOC( Gia_ManFra_t, 1 );
+    memset( p, 0, sizeof(Gia_ManFra_t) );
+    p->pAig  = pAig;
+    p->pPars = pPars;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFraStop( Gia_ManFra_t * p )  
+{
+    Vec_VecFree( (Vec_Vec_t *)p->vIns );
+    Vec_VecFree( (Vec_Vec_t *)p->vAnds );
+    Vec_VecFree( (Vec_Vec_t *)p->vOuts );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes supports of all timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFraSupports( Gia_ManFra_t * p )
+{
+    Vec_Int_t * vIns = NULL, * vAnds, * vOuts;
+    Gia_Obj_t * pObj;
+    int f, i;
+    p->vIns  = Vec_PtrStart( p->pPars->nFrames );
+    p->vAnds = Vec_PtrStart( p->pPars->nFrames );
+    p->vOuts = Vec_PtrStart( p->pPars->nFrames );
+    Gia_ManIncrementTravId( p->pAig );
+    for ( f = p->pPars->nFrames - 1; f >= 0; f-- )
+    {
+        vOuts = Gia_ManCollectPoIds( p->pAig );
+        if ( vIns )
+        Gia_ManForEachObjVec( vIns, p->pAig, pObj, i )
+            if ( Gia_ObjIsRo(p->pAig, pObj) )
+                Vec_IntPush( vOuts, Gia_ObjId( p->pAig, Gia_ObjRoToRi(p->pAig, pObj) ) );
+        vIns = Vec_IntAlloc( 100 );
+        Gia_ManCollectCis( p->pAig, Vec_IntArray(vOuts), Vec_IntSize(vOuts), vIns );
+        vAnds = Vec_IntAlloc( 100 );
+        Gia_ManCollectAnds( p->pAig, Vec_IntArray(vOuts), Vec_IntSize(vOuts), vAnds );
+        Vec_PtrWriteEntry( p->vIns,  f, vIns );
+        Vec_PtrWriteEntry( p->vAnds, f, vAnds );
+        Vec_PtrWriteEntry( p->vOuts, f, vOuts );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFramesInit( Gia_Man_t * pAig, Gia_ParFra_t * pPars )
+{
+    int fUseAllPis = 1;
+    Gia_Man_t * pFrames, * pTemp;
+    Gia_ManFra_t * p;
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vIns, * vAnds, * vOuts;
+    int i, f;
+    p = Gia_ManFraStart( pAig, pPars );
+    Gia_ManFraSupports( p );
+    pFrames = Gia_ManStart( Vec_VecSizeSize((Vec_Vec_t*)p->vIns)+
+        Vec_VecSizeSize((Vec_Vec_t*)p->vAnds)+Vec_VecSizeSize((Vec_Vec_t*)p->vOuts) );
+    pFrames->pName = Abc_UtilStrsav( pAig->pName );
+    pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec );
+    Gia_ManHashAlloc( pFrames );
+    Gia_ManConst0(pAig)->Value = 0;
+    for ( f = 0; f < pPars->nFrames; f++ )
+    {
+        vIns  = (Vec_Int_t *)Vec_PtrEntry( p->vIns,  f );
+        vAnds = (Vec_Int_t *)Vec_PtrEntry( p->vAnds, f );
+        vOuts = (Vec_Int_t *)Vec_PtrEntry( p->vOuts, f );
+        if ( pPars->fVerbose )
+            printf( "Frame %3d : CI = %6d. AND = %6d. CO = %6d.\n", 
+            f, Vec_IntSize(vIns), Vec_IntSize(vAnds), Vec_IntSize(vOuts) );
+        if ( fUseAllPis )
+        {
+            Gia_ManForEachPi( pAig, pObj, i )
+                pObj->Value = Gia_ManAppendCi( pFrames );
+            if ( f == 0 )
+            {
+                Gia_ManForEachObjVec( vIns, pAig, pObj, i )
+                {
+                    assert( Gia_ObjIsCi(pObj) );
+                    if ( !Gia_ObjIsPi(pAig, pObj) )
+                        pObj->Value = 0;
+                }
+            }
+            else
+            {
+                Gia_ManForEachObjVec( vIns, pAig, pObj, i )
+                {
+                    assert( Gia_ObjIsCi(pObj) );
+                    if ( !Gia_ObjIsPi(pAig, pObj) )
+                        pObj->Value = Gia_ObjRoToRi(pAig, pObj)->Value;
+                }
+            }
+        }
+        else
+        {
+            if ( f == 0 )
+            {
+                Gia_ManForEachObjVec( vIns, pAig, pObj, i )
+                {
+                    assert( Gia_ObjIsCi(pObj) );
+                    if ( Gia_ObjIsPi(pAig, pObj) )
+                        pObj->Value = Gia_ManAppendCi( pFrames );
+                    else
+                        pObj->Value = 0;
+                }
+            }
+            else
+            {
+                Gia_ManForEachObjVec( vIns, pAig, pObj, i )
+                {
+                    assert( Gia_ObjIsCi(pObj) );
+                    if ( Gia_ObjIsPi(pAig, pObj) )
+                        pObj->Value = Gia_ManAppendCi( pFrames );
+                    else
+                        pObj->Value = Gia_ObjRoToRi(pAig, pObj)->Value;
+                }
+            }
+        }
+        Gia_ManForEachObjVec( vAnds, pAig, pObj, i )
+        {
+            assert( Gia_ObjIsAnd(pObj) );
+            pObj->Value = Gia_ManHashAnd( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        }
+        Gia_ManForEachObjVec( vOuts, pAig, pObj, i )
+        {
+            assert( Gia_ObjIsCo(pObj) );
+            if ( Gia_ObjIsPo(pAig, pObj) )
+                pObj->Value = Gia_ManAppendCo( pFrames, Gia_ObjFanin0Copy(pObj) );
+            else
+                pObj->Value = Gia_ObjFanin0Copy(pObj);
+        }
+    }
+    Gia_ManFraStop( p );
+    Gia_ManHashStop( pFrames );
+    if ( Gia_ManCombMarkUsed(pFrames) < Gia_ManAndNum(pFrames) )
+    {
+        pFrames = Gia_ManDupMarked( pTemp = pFrames );
+        if ( pPars->fVerbose )
+            printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", 
+                Gia_ManAndNum(pTemp), Gia_ManAndNum(pFrames) );
+        Gia_ManStop( pTemp );
+    }
+    else if ( pPars->fVerbose )
+            printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", 
+                Gia_ManAndNum(pFrames), Gia_ManAndNum(pFrames) );
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFrames( Gia_Man_t * pAig, Gia_ParFra_t * pPars )
+{
+    Gia_Man_t * pFrames, * pTemp;
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vPoLits = NULL;
+    int i, f;
+    assert( Gia_ManRegNum(pAig) > 0 );
+    assert( pPars->nFrames > 0 );
+    if ( pPars->fInit )
+        return Gia_ManFramesInit( pAig, pPars );
+    if ( pPars->fOrPos )
+        vPoLits = Vec_IntStart( Gia_ManPoNum(pAig) );
+    pFrames = Gia_ManStart( pPars->nFrames * Gia_ManObjNum(pAig) );
+    pFrames->pName = Abc_UtilStrsav( pAig->pName );
+    pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec );
+    if ( !pPars->fDisableSt )
+        Gia_ManHashAlloc( pFrames );
+    Gia_ManConst0(pAig)->Value = 0;
+    // create primary inputs
+    for ( f = 0; f < pPars->nFrames; f++ )
+        Gia_ManForEachPi( pAig, pObj, i )
+            pObj->Value = Gia_ManAppendCi( pFrames );
+    // add internal nodes for each timeframe
+    for ( f = 0; f < pPars->nFrames; f++ )
+    {
+        if ( f == 0 )
+        {
+            Gia_ManForEachRo( pAig, pObj, i )
+                pObj->Value = Gia_ManAppendCi( pFrames );
+        }
+        else
+        {
+            Gia_ManForEachRo( pAig, pObj, i )
+                pObj->Value = Gia_ObjRoToRi( pAig, pObj )->Value;
+        }
+        Gia_ManForEachPi( pAig, pObj, i )
+            pObj->Value = Gia_Obj2Lit( pFrames, Gia_ManPi(pFrames, f * Gia_ManPiNum(pAig) + i) );
+        if ( !pPars->fDisableSt )
+            Gia_ManForEachAnd( pAig, pObj, i )
+                pObj->Value = Gia_ManHashAnd( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else
+            Gia_ManForEachAnd( pAig, pObj, i )
+                pObj->Value = Gia_ManAppendAnd2( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        if ( vPoLits )
+        {
+            if ( !pPars->fDisableSt )
+                Gia_ManForEachPo( pAig, pObj, i )
+                    Vec_IntWriteEntry( vPoLits, i, Gia_ManHashOr(pFrames, Vec_IntEntry(vPoLits, i), Gia_ObjFanin0Copy(pObj)) );
+            else
+                Gia_ManForEachPo( pAig, pObj, i )
+                    Vec_IntWriteEntry( vPoLits, i, Abc_LitNot(Gia_ManAppendAnd2(pFrames, Abc_LitNot(Vec_IntEntry(vPoLits, i)), Abc_LitNot(Gia_ObjFanin0Copy(pObj)))) );
+        }
+        else
+        {
+            Gia_ManForEachPo( pAig, pObj, i )
+                pObj->Value = Gia_ManAppendCo( pFrames, Gia_ObjFanin0Copy(pObj) );
+        }
+        if ( f == pPars->nFrames - 1 )
+        {
+            if ( vPoLits )
+                Gia_ManForEachPo( pAig, pObj, i )
+                    pObj->Value = Gia_ManAppendCo( pFrames, Vec_IntEntry(vPoLits, i) );
+            Gia_ManForEachRi( pAig, pObj, i )
+                pObj->Value = Gia_ManAppendCo( pFrames, Gia_ObjFanin0Copy(pObj) );
+        }
+        else
+        {
+            Gia_ManForEachRi( pAig, pObj, i )
+                pObj->Value = Gia_ObjFanin0Copy(pObj);
+        }
+    }
+    Vec_IntFreeP( &vPoLits );
+    if ( !pPars->fDisableSt )
+        Gia_ManHashStop( pFrames );
+    Gia_ManSetRegNum( pFrames, Gia_ManRegNum(pAig) );
+    if ( Gia_ManCombMarkUsed(pFrames) < Gia_ManAndNum(pFrames) )
+    {
+        pFrames = Gia_ManDupMarked( pTemp = pFrames );
+        if ( pPars->fVerbose )
+            printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", 
+                Gia_ManAndNum(pTemp), Gia_ManAndNum(pFrames) );
+        Gia_ManStop( pTemp );
+    }
+    else if ( pPars->fVerbose )
+            printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", 
+                Gia_ManAndNum(pFrames), Gia_ManAndNum(pFrames) );
+    return pFrames;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Perform init unrolling as long as PO(s) are constant 0.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFramesInitSpecial( Gia_Man_t * pAig, int nFrames, int fVerbose )
+{
+    Gia_Man_t * pFrames, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, f;
+    assert( Gia_ManRegNum(pAig) > 0 );
+    if ( nFrames > 0 )
+        printf( "Computing specialized unrolling with %d frames...\n", nFrames );
+    pFrames = Gia_ManStart( Gia_ManObjNum(pAig) );
+    pFrames->pName = Abc_UtilStrsav( pAig->pName );
+    pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec );
+    Gia_ManHashAlloc( pFrames );
+    Gia_ManConst0(pAig)->Value = 0;
+    for ( f = 0; nFrames == 0 || f < nFrames; f++ )
+    {
+        if ( fVerbose && (f % 100 == 0) )
+        {
+            printf( "%6d : ", f );
+            Gia_ManPrintStats( pFrames, NULL );
+        }
+        Gia_ManForEachRo( pAig, pObj, i )
+            pObj->Value = f ? Gia_ObjRoToRi( pAig, pObj )->Value : 0;
+        Gia_ManForEachPi( pAig, pObj, i )
+            pObj->Value = Gia_ManAppendCi( pFrames );
+        Gia_ManForEachAnd( pAig, pObj, i )
+            pObj->Value = Gia_ManHashAnd( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        Gia_ManForEachPo( pAig, pObj, i )
+            if ( Gia_ObjFanin0Copy(pObj) != 0 )
+                break;
+        if ( i < Gia_ManPoNum(pAig) )
+            break;
+        Gia_ManForEachRi( pAig, pObj, i )
+            pObj->Value = Gia_ObjFanin0Copy(pObj);
+    }
+    if ( fVerbose )
+        printf( "Computed prefix of %d frames.\n", f );
+    Gia_ManForEachRi( pAig, pObj, i )
+        Gia_ManAppendCo( pFrames, pObj->Value );
+    Gia_ManHashStop( pFrames );
+    pFrames = Gia_ManCleanup( pTemp = pFrames );
+    if ( fVerbose )
+        printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", 
+            Gia_ManAndNum(pTemp), Gia_ManAndNum(pFrames) );
+    Gia_ManStop( pTemp );
+    return pFrames;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaFront.c b/abc-build/src/aig/gia/giaFront.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaFront.c
@@ -0,0 +1,295 @@
+/**CFile****************************************************************
+
+  FileName    [giaFront.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Frontier representation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaFront.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Find the next place on the frontier.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManFrontFindNext( char * pFront, int nFront, int iFront )
+{
+    assert( iFront < nFront );
+    for ( ; pFront[iFront]; iFront = (iFront + 1) % nFront );
+    assert( pFront[iFront] == 0 );
+    pFront[iFront] = 1;
+    return iFront;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the frontier manager to its initial state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFrontTransform( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, * pFrontToId; // mapping of nodes into frontier variables
+    assert( p->nFront > 0 );
+    pFrontToId = ABC_FALLOC( int, p->nFront );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjIsCo(pObj) )
+        {
+            assert( pObj->Value == GIA_NONE );
+            pObj->iDiff0 = i - pFrontToId[Gia_ObjDiff0(pObj)];
+        }
+        else if ( Gia_ObjIsAnd(pObj) )
+        {
+            assert( (int)pObj->Value < p->nFront );
+            pObj->iDiff0 = i - pFrontToId[Gia_ObjDiff0(pObj)];
+            pObj->iDiff1 = i - pFrontToId[Gia_ObjDiff1(pObj)];
+            pFrontToId[pObj->Value] = i;
+        }
+        else
+        {
+            assert( (int)pObj->Value < p->nFront );
+            pFrontToId[pObj->Value] = i;
+        }
+        pObj->Value = 0;
+    }
+    ABC_FREE( pFrontToId );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determine the frontier.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCrossCutSimple( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, nCutCur = 0, nCutMax = 0;
+    Gia_ManCreateValueRefs( p );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( pObj->Value )
+            nCutCur++;
+        if ( nCutMax < nCutCur )
+            nCutMax = nCutCur;
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            if ( --Gia_ObjFanin0(pObj)->Value == 0 )
+                nCutCur--;
+            if ( --Gia_ObjFanin1(pObj)->Value == 0 )
+                nCutCur--;
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+        {
+            if ( --Gia_ObjFanin0(pObj)->Value == 0 )
+                nCutCur--;
+        }
+    }
+//    Gia_ManForEachObj( p, pObj, i )
+//        assert( pObj->Value == 0 );
+    return nCutMax;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Determine the frontier.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFront( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj, * pFanin0New, * pFanin1New, * pObjNew;
+    char * pFront;    // places used for the frontier
+    int i, iLit, nCrossCut = 0, nCrossCutMax = 0;
+    int nCrossCutMaxInit = Gia_ManCrossCutSimple( p );
+    int iFront = 0;//, clk = Abc_Clock(); 
+    // set references for all objects
+    Gia_ManCreateValueRefs( p );
+    // start the new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nFront = 1 + (int)((float)1.1 * nCrossCutMaxInit); 
+    // start the frontier
+    pFront = ABC_CALLOC( char, pNew->nFront );
+    // add constant node
+    Gia_ManConst0(pNew)->Value = iFront = Gia_ManFrontFindNext( pFront, pNew->nFront, iFront );
+    if ( Gia_ObjValue(Gia_ManConst0(p)) == 0 )
+        pFront[iFront] = 0;
+    else
+        nCrossCut = 1;
+    // iterate through the objects
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsCi(pObj) )
+        {
+            if ( Gia_ObjValue(pObj) && nCrossCutMax < ++nCrossCut )
+                nCrossCutMax = nCrossCut;
+            // create new node
+            iLit = Gia_ManAppendCi( pNew );
+            pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(iLit) );
+            assert( Gia_ObjId(pNew, pObjNew) == Gia_ObjId(p, pObj) );
+            pObjNew->Value = iFront = Gia_ManFrontFindNext( pFront, pNew->nFront, iFront );
+            // handle CIs without fanout
+            if ( Gia_ObjValue(pObj) == 0 )
+                pFront[iFront] = 0;
+            continue;
+        }
+        if ( Gia_ObjIsCo(pObj) )
+        {
+            assert( Gia_ObjValue(pObj) == 0 );
+            // create new node
+            iLit = Gia_ManAppendCo( pNew, 0 );
+            pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(iLit) );
+            assert( Gia_ObjId(pNew, pObjNew) == Gia_ObjId(p, pObj) );
+            // get the fanin
+            pFanin0New = Gia_ManObj( pNew, Gia_ObjFaninId0(pObj, i) );
+            assert( pFanin0New->Value != GIA_NONE );
+            pObjNew->Value = GIA_NONE;
+            pObjNew->iDiff0 = pFanin0New->Value;
+            pObjNew->fCompl0 = Gia_ObjFaninC0(pObj);
+            // deref the fanin
+            if ( --Gia_ObjFanin0(pObj)->Value == 0 )
+            {
+                pFront[pFanin0New->Value] = 0;
+                nCrossCut--;
+            }
+            continue;
+        }
+        if ( Gia_ObjValue(pObj) && nCrossCutMax < ++nCrossCut )
+            nCrossCutMax = nCrossCut;
+        // create new node
+        pObjNew = Gia_ManAppendObj( pNew );
+        assert( Gia_ObjId(pNew, pObjNew) == Gia_ObjId(p, pObj) );
+        // assign the first fanin
+        pFanin0New = Gia_ManObj( pNew, Gia_ObjFaninId0(pObj, i) );
+        assert( pFanin0New->Value != GIA_NONE );
+        pObjNew->iDiff0 = pFanin0New->Value;
+        pObjNew->fCompl0 = Gia_ObjFaninC0(pObj);
+        // assign the second fanin
+        pFanin1New = Gia_ManObj( pNew, Gia_ObjFaninId1(pObj, i) );
+        assert( pFanin1New->Value != GIA_NONE );
+        pObjNew->iDiff1 = pFanin1New->Value;
+        pObjNew->fCompl1 = Gia_ObjFaninC1(pObj);
+        // assign the frontier number
+        pObjNew->Value = iFront = Gia_ManFrontFindNext( pFront, pNew->nFront, iFront );
+        // deref the fanins
+        if ( --Gia_ObjFanin0(pObj)->Value == 0 )
+        {
+            pFront[pFanin0New->Value] = 0;
+            nCrossCut--;
+        }
+        if ( --Gia_ObjFanin1(pObj)->Value == 0 )
+        {
+            pFront[pFanin1New->Value] = 0;
+            nCrossCut--;
+        }
+        // handle nodes without fanout (choice nodes)
+        if ( Gia_ObjValue(pObj) == 0 )
+            pFront[iFront] = 0;
+    }
+    assert( pNew->nObjs == p->nObjs );
+    assert( nCrossCut == 0 || nCrossCutMax == nCrossCutMaxInit );
+    for ( i = 0; i < pNew->nFront; i++ )
+        assert( pFront[i] == 0 );
+    ABC_FREE( pFront );
+//printf( "Crosscut = %6d. Frontier = %6d. ", nCrossCutMaxInit, pNew->nFront );
+//ABC_PRT( "Time", Abc_Clock() - clk );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFrontTest( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    pNew  = Gia_ManFront( p );
+    Gia_ManFrontTransform( pNew );
+//    Gia_ManCleanValue( p );
+//    Gia_ManCleanValue( pNew );
+    if ( memcmp( pNew->pObjs, p->pObjs, sizeof(Gia_Obj_t) * p->nObjs ) )
+    {
+/*
+        Gia_Obj_t * pObj, * pObjNew;
+        int i;
+        Gia_ManForEachObj( p, pObj, i )
+        {
+            pObjNew = Gia_ManObj( pNew, i );
+            printf( "%5d %5d   %5d %5d\n", 
+                pObj->iDiff0, pObjNew->iDiff0, 
+                pObj->iDiff1, pObjNew->iDiff1 );
+        }
+*/
+        printf( "Verification failed.\n" );
+    }
+    else
+        printf( "Verification successful.\n" );
+    Gia_ManStop( pNew );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaFx.c b/abc-build/src/aig/gia/giaFx.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaFx.c
@@ -0,0 +1,479 @@
+/**CFile****************************************************************
+
+  FileName    [giaFx.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Interface to fast_extract package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaFx.c,v 1.00 2013/09/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "bool/kit/kit.h"
+#include "misc/vec/vecWec.h"
+#include "bool/dec/dec.h"
+#include "opt/dau/dau.h"
+#include "misc/util/utilTruth.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Create GIA for SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManGraphToAig( Gia_Man_t * p, Dec_Graph_t * pGraph )
+{
+    Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized"
+    int i, iAnd0, iAnd1;
+    // check for constant function
+    if ( Dec_GraphIsConst(pGraph) )
+        return Abc_LitNotCond( 1, Dec_GraphIsComplement(pGraph) );
+    // check for a literal
+    if ( Dec_GraphIsVar(pGraph) )
+        return Abc_LitNotCond( Dec_GraphVar(pGraph)->iFunc, Dec_GraphIsComplement(pGraph) );
+    // build the AIG nodes corresponding to the AND gates of the graph
+    Dec_GraphForEachNode( pGraph, pNode, i )
+    {
+        iAnd0 = Abc_LitNotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->iFunc, pNode->eEdge0.fCompl ); 
+        iAnd1 = Abc_LitNotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->iFunc, pNode->eEdge1.fCompl ); 
+        pNode->iFunc = Gia_ManHashAnd( p, iAnd0, iAnd1 );
+    }
+    // complement the result if necessary
+    return Abc_LitNotCond( pNode->iFunc, Dec_GraphIsComplement(pGraph) );
+}
+int Gia_ManSopToAig( Gia_Man_t * p, char * pSop, Vec_Int_t * vLeaves )
+{
+    int i, iAnd, iSum, Value, nFanins;
+    char * pCube;
+    // get the number of variables
+    nFanins = Kit_PlaGetVarNum(pSop);
+    // go through the cubes of the node's SOP
+    iSum = 0;
+    Kit_PlaForEachCube( pSop, nFanins, pCube )
+    {
+        // create the AND of literals
+        iAnd = 1;
+        Kit_PlaCubeForEachVar( pCube, Value, i )
+        {
+            assert( Vec_IntEntry(vLeaves, i) >= 0 );
+            if ( Value == '1' )
+                iAnd = Gia_ManHashAnd( p, iAnd, Vec_IntEntry(vLeaves, i) );
+            else if ( Value == '0' )
+                iAnd = Gia_ManHashAnd( p, iAnd, Abc_LitNot(Vec_IntEntry(vLeaves, i)) );
+            else assert( Value == '-' );
+        }
+        // add to the sum of cubes
+        iSum = Gia_ManHashOr( p, iSum, iAnd );
+    }
+    // decide whether to complement the result
+    if ( Kit_PlaIsComplement(pSop) )
+        iSum = Abc_LitNot(iSum);
+    return iSum;
+}
+int Gia_ManFactorNode( Gia_Man_t * p, char * pSop, Vec_Int_t * vLeaves )
+{
+    if ( Kit_PlaGetVarNum(pSop) == 0 )
+        return Abc_LitNotCond( 1, Kit_PlaIsConst0(pSop) );
+    assert( Kit_PlaGetVarNum(pSop) == Vec_IntSize(vLeaves) );
+    if ( Kit_PlaGetVarNum(pSop) > 2 && Kit_PlaGetCubeNum(pSop) > 1 )
+    {
+        Dec_Graph_t * pFForm;
+        Dec_Node_t * pFFNode;
+        int i, Lit;
+        pFForm = Dec_Factor( pSop );
+        // assign fanins
+        Dec_GraphForEachLeaf( pFForm, pFFNode, i )
+        {
+            assert( Vec_IntEntry(vLeaves, i) >= 0 );
+            pFFNode->iFunc = Vec_IntEntry(vLeaves, i);
+        }
+        // perform strashing
+        Lit = Gia_ManGraphToAig( p, pFForm );
+        Dec_GraphFree( pFForm );
+        return Lit;
+    }
+    return Gia_ManSopToAig( p, pSop, vLeaves );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computing truth tables for the mapped network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Wrd_t * Gia_ManComputeTruths( Gia_Man_t * p, int nCutSize, int nLutNum, int fReverse )
+{
+    Vec_Wrd_t * vTruths;
+    Vec_Int_t vLeaves;
+    word * pTruth;
+    int i, k, nWords;
+    nWords = Abc_Truth6WordNum( nCutSize );
+    vTruths = Vec_WrdAlloc( nWords * nLutNum );
+    Gia_ObjComputeTruthTableStart( p, nCutSize );
+    Gia_ManForEachLut( p, i )
+    {
+        // collect and sort fanins
+        vLeaves.nCap = vLeaves.nSize = Gia_ObjLutSize( p, i );
+        vLeaves.pArray = Gia_ObjLutFanins( p, i );
+        assert( Vec_IntCheckUniqueSmall(&vLeaves) );
+        Vec_IntSelectSort( Vec_IntArray(&vLeaves), Vec_IntSize(&vLeaves) );
+        if ( !fReverse )
+            Vec_IntReverseOrder( &vLeaves );
+        // compute truth table
+        pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, i), &vLeaves );
+        for ( k = 0; k < nWords; k++ )
+            Vec_WrdPush( vTruths, pTruth[k] );
+//        Kit_DsdPrintFromTruth( (unsigned *)pTruth, 6 ); printf( "\n" );
+    }
+    Gia_ObjComputeTruthTableStop( p );
+    assert( Vec_WrdCap(vTruths) == 16 || Vec_WrdSize(vTruths) == Vec_WrdCap(vTruths) );
+    return vTruths;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Extracts information about the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManAssignNumbers( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, Counter = 0;
+    Gia_ManFillValue( p );
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Counter++;
+    Gia_ManForEachLut( p, i )
+        Gia_ManObj(p, i)->Value = Counter++;
+    return Counter;
+}
+Vec_Wec_t * Gia_ManFxRetrieve( Gia_Man_t * p, Vec_Str_t ** pvCompl, int fReverse )
+{
+    Vec_Wec_t * vCubes;
+    Vec_Wrd_t * vTruths;
+    Vec_Int_t * vCube, * vCover;
+    int nItems, nCutSize, nWords;
+    int i, c, v, Lit, Cube, Counter = 0;
+//    abctime clk = Abc_Clock();
+    nItems = Gia_ManAssignNumbers( p );
+    // compute truth tables
+    nCutSize = Gia_ManLutSizeMax( p );
+    nWords = Abc_Truth6WordNum( nCutSize );
+    vTruths = Gia_ManComputeTruths( p, nCutSize, nItems - Gia_ManCiNum(p), fReverse );
+    vCover = Vec_IntAlloc( 1 << 16 );
+    // collect cubes
+    vCubes = Vec_WecAlloc( 1000 );
+    *pvCompl = Vec_StrStart( nItems );
+    Gia_ManForEachLut( p, i )
+    {
+        Gia_Obj_t * pObj = Gia_ManObj( p, i );
+        int nVars = Gia_ObjLutSize( p, i );
+        int * pVars = Gia_ObjLutFanins( p, i );
+        word * pTruth = Vec_WrdEntryP( vTruths, Counter++ * nWords );
+        int Status = Kit_TruthIsop( (unsigned *)pTruth, nVars, vCover, 1 );
+        if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) )
+        {
+            Vec_StrWriteEntry( *pvCompl, pObj->Value, (char)(Vec_IntSize(vCover) == 0) );
+            vCube = Vec_WecPushLevel( vCubes );
+            Vec_IntPush( vCube, pObj->Value );
+            continue;
+        }
+        Vec_StrWriteEntry( *pvCompl, pObj->Value, (char)Status );
+        Vec_IntForEachEntry( vCover, Cube, c )
+        {
+            vCube = Vec_WecPushLevel( vCubes );
+            Vec_IntPush( vCube, pObj->Value );
+            for ( v = 0; v < nVars; v++ )
+            {
+                Lit = 3 & (Cube >> (v << 1));
+                if ( Lit == 1 )
+                    Vec_IntPush( vCube, Abc_Var2Lit(Gia_ManObj(p, pVars[v])->Value, 1) );
+                else if ( Lit == 2 )
+                    Vec_IntPush( vCube, Abc_Var2Lit(Gia_ManObj(p, pVars[v])->Value, 0) );
+                else if ( Lit != 0 )
+                    assert( 0 );
+            }
+            Vec_IntSelectSort( Vec_IntArray(vCube) + 1, Vec_IntSize(vCube) - 1 );
+        }        
+    }
+    assert( Counter * nWords == Vec_WrdSize(vTruths) );
+    Vec_WrdFree( vTruths );
+    Vec_IntFree( vCover );
+//    Abc_PrintTime( 1, "Setup time", Abc_Clock() - clk );
+    return vCubes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generates GIA after factoring the resulting SOPs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFxTopoOrder_rec( Vec_Wec_t * vCubes, Vec_Int_t * vFirst, Vec_Int_t * vCount, Vec_Int_t * vVisit, Vec_Int_t * vOrder, int iObj )
+{
+    int c, v, Lit;
+    int iFirst = Vec_IntEntry( vFirst, iObj );
+    int nCubes = Vec_IntEntry( vCount, iObj ); 
+    assert( !Vec_IntEntry( vVisit, iObj ) );
+    Vec_IntWriteEntry( vVisit, iObj, 1 );
+    for ( c = 0; c < nCubes; c++ )
+    {
+        Vec_Int_t * vCube = Vec_WecEntry( vCubes, iFirst + c );
+        assert( Vec_IntEntry(vCube, 0) == iObj );
+        Vec_IntForEachEntryStart( vCube, Lit, v, 1 )
+            if ( !Vec_IntEntry( vVisit, Abc_Lit2Var(Lit) ) )
+                Gia_ManFxTopoOrder_rec( vCubes, vFirst, vCount, vVisit, vOrder, Abc_Lit2Var(Lit) );
+    }
+    Vec_IntPush( vOrder, iObj );
+}
+Vec_Int_t * Gia_ManFxTopoOrder( Vec_Wec_t * vCubes, int nInputs, int nStart, Vec_Int_t ** pvFirst, Vec_Int_t ** pvCount )
+{
+    Vec_Int_t * vOrder, * vFirst, * vCount, * vVisit, * vCube;
+    int i, iFanin, nNodeMax = -1;
+    // find the largest index
+    Vec_WecForEachLevel( vCubes, vCube, i )
+        nNodeMax = Abc_MaxInt( nNodeMax, Vec_IntEntry(vCube, 0) );
+    nNodeMax++;
+    // quit if there is no new nodes
+    if ( nNodeMax == nStart )
+    {
+        printf( "The network is unchanged by fast extract.\n" );
+        return NULL;
+    }
+    // find first cube and how many cubes
+    vFirst = Vec_IntStart( nNodeMax );
+    vCount = Vec_IntStart( nNodeMax );
+    Vec_WecForEachLevel( vCubes, vCube, i )
+    {
+        iFanin = Vec_IntEntry( vCube, 0 );
+        assert( iFanin >= nInputs );
+        if ( Vec_IntEntry(vCount, iFanin) == 0 )
+            Vec_IntWriteEntry( vFirst, iFanin, i );
+        Vec_IntAddToEntry( vCount, iFanin, 1 );
+    }
+    // put all of them in a topo order
+    vOrder = Vec_IntStart( nInputs );
+    vVisit = Vec_IntStart( nNodeMax );
+    for ( i = 0; i < nInputs; i++ )
+        Vec_IntWriteEntry( vVisit, i, 1 );
+    for ( i = nInputs; i < nNodeMax; i++ )
+        if ( !Vec_IntEntry( vVisit, i ) )
+            Gia_ManFxTopoOrder_rec( vCubes, vFirst, vCount, vVisit, vOrder, i );
+    assert( Vec_IntSize(vOrder) == nNodeMax );
+    Vec_IntFree( vVisit );
+    // return topological order of new nodes
+    *pvFirst = vFirst;
+    *pvCount = vCount;
+    return vOrder;
+}
+Gia_Man_t * Gia_ManFxInsert( Gia_Man_t * p, Vec_Wec_t * vCubes, Vec_Str_t * vCompls )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj; Vec_Str_t * vSop;
+    Vec_Int_t * vOrder, * vFirst, * vCount, * vFanins, * vCover;
+    Vec_Int_t * vCopies, * vCube, * vMap;
+    int k, c, v, Lit, Var, iItem;
+//    abctime clk = Abc_Clock();
+    // prepare the cubes
+    vOrder = Gia_ManFxTopoOrder( vCubes, Gia_ManCiNum(p), Vec_StrSize(vCompls), &vFirst, &vCount );
+    if ( vOrder == NULL )
+        return Gia_ManDup( p );
+    assert( Vec_IntSize(vOrder) > Vec_StrSize(vCompls) );
+    // create new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashStart( pNew );
+    // create primary inputs
+    vMap = Vec_IntStartFull( Vec_IntSize(vOrder) );
+    vCopies = Vec_IntAlloc( Vec_IntSize(vOrder) );
+    Gia_ManForEachCi( p, pObj, k )
+        Vec_IntPush( vCopies, Gia_ManAppendCi(pNew) );
+    Vec_IntFillExtra( vCopies, Vec_IntSize(vOrder), -1 );
+    // add AIG nodes in the topological order
+    vSop = Vec_StrAlloc( 1000 );
+    vCover = Vec_IntAlloc( 1 << 16 );
+    vFanins = Vec_IntAlloc( 100 );
+    Vec_IntForEachEntryStart( vOrder, iItem, k, Gia_ManCiNum(p) )
+    {
+        int iFirst = Vec_IntEntry( vFirst, iItem );
+        int nCubes = Vec_IntEntry( vCount, iItem );
+        // collect fanins
+        Vec_IntClear( vFanins );
+        for ( c = 0; c < nCubes; c++ )
+        {
+            vCube = Vec_WecEntry( vCubes, iFirst + c );
+            Vec_IntForEachEntryStart( vCube, Lit, v, 1 )
+                if ( Vec_IntEntry(vMap, Abc_Lit2Var(Lit)) == -1 )
+                {
+                    Vec_IntWriteEntry( vMap, Abc_Lit2Var(Lit), Vec_IntSize(vFanins) );
+                    Vec_IntPush( vFanins, Abc_Lit2Var(Lit) );
+                }
+        }
+        if ( Vec_IntSize(vFanins) > 6 )
+        {
+            // create SOP
+            Vec_StrClear( vSop );
+            for ( c = 0; c < nCubes; c++ )
+            {
+                for ( v = 0; v < Vec_IntSize(vFanins); v++ )
+                    Vec_StrPush( vSop, '-' );
+                vCube = Vec_WecEntry( vCubes, iFirst + c );
+                Vec_IntForEachEntryStart( vCube, Lit, v, 1 )
+                {
+                    Lit = Abc_Lit2LitV( Vec_IntArray(vMap), Lit );
+                    assert( Lit >= 0 && Abc_Lit2Var(Lit) < Vec_IntSize(vFanins) );
+                    Vec_StrWriteEntry( vSop, Vec_StrSize(vSop) - Vec_IntSize(vFanins) + Abc_Lit2Var(Lit), (char)(Abc_LitIsCompl(Lit)? '0' : '1') );
+                }
+                Vec_StrPush( vSop, ' ' );
+                Vec_StrPush( vSop, '1' );
+                Vec_StrPush( vSop, '\n' );
+            }
+            Vec_StrPush( vSop, '\0' );
+            // collect fanins
+            Vec_IntForEachEntry( vFanins, Var, v )
+            {
+                Vec_IntWriteEntry( vMap, Var, -1 );
+                Vec_IntWriteEntry( vFanins, v, Vec_IntEntry(vCopies, Var) );
+            }
+            // derive new AIG
+            Lit = Gia_ManFactorNode( pNew, Vec_StrArray(vSop), vFanins );
+        }
+        else
+        {
+            word uTruth = 0, uCube;
+            for ( c = 0; c < nCubes; c++ )
+            {
+                uCube = ~(word)0;
+                vCube = Vec_WecEntry( vCubes, iFirst + c );
+                Vec_IntForEachEntryStart( vCube, Lit, v, 1 )
+                {
+                    Lit = Abc_Lit2LitV( Vec_IntArray(vMap), Lit );
+                    assert( Lit >= 0 && Abc_Lit2Var(Lit) < Vec_IntSize(vFanins) );
+                    uCube &= Abc_LitIsCompl(Lit) ? ~s_Truths6[Abc_Lit2Var(Lit)] : s_Truths6[Abc_Lit2Var(Lit)];
+                }
+                uTruth |= uCube;
+            }
+            // complement constant
+            if ( uTruth == 0 )
+                uTruth = ~uTruth;
+            // collect fanins
+            Vec_IntForEachEntry( vFanins, Var, v )
+            {
+                Vec_IntWriteEntry( vMap, Var, -1 );
+                Vec_IntWriteEntry( vFanins, v, Vec_IntEntry(vCopies, Var) );
+            }
+            // create truth table
+            Lit = Dsm_ManTruthToGia( pNew, &uTruth, vFanins, vCover );
+        }
+        // complement if the original SOP was complemented
+        Lit = Abc_LitNotCond( Lit, (iItem < Vec_StrSize(vCompls)) && (Vec_StrEntry(vCompls, iItem) > 0) );
+        // remeber this literal
+        assert( Vec_IntEntry(vCopies, iItem) == -1 );
+        Vec_IntWriteEntry( vCopies, iItem, Lit );
+    }
+    Gia_ManHashStop( pNew );
+    // create primary outputs
+    Gia_ManForEachCo( p, pObj, k )
+    {
+        Lit = Gia_ObjFaninId0p(p, pObj) ? Vec_IntEntry(vCopies, Gia_ObjFanin0(pObj)->Value) : 0;
+        Gia_ManAppendCo( pNew, Abc_LitNotCond( Lit, Gia_ObjFaninC0(pObj) ) );
+    }
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    // cleanup
+    Vec_IntFree( vOrder );
+    Vec_IntFree( vFirst );
+    Vec_IntFree( vCount );
+    Vec_IntFree( vFanins );
+    Vec_IntFree( vCopies );
+    Vec_IntFree( vMap );
+    Vec_StrFree( vSop );
+    Vec_IntFree( vCover );
+    // remove dangling nodes
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+//    Abc_PrintTime( 1, "Setdn time", Abc_Clock() - clk );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs classical fast_extract on logic functions.]
+
+  Description []
+               
+  SideEffects [Sorts the fanins of each cut in the increasing order.]
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManPerformFx( Gia_Man_t * p, int nNewNodesMax, int LitCountMax, int fReverse, int fVerbose, int fVeryVerbose )
+{
+    extern int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitCountMax, int fVerbose, int fVeryVerbose );
+    Gia_Man_t * pNew = NULL;
+    Vec_Wec_t * vCubes;
+    Vec_Str_t * vCompl;
+//    abctime clk;
+    assert( Gia_ManHasMapping(p) );   
+    // collect information
+    vCubes = Gia_ManFxRetrieve( p, &vCompl, fReverse );
+    // call the fast extract procedure
+//    clk = Abc_Clock();
+    Fx_FastExtract( vCubes, Vec_StrSize(vCompl), nNewNodesMax, LitCountMax, fVerbose, fVeryVerbose );
+//    Abc_PrintTime( 1, "Fx runtime", Abc_Clock() - clk );
+    // insert information
+    pNew = Gia_ManFxInsert( p, vCubes, vCompl );
+    // cleanup
+    Vec_WecFree( vCubes );
+    Vec_StrFree( vCompl );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaGiarf.c b/abc-build/src/aig/gia/giaGiarf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaGiarf.c
@@ -0,0 +1,1079 @@
+/**CFile****************************************************************
+
+  FileName    [gia.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// combinational simulation manager
+typedef struct Hcd_Man_t_ Hcd_Man_t;
+struct Hcd_Man_t_
+{
+    // parameters
+    Gia_Man_t *      pGia;           // the AIG to be used for simulation
+    int              nBTLimit;       // internal backtrack limit 
+    int              fVerbose;       // internal verbose flag 
+    // internal variables
+    unsigned *       pSimInfo;       // simulation info for each object
+    Vec_Ptr_t *      vSimInfo;       // pointers to the CI simulation info
+    Vec_Ptr_t *      vSimPres;       // pointers to the presense of simulation info
+    // temporaries
+    Vec_Int_t *      vClassOld;      // old class numbers
+    Vec_Int_t *      vClassNew;      // new class numbers
+    Vec_Int_t *      vClassTemp;     // temporary storage
+    Vec_Int_t *      vRefinedC;      // refined const reprs
+};
+
+static inline unsigned   Hcd_ObjSim( Hcd_Man_t * p, int Id )                  { return p->pSimInfo[Id];      }
+static inline unsigned * Hcd_ObjSimP( Hcd_Man_t * p, int Id )                 { return p->pSimInfo + Id;     }
+static inline unsigned   Hcd_ObjSetSim( Hcd_Man_t * p, int Id, unsigned n )   { return p->pSimInfo[Id] = n;  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the fraiging manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hcd_Man_t * Gia_ManEquivStart( Gia_Man_t * pGia, int nBTLimit, int fVerbose )
+{
+    Hcd_Man_t * p;
+    Gia_Obj_t * pObj;
+    int i;
+    p = ABC_CALLOC( Hcd_Man_t, 1 );
+    p->pGia       = pGia;
+    p->nBTLimit   = nBTLimit;
+    p->fVerbose   = fVerbose;
+    p->pSimInfo   = ABC_ALLOC( unsigned, Gia_ManObjNum(pGia) );
+    p->vClassOld  = Vec_IntAlloc( 100 );
+    p->vClassNew  = Vec_IntAlloc( 100 );
+    p->vClassTemp = Vec_IntAlloc( 100 );
+    p->vRefinedC  = Vec_IntAlloc( 100 );
+    // collect simulation info
+    p->vSimInfo = Vec_PtrAlloc( 1000 );
+    Gia_ManForEachCi( pGia, pObj, i )
+        Vec_PtrPush( p->vSimInfo, Hcd_ObjSimP(p, Gia_ObjId(pGia,pObj)) );
+    p->vSimPres = Vec_PtrAllocSimInfo( Gia_ManCiNum(pGia), 1 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the fraiging manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManEquivStop( Hcd_Man_t * p )
+{
+    Vec_PtrFree( p->vSimInfo );
+    Vec_PtrFree( p->vSimPres );
+    Vec_IntFree( p->vClassOld );
+    Vec_IntFree( p->vClassNew );
+    Vec_IntFree( p->vClassTemp );
+    Vec_IntFree( p->vRefinedC );
+    ABC_FREE( p->pSimInfo );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compared two simulation infos.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Hcd_ManCompareEqual( unsigned s0, unsigned s1 )
+{
+    if ( (s0 & 1) == (s1 & 1) )
+        return s0 == s1;
+    else
+        return s0 ==~s1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares one simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Hcd_ManCompareConst( unsigned s )
+{
+    if ( s & 1 )
+        return s ==~0;
+    else
+        return s == 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates one equivalence class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hcd_ManClassCreate( Gia_Man_t * pGia, Vec_Int_t * vClass )
+{
+    int Repr = -1, EntPrev = -1, Ent, i;
+    assert( Vec_IntSize(vClass) > 0 );
+    Vec_IntForEachEntry( vClass, Ent, i )
+    {
+        if ( i == 0 )
+        {
+            Repr = Ent;
+            Gia_ObjSetRepr( pGia, Ent, -1 );
+            EntPrev = Ent;
+        }
+        else
+        {
+            Gia_ObjSetRepr( pGia, Ent, Repr );
+            Gia_ObjSetNext( pGia, EntPrev, Ent );
+            EntPrev = Ent;
+        }
+    }
+    Gia_ObjSetNext( pGia, EntPrev, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines one equivalence class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hcd_ManClassClassRemoveOne( Hcd_Man_t * p, int i )
+{
+    int iRepr, Ent;
+    if ( Gia_ObjIsConst(p->pGia, i) )
+    {
+        Gia_ObjSetRepr( p->pGia, i, GIA_VOID );
+        return 1;
+    }
+    if ( !Gia_ObjIsClass(p->pGia, i) )
+        return 0;
+    assert( Gia_ObjIsClass(p->pGia, i) );
+    iRepr = Gia_ObjRepr( p->pGia, i );
+    if ( iRepr == GIA_VOID )
+        iRepr = i;
+    // collect nodes
+    Vec_IntClear( p->vClassOld );
+    Vec_IntClear( p->vClassNew );
+    Gia_ClassForEachObj( p->pGia, iRepr, Ent )
+    {
+        if ( Ent == i )
+            Vec_IntPush( p->vClassNew, Ent );
+        else
+            Vec_IntPush( p->vClassOld, Ent );
+    }
+    assert( Vec_IntSize( p->vClassNew ) == 1 );
+    Hcd_ManClassCreate( p->pGia, p->vClassOld );
+    Hcd_ManClassCreate( p->pGia, p->vClassNew );
+    assert( !Gia_ObjIsClass(p->pGia, i) );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines one equivalence class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hcd_ManClassRefineOne( Hcd_Man_t * p, int i )
+{
+    unsigned Sim0, Sim1;
+    int Ent;
+    Vec_IntClear( p->vClassOld );
+    Vec_IntClear( p->vClassNew );
+    Vec_IntPush( p->vClassOld, i );
+    Sim0 = Hcd_ObjSim(p, i);
+    Gia_ClassForEachObj1( p->pGia, i, Ent )
+    {
+        Sim1 = Hcd_ObjSim(p, Ent);
+        if ( Hcd_ManCompareEqual( Sim0, Sim1 ) )
+            Vec_IntPush( p->vClassOld, Ent );
+        else
+            Vec_IntPush( p->vClassNew, Ent );
+    }
+    if ( Vec_IntSize( p->vClassNew ) == 0 )
+        return 0;
+    Hcd_ManClassCreate( p->pGia, p->vClassOld );
+    Hcd_ManClassCreate( p->pGia, p->vClassNew );
+    if ( Vec_IntSize(p->vClassNew) > 1 )
+        return 1 + Hcd_ManClassRefineOne( p, Vec_IntEntry(p->vClassNew,0) );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash key of the simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hcd_ManHashKey( unsigned * pSim, int nWords, int nTableSize )
+{
+    static int s_Primes[16] = { 
+        1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, 
+        4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 };
+    unsigned uHash = 0;
+    int i;
+    if ( pSim[0] & 1 )
+        for ( i = 0; i < nWords; i++ )
+            uHash ^= ~pSim[i] * s_Primes[i & 0xf];
+    else
+        for ( i = 0; i < nWords; i++ )
+            uHash ^=  pSim[i] * s_Primes[i & 0xf];
+    return (int)(uHash % nTableSize);
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Rehashes the refined classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hcd_ManClassesRehash( Hcd_Man_t * p, Vec_Int_t * vRefined )
+{
+    int * pTable, nTableSize, Key, i, k;
+    nTableSize = Abc_PrimeCudd( 100 + Vec_IntSize(vRefined) / 5 );
+    pTable = ABC_CALLOC( int, nTableSize );
+    Vec_IntForEachEntry( vRefined, i, k )
+    {
+        assert( !Hcd_ManCompareConst( Hcd_ObjSim(p, i) ) );
+        Key = Hcd_ManHashKey( Hcd_ObjSimP(p, i), 1, nTableSize );
+        if ( pTable[Key] == 0 )
+            Gia_ObjSetRepr( p->pGia, i, GIA_VOID );
+        else
+        {
+            Gia_ObjSetNext( p->pGia, pTable[Key], i );
+            Gia_ObjSetRepr( p->pGia, i, Gia_ObjRepr(p->pGia, pTable[Key]) );
+            if ( Gia_ObjRepr(p->pGia, i) == GIA_VOID )
+                Gia_ObjSetRepr( p->pGia, i, pTable[Key] );
+        }
+        pTable[Key] = i;
+    }
+    ABC_FREE( pTable );
+//    Gia_ManEquivPrintClasses( p->pGia, 0, 0.0 );
+    // refine classes in the table
+    Vec_IntForEachEntry( vRefined, i, k )
+    {
+        if ( Gia_ObjIsHead( p->pGia, i ) )
+            Hcd_ManClassRefineOne( p, i );
+    }
+    Gia_ManEquivPrintClasses( p->pGia, 0, 0.0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines equivalence classes after simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hcd_ManClassesRefine( Hcd_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Vec_IntClear( p->vRefinedC );
+    Gia_ManForEachAnd( p->pGia, pObj, i )
+    {
+        if ( Gia_ObjIsTail(p->pGia, i) ) // add check for the class level
+        {
+            Hcd_ManClassRefineOne( p, Gia_ObjRepr(p->pGia, i) );
+        }
+        else if ( Gia_ObjIsConst(p->pGia, i) )
+        {
+            if ( !Hcd_ManCompareConst( Hcd_ObjSim(p, i) ) )
+                Vec_IntPush( p->vRefinedC, i );
+        }
+    }
+    Hcd_ManClassesRehash( p, p->vRefinedC );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates equivalence classes for the first time.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hcd_ManClassesCreate( Hcd_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    assert( p->pGia->pReprs == NULL );
+    p->pGia->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p->pGia) );
+    p->pGia->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p->pGia) );
+    Gia_ManForEachObj( p->pGia, pObj, i )
+        Gia_ObjSetRepr( p->pGia, i, Gia_ObjIsAnd(pObj) ? 0 : GIA_VOID );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Initializes simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hcd_ManSimulationInit( Hcd_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachCi( p->pGia, pObj, i )
+        Hcd_ObjSetSim( p, i, (Gia_ManRandom(0) << 1) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one round of simple combinational simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hcd_ManSimulateSimple( Hcd_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    unsigned Res0, Res1;
+    int i;
+    Gia_ManForEachAnd( p->pGia, pObj, i )
+    {
+        Res0 = Hcd_ObjSim( p, Gia_ObjFaninId0(pObj, i) );
+        Res1 = Hcd_ObjSim( p, Gia_ObjFaninId1(pObj, i) );
+        Hcd_ObjSetSim( p, i, (Gia_ObjFaninC0(pObj)? ~Res0: Res0) &
+                             (Gia_ObjFaninC1(pObj)? ~Res1: Res1) );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulate and refine one equivalence class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Gia_Resimulate_rec( Hcd_Man_t * p, int iObj )
+{
+    Gia_Obj_t * pObj;
+    unsigned Res0, Res1;
+    if ( Gia_ObjIsTravIdCurrentId( p->pGia, iObj ) )
+        return Hcd_ObjSim( p, iObj );
+    Gia_ObjSetTravIdCurrentId( p->pGia, iObj );
+    pObj = Gia_ManObj(p->pGia, iObj);
+    if ( Gia_ObjIsCi(pObj) )
+        return Hcd_ObjSim( p, iObj );
+    assert( Gia_ObjIsAnd(pObj) );
+    Res0 = Gia_Resimulate_rec( p, Gia_ObjFaninId0(pObj, iObj) );
+    Res1 = Gia_Resimulate_rec( p, Gia_ObjFaninId1(pObj, iObj) );
+    return Hcd_ObjSetSim( p, iObj, (Gia_ObjFaninC0(pObj)? ~Res0: Res0) &
+                                   (Gia_ObjFaninC1(pObj)? ~Res1: Res1) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulate and refine one equivalence class.]
+
+  Description [Assumes that the counter-example is assigned at the PIs.
+  The counter-example should have the first bit set to 0 at each PI.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ResimulateAndRefine( Hcd_Man_t * p, int i )
+{
+    int RetValue, iObj;
+    Gia_ManIncrementTravId( p->pGia );
+    Gia_ClassForEachObj( p->pGia, i, iObj )
+        Gia_Resimulate_rec( p, iObj );
+    RetValue = Hcd_ManClassRefineOne( p, i );
+    if ( RetValue == 0 )
+        printf( "!!! no refinement !!!\n" );
+//    assert( RetValue );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns temporary representative of the node.]
+
+  Description [The temp repr is the first node among the nodes in the class that
+  (a) precedes the given node, and (b) whose level is lower than the given node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Gia_ObjTempRepr( Gia_Man_t * p, int i, int Level )
+{
+    int iRepr, iMember;
+    iRepr = Gia_ObjRepr( p, i ); 
+    if ( !Gia_ObjProved(p, i) )
+        return NULL;
+    if ( Gia_ObjFailed(p, i) )
+        return NULL;
+    if ( iRepr == GIA_VOID )
+        return NULL;
+    if ( iRepr == 0 )
+        return Gia_ManConst0( p );
+//    if ( p->pLevels[iRepr] < Level )
+//        return Gia_ManObj( p, iRepr );
+    Gia_ClassForEachObj( p, iRepr, iMember )
+    {
+        if ( Gia_ObjFailed(p, iMember) )
+            continue;
+        if ( iMember >= i )
+            return NULL;
+        if ( Gia_ObjLevelId(p, iMember) < Level )
+            return Gia_ManObj( p, iMember );
+    }
+    assert( 0 );
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generates reduced AIG for the given level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_GenerateReducedLevel( Gia_Man_t * p, int Level, Vec_Ptr_t ** pvRoots )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj, * pRepr;
+    Vec_Ptr_t * vRoots;
+    int i;
+    vRoots = Vec_PtrAlloc( 100 );
+    // copy unmarked nodes
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        if ( Gia_ObjLevelId(p, i) > Level )
+            continue;
+        if ( Gia_ObjLevelId(p, i) == Level )
+            Vec_PtrPush( vRoots, pObj );
+        if ( Gia_ObjLevelId(p, i) < Level && (pRepr = Gia_ObjTempRepr(p, i, Level)) )
+        {
+//            printf( "Substituting %d <--- %d\n", Gia_ObjId(p, pRepr), Gia_ObjId(p, pObj) ); 
+            assert( pRepr < pObj );
+            pObj->Value  = Abc_LitNotCond( pRepr->Value, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) );
+            continue;
+        }
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    }
+    *pvRoots = vRoots;
+    // required by SAT solving
+    Gia_ManCreateRefs( pNew );
+    Gia_ManFillValue( pNew );
+    Gia_ManIncrementTravId( pNew ); // needed for MiniSat to record cexes
+//    Gia_ManSetPhase( pNew ); // needed if MiniSat is using polarity -- should not be enabled for TAS because fPhase is used to label
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects relevant classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Gia_CollectRelatedClasses( Gia_Man_t * pGia, Vec_Ptr_t * vRoots )
+{
+    Vec_Ptr_t * vClasses;
+    Gia_Obj_t * pRoot, * pRepr;
+    int i;
+    vClasses = Vec_PtrAlloc( 100 );
+    Gia_ManConst0( pGia )->fMark0 = 1;
+    Vec_PtrForEachEntry( Gia_Obj_t *, vRoots, pRoot, i )
+    {
+        pRepr = Gia_ObjReprObj( pGia, Gia_ObjId(pGia, pRoot) );
+        if ( pRepr == NULL || pRepr->fMark0 )
+            continue;
+        pRepr->fMark0 = 1;
+        Vec_PtrPush( vClasses, pRepr );
+    }
+    Gia_ManConst0( pGia )->fMark0 = 0;
+    Vec_PtrForEachEntry( Gia_Obj_t *, vClasses, pRepr, i )
+        pRepr->fMark0 = 0;
+    return vClasses;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects class members.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Obj_t * Gia_CollectClassMembers( Gia_Man_t * p, Gia_Obj_t * pRepr, Vec_Ptr_t * vMembers, int Level )
+{
+    Gia_Obj_t * pTempRepr = NULL;
+    int iRepr, iMember;
+    iRepr = Gia_ObjId( p, pRepr );
+    Vec_PtrClear( vMembers );
+    Gia_ClassForEachObj( p, iRepr, iMember )
+    {
+        if ( Gia_ObjLevelId(p, iMember) == Level )
+            Vec_PtrPush( vMembers, Gia_ManObj( p, iMember ) );
+        if ( pTempRepr == NULL && Gia_ObjLevelId(p, iMember) < Level )
+            pTempRepr = Gia_ManObj( p, iMember );
+    }
+    return pTempRepr;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Packs patterns into array of simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+*************************************`**********************************/
+int Gia_GiarfStorePatternTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * pLits, int nLits )
+{
+    unsigned * pInfo, * pPres;
+    int i;
+    for ( i = 0; i < nLits; i++ )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i]));
+        pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i]));
+        if ( Abc_InfoHasBit( pPres, iBit ) && 
+             Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) )
+             return 0;
+    }
+    for ( i = 0; i < nLits; i++ )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i]));
+        pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i]));
+        Abc_InfoSetBit( pPres, iBit );
+        if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) )
+            Abc_InfoXorBit( pInfo, iBit );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure to test the new SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_GiarfStorePattern( Vec_Ptr_t * vSimInfo, Vec_Ptr_t * vPres, Vec_Int_t * vCex )
+{
+    int k;
+    for ( k = 1; k < 32; k++ )
+        if ( Gia_GiarfStorePatternTry( vSimInfo, vPres, k, (int *)Vec_IntArray(vCex), Vec_IntSize(vCex) ) )
+            break;
+    return (int)(k < 32);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts pattern into simulation info for the PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_GiarfInsertPattern( Hcd_Man_t * p, Vec_Int_t * vCex, int k )
+{
+    Gia_Obj_t * pObj;
+    unsigned * pInfo;
+    int Lit, i;
+    Vec_IntForEachEntry( vCex, Lit, i )
+    {
+        pObj = Gia_ManCi( p->pGia, Abc_Lit2Var(Lit) );
+        pInfo = Hcd_ObjSimP( p, Gia_ObjId( p->pGia, pObj ) );
+        if ( Abc_InfoHasBit( pInfo, k ) == Abc_LitIsCompl(Lit) )
+            Abc_InfoXorBit( pInfo, k );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts pattern into simulation info for the PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_GiarfPrintClasses( Gia_Man_t * pGia )
+{
+    int nFails  = 0;
+    int nProves = 0;
+    int nTotal  = 0;
+    int nBoth   = 0;
+    int i;
+    for ( i = 0; i < Gia_ManObjNum(pGia); i++ )
+    {
+        nFails  += Gia_ObjFailed(pGia, i);
+        nProves += Gia_ObjProved(pGia, i);
+        nTotal  += Gia_ObjReprObj(pGia, i) != NULL;
+        nBoth   += Gia_ObjFailed(pGia, i) && Gia_ObjProved(pGia, i);
+    }
+    printf( "nFails = %7d.  nProves = %7d.  nBoth = %7d.  nTotal = %7d.\n", 
+        nFails, nProves, nBoth, nTotal );
+}
+
+ABC_NAMESPACE_IMPL_END
+
+#include "proof/cec/cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs computation of AIGs with choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ComputeEquivalencesLevel( Hcd_Man_t * p, Gia_Man_t * pGiaLev, Vec_Ptr_t * vOldRoots, int Level, int fUseMiniSat )
+{
+    int fUse2Solver = 0;
+    Cec_ManSat_t * pSat;
+    Cec_ParSat_t Pars;
+    Tas_Man_t * pTas;
+    Vec_Int_t * vCex;
+    Vec_Ptr_t * vClasses, * vMembers, * vOldRootsNew;
+    Gia_Obj_t * pRoot, * pMember, * pMemberPrev, * pRepr, * pTempRepr;
+    int i, k, nIter, iRoot, iRootNew, iMember, iMemberPrev, status, fOneFailed;//, iRepr;//, fTwoMember;
+    int nSaved = 0, nRecords = 0, nUndec = 0, nClassRefs = 0, nTsat = 0, nMiniSat = 0;
+    clock_t clk, timeTsat = 0, timeMiniSat = 0, timeSim = 0, timeTotal = clock();
+    if ( Vec_PtrSize(vOldRoots) == 0 )
+        return 0;
+    // start SAT solvers
+    Cec_ManSatSetDefaultParams( &Pars );
+    Pars.fPolarFlip = 0;
+    Pars.nBTLimit   = p->nBTLimit;
+    pSat = Cec_ManSatCreate( pGiaLev, &Pars );
+    pTas = Tas_ManAlloc( pGiaLev, p->nBTLimit );
+    if ( fUseMiniSat )
+        vCex = Cec_ManSatReadCex( pSat );
+    else
+        vCex = Tas_ReadModel( pTas );
+    vMembers = Vec_PtrAlloc( 100 );
+    Vec_PtrCleanSimInfo( p->vSimPres, 0, 1 );
+    // resolve constants
+    Vec_PtrForEachEntry( Gia_Obj_t *, vOldRoots, pRoot, i )
+    {
+        iRoot = Gia_ObjId( p->pGia, pRoot );
+        if ( !Gia_ObjIsConst( p->pGia, iRoot ) )
+            continue;
+        iRootNew = Abc_LitNotCond( pRoot->Value, pRoot->fPhase );
+        assert( iRootNew != 1 );
+        if ( fUse2Solver )
+        {
+            nTsat++;
+           clk = clock();
+            status = Tas_ManSolve( pTas, Gia_ObjFromLit(pGiaLev, iRootNew), NULL );
+           timeTsat += clock() - clk;
+            if ( status == -1 )
+            {
+                nMiniSat++;
+               clk = clock();
+                status = Cec_ManSatCheckNode( pSat, Gia_ObjFromLit(pGiaLev, iRootNew) );
+               timeMiniSat += clock() - clk;
+                if ( status == 0 )
+                {
+                    Cec_ManSavePattern( pSat, Gia_ObjFromLit(pGiaLev, iRootNew), NULL );
+                    vCex = Cec_ManSatReadCex( pSat );
+                }
+            }
+            else if ( status == 0 )
+                vCex = Tas_ReadModel( pTas );
+        }
+        else if ( fUseMiniSat )
+        {
+            nMiniSat++;
+           clk = clock();
+            status = Cec_ManSatCheckNode( pSat, Gia_ObjFromLit(pGiaLev, iRootNew) );
+           timeMiniSat += clock() - clk;
+            if ( status == 0 )
+                Cec_ManSavePattern( pSat, Gia_ObjFromLit(pGiaLev, iRootNew), NULL );
+        }
+        else
+        {
+            nTsat++;
+           clk = clock();
+            status = Tas_ManSolve( pTas, Gia_ObjFromLit(pGiaLev, iRootNew), NULL );
+           timeTsat += clock() - clk;
+        }
+        if ( status == -1 ) // undec
+        {
+//            Gia_ObjSetFailed( p->pGia, iRoot );
+            nUndec++;
+//            Hcd_ManClassClassRemoveOne( p, iRoot );
+            Gia_ObjSetFailed( p->pGia, iRoot );
+        }
+        else if ( status == 1 ) // unsat
+        {
+            Gia_ObjSetProved( p->pGia, iRoot );
+//            printf( "proved constant %d\n", iRoot );
+        }
+        else  // sat
+        {
+//            printf( "Disproved constant %d\n", iRoot );
+            Gia_ObjUnsetRepr( p->pGia, iRoot ); // do we need this?
+            nRecords++;
+            nSaved += Gia_GiarfStorePattern( p->vSimInfo, p->vSimPres, vCex );
+        }
+    }
+
+    vClasses = Vec_PtrAlloc( 100 );
+    vOldRootsNew = Vec_PtrAlloc( 100 );
+    for ( nIter = 0; Vec_PtrSize(vOldRoots) > 0; nIter++ )
+    {
+//        printf( "Iter = %d  (Size = %d)\n", nIter, Vec_PtrSize(vOldRoots) );
+        // resolve equivalences 
+        Vec_PtrClear( vClasses );
+        Vec_PtrClear( vOldRootsNew );
+        Gia_ManConst0( p->pGia )->fMark0 = 1;
+        Vec_PtrForEachEntry( Gia_Obj_t *, vOldRoots, pRoot, i )
+        {
+            iRoot = Gia_ObjId( p->pGia, pRoot );
+            if ( Gia_ObjIsHead( p->pGia, iRoot ) )
+                pRepr = pRoot;
+            else if ( Gia_ObjIsClass( p->pGia, iRoot ) )
+                pRepr = Gia_ObjReprObj( p->pGia, iRoot );
+            else
+                continue;
+            if ( pRepr->fMark0 )
+                continue;
+            pRepr->fMark0 = 1;
+            Vec_PtrPush( vClasses, pRepr );
+//            iRepr = Gia_ObjId( p->pGia, pRepr );
+//            fTwoMember = Gia_ClassIsPair(p->pGia, iRepr)
+            // derive temp repr and members on this level
+            pTempRepr = Gia_CollectClassMembers( p->pGia, pRepr, vMembers, Level );
+            if ( pTempRepr )
+                Vec_PtrPush( vMembers, pTempRepr );
+            if ( Vec_PtrSize(vMembers) < 2 )
+                continue;
+            // try proving the members
+            fOneFailed = 0;
+            pMemberPrev = (Gia_Obj_t *)Vec_PtrEntryLast( vMembers );
+            Vec_PtrForEachEntry( Gia_Obj_t *, vMembers, pMember, k )
+            {
+                iMemberPrev = Abc_LitNotCond( pMemberPrev->Value,  pMemberPrev->fPhase ); 
+                iMember     = Abc_LitNotCond( pMember->Value,     !pMember->fPhase ); 
+                assert( iMemberPrev != iMember );
+                if ( fUse2Solver )
+                {
+                    nTsat++;
+                   clk = clock();
+                    status = Tas_ManSolve( pTas, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) );
+                   timeTsat += clock() - clk;
+                    if ( status == -1 )
+                    {
+                        nMiniSat++;
+                       clk = clock();
+                        status = Cec_ManSatCheckNodeTwo( pSat, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) );
+                       timeMiniSat += clock() - clk;
+                        if ( status == 0 )
+                        {
+                            Cec_ManSavePattern( pSat, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) );
+                            vCex = Cec_ManSatReadCex( pSat );
+                        }
+                    }
+                    else if ( status == 0 )
+                        vCex = Tas_ReadModel( pTas );
+                }
+                else if ( fUseMiniSat )
+                {
+                    nMiniSat++;
+                   clk = clock();
+                    status = Cec_ManSatCheckNodeTwo( pSat, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) );
+                   timeMiniSat += clock() - clk;
+                    if ( status == 0 )
+                        Cec_ManSavePattern( pSat, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) );
+                }
+                else
+                {
+                    nTsat++;
+                   clk = clock();
+                    status = Tas_ManSolve( pTas, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) );
+                   timeTsat += clock() - clk;
+                }
+                if ( status == -1 ) // undec
+                {
+//                    Gia_ObjSetFailed( p->pGia, iRoot );
+                    nUndec++;
+                    if ( Gia_ObjLevel(p->pGia, pMemberPrev) > Gia_ObjLevel(p->pGia, pMember) )
+                    {
+//                        Hcd_ManClassClassRemoveOne( p, Gia_ObjId(p->pGia, pMemberPrev) );
+                        Gia_ObjSetFailed( p->pGia, Gia_ObjId(p->pGia, pMemberPrev) );
+                        Gia_ObjSetFailed( p->pGia, Gia_ObjId(p->pGia, pMember) );
+                    }
+                    else
+                    {
+//                        Hcd_ManClassClassRemoveOne( p, Gia_ObjId(p->pGia, pMember) );
+                        Gia_ObjSetFailed( p->pGia, Gia_ObjId(p->pGia, pMemberPrev) );
+                        Gia_ObjSetFailed( p->pGia, Gia_ObjId(p->pGia, pMember) );
+                    }
+                }
+                else if ( status == 1 ) // unsat
+                {
+//                    Gia_ObjSetProved( p->pGia, iRoot );
+                }
+                else  // sat
+                {
+//                    iRepr = Gia_ObjId( p->pGia, pRepr );
+//                    if ( Gia_ClassIsPair(p->pGia, iRepr) )
+//                        Gia_ClassUndoPair(p->pGia, iRepr);
+//                    else
+                    {
+                        fOneFailed = 1;
+                        nRecords++;
+                        nSaved += Gia_GiarfStorePattern( p->vSimInfo, p->vSimPres, vCex );
+                        Gia_GiarfInsertPattern( p, vCex, (k % 31) + 1 );
+                    }
+                }
+                pMemberPrev = pMember;
+//                if ( fOneFailed )
+//                    k += Vec_PtrSize(vMembers) / 4;
+            }
+            // if fail, quit this class
+            if ( fOneFailed )
+            {
+                nClassRefs++;
+                Vec_PtrForEachEntry( Gia_Obj_t *, vMembers, pMember, k )
+                    if ( pMember != pTempRepr && !Gia_ObjFailed(p->pGia, Gia_ObjId(p->pGia, pMember)) )
+                        Vec_PtrPush( vOldRootsNew, pMember );
+                clk = clock();
+                Gia_ResimulateAndRefine( p, Gia_ObjId(p->pGia, pRepr) );
+                timeSim += clock() - clk;
+            }
+            else
+            {
+                Vec_PtrForEachEntry( Gia_Obj_t *, vMembers, pMember, k )
+                    Gia_ObjSetProved( p->pGia, Gia_ObjId(p->pGia, pMember) );
+/*
+//            }
+//            else
+//            {
+                printf( "Proved equivalent: " );
+                Vec_PtrForEachEntry( Gia_Obj_t *, vMembers, pMember, k )
+                    printf( "%d(L=%d)  ", Gia_ObjId(p->pGia, pMember), p->pGia->pLevels[Gia_ObjId(p->pGia, pMember)] );
+                printf( "\n" );
+*/
+            }
+
+        }
+        Vec_PtrClear( vOldRoots );
+        Vec_PtrForEachEntry( Gia_Obj_t *, vOldRootsNew, pMember, i )
+            Vec_PtrPush( vOldRoots, pMember );
+        // clean up
+        Gia_ManConst0( p->pGia )->fMark0 = 0;
+        Vec_PtrForEachEntry( Gia_Obj_t *, vClasses, pRepr, i )
+            pRepr->fMark0 = 0;
+    }
+    Vec_PtrFree( vClasses );
+    Vec_PtrFree( vOldRootsNew );
+    printf( "nSaved = %d   nRecords = %d   nUndec = %d   nClassRefs = %d   nMiniSat = %d   nTas = %d\n", 
+        nSaved, nRecords, nUndec, nClassRefs, nMiniSat, nTsat );
+    ABC_PRT( "Tas    ",  timeTsat );
+    ABC_PRT( "MiniSat",  timeMiniSat );
+    ABC_PRT( "Sim    ",  timeSim );
+    ABC_PRT( "Total  ",  clock() - timeTotal );
+
+    // resimulate
+//    clk = clock();
+    Hcd_ManSimulateSimple( p );
+    Hcd_ManClassesRefine( p );
+//    ABC_PRT( "Simulate/refine", clock() - clk );
+
+    // verify the results
+    Vec_PtrFree( vMembers );
+    Tas_ManStop( pTas );
+    Cec_ManSatStop( pSat );
+    return nIter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs computation of AIGs with choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ComputeEquivalences( Gia_Man_t * pGia, int nBTLimit, int fUseMiniSat, int fVerbose )
+{
+    Hcd_Man_t * p;
+    Vec_Ptr_t * vRoots;
+    Gia_Man_t * pGiaLev;
+    int i, Lev, nLevels, nIters;
+    clock_t clk;
+    Gia_ManRandom( 1 );
+    Gia_ManSetPhase( pGia );
+    nLevels = Gia_ManLevelNum( pGia );
+    Gia_ManIncrementTravId( pGia );
+    // start the manager
+    p = Gia_ManEquivStart( pGia, nBTLimit, fVerbose );
+    // create trivial classes
+    Hcd_ManClassesCreate( p );
+    // refine
+    for ( i = 0; i < 3; i++ )
+    {
+        clk = clock();       
+        Hcd_ManSimulationInit( p );
+        Hcd_ManSimulateSimple( p );
+        ABC_PRT( "Sim", clock() - clk );
+        clk = clock();
+        Hcd_ManClassesRefine( p );
+        ABC_PRT( "Ref", clock() - clk );
+    }
+    // process in the levelized order
+    for ( Lev = 1; Lev < nLevels; Lev++ )
+    {
+        clk = clock();
+        printf( "LEVEL %3d  (out of %3d)   ", Lev, nLevels );
+        pGiaLev = Gia_GenerateReducedLevel( pGia, Lev, &vRoots );
+        nIters = Gia_ComputeEquivalencesLevel( p, pGiaLev, vRoots, Lev, fUseMiniSat );
+        Gia_ManStop( pGiaLev );
+        Vec_PtrFree( vRoots );
+        printf( "Iters = %3d   " );
+        ABC_PRT( "Time", clock() - clk );
+    }
+    Gia_GiarfPrintClasses( pGia );
+    // clean up
+    Gia_ManEquivStop( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaGig.c b/abc-build/src/aig/gia/giaGig.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaGig.c
@@ -0,0 +1,301 @@
+/**CFile****************************************************************
+
+  FileName    [giaGig.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Parser for Gate-Inverter Graph by Niklas Een.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaGig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/extra/extra.h"
+#include "misc/util/utilTruth.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+enum { 
+    GIG_NONE   =  0,
+    GIG_RESET  =  1,
+    GIG_PI     =  2,
+    GIG_PO     =  3,
+    GIG_SEQ    =  4,
+    GIG_LUT    =  5,
+    GIG_DELAY  =  6,
+    GIG_BOX    =  7,
+    GIG_SEL    =  8,
+    GIG_BAR    =  9,
+    GIG_UNUSED = 10     
+};
+
+static char * s_GigNames[GIG_UNUSED] = 
+{
+    "NONE",   // GIG_NONE   = 0
+    "Reset",  // GIG_RESET  = 1
+    "PI",     // GIG_PI     = 2
+    "PO",     // GIG_PO     = 3
+    "Seq",    // GIG_SEQ    = 4
+    "Lut4",   // GIG_LUT    = 5
+    "Delay",  // GIG_DELAY  = 6
+    "Box",    // GIG_BOX    = 7
+    "Sel",    // GIG_SEL    = 8
+    "Bar"     // GIG_BAR    = 9
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Gia_ManGigCount( Vec_Int_t * vObjs, Vec_Int_t * vStore )
+{
+    static int nObjs[GIG_UNUSED]; int i;
+    for ( i = 0; i < GIG_UNUSED; i++ )
+        nObjs[i] = 0;
+    for ( i = 0; i < Vec_IntSize(vObjs); i++ )
+        nObjs[Vec_IntEntry(vStore, Vec_IntEntry(vObjs,i) + 1)]++;
+    return nObjs;
+}
+void Gia_ManGigPrint( int * nObjs )
+{
+    int i;
+    printf( "Statistics:  " );
+    for ( i = 1; i < GIG_UNUSED; i++ )
+        printf( "%s = %d   ", s_GigNames[i], nObjs[i] );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintDelays( Vec_Int_t * vObjs, Vec_Int_t * vStore )
+{
+    Vec_Int_t * vFanCount = Vec_IntStart( Vec_IntSize(vObjs) + 100 );
+    int i, * pEntry;//, Counter = 0;
+    for ( i = 0; i < Vec_IntSize(vObjs); i++ )
+    {
+        pEntry = Vec_IntEntryP( vStore, Vec_IntEntry(vObjs,i) );
+        if ( pEntry[1] != GIG_SEL )
+            continue;
+        assert( pEntry[2] == 1 );
+        Vec_IntAddToEntry( vFanCount, pEntry[3], 1 );
+    }
+    for ( i = 0; i < Vec_IntSize(vObjs); i++ )
+    {
+        pEntry = Vec_IntEntryP( vStore, Vec_IntEntry(vObjs,i) );
+        if ( pEntry[1] != GIG_DELAY )
+            continue;
+        printf( "(%d,%d,%d)  ", pEntry[2], Vec_IntEntry(vFanCount, pEntry[0]), pEntry[3+pEntry[2]] );
+    }
+    printf( "\n" );
+    Vec_IntFree( vFanCount );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManBuildGig2( Vec_Int_t * vObjs, Vec_Int_t * vStore, char * pFileName )
+{
+    Gia_Man_t * pNew, * pTemp;
+    //int * nObjs = Gia_ManGigCount( vObjs, vStore );
+    Vec_Int_t * vNets = Vec_IntAlloc( Vec_IntSize(vObjs) );
+    Vec_Int_t * vTypes = Vec_IntAlloc( Vec_IntSize(vObjs) );
+    Vec_Int_t * vMap;
+    int i, Type;
+    // connect net IDs
+    for ( i = 0; i < Vec_IntSize(vObjs); i++ )
+    {
+        Vec_IntPush( vNets, Vec_IntEntry(vStore, Vec_IntEntry(vObjs,i)) );
+        Vec_IntPush( vTypes, Vec_IntEntry(vStore, Vec_IntEntry(vObjs,i) + 1) );
+    }
+    // create mapping for net IDs into GIA IDs
+    vMap = Vec_IntStartFull( Vec_IntFindMax(vNets) + 1 ); 
+    Vec_IntWriteEntry( vMap, 0, 0 );
+    Vec_IntWriteEntry( vMap, 1, 1 );
+    // create new manager
+    pNew = Gia_ManStart( Vec_IntSize(vObjs) );
+    pNew->pName = Abc_UtilStrsav( pFileName );
+    pNew->pSpec = Abc_UtilStrsav( pFileName );
+    // create primary inputs
+    for ( i = 0; i < Vec_IntSize(vObjs); i++ )
+        if ( Vec_IntEntry(vTypes, i) == GIG_PI )
+            Vec_IntWriteEntry( vMap, Vec_IntEntry(vNets, i), Gia_ManAppendCi(pNew) );
+    // create box outputs
+    for ( i = 0; i < Vec_IntSize(vObjs); i++ )
+        if ( Vec_IntEntry(vTypes, i) == GIG_BOX )
+            Vec_IntWriteEntry( vMap, Vec_IntEntry(vNets, i), Gia_ManAppendCi(pNew) );
+    // create internal nodes
+    Gia_ManHashAlloc( pNew );
+    for ( i = 0; i < Vec_IntSize(vObjs); i++ )
+    {
+        Type = Vec_IntEntry(vTypes, i);
+        if ( Type != GIG_LUT && Type != GIG_DELAY && Type != GIG_BAR )
+            continue;
+
+    }
+    Vec_IntFree( vMap );
+    Vec_IntFree( vNets );
+    Vec_IntFree( vTypes );
+    // rehash
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+Gia_Man_t * Gia_ManBuildGig( Vec_Int_t * vObjs, Vec_Int_t * vStore, char * pFileName )
+{
+    printf( "Parsed %d objects and %d tokens.\n", Vec_IntSize(vObjs), Vec_IntSize(vStore) );
+    Gia_ManGigPrint( Gia_ManGigCount(vObjs, vStore) );
+    Gia_ManPrintDelays( vObjs, vStore );
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManReadGig( char * pFileName )
+{
+    Gia_Man_t * pNew;
+    int Type, Offset, fEndOfLine, Digit, nObjs; 
+    char * pChars  = " w(-,)]\r\t";
+    char * pBuffer = Extra_FileReadContents( pFileName );
+    char * pStart  = pBuffer, * pToken;
+    Vec_Int_t * vObjs, * vStore;
+    if ( pBuffer == NULL )
+        printf( "Cannot open input file %s\n", pFileName );
+    // count objects
+    for ( nObjs = 0, pToken = pBuffer; *pToken; pToken++ )
+        nObjs += (int)(*pToken == '\n');
+    // read objects
+    vObjs  = Vec_IntAlloc( nObjs );
+    vStore = Vec_IntAlloc( 10*nObjs );
+    while ( 1 )
+    {
+        // read net ID
+        pToken = strtok( pStart, pChars );
+        pStart = NULL;
+        if ( pToken == NULL )
+            break;
+        // start new object
+        Vec_IntPush( vObjs, Vec_IntSize(vStore) );
+        // save net ID
+        assert( pToken[0] >= '0' && pToken[0] <= '9' );
+        Vec_IntPush( vStore, atoi(pToken) );
+        // read equal
+        pToken = strtok( pStart, pChars );
+        assert( pToken[0] == '=' );
+        // read type
+        pToken = strtok( pStart, pChars );
+        fEndOfLine = 0;
+        if ( pToken[strlen(pToken)-1] == '\n' )
+        {
+            pToken[strlen(pToken)-1] = 0;
+            fEndOfLine = 1;
+        }
+        for ( Type = GIG_RESET; Type < GIG_UNUSED; Type++ )
+            if ( !strcmp(pToken, s_GigNames[Type]) )
+                break;
+        assert( Type < GIG_UNUSED );
+        Vec_IntPush( vStore, Type );
+        if ( fEndOfLine )
+            continue;
+        // read fanins
+        Offset = Vec_IntSize(vStore);
+        Vec_IntPush( vStore, 0 );
+        while ( 1 )
+        {
+            pToken = strtok( pStart, pChars );
+            if ( pToken == NULL || pToken[0] == '\n' || pToken[0] == '[' )
+                break;
+            assert( pToken[0] >= '0' && pToken[0] <= '9' );
+            Vec_IntPush( vStore, atoi(pToken) );
+            Vec_IntAddToEntry( vStore, Offset, 1 );
+        }
+        assert( pToken != NULL );
+        if ( pToken[0] == '\n' )
+            continue;
+        assert( pToken[0] == '[' );
+        // read attribute
+        pToken++;
+        if ( Type == GIG_LUT )
+        {
+            assert( strlen(pToken) == 4 );
+            Digit  = Abc_TtReadHexDigit(pToken[0]);
+            Digit |= Abc_TtReadHexDigit(pToken[1]) << 4;
+            Digit |= Abc_TtReadHexDigit(pToken[2]) << 8;
+            Digit |= Abc_TtReadHexDigit(pToken[3]) << 12;
+            Vec_IntPush( vStore, Digit );
+        }
+        else
+        {
+            assert( Type == GIG_DELAY );
+            Vec_IntPush( vStore, atoi(pToken) );
+        }
+        // read end of line
+        pToken = strtok( pStart, pChars );
+        assert( pToken[0] == '\n' );
+    }
+    ABC_FREE( pBuffer );
+    // create AIG
+    pNew = Gia_ManBuildGig( vObjs, vStore, pFileName );
+    // cleanup
+    Vec_IntFree( vObjs );
+    Vec_IntFree( vStore );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaGlitch.c b/abc-build/src/aig/gia/giaGlitch.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaGlitch.c
@@ -0,0 +1,787 @@
+/**CFile****************************************************************
+
+  FileName    [giaGlitch.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Glitch simulation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaGlitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Gli_Obj_t_ Gli_Obj_t;
+struct Gli_Obj_t_
+{
+    unsigned       fTerm    :  1;    // terminal node
+    unsigned       fPhase   :  1;    // value under 000 pattern
+    unsigned       fPhase2  :  1;    // value under 000 pattern
+    unsigned       fMark    :  1;    // user-controlled mark
+    unsigned       nFanins  :  3;    // the number of fanins
+    unsigned       nFanouts : 25;    // total number of fanouts
+    unsigned       Handle;           // ID of the node
+    unsigned       uTruth[2];        // truth table of the node
+    unsigned       uSimInfo;         // simulation info of the node
+    union 
+    {
+        int        iFanin;           // the number of fanins added
+        int        nSwitches;        // the number of switches
+    };
+    union 
+    {
+        int        iFanout;          // the number of fanouts added
+        int        nGlitches;        // the number of glitches ( nGlitches >= nSwitches )
+    };
+    int            Fanios[0];        // the array of fanins/fanouts
+};
+
+typedef struct Gli_Man_t_ Gli_Man_t;
+struct Gli_Man_t_
+{
+    Vec_Int_t *    vCis;             // the vector of CIs (PIs + LOs)
+    Vec_Int_t *    vCos;             // the vector of COs (POs + LIs)
+    Vec_Int_t *    vCisChanged;      // the changed CIs
+    Vec_Int_t *    vAffected;        // the affected nodes
+    Vec_Int_t *    vFrontier;        // the fanouts of these nodes
+    int            nObjs;            // the number of objects
+    int            nRegs;            // the number of registers
+    int            nTravIds;         // traversal ID of the network
+    int            iObjData;         // pointer to the current data
+    int            nObjData;         // the size of array to store the logic network
+    int *          pObjData;         // the internal nodes
+    unsigned *     pSimInfoPrev;     // previous values of the CIs
+};
+
+
+static inline int         Gli_ManCiNum( Gli_Man_t * p )            { return Vec_IntSize(p->vCis);                                         }
+static inline int         Gli_ManCoNum( Gli_Man_t * p )            { return Vec_IntSize(p->vCos);                                         }
+static inline int         Gli_ManPiNum( Gli_Man_t * p )            { return Vec_IntSize(p->vCis) - p->nRegs;                              }
+static inline int         Gli_ManPoNum( Gli_Man_t * p )            { return Vec_IntSize(p->vCos) - p->nRegs;                              }
+static inline int         Gli_ManRegNum( Gli_Man_t * p )           { return p->nRegs;                                                     }
+static inline int         Gli_ManObjNum( Gli_Man_t * p )           { return p->nObjs;                                                     } 
+static inline int         Gli_ManNodeNum( Gli_Man_t * p )          { return p->nObjs - Vec_IntSize(p->vCis) - Vec_IntSize(p->vCos);       } 
+
+static inline Gli_Obj_t * Gli_ManObj( Gli_Man_t * p, int v )       { return (Gli_Obj_t *)(p->pObjData + v);                               } 
+static inline Gli_Obj_t * Gli_ManCi( Gli_Man_t * p, int v )        { return Gli_ManObj( p, Vec_IntEntry(p->vCis,v) );                     }
+static inline Gli_Obj_t * Gli_ManCo( Gli_Man_t * p, int v )        { return Gli_ManObj( p, Vec_IntEntry(p->vCos,v) );                     }
+static inline Gli_Obj_t * Gli_ManPi( Gli_Man_t * p, int v )        { assert( v < Gli_ManPiNum(p) );  return Gli_ManCi( p, v );            }
+static inline Gli_Obj_t * Gli_ManPo( Gli_Man_t * p, int v )        { assert( v < Gli_ManPoNum(p) );  return Gli_ManCo( p, v );            }
+static inline Gli_Obj_t * Gli_ManRo( Gli_Man_t * p, int v )        { assert( v < Gli_ManRegNum(p) ); return Gli_ManCi( p, Gli_ManRegNum(p)+v );      }
+static inline Gli_Obj_t * Gli_ManRi( Gli_Man_t * p, int v )        { assert( v < Gli_ManRegNum(p) ); return Gli_ManCo( p, Gli_ManRegNum(p)+v );      }
+
+static inline int         Gli_ObjIsTerm( Gli_Obj_t * pObj )        { return pObj->fTerm;                                                  } 
+static inline int         Gli_ObjIsCi( Gli_Obj_t * pObj )          { return pObj->fTerm && pObj->nFanins == 0;                            } 
+static inline int         Gli_ObjIsCo( Gli_Obj_t * pObj )          { return pObj->fTerm && pObj->nFanins == 1;                            } 
+static inline int         Gli_ObjIsNode( Gli_Obj_t * pObj )        { return!pObj->fTerm;                                                  } 
+
+static inline int         Gli_ObjFaninNum( Gli_Obj_t * pObj )      { return pObj->nFanins;                                                } 
+static inline int         Gli_ObjFanoutNum( Gli_Obj_t * pObj )     { return pObj->nFanouts;                                               } 
+static inline int         Gli_ObjSize( Gli_Obj_t * pObj )          { return sizeof(Gli_Obj_t) / 4 + pObj->nFanins + pObj->nFanouts;       } 
+
+static inline Gli_Obj_t * Gli_ObjFanin( Gli_Obj_t * pObj, int i )  { return (Gli_Obj_t *)(((int *)pObj) - pObj->Fanios[i]);               } 
+static inline Gli_Obj_t * Gli_ObjFanout( Gli_Obj_t * pObj, int i ) { return (Gli_Obj_t *)(((int *)pObj) + pObj->Fanios[pObj->nFanins+i]); } 
+
+#define Gli_ManForEachObj( p, pObj, i )                 \
+    for ( i = 0; (i < p->nObjData) && (pObj = Gli_ManObj(p,i)); i += Gli_ObjSize(pObj) )
+#define Gli_ManForEachNode( p, pObj, i )                \
+    for ( i = 0; (i < p->nObjData) && (pObj = Gli_ManObj(p,i)); i += Gli_ObjSize(pObj) ) if ( Gli_ObjIsTerm(pObj) ) {} else
+
+#define Gli_ManForEachEntry( vVec, p, pObj, i )         \
+    for ( i = 0; (i < Vec_IntSize(vVec)) && (pObj = Gli_ManObj(p,Vec_IntEntry(vVec,i))); i++ )
+#define Gli_ManForEachCi( p, pObj, i )                  \
+    for ( i = 0; (i < Vec_IntSize(p->vCis)) && (pObj = Gli_ManObj(p,Vec_IntEntry(p->vCis,i))); i++ )
+#define Gli_ManForEachCo( p, pObj, i )                  \
+    for ( i = 0; (i < Vec_IntSize(p->vCos)) && (pObj = Gli_ManObj(p,Vec_IntEntry(p->vCos,i))); i++ )
+
+#define Gli_ManForEachPi( p, pObj, i )                                  \
+    for ( i = 0; (i < Gli_ManPiNum(p)) && ((pObj) = Gli_ManCi(p, i)); i++ )
+#define Gli_ManForEachPo( p, pObj, i )                                  \
+    for ( i = 0; (i < Gli_ManPoNum(p)) && ((pObj) = Gli_ManCo(p, i)); i++ )
+#define Gli_ManForEachRo( p, pObj, i )                                  \
+    for ( i = 0; (i < Gli_ManRegNum(p)) && ((pObj) = Gli_ManCi(p, Gli_ManPiNum(p)+i)); i++ )
+#define Gli_ManForEachRi( p, pObj, i )                                  \
+    for ( i = 0; (i < Gli_ManRegNum(p)) && ((pObj) = Gli_ManCo(p, Gli_ManPoNum(p)+i)); i++ )
+#define Gli_ManForEachRiRo( p, pObjRi, pObjRo, i )                      \
+    for ( i = 0; (i < Gli_ManRegNum(p)) && ((pObjRi) = Gli_ManCo(p, Gli_ManPoNum(p)+i)) && ((pObjRo) = Gli_ManCi(p, Gli_ManPiNum(p)+i)); i++ )
+
+#define Gli_ObjForEachFanin( pObj, pNext, i )           \
+    for ( i = 0; (i < (int)pObj->nFanins) && (pNext = Gli_ObjFanin(pObj,i)); i++ )
+#define Gli_ObjForEachFanout( pObj, pNext, i )          \
+    for ( i = 0; (i < (int)pObj->nFanouts) && (pNext = Gli_ObjFanout(pObj,i)); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates logic network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gli_Man_t * Gli_ManAlloc( int nObjs, int nRegs, int nFanioPairs )
+{
+    Gli_Man_t * p;
+    p = (Gli_Man_t *)ABC_CALLOC( int, (sizeof(Gli_Man_t) / 4) + (sizeof(Gli_Obj_t) / 4) * nObjs + 2 * nFanioPairs );
+    p->nRegs = nRegs;
+    p->vCis = Vec_IntAlloc( 1000 );
+    p->vCos = Vec_IntAlloc( 1000 );
+    p->vCisChanged = Vec_IntAlloc( 1000 );
+    p->vAffected = Vec_IntAlloc( 1000 );
+    p->vFrontier = Vec_IntAlloc( 1000 );
+    p->nObjData = (sizeof(Gli_Obj_t) / 4) * nObjs + 2 * nFanioPairs;
+    p->pObjData = (int *)(p + 1);
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes logic network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gli_ManStop( Gli_Man_t * p )
+{
+    Vec_IntFree( p->vCis );
+    Vec_IntFree( p->vCos );
+    Vec_IntFree( p->vCisChanged );
+    Vec_IntFree( p->vAffected );
+    Vec_IntFree( p->vFrontier );
+    ABC_FREE( p->pSimInfoPrev );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks logic network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gli_ManPrintObjects( Gli_Man_t * p )
+{
+    Gli_Obj_t * pObj, * pNext;
+    int i, k;
+    Gli_ManForEachObj( p, pObj, i )
+    {
+        printf( "Node %d \n", pObj->Handle );
+        printf( "Fanins: " );
+        Gli_ObjForEachFanin( pObj, pNext, k )
+            printf( "%d ", pNext->Handle );
+        printf( "\n" );
+        printf( "Fanouts: " );
+        Gli_ObjForEachFanout( pObj, pNext, k )
+            printf( "%d ", pNext->Handle );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks logic network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gli_ManFinalize( Gli_Man_t * p )
+{
+    Gli_Obj_t * pObj;
+    int i;
+    assert( p->iObjData == p->nObjData );
+    Gli_ManForEachObj( p, pObj, i )
+    {
+        assert( pObj->iFanin == (int)pObj->nFanins );
+        assert( pObj->iFanout == (int)pObj->nFanouts );
+        pObj->iFanin = 0;
+        pObj->iFanout = 0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates fanin/fanout pair.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gli_ObjAddFanin( Gli_Obj_t * pObj, Gli_Obj_t * pFanin )
+{ 
+    assert( pObj->iFanin < (int)pObj->nFanins );
+    assert( pFanin->iFanout < (int)pFanin->nFanouts );
+    pFanin->Fanios[pFanin->nFanins + pFanin->iFanout++] = 
+    pObj->Fanios[pObj->iFanin++] = pObj->Handle - pFanin->Handle;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Allocates object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gli_Obj_t * Gli_ObjAlloc( Gli_Man_t * p, int nFanins, int nFanouts )
+{
+    Gli_Obj_t * pObj;
+    pObj = Gli_ManObj( p, p->iObjData );
+    pObj->Handle   = p->iObjData;
+    pObj->nFanins  = nFanins;
+    pObj->nFanouts = nFanouts;
+    p->iObjData += Gli_ObjSize( pObj );
+    p->nObjs++;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates CI.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gli_ManCreateCi( Gli_Man_t * p, int nFanouts )
+{
+    Gli_Obj_t * pObj;
+    pObj = Gli_ObjAlloc( p, 0, nFanouts );
+    pObj->fTerm = 1;
+    Vec_IntPush( p->vCis, pObj->Handle );
+    return pObj->Handle;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates CO.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gli_ManCreateCo( Gli_Man_t * p, int iFanin )
+{
+    Gli_Obj_t * pObj, * pFanin;
+    pObj = Gli_ObjAlloc( p, 1, 0 );
+    pObj->fTerm = 1;
+    pFanin = Gli_ManObj( p, iFanin );
+    Gli_ObjAddFanin( pObj, pFanin );
+    pObj->fPhase = pObj->fPhase2 = pFanin->fPhase;
+    Vec_IntPush( p->vCos, pObj->Handle );
+    return pObj->Handle;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gli_NodeComputeValue( Gli_Obj_t * pNode )
+{
+    int i, Phase = 0;
+    for ( i = 0; i < (int)pNode->nFanins; i++ )
+        Phase |= (Gli_ObjFanin(pNode, i)->fPhase << i);
+    return Abc_InfoHasBit( pNode->uTruth, Phase );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gli_NodeComputeValue2( Gli_Obj_t * pNode )
+{
+    int i, Phase = 0;
+    for ( i = 0; i < (int)pNode->nFanins; i++ )
+        Phase |= (Gli_ObjFanin(pNode, i)->fPhase2 << i);
+    return Abc_InfoHasBit( pNode->uTruth, Phase );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gli_ManCreateNode( Gli_Man_t * p, Vec_Int_t * vFanins, int nFanouts, unsigned * puTruth )
+{
+    Gli_Obj_t * pObj, * pFanin;
+    int i;
+    assert( Vec_IntSize(vFanins) <= 6 );
+    pObj = Gli_ObjAlloc( p, Vec_IntSize(vFanins), nFanouts );
+    Gli_ManForEachEntry( vFanins, p, pFanin, i )
+        Gli_ObjAddFanin( pObj, pFanin );
+    pObj->uTruth[0] = puTruth[0];
+    pObj->uTruth[1] = puTruth[Vec_IntSize(vFanins) == 6];
+    pObj->fPhase = pObj->fPhase2 = Gli_NodeComputeValue( pObj );
+    return pObj->Handle;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of switches of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gli_ObjNumSwitches( Gli_Man_t * p, int iNode )
+{
+    return Gli_ManObj( p, iNode )->nSwitches;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of glitches of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gli_ObjNumGlitches( Gli_Man_t * p, int iNode )
+{
+    return Gli_ManObj( p, iNode )->nGlitches;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sets random info at the PIs and collects changed PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gli_ManSetPiRandom( Gli_Man_t * p, float PiTransProb )
+{
+    Gli_Obj_t * pObj;
+    float Multi = 1.0 / (1 << 16);
+    int i;
+    assert( 0.0 < PiTransProb && PiTransProb < 1.0 );
+    Vec_IntClear( p->vCisChanged );
+    Gli_ManForEachCi( p, pObj, i )
+        if ( Multi * (Gia_ManRandom(0) & 0xffff) < PiTransProb )
+        {
+            Vec_IntPush( p->vCisChanged, pObj->Handle );
+            pObj->fPhase  ^= 1;
+            pObj->fPhase2 ^= 1;
+            pObj->nSwitches++;
+            pObj->nGlitches++;
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets random info at the PIs and collects changed PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gli_ManSetPiFromSaved( Gli_Man_t * p, int iBit )
+{
+    Gli_Obj_t * pObj;
+    int i;
+    Vec_IntClear( p->vCisChanged );
+    Gli_ManForEachCi( p, pObj, i )
+        if ( (p->pSimInfoPrev[i] ^ pObj->uSimInfo) & (1 << iBit) )
+        {
+            Vec_IntPush( p->vCisChanged, pObj->Handle );
+            pObj->fPhase  ^= 1;
+            pObj->fPhase2 ^= 1;
+            pObj->nSwitches++;
+            pObj->nGlitches++;
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes switching activity of each node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gli_ManSwitching( Gli_Man_t * p )
+{
+    Gli_Obj_t * pThis;
+    int i;
+    Gli_ManForEachNode( p, pThis, i )
+    {
+        if ( ((int)pThis->fPhase) == Gli_NodeComputeValue(pThis) )
+            continue;
+        pThis->fPhase ^= 1;
+        pThis->nSwitches++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes glitching activity of each node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gli_ManGlitching( Gli_Man_t * p )
+{
+    Gli_Obj_t * pThis, * pFanout;//, * pOther = Gli_ManObj(p, 41);
+    int i, k, Handle;
+//    Gli_ManForEachObj( p, pThis, i )
+//        assert( pThis->fMark == 0 );
+    // start the array of affected nodes
+    Vec_IntClear( p->vAffected );
+    Vec_IntForEachEntry( p->vCisChanged, Handle, i )
+        Vec_IntPush( p->vAffected, Handle );
+    // iteration propagation
+    while ( Vec_IntSize(p->vAffected) > 0 )
+    {
+        // compute the frontier
+        Vec_IntClear( p->vFrontier );
+        Gli_ManForEachEntry( p->vAffected, p, pThis, i )
+        {
+            Gli_ObjForEachFanout( pThis, pFanout, k )
+            {
+                if ( Gli_ObjIsCo(pFanout) )
+                    continue;
+                if ( pFanout->fMark )
+                    continue;
+                pFanout->fMark = 1;
+                Vec_IntPush( p->vFrontier, pFanout->Handle );
+            }
+        }
+        // compute the next set of affected nodes
+        Vec_IntClear( p->vAffected );
+        Gli_ManForEachEntry( p->vFrontier, p, pThis, i )
+        {
+            pThis->fMark = 0;
+            if ( ((int)pThis->fPhase2) == Gli_NodeComputeValue2(pThis) )
+                continue;
+            pThis->fPhase2 ^= 1;
+            pThis->nGlitches++;
+            Vec_IntPush( p->vAffected, pThis->Handle );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks that the resulting values are the same.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gli_ManVerify( Gli_Man_t * p )
+{
+    Gli_Obj_t * pObj;
+    int i;
+    Gli_ManForEachObj( p, pObj, i )
+    {
+        assert( pObj->fPhase == pObj->fPhase2 );
+        assert( pObj->nGlitches >= pObj->nSwitches );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Gli_ManSimulateSeqNode( Gli_Man_t * p, Gli_Obj_t * pNode )
+{
+    unsigned pSimInfos[6], Result = 0;
+    int nFanins = Gli_ObjFaninNum(pNode);
+    int i, k, Phase;
+    Gli_Obj_t * pFanin;
+    assert( nFanins <= 6 );
+    Gli_ObjForEachFanin( pNode, pFanin, i )
+        pSimInfos[i] = pFanin->uSimInfo;
+    for ( i = 0; i < 32; i++ )
+    {
+        Phase = 0;
+        for ( k = 0; k < nFanins; k++ )
+            if ( (pSimInfos[k] >> i) & 1 )
+                Phase |= (1 << k);
+        if ( Abc_InfoHasBit( pNode->uTruth, Phase ) )
+            Result |= (1 << i);
+    }
+    return Result;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Gli_ManUpdateRandomInput( unsigned uInfo, float PiTransProb )
+{
+    float Multi = 1.0 / (1 << 16);
+    int i;
+    if ( PiTransProb == 0.5 )
+        return Gia_ManRandom(0);
+    for ( i = 0; i < 32; i++ )
+        if ( Multi * (Gia_ManRandom(0) & 0xffff) < PiTransProb )
+            uInfo ^= (1 << i);
+    return uInfo;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates sequential network randomly for the given number of frames.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gli_ManSimulateSeqPref( Gli_Man_t * p, int nPref )
+{
+    Gli_Obj_t * pObj, * pObjRi, * pObjRo;
+    int i, f;
+    // initialize simulation data
+    Gli_ManForEachPi( p, pObj, i )
+        pObj->uSimInfo = Gli_ManUpdateRandomInput( pObj->uSimInfo, 0.5 );
+    Gli_ManForEachRo( p, pObj, i )
+        pObj->uSimInfo = 0;
+    for ( f = 0; f < nPref; f++ )
+    {
+        // simulate one frame
+        Gli_ManForEachNode( p, pObj, i )
+            pObj->uSimInfo = Gli_ManSimulateSeqNode( p, pObj );
+        Gli_ManForEachRi( p, pObj, i )
+            pObj->uSimInfo = Gli_ObjFanin(pObj, 0)->uSimInfo;
+        // initialize the next frame
+        Gli_ManForEachPi( p, pObj, i )
+            pObj->uSimInfo = Gli_ManUpdateRandomInput( pObj->uSimInfo, 0.5 );
+        Gli_ManForEachRiRo( p, pObjRi, pObjRo, i )
+            pObjRo->uSimInfo = pObjRi->uSimInfo;
+    }
+    // save simulation data after nPref timeframes
+    if ( p->pSimInfoPrev == NULL )
+        p->pSimInfoPrev = ABC_ALLOC( unsigned, Gli_ManCiNum(p) );
+    Gli_ManForEachCi( p, pObj, i )
+        p->pSimInfoPrev[i] = pObj->uSimInfo;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Initialized object values to be one pattern in the saved data.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gli_ManSetDataSaved( Gli_Man_t * p, int iBit )
+{
+    Gli_Obj_t * pObj;
+    int i;
+    Gli_ManForEachCi( p, pObj, i )
+        pObj->fPhase = pObj->fPhase2 = ((p->pSimInfoPrev[i] >> iBit) & 1);
+    Gli_ManForEachNode( p, pObj, i )
+        pObj->fPhase = pObj->fPhase2 = Gli_NodeComputeValue( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets random info at the PIs and collects changed PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gli_ManSetPiRandomSeq( Gli_Man_t * p, float PiTransProb )
+{
+    Gli_Obj_t * pObj, * pObjRi;
+    float Multi = 1.0 / (1 << 16);
+    int i;
+    assert( 0.0 < PiTransProb && PiTransProb < 1.0 );
+    // transfer data to the COs
+    Gli_ManForEachCo( p, pObj, i )
+        pObj->fPhase = pObj->fPhase2 = Gli_ObjFanin(pObj, 0)->fPhase;
+    // set changed PIs
+    Vec_IntClear( p->vCisChanged );
+    Gli_ManForEachPi( p, pObj, i )
+        if ( Multi * (Gia_ManRandom(0) & 0xffff) < PiTransProb )
+        {
+            Vec_IntPush( p->vCisChanged, pObj->Handle );
+            pObj->fPhase  ^= 1;
+            pObj->fPhase2 ^= 1;
+            pObj->nSwitches++;
+            pObj->nGlitches++;
+        }
+    // set changed ROs
+    Gli_ManForEachRiRo( p, pObjRi, pObj, i )
+        if ( pObjRi->fPhase != pObj->fPhase )
+        {
+            Vec_IntPush( p->vCisChanged, pObj->Handle );
+            pObj->fPhase  ^= 1;
+            pObj->fPhase2 ^= 1;
+            pObj->nSwitches++;
+            pObj->nGlitches++;
+        }
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes glitching activity of each node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gli_ManSwitchesAndGlitches( Gli_Man_t * p, int nPatterns, float PiTransProb, int fVerbose )
+{
+    int i, k;
+    abctime clk = Abc_Clock();
+    Gia_ManRandom( 1 );
+    Gli_ManFinalize( p );
+    if ( p->nRegs == 0 )
+    {
+        for ( i = 0; i < nPatterns; i++ )
+        {
+            Gli_ManSetPiRandom( p, PiTransProb );
+            Gli_ManSwitching( p );
+            Gli_ManGlitching( p );
+//            Gli_ManVerify( p );
+        }
+    }
+    else 
+    {
+        int nIters = Abc_BitWordNum(nPatterns);
+        Gli_ManSimulateSeqPref( p, 16 );
+        for ( i = 0; i < 32; i++ )
+        {
+            Gli_ManSetDataSaved( p, i );
+            for ( k = 0; k < nIters; k++ )
+            {
+                Gli_ManSetPiRandomSeq( p, PiTransProb );
+                Gli_ManSwitching( p );
+                Gli_ManGlitching( p );
+//                Gli_ManVerify( p );
+            }
+        }
+    }
+    if ( fVerbose )
+    {
+        printf( "\nSimulated %d patterns.  ", nPatterns );
+        ABC_PRMn( "Memory", 4*p->nObjData );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaHash.c b/abc-build/src/aig/gia/giaHash.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaHash.c
@@ -0,0 +1,767 @@
+/**CFile****************************************************************
+
+  FileName    [giaHash.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Structural hashing.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaHash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the place where this node is stored (or should be stored).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManHashOne( int iLit0, int iLit1, int iLitC, int TableSize ) 
+{
+    unsigned Key = iLitC * 2011;
+    Key += Abc_Lit2Var(iLit0) * 7937;
+    Key += Abc_Lit2Var(iLit1) * 2971;
+    Key += Abc_LitIsCompl(iLit0) * 911;
+    Key += Abc_LitIsCompl(iLit1) * 353;
+    return (int)(Key % TableSize);
+}
+static inline int * Gia_ManHashFind( Gia_Man_t * p, int iLit0, int iLit1, int iLitC )
+{
+    Gia_Obj_t * pThis;
+    int * pPlace = p->pHTable + Gia_ManHashOne( iLit0, iLit1, iLitC, p->nHTable );
+    assert( p->pMuxes || iLit0 < iLit1 );
+    assert( iLit0 < iLit1 || (!Abc_LitIsCompl(iLit0) && !Abc_LitIsCompl(iLit1)) );
+    assert( iLitC == -1 || !Abc_LitIsCompl(iLit1) );
+    for ( pThis = (*pPlace)? Gia_ManObj(p, Abc_Lit2Var(*pPlace)) : NULL; pThis; 
+          pPlace = (int *)&pThis->Value, pThis = (*pPlace)? Gia_ManObj(p, Abc_Lit2Var(*pPlace)) : NULL )
+              if ( Gia_ObjFaninLit0p(p, pThis) == iLit0 && Gia_ObjFaninLit1p(p, pThis) == iLit1 && (p->pMuxes == NULL || Gia_ObjFaninLit2p(p, pThis) == iLitC) )
+                  break;
+    return pPlace;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManHashLookup( Gia_Man_t * p, Gia_Obj_t * p0, Gia_Obj_t * p1 )
+{
+    int iLit0 = Gia_ObjToLit( p, p0 );
+    int iLit1 = Gia_ObjToLit( p, p1 );
+    if ( iLit0 > iLit1 )
+        iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1;
+    return *Gia_ManHashFind( p, iLit0, iLit1, -1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManHashAlloc( Gia_Man_t * p )  
+{
+    assert( p->pHTable == NULL );
+    p->nHTable = Abc_PrimeCudd( Gia_ManAndNum(p) ? Gia_ManAndNum(p) + 1000 : p->nObjsAlloc );
+    p->pHTable = ABC_CALLOC( int, p->nHTable );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManHashStart( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj;
+    int * pPlace, i;
+    Gia_ManHashAlloc( p );
+    Gia_ManCleanValue( p );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        pPlace = Gia_ManHashFind( p, Gia_ObjFaninLit0(pObj, i), Gia_ObjFaninLit1(pObj, i), Gia_ObjFaninLit2(p, i) );
+        assert( *pPlace == 0 );
+        *pPlace = Abc_Var2Lit( i, 0 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManHashStop( Gia_Man_t * p )  
+{
+    ABC_FREE( p->pHTable );
+    p->nHTable = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManHashResize( Gia_Man_t * p )
+{
+    Gia_Obj_t * pThis;
+    int * pHTableOld, * pPlace;
+    int nHTableOld, iNext, Counter, Counter2, i;
+    assert( p->pHTable != NULL );
+    // replace the table
+    pHTableOld = p->pHTable;
+    nHTableOld = p->nHTable;
+    p->nHTable = Abc_PrimeCudd( 2 * Gia_ManAndNum(p) ); 
+    p->pHTable = ABC_CALLOC( int, p->nHTable );
+    // rehash the entries from the old table
+    Counter = 0;
+    for ( i = 0; i < nHTableOld; i++ )
+    for ( pThis = (pHTableOld[i]? Gia_ManObj(p, Abc_Lit2Var(pHTableOld[i])) : NULL),
+          iNext = (pThis? pThis->Value : 0);  
+          pThis;  pThis = (iNext? Gia_ManObj(p, Abc_Lit2Var(iNext)) : NULL),   
+          iNext = (pThis? pThis->Value : 0)  )
+    {
+        pThis->Value = 0;
+        pPlace = Gia_ManHashFind( p, Gia_ObjFaninLit0p(p, pThis), Gia_ObjFaninLit1p(p, pThis), Gia_ObjFaninLit2p(p, pThis) );
+        assert( *pPlace == 0 ); // should not be there
+        *pPlace = Abc_Var2Lit( Gia_ObjId(p, pThis), 0 );
+        assert( *pPlace != 0 );
+        Counter++;
+    }
+    Counter2 = Gia_ManAndNum(p);
+    assert( Counter == Counter2 );
+    ABC_FREE( pHTableOld );
+//    if ( p->fVerbose )
+//        printf( "Resizing GIA hash table: %d -> %d.\n", nHTableOld, p->nHTable );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Profiles the hash table.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Gia_ManHashProfile( Gia_Man_t * p )
+{
+    Gia_Obj_t * pEntry;
+    int i, Counter, Limit;
+    printf( "Table size = %d. Entries = %d. ", p->nHTable, Gia_ManAndNum(p) );
+    printf( "Hits = %d. Misses = %d.\n", (int)p->nHashHit, (int)p->nHashMiss );
+    Limit = Abc_MinInt( 1000, p->nHTable );
+    for ( i = 0; i < Limit; i++ )
+    {
+        Counter = 0;
+        for ( pEntry = (p->pHTable[i]? Gia_ManObj(p, Abc_Lit2Var(p->pHTable[i])) : NULL); 
+              pEntry; 
+              pEntry = (pEntry->Value? Gia_ManObj(p, Abc_Lit2Var(pEntry->Value)) : NULL) )
+            Counter++;
+        if ( Counter ) 
+            printf( "%d ", Counter );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recognizes what nodes are control and data inputs of a MUX.]
+
+  Description [If the node is a MUX, returns the control variable C.
+  Assigns nodes T and E to be the then and else variables of the MUX. 
+  Node C is never complemented. Nodes T and E can be complemented.
+  This function also recognizes EXOR/NEXOR gates as MUXes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Gia_ObjRecognizeMuxTwo( Gia_Obj_t * pNode0, Gia_Obj_t * pNode1, Gia_Obj_t ** ppNodeT, Gia_Obj_t ** ppNodeE )
+{
+    assert( !Gia_IsComplement(pNode0) );
+    assert( !Gia_IsComplement(pNode1) );
+    // find the control variable
+    if ( Gia_ObjFanin1(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC1(pNode1)) )
+    {
+//        if ( FrGia_IsComplement(pNode1->p2) )
+        if ( Gia_ObjFaninC1(pNode0) )
+        { // pNode2->p2 is positive phase of C
+            *ppNodeT = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1);
+            *ppNodeE = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1);
+            return Gia_ObjChild1(pNode1);//pNode2->p2;
+        }
+        else
+        { // pNode1->p2 is positive phase of C
+            *ppNodeT = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1);
+            *ppNodeE = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1);
+            return Gia_ObjChild1(pNode0);//pNode1->p2;
+        }
+    }
+    else if ( Gia_ObjFanin0(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC0(pNode1)) )
+    {
+//        if ( FrGia_IsComplement(pNode1->p1) )
+        if ( Gia_ObjFaninC0(pNode0) )
+        { // pNode2->p1 is positive phase of C
+            *ppNodeT = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2);
+            *ppNodeE = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2);
+            return Gia_ObjChild0(pNode1);//pNode2->p1;
+        }
+        else
+        { // pNode1->p1 is positive phase of C
+            *ppNodeT = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2);
+            *ppNodeE = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2);
+            return Gia_ObjChild0(pNode0);//pNode1->p1;
+        }
+    }
+    else if ( Gia_ObjFanin0(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC1(pNode1)) )
+    {
+//        if ( FrGia_IsComplement(pNode1->p1) )
+        if ( Gia_ObjFaninC0(pNode0) )
+        { // pNode2->p2 is positive phase of C
+            *ppNodeT = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1);
+            *ppNodeE = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2);
+            return Gia_ObjChild1(pNode1);//pNode2->p2;
+        }
+        else
+        { // pNode1->p1 is positive phase of C
+            *ppNodeT = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2);
+            *ppNodeE = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1);
+            return Gia_ObjChild0(pNode0);//pNode1->p1;
+        }
+    }
+    else if ( Gia_ObjFanin1(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC0(pNode1)) )
+    {
+//        if ( FrGia_IsComplement(pNode1->p2) )
+        if ( Gia_ObjFaninC1(pNode0) )
+        { // pNode2->p1 is positive phase of C
+            *ppNodeT = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2);
+            *ppNodeE = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1);
+            return Gia_ObjChild0(pNode1);//pNode2->p1;
+        }
+        else
+        { // pNode1->p2 is positive phase of C
+            *ppNodeT = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1);
+            *ppNodeE = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2);
+            return Gia_ObjChild1(pNode0);//pNode1->p2;
+        }
+    }
+    assert( 0 ); // this is not MUX
+    return NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Rehashes AIG with mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Gia_ManHashAndP( Gia_Man_t * p, Gia_Obj_t * p0, Gia_Obj_t * p1 )  
+{ 
+    return Gia_ObjFromLit( p, Gia_ManHashAnd( p, Gia_ObjToLit(p, p0), Gia_ObjToLit(p, p1) ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Rehashes AIG with mapping.]
+
+  Description [http://fmv.jku.at/papers/BrummayerBiere-MEMICS06.pdf]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Gia_Obj_t * Gia_ManAddStrash( Gia_Man_t * p, Gia_Obj_t * p0, Gia_Obj_t * p1 )  
+{ 
+    Gia_Obj_t * pNode0, * pNode1, * pFanA, * pFanB, * pFanC, * pFanD;
+    assert( p->fAddStrash );
+    pNode0 = Gia_Regular(p0);
+    pNode1 = Gia_Regular(p1);
+    if ( !Gia_ObjIsAnd(pNode0) && !Gia_ObjIsAnd(pNode1) )
+        return NULL;
+    pFanA = Gia_ObjIsAnd(pNode0) ? Gia_ObjChild0(pNode0) : NULL;
+    pFanB = Gia_ObjIsAnd(pNode0) ? Gia_ObjChild1(pNode0) : NULL;
+    pFanC = Gia_ObjIsAnd(pNode1) ? Gia_ObjChild0(pNode1) : NULL;
+    pFanD = Gia_ObjIsAnd(pNode1) ? Gia_ObjChild1(pNode1) : NULL;
+    if ( Gia_IsComplement(p0) )
+    {
+        if ( pFanA == Gia_Not(p1) || pFanB == Gia_Not(p1) )
+            return p1;
+        if ( pFanB == p1 )
+            return Gia_ManHashAndP( p, Gia_Not(pFanA), pFanB );
+        if ( pFanA == p1 )
+            return Gia_ManHashAndP( p, Gia_Not(pFanB), pFanA );
+    }
+    else
+    {
+        if ( pFanA == Gia_Not(p1) || pFanB == Gia_Not(p1) )
+            return Gia_ManConst0(p);
+        if ( pFanA == p1 || pFanB == p1 )
+            return p0;
+    }
+    if ( Gia_IsComplement(p1) )
+    {
+        if ( pFanC == Gia_Not(p0) || pFanD == Gia_Not(p0) )
+            return p0;
+        if ( pFanD == p0 )
+            return Gia_ManHashAndP( p, Gia_Not(pFanC), pFanD );
+        if ( pFanC == p0 )
+            return Gia_ManHashAndP( p, Gia_Not(pFanD), pFanC );
+    }
+    else
+    {
+        if ( pFanC == Gia_Not(p0) || pFanD == Gia_Not(p0) )
+            return Gia_ManConst0(p);
+        if ( pFanC == p0 || pFanD == p0 )
+            return p1;
+    }
+    if ( !Gia_IsComplement(p0) && !Gia_IsComplement(p1) ) 
+    {
+        if ( pFanA == Gia_Not(pFanC) || pFanA == Gia_Not(pFanD) || pFanB == Gia_Not(pFanC) || pFanB == Gia_Not(pFanD) )
+            return Gia_ManConst0(p);
+        if ( pFanA == pFanC || pFanB == pFanC )
+            return Gia_ManHashAndP( p, p0, pFanD );
+        if ( pFanB == pFanC || pFanB == pFanD )
+            return Gia_ManHashAndP( p, pFanA, p1 );
+        if ( pFanA == pFanD || pFanB == pFanD )
+            return Gia_ManHashAndP( p, p0, pFanC );
+        if ( pFanA == pFanC || pFanA == pFanD )
+            return Gia_ManHashAndP( p, pFanB, p1 );
+    }
+    else if ( Gia_IsComplement(p0) && !Gia_IsComplement(p1) )
+    {
+        if ( pFanA == Gia_Not(pFanC) || pFanA == Gia_Not(pFanD) || pFanB == Gia_Not(pFanC) || pFanB == Gia_Not(pFanD) )
+            return p1;
+        if ( pFanB == pFanC || pFanB == pFanD )
+            return Gia_ManHashAndP( p, Gia_Not(pFanA), p1 );
+        if ( pFanA == pFanC || pFanA == pFanD )
+            return Gia_ManHashAndP( p, Gia_Not(pFanB), p1 );
+    }
+    else if ( !Gia_IsComplement(p0) && Gia_IsComplement(p1) )
+    {
+        if ( pFanC == Gia_Not(pFanA) || pFanC == Gia_Not(pFanB) || pFanD == Gia_Not(pFanA) || pFanD == Gia_Not(pFanB) )
+            return p0;
+        if ( pFanD == pFanA || pFanD == pFanB )
+            return Gia_ManHashAndP( p, Gia_Not(pFanC), p0 );
+        if ( pFanC == pFanA || pFanC == pFanB )
+            return Gia_ManHashAndP( p, Gia_Not(pFanD), p0 );
+    }
+    else // if ( Gia_IsComplement(p0) && Gia_IsComplement(p1) )
+    {
+        if ( pFanA == pFanD && pFanB == Gia_Not(pFanC) )
+            return Gia_Not(pFanA);
+        if ( pFanB == pFanC && pFanA == Gia_Not(pFanD) )
+            return Gia_Not(pFanB);
+        if ( pFanA == pFanC && pFanB == Gia_Not(pFanD) )
+            return Gia_Not(pFanA);
+        if ( pFanB == pFanD && pFanA == Gia_Not(pFanC) )
+            return Gia_Not(pFanB);
+    }
+/*
+    if ( !Gia_IsComplement(p0) || !Gia_IsComplement(p1) )
+        return NULL;
+    if ( !Gia_ObjIsAnd(pNode0) || !Gia_ObjIsAnd(pNode1) )
+        return NULL;
+    if ( (Gia_ObjFanin0(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC0(pNode1))) || 
+         (Gia_ObjFanin0(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC1(pNode1))) ||
+         (Gia_ObjFanin1(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC0(pNode1))) ||
+         (Gia_ObjFanin1(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC1(pNode1))) )
+    {
+        Gia_Obj_t * pNodeC, * pNodeT, * pNodeE;
+        int fCompl;
+        pNodeC = Gia_ObjRecognizeMuxTwo( pNode0, pNode1, &pNodeT, &pNodeE );
+        // using non-standard canonical rule for MUX (d0 is not compl; d1 may be compl)
+        if ( (fCompl = Gia_IsComplement(pNodeE)) )
+        {
+            pNodeE = Gia_Not(pNodeE);
+            pNodeT = Gia_Not(pNodeT);
+        }
+        pNode0 = Gia_ManHashAndP( p, Gia_Not(pNodeC), pNodeE );
+        pNode1 = Gia_ManHashAndP( p, pNodeC,          pNodeT );
+        p->fAddStrash = 0;
+        pNodeC = Gia_NotCond( Gia_ManHashAndP( p, Gia_Not(pNode0), Gia_Not(pNode1) ), !fCompl );
+        p->fAddStrash = 1;
+        return pNodeC;
+    }
+*/
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Hashes XOR gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManHashXorReal( Gia_Man_t * p, int iLit0, int iLit1 )  
+{ 
+    int fCompl = 0;
+    assert( p->fAddStrash == 0 );
+    if ( iLit0 < 2 )
+        return iLit0 ? Abc_LitNot(iLit1) : iLit1;
+    if ( iLit1 < 2 )
+        return iLit1 ? Abc_LitNot(iLit0) : iLit0;
+    if ( iLit0 == iLit1 )
+        return 0;
+    if ( iLit0 == Abc_LitNot(iLit1) )
+        return 1;
+    if ( (p->nObjs & 0xFF) == 0 && 2 * p->nHTable < Gia_ManAndNum(p) )
+        Gia_ManHashResize( p );
+    if ( iLit0 < iLit1 )
+        iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1;
+    if ( Abc_LitIsCompl(iLit0) )
+        iLit0 = Abc_LitNot(iLit0), fCompl ^= 1;
+    if ( Abc_LitIsCompl(iLit1) )
+        iLit1 = Abc_LitNot(iLit1), fCompl ^= 1;
+    {
+        int *pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 );
+        if ( *pPlace )
+        {
+            p->nHashHit++;
+            return Abc_LitNotCond( *pPlace, fCompl );
+        }
+        p->nHashMiss++;
+        if ( p->nObjs < p->nObjsAlloc )
+            *pPlace = Gia_ManAppendXorReal( p, iLit0, iLit1 );
+        else
+        {
+            int iNode = Gia_ManAppendXorReal( p, iLit0, iLit1 );
+            pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 );
+            assert( *pPlace == 0 );
+            *pPlace = iNode;
+        }
+        return Abc_LitNotCond( *pPlace, fCompl );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Hashes MUX gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManHashMuxReal( Gia_Man_t * p, int iLitC, int iLit1, int iLit0 )  
+{
+    int fCompl = 0;
+    assert( p->fAddStrash == 0 );
+    if ( iLitC < 2 )
+        return iLitC ? iLit1 : iLit0;
+    if ( iLit0 < 2 )
+        return iLit0 ? Gia_ManHashOr(p, Abc_LitNot(iLitC), iLit1) : Gia_ManHashAnd(p, iLitC, iLit1);
+    if ( iLit1 < 2 )
+        return iLit1 ? Gia_ManHashOr(p, iLitC, iLit0) : Gia_ManHashAnd(p, Abc_LitNot(iLitC), iLit0);
+    assert( iLit0 > 1 && iLit1 > 1 && iLitC > 1 );
+    if ( iLit0 == iLit1 )
+        return iLit0;
+    if ( iLitC == iLit0 || iLitC == Abc_LitNot(iLit1) )
+        return Gia_ManHashAnd(p, iLit0, iLit1);
+    if ( iLitC == iLit1 || iLitC == Abc_LitNot(iLit0) )
+        return Gia_ManHashOr(p, iLit0, iLit1);
+    if ( Abc_Lit2Var(iLit0) == Abc_Lit2Var(iLit1) )
+        return Gia_ManHashXorReal( p, iLitC, iLit0 );
+    if ( iLit0 > iLit1 )
+        iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1, iLitC = Abc_LitNot(iLitC);
+    if ( Abc_LitIsCompl(iLit1) )
+        iLit0 = Abc_LitNot(iLit0), iLit1 = Abc_LitNot(iLit1), fCompl = 1;
+    {
+        int *pPlace = Gia_ManHashFind( p, iLit0, iLit1, iLitC );
+        if ( *pPlace )
+        {
+            p->nHashHit++;
+            return Abc_LitNotCond( *pPlace, fCompl );
+        }
+        p->nHashMiss++;
+        if ( p->nObjs < p->nObjsAlloc )
+            *pPlace = Gia_ManAppendMuxReal( p, iLitC, iLit1, iLit0 );
+        else
+        {
+            int iNode = Gia_ManAppendMuxReal( p, iLitC, iLit1, iLit0 );
+            pPlace = Gia_ManHashFind( p, iLit0, iLit1, iLitC );
+            assert( *pPlace == 0 );
+            *pPlace = iNode;
+        }
+        return Abc_LitNotCond( *pPlace, fCompl );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Hashes AND gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManHashAnd( Gia_Man_t * p, int iLit0, int iLit1 )  
+{ 
+    if ( iLit0 < 2 )
+        return iLit0 ? iLit1 : 0;
+    if ( iLit1 < 2 )
+        return iLit1 ? iLit0 : 0;
+    if ( iLit0 == iLit1 )
+        return iLit1;
+    if ( iLit0 == Abc_LitNot(iLit1) )
+        return 0;
+    if ( (p->nObjs & 0xFF) == 0 && 2 * p->nHTable < Gia_ManAndNum(p) )
+        Gia_ManHashResize( p );
+    if ( p->fAddStrash )
+    {
+        Gia_Obj_t * pObj = Gia_ManAddStrash( p, Gia_ObjFromLit(p, iLit0), Gia_ObjFromLit(p, iLit1) );
+        if ( pObj != NULL )
+            return Gia_ObjToLit( p, pObj );
+    }
+    if ( iLit0 > iLit1 )
+        iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1;
+    {
+        int * pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 );
+        if ( *pPlace )
+        {
+            p->nHashHit++;
+            return *pPlace;
+        }
+        p->nHashMiss++;
+        if ( p->nObjs < p->nObjsAlloc )
+            return *pPlace = Gia_ManAppendAnd( p, iLit0, iLit1 );
+        else
+        {
+            int iNode = Gia_ManAppendAnd( p, iLit0, iLit1 );
+            pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 );
+            assert( *pPlace == 0 );
+            return *pPlace = iNode;
+        }
+    }
+}
+int Gia_ManHashOr( Gia_Man_t * p, int iLit0, int iLit1 )  
+{ 
+    return Abc_LitNot(Gia_ManHashAnd( p, Abc_LitNot(iLit0), Abc_LitNot(iLit1) ));
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManHashAndTry( Gia_Man_t * p, int iLit0, int iLit1 )  
+{ 
+    if ( iLit0 < 2 )
+        return iLit0 ? iLit1 : 0;
+    if ( iLit1 < 2 )
+        return iLit1 ? iLit0 : 0;
+    if ( iLit0 == iLit1 )
+        return iLit1;
+    if ( iLit0 == Abc_LitNot(iLit1) )
+        return 0;
+    if ( iLit0 > iLit1 )
+        iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1;
+    {
+        int * pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 );
+        if ( *pPlace ) 
+            return *pPlace;
+        return -1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManHashXor( Gia_Man_t * p, int iLit0, int iLit1 )  
+{ 
+    int fCompl = Abc_LitIsCompl(iLit0) ^ Abc_LitIsCompl(iLit1);
+    int iTemp0 = Gia_ManHashAnd( p, Abc_LitRegular(iLit0), Abc_LitNot(Abc_LitRegular(iLit1)) );
+    int iTemp1 = Gia_ManHashAnd( p, Abc_LitRegular(iLit1), Abc_LitNot(Abc_LitRegular(iLit0)) );
+    return Abc_LitNotCond( Gia_ManHashAnd( p, Abc_LitNot(iTemp0), Abc_LitNot(iTemp1) ), !fCompl );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManHashMux( Gia_Man_t * p, int iCtrl, int iData1, int iData0 )  
+{ 
+    int iTemp0, iTemp1, fCompl = 0;
+    if ( iData0 > iData1 )
+        iData0 ^= iData1, iData1 ^= iData0, iData0 ^= iData1, iCtrl = Abc_LitNot(iCtrl);
+    if ( Abc_LitIsCompl(iData1) )
+        iData0 = Abc_LitNot(iData0), iData1 = Abc_LitNot(iData1), fCompl = 1;
+    iTemp0 = Gia_ManHashAnd( p, Abc_LitNot(iCtrl), iData0 );
+    iTemp1 = Gia_ManHashAnd( p, iCtrl, iData1 );
+    return Abc_LitNotCond( Gia_ManHashAnd( p, Abc_LitNot(iTemp0), Abc_LitNot(iTemp1) ), !fCompl );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Rehashes AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManRehash( Gia_Man_t * p, int fAddStrash )  
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i;
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->fAddStrash = fAddStrash;
+    Gia_ManHashAlloc( pNew );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Gia_ManAppendCi( pNew );
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+    Gia_ManHashStop( pNew );
+    pNew->fAddStrash = 0;
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+//    printf( "Top gate is %s\n", Gia_ObjFaninC0(Gia_ManCo(pNew, 0))? "OR" : "AND" );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates well-balanced AND gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManHashAndMulti( Gia_Man_t * p, Vec_Int_t * vLits )
+{
+    if ( Vec_IntSize(vLits) == 0 )
+        return 0;
+    while ( Vec_IntSize(vLits) > 1 )
+    {
+        int i, k = 0, Lit1, Lit2, LitRes;
+        Vec_IntForEachEntryDouble( vLits, Lit1, Lit2, i )
+        {
+            LitRes = Gia_ManHashAnd( p, Lit1, Lit2 );
+            Vec_IntWriteEntry( vLits, k++, LitRes );
+        }
+        if ( Vec_IntSize(vLits) & 1 )
+            Vec_IntWriteEntry( vLits, k++, Vec_IntEntryLast(vLits) );
+        Vec_IntShrink( vLits, k );
+    }
+    assert( Vec_IntSize(vLits) == 1 );
+    return Vec_IntEntry(vLits, 0);
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaHcd.c b/abc-build/src/aig/gia/giaHcd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaHcd.c
@@ -0,0 +1,689 @@
+/**CFile****************************************************************
+
+  FileName    [giaHcd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [New choice computation package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaHcd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "giaAig.h"
+#include "aig/aig/aig.h"
+#include "opt/dar/dar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// choicing parameters
+typedef struct Hcd_Pars_t_ Hcd_Pars_t;
+struct Hcd_Pars_t_
+{
+    int              nWords;        // the number of simulation words
+    int              nBTLimit;      // conflict limit at a node
+    int              nSatVarMax;    // the max number of SAT variables
+    int              fSynthesis;    // set to 1 to perform synthesis
+    int              fPolarFlip;    // uses polarity adjustment
+    int              fSimulateTfo;  // uses simulation of TFO classes
+    int              fPower;        // uses power-aware rewriting
+    int              fUseGia;       // uses GIA package 
+    int              fUseCSat;      // uses circuit-based solver
+    int              fVerbose;      // verbose stats
+    clock_t          timeSynth;     // synthesis runtime
+    int              nNodesAhead;   // the lookahead in terms of nodes
+    int              nCallsRecycle; // calls to perform before recycling SAT solver
+};
+
+extern void Gia_ComputeEquivalences( Gia_Man_t * pMiter, int nBTLimit, int fUseMiniSat, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hcd_ManSetDefaultParams( Hcd_Pars_t * p )
+{
+    memset( p, 0, sizeof(Hcd_Pars_t) );
+    p->nWords         =     8;  // the number of simulation words
+    p->nBTLimit       =  1000;  // conflict limit at a node
+    p->nSatVarMax     =  5000;  // the max number of SAT variables
+    p->fSynthesis     =     1;  // derives three snapshots
+    p->fPolarFlip     =     1;  // uses polarity adjustment
+    p->fSimulateTfo   =     1;  // simulate TFO
+    p->fPower         =     0;  // power-aware rewriting
+    p->fVerbose       =     0;  // verbose stats
+    p->nNodesAhead    =  1000;  // the lookahead in terms of nodes
+    p->nCallsRecycle  =   100;  // calls to perform before recycling SAT solver
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reproduces script "compress".]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Hcd_Compress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose )
+//alias compress2   "b -l; rw -l; rwz -l; b -l; rwz -l; b -l"
+{
+    Aig_Man_t * pTemp;
+
+    Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr;
+    Dar_RefPar_t ParsRef, * pParsRef = &ParsRef;
+
+    Dar_ManDefaultRwrParams( pParsRwr );
+    Dar_ManDefaultRefParams( pParsRef );
+
+    pParsRwr->fUpdateLevel = fUpdateLevel;
+    pParsRef->fUpdateLevel = fUpdateLevel;
+
+    pParsRwr->fPower = fPower;
+
+    pParsRwr->fVerbose = 0;//fVerbose;
+    pParsRef->fVerbose = 0;//fVerbose;
+
+//    pAig = Aig_ManDupDfs( pAig ); 
+    if ( fVerbose ) Aig_ManPrintStats( pAig );
+
+    // rewrite
+    Dar_ManRewrite( pAig, pParsRwr );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) Aig_ManPrintStats( pAig );
+    
+    // refactor
+    Dar_ManRefactor( pAig, pParsRef );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) Aig_ManPrintStats( pAig );
+
+    // balance
+    if ( fBalance )
+    {
+    pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) Aig_ManPrintStats( pAig );
+    }
+
+    pParsRwr->fUseZeros = 1;
+    pParsRef->fUseZeros = 1;
+    
+    // rewrite
+    Dar_ManRewrite( pAig, pParsRwr );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) Aig_ManPrintStats( pAig );
+
+    return pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reproduces script "compress2".]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Hcd_Compress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose )
+//alias compress2   "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l"
+{
+    Aig_Man_t * pTemp;
+
+    Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr;
+    Dar_RefPar_t ParsRef, * pParsRef = &ParsRef;
+
+    Dar_ManDefaultRwrParams( pParsRwr );
+    Dar_ManDefaultRefParams( pParsRef );
+
+    pParsRwr->fUpdateLevel = fUpdateLevel;
+    pParsRef->fUpdateLevel = fUpdateLevel;
+    pParsRwr->fFanout = fFanout;
+    pParsRwr->fPower = fPower;
+
+    pParsRwr->fVerbose = 0;//fVerbose;
+    pParsRef->fVerbose = 0;//fVerbose;
+
+//    pAig = Aig_ManDupDfs( pAig ); 
+    if ( fVerbose ) Aig_ManPrintStats( pAig );
+
+    // rewrite
+    Dar_ManRewrite( pAig, pParsRwr );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) Aig_ManPrintStats( pAig );
+    
+    // refactor
+    Dar_ManRefactor( pAig, pParsRef );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) Aig_ManPrintStats( pAig );
+
+    // balance
+//    if ( fBalance )
+    {
+    pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) Aig_ManPrintStats( pAig );
+    }
+    
+    // rewrite
+    Dar_ManRewrite( pAig, pParsRwr );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) Aig_ManPrintStats( pAig );
+
+    pParsRwr->fUseZeros = 1;
+    pParsRef->fUseZeros = 1;
+    
+    // rewrite
+    Dar_ManRewrite( pAig, pParsRwr );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) Aig_ManPrintStats( pAig );
+
+    // balance
+    if ( fBalance )
+    {
+    pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) Aig_ManPrintStats( pAig );
+    }
+    
+    // refactor
+    Dar_ManRefactor( pAig, pParsRef );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) Aig_ManPrintStats( pAig );
+    
+    // rewrite
+    Dar_ManRewrite( pAig, pParsRwr );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) Aig_ManPrintStats( pAig );
+
+    // balance
+    if ( fBalance )
+    {
+    pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) Aig_ManPrintStats( pAig );
+    }
+    return pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reproduces script "compress2".]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Hcd_ChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose )
+//alias resyn    "b; rw; rwz; b; rwz; b"
+//alias resyn2   "b; rw; rf; b; rw; rwz; b; rfz; rwz; b"
+{
+    Vec_Ptr_t * vGias;
+    Gia_Man_t * pGia;
+
+    vGias = Vec_PtrAlloc( 3 );
+    pGia = Gia_ManFromAig(pAig);
+    Vec_PtrPush( vGias, pGia );
+
+    pAig = Hcd_Compress( pAig, fBalance, fUpdateLevel, fPower, fVerbose );
+    pGia = Gia_ManFromAig(pAig);
+    Vec_PtrPush( vGias, pGia );
+//Aig_ManPrintStats( pAig );
+
+    pAig = Hcd_Compress2( pAig, fBalance, fUpdateLevel, 1, fPower, fVerbose );
+    pGia = Gia_ManFromAig(pAig);
+    Vec_PtrPush( vGias, pGia );
+//Aig_ManPrintStats( pAig );
+
+    Aig_ManStop( pAig );
+    return vGias;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hcd_ManChoiceMiter_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( ~pObj->Value )
+        return pObj->Value;
+    Hcd_ManChoiceMiter_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    if ( Gia_ObjIsCo(pObj) )
+        return pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Hcd_ManChoiceMiter_rec( pNew, p, Gia_ObjFanin1(pObj) );
+    return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the miter of several AIGs for choice computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Hcd_ManChoiceMiter( Vec_Ptr_t * vGias )
+{
+    Gia_Man_t * pNew, * pGia, * pGia0;
+    int i, k, iNode, nNodes;
+    // make sure they have equal parameters
+    assert( Vec_PtrSize(vGias) > 0 );
+    pGia0 = (Gia_Man_t *)Vec_PtrEntry( vGias, 0 );
+    Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i )
+    {
+        assert( Gia_ManCiNum(pGia)  == Gia_ManCiNum(pGia0) );
+        assert( Gia_ManCoNum(pGia)  == Gia_ManCoNum(pGia0) );
+        assert( Gia_ManRegNum(pGia) == Gia_ManRegNum(pGia0) );
+        Gia_ManFillValue( pGia );
+        Gia_ManConst0(pGia)->Value = 0;
+    }
+    // start the new manager
+    pNew = Gia_ManStart( Vec_PtrSize(vGias) * Gia_ManObjNum(pGia0) );
+    pNew->pName = Abc_UtilStrsav( pGia0->pName );
+    pNew->pSpec = Abc_UtilStrsav( pGia0->pSpec );
+    // create new CIs and assign them to the old manager CIs
+    for ( k = 0; k < Gia_ManCiNum(pGia0); k++ )
+    {
+        iNode = Gia_ManAppendCi(pNew);
+        Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i )
+            Gia_ManCi( pGia, k )->Value = iNode; 
+    }
+    // create internal nodes
+    Gia_ManHashAlloc( pNew );
+    for ( k = 0; k < Gia_ManCoNum(pGia0); k++ )
+    {
+        Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i )
+            Hcd_ManChoiceMiter_rec( pNew, pGia, Gia_ManCo( pGia, k ) );
+    }
+    Gia_ManHashStop( pNew );
+    // check the presence of dangling nodes
+    nNodes = Gia_ManHasDangling( pNew );
+    assert( nNodes == 0 );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pOld is in the TFI of pNode.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hcd_ObjCheckTfi_rec( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode, Vec_Ptr_t * vVisited )
+{
+    // check the trivial cases
+    if ( pNode == NULL )
+        return 0;
+    if ( Gia_ObjIsCi(pNode) )
+        return 0;
+//    if ( pNode->Id < pOld->Id ) // cannot use because of choices of pNode
+//        return 0;
+    if ( pNode == pOld )
+        return 1;
+    // skip the visited node
+    if ( pNode->fMark0 )
+        return 0;
+    pNode->fMark0 = 1;
+    Vec_PtrPush( vVisited, pNode );
+    // check the children
+    if ( Hcd_ObjCheckTfi_rec( p, pOld, Gia_ObjFanin0(pNode), vVisited ) )
+        return 1;
+    if ( Hcd_ObjCheckTfi_rec( p, pOld, Gia_ObjFanin1(pNode), vVisited ) )
+        return 1;
+    // check equivalent nodes
+    return Hcd_ObjCheckTfi_rec( p, pOld, Gia_ObjNextObj(p, Gia_ObjId(p, pNode)), vVisited );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pOld is in the TFI of pNode.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hcd_ObjCheckTfi( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode )
+{
+    Vec_Ptr_t * vVisited;
+    Gia_Obj_t * pObj;
+    int RetValue, i;
+    assert( !Gia_IsComplement(pOld) );
+    assert( !Gia_IsComplement(pNode) );
+    vVisited = Vec_PtrAlloc( 100 );
+    RetValue = Hcd_ObjCheckTfi_rec( p, pOld, pNode, vVisited );
+    Vec_PtrForEachEntry( Gia_Obj_t *, vVisited, pObj, i )
+        pObj->fMark0 = 0;
+    Vec_PtrFree( vVisited );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the next entry while making choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hcd_ManAddNextEntry_rec( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode )
+{
+    if ( Gia_ObjNext(p, Gia_ObjId(p, pOld)) == 0 )
+    {
+        Gia_ObjSetNext( p, Gia_ObjId(p, pOld), Gia_ObjId(p, pNode) );
+        return;
+    }
+    Hcd_ManAddNextEntry_rec( p, Gia_ObjNextObj(p, Gia_ObjId(p, pOld)), pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hcd_ManEquivToChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    Gia_Obj_t * pRepr, * pReprNew, * pObjNew;
+    if ( ~pObj->Value )
+        return;
+    if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+    {
+        if ( Gia_ObjIsConst0(pRepr) )
+        {
+            pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) );
+            return;
+        }
+        Hcd_ManEquivToChoices_rec( pNew, p, pRepr );
+        assert( Gia_ObjIsAnd(pObj) );
+        Hcd_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) );
+        Hcd_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin1(pObj) );
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        if ( Abc_LitRegular(pObj->Value) == Abc_LitRegular(pRepr->Value) )
+        {
+            assert( (int)pObj->Value == Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ) );
+            return;
+        }
+        if ( pRepr->Value > pObj->Value ) // should never happen with high resource limit
+            return;
+        assert( pRepr->Value < pObj->Value );
+        pReprNew = Gia_ManObj( pNew, Abc_Lit2Var(pRepr->Value) );
+        pObjNew  = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) );
+        if ( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) )
+        {
+            assert( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) == pReprNew );
+            pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) );
+            return;
+        }
+        if ( !Hcd_ObjCheckTfi( pNew, pReprNew, pObjNew ) )
+        {
+            assert( Gia_ObjNext(pNew, Gia_ObjId(pNew, pObjNew)) == 0 );
+            Gia_ObjSetRepr( pNew, Gia_ObjId(pNew, pObjNew), Gia_ObjId(pNew, pReprNew) );
+            Hcd_ManAddNextEntry_rec( pNew, pReprNew, pObjNew ); 
+        }
+        pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Hcd_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    Hcd_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin1(pObj) );
+    pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes choices, which contain fanouts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hcd_ManRemoveBadChoices( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, iObj, iPrev, Counter = 0;
+    // mark nodes with fanout
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        pObj->fMark0 = 0;
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            Gia_ObjFanin0(pObj)->fMark0 = 1;
+            Gia_ObjFanin1(pObj)->fMark0 = 1;
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+            Gia_ObjFanin0(pObj)->fMark0 = 1;
+    }
+    // go through the classes and remove 
+    Gia_ManForEachClass( p, i )
+    {
+        for ( iPrev = i, iObj = Gia_ObjNext(p, i); iObj; iObj = Gia_ObjNext(p, iPrev) )
+        {
+            if ( !Gia_ManObj(p, iObj)->fMark0 )
+            {
+                iPrev = iObj; 
+                continue;
+            }
+            Gia_ObjSetRepr( p, iObj, GIA_VOID );
+            Gia_ObjSetNext( p, iPrev, Gia_ObjNext(p, iObj) );
+            Gia_ObjSetNext( p, iObj, 0 );
+            Counter++;
+        } 
+    }
+    // remove the marks
+    Gia_ManCleanMark0( p );
+//    printf( "Removed %d bad choices.\n", Counter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces AIG using equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Hcd_ManEquivToChoices( Gia_Man_t * p, int nSnapshots )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pRepr;
+    int i;
+    assert( (Gia_ManCoNum(p) % nSnapshots) == 0 );
+    Gia_ManSetPhase( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) );
+    pNew->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    for ( i = 0; i < Gia_ManObjNum(p); i++ )
+        Gia_ObjSetRepr( pNew, i, GIA_VOID );
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManForEachRo( p, pObj, i )
+        if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+        {
+            assert( Gia_ObjIsConst0(pRepr) || Gia_ObjIsRo(p, pRepr) );
+            pObj->Value = pRepr->Value;
+        }
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachCo( p, pObj, i )
+        Hcd_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    Gia_ManForEachCo( p, pObj, i )
+        if ( i % nSnapshots == 0 )
+            Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    Hcd_ManRemoveBadChoices( pNew );
+//    Gia_ManEquivPrintClasses( pNew, 0, 0 );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+//    Gia_ManEquivPrintClasses( pNew, 0, 0 );
+    return pNew;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Performs computation of AIGs with choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Hcd_ComputeChoices( Aig_Man_t * pAig, int nBTLimit, int fSynthesis, int fUseMiniSat, int fVerbose )
+{
+    Vec_Ptr_t * vGias;
+    Gia_Man_t * pGia, * pMiter;
+    Aig_Man_t * pAigNew;
+    int i;
+    clock_t clk = clock();
+    // perform synthesis
+    if ( fSynthesis )
+    {
+        vGias = Hcd_ChoiceSynthesis( Aig_ManDupDfs(pAig), 1, 1, 0, 0 );
+        if ( fVerbose )
+            ABC_PRT( "Synthesis time", clock() - clk );
+        // create choices
+        clk = clock();
+        pMiter = Hcd_ManChoiceMiter( vGias );
+        Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i )
+            Gia_ManStop( pGia );
+
+        Gia_AigerWrite( pMiter, "m3.aig", 0, 0 );
+    }
+    else 
+    {
+        vGias = Vec_PtrStart( 3 );
+        pMiter = Gia_ManFromAig(pAig);
+    }
+    // perform choicing
+    Gia_ComputeEquivalences( pMiter, nBTLimit, fUseMiniSat, fVerbose );
+    // derive AIG with choices
+    pGia = Hcd_ManEquivToChoices( pMiter, Vec_PtrSize(vGias) );
+    Gia_ManSetRegNum( pGia, Aig_ManRegNum(pAig) );
+    Gia_ManStop( pMiter );
+    Vec_PtrFree( vGias );
+    if ( fVerbose )
+        ABC_PRT( "Choicing time", clock() - clk );
+//    Gia_ManHasChoices_very_old( pGia );
+    // transform back
+    pAigNew = Gia_ManToAig( pGia, 1 );
+    Gia_ManStop( pGia );
+
+    if ( fVerbose )
+    {
+        extern int Dch_DeriveChoiceCountReprs( Aig_Man_t * pAig );
+        extern int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig );
+        printf( "Choices   : Reprs = %5d. Equivs = %5d. Choices = %5d.\n", 
+            Dch_DeriveChoiceCountReprs( pAigNew ), 
+            Dch_DeriveChoiceCountEquivs( pAigNew ), 
+            Aig_ManChoiceNum( pAigNew ) );
+    }
+
+    return pAigNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs computation of AIGs with choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hcd_ComputeChoicesTest( Gia_Man_t * pGia, int nBTLimit, int fSynthesis, int fUseMiniSat, int fVerbose )
+{
+    Aig_Man_t * pAig, * pAigNew;
+    pAig = Gia_ManToAig( pGia, 0 );
+    pAigNew = Hcd_ComputeChoices( pAig, nBTLimit, fSynthesis, fUseMiniSat, fVerbose );
+    Aig_ManStop( pAigNew );
+    Aig_ManStop( pAig );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaIf.c b/abc-build/src/aig/gia/giaIf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaIf.c
@@ -0,0 +1,1817 @@
+/**CFile****************************************************************
+
+  FileName    [giaMap.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Manipulation of mapping associated with the AIG.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "aig/aig/aig.h"
+#include "map/if/if.h"
+#include "bool/kit/kit.h"
+#include "base/main/main.h"
+#include "sat/bsat/satSolver.h"
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash );
+extern int Abc_RecToGia3( Gia_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, Vec_Int_t * vLeaves, int fHash );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Load the network into FPGA manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSetIfParsDefault( void * pp )
+{
+    If_Par_t * pPars = (If_Par_t *)pp;
+//    extern void * Abc_FrameReadLibLut();
+    If_Par_t * p = (If_Par_t *)pPars;
+    // set defaults
+    memset( p, 0, sizeof(If_Par_t) );
+    // user-controlable paramters
+    p->nLutSize    = -1;
+//    p->nLutSize    =  6;
+    p->nCutsMax    =  8;
+    p->nFlowIters  =  1;
+    p->nAreaIters  =  2;
+    p->DelayTarget = -1;
+    p->Epsilon     =  (float)0.005;
+    p->fPreprocess =  1;
+    p->fArea       =  0;
+    p->fFancy      =  0;
+    p->fExpRed     =  1; ////
+    p->fLatchPaths =  0;
+    p->fEdge       =  1;
+    p->fPower      =  0;
+    p->fCutMin     =  0;
+    p->fVerbose    =  0;
+    p->pLutStruct  =  NULL;
+    // internal parameters
+    p->fTruth      =  0;
+    p->nLatchesCi  =  0;
+    p->nLatchesCo  =  0;
+    p->fLiftLeaves =  0;
+    p->fUseCoAttrs =  1;   // use CO attributes
+    p->pLutLib     =  NULL;
+    p->pTimesArr   =  NULL; 
+    p->pTimesReq   =  NULL;   
+    p->pFuncCost   =  NULL;   
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints mapping statistics.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManLutFaninCount( Gia_Man_t * p )
+{
+    int i, Counter = 0;
+    Gia_ManForEachLut( p, i )
+        Counter += Gia_ObjLutSize(p, i);
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints mapping statistics.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManLutSizeMax( Gia_Man_t * p )
+{
+    int i, nSizeMax = -1;
+    Gia_ManForEachLut( p, i )
+        nSizeMax = Abc_MaxInt( nSizeMax, Gia_ObjLutSize(p, i) );
+    return nSizeMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints mapping statistics.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManLutNum( Gia_Man_t * p )
+{
+    int i, Counter = 0;
+    Gia_ManForEachLut( p, i )
+        Counter ++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints mapping statistics.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManLutLevel( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, k, iFan, Level;
+    int * pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    Gia_ManForEachLut( p, i )
+    {
+        Level = 0;
+        Gia_LutForEachFanin( p, i, iFan, k )
+            if ( Level < pLevels[iFan] )
+                Level = pLevels[iFan];
+        pLevels[i] = Level + 1;
+    }
+    Level = 0;
+    Gia_ManForEachCo( p, pObj, k )
+        if ( Level < pLevels[Gia_ObjFaninId0p(p, pObj)] )
+            Level = pLevels[Gia_ObjFaninId0p(p, pObj)];
+    ABC_FREE( pLevels );
+    return Level;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSetRefsMapped( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj;
+    int i, k, iFan;
+    ABC_FREE( p->pRefs );
+    p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ObjRefInc( p, Gia_ObjFanin0(pObj) );
+    Gia_ManForEachLut( p, i )
+        Gia_LutForEachFanin( p, i, iFan, k )
+            Gia_ObjRefInc( p, Gia_ManObj(p, iFan) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Calculate mapping overlap.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManComputeOverlap2One_rec( Gia_Man_t * p, int iObj, Vec_Str_t * vLabel, Vec_Int_t * vVisit )
+{
+    Gia_Obj_t * pObj;
+    int Counter;
+    if ( Vec_StrEntry(vLabel, iObj) )
+        return 0;
+    Vec_StrWriteEntry( vLabel, iObj, 1 );
+    pObj = Gia_ManObj( p, iObj );
+    assert( Gia_ObjIsAnd(pObj) );
+    Counter  = Gia_ManComputeOverlap2One_rec( p, Gia_ObjFaninId0(pObj, iObj), vLabel, vVisit );
+    Counter += Gia_ManComputeOverlap2One_rec( p, Gia_ObjFaninId1(pObj, iObj), vLabel, vVisit );
+    Vec_IntPush( vVisit, iObj );
+    return Counter + 1;
+}
+int Gia_ManComputeOverlap2One( Gia_Man_t * p, int iObj, Vec_Str_t * vLabel, Vec_Int_t * vVisit )
+{
+    int iFan, k, Counter;
+    Vec_IntClear( vVisit );
+    Gia_LutForEachFanin( p, iObj, iFan, k )
+        Vec_StrWriteEntry( vLabel, iFan, 1 );
+    Counter = Gia_ManComputeOverlap2One_rec( p, iObj, vLabel, vVisit );
+    Gia_LutForEachFanin( p, iObj, iFan, k )
+        Vec_StrWriteEntry( vLabel, iFan, 0 );
+    Vec_IntForEachEntry( vVisit, iFan, k )
+        Vec_StrWriteEntry( vLabel, iFan, 0 );
+    return Counter;
+}
+int Gia_ManComputeOverlap2( Gia_Man_t * p )
+{
+    Vec_Int_t * vVisit;
+    Vec_Str_t * vLabel;
+    int i, Count = -Gia_ManAndNum(p);
+    assert( Gia_ManHasMapping(p) );
+    vVisit = Vec_IntAlloc( 100 );
+    vLabel = Vec_StrStart( Gia_ManObjNum(p) );
+    Gia_ManForEachLut( p, i )
+        Count += Gia_ManComputeOverlap2One( p, i, vLabel, vVisit );
+    Vec_StrFree( vLabel );
+    Vec_IntFree( vVisit );
+    return Count;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Calculate mapping overlap.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManComputeOverlapOne_rec( Gia_Man_t * p, int iObj )
+{
+    Gia_Obj_t * pObj;
+    if ( Gia_ObjIsTravIdCurrentId(p, iObj) )
+        return 0;
+    Gia_ObjSetTravIdCurrentId( p, iObj );
+    pObj = Gia_ManObj( p, iObj );
+    assert( Gia_ObjIsAnd(pObj) );
+    return 1 + Gia_ManComputeOverlapOne_rec( p, Gia_ObjFaninId0(pObj, iObj) )
+          + Gia_ManComputeOverlapOne_rec( p, Gia_ObjFaninId1(pObj, iObj) );
+}
+int Gia_ManComputeOverlapOne( Gia_Man_t * p, int iObj )
+{
+    int iFan, k;
+    Gia_ManIncrementTravId(p);
+    Gia_LutForEachFanin( p, iObj, iFan, k )
+        Gia_ObjSetTravIdCurrentId( p, iFan );
+    return Gia_ManComputeOverlapOne_rec( p, iObj );
+}
+int Gia_ManComputeOverlap( Gia_Man_t * p )
+{
+    int i, Count = -Gia_ManAndNum(p);
+    assert( Gia_ManHasMapping(p) );
+    Gia_ManForEachLut( p, i )
+        Count += Gia_ManComputeOverlapOne( p, i );
+    return Count;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints mapping statistics.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintGetMuxFanins( Gia_Man_t * p, Gia_Obj_t * pObj, int * pFanins )
+{
+    Gia_Obj_t * pData0, * pData1;
+    Gia_Obj_t * pCtrl = Gia_ObjRecognizeMux( pObj, &pData1, &pData0 );
+    pFanins[0] = Gia_ObjId(p, Gia_Regular(pCtrl));
+    pFanins[1] = Gia_ObjId(p, Gia_Regular(pData1));
+    pFanins[2] = Gia_ObjId(p, Gia_Regular(pData0));
+}
+int Gia_ManCountDupLut6( Gia_Man_t * p )
+{
+    int i, nCountDup = 0, nCountPis = 0, nCountMux = 0;
+    Gia_ManCleanMark01( p );
+    Gia_ManForEachLut( p, i )
+        if ( Gia_ObjLutSize(p, i) == 3 && Gia_ObjLutIsMux(p, i) )
+        {
+            Gia_Obj_t * pFanin;
+            int pFanins[3];
+            Gia_ManPrintGetMuxFanins( p, Gia_ManObj(p, i), pFanins );
+            Gia_ManObj(p, i)->fMark1 = 1;
+
+            pFanin = Gia_ManObj(p, pFanins[1]);
+            nCountPis += Gia_ObjIsCi(pFanin);
+            nCountDup += pFanin->fMark0;
+            nCountMux += pFanin->fMark1;
+            pFanin->fMark0 = 1;
+
+            pFanin = Gia_ManObj(p, pFanins[2]);
+            nCountPis += Gia_ObjIsCi(pFanin);
+            nCountDup += pFanin->fMark0;
+            nCountMux += pFanin->fMark1;
+            pFanin->fMark0 = 1;
+        }
+    Gia_ManCleanMark01( p );
+    if ( nCountDup + nCountPis + nCountMux )
+        printf( "Dup fanins = %d.  CI fanins = %d.  MUX fanins = %d.  Total = %d.  (%.2f %%)\n", 
+            nCountDup, nCountPis, nCountMux, nCountDup + nCountPis, 100.0 * (nCountDup + nCountPis + nCountMux) / Gia_ManLutNum(p) );
+    return nCountDup + nCountPis;
+}
+
+void Gia_ManPrintMappingStats( Gia_Man_t * p, char * pDumpFile )
+{
+    Gia_Obj_t * pObj;
+    int * pLevels;
+    int i, k, iFan, nLutSize = 0, nLuts = 0, nFanins = 0, LevelMax = 0, Ave = 0, nMuxF7 = 0;
+    if ( !Gia_ManHasMapping(p) )
+        return;
+    pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    Gia_ManForEachLut( p, i )
+    {
+        if ( Gia_ObjLutSize(p, i) == 3 && Gia_ObjLutIsMux(p, i) )
+        {
+            int pFanins[3];
+            Gia_ManPrintGetMuxFanins( p, Gia_ManObj(p, i), pFanins );
+            pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[0]]+1 );
+            pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[1]] );
+            pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[2]] );
+            LevelMax = Abc_MaxInt( LevelMax, pLevels[i] );
+            nMuxF7++;
+            nFanins++;
+            continue;
+        }
+        nLuts++;
+        nFanins += Gia_ObjLutSize(p, i);
+        nLutSize = Abc_MaxInt( nLutSize, Gia_ObjLutSize(p, i) );
+        Gia_LutForEachFanin( p, i, iFan, k )
+            pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[iFan] );
+        pLevels[i]++;
+        LevelMax = Abc_MaxInt( LevelMax, pLevels[i] );
+    }
+    Gia_ManForEachCo( p, pObj, i )
+        Ave += pLevels[Gia_ObjFaninId0p(p, pObj)];
+    ABC_FREE( pLevels );
+
+#ifdef WIN32
+    {
+    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+    Abc_Print( 1, "Mapping (K=%d)  :  ", nLutSize );
+    SetConsoleTextAttribute( hConsole, 14 ); // yellow
+    Abc_Print( 1, "lut =%7d  ",  nLuts );
+    if ( nMuxF7 )
+    Abc_Print( 1, "mux =%7d  ",  nMuxF7 );
+    SetConsoleTextAttribute( hConsole, 10 ); // green
+    Abc_Print( 1, "edge =%8d  ", nFanins );
+    SetConsoleTextAttribute( hConsole, 12 ); // red
+    Abc_Print( 1, "lev =%5d ",   LevelMax );
+    Abc_Print( 1, "(%.2f)  ",    (float)Ave / Gia_ManCoNum(p) );
+    SetConsoleTextAttribute( hConsole, 7 );  // normal
+    Abc_Print( 1, "over =%5.1f %%  ", 100.0 * Gia_ManComputeOverlap(p) / Gia_ManAndNum(p) );
+    Abc_Print( 1, "mem =%5.2f MB", 4.0*(Gia_ManObjNum(p) + 2*nLuts + nFanins)/(1<<20) );
+    Abc_Print( 1, "\n" );
+    }
+#else
+    Abc_Print( 1, "Mapping (K=%d)  :  ", nLutSize );
+    Abc_Print( 1, "%slut =%7d%s  ",  "\033[1;33m", nLuts,    "\033[0m" );  // yellow
+    Abc_Print( 1, "%sedge =%8d%s  ", "\033[1;32m", nFanins,  "\033[0m" );  // green
+    Abc_Print( 1, "%slev =%5d%s ",   "\033[1;31m", LevelMax, "\033[0m" );  // red
+    Abc_Print( 1, "%s(%.2f)%s  ",    "\033[1;31m", (float)Ave / Gia_ManCoNum(p), "\033[0m" );
+    Abc_Print( 1, "over =%5.1f %%  ", 100.0 * Gia_ManComputeOverlap(p) / Gia_ManAndNum(p) );
+    Abc_Print( 1, "mem =%5.2f MB", 4.0*(Gia_ManObjNum(p) + 2*nLuts + nFanins)/(1<<20) );
+    Abc_Print( 1, "\n" );
+#endif
+
+    if ( nMuxF7 )
+        Gia_ManCountDupLut6( p );
+
+    if ( pDumpFile )
+    {
+        static char FileNameOld[1000] = {0};
+        static abctime clk = 0;
+        FILE * pTable = fopen( pDumpFile, "a+" );
+        if ( strcmp( FileNameOld, p->pName ) )
+        {
+            sprintf( FileNameOld, "%s", p->pName );
+            fprintf( pTable, "\n" );
+            fprintf( pTable, "%s  ", p->pName );
+            fprintf( pTable, "%d ", Gia_ManCiNum(p) );
+            fprintf( pTable, "%d ", Gia_ManCoNum(p) );
+            fprintf( pTable, "%d  ", Gia_ManAndNum(p) );
+            fprintf( pTable, "%d ", nLuts           );
+            fprintf( pTable, "%d ", LevelMax        );
+            clk = Abc_Clock();
+        }
+        else
+        {
+            fprintf( pTable, " " );
+            fprintf( pTable, "%d ", nLuts           );
+            fprintf( pTable, "%d ", LevelMax        );
+            fprintf( pTable, "%.2f", 1.0*(Abc_Clock() - clk)/CLOCKS_PER_SEC );
+            clk = Abc_Clock();
+        }
+        fclose( pTable );
+    }
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints mapping statistics.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintPackingStats( Gia_Man_t * p )
+{
+    int fVerbose = 0;
+    int nObjToShow = 200;
+    int nNumStr[5] = {0};
+    int i, k, Entry, nEntries, nEntries2, MaxSize = -1;
+    if ( p->vPacking == NULL )
+        return;
+    nEntries = Vec_IntEntry( p->vPacking, 0 );
+    nEntries2 = 0;
+    Vec_IntForEachEntryStart( p->vPacking, Entry, i, 1 )
+    {
+        assert( Entry > 0 && Entry < 4 );
+        nNumStr[Entry]++;
+        i++;
+        if ( fVerbose && nEntries2 < nObjToShow ) Abc_Print( 1, "{ " );
+        for ( k = 0; k < Entry; k++, i++ )
+            if ( fVerbose && nEntries2 < nObjToShow ) Abc_Print( 1, "%d ", Vec_IntEntry(p->vPacking, i) );
+        if ( fVerbose && nEntries2 < nObjToShow ) Abc_Print( 1, "}\n" );
+        i--;
+        nEntries2++;
+    }
+    assert( nEntries == nEntries2 );
+    if ( nNumStr[3] > 0 )
+        MaxSize = 3;
+    else if ( nNumStr[2] > 0 )
+        MaxSize = 2;
+    else if ( nNumStr[1] > 0 )
+        MaxSize = 1;
+    Abc_Print( 1, "Packing (N=%d)  :  ", MaxSize );
+    for ( i = 1; i <= MaxSize; i++ )
+        Abc_Print( 1, "%d x LUT = %d   ", i, nNumStr[i] );
+    Abc_Print( 1, "Total = %d", nEntries2 );
+    Abc_Print( 1, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintNodeProfile( int * pCounts, int nSizeMax )
+{
+    int i, SizeAll = 0, NodeAll = 0;
+    for ( i = 0; i <= nSizeMax; i++ )
+    {
+        SizeAll += i * pCounts[i];
+        NodeAll += pCounts[i];
+    }
+    Abc_Print( 1, "LUT = %d : ", NodeAll );
+    for ( i = 2; i <= nSizeMax; i++ )
+        Abc_Print( 1, "%d=%d %.1f %%  ", i, pCounts[i], 100.0*pCounts[i]/NodeAll );
+    Abc_Print( 1, "Ave = %.2f\n", 1.0*SizeAll/(NodeAll ? NodeAll : 1) );
+}
+void Gia_ManPrintLutStats( Gia_Man_t * p )
+{
+    int i, nSizeMax, pCounts[33] = {0};
+    nSizeMax = Gia_ManLutSizeMax( p );
+    if ( nSizeMax > 32 )
+    {
+        Abc_Print( 1, "The max LUT size (%d) is too large.\n", nSizeMax );
+        return;
+    }
+    Gia_ManForEachLut( p, i )
+        pCounts[ Gia_ObjLutSize(p, i) ]++;
+    Gia_ManPrintNodeProfile( pCounts, nSizeMax );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes levels for AIG with choices and white boxes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManChoiceLevel_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
+    Gia_Obj_t * pNext;
+    int i, iBox, iTerm1, nTerms, LevelMax = 0;
+    if ( Gia_ObjIsTravIdCurrent( p, pObj ) )
+        return;
+    Gia_ObjSetTravIdCurrent( p, pObj );
+    if ( Gia_ObjIsCi(pObj) )
+    {
+        if ( pManTime )
+        {
+            iBox = Tim_ManBoxForCi( pManTime, Gia_ObjCioId(pObj) );
+            if ( iBox >= 0 ) // this is not a true PI
+            {
+                iTerm1 = Tim_ManBoxInputFirst( pManTime, iBox );
+                nTerms = Tim_ManBoxInputNum( pManTime, iBox );
+                for ( i = 0; i < nTerms; i++ )
+                {
+                    pNext = Gia_ManCo( p, iTerm1 + i );
+                    Gia_ManChoiceLevel_rec( p, pNext );
+                    if ( LevelMax < Gia_ObjLevel(p, pNext) )
+                        LevelMax = Gia_ObjLevel(p, pNext);
+                }
+                LevelMax++;
+            }
+        }
+//        Abc_Print( 1, "%d ", pObj->Level );
+    }
+    else if ( Gia_ObjIsCo(pObj) )
+    {
+        pNext = Gia_ObjFanin0(pObj);
+        Gia_ManChoiceLevel_rec( p, pNext );
+        if ( LevelMax < Gia_ObjLevel(p, pNext) )
+            LevelMax = Gia_ObjLevel(p, pNext);
+    }
+    else if ( Gia_ObjIsAnd(pObj) )
+    { 
+        // get the maximum level of the two fanins
+        pNext = Gia_ObjFanin0(pObj);
+        Gia_ManChoiceLevel_rec( p, pNext );
+        if ( LevelMax < Gia_ObjLevel(p, pNext) )
+            LevelMax = Gia_ObjLevel(p, pNext);
+        pNext = Gia_ObjFanin1(pObj);
+        Gia_ManChoiceLevel_rec( p, pNext );
+        if ( LevelMax < Gia_ObjLevel(p, pNext) )
+            LevelMax = Gia_ObjLevel(p, pNext);
+        LevelMax++;
+
+        // get the level of the nodes in the choice node
+        if ( (pNext = Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))) )
+        {
+            Gia_ManChoiceLevel_rec( p, pNext );
+            if ( LevelMax < Gia_ObjLevel(p, pNext) )
+                LevelMax = Gia_ObjLevel(p, pNext);
+        }
+    }
+    else if ( !Gia_ObjIsConst0(pObj) )
+        assert( 0 );
+    Gia_ObjSetLevel( p, pObj, LevelMax );
+}
+int Gia_ManChoiceLevel( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, LevelMax = 0;
+//    assert( Gia_ManRegNum(p) == 0 );
+    Gia_ManCleanLevels( p, Gia_ManObjNum(p) );
+    Gia_ManIncrementTravId( p );
+    Gia_ManForEachCo( p, pObj, i )
+    {
+        Gia_ManChoiceLevel_rec( p, pObj );
+        if ( LevelMax < Gia_ObjLevel(p, pObj) )
+            LevelMax = Gia_ObjLevel(p, pObj);
+    }
+    // account for dangling boxes
+    Gia_ManForEachCi( p, pObj, i )
+    {
+        Gia_ManChoiceLevel_rec( p, pObj );
+        if ( LevelMax < Gia_ObjLevel(p, pObj) )
+            LevelMax = Gia_ObjLevel(p, pObj);
+//        Abc_Print( 1, "%d ", Gia_ObjLevel(p, pObj) );
+    }
+//    Abc_Print( 1, "\n" );
+    Gia_ManForEachAnd( p, pObj, i )
+        assert( Gia_ObjLevel(p, pObj) > 0 );
+//    printf( "Max level %d\n", LevelMax );
+    return LevelMax;
+} 
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Converts GIA into IF manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline If_Obj_t * If_ManFanin0Copy( If_Man_t * pIfMan, Gia_Obj_t * pObj ) { return If_NotCond( If_ManObj(pIfMan, Gia_ObjValue(Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj) ); }
+static inline If_Obj_t * If_ManFanin1Copy( If_Man_t * pIfMan, Gia_Obj_t * pObj ) { return If_NotCond( If_ManObj(pIfMan, Gia_ObjValue(Gia_ObjFanin1(pObj))), Gia_ObjFaninC1(pObj) ); }
+If_Man_t * Gia_ManToIf( Gia_Man_t * p, If_Par_t * pPars )
+{
+    If_Man_t * pIfMan;
+    If_Obj_t * pIfObj;
+    Gia_Obj_t * pObj;
+    int i;
+    // create levels with choices
+    Gia_ManChoiceLevel( p );
+    // mark representative nodes
+    if ( Gia_ManHasChoices(p) )
+        Gia_ManMarkFanoutDrivers( p );
+    // start the mapping manager and set its parameters
+    pIfMan = If_ManStart( pPars );
+    pIfMan->pName = Abc_UtilStrsav( Gia_ManName(p) );
+    // print warning about excessive memory usage
+    if ( 1.0 * Gia_ManObjNum(p) * pIfMan->nObjBytes / (1<<30) > 1.0 )
+        printf( "Warning: The mapper will allocate %.1f GB for to represent the subject graph with %d AIG nodes.\n", 
+            1.0 * Gia_ManObjNum(p) * pIfMan->nObjBytes / (1<<30), Gia_ManObjNum(p) );
+    // load the AIG into the mapper
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = If_ObjId( If_ManConst1(pIfMan) );
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            pIfObj = If_ManCreateAnd( pIfMan, If_ManFanin0Copy(pIfMan, pObj), If_ManFanin1Copy(pIfMan, pObj) );
+        else if ( Gia_ObjIsCi(pObj) )
+        {
+            pIfObj = If_ManCreateCi( pIfMan );
+            If_ObjSetLevel( pIfObj, Gia_ObjLevel(p, pObj) );
+//            Abc_Print( 1, "pi%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) );
+            if ( pIfMan->nLevelMax < (int)pIfObj->Level )
+                pIfMan->nLevelMax = (int)pIfObj->Level;
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+        {
+            pIfObj = If_ManCreateCo( pIfMan, If_NotCond( If_ManFanin0Copy(pIfMan, pObj), Gia_ObjIsConst0(Gia_ObjFanin0(pObj))) );
+//            Abc_Print( 1, "po%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) );
+        }
+        else assert( 0 );
+        assert( i == If_ObjId(pIfObj) );
+        Gia_ObjSetValue( pObj, If_ObjId(pIfObj) );
+        // set up the choice node
+        if ( Gia_ObjSibl(p, i) && pObj->fMark0 )
+        {
+            Gia_Obj_t * pSibl, * pPrev;
+            for ( pPrev = pObj, pSibl = Gia_ObjSiblObj(p, i); pSibl; pPrev = pSibl, pSibl = Gia_ObjSiblObj(p, Gia_ObjId(p, pSibl)) )
+                If_ObjSetChoice( If_ManObj(pIfMan, Gia_ObjValue(pPrev)), If_ManObj(pIfMan, Gia_ObjValue(pSibl)) );
+            If_ManCreateChoice( pIfMan, If_ManObj(pIfMan, Gia_ObjValue(pObj)) );
+            pPars->fExpRed = 0;
+        }
+//        assert( If_ObjLevel(pIfObj) == Gia_ObjLevel(pNode) );
+    }
+    if ( Gia_ManHasChoices(p) )
+        Gia_ManCleanMark0( p );
+    return pIfMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Rebuilds GIA from mini AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManBuildFromMiniInt( Gia_Man_t * pNew, Vec_Int_t * vLeaves, Vec_Int_t * vAig, int fHash )
+{
+    assert( Vec_IntSize(vAig) > 0 );
+    assert( Vec_IntEntryLast(vAig) < 2 );
+    if ( Vec_IntSize(vAig) == 1 ) // const
+        return Vec_IntEntry(vAig, 0);
+    if ( Vec_IntSize(vAig) == 2 ) // variable
+    {
+        assert( Vec_IntEntry(vAig, 0) == 0 );
+        assert( Vec_IntSize(vLeaves) == 1 );
+        return Abc_LitNotCond( Vec_IntEntry(vLeaves, 0), Vec_IntEntry(vAig, 1) );
+    }
+    else
+    {
+        int nLeaves = Vec_IntSize(vLeaves);
+        int i, iVar0, iVar1, iLit0, iLit1, iLit = 0;
+        assert( Vec_IntSize(vAig) & 1 );
+        Vec_IntForEachEntryDouble( vAig, iLit0, iLit1, i )
+        {
+            iVar0 = Abc_Lit2Var( iLit0 );
+            iVar1 = Abc_Lit2Var( iLit1 );
+            iLit0 = Abc_LitNotCond( iVar0 < nLeaves ? Vec_IntEntry(vLeaves, iVar0) : Vec_IntEntry(vAig, iVar0 - nLeaves), Abc_LitIsCompl(iLit0) );
+            iLit1 = Abc_LitNotCond( iVar1 < nLeaves ? Vec_IntEntry(vLeaves, iVar1) : Vec_IntEntry(vAig, iVar1 - nLeaves), Abc_LitIsCompl(iLit1) );
+            if ( fHash )
+                iLit = Gia_ManHashAnd( pNew, iLit0, iLit1 );
+            else if ( iLit0 == iLit1 )
+                iLit = iLit0;
+            else
+                iLit = Gia_ManAppendAnd( pNew, iLit0, iLit1 );
+            assert( (i & 1) == 0 );
+            Vec_IntWriteEntry( vAig, Abc_Lit2Var(i), iLit );  // overwriting entries
+        }
+        assert( i == Vec_IntSize(vAig) - 1 );
+        iLit = Abc_LitNotCond( iLit, Vec_IntEntry(vAig, i) );
+        Vec_IntClear( vAig ); // useless
+        return iLit;
+    }
+}
+int Gia_ManBuildFromMini( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Cut_t * pCut, Vec_Int_t * vLeaves, Vec_Int_t * vAig, int fHash, int fUseDsd )
+{
+    if ( fUseDsd )
+        If_CutDsdBalanceEval( pIfMan, pCut, vAig );
+    else
+        If_CutSopBalanceEval( pIfMan, pCut, vAig );
+    return Gia_ManBuildFromMiniInt( pNew, vLeaves, vAig, fHash );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts IF into GIA manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManFromIfAig_rec( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Obj_t * pIfObj )
+{
+    int iLit0, iLit1;
+    if ( pIfObj->iCopy )
+        return pIfObj->iCopy;
+    iLit0 = Gia_ManFromIfAig_rec( pNew, pIfMan, pIfObj->pFanin0 );
+    iLit1 = Gia_ManFromIfAig_rec( pNew, pIfMan, pIfObj->pFanin1 );
+    iLit0 = Abc_LitNotCond( iLit0, pIfObj->fCompl0 );
+    iLit1 = Abc_LitNotCond( iLit1, pIfObj->fCompl1 );
+    pIfObj->iCopy = Gia_ManHashAnd( pNew, iLit0, iLit1 );
+    return pIfObj->iCopy;
+}
+Gia_Man_t * Gia_ManFromIfAig( If_Man_t * pIfMan )
+{
+    int fHash = 0;
+    Gia_Man_t * pNew, * pTemp;
+    If_Obj_t * pIfObj, * pIfLeaf;
+    If_Cut_t * pCutBest;
+    Vec_Int_t * vLeaves;
+    Vec_Int_t * vAig;
+    int i, k;
+    assert( pIfMan->pPars->pLutStruct == NULL );
+    assert( pIfMan->pPars->fDelayOpt || pIfMan->pPars->fDsdBalance || pIfMan->pPars->fUserRecLib );
+    // create new manager
+    pNew = Gia_ManStart( If_ManObjNum(pIfMan) );
+    Gia_ManHashAlloc( pNew );
+    // iterate through nodes used in the mapping
+    vAig = Vec_IntAlloc( 1 << 16 );
+    vLeaves = Vec_IntAlloc( 16 );
+//    If_ManForEachObj( pIfMan, pIfObj, i )
+//        pIfObj->iCopy = 0;
+    If_ManForEachObj( pIfMan, pIfObj, i )
+    {
+        if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) )
+            continue;
+        if ( If_ObjIsAnd(pIfObj) )
+        {
+            pCutBest = If_ObjCutBest( pIfObj );
+            // if the cut does not offer delay improvement
+//            if ( (int)pIfObj->Level <= (int)pCutBest->Delay )
+//            {
+//                Gia_ManFromIfAig_rec( pNew, pIfMan, pIfObj );
+//                continue;
+//            }
+            // collect leaves of the best cut
+            Vec_IntClear( vLeaves );
+            If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, k )
+                Vec_IntPush( vLeaves, pIfLeaf->iCopy );
+            // get the functionality
+            if ( pIfMan->pPars->fDelayOpt )
+                pIfObj->iCopy = Gia_ManBuildFromMini( pNew, pIfMan, pCutBest, vLeaves, vAig, fHash, 0 );
+            else if ( pIfMan->pPars->fDsdBalance )
+                pIfObj->iCopy = Gia_ManBuildFromMini( pNew, pIfMan, pCutBest, vLeaves, vAig, fHash, 1 );
+            else if ( pIfMan->pPars->fUserRecLib )
+                pIfObj->iCopy = Abc_RecToGia3( pNew, pIfMan, pCutBest, vLeaves, fHash );
+            else assert( 0 );
+        }
+        else if ( If_ObjIsCi(pIfObj) )
+            pIfObj->iCopy = Gia_ManAppendCi(pNew);
+        else if ( If_ObjIsCo(pIfObj) )
+            pIfObj->iCopy = Gia_ManAppendCo( pNew, Abc_LitNotCond(If_ObjFanin0(pIfObj)->iCopy, If_ObjFaninC0(pIfObj)) );
+        else if ( If_ObjIsConst1(pIfObj) )
+            pIfObj->iCopy = 1;
+        else assert( 0 );
+    }
+    Vec_IntFree( vAig );
+    Vec_IntFree( vLeaves );
+    pNew = Gia_ManRehash( pTemp = pNew, 0 );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Write mapping for LUT with given fanins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManFromIfLogicCreateLut( Gia_Man_t * pNew, word * pRes, Vec_Int_t * vLeaves, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2 )
+{
+    int i, iLit, iObjLit1;
+    iObjLit1 = Kit_TruthToGia( pNew, (unsigned *)pRes, Vec_IntSize(vLeaves), vCover, vLeaves, 0 );
+    // do not create LUT in the simple case
+    if ( Abc_Lit2Var(iObjLit1) == 0 )
+        return iObjLit1;
+    Vec_IntForEachEntry( vLeaves, iLit, i )
+        if ( Abc_Lit2Var(iObjLit1) == Abc_Lit2Var(iLit) )
+            return iObjLit1;
+    // write mapping
+    Vec_IntSetEntry( vMapping, Abc_Lit2Var(iObjLit1), Vec_IntSize(vMapping2) );
+    Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) );
+//    Vec_IntForEachEntry( vLeaves, iLit, i )
+//        assert( Abc_Lit2Var(iLit) < Abc_Lit2Var(iObjLit1) );
+    Vec_IntForEachEntry( vLeaves, iLit, i )
+        Vec_IntPush( vMapping2, Abc_Lit2Var(iLit)  );
+    Vec_IntPush( vMapping2, Abc_Lit2Var(iObjLit1) );
+    return iObjLit1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write mapping for LUT with given fanins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManFromIfLogicCreateLutSpecial( Gia_Man_t * pNew, word * pRes, Vec_Int_t * vLeaves, Vec_Int_t * vLeavesTemp, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vPacking )
+{
+    word z = If_CutPerformDerive07( NULL, (unsigned *)pRes, Vec_IntSize(vLeaves), Vec_IntSize(vLeaves), NULL );
+    word Truth;
+    int i, iObjLit1, iObjLit2;
+    // create first LUT
+    Vec_IntClear( vLeavesTemp );
+    for ( i = 0; i < 4; i++ )
+    {
+        int v = (int)((z >> (16+(i<<2))) & 7);
+        if ( v == 6 && Vec_IntSize(vLeaves) == 5 )
+            continue;
+        Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, v) );
+    }
+    Truth = (z & 0xffff);
+    Truth |= (Truth << 16);
+    Truth |= (Truth << 32);
+    iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, &Truth, vLeavesTemp, vCover, vMapping, vMapping2 );
+    // create second LUT
+    Vec_IntClear( vLeavesTemp );
+    for ( i = 0; i < 4; i++ )
+    {
+        int v =  (int)((z >> (48+(i<<2))) & 7);
+        if ( v == 6 && Vec_IntSize(vLeaves) == 5 )
+            continue;
+        if ( v == 7 )
+            Vec_IntPush( vLeavesTemp, iObjLit1 );
+        else
+            Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, v) );
+    }
+    Truth = ((z >> 32) & 0xffff);
+    Truth |= (Truth << 16);
+    Truth |= (Truth << 32);
+    iObjLit2 = Gia_ManFromIfLogicCreateLut( pNew, &Truth, vLeavesTemp, vCover, vMapping, vMapping2 );
+    // write packing
+    Vec_IntPush( vPacking, 2 );
+    Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) );
+    Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit2) );
+    Vec_IntAddToEntry( vPacking, 0, 1 );
+    return iObjLit2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the node into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManFromIfLogicNode( void * pIfMan, Gia_Man_t * pNew, int iObj, Vec_Int_t * vLeaves, Vec_Int_t * vLeavesTemp, 
+    word * pRes, char * pStr, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vPacking, int fCheck75, int fCheck44e )
+{
+    int nLeaves = Vec_IntSize(vLeaves);
+    int i, Length, nLutLeaf, nLutLeaf2, nLutRoot, iObjLit1, iObjLit2, iObjLit3;
+    // workaround for the special case
+    if ( fCheck75 )
+        pStr = "54";
+    // perform special case matching for 44
+    if ( fCheck44e )
+    {
+        if ( Vec_IntSize(vLeaves) <= 4 )
+        {
+            // create mapping
+            iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, pRes, vLeaves, vCover, vMapping, vMapping2 );
+            // write packing
+            if ( !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(iObjLit1))) && iObjLit1 > 1 )
+            {
+                Vec_IntPush( vPacking, 1 );
+                Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) );
+                Vec_IntAddToEntry( vPacking, 0, 1 );
+            }
+            return iObjLit1;
+        }
+        return Gia_ManFromIfLogicCreateLutSpecial( pNew, pRes, vLeaves, vLeavesTemp, vCover, vMapping, vMapping2, vPacking );
+    }
+    // check if there is no LUT structures
+    if ( pStr == NULL )
+        return Gia_ManFromIfLogicCreateLut( pNew, pRes, vLeaves, vCover, vMapping, vMapping2 );
+    // quit if parameters are wrong
+    Length = strlen(pStr);
+    if ( Length != 2 && Length != 3 )
+    {
+        printf( "Wrong LUT struct (%s)\n", pStr );
+        return -1;
+    }
+    for ( i = 0; i < Length; i++ )
+        if ( pStr[i] - '0' < 3 || pStr[i] - '0' > 6 )
+        {
+            printf( "The LUT size (%d) should belong to {3,4,5,6}.\n", pStr[i] - '0' );
+            return -1;
+        }
+
+    nLutLeaf  =                   pStr[0] - '0';
+    nLutLeaf2 = ( Length == 3 ) ? pStr[1] - '0' : 0;
+    nLutRoot  =                   pStr[Length-1] - '0';
+    if ( nLeaves > nLutLeaf - 1 + (nLutLeaf2 ? nLutLeaf2 - 1 : 0) + nLutRoot )
+    {
+        printf( "The node size (%d) is too large for the LUT structure %s.\n", nLeaves, pStr );
+        return -1;
+    }
+
+    // consider easy case
+    if ( nLeaves <= Abc_MaxInt( nLutLeaf2, Abc_MaxInt(nLutLeaf, nLutRoot) ) )
+    {
+        // create mapping
+        iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, pRes, vLeaves, vCover, vMapping, vMapping2 );
+        // write packing
+        if ( !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(iObjLit1))) && iObjLit1 > 1 )
+        {
+            Vec_IntPush( vPacking, 1 );
+            Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) );
+            Vec_IntAddToEntry( vPacking, 0, 1 );
+        }
+        return iObjLit1;
+    }
+    else
+    {
+        extern int If_CluMinimumBase( word * t, int * pSupp, int nVarsAll, int * pnVars );
+
+        static word TruthStore[16][1<<10] = {{0}}, * pTruths[16];
+        word Func0, Func1, Func2;
+        char pLut0[32], pLut1[32], pLut2[32] = {0};
+
+        if ( TruthStore[0][0] == 0 )
+        {
+            static word Truth6[6] = {
+                0xAAAAAAAAAAAAAAAA,
+                0xCCCCCCCCCCCCCCCC,
+                0xF0F0F0F0F0F0F0F0,
+                0xFF00FF00FF00FF00,
+                0xFFFF0000FFFF0000,
+                0xFFFFFFFF00000000
+            };
+            int nVarsMax = 16;
+            int nWordsMax = (1 << 10);
+            int i, k;
+            assert( nVarsMax <= 16 );
+            for ( i = 0; i < nVarsMax; i++ )
+                pTruths[i] = TruthStore[i];
+            for ( i = 0; i < 6; i++ )
+                for ( k = 0; k < nWordsMax; k++ )
+                    pTruths[i][k] = Truth6[i];
+            for ( i = 6; i < nVarsMax; i++ )
+                for ( k = 0; k < nWordsMax; k++ )
+                    pTruths[i][k] = ((k >> (i-6)) & 1) ? ~(word)0 : 0;
+        }
+        // derive truth table
+        if ( Kit_TruthIsConst0((unsigned *)pRes, nLeaves) || Kit_TruthIsConst1((unsigned *)pRes, nLeaves) )
+        {
+//            fprintf( pFile, ".names %s\n %d\n", Abc_ObjName(Abc_ObjFanout0(pObj)), Kit_TruthIsConst1((unsigned *)pRes, nLeaves) );
+            iObjLit1 = Abc_LitNotCond( 0, Kit_TruthIsConst1((unsigned *)pRes, nLeaves) );
+            // write mapping
+            if ( Vec_IntEntry(vMapping, 0) == 0 )
+            {
+                Vec_IntSetEntry( vMapping, 0, Vec_IntSize(vMapping2) );
+                Vec_IntPush( vMapping2, 0 );
+                Vec_IntPush( vMapping2, 0 );
+            }
+            return iObjLit1;
+        }
+        // check for elementary truth table
+        for ( i = 0; i < nLeaves; i++ )
+        {
+            if ( Kit_TruthIsEqual((unsigned *)pRes, (unsigned *)pTruths[i], nLeaves) )
+                return Vec_IntEntry(vLeaves, i);
+            if ( Kit_TruthIsOpposite((unsigned *)pRes, (unsigned *)pTruths[i], nLeaves) )
+                return Abc_LitNot(Vec_IntEntry(vLeaves, i));
+        }
+
+        // perform decomposition
+        if ( fCheck75 ) 
+        {
+//            if ( nLeaves < 8 && If_CutPerformCheck16( p, (unsigned *)pTruth, nVars, nLeaves, "44" ) )
+            if ( nLeaves < 8 && If_CluCheckExt( NULL, pRes, nLeaves, 4, 4, pLut0, pLut1, &Func0, &Func1 ) )
+            {
+                nLutLeaf = 4;
+                nLutRoot = 4;
+            }
+//            if ( If_CutPerformCheck45( p, (unsigned *)pTruth, nVars, nLeaves, pStr ) )
+            else if ( If_CluCheckExt( NULL, pRes, nLeaves, 5, 4, pLut0, pLut1, &Func0, &Func1 ) )
+            {
+                nLutLeaf = 5;
+                nLutRoot = 4;
+            }
+//            if ( If_CutPerformCheck54( p, (unsigned *)pTruth, nVars, nLeaves, pStr ) )
+            else if ( If_CluCheckExt( NULL, pRes, nLeaves, 4, 5, pLut0, pLut1, &Func0, &Func1 ) )
+            {
+                nLutLeaf = 4;
+                nLutRoot = 5;
+            }
+            else
+            {
+                Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves );  printf( "    " );
+                Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves );  printf( "\n" );
+                printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj );
+                return -1;
+            }
+        }
+        else
+        {
+            if ( Length == 2 )
+            {
+                if ( !If_CluCheckExt( NULL, pRes, nLeaves, nLutLeaf, nLutRoot, pLut0, pLut1, &Func0, &Func1 ) )
+                {
+                    Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves );  printf( "    " );
+                    Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves );  printf( "\n" );
+                    printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj );
+                    return -1;
+                }
+            }
+            else
+            {
+                if ( !If_CluCheckExt3( pIfMan, pRes, nLeaves, nLutLeaf, nLutLeaf2, nLutRoot, pLut0, pLut1, pLut2, &Func0, &Func1, &Func2 ) )
+                {
+                    Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves );  printf( "    " );
+                    Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves );  printf( "\n" );
+                    printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj );
+                    return -1;
+                }
+            }
+        }
+
+/*
+        // write leaf node
+        Id = Abc2_NtkAllocObj( pNew, pLut1[0], Abc2_ObjType(pObj) );
+        iObjLit1 = Abc_Var2Lit( Id, 0 );
+        pObjNew = Abc2_NtkObj( pNew, Id );
+        for ( i = 0; i < pLut1[0]; i++ )
+            Abc2_ObjSetFaninLit( pObjNew, i, Abc2_ObjFaninCopy(pObj, pLut1[2+i]) );
+        Abc2_ObjSetTruth( pObjNew, Func1 );
+*/
+        // write leaf node
+        Vec_IntClear( vLeavesTemp );
+        for ( i = 0; i < pLut1[0]; i++ )
+            Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, pLut1[2+i]) );
+        iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, &Func1, vLeavesTemp, vCover, vMapping, vMapping2 );
+
+        if ( Length == 3 && pLut2[0] > 0 )
+        {
+        /*
+            Id = Abc2_NtkAllocObj( pNew, pLut2[0], Abc2_ObjType(pObj) );
+            iObjLit2 = Abc_Var2Lit( Id, 0 );
+            pObjNew = Abc2_NtkObj( pNew, Id );
+            for ( i = 0; i < pLut2[0]; i++ )
+                if ( pLut2[2+i] == nLeaves )
+                    Abc2_ObjSetFaninLit( pObjNew, i, iObjLit1 );
+                else
+                    Abc2_ObjSetFaninLit( pObjNew, i, Abc2_ObjFaninCopy(pObj, pLut2[2+i]) );
+            Abc2_ObjSetTruth( pObjNew, Func2 );
+        */
+
+            // write leaf node
+            Vec_IntClear( vLeavesTemp );
+            for ( i = 0; i < pLut2[0]; i++ )
+                if ( pLut2[2+i] == nLeaves )
+                    Vec_IntPush( vLeavesTemp, iObjLit1 );
+                else
+                    Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, pLut2[2+i]) );
+            iObjLit2 = Gia_ManFromIfLogicCreateLut( pNew, &Func2, vLeavesTemp, vCover, vMapping, vMapping2 );
+
+            // write packing
+            Vec_IntPush( vPacking, 3 );
+            Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) );
+            Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit2) );
+        }
+        else
+        {
+            // write packing
+            Vec_IntPush( vPacking, 2 );
+            Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) );
+            iObjLit2 = -1;
+        }
+/*
+        // write root node
+        Id = Abc2_NtkAllocObj( pNew, pLut0[0], Abc2_ObjType(pObj) );
+        iObjLit3 = Abc_Var2Lit( Id, 0 );
+        pObjNew = Abc2_NtkObj( pNew, Id );
+        for ( i = 0; i < pLut0[0]; i++ )
+            if ( pLut0[2+i] == nLeaves )
+                Abc2_ObjSetFaninLit( pObjNew, i, iObjLit1 );
+            else if ( pLut0[2+i] == nLeaves+1 )
+                Abc2_ObjSetFaninLit( pObjNew, i, iObjLit2 );
+            else
+                Abc2_ObjSetFaninLit( pObjNew, i, Abc2_ObjFaninCopy(pObj, pLut0[2+i]) );
+        Abc2_ObjSetTruth( pObjNew, Func0 );
+        Abc2_ObjSetCopy( pObj, iObjLit3 );
+*/
+        // write root node
+        Vec_IntClear( vLeavesTemp );
+        for ( i = 0; i < pLut0[0]; i++ )
+            if ( pLut0[2+i] == nLeaves )
+                Vec_IntPush( vLeavesTemp, iObjLit1 );
+            else if ( pLut0[2+i] == nLeaves+1 )
+                Vec_IntPush( vLeavesTemp, iObjLit2 );
+            else
+                Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, pLut0[2+i]) );
+        iObjLit3 = Gia_ManFromIfLogicCreateLut( pNew, &Func0, vLeavesTemp, vCover, vMapping, vMapping2 );
+
+        // write packing
+        Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit3) );
+        Vec_IntAddToEntry( vPacking, 0, 1 );
+    }
+    return iObjLit3;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively derives the local AIG for the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManNodeIfToGia_rec( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited, int fHash )
+{
+    If_Cut_t * pCut;
+    If_Obj_t * pTemp;
+    int iFunc, iFunc0, iFunc1;
+    // get the best cut
+    pCut = If_ObjCutBest(pIfObj);
+    // if the cut is visited, return the result
+    if ( If_CutDataInt(pCut) )
+        return If_CutDataInt(pCut);
+    // mark the node as visited
+    Vec_PtrPush( vVisited, pCut );
+    // insert the worst case
+    If_CutSetDataInt( pCut, ~0 );
+    // skip in case of primary input
+    if ( If_ObjIsCi(pIfObj) )
+        return If_CutDataInt(pCut);
+    // compute the functions of the children
+    for ( pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv )
+    {
+        iFunc0 = Gia_ManNodeIfToGia_rec( pNew, pIfMan, pTemp->pFanin0, vVisited, fHash );
+        if ( iFunc0 == ~0 )
+            continue;
+        iFunc1 = Gia_ManNodeIfToGia_rec( pNew, pIfMan, pTemp->pFanin1, vVisited, fHash );
+        if ( iFunc1 == ~0 )
+            continue;
+        // both branches are solved
+        if ( fHash )
+            iFunc = Gia_ManHashAnd( pNew, Abc_LitNotCond(iFunc0, pTemp->fCompl0), Abc_LitNotCond(iFunc1, pTemp->fCompl1) ); 
+        else
+            iFunc = Gia_ManAppendAnd( pNew, Abc_LitNotCond(iFunc0, pTemp->fCompl0), Abc_LitNotCond(iFunc1, pTemp->fCompl1) ); 
+        if ( pTemp->fPhase != pIfObj->fPhase )
+            iFunc = Abc_LitNot(iFunc);
+        If_CutSetDataInt( pCut, iFunc );
+        break;
+    }
+    return If_CutDataInt(pCut);
+}
+int Gia_ManNodeIfToGia( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vLeaves, int fHash )
+{
+    If_Cut_t * pCut;
+    If_Obj_t * pLeaf;
+    int i, iRes;
+    // get the best cut
+    pCut = If_ObjCutBest(pIfObj);
+    assert( pCut->nLeaves > 1 );
+    // set the leaf variables
+    If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+        If_CutSetDataInt( If_ObjCutBest(pLeaf), Vec_IntEntry(vLeaves, i) );
+    // recursively compute the function while collecting visited cuts
+    Vec_PtrClear( pIfMan->vTemp );
+    iRes = Gia_ManNodeIfToGia_rec( pNew, pIfMan, pIfObj, pIfMan->vTemp, fHash ); 
+    if ( iRes == ~0 )
+    {
+        Abc_Print( -1, "Gia_ManNodeIfToGia(): Computing local AIG has failed.\n" );
+        return ~0;
+    }
+    // clean the cuts
+    If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+        If_CutSetDataInt( If_ObjCutBest(pLeaf), 0 );
+    Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i )
+        If_CutSetDataInt( pCut, 0 );
+    return iRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts IF into GIA manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManFromIfLogicFindLut( If_Man_t * pIfMan, Gia_Man_t * pNew, If_Cut_t * pCutBest, sat_solver * pSat, Vec_Int_t * vLeaves, Vec_Int_t * vLits, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vPacking )
+{
+    word uBound, uFree;
+    int nLutSize = (int)(pIfMan->pPars->pLutStruct[0] - '0');
+    int nVarsF = 0, pVarsF[IF_MAX_FUNC_LUTSIZE];
+    int nVarsB = 0, pVarsB[IF_MAX_FUNC_LUTSIZE];
+    int nVarsS = 0, pVarsS[IF_MAX_FUNC_LUTSIZE];
+    unsigned uSetNew, uSetOld;
+    int RetValue, RetValue2, k;
+    char * pPerm;
+    if ( Vec_IntSize(vLeaves) <= nLutSize )
+    {
+        RetValue = Gia_ManFromIfLogicCreateLut( pNew, If_CutTruthW(pIfMan, pCutBest), vLeaves, vCover, vMapping, vMapping2 );
+        // write packing
+        if ( !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(RetValue))) && RetValue > 1 )
+        {
+            Vec_IntPush( vPacking, 1 );
+            Vec_IntPush( vPacking, Abc_Lit2Var(RetValue) );
+            Vec_IntAddToEntry( vPacking, 0, 1 );
+        }
+        return RetValue;
+    }
+    assert( If_DsdManSuppSize(pIfMan->pIfDsdMan, If_CutDsdLit(pIfMan, pCutBest)) == (int)pCutBest->nLeaves );
+    // find the bound set
+    if ( pIfMan->pPars->fDelayOptLut )
+        uSetOld = pCutBest->uMaskFunc;
+    else
+        uSetOld = If_DsdManCheckXY( pIfMan->pIfDsdMan, If_CutDsdLit(pIfMan, pCutBest), nLutSize, 1, 0, 1, 0 );
+    // remap bound set
+    uSetNew = 0;
+    pPerm = If_CutDsdPerm( pIfMan, pCutBest );
+    for ( k = 0; k < If_CutLeaveNum(pCutBest); k++ )
+    {
+        int iVar = Abc_Lit2Var((int)pPerm[k]);
+        int Value = ((uSetOld >> (k << 1)) & 3);
+        if ( Value == 1 )
+            uSetNew |= (1 << (2*iVar));
+        else if ( Value == 3 )
+            uSetNew |= (3 << (2*iVar));
+        else assert( Value == 0 );
+    }
+    RetValue = If_ManSatCheckXY( pSat, nLutSize, If_CutTruthW(pIfMan, pCutBest), pCutBest->nLeaves, uSetNew, &uBound, &uFree, vLits );
+    assert( RetValue );
+    // collect variables
+    for ( k = 0; k < If_CutLeaveNum(pCutBest); k++ )
+    {
+        int Value = ((uSetNew >> (k << 1)) & 3);
+        if ( Value == 0 )
+            pVarsF[nVarsF++] = k;
+        else if ( Value == 1 )
+            pVarsB[nVarsB++] = k;
+        else if ( Value == 3 )
+            pVarsS[nVarsS++] = k;
+        else assert( Value == 0 );
+    }
+    // collect bound set variables
+    Vec_IntClear( vLits );
+    for ( k = 0; k < nVarsS; k++ )
+        Vec_IntPush( vLits, Vec_IntEntry(vLeaves, pVarsS[k]) );
+    for ( k = 0; k < nVarsB; k++ )
+        Vec_IntPush( vLits, Vec_IntEntry(vLeaves, pVarsB[k]) );
+    RetValue = Gia_ManFromIfLogicCreateLut( pNew, &uBound, vLits, vCover, vMapping, vMapping2 );
+    // collecct free set variables
+    Vec_IntClear( vLits );
+    Vec_IntPush( vLits, RetValue );
+    for ( k = 0; k < nVarsS; k++ )
+        Vec_IntPush( vLits, Vec_IntEntry(vLeaves, pVarsS[k]) );
+    for ( k = 0; k < nVarsF; k++ )
+        Vec_IntPush( vLits, Vec_IntEntry(vLeaves, pVarsF[k]) );
+    // add packing
+    RetValue2 = Gia_ManFromIfLogicCreateLut( pNew, &uFree, vLits, vCover, vMapping, vMapping2 );
+    // write packing
+    Vec_IntPush( vPacking, 2 );
+    Vec_IntPush( vPacking, Abc_Lit2Var(RetValue) );
+    Vec_IntPush( vPacking, Abc_Lit2Var(RetValue2) );
+    Vec_IntAddToEntry( vPacking, 0, 1 );
+    return RetValue2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts IF into GIA manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFromIfLogic( If_Man_t * pIfMan )
+{
+    Gia_Man_t * pNew;
+    If_Cut_t * pCutBest;
+    If_Obj_t * pIfObj, * pIfLeaf;
+    Vec_Int_t * vMapping, * vMapping2, * vPacking = NULL;
+    Vec_Int_t * vLeaves, * vLeaves2, * vCover, * vLits;
+    sat_solver * pSat = NULL;
+    int i, k, Entry;
+    assert( !pIfMan->pPars->fDeriveLuts || pIfMan->pPars->fTruth );
+//    if ( pIfMan->pPars->fEnableCheck07 )
+//        pIfMan->pPars->fDeriveLuts = 0;
+    // start mapping and packing
+    vMapping  = Vec_IntStart( If_ManObjNum(pIfMan) );
+    vMapping2 = Vec_IntStart( 1 );
+    if ( pIfMan->pPars->fDeriveLuts && (pIfMan->pPars->pLutStruct || pIfMan->pPars->fEnableCheck75 || pIfMan->pPars->fEnableCheck75u || pIfMan->pPars->fEnableCheck07) )
+    {
+        vPacking = Vec_IntAlloc( 1000 );
+        Vec_IntPush( vPacking, 0 );
+    }
+    // create new manager
+    pNew = Gia_ManStart( If_ManObjNum(pIfMan) );
+    // iterate through nodes used in the mapping
+    vLits    = Vec_IntAlloc( 1000 );
+    vCover   = Vec_IntAlloc( 1 << 16 );
+    vLeaves  = Vec_IntAlloc( 16 );
+    vLeaves2 = Vec_IntAlloc( 16 );
+    If_ManCleanCutData( pIfMan );
+    If_ManForEachObj( pIfMan, pIfObj, i )
+    {
+        if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) )
+            continue;
+        if ( If_ObjIsAnd(pIfObj) )
+        {
+            pCutBest = If_ObjCutBest( pIfObj );
+            // perform sorting of cut leaves by delay, so that the slowest pin drives the fastest input of the LUT
+            if ( !pIfMan->pPars->fUseTtPerm && !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->nGateSize && !pIfMan->pPars->fEnableCheck75 && !pIfMan->pPars->fEnableCheck75u && !pIfMan->pPars->fEnableCheck07 )
+                If_CutRotatePins( pIfMan, pCutBest );
+            // collect leaves of the best cut
+            Vec_IntClear( vLeaves );
+            If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, k )
+                Vec_IntPush( vLeaves, pIfLeaf->iCopy );
+            // perform one of the two types of mapping: with and without structures
+            if ( pIfMan->pPars->fUseDsd && pIfMan->pPars->pLutStruct )
+            {
+                if ( pSat == NULL )
+                    pSat = (sat_solver *)If_ManSatBuildXY( (int)(pIfMan->pPars->pLutStruct[0] - '0') );
+                if ( pIfMan->pPars->pLutStruct && pIfMan->pPars->fDeriveLuts )
+                    pIfObj->iCopy = Gia_ManFromIfLogicFindLut( pIfMan, pNew, pCutBest, pSat, vLeaves, vLits, vCover, vMapping, vMapping2, vPacking );
+                else
+                    pIfObj->iCopy = Gia_ManFromIfLogicCreateLut( pNew, If_CutTruthW(pIfMan, pCutBest), vLeaves, vCover, vMapping, vMapping2 );
+                pIfObj->iCopy = Abc_LitNotCond( pIfObj->iCopy, pCutBest->fCompl );
+            }
+            else if ( (pIfMan->pPars->fDeriveLuts && pIfMan->pPars->fTruth) || pIfMan->pPars->fUseDsd || pIfMan->pPars->fUseTtPerm )
+            {
+                word * pTruth = If_CutTruthW(pIfMan, pCutBest);
+                if ( pIfMan->pPars->fUseTtPerm )
+                    for ( k = 0; k < (int)pCutBest->nLeaves; k++ )
+                        if ( If_CutLeafBit(pCutBest, k) )
+                            Abc_TtFlip( pTruth, Abc_TtWordNum(pCutBest->nLeaves), k );
+                // perform decomposition of the cut
+                pIfObj->iCopy = Gia_ManFromIfLogicNode( pIfMan, pNew, i, vLeaves, vLeaves2, pTruth, pIfMan->pPars->pLutStruct, vCover, vMapping, vMapping2, vPacking, (pIfMan->pPars->fEnableCheck75 || pIfMan->pPars->fEnableCheck75u), pIfMan->pPars->fEnableCheck07 );
+                pIfObj->iCopy = Abc_LitNotCond( pIfObj->iCopy, pCutBest->fCompl );
+            }
+            else
+            {
+                pIfObj->iCopy = Gia_ManNodeIfToGia( pNew, pIfMan, pIfObj, vLeaves, 0 );
+                // write mapping
+                Vec_IntSetEntry( vMapping, Abc_Lit2Var(pIfObj->iCopy), Vec_IntSize(vMapping2) );
+                Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) );
+                Vec_IntForEachEntry( vLeaves, Entry, k )
+                    assert( Abc_Lit2Var(Entry) < Abc_Lit2Var(pIfObj->iCopy) );
+                Vec_IntForEachEntry( vLeaves, Entry, k )
+                    Vec_IntPush( vMapping2, Abc_Lit2Var(Entry)  );
+                Vec_IntPush( vMapping2, Abc_Lit2Var(pIfObj->iCopy) );
+            }
+        }
+        else if ( If_ObjIsCi(pIfObj) )
+            pIfObj->iCopy = Gia_ManAppendCi(pNew);
+        else if ( If_ObjIsCo(pIfObj) )
+            pIfObj->iCopy = Gia_ManAppendCo( pNew, Abc_LitNotCond(If_ObjFanin0(pIfObj)->iCopy, If_ObjFaninC0(pIfObj)) );
+        else if ( If_ObjIsConst1(pIfObj) )
+        {
+            pIfObj->iCopy = 1;
+            // create const LUT
+            Vec_IntWriteEntry( vMapping, 0, Vec_IntSize(vMapping2) );
+            Vec_IntPush( vMapping2, 0 );
+            Vec_IntPush( vMapping2, 0 );
+        }
+        else assert( 0 );
+    }
+    Vec_IntFree( vLits );
+    Vec_IntFree( vCover );
+    Vec_IntFree( vLeaves );
+    Vec_IntFree( vLeaves2 );
+    if ( pSat != NULL )
+        sat_solver_delete(pSat);
+//    printf( "Mapping array size:  IfMan = %d. Gia = %d. Increase = %.2f\n", 
+//        If_ManObjNum(pIfMan), Gia_ManObjNum(pNew), 1.0 * Gia_ManObjNum(pNew) / If_ManObjNum(pIfMan) );
+    // finish mapping 
+    if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) )
+        Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) );
+    else
+        Vec_IntFillExtra( vMapping, Gia_ManObjNum(pNew), 0 );
+    assert( Vec_IntSize(vMapping) == Gia_ManObjNum(pNew) );
+    Vec_IntForEachEntry( vMapping, Entry, i )
+        if ( Entry > 0 )
+            Vec_IntAddToEntry( vMapping, i, Gia_ManObjNum(pNew) );
+    Vec_IntAppend( vMapping, vMapping2 );
+    Vec_IntFree( vMapping2 );
+    // attach mapping and packing
+    assert( pNew->vMapping == NULL );
+    assert( pNew->vPacking == NULL );
+    pNew->vMapping = vMapping;
+    pNew->vPacking = vPacking;
+    // verify that COs have mapping
+    {
+        Gia_Obj_t * pObj;
+        Gia_ManForEachCo( pNew, pObj, i )
+           assert( !Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) || Gia_ObjIsLut(pNew, Gia_ObjFaninId0p(pNew, pObj)) );
+    }
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManMappingVerify_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    int Id, iFan, k, Result = 1;
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return 1;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( !Gia_ObjIsAnd(pObj) )
+        return 1;
+    if ( !Gia_ObjIsLut(p, Gia_ObjId(p, pObj)) )
+    {
+        Abc_Print( -1, "Gia_ManMappingVerify: Internal node %d does not have mapping.\n", Gia_ObjId(p, pObj) );
+        return 0;
+    }
+    Id = Gia_ObjId(p, pObj);
+    Gia_LutForEachFanin( p, Id, iFan, k )
+        if ( Result )
+            Result &= Gia_ManMappingVerify_rec( p, Gia_ManObj(p, iFan) );
+    return Result;
+}
+void Gia_ManMappingVerify( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pFanin;
+    int i, Result = 1;
+    assert( Gia_ManHasMapping(p) );
+    Gia_ManIncrementTravId( p );
+    Gia_ManForEachCo( p, pObj, i )
+    {
+        pFanin = Gia_ObjFanin0(pObj);
+        if ( !Gia_ObjIsAnd(pFanin) )
+            continue;
+        if ( !Gia_ObjIsLut(p, Gia_ObjId(p, pFanin)) )
+        {
+            Abc_Print( -1, "Gia_ManMappingVerify: CO driver %d does not have mapping.\n", Gia_ObjId(p, pFanin) );
+            Result = 0;
+            continue;
+        }
+        Result &= Gia_ManMappingVerify_rec( p, pFanin );
+    }
+//    if ( Result && Gia_NtkIsRoot(p) )
+//        Abc_Print( 1, "Mapping verified correctly.\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers mapping from hie GIA to normalized GIA.]
+
+  Description [Hie GIA (pGia) points to normalized GIA (p).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManTransferMapping( Gia_Man_t * pGia, Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, k, iFan;
+    if ( !Gia_ManHasMapping(pGia) )
+        return;
+    Gia_ManMappingVerify( pGia );
+    Vec_IntFreeP( &p->vMapping );
+    p->vMapping = Vec_IntAlloc( 2 * Gia_ManObjNum(p) );
+    Vec_IntFill( p->vMapping, Gia_ManObjNum(p), 0 );
+    Gia_ManForEachLut( pGia, i )
+    {
+        assert( !Abc_LitIsCompl(Gia_ObjValue(Gia_ManObj(pGia, i))) );
+        pObj = Gia_ManObj( p, Abc_Lit2Var(Gia_ObjValue(Gia_ManObj(pGia, i))) );
+        Vec_IntWriteEntry( p->vMapping, Gia_ObjId(p, pObj), Vec_IntSize(p->vMapping) );
+        Vec_IntPush( p->vMapping, Gia_ObjLutSize(pGia, i) );
+        Gia_LutForEachFanin( pGia, i, iFan, k )
+            Vec_IntPush( p->vMapping, Abc_Lit2Var(Gia_ObjValue(Gia_ManObj(pGia, iFan))) );
+        Vec_IntPush( p->vMapping, Gia_ObjLutIsMux(pGia, i) ? -Gia_ObjId(p, pObj) : Gia_ObjId(p, pObj) );
+    }
+    Gia_ManMappingVerify( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers packing from hie GIA to normalized GIA.]
+
+  Description [Hie GIA (pGia) points to normalized GIA (p).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManTransferPacking( Gia_Man_t * pGia, Gia_Man_t * p )
+{
+    Vec_Int_t * vPackingNew;
+    Gia_Obj_t * pObj, * pObjNew;
+    int i, k, Entry, nEntries, nEntries2;
+    if ( pGia->vPacking == NULL )
+        return;
+    nEntries = Vec_IntEntry( pGia->vPacking, 0 );
+    nEntries2 = 0;
+    // create new packing info
+    vPackingNew = Vec_IntAlloc( Vec_IntSize(pGia->vPacking) );
+    Vec_IntPush( vPackingNew, nEntries );
+    Vec_IntForEachEntryStart( pGia->vPacking, Entry, i, 1 )
+    {
+        assert( Entry > 0 && Entry < 4 );
+        Vec_IntPush( vPackingNew, Entry );
+        i++;
+        for ( k = 0; k < Entry; k++, i++ )
+        {
+            pObj = Gia_ManObj(pGia, Vec_IntEntry(pGia->vPacking, i));
+            pObjNew = Gia_ManObj(p, Abc_Lit2Var(Gia_ObjValue(pObj)));
+            assert( Gia_ObjIsLut(pGia, Gia_ObjId(pGia, pObj)) );
+            assert( Gia_ObjIsLut(p, Gia_ObjId(p, pObjNew)) );
+            Vec_IntPush( vPackingNew, Gia_ObjId(p, pObjNew) );
+//            printf( "%d -> %d  ", Vec_IntEntry(pGia->vPacking, i), Gia_ObjId(p, pObjNew) );
+        }
+        i--;
+        nEntries2++;
+    }
+    assert( nEntries == nEntries2 );
+    // attach packing info
+    assert( p->vPacking == NULL );
+    p->vPacking = vPackingNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Interface of LUT mapping package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+Gia_Man_t * Gia_ManPerformMapping( Gia_Man_t * p, void * pp, int fNormalized )
+{
+    extern void Gia_ManIffTest( Gia_Man_t * pGia, If_LibLut_t * pLib, int fVerbose );
+    Gia_Man_t * pNew;
+    If_Man_t * pIfMan;
+    If_Par_t * pPars = (If_Par_t *)pp;
+    // disable cut minimization when GIA strucure is needed
+    if ( !pPars->fDelayOpt && !pPars->fDelayOptLut && !pPars->fDsdBalance && !pPars->fUserRecLib && !pPars->fDeriveLuts && !pPars->fUseDsd && !pPars->fUseTtPerm )
+        pPars->fCutMin = 0;
+
+    // reconstruct GIA according to the hierarchy manager
+    assert( pPars->pTimesArr == NULL );
+    assert( pPars->pTimesReq == NULL );
+    if ( p->pManTime )
+    {
+        if ( fNormalized )
+        {
+            pNew = Gia_ManDupUnnormalize( p );
+            if ( pNew == NULL )
+                return NULL;
+            pNew->pManTime   = p->pManTime;   p->pManTime  = NULL;
+            pNew->pAigExtra  = p->pAigExtra;  p->pAigExtra = NULL;
+            pNew->nAnd2Delay = p->nAnd2Delay; p->nAnd2Delay = 0;
+            p = pNew;
+            // set arrival and required times
+            pPars->pTimesArr = Tim_ManGetArrTimes( (Tim_Man_t *)p->pManTime );
+            pPars->pTimesReq = Tim_ManGetReqTimes( (Tim_Man_t *)p->pManTime );
+        }
+    }
+    else 
+        p = Gia_ManDup( p );
+    // translate into the mapper
+    pIfMan = Gia_ManToIf( p, pPars );    
+    if ( pIfMan == NULL )
+    {
+        Gia_ManStop( p );
+        return NULL;
+    }
+    // create DSD manager
+    if ( pPars->fUseDsd )
+    {
+        If_DsdMan_t * p = (If_DsdMan_t *)Abc_FrameReadManDsd();
+        assert( pPars->nLutSize <= If_DsdManVarNum(p) );
+        assert( (pPars->pLutStruct == NULL && If_DsdManLutSize(p) == 0) || (pPars->pLutStruct && pPars->pLutStruct[0] - '0' == If_DsdManLutSize(p)) );
+        pIfMan->pIfDsdMan = (If_DsdMan_t *)Abc_FrameReadManDsd();
+        if ( pPars->fDsdBalance )
+            If_DsdManAllocIsops( pIfMan->pIfDsdMan, pPars->nLutSize );
+    }
+    // compute switching for the IF objects
+    if ( pPars->fPower )
+    {
+        if ( p->pManTime == NULL )
+            If_ManComputeSwitching( pIfMan );
+        else
+            Abc_Print( 0, "Switching activity computation for designs with boxes is disabled.\n" );
+    }
+    if ( p->pManTime )
+        pIfMan->pManTim = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 );
+    if ( !If_ManPerformMapping( pIfMan ) )
+    {
+        If_ManStop( pIfMan );
+        Gia_ManStop( p );
+        return NULL;
+    }
+    // transform the result of mapping into the new network
+    if ( pIfMan->pPars->fDelayOpt || pIfMan->pPars->fDsdBalance || pIfMan->pPars->fUserRecLib )
+        pNew = Gia_ManFromIfAig( pIfMan );
+    else
+        pNew = Gia_ManFromIfLogic( pIfMan );
+    If_ManStop( pIfMan );
+    // transfer name
+    assert( pNew->pName == NULL );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    // return the original (unmodified by the mapper) timing manager
+    pNew->pManTime   = p->pManTime;   p->pManTime   = NULL;
+    pNew->pAigExtra  = p->pAigExtra;  p->pAigExtra  = NULL;
+    pNew->nAnd2Delay = p->nAnd2Delay; p->nAnd2Delay = 0;
+    Gia_ManStop( p );
+    // normalize and transfer mapping
+    pNew = Gia_ManDupNormalize( p = pNew );
+    Gia_ManTransferMapping( p, pNew );
+    Gia_ManTransferPacking( p, pNew );
+    pNew->pManTime   = p->pManTime;   p->pManTime   = NULL;
+    pNew->pAigExtra  = p->pAigExtra;  p->pAigExtra  = NULL;
+    pNew->nAnd2Delay = p->nAnd2Delay; p->nAnd2Delay = 0;
+    Gia_ManStop( p );
+    return pNew;
+}
+Gia_Man_t * Gia_ManPerformSopBalance( Gia_Man_t * p, int nCutNum, int nRelaxRatio, int fVerbose )
+{
+    Gia_Man_t * pNew;
+    If_Man_t * pIfMan;
+    If_Par_t Pars, * pPars = &Pars;
+    If_ManSetDefaultPars( pPars );
+    pPars->nCutsMax    = nCutNum;
+    pPars->nRelaxRatio = nRelaxRatio;
+    pPars->fVerbose    = fVerbose;
+    pPars->nLutSize    = 6;
+    pPars->fDelayOpt   = 1;
+    pPars->fCutMin     = 1;
+    pPars->fTruth      = 1;
+    pPars->fExpRed     = 0;
+    // perform mapping
+    pIfMan = Gia_ManToIf( p, pPars );
+    If_ManPerformMapping( pIfMan );
+    pNew = Gia_ManFromIfAig( pIfMan );
+    If_ManStop( pIfMan );
+    // transfer name
+    assert( pNew->pName == NULL );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tests decomposition structures.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+void Gia_ManTestStruct( Gia_Man_t * p )
+{
+    int nCutMax = 7;
+    int LutCount[8] = {0}, LutNDecomp[8] = {0};
+    int i, k, iFan, nFanins, Status;
+    Vec_Int_t * vLeaves;
+    word * pTruth;
+
+    vLeaves = Vec_IntAlloc( 100 );
+    Gia_ObjComputeTruthTableStart( p, nCutMax );
+    Gia_ManForEachLut( p, i )
+    {
+        nFanins = Gia_ObjLutSize(p, i);
+        assert( nFanins <= 7 );
+        LutCount[Abc_MaxInt(nFanins, 5)]++;
+        if ( nFanins <= 5 )
+            continue;
+        Vec_IntClear( vLeaves );
+        Gia_LutForEachFanin( p, i, iFan, k )
+            Vec_IntPush( vLeaves, iFan );
+        pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, i), vLeaves );
+        // check if it is decomposable
+        Status = If_CutPerformCheck07( NULL, (unsigned *)pTruth, 7, nFanins, NULL );
+        if ( Status == 1 )
+            continue;
+        LutNDecomp[nFanins]++;
+        if ( LutNDecomp[nFanins] > 10 )
+            continue;
+        Kit_DsdPrintFromTruth( (unsigned *)pTruth, nFanins ); printf( "\n" );
+    }
+    Gia_ObjComputeTruthTableStop( p );
+
+    printf( "LUT5 = %d    ", LutCount[5] );
+    printf( "LUT6 = %d  NonDec = %d (%.2f %%)    ", LutCount[6], LutNDecomp[6], 100.0 * LutNDecomp[6]/Abc_MaxInt(LutCount[6], 1) );
+    printf( "LUT7 = %d  NonDec = %d (%.2f %%)    ", LutCount[7], LutNDecomp[7], 100.0 * LutNDecomp[7]/Abc_MaxInt(LutCount[7], 1) );
+    printf( "\n" );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaIff.c b/abc-build/src/aig/gia/giaIff.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaIff.c
@@ -0,0 +1,444 @@
+/**CFile****************************************************************
+
+  FileName    [giaIff.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Hierarchical mapping of AIG with white boxes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaIff.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "map/if/if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Iff_Man_t_ Iff_Man_t;
+struct Iff_Man_t_
+{
+    Gia_Man_t *     pGia;       // mapped GIA
+    If_LibLut_t *   pLib;       // LUT library
+    int             nLutSize;   // LUT size
+    int             nDegree;    // degree 
+    Vec_Flt_t *     vTimes;     // arrival times
+    Vec_Int_t *     vMatch[4];  // matches
+};
+
+static inline float Iff_ObjTimeId( Iff_Man_t * p, int iObj )                                { return Vec_FltEntry( p->vTimes, iObj );                       }
+static inline float Iff_ObjTime( Iff_Man_t * p, Gia_Obj_t * pObj )                          { return Iff_ObjTimeId( p, Gia_ObjId(p->pGia, pObj) );          }
+static inline void  Iff_ObjSetTimeId( Iff_Man_t * p, int iObj, float Time )                 { Vec_FltWriteEntry( p->vTimes, iObj, Time );                   }
+static inline void  Iff_ObjSetTime( Iff_Man_t * p, Gia_Obj_t * pObj, float Time )           { Iff_ObjSetTimeId( p, Gia_ObjId(p->pGia, pObj), Time );        }
+
+static inline int   Iff_ObjMatchId( Iff_Man_t * p, int iObj, int Type )                     { return Vec_IntEntry( p->vMatch[Type], iObj );                 }
+static inline int   Iff_ObjMatch( Iff_Man_t * p, Gia_Obj_t * pObj, int Type )               { return Iff_ObjMatchId( p, Gia_ObjId(p->pGia, pObj), Type );   }
+static inline void  Iff_ObjSetMatchId( Iff_Man_t * p, int iObj, int Type, int Match )       { Vec_IntWriteEntry( p->vMatch[Type], iObj, Match );            }
+static inline void  Iff_ObjSetMatch( Iff_Man_t * p, Gia_Obj_t * pObj, int Type, int Match ) { Iff_ObjSetMatchId( p, Gia_ObjId(p->pGia, pObj), Type, Match );}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Iff_Man_t * Gia_ManIffStart( Gia_Man_t * pGia )
+{
+    Iff_Man_t * p = ABC_CALLOC( Iff_Man_t, 1 );
+    p->vTimes    = Vec_FltStartFull( Gia_ManObjNum(pGia) );
+    p->vMatch[2] = Vec_IntStartFull( Gia_ManObjNum(pGia) );
+    p->vMatch[3] = Vec_IntStartFull( Gia_ManObjNum(pGia) );
+    return p;
+}
+void Gia_ManIffStop( Iff_Man_t * p )
+{
+    Vec_FltFree( p->vTimes );
+    Vec_IntFree( p->vMatch[2] );
+    Vec_IntFree( p->vMatch[3] );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of unique fanins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_IffObjCount( Gia_Man_t * pGia, int iObj, int iFaninSkip2, int iFaninSkip3 )
+{
+    int i, iFanin, Count = 0;
+    Gia_ManIncrementTravId( pGia );
+    Gia_LutForEachFanin( pGia, iObj, iFanin, i )
+    {
+        if ( iFanin == iFaninSkip2 || iFanin == iFaninSkip3 )
+            continue;
+        if ( Gia_ObjIsTravIdCurrentId( pGia, iFanin ) )
+            continue;
+        Gia_ObjSetTravIdCurrentId( pGia, iFanin );
+        Count++;
+    }
+    if ( iFaninSkip2 >= 0 )
+    {
+        Gia_LutForEachFanin( pGia, iFaninSkip2, iFanin, i )
+        {
+            if ( iFanin == iFaninSkip3 )
+                continue;
+            if ( Gia_ObjIsTravIdCurrentId( pGia, iFanin ) )
+                continue;
+            Gia_ObjSetTravIdCurrentId( pGia, iFanin );
+            Count++;
+        }
+    }
+    if ( iFaninSkip3 >= 0 )
+    {
+        Gia_LutForEachFanin( pGia, iFaninSkip3, iFanin, i )
+        {
+            if ( iFanin == iFaninSkip2 )
+                continue;
+            if ( Gia_ObjIsTravIdCurrentId( pGia, iFanin ) )
+                continue;
+            Gia_ObjSetTravIdCurrentId( pGia, iFanin );
+            Count++;
+        }
+    }
+    return Count;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Gia_IffObjTimeOne( Iff_Man_t * p, int iObj, int iFaninSkip2, int iFaninSkip3 )
+{
+    int i, iFanin;
+    float DelayMax = -ABC_INFINITY;
+    Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
+        if ( iFanin != iFaninSkip2 && iFanin != iFaninSkip3 && DelayMax < Iff_ObjTimeId(p, iFanin) )
+            DelayMax = Iff_ObjTimeId(p, iFanin);
+    assert( i == Gia_ObjLutSize(p->pGia, iObj) );
+    if ( iFaninSkip2 == -1 )
+        return DelayMax;
+    Gia_LutForEachFanin( p->pGia, iFaninSkip2, iFanin, i )
+        if ( iFanin != iFaninSkip3 && DelayMax < Iff_ObjTimeId(p, iFanin) )
+            DelayMax = Iff_ObjTimeId(p, iFanin);
+    if ( iFaninSkip3 == -1 )
+        return DelayMax;
+    Gia_LutForEachFanin( p->pGia, iFaninSkip3, iFanin, i )
+        if ( iFanin != iFaninSkip2 && DelayMax < Iff_ObjTimeId(p, iFanin) )
+            DelayMax = Iff_ObjTimeId(p, iFanin);
+    assert( DelayMax >= 0 );
+    return DelayMax;
+}
+float Gia_IffObjTimeTwo( Iff_Man_t * p, int iObj, int * piFanin, float DelayMin )
+{
+    int i, iFanin, nSize;
+    float This;
+    *piFanin = -1;
+    Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
+    {
+        if ( Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin)) )
+            continue;
+        This = Gia_IffObjTimeOne( p, iObj, iFanin, -1 );
+        nSize = Gia_IffObjCount( p->pGia, iObj, iFanin, -1 );
+        assert( nSize <= p->pLib->LutMax );
+        This += p->pLib->pLutDelays[nSize][0];
+        if ( DelayMin > This )
+        {
+            DelayMin = This;
+            *piFanin = iFanin;
+        }
+    }
+    return DelayMin;
+}
+float Gia_IffObjTimeThree( Iff_Man_t * p, int iObj, int * piFanin, int * piFanin2, float DelayMin )
+{
+    int i, k, iFanin, iFanin2, nSize;
+    float This;
+    *piFanin = -1;
+    *piFanin2 = -1;
+    Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
+    Gia_LutForEachFanin( p->pGia, iObj, iFanin2, k )
+    {
+        if ( iFanin == iFanin2 )
+            continue;
+        if ( Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin)) )
+            continue;
+        if ( Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin2)) )
+            continue;
+        This  = Gia_IffObjTimeOne( p, iObj, iFanin, iFanin2 );
+        nSize = Gia_IffObjCount( p->pGia, iObj, iFanin, iFanin2 );
+        assert( nSize <= p->pLib->LutMax );
+        This += p->pLib->pLutDelays[nSize][0];
+        if ( DelayMin > This )
+        {
+            DelayMin  = This;
+            *piFanin  = iFanin;
+            *piFanin2 = iFanin2;
+        }
+    }
+    return DelayMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Iff_Man_t * Gia_ManIffPerform( Gia_Man_t * pGia, If_LibLut_t * pLib, Tim_Man_t * pTime, int nLutSize, int nDegree )
+{
+    Iff_Man_t * p;
+    Gia_Obj_t * pObj;
+    int iObj, iFanin, iFanin1, iFanin2;
+    int CountAll = 0, Count2 = 0, Count3 = 0;
+    float arrTime1, arrTime2, arrTime3, arrMax = -ABC_INFINITY; 
+    assert( nDegree == 2 || nDegree == 3 );
+    // start the mapping manager and set its parameters
+    p = Gia_ManIffStart( pGia );
+    p->pGia     = pGia;
+    p->pLib     = pLib;
+    p->nLutSize = nLutSize;
+    p->nDegree  = nDegree;
+    // compute arrival times of each node
+    Iff_ObjSetTimeId( p, 0, 0 );
+    Tim_ManIncrementTravId( pTime );
+    Gia_ManForEachObj1( pGia, pObj, iObj )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            if ( !Gia_ObjIsLut(pGia, iObj) )
+                continue;
+            CountAll++;
+            // compute arrival times of LUT inputs
+            arrTime1 = Gia_IffObjTimeOne( p, iObj, -1, -1 );
+            arrTime1 += p->pLib->pLutDelays[Gia_ObjLutSize(pGia, iObj)][0];
+            // compute arrival times of LUT pairs
+            arrTime2 = Gia_IffObjTimeTwo( p, iObj, &iFanin, arrTime1 );
+            if ( nDegree == 2 )
+            {
+                // set arrival times
+                Iff_ObjSetTimeId( p, iObj, arrTime2 );
+                if ( arrTime2 < arrTime1 )
+                    Iff_ObjSetMatchId( p, iObj, 2, iFanin ), Count2++;                
+            }
+            else if ( nDegree == 3 )
+            {                
+                // compute arrival times of LUT triples
+                arrTime3 = Gia_IffObjTimeThree( p, iObj, &iFanin1, &iFanin2, arrTime2 );
+                // set arrival times
+                Iff_ObjSetTimeId( p, iObj, arrTime3 );
+                if ( arrTime3 == arrTime1 )
+                    continue;
+                if ( arrTime3 == arrTime2 )
+                    Iff_ObjSetMatchId( p, iObj, 2, iFanin ), Count2++;
+                else
+                {
+                    assert( arrTime3 < arrTime2 );
+                    Iff_ObjSetMatchId( p, iObj, 2, iFanin1 );
+                    Iff_ObjSetMatchId( p, iObj, 3, iFanin2 ), Count3++;
+                }
+            }
+            else assert( 0 );
+        }
+        else if ( Gia_ObjIsCi(pObj) )
+        {
+            arrTime1 = Tim_ManGetCiArrival( pTime, Gia_ObjCioId(pObj) );
+            Iff_ObjSetTime( p, pObj, arrTime1 );
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+        {
+            arrTime1 = Iff_ObjTimeId( p, Gia_ObjFaninId0p(pGia, pObj) );
+            Tim_ManSetCoArrival( pTime, Gia_ObjCioId(pObj), arrTime1 );
+            Iff_ObjSetTime( p, pObj, arrTime1 );
+            arrMax = Abc_MaxFloat( arrMax, arrTime1 );
+        }
+        else assert( 0 );
+    }
+    printf( "Max delay = %.2f.  Count1 = %d.  Count2 = %d.  Count3 = %d.\n", 
+        arrMax, CountAll - Count2 - Count3, Count2, Count3 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+void Gia_ManIffSelect_rec( Iff_Man_t * p, int iObj, Vec_Int_t * vPacking )
+{
+    int i, iFanin, iFaninSkip2, iFaninSkip3;
+    if ( Gia_ObjIsTravIdCurrentId( p->pGia, iObj ) )
+        return;
+    Gia_ObjSetTravIdCurrentId( p->pGia, iObj );
+    assert( Gia_ObjIsLut(p->pGia, iObj) );
+    iFaninSkip2 = Iff_ObjMatchId(p, iObj, 2);
+    iFaninSkip3 = Iff_ObjMatchId(p, iObj, 3);
+    if ( iFaninSkip2 == -1 )
+    {
+        assert( iFaninSkip3 == -1 );
+        Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
+            Gia_ManIffSelect_rec( p, iFanin, vPacking );
+        Vec_IntPush( vPacking, 1 );
+        Vec_IntPush( vPacking, iObj );
+    }
+    else if ( iFaninSkip3 == -1 )
+    {
+        assert( iFaninSkip2 > 0 );
+        Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
+            if ( iFanin != iFaninSkip2 )
+                Gia_ManIffSelect_rec( p, iFanin, vPacking );
+        Gia_LutForEachFanin( p->pGia, iFaninSkip2, iFanin, i )
+            Gia_ManIffSelect_rec( p, iFanin, vPacking );
+        Vec_IntPush( vPacking, 2 );
+        Vec_IntPush( vPacking, iFaninSkip2 );
+        Vec_IntPush( vPacking, iObj );
+    }
+    else
+    {
+        assert( iFaninSkip2 > 0 && iFaninSkip3 > 0 );
+        Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
+            if ( iFanin != iFaninSkip2 && iFanin != iFaninSkip3 )
+                Gia_ManIffSelect_rec( p, iFanin, vPacking );
+        Gia_LutForEachFanin( p->pGia, iFaninSkip2, iFanin, i )
+            if ( iFanin != iFaninSkip3 )
+                Gia_ManIffSelect_rec( p, iFanin, vPacking );
+        Gia_LutForEachFanin( p->pGia, iFaninSkip3, iFanin, i )
+            if ( iFanin != iFaninSkip2 )
+                Gia_ManIffSelect_rec( p, iFanin, vPacking );
+        Vec_IntPush( vPacking, 3 );
+        Vec_IntPush( vPacking, iFaninSkip2 );
+        Vec_IntPush( vPacking, iFaninSkip3 );
+        Vec_IntPush( vPacking, iObj );
+    }
+    Vec_IntAddToEntry( vPacking, 0, 1 );
+}
+Vec_Int_t * Gia_ManIffSelect( Iff_Man_t * p )
+{
+    Vec_Int_t * vPacking;
+    Gia_Obj_t * pObj; int i;
+    vPacking = Vec_IntAlloc( Gia_ManObjNum(p->pGia) );
+    Vec_IntPush( vPacking, 0 );
+    // mark const0 and PIs
+    Gia_ManIncrementTravId( p->pGia );
+    Gia_ObjSetTravIdCurrentId( p->pGia, 0 );
+    Gia_ManForEachCi( p->pGia, pObj, i )
+        Gia_ObjSetTravIdCurrent( p->pGia, pObj );
+    // recursively collect internal nodes
+    Gia_ManForEachCo( p->pGia, pObj, i )
+        Gia_ManIffSelect_rec( p, Gia_ObjFaninId0p(p->pGia, pObj), vPacking );
+    return vPacking;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This command performs hierarhical mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+void Gia_ManIffTest( Gia_Man_t * pGia, If_LibLut_t * pLib, int fVerbose )
+{
+    Iff_Man_t * p;
+    Tim_Man_t * pTemp = NULL;
+    int nDegree = -1;
+    int nLutSize = Gia_ManLutSizeMax( pGia );
+    if ( nLutSize <= 4 )
+    {
+        nLutSize = 4;
+        if ( pLib->LutMax == 7 )
+            nDegree = 2;
+        else if ( pLib->LutMax == 10 )
+            nDegree = 3;
+        else
+            { printf( "LUT library for packing 4-LUTs should have 7 or 10 inputs.\n" ); return; }
+    }
+    else if ( nLutSize <= 6 )
+    {
+        nLutSize = 6;
+        if ( pLib->LutMax == 11 )
+            nDegree = 2;
+        else if ( pLib->LutMax == 16 )
+            nDegree = 3;
+        else
+            { printf( "LUT library for packing 6-LUTs should have 11 or 16 inputs.\n" ); return; }
+    }
+    else
+    {
+        printf( "The LUT size is more than 6.\n" );
+        return;
+    }
+    if ( fVerbose )
+        printf( "Performing %d-clustering with %d-LUTs:\n", nDegree, nLutSize );
+    // create timing manager
+    if ( pGia->pManTime == NULL )
+        pGia->pManTime = pTemp = Tim_ManStart( Gia_ManCiNum(pGia), Gia_ManCoNum(pGia) );
+    // perform timing computation
+    p = Gia_ManIffPerform( pGia, pLib, (Tim_Man_t *)pGia->pManTime, nLutSize, nDegree );
+    // remove timing manager
+    if ( pGia->pManTime == pTemp )
+        pGia->pManTime = NULL;
+    Tim_ManStopP( (Tim_Man_t **)&pTemp );
+    // derive clustering
+    Vec_IntFreeP( &pGia->vPacking );
+    pGia->vPacking = Gia_ManIffSelect( p );
+    Gia_ManIffStop( p );
+    // print statistics
+    if ( fVerbose )
+        Gia_ManPrintPackingStats( pGia );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaIso.c b/abc-build/src/aig/gia/giaIso.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaIso.c
@@ -0,0 +1,1331 @@
+/**CFile****************************************************************
+
+  FileName    [giaIso.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Graph isomorphism.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaIso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+ 
+
+#define ISO_MASK 0xFF
+static int s_256Primes[ISO_MASK+1] = 
+{
+    0x984b6ad9,0x18a6eed3,0x950353e2,0x6222f6eb,0xdfbedd47,0xef0f9023,0xac932a26,0x590eaf55,
+    0x97d0a034,0xdc36cd2e,0x22736b37,0xdc9066b0,0x2eb2f98b,0x5d9c7baf,0x85747c9e,0x8aca1055,
+    0x50d66b74,0x2f01ae9e,0xa1a80123,0x3e1ce2dc,0xebedbc57,0x4e68bc34,0x855ee0cf,0x17275120,
+    0x2ae7f2df,0xf71039eb,0x7c283eec,0x70cd1137,0x7cf651f3,0xa87bfa7a,0x14d87f02,0xe82e197d,
+    0x8d8a5ebe,0x1e6a15dc,0x197d49db,0x5bab9c89,0x4b55dea7,0x55dede49,0x9a6a8080,0xe5e51035,
+    0xe148d658,0x8a17eb3b,0xe22e4b38,0xe5be2a9a,0xbe938cbb,0x3b981069,0x7f9c0c8e,0xf756df10,
+    0x8fa783f7,0x252062ce,0x3dc46b4b,0xf70f6432,0x3f378276,0x44b137a1,0x2bf74b77,0x04892ed6,
+    0xfd318de1,0xd58c235e,0x94c6d25b,0x7aa5f218,0x35c9e921,0x5732fbbb,0x06026481,0xf584a44f,
+    0x946e1b5f,0x8463d5b2,0x4ebca7b2,0x54887b15,0x08d1e804,0x5b22067d,0x794580f6,0xb351ea43,
+    0xbce555b9,0x19ae2194,0xd32f1396,0x6fc1a7f1,0x1fd8a867,0x3a89fdb0,0xea49c61c,0x25f8a879,
+    0xde1e6437,0x7c74afca,0x8ba63e50,0xb1572074,0xe4655092,0xdb6f8b1c,0xc2955f3c,0x327f85ba,
+    0x60a17021,0x95bd261d,0xdea94f28,0x04528b65,0xbe0109cc,0x26dd5688,0x6ab2729d,0xc4f029ce,
+    0xacf7a0be,0x4c912f55,0x34c06e65,0x4fbb938e,0x1533fb5f,0x03da06bd,0x48262889,0xc2523d7d,
+    0x28a71d57,0x89f9713a,0xf574c551,0x7a99deb5,0x52834d91,0x5a6f4484,0xc67ba946,0x13ae698f,
+    0x3e390f34,0x34fc9593,0x894c7932,0x6cf414a3,0xdb7928ab,0x13a3b8a3,0x4b381c1d,0xa10b54cb,
+    0x55359d9d,0x35a3422a,0x58d1b551,0x0fd4de20,0x199eb3f4,0x167e09e2,0x3ee6a956,0x5371a7fa,
+    0xd424efda,0x74f521c5,0xcb899ff6,0x4a42e4f4,0x747917b6,0x4b08df0b,0x090c7a39,0x11e909e4,
+    0x258e2e32,0xd9fad92d,0x48fe5f69,0x0545cde6,0x55937b37,0x9b4ae4e4,0x1332b40e,0xc3792351,
+    0xaff982ef,0x4dba132a,0x38b81ef1,0x28e641bf,0x227208c1,0xec4bbe37,0xc4e1821c,0x512c9d09,
+    0xdaef1257,0xb63e7784,0x043e04d7,0x9c2cea47,0x45a0e59a,0x281315ca,0x849f0aac,0xa4071ed3,
+    0x0ef707b3,0xfe8dac02,0x12173864,0x471f6d46,0x24a53c0a,0x35ab9265,0xbbf77406,0xa2144e79,
+    0xb39a884a,0x0baf5b6d,0xcccee3dd,0x12c77584,0x2907325b,0xfd1adcd2,0xd16ee972,0x345ad6c1,
+    0x315ebe66,0xc7ad2b8d,0x99e82c8d,0xe52da8c8,0xba50f1d3,0x66689cd8,0x2e8e9138,0x43e15e74,
+    0xf1ced14d,0x188ec52a,0xe0ef3cbb,0xa958aedc,0x4107a1bc,0x5a9e7a3e,0x3bde939f,0xb5b28d5a,
+    0x596fe848,0xe85ad00c,0x0b6b3aae,0x44503086,0x25b5695c,0xc0c31dcd,0x5ee617f0,0x74d40c3a,
+    0xd2cb2b9f,0x1e19f5fa,0x81e24faf,0xa01ed68f,0xcee172fc,0x7fdf2e4d,0x002f4774,0x664f82dd,
+    0xc569c39a,0xa2d4dcbe,0xaadea306,0xa4c947bf,0xa413e4e3,0x81fb5486,0x8a404970,0x752c980c,
+    0x98d1d881,0x5c932c1e,0xeee65dfb,0x37592cdd,0x0fd4e65b,0xad1d383f,0x62a1452f,0x8872f68d,
+    0xb58c919b,0x345c8ee3,0xb583a6d6,0x43d72cb3,0x77aaa0aa,0xeb508242,0xf2db64f8,0x86294328,
+    0x82211731,0x1239a9d5,0x673ba5de,0xaf4af007,0x44203b19,0x2399d955,0xa175cd12,0x595928a7,
+    0x6918928b,0xde3126bb,0x6c99835c,0x63ba1fa2,0xdebbdff0,0x3d02e541,0xd6f7aac6,0xe80b4cd0,
+    0xd0fa29f1,0x804cac5e,0x2c226798,0x462f624c,0xad05b377,0x22924fcd,0xfbea205c,0x1b47586d
+};
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Gia_IsoMan_t_       Gia_IsoMan_t;
+struct Gia_IsoMan_t_ 
+{
+    Gia_Man_t *      pGia;
+    int              nObjs;
+    int              nUniques;
+    int              nSingles;
+    int              nEntries;
+    // internal data
+    int *            pLevels;
+    int *            pUniques;
+    word *           pStoreW;
+    unsigned *       pStoreU;
+    // equivalence classes
+    Vec_Int_t *      vLevCounts;
+    Vec_Int_t *      vClasses;
+    Vec_Int_t *      vClasses2;
+    // statistics 
+    abctime          timeStart;
+    abctime          timeSim;
+    abctime          timeRefine;
+    abctime          timeSort;
+    abctime          timeOther;
+    abctime          timeTotal;
+};
+
+static inline unsigned  Gia_IsoGetValue( Gia_IsoMan_t * p, int i )             { return (unsigned)(p->pStoreW[i]);       }
+static inline unsigned  Gia_IsoGetItem( Gia_IsoMan_t * p, int i )              { return (unsigned)(p->pStoreW[i] >> 32); }
+
+static inline void      Gia_IsoSetValue( Gia_IsoMan_t * p, int i, unsigned v ) { ((unsigned *)(p->pStoreW + i))[0] = v;  }
+static inline void      Gia_IsoSetItem( Gia_IsoMan_t * p, int i, unsigned v )  { ((unsigned *)(p->pStoreW + i))[1] = v;  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_IsoMan_t * Gia_IsoManStart( Gia_Man_t * pGia )
+{
+    Gia_IsoMan_t * p;
+    p = ABC_CALLOC( Gia_IsoMan_t, 1 );
+    p->pGia      = pGia;
+    p->nObjs     = Gia_ManObjNum( pGia );
+    p->nUniques  = 1;
+    p->nEntries  = p->nObjs;
+    // internal data
+    p->pLevels   = ABC_CALLOC( int, p->nObjs );
+    p->pUniques  = ABC_CALLOC( int, p->nObjs );
+    p->pStoreW   = ABC_CALLOC( word, p->nObjs );
+    // class representation
+    p->vClasses  = Vec_IntAlloc( p->nObjs/4 );
+    p->vClasses2 = Vec_IntAlloc( p->nObjs/4 );
+    return p;
+}
+void Gia_IsoManStop( Gia_IsoMan_t * p )
+{
+    // class representation
+    Vec_IntFree( p->vClasses );
+    Vec_IntFree( p->vClasses2 );
+    // internal data
+    ABC_FREE( p->pLevels );
+    ABC_FREE( p->pUniques );
+    ABC_FREE( p->pStoreW );
+    ABC_FREE( p );
+}
+void Gia_IsoManTransferUnique( Gia_IsoMan_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    // copy unique numbers into the nodes
+    Gia_ManForEachObj( p->pGia, pObj, i )
+        pObj->Value = p->pUniques[i];
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_IsoPrintClasses( Gia_IsoMan_t * p )
+{
+    int fVerbose = 0;
+    int i, k, iBegin, nSize;
+    printf( "The total of %d classes:\n", Vec_IntSize(p->vClasses)/2 );
+    Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i )
+    {
+        printf( "%5d : (%3d,%3d)  ", i/2, iBegin, nSize );
+        if ( fVerbose )
+        {
+            printf( "{" );
+            for ( k = 0; k < nSize; k++ )
+                printf( " %3d,%08x", Gia_IsoGetItem(p, iBegin+k), Gia_IsoGetValue(p, iBegin+k) );
+            printf( " }" );
+        }
+        printf( "\n" );
+    }
+}
+void Gia_IsoPrint( Gia_IsoMan_t * p, int Iter, abctime Time )
+{
+    printf( "Iter %4d :  ", Iter );
+    printf( "Entries =%8d.  ", p->nEntries );
+//    printf( "Classes =%8d.  ", Vec_IntSize(p->vClasses)/2 );
+    printf( "Uniques =%8d.  ", p->nUniques );
+    printf( "Singles =%8d.  ", p->nSingles );
+    printf( "%9.2f sec", (float)(Time)/(float)(CLOCKS_PER_SEC) );
+    printf( "\n" );
+    fflush( stdout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_IsoPrepare( Gia_IsoMan_t * p )
+{
+    Gia_Obj_t * pObj;
+    int * pLevBegins, * pLevSizes;
+    int i, iObj, MaxLev = 0;
+    // assign levels
+    p->pLevels[0] = 0;
+    Gia_ManForEachCi( p->pGia, pObj, i )
+        p->pLevels[Gia_ObjId(p->pGia, pObj)] = 0;
+    Gia_ManForEachAnd( p->pGia, pObj, i )
+        p->pLevels[i] = 1 + Abc_MaxInt( p->pLevels[Gia_ObjFaninId0(pObj, i)], p->pLevels[Gia_ObjFaninId1(pObj, i)] );
+    Gia_ManForEachCo( p->pGia, pObj, i )
+    {
+        iObj = Gia_ObjId(p->pGia, pObj);
+        p->pLevels[iObj] = 1 + p->pLevels[Gia_ObjFaninId0(pObj, iObj)]; // "1 +" is different!
+        MaxLev = Abc_MaxInt( MaxLev, p->pLevels[Gia_ObjId(p->pGia, pObj)] );
+    }
+
+    // count nodes on each level
+    pLevSizes = ABC_CALLOC( int, MaxLev+1 );
+    for ( i = 1; i < p->nObjs; i++ )
+        pLevSizes[p->pLevels[i]]++;
+    // start classes
+    Vec_IntClear( p->vClasses );
+    Vec_IntPush( p->vClasses, 0 );
+    Vec_IntPush( p->vClasses, 1 );
+    // find beginning of each level
+    pLevBegins = ABC_CALLOC( int, MaxLev+2 );
+    pLevBegins[0] = 1;
+    for ( i = 0; i <= MaxLev; i++ )
+    {
+        assert( pLevSizes[i] > 0 ); // we do not allow AIG with a const node and no PIs
+        Vec_IntPush( p->vClasses, pLevBegins[i] );
+        Vec_IntPush( p->vClasses, pLevSizes[i] );
+        pLevBegins[i+1] = pLevBegins[i] + pLevSizes[i];
+    }
+    assert( pLevBegins[MaxLev+1] == p->nObjs );
+    // put them into the structure
+    for ( i = 1; i < p->nObjs; i++ )
+        Gia_IsoSetItem( p, pLevBegins[p->pLevels[i]]++, i );
+    ABC_FREE( pLevBegins );
+    ABC_FREE( pLevSizes );
+/*
+    // print the results
+    for ( i = 0; i < p->nObjs; i++ )
+        printf( "%3d : (%d,%d)\n", i, Gia_IsoGetItem(p, i), Gia_IsoGetValue(p, i) );
+    printf( "\n" );
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_IsoAssignUnique( Gia_IsoMan_t * p )
+{
+    int i, iBegin, nSize;
+    p->nSingles = 0;
+    Vec_IntClear( p->vClasses2 );
+    Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i )
+    {
+        if ( nSize == 1 )
+        {
+            assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 );
+            p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++;
+            p->nSingles++;
+        }
+        else
+        {
+            Vec_IntPush( p->vClasses2, iBegin );
+            Vec_IntPush( p->vClasses2, nSize );
+        }
+    }
+    ABC_SWAP( Vec_Int_t *, p->vClasses, p->vClasses2 );
+    p->nEntries -= p->nSingles;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_IsoSort( Gia_IsoMan_t * p )
+{
+    Gia_Obj_t * pObj, * pObj0;
+    int i, k, fSameValue, iBegin, iBeginOld, nSize, nSizeNew;
+    int fRefined = 0;
+    abctime clk;
+
+    // go through the equiv classes
+    p->nSingles = 0;
+    Vec_IntClear( p->vClasses2 );
+    Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i )
+    {
+        assert( nSize > 1 );
+        fSameValue = 1;
+        pObj0 = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin) );
+        for ( k = 0; k < nSize; k++ )
+        {
+            pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin+k) );
+            Gia_IsoSetValue( p, iBegin+k, pObj->Value );
+            if ( pObj->Value != pObj0->Value )
+                fSameValue = 0;
+        }
+        if ( fSameValue )
+        {
+            Vec_IntPush( p->vClasses2, iBegin );
+            Vec_IntPush( p->vClasses2, nSize );
+            continue;
+        }
+        fRefined = 1;
+        // sort objects
+        clk = Abc_Clock();
+        Abc_QuickSort3( p->pStoreW + iBegin, nSize, 0 );
+        p->timeSort += Abc_Clock() - clk;
+        // divide into new classes
+        iBeginOld = iBegin;
+        pObj0 = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin) );
+        for ( k = 1; k < nSize; k++ )
+        {
+            pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin+k) );
+            if ( pObj0->Value == pObj->Value )
+                continue;
+            nSizeNew = iBegin + k - iBeginOld;
+            if ( nSizeNew == 1 )
+            {
+                assert( p->pUniques[Gia_IsoGetItem(p, iBeginOld)] == 0 );
+                p->pUniques[Gia_IsoGetItem(p, iBeginOld)] = p->nUniques++;
+                p->nSingles++;
+            }
+            else
+            {
+                Vec_IntPush( p->vClasses2, iBeginOld );
+                Vec_IntPush( p->vClasses2, nSizeNew );
+            }
+            iBeginOld = iBegin + k;
+            pObj0 = pObj;
+        }
+        // add the last one
+        nSizeNew = iBegin + k - iBeginOld;
+        if ( nSizeNew == 1 )
+        {
+            assert( p->pUniques[Gia_IsoGetItem(p, iBeginOld)] == 0 );
+            p->pUniques[Gia_IsoGetItem(p, iBeginOld)] = p->nUniques++;
+            p->nSingles++;
+        }
+        else
+        {
+            Vec_IntPush( p->vClasses2, iBeginOld );
+            Vec_IntPush( p->vClasses2, nSizeNew );
+        }
+    }
+
+    ABC_SWAP( Vec_Int_t *, p->vClasses, p->vClasses2 );
+    p->nEntries -= p->nSingles;
+    return fRefined;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Gia_IsoCollectCosClasses( Gia_IsoMan_t * p, int fVerbose )
+{
+    Vec_Ptr_t * vGroups;
+    Vec_Int_t * vLevel;
+    Gia_Obj_t * pObj;
+    int i, k, iBegin, nSize;
+    // add singletons
+    vGroups = Vec_PtrAlloc( 1000 );
+    Gia_ManForEachPo( p->pGia, pObj, i )
+        if ( p->pUniques[Gia_ObjId(p->pGia, pObj)] > 0 )
+        {
+            vLevel = Vec_IntAlloc( 1 );
+            Vec_IntPush( vLevel, i );
+            Vec_PtrPush( vGroups, vLevel );
+        }
+
+    // add groups
+    Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i )
+    {
+        for ( k = 0; k < nSize; k++ )
+        {
+            pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin+k) );
+            if ( Gia_ObjIsPo(p->pGia, pObj) )
+                break;
+        }
+        if ( k == nSize )
+            continue;
+        vLevel = Vec_IntAlloc( 8 );
+        for ( k = 0; k < nSize; k++ )
+        {
+            pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin+k) );
+            if ( Gia_ObjIsPo(p->pGia, pObj) )
+                Vec_IntPush( vLevel, Gia_ObjCioId(pObj) );
+        }
+        Vec_PtrPush( vGroups, vLevel );
+    }
+    // canonicize order
+    Vec_PtrForEachEntry( Vec_Int_t *, vGroups, vLevel, i )
+        Vec_IntSort( vLevel, 0 );
+    Vec_VecSortByFirstInt( (Vec_Vec_t *)vGroups, 0 );
+//    Vec_VecFree( (Vec_Vec_t *)vGroups );
+//    return NULL;
+    return vGroups;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Gia_IsoUpdateValue( int Value, int fCompl )
+{
+    return (Value+1) * s_256Primes[Abc_Var2Lit(Value, fCompl) & ISO_MASK];
+}
+static inline unsigned Gia_IsoUpdate( Gia_IsoMan_t * p, int Iter, int iObj, int fCompl )
+{
+    if ( Iter == 0 )              return Gia_IsoUpdateValue( p->pLevels[iObj], fCompl );
+    if ( p->pUniques[iObj] > 0 )  return Gia_IsoUpdateValue( p->pUniques[iObj], fCompl );
+//    if ( p->pUniques[iObj] > 0 )  return Gia_IsoUpdateValue( 11, fCompl );
+    return 0;
+}
+void Gia_IsoSimulate( Gia_IsoMan_t * p, int Iter )
+{
+    Gia_Obj_t * pObj, * pObjF;
+    int i, iObj;
+    // initialize constant, inputs, and flops in the first frame
+    Gia_ManConst0(p->pGia)->Value += s_256Primes[ISO_MASK];
+    Gia_ManForEachPi( p->pGia, pObj, i )
+        pObj->Value += s_256Primes[ISO_MASK-1];
+    if ( Iter == 0 )
+        Gia_ManForEachRo( p->pGia, pObj, i )
+            pObj->Value += s_256Primes[ISO_MASK-2];
+    // simulate nodes
+    Gia_ManForEachAnd( p->pGia, pObj, i )
+    {
+        pObj->Value += Gia_ObjFanin0(pObj)->Value + Gia_IsoUpdate(p, Iter, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj));
+        pObj->Value += Gia_ObjFanin1(pObj)->Value + Gia_IsoUpdate(p, Iter, Gia_ObjFaninId1(pObj, i), Gia_ObjFaninC1(pObj));
+    }
+    // simulate COs
+    Gia_ManForEachCo( p->pGia, pObj, i )
+    {
+        iObj = Gia_ObjId(p->pGia, pObj);
+        pObj->Value += Gia_ObjFanin0(pObj)->Value + Gia_IsoUpdate(p, Iter, Gia_ObjFaninId0(pObj, iObj), Gia_ObjFaninC0(pObj));
+    }
+    // transfer flop values
+    Gia_ManForEachRiRo( p->pGia, pObjF, pObj, i )
+        pObj->Value += pObjF->Value;
+}
+void Gia_IsoSimulateBack( Gia_IsoMan_t * p, int Iter )
+{
+    Gia_Obj_t * pObj, * pObjF;
+    int i, iObj;
+    // simulate COs
+    Gia_ManForEachCo( p->pGia, pObj, i )
+    {
+        iObj = Gia_ObjId(p->pGia, pObj);
+        Gia_ObjFanin0(pObj)->Value += pObj->Value + Gia_IsoUpdate(p, Iter, iObj, Gia_ObjFaninC0(pObj));
+    }
+    // simulate objects
+    Gia_ManForEachAndReverse( p->pGia, pObj, i )
+    {
+        Gia_ObjFanin0(pObj)->Value += pObj->Value + Gia_IsoUpdate(p, Iter, i, Gia_ObjFaninC0(pObj));
+        Gia_ObjFanin1(pObj)->Value += pObj->Value + Gia_IsoUpdate(p, Iter, i, Gia_ObjFaninC1(pObj));
+    }
+    // transfer flop values
+    Gia_ManForEachRiRo( p->pGia, pObjF, pObj, i )
+        pObjF->Value += pObj->Value;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_IsoAssignOneClass2( Gia_IsoMan_t * p )
+{
+    int i, iBegin = -1, nSize = -1;
+    // find two variable class
+    assert( Vec_IntSize(p->vClasses) > 0 );
+    Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i )
+    {
+        if ( nSize == 2 )
+            break;
+    }
+    assert( nSize > 1 );
+
+    if ( nSize == 2 )
+    {
+        assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 );
+        p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++;
+        p->nSingles++;
+        p->nEntries--;
+
+        assert( p->pUniques[Gia_IsoGetItem(p, iBegin+1)] == 0 );
+        p->pUniques[Gia_IsoGetItem(p, iBegin+1)] = p->nUniques++;
+        p->nSingles++;
+        p->nEntries--;
+    }
+    else
+    {
+        assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 );
+        p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++;
+        p->nSingles++;
+        p->nEntries--;
+    }
+
+    for ( ; i < Vec_IntSize(p->vClasses) - 2; i += 2 )
+    {
+        p->vClasses->pArray[i+0] = p->vClasses->pArray[i+2];
+        p->vClasses->pArray[i+1] = p->vClasses->pArray[i+3];
+    }
+    Vec_IntShrink( p->vClasses, Vec_IntSize(p->vClasses) - 2 );
+
+    printf( "Broke ties in class %d of size %d at level %d.\n", i/2, nSize, p->pLevels[Gia_IsoGetItem(p, iBegin)] );
+}
+
+void Gia_IsoAssignOneClass3( Gia_IsoMan_t * p )
+{
+    int iBegin, nSize;
+    // find the last class
+    assert( Vec_IntSize(p->vClasses) > 0 );
+    iBegin = Vec_IntEntry( p->vClasses, Vec_IntSize(p->vClasses) - 2 );
+    nSize  = Vec_IntEntry( p->vClasses, Vec_IntSize(p->vClasses) - 1 );
+    Vec_IntShrink( p->vClasses, Vec_IntSize(p->vClasses) - 2 );
+
+    // assign the class
+    assert( nSize > 1 );
+    if ( nSize == 2 )
+    {
+        assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 );
+        p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++;
+        p->nSingles++;
+        p->nEntries--;
+
+        assert( p->pUniques[Gia_IsoGetItem(p, iBegin+1)] == 0 );
+        p->pUniques[Gia_IsoGetItem(p, iBegin+1)] = p->nUniques++;
+        p->nSingles++;
+        p->nEntries--;
+    }
+    else
+    {
+        assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 );
+        p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++;
+        p->nSingles++;
+        p->nEntries--;
+    }
+    printf( "Broke ties in last class of size %d at level %d.\n", nSize, p->pLevels[Gia_IsoGetItem(p, iBegin)] );
+}
+
+void Gia_IsoAssignOneClass( Gia_IsoMan_t * p, int fVerbose )
+{
+    int i, k, iBegin0, iBegin, nSize, Shrink;
+    // find the classes with the highest level
+    assert( Vec_IntSize(p->vClasses) > 0 );
+    iBegin0 = Vec_IntEntry( p->vClasses, Vec_IntSize(p->vClasses) - 2 );
+    for ( i = Vec_IntSize(p->vClasses) - 2; i >= 0; i -= 2 )
+    {
+        iBegin = Vec_IntEntry( p->vClasses, i );
+        if ( p->pLevels[Gia_IsoGetItem(p, iBegin)] != p->pLevels[Gia_IsoGetItem(p, iBegin0)] )
+            break;
+    }
+    i += 2;
+    assert( i >= 0 );
+    // assign all classes starting with this one
+    for ( Shrink = i; i < Vec_IntSize(p->vClasses); i += 2 )
+    {
+        iBegin = Vec_IntEntry( p->vClasses, i );
+        nSize  = Vec_IntEntry( p->vClasses, i + 1 );
+        for ( k = 0; k < nSize; k++ )
+        {
+            assert( p->pUniques[Gia_IsoGetItem(p, iBegin+k)] == 0 );
+            p->pUniques[Gia_IsoGetItem(p, iBegin+k)] = p->nUniques++;
+//            Gia_ManObj(p->pGia, Gia_IsoGetItem(p, iBegin+k))->Value += s_256Primes[0]; ///  new addition!!!
+            p->nSingles++;
+            p->nEntries--;
+        }
+        if ( fVerbose )
+            printf( "Broke ties in class of size %d at level %d.\n", nSize, p->pLevels[Gia_IsoGetItem(p, iBegin)] );
+    }
+    Vec_IntShrink( p->vClasses, Shrink );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Report topmost equiv nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_IsoReportTopmost( Gia_IsoMan_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, k, iBegin, nSize, Counter = 0;
+    // go through equivalence classes
+    Gia_ManIncrementTravId( p->pGia );
+    Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i )
+    {
+//        printf( "%d(%d) ", nSize, p->pLevels[Gia_IsoGetItem(p, iBegin)] );
+        for ( k = 0; k < nSize; k++ )
+        {
+            pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p, iBegin+k) );
+            if ( Gia_ObjIsAnd(pObj) )
+            {
+                Gia_ObjSetTravIdCurrent( p->pGia, Gia_ObjFanin0(pObj) );
+                Gia_ObjSetTravIdCurrent( p->pGia, Gia_ObjFanin1(pObj) );
+            }
+            else if ( Gia_ObjIsRo(p->pGia, pObj) )
+                Gia_ObjSetTravIdCurrent( p->pGia, Gia_ObjFanin0(Gia_ObjRoToRi(p->pGia, pObj)) );
+        }
+    }
+//    printf( "\n" );
+
+    // report non-labeled nodes
+    Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i )
+    {
+        for ( k = 0; k < nSize; k++ )
+        {
+            pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p, iBegin+k) );
+            if ( !Gia_ObjIsTravIdCurrent(p->pGia, pObj) )
+            {
+                printf( "%5d : ", ++Counter );
+                printf( "Obj %6d : Level = %4d.  iBegin = %4d.  Size = %4d.\n", 
+                    Gia_ObjId(p->pGia, pObj), p->pLevels[Gia_ObjId(p->pGia, pObj)], iBegin, nSize );
+                break;
+            }
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_IsoRecognizeMuxes( Gia_Man_t * pGia )
+{
+    Gia_Obj_t * pObj, * pObjC, * pObj1, * pObj0;
+    int i;
+    Gia_ManForEachAnd( pGia, pObj, i )
+    {
+        if ( !Gia_ObjIsMuxType(pObj) )
+            continue;
+        pObjC = Gia_ObjRecognizeMux( pObj, &pObj1, &pObj0 );
+        if ( Gia_Regular(pObj0) == Gia_Regular(pObj1) )
+        {
+            // this is XOR
+            Gia_Regular(pObj)->Value += s_256Primes[233];
+            Gia_Regular(pObjC)->Value += s_256Primes[234];
+            Gia_Regular(pObj0)->Value += s_256Primes[234];
+        }
+        else
+        {
+            // this is MUX
+            Gia_Regular(pObj)->Value += s_256Primes[235];
+            Gia_Regular(pObjC)->Value += s_256Primes[236];
+            Gia_Regular(pObj0)->Value += s_256Primes[237];
+            Gia_Regular(pObj1)->Value += s_256Primes[237];
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Gia_IsoDeriveEquivPos( Gia_Man_t * pGia, int fForward, int fVerbose )
+{
+    int nIterMax = 10000;
+    int nFixedPoint = 1;
+    Gia_IsoMan_t * p;
+    Vec_Ptr_t * vEquivs = NULL;
+    int fRefined, fRefinedAll;
+    int i, c;
+    abctime clk = Abc_Clock(), clkTotal = Abc_Clock();
+    assert( Gia_ManCiNum(pGia) > 0 );
+    assert( Gia_ManPoNum(pGia) > 0 );
+
+    Gia_ManCleanValue( pGia );
+    p = Gia_IsoManStart( pGia );
+    Gia_IsoPrepare( p );
+    Gia_IsoAssignUnique( p );
+    p->timeStart = Abc_Clock() - clk;
+    if ( fVerbose )
+        Gia_IsoPrint( p, 0, Abc_Clock() - clkTotal );
+
+//    Gia_IsoRecognizeMuxes( pGia );
+
+    i = 0;
+    if ( fForward )
+    {
+        for ( c = 0; i < nIterMax && c < nFixedPoint+1; i++, c = fRefined ? 0 : c+1 )
+        {
+            clk = Abc_Clock();   Gia_IsoSimulate( p, i );      p->timeSim += Abc_Clock() - clk;
+            clk = Abc_Clock();   fRefined = Gia_IsoSort( p );  p->timeRefine += Abc_Clock() - clk;
+            if ( fVerbose )
+                Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal );
+        }
+    }
+    else
+    {
+        while ( Vec_IntSize(p->vClasses) > 0 )
+        {
+            for ( fRefinedAll = 1; i < nIterMax && fRefinedAll; )
+            {
+                fRefinedAll = 0;
+                for ( c = 0; i < nIterMax && c < nFixedPoint+1; i++, c = fRefined ? 0 : c+1 )
+                {
+                    clk = Abc_Clock();   Gia_IsoSimulate( p, i );      p->timeSim += Abc_Clock() - clk;
+                    clk = Abc_Clock();   fRefined = Gia_IsoSort( p );  p->timeRefine += Abc_Clock() - clk;
+                    if ( fVerbose )
+                        Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal );
+                    fRefinedAll |= fRefined;
+                }
+                for ( c = 0; i < nIterMax && c < nFixedPoint+1; i++, c = fRefined ? 0 : c+1 )
+                {
+                    clk = Abc_Clock();   Gia_IsoSimulateBack( p, i );  p->timeSim += Abc_Clock() - clk;
+                    clk = Abc_Clock();   fRefined = Gia_IsoSort( p );  p->timeRefine += Abc_Clock() - clk;
+                    if ( fVerbose )
+                        Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal );
+                    fRefinedAll |= fRefined;
+                }
+            }
+            if ( !fRefinedAll )
+                break;
+        }
+
+//        Gia_IsoReportTopmost( p );
+
+        while ( Vec_IntSize(p->vClasses) > 0 )
+        {
+            Gia_IsoAssignOneClass( p, fVerbose );
+            for ( fRefinedAll = 1; i < nIterMax && fRefinedAll; )
+            {
+                fRefinedAll = 0;
+                for ( c = 0; i < nIterMax && c < nFixedPoint; i++, c = fRefined ? 0 : c+1 )
+                {
+                    clk = Abc_Clock();   Gia_IsoSimulateBack( p, i );  p->timeSim += Abc_Clock() - clk;
+                    clk = Abc_Clock();   fRefined = Gia_IsoSort( p );  p->timeRefine += Abc_Clock() - clk;
+                    if ( fVerbose )
+                        Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal );
+                    fRefinedAll |= fRefined;
+                }
+                for ( c = 0; i < nIterMax && c < nFixedPoint; i++, c = fRefined ? 0 : c+1 )
+                {
+                    clk = Abc_Clock();   Gia_IsoSimulate( p, i );      p->timeSim += Abc_Clock() - clk;
+                    clk = Abc_Clock();   fRefined = Gia_IsoSort( p );  p->timeRefine += Abc_Clock() - clk;
+                    if ( fVerbose )
+                        Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal );
+                    fRefinedAll |= fRefined;
+//                    if ( fRefined )
+//                        printf( "Refinedment happened.\n" );
+                }
+            }
+        }
+
+        if ( fVerbose )
+            Gia_IsoPrint( p, i+2, Abc_Clock() - clkTotal );
+    }
+//    Gia_IsoPrintClasses( p );
+    if ( fVerbose )
+    {
+        p->timeTotal = Abc_Clock() - clkTotal;
+        p->timeOther = p->timeTotal - p->timeStart - p->timeSim - p->timeRefine;
+        ABC_PRTP( "Start    ", p->timeStart,              p->timeTotal );
+        ABC_PRTP( "Simulate ", p->timeSim,                p->timeTotal );
+        ABC_PRTP( "Refine   ", p->timeRefine-p->timeSort, p->timeTotal );
+        ABC_PRTP( "Sort     ", p->timeSort,               p->timeTotal );
+        ABC_PRTP( "Other    ", p->timeOther,              p->timeTotal );
+        ABC_PRTP( "TOTAL    ", p->timeTotal,              p->timeTotal );
+    }
+
+    if ( Gia_ManPoNum(p->pGia) > 1 )
+        vEquivs = Gia_IsoCollectCosClasses( p, fVerbose );
+    Gia_IsoManTransferUnique( p );
+    Gia_IsoManStop( p );
+
+    return vEquivs;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds canonical ordering of CIs/COs/nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ObjCompareByValue( Gia_Obj_t ** pp1, Gia_Obj_t ** pp2 )
+{
+    Gia_Obj_t * pObj1 = *pp1;
+    Gia_Obj_t * pObj2 = *pp2;
+//    assert( pObj1->Value != pObj2->Value );
+    return (int)pObj1->Value - (int)pObj2->Value;
+}
+void Gia_ManFindCaninicalOrder_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vAnds )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    assert( Gia_ObjIsAnd(pObj) );
+    if ( !Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) || !Gia_ObjIsAnd(Gia_ObjFanin1(pObj)) )
+    {
+        Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin0(pObj), vAnds );
+        Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin1(pObj), vAnds );
+    }
+    else
+    {
+        assert( Gia_ObjFanin0(pObj)->Value != Gia_ObjFanin1(pObj)->Value );
+        if ( Gia_ObjFanin0(pObj)->Value < Gia_ObjFanin1(pObj)->Value )
+        {
+            Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin0(pObj), vAnds );
+            Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin1(pObj), vAnds );
+        }
+        else
+        {
+            Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin1(pObj), vAnds );
+            Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin0(pObj), vAnds );
+        }
+    }
+    Vec_IntPush( vAnds, Gia_ObjId(p, pObj) );
+}
+void Gia_ManFindCaninicalOrder( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, Vec_Int_t ** pvPiPerm )
+{
+    Vec_Ptr_t * vTemp;
+    Gia_Obj_t * pObj;
+    int i;
+
+    vTemp = Vec_PtrAlloc( 1000 );
+    Vec_IntClear( vCis );
+    Vec_IntClear( vAnds );
+    Vec_IntClear( vCos );
+
+    // assign unique IDs to PIs
+    Vec_PtrClear( vTemp );
+    Gia_ManForEachPi( p, pObj, i )
+        Vec_PtrPush( vTemp, pObj );
+    Vec_PtrSort( vTemp, (int (*)(void))Gia_ObjCompareByValue );
+    // create the result
+    Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i )
+        Vec_IntPush( vCis, Gia_ObjId(p, pObj) );
+    // remember PI permutation
+    if ( pvPiPerm ) 
+    {
+        *pvPiPerm = Vec_IntAlloc( Gia_ManPiNum(p) );
+        Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i )
+            Vec_IntPush( *pvPiPerm, Gia_ObjCioId(pObj) );
+    }
+
+    // assign unique IDs to POs
+    if ( Gia_ManPoNum(p) == 1 )
+        Vec_IntPush( vCos, Gia_ObjId(p, Gia_ManPo(p, 0)) );
+    else
+    {
+        Vec_PtrClear( vTemp );
+        Gia_ManForEachPo( p, pObj, i )
+        {
+            pObj->Value = Abc_Var2Lit( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) );
+            Vec_PtrPush( vTemp, pObj );
+        }
+        Vec_PtrSort( vTemp, (int (*)(void))Gia_ObjCompareByValue );
+        Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i )
+            Vec_IntPush( vCos, Gia_ObjId(p, pObj) );
+    }
+
+    // assign unique IDs to ROs
+    Vec_PtrClear( vTemp );
+    Gia_ManForEachRo( p, pObj, i )
+        Vec_PtrPush( vTemp, pObj );
+    Vec_PtrSort( vTemp, (int (*)(void))Gia_ObjCompareByValue );
+    // create the result
+    Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i )
+    {
+        Vec_IntPush( vCis, Gia_ObjId(p, pObj) );
+        Vec_IntPush( vCos, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) );
+    }
+    Vec_PtrFree( vTemp );
+
+    // assign unique IDs to internal nodes
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+    Gia_ManForEachObjVec( vCis, p, pObj, i )
+        Gia_ObjSetTravIdCurrent( p, pObj );
+    Gia_ManForEachObjVec( vCos, p, pObj, i )
+        Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin0(pObj), vAnds );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManIsoCanonicize( Gia_Man_t * p, int fVerbose )
+{
+    Gia_Man_t * pRes = NULL;
+    Vec_Int_t * vCis, * vAnds, * vCos;
+    Vec_Ptr_t * vEquiv;
+    if ( Gia_ManCiNum(p) == 0 ) // const AIG
+    {
+        assert( Gia_ManPoNum(p) == 1 );
+        assert( Gia_ManObjNum(p) == 2 );
+        return Gia_ManDup(p);
+    }
+    // derive canonical values
+    vEquiv = Gia_IsoDeriveEquivPos( p, 0, fVerbose );
+    Vec_VecFreeP( (Vec_Vec_t **)&vEquiv );
+    // find canonical order of CIs/COs/nodes
+    // find canonical order
+    vCis  = Vec_IntAlloc( Gia_ManCiNum(p) );
+    vAnds = Vec_IntAlloc( Gia_ManAndNum(p) );
+    vCos  = Vec_IntAlloc( Gia_ManCoNum(p) );
+    Gia_ManFindCaninicalOrder( p, vCis, vAnds, vCos, NULL );
+    // derive the new AIG
+    pRes = Gia_ManDupFromVecs( p, vCis, vAnds, vCos, Gia_ManRegNum(p) );
+    // cleanup
+    Vec_IntFree( vCis );
+    Vec_IntFree( vAnds );
+    Vec_IntFree( vCos );
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Gia_ManIsoFindString( Gia_Man_t * p, int iPo, int fVerbose, Vec_Int_t ** pvPiPerm )
+{
+    Gia_Man_t * pPart;
+    Vec_Ptr_t * vEquiv;
+    Vec_Int_t * vCis, * vAnds, * vCos;
+    Vec_Str_t * vStr;
+    // duplicate
+    pPart = Gia_ManDupCones( p, &iPo, 1, 1 );
+//Gia_ManPrint( pPart );
+    assert( Gia_ManPoNum(pPart) == 1 );
+    if ( Gia_ManCiNum(pPart) == 0 ) // const AIG
+    {
+        assert( Gia_ManPoNum(pPart) == 1 );
+        assert( Gia_ManObjNum(pPart) == 2 );
+        vStr = Gia_AigerWriteIntoMemoryStr( pPart );
+        Gia_ManStop( pPart );
+        if ( pvPiPerm )
+            *pvPiPerm = Vec_IntAlloc( 0 );
+        return vStr;
+    }
+    // derive canonical values
+    vEquiv = Gia_IsoDeriveEquivPos( pPart, 0, fVerbose );
+    Vec_VecFreeP( (Vec_Vec_t **)&vEquiv );
+    // find canonical order
+    vCis  = Vec_IntAlloc( Gia_ManCiNum(pPart) );
+    vAnds = Vec_IntAlloc( Gia_ManAndNum(pPart) );
+    vCos  = Vec_IntAlloc( Gia_ManCoNum(pPart) );
+    Gia_ManFindCaninicalOrder( pPart, vCis, vAnds, vCos, pvPiPerm );
+//printf( "Internal: " );
+//Vec_IntPrint( vCis );
+    // derive the AIGER string
+    vStr = Gia_AigerWriteIntoMemoryStrPart( pPart, vCis, vAnds, vCos, Gia_ManRegNum(pPart) );
+    // cleanup
+    Vec_IntFree( vCis );
+    Vec_IntFree( vAnds );
+    Vec_IntFree( vCos );
+    Gia_ManStop( pPart );
+    return vStr;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Vec_IntCountNonTrivial( Vec_Ptr_t * vEquivs, int * pnUsed )
+{
+    Vec_Int_t * vClass;
+    int i, nClasses = 0;
+    *pnUsed = 0;
+    Vec_PtrForEachEntry( Vec_Int_t *, vEquivs, vClass, i )
+    {
+        if ( Vec_IntSize(vClass) < 2 )
+            continue;
+        nClasses++;
+        (*pnUsed) += Vec_IntSize(vClass);
+    }
+    return nClasses;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManIsoReduce( Gia_Man_t * pInit, Vec_Ptr_t ** pvPosEquivs, Vec_Ptr_t ** pvPiPerms, int fEstimate, int fDualOut, int fVerbose, int fVeryVerbose )
+{ 
+    Gia_Man_t * p, * pPart;
+    Vec_Ptr_t * vEquivs, * vEquivs2, * vStrings;
+    Vec_Int_t * vRemain, * vLevel, * vLevel2;
+    Vec_Str_t * vStr, * vStr2;
+    int i, k, s, sStart, iPo, Counter;
+    int nClasses, nUsedPos;
+    abctime clk = Abc_Clock();
+    if ( pvPosEquivs )
+        *pvPosEquivs = NULL;
+    if ( pvPiPerms )
+        *pvPiPerms = Vec_PtrStart( Gia_ManPoNum(pInit) );
+
+    if ( fDualOut )
+    {
+        assert( (Gia_ManPoNum(pInit) & 1) == 0 );
+        if ( Gia_ManPoNum(pInit) == 2 )
+            return Gia_ManDup(pInit);
+        p = Gia_ManTransformMiter( pInit );
+        p = Gia_ManSeqStructSweep( pPart = p, 1, 1, 0 );
+        Gia_ManStop( pPart );
+    }
+    else
+    {
+        if ( Gia_ManPoNum(pInit) == 1 )
+            return Gia_ManDup(pInit);
+        p = pInit;
+    }
+
+    // create preliminary equivalences
+    vEquivs = Gia_IsoDeriveEquivPos( p, 1, fVeryVerbose );
+    if ( vEquivs == NULL )
+    {
+        if ( fDualOut )
+            Gia_ManStop( p );
+        return NULL;
+    }
+    nClasses = Vec_IntCountNonTrivial( vEquivs, &nUsedPos );
+    printf( "Reduced %d outputs to %d candidate   classes (%d outputs are in %d non-trivial classes).  ", 
+        Gia_ManPoNum(p), Vec_PtrSize(vEquivs), nUsedPos, nClasses );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    if ( fEstimate )
+    {
+        Vec_VecFree( (Vec_Vec_t *)vEquivs );
+        return Gia_ManDup(pInit);
+    }
+
+    // perform refinement of equivalence classes
+    Counter = 0;
+    vEquivs2 = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Vec_Int_t *, vEquivs, vLevel, i )
+    {
+        if ( Vec_IntSize(vLevel) < 2 )
+        {
+            Vec_PtrPush( vEquivs2, Vec_IntDup(vLevel) );
+            for ( k = 0; k < Vec_IntSize(vLevel); k++ )
+                if ( ++Counter % 100 == 0 )
+                    printf( "%6d finished...\r", Counter );
+            continue;
+        }
+
+        if ( fVerbose )
+        {
+            iPo = Vec_IntEntry(vLevel, 0);
+            printf( "%6d %6d %6d : ", i, Vec_IntSize(vLevel), iPo );
+            pPart = Gia_ManDupCones( p, &iPo, 1, 1 );
+            Gia_ManPrintStats(pPart, NULL);
+            Gia_ManStop( pPart );
+        }
+
+        sStart = Vec_PtrSize( vEquivs2 ); 
+        vStrings = Vec_PtrAlloc( 100 );
+        Vec_IntForEachEntry( vLevel, iPo, k )
+        {
+            if ( ++Counter % 100 == 0 )
+                printf( "%6d finished...\r", Counter );
+            assert( pvPiPerms == NULL || Vec_PtrArray(*pvPiPerms)[iPo] == NULL );
+            vStr = Gia_ManIsoFindString( p, iPo, 0, pvPiPerms ? (Vec_Int_t **)Vec_PtrArray(*pvPiPerms) + iPo : NULL );
+
+//            printf( "Output %2d : ", iPo );
+//            Vec_IntPrint( Vec_PtrArray(*pvPiPerms)[iPo] );
+
+            // check if this string already exists
+            Vec_PtrForEachEntry( Vec_Str_t *, vStrings, vStr2, s )
+                if ( Vec_StrCompareVec(vStr, vStr2) == 0 )
+                    break;
+            if ( s == Vec_PtrSize(vStrings) )
+            {
+                Vec_PtrPush( vStrings, vStr );
+                Vec_PtrPush( vEquivs2, Vec_IntAlloc(8) );
+            }
+            else
+                Vec_StrFree( vStr );
+            // add this entry to the corresponding level
+            vLevel2 = (Vec_Int_t *)Vec_PtrEntry( vEquivs2, sStart + s );
+            Vec_IntPush( vLevel2, iPo );
+        }
+//        if ( Vec_PtrSize(vEquivs2) - sStart > 1 )
+//            printf( "Refined class %d into %d classes.\n", i, Vec_PtrSize(vEquivs2) - sStart );
+        Vec_VecFree( (Vec_Vec_t *)vStrings );
+    }
+    assert( Counter == Gia_ManPoNum(p) );
+    Vec_VecSortByFirstInt( (Vec_Vec_t *)vEquivs2, 0 );
+    Vec_VecFree( (Vec_Vec_t *)vEquivs );
+    vEquivs = vEquivs2;
+
+    // collect the first ones
+    vRemain = Vec_IntAlloc( 100 );
+    Vec_PtrForEachEntry( Vec_Int_t *, vEquivs, vLevel, i )
+        Vec_IntPush( vRemain, Vec_IntEntry(vLevel, 0) );
+
+    if ( fDualOut )
+    {
+        Vec_Int_t * vTemp = Vec_IntAlloc( Vec_IntSize(vRemain) );
+        int i, Entry;
+        Vec_IntForEachEntry( vRemain, Entry, i )
+        {
+//            printf( "%d ", Entry );
+            Vec_IntPush( vTemp, 2*Entry );
+            Vec_IntPush( vTemp, 2*Entry+1 );
+        }
+//        printf( "\n" );
+        Vec_IntFree( vRemain );
+        vRemain = vTemp;
+        Gia_ManStop( p );
+        p = pInit;
+    }
+
+
+    // derive the resulting AIG
+    pPart = Gia_ManDupCones( p, Vec_IntArray(vRemain), Vec_IntSize(vRemain), 0 );
+    Vec_IntFree( vRemain );
+    // report the results
+    nClasses = Vec_IntCountNonTrivial( vEquivs, &nUsedPos );
+    if ( !fDualOut )
+        printf( "Reduced %d outputs to %d equivalence classes (%d outputs are in %d non-trivial classes).  ", 
+            Gia_ManPoNum(p), Vec_PtrSize(vEquivs), nUsedPos, nClasses );
+    else
+        printf( "Reduced %d dual outputs to %d dual outputs.  ", Gia_ManPoNum(p)/2, Gia_ManPoNum(pPart)/2 );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    if ( fVerbose )
+    {
+        printf( "Nontrivial classes:\n" );
+        Vec_VecPrintInt( (Vec_Vec_t *)vEquivs, 1 );
+    }
+    if ( pvPosEquivs )
+        *pvPosEquivs = vEquivs;
+    else
+        Vec_VecFree( (Vec_Vec_t *)vEquivs );
+//    Gia_ManStopP( &pPart );
+    return pPart;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_IsoTestOld( Gia_Man_t * p, int fVerbose )
+{
+    Vec_Ptr_t * vEquivs;
+    abctime clk = Abc_Clock(); 
+    vEquivs = Gia_IsoDeriveEquivPos( p, 0, fVerbose );
+    printf( "Reduced %d outputs to %d.  ", Gia_ManPoNum(p), vEquivs ? Vec_PtrSize(vEquivs) : 1 );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    if ( fVerbose && vEquivs && Gia_ManPoNum(p) != Vec_PtrSize(vEquivs) )
+    {
+        printf( "Nontrivial classes:\n" );
+//        Vec_VecPrintInt( (Vec_Vec_t *)vEquivs, 1 );
+    }
+    Vec_VecFreeP( (Vec_Vec_t **)&vEquivs );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Test remapping of CEXes for isomorphic POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_IsoTestGenPerm( int nPis )
+{
+    Vec_Int_t * vPerm;
+    int i, * pArray;
+    vPerm = Vec_IntStartNatural( nPis );
+    pArray = Vec_IntArray( vPerm );
+    for ( i = 0; i < nPis; i++ )
+    {
+        int iNew = rand() % nPis;
+        ABC_SWAP( int, pArray[i], pArray[iNew] );
+    }
+    return vPerm;
+}
+void Gia_IsoTest( Gia_Man_t * p, Abc_Cex_t * pCex, int fVerbose )
+{
+    Abc_Cex_t * pCexNew;
+    Vec_Int_t * vPiPerm;
+    Vec_Ptr_t * vPosEquivs, * vPisPerm;
+    Vec_Int_t * vPerm0, * vPerm1;
+    Gia_Man_t * pPerm, * pDouble, * pAig;
+    assert( Gia_ManPoNum(p) == 1 );
+    assert( Gia_ManRegNum(p) > 0 );
+    // generate random permutation of PIs
+    vPiPerm = Gia_IsoTestGenPerm( Gia_ManPiNum(p) );
+    printf( "Considering random permutation of the primary inputs of the AIG:\n" );
+    Vec_IntPrint( vPiPerm );
+    // create AIG with two primary outputs (original and permuted)
+    pPerm = Gia_ManDupPerm( p, vPiPerm );
+    pDouble = Gia_ManDupAppendNew( p, pPerm );
+//Gia_AigerWrite( pDouble, "test.aig", 0, 0 );
+
+    // analyze the two-output miter
+    pAig = Gia_ManIsoReduce( pDouble, &vPosEquivs, &vPisPerm, 0, 0, 0, 0 );
+    Vec_VecFree( (Vec_Vec_t *)vPosEquivs );
+
+    // given CEX for output 0, derive CEX for output 1
+    vPerm0 = (Vec_Int_t *)Vec_PtrEntry( vPisPerm, 0 );
+    vPerm1 = (Vec_Int_t *)Vec_PtrEntry( vPisPerm, 1 );
+    pCexNew = Abc_CexPermuteTwo( pCex, vPerm0, vPerm1 );
+    Vec_VecFree( (Vec_Vec_t *)vPisPerm );
+
+    // check that original CEX and the resulting CEX is valid
+    if ( Gia_ManVerifyCex(p, pCex, 0) )
+        printf( "CEX for the init AIG is valid.\n" );
+    else
+        printf( "CEX for the init AIG is not valid.\n" );
+    if ( Gia_ManVerifyCex(pPerm, pCexNew, 0) )
+        printf( "CEX for the perm AIG is valid.\n" );
+    else
+        printf( "CEX for the perm AIG is not valid.\n" );
+    // delete
+    Gia_ManStop( pAig );
+    Gia_ManStop( pDouble );
+    Gia_ManStop( pPerm );
+    Vec_IntFree( vPiPerm );
+    Abc_CexFree( pCexNew );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaIso2.c b/abc-build/src/aig/gia/giaIso2.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaIso2.c
@@ -0,0 +1,776 @@
+/**CFile****************************************************************
+
+  FileName    [gia.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/vec/vecHsh.h"
+#include "misc/vec/vecWec.h"
+
+
+ABC_NAMESPACE_IMPL_START
+
+
+#define ISO_MASK 0xFF
+static int s_256Primes[ISO_MASK+1] = 
+{
+    0x984b6ad9,0x18a6eed3,0x950353e2,0x6222f6eb,0xdfbedd47,0xef0f9023,0xac932a26,0x590eaf55,
+    0x97d0a034,0xdc36cd2e,0x22736b37,0xdc9066b0,0x2eb2f98b,0x5d9c7baf,0x85747c9e,0x8aca1055,
+    0x50d66b74,0x2f01ae9e,0xa1a80123,0x3e1ce2dc,0xebedbc57,0x4e68bc34,0x855ee0cf,0x17275120,
+    0x2ae7f2df,0xf71039eb,0x7c283eec,0x70cd1137,0x7cf651f3,0xa87bfa7a,0x14d87f02,0xe82e197d,
+    0x8d8a5ebe,0x1e6a15dc,0x197d49db,0x5bab9c89,0x4b55dea7,0x55dede49,0x9a6a8080,0xe5e51035,
+    0xe148d658,0x8a17eb3b,0xe22e4b38,0xe5be2a9a,0xbe938cbb,0x3b981069,0x7f9c0c8e,0xf756df10,
+    0x8fa783f7,0x252062ce,0x3dc46b4b,0xf70f6432,0x3f378276,0x44b137a1,0x2bf74b77,0x04892ed6,
+    0xfd318de1,0xd58c235e,0x94c6d25b,0x7aa5f218,0x35c9e921,0x5732fbbb,0x06026481,0xf584a44f,
+    0x946e1b5f,0x8463d5b2,0x4ebca7b2,0x54887b15,0x08d1e804,0x5b22067d,0x794580f6,0xb351ea43,
+    0xbce555b9,0x19ae2194,0xd32f1396,0x6fc1a7f1,0x1fd8a867,0x3a89fdb0,0xea49c61c,0x25f8a879,
+    0xde1e6437,0x7c74afca,0x8ba63e50,0xb1572074,0xe4655092,0xdb6f8b1c,0xc2955f3c,0x327f85ba,
+    0x60a17021,0x95bd261d,0xdea94f28,0x04528b65,0xbe0109cc,0x26dd5688,0x6ab2729d,0xc4f029ce,
+    0xacf7a0be,0x4c912f55,0x34c06e65,0x4fbb938e,0x1533fb5f,0x03da06bd,0x48262889,0xc2523d7d,
+    0x28a71d57,0x89f9713a,0xf574c551,0x7a99deb5,0x52834d91,0x5a6f4484,0xc67ba946,0x13ae698f,
+    0x3e390f34,0x34fc9593,0x894c7932,0x6cf414a3,0xdb7928ab,0x13a3b8a3,0x4b381c1d,0xa10b54cb,
+    0x55359d9d,0x35a3422a,0x58d1b551,0x0fd4de20,0x199eb3f4,0x167e09e2,0x3ee6a956,0x5371a7fa,
+    0xd424efda,0x74f521c5,0xcb899ff6,0x4a42e4f4,0x747917b6,0x4b08df0b,0x090c7a39,0x11e909e4,
+    0x258e2e32,0xd9fad92d,0x48fe5f69,0x0545cde6,0x55937b37,0x9b4ae4e4,0x1332b40e,0xc3792351,
+    0xaff982ef,0x4dba132a,0x38b81ef1,0x28e641bf,0x227208c1,0xec4bbe37,0xc4e1821c,0x512c9d09,
+    0xdaef1257,0xb63e7784,0x043e04d7,0x9c2cea47,0x45a0e59a,0x281315ca,0x849f0aac,0xa4071ed3,
+    0x0ef707b3,0xfe8dac02,0x12173864,0x471f6d46,0x24a53c0a,0x35ab9265,0xbbf77406,0xa2144e79,
+    0xb39a884a,0x0baf5b6d,0xcccee3dd,0x12c77584,0x2907325b,0xfd1adcd2,0xd16ee972,0x345ad6c1,
+    0x315ebe66,0xc7ad2b8d,0x99e82c8d,0xe52da8c8,0xba50f1d3,0x66689cd8,0x2e8e9138,0x43e15e74,
+    0xf1ced14d,0x188ec52a,0xe0ef3cbb,0xa958aedc,0x4107a1bc,0x5a9e7a3e,0x3bde939f,0xb5b28d5a,
+    0x596fe848,0xe85ad00c,0x0b6b3aae,0x44503086,0x25b5695c,0xc0c31dcd,0x5ee617f0,0x74d40c3a,
+    0xd2cb2b9f,0x1e19f5fa,0x81e24faf,0xa01ed68f,0xcee172fc,0x7fdf2e4d,0x002f4774,0x664f82dd,
+    0xc569c39a,0xa2d4dcbe,0xaadea306,0xa4c947bf,0xa413e4e3,0x81fb5486,0x8a404970,0x752c980c,
+    0x98d1d881,0x5c932c1e,0xeee65dfb,0x37592cdd,0x0fd4e65b,0xad1d383f,0x62a1452f,0x8872f68d,
+    0xb58c919b,0x345c8ee3,0xb583a6d6,0x43d72cb3,0x77aaa0aa,0xeb508242,0xf2db64f8,0x86294328,
+    0x82211731,0x1239a9d5,0x673ba5de,0xaf4af007,0x44203b19,0x2399d955,0xa175cd12,0x595928a7,
+    0x6918928b,0xde3126bb,0x6c99835c,0x63ba1fa2,0xdebbdff0,0x3d02e541,0xd6f7aac6,0xe80b4cd0,
+    0xd0fa29f1,0x804cac5e,0x2c226798,0x462f624c,0xad05b377,0x22924fcd,0xfbea205c,0x1b47586d
+};
+
+static int s_PrimeC = 49;
+//static int s_PrimeC = 1;
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Gia_Iso2Man_t_       Gia_Iso2Man_t;
+struct Gia_Iso2Man_t_ 
+{
+    Gia_Man_t *      pGia;
+    int              nObjs;
+    int              nUniques;
+    // internal data
+    Vec_Int_t *      vUniques;      // unique numbers
+    Vec_Int_t *      vTied;         // tied objects   
+    Vec_Int_t *      vTable;        // hash table
+    Vec_Int_t *      vPlaces;       // used places in the table
+    Vec_Ptr_t *      vSingles;      // singleton objects
+    // isomorphism check
+    Vec_Int_t *      vVec0;         // isomorphism map
+    Vec_Int_t *      vVec1;         // isomorphism map
+    Vec_Int_t *      vMap0;         // isomorphism map
+    Vec_Int_t *      vMap1;         // isomorphism map
+    // statistics 
+    int              nIters;
+    abctime          timeStart;
+    abctime          timeSim;
+    abctime          timeRefine;
+    abctime          timeSort;
+    abctime          timeOther;
+    abctime          timeTotal;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_Iso2ManCollectTies( Gia_Man_t * p )
+{
+    Vec_Int_t * vTies;
+    Gia_Obj_t * pObj;
+    int i;
+    vTies = Vec_IntAlloc( Gia_ManCandNum(p) );
+    Gia_ManForEachCand( p, pObj, i )
+        Vec_IntPush( vTies, i );
+    return vTies;
+}
+void Gia_Iso2ManPrepare( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+        pObj->Value = Gia_ObjIsAnd(pObj) ? 1 + Abc_MaxInt(Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value) : 0;
+    Gia_ManConst0(p)->Value = s_256Primes[ISO_MASK];
+    Gia_ManForEachObj1( p, pObj, i )
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = s_256Primes[pObj->Value & ISO_MASK] + s_256Primes[ISO_MASK - 10 + Gia_ObjFaninC0(pObj) + Gia_ObjFaninC1(pObj)];
+        else if ( Gia_ObjIsPi(p, pObj) )
+            pObj->Value = s_256Primes[ISO_MASK-1];
+        else if ( Gia_ObjIsRo(p, pObj) )
+            pObj->Value = s_256Primes[ISO_MASK-2];
+}
+void Gia_Iso2ManPropagate( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pObjRo;
+    int i;
+    Gia_ManForEachObj1( p, pObj, i )
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            pObj->Value += (Gia_ObjFaninC0(pObj) + s_PrimeC) * Gia_ObjFanin0(pObj)->Value + (Gia_ObjFaninC1(pObj) + s_PrimeC) * Gia_ObjFanin1(pObj)->Value;
+            if ( Gia_ObjFaninC0(pObj) == Gia_ObjFaninC1(pObj) && Gia_ObjFanin0(pObj)->Value == Gia_ObjFanin1(pObj)->Value )
+                pObj->Value += s_256Primes[ISO_MASK - 11];
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value += (Gia_ObjFaninC0(pObj) + s_PrimeC) * Gia_ObjFanin0(pObj)->Value;
+    Gia_ManForEachRiRo( p, pObj, pObjRo, i )
+    {
+        pObjRo->Value += pObj->Value;
+        if ( pObjRo == Gia_ObjFanin0(pObj) )
+            pObjRo->Value += s_256Primes[ISO_MASK - 12];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Gia_Iso2ManCone_rec( Gia_Man_t * p, int Id, int Level )
+{
+    Gia_Obj_t * pObj;
+    if ( Level == 0 )
+        return 0;
+    if ( Gia_ObjIsTravIdCurrentId(p, Id) )
+        return 0;
+    Gia_ObjSetTravIdCurrentId(p, Id);
+    pObj = Gia_ManObj( p, Id );
+    if ( Gia_ObjIsAnd(pObj) )
+        return pObj->Value + Gia_Iso2ManCone_rec( p, Gia_ObjFaninId0(pObj, Id), Level-1 ) + Gia_Iso2ManCone_rec( p, Gia_ObjFaninId1(pObj, Id), Level-1 );
+    if ( Gia_ObjIsPi(p, pObj) )
+        return pObj->Value;
+    if ( Gia_ObjIsRo(p, pObj) )
+        return pObj->Value + Gia_Iso2ManCone_rec( p, Gia_ObjId(p, Gia_ObjFanin0(Gia_ObjRoToRi(p, pObj))), Level );
+    assert( Gia_ObjIsConst0(pObj) );
+    return pObj->Value;
+}
+unsigned Gia_Iso2ManCone( Gia_Man_t * p, int Id, int Level )
+{
+    Gia_ManIncrementTravId( p );
+    return Gia_Iso2ManCone_rec( p, Id, Level );
+}
+void Gia_Iso2ManUpdate( Gia_Iso2Man_t * p, int Level )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i )
+        pObj->Value += Gia_Iso2ManCone( p->pGia, Gia_ObjId(p->pGia, pObj), Level );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Iso2Man_t * Gia_Iso2ManStart( Gia_Man_t * pGia )
+{
+    Gia_Iso2Man_t * p;
+    p = ABC_CALLOC( Gia_Iso2Man_t, 1 );
+    p->pGia      = pGia;
+    p->nObjs     = Gia_ManObjNum( pGia );
+    p->nUniques  = 0;
+    // internal data
+    p->vUniques  = Vec_IntStartFull( p->nObjs );
+    p->vTied     = Gia_Iso2ManCollectTies( pGia );
+    p->vTable    = Vec_IntStart( Abc_PrimeCudd(1*p->nObjs) );
+    p->vPlaces   = Vec_IntAlloc( 1000 );
+    p->vSingles  = Vec_PtrAlloc( 1000 );
+    p->vVec0     = Vec_IntAlloc( 10000 );
+    p->vVec1     = Vec_IntAlloc( 10000 );
+    p->vMap0     = Vec_IntStart( p->nObjs );
+    p->vMap1     = Vec_IntStart( p->nObjs );
+    // add constant 0 object
+    Vec_IntWriteEntry( p->vUniques, 0, p->nUniques++ );
+    return p;
+}
+void Gia_Iso2ManStop( Gia_Iso2Man_t * p )
+{
+    Vec_IntFree( p->vUniques );
+    Vec_IntFree( p->vTied );
+    Vec_IntFree( p->vTable );
+    Vec_IntFree( p->vPlaces );
+    Vec_PtrFree( p->vSingles );
+    Vec_IntFree( p->vMap0 );
+    Vec_IntFree( p->vMap1 );
+    Vec_IntFree( p->vVec0 );
+    Vec_IntFree( p->vVec1 );
+    ABC_FREE( p );
+}
+void Gia_Iso2ManPrint( Gia_Iso2Man_t * p, abctime Time, int fVerbose )
+{
+    if ( !fVerbose )
+        return;
+    printf( "Iter %4d :  ", p->nIters++ );
+    printf( "Entries =%8d.  ", Vec_IntSize(p->vTied) );
+    printf( "Uniques =%8d.  ", p->nUniques );
+    printf( "Singles =%8d.  ", Vec_PtrSize(p->vSingles) );
+    printf( "%9.2f sec", (float)(Time)/(float)(CLOCKS_PER_SEC) );
+    printf( "\n" );
+    fflush( stdout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Uniqifies objects using their signature.]
+
+  Description [Assumes the tied objects are in p->vTied. Assumes that 
+  updated signature (pObj->Value) is assigned to these objects. Returns 
+  the array of unique objects p->vSingles sorted by signature.  Compacts 
+  the array of tied objects p->vTied.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ObjCompareByValue2( Gia_Obj_t ** pp1, Gia_Obj_t ** pp2 ) { return (int)(*pp1)->Value - (int)(*pp2)->Value; }
+int Gia_Iso2ManUniqify( Gia_Iso2Man_t * p )
+{
+    int fVerify = 0;
+    Gia_Obj_t * pObj, * pTemp;
+    int * pTable = Vec_IntArray(p->vTable);
+    int i, k, nSize = Vec_IntSize(p->vTable);
+
+    if ( fVerify )
+        for ( k = 0; k < nSize; k++ )
+            assert( pTable[k] == 0 );
+    if ( fVerify )
+        Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i )
+            assert( pObj->fMark0 == 0 );
+
+#if 0
+    Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i )
+    {
+        printf( "%3d : ", Gia_ObjId(p->pGia, pObj) );
+        Extra_PrintBinary( stdout, &pObj->Value, 32 );
+        printf( "\n" );
+    }
+#endif
+
+    // add objects to the table
+    Vec_IntClear( p->vPlaces );
+    Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i )
+    {
+        for ( k = pObj->Value % nSize; (pTemp = pTable[k] ? Gia_ManObj(p->pGia, pTable[k]) : NULL); k = (k + 1) % nSize )
+            if ( pTemp->Value == pObj->Value )
+            {
+                pTemp->fMark0 = 1;
+                pObj->fMark0 = 1;
+                break;
+            }
+        if ( pTemp != NULL )
+            continue;
+        pTable[k] = Gia_ObjId(p->pGia, pObj);
+        Vec_IntPush( p->vPlaces, k );
+    }
+    // clean the table
+    Vec_IntForEachEntry( p->vPlaces, k, i )
+        pTable[k] = 0;
+    // collect singleton objects and compact tied objects
+    k = 0;
+    Vec_PtrClear( p->vSingles );
+    Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i )
+        if ( pObj->fMark0 == 0 )
+            Vec_PtrPush( p->vSingles, pObj );
+        else 
+        {
+            pObj->fMark0 = 0;
+            Vec_IntWriteEntry( p->vTied, k++, Gia_ObjId(p->pGia, pObj) );
+        }
+    Vec_IntShrink( p->vTied, k );
+    // sort singletons
+    Vec_PtrSort( p->vSingles, (int (*)(void))Gia_ObjCompareByValue2 );
+    // add them to unique and increment signature
+    Vec_PtrForEachEntry( Gia_Obj_t *, p->vSingles, pObj, i )
+    {
+        pObj->Value += s_256Primes[p->nUniques & ISO_MASK];
+        assert( Vec_IntEntry(p->vUniques, Gia_ObjId(p->pGia, pObj)) == -1 );
+        Vec_IntWriteEntry( p->vUniques, Gia_ObjId(p->pGia, pObj), p->nUniques++ );
+    }
+    return Vec_PtrSize( p->vSingles );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Wec_t * Gia_Iso2ManDerivePoClasses( Gia_Man_t * pGia )
+{
+    Vec_Wec_t * vEquivs;
+    Vec_Int_t * vValues;
+    Vec_Int_t * vMap;
+    Gia_Obj_t * pObj;
+    int i;
+    vValues = Vec_IntAlloc( Gia_ManPoNum(pGia) );
+    Gia_ManForEachPo( pGia, pObj, i )
+        Vec_IntPush( vValues, pObj->Value );
+    vMap = Hsh_IntManHashArray( vValues, 1 );
+    Vec_IntFree( vValues );
+    vEquivs = Vec_WecCreateClasses( vMap );
+    Vec_IntFree( vMap );
+    return vEquivs;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_Iso2ManCollectOrder2_rec( Gia_Man_t * p, int Id, Vec_Int_t * vVec )
+{
+    Gia_Obj_t * pObj;
+    if ( Gia_ObjIsTravIdCurrentId(p, Id) )
+        return;
+    Gia_ObjSetTravIdCurrentId(p, Id);
+    pObj = Gia_ManObj( p, Id );
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        if ( Gia_ObjFanin0(pObj)->Value <= Gia_ObjFanin1(pObj)->Value )
+        {
+            Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId0(pObj, Id), vVec );
+            Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId1(pObj, Id), vVec );
+        }
+        else
+        {
+            Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId1(pObj, Id), vVec );
+            Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId0(pObj, Id), vVec );
+        }
+    }
+    else if ( Gia_ObjIsCo(pObj) )
+    {
+        Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId0(pObj, Id), vVec );
+    }
+    else if ( Gia_ObjIsPi(p, pObj) )
+    {
+    }
+    else assert( Gia_ObjIsConst0(pObj) );
+    Vec_IntPush( vVec, Id );
+}
+Vec_Int_t * Gia_Iso2ManCollectOrder2( Gia_Man_t * pGia, int * pPos, int nPos )
+{
+    Vec_Int_t * vVec;
+    int i;
+    vVec = Vec_IntAlloc( 1000 );
+    Gia_ManIncrementTravId( pGia );
+    for ( i = 0; i < nPos; i++ )
+        Gia_Iso2ManCollectOrder2_rec( pGia, Gia_ObjId(pGia, Gia_ManPo(pGia, pPos[i])), vVec );
+    return vVec;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_Iso2ManCollectOrder_rec( Gia_Man_t * p, int Id, Vec_Int_t * vRoots, Vec_Int_t * vVec, Vec_Int_t * vMap )
+{
+    Gia_Obj_t * pObj;
+    if ( Gia_ObjIsTravIdCurrentId(p, Id) )
+        return;
+    Gia_ObjSetTravIdCurrentId(p, Id);
+    pObj = Gia_ManObj( p, Id );
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        if ( Gia_ObjFanin0(pObj)->Value <= Gia_ObjFanin1(pObj)->Value )
+        {
+            Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vVec, vMap );
+            Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId1(pObj, Id), vRoots, vVec, vMap );
+        }
+        else
+        {
+            Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId1(pObj, Id), vRoots, vVec, vMap );
+            Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vVec, vMap );
+        }
+    }
+    else if ( Gia_ObjIsCo(pObj) )
+    {
+        Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vVec, vMap );
+    }
+    else if ( Gia_ObjIsCi(pObj) )
+    {
+        if ( Gia_ObjIsRo(p, pObj) )
+            Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) );
+    }
+    else assert( Gia_ObjIsConst0(pObj) );
+    Vec_IntWriteEntry( vMap, Id, Vec_IntSize(vVec) );
+    Vec_IntPush( vVec, Id );
+}
+void Gia_Iso2ManCollectOrder( Gia_Man_t * pGia, int * pPos, int nPos, Vec_Int_t * vRoots, Vec_Int_t * vVec, Vec_Int_t * vMap )
+{
+    int i, iRoot;
+    Vec_IntClear( vRoots );
+    for ( i = 0; i < nPos; i++ )
+        Vec_IntPush( vRoots, Gia_ObjId(pGia, Gia_ManPo(pGia, pPos[i])) );
+    Vec_IntClear( vVec );
+    Gia_ManIncrementTravId( pGia );
+    Vec_IntForEachEntry( vRoots, iRoot, i )
+        Gia_Iso2ManCollectOrder_rec( pGia, iRoot, vRoots, vVec, vMap );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_Iso2ManCheckIsoPair( Gia_Man_t * p, Vec_Int_t * vVec0, Vec_Int_t * vVec1, Vec_Int_t * vMap0, Vec_Int_t * vMap1 )
+{
+    Gia_Obj_t * pObj0, * pObj1;
+    int k, iObj0, iObj1;
+    Vec_IntForEachEntryTwo( vVec0, vVec1, iObj0, iObj1, k )
+    {
+        if ( iObj0 == iObj1 )
+            continue;
+        pObj0 = Gia_ManObj(p, iObj0);
+        pObj1 = Gia_ManObj(p, iObj1);
+        if ( pObj0->Value != pObj1->Value )
+            return 0;
+        assert( pObj0->Value == pObj1->Value );
+        if ( !Gia_ObjIsAnd(pObj0) )
+            continue;
+        if ( Gia_ObjFanin0(pObj0)->Value <= Gia_ObjFanin1(pObj0)->Value )
+        {
+            if ( Gia_ObjFanin0(pObj1)->Value <= Gia_ObjFanin1(pObj1)->Value )
+            {
+                if ( Gia_ObjFaninC0(pObj0) != Gia_ObjFaninC0(pObj1)  || Gia_ObjFaninC1(pObj0) != Gia_ObjFaninC1(pObj1)   ||
+                     Vec_IntEntry(vMap0, Gia_ObjFaninId0p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId0p(p, pObj1)) || 
+                     Vec_IntEntry(vMap0, Gia_ObjFaninId1p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId1p(p, pObj1)) )
+                     return 0;
+            }
+            else
+            {
+                if ( Gia_ObjFaninC0(pObj0) != Gia_ObjFaninC1(pObj1)  || Gia_ObjFaninC1(pObj0) != Gia_ObjFaninC0(pObj1)   ||
+                     Vec_IntEntry(vMap0, Gia_ObjFaninId0p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId1p(p, pObj1)) || 
+                     Vec_IntEntry(vMap0, Gia_ObjFaninId1p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId0p(p, pObj1)) )
+                     return 0;
+            }
+        }
+        else
+        {
+            if ( Gia_ObjFanin0(pObj1)->Value <= Gia_ObjFanin1(pObj1)->Value )
+            {
+                if ( Gia_ObjFaninC1(pObj0) != Gia_ObjFaninC0(pObj1)  || Gia_ObjFaninC0(pObj0) != Gia_ObjFaninC1(pObj1)   ||
+                     Vec_IntEntry(vMap0, Gia_ObjFaninId1p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId0p(p, pObj1)) || 
+                     Vec_IntEntry(vMap0, Gia_ObjFaninId0p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId1p(p, pObj1)) )
+                     return 0;
+            }
+            else
+            {
+                if ( Gia_ObjFaninC1(pObj0) != Gia_ObjFaninC1(pObj1)  || Gia_ObjFaninC0(pObj0) != Gia_ObjFaninC0(pObj1)   ||
+                     Vec_IntEntry(vMap0, Gia_ObjFaninId1p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId1p(p, pObj1)) || 
+                     Vec_IntEntry(vMap0, Gia_ObjFaninId0p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId0p(p, pObj1)) )
+                     return 0;
+            }
+        }
+    }
+    return 1;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_Iso2ManCheckIsoClassOneSkip( Gia_Man_t * p, Vec_Int_t * vClass, Vec_Int_t * vRoots, Vec_Int_t * vVec0, Vec_Int_t * vVec1, Vec_Int_t * vMap0, Vec_Int_t * vMap1 )
+{
+    int i, iPo;
+    assert( Vec_IntSize(vClass) > 1 );
+    iPo = Vec_IntEntry( vClass, 0 );
+    Gia_Iso2ManCollectOrder( p, &iPo, 1, vRoots, vVec0, vMap0 );
+    Vec_IntForEachEntryStart( vClass, iPo, i, 1 )
+    {
+        Gia_Iso2ManCollectOrder( p, &iPo, 1, vRoots, vVec1, vMap1 );
+        if ( Vec_IntSize(vVec0) != Vec_IntSize(vVec1) )
+            return 0;
+        if ( !Gia_Iso2ManCheckIsoPair( p, vVec0, vVec1, vMap0, vMap1 ) )
+            return 0;
+    }
+    return 1;
+} 
+Vec_Wec_t * Gia_Iso2ManCheckIsoClassesSkip( Gia_Man_t * p, Vec_Wec_t * vEquivs )
+{
+    Vec_Wec_t * vEquivs2;
+    Vec_Int_t * vRoots = Vec_IntAlloc( 10000 );
+    Vec_Int_t * vVec0 = Vec_IntAlloc( 10000 );
+    Vec_Int_t * vVec1 = Vec_IntAlloc( 10000 );
+    Vec_Int_t * vMap0 = Vec_IntStart( Gia_ManObjNum(p) );
+    Vec_Int_t * vMap1 = Vec_IntStart( Gia_ManObjNum(p) );
+    Vec_Int_t * vClass, * vClass2;
+    int i, k, Entry, Counter = 0;
+    vEquivs2 = Vec_WecAlloc( 2 * Vec_WecSize(vEquivs) );
+    Vec_WecForEachLevel( vEquivs, vClass, i )
+    {
+        if ( i % 50 == 0 )
+            printf( "Finished %8d outputs (out of %8d)...\r", Counter, Gia_ManPoNum(p) ), fflush(stdout);
+        Counter += Vec_IntSize(vClass);
+        if ( Vec_IntSize(vClass) < 2 || Gia_Iso2ManCheckIsoClassOneSkip(p, vClass, vRoots, vVec0, vVec1, vMap0, vMap1) )
+        {
+            vClass2 = Vec_WecPushLevel( vEquivs2 );
+            *vClass2 = *vClass;
+            vClass->pArray = NULL;
+            vClass->nSize = vClass->nCap = 0;
+        }
+        else
+        {
+            Vec_IntForEachEntry( vClass, Entry, k )
+            {
+                vClass2 = Vec_WecPushLevel( vEquivs2 );
+                Vec_IntPush( vClass2, Entry );
+            }
+        }
+    }
+    Vec_IntFree( vRoots );
+    Vec_IntFree( vVec0 );
+    Vec_IntFree( vVec1 );
+    Vec_IntFree( vMap0 );
+    Vec_IntFree( vMap1 );
+    return vEquivs2;
+}
+
+void Gia_Iso2ManCheckIsoClassOne( Gia_Man_t * p, Vec_Int_t * vClass, Vec_Int_t * vRoots, Vec_Int_t * vVec0, Vec_Int_t * vVec1, Vec_Int_t * vMap0, Vec_Int_t * vMap1, Vec_Int_t * vNewClass )
+{
+    int i, k = 1, iPo;
+    Vec_IntClear( vNewClass );
+    if ( Vec_IntSize(vClass) <= 1 )
+        return;
+    assert( Vec_IntSize(vClass) > 1 );
+    iPo = Vec_IntEntry( vClass, 0 );
+    Gia_Iso2ManCollectOrder( p, &iPo, 1, vRoots, vVec0, vMap0 );
+    Vec_IntForEachEntryStart( vClass, iPo, i, 1 )
+    {
+        Gia_Iso2ManCollectOrder( p, &iPo, 1, vRoots, vVec1, vMap1 );
+        if ( Vec_IntSize(vVec0) == Vec_IntSize(vVec1) && Gia_Iso2ManCheckIsoPair(p, vVec0, vVec1, vMap0, vMap1) )
+            Vec_IntWriteEntry( vClass, k++, iPo );
+        else
+            Vec_IntPush( vNewClass, iPo );
+    }
+    Vec_IntShrink( vClass, k );
+} 
+Vec_Wec_t * Gia_Iso2ManCheckIsoClasses( Gia_Man_t * p, Vec_Wec_t * vEquivs )
+{
+    Vec_Wec_t * vEquivs2;
+    Vec_Int_t * vRoots = Vec_IntAlloc( 10000 );
+    Vec_Int_t * vVec0 = Vec_IntAlloc( 10000 );
+    Vec_Int_t * vVec1 = Vec_IntAlloc( 10000 );
+    Vec_Int_t * vMap0 = Vec_IntStart( Gia_ManObjNum(p) );
+    Vec_Int_t * vMap1 = Vec_IntStart( Gia_ManObjNum(p) );
+    Vec_Int_t * vClass, * vClass2, * vNewClass;
+    int i, Counter = 0;
+    vNewClass = Vec_IntAlloc( 100 );
+    vEquivs2 = Vec_WecAlloc( 2 * Vec_WecSize(vEquivs) );
+    Vec_WecForEachLevel( vEquivs, vClass, i )
+    {
+        if ( i % 50 == 0 )
+            printf( "Finished %8d outputs (out of %8d)...\r", Counter, Gia_ManPoNum(p) ), fflush(stdout);
+        // split this class
+        Gia_Iso2ManCheckIsoClassOne( p, vClass, vRoots, vVec0, vVec1, vMap0, vMap1, vNewClass );
+        Counter += Vec_IntSize(vClass);
+        // add remaining class
+        vClass2 = Vec_WecPushLevel( vEquivs2 );
+        *vClass2 = *vClass;
+        vClass->pArray = NULL;
+        vClass->nSize = vClass->nCap = 0;
+        // add new class
+        if ( Vec_IntSize(vNewClass) == 0 )
+            continue;
+        vClass = Vec_WecPushLevel( vEquivs );
+        Vec_IntAppend( vClass, vNewClass );
+    }
+    Vec_IntFree( vNewClass );   
+    Vec_IntFree( vRoots );
+    Vec_IntFree( vVec0 );
+    Vec_IntFree( vVec1 );
+    Vec_IntFree( vMap0 );
+    Vec_IntFree( vMap1 );
+    return vEquivs2;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Wec_t * Gia_Iso2ManPerform( Gia_Man_t * pGia, int fVerbose )
+{
+    Gia_Iso2Man_t * p;
+    abctime clk = Abc_Clock();
+    p = Gia_Iso2ManStart( pGia );
+    Gia_Iso2ManPrepare( pGia );
+    Gia_Iso2ManPropagate( pGia );
+    Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose );
+    while ( Gia_Iso2ManUniqify( p ) )
+    {
+        Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose );
+        Gia_Iso2ManPropagate( pGia );
+    }
+    Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose );
+/*
+    Gia_Iso2ManUpdate( p, 20 );
+    while ( Gia_Iso2ManUniqify( p ) )
+    {
+        Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose );
+        Gia_Iso2ManPropagate( pGia );
+    }
+    Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose );
+*/
+    Gia_Iso2ManStop( p );
+    return Gia_Iso2ManDerivePoClasses( pGia );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManIsoReduce2( Gia_Man_t * pGia, Vec_Ptr_t ** pvPosEquivs, Vec_Ptr_t ** pvPiPerms, int fEstimate, int fBetterQual, int fDualOut, int fVerbose, int fVeryVerbose )
+{
+    Gia_Man_t * pPart;
+    Vec_Wec_t * vEquivs, * vEquivs2;
+    Vec_Int_t * vRemains;
+    int nClasses, nUsedPos;
+    abctime clk = Abc_Clock();
+    vEquivs = Gia_Iso2ManPerform( pGia, fVeryVerbose );
+    // report class stats
+    nClasses = Vec_WecCountNonTrivial( vEquivs, &nUsedPos );
+    printf( "Reduced %d outputs to %d candidate   classes (%d outputs are in %d non-trivial classes).  ", 
+        Gia_ManPoNum(pGia), Vec_WecSize(vEquivs), nUsedPos, nClasses );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    if ( fEstimate )
+    {
+        Vec_WecFree( vEquivs );
+        return Gia_ManDup(pGia);
+    }
+    // verify classes
+    if ( fBetterQual )
+        vEquivs2 = Gia_Iso2ManCheckIsoClasses( pGia, vEquivs );
+    else
+        vEquivs2 = Gia_Iso2ManCheckIsoClassesSkip( pGia, vEquivs );
+    Vec_WecFree( vEquivs );
+    vEquivs = vEquivs2;
+    // sort equiv classes by the first integer
+    Vec_WecSortByFirstInt( vEquivs, 0 );
+    // find the first outputs
+    vRemains = Vec_WecCollectFirsts( vEquivs );
+    // derive the final GIA
+    pPart = Gia_ManDupCones( pGia, Vec_IntArray(vRemains), Vec_IntSize(vRemains), 0 );
+    Vec_IntFree( vRemains );
+    // report class stats
+    nClasses = Vec_WecCountNonTrivial( vEquivs, &nUsedPos );
+    printf( "Reduced %d outputs to %d equivalence classes (%d outputs are in %d non-trivial classes).  ", 
+        Gia_ManPoNum(pGia), Vec_WecSize(vEquivs), nUsedPos, nClasses );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    if ( fVerbose )
+    { 
+        printf( "Nontrivial classes:\n" );
+        Vec_WecPrint( vEquivs, 1 );
+    }
+    if ( pvPiPerms )
+        *pvPiPerms = NULL;
+    if ( pvPosEquivs )
+        *pvPosEquivs = Vec_WecConvertToVecPtr( vEquivs );
+    Vec_WecFree( vEquivs );
+//    Gia_ManStopP( &pPart );
+    return pPart;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaIso3.c b/abc-build/src/aig/gia/giaIso3.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaIso3.c
@@ -0,0 +1,167 @@
+/**CFile****************************************************************
+
+  FileName    [giaIso3.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaIso3.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static unsigned Iso_Nodes[6] = { 0x04892ed6, 0xc2523d7d, 0xdc36cd2e, 0xf2db64f8, 0xde3126bb, 0xdebbdff0 }; // ab, a!b, !a!b, pi, po, const0
+static unsigned Iso_Fanio[2] = { 0x855ee0cf, 0x946e1b5f }; // fanin, fanout
+static unsigned Iso_Compl[2] = { 0x8ba63e50, 0x14d87f02 }; // non-compl, compl
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Gia_Iso3Node( Gia_Obj_t * pObj )
+{
+    if ( Gia_ObjIsAnd(pObj) )
+        return Iso_Nodes[Gia_ObjFaninC0(pObj) + Gia_ObjFaninC1(pObj)];
+    if ( Gia_ObjIsCi(pObj) )
+        return Iso_Nodes[3];
+    if ( Gia_ObjIsCo(pObj) )
+        return Iso_Nodes[4];
+    return Iso_Nodes[5];
+}
+void Gia_Iso3Init( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+        pObj->Value = Gia_Iso3Node( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_Iso3ComputeEdge( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanin, int fCompl, Vec_Int_t * vSign )
+{
+    pObj->Value   += Vec_IntEntry(vSign, Gia_ObjId(p, pFanin)) + Iso_Compl[fCompl] + Iso_Fanio[0];
+    pFanin->Value += Vec_IntEntry(vSign, Gia_ObjId(p, pObj))   + Iso_Compl[fCompl] + Iso_Fanio[1];
+}
+void Gia_Iso3Compute( Gia_Man_t * p, Vec_Int_t * vSign )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) )
+            Gia_Iso3ComputeEdge( p, pObj, Gia_ObjFanin0(pObj), Gia_ObjFaninC0(pObj), vSign );
+        if ( Gia_ObjIsAnd(pObj) )
+            Gia_Iso3ComputeEdge( p, pObj, Gia_ObjFanin1(pObj), Gia_ObjFaninC1(pObj), vSign );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Gia_Iso3Save( Gia_Man_t * p )
+{
+    Vec_Int_t * vSign;
+    Gia_Obj_t * pObj;
+    int i;
+    vSign = Vec_IntAlloc( Gia_ManObjNum(p) );
+    Gia_ManForEachObj( p, pObj, i )
+        Vec_IntPush( vSign, pObj->Value );
+    return vSign;
+}
+int Gia_Iso3Unique( Vec_Int_t * vSign )
+{
+    int nUnique;
+    Vec_Int_t * vCopy = Vec_IntDup( vSign );
+    Vec_IntUniqify( vCopy );
+    nUnique = Vec_IntSize(vCopy);
+    Vec_IntFree( vCopy );
+    return nUnique;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_Iso3Test( Gia_Man_t * p )
+{
+    int nIterMax = 500;
+    int i, Prev = -1, This; 
+    abctime clk = Abc_Clock();
+    Vec_Int_t * vSign = NULL;
+    Gia_Iso3Init( p );
+    for ( i = 0; i < nIterMax; i++ )
+    {
+        vSign = Gia_Iso3Save( p );
+//        This = Gia_Iso3Unique( vSign );
+        This = Vec_IntUniqueCount( vSign, 1, NULL );
+        printf( "Iter %3d : %6d  out of %6d  ", i, This, Vec_IntSize(vSign) );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+        if ( This == Prev )
+            break;
+        Prev = This;
+        Gia_Iso3Compute( p, vSign );
+        Vec_IntFreeP( &vSign );
+    }
+    Vec_IntFreeP( &vSign );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaJf.c b/abc-build/src/aig/gia/giaJf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaJf.c
@@ -0,0 +1,1801 @@
+/**CFile****************************************************************
+
+  FileName    [giaJf.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaJf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/vec/vecSet.h"
+#include "misc/vec/vecMem.h"
+#include "misc/extra/extra.h"
+#include "bool/kit/kit.h"
+#include "misc/util/utilTruth.h"
+#include "opt/dau/dau.h"
+#include "sat/cnf/cnf.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define JF_LEAF_MAX   8
+#define JF_WORD_MAX  ((JF_LEAF_MAX > 6) ? 1 << (JF_LEAF_MAX-6) : 1)
+#define JF_CUT_MAX   16
+
+typedef struct Jf_Cut_t_ Jf_Cut_t; 
+struct Jf_Cut_t_
+{
+    word             Sign;        // signature
+    float            Flow;        // flow
+    int              Time;        // arrival time
+    int              iFunc;       // function 
+    int              Cost;        // cut cost
+    int              pCut[JF_LEAF_MAX+2]; // cut
+};
+
+typedef struct Jf_Man_t_ Jf_Man_t; 
+struct Jf_Man_t_
+{
+    Gia_Man_t *      pGia;        // user's manager
+    Jf_Par_t *       pPars;       // users parameter
+    Sdm_Man_t *      pDsd;        // extern DSD manager
+    Vec_Int_t *      vCnfs;       // costs of elementary CNFs
+    Vec_Mem_t *      vTtMem;      // truth table memory and hash table
+    Vec_Int_t        vCuts;       // cuts for each node
+    Vec_Int_t        vArr;        // arrival time
+    Vec_Int_t        vDep;        // departure time
+    Vec_Flt_t        vFlow;       // area flow
+    Vec_Flt_t        vRefs;       // ref counters
+    Vec_Set_t        pMem;        // cut storage
+    Vec_Int_t *      vTemp;       // temporary
+    float (*pCutCmp) (Jf_Cut_t *, Jf_Cut_t *);// procedure to compare cuts
+    abctime          clkStart;    // starting time
+    word             CutCount[4]; // statistics
+    int              nCoarse;     // coarse nodes
+};
+
+static inline int    Jf_ObjIsUnit( Gia_Obj_t * p )          { return !p->fMark0;                                       }
+static inline void   Jf_ObjCleanUnit( Gia_Obj_t * p )       { assert(Jf_ObjIsUnit(p)); p->fMark0 = 1;                  }
+static inline void   Jf_ObjSetUnit( Gia_Obj_t * p )         { p->fMark0 = 0;                                           }
+
+static inline int    Jf_ObjCutH( Jf_Man_t * p, int i )      { return Vec_IntEntry(&p->vCuts, i);                       }
+static inline int *  Jf_ObjCuts( Jf_Man_t * p, int i )      { return (int *)Vec_SetEntry(&p->pMem, Jf_ObjCutH(p, i));  }
+static inline int *  Jf_ObjCutBest( Jf_Man_t * p, int i )   { return Jf_ObjCuts(p, i) + 1;                             }
+static inline int    Jf_ObjArr( Jf_Man_t * p, int i )       { return Vec_IntEntry(&p->vArr, i);                        }
+static inline int    Jf_ObjDep( Jf_Man_t * p, int i )       { return Vec_IntEntry(&p->vDep, i);                        }
+static inline float  Jf_ObjFlow( Jf_Man_t * p, int i )      { return Vec_FltEntry(&p->vFlow, i);                       }
+static inline float  Jf_ObjRefs( Jf_Man_t * p, int i )      { return Vec_FltEntry(&p->vRefs, i);                       }
+//static inline int    Jf_ObjLit( int i, int c )            { return i;                                                }
+static inline int    Jf_ObjLit( int i, int c )              { return Abc_Var2Lit( i, c );                              }
+
+static inline int    Jf_CutSize( int * pCut )               { return pCut[0] & 0xF;                                    }  //  4 bits
+static inline int    Jf_CutCost( int * pCut )               { return (pCut[0] >> 4) & 0xF;                             }  //  4 bits
+static inline int    Jf_CutFunc( int * pCut )               { return ((unsigned)pCut[0] >> 8);                         }  // 24 bits
+static inline int    Jf_CutSetAll( int f, int c, int s )    { return (f << 8) | (c << 4) | s;                          }
+static inline void   Jf_CutSetSize( int * pCut, int s )     { assert(s>=0 && s<16); pCut[0] ^= (Jf_CutSize(pCut) ^ s); }
+static inline void   Jf_CutSetCost( int * pCut, int c )     { assert(c>=0 && c<16); pCut[0] ^=((Jf_CutCost(pCut) ^ c) << 4); }
+static inline void   Jf_CutSetFunc( int * pCut, int f )     { assert(f>=0); pCut[0] ^=((Jf_CutFunc(pCut) ^ f) << 8);   }
+
+static inline int    Jf_CutFuncClass( int * pCut )          { return Abc_Lit2Var(Jf_CutFunc(pCut));                    }
+static inline int    Jf_CutFuncCompl( int * pCut )          { return Abc_LitIsCompl(Jf_CutFunc(pCut));                 }
+static inline int *  Jf_CutLits( int * pCut )               { return pCut + 1;                                         }
+static inline int    Jf_CutLit( int * pCut, int i )         { assert(i);return pCut[i];                                }
+//static inline int    Jf_CutVar( int * pCut, int i )         { assert(i); return pCut[i];                               }
+static inline int    Jf_CutVar( int * pCut, int i )         {  assert(i);return Abc_Lit2Var(pCut[i]);                  }
+static inline int    Jf_CutIsTriv( int * pCut, int i )      { return Jf_CutSize(pCut) == 1 && Jf_CutVar(pCut, 1) == i; } 
+static inline int    Jf_CutCnfSizeF( Jf_Man_t * p, int f )  { return Vec_IntEntry( p->vCnfs, f );                      }
+static inline int    Jf_CutCnfSize( Jf_Man_t * p, int * c ) { return Jf_CutCnfSizeF( p, Jf_CutFuncClass(c) );          }
+
+static inline int    Jf_ObjFunc0( Gia_Obj_t * p, int * c )  { return Abc_LitNotCond(Jf_CutFunc(c), Gia_ObjFaninC0(p)); } 
+static inline int    Jf_ObjFunc1( Gia_Obj_t * p, int * c )  { return Abc_LitNotCond(Jf_CutFunc(c), Gia_ObjFaninC1(p)); } 
+
+#define Jf_ObjForEachCut( pList, pCut, i )   for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += Jf_CutSize(pCut) + 1 )
+#define Jf_CutForEachLit( pCut, Lit, i )     for ( i = 1; i <= Jf_CutSize(pCut) && (Lit = Jf_CutLit(pCut, i)); i++ )
+#define Jf_CutForEachVar( pCut, Var, i )     for ( i = 1; i <= Jf_CutSize(pCut) && (Var = Jf_CutVar(pCut, i)); i++ )
+
+extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CNF for the mapped GIA.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Jf_ManGenCnf( word uTruth, int iLitOut, Vec_Int_t * vLeaves, Vec_Int_t * vLits, Vec_Int_t * vClas, Vec_Int_t * vCover )
+{
+    if ( uTruth == 0 || ~uTruth == 0 )
+    {
+        Vec_IntPush( vClas, Vec_IntSize(vLits) );
+        Vec_IntPush( vLits, Abc_LitNotCond(iLitOut, (uTruth == 0)) );
+    }
+    else 
+    {
+        int i, k, c, Literal, Cube;
+        assert( Vec_IntSize(vLeaves) > 0 );
+        for ( c = 0; c < 2; c ++ )
+        {
+            int RetValue = Kit_TruthIsop( (unsigned *)&uTruth, Vec_IntSize(vLeaves), vCover, 0 );
+            assert( RetValue == 0 );
+            Vec_IntForEachEntry( vCover, Cube, i )
+            {
+                Vec_IntPush( vClas, Vec_IntSize(vLits) );
+                Vec_IntPush( vLits, Abc_LitNotCond(iLitOut, c) );
+                for ( k = 0; k < Vec_IntSize(vLeaves); k++ )
+                {
+                    Literal = 3 & (Cube >> (k << 1));
+                    if ( Literal == 1 )      // '0'  -> pos lit
+                        Vec_IntPush( vLits, Abc_LitNotCond(Vec_IntEntry(vLeaves, k), 0) );
+                    else if ( Literal == 2 ) // '1'  -> neg lit
+                        Vec_IntPush( vLits, Abc_LitNotCond(Vec_IntEntry(vLeaves, k), 1) );
+                    else if ( Literal != 0 )
+                        assert( 0 );
+                }
+            }
+            uTruth = ~uTruth;
+        }
+    }
+}
+Cnf_Dat_t * Jf_ManCreateCnfRemap( Gia_Man_t * p, Vec_Int_t * vLits, Vec_Int_t * vClas, int fAddOrCla )
+{
+    Cnf_Dat_t * pCnf; 
+    Gia_Obj_t * pObj;
+    int i, Entry, * pMap, nVars = 0;
+    if ( fAddOrCla )
+    {
+        Vec_IntPush( vClas, Vec_IntSize(vLits) );
+        Gia_ManForEachPo( p, pObj, i )
+            Vec_IntPush( vLits, Abc_Var2Lit(Gia_ObjId(p, pObj), 0) );
+    }
+    // label nodes present in the mapping
+    Vec_IntForEachEntry( vLits, Entry, i )
+        Gia_ManObj(p, Abc_Lit2Var(Entry))->fMark0 = 1;
+    // create variable map
+    pMap = ABC_FALLOC( int, Gia_ManObjNum(p) );
+    Gia_ManForEachObjReverse( p, pObj, i )
+        if ( pObj->fMark0 )
+            pObj->fMark0 = 0, pMap[i] = nVars++;
+    // relabel literals
+    Vec_IntForEachEntry( vLits, Entry, i )
+        Vec_IntWriteEntry( vLits, i, Abc_Lit2LitV(pMap, Entry) );
+    // generate CNF
+    pCnf = ABC_CALLOC( Cnf_Dat_t, 1 );
+    pCnf->pMan = (Aig_Man_t *)p;
+    pCnf->nVars = nVars;
+    pCnf->nLiterals = Vec_IntSize(vLits);
+    pCnf->nClauses = Vec_IntSize(vClas);
+    pCnf->pClauses = ABC_ALLOC( int *, pCnf->nClauses+1 );
+    pCnf->pClauses[0] = Vec_IntReleaseArray(vLits);
+    Vec_IntForEachEntry( vClas, Entry, i )
+        pCnf->pClauses[i] = pCnf->pClauses[0] + Entry;
+    pCnf->pClauses[i] = pCnf->pClauses[0] + pCnf->nLiterals;
+    pCnf->pVarNums = pMap;
+    return pCnf;
+}
+Cnf_Dat_t * Jf_ManCreateCnf( Gia_Man_t * p, Vec_Int_t * vLits, Vec_Int_t * vClas )
+{
+    Cnf_Dat_t * pCnf; 
+    int i, Entry, iOut;
+    // generate CNF
+    pCnf = ABC_CALLOC( Cnf_Dat_t, 1 );
+    pCnf->pMan = (Aig_Man_t *)p;
+    pCnf->nVars = Gia_ManObjNum(p);
+    pCnf->nLiterals = Vec_IntSize(vLits);
+    pCnf->nClauses = Vec_IntSize(vClas);
+    pCnf->pClauses = ABC_ALLOC( int *, pCnf->nClauses+1 );
+    pCnf->pClauses[0] = Vec_IntReleaseArray(vLits);
+    Vec_IntForEachEntry( vClas, Entry, i )
+        pCnf->pClauses[i] = pCnf->pClauses[0] + Entry;
+    pCnf->pClauses[i] = pCnf->pClauses[0] + pCnf->nLiterals;
+    // create mapping of objects into their clauses
+    pCnf->pObj2Clause = ABC_FALLOC( int, Gia_ManObjNum(p) );
+    pCnf->pObj2Count  = ABC_FALLOC( int, Gia_ManObjNum(p) );
+    for ( i = 0; i < pCnf->nClauses; i++ )
+    {
+        iOut = Abc_Lit2Var(pCnf->pClauses[i][0]);
+        if ( pCnf->pObj2Clause[iOut] == -1 )
+        {
+            pCnf->pObj2Clause[iOut] = i;
+            pCnf->pObj2Count[iOut] = 1;
+        }
+        else
+        {
+            assert( pCnf->pObj2Count[iOut] > 0 );
+            pCnf->pObj2Count[iOut]++;
+        }
+    }
+    return pCnf;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computing references while discounting XOR/MUX.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float * Jf_ManInitRefs( Jf_Man_t * pMan )
+{
+    Gia_Man_t * p = pMan->pGia;
+    Gia_Obj_t * pObj, * pCtrl, * pData0, * pData1;
+    float * pRes; int i;
+    assert( p->pRefs == NULL );
+    p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        Gia_ObjRefFanin0Inc( p, pObj );
+        if ( Gia_ObjIsBuf(pObj) )
+            continue;
+        Gia_ObjRefFanin1Inc( p, pObj );
+        if ( !Gia_ObjIsMuxType(pObj) )
+            continue;
+        // discount XOR/MUX
+        pCtrl = Gia_ObjRecognizeMux( pObj, &pData1, &pData0 );
+        Gia_ObjRefDec( p, Gia_Regular(pCtrl) );
+        if ( Gia_Regular(pData1) == Gia_Regular(pData0) )
+            Gia_ObjRefDec( p, Gia_Regular(pData1) );
+    }
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ObjRefFanin0Inc( p, pObj );
+    // mark XOR/MUX internal nodes, which are not used elsewhere
+    if ( pMan->pPars->fCoarsen )
+    {
+        pMan->nCoarse = 0;
+        Gia_ManForEachAnd( p, pObj, i )
+        {
+            if ( !Gia_ObjIsMuxType(pObj) )
+                continue;
+            if ( Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 )
+            {
+                Jf_ObjSetUnit(Gia_ObjFanin0(Gia_ObjFanin0(pObj)));
+                Jf_ObjSetUnit(Gia_ObjFanin0(Gia_ObjFanin1(pObj)));
+                Jf_ObjCleanUnit(Gia_ObjFanin0(pObj)), pMan->nCoarse++;
+            }
+            if ( Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1 )
+            {
+                Jf_ObjSetUnit(Gia_ObjFanin1(Gia_ObjFanin0(pObj)));
+                Jf_ObjSetUnit(Gia_ObjFanin1(Gia_ObjFanin1(pObj)));
+                Jf_ObjCleanUnit(Gia_ObjFanin1(pObj)), pMan->nCoarse++;
+            }
+        }
+    }
+    // multiply by factor
+    pRes = ABC_ALLOC( float, Gia_ManObjNum(p) );
+    for ( i = 0; i < Gia_ManObjNum(p); i++ )
+        pRes[i] = Abc_MaxInt( 1, p->pRefs[i] );
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Jf_ManProfileClasses( Jf_Man_t * p )
+{
+    Gia_Obj_t * pObj; 
+    int Counts[595] = {0}, Costs[595] = {0};
+    int i, iFunc, Total = 0, CostTotal = 0, Other = 0, CostOther = 0;
+    printf( "DSD classes that appear in more than %.1f %% of mapped nodes:\n", 0.1 * p->pPars->nVerbLimit );
+    Gia_ManForEachAnd( p->pGia, pObj, i )
+        if ( !Gia_ObjIsBuf(pObj) && Gia_ObjRefNumId(p->pGia, i) )
+        {
+            iFunc = Jf_CutFuncClass( Jf_ObjCutBest(p, i) );
+            assert( iFunc < 595 );
+            if ( p->pPars->fGenCnf )
+            {
+                Costs[iFunc] += Jf_CutCnfSizeF(p, iFunc);
+                CostTotal += Jf_CutCnfSizeF(p, iFunc);
+            }
+            Counts[iFunc]++;
+            Total++;
+        }
+    CostTotal = Abc_MaxInt(CostTotal, 1);
+    Total = Abc_MaxInt(Total, 1);
+    for ( i = 0; i < 595; i++ )
+        if ( Counts[i] && 100.0 * Counts[i] / Total >= 0.1 * p->pPars->nVerbLimit )
+        {
+            printf( "%5d  :  ", i );
+            printf( "%-20s   ", Sdm_ManReadDsdStr(p->pDsd, i) );
+            printf( "%8d  ",    Counts[i] );
+            printf( "%5.1f %%   ", 100.0 * Counts[i] / Total );
+            printf( "%8d  ",    Costs[i] );
+            printf( "%5.1f %%", 100.0 * Costs[i] / CostTotal );
+            printf( "\n" );
+        }
+        else
+        {
+            Other += Counts[i];
+            CostOther += Costs[i];
+        }
+    printf( "Other  :  " );
+    printf( "%-20s   ",   "" );
+    printf( "%8d  ",    Other );
+    printf( "%5.1f %%   ", 100.0 * Other / Total );
+    printf( "%8d  ",    CostOther );
+    printf( "%5.1f %%", 100.0 * CostOther / CostTotal );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Manager manipulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Jf_Man_t * Jf_ManAlloc( Gia_Man_t * pGia, Jf_Par_t * pPars )
+{
+    Jf_Man_t * p;
+    assert( pPars->nLutSize <= JF_LEAF_MAX );
+    assert( pPars->nCutNum <= JF_CUT_MAX );
+    Vec_IntFreeP( &pGia->vMapping );
+    p = ABC_CALLOC( Jf_Man_t, 1 );
+    p->pGia      = pGia;
+    p->pPars     = pPars;
+    if ( pPars->fCutMin && !pPars->fFuncDsd )
+        p->vTtMem = Vec_MemAllocForTT( pPars->nLutSize, 0 );
+    else if ( pPars->fCutMin && pPars->fFuncDsd )
+    {
+        p->pDsd = Sdm_ManRead();
+        if ( pPars->fGenCnf )
+        {
+            p->vCnfs = Vec_IntStart( 595 );
+            Sdm_ManReadCnfCosts( p->pDsd, Vec_IntArray(p->vCnfs), Vec_IntSize(p->vCnfs) );
+        }
+    }
+    Vec_IntFill( &p->vCuts, Gia_ManObjNum(pGia), 0 );
+    Vec_IntFill( &p->vArr,  Gia_ManObjNum(pGia), 0 );
+    Vec_IntFill( &p->vDep,  Gia_ManObjNum(pGia), 0 );
+    Vec_FltFill( &p->vFlow, Gia_ManObjNum(pGia), 0 );
+    p->vRefs.nCap = p->vRefs.nSize = Gia_ManObjNum(pGia);
+    p->vRefs.pArray = Jf_ManInitRefs( p );
+    Vec_SetAlloc_( &p->pMem, 20 );
+    p->vTemp     = Vec_IntAlloc( 1000 );
+    p->clkStart  = Abc_Clock();
+    return p;
+}
+void Jf_ManFree( Jf_Man_t * p )
+{
+    if ( p->pPars->fVerbose && p->pDsd )
+        Sdm_ManPrintDsdStats( p->pDsd, 0 );
+    if ( p->pPars->fVerbose && p->vTtMem )
+    {
+        printf( "Unique truth tables = %d. Memory = %.2f MB   ", Vec_MemEntryNum(p->vTtMem), Vec_MemMemory(p->vTtMem) / (1<<20) ); 
+        Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
+    }
+    if ( p->pPars->fVeryVerbose && p->pPars->fCutMin && p->pPars->fFuncDsd )
+        Jf_ManProfileClasses( p );
+    if ( p->pPars->fCoarsen )
+        Gia_ManCleanMark0( p->pGia );
+    ABC_FREE( p->pGia->pRefs );
+    ABC_FREE( p->vCuts.pArray );
+    ABC_FREE( p->vArr.pArray );
+    ABC_FREE( p->vDep.pArray );
+    ABC_FREE( p->vFlow.pArray );
+    ABC_FREE( p->vRefs.pArray );
+    if ( p->pPars->fCutMin && !p->pPars->fFuncDsd )
+    {
+        Vec_MemHashFree( p->vTtMem );
+        Vec_MemFree( p->vTtMem );
+    }
+    Vec_IntFreeP( &p->vCnfs );
+    Vec_SetFree_( &p->pMem );
+    Vec_IntFreeP( &p->vTemp );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cut functions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Jf_CutPrint( int * pCut )
+{
+    int i; 
+    printf( "%d {", Jf_CutSize(pCut) );
+    for ( i = 1; i <= Jf_CutSize(pCut); i++ )
+        printf( " %d", Jf_CutLit(pCut, i) );
+    printf( " } Func = %d\n", Jf_CutFunc(pCut) );
+}
+static inline void Jf_ObjCutPrint( int * pCuts )
+{
+    int i, * pCut; 
+    Jf_ObjForEachCut( pCuts, pCut, i )
+        Jf_CutPrint( pCut );
+    printf( "\n" );
+}
+static inline void Jf_ObjBestCutConePrint( Jf_Man_t * p, Gia_Obj_t * pObj )
+{
+    int * pCut = Jf_ObjCutBest( p, Gia_ObjId(p->pGia, pObj) );
+    printf( "Best cut of node %d : ", Gia_ObjId(p->pGia, pObj) );
+    Jf_CutPrint( pCut );
+    Gia_ManPrintCone( p->pGia, pObj, Jf_CutLits(pCut), Jf_CutSize(pCut), p->vTemp );
+}
+static inline void Jf_CutCheck( int * pCut )
+{
+    int i, k;
+    for ( i = 2; i <= Jf_CutSize(pCut); i++ )
+        for ( k = 1; k < i; k++ )
+            assert( Jf_CutLit(pCut, i) != Jf_CutLit(pCut, k) );
+}
+static inline int Jf_CountBitsSimple( unsigned n )
+{
+    int i, Count = 0;
+    for ( i = 0; i < 32; i++ )
+        Count += ((n >> i) & 1);
+    return Count;
+}
+static inline int Jf_CountBits32( unsigned i )
+{
+    i = i - ((i >> 1) & 0x55555555);
+    i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
+    i = ((i + (i >> 4)) & 0x0F0F0F0F);
+    return (i*(0x01010101))>>24;
+}
+static inline int Jf_CountBits( word i )
+{
+    i = i - ((i >> 1) & 0x5555555555555555);
+    i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333);
+    i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F);
+    return (i*(0x0101010101010101))>>56;
+}
+static inline unsigned Jf_CutGetSign32( int * pCut )
+{
+    unsigned Sign = 0; int i; 
+    for ( i = 1; i <= Jf_CutSize(pCut); i++ )
+        Sign |= 1 << (Jf_CutVar(pCut, i) & 0x1F);
+    return Sign;
+}
+static inline word Jf_CutGetSign( int * pCut )
+{
+    word Sign = 0; int i; 
+    for ( i = 1; i <= Jf_CutSize(pCut); i++ )
+        Sign |= ((word)1) << (Jf_CutVar(pCut, i) & 0x3F);
+    return Sign;
+}
+static inline int Jf_CutArr( Jf_Man_t * p, int * pCut )
+{
+    int i, Time = 0;
+    for ( i = 1; i <= Jf_CutSize(pCut); i++ )
+        Time = Abc_MaxInt( Time, Jf_ObjArr(p, Jf_CutVar(pCut, i)) );
+    return Time + 1; 
+}
+
+static inline void Jf_ObjSetBestCut( int * pCuts, int * pCut, Vec_Int_t * vTemp )
+{
+    assert( pCuts < pCut );
+    if ( ++pCuts < pCut )
+    {
+        int nBlock = pCut - pCuts;
+        int nSize = Jf_CutSize(pCut) + 1;
+        Vec_IntGrow( vTemp, nBlock );
+        memmove( Vec_IntArray(vTemp), pCuts, sizeof(int) * nBlock );
+        memmove( pCuts, pCut, sizeof(int) * nSize );
+        memmove( pCuts + nSize, Vec_IntArray(vTemp), sizeof(int) * nBlock );
+    }
+}
+static inline void Jf_CutRef( Jf_Man_t * p, int * pCut )
+{
+    int i;
+    for ( i = 1; i <= Jf_CutSize(pCut); i++ )
+        Gia_ObjRefIncId( p->pGia, Jf_CutVar(pCut, i) );
+}
+static inline void Jf_CutDeref( Jf_Man_t * p, int * pCut )
+{
+    int i;
+    for ( i = 1; i <= Jf_CutSize(pCut); i++ )
+        Gia_ObjRefDecId( p->pGia, Jf_CutVar(pCut, i) );
+}
+static inline float Jf_CutFlow( Jf_Man_t * p, int * pCut )
+{
+    float Flow = 0; int i; 
+    for ( i = 1; i <= Jf_CutSize(pCut); i++ )
+        Flow += Jf_ObjFlow( p, Jf_CutVar(pCut, i) );
+    assert( Flow >= 0 );
+    return Flow; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cut merging.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Jf_CutIsContainedOrder( int * pBase, int * pCut ) // check if pCut is contained pBase
+{
+    int nSizeB = Jf_CutSize(pBase);
+    int nSizeC = Jf_CutSize(pCut);
+    int i, k;
+    if ( nSizeB == nSizeC )
+    {
+        for ( i = 1; i <= nSizeB; i++ )
+            if ( pBase[i] != pCut[i] )
+                return 0;
+        return 1;
+    }
+    assert( nSizeB > nSizeC ); 
+    for ( i = k = 1; i <= nSizeB; i++ )
+    {
+        if ( pBase[i] > pCut[k] )
+            return 0;
+        if ( pBase[i] == pCut[k] )
+        {
+            if ( k++ == nSizeC )
+                return 1;
+        }
+    }
+    return 0;
+}
+static inline int Jf_CutMergeOrder( int * pCut0, int * pCut1, int * pCut, int LutSize )
+{ 
+    int nSize0 = Jf_CutSize(pCut0);
+    int nSize1 = Jf_CutSize(pCut1);
+    int * pC0 = pCut0 + 1;
+    int * pC1 = pCut1 + 1;
+    int * pC = pCut + 1;
+    int i, k, c, s;
+    // the case of the largest cut sizes
+    if ( nSize0 == LutSize && nSize1 == LutSize )
+    {
+        for ( i = 0; i < nSize0; i++ )
+        {
+            if ( pC0[i] != pC1[i] )
+                return 0;
+            pC[i] = pC0[i];
+        }
+        pCut[0] = LutSize;
+        return 1;
+    }
+    // compare two cuts with different numbers
+    i = k = c = s = 0;
+    if ( nSize0 == 0 ) goto FlushCut1;
+    if ( nSize1 == 0 ) goto FlushCut0;
+    while ( 1 )
+    {
+        if ( c == LutSize ) return 0;
+        if ( pC0[i] < pC1[k] )
+        {
+            pC[c++] = pC0[i++];
+            if ( i >= nSize0 ) goto FlushCut1;
+        }
+        else if ( pC0[i] > pC1[k] )
+        {
+            pC[c++] = pC1[k++];
+            if ( k >= nSize1 ) goto FlushCut0;
+        }
+        else
+        {
+            pC[c++] = pC0[i++]; k++;
+            if ( i >= nSize0 ) goto FlushCut1;
+            if ( k >= nSize1 ) goto FlushCut0;
+        }
+    }
+
+FlushCut0:
+    if ( c + nSize0 > LutSize + i ) return 0;
+    while ( i < nSize0 )
+        pC[c++] = pC0[i++];
+    pCut[0] = c;
+    return 1;
+
+FlushCut1:
+    if ( c + nSize1 > LutSize + k ) return 0;
+    while ( k < nSize1 )
+        pC[c++] = pC1[k++];
+    pCut[0] = c;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cut merging.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Jf_CutFindLeaf0( int * pCut, int iObj )
+{
+    int i, nLits = Jf_CutSize(pCut);
+    for ( i = 1; i <= nLits; i++ )
+        if ( pCut[i] == iObj )
+            return i;
+    return i;
+}
+static inline int Jf_CutIsContained0( int * pBase, int * pCut ) // check if pCut is contained pBase
+{
+    int i, nLits = Jf_CutSize(pCut);
+    for ( i = 1; i <= nLits; i++ )
+        if ( Jf_CutFindLeaf0(pBase, pCut[i]) > pBase[0] )
+            return 0;
+    return 1;
+}
+static inline int Jf_CutMerge0( int * pCut0, int * pCut1, int * pCut, int LutSize )
+{
+    int nSize0 = Jf_CutSize(pCut0);
+    int nSize1 = Jf_CutSize(pCut1), i;
+    pCut[0] = nSize0;
+    for ( i = 1; i <= nSize1; i++ )
+        if ( Jf_CutFindLeaf0(pCut0, pCut1[i]) > nSize0 )
+        {
+            if ( pCut[0] == LutSize )
+                return 0;
+            pCut[++pCut[0]] = pCut1[i];
+        }
+    memcpy( pCut + 1, pCut0 + 1, sizeof(int) * nSize0 );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cut merging.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Jf_CutFindLeaf1( int * pCut, int iLit )
+{
+    int i, nLits = Jf_CutSize(pCut);
+    for ( i = 1; i <= nLits; i++ )
+        if ( Abc_Lit2Var(pCut[i]) == iLit )
+            return i;
+    return i;
+}
+static inline int Jf_CutIsContained1( int * pBase, int * pCut ) // check if pCut is contained pBase
+{
+    int i, nLits = Jf_CutSize(pCut);
+    for ( i = 1; i <= nLits; i++ )
+        if ( Jf_CutFindLeaf1(pBase, Abc_Lit2Var(pCut[i])) > pBase[0] )
+            return 0;
+    return 1;
+}
+static inline int Jf_CutMerge1( int * pCut0, int * pCut1, int * pCut, int LutSize )
+{
+    int nSize0 = Jf_CutSize(pCut0);
+    int nSize1 = Jf_CutSize(pCut1), i;
+    pCut[0] = nSize0;
+    for ( i = 1; i <= nSize1; i++ )
+        if ( Jf_CutFindLeaf1(pCut0, Abc_Lit2Var(pCut1[i])) > nSize0 )
+        {
+            if ( pCut[0] == LutSize )
+                return 0;
+            pCut[++pCut[0]] = pCut1[i];
+        }
+    memcpy( pCut + 1, pCut0 + 1, sizeof(int) * nSize0 );
+    return 1;
+}
+static inline int Jf_CutMerge2( int * pCut0, int * pCut1, int * pCut, int LutSize )
+{
+    int ConfigMask = 0x3FFFF; // 18 bits
+    int nSize0 = Jf_CutSize(pCut0);
+    int nSize1 = Jf_CutSize(pCut1);
+    int i, iPlace;
+    pCut[0] = nSize0;
+    for ( i = 1; i <= nSize1; i++ )
+    {
+        iPlace = Jf_CutFindLeaf1(pCut0, Abc_Lit2Var(pCut1[i]));
+        if ( iPlace > nSize0 )
+        {
+            if ( pCut[0] == LutSize )
+                return 0;
+            pCut[(iPlace = ++pCut[0])] = pCut1[i];
+        }
+        else if ( pCut0[iPlace] != pCut1[i] )
+            ConfigMask |= (1 << (iPlace+17));
+        ConfigMask ^= (((i-1) ^ 7) << (3*(iPlace-1)));
+    }
+    memcpy( pCut + 1, pCut0 + 1, sizeof(int) * nSize0 );
+    return ConfigMask;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Cut filtering.]
+
+  Description [Returns the number of cuts after filtering and the last
+  cut in the last entry.  If the cut is filtered, its size is set to -1.]
+               
+  SideEffects [This was found to be 15% slower.]
+
+  SeeAlso     []
+
+***********************************************************************/
+int Jf_ObjCutFilterBoth( Jf_Man_t * p, Jf_Cut_t ** pSto, int c )
+{
+    int k, last;
+    // filter this cut using other cuts
+    for ( k = 0; k < c; k++ )
+        if ( pSto[c]->pCut[0] >= pSto[k]->pCut[0] && 
+            (pSto[c]->Sign & pSto[k]->Sign) == pSto[k]->Sign && 
+             Jf_CutIsContained1(pSto[c]->pCut, pSto[k]->pCut) )
+        {
+                pSto[c]->pCut[0] = -1;
+                return c;
+        }
+    // filter other cuts using this cut
+    for ( k = last = 0; k < c; k++ )
+        if ( !(pSto[c]->pCut[0] < pSto[k]->pCut[0] && 
+              (pSto[c]->Sign & pSto[k]->Sign) == pSto[c]->Sign && 
+               Jf_CutIsContained1(pSto[k]->pCut, pSto[c]->pCut)) )
+        {
+            if ( last++ == k )
+                continue;
+            ABC_SWAP( Jf_Cut_t *, pSto[last-1], pSto[k] );
+        }
+    assert( last <= c );
+    if ( last < c )
+        ABC_SWAP( Jf_Cut_t *, pSto[last], pSto[c] );
+    return last;
+}
+int Jf_ObjCutFilter( Jf_Man_t * p, Jf_Cut_t ** pSto, int c )
+{
+    int k;
+    if ( p->pPars->fCutMin )
+    {
+        for ( k = 0; k < c; k++ )
+            if ( pSto[c]->pCut[0] >= pSto[k]->pCut[0] && 
+                (pSto[c]->Sign & pSto[k]->Sign) == pSto[k]->Sign && 
+                 Jf_CutIsContained1(pSto[c]->pCut, pSto[k]->pCut) )
+                 return 0;
+    }
+    else
+    {
+        for ( k = 0; k < c; k++ )
+            if ( pSto[c]->pCut[0] >= pSto[k]->pCut[0] && 
+                (pSto[c]->Sign & pSto[k]->Sign) == pSto[k]->Sign && 
+                 Jf_CutIsContainedOrder(pSto[c]->pCut, pSto[k]->pCut) )
+                 return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting cuts by size.]
+
+  Description []
+               
+  SideEffects [Did not really help.]
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Jf_ObjSortCuts( Jf_Cut_t ** pSto, int nSize )
+{
+    int i, j, best_i;
+    for ( i = 0; i < nSize-1; i++ )
+    {
+        best_i = i;
+        for ( j = i+1; j < nSize; j++ )
+            if ( pSto[j]->pCut[0] < pSto[best_i]->pCut[0] )
+                best_i = j;
+        ABC_SWAP( Jf_Cut_t *, pSto[i], pSto[best_i] );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reference counting.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Jf_CutRef_rec( Jf_Man_t * p, int * pCut )
+{
+    int i, Var, Count = Jf_CutCost(pCut);
+    Jf_CutForEachVar( pCut, Var, i )
+        if ( !Gia_ObjRefIncId(p->pGia, Var) && !Jf_CutIsTriv(Jf_ObjCutBest(p, Var), Var) )
+            Count += Jf_CutRef_rec( p, Jf_ObjCutBest(p, Var) );
+    return Count;
+}
+int Jf_CutDeref_rec( Jf_Man_t * p, int * pCut )
+{
+    int i, Var, Count = Jf_CutCost(pCut);
+    Jf_CutForEachVar( pCut, Var, i )
+        if ( !Gia_ObjRefDecId(p->pGia, Var) && !Jf_CutIsTriv(Jf_ObjCutBest(p, Var), Var) )
+            Count += Jf_CutDeref_rec( p, Jf_ObjCutBest(p, Var) );
+    return Count;
+}
+static inline int Jf_CutAreaOld( Jf_Man_t * p, int * pCut )
+{
+    int Ela1, Ela2;
+    Ela1 = Jf_CutRef_rec( p, pCut );
+    Ela2 = Jf_CutDeref_rec( p, pCut );
+    assert( Ela1 == Ela2 );
+    return Ela1;
+}
+
+int Jf_CutAreaRef_rec( Jf_Man_t * p, int * pCut )
+{
+    int i, Var, Count = Jf_CutCost(pCut);
+    Jf_CutForEachVar( pCut, Var, i )
+    {
+        if ( !Gia_ObjRefIncId(p->pGia, Var) && !Jf_CutIsTriv(Jf_ObjCutBest(p, Var), Var) )
+            Count += Jf_CutAreaRef_rec( p, Jf_ObjCutBest(p, Var) );
+        Vec_IntPush( p->vTemp, Var );
+    }
+    return Count;
+}
+int Jf_CutAreaRefEdge_rec( Jf_Man_t * p, int * pCut )
+{
+    int i, Var, Count = (Jf_CutCost(pCut) << 4) | Jf_CutSize(pCut);
+    Jf_CutForEachVar( pCut, Var, i )
+    {
+        if ( !Gia_ObjRefIncId(p->pGia, Var) && !Jf_CutIsTriv(Jf_ObjCutBest(p, Var), Var) )
+            Count += Jf_CutAreaRefEdge_rec( p, Jf_ObjCutBest(p, Var) );
+        Vec_IntPush( p->vTemp, Var );
+    }
+    return Count;
+}
+static inline int Jf_CutArea( Jf_Man_t * p, int * pCut, int fEdge )
+{
+    int Ela, Entry, i;
+    Vec_IntClear( p->vTemp );
+    if ( fEdge )
+        Ela = Jf_CutAreaRefEdge_rec( p, pCut );
+    else
+        Ela = Jf_CutAreaRef_rec( p, pCut );
+    Vec_IntForEachEntry( p->vTemp, Entry, i )
+        Gia_ObjRefDecId( p->pGia, Entry );
+    return Ela;
+}
+// returns 1 if MFFC size is less than limit
+int Jf_CutCheckMffc_rec( Jf_Man_t * p, int * pCut, int Limit )
+{
+    int i, Var;
+    Jf_CutForEachVar( pCut, Var, i )
+    {
+        int fRecur = (!Gia_ObjRefDecId(p->pGia, Var) && !Jf_CutIsTriv(Jf_ObjCutBest(p, Var), Var));
+        Vec_IntPush( p->vTemp, Var );
+        if ( Vec_IntSize(p->vTemp) >= Limit )
+            return 0;
+        if ( fRecur && !Jf_CutCheckMffc_rec( p, Jf_ObjCutBest(p, Var), Limit ) )
+            return 0;
+    }
+    return 1;
+}
+static inline int Jf_CutCheckMffc( Jf_Man_t * p, int * pCut, int Limit )
+{
+    int RetValue, Entry, i;
+    Vec_IntClear( p->vTemp );
+    RetValue = Jf_CutCheckMffc_rec( p, pCut, Limit );
+    Vec_IntForEachEntry( p->vTemp, Entry, i )
+        Gia_ObjRefIncId( p->pGia, Entry );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedures.]
+
+  Description [Return positive value if the new cut is better than the old cut.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Jf_CutCompareDelay( Jf_Cut_t * pOld, Jf_Cut_t * pNew )
+{
+    if ( pOld->Time    != pNew->Time    ) return pOld->Time    - pNew->Time;
+    if ( pOld->pCut[0] != pNew->pCut[0] ) return pOld->pCut[0] - pNew->pCut[0];
+    if ( pOld->Flow    != pNew->Flow    ) return pOld->Flow    - pNew->Flow;
+    return 0;
+}
+float Jf_CutCompareArea( Jf_Cut_t * pOld, Jf_Cut_t * pNew )
+{
+//    float Epsilon = (float)0.001;
+//    if ( pOld->Flow > pNew->Flow + Epsilon ) return 1;
+//    if ( pOld->Flow < pNew->Flow - Epsilon ) return -1;
+    if ( pOld->Flow    != pNew->Flow    ) return pOld->Flow    - pNew->Flow;
+    if ( pOld->pCut[0] != pNew->pCut[0] ) return pOld->pCut[0] - pNew->pCut[0];
+    if ( pOld->Time    != pNew->Time    ) return pOld->Time    - pNew->Time;
+    return 0;
+}
+static inline int Jf_ObjAddCutToStore( Jf_Man_t * p, Jf_Cut_t ** pSto, int c, int cMax )
+{
+    Jf_Cut_t * pTemp;
+    int k, last, iPivot;
+    // if the store is empty, add anything
+    if ( c == 0 )
+        return 1;
+    // special case when the cut store is full and last cut is better than new cut
+    if ( c == cMax && p->pCutCmp(pSto[c-1], pSto[c]) <= 0 )
+        return c;
+    // find place of the given cut in the store
+    assert( c <= cMax );
+    for ( iPivot = c-1; iPivot >= 0; iPivot-- )
+        if ( p->pCutCmp(pSto[iPivot], pSto[c]) < 0 ) // iPivot-th cut is better than new cut
+            break;
+    // filter this cut using other cuts
+    if ( p->pPars->fCutMin )
+    {
+        for ( k = 0; k <= iPivot; k++ )
+            if ( pSto[c]->pCut[0] >= pSto[k]->pCut[0] && 
+                (pSto[c]->Sign & pSto[k]->Sign) == pSto[k]->Sign && 
+                 Jf_CutIsContained1(pSto[c]->pCut, pSto[k]->pCut) )
+                    return c;
+    }
+    else
+    {
+        for ( k = 0; k <= iPivot; k++ )
+            if ( pSto[c]->pCut[0] >= pSto[k]->pCut[0] && 
+                (pSto[c]->Sign & pSto[k]->Sign) == pSto[k]->Sign && 
+                 Jf_CutIsContainedOrder(pSto[c]->pCut, pSto[k]->pCut) )
+                    return c;
+    }
+    // insert this cut after iPivot
+    pTemp = pSto[c];
+    for ( ++iPivot, k = c++; k > iPivot; k-- )
+        pSto[k] = pSto[k-1];
+    pSto[iPivot] = pTemp;
+    // filter other cuts using this cut
+    if ( p->pPars->fCutMin )
+    {
+        for ( k = last = iPivot+1; k < c; k++ )
+            if ( !(pSto[iPivot]->pCut[0] <= pSto[k]->pCut[0] && 
+                  (pSto[iPivot]->Sign & pSto[k]->Sign) == pSto[iPivot]->Sign && 
+                   Jf_CutIsContained1(pSto[k]->pCut, pSto[iPivot]->pCut)) )
+            {
+                if ( last++ == k )
+                    continue;
+                ABC_SWAP( Jf_Cut_t *, pSto[last-1], pSto[k] );
+            }
+    }
+    else
+    {
+        for ( k = last = iPivot+1; k < c; k++ )
+            if ( !(pSto[iPivot]->pCut[0] <= pSto[k]->pCut[0] && 
+                  (pSto[iPivot]->Sign & pSto[k]->Sign) == pSto[iPivot]->Sign && 
+                   Jf_CutIsContainedOrder(pSto[k]->pCut, pSto[iPivot]->pCut)) )
+            {
+                if ( last++ == k )
+                    continue;
+                ABC_SWAP( Jf_Cut_t *, pSto[last-1], pSto[k] );
+            }
+    }
+    c = last;
+    // remove the last cut if too many
+    if ( c == cMax + 1 )
+        return c - 1;
+    return c;
+}
+static inline void Jf_ObjPrintStore( Jf_Man_t * p, Jf_Cut_t ** pSto, int c )
+{
+    int i;
+    for ( i = 0; i < c; i++ )
+    {
+        printf( "Flow =%9.5f  ", pSto[i]->Flow );
+        printf( "Time = %5d   ", pSto[i]->Time );
+        printf( "Func = %5d   ", pSto[i]->iFunc );
+        printf( "  " );
+        Jf_CutPrint( pSto[i]->pCut );
+    }
+    printf( "\n" );
+}
+static inline void Jf_ObjCheckPtrs( Jf_Cut_t ** pSto, int c )
+{
+    int i, k;
+    for ( i = 1; i < c; i++ )
+        for ( k = 0; k < i; k++ )
+            assert( pSto[k] != pSto[i] );
+}
+static inline void Jf_ObjCheckStore( Jf_Man_t * p, Jf_Cut_t ** pSto, int c, int iObj )
+{
+    int i, k;
+    for ( i = 1; i < c; i++ )
+        assert( p->pCutCmp(pSto[i-1], pSto[i]) <= 0 );
+    for ( i = 1; i < c; i++ )
+        for ( k = 0; k < i; k++ )
+        {
+            assert( !Jf_CutIsContained1(pSto[k]->pCut, pSto[i]->pCut) );
+            assert( !Jf_CutIsContained1(pSto[i]->pCut, pSto[k]->pCut) );
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cut minimization.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Jf_TtComputeForCut( Jf_Man_t * p, int iFuncLit0, int iFuncLit1, int * pCut0, int * pCut1, int * pCutOut )
+{
+    word uTruth[JF_WORD_MAX], uTruth0[JF_WORD_MAX], uTruth1[JF_WORD_MAX];
+    int fCompl, truthId;
+    int LutSize    = p->pPars->nLutSize;
+    int nWords     = Abc_Truth6WordNum(p->pPars->nLutSize);
+    word * pTruth0 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(iFuncLit0));
+    word * pTruth1 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(iFuncLit1));
+    Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(iFuncLit0) );
+    Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(iFuncLit1) );
+    Abc_TtExpand( uTruth0, LutSize, pCut0 + 1, Jf_CutSize(pCut0), pCutOut + 1, Jf_CutSize(pCutOut) );
+    Abc_TtExpand( uTruth1, LutSize, pCut1 + 1, Jf_CutSize(pCut1), pCutOut + 1, Jf_CutSize(pCutOut) );
+    fCompl         = (int)(uTruth0[0] & uTruth1[0] & 1);
+    Abc_TtAnd( uTruth, uTruth0, uTruth1, nWords, fCompl );
+    pCutOut[0]     = Abc_TtMinBase( uTruth, pCutOut + 1, pCutOut[0], LutSize );
+    assert( (uTruth[0] & 1) == 0 );
+    truthId        = Vec_MemHashInsert(p->vTtMem, uTruth);
+    return Abc_Var2Lit( truthId, fCompl );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cut enumeration.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Jf_ObjAssignCut( Jf_Man_t * p, Gia_Obj_t * pObj )
+{
+    int iObj = Gia_ObjId(p->pGia, pObj);
+    int pClause[3] = { 1, Jf_CutSetAll(2, 0, 1), Jf_ObjLit(iObj, 0) }; // set function
+    assert( Gia_ObjIsCi(pObj) || Gia_ObjIsBuf(pObj) );
+    Vec_IntWriteEntry( &p->vCuts, iObj, Vec_SetAppend( &p->pMem, pClause, 3 ) );
+}
+static inline void Jf_ObjPropagateBuf( Jf_Man_t * p, Gia_Obj_t * pObj, int fReverse )
+{
+    int iObj = Gia_ObjId( p->pGia, pObj );
+    int iFanin = Gia_ObjFaninId0( pObj, iObj );
+    assert( 0 );
+    assert( Gia_ObjIsBuf(pObj) );
+    if ( fReverse )
+        ABC_SWAP( int, iObj, iFanin );
+    Vec_IntWriteEntry( &p->vArr,  iObj, Jf_ObjArr(p, iFanin) );
+    Vec_FltWriteEntry( &p->vFlow, iObj, Jf_ObjFlow(p, iFanin) );
+}
+static inline int Jf_ObjHasCutWithSize( Jf_Cut_t ** pSto, int c, int nSize )
+{
+    int i;
+    for ( i = 0; i < c; i++ )
+        if ( pSto[i]->pCut[0] <= nSize )
+            return 1;
+    return 0;
+}
+void Jf_ObjComputeCuts( Jf_Man_t * p, Gia_Obj_t * pObj, int fEdge )
+{
+    int        LutSize = p->pPars->nLutSize;
+    int        CutNum = p->pPars->nCutNum;
+    int        iObj = Gia_ObjId(p->pGia, pObj);
+    word       Sign0[JF_CUT_MAX+2]; // signatures of the first cut
+    word       Sign1[JF_CUT_MAX+2]; // signatures of the second cut
+    Jf_Cut_t   Sto[JF_CUT_MAX+2];   // cut storage
+    Jf_Cut_t * pSto[JF_CUT_MAX+2];  // pointers to cut storage
+    int *      pCut0, * pCut1, * pCuts0, * pCuts1;
+    int        nOldSupp, Config, i, k, c = 0;
+    // prepare cuts
+    for ( i = 0; i <= CutNum+1; i++ )
+        pSto[i] = Sto + i, pSto[i]->Cost = 0, pSto[i]->iFunc = ~0;
+    // compute signatures
+    pCuts0 = Jf_ObjCuts( p, Gia_ObjFaninId0(pObj, iObj) );
+    Jf_ObjForEachCut( pCuts0, pCut0, i )
+        Sign0[i] = Jf_CutGetSign( pCut0 );
+    // compute signatures
+    pCuts1 = Jf_ObjCuts( p, Gia_ObjFaninId1(pObj, iObj) );
+    Jf_ObjForEachCut( pCuts1, pCut1, i )
+        Sign1[i] = Jf_CutGetSign( pCut1 );
+    // merge cuts
+    p->CutCount[0] += pCuts0[0] * pCuts1[0];
+    Jf_ObjForEachCut( pCuts0, pCut0, i )
+    Jf_ObjForEachCut( pCuts1, pCut1, k )
+    {
+        if ( Jf_CountBits(Sign0[i] | Sign1[k]) > LutSize )
+            continue;
+        p->CutCount[1]++;        
+        if ( !p->pPars->fCutMin )
+        {
+            if ( !Jf_CutMergeOrder(pCut0, pCut1, pSto[c]->pCut, LutSize) )
+                continue;
+            pSto[c]->Sign = Sign0[i] | Sign1[k];
+        }
+        else if ( p->pPars->fFuncDsd )
+        {
+            if ( !(Config = Jf_CutMerge2(pCut0, pCut1, pSto[c]->pCut, LutSize)) )
+                continue;
+            pSto[c]->Sign = Sign0[i] | Sign1[k];
+            nOldSupp = pSto[c]->pCut[0];
+            pSto[c]->iFunc = Sdm_ManComputeFunc( p->pDsd, Jf_ObjFunc0(pObj, pCut0), Jf_ObjFunc1(pObj, pCut1), pSto[c]->pCut, Config, 0 );
+            if ( pSto[c]->iFunc == -1 )
+                continue;
+            if ( p->pPars->fGenCnf && Jf_CutCnfSizeF(p, Abc_Lit2Var(pSto[c]->iFunc)) >= 12 ) // no more than 15
+                continue;
+            assert( pSto[c]->pCut[0] <= nOldSupp );
+            if ( pSto[c]->pCut[0] < nOldSupp )
+                pSto[c]->Sign = Jf_CutGetSign( pSto[c]->pCut );
+        }
+        else
+        {
+            if ( !Jf_CutMergeOrder(pCut0, pCut1, pSto[c]->pCut, LutSize) )
+                continue;
+            pSto[c]->Sign = Sign0[i] | Sign1[k];
+            nOldSupp = pSto[c]->pCut[0];
+            pSto[c]->iFunc = Jf_TtComputeForCut( p, Jf_ObjFunc0(pObj, pCut0), Jf_ObjFunc1(pObj, pCut1), pCut0, pCut1, pSto[c]->pCut );
+            assert( pSto[c]->pCut[0] <= nOldSupp );
+            if ( pSto[c]->pCut[0] < nOldSupp )
+                pSto[c]->Sign = Jf_CutGetSign( pSto[c]->pCut );
+            if ( pSto[c]->iFunc >= (1 << 24) )
+                printf( "Hard limit on the number of different Boolean functions (2^23) is reached. Quitting...\n" ), exit(1);
+        }
+        p->CutCount[2]++;
+        pSto[c]->Time = p->pPars->fAreaOnly ? 0 : Jf_CutArr(p, pSto[c]->pCut);
+        pSto[c]->Flow = Jf_CutFlow(p, pSto[c]->pCut);
+        c = Jf_ObjAddCutToStore( p, pSto, c, CutNum );
+        assert( c <= CutNum );
+    }
+//    Jf_ObjPrintStore( p, pSto, c );
+//    Jf_ObjCheckStore( p, pSto, c, iObj );
+    // add two variable cut
+    if ( !Jf_ObjIsUnit(pObj) && !Jf_ObjHasCutWithSize(pSto, c, 2) )
+    {
+        assert( Jf_ObjIsUnit(Gia_ObjFanin0(pObj)) && Jf_ObjIsUnit(Gia_ObjFanin1(pObj)) );
+        if ( p->pPars->fCutMin ) pSto[c]->iFunc = 4;  // set function (DSD only!)
+        pSto[c]->pCut[0] = 2; 
+        pSto[c]->pCut[1] = Jf_ObjLit(Gia_ObjFaninId0(pObj, iObj), Gia_ObjFaninC0(pObj)); 
+        pSto[c]->pCut[2] = Jf_ObjLit(Gia_ObjFaninId1(pObj, iObj), Gia_ObjFaninC1(pObj)); 
+        c++;
+    }
+    // add elementary cut
+    if ( Jf_ObjIsUnit(pObj) && !(p->pPars->fCutMin && Jf_ObjHasCutWithSize(pSto, c, 1)) )
+    {
+        if ( p->pPars->fCutMin ) pSto[c]->iFunc = 2;  // set function
+        pSto[c]->pCut[0] = 1;
+        pSto[c]->pCut[1] = Jf_ObjLit(iObj, 0);
+        c++;
+    }
+    // reorder cuts
+//    Jf_ObjSortCuts( pSto + 1, c - 1 );
+//    Jf_ObjCheckPtrs( pSto, CutNum );
+    // find cost of the best cut
+    pSto[0]->Cost = p->pPars->fGenCnf ? Jf_CutCnfSizeF(p, Abc_Lit2Var(pSto[0]->iFunc)) : 1;
+    assert( pSto[0]->Cost >= 0 );
+    // save best info
+    assert( pSto[0]->Flow >= 0 );
+    Vec_IntWriteEntry( &p->vArr,  iObj, pSto[0]->Time );
+    Vec_FltWriteEntry( &p->vFlow, iObj, (pSto[0]->Flow + (fEdge ? pSto[0]->pCut[0] : pSto[0]->Cost)) / Jf_ObjRefs(p, iObj) );
+    // add cuts to storage cuts
+    Vec_IntClear( p->vTemp );
+    Vec_IntPush( p->vTemp, c );
+    for ( i = 0; i < c; i++ )
+    {
+        pSto[i]->Cost = p->pPars->fGenCnf ? Jf_CutCnfSizeF(p, Abc_Lit2Var(pSto[i]->iFunc)) : 1;
+        Vec_IntPush( p->vTemp, Jf_CutSetAll(pSto[i]->iFunc, pSto[i]->Cost, pSto[i]->pCut[0]) );
+        for ( k = 1; k <= pSto[i]->pCut[0]; k++ )
+            Vec_IntPush( p->vTemp, pSto[i]->pCut[k] );
+    }
+    Vec_IntWriteEntry( &p->vCuts, iObj, Vec_SetAppend(&p->pMem, Vec_IntArray(p->vTemp), Vec_IntSize(p->vTemp)) );
+    p->CutCount[3] += c;
+}
+void Jf_ManComputeCuts( Jf_Man_t * p, int fEdge )
+{
+    Gia_Obj_t * pObj; int i;
+    if ( p->pPars->fVerbose )
+    {
+        printf( "Aig: CI = %d  CO = %d  AND = %d    ", Gia_ManCiNum(p->pGia), Gia_ManCoNum(p->pGia), Gia_ManAndNum(p->pGia) );
+        printf( "LutSize = %d  CutMax = %d  Rounds = %d\n", p->pPars->nLutSize, p->pPars->nCutNum, p->pPars->nRounds );
+        printf( "Computing cuts...\r" );
+        fflush( stdout );
+    }
+    Gia_ManForEachObj( p->pGia, pObj, i )
+    {
+        if ( Gia_ObjIsCi(pObj) || Gia_ObjIsBuf(pObj) )
+            Jf_ObjAssignCut( p, pObj );
+        if ( Gia_ObjIsBuf(pObj) )
+            Jf_ObjPropagateBuf( p, pObj, 0 );
+        else if ( Gia_ObjIsAnd(pObj) )
+            Jf_ObjComputeCuts( p, pObj, fEdge );
+    }
+    if ( p->pPars->fVerbose )
+    {
+        printf( "CutPair = %lu  ", p->CutCount[0] );
+        printf( "Merge = %lu  ",   p->CutCount[1] );
+        printf( "Eval = %lu  ",    p->CutCount[2] );
+        printf( "Cut = %lu  ",     p->CutCount[3] );
+        Abc_PrintTime( 1, "Time",  Abc_Clock() - p->clkStart );
+        printf( "Memory:  " );
+        printf( "Gia = %.2f MB  ", Gia_ManMemory(p->pGia) / (1<<20) );
+        printf( "Man = %.2f MB  ", 6.0 * sizeof(int) * Gia_ManObjNum(p->pGia) / (1<<20) );
+        printf( "Cuts = %.2f MB",  Vec_ReportMemory(&p->pMem) / (1<<20) );
+        if ( p->nCoarse )
+        printf( "   Coarse = %d (%.1f %%)",  p->nCoarse, 100.0 * p->nCoarse / Gia_ManObjNum(p->pGia) );
+        printf( "\n" );
+        fflush( stdout );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computing delay/area.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Jf_ManComputeDelay( Jf_Man_t * p, int fEval )
+{
+    Gia_Obj_t * pObj; 
+    int i, Delay = 0;
+    if ( fEval )
+    {
+        Gia_ManForEachObj( p->pGia, pObj, i )
+            if ( Gia_ObjIsBuf(pObj) )
+                Jf_ObjPropagateBuf( p, pObj, 0 );
+            else if ( Gia_ObjIsAnd(pObj) && Gia_ObjRefNum(p->pGia, pObj) > 0 )
+                Vec_IntWriteEntry( &p->vArr, i, Jf_CutArr(p, Jf_ObjCutBest(p, i)) );
+    }
+    Gia_ManForEachCoDriver( p->pGia, pObj, i )
+    {
+        assert( Gia_ObjRefNum(p->pGia, pObj) > 0 );
+        Delay = Abc_MaxInt( Delay, Jf_ObjArr(p, Gia_ObjId(p->pGia, pObj)) );
+    }
+    return Delay;
+}
+int Jf_ManComputeRefs( Jf_Man_t * p )
+{
+    Gia_Obj_t * pObj; 
+    float nRefsNew; int i, * pCut;
+    float * pRefs = Vec_FltArray(&p->vRefs);
+    float * pFlow = Vec_FltArray(&p->vFlow);
+    assert( p->pGia->pRefs != NULL );
+    memset( p->pGia->pRefs, 0, sizeof(int) * Gia_ManObjNum(p->pGia) );
+    p->pPars->Area = p->pPars->Edge = 0;
+    Gia_ManForEachObjReverse( p->pGia, pObj, i )
+    {
+        if ( Gia_ObjIsCo(pObj) || Gia_ObjIsBuf(pObj) )
+            Gia_ObjRefInc( p->pGia, Gia_ObjFanin0(pObj) );
+        else if ( Gia_ObjIsAnd(pObj) && Gia_ObjRefNum(p->pGia, pObj) > 0 )
+        {
+            assert( Jf_ObjIsUnit(pObj) );
+            pCut = Jf_ObjCutBest(p, i);
+            Jf_CutRef( p, pCut );
+            if ( p->pPars->fGenCnf )
+            p->pPars->Clause += Jf_CutCnfSize(p, pCut);
+            p->pPars->Edge += Jf_CutSize(pCut);
+            p->pPars->Area++;
+        }
+    }
+    // blend references and normalize flow
+    for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ )
+    {
+        if ( p->pPars->fOptEdge )
+            nRefsNew = Abc_MaxFloat( 1, 0.8 * pRefs[i] + 0.2 * p->pGia->pRefs[i] );
+        else
+            nRefsNew = Abc_MaxFloat( 1, 0.2 * pRefs[i] + 0.8 * p->pGia->pRefs[i] );
+        pFlow[i] = pFlow[i] * pRefs[i] / nRefsNew;
+        pRefs[i] = nRefsNew;
+        assert( pFlow[i] >= 0 );
+    }
+    // compute delay
+    p->pPars->Delay = Jf_ManComputeDelay( p, 1 );
+    return p->pPars->Area;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Mapping rounds.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Jf_ObjComputeBestCut( Jf_Man_t * p, Gia_Obj_t * pObj, int fEdge, int fEla )
+{
+    int i, iObj = Gia_ObjId( p->pGia, pObj );
+    int * pCuts = Jf_ObjCuts( p, iObj );
+    int * pCut, * pCutBest = NULL;
+    int Time = ABC_INFINITY, TimeBest = ABC_INFINITY;
+    float Area, AreaBest = ABC_INFINITY;
+    Jf_ObjForEachCut( pCuts, pCut, i )
+    {
+        if ( Jf_CutIsTriv(pCut, iObj) ) continue;
+        if ( fEdge && !fEla ) 
+            Jf_CutSetCost(pCut, Jf_CutSize(pCut));
+        Area = fEla ? Jf_CutArea(p, pCut, fEdge) : Jf_CutFlow(p, pCut) + Jf_CutCost(pCut);
+        if ( pCutBest == NULL || AreaBest > Area || (AreaBest == Area && TimeBest > (Time = Jf_CutArr(p, pCut))) )
+            pCutBest = pCut, AreaBest = Area, TimeBest = Time;
+    }
+    Vec_IntWriteEntry( &p->vArr,  iObj, Jf_CutArr(p, pCutBest) );
+    if ( !fEla )
+    Vec_FltWriteEntry( &p->vFlow, iObj, AreaBest / Jf_ObjRefs(p, iObj) );
+    Jf_ObjSetBestCut( pCuts, pCutBest, p->vTemp );
+//    Jf_CutPrint( Jf_ObjCutBest(p, iObj) ); printf( "\n" );
+}
+void Jf_ManPropagateFlow( Jf_Man_t * p, int fEdge )
+{
+    Gia_Obj_t * pObj; 
+    int i;
+    Gia_ManForEachObj( p->pGia, pObj, i )
+        if ( Gia_ObjIsBuf(pObj) )
+            Jf_ObjPropagateBuf( p, pObj, 0 );
+        else if ( Gia_ObjIsAnd(pObj) && Jf_ObjIsUnit(pObj) )
+            Jf_ObjComputeBestCut( p, pObj, fEdge, 0 );
+    Jf_ManComputeRefs( p );
+}
+void Jf_ManPropagateEla( Jf_Man_t * p, int fEdge )
+{
+    Gia_Obj_t * pObj; 
+    int i, CostBef, CostAft;
+    p->pPars->Area = p->pPars->Edge = p->pPars->Clause = 0;
+    Gia_ManForEachObjReverse( p->pGia, pObj, i )
+        if ( Gia_ObjIsBuf(pObj) )
+            Jf_ObjPropagateBuf( p, pObj, 1 );
+        else if ( Gia_ObjIsAnd(pObj) && Gia_ObjRefNum(p->pGia, pObj) > 0 )
+        {
+            assert( Jf_ObjIsUnit(pObj) );
+            if ( Jf_CutCheckMffc(p, Jf_ObjCutBest(p, i), 50) )
+            {
+                CostBef = Jf_CutDeref_rec( p, Jf_ObjCutBest(p, i) );
+                Jf_ObjComputeBestCut( p, pObj, fEdge, 1 );
+                CostAft = Jf_CutRef_rec( p, Jf_ObjCutBest(p, i) );
+    //            if ( CostBef != CostAft )  printf( "%d -> %d   ", CostBef, CostAft );
+                assert( CostBef >= CostAft ); // does not hold because of JF_EDGE_LIM
+            }
+            if ( p->pPars->fGenCnf )
+            p->pPars->Clause += Jf_CutCnfSize(p, Jf_ObjCutBest(p, i));
+            p->pPars->Edge += Jf_CutSize(Jf_ObjCutBest(p, i));
+            p->pPars->Area++;
+        }
+    p->pPars->Delay = Jf_ManComputeDelay( p, 1 );
+//    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the result of mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Jf_ManDeriveMappingGia( Jf_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj; 
+    Vec_Int_t * vCopies   = Vec_IntStartFull( Gia_ManObjNum(p->pGia) );
+    Vec_Int_t * vMapping  = Vec_IntStart( 2 * Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + 2 * (int)p->pPars->Area );
+    Vec_Int_t * vMapping2 = Vec_IntStart( (int)p->pPars->Edge + 2 * (int)p->pPars->Area + 1000 );
+    Vec_Int_t * vCover    = Vec_IntAlloc( 1 << 16 );
+    Vec_Int_t * vLeaves   = Vec_IntAlloc( 16 );
+    Vec_Int_t * vLits = NULL, * vClas = NULL;
+    int i, k, iLit, Class, * pCut;
+    word uTruth = 0, * pTruth = &uTruth;
+    assert( p->pPars->fCutMin );
+    if ( p->pPars->fGenCnf )
+    {
+        vLits = Vec_IntAlloc( 1000 );
+        vClas = Vec_IntAlloc( 1000 );
+        Vec_IntPush( vClas, Vec_IntSize(vLits) );
+        Vec_IntPush( vLits, 1 );
+    }
+    // create new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p->pGia) );
+    pNew->pName = Abc_UtilStrsav( p->pGia->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pGia->pSpec );
+    // map primary inputs
+    Vec_IntWriteEntry( vCopies, 0, 0 );
+    Gia_ManForEachCi( p->pGia, pObj, i )
+        Vec_IntWriteEntry( vCopies, Gia_ObjId(p->pGia, pObj), Gia_ManAppendCi(pNew) );
+    // iterate through nodes used in the mapping
+    Gia_ManForEachAnd( p->pGia, pObj, i )
+    {
+       if ( Gia_ObjIsBuf(pObj) || Gia_ObjRefNum(p->pGia, pObj) == 0 )
+            continue;
+        pCut = Jf_ObjCutBest( p, i );
+//        printf( "Best cut of node %d:  ", i );  Jf_CutPrint(pCut);
+        Class = Jf_CutFuncClass( pCut );
+        if ( Jf_CutSize(pCut) == 0 )
+        {
+            assert( Class == 0 );
+            Vec_IntWriteEntry( vCopies, i, Jf_CutFunc(pCut) );
+            continue;
+        }
+        if ( Jf_CutSize(pCut) == 1 )
+        {
+            assert( Class == 1 );
+            iLit = Abc_LitNotCond( Jf_CutLit(pCut, 1) , Jf_CutFuncCompl(pCut) );
+            iLit = Abc_Lit2LitL( Vec_IntArray(vCopies), iLit );
+            Vec_IntWriteEntry( vCopies, i, iLit );
+            continue;
+        }
+        if ( p->pPars->fFuncDsd )
+            uTruth = Sdm_ManReadDsdTruth(p->pDsd, Class);
+        else
+            pTruth = Vec_MemReadEntry(p->vTtMem, Class);
+        assert( p->pDsd == NULL || Sdm_ManReadDsdVarNum(p->pDsd, Class) == Jf_CutSize(pCut) );
+        // collect leaves
+        Vec_IntClear( vLeaves );
+        Jf_CutForEachLit( pCut, iLit, k )
+            Vec_IntPush( vLeaves, Abc_Lit2LitL(Vec_IntArray(vCopies), iLit) );
+        // create GIA
+        iLit = Kit_TruthToGia( pNew, (unsigned *)pTruth, Vec_IntSize(vLeaves), vCover, vLeaves, 0 );
+        if ( p->pPars->fGenCnf )
+            Jf_ManGenCnf( uTruth, iLit, vLeaves, vLits, vClas, vCover );
+        iLit = Abc_LitNotCond( iLit, Jf_CutFuncCompl(pCut) );
+        Vec_IntWriteEntry( vCopies, i, iLit );
+        // create mapping
+        Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLit), Vec_IntSize(vMapping2) );
+        Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) );
+        Vec_IntForEachEntry( vLeaves, iLit, k )
+            Vec_IntPush( vMapping2, Abc_Lit2Var(iLit) );
+        Vec_IntPush( vMapping2, Abc_Lit2Var(Vec_IntEntry(vCopies, i)) );
+    }
+    Gia_ManForEachCo( p->pGia, pObj, i )
+    {
+        if ( p->pPars->fGenCnf )
+            Vec_IntClear( vLeaves );
+        iLit = Vec_IntEntry( vCopies, Gia_ObjFaninId0p(p->pGia, pObj) );
+        if ( p->pPars->fGenCnf )
+            Vec_IntPush( vLeaves, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) );
+        iLit = Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) );
+        if ( p->pPars->fGenCnf )
+            Jf_ManGenCnf( ABC_CONST(0xAAAAAAAAAAAAAAAA), iLit, vLeaves, vLits, vClas, vCover );
+    }
+    Vec_IntFree( vCopies );
+    Vec_IntFree( vCover );
+    Vec_IntFree( vLeaves );
+    // finish mapping 
+    if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) )
+        Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) );
+    else
+        Vec_IntFillExtra( vMapping, Gia_ManObjNum(pNew), 0 );
+    assert( Vec_IntSize(vMapping) == Gia_ManObjNum(pNew) );
+    Vec_IntForEachEntry( vMapping, iLit, i )
+        if ( iLit > 0 )
+            Vec_IntAddToEntry( vMapping, i, Gia_ManObjNum(pNew) );
+    Vec_IntAppend( vMapping, vMapping2 );
+    Vec_IntFree( vMapping2 );
+    // attach mapping and packing
+    assert( pNew->vMapping == NULL );
+    pNew->vMapping = vMapping;
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p->pGia) );
+    // derive CNF
+    if ( p->pPars->fGenCnf )
+    {
+        if ( p->pPars->fCnfObjIds )
+            pNew->pData = Jf_ManCreateCnf( pNew, vLits, vClas );
+        else
+            pNew->pData = Jf_ManCreateCnfRemap( pNew, vLits, vClas, p->pPars->fAddOrCla );
+    }
+    Vec_IntFreeP( &vLits );
+    Vec_IntFreeP( &vClas );
+    return pNew;
+}
+void Jf_ManDeriveMapping( Jf_Man_t * p )
+{
+    Vec_Int_t * vMapping;
+    Gia_Obj_t * pObj; 
+    int i, k, * pCut;
+    assert( !p->pPars->fCutMin );
+    vMapping = Vec_IntAlloc( Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 );
+    Vec_IntFill( vMapping, Gia_ManObjNum(p->pGia), 0 );
+    Gia_ManForEachAnd( p->pGia, pObj, i )
+    {
+        if ( Gia_ObjIsBuf(pObj) || Gia_ObjRefNum(p->pGia, pObj) == 0 )
+            continue;
+        pCut = Jf_ObjCutBest( p, i );
+        Vec_IntWriteEntry( vMapping, i, Vec_IntSize(vMapping) );
+        assert( !p->pPars->fCutMin || Jf_CutSize(pCut) <= 6 );
+        Vec_IntPush( vMapping, Jf_CutSize(pCut) );
+        for ( k = 1; k <= Jf_CutSize(pCut); k++ )
+            Vec_IntPush( vMapping, Jf_CutVar(pCut, k) );
+        Vec_IntPush( vMapping, i );
+    }
+    assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) );
+    p->pGia->vMapping = vMapping;
+//    Gia_ManMappingVerify( p->pGia );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive GIA without mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Jf_ManDeriveGia( Jf_Man_t * p )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj; 
+    Vec_Int_t * vCopies   = Vec_IntStartFull( Gia_ManObjNum(p->pGia) );
+    Vec_Int_t * vCover    = Vec_IntAlloc( 1 << 16 );
+    Vec_Int_t * vLeaves   = Vec_IntAlloc( 16 );
+    int i, k, iLit, Class, * pCut;
+    int nWords = Abc_Truth6WordNum(p->pPars->nLutSize);
+    word uTruth = 0, * pTruth = &uTruth, Truth[JF_WORD_MAX];
+    // create new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p->pGia) );
+    pNew->pName = Abc_UtilStrsav( p->pGia->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pGia->pSpec );
+    // map primary inputs
+    Vec_IntWriteEntry( vCopies, 0, 0 );
+    Gia_ManForEachCi( p->pGia, pObj, i )
+        Vec_IntWriteEntry( vCopies, Gia_ObjId(p->pGia, pObj), Gia_ManAppendCi(pNew) );
+    // iterate through nodes used in the mapping
+    if ( !p->pPars->fCutMin )
+        Gia_ObjComputeTruthTableStart( p->pGia, p->pPars->nLutSize );
+    Gia_ManHashStart( pNew );
+    Gia_ManForEachAnd( p->pGia, pObj, i )
+    {
+       if ( Gia_ObjIsBuf(pObj) || Gia_ObjRefNum(p->pGia, pObj) == 0 )
+            continue;
+        pCut = Jf_ObjCutBest( p, i );
+//        printf( "Best cut of node %d:  ", i );  Jf_CutPrint(pCut);
+        // get the truth table
+        if ( p->pPars->fCutMin )
+        {
+            Class = Jf_CutFuncClass( pCut );
+            if ( Jf_CutSize(pCut) == 0 )
+            {
+                assert( Class == 0 );
+                Vec_IntWriteEntry( vCopies, i, Jf_CutFunc(pCut) );
+                continue;
+            }
+            if ( Jf_CutSize(pCut) == 1 )
+            {
+                assert( Class == 1 );
+                iLit = Abc_LitNotCond( Jf_CutLit(pCut, 1) , Jf_CutFuncCompl(pCut) );
+                iLit = Abc_Lit2LitL( Vec_IntArray(vCopies), iLit );
+                Vec_IntWriteEntry( vCopies, i, iLit );
+                continue;
+            }
+            if ( p->pPars->fFuncDsd )
+                uTruth = Sdm_ManReadDsdTruth(p->pDsd, Class);
+            else
+                Abc_TtCopy( (pTruth = Truth), Vec_MemReadEntry(p->vTtMem, Class), nWords, 0 );
+            assert( p->pDsd == NULL || Sdm_ManReadDsdVarNum(p->pDsd, Class) == Jf_CutSize(pCut) );
+        }
+        else
+        {
+            Vec_IntClear( vLeaves );
+            Jf_CutForEachLit( pCut, iLit, k )
+                Vec_IntPush( vLeaves, Abc_Lit2Var(iLit) );
+            pTruth = Gia_ObjComputeTruthTableCut( p->pGia, pObj, vLeaves );
+        }
+        // collect incoming literals
+        Vec_IntClear( vLeaves );
+        Jf_CutForEachLit( pCut, iLit, k )
+            Vec_IntPush( vLeaves, Abc_Lit2LitL(Vec_IntArray(vCopies), iLit) );
+        // create GIA
+        iLit = Dsm_ManTruthToGia( pNew, pTruth, vLeaves, vCover );
+        iLit = Abc_LitNotCond( iLit, (p->pPars->fCutMin && Jf_CutFuncCompl(pCut)) );
+        Vec_IntWriteEntry( vCopies, i, iLit );
+    }
+    Gia_ManForEachCo( p->pGia, pObj, i )
+    {
+        iLit = Vec_IntEntry( vCopies, Gia_ObjFaninId0p(p->pGia, pObj) );
+        Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) );
+    }
+    if ( !p->pPars->fCutMin )
+        Gia_ObjComputeTruthTableStop( p->pGia );
+    Vec_IntFree( vCopies );
+    Vec_IntFree( vLeaves );
+    Vec_IntFree( vCover );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p->pGia) );
+//    Dsm_ManReportStats();
+    // perform cleanup
+    if ( !p->pPars->fCutMin )
+    {
+        pNew = Gia_ManCleanup( pTemp = pNew );
+        Gia_ManStop( pTemp );
+    }
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Jf_ManSetDefaultPars( Jf_Par_t * pPars )
+{
+    memset( pPars, 0, sizeof(Jf_Par_t) );
+    pPars->nLutSize     =  6;
+    pPars->nCutNum      =  8;
+    pPars->nRounds      =  1;
+    pPars->nVerbLimit   =  5;
+    pPars->DelayTarget  = -1;
+    pPars->fAreaOnly    =  1;
+    pPars->fOptEdge     =  1; 
+    pPars->fCoarsen     =  0;
+    pPars->fCutMin      =  0;
+    pPars->fFuncDsd     =  0;
+    pPars->fGenCnf      =  0;
+    pPars->fPureAig     =  0;
+    pPars->fVerbose     =  0;
+    pPars->fVeryVerbose =  0;
+    pPars->nLutSizeMax  =  JF_LEAF_MAX;
+    pPars->nCutNumMax   =  JF_CUT_MAX;
+}
+void Jf_ManPrintStats( Jf_Man_t * p, char * pTitle )
+{
+    if ( !p->pPars->fVerbose )
+        return;
+    printf( "%s :  ", pTitle );
+    printf( "Level =%6lu   ", p->pPars->Delay );
+    printf( "Area =%9lu   ",  p->pPars->Area );
+    printf( "Edge =%9lu   ",  p->pPars->Edge );
+    if ( p->pPars->fGenCnf )
+    printf( "Cnf =%9lu   ",   p->pPars->Clause );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
+    fflush( stdout );
+}
+Gia_Man_t * Jf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars )
+{
+    Gia_Man_t * pNew = pGia;
+    Jf_Man_t * p; int i;
+    assert( !pPars->fCutMin || !pPars->fFuncDsd || pPars->nLutSize <= 6 );
+    if ( pPars->fGenCnf )
+        pPars->fCutMin = 1, pPars->fFuncDsd = 1, pPars->fOptEdge = 0;
+    if ( pPars->fCutMin && !pPars->fFuncDsd )
+        pPars->fCoarsen = 0;
+    p = Jf_ManAlloc( pGia, pPars );
+    p->pCutCmp = pPars->fAreaOnly ? Jf_CutCompareArea : Jf_CutCompareDelay;
+    Jf_ManComputeCuts( p, 0 );
+    Jf_ManComputeRefs( p );                         Jf_ManPrintStats( p, "Start" );
+    for ( i = 0; i < pPars->nRounds; i++ )
+    {
+        if ( !p->pPars->fGenCnf )
+        {
+        Jf_ManPropagateFlow( p, pPars->fOptEdge );  Jf_ManPrintStats( p, "Flow " );
+        }
+        Jf_ManPropagateEla( p, 0 );                 Jf_ManPrintStats( p, "Area " );
+        Jf_ManPropagateEla( p, 1 );                 Jf_ManPrintStats( p, "Edge " );
+    }
+    if ( p->pPars->fVeryVerbose && p->pPars->fCutMin && !p->pPars->fFuncDsd )
+        Vec_MemDumpTruthTables( p->vTtMem, Gia_ManName(p->pGia), p->pPars->nLutSize );
+    if ( p->pPars->fPureAig )
+        pNew = Jf_ManDeriveGia(p);
+    else if ( p->pPars->fCutMin )
+        pNew = Jf_ManDeriveMappingGia(p);
+    else
+        Jf_ManDeriveMapping(p);
+    Jf_ManFree( p );
+    return pNew;
+}
+Gia_Man_t * Jf_ManDeriveCnf( Gia_Man_t * p, int fCnfObjIds )
+{
+    Jf_Par_t Pars, * pPars = &Pars;
+    Jf_ManSetDefaultPars( pPars );
+    pPars->fGenCnf = 1;
+    pPars->fCnfObjIds = fCnfObjIds;
+    return Jf_ManPerformMapping( p, pPars );
+}
+Gia_Man_t * Jf_ManDeriveCnfMiter( Gia_Man_t * p, int fVerbose )
+{
+    Jf_Par_t Pars, * pPars = &Pars;
+    Jf_ManSetDefaultPars( pPars );
+    pPars->fGenCnf = 1;
+    pPars->fCnfObjIds = 0;
+    pPars->fAddOrCla = 1;
+    pPars->fVerbose = fVerbose;
+    return Jf_ManPerformMapping( p, pPars );
+}
+void Jf_ManDumpCnf( Gia_Man_t * p, char * pFileName, int fVerbose )
+{
+    abctime clk = Abc_Clock();
+    Gia_Man_t * pNew;
+    Cnf_Dat_t * pCnf;
+    pNew = Jf_ManDeriveCnfMiter( p, fVerbose );
+    pCnf = (Cnf_Dat_t *)pNew->pData; pNew->pData = NULL;
+    Cnf_DataWriteIntoFile( pCnf, pFileName, 0, NULL, NULL );
+    Gia_ManStop( pNew );
+//    if ( fVerbose )
+    {
+        printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    Cnf_DataFree(pCnf);
+}
+
+void Jf_ManTestCnf( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Cnf_Dat_t * pCnf;
+    int i;
+//    Cnf_Dat_t * pCnf = Cnf_DeriveGia( p );
+    pNew = Jf_ManDeriveCnf( p, 1 );
+    pCnf = (Cnf_Dat_t *)pNew->pData; pNew->pData = NULL;
+    Cnf_DataWriteIntoFile( pCnf, "test.cnf", 0, NULL, NULL );
+    for ( i = 0; i < pCnf->nVars; i++ )
+        printf( "%d : %d %d\n", i, pCnf->pObj2Count[i], pCnf->pObj2Clause[i] );
+    Gia_ManStop( pNew );
+    Cnf_DataFree(pCnf);
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaKf.c b/abc-build/src/aig/gia/giaKf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaKf.c
@@ -0,0 +1,1337 @@
+/**CFile****************************************************************
+
+  FileName    [giaKf.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Cut computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaKf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/vec/vecSet.h"
+
+#ifdef ABC_USE_PTHREADS
+
+#ifdef _WIN32
+#include "../lib/pthread.h"
+#else
+#include <pthread.h>
+#include <unistd.h>
+#endif
+
+#endif
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define KF_LEAF_MAX  16
+#define KF_CUT_MAX   32
+#define KF_PROC_MAX  32
+#define KF_WORD_MAX  ((KF_LEAF_MAX > 6) ? 1 << (KF_LEAF_MAX-6) : 1)
+#define KF_LOG_TABLE  8
+
+#define KF_ADD_ON1    2  // offset in cut storage for each node (cut count; best cut)
+#define KF_ADD_ON2    4  // offset in cut storage for each cut (leaf count; function, cut delay; cut area)
+
+typedef struct Kf_Cut_t_ Kf_Cut_t; 
+typedef struct Kf_Set_t_ Kf_Set_t; 
+typedef struct Kf_Man_t_ Kf_Man_t; 
+
+struct Kf_Cut_t_
+{
+    word            Sign;        // signature
+    int             Polar;       // polarity
+    int             Delay;       // delay
+    float           Area;        // area 
+    int             iFunc;       // function 
+    int             iNext;       // next cut
+    int             nLeaves;     // number of leaves
+    int             pLeaves[KF_LEAF_MAX]; 
+};
+struct Kf_Set_t_
+{
+    Kf_Man_t *      pMan;        // manager
+    unsigned short  nLutSize;    // lut size
+    unsigned short  nCutNum;     // cut count
+    int             nCuts0;      // fanin0 cut count
+    int             nCuts1;      // fanin1 cut count
+    int             nCuts;       // resulting cut count
+    int             nTEntries;   // hash table entries 
+    int             TableMask;   // hash table mask
+    int             pTable[1 << KF_LOG_TABLE];
+    int             pValue[1 << KF_LOG_TABLE];
+    int             pPlace[KF_LEAF_MAX];
+    int             pList [KF_LEAF_MAX+1];
+    Kf_Cut_t        pCuts0[KF_CUT_MAX];
+    Kf_Cut_t        pCuts1[KF_CUT_MAX];
+    Kf_Cut_t        pCutsR[KF_CUT_MAX*KF_CUT_MAX];
+    Kf_Cut_t *      ppCuts[KF_CUT_MAX];
+    Kf_Cut_t *      pCutBest;
+    word            CutCount[4]; // statistics
+};
+struct Kf_Man_t_
+{
+    Gia_Man_t *     pGia;        // user's manager
+    Jf_Par_t *      pPars;       // user's parameters
+    Vec_Set_t       pMem;        // cut storage
+    Vec_Int_t       vCuts;       // node params
+    Vec_Int_t       vTime;       // node params
+    Vec_Flt_t       vArea;       // node params
+    Vec_Flt_t       vRefs;       // node params
+    Vec_Int_t *     vTemp;       // temporary
+    abctime         clkStart;    // starting time
+    Kf_Set_t        pSett[KF_PROC_MAX];
+};
+
+static inline int   Kf_SetCutId( Kf_Set_t * p, Kf_Cut_t * pCut )           { return pCut - p->pCutsR;               }
+static inline Kf_Cut_t * Kf_SetCut( Kf_Set_t * p, int i )                  { return i >= 0 ? p->pCutsR + i : NULL;  }
+
+static inline int   Kf_ObjTime( Kf_Man_t * p, int i )                      { return Vec_IntEntry(&p->vTime, i);     }
+static inline float Kf_ObjArea( Kf_Man_t * p, int i )                      { return Vec_FltEntry(&p->vArea, i);     }
+static inline float Kf_ObjRefs( Kf_Man_t * p, int i )                      { return Vec_FltEntry(&p->vRefs, i);     }
+
+static inline void  Kf_ObjSetCuts( Kf_Man_t * p, int i, Vec_Int_t * vVec ) { Vec_IntWriteEntry(&p->vCuts, i, Vec_SetAppend(&p->pMem, Vec_IntArray(vVec), Vec_IntSize(vVec)));  }
+static inline int * Kf_ObjCuts( Kf_Man_t * p, int i )                      { return (int *)Vec_SetEntry(&p->pMem, Vec_IntEntry(&p->vCuts, i));    }
+static inline int * Kf_ObjCuts0( Kf_Man_t * p, int i )                     { return Kf_ObjCuts(p, Gia_ObjFaninId0(Gia_ManObj(p->pGia, i), i));    }
+static inline int * Kf_ObjCuts1( Kf_Man_t * p, int i )                     { return Kf_ObjCuts(p, Gia_ObjFaninId1(Gia_ManObj(p->pGia, i), i));    }
+static inline int * Kf_ObjCutBest( Kf_Man_t * p, int i )                   { int * pCuts = Kf_ObjCuts(p, i); return pCuts + pCuts[1];             }
+
+#define Kf_ObjForEachCutInt( pList, pCut, i )        for ( i = 0, pCut = pList + KF_ADD_ON1; i < pList[0]; i++, pCut += pCut[0] + KF_ADD_ON2 )
+#define Kf_ListForEachCut( p, iList, pCut )          for ( pCut = Kf_SetCut(p, p->pList[iList]); pCut; pCut = Kf_SetCut(p, pCut->iNext) )
+#define Kf_ListForEachCutP( p, iList, pCut, pPlace ) for ( pPlace = p->pList+iList, pCut = Kf_SetCut(p, *pPlace); pCut; pCut = Kf_SetCut(p, *pPlace) )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Kf_SetLoadCuts( Kf_Cut_t * pCuts, int * pIntCuts )
+{
+    Kf_Cut_t * pCut;
+    int k, * pIntCut, nCuts = 0; 
+    Kf_ObjForEachCutInt( pIntCuts, pIntCut, nCuts )
+    {
+        pCut = pCuts + nCuts;
+        pCut->Sign  = 0;
+        pCut->Polar = 0;
+        pCut->iFunc = pIntCut[pIntCut[0] + 1];
+        pCut->Delay = pIntCut[pIntCut[0] + 2];
+        pCut->Area  = Abc_Int2Float(pIntCut[pIntCut[0] + 3]);
+        pCut->nLeaves = pIntCut[0];    
+        for ( k = 0; k < pIntCut[0]; k++ )
+        {
+            pCut->pLeaves[k] = Abc_Lit2Var(pIntCut[k+1]);
+            pCut->Sign |= ((word)1) << (pCut->pLeaves[k] & 0x3F);
+            if ( Abc_LitIsCompl(pIntCut[k+1]) )
+                pCut->Polar |= (1 << k);
+        }
+    }
+    return nCuts;
+}
+static inline void Kf_SetPrepare( Kf_Set_t * p, int * pCuts0, int * pCuts1 )
+{
+    int i;
+    // prepare hash table
+//    for ( i = 0; i <= p->TableMask; i++ )
+//        assert( p->pTable[i] == 0 );
+    // prepare cut storage
+    for ( i = 0; i <= p->nLutSize; i++ )
+        p->pList[i] = -1;
+    // transfer cuts
+    p->nCuts0 = Kf_SetLoadCuts( p->pCuts0, pCuts0 );
+    p->nCuts1 = Kf_SetLoadCuts( p->pCuts1, pCuts1 );
+    p->nCuts = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Kf_ManStoreStart( Vec_Int_t * vTemp, int nCuts )
+{
+    Vec_IntClear( vTemp );
+    Vec_IntPush( vTemp, nCuts );                // cut count
+    Vec_IntPush( vTemp, -1 );                   // best offset
+}
+static inline void Kf_ManStoreAddUnit( Vec_Int_t * vTemp, int iObj, int Time, float Area )
+{
+    Vec_IntAddToEntry( vTemp, 0, 1 );
+    Vec_IntPush( vTemp, 1 );                    // cut size
+    Vec_IntPush( vTemp, Abc_Var2Lit(iObj, 0) ); // leaf
+    Vec_IntPush( vTemp, 2 );                    // function
+    Vec_IntPush( vTemp, Time );                 // delay
+    Vec_IntPush( vTemp, Abc_Float2Int(Area) );  // area
+}
+static inline void Kf_ManSaveResults( Kf_Cut_t ** ppCuts, int nCuts, Kf_Cut_t * pCutBest, Vec_Int_t * vTemp )
+{
+    int i, k;
+    assert( nCuts > 0 && nCuts < KF_CUT_MAX );
+    Kf_ManStoreStart( vTemp, nCuts );
+    for ( i = 0; i < nCuts; i++ )
+    {
+        if ( ppCuts[i] == pCutBest )
+            Vec_IntWriteEntry( vTemp, 1, Vec_IntSize(vTemp) );
+        Vec_IntPush( vTemp, ppCuts[i]->nLeaves );
+//        Vec_IntPushArray( vTemp, ppCuts[i]->pLeaves, ppCuts[i]->nLeaves );
+        for ( k = 0; k < ppCuts[i]->nLeaves; k++ )
+            Vec_IntPush( vTemp, Abc_Var2Lit(ppCuts[i]->pLeaves[k], 0) );
+        Vec_IntPush( vTemp, ppCuts[i]->iFunc );
+        Vec_IntPush( vTemp, ppCuts[i]->Delay );
+        Vec_IntPush( vTemp, Abc_Float2Int(ppCuts[i]->Area) );
+    }
+    assert( Vec_IntEntry(vTemp, 1) > 0 );
+}
+static inline int Kf_SetCompareCuts( Kf_Cut_t * p1, Kf_Cut_t * p2 )
+{
+    if ( p1 == NULL || p2 == NULL )
+        return (p1 != NULL) - (p2 != NULL);
+    if ( p1->nLeaves != p2->nLeaves )
+        return p1->nLeaves - p2->nLeaves;
+    return memcmp( p1->pLeaves, p2->pLeaves, sizeof(int)*p1->nLeaves );
+}
+static inline void Kf_SetAddToList( Kf_Set_t * p, Kf_Cut_t * pCut, int fSort )
+{
+    if ( !fSort )
+        pCut->iNext = p->pList[pCut->nLeaves], p->pList[pCut->nLeaves] = Kf_SetCutId(p, pCut);
+    else
+    {
+        int Value, * pPlace;
+        Kf_Cut_t * pTemp;
+        Vec_IntSelectSort( pCut->pLeaves, pCut->nLeaves );
+        Kf_ListForEachCutP( p, pCut->nLeaves, pTemp, pPlace )
+        {
+            if ( (Value = Kf_SetCompareCuts(pTemp, pCut)) > 0 )
+                break;
+            assert( Value < 0 );
+            pPlace = &pTemp->iNext;
+        }
+        pCut->iNext = *pPlace, *pPlace = Kf_SetCutId(p, pCut);
+    }
+}
+static inline int Kf_CutCompare( Kf_Cut_t * pCut0, Kf_Cut_t * pCut1, int fArea )
+{
+    if ( fArea )
+    {
+        if ( pCut0->Area    < pCut1->Area )    return -1;
+        if ( pCut0->Area    > pCut1->Area )    return  1;
+        if ( pCut0->Delay   < pCut1->Delay )   return -1;
+        if ( pCut0->Delay   > pCut1->Delay )   return  1;
+        if ( pCut0->nLeaves < pCut1->nLeaves ) return -1;
+        if ( pCut0->nLeaves > pCut1->nLeaves ) return  1;
+    }
+    else
+    {
+        if ( pCut0->Delay   < pCut1->Delay )   return -1;
+        if ( pCut0->Delay   > pCut1->Delay )   return  1;
+        if ( pCut0->nLeaves < pCut1->nLeaves ) return -1;
+        if ( pCut0->nLeaves > pCut1->nLeaves ) return  1;
+        if ( pCut0->Area    < pCut1->Area )    return -1;
+        if ( pCut0->Area    > pCut1->Area )    return  1;
+    }
+    return 0;
+}
+static inline int Kf_SetStoreAddOne( Kf_Set_t * p, int nCuts, int nCutNum, Kf_Cut_t * pCut, int fArea )
+{
+    int i;
+    p->ppCuts[nCuts] = pCut;
+    if ( nCuts == 0 )
+        return 1;
+    for ( i = nCuts; i > 0; i-- )
+        if ( Kf_CutCompare(p->ppCuts[i-1], p->ppCuts[i], fArea) > 0 )
+            ABC_SWAP( Kf_Cut_t *, p->ppCuts[i-1], p->ppCuts[i] )
+        else
+            break;
+    return Abc_MinInt( nCuts+1, nCutNum );
+}
+static inline void Kf_SetSelectBest( Kf_Set_t * p, int fArea, int fSort )
+{
+//    int fArea = p->pMan->pPars->fArea;
+    Kf_Cut_t * pCut;
+    int i, nCuts = 0;
+    for ( i = 0; i <= p->nLutSize; i++ )
+        Kf_ListForEachCut( p, i, pCut )
+            nCuts = Kf_SetStoreAddOne( p, nCuts, p->nCutNum-1, pCut, fArea );
+    assert( nCuts > 0 && nCuts < p->nCutNum );
+    p->nCuts = nCuts;
+    p->pCutBest = p->ppCuts[0];
+    if ( !fSort )
+        return;
+    // sort by size in the reverse order
+    for ( i = 0; i <= p->nLutSize; i++ )
+        p->pList[i] = -1;
+    for ( i = 0; i < nCuts; i++ )
+        Kf_SetAddToList( p, p->ppCuts[i], 0 );
+    p->nCuts = 0;
+    for ( i = p->nLutSize; i >= 0; i-- )
+        Kf_ListForEachCut( p, i, pCut )
+            p->ppCuts[p->nCuts++] = pCut;
+    assert( p->nCuts == nCuts );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check correctness of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Kf_CheckCut( Kf_Cut_t * pBase, Kf_Cut_t * pCut ) // check if pCut is contained in pBase
+{
+    int nSizeB = pBase->nLeaves;
+    int nSizeC = pCut->nLeaves;
+    int * pB = pBase->pLeaves;
+    int * pC = pCut->pLeaves;
+    int i, k;
+    for ( i = 0; i < nSizeC; i++ )
+    {
+        for ( k = 0; k < nSizeB; k++ )
+            if ( pC[i] == pB[k] )
+                break;
+        if ( k == nSizeB )
+            return 0;
+    }
+    return 1;
+}
+static inline int Kf_CheckCuts( Kf_Set_t * p )
+{
+    Kf_Cut_t * pCut0, * pCut1; 
+    int i, k, m, n, Value;
+    assert( p->nCuts > 0 );
+    for ( i = 0; i <= p->nLutSize; i++ )
+    Kf_ListForEachCut( p, i, pCut0 )
+    {
+        // check duplicates
+        for ( m = 0; m < pCut0->nLeaves; m++ )
+        for ( n = m+1; n < pCut0->nLeaves; n++ )
+            assert( pCut0->pLeaves[m] != pCut0->pLeaves[n] );
+        // check pairs
+        for ( k = 0; k <= p->nLutSize; k++ )
+        Kf_ListForEachCut( p, k, pCut1 )
+        {
+            if ( pCut0 == pCut1 )
+                continue;
+            // check containments
+            Value = Kf_CheckCut( pCut0, pCut1 );
+            assert( Value == 0 );
+        }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Kf_HashLookup( Kf_Set_t * p, int i )
+{
+    int k;
+    assert( i > 0 );
+    for ( k = i & p->TableMask; p->pTable[k]; k = (k + 1) & p->TableMask )
+        if ( p->pTable[k] == i )
+            return -1;
+    return k;
+}
+static inline int Kf_HashFindOrAdd( Kf_Set_t * p, int i )
+{
+    int k = Kf_HashLookup( p, i );
+    if ( k == -1 )
+        return 0;
+    if ( p->nTEntries == p->nLutSize )
+        return 1;
+    assert( p->pTable[k] == 0 );
+    p->pTable[k] = i;
+    p->pPlace[p->nTEntries] = k;
+    p->pValue[k] = p->nTEntries++;
+    return 0;
+}
+static inline void Kf_HashPopulate( Kf_Set_t * p, Kf_Cut_t * pCut )
+{
+    int i;
+    assert( p->nTEntries == 0 );
+    for ( i = 0; i < pCut->nLeaves; i++ )
+        Kf_HashFindOrAdd( p, pCut->pLeaves[i] );
+    assert( p->nTEntries == pCut->nLeaves );
+}
+static inline void Kf_HashCleanup( Kf_Set_t * p, int iStart )
+{
+    int i;
+    for ( i = iStart; i < p->nTEntries; i++ )
+        p->pTable[p->pPlace[i]] = 0;
+    p->nTEntries = iStart;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cut merging with arbitary order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Kf_SetCountBits( word i )
+{
+    i = i - ((i >> 1) & 0x5555555555555555);
+    i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333);
+    i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F);
+    return (i*(0x0101010101010101))>>56;
+}
+static inline word Kf_SetCutGetSign( Kf_Cut_t * p )
+{
+    word Sign = 0; int i; 
+    for ( i = 0; i < p->nLeaves; i++ )
+        Sign |= ((word)1) << (p->pLeaves[i] & 0x3F);
+    return Sign;
+}
+// returns 1 if the cut in hash table is dominated by the given one
+static inline int Kf_SetCutDominatedByThis( Kf_Set_t * p, Kf_Cut_t * pCut )
+{
+    int i;
+    for ( i = 0; i < pCut->nLeaves; i++ )
+        if ( Kf_HashLookup(p, pCut->pLeaves[i]) >= 0 )
+            return 0;
+    return 1;
+}
+static inline int Kf_SetRemoveDuplicates( Kf_Set_t * p, int nLeaves, word Sign )
+{
+    Kf_Cut_t * pCut; 
+    Kf_ListForEachCut( p, nLeaves, pCut )
+        if ( pCut->Sign == Sign && Kf_SetCutDominatedByThis(p, pCut) )
+            return 1;
+    return 0;
+}
+static inline void Kf_SetFilter( Kf_Set_t * p )
+{
+    Kf_Cut_t * pCut0, * pCut1; 
+    int i, k, * pPlace;
+    assert( p->nCuts > 0 );
+    for ( i = 0; i <= p->nLutSize; i++ )
+        Kf_ListForEachCutP( p, i, pCut0, pPlace )
+        {
+            Kf_HashPopulate( p, pCut0 );
+            for ( k = 0; k < pCut0->nLeaves; k++ )
+                Kf_ListForEachCut( p, k, pCut1 )
+                    if ( (pCut0->Sign & pCut1->Sign) == pCut1->Sign && Kf_SetCutDominatedByThis(p, pCut1) )
+                        { k = pCut0->nLeaves; p->nCuts--; break; }
+            if ( k == pCut0->nLeaves + 1 ) // remove pCut0
+                *pPlace = pCut0->iNext;
+            else
+                pPlace = &pCut0->iNext;
+            Kf_HashCleanup( p, 0 );
+        }
+    assert( p->nCuts > 0 );
+}
+static inline void Kf_SetMergePairs( Kf_Set_t * p, Kf_Cut_t * pCut0, Kf_Cut_t * pCuts, int nCuts, int fArea )
+{
+    Kf_Cut_t * pCut1, * pCutR;  int i;
+    Kf_HashPopulate( p, pCut0 );
+    for ( pCut1 = pCuts; pCut1 < pCuts + nCuts; pCut1++ )
+    {
+        if ( pCut0->nLeaves + pCut1->nLeaves > p->nLutSize && Kf_SetCountBits(pCut0->Sign | pCut1->Sign) > p->nLutSize )
+            continue;
+        Kf_HashCleanup( p, pCut0->nLeaves );
+        for ( i = 0; i < pCut1->nLeaves; i++ )
+            if ( Kf_HashFindOrAdd(p, pCut1->pLeaves[i]) )
+                break;
+        if ( i < pCut1->nLeaves )
+            continue;
+        p->CutCount[1]++;        
+        if ( Kf_SetRemoveDuplicates(p, p->nTEntries, pCut0->Sign | pCut1->Sign) )
+            continue;
+        // create new cut
+        pCutR = p->pCutsR + p->nCuts++;
+        pCutR->nLeaves = p->nTEntries;
+        for ( i = 0; i < p->nTEntries; i++ )
+            pCutR->pLeaves[i] = p->pTable[p->pPlace[i]];
+        pCutR->Sign  = pCut0->Sign | pCut1->Sign;
+        pCutR->Delay = Abc_MaxInt(pCut0->Delay, pCut1->Delay);
+        pCutR->Area  = pCut0->Area + pCut1->Area;
+        // add new cut
+        Kf_SetAddToList( p, pCutR, 0 );
+    }
+    Kf_HashCleanup( p, 0 );
+}
+static inline void Kf_SetMerge( Kf_Set_t * p, int * pCuts0, int * pCuts1, int fArea, int fCutMin )
+{
+    int c0, c1;
+    Kf_SetPrepare( p, pCuts0, pCuts1 );
+    p->CutCount[0] += p->nCuts0 * p->nCuts1;
+//    for ( c0 = 1; c0 < p->nCuts0; c0++ )
+//        assert( p->pCuts0[c0-1].nLeaves >= p->pCuts0[c0].nLeaves );
+    for ( c0 = c1 = 0; c0 < p->nCuts0 && c1 < p->nCuts1; )
+    {
+        if ( p->pCuts0[c0].nLeaves >= p->pCuts1[c1].nLeaves )
+            Kf_SetMergePairs( p, p->pCuts0 + c0++, p->pCuts1 + c1, p->nCuts1 - c1, fArea );
+        else 
+            Kf_SetMergePairs( p, p->pCuts1 + c1++, p->pCuts0 + c0, p->nCuts0 - c0, fArea );
+    }
+    p->CutCount[2] += p->nCuts;        
+    Kf_SetFilter( p );
+//    Kf_CheckCuts( p );
+    p->CutCount[3] += Abc_MinInt( p->nCuts, p->nCutNum-1 );
+    Kf_SetSelectBest( p, fArea, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cut merging with fixed order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Kf_SetCutIsContainedSimple( Kf_Cut_t * pBase, Kf_Cut_t * pCut ) // check if pCut is contained in pBase
+{
+    int nSizeB = pBase->nLeaves;
+    int nSizeC = pCut->nLeaves;
+    int * pB = pBase->pLeaves;
+    int * pC = pCut->pLeaves;
+    int i, k;
+    assert( nSizeB >= nSizeC ); 
+    for ( i = 0; i < nSizeC; i++ )
+    {
+        for ( k = 0; k < nSizeB; k++ )
+            if ( pC[i] == pB[k] )
+                break;
+        if ( k == nSizeB )
+            return 0;
+    }
+    return 1;
+}
+static inline int Kf_SetMergeSimpleOne( Kf_Cut_t * pCut0, Kf_Cut_t * pCut1, Kf_Cut_t * pCut, int nLutSize )
+{ 
+    int nSize0 = pCut0->nLeaves;
+    int nSize1 = pCut1->nLeaves;
+    int * pC0 = pCut0->pLeaves;
+    int * pC1 = pCut1->pLeaves;
+    int * pC = pCut->pLeaves;
+    int i, k, c;
+    // compare two cuts with different numbers
+    c = nSize0;
+    for ( i = 0; i < nSize1; i++ )
+    {
+        for ( k = 0; k < nSize0; k++ )
+            if ( pC1[i] == pC0[k] )
+                break;
+        if ( k < nSize0 )
+            continue;
+        if ( c == nLutSize )
+            return 0;
+        pC[c++] = pC1[i];
+    }
+    for ( i = 0; i < nSize0; i++ )
+        pC[i] = pC0[i];
+    pCut->nLeaves = c;
+    return 1;
+}
+static inline int Kf_SetRemoveDuplicatesSimple( Kf_Set_t * p, Kf_Cut_t * pCutNew )
+{
+    Kf_Cut_t * pCut;
+    Kf_ListForEachCut( p, pCutNew->nLeaves, pCut )
+        if ( pCut->Sign == pCutNew->Sign && Kf_SetCutIsContainedSimple(pCut, pCutNew) )
+            return 1;
+    return 0;
+}
+static inline void Kf_SetFilterSimple( Kf_Set_t * p )
+{
+    Kf_Cut_t * pCut0, * pCut1; 
+    int i, k, * pPlace;
+    assert( p->nCuts > 0 );
+    for ( i = 0; i <= p->nLutSize; i++ )
+        Kf_ListForEachCutP( p, i, pCut0, pPlace )
+        {
+            for ( k = 0; k < pCut0->nLeaves; k++ )
+                Kf_ListForEachCut( p, k, pCut1 )
+                    if ( (pCut0->Sign & pCut1->Sign) == pCut1->Sign && Kf_SetCutIsContainedSimple(pCut0, pCut1) )
+                        { k = pCut0->nLeaves; p->nCuts--; break; }
+            if ( k == pCut0->nLeaves + 1 ) // remove pCut0
+                *pPlace = pCut0->iNext;
+            else
+                pPlace = &pCut0->iNext;
+        }
+    assert( p->nCuts > 0 );
+}
+static inline void Kf_SetMergeSimple( Kf_Set_t * p, int * pCuts0, int * pCuts1, int fArea, int fCutMin )
+{
+    Kf_Cut_t * pCut0, * pCut1, * pCutR;
+    Kf_SetPrepare( p, pCuts0, pCuts1 );
+    p->CutCount[0] += p->nCuts0 * p->nCuts1;
+    for ( pCut0 = p->pCuts0; pCut0 < p->pCuts0 + p->nCuts0; pCut0++ )
+    for ( pCut1 = p->pCuts1; pCut1 < p->pCuts1 + p->nCuts1; pCut1++ )
+    {
+        if ( pCut0->nLeaves + pCut1->nLeaves > p->nLutSize && Kf_SetCountBits(pCut0->Sign | pCut1->Sign) > p->nLutSize )
+            continue;
+        p->CutCount[1]++;        
+        pCutR = p->pCutsR + p->nCuts;
+        if ( !Kf_SetMergeSimpleOne(pCut0, pCut1, pCutR, p->nLutSize) )
+            continue;
+        p->CutCount[2]++;        
+        pCutR->Sign = pCut0->Sign | pCut1->Sign;
+        if ( Kf_SetRemoveDuplicatesSimple(p, pCutR) )
+            continue;
+        p->nCuts++;
+        if ( fCutMin )
+        {
+            int nOldSupp = pCutR->nLeaves;
+//            pCutR->iFunc = Kf_SetComputeTruth( p, pCut0->iFunc, pCut1->iFunc, pCut0, pCut1, pCutR );
+            assert( pCutR->nLeaves <= nOldSupp );
+            if ( pCutR->nLeaves < nOldSupp )
+                pCutR->Sign = Kf_SetCutGetSign( pCutR );
+            // delay and area are inaccurate
+        }
+        assert( pCutR->nLeaves > 1 );
+        pCutR->Delay = Abc_MaxInt(pCut0->Delay, pCut1->Delay);
+        pCutR->Area  = pCut0->Area + pCut1->Area;
+        // add new cut
+        Kf_SetAddToList( p, pCutR, 0 );
+    }
+    Kf_SetFilterSimple( p );
+//    Kf_CheckCuts( p );
+    p->CutCount[3] += Abc_MinInt( p->nCuts, p->nCutNum-1 );
+    Kf_SetSelectBest( p, fArea, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cut merging with fixed order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Kf_SetCutIsContainedOrder( Kf_Cut_t * pBase, Kf_Cut_t * pCut ) // check if pCut is contained in pBase
+{
+    int nSizeB = pBase->nLeaves;
+    int nSizeC = pCut->nLeaves;
+    int i, k;
+    if ( nSizeB == nSizeC )
+    {
+        for ( i = 0; i < nSizeB; i++ )
+            if ( pBase->pLeaves[i] != pCut->pLeaves[i] )
+                return 0;
+        return 1;
+    }
+    assert( nSizeB > nSizeC ); 
+    for ( i = k = 0; i < nSizeB; i++ )
+    {
+        if ( pBase->pLeaves[i] > pCut->pLeaves[k] )
+            return 0;
+        if ( pBase->pLeaves[i] == pCut->pLeaves[k] )
+        {
+            if ( ++k == nSizeC )
+                return 1;
+        }
+    }
+    return 0;
+}
+static inline int Kf_SetMergeOrderOne( Kf_Cut_t * pCut0, Kf_Cut_t * pCut1, Kf_Cut_t * pCut, int nLutSize )
+{ 
+    int nSize0 = pCut0->nLeaves;
+    int nSize1 = pCut1->nLeaves;
+    int * pC0 = pCut0->pLeaves;
+    int * pC1 = pCut1->pLeaves;
+    int * pC = pCut->pLeaves;
+    int i, k, c;
+    // the case of the largest cut sizes
+    if ( nSize0 == nLutSize && nSize1 == nLutSize )
+    {
+        for ( i = 0; i < nSize0; i++ )
+        {
+            if ( pC0[i] != pC1[i] )  return 0;
+            pC[i] = pC0[i];
+        }
+        pCut->nLeaves = nLutSize;
+        return 1;
+    }
+    // compare two cuts with different numbers
+    i = k = c = 0;
+    while ( 1 )
+    {
+        if ( c == nLutSize ) return 0;
+        if ( pC0[i] < pC1[k] )
+        {
+            pC[c++] = pC0[i++];
+            if ( i >= nSize0 ) goto FlushCut1;
+        }
+        else if ( pC0[i] > pC1[k] )
+        {
+            pC[c++] = pC1[k++];
+            if ( k >= nSize1 ) goto FlushCut0;
+        }
+        else
+        {
+            pC[c++] = pC0[i++]; k++;
+            if ( i >= nSize0 ) goto FlushCut1;
+            if ( k >= nSize1 ) goto FlushCut0;
+        }
+    }
+
+FlushCut0:
+    if ( c + nSize0 > nLutSize + i ) return 0;
+    while ( i < nSize0 )
+        pC[c++] = pC0[i++];
+    pCut->nLeaves = c;
+    return 1;
+
+FlushCut1:
+    if ( c + nSize1 > nLutSize + k ) return 0;
+    while ( k < nSize1 )
+        pC[c++] = pC1[k++];
+    pCut->nLeaves = c;
+    return 1;
+}
+static inline int Kf_SetRemoveDuplicatesOrder( Kf_Set_t * p, Kf_Cut_t * pCutNew )
+{
+    Kf_Cut_t * pCut;
+    Kf_ListForEachCut( p, pCutNew->nLeaves, pCut )
+        if ( pCut->Sign == pCutNew->Sign && Kf_SetCutIsContainedOrder(pCut, pCutNew) )
+            return 1;
+    return 0;
+}
+static inline void Kf_SetFilterOrder( Kf_Set_t * p )
+{
+    Kf_Cut_t * pCut0, * pCut1; 
+    int i, k, * pPlace;
+    assert( p->nCuts > 0 );
+    for ( i = 0; i <= p->nLutSize; i++ )
+        Kf_ListForEachCutP( p, i, pCut0, pPlace )
+        {
+            for ( k = 0; k < pCut0->nLeaves; k++ )
+                Kf_ListForEachCut( p, k, pCut1 )
+                    if ( (pCut0->Sign & pCut1->Sign) == pCut1->Sign && Kf_SetCutIsContainedOrder(pCut0, pCut1) )
+                        { k = pCut0->nLeaves; p->nCuts--; break; }
+            if ( k == pCut0->nLeaves + 1 ) // remove pCut0
+                *pPlace = pCut0->iNext;
+            else
+                pPlace = &pCut0->iNext;
+        }
+    assert( p->nCuts > 0 );
+}
+/*
+int Kf_SetComputeTruth( Kf_Man_t * p, int iFuncLit0, int iFuncLit1, int * pCut0, int * pCut1, int * pCutOut )
+{
+    word uTruth[JF_WORD_MAX], uTruth0[JF_WORD_MAX], uTruth1[JF_WORD_MAX];
+    int fCompl, truthId;
+    int LutSize    = p->pPars->nLutSize;
+    int nWords     = Abc_Truth6WordNum(p->pPars->nLutSize);
+    word * pTruth0 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(iFuncLit0));
+    word * pTruth1 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(iFuncLit1));
+    Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(iFuncLit0) );
+    Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(iFuncLit1) );
+    Abc_TtExpand( uTruth0, LutSize, pCut0 + 1, Kf_CutSize(pCut0), pCutOut + 1, Kf_CutSize(pCutOut) );
+    Abc_TtExpand( uTruth1, LutSize, pCut1 + 1, Kf_CutSize(pCut1), pCutOut + 1, Kf_CutSize(pCutOut) );
+    fCompl         = (int)(uTruth0[0] & uTruth1[0] & 1);
+    Abc_TtAnd( uTruth, uTruth0, uTruth1, nWords, fCompl );
+    pCutOut[0]     = Abc_TtMinBase( uTruth, pCutOut + 1, pCutOut[0], LutSize );
+    assert( (uTruth[0] & 1) == 0 );
+    truthId        = Vec_MemHashInsert(p->vTtMem, uTruth);
+    return Abc_Var2Lit( truthId, fCompl );
+}
+*/
+static inline void Kf_SetMergeOrder( Kf_Set_t * p, int * pCuts0, int * pCuts1, int fArea, int fCutMin )
+{
+    Kf_Cut_t * pCut0, * pCut1, * pCutR;
+    Kf_SetPrepare( p, pCuts0, pCuts1 );
+    p->CutCount[0] += p->nCuts0 * p->nCuts1;
+    for ( pCut0 = p->pCuts0; pCut0 < p->pCuts0 + p->nCuts0; pCut0++ )
+    for ( pCut1 = p->pCuts1; pCut1 < p->pCuts1 + p->nCuts1; pCut1++ )
+    {
+        if ( pCut0->nLeaves + pCut1->nLeaves > p->nLutSize && Kf_SetCountBits(pCut0->Sign | pCut1->Sign) > p->nLutSize )
+            continue;
+        p->CutCount[1]++;        
+        pCutR = p->pCutsR + p->nCuts;
+        if ( !Kf_SetMergeOrderOne(pCut0, pCut1, pCutR, p->nLutSize) )
+            continue;
+        p->CutCount[2]++;        
+        pCutR->Sign = pCut0->Sign | pCut1->Sign;
+        if ( Kf_SetRemoveDuplicatesOrder(p, pCutR) )
+            continue;
+        p->nCuts++;
+        if ( fCutMin )
+        {
+            int nOldSupp = pCutR->nLeaves;
+//            pCutR->iFunc = Kf_SetComputeTruth( p, pCut0->iFunc, pCut1->iFunc, pCut0, pCut1, pCutR );
+            assert( pCutR->nLeaves <= nOldSupp );
+            if ( pCutR->nLeaves < nOldSupp )
+                pCutR->Sign = Kf_SetCutGetSign( pCutR );
+            // delay and area are inaccurate
+        }
+        assert( pCutR->nLeaves > 1 );
+        pCutR->Delay = Abc_MaxInt(pCut0->Delay, pCut1->Delay);
+        pCutR->Area  = pCut0->Area + pCut1->Area;
+        // add new cut
+        Kf_SetAddToList( p, pCutR, 0 );
+    }
+    Kf_SetFilterOrder( p );
+//    Kf_CheckCuts( p );
+    p->CutCount[3] += Abc_MinInt( p->nCuts, p->nCutNum-1 );
+    Kf_SetSelectBest( p, fArea, 1 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Cut operations.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int  Kf_CutSize( int * pCut )         { return pCut[0];                          } 
+static inline int  Kf_CutFunc( int * pCut )         { return pCut[pCut[0] + 1];                } 
+static inline int  Kf_CutLeaf( int * pCut, int i )  { assert(i); return Abc_Lit2Var(pCut[i]);  }
+static inline int  Kf_CutTime( Kf_Man_t * p, int * pCut )
+{
+    int i, Time = 0;
+    for ( i = 1; i <= Kf_CutSize(pCut); i++ )
+        Time = Abc_MaxInt( Time, Kf_ObjTime(p, Kf_CutLeaf(pCut, i)) );
+    return Time + 1; 
+}
+static inline void Kf_CutRef( Kf_Man_t * p, int * pCut )
+{
+    int i;
+    for ( i = 1; i <= Kf_CutSize(pCut); i++ )
+        Gia_ObjRefIncId( p->pGia, Kf_CutLeaf(pCut, i) );
+}
+static inline void Kf_CutDeref( Kf_Man_t * p, int * pCut )
+{
+    int i;
+    for ( i = 1; i <= Kf_CutSize(pCut); i++ )
+        Gia_ObjRefDecId( p->pGia, Kf_CutLeaf(pCut, i) );
+}
+static inline void Kf_CutPrint( int * pCut )
+{
+    int i; 
+    printf( "%d {", Kf_CutSize(pCut) );
+    for ( i = 1; i <= Kf_CutSize(pCut); i++ )
+        printf( " %d", Kf_CutLeaf(pCut, i) );
+    printf( " } Func = %d\n", Kf_CutFunc(pCut) );
+}
+static inline void Gia_CutSetPrint( int * pCuts )
+{
+    int i, * pCut; 
+    Kf_ObjForEachCutInt( pCuts, pCut, i )
+        Kf_CutPrint( pCut );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computing delay/area.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kf_ManComputeDelay( Kf_Man_t * p, int fEval )
+{
+    Gia_Obj_t * pObj; 
+    int i, Delay = 0;
+    if ( fEval )
+    {
+        Gia_ManForEachAnd( p->pGia, pObj, i )
+            if ( Gia_ObjRefNum(p->pGia, pObj) > 0 )
+                Vec_IntWriteEntry( &p->vTime, i, Kf_CutTime(p, Kf_ObjCutBest(p, i)) );
+    }
+    Gia_ManForEachCoDriver( p->pGia, pObj, i )
+    {
+        assert( Gia_ObjRefNum(p->pGia, pObj) > 0 );
+        Delay = Abc_MaxInt( Delay, Kf_ObjTime(p, Gia_ObjId(p->pGia, pObj)) );
+    }
+    return Delay;
+}
+int Kf_ManComputeRefs( Kf_Man_t * p )
+{
+    Gia_Obj_t * pObj; 
+    float nRefsNew; int i, * pCut;
+    float * pRefs = Vec_FltArray(&p->vRefs);
+    float * pFlow = Vec_FltArray(&p->vArea);
+    assert( p->pGia->pRefs != NULL );
+    memset( p->pGia->pRefs, 0, sizeof(int) * Gia_ManObjNum(p->pGia) );
+    p->pPars->Area = p->pPars->Edge = 0;
+    Gia_ManForEachObjReverse( p->pGia, pObj, i )
+    {
+        if ( Gia_ObjIsCo(pObj) || Gia_ObjIsBuf(pObj) )
+            Gia_ObjRefInc( p->pGia, Gia_ObjFanin0(pObj) );
+        else if ( Gia_ObjIsAnd(pObj) && Gia_ObjRefNum(p->pGia, pObj) > 0 )
+        {
+            pCut = Kf_ObjCutBest(p, i);
+            Kf_CutRef( p, pCut );
+            p->pPars->Edge += Kf_CutSize(pCut);
+            p->pPars->Area++;
+        }
+    }
+    // blend references and normalize flow
+    for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ )
+    {
+        if ( p->pPars->fOptEdge )
+            nRefsNew = Abc_MaxFloat( 1, 0.8 * pRefs[i] + 0.2 * p->pGia->pRefs[i] );
+        else
+            nRefsNew = Abc_MaxFloat( 1, 0.2 * pRefs[i] + 0.8 * p->pGia->pRefs[i] );
+        pFlow[i] = pFlow[i] * pRefs[i] / nRefsNew;
+        pRefs[i] = nRefsNew;
+        assert( pFlow[i] >= 0 );
+    }
+    // compute delay
+    p->pPars->Delay = Kf_ManComputeDelay( p, 1 );
+    return p->pPars->Area;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+#ifdef ABC_USE_PTHREADS
+#define PAR_THR_MAX 100
+typedef struct Kf_ThData_t_
+{
+    Kf_Set_t *  pSett;
+    int         Id;
+    int         Status;
+    abctime     clkUsed;
+} Kf_ThData_t;
+void * Kf_WorkerThread( void * pArg )
+{
+    Kf_ThData_t * pThData = (Kf_ThData_t *)pArg;
+    Kf_Man_t * pMan = pThData->pSett->pMan;
+    int fAreaOnly = pThData->pSett->pMan->pPars->fAreaOnly;
+    int fCutMin = pThData->pSett->pMan->pPars->fCutMin;
+    volatile int * pPlace = &pThData->Status;
+    abctime clk;
+    while ( 1 )
+    {
+        while ( *pPlace == 0 );
+        assert( pThData->Status == 1 );
+        if ( pThData->Id == -1 )
+        {
+	        pthread_exit( NULL );
+            assert( 0 );
+            return NULL;
+        }
+        assert( pThData->Id >= 0 );
+        clk = Abc_Clock();
+        Kf_SetMergeOrder( pThData->pSett, Kf_ObjCuts0(pMan, pThData->Id), Kf_ObjCuts1(pMan, pThData->Id), fAreaOnly, fCutMin );
+        pThData->clkUsed += Abc_Clock() - clk;
+        pThData->Status = 0;
+//        printf( "Finished object %d\n", pThData->Id );
+    }
+	assert( 0 );
+	return NULL;
+}
+#endif
+Vec_Int_t * Kf_ManCreateFaninCounts( Gia_Man_t * p )  
+{
+    Vec_Int_t * vCounts;
+    Gia_Obj_t * pObj; int i;
+    vCounts = Vec_IntAlloc( Gia_ManObjNum(p) );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            Vec_IntPush( vCounts, 2 - Gia_ObjIsCi(Gia_ObjFanin0(pObj)) - Gia_ObjIsCi(Gia_ObjFanin1(pObj)) );
+        else
+            Vec_IntPush( vCounts, 0 );
+    }
+    assert( Vec_IntSize(vCounts) == Gia_ManObjNum(p) );
+    return vCounts;
+}
+#ifdef ABC_USE_PTHREADS
+void Kf_ManComputeCuts( Kf_Man_t * p )
+{
+	pthread_t WorkerThread[PAR_THR_MAX];
+    Kf_ThData_t ThData[PAR_THR_MAX];
+    Vec_Int_t * vStack, * vFanins;
+    Gia_Obj_t * pObj;
+    int nProcs = p->pPars->nProcNum;
+    int i, k, iFan, status, nCountFanins, fRunning;
+    abctime clk, clkUsed = 0;
+    assert( nProcs <= PAR_THR_MAX );
+    // start fanins
+    vFanins = Kf_ManCreateFaninCounts( p->pGia );
+    Gia_ManStaticFanoutStart( p->pGia );
+    // start the stack
+    vStack = Vec_IntAlloc( 1000 );
+    Gia_ManForEachObjReverse( p->pGia, pObj, k )
+        if ( Gia_ObjIsAnd(pObj) && Vec_IntEntry(vFanins, k) == 0 )
+            Vec_IntPush( vStack, k );
+    // start the threads
+    for ( i = 0; i < nProcs; i++ )
+    {
+        ThData[i].pSett = p->pSett + i;
+        ThData[i].Id = -1;
+        ThData[i].Status = 0;
+        ThData[i].clkUsed = 0;
+        status = pthread_create( WorkerThread + i, NULL, Kf_WorkerThread, (void *)(ThData + i) );  assert( status == 0 );
+    }
+    nCountFanins = Vec_IntSum(vFanins);
+    fRunning = 1;
+    while ( nCountFanins > 0 || Vec_IntSize(vStack) > 0 || fRunning )
+    {
+        for ( i = 0; i < nProcs; i++ )
+        {
+            if ( ThData[i].Status )
+                continue;
+            assert( ThData[i].Status == 0 );
+            if ( ThData[i].Id >= 0 )
+            {
+                int iObj = ThData[i].Id;
+                Kf_Set_t * pSett = p->pSett + i;
+                //printf( "Closing obj %d with Thread %d:\n", iObj, i );
+                clk = Abc_Clock();
+                // finalize the results
+                Kf_ManSaveResults( pSett->ppCuts, pSett->nCuts, pSett->pCutBest, p->vTemp );
+                Vec_IntWriteEntry( &p->vTime, iObj, pSett->pCutBest->Delay + 1 );
+                Vec_FltWriteEntry( &p->vArea, iObj, (pSett->pCutBest->Area + 1)/Kf_ObjRefs(p, iObj) );
+                if ( pSett->pCutBest->nLeaves > 1 )
+                    Kf_ManStoreAddUnit( p->vTemp, iObj, Kf_ObjTime(p, iObj), Kf_ObjArea(p, iObj) );
+                Kf_ObjSetCuts( p, iObj, p->vTemp );
+                //Gia_CutSetPrint( Kf_ObjCuts(p, iObj) );
+                clkUsed += Abc_Clock() - clk;
+                // schedule other nodes
+                Gia_ObjForEachFanoutStaticId( p->pGia, iObj, iFan, k )
+                {
+                    if ( !Gia_ObjIsAnd(Gia_ManObj(p->pGia, iFan)) )
+                        continue;
+                    assert( Vec_IntEntry(vFanins, iFan) > 0 );
+                    if ( Vec_IntAddToEntry(vFanins, iFan, -1) == 0 )
+                        Vec_IntPush( vStack, iFan );
+                    assert( nCountFanins > 0 );
+                    nCountFanins--;
+                }
+                ThData[i].Id = -1;
+            }
+            if ( Vec_IntSize(vStack) > 0 )
+            {
+                ThData[i].Id = Vec_IntPop( vStack );
+                ThData[i].Status = 1;
+                //printf( "Scheduling %d for Thread %d\n", ThData[i].Id, i );
+            }
+        }
+        fRunning = 0;
+        for ( i = 0; i < nProcs; i++ )
+            if ( ThData[i].Status == 1 || (ThData[i].Status == 0 && ThData[i].Id >= 0) )
+                fRunning = 1;
+//        printf( "fRunning %d\n", fRunning );
+    }
+    Vec_IntForEachEntry( vFanins, iFan, k )
+        if ( iFan != 0 )
+        {
+            printf( "%d -> %d    ", k, iFan );
+            Gia_ObjPrint( p->pGia, Gia_ManObj(p->pGia, k) );
+        }
+    assert( Vec_IntSum(vFanins) == 0 );
+    // stop the threads
+    for ( i = 0; i < nProcs; i++ )
+    {
+        assert( ThData[i].Status == 0 );
+        ThData[i].Id = -1;
+        ThData[i].Status = 1;
+    }
+    Gia_ManStaticFanoutStop( p->pGia );
+    Vec_IntFree( vStack );
+    Vec_IntFree( vFanins );
+    if ( !p->pPars->fVerbose )
+        return;
+    // print runtime statistics
+    printf( "Main     : " );
+    Abc_PrintTime( 1, "Time", clkUsed );
+    for ( i = 0; i < nProcs; i++ )
+    {
+        printf( "Thread %d : ", i );
+        Abc_PrintTime( 1, "Time", ThData[i].clkUsed );
+    }
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kf_ManPrintStats( Kf_Man_t * p, char * pTitle )
+{
+    if ( !p->pPars->fVerbose )
+        return;
+    printf( "%s :  ", pTitle );
+    printf( "Level =%6lu   ", p->pPars->Delay );
+    printf( "Area =%9lu   ",  p->pPars->Area );
+    printf( "Edge =%9lu   ",  p->pPars->Edge );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
+    fflush( stdout );
+}
+void Kf_ManComputeMapping( Kf_Man_t * p )
+{
+    Gia_Obj_t * pObj; int i, iPi;
+    if ( p->pPars->fVerbose )
+    {
+        printf( "Aig: CI = %d  CO = %d  AND = %d    ", Gia_ManCiNum(p->pGia), Gia_ManCoNum(p->pGia), Gia_ManAndNum(p->pGia) );
+        printf( "LutSize = %d  CutMax = %d  Threads = %d\n", p->pPars->nLutSize, p->pPars->nCutNum, p->pPars->nProcNum );
+        printf( "Computing cuts...\r" );
+        fflush( stdout );
+    }
+    Gia_ManForEachCi( p->pGia, pObj, iPi )
+    {
+        i = Gia_ObjId(p->pGia, pObj);
+        Kf_ManStoreStart( p->vTemp, 0 );
+        Kf_ManStoreAddUnit( p->vTemp, i, 0, 0 );
+        assert( Vec_IntSize(p->vTemp) == 1 + KF_ADD_ON1 + KF_ADD_ON2 );
+        Kf_ObjSetCuts( p, i, p->vTemp );
+    }
+    if ( p->pPars->nProcNum > 0 )
+        Kf_ManComputeCuts( p );
+    else
+    {
+        Gia_ManForEachAnd( p->pGia, pObj, i )
+        {
+            if ( p->pPars->fCutHashing )
+                Kf_SetMerge( p->pSett, Kf_ObjCuts0(p, i), Kf_ObjCuts1(p, i), p->pPars->fAreaOnly, p->pPars->fCutMin );
+            else if ( p->pPars->fCutSimple )
+                Kf_SetMergeSimple( p->pSett, Kf_ObjCuts0(p, i), Kf_ObjCuts1(p, i), p->pPars->fAreaOnly, p->pPars->fCutMin );
+            else 
+                Kf_SetMergeOrder( p->pSett, Kf_ObjCuts0(p, i), Kf_ObjCuts1(p, i), p->pPars->fAreaOnly, p->pPars->fCutMin );
+            Kf_ManSaveResults( p->pSett->ppCuts, p->pSett->nCuts, p->pSett->pCutBest, p->vTemp );
+            Vec_IntWriteEntry( &p->vTime, i, p->pSett->pCutBest->Delay + 1 );
+            Vec_FltWriteEntry( &p->vArea, i, (p->pSett->pCutBest->Area + 1)/Kf_ObjRefs(p, i) );
+            if ( p->pSett->pCutBest->nLeaves > 1 )
+                Kf_ManStoreAddUnit( p->vTemp, i, Kf_ObjTime(p, i), Kf_ObjArea(p, i) );
+            Kf_ObjSetCuts( p, i, p->vTemp );
+            //Gia_CutSetPrint( Kf_ObjCuts(p, i) );
+        }
+    }
+    Kf_ManComputeRefs( p );
+    if ( p->pPars->fVerbose )
+    {
+        printf( "CutPair = %lu  ", p->pSett->CutCount[0] );
+        printf( "Merge = %lu  ",   p->pSett->CutCount[1] );
+        printf( "Eval = %lu  ",    p->pSett->CutCount[2] );
+        printf( "Cut = %lu  ",     p->pSett->CutCount[3] );
+        Abc_PrintTime( 1, "Time",  Abc_Clock() - p->clkStart );
+        printf( "Memory:  " );
+        printf( "Gia = %.2f MB  ", Gia_ManMemory(p->pGia) / (1<<20) );
+        printf( "Man = %.2f MB  ", 4.0 * sizeof(int) * Gia_ManObjNum(p->pGia) / (1<<20) );
+        printf( "Cuts = %.2f MB  ",Vec_ReportMemory(&p->pMem) / (1<<20) );
+        printf( "Set = %.2f KB  ", 1.0 * sizeof(Kf_Set_t) / (1<<10) );
+        printf( "\n" );
+        fflush( stdout );
+        Kf_ManPrintStats( p, "Start" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kf_ManSetInitRefs( Gia_Man_t * p, Vec_Flt_t * vRefs )
+{
+    Gia_Obj_t * pObj, * pCtrl, * pData0, * pData1; int i;
+    Vec_FltFill( vRefs, Gia_ManObjNum(p), 0 );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        Vec_FltAddToEntry( vRefs, Gia_ObjFaninId0(pObj, i), 1 );
+        Vec_FltAddToEntry( vRefs, Gia_ObjFaninId1(pObj, i), 1 );
+        if ( !Gia_ObjIsMuxType(pObj) )
+            continue;
+        // discount XOR/MUX
+        pCtrl = Gia_ObjRecognizeMux( pObj, &pData1, &pData0 );
+        Vec_FltAddToEntry( vRefs, Gia_ObjId(p, Gia_Regular(pCtrl)), -1 );
+        if ( Gia_Regular(pData0) == Gia_Regular(pData1) )
+            Vec_FltAddToEntry( vRefs, Gia_ObjId(p, Gia_Regular(pData0)), -1 );
+    }
+    Gia_ManForEachCo( p, pObj, i )
+        Vec_FltAddToEntry( vRefs, Gia_ObjFaninId0(pObj, Gia_ObjId(p, pObj)), 1 );
+    for ( i = 0; i < Gia_ManObjNum(p); i++ )
+        Vec_FltUpdateEntry( vRefs, i, 1 );
+}
+Kf_Man_t * Kf_ManAlloc( Gia_Man_t * pGia, Jf_Par_t * pPars )
+{
+    Kf_Man_t * p; int i;
+    assert( pPars->nLutSize <= KF_LEAF_MAX );
+    assert( pPars->nCutNum  <= KF_CUT_MAX  );
+    assert( pPars->nProcNum <= KF_PROC_MAX );
+    Vec_IntFreeP( &pGia->vMapping );
+    p = ABC_CALLOC( Kf_Man_t, 1 );
+    p->clkStart  = Abc_Clock();
+    p->pGia      = pGia;
+    p->pPars     = pPars;
+    Vec_SetAlloc_( &p->pMem, 20 );
+    Vec_IntFill( &p->vCuts, Gia_ManObjNum(pGia), 0 );
+    Vec_IntFill( &p->vTime, Gia_ManObjNum(pGia), 0 );
+    Vec_FltFill( &p->vArea, Gia_ManObjNum(pGia), 0 );
+    Kf_ManSetInitRefs( pGia, &p->vRefs );
+    p->vTemp     = Vec_IntAlloc( 1000 );
+    pGia->pRefs  = ABC_CALLOC( int, Gia_ManObjNum(pGia) );
+    // prepare cut sets
+    for ( i = 0; i < Abc_MaxInt(1, pPars->nProcNum); i++ )
+    {
+        (p->pSett + i)->pMan      = p;
+        (p->pSett + i)->nLutSize  = (unsigned short)pPars->nLutSize;
+        (p->pSett + i)->nCutNum   = (unsigned short)pPars->nCutNum;
+        (p->pSett + i)->TableMask = (1 << KF_LOG_TABLE) - 1;
+    }
+    return p;
+}
+void Kf_ManFree( Kf_Man_t * p )
+{
+    ABC_FREE( p->pGia->pRefs );
+    ABC_FREE( p->vCuts.pArray );
+    ABC_FREE( p->vTime.pArray );
+    ABC_FREE( p->vArea.pArray );
+    ABC_FREE( p->vRefs.pArray );
+    Vec_IntFreeP( &p->vTemp );
+    Vec_SetFree_( &p->pMem );
+    ABC_FREE( p );
+}
+Gia_Man_t * Kf_ManDerive( Kf_Man_t * p )
+{
+    Vec_Int_t * vMapping;
+    Gia_Obj_t * pObj; 
+    int i, k, * pCut;
+    assert( !p->pPars->fCutMin );
+    vMapping = Vec_IntAlloc( Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 );
+    Vec_IntFill( vMapping, Gia_ManObjNum(p->pGia), 0 );
+    Gia_ManForEachAnd( p->pGia, pObj, i )
+    {
+        if ( Gia_ObjIsBuf(pObj) || Gia_ObjRefNum(p->pGia, pObj) == 0 )
+            continue;
+        pCut = Kf_ObjCutBest( p, i );
+        Vec_IntWriteEntry( vMapping, i, Vec_IntSize(vMapping) );
+        Vec_IntPush( vMapping, Kf_CutSize(pCut) );
+        for ( k = 1; k <= Kf_CutSize(pCut); k++ )
+            Vec_IntPush( vMapping, Kf_CutLeaf(pCut, k) );
+        Vec_IntPush( vMapping, i );
+    }
+    assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) );
+    p->pGia->vMapping = vMapping;
+//    Gia_ManMappingVerify( p->pGia );
+    return p->pGia;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kf_ManSetDefaultPars( Jf_Par_t * pPars )
+{
+    memset( pPars, 0, sizeof(Jf_Par_t) );
+    pPars->nLutSize     =  6;
+    pPars->nCutNum      =  8;
+    pPars->nProcNum     =  0;
+    pPars->nRounds      =  1;
+    pPars->nVerbLimit   =  5;
+    pPars->DelayTarget  = -1;
+    pPars->fAreaOnly    =  0;
+    pPars->fOptEdge     =  1; 
+    pPars->fCoarsen     =  0;
+    pPars->fCutMin      =  0;
+    pPars->fFuncDsd     =  0;
+    pPars->fGenCnf      =  0;
+    pPars->fPureAig     =  0;
+    pPars->fCutHashing  =  0;
+    pPars->fCutSimple   =  0;
+    pPars->fVerbose     =  0;
+    pPars->fVeryVerbose =  0;
+    pPars->nLutSizeMax  =  KF_LEAF_MAX;
+    pPars->nCutNumMax   =  KF_CUT_MAX;
+    pPars->nProcNumMax  =  KF_PROC_MAX;
+}
+Gia_Man_t * Kf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars )
+{
+    Kf_Man_t * p;
+    Gia_Man_t * pNew;
+    p = Kf_ManAlloc( pGia, pPars );
+    Kf_ManComputeMapping( p );
+    pNew = Kf_ManDerive( p );
+    Kf_ManFree( p );
+    return pNew;
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaLf.c b/abc-build/src/aig/gia/giaLf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaLf.c
@@ -0,0 +1,66 @@
+/**CFile****************************************************************
+
+  FileName    [giaLf.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Cut computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaLf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/vec/vecSet.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lf_ManSetDefaultPars( Jf_Par_t * pPars )
+{
+    Jf_ManSetDefaultPars( pPars );
+}
+Gia_Man_t * Lf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars )
+{
+    return Jf_ManPerformMapping( pGia, pPars );
+}
+Gia_Man_t * Gia_ManPerformLfMapping( Gia_Man_t * p, Jf_Par_t * pPars, int fNormalized )
+{
+    return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaMan.c b/abc-build/src/aig/gia/giaMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaMan.c
@@ -0,0 +1,726 @@
+/**CFile****************************************************************
+
+  FileName    [giaMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Package manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/tim/tim.h"
+#include "proof/abs/abs.h"
+#include "opt/dar/dar.h"
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManStart( int nObjsMax )
+{
+    Gia_Man_t * p;
+    assert( nObjsMax > 0 );
+    p = ABC_CALLOC( Gia_Man_t, 1 );
+    p->nObjsAlloc = nObjsMax;
+    p->pObjs = ABC_CALLOC( Gia_Obj_t, nObjsMax );
+    p->pObjs->iDiff0 = p->pObjs->iDiff1 = GIA_NONE;
+    p->nObjs = 1;
+    p->vCis  = Vec_IntAlloc( nObjsMax / 20 );
+    p->vCos  = Vec_IntAlloc( nObjsMax / 20 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManStop( Gia_Man_t * p )
+{
+    if ( p->vSeqModelVec )
+        Vec_PtrFreeFree( p->vSeqModelVec );
+    Gia_ManStaticFanoutStop( p );
+    Tim_ManStopP( (Tim_Man_t **)&p->pManTime );
+    assert( p->pManTime == NULL );
+    Vec_PtrFreeFree( p->vNamesIn );
+    Vec_PtrFreeFree( p->vNamesOut );
+    Vec_IntFreeP( &p->vSwitching );
+    Vec_IntFreeP( &p->vSuper );
+    Vec_IntFreeP( &p->vStore );
+    Vec_IntFreeP( &p->vClassNew );
+    Vec_IntFreeP( &p->vClassOld );
+    Vec_WrdFreeP( &p->vSims );
+    Vec_WrdFreeP( &p->vSimsPi );
+    Vec_FltFreeP( &p->vTiming );
+    Vec_VecFreeP( &p->vClockDoms );
+    Vec_IntFreeP( &p->vCofVars );
+    Vec_IntFreeP( &p->vLutConfigs );
+    Vec_IntFreeP( &p->vUserPiIds );
+    Vec_IntFreeP( &p->vUserPoIds );
+    Vec_IntFreeP( &p->vUserFfIds );
+    Vec_IntFreeP( &p->vFlopClasses );
+    Vec_IntFreeP( &p->vGateClasses );
+    Vec_IntFreeP( &p->vObjClasses );
+    Vec_IntFreeP( &p->vInitClasses );
+    Vec_IntFreeP( &p->vDoms );
+    Vec_IntFreeP( &p->vLevels );
+    Vec_IntFreeP( &p->vTruths );
+    Vec_IntFreeP( &p->vTtNums );
+    Vec_IntFreeP( &p->vTtNodes );
+    Vec_WrdFreeP( &p->vTtMemory );
+    Vec_PtrFreeP( &p->vTtInputs );
+    Vec_IntFreeP( &p->vMapping );
+    Vec_IntFreeP( &p->vCellMapping );
+    Vec_IntFreeP( &p->vPacking );
+    Vec_FltFreeP( &p->vInArrs );
+    Vec_FltFreeP( &p->vOutReqs );
+    Gia_ManStopP( &p->pAigExtra );
+    Vec_IntFree( p->vCis );
+    Vec_IntFree( p->vCos );
+    ABC_FREE( p->pData2 );
+    ABC_FREE( p->pTravIds );
+    ABC_FREE( p->pPlacement );
+    ABC_FREE( p->pSwitching );
+    ABC_FREE( p->pCexSeq );
+    ABC_FREE( p->pCexComb );
+    ABC_FREE( p->pIso );
+//    ABC_FREE( p->pMapping );
+    ABC_FREE( p->pFanData );
+    ABC_FREE( p->pReprsOld );
+    ABC_FREE( p->pReprs );
+    ABC_FREE( p->pNexts );
+    ABC_FREE( p->pSibls );
+    ABC_FREE( p->pRefs );
+//    ABC_FREE( p->pNodeRefs );
+    ABC_FREE( p->pHTable );
+    ABC_FREE( p->pMuxes );
+    ABC_FREE( p->pObjs );
+    ABC_FREE( p->pSpec );
+    ABC_FREE( p->pName );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns memory used in megabytes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+double Gia_ManMemory( Gia_Man_t * p )
+{
+    double Memory = sizeof(Gia_Man_t);
+    Memory += sizeof(Gia_Obj_t) * Gia_ManObjNum(p);
+    Memory += sizeof(int) * Gia_ManCiNum(p);
+    Memory += sizeof(int) * Gia_ManCoNum(p);
+    Memory += sizeof(int) * p->nHTable * (p->pHTable != NULL);
+    return Memory;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManStopP( Gia_Man_t ** p )
+{
+    if ( *p == NULL )
+        return;
+    Gia_ManStop( *p );
+    *p = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats for the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintClasses_old( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    if ( p->vFlopClasses == NULL )
+        return;
+    Gia_ManForEachRo( p, pObj, i )
+        Abc_Print( 1, "%d", Vec_IntEntry(p->vFlopClasses, i) );
+    Abc_Print( 1, "\n" );
+
+    {
+        Gia_Man_t * pTemp;
+        pTemp = Gia_ManDupFlopClass( p, 1 );
+        Gia_AigerWrite( pTemp, "dom1.aig", 0, 0 );
+        Gia_ManStop( pTemp );
+        pTemp = Gia_ManDupFlopClass( p, 2 );
+        Gia_AigerWrite( pTemp, "dom2.aig", 0, 0 );
+        Gia_ManStop( pTemp );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats for the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintPlacement( Gia_Man_t * p )
+{
+    int i, nFixed = 0, nUndef = 0;
+    if ( p->pPlacement == NULL )
+        return;
+    for ( i = 0; i < Gia_ManObjNum(p); i++ )
+    {
+        nFixed += p->pPlacement[i].fFixed;
+        nUndef += p->pPlacement[i].fUndef;
+    }
+    Abc_Print( 1, "Placement:  Objects = %8d.  Fixed = %8d.  Undef = %8d.\n", Gia_ManObjNum(p), nFixed, nUndef );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG for unrolling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintTents_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vObjs )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    Vec_IntPush( vObjs, Gia_ObjId(p, pObj) );
+    if ( Gia_ObjIsCi(pObj) )
+        return;
+    Gia_ManPrintTents_rec( p, Gia_ObjFanin0(pObj), vObjs );
+    if ( Gia_ObjIsAnd(pObj) )
+        Gia_ManPrintTents_rec( p, Gia_ObjFanin1(pObj), vObjs );
+}
+void Gia_ManPrintTents( Gia_Man_t * p )
+{
+    Vec_Int_t * vObjs;
+    Gia_Obj_t * pObj;
+    int t, i, iObjId, nSizePrev, nSizeCurr;
+    assert( Gia_ManPoNum(p) > 0 );
+    vObjs = Vec_IntAlloc( 100 );
+    // save constant class
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+    Vec_IntPush( vObjs, 0 );
+    // create starting root
+    nSizePrev = Vec_IntSize(vObjs);
+    Gia_ManForEachPo( p, pObj, i )
+        Gia_ManPrintTents_rec( p, pObj, vObjs );
+    // build tents
+    Abc_Print( 1, "Tents:  " );
+    for ( t = 1; nSizePrev < Vec_IntSize(vObjs); t++ )
+    {
+        int nPis = 0;
+        nSizeCurr = Vec_IntSize(vObjs);
+        Vec_IntForEachEntryStartStop( vObjs, iObjId, i, nSizePrev, nSizeCurr )
+        {
+            nPis += Gia_ObjIsPi(p, Gia_ManObj(p, iObjId));
+            if ( Gia_ObjIsRo(p, Gia_ManObj(p, iObjId)) )
+                Gia_ManPrintTents_rec( p, Gia_ObjRoToRi(p, Gia_ManObj(p, iObjId)), vObjs );
+        }
+        Abc_Print( 1, "%d=%d(%d)  ", t, nSizeCurr - nSizePrev, nPis );
+        nSizePrev = nSizeCurr;
+    }
+    Abc_Print( 1, " Unused=%d\n", Gia_ManObjNum(p) - Vec_IntSize(vObjs) );
+    Vec_IntFree( vObjs );
+    // the remaining objects are PIs without fanout
+//    Gia_ManForEachObj( p, pObj, i )
+//        if ( !Gia_ObjIsTravIdCurrent(p, pObj) )
+//            Gia_ObjPrint( p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintInitClasses( Vec_Int_t * vInits )
+{
+    int i, Value;
+    int Counts[6] = {0};
+    Vec_IntForEachEntry( vInits, Value, i )
+        Counts[Value]++;
+    for ( i = 0; i < 6; i++ )
+        if ( Counts[i] )
+            printf( "%d = %d  ", i, Counts[i] );
+    printf( "  " );
+    printf( "B = %d  ", Counts[0] + Counts[1] );
+    printf( "X = %d  ", Counts[2] + Counts[3] );
+    printf( "Q = %d\n", Counts[4] + Counts[5] );
+    Vec_IntForEachEntry( vInits, Value, i )
+    {
+        Counts[Value]++;
+        if ( Value == 0 )
+            printf( "0" );
+        else if ( Value == 1 )
+            printf( "1" );
+        else if ( Value == 2 )
+            printf( "2" );
+        else if ( Value == 3 )
+            printf( "3" );
+        else if ( Value == 4 )
+            printf( "4" );
+        else if ( Value == 5 )
+            printf( "5" );
+        else assert( 0 );
+    }
+    printf( "\n" );
+    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats for the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintChoiceStats( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, nEquivs = 0, nChoices = 0;
+    Gia_ManMarkFanoutDrivers( p );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        if ( !Gia_ObjSibl(p, i) )
+            continue;
+        nEquivs++;
+        if ( pObj->fMark0 )
+            nChoices++;
+        assert( !Gia_ObjSiblObj(p, i)->fMark0 );
+        assert( Gia_ObjIsAnd(Gia_ObjSiblObj(p, i)) );
+    }
+    Abc_Print( 1, "Choice stats: Equivs =%7d. Choices =%7d.\n", nEquivs, nChoices );
+    Gia_ManCleanMark0( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats for the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars )
+{
+    extern float Gia_ManLevelAve( Gia_Man_t * p );
+    if ( pPars && pPars->fMiter )
+    {
+        Gia_ManPrintStatsMiter( p, 0 );
+        return;
+    }
+#ifdef WIN32
+    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 15 ); // bright
+    if ( p->pName )
+        Abc_Print( 1, "%-8s : ", p->pName );
+    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 );  // normal
+#else
+    if ( p->pName )
+        Abc_Print( 1, "%s%-8s%s : ", "\033[1;37m", p->pName, "\033[0m" );  // bright
+#endif
+    Abc_Print( 1, "i/o =%7d/%7d", Gia_ManPiNum(p), Gia_ManPoNum(p) );
+    if ( Gia_ManConstrNum(p) )
+        Abc_Print( 1, "(c=%d)", Gia_ManConstrNum(p) );
+    if ( Gia_ManRegNum(p) )
+        Abc_Print( 1, "  ff =%7d", Gia_ManRegNum(p) );
+
+#ifdef WIN32
+    {
+    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+    SetConsoleTextAttribute( hConsole, 11 ); // blue
+    Abc_Print( 1, "  %s =%8d", p->pMuxes? "nod" : "and", Gia_ManAndNum(p) );
+    SetConsoleTextAttribute( hConsole, 13 ); // magenta
+    Abc_Print( 1, "  lev =%5d", Gia_ManLevelNum(p) ); 
+    Abc_Print( 1, " (%.2f)", Gia_ManLevelAve(p) ); 
+    SetConsoleTextAttribute( hConsole, 7 ); // normal
+    }
+#else
+    Abc_Print( 1, "  %s%s =%8d%s",  "\033[1;36m", p->pMuxes? "nod" : "and", Gia_ManAndNum(p), "\033[0m" ); // blue
+    Abc_Print( 1, "  %slev =%5d%s", "\033[1;35m", Gia_ManLevelNum(p), "\033[0m" ); // magenta
+    Abc_Print( 1, " %s(%.2f)%s",    "\033[1;35m", Gia_ManLevelAve(p), "\033[0m" ); 
+#endif
+    Vec_IntFreeP( &p->vLevels );
+    if ( pPars && pPars->fCut )
+        Abc_Print( 1, "  cut = %d(%d)", Gia_ManCrossCut(p, 0), Gia_ManCrossCut(p, 1) );
+    Abc_Print( 1, "  mem =%5.2f MB", Gia_ManMemory(p)/(1<<20) );
+    if ( Gia_ManHasChoices(p) )
+        Abc_Print( 1, "  ch =%5d", Gia_ManChoiceNum(p) );
+    if ( pPars && pPars->fMuxXor )
+        printf( "\nXOR/MUX " ), Gia_ManPrintMuxStats( p );
+    if ( pPars && pPars->fSwitch )
+    {
+        static int nPiPo = 0;
+        static float PrevSwiTotal = 0;
+        float SwiTotal = Gia_ManComputeSwitching( p, 48, 16, 0 );
+        Abc_Print( 1, "  power =%8.1f", SwiTotal );
+        if ( PrevSwiTotal > 0 && nPiPo == Gia_ManCiNum(p) + Gia_ManCoNum(p) )
+            Abc_Print( 1, " %6.2f %%", 100.0*(PrevSwiTotal-SwiTotal)/PrevSwiTotal );
+        else if ( PrevSwiTotal == 0 || nPiPo != Gia_ManCiNum(p) + Gia_ManCoNum(p) )
+            PrevSwiTotal = SwiTotal, nPiPo = Gia_ManCiNum(p) + Gia_ManCoNum(p);
+    }
+//    Abc_Print( 1, "obj =%5d  ", Gia_ManObjNum(p) );
+    Abc_Print( 1, "\n" );
+
+//    Gia_ManSatExperiment( p );
+    if ( p->pReprs && p->pNexts )
+        Gia_ManEquivPrintClasses( p, 0, 0.0 );
+    if ( Gia_ManHasMapping(p) && (pPars == NULL || !pPars->fSkipMap) )
+        Gia_ManPrintMappingStats( p, pPars ? pPars->pDumpFile : NULL );
+    if ( pPars && pPars->fNpn && Gia_ManHasMapping(p) && Gia_ManLutSizeMax(p) <= 4 )
+        Gia_ManPrintNpnClasses( p );
+    if ( p->vPacking )
+        Gia_ManPrintPackingStats( p );
+    if ( pPars && pPars->fLutProf && Gia_ManHasMapping(p) )
+        Gia_ManPrintLutStats( p );
+    if ( p->pPlacement )
+        Gia_ManPrintPlacement( p );
+    if ( p->pManTime )
+        Tim_ManPrintStats( (Tim_Man_t *)p->pManTime, p->nAnd2Delay );
+    // print register classes
+    Gia_ManPrintFlopClasses( p );
+    Gia_ManPrintGateClasses( p );
+    Gia_ManPrintObjClasses( p );
+    if ( p->vInitClasses )
+        Gia_ManPrintInitClasses( p->vInitClasses );
+    if ( pPars && pPars->fTents )
+    {
+/*
+        int k, Entry, Prev = 1;
+        Vec_Int_t * vLimit = Vec_IntAlloc( 1000 );
+        Gia_Man_t * pNew = Gia_ManUnrollDup( p, vLimit );
+        Abc_Print( 1, "Tents:  " );
+        Vec_IntForEachEntryStart( vLimit, Entry, k, 1 )
+            Abc_Print( 1, "%d=%d  ", k, Entry-Prev ), Prev = Entry;
+        Abc_Print( 1, " Unused=%d.", Gia_ManObjNum(p) - Gia_ManObjNum(pNew) );
+        Abc_Print( 1, "\n" );
+        Vec_IntFree( vLimit );
+        Gia_ManStop( pNew );
+*/
+        Gia_ManPrintTents( p );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats for the AIG.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintStatsShort( Gia_Man_t * p )
+{
+    Abc_Print( 1, "i/o =%7d/%7d  ", Gia_ManPiNum(p), Gia_ManPoNum(p) );
+    Abc_Print( 1, "ff =%7d  ", Gia_ManRegNum(p) );
+    Abc_Print( 1, "and =%8d  ", Gia_ManAndNum(p) );
+    Abc_Print( 1, "lev =%5d  ", Gia_ManLevelNum(p) );
+//    Abc_Print( 1, "mem =%5.2f MB", 12.0*Gia_ManObjNum(p)/(1<<20) );
+    Abc_Print( 1, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats for the AIG.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintMiterStatus( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pChild;
+    int i, nSat = 0, nUnsat = 0, nUndec = 0, iOut = -1;
+    Gia_ManForEachPo( p, pObj, i )
+    {
+        pChild = Gia_ObjChild0(pObj);
+        // check if the output is constant 0
+        if ( pChild == Gia_ManConst0(p) )
+            nUnsat++;
+        // check if the output is constant 1
+        else if ( pChild == Gia_ManConst1(p) )
+        {
+            nSat++;
+            if ( iOut == -1 )
+                iOut = i;
+        }
+        // check if the output is a primary input
+        else if ( Gia_ObjIsPi(p, Gia_Regular(pChild)) )
+        {
+            nSat++;
+            if ( iOut == -1 )
+                iOut = i;
+        }
+/*
+        // check if the output is 1 for the 0000 pattern
+        else if ( Gia_Regular(pChild)->fPhase != (unsigned)Gia_IsComplement(pChild) )
+        {
+            nSat++;
+            if ( iOut == -1 )
+                iOut = i;
+        }
+*/
+        else
+            nUndec++;
+    }
+    Abc_Print( 1, "Outputs = %7d.  Unsat = %7d.  Sat = %7d.  Undec = %7d.\n",
+        Gia_ManPoNum(p), nUnsat, nSat, nUndec );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Statistics of the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintStatsMiter( Gia_Man_t * p, int fVerbose )
+{
+    Gia_Obj_t * pObj;
+    Vec_Flt_t * vProb;
+    int i, iObjId;
+    Gia_ManLevelNum( p );
+    Gia_ManCreateRefs( p );
+    vProb = Gia_ManPrintOutputProb( p );
+    printf( "Statistics for each outputs of the miter:\n" );
+    Gia_ManForEachPo( p, pObj, i )
+    {
+        iObjId = Gia_ObjId(p, pObj);
+        printf( "%4d : ", i );
+        printf( "Level = %5d  ",  Gia_ObjLevelId(p, iObjId) );
+        printf( "Supp = %5d  ",   Gia_ManSuppSize(p, &iObjId, 1) );
+        printf( "Cone = %5d  ",   Gia_ManConeSize(p, &iObjId, 1) );
+        printf( "Mffc = %5d  ",   Gia_NodeMffcSize(p, Gia_ObjFanin0(pObj)) );
+        printf( "Prob = %8.4f  ", Vec_FltEntry(vProb, iObjId) );
+        printf( "\n" );
+    }
+    Vec_FltFree( vProb );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats for the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSetRegNum( Gia_Man_t * p, int nRegs )
+{
+    assert( p->nRegs == 0 );
+    p->nRegs = nRegs;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reports the reduction of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManReportImprovement( Gia_Man_t * p, Gia_Man_t * pNew )
+{
+    Abc_Print( 1, "REG: Beg = %5d. End = %5d. (R =%5.1f %%)  ",
+        Gia_ManRegNum(p), Gia_ManRegNum(pNew),
+        Gia_ManRegNum(p)? 100.0*(Gia_ManRegNum(p)-Gia_ManRegNum(pNew))/Gia_ManRegNum(p) : 0.0 );
+    Abc_Print( 1, "AND: Beg = %6d. End = %6d. (R =%5.1f %%)",
+        Gia_ManAndNum(p), Gia_ManAndNum(pNew),
+        Gia_ManAndNum(p)? 100.0*(Gia_ManAndNum(p)-Gia_ManAndNum(pNew))/Gia_ManAndNum(p) : 0.0 );
+    Abc_Print( 1, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints NPN class statistics.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintNpnClasses( Gia_Man_t * p )
+{
+    extern char ** Kit_DsdNpn4ClassNames();
+    char ** pNames = Kit_DsdNpn4ClassNames();
+    Vec_Int_t * vLeaves, * vTruth, * vVisited;
+    int * pLutClass, ClassCounts[222] = {0};
+    int i, k, iFan, Class, OtherClasses, OtherClasses2, nTotal, Counter, Counter2;
+    unsigned * pTruth;
+    assert( Gia_ManHasMapping(p) );
+    assert(  Gia_ManLutSizeMax( p ) <= 4 );
+    vLeaves   = Vec_IntAlloc( 100 );
+    vVisited  = Vec_IntAlloc( 100 );
+    vTruth    = Vec_IntAlloc( (1<<16) );
+    pLutClass = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    Gia_ManCleanTruth( p );
+    Gia_ManForEachLut( p, i )
+    {
+        if ( Gia_ObjLutSize(p,i) > 4 )
+            continue;
+        Vec_IntClear( vLeaves );
+        Gia_LutForEachFanin( p, i, iFan, k )
+            Vec_IntPush( vLeaves, iFan );
+        for ( ; k < 4; k++ )
+            Vec_IntPush( vLeaves, 0 );
+        pTruth = Gia_ManConvertAigToTruth( p, Gia_ManObj(p, i), vLeaves, vTruth, vVisited );
+        Class = Dar_LibReturnClass( *pTruth );
+        ClassCounts[ Class ]++;
+        pLutClass[i] = Class;
+    }
+    Vec_IntFree( vLeaves );
+    Vec_IntFree( vTruth );
+    Vec_IntFree( vVisited );
+    Vec_IntFreeP( &p->vTruths );
+    nTotal = 0;
+    for ( i = 0; i < 222; i++ )
+        nTotal += ClassCounts[i];
+    Abc_Print( 1, "NPN CLASS STATISTICS (for %d LUT4 present in the current mapping):\n", nTotal );
+    OtherClasses = 0;
+    for ( i = 0; i < 222; i++ )
+    {
+        if ( ClassCounts[i] == 0 )
+            continue;
+//        if ( 100.0 * ClassCounts[i] / (nTotal+1) < 0.1 ) // do not show anything below 0.1 percent
+//            continue;
+        OtherClasses += ClassCounts[i];
+        Abc_Print( 1, "Class %3d :  Count = %6d   (%7.2f %%)   %s\n", 
+            i, ClassCounts[i], 100.0 * ClassCounts[i] / (nTotal+1), pNames[i] );
+    }
+    OtherClasses = nTotal - OtherClasses;
+    Abc_Print( 1, "Other     :  Count = %6d   (%7.2f %%)\n", 
+        OtherClasses, 100.0 * OtherClasses / (nTotal+1) );
+    // count the number of LUTs that have MUX function and two fanins with MUX functions
+    OtherClasses = OtherClasses2 = 0;
+    ABC_FREE( p->pRefs );
+    Gia_ManSetRefsMapped( p );
+    Gia_ManForEachLut( p, i )
+    {
+        if ( pLutClass[i] != 109 )
+            continue;
+        Counter = Counter2 = 0;
+        Gia_LutForEachFanin( p, i, iFan, k )
+        {
+            Counter  += (pLutClass[iFan] == 109);
+            Counter2 += (pLutClass[iFan] == 109) && (Gia_ObjRefNumId(p, iFan) == 1);
+        }
+        OtherClasses  += (Counter > 1);
+        OtherClasses2 += (Counter2 > 1);
+//            Abc_Print( 1, "%d -- ", pLutClass[i] );
+//            Gia_LutForEachFanin( p, i, iFan, k )
+//                Abc_Print( 1, "%d ", pLutClass[iFan] );
+//            Abc_Print( 1, "\n" );
+    }
+    ABC_FREE( p->pRefs );
+    Abc_Print( 1, "Approximate number of 4:1 MUX structures: All = %6d  (%7.2f %%)  MFFC = %6d  (%7.2f %%)\n", 
+        OtherClasses,  100.0 * OtherClasses  / (nTotal+1),
+        OtherClasses2, 100.0 * OtherClasses2 / (nTotal+1) );
+    ABC_FREE( pLutClass );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/aig/gia/giaMem.c b/abc-build/src/aig/gia/giaMem.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaMem.c
@@ -0,0 +1,598 @@
+/**CFile****************************************************************
+
+  FileName    [giaMem.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Memory managers.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: giaMem.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+struct Gia_MmFixed_t_
+{
+    // information about individual entries
+    int           nEntrySize;    // the size of one entry
+    int           nEntriesAlloc; // the total number of entries allocated
+    int           nEntriesUsed;  // the number of entries in use
+    int           nEntriesMax;   // the max number of entries in use
+    char *        pEntriesFree;  // the linked list of free entries
+
+    // this is where the memory is stored
+    int           nChunkSize;    // the size of one chunk
+    int           nChunksAlloc;  // the maximum number of memory chunks 
+    int           nChunks;       // the current number of memory chunks 
+    char **       pChunks;       // the allocated memory
+
+    // statistics
+    int           nMemoryUsed;   // memory used in the allocated entries
+    int           nMemoryAlloc;  // memory allocated
+};
+
+struct Gia_MmFlex_t_
+{
+    // information about individual entries
+    int           nEntriesUsed;  // the number of entries allocated
+    char *        pCurrent;      // the current pointer to free memory
+    char *        pEnd;          // the first entry outside the free memory
+
+    // this is where the memory is stored
+    int           nChunkSize;    // the size of one chunk
+    int           nChunksAlloc;  // the maximum number of memory chunks 
+    int           nChunks;       // the current number of memory chunks 
+    char **       pChunks;       // the allocated memory
+
+    // statistics
+    int           nMemoryUsed;   // memory used in the allocated entries
+    int           nMemoryAlloc;  // memory allocated
+};
+
+struct Gia_MmStep_t_
+{
+    int               nMems;    // the number of fixed memory managers employed
+    Gia_MmFixed_t **  pMems;    // memory managers: 2^1 words, 2^2 words, etc
+    int               nMapSize; // the size of the memory array
+    Gia_MmFixed_t **  pMap;     // maps the number of bytes into its memory manager
+    // additional memory chunks
+    int           nChunksAlloc;  // the maximum number of memory chunks 
+    int           nChunks;       // the current number of memory chunks 
+    char **       pChunks;       // the allocated memory
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates memory pieces of fixed size.]
+
+  Description [The size of the chunk is computed as the minimum of
+  1024 entries and 64K. Can only work with entry size at least 4 byte long.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_MmFixed_t * Gia_MmFixedStart( int nEntrySize, int nEntriesMax )
+{
+    Gia_MmFixed_t * p;
+
+    p = ABC_ALLOC( Gia_MmFixed_t, 1 );
+    memset( p, 0, sizeof(Gia_MmFixed_t) );
+
+    p->nEntrySize    = nEntrySize;
+    p->nEntriesAlloc = 0;
+    p->nEntriesUsed  = 0;
+    p->pEntriesFree  = NULL;
+
+    p->nChunkSize = nEntriesMax / 8;
+    if ( p->nChunkSize < 8 )
+        p->nChunkSize = 8;
+
+    p->nChunksAlloc  = 64;
+    p->nChunks       = 0;
+    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
+
+    p->nMemoryUsed   = 0;
+    p->nMemoryAlloc  = 0;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_MmFixedStop( Gia_MmFixed_t * p, int fVerbose )
+{
+    int i;
+    if ( p == NULL )
+        return;
+    if ( fVerbose )
+    {
+        printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n",
+            p->nEntrySize, p->nChunkSize, p->nChunks );
+        printf( "   Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n",
+            p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc );
+    }
+    for ( i = 0; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    ABC_FREE( p->pChunks );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Gia_MmFixedEntryFetch( Gia_MmFixed_t * p )
+{
+    char * pTemp;
+    int i;
+
+    // check if there are still free entries
+    if ( p->nEntriesUsed == p->nEntriesAlloc )
+    { // need to allocate more entries
+        assert( p->pEntriesFree == NULL );
+        if ( p->nChunks == p->nChunksAlloc )
+        {
+            p->nChunksAlloc *= 2;
+            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
+        }
+        p->pEntriesFree = ABC_ALLOC( char, p->nEntrySize * p->nChunkSize );
+        p->nMemoryAlloc += p->nEntrySize * p->nChunkSize;
+        // transform these entries into a linked list
+        pTemp = p->pEntriesFree;
+        for ( i = 1; i < p->nChunkSize; i++ )
+        {
+            *((char **)pTemp) = pTemp + p->nEntrySize;
+            pTemp += p->nEntrySize;
+        }
+        // set the last link
+        *((char **)pTemp) = NULL;
+        // add the chunk to the chunk storage
+        p->pChunks[ p->nChunks++ ] = p->pEntriesFree;
+        // add to the number of entries allocated
+        p->nEntriesAlloc += p->nChunkSize;
+    }
+    // incrememt the counter of used entries
+    p->nEntriesUsed++;
+    if ( p->nEntriesMax < p->nEntriesUsed )
+        p->nEntriesMax = p->nEntriesUsed;
+    // return the first entry in the free entry list
+    pTemp = p->pEntriesFree;
+    p->pEntriesFree = *((char **)pTemp);
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_MmFixedEntryRecycle( Gia_MmFixed_t * p, char * pEntry )
+{
+    // decrement the counter of used entries
+    p->nEntriesUsed--;
+    // add the entry to the linked list of free entries
+    *((char **)pEntry) = p->pEntriesFree;
+    p->pEntriesFree = pEntry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description [Relocates all the memory except the first chunk.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_MmFixedRestart( Gia_MmFixed_t * p )
+{
+    int i;
+    char * pTemp;
+    if ( p->nChunks == 0 )
+        return;
+    // deallocate all chunks except the first one
+    for ( i = 1; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    p->nChunks = 1;
+    // transform these entries into a linked list
+    pTemp = p->pChunks[0];
+    for ( i = 1; i < p->nChunkSize; i++ )
+    {
+        *((char **)pTemp) = pTemp + p->nEntrySize;
+        pTemp += p->nEntrySize;
+    }
+    // set the last link
+    *((char **)pTemp) = NULL;
+    // set the free entry list
+    p->pEntriesFree  = p->pChunks[0];
+    // set the correct statistics
+    p->nMemoryAlloc  = p->nEntrySize * p->nChunkSize;
+    p->nMemoryUsed   = 0;
+    p->nEntriesAlloc = p->nChunkSize;
+    p->nEntriesUsed  = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_MmFixedReadMemUsage( Gia_MmFixed_t * p )
+{
+    return p->nMemoryAlloc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_MmFixedReadMaxEntriesUsed( Gia_MmFixed_t * p )
+{
+    return p->nEntriesMax;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates entries of flexible size.]
+
+  Description [Can only work with entry size at least 4 byte long.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_MmFlex_t * Gia_MmFlexStart()
+{
+    Gia_MmFlex_t * p;
+
+    p = ABC_ALLOC( Gia_MmFlex_t, 1 );
+    memset( p, 0, sizeof(Gia_MmFlex_t) );
+
+    p->nEntriesUsed  = 0;
+    p->pCurrent      = NULL;
+    p->pEnd          = NULL;
+
+    p->nChunkSize    = (1 << 18);
+    p->nChunksAlloc  = 64;
+    p->nChunks       = 0;
+    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
+
+    p->nMemoryUsed   = 0;
+    p->nMemoryAlloc  = 0;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_MmFlexStop( Gia_MmFlex_t * p, int fVerbose )
+{
+    int i;
+    if ( p == NULL )
+        return;
+    if ( fVerbose )
+    {
+        printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n",
+            p->nChunkSize, p->nChunks );
+        printf( "   Entries used = %d. Memory used = %d. Memory alloc = %d.\n",
+            p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc );
+    }
+    for ( i = 0; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    ABC_FREE( p->pChunks );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Gia_MmFlexEntryFetch( Gia_MmFlex_t * p, int nBytes )
+{
+    char * pTemp;
+    // check if there are still free entries
+    if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd )
+    { // need to allocate more entries
+        if ( p->nChunks == p->nChunksAlloc )
+        {
+            p->nChunksAlloc *= 2;
+            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
+        }
+        if ( nBytes > p->nChunkSize )
+        {
+            // resize the chunk size if more memory is requested than it can give
+            // (ideally, this should never happen)
+            p->nChunkSize = 2 * nBytes;
+        }
+        p->pCurrent = ABC_ALLOC( char, p->nChunkSize );
+        p->pEnd     = p->pCurrent + p->nChunkSize;
+        p->nMemoryAlloc += p->nChunkSize;
+        // add the chunk to the chunk storage
+        p->pChunks[ p->nChunks++ ] = p->pCurrent;
+    }
+    assert( p->pCurrent + nBytes <= p->pEnd );
+    // increment the counter of used entries
+    p->nEntriesUsed++;
+    // keep track of the memory used
+    p->nMemoryUsed += nBytes;
+    // return the next entry
+    pTemp = p->pCurrent;
+    p->pCurrent += nBytes;
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description [Relocates all the memory except the first chunk.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_MmFlexRestart( Gia_MmFlex_t * p )
+{
+    int i;
+    if ( p->nChunks == 0 )
+        return;
+    // deallocate all chunks except the first one
+    for ( i = 1; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    p->nChunks  = 1;
+    p->nMemoryAlloc = p->nChunkSize;
+    // transform these entries into a linked list
+    p->pCurrent = p->pChunks[0];
+    p->pEnd     = p->pCurrent + p->nChunkSize;
+    p->nEntriesUsed = 0;
+    p->nMemoryUsed = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_MmFlexReadMemUsage( Gia_MmFlex_t * p )
+{
+    return p->nMemoryUsed;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the hierarchical memory manager.]
+
+  Description [This manager can allocate entries of any size.
+  Iternally they are mapped into the entries with the number of bytes
+  equal to the power of 2. The smallest entry size is 8 bytes. The
+  next one is 16 bytes etc. So, if the user requests 6 bytes, he gets 
+  8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc.
+  The input parameters "nSteps" says how many fixed memory managers
+  are employed internally. Calling this procedure with nSteps equal
+  to 10 results in 10 hierarchically arranged internal memory managers, 
+  which can allocate up to 4096 (1Kb) entries. Requests for larger 
+  entries are handed over to malloc() and then ABC_FREE()ed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_MmStep_t * Gia_MmStepStart( int nSteps )
+{
+    Gia_MmStep_t * p;
+    int i, k;
+    p = ABC_ALLOC( Gia_MmStep_t, 1 );
+    memset( p, 0, sizeof(Gia_MmStep_t) );
+    p->nMems = nSteps;
+    // start the fixed memory managers
+    p->pMems = ABC_ALLOC( Gia_MmFixed_t *, p->nMems );
+    for ( i = 0; i < p->nMems; i++ )
+        p->pMems[i] = Gia_MmFixedStart( (8<<i), (1<<13) );
+    // set up the mapping of the required memory size into the corresponding manager
+    p->nMapSize = (4<<p->nMems);
+    p->pMap = ABC_ALLOC( Gia_MmFixed_t *, p->nMapSize+1 );
+    p->pMap[0] = NULL;
+    for ( k = 1; k <= 4; k++ )
+        p->pMap[k] = p->pMems[0];
+    for ( i = 0; i < p->nMems; i++ )
+        for ( k = (4<<i)+1; k <= (8<<i); k++ )
+            p->pMap[k] = p->pMems[i];
+//for ( i = 1; i < 100; i ++ )
+//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize );
+    p->nChunksAlloc  = 64;
+    p->nChunks       = 0;
+    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_MmStepStop( Gia_MmStep_t * p, int fVerbose )
+{
+    int i;
+    for ( i = 0; i < p->nMems; i++ )
+        Gia_MmFixedStop( p->pMems[i], fVerbose );
+    if ( p->nChunksAlloc )
+    {
+        for ( i = 0; i < p->nChunks; i++ )
+            ABC_FREE( p->pChunks[i] );
+        ABC_FREE( p->pChunks );
+    }
+    ABC_FREE( p->pMems );
+    ABC_FREE( p->pMap );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Gia_MmStepEntryFetch( Gia_MmStep_t * p, int nBytes )
+{
+    if ( nBytes == 0 )
+        return NULL;
+    if ( nBytes > p->nMapSize )
+    {
+        if ( p->nChunks == p->nChunksAlloc )
+        {
+            p->nChunksAlloc *= 2;
+            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
+        }
+        p->pChunks[ p->nChunks++ ] = ABC_ALLOC( char, nBytes );
+        return p->pChunks[p->nChunks-1];
+    }
+    return Gia_MmFixedEntryFetch( p->pMap[nBytes] );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_MmStepEntryRecycle( Gia_MmStep_t * p, char * pEntry, int nBytes )
+{
+    if ( nBytes == 0 )
+        return;
+    if ( nBytes > p->nMapSize )
+    {
+//        ABC_FREE( pEntry );
+        return;
+    }
+    Gia_MmFixedEntryRecycle( p->pMap[nBytes], pEntry );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_MmStepReadMemUsage( Gia_MmStep_t * p )
+{
+    int i, nMemTotal = 0;
+    for ( i = 0; i < p->nMems; i++ )
+        nMemTotal += p->pMems[i]->nMemoryAlloc;
+    return nMemTotal;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaMf.c b/abc-build/src/aig/gia/giaMf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaMf.c
@@ -0,0 +1,1665 @@
+/**CFile****************************************************************
+
+  FileName    [giaMf.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Cut computation.]
+
+  Author      [Alan Mishchenko]`
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaMf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/vec/vecMem.h"
+#include "misc/util/utilTruth.h"
+#include "misc/extra/extra.h"
+#include "sat/cnf/cnf.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define MF_LEAF_MAX   10
+#define MF_CUT_MAX    16
+#define MF_LOG_PAGE   12
+#define MF_NO_LEAF    31
+#define MF_TT_WORDS  ((MF_LEAF_MAX > 6) ? 1 << (MF_LEAF_MAX-6) : 1)
+
+typedef struct Mf_Cut_t_ Mf_Cut_t; 
+struct Mf_Cut_t_
+{
+    word            Sign;           // signature
+    int             Delay;          // delay
+    float           Flow;           // flow
+    unsigned        iFunc   : 27;   // function
+    unsigned        nLeaves :  5;   // leaf number (MF_NO_LEAF)
+    int             pLeaves[MF_LEAF_MAX+1]; // leaves
+};
+typedef struct Mf_Obj_t_ Mf_Obj_t; 
+struct Mf_Obj_t_
+{
+    int             iCutSet;        // cutset
+    float           Flow;           // area
+    float           nFlowRefs;      // flow references
+    unsigned        Delay    : 16;  // delay 
+    unsigned        nMapRefs : 16;  // map references
+};
+typedef struct Mf_Man_t_ Mf_Man_t; 
+struct Mf_Man_t_
+{
+    // user data
+    Gia_Man_t *     pGia0;          // original manager
+    Gia_Man_t *     pGia;           // derived manager
+    Jf_Par_t *      pPars;          // parameters
+    // cut data
+    Mf_Obj_t *      pLfObjs;        // best cuts
+    Vec_Ptr_t       vPages;         // cut memory
+    Vec_Mem_t *     vTtMem;         // truth tables
+    Vec_Int_t       vCnfSizes;      // handles to CNF
+    Vec_Int_t       vCnfMem;        // memory for CNF
+    int             iCur;           // current position
+    int             Iter;           // mapping iterations
+    int             fUseEla;        // use exact area
+    // statistics
+    abctime         clkStart;       // starting time
+    double          CutCount[4];    // cut counts
+    int             nCutCounts[MF_LEAF_MAX+1];
+};
+
+static inline Mf_Obj_t * Mf_ManObj( Mf_Man_t * p, int i )            { return p->pLfObjs + i;                                          }
+static inline int *      Mf_ManCutSet( Mf_Man_t * p, int i )         { return (int *)Vec_PtrEntry(&p->vPages, i >> 16) + (i & 0xFFFF); }
+static inline int *      Mf_ObjCutSet( Mf_Man_t * p, int i )         { return Mf_ManCutSet(p, Mf_ManObj(p, i)->iCutSet);               }
+static inline int *      Mf_ObjCutBest( Mf_Man_t * p, int i )        { return Mf_ObjCutSet(p, i) + 1;                                  }
+
+static inline int        Mf_ObjMapRefNum( Mf_Man_t * p, int i )      { return Mf_ManObj(p, i)->nMapRefs;                               }
+static inline int        Mf_ObjMapRefInc( Mf_Man_t * p, int i )      { return Mf_ManObj(p, i)->nMapRefs++;                             }
+static inline int        Mf_ObjMapRefDec( Mf_Man_t * p, int i )      { return --Mf_ManObj(p, i)->nMapRefs;                             }
+
+static inline int        Mf_CutSize( int * pCut )                    { return pCut[0] & MF_NO_LEAF;                                    }
+static inline int        Mf_CutFunc( int * pCut )                    { return ((unsigned)pCut[0] >> 5);                                }
+static inline int        Mf_CutSetBoth( int n, int f )               { return n | (f << 5);                                            }
+static inline int        Mf_CutIsTriv( int * pCut, int i )           { return Mf_CutSize(pCut) == 1 && pCut[1] == i;                   } 
+
+#define Mf_SetForEachCut( pList, pCut, i )      for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += Mf_CutSize(pCut) + 1 )
+#define Mf_ObjForEachCut( pCuts, i, nCuts )     for ( i = 0, i < nCuts; i++ )
+
+extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash );
+extern void Dau_DsdPrintFromTruth( word * pTruth, int nVarsInit );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computing truth tables of useful DSD classes of 6-functions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int s_nCalls = 0;
+static Vec_Mem_t * s_vTtMem = NULL;
+int Mf_ManTruthCanonicize( word * t, int nVars )
+{
+    word Temp, Best = *t;
+    int r, i, Config = 0;
+    for ( r = 0; r < 1; r++ )
+    {
+        if ( Best > (Temp = ~Best) )
+            Best = Temp, Config ^= (1 << nVars);
+        for ( i = 0; i < nVars; i++ )
+            if ( Best > (Temp = Abc_Tt6Flip(Best, i)) )
+                Best = Temp, Config ^= (1 << i);
+    }
+    *t = Best;
+    if ( s_vTtMem == NULL )
+        s_vTtMem = Vec_MemAllocForTT( 6, 0 );
+    Vec_MemHashInsert( s_vTtMem, t );
+    s_nCalls++;
+    return Config;
+}
+void Mf_ManTruthQuit()
+{
+    if ( s_vTtMem == NULL )
+        return;
+    printf( "TT = %d (%.2f %%)\n", Vec_MemEntryNum(s_vTtMem), 100.0 * Vec_MemEntryNum(s_vTtMem) / s_nCalls );
+    Vec_MemHashFree( s_vTtMem );
+    Vec_MemFree( s_vTtMem );
+    s_vTtMem = NULL;
+    s_nCalls = 0;
+}
+
+Vec_Wrd_t * Mf_ManTruthCollect( int Limit )
+{
+    extern Vec_Wrd_t * Mpm_ManGetTruthWithCnf( int Limit );
+    int * pPerm = Extra_PermSchedule( 6 );
+    int * pComp = Extra_GreyCodeSchedule( 6 );
+    Vec_Wrd_t * vTruths = Mpm_ManGetTruthWithCnf( Limit );
+    Vec_Wrd_t * vResult = Vec_WrdAlloc( 1 << 20 );
+    word uTruth, tCur, tTemp1, tTemp2;
+    int i, p, c, k;
+    Vec_WrdForEachEntry( vTruths, uTruth, k )
+    {
+        for ( i = 0; i < 2; i++ )
+        {
+            tCur = i ? ~uTruth : uTruth;
+            tTemp1 = tCur;
+            for ( p = 0; p < 720; p++ )
+            {
+                tTemp2 = tCur;
+                for ( c = 0; c < 64; c++ )
+                {
+                    tCur = Abc_Tt6Flip( tCur, pComp[c] );
+                    Vec_WrdPush( vResult, tCur );
+                }
+                assert( tTemp2 == tCur );
+                tCur = Abc_Tt6SwapAdjacent( tCur, pPerm[p] );
+            }
+            assert( tTemp1 == tCur );
+        }
+    }
+    ABC_FREE( pPerm );
+    ABC_FREE( pComp );
+    printf( "Original = %d.  ", Vec_WrdSize(vTruths) );
+    Vec_WrdFree( vTruths );
+    printf( "Total = %d.  ", Vec_WrdSize(vResult) );
+    vTruths = Vec_WrdUniqifyHash( vResult, 1 );
+    Vec_WrdFree( vResult );
+    printf( "Unique = %d.  ", Vec_WrdSize(vTruths) );
+    Vec_WrdForEachEntry( vTruths, uTruth, k )
+    {
+        Mf_ManTruthCanonicize( &uTruth, 6 );
+        Vec_WrdWriteEntry( vTruths, k, uTruth );
+    }
+    vResult = Vec_WrdUniqifyHash( vTruths, 1 );
+    Vec_WrdFree( vTruths );
+    printf( "Unique = %d.  \n", Vec_WrdSize(vResult) );
+    return vResult;
+}
+int Mf_ManTruthCount()
+{
+    Vec_Wrd_t * vTruths = Mf_ManTruthCollect( 10 );
+    int RetValue = Vec_WrdSize( vTruths );
+    Vec_WrdFree( vTruths );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect truth tables used by the mapper.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mf_ManProfileTruths( Mf_Man_t * p )
+{
+    Vec_Int_t * vCounts;
+    int i, Entry, * pCut, Counter = 0;
+    vCounts = Vec_IntStart( Vec_IntSize(&p->vCnfSizes) );
+    Gia_ManForEachAndId( p->pGia, i )
+    {
+        if ( !Mf_ObjMapRefNum(p, i) )
+            continue;
+        pCut = Mf_ObjCutBest( p, i );
+        Vec_IntAddToEntry( vCounts, Abc_Lit2Var(Mf_CutFunc(pCut)), 1 );
+    }
+    Vec_IntForEachEntry( vCounts, Entry, i )
+    {
+        if ( Entry == 0 )
+            continue;
+        printf( "%6d : ", Counter++ );
+        printf( "%6d : ", i );
+        printf( "Occur = %4d  ", Entry ); 
+        printf( "CNF size = %2d  ", Vec_IntEntry(&p->vCnfSizes, i) );
+        Dau_DsdPrintFromTruth( Vec_MemReadEntry(p->vTtMem, i), p->pPars->nLutSize );
+    }
+    Vec_IntFree( vCounts );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CNFs for each function used in the mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Mf_CubeLit( int Cube, int iVar ) { return (Cube >> (iVar << 1)) & 3; }
+static inline int Mf_ManCountLits( int * pCnf, int nCubes, int nVars )
+{
+    int i, k, nLits = nCubes;
+    for ( i = 0; i < nCubes; i++ )
+        for ( k = 0; k < nVars; k++ )
+            if ( Mf_CubeLit(pCnf[i], k) )
+                nLits++;
+    return nLits;
+}
+Vec_Int_t * Mf_ManDeriveCnfs( Mf_Man_t * p, int * pnVars, int * pnClas, int * pnLits )
+{
+    int i, k, iFunc, nCubes, nLits, * pCut, pCnf[512];
+    Vec_Int_t * vLits = Vec_IntStart( Vec_IntSize(&p->vCnfSizes) );
+    Vec_Int_t * vCnfs = Vec_IntAlloc( 3 * Vec_IntSize(&p->vCnfSizes) );
+    Vec_IntFill( vCnfs, Vec_IntSize(&p->vCnfSizes), -1 );
+    assert( p->pPars->nLutSize <= 8 );
+    // constant/buffer
+    for ( iFunc = 0; iFunc < 2; iFunc++ )
+    {
+        if ( p->pPars->nLutSize <= 6 )
+            nCubes = Abc_Tt6Cnf( *Vec_MemReadEntry(p->vTtMem, iFunc), iFunc, pCnf );
+        else
+            nCubes = Abc_Tt8Cnf( Vec_MemReadEntry(p->vTtMem, iFunc), iFunc, pCnf );
+        nLits = Mf_ManCountLits( pCnf, nCubes, iFunc );
+        Vec_IntWriteEntry( vLits, iFunc, nLits );
+        Vec_IntWriteEntry( vCnfs, iFunc, Vec_IntSize(vCnfs) );
+        Vec_IntPush( vCnfs, nCubes );
+        for ( k = 0; k < nCubes; k++ )
+            Vec_IntPush( vCnfs, pCnf[k] );
+    }
+    // other functions
+    *pnVars = 1 + Gia_ManCiNum(p->pGia) + Gia_ManCoNum(p->pGia);
+    *pnClas = 1 + 2 * Gia_ManCoNum(p->pGia);
+    *pnLits = 1 + 4 * Gia_ManCoNum(p->pGia);
+    Gia_ManForEachAndId( p->pGia, i )
+    {
+        if ( !Mf_ObjMapRefNum(p, i) )
+            continue;
+        pCut = Mf_ObjCutBest( p, i );
+        iFunc = Abc_Lit2Var( Mf_CutFunc(pCut) );
+        if ( Vec_IntEntry(vCnfs, iFunc) == -1 )
+        {
+            if ( p->pPars->nLutSize <= 6 )
+                nCubes = Abc_Tt6Cnf( *Vec_MemReadEntry(p->vTtMem, iFunc), Mf_CutSize(pCut), pCnf );
+            else
+                nCubes = Abc_Tt8Cnf( Vec_MemReadEntry(p->vTtMem, iFunc), Mf_CutSize(pCut), pCnf );
+            assert( nCubes == Vec_IntEntry(&p->vCnfSizes, iFunc) );
+            nLits = Mf_ManCountLits( pCnf, nCubes, Mf_CutSize(pCut) );
+            // save CNF
+            Vec_IntWriteEntry( vLits, iFunc, nLits );
+            Vec_IntWriteEntry( vCnfs, iFunc, Vec_IntSize(vCnfs) );
+            Vec_IntPush( vCnfs, nCubes );
+            for ( k = 0; k < nCubes; k++ )
+                Vec_IntPush( vCnfs, pCnf[k] );
+        }
+        *pnVars += 1;
+        *pnClas += Vec_IntEntry(&p->vCnfSizes, iFunc);
+        *pnLits += Vec_IntEntry(vLits, iFunc);
+    }
+    Vec_IntFree( vLits );
+    return vCnfs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CNF for the AIG using the mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Dat_t * Mf_ManDeriveCnf( Mf_Man_t * p, int fCnfObjIds, int fAddOrCla )
+{
+    Cnf_Dat_t * pCnf; 
+    Gia_Obj_t * pObj;
+    int Id, DriId, nVars, nClas, nLits, iVar = 1, iCla = 0, iLit = 0;
+    Vec_Int_t * vCnfs = Mf_ManDeriveCnfs( p, &nVars, &nClas, &nLits );
+    Vec_Int_t * vCnfIds = Vec_IntStartFull( Gia_ManObjNum(p->pGia) );
+    int pFanins[16], * pCut, * pCnfIds = Vec_IntArray( vCnfIds );
+    int i, k, c, iFunc, nCubes, * pCubes, fComplLast;
+    nVars++;  // zero-ID to remain unused
+    if ( fAddOrCla )
+    {
+        nClas++;
+        nLits += Gia_ManCoNum(p->pGia);
+    }
+    // create CNF IDs
+    if ( fCnfObjIds )
+    {
+        iVar += 1 + Gia_ManCiNum(p->pGia) + Gia_ManCoNum(p->pGia);
+        Gia_ManForEachCoId( p->pGia, Id, i )
+            Vec_IntWriteEntry( vCnfIds, Id, Id );
+        Gia_ManForEachAndReverseId( p->pGia, Id )
+            if ( Mf_ObjMapRefNum(p, Id) )
+                Vec_IntWriteEntry( vCnfIds, Id, Id ), iVar++;
+        Gia_ManForEachCiId( p->pGia, Id, i )
+            Vec_IntWriteEntry( vCnfIds, Id, Id );
+        Vec_IntWriteEntry( vCnfIds, 0, 0 );
+        assert( iVar == nVars );
+    }
+    else
+    {
+        Gia_ManForEachCoId( p->pGia, Id, i )
+            Vec_IntWriteEntry( vCnfIds, Id, iVar++ );
+        Gia_ManForEachAndReverseId( p->pGia, Id )
+            if ( Mf_ObjMapRefNum(p, Id) )
+                Vec_IntWriteEntry( vCnfIds, Id, iVar++ );
+        Gia_ManForEachCiId( p->pGia, Id, i )
+            Vec_IntWriteEntry( vCnfIds, Id, iVar++ );
+        Vec_IntWriteEntry( vCnfIds, 0, iVar++ );
+        assert( iVar == nVars );
+    }
+    // generate CNF
+    pCnf = ABC_CALLOC( Cnf_Dat_t, 1 );
+    pCnf->pMan        = (Aig_Man_t *)p->pGia;
+    pCnf->nVars       = nVars;
+    pCnf->nLiterals   = nLits;
+    pCnf->nClauses    = nClas;
+    pCnf->pClauses    = ABC_ALLOC( int *, nClas+1 );
+    pCnf->pClauses[0] = ABC_ALLOC( int, nLits );
+    // add last clause
+    if ( fAddOrCla )
+    {
+        pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit;
+        Gia_ManForEachCoId( p->pGia, Id, i )
+            pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[Id], 0);
+    }
+    // add clauses for the COs
+    Gia_ManForEachCo( p->pGia, pObj, i )
+    {
+        Id = Gia_ObjId( p->pGia, pObj );
+        DriId = Gia_ObjFaninId0( pObj, Id );
+
+        pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit;
+        pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[Id], 0);
+        pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[DriId], !Gia_ObjFaninC0(pObj));
+
+        pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit;
+        pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[Id], 1);
+        pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[DriId], Gia_ObjFaninC0(pObj));
+    }
+    // add clauses for the mapping
+    Gia_ManForEachAndReverseId( p->pGia, Id )
+    {
+        if ( !Mf_ObjMapRefNum(p, Id) )
+            continue;
+        pCut = Mf_ObjCutBest( p, Id );
+        iFunc = Abc_Lit2Var( Mf_CutFunc(pCut) );
+        //Dau_DsdPrintFromTruth( Vec_MemReadEntry(p->vTtMem, iFunc), 3 );
+        fComplLast = Abc_LitIsCompl( Mf_CutFunc(pCut) );
+        for ( k = 0; k < Mf_CutSize(pCut); k++ )
+            pFanins[k] = pCnfIds[pCut[k+1]];
+        pFanins[k++] = pCnfIds[Id];
+        // get clauses
+        pCubes = Vec_IntEntryP( vCnfs, Vec_IntEntry(vCnfs, iFunc) );
+        nCubes = *pCubes++;
+        for ( c = 0; c < nCubes; c++ )
+        {
+            pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit;
+            k = Mf_CutSize(pCut);
+            assert( Mf_CubeLit(pCubes[c], k) );
+            pCnf->pClauses[0][iLit++] = Abc_Var2Lit( pFanins[k], (Mf_CubeLit(pCubes[c], k) == 2) ^ fComplLast );
+            for ( k = 0; k < Mf_CutSize(pCut); k++ )
+                if ( Mf_CubeLit(pCubes[c], k) )
+                    pCnf->pClauses[0][iLit++] = Abc_Var2Lit( pFanins[k], Mf_CubeLit(pCubes[c], k) == 2 );
+        }
+    }
+    // constant clause
+    pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit;
+    pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[0], 1);
+    assert( iCla == nClas );
+    assert( iLit == nLits );
+    // add closing pointer
+    pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit;
+    // cleanup
+    Vec_IntFree( vCnfs );
+    // create mapping of objects into their clauses
+    if ( fCnfObjIds )
+    {
+        pCnf->pObj2Clause = ABC_FALLOC( int, Gia_ManObjNum(p->pGia) );
+        pCnf->pObj2Count  = ABC_FALLOC( int, Gia_ManObjNum(p->pGia) );
+        for ( i = 0; i < pCnf->nClauses; i++ )
+        {
+            Id = Abc_Lit2Var(pCnf->pClauses[i][0]);
+            if ( pCnf->pObj2Clause[Id] == -1 )
+            {
+                pCnf->pObj2Clause[Id] = i;
+                pCnf->pObj2Count[Id] = 1;
+            }
+            else
+            {
+                assert( pCnf->pObj2Count[Id] > 0 );
+                pCnf->pObj2Count[Id]++;
+            }
+        }
+    }
+    else
+    {
+        if ( p->pGia != p->pGia0 ) // diff managers - create map for CIs/COs
+        {
+            pCnf->pVarNums = ABC_FALLOC( int, Gia_ManObjNum(p->pGia0) );
+            Gia_ManForEachCiId( p->pGia0, Id, i )
+                pCnf->pVarNums[Id] = pCnfIds[Gia_ManCiIdToId(p->pGia, i)];
+            Gia_ManForEachCoId( p->pGia0, Id, i )
+                pCnf->pVarNums[Id] = pCnfIds[Gia_ManCoIdToId(p->pGia, i)];
+/*
+            // transform polarity of the internal nodes
+            Gia_ManSetPhase( p->pGia );
+            Gia_ManForEachCo( p->pGia, pObj, i )
+                pObj->fPhase = 0;
+            for ( i = 0; i < pCnf->nLiterals; i++ )
+                if ( Gia_ManObj(p->pGia, Abc_Lit2Var(pCnf->pClauses[0][i]))->fPhase )
+                    pCnf->pClauses[0][i] = Abc_LitNot( pCnf->pClauses[0][i] );
+*/
+        }
+        else
+            pCnf->pVarNums = Vec_IntReleaseArray(vCnfIds);
+    }
+    Vec_IntFree( vCnfIds );
+    return pCnf;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Mf_CutComputeTruth6( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, int fCompl0, int fCompl1, Mf_Cut_t * pCutR, int fIsXor )
+{
+//    extern int Mf_ManTruthCanonicize( word * t, int nVars );
+    int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t;
+    word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc));
+    word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc));
+    if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0;
+    if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1;
+    t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves );
+    t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves );
+    t =  fIsXor ? t0 ^ t1 : t0 & t1;
+    if ( (fCompl = (int)(t & 1)) ) t = ~t;
+    pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves );
+    assert( (int)(t & 1) == 0 );
+    truthId        = Vec_MemHashInsert(p->vTtMem, &t);
+    pCutR->iFunc   = Abc_Var2Lit( truthId, fCompl );
+    if ( p->pPars->fGenCnf && truthId == Vec_IntSize(&p->vCnfSizes) )
+        Vec_IntPush( &p->vCnfSizes, Abc_Tt6CnfSize(t, pCutR->nLeaves) );
+//    p->nCutMux += Mf_ManTtIsMux( t );
+    assert( (int)pCutR->nLeaves <= nOldSupp );
+//    Mf_ManTruthCanonicize( &t, pCutR->nLeaves );
+    return (int)pCutR->nLeaves < nOldSupp;
+}
+static inline int Mf_CutComputeTruth( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, int fCompl0, int fCompl1, Mf_Cut_t * pCutR, int fIsXor )
+{
+    if ( p->pPars->nLutSize <= 6 )
+        return Mf_CutComputeTruth6( p, pCut0, pCut1, fCompl0, fCompl1, pCutR, fIsXor );
+    {
+    word uTruth[MF_TT_WORDS], uTruth0[MF_TT_WORDS], uTruth1[MF_TT_WORDS];
+    int nOldSupp   = pCutR->nLeaves, truthId;
+    int LutSize    = p->pPars->nLutSize, fCompl;
+    int nWords     = Abc_Truth6WordNum(LutSize);
+    word * pTruth0 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc));
+    word * pTruth1 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc));
+    Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 );
+    Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 );
+    Abc_TtExpand( uTruth0, LutSize, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves );
+    Abc_TtExpand( uTruth1, LutSize, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves );
+    if ( fIsXor )
+        Abc_TtXor( uTruth, uTruth0, uTruth1, nWords, (fCompl = (int)((uTruth0[0] ^ uTruth1[0]) & 1)) );
+    else
+        Abc_TtAnd( uTruth, uTruth0, uTruth1, nWords, (fCompl = (int)((uTruth0[0] & uTruth1[0]) & 1)) );
+    pCutR->nLeaves = Abc_TtMinBase( uTruth, pCutR->pLeaves, pCutR->nLeaves, LutSize );
+    assert( (uTruth[0] & 1) == 0 );
+//Kit_DsdPrintFromTruth( uTruth, pCutR->nLeaves ), printf("\n" ), printf("\n" );
+    truthId        = Vec_MemHashInsert(p->vTtMem, uTruth);
+    pCutR->iFunc   = Abc_Var2Lit( truthId, fCompl );
+    if ( p->pPars->fGenCnf && truthId == Vec_IntSize(&p->vCnfSizes) && LutSize <= 8 )
+        Vec_IntPush( &p->vCnfSizes, Abc_Tt8CnfSize(uTruth, pCutR->nLeaves) );
+    assert( (int)pCutR->nLeaves <= nOldSupp );
+    return (int)pCutR->nLeaves < nOldSupp;
+    }
+}
+static inline int Mf_CutComputeTruthMux6( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, Mf_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, Mf_Cut_t * pCutR )
+{
+    int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t;
+    word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc));
+    word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc));
+    word tC = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCutC->iFunc));
+    if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0;
+    if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1;
+    if ( Abc_LitIsCompl(pCutC->iFunc) ^ fComplC ) tC = ~tC;
+    t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves );
+    t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves );
+    tC = Abc_Tt6Expand( tC, pCutC->pLeaves, pCutC->nLeaves, pCutR->pLeaves, pCutR->nLeaves );
+    t = (tC & t1) | (~tC & t0);
+    if ( (fCompl = (int)(t & 1)) ) t = ~t;
+    pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves );
+    assert( (int)(t & 1) == 0 );
+    truthId        = Vec_MemHashInsert(p->vTtMem, &t);
+    pCutR->iFunc   = Abc_Var2Lit( truthId, fCompl );
+    if ( p->pPars->fGenCnf && truthId == Vec_IntSize(&p->vCnfSizes) )
+        Vec_IntPush( &p->vCnfSizes, Abc_Tt6CnfSize(t, pCutR->nLeaves) );
+    assert( (int)pCutR->nLeaves <= nOldSupp );
+    return (int)pCutR->nLeaves < nOldSupp;
+}
+static inline int Mf_CutComputeTruthMux( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, Mf_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, Mf_Cut_t * pCutR )
+{
+    if ( p->pPars->nLutSize <= 6 )
+        return Mf_CutComputeTruthMux6( p, pCut0, pCut1, pCutC, fCompl0, fCompl1, fComplC, pCutR );
+    {
+    word uTruth[MF_TT_WORDS], uTruth0[MF_TT_WORDS], uTruth1[MF_TT_WORDS], uTruthC[MF_TT_WORDS];
+    int nOldSupp   = pCutR->nLeaves, truthId;
+    int LutSize    = p->pPars->nLutSize, fCompl;
+    int nWords     = Abc_Truth6WordNum(LutSize);
+    word * pTruth0 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc));
+    word * pTruth1 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc));
+    word * pTruthC = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCutC->iFunc));
+    Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 );
+    Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 );
+    Abc_TtCopy( uTruthC, pTruthC, nWords, Abc_LitIsCompl(pCutC->iFunc) ^ fComplC );
+    Abc_TtExpand( uTruth0, LutSize, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves );
+    Abc_TtExpand( uTruth1, LutSize, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves );
+    Abc_TtExpand( uTruthC, LutSize, pCutC->pLeaves, pCutC->nLeaves, pCutR->pLeaves, pCutR->nLeaves );
+    Abc_TtMux( uTruth, uTruthC, uTruth1, uTruth0, nWords );
+    fCompl         = (int)(uTruth[0] & 1);
+    if ( fCompl ) Abc_TtNot( uTruth, nWords );
+    pCutR->nLeaves = Abc_TtMinBase( uTruth, pCutR->pLeaves, pCutR->nLeaves, LutSize );
+    assert( (uTruth[0] & 1) == 0 );
+    truthId        = Vec_MemHashInsert(p->vTtMem, uTruth);
+    pCutR->iFunc   = Abc_Var2Lit( truthId, fCompl );
+    if ( p->pPars->fGenCnf && truthId == Vec_IntSize(&p->vCnfSizes) && LutSize <= 8 )
+        Vec_IntPush( &p->vCnfSizes, Abc_Tt8CnfSize(uTruth, pCutR->nLeaves) );
+    assert( (int)pCutR->nLeaves <= nOldSupp );
+    return (int)pCutR->nLeaves < nOldSupp;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Mf_CutCountBits( word i )
+{
+    i = i - ((i >> 1) & 0x5555555555555555);
+    i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333);
+    i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F);
+    return (i*(0x0101010101010101))>>56;
+}
+static inline word Mf_CutGetSign( int * pLeaves, int nLeaves )
+{
+    word Sign = 0; int i; 
+    for ( i = 0; i < nLeaves; i++ )
+        Sign |= ((word)1) << (pLeaves[i] & 0x3F);
+    return Sign;
+}
+static inline int Mf_CutCreateUnit( Mf_Cut_t * p, int i )
+{
+    p->Delay      = 0;
+    p->Flow       = 0;
+    p->iFunc      = 2;
+    p->nLeaves    = 1;
+    p->pLeaves[0] = i;
+    p->Sign       = ((word)1) << (i & 0x3F);
+    return 1;
+}
+static inline void Mf_CutPrint( Mf_Man_t * p, Mf_Cut_t * pCut )
+{
+    int i, nDigits = Abc_Base10Log(Gia_ManObjNum(p->pGia)); 
+    printf( "%d  {", pCut->nLeaves );
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        printf( " %*d", nDigits, pCut->pLeaves[i] );
+    for ( ; i < (int)p->pPars->nLutSize; i++ )
+        printf( " %*s", nDigits, " " );
+    printf( "  }   D = %4d  A = %9.4f  F = %6d  ", 
+        pCut->Delay, pCut->Flow, pCut->iFunc );
+    if ( p->vTtMem )
+    {
+        if ( p->pPars->fGenCnf )
+            printf( "CNF = %2d  ", Vec_IntEntry(&p->vCnfSizes, Abc_Lit2Var(pCut->iFunc)) );
+        Dau_DsdPrintFromTruth( Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut->iFunc)), pCut->nLeaves );
+    }
+    else
+        printf( "\n" );
+}
+static inline int Mf_ManPrepareCuts( Mf_Cut_t * pCuts, Mf_Man_t * p, int iObj, int fAddUnit )
+{
+    if ( Mf_ManObj(p, iObj)->iCutSet )
+    {
+        Mf_Cut_t * pMfCut = pCuts;
+        int i, * pCut, * pList = Mf_ObjCutSet(p, iObj);
+        Mf_SetForEachCut( pList, pCut, i )
+        {
+            pMfCut->Delay   = 0;
+            pMfCut->Flow    = 0;
+            pMfCut->iFunc   = Mf_CutFunc( pCut );
+            pMfCut->nLeaves = Mf_CutSize( pCut );
+            pMfCut->Sign    = Mf_CutGetSign( pCut+1, Mf_CutSize(pCut) );
+            memcpy( pMfCut->pLeaves, pCut+1, sizeof(int) * Mf_CutSize(pCut) );
+            pMfCut++;
+        }
+        if ( fAddUnit && pCuts->nLeaves > 1 )
+            return pList[0] + Mf_CutCreateUnit( pMfCut, iObj );
+        return pList[0];
+    }
+    return Mf_CutCreateUnit( pCuts, iObj );
+}
+static inline int Mf_ManSaveCuts( Mf_Man_t * p, Mf_Cut_t ** pCuts, int nCuts )
+{
+    int i, * pPlace, iCur, nInts = 1;
+    for ( i = 0; i < nCuts; i++ )
+        nInts += pCuts[i]->nLeaves + 1;
+    if ( (p->iCur & 0xFFFF) + nInts > 0xFFFF )
+        p->iCur = ((p->iCur >> 16) + 1) << 16;
+    if ( Vec_PtrSize(&p->vPages) == (p->iCur >> 16) )
+        Vec_PtrPush( &p->vPages, ABC_ALLOC(int, (1<<16)) );
+    iCur = p->iCur; p->iCur += nInts;
+    pPlace = Mf_ManCutSet( p, iCur );
+    *pPlace++ = nCuts;
+    for ( i = 0; i < nCuts; i++ )
+    {
+        *pPlace++ = Mf_CutSetBoth(pCuts[i]->nLeaves, pCuts[i]->iFunc);
+        memcpy( pPlace, pCuts[i]->pLeaves, sizeof(int) * pCuts[i]->nLeaves );
+        pPlace += pCuts[i]->nLeaves;
+    }
+    return iCur;
+}
+static inline void Mf_ObjSetBestCut( int * pCuts, int * pCut )
+{
+    assert( pCuts < pCut );
+    if ( ++pCuts < pCut )
+    {
+        int pTemp[MF_CUT_MAX*(MF_LEAF_MAX+2)];
+        int nBlock = pCut - pCuts;
+        int nSize = Mf_CutSize(pCut) + 1;
+        memmove( pTemp, pCuts, sizeof(int) * nBlock );
+        memmove( pCuts, pCut, sizeof(int) * nSize );
+        memmove( pCuts + nSize, pTemp, sizeof(int) * nBlock );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check correctness of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Mf_CutCheck( Mf_Cut_t * pBase, Mf_Cut_t * pCut ) // check if pCut is contained in pBase
+{
+    int nSizeB = pBase->nLeaves;
+    int nSizeC = pCut->nLeaves;
+    int i, * pB = pBase->pLeaves;
+    int k, * pC = pCut->pLeaves;
+    for ( i = 0; i < nSizeC; i++ )
+    {
+        for ( k = 0; k < nSizeB; k++ )
+            if ( pC[i] == pB[k] )
+                break;
+        if ( k == nSizeB )
+            return 0;
+    }
+    return 1;
+}
+static inline int Mf_SetCheckArray( Mf_Cut_t ** ppCuts, int nCuts )
+{
+    Mf_Cut_t * pCut0, * pCut1; 
+    int i, k, m, n, Value;
+    assert( nCuts > 0 );
+    for ( i = 0; i < nCuts; i++ )
+    {
+        pCut0 = ppCuts[i];
+        assert( pCut0->nLeaves <= MF_LEAF_MAX );
+        assert( pCut0->Sign == Mf_CutGetSign(pCut0->pLeaves, pCut0->nLeaves) );
+        // check duplicates
+        for ( m = 0; m < (int)pCut0->nLeaves; m++ )
+        for ( n = m + 1; n < (int)pCut0->nLeaves; n++ )
+            assert( pCut0->pLeaves[m] < pCut0->pLeaves[n] );
+        // check pairs
+        for ( k = 0; k < nCuts; k++ )
+        {
+            pCut1 = ppCuts[k];
+            if ( pCut0 == pCut1 )
+                continue;
+            // check containments
+            Value = Mf_CutCheck( pCut0, pCut1 );
+            assert( Value == 0 );
+        }
+    }
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Mf_CutMergeOrder( Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, Mf_Cut_t * pCut, int nLutSize )
+{ 
+    int nSize0   = pCut0->nLeaves;
+    int nSize1   = pCut1->nLeaves;
+    int i, * pC0 = pCut0->pLeaves;
+    int k, * pC1 = pCut1->pLeaves;
+    int c, * pC  = pCut->pLeaves;
+    // the case of the largest cut sizes
+    if ( nSize0 == nLutSize && nSize1 == nLutSize )
+    {
+        for ( i = 0; i < nSize0; i++ )
+        {
+            if ( pC0[i] != pC1[i] )  return 0;
+            pC[i] = pC0[i];
+        }
+        pCut->nLeaves = nLutSize;
+        pCut->iFunc = -1;
+        pCut->Sign = pCut0->Sign | pCut1->Sign;
+        return 1;
+    }
+    // compare two cuts with different numbers
+    i = k = c = 0;
+    if ( nSize0 == 0 ) goto FlushCut1;
+    if ( nSize1 == 0 ) goto FlushCut0;
+    while ( 1 )
+    {
+        if ( c == nLutSize ) return 0;
+        if ( pC0[i] < pC1[k] )
+        {
+            pC[c++] = pC0[i++];
+            if ( i >= nSize0 ) goto FlushCut1;
+        }
+        else if ( pC0[i] > pC1[k] )
+        {
+            pC[c++] = pC1[k++];
+            if ( k >= nSize1 ) goto FlushCut0;
+        }
+        else
+        {
+            pC[c++] = pC0[i++]; k++;
+            if ( i >= nSize0 ) goto FlushCut1;
+            if ( k >= nSize1 ) goto FlushCut0;
+        }
+    }
+
+FlushCut0:
+    if ( c + nSize0 > nLutSize + i ) return 0;
+    while ( i < nSize0 )
+        pC[c++] = pC0[i++];
+    pCut->nLeaves = c;
+    pCut->iFunc = -1;
+    pCut->Sign = pCut0->Sign | pCut1->Sign;
+    return 1;
+
+FlushCut1:
+    if ( c + nSize1 > nLutSize + k ) return 0;
+    while ( k < nSize1 )
+        pC[c++] = pC1[k++];
+    pCut->nLeaves = c;
+    pCut->iFunc = -1;
+    pCut->Sign = pCut0->Sign | pCut1->Sign;
+    return 1;
+}
+static inline int Mf_CutMergeOrderMux( Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, Mf_Cut_t * pCut2, Mf_Cut_t * pCut, int nLutSize )
+{ 
+    int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves;
+    int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves;
+    int x2, i2 = 0, nSize2 = pCut2->nLeaves, * pC2 = pCut2->pLeaves;
+    int xMin, c = 0, * pC  = pCut->pLeaves;
+    while ( 1 )
+    {
+        x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0];
+        x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1];
+        x2 = (i2 == nSize2) ? ABC_INFINITY : pC2[i2];
+        xMin = Abc_MinInt( Abc_MinInt(x0, x1), x2 );
+        if ( xMin == ABC_INFINITY ) break;
+        if ( c == nLutSize ) return 0;
+        pC[c++] = xMin;
+        if (x0 == xMin) i0++;
+        if (x1 == xMin) i1++;
+        if (x2 == xMin) i2++;
+    }
+    pCut->nLeaves = c;
+    pCut->iFunc = -1;
+    pCut->Sign = pCut0->Sign | pCut1->Sign | pCut2->Sign;
+    return 1;
+}
+static inline int Mf_SetCutIsContainedOrder( Mf_Cut_t * pBase, Mf_Cut_t * pCut ) // check if pCut is contained in pBase
+{
+    int i, nSizeB = pBase->nLeaves;
+    int k, nSizeC = pCut->nLeaves;
+    if ( nSizeB == nSizeC )
+    {
+        for ( i = 0; i < nSizeB; i++ )
+            if ( pBase->pLeaves[i] != pCut->pLeaves[i] )
+                return 0;
+        return 1;
+    }
+    assert( nSizeB > nSizeC ); 
+    if ( nSizeC == 0 )
+        return 1;
+    for ( i = k = 0; i < nSizeB; i++ )
+    {
+        if ( pBase->pLeaves[i] > pCut->pLeaves[k] )
+            return 0;
+        if ( pBase->pLeaves[i] == pCut->pLeaves[k] )
+        {
+            if ( ++k == nSizeC )
+                return 1;
+        }
+    }
+    return 0;
+}
+static inline int Mf_SetLastCutIsContained( Mf_Cut_t ** pCuts, int nCuts )
+{
+    int i;
+    for ( i = 0; i < nCuts; i++ )
+        if ( pCuts[i]->nLeaves <= pCuts[nCuts]->nLeaves && (pCuts[i]->Sign & pCuts[nCuts]->Sign) == pCuts[i]->Sign && Mf_SetCutIsContainedOrder(pCuts[nCuts], pCuts[i]) )
+            return 1;
+    return 0;
+}
+static inline int Mf_SetLastCutContainsArea( Mf_Cut_t ** pCuts, int nCuts )
+{
+    int i, k, fChanges = 0;
+    for ( i = 0; i < nCuts; i++ )
+        if ( pCuts[nCuts]->nLeaves < pCuts[i]->nLeaves && (pCuts[nCuts]->Sign & pCuts[i]->Sign) == pCuts[nCuts]->Sign && Mf_SetCutIsContainedOrder(pCuts[i], pCuts[nCuts]) )
+            pCuts[i]->nLeaves = MF_NO_LEAF, fChanges = 1;
+    if ( !fChanges )
+        return nCuts;
+    for ( i = k = 0; i <= nCuts; i++ )
+    {
+        if ( pCuts[i]->nLeaves == MF_NO_LEAF )
+            continue;
+        if ( k < i )
+            ABC_SWAP( Mf_Cut_t *, pCuts[k], pCuts[i] );
+        k++;
+    }
+    return k - 1;
+}
+static inline int Mf_CutCompareArea( Mf_Cut_t * pCut0, Mf_Cut_t * pCut1 )
+{
+    if ( pCut0->Flow    < pCut1->Flow    )  return -1;
+    if ( pCut0->Flow    > pCut1->Flow    )  return  1;
+    if ( pCut0->Delay   < pCut1->Delay   )  return -1;
+    if ( pCut0->Delay   > pCut1->Delay   )  return  1;
+    if ( pCut0->nLeaves < pCut1->nLeaves )  return -1;
+    if ( pCut0->nLeaves > pCut1->nLeaves )  return  1;
+    return 0;
+}
+static inline void Mf_SetSortByArea( Mf_Cut_t ** pCuts, int nCuts )
+{
+    int i;
+    for ( i = nCuts; i > 0; i-- )
+    {
+        if ( Mf_CutCompareArea(pCuts[i - 1], pCuts[i]) < 0 )//!= 1 )
+            return;
+        ABC_SWAP( Mf_Cut_t *, pCuts[i - 1], pCuts[i] );
+    }
+}
+static inline int Mf_SetAddCut( Mf_Cut_t ** pCuts, int nCuts, int nCutNum )
+{
+    if ( nCuts == 0 )
+        return 1;
+    nCuts = Mf_SetLastCutContainsArea(pCuts, nCuts);
+    Mf_SetSortByArea( pCuts, nCuts );
+    return Abc_MinInt( nCuts + 1, nCutNum - 1 );
+}
+static inline int Mf_CutArea( Mf_Man_t * p, int nLeaves, int iFunc )
+{
+    if ( nLeaves < 2 )
+        return 0;
+    if ( p->pPars->fGenCnf )
+        return Vec_IntEntry(&p->vCnfSizes, Abc_Lit2Var(iFunc));
+    if ( p->pPars->fOptEdge )
+        return nLeaves + p->pPars->nAreaTuner;
+    return 1;
+}
+static inline void Mf_CutParams( Mf_Man_t * p, Mf_Cut_t * pCut, float FlowRefs )
+{
+    Mf_Obj_t * pBest; 
+    int i, nLeaves = pCut->nLeaves; 
+    assert( nLeaves <= p->pPars->nLutSize );
+    pCut->Delay = 0;
+    pCut->Flow  = 0;
+    for ( i = 0; i < nLeaves; i++ )
+    {
+        pBest = Mf_ManObj(p, pCut->pLeaves[i]);
+        pCut->Delay = Abc_MaxInt( pCut->Delay, pBest->Delay );
+        pCut->Flow += pBest->Flow;
+    }
+    pCut->Delay += (int)(nLeaves > 1);
+    pCut->Flow = (pCut->Flow + Mf_CutArea(p, nLeaves, pCut->iFunc)) / FlowRefs;
+}
+void Mf_ObjMergeOrder( Mf_Man_t * p, int iObj )
+{
+    Mf_Cut_t pCuts0[MF_CUT_MAX], pCuts1[MF_CUT_MAX], pCuts[MF_CUT_MAX], * pCutsR[MF_CUT_MAX];
+    Gia_Obj_t * pObj = Gia_ManObj(p->pGia, iObj);
+    Mf_Obj_t * pBest = Mf_ManObj(p, iObj);
+    int nLutSize = p->pPars->nLutSize;
+    int nCutNum  = p->pPars->nCutNum;
+    int nCuts0   = Mf_ManPrepareCuts(pCuts0, p, Gia_ObjFaninId0(pObj, iObj), 1);
+    int nCuts1   = Mf_ManPrepareCuts(pCuts1, p, Gia_ObjFaninId1(pObj, iObj), 1);
+    int fComp0   = Gia_ObjFaninC0(pObj);
+    int fComp1   = Gia_ObjFaninC1(pObj);
+    int iSibl    = Gia_ObjSibl(p->pGia, iObj);
+    Mf_Cut_t * pCut0, * pCut1, * pCut0Lim = pCuts0 + nCuts0, * pCut1Lim = pCuts1 + nCuts1;
+    int i, nCutsR = 0;
+    for ( i = 0; i < nCutNum; i++ )
+        pCutsR[i] = pCuts + i;
+    if ( iSibl )
+    {
+        Mf_Cut_t pCuts2[MF_CUT_MAX];
+        Gia_Obj_t * pObjE = Gia_ObjSiblObj(p->pGia, iObj);
+        int fCompE = Gia_ObjPhase(pObj) ^ Gia_ObjPhase(pObjE);
+        int nCuts2 = Mf_ManPrepareCuts(pCuts2, p, iSibl, 0);
+        Mf_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2;
+        for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ )
+        {
+            *pCutsR[nCutsR] = *pCut2;
+            if ( pCutsR[nCutsR]->iFunc >= 0 )
+                pCutsR[nCutsR]->iFunc = Abc_LitNotCond( pCutsR[nCutsR]->iFunc, fCompE );
+            Mf_CutParams( p, pCutsR[nCutsR], pBest->nFlowRefs );
+            nCutsR = Mf_SetAddCut( pCutsR, nCutsR, nCutNum );
+        }
+    }
+    if ( Gia_ObjIsMuxId(p->pGia, iObj) )
+    {
+        Mf_Cut_t pCuts2[MF_CUT_MAX];
+        int nCuts2  = Mf_ManPrepareCuts(pCuts2, p, Gia_ObjFaninId2(p->pGia, iObj), 1);
+        int fComp2  = Gia_ObjFaninC2(p->pGia, pObj);
+        Mf_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2;
+        p->CutCount[0] += nCuts0 * nCuts1 * nCuts2;
+        for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ )
+        for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ )
+        for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ )
+        {
+            if ( Mf_CutCountBits(pCut0->Sign | pCut1->Sign | pCut2->Sign) > nLutSize )
+                continue;
+            p->CutCount[1]++; 
+            if ( !Mf_CutMergeOrderMux(pCut0, pCut1, pCut2, pCutsR[nCutsR], nLutSize) )
+                continue;
+            if ( Mf_SetLastCutIsContained(pCutsR, nCutsR) )
+                continue;
+            p->CutCount[2]++;
+            if ( p->pPars->fCutMin && Mf_CutComputeTruthMux(p, pCut0, pCut1, pCut2, fComp0, fComp1, fComp2, pCutsR[nCutsR]) )
+                pCutsR[nCutsR]->Sign = Mf_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves);
+            Mf_CutParams( p, pCutsR[nCutsR], pBest->nFlowRefs );
+            nCutsR = Mf_SetAddCut( pCutsR, nCutsR, nCutNum );
+        }
+    }
+    else
+    {
+        int fIsXor = Gia_ObjIsXor(pObj);
+        p->CutCount[0] += nCuts0 * nCuts1;
+        for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ )
+        for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ )
+        {
+            if ( (int)(pCut0->nLeaves + pCut1->nLeaves) > nLutSize && Mf_CutCountBits(pCut0->Sign | pCut1->Sign) > nLutSize )
+                continue;
+            p->CutCount[1]++; 
+            if ( !Mf_CutMergeOrder(pCut0, pCut1, pCutsR[nCutsR], nLutSize) )
+                continue;
+            if ( Mf_SetLastCutIsContained(pCutsR, nCutsR) )
+                continue;
+            p->CutCount[2]++;
+            if ( p->pPars->fCutMin && Mf_CutComputeTruth(p, pCut0, pCut1, fComp0, fComp1, pCutsR[nCutsR], fIsXor) )
+                pCutsR[nCutsR]->Sign = Mf_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves);
+            Mf_CutParams( p, pCutsR[nCutsR], pBest->nFlowRefs );
+            nCutsR = Mf_SetAddCut( pCutsR, nCutsR, nCutNum );
+        }
+    }
+    // debug printout
+    if ( 0 )
+//    if ( iObj % 1000 == 0 )
+//    if ( iObj == 474 )
+    {
+        printf( "*** Obj = %d  FlowRefs = %.2f  MapRefs = %2d\n", iObj, pBest->nFlowRefs, pBest->nMapRefs );
+        for ( i = 0; i < nCutsR; i++ )
+            Mf_CutPrint( p, pCutsR[i] );
+        printf( "\n" );
+    } 
+    // store the cutset
+    pBest->Flow = pCutsR[0]->Flow;
+    pBest->Delay = pCutsR[0]->Delay;
+    pBest->iCutSet = Mf_ManSaveCuts( p, pCutsR, nCutsR );
+    // verify
+    assert( nCutsR > 0 && nCutsR < nCutNum );
+//    assert( Mf_SetCheckArray(pCutsR, nCutsR) );
+    p->nCutCounts[pCutsR[0]->nLeaves]++;
+    p->CutCount[3] += nCutsR;
+}
+ 
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mf_ManSetFlowRefs( Gia_Man_t * p, Vec_Int_t * vRefs )
+{
+    int fDiscount = 1;
+    Gia_Obj_t * pObj, * pCtrl, * pData0, * pData1; 
+    int i, Id;
+    Vec_IntFill( vRefs, Gia_ManObjNum(p), 0 );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) )
+            Vec_IntAddToEntry( vRefs, Gia_ObjFaninId0(pObj, i), 1 );
+        if ( Gia_ObjIsAnd(Gia_ObjFanin1(pObj)) )
+            Vec_IntAddToEntry( vRefs, Gia_ObjFaninId1(pObj, i), 1 );
+        if ( p->pMuxes )
+        {
+            if ( Gia_ObjIsMuxId(p, i) && Gia_ObjIsAnd(Gia_ObjFanin2(p, pObj)) )
+                Vec_IntAddToEntry( vRefs, Gia_ObjFaninId2(p, i), 1 );
+        }
+        else if ( fDiscount && Gia_ObjIsMuxType(pObj) ) // discount XOR/MUX
+        {
+            pCtrl  = Gia_Regular(Gia_ObjRecognizeMux(pObj, &pData1, &pData0));
+            pData0 = Gia_Regular(pData0);
+            pData1 = Gia_Regular(pData1);
+            if ( Gia_ObjIsAnd(pCtrl) )
+                Vec_IntAddToEntry( vRefs, Gia_ObjId(p, pCtrl), -1 );
+            if ( pData0 == pData1 && Gia_ObjIsAnd(pData0) )
+                Vec_IntAddToEntry( vRefs, Gia_ObjId(p, pData0), -1 );
+        }
+    }
+    Gia_ManForEachCoDriverId( p, Id, i )
+        if ( Gia_ObjIsAnd(Gia_ManObj(p, Id)) )
+            Vec_IntAddToEntry( vRefs, Id, 1 );
+    for ( i = 0; i < Vec_IntSize(vRefs); i++ )
+        Vec_IntUpdateEntry( vRefs, i, 1 );
+}
+int Mf_ManSetMapRefs( Mf_Man_t * p )
+{
+    float Coef = 1.0 / (1.0 + (p->Iter + 1) * (p->Iter + 1));
+    int * pCut, i, k, Id;
+    // compute delay
+    int Delay = 0;
+    Gia_ManForEachCoDriverId( p->pGia, Id, i )
+        Delay = Abc_MaxInt( Delay, Mf_ManObj(p, Id)->Delay );
+    // check delay target
+    if ( p->pPars->DelayTarget == -1 && p->pPars->nRelaxRatio )
+        p->pPars->DelayTarget = (int)((float)Delay * (100.0 + p->pPars->nRelaxRatio) / 100.0);
+    if ( p->pPars->DelayTarget != -1 )
+    {
+        if ( Delay < p->pPars->DelayTarget + 0.01 )
+            Delay = p->pPars->DelayTarget;
+        else if ( p->pPars->nRelaxRatio == 0 )
+            Abc_Print( 0, "Relaxing user-specified delay target from %d to %d.\n", p->pPars->DelayTarget, Delay );
+    }
+    p->pPars->Delay = Delay;
+    // check references
+//    Gia_ManForEachAndId( p->pGia, i )
+//        assert( Mf_ManObj(p, i)->nMapRefs == 0 );
+    // compute area and edges
+    if ( !p->fUseEla )
+        Gia_ManForEachCoDriverId( p->pGia, Id, i )
+            Mf_ObjMapRefInc( p, Id );
+    p->pPars->Area = p->pPars->Edge = p->pPars->Clause = 0;
+    Gia_ManForEachAndReverseId( p->pGia, i )
+    {
+        if ( !Mf_ObjMapRefNum(p, i) )
+            continue;
+        pCut = Mf_ObjCutBest( p, i );
+        if ( !p->fUseEla )
+            for ( k = 1; k <= Mf_CutSize(pCut); k++ )
+                Mf_ObjMapRefInc( p, pCut[k] );
+        p->pPars->Edge += Mf_CutSize(pCut);
+        p->pPars->Area++;
+        if ( p->pPars->fGenCnf )
+            p->pPars->Clause += Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut));
+    }
+    // blend references
+    for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ )
+        p->pLfObjs[i].nFlowRefs = Coef * p->pLfObjs[i].nFlowRefs + (1.0 - Coef) * Abc_MaxFloat(1, p->pLfObjs[i].nMapRefs);
+//        p->pLfObjs[i]. = 0.2 * p->pLfObjs[i]. + 0.8 * Abc_MaxFloat(1, p->pLfObjs[i].nMapRefs);
+    return p->pPars->Area;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Mf_ManDeriveMapping( Mf_Man_t * p )
+{
+    Vec_Int_t * vMapping;
+    int i, k, * pCut;
+    assert( !p->pPars->fCutMin && p->pGia->vMapping == NULL );
+    vMapping = Vec_IntAlloc( Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 );
+    Vec_IntFill( vMapping, Gia_ManObjNum(p->pGia), 0 );
+    Gia_ManForEachAndId( p->pGia, i )
+    {
+        if ( !Mf_ObjMapRefNum(p, i) )
+            continue;
+        pCut = Mf_ObjCutBest( p, i );
+        Vec_IntWriteEntry( vMapping, i, Vec_IntSize(vMapping) );
+        Vec_IntPush( vMapping, Mf_CutSize(pCut) );
+        for ( k = 1; k <= Mf_CutSize(pCut); k++ )
+            Vec_IntPush( vMapping, pCut[k] );
+        Vec_IntPush( vMapping, i );
+    }
+    assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) );
+    p->pGia->vMapping = vMapping;
+    return p->pGia;
+}
+Gia_Man_t * Mf_ManDeriveMappingCoarse( Mf_Man_t * p )
+{
+    Gia_Man_t * pNew, * pGia = p->pGia;
+    Gia_Obj_t * pObj;
+    int i, k, * pCut;
+    assert( !p->pPars->fCutMin && pGia->pMuxes );
+    // create new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(pGia) );
+    pNew->pName = Abc_UtilStrsav( pGia->pName );
+    pNew->pSpec = Abc_UtilStrsav( pGia->pSpec );
+    // map primary inputs
+    Gia_ManConst0(pGia)->Value = 0;
+    Gia_ManForEachCi( pGia, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    // start mapping
+    pNew->vMapping = Vec_IntAlloc( Gia_ManObjNum(pGia) + 2*Gia_ManXorNum(pGia) + 2*Gia_ManMuxNum(pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 );
+    Vec_IntFill( pNew->vMapping, Gia_ManObjNum(pGia) + 2*Gia_ManXorNum(pGia) + 2*Gia_ManMuxNum(pGia), 0 );
+    // iterate through nodes used in the mapping
+    Gia_ManForEachAnd( pGia, pObj, i )
+    {
+        if ( Gia_ObjIsMuxId(pGia, i) )
+            pObj->Value = Gia_ManAppendMux( pNew, Gia_ObjFanin2Copy(pGia, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) );
+        else if ( Gia_ObjIsXor(pObj) )
+            pObj->Value = Gia_ManAppendXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else 
+            pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        if ( !Mf_ObjMapRefNum(p, i) )
+            continue;
+        pCut = Mf_ObjCutBest( p, i );
+        Vec_IntWriteEntry( pNew->vMapping, Abc_Lit2Var(pObj->Value), Vec_IntSize(pNew->vMapping) );
+        Vec_IntPush( pNew->vMapping, Mf_CutSize(pCut));
+        for ( k = 1; k <= Mf_CutSize(pCut); k++ )
+            Vec_IntPush( pNew->vMapping, Abc_Lit2Var(Gia_ManObj(pGia, pCut[k])->Value) );
+        Vec_IntPush( pNew->vMapping, Abc_Lit2Var(pObj->Value) );
+    }
+    Gia_ManForEachCo( pGia, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) );
+    assert( Vec_IntCap(pNew->vMapping) == 16 || Vec_IntSize(pNew->vMapping) == Vec_IntCap(pNew->vMapping) );
+    return pNew;
+}
+Gia_Man_t * Mf_ManDeriveMappingGia( Mf_Man_t * p )
+{
+    Gia_Man_t * pNew; 
+    Gia_Obj_t * pObj; 
+    Vec_Int_t * vCopies   = Vec_IntStartFull( Gia_ManObjNum(p->pGia) );
+    Vec_Int_t * vMapping  = Vec_IntStart( 2 * Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + 2 * (int)p->pPars->Area );
+    Vec_Int_t * vMapping2 = Vec_IntStart( (int)p->pPars->Edge + 2 * (int)p->pPars->Area + 1000 );
+    Vec_Int_t * vCover    = Vec_IntAlloc( 1 << 16 );
+    Vec_Int_t * vLeaves   = Vec_IntAlloc( 16 );
+    int i, k, Id, iLit, * pCut;
+    word uTruth = 0, * pTruth = &uTruth;
+    assert( p->pPars->fCutMin );
+    // create new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p->pGia) );
+    pNew->pName = Abc_UtilStrsav( p->pGia->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pGia->pSpec );
+    // map primary inputs
+    Vec_IntWriteEntry( vCopies, 0, 0 );
+    Gia_ManForEachCiId( p->pGia, Id, i )
+        Vec_IntWriteEntry( vCopies, Id, Gia_ManAppendCi(pNew) );
+    // iterate through nodes used in the mapping
+    Gia_ManForEachAnd( p->pGia, pObj, i )
+    {
+        if ( !Mf_ObjMapRefNum(p, i) )
+            continue;
+        pCut = Mf_ObjCutBest( p, i );
+        if ( Mf_CutSize(pCut) == 0 )
+        {
+            assert( Abc_Lit2Var(Mf_CutFunc(pCut)) == 0 );
+            Vec_IntWriteEntry( vCopies, i, Mf_CutFunc(pCut) );
+            continue;
+        }
+        if ( Mf_CutSize(pCut) == 1 )
+        {
+            assert( Abc_Lit2Var(Mf_CutFunc(pCut)) == 1 );
+            iLit = Vec_IntEntry( vCopies, pCut[1] );
+            Vec_IntWriteEntry( vCopies, i, Abc_LitNotCond(iLit, Abc_LitIsCompl(Mf_CutFunc(pCut))) );
+            continue;
+        }
+        Vec_IntClear( vLeaves );
+        for ( k = 1; k <= Mf_CutSize(pCut); k++ )
+            Vec_IntPush( vLeaves, Vec_IntEntry(vCopies, pCut[k]) );
+        pTruth = Vec_MemReadEntry( p->vTtMem, Abc_Lit2Var(Mf_CutFunc(pCut)) );
+        iLit = Kit_TruthToGia( pNew, (unsigned *)pTruth, Vec_IntSize(vLeaves), vCover, vLeaves, 0 );
+        Vec_IntWriteEntry( vCopies, i, Abc_LitNotCond(iLit, Abc_LitIsCompl(Mf_CutFunc(pCut))) );
+        // create mapping
+        Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLit), Vec_IntSize(vMapping2) );
+        Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) );
+        Vec_IntForEachEntry( vLeaves, iLit, k )
+            Vec_IntPush( vMapping2, Abc_Lit2Var(iLit) );
+        Vec_IntPush( vMapping2, Abc_Lit2Var(Vec_IntEntry(vCopies, i)) );
+    }
+    Gia_ManForEachCo( p->pGia, pObj, i )
+    {
+        iLit = Vec_IntEntry( vCopies, Gia_ObjFaninId0p(p->pGia, pObj) );
+        iLit = Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) );
+    }
+    Vec_IntFree( vCopies );
+    Vec_IntFree( vCover );
+    Vec_IntFree( vLeaves );
+    // finish mapping 
+    if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) )
+        Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) );
+    else
+        Vec_IntFillExtra( vMapping, Gia_ManObjNum(pNew), 0 );
+    assert( Vec_IntSize(vMapping) == Gia_ManObjNum(pNew) );
+    Vec_IntForEachEntry( vMapping, iLit, i )
+        if ( iLit > 0 )
+            Vec_IntAddToEntry( vMapping, i, Gia_ManObjNum(pNew) );
+    Vec_IntAppend( vMapping, vMapping2 );
+    Vec_IntFree( vMapping2 );
+    // attach mapping and packing
+    assert( pNew->vMapping == NULL );
+    pNew->vMapping = vMapping;
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p->pGia) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mf_Man_t * Mf_ManAlloc( Gia_Man_t * pGia, Jf_Par_t * pPars )
+{
+    Mf_Man_t * p;
+    Vec_Int_t * vFlowRefs;
+    int i, Entry;
+    assert( pPars->nCutNum > 1  && pPars->nCutNum <= MF_CUT_MAX );
+    assert( pPars->nLutSize > 1 && pPars->nLutSize <= MF_LEAF_MAX );
+    ABC_FREE( pGia->pRefs );
+    Vec_IntFreeP( &pGia->vMapping );
+    if ( Gia_ManHasChoices(pGia) )
+        Gia_ManSetPhase(pGia);
+    p = ABC_CALLOC( Mf_Man_t, 1 );
+    p->clkStart  = Abc_Clock();
+    p->pGia      = pGia;
+    p->pPars     = pPars;
+    p->vTtMem    = pPars->fCutMin ? Vec_MemAllocForTT( pPars->nLutSize, 0 ) : NULL;
+    p->pLfObjs   = ABC_CALLOC( Mf_Obj_t, Gia_ManObjNum(pGia) );
+    p->iCur      = 2;
+    Vec_PtrGrow( &p->vPages, 256 );
+    if ( pPars->fGenCnf )
+    {
+        Vec_IntGrow( &p->vCnfSizes, 10000 );
+        Vec_IntPush( &p->vCnfSizes, 1 );
+        Vec_IntPush( &p->vCnfSizes, 2 );
+        Vec_IntGrow( &p->vCnfMem, 10000 );
+    }
+    vFlowRefs = Vec_IntAlloc(0);
+    Mf_ManSetFlowRefs( pGia, vFlowRefs );
+    Vec_IntForEachEntry( vFlowRefs, Entry, i )
+        p->pLfObjs[i].nFlowRefs = Entry;
+    Vec_IntFree(vFlowRefs);
+    return p;
+}
+void Mf_ManFree( Mf_Man_t * p )
+{
+    assert( !p->pPars->fGenCnf || Vec_IntSize(&p->vCnfSizes) == Vec_MemEntryNum(p->vTtMem) );
+    if ( p->pPars->fCutMin )
+        Vec_MemHashFree( p->vTtMem );
+    if ( p->pPars->fCutMin )
+        Vec_MemFree( p->vTtMem );
+    Vec_PtrFreeData( &p->vPages );
+    ABC_FREE( p->vCnfSizes.pArray );
+    ABC_FREE( p->vCnfMem.pArray );
+    ABC_FREE( p->vPages.pArray );
+    ABC_FREE( p->pLfObjs );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mf_ManSetDefaultPars( Jf_Par_t * pPars )
+{
+    memset( pPars, 0, sizeof(Jf_Par_t) );
+    pPars->nLutSize     =  6;
+    pPars->nCutNum      =  8;
+    pPars->nProcNum     =  0;
+    pPars->nRounds      =  2;
+    pPars->nRoundsEla   =  1;
+    pPars->nRelaxRatio  =  0;
+    pPars->nCoarseLimit =  3;
+    pPars->nAreaTuner   =  1;
+    pPars->nVerbLimit   =  5;
+    pPars->DelayTarget  = -1;
+    pPars->fAreaOnly    =  0;
+    pPars->fOptEdge     =  1; 
+    pPars->fCoarsen     =  1;
+    pPars->fCutMin      =  0;
+    pPars->fGenCnf      =  0;
+    pPars->fPureAig     =  0;
+    pPars->fVerbose     =  0;
+    pPars->fVeryVerbose =  0;
+    pPars->nLutSizeMax  =  MF_LEAF_MAX;
+    pPars->nCutNumMax   =  MF_CUT_MAX;
+}
+void Mf_ManPrintStats( Mf_Man_t * p, char * pTitle )
+{
+    if ( !p->pPars->fVerbose )
+        return;
+    printf( "%s :  ", pTitle );
+    printf( "Level =%6lu   ",   p->pPars->Delay );
+    printf( "Area =%9lu   ",  p->pPars->Area );
+    printf( "Edge =%9lu   ",  p->pPars->Edge );
+    if ( p->pPars->fGenCnf )
+        printf( "CNF =%9lu   ", p->pPars->Clause );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
+    fflush( stdout );
+}
+void Mf_ManPrintInit( Mf_Man_t * p )
+{
+    if ( !p->pPars->fVerbose )
+        return;
+    printf( "LutSize = %d  ", p->pPars->nLutSize );
+    printf( "CutNum = %d  ",  p->pPars->nCutNum );
+    printf( "Iter = %d  ",    p->pPars->nRounds + p->pPars->nRoundsEla );
+    printf( "Edge = %d  ",    p->pPars->fOptEdge );
+    printf( "CutMin = %d  ",  p->pPars->fCutMin );
+    printf( "Coarse = %d  ",  p->pPars->fCoarsen );
+    printf( "CNF = %d  ",     p->pPars->fGenCnf );
+    printf( "\n" );
+    printf( "Computing cuts...\r" );
+    fflush( stdout );
+}
+void Mf_ManPrintQuit( Mf_Man_t * p, Gia_Man_t * pNew )
+{
+    float MemGia   = Gia_ManMemory(p->pGia) / (1<<20);
+    float MemMan   = 1.0 * sizeof(Mf_Obj_t) * Gia_ManObjNum(p->pGia) / (1<<20);
+    float MemCuts  = 1.0 * sizeof(int) * (1 << 16) * Vec_PtrSize(&p->vPages) / (1<<20);
+    float MemTt    = p->vTtMem ? Vec_MemMemory(p->vTtMem) / (1<<20) : 0;
+    float MemMap   = Vec_IntMemory(pNew->vMapping) / (1<<20);
+    if ( p->CutCount[0] == 0 )
+        p->CutCount[0] = 1;
+    if ( !p->pPars->fVerbose )
+        return;
+    printf( "CutPair = %.0f  ",         p->CutCount[0] );
+    printf( "Merge = %.0f (%.2f %%)  ", p->CutCount[1], 100.0*p->CutCount[1]/p->CutCount[0] );
+    printf( "Eval = %.0f (%.2f %%)  ",  p->CutCount[2], 100.0*p->CutCount[2]/p->CutCount[0] );
+    printf( "Cut = %.0f (%.2f %%)  ",   p->CutCount[3], 100.0*p->CutCount[3]/p->CutCount[0] );
+    printf( "\n" );
+    printf( "Gia = %.2f MB  ",          MemGia );
+    printf( "Man = %.2f MB  ",          MemMan ); 
+    printf( "Cut = %.2f MB   ",         MemCuts );
+    printf( "Map = %.2f MB  ",          MemMap ); 
+    printf( "TT = %.2f MB  ",           MemTt ); 
+    printf( "Total = %.2f MB",          MemGia + MemMan + MemCuts + MemMap + MemTt ); 
+    printf( "\n" );
+    if ( 1 )
+    {
+        int i;
+        for ( i = 0; i <= p->pPars->nLutSize; i++ )
+            printf( "%d = %d  ", i, p->nCutCounts[i] );
+        if ( p->vTtMem )
+            printf( "TT = %d (%.2f %%)  ", Vec_MemEntryNum(p->vTtMem), 100.0 * Vec_MemEntryNum(p->vTtMem) / p->CutCount[2] );
+        Abc_PrintTime( 1, "Time",    Abc_Clock() - p->clkStart );
+    }
+    fflush( stdout );
+}
+void Mf_ManComputeCuts( Mf_Man_t * p )
+{
+    int i;
+    Gia_ManForEachAndId( p->pGia, i )
+        Mf_ObjMergeOrder( p, i );
+    Mf_ManSetMapRefs( p );
+    Mf_ManPrintStats( p, p->fUseEla ? "Ela  " : (p->Iter ? "Area " : "Delay") );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Flow and area.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mf_CutRef_rec( Mf_Man_t * p, int * pCut )
+{
+    int i, Count = Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut));
+    for ( i = 1; i <= Mf_CutSize(pCut); i++ )
+        if ( !Mf_ObjMapRefInc(p, pCut[i]) && Mf_ManObj(p, pCut[i])->iCutSet )
+            Count += Mf_CutRef_rec( p, Mf_ObjCutBest(p, pCut[i]) );
+    return Count;
+}
+int Mf_CutDeref_rec( Mf_Man_t * p, int * pCut )
+{
+    int i, Count = Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut));
+    for ( i = 1; i <= Mf_CutSize(pCut); i++ )
+        if ( !Mf_ObjMapRefDec(p, pCut[i]) && Mf_ManObj(p, pCut[i])->iCutSet )
+            Count += Mf_CutDeref_rec( p, Mf_ObjCutBest(p, pCut[i]) );
+    return Count;
+}
+static inline int Mf_CutAreaDerefed( Mf_Man_t * p, int * pCut )
+{
+    int Ela1 = Mf_CutRef_rec( p, pCut );
+    int Ela2 = Mf_CutDeref_rec( p, pCut );
+    assert( Ela1 == Ela2 );
+    return Ela1;
+}
+static inline float Mf_CutFlow( Mf_Man_t * p, int * pCut, int * pTime )
+{
+    Mf_Obj_t * pObj;
+    float Flow = 0; 
+    int i, Time = 0; 
+    for ( i = 1; i <= Mf_CutSize(pCut); i++ )
+    {
+        pObj = Mf_ManObj( p, pCut[i] );
+        Time = Abc_MaxInt( Time, pObj->Delay );
+        Flow += pObj->Flow;
+    }
+    *pTime = Time + 1;
+    return Flow + Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut));
+}
+static inline void Mf_ObjComputeBestCut( Mf_Man_t * p, int iObj )
+{
+    Mf_Obj_t * pBest = Mf_ManObj(p, iObj);
+    int * pCutSet = Mf_ObjCutSet( p, iObj );
+    int * pCut, * pCutBest = NULL;
+    int Value1 = -1, Value2 = -1;
+    int i, Time = 0, TimeBest = ABC_INFINITY; 
+    float Flow, FlowBest = ABC_INFINITY;
+    if ( p->fUseEla && pBest->nMapRefs )
+        Value1 = Mf_CutDeref_rec( p, Mf_ObjCutBest(p, iObj) );
+    Mf_SetForEachCut( pCutSet, pCut, i )
+    {
+        assert( !Mf_CutIsTriv(pCut, iObj) );
+        assert( Mf_CutSize(pCut) <= p->pPars->nLutSize );
+        Flow = p->fUseEla ? Mf_CutAreaDerefed(p, pCut) : Mf_CutFlow(p, pCut, &Time);
+        if ( pCutBest == NULL || FlowBest > Flow || (FlowBest == Flow && TimeBest > Time) )
+            pCutBest = pCut, FlowBest = Flow, TimeBest = Time;
+    }
+    assert( pCutBest != NULL );
+    if ( p->fUseEla && pBest->nMapRefs )
+        Value1 = Mf_CutRef_rec( p, pCutBest );
+    else
+        pBest->nMapRefs = 0;
+    assert( Value1 >= Value2 );
+    if ( p->fUseEla )
+        Mf_CutFlow( p, pCutBest, &TimeBest );
+    pBest->Delay = TimeBest;
+    pBest->Flow  = FlowBest / Mf_ManObj(p, iObj)->nFlowRefs;
+    Mf_ObjSetBestCut( pCutSet, pCutBest );
+//    Mf_CutPrint( Mf_ObjCutBest(p, iObj) ); printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Technology mappping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mf_ManComputeMapping( Mf_Man_t * p )
+{
+    int i;
+    Gia_ManForEachAndId( p->pGia, i )
+        Mf_ObjComputeBestCut( p, i );
+    Mf_ManSetMapRefs( p );
+    Mf_ManPrintStats( p, p->fUseEla ? "Ela  " : (p->Iter ? "Area " : "Delay") );
+}
+Gia_Man_t * Mf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars )
+{
+    Mf_Man_t * p;
+    Gia_Man_t * pNew, * pCls;
+    if ( pPars->fGenCnf )
+        pPars->fCutMin = 1;
+    if ( Gia_ManHasChoices(pGia) )
+        pPars->fCutMin = 1, pPars->fCoarsen = 0; 
+    pCls = pPars->fCoarsen ? Gia_ManDupMuxes(pGia, pPars->nCoarseLimit) : pGia;
+    p = Mf_ManAlloc( pCls, pPars );
+    p->pGia0 = pGia;
+    if ( pPars->fVerbose && pPars->fCoarsen )
+    {
+        printf( "Initial " );  Gia_ManPrintMuxStats( pGia );  printf( "\n" );
+        printf( "Derived " );  Gia_ManPrintMuxStats( pCls );  printf( "\n" );
+    }
+    Mf_ManPrintInit( p );
+    Mf_ManComputeCuts( p );
+    for ( p->Iter = 1; p->Iter < p->pPars->nRounds; p->Iter++ )
+        Mf_ManComputeMapping( p );
+    p->fUseEla = 1;
+    for ( ; p->Iter < p->pPars->nRounds + pPars->nRoundsEla; p->Iter++ )
+        Mf_ManComputeMapping( p );
+    if ( pPars->fVeryVerbose && pPars->fCutMin )
+        Vec_MemDumpTruthTables( p->vTtMem, Gia_ManName(p->pGia), pPars->nLutSize );
+    if ( pPars->fCutMin )
+        pNew = Mf_ManDeriveMappingGia( p );
+    else if ( pPars->fCoarsen )
+        pNew = Mf_ManDeriveMappingCoarse( p );
+    else
+        pNew = Mf_ManDeriveMapping( p );
+    if ( p->pPars->fGenCnf )
+        pGia->pData = Mf_ManDeriveCnf( p, p->pPars->fCnfObjIds, p->pPars->fAddOrCla );
+//    if ( p->pPars->fGenCnf )
+//        Mf_ManProfileTruths( p );
+    Gia_ManMappingVerify( pNew );
+    Mf_ManPrintQuit( p, pNew );
+    Mf_ManFree( p );
+    if ( pCls != pGia )
+        Gia_ManStop( pCls );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [CNF generation]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose )
+{
+    Gia_Man_t * pNew;
+    Jf_Par_t Pars, * pPars = &Pars;
+    assert( nLutSize >= 3 && nLutSize <= 8 );
+    Mf_ManSetDefaultPars( pPars );
+    pPars->fGenCnf    = 1;
+    pPars->fCoarsen   = !fCnfObjIds;
+    pPars->nLutSize   = nLutSize;
+    pPars->fCnfObjIds = fCnfObjIds;
+    pPars->fAddOrCla  = fAddOrCla;
+    pPars->fVerbose   = fVerbose;
+    pNew = Mf_ManPerformMapping( pGia, pPars );
+    Gia_ManStopP( &pNew );
+//    Cnf_DataPrint( (Cnf_Dat_t *)pGia->pData, 1 );
+    return pGia->pData;
+}
+void Mf_ManDumpCnf( Gia_Man_t * p, char * pFileName, int nLutSize, int fVerbose )
+{
+    abctime clk = Abc_Clock();
+    Cnf_Dat_t * pCnf;
+    pCnf = Mf_ManGenerateCnf( p, nLutSize, 0, 1, fVerbose );
+    Cnf_DataWriteIntoFile( pCnf, pFileName, 0, NULL, NULL );
+//    if ( fVerbose )
+    {
+        printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    Cnf_DataFree(pCnf);
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaMfs.c b/abc-build/src/aig/gia/giaMfs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaMfs.c
@@ -0,0 +1,390 @@
+/**CFile****************************************************************
+
+  FileName    [giaMfs.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Interface with the MFS package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaMfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "bool/kit/kit.h"
+#include "opt/sfm/sfm.h"
+#include "misc/tim/tim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static word s_ElemVar  = ABC_CONST(0xAAAAAAAAAAAAAAAA);
+static word s_ElemVar2 = ABC_CONST(0xCCCCCCCCCCCCCCCC);
+
+extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManExtractMfs_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vId2Mfs, Vec_Wec_t * vFanins, Vec_Str_t * vFixed, Vec_Wrd_t * vTruths, Vec_Wrd_t * vTruthsTemp )
+{
+    Vec_Int_t * vArray;
+    int i, Fanin;
+    Gia_Obj_t * pObj = Gia_ManObj( p, iObj );
+    assert( Gia_ObjIsLut(p, iObj) );
+    if ( !~pObj->Value )
+        return;
+    Gia_LutForEachFanin( p, iObj, Fanin, i )
+        Gia_ManExtractMfs_rec( p, Fanin, vId2Mfs, vFanins, vFixed, vTruths, vTruthsTemp );
+    pObj->Value = Vec_WecSize(vFanins);
+    vArray = Vec_WecPushLevel( vFanins );
+    Vec_IntGrow( vArray, Gia_ObjLutSize(p, iObj) );
+    Gia_LutForEachFanin( p, iObj, Fanin, i )
+        Vec_IntPush( vArray, Gia_ManObj(p, Fanin)->Value );
+    Vec_StrPush( vFixed, (char)0 );
+    Vec_WrdPush( vTruths, Gia_ObjComputeTruthTable6Lut(p, iObj, vTruthsTemp) );
+    Vec_IntWriteEntry( vId2Mfs, iObj, pObj->Value );
+}
+void Gia_ManExtractMfs_rec2( Gia_Man_t * p, int iObj, Vec_Int_t * vId2Mfs, Vec_Wec_t * vFanins, Vec_Str_t * vFixed, Vec_Wrd_t * vTruths )
+{
+    Vec_Int_t * vArray;
+    Gia_Obj_t * pObj = Gia_ManObj( p, iObj );
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManExtractMfs_rec2( p, Gia_ObjFaninId0(pObj, iObj), vId2Mfs, vFanins, vFixed, vTruths );
+    Gia_ManExtractMfs_rec2( p, Gia_ObjFaninId1(pObj, iObj), vId2Mfs, vFanins, vFixed, vTruths );
+    pObj->Value = Vec_WecSize(vFanins);
+    vArray = Vec_WecPushLevel( vFanins );
+    Vec_IntGrow( vArray, 2 );
+    Vec_IntPush( vArray, Gia_ObjFanin0(pObj)->Value );
+    Vec_IntPush( vArray, Gia_ObjFanin1(pObj)->Value );
+    Vec_StrPush( vFixed, (char)1 );
+    Vec_WrdPush( vTruths, (Gia_ObjFaninC0(pObj) ? ~s_ElemVar : s_ElemVar) & (Gia_ObjFaninC1(pObj) ? ~s_ElemVar2 : s_ElemVar2) );
+    Vec_IntWriteEntry( vId2Mfs, iObj, pObj->Value );
+}
+Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p, Gia_Man_t * pBoxes, Vec_Int_t ** pvId2Mfs )
+{
+    Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
+    Vec_Int_t * vPoNodes;
+    Vec_Int_t * vId2Mfs;
+    Vec_Wec_t * vFanins;
+    Vec_Str_t * vFixed;
+    Vec_Wrd_t * vTruths, * vTruthsTemp;
+    Vec_Int_t * vArray;
+    Gia_Obj_t * pObj, * pObjBox;
+    int i, k, nRealPis, nRealPos, nPiNum, nPoNum, curCi, curCo;
+    assert( pManTime == NULL || Tim_ManCiNum(pManTime) == Gia_ManCiNum(p) );
+    assert( pManTime == NULL || Tim_ManCoNum(pManTime) == Gia_ManCoNum(p) );
+    // get the real number of PIs and POs
+    nRealPis = pManTime ? Tim_ManPiNum(pManTime) : Gia_ManCiNum(p);
+    nRealPos = pManTime ? Tim_ManPoNum(pManTime) : Gia_ManCoNum(p);
+    // create mapping from GIA into MFS
+    vId2Mfs  = Vec_IntStartFull( Gia_ManObjNum(p) );
+    // collect PO nodes
+    vPoNodes = Vec_IntAlloc( 1000 );
+    // create the arrays
+    vFanins  = Vec_WecAlloc( 1000 );
+    vFixed   = Vec_StrAlloc( 1000 );
+    vTruths  = Vec_WrdAlloc( 1000 );
+    vTruthsTemp = Vec_WrdStart( Gia_ManObjNum(p) );
+    // assign MFS ids to primary inputs
+    Gia_ManFillValue( p );
+    for ( i = 0; i < nRealPis; i++ )
+    {
+        pObj = Gia_ManPi( p, i );
+        pObj->Value = Vec_WecSize(vFanins);
+        Vec_WecPushLevel( vFanins );
+        Vec_StrPush( vFixed, (char)0 );
+        Vec_WrdPush( vTruths, (word)0 );
+        Vec_IntWriteEntry( vId2Mfs, Gia_ObjId(p, pObj), pObj->Value );
+    }
+    // assign MFS ids to black box outputs
+    curCi = nRealPis;
+    curCo = 0;
+    if ( pManTime )
+    for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ )
+    {
+        if ( !Tim_ManBoxIsBlack(pManTime, i) )
+        {
+            // collect POs
+            for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ )
+            {
+                pObj = Gia_ManPo( p, curCo + k );
+                Vec_IntPush( vPoNodes, Gia_ObjId(p, pObj) );
+            }
+            // assign values to the PIs
+            for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ )
+            {
+                pObj = Gia_ManPi( p, curCi + k );
+                pObj->Value = Vec_WecSize(vFanins);
+                Vec_WecPushLevel( vFanins );
+                Vec_StrPush( vFixed, (char)1 );
+                Vec_WrdPush( vTruths, (word)0 );
+                Vec_IntWriteEntry( vId2Mfs, Gia_ObjId(p, pObj), pObj->Value );
+            }
+        }
+        curCo += Tim_ManBoxInputNum(pManTime, i);
+        curCi += Tim_ManBoxOutputNum(pManTime, i);
+    }
+    // collect POs
+//    for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ )
+    for ( i = Gia_ManCoNum(p) - nRealPos; i < Gia_ManCoNum(p); i++ )
+    {
+        pObj = Gia_ManPo( p, i );
+        Vec_IntPush( vPoNodes, Gia_ObjId(p, pObj) );
+    }
+    curCo += nRealPos;
+    // verify counts
+    assert( curCi == Gia_ManPiNum(p) );
+    assert( curCo == Gia_ManPoNum(p) );
+    // remeber the end of PIs
+    nPiNum = Vec_WecSize(vFanins);
+    nPoNum = Vec_IntSize(vPoNodes);
+    // assign value to constant node
+    pObj = Gia_ManConst0(p);
+    Vec_IntWriteEntry( vId2Mfs, Gia_ObjId(p, pObj), Vec_WecSize(vFanins) );
+    pObj->Value = Vec_WecSize(vFanins);
+    Vec_WecPushLevel( vFanins );
+    Vec_StrPush( vFixed, (char)0 );
+    Vec_WrdPush( vTruths, (word)0 );
+    Vec_IntWriteEntry( vId2Mfs, Gia_ObjId(p, pObj), pObj->Value );
+    // create internal nodes
+    curCi = nRealPis;
+    curCo = 0;
+    if ( pManTime )
+    for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ )
+    {
+        // recursively add for box inputs
+        Gia_ManIncrementTravId( pBoxes );
+        for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ )
+        {
+            // build logic
+            pObj = Gia_ManPo( p, curCo + k );
+            Gia_ManExtractMfs_rec( p, Gia_ObjFaninId0p(p, pObj), vId2Mfs, vFanins, vFixed, vTruths, vTruthsTemp );
+            // add buffer/inverter
+            pObj->Value = Vec_WecSize(vFanins);
+            vArray = Vec_WecPushLevel( vFanins );
+            Vec_IntGrow( vArray, 1 );
+            assert( !~Gia_ObjFanin0(pObj)->Value );
+            Vec_IntPush( vArray, Gia_ObjFanin0(pObj)->Value );
+            Vec_StrPush( vFixed, (char)0 );
+            Vec_WrdPush( vTruths, Gia_ObjFaninC0(pObj) ? ~s_ElemVar : s_ElemVar );
+            Vec_IntWriteEntry( vId2Mfs, Gia_ObjId(p, pObj), pObj->Value );
+            // transfer to the PI
+            pObjBox = Gia_ManPi( pBoxes, k );
+            pObjBox->Value = pObj->Value;
+            Gia_ObjSetTravIdCurrent( pBoxes, pObjBox );
+        }
+        if ( !Tim_ManBoxIsBlack(pManTime, i) )
+        {
+            pObjBox = Gia_ManConst0(pBoxes);
+            pObjBox->Value = Vec_WecSize(vFanins);
+            Vec_WecPushLevel( vFanins );
+            Vec_StrPush( vFixed, (char)0 );
+            Vec_WrdPush( vTruths, (word)0 );
+            Gia_ObjSetTravIdCurrent( pBoxes, pObjBox );
+            // add internal nodes and transfer
+            for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ )
+            {
+                // build logic
+                pObjBox = Gia_ManPo( pBoxes, curCi - Tim_ManPiNum(pManTime) + k );
+                Gia_ManExtractMfs_rec2( pBoxes, Gia_ObjFaninId0p(pBoxes, pObjBox), vId2Mfs, vFanins, vFixed, vTruths );
+                // add buffer/inverter
+                vArray = Vec_WecPushLevel( vFanins );
+                Vec_IntGrow( vArray, 1 );
+                assert( !~Gia_ObjFanin0(pObjBox)->Value );
+                Vec_IntPush( vArray, Gia_ObjFanin0(pObjBox)->Value );
+                Vec_StrPush( vFixed, (char)1 );
+                Vec_WrdPush( vTruths, Gia_ObjFaninC0(pObjBox) ? ~s_ElemVar : s_ElemVar );
+                // transfer to the PI
+                pObj = Gia_ManPi( p, curCi + k );
+                pObj->Value = pObjBox->Value;
+            }
+        }
+        curCo += Tim_ManBoxInputNum(pManTime, i);
+        curCi += Tim_ManBoxOutputNum(pManTime, i);
+    }
+    // create POs with buffers
+    Gia_ManForEachObjVec( vPoNodes, p, pObj, i )
+    {
+        Gia_ManExtractMfs_rec( p, Gia_ObjFaninId0p(p, pObj), vId2Mfs, vFanins, vFixed, vTruths, vTruthsTemp );
+        pObj->Value = Vec_WecSize(vFanins);
+        // add buffer/inverter
+        vArray = Vec_WecPushLevel( vFanins );
+        Vec_IntGrow( vArray, 1 );
+        assert( !~Gia_ObjFanin0(pObj)->Value );
+        Vec_IntPush( vArray, Gia_ObjFanin0(pObj)->Value );
+        Vec_StrPush( vFixed, (char)0 );
+        Vec_WrdPush( vTruths, Gia_ObjFaninC0(pObj) ? ~s_ElemVar : s_ElemVar );
+        Vec_IntWriteEntry( vId2Mfs, Gia_ObjId(p, pObj), pObj->Value );
+    }
+    Vec_IntFree( vPoNodes );
+    Vec_WrdFree( vTruthsTemp );
+    *pvId2Mfs = vId2Mfs;
+    return Sfm_NtkConstruct( vFanins, nPiNum, nPoNum, vFixed, NULL, vTruths );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManInsertMfs( Gia_Man_t * p, Sfm_Ntk_t * pNtk, Vec_Int_t * vId2Mfs )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vMfsTopo, * vMfs2New, * vArray, * vCover;
+    int i, k, Fanin, iMfsId, iLitNew;
+    word * pTruth;
+    // collect MFS nodes in the topo order
+    vMfsTopo = Sfm_NtkDfs( pNtk );
+    // create mapping from MFS to new GIA literals
+    vMfs2New = Vec_IntStartFull( Vec_IntCap(vMfsTopo) );
+    // start new GIA
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // map primary inputs
+    Gia_ManForEachCi( p, pObj, i )
+    {
+        iMfsId = Vec_IntEntry( vId2Mfs, Gia_ObjId(p, pObj) );
+        assert( iMfsId >= 0 );
+        Vec_IntWriteEntry( vMfs2New, iMfsId, Gia_ManAppendCi(pNew) );
+    }
+    // map internal nodes
+    vCover = Vec_IntAlloc( 1 << 16 );
+    Vec_IntForEachEntry( vMfsTopo, iMfsId, i )
+    {
+        assert( Sfm_NodeReadUsed(pNtk, iMfsId) );
+        pTruth = Sfm_NodeReadTruth( pNtk, iMfsId );
+        if ( pTruth[0] == 0 || ~pTruth[0] == 0 )
+        {
+            Vec_IntWriteEntry( vMfs2New, iMfsId, 0 );
+            continue;
+        }
+        vArray = Sfm_NodeReadFanins( pNtk, iMfsId ); // belongs to pNtk
+        Vec_IntForEachEntry( vArray, Fanin, k )
+        {
+            iLitNew = Vec_IntEntry( vMfs2New, Fanin );
+            assert( iLitNew >= 0 );
+            Vec_IntWriteEntry( vArray, k, iLitNew );            
+        }
+        // derive new function
+        iLitNew = Kit_TruthToGia( pNew, (unsigned *)pTruth, Vec_IntSize(vArray), vCover, vArray, 0 );
+        Vec_IntWriteEntry( vMfs2New, iMfsId, iLitNew );
+    }
+    Vec_IntFree( vCover );
+    // map output nodes
+    Gia_ManForEachCo( p, pObj, i )
+    {
+        iMfsId = Vec_IntEntry( vId2Mfs, Gia_ObjId(p, pObj) );
+        assert( iMfsId >= 0 );
+        vArray = Sfm_NodeReadFanins( pNtk, iMfsId ); // belongs to pNtk
+        assert( Vec_IntSize(vArray) == 1 );
+        // get the fanin
+        iLitNew = Vec_IntEntry( vMfs2New, Vec_IntEntry(vArray, 0) );
+        assert( iLitNew >= 0 );
+        // create CO
+        pTruth = Sfm_NodeReadTruth( pNtk, iMfsId );
+        assert( pTruth[0] == s_ElemVar || ~pTruth[0] == s_ElemVar );
+        Gia_ManAppendCo( pNew, Abc_LitNotCond(iLitNew, (int)(pTruth[0] != s_ElemVar)) );
+    }
+    Vec_IntFree( vMfs2New );
+    Vec_IntFree( vMfsTopo );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManPerformMfs( Gia_Man_t * p, Sfm_Par_t * pPars )
+{
+    Sfm_Ntk_t * pNtk;
+    Vec_Int_t * vId2Mfs;
+    Gia_Man_t * pNew;
+    int nFaninMax, nNodes;
+    assert( Gia_ManRegNum(p) == 0 );
+    assert( p->vMapping != NULL );
+    if ( p->pManTime != NULL && p->pAigExtra == NULL )
+    {
+        Abc_Print( 1, "Timing manager is given but there is no GIA of boxes.\n" );
+        return NULL;
+    }
+    // count fanouts
+    nFaninMax = Gia_ManLutSizeMax( p );
+    if ( nFaninMax > 6 )
+    {
+        Abc_Print( 1, "Currently \"&mfs\" cannot process the network containing nodes with more than 6 fanins.\n" );
+        return NULL;
+    }
+    // collect information
+    pNtk = Gia_ManExtractMfs( p, p->pAigExtra, &vId2Mfs );
+    // perform optimization
+    nNodes = Sfm_NtkPerform( pNtk, pPars );
+    // call the fast extract procedure
+    if ( nNodes == 0 )
+    {
+        Abc_Print( 1, "The network is not changed by \"&mfs\".\n" );
+        pNew = Gia_ManDup( p );
+        pNew->vMapping = Vec_IntDup( p->vMapping );
+    }
+    else
+    {
+        pNew = Gia_ManInsertMfs( p, pNtk, vId2Mfs );
+        if( pPars->fVerbose )
+            Abc_Print( 1, "The network has %d nodes changed by \"&mfs\".\n", nNodes );
+    }
+    Vec_IntFree( vId2Mfs );
+    Sfm_NtkFree( pNtk );
+    return pNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaMini.c b/abc-build/src/aig/gia/giaMini.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaMini.c
@@ -0,0 +1,189 @@
+/**CFile****************************************************************
+
+  FileName    [giaMini.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Reader/writer for MiniAIG.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaMini.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "base/main/main.h"
+#include "aig/miniaig/miniaig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Converts MiniAIG into GIA.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ObjFromMiniFanin0Copy( Gia_Man_t * pGia, Vec_Int_t * vCopies, Mini_Aig_t * p, int Id )
+{
+    int Lit = Mini_AigNodeFanin0( p, Id );
+    return Abc_LitNotCond( Vec_IntEntry(vCopies, Abc_Lit2Var(Lit)), Abc_LitIsCompl(Lit) );
+}
+int Gia_ObjFromMiniFanin1Copy( Gia_Man_t * pGia, Vec_Int_t * vCopies, Mini_Aig_t * p, int Id )
+{
+    int Lit = Mini_AigNodeFanin1( p, Id );
+    return Abc_LitNotCond( Vec_IntEntry(vCopies, Abc_Lit2Var(Lit)), Abc_LitIsCompl(Lit) );
+}
+Gia_Man_t * Gia_ManFromMiniAig( Mini_Aig_t * p )
+{
+    Gia_Man_t * pGia, * pTemp;
+    Vec_Int_t * vCopies;
+    int i, iGiaLit, nNodes;
+    // get the number of nodes
+    nNodes = Mini_AigNodeNum(p);
+    // create ABC network
+    pGia = Gia_ManStart( nNodes );
+    pGia->pName = Abc_UtilStrsav( "MiniAig" );
+    // create mapping from MiniAIG objects into ABC objects
+    vCopies = Vec_IntAlloc( nNodes );
+    Vec_IntPush( vCopies, 0 );
+    // iterate through the objects
+    Gia_ManHashAlloc( pGia );
+    for ( i = 1; i < nNodes; i++ )
+    {
+        if ( Mini_AigNodeIsPi( p, i ) )
+            iGiaLit = Gia_ManAppendCi(pGia);
+        else if ( Mini_AigNodeIsPo( p, i ) )
+            iGiaLit = Gia_ManAppendCo(pGia, Gia_ObjFromMiniFanin0Copy(pGia, vCopies, p, i));
+        else if ( Mini_AigNodeIsAnd( p, i ) )
+            iGiaLit = Gia_ManHashAnd(pGia, Gia_ObjFromMiniFanin0Copy(pGia, vCopies, p, i), Gia_ObjFromMiniFanin1Copy(pGia, vCopies, p, i));
+        else assert( 0 );
+        Vec_IntPush( vCopies, iGiaLit );
+    }
+    Gia_ManHashStop( pGia );
+    assert( Vec_IntSize(vCopies) == nNodes );
+    Vec_IntFree( vCopies );
+    Gia_ManSetRegNum( pGia, Mini_AigRegNum(p) );
+    pGia = Gia_ManCleanup( pTemp = pGia );
+    Gia_ManStop( pTemp );
+    return pGia;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts GIA into MiniAIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mini_Aig_t * Gia_ManToMiniAig( Gia_Man_t * pGia )
+{
+    Mini_Aig_t * p;
+    Gia_Obj_t * pObj;
+    int i;
+    // create the manager
+    p = Mini_AigStart();
+    Gia_ManConst0(pGia)->Value = Mini_AigLitConst0();
+    // create primary inputs
+    Gia_ManForEachCi( pGia, pObj, i )
+        pObj->Value = Mini_AigCreatePi(p);
+    // create internal nodes
+    Gia_ManForEachAnd( pGia, pObj, i )
+        pObj->Value = Mini_AigAnd( p, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    // create primary outputs
+    Gia_ManForEachCo( pGia, pObj, i )
+        pObj->Value = Mini_AigCreatePo( p, Gia_ObjFanin0Copy(pObj) );
+    // set registers
+    Mini_AigSetRegNum( p, Gia_ManRegNum(pGia) );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedures to input/output MiniAIG into/from internal GIA.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameGiaInputMiniAig( Abc_Frame_t * pAbc, void * p )
+{
+    Gia_Man_t * pGia;
+    if ( pAbc == NULL )
+        printf( "ABC framework is not initialized by calling Abc_Start()\n" );
+    pGia = Gia_ManFromMiniAig( (Mini_Aig_t *)p );
+    Abc_FrameUpdateGia( pAbc, pGia );
+//    Gia_ManDelete( pGia );
+}
+void * Abc_FrameGiaOutputMiniAig( Abc_Frame_t * pAbc )
+{
+    Gia_Man_t * pGia;
+    if ( pAbc == NULL )
+        printf( "ABC framework is not initialized by calling Abc_Start()\n" );
+    pGia = Abc_FrameReadGia( pAbc );
+    if ( pGia == NULL )
+        printf( "Current network in ABC framework is not defined.\n" );
+    return Gia_ManToMiniAig( pGia );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedures to read/write GIA to/from MiniAIG file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManReadMiniAig( char * pFileName )
+{
+    Mini_Aig_t * p = Mini_AigLoad( pFileName );
+    Gia_Man_t * pGia = Gia_ManFromMiniAig( p );
+    ABC_FREE( pGia->pName );
+    pGia->pName = Extra_FileNameGeneric( pFileName ); 
+    Mini_AigStop( p );
+    return pGia;
+}
+void Gia_ManWriteMiniAig( Gia_Man_t * pGia, char * pFileName )
+{
+    Mini_Aig_t * p = Gia_ManToMiniAig( pGia );
+    Mini_AigDump( p, pFileName );
+    Mini_AigStop( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaMuxes.c b/abc-build/src/aig/gia/giaMuxes.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaMuxes.c
@@ -0,0 +1,598 @@
+/**CFile****************************************************************
+
+  FileName    [giaMuxes.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Multiplexer profiling algorithm.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaMuxes.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/util/utilNam.h"
+#include "misc/vec/vecWec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Counts XORs and MUXes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCountMuxXor( Gia_Man_t * p, int * pnMuxes, int * pnXors )
+{
+    Gia_Obj_t * pObj, * pFan0, * pFan1; int i;
+    *pnMuxes = *pnXors = 0;
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        if ( !Gia_ObjIsMuxType(pObj) )
+            continue;
+        if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) )
+            (*pnXors)++;
+        else
+            (*pnMuxes)++;
+    }
+}
+void Gia_ManPrintMuxStats( Gia_Man_t * p )
+{
+    int nAnds, nMuxes, nXors, nTotal;
+    if ( p->pMuxes )
+    {
+        nAnds  = Gia_ManAndNum(p)-Gia_ManXorNum(p)-Gia_ManMuxNum(p);
+        nXors  = Gia_ManXorNum(p);
+        nMuxes = Gia_ManMuxNum(p);
+        nTotal = nAnds + 3*nXors + 3*nMuxes;
+    }
+    else 
+    {
+        Gia_ManCountMuxXor( p, &nMuxes, &nXors );
+        nAnds  = Gia_ManAndNum(p) - 3*nMuxes - 3*nXors;
+        nTotal = Gia_ManAndNum(p);
+    }
+    Abc_Print( 1, "stats:  " );
+    Abc_Print( 1, "xor =%8d %6.2f %%   ", nXors,  300.0*nXors/nTotal );
+    Abc_Print( 1, "mux =%8d %6.2f %%   ", nMuxes, 300.0*nMuxes/nTotal );
+    Abc_Print( 1, "and =%8d %6.2f %%   ", nAnds,  100.0*nAnds/nTotal );
+    Abc_Print( 1, "obj =%8d  ", Gia_ManAndNum(p) );
+    fflush( stdout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives GIA with MUXes.]
+
+  Description [Create MUX if the sum of fanin references does not exceed limit.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupMuxes( Gia_Man_t * p, int Limit )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pFan0, * pFan1, * pFanC, * pSiblNew, * pObjNew;
+    int i;
+    assert( p->pMuxes == NULL );
+    assert( Limit >= 2 );
+    ABC_FREE( p->pRefs );
+    Gia_ManCreateRefs( p ); 
+    // start the new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc );
+    if ( Gia_ManHasChoices(p) )
+        pNew->pSibls = ABC_CALLOC( int, pNew->nObjsAlloc );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManHashStart( pNew );
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Gia_ManAppendCi( pNew );
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+        else if ( !Gia_ObjIsMuxType(pObj) || Gia_ObjSibl(p, Gia_ObjFaninId0(pObj, i)) || Gia_ObjSibl(p, Gia_ObjFaninId1(pObj, i)) )
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) )
+            pObj->Value = Gia_ManHashXorReal( pNew, Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)) );
+        else if ( Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) + Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) > Limit )
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else
+        {
+            pFanC = Gia_ObjRecognizeMux( pObj, &pFan1, &pFan0 );
+            pObj->Value = Gia_ManHashMuxReal( pNew, Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFanC)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)) );
+        }
+        if ( !Gia_ObjSibl(p, i) )
+            continue;
+        pObjNew  = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) );
+        pSiblNew = Gia_ManObj( pNew, Abc_Lit2Var(Gia_ObjSiblObj(p, i)->Value) );
+        if ( Gia_ObjIsAnd(pObjNew) && Gia_ObjIsAnd(pSiblNew) && Gia_ObjId(pNew, pObjNew) > Gia_ObjId(pNew, pSiblNew) )
+            pNew->pSibls[Gia_ObjId(pNew, pObjNew)] = Gia_ObjId(pNew, pSiblNew);
+    }
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    // perform cleanup
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives GIA without MUXes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupNoMuxes( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( p->pMuxes != NULL );
+    // start the new manager
+    pNew = Gia_ManStart( 5000 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManHashStart( pNew );
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Gia_ManAppendCi( pNew );
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+        else if ( Gia_ObjIsMuxId(p, i) )
+            pObj->Value = Gia_ManHashMux( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) );
+        else if ( Gia_ObjIsXor(pObj) )
+            pObj->Value = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else 
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    }
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    // perform cleanup
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Test these procedures.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupMuxesTest( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew, * pNew2;
+    pNew = Gia_ManDupMuxes( p, 2 );
+    pNew2 = Gia_ManDupNoMuxes( pNew );
+    Gia_ManPrintStats( p, NULL );
+    Gia_ManPrintStats( pNew, NULL );
+    Gia_ManPrintStats( pNew2, NULL );
+    Gia_ManStop( pNew );
+//    Gia_ManStop( pNew2 );
+    return pNew2;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the size of MUX structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_MuxRef_rec( Gia_Man_t * p, int iObj )
+{
+    Gia_Obj_t * pObj;
+    if ( !Gia_ObjIsMuxId(p, iObj) )
+        return 0;
+    pObj = Gia_ManObj( p, iObj );
+    if ( Gia_ObjRefInc(p, pObj) )
+        return 0;
+    return Gia_MuxRef_rec( p, Gia_ObjFaninId0p(p, pObj) ) + 
+           Gia_MuxRef_rec( p, Gia_ObjFaninId1p(p, pObj) ) + 
+           Gia_MuxRef_rec( p, Gia_ObjFaninId2p(p, pObj) ) + 1;
+}
+int Gia_MuxRef( Gia_Man_t * p, int iObj )
+{
+    Gia_Obj_t * pObj = Gia_ManObj( p, iObj );
+    assert( Gia_ObjIsMuxId(p, iObj) );
+    return Gia_MuxRef_rec( p, Gia_ObjFaninId0p(p, pObj) ) + 
+           Gia_MuxRef_rec( p, Gia_ObjFaninId1p(p, pObj) ) + 
+           Gia_MuxRef_rec( p, Gia_ObjFaninId2p(p, pObj) ) + 1;
+}
+int Gia_MuxDeref_rec( Gia_Man_t * p, int iObj )
+{
+    Gia_Obj_t * pObj;
+    if ( !Gia_ObjIsMuxId(p, iObj) )
+        return 0;
+    pObj = Gia_ManObj( p, iObj );
+    if ( Gia_ObjRefDec(p, pObj) )
+        return 0;
+    return Gia_MuxDeref_rec( p, Gia_ObjFaninId0p(p, pObj) ) + 
+           Gia_MuxDeref_rec( p, Gia_ObjFaninId1p(p, pObj) ) + 
+           Gia_MuxDeref_rec( p, Gia_ObjFaninId2p(p, pObj) ) + 1;
+}
+int Gia_MuxDeref( Gia_Man_t * p, int iObj )
+{
+    Gia_Obj_t * pObj = Gia_ManObj( p, iObj );
+    assert( Gia_ObjIsMuxId(p, iObj) );
+    return Gia_MuxDeref_rec( p, Gia_ObjFaninId0p(p, pObj) ) + 
+           Gia_MuxDeref_rec( p, Gia_ObjFaninId1p(p, pObj) ) + 
+           Gia_MuxDeref_rec( p, Gia_ObjFaninId2p(p, pObj) ) + 1;
+}
+int Gia_MuxMffcSize( Gia_Man_t * p, int iObj )
+{
+    int Count1, Count2;
+    if ( !Gia_ObjIsMuxId(p, iObj) )
+        return 0;
+    Count1 = Gia_MuxDeref( p, iObj );
+    Count2 = Gia_MuxRef( p, iObj );
+    assert( Count1 == Count2 );
+    return Count1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_MuxStructPrint_rec( Gia_Man_t * p, int iObj, int fFirst )
+{
+    Gia_Obj_t * pObj = Gia_ManObj( p, iObj );
+    int iCtrl;
+    if ( !fFirst && (!Gia_ObjIsMuxId(p, iObj) || Gia_ObjRefNumId(p, iObj) > 0) )
+    {
+//        printf( "%d", iObj );
+        printf( "<%02d>", Gia_ObjLevelId(p, iObj) );
+        return;
+    }
+    iCtrl = Gia_ObjFaninId2p(p, pObj);
+    printf( " [(" );
+    if ( Gia_ObjIsMuxId(p, iCtrl) && Gia_ObjRefNumId(p, iCtrl) == 0 )
+        Gia_MuxStructPrint_rec( p, iCtrl, 0 );
+    else
+    {
+        printf( "%d", iCtrl );
+        printf( "<%d>", Gia_ObjLevelId(p, iCtrl) );
+    }
+    printf( ")" );
+    if ( Gia_ObjFaninC2(p, pObj) )
+    {
+        Gia_MuxStructPrint_rec( p, Gia_ObjFaninId0p(p, pObj), 0 );
+        printf( "|" );
+        Gia_MuxStructPrint_rec( p, Gia_ObjFaninId1p(p, pObj), 0 );
+        printf( "]" );
+    }
+    else
+    {
+        Gia_MuxStructPrint_rec( p, Gia_ObjFaninId1p(p, pObj), 0 );
+        printf( "|" );
+        Gia_MuxStructPrint_rec( p, Gia_ObjFaninId0p(p, pObj), 0 );
+        printf( "]" );
+    }
+}
+void Gia_MuxStructPrint( Gia_Man_t * p, int iObj )
+{
+    int Count1, Count2;
+    assert( Gia_ObjIsMuxId(p, iObj) );
+    Count1 = Gia_MuxDeref( p, iObj );
+    Gia_MuxStructPrint_rec( p, iObj, 1 );
+    Count2 = Gia_MuxRef( p, iObj );
+    assert( Count1 == Count2 );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_MuxStructDump_rec( Gia_Man_t * p, int iObj, int fFirst, Vec_Str_t * vStr, int nDigitsId )
+{
+    Gia_Obj_t * pObj = Gia_ManObj( p, iObj );
+    int iCtrl;
+    if ( !fFirst && (!Gia_ObjIsMuxId(p, iObj) || Gia_ObjRefNumId(p, iObj) > 0) )
+        return;
+    iCtrl = Gia_ObjFaninId2p(p, pObj);
+    Vec_StrPush( vStr, '[' );
+    Vec_StrPush( vStr, '(' );
+    if ( Gia_ObjIsMuxId(p, iCtrl) && Gia_ObjRefNumId(p, iCtrl) == 0 )
+        Gia_MuxStructDump_rec( p, iCtrl, 0, vStr, nDigitsId );
+    else
+        Vec_StrPrintNumStar( vStr, iCtrl, nDigitsId );
+    Vec_StrPush( vStr, ')' );
+    if ( Gia_ObjFaninC2(p, pObj) )
+    {
+        Gia_MuxStructDump_rec( p, Gia_ObjFaninId0p(p, pObj), 0, vStr, nDigitsId );
+        Vec_StrPush( vStr, '|' );
+        Gia_MuxStructDump_rec( p, Gia_ObjFaninId1p(p, pObj), 0, vStr, nDigitsId );
+        Vec_StrPush( vStr, ']' );
+    }
+    else
+    {
+        Gia_MuxStructDump_rec( p, Gia_ObjFaninId1p(p, pObj), 0, vStr, nDigitsId );
+        Vec_StrPush( vStr, '|' );
+        Gia_MuxStructDump_rec( p, Gia_ObjFaninId0p(p, pObj), 0, vStr, nDigitsId );
+        Vec_StrPush( vStr, ']' );
+    }
+}
+int Gia_MuxStructDump( Gia_Man_t * p, int iObj, Vec_Str_t * vStr, int nDigitsNum, int nDigitsId )
+{
+    int Count1, Count2;
+    assert( Gia_ObjIsMuxId(p, iObj) );
+    Count1 = Gia_MuxDeref( p, iObj );
+    Vec_StrClear( vStr );
+    Vec_StrPrintNumStar( vStr, Count1, nDigitsNum );
+    Gia_MuxStructDump_rec( p, iObj, 1, vStr, nDigitsId );
+    Vec_StrPush( vStr, '\0' );
+    Count2 = Gia_MuxRef( p, iObj );
+    assert( Count1 == Count2 );
+    return Count1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManMuxCompare( char ** pp1, char ** pp2 )
+{
+    int Diff = strcmp( *pp1, *pp2 );
+    if ( Diff < 0 )
+        return 1;
+    if ( Diff > 0) 
+        return -1;
+    return 0; 
+}
+int Gia_ManMuxCountOne( char * p )
+{
+    int Count = 0;
+    for ( ; *p; p++ )
+        Count += (*p == '[');
+    return Count;
+}
+
+typedef struct Mux_Man_t_ Mux_Man_t; 
+struct Mux_Man_t_
+{
+    Gia_Man_t *     pGia;      // manager
+    Abc_Nam_t *     pNames;    // hashing name into ID
+    Vec_Wec_t *     vTops;     // top nodes for each struct
+};
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mux_Man_t * Mux_ManAlloc( Gia_Man_t * pGia )
+{
+    Mux_Man_t * p;
+    p = ABC_CALLOC( Mux_Man_t, 1 );
+    p->pGia   = pGia;
+    p->pNames = Abc_NamStart( 10000, 50 );
+    p->vTops  = Vec_WecAlloc( 1000 );
+    Vec_WecPushLevel( p->vTops );
+    return p;
+}
+void Mux_ManFree( Mux_Man_t * p )
+{
+    Abc_NamStop( p->pNames );
+    Vec_WecFree( p->vTops );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManMuxProfile( Mux_Man_t * p, int fWidth )
+{
+    int i, Entry, Counter, Total;
+    Vec_Int_t * vVec, * vCounts;
+    vCounts = Vec_IntStart( 1000 );
+    if ( fWidth )
+    {
+        Vec_WecForEachLevelStart( p->vTops, vVec, i, 1 )
+            Vec_IntAddToEntry( vCounts, Abc_MinInt(Vec_IntSize(vVec), 999), 1 );
+    }
+    else
+    {
+        for ( i = 1; i < Vec_WecSize(p->vTops); i++ )
+            Vec_IntAddToEntry( vCounts, Abc_MinInt(atoi(Abc_NamStr(p->pNames, i)), 999), 1 );
+    }
+    Total = Vec_IntCountPositive(vCounts);
+    if ( Total == 0 )
+        return 0;
+    printf( "The distribution of MUX tree %s:\n", fWidth ? "widths" : "sizes"  );
+    Counter = 0;
+    Vec_IntForEachEntry( vCounts, Entry, i )
+    {
+        if ( !Entry ) continue;
+        if ( ++Counter == 12 )
+            printf( "\n" ), Counter = 0;
+        printf( "  %d=%d", i, Entry );
+    }
+    printf( "\nSummary: " );
+    printf( "Max = %d  ", Vec_IntFindMax(vCounts) );
+    printf( "Ave = %.2f", 1.0*Vec_IntSum(vCounts)/Total );
+    printf( "\n" );
+    Vec_IntFree( vCounts );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManMuxProfiling( Gia_Man_t * p )
+{
+    Mux_Man_t * pMan;
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    Vec_Str_t * vStr;
+    Vec_Int_t * vFans, * vVec;
+    int i, Counter, fFound, iStructId, nDigitsId;
+    abctime clk = Abc_Clock();
+
+    pNew = Gia_ManDupMuxes( p, 2 );
+    nDigitsId = Abc_Base10Log( Gia_ManObjNum(pNew) );
+
+    pMan = Mux_ManAlloc( pNew );
+     
+    Gia_ManLevelNum( pNew );
+    Gia_ManCreateRefs( pNew );
+    Gia_ManForEachCo( pNew, pObj, i )
+        Gia_ObjRefFanin0Inc( pNew, pObj );
+
+    vStr = Vec_StrAlloc( 1000 );
+    vFans = Gia_ManFirstFanouts( pNew );
+    Gia_ManForEachMux( pNew, pObj, i )
+    {
+        // skip MUXes in the middle of the tree (which have only one MUX fanout)
+        if ( Gia_ObjRefNumId(pNew, i) == 1 && Gia_ObjIsMuxId(pNew, Vec_IntEntry(vFans, i)) )
+            continue;
+        // this node is the root of the MUX structure - create hash key
+        Counter = Gia_MuxStructDump( pNew, i, vStr, 3, nDigitsId );
+        if ( Counter == 1 )
+            continue;
+        iStructId = Abc_NamStrFindOrAdd( pMan->pNames, Vec_StrArray(vStr), &fFound );
+        if ( !fFound )
+            Vec_WecPushLevel( pMan->vTops );
+        assert( Abc_NamObjNumMax(pMan->pNames) == Vec_WecSize(pMan->vTops) );
+        Vec_IntPush( Vec_WecEntry(pMan->vTops, iStructId), i );
+    }
+    Vec_StrFree( vStr );
+    Vec_IntFree( vFans );
+
+    printf( "MUX structure profile for AIG \"%s\":\n", p->pName );
+    printf( "Total MUXes = %d.  Total trees = %d.  Unique trees = %d.  Memory = %.2f MB   ", 
+        Gia_ManMuxNum(pNew), Vec_WecSizeSize(pMan->vTops), Vec_WecSize(pMan->vTops)-1, 
+        1.0*Abc_NamMemUsed(pMan->pNames)/(1<<20) );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+
+    if ( Gia_ManMuxProfile(pMan, 0) )
+    {
+        Gia_ManMuxProfile( pMan, 1 );
+
+        // short the first ones
+        printf( "The first %d structures: \n", 10 );
+        Vec_WecForEachLevelStartStop( pMan->vTops, vVec, i, 1, Abc_MinInt(Vec_WecSize(pMan->vTops), 10) )
+        {
+            char * pTemp = Abc_NamStr(pMan->pNames, i);
+            printf( "%5d : ", i );
+            printf( "Occur = %4d   ", Vec_IntSize(vVec) );
+            printf( "Size = %4d   ", atoi(pTemp) );
+            printf( "%s\n", pTemp );
+        }
+
+        // print trees for the first one
+        Counter = 0;
+        Vec_WecForEachLevelStart( pMan->vTops, vVec, i, 1 )
+        {
+            char * pTemp = Abc_NamStr(pMan->pNames, i);
+            if ( Vec_IntSize(vVec) > 5 && atoi(pTemp) > 5 )
+            {
+                int k, Entry;
+                printf( "For example, structure %d has %d MUXes and bit-width %d:\n", i, atoi(pTemp), Vec_IntSize(vVec) );
+                Vec_IntForEachEntry( vVec, Entry, k )
+                    Gia_MuxStructPrint( pNew, Entry );
+                if ( ++Counter == 5 )
+                    break;
+            }
+        }
+    }
+
+    Mux_ManFree( pMan );
+    Gia_ManStop( pNew );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaNf.c b/abc-build/src/aig/gia/giaNf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaNf.c
@@ -0,0 +1,58 @@
+/**CFile****************************************************************
+
+  FileName    [giaNf.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Technology mapper.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaNf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nf_ManSetDefaultPars( Jf_Par_t * pPars )
+{
+}
+Gia_Man_t * Nf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars )
+{
+    return Gia_ManDup( pGia );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaPat.c b/abc-build/src/aig/gia/giaPat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaPat.c
@@ -0,0 +1,135 @@
+/**CFile****************************************************************
+
+  FileName    [gia.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int   Sat_ObjXValue( Gia_Obj_t * pObj )          { return (pObj->fMark1 << 1) | pObj->fMark0;             }
+static inline void  Sat_ObjSetXValue( Gia_Obj_t * pObj, int v) { pObj->fMark0 = (v & 1); pObj->fMark1 = ((v >> 1) & 1); }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes in the cone and initialized them to x.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_SatCollectCone_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vVisit )
+{
+    if ( Sat_ObjXValue(pObj) == GIA_UND )
+        return;
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        Gia_SatCollectCone_rec( p, Gia_ObjFanin0(pObj), vVisit );
+        Gia_SatCollectCone_rec( p, Gia_ObjFanin1(pObj), vVisit );
+    }
+    assert( Sat_ObjXValue(pObj) == 0 );
+    Sat_ObjSetXValue( pObj, GIA_UND );
+    Vec_IntPush( vVisit, Gia_ObjId(p, pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes in the cone and initialized them to x.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_SatCollectCone( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vVisit )
+{
+    assert( !Gia_IsComplement(pObj) );
+    assert( !Gia_ObjIsConst0(pObj) );
+    assert( Sat_ObjXValue(pObj) == 0 );
+    Vec_IntClear( vVisit );
+    Gia_SatCollectCone_rec( p, pObj, vVisit );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the counter-examples asserts the output.]
+
+  Description [Assumes that fMark0 and fMark1 are clean. Leaves them clean.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_SatVerifyPattern( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vCex, Vec_Int_t * vVisit )
+{
+    Gia_Obj_t * pObj;
+    int i, Entry, Value, Value0, Value1;
+    assert( Gia_ObjIsCo(pRoot) );
+    assert( !Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) );
+    // collect nodes and initialized them to x
+    Gia_SatCollectCone( p, Gia_ObjFanin0(pRoot), vVisit );
+    // set binary values to nodes in the counter-example
+    Vec_IntForEachEntry( vCex, Entry, i )
+//        Sat_ObjSetXValue( Gia_ManObj(p, Abc_Lit2Var(Entry)), Abc_LitIsCompl(Entry)? GIA_ZER : GIA_ONE );
+        Sat_ObjSetXValue( Gia_ManCi(p, Abc_Lit2Var(Entry)), Abc_LitIsCompl(Entry)? GIA_ZER : GIA_ONE );
+    // simulate
+    Gia_ManForEachObjVec( vVisit, p, pObj, i )
+    {
+        if ( Gia_ObjIsCi(pObj) )
+            continue;
+        assert( Gia_ObjIsAnd(pObj) );
+        Value0 = Sat_ObjXValue( Gia_ObjFanin0(pObj) );
+        Value1 = Sat_ObjXValue( Gia_ObjFanin1(pObj) );
+        Value = Gia_XsimAndCond( Value0, Gia_ObjFaninC0(pObj), Value1, Gia_ObjFaninC1(pObj) );
+        Sat_ObjSetXValue( pObj, Value );
+    }
+    Value = Sat_ObjXValue( Gia_ObjFanin0(pRoot) );
+    Value = Gia_XsimNotCond( Value, Gia_ObjFaninC0(pRoot) );
+    if ( Value != GIA_ONE )
+        printf( "Gia_SatVerifyPattern(): Verification FAILED.\n" );
+//    else
+//        printf( "Gia_SatVerifyPattern(): Verification succeeded.\n" );
+//    assert( Value == GIA_ONE );
+    // clean the nodes
+    Gia_ManForEachObjVec( vVisit, p, pObj, i )
+        Sat_ObjSetXValue( pObj, 0 );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaProp.c b/abc-build/src/aig/gia/giaProp.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaProp.c
@@ -0,0 +1,176 @@
+/**CFile****************************************************************
+
+  FileName    [giaProp.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Constraint propagation on the AIG.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaProp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define GIA_SAT_SHIFT 12
+#define GIA_ROOT_MASK 
+#define GIA_PATH00_MASK
+#define GIA_PATH10_MASK
+#define GIA_PATH20_MASK
+#define GIA_PATH30_MASK
+#define GIA_PATH00_MASK
+#define GIA_PATH10_MASK
+#define GIA_PATH20_MASK
+#define GIA_PATH30_MASK
+
+static inline int Gia_SatObjIsRoot( Gia_Obj_t * p )      { return 0; }
+static inline int Gia_SatObjXorRoot( Gia_Obj_t * p )     { return 0; }
+
+
+static inline int Gia_SatObjIsAssigned( Gia_Obj_t * p )  { return 0; }
+static inline int Gia_SatObjIsHeld( Gia_Obj_t * p )      { return 0; }
+static inline int Gia_SatObjValue( Gia_Obj_t * p )       { return 0; }
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the give cut is satisfied.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_SatPathCheckCutSat_rec( Gia_Obj_t * p, int fCompl )
+{
+    if ( Gia_SatObjIsRoot(p) )
+        return Gia_ObjIsAssigned(p) && Gia_SatObjValue(p) == fCompl;
+    if ( Gia_SatObjPath0(p) && !Gia_SatPathCheckCutSat_rec( Gia_ObjFanin0(p), fCompl ^ Gia_ObjFaninC0(p) ) )
+        return 0;
+    if ( Gia_SatObjPath1(p) && !Gia_SatPathCheckCutSat_rec( Gia_ObjFanin1(p), fCompl ^ Gia_ObjFaninC1(p) ) )
+        return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the give cut is satisfied.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_SatPathCheckCutSat( Gia_Obj_t * p )
+{
+    int RetValue;
+    assert( Gia_SatObjIsRoot(p) );
+    Gia_SatObjXorRoot(p);
+    RetValue = Gia_SatPathCheckCutSat_rec( p );
+    Gia_SatObjXorRoot(p);
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Unbinds literals on the path.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_SatPathUnbind_rec( Gia_Obj_t * p )
+{
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a feasible path from the node to a terminal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_SatPathStart_rec( Gia_Obj_t * p, int fDiffs, int fCompl )
+{
+    if ( Gia_SatObjIsRoot(p) )
+        return fDiffs && (!Gia_ObjIsAssigned(p) || Gia_SatObjValue(p) != fCompl);
+    if ( fCompl == 0 )
+    {
+        if ( Gia_SatPathStart_rec( Gia_ObjFanin0(p), fDiffs + !Gia_SatObjPath0(p), fCompl ^ Gia_ObjFaninC0(p) ) &&
+             Gia_SatPathStart_rec( Gia_ObjFanin1(p), fDiffs + !Gia_SatObjPath1(p), fCompl ^ Gia_ObjFaninC1(p) ) )
+            return Gia_ObjSetDraftPath0(p) + Gia_ObjSetDraftPath1(p);
+    }
+    else
+    {
+        if ( Gia_SatPathStart_rec( Gia_ObjFanin0(p), fDiffs + !Gia_SatObjPath0(p), fCompl ^ Gia_ObjFaninC0(p) ) )
+        {
+            Gia_ObjUnsetDraftPath1(p);
+            return Gia_ObjSetDraftPath0(p);
+        }
+        if ( Gia_SatPathStart_rec( Gia_ObjFanin1(p), fDiffs + !Gia_SatObjPath1(p), fCompl ^ Gia_ObjFaninC1(p) ) )
+        {
+            Gia_ObjUnsetDraftPath0(p);
+            return Gia_ObjSetDraftPath1(p);
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a feasible path from the node to a terminal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_SatPathStart( Gia_Obj_t * p )
+{
+    int RetValue;
+    assert( Gia_SatObjIsRoot(p) );
+    Gia_SatObjXorRoot(p);
+    RetValue = Gia_SatPathStart_rec( p, 0, 0 );
+    Gia_SatObjXorRoot(p);
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaResub.c b/abc-build/src/aig/gia/giaResub.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaResub.c
@@ -0,0 +1,292 @@
+/**CFile****************************************************************
+
+  FileName    [giaResub.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Resubstitution.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/vec/vecWec.h"
+#include "misc/vec/vecQue.h"
+#include "misc/vec/vecHsh.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes MFFCs of all qualifying nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ObjCheckMffc_rec( Gia_Man_t * p,Gia_Obj_t * pObj, int Limit, Vec_Int_t * vNodes )
+{
+    int iFanin;
+    if ( Gia_ObjIsCi(pObj) )
+        return 1;
+    assert( Gia_ObjIsAnd(pObj) );
+    iFanin = Gia_ObjFaninId0p(p, pObj);
+    Vec_IntPush( vNodes, iFanin );
+    if ( !Gia_ObjRefDecId(p, iFanin) && (Vec_IntSize(vNodes) > Limit || !Gia_ObjCheckMffc_rec(p, Gia_ObjFanin0(pObj), Limit, vNodes)) )
+        return 0;
+    iFanin = Gia_ObjFaninId1p(p, pObj);
+    Vec_IntPush( vNodes, iFanin );
+    if ( !Gia_ObjRefDecId(p, iFanin) && (Vec_IntSize(vNodes) > Limit || !Gia_ObjCheckMffc_rec(p, Gia_ObjFanin1(pObj), Limit, vNodes)) )
+        return 0;
+    if ( !Gia_ObjIsMux(p, pObj) )
+        return 1;
+    iFanin = Gia_ObjFaninId2p(p, pObj);
+    Vec_IntPush( vNodes, iFanin );
+    if ( !Gia_ObjRefDecId(p, iFanin) && (Vec_IntSize(vNodes) > Limit || !Gia_ObjCheckMffc_rec(p, Gia_ObjFanin2(p, pObj), Limit, vNodes)) )
+        return 0;
+    return 1;
+}
+static inline int Gia_ObjCheckMffc( Gia_Man_t * p, Gia_Obj_t * pRoot, int Limit, Vec_Int_t * vNodes, Vec_Int_t * vLeaves, Vec_Int_t * vInners )
+{
+    int RetValue, iObj, i;
+    Vec_IntClear( vNodes );
+    RetValue = Gia_ObjCheckMffc_rec( p, pRoot, Limit, vNodes );
+    if ( RetValue )
+    {
+        Vec_IntClear( vLeaves );
+        Vec_IntClear( vInners );
+        Vec_IntSort( vNodes, 0 );
+        Vec_IntForEachEntry( vNodes, iObj, i )
+            if ( Gia_ObjRefNumId(p, iObj) > 0 || Gia_ObjIsCi(Gia_ManObj(p, iObj)) )
+            {
+                if ( !Vec_IntSize(vLeaves) || Vec_IntEntryLast(vLeaves) != iObj )
+                    Vec_IntPush( vLeaves, iObj );
+            }
+            else
+            {
+                if ( !Vec_IntSize(vInners) || Vec_IntEntryLast(vInners) != iObj )
+                    Vec_IntPush( vInners, iObj );
+            }
+        Vec_IntPush( vInners, Gia_ObjId(p, pRoot) );
+    }
+    Vec_IntForEachEntry( vNodes, iObj, i )
+        Gia_ObjRefIncId( p, iObj );
+    return RetValue;
+}
+Vec_Wec_t * Gia_ManComputeMffcs( Gia_Man_t * p, int LimitMin, int LimitMax, int SuppMax, int RatioBest )
+{
+    Gia_Obj_t * pObj;
+    Vec_Wec_t * vMffcs;
+    Vec_Int_t * vNodes, * vLeaves, * vInners, * vMffc;
+    int i, iPivot;
+    assert( p->pMuxes );
+    vNodes  = Vec_IntAlloc( 2 * LimitMax );
+    vLeaves = Vec_IntAlloc( 2 * LimitMax );
+    vInners = Vec_IntAlloc( 2 * LimitMax );
+    vMffcs  = Vec_WecAlloc( 1000 );
+    Gia_ManCreateRefs( p );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        if ( !Gia_ObjRefNum(p, pObj) )
+            continue;
+        if ( !Gia_ObjCheckMffc(p, pObj, LimitMax, vNodes, vLeaves, vInners) )
+            continue;
+        if ( Vec_IntSize(vInners) < LimitMin )
+            continue;
+        if ( Vec_IntSize(vLeaves) > SuppMax )
+            continue;
+        // improve cut
+        // collect cut
+        vMffc = Vec_WecPushLevel( vMffcs );
+        Vec_IntGrow( vMffc, Vec_IntSize(vLeaves) + Vec_IntSize(vInners) + 20 );
+        Vec_IntPush( vMffc, i );
+        Vec_IntPush( vMffc, Vec_IntSize(vLeaves) );
+        Vec_IntPush( vMffc, Vec_IntSize(vInners) );
+        Vec_IntAppend( vMffc, vLeaves );
+//        Vec_IntAppend( vMffc, vInners );
+        // add last entry equal to the ratio
+        Vec_IntPush( vMffc, 1000 * Vec_IntSize(vInners) / Vec_IntSize(vLeaves) );
+    }
+    Vec_IntFree( vNodes );
+    Vec_IntFree( vLeaves );
+    Vec_IntFree( vInners );
+    // sort MFFCs by their inner/leaf ratio
+    Vec_WecSortByLastInt( vMffcs, 1 );
+    Vec_WecForEachLevel( vMffcs, vMffc, i )
+        Vec_IntPop( vMffc );
+    // remove those whose ratio is not good
+    iPivot = RatioBest * Vec_WecSize(vMffcs) / 100;
+    Vec_WecForEachLevelStart( vMffcs, vMffc, i, iPivot )
+        Vec_IntErase( vMffc );
+    assert( iPivot <= Vec_WecSize(vMffcs) );
+    Vec_WecShrink( vMffcs, iPivot );
+    return vMffcs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintDivStats( Gia_Man_t * p, Vec_Wec_t * vMffcs, Vec_Wec_t * vPivots ) 
+{
+    int fVerbose = 0;
+    Vec_Int_t * vMffc;
+    int i, nDivs, nDivsAll = 0, nDivs0 = 0;
+    Vec_WecForEachLevel( vMffcs, vMffc, i )
+    {
+        nDivs = Vec_IntSize(vMffc) - 3 - Vec_IntEntry(vMffc, 1) - Vec_IntEntry(vMffc, 2);
+        nDivs0 += (nDivs == 0);
+        nDivsAll += nDivs;
+        if ( !fVerbose )
+            continue;
+        printf( "%6d : ",      Vec_IntEntry(vMffc, 0) );
+        printf( "Leaf =%3d  ", Vec_IntEntry(vMffc, 1) );
+        printf( "Mffc =%4d  ", Vec_IntEntry(vMffc, 2) );
+        printf( "Divs =%4d  ", nDivs );
+        printf( "\n" );
+    }
+    printf( "Collected %d (%.1f %%) MFFCs and %d (%.1f %%) have no divisors (div ave for others is %.2f).\n", 
+        Vec_WecSize(vMffcs), 100.0 * Vec_WecSize(vMffcs) / Gia_ManAndNum(p), 
+        nDivs0, 100.0 * nDivs0 / Gia_ManAndNum(p), 
+        1.0*nDivsAll/Abc_MaxInt(1, Vec_WecSize(vMffcs) - nDivs0) );
+    printf( "Using %.2f MB for MFFCs and %.2f MB for pivots.   ", 
+        Vec_WecMemory(vMffcs)/(1<<20), Vec_WecMemory(vPivots)/(1<<20) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute divisors and Boolean functions for the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManAddDivisors( Gia_Man_t * p, Vec_Wec_t * vMffcs )
+{
+    Vec_Wec_t * vPivots;
+    Vec_Int_t * vMffc, * vPivot, * vPivot0, * vPivot1;
+    Vec_Int_t * vCommon, * vCommon2, * vMap;
+    Gia_Obj_t * pObj;
+    int i, k, iObj, iPivot, iMffc;
+//abctime clkStart = Abc_Clock();
+    // initialize pivots (mapping of nodes into MFFCs whose leaves they are)
+    vMap = Vec_IntStartFull( Gia_ManObjNum(p) );
+    vPivots = Vec_WecStart( Gia_ManObjNum(p) );
+    Vec_WecForEachLevel( vMffcs, vMffc, i )
+    {
+        assert( Vec_IntSize(vMffc) == 3 + Vec_IntEntry(vMffc, 1) );
+        iPivot = Vec_IntEntry( vMffc, 0 );
+        Vec_IntWriteEntry( vMap, iPivot, i );
+        // iterate through the MFFC leaves
+        Vec_IntForEachEntryStart( vMffc, iObj, k, 3 )
+        {
+            vPivot = Vec_WecEntry( vPivots, iObj );
+            if ( Vec_IntSize(vPivot) == 0 )
+                Vec_IntGrow(vPivot, 4);
+            Vec_IntPush( vPivot, iPivot );            
+        }
+    }
+    Vec_WecForEachLevel( vPivots, vPivot, i )
+        Vec_IntSort( vPivot, 0 );
+    // create pivots for internal nodes while growing MFFCs
+    vCommon = Vec_IntAlloc( 100 );
+    vCommon2 = Vec_IntAlloc( 100 );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        // find commont pivots
+        // the slow down happens because some PIs have very large sets of pivots
+        vPivot0 = Vec_WecEntry( vPivots, Gia_ObjFaninId0(pObj, i) );
+        vPivot1 = Vec_WecEntry( vPivots, Gia_ObjFaninId1(pObj, i) );
+        Vec_IntTwoFindCommon( vPivot0, vPivot1, vCommon );
+        if ( Gia_ObjIsMuxId(p, i) )
+        {
+            vPivot = Vec_WecEntry( vPivots, Gia_ObjFaninId2(p, i) );
+            Vec_IntTwoFindCommon( vPivot, vCommon, vCommon2 );
+            ABC_SWAP( Vec_Int_t *, vCommon, vCommon2 );
+        }
+        if ( Vec_IntSize(vCommon) == 0 )
+            continue;
+        // add new pivots (this trick increased memory used in vPivots)
+        vPivot = Vec_WecEntry( vPivots, i );
+        Vec_IntTwoMerge2( vPivot, vCommon, vCommon2 );
+        ABC_SWAP( Vec_Int_t, *vPivot, *vCommon2 );
+        // grow MFFCs
+        Vec_IntForEachEntry( vCommon, iObj, k )
+        {
+            iMffc = Vec_IntEntry( vMap, iObj );
+            assert( iMffc != -1 );
+            vMffc = Vec_WecEntry( vMffcs, iMffc );
+            Vec_IntPush( vMffc, i );
+        }
+    }
+//Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart );
+    Vec_IntFree( vCommon );
+    Vec_IntFree( vCommon2 );
+    Vec_IntFree( vMap );
+    Gia_ManPrintDivStats( p, vMffcs, vPivots );
+    Vec_WecFree( vPivots );
+    // returns the modified array of MFFCs
+}
+void Gia_ManResubTest( Gia_Man_t * p )
+{
+    Vec_Wec_t * vMffcs;
+    Gia_Man_t * pNew = Gia_ManDupMuxes( p, 2 );
+abctime clkStart = Abc_Clock();
+    vMffcs = Gia_ManComputeMffcs( pNew, 4, 100, 8, 100 );
+    Gia_ManAddDivisors( pNew, vMffcs );
+    Vec_WecFree( vMffcs );
+Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart );
+    Gia_ManStop( pNew );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Perform resubstitution.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaRetime.c b/abc-build/src/aig/gia/giaRetime.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaRetime.c
@@ -0,0 +1,304 @@
+/**CFile****************************************************************
+
+  FileName    [giaRetime.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Performs most-forward retiming for AIG with flop classes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaRetime.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Marks objects reachables from Const0 and PIs/
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManMarkAutonomous_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return pObj->fMark0;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    assert( pObj->fMark0 == 0 );
+    if ( Gia_ObjIsPi(p, pObj) || Gia_ObjIsConst0(pObj) )
+        return pObj->fMark0 = 1;
+    if ( Gia_ObjIsCo(pObj) )
+        return pObj->fMark0 = Gia_ManMarkAutonomous_rec( p, Gia_ObjFanin0(pObj) );
+    if ( Gia_ObjIsCi(pObj) )
+        return pObj->fMark0 = Gia_ManMarkAutonomous_rec( p, Gia_ObjRoToRi(p, pObj) );
+    assert( Gia_ObjIsAnd(pObj) );
+    if ( Gia_ManMarkAutonomous_rec( p, Gia_ObjFanin0(pObj) ) )
+        return pObj->fMark0 = 1;
+    return pObj->fMark0 = Gia_ManMarkAutonomous_rec( p, Gia_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks with current trav ROs reachable from Const0 and PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManMarkAutonomous( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManCleanMark0( p );
+    Gia_ManIncrementTravId( p );
+    Gia_ManForEachRo( p, pObj, i )
+        Gia_ManMarkAutonomous_rec( p, pObj );
+    Gia_ManIncrementTravId( p );
+    Gia_ManForEachRo( p, pObj, i )
+        if ( pObj->fMark0 )
+            Gia_ObjSetTravIdCurrent( p, pObj );
+    Gia_ManCleanMark0( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG recursively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManRetimeDup_rec( Gia_Man_t * pNew, Gia_Obj_t * pObj )
+{
+    if ( ~pObj->Value )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManRetimeDup_rec( pNew, Gia_ObjFanin0(pObj) );
+    Gia_ManRetimeDup_rec( pNew, Gia_ObjFanin1(pObj) );
+    pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG while retiming the registers to the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManRetimeDupForward( Gia_Man_t * p, Vec_Ptr_t * vCut )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pObjRi, * pObjRo;
+    int i;
+    // create the new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+    // create the true PIs
+    Gia_ManFillValue( p );
+    Gia_ManSetPhase( p );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    // create the registers
+    Vec_PtrForEachEntry( Gia_Obj_t *, vCut, pObj, i )
+        pObj->Value = Abc_LitNotCond( Gia_ManAppendCi(pNew), pObj->fPhase );
+    // duplicate logic above the cut
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManRetimeDup_rec( pNew, Gia_ObjFanin0(pObj) );
+    // create the true POs
+    Gia_ManForEachPo( p, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    // remember value in LI
+    Gia_ManForEachRi( p, pObj, i )
+        pObj->Value = Gia_ObjFanin0Copy(pObj);
+    // transfer values from the LIs to the LOs
+    Gia_ManForEachRiRo( p, pObjRi, pObjRo, i )
+        pObjRo->Value = pObjRi->Value;
+    // erase the data values on the internal nodes of the cut
+    Vec_PtrForEachEntry( Gia_Obj_t *, vCut, pObj, i )
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = ~0;
+    // duplicate logic below the cut
+    Vec_PtrForEachEntry( Gia_Obj_t *, vCut, pObj, i )
+    {
+        Gia_ManRetimeDup_rec( pNew, pObj );
+        Gia_ManAppendCo( pNew, Abc_LitNotCond( pObj->Value, pObj->fPhase ) );
+    }
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Vec_PtrSize(vCut) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the cut for forward retiming.]
+
+  Description [Assumes topological ordering of the nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManRetimeForwardOne( Gia_Man_t * p, int * pnRegFixed, int * pnRegMoves )
+{
+    Vec_Int_t * vFlopClasses = NULL;
+    Vec_Int_t * vObjClasses = NULL;
+    Gia_Man_t * pNew;
+    Vec_Ptr_t * vCut;
+    Gia_Obj_t * pObj;
+    int i;
+    if ( p->vFlopClasses )
+    {
+//        printf( "Performing retiming with register classes.\n" );
+        vObjClasses = Vec_IntAlloc( Gia_ManObjNum(p) );
+        for ( i = 0; i < Gia_ManObjNum(p); i++ )
+            Vec_IntPush( vObjClasses, -1 );
+        Gia_ManForEachRo( p, pObj, i )
+            Vec_IntWriteEntry( vObjClasses, Gia_ObjId(p, pObj), Vec_IntEntry(p->vFlopClasses, i) );
+        vFlopClasses = Vec_IntAlloc( Gia_ManRegNum(p) );
+    }
+    // mark the retimable nodes
+    Gia_ManIncrementTravId( p );
+    Gia_ManMarkAutonomous( p );
+    // mark the retimable registers with the fresh trav ID
+    Gia_ManIncrementTravId( p );
+    *pnRegFixed = 0;
+    Gia_ManForEachRo( p, pObj, i )
+        if ( Gia_ObjIsTravIdPrevious(p, pObj) )
+            Gia_ObjSetTravIdCurrent(p, pObj);
+        else
+            (*pnRegFixed)++;
+    // mark all the nodes that can be retimed forward
+    *pnRegMoves = 0;
+    Gia_ManForEachAnd( p, pObj, i )
+        if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) && Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) )
+        {
+            if ( vObjClasses && Vec_IntEntry(vObjClasses, Gia_ObjFaninId0(pObj, i)) != Vec_IntEntry(vObjClasses, Gia_ObjFaninId1(pObj, i)) )
+                continue;
+            if ( vObjClasses )
+                Vec_IntWriteEntry( vObjClasses, Gia_ObjId(p, pObj), Vec_IntEntry(vObjClasses, Gia_ObjFaninId0(pObj, i)) );
+            Gia_ObjSetTravIdCurrent(p, pObj);
+            (*pnRegMoves)++;
+        }
+    // mark the remaining registers
+    Gia_ManForEachRo( p, pObj, i )
+        Gia_ObjSetTravIdCurrent(p, pObj);
+    // find the cut (all such marked objects that fanout into unmarked nodes)
+    vCut = Vec_PtrAlloc( 1000 );
+    Gia_ManIncrementTravId( p );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjIsTravIdPrevious(p, pObj) )
+            continue;
+        if ( (Gia_ObjIsCo(pObj) || Gia_ObjIsAnd(pObj)) && Gia_ObjIsTravIdPrevious(p, Gia_ObjFanin0(pObj)) )
+        {
+            if ( vFlopClasses )
+                Vec_IntPush( vFlopClasses, Vec_IntEntry(vObjClasses, Gia_ObjFaninId0(pObj, i)) );
+            Vec_PtrPush( vCut, Gia_ObjFanin0(pObj) );
+            Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) );
+        }
+        if ( Gia_ObjIsAnd(pObj) && Gia_ObjIsTravIdPrevious(p, Gia_ObjFanin1(pObj)) )
+        {
+            if ( vFlopClasses )
+                Vec_IntPush( vFlopClasses, Vec_IntEntry(vObjClasses, Gia_ObjFaninId1(pObj, i)) );
+            Vec_PtrPush( vCut, Gia_ObjFanin1(pObj) );
+            Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin1(pObj) );
+        }
+    }
+    assert( vFlopClasses == NULL || Vec_IntSize(vFlopClasses) == Vec_PtrSize(vCut) );
+    // finally derive the new manager
+    pNew = Gia_ManRetimeDupForward( p, vCut );
+    Vec_PtrFree( vCut );
+    if ( vObjClasses )
+    Vec_IntFree( vObjClasses );
+    pNew->vFlopClasses = vFlopClasses;
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the cut for forward retiming.]
+
+  Description [Assumes topological ordering of the nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManRetimeForward( Gia_Man_t * p, int nMaxIters, int fVerbose )
+{
+    Gia_Man_t * pNew, * pTemp;
+    int i, nRegFixed, nRegMoves = 1;
+    abctime clk;
+    pNew = p;
+    for ( i = 0; i < nMaxIters && nRegMoves > 0; i++ )
+    {
+        clk = Abc_Clock();
+        pNew = Gia_ManRetimeForwardOne( pTemp = pNew, &nRegFixed, &nRegMoves );
+        if ( fVerbose )
+        {
+            printf( "%2d : And = %6d. Reg = %5d. Unret = %5d. Move = %6d. ", 
+                i + 1, Gia_ManAndNum(pTemp), Gia_ManRegNum(pTemp), nRegFixed, nRegMoves );
+            ABC_PRT( "Time", Abc_Clock() - clk );
+        }
+        if ( pTemp != p )
+            Gia_ManStop( pTemp );
+    }
+/*
+    clk = Abc_Clock();
+    pNew = Gia_ManReduceLaches( pNew, fVerbose );
+    if ( fVerbose )
+    {
+        ABC_PRT( "Register sharing time", Abc_Clock() - clk );
+    }
+*/
+    return pNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaSat.c b/abc-build/src/aig/gia/giaSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaSat.c
@@ -0,0 +1,427 @@
+/**CFile****************************************************************
+
+  FileName    [giaSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [New constraint-propagation procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define GIA_LIMIT 10
+
+
+typedef struct Gia_ManSat_t_ Gia_ManSat_t;
+struct Gia_ManSat_t_
+{
+    Aig_MmFlex_t *    pMem;
+};
+
+typedef struct Gia_ObjSat1_t_ Gia_ObjSat1_t;
+struct Gia_ObjSat1_t_
+{
+    char              nFans;
+    char              nOffset;
+    char              PathsH;
+    char              PathsV;
+};
+
+typedef struct Gia_ObjSat2_t_ Gia_ObjSat2_t;
+struct Gia_ObjSat2_t_
+{
+    unsigned          fTerm :  1;
+    unsigned          iLit  : 31;
+};
+
+typedef struct Gia_ObjSat_t_ Gia_ObjSat_t;
+struct Gia_ObjSat_t_
+{
+    union {
+        Gia_ObjSat1_t Obj1;
+        Gia_ObjSat2_t Obj2;
+    };
+};
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_ManSat_t * Gia_ManSatStart()
+{
+    Gia_ManSat_t * p;
+    p = ABC_CALLOC( Gia_ManSat_t, 1 );
+    p->pMem = Aig_MmFlexStart();
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSatStop( Gia_ManSat_t * p )
+{
+    Aig_MmFlexStop( p->pMem, 0 );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate rooted at this ]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSatPartCollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, int * pLits, int * pnLits )
+{
+    Gia_Obj_t * pFanin;
+    assert( Gia_ObjIsAnd(pObj) );
+    assert( pObj->fMark0 == 0 );
+    pFanin = Gia_ObjFanin0(pObj);
+    if ( pFanin->fMark0 || Gia_ObjFaninC0(pObj) )
+        pLits[(*pnLits)++] = Gia_Var2Lit(Gia_ObjId(p, pFanin), Gia_ObjFaninC0(pObj));
+    else
+        Gia_ManSatPartCollectSuper(p, pFanin, pLits, pnLits);
+    pFanin = Gia_ObjFanin1(pObj);
+    if ( pFanin->fMark0 || Gia_ObjFaninC1(pObj) )
+        pLits[(*pnLits)++] = Gia_Var2Lit(Gia_ObjId(p, pFanin), Gia_ObjFaninC1(pObj));
+    else
+        Gia_ManSatPartCollectSuper(p, pFanin, pLits, pnLits);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of words used.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManSatPartCreate_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int * pObjPlace, int * pStore )
+{
+    Gia_Obj_t * pFanin;
+    int i, nWordsUsed, nSuperSize = 0, Super[2*GIA_LIMIT];
+    // make sure this is a valid node
+    assert( Gia_ObjIsAnd(pObj) );
+    assert( pObj->fMark0 == 0 );
+    // collect inputs to the supergate
+    Gia_ManSatPartCollectSuper( p, pObj, Super, &nSuperSize );
+    assert( nSuperSize <= 2*GIA_LIMIT );
+    // create the root entry
+    *pObjPlace = 0;
+    ((Gia_ObjSat1_t *)pObjPlace)->nFans   = Gia_Var2Lit( nSuperSize, 0 );
+    ((Gia_ObjSat1_t *)pObjPlace)->nOffset = pStore - pObjPlace;
+    nWordsUsed = nSuperSize;
+    for ( i = 0; i < nSuperSize; i++ )
+    {
+        pFanin = Gia_ManObj( p, Gia_Lit2Var(Super[i]) );
+        if ( pFanin->fMark0 )
+        {
+            ((Gia_ObjSat2_t *)(pStore + i))->fTerm = 1;
+            ((Gia_ObjSat2_t *)(pStore + i))->iLit  = Super[i];
+        }
+        else
+        {
+            assert( Gia_LitIsCompl(Super[i]) );
+            nWordsUsed += Gia_ManSatPartCreate_rec( p, pFanin, pStore + i, pStore + nWordsUsed );
+        }
+    }
+    return nWordsUsed;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates part and returns the number of words used.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManSatPartCreate( Gia_Man_t * p, Gia_Obj_t * pObj, int * pStore )
+{
+    return 1 + Gia_ManSatPartCreate_rec( p, pObj, pStore, pStore + 1 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of internal nodes in the leaf-DAG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSatPartCountClauses( Gia_Man_t * p, Gia_Obj_t * pObj, int * pnOnset, int * pnOffset )
+{
+    Gia_Obj_t * pFanin;
+    int nOnset0, nOnset1, nOffset0, nOffset1;
+    assert( Gia_ObjIsAnd(pObj) );
+    pFanin = Gia_ObjFanin0(pObj);
+    if ( pFanin->fMark0 )
+        nOnset0 = 1, nOffset0 = 1;
+    else
+    {
+        Gia_ManSatPartCountClauses(p, pFanin, &nOnset0, &nOffset0);
+        if ( Gia_ObjFaninC0(pObj) )
+        {
+            int Temp = nOnset0;
+            nOnset0 = nOffset0;
+            nOffset0 = Temp;
+        }
+    }
+    pFanin = Gia_ObjFanin1(pObj);
+    if ( pFanin->fMark0 )
+        nOnset1 = 1, nOffset1 = 1;
+    else
+    {
+        Gia_ManSatPartCountClauses(p, pFanin, &nOnset1, &nOffset1);
+        if ( Gia_ObjFaninC1(pObj) )
+        {
+            int Temp = nOnset1;
+            nOnset1 = nOffset1;
+            nOffset1 = Temp;
+        }
+    }
+    *pnOnset  = nOnset0  * nOnset1;
+    *pnOffset = nOffset0 + nOffset1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of internal nodes in the leaf-DAG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManSatPartCount( Gia_Man_t * p, Gia_Obj_t * pObj, int * pnLeaves, int * pnNodes )
+{
+    Gia_Obj_t * pFanin;
+    int Level0 = 0, Level1 = 0;
+    assert( Gia_ObjIsAnd(pObj) );
+    assert( pObj->fMark0 == 0 );
+    (*pnNodes)++;
+    pFanin = Gia_ObjFanin0(pObj);
+    if ( pFanin->fMark0 )
+        (*pnLeaves)++;
+    else
+        Level0 = Gia_ManSatPartCount(p, pFanin, pnLeaves, pnNodes) + Gia_ObjFaninC0(pObj);
+    pFanin = Gia_ObjFanin1(pObj);
+    if ( pFanin->fMark0 )
+        (*pnLeaves)++;
+    else
+        Level1 = Gia_ManSatPartCount(p, pFanin, pnLeaves, pnNodes) + Gia_ObjFaninC1(pObj);
+    return Abc_MaxInt( Level0, Level1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of internal nodes in the leaf-DAG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManSatPartCountNodes( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    Gia_Obj_t * pFanin;
+    int nNodes0 = 0, nNodes1 = 0;
+    assert( Gia_ObjIsAnd(pObj) );
+    assert( pObj->fMark0 == 0 );
+    pFanin = Gia_ObjFanin0(pObj);
+    if ( !(pFanin->fMark0) )
+        nNodes0 = Gia_ManSatPartCountNodes(p, pFanin);
+    pFanin = Gia_ObjFanin1(pObj);
+    if ( !(pFanin->fMark0) )
+        nNodes1 = Gia_ManSatPartCountNodes(p, pFanin);
+    return nNodes0 + nNodes1 + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of internal nodes in the leaf-DAG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSatPartPrint( Gia_Man_t * p, Gia_Obj_t * pObj, int Step )
+{
+    Gia_Obj_t * pFanin;
+    assert( Gia_ObjIsAnd(pObj) );
+    assert( pObj->fMark0 == 0 );
+    pFanin = Gia_ObjFanin0(pObj);
+    if ( pFanin->fMark0 )
+        printf( "%s%d", Gia_ObjFaninC0(pObj)?"!":"", Gia_ObjId(p,pFanin) );
+    else
+    {
+        if ( Gia_ObjFaninC0(pObj) )
+            printf( "(" );
+        Gia_ManSatPartPrint(p, pFanin, Step + Gia_ObjFaninC0(pObj));
+        if ( Gia_ObjFaninC0(pObj) )
+            printf( ")" );
+    }
+    printf( "%s", (Step & 1)? " + " : "*" );
+    pFanin = Gia_ObjFanin1(pObj);
+    if ( pFanin->fMark0 )
+        printf( "%s%d", Gia_ObjFaninC1(pObj)?"!":"", Gia_ObjId(p,pFanin) );
+    else
+    {
+        if ( Gia_ObjFaninC1(pObj) )
+            printf( "(" );
+        Gia_ManSatPartPrint(p, pFanin, Step + Gia_ObjFaninC1(pObj));
+        if ( Gia_ObjFaninC1(pObj) )
+            printf( ")" );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSatExperiment( Gia_Man_t * p )
+{
+    int nStored, Storage[1000], * pStart; 
+    Gia_ManSat_t * pMan;
+    Gia_Obj_t * pObj;
+    int i, nLevels, nLeaves, nNodes, nCount[2*GIA_LIMIT+2] = {0}, nCountAll = 0;
+    int Num0 = 0, Num1 = 0;
+    clock_t clk = clock();
+    int nWords = 0, nWords2 = 0;
+    pMan = Gia_ManSatStart();
+    // mark the nodes to become roots of leaf-DAGs
+    Gia_ManCreateValueRefs( p );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        pObj->fMark0 = 0;
+        if ( Gia_ObjIsCo(pObj) )
+            Gia_ObjFanin0(pObj)->fMark0 = 1;
+        else if ( Gia_ObjIsCi(pObj) )
+            pObj->fMark0 = 1;
+        else if ( Gia_ObjIsAnd(pObj) )
+        {
+            if ( pObj->Value > 1 || Gia_ManSatPartCountNodes(p,pObj) >= GIA_LIMIT )
+                pObj->fMark0 = 1;
+        }
+        pObj->Value = 0;
+    }
+    // compute the sizes of leaf-DAGs
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        if ( pObj->fMark0 == 0 )
+            continue;
+        pObj->fMark0 = 0;
+
+        nCountAll++;
+        nStored = Gia_ManSatPartCreate( p, pObj, Storage );
+        nWords2 += nStored;
+        assert( nStored < 500 );
+        pStart = (int *)Aig_MmFlexEntryFetch( pMan->pMem, sizeof(int) * nStored );
+        memcpy( pStart, Storage, sizeof(int) * nStored );
+
+        nLeaves = nNodes = 0;
+        nLevels = 1+Gia_ManSatPartCount( p, pObj, &nLeaves, &nNodes );
+        nWords += nLeaves + nNodes;
+        if ( nNodes <= 2*GIA_LIMIT )
+            nCount[nNodes]++;
+        else
+            nCount[2*GIA_LIMIT+1]++;
+//        if ( nNodes > 10 && i % 100 == 0 )
+//        if ( nNodes > 5 )
+        if ( 0 )
+        {
+            Gia_ManSatPartCountClauses( p, pObj, &Num0, &Num1 );
+            printf( "%8d :  And = %3d.  Lev = %2d. Clauses = %3d. (%3d + %3d).\n", i, nNodes, nLevels, Num0+Num1, Num0, Num1 );
+            Gia_ManSatPartPrint( p, pObj, 0 );
+            printf( "\n" );
+        }
+
+        pObj->fMark0 = 1;
+    }
+    printf( "\n" );
+    Gia_ManForEachObj( p, pObj, i )
+        pObj->fMark0 = 0;
+    Gia_ManSatStop( pMan );
+    for ( i = 0; i < 2*GIA_LIMIT+2; i++ )
+        printf( "%2d=%6d  %7.2f %%  %7.2f %%\n", i, nCount[i], 100.0*nCount[i]/nCountAll, 100.0*i*nCount[i]/Gia_ManAndNum(p) );
+    ABC_PRMn( "MemoryEst", 4*nWords );
+    ABC_PRMn( "MemoryReal", 4*nWords2 );
+    printf( "%5.2f bpn  ", 4.0*nWords2/Gia_ManObjNum(p) );
+    ABC_PRT( "Time", clock() - clk );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaScl.c b/abc-build/src/aig/gia/giaScl.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaScl.c
@@ -0,0 +1,309 @@
+/**CFile****************************************************************
+
+  FileName    [giaScl.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Sequential cleanup.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaScl.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Marks unreachable internal nodes and returned their number.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCombMarkUsed_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( pObj == NULL )
+        return 0;
+    if ( !pObj->fMark0 )
+        return 0;
+    pObj->fMark0 = 0;
+    assert( Gia_ObjIsAnd(pObj) );
+    return 1 + Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin0(pObj) )
+             + Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin1(pObj) )
+             + (p->pNexts ? Gia_ManCombMarkUsed_rec( p, Gia_ObjNextObj(p, Gia_ObjId(p, pObj)) ) : 0)
+             + (p->pSibls ? Gia_ManCombMarkUsed_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)) ) : 0)
+             + (p->pMuxes ? Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin2(p, pObj) ) : 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks unreachable internal nodes and returned their number.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCombMarkUsed( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, nNodes = 0;
+    Gia_ManForEachObj( p, pObj, i )
+        pObj->fMark0 = Gia_ObjIsAnd(pObj);
+    Gia_ManForEachCo( p, pObj, i )
+        nNodes += Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin0(pObj) );
+    return nNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs combinational cleanup.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManCleanup( Gia_Man_t * p )
+{
+    Gia_ManCombMarkUsed( p );
+    return Gia_ManDupMarked( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Skip the first outputs during cleanup.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManCleanupOutputs( Gia_Man_t * p, int nOutputs )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Gia_ManRegNum(p) == 0 );
+    assert( nOutputs < Gia_ManCoNum(p) );
+    Gia_ManCombMarkUsed( p );
+    Gia_ManForEachCo( p, pObj, i )
+        if ( i < nOutputs )
+            pObj->fMark0 = 1;
+        else
+            break;
+    return Gia_ManDupMarked( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Marks CIs/COs/ANDs unreachable from POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManSeqMarkUsed_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vRoots )
+{
+    if ( !pObj->fMark0 )
+        return 0;
+    pObj->fMark0 = 0;
+    if ( Gia_ObjIsCo(pObj) )
+        return Gia_ManSeqMarkUsed_rec( p, Gia_ObjFanin0(pObj), vRoots );
+    if ( Gia_ObjIsRo(p, pObj) )
+    {
+        Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) );
+        return 0;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    return 1 + Gia_ManSeqMarkUsed_rec( p, Gia_ObjFanin0(pObj), vRoots )
+             + Gia_ManSeqMarkUsed_rec( p, Gia_ObjFanin1(pObj), vRoots );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks CIs/COs/ANDs unreachable from POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManSeqMarkUsed( Gia_Man_t * p )
+{
+    Vec_Int_t * vRoots;
+    Gia_Obj_t * pObj;
+    int i, nNodes = 0;
+    Gia_ManSetMark0( p );
+    Gia_ManConst0(p)->fMark0 = 0;
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->fMark0 = 0;
+    vRoots = Gia_ManCollectPoIds( p );
+    Gia_ManForEachObjVec( vRoots, p, pObj, i )
+        nNodes += Gia_ManSeqMarkUsed_rec( p, pObj, vRoots );
+    Vec_IntFree( vRoots );
+    return nNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs sequential cleanup.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManSeqCleanup( Gia_Man_t * p )
+{
+    Gia_ManSeqMarkUsed( p );
+    return Gia_ManDupMarked( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find representatives due to identical fanins.]
+
+  Description [Returns the old manager if there is no changes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManReduceEquiv( Gia_Man_t * p, int fVerbose )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObjRi, * pObjRo;
+    unsigned * pCi2Lit, * pMaps;
+    int i, iLit, nFanins = 1, Counter0 = 0, Counter = 0;
+    Gia_ManForEachRi( p, pObjRi, i )
+        Gia_ObjFanin0(pObjRi)->Value = 0;
+    Gia_ManForEachRi( p, pObjRi, i )
+        if ( Gia_ObjFanin0(pObjRi)->Value == 0 )
+            Gia_ObjFanin0(pObjRi)->Value = 2*nFanins++;
+    pCi2Lit = ABC_FALLOC( unsigned, Gia_ManCiNum(p) );
+    pMaps   = ABC_FALLOC( unsigned, 2 * nFanins );
+    Gia_ManForEachRiRo( p, pObjRi, pObjRo, i )
+    {
+        iLit = Gia_ObjFanin0Copy( pObjRi );
+        if ( Gia_ObjFaninId0p(p, pObjRi) == 0 && Gia_ObjFaninC0(pObjRi) == 0 ) // const 0 
+            pCi2Lit[Gia_ManPiNum(p)+i] = 0, Counter0++;
+        else if ( ~pMaps[iLit] ) // in this case, ID(pObj) > ID(pRepr) 
+            pCi2Lit[Gia_ManPiNum(p)+i] = pMaps[iLit], Counter++; 
+        else
+            pMaps[iLit] = Abc_Var2Lit( Gia_ObjId(p, pObjRo), 0 );
+    }
+/*
+    Gia_ManForEachCi( p, pObjRo, i )
+    {
+        if ( ~pCi2Lit[i] )
+        {
+            Gia_Obj_t * pObj0 = Gia_ObjRoToRi(p, pObjRo);
+            Gia_Obj_t * pObj1 = Gia_ObjRoToRi(p, Gia_ManObj(p, pCi2Lit[i]));
+            Gia_Obj_t * pFan0 = Gia_ObjChild0( p, Gia_ObjRoToRi(p, pObjRo) );
+            Gia_Obj_t * pFan1 = Gia_ObjChild0( p, Gia_ObjRoToRi(p, Gia_ManObj(p, pCi2Lit[i])) );
+            assert( pFan0 == pFan1 );
+        }
+    }
+*/
+//    if ( fVerbose )
+//        printf( "ReduceEquiv detected %d constant regs and %d equivalent regs.\n", Counter0, Counter );
+    ABC_FREE( pMaps );
+    if ( Counter0 || Counter )
+        pNew = Gia_ManDupDfsCiMap( p, (int *)pCi2Lit, NULL );
+    else
+        pNew = p;
+    ABC_FREE( pCi2Lit );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs sequential cleanup.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManSeqStructSweep( Gia_Man_t * p, int fConst, int fEquiv, int fVerbose )
+{
+    Gia_Man_t * pTemp;
+    if ( Gia_ManRegNum(p) == 0 )
+        return Gia_ManCleanup( p );
+    if ( fVerbose )
+        printf( "Performing sequential cleanup.\n" );
+    p = Gia_ManSeqCleanup( pTemp = p );
+    if ( fVerbose )
+        Gia_ManReportImprovement( pTemp, p );
+    if ( fConst && Gia_ManRegNum(p) )
+    {
+        p = Gia_ManReduceConst( pTemp = p, fVerbose );
+        if ( fVerbose )
+            Gia_ManReportImprovement( pTemp, p );
+        Gia_ManStop( pTemp );
+    }
+    if ( fVerbose && fEquiv )
+        printf( "Merging combinationally equivalent flops.\n" );
+    if ( fEquiv )
+    while ( 1 )
+    {
+        p = Gia_ManSeqCleanup( pTemp = p );
+        if ( fVerbose )
+            Gia_ManReportImprovement( pTemp, p );
+        Gia_ManStop( pTemp );
+        if ( Gia_ManRegNum(p) == 0 )
+            break;
+        p = Gia_ManReduceEquiv( pTemp = p, fVerbose );
+        if ( p == pTemp )
+            break;
+        Gia_ManStop( pTemp );
+    }
+    return p;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaShrink.c b/abc-build/src/aig/gia/giaShrink.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaShrink.c
@@ -0,0 +1,154 @@
+/**CFile****************************************************************
+
+  FileName    [giaShrink.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Implementation of mapShrink based on ideas of Niklas Een.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaShrink.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "aig/aig/aig.h"
+#include "opt/dar/dar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern int  Dar_LibEvalBuild( Gia_Man_t * p, Vec_Int_t * vCut, unsigned uTruth, int fKeepLevel, Vec_Int_t * vLeavesBest );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs AIG shrinking using the current mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManMapShrink4( Gia_Man_t * p, int fKeepLevel, int fVerbose )
+{
+    Vec_Int_t * vLeaves, * vTruth, * vVisited, * vLeavesBest;
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pFanin;
+    unsigned * pTruth;
+    int i, k, iFan;
+    abctime clk = Abc_Clock();
+//    int ClassCounts[222] = {0};
+    int * pLutClass, Counter = 0;
+    assert( Gia_ManHasMapping(p) );
+    if ( Gia_ManLutSizeMax( p ) > 4 )
+    {
+        printf( "Resynthesis is not performed when nodes have more than 4 inputs.\n" );
+        return NULL;
+    }
+    pLutClass   = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    vLeaves     = Vec_IntAlloc( 0 );
+    vTruth      = Vec_IntAlloc( (1<<16) );
+    vVisited    = Vec_IntAlloc( 0 );
+    vLeavesBest = Vec_IntAlloc( 4 );
+    // prepare the library
+    Dar_LibPrepare( 5 ); 
+    // clean the old manager
+    Gia_ManCleanTruth( p );
+    Gia_ManSetPhase( p );
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    // start the new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManCleanLevels( pNew, Gia_ManObjNum(p) );
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsCi(pObj) )
+        {
+            pObj->Value = Gia_ManAppendCi( pNew );
+            if ( p->vLevels )
+                Gia_ObjSetLevel( pNew, Gia_ObjFromLit(pNew, Gia_ObjValue(pObj)), Gia_ObjLevel(p, pObj) );
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+        {
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+        }
+        else if ( Gia_ObjIsLut(p, i) )
+        {
+            Counter++;
+            // collect leaves of this gate
+            Vec_IntClear( vLeaves );
+            Gia_LutForEachFanin( p, i, iFan, k )
+                Vec_IntPush( vLeaves, iFan );
+            for ( ; k < 4; k++ )
+                Vec_IntPush( vLeaves, 0 );
+            //.compute the truth table 
+            pTruth = Gia_ManConvertAigToTruth( p, pObj, vLeaves, vTruth, vVisited );
+            // change from node IDs to their literals
+            Gia_ManForEachObjVec( vLeaves, p, pFanin, k )
+            {
+//                assert( Gia_ObjValue(pFanin) != ~0 ); 
+                Vec_IntWriteEntry( vLeaves, k, Gia_ObjValue(pFanin) != ~0 ? Gia_ObjValue(pFanin) : 0 );
+            }
+            // derive new structre
+            if ( Gia_ManTruthIsConst0(pTruth, Vec_IntSize(vLeaves)) )
+                pObj->Value = 0;
+            else if ( Gia_ManTruthIsConst1(pTruth, Vec_IntSize(vLeaves)) )
+                pObj->Value = 1;
+            else
+            {
+                pObj->Value = Dar_LibEvalBuild( pNew, vLeaves, 0xffff & *pTruth, fKeepLevel, vLeavesBest );
+                pObj->Value = Abc_LitNotCond( pObj->Value, Gia_ObjPhaseRealLit(pNew, pObj->Value) ^ pObj->fPhase );
+            }
+        }
+    }
+    // cleanup the AIG
+    Gia_ManHashStop( pNew );
+    // check the presence of dangling nodes
+    if ( Gia_ManHasDangling(pNew) )
+    {
+        pNew = Gia_ManCleanup( pTemp = pNew );
+        if ( fVerbose && Gia_ManAndNum(pNew) != Gia_ManAndNum(pTemp) )
+            printf( "Gia_ManMapShrink4() node reduction after sweep %6d -> %6d.\n", Gia_ManAndNum(pTemp), Gia_ManAndNum(pNew) );
+        Gia_ManStop( pTemp );
+    }
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    Vec_IntFree( vLeaves );
+    Vec_IntFree( vTruth );
+    Vec_IntFree( vVisited );
+    Vec_IntFree( vLeavesBest );
+    if ( fVerbose )
+    {
+        printf( "Total gain in AIG nodes = %d.  ", Gia_ManObjNum(p)-Gia_ManObjNum(pNew) );
+        ABC_PRT( "Total runtime", Abc_Clock() - clk );
+    }
+    ABC_FREE( pLutClass );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaShrink6.c b/abc-build/src/aig/gia/giaShrink6.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaShrink6.c
@@ -0,0 +1,489 @@
+/**CFile****************************************************************
+
+  FileName    [giaShrink6.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Implementation of DAG-aware unmapping for 6-input cuts.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaShrink6.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "bool/bdc/bdc.h"
+#include "bool/rsb/rsb.h"
+//#include "misc/util/utilTruth.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static word Truth[8] = {
+    ABC_CONST(0xAAAAAAAAAAAAAAAA),
+    ABC_CONST(0xCCCCCCCCCCCCCCCC),
+    ABC_CONST(0xF0F0F0F0F0F0F0F0),
+    ABC_CONST(0xFF00FF00FF00FF00),
+    ABC_CONST(0xFFFF0000FFFF0000),
+    ABC_CONST(0xFFFFFFFF00000000),
+    ABC_CONST(0x0000000000000000),
+    ABC_CONST(0xFFFFFFFFFFFFFFFF)
+};
+
+// fanout structure
+typedef struct Shr_Fan_t_ Shr_Fan_t;
+struct Shr_Fan_t_
+{
+    int                iFan;           // fanout ID
+    int                Next;           // next structure
+};
+
+// operation manager
+typedef struct Shr_Man_t_ Shr_Man_t;
+struct Shr_Man_t_
+{
+    Gia_Man_t *        pGia;           // user's AIG
+    Gia_Man_t *        pNew;           // constructed AIG
+    int                nDivMax;        // max number of divisors
+    int                nNewSize;       // max growth size
+    // dynamic fanout (can only grow)
+    Vec_Wrd_t *        vFanMem;        // fanout memory
+    Vec_Int_t *        vObj2Fan;       // fanout
+    Shr_Fan_t *        pFanTemp;       // temporary fanout
+    // divisors
+    Vec_Int_t *        vDivs;          // divisors
+    Vec_Int_t *        vPrio;          // priority queue
+    Vec_Int_t *        vDivResub;      // resubstitution
+    Vec_Int_t *        vLeaves;        // cut leaves
+    // truth tables
+    Vec_Wrd_t *        vTruths;        // truth tables
+    Vec_Wrd_t *        vDivTruths;     // truth tables
+    // bidecomposition
+    Rsb_Man_t *        pManRsb;
+    Bdc_Man_t *        pManDec;       
+    Bdc_Par_t          Pars;
+    // statistics 
+};
+
+#define Shr_ObjForEachFanout( p, iNode, iFan )                      \
+    for ( iFan = Shr_ManFanIterStart(p, iNode); iFan; iFan = Shr_ManFanIterNext(p) )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Shr_Man_t * Shr_ManAlloc( Gia_Man_t * pGia )
+{
+    Shr_Man_t * p;
+    p = ABC_CALLOC( Shr_Man_t, 1 );
+    p->nDivMax     = 64;
+    p->nNewSize    = 2 * Gia_ManObjNum(pGia);
+    p->pGia        = pGia;
+    p->vFanMem     = Vec_WrdAlloc( 1000 );   Vec_WrdPush(p->vFanMem, -1); 
+    p->vObj2Fan    = Vec_IntStart( p->nNewSize );
+    p->vDivs       = Vec_IntAlloc( 1000 );
+    p->vPrio       = Vec_IntAlloc( 1000 );
+    p->vTruths     = Vec_WrdStart( p->nNewSize );
+    p->vDivTruths  = Vec_WrdAlloc( 100 );
+    p->vDivResub   = Vec_IntAlloc( 6 );
+    p->vLeaves     = Vec_IntAlloc( 6 );
+    // start new manager
+    p->pNew        = Gia_ManStart( p->nNewSize );
+    p->pNew->pName = Abc_UtilStrsav( pGia->pName );
+    p->pNew->pSpec = Abc_UtilStrsav( pGia->pSpec );
+    Gia_ManHashAlloc( p->pNew );
+    Gia_ManCleanLevels( p->pNew, p->nNewSize );
+    // allocate traversal IDs
+    p->pNew->nObjs = p->nNewSize;
+    Gia_ManIncrementTravId( p->pNew );
+    p->pNew->nObjs = 1;
+    // start decompostion
+    p->Pars.nVarsMax = 6;
+    p->Pars.fVerbose = 0;
+    p->pManDec = Bdc_ManAlloc( &p->Pars );
+    p->pManRsb = Rsb_ManAlloc( 6, p->nDivMax, 4, 1 );
+    return p;
+}
+Gia_Man_t * Shr_ManFree( Shr_Man_t * p )
+{
+    // prepare the manager
+    Gia_Man_t * pTemp;
+    Gia_ManHashStop( p->pNew );
+    Vec_IntFreeP( &p->pNew->vLevels );
+    if ( Gia_ManHasDangling(p->pNew) )
+    {
+        p->pNew = Gia_ManCleanup( pTemp = p->pNew );
+        if ( Gia_ManAndNum(p->pNew) != Gia_ManAndNum(pTemp) )
+            printf( "Node reduction after sweep %6d -> %6d.\n", Gia_ManAndNum(pTemp), Gia_ManAndNum(p->pNew) );
+        Gia_ManStop( pTemp );
+    }
+    Gia_ManSetRegNum( p->pNew, Gia_ManRegNum(p->pGia) );
+    pTemp = p->pNew; p->pNew = NULL;
+    // free data structures
+    Rsb_ManFree( p->pManRsb );
+    Bdc_ManFree( p->pManDec );
+    Gia_ManStopP( &p->pNew );
+    Vec_WrdFree( p->vFanMem );
+    Vec_IntFree( p->vObj2Fan );
+    Vec_IntFree( p->vDivs );
+    Vec_IntFree( p->vPrio );
+    Vec_WrdFree( p->vTruths );
+    Vec_WrdFree( p->vDivTruths );
+    Vec_IntFree( p->vDivResub );
+    Vec_IntFree( p->vLeaves );
+    ABC_FREE( p );
+    return pTemp;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Fanout manipulation.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Shr_ManAddFanout( Shr_Man_t * p, int iFanin, int iFanout )
+{
+    Shr_Fan_t FanStr;
+    FanStr.iFan = iFanout;
+    FanStr.Next = Vec_IntEntry(p->vObj2Fan, iFanin);
+    Vec_IntWriteEntry( p->vObj2Fan, iFanin, Vec_WrdSize(p->vFanMem) );
+    Vec_WrdPush(p->vFanMem, *((word *)&FanStr) );
+}
+static inline int Shr_ManFanIterStart( Shr_Man_t * p, int iNode )
+{
+    if ( Vec_IntEntry(p->vObj2Fan, iNode) == 0 )
+        return 0;
+    p->pFanTemp = (Shr_Fan_t *)Vec_WrdEntryP( p->vFanMem, Vec_IntEntry(p->vObj2Fan, iNode) );
+    return p->pFanTemp->iFan;
+}
+static inline int Shr_ManFanIterNext( Shr_Man_t * p )
+{
+    if ( p->pFanTemp->Next == 0 )
+        return 0;
+    p->pFanTemp = (Shr_Fan_t *)Vec_WrdEntryP( p->vFanMem, p->pFanTemp->Next );
+    return p->pFanTemp->iFan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect divisors.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Shr_ManDivPushOrderByLevel( Shr_Man_t * p, int iDiv )
+{
+    int iPlace, * pArray;
+    Vec_IntPush( p->vPrio, iDiv );
+    if ( Vec_IntSize(p->vPrio) == 1 )
+        return 0; 
+    pArray = Vec_IntArray(p->vPrio);
+    for ( iPlace = Vec_IntSize(p->vPrio) - 1; iPlace > 0; iPlace-- )
+        if ( Gia_ObjLevel(p->pNew, Gia_ManObj(p->pNew, pArray[iPlace-1])) > 
+             Gia_ObjLevel(p->pNew, Gia_ManObj(p->pNew, pArray[iPlace])) )
+             ABC_SWAP( int, pArray[iPlace-1], pArray[iPlace] )
+        else
+            break;
+    return iPlace; // the place of the new divisor
+}
+static inline int Shr_ManCollectDivisors( Shr_Man_t * p, Vec_Int_t * vLeaves, int Limit, int nFanoutMax )
+{
+    Gia_Obj_t * pFan;
+    int i, c, iDiv, iFan, iPlace;
+    assert( Limit > 6 );
+    Vec_IntClear( p->vDivs );
+    Vec_IntClear( p->vPrio );
+    Gia_ManIncrementTravId( p->pNew );
+    Vec_IntForEachEntry( vLeaves, iDiv, i )
+    {
+        Vec_IntPush( p->vDivs, iDiv );
+        Shr_ManDivPushOrderByLevel( p, iDiv );
+        Gia_ObjSetTravIdCurrentId( p->pNew, iDiv );
+    }
+    Vec_IntForEachEntry( p->vPrio, iDiv, i )
+    {
+        c = 0;
+        assert( Gia_ObjIsTravIdCurrentId(p->pNew, iDiv) );
+        Shr_ObjForEachFanout( p, iDiv, iFan )
+        {
+            if ( c++ == nFanoutMax )
+                break;
+            if ( Gia_ObjIsTravIdCurrentId(p->pNew, iFan) )
+                continue;
+            pFan = Gia_ManObj( p->pNew, iFan );
+            assert( Gia_ObjIsAnd(pFan) );
+            assert( Gia_ObjLevel(p->pNew, Gia_ManObj(p->pNew, iDiv)) < Gia_ObjLevel(p->pNew, pFan) );
+            if ( !Gia_ObjIsTravIdCurrentId(p->pNew, Gia_ObjFaninId0(pFan, iFan)) ||
+                 !Gia_ObjIsTravIdCurrentId(p->pNew, Gia_ObjFaninId1(pFan, iFan)) )
+                continue;
+            Vec_IntPush( p->vDivs, iFan );
+            Gia_ObjSetTravIdCurrentId( p->pNew, iFan );
+            iPlace = Shr_ManDivPushOrderByLevel( p, iFan );
+            assert( i < iPlace );
+            if ( Vec_IntSize(p->vDivs) == Limit )
+                return Vec_IntSize(p->vDivs);
+        }
+    }
+    return Vec_IntSize(p->vDivs);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resynthesizes nodes using bi-decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Shr_ObjPerformBidec( Shr_Man_t * p, Bdc_Man_t * pManDec, Gia_Man_t * pNew, Vec_Int_t * vLeafLits, word uTruth1, word uTruthC )
+{
+    Bdc_Fun_t * pFunc;
+    Gia_Obj_t * pObj;
+    int i, iVar, iLit, nNodes, iLast;
+    int nVars = Vec_IntSize(vLeafLits);
+    assert( uTruth1 != 0 && uTruthC != 0 );
+    Bdc_ManDecompose( pManDec, (unsigned *)&uTruth1, (unsigned *)&uTruthC, nVars, NULL, 1000 );
+    Bdc_FuncSetCopyInt( Bdc_ManFunc(pManDec, 0), 1 );
+    Vec_IntForEachEntry( vLeafLits, iVar, i )
+        Bdc_FuncSetCopyInt( Bdc_ManFunc(pManDec, i+1), Abc_Var2Lit(iVar, 0) );
+    nNodes = Bdc_ManNodeNum( pManDec );
+    for ( i = nVars + 1; i < nNodes; i++ )
+    {
+        pFunc = Bdc_ManFunc( pManDec, i );
+        iLast = Gia_ManObjNum(pNew);
+        iLit  = Gia_ManHashAnd( pNew, Bdc_FunFanin0Copy(pFunc), Bdc_FunFanin1Copy(pFunc) );
+        Bdc_FuncSetCopyInt( pFunc, iLit );
+        if ( iLast == Gia_ManObjNum(pNew) )
+            continue;
+        assert( iLast + 1 == Gia_ManObjNum(pNew) );
+        pObj = Gia_ManObj(pNew, Abc_Lit2Var(iLit));
+        Gia_ObjSetAndLevel( pNew, pObj );
+        Shr_ManAddFanout( p, Gia_ObjFaninId0p(pNew, pObj), Gia_ObjId(pNew, pObj) );
+        Shr_ManAddFanout( p, Gia_ObjFaninId1p(pNew, pObj), Gia_ObjId(pNew, pObj) );
+        assert( Gia_ManObjNum(pNew) < p->nNewSize );
+    }
+    return Bdc_FunObjCopy( Bdc_ManRoot(pManDec) );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compute truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word Shr_ManComputeTruth6_rec( Gia_Man_t * p, int iNode, Vec_Wrd_t * vTruths )
+{
+    Gia_Obj_t * pObj;
+    word Truth0, Truth1;
+    if ( Gia_ObjIsTravIdCurrentId(p, iNode) )
+        return Vec_WrdEntry(vTruths, iNode);
+    Gia_ObjSetTravIdCurrentId(p, iNode);
+    pObj = Gia_ManObj( p, iNode );
+    assert( Gia_ObjIsAnd(pObj) );
+    Truth0 = Shr_ManComputeTruth6_rec( p, Gia_ObjFaninId0p(p, pObj), vTruths );
+    Truth1 = Shr_ManComputeTruth6_rec( p, Gia_ObjFaninId1p(p, pObj), vTruths );
+    if ( Gia_ObjFaninC0(pObj) )
+        Truth0 = ~Truth0;
+    if ( Gia_ObjFaninC1(pObj) )
+        Truth1 = ~Truth1;
+    Vec_WrdWriteEntry( vTruths, iNode, Truth0 & Truth1 );
+    return Truth0 & Truth1;
+}
+word Shr_ManComputeTruth6( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves, Vec_Wrd_t * vTruths )
+{
+    int i, iLeaf;
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManIncrementTravId( p );
+    Vec_IntForEachEntry( vLeaves, iLeaf, i )
+    {
+        Gia_ObjSetTravIdCurrentId( p, iLeaf );
+        Vec_WrdWriteEntry( vTruths, iLeaf, Truth[i] );
+    }
+    return Shr_ManComputeTruth6_rec( p, Gia_ObjId(p, pObj), vTruths );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Shr_ManComputeTruths( Gia_Man_t * p, int nVars, Vec_Int_t * vDivs, Vec_Wrd_t * vDivTruths, Vec_Wrd_t * vTruths )
+{
+    Gia_Obj_t * pObj;
+    word Truth0, Truth1;//, Truthh;
+    int i, iDiv;
+    Vec_WrdClear( vDivTruths );
+    Vec_IntForEachEntryStop( vDivs, iDiv, i, nVars )
+    {
+        Vec_WrdWriteEntry( vTruths, iDiv, Truth[i] );
+        Vec_WrdPush( vDivTruths, Truth[i] );
+    }
+    Vec_IntForEachEntryStart( vDivs, iDiv, i, nVars )
+    {
+        pObj = Gia_ManObj( p, iDiv );
+        Truth0 = Vec_WrdEntry( vTruths, Gia_ObjFaninId0(pObj, iDiv) );
+        Truth1 = Vec_WrdEntry( vTruths, Gia_ObjFaninId1(pObj, iDiv) );
+        if ( Gia_ObjFaninC0(pObj) )
+            Truth0 = ~Truth0;
+        if ( Gia_ObjFaninC1(pObj) )
+            Truth1 = ~Truth1;
+        Vec_WrdWriteEntry( vTruths, iDiv, Truth0 & Truth1 );
+        Vec_WrdPush( vDivTruths, Truth0 & Truth1 );
+
+//        Truthh = Truth0 & Truth1;
+//        Abc_TtPrintBinary( &Truthh, nVars );   //printf( "\n" );
+//        Kit_DsdPrintFromTruth( &Truthh, nVars );    printf( "\n" );
+    }
+//    printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManMapShrink6( Gia_Man_t * p, int nFanoutMax, int fKeepLevel, int fVerbose )
+{
+    Shr_Man_t * pMan;
+    Gia_Obj_t * pObj, * pFanin;
+    word uTruth, uTruth0, uTruth1;
+    int i, k, nDivs, iNode;
+    int RetValue, Counter1 = 0, Counter2 = 0;
+    abctime clk2, clk = Abc_Clock();
+    abctime timeFanout = 0;
+    assert( Gia_ManHasMapping(p) );
+    pMan = Shr_ManAlloc( p );
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsCi(pObj) )
+        {
+            pObj->Value = Gia_ManAppendCi( pMan->pNew );
+            if ( p->vLevels )
+                Gia_ObjSetLevel( pMan->pNew, Gia_ObjFromLit(pMan->pNew, Gia_ObjValue(pObj)), Gia_ObjLevel(p, pObj) );
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+        {
+            pObj->Value = Gia_ManAppendCo( pMan->pNew, Gia_ObjFanin0Copy(pObj) );
+        }
+        else if ( Gia_ObjIsLut(p, i) )
+        {
+            // collect leaves of this gate  
+            Vec_IntClear( pMan->vLeaves );
+            Gia_LutForEachFanin( p, i, iNode, k )
+                Vec_IntPush( pMan->vLeaves, iNode );
+            assert( Vec_IntSize(pMan->vLeaves) <= 6 );
+            // compute truth table 
+            uTruth = Shr_ManComputeTruth6( pMan->pGia, pObj, pMan->vLeaves, pMan->vTruths );
+            assert( pObj->Value == ~0 );
+            if ( uTruth == 0 || ~uTruth == 0 )
+                pObj->Value = Abc_LitNotCond( 0, ~uTruth == 0 );
+            else
+                Gia_ManForEachObjVec( pMan->vLeaves, p, pFanin, k )
+                    if ( uTruth == Truth[k] || ~uTruth == Truth[k] )
+                        pObj->Value = Abc_LitNotCond( pFanin->Value, ~uTruth == Truth[k] );
+            if ( pObj->Value != ~0 )
+                continue;
+            // translate into new nodes
+            Gia_ManForEachObjVec( pMan->vLeaves, p, pFanin, k )
+            {
+                if ( Abc_LitIsCompl(pFanin->Value) )
+                    uTruth = ((uTruth & Truth[k]) >> (1 << k)) | ((uTruth & ~Truth[k]) << (1 << k));
+                Vec_IntWriteEntry( pMan->vLeaves, k, Abc_Lit2Var(pFanin->Value) );
+            }
+            // compute divisors
+            clk2 = Abc_Clock();
+            nDivs = Shr_ManCollectDivisors( pMan, pMan->vLeaves, pMan->nDivMax, nFanoutMax );
+            assert( nDivs <= pMan->nDivMax );
+            timeFanout += Abc_Clock() - clk2;
+            // compute truth tables
+            Shr_ManComputeTruths( pMan->pNew, Vec_IntSize(pMan->vLeaves), pMan->vDivs, pMan->vDivTruths, pMan->vTruths );
+            // perform resubstitution
+            RetValue = Rsb_ManPerformResub6( pMan->pManRsb, Vec_IntSize(pMan->vLeaves), uTruth, pMan->vDivTruths, &uTruth0, &uTruth1, 0 );
+            if ( RetValue ) // resub exists
+            {
+                Vec_Int_t * vResult = Rsb_ManGetFanins(pMan->pManRsb);
+                Vec_IntClear( pMan->vDivResub );
+                Vec_IntForEachEntry( vResult, iNode, k )
+                    Vec_IntPush( pMan->vDivResub, Vec_IntEntry(pMan->vDivs, iNode) );
+                pObj->Value = Shr_ObjPerformBidec( pMan, pMan->pManDec, pMan->pNew, pMan->vDivResub, uTruth1, uTruth0 | uTruth1 );
+                Counter1++;
+            }
+            else
+            {
+                pObj->Value = Shr_ObjPerformBidec( pMan, pMan->pManDec, pMan->pNew, pMan->vLeaves, uTruth, ~(word)0 );
+                Counter2++;
+            }
+        }
+    }
+    if ( fVerbose )
+    {
+        printf( "Performed %d resubs and %d decomps.  ", Counter1, Counter2 );
+        printf( "Gain in AIG nodes = %d.  ", Gia_ManObjNum(p)-Gia_ManObjNum(pMan->pNew) );
+        ABC_PRT( "Runtime", Abc_Clock() - clk );
+//        ABC_PRT( "Divisors", timeFanout );        
+    }
+    return Shr_ManFree( pMan );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaShrink7.c b/abc-build/src/aig/gia/giaShrink7.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaShrink7.c
@@ -0,0 +1,373 @@
+/**CFile****************************************************************
+
+  FileName    [giaShrink7.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Implementation of DAG-aware unmapping for 6-input cuts.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaShrink6.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/vec/vecHash.h"
+#include "misc/util/utilTruth.h"
+
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// operation manager
+typedef struct Unm_Man_t_ Unm_Man_t;
+struct Unm_Man_t_
+{
+    Gia_Man_t *        pGia;           // user's AIG
+    Gia_Man_t *        pNew;           // constructed AIG
+    Hash_IntMan_t *    pHash;          // hash table
+    int                nNewSize;       // expected size of new manager
+    Vec_Int_t *        vUsed;          // used nodes
+    Vec_Int_t *        vId2Used;       // mapping of obj IDs into used node IDs
+    Vec_Wrd_t *        vTruths;        // truth tables
+    Vec_Int_t *        vLeaves;        // temporary storage for leaves
+    abctime            clkStart;       // starting the clock
+};
+
+extern word Shr_ManComputeTruth6( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves, Vec_Wrd_t * vTruths );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Unm_Man_t * Unm_ManAlloc( Gia_Man_t * pGia )
+{
+    Unm_Man_t * p;
+    p = ABC_CALLOC( Unm_Man_t, 1 );
+    p->clkStart    = Abc_Clock();
+    p->nNewSize    = 3 * Gia_ManObjNum(pGia) / 2;
+    p->pGia        = pGia;
+    p->pNew        = Gia_ManStart( p->nNewSize );
+    p->pNew->pName = Abc_UtilStrsav( pGia->pName );
+    p->pNew->pSpec = Abc_UtilStrsav( pGia->pSpec );
+    Gia_ManHashAlloc( p->pNew );
+    Gia_ManCleanLevels( p->pNew, p->nNewSize );
+    // allocate traversal IDs
+    p->pNew->nObjs = p->nNewSize;
+    Gia_ManIncrementTravId( p->pNew );
+    p->pNew->nObjs = 1;
+    // start hashing
+    p->pHash = Hash_IntManStart( 1000 );
+    // truth tables
+    p->vLeaves = Vec_IntStart( 10 );
+    return p;
+}
+Gia_Man_t * Unm_ManFree( Unm_Man_t * p )
+{
+    Gia_Man_t * pTemp = p->pNew; p->pNew = NULL;
+    Gia_ManHashStop( pTemp );
+    Vec_IntFreeP( &pTemp->vLevels );
+    Gia_ManSetRegNum( pTemp, Gia_ManRegNum(p->pGia) );
+    // truth tables
+    Vec_WrdFreeP( &p->vTruths );
+    Vec_IntFreeP( &p->vLeaves );
+    Vec_IntFreeP( &p->vUsed );
+    Vec_IntFreeP( &p->vId2Used );
+    // free data structures
+    Hash_IntManStop( p->pHash );
+    ABC_FREE( p );
+
+    Gia_ManStop( pTemp );
+    pTemp = NULL;
+
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes information about node pairs.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Unm_ManPrintPairStats( Hash_IntMan_t * pHash, int nTotal0, int nPairs0, int nPairs1, int fUseLit )
+{
+    int i, Num, nRefs, nPairs = 0, nTotal = 0, Counter[21] = {0};
+    Num = Hash_IntManEntryNum( pHash );
+    for ( i = 1; i <= Num; i++ )
+    {
+        nRefs = Abc_MinInt( 20, Hash_IntObjData2(pHash, i) );
+        nTotal += nRefs;
+        Counter[nRefs]++;
+        nPairs += (nRefs > 1);
+/*
+        if ( fUseLit )
+            printf( "(%c%c, %c%c) %d\n", 
+                Abc_LitIsCompl(Hash_IntObjData0(pHash, i)-2) ? '!' : ' ', 
+                'a' + Abc_Lit2Var(Hash_IntObjData0(pHash, i)-2), 
+                Abc_LitIsCompl(Hash_IntObjData1(pHash, i)-2) ? '!' : ' ', 
+                'a' + Abc_Lit2Var(Hash_IntObjData1(pHash, i)-2), nRefs );
+        else
+            printf( "( %c,  %c) %d\n", 
+                'a' + Hash_IntObjData0(pHash, i)-1, 
+                'a' + Hash_IntObjData1(pHash, i)-1, nRefs );
+*/
+//        printf( "(%4d, %4d) %d\n", Hash_IntObjData0(pHash, i), Hash_IntObjData1(pHash, i), nRefs );
+
+    }
+    printf( "Statistics for pairs appearing less than 20 times:\n" );
+    for ( i = 0; i < 21; i++ )
+        if ( Counter[i] > 0 )
+            printf( "%3d : %7d  %7.2f %%\n", i, Counter[i], 100.0 * Counter[i] * i / Abc_MaxInt(nTotal, 1) );
+    printf( "Pairs:  Total = %8d    Init = %8d %7.2f %%    Final = %8d %7.2f %%    Real = %8d %7.2f %%\n", nTotal0, 
+        nPairs0,  100.0 * nPairs0 / Abc_MaxInt(nTotal0, 1), 
+        nPairs, 100.0 * nPairs / Abc_MaxInt(nTotal0, 1), 
+        nPairs1, 100.0 * nPairs1 / Abc_MaxInt(nTotal0, 1) );
+    return nPairs;
+}
+Vec_Int_t * Unm_ManComputePairs( Unm_Man_t * p, int fVerbose )
+{
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vPairs = Vec_IntAlloc( 1000 );
+    Vec_Int_t * vNum2Obj = Vec_IntStart( 1 );
+    Hash_IntMan_t * pHash = Hash_IntManStart( 1000 );
+    int nTotal = 0, nPairs0 = 0, nPairs = 0;
+    int i, k, j, FanK, FanJ, Num, nRefs;
+    Gia_ManSetRefsMapped( p->pGia );
+    Gia_ManForEachLut( p->pGia, i )
+    {
+        nTotal += Gia_ObjLutSize(p->pGia, i) * (Gia_ObjLutSize(p->pGia, i) - 1) / 2;
+        pObj = Gia_ManObj( p->pGia, i );
+        // collect leaves of this gate  
+        Vec_IntClear( p->vLeaves );
+        Gia_LutForEachFanin( p->pGia, i, Num, k )
+            if ( Gia_ObjRefNumId(p->pGia, Num) > 1 )
+                Vec_IntPush( p->vLeaves, Num );
+        if ( Vec_IntSize(p->vLeaves) < 2 )
+            continue;
+        nPairs0 += Vec_IntSize(p->vLeaves) * (Vec_IntSize(p->vLeaves) - 1) / 2;
+        // enumerate pairs
+        Vec_IntForEachEntry( p->vLeaves, FanK, k )
+        Vec_IntForEachEntryStart( p->vLeaves, FanJ, j, k+1 )
+        {
+            if ( FanK > FanJ )
+                ABC_SWAP( int, FanK, FanJ );
+            Num = Hash_Int2ManInsert( pHash, FanK, FanJ, 0 );
+            nRefs = Hash_Int2ObjInc(pHash, Num);
+            if ( nRefs == 0 )
+            {
+                assert( Num == Hash_IntManEntryNum(pHash) );
+                assert( Num == Vec_IntSize(vNum2Obj) );
+                Vec_IntPush( vNum2Obj, i );
+                continue;
+            }
+            if ( nRefs == 1 )
+            {
+                assert( Num < Vec_IntSize(vNum2Obj) );
+                Vec_IntPush( vPairs, Vec_IntEntry(vNum2Obj, Num) );
+                Vec_IntPush( vPairs, FanK );
+                Vec_IntPush( vPairs, FanJ);
+            }
+            Vec_IntPush( vPairs, i );
+            Vec_IntPush( vPairs, FanK );
+            Vec_IntPush( vPairs, FanJ );
+        }
+    }
+    Vec_IntFree( vNum2Obj );
+    if ( fVerbose )
+        nPairs = Unm_ManPrintPairStats( pHash, nTotal, nPairs0, Vec_IntSize(vPairs) / 3, 0 );
+    Hash_IntManStop( pHash );
+    return vPairs;    
+}
+// finds used nodes
+Vec_Int_t * Unm_ManFindUsedNodes( Vec_Int_t * vPairs, int nObjs )
+{
+    Vec_Int_t * vNodes = Vec_IntAlloc( 1000 );
+    Vec_Str_t * vMarks = Vec_StrStart( nObjs ); int i;
+    for ( i = 0; i < Vec_IntSize(vPairs); i += 3 )
+        Vec_StrWriteEntry( vMarks, Vec_IntEntry(vPairs, i), 1 );
+    for ( i = 0; i < nObjs; i++ )
+        if ( Vec_StrEntry( vMarks, i ) )
+            Vec_IntPush( vNodes, i );
+    Vec_StrFree( vMarks );
+    printf( "The number of used nodes = %d\n", Vec_IntSize(vNodes) );
+    return vNodes;
+}
+// computes truth table for selected nodes
+Vec_Wrd_t * Unm_ManComputeTruths( Unm_Man_t * p )
+{
+    Vec_Wrd_t * vTruthsTemp, * vTruths;
+    int i, k, iObj, iNode;
+    word uTruth;
+    vTruths = Vec_WrdAlloc( Vec_IntSize(p->vUsed) );
+    vTruthsTemp = Vec_WrdStart( Gia_ManObjNum(p->pGia) );
+    Vec_IntForEachEntry( p->vUsed, iObj, i )
+    {
+        assert( Gia_ObjIsLut(p->pGia, iObj) );
+        // collect leaves of this gate  
+        Vec_IntClear( p->vLeaves );
+        Gia_LutForEachFanin( p->pGia, iObj, iNode, k )
+            Vec_IntPush( p->vLeaves, iNode );
+        assert( Vec_IntSize(p->vLeaves) <= 6 );
+        // compute truth table 
+        uTruth = Shr_ManComputeTruth6( p->pGia, Gia_ManObj(p->pGia, iObj), p->vLeaves, vTruthsTemp );
+        Vec_WrdPush( vTruths, uTruth );
+//        if ( i % 100 == 0 )
+//            Kit_DsdPrintFromTruth( (unsigned *)&uTruth, 6 ), printf( "\n" );
+    }
+    Vec_WrdFreeP( &vTruthsTemp );
+    return vTruths;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects decomposable pairs.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Unm_ManCollectDecomp( Unm_Man_t * p, Vec_Int_t * vPairs, int fVerbose )
+{
+    word uTruth; int nNonUnique = 0;
+    int i, k, j, s, iObj, iNode, iUsed, FanK, FanJ, Res, Num, nRefs;
+    Vec_Int_t * vNum2Obj = Vec_IntStart( 1 );
+    Vec_Int_t * vPairs2 = Vec_IntAlloc( 1000 );
+    assert( Hash_IntManEntryNum(p->pHash) == 0 );
+    for ( i = 0; i < Vec_IntSize(vPairs); i += 3 )
+    {
+        iObj = Vec_IntEntry( vPairs, i );
+        assert( Gia_ObjIsLut(p->pGia, iObj) );
+        // collect leaves of this gate  
+        Vec_IntClear( p->vLeaves );
+        Gia_LutForEachFanin( p->pGia, iObj, iNode, s )
+            Vec_IntPush( p->vLeaves, iNode );
+        assert( Vec_IntSize(p->vLeaves) <= 6 );
+        FanK = Vec_IntEntry(vPairs, i+1);
+        FanJ = Vec_IntEntry(vPairs, i+2);
+        k = Vec_IntFind( p->vLeaves, FanK );
+        j = Vec_IntFind( p->vLeaves, FanJ );
+        assert( FanK < FanJ );
+        iUsed = Vec_IntEntry( p->vId2Used, iObj );
+        uTruth = Vec_WrdEntry( p->vTruths, iUsed );
+        Res = Abc_TtCheckDsdAnd( uTruth, k, j, NULL );
+        if ( Res == -1 )
+            continue;
+        // derive literals
+        FanK = Abc_Var2Lit( FanK, ((Res >> 0) & 1) );
+        FanJ = Abc_Var2Lit( FanJ, ((Res >> 1) & 1) );
+        if ( Res == 4 )
+            ABC_SWAP( int, FanK, FanJ );
+        Num = Hash_Int2ManInsert( p->pHash, FanK, FanJ, 0 );
+        nRefs = Hash_Int2ObjInc(p->pHash, Num);
+        if ( nRefs == 0 )
+        {
+            assert( Num == Hash_IntManEntryNum(p->pHash) );
+            assert( Num == Vec_IntSize(vNum2Obj) );
+            Vec_IntPush( vNum2Obj, iObj );
+            continue;
+        }
+        if ( nRefs == 1 )
+        {
+            assert( Num < Vec_IntSize(vNum2Obj) );
+            Vec_IntPush( vPairs2, Vec_IntEntry(vNum2Obj, Num) );
+            Vec_IntPush( vPairs2, FanK );
+            Vec_IntPush( vPairs2, FanJ );
+            nNonUnique++;
+        }
+        Vec_IntPush( vPairs2, iObj );
+        Vec_IntPush( vPairs2, FanK );
+        Vec_IntPush( vPairs2, FanJ );
+    }
+    Vec_IntFree( vNum2Obj );
+    if ( fVerbose )
+        Unm_ManPrintPairStats( p->pHash, Vec_IntSize(vPairs)/3, Hash_IntManEntryNum(p->pHash), Vec_IntSize(vPairs2)/3, 1 );
+//    Hash_IntManStop( pHash );
+    return vPairs2;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute truth tables for the selected nodes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Unm_ManWork( Unm_Man_t * p )
+{
+    Vec_Int_t * vPairs, * vPairs2;
+    // find the duplicated pairs
+    vPairs = Unm_ManComputePairs( p, 1 );
+    // find the used nodes
+    p->vUsed = Unm_ManFindUsedNodes( vPairs, Gia_ManObjNum(p->pGia) );
+    p->vId2Used = Vec_IntInvert( p->vUsed, -1 );
+    Vec_IntFillExtra( p->vId2Used, Gia_ManObjNum(p->pGia), -1 );
+    // compute truth tables for used nodes
+    p->vTruths = Unm_ManComputeTruths( p );
+    // derive new pairs
+    vPairs2 = Unm_ManCollectDecomp( p, vPairs, 1 );
+    Vec_IntFreeP( &vPairs );
+    Vec_IntFreeP( &vPairs2 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Unm_ManTest( Gia_Man_t * pGia )
+{
+    Unm_Man_t * p;
+    p = Unm_ManAlloc( pGia );
+    Unm_ManWork( p );
+
+    Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
+    return Unm_ManFree( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaSim.c b/abc-build/src/aig/gia/giaSim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaSim.c
@@ -0,0 +1,767 @@
+/**CFile****************************************************************
+
+  FileName    [giaSim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Fast sequential simulator.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Gia_ManSim_t_ Gia_ManSim_t;
+struct Gia_ManSim_t_
+{
+    Gia_Man_t *    pAig;
+    Gia_ParSim_t * pPars; 
+    int            nWords;
+    Vec_Int_t *    vCis2Ids;
+    Vec_Int_t *    vConsts;
+    // simulation information
+    unsigned *     pDataSim;     // simulation data
+    unsigned *     pDataSimCis;  // simulation data for CIs
+    unsigned *     pDataSimCos;  // simulation data for COs
+};
+
+static inline unsigned * Gia_SimData( Gia_ManSim_t * p, int i )    { return p->pDataSim + i * p->nWords;    }
+static inline unsigned * Gia_SimDataCi( Gia_ManSim_t * p, int i )  { return p->pDataSimCis + i * p->nWords; }
+static inline unsigned * Gia_SimDataCo( Gia_ManSim_t * p, int i )  { return p->pDataSimCos + i * p->nWords; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSimCollect_rec( Gia_Man_t * pGia, Gia_Obj_t * pObj, Vec_Int_t * vVec )
+{
+    Vec_IntPush( vVec, Gia_ObjToLit(pGia, pObj) );
+    if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManSimCollect_rec( pGia, Gia_ObjChild0(pObj), vVec );
+    Gia_ManSimCollect_rec( pGia, Gia_ObjChild1(pObj), vVec );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives signal implications.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSimCollect( Gia_Man_t * pGia, Gia_Obj_t * pObj, Vec_Int_t * vVec )
+{
+    Vec_IntClear( vVec );
+    Gia_ManSimCollect_rec( pGia, pObj, vVec );
+    Vec_IntUniqify( vVec );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds signals, which reset flops to have constant values.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManSimDeriveResets( Gia_Man_t * pGia )
+{
+    int nImpLimit = 5;
+    Vec_Int_t * vResult;
+    Vec_Int_t * vCountLits, * vSuperGate;
+    Gia_Obj_t * pObj;
+    int i, k, Lit, Count;
+    int Counter0 = 0, Counter1 = 0;
+    int CounterPi0 = 0, CounterPi1 = 0;
+    abctime clk = Abc_Clock();
+
+    // create reset counters for each literal
+    vCountLits = Vec_IntStart( 2 * Gia_ManObjNum(pGia) );
+
+    // collect implications for each flop input driver
+    vSuperGate = Vec_IntAlloc( 1000 );
+    Gia_ManForEachRi( pGia, pObj, i )
+    {
+        if ( Gia_ObjFaninId0p(pGia, pObj) == 0 )
+            continue;
+        Vec_IntAddToEntry( vCountLits, Gia_ObjToLit(pGia, Gia_ObjChild0(pObj)), 1 );
+        Gia_ManSimCollect( pGia, Gia_ObjFanin0(pObj), vSuperGate );
+        Vec_IntForEachEntry( vSuperGate, Lit, k )
+            Vec_IntAddToEntry( vCountLits, Lit, 1 );
+    }
+    Vec_IntFree( vSuperGate );
+
+    // label signals whose counter if more than the limit
+    vResult = Vec_IntStartFull( Gia_ManObjNum(pGia) );
+    Vec_IntForEachEntry( vCountLits, Count, Lit )
+    {
+        if ( Count < nImpLimit )
+            continue;
+        pObj = Gia_ManObj( pGia, Abc_Lit2Var(Lit) );
+        if ( Abc_LitIsCompl(Lit) ) // const 0
+        {
+//            Ssm_ObjSetLogic0( pObj );
+            Vec_IntWriteEntry( vResult, Abc_Lit2Var(Lit), 0 );
+            CounterPi0 += Gia_ObjIsPi(pGia, pObj);
+            Counter0++;
+        }
+        else
+        {
+//            Ssm_ObjSetLogic1( pObj );
+            Vec_IntWriteEntry( vResult, Abc_Lit2Var(Lit), 1 );
+            CounterPi1 += Gia_ObjIsPi(pGia, pObj);
+            Counter1++;
+        }
+//        if ( Gia_ObjIsPi(pGia, pObj) )
+//            printf( "%d ", Count );
+    }
+//    printf( "\n" );
+    Vec_IntFree( vCountLits );
+
+    printf( "Logic0 = %d (%d). Logic1 = %d (%d). ", Counter0, CounterPi0, Counter1, CounterPi1 );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return vResult;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSimSetDefaultParams( Gia_ParSim_t * p )
+{
+    memset( p, 0, sizeof(Gia_ParSim_t) );
+    // user-controlled parameters
+    p->nWords       =   8;    // the number of machine words
+    p->nIters       =  32;    // the number of timeframes
+    p->RandSeed     =   0;    // the seed to generate random numbers
+    p->TimeLimit    =  60;    // time limit in seconds
+    p->fCheckMiter  =   0;    // check if miter outputs are non-zero 
+    p->fVerbose     =   0;    // enables verbose output
+    p->iOutFail     =  -1;    // index of the failed output
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSimDelete( Gia_ManSim_t * p )
+{
+    Vec_IntFreeP( &p->vConsts );
+    Vec_IntFreeP( &p->vCis2Ids );
+    Gia_ManStopP( &p->pAig );
+    ABC_FREE( p->pDataSim );
+    ABC_FREE( p->pDataSimCis );
+    ABC_FREE( p->pDataSimCos );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates fast simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_ManSim_t * Gia_ManSimCreate( Gia_Man_t * pAig, Gia_ParSim_t * pPars )
+{
+    Gia_ManSim_t * p;
+    int Entry, i;
+    p = ABC_ALLOC( Gia_ManSim_t, 1 );
+    memset( p, 0, sizeof(Gia_ManSim_t) );
+    // look for reset signals
+    if ( pPars->fVerbose )
+        p->vConsts = Gia_ManSimDeriveResets( pAig );
+    // derive the frontier
+    p->pAig   = Gia_ManFront( pAig );
+    p->pPars  = pPars;
+    p->nWords = pPars->nWords;
+    p->pDataSim = ABC_ALLOC( unsigned, p->nWords * p->pAig->nFront );
+    p->pDataSimCis = ABC_ALLOC( unsigned, p->nWords * Gia_ManCiNum(p->pAig) );
+    p->pDataSimCos = ABC_ALLOC( unsigned, p->nWords * Gia_ManCoNum(p->pAig) );
+    if ( !p->pDataSim || !p->pDataSimCis || !p->pDataSimCos )
+    { 
+        Abc_Print( 1, "Simulator could not allocate %.2f GB for simulation info.\n", 
+            4.0 * p->nWords * (p->pAig->nFront + Gia_ManCiNum(p->pAig) + Gia_ManCoNum(p->pAig)) / (1<<30) );
+        Gia_ManSimDelete( p );
+        return NULL;
+    }
+    p->vCis2Ids = Vec_IntAlloc( Gia_ManCiNum(p->pAig) );
+    Vec_IntForEachEntry( pAig->vCis, Entry, i )
+        Vec_IntPush( p->vCis2Ids, i );  //  do we need p->vCis2Ids?
+    if ( pPars->fVerbose )
+    Abc_Print( 1, "AIG = %7.2f MB.   Front mem = %7.2f MB.  Other mem = %7.2f MB.\n", 
+        12.0*Gia_ManObjNum(p->pAig)/(1<<20), 
+        4.0*p->nWords*p->pAig->nFront/(1<<20), 
+        4.0*p->nWords*(Gia_ManCiNum(p->pAig) + Gia_ManCoNum(p->pAig))/(1<<20) );
+
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSimInfoRandom( Gia_ManSim_t * p, unsigned * pInfo )
+{
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = Gia_ManRandom( 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSimInfoZero( Gia_ManSim_t * p, unsigned * pInfo )
+{
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns index of the first pattern that failed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManSimInfoIsZero( Gia_ManSim_t * p, unsigned * pInfo )
+{
+    int w;
+    for ( w = 0; w < p->nWords; w++ )
+        if ( pInfo[w] )
+            return 32*w + Gia_WordFindFirstBit( pInfo[w] );
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSimInfoOne( Gia_ManSim_t * p, unsigned * pInfo )
+{
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = ~0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSimInfoCopy( Gia_ManSim_t * p, unsigned * pInfo, unsigned * pInfo0 )
+{
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSimulateCi( Gia_ManSim_t * p, Gia_Obj_t * pObj, int iCi )
+{
+    unsigned * pInfo  = Gia_SimData( p, Gia_ObjValue(pObj) );
+    unsigned * pInfo0 = Gia_SimDataCi( p, iCi );
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSimulateCo( Gia_ManSim_t * p, int iCo, Gia_Obj_t * pObj )
+{
+    unsigned * pInfo  = Gia_SimDataCo( p, iCo );
+    unsigned * pInfo0 = Gia_SimData( p, Gia_ObjDiff0(pObj) );
+    int w;
+    if ( Gia_ObjFaninC0(pObj) )
+        for ( w = p->nWords-1; w >= 0; w-- )
+            pInfo[w] = ~pInfo0[w];
+    else 
+        for ( w = p->nWords-1; w >= 0; w-- )
+            pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSimulateNode( Gia_ManSim_t * p, Gia_Obj_t * pObj )
+{
+    unsigned * pInfo  = Gia_SimData( p, Gia_ObjValue(pObj) );
+    unsigned * pInfo0 = Gia_SimData( p, Gia_ObjDiff0(pObj) );
+    unsigned * pInfo1 = Gia_SimData( p, Gia_ObjDiff1(pObj) );
+    int w;
+    if ( Gia_ObjFaninC0(pObj) )
+    {
+        if (  Gia_ObjFaninC1(pObj) )
+            for ( w = p->nWords-1; w >= 0; w-- )
+                pInfo[w] = ~(pInfo0[w] | pInfo1[w]);
+        else 
+            for ( w = p->nWords-1; w >= 0; w-- )
+                pInfo[w] = ~pInfo0[w] & pInfo1[w];
+    }
+    else 
+    {
+        if (  Gia_ObjFaninC1(pObj) )
+            for ( w = p->nWords-1; w >= 0; w-- )
+                pInfo[w] = pInfo0[w] & ~pInfo1[w];
+        else 
+            for ( w = p->nWords-1; w >= 0; w-- )
+                pInfo[w] = pInfo0[w] & pInfo1[w];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSimInfoInit( Gia_ManSim_t * p )
+{
+    int iPioNum, i;
+    Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i )
+    {
+        if ( iPioNum < Gia_ManPiNum(p->pAig) )
+            Gia_ManSimInfoRandom( p, Gia_SimDataCi(p, i) );
+        else
+            Gia_ManSimInfoZero( p, Gia_SimDataCi(p, i) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSimInfoTransfer( Gia_ManSim_t * p )
+{
+    int iPioNum, i;
+    Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i )
+    {
+        if ( iPioNum < Gia_ManPiNum(p->pAig) )
+            Gia_ManSimInfoRandom( p, Gia_SimDataCi(p, i) );
+        else
+            Gia_ManSimInfoCopy( p, Gia_SimDataCi(p, i), Gia_SimDataCo(p, Gia_ManPoNum(p->pAig)+iPioNum-Gia_ManPiNum(p->pAig)) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSimulateRound( Gia_ManSim_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, iCis = 0, iCos = 0;
+    assert( p->pAig->nFront > 0 );
+    assert( Gia_ManConst0(p->pAig)->Value == 0 );
+    Gia_ManSimInfoZero( p, Gia_SimData(p, 0) );
+    Gia_ManForEachObj1( p->pAig, pObj, i )
+    {
+        if ( Gia_ObjIsAndOrConst0(pObj) )
+        {
+            assert( Gia_ObjValue(pObj) < p->pAig->nFront );
+            Gia_ManSimulateNode( p, pObj );
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+        {
+            assert( Gia_ObjValue(pObj) == GIA_NONE );
+            Gia_ManSimulateCo( p, iCos++, pObj );
+        }
+        else // if ( Gia_ObjIsCi(pObj) )
+        {
+            assert( Gia_ObjValue(pObj) < p->pAig->nFront );
+            Gia_ManSimulateCi( p, pObj, iCis++ );
+        }
+    }
+    assert( Gia_ManCiNum(p->pAig) == iCis );
+    assert( Gia_ManCoNum(p->pAig) == iCos );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns index of the PO and pattern that failed it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManCheckPos( Gia_ManSim_t * p, int * piPo, int * piPat )
+{
+    int i, iPat;
+    for ( i = 0; i < Gia_ManPoNum(p->pAig); i++ )
+    {
+        iPat = Gia_ManSimInfoIsZero( p, Gia_SimDataCo(p, i) );
+        if ( iPat >= 0 )
+        {
+            *piPo = i;
+            *piPat = iPat;
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Gia_ManGenerateCounter( Gia_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat, Vec_Int_t * vCis2Ids )
+{
+    Abc_Cex_t * p;
+    unsigned * pData;
+    int f, i, w, iPioId, Counter;
+    p = Abc_CexAlloc( Gia_ManRegNum(pAig), Gia_ManPiNum(pAig), iFrame+1 );
+    p->iFrame = iFrame;
+    p->iPo    = iOut;
+    // fill in the binary data
+    Counter = p->nRegs;
+    pData = ABC_ALLOC( unsigned, nWords );
+    for ( f = 0; f <= iFrame; f++, Counter += p->nPis )
+    for ( i = 0; i < Gia_ManPiNum(pAig); i++ )
+    {
+        iPioId = Vec_IntEntry( vCis2Ids, i );
+        if ( iPioId >= p->nPis )
+            continue;
+        for ( w = nWords-1; w >= 0; w-- )
+            pData[w] = Gia_ManRandom( 0 );
+        if ( Abc_InfoHasBit( pData, iPat ) )
+            Abc_InfoSetBit( p->pData, Counter + iPioId );
+    }
+    ABC_FREE( pData );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManResetRandom( Gia_ParSim_t * pPars )
+{
+    int i;
+    Gia_ManRandom( 1 );
+    for ( i = 0; i < pPars->RandSeed; i++ )
+        Gia_ManRandom( 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManSimSimulate( Gia_Man_t * pAig, Gia_ParSim_t * pPars )
+{
+    extern int Gia_ManSimSimulateEquiv( Gia_Man_t * pAig, Gia_ParSim_t * pPars );
+    Gia_ManSim_t * p;
+    abctime clkTotal = Abc_Clock();
+    int i, iOut, iPat, RetValue = 0;
+    abctime nTimeToStop = pPars->TimeLimit ? pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0;
+    if ( pAig->pReprs && pAig->pNexts )
+        return Gia_ManSimSimulateEquiv( pAig, pPars );
+    ABC_FREE( pAig->pCexSeq );
+    p = Gia_ManSimCreate( pAig, pPars );
+    Gia_ManResetRandom( pPars );
+    Gia_ManSimInfoInit( p );
+    for ( i = 0; i < pPars->nIters; i++ )
+    {
+        Gia_ManSimulateRound( p );
+        if ( pPars->fVerbose )
+        {
+            Abc_Print( 1, "Frame %4d out of %4d and timeout %3d sec. ", i+1, pPars->nIters, pPars->TimeLimit );
+            Abc_Print( 1, "Time = %7.2f sec\r", (1.0*Abc_Clock()-clkTotal)/CLOCKS_PER_SEC );
+        }
+        if ( pPars->fCheckMiter && Gia_ManCheckPos( p, &iOut, &iPat ) )
+        {
+            Gia_ManResetRandom( pPars );
+            pPars->iOutFail = iOut;
+            pAig->pCexSeq = Gia_ManGenerateCounter( pAig, i, iOut, p->nWords, iPat, p->vCis2Ids );
+            Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.  ", iOut, pAig->pName, i );
+            if ( !Gia_ManVerifyCex( pAig, pAig->pCexSeq, 0 ) )
+            {
+//                Abc_Print( 1, "\n" );
+                Abc_Print( 1, "\nGenerated counter-example is INVALID.                    " );
+//                Abc_Print( 1, "\n" );
+            }
+            else
+            {
+//                Abc_Print( 1, "\n" );
+//                if ( pPars->fVerbose )
+//                Abc_Print( 1, "\nGenerated counter-example is verified correctly.         " );
+//                Abc_Print( 1, "\n" );
+            }
+            RetValue = 1;
+            break;
+        }
+        if ( Abc_Clock() > nTimeToStop )
+        {
+            i++;
+            break;
+        }
+        if ( i < pPars->nIters - 1 )
+            Gia_ManSimInfoTransfer( p );
+    }
+    Gia_ManSimDelete( p );
+    if ( pAig->pCexSeq == NULL )
+        Abc_Print( 1, "No bug detected after simulating %d frames with %d words.  ", i, pPars->nWords );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManSimReadFile( char * pFileIn )
+{
+    int c;
+    Vec_Int_t * vPat;
+    FILE * pFile = fopen( pFileIn, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open input file.\n" );
+        return NULL;
+    }
+    vPat = Vec_IntAlloc( 1000 );
+    while ( (c = fgetc(pFile)) != EOF )
+        if ( c == '0' || c == '1' )
+            Vec_IntPush( vPat, c - '0' );
+    fclose( pFile );
+    return vPat;
+}
+int Gia_ManSimWriteFile( char * pFileOut, Vec_Int_t * vPat, int nOuts )
+{
+    int c, i;
+    FILE * pFile = fopen( pFileOut, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open output file.\n" );
+        return 0;
+    }
+    assert( Vec_IntSize(vPat) % nOuts == 0 );
+    Vec_IntForEachEntry( vPat, c, i )
+    {
+        fputc( '0' + c, pFile );
+        if ( i % nOuts == nOuts - 1 )
+            fputc( '\n', pFile );
+    }
+    fclose( pFile );
+    return 1;
+}
+Vec_Int_t * Gia_ManSimSimulateOne( Gia_Man_t * p, Vec_Int_t * vPat )
+{
+    Vec_Int_t * vPatOut;
+    Gia_Obj_t * pObj, * pObjRo;
+    int i, k, f;
+    assert( Vec_IntSize(vPat) % Gia_ManPiNum(p) == 0 );
+    Gia_ManConst0(p)->fMark1 = 0;
+    Gia_ManForEachRo( p, pObj, i )
+        pObj->fMark1 = 0;
+    vPatOut = Vec_IntAlloc( 1000 );
+    for ( k = f = 0; f < Vec_IntSize(vPat) / Gia_ManPiNum(p); f++ )
+    {
+        Gia_ManForEachPi( p, pObj, i )
+            pObj->fMark1 = Vec_IntEntry( vPat, k++ );
+        Gia_ManForEachAnd( p, pObj, i )
+            pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj));
+        Gia_ManForEachCo( p, pObj, i )
+            pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj));
+        Gia_ManForEachPo( p, pObj, i )
+            Vec_IntPush( vPatOut, pObj->fMark1 );
+        Gia_ManForEachRiRo( p, pObj, pObjRo, i )
+            pObjRo->fMark1 = pObj->fMark1;
+    }
+    assert( k == Vec_IntSize(vPat) );
+    Gia_ManForEachObj( p, pObj, i )
+        pObj->fMark1 = 0;
+    return vPatOut;
+}
+void Gia_ManSimSimulatePattern( Gia_Man_t * p, char * pFileIn, char * pFileOut )
+{
+    Vec_Int_t * vPat, * vPatOut;
+    vPat = Gia_ManSimReadFile( pFileIn );
+    if ( vPat == NULL )
+        return;
+    if ( Vec_IntSize(vPat) % Gia_ManPiNum(p) )
+    {
+        printf( "The number of 0s and 1s in the input file (%d) does not evenly divide by the number of primary inputs (%d).\n", 
+            Vec_IntSize(vPat), Gia_ManPiNum(p) );
+        Vec_IntFree( vPat );
+        return;
+    }
+    vPatOut = Gia_ManSimSimulateOne( p, vPat );
+    if ( Gia_ManSimWriteFile( pFileOut, vPatOut, Gia_ManPoNum(p) ) )
+        printf( "Output patterns are written into file \"%s\".\n", pFileOut );
+    Vec_IntFree( vPat );
+    Vec_IntFree( vPatOut );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaSim2.c b/abc-build/src/aig/gia/giaSim2.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaSim2.c
@@ -0,0 +1,706 @@
+/**CFile****************************************************************
+
+  FileName    [giaSim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Fast sequential simulator.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Gia_Sim2_t_ Gia_Sim2_t;
+struct Gia_Sim2_t_
+{
+    Gia_Man_t *    pAig;
+    Gia_ParSim_t * pPars; 
+    int            nWords;
+    unsigned *     pDataSim; 
+    Vec_Int_t *    vClassOld;
+    Vec_Int_t *    vClassNew;
+};
+
+static inline unsigned * Gia_Sim2Data( Gia_Sim2_t * p, int i )    { return p->pDataSim + i * p->nWords;    }
+
+extern void Gia_ManResetRandom( Gia_ParSim_t * pPars );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_Sim2Delete( Gia_Sim2_t * p )
+{
+    Vec_IntFreeP( &p->vClassOld );
+    Vec_IntFreeP( &p->vClassNew );
+    ABC_FREE( p->pDataSim );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates fast simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Sim2_t * Gia_Sim2Create( Gia_Man_t * pAig, Gia_ParSim_t * pPars )
+{
+    Gia_Sim2_t * p;
+    Gia_Obj_t * pObj;
+    int i;
+    p = ABC_CALLOC( Gia_Sim2_t, 1 );
+    p->pAig      = pAig;
+    p->pPars     = pPars;
+    p->nWords    = pPars->nWords;
+    p->pDataSim  = ABC_ALLOC( unsigned, p->nWords * Gia_ManObjNum(p->pAig) );
+    if ( !p->pDataSim  )
+    { 
+        Abc_Print( 1, "Simulator could not allocate %.2f GB for simulation info.\n", 
+            4.0 * p->nWords * Gia_ManObjNum(p->pAig) / (1<<30) );
+        Gia_Sim2Delete( p );
+        return NULL;
+    }
+    p->vClassOld = Vec_IntAlloc( 100 );
+    p->vClassNew = Vec_IntAlloc( 100 );
+    if ( pPars->fVerbose )
+        Abc_Print( 1, "Memory: AIG = %7.2f MB.  SimInfo = %7.2f MB.\n", 
+            12.0*Gia_ManObjNum(p->pAig)/(1<<20), 4.0*p->nWords*Gia_ManObjNum(p->pAig)/(1<<20) );
+    // prepare AIG
+    Gia_ManSetPhase( pAig );
+    Gia_ManForEachObj( pAig, pObj, i )
+        pObj->Value = i;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_Sim2InfoRandom( Gia_Sim2_t * p, unsigned * pInfo )
+{
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = Gia_ManRandom( 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_Sim2InfoZero( Gia_Sim2_t * p, unsigned * pInfo )
+{
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_Sim2InfoOne( Gia_Sim2_t * p, unsigned * pInfo )
+{
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = ~0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_Sim2InfoCopy( Gia_Sim2_t * p, unsigned * pInfo, unsigned * pInfo0 )
+{
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_Sim2SimulateCo( Gia_Sim2_t * p, Gia_Obj_t * pObj )
+{
+    unsigned * pInfo  = Gia_Sim2Data( p, Gia_ObjValue(pObj) );
+    unsigned * pInfo0 = Gia_Sim2Data( p, Gia_ObjFaninId0(pObj, Gia_ObjValue(pObj)) );
+    int w;
+    if ( Gia_ObjFaninC0(pObj) )
+        for ( w = p->nWords-1; w >= 0; w-- )
+            pInfo[w] = ~pInfo0[w];
+    else 
+        for ( w = p->nWords-1; w >= 0; w-- )
+            pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_Sim2SimulateNode( Gia_Sim2_t * p, Gia_Obj_t * pObj )
+{
+    unsigned * pInfo  = Gia_Sim2Data( p, Gia_ObjValue(pObj) );
+    unsigned * pInfo0 = Gia_Sim2Data( p, Gia_ObjFaninId0(pObj, Gia_ObjValue(pObj)) );
+    unsigned * pInfo1 = Gia_Sim2Data( p, Gia_ObjFaninId1(pObj, Gia_ObjValue(pObj)) );
+    int w;
+    if ( Gia_ObjFaninC0(pObj) )
+    {
+        if (  Gia_ObjFaninC1(pObj) )
+            for ( w = p->nWords-1; w >= 0; w-- )
+                pInfo[w] = ~(pInfo0[w] | pInfo1[w]);
+        else 
+            for ( w = p->nWords-1; w >= 0; w-- )
+                pInfo[w] = ~pInfo0[w] & pInfo1[w];
+    }
+    else 
+    {
+        if (  Gia_ObjFaninC1(pObj) )
+            for ( w = p->nWords-1; w >= 0; w-- )
+                pInfo[w] = pInfo0[w] & ~pInfo1[w];
+        else 
+            for ( w = p->nWords-1; w >= 0; w-- )
+                pInfo[w] = pInfo0[w] & pInfo1[w];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_Sim2InfoTransfer( Gia_Sim2_t * p )
+{
+    Gia_Obj_t * pObjRo, * pObjRi;
+    unsigned * pInfo0, * pInfo1;
+    int i;
+    Gia_ManForEachRiRo( p->pAig, pObjRi, pObjRo, i )
+    {
+        pInfo0 = Gia_Sim2Data( p, Gia_ObjValue(pObjRo) );
+        pInfo1 = Gia_Sim2Data( p, Gia_ObjValue(pObjRi) );
+        Gia_Sim2InfoCopy( p, pInfo0, pInfo1 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_Sim2SimulateRound( Gia_Sim2_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    pObj = Gia_ManConst0(p->pAig);
+    assert( Gia_ObjValue(pObj) == 0 );
+    Gia_Sim2InfoZero( p, Gia_Sim2Data(p, Gia_ObjValue(pObj)) );
+    Gia_ManForEachPi( p->pAig, pObj, i )
+        Gia_Sim2InfoRandom( p, Gia_Sim2Data(p, Gia_ObjValue(pObj)) );
+    Gia_ManForEachAnd( p->pAig, pObj, i )
+    {
+        assert( Gia_ObjValue(pObj) == i );
+        Gia_Sim2SimulateNode( p, pObj );
+    }
+    Gia_ManForEachCo( p->pAig, pObj, i )
+        Gia_Sim2SimulateCo( p, pObj );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compares simulation info of two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_Sim2CompareEqual( unsigned * p0, unsigned * p1, int nWords, int fCompl )
+{
+    int w;
+    if ( !fCompl )
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( p0[w] != p1[w] )
+                return 0;
+        return 1;
+    }
+    else
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( p0[w] != ~p1[w] )
+                return 0;
+        return 1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares simulation info of one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_Sim2CompareZero( unsigned * p0, int nWords, int fCompl )
+{
+    int w;
+    if ( !fCompl )
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( p0[w] != 0 )
+                return 0;
+        return 1;
+    }
+    else
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( p0[w] != ~0 )
+                return 0;
+        return 1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates equivalence class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_Sim2ClassCreate( Gia_Man_t * p, Vec_Int_t * vClass )
+{
+    int Repr = GIA_VOID, EntPrev = -1, Ent, i;
+    assert( Vec_IntSize(vClass) > 0 );
+    Vec_IntForEachEntry( vClass, Ent, i )
+    {
+        if ( i == 0 )
+        {
+            Repr = Ent;
+            Gia_ObjSetRepr( p, Ent, GIA_VOID );
+            EntPrev = Ent;
+        }
+        else
+        {
+            assert( Repr < Ent );
+            Gia_ObjSetRepr( p, Ent, Repr );
+            Gia_ObjSetNext( p, EntPrev, Ent );
+            EntPrev = Ent;
+        }
+    }
+    Gia_ObjSetNext( p, EntPrev, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines one equivalence class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_Sim2ClassRefineOne( Gia_Sim2_t * p, int i )
+{
+    Gia_Obj_t * pObj0, * pObj1;
+    unsigned * pSim0, * pSim1;
+    int Ent;
+    Vec_IntClear( p->vClassOld );
+    Vec_IntClear( p->vClassNew );
+    Vec_IntPush( p->vClassOld, i );
+    pObj0 = Gia_ManObj( p->pAig, i );
+    pSim0 = Gia_Sim2Data( p, i );
+    Gia_ClassForEachObj1( p->pAig, i, Ent )
+    {
+        pObj1 = Gia_ManObj( p->pAig, Ent );
+        pSim1 = Gia_Sim2Data( p, Ent );
+        if ( Gia_Sim2CompareEqual( pSim0, pSim1, p->nWords, Gia_ObjPhase(pObj0) ^ Gia_ObjPhase(pObj1) ) )
+            Vec_IntPush( p->vClassOld, Ent );
+        else
+            Vec_IntPush( p->vClassNew, Ent );
+    }
+    if ( Vec_IntSize( p->vClassNew ) == 0 )
+        return 0;
+    Gia_Sim2ClassCreate( p->pAig, p->vClassOld );
+    Gia_Sim2ClassCreate( p->pAig, p->vClassNew );
+    if ( Vec_IntSize(p->vClassNew) > 1 )
+        return 1 + Gia_Sim2ClassRefineOne( p, Vec_IntEntry(p->vClassNew,0) );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash key of the simuation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_Sim2HashKey( unsigned * pSim, int nWords, int nTableSize )
+{
+    static int s_Primes[16] = { 
+        1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, 
+        4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 };
+    unsigned uHash = 0;
+    int i;
+    if ( pSim[0] & 1 )
+        for ( i = 0; i < nWords; i++ )
+            uHash ^= ~pSim[i] * s_Primes[i & 0xf];
+    else
+        for ( i = 0; i < nWords; i++ )
+            uHash ^= pSim[i] * s_Primes[i & 0xf];
+    return (int)(uHash % nTableSize);
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines nodes belonging to candidate constant class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_Sim2ProcessRefined( Gia_Sim2_t * p, Vec_Int_t * vRefined )
+{
+    unsigned * pSim;
+    int * pTable, nTableSize, i, k, Key;
+    if ( Vec_IntSize(vRefined) == 0 )
+        return;
+    nTableSize = Abc_PrimeCudd( 1000 + Vec_IntSize(vRefined) / 3 );
+    pTable = ABC_CALLOC( int, nTableSize );
+    Vec_IntForEachEntry( vRefined, i, k )
+    {
+        pSim = Gia_Sim2Data( p, i );
+        Key = Gia_Sim2HashKey( pSim, p->nWords, nTableSize );
+        if ( pTable[Key] == 0 )
+        {
+            assert( Gia_ObjRepr(p->pAig, i) == 0 );
+            assert( Gia_ObjNext(p->pAig, i) == 0 );
+            Gia_ObjSetRepr( p->pAig, i, GIA_VOID );
+        }
+        else
+        {
+            Gia_ObjSetNext( p->pAig, pTable[Key], i );
+            Gia_ObjSetRepr( p->pAig, i, Gia_ObjRepr(p->pAig, pTable[Key]) );
+            if ( Gia_ObjRepr(p->pAig, i) == GIA_VOID )
+                Gia_ObjSetRepr( p->pAig, i, pTable[Key] );
+            assert( Gia_ObjRepr(p->pAig, i) > 0 );
+        }
+        pTable[Key] = i;
+    }
+/*
+    Vec_IntForEachEntry( vRefined, i, k )
+    {
+        if ( Gia_ObjIsHead( p->pAig, i ) )
+            Gia_Sim2ClassRefineOne( p, i );
+    }
+*/
+    ABC_FREE( pTable );
+}
+/**Function*************************************************************
+
+  Synopsis    [Refines equivalences after one simulation round.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_Sim2InfoRefineEquivs( Gia_Sim2_t * p )
+{
+    Vec_Int_t * vRefined;
+    Gia_Obj_t * pObj;
+    unsigned * pSim;
+    int i, Count = 0;
+    // process constant candidates
+    vRefined = Vec_IntAlloc( 100 );
+    Gia_ManForEachObj1( p->pAig, pObj, i )
+    {
+        if ( !Gia_ObjIsConst(p->pAig, i) )
+            continue;
+        pSim = Gia_Sim2Data( p, i );
+//Extra_PrintBinary( stdout, pSim, 32 * p->nWords );  printf( "\n" );
+        if ( !Gia_Sim2CompareZero( pSim, p->nWords, Gia_ObjPhase(pObj) ) )
+        {
+            Vec_IntPush( vRefined, i );
+            Count++;
+        }
+    }
+    Gia_Sim2ProcessRefined( p, vRefined );
+    Vec_IntFree( vRefined );
+    // process other classes
+    Gia_ManForEachClass( p->pAig, i )
+        Count += Gia_Sim2ClassRefineOne( p, i );
+//    if ( Count )
+//        printf( "Refined %d times.\n", Count );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns index of the first pattern that failed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_Sim2InfoIsZero( Gia_Sim2_t * p, unsigned * pInfo )
+{
+    int w;
+    for ( w = 0; w < p->nWords; w++ )
+        if ( pInfo[w] )
+            return 32*w + Gia_WordFindFirstBit( pInfo[w] );
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns index of the PO and pattern that failed it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_Sim2CheckPos( Gia_Sim2_t * p, int * piPo, int * piPat )
+{
+    Gia_Obj_t * pObj;
+    int i, iPat;
+    Gia_ManForEachPo( p->pAig, pObj, i )
+    {
+        iPat = Gia_Sim2InfoIsZero( p, Gia_Sim2Data( p, Gia_ObjValue(pObj) ) );
+        if ( iPat >= 0 )
+        {
+            *piPo = i;
+            *piPat = iPat;
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Gia_Sim2GenerateCounter( Gia_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat )
+{
+    Abc_Cex_t * p;
+    unsigned * pData;
+    int f, i, w, Counter;
+    p = Abc_CexAlloc( Gia_ManRegNum(pAig), Gia_ManPiNum(pAig), iFrame+1 );
+    p->iFrame = iFrame;
+    p->iPo = iOut;
+    // fill in the binary data
+    Counter = p->nRegs;
+    pData = ABC_ALLOC( unsigned, nWords );
+    for ( f = 0; f <= iFrame; f++, Counter += p->nPis )
+    for ( i = 0; i < Gia_ManPiNum(pAig); i++ )
+    {
+        for ( w = nWords-1; w >= 0; w-- )
+            pData[w] = Gia_ManRandom( 0 );
+        if ( Abc_InfoHasBit( pData, iPat ) )
+            Abc_InfoSetBit( p->pData, Counter + i );
+    }
+    ABC_FREE( pData );
+    return p;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Performs simulation to refine equivalence classes.]
+
+  Description [Returns 1 if counter-example is detected.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManSimSimulateEquiv( Gia_Man_t * pAig, Gia_ParSim_t * pPars )
+{
+    Gia_Sim2_t * p;
+    Gia_Obj_t * pObj;
+    abctime clkTotal = Abc_Clock();
+    int i, RetValue = 0, iOut, iPat;
+    abctime nTimeToStop = pPars->TimeLimit ? pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0;
+    assert( pAig->pReprs && pAig->pNexts );
+    ABC_FREE( pAig->pCexSeq );
+    p = Gia_Sim2Create( pAig, pPars );
+    Gia_ManResetRandom( pPars );
+    Gia_ManForEachRo( p->pAig, pObj, i )
+        Gia_Sim2InfoZero( p, Gia_Sim2Data(p, Gia_ObjValue(pObj)) );
+    for ( i = 0; i < pPars->nIters; i++ )
+    {
+        Gia_Sim2SimulateRound( p );
+        if ( pPars->fVerbose )
+        {
+            Abc_Print( 1, "Frame %4d out of %4d and timeout %3d sec. ", i+1, pPars->nIters, pPars->TimeLimit );
+            if ( pAig->pReprs && pAig->pNexts )
+                Abc_Print( 1, "Lits = %4d. ", Gia_ManEquivCountLitsAll(pAig) );
+            Abc_Print( 1, "Time = %7.2f sec\r", (1.0*Abc_Clock()-clkTotal)/CLOCKS_PER_SEC );
+        }
+        if ( pPars->fCheckMiter && Gia_Sim2CheckPos( p, &iOut, &iPat ) )
+        {
+            Gia_ManResetRandom( pPars );
+            pPars->iOutFail = iOut;
+            pAig->pCexSeq = Gia_Sim2GenerateCounter( pAig, i, iOut, p->nWords, iPat );
+            Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.  ", iOut, pAig->pName, i );
+            if ( !Gia_ManVerifyCex( pAig, pAig->pCexSeq, 0 ) )
+            {
+//                Abc_Print( 1, "\n" );
+                Abc_Print( 1, "\nGenerated counter-example is INVALID.                    " );
+//                Abc_Print( 1, "\n" );
+            }
+            else
+            {
+//                Abc_Print( 1, "\n" );
+//                if ( pPars->fVerbose )
+//                Abc_Print( 1, "\nGenerated counter-example is verified correctly.         " );
+//                Abc_Print( 1, "\n" );
+            }
+            RetValue = 1;
+            break;
+        }
+        if ( pAig->pReprs && pAig->pNexts )
+            Gia_Sim2InfoRefineEquivs( p );
+        if ( Abc_Clock() > nTimeToStop )
+        {
+            i++;
+            break;
+        }
+        if ( i < pPars->nIters - 1 )
+            Gia_Sim2InfoTransfer( p );
+    }
+    Gia_Sim2Delete( p );
+    if ( pAig->pCexSeq == NULL )
+        Abc_Print( 1, "No bug detected after simulating %d frames with %d words.  ", i, pPars->nWords );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaSopb.c b/abc-build/src/aig/gia/giaSopb.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaSopb.c
@@ -0,0 +1,230 @@
+/**CFile****************************************************************
+
+  FileName    [giaSopb.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [SOP balancing for a window.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaSopb.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManHighlight_rec( Gia_Man_t * p, int iObj )
+{
+    Gia_Obj_t * pObj;
+    if ( Gia_ObjIsTravIdCurrentId(p, iObj) )
+        return;
+    Gia_ObjSetTravIdCurrentId(p, iObj);
+    pObj = Gia_ManObj( p, iObj );
+    if ( Gia_ObjIsAnd(pObj) )
+        Gia_ManHighlight_rec( p, Gia_ObjFaninId0(pObj, iObj) );
+    if ( Gia_ObjIsAnd(pObj) )
+        Gia_ManHighlight_rec( p, Gia_ObjFaninId1(pObj, iObj) );
+}
+void Gia_ManPrepareWin( Gia_Man_t * p, Vec_Int_t * vOuts, Vec_Int_t ** pvPis, Vec_Int_t ** pvPos, Vec_Int_t ** pvAnds )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    // mark the section
+    Gia_ManIncrementTravId( p );
+    Gia_ManForEachCoVec( vOuts, p, pObj, i )
+        Gia_ManHighlight_rec( p, Gia_ObjFaninId0p(p, pObj) );
+    // mark fanins of the outside area
+    Gia_ManCleanMark0( p );
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsCi(pObj) )
+            continue;
+        if ( Gia_ObjIsAnd(pObj) && !Gia_ObjIsTravIdCurrentId(p, i) )
+            continue;
+        Gia_ObjFanin0(pObj)->fMark0 = 1;
+        if ( Gia_ObjIsAnd(pObj) )
+            Gia_ObjFanin1(pObj)->fMark0 = 1;
+    }
+    // collect pointed nodes
+    *pvPis  = Vec_IntAlloc( 1000 );
+    *pvPos  = Vec_IntAlloc( 1000 );
+    *pvAnds = Vec_IntAlloc( 1000 );
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( !Gia_ObjIsTravIdCurrentId(p, i) )
+            continue;
+        if ( Gia_ObjIsCi(pObj) )
+            Vec_IntPush( *pvPis, i );
+        else if ( pObj->fMark0 )
+            Vec_IntPush( *pvPos, i );
+        if ( Gia_ObjIsAnd(pObj) )
+            Vec_IntPush( *pvAnds, i );
+    }
+    Gia_ManCleanMark0( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManExtractWin( Gia_Man_t * p, Vec_Int_t * vOuts )
+{
+    Vec_Int_t * vPis, * vPos, * vAnds;
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManPrepareWin( p, vOuts, &vPis, &vPos, &vAnds );
+    // create AIG
+    pNew = Gia_ManStart( Vec_IntSize(vPis) + Vec_IntSize(vPos) + Vec_IntSize(vAnds) + 1 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachObjVec( vPis, p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachObjVec( vAnds, p, pObj, i )
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachObjVec( vPos, p, pObj, i )
+        Gia_ManAppendCo( pNew, pObj->Value );
+    Vec_IntFree( vPis );
+    Vec_IntFree( vPos );
+    Vec_IntFree( vAnds );
+    return pNew;
+}
+Gia_Man_t * Gia_ManInsertWin( Gia_Man_t * p, Vec_Int_t * vOuts, Gia_Man_t * pWin )
+{
+    Vec_Int_t * vPos, * vPis, * vAnds;
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManPrepareWin( p, vOuts, &vPis, &vPos, &vAnds );
+    // create AIG
+    pNew = Gia_ManStart( Gia_ManObjNum(p) - Vec_IntSize(vAnds) + Gia_ManAndNum(pWin) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // inputs
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManConst0(pWin)->Value = 0;
+    Gia_ManForEachCi( pWin, pObj, i )
+        pObj->Value = Gia_ManObj(p, Vec_IntEntry(vPis, i))->Value;
+    // internal nodes
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachAnd( pWin, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachCo( pWin, pObj, i )
+        Gia_ManObj( p, Vec_IntEntry(vPos, i) )->Value = Gia_ObjFanin0Copy(pObj);
+    Gia_ManForEachAnd( p, pObj, i )
+        if ( !Gia_ObjIsTravIdCurrentId(p, i) )
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManHashStop( pNew );
+    // cleanup
+    Vec_IntFree( vPis );
+    Vec_IntFree( vPos );
+    Vec_IntFree( vAnds );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManFindLatest( Gia_Man_t * p, int LevelMax )
+{
+    Vec_Int_t * vOuts;
+    Gia_Obj_t * pObj;
+    int i;
+    vOuts = Vec_IntAlloc( 1000 );
+    Gia_ManForEachCo( p, pObj, i )
+        if ( Gia_ObjLevel(p, pObj) > LevelMax )
+            Vec_IntPush( vOuts, i );
+    return vOuts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManPerformSopBalanceWin( Gia_Man_t * p, int LevelMax, int nLevelRatio, int nCutNum, int nRelaxRatio, int fVerbose )
+{
+    Vec_Int_t * vOuts;
+    Gia_Man_t * pNew, * pWin, * pWinNew;
+    int nLevels = Gia_ManLevelNum( p );
+    if ( nLevelRatio )
+        LevelMax = (int)((1.0 - 0.01 * nLevelRatio) * nLevels);
+//printf( "Using LevelMax = %d.\n", LevelMax );
+    vOuts = Gia_ManFindLatest( p, LevelMax );
+    if ( Vec_IntSize(vOuts) == 0 )
+    {
+        Vec_IntFree( vOuts );
+        return Gia_ManDup( p );
+    }
+    pWin = Gia_ManExtractWin( p, vOuts );
+    pWinNew = Gia_ManPerformSopBalance( pWin, nCutNum, nRelaxRatio, fVerbose );
+    Gia_ManStop( pWin );
+    pNew = Gia_ManInsertWin( p, vOuts, pWinNew );
+    Gia_ManStop( pWinNew );
+    Vec_IntFree( vOuts );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaSort.c b/abc-build/src/aig/gia/giaSort.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaSort.c
@@ -0,0 +1,273 @@
+/**CFile****************************************************************
+
+  FileName    [gia.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This is implementation of qsort in MiniSat.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int num_cmp1( int * x, int * y) { return ((*x) < (*y)) ? -1 : (((*x) > (*y)) ? 1 : 0); }
+static int num_cmp2( int * x, int * y) { return (*x) < (*y); }
+static inline void selectionsort(int* array, int size, int(*comp)(const void *, const void *))
+{
+    int     i, j, best_i;
+    int     tmp;
+    for (i = 0; i < size-1; i++){
+        best_i = i;
+        for (j = i+1; j < size; j++){
+            if (comp(array + j, array + best_i))
+                best_i = j;
+        }
+        tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp;
+    }
+}
+static void sort_rec(int* array, int size, int(*comp)(const void *, const void *))
+{
+    if (size <= 15)
+        selectionsort(array, size, comp);
+    else{
+        int    pivot = array[size/2];
+        int    tmp;
+        int    i = -1;
+        int    j = size;
+        for(;;){
+            do i++; while(comp(array + i, &pivot));
+            do j--; while(comp(&pivot, array + j));
+            if (i >= j) break;
+            tmp = array[i]; array[i] = array[j]; array[j] = tmp;
+        }
+        sort_rec(array    , i     , comp);
+        sort_rec(&array[i], size-i, comp);
+    }
+}
+void minisat_sort(int* array, int size, int(*comp)(const void *, const void *))
+{
+    sort_rec(array,size,comp);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [This is implementation of qsort in MiniSat.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void selectionsort2(int* array, int size)
+{
+    int     i, j, best_i;
+    int     tmp;
+    for (i = 0; i < size-1; i++){
+        best_i = i;
+        for (j = i+1; j < size; j++){
+            if (array[j] < array[best_i])
+                best_i = j;
+        }
+        tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp;
+    }
+}
+static void sort_rec2(int* array, int size)
+{
+    if (size <= 15)
+        selectionsort2(array, size);
+    else{
+        int    pivot = array[size/2];
+        int    tmp;
+        int    i = -1;
+        int    j = size;
+        for(;;){
+            do i++; while(array[i] < pivot);
+            do j--; while(pivot < array[j]);
+            if (i >= j) break;
+            tmp = array[i]; array[i] = array[j]; array[j] = tmp;
+        }
+        sort_rec2(array    , i     );
+        sort_rec2(&array[i], size-i);
+    }
+}
+void minisat_sort2(int* array, int size)
+{
+    sort_rec2(array,size);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This is implementation of qsort in MiniSat.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Gia_SortGetTest( int nSize )
+{
+    int i, * pArray;
+    srand( 0 );
+    pArray = ABC_ALLOC( int, nSize );
+    for ( i = 0; i < nSize; i++ )
+        pArray[i] = rand();
+    return pArray;
+}
+void Gia_SortVerifySorted( int * pArray, int nSize )
+{
+    int i;
+    for ( i = 1; i < nSize; i++ )
+        assert( pArray[i-1] <= pArray[i] );
+}
+void Gia_SortTest()
+{
+    int nSize = 100000000;
+    int * pArray;
+    abctime clk = Abc_Clock();
+
+    printf( "Sorting %d integers\n", nSize );
+    pArray = Gia_SortGetTest( nSize );
+clk = Abc_Clock();
+    qsort( pArray, nSize, 4, (int (*)(const void *, const void *)) num_cmp1 );
+ABC_PRT( "qsort  ", Abc_Clock() - clk );
+    Gia_SortVerifySorted( pArray, nSize );
+    ABC_FREE( pArray );
+
+    pArray = Gia_SortGetTest( nSize );
+clk = Abc_Clock();
+    minisat_sort( pArray, nSize, (int (*)(const void *, const void *)) num_cmp2 );
+ABC_PRT( "minisat", Abc_Clock() - clk );
+    Gia_SortVerifySorted( pArray, nSize );
+    ABC_FREE( pArray );
+
+    pArray = Gia_SortGetTest( nSize );
+clk = Abc_Clock();
+    minisat_sort2( pArray, nSize );
+ABC_PRT( "minisat with inlined comparison", Abc_Clock() - clk );
+    Gia_SortVerifySorted( pArray, nSize );
+    ABC_FREE( pArray );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This is implementation of qsort in MiniSat.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void selectionsort3(float* array, int* perm, int size)
+{
+    float   tmpf;
+    int     tmpi;
+    int     i, j, best_i;
+    for (i = 0; i < size-1; i++){
+        best_i = i;
+        for (j = i+1; j < size; j++){
+            if (array[j] < array[best_i])
+                best_i = j;
+        }
+        tmpf = array[i]; array[i] = array[best_i]; array[best_i] = tmpf;
+        tmpi = perm[i];  perm[i]  = perm[best_i];  perm[best_i]  = tmpi;
+    }
+}
+static void sort_rec3(float* array, int* perm, int size)
+{
+    if (size <= 15)
+        selectionsort3(array, perm, size);
+    else{
+        float  pivot = array[size/2];
+        float  tmpf;
+        int    tmpi;
+        int    i = -1;
+        int    j = size;
+        for(;;){
+            do i++; while(array[i] < pivot);
+            do j--; while(pivot < array[j]);
+            if (i >= j) break;
+            tmpf = array[i]; array[i] = array[j]; array[j] = tmpf;
+            tmpi = perm[i];  perm[i]  = perm[j];  perm[j]  = tmpi;
+        }
+        sort_rec3(array    , perm,     i     );
+        sort_rec3(&array[i], &perm[i], size-i);
+    }
+}
+void minisat_sort3(float* array, int* perm, int size)
+{
+    sort_rec3(array, perm, size);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts the array of floating point numbers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Gia_SortFloats( float * pArray, int * pPerm, int nSize )
+{
+    int i;
+    if ( pPerm == NULL )
+    {
+        pPerm = ABC_ALLOC( int, nSize );
+        for ( i = 0; i < nSize; i++ )
+            pPerm[i] = i;
+    }
+    minisat_sort3( pArray, pPerm, nSize );
+//    for ( i = 1; i < nSize; i++ )
+//        assert( pArray[i-1] <= pArray[i] );
+    return pPerm;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaSpeedup.c b/abc-build/src/aig/gia/giaSpeedup.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaSpeedup.c
@@ -0,0 +1,805 @@
+/**CFile****************************************************************
+
+  FileName    [gia.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "map/if/if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts the pins in the decreasing order of delays.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_LutDelayTraceSortPins( Gia_Man_t * p, int iObj, int * pPinPerm, float * pPinDelays )
+{
+    int iFanin, i, j, best_i, temp;
+    assert( Gia_ObjIsLut(p, iObj) );
+    // start the trivial permutation and collect pin delays
+    Gia_LutForEachFanin( p, iObj, iFanin, i )
+    {
+        pPinPerm[i] = i;
+        pPinDelays[i] = Gia_ObjTimeArrival(p, iFanin);
+    }
+    // selection sort the pins in the decreasible order of delays
+    // this order will match the increasing order of LUT input pins
+    for ( i = 0; i < Gia_ObjLutSize(p, iObj)-1; i++ )
+    {
+        best_i = i;
+        for ( j = i+1; j < Gia_ObjLutSize(p, iObj); j++ )
+            if ( pPinDelays[pPinPerm[j]] > pPinDelays[pPinPerm[best_i]] )
+                best_i = j;
+        if ( best_i == i )
+            continue;
+        temp = pPinPerm[i]; 
+        pPinPerm[i] = pPinPerm[best_i]; 
+        pPinPerm[best_i] = temp;
+    }
+    // verify
+    assert( Gia_ObjLutSize(p, iObj) == 0 || pPinPerm[0] < Gia_ObjLutSize(p, iObj) );
+    for ( i = 1; i < Gia_ObjLutSize(p, iObj); i++ )
+    {
+        assert( pPinPerm[i] < Gia_ObjLutSize(p, iObj) );
+        assert( pPinDelays[pPinPerm[i-1]] >= pPinDelays[pPinPerm[i]] );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts the pins in the decreasing order of delays.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_LutWhereIsPin( Gia_Man_t * p, int iFanout, int iFanin, int * pPinPerm )
+{
+    int i;
+    for ( i = 0; i < Gia_ObjLutSize(p, iFanout); i++ )
+        if ( Gia_ObjLutFanin(p, iFanout, pPinPerm[i]) == iFanin )
+            return i;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the arrival times for the given object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Gia_ObjComputeArrival( Gia_Man_t * p, int iObj, int fUseSorting )
+{
+    If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib;
+    Gia_Obj_t * pObj = Gia_ManObj( p, iObj );
+    int k, iFanin, pPinPerm[32];
+    float pPinDelays[32];
+    float tArrival, * pDelays;
+    if ( Gia_ObjIsCi(pObj) )
+        return Gia_ObjTimeArrival(p, iObj);
+    if ( Gia_ObjIsCo(pObj) )
+        return Gia_ObjTimeArrival(p, Gia_ObjFaninId0p(p, pObj) );
+    assert( Gia_ObjIsLut(p, iObj) );
+    tArrival = -TIM_ETERNITY;
+    if ( pLutLib == NULL )
+    {
+        Gia_LutForEachFanin( p, iObj, iFanin, k )
+            if ( tArrival < Gia_ObjTimeArrival(p, iFanin) + 1.0 )
+                tArrival = Gia_ObjTimeArrival(p, iFanin) + 1.0;
+    }
+    else if ( !pLutLib->fVarPinDelays )
+    {
+        pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)];
+        Gia_LutForEachFanin( p, iObj, iFanin, k )
+            if ( tArrival < Gia_ObjTimeArrival(p, iFanin) + pDelays[0] )
+                tArrival = Gia_ObjTimeArrival(p, iFanin) + pDelays[0];
+    }
+    else
+    {
+        pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)];
+        if ( fUseSorting )
+        {
+            Gia_LutDelayTraceSortPins( p, iObj, pPinPerm, pPinDelays );
+            Gia_LutForEachFanin( p, iObj, iFanin, k ) 
+                if ( tArrival < Gia_ObjTimeArrival( p, Gia_ObjLutFanin(p,iObj,pPinPerm[k])) + pDelays[k] )
+                    tArrival = Gia_ObjTimeArrival( p, Gia_ObjLutFanin(p,iObj,pPinPerm[k])) + pDelays[k];
+        }
+        else
+        {
+            Gia_LutForEachFanin( p, iObj, iFanin, k )
+                if ( tArrival < Gia_ObjTimeArrival(p, iFanin) + pDelays[k] )
+                    tArrival = Gia_ObjTimeArrival(p, iFanin) + pDelays[k];
+        }
+    }
+    if ( Gia_ObjLutSize(p, iObj) == 0 )
+        tArrival = 0.0;
+    return tArrival;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Propagates the required times through the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Gia_ObjPropagateRequired( Gia_Man_t * p, int iObj, int fUseSorting )
+{
+    If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib;
+    int k, iFanin, pPinPerm[32];
+    float pPinDelays[32];
+    float tRequired = 0.0; // Suppress "might be used uninitialized"
+    float * pDelays;
+    assert( Gia_ObjIsLut(p, iObj) );
+    if ( pLutLib == NULL )
+    {
+        tRequired = Gia_ObjTimeRequired( p, iObj) - (float)1.0;
+        Gia_LutForEachFanin( p, iObj, iFanin, k )
+            if ( Gia_ObjTimeRequired(p, iFanin) > tRequired )
+                Gia_ObjSetTimeRequired( p, iFanin, tRequired );
+    }
+    else if ( !pLutLib->fVarPinDelays )
+    {
+        pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)];
+        tRequired = Gia_ObjTimeRequired(p, iObj) - pDelays[0];
+        Gia_LutForEachFanin( p, iObj, iFanin, k )
+            if ( Gia_ObjTimeRequired(p, iFanin) > tRequired )
+                Gia_ObjSetTimeRequired( p, iFanin, tRequired );
+    }
+    else 
+    {
+        pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)];
+        if ( fUseSorting )
+        {
+            Gia_LutDelayTraceSortPins( p, iObj, pPinPerm, pPinDelays );
+            Gia_LutForEachFanin( p, iObj, iFanin, k )
+            {
+                tRequired = Gia_ObjTimeRequired( p, iObj) - pDelays[k];
+                if ( Gia_ObjTimeRequired( p, Gia_ObjLutFanin(p, iObj,pPinPerm[k])) > tRequired )
+                    Gia_ObjSetTimeRequired( p,  Gia_ObjLutFanin(p, iObj,pPinPerm[k]), tRequired );
+            }
+        }
+        else
+        {
+            Gia_LutForEachFanin( p, iObj, iFanin, k )
+            {
+                tRequired = Gia_ObjTimeRequired(p, iObj) - pDelays[k];
+                if ( Gia_ObjTimeRequired(p, iFanin) > tRequired )
+                    Gia_ObjSetTimeRequired( p,  iFanin, tRequired );
+            }
+        }
+    }
+    return tRequired;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the delay trace of the given network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Gia_ManDelayTraceLut( Gia_Man_t * p )
+{
+    int fUseSorting = 1;
+    If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib;
+    Vec_Int_t * vObjs;
+    Gia_Obj_t * pObj;
+    float tArrival, tArrivalCur, tRequired, tSlack;
+    int i, iObj;
+
+    // get the library
+    if ( pLutLib && pLutLib->LutMax < Gia_ManLutSizeMax(p) )
+    {
+        printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", 
+            pLutLib->LutMax, Gia_ManLutSizeMax(p) );
+        return -TIM_ETERNITY;
+    }
+
+    // initialize the arrival times
+    Gia_ManTimeStart( p );
+
+    // propagate arrival times
+    if ( p->pManTime )
+        Tim_ManIncrementTravId( (Tim_Man_t *)p->pManTime );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( !Gia_ObjIsCi(pObj) && !Gia_ObjIsCo(pObj) && !Gia_ObjIsLut(p, i) )
+            continue;
+        tArrival = Gia_ObjComputeArrival( p, i, fUseSorting );
+        if ( Gia_ObjIsCi(pObj) && p->pManTime )
+        {
+            tArrival = Tim_ManGetCiArrival( (Tim_Man_t *)p->pManTime, Gia_ObjCioId(pObj) );
+//printf( "%.3f  ", tArrival );
+        }
+        if ( Gia_ObjIsCo(pObj) && p->pManTime )
+            Tim_ManSetCoArrival( (Tim_Man_t *)p->pManTime, Gia_ObjCioId(pObj), tArrival );
+        Gia_ObjSetTimeArrival( p, i, tArrival );
+    }
+
+    // get the latest arrival times
+    tArrival = -TIM_ETERNITY;
+    Gia_ManForEachCo( p, pObj, i )
+    {
+        tArrivalCur = Gia_ObjTimeArrivalObj( p, Gia_ObjFanin0(pObj) );
+        Gia_ObjSetTimeArrival( p, Gia_ObjId(p,pObj), tArrivalCur );
+        if ( tArrival < tArrivalCur )
+            tArrival = tArrivalCur;
+    }
+
+    // initialize the required times
+    if ( p->pManTime )
+    {
+        Tim_ManIncrementTravId( (Tim_Man_t *)p->pManTime );
+        Tim_ManInitPoRequiredAll( (Tim_Man_t *)p->pManTime, tArrival );
+    }
+    else
+    {
+        Gia_ManForEachCo( p, pObj, i )
+            Gia_ObjSetTimeRequiredObj( p, pObj, tArrival );
+    }
+
+    // propagate the required times
+    vObjs = Gia_ManOrderReverse( p );
+    Vec_IntForEachEntry( vObjs, iObj, i )
+    {
+        pObj = Gia_ManObj(p, iObj);
+        if ( Gia_ObjIsLut(p, iObj) )
+        {
+            Gia_ObjPropagateRequired( p, iObj, fUseSorting );
+        }
+        else if ( Gia_ObjIsCi(pObj) )
+        {
+            if ( p->pManTime )
+                Tim_ManSetCiRequired( (Tim_Man_t *)p->pManTime, Gia_ObjCioId(pObj), Gia_ObjTimeRequired(p, iObj) );
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+        {
+            if ( p->pManTime )
+            {
+                tRequired = Tim_ManGetCoRequired( (Tim_Man_t *)p->pManTime, Gia_ObjCioId(pObj) );
+                Gia_ObjSetTimeRequired( p, iObj, tRequired );
+            }
+            if ( Gia_ObjTimeRequired(p, Gia_ObjFaninId0p(p, pObj)) > Gia_ObjTimeRequired(p, iObj) )
+                Gia_ObjSetTimeRequired(p, Gia_ObjFaninId0p(p, pObj), Gia_ObjTimeRequired(p, iObj) );
+        }
+
+        // set slack for this object
+        tSlack = Gia_ObjTimeRequired(p, iObj) - Gia_ObjTimeArrival(p, iObj);
+        assert( tSlack + 0.01 > 0.0 );
+        Gia_ObjSetTimeSlack( p, iObj, tSlack < 0.0 ? 0.0 : tSlack );
+    }
+    Vec_IntFree( vObjs );
+    return tArrival;
+}
+
+#if 0
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the required times for the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Gia_ObjComputeRequired( Gia_Man_t * p, int iObj, int fUseSorting )
+{
+    If_LibLut_t * pLutLib = p->pLutLib;
+    int pPinPerm[32];
+    float pPinDelays[32];
+    Gia_Obj_t * pFanout;
+    float tRequired, tDelay, * pDelays;
+    int k, iFanin;
+    if ( Gia_ObjIsCo(iObj) )
+        return Gia_ObjTimeRequired( p, iObj);
+    tRequired = TIM_ETERNITY;
+    if ( pLutLib == NULL )
+    {
+        Gia_ObjForEachFanout( iObj, pFanout, k )
+        {
+            tDelay = Gia_ObjIsCo(pFanout)? 0.0 : 1.0;
+            if ( tRequired > Gia_ObjTimeRequired( p, pFanout) - tDelay )
+                tRequired = Gia_ObjTimeRequired( p, pFanout) - tDelay;
+        }
+    }
+    else if ( !pLutLib->fVarPinDelays )
+    {
+        Gia_ObjForEachFanout( iObj, pFanout, k )
+        {
+            pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, pFanout)];
+            tDelay = Gia_ObjIsCo(pFanout)? 0.0 : pDelays[0];
+            if ( tRequired > Gia_ObjTimeRequired( p, pFanout) - tDelay )
+                tRequired = Gia_ObjTimeRequired( p, pFanout) - tDelay;
+        }
+    }
+    else
+    {
+        if ( fUseSorting )
+        {
+            Gia_ObjForEachFanout( iObj, pFanout, k ) 
+            {
+                pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, pFanout)];
+                Gia_LutDelayTraceSortPins( p, pFanout, pPinPerm, pPinDelays );
+                iFanin = Gia_LutWhereIsPin( p, pFanout, iObj, pPinPerm );
+                assert( Gia_ObjLutFanin( p, pFanout, pPinPerm[iFanin]) == iObj );
+                tDelay = Gia_ObjIsCo(pFanout)? 0.0 : pDelays[iFanin];
+                if ( tRequired > Gia_ObjTimeRequired( p, pFanout) - tDelay )
+                    tRequired = Gia_ObjTimeRequired( p, pFanout) - tDelay;
+            }
+        }
+        else
+        {
+            Gia_ObjForEachFanout( iObj, pFanout, k )
+            {
+                pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, pFanout)];
+                iFanin = Gia_ObjFindFanin( p, pFanout, iObj );
+                assert( Gia_ObjLutFanin(p, pFanout, iFanin) == iObj );
+                tDelay = Gia_ObjIsCo(pFanout)? 0.0 : pDelays[iFanin];
+                if ( tRequired > Gia_ObjTimeRequired( p, pFanout) - tDelay )
+                    tRequired = Gia_ObjTimeRequired( p, pFanout) - tDelay;
+            }
+        }
+    }
+    return tRequired;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the arrival times for the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_LutVerifyTiming(  Gia_Man_t * p )
+{
+    int iObj;
+    float tArrival, tRequired;
+    int i;
+    Gia_LutForEachObj( p, iObj, i )
+    {
+        if ( Gia_ObjIsCi(iObj) && Gia_ObjFanoutNum(iObj) == 0 )
+            continue;
+        tArrival = Gia_ObjComputeArrival( p, iObj, 1 );
+        tRequired = Gia_ObjComputeRequired( p, iObj, 1 );
+        if ( !Gia_LutTimeEqual( tArrival, Gia_ObjTimeArrival( p, iObj), (float)0.01 ) )
+            printf( "Gia_LutVerifyTiming(): Object %d has different arrival time (%.2f) from computed (%.2f).\n", 
+                iObj->Id, Gia_ObjTimeArrival( p, iObj), tArrival );
+        if ( !Gia_LutTimeEqual( tRequired, Gia_ObjTimeRequired( p, iObj), (float)0.01 ) )
+            printf( "Gia_LutVerifyTiming(): Object %d has different required time (%.2f) from computed (%.2f).\n", 
+                iObj->Id, Gia_ObjTimeRequired( p, iObj), tRequired );
+    }
+    return 1;
+}
+
+#endif
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the delay trace for the given network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Gia_ManDelayTraceLutPrint( Gia_Man_t * p, int fVerbose )
+{
+    If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib;
+    int i, Nodes, * pCounters;
+    float tArrival, tDelta, nSteps, Num;
+    // get the library
+    if ( pLutLib && pLutLib->LutMax < Gia_ManLutSizeMax(p) )
+    {
+        printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", 
+            pLutLib->LutMax, Gia_ManLutSizeMax(p) );
+        return -ABC_INFINITY;
+    }
+    // decide how many steps
+    nSteps = pLutLib ? 20 : Gia_ManLutLevel(p);
+    pCounters = ABC_ALLOC( int, nSteps + 1 );
+    memset( pCounters, 0, sizeof(int)*(nSteps + 1) );
+    // perform delay trace
+    tArrival = Gia_ManDelayTraceLut( p );
+    tDelta   = tArrival / nSteps;
+    // count how many nodes have slack in the corresponding intervals
+    Gia_ManForEachLut( p, i )
+    {
+        if ( Gia_ObjLutSize(p, i) == 0 )
+            continue;
+        Num = Gia_ObjTimeSlack(p, i) / tDelta;
+        if ( Num > nSteps )
+            continue;
+        assert( Num >=0 && Num <= nSteps );
+        pCounters[(int)Num]++;
+    }
+    // print the results    
+    if ( fVerbose )
+    {
+        printf( "Max delay = %6.2f. Delay trace using %s model:\n", tArrival, pLutLib? "LUT library" : "unit-delay" );
+        Nodes = 0;
+        for ( i = 0; i < nSteps; i++ )
+        {
+            Nodes += pCounters[i];
+            printf( "%3d %s : %5d  (%6.2f %%)\n", pLutLib? 5*(i+1) : i+1, 
+                pLutLib? "%":"lev", Nodes, 100.0*Nodes/Gia_ManLutNum(p) );
+        }
+    }
+    ABC_FREE( pCounters );
+    Gia_ManTimeStop( p );
+    return tArrival;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determines timing-critical edges of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Gia_LutDelayTraceTCEdges( Gia_Man_t * p, int iObj, float tDelta )
+{
+    If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib;
+    int pPinPerm[32];
+    float pPinDelays[32];
+    float tRequired, * pDelays;
+    unsigned uResult = 0;
+    int k, iFanin;
+    tRequired = Gia_ObjTimeRequired( p, iObj );
+    if ( pLutLib == NULL )
+    {
+        Gia_LutForEachFanin( p, iObj, iFanin, k )
+            if ( tRequired < Gia_ObjTimeArrival(p, iFanin) + 1.0 + tDelta )
+                uResult |= (1 << k);
+    }
+    else if ( !pLutLib->fVarPinDelays )
+    {
+        pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)];
+        Gia_LutForEachFanin( p, iObj, iFanin, k )
+            if ( tRequired < Gia_ObjTimeArrival(p, iFanin) + pDelays[0] + tDelta )
+                uResult |= (1 << k);
+    }
+    else
+    {
+        pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)];
+        Gia_LutDelayTraceSortPins( p, iObj, pPinPerm, pPinDelays );
+        Gia_LutForEachFanin( p, iObj, iFanin, k )
+            if ( tRequired < Gia_ObjTimeArrival( p, Gia_ObjLutFanin(p, iObj,pPinPerm[k])) + pDelays[k] + tDelta )
+                uResult |= (1 << pPinPerm[k]);
+    }
+    return uResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds strashed nodes for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManSpeedupObj_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return 1;
+    Gia_ObjSetTravIdCurrent( p, pObj );
+    if ( Gia_ObjIsCi(pObj) )
+        return 0;
+    assert( Gia_ObjIsAnd(pObj) );
+    if ( !Gia_ManSpeedupObj_rec( p, Gia_ObjFanin0(pObj), vNodes ) )
+        return 0;
+    if ( !Gia_ManSpeedupObj_rec( p, Gia_ObjFanin1(pObj), vNodes ) )
+        return 0;
+    Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds strashed nodes for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSpeedupObj( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves, Vec_Int_t * vTimes )
+{
+    Vec_Int_t * vNodes;
+    Gia_Obj_t * pTemp = NULL;
+    int pCofs[32], nCofs, nSkip, i, k, iResult, iObj;
+    // mark the leaves
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+    Gia_ManForEachObjVec( vLeaves, p, pTemp, i )
+        Gia_ObjSetTravIdCurrent( p, pTemp );
+    // collect the AIG nodes
+    vNodes = Vec_IntAlloc( 100 );
+    if ( !Gia_ManSpeedupObj_rec( p, pObj, vNodes ) )
+    {
+        printf( "Bad node!!!\n" );
+        Vec_IntFree( vNodes );
+        return;
+    }
+    // derive cofactors
+    nCofs = (1 << Vec_IntSize(vTimes));
+    for ( i = 0; i < nCofs; i++ )
+    {
+        Gia_ManForEachObjVec( vLeaves, p, pTemp, k )
+            pTemp->Value = Abc_Var2Lit( Gia_ObjId(p, pTemp), 0 );
+        Gia_ManForEachObjVec( vTimes, p, pTemp, k )
+            pTemp->Value = ((i & (1<<k)) != 0);
+        Gia_ManForEachObjVec( vNodes, p, pTemp, k )
+            pTemp->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pTemp), Gia_ObjFanin1Copy(pTemp) );
+        pCofs[i] = pTemp->Value;
+    }
+    Vec_IntFree( vNodes );
+    // collect the resulting tree
+    Gia_ManForEachObjVec( vTimes, p, pTemp, k )
+        for ( nSkip = (1<<k), i = 0; i < nCofs; i += 2*nSkip )
+            pCofs[i] = Gia_ManHashMux( pNew, Gia_ObjToLit(p,pTemp), pCofs[i+nSkip], pCofs[i] );
+    // create choice node  (pObj is repr and ppCofs[0] is new)
+    iObj    = Gia_ObjId( p, pObj );
+    iResult = Abc_Lit2Var( pCofs[0] );
+    if ( iResult <= iObj )
+        return;
+    Gia_ObjSetRepr( pNew, iResult, iObj );
+    Gia_ObjSetNext( pNew, iResult, Gia_ObjNext(pNew, iObj) );
+    Gia_ObjSetNext( pNew, iObj, iResult );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds choices to speed up the network by the given percentage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManSpeedup( Gia_Man_t * p, int Percentage, int Degree, int fVerbose, int fVeryVerbose )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Vec_Int_t * vTimeCries, * vTimeFanins;
+    int iObj, iFanin, iFanin2, nNodesNew;
+    float tDelta, tArrival;
+    int i, k, k2, Counter, CounterRes, nTimeCris;
+    int fUseLutLib = (p->pLutLib != NULL);
+    void * pTempTim = NULL;
+    unsigned * puTCEdges;
+    assert( Gia_ManHasMapping(p) );
+    if ( !fUseLutLib && p->pManTime )
+    {
+        pTempTim = p->pManTime;
+        p->pManTime = Tim_ManDup( (Tim_Man_t *)pTempTim, 1 );
+    }
+    // perform delay trace
+    tArrival = Gia_ManDelayTraceLut( p );
+    tDelta = fUseLutLib ? tArrival*Percentage/100.0 : 1.0;
+    if ( fVerbose )
+    {
+        printf( "Max delay = %.2f. Delta = %.2f. ", tArrival, tDelta );
+        printf( "Using %s model. ", fUseLutLib ? "LUT library" : "unit-delay" );
+        if ( fUseLutLib )
+            printf( "Percentage = %d. ", Percentage );
+        printf( "\n" );
+    }
+    // mark the timing critical nodes and edges
+    puTCEdges = ABC_CALLOC( unsigned, Gia_ManObjNum(p) );
+    Gia_ManForEachLut( p, iObj )
+    {
+        if ( Gia_ObjTimeSlack(p, iObj) >= tDelta )
+            continue;
+        puTCEdges[iObj] = Gia_LutDelayTraceTCEdges( p, iObj, tDelta );
+    }
+    if ( fVerbose )
+    {
+        Counter = CounterRes = 0;
+        Gia_ManForEachLut( p, iObj )
+        {
+            Gia_LutForEachFanin( p, iObj, iFanin, k )
+                if ( !Gia_ObjIsCi(Gia_ManObj(p, iFanin)) && Gia_ObjTimeSlack(p, iFanin) < tDelta )
+                    Counter++;
+            CounterRes += Gia_WordCountOnes( puTCEdges[iObj] );
+        }
+        printf( "Edges: Total = %7d. 0-slack = %7d. Critical = %7d. Ratio = %4.2f\n", 
+            Gia_ManLutFaninCount(p), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 );
+    }
+
+    // start the resulting network
+    pNew = Gia_ManDup( p );
+    Gia_ManHashStart( pNew );
+    nNodesNew = 1000 + 3 * Gia_ManObjNum(pNew);
+    pNew->pNexts = ABC_CALLOC( int, nNodesNew );
+    pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, nNodesNew );
+    for ( i = 0; i < nNodesNew; i++ )
+        Gia_ObjSetRepr( pNew, i, GIA_VOID );
+
+    // collect nodes to be used for resynthesis
+    Counter = CounterRes = 0;
+    vTimeCries = Vec_IntAlloc( 16 );
+    vTimeFanins = Vec_IntAlloc( 16 );
+    Gia_ManForEachLut( p, iObj )
+    {
+        if ( Gia_ObjTimeSlack(p, iObj) >= tDelta )
+            continue;
+        // count the number of non-PI timing-critical nodes
+        nTimeCris = 0;
+        Gia_LutForEachFanin( p, iObj, iFanin, k )
+            if ( !Gia_ObjIsCi(Gia_ManObj(p, iFanin)) && (puTCEdges[iObj] & (1<<k)) )
+                nTimeCris++;
+        if ( !fVeryVerbose && nTimeCris == 0 )
+            continue;
+        Counter++;
+        // count the total number of timing critical second-generation nodes
+        Vec_IntClear( vTimeCries );
+        if ( nTimeCris )
+        {
+            Gia_LutForEachFanin( p, iObj, iFanin, k )
+                if ( !Gia_ObjIsCi(Gia_ManObj(p, iFanin)) && (puTCEdges[iObj] & (1<<k)) )
+                    Gia_LutForEachFanin( p, iFanin, iFanin2, k2 )
+                        if ( puTCEdges[iFanin] & (1<<k2) )
+                            Vec_IntPushUnique( vTimeCries, iFanin2 );
+        }
+//        if ( !fVeryVerbose && (Vec_IntSize(vTimeCries) == 0 || Vec_IntSize(vTimeCries) > Degree) )
+        if ( (Vec_IntSize(vTimeCries) == 0 || Vec_IntSize(vTimeCries) > Degree) )
+            continue;
+        CounterRes++;
+        // collect second generation nodes
+        Vec_IntClear( vTimeFanins );
+        Gia_LutForEachFanin( p, iObj, iFanin, k )
+        {
+            if ( Gia_ObjIsCi(Gia_ManObj(p, iFanin)) )
+                Vec_IntPushUnique( vTimeFanins, iFanin );
+            else
+                Gia_LutForEachFanin( p, iFanin, iFanin2, k2 )
+                    Vec_IntPushUnique( vTimeFanins, iFanin2 );                    
+        }
+        // print the results
+        if ( fVeryVerbose )
+        {
+        printf( "%5d Node %5d : %d %2d %2d  ", Counter, iObj, 
+            nTimeCris, Vec_IntSize(vTimeCries), Vec_IntSize(vTimeFanins) );
+        Gia_LutForEachFanin( p, iObj, iFanin, k )
+            printf( "%d(%.2f)%s ", iFanin, Gia_ObjTimeSlack(p, iFanin), (puTCEdges[iObj] & (1<<k))? "*":"" );
+        printf( "\n" );
+        }
+        // add the node to choices
+        if ( Vec_IntSize(vTimeCries) == 0 || Vec_IntSize(vTimeCries) > Degree )
+            continue;
+        // order the fanins in the increasing order of criticalily
+        if ( Vec_IntSize(vTimeCries) > 1 )
+        {
+            iFanin = Vec_IntEntry( vTimeCries, 0 );
+            iFanin2 = Vec_IntEntry( vTimeCries, 1 );
+            if ( Gia_ObjTimeSlack(p, iFanin) < Gia_ObjTimeSlack(p, iFanin2) )
+            {
+                Vec_IntWriteEntry( vTimeCries, 0, iFanin2 );
+                Vec_IntWriteEntry( vTimeCries, 1, iFanin );
+            }
+        }
+        if ( Vec_IntSize(vTimeCries) > 2 )
+        {
+            iFanin = Vec_IntEntry( vTimeCries, 1 );
+            iFanin2 = Vec_IntEntry( vTimeCries, 2 );
+            if ( Gia_ObjTimeSlack(p, iFanin) < Gia_ObjTimeSlack(p, iFanin2) )
+            {
+                Vec_IntWriteEntry( vTimeCries, 1, iFanin2 );
+                Vec_IntWriteEntry( vTimeCries, 2, iFanin );
+            }
+            iFanin = Vec_IntEntry( vTimeCries, 0 );
+            iFanin2 = Vec_IntEntry( vTimeCries, 1 );
+            if ( Gia_ObjTimeSlack(p, iFanin) < Gia_ObjTimeSlack(p, iFanin2) )
+            {
+                Vec_IntWriteEntry( vTimeCries, 0, iFanin2 );
+                Vec_IntWriteEntry( vTimeCries, 1, iFanin );
+            }
+        }
+        // add choice
+        Gia_ManSpeedupObj( pNew, p, Gia_ManObj(p,iObj), vTimeFanins, vTimeCries );
+        // quit if the number of nodes is large
+        if ( Gia_ManObjNum(pNew) > nNodesNew - 100 )
+        {
+            printf( "Speedup stopped adding choices because there was too many to add.\n" );
+            break;
+        }
+    }
+    Gia_ManTimeStop( p );
+    Vec_IntFree( vTimeCries );
+    Vec_IntFree( vTimeFanins );
+    ABC_FREE( puTCEdges );
+    if ( fVerbose )
+        printf( "Nodes: Total = %7d. 0-slack = %7d. Workable = %7d. Ratio = %4.2f\n", 
+        Gia_ManLutNum(p), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 ); 
+    if ( pTempTim )
+    {
+        Tim_ManStop( (Tim_Man_t *)p->pManTime );
+        p->pManTime = pTempTim;
+    }
+    // derive AIG with choices
+//Gia_ManPrintStats( pNew, 0 );
+    pTemp = Gia_ManEquivToChoices( pNew, 1 );
+    Gia_ManStop( pNew );
+//Gia_ManPrintStats( pTemp, 0 );
+//    pNew = Gia_ManDupOrderDfsChoices( pTemp );
+//    Gia_ManStop( pTemp );
+//Gia_ManPrintStats( pNew, 0 );
+//    return pNew;
+    return pTemp;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaStg.c b/abc-build/src/aig/gia/giaStg.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaStg.c
@@ -0,0 +1,528 @@
+/**CFile****************************************************************
+
+  FileName    [gia.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/extra/extra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintStateEncoding( Vec_Vec_t * vCodes, int nBits )
+{
+    char * pBuffer;
+    Vec_Int_t * vVec;
+    int i, k, Bit;
+    pBuffer = ABC_ALLOC( char, nBits + 1 );
+    pBuffer[nBits] = 0;
+    Vec_VecForEachLevelInt( vCodes, vVec, i )
+    {
+        printf( "%6d : ", i+1 );
+        memset( pBuffer, '-', nBits );
+        Vec_IntForEachEntry( vVec, Bit, k )
+        {
+            assert( Bit < nBits );
+            pBuffer[Bit] = '1';
+        }
+        printf( "%s\n", pBuffer );
+    }
+    ABC_FREE( pBuffer );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCreateOrGate( Gia_Man_t * p, Vec_Int_t * vLits )
+{
+    if ( Vec_IntSize(vLits) == 0 )
+        return 0;
+    while ( Vec_IntSize(vLits) > 1 )
+    {
+        int i, k = 0, Lit1, Lit2, LitRes;
+        Vec_IntForEachEntryDouble( vLits, Lit1, Lit2, i )
+        {
+            LitRes = Gia_ManHashOr( p, Lit1, Lit2 );
+            Vec_IntWriteEntry( vLits, k++, LitRes );
+        }
+        if ( Vec_IntSize(vLits) & 1 )
+            Vec_IntWriteEntry( vLits, k++, Vec_IntEntryLast(vLits) );
+        Vec_IntShrink( vLits, k );
+    }
+    assert( Vec_IntSize(vLits) == 1 );
+    return Vec_IntEntry(vLits, 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Gia_ManAssignCodes( int kHot, int nStates, int * pnBits )
+{
+    Vec_Vec_t * vCodes;
+    int s, i1, i2, i3, i4, i5, nBits;
+    assert( nStates > 0 );
+    assert( kHot >= 1 && kHot <= 5 );
+    vCodes = Vec_VecStart( nStates );
+    *pnBits = -1;
+    if ( kHot == 1 )
+    {
+        for ( i1 = 0; i1 < nStates; i1++ )
+            Vec_VecPushInt( vCodes, i1, i1 );
+        *pnBits = nStates;
+        return vCodes;
+    }
+    if ( kHot == 2 )
+    {
+        for ( nBits = kHot; nBits < ABC_INFINITY; nBits++ )
+            if ( nBits * (nBits-1) / 2 >= nStates )
+                break;
+        *pnBits = nBits;
+        s = 0;
+        for ( i1 = 0; i1 < nBits; i1++ )
+        for ( i2 = i1 + 1; i2 < nBits; i2++ )
+        {
+            Vec_VecPushInt( vCodes, s, i1 );
+            Vec_VecPushInt( vCodes, s, i2 );
+            if ( ++s == nStates )
+                return vCodes;
+        }
+    }
+    if ( kHot == 3 )
+    {
+        for ( nBits = kHot; nBits < ABC_INFINITY; nBits++ )
+            if ( nBits * (nBits-1) * (nBits-2) / 6 >= nStates )
+                break;       
+        *pnBits = nBits;
+        s = 0;
+        for ( i1 = 0; i1 < nBits; i1++ )
+        for ( i2 = i1 + 1; i2 < nBits; i2++ )
+        for ( i3 = i2 + 1; i3 < nBits; i3++ )
+        {
+            Vec_VecPushInt( vCodes, s, i1 );
+            Vec_VecPushInt( vCodes, s, i2 );
+            Vec_VecPushInt( vCodes, s, i3 );
+            if ( ++s == nStates )
+                return vCodes;
+        }
+    }
+    if ( kHot == 4 )
+    {
+        for ( nBits = kHot; nBits < ABC_INFINITY; nBits++ )
+            if ( nBits * (nBits-1) * (nBits-2) * (nBits-3) / 24 >= nStates )
+                break;       
+        *pnBits = nBits;
+        s = 0;
+        for ( i1 = 0; i1 < nBits; i1++ )
+        for ( i2 = i1 + 1; i2 < nBits; i2++ )
+        for ( i3 = i2 + 1; i3 < nBits; i3++ )
+        for ( i4 = i3 + 1; i4 < nBits; i4++ )
+        {
+            Vec_VecPushInt( vCodes, s, i1 );
+            Vec_VecPushInt( vCodes, s, i2 );
+            Vec_VecPushInt( vCodes, s, i3 );
+            Vec_VecPushInt( vCodes, s, i4 );
+            if ( ++s == nStates )
+                return vCodes;
+        }
+    }
+    if ( kHot == 5 )
+    {
+        for ( nBits = kHot; nBits < ABC_INFINITY; nBits++ )
+            if ( nBits * (nBits-1) * (nBits-2) * (nBits-3) * (nBits-4) / 120 >= nStates )
+                break;       
+        *pnBits = nBits;
+        s = 0;
+        for ( i1 = 0; i1 < nBits; i1++ )
+        for ( i2 = i1 + 1; i2 < nBits; i2++ )
+        for ( i3 = i2 + 1; i3 < nBits; i3++ )
+        for ( i4 = i3 + 1; i4 < nBits; i4++ )
+        for ( i5 = i4 + 1; i5 < nBits; i5++ )
+        {
+            Vec_VecPushInt( vCodes, s, i1 );
+            Vec_VecPushInt( vCodes, s, i2 );
+            Vec_VecPushInt( vCodes, s, i3 );
+            Vec_VecPushInt( vCodes, s, i4 );
+            Vec_VecPushInt( vCodes, s, i5 );
+            if ( ++s == nStates )
+                return vCodes;
+        }
+    }
+    assert( 0 );
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManStgKHot( Vec_Int_t * vLines, int nIns, int nOuts, int nStates, int kHot, int fVerbose )
+{
+    Gia_Man_t * p, * pTemp;
+    Vec_Int_t * vInMints, * vCurs, * vVec;
+    Vec_Vec_t * vLitsNext, * vLitsOuts, * vCodes;
+    int i, b, k, nBits, LitC, Lit;
+    assert( Vec_IntSize(vLines) % 4 == 0 );
+
+    // produce state encoding
+    vCodes = Gia_ManAssignCodes( kHot, nStates, &nBits );
+    assert( Vec_VecSize(vCodes) == nStates );
+    if ( fVerbose )
+        Gia_ManPrintStateEncoding( vCodes, nBits );
+
+    // start manager
+    p = Gia_ManStart( 10000 );
+    p->pName = Abc_UtilStrsav( "stg" );
+    for ( i = 0; i < nIns + nBits; i++ )
+        Gia_ManAppendCi(p);
+
+    // create input minterms
+    Gia_ManHashAlloc( p );
+    vInMints = Vec_IntAlloc( 1 << nIns );
+    for ( i = 0; i < (1 << nIns); i++ )
+    {
+        for ( Lit = 1, b = 0; b < nIns; b++ )
+            Lit = Gia_ManHashAnd( p, Lit, Abc_Var2Lit( b+1, !((i >> b) & 1) ) );
+        Vec_IntPush( vInMints, Lit );
+    } 
+
+    // create current states
+    vCurs  = Vec_IntAlloc( nStates );
+    Vec_VecForEachLevelInt( vCodes, vVec, i )
+    {
+        Lit = 1;
+        Vec_IntForEachEntry( vVec, b, k )
+        {
+            assert( b >= 0 && b < nBits );
+            Lit = Gia_ManHashAnd( p, Lit, Abc_Var2Lit(1+nIns+b, (b<kHot)) );
+        }
+        Vec_IntPush( vCurs, Lit );
+    }
+
+    // go through the lines
+    vLitsNext = Vec_VecStart( nBits );
+    vLitsOuts = Vec_VecStart( nOuts );
+    for ( i = 0; i < Vec_IntSize(vLines); )
+    {
+        int iMint = Vec_IntEntry(vLines, i++);
+        int iCur  = Vec_IntEntry(vLines, i++);
+        int iNext = Vec_IntEntry(vLines, i++);
+        int iOut  = Vec_IntEntry(vLines, i++);
+        assert( iMint >= 0 && iMint < (1<<nIns)  );
+        assert( iCur  >= 0 && iCur  < nStates    );
+        assert( iNext >= 0 && iNext < nStates    );
+        assert( iOut  >= 0 && iOut  < (1<<nOuts) );
+        // create condition
+        LitC = Gia_ManHashAnd( p, Vec_IntEntry(vInMints, iMint), Vec_IntEntry(vCurs, iCur) );
+        // update next state
+//        Vec_VecPushInt( vLitsNext, iNext, LitC );
+        vVec = (Vec_Int_t *)Vec_VecEntryInt( vCodes, iNext );
+        Vec_IntForEachEntry( vVec, b, k )
+            Vec_VecPushInt( vLitsNext, b, LitC );
+        // update outputs
+        for ( b = 0; b < nOuts; b++ )
+            if ( (iOut >> b) & 1 ) 
+                Vec_VecPushInt( vLitsOuts, b, LitC );
+    }
+    Vec_IntFree( vInMints );
+    Vec_IntFree( vCurs );
+    Vec_VecFree( vCodes );
+
+    // create POs
+    Vec_VecForEachLevelInt( vLitsOuts, vVec, b )
+        Gia_ManAppendCo( p, Gia_ManCreateOrGate(p, vVec) );
+    Vec_VecFree( vLitsOuts );
+
+    // create next states
+    Vec_VecForEachLevelInt( vLitsNext, vVec, b )
+        Gia_ManAppendCo( p, Abc_LitNotCond( Gia_ManCreateOrGate(p, vVec), (b<kHot) ) );
+    Vec_VecFree( vLitsNext );
+
+    Gia_ManSetRegNum( p, nBits );
+    Gia_ManHashStop( p );
+
+    p = Gia_ManCleanup( pTemp = p );
+    Gia_ManStop( pTemp );
+    assert( !Gia_ManHasDangling(p) );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManStgOneHot( Vec_Int_t * vLines, int nIns, int nOuts, int nStates )
+{
+    Gia_Man_t * p, * pTemp;
+    Vec_Int_t * vInMints, * vCurs, * vVec;
+    Vec_Vec_t * vLitsNext, * vLitsOuts;
+    int i, b, LitC, Lit;
+    assert( Vec_IntSize(vLines) % 4 == 0 );
+
+    // start manager
+    p = Gia_ManStart( 10000 );
+    p->pName = Abc_UtilStrsav( "stg" );
+    for ( i = 0; i < nIns + nStates; i++ )
+        Gia_ManAppendCi(p);
+
+    // create input minterms
+    Gia_ManHashAlloc( p );
+    vInMints = Vec_IntAlloc( 1 << nIns );
+    for ( i = 0; i < (1 << nIns); i++ )
+    {
+        for ( Lit = 1, b = 0; b < nIns; b++ )
+            Lit = Gia_ManHashAnd( p, Lit, Abc_Var2Lit( b+1, !((i >> b) & 1) ) );
+        Vec_IntPush( vInMints, Lit );
+    } 
+
+    // create current states
+    vCurs  = Vec_IntAlloc( nStates );
+    for ( i = 0; i < nStates; i++ )
+        Vec_IntPush( vCurs, Abc_Var2Lit( 1+nIns+i, !i ) );
+
+    // go through the lines
+    vLitsNext = Vec_VecStart( nStates );
+    vLitsOuts = Vec_VecStart( nOuts );
+    for ( i = 0; i < Vec_IntSize(vLines); )
+    {
+        int iMint = Vec_IntEntry(vLines, i++);
+        int iCur  = Vec_IntEntry(vLines, i++) - 1;
+        int iNext = Vec_IntEntry(vLines, i++) - 1;
+        int iOut  = Vec_IntEntry(vLines, i++);
+        assert( iMint >= 0 && iMint < (1<<nIns)  );
+        assert( iCur  >= 0 && iCur  < nStates    );
+        assert( iNext >= 0 && iNext < nStates    );
+        assert( iOut  >= 0 && iOut  < (1<<nOuts) );
+        // create condition
+        LitC = Gia_ManHashAnd( p, Vec_IntEntry(vInMints, iMint), Vec_IntEntry(vCurs, iCur) );
+        // update next state
+//        Lit = Gia_ManHashOr( p, LitC, Vec_IntEntry(vNexts, iNext) );
+//        Vec_IntWriteEntry( vNexts, iNext, Lit );
+        Vec_VecPushInt( vLitsNext, iNext, LitC );
+        // update outputs
+        for ( b = 0; b < nOuts; b++ )
+            if ( (iOut >> b) & 1 ) 
+            {
+//                Lit = Gia_ManHashOr( p, LitC, Vec_IntEntry(vOuts, b) );
+//                Vec_IntWriteEntry( vOuts, b, Lit );
+                Vec_VecPushInt( vLitsOuts, b, LitC );
+            }
+    }
+    Vec_IntFree( vInMints );
+    Vec_IntFree( vCurs );
+
+    // create POs
+    Vec_VecForEachLevelInt( vLitsOuts, vVec, i )
+        Gia_ManAppendCo( p, Gia_ManCreateOrGate(p, vVec) );
+    Vec_VecFree( vLitsOuts );
+
+    // create next states
+    Vec_VecForEachLevelInt( vLitsNext, vVec, i )
+        Gia_ManAppendCo( p, Abc_LitNotCond( Gia_ManCreateOrGate(p, vVec), !i ) );
+    Vec_VecFree( vLitsNext );
+
+    Gia_ManSetRegNum( p, nStates );
+    Gia_ManHashStop( p );
+
+    p = Gia_ManCleanup( pTemp = p );
+    Gia_ManStop( pTemp );
+    assert( !Gia_ManHasDangling(p) );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManStgPrint( FILE * pFile, Vec_Int_t * vLines, int nIns, int nOuts, int nStates )
+{
+    int i, nDigits = Abc_Base10Log( nStates );
+    assert( Vec_IntSize(vLines) % 4 == 0 );
+    for ( i = 0; i < Vec_IntSize(vLines); i += 4 )
+    {
+        int iMint = Vec_IntEntry(vLines, i  );
+        int iCur  = Vec_IntEntry(vLines, i+1) - 1;
+        int iNext = Vec_IntEntry(vLines, i+2) - 1;
+        int iOut  = Vec_IntEntry(vLines, i+3);
+        assert( iMint >= 0 && iMint < (1<<nIns)  );
+        assert( iCur  >= 0 && iCur  < nStates    );
+        assert( iNext >= 0 && iNext < nStates    );
+        assert( iOut  >= 0 && iOut  < (1<<nOuts) );
+        Extra_PrintBinary( pFile, (unsigned *)Vec_IntEntryP(vLines, i),  nIns );
+        fprintf( pFile, " %*d",  nDigits,     Vec_IntEntry(vLines,  i+1) );
+        fprintf( pFile, " %*d ", nDigits,     Vec_IntEntry(vLines,  i+2) );
+        Extra_PrintBinary( pFile, (unsigned *)Vec_IntEntryP(vLines, i+3), nOuts );
+        fprintf( pFile, "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManStgReadLines( char * pFileName, int * pnIns, int * pnOuts, int * pnStates )
+{
+    Vec_Int_t * vLines;
+    char pBuffer[1000];
+    char * pToken;
+    int Number, nInputs = -1, nOutputs = -1, nStates = 1;
+    FILE * pFile;
+    if ( !strcmp(pFileName + strlen(pFileName) - 3, "aig") )
+    {
+        printf( "Input file \"%s\" has extension \"%s\".\n", pFileName, "aig" );
+        return NULL;
+    }
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\".\n", pFileName );
+        return NULL;
+    }
+    vLines = Vec_IntAlloc( 1000 );
+    while ( fgets( pBuffer, 1000, pFile ) != NULL )
+    {
+        if ( pBuffer[0] == '.' || pBuffer[0] == '#' )
+            continue;
+        // read condition
+        pToken = strtok( pBuffer, " \r\n" );
+        if ( nInputs == -1 )
+            nInputs = strlen(pToken);
+        else
+            assert( nInputs == (int)strlen(pToken) );
+        Number = Extra_ReadBinary( pToken );
+        Vec_IntPush( vLines, Number );
+        // read current state
+        pToken = strtok( NULL, " \r\n" );
+        Vec_IntPush( vLines, atoi(pToken) );
+        nStates = Abc_MaxInt( nStates, Vec_IntEntryLast(vLines)+1 );
+        // read next state
+        pToken = strtok( NULL, " \r\n" );
+        Vec_IntPush( vLines, atoi(pToken) );
+        // read output
+        pToken = strtok( NULL, " \r\n" );
+        if ( nOutputs == -1 )
+            nOutputs = strlen(pToken);
+        else
+            assert( nOutputs == (int)strlen(pToken) );
+        Number = Extra_ReadBinary( pToken );
+        Vec_IntPush( vLines, Number );
+    }
+    fclose( pFile );
+    if ( pnIns )
+        *pnIns = nInputs;
+    if ( pnOuts )
+        *pnOuts = nOutputs;
+    if ( pnStates )
+        *pnStates = nStates;
+    return vLines;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManStgRead( char * pFileName, int kHot, int fVerbose )
+{
+    Gia_Man_t * p;
+    Vec_Int_t * vLines;
+    int nIns, nOuts, nStates;
+    vLines = Gia_ManStgReadLines( pFileName, &nIns, &nOuts, &nStates );
+    if ( vLines == NULL )
+        return NULL;
+//    p = Gia_ManStgOneHot( vLines, nIns, nOuts, nStates );
+    p = Gia_ManStgKHot( vLines, nIns, nOuts, nStates, kHot, fVerbose );
+    Vec_IntFree( vLines );
+    return p;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaStr.c b/abc-build/src/aig/gia/giaStr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaStr.c
@@ -0,0 +1,58 @@
+/**CFile****************************************************************
+
+  FileName    [giaStr.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Cut computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaStr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManLutBalance( Gia_Man_t * p, int nLutSize, int fUseMuxes, int fRecursive, int fOptArea, int fVerbose )
+{
+    return Gia_ManDup(p);
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaSupMin.c b/abc-build/src/aig/gia/giaSupMin.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaSupMin.c
@@ -0,0 +1,165 @@
+/**CFile****************************************************************
+
+  FileName    [giaSupMin.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Support minimization for AIGs with don't-cares.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaSupMin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// decomposition manager
+typedef struct Gia_ManSup_t_ Gia_ManSup_t;
+struct Gia_ManSup_t_ 
+{
+    int             nVarsMax;     // the max number of variables
+    int             nWordsMax;    // the max number of words
+    Vec_Ptr_t *     vTruthVars;   // elementary truth tables
+    Vec_Ptr_t *     vTruthNodes;  // internal truth tables
+    // current problem
+    Gia_Man_t *     pGia;
+    int             iData;
+    int             iCare;
+    Vec_Int_t *     vConeCare;
+    Vec_Int_t *     vConeData;
+    unsigned *      pTruthIn;
+    unsigned *      pTruthOut;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts Decmetry manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_ManSup_t * Gia_ManSupStart( int nVarsMax )
+{
+    Gia_ManSup_t * p;
+    assert( nVarsMax <= 20 );
+    p = ABC_CALLOC( Gia_ManSup_t, 1 );
+    p->nVarsMax    = nVarsMax;
+    p->nWordsMax   = Kit_TruthWordNum( p->nVarsMax );
+    p->vTruthVars  = Vec_PtrAllocTruthTables( p->nVarsMax );
+    p->vTruthNodes = Vec_PtrAllocSimInfo( 512, p->nWordsMax );
+    p->vConeCare   = Vec_IntAlloc( 512 );
+    p->vConeData   = Vec_IntAlloc( 512 );
+    p->pTruthIn    = ABC_ALLOC( unsigned, p->nWordsMax );
+    p->pTruthOut   = ABC_ALLOC( unsigned, p->nWordsMax );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops Decmetry manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSupStop( Gia_ManSup_t * p )
+{
+    ABC_FREE( p->pTruthIn );
+    ABC_FREE( p->pTruthOut );
+    Vec_IntFreeP( &p->vConeCare );
+    Vec_IntFreeP( &p->vConeData );
+    Vec_PtrFreeP( &p->vTruthVars );
+    Vec_PtrFreeP( &p->vTruthNodes );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSupExperimentOne( Gia_ManSup_t * p, Gia_Obj_t * pData, Gia_Obj_t * pCare )
+{
+    int iData = Gia_ObjId( p->pGia, Gia_Regular(pData) );
+    int iCare = Gia_ObjId( p->pGia, Gia_Regular(pCare) );
+    if ( !Gia_ObjIsAnd(Gia_Regular(pCare)) )
+    {
+        Abc_Print( 1, "Enable is not an AND.\n" );
+        return;
+    }
+    Abc_Print( 1, "DataSupp = %6d. DataCone = %6d.   CareSupp = %6d. CareCone = %6d.", 
+        Gia_ManSuppSize( p->pGia, &iData, 1 ),
+        Gia_ManConeSize( p->pGia, &iData, 1 ),
+        Gia_ManSuppSize( p->pGia, &iCare, 1 ),
+        Gia_ManConeSize( p->pGia, &iCare, 1 ) );
+    Abc_Print( 1, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSupExperiment( Gia_Man_t * pGia, Vec_Int_t * vPairs )
+{
+    Gia_ManSup_t * p;
+    Gia_Obj_t * pData, * pCare;
+    int i;
+    p = Gia_ManSupStart( 16 );
+    p->pGia = pGia;
+    assert( Vec_IntSize(vPairs) % 2 == 0 );
+    for ( i = 0; i < Vec_IntSize(vPairs)/2; i++ )
+    {
+        Abc_Print( 1, "%6d : ", i );
+        pData = Gia_ManPo( pGia, Vec_IntEntry(vPairs, 2*i+0) );
+        pCare = Gia_ManPo( pGia, Vec_IntEntry(vPairs, 2*i+1) );
+        Gia_ManSupExperimentOne( p, Gia_ObjChild0(pData), Gia_ObjChild0(pCare) );
+    }
+    Gia_ManSupStop( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaSweep.c b/abc-build/src/aig/gia/giaSweep.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaSweep.c
@@ -0,0 +1,347 @@
+/**CFile****************************************************************
+
+  FileName    [giaSweep.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Sweeping of GIA manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaSweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "giaAig.h"
+#include "proof/dch/dch.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Mark GIA nodes that feed into POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManFraigCheckCis( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    for ( assert( Gia_ObjIsCi(pObj) ); Gia_ObjIsCi(pObj); pObj-- )
+        if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+            return 1;
+    return 0;
+}
+Gia_Obj_t * Gia_ManFraigMarkCis( Gia_Man_t * p, Gia_Obj_t * pObj, int fMark )
+{
+    for ( assert( Gia_ObjIsCi(pObj) ); Gia_ObjIsCi(pObj); pObj-- )
+        if ( fMark )
+            Gia_ObjSetTravIdCurrent( p, pObj );
+    return pObj;
+}
+Gia_Obj_t * Gia_ManFraigMarkCos( Gia_Man_t * p, Gia_Obj_t * pObj, int fMark )
+{
+    for ( assert( Gia_ObjIsCo(pObj) ); Gia_ObjIsCo(pObj); pObj-- )
+        if ( fMark )
+        {
+            Gia_ObjSetTravIdCurrent( p, pObj );
+            Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) );
+        }
+    return pObj;
+}
+Gia_Obj_t * Gia_ManFraigMarkAnd( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    for ( assert( Gia_ObjIsAnd(pObj) ); Gia_ObjIsAnd(pObj); pObj-- )
+        if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        {
+            Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) );
+            Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin1(pObj) );
+        }
+    return pObj;
+}
+Gia_Man_t * Gia_ManFraigCreateGia( Gia_Man_t * p )
+{
+    Vec_Int_t * vBoxPres;
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i, fLabelPos;
+    assert( p->pManTime != NULL );
+    // start marks
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+    vBoxPres = Vec_IntAlloc( 1000 );
+    // mark primary outputs
+    fLabelPos = 1;
+    pObj = Gia_ManObj( p, Gia_ManObjNum(p) - 1 );
+    assert( Gia_ObjIsCo(pObj) );
+    while ( Gia_ObjIsCo(pObj) )
+    {
+        pObj = Gia_ManFraigMarkCos( p, pObj, fLabelPos );
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj = Gia_ManFraigMarkAnd( p, pObj );
+        assert( Gia_ObjIsCi(pObj) );
+        fLabelPos = Gia_ManFraigCheckCis(p, pObj);
+        pObj = Gia_ManFraigMarkCis( p, pObj, fLabelPos );
+        Vec_IntPush( vBoxPres, fLabelPos );
+    }
+    Vec_IntPop( vBoxPres );
+    Vec_IntReverseOrder( vBoxPres );
+    assert( Gia_ObjIsConst0(pObj) );
+    // mark primary inputs
+    Gia_ManForEachObj1( p, pObj, i )
+        if ( Gia_ObjIsCi(pObj) )
+            Gia_ObjSetTravIdCurrent( p, pObj );
+        else
+            break;
+    // duplicate marked entries
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( !Gia_ObjIsTravIdCurrent(p, pObj) )
+            continue;
+        if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Gia_ManAppendCi(pNew);
+        else if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+        else assert( 0 );
+    }
+    // update timing manager
+    pNew->pManTime = Gia_ManUpdateTimMan( p, vBoxPres );
+    // update extra STG
+    assert( p->pAigExtra != NULL );
+    assert( pNew->pAigExtra == NULL );
+    pNew->pAigExtra = Gia_ManUpdateExtraAig( p->pManTime, p->pAigExtra, vBoxPres );
+    Vec_IntFree( vBoxPres );
+//    assert( Gia_ManPiNum(pNew) == Tim_ManCiNum(pNew->pManTime) );
+//    assert( Gia_ManPoNum(pNew) == Tim_ManCoNum(pNew->pManTime) );
+//    assert( Gia_ManPiNum(pNew) == Tim_ManPiNum(pNew->pManTime) + Gia_ManPoNum(pNew->pAigExtra) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ObjFanin0CopyRepr( Gia_Man_t * p, Gia_Obj_t * pObj, int * pReprs )
+{
+    int fanId = Gia_ObjFaninId0p( p, pObj );
+    if ( pReprs[fanId] == -1 )
+        return Gia_ObjFanin0Copy( pObj );
+    assert( Abc_Lit2Var(pReprs[fanId]) < Gia_ObjId(p, pObj) );
+    return Abc_LitNotCond( Gia_ObjValue(Gia_ManObj(p, Abc_Lit2Var(pReprs[fanId]))), Gia_ObjFaninC0(pObj) ^ Abc_LitIsCompl(pReprs[fanId]) );
+}
+int Gia_ObjFanin1CopyRepr( Gia_Man_t * p, Gia_Obj_t * pObj, int * pReprs )
+{
+    int fanId = Gia_ObjFaninId1p( p, pObj );
+    if ( pReprs[fanId] == -1 )
+        return Gia_ObjFanin1Copy( pObj );
+    assert( Abc_Lit2Var(pReprs[fanId]) < Gia_ObjId(p, pObj) );
+    return Abc_LitNotCond( Gia_ObjValue(Gia_ManObj(p, Abc_Lit2Var(pReprs[fanId]))), Gia_ObjFaninC1(pObj) ^ Abc_LitIsCompl(pReprs[fanId]) );
+}
+Gia_Man_t * Gia_ManFraigReduceGia( Gia_Man_t * p, int * pReprs )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( pReprs != NULL );
+    assert( Gia_ManRegNum(p) == 0 );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManFillValue( p );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0CopyRepr(p, pObj, pReprs), Gia_ObjFanin1CopyRepr(p, pObj, pReprs) );
+        else if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Gia_ManAppendCi( pNew );
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0CopyRepr(p, pObj, pReprs) );
+        else if ( Gia_ObjIsConst0(pObj) )
+            pObj->Value = 0;
+        else assert( 0 );
+    }
+    Gia_ManHashStop( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes representatives in terms of the original objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Gia_ManFraigSelectReprs( Gia_Man_t * p, Gia_Man_t * pGia, int fVerbose )
+{
+    Gia_Obj_t * pObj;
+    int * pReprs   = ABC_FALLOC( int, Gia_ManObjNum(p) );
+    int * pGia2Abc = ABC_FALLOC( int, Gia_ManObjNum(pGia) );
+    int i, iLitGia, iLitGia2, iReprGia, fCompl;
+    int nConsts = 0, nReprs = 0;
+    pGia2Abc[0] = 0;
+    Gia_ManSetPhase( pGia );
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsCo(pObj) )
+            continue;
+        assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) );
+        iLitGia = Gia_ObjValue(pObj);
+        if ( iLitGia == -1 )
+            continue;
+        iReprGia = Gia_ObjReprSelf( pGia, Abc_Lit2Var(iLitGia) );
+        if ( pGia2Abc[iReprGia] == -1 )
+            pGia2Abc[iReprGia] = i;
+        else
+        { 
+            iLitGia2 = Gia_ObjValue( Gia_ManObj(p, pGia2Abc[iReprGia]) );
+            assert( Gia_ObjReprSelf(pGia, Abc_Lit2Var(iLitGia)) == Gia_ObjReprSelf(pGia, Abc_Lit2Var(iLitGia2)) );
+            fCompl  = Abc_LitIsCompl(iLitGia) ^ Abc_LitIsCompl(iLitGia2);
+            fCompl ^= Gia_ManObj(pGia, Abc_Lit2Var(iLitGia))->fPhase;
+            fCompl ^= Gia_ManObj(pGia, Abc_Lit2Var(iLitGia2))->fPhase;
+            pReprs[i] = Abc_Var2Lit( pGia2Abc[iReprGia], fCompl );
+            assert( Abc_Lit2Var(pReprs[i]) < i );
+            if ( pGia2Abc[iReprGia] == 0 )
+                nConsts++;
+            else
+                nReprs++;
+        }
+    }
+    ABC_FREE( pGia2Abc );
+    if ( fVerbose )
+        printf( "Found %d const reprs and %d other reprs.\n", nConsts, nReprs );
+    return pReprs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFraigSweepPerform( Gia_Man_t * p, void * pPars )
+{
+    Aig_Man_t * pNew;
+    pNew = Gia_ManToAigSimple( p );
+    assert( Gia_ManObjNum(p) == Aig_ManObjNum(pNew) );
+    Dch_ComputeEquivalences( pNew, (Dch_Pars_t *)pPars );
+    Gia_ManReprFromAigRepr( pNew, p );
+    Aig_ManStop( pNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces root model with scorr.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFraigSweep( Gia_Man_t * p, void * pPars )
+{ 
+    Gia_Man_t * pGia, * pNew, * pTemp;
+    int * pReprs;
+    assert( Gia_ManRegNum(p) == 0 );
+    if ( p->pManTime == NULL )
+    {
+        Gia_ManFraigSweepPerform( p, pPars );
+        pNew = Gia_ManEquivReduce( p, 1, 0, 0, 0 );
+        if ( pNew == NULL )
+            return Gia_ManDup(p);
+        return pNew;
+    }
+    if ( p->pAigExtra == NULL )
+    {
+        printf( "Timing manager is given but there is no GIA of boxes.\n" );
+        return NULL;
+    }
+    // order AIG objects
+    pNew = Gia_ManDupUnnormalize( p );
+    if ( pNew == NULL )
+        return NULL;
+    // find global equivalences
+    pNew->pManTime = p->pManTime;
+    pGia = Gia_ManDupCollapse( pNew, p->pAigExtra, NULL );
+    pNew->pManTime = NULL;
+    Gia_ManFraigSweepPerform( pGia, pPars );
+    // transfer equivalences
+    pReprs = Gia_ManFraigSelectReprs( pNew, pGia, ((Dch_Pars_t *)pPars)->fVerbose );
+    Gia_ManStop( pGia );
+    // reduce AIG
+    pNew = Gia_ManFraigReduceGia( pTemp = pNew, pReprs );
+    Gia_ManStop( pTemp );
+    ABC_FREE( pReprs );
+    // derive new AIG
+    assert( pNew->pManTime  == NULL );
+    assert( pNew->pAigExtra == NULL );
+    pNew->pManTime   = p->pManTime;
+    pNew->pAigExtra  = p->pAigExtra;
+    pNew->nAnd2Delay = p->nAnd2Delay;
+    pNew = Gia_ManFraigCreateGia( pTemp = pNew );
+    assert( pTemp->pManTime  == p->pManTime );
+    assert( pTemp->pAigExtra == p->pAigExtra );
+    pTemp->pManTime  = NULL;
+    pTemp->pAigExtra = NULL;
+    Gia_ManStop( pTemp );
+    // normalize the result
+    pNew = Gia_ManDupNormalize( pTemp = pNew );
+    pNew->pManTime   = pTemp->pManTime;   pTemp->pManTime   = NULL;
+    pNew->pAigExtra  = pTemp->pAigExtra;  pTemp->pAigExtra  = NULL;
+    pNew->nAnd2Delay = pTemp->nAnd2Delay; pTemp->nAnd2Delay = 0;
+    Gia_ManStop( pTemp );
+    // return the result
+    assert( pNew->pManTime  != NULL );
+    assert( pNew->pAigExtra != NULL );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaSweeper.c b/abc-build/src/aig/gia/giaSweeper.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaSweeper.c
@@ -0,0 +1,1185 @@
+/**CFile****************************************************************
+
+  FileName    [giaSweeper.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Incremental SAT sweeper.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaSweeper.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "base/main/main.h"
+#include "sat/bsat/satSolver.h"
+#include "proof/ssc/ssc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/*
+
+SAT sweeping/equivalence checking requires the following steps:
+- Creating probes
+  These APIs should be called for all internal points in the logic, which may be used as
+      - nodes representing conditions to be used as constraints
+      - nodes representing functions to be equivalence checked
+      - nodes representing functions needed by the user at the end of SAT sweeping
+  Creating new probe using  Gia_SweeperProbeCreate():   int Gia_SweeperProbeCreate( Gia_Man_t * p, int iLit );
+  Delete existing probe using Gia_SweeperProbeDelete(): int Gia_SweeperProbeDelete( Gia_Man_t * p, int ProbeId );
+  Update existing probe using Gia_SweeperProbeUpdate(): int Gia_SweeperProbeUpdate( Gia_Man_t * p, int ProbeId, int iLit );
+  Comments:
+      - a probe is identified by its 0-based ID, which is returned by above procedures
+      - GIA literal of the probe is returned by       int Gia_SweeperProbeLit( Gia_Man_t * p, int ProbeId )
+- Adding/removing conditions on the current path by calling Gia_SweeperCondPush() and Gia_SweeperCondPop()
+      extern void Gia_SweeperCondPush( Gia_Man_t * p, int ProbeId );
+      extern void Gia_SweeperCondPop( Gia_Man_t * p );
+- Performing equivalence checking by calling     int Gia_SweeperCheckEquiv( Gia_Man_t * pGia, int Probe1, int Probe2 )
+      (resource limits, such as the number of conflicts, will be controllable by dedicated GIA APIs)
+- The resulting AIG to be returned to the user by calling Gia_SweeperExtractUserLogic()
+      Gia_Man_t * Gia_SweeperExtractUserLogic( Gia_Man_t * p, Vec_Int_t * vProbeIds, Vec_Ptr_t * vOutNames )
+
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Swp_Man_t_ Swp_Man_t;
+struct Swp_Man_t_
+{
+    Gia_Man_t *    pGia;        // GIA manager under construction
+    int            nConfMax;    // conflict limit in seconds
+    int            nTimeOut;    // runtime limit in seconds
+    Vec_Int_t *    vProbes;     // probes
+    Vec_Int_t *    vCondProbes; // conditions as probes
+    Vec_Int_t *    vCondAssump; // conditions as SAT solver literals
+    // equivalence checking
+    sat_solver *   pSat;        // SAT solver 
+    Vec_Int_t *    vId2Lit;     // mapping of Obj IDs into SAT literal
+    Vec_Int_t *    vFront;      // temporary frontier
+    Vec_Int_t *    vFanins;     // temporary fanins
+    Vec_Int_t *    vCexSwp;     // sweeper counter-example
+    Vec_Int_t *    vCexUser;    // user-visible counter-example
+    int            nSatVars;    // counter of SAT variables
+    // statistics
+    int            nSatCalls;
+    int            nSatCallsSat;
+    int            nSatCallsUnsat;
+    int            nSatCallsUndec;
+    int            nSatProofs;
+    abctime        timeStart;
+    abctime        timeTotal;
+    abctime        timeCnf;
+    abctime        timeSat;
+    abctime        timeSatSat;
+    abctime        timeSatUnsat;
+    abctime        timeSatUndec;
+};
+
+static inline int  Swp_ManObj2Lit( Swp_Man_t * p, int Id )              { return Vec_IntGetEntry( p->vId2Lit, Id );              }
+static inline int  Swp_ManLit2Lit( Swp_Man_t * p, int Lit )             { assert( Vec_IntEntry(p->vId2Lit, Abc_Lit2Var(Lit)) ); return Abc_Lit2LitL( Vec_IntArray(p->vId2Lit), Lit );  }
+static inline void Swp_ManSetObj2Lit( Swp_Man_t * p, int Id, int Lit )  { assert( Lit > 0 ); Vec_IntSetEntry( p->vId2Lit, Id, Lit );                }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+    
+/**Function*************************************************************
+
+  Synopsis    [Creating/deleting the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Swp_Man_t * Swp_ManStart( Gia_Man_t * pGia )
+{
+    Swp_Man_t * p;
+    int Lit;
+    assert( pGia->pHTable != NULL );
+    pGia->pData = p = ABC_CALLOC( Swp_Man_t, 1 );
+    p->pGia         = pGia;
+    p->nConfMax     = 1000;
+    p->vProbes      = Vec_IntAlloc( 100 );
+    p->vCondProbes  = Vec_IntAlloc( 100 );
+    p->vCondAssump  = Vec_IntAlloc( 100 );
+    p->vId2Lit      = Vec_IntAlloc( 10000 );
+    p->vFront       = Vec_IntAlloc( 100 );
+    p->vFanins      = Vec_IntAlloc( 100 );
+    p->vCexSwp      = Vec_IntAlloc( 100 );
+    p->pSat         = sat_solver_new();
+    p->nSatVars     = 1;
+    sat_solver_setnvars( p->pSat, 1000 );
+    Swp_ManSetObj2Lit( p, 0, (Lit = Abc_Var2Lit(p->nSatVars++, 0)) );
+    Lit = Abc_LitNot(Lit);
+    sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+    p->timeStart    = Abc_Clock();
+    return p;
+}
+static inline void Swp_ManStop( Gia_Man_t * pGia )
+{
+    Swp_Man_t * p = (Swp_Man_t *)pGia->pData;
+    sat_solver_delete( p->pSat );
+    Vec_IntFree( p->vFanins );
+    Vec_IntFree( p->vCexSwp );
+    Vec_IntFree( p->vId2Lit );
+    Vec_IntFree( p->vFront );
+    Vec_IntFree( p->vProbes );
+    Vec_IntFree( p->vCondProbes );
+    Vec_IntFree( p->vCondAssump );
+    ABC_FREE( p );
+    pGia->pData = NULL;
+}
+Gia_Man_t * Gia_SweeperStart( Gia_Man_t * pGia )
+{
+    if ( pGia == NULL )
+        pGia = Gia_ManStart( 10000 );
+    if ( pGia->pHTable == NULL )
+        Gia_ManHashStart( pGia );
+    // recompute fPhase and fMark1 to mark multiple fanout nodes if AIG is already defined!!!
+
+    Swp_ManStart( pGia );
+    pGia->fSweeper = 1;
+    return pGia;
+}
+void Gia_SweeperStop( Gia_Man_t * pGia )
+{
+    pGia->fSweeper = 0;
+    Swp_ManStop( pGia );
+    Gia_ManHashStop( pGia );
+//    Gia_ManStop( pGia );
+}
+int Gia_SweeperIsRunning( Gia_Man_t * pGia )
+{
+    return (pGia->pData != NULL);
+}
+double Gia_SweeperMemUsage( Gia_Man_t * pGia )
+{
+    Swp_Man_t * p = (Swp_Man_t *)pGia->pData;
+    double nMem = sizeof(Swp_Man_t);
+    nMem += Vec_IntCap(p->vProbes);
+    nMem += Vec_IntCap(p->vCondProbes);
+    nMem += Vec_IntCap(p->vCondAssump);
+    nMem += Vec_IntCap(p->vId2Lit);
+    nMem += Vec_IntCap(p->vFront);
+    nMem += Vec_IntCap(p->vFanins);
+    nMem += Vec_IntCap(p->vCexSwp);
+    return 4.0 * nMem;
+}
+void Gia_SweeperPrintStats( Gia_Man_t * pGia )
+{
+    Swp_Man_t * p = (Swp_Man_t *)pGia->pData;
+    double nMemSwp = Gia_SweeperMemUsage(pGia);
+    double nMemGia = (double)Gia_ManObjNum(pGia)*(sizeof(Gia_Obj_t) + sizeof(int));
+    double nMemSat = sat_solver_memory(p->pSat);
+    double nMemTot = nMemSwp + nMemGia + nMemSat;
+    printf( "SAT sweeper statistics:\n" );
+    printf( "Memory usage:\n" );
+    ABC_PRMP( "Sweeper         ", nMemSwp, nMemTot );
+    ABC_PRMP( "AIG manager     ", nMemGia, nMemTot );
+    ABC_PRMP( "SAT solver      ", nMemSat, nMemTot );
+    ABC_PRMP( "TOTAL           ", nMemTot, nMemTot );
+    printf( "Runtime usage:\n" );
+    p->timeTotal = Abc_Clock() - p->timeStart;
+    ABC_PRTP( "CNF construction", p->timeCnf,      p->timeTotal );
+    ABC_PRTP( "SAT solving     ", p->timeSat,      p->timeTotal );
+    ABC_PRTP( "    Sat         ", p->timeSatSat,   p->timeTotal );
+    ABC_PRTP( "    Unsat       ", p->timeSatUnsat, p->timeTotal );
+    ABC_PRTP( "    Undecided   ", p->timeSatUndec, p->timeTotal );
+    ABC_PRTP( "TOTAL RUNTIME   ", p->timeTotal,    p->timeTotal );
+    printf( "GIA: " );
+    Gia_ManPrintStats( pGia, NULL );
+    printf( "SAT calls = %d. Sat = %d. Unsat = %d. Undecided = %d.  Proofs = %d.\n", 
+        p->nSatCalls, p->nSatCallsSat, p->nSatCallsUnsat, p->nSatCallsUndec, p->nSatProofs );
+    Sat_SolverPrintStats( stdout, p->pSat );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Setting resource limits.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_SweeperSetConflictLimit( Gia_Man_t * p, int nConfMax )
+{
+    Swp_Man_t * pSwp = (Swp_Man_t *)p->pData;
+    pSwp->nConfMax = nConfMax;
+}
+void Gia_SweeperSetRuntimeLimit( Gia_Man_t * p, int nSeconds )
+{
+    Swp_Man_t * pSwp = (Swp_Man_t *)p->pData;
+    pSwp->nTimeOut = nSeconds;
+}
+Vec_Int_t * Gia_SweeperGetCex( Gia_Man_t * p )
+{
+    Swp_Man_t * pSwp = (Swp_Man_t *)p->pData;
+    assert( pSwp->vCexUser == NULL || Vec_IntSize(pSwp->vCexUser) == Gia_ManPiNum(p) );
+    return pSwp->vCexUser;
+}
+    
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+// create new probe
+int Gia_SweeperProbeCreate( Gia_Man_t * p, int iLit )
+{
+    Swp_Man_t * pSwp = (Swp_Man_t *)p->pData;
+    int ProbeId = Vec_IntSize(pSwp->vProbes);
+    assert( iLit >= 0 );
+    Vec_IntPush( pSwp->vProbes, iLit );
+    return ProbeId;
+}
+// delete existing probe
+int Gia_SweeperProbeDelete( Gia_Man_t * p, int ProbeId )
+{
+    Swp_Man_t * pSwp = (Swp_Man_t *)p->pData;
+    int iLit = Vec_IntEntry(pSwp->vProbes, ProbeId);
+    assert( iLit >= 0 );
+    Vec_IntWriteEntry(pSwp->vProbes, ProbeId, -1);
+    return iLit;
+}
+// update existing probe
+int Gia_SweeperProbeUpdate( Gia_Man_t * p, int ProbeId, int iLitNew )
+{
+    Swp_Man_t * pSwp = (Swp_Man_t *)p->pData;
+    int iLit = Vec_IntEntry(pSwp->vProbes, ProbeId);
+    assert( iLit >= 0 );
+    Vec_IntWriteEntry(pSwp->vProbes, ProbeId, iLitNew);
+    return iLit;
+}
+// returns literal associated with the probe
+int Gia_SweeperProbeLit( Gia_Man_t * p, int ProbeId )
+{
+    Swp_Man_t * pSwp = (Swp_Man_t *)p->pData;
+    int iLit = Vec_IntEntry(pSwp->vProbes, ProbeId);
+    assert( iLit >= 0 );
+    return iLit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure returns indexes of all currently defined valid probes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_SweeperCollectValidProbeIds( Gia_Man_t * p )
+{
+    Swp_Man_t * pSwp = (Swp_Man_t *)p->pData;
+    Vec_Int_t * vProbeIds = Vec_IntAlloc( 1000 );
+    int iLit, ProbeId;
+    Vec_IntForEachEntry( pSwp->vProbes, iLit, ProbeId )
+    {
+        if ( iLit < 0 ) continue;
+        Vec_IntPush( vProbeIds, ProbeId );
+    }
+    return vProbeIds;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_SweeperCondPush( Gia_Man_t * p, int ProbeId )
+{
+    Swp_Man_t * pSwp = (Swp_Man_t *)p->pData;
+    Vec_IntPush( pSwp->vCondProbes, ProbeId );
+}
+int Gia_SweeperCondPop( Gia_Man_t * p )
+{
+    Swp_Man_t * pSwp = (Swp_Man_t *)p->pData;
+    return Vec_IntPop( pSwp->vCondProbes );
+}
+Vec_Int_t * Gia_SweeperCondVector( Gia_Man_t * p )
+{
+    Swp_Man_t * pSwp = (Swp_Man_t *)p->pData;
+    return pSwp->vCondProbes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Gia_ManExtract_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vObjIds )
+{
+    if ( !Gia_ObjIsAnd(pObj) )
+        return;
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    Gia_ManExtract_rec( p, Gia_ObjFanin0(pObj), vObjIds );
+    Gia_ManExtract_rec( p, Gia_ObjFanin1(pObj), vObjIds );
+    Vec_IntPush( vObjIds, Gia_ObjId(p, pObj) );
+}
+Gia_Man_t * Gia_SweeperExtractUserLogic( Gia_Man_t * p, Vec_Int_t * vProbeIds, Vec_Ptr_t * vInNames, Vec_Ptr_t * vOutNames )
+{
+    Vec_Int_t * vObjIds, * vValues;
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, ProbeId;
+    assert( vInNames  == NULL || Gia_ManPiNum(p) == Vec_PtrSize(vInNames) );
+    assert( vOutNames == NULL || Vec_IntSize(vProbeIds) == Vec_PtrSize(vOutNames) );
+    // create new
+    Gia_ManIncrementTravId( p );
+    vObjIds = Vec_IntAlloc( 1000 );
+    Vec_IntForEachEntry( vProbeIds, ProbeId, i )
+    {
+        pObj = Gia_Lit2Obj( p, Gia_SweeperProbeLit(p, ProbeId) );
+        Gia_ManExtract_rec( p, Gia_Regular(pObj), vObjIds );
+    }
+    // create new manager
+    pNew = Gia_ManStart( 1 + Gia_ManPiNum(p) + Vec_IntSize(vObjIds) + Vec_IntSize(vProbeIds) + 100 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    // create internal nodes
+    Gia_ManHashStart( pNew );
+    vValues = Vec_IntAlloc( Vec_IntSize(vObjIds) );
+    Gia_ManForEachObjVec( vObjIds, p, pObj, i )
+    {
+        Vec_IntPush( vValues, pObj->Value );
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    }
+    Gia_ManHashStop( pNew );
+    // create outputs
+    Vec_IntForEachEntry( vProbeIds, ProbeId, i )
+    {
+        pObj = Gia_Lit2Obj( p, Gia_SweeperProbeLit(p, ProbeId) );
+        Gia_ManAppendCo( pNew, Gia_Regular(pObj)->Value ^ Gia_IsComplement(pObj) );
+    }
+    // return the values back
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->Value = 0;
+    Gia_ManForEachObjVec( vObjIds, p, pObj, i )
+        pObj->Value = Vec_IntEntry( vValues, i );
+    Vec_IntFree( vObjIds );
+    Vec_IntFree( vValues );
+    // duplicate if needed
+    if ( Gia_ManHasDangling(pNew) )
+    {
+        pNew = Gia_ManCleanup( pTemp = pNew );
+        Gia_ManStop( pTemp );
+    }
+    // copy names if present
+    if ( vInNames )
+        pNew->vNamesIn = Vec_PtrDupStr( vInNames );
+    if ( vOutNames )
+        pNew->vNamesOut = Vec_PtrDupStr( vOutNames );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_SweeperLogicDump( Gia_Man_t * p, Vec_Int_t * vProbeIds, int fDumpConds, char * pFileName )
+{
+    Gia_Man_t * pGiaOuts = Gia_SweeperExtractUserLogic( p, vProbeIds, NULL, NULL );
+    Vec_Int_t * vProbeConds = Gia_SweeperCondVector( p );
+    printf( "Dumping logic cones" );
+    if ( fDumpConds && Vec_IntSize(vProbeConds) > 0 )
+    {
+        Gia_Man_t * pGiaCond = Gia_SweeperExtractUserLogic( p, vProbeConds, NULL, NULL );
+        Gia_ManDupAppendShare( pGiaOuts, pGiaCond );
+        pGiaOuts->nConstrs = Gia_ManPoNum(pGiaCond);
+        Gia_ManHashStop( pGiaOuts );
+        Gia_ManStop( pGiaCond );
+        printf( " and conditions" );
+    }
+    Gia_AigerWrite( pGiaOuts, pFileName, 0, 0 );
+    Gia_ManStop( pGiaOuts );
+    printf( " into file \"%s\".\n", pFileName );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sweeper cleanup.]
+
+  Description [Returns new GIA with sweeper defined, which is the same
+  as the original sweeper, with all the dangling logic removed and SAT 
+  solver restarted. The probe IDs are guaranteed to have the same logic
+  functions as in the original manager.]
+               
+  SideEffects [The input manager is deleted inside this procedure.]
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_SweeperCleanup( Gia_Man_t * p, char * pCommLime )
+{
+    Swp_Man_t * pSwp = (Swp_Man_t *)p->pData;
+    Vec_Int_t * vObjIds;
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, iLit, ProbeId;
+
+    // collect all internal nodes pointed to by currently-used probes
+    Gia_ManIncrementTravId( p );
+    vObjIds = Vec_IntAlloc( 1000 );
+    Vec_IntForEachEntry( pSwp->vProbes, iLit, ProbeId )
+    {
+        if ( iLit < 0 ) continue;
+        pObj = Gia_Lit2Obj( p, iLit );
+        Gia_ManExtract_rec( p, Gia_Regular(pObj), vObjIds );
+    }
+    // create new manager
+    pNew = Gia_ManStart( 1 + Gia_ManPiNum(p) + Vec_IntSize(vObjIds) + 100 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    // create internal nodes
+    Gia_ManHashStart( pNew );
+    Gia_ManForEachObjVec( vObjIds, p, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManHashStop( pNew );
+    // create outputs
+    Vec_IntForEachEntry( pSwp->vProbes, iLit, ProbeId )
+    {
+        if ( iLit < 0 ) continue;
+        pObj = Gia_Lit2Obj( p, iLit );
+        iLit = Gia_Regular(pObj)->Value ^ Gia_IsComplement(pObj);
+        Vec_IntWriteEntry( pSwp->vProbes, ProbeId, iLit );
+    }
+    Vec_IntFree( vObjIds );
+    // duplicate if needed
+    if ( Gia_ManHasDangling(pNew) )
+    {
+        pNew = Gia_ManCleanup( pTemp = pNew );
+        Gia_ManStop( pTemp );
+    }
+    // execute command line
+    if ( pCommLime )
+    {
+        // set pNew to be current GIA in ABC
+        Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew );
+        // execute command line pCommLine using Abc_CmdCommandExecute()
+        Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), pCommLime );
+        // get pNew to be current GIA in ABC     
+        pNew = Abc_FrameGetGia( Abc_FrameGetGlobalFrame() );
+    }
+    // restart the SAT solver
+    Vec_IntClear( pSwp->vId2Lit );
+    sat_solver_delete( pSwp->pSat );
+    pSwp->pSat         = sat_solver_new();
+    pSwp->nSatVars     = 1;
+    sat_solver_setnvars( pSwp->pSat, 1000 );
+    Swp_ManSetObj2Lit( pSwp, 0, (iLit = Abc_Var2Lit(pSwp->nSatVars++, 0)) );
+    iLit = Abc_LitNot(iLit);
+    sat_solver_addclause( pSwp->pSat, &iLit, &iLit + 1 );
+    pSwp->timeStart    = Abc_Clock();
+    // return the result
+    pNew->pData = p->pData; p->pData = NULL;
+    Gia_ManStop( p );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Addes clauses to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Gia_ManAddClausesMux( Swp_Man_t * p, Gia_Obj_t * pNode )
+{
+    Gia_Obj_t * pNodeI, * pNodeT, * pNodeE;
+    int pLits[4], LitF, LitI, LitT, LitE, RetValue;
+    assert( !Gia_IsComplement( pNode ) );
+    assert( Gia_ObjIsMuxType( pNode ) );
+    // get nodes (I = if, T = then, E = else)
+    pNodeI = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE );
+    // get the Litiable numbers
+    LitF = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNode) );
+    LitI = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNodeI) );
+    LitT = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNodeT) );
+    LitE = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNodeE) );
+
+    // f = ITE(i, t, e)
+
+    // i' + t' + f
+    // i' + t  + f'
+    // i  + e' + f
+    // i  + e  + f'
+
+    // create four clauses
+    pLits[0] = Abc_LitNotCond(LitI, 1);
+    pLits[1] = Abc_LitNotCond(LitT, 1);
+    pLits[2] = Abc_LitNotCond(LitF, 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = Abc_LitNotCond(LitI, 1);
+    pLits[1] = Abc_LitNotCond(LitT, 0);
+    pLits[2] = Abc_LitNotCond(LitF, 1);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = Abc_LitNotCond(LitI, 0);
+    pLits[1] = Abc_LitNotCond(LitE, 1);
+    pLits[2] = Abc_LitNotCond(LitF, 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = Abc_LitNotCond(LitI, 0);
+    pLits[1] = Abc_LitNotCond(LitE, 0);
+    pLits[2] = Abc_LitNotCond(LitF, 1);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+
+    // two additional clauses
+    // t' & e' -> f'
+    // t  & e  -> f
+
+    // t  + e   + f'
+    // t' + e'  + f
+
+    if ( LitT == LitE )
+    {
+//        assert( fCompT == !fCompE );
+        return;
+    }
+
+    pLits[0] = Abc_LitNotCond(LitT, 0);
+    pLits[1] = Abc_LitNotCond(LitE, 0);
+    pLits[2] = Abc_LitNotCond(LitF, 1);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = Abc_LitNotCond(LitT, 1);
+    pLits[1] = Abc_LitNotCond(LitE, 1);
+    pLits[2] = Abc_LitNotCond(LitF, 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Addes clauses to the solver.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Gia_ManAddClausesSuper( Swp_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSuper )
+{
+    int i, RetValue, Lit, LitNode, pLits[2];
+    assert( !Gia_IsComplement(pNode) );
+    assert( Gia_ObjIsAnd( pNode ) );
+    // suppose AND-gate is A & B = C
+    // add !A => !C   or   A + !C
+    // add !B => !C   or   B + !C
+    LitNode = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNode) );
+    Vec_IntForEachEntry( vSuper, Lit, i )
+    {
+        pLits[0] = Swp_ManLit2Lit( p, Lit );
+        pLits[1] = Abc_LitNot( LitNode );
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+        // update literals
+        Vec_IntWriteEntry( vSuper, i, Abc_LitNot(pLits[0]) );
+    }
+    // add A & B => C   or   !A + !B + C
+    Vec_IntPush( vSuper, LitNode );
+    RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(vSuper), Vec_IntArray(vSuper) + Vec_IntSize(vSuper) );
+    assert( RetValue );
+    (void) RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Gia_ManCollectSuper_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper )
+{
+    // stop at complements, shared, PIs, and MUXes
+    if ( Gia_IsComplement(pObj) || pObj->fMark1 || Gia_ObjIsCi(pObj) || Gia_ObjIsMuxType(pObj) )
+    {
+        Vec_IntPushUnique( vSuper, Gia_Obj2Lit(p, pObj) );
+        return;
+    }
+    Gia_ManCollectSuper_rec( p, Gia_ObjChild0(pObj), vSuper );
+    Gia_ManCollectSuper_rec( p, Gia_ObjChild1(pObj), vSuper );
+}
+static void Gia_ManCollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper )
+{
+    assert( !Gia_IsComplement(pObj) );
+    assert( Gia_ObjIsAnd(pObj) );
+    Vec_IntClear( vSuper );
+    Gia_ManCollectSuper_rec( p, Gia_ObjChild0(pObj), vSuper );
+    Gia_ManCollectSuper_rec( p, Gia_ObjChild1(pObj), vSuper );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the solver clause database.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Gia_ManObjAddToFrontier( Swp_Man_t * p, int Id, Vec_Int_t * vFront )
+{
+    Gia_Obj_t * pObj;
+    if ( Id == 0 || Swp_ManObj2Lit(p, Id) )
+        return;
+    pObj = Gia_ManObj( p->pGia, Id );
+    Swp_ManSetObj2Lit( p, Id, Abc_Var2Lit(p->nSatVars++, pObj->fPhase) );
+    sat_solver_setnvars( p->pSat, p->nSatVars + 100 );
+    if ( Gia_ObjIsAnd(pObj) )
+        Vec_IntPush( vFront, Id );
+}
+static void Gia_ManCnfNodeAddToSolver( Swp_Man_t * p, int NodeId )
+{
+    Gia_Obj_t * pNode;
+    int i, k, Id, Lit;
+    abctime clk;
+    // quit if CNF is ready
+    if ( NodeId == 0 || Swp_ManObj2Lit(p, NodeId) )
+        return;
+clk = Abc_Clock();
+    // start the frontier
+    Vec_IntClear( p->vFront );
+    Gia_ManObjAddToFrontier( p, NodeId, p->vFront );
+    // explore nodes in the frontier
+    Gia_ManForEachObjVec( p->vFront, p->pGia, pNode, i )
+    {
+        // create the supergate
+        assert( Swp_ManObj2Lit(p, Gia_ObjId(p->pGia, pNode)) );
+        if ( Gia_ObjIsMuxType(pNode) )
+        {
+            Vec_IntClear( p->vFanins );
+            Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId0p( p->pGia, Gia_ObjFanin0(pNode) ) );
+            Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId0p( p->pGia, Gia_ObjFanin1(pNode) ) );
+            Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId1p( p->pGia, Gia_ObjFanin0(pNode) ) );
+            Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId1p( p->pGia, Gia_ObjFanin1(pNode) ) );
+            Vec_IntForEachEntry( p->vFanins, Id, k )
+                Gia_ManObjAddToFrontier( p, Id, p->vFront );
+            Gia_ManAddClausesMux( p, pNode );
+        }
+        else
+        {
+            Gia_ManCollectSuper( p->pGia, pNode, p->vFanins );
+            Vec_IntForEachEntry( p->vFanins, Lit, k )
+                Gia_ManObjAddToFrontier( p, Abc_Lit2Var(Lit), p->vFront );
+            Gia_ManAddClausesSuper( p, pNode, p->vFanins );
+        }
+        assert( Vec_IntSize(p->vFanins) > 1 );
+    }
+p->timeCnf += Abc_Clock() - clk;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Vec_Int_t * Gia_ManGetCex( Gia_Man_t * pGia, Vec_Int_t * vId2Lit, sat_solver * pSat, Vec_Int_t * vCex )
+{
+    Gia_Obj_t * pObj;
+    int i, LitSat, Value;
+    Vec_IntClear( vCex );
+    Gia_ManForEachPi( pGia, pObj, i )
+    {
+        if ( Gia_ObjId(pGia, pObj) >= Vec_IntSize(vId2Lit) )
+        {
+            Vec_IntPush( vCex, 2 );
+            continue;
+        }
+        LitSat = Vec_IntEntry( vId2Lit, Gia_ObjId(pGia, pObj) );
+        if ( LitSat == 0 )
+        {
+            Vec_IntPush( vCex, 2 );
+            continue;
+        }
+        assert( LitSat > 0 );
+        Value = sat_solver_var_value(pSat, Abc_Lit2Var(LitSat)) ^ Abc_LitIsCompl(LitSat);
+        Vec_IntPush( vCex, Value );
+    }
+    return vCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Runs equivalence test for probes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_SweeperCheckEquiv( Gia_Man_t * pGia, int Probe1, int Probe2 )
+{
+    Swp_Man_t * p = (Swp_Man_t *)pGia->pData;
+    int iLitOld, iLitNew, iLitAig, pLitsSat[2], RetValue, RetValue1, ProbeId, i;
+    abctime clk;
+    p->nSatCalls++;
+    assert( p->pSat != NULL );
+    p->vCexUser = NULL;
+
+    // get the literals
+    iLitOld = Gia_SweeperProbeLit( pGia, Probe1 );
+    iLitNew = Gia_SweeperProbeLit( pGia, Probe2 );
+    // if the literals are identical, the probes are equivalent
+    if ( iLitOld == iLitNew )
+        return 1;
+    // if the literals are opposites, the probes are not equivalent
+    if ( Abc_LitRegular(iLitOld) == Abc_LitRegular(iLitNew) )
+    {
+        Vec_IntFill( p->vCexSwp, Gia_ManPiNum(pGia), 2 );
+        p->vCexUser = p->vCexSwp;
+        return 0;
+    }
+    // order the literals
+    if ( iLitOld < iLitNew )
+        ABC_SWAP( int, iLitOld, iLitNew );
+    assert( iLitOld > iLitNew );
+
+    // create logic cones and the array of assumptions
+    Vec_IntClear( p->vCondAssump );
+    Vec_IntForEachEntry( p->vCondProbes, ProbeId, i )
+    {
+        iLitAig = Gia_SweeperProbeLit( pGia, ProbeId );
+        Gia_ManCnfNodeAddToSolver( p, Abc_Lit2Var(iLitAig) );
+        Vec_IntPush( p->vCondAssump, Abc_LitNot(Swp_ManLit2Lit(p, iLitAig)) );
+    }
+    Gia_ManCnfNodeAddToSolver( p, Abc_Lit2Var(iLitOld) );
+    Gia_ManCnfNodeAddToSolver( p, Abc_Lit2Var(iLitNew) );
+    sat_solver_compress( p->pSat );
+
+    // set the SAT literals
+    pLitsSat[0] = Swp_ManLit2Lit( p, iLitOld );
+    pLitsSat[1] = Swp_ManLit2Lit( p, iLitNew );
+
+    // solve under assumptions
+    // A = 1; B = 0     OR     A = 1; B = 1 
+    Vec_IntPush( p->vCondAssump, pLitsSat[0] );
+    Vec_IntPush( p->vCondAssump, Abc_LitNot(pLitsSat[1]) );
+
+    // set runtime limit for this call
+    if ( p->nTimeOut )
+        sat_solver_set_runtime_limit( p->pSat, p->nTimeOut * CLOCKS_PER_SEC + Abc_Clock() );
+
+clk = Abc_Clock();
+    RetValue1 = sat_solver_solve( p->pSat, Vec_IntArray(p->vCondAssump), Vec_IntArray(p->vCondAssump) + Vec_IntSize(p->vCondAssump), 
+        (ABC_INT64_T)p->nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    Vec_IntShrink( p->vCondAssump, Vec_IntSize(p->vCondAssump) - 2 );
+p->timeSat += Abc_Clock() - clk;
+    if ( RetValue1 == l_False )
+    {
+        pLitsSat[0] = Abc_LitNot( pLitsSat[0] );
+        RetValue = sat_solver_addclause( p->pSat, pLitsSat, pLitsSat + 2 );
+        assert( RetValue );
+        pLitsSat[0] = Abc_LitNot( pLitsSat[0] );
+p->timeSatUnsat += Abc_Clock() - clk;
+        p->nSatCallsUnsat++;
+    }
+    else if ( RetValue1 == l_True )
+    {
+        p->vCexUser = Gia_ManGetCex( p->pGia, p->vId2Lit, p->pSat, p->vCexSwp );
+p->timeSatSat += Abc_Clock() - clk;
+        p->nSatCallsSat++;
+        return 0;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+p->timeSatUndec += Abc_Clock() - clk;
+        p->nSatCallsUndec++;
+        return -1;
+    }
+
+    // if the old node was constant 0, we already know the answer
+    if ( Gia_ManIsConstLit(iLitNew) )
+    {
+        p->nSatProofs++;
+        return 1;
+    }
+
+    // solve under assumptions
+    // A = 0; B = 1     OR     A = 0; B = 0 
+    Vec_IntPush( p->vCondAssump, Abc_LitNot(pLitsSat[0]) );
+    Vec_IntPush( p->vCondAssump, pLitsSat[1] );
+
+clk = Abc_Clock();
+    RetValue1 = sat_solver_solve( p->pSat, Vec_IntArray(p->vCondAssump), Vec_IntArray(p->vCondAssump) + Vec_IntSize(p->vCondAssump), 
+        (ABC_INT64_T)p->nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    Vec_IntShrink( p->vCondAssump, Vec_IntSize(p->vCondAssump) - 2 );
+p->timeSat += Abc_Clock() - clk;
+    if ( RetValue1 == l_False )
+    {
+        pLitsSat[1] = Abc_LitNot( pLitsSat[1] );
+        RetValue = sat_solver_addclause( p->pSat, pLitsSat, pLitsSat + 2 );
+        assert( RetValue );
+        pLitsSat[1] = Abc_LitNot( pLitsSat[1] );
+p->timeSatUnsat += Abc_Clock() - clk;
+        p->nSatCallsUnsat++;
+    }
+    else if ( RetValue1 == l_True )
+    {
+        p->vCexUser = Gia_ManGetCex( p->pGia, p->vId2Lit, p->pSat, p->vCexSwp );
+p->timeSatSat += Abc_Clock() - clk;
+        p->nSatCallsSat++;
+        return 0;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+p->timeSatUndec += Abc_Clock() - clk;
+        p->nSatCallsUndec++;
+        return -1;
+    }
+    // return SAT proof
+    p->nSatProofs++;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the set of conditions is UNSAT (0 if SAT; -1 if undecided).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_SweeperCondCheckUnsat( Gia_Man_t * pGia )
+{
+    Swp_Man_t * p = (Swp_Man_t *)pGia->pData;
+    int RetValue, ProbeId, iLitAig, i;
+    abctime clk;
+    assert( p->pSat != NULL );
+    p->nSatCalls++;
+    p->vCexUser = NULL;
+
+    // create logic cones and the array of assumptions
+    Vec_IntClear( p->vCondAssump );
+    Vec_IntForEachEntry( p->vCondProbes, ProbeId, i )
+    {
+        iLitAig = Gia_SweeperProbeLit( pGia, ProbeId );
+        Gia_ManCnfNodeAddToSolver( p, Abc_Lit2Var(iLitAig) );
+        Vec_IntPush( p->vCondAssump, Abc_LitNot(Swp_ManLit2Lit(p, iLitAig)) );
+    }
+    sat_solver_compress( p->pSat );
+
+    // set runtime limit for this call
+    if ( p->nTimeOut )
+        sat_solver_set_runtime_limit( p->pSat, p->nTimeOut * CLOCKS_PER_SEC + Abc_Clock() );
+
+clk = Abc_Clock();
+    RetValue = sat_solver_solve( p->pSat, Vec_IntArray(p->vCondAssump), Vec_IntArray(p->vCondAssump) + Vec_IntSize(p->vCondAssump), 
+        (ABC_INT64_T)p->nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+p->timeSat += Abc_Clock() - clk;
+    if ( RetValue == l_False )
+    {
+        assert( Vec_IntSize(p->vCondProbes) > 0 );
+p->timeSatUnsat += Abc_Clock() - clk;
+        p->nSatCallsUnsat++;
+        p->nSatProofs++;
+        return 1;
+    }
+    else if ( RetValue == l_True )
+    {
+        p->vCexUser = Gia_ManGetCex( p->pGia, p->vId2Lit, p->pSat, p->vCexSwp );
+p->timeSatSat += Abc_Clock() - clk;
+        p->nSatCallsSat++;
+        return 0;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+p->timeSatUndec += Abc_Clock() - clk;
+        p->nSatCallsUndec++;
+        return -1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs grafting from another manager.]
+
+  Description [Returns the array of resulting literals in the destination manager.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_SweeperGraft( Gia_Man_t * pDst, Vec_Int_t * vProbes, Gia_Man_t * pSrc )
+{
+    Vec_Int_t * vOutLits;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Gia_SweeperIsRunning(pDst) );
+    if ( vProbes )
+        assert( Vec_IntSize(vProbes) == Gia_ManPiNum(pSrc) );
+    else
+        assert( Gia_ManPiNum(pDst) == Gia_ManPiNum(pSrc) );
+    Gia_ManForEachPi( pSrc, pObj, i )
+        pObj->Value = vProbes ? Gia_SweeperProbeLit(pDst, Vec_IntEntry(vProbes, i)) : Gia_Obj2Lit(pDst,Gia_ManPi(pDst, i));
+    Gia_ManForEachAnd( pSrc, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pDst, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    vOutLits = Vec_IntAlloc( Gia_ManPoNum(pSrc) );
+    Gia_ManForEachPo( pSrc, pObj, i )
+        Vec_IntPush( vOutLits, Gia_ObjFanin0Copy(pObj) );
+    return vOutLits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs conditional sweeping of the cone.]
+
+  Description [Returns the result as a new GIA manager with as many inputs 
+  as the original manager and as many outputs as there are logic cones.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_SweeperSweep( Gia_Man_t * p, Vec_Int_t * vProbeOuts, int nWords, int nConfs, int fVerify, int fVerbose )
+{
+    Vec_Int_t * vProbeConds;
+    Gia_Man_t * pGiaCond, * pGiaOuts, * pGiaRes;
+    Ssc_Pars_t Pars, * pPars = &Pars;
+    Ssc_ManSetDefaultParams( pPars );
+    pPars->nWords   = nWords;
+    pPars->nBTLimit = nConfs;
+    pPars->fVerify  = fVerify;
+    pPars->fVerbose = fVerbose;
+    // sweeper is running
+    assert( Gia_SweeperIsRunning(p) );
+    // extract conditions and logic cones
+    vProbeConds = Gia_SweeperCondVector( p );
+    pGiaCond = Gia_SweeperExtractUserLogic( p, vProbeConds, NULL, NULL );
+    pGiaOuts = Gia_SweeperExtractUserLogic( p, vProbeOuts, NULL, NULL );
+    Gia_ManSetPhase( pGiaOuts );
+    // if there is no conditions, define constant true constraint (constant 0 output)
+    if ( Gia_ManPoNum(pGiaCond) == 0 )
+        Gia_ManAppendCo( pGiaCond, Gia_ManConst0Lit() );
+    // perform sweeping under constraints
+    pGiaRes = Ssc_PerformSweeping( pGiaOuts, pGiaCond, pPars );
+    Gia_ManStop( pGiaCond );
+    Gia_ManStop( pGiaOuts );
+    return pGiaRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure to perform conditional fraig sweeping on separate logic cones.]
+
+  Description [The procedure takes GIA with the sweeper defined. The sweeper
+  is assumed to have some conditions currently pushed, which will be used
+  as constraints for fraig sweeping. The second argument (vProbes) contains
+  the array of probe IDs pointing to the user's logic cones to be SAT swept.
+  Finally, the optional command line (pCommLine) is an ABC command line
+  to be applied to the resulting GIA after SAT sweeping before it is 
+  grafted back into the original GIA manager. The return value is the status
+  (success/failure) and the array of original probes possibly pointing to the
+  new literals in the original GIA manager, corresponding to the user's
+  logic cones after sweeping, synthesis and grafting.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_SweeperFraig( Gia_Man_t * p, Vec_Int_t * vProbeIds, char * pCommLime, int nWords, int nConfs, int fVerify, int fVerbose )
+{
+    Gia_Man_t * pNew;
+    Vec_Int_t * vLits;
+    int ProbeId, i;
+    // sweeper is running
+    assert( Gia_SweeperIsRunning(p) );
+    // sweep the logic
+    pNew = Gia_SweeperSweep( p, vProbeIds, nWords, nConfs, fVerify, fVerbose );
+    if ( pNew == NULL )
+        return 0;
+    // execute command line
+    if ( pCommLime )
+    {
+        // set pNew to be current GIA in ABC
+        Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew );
+        // execute command line pCommLine using Abc_CmdCommandExecute()
+        Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), pCommLime );
+        // get pNew to be current GIA in ABC     
+        pNew = Abc_FrameGetGia( Abc_FrameGetGlobalFrame() );
+    }
+    // return logic back into the main manager
+    vLits = Gia_SweeperGraft( p, NULL, pNew );
+    Gia_ManStop( pNew );
+    // update the array of probes
+    Vec_IntForEachEntry( vProbeIds, ProbeId, i )
+        Gia_SweeperProbeUpdate( p, ProbeId, Vec_IntEntry(vLits, i) );
+    Vec_IntFree( vLits );        
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Executes given command line for the logic defined by the probes.]
+
+  Description [ ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_SweeperRun( Gia_Man_t * p, Vec_Int_t * vProbeIds, char * pCommLime, int fVerbose )
+{
+    Gia_Man_t * pNew;
+    Vec_Int_t * vLits;
+    int ProbeId, i;
+    // sweeper is running
+    assert( Gia_SweeperIsRunning(p) );
+    // sweep the logic
+    pNew = Gia_SweeperExtractUserLogic( p, vProbeIds, NULL, NULL );
+    // execute command line
+    if ( pCommLime )
+    {
+        if ( fVerbose )
+            printf( "GIA manager statistics before and after applying \"%s\":\n", pCommLime );
+        if ( fVerbose )
+            Gia_ManPrintStats( pNew, NULL );
+        // set pNew to be current GIA in ABC
+        Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew );
+        // execute command line pCommLine using Abc_CmdCommandExecute()
+        Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), pCommLime );
+        // get pNew to be current GIA in ABC     
+        pNew = Abc_FrameGetGia( Abc_FrameGetGlobalFrame() );
+        if ( fVerbose )
+            Gia_ManPrintStats( pNew, NULL );
+    }
+    // return logic back into the main manager
+    vLits = Gia_SweeperGraft( p, NULL, pNew );
+    Gia_ManStop( pNew );
+    // update the array of probes
+    Vec_IntForEachEntry( vProbeIds, ProbeId, i )
+        Gia_SweeperProbeUpdate( p, ProbeId, Vec_IntEntry(vLits, i) );
+    Vec_IntFree( vLits );        
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sweeper sweeper test.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_SweeperFraigTest( Gia_Man_t * pInit, int nWords, int nConfs, int fVerbose )
+{
+    Gia_Man_t * p, * pGia;
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vOuts;
+    int i;
+    // add one-hotness constraints
+    p = Gia_ManDupOneHot( pInit );
+    // create sweeper
+    Gia_SweeperStart( p );
+    // collect outputs and create conditions
+    vOuts = Vec_IntAlloc( Gia_ManPoNum(p) );
+    Gia_ManForEachPo( p, pObj, i )
+        if ( i < Gia_ManPoNum(p) - p->nConstrs )  // this is the user's output
+            Vec_IntPush( vOuts, Gia_SweeperProbeCreate( p,  Gia_ObjFaninLit0p(p, pObj) ) );
+        else // this is a constraint
+            Gia_SweeperCondPush( p, Gia_SweeperProbeCreate( p, Gia_ObjFaninLit0p(p, pObj) ) );
+    // perform the sweeping
+    pGia = Gia_SweeperSweep( p, vOuts, nWords, nConfs, fVerbose, 0 );
+//    pGia = Gia_ManDup( p );
+    Vec_IntFree( vOuts );
+    // sop the sweeper
+    Gia_SweeperStop( p );
+    Gia_ManStop( p );
+    return pGia;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaSwitch.c b/abc-build/src/aig/gia/giaSwitch.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaSwitch.c
@@ -0,0 +1,829 @@
+/**CFile****************************************************************
+
+  FileName    [giaSwitch.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Computing switching activity.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "giaAig.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// switching estimation parameters
+typedef struct Gia_ParSwi_t_ Gia_ParSwi_t;
+struct Gia_ParSwi_t_
+{
+    // user-controlled parameters
+    int            nWords;       // the number of machine words
+    int            nIters;       // the number of timeframes
+    int            nPref;        // the number of first timeframes to skip
+    int            nRandPiFactor;   // PI trans prob (-1=3/8; 0=1/2; 1=1/4; 2=1/8, etc)
+    int            fProbOne;     // collect probability of one
+    int            fProbTrans;   // collect probatility of Swiing
+    int            fVerbose;     // enables verbose output
+};
+
+typedef struct Gia_ManSwi_t_ Gia_ManSwi_t;
+struct Gia_ManSwi_t_
+{
+    Gia_Man_t *    pAig;
+    Gia_ParSwi_t * pPars; 
+    int            nWords;
+    // simulation information
+    unsigned *     pDataSim;     // simulation data
+    unsigned *     pDataSimCis;  // simulation data for CIs
+    unsigned *     pDataSimCos;  // simulation data for COs
+    int *          pData1;       // switching data
+};
+
+static inline unsigned * Gia_SwiData( Gia_ManSwi_t * p, int i )    { return p->pDataSim + i * p->nWords;    }
+static inline unsigned * Gia_SwiDataCi( Gia_ManSwi_t * p, int i )  { return p->pDataSimCis + i * p->nWords; }
+static inline unsigned * Gia_SwiDataCo( Gia_ManSwi_t * p, int i )  { return p->pDataSimCos + i * p->nWords; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSetDefaultParamsSwi( Gia_ParSwi_t * p )
+{
+    memset( p, 0, sizeof(Gia_ParSwi_t) );
+    p->nWords        =  10;  // the number of machine words of simulatation data 
+    p->nIters        =  48;  // the number of all timeframes to simulate
+    p->nPref         =  16;  // the number of first timeframes to skip when computing switching
+    p->nRandPiFactor =   0;  // primary input transition probability (-1=3/8; 0=1/2; 1=1/4; 2=1/8, etc)
+    p->fProbOne      =   0;  // compute probability of signal being one (if 0, compute probability of switching)
+    p->fProbTrans    =   1;  // compute signal transition probability (if 0, compute transition probability using probability of being one)
+    p->fVerbose      =   0;  // enables verbose output
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates fast simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_ManSwi_t * Gia_ManSwiCreate( Gia_Man_t * pAig, Gia_ParSwi_t * pPars )
+{
+    Gia_ManSwi_t * p;
+    p = ABC_ALLOC( Gia_ManSwi_t, 1 );
+    memset( p, 0, sizeof(Gia_ManSwi_t) );
+    p->pAig   = Gia_ManFront( pAig );
+    p->pPars  = pPars;
+    p->nWords = pPars->nWords;
+    p->pDataSim = ABC_ALLOC( unsigned, p->nWords * p->pAig->nFront );
+    p->pDataSimCis = ABC_ALLOC( unsigned, p->nWords * Gia_ManCiNum(p->pAig) );
+    p->pDataSimCos = ABC_ALLOC( unsigned, p->nWords * Gia_ManCoNum(p->pAig) );
+    p->pData1 = ABC_CALLOC( int, Gia_ManObjNum(pAig) );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSwiDelete( Gia_ManSwi_t * p )
+{
+    Gia_ManStop( p->pAig );
+    ABC_FREE( p->pData1 );
+    ABC_FREE( p->pDataSim );
+    ABC_FREE( p->pDataSimCis );
+    ABC_FREE( p->pDataSimCos );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSwiSimInfoRandom( Gia_ManSwi_t * p, unsigned * pInfo, int nProbNum )
+{
+    unsigned Mask;
+    int w, i;
+    if ( nProbNum == -1 )
+    { // 3/8 = 1/4 + 1/8
+        Mask = (Gia_ManRandom( 0 ) & Gia_ManRandom( 0 )) | 
+               (Gia_ManRandom( 0 ) & Gia_ManRandom( 0 ) & Gia_ManRandom( 0 ));
+        for ( w = p->nWords-1; w >= 0; w-- )
+            pInfo[w] ^= Mask;
+    }
+    else if ( nProbNum > 0 )
+    {
+        Mask = Gia_ManRandom( 0 );
+        for ( i = 0; i < nProbNum; i++ )
+            Mask &= Gia_ManRandom( 0 );
+        for ( w = p->nWords-1; w >= 0; w-- )
+            pInfo[w] ^= Mask;
+    }
+    else if ( nProbNum == 0 )
+    {
+        for ( w = p->nWords-1; w >= 0; w-- )
+            pInfo[w] = Gia_ManRandom( 0 );
+    }
+    else
+        assert( 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSwiSimInfoRandomShift( Gia_ManSwi_t * p, unsigned * pInfo, int nProbNum )
+{
+    unsigned Mask;
+    int w, i;
+    if ( nProbNum == -1 )
+    { // 3/8 = 1/4 + 1/8
+        Mask = (Gia_ManRandom( 0 ) & Gia_ManRandom( 0 )) | 
+               (Gia_ManRandom( 0 ) & Gia_ManRandom( 0 ) & Gia_ManRandom( 0 ));
+    }
+    else if ( nProbNum >= 0 )
+    {
+        Mask = Gia_ManRandom( 0 );
+        for ( i = 0; i < nProbNum; i++ )
+            Mask &= Gia_ManRandom( 0 );
+    }
+    else
+        assert( 0 );
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = (pInfo[w] << 16) | ((pInfo[w] ^ Mask) & 0xffff);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSwiSimInfoZero( Gia_ManSwi_t * p, unsigned * pInfo )
+{
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSwiSimInfoOne( Gia_ManSwi_t * p, unsigned * pInfo )
+{
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = ~0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSwiSimInfoCopy( Gia_ManSwi_t * p, unsigned * pInfo, unsigned * pInfo0 )
+{
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSwiSimInfoCopyShift( Gia_ManSwi_t * p, unsigned * pInfo, unsigned * pInfo0 )
+{
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = (pInfo[w] << 16) | (pInfo0[w] & 0xffff);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSwiSimulateCi( Gia_ManSwi_t * p, Gia_Obj_t * pObj, int iCi )
+{
+    unsigned * pInfo  = Gia_SwiData( p, Gia_ObjValue(pObj) );
+    unsigned * pInfo0 = Gia_SwiDataCi( p, iCi );
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSwiSimulateCo( Gia_ManSwi_t * p, int iCo, Gia_Obj_t * pObj )
+{
+    unsigned * pInfo  = Gia_SwiDataCo( p, iCo );
+    unsigned * pInfo0 = Gia_SwiData( p, Gia_ObjDiff0(pObj) );
+    int w;
+    if ( Gia_ObjFaninC0(pObj) )
+        for ( w = p->nWords-1; w >= 0; w-- )
+            pInfo[w] = ~pInfo0[w];
+    else 
+        for ( w = p->nWords-1; w >= 0; w-- )
+            pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSwiSimulateNode( Gia_ManSwi_t * p, Gia_Obj_t * pObj )
+{
+    unsigned * pInfo  = Gia_SwiData( p, Gia_ObjValue(pObj) );
+    unsigned * pInfo0 = Gia_SwiData( p, Gia_ObjDiff0(pObj) );
+    unsigned * pInfo1 = Gia_SwiData( p, Gia_ObjDiff1(pObj) );
+    int w;
+    if ( Gia_ObjFaninC0(pObj) )
+    {
+        if (  Gia_ObjFaninC1(pObj) )
+            for ( w = p->nWords-1; w >= 0; w-- )
+                pInfo[w] = ~(pInfo0[w] | pInfo1[w]);
+        else 
+            for ( w = p->nWords-1; w >= 0; w-- )
+                pInfo[w] = ~pInfo0[w] & pInfo1[w];
+    }
+    else 
+    {
+        if (  Gia_ObjFaninC1(pObj) )
+            for ( w = p->nWords-1; w >= 0; w-- )
+                pInfo[w] = pInfo0[w] & ~pInfo1[w];
+        else 
+            for ( w = p->nWords-1; w >= 0; w-- )
+                pInfo[w] = pInfo0[w] & pInfo1[w];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSwiSimInfoInit( Gia_ManSwi_t * p )
+{
+    int i = 0;
+    for ( ; i < Gia_ManPiNum(p->pAig); i++ )
+        Gia_ManSwiSimInfoRandom( p, Gia_SwiDataCi(p, i), 0 );
+    for ( ; i < Gia_ManCiNum(p->pAig); i++ )
+        Gia_ManSwiSimInfoZero( p, Gia_SwiDataCi(p, i) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSwiSimInfoTransfer( Gia_ManSwi_t * p, int nProbNum )
+{
+    int i = 0, nShift = Gia_ManPoNum(p->pAig)-Gia_ManPiNum(p->pAig);
+    for ( ; i < Gia_ManPiNum(p->pAig); i++ )
+        Gia_ManSwiSimInfoRandom( p, Gia_SwiDataCi(p, i), nProbNum );
+    for ( ; i < Gia_ManCiNum(p->pAig); i++ )
+        Gia_ManSwiSimInfoCopy( p, Gia_SwiDataCi(p, i), Gia_SwiDataCo(p, nShift+i) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSwiSimInfoTransferShift( Gia_ManSwi_t * p, int nProbNum )
+{
+    int i = 0, nShift = Gia_ManPoNum(p->pAig)-Gia_ManPiNum(p->pAig);
+    for ( ; i < Gia_ManPiNum(p->pAig); i++ )
+        Gia_ManSwiSimInfoRandomShift( p, Gia_SwiDataCi(p, i), nProbNum );
+    for ( ; i < Gia_ManCiNum(p->pAig); i++ )
+        Gia_ManSwiSimInfoCopyShift( p, Gia_SwiDataCi(p, i), Gia_SwiDataCo(p, nShift+i) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManSwiSimInfoCountOnes( Gia_ManSwi_t * p, int iPlace )
+{
+    unsigned * pInfo;
+    int w, Counter = 0;
+    pInfo = Gia_SwiData( p, iPlace );
+    for ( w = p->nWords-1; w >= 0; w-- )
+        Counter += Gia_WordCountOnes( pInfo[w] );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManSwiSimInfoCountTrans( Gia_ManSwi_t * p, int iPlace )
+{
+    unsigned * pInfo;
+    int w, Counter = 0;
+    pInfo = Gia_SwiData( p, iPlace );
+    for ( w = p->nWords-1; w >= 0; w-- )
+        Counter += 2*Gia_WordCountOnes( (pInfo[w] ^ (pInfo[w] >> 16)) & 0xffff );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManSwiSimulateRound( Gia_ManSwi_t * p, int fCount )
+{
+    Gia_Obj_t * pObj;
+    int i;//, iCis = 0, iCos = 0;
+    assert( p->pAig->nFront > 0 );
+    assert( Gia_ManConst0(p->pAig)->Value == 0 );
+    Gia_ManSwiSimInfoZero( p, Gia_SwiData(p, 0) );
+    Gia_ManForEachObj1( p->pAig, pObj, i )
+    {
+        if ( Gia_ObjIsAndOrConst0(pObj) )
+        {
+            assert( Gia_ObjValue(pObj) < p->pAig->nFront );
+            Gia_ManSwiSimulateNode( p, pObj );
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+        {
+            assert( Gia_ObjValue(pObj) == GIA_NONE );
+//            Gia_ManSwiSimulateCo( p, iCos++, pObj );
+            Gia_ManSwiSimulateCo( p, Gia_ObjCioId(pObj), pObj );
+        }
+        else // if ( Gia_ObjIsCi(pObj) )
+        {
+            assert( Gia_ObjValue(pObj) < p->pAig->nFront );
+//            Gia_ManSwiSimulateCi( p, pObj, iCis++ );
+            Gia_ManSwiSimulateCi( p, pObj, Gia_ObjCioId(pObj) );
+        }
+        if ( fCount && !Gia_ObjIsCo(pObj) )
+        {
+            if ( p->pPars->fProbTrans )
+                p->pData1[i] += Gia_ManSwiSimInfoCountTrans( p, Gia_ObjValue(pObj) );
+            else 
+                p->pData1[i] += Gia_ManSwiSimInfoCountOnes( p, Gia_ObjValue(pObj) );
+        }
+    }
+//    assert( Gia_ManCiNum(p->pAig) == iCis );
+//    assert( Gia_ManCoNum(p->pAig) == iCos );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes switching activity of one node.]
+
+  Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Gia_ManSwiComputeSwitching( int nOnes, int nSimWords )
+{
+    int nTotal = 32 * nSimWords;
+    return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes switching activity of one node.]
+
+  Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+float Gia_ManSwiComputeProbOne( int nOnes, int nSimWords )
+{
+    int nTotal = 32 * nSimWords;
+    return (float)nOnes / nTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManSwiSimulate( Gia_Man_t * pAig, Gia_ParSwi_t * pPars )
+{
+    Gia_ManSwi_t * p;
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vSwitching;
+    float * pSwitching;
+    int i;
+    abctime clk, clkTotal = Abc_Clock();
+    if ( pPars->fProbOne && pPars->fProbTrans )
+        printf( "Conflict of options: Can either compute probability of 1, or probability of switching by observing transitions.\n" );
+    // create manager
+    clk = Abc_Clock();
+    p = Gia_ManSwiCreate( pAig, pPars );
+    if ( pPars->fVerbose )
+    {
+        printf( "Obj = %8d (%8d). F = %6d. ", 
+            pAig->nObjs, Gia_ManCiNum(pAig) + Gia_ManAndNum(pAig), p->pAig->nFront );
+        printf( "AIG = %7.2f MB. F-mem = %7.2f MB. Other = %7.2f MB.  ", 
+            12.0*Gia_ManObjNum(p->pAig)/(1<<20), 
+            4.0*p->nWords*p->pAig->nFront/(1<<20), 
+            4.0*p->nWords*(Gia_ManCiNum(p->pAig) + Gia_ManCoNum(p->pAig))/(1<<20) );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    // perform simulation
+    Gia_ManRandom( 1 );
+    Gia_ManSwiSimInfoInit( p );
+    for ( i = 0; i < pPars->nIters; i++ )
+    {
+        Gia_ManSwiSimulateRound( p, i >= pPars->nPref );
+        if ( i == pPars->nIters - 1 )
+            break;
+        if ( pPars->fProbTrans )
+            Gia_ManSwiSimInfoTransferShift( p, pPars->nRandPiFactor );
+        else
+            Gia_ManSwiSimInfoTransfer( p, pPars->nRandPiFactor );
+    }
+    if ( pPars->fVerbose )
+    {
+        printf( "Simulated %d frames with %d words. ", pPars->nIters, pPars->nWords );
+        ABC_PRT( "Simulation time", Abc_Clock() - clkTotal );
+    }
+    // derive the result
+    vSwitching = Vec_IntStart( Gia_ManObjNum(pAig) );
+    pSwitching = (float *)vSwitching->pArray;
+    if ( pPars->fProbOne )
+    {
+        Gia_ManForEachObj( pAig, pObj, i )
+            pSwitching[i] = Gia_ManSwiComputeProbOne( p->pData1[i], pPars->nWords*(pPars->nIters-pPars->nPref) );
+        Gia_ManForEachCo( pAig, pObj, i )
+        {
+            if ( Gia_ObjFaninC0(pObj) )
+                pSwitching[Gia_ObjId(pAig,pObj)] = (float)1.0-pSwitching[Gia_ObjId(pAig,Gia_ObjFanin0(pObj))];
+            else
+                pSwitching[Gia_ObjId(pAig,pObj)] = pSwitching[Gia_ObjId(pAig,Gia_ObjFanin0(pObj))];
+        }
+    }
+    else if ( pPars->fProbTrans )
+    {
+        Gia_ManForEachObj( pAig, pObj, i )
+            pSwitching[i] = Gia_ManSwiComputeProbOne( p->pData1[i], pPars->nWords*(pPars->nIters-pPars->nPref) );
+    }
+    else
+    {
+        Gia_ManForEachObj( pAig, pObj, i )
+            pSwitching[i] = Gia_ManSwiComputeSwitching( p->pData1[i], pPars->nWords*(pPars->nIters-pPars->nPref) );
+    }
+/*
+    printf( "PI: " );
+    Gia_ManForEachPi( pAig, pObj, i )
+        printf( "%d=%d (%f)  ", i, p->pData1[Gia_ObjId(pAig,pObj)], pSwitching[Gia_ObjId(pAig,pObj)] );
+    printf( "\n" );
+
+    printf( "LO: " );
+    Gia_ManForEachRo( pAig, pObj, i )
+        printf( "%d=%d (%f)  ", i, p->pData1[Gia_ObjId(pAig,pObj)], pSwitching[Gia_ObjId(pAig,pObj)] );
+    printf( "\n" );
+
+    printf( "PO: " );
+    Gia_ManForEachPo( pAig, pObj, i )
+        printf( "%d=%d (%f)  ", i, p->pData1[Gia_ObjId(pAig,pObj)], pSwitching[Gia_ObjId(pAig,pObj)] );
+    printf( "\n" );
+
+    printf( "LI: " );
+    Gia_ManForEachRi( pAig, pObj, i )
+        printf( "%d=%d (%f)  ", i, p->pData1[Gia_ObjId(pAig,pObj)], pSwitching[Gia_ObjId(pAig,pObj)] );
+    printf( "\n" );
+*/
+    Gia_ManSwiDelete( p );
+    return vSwitching;
+
+}
+/**Function*************************************************************
+
+  Synopsis    [Computes probability of switching (or of being 1).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManComputeSwitchProbs( Gia_Man_t * pGia, int nFrames, int nPref, int fProbOne )
+{
+    Gia_ParSwi_t Pars, * pPars = &Pars;
+    // set the default parameters
+    Gia_ManSetDefaultParamsSwi( pPars ); 
+    // override some of the defaults
+    pPars->nIters   = nFrames;  // set number of total timeframes
+    if ( Abc_FrameReadFlag("seqsimframes") )
+        pPars->nIters = atoi( Abc_FrameReadFlag("seqsimframes") );
+    pPars->nPref    = nPref;    // set number of first timeframes to skip  
+    // decide what should be computed
+    if ( fProbOne )
+    {
+        // if the user asked to compute propability of 1, we do not need transition information
+        pPars->fProbOne   = 1;  // enable computing probabiblity of being one
+        pPars->fProbTrans = 0;  // disable computing transition probability 
+    }
+    else
+    {
+        // if the user asked for transition propabability, we do not need to compute probability of 1
+        pPars->fProbOne   = 0;  // disable computing probabiblity of being one
+        pPars->fProbTrans = 1;  // enable computing transition probability 
+    }
+    // perform the computation of switching activity
+    return Gia_ManSwiSimulate( pGia, pPars );
+}
+Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * pAig, int nFrames, int nPref, int fProbOne )
+{
+    Vec_Int_t * vSwitching, * vResult;
+    Gia_Man_t * p;
+    Aig_Obj_t * pObj;
+    int i;
+    // translate AIG into the intermediate form (takes care of choices if present!)
+    p = Gia_ManFromAigSwitch( pAig );
+    // perform the computation of switching activity
+    vSwitching = Gia_ManComputeSwitchProbs( p, nFrames, nPref, fProbOne );
+    // transfer the computed result to the original AIG
+    vResult = Vec_IntStart( Aig_ManObjNumMax(pAig) );
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+//        if ( Aig_ObjIsCo(pObj) )
+//            printf( "%d=%f\n", i, Abc_Int2Float( Vec_IntEntry(vSwitching, Abc_Lit2Var(pObj->iData)) ) );
+        Vec_IntWriteEntry( vResult, i, Vec_IntEntry(vSwitching, Abc_Lit2Var(pObj->iData)) );
+    }
+    // delete intermediate results
+    Vec_IntFree( vSwitching );
+    Gia_ManStop( p );
+    return vResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes probability of switching (or of being 1).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Gia_ManEvaluateSwitching( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    float SwitchTotal = 0.0;
+    int i;
+    assert( p->pSwitching );
+    ABC_FREE( p->pRefs );
+    Gia_ManCreateRefs( p );
+    Gia_ManForEachObj( p, pObj, i )
+        SwitchTotal += (float)Gia_ObjRefNum(p, pObj) * p->pSwitching[i] / 255;
+    return SwitchTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes probability of switching (or of being 1).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+float Gia_ManComputeSwitching( Gia_Man_t * p, int nFrames, int nPref, int fProbOne )
+{
+    Gia_Man_t * pDfs;
+    Gia_Obj_t * pObj, * pObjDfs;
+    Vec_Int_t * vSwitching;
+    float * pSwitching, Switch, SwitchTotal = 0.0;
+    int i;
+    // derives the DFS ordered AIG
+    if ( Gia_ManHasMapping(p) )
+        Gia_ManSetRefsMapped(p);
+    else
+        Gia_ManCreateRefs( p );
+//    pDfs = Gia_ManDupOrderDfs( p );
+    pDfs = Gia_ManDup( p );
+    assert( Gia_ManObjNum(pDfs) == Gia_ManObjNum(p) );
+    // perform the computation of switching activity
+    vSwitching = Gia_ManComputeSwitchProbs( pDfs, nFrames, nPref, fProbOne );
+    // transfer the computed result to the original AIG
+    ABC_FREE( p->pSwitching );
+    p->pSwitching = ABC_CALLOC( unsigned char, Gia_ManObjNum(p) );
+    pSwitching = (float *)vSwitching->pArray;
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        pObjDfs = Gia_ObjFromLit( pDfs, pObj->Value );
+        Switch = pSwitching[ Gia_ObjId(pDfs, pObjDfs) ];
+        p->pSwitching[i] = (char)((Switch >= 1.0) ? 255 : (int)((0.002 + Switch) * 255)); // 0.00196 = (1/255)/2
+        if ( Gia_ObjIsCi(pObj) || (Gia_ObjIsAnd(pObj) && (!Gia_ManHasMapping(p) || Gia_ObjIsLut(p, i))) )
+        {
+            SwitchTotal += (float)Gia_ObjRefNum(p, pObj) * p->pSwitching[i] / 255;
+//            printf( "%d = %.2f\n", i, (float)Gia_ObjRefNum(p, pObj) * p->pSwitching[i] / 255 );            
+        }
+    }
+    Vec_IntFree( vSwitching );
+    Gia_ManStop( pDfs );
+    return SwitchTotal;
+}
+*/
+float Gia_ManComputeSwitching( Gia_Man_t * p, int nFrames, int nPref, int fProbOne )
+{
+    Vec_Int_t * vSwitching = Gia_ManComputeSwitchProbs( p, nFrames, nPref, fProbOne );
+    float * pSwi = (float *)Vec_IntArray(vSwitching), SwiTotal = 0;
+    Gia_Obj_t * pObj;
+    int i, k, iFan;
+    if ( Gia_ManHasMapping(p) )
+    {
+        Gia_ManForEachLut( p, i )
+            Gia_LutForEachFanin( p, i, iFan, k )
+                SwiTotal += pSwi[iFan];
+    }
+    else
+    {
+        Gia_ManForEachAnd( p, pObj, i )
+            SwiTotal += pSwi[Gia_ObjFaninId0(pObj, i)] + pSwi[Gia_ObjFaninId1(pObj, i)];
+    }
+    Vec_IntFree( vSwitching );
+    return SwiTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determine probability of being 1 at the outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Flt_t * Gia_ManPrintOutputProb( Gia_Man_t * p )
+{
+    Vec_Flt_t * vSimData;
+    Gia_Man_t * pDfs = Gia_ManDup( p );
+    assert( Gia_ManObjNum(pDfs) == Gia_ManObjNum(p) );
+    vSimData = (Vec_Flt_t *)Gia_ManComputeSwitchProbs( pDfs, (Gia_ManRegNum(p) ? 16 : 1), 0, 1 );
+    Gia_ManStop( pDfs );
+    return vSimData;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaTim.c b/abc-build/src/aig/gia/giaTim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaTim.c
@@ -0,0 +1,633 @@
+/**CFile****************************************************************
+
+  FileName    [giaTim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Procedures with hierarchy/timing manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaTim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "misc/tim/tim.h"
+#include "proof/cec/cec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG in the DFS order while putting CIs first.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupNormalize( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    pNew->nConstrs = p->nConstrs;
+    assert( Gia_ManIsNormalized(pNew) );
+    Gia_ManDupRemapEquiv( pNew, p );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the ordering of AIG objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManOrderWithBoxes_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return 0;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+    {
+        p->iData2 = Gia_ObjCioId(pObj);
+        return 1;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) )
+        if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)), vNodes ) )
+            return 1;
+    if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin0(pObj), vNodes ) )
+        return 1;
+    if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin1(pObj), vNodes ) )
+        return 1;
+    Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+    return 0;
+}
+Vec_Int_t * Gia_ManOrderWithBoxes( Gia_Man_t * p )
+{
+    Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
+    Vec_Int_t * vNodes;
+    Gia_Obj_t * pObj;
+    int i, k, curCi, curCo;
+    assert( pManTime != NULL );
+    assert( Gia_ManIsNormalized( p ) );
+    // start trav IDs
+    Gia_ManIncrementTravId( p );
+    // start the array
+    vNodes = Vec_IntAlloc( Gia_ManObjNum(p) );
+    // include constant
+    Vec_IntPush( vNodes, 0 );
+    Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+    // include primary inputs
+    for ( i = 0; i < Tim_ManPiNum(pManTime); i++ )
+    {
+        pObj = Gia_ManPi( p, i );
+        Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+        Gia_ObjSetTravIdCurrent( p, pObj );
+        assert( Gia_ObjId(p, pObj) == i+1 );
+    }
+    // for each box, include box nodes
+    curCi = Tim_ManPiNum(pManTime);
+    curCo = 0;
+    for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ )
+    {
+        // add internal nodes
+        for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ )
+        {
+            pObj = Gia_ManPo( p, curCo + k );
+            if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin0(pObj), vNodes ) )
+            {
+                int iCiNum  = p->iData2;
+                int iBoxNum = Tim_ManBoxFindFromCiNum( pManTime, iCiNum );
+                printf( "The command has to terminate. Boxes are not in a topological order.\n" );
+                printf( "The following information may help debugging (numbers are 0-based):\n" );
+                printf( "Input %d of BoxA %d (1stCI = %d; 1stCO = %d) has TFI with CI %d,\n", 
+                    k, i, Tim_ManBoxOutputFirst(pManTime, i), Tim_ManBoxInputFirst(pManTime, i), iCiNum );
+                printf( "which corresponds to output %d of BoxB %d (1stCI = %d; 1stCO = %d).\n", 
+                    iCiNum - Tim_ManBoxOutputFirst(pManTime, iBoxNum), iBoxNum, 
+                    Tim_ManBoxOutputFirst(pManTime, iBoxNum), Tim_ManBoxInputFirst(pManTime, iBoxNum) );
+                printf( "In a correct topological order, BoxB should precede BoxA.\n" );
+                Vec_IntFree( vNodes );
+                p->iData2 = 0;
+                return NULL;
+            }
+        }
+        // add POs corresponding to box inputs
+        for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ )
+        {
+            pObj = Gia_ManPo( p, curCo + k );
+            Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+        }
+        curCo += Tim_ManBoxInputNum(pManTime, i);
+        // add PIs corresponding to box outputs
+        for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ )
+        {
+            pObj = Gia_ManPi( p, curCi + k );
+            Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+            Gia_ObjSetTravIdCurrent( p, pObj );
+        }
+        curCi += Tim_ManBoxOutputNum(pManTime, i);
+    }
+    // add remaining nodes
+    for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ )
+    {
+        pObj = Gia_ManPo( p, i );
+        Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin0(pObj), vNodes );
+    }
+    // add POs
+    for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ )
+    {
+        pObj = Gia_ManPo( p, i );
+        Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+    }
+    curCo += Tim_ManPoNum(pManTime);
+    // verify counts
+    assert( curCi == Gia_ManPiNum(p) );
+    assert( curCo == Gia_ManPoNum(p) );
+    assert( Vec_IntSize(vNodes) == Gia_ManObjNum(p) );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG according to the timing manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupUnnormalize( Gia_Man_t * p )
+{
+    Vec_Int_t * vNodes;
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    vNodes = Gia_ManOrderWithBoxes( p );
+    if ( vNodes == NULL )
+        return NULL;
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    if ( Gia_ManHasChoices(p) )
+        pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    Gia_ManForEachObjVec( vNodes, p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+            if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) )
+                pNew->pSibls[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var(Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))->Value);        
+        }
+        else if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Gia_ManAppendCi( pNew );
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+        else if ( Gia_ObjIsConst0(pObj) )
+            pObj->Value = 0;
+        else assert( 0 );
+    }
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    Vec_IntFree( vNodes );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Remaps the AIG from the old manager into the new manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCleanupRemap( Gia_Man_t * p, Gia_Man_t * pGia )
+{
+    Gia_Obj_t * pObj, * pObjGia;
+    int i, iPrev;
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        iPrev = Gia_ObjValue(pObj);
+        if ( iPrev == ~0 )
+            continue;
+        pObjGia = Gia_ManObj( pGia, Abc_Lit2Var(iPrev) );
+        if ( pObjGia->Value == ~0 )
+            Gia_ObjSetValue( pObj, pObjGia->Value ); 
+        else
+            Gia_ObjSetValue( pObj, Abc_LitNotCond(pObjGia->Value, Abc_LitIsCompl(iPrev)) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes AIG with boxes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManDupCollapse_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Man_t * pNew )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    assert( Gia_ObjIsAnd(pObj) );
+    if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) )
+        Gia_ManDupCollapse_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)), pNew );
+    Gia_ManDupCollapse_rec( p, Gia_ObjFanin0(pObj), pNew );
+    Gia_ManDupCollapse_rec( p, Gia_ObjFanin1(pObj), pNew );
+//    assert( !~pObj->Value );
+    pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) )
+        pNew->pSibls[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var(Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))->Value);        
+}
+Gia_Man_t * Gia_ManDupCollapse( Gia_Man_t * p, Gia_Man_t * pBoxes, Vec_Int_t * vBoxPres )
+{
+    Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pObjBox;
+    int i, k, curCi, curCo;
+    assert( Gia_ManRegNum(p) == 0 );
+    assert( Gia_ManPiNum(p) == Tim_ManPiNum(pManTime) + Gia_ManPoNum(pBoxes) );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    if ( Gia_ManHasChoices(p) )
+        pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    Gia_ManHashAlloc( pNew );
+    // copy const and real PIs
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+    for ( i = 0; i < Tim_ManPiNum(pManTime); i++ )
+    {
+        pObj = Gia_ManPi( p, i );
+        pObj->Value = Gia_ManAppendCi(pNew);
+        Gia_ObjSetTravIdCurrent( p, pObj );
+    }
+    // create logic for each box
+    curCi = Tim_ManPiNum(pManTime);
+    curCo = 0;
+    for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ )
+    {
+        // clean boxes
+        Gia_ManIncrementTravId( pBoxes );
+        Gia_ObjSetTravIdCurrent( pBoxes, Gia_ManConst0(pBoxes) );
+        Gia_ManConst0(pBoxes)->Value = 0;
+        // add internal nodes
+        if ( Tim_ManBoxIsBlack(pManTime, i) )
+        {
+            int fSkip = (vBoxPres != NULL && !Vec_IntEntry(vBoxPres, i));
+            for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ )
+            {
+                pObj = Gia_ManPo( p, curCo + k );
+                Gia_ManDupCollapse_rec( p, Gia_ObjFanin0(pObj), pNew );
+                pObj->Value = fSkip ? -1 : Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+            }
+            for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ )
+            {
+                pObj = Gia_ManPi( p, curCi + k );
+                pObj->Value = fSkip ? 0 : Gia_ManAppendCi(pNew);
+                Gia_ObjSetTravIdCurrent( p, pObj );
+            }
+        }
+        else
+        {
+            for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ )
+            {
+                // build logic
+                pObj = Gia_ManPo( p, curCo + k );
+                Gia_ManDupCollapse_rec( p, Gia_ObjFanin0(pObj), pNew );
+                // transfer to the PI
+                pObjBox = Gia_ManPi( pBoxes, k );
+                pObjBox->Value = Gia_ObjFanin0Copy(pObj);
+                Gia_ObjSetTravIdCurrent( pBoxes, pObjBox );
+            }
+            for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ )
+            {
+                // build logic
+                pObjBox = Gia_ManPo( pBoxes, curCi - Tim_ManPiNum(pManTime) + k );
+                Gia_ManDupCollapse_rec( pBoxes, Gia_ObjFanin0(pObjBox), pNew );
+                // transfer to the PI
+                pObj = Gia_ManPi( p, curCi + k );
+                pObj->Value = Gia_ObjFanin0Copy(pObjBox);
+                Gia_ObjSetTravIdCurrent( p, pObj );
+            }
+        }
+        curCo += Tim_ManBoxInputNum(pManTime, i);
+        curCi += Tim_ManBoxOutputNum(pManTime, i);
+    }
+    // add remaining nodes
+    for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ )
+    {
+        pObj = Gia_ManPo( p, i );
+        Gia_ManDupCollapse_rec( p, Gia_ObjFanin0(pObj), pNew );
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+    curCo += Tim_ManPoNum(pManTime);
+    // verify counts
+    assert( curCi == Gia_ManPiNum(p) );
+    assert( curCo == Gia_ManPoNum(p) );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    Gia_ManHashStop( pNew );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManCleanupRemap( p, pTemp );
+    Gia_ManStop( pTemp );
+    assert( Tim_ManPoNum(pManTime) == Gia_ManPoNum(pNew) );
+    assert( Tim_ManPiNum(pManTime) == Gia_ManPiNum(pNew) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes level with boxes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManLevelWithBoxes_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return 0;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+        return 1;
+    assert( Gia_ObjIsAnd(pObj) );
+    if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) )
+        Gia_ManLevelWithBoxes_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)) );
+    if ( Gia_ManLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) ) )
+        return 1;
+    if ( Gia_ManLevelWithBoxes_rec( p, Gia_ObjFanin1(pObj) ) )
+        return 1;
+    Gia_ObjSetAndLevel( p, pObj );
+    return 0;
+}
+int Gia_ManLevelWithBoxes( Gia_Man_t * p )
+{
+    int nAnd2Delay = p->nAnd2Delay ? p->nAnd2Delay : 1;
+    Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
+    Gia_Obj_t * pObj, * pObjIn;
+    int i, k, j, curCi, curCo, LevelMax;
+    assert( Gia_ManRegNum(p) == 0 );
+    // copy const and real PIs
+    Gia_ManCleanLevels( p, Gia_ManObjNum(p) );
+    Gia_ObjSetLevel( p, Gia_ManConst0(p), 0 );
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+    for ( i = 0; i < Tim_ManPiNum(pManTime); i++ )
+    {
+        pObj = Gia_ManPi( p, i );
+        Gia_ObjSetLevel( p, pObj, Tim_ManGetCiArrival(pManTime, i) / nAnd2Delay );
+        Gia_ObjSetTravIdCurrent( p, pObj );
+    }
+    // create logic for each box
+    curCi = Tim_ManPiNum(pManTime);
+    curCo = 0;
+    for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ )
+    {
+        int nBoxInputs  = Tim_ManBoxInputNum( pManTime, i );
+        int nBoxOutputs = Tim_ManBoxOutputNum( pManTime, i );
+        float * pDelayTable = Tim_ManBoxDelayTable( pManTime, i );
+        // compute level for TFI of box inputs
+        for ( k = 0; k < nBoxInputs; k++ )
+        {
+            pObj = Gia_ManPo( p, curCo + k );
+            if ( Gia_ManLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) ) )
+            {
+                printf( "Boxes are not in a topological order. Switching to level computation without boxes.\n" );
+                return Gia_ManLevelNum( p );
+            }
+            // set box input level
+            Gia_ObjSetCoLevel( p, pObj );
+        }
+        // compute level for box outputs
+        for ( k = 0; k < nBoxOutputs; k++ )
+        {
+            pObj = Gia_ManPi( p, curCi + k );
+            Gia_ObjSetTravIdCurrent( p, pObj );
+            // evaluate delay of this output
+            LevelMax = 0;
+            assert( nBoxInputs == (int)pDelayTable[1] );
+            for ( j = 0; j < nBoxInputs && (pObjIn = Gia_ManPo(p, curCo + j)); j++ )
+                if ( (int)pDelayTable[3+k*nBoxInputs+j] != -ABC_INFINITY )
+                    LevelMax = Abc_MaxInt( LevelMax, Gia_ObjLevel(p, pObjIn) + ((int)pDelayTable[3+k*nBoxInputs+j] / nAnd2Delay) );
+            // set box output level
+            Gia_ObjSetLevel( p, pObj, LevelMax );
+        }
+        curCo += nBoxInputs;
+        curCi += nBoxOutputs;
+    }
+    // add remaining nodes
+    p->nLevels = 0;
+    for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ )
+    {
+        pObj = Gia_ManPo( p, i );
+        Gia_ManLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) );
+        Gia_ObjSetCoLevel( p, pObj );
+        p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) );
+    }
+    curCo += Tim_ManPoNum(pManTime);
+    // verify counts
+    assert( curCi == Gia_ManPiNum(p) );
+    assert( curCo == Gia_ManPoNum(p) );
+//    printf( "Max level is %d.\n", p->nLevels );
+    return p->nLevels;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verify XAIG against its spec.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManVerifyWithBoxes( Gia_Man_t * pGia, void * pParsInit )
+{
+    int fVerbose =  1;
+    int Status   = -1;
+    Gia_Man_t * pSpec, * pGia0, * pGia1, * pMiter;
+    Vec_Int_t * vBoxPres = NULL;
+    if ( pGia->pSpec == NULL )
+    {
+        printf( "Spec file is not given. Use standard flow.\n" );
+        return Status;
+    }
+    if ( pGia->pManTime == NULL )
+    {
+        printf( "Design has no tim manager. Use standard flow.\n" );
+        return Status;
+    }
+    if ( pGia->pAigExtra == NULL )
+    {
+        printf( "Design has no box logic. Use standard flow.\n" );
+        return Status;
+    }
+    // read original AIG
+    pSpec = Gia_AigerRead( pGia->pSpec, 0, 0 );
+    if ( pSpec->pManTime == NULL )
+    {
+        printf( "Spec has no tim manager. Use standard flow.\n" );
+        return Status;
+    }
+    if ( pSpec->pAigExtra == NULL )
+    {
+        printf( "Spec has no box logic. Use standard flow.\n" );
+        return Status;
+    }
+    // if timing managers have different number of black boxes,
+    // it is possible that some of the boxes are swept away
+    if ( Tim_ManBlackBoxNum( (Tim_Man_t *)pSpec->pManTime ) > 0 )
+    {
+        // specification cannot have fewer boxes than implementation
+        if ( Tim_ManBoxNum( (Tim_Man_t *)pSpec->pManTime ) < Tim_ManBoxNum( (Tim_Man_t *)pGia->pManTime ) )
+        {
+            printf( "Spec has more boxes than the design. Cannot proceed.\n" );
+            return Status;
+        }
+        // to align the boxes, find what boxes of pSpec are dropped in pGia
+        if ( Tim_ManBoxNum( (Tim_Man_t *)pSpec->pManTime ) != Tim_ManBoxNum( (Tim_Man_t *)pGia->pManTime ) )
+        {
+            vBoxPres = Tim_ManAlignTwo( (Tim_Man_t *)pSpec->pManTime, (Tim_Man_t *)pGia->pManTime );
+            if ( vBoxPres == NULL )
+            {
+                printf( "Boxes of spec and design cannot be aligned. Cannot proceed.\n" );
+                return Status;
+            }
+        }
+    }
+    // collapse two designs
+    pGia0 = Gia_ManDupCollapse( pSpec, pSpec->pAigExtra, vBoxPres );
+    pGia1 = Gia_ManDupCollapse( pGia,  pGia->pAigExtra,  NULL  );
+    Vec_IntFreeP( &vBoxPres );
+    // compute the miter
+    pMiter = Gia_ManMiter( pGia0, pGia1, 0, 1, 0, 0, fVerbose );
+    if ( pMiter )
+    {
+        Cec_ParCec_t ParsCec, * pPars = &ParsCec;
+        Cec_ManCecSetDefaultParams( pPars );
+        pPars->fVerbose = fVerbose;
+        if ( pParsInit )
+            memcpy( pPars, pParsInit, sizeof(Cec_ParCec_t) );
+        Status = Cec_ManVerify( pMiter, pPars );
+        Gia_ManStop( pMiter );
+        if ( pPars->iOutFail >= 0 )
+            Abc_Print( 1, "Verification failed for at least one output (%d).\n", pPars->iOutFail );
+    }
+    Gia_ManStop( pGia0 );
+    Gia_ManStop( pGia1 );
+    Gia_ManStop( pSpec );
+    return Status;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Update hierarchy/timing manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Gia_ManUpdateTimMan( Gia_Man_t * p, Vec_Int_t * vBoxPres )
+{
+    Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
+    assert( pManTime != NULL );
+    assert( Tim_ManBoxNum(pManTime) == Vec_IntSize(vBoxPres) );
+    return Tim_ManTrim( pManTime, vBoxPres );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Update AIG of the holes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManUpdateExtraAig( void * pTime, Gia_Man_t * p, Vec_Int_t * vBoxPres )
+{
+    Gia_Man_t * pNew = NULL;
+    Tim_Man_t * pManTime = (Tim_Man_t *)pTime;
+    Vec_Int_t * vOutPres = Vec_IntAlloc( 100 );
+    int i, k, curPo = 0;
+    assert( Vec_IntSize(vBoxPres) == Tim_ManBoxNum(pManTime) );
+    assert( Gia_ManPoNum(p) == Tim_ManCiNum(pManTime) - Tim_ManPiNum(pManTime) );
+    for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ )
+    {
+        for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ )
+            Vec_IntPush( vOutPres, Vec_IntEntry(vBoxPres, i) );
+        curPo += Tim_ManBoxOutputNum(pManTime, i);
+    }
+    assert( curPo == Gia_ManPoNum(p) );
+//    if ( Vec_IntSize(vOutPres) > 0 )
+        pNew = Gia_ManDupOutputVec( p, vOutPres );
+    Vec_IntFree( vOutPres );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaTis.c b/abc-build/src/aig/gia/giaTis.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaTis.c
@@ -0,0 +1,213 @@
+/**CFile****************************************************************
+
+  FileName    [giaTis.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Technology independent synthesis.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaTis.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives GIA with MUXes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManTisDupMuxes( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pFan0, * pFan1, * pFanC;
+    int i;
+    assert( p->pMuxes == NULL );
+    ABC_FREE( p->pRefs );
+    Gia_ManCreateRefs( p ); 
+    // start the new manager
+    pNew = Gia_ManStart( 5000 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc );
+    // create constant
+    Gia_ManConst0(p)->Value = 0;
+    // create PIs
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    // create internal nodes
+    Gia_ManHashStart( pNew );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        if ( !Gia_ObjIsMuxType(pObj) || (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) > 1 && Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) > 1) )
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) )
+            pObj->Value = Gia_ManHashXorReal( pNew, Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)) );
+        else
+        {
+            pFanC = Gia_ObjRecognizeMux( pObj, &pFan1, &pFan0 );
+            pObj->Value = Gia_ManHashMuxReal( pNew, Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFanC)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)) );
+        }
+    }
+    Gia_ManHashStop( pNew );
+    // create ROs
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    // perform cleanup
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManTisCollectMffc_rec( Gia_Man_t * p, int Id, Vec_Int_t * vMffc, Vec_Int_t * vLeaves )
+{
+    Gia_Obj_t * pObj;
+    if ( Gia_ObjIsTravIdCurrentId(p, Id) )
+        return;
+    Gia_ObjSetTravIdCurrentId(p, Id);
+    if ( Gia_ObjRefNumId(p, Id) > 1 )
+    {
+        Vec_IntPush( vLeaves, Id );
+        return;
+    }
+    pObj = Gia_ManObj( p, Id );
+    if ( Gia_ObjIsCi(pObj) )
+    {
+        Vec_IntPush( vLeaves, Id );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId0(pObj, Id), vMffc, vLeaves );
+    Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId1(pObj, Id), vMffc, vLeaves );
+    if ( Gia_ObjIsMuxId(p, Id) )
+        Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId2(p, Id), vMffc, vLeaves );
+    Vec_IntPush( vMffc, Id );
+}
+void Gia_ManTisCollectMffc( Gia_Man_t * p, int Id, Vec_Int_t * vMffc, Vec_Int_t * vLeaves )
+{
+    Gia_Obj_t * pObj = Gia_ManObj( p, Id );
+    assert( Gia_ObjIsAnd(pObj) );
+    Vec_IntClear( vMffc );
+    Vec_IntClear( vLeaves );
+    Gia_ManIncrementTravId( p );
+    Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId0(pObj, Id), vMffc, vLeaves );
+    Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId1(pObj, Id), vMffc, vLeaves );
+    if ( Gia_ObjIsMuxId(p, Id) )
+        Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId2(p, Id), vMffc, vLeaves );
+    Vec_IntPush( vMffc, Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManTisPrintMffc( Gia_Man_t * p, int Id, Vec_Int_t * vMffc, Vec_Int_t * vLeaves )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    printf( "MFFC %d has %d nodes and %d leaves:\n", Id, Vec_IntSize(vMffc), Vec_IntSize(vLeaves) );
+    Gia_ManForEachObjVecReverse( vMffc, p, pObj, i )
+    {
+        printf( "Node %2d : ", Vec_IntSize(vMffc) - 1 - i );
+        Gia_ObjPrint( p, pObj );
+    }
+    Gia_ManForEachObjVec( vLeaves, p, pObj, i )
+    {
+        printf( "Leaf %2d : ", i );
+        Gia_ObjPrint( p, pObj );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManTisTest( Gia_Man_t * pInit )
+{
+    Gia_Man_t * p;
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vMffc, * vLeaves;
+    int i;
+    vMffc = Vec_IntAlloc( 10 );
+    vLeaves = Vec_IntAlloc( 10 );
+    p = Gia_ManTisDupMuxes( pInit );
+    Gia_ManCreateRefs( p );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        if ( Gia_ObjRefNumId(p, i) == 1 )
+            continue;
+        Gia_ManTisCollectMffc( p, i, vMffc, vLeaves );
+        Gia_ManTisPrintMffc( p, i, vMffc, vLeaves );
+    }
+    Gia_ManForEachCo( p, pObj, i )
+    {
+        if ( Gia_ObjRefNumId(p, Gia_ObjFaninId0p(p, pObj)) > 1 )
+            continue;
+        Gia_ManTisCollectMffc( p, Gia_ObjFaninId0p(p, pObj), vMffc, vLeaves );
+        Gia_ManTisPrintMffc( p, Gia_ObjFaninId0p(p, pObj), vMffc, vLeaves );
+    }
+    Gia_ManStop( p );
+    Vec_IntFree( vMffc );
+    Vec_IntFree( vLeaves );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaTruth.c b/abc-build/src/aig/gia/giaTruth.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaTruth.c
@@ -0,0 +1,411 @@
+/**CFile****************************************************************
+
+  FileName    [giaTruth.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Truth table computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaTruth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static word s_Truth6[6] = {
+    ABC_CONST(0xAAAAAAAAAAAAAAAA),
+    ABC_CONST(0xCCCCCCCCCCCCCCCC),
+    ABC_CONST(0xF0F0F0F0F0F0F0F0),
+    ABC_CONST(0xFF00FF00FF00FF00),
+    ABC_CONST(0xFFFF0000FFFF0000),
+    ABC_CONST(0xFFFFFFFF00000000)
+};
+
+static inline word * Gla_ObjTruthElem( Gia_Man_t * p, int i )            { return (word *)Vec_PtrEntry( p->vTtInputs, i );                                           }
+static inline word * Gla_ObjTruthNodeId( Gia_Man_t * p, int Id )         { return Vec_WrdArray(p->vTtMemory) + p->nTtWords * Id;                                     }
+static inline word * Gla_ObjTruthNode( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Vec_WrdArray(p->vTtMemory) + p->nTtWords * Gia_ObjNum(p, pObj);                    }
+static inline word * Gla_ObjTruthFree1( Gia_Man_t * p )                  { return Vec_WrdArray(p->vTtMemory) + Vec_WrdSize(p->vTtMemory) - p->nTtWords * 1;          }
+static inline word * Gla_ObjTruthFree2( Gia_Man_t * p )                  { return Vec_WrdArray(p->vTtMemory) + Vec_WrdSize(p->vTtMemory) - p->nTtWords * 2;          }
+static inline word * Gla_ObjTruthConst0( Gia_Man_t * p, word * pDst )                   { int w; for ( w = 0; w < p->nTtWords; w++ ) pDst[w] = 0; return pDst;                      }
+static inline word * Gla_ObjTruthDup( Gia_Man_t * p, word * pDst, word * pSrc, int c )  { int w; for ( w = 0; w < p->nTtWords; w++ ) pDst[w] = c ? ~pSrc[w] : pSrc[w]; return pDst; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table of a 6-LUT.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ObjComputeTruthTable6Lut_rec( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTemp )
+{
+    word uTruth0, uTruth1;
+    Gia_Obj_t * pObj = Gia_ManObj( p, iObj );
+    if ( !Gia_ObjIsAnd(pObj) )
+        return;
+    Gia_ObjComputeTruthTable6Lut_rec( p, Gia_ObjFaninId0p(p, pObj), vTemp );
+    Gia_ObjComputeTruthTable6Lut_rec( p, Gia_ObjFaninId1p(p, pObj), vTemp );
+    uTruth0 = Vec_WrdEntry( vTemp, Gia_ObjFanin0(pObj)->Value );
+    uTruth0 = Gia_ObjFaninC0(pObj) ? ~uTruth0 : uTruth0;
+    uTruth1 = Vec_WrdEntry( vTemp, Gia_ObjFanin1(pObj)->Value );
+    uTruth1 = Gia_ObjFaninC1(pObj) ? ~uTruth1 : uTruth1;
+    Vec_WrdWriteEntry( vTemp, iObj, uTruth0 & uTruth1 );
+}
+word Gia_ObjComputeTruthTable6Lut( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTemp )
+{
+    int i, Fanin;
+    assert( Vec_WrdSize(vTemp) == Gia_ManObjNum(p) );
+    assert( Gia_ObjIsLut(p, iObj) );
+    Gia_LutForEachFanin( p, iObj, Fanin, i )
+        Vec_WrdWriteEntry( vTemp, Fanin, s_Truth6[i] );
+    assert( i <= 6 );
+    Gia_ObjComputeTruthTable6Lut_rec( p, iObj, vTemp );
+    return Vec_WrdEntry( vTemp, iObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table up to 6 inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ObjComputeTruthTable6_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Wrd_t * vTruths )
+{
+    word uTruth0, uTruth1;
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    assert( !pObj->fMark0 );
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ObjComputeTruthTable6_rec( p, Gia_ObjFanin0(pObj), vTruths );
+    Gia_ObjComputeTruthTable6_rec( p, Gia_ObjFanin1(pObj), vTruths );
+    uTruth0 = Vec_WrdEntry( vTruths, Gia_ObjFanin0(pObj)->Value );
+    uTruth0 = Gia_ObjFaninC0(pObj) ? ~uTruth0 : uTruth0;
+    uTruth1 = Vec_WrdEntry( vTruths, Gia_ObjFanin1(pObj)->Value );
+    uTruth1 = Gia_ObjFaninC1(pObj) ? ~uTruth1 : uTruth1;
+    pObj->Value = Vec_WrdSize(vTruths);
+    Vec_WrdPush( vTruths, uTruth0 & uTruth1 );
+}
+word Gia_ObjComputeTruthTable6( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp, Vec_Wrd_t * vTruths )
+{
+    Gia_Obj_t * pLeaf;
+    int i;
+    assert( Vec_IntSize(vSupp) <= 6 );
+    assert( Gia_ObjIsAnd(pObj) );
+    assert( !pObj->fMark0 );
+    Vec_WrdClear( vTruths );
+    Gia_ManIncrementTravId( p );
+    Gia_ManForEachObjVec( vSupp, p, pLeaf, i )
+    {
+        assert( pLeaf->fMark0 || Gia_ObjIsRo(p, pLeaf) );
+        pLeaf->Value = Vec_WrdSize(vTruths);
+        Vec_WrdPush( vTruths, s_Truth6[i] );
+        Gia_ObjSetTravIdCurrent(p, pLeaf);
+    }
+    Gia_ObjComputeTruthTable6_rec( p, pObj, vTruths );
+    return Vec_WrdEntryLast( vTruths );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes reachable from the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ObjCollectInternal_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( !Gia_ObjIsAnd(pObj) )
+        return;
+    if ( pObj->fMark0 )
+        return;
+    pObj->fMark0 = 1;
+    Gia_ObjCollectInternal_rec( p, Gia_ObjFanin0(pObj) );
+    Gia_ObjCollectInternal_rec( p, Gia_ObjFanin1(pObj) );
+    Gia_ObjSetNum( p, pObj, Vec_IntSize(p->vTtNodes) );
+    Vec_IntPush( p->vTtNodes, Gia_ObjId(p, pObj) );
+}
+void Gia_ObjCollectInternal( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    Vec_IntClear( p->vTtNodes );
+    Gia_ObjCollectInternal_rec( p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computing the truth table for GIA object.]
+
+  Description [The truth table should be used by the calling application
+  (or saved into the user's storage) before this procedure is called again.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word * Gia_ObjComputeTruthTable( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    Gia_Obj_t * pTemp, * pRoot;
+    word * pTruth, * pTruthL, * pTruth0, * pTruth1;
+    int i;
+    if ( p->vTtMemory == NULL )
+    {
+        p->nTtVars   = Gia_ManPiNum( p );
+        p->nTtWords  = Abc_Truth6WordNum( p->nTtVars );
+        p->vTtNums   = Vec_IntStart( Gia_ManObjNum(p) + 1000 );
+        p->vTtNodes  = Vec_IntAlloc( 256 );
+        p->vTtInputs = Vec_PtrAllocTruthTables( Abc_MaxInt(6, p->nTtVars) );
+        p->vTtMemory = Vec_WrdStart( p->nTtWords * 256 );
+    }
+    else
+    {
+        // make sure the number of primary inputs did not change 
+        // since the truth table computation storage was prepared
+        assert( p->nTtVars == Gia_ManPiNum(p) );
+    }
+    // extend ID numbers
+    if ( Vec_IntSize(p->vTtNums) < Gia_ManObjNum(p) )
+        Vec_IntFillExtra( p->vTtNums, Gia_ManObjNum(p), 0 );
+    // collect internal nodes
+    pRoot = Gia_ObjIsCo(pObj) ? Gia_ObjFanin0(pObj) : pObj;
+    Gia_ObjCollectInternal( p, pRoot );
+    // extend TT storage
+    if ( Vec_WrdSize(p->vTtMemory) < p->nTtWords * (Vec_IntSize(p->vTtNodes) + 2) )
+        Vec_WrdFillExtra( p->vTtMemory, p->nTtWords * (Vec_IntSize(p->vTtNodes) + 2), 0 );
+    // compute the truth table for internal nodes
+    Gia_ManForEachObjVec( p->vTtNodes, p, pTemp, i )
+    {
+        pTemp->fMark0 = 0; // unmark nodes marked by Gia_ObjCollectInternal()
+        pTruth  = Gla_ObjTruthNode(p, pTemp);
+        pTruthL = pTruth + p->nTtWords;
+        pTruth0 = Gia_ObjIsAnd(Gia_ObjFanin0(pTemp)) ? Gla_ObjTruthNode(p, Gia_ObjFanin0(pTemp)) : Gla_ObjTruthElem(p, Gia_ObjCioId(Gia_ObjFanin0(pTemp)) );
+        pTruth1 = Gia_ObjIsAnd(Gia_ObjFanin1(pTemp)) ? Gla_ObjTruthNode(p, Gia_ObjFanin1(pTemp)) : Gla_ObjTruthElem(p, Gia_ObjCioId(Gia_ObjFanin1(pTemp)) );
+        if ( Gia_ObjFaninC0(pTemp) )
+        {
+            if ( Gia_ObjFaninC1(pTemp) )
+                while ( pTruth < pTruthL )
+                    *pTruth++ = ~*pTruth0++ & ~*pTruth1++;
+            else
+                while ( pTruth < pTruthL )
+                    *pTruth++ = ~*pTruth0++ &  *pTruth1++;
+        }
+        else
+        {
+            if ( Gia_ObjFaninC1(pTemp) )
+                while ( pTruth < pTruthL )
+                    *pTruth++ =  *pTruth0++ & ~*pTruth1++;
+            else
+                while ( pTruth < pTruthL )
+                    *pTruth++ =  *pTruth0++ &  *pTruth1++;
+        }
+    }
+    // compute the final table
+    if ( Gia_ObjIsConst0(pRoot) )
+        pTruth = Gla_ObjTruthConst0( p, Gla_ObjTruthFree1(p) );
+    else if ( Gia_ObjIsPi(p, pRoot) )
+        pTruth = Gla_ObjTruthElem( p, Gia_ObjCioId(pRoot) );
+    else if ( Gia_ObjIsAnd(pRoot) )
+        pTruth = Gla_ObjTruthNode( p, pRoot );
+    else
+        pTruth = NULL;
+    return Gla_ObjTruthDup( p, Gla_ObjTruthFree2(p), pTruth, Gia_ObjIsCo(pObj) && Gia_ObjFaninC0(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Testing truth table computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ObjComputeTruthTableTest( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    unsigned * pTruth;
+    abctime clk = Abc_Clock();
+    int i;
+    Gia_ManForEachPo( p, pObj, i )
+    {
+        pTruth = (unsigned *)Gia_ObjComputeTruthTable( p, pObj );
+//        Extra_PrintHex( stdout, pTruth, Gia_ManPiNum(p) ); printf( "\n" );
+    }
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ObjComputeTruthTableStart( Gia_Man_t * p, int nVarsMax )
+{
+    assert( p->vTtMemory == NULL );
+    p->nTtVars   = nVarsMax;
+    p->nTtWords  = Abc_Truth6WordNum( p->nTtVars );
+    p->vTtNodes  = Vec_IntAlloc( 256 );
+    p->vTtInputs = Vec_PtrAllocTruthTables( Abc_MaxInt(6, p->nTtVars) );
+    p->vTtMemory = Vec_WrdStart( p->nTtWords * 64 );
+    p->vTtNums   = Vec_IntAlloc( Gia_ManObjNum(p) + 1000 );
+    Vec_IntFill( p->vTtNums, Vec_IntCap(p->vTtNums), -ABC_INFINITY );
+}
+void Gia_ObjComputeTruthTableStop( Gia_Man_t * p )
+{
+    p->nTtVars   = 0;
+    p->nTtWords  = 0;
+    Vec_IntFreeP( &p->vTtNums );
+    Vec_IntFreeP( &p->vTtNodes );
+    Vec_PtrFreeP( &p->vTtInputs );
+    Vec_WrdFreeP( &p->vTtMemory );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes reachable from the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ObjCollectInternalCut_rec( Gia_Man_t * p, int iObj )
+{
+    if ( Gia_ObjHasNumId(p, iObj) )
+        return;
+    assert( Gia_ObjIsAnd(Gia_ManObj(p, iObj)) );
+    Gia_ObjCollectInternalCut_rec( p, Gia_ObjFaninId0(Gia_ManObj(p, iObj), iObj) );
+    Gia_ObjCollectInternalCut_rec( p, Gia_ObjFaninId1(Gia_ManObj(p, iObj), iObj) );
+    Gia_ObjSetNumId( p, iObj, Vec_IntSize(p->vTtNodes) );
+    Vec_IntPush( p->vTtNodes, iObj );
+}
+void Gia_ObjCollectInternalCut( Gia_Man_t * p, int iRoot, Vec_Int_t * vLeaves )
+{
+    int i, iObj;
+    assert( !Gia_ObjHasNumId(p, iRoot) );
+    assert( Gia_ObjIsAnd(Gia_ManObj(p, iRoot)) );
+    Vec_IntForEachEntry( vLeaves, iObj, i )
+    {
+        assert( !Gia_ObjHasNumId(p, iObj) );
+        Gia_ObjSetNumId( p, iObj, -i );
+    }
+    assert( !Gia_ObjHasNumId(p, iRoot) ); // the root cannot be one of the leaves
+    Vec_IntClear( p->vTtNodes );
+    Vec_IntPush( p->vTtNodes, -1 );
+    Gia_ObjCollectInternalCut_rec( p, iRoot );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the truth table of pRoot in terms of leaves.]
+
+  Description [The root cannot be one of the leaves.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word * Gia_ObjComputeTruthTableCut( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves )
+{
+    Gia_Obj_t * pTemp;
+    word * pTruth, * pTruthL, * pTruth0, * pTruth1;
+    int i, iObj, Id0, Id1;
+    assert( p->vTtMemory != NULL );
+    assert( Vec_IntSize(vLeaves) <= p->nTtVars );
+    // extend ID numbers
+    if ( Vec_IntSize(p->vTtNums) < Gia_ManObjNum(p) )
+        Vec_IntFillExtra( p->vTtNums, Gia_ManObjNum(p), -ABC_INFINITY );
+    // collect internal nodes
+    Gia_ObjCollectInternalCut( p, Gia_ObjId(p, pRoot), vLeaves );
+    // extend TT storage
+    if ( Vec_WrdSize(p->vTtMemory) < p->nTtWords * (Vec_IntSize(p->vTtNodes) + 2) )
+        Vec_WrdFillExtra( p->vTtMemory, p->nTtWords * (Vec_IntSize(p->vTtNodes) + 2), 0 );
+    // compute the truth table for internal nodes
+    Vec_IntForEachEntryStart( p->vTtNodes, iObj, i, 1 )
+    {
+        assert( i == Gia_ObjNumId(p, iObj) );
+        pTemp   = Gia_ManObj( p, iObj );
+        pTruth  = Gla_ObjTruthNodeId( p, i );  
+        pTruthL = pTruth + p->nTtWords;
+        Id0 = Gia_ObjNumId( p, Gia_ObjFaninId0(pTemp, iObj) );
+        Id1 = Gia_ObjNumId( p, Gia_ObjFaninId1(pTemp, iObj) );
+        pTruth0 = (Id0 > 0) ? Gla_ObjTruthNodeId(p, Id0) : Gla_ObjTruthElem(p, -Id0);
+        pTruth1 = (Id1 > 0) ? Gla_ObjTruthNodeId(p, Id1) : Gla_ObjTruthElem(p, -Id1);
+        if ( Gia_ObjFaninC0(pTemp) )
+        {
+            if ( Gia_ObjFaninC1(pTemp) )
+                while ( pTruth < pTruthL )
+                    *pTruth++ = ~*pTruth0++ & ~*pTruth1++;
+            else
+                while ( pTruth < pTruthL )
+                    *pTruth++ = ~*pTruth0++ &  *pTruth1++;
+        }
+        else
+        {
+            if ( Gia_ObjFaninC1(pTemp) )
+                while ( pTruth < pTruthL )
+                    *pTruth++ =  *pTruth0++ & ~*pTruth1++;
+            else
+                while ( pTruth < pTruthL )
+                    *pTruth++ =  *pTruth0++ &  *pTruth1++;
+        }
+    }
+    pTruth = Gla_ObjTruthNode( p, pRoot );
+    // unmark leaves marked by Gia_ObjCollectInternal()
+    Vec_IntForEachEntry( vLeaves, iObj, i )
+        Gia_ObjResetNumId( p, iObj );
+    Vec_IntForEachEntryStart( p->vTtNodes, iObj, i, 1 )
+        Gia_ObjResetNumId( p, iObj );
+    return pTruth;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaTsim.c b/abc-build/src/aig/gia/giaTsim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaTsim.c
@@ -0,0 +1,757 @@
+/**CFile****************************************************************
+
+  FileName    [giaTsim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Ternary simulation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaTsim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Gia_ManTerSimInfoGet( unsigned * pInfo, int i )
+{
+    return 3 & (pInfo[i >> 4] >> ((i & 15) << 1));
+}
+static inline void Gia_ManTerSimInfoSet( unsigned * pInfo, int i, int Value )
+{
+    assert( Value >= GIA_ZER && Value <= GIA_UND );
+    Value ^= Gia_ManTerSimInfoGet( pInfo, i );
+    pInfo[i >> 4] ^= (Value << ((i & 15) << 1));
+}
+
+static inline unsigned * Gia_ManTerStateNext( unsigned * pState, int nWords )                      { return *((unsigned **)(pState + nWords));  }
+static inline void       Gia_ManTerStateSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; }
+
+// ternary simulation manager
+typedef struct Gia_ManTer_t_ Gia_ManTer_t;
+struct Gia_ManTer_t_
+{
+    Gia_Man_t *    pAig;
+    int            nIters;
+    int            nStateWords;
+    Vec_Ptr_t *    vStates;
+    Vec_Ptr_t *    vFlops;
+    Vec_Int_t *    vRetired;     // retired registers
+    char *         pRetired;     // retired registers
+    int *          pCount0;
+    int *          pCountX;
+    // hash table for states
+    int            nBins;
+    unsigned **    pBins;
+    // simulation information
+    unsigned *     pDataSim;     // simulation data
+    unsigned *     pDataSimCis;  // simulation data for CIs
+    unsigned *     pDataSimCos;  // simulation data for COs
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates fast simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_ManTer_t * Gia_ManTerCreate( Gia_Man_t * pAig )
+{
+    Gia_ManTer_t * p;
+    p = ABC_CALLOC( Gia_ManTer_t, 1 );
+    p->pAig   = Gia_ManFront( pAig );
+    p->nIters = 300;
+    p->pDataSim    = ABC_ALLOC( unsigned, Abc_BitWordNum(2*p->pAig->nFront) );
+    p->pDataSimCis = ABC_ALLOC( unsigned, Abc_BitWordNum(2*Gia_ManCiNum(p->pAig)) );
+    p->pDataSimCos = ABC_ALLOC( unsigned, Abc_BitWordNum(2*Gia_ManCoNum(p->pAig)) );
+    // allocate storage for terminary states
+    p->nStateWords = Abc_BitWordNum( 2*Gia_ManRegNum(pAig) );
+    p->vStates  = Vec_PtrAlloc( 1000 );
+    p->pCount0  = ABC_CALLOC( int, Gia_ManRegNum(pAig) );
+    p->pCountX  = ABC_CALLOC( int, Gia_ManRegNum(pAig) );
+    p->nBins    = Abc_PrimeCudd( 500 );
+    p->pBins    = ABC_CALLOC( unsigned *, p->nBins );
+    p->vRetired = Vec_IntAlloc( 100 );
+    p->pRetired = ABC_CALLOC( char, Gia_ManRegNum(pAig) );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManTerStatesFree( Vec_Ptr_t * vStates )
+{
+    unsigned * pTemp;
+    int i;
+    Vec_PtrForEachEntry( unsigned *, vStates, pTemp, i )
+        ABC_FREE( pTemp );
+    Vec_PtrFree( vStates );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManTerDelete( Gia_ManTer_t * p )
+{
+    if ( p->vStates ) 
+        Gia_ManTerStatesFree( p->vStates );
+    if ( p->vFlops ) 
+        Gia_ManTerStatesFree( p->vFlops );
+    Gia_ManStop( p->pAig );
+    Vec_IntFree( p->vRetired );
+    ABC_FREE( p->pRetired );
+    ABC_FREE( p->pCount0 );
+    ABC_FREE( p->pCountX );
+    ABC_FREE( p->pBins );
+    ABC_FREE( p->pDataSim );
+    ABC_FREE( p->pDataSimCis );
+    ABC_FREE( p->pDataSimCos );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManTerSimulateCi( Gia_ManTer_t * p, Gia_Obj_t * pObj, int iCi )
+{
+    Gia_ManTerSimInfoSet( p->pDataSim, Gia_ObjValue(pObj), Gia_ManTerSimInfoGet(p->pDataSimCis, iCi) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManTerSimulateCo( Gia_ManTer_t * p, int iCo, Gia_Obj_t * pObj )
+{
+    int Value = Gia_ManTerSimInfoGet( p->pDataSim, Gia_ObjDiff0(pObj) );
+    Gia_ManTerSimInfoSet( p->pDataSimCos, iCo, Gia_XsimNotCond( Value, Gia_ObjFaninC0(pObj) ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManTerSimulateNode( Gia_ManTer_t * p, Gia_Obj_t * pObj )
+{
+    int Value0 = Gia_ManTerSimInfoGet( p->pDataSim, Gia_ObjDiff0(pObj) );
+    int Value1 = Gia_ManTerSimInfoGet( p->pDataSim, Gia_ObjDiff1(pObj) );
+    Gia_ManTerSimInfoSet( p->pDataSim, Gia_ObjValue(pObj), Gia_XsimAndCond( Value0, Gia_ObjFaninC0(pObj), Value1, Gia_ObjFaninC1(pObj) ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManTerSimInfoInit( Gia_ManTer_t * p )
+{
+    int i = 0;
+    for ( ; i < Gia_ManPiNum(p->pAig); i++ )
+        Gia_ManTerSimInfoSet( p->pDataSimCis, i, GIA_UND );
+    for ( ; i < Gia_ManCiNum(p->pAig); i++ )
+        Gia_ManTerSimInfoSet( p->pDataSimCis, i, GIA_ZER );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManTerSimInfoTransfer( Gia_ManTer_t * p )
+{
+    int i = 0;
+    for ( ; i < Gia_ManPiNum(p->pAig); i++ )
+        Gia_ManTerSimInfoSet( p->pDataSimCis, i, GIA_UND );
+    for ( ; i < Gia_ManCiNum(p->pAig); i++ )
+        Gia_ManTerSimInfoSet( p->pDataSimCis, i, Gia_ManTerSimInfoGet( p->pDataSimCos, Gia_ManCoNum(p->pAig)-Gia_ManCiNum(p->pAig)+i ) );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash value of the node using its simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManTerStateHash( unsigned * pState, int nWords, int nTableSize )
+{
+    static int s_FPrimes[128] = { 
+        1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 
+        1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 
+        2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 
+        2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 
+        3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 
+        3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 
+        4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 
+        4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 
+        5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 
+        6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 
+        6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 
+        7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 
+        8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+    };
+    unsigned uHash;
+    int i;
+    uHash = 0;
+    for ( i = 0; i < nWords; i++ )
+        uHash ^= pState[i] * s_FPrimes[i & 0x7F];
+    return uHash % nTableSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts value into the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Gia_ManTerStateLookup( unsigned * pState, int nWords, unsigned ** pBins, int nBins )
+{
+    unsigned * pEntry;
+    int Hash = Gia_ManTerStateHash( pState, nWords, nBins );
+    for ( pEntry = pBins[Hash]; pEntry; pEntry = Gia_ManTerStateNext(pEntry, nWords) )
+        if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) )
+            return pEntry;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts value into the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManTerStateInsert( unsigned * pState, int nWords, unsigned ** pBins, int nBins )
+{
+    int Hash = Gia_ManTerStateHash( pState, nWords, nBins );
+    assert( !Gia_ManTerStateLookup( pState, nWords, pBins, nBins ) );
+    Gia_ManTerStateSetNext( pState, nWords, pBins[Hash] );
+    pBins[Hash] = pState;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocs new ternary state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Gia_ManTerStateAlloc( int nWords )
+{
+    return (unsigned *)ABC_CALLOC( char, sizeof(unsigned) * nWords + sizeof(unsigned *) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates new ternary state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Gia_ManTerStateCreate( Gia_ManTer_t * p )
+{
+    int i, Value, nPis = Gia_ManPiNum(p->pAig);
+    unsigned * pRes = Gia_ManTerStateAlloc( p->nStateWords );
+    for ( i = nPis; i < Gia_ManCiNum(p->pAig); i++ )
+    {
+        Value = Gia_ManTerSimInfoGet( p->pDataSimCis, i );
+        Gia_ManTerSimInfoSet( pRes, i-nPis, Value );
+        if ( Value == GIA_ZER )
+            p->pCount0[i-nPis]++;
+        if ( Value == GIA_UND )
+            p->pCountX[i-nPis]++;
+    }
+    Vec_PtrPush( p->vStates, pRes );
+    return pRes;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one round of ternary simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManTerSimulateRound( Gia_ManTer_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, iCis = 0, iCos = 0;
+    assert( p->pAig->nFront > 0 );
+    assert( Gia_ManConst0(p->pAig)->Value == 0 );
+    Gia_ManTerSimInfoSet( p->pDataSim, 0, GIA_ZER );
+    Gia_ManForEachObj1( p->pAig, pObj, i )
+    {
+        if ( Gia_ObjIsAndOrConst0(pObj) )
+        {
+            assert( Gia_ObjValue(pObj) < p->pAig->nFront );
+            Gia_ManTerSimulateNode( p, pObj );
+        }
+        else if ( Gia_ObjIsCi(pObj) )
+        {
+            assert( Gia_ObjValue(pObj) < p->pAig->nFront );
+            Gia_ManTerSimulateCi( p, pObj, iCis++ );
+        }
+        else // if ( Gia_ObjIsCo(pObj) )
+        {
+            assert( Gia_ObjValue(pObj) == GIA_NONE );
+            Gia_ManTerSimulateCo( p, iCos++, pObj );
+        }
+    }
+    assert( Gia_ManCiNum(p->pAig) == iCis );
+    assert( Gia_ManCoNum(p->pAig) == iCos );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Retires a set of registers to speed up convergence.]
+
+  Description [Retire all non-ternary registers which has max number 
+  of ternary values so far.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManTerRetire2( Gia_ManTer_t * p, unsigned * pState )
+{
+    int i, Entry, iMaxTerValue = -1;
+    // find non-retired register with this value
+    for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ )
+        if ( Gia_ManTerSimInfoGet( pState, i ) != GIA_UND && !p->pRetired[i] && iMaxTerValue < p->pCountX[i] )
+            iMaxTerValue = p->pCountX[i];
+    assert( iMaxTerValue >= 0 );
+    // retire the first registers with this value
+    for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ )
+        if ( Gia_ManTerSimInfoGet( pState, i ) != GIA_UND && !p->pRetired[i] && iMaxTerValue == p->pCountX[i] )
+        {
+            assert( p->pRetired[i] == 0 );
+            p->pRetired[i] = 1;
+            Vec_IntPush( p->vRetired, i );
+            if ( iMaxTerValue == 0 )
+                break;
+        }
+    // update all the retired registers
+    Vec_IntForEachEntry( p->vRetired, Entry, i )
+        Gia_ManTerSimInfoSet( p->pDataSimCis, Gia_ManPiNum(p->pAig)+Entry, GIA_UND );
+    return Vec_IntSize(p->vRetired);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Retires a set of registers to speed up convergence.]
+
+  Description [Retire all non-ternary registers which has max number 
+  of ternary values so far.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManTerRetire( Gia_ManTer_t * p, unsigned * pThis, unsigned * pPrev )
+{
+    int i, Entry;
+    // find registers whose value has changed
+    Vec_IntClear( p->vRetired );
+    for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ )
+        if ( Gia_ManTerSimInfoGet( pThis, i ) != Gia_ManTerSimInfoGet( pPrev, i ) )
+            Vec_IntPush( p->vRetired, i );
+    // set all of them to zero
+    Vec_IntForEachEntry( p->vRetired, Entry, i )
+        Gia_ManTerSimInfoSet( p->pDataSimCis, Gia_ManPiNum(p->pAig)+Entry, GIA_UND );
+    return Vec_IntSize(p->vRetired);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts value into the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManTerStatePrint( unsigned * pState, int nRegs, int iNum )
+{
+    int i, nZeros = 0, nOnes = 0, nDcs = 0;
+    printf( " %4d : ", iNum );
+    for ( i = 0; i < nRegs; i++ )
+    {
+        if ( Gia_ManTerSimInfoGet(pState, i) == GIA_ZER )
+            printf( "0" ), nZeros++;
+        else if ( Gia_ManTerSimInfoGet(pState, i) == GIA_ONE )
+            printf( "1" ), nOnes++;
+        else if ( Gia_ManTerSimInfoGet(pState, i) == GIA_UND )
+            printf( "x" ), nDcs++;
+        else
+            assert( 0 );
+    }
+    printf( " (0=%4d, 1=%4d, x=%4d)\n", nZeros, nOnes, nDcs );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManTerAnalyze2( Vec_Ptr_t * vStates, int nRegs )
+{
+    unsigned * pTemp, * pStates = (unsigned *)Vec_PtrPop( vStates );
+    int i, w, nZeros, nConsts, nStateWords;
+    // detect constant zero registers
+    nStateWords = Abc_BitWordNum( 2*nRegs );
+    memset( pStates, 0, sizeof(int) * nStateWords );
+    Vec_PtrForEachEntry( unsigned *, vStates, pTemp, i )
+        for ( w = 0; w < nStateWords; w++ )
+            pStates[w] |= pTemp[w];
+    // count the number of zeros
+    nZeros = 0;
+    for ( i = 0; i < nRegs; i++ )
+        if ( Gia_ManTerSimInfoGet(pStates, i) == GIA_ZER )
+            nZeros++;
+    printf( "Found %d constant registers.\n", nZeros );
+    // detect non-ternary registers
+    memset( pStates, 0, sizeof(int) * nStateWords );
+    Vec_PtrForEachEntry( unsigned *, vStates, pTemp, i )
+        for ( w = 0; w < nStateWords; w++ )
+            pStates[w] |= (~(pTemp[w] ^ (pTemp[w] >> 1)) & 0x55555555);
+    // count the nonternary registers
+    nConsts = 0;
+    for ( i = 0; i < nRegs; i++ )
+        if ( Gia_ManTerSimInfoGet(pStates, i) == 0 )
+            nConsts++;
+    printf( "Found %d non-ternary registers.\n", nConsts );
+    // return the state back
+    Vec_PtrPush( vStates, pStates );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManTerAnalyze( Gia_ManTer_t * p )
+{
+    int i, nZeros = 0, nConsts = 0;
+    for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ )
+        if ( p->pCount0[i] == Vec_PtrSize(p->vStates) )
+            nZeros++;
+        else if ( p->pCountX[i] == 0 )
+            nConsts++;
+//    printf( "Found %d constant registers.\n", nZeros );
+//    printf( "Found %d non-ternary registers.\n", nConsts );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transposes state vector for non-ternary registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Gia_ManTerTranspose( Gia_ManTer_t * p )
+{
+    Vec_Ptr_t * vFlops;
+    unsigned * pState, * pFlop;
+    int i, k, nFlopWords;
+    vFlops = Vec_PtrAlloc( 100 );
+    nFlopWords = Abc_BitWordNum( 2*Vec_PtrSize(p->vStates) );
+    for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ )
+    {
+        if ( p->pCount0[i] == Vec_PtrSize(p->vStates) ) 
+            continue;
+        if ( p->pCountX[i] > 0 )
+            continue;
+        pFlop = Gia_ManTerStateAlloc( nFlopWords );
+        Vec_PtrPush( vFlops, pFlop );
+        Vec_PtrForEachEntry( unsigned *, p->vStates, pState, k )
+            Gia_ManTerSimInfoSet( pFlop, k, Gia_ManTerSimInfoGet(pState, i) );
+//Gia_ManTerStatePrint( pFlop, Vec_PtrSize(p->vStates), i );
+    }
+    return vFlops;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transposes state vector for non-ternary registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManFindEqualFlop( Vec_Ptr_t * vFlops, int iFlop, int nFlopWords )
+{
+    unsigned * pFlop, * pTemp;
+    int i;
+    pFlop = (unsigned *)Vec_PtrEntry( vFlops, iFlop );
+    Vec_PtrForEachEntryStop( unsigned *, vFlops, pTemp, i, iFlop )
+        if ( !memcmp( pTemp, pFlop, sizeof(unsigned) * nFlopWords ) )
+            return i;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates map of registers to replace.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Gia_ManTerCreateMap( Gia_ManTer_t * p, int fVerbose )
+{
+    int * pCi2Lit;
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vMapKtoI;
+    int i, iRepr, nFlopWords, Counter0 = 0, CounterE = 0;
+    nFlopWords = Abc_BitWordNum( 2*Vec_PtrSize(p->vStates) );
+    p->vFlops = Gia_ManTerTranspose( p );
+    pCi2Lit = ABC_FALLOC( int, Gia_ManCiNum(p->pAig) );
+    vMapKtoI = Vec_IntAlloc( 100 );
+    for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ )
+        if ( p->pCount0[i] == Vec_PtrSize(p->vStates) )
+            pCi2Lit[Gia_ManPiNum(p->pAig)+i] = 0, Counter0++;
+        else if ( p->pCountX[i] == 0 )
+        {
+            iRepr = Gia_ManFindEqualFlop( p->vFlops, Vec_IntSize(vMapKtoI), nFlopWords );
+            Vec_IntPush( vMapKtoI, i );
+            if ( iRepr < 0 )
+                continue;
+            pObj = Gia_ManCi( p->pAig, Gia_ManPiNum(p->pAig)+Vec_IntEntry(vMapKtoI, iRepr) );
+            pCi2Lit[Gia_ManPiNum(p->pAig)+i] = Abc_Var2Lit( Gia_ObjId( p->pAig, pObj ), 0 );
+            CounterE++;
+        }
+    Vec_IntFree( vMapKtoI );
+    if ( fVerbose )
+        printf( "Transforming %d const and %d equiv registers.\n", Counter0, CounterE );
+    return pCi2Lit;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_ManTer_t * Gia_ManTerSimulate( Gia_Man_t * pAig, int fVerbose )
+{
+    Gia_ManTer_t * p;
+    unsigned * pState, * pPrev, * pLoop;
+    int i, Counter;
+    abctime clk, clkTotal = Abc_Clock();
+    assert( Gia_ManRegNum(pAig) > 0 );
+    // create manager
+    clk = Abc_Clock();
+    p = Gia_ManTerCreate( pAig );
+    if ( 0 )
+    {
+        printf( "Obj = %8d (%8d). F = %6d. ", 
+            pAig->nObjs, Gia_ManCiNum(pAig) + Gia_ManAndNum(pAig), p->pAig->nFront );
+        printf( "AIG = %7.2f MB. F-mem = %7.2f MB. Other = %7.2f MB.  ", 
+            12.0*Gia_ManObjNum(p->pAig)/(1<<20), 
+            4.0*Abc_BitWordNum(2 * p->pAig->nFront)/(1<<20), 
+            4.0*Abc_BitWordNum(2 * (Gia_ManCiNum(pAig) + Gia_ManCoNum(pAig)))/(1<<20) );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    // perform simulation
+    Gia_ManTerSimInfoInit( p );
+    // hash the first state
+    pState = Gia_ManTerStateCreate( p );
+    Gia_ManTerStateInsert( pState, p->nStateWords, p->pBins, p->nBins );
+//Gia_ManTerStatePrint( pState, Gia_ManRegNum(pAig), 0 );
+    // perform simuluation till convergence
+    pPrev = NULL;
+    for ( i = 0; ; i++ )
+    {
+        Gia_ManTerSimulateRound( p );
+        Gia_ManTerSimInfoTransfer( p );
+        pState = Gia_ManTerStateCreate( p );
+//Gia_ManTerStatePrint( pState, Gia_ManRegNum(pAig), i+1 );
+        if ( (pLoop = Gia_ManTerStateLookup(pState, p->nStateWords, p->pBins, p->nBins)) )
+        {
+            pAig->nTerStates = Vec_PtrSize( p->vStates );
+            pAig->nTerLoop = Vec_PtrFind( p->vStates, pLoop );
+            break;
+        }
+        Gia_ManTerStateInsert( pState, p->nStateWords, p->pBins, p->nBins );
+        if ( i >= p->nIters && i % 10 == 0 )
+        {
+            Counter = Gia_ManTerRetire( p, pState, pPrev );
+//            Counter = Gia_ManTerRetire2( p, pState );
+//            if ( fVerbose )
+//                printf( "Retired %d registers.\n", Counter );
+        }
+        pPrev = pState;
+    }
+    if ( fVerbose )
+    {
+        printf( "Ternary simulation saturated after %d iterations. ", i+1 );
+        ABC_PRT( "Time", Abc_Clock() - clkTotal );
+    }
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManReduceConst( Gia_Man_t * pAig, int fVerbose )
+{
+    Gia_ManTer_t * p;
+    Gia_Man_t * pNew = NULL;
+    int * pCi2Lit;
+    p = Gia_ManTerSimulate( pAig, fVerbose );
+    Gia_ManTerAnalyze( p );
+    pCi2Lit = Gia_ManTerCreateMap( p, fVerbose );
+    Gia_ManTerDelete( p );
+    pNew = Gia_ManDupDfsCiMap( pAig, pCi2Lit, NULL );
+    ABC_FREE( pCi2Lit );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/giaUtil.c b/abc-build/src/aig/gia/giaUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/giaUtil.c
@@ -0,0 +1,1911 @@
+/**CFile****************************************************************
+
+  FileName    [giaUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Various utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: giaUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "base/main/mainInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+#define NUMBER1  3716960521u
+#define NUMBER2  2174103536u
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a sequence or random numbers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [http://www.codeproject.com/KB/recipes/SimpleRNG.aspx]
+
+***********************************************************************/
+unsigned Gia_ManRandom( int fReset )
+{
+    static unsigned int m_z = NUMBER1;
+    static unsigned int m_w = NUMBER2;
+    if ( fReset )
+    {
+        m_z = NUMBER1;
+        m_w = NUMBER2;
+    }
+    m_z = 36969 * (m_z & 65535) + (m_z >> 16);
+    m_w = 18000 * (m_w & 65535) + (m_w >> 16);
+    return (m_z << 16) + m_w;
+}
+word Gia_ManRandomW( int fReset )
+{ 
+    return ((word)Gia_ManRandom(fReset) << 32) | ((word)Gia_ManRandom(fReset) << 0);
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates random info for the primary inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManRandomInfo( Vec_Ptr_t * vInfo, int iInputStart, int iWordStart, int iWordStop )
+{
+    unsigned * pInfo;
+    int i, w;
+    Vec_PtrForEachEntryStart( unsigned *, vInfo, pInfo, i, iInputStart )
+        for ( w = iWordStart; w < iWordStop; w++ )
+            pInfo[w] = Gia_ManRandom(0);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the time stamp.]
+
+  Description [The file should be closed.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Gia_TimeStamp()
+{
+    static char Buffer[100];
+	char * TimeStamp;
+	time_t ltime;
+    // get the current time
+	time( &ltime );
+	TimeStamp = asctime( localtime( &ltime ) );
+	TimeStamp[ strlen(TimeStamp) - 1 ] = 0;
+    strcpy( Buffer, TimeStamp );
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the composite name of the file.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Gia_FileNameGenericAppend( char * pBase, char * pSuffix )
+{
+    static char Buffer[1000];
+    char * pDot;
+    strcpy( Buffer, pBase );
+    if ( (pDot = strrchr( Buffer, '.' )) )
+        *pDot = 0;
+    strcat( Buffer, pSuffix );
+    if ( (pDot = strrchr( Buffer, '\\' )) || (pDot = strrchr( Buffer, '/' )) )
+        return pDot+1;
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManIncrementTravId( Gia_Man_t * p )                     
+{ 
+    if ( p->pTravIds == NULL )
+    {
+        p->nTravIdsAlloc = Gia_ManObjNum(p) + 100; 
+        p->pTravIds = ABC_CALLOC( int, p->nTravIdsAlloc ); 
+        p->nTravIds = 0;  
+    }
+    while ( p->nTravIdsAlloc < Gia_ManObjNum(p) )
+    {
+        p->nTravIdsAlloc *= 2;
+        p->pTravIds = ABC_REALLOC( int, p->pTravIds, p->nTravIdsAlloc );
+        memset( p->pTravIds + p->nTravIdsAlloc/2, 0, sizeof(int) * p->nTravIdsAlloc/2 );
+    }
+    p->nTravIds++;                                                    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets phases of the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCleanMark01( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+        pObj->fMark0 = pObj->fMark1 = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets phases of the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSetMark0( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+        pObj->fMark0 = 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets phases of the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCleanMark0( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+        pObj->fMark0 = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets phases of the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCheckMark0( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+        assert( pObj->fMark0 == 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets phases of the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSetMark1( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+        pObj->fMark1 = 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets phases of the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCleanMark1( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+        pObj->fMark1 = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets phases of the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCheckMark1( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+        assert( pObj->fMark1 == 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCleanValue( Gia_Man_t * p )  
+{
+    int i;
+    for ( i = 0; i < p->nObjs; i++ )
+        p->pObjs[i].Value = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFillValue( Gia_Man_t * p )  
+{
+    int i;
+    for ( i = 0; i < p->nObjs; i++ )
+        p->pObjs[i].Value = ~0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the phase of one object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ObjSetPhase( Gia_Man_t * p, Gia_Obj_t * pObj )  
+{
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        int fPhase0 = Gia_ObjPhase(Gia_ObjFanin0(pObj)) ^ Gia_ObjFaninC0(pObj);
+        int fPhase1 = Gia_ObjPhase(Gia_ObjFanin1(pObj)) ^ Gia_ObjFaninC1(pObj);
+        if ( Gia_ObjIsMux(p, pObj) )
+        {
+            int fPhase2 = Gia_ObjPhase(Gia_ObjFanin2(p, pObj)) ^ Gia_ObjFaninC2(p, pObj);
+            pObj->fPhase = (fPhase2 && fPhase1) || (!fPhase2 && fPhase0);
+        }
+        else if ( Gia_ObjIsXor(pObj) )
+            pObj->fPhase = fPhase0 ^ fPhase1;
+        else
+            pObj->fPhase = fPhase0 & fPhase1;
+    }
+    else if ( Gia_ObjIsCo(pObj) )
+        pObj->fPhase = (Gia_ObjPhase(Gia_ObjFanin0(pObj)) ^ Gia_ObjFaninC0(pObj));
+    else
+        pObj->fPhase = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets phases of the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSetPhase( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+        Gia_ObjSetPhase( p, pObj );
+}
+void Gia_ManSetPhasePattern( Gia_Man_t * p, Vec_Int_t * vCiValues )  
+{
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Gia_ManCiNum(p) == Vec_IntSize(vCiValues) );
+    Gia_ManForEachObj( p, pObj, i )
+        if ( Gia_ObjIsCi(pObj) )
+            pObj->fPhase = Vec_IntEntry( vCiValues, Gia_ObjCioId(pObj) );
+        else
+            Gia_ObjSetPhase( p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets phases of the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSetPhase1( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->fPhase = 1;
+    Gia_ManForEachObj( p, pObj, i )
+        if ( !Gia_ObjIsCi(pObj) )
+            Gia_ObjSetPhase( p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets phases of the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCleanPhase( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+        pObj->fPhase = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of COs whose value is 1.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCheckCoPhase( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, Counter = 0;
+    Gia_ManForEachCo( p, pObj, i )
+        Counter += pObj->fPhase;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares copies for the model.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCleanLevels( Gia_Man_t * p, int Size )
+{
+    if ( p->vLevels == NULL )
+        p->vLevels = Vec_IntAlloc( Size );
+    Vec_IntFill( p->vLevels, Size, 0 );
+}
+/**Function*************************************************************
+
+  Synopsis    [Prepares copies for the model.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCleanTruth( Gia_Man_t * p )
+{
+    if ( p->vTruths == NULL )
+        p->vTruths = Vec_IntAlloc( Gia_ManObjNum(p) );
+    Vec_IntFill( p->vTruths, Gia_ManObjNum(p), -1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManLevelNum( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManCleanLevels( p, Gia_ManObjNum(p) );
+    p->nLevels = 0;
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            Gia_ObjSetGateLevel( p, pObj );
+        else if ( Gia_ObjIsCo(pObj) )
+            Gia_ObjSetCoLevel( p, pObj );
+        else
+            Gia_ObjSetLevel( p, pObj, 0 );
+        p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) );
+    }
+    return p->nLevels;
+}
+float Gia_ManLevelAve( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj;
+    int i, Ave = 0;
+    assert( p->vLevels );
+    Gia_ManForEachCo( p, pObj, i )
+        Ave += Gia_ObjLevel(p, pObj);
+    return (float)Ave / Gia_ManCoNum(p);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns levels using CI level information.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManGetCiLevels( Gia_Man_t * p )  
+{
+    Vec_Int_t * vCiLevels;
+    Gia_Obj_t * pObj;
+    int i;
+    if ( p->vLevels == NULL )
+        return NULL;
+    vCiLevels = Vec_IntAlloc( Gia_ManCiNum(p) );
+    Gia_ManForEachCi( p, pObj, i )
+        Vec_IntPush( vCiLevels, Gia_ObjLevel(p, pObj) );
+    return vCiLevels;
+}
+int Gia_ManSetLevels( Gia_Man_t * p, Vec_Int_t * vCiLevels )  
+{
+    Gia_Obj_t * pObj;
+    int i;
+    if ( vCiLevels == NULL )
+        return Gia_ManLevelNum( p );
+    assert( Vec_IntSize(vCiLevels) == Gia_ManCiNum(p) );
+    Gia_ManCleanLevels( p, Gia_ManObjNum(p) );
+    p->nLevels = 0;
+    Gia_ManForEachCi( p, pObj, i )
+    {
+        Gia_ObjSetLevel( p, pObj, Vec_IntEntry(vCiLevels, i) );
+        p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) );
+    }
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            Gia_ObjSetGateLevel( p, pObj );
+        else if ( Gia_ObjIsCo(pObj) )
+            Gia_ObjSetCoLevel( p, pObj );
+        else continue;
+        p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) );
+    }
+    return p->nLevels;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute reverse levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManReverseLevel( Gia_Man_t * p )  
+{
+    Vec_Int_t * vLevelRev;
+    Gia_Obj_t * pObj;
+    int i;
+    vLevelRev = Vec_IntStart( Gia_ManObjNum(p) );
+    Gia_ManForEachAndReverse( p, pObj, i )
+    {
+        int LevelR = Vec_IntEntry( vLevelRev, i );
+        if ( Gia_ObjIsMux(p, pObj) )
+        {
+            Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId0(pObj, i), LevelR + 2 );
+            Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId1(pObj, i), LevelR + 2 );
+            Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId2(p, i), LevelR + 2 );
+        }
+        else if ( Gia_ObjIsXor(pObj) )
+        {
+            Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId0(pObj, i), LevelR + 2 );
+            Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId1(pObj, i), LevelR + 2 );
+        }
+        else
+        {
+            Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId0(pObj, i), LevelR + 1 );
+            Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId1(pObj, i), LevelR + 1 );
+        }
+    }
+    return vLevelRev;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute required levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManRequiredLevel( Gia_Man_t * p )  
+{
+    Vec_Int_t * vRequired;
+    Gia_Obj_t * pObj;
+    int i, LevelMax = 0;
+    vRequired = Gia_ManReverseLevel( p );
+    Gia_ManForEachCi( p, pObj, i )
+        LevelMax = Abc_MaxInt( LevelMax, Vec_IntEntry(vRequired, Gia_ObjId(p, pObj)) );
+    Gia_ManForEachObj( p, pObj, i )
+        Vec_IntWriteEntry( vRequired, i, LevelMax - Vec_IntEntry(vRequired, i) );
+    return vRequired;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute slacks measured using the number of AIG levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManComputeSlacks( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, nLevels = Gia_ManLevelNum( p );
+    Vec_Int_t * vLevelR = Gia_ManReverseLevel( p );
+    Vec_Int_t * vSlacks = Vec_IntAlloc( Gia_ManObjNum(p) );
+    Gia_ManForEachObj( p, pObj, i )
+        Vec_IntPush( vSlacks, nLevels - Gia_ObjLevelId(p, i) - Vec_IntEntry(vLevelR, i) );
+    assert( Vec_IntSize(vSlacks) == Gia_ManObjNum(p) );
+    Vec_IntFree( vLevelR );
+    return vSlacks;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCreateValueRefs( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        pObj->Value = 0;
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            Gia_ObjFanin0(pObj)->Value++;
+            Gia_ObjFanin1(pObj)->Value++;
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+            Gia_ObjFanin0(pObj)->Value++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns references.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCreateRefs( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj;
+    int i;
+    assert( p->pRefs == NULL );
+    p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            Gia_ObjRefFanin0Inc( p, pObj );
+            Gia_ObjRefFanin1Inc( p, pObj );
+            if ( Gia_ObjIsMuxId(p, i) )
+                Gia_ObjRefFanin2Inc( p, pObj );
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+            Gia_ObjRefFanin0Inc( p, pObj );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns references.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Gia_ManCreateMuxRefs( Gia_Man_t * p )  
+{
+    Gia_Obj_t * pObj, * pCtrl, * pFan0, * pFan1;
+    int i, * pMuxRefs;
+    pMuxRefs = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjRecognizeExor( pObj, &pFan0, &pFan1 ) )
+            continue;
+        if ( !Gia_ObjIsMuxType(pObj) )
+            continue;
+        pCtrl = Gia_ObjRecognizeMux( pObj, &pFan0, &pFan1 );
+        pMuxRefs[ Gia_ObjId(p, Gia_Regular(pCtrl)) ]++;
+    }
+    return pMuxRefs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the maximum frontier size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManDfsForCrossCut_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+    {
+        Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+        return;
+    }
+    if ( Gia_ObjIsCo(pObj) )
+    {
+        Gia_ObjFanin0(pObj)->Value++;
+        Gia_ManDfsForCrossCut_rec( p, Gia_ObjFanin0(pObj), vNodes );
+        Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ObjFanin0(pObj)->Value++;
+    Gia_ObjFanin1(pObj)->Value++;
+    Gia_ManDfsForCrossCut_rec( p, Gia_ObjFanin0(pObj), vNodes );
+    Gia_ManDfsForCrossCut_rec( p, Gia_ObjFanin1(pObj), vNodes );
+    Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+}
+Vec_Int_t * Gia_ManDfsForCrossCut( Gia_Man_t * p, int fReverse )
+{
+    Vec_Int_t * vNodes;
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManCleanValue( p );
+    vNodes = Vec_IntAlloc( Gia_ManObjNum(p) );
+    Gia_ManIncrementTravId( p );
+    if ( fReverse )
+    {
+        Gia_ManForEachCoReverse( p, pObj, i )
+            if ( !Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) )
+                Gia_ManDfsForCrossCut_rec( p, pObj, vNodes );
+    }
+    else
+    {
+        Gia_ManForEachCo( p, pObj, i )
+            if ( !Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) )
+                Gia_ManDfsForCrossCut_rec( p, pObj, vNodes );
+    }
+    return vNodes;
+}
+int Gia_ManCrossCut( Gia_Man_t * p, int fReverse )
+{
+    Vec_Int_t * vNodes;
+    Gia_Obj_t * pObj;
+    int i, nCutCur = 0, nCutMax = 0;
+    vNodes = Gia_ManDfsForCrossCut( p, fReverse );
+    Gia_ManForEachObjVec( vNodes, p, pObj, i )
+    {
+        if ( pObj->Value )
+            nCutCur++;
+        if ( nCutMax < nCutCur )
+            nCutMax = nCutCur;
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            if ( --Gia_ObjFanin0(pObj)->Value == 0 )
+                nCutCur--;
+            if ( --Gia_ObjFanin1(pObj)->Value == 0 )
+                nCutCur--;
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+        {
+            if ( --Gia_ObjFanin0(pObj)->Value == 0 )
+                nCutCur--;
+        }
+    }
+    Vec_IntFree( vNodes );
+    Gia_ManForEachObj( p, pObj, i )
+        assert( pObj->Value == 0 );
+    return nCutMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Makes sure the manager is normalized.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManIsNormalized( Gia_Man_t * p )  
+{
+    int i, nOffset;
+    nOffset = 1;
+    for ( i = 0; i < Gia_ManCiNum(p); i++ )
+        if ( !Gia_ObjIsCi( Gia_ManObj(p, nOffset+i) ) )
+            return 0;
+    nOffset = 1 + Gia_ManCiNum(p) + Gia_ManAndNum(p);
+    for ( i = 0; i < Gia_ManCoNum(p); i++ )
+        if ( !Gia_ObjIsCo( Gia_ManObj(p, nOffset+i) ) )
+            return 0;
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects PO Ids into one array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManCollectPoIds( Gia_Man_t * p )
+{
+    Vec_Int_t * vStart;
+    int Entry, i;
+    vStart = Vec_IntAlloc( Gia_ManPoNum(p) );
+    Vec_IntForEachEntryStop( p->vCos, Entry, i, Gia_ManPoNum(p) )
+        Vec_IntPush( vStart, Entry );
+    return vStart;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node is the root of MUX or EXOR/NEXOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ObjIsMuxType( Gia_Obj_t * pNode )
+{
+    Gia_Obj_t * pNode0, * pNode1;
+    // check that the node is regular
+    assert( !Gia_IsComplement(pNode) );
+    // if the node is not AND, this is not MUX
+    if ( !Gia_ObjIsAnd(pNode) || Gia_ObjIsBuf(pNode) )
+        return 0;
+    // if the children are not complemented, this is not MUX
+    if ( !Gia_ObjFaninC0(pNode) || !Gia_ObjFaninC1(pNode) )
+        return 0;
+    // get children
+    pNode0 = Gia_ObjFanin0(pNode);
+    pNode1 = Gia_ObjFanin1(pNode);
+    // if the children are not ANDs, this is not MUX
+    if ( !Gia_ObjIsAnd(pNode0) || !Gia_ObjIsAnd(pNode1) )
+        return 0;
+    // otherwise the node is MUX iff it has a pair of equal grandchildren
+    return (Gia_ObjFanin0(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC0(pNode1))) || 
+           (Gia_ObjFanin0(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC1(pNode1))) ||
+           (Gia_ObjFanin1(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC0(pNode1))) ||
+           (Gia_ObjFanin1(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC1(pNode1)));
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recognizes what nodes are inputs of the EXOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ObjRecognizeExor( Gia_Obj_t * pObj, Gia_Obj_t ** ppFan0, Gia_Obj_t ** ppFan1 )
+{
+    Gia_Obj_t * p0, * p1;
+    assert( !Gia_IsComplement(pObj) );
+    if ( !Gia_ObjIsAnd(pObj) || Gia_ObjIsBuf(pObj) )
+        return 0;
+    assert( Gia_ObjIsAnd(pObj) );
+    p0 = Gia_ObjChild0(pObj);
+    p1 = Gia_ObjChild1(pObj);
+    if ( !Gia_IsComplement(p0) || !Gia_IsComplement(p1) )
+        return 0;
+    p0 = Gia_Regular(p0);
+    p1 = Gia_Regular(p1);
+    if ( !Gia_ObjIsAnd(p0) || !Gia_ObjIsAnd(p1) )
+        return 0;
+    if ( Gia_ObjFanin0(p0) != Gia_ObjFanin0(p1) || Gia_ObjFanin1(p0) != Gia_ObjFanin1(p1) )
+        return 0;
+    if ( Gia_ObjFaninC0(p0) == Gia_ObjFaninC0(p1) || Gia_ObjFaninC1(p0) == Gia_ObjFaninC1(p1) )
+        return 0;
+    *ppFan0 = Gia_ObjChild0(p0);
+    *ppFan1 = Gia_ObjChild1(p0);
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recognizes what nodes are control and data inputs of a MUX.]
+
+  Description [If the node is a MUX, returns the control variable C.
+  Assigns nodes T and E to be the then and else variables of the MUX. 
+  Node C is never complemented. Nodes T and E can be complemented.
+  This function also recognizes EXOR/NEXOR gates as MUXes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Obj_t * Gia_ObjRecognizeMux( Gia_Obj_t * pNode, Gia_Obj_t ** ppNodeT, Gia_Obj_t ** ppNodeE )
+{
+    Gia_Obj_t * pNode0, * pNode1;
+    assert( !Gia_IsComplement(pNode) );
+    assert( Gia_ObjIsMuxType(pNode) );
+    // get children
+    pNode0 = Gia_ObjFanin0(pNode);
+    pNode1 = Gia_ObjFanin1(pNode);
+
+    // find the control variable
+    if ( Gia_ObjFanin1(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC1(pNode1)) )
+    {
+//        if ( FrGia_IsComplement(pNode1->p2) )
+        if ( Gia_ObjFaninC1(pNode0) )
+        { // pNode2->p2 is positive phase of C
+            *ppNodeT = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1);
+            *ppNodeE = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1);
+            return Gia_ObjChild1(pNode1);//pNode2->p2;
+        }
+        else
+        { // pNode1->p2 is positive phase of C
+            *ppNodeT = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1);
+            *ppNodeE = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1);
+            return Gia_ObjChild1(pNode0);//pNode1->p2;
+        }
+    }
+    else if ( Gia_ObjFanin0(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC0(pNode1)) )
+    {
+//        if ( FrGia_IsComplement(pNode1->p1) )
+        if ( Gia_ObjFaninC0(pNode0) )
+        { // pNode2->p1 is positive phase of C
+            *ppNodeT = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2);
+            *ppNodeE = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2);
+            return Gia_ObjChild0(pNode1);//pNode2->p1;
+        }
+        else
+        { // pNode1->p1 is positive phase of C
+            *ppNodeT = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2);
+            *ppNodeE = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2);
+            return Gia_ObjChild0(pNode0);//pNode1->p1;
+        }
+    }
+    else if ( Gia_ObjFanin0(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC1(pNode1)) )
+    {
+//        if ( FrGia_IsComplement(pNode1->p1) )
+        if ( Gia_ObjFaninC0(pNode0) )
+        { // pNode2->p2 is positive phase of C
+            *ppNodeT = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1);
+            *ppNodeE = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2);
+            return Gia_ObjChild1(pNode1);//pNode2->p2;
+        }
+        else
+        { // pNode1->p1 is positive phase of C
+            *ppNodeT = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2);
+            *ppNodeE = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1);
+            return Gia_ObjChild0(pNode0);//pNode1->p1;
+        }
+    }
+    else if ( Gia_ObjFanin1(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC0(pNode1)) )
+    {
+//        if ( FrGia_IsComplement(pNode1->p2) )
+        if ( Gia_ObjFaninC1(pNode0) )
+        { // pNode2->p1 is positive phase of C
+            *ppNodeT = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2);
+            *ppNodeE = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1);
+            return Gia_ObjChild0(pNode1);//pNode2->p1;
+        }
+        else
+        { // pNode1->p2 is positive phase of C
+            *ppNodeT = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1);
+            *ppNodeE = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2);
+            return Gia_ObjChild1(pNode0);//pNode1->p2;
+        }
+    }
+    assert( 0 ); // this is not MUX
+    return NULL;
+}
+int Gia_ObjRecognizeMuxLits( Gia_Man_t * p, Gia_Obj_t * pNode, int * iLitT, int * iLitE )
+{
+    Gia_Obj_t * pNodeT, * pNodeE;
+    Gia_Obj_t * pCtrl = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE );
+    assert( pCtrl != NULL );
+    *iLitT = Gia_Obj2Lit( p, pNodeT );
+    *iLitE = Gia_Obj2Lit( p, pNodeE );
+    return Gia_Obj2Lit( p, pCtrl );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences the node's MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_NodeDeref_rec( Gia_Man_t * p, Gia_Obj_t * pNode )
+{
+    Gia_Obj_t * pFanin;
+    int Counter = 0;
+    if ( Gia_ObjIsCi(pNode) )
+        return 0;
+    assert( Gia_ObjIsAnd(pNode) );
+    pFanin = Gia_ObjFanin0(pNode);
+    assert( Gia_ObjRefNum(p, pFanin) > 0 );
+    if ( Gia_ObjRefDec(p, pFanin) == 0 )
+        Counter += Gia_NodeDeref_rec( p, pFanin );
+    pFanin = Gia_ObjFanin1(pNode);
+    assert( Gia_ObjRefNum(p, pFanin) > 0 );
+    if ( Gia_ObjRefDec(p, pFanin) == 0 )
+        Counter += Gia_NodeDeref_rec( p, pFanin );
+    return Counter + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [References the node's MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_NodeRef_rec( Gia_Man_t * p, Gia_Obj_t * pNode )
+{
+    Gia_Obj_t * pFanin;
+    int Counter = 0;
+    if ( Gia_ObjIsCi(pNode) )
+        return 0;
+    assert( Gia_ObjIsAnd(pNode) );
+    pFanin = Gia_ObjFanin0(pNode);
+    if ( Gia_ObjRefInc(p, pFanin) == 0 )
+        Counter += Gia_NodeRef_rec( p, pFanin );
+    pFanin = Gia_ObjFanin1(pNode);
+    if ( Gia_ObjRefInc(p, pFanin) == 0 )
+        Counter += Gia_NodeRef_rec( p, pFanin );
+    return Counter + 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [References the node's MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManPoMffcSize( Gia_Man_t * p )
+{
+    Gia_ManCreateRefs( p );
+    return Gia_NodeDeref_rec( p, Gia_ObjFanin0(Gia_ManPo(p, 0)) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of internal nodes in the MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_NodeMffcSize( Gia_Man_t * p, Gia_Obj_t * pNode )
+{
+    int ConeSize1, ConeSize2;
+    assert( !Gia_IsComplement(pNode) );
+    assert( Gia_ObjIsCand(pNode) );
+    ConeSize1 = Gia_NodeDeref_rec( p, pNode );
+    ConeSize2 = Gia_NodeRef_rec( p, pNode );
+    assert( ConeSize1 == ConeSize2 );
+    assert( ConeSize1 >= 0 );
+    return ConeSize1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if AIG has dangling nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManHasDangling( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, Counter = 0;
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        pObj->fMark0 = 0;
+        if ( Gia_ObjIsCo(pObj) )
+            Gia_ObjFanin0(pObj)->fMark0 = 1;
+        else if ( Gia_ObjIsMux(p, pObj) )
+        {
+            Gia_ObjFanin0(pObj)->fMark0 = 1;
+            Gia_ObjFanin1(pObj)->fMark0 = 1;
+            Gia_ObjFanin2(p, pObj)->fMark0 = 1;
+        }
+        else if ( Gia_ObjIsAnd(pObj) )
+        {
+            Gia_ObjFanin0(pObj)->fMark0 = 1;
+            Gia_ObjFanin1(pObj)->fMark0 = 1;
+        }
+    }
+    Gia_ManForEachAnd( p, pObj, i )
+        Counter += !pObj->fMark0;
+    Gia_ManCleanMark0( p );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if AIG has dangling nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManMarkDangling( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, Counter = 0;
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        pObj->fMark0 = 0;
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            Gia_ObjFanin0(pObj)->fMark0 = 1;
+            Gia_ObjFanin1(pObj)->fMark0 = 1;
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+            Gia_ObjFanin0(pObj)->fMark0 = 1;
+    }
+    Gia_ManForEachAnd( p, pObj, i )
+        Counter += !pObj->fMark0;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if AIG has dangling nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManGetDangling( Gia_Man_t * p )
+{
+    Vec_Int_t * vDangles;
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        pObj->fMark0 = 0;
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            Gia_ObjFanin0(pObj)->fMark0 = 1;
+            Gia_ObjFanin1(pObj)->fMark0 = 1;
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+            Gia_ObjFanin0(pObj)->fMark0 = 1;
+    }
+    vDangles = Vec_IntAlloc( 100 );
+    Gia_ManForEachAnd( p, pObj, i )
+        if ( !pObj->fMark0 )
+            Vec_IntPush( vDangles, i );
+    Gia_ManCleanMark0( p );
+    return vDangles;
+}
+/**Function*************************************************************
+
+  Synopsis    [Verbose printing of the AIG node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ObjPrint( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( pObj == NULL )
+    {
+        printf( "Object is NULL." );
+        return;
+    }
+    if ( Gia_IsComplement(pObj) )
+    {
+        printf( "Compl " );
+        pObj = Gia_Not(pObj);
+    }
+    assert( !Gia_IsComplement(pObj) );
+    printf( "Obj %4d : ", Gia_ObjId(p, pObj) );
+    if ( Gia_ObjIsConst0(pObj) )
+        printf( "constant 0" );
+    else if ( Gia_ObjIsPi(p, pObj) )
+        printf( "PI" );
+    else if ( Gia_ObjIsPo(p, pObj) )
+        printf( "PO( %4d%s )", Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " ") );
+    else if ( Gia_ObjIsCi(pObj) )
+        printf( "RO( %4d%s )", Gia_ObjFaninId0p(p, Gia_ObjRoToRi(p, pObj)), (Gia_ObjFaninC0(Gia_ObjRoToRi(p, pObj))? "\'" : " ") );
+    else if ( Gia_ObjIsCo(pObj) )
+        printf( "RI( %4d%s )", Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " ") );
+//    else if ( Gia_ObjIsBuf(pObj) )
+//        printf( "BUF( %d%s )", Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " ") );
+    else if ( Gia_ObjIsXor(pObj) )
+        printf( "XOR( %4d%s, %4d%s )", 
+            Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " "), 
+            Gia_ObjFaninId1p(p, pObj), (Gia_ObjFaninC1(pObj)? "\'" : " ") );
+    else if ( Gia_ObjIsMuxId(p, Gia_ObjId(p, pObj)) )
+        printf( "MUX( %4d%s, %4d%s, %4d%s )", 
+            Gia_ObjFaninId2p(p, pObj), (Gia_ObjFaninC2(p, pObj)? "\'" : " "), 
+            Gia_ObjFaninId1p(p, pObj), (Gia_ObjFaninC1(pObj)? "\'" : " "), 
+            Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " ") );
+    else
+        printf( "AND( %4d%s, %4d%s )", 
+            Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " "), 
+            Gia_ObjFaninId1p(p, pObj), (Gia_ObjFaninC1(pObj)? "\'" : " ") );
+    if ( p->pRefs )
+        printf( " (refs = %3d)", Gia_ObjRefNum(p, pObj) );
+    if ( pObj->fMark0 )
+        printf( " mark0" );
+    if ( pObj->fMark1 )
+        printf( " mark1" );
+    printf( "\n" );
+/*
+    if ( p->pRefs )
+    {
+        Gia_Obj_t * pFanout;
+        int i;
+        int iFan = -1; // Suppress "might be used uninitialized"
+        printf( "\nFanouts:\n" );
+        Gia_ObjForEachFanout( p, pObj, pFanout, iFan, i )
+        {
+            printf( "    " );
+            printf( "Node %4d : ", Gia_ObjId(pFanout) );
+            if ( Gia_ObjIsPo(pFanout) )
+                printf( "PO( %4d%s )", Gia_ObjFanin0(pFanout)->Id, (Gia_ObjFaninC0(pFanout)? "\'" : " ") );
+            else if ( Gia_ObjIsBuf(pFanout) )
+                printf( "BUF( %d%s )", Gia_ObjFanin0(pFanout)->Id, (Gia_ObjFaninC0(pFanout)? "\'" : " ") );
+            else
+                printf( "AND( %4d%s, %4d%s )", 
+                    Gia_ObjFanin0(pFanout)->Id, (Gia_ObjFaninC0(pFanout)? "\'" : " "), 
+                    Gia_ObjFanin1(pFanout)->Id, (Gia_ObjFaninC1(pFanout)? "\'" : " ") );
+            printf( "\n" );
+        }
+        return;
+    }
+*/
+}
+void Gia_ManPrint( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    printf( "GIA manager has %d ANDs, %d XORs, %d MUXes.\n", 
+        Gia_ManAndNum(p) - Gia_ManXorNum(p) - Gia_ManMuxNum(p), Gia_ManXorNum(p), Gia_ManMuxNum(p) ); 
+    Gia_ManForEachObj( p, pObj, i )
+        Gia_ObjPrint( p, pObj );
+}
+void Gia_ManPrintCo_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        Gia_ManPrintCo_rec( p, Gia_ObjFanin0(pObj) );
+        Gia_ManPrintCo_rec( p, Gia_ObjFanin1(pObj) );
+    }
+    Gia_ObjPrint( p, pObj );
+}
+void Gia_ManPrintCo( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    assert( Gia_ObjIsCo(pObj) );
+    printf( "TFI cone of CO number %d:\n", Gia_ObjCioId(pObj) );
+    Gia_ManPrintCo_rec( p, Gia_ObjFanin0(pObj) );
+    Gia_ObjPrint( p, pObj );
+}
+
+void Gia_ManPrintCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes )
+{
+    if ( Vec_IntFind(vNodes, Gia_ObjId(p, pObj)) >= 0 )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManPrintCollect_rec( p, Gia_ObjFanin0(pObj), vNodes );
+    Gia_ManPrintCollect_rec( p, Gia_ObjFanin1(pObj), vNodes );
+    Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+}
+void Gia_ManPrintCone( Gia_Man_t * p, Gia_Obj_t * pObj, int * pLeaves, int nLeaves, Vec_Int_t * vNodes )
+{
+    int i;
+    Vec_IntClear( vNodes );
+    for ( i = 0; i < nLeaves; i++ )
+        Vec_IntPush( vNodes, pLeaves[i] );
+    Gia_ManPrintCollect_rec( p, pObj, vNodes );
+    printf( "GIA logic cone for node %d:\n", Gia_ObjId(p, pObj) );
+    Gia_ManForEachObjVec( vNodes, p, pObj, i )
+        Gia_ObjPrint( p, pObj );
+}
+
+void Gia_ManPrintCollect2_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes )
+{
+    if ( Vec_IntFind(vNodes, Gia_ObjId(p, pObj)) >= 0 )
+        return;
+    if ( Gia_ObjIsCo(pObj) || Gia_ObjIsAnd(pObj) )
+        Gia_ManPrintCollect2_rec( p, Gia_ObjFanin0(pObj), vNodes );
+    if ( Gia_ObjIsAnd(pObj) )
+        Gia_ManPrintCollect2_rec( p, Gia_ObjFanin1(pObj), vNodes );
+    Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+}
+void Gia_ManPrintCone2( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    Vec_Int_t * vNodes;
+    int i;
+    vNodes = Vec_IntAlloc( 100 );
+    Gia_ManPrintCollect2_rec( p, pObj, vNodes );
+    printf( "GIA logic cone for node %d:\n", Gia_ObjId(p, pObj) );
+    Gia_ManForEachObjVec( vNodes, p, pObj, i )
+        Gia_ObjPrint( p, pObj );
+    Vec_IntFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Complements the constraint outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManInvertConstraints( Gia_Man_t * pAig )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    if ( Gia_ManConstrNum(pAig) == 0 )
+        return;
+    Gia_ManForEachPo( pAig, pObj, i )
+        if ( i >= Gia_ManPoNum(pAig) - Gia_ManConstrNum(pAig) )
+            Gia_ObjFlipFaninC0( pObj );
+}
+void Gia_ManInvertPos( Gia_Man_t * pAig )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachPo( pAig, pObj, i )
+        Gia_ObjFlipFaninC0( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Testing the speedup due to grouping POs into batches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCollectObjs_rec( Gia_Man_t * p, int iObjId, Vec_Int_t * vObjs, int Limit )
+{
+    Gia_Obj_t * pObj;
+    if ( Vec_IntSize(vObjs) == Limit )
+        return;
+    if ( Gia_ObjIsTravIdCurrentId(p, iObjId) )
+        return;
+    Gia_ObjSetTravIdCurrentId(p, iObjId);
+    pObj = Gia_ManObj( p, iObjId );
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        Gia_ManCollectObjs_rec( p, Gia_ObjFaninId0p(p, pObj), vObjs, Limit );
+        if ( Vec_IntSize(vObjs) == Limit )
+            return;
+        Gia_ManCollectObjs_rec( p, Gia_ObjFaninId1p(p, pObj), vObjs, Limit );
+        if ( Vec_IntSize(vObjs) == Limit )
+            return;
+    }
+    Vec_IntPush( vObjs, iObjId );
+}
+unsigned * Gia_ManComputePoTruthTables( Gia_Man_t * p, int nBytesMax )
+{
+    int nVars = Gia_ManPiNum(p);
+    int nTruthWords = Abc_TruthWordNum( nVars );
+    int nTruths = nBytesMax / (sizeof(unsigned) * nTruthWords);
+    int nTotalNodes = 0, nRounds = 0;
+    Vec_Int_t * vObjs;
+    Gia_Obj_t * pObj;
+    abctime clk = Abc_Clock();
+    int i;
+    printf( "Var = %d. Words = %d. Truths = %d.\n", nVars, nTruthWords, nTruths );
+    vObjs = Vec_IntAlloc( nTruths );
+    Gia_ManIncrementTravId( p );
+    Gia_ManForEachPo( p, pObj, i )
+    {
+        Gia_ManCollectObjs_rec( p, Gia_ObjFaninId0p(p, pObj), vObjs, nTruths );
+        if ( Vec_IntSize(vObjs) == nTruths )
+        {
+            nRounds++;
+//            printf( "%d ", i );
+            nTotalNodes += Vec_IntSize( vObjs );
+            Vec_IntClear( vObjs );
+            Gia_ManIncrementTravId( p );
+        }
+    }
+//    printf( "\n" );
+    nTotalNodes += Vec_IntSize( vObjs );
+    Vec_IntFree( vObjs );
+
+    printf( "Rounds = %d. Objects = %d. Total = %d.   ", nRounds, Gia_ManObjNum(p), nTotalNodes );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+
+    return NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the manager are structural identical.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCompare( Gia_Man_t * p1, Gia_Man_t * p2 )
+{
+    Gia_Obj_t * pObj1, * pObj2;
+    int i;
+    if ( Gia_ManObjNum(p1) != Gia_ManObjNum(p2) )
+    {
+        printf( "AIGs have different number of objects.\n" );
+        return 0;
+    }
+    Gia_ManCleanValue( p1 );
+    Gia_ManCleanValue( p2 );
+    Gia_ManForEachObj( p1, pObj1, i )
+    {
+        pObj2 = Gia_ManObj( p2, i );
+        if ( memcmp( pObj1, pObj2, sizeof(Gia_Obj_t) ) )
+        {
+            printf( "Objects %d are different.\n", i );
+            return 0;
+        }
+        if ( p1->pReprs && p2->pReprs )
+        {
+            if ( memcmp( &p1->pReprs[i], &p2->pReprs[i], sizeof(Gia_Rpr_t) ) )
+            {
+                printf( "Representatives of objects %d are different.\n", i );
+                return 0;
+            }
+        }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks nodes that appear as faninis of other nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManMarkFanoutDrivers( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        pObj->fMark0 = 0;
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            Gia_ObjFanin0(pObj)->fMark0 = 1;
+            Gia_ObjFanin1(pObj)->fMark0 = 1;
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+            Gia_ObjFanin0(pObj)->fMark0 = 1;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Swaps PO number 0 with PO number i.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManSwapPos( Gia_Man_t * p, int i )
+{
+    int Lit0, LitI;
+    assert( i >= 0 && i < Gia_ManPoNum(p) );
+    if ( i == 0 )
+        return;
+    Lit0 = Gia_ObjFaninLit0p( p, Gia_ManPo(p, 0) );
+    LitI = Gia_ObjFaninLit0p( p, Gia_ManPo(p, i) );
+    Gia_ManPatchCoDriver( p, 0, LitI );
+    Gia_ManPatchCoDriver( p, i, Lit0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Save/load value from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManSaveValue( Gia_Man_t * p )
+{
+    Vec_Int_t * vValues;
+    Gia_Obj_t * pObj;
+    int i;
+    vValues = Vec_IntAlloc( Gia_ManObjNum(p) );
+    Gia_ManForEachObj( p, pObj, i )
+        Vec_IntPush( vValues, pObj->Value );
+    return vValues;
+}
+void Gia_ManLoadValue( Gia_Man_t * p, Vec_Int_t * vValues )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+        pObj->Value = Vec_IntEntry(vValues, i);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array containing the first fanout of each object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManFirstFanouts( Gia_Man_t * p )
+{
+    Vec_Int_t * vFans = Vec_IntStart( Gia_ManObjNum(p) );
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            if ( Vec_IntEntry(vFans, Gia_ObjFaninId0p(p, pObj)) == 0 )
+                Vec_IntWriteEntry(vFans, Gia_ObjFaninId0p(p, pObj), i);
+            if ( Vec_IntEntry(vFans, Gia_ObjFaninId1p(p, pObj)) == 0 )
+                Vec_IntWriteEntry(vFans, Gia_ObjFaninId1p(p, pObj), i);
+            if ( Gia_ObjIsMuxId(p, i) && Vec_IntEntry(vFans, Gia_ObjFaninId2p(p, pObj)) == 0 )
+                Vec_IntWriteEntry(vFans, Gia_ObjFaninId2p(p, pObj), i);
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+        {
+            if ( Vec_IntEntry(vFans, Gia_ObjFaninId0p(p, pObj)) == 0 )
+                Vec_IntWriteEntry(vFans, Gia_ObjFaninId0p(p, pObj), i);
+        }
+    }
+    return vFans;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if AIG has choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManHasChoices_very_old( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, Counter1 = 0, Counter2 = 0;
+    int nFailNoRepr = 0;
+    int nFailHaveRepr = 0;
+    int nChoiceNodes = 0;
+    int nChoices = 0;
+    if ( p->pReprs == NULL || p->pNexts == NULL )
+        return 0;
+    // check if there are any representatives
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) )
+        {
+//            printf( "%d ", i );
+            Counter1++;
+        }
+//        if ( Gia_ObjNext( p, Gia_ObjId(p, pObj) ) )
+//            Counter2++;
+    }
+//    printf( "\n" );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+//        if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) )
+//            Counter1++;
+        if ( Gia_ObjNext( p, Gia_ObjId(p, pObj) ) )
+        {
+//            printf( "%d ", i );
+            Counter2++;
+        }
+    }
+//    printf( "\n" );
+    if ( Counter1 == 0 )
+    {
+        printf( "Warning: AIG has repr data-strucure but not reprs.\n" );
+        return 0;
+    }
+    printf( "%d nodes have reprs.\n", Counter1 );
+    printf( "%d nodes have nexts.\n", Counter2 );
+    // check if there are any internal nodes without fanout
+    // make sure all nodes without fanout have representatives
+    // make sure all nodes with fanout have no representatives
+    ABC_FREE( p->pRefs );
+    Gia_ManCreateRefs( p );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        if ( Gia_ObjRefNum(p, pObj) == 0 )
+        {
+            if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) == NULL )
+                nFailNoRepr++;
+            else
+                nChoices++;
+        }
+        else
+        {
+            if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) != NULL )
+                nFailHaveRepr++;
+            if ( Gia_ObjNextObj( p, Gia_ObjId(p, pObj) ) != NULL )
+                nChoiceNodes++;
+        }
+        if ( Gia_ObjReprObj( p, i ) )
+            assert( Gia_ObjRepr(p, i) < i );
+    }
+    if ( nChoices == 0 )
+        return 0;
+    if ( nFailNoRepr )
+    {
+        printf( "Gia_ManHasChoices_very_old(): Error: %d internal nodes have no fanout and no repr.\n", nFailNoRepr );
+//        return 0;
+    }
+    if ( nFailHaveRepr )
+    {
+        printf( "Gia_ManHasChoices_very_old(): Error: %d internal nodes have both fanout and repr.\n", nFailHaveRepr );
+//        return 0;
+    }
+//    printf( "Gia_ManHasChoices_very_old(): AIG has %d choice nodes with %d choices.\n", nChoiceNodes, nChoices );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Proving multi-output properties.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManGroupProve( Gia_Man_t * pInit, char * pCommLine, int nGroupSize, int fVerbose )
+{
+    Abc_Frame_t * pAbc = Abc_FrameReadGlobalFrame();
+    Gia_Man_t * p = Gia_ManDup( pInit );
+    Gia_Man_t * pGroup;
+    Vec_Int_t * vOuts;
+    Vec_Int_t * vOutMap;
+    Vec_Ptr_t * vCexes;
+    int i, k, nGroupCur, nGroups;
+    abctime clk, timeComm = 0;
+    abctime timeStart = Abc_Clock();
+    // pre-conditions
+    assert( nGroupSize > 0 );
+    assert( pCommLine != NULL );
+    assert( p->nConstrs == 0 );
+    Abc_Print( 1, "RUNNING MultiProve: Group size = %d. Command line = \"%s\".\n", nGroupSize, pCommLine );
+    // create output map
+    vOuts   = Vec_IntStartNatural( Gia_ManPoNum(p) );
+    vOutMap = Vec_IntAlloc( Gia_ManPoNum(p) );
+    vCexes  = Vec_PtrAlloc( Gia_ManPoNum(p) );
+    nGroups = Gia_ManPoNum(p) / nGroupSize + (int)((Gia_ManPoNum(p) % nGroupSize) > 0);
+    for ( i = 0; i < nGroups; i++ )
+    {
+        // derive the group
+        nGroupCur = ((i + 1) * nGroupSize < Gia_ManPoNum(p)) ? nGroupSize : Gia_ManPoNum(p) - i * nGroupSize;
+        pGroup = Gia_ManDupCones( p, Vec_IntArray(vOuts) + i * nGroupSize, nGroupCur, 0 );
+        Abc_Print( 1, "GROUP %4d : %4d <= PoId < %4d : ", i, i * nGroupSize, i * nGroupSize + nGroupCur );
+        // set the current GIA
+        Abc_FrameUpdateGia( pAbc, pGroup );
+        // solve the group
+        clk = Abc_Clock();
+        Cmd_CommandExecute( pAbc, pCommLine );
+        timeComm += Abc_Clock() - clk;
+        // get the solution status
+        if ( nGroupSize == 1 )
+        {
+            Vec_IntPush( vOutMap, Abc_FrameReadProbStatus(pAbc) );
+            Vec_PtrPush( vCexes, Abc_FrameReadCex(pAbc) );
+        }
+        else // if ( nGroupSize > 1 )  
+        {
+            Vec_Int_t * vStatusCur = Abc_FrameReadPoStatuses( pAbc );
+            Vec_Ptr_t * vCexesCur = Abc_FrameReadCexVec( pAbc );
+            assert( vStatusCur != NULL ); // only works for "bmc3" and "pdr"
+//            assert( vCexesCur != NULL );
+            for ( k = 0; k < nGroupCur; k++ )
+            {
+                Vec_IntPush( vOutMap, Vec_IntEntry(vStatusCur, k) );
+                Vec_PtrPush( vCexes, vCexesCur ? Vec_PtrEntry(vCexesCur, k) : NULL );
+            }
+        }
+    }
+    assert( Vec_PtrSize(vCexes) == Gia_ManPoNum(p) );
+    assert( Vec_IntSize(vOutMap) == Gia_ManPoNum(p) );
+    // set CEXes
+    if ( Vec_PtrCountZero(vCexes) < Vec_PtrSize(vCexes) )
+        Abc_FrameReplaceCexVec( pAbc, &vCexes );
+    else  // there is no CEXes
+        Vec_PtrFree( vCexes );
+    // report the result
+    Abc_Print( 1, "SUMMARY:  " );
+    Abc_Print( 1, "Properties = %6d. ", Gia_ManPoNum(p) );
+    Abc_Print( 1, "UNSAT = %6d. ",      Vec_IntCountEntry(vOutMap, 1) );
+    Abc_Print( 1, "SAT = %6d. ",        Vec_IntCountEntry(vOutMap, 0) );
+    Abc_Print( 1, "UNDEC = %6d. ",      Vec_IntCountEntry(vOutMap, -1) );
+    Abc_Print( 1, "\n" );
+    Abc_PrintTime( 1, "Command time", timeComm );
+    Abc_PrintTime( 1, "Total time  ", Abc_Clock() - timeStart );
+    // cleanup
+    Vec_IntFree( vOuts );
+    Gia_ManStop( p );
+    return vOutMap;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManPoXSim( Gia_Man_t * p, int nFrames, int fVerbose )
+{
+    Vec_Int_t * vRes;
+    Gia_Obj_t * pObj;
+    int f, k, nLeft = Gia_ManPoNum(p);
+    vRes = Vec_IntAlloc( Gia_ManPoNum(p) );
+    Vec_IntFill( vRes, Gia_ManPoNum(p), nFrames );
+    Gia_ObjTerSimSet0( Gia_ManConst0(p) );
+    Gia_ManForEachRi( p, pObj, k )
+        Gia_ObjTerSimSet0( pObj );
+    for ( f = 0; f < nFrames; f++ )
+    {
+        Gia_ManForEachPi( p, pObj, k )
+            Gia_ObjTerSimSetX( pObj );
+        Gia_ManForEachRo( p, pObj, k )
+            Gia_ObjTerSimRo( p, pObj );
+        Gia_ManForEachAnd( p, pObj, k )
+            Gia_ObjTerSimAnd( pObj );
+        Gia_ManForEachCo( p, pObj, k )
+            Gia_ObjTerSimCo( pObj );
+        if ( fVerbose )
+        {
+            Gia_ManForEachPo( p, pObj, k )
+                Gia_ObjTerSimPrint( pObj );
+            printf( "\n" );
+        }
+        Gia_ManForEachPo( p, pObj, k )
+            if ( Vec_IntEntry(vRes, k) == nFrames && Gia_ObjTerSimGetX(pObj) )
+                Vec_IntWriteEntry(vRes, k, f), nLeft--;
+        if ( nLeft == 0 )
+            break;
+    }
+    if ( fVerbose )
+    {
+        if ( nLeft == 0 )
+            printf( "Simulation converged after %d frames.\n", f+1 );
+        else
+            printf( "Simulation terminated after %d frames.\n", nFrames );
+    }        
+//    Vec_IntPrint( vRes );
+    return vRes;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/gia/module.make b/abc-build/src/aig/gia/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/gia/module.make
@@ -0,0 +1,68 @@
+SRC +=	src/aig/gia/giaAig.c \
+	src/aig/gia/giaAgi.c \
+	src/aig/gia/giaAiger.c \
+	src/aig/gia/giaAigerExt.c \
+	src/aig/gia/giaBalance.c \
+	src/aig/gia/giaBalance2.c \
+	src/aig/gia/giaBidec.c \
+	src/aig/gia/giaCCof.c \
+	src/aig/gia/giaCex.c \
+	src/aig/gia/giaCof.c \
+	src/aig/gia/giaCone.c \
+	src/aig/gia/giaCSatOld.c \
+	src/aig/gia/giaCSat.c \
+	src/aig/gia/giaCTas.c \
+	src/aig/gia/giaDfs.c \
+	src/aig/gia/giaDup.c \
+	src/aig/gia/giaEmbed.c \
+	src/aig/gia/giaEnable.c \
+	src/aig/gia/giaEquiv.c \
+	src/aig/gia/giaEra.c \
+	src/aig/gia/giaEra2.c \
+	src/aig/gia/giaFalse.c \
+	src/aig/gia/giaFanout.c \
+	src/aig/gia/giaForce.c \
+	src/aig/gia/giaFrames.c \
+	src/aig/gia/giaFront.c \
+	src/aig/gia/giaFx.c \
+	src/aig/gia/giaGig.c \
+	src/aig/gia/giaGlitch.c \
+	src/aig/gia/giaHash.c \
+	src/aig/gia/giaIf.c \
+	src/aig/gia/giaIff.c \
+	src/aig/gia/giaIso.c \
+	src/aig/gia/giaIso2.c \
+	src/aig/gia/giaIso3.c \
+	src/aig/gia/giaJf.c \
+	src/aig/gia/giaKf.c \
+	src/aig/gia/giaLf.c \
+	src/aig/gia/giaMf.c \
+	src/aig/gia/giaMan.c \
+	src/aig/gia/giaMem.c \
+	src/aig/gia/giaMfs.c \
+	src/aig/gia/giaMini.c \
+	src/aig/gia/giaMuxes.c \
+	src/aig/gia/giaNf.c \
+	src/aig/gia/giaPat.c \
+	src/aig/gia/giaResub.c \
+	src/aig/gia/giaRetime.c \
+	src/aig/gia/giaScl.c \
+	src/aig/gia/giaShrink.c \
+	src/aig/gia/giaShrink6.c \
+	src/aig/gia/giaShrink7.c \
+	src/aig/gia/giaSim.c \
+	src/aig/gia/giaSim2.c \
+	src/aig/gia/giaSopb.c \
+	src/aig/gia/giaSort.c \
+	src/aig/gia/giaSpeedup.c \
+	src/aig/gia/giaStg.c \
+	src/aig/gia/giaStr.c \
+	src/aig/gia/giaSupMin.c \
+	src/aig/gia/giaSweep.c \
+	src/aig/gia/giaSweeper.c \
+	src/aig/gia/giaSwitch.c \
+	src/aig/gia/giaTim.c \
+	src/aig/gia/giaTis.c \
+	src/aig/gia/giaTruth.c \
+	src/aig/gia/giaTsim.c \
+	src/aig/gia/giaUtil.c
diff --git a/abc-build/src/aig/hop/cudd2.c b/abc-build/src/aig/hop/cudd2.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/hop/cudd2.c
@@ -0,0 +1,360 @@
+/**CFile****************************************************************
+
+  FileName    [cudd2.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Minimalistic And-Inverter Graph package.]
+
+  Synopsis    [Recording AIGs for the BDD operations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 3, 2006.]
+
+  Revision    [$Id: cudd2.c,v 1.00 2006/10/03 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "hop.h"
+#include "misc/st/st.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Aig_CuddMan_t_        Aig_CuddMan_t;
+struct Aig_CuddMan_t_
+{
+    Aig_Man_t *  pAig;   // internal AIG package
+    st__table *   pTable; // hash table mapping BDD nodes into AIG nodes
+};
+
+// static Cudd AIG manager used in this experiment
+static Aig_CuddMan_t * s_pCuddMan = NULL;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Start AIG recording.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cudd2_Init( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd )
+{
+    int v;
+    // start the BDD-to-AIG manager when the first BDD manager is allocated
+    if ( s_pCuddMan != NULL )
+        return;
+    s_pCuddMan = ALLOC( Aig_CuddMan_t, 1 );
+    s_pCuddMan->pAig = Aig_ManStart();
+    s_pCuddMan->pTable = st__init_table( st__ptrcmp, st__ptrhash );
+    for ( v = 0; v < (int)numVars; v++ )
+        Aig_ObjCreatePi( s_pCuddMan->pAig );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops AIG recording.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cudd2_Quit( void * pCudd )
+{
+    assert( s_pCuddMan != NULL );
+    Aig_ManDumpBlif( s_pCuddMan->pAig, "aig_temp.blif", NULL, NULL );
+    Aig_ManStop( s_pCuddMan->pAig );
+    st__free_table( s_pCuddMan->pTable );
+    free( s_pCuddMan );
+    s_pCuddMan = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fetches AIG node corresponding to the BDD node from the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Aig_Obj_t * Cudd2_GetArg( void * pArg )
+{
+    Aig_Obj_t * pNode;
+    assert( s_pCuddMan != NULL );
+    if ( ! st__lookup( s_pCuddMan->pTable, (char *)Aig_Regular(pArg), (char **)&pNode ) )
+    {
+        printf( "Cudd2_GetArg(): An argument BDD is not in the hash table.\n" );
+        return NULL;
+    }
+    return Aig_NotCond( pNode, Aig_IsComplement(pArg) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the AIG node corresponding to the BDD node into the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Cudd2_SetArg( Aig_Obj_t * pNode, void * pResult )
+{
+    assert( s_pCuddMan != NULL );
+    if ( st__is_member( s_pCuddMan->pTable, (char *)Aig_Regular(pResult) ) )
+        return;
+    pNode = Aig_NotCond( pNode,  Aig_IsComplement(pResult) );
+    st__insert( s_pCuddMan->pTable, (char *)Aig_Regular(pResult), (char *)pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Registers constant 1 node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cudd2_bddOne( void * pCudd, void * pResult )
+{
+    Cudd2_SetArg( Aig_ManConst1(s_pCuddMan->pAig), pResult );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds elementary variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cudd2_bddIthVar( void * pCudd, int iVar, void * pResult )
+{
+    int v;
+    assert( s_pCuddMan != NULL );
+    for ( v = Aig_ManPiNum(s_pCuddMan->pAig); v <= iVar; v++ )
+        Aig_ObjCreatePi( s_pCuddMan->pAig );
+    Cudd2_SetArg( Aig_ManPi(s_pCuddMan->pAig, iVar), pResult );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cudd2_bddAnd( void * pCudd, void * pArg0, void * pArg1, void * pResult )
+{
+    Aig_Obj_t * pNode0, * pNode1, * pNode;
+    pNode0 = Cudd2_GetArg( pArg0 );
+    pNode1 = Cudd2_GetArg( pArg1 );
+    pNode  = Aig_And( s_pCuddMan->pAig, pNode0, pNode1 );
+    Cudd2_SetArg( pNode, pResult );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cudd2_bddOr( void * pCudd, void * pArg0, void * pArg1, void * pResult )
+{
+    Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), Aig_Not(pResult) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cudd2_bddNand( void * pCudd, void * pArg0, void * pArg1, void * pResult )
+{
+    Cudd2_bddAnd( pCudd, pArg0, pArg1, Aig_Not(pResult) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cudd2_bddNor( void * pCudd, void * pArg0, void * pArg1, void * pResult )
+{
+    Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), pResult );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cudd2_bddXor( void * pCudd, void * pArg0, void * pArg1, void * pResult )
+{
+    Aig_Obj_t * pNode0, * pNode1, * pNode;
+    pNode0 = Cudd2_GetArg( pArg0 );
+    pNode1 = Cudd2_GetArg( pArg1 );
+    pNode  = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 );
+    Cudd2_SetArg( pNode, pResult );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cudd2_bddXnor( void * pCudd, void * pArg0, void * pArg1, void * pResult )
+{
+    Cudd2_bddXor( pCudd, pArg0, pArg1, Aig_Not(pResult) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cudd2_bddIte( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult )
+{
+    Aig_Obj_t * pNode0, * pNode1, * pNode2, * pNode;
+    pNode0 = Cudd2_GetArg( pArg0 );
+    pNode1 = Cudd2_GetArg( pArg1 );
+    pNode2 = Cudd2_GetArg( pArg2 );
+    pNode  = Aig_Mux( s_pCuddMan->pAig, pNode0, pNode1, pNode2 );
+    Cudd2_SetArg( pNode, pResult );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult )
+{
+    Aig_Obj_t * pNode0, * pNode1, * pNode;
+    pNode0 = Cudd2_GetArg( pArg0 );
+    pNode1 = Cudd2_GetArg( pArg1 );
+    pNode  = Aig_Compose( s_pCuddMan->pAig, pNode0, pNode1, v );
+    Cudd2_SetArg( pNode, pResult );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Should be called after each containment check.]
+
+  Description [Result should be 1 if Cudd2_bddLeq returned 1.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cudd2_bddLeq( void * pCudd, void * pArg0, void * pArg1, int Result )
+{
+    Aig_Obj_t * pNode0, * pNode1, * pNode;
+    pNode0 = Cudd2_GetArg( pArg0 );
+    pNode1 = Cudd2_GetArg( pArg1 );
+    pNode  = Aig_And( s_pCuddMan->pAig, pNode0, Aig_Not(pNode1) );
+    Aig_ObjCreatePo( s_pCuddMan->pAig, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Should be called after each equality check.]
+
+  Description [Result should be 1 if they are equal.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cudd2_bddEqual( void * pCudd, void * pArg0, void * pArg1, int Result )
+{
+    Aig_Obj_t * pNode0, * pNode1, * pNode;
+    pNode0 = Cudd2_GetArg( pArg0 );
+    pNode1 = Cudd2_GetArg( pArg1 );
+    pNode  = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 );
+    Aig_ObjCreatePo( s_pCuddMan->pAig, pNode );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/hop/cudd2.h b/abc-build/src/aig/hop/cudd2.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/hop/cudd2.h
@@ -0,0 +1,86 @@
+/**CFile****************************************************************
+
+  FileName    [cudd2.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Minimalistic And-Inverter Graph package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 3, 2006.]
+
+  Revision    [$Id: cudd2.h,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__hop__cudd2_h
+#define ABC__aig__hop__cudd2_h
+
+
+// HA: Added for printing messages
+#ifndef MSG 
+#define MSG(msg) (printf("%s = \n",(msg)));
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                             ITERATORS                            ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+extern void Cudd2_Init      ( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd );
+extern void Cudd2_Quit      ( void * pCudd );
+extern void Cudd2_bddOne    ( void * pCudd, void * pResult );
+extern void Cudd2_bddIthVar ( void * pCudd, int iVar, void * pResult );
+extern void Cudd2_bddAnd    ( void * pCudd, void * pArg0, void * pArg1, void * pResult );
+extern void Cudd2_bddOr     ( void * pCudd, void * pArg0, void * pArg1, void * pResult );
+extern void Cudd2_bddNand   ( void * pCudd, void * pArg0, void * pArg1, void * pResult );
+extern void Cudd2_bddNor    ( void * pCudd, void * pArg0, void * pArg1, void * pResult );
+extern void Cudd2_bddXor    ( void * pCudd, void * pArg0, void * pArg1, void * pResult );
+extern void Cudd2_bddXnor   ( void * pCudd, void * pArg0, void * pArg1, void * pResult );
+extern void Cudd2_bddIte    ( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult );
+extern void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult );
+extern void Cudd2_bddLeq    ( void * pCudd, void * pArg0, void * pArg1, int Result );
+extern void Cudd2_bddEqual  ( void * pCudd, void * pArg0, void * pArg1, int Result );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/aig/hop/hop.h b/abc-build/src/aig/hop/hop.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/hop/hop.h
@@ -0,0 +1,356 @@
+/**CFile****************************************************************
+
+  FileName    [hop.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Minimalistic And-Inverter Graph package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: hop.h,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__hop__hop_h
+#define ABC__aig__hop__hop_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Hop_Man_t_            Hop_Man_t;
+typedef struct Hop_Obj_t_            Hop_Obj_t;
+typedef int                          Hop_Edge_t;
+
+// object types
+typedef enum { 
+    AIG_NONE,                        // 0: non-existent object
+    AIG_CONST1,                      // 1: constant 1 
+    AIG_PI,                          // 2: primary input
+    AIG_PO,                          // 3: primary output
+    AIG_AND,                         // 4: AND node
+    AIG_EXOR,                        // 5: EXOR node
+    AIG_VOID                         // 6: unused object
+} Hop_Type_t;
+
+// the AIG node
+struct Hop_Obj_t_  // 6 words
+{
+    union { 
+        void *       pData;          // misc
+        int          iData; };       // misc
+    union { 
+        Hop_Obj_t *  pNext;          // strashing table
+        int          PioNum; };      // the number of PI/PO
+    Hop_Obj_t *      pFanin0;        // fanin
+    Hop_Obj_t *      pFanin1;        // fanin
+    unsigned int     Type    :  3;   // object type
+    unsigned int     fPhase  :  1;   // value under 000...0 pattern
+    unsigned int     fMarkA  :  1;   // multipurpose mask
+    unsigned int     fMarkB  :  1;   // multipurpose mask
+    unsigned int     nRefs   : 26;   // reference count (level)
+    int              Id;             // unique ID of the node
+};
+
+// the AIG manager
+struct Hop_Man_t_
+{
+    // AIG nodes
+    Vec_Ptr_t *      vPis;           // the array of PIs
+    Vec_Ptr_t *      vPos;           // the array of POs
+    Vec_Ptr_t *      vObjs;          // the array of all nodes (optional)
+    Hop_Obj_t *      pConst1;        // the constant 1 node
+    Hop_Obj_t        Ghost;          // the ghost node
+    // AIG node counters
+    int              nObjs[AIG_VOID];// the number of objects by type
+    int              nCreated;       // the number of created objects
+    int              nDeleted;       // the number of deleted objects
+    // stuctural hash table
+    Hop_Obj_t **     pTable;         // structural hash table
+    int              nTableSize;     // structural hash table size
+    // various data members
+    void *           pData;          // the temporary data
+    int              nTravIds;       // the current traversal ID
+    int              fRefCount;      // enables reference counting
+    int              fCatchExor;     // enables EXOR nodes
+    // memory management
+    Vec_Ptr_t *      vChunks;        // allocated memory pieces
+    Vec_Ptr_t *      vPages;         // memory pages used by nodes
+    Hop_Obj_t *      pListFree;      // the list of free nodes 
+    // timing statistics
+    abctime          time1;
+    abctime          time2;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+extern void Hop_ManAddMemory( Hop_Man_t * p );
+
+static inline int          Hop_BitWordNum( int nBits )            { return (nBits>>5) + ((nBits&31) > 0);           }
+static inline int          Hop_TruthWordNum( int nVars )          { return nVars <= 5 ? 1 : (1 << (nVars - 5));     }
+static inline int          Hop_InfoHasBit( unsigned * p, int i )  { return (p[(i)>>5] & (1<<((i) & 31))) > 0;       }
+static inline void         Hop_InfoSetBit( unsigned * p, int i )  { p[(i)>>5] |= (1<<((i) & 31));                   }
+static inline void         Hop_InfoXorBit( unsigned * p, int i )  { p[(i)>>5] ^= (1<<((i) & 31));                   }
+static inline int          Hop_Base2Log( unsigned n )             { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n >>= 1, r++ ) {}; return r; }
+static inline int          Hop_Base10Log( unsigned n )            { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n /= 10, r++ ) {}; return r; }
+
+static inline Hop_Obj_t *  Hop_Regular( Hop_Obj_t * p )           { return (Hop_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); }
+static inline Hop_Obj_t *  Hop_Not( Hop_Obj_t * p )               { return (Hop_Obj_t *)((ABC_PTRUINT_T)(p) ^  01); }
+static inline Hop_Obj_t *  Hop_NotCond( Hop_Obj_t * p, int c )    { return (Hop_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); }
+static inline int          Hop_IsComplement( Hop_Obj_t * p )      { return (int)((ABC_PTRUINT_T)(p) & 01);          }
+
+static inline Hop_Obj_t *  Hop_ManConst0( Hop_Man_t * p )         { return Hop_Not(p->pConst1);                     }
+static inline Hop_Obj_t *  Hop_ManConst1( Hop_Man_t * p )         { return p->pConst1;                              }
+static inline Hop_Obj_t *  Hop_ManGhost( Hop_Man_t * p )          { return &p->Ghost;                               }
+static inline Hop_Obj_t *  Hop_ManPi( Hop_Man_t * p, int i )      { return (Hop_Obj_t *)Vec_PtrEntry(p->vPis, i);   }
+static inline Hop_Obj_t *  Hop_ManPo( Hop_Man_t * p, int i )      { return (Hop_Obj_t *)Vec_PtrEntry(p->vPos, i);   }
+static inline Hop_Obj_t *  Hop_ManObj( Hop_Man_t * p, int i )     { return p->vObjs ? (Hop_Obj_t *)Vec_PtrEntry(p->vObjs, i) : NULL;  }
+
+static inline Hop_Edge_t   Hop_EdgeCreate( int Id, int fCompl )            { return (Id << 1) | fCompl;             }
+static inline int          Hop_EdgeId( Hop_Edge_t Edge )                   { return Edge >> 1;                      }
+static inline int          Hop_EdgeIsComplement( Hop_Edge_t Edge )         { return Edge & 1;                       }
+static inline Hop_Edge_t   Hop_EdgeRegular( Hop_Edge_t Edge )              { return (Edge >> 1) << 1;               }
+static inline Hop_Edge_t   Hop_EdgeNot( Hop_Edge_t Edge )                  { return Edge ^ 1;                       }
+static inline Hop_Edge_t   Hop_EdgeNotCond( Hop_Edge_t Edge, int fCond )   { return Edge ^ fCond;                   }
+
+static inline int          Hop_ManPiNum( Hop_Man_t * p )          { return p->nObjs[AIG_PI];                    }
+static inline int          Hop_ManPoNum( Hop_Man_t * p )          { return p->nObjs[AIG_PO];                    }
+static inline int          Hop_ManAndNum( Hop_Man_t * p )         { return p->nObjs[AIG_AND];                   }
+static inline int          Hop_ManExorNum( Hop_Man_t * p )        { return p->nObjs[AIG_EXOR];                  }
+static inline int          Hop_ManNodeNum( Hop_Man_t * p )        { return p->nObjs[AIG_AND]+p->nObjs[AIG_EXOR];}
+static inline int          Hop_ManGetCost( Hop_Man_t * p )        { return p->nObjs[AIG_AND]+3*p->nObjs[AIG_EXOR]; }
+static inline int          Hop_ManObjNum( Hop_Man_t * p )         { return p->nCreated - p->nDeleted;           }
+
+static inline Hop_Type_t   Hop_ObjType( Hop_Obj_t * pObj )        { return (Hop_Type_t)pObj->Type;               }
+static inline int          Hop_ObjIsNone( Hop_Obj_t * pObj )      { return pObj->Type == AIG_NONE;   }
+static inline int          Hop_ObjIsConst1( Hop_Obj_t * pObj )    { assert(!Hop_IsComplement(pObj)); return pObj->Type == AIG_CONST1; }
+static inline int          Hop_ObjIsPi( Hop_Obj_t * pObj )        { return pObj->Type == AIG_PI;     }
+static inline int          Hop_ObjIsPo( Hop_Obj_t * pObj )        { return pObj->Type == AIG_PO;     }
+static inline int          Hop_ObjIsAnd( Hop_Obj_t * pObj )       { return pObj->Type == AIG_AND;    }
+static inline int          Hop_ObjIsExor( Hop_Obj_t * pObj )      { return pObj->Type == AIG_EXOR;   }
+static inline int          Hop_ObjIsNode( Hop_Obj_t * pObj )      { return pObj->Type == AIG_AND || pObj->Type == AIG_EXOR;   }
+static inline int          Hop_ObjIsTerm( Hop_Obj_t * pObj )      { return pObj->Type == AIG_PI  || pObj->Type == AIG_PO || pObj->Type == AIG_CONST1; }
+static inline int          Hop_ObjIsHash( Hop_Obj_t * pObj )      { return pObj->Type == AIG_AND || pObj->Type == AIG_EXOR;   }
+
+static inline int          Hop_ObjIsMarkA( Hop_Obj_t * pObj )     { return pObj->fMarkA;  }
+static inline void         Hop_ObjSetMarkA( Hop_Obj_t * pObj )    { pObj->fMarkA = 1;     }
+static inline void         Hop_ObjClearMarkA( Hop_Obj_t * pObj )  { pObj->fMarkA = 0;     }
+ 
+static inline void         Hop_ObjSetTravId( Hop_Obj_t * pObj, int TravId )                { pObj->pData = (void *)(ABC_PTRINT_T)TravId;                      }
+static inline void         Hop_ObjSetTravIdCurrent( Hop_Man_t * p, Hop_Obj_t * pObj )      { pObj->pData = (void *)(ABC_PTRINT_T)p->nTravIds;                 }
+static inline void         Hop_ObjSetTravIdPrevious( Hop_Man_t * p, Hop_Obj_t * pObj )     { pObj->pData = (void *)(ABC_PTRINT_T)(p->nTravIds - 1);           }
+static inline int          Hop_ObjIsTravIdCurrent( Hop_Man_t * p, Hop_Obj_t * pObj )       { return (int)((int)(ABC_PTRINT_T)pObj->pData == p->nTravIds);     }
+static inline int          Hop_ObjIsTravIdPrevious( Hop_Man_t * p, Hop_Obj_t * pObj )      { return (int)((int)(ABC_PTRINT_T)pObj->pData == p->nTravIds - 1); }
+
+static inline int          Hop_ObjTravId( Hop_Obj_t * pObj )      { return (int)(ABC_PTRINT_T)pObj->pData;        }
+static inline int          Hop_ObjPhase( Hop_Obj_t * pObj )       { return pObj->fPhase;                           }
+static inline int          Hop_ObjRefs( Hop_Obj_t * pObj )        { return pObj->nRefs;                            }
+static inline void         Hop_ObjRef( Hop_Obj_t * pObj )         { pObj->nRefs++;                                 }
+static inline void         Hop_ObjDeref( Hop_Obj_t * pObj )       { assert( pObj->nRefs > 0 ); pObj->nRefs--;      }
+static inline void         Hop_ObjClearRef( Hop_Obj_t * pObj )    { pObj->nRefs = 0;                               }
+static inline int          Hop_ObjFaninC0( Hop_Obj_t * pObj )     { return Hop_IsComplement(pObj->pFanin0);        }
+static inline int          Hop_ObjFaninC1( Hop_Obj_t * pObj )     { return Hop_IsComplement(pObj->pFanin1);        }
+static inline Hop_Obj_t *  Hop_ObjFanin0( Hop_Obj_t * pObj )      { return Hop_Regular(pObj->pFanin0);             }
+static inline Hop_Obj_t *  Hop_ObjFanin1( Hop_Obj_t * pObj )      { return Hop_Regular(pObj->pFanin1);             }
+static inline Hop_Obj_t *  Hop_ObjChild0( Hop_Obj_t * pObj )      { return pObj->pFanin0;                          }
+static inline Hop_Obj_t *  Hop_ObjChild1( Hop_Obj_t * pObj )      { return pObj->pFanin1;                          }
+static inline Hop_Obj_t *  Hop_ObjChild0Copy( Hop_Obj_t * pObj )  { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin0(pObj)? Hop_NotCond((Hop_Obj_t *)Hop_ObjFanin0(pObj)->pData, Hop_ObjFaninC0(pObj)) : NULL;  }
+static inline Hop_Obj_t *  Hop_ObjChild1Copy( Hop_Obj_t * pObj )  { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin1(pObj)? Hop_NotCond((Hop_Obj_t *)Hop_ObjFanin1(pObj)->pData, Hop_ObjFaninC1(pObj)) : NULL;  }
+static inline int          Hop_ObjChild0CopyI( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin0(pObj)? Abc_LitNotCond(Hop_ObjFanin0(pObj)->iData, Hop_ObjFaninC0(pObj)) : -1;              }
+static inline int          Hop_ObjChild1CopyI( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin1(pObj)? Abc_LitNotCond(Hop_ObjFanin1(pObj)->iData, Hop_ObjFaninC1(pObj)) : -1;              }
+static inline int          Hop_ObjLevel( Hop_Obj_t * pObj )       { return pObj->nRefs;                            }
+static inline int          Hop_ObjLevelNew( Hop_Obj_t * pObj )    { return 1 + Hop_ObjIsExor(pObj) + Abc_MaxInt(Hop_ObjFanin0(pObj)->nRefs, Hop_ObjFanin1(pObj)->nRefs);       }
+static inline int          Hop_ObjPhaseCompl( Hop_Obj_t * pObj )  { return Hop_IsComplement(pObj)? !Hop_Regular(pObj)->fPhase : pObj->fPhase; }
+static inline void         Hop_ObjClean( Hop_Obj_t * pObj )       { memset( pObj, 0, sizeof(Hop_Obj_t) ); }
+static inline int          Hop_ObjWhatFanin( Hop_Obj_t * pObj, Hop_Obj_t * pFanin )    
+{ 
+    if ( Hop_ObjFanin0(pObj) == pFanin ) return 0; 
+    if ( Hop_ObjFanin1(pObj) == pFanin ) return 1; 
+    assert(0); return -1; 
+}
+static inline int          Hop_ObjFanoutC( Hop_Obj_t * pObj, Hop_Obj_t * pFanout )    
+{ 
+    if ( Hop_ObjFanin0(pFanout) == pObj ) return Hop_ObjFaninC0(pObj); 
+    if ( Hop_ObjFanin1(pFanout) == pObj ) return Hop_ObjFaninC1(pObj); 
+    assert(0); return -1; 
+}
+
+// create the ghost of the new node
+static inline Hop_Obj_t *  Hop_ObjCreateGhost( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type )    
+{
+    Hop_Obj_t * pGhost;
+    assert( Type != AIG_AND || !Hop_ObjIsConst1(Hop_Regular(p0)) );
+    assert( p1 == NULL || !Hop_ObjIsConst1(Hop_Regular(p1)) );
+    assert( Type == AIG_PI || Hop_Regular(p0) != Hop_Regular(p1) );
+    pGhost = Hop_ManGhost(p);
+    pGhost->Type = Type;
+    if ( Hop_Regular(p0)->Id < Hop_Regular(p1)->Id )
+    {
+        pGhost->pFanin0 = p0;
+        pGhost->pFanin1 = p1;
+    }
+    else
+    {
+        pGhost->pFanin0 = p1;
+        pGhost->pFanin1 = p0;
+    }
+    return pGhost;
+}
+
+// internal memory manager
+static inline Hop_Obj_t * Hop_ManFetchMemory( Hop_Man_t * p )  
+{ 
+    Hop_Obj_t * pTemp;
+    if ( p->pListFree == NULL )
+        Hop_ManAddMemory( p );
+    pTemp = p->pListFree;
+    p->pListFree = *((Hop_Obj_t **)pTemp);
+    memset( pTemp, 0, sizeof(Hop_Obj_t) ); 
+    if ( p->vObjs )
+    {
+        assert( p->nCreated == Vec_PtrSize(p->vObjs) );
+        Vec_PtrPush( p->vObjs, pTemp );
+    }
+    pTemp->Id = p->nCreated++;
+    return pTemp;
+}
+static inline void Hop_ManRecycleMemory( Hop_Man_t * p, Hop_Obj_t * pEntry )
+{
+    pEntry->Type = AIG_NONE; // distinquishes dead node from live node
+    *((Hop_Obj_t **)pEntry) = p->pListFree;
+    p->pListFree = pEntry;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                             ITERATORS                            ///
+////////////////////////////////////////////////////////////////////////
+
+// iterator over the primary inputs
+#define Hop_ManForEachPi( p, pObj, i )                                          \
+    Vec_PtrForEachEntry( Hop_Obj_t *, p->vPis, pObj, i )
+// iterator over the primary outputs
+#define Hop_ManForEachPo( p, pObj, i )                                          \
+    Vec_PtrForEachEntry( Hop_Obj_t *, p->vPos, pObj, i )
+// iterator over all objects, including those currently not used
+#define Hop_ManForEachNode( p, pObj, i )                                        \
+    for ( i = 0; i < p->nTableSize; i++ )                                       \
+        if ( ((pObj) = p->pTable[i]) == NULL ) {} else
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== hopBalance.c ========================================================*/
+extern Hop_Man_t *     Hop_ManBalance( Hop_Man_t * p, int fUpdateLevel );
+extern Hop_Obj_t *     Hop_NodeBalanceBuildSuper( Hop_Man_t * p, Vec_Ptr_t * vSuper, Hop_Type_t Type, int fUpdateLevel );
+/*=== hopCheck.c ========================================================*/
+extern int             Hop_ManCheck( Hop_Man_t * p );
+/*=== hopDfs.c ==========================================================*/
+extern Vec_Ptr_t *     Hop_ManDfs( Hop_Man_t * p );
+extern Vec_Ptr_t *     Hop_ManDfsNode( Hop_Man_t * p, Hop_Obj_t * pNode );
+extern int             Hop_ManCountLevels( Hop_Man_t * p );
+extern void            Hop_ManCreateRefs( Hop_Man_t * p );
+extern int             Hop_DagSize( Hop_Obj_t * pObj );
+extern int             Hop_ObjFanoutCount( Hop_Obj_t * pObj, Hop_Obj_t * pPivot );
+extern void            Hop_ConeUnmark_rec( Hop_Obj_t * pObj );
+extern Hop_Obj_t *     Hop_Transfer( Hop_Man_t * pSour, Hop_Man_t * pDest, Hop_Obj_t * pObj, int nVars );
+extern Hop_Obj_t *     Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, int iVar );
+extern Hop_Obj_t *     Hop_Complement( Hop_Man_t * p, Hop_Obj_t * pRoot, int iVar );
+extern Hop_Obj_t *     Hop_Remap( Hop_Man_t * p, Hop_Obj_t * pRoot, unsigned uSupp, int nVars );
+extern Hop_Obj_t *     Hop_Permute( Hop_Man_t * p, Hop_Obj_t * pRoot, int nRootVars, int * pPermute );
+/*=== hopMan.c ==========================================================*/
+extern Hop_Man_t *     Hop_ManStart();
+extern Hop_Man_t *     Hop_ManDup( Hop_Man_t * p );
+extern void            Hop_ManStop( Hop_Man_t * p );
+extern int             Hop_ManCleanup( Hop_Man_t * p );
+extern void            Hop_ManPrintStats( Hop_Man_t * p );
+/*=== hopMem.c ==========================================================*/
+extern void            Hop_ManStartMemory( Hop_Man_t * p );
+extern void            Hop_ManStopMemory( Hop_Man_t * p );
+/*=== hopObj.c ==========================================================*/
+extern Hop_Obj_t *     Hop_ObjCreatePi( Hop_Man_t * p );
+extern Hop_Obj_t *     Hop_ObjCreatePo( Hop_Man_t * p, Hop_Obj_t * pDriver );
+extern Hop_Obj_t *     Hop_ObjCreate( Hop_Man_t * p, Hop_Obj_t * pGhost );
+extern void            Hop_ObjConnect( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFan0, Hop_Obj_t * pFan1 );
+extern void            Hop_ObjDisconnect( Hop_Man_t * p, Hop_Obj_t * pObj );
+extern void            Hop_ObjDelete( Hop_Man_t * p, Hop_Obj_t * pObj );
+extern void            Hop_ObjDelete_rec( Hop_Man_t * p, Hop_Obj_t * pObj );
+extern Hop_Obj_t *     Hop_ObjRepr( Hop_Obj_t * pObj );
+extern void            Hop_ObjCreateChoice( Hop_Obj_t * pOld, Hop_Obj_t * pNew );
+/*=== hopOper.c =========================================================*/
+extern Hop_Obj_t *     Hop_IthVar( Hop_Man_t * p, int i );
+extern Hop_Obj_t *     Hop_Oper( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type );
+extern Hop_Obj_t *     Hop_And( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 );
+extern Hop_Obj_t *     Hop_Or( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 );
+extern Hop_Obj_t *     Hop_Exor( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 );
+extern Hop_Obj_t *     Hop_Mux( Hop_Man_t * p, Hop_Obj_t * pC, Hop_Obj_t * p1, Hop_Obj_t * p0 );
+extern Hop_Obj_t *     Hop_Maj( Hop_Man_t * p, Hop_Obj_t * pA, Hop_Obj_t * pB, Hop_Obj_t * pC );
+extern Hop_Obj_t *     Hop_Miter( Hop_Man_t * p, Vec_Ptr_t * vPairs );
+extern Hop_Obj_t *     Hop_CreateAnd( Hop_Man_t * p, int nVars );
+extern Hop_Obj_t *     Hop_CreateOr( Hop_Man_t * p, int nVars );
+extern Hop_Obj_t *     Hop_CreateExor( Hop_Man_t * p, int nVars );
+/*=== hopTable.c ========================================================*/
+extern Hop_Obj_t *     Hop_TableLookup( Hop_Man_t * p, Hop_Obj_t * pGhost );
+extern void            Hop_TableInsert( Hop_Man_t * p, Hop_Obj_t * pObj );
+extern void            Hop_TableDelete( Hop_Man_t * p, Hop_Obj_t * pObj );
+extern int             Hop_TableCountEntries( Hop_Man_t * p );
+extern void            Hop_TableProfile( Hop_Man_t * p );
+/*=== hopTruth.c ========================================================*/
+extern unsigned *      Hop_ManConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, int fMsbFirst );
+extern word            Hop_ManComputeTruth6( Hop_Man_t * p, Hop_Obj_t * pObj, int nVars );
+/*=== hopUtil.c =========================================================*/
+extern void            Hop_ManIncrementTravId( Hop_Man_t * p );
+extern void            Hop_ManCleanData( Hop_Man_t * p );
+extern void            Hop_ObjCleanData_rec( Hop_Obj_t * pObj );
+extern void            Hop_ObjCollectMulti( Hop_Obj_t * pFunc, Vec_Ptr_t * vSuper );
+extern int             Hop_ObjIsMuxType( Hop_Obj_t * pObj );
+extern int             Hop_ObjRecognizeExor( Hop_Obj_t * pObj, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 );
+extern Hop_Obj_t *     Hop_ObjRecognizeMux( Hop_Obj_t * pObj, Hop_Obj_t ** ppObjT, Hop_Obj_t ** ppObjE );
+extern void            Hop_ObjPrintEqn( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level );
+extern void            Hop_ObjPrintVerilog( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level );
+extern void            Hop_ObjPrintVerbose( Hop_Obj_t * pObj, int fHaig );
+extern void            Hop_ManPrintVerbose( Hop_Man_t * p, int fHaig );
+extern void            Hop_ManDumpBlif( Hop_Man_t * p, char * pFileName );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/aig/hop/hopBalance.c b/abc-build/src/aig/hop/hopBalance.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/hop/hopBalance.c
@@ -0,0 +1,401 @@
+/**CFile****************************************************************
+
+  FileName    [hopBalance.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Minimalistic And-Inverter Graph package.]
+
+  Synopsis    [Algebraic AIG balancing.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: hopBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "hop.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Hop_Obj_t * Hop_NodeBalance_rec( Hop_Man_t * pNew, Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel );
+static Vec_Ptr_t * Hop_NodeBalanceCone( Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level );
+static int         Hop_NodeBalanceFindLeft( Vec_Ptr_t * vSuper );
+static void        Hop_NodeBalancePermute( Hop_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor );
+static void        Hop_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Hop_Obj_t * pObj );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs algebraic balancing of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Man_t * Hop_ManBalance( Hop_Man_t * p, int fUpdateLevel )
+{
+    Hop_Man_t * pNew;
+    Hop_Obj_t * pObj, * pObjNew;
+    Vec_Vec_t * vStore;
+    int i;
+    // create the new manager 
+    pNew = Hop_ManStart();
+    pNew->fRefCount = 0;
+    // map the PI nodes
+    Hop_ManCleanData( p );
+    Hop_ManConst1(p)->pData = Hop_ManConst1(pNew);
+    Hop_ManForEachPi( p, pObj, i )
+        pObj->pData = Hop_ObjCreatePi(pNew);
+    // balance the AIG
+    vStore = Vec_VecAlloc( 50 );
+    Hop_ManForEachPo( p, pObj, i )
+    {
+        pObjNew = Hop_NodeBalance_rec( pNew, Hop_ObjFanin0(pObj), vStore, 0, fUpdateLevel );
+        Hop_ObjCreatePo( pNew, Hop_NotCond( pObjNew, Hop_ObjFaninC0(pObj) ) );
+    }
+    Vec_VecFree( vStore );
+    // remove dangling nodes
+//    Hop_ManCreateRefs( pNew );
+//    if ( i = Hop_ManCleanup( pNew ) )
+//        printf( "Cleanup after balancing removed %d dangling nodes.\n", i );
+    // check the resulting AIG
+    if ( !Hop_ManCheck(pNew) )
+        printf( "Hop_ManBalance(): The check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the new node constructed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_NodeBalance_rec( Hop_Man_t * pNew, Hop_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel )
+{
+    Hop_Obj_t * pObjNew;
+    Vec_Ptr_t * vSuper;
+    int i;
+    assert( !Hop_IsComplement(pObjOld) );
+    // return if the result is known
+    if ( pObjOld->pData )
+        return (Hop_Obj_t *)pObjOld->pData;
+    assert( Hop_ObjIsNode(pObjOld) );
+    // get the implication supergate
+    vSuper = Hop_NodeBalanceCone( pObjOld, vStore, Level );
+    // check if supergate contains two nodes in the opposite polarity
+    if ( vSuper->nSize == 0 )
+        return (Hop_Obj_t *)(pObjOld->pData = Hop_ManConst0(pNew));
+    if ( Vec_PtrSize(vSuper) < 2 )
+        printf( "BUG!\n" );
+    // for each old node, derive the new well-balanced node
+    for ( i = 0; i < Vec_PtrSize(vSuper); i++ )
+    {
+        pObjNew = Hop_NodeBalance_rec( pNew, Hop_Regular((Hop_Obj_t *)vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel );
+        vSuper->pArray[i] = Hop_NotCond( pObjNew, Hop_IsComplement((Hop_Obj_t *)vSuper->pArray[i]) );
+    }
+    // build the supergate
+    pObjNew = Hop_NodeBalanceBuildSuper( pNew, vSuper, Hop_ObjType(pObjOld), fUpdateLevel );
+    // make sure the balanced node is not assigned
+//    assert( pObjOld->Level >= Hop_Regular(pObjNew)->Level );
+    assert( pObjOld->pData == NULL );
+    return (Hop_Obj_t *)(pObjOld->pData = pObjNew);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the nodes of the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hop_NodeBalanceCone_rec( Hop_Obj_t * pRoot, Hop_Obj_t * pObj, Vec_Ptr_t * vSuper )
+{
+    int RetValue1, RetValue2, i;
+    // check if the node is visited
+    if ( Hop_Regular(pObj)->fMarkB )
+    {
+        // check if the node occurs in the same polarity
+        for ( i = 0; i < vSuper->nSize; i++ )
+            if ( vSuper->pArray[i] == pObj )
+                return 1;
+        // check if the node is present in the opposite polarity
+        for ( i = 0; i < vSuper->nSize; i++ )
+            if ( vSuper->pArray[i] == Hop_Not(pObj) )
+                return -1;
+        assert( 0 );
+        return 0;
+    }
+    // if the new node is complemented or a PI, another gate begins
+    if ( pObj != pRoot && (Hop_IsComplement(pObj) || Hop_ObjType(pObj) != Hop_ObjType(pRoot) || Hop_ObjRefs(pObj) > 1 || Vec_PtrSize(vSuper) > 10000) )
+    {
+        Vec_PtrPush( vSuper, pObj );
+        Hop_Regular(pObj)->fMarkB = 1;
+        return 0;
+    }
+    assert( !Hop_IsComplement(pObj) );
+    assert( Hop_ObjIsNode(pObj) );
+    // go through the branches
+    RetValue1 = Hop_NodeBalanceCone_rec( pRoot, Hop_ObjChild0(pObj), vSuper );
+    RetValue2 = Hop_NodeBalanceCone_rec( pRoot, Hop_ObjChild1(pObj), vSuper );
+    if ( RetValue1 == -1 || RetValue2 == -1 )
+        return -1;
+    // return 1 if at least one branch has a duplicate
+    return RetValue1 || RetValue2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the nodes of the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Hop_NodeBalanceCone( Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level )
+{
+    Vec_Ptr_t * vNodes;
+    int RetValue, i;
+    assert( !Hop_IsComplement(pObj) );
+    // extend the storage
+    if ( Vec_VecSize( vStore ) <= Level )
+        Vec_VecPush( vStore, Level, 0 );
+    // get the temporary array of nodes
+    vNodes = Vec_VecEntry( vStore, Level );
+    Vec_PtrClear( vNodes );
+    // collect the nodes in the implication supergate
+    RetValue = Hop_NodeBalanceCone_rec( pObj, pObj, vNodes );
+    assert( vNodes->nSize > 1 );
+    // unmark the visited nodes
+    Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i )
+        Hop_Regular(pObj)->fMarkB = 0;
+    // if we found the node and its complement in the same implication supergate, 
+    // return empty set of nodes (meaning that we should use constant-0 node)
+    if ( RetValue == -1 )
+        vNodes->nSize = 0;
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure used for sorting the nodes in decreasing order of levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hop_NodeCompareLevelsDecrease( Hop_Obj_t ** pp1, Hop_Obj_t ** pp2 )
+{
+    int Diff = Hop_ObjLevel(Hop_Regular(*pp1)) - Hop_ObjLevel(Hop_Regular(*pp2));
+    if ( Diff > 0 )
+        return -1;
+    if ( Diff < 0 ) 
+        return 1;
+    Diff = Hop_Regular(*pp1)->Id - Hop_Regular(*pp2)->Id;
+    if ( Diff > 0 )
+        return -1;
+    if ( Diff < 0 ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Builds implication supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_NodeBalanceBuildSuper( Hop_Man_t * p, Vec_Ptr_t * vSuper, Hop_Type_t Type, int fUpdateLevel )
+{
+    Hop_Obj_t * pObj1, * pObj2;
+    int LeftBound;
+    assert( vSuper->nSize > 1 );
+    // sort the new nodes by level in the decreasing order
+    Vec_PtrSort( vSuper, (int (*)(void))Hop_NodeCompareLevelsDecrease );
+    // balance the nodes
+    while ( vSuper->nSize > 1 )
+    {
+        // find the left bound on the node to be paired
+        LeftBound = (!fUpdateLevel)? 0 : Hop_NodeBalanceFindLeft( vSuper );
+        // find the node that can be shared (if no such node, randomize choice)
+        Hop_NodeBalancePermute( p, vSuper, LeftBound, Type == AIG_EXOR );
+        // pull out the last two nodes
+        pObj1 = (Hop_Obj_t *)Vec_PtrPop(vSuper);
+        pObj2 = (Hop_Obj_t *)Vec_PtrPop(vSuper);
+        Hop_NodeBalancePushUniqueOrderByLevel( vSuper, Hop_Oper(p, pObj1, pObj2, Type) );
+    }
+    return (Hop_Obj_t *)Vec_PtrEntry(vSuper, 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the left bound on the next candidate to be paired.]
+
+  Description [The nodes in the array are in the decreasing order of levels. 
+  The last node in the array has the smallest level. By default it would be paired 
+  with the next node on the left. However, it may be possible to pair it with some
+  other node on the left, in such a way that the new node is shared. This procedure
+  finds the index of the left-most node, which can be paired with the last node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hop_NodeBalanceFindLeft( Vec_Ptr_t * vSuper )
+{
+    Hop_Obj_t * pObjRight, * pObjLeft;
+    int Current;
+    // if two or less nodes, pair with the first
+    if ( Vec_PtrSize(vSuper) < 3 )
+        return 0;
+    // set the pointer to the one before the last
+    Current = Vec_PtrSize(vSuper) - 2;
+    pObjRight = (Hop_Obj_t *)Vec_PtrEntry( vSuper, Current );
+    // go through the nodes to the left of this one
+    for ( Current--; Current >= 0; Current-- )
+    {
+        // get the next node on the left
+        pObjLeft = (Hop_Obj_t *)Vec_PtrEntry( vSuper, Current );
+        // if the level of this node is different, quit the loop
+        if ( Hop_ObjLevel(Hop_Regular(pObjLeft)) != Hop_ObjLevel(Hop_Regular(pObjRight)) )
+            break;
+    }
+    Current++;    
+    // get the node, for which the equality holds
+    pObjLeft = (Hop_Obj_t *)Vec_PtrEntry( vSuper, Current );
+    assert( Hop_ObjLevel(Hop_Regular(pObjLeft)) == Hop_ObjLevel(Hop_Regular(pObjRight)) );
+    return Current;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Moves closer to the end the node that is best for sharing.]
+
+  Description [If there is no node with sharing, randomly chooses one of 
+  the legal nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_NodeBalancePermute( Hop_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor )
+{
+    Hop_Obj_t * pObj1, * pObj2, * pObj3, * pGhost;
+    int RightBound, i;
+    // get the right bound
+    RightBound = Vec_PtrSize(vSuper) - 2;
+    assert( LeftBound <= RightBound );
+    if ( LeftBound == RightBound )
+        return;
+    // get the two last nodes
+    pObj1 = (Hop_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 );
+    pObj2 = (Hop_Obj_t *)Vec_PtrEntry( vSuper, RightBound     );
+    if ( Hop_Regular(pObj1) == p->pConst1 || Hop_Regular(pObj2) == p->pConst1 )
+        return;
+    // find the first node that can be shared
+    for ( i = RightBound; i >= LeftBound; i-- )
+    {
+        pObj3 = (Hop_Obj_t *)Vec_PtrEntry( vSuper, i );
+        if ( Hop_Regular(pObj3) == p->pConst1 )
+        {
+            Vec_PtrWriteEntry( vSuper, i,          pObj2 );
+            Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
+            return;
+        }
+        pGhost = Hop_ObjCreateGhost( p, pObj1, pObj3, fExor? AIG_EXOR : AIG_AND );
+        if ( Hop_TableLookup( p, pGhost ) )
+        {
+            if ( pObj3 == pObj2 )
+                return;
+            Vec_PtrWriteEntry( vSuper, i,          pObj2 );
+            Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
+            return;
+        }
+    }
+/*
+    // we did not find the node to share, randomize choice
+    {
+        int Choice = rand() % (RightBound - LeftBound + 1);
+        pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice );
+        if ( pObj3 == pObj2 )
+            return;
+        Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 );
+        Vec_PtrWriteEntry( vSuper, RightBound,         pObj3 );
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts a new node in the order by levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Hop_Obj_t * pObj )
+{
+    Hop_Obj_t * pObj1, * pObj2;
+    int i;
+    if ( Vec_PtrPushUnique(vStore, pObj) )
+        return;
+    // find the p of the node
+    for ( i = vStore->nSize-1; i > 0; i-- )
+    {
+        pObj1 = (Hop_Obj_t *)vStore->pArray[i  ];
+        pObj2 = (Hop_Obj_t *)vStore->pArray[i-1];
+        if ( Hop_ObjLevel(Hop_Regular(pObj1)) <= Hop_ObjLevel(Hop_Regular(pObj2)) )
+            break;
+        vStore->pArray[i  ] = pObj2;
+        vStore->pArray[i-1] = pObj1;
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/hop/hopCheck.c b/abc-build/src/aig/hop/hopCheck.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/hop/hopCheck.c
@@ -0,0 +1,115 @@
+/**CFile****************************************************************
+
+  FileName    [hopCheck.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Minimalistic And-Inverter Graph package.]
+
+  Synopsis    [AIG checking procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: hopCheck.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "hop.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the consistency of the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hop_ManCheck( Hop_Man_t * p )
+{
+    Hop_Obj_t * pObj, * pObj2;
+    int i;
+    // check primary inputs
+    Hop_ManForEachPi( p, pObj, i )
+    {
+        if ( Hop_ObjFanin0(pObj) || Hop_ObjFanin1(pObj) )
+        {
+            printf( "Hop_ManCheck: The PI node \"%p\" has fanins.\n", pObj );
+            return 0;
+        }
+    }
+    // check primary outputs
+    Hop_ManForEachPo( p, pObj, i )
+    {
+        if ( !Hop_ObjFanin0(pObj) )
+        {
+            printf( "Hop_ManCheck: The PO node \"%p\" has NULL fanin.\n", pObj );
+            return 0;
+        }
+        if ( Hop_ObjFanin1(pObj) )
+        {
+            printf( "Hop_ManCheck: The PO node \"%p\" has second fanin.\n", pObj );
+            return 0;
+        }
+    }
+    // check internal nodes
+    Hop_ManForEachNode( p, pObj, i )
+    {
+        if ( !Hop_ObjFanin0(pObj) || !Hop_ObjFanin1(pObj) )
+        {
+            printf( "Hop_ManCheck: The AIG has internal node \"%p\" with a NULL fanin.\n", pObj );
+            return 0;
+        }
+        if ( Hop_ObjFanin0(pObj)->Id >= Hop_ObjFanin1(pObj)->Id )
+        {
+            printf( "Hop_ManCheck: The AIG has node \"%p\" with a wrong ordering of fanins.\n", pObj );
+            return 0;
+        }
+        pObj2 = Hop_TableLookup( p, pObj );
+        if ( pObj2 != pObj )
+        {
+            printf( "Hop_ManCheck: Node \"%p\" is not in the structural hashing table.\n", pObj );
+            return 0;
+        }
+    }
+    // count the total number of nodes
+    if ( Hop_ManObjNum(p) != 1 + Hop_ManPiNum(p) + Hop_ManPoNum(p) + Hop_ManAndNum(p) + Hop_ManExorNum(p) )
+    {
+        printf( "Hop_ManCheck: The number of created nodes is wrong.\n" );
+        return 0;
+    }
+    // count the number of nodes in the table
+    if ( Hop_TableCountEntries(p) != Hop_ManAndNum(p) + Hop_ManExorNum(p) )
+    {
+        printf( "Hop_ManCheck: The number of nodes in the structural hashing table is wrong.\n" );
+        return 0;
+    }
+//    if ( !Hop_ManIsAcyclic(p) )
+//        return 0;
+    return 1; 
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/hop/hopDfs.c b/abc-build/src/aig/hop/hopDfs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/hop/hopDfs.c
@@ -0,0 +1,591 @@
+/**CFile****************************************************************
+
+  FileName    [hopDfs.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Minimalistic And-Inverter Graph package.]
+
+  Synopsis    [DFS traversal procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: hopDfs.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "hop.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ManDfs_rec( Hop_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+        return;
+    Hop_ManDfs_rec( Hop_ObjFanin0(pObj), vNodes );
+    Hop_ManDfs_rec( Hop_ObjFanin1(pObj), vNodes );
+    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjSetMarkA(pObj);
+    Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Hop_ManDfs( Hop_Man_t * p )
+{
+    Vec_Ptr_t * vNodes;
+    Hop_Obj_t * pObj;
+    int i;
+    vNodes = Vec_PtrAlloc( Hop_ManNodeNum(p) );
+    Hop_ManForEachNode( p, pObj, i )
+        Hop_ManDfs_rec( pObj, vNodes );
+    Hop_ManForEachNode( p, pObj, i )
+        Hop_ObjClearMarkA(pObj);
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Hop_ManDfsNode( Hop_Man_t * p, Hop_Obj_t * pNode )
+{
+    Vec_Ptr_t * vNodes;
+    Hop_Obj_t * pObj;
+    int i;
+    assert( !Hop_IsComplement(pNode) );
+    vNodes = Vec_PtrAlloc( 16 );
+    Hop_ManDfs_rec( pNode, vNodes );
+    Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i )
+        Hop_ObjClearMarkA(pObj);
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the max number of levels in the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hop_ManCountLevels( Hop_Man_t * p )
+{
+    Vec_Ptr_t * vNodes;
+    Hop_Obj_t * pObj;
+    int i, LevelsMax, Level0, Level1;
+    // initialize the levels
+    Hop_ManConst1(p)->pData = NULL;
+    Hop_ManForEachPi( p, pObj, i )
+        pObj->pData = NULL;
+    // compute levels in a DFS order
+    vNodes = Hop_ManDfs( p );
+    Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i )
+    {
+        Level0 = (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData;
+        Level1 = (int)(ABC_PTRUINT_T)Hop_ObjFanin1(pObj)->pData;
+        pObj->pData = (void *)(ABC_PTRUINT_T)(1 + Hop_ObjIsExor(pObj) + Abc_MaxInt(Level0, Level1));
+    }
+    Vec_PtrFree( vNodes );
+    // get levels of the POs
+    LevelsMax = 0;
+    Hop_ManForEachPo( p, pObj, i )
+        LevelsMax = Abc_MaxInt( LevelsMax, (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData );
+    return LevelsMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates correct reference counters at each node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ManCreateRefs( Hop_Man_t * p )
+{
+    Hop_Obj_t * pObj;
+    int i;
+    if ( p->fRefCount )
+        return;
+    p->fRefCount = 1;
+    // clear refs
+    Hop_ObjClearRef( Hop_ManConst1(p) );
+    Hop_ManForEachPi( p, pObj, i )
+        Hop_ObjClearRef( pObj );
+    Hop_ManForEachNode( p, pObj, i )
+        Hop_ObjClearRef( pObj );
+    Hop_ManForEachPo( p, pObj, i )
+        Hop_ObjClearRef( pObj );
+    // set refs
+    Hop_ManForEachNode( p, pObj, i )
+    {
+        Hop_ObjRef( Hop_ObjFanin0(pObj) );
+        Hop_ObjRef( Hop_ObjFanin1(pObj) );
+    }
+    Hop_ManForEachPo( p, pObj, i )
+        Hop_ObjRef( Hop_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of AIG nodes rooted at this cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ConeMark_rec( Hop_Obj_t * pObj )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+        return;
+    Hop_ConeMark_rec( Hop_ObjFanin0(pObj) );
+    Hop_ConeMark_rec( Hop_ObjFanin1(pObj) );
+    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjSetMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of AIG nodes rooted at this cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ConeCleanAndMark_rec( Hop_Obj_t * pObj )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+        return;
+    Hop_ConeCleanAndMark_rec( Hop_ObjFanin0(pObj) );
+    Hop_ConeCleanAndMark_rec( Hop_ObjFanin1(pObj) );
+    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjSetMarkA( pObj );
+    pObj->pData = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of AIG nodes rooted at this cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hop_ConeCountAndMark_rec( Hop_Obj_t * pObj )
+{
+    int Counter;
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+        return 0;
+    Counter = 1 + Hop_ConeCountAndMark_rec( Hop_ObjFanin0(pObj) ) + 
+        Hop_ConeCountAndMark_rec( Hop_ObjFanin1(pObj) );
+    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjSetMarkA( pObj );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of AIG nodes rooted at this cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ConeUnmark_rec( Hop_Obj_t * pObj )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) )
+        return;
+    Hop_ConeUnmark_rec( Hop_ObjFanin0(pObj) ); 
+    Hop_ConeUnmark_rec( Hop_ObjFanin1(pObj) );
+    assert( Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjClearMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of AIG nodes rooted at this cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hop_DagSize( Hop_Obj_t * pObj )
+{
+    int Counter;
+    Counter = Hop_ConeCountAndMark_rec( Hop_Regular(pObj) );
+    Hop_ConeUnmark_rec( Hop_Regular(pObj) );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts how many fanout the given node has.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hop_ObjFanoutCount_rec( Hop_Obj_t * pObj, Hop_Obj_t * pPivot )
+{
+    int Counter;
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+        return (int)(pObj == pPivot);
+    Counter = Hop_ObjFanoutCount_rec( Hop_ObjFanin0(pObj), pPivot ) + 
+              Hop_ObjFanoutCount_rec( Hop_ObjFanin1(pObj), pPivot );
+    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjSetMarkA( pObj );
+    return Counter;
+}
+int Hop_ObjFanoutCount( Hop_Obj_t * pObj, Hop_Obj_t * pPivot )
+{
+    int Counter;
+    assert( !Hop_IsComplement(pPivot) );
+    Counter = Hop_ObjFanoutCount_rec( Hop_Regular(pObj), pPivot );
+    Hop_ConeUnmark_rec( Hop_Regular(pObj) );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the AIG from one manager into another.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_Transfer_rec( Hop_Man_t * pDest, Hop_Obj_t * pObj )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+        return;
+    Hop_Transfer_rec( pDest, Hop_ObjFanin0(pObj) ); 
+    Hop_Transfer_rec( pDest, Hop_ObjFanin1(pObj) );
+    pObj->pData = Hop_And( pDest, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) );
+    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjSetMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the AIG from one manager into another.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_Transfer( Hop_Man_t * pSour, Hop_Man_t * pDest, Hop_Obj_t * pRoot, int nVars )
+{
+    Hop_Obj_t * pObj;
+    int i;
+    // solve simple cases
+    if ( pSour == pDest )
+        return pRoot;
+    if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) )
+        return Hop_NotCond( Hop_ManConst1(pDest), Hop_IsComplement(pRoot) );
+    // set the PI mapping
+    Hop_ManForEachPi( pSour, pObj, i )
+    {
+        if ( i == nVars )
+           break;
+        pObj->pData = Hop_IthVar(pDest, i);
+    }
+    // transfer and set markings
+    Hop_Transfer_rec( pDest, Hop_Regular(pRoot) );
+    // clear the markings
+    Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
+    return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_Compose_rec( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFunc, Hop_Obj_t * pVar )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( Hop_ObjIsMarkA(pObj) )
+        return;
+    if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) )
+    {
+        pObj->pData = pObj == pVar ? pFunc : pObj;
+        return;
+    }
+    Hop_Compose_rec( p, Hop_ObjFanin0(pObj), pFunc, pVar ); 
+    Hop_Compose_rec( p, Hop_ObjFanin1(pObj), pFunc, pVar );
+    pObj->pData = Hop_And( p, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) );
+    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjSetMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, int iVar )
+{
+    // quit if the PI variable is not defined
+    if ( iVar >= Hop_ManPiNum(p) )
+    {
+        printf( "Hop_Compose(): The PI variable %d is not defined.\n", iVar );
+        return NULL;
+    }
+    // recursively perform composition
+    Hop_Compose_rec( p, Hop_Regular(pRoot), pFunc, Hop_ManPi(p, iVar) );
+    // clear the markings
+    Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
+    return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Complements the AIG (pRoot) with the function (pFunc) using PI var (iVar).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_Complement_rec( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pVar )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( Hop_ObjIsMarkA(pObj) )
+        return;
+    if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) )
+    {
+        pObj->pData = pObj == pVar ? Hop_Not(pObj) : pObj;
+        return;
+    }
+    Hop_Complement_rec( p, Hop_ObjFanin0(pObj), pVar ); 
+    Hop_Complement_rec( p, Hop_ObjFanin1(pObj), pVar );
+    pObj->pData = Hop_And( p, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) );
+    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjSetMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Complements the AIG (pRoot) with the function (pFunc) using PI var (iVar).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_Complement( Hop_Man_t * p, Hop_Obj_t * pRoot, int iVar )
+{
+    // quit if the PI variable is not defined
+    if ( iVar >= Hop_ManPiNum(p) )
+    {
+        printf( "Hop_Complement(): The PI variable %d is not defined.\n", iVar );
+        return NULL;
+    }
+    // recursively perform composition
+    Hop_Complement_rec( p, Hop_Regular(pRoot), Hop_ManPi(p, iVar) );
+    // clear the markings
+    Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
+    return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Remaps the AIG (pRoot) to have the given support (uSupp).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_Remap_rec( Hop_Man_t * p, Hop_Obj_t * pObj )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+        return;
+    Hop_Remap_rec( p, Hop_ObjFanin0(pObj) ); 
+    Hop_Remap_rec( p, Hop_ObjFanin1(pObj) );
+    pObj->pData = Hop_And( p, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) );
+    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjSetMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Remaps the AIG (pRoot) to have the given support (uSupp).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_Remap( Hop_Man_t * p, Hop_Obj_t * pRoot, unsigned uSupp, int nVars )
+{
+    Hop_Obj_t * pObj;
+    int i, k;
+    // quit if the PI variable is not defined
+    if ( nVars > Hop_ManPiNum(p) )
+    {
+        printf( "Hop_Remap(): The number of variables (%d) is more than the manager size (%d).\n", nVars, Hop_ManPiNum(p) );
+        return NULL;
+    }
+    // return if constant
+    if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) )
+        return pRoot;
+    if ( uSupp == 0 )
+        return Hop_NotCond( Hop_ManConst0(p), Hop_ObjPhaseCompl(pRoot) );
+    // set the PI mapping
+    k = 0;
+    Hop_ManForEachPi( p, pObj, i )
+    {
+        if ( i == nVars )
+           break;
+        if ( uSupp & (1 << i) )
+            pObj->pData = Hop_IthVar(p, k++);
+        else
+            pObj->pData = Hop_ManConst0(p);
+    }
+    assert( k > 0 && k < nVars );
+    // recursively perform composition
+    Hop_Remap_rec( p, Hop_Regular(pRoot) );
+    // clear the markings
+    Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
+    return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Permute the AIG according to the given permutation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_Permute( Hop_Man_t * p, Hop_Obj_t * pRoot, int nRootVars, int * pPermute )
+{
+    Hop_Obj_t * pObj;
+    int i;
+    // return if constant
+    if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) )
+        return pRoot;
+    // create mapping
+    Hop_ManForEachPi( p, pObj, i )
+    {
+        if ( i == nRootVars )
+            break;
+        assert( pPermute[i] >= 0 && pPermute[i] < Hop_ManPiNum(p) );
+        pObj->pData = Hop_IthVar( p, pPermute[i] );
+    }
+    // recursively perform composition
+    Hop_Remap_rec( p, Hop_Regular(pRoot) );
+    // clear the markings
+    Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
+    return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/hop/hopMan.c b/abc-build/src/aig/hop/hopMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/hop/hopMan.c
@@ -0,0 +1,169 @@
+/**CFile****************************************************************
+
+  FileName    [hopMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Minimalistic And-Inverter Graph package.]
+
+  Synopsis    [AIG manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: hopMan.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "hop.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Man_t * Hop_ManStart()
+{
+    Hop_Man_t * p;
+    // start the manager
+    p = ABC_ALLOC( Hop_Man_t, 1 );
+    memset( p, 0, sizeof(Hop_Man_t) );
+    // perform initializations
+    p->nTravIds = 1;
+    p->fRefCount = 1;
+    p->fCatchExor = 0;
+    // allocate arrays for nodes
+    p->vPis = Vec_PtrAlloc( 100 );
+    p->vPos = Vec_PtrAlloc( 100 );
+    // prepare the internal memory manager
+    Hop_ManStartMemory( p );
+    // create the constant node
+    p->pConst1 = Hop_ManFetchMemory( p );
+    p->pConst1->Type = AIG_CONST1;
+    p->pConst1->fPhase = 1;
+    p->nCreated = 1;
+    // start the table
+//    p->nTableSize = 107;
+    p->nTableSize = 10007;
+    p->pTable = ABC_ALLOC( Hop_Obj_t *, p->nTableSize );
+    memset( p->pTable, 0, sizeof(Hop_Obj_t *) * p->nTableSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ManStop( Hop_Man_t * p )
+{
+    Hop_Obj_t * pObj;
+    int i;
+    // make sure the nodes have clean marks
+    pObj = Hop_ManConst1(p);
+    assert( !pObj->fMarkA && !pObj->fMarkB );
+    Hop_ManForEachPi( p, pObj, i )
+        assert( !pObj->fMarkA && !pObj->fMarkB );
+    Hop_ManForEachPo( p, pObj, i )
+        assert( !pObj->fMarkA && !pObj->fMarkB );
+    Hop_ManForEachNode( p, pObj, i )
+        assert( !pObj->fMarkA && !pObj->fMarkB );
+    // print time
+    if ( p->time1 ) { ABC_PRT( "time1", p->time1 ); }
+    if ( p->time2 ) { ABC_PRT( "time2", p->time2 ); }
+//    Hop_TableProfile( p );
+    if ( p->vChunks )  Hop_ManStopMemory( p );
+    if ( p->vPis )     Vec_PtrFree( p->vPis );
+    if ( p->vPos )     Vec_PtrFree( p->vPos );
+    if ( p->vObjs )    Vec_PtrFree( p->vObjs );
+    ABC_FREE( p->pTable );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of dangling nodes removed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hop_ManCleanup( Hop_Man_t * p )
+{
+    Vec_Ptr_t * vObjs;
+    Hop_Obj_t * pNode;
+    int i, nNodesOld;
+    assert( p->fRefCount );
+    nNodesOld = Hop_ManNodeNum(p);
+    // collect roots of dangling nodes
+    vObjs = Vec_PtrAlloc( 100 );
+    Hop_ManForEachNode( p, pNode, i )
+        if ( Hop_ObjRefs(pNode) == 0 )
+            Vec_PtrPush( vObjs, pNode );
+    // recursively remove dangling nodes
+    Vec_PtrForEachEntry( Hop_Obj_t *, vObjs, pNode, i )
+        Hop_ObjDelete_rec( p, pNode );
+    Vec_PtrFree( vObjs );
+    return nNodesOld - Hop_ManNodeNum(p);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ManPrintStats( Hop_Man_t * p )
+{
+    printf( "PI/PO = %d/%d. ", Hop_ManPiNum(p), Hop_ManPoNum(p) );
+    printf( "A = %7d. ",       Hop_ManAndNum(p) );
+    printf( "X = %5d. ",       Hop_ManExorNum(p) );
+    printf( "Cre = %7d. ",     p->nCreated );
+    printf( "Del = %7d. ",     p->nDeleted );
+    printf( "Lev = %3d. ",     Hop_ManCountLevels(p) );
+    printf( "\n" );
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/hop/hopMem.c b/abc-build/src/aig/hop/hopMem.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/hop/hopMem.c
@@ -0,0 +1,120 @@
+/**CFile****************************************************************
+
+  FileName    [hopMem.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Minimalistic And-Inverter Graph package.]
+
+  Synopsis    [Memory management for the AIG nodes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: hopMem.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "hop.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// memory management
+#define IVY_PAGE_SIZE      12        // page size containing 2^IVY_PAGE_SIZE nodes
+#define IVY_PAGE_MASK    4095        // page bitmask (2^IVY_PAGE_SIZE)-1
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the internal memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ManStartMemory( Hop_Man_t * p )
+{
+    p->vChunks = Vec_PtrAlloc( 128 );
+    p->vPages = Vec_PtrAlloc( 128 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the internal memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ManStopMemory( Hop_Man_t * p )
+{
+    void * pMemory;
+    int i;
+    Vec_PtrForEachEntry( void *, p->vChunks, pMemory, i )
+        ABC_FREE( pMemory );
+    Vec_PtrFree( p->vChunks );
+    Vec_PtrFree( p->vPages );
+    p->pListFree = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates additional memory for the nodes.]
+
+  Description [Allocates IVY_PAGE_SIZE nodes. Aligns memory by 32 bytes. 
+  Records the pointer to the AIG manager in the -1 entry.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ManAddMemory( Hop_Man_t * p )
+{
+    char * pMemory;
+    int i, nBytes;
+    assert( sizeof(Hop_Obj_t) <= 64 );
+    assert( p->pListFree == NULL );
+//    assert( (Hop_ManObjNum(p) & IVY_PAGE_MASK) == 0 );
+    // allocate new memory page
+    nBytes = sizeof(Hop_Obj_t) * (1<<IVY_PAGE_SIZE) + 64;
+    pMemory = ABC_ALLOC( char, nBytes );
+    Vec_PtrPush( p->vChunks, pMemory );
+    // align memory at the 32-byte boundary
+    pMemory = pMemory + 64 - (((int)(ABC_PTRUINT_T)pMemory) & 63);
+    // remember the manager in the first entry
+    Vec_PtrPush( p->vPages, pMemory );
+    // break the memory down into nodes
+    p->pListFree = (Hop_Obj_t *)pMemory;
+    for ( i = 1; i <= IVY_PAGE_MASK; i++ )
+    {
+        *((char **)pMemory) = pMemory + sizeof(Hop_Obj_t);
+        pMemory += sizeof(Hop_Obj_t);
+    }
+    *((char **)pMemory) = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/hop/hopObj.c b/abc-build/src/aig/hop/hopObj.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/hop/hopObj.c
@@ -0,0 +1,277 @@
+/**CFile****************************************************************
+
+  FileName    [hopObj.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Minimalistic And-Inverter Graph package.]
+
+  Synopsis    [Adding/removing objects.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: hopObj.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "hop.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates primary input.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_ObjCreatePi( Hop_Man_t * p )
+{
+    Hop_Obj_t * pObj;
+    pObj = Hop_ManFetchMemory( p );
+    pObj->Type = AIG_PI;
+    pObj->PioNum = Vec_PtrSize( p->vPis );
+    Vec_PtrPush( p->vPis, pObj );
+    p->nObjs[AIG_PI]++;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates primary output with the given driver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_ObjCreatePo( Hop_Man_t * p, Hop_Obj_t * pDriver )
+{
+    Hop_Obj_t * pObj;
+    pObj = Hop_ManFetchMemory( p );
+    pObj->Type = AIG_PO;
+    Vec_PtrPush( p->vPos, pObj );
+    // add connections
+    pObj->pFanin0 = pDriver;
+    if ( p->fRefCount )
+        Hop_ObjRef( Hop_Regular(pDriver) );
+    else
+        pObj->nRefs = Hop_ObjLevel( Hop_Regular(pDriver) );
+    // set the phase
+    pObj->fPhase = Hop_ObjPhaseCompl(pDriver);
+    // update node counters of the manager
+    p->nObjs[AIG_PO]++;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the new node assuming it does not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_ObjCreate( Hop_Man_t * p, Hop_Obj_t * pGhost )
+{
+    Hop_Obj_t * pObj;
+    assert( !Hop_IsComplement(pGhost) );
+    assert( Hop_ObjIsNode(pGhost) );
+    assert( pGhost == &p->Ghost );
+    // get memory for the new object
+    pObj = Hop_ManFetchMemory( p );
+    pObj->Type = pGhost->Type;
+    // add connections
+    Hop_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 );
+    // update node counters of the manager
+    p->nObjs[Hop_ObjType(pObj)]++;
+    assert( pObj->pData == NULL );
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Connect the object to the fanin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ObjConnect( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFan0, Hop_Obj_t * pFan1 )
+{
+    assert( !Hop_IsComplement(pObj) );
+    assert( Hop_ObjIsNode(pObj) );
+    // add the first fanin
+    pObj->pFanin0 = pFan0;
+    pObj->pFanin1 = pFan1;
+    // increment references of the fanins and add their fanouts
+    if ( p->fRefCount )
+    {
+        if ( pFan0 != NULL )
+            Hop_ObjRef( Hop_ObjFanin0(pObj) );
+        if ( pFan1 != NULL )
+            Hop_ObjRef( Hop_ObjFanin1(pObj) );
+    }
+    else
+        pObj->nRefs = Hop_ObjLevelNew( pObj );
+    // set the phase
+    pObj->fPhase = Hop_ObjPhaseCompl(pFan0) & Hop_ObjPhaseCompl(pFan1);
+    // add the node to the structural hash table
+    Hop_TableInsert( p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Connect the object to the fanin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ObjDisconnect( Hop_Man_t * p, Hop_Obj_t * pObj )
+{
+    assert( !Hop_IsComplement(pObj) );
+    assert( Hop_ObjIsNode(pObj) );
+    // remove connections
+    if ( pObj->pFanin0 != NULL )
+        Hop_ObjDeref(Hop_ObjFanin0(pObj));
+    if ( pObj->pFanin1 != NULL )
+        Hop_ObjDeref(Hop_ObjFanin1(pObj));
+    // remove the node from the structural hash table
+    Hop_TableDelete( p, pObj );
+    // add the first fanin
+    pObj->pFanin0 = NULL;
+    pObj->pFanin1 = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ObjDelete( Hop_Man_t * p, Hop_Obj_t * pObj )
+{
+    assert( !Hop_IsComplement(pObj) );
+    assert( !Hop_ObjIsTerm(pObj) );
+    assert( Hop_ObjRefs(pObj) == 0 );
+    // update node counters of the manager
+    p->nObjs[pObj->Type]--;
+    p->nDeleted++;
+    // remove connections
+    Hop_ObjDisconnect( p, pObj );
+    // remove PIs/POs from the arrays
+    if ( Hop_ObjIsPi(pObj) )
+        Vec_PtrRemove( p->vPis, pObj );
+    // free the node
+    Hop_ManRecycleMemory( p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the MFFC of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ObjDelete_rec( Hop_Man_t * p, Hop_Obj_t * pObj )
+{
+    Hop_Obj_t * pFanin0, * pFanin1;
+    assert( !Hop_IsComplement(pObj) );
+    if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) )
+        return;
+    assert( Hop_ObjIsNode(pObj) );
+    pFanin0 = Hop_ObjFanin0(pObj);
+    pFanin1 = Hop_ObjFanin1(pObj);
+    Hop_ObjDelete( p, pObj );
+    if ( pFanin0 && !Hop_ObjIsNone(pFanin0) && Hop_ObjRefs(pFanin0) == 0 )
+        Hop_ObjDelete_rec( p, pFanin0 );
+    if ( pFanin1 && !Hop_ObjIsNone(pFanin1) && Hop_ObjRefs(pFanin1) == 0 )
+        Hop_ObjDelete_rec( p, pFanin1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the representative of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_ObjRepr( Hop_Obj_t * pObj )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( pObj->pData == NULL || pObj->pData == pObj )
+        return pObj;
+    return Hop_ObjRepr( (Hop_Obj_t *)pObj->pData );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets an equivalence relation between the nodes.]
+
+  Description [Makes the representative of pNew point to the representaive of pOld.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ObjCreateChoice( Hop_Obj_t * pOld, Hop_Obj_t * pNew )
+{
+    Hop_Obj_t * pOldRepr;
+    Hop_Obj_t * pNewRepr;
+    assert( pOld != NULL && pNew != NULL );
+    pOldRepr = Hop_ObjRepr(pOld);
+    pNewRepr = Hop_ObjRepr(pNew);
+    if ( pNewRepr != pOldRepr )
+        pNewRepr->pData = pOldRepr;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/hop/hopOper.c b/abc-build/src/aig/hop/hopOper.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/hop/hopOper.c
@@ -0,0 +1,378 @@
+/**CFile****************************************************************
+
+  FileName    [hopOper.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Minimalistic And-Inverter Graph package.]
+
+  Synopsis    [AIG operations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: hopOper.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "hop.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// procedure to detect an EXOR gate
+static inline int Hop_ObjIsExorType( Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 )
+{
+    if ( !Hop_IsComplement(p0) || !Hop_IsComplement(p1) )
+        return 0;
+    p0 = Hop_Regular(p0);
+    p1 = Hop_Regular(p1);
+    if ( !Hop_ObjIsAnd(p0) || !Hop_ObjIsAnd(p1) )
+        return 0;
+    if ( Hop_ObjFanin0(p0) != Hop_ObjFanin0(p1) || Hop_ObjFanin1(p0) != Hop_ObjFanin1(p1) )
+        return 0;
+    if ( Hop_ObjFaninC0(p0) == Hop_ObjFaninC0(p1) || Hop_ObjFaninC1(p0) == Hop_ObjFaninC1(p1) )
+        return 0;
+    *ppFan0 = Hop_ObjChild0(p0);
+    *ppFan1 = Hop_ObjChild1(p0);
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns i-th elementary variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_IthVar( Hop_Man_t * p, int i )
+{
+    int v;
+    for ( v = Hop_ManPiNum(p); v <= i; v++ )
+        Hop_ObjCreatePi( p );
+    assert( i < Vec_PtrSize(p->vPis) );
+    return Hop_ManPi( p, i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform one operation.]
+
+  Description [The argument nodes can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_Oper( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type )
+{
+    if ( Type == AIG_AND )
+        return Hop_And( p, p0, p1 );
+    if ( Type == AIG_EXOR )
+        return Hop_Exor( p, p0, p1 );
+    assert( 0 );
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs canonicization step.]
+
+  Description [The argument nodes can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_And( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 )
+{
+    Hop_Obj_t * pGhost, * pResult;
+//    Hop_Obj_t * pFan0, * pFan1;
+    // check trivial cases
+    if ( p0 == p1 )
+        return p0;
+    if ( p0 == Hop_Not(p1) )
+        return Hop_Not(p->pConst1);
+    if ( Hop_Regular(p0) == p->pConst1 )
+        return p0 == p->pConst1 ? p1 : Hop_Not(p->pConst1);
+    if ( Hop_Regular(p1) == p->pConst1 )
+        return p1 == p->pConst1 ? p0 : Hop_Not(p->pConst1);
+    // check if it can be an EXOR gate
+//    if ( Hop_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) )
+//        return Hop_Exor( p, pFan0, pFan1 );
+    // check the table
+    pGhost = Hop_ObjCreateGhost( p, p0, p1, AIG_AND );
+    if ( (pResult = Hop_TableLookup( p, pGhost )) )
+        return pResult;
+    return Hop_ObjCreate( p, pGhost );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs canonicization step.]
+
+  Description [The argument nodes can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_Exor( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 )
+{
+/*
+    Hop_Obj_t * pGhost, * pResult;
+    // check trivial cases
+    if ( p0 == p1 )
+        return Hop_Not(p->pConst1);
+    if ( p0 == Hop_Not(p1) )
+        return p->pConst1;
+    if ( Hop_Regular(p0) == p->pConst1 )
+        return Hop_NotCond( p1, p0 == p->pConst1 );
+    if ( Hop_Regular(p1) == p->pConst1 )
+        return Hop_NotCond( p0, p1 == p->pConst1 );
+    // check the table
+    pGhost = Hop_ObjCreateGhost( p, p0, p1, AIG_EXOR );
+    if ( pResult = Hop_TableLookup( p, pGhost ) )
+        return pResult;
+    return Hop_ObjCreate( p, pGhost );
+*/
+    return Hop_Or( p, Hop_And(p, p0, Hop_Not(p1)), Hop_And(p, Hop_Not(p0), p1) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements Boolean OR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_Or( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 )
+{
+    return Hop_Not( Hop_And( p, Hop_Not(p0), Hop_Not(p1) ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements ITE operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_Mux( Hop_Man_t * p, Hop_Obj_t * pC, Hop_Obj_t * p1, Hop_Obj_t * p0 )
+{
+/*    
+    Hop_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp;
+    int Count0, Count1;
+    // consider trivial cases
+    if ( p0 == Hop_Not(p1) )
+        return Hop_Exor( p, pC, p0 );
+    // other cases can be added
+    // implement the first MUX (F = C * x1 + C' * x0)
+
+    // check for constants here!!!
+
+    pTempA1 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, pC,          p1, AIG_AND) );
+    pTempA2 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pC), p0, AIG_AND) );
+    if ( pTempA1 && pTempA2 )
+    {
+        pTemp = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pTempA1), Hop_Not(pTempA2), AIG_AND) );
+        if ( pTemp ) return Hop_Not(pTemp);
+    }
+    Count0 = (pTempA1 != NULL) + (pTempA2 != NULL);
+    // implement the second MUX (F' = C * x1' + C' * x0')
+    pTempB1 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, pC,          Hop_Not(p1), AIG_AND) );
+    pTempB2 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pC), Hop_Not(p0), AIG_AND) );
+    if ( pTempB1 && pTempB2 )
+    {
+        pTemp = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pTempB1), Hop_Not(pTempB2), AIG_AND) );
+        if ( pTemp ) return pTemp;
+    }
+    Count1 = (pTempB1 != NULL) + (pTempB2 != NULL);
+    // compare and decide which one to implement
+    if ( Count0 >= Count1 )
+    {
+        pTempA1 = pTempA1? pTempA1 : Hop_And(p, pC,          p1);
+        pTempA2 = pTempA2? pTempA2 : Hop_And(p, Hop_Not(pC), p0);
+        return Hop_Or( p, pTempA1, pTempA2 );
+    }
+    pTempB1 = pTempB1? pTempB1 : Hop_And(p, pC,          Hop_Not(p1));
+    pTempB2 = pTempB2? pTempB2 : Hop_And(p, Hop_Not(pC), Hop_Not(p0));
+    return Hop_Not( Hop_Or( p, pTempB1, pTempB2 ) );
+*/
+    return Hop_Or( p, Hop_And(p, pC, p1), Hop_And(p, Hop_Not(pC), p0) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements ITE operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_Maj( Hop_Man_t * p, Hop_Obj_t * pA, Hop_Obj_t * pB, Hop_Obj_t * pC )
+{
+    return Hop_Or( p, Hop_Or(p, Hop_And(p, pA, pB), Hop_And(p, pA, pC)), Hop_And(p, pB, pC) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs the well-balanced tree of gates.]
+
+  Description [Disregards levels and possible logic sharing.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_Multi_rec( Hop_Man_t * p, Hop_Obj_t ** ppObjs, int nObjs, Hop_Type_t Type )
+{
+    Hop_Obj_t * pObj1, * pObj2;
+    if ( nObjs == 1 )
+        return ppObjs[0];
+    pObj1 = Hop_Multi_rec( p, ppObjs,           nObjs/2,         Type );
+    pObj2 = Hop_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type );
+    return Hop_Oper( p, pObj1, pObj2, Type );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Old code.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_Multi( Hop_Man_t * p, Hop_Obj_t ** pArgs, int nArgs, Hop_Type_t Type )
+{
+    assert( Type == AIG_AND || Type == AIG_EXOR );
+    assert( nArgs > 0 );
+    return Hop_Multi_rec( p, pArgs, nArgs, Type );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_Miter( Hop_Man_t * p, Vec_Ptr_t * vPairs )
+{
+    int i;
+    assert( vPairs->nSize > 0 );
+    assert( vPairs->nSize % 2 == 0 );
+    // go through the cubes of the node's SOP
+    for ( i = 0; i < vPairs->nSize; i += 2 )
+        vPairs->pArray[i/2] = Hop_Not( Hop_Exor( p, (Hop_Obj_t *)vPairs->pArray[i], (Hop_Obj_t *)vPairs->pArray[i+1] ) );
+    vPairs->nSize = vPairs->nSize/2;
+    return Hop_Not( Hop_Multi_rec( p, (Hop_Obj_t **)vPairs->pArray, vPairs->nSize, AIG_AND ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates AND function with nVars inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_CreateAnd( Hop_Man_t * p, int nVars )
+{
+    Hop_Obj_t * pFunc;
+    int i;
+    pFunc = Hop_ManConst1( p );
+    for ( i = 0; i < nVars; i++ )
+        pFunc = Hop_And( p, pFunc, Hop_IthVar(p, i) );
+    return pFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates AND function with nVars inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_CreateOr( Hop_Man_t * p, int nVars )
+{
+    Hop_Obj_t * pFunc;
+    int i;
+    pFunc = Hop_ManConst0( p );
+    for ( i = 0; i < nVars; i++ )
+        pFunc = Hop_Or( p, pFunc, Hop_IthVar(p, i) );
+    return pFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates AND function with nVars inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_CreateExor( Hop_Man_t * p, int nVars )
+{
+    Hop_Obj_t * pFunc;
+    int i;
+    pFunc = Hop_ManConst0( p );
+    for ( i = 0; i < nVars; i++ )
+        pFunc = Hop_Exor( p, pFunc, Hop_IthVar(p, i) );
+    return pFunc;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/hop/hopTable.c b/abc-build/src/aig/hop/hopTable.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/hop/hopTable.c
@@ -0,0 +1,232 @@
+/**CFile****************************************************************
+
+  FileName    [hopTable.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Minimalistic And-Inverter Graph package.]
+
+  Synopsis    [Structural hashing table.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006. ]
+
+  Revision    [$Id: hopTable.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "hop.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// hashing the node
+static unsigned long Hop_Hash( Hop_Obj_t * pObj, int TableSize ) 
+{
+    unsigned long Key = Hop_ObjIsExor(pObj) * 1699;
+    Key ^= Hop_ObjFanin0(pObj)->Id * 7937;
+    Key ^= Hop_ObjFanin1(pObj)->Id * 2971;
+    Key ^= Hop_ObjFaninC0(pObj) * 911;
+    Key ^= Hop_ObjFaninC1(pObj) * 353;
+    return Key % TableSize;
+}
+
+// returns the place where this node is stored (or should be stored)
+static Hop_Obj_t ** Hop_TableFind( Hop_Man_t * p, Hop_Obj_t * pObj )
+{
+    Hop_Obj_t ** ppEntry;
+    assert( Hop_ObjChild0(pObj) && Hop_ObjChild1(pObj) );
+    assert( Hop_ObjFanin0(pObj)->Id < Hop_ObjFanin1(pObj)->Id );
+    for ( ppEntry = p->pTable + Hop_Hash(pObj, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext )
+        if ( *ppEntry == pObj )
+            return ppEntry;
+    assert( *ppEntry == NULL );
+    return ppEntry;
+}
+
+static void         Hop_TableResize( Hop_Man_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    [Checks if a node with the given attributes is in the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_TableLookup( Hop_Man_t * p, Hop_Obj_t * pGhost )
+{
+    Hop_Obj_t * pEntry;
+    assert( !Hop_IsComplement(pGhost) );
+    assert( Hop_ObjChild0(pGhost) && Hop_ObjChild1(pGhost) );
+    assert( Hop_ObjFanin0(pGhost)->Id < Hop_ObjFanin1(pGhost)->Id );
+    if ( p->fRefCount && (!Hop_ObjRefs(Hop_ObjFanin0(pGhost)) || !Hop_ObjRefs(Hop_ObjFanin1(pGhost))) )
+        return NULL;
+    for ( pEntry = p->pTable[Hop_Hash(pGhost, p->nTableSize)]; pEntry; pEntry = pEntry->pNext )
+    {
+        if ( Hop_ObjChild0(pEntry) == Hop_ObjChild0(pGhost) && 
+             Hop_ObjChild1(pEntry) == Hop_ObjChild1(pGhost) && 
+             Hop_ObjType(pEntry) == Hop_ObjType(pGhost) )
+            return pEntry;
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the new node to the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_TableInsert( Hop_Man_t * p, Hop_Obj_t * pObj )
+{
+    Hop_Obj_t ** ppPlace;
+    assert( !Hop_IsComplement(pObj) );
+    assert( Hop_TableLookup(p, pObj) == NULL );
+    if ( (pObj->Id & 0xFF) == 0 && 2 * p->nTableSize < Hop_ManNodeNum(p) )
+        Hop_TableResize( p );
+    ppPlace = Hop_TableFind( p, pObj );
+    assert( *ppPlace == NULL );
+    *ppPlace = pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the node from the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_TableDelete( Hop_Man_t * p, Hop_Obj_t * pObj )
+{
+    Hop_Obj_t ** ppPlace;
+    assert( !Hop_IsComplement(pObj) );
+    ppPlace = Hop_TableFind( p, pObj );
+    assert( *ppPlace == pObj ); // node should be in the table
+    // remove the node
+    *ppPlace = pObj->pNext;
+    pObj->pNext = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of nodes in the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hop_TableCountEntries( Hop_Man_t * p )
+{
+    Hop_Obj_t * pEntry;
+    int i, Counter = 0;
+    for ( i = 0; i < p->nTableSize; i++ )
+        for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext )
+            Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the table.]
+
+  Description [Typically this procedure should not be called.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_TableResize( Hop_Man_t * p )
+{
+    Hop_Obj_t * pEntry, * pNext;
+    Hop_Obj_t ** pTableOld, ** ppPlace;
+    int nTableSizeOld, Counter, nEntries, i;
+    abctime clk;
+clk = Abc_Clock();
+    // save the old table
+    pTableOld = p->pTable;
+    nTableSizeOld = p->nTableSize;
+    // get the new table
+    p->nTableSize = Abc_PrimeCudd( 2 * Hop_ManNodeNum(p) ); 
+    p->pTable = ABC_ALLOC( Hop_Obj_t *, p->nTableSize );
+    memset( p->pTable, 0, sizeof(Hop_Obj_t *) * p->nTableSize );
+    // rehash the entries from the old table
+    Counter = 0;
+    for ( i = 0; i < nTableSizeOld; i++ )
+    for ( pEntry = pTableOld[i], pNext = pEntry? pEntry->pNext : NULL; pEntry; pEntry = pNext, pNext = pEntry? pEntry->pNext : NULL )
+    {
+        // get the place where this entry goes in the table 
+        ppPlace = Hop_TableFind( p, pEntry );
+        assert( *ppPlace == NULL ); // should not be there
+        // add the entry to the list
+        *ppPlace = pEntry;
+        pEntry->pNext = NULL;
+        Counter++;
+    }
+    nEntries = Hop_ManNodeNum(p);
+    assert( Counter == nEntries );
+//    printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize );
+//    ABC_PRT( "Time", Abc_Clock() - clk );
+    // replace the table and the parameters
+    ABC_FREE( pTableOld );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Profiles the hash table.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Hop_TableProfile( Hop_Man_t * p )
+{
+    Hop_Obj_t * pEntry;
+    int i, Counter;
+    for ( i = 0; i < p->nTableSize; i++ )
+    {
+        Counter = 0;
+        for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext )
+            Counter++;
+        if ( Counter ) 
+            printf( "%d ", Counter );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/hop/hopTruth.c b/abc-build/src/aig/hop/hopTruth.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/hop/hopTruth.c
@@ -0,0 +1,274 @@
+/**CFile****************************************************************
+
+  FileName    [hopTruth.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Minimalistic And-Inverter Graph package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: hopTruth.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "hop.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int  Hop_ManTruthWordNum( int nVars )  { return nVars <= 5 ? 1 : (1 << (nVars - 5)); }
+
+static inline void Hop_ManTruthCopy( unsigned * pOut, unsigned * pIn, int nVars )
+{
+    int w;
+    for ( w = Hop_ManTruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = pIn[w];
+}
+static inline void Hop_ManTruthClear( unsigned * pOut, int nVars )
+{
+    int w;
+    for ( w = Hop_ManTruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = 0;
+}
+static inline void Hop_ManTruthFill( unsigned * pOut, int nVars )
+{
+    int w;
+    for ( w = Hop_ManTruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = ~(unsigned)0;
+}
+static inline void Hop_ManTruthNot( unsigned * pOut, unsigned * pIn, int nVars )
+{
+    int w;
+    for ( w = Hop_ManTruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = ~pIn[w];
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    [Construct BDDs and mark AIG nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hop_ManConvertAigToTruth_rec1( Hop_Obj_t * pObj )
+{
+    int Counter = 0;
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+        return 0;
+    Counter += Hop_ManConvertAigToTruth_rec1( Hop_ObjFanin0(pObj) ); 
+    Counter += Hop_ManConvertAigToTruth_rec1( Hop_ObjFanin1(pObj) );
+    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjSetMarkA( pObj );
+    return Counter + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Hop_ManConvertAigToTruth_rec2( Hop_Obj_t * pObj, Vec_Int_t * vTruth, int nWords )
+{
+    unsigned * pTruth, * pTruth0, * pTruth1;
+    int i;
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) )
+        return (unsigned *)pObj->pData;
+    // compute the truth tables of the fanins
+    pTruth0 = Hop_ManConvertAigToTruth_rec2( Hop_ObjFanin0(pObj), vTruth, nWords );
+    pTruth1 = Hop_ManConvertAigToTruth_rec2( Hop_ObjFanin1(pObj), vTruth, nWords );
+    // creat the truth table of the node
+    pTruth  = Vec_IntFetch( vTruth, nWords );
+    if ( Hop_ObjIsExor(pObj) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = pTruth0[i] ^ pTruth1[i];
+    else if ( !Hop_ObjFaninC0(pObj) && !Hop_ObjFaninC1(pObj) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = pTruth0[i] & pTruth1[i];
+    else if ( !Hop_ObjFaninC0(pObj) && Hop_ObjFaninC1(pObj) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = pTruth0[i] & ~pTruth1[i];
+    else if ( Hop_ObjFaninC0(pObj) && !Hop_ObjFaninC1(pObj) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ~pTruth0[i] & pTruth1[i];
+    else // if ( Hop_ObjFaninC0(pObj) && Hop_ObjFaninC1(pObj) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ~pTruth0[i] & ~pTruth1[i];
+    assert( Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjClearMarkA( pObj );
+    pObj->pData = pTruth;
+    return pTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table of the node.]
+
+  Description [Assumes that the structural support is no more than 8 inputs.
+  Uses array vTruth to store temporary truth tables. The returned pointer should 
+  be used immediately.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Hop_ManConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, int fMsbFirst )
+{
+    static unsigned uTruths[8][8] = { // elementary truth tables
+        { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA },
+        { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC },
+        { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 },
+        { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 },
+        { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, 
+        { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, 
+        { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, 
+        { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } 
+    };
+    Hop_Obj_t * pObj;
+    unsigned * pTruth, * pTruth2;
+    int i, nWords, nNodes;
+    Vec_Ptr_t * vTtElems;
+
+    // if the number of variables is more than 8, allocate truth tables
+    if ( nVars > 8 )
+        vTtElems = Vec_PtrAllocTruthTables( nVars );
+    else
+        vTtElems = NULL;
+
+    // clear the data fields and set marks
+    nNodes = Hop_ManConvertAigToTruth_rec1( Hop_Regular(pRoot) );
+    // prepare memory
+    nWords = Hop_TruthWordNum( nVars );
+    Vec_IntClear( vTruth );
+    Vec_IntGrow( vTruth, nWords * (nNodes+1) );
+    pTruth = Vec_IntFetch( vTruth, nWords );
+    // check the case of a constant
+    if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) )
+    {
+        assert( nNodes == 0 );
+        if ( Hop_IsComplement(pRoot) )
+            Hop_ManTruthClear( pTruth, nVars );
+        else
+            Hop_ManTruthFill( pTruth, nVars );
+        return pTruth;
+    }
+    // set elementary truth tables at the leaves
+    assert( nVars <= Hop_ManPiNum(p) );
+//    assert( Hop_ManPiNum(p) <= 8 ); 
+    if ( fMsbFirst )
+    {
+//        Hop_ManForEachPi( p, pObj, i )
+        for ( i = 0; i < nVars; i++ )
+        {
+            pObj = Hop_ManPi( p, i );
+            if ( vTtElems )
+                pObj->pData = Vec_PtrEntry(vTtElems, nVars-1-i);
+            else               
+                pObj->pData = (void *)uTruths[nVars-1-i];
+        }
+    }
+    else
+    {
+//        Hop_ManForEachPi( p, pObj, i )
+        for ( i = 0; i < nVars; i++ )
+        {
+            pObj = Hop_ManPi( p, i );
+            if ( vTtElems )
+                pObj->pData = Vec_PtrEntry(vTtElems, i);
+            else               
+                pObj->pData = (void *)uTruths[i];
+        }
+    }
+    // clear the marks and compute the truth table
+    pTruth2 = Hop_ManConvertAigToTruth_rec2( Hop_Regular(pRoot), vTruth, nWords );
+    // copy the result
+    Hop_ManTruthCopy( pTruth, pTruth2, nVars );
+    if ( Hop_IsComplement(pRoot) )
+        Hop_ManTruthNot( pTruth, pTruth, nVars );
+    if ( vTtElems )
+        Vec_PtrFree( vTtElems );
+    return pTruth;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compute truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static word Truth[8] = 
+{
+    ABC_CONST(0xAAAAAAAAAAAAAAAA),
+    ABC_CONST(0xCCCCCCCCCCCCCCCC),
+    ABC_CONST(0xF0F0F0F0F0F0F0F0),
+    ABC_CONST(0xFF00FF00FF00FF00),
+    ABC_CONST(0xFFFF0000FFFF0000),
+    ABC_CONST(0xFFFFFFFF00000000),
+    ABC_CONST(0x0000000000000000),
+    ABC_CONST(0xFFFFFFFFFFFFFFFF)
+};
+word Hop_ManComputeTruth6_rec( Hop_Man_t * p, Hop_Obj_t * pObj )
+{
+    word Truth0, Truth1;
+    if ( Hop_ObjIsPi(pObj) )
+        return Truth[pObj->iData];
+    assert( Hop_ObjIsNode(pObj) );
+    Truth0 = Hop_ManComputeTruth6_rec( p, Hop_ObjFanin0(pObj) );
+    Truth1 = Hop_ManComputeTruth6_rec( p, Hop_ObjFanin1(pObj) );
+    Truth0 = Hop_ObjFaninC0(pObj) ? ~Truth0 : Truth0;
+    Truth1 = Hop_ObjFaninC1(pObj) ? ~Truth1 : Truth1;
+    return Truth0 & Truth1;
+}
+word Hop_ManComputeTruth6( Hop_Man_t * p, Hop_Obj_t * pObj, int nVars )
+{
+    word Truth;
+    int i;
+    if ( Hop_ObjIsConst1( Hop_Regular(pObj) ) )
+        return Hop_IsComplement(pObj) ? 0 : ~(word)0;
+    for ( i = 0; i < nVars; i++ )
+        Hop_ManPi( p, i )->iData = i;
+    Truth = Hop_ManComputeTruth6_rec( p, Hop_Regular(pObj) );
+    return Hop_IsComplement(pObj) ? ~Truth : Truth;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/hop/hopUtil.c b/abc-build/src/aig/hop/hopUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/hop/hopUtil.c
@@ -0,0 +1,578 @@
+/**CFile****************************************************************
+
+  FileName    [hopUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Various procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: hopUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "hop.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Increments the current traversal ID of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ManIncrementTravId( Hop_Man_t * p )
+{
+    if ( p->nTravIds >= (1<<30)-1 )
+        Hop_ManCleanData( p );
+    p->nTravIds++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the data pointers for the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ManCleanData( Hop_Man_t * p )
+{
+    Hop_Obj_t * pObj;
+    int i;
+    p->nTravIds = 1;
+    Hop_ManConst1(p)->pData = NULL;
+    Hop_ManForEachPi( p, pObj, i )
+        pObj->pData = NULL;
+    Hop_ManForEachPo( p, pObj, i )
+        pObj->pData = NULL;
+    Hop_ManForEachNode( p, pObj, i )
+        pObj->pData = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively cleans the data pointers in the cone of the node.]
+
+  Description [Applicable to small AIGs only because no caching is performed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ObjCleanData_rec( Hop_Obj_t * pObj )
+{
+    assert( !Hop_IsComplement(pObj) );
+    assert( !Hop_ObjIsPo(pObj) );
+    if ( Hop_ObjIsAnd(pObj) )
+    {
+        Hop_ObjCleanData_rec( Hop_ObjFanin0(pObj) );
+        Hop_ObjCleanData_rec( Hop_ObjFanin1(pObj) );
+    }
+    pObj->pData = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detects multi-input gate rooted at this node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ObjCollectMulti_rec( Hop_Obj_t * pRoot, Hop_Obj_t * pObj, Vec_Ptr_t * vSuper )
+{
+    if ( pRoot != pObj && (Hop_IsComplement(pObj) || Hop_ObjIsPi(pObj) || Hop_ObjType(pRoot) != Hop_ObjType(pObj)) )
+    {
+        Vec_PtrPushUnique(vSuper, pObj);
+        return;
+    }
+    Hop_ObjCollectMulti_rec( pRoot, Hop_ObjChild0(pObj), vSuper );
+    Hop_ObjCollectMulti_rec( pRoot, Hop_ObjChild1(pObj), vSuper );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detects multi-input gate rooted at this node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ObjCollectMulti( Hop_Obj_t * pRoot, Vec_Ptr_t * vSuper )
+{
+    assert( !Hop_IsComplement(pRoot) );
+    Vec_PtrClear( vSuper );
+    Hop_ObjCollectMulti_rec( pRoot, pRoot, vSuper );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node is the root of MUX or EXOR/NEXOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hop_ObjIsMuxType( Hop_Obj_t * pNode )
+{
+    Hop_Obj_t * pNode0, * pNode1;
+    // check that the node is regular
+    assert( !Hop_IsComplement(pNode) );
+    // if the node is not AND, this is not MUX
+    if ( !Hop_ObjIsAnd(pNode) )
+        return 0;
+    // if the children are not complemented, this is not MUX
+    if ( !Hop_ObjFaninC0(pNode) || !Hop_ObjFaninC1(pNode) )
+        return 0;
+    // get children
+    pNode0 = Hop_ObjFanin0(pNode);
+    pNode1 = Hop_ObjFanin1(pNode);
+    // if the children are not ANDs, this is not MUX
+    if ( !Hop_ObjIsAnd(pNode0) || !Hop_ObjIsAnd(pNode1) )
+        return 0;
+    // otherwise the node is MUX iff it has a pair of equal grandchildren
+    return (Hop_ObjFanin0(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC0(pNode1))) || 
+           (Hop_ObjFanin0(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC1(pNode1))) ||
+           (Hop_ObjFanin1(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC0(pNode1))) ||
+           (Hop_ObjFanin1(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC1(pNode1)));
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recognizes what nodes are inputs of the EXOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Hop_ObjRecognizeExor( Hop_Obj_t * pObj, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 )
+{
+    Hop_Obj_t * p0, * p1;
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) )
+        return 0;
+    if ( Hop_ObjIsExor(pObj) )
+    {
+        *ppFan0 = Hop_ObjChild0(pObj);
+        *ppFan1 = Hop_ObjChild1(pObj);
+        return 1;
+    }
+    assert( Hop_ObjIsAnd(pObj) );
+    p0 = Hop_ObjChild0(pObj);
+    p1 = Hop_ObjChild1(pObj);
+    if ( !Hop_IsComplement(p0) || !Hop_IsComplement(p1) )
+        return 0;
+    p0 = Hop_Regular(p0);
+    p1 = Hop_Regular(p1);
+    if ( !Hop_ObjIsAnd(p0) || !Hop_ObjIsAnd(p1) )
+        return 0;
+    if ( Hop_ObjFanin0(p0) != Hop_ObjFanin0(p1) || Hop_ObjFanin1(p0) != Hop_ObjFanin1(p1) )
+        return 0;
+    if ( Hop_ObjFaninC0(p0) == Hop_ObjFaninC0(p1) || Hop_ObjFaninC1(p0) == Hop_ObjFaninC1(p1) )
+        return 0;
+    *ppFan0 = Hop_ObjChild0(p0);
+    *ppFan1 = Hop_ObjChild1(p0);
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recognizes what nodes are control and data inputs of a MUX.]
+
+  Description [If the node is a MUX, returns the control variable C.
+  Assigns nodes T and E to be the then and else variables of the MUX. 
+  Node C is never complemented. Nodes T and E can be complemented.
+  This function also recognizes EXOR/NEXOR gates as MUXes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Hop_ObjRecognizeMux( Hop_Obj_t * pNode, Hop_Obj_t ** ppNodeT, Hop_Obj_t ** ppNodeE )
+{
+    Hop_Obj_t * pNode0, * pNode1;
+    assert( !Hop_IsComplement(pNode) );
+    assert( Hop_ObjIsMuxType(pNode) );
+    // get children
+    pNode0 = Hop_ObjFanin0(pNode);
+    pNode1 = Hop_ObjFanin1(pNode);
+
+    // find the control variable
+    if ( Hop_ObjFanin1(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC1(pNode1)) )
+    {
+//        if ( Fraig_IsComplement(pNode1->p2) )
+        if ( Hop_ObjFaninC1(pNode0) )
+        { // pNode2->p2 is positive phase of C
+            *ppNodeT = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1);
+            *ppNodeE = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1);
+            return Hop_ObjChild1(pNode1);//pNode2->p2;
+        }
+        else
+        { // pNode1->p2 is positive phase of C
+            *ppNodeT = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1);
+            *ppNodeE = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1);
+            return Hop_ObjChild1(pNode0);//pNode1->p2;
+        }
+    }
+    else if ( Hop_ObjFanin0(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC0(pNode1)) )
+    {
+//        if ( Fraig_IsComplement(pNode1->p1) )
+        if ( Hop_ObjFaninC0(pNode0) )
+        { // pNode2->p1 is positive phase of C
+            *ppNodeT = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2);
+            *ppNodeE = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2);
+            return Hop_ObjChild0(pNode1);//pNode2->p1;
+        }
+        else
+        { // pNode1->p1 is positive phase of C
+            *ppNodeT = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2);
+            *ppNodeE = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2);
+            return Hop_ObjChild0(pNode0);//pNode1->p1;
+        }
+    }
+    else if ( Hop_ObjFanin0(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC1(pNode1)) )
+    {
+//        if ( Fraig_IsComplement(pNode1->p1) )
+        if ( Hop_ObjFaninC0(pNode0) )
+        { // pNode2->p2 is positive phase of C
+            *ppNodeT = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1);
+            *ppNodeE = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2);
+            return Hop_ObjChild1(pNode1);//pNode2->p2;
+        }
+        else
+        { // pNode1->p1 is positive phase of C
+            *ppNodeT = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2);
+            *ppNodeE = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1);
+            return Hop_ObjChild0(pNode0);//pNode1->p1;
+        }
+    }
+    else if ( Hop_ObjFanin1(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC0(pNode1)) )
+    {
+//        if ( Fraig_IsComplement(pNode1->p2) )
+        if ( Hop_ObjFaninC1(pNode0) )
+        { // pNode2->p1 is positive phase of C
+            *ppNodeT = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2);
+            *ppNodeE = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1);
+            return Hop_ObjChild0(pNode1);//pNode2->p1;
+        }
+        else
+        { // pNode1->p2 is positive phase of C
+            *ppNodeT = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1);
+            *ppNodeE = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2);
+            return Hop_ObjChild1(pNode0);//pNode1->p2;
+        }
+    }
+    assert( 0 ); // this is not MUX
+    return NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints Eqn formula for the AIG rooted at this node.]
+
+  Description [The formula is in terms of PIs, which should have
+  their names assigned in pObj->pData fields.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ObjPrintEqn( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level )
+{
+    Vec_Ptr_t * vSuper;
+    Hop_Obj_t * pFanin;
+    int fCompl, i;
+    // store the complemented attribute
+    fCompl = Hop_IsComplement(pObj);
+    pObj = Hop_Regular(pObj);
+    // constant case
+    if ( Hop_ObjIsConst1(pObj) )
+    {
+        fprintf( pFile, "%d", !fCompl );
+        return;
+    }
+    // PI case
+    if ( Hop_ObjIsPi(pObj) )
+    {
+        fprintf( pFile, "%s%s", fCompl? "!" : "", (char*)pObj->pData );
+        return;
+    }
+    // AND case
+    Vec_VecExpand( vLevels, Level );
+    vSuper = Vec_VecEntry(vLevels, Level);
+    Hop_ObjCollectMulti( pObj, vSuper );
+    fprintf( pFile, "%s", (Level==0? "" : "(") );
+    Vec_PtrForEachEntry( Hop_Obj_t *, vSuper, pFanin, i )
+    {
+        Hop_ObjPrintEqn( pFile, Hop_NotCond(pFanin, fCompl), vLevels, Level+1 );
+        if ( i < Vec_PtrSize(vSuper) - 1 )
+            fprintf( pFile, " %s ", fCompl? "+" : "*" );
+    }
+    fprintf( pFile, "%s", (Level==0? "" : ")") );
+    return;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints Verilog formula for the AIG rooted at this node.]
+
+  Description [The formula is in terms of PIs, which should have
+  their names assigned in pObj->pData fields.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ObjPrintVerilog( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level )
+{
+    Vec_Ptr_t * vSuper;
+    Hop_Obj_t * pFanin, * pFanin0, * pFanin1, * pFaninC;
+    int fCompl, i;
+    // store the complemented attribute
+    fCompl = Hop_IsComplement(pObj);
+    pObj = Hop_Regular(pObj);
+    // constant case
+    if ( Hop_ObjIsConst1(pObj) )
+    {
+        fprintf( pFile, "1\'b%d", !fCompl );
+        return;
+    }
+    // PI case
+    if ( Hop_ObjIsPi(pObj) )
+    {
+        fprintf( pFile, "%s%s", fCompl? "~" : "", (char*)pObj->pData );
+        return;
+    }
+    // EXOR case
+    if ( Hop_ObjIsExor(pObj) )
+    {
+        Vec_VecExpand( vLevels, Level );
+        vSuper = Vec_VecEntry( vLevels, Level );
+        Hop_ObjCollectMulti( pObj, vSuper );
+        fprintf( pFile, "%s", (Level==0? "" : "(") );
+        Vec_PtrForEachEntry( Hop_Obj_t *, vSuper, pFanin, i )
+        {
+            Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin, (fCompl && i==0)), vLevels, Level+1 );
+            if ( i < Vec_PtrSize(vSuper) - 1 )
+                fprintf( pFile, " ^ " );
+        }
+        fprintf( pFile, "%s", (Level==0? "" : ")") );
+        return;
+    }
+    // MUX case
+    if ( Hop_ObjIsMuxType(pObj) )
+    {
+        if ( Hop_ObjRecognizeExor( pObj, &pFanin0, &pFanin1 ) )
+        {
+            fprintf( pFile, "%s", (Level==0? "" : "(") );
+            Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin0, fCompl), vLevels, Level+1 );
+            fprintf( pFile, " ^ " );
+            Hop_ObjPrintVerilog( pFile, pFanin1, vLevels, Level+1 );
+            fprintf( pFile, "%s", (Level==0? "" : ")") );
+        }
+        else 
+        {
+            pFaninC = Hop_ObjRecognizeMux( pObj, &pFanin1, &pFanin0 );
+            fprintf( pFile, "%s", (Level==0? "" : "(") );
+            Hop_ObjPrintVerilog( pFile, pFaninC, vLevels, Level+1 );
+            fprintf( pFile, " ? " );
+            Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin1, fCompl), vLevels, Level+1 );
+            fprintf( pFile, " : " );
+            Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin0, fCompl), vLevels, Level+1 );
+            fprintf( pFile, "%s", (Level==0? "" : ")") );
+        }
+        return;
+    }
+    // AND case
+    Vec_VecExpand( vLevels, Level );
+    vSuper = Vec_VecEntry(vLevels, Level);
+    Hop_ObjCollectMulti( pObj, vSuper );
+    fprintf( pFile, "%s", (Level==0? "" : "(") );
+    Vec_PtrForEachEntry( Hop_Obj_t *, vSuper, pFanin, i )
+    {
+        Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin, fCompl), vLevels, Level+1 );
+        if ( i < Vec_PtrSize(vSuper) - 1 )
+            fprintf( pFile, " %s ", fCompl? "|" : "&" );
+    }
+    fprintf( pFile, "%s", (Level==0? "" : ")") );
+    return;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints node in HAIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ObjPrintVerbose( Hop_Obj_t * pObj, int fHaig )
+{
+    assert( !Hop_IsComplement(pObj) );
+    printf( "Node %p : ", pObj );
+    if ( Hop_ObjIsConst1(pObj) )
+        printf( "constant 1" );
+    else if ( Hop_ObjIsPi(pObj) )
+        printf( "PI" );
+    else
+        printf( "AND( %p%s, %p%s )", 
+            Hop_ObjFanin0(pObj), (Hop_ObjFaninC0(pObj)? "\'" : " "), 
+            Hop_ObjFanin1(pObj), (Hop_ObjFaninC1(pObj)? "\'" : " ") );
+    printf( " (refs = %3d)", Hop_ObjRefs(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints node in HAIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ManPrintVerbose( Hop_Man_t * p, int fHaig )
+{
+    Vec_Ptr_t * vNodes;
+    Hop_Obj_t * pObj;
+    int i;
+    printf( "PIs: " );
+    Hop_ManForEachPi( p, pObj, i )
+        printf( " %p", pObj );
+    printf( "\n" );
+    vNodes = Hop_ManDfs( p );
+    Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i )
+        Hop_ObjPrintVerbose( pObj, fHaig ), printf( "\n" );
+    printf( "\n" );
+    Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG into the BLIF file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Hop_ManDumpBlif( Hop_Man_t * p, char * pFileName )
+{
+    FILE * pFile;
+    Vec_Ptr_t * vNodes;
+    Hop_Obj_t * pObj, * pConst1 = NULL;
+    int i, nDigits, Counter = 0;
+    if ( Hop_ManPoNum(p) == 0 )
+    {
+        printf( "Hop_ManDumpBlif(): AIG manager does not have POs.\n" );
+        return;
+    }
+    // collect nodes in the DFS order
+    vNodes = Hop_ManDfs( p );
+    // assign IDs to objects
+    Hop_ManConst1(p)->pData = (void *)(ABC_PTRUINT_T)Counter++;
+    Hop_ManForEachPi( p, pObj, i )
+        pObj->pData = (void *)(ABC_PTRUINT_T)Counter++;
+    Hop_ManForEachPo( p, pObj, i )
+        pObj->pData = (void *)(ABC_PTRUINT_T)Counter++;
+    Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i )
+        pObj->pData = (void *)(ABC_PTRUINT_T)Counter++;
+    nDigits = Hop_Base10Log( Counter );
+    // write the file
+    pFile = fopen( pFileName, "w" );
+    fprintf( pFile, "# BLIF file written by procedure Hop_ManDumpBlif() in ABC\n" );
+    fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" );
+    fprintf( pFile, ".model test\n" );
+    // write PIs
+    fprintf( pFile, ".inputs" );
+    Hop_ManForEachPi( p, pObj, i )
+        fprintf( pFile, " n%0*d", nDigits, (int)(ABC_PTRUINT_T)pObj->pData );
+    fprintf( pFile, "\n" );
+    // write POs
+    fprintf( pFile, ".outputs" );
+    Hop_ManForEachPo( p, pObj, i )
+        fprintf( pFile, " n%0*d", nDigits, (int)(ABC_PTRUINT_T)pObj->pData );
+    fprintf( pFile, "\n" );
+    // write nodes
+    Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i )
+    {
+        fprintf( pFile, ".names n%0*d n%0*d n%0*d\n", 
+            nDigits, (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData, 
+            nDigits, (int)(ABC_PTRUINT_T)Hop_ObjFanin1(pObj)->pData, 
+            nDigits, (int)(ABC_PTRUINT_T)pObj->pData );
+        fprintf( pFile, "%d%d 1\n", !Hop_ObjFaninC0(pObj), !Hop_ObjFaninC1(pObj) );
+    }
+    // write POs
+    Hop_ManForEachPo( p, pObj, i )
+    {
+        fprintf( pFile, ".names n%0*d n%0*d\n", 
+            nDigits, (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData, 
+            nDigits, (int)(ABC_PTRUINT_T)pObj->pData );
+        fprintf( pFile, "%d 1\n", !Hop_ObjFaninC0(pObj) );
+        if ( Hop_ObjIsConst1(Hop_ObjFanin0(pObj)) )
+            pConst1 = Hop_ManConst1(p);
+    }
+    if ( pConst1 )
+        fprintf( pFile, ".names n%0*d\n 1\n", nDigits, (int)(ABC_PTRUINT_T)pConst1->pData );
+    fprintf( pFile, ".end\n\n" );
+    fclose( pFile );
+    Vec_PtrFree( vNodes );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/hop/hop_.c b/abc-build/src/aig/hop/hop_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/hop/hop_.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+  FileName    [hop_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Minimalistic And-Inverter Graph package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: hop_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "hop.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/hop/module.make b/abc-build/src/aig/hop/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/hop/module.make
@@ -0,0 +1,10 @@
+SRC +=	src/aig/hop/hopBalance.c \
+	src/aig/hop/hopCheck.c \
+	src/aig/hop/hopDfs.c \
+	src/aig/hop/hopMan.c \
+	src/aig/hop/hopMem.c \
+	src/aig/hop/hopObj.c \
+	src/aig/hop/hopOper.c \
+	src/aig/hop/hopTable.c \
+	src/aig/hop/hopTruth.c \
+	src/aig/hop/hopUtil.c 
diff --git a/abc-build/src/aig/ioa/ioa.h b/abc-build/src/aig/ioa/ioa.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ioa/ioa.h
@@ -0,0 +1,87 @@
+/**CFile****************************************************************
+
+  FileName    [ioa.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: ioa.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__ioa__ioa_h
+#define ABC__aig__ioa__ioa_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+//#include "bar.h"
+#include "aig/aig/aig.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                             ITERATORS                            ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== ioaReadAig.c ========================================================*/
+extern Aig_Man_t *    Ioa_ReadAigerFromMemory( char * pContents, int nFileSize, int fCheck );
+extern Aig_Man_t *    Ioa_ReadAiger( char * pFileName, int fCheck );
+/*=== ioaWriteAig.c =======================================================*/
+extern Vec_Str_t *    Ioa_WriteAigerIntoMemoryStr( Aig_Man_t * pMan );
+extern char *         Ioa_WriteAigerIntoMemory( Aig_Man_t * pMan, int * pnSize );
+extern void           Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact );
+/*=== ioaUtil.c =======================================================*/
+extern int            Ioa_FileSize( char * pFileName );
+extern char *         Ioa_FileNameGeneric( char * FileName );
+extern char *         Ioa_FileNameGenericAppend( char * pBase, char * pSuffix );
+extern char *         Ioa_TimeStamp();
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/aig/ioa/ioaReadAig.c b/abc-build/src/aig/ioa/ioaReadAig.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ioa/ioaReadAig.c
@@ -0,0 +1,465 @@
+/**CFile****************************************************************
+
+  FileName    [ioaReadAiger.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to read binary AIGER format developed by
+  Armin Biere, Johannes Kepler University (http://fmv.jku.at/)]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - December 16, 2006.]
+
+  Revision    [$Id: ioaReadAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioa.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Extracts one unsigned AIG edge from the input buffer.]
+
+  Description [This procedure is a slightly modified version of Armin Biere's
+  procedure "unsigned decode (FILE * file)". ]
+  
+  SideEffects [Updates the current reading position.]
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Ioa_ReadAigerDecode( char ** ppPos )
+{
+    unsigned x = 0, i = 0;
+    unsigned char ch;
+
+//    while ((ch = getnoneofch (file)) & 0x80)
+    while ((ch = *(*ppPos)++) & 0x80)
+        x |= (ch & 0x7f) << (7 * i++);
+
+    return x | (ch << (7 * i));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Decodes the encoded array of literals.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Ioa_WriteDecodeLiterals( char ** ppPos, int nEntries )
+{
+    Vec_Int_t * vLits;
+    int Lit, LitPrev, Diff, i;
+    vLits = Vec_IntAlloc( nEntries );
+    LitPrev = Ioa_ReadAigerDecode( ppPos );
+    Vec_IntPush( vLits, LitPrev );
+    for ( i = 1; i < nEntries; i++ )
+    {
+//        Diff = Lit - LitPrev;
+//        Diff = (Lit < LitPrev)? -Diff : Diff;
+//        Diff = ((2 * Diff) << 1) | (int)(Lit < LitPrev);
+        Diff = Ioa_ReadAigerDecode( ppPos );
+        Diff = (Diff & 1)? -(Diff >> 1) : Diff >> 1;
+        Lit  = Diff + LitPrev;
+        Vec_IntPush( vLits, Lit );
+        LitPrev = Lit;
+    }
+    return vLits;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the AIG in from the memory buffer.]
+
+  Description [The buffer constains the AIG in AIGER format. The size gives
+  the number of bytes in the buffer. The buffer is allocated by the user 
+  and not deallocated by this procedure.]
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Ioa_ReadAigerFromMemory( char * pContents, int nFileSize, int fCheck )
+{
+    Vec_Int_t * vLits = NULL;
+    Vec_Ptr_t * vNodes, * vDrivers;//, * vTerms;
+    Aig_Obj_t * pObj, * pNode0, * pNode1;
+    Aig_Man_t * pNew;
+    int nTotal, nInputs, nOutputs, nLatches, nAnds, i;//, iTerm, nDigits;
+    int nBad = 0, nConstr = 0, nJust = 0, nFair = 0;
+    char * pDrivers, * pSymbols, * pCur;//, * pType;
+    unsigned uLit0, uLit1, uLit;
+
+    // check if the input file format is correct
+    if ( strncmp(pContents, "aig", 3) != 0 || (pContents[3] != ' ' && pContents[3] != '2') )
+    {
+        fprintf( stdout, "Wrong input file format.\n" );
+        return NULL;
+    }
+
+    // read the parameters (M I L O A + B C J F)
+    pCur = pContents;         while ( *pCur != ' ' ) pCur++; pCur++;
+    // read the number of objects
+    nTotal = atoi( pCur );    while ( *pCur != ' ' ) pCur++; pCur++;
+    // read the number of inputs
+    nInputs = atoi( pCur );   while ( *pCur != ' ' ) pCur++; pCur++;
+    // read the number of latches
+    nLatches = atoi( pCur );  while ( *pCur != ' ' ) pCur++; pCur++;
+    // read the number of outputs
+    nOutputs = atoi( pCur );  while ( *pCur != ' ' ) pCur++; pCur++;
+    // read the number of nodes
+    nAnds = atoi( pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
+    if ( *pCur == ' ' )
+    {
+        assert( nOutputs == 0 );
+        // read the number of properties
+        pCur++;
+        nBad = atoi( pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
+        nOutputs += nBad;
+    }
+    if ( *pCur == ' ' )
+    {
+        // read the number of properties
+        pCur++;
+        nConstr = atoi( pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
+        nOutputs += nConstr;
+    }
+    if ( *pCur == ' ' )
+    {
+        // read the number of properties
+        pCur++;
+        nJust = atoi( pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
+        nOutputs += nJust;
+    }
+    if ( *pCur == ' ' )
+    {
+        // read the number of properties
+        pCur++;
+        nFair = atoi( pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
+        nOutputs += nFair;
+    }
+    if ( *pCur != '\n' )
+    {
+        fprintf( stdout, "The parameter line is in a wrong format.\n" );
+        return NULL;
+    }
+    pCur++;
+
+    // check the parameters
+    if ( nTotal != nInputs + nLatches + nAnds )
+    {
+        fprintf( stdout, "The number of objects does not match.\n" );
+        return NULL;
+    }
+    if ( nJust || nFair )
+    {
+        fprintf( stdout, "Reading AIGER files with liveness properties are currently not supported.\n" );
+        return NULL;
+    }
+
+    if ( nConstr )
+    {
+        if ( nConstr == 1 )
+            fprintf( stdout, "Warning: The last output is interpreted as a constraint.\n" );
+        else
+            fprintf( stdout, "Warning: The last %d outputs are interpreted as constraints.\n", nConstr );
+    }
+
+    // allocate the empty AIG
+    pNew = Aig_ManStart( nAnds );
+    pNew->nConstrs = nConstr;
+
+    // prepare the array of nodes
+    vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds );
+    Vec_PtrPush( vNodes, Aig_ManConst0(pNew) );
+
+    // create the PIs
+    for ( i = 0; i < nInputs + nLatches; i++ )
+    {
+        pObj = Aig_ObjCreateCi(pNew);    
+        Vec_PtrPush( vNodes, pObj );
+    }
+/*
+    // create the POs
+    for ( i = 0; i < nOutputs + nLatches; i++ )
+    {
+        pObj = Aig_ObjCreateCo(pNew);   
+    }
+*/
+    // create the latches
+    pNew->nRegs = nLatches;
+/*
+    nDigits = Ioa_Base10Log( nLatches );
+    for ( i = 0; i < nLatches; i++ )
+    {
+        pObj = Aig_ObjCreateLatch(pNew);
+        Aig_LatchSetInit0( pObj );
+        pNode0 = Aig_ObjCreateBi(pNew);
+        pNode1 = Aig_ObjCreateBo(pNew);
+        Aig_ObjAddFanin( pObj, pNode0 );
+        Aig_ObjAddFanin( pNode1, pObj );
+        Vec_PtrPush( vNodes, pNode1 );
+        // assign names to latch and its input
+//        Aig_ObjAssignName( pObj, Aig_ObjNameDummy("_L", i, nDigits), NULL );
+//        printf( "Creating latch %s with input %d and output %d.\n", Aig_ObjName(pObj), pNode0->Id, pNode1->Id );
+    } 
+*/ 
+
+    // remember the beginning of latch/PO literals
+    pDrivers = pCur;
+    if ( pContents[3] == ' ' ) // standard AIGER
+    {
+        // scroll to the beginning of the binary data
+        for ( i = 0; i < nLatches + nOutputs; )
+            if ( *pCur++ == '\n' )
+                i++;
+    }
+    else // modified AIGER
+    {
+        vLits = Ioa_WriteDecodeLiterals( &pCur, nLatches + nOutputs );
+    }
+
+    // create the AND gates
+//    pProgress = Bar_ProgressStart( stdout, nAnds );
+    for ( i = 0; i < nAnds; i++ )
+    {
+//        Bar_ProgressUpdate( pProgress, i, NULL );
+        uLit = ((i + 1 + nInputs + nLatches) << 1);
+        uLit1 = uLit  - Ioa_ReadAigerDecode( &pCur );
+        uLit0 = uLit1 - Ioa_ReadAigerDecode( &pCur );
+//        assert( uLit1 > uLit0 );
+        pNode0 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), uLit0 & 1 );
+        pNode1 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit1 >> 1), uLit1 & 1 );
+        assert( Vec_PtrSize(vNodes) == i + 1 + nInputs + nLatches );
+        Vec_PtrPush( vNodes, Aig_And(pNew, pNode0, pNode1) );
+    }
+//    Bar_ProgressStop( pProgress );
+
+    // remember the place where symbols begin
+    pSymbols = pCur;
+
+    // read the latch driver literals
+    vDrivers = Vec_PtrAlloc( nLatches + nOutputs );
+    if ( pContents[3] == ' ' ) // standard AIGER
+    {
+        pCur = pDrivers;
+        for ( i = 0; i < nLatches; i++ )
+        {
+            uLit0 = atoi( pCur );  while ( *pCur++ != '\n' );
+            pNode0 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) );
+            Vec_PtrPush( vDrivers, pNode0 );
+        }
+        // read the PO driver literals
+        for ( i = 0; i < nOutputs; i++ )
+        {
+            uLit0 = atoi( pCur );  while ( *pCur++ != '\n' );
+            pNode0 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) );
+            Vec_PtrPush( vDrivers, pNode0 );
+        }
+
+    }
+    else
+    {
+        // read the latch driver literals
+        for ( i = 0; i < nLatches; i++ )
+        {
+            uLit0 = Vec_IntEntry( vLits, i );
+            pNode0 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) );
+            Vec_PtrPush( vDrivers, pNode0 );
+        }
+        // read the PO driver literals
+        for ( i = 0; i < nOutputs; i++ )
+        {
+            uLit0 = Vec_IntEntry( vLits, i+nLatches );
+            pNode0 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) );
+            Vec_PtrPush( vDrivers, pNode0 );
+        }
+        Vec_IntFree( vLits );
+    }
+
+    // create the POs
+    for ( i = 0; i < nOutputs; i++ )
+        Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vDrivers, nLatches + i) );
+    for ( i = 0; i < nLatches; i++ )
+        Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vDrivers, i) );
+    Vec_PtrFree( vDrivers );
+
+/*
+    // read the names if present
+    pCur = pSymbols;
+    if ( *pCur != 'c' )
+    {
+        int Counter = 0;
+        while ( pCur < pContents + nFileSize && *pCur != 'c' )
+        {
+            // get the terminal type
+            pType = pCur;
+            if ( *pCur == 'i' )
+                vTerms = pNew->vPis;
+            else if ( *pCur == 'l' )
+                vTerms = pNew->vBoxes;
+            else if ( *pCur == 'o' )
+                vTerms = pNew->vPos;
+            else
+            {
+                fprintf( stdout, "Wrong terminal type.\n" );
+                return NULL;
+            }
+            // get the terminal number
+            iTerm = atoi( ++pCur );  while ( *pCur++ != ' ' );
+            // get the node
+            if ( iTerm >= Vec_PtrSize(vTerms) )
+            {
+                fprintf( stdout, "The number of terminal is out of bound.\n" );
+                return NULL;
+            }
+            pObj = Vec_PtrEntry( vTerms, iTerm );
+            if ( *pType == 'l' )
+                pObj = Aig_ObjFanout0(pObj);
+            // assign the name
+            pName = pCur;          while ( *pCur++ != '\n' );
+            // assign this name 
+            *(pCur-1) = 0;
+            Aig_ObjAssignName( pObj, pName, NULL );
+            if ( *pType == 'l' )
+            {
+                Aig_ObjAssignName( Aig_ObjFanin0(pObj), Aig_ObjName(pObj), "L" );
+                Aig_ObjAssignName( Aig_ObjFanin0(Aig_ObjFanin0(pObj)), Aig_ObjName(pObj), "_in" );
+            }
+            // mark the node as named
+            pObj->pCopy = (Aig_Obj_t *)Aig_ObjName(pObj);
+        } 
+
+        // assign the remaining names
+        Aig_ManForEachCi( pNew, pObj, i )
+        {
+            if ( pObj->pCopy ) continue;
+            Aig_ObjAssignName( pObj, Aig_ObjName(pObj), NULL );
+            Counter++;
+        }
+        Aig_ManForEachLatchOutput( pNew, pObj, i )
+        {
+            if ( pObj->pCopy ) continue;
+            Aig_ObjAssignName( pObj, Aig_ObjName(pObj), NULL );
+            Aig_ObjAssignName( Aig_ObjFanin0(pObj), Aig_ObjName(pObj), "L" );
+            Aig_ObjAssignName( Aig_ObjFanin0(Aig_ObjFanin0(pObj)), Aig_ObjName(pObj), "_in" );
+            Counter++;
+        }
+        Aig_ManForEachCo( pNew, pObj, i )
+        {
+            if ( pObj->pCopy ) continue;
+            Aig_ObjAssignName( pObj, Aig_ObjName(pObj), NULL );
+            Counter++;
+        }
+        if ( Counter )
+            printf( "Ioa_ReadAiger(): Added %d default names for nameless I/O/register objects.\n", Counter );
+    }
+    else
+    {
+//        printf( "Ioa_ReadAiger(): I/O/register names are not given. Generating short names.\n" );
+        Aig_ManShortNames( pNew );
+    }
+*/
+    pCur = pSymbols;
+    if ( pCur + 1 < pContents + nFileSize && *pCur == 'c' )
+    {
+        pCur++;
+        if ( *pCur == 'n' )
+        {
+            pCur++;
+            // read model name
+            ABC_FREE( pNew->pName );
+            pNew->pName = Abc_UtilStrsav( pCur );
+        }
+    }
+
+    // skipping the comments
+    Vec_PtrFree( vNodes );
+
+    // remove the extra nodes
+    Aig_ManCleanup( pNew );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(pNew) );
+
+    // update polarity of the additional outputs
+    if ( nBad || nConstr || nJust || nFair )
+        Aig_ManInvertConstraints( pNew );
+
+    // check the result
+    if ( fCheck && !Aig_ManCheck( pNew ) )
+    {
+        printf( "Ioa_ReadAiger: The network check has failed.\n" );
+        Aig_ManStop( pNew );
+        return NULL;
+    }
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the AIG in the binary AIGER format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Ioa_ReadAiger( char * pFileName, int fCheck )
+{
+    FILE * pFile;
+    Aig_Man_t * pNew;
+    char * pName, * pContents;
+    int nFileSize, RetValue;
+
+    // read the file into the buffer
+    nFileSize = Ioa_FileSize( pFileName );
+    pFile = fopen( pFileName, "rb" );
+    pContents = ABC_ALLOC( char, nFileSize );
+    RetValue = fread( pContents, nFileSize, 1, pFile );
+    fclose( pFile );
+
+    pNew = Ioa_ReadAigerFromMemory( pContents, nFileSize, fCheck );
+    ABC_FREE( pContents );
+    if ( pNew )
+    {
+        pName = Ioa_FileNameGeneric( pFileName );
+        ABC_FREE( pNew->pName );
+        pNew->pName = Abc_UtilStrsav( pName );
+        pNew->pSpec = Abc_UtilStrsav( pFileName );
+        ABC_FREE( pName );
+    }
+    return pNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ioa/ioaUtil.c b/abc-build/src/aig/ioa/ioaUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ioa/ioaUtil.c
@@ -0,0 +1,146 @@
+/**CFile****************************************************************
+
+  FileName    [ioaUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to read binary AIGER format developed by
+  Armin Biere, Johannes Kepler University (http://fmv.jku.at/)]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - December 16, 2006.]
+
+  Revision    [$Id: ioaUtil.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioa.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the file size.]
+
+  Description [The file should be closed.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ioa_FileSize( char * pFileName )
+{
+    FILE * pFile;
+    int nFileSize;
+    pFile = fopen( pFileName, "r" );
+    if ( pFile == NULL )
+    {
+        printf( "Ioa_FileSize(): The file is unavailable (absent or open).\n" );
+        return 0;
+    }
+    fseek( pFile, 0, SEEK_END );  
+    nFileSize = ftell( pFile ); 
+    fclose( pFile );
+    return nFileSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Ioa_FileNameGeneric( char * FileName )
+{
+    char * pDot, * pRes;
+    pRes = Abc_UtilStrsav( FileName );
+    if ( (pDot = strrchr( pRes, '.' )) )
+        *pDot = 0;
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the composite name of the file.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Ioa_FileNameGenericAppend( char * pBase, char * pSuffix )
+{
+    static char Buffer[1000];
+    char * pDot;
+    if ( pBase == NULL )
+    {
+        strcpy( Buffer, pSuffix );
+        return Buffer;
+    }
+    strcpy( Buffer, pBase );
+    if ( (pDot = strrchr( Buffer, '.' )) )
+        *pDot = 0;
+    strcat( Buffer, pSuffix );
+    // find the last occurrance of slash
+    for ( pDot = Buffer + strlen(Buffer) - 1; pDot >= Buffer; pDot-- )    
+        if (!((*pDot >= '0' && *pDot <= '9') ||
+              (*pDot >= 'a' && *pDot <= 'z') ||
+              (*pDot >= 'A' && *pDot <= 'Z') || 
+               *pDot == '_' || *pDot == '.') )
+               break;
+    return pDot + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the time stamp.]
+
+  Description [The file should be closed.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Ioa_TimeStamp()
+{
+    static char Buffer[100];
+	char * TimeStamp;
+	time_t ltime;
+    // get the current time
+	time( &ltime );
+	TimeStamp = asctime( localtime( &ltime ) );
+	TimeStamp[ strlen(TimeStamp) - 1 ] = 0;
+    strcpy( Buffer, TimeStamp );
+    return Buffer;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ioa/ioaWriteAig.c b/abc-build/src/aig/ioa/ioaWriteAig.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ioa/ioaWriteAig.c
@@ -0,0 +1,599 @@
+/**CFile****************************************************************
+
+  FileName    [ioaWriteAiger.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to write binary AIGER format developed by
+  Armin Biere, Johannes Kepler University (http://fmv.jku.at/)]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - December 16, 2006.]
+
+  Revision    [$Id: ioaWriteAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioa.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+/*
+    The following is taken from the AIGER format description, 
+    which can be found at http://fmv.jku.at/aiger
+*/
+
+
+/*
+         The AIGER And-Inverter Graph (AIG) Format Version 20061129
+         ----------------------------------------------------------
+              Armin Biere, Johannes Kepler University, 2006
+
+  This report describes the AIG file format as used by the AIGER library.
+  The purpose of this report is not only to motivate and document the
+  format, but also to allow independent implementations of writers and
+  readers by giving precise and unambiguous definitions.
+
+  ...
+
+Introduction
+
+  The name AIGER contains as one part the acronym AIG of And-Inverter
+  Graphs and also if pronounced in German sounds like the name of the
+  'Eiger', a mountain in the Swiss alps.  This choice should emphasize the
+  origin of this format. It was first openly discussed at the Alpine
+  Verification Meeting 2006 in Ascona as a way to provide a simple, compact
+  file format for a model checking competition affiliated to CAV 2007.
+
+  ...
+
+Binary Format Definition
+
+  The binary format is semantically a subset of the ASCII format with a
+  slightly different syntax.  The binary format may need to reencode
+  literals, but translating a file in binary format into ASCII format and
+  then back in to binary format will result in the same file.
+
+  The main differences of the binary format to the ASCII format are as
+  follows.  After the header the list of input literals and all the
+  current state literals of a latch can be omitted.  Furthermore the
+  definitions of the AND gates are binary encoded.  However, the symbol
+  table and the comment section are as in the ASCII format.
+
+  The header of an AIGER file in binary format has 'aig' as format
+  identifier, but otherwise is identical to the ASCII header.  The standard
+  file extension for the binary format is therefore '.aig'. 
+  
+  A header for the binary format is still in ASCII encoding:
+
+    aig M I L O A
+
+  Constants, variables and literals are handled in the same way as in the
+  ASCII format.  The first simplifying restriction is on the variable
+  indices of inputs and latches.  The variable indices of inputs come first,
+  followed by the pseudo-primary inputs of the latches and then the variable
+  indices of all LHS of AND gates:
+
+    input variable indices        1,          2,  ... ,  I
+    latch variable indices      I+1,        I+2,  ... ,  (I+L)
+    AND variable indices      I+L+1,      I+L+2,  ... ,  (I+L+A) == M
+
+  The corresponding unsigned literals are
+
+    input literals                2,          4,  ... ,  2*I
+    latch literals            2*I+2,      2*I+4,  ... ,  2*(I+L)
+    AND literals          2*(I+L)+2,  2*(I+L)+4,  ... ,  2*(I+L+A) == 2*M
+                    
+  All literals have to be defined, and therefore 'M = I + L + A'.  With this
+  restriction it becomes possible that the inputs and the current state
+  literals of the latches do not have to be listed explicitly.  Therefore,
+  after the header only the list of 'L' next state literals follows, one per
+  latch on a single line, and then the 'O' outputs, again one per line.
+
+  In the binary format we assume that the AND gates are ordered and respect
+  the child parent relation.  AND gates with smaller literals on the LHS
+  come first.  Therefore we can assume that the literals on the right-hand
+  side of a definition of an AND gate are smaller than the LHS literal.
+  Furthermore we can sort the literals on the RHS, such that the larger
+  literal comes first.  A definition thus consists of three literals
+    
+      lhs rhs0 rhs1
+
+  with 'lhs' even and 'lhs > rhs0 >= rhs1'.  Also the variable indices are
+  pairwise different to avoid combinational self loops.  Since the LHS
+  indices of the definitions are all consecutive (as even integers),
+  the binary format does not have to keep 'lhs'.  In addition, we can use
+  the order restriction and only write the differences 'delta0' and 'delta1'
+  instead of 'rhs0' and 'rhs1', with
+
+      delta0 = lhs - rhs0,  delta1 = rhs0 - rhs1
+  
+  The differences will all be strictly positive, and in practice often very
+  small.  We can take advantage of this fact by the simple little-endian
+  encoding of unsigned integers of the next section.  After the binary delta
+  encoding of the RHSs of all AND gates, the optional symbol table and
+  optional comment section start in the same format as in the ASCII case.
+
+  ...
+
+*/
+
+static int      Ioa_ObjMakeLit( int Var, int fCompl )                 { return (Var << 1) | fCompl;  }
+static int      Ioa_ObjAigerNum( Aig_Obj_t * pObj )                   { return pObj->iData;          }
+static void     Ioa_ObjSetAigerNum( Aig_Obj_t * pObj, unsigned Num )  { pObj->iData = Num;           }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one unsigned AIG edge to the output buffer.]
+
+  Description [This procedure is a slightly modified version of Armin Biere's
+  procedure "void encode (FILE * file, unsigned x)" ]
+  
+  SideEffects [Returns the current writing position.]
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ioa_WriteAigerEncode( unsigned char * pBuffer, int Pos, unsigned x )
+{
+    unsigned char ch;
+    while (x & ~0x7f)
+    {
+        ch = (x & 0x7f) | 0x80;
+//        putc (ch, file);
+        pBuffer[Pos++] = ch;
+        x >>= 7;
+    }
+    ch = x;
+//    putc (ch, file);
+    pBuffer[Pos++] = ch;
+    return Pos;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one unsigned AIG edge to the output buffer.]
+
+  Description [This procedure is a slightly modified version of Armin Biere's
+  procedure "void encode (FILE * file, unsigned x)" ]
+  
+  SideEffects [Returns the current writing position.]
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ioa_WriteAigerEncodeStr( Vec_Str_t * vStr, unsigned x )
+{
+    unsigned char ch;
+    while (x & ~0x7f)
+    {
+        ch = (x & 0x7f) | 0x80;
+//        putc (ch, file);
+//        pBuffer[Pos++] = ch;
+        Vec_StrPush( vStr, ch );
+        x >>= 7;
+    }
+    ch = x;
+//    putc (ch, file);
+//    pBuffer[Pos++] = ch;
+    Vec_StrPush( vStr, ch );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the array of literals to be written.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Ioa_WriteAigerLiterals( Aig_Man_t * pMan )
+{
+    Vec_Int_t * vLits;
+    Aig_Obj_t * pObj, * pDriver;
+    int i;
+    vLits = Vec_IntAlloc( Aig_ManCoNum(pMan) );
+    Aig_ManForEachLiSeq( pMan, pObj, i )
+    {
+        pDriver = Aig_ObjFanin0(pObj);
+        Vec_IntPush( vLits, Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) );
+    }
+    Aig_ManForEachPoSeq( pMan, pObj, i )
+    {
+        pDriver = Aig_ObjFanin0(pObj);
+        Vec_IntPush( vLits, Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) );
+    }
+    return vLits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the binary encoded array of literals.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Ioa_WriteEncodeLiterals( Vec_Int_t * vLits )
+{
+    Vec_Str_t * vBinary;
+    int Pos = 0, Lit, LitPrev, Diff, i;
+    vBinary = Vec_StrAlloc( 2 * Vec_IntSize(vLits) );
+    LitPrev = Vec_IntEntry( vLits, 0 );
+    Pos = Ioa_WriteAigerEncode( (unsigned char *)Vec_StrArray(vBinary), Pos, LitPrev ); 
+    Vec_IntForEachEntryStart( vLits, Lit, i, 1 )
+    {
+        Diff = Lit - LitPrev;
+        Diff = (Lit < LitPrev)? -Diff : Diff;
+        Diff = (Diff << 1) | (int)(Lit < LitPrev);
+        Pos = Ioa_WriteAigerEncode( (unsigned char *)Vec_StrArray(vBinary), Pos, Diff );
+        LitPrev = Lit;
+        if ( Pos + 10 > vBinary->nCap )
+            Vec_StrGrow( vBinary, vBinary->nCap+1 );
+    }
+    vBinary->nSize = Pos;
+/*
+    // verify
+    {
+        extern Vec_Int_t * Ioa_WriteDecodeLiterals( char ** ppPos, int nEntries );
+        char * pPos = Vec_StrArray( vBinary );
+        Vec_Int_t * vTemp = Ioa_WriteDecodeLiterals( &pPos, Vec_IntSize(vLits) );
+        for ( i = 0; i < Vec_IntSize(vLits); i++ )
+        {
+            int Entry1 = Vec_IntEntry(vLits,i);
+            int Entry2 = Vec_IntEntry(vTemp,i);
+            assert( Entry1 == Entry2 );
+        }
+        Vec_IntFree( vTemp );
+    }
+*/
+    return vBinary;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG in into the memory buffer.]
+
+  Description [The resulting buffer constains the AIG in AIGER format. 
+  The returned size (pnSize) gives the number of bytes in the buffer. 
+  The resulting buffer should be deallocated by the user.]
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Ioa_WriteAigerIntoMemoryStr( Aig_Man_t * pMan )
+{
+    Vec_Str_t * vBuffer;
+    Aig_Obj_t * pObj, * pDriver;
+    int nNodes, i, uLit, uLit0, uLit1; 
+    // set the node numbers to be used in the output file
+    nNodes = 0;
+    Ioa_ObjSetAigerNum( Aig_ManConst1(pMan), nNodes++ );
+    Aig_ManForEachCi( pMan, pObj, i )
+        Ioa_ObjSetAigerNum( pObj, nNodes++ );
+    Aig_ManForEachNode( pMan, pObj, i )
+        Ioa_ObjSetAigerNum( pObj, nNodes++ );
+
+    // write the header "M I L O A" where M = I + L + A
+/*
+    fprintf( pFile, "aig%s %u %u %u %u %u\n", 
+        fCompact? "2" : "",
+        Aig_ManCiNum(pMan) + Aig_ManNodeNum(pMan), 
+        Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan),
+        Aig_ManRegNum(pMan),
+        Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan),
+        Aig_ManNodeNum(pMan) );
+*/
+    vBuffer = Vec_StrAlloc( 3*Aig_ManObjNum(pMan) );
+    Vec_StrPrintStr( vBuffer, "aig " );
+    Vec_StrPrintNum( vBuffer, Aig_ManCiNum(pMan) + Aig_ManNodeNum(pMan) );
+    Vec_StrPrintStr( vBuffer, " " );
+    Vec_StrPrintNum( vBuffer, Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan) );
+    Vec_StrPrintStr( vBuffer, " " );
+    Vec_StrPrintNum( vBuffer, Aig_ManRegNum(pMan) );
+    Vec_StrPrintStr( vBuffer, " " );
+    Vec_StrPrintNum( vBuffer, Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) );
+    Vec_StrPrintStr( vBuffer, " " );
+    Vec_StrPrintNum( vBuffer, Aig_ManNodeNum(pMan) );
+    Vec_StrPrintStr( vBuffer, "\n" );
+
+    // write latch drivers
+    Aig_ManForEachLiSeq( pMan, pObj, i )
+    {
+        pDriver = Aig_ObjFanin0(pObj);
+        uLit    = Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) );
+//        fprintf( pFile, "%u\n", uLit );
+        Vec_StrPrintNum( vBuffer, uLit );
+        Vec_StrPrintStr( vBuffer, "\n" );
+    }
+
+    // write PO drivers
+    Aig_ManForEachPoSeq( pMan, pObj, i )
+    {
+        pDriver = Aig_ObjFanin0(pObj);
+        uLit    = Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) );
+//        fprintf( pFile, "%u\n", uLit );
+        Vec_StrPrintNum( vBuffer, uLit );
+        Vec_StrPrintStr( vBuffer, "\n" );
+    }
+    // write the nodes into the buffer
+    Aig_ManForEachNode( pMan, pObj, i )
+    {
+        uLit  = Ioa_ObjMakeLit( Ioa_ObjAigerNum(pObj), 0 );
+        uLit0 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) );
+        uLit1 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) );
+        assert( uLit0 != uLit1 );
+        if ( uLit0 > uLit1 )
+        {
+            int Temp = uLit0;
+            uLit0 = uLit1;
+            uLit1 = Temp;
+        }
+//        Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit  - uLit1 );
+//        Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 );
+        Ioa_WriteAigerEncodeStr( vBuffer, uLit  - uLit1 );
+        Ioa_WriteAigerEncodeStr( vBuffer, uLit1 - uLit0 );
+    }
+    Vec_StrPrintStr( vBuffer, "c" );
+    return vBuffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG in into the memory buffer.]
+
+  Description [The resulting buffer constains the AIG in AIGER format. 
+  The returned size (pnSize) gives the number of bytes in the buffer. 
+  The resulting buffer should be deallocated by the user.]
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Ioa_WriteAigerIntoMemory( Aig_Man_t * pMan, int * pnSize )
+{
+    char * pBuffer;
+    Vec_Str_t * vBuffer;
+    vBuffer = Ioa_WriteAigerIntoMemoryStr( pMan );
+    if ( pMan->pName )
+    {
+        Vec_StrPrintStr( vBuffer, "n" );
+        Vec_StrPrintStr( vBuffer, pMan->pName );
+        Vec_StrPush( vBuffer, 0 );
+    }
+    // prepare the return values
+    *pnSize = Vec_StrSize( vBuffer );
+    pBuffer = Vec_StrReleaseArray( vBuffer );
+    Vec_StrFree( vBuffer );
+    return pBuffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure is used to test the above procedure.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ioa_WriteAigerBufferTest( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact )
+{
+    FILE * pFile;
+    char * pBuffer;
+    int nSize;
+    if ( Aig_ManCoNum(pMan) == 0 )
+    {
+        printf( "AIG cannot be written because it has no POs.\n" );
+        return;
+    }
+    // start the output stream
+    pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Ioa_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName );
+        return;
+    }
+    // write the buffer
+    pBuffer = Ioa_WriteAigerIntoMemory( pMan, &nSize );
+    fwrite( pBuffer, 1, nSize, pFile );
+    ABC_FREE( pBuffer );
+    // write the comment
+//    fprintf( pFile, "c" );
+//    if ( pMan->pName )
+//        fprintf( pFile, "n%s%c", pMan->pName, '\0' );
+    fprintf( pFile, "\nThis file was produced by the IOA package in ABC on %s\n", Ioa_TimeStamp() );
+    fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" );
+	fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG in the binary AIGER format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact )
+{
+//    Bar_Progress_t * pProgress;
+    FILE * pFile;
+    Aig_Obj_t * pObj, * pDriver;
+    int i, nNodes, nBufferSize, Pos;
+    unsigned char * pBuffer;
+    unsigned uLit0, uLit1, uLit;
+
+    if ( Aig_ManCoNum(pMan) == 0 )
+    {
+        printf( "AIG cannot be written because it has no POs.\n" );
+        return;
+    }
+
+//    assert( Aig_ManIsStrash(pMan) );
+    // start the output stream
+    pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Ioa_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName );
+        return;
+    }
+/*
+    Aig_ManForEachLatch( pMan, pObj, i )
+        if ( !Aig_LatchIsInit0(pObj) )
+        {
+            fprintf( stdout, "Ioa_WriteAiger(): Cannot write AIGER format with non-0 latch init values. Run \"zero\".\n" );
+            return;
+        }
+*/
+    // set the node numbers to be used in the output file
+    nNodes = 0;
+    Ioa_ObjSetAigerNum( Aig_ManConst1(pMan), nNodes++ );
+    Aig_ManForEachCi( pMan, pObj, i )
+        Ioa_ObjSetAigerNum( pObj, nNodes++ );
+    Aig_ManForEachNode( pMan, pObj, i )
+        Ioa_ObjSetAigerNum( pObj, nNodes++ );
+
+    // write the header "M I L O A" where M = I + L + A
+    fprintf( pFile, "aig%s %u %u %u %u %u", 
+        fCompact? "2" : "",
+        Aig_ManCiNum(pMan) + Aig_ManNodeNum(pMan), 
+        Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan),
+        Aig_ManRegNum(pMan),
+        Aig_ManConstrNum(pMan) ? 0 : Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan),
+        Aig_ManNodeNum(pMan) );
+    // write the extended header "B C J F"
+    if ( Aig_ManConstrNum(pMan) )
+        fprintf( pFile, " %u %u", Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) - Aig_ManConstrNum(pMan), Aig_ManConstrNum(pMan) );
+    fprintf( pFile, "\n" ); 
+
+    // if the driver node is a constant, we need to complement the literal below
+    // because, in the AIGER format, literal 0/1 is represented as number 0/1
+    // while, in ABC, constant 1 node has number 0 and so literal 0/1 will be 1/0
+
+    Aig_ManInvertConstraints( pMan );
+    if ( !fCompact ) 
+    {
+        // write latch drivers
+        Aig_ManForEachLiSeq( pMan, pObj, i )
+        {
+            pDriver = Aig_ObjFanin0(pObj);
+            fprintf( pFile, "%u\n", Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) );
+        }
+
+        // write PO drivers
+        Aig_ManForEachPoSeq( pMan, pObj, i )
+        {
+            pDriver = Aig_ObjFanin0(pObj);
+            fprintf( pFile, "%u\n", Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) );
+        }
+    }
+    else
+    {
+        Vec_Int_t * vLits = Ioa_WriteAigerLiterals( pMan );
+        Vec_Str_t * vBinary = Ioa_WriteEncodeLiterals( vLits );
+        fwrite( Vec_StrArray(vBinary), 1, Vec_StrSize(vBinary), pFile );
+        Vec_StrFree( vBinary );
+        Vec_IntFree( vLits );
+    }
+    Aig_ManInvertConstraints( pMan );
+
+    // write the nodes into the buffer
+    Pos = 0;
+    nBufferSize = 6 * Aig_ManNodeNum(pMan) + 100; // skeptically assuming 3 chars per one AIG edge
+    pBuffer = ABC_ALLOC( unsigned char, nBufferSize );
+//    pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(pMan) );
+    Aig_ManForEachNode( pMan, pObj, i )
+    {
+//        Bar_ProgressUpdate( pProgress, i, NULL );
+        uLit  = Ioa_ObjMakeLit( Ioa_ObjAigerNum(pObj), 0 );
+        uLit0 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) );
+        uLit1 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) );
+        assert( uLit0 != uLit1 );
+        if ( uLit0 > uLit1 )
+        {
+            int Temp = uLit0;
+            uLit0 = uLit1;
+            uLit1 = Temp;
+        }
+        Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit  - uLit1 );
+        Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 );
+        if ( Pos > nBufferSize - 10 )
+        {
+            printf( "Ioa_WriteAiger(): AIGER generation has failed because the allocated buffer is too small.\n" );
+	        fclose( pFile );
+            return;
+        }
+    }
+    assert( Pos < nBufferSize );
+//    Bar_ProgressStop( pProgress );
+
+    // write the buffer
+    fwrite( pBuffer, 1, Pos, pFile );
+    ABC_FREE( pBuffer );
+/*
+    // write the symbol table
+    if ( fWriteSymbols )
+    {
+        int bads;
+        // write PIs
+        Aig_ManForEachPiSeq( pMan, pObj, i )
+            fprintf( pFile, "i%d %s\n", i, Aig_ObjName(pObj) );
+        // write latches
+        Aig_ManForEachLoSeq( pMan, pObj, i )
+            fprintf( pFile, "l%d %s\n", i, Aig_ObjName(Aig_ObjFanout0(pObj)) );
+        // write POs
+        bads = Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) - Aig_ManConstrNum(pMan);
+        Aig_ManForEachPoSeq( pMan, pObj, i )
+            if ( !Aig_ManConstrNum(pMan) )
+                fprintf( pFile, "o%d %s\n", i, Aig_ObjName(pObj) );
+            else if ( i < bads )
+                fprintf( pFile, "b%d %s\n", i, Aig_ObjName(pObj) );
+            else
+                fprintf( pFile, "c%d %s\n", i - bads, Aig_ObjName(pObj) );
+    }
+*/
+    // write the comment
+    fprintf( pFile, "c" );
+    if ( pMan->pName )
+        fprintf( pFile, "n%s%c", pMan->pName, '\0' );
+    fprintf( pFile, "\nThis file was produced by the IOA package in ABC on %s\n", Ioa_TimeStamp() );
+    fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" );
+	fclose( pFile );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ioa/module.make b/abc-build/src/aig/ioa/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ioa/module.make
@@ -0,0 +1,3 @@
+SRC +=	src/aig/ioa/ioaReadAig.c \
+	src/aig/ioa/ioaWriteAig.c \
+	src/aig/ioa/ioaUtil.c  	
diff --git a/abc-build/src/aig/ivy/attr.h b/abc-build/src/aig/ivy/attr.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/attr.h
@@ -0,0 +1,418 @@
+/**CFile****************************************************************
+
+  FileName    [attr.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network attributes.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: attr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__ivy__attr_h
+#define ABC__aig__ivy__attr_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "misc/extra/extra.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Attr_ManStruct_t_     Attr_Man_t;
+struct Attr_ManStruct_t_
+{
+    // attribute info
+    int                        nAttrSize;     // the size of each attribute in bytes
+    Extra_MmFixed_t *          pManMem;       // memory manager for attributes
+    int                        nAttrs;        // the number of attributes allocated
+    void **                    pAttrs;        // the array of attributes
+    int                        fUseInt;       // uses integer attributes
+    // attribute specific info
+    void *                     pManAttr;      // the manager for this attribute
+    void (*pFuncFreeMan) (void *);            // the procedure to call to free attribute-specific manager
+    void (*pFuncFreeObj) (void *, void *);    // the procedure to call to free attribute-specific data
+};
+
+// at any time, an attribute of the given ID can be
+// - not available (p->nAttrs < Id)
+// - available but not allocated (p->nAttrs >= Id && p->pAttrs[Id] == NULL)
+// - available and allocated (p->nAttrs >= Id && p->pAttrs[Id] != NULL)
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the attribute manager.]
+
+  Description [The manager is simple if it does not need memory manager.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Attr_Man_t * Attr_ManAlloc( int nAttrSize, int fManMem )
+{
+    Attr_Man_t * p;
+    p = ALLOC( Attr_Man_t, 1 );
+    memset( p, 0, sizeof(Attr_Man_t) );
+    p->nAttrSize = nAttrSize;
+    if ( fManMem )
+        p->pManMem = Extra_MmFixedStart( nAttrSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Start the attribute manager for integers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Attr_Man_t * Attr_ManStartInt( int nAttrs )
+{
+    Attr_Man_t * p;
+    p = Attr_ManAlloc( sizeof(int), 0 );
+    p->nAttrs  = nAttrs;
+    p->pAttrs  = (void **)ALLOC( int, nAttrs );
+    memset( (int *)p->pAttrs, 0, sizeof(int) * nAttrs );
+    p->fUseInt = 1;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Start the attribute manager for pointers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Attr_Man_t * Attr_ManStartPtr( int nAttrs )
+{
+    Attr_Man_t * p;
+    p = Attr_ManAlloc( sizeof(void *), 0 );
+    p->nAttrs  = nAttrs;
+    p->pAttrs  = ALLOC( void *, nAttrs );
+    memset( p->pAttrs, 0, sizeof(void *) * nAttrs );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Start the attribute manager for the fixed entry size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Attr_Man_t * Attr_ManStartPtrMem( int nAttrs, int nAttrSize )
+{
+    Attr_Man_t * p;
+    int i;
+    p = Attr_ManAlloc( nAttrSize, 1 );
+    p->nAttrs  = nAttrs;
+    p->pAttrs  = ALLOC( void *, nAttrs );
+    for ( i = 0; i < p->nAttrs; i++ )
+    {
+        p->pAttrs[i] = Extra_MmFixedEntryFetch( p->pManMem );
+        memset( p->pAttrs[i], 0, nAttrSize );
+    }
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop the attribute manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Attr_ManStop( Attr_Man_t * p )
+{
+    // free the attributes of objects
+    if ( p->pFuncFreeObj )
+    {
+        int i;
+        if ( p->fUseInt )
+        {
+            for ( i = 0; i < p->nAttrs; i++ )
+                if ( ((int *)p->pAttrs)[i] )
+                    p->pFuncFreeObj( p->pManAttr, (void *)((int *)p->pAttrs)[i] );
+        }
+        else
+        {
+            for ( i = 0; i < p->nAttrs; i++ )
+                if ( p->pAttrs[i] )
+                    p->pFuncFreeObj( p->pManAttr, p->pAttrs[i] );
+        }
+    }
+    // free the attribute manager
+    if ( p->pManAttr && p->pFuncFreeMan )
+        p->pFuncFreeMan( p->pManAttr );
+    // free the memory manager
+    if ( p->pManMem )  
+        Extra_MmFixedStop( p->pManMem);
+    // free the attribute manager
+    FREE( p->pAttrs );
+    free( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the attribute of the given object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Attr_ManReadAttrInt( Attr_Man_t * p, int Id )
+{
+    assert( p->fUseInt );
+    if ( Id >= p->nAttrs )
+        return 0;
+    return ((int *)p->pAttrs)[Id]; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the attribute of the given object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void * Attr_ManReadAttrPtr( Attr_Man_t * p, int Id )
+{
+    assert( !p->fUseInt );
+    if ( Id >= p->nAttrs )
+        return NULL;
+    return p->pAttrs[Id]; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the attribute of the given object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Attr_ManWriteAttrInt( Attr_Man_t * p, int Id, int Attr )
+{
+    assert( p->fUseInt );
+    ((int *)p->pAttrs)[Id] = Attr; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the attribute of the given object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Attr_ManWriteAttrPtr( Attr_Man_t * p, int Id, void * pAttr )
+{
+    assert( !p->fUseInt );
+    assert( p->pManMem == NULL );
+    p->pAttrs[Id] = pAttr; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns or creates the pointer to the attribute of the given object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int * Attr_ManFetchSpotInt( Attr_Man_t * p, int Id )
+{
+    assert( p->fUseInt );
+    if ( Id >= p->nAttrs )
+    {
+        // save the old size
+        int i, nAttrsOld = p->nAttrs;
+        // get the new size
+        p->nAttrs = p->nAttrs? 2*p->nAttrs : 1024;
+        p->pAttrs = realloc( p->pAttrs, sizeof(int) * p->nAttrs ); 
+        // fill in the empty spots
+        for ( i = nAttrsOld; i < p->nAttrs; i++ )
+            ((int *)p->pAttrs)[Id] = 0;
+    }
+    return ((int *)p->pAttrs) + Id;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns or creates the pointer to the attribute of the given object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void ** Attr_ManFetchSpotPtr( Attr_Man_t * p, int Id )
+{
+    assert( !p->fUseInt );
+    if ( Id >= p->nAttrs )
+    {
+        // save the old size
+        int i, nAttrsOld = p->nAttrs;
+        // get the new size
+        p->nAttrs = p->nAttrs? 2*p->nAttrs : 1024;
+        p->pAttrs = realloc( p->pAttrs, sizeof(void *) * p->nAttrs ); 
+        // fill in the empty spots
+        for ( i = nAttrsOld; i < p->nAttrs; i++ )
+            p->pAttrs[Id] = NULL;
+    }
+    // if memory manager is available but entry is not created, create it
+    if ( p->pManMem && p->pAttrs[Id] != NULL ) 
+    {
+        p->pAttrs[Id] = Extra_MmFixedEntryFetch( p->pManMem );
+        memset( p->pAttrs[Id], 0, p->nAttrSize );
+    }
+    return p->pAttrs + Id;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns or creates the attribute of the given object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Attr_ManFetchAttrInt( Attr_Man_t * p, int Id )
+{
+    return *Attr_ManFetchSpotInt( p, Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns or creates the attribute of the given object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void * Attr_ManFetchAttrPtr( Attr_Man_t * p, int Id )
+{
+    return *Attr_ManFetchSpotPtr( p, Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the attribute of the given object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Attr_ManSetAttrInt( Attr_Man_t * p, int Id, int Attr )
+{
+    *Attr_ManFetchSpotInt( p, Id ) = Attr;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the attribute of the given object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Attr_ManSetAttrPtr( Attr_Man_t * p, int Id, void * pAttr )
+{
+    assert( p->pManMem == NULL );
+    *Attr_ManFetchSpotPtr( p, Id ) = pAttr;
+}
+
+
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/aig/ivy/ivy.h b/abc-build/src/aig/ivy/ivy.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivy.h
@@ -0,0 +1,562 @@
+/**CFile****************************************************************
+
+  FileName    [ivy.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivy.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__ivy__ivy_h
+#define ABC__aig__ivy__ivy_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "misc/extra/extra.h"
+#include "misc/vec/vec.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ivy_Man_t_            Ivy_Man_t;
+typedef struct Ivy_Obj_t_            Ivy_Obj_t;
+typedef int                          Ivy_Edge_t;
+typedef struct Ivy_FraigParams_t_    Ivy_FraigParams_t;
+
+// object types
+typedef enum { 
+    IVY_NONE,                        // 0: non-existent object
+    IVY_PI,                          // 1: primary input (and constant 1 node)
+    IVY_PO,                          // 2: primary output
+    IVY_ASSERT,                      // 3: assertion
+    IVY_LATCH,                       // 4: sequential element
+    IVY_AND,                         // 5: AND node
+    IVY_EXOR,                        // 6: EXOR node
+    IVY_BUF,                         // 7: buffer (temporary)
+    IVY_VOID                         // 8: unused object
+} Ivy_Type_t;
+
+// latch initial values
+typedef enum { 
+    IVY_INIT_NONE,                   // 0: not a latch
+    IVY_INIT_0,                      // 1: zero
+    IVY_INIT_1,                      // 2: one
+    IVY_INIT_DC                      // 3: don't-care
+} Ivy_Init_t;
+
+// the AIG node
+struct Ivy_Obj_t_  // 24 bytes (32-bit) or 32 bytes (64-bit)   // 10 words - 16 words
+{
+    int              Id;             // integer ID
+    int              TravId;         // traversal ID
+    unsigned         Type     :  4;  // object type
+    unsigned         fMarkA   :  1;  // multipurpose mask
+    unsigned         fMarkB   :  1;  // multipurpose mask
+    unsigned         fExFan   :  1;  // set to 1 if last fanout added is EXOR
+    unsigned         fPhase   :  1;  // value under 000...0 pattern
+    unsigned         fFailTfo :  1;  // the TFO of the failed node
+    unsigned         Init     :  2;  // latch initial value
+    unsigned         Level    : 21;  // logic level
+    int              nRefs;          // reference counter
+    Ivy_Obj_t *      pFanin0;        // fanin
+    Ivy_Obj_t *      pFanin1;        // fanin
+    Ivy_Obj_t *      pFanout;        // fanout
+    Ivy_Obj_t *      pNextFan0;      // next fanout of the first fanin
+    Ivy_Obj_t *      pNextFan1;      // next fanout of the second fanin
+    Ivy_Obj_t *      pPrevFan0;      // prev fanout of the first fanin
+    Ivy_Obj_t *      pPrevFan1;      // prev fanout of the second fanin
+    Ivy_Obj_t *      pEquiv;         // equivalent node
+};
+
+// the AIG manager
+struct Ivy_Man_t_
+{
+    // AIG nodes
+    Vec_Ptr_t *      vPis;           // the array of PIs
+    Vec_Ptr_t *      vPos;           // the array of POs
+    Vec_Ptr_t *      vBufs;          // the array of buffers
+    Vec_Ptr_t *      vObjs;          // the array of objects
+    Ivy_Obj_t *      pConst1;        // the constant 1 node
+    Ivy_Obj_t        Ghost;          // the ghost node
+    // AIG node counters
+    int              nObjs[IVY_VOID];// the number of objects by type
+    int              nCreated;       // the number of created objects
+    int              nDeleted;       // the number of deleted objects
+    // stuctural hash table
+    int *            pTable;         // structural hash table
+    int              nTableSize;     // structural hash table size
+    // various data members
+    int              fCatchExor;     // set to 1 to detect EXORs
+    int              nTravIds;       // the traversal ID
+    int              nLevelMax;      // the maximum level
+    Vec_Int_t *      vRequired;      // required times
+    int              fFanout;        // fanout is allocated
+    void *           pData;          // the temporary data
+    void *           pCopy;          // the temporary data
+    Ivy_Man_t *      pHaig;          // history AIG if present
+    int              nClassesSkip;   // the number of skipped classes
+    // memory management
+    Vec_Ptr_t *      vChunks;        // allocated memory pieces
+    Vec_Ptr_t *      vPages;         // memory pages used by nodes
+    Ivy_Obj_t *      pListFree;      // the list of free nodes 
+    // timing statistics
+    abctime          time1;
+    abctime          time2;
+};
+
+struct Ivy_FraigParams_t_
+{
+    int              nSimWords;         // the number of words in the simulation info
+    double           dSimSatur;         // the ratio of refined classes when saturation is reached
+    int              fPatScores;        // enables simulation pattern scoring
+    int              MaxScore;          // max score after which resimulation is used
+    double           dActConeRatio;     // the ratio of cone to be bumped
+    double           dActConeBumpMax;   // the largest bump in activity
+    int              fProve;            // prove the miter outputs
+    int              fVerbose;          // verbose output
+    int              fDoSparse;         // skip sparse functions
+    int              nBTLimitNode;      // conflict limit at a node
+    int              nBTLimitMiter;     // conflict limit at an output
+//    int              nBTLimitGlobal;    // conflict limit global
+//    int              nInsLimitNode;     // inspection limit at a node
+//    int              nInsLimitMiter;    // inspection limit at an output
+//    int              nInsLimitGlobal;   // inspection limit global
+};
+
+
+#define IVY_CUT_LIMIT     256
+#define IVY_CUT_INPUT       6
+
+typedef struct Ivy_Cut_t_ Ivy_Cut_t;
+struct Ivy_Cut_t_
+{
+    int         nLatches;
+    short       nSize;
+    short       nSizeMax;
+    int         pArray[IVY_CUT_INPUT];
+    unsigned    uHash;
+};
+
+typedef struct Ivy_Store_t_ Ivy_Store_t;
+struct Ivy_Store_t_
+{
+    int         nCuts;
+    int         nCutsM;
+    int         nCutsMax;
+    int         fSatur;
+    Ivy_Cut_t   pCuts[IVY_CUT_LIMIT]; // storage for cuts
+};
+
+#define IVY_LEAF_MASK     255
+#define IVY_LEAF_BITS       8
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define IVY_MIN(a,b)       (((a) < (b))? (a) : (b))
+#define IVY_MAX(a,b)       (((a) > (b))? (a) : (b))
+
+extern void Ivy_ManAddMemory( Ivy_Man_t * p );
+
+static inline int          Ivy_BitWordNum( int nBits )            { return (nBits>>5) + ((nBits&31) > 0);           }
+static inline int          Ivy_TruthWordNum( int nVars )          { return nVars <= 5 ? 1 : (1 << (nVars - 5));     }
+static inline int          Ivy_InfoHasBit( unsigned * p, int i )  { return (p[(i)>>5] & (1<<((i) & 31))) > 0;       }
+static inline void         Ivy_InfoSetBit( unsigned * p, int i )  { p[(i)>>5] |= (1<<((i) & 31));                   }
+static inline void         Ivy_InfoXorBit( unsigned * p, int i )  { p[(i)>>5] ^= (1<<((i) & 31));                   }
+
+static inline Ivy_Obj_t *  Ivy_Regular( Ivy_Obj_t * p )           { return (Ivy_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); }
+static inline Ivy_Obj_t *  Ivy_Not( Ivy_Obj_t * p )               { return (Ivy_Obj_t *)((ABC_PTRUINT_T)(p) ^  01); }
+static inline Ivy_Obj_t *  Ivy_NotCond( Ivy_Obj_t * p, int c )    { return (Ivy_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); }
+static inline int          Ivy_IsComplement( Ivy_Obj_t * p )      { return (int)((ABC_PTRUINT_T)(p) & 01);          }
+
+static inline Ivy_Obj_t *  Ivy_ManConst0( Ivy_Man_t * p )         { return Ivy_Not(p->pConst1);                     }
+static inline Ivy_Obj_t *  Ivy_ManConst1( Ivy_Man_t * p )         { return p->pConst1;                              }
+static inline Ivy_Obj_t *  Ivy_ManGhost( Ivy_Man_t * p )          { return &p->Ghost;                               }
+static inline Ivy_Obj_t *  Ivy_ManPi( Ivy_Man_t * p, int i )      { return (Ivy_Obj_t *)Vec_PtrEntry(p->vPis, i);   }
+static inline Ivy_Obj_t *  Ivy_ManPo( Ivy_Man_t * p, int i )      { return (Ivy_Obj_t *)Vec_PtrEntry(p->vPos, i);   }
+static inline Ivy_Obj_t *  Ivy_ManObj( Ivy_Man_t * p, int i )     { return (Ivy_Obj_t *)Vec_PtrEntry(p->vObjs, i);  }
+
+static inline Ivy_Edge_t   Ivy_EdgeCreate( int Id, int fCompl )            { return (Id << 1) | fCompl;             }
+static inline int          Ivy_EdgeId( Ivy_Edge_t Edge )                   { return Edge >> 1;                      }
+static inline int          Ivy_EdgeIsComplement( Ivy_Edge_t Edge )         { return Edge & 1;                       }
+static inline Ivy_Edge_t   Ivy_EdgeRegular( Ivy_Edge_t Edge )              { return (Edge >> 1) << 1;               }
+static inline Ivy_Edge_t   Ivy_EdgeNot( Ivy_Edge_t Edge )                  { return Edge ^ 1;                       }
+static inline Ivy_Edge_t   Ivy_EdgeNotCond( Ivy_Edge_t Edge, int fCond )   { return Edge ^ fCond;                   }
+static inline Ivy_Edge_t   Ivy_EdgeFromNode( Ivy_Obj_t * pNode )           { return Ivy_EdgeCreate( Ivy_Regular(pNode)->Id, Ivy_IsComplement(pNode) );          }
+static inline Ivy_Obj_t *  Ivy_EdgeToNode( Ivy_Man_t * p, Ivy_Edge_t Edge ){ return Ivy_NotCond( Ivy_ManObj(p, Ivy_EdgeId(Edge)), Ivy_EdgeIsComplement(Edge) ); }
+
+static inline int          Ivy_LeafCreate( int Id, int Lat )      { return (Id << IVY_LEAF_BITS) | Lat;         }
+static inline int          Ivy_LeafId( int Leaf )                 { return Leaf >> IVY_LEAF_BITS;               }
+static inline int          Ivy_LeafLat( int Leaf )                { return Leaf & IVY_LEAF_MASK;                }
+
+static inline int          Ivy_ManPiNum( Ivy_Man_t * p )          { return p->nObjs[IVY_PI];                    }
+static inline int          Ivy_ManPoNum( Ivy_Man_t * p )          { return p->nObjs[IVY_PO];                    }
+static inline int          Ivy_ManAssertNum( Ivy_Man_t * p )      { return p->nObjs[IVY_ASSERT];                }
+static inline int          Ivy_ManLatchNum( Ivy_Man_t * p )       { return p->nObjs[IVY_LATCH];                 }
+static inline int          Ivy_ManAndNum( Ivy_Man_t * p )         { return p->nObjs[IVY_AND];                   }
+static inline int          Ivy_ManExorNum( Ivy_Man_t * p )        { return p->nObjs[IVY_EXOR];                  }
+static inline int          Ivy_ManBufNum( Ivy_Man_t * p )         { return p->nObjs[IVY_BUF];                   }
+static inline int          Ivy_ManObjNum( Ivy_Man_t * p )         { return p->nCreated - p->nDeleted;           }
+static inline int          Ivy_ManObjIdMax( Ivy_Man_t * p )       { return Vec_PtrSize(p->vObjs)-1;             }
+static inline int          Ivy_ManNodeNum( Ivy_Man_t * p )        { return p->nObjs[IVY_AND]+p->nObjs[IVY_EXOR];}
+static inline int          Ivy_ManHashObjNum( Ivy_Man_t * p )     { return p->nObjs[IVY_AND]+p->nObjs[IVY_EXOR]+p->nObjs[IVY_LATCH];     }
+static inline int          Ivy_ManGetCost( Ivy_Man_t * p )        { return p->nObjs[IVY_AND]+3*p->nObjs[IVY_EXOR]+8*p->nObjs[IVY_LATCH]; }
+
+static inline Ivy_Type_t   Ivy_ObjType( Ivy_Obj_t * pObj )        { return (Ivy_Type_t)pObj->Type;               }
+static inline Ivy_Init_t   Ivy_ObjInit( Ivy_Obj_t * pObj )        { return (Ivy_Init_t)pObj->Init;               }
+static inline int          Ivy_ObjIsConst1( Ivy_Obj_t * pObj )    { return pObj->Id == 0;            }
+static inline int          Ivy_ObjIsGhost( Ivy_Obj_t * pObj )     { return pObj->Id < 0;             }
+static inline int          Ivy_ObjIsNone( Ivy_Obj_t * pObj )      { return pObj->Type == IVY_NONE;   }
+static inline int          Ivy_ObjIsPi( Ivy_Obj_t * pObj )        { return pObj->Type == IVY_PI;     }
+static inline int          Ivy_ObjIsPo( Ivy_Obj_t * pObj )        { return pObj->Type == IVY_PO;     }
+static inline int          Ivy_ObjIsCi( Ivy_Obj_t * pObj )        { return pObj->Type == IVY_PI || pObj->Type == IVY_LATCH; }
+static inline int          Ivy_ObjIsCo( Ivy_Obj_t * pObj )        { return pObj->Type == IVY_PO || pObj->Type == IVY_LATCH; }
+static inline int          Ivy_ObjIsAssert( Ivy_Obj_t * pObj )    { return pObj->Type == IVY_ASSERT; }
+static inline int          Ivy_ObjIsLatch( Ivy_Obj_t * pObj )     { return pObj->Type == IVY_LATCH;  }
+static inline int          Ivy_ObjIsAnd( Ivy_Obj_t * pObj )       { return pObj->Type == IVY_AND;    }
+static inline int          Ivy_ObjIsExor( Ivy_Obj_t * pObj )      { return pObj->Type == IVY_EXOR;   }
+static inline int          Ivy_ObjIsBuf( Ivy_Obj_t * pObj )       { return pObj->Type == IVY_BUF;    }
+static inline int          Ivy_ObjIsNode( Ivy_Obj_t * pObj )      { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR; }
+static inline int          Ivy_ObjIsTerm( Ivy_Obj_t * pObj )      { return pObj->Type == IVY_PI  || pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT; }
+static inline int          Ivy_ObjIsHash( Ivy_Obj_t * pObj )      { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR || pObj->Type == IVY_LATCH; }
+static inline int          Ivy_ObjIsOneFanin( Ivy_Obj_t * pObj )  { return pObj->Type == IVY_PO  || pObj->Type == IVY_ASSERT || pObj->Type == IVY_BUF || pObj->Type == IVY_LATCH; }
+
+static inline int          Ivy_ObjIsMarkA( Ivy_Obj_t * pObj )     { return pObj->fMarkA;  }
+static inline void         Ivy_ObjSetMarkA( Ivy_Obj_t * pObj )    { pObj->fMarkA = 1;     }
+static inline void         Ivy_ObjClearMarkA( Ivy_Obj_t * pObj )  { pObj->fMarkA = 0;     }
+ 
+static inline void         Ivy_ObjSetTravId( Ivy_Obj_t * pObj, int TravId )                { pObj->TravId = TravId;                               }
+static inline void         Ivy_ObjSetTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj )      { pObj->TravId = p->nTravIds;                          }
+static inline void         Ivy_ObjSetTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj )     { pObj->TravId = p->nTravIds - 1;                      }
+static inline int          Ivy_ObjIsTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj )       { return (int )((int)pObj->TravId == p->nTravIds);     }
+static inline int          Ivy_ObjIsTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj )      { return (int )((int)pObj->TravId == p->nTravIds - 1); }
+
+static inline int          Ivy_ObjId( Ivy_Obj_t * pObj )          { return pObj->Id;                               }
+static inline int          Ivy_ObjTravId( Ivy_Obj_t * pObj )      { return pObj->TravId;                           }
+static inline int          Ivy_ObjPhase( Ivy_Obj_t * pObj )       { return pObj->fPhase;                           }
+static inline int          Ivy_ObjExorFanout( Ivy_Obj_t * pObj )  { return pObj->fExFan;                           }
+static inline int          Ivy_ObjRefs( Ivy_Obj_t * pObj )        { return pObj->nRefs;                            }
+static inline void         Ivy_ObjRefsInc( Ivy_Obj_t * pObj )     { pObj->nRefs++;                                 }
+static inline void         Ivy_ObjRefsDec( Ivy_Obj_t * pObj )     { assert( pObj->nRefs > 0 ); pObj->nRefs--;      }
+static inline int          Ivy_ObjFaninId0( Ivy_Obj_t * pObj )    { return pObj->pFanin0? Ivy_ObjId(Ivy_Regular(pObj->pFanin0)) : 0; }
+static inline int          Ivy_ObjFaninId1( Ivy_Obj_t * pObj )    { return pObj->pFanin1? Ivy_ObjId(Ivy_Regular(pObj->pFanin1)) : 0; }
+static inline int          Ivy_ObjFaninC0( Ivy_Obj_t * pObj )     { return Ivy_IsComplement(pObj->pFanin0);        }
+static inline int          Ivy_ObjFaninC1( Ivy_Obj_t * pObj )     { return Ivy_IsComplement(pObj->pFanin1);        }
+static inline Ivy_Obj_t *  Ivy_ObjFanin0( Ivy_Obj_t * pObj )      { return Ivy_Regular(pObj->pFanin0);             }
+static inline Ivy_Obj_t *  Ivy_ObjFanin1( Ivy_Obj_t * pObj )      { return Ivy_Regular(pObj->pFanin1);             }
+static inline Ivy_Obj_t *  Ivy_ObjChild0( Ivy_Obj_t * pObj )      { return pObj->pFanin0;                          }
+static inline Ivy_Obj_t *  Ivy_ObjChild1( Ivy_Obj_t * pObj )      { return pObj->pFanin1;                          }
+static inline Ivy_Obj_t *  Ivy_ObjChild0Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin0(pObj)? Ivy_NotCond(Ivy_ObjFanin0(pObj)->pEquiv, Ivy_ObjFaninC0(pObj)) : NULL;  }
+static inline Ivy_Obj_t *  Ivy_ObjChild1Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin1(pObj)? Ivy_NotCond(Ivy_ObjFanin1(pObj)->pEquiv, Ivy_ObjFaninC1(pObj)) : NULL;  }
+static inline Ivy_Obj_t *  Ivy_ObjEquiv( Ivy_Obj_t * pObj )       { return Ivy_Regular(pObj)->pEquiv? Ivy_NotCond(Ivy_Regular(pObj)->pEquiv, Ivy_IsComplement(pObj)) : NULL; }
+static inline int          Ivy_ObjLevel( Ivy_Obj_t * pObj )       { return pObj->Level;                            }
+static inline int          Ivy_ObjLevelNew( Ivy_Obj_t * pObj )    { return 1 + Ivy_ObjIsExor(pObj) + IVY_MAX(Ivy_ObjFanin0(pObj)->Level, Ivy_ObjFanin1(pObj)->Level);       }
+static inline int          Ivy_ObjFaninPhase( Ivy_Obj_t * pObj )  { return Ivy_IsComplement(pObj)? !Ivy_Regular(pObj)->fPhase : pObj->fPhase; }
+
+static inline void         Ivy_ObjClean( Ivy_Obj_t * pObj )       
+{ 
+    int IdSaved = pObj->Id; 
+    memset( pObj, 0, sizeof(Ivy_Obj_t) ); 
+    pObj->Id = IdSaved; 
+}
+static inline void         Ivy_ObjOverwrite( Ivy_Obj_t * pBase, Ivy_Obj_t * pData )   
+{ 
+    int IdSaved = pBase->Id; 
+    memcpy( pBase, pData, sizeof(Ivy_Obj_t) ); 
+    pBase->Id = IdSaved;         
+}
+static inline int          Ivy_ObjWhatFanin( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanin )    
+{ 
+    if ( Ivy_ObjFanin0(pObj) == pFanin ) return 0; 
+    if ( Ivy_ObjFanin1(pObj) == pFanin ) return 1; 
+    assert(0); return -1; 
+}
+static inline int          Ivy_ObjFanoutC( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout )    
+{ 
+    if ( Ivy_ObjFanin0(pFanout) == pObj ) return Ivy_ObjFaninC0(pObj); 
+    if ( Ivy_ObjFanin1(pFanout) == pObj ) return Ivy_ObjFaninC1(pObj); 
+    assert(0); return -1; 
+}
+
+// create the ghost of the new node
+static inline Ivy_Obj_t *  Ivy_ObjCreateGhost( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type, Ivy_Init_t Init )    
+{
+    Ivy_Obj_t * pGhost, * pTemp;
+    assert( Type != IVY_AND || !Ivy_ObjIsConst1(Ivy_Regular(p0)) );
+    assert( p1 == NULL || !Ivy_ObjIsConst1(Ivy_Regular(p1)) );
+    assert( Type == IVY_PI || Ivy_Regular(p0) != Ivy_Regular(p1) );
+    assert( Type != IVY_LATCH || !Ivy_IsComplement(p0) );
+//    assert( p1 == NULL || (!Ivy_ObjIsLatch(Ivy_Regular(p0)) || !Ivy_ObjIsLatch(Ivy_Regular(p1))) );
+    pGhost = Ivy_ManGhost(p);
+    pGhost->Type = Type;
+    pGhost->Init = Init;
+    pGhost->pFanin0 = p0;
+    pGhost->pFanin1 = p1;
+    if ( p1 && Ivy_ObjFaninId0(pGhost) > Ivy_ObjFaninId1(pGhost) )
+        pTemp = pGhost->pFanin0, pGhost->pFanin0 = pGhost->pFanin1, pGhost->pFanin1 = pTemp;
+    return pGhost;
+}
+
+// get the complemented initial state
+static Ivy_Init_t Ivy_InitNotCond( Ivy_Init_t Init, int fCompl )
+{
+    assert( Init != IVY_INIT_NONE );
+    if ( fCompl == 0 )
+        return Init;
+    if ( Init == IVY_INIT_0 )
+        return IVY_INIT_1;
+    if ( Init == IVY_INIT_1 )
+        return IVY_INIT_0;
+    return IVY_INIT_DC;
+}
+
+// get the initial state after forward retiming over AND gate
+static Ivy_Init_t Ivy_InitAnd( Ivy_Init_t InitA, Ivy_Init_t InitB )
+{
+    assert( InitA != IVY_INIT_NONE && InitB != IVY_INIT_NONE );
+    if ( InitA == IVY_INIT_0 || InitB == IVY_INIT_0 )
+        return IVY_INIT_0;
+    if ( InitA == IVY_INIT_DC || InitB == IVY_INIT_DC )
+        return IVY_INIT_DC;
+    return IVY_INIT_1;
+}
+
+// get the initial state after forward retiming over EXOR gate
+static Ivy_Init_t Ivy_InitExor( Ivy_Init_t InitA, Ivy_Init_t InitB )
+{
+    assert( InitA != IVY_INIT_NONE && InitB != IVY_INIT_NONE );
+    if ( InitA == IVY_INIT_DC || InitB == IVY_INIT_DC )
+        return IVY_INIT_DC;
+    if ( InitA == IVY_INIT_0 && InitB == IVY_INIT_1 )
+        return IVY_INIT_1;
+    if ( InitA == IVY_INIT_1 && InitB == IVY_INIT_0 )
+        return IVY_INIT_1;
+    return IVY_INIT_0;
+}
+
+// internal memory manager
+static inline Ivy_Obj_t * Ivy_ManFetchMemory( Ivy_Man_t * p )  
+{ 
+    Ivy_Obj_t * pTemp;
+    if ( p->pListFree == NULL )
+        Ivy_ManAddMemory( p );
+    pTemp = p->pListFree;
+    p->pListFree = *((Ivy_Obj_t **)pTemp);
+    memset( pTemp, 0, sizeof(Ivy_Obj_t) ); 
+    return pTemp;
+}
+static inline void Ivy_ManRecycleMemory( Ivy_Man_t * p, Ivy_Obj_t * pEntry )
+{
+    pEntry->Type = IVY_NONE; // distinquishes dead node from live node
+    *((Ivy_Obj_t **)pEntry) = p->pListFree;
+    p->pListFree = pEntry;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                             ITERATORS                            ///
+////////////////////////////////////////////////////////////////////////
+
+// iterator over the primary inputs
+#define Ivy_ManForEachPi( p, pObj, i )                                          \
+    Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPis, pObj, i )
+// iterator over the primary outputs
+#define Ivy_ManForEachPo( p, pObj, i )                                          \
+    Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPos, pObj, i )
+// iterator over all objects, including those currently not used
+#define Ivy_ManForEachObj( p, pObj, i )                                         \
+    Vec_PtrForEachEntry( Ivy_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else
+// iterator over the combinational inputs
+#define Ivy_ManForEachCi( p, pObj, i )                                          \
+    Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsCi(pObj) ) {} else
+// iterator over the combinational outputs
+#define Ivy_ManForEachCo( p, pObj, i )                                          \
+    Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsCo(pObj) ) {} else
+// iterator over logic nodes (AND and EXOR gates)
+#define Ivy_ManForEachNode( p, pObj, i )                                        \
+    Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsNode(pObj) ) {} else
+// iterator over logic latches
+#define Ivy_ManForEachLatch( p, pObj, i )                                       \
+    Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsLatch(pObj) ) {} else
+// iterator over the nodes whose IDs are stored in the array
+#define Ivy_ManForEachNodeVec( p, vIds, pObj, i )                               \
+    for ( i = 0; i < Vec_IntSize(vIds) && ((pObj) = Ivy_ManObj(p, Vec_IntEntry(vIds,i))); i++ )
+// iterator over the fanouts of an object
+#define Ivy_ObjForEachFanout( p, pObj, vArray, pFanout, i )                     \
+    for ( i = 0, Ivy_ObjCollectFanouts(p, pObj, vArray);                        \
+          i < Vec_PtrSize(vArray) && ((pFanout) = (Ivy_Obj_t *)Vec_PtrEntry(vArray,i)); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== ivyBalance.c ========================================================*/
+extern Ivy_Man_t *     Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel );
+extern Ivy_Obj_t *     Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel );
+/*=== ivyCanon.c ========================================================*/
+extern Ivy_Obj_t *     Ivy_CanonAnd( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 );
+extern Ivy_Obj_t *     Ivy_CanonExor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 );
+extern Ivy_Obj_t *     Ivy_CanonLatch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init );
+/*=== ivyCheck.c ========================================================*/
+extern int             Ivy_ManCheck( Ivy_Man_t * p );
+extern int             Ivy_ManCheckFanoutNums( Ivy_Man_t * p );
+extern int             Ivy_ManCheckFanouts( Ivy_Man_t * p );
+extern int             Ivy_ManCheckChoices( Ivy_Man_t * p );
+/*=== ivyCut.c ==========================================================*/
+extern void            Ivy_ManSeqFindCut( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSize );
+extern Ivy_Store_t *   Ivy_NodeFindCutsAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves );
+/*=== ivyDfs.c ==========================================================*/
+extern Vec_Int_t *     Ivy_ManDfs( Ivy_Man_t * p );
+extern Vec_Int_t *     Ivy_ManDfsSeq( Ivy_Man_t * p, Vec_Int_t ** pvLatches );
+extern void            Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone );
+extern Vec_Vec_t *     Ivy_ManLevelize( Ivy_Man_t * p );
+extern Vec_Int_t *     Ivy_ManRequiredLevels( Ivy_Man_t * p );
+extern int             Ivy_ManIsAcyclic( Ivy_Man_t * p );
+extern int             Ivy_ManSetLevels( Ivy_Man_t * p, int fHaig );
+/*=== ivyDsd.c ==========================================================*/
+extern int             Ivy_TruthDsd( unsigned uTruth, Vec_Int_t * vTree );
+extern void            Ivy_TruthDsdPrint( FILE * pFile, Vec_Int_t * vTree );
+extern unsigned        Ivy_TruthDsdCompute( Vec_Int_t * vTree );
+extern void            Ivy_TruthDsdComputePrint( unsigned uTruth );
+extern Ivy_Obj_t *     Ivy_ManDsdConstruct( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vTree );
+/*=== ivyFanout.c ==========================================================*/
+extern void            Ivy_ManStartFanout( Ivy_Man_t * p );
+extern void            Ivy_ManStopFanout( Ivy_Man_t * p );
+extern void            Ivy_ObjAddFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout );
+extern void            Ivy_ObjDeleteFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout );
+extern void            Ivy_ObjPatchFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanoutOld, Ivy_Obj_t * pFanoutNew );
+extern void            Ivy_ObjCollectFanouts( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vArray );
+extern Ivy_Obj_t *     Ivy_ObjReadFirstFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+extern int             Ivy_ObjFanoutNum( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+/*=== ivyFastMap.c =============================================================*/
+extern void            Ivy_FastMapPerform( Ivy_Man_t * pAig, int nLimit, int fRecovery, int fVerbose );
+extern void            Ivy_FastMapStop( Ivy_Man_t * pAig );
+extern void            Ivy_FastMapReadSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Int_t * vLeaves );
+extern void            Ivy_FastMapReverseLevel( Ivy_Man_t * pAig );
+/*=== ivyFraig.c ==========================================================*/
+extern int             Ivy_FraigProve( Ivy_Man_t ** ppManAig, void * pPars );
+extern Ivy_Man_t *     Ivy_FraigPerform( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams );
+extern Ivy_Man_t *     Ivy_FraigMiter( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams );
+extern void            Ivy_FraigParamsDefault( Ivy_FraigParams_t * pParams );
+/*=== ivyHaig.c ==========================================================*/
+extern void            Ivy_ManHaigStart( Ivy_Man_t * p, int fVerbose );
+extern void            Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew );
+extern void            Ivy_ManHaigStop( Ivy_Man_t * p );
+extern void            Ivy_ManHaigPostprocess( Ivy_Man_t * p, int fVerbose );
+extern void            Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+extern void            Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew );
+extern void            Ivy_ManHaigSimulate( Ivy_Man_t * p );
+/*=== ivyMan.c ==========================================================*/
+extern Ivy_Man_t *     Ivy_ManStart();
+extern Ivy_Man_t *     Ivy_ManStartFrom( Ivy_Man_t * p );
+extern Ivy_Man_t *     Ivy_ManDup( Ivy_Man_t * p );
+extern Ivy_Man_t *     Ivy_ManFrames( Ivy_Man_t * pMan, int nLatches, int nFrames, int fInit, Vec_Ptr_t ** pvMapping );
+extern void            Ivy_ManStop( Ivy_Man_t * p );
+extern int             Ivy_ManCleanup( Ivy_Man_t * p );
+extern int             Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel );
+extern void            Ivy_ManPrintStats( Ivy_Man_t * p );
+extern void            Ivy_ManMakeSeq( Ivy_Man_t * p, int nLatches, int * pInits );
+/*=== ivyMem.c ==========================================================*/
+extern void            Ivy_ManStartMemory( Ivy_Man_t * p );
+extern void            Ivy_ManStopMemory( Ivy_Man_t * p );
+/*=== ivyMulti.c ==========================================================*/
+extern Ivy_Obj_t *     Ivy_Multi( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
+extern Ivy_Obj_t *     Ivy_Multi1( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
+extern Ivy_Obj_t *     Ivy_Multi_rec( Ivy_Man_t * p, Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type );
+extern Ivy_Obj_t *     Ivy_MultiBalance_rec( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
+extern int             Ivy_MultiPlus( Ivy_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSol );
+/*=== ivyObj.c ==========================================================*/
+extern Ivy_Obj_t *     Ivy_ObjCreatePi( Ivy_Man_t * p );
+extern Ivy_Obj_t *     Ivy_ObjCreatePo( Ivy_Man_t * p, Ivy_Obj_t * pDriver );
+extern Ivy_Obj_t *     Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost );
+extern void            Ivy_ObjConnect( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFan0, Ivy_Obj_t * pFan1 );
+extern void            Ivy_ObjDisconnect( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+extern void            Ivy_ObjPatchFanin0( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFaninNew );
+extern void            Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop );
+extern void            Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop );
+extern void            Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel );
+extern void            Ivy_NodeFixBufferFanins( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel );
+/*=== ivyOper.c =========================================================*/
+extern Ivy_Obj_t *     Ivy_Oper( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type );
+extern Ivy_Obj_t *     Ivy_And( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 );
+extern Ivy_Obj_t *     Ivy_Or( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 );
+extern Ivy_Obj_t *     Ivy_Exor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 );
+extern Ivy_Obj_t *     Ivy_Mux( Ivy_Man_t * p, Ivy_Obj_t * pC, Ivy_Obj_t * p1, Ivy_Obj_t * p0 );
+extern Ivy_Obj_t *     Ivy_Maj( Ivy_Man_t * p, Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * pC );
+extern Ivy_Obj_t *     Ivy_Miter( Ivy_Man_t * p, Vec_Ptr_t * vPairs );
+extern Ivy_Obj_t *     Ivy_Latch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init );
+/*=== ivyResyn.c =========================================================*/
+extern Ivy_Man_t *     Ivy_ManResyn0( Ivy_Man_t * p, int fUpdateLevel, int fVerbose );
+extern Ivy_Man_t *     Ivy_ManResyn( Ivy_Man_t * p, int fUpdateLevel, int fVerbose );
+extern Ivy_Man_t *     Ivy_ManRwsat( Ivy_Man_t * pMan, int fVerbose );
+/*=== ivyRewrite.c =========================================================*/
+extern int             Ivy_ManSeqRewrite( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost );
+extern int             Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost );
+extern int             Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose );
+/*=== ivySeq.c =========================================================*/
+extern int             Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose );
+/*=== ivyShow.c =========================================================*/
+extern void            Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold );
+/*=== ivyTable.c ========================================================*/
+extern Ivy_Obj_t *     Ivy_TableLookup( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+extern void            Ivy_TableInsert( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+extern void            Ivy_TableDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+extern void            Ivy_TableUpdate( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ObjIdNew );
+extern int             Ivy_TableCountEntries( Ivy_Man_t * p );
+extern void            Ivy_TableProfile( Ivy_Man_t * p );
+/*=== ivyUtil.c =========================================================*/
+extern void            Ivy_ManIncrementTravId( Ivy_Man_t * p );
+extern void            Ivy_ManCleanTravId( Ivy_Man_t * p );
+extern unsigned *      Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth );
+extern void            Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes );
+extern Vec_Int_t *     Ivy_ManLatches( Ivy_Man_t * p );
+extern int             Ivy_ManLevels( Ivy_Man_t * p );
+extern void            Ivy_ManResetLevels( Ivy_Man_t * p );
+extern int             Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+extern void            Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+extern void            Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew );
+extern int             Ivy_ObjIsMuxType( Ivy_Obj_t * pObj );
+extern Ivy_Obj_t *     Ivy_ObjRecognizeMux( Ivy_Obj_t * pObj, Ivy_Obj_t ** ppObjT, Ivy_Obj_t ** ppObjE );
+extern Ivy_Obj_t *     Ivy_ObjReal( Ivy_Obj_t * pObj );
+extern void            Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig );
+extern void            Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig );
+extern int             Ivy_CutTruthPrint( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/aig/ivy/ivyBalance.c b/abc-build/src/aig/ivy/ivyBalance.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyBalance.c
@@ -0,0 +1,414 @@
+/**CFile****************************************************************
+
+  FileName    [ivyBalance.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Algebraic AIG balancing.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int         Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel );
+static Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level );
+static int         Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper );
+static void        Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor );
+static void        Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs algebraic balancing of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel )
+{
+    Ivy_Man_t * pNew;
+    Ivy_Obj_t * pObj, * pDriver;
+    Vec_Vec_t * vStore;
+    int i, NewNodeId;
+    // clean the old manager
+    Ivy_ManCleanTravId( p );
+    // create the new manager 
+    pNew = Ivy_ManStart();
+    // map the nodes
+    Ivy_ManConst1(p)->TravId = Ivy_EdgeFromNode( Ivy_ManConst1(pNew) );
+    Ivy_ManForEachPi( p, pObj, i )
+        pObj->TravId = Ivy_EdgeFromNode( Ivy_ObjCreatePi(pNew) );
+    // if HAIG is defined, trasfer the pointers to the PIs/latches
+//    if ( p->pHaig )
+//        Ivy_ManHaigTrasfer( p, pNew );
+    // balance the AIG
+    vStore = Vec_VecAlloc( 50 );
+    Ivy_ManForEachPo( p, pObj, i )
+    {
+        pDriver   = Ivy_ObjReal( Ivy_ObjChild0(pObj) );
+        NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(pDriver), vStore, 0, fUpdateLevel );
+        NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(pDriver) );
+        Ivy_ObjCreatePo( pNew, Ivy_EdgeToNode(pNew, NewNodeId) );
+    }
+    Vec_VecFree( vStore );
+    if ( (i = Ivy_ManCleanup( pNew )) )
+    {
+//        printf( "Cleanup after balancing removed %d dangling nodes.\n", i );
+    }
+    // check the resulting AIG
+    if ( !Ivy_ManCheck(pNew) )
+        printf( "Ivy_ManBalance(): The check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure used for sorting the nodes in decreasing order of levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_NodeCompareLevelsDecrease( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 )
+{
+    int Diff = Ivy_Regular(*pp1)->Level - Ivy_Regular(*pp2)->Level;
+    if ( Diff > 0 )
+        return -1;
+    if ( Diff < 0 ) 
+        return 1;
+    Diff = Ivy_Regular(*pp1)->Id - Ivy_Regular(*pp2)->Id;
+    if ( Diff > 0 )
+        return -1;
+    if ( Diff < 0 ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the ID of new node constructed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel )
+{
+    Ivy_Obj_t * pObjNew;
+    Vec_Ptr_t * vSuper;
+    int i, NewNodeId;
+    assert( !Ivy_IsComplement(pObjOld) );
+    assert( !Ivy_ObjIsBuf(pObjOld) );
+    // return if the result is known
+    if ( Ivy_ObjIsConst1(pObjOld) )
+        return pObjOld->TravId;
+    if ( pObjOld->TravId )
+        return pObjOld->TravId;
+    assert( Ivy_ObjIsNode(pObjOld) );
+    // get the implication supergate
+    vSuper = Ivy_NodeBalanceCone( pObjOld, vStore, Level );
+    if ( vSuper->nSize == 0 )
+    { // it means that the supergate contains two nodes in the opposite polarity
+        pObjOld->TravId = Ivy_EdgeFromNode( Ivy_ManConst0(pNew) );
+        return pObjOld->TravId;
+    }
+    if ( vSuper->nSize < 2 )
+        printf( "BUG!\n" );
+    // for each old node, derive the new well-balanced node
+    for ( i = 0; i < vSuper->nSize; i++ )
+    {
+        NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular((Ivy_Obj_t *)vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel );
+        NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement((Ivy_Obj_t *)vSuper->pArray[i]) );
+        vSuper->pArray[i] = Ivy_EdgeToNode( pNew, NewNodeId );
+    }
+    // build the supergate
+    pObjNew = Ivy_NodeBalanceBuildSuper( pNew, vSuper, Ivy_ObjType(pObjOld), fUpdateLevel );
+    vSuper->nSize = 0;
+    // make sure the balanced node is not assigned
+    assert( pObjOld->TravId == 0 );
+    pObjOld->TravId = Ivy_EdgeFromNode( pObjNew );
+//    assert( pObjOld->Level >= Ivy_Regular(pObjNew)->Level );
+    return pObjOld->TravId;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Builds implication supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel )
+{
+    Ivy_Obj_t * pObj1, * pObj2;
+    int LeftBound;
+    assert( vSuper->nSize > 1 );
+    // sort the new nodes by level in the decreasing order
+    Vec_PtrSort( vSuper, (int (*)(void))Ivy_NodeCompareLevelsDecrease );
+    // balance the nodes
+    while ( vSuper->nSize > 1 )
+    {
+        // find the left bound on the node to be paired
+        LeftBound = (!fUpdateLevel)? 0 : Ivy_NodeBalanceFindLeft( vSuper );
+        // find the node that can be shared (if no such node, randomize choice)
+        Ivy_NodeBalancePermute( p, vSuper, LeftBound, Type == IVY_EXOR );
+        // pull out the last two nodes
+        pObj1 = (Ivy_Obj_t *)Vec_PtrPop(vSuper);
+        pObj2 = (Ivy_Obj_t *)Vec_PtrPop(vSuper);
+        Ivy_NodeBalancePushUniqueOrderByLevel( vSuper, Ivy_Oper(p, pObj1, pObj2, Type) );
+    }
+    return (Ivy_Obj_t *)Vec_PtrEntry(vSuper, 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the nodes of the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_NodeBalanceCone_rec( Ivy_Obj_t * pRoot, Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper )
+{
+    int RetValue1, RetValue2, i;
+    // check if the node is visited
+    if ( Ivy_Regular(pObj)->fMarkB )
+    {
+        // check if the node occurs in the same polarity
+        for ( i = 0; i < vSuper->nSize; i++ )
+            if ( vSuper->pArray[i] == pObj )
+                return 1;
+        // check if the node is present in the opposite polarity
+        for ( i = 0; i < vSuper->nSize; i++ )
+            if ( vSuper->pArray[i] == Ivy_Not(pObj) )
+                return -1;
+        assert( 0 );
+        return 0;
+    }
+    // if the new node is complemented or a PI, another gate begins
+    if ( pObj != pRoot && (Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Ivy_ObjType(pRoot) || Ivy_ObjRefs(pObj) > 1 || Vec_PtrSize(vSuper) > 10000) )
+    {
+        Vec_PtrPush( vSuper, pObj );
+        Ivy_Regular(pObj)->fMarkB = 1;
+        return 0;
+    }
+    assert( !Ivy_IsComplement(pObj) );
+    assert( Ivy_ObjIsNode(pObj) );
+    // go through the branches
+    RetValue1 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild0(pObj) ), vSuper );
+    RetValue2 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild1(pObj) ), vSuper );
+    if ( RetValue1 == -1 || RetValue2 == -1 )
+        return -1;
+    // return 1 if at least one branch has a duplicate
+    return RetValue1 || RetValue2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the nodes of the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level )
+{
+    Vec_Ptr_t * vNodes;
+    int RetValue, i;
+    assert( !Ivy_IsComplement(pObj) );
+    // extend the storage
+    if ( Vec_VecSize( vStore ) <= Level )
+        Vec_VecPush( vStore, Level, 0 );
+    // get the temporary array of nodes
+    vNodes = Vec_VecEntry( vStore, Level );
+    Vec_PtrClear( vNodes );
+    // collect the nodes in the implication supergate
+    RetValue = Ivy_NodeBalanceCone_rec( pObj, pObj, vNodes );
+    assert( vNodes->nSize > 1 );
+    // unmark the visited nodes
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, i )
+        Ivy_Regular(pObj)->fMarkB = 0;
+    // if we found the node and its complement in the same implication supergate, 
+    // return empty set of nodes (meaning that we should use constant-0 node)
+    if ( RetValue == -1 )
+        vNodes->nSize = 0;
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the left bound on the next candidate to be paired.]
+
+  Description [The nodes in the array are in the decreasing order of levels. 
+  The last node in the array has the smallest level. By default it would be paired 
+  with the next node on the left. However, it may be possible to pair it with some
+  other node on the left, in such a way that the new node is shared. This procedure
+  finds the index of the left-most node, which can be paired with the last node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper )
+{
+    Ivy_Obj_t * pObjRight, * pObjLeft;
+    int Current;
+    // if two or less nodes, pair with the first
+    if ( Vec_PtrSize(vSuper) < 3 )
+        return 0;
+    // set the pointer to the one before the last
+    Current = Vec_PtrSize(vSuper) - 2;
+    pObjRight = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, Current );
+    // go through the nodes to the left of this one
+    for ( Current--; Current >= 0; Current-- )
+    {
+        // get the next node on the left
+        pObjLeft = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, Current );
+        // if the level of this node is different, quit the loop
+        if ( Ivy_Regular(pObjLeft)->Level != Ivy_Regular(pObjRight)->Level )
+            break;
+    }
+    Current++;    
+    // get the node, for which the equality holds
+    pObjLeft = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, Current );
+    assert( Ivy_Regular(pObjLeft)->Level == Ivy_Regular(pObjRight)->Level );
+    return Current;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Moves closer to the end the node that is best for sharing.]
+
+  Description [If there is no node with sharing, randomly chooses one of 
+  the legal nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor )
+{
+    Ivy_Obj_t * pObj1, * pObj2, * pObj3, * pGhost;
+    int RightBound, i;
+    // get the right bound
+    RightBound = Vec_PtrSize(vSuper) - 2;
+    assert( LeftBound <= RightBound );
+    if ( LeftBound == RightBound )
+        return;
+    // get the two last nodes
+    pObj1 = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 );
+    pObj2 = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, RightBound     );
+    if ( Ivy_Regular(pObj1) == p->pConst1 || Ivy_Regular(pObj2) == p->pConst1 )
+        return;
+    // find the first node that can be shared
+    for ( i = RightBound; i >= LeftBound; i-- )
+    {
+        pObj3 = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, i );
+        if ( Ivy_Regular(pObj3) == p->pConst1 )
+        {
+            Vec_PtrWriteEntry( vSuper, i,          pObj2 );
+            Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
+            return;
+        }
+        pGhost = Ivy_ObjCreateGhost( p, pObj1, pObj3, fExor? IVY_EXOR : IVY_AND, IVY_INIT_NONE );
+        if ( Ivy_TableLookup( p, pGhost ) )
+        {
+            if ( pObj3 == pObj2 )
+                return;
+            Vec_PtrWriteEntry( vSuper, i,          pObj2 );
+            Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
+            return;
+        }
+    }
+/*
+    // we did not find the node to share, randomize choice
+    {
+        int Choice = rand() % (RightBound - LeftBound + 1);
+        pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice );
+        if ( pObj3 == pObj2 )
+            return;
+        Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 );
+        Vec_PtrWriteEntry( vSuper, RightBound,         pObj3 );
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts a new node in the order by levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj )
+{
+    Ivy_Obj_t * pObj1, * pObj2;
+    int i;
+    if ( Vec_PtrPushUnique(vStore, pObj) )
+        return;
+    // find the p of the node
+    for ( i = vStore->nSize-1; i > 0; i-- )
+    {
+        pObj1 = (Ivy_Obj_t *)vStore->pArray[i  ];
+        pObj2 = (Ivy_Obj_t *)vStore->pArray[i-1];
+        if ( Ivy_Regular(pObj1)->Level <= Ivy_Regular(pObj2)->Level )
+            break;
+        vStore->pArray[i  ] = pObj2;
+        vStore->pArray[i-1] = pObj1;
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyCanon.c b/abc-build/src/aig/ivy/ivyCanon.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyCanon.c
@@ -0,0 +1,149 @@
+/**CFile****************************************************************
+
+  FileName    [ivyCanon.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Finding canonical form of objects.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyCanon.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Ivy_Obj_t * Ivy_TableLookupPair_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1, int fCompl0, int fCompl1, Ivy_Type_t Type );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the canonical form of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_CanonPair_rec( Ivy_Man_t * p, Ivy_Obj_t * pGhost )
+{
+    Ivy_Obj_t * pResult, * pLat0, * pLat1;
+    Ivy_Init_t Init, Init0, Init1;
+    int fCompl0, fCompl1;
+    Ivy_Type_t Type;
+    assert( Ivy_ObjIsNode(pGhost) );
+    assert( Ivy_ObjIsAnd(pGhost) || (!Ivy_ObjFaninC0(pGhost) && !Ivy_ObjFaninC1(pGhost)) );
+    assert( Ivy_ObjFaninId0(pGhost) != 0 && Ivy_ObjFaninId1(pGhost) != 0 );
+    // consider the case when the pair is canonical
+    if ( !Ivy_ObjIsLatch(Ivy_ObjFanin0(pGhost)) || !Ivy_ObjIsLatch(Ivy_ObjFanin1(pGhost)) )
+    {
+        if ( (pResult = Ivy_TableLookup( p, pGhost )) )
+            return pResult;
+        return Ivy_ObjCreate( p, pGhost );
+    }
+    /// remember the latches
+    pLat0 = Ivy_ObjFanin0(pGhost);
+    pLat1 = Ivy_ObjFanin1(pGhost);
+    // remember type and compls
+    Type = Ivy_ObjType(pGhost);
+    fCompl0 = Ivy_ObjFaninC0(pGhost);
+    fCompl1 = Ivy_ObjFaninC1(pGhost);
+    // call recursively
+    pResult = Ivy_Oper( p, Ivy_NotCond(Ivy_ObjFanin0(pLat0), fCompl0), Ivy_NotCond(Ivy_ObjFanin0(pLat1), fCompl1), Type );
+    // build latch on top of this
+    Init0 = Ivy_InitNotCond( Ivy_ObjInit(pLat0), fCompl0 );
+    Init1 = Ivy_InitNotCond( Ivy_ObjInit(pLat1), fCompl1 );
+    Init  = (Type == IVY_AND)? Ivy_InitAnd(Init0, Init1) : Ivy_InitExor(Init0, Init1);
+    return Ivy_Latch( p, pResult, Init );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the canonical form of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_CanonAnd( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 )
+{
+    Ivy_Obj_t * pGhost, * pResult;
+    pGhost = Ivy_ObjCreateGhost( p, pObj0, pObj1, IVY_AND, IVY_INIT_NONE );
+    pResult = Ivy_CanonPair_rec( p, pGhost );
+    return pResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the canonical form of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_CanonExor( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 )
+{
+    Ivy_Obj_t * pGhost, * pResult;
+    int fCompl = Ivy_IsComplement(pObj0) ^ Ivy_IsComplement(pObj1);
+    pObj0 = Ivy_Regular(pObj0);
+    pObj1 = Ivy_Regular(pObj1);
+    pGhost = Ivy_ObjCreateGhost( p, pObj0, pObj1, IVY_EXOR, IVY_INIT_NONE );
+    pResult = Ivy_CanonPair_rec( p, pGhost );
+    return Ivy_NotCond( pResult, fCompl );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the canonical form of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_CanonLatch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init )
+{
+    Ivy_Obj_t * pGhost, * pResult;
+    int fCompl = Ivy_IsComplement(pObj);
+    pObj = Ivy_Regular(pObj);
+    pGhost = Ivy_ObjCreateGhost( p, pObj, NULL, IVY_LATCH, Ivy_InitNotCond(Init, fCompl) );
+    pResult = Ivy_TableLookup( p, pGhost );
+    if ( pResult == NULL )
+        pResult = Ivy_ObjCreate( p, pGhost );
+    return Ivy_NotCond( pResult, fCompl );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyCheck.c b/abc-build/src/aig/ivy/ivyCheck.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyCheck.c
@@ -0,0 +1,278 @@
+/**CFile****************************************************************
+
+  FileName    [ivyCheck.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [AIG checking procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyCheck.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the consistency of the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManCheck( Ivy_Man_t * p )
+{
+    Ivy_Obj_t * pObj, * pObj2;
+    int i;
+    Ivy_ManForEachObj( p, pObj, i )
+    {
+        // skip deleted nodes
+        if ( Ivy_ObjId(pObj) != i )
+        {
+            printf( "Ivy_ManCheck: Node with ID %d is listed as number %d in the array of objects.\n", pObj->Id, i );
+            return 0;
+        }
+        // consider the constant node and PIs
+        if ( i == 0 || Ivy_ObjIsPi(pObj) )
+        {
+            if ( Ivy_ObjFaninId0(pObj) || Ivy_ObjFaninId1(pObj) || Ivy_ObjLevel(pObj) )
+            {
+                printf( "Ivy_ManCheck: The AIG has non-standard constant or PI node with ID \"%d\".\n", pObj->Id );
+                return 0;
+            }
+            continue;
+        }
+        if ( Ivy_ObjIsPo(pObj) )
+        {
+            if ( Ivy_ObjFaninId1(pObj) )
+            {
+                printf( "Ivy_ManCheck: The AIG has non-standard PO node with ID \"%d\".\n", pObj->Id );
+                return 0;
+            }
+            continue;
+        }
+        if ( Ivy_ObjIsBuf(pObj) )
+        {
+            if ( Ivy_ObjFanin1(pObj) )
+            {
+                printf( "Ivy_ManCheck: The buffer with ID \"%d\" contains second fanin.\n", pObj->Id );
+                return 0;
+            }
+            continue;
+        }
+        if ( Ivy_ObjIsLatch(pObj) )
+        {
+            if ( Ivy_ObjFanin1(pObj) )
+            {
+                printf( "Ivy_ManCheck: The latch with ID \"%d\" contains second fanin.\n", pObj->Id );
+                return 0;
+            }
+            if ( Ivy_ObjInit(pObj) == IVY_INIT_NONE )
+            {
+                printf( "Ivy_ManCheck: The latch with ID \"%d\" does not have initial state.\n", pObj->Id );
+                return 0;
+            }
+            pObj2 = Ivy_TableLookup( p, pObj );
+            if ( pObj2 != pObj )
+                printf( "Ivy_ManCheck: Latch with ID \"%d\" is not in the structural hashing table.\n", pObj->Id );
+                continue;
+        }
+        // consider the AND node
+        if ( !Ivy_ObjFanin0(pObj) || !Ivy_ObjFanin1(pObj) )
+        {
+            printf( "Ivy_ManCheck: The AIG has internal node \"%d\" with a NULL fanin.\n", pObj->Id );
+            return 0;
+        }
+        if ( Ivy_ObjFaninId0(pObj) >= Ivy_ObjFaninId1(pObj) )
+        {
+            printf( "Ivy_ManCheck: The AIG has node \"%d\" with a wrong ordering of fanins.\n", pObj->Id );
+            return 0;
+        }
+        if ( Ivy_ObjLevel(pObj) != Ivy_ObjLevelNew(pObj) )
+            printf( "Ivy_ManCheck: Node with ID \"%d\" has level %d but should have level %d.\n", pObj->Id, Ivy_ObjLevel(pObj), Ivy_ObjLevelNew(pObj) );
+        pObj2 = Ivy_TableLookup( p, pObj );
+        if ( pObj2 != pObj )
+            printf( "Ivy_ManCheck: Node with ID \"%d\" is not in the structural hashing table.\n", pObj->Id );
+        if ( Ivy_ObjRefs(pObj) == 0 )
+            printf( "Ivy_ManCheck: Node with ID \"%d\" has no fanouts.\n", pObj->Id );
+        // check fanouts
+        if ( p->fFanout && Ivy_ObjRefs(pObj) != Ivy_ObjFanoutNum(p, pObj) )
+            printf( "Ivy_ManCheck: Node with ID \"%d\" has mismatch between the number of fanouts and refs.\n", pObj->Id );
+    }
+    // count the number of nodes in the table
+    if ( Ivy_TableCountEntries(p) != Ivy_ManAndNum(p) + Ivy_ManExorNum(p) + Ivy_ManLatchNum(p) )
+    {
+        printf( "Ivy_ManCheck: The number of nodes in the structural hashing table is wrong.\n" );
+        return 0;
+    }
+//    if ( !Ivy_ManCheckFanouts(p) )
+//        return 0;
+    if ( !Ivy_ManIsAcyclic(p) )
+        return 0;
+    return 1; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the fanouts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManCheckFanoutNums( Ivy_Man_t * p )
+{
+    Ivy_Obj_t * pObj;
+    int i, Counter = 0;
+    Ivy_ManForEachObj( p, pObj, i )
+        if ( Ivy_ObjIsNode(pObj) )
+            Counter += (Ivy_ObjRefs(pObj) == 0);
+    if ( Counter )
+        printf( "Sequential AIG has %d dangling nodes.\n", Counter );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the fanouts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManCheckFanouts( Ivy_Man_t * p )
+{
+    Vec_Ptr_t * vFanouts;
+    Ivy_Obj_t * pObj, * pFanout, * pFanin;
+    int i, k, RetValue = 1;
+    if ( !p->fFanout )
+        return 1;
+    vFanouts = Vec_PtrAlloc( 100 );
+    // make sure every fanin is a fanout
+    Ivy_ManForEachObj( p, pObj, i )
+    {
+        pFanin = Ivy_ObjFanin0(pObj);
+        if ( pFanin == NULL )
+            continue;
+        Ivy_ObjForEachFanout( p, pFanin, vFanouts, pFanout, k )
+            if ( pFanout == pObj )
+                break;
+        if ( k == Vec_PtrSize(vFanouts) )
+        {
+            printf( "Node %d is a fanin of node %d but the fanout is not there.\n", pFanin->Id, pObj->Id );
+            RetValue = 0;
+        }
+
+        pFanin = Ivy_ObjFanin1(pObj);
+        if ( pFanin == NULL )
+            continue;
+        Ivy_ObjForEachFanout( p, pFanin, vFanouts, pFanout, k )
+            if ( pFanout == pObj )
+                break;
+        if ( k == Vec_PtrSize(vFanouts) )
+        {
+            printf( "Node %d is a fanin of node %d but the fanout is not there.\n", pFanin->Id, pObj->Id );
+            RetValue = 0;
+        }
+        // check that the previous fanout has the same fanin
+        if ( pObj->pPrevFan0 )
+        {
+            if ( Ivy_ObjFanin0(pObj->pPrevFan0) != Ivy_ObjFanin0(pObj) && 
+                 Ivy_ObjFanin0(pObj->pPrevFan0) != Ivy_ObjFanin1(pObj) && 
+                 Ivy_ObjFanin1(pObj->pPrevFan0) != Ivy_ObjFanin0(pObj) && 
+                 Ivy_ObjFanin1(pObj->pPrevFan0) != Ivy_ObjFanin1(pObj) )
+            {
+                printf( "Node %d has prev %d without common fanin.\n", pObj->Id, pObj->pPrevFan0->Id );
+                RetValue = 0;
+            }
+        }
+        // check that the previous fanout has the same fanin
+        if ( pObj->pPrevFan1 )
+        {
+            if ( Ivy_ObjFanin0(pObj->pPrevFan1) != Ivy_ObjFanin0(pObj) && 
+                 Ivy_ObjFanin0(pObj->pPrevFan1) != Ivy_ObjFanin1(pObj) && 
+                 Ivy_ObjFanin1(pObj->pPrevFan1) != Ivy_ObjFanin0(pObj) && 
+                 Ivy_ObjFanin1(pObj->pPrevFan1) != Ivy_ObjFanin1(pObj) )
+            {
+                printf( "Node %d has prev %d without common fanin.\n", pObj->Id, pObj->pPrevFan1->Id );
+                RetValue = 0;
+            }
+        }
+    }
+    // make sure every fanout is a fanin
+    Ivy_ManForEachObj( p, pObj, i )
+    {
+        Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, k )
+            if ( Ivy_ObjFanin0(pFanout) != pObj && Ivy_ObjFanin1(pFanout) != pObj )
+            {
+                printf( "Node %d is a fanout of node %d but the fanin is not there.\n", pFanout->Id, pObj->Id );
+                RetValue = 0;
+            }
+    }
+    Vec_PtrFree( vFanouts );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks that each choice node has exactly one node with fanouts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManCheckChoices( Ivy_Man_t * p )
+{
+    Ivy_Obj_t * pObj, * pTemp;
+    int i;
+    Ivy_ManForEachObj( p->pHaig, pObj, i )
+    {
+        if ( Ivy_ObjRefs(pObj) == 0 )
+            continue;
+        // count the number of nodes in the loop
+        assert( !Ivy_IsComplement(pObj->pEquiv) );
+        for ( pTemp = pObj->pEquiv; pTemp && pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+            if ( Ivy_ObjRefs(pTemp) > 1 )
+                printf( "Node %d has member %d in its equiv class with %d fanouts.\n", pObj->Id, pTemp->Id, Ivy_ObjRefs(pTemp) );
+    }
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyCut.c b/abc-build/src/aig/ivy/ivyCut.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyCut.c
@@ -0,0 +1,995 @@
+/**CFile****************************************************************
+
+  FileName    [ivyCut.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Computes reconvergence driven sequential cut.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyCut.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Ivy_NodeCutHashValue( int NodeId )  { return 1 << (NodeId % 31); }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluate the cost of removing the node from the set of leaves.]
+
+  Description [Returns the number of new leaves that will be brought in.
+  Returns large number if the node cannot be removed from the set of leaves.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Ivy_NodeGetLeafCostOne( Ivy_Man_t * p, int Leaf, Vec_Int_t * vInside )
+{
+    Ivy_Obj_t * pNode;
+    int nLatches, FaninLeaf, Cost;
+    // make sure leaf is not a contant node
+    assert( Leaf > 0 ); 
+    // get the node
+    pNode = Ivy_ManObj( p, Ivy_LeafId(Leaf) );
+    // cannot expand over the PI node
+    if ( Ivy_ObjIsPi(pNode) || Ivy_ObjIsConst1(pNode) )
+        return 999;
+    // get the number of latches
+    nLatches = Ivy_LeafLat(Leaf) + Ivy_ObjIsLatch(pNode);
+    if ( nLatches > 15 )
+        return 999;
+    // get the first fanin
+    FaninLeaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pNode), nLatches );
+    Cost = FaninLeaf && (Vec_IntFind(vInside, FaninLeaf) == -1);
+    // quit if this is the one fanin node
+    if ( Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) )
+        return Cost;
+    assert( Ivy_ObjIsNode(pNode) );
+    // get the second fanin
+    FaninLeaf = Ivy_LeafCreate( Ivy_ObjFaninId1(pNode), nLatches );
+    Cost += FaninLeaf && (Vec_IntFind(vInside, FaninLeaf) == -1);
+    return Cost;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Builds reconvergence-driven cut by changing one leaf at a time.]
+
+  Description [This procedure looks at the current leaves and tries to change 
+  one leaf at a time in such a way that the cut grows as little as possible.
+  In evaluating the fanins, this procedure looks only at their immediate 
+  predecessors (this is why it is called a one-level construction procedure).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManSeqFindCut_int( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSizeLimit )
+{
+    Ivy_Obj_t * pNode;
+    int CostBest, CostCur, Leaf, LeafBest, Next, nLatches, i;
+    int LeavesBest[10];
+    int Counter;
+
+    // add random selection of the best fanin!!!
+
+    // find the best fanin
+    CostBest = 99;
+    LeafBest = -1;
+    Counter = -1;
+//printf( "Evaluating fanins of the cut:\n" );
+    Vec_IntForEachEntry( vFront, Leaf, i )
+    {
+        CostCur = Ivy_NodeGetLeafCostOne( p, Leaf, vInside );
+//printf( "    Fanin %s has cost %d.\n", Ivy_ObjName(pNode), CostCur );
+        if ( CostBest > CostCur )
+        {
+            CostBest = CostCur;
+            LeafBest = Leaf;
+            LeavesBest[0] = Leaf;
+            Counter = 1;
+        }
+        else if ( CostBest == CostCur )
+            LeavesBest[Counter++] = Leaf;
+
+        if ( CostBest <= 1 ) // can be if ( CostBest <= 1 )
+            break;
+    }
+    if ( CostBest == 99 )
+        return 0;
+//        return Ivy_NodeBuildCutLevelTwo_int( vInside, vFront, nFaninLimit );
+
+    assert( CostBest < 3 );
+    if ( Vec_IntSize(vFront) - 1 + CostBest > nSizeLimit )
+        return 0;
+//        return Ivy_NodeBuildCutLevelTwo_int( vInside, vFront, nFaninLimit );
+
+    assert( Counter > 0 );
+printf( "%d", Counter );
+
+    LeafBest = LeavesBest[rand() % Counter];
+
+    // remove the node from the array
+    assert( LeafBest >= 0 );
+    Vec_IntRemove( vFront, LeafBest );
+//printf( "Removing fanin %s.\n", Ivy_ObjName(pNode) );
+
+    // get the node and its latches
+    pNode = Ivy_ManObj( p, Ivy_LeafId(LeafBest) );
+    nLatches = Ivy_LeafLat(LeafBest) + Ivy_ObjIsLatch(pNode);
+    assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) );
+
+    // add the left child to the fanins
+    Next = Ivy_LeafCreate( Ivy_ObjFaninId0(pNode), nLatches );
+    if ( Next && Vec_IntFind(vInside, Next) == -1 )
+    {
+//printf( "Adding fanin %s.\n", Ivy_ObjName(pNext) );
+        Vec_IntPush( vFront, Next );
+        Vec_IntPush( vInside, Next );
+    }
+
+    // quit if this is the one fanin node
+    if ( Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) )
+        return 1;
+    assert( Ivy_ObjIsNode(pNode) );
+
+    // add the right child to the fanins
+    Next = Ivy_LeafCreate( Ivy_ObjFaninId1(pNode), nLatches );
+    if ( Next && Vec_IntFind(vInside, Next) == -1 )
+    {
+//printf( "Adding fanin %s.\n", Ivy_ObjName(pNext) );
+        Vec_IntPush( vFront, Next );
+        Vec_IntPush( vInside, Next );
+    }
+    assert( Vec_IntSize(vFront) <= nSizeLimit );
+    // keep doing this
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes one sequential cut of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManSeqFindCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSize )
+{
+    assert( !Ivy_IsComplement(pRoot) );
+    assert( Ivy_ObjIsNode(pRoot) );
+    assert( Ivy_ObjFaninId0(pRoot) );
+    assert( Ivy_ObjFaninId1(pRoot) );
+
+    // start the cut 
+    Vec_IntClear( vFront );
+    Vec_IntPush( vFront, Ivy_LeafCreate(Ivy_ObjFaninId0(pRoot), 0) );
+    Vec_IntPush( vFront, Ivy_LeafCreate(Ivy_ObjFaninId1(pRoot), 0) );
+
+    // start the visited nodes
+    Vec_IntClear( vInside );
+    Vec_IntPush( vInside, Ivy_LeafCreate(pRoot->Id, 0) );
+    Vec_IntPush( vInside, Ivy_LeafCreate(Ivy_ObjFaninId0(pRoot), 0) );
+    Vec_IntPush( vInside, Ivy_LeafCreate(Ivy_ObjFaninId1(pRoot), 0) );
+
+    // compute the cut
+    while ( Ivy_ManSeqFindCut_int( p, vFront, vInside, nSize ) );
+    assert( Vec_IntSize(vFront) <= nSize );
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computing Boolean cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManFindBoolCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume, Ivy_Obj_t * pPivot )
+{
+    int RetValue0, RetValue1;
+    if ( pObj == pPivot )
+    {
+        Vec_PtrPushUnique( vLeaves, pObj );
+        Vec_PtrPushUnique( vVolume, pObj );
+        return 1;        
+    }
+    if ( pObj->fMarkA )
+        return 0;
+
+//    assert( !Ivy_ObjIsCi(pObj) );
+    if ( Ivy_ObjIsCi(pObj) )
+        return 0;
+
+    if ( Ivy_ObjIsBuf(pObj) )
+    {
+        RetValue0 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin0(pObj), vLeaves, vVolume, pPivot );
+        if ( !RetValue0 )
+            return 0;
+        Vec_PtrPushUnique( vVolume, pObj );
+        return 1;
+    }
+    assert( Ivy_ObjIsNode(pObj) );
+    RetValue0 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin0(pObj), vLeaves, vVolume, pPivot );
+    RetValue1 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin1(pObj), vLeaves, vVolume, pPivot );
+    if ( !RetValue0 && !RetValue1 )
+        return 0;
+    // add new leaves
+    if ( !RetValue0 )
+    {
+        Vec_PtrPushUnique( vLeaves, Ivy_ObjFanin0(pObj) );
+        Vec_PtrPushUnique( vVolume, Ivy_ObjFanin0(pObj) );
+    }
+    if ( !RetValue1 )
+    {
+        Vec_PtrPushUnique( vLeaves, Ivy_ObjFanin1(pObj) );
+        Vec_PtrPushUnique( vVolume, Ivy_ObjFanin1(pObj) );
+    }
+    Vec_PtrPushUnique( vVolume, pObj );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the cost of one node (how many new nodes are added.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManFindBoolCutCost( Ivy_Obj_t * pObj )
+{
+    int Cost;
+    // make sure the node is in the construction zone
+    assert( pObj->fMarkA == 1 );  
+    // cannot expand over the PI node
+    if ( Ivy_ObjIsCi(pObj) )
+        return 999;
+    // always expand over the buffer
+    if ( Ivy_ObjIsBuf(pObj) )
+        return !Ivy_ObjFanin0(pObj)->fMarkA;
+    // get the cost of the cone
+    Cost = (!Ivy_ObjFanin0(pObj)->fMarkA) + (!Ivy_ObjFanin1(pObj)->fMarkA);
+    // return the number of nodes to be added to the leaves if this node is removed
+    return Cost;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computing Boolean cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManFindBoolCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVolume, Vec_Ptr_t * vLeaves )
+{
+    Ivy_Obj_t * pObj = NULL; // Suppress "might be used uninitialized"
+    Ivy_Obj_t * pFaninC, * pFanin0, * pFanin1, * pPivot;
+    int RetValue, LevelLimit, Lev, k;
+    assert( !Ivy_IsComplement(pRoot) );
+    // clear the frontier and collect the nodes
+    Vec_PtrClear( vFront );
+    Vec_PtrClear( vVolume );
+    if ( Ivy_ObjIsMuxType(pRoot) )
+        pFaninC = Ivy_ObjRecognizeMux( pRoot, &pFanin0, &pFanin1 );
+    else
+    {
+        pFaninC = NULL;
+        pFanin0 = Ivy_ObjFanin0(pRoot);
+        pFanin1 = Ivy_ObjFanin1(pRoot); 
+    }
+    // start cone A
+    pFanin0->fMarkA = 1;
+    Vec_PtrPush( vFront, pFanin0 );
+    Vec_PtrPush( vVolume, pFanin0 );
+    // start cone B
+    pFanin1->fMarkB = 1;
+    Vec_PtrPush( vFront, pFanin1 );
+    Vec_PtrPush( vVolume, pFanin1 );
+    // iteratively expand until the common node (pPivot) is found or limit is reached
+    assert( Ivy_ObjLevel(pRoot) == Ivy_ObjLevelNew(pRoot) );
+    pPivot = NULL;
+    LevelLimit = IVY_MAX( Ivy_ObjLevel(pRoot) - 10, 1 );
+    for ( Lev = Ivy_ObjLevel(pRoot) - 1; Lev >= LevelLimit; Lev-- )
+    {
+        while ( 1 )
+        {
+            // find the next node to expand on this level
+            Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, k )
+                if ( (int)pObj->Level == Lev )
+                    break;
+            if ( k == Vec_PtrSize(vFront) )
+                break;
+            assert( (int)pObj->Level <= Lev );
+            assert( pObj->fMarkA ^ pObj->fMarkB );
+            // remove the old node
+            Vec_PtrRemove( vFront, pObj );
+
+            // expand this node
+            pFanin0 = Ivy_ObjFanin0(pObj);
+            if ( !pFanin0->fMarkA && !pFanin0->fMarkB )
+            {
+                Vec_PtrPush( vFront, pFanin0 );
+                Vec_PtrPush( vVolume, pFanin0 );
+            }
+            // mark the new nodes
+            if ( pObj->fMarkA )
+                pFanin0->fMarkA = 1; 
+            if ( pObj->fMarkB )
+                pFanin0->fMarkB = 1; 
+
+            if ( Ivy_ObjIsBuf(pObj) )
+            {
+                if ( pFanin0->fMarkA && pFanin0->fMarkB )
+                {
+                    pPivot = pFanin0;
+                    break;
+                }
+                continue;
+            }
+
+            // expand this node
+            pFanin1 = Ivy_ObjFanin1(pObj); 
+            if ( !pFanin1->fMarkA && !pFanin1->fMarkB )
+            {
+                Vec_PtrPush( vFront, pFanin1 );
+                Vec_PtrPush( vVolume, pFanin1 );
+            }
+            // mark the new nodes
+            if ( pObj->fMarkA )
+                pFanin1->fMarkA = 1; 
+            if ( pObj->fMarkB )
+                pFanin1->fMarkB = 1; 
+
+            // consider if it is time to quit
+            if ( pFanin0->fMarkA && pFanin0->fMarkB )
+            {
+                pPivot = pFanin0;
+                break;
+            }
+            if ( pFanin1->fMarkA && pFanin1->fMarkB )
+            {
+                pPivot = pFanin1;
+                break;
+            }
+        }
+        if ( pPivot != NULL )
+            break;
+    }
+    if ( pPivot == NULL )
+        return 0;
+    // if the MUX control is defined, it should not be
+    if ( pFaninC && !pFaninC->fMarkA && !pFaninC->fMarkB )
+        Vec_PtrPush( vFront, pFaninC );
+    // clean the markings
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vVolume, pObj, k )
+        pObj->fMarkA = pObj->fMarkB = 0;
+
+    // mark the nodes on the frontier (including the pivot)
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, k )
+        pObj->fMarkA = 1;
+    // cut exists, collect all the nodes on the shortest path to the pivot
+    Vec_PtrClear( vLeaves );
+    Vec_PtrClear( vVolume );
+    RetValue = Ivy_ManFindBoolCut_rec( p, pRoot, vLeaves, vVolume, pPivot );
+    assert( RetValue == 1 );
+    // unmark the nodes on the frontier (including the pivot)
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, k )
+        pObj->fMarkA = 0;
+
+    // mark the nodes in the volume
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vVolume, pObj, k )
+        pObj->fMarkA = 1;
+    // expand the cut without increasing its size
+    while ( 1 )
+    {
+        Vec_PtrForEachEntry( Ivy_Obj_t *, vLeaves, pObj, k )
+            if ( Ivy_ManFindBoolCutCost(pObj) < 2 )
+                break;
+        if ( k == Vec_PtrSize(vLeaves) )
+            break;
+        // the node can be expanded
+        // remove the old node
+        Vec_PtrRemove( vLeaves, pObj );
+        // expand this node
+        pFanin0 = Ivy_ObjFanin0(pObj);
+        if ( !pFanin0->fMarkA )
+        {
+            pFanin0->fMarkA = 1;
+            Vec_PtrPush( vVolume, pFanin0 );
+            Vec_PtrPush( vLeaves, pFanin0 );
+        }
+        if ( Ivy_ObjIsBuf(pObj) )
+            continue;
+        // expand this node
+        pFanin1 = Ivy_ObjFanin1(pObj);
+        if ( !pFanin1->fMarkA )
+        {
+            pFanin1->fMarkA = 1;
+            Vec_PtrPush( vVolume, pFanin1 );
+            Vec_PtrPush( vLeaves, pFanin1 );
+        }        
+    }
+    // unmark the nodes in the volume
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vVolume, pObj, k )
+        pObj->fMarkA = 0;
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManTestCutsBool( Ivy_Man_t * p )
+{
+    Vec_Ptr_t * vFront, * vVolume, * vLeaves;
+    Ivy_Obj_t * pObj;//, * pTemp;
+    int i, RetValue;//, k;
+    vFront = Vec_PtrAlloc( 100 );
+    vVolume = Vec_PtrAlloc( 100 );
+    vLeaves = Vec_PtrAlloc( 100 );
+    Ivy_ManForEachObj( p, pObj, i )
+    {
+        if ( !Ivy_ObjIsNode(pObj) )
+            continue;
+        if ( Ivy_ObjIsMuxType(pObj) )
+        {
+            printf( "m" );
+            continue;
+        }
+        if ( Ivy_ObjIsExor(pObj) )
+            printf( "x" );
+        RetValue = Ivy_ManFindBoolCut( p, pObj, vFront, vVolume, vLeaves );
+        if ( RetValue == 0 )
+            printf( "- " );
+        else
+            printf( "%d ", Vec_PtrSize(vLeaves) );
+/*        
+        printf( "( " );
+        Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, k )
+            printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) );
+        printf( ")\n" );
+*/
+    }
+    printf( "\n" );
+    Vec_PtrFree( vFront );
+    Vec_PtrFree( vVolume );
+    Vec_PtrFree( vLeaves );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Find the hash value of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut )
+{
+    int i;
+//    for ( i = 1; i < pCut->nSize; i++ )
+//        assert( pCut->pArray[i-1] < pCut->pArray[i] );
+    pCut->uHash = 0;
+    for ( i = 0; i < pCut->nSize; i++ )
+        pCut->uHash |= (1 << (pCut->pArray[i] % 31));
+    return pCut->uHash;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes one node to the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Ivy_NodeCutShrink( Ivy_Cut_t * pCut, int iOld )
+{
+    int i, k;
+    for ( i = k = 0; i < pCut->nSize; i++ )
+        if ( pCut->pArray[i] != iOld )
+            pCut->pArray[k++] = pCut->pArray[i];
+    assert( k == pCut->nSize - 1 );
+    pCut->nSize--;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one node to the cut.]
+
+  Description [Returns 1 if the cuts is still okay.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Ivy_NodeCutExtend( Ivy_Cut_t * pCut, int iNew )
+{
+    int i;
+    for ( i = 0; i < pCut->nSize; i++ )
+        if ( pCut->pArray[i] == iNew )
+            return 1;
+    // check if there is room
+    if ( pCut->nSize == pCut->nSizeMax )
+        return 0;
+    // add the new one
+    for ( i = pCut->nSize - 1; i >= 0; i-- )
+        if ( pCut->pArray[i] > iNew )
+            pCut->pArray[i+1] = pCut->pArray[i];
+        else
+        {
+            assert( pCut->pArray[i] < iNew );
+            break;
+        }
+    pCut->pArray[i+1] = iNew;
+    pCut->nSize++;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the cut can be constructed; 0 otherwise.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Ivy_NodeCutPrescreen( Ivy_Cut_t * pCut, int Id0, int Id1 )
+{
+    int i;
+    if ( pCut->nSize < pCut->nSizeMax )
+        return 1;
+    for ( i = 0; i < pCut->nSize; i++ )
+        if ( pCut->pArray[i] == Id0 || pCut->pArray[i] == Id1 )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives new cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Ivy_NodeCutDeriveNew( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 )
+{
+    unsigned uHash = 0;
+    int i, k; 
+    assert( pCut->nSize > 0 );
+    assert( IdNew0 < IdNew1 );
+    for ( i = k = 0; i < pCut->nSize; i++ )
+    {
+        if ( pCut->pArray[i] == IdOld )
+            continue;
+        if ( IdNew0 <= pCut->pArray[i] )
+        {
+            if ( IdNew0 < pCut->pArray[i] )
+            {
+                pCutNew->pArray[ k++ ] = IdNew0;
+                uHash |= Ivy_NodeCutHashValue( IdNew0 );
+            }
+            IdNew0 = 0x7FFFFFFF;
+        }
+        if ( IdNew1 <= pCut->pArray[i] )
+        {
+            if ( IdNew1 < pCut->pArray[i] )
+            {
+                pCutNew->pArray[ k++ ] = IdNew1;
+                uHash |= Ivy_NodeCutHashValue( IdNew1 );
+            }
+            IdNew1 = 0x7FFFFFFF;
+        }
+        pCutNew->pArray[ k++ ] = pCut->pArray[i];
+        uHash |= Ivy_NodeCutHashValue( pCut->pArray[i] );
+    }
+    if ( IdNew0 < 0x7FFFFFFF )
+    {
+        pCutNew->pArray[ k++ ] = IdNew0;
+        uHash |= Ivy_NodeCutHashValue( IdNew0 );
+    }
+    if ( IdNew1 < 0x7FFFFFFF )
+    {
+        pCutNew->pArray[ k++ ] = IdNew1;
+        uHash |= Ivy_NodeCutHashValue( IdNew1 );
+    }
+    pCutNew->nSize = k;
+    pCutNew->uHash = uHash;
+    assert( pCutNew->nSize <= pCut->nSizeMax );
+//    for ( i = 1; i < pCutNew->nSize; i++ )
+//        assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check if the cut exists.]
+
+  Description [Returns 1 if the cut exists.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_NodeCutFindOrAdd( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew )
+{
+    Ivy_Cut_t * pCut;
+    int i, k;
+    assert( pCutNew->uHash );
+    // try to find the cut
+    for ( i = 0; i < pCutStore->nCuts; i++ )
+    {
+        pCut = pCutStore->pCuts + i;
+        if ( pCut->uHash == pCutNew->uHash && pCut->nSize == pCutNew->nSize )
+        {
+            for ( k = 0; k < pCutNew->nSize; k++ )
+                if ( pCut->pArray[k] != pCutNew->pArray[k] )
+                    break;
+            if ( k == pCutNew->nSize )
+                return 1;
+        }
+    }
+    assert( pCutStore->nCuts < pCutStore->nCutsMax );
+    // add the cut
+    pCut = pCutStore->pCuts + pCutStore->nCuts++;
+    *pCut = *pCutNew;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pDom is contained in pCut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut )
+{
+    int i, k;
+    for ( i = 0; i < pDom->nSize; i++ )
+    {
+        for ( k = 0; k < pCut->nSize; k++ )
+            if ( pDom->pArray[i] == pCut->pArray[k] )
+                break;
+        if ( k == pCut->nSize ) // node i in pDom is not contained in pCut
+            return 0;
+    }
+    // every node in pDom is contained in pCut
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check if the cut exists.]
+
+  Description [Returns 1 if the cut exists.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_NodeCutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew )
+{
+    Ivy_Cut_t * pCut;
+    int i, k;
+    assert( pCutNew->uHash );
+    // try to find the cut
+    for ( i = 0; i < pCutStore->nCuts; i++ )
+    {
+        pCut = pCutStore->pCuts + i;
+        if ( pCut->nSize == 0 )
+            continue;
+        if ( pCut->nSize == pCutNew->nSize )
+        {
+            if ( pCut->uHash == pCutNew->uHash )
+            {
+                for ( k = 0; k < pCutNew->nSize; k++ )
+                    if ( pCut->pArray[k] != pCutNew->pArray[k] )
+                        break;
+                if ( k == pCutNew->nSize )
+                    return 1;
+            }
+            continue;
+        }
+        if ( pCut->nSize < pCutNew->nSize )
+        {
+            // skip the non-contained cuts
+            if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash )
+                continue;
+            // check containment seriously
+            if ( Ivy_CutCheckDominance( pCut, pCutNew ) )
+                return 1;
+            continue;
+        }
+        // check potential containment of other cut
+
+        // skip the non-contained cuts
+        if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash )
+            continue;
+        // check containment seriously
+        if ( Ivy_CutCheckDominance( pCutNew, pCut ) )
+        {
+            // remove the current cut
+//            --pCutStore->nCuts;
+//            for ( k = i; k < pCutStore->nCuts; k++ )
+//                pCutStore->pCuts[k] = pCutStore->pCuts[k+1];
+//            i--;
+            pCut->nSize = 0;
+        }
+    }
+    assert( pCutStore->nCuts < pCutStore->nCutsMax );
+    // add the cut
+    pCut = pCutStore->pCuts + pCutStore->nCuts++;
+    *pCut = *pCutNew;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_NodeCompactCuts( Ivy_Store_t * pCutStore )
+{
+    Ivy_Cut_t * pCut;
+    int i, k;
+    for ( i = k = 0; i < pCutStore->nCuts; i++ )
+    {
+        pCut = pCutStore->pCuts + i;
+        if ( pCut->nSize == 0 )
+            continue;
+        pCutStore->pCuts[k++] = *pCut;
+    }
+    pCutStore->nCuts = k;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_NodePrintCut( Ivy_Cut_t * pCut )
+{
+    int i;
+    assert( pCut->nSize > 0 );
+    printf( "%d : {", pCut->nSize );
+    for ( i = 0; i < pCut->nSize; i++ )
+        printf( " %d", pCut->pArray[i] );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_NodePrintCuts( Ivy_Store_t * pCutStore )
+{
+    int i;
+    printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] );
+    for ( i = 0; i < pCutStore->nCuts; i++ )
+        Ivy_NodePrintCut( pCutStore->pCuts + i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Ivy_Obj_t * Ivy_ObjRealFanin( Ivy_Obj_t * pObj )
+{
+    if ( !Ivy_ObjIsBuf(pObj) )
+        return pObj;
+    return Ivy_ObjRealFanin( Ivy_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves )
+{
+    static Ivy_Store_t CutStore, * pCutStore = &CutStore;
+    Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut;
+    Ivy_Obj_t * pLeaf;
+    int i, k, iLeaf0, iLeaf1;
+
+    assert( nLeaves <= IVY_CUT_INPUT );
+
+    // start the structure
+    pCutStore->nCuts = 0;
+    pCutStore->nCutsMax = IVY_CUT_LIMIT;
+    // start the trivial cut
+    pCutNew->uHash = 0;
+    pCutNew->nSize = 1;
+    pCutNew->nSizeMax = nLeaves;
+    pCutNew->pArray[0] = pObj->Id;
+    Ivy_NodeCutHash( pCutNew );
+    // add the trivial cut
+    Ivy_NodeCutFindOrAdd( pCutStore, pCutNew );
+    assert( pCutStore->nCuts == 1 );
+
+    // explore the cuts
+    for ( i = 0; i < pCutStore->nCuts; i++ )
+    {
+        // expand this cut
+        pCut = pCutStore->pCuts + i;
+        if ( pCut->nSize == 0 )
+            continue;
+        for ( k = 0; k < pCut->nSize; k++ )
+        {
+            pLeaf = Ivy_ManObj( p, pCut->pArray[k] );
+            if ( Ivy_ObjIsCi(pLeaf) )
+                continue;
+/*
+            *pCutNew = *pCut;
+            Ivy_NodeCutShrink( pCutNew, pLeaf->Id );
+            if ( !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId0(pLeaf) ) )
+                continue;
+            if ( Ivy_ObjIsNode(pLeaf) && !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId1(pLeaf) ) )
+                continue;
+            Ivy_NodeCutHash( pCutNew );
+*/
+            iLeaf0 = Ivy_ObjId( Ivy_ObjRealFanin(Ivy_ObjFanin0(pLeaf)) );
+            iLeaf1 = Ivy_ObjId( Ivy_ObjRealFanin(Ivy_ObjFanin1(pLeaf)) );
+//            if ( iLeaf0 == iLeaf1 ) // strange situation observed on Jan 18, 2007
+//                continue;
+            if ( !Ivy_NodeCutPrescreen( pCut, iLeaf0, iLeaf1 ) )
+                continue;
+            if ( iLeaf0 > iLeaf1 )
+                Ivy_NodeCutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf1, iLeaf0 );
+            else
+                Ivy_NodeCutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf0, iLeaf1 );
+            Ivy_NodeCutFindOrAddFilter( pCutStore, pCutNew );
+            if ( pCutStore->nCuts == IVY_CUT_LIMIT )
+                break;
+        }
+        if ( pCutStore->nCuts == IVY_CUT_LIMIT )
+            break;
+    }
+    Ivy_NodeCompactCuts( pCutStore );
+//    Ivy_NodePrintCuts( pCutStore );
+    return pCutStore;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManTestCutsAll( Ivy_Man_t * p )
+{
+    Ivy_Obj_t * pObj;
+    int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver;
+    abctime clk = Abc_Clock();
+    nNodeTotal = nNodeOver = 0;
+    nCutsTotal = -Ivy_ManNodeNum(p);
+    Ivy_ManForEachObj( p, pObj, i )
+    {
+        if ( !Ivy_ObjIsNode(pObj) )
+            continue;
+        nCutsCut    = Ivy_NodeFindCutsAll( p, pObj, 5 )->nCuts;
+        nCutsTotal += nCutsCut;
+        nNodeOver  += (nCutsCut == IVY_CUT_LIMIT);
+        nNodeTotal++;
+    }
+    printf( "Total cuts = %6d. Trivial = %6d.   Nodes = %6d. Satur = %6d.  ", 
+        nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyCutTrav.c b/abc-build/src/aig/ivy/ivyCutTrav.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyCutTrav.c
@@ -0,0 +1,478 @@
+/**CFile****************************************************************
+
+  FileName    [ivyCutTrav.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyCutTrav.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId );
+static void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront );
+static void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, int nLeaves, int nWords, Vec_Int_t * vStore );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes cuts for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Store_t * Ivy_NodeFindCutsTravAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves, int nNodeLimit, 
+                                      Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront, Vec_Int_t * vStore, Vec_Vec_t * vBitCuts )
+{
+    static Ivy_Store_t CutStore, * pCutStore = &CutStore;
+    Vec_Ptr_t * vCuts, * vCuts0, * vCuts1;
+    unsigned * pBitCut;
+    Ivy_Obj_t * pLeaf;
+    Ivy_Cut_t * pCut;
+    int i, k, nWords, nNodes;
+
+    assert( nLeaves <= IVY_CUT_INPUT );
+
+    // find the given number of nodes in the TFI
+    Ivy_NodeComputeVolume( pObj, nNodeLimit - 1, vNodes, vFront );
+    nNodes = Vec_PtrSize(vNodes);
+//    assert( nNodes <= nNodeLimit );
+
+    // make sure vBitCuts has enough room
+    Vec_VecExpand( vBitCuts, nNodes-1 );
+    Vec_VecClear( vBitCuts );
+
+    // prepare the memory manager
+    Vec_IntClear( vStore );
+    Vec_IntGrow( vStore, 64000 );
+
+    // set elementary cuts for the leaves
+    nWords = Extra_BitWordNum( nNodes );
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pLeaf, i )
+    {
+        assert( Ivy_ObjTravId(pLeaf) < nNodes );
+        // get the new bitcut
+        pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) );
+        // set it as the cut of this leaf
+        Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut );
+    }
+
+    // compute the cuts for each node
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pLeaf, i )
+    {
+        // skip the leaves
+        vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pLeaf) );
+        if ( Vec_PtrSize(vCuts) > 0 )
+            continue;
+        // add elementary cut
+        pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) );
+        // set it as the cut of this leaf
+        Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut );
+        // get the fanin cuts
+        vCuts0 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin0(pLeaf) ) );
+        vCuts1 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin1(pLeaf) ) );
+        assert( Vec_PtrSize(vCuts0) > 0 );
+        assert( Vec_PtrSize(vCuts1) > 0 );
+        // merge the cuts
+        Ivy_NodeFindCutsMerge( vCuts0, vCuts1, vCuts, nLeaves, nWords, vStore );
+    }
+
+    // start the structure
+    pCutStore->nCuts = 0;
+    pCutStore->nCutsMax = IVY_CUT_LIMIT;
+    // collect the cuts of the root node
+    vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pObj) );
+    Vec_PtrForEachEntry( unsigned *, vCuts, pBitCut, i )
+    {
+        pCut = pCutStore->pCuts + pCutStore->nCuts++;
+        pCut->nSize = 0;
+        pCut->nSizeMax = nLeaves;
+        pCut->uHash = 0;
+        for ( k = 0; k < nNodes; k++ )
+            if ( Extra_TruthHasBit(pBitCut, k) )
+                pCut->pArray[ pCut->nSize++ ] = Ivy_ObjId( (Ivy_Obj_t *)Vec_PtrEntry(vNodes, k) );
+        assert( pCut->nSize <= nLeaves );
+        if ( pCutStore->nCuts == pCutStore->nCutsMax )
+            break;
+    }
+
+    // clean the travIds
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pLeaf, i )
+        pLeaf->TravId = 0;
+    return pCutStore;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates elementary bit-cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId )
+{
+    unsigned * pBitCut;
+    pBitCut = Vec_IntFetch( vStore, nWords );
+    memset( pBitCut, 0, 4 * nWords );
+    Extra_TruthSetBit( pBitCut, NodeId );
+    return pBitCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the node by level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_CompareNodesByLevel( Ivy_Obj_t ** ppObj1, Ivy_Obj_t ** ppObj2 )
+{
+    Ivy_Obj_t * pObj1 = *ppObj1;
+    Ivy_Obj_t * pObj2 = *ppObj2;
+    if ( pObj1->Level < pObj2->Level )
+        return -1;
+    if ( pObj1->Level > pObj2->Level )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Mark all nodes up to the given depth.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_NodeComputeVolumeTrav1_rec( Ivy_Obj_t * pObj, int Depth )
+{
+    if ( Ivy_ObjIsCi(pObj) || Depth == 0 )
+        return;
+    Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin0(pObj), Depth - 1 );
+    Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin1(pObj), Depth - 1 );
+    pObj->fMarkA = 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect the marked nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_NodeComputeVolumeTrav2_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    if ( !pObj->fMarkA )
+        return;
+    Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin0(pObj), vNodes );
+    Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin1(pObj), vNodes );
+    Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront )
+{
+    Ivy_Obj_t * pTemp, * pFanin;
+    int i, nNodes;
+    // mark nodes up to the given depth
+    Ivy_NodeComputeVolumeTrav1_rec( pObj, 6 );
+    // collect the marked nodes
+    Vec_PtrClear( vFront );
+    Ivy_NodeComputeVolumeTrav2_rec( pObj, vFront );
+    // find the fanins that are not marked
+    Vec_PtrClear( vNodes );
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i )
+    {
+        pFanin = Ivy_ObjFanin0(pTemp);
+        if ( !pFanin->fMarkA )
+        {
+            pFanin->fMarkA = 1;
+            Vec_PtrPush( vNodes, pFanin );
+        }
+        pFanin = Ivy_ObjFanin1(pTemp);
+        if ( !pFanin->fMarkA )
+        {
+            pFanin->fMarkA = 1;
+            Vec_PtrPush( vNodes, pFanin );
+        }
+    }
+    // remember the number of nodes in the frontier
+    nNodes = Vec_PtrSize( vNodes );
+    // add the remaining nodes
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i )
+        Vec_PtrPush( vNodes, pTemp );
+    // unmark the nodes
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pTemp, i )
+    {
+        pTemp->fMarkA = 0;
+        pTemp->TravId = i;
+    }
+    // collect the frontier nodes
+    Vec_PtrClear( vFront );
+    Vec_PtrForEachEntryStop( Ivy_Obj_t *, vNodes, pTemp, i, nNodes )
+        Vec_PtrPush( vFront, pTemp );
+//    printf( "%d ", Vec_PtrSize(vNodes) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_NodeComputeVolume2( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront )
+{
+    Ivy_Obj_t * pLeaf, * pPivot, * pFanin;
+    int LevelMax, i;
+    assert( Ivy_ObjIsNode(pObj) );
+    // clear arrays
+    Vec_PtrClear( vNodes );
+    Vec_PtrClear( vFront );
+    // add the root
+    pObj->fMarkA = 1;
+    Vec_PtrPush( vNodes, pObj );
+    Vec_PtrPush( vFront, pObj );
+    // expand node with maximum level
+    LevelMax = pObj->Level;
+    do {
+        // get the node to expand
+        pPivot = NULL;
+        Vec_PtrForEachEntryReverse( Ivy_Obj_t *, vFront, pLeaf, i )
+        {
+            if ( (int)pLeaf->Level == LevelMax )
+            {
+                pPivot = pLeaf;
+                break;
+            }
+        }
+        // decrease level if we did not find the node
+        if ( pPivot == NULL )
+        {
+            if ( --LevelMax == 0 )
+                break;
+            continue;
+        }
+        // the node to expand is found
+        // remove it from frontier
+        Vec_PtrRemove( vFront, pPivot );
+        // add fanins
+        pFanin = Ivy_ObjFanin0(pPivot); 
+        if ( !pFanin->fMarkA )
+        {
+            pFanin->fMarkA = 1;
+            Vec_PtrPush( vNodes, pFanin );
+            Vec_PtrPush( vFront, pFanin );
+        }
+        pFanin = Ivy_ObjFanin1(pPivot); 
+        if ( pFanin && !pFanin->fMarkA )
+        {
+            pFanin->fMarkA = 1;
+            Vec_PtrPush( vNodes, pFanin );
+            Vec_PtrPush( vFront, pFanin );
+        }
+        // quit if we collected enough nodes
+    } while ( Vec_PtrSize(vNodes) < nNodeLimit );
+
+    // sort nodes by level
+    Vec_PtrSort( vNodes, (int (*)(void))Ivy_CompareNodesByLevel );
+    // make sure the nodes are ordered in the increasing number of levels
+    pFanin = (Ivy_Obj_t *)Vec_PtrEntry( vNodes, 0 );
+    pPivot = (Ivy_Obj_t *)Vec_PtrEntryLast( vNodes );
+    assert( pFanin->Level <= pPivot->Level );
+
+    // clean the marks and remember node numbers in the TravId
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pFanin, i )
+    {
+        pFanin->fMarkA = 0;
+        pFanin->TravId = i;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Extra_TruthOrWords( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nWords )
+{
+    int w;
+    for ( w = nWords-1; w >= 0; w-- )
+        pOut[w] = pIn0[w] | pIn1[w];
+}
+static inline int Extra_TruthIsImplyWords( unsigned * pIn1, unsigned * pIn2, int nWords )
+{
+    int w;
+    for ( w = nWords-1; w >= 0; w-- )
+        if ( pIn1[w] & ~pIn2[w] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two sets of bit-cuts at a node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, 
+                           int nLeaves, int nWords, Vec_Int_t * vStore )
+{
+    unsigned * pBitCut, * pBitCut0, * pBitCut1, * pBitCutTest;
+    int i, k, c, w, Counter;
+    // iterate through the cut pairs
+    Vec_PtrForEachEntry( unsigned *, vCuts0, pBitCut0, i )
+    Vec_PtrForEachEntry( unsigned *, vCuts1, pBitCut1, k )
+    {
+        // skip infeasible cuts
+        Counter = 0;
+        for ( w = 0; w < nWords; w++ )
+        {
+            Counter += Extra_WordCountOnes( pBitCut0[w] | pBitCut1[w] );
+            if ( Counter > nLeaves )
+                break;
+        }
+        if ( Counter > nLeaves )
+            continue;
+        // the new cut is feasible - create it
+        pBitCutTest = Vec_IntFetch( vStore, nWords );
+        Extra_TruthOrWords( pBitCutTest, pBitCut0, pBitCut1, nWords );
+        // filter contained cuts; try to find containing cut
+        w = 0;
+        Vec_PtrForEachEntry( unsigned *, vCuts, pBitCut, c )
+        {
+            if ( Extra_TruthIsImplyWords( pBitCut, pBitCutTest, nWords ) )
+                break;
+            if ( Extra_TruthIsImplyWords( pBitCutTest, pBitCut, nWords ) )
+                continue;
+            Vec_PtrWriteEntry( vCuts, w++, pBitCut );
+        }
+        if ( c != Vec_PtrSize(vCuts) )
+            continue;
+        Vec_PtrShrink( vCuts, w );
+        // add the cut
+        Vec_PtrPush( vCuts, pBitCutTest );
+    }
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Compute the set of all cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManTestCutsTravAll( Ivy_Man_t * p )
+{
+    Ivy_Store_t * pStore;
+    Ivy_Obj_t * pObj;
+    Vec_Ptr_t * vNodes, * vFront;
+    Vec_Int_t * vStore;
+    Vec_Vec_t * vBitCuts;
+    int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver;
+    abctime clk = Abc_Clock();
+
+    vNodes = Vec_PtrAlloc( 100 );
+    vFront = Vec_PtrAlloc( 100 );
+    vStore = Vec_IntAlloc( 100 );
+    vBitCuts = Vec_VecAlloc( 100 );
+
+    nNodeTotal = nNodeOver = 0;
+    nCutsTotal = -Ivy_ManNodeNum(p);
+    Ivy_ManForEachObj( p, pObj, i )
+    {
+        if ( !Ivy_ObjIsNode(pObj) )
+            continue;
+        pStore = Ivy_NodeFindCutsTravAll( p, pObj, 4, 60, vNodes, vFront, vStore, vBitCuts );
+        nCutsCut    = pStore->nCuts;
+        nCutsTotal += nCutsCut;
+        nNodeOver  += (nCutsCut == IVY_CUT_LIMIT);
+        nNodeTotal++;
+    }
+    printf( "Total cuts = %6d. Trivial = %6d.   Nodes = %6d. Satur = %6d.  ", 
+        nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+
+    Vec_PtrFree( vNodes );
+    Vec_PtrFree( vFront );
+    Vec_IntFree( vStore );
+    Vec_VecFree( vBitCuts );
+
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyDfs.c b/abc-build/src/aig/ivy/ivyDfs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyDfs.c
@@ -0,0 +1,498 @@
+/**CFile****************************************************************
+
+  FileName    [ivyDfs.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [DFS collection procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyDfs.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManDfs_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Int_t * vNodes )
+{
+    if ( Ivy_ObjIsMarkA(pObj) )
+        return;
+    Ivy_ObjSetMarkA(pObj);
+    if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) )
+    {
+        if ( p->pHaig == NULL && pObj->pEquiv )
+            Ivy_ManDfs_rec( p, Ivy_Regular(pObj->pEquiv), vNodes );
+        return;
+    }
+//printf( "visiting node %d\n", pObj->Id );
+/*
+    if ( pObj->Id == 87 || pObj->Id == 90 )
+    {
+        int y = 0;
+    }
+*/
+    assert( Ivy_ObjIsBuf(pObj) || Ivy_ObjIsAnd(pObj) || Ivy_ObjIsExor(pObj) );
+    Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes );
+    if ( !Ivy_ObjIsBuf(pObj) )
+        Ivy_ManDfs_rec( p, Ivy_ObjFanin1(pObj), vNodes );
+    if ( p->pHaig == NULL && pObj->pEquiv )
+        Ivy_ManDfs_rec( p, Ivy_Regular(pObj->pEquiv), vNodes );
+    Vec_IntPush( vNodes, pObj->Id );
+
+//printf( "adding node %d with fanins %d and %d and equiv %d (refs = %d)\n", 
+//       pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id, 
+//       pObj->pEquiv? Ivy_Regular(pObj->pEquiv)->Id: -1, Ivy_ObjRefs(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects AND/EXOR nodes in the DFS order from CIs to COs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Ivy_ManDfs( Ivy_Man_t * p )
+{
+    Vec_Int_t * vNodes;
+    Ivy_Obj_t * pObj;
+    int i;
+    assert( Ivy_ManLatchNum(p) == 0 );
+    // make sure the nodes are not marked
+    Ivy_ManForEachObj( p, pObj, i )
+        assert( !pObj->fMarkA && !pObj->fMarkB );
+    // collect the nodes
+    vNodes = Vec_IntAlloc( Ivy_ManNodeNum(p) );
+    Ivy_ManForEachPo( p, pObj, i )
+        Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes );
+    // unmark the collected nodes
+//    Ivy_ManForEachNodeVec( p, vNodes, pObj, i )
+//        Ivy_ObjClearMarkA(pObj);
+    Ivy_ManForEachObj( p, pObj, i )
+        Ivy_ObjClearMarkA(pObj);
+    // make sure network does not have dangling nodes
+    assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects AND/EXOR nodes in the DFS order from CIs to COs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Ivy_ManDfsSeq( Ivy_Man_t * p, Vec_Int_t ** pvLatches )
+{
+    Vec_Int_t * vNodes, * vLatches;
+    Ivy_Obj_t * pObj;
+    int i;
+//    assert( Ivy_ManLatchNum(p) > 0 );
+    // make sure the nodes are not marked
+    Ivy_ManForEachObj( p, pObj, i )
+        assert( !pObj->fMarkA && !pObj->fMarkB );
+    // collect the latches
+    vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) );
+    Ivy_ManForEachLatch( p, pObj, i )
+        Vec_IntPush( vLatches, pObj->Id );
+    // collect the nodes
+    vNodes = Vec_IntAlloc( Ivy_ManNodeNum(p) );
+    Ivy_ManForEachPo( p, pObj, i )
+        Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes );
+    Ivy_ManForEachNodeVec( p, vLatches, pObj, i )
+        Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes );
+    // unmark the collected nodes
+//    Ivy_ManForEachNodeVec( p, vNodes, pObj, i )
+//        Ivy_ObjClearMarkA(pObj);
+    Ivy_ManForEachObj( p, pObj, i )
+        Ivy_ObjClearMarkA(pObj);
+    // make sure network does not have dangling nodes
+//    assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) );
+
+// temporary!!!
+
+    if ( pvLatches == NULL )
+        Vec_IntFree( vLatches );
+    else
+        *pvLatches = vLatches;
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes in the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManCollectCone_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vCone )
+{
+    if ( pObj->fMarkA )
+        return;
+    if ( Ivy_ObjIsBuf(pObj) )
+    {
+        Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone );
+        Vec_PtrPush( vCone, pObj );
+        return;
+    }
+    assert( Ivy_ObjIsNode(pObj) );
+    Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone );
+    Ivy_ManCollectCone_rec( Ivy_ObjFanin1(pObj), vCone );
+    Vec_PtrPushUnique( vCone, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes in the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone )
+{
+    Ivy_Obj_t * pTemp;
+    int i;
+    assert( !Ivy_IsComplement(pObj) );
+    assert( Ivy_ObjIsNode(pObj) );
+    // mark the nodes
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i )
+        Ivy_Regular(pTemp)->fMarkA = 1;
+    assert( pObj->fMarkA == 0 );
+    // collect the cone
+    Vec_PtrClear( vCone );
+    Ivy_ManCollectCone_rec( pObj, vCone );
+    // unmark the nodes
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i )
+        Ivy_Regular(pTemp)->fMarkA = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the nodes by level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Ivy_ManLevelize( Ivy_Man_t * p )
+{
+    Vec_Vec_t * vNodes;
+    Ivy_Obj_t * pObj;
+    int i;
+    vNodes = Vec_VecAlloc( 100 );
+    Ivy_ManForEachObj( p, pObj, i )
+    {
+        assert( !Ivy_ObjIsBuf(pObj) );
+        if ( Ivy_ObjIsNode(pObj) )
+            Vec_VecPush( vNodes, pObj->Level, pObj );
+    }
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes required levels for each node.]
+
+  Description [Assumes topological ordering of the nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Ivy_ManRequiredLevels( Ivy_Man_t * p )
+{
+    Ivy_Obj_t * pObj;
+    Vec_Int_t * vLevelsR;
+    Vec_Vec_t * vNodes;
+    int i, k, Level, LevelMax;
+    assert( p->vRequired == NULL );
+    // start the required times
+    vLevelsR = Vec_IntStart( Ivy_ManObjIdMax(p) + 1 );
+    // iterate through the nodes in the reverse order
+    vNodes = Ivy_ManLevelize( p );
+    Vec_VecForEachEntryReverseReverse( Ivy_Obj_t *, vNodes, pObj, i, k )
+    {
+        Level = Vec_IntEntry( vLevelsR, pObj->Id ) + 1 + Ivy_ObjIsExor(pObj);
+        if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId0(pObj) ) < Level )
+            Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId0(pObj), Level );
+        if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId1(pObj) ) < Level )
+            Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId1(pObj), Level );
+    }
+    Vec_VecFree( vNodes );
+    // convert it into the required times
+    LevelMax = Ivy_ManLevels( p );
+//printf( "max %5d\n",LevelMax );
+    Ivy_ManForEachObj( p, pObj, i )
+    {
+        Level = Vec_IntEntry( vLevelsR, pObj->Id );
+        Vec_IntWriteEntry( vLevelsR, pObj->Id, LevelMax - Level );
+//printf( "%5d : %5d %5d\n", pObj->Id, Level, LevelMax - Level );
+    }
+    p->vRequired = vLevelsR;
+    return vLevelsR;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively detects combinational loops.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManIsAcyclic_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+    // skip the node if it is already visited
+    if ( Ivy_ObjIsTravIdPrevious(p, pObj) )
+        return 1;
+    // check if the node is part of the combinational loop
+    if ( Ivy_ObjIsTravIdCurrent(p, pObj) )
+    {
+        fprintf( stdout, "Manager contains combinational loop!\n" );
+        fprintf( stdout, "Node \"%d\" is encountered twice on the following path:\n",  Ivy_ObjId(pObj) );
+        fprintf( stdout, " %d",  Ivy_ObjId(pObj) );
+        return 0;
+    }
+    // mark this node as a node on the current path
+    Ivy_ObjSetTravIdCurrent( p, pObj );
+    // explore equivalent nodes if pObj is the main node
+    if ( p->pHaig == NULL && pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 )
+    {
+        Ivy_Obj_t * pTemp;
+        assert( !Ivy_IsComplement(pObj->pEquiv) );
+        for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+        {
+            // traverse the fanin's cone searching for the loop
+            if ( !Ivy_ManIsAcyclic_rec(p, pTemp) )
+            {
+                // return as soon as the loop is detected
+                fprintf( stdout, " -> (%d", Ivy_ObjId(pObj) );
+                for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+                    fprintf( stdout, " %d", Ivy_ObjId(pTemp) );
+                fprintf( stdout, ")" );
+                return 0; 
+            }
+        }
+    }
+    // quite if it is a CI node
+    if ( Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) )
+    {
+        // mark this node as a visited node
+        Ivy_ObjSetTravIdPrevious( p, pObj );
+        return 1;
+    }
+    assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) );
+    // traverse the fanin's cone searching for the loop
+    if ( !Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin0(pObj)) )
+    {
+        // return as soon as the loop is detected
+        fprintf( stdout, " -> %d", Ivy_ObjId(pObj) );
+        return 0;
+    }
+    // traverse the fanin's cone searching for the loop
+    if ( Ivy_ObjIsNode(pObj) && !Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin1(pObj)) )
+    {
+        // return as soon as the loop is detected
+        fprintf( stdout, " -> %d", Ivy_ObjId(pObj) );
+        return 0;
+    }
+    // mark this node as a visited node
+    Ivy_ObjSetTravIdPrevious( p, pObj );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detects combinational loops.]
+
+  Description [This procedure is based on the idea suggested by Donald Chai. 
+  As we traverse the network and visit the nodes, we need to distinquish 
+  three types of nodes: (1) those that are visited for the first time, 
+  (2) those that have been visited in this traversal but are currently not 
+  on the traversal path, (3) those that have been visited and are currently 
+  on the travesal path. When the node of type (3) is encountered, it means 
+  that there is a combinational loop. To mark the three types of nodes, 
+  two new values of the traversal IDs are used.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManIsAcyclic( Ivy_Man_t * p )
+{
+    Ivy_Obj_t * pObj;
+    int fAcyclic, i;
+    // set the traversal ID for this DFS ordering
+    Ivy_ManIncrementTravId( p );   
+    Ivy_ManIncrementTravId( p );   
+    // pObj->TravId == pNet->nTravIds      means "pObj is on the path"
+    // pObj->TravId == pNet->nTravIds - 1  means "pObj is visited but is not on the path"
+    // pObj->TravId <  pNet->nTravIds - 1  means "pObj is not visited"
+    // traverse the network to detect cycles
+    fAcyclic = 1;
+    Ivy_ManForEachCo( p, pObj, i )
+    {
+        // traverse the output logic cone
+        if ( (fAcyclic = Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin0(pObj))) )
+            continue;
+        // stop as soon as the first loop is detected
+        fprintf( stdout, " (cone of %s \"%d\")\n", Ivy_ObjIsLatch(pObj)? "latch" : "PO", Ivy_ObjId(pObj) );
+        break;
+    }
+    return fAcyclic;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the levels of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManSetLevels_rec( Ivy_Obj_t * pObj, int fHaig )
+{
+    // quit if the node is visited
+    if ( Ivy_ObjIsMarkA(pObj) )
+        return pObj->Level;
+    Ivy_ObjSetMarkA(pObj);
+    // quit if this is a CI
+    if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) )
+        return 0;
+    assert( Ivy_ObjIsBuf(pObj) || Ivy_ObjIsAnd(pObj) || Ivy_ObjIsExor(pObj) );
+    // get levels of the fanins
+    Ivy_ManSetLevels_rec( Ivy_ObjFanin0(pObj), fHaig );
+    if ( !Ivy_ObjIsBuf(pObj) )
+        Ivy_ManSetLevels_rec( Ivy_ObjFanin1(pObj), fHaig );
+    // get level of the node
+    if ( Ivy_ObjIsBuf(pObj) )
+        pObj->Level = 1 + Ivy_ObjFanin0(pObj)->Level;
+    else if ( Ivy_ObjIsNode(pObj) )
+        pObj->Level = Ivy_ObjLevelNew( pObj );
+    else assert( 0 );
+    // get level of other choices
+    if ( fHaig && pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 )
+    {
+        Ivy_Obj_t * pTemp;
+        unsigned LevelMax = pObj->Level;
+        for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+        {
+            Ivy_ManSetLevels_rec( pTemp, fHaig );
+            LevelMax = IVY_MAX( LevelMax, pTemp->Level );
+        }
+        // get this level
+        pObj->Level = LevelMax;
+        for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+            pTemp->Level = LevelMax;
+    }
+    return pObj->Level;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the levels of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManSetLevels( Ivy_Man_t * p, int fHaig )
+{
+    Ivy_Obj_t * pObj;
+    int i, LevelMax;
+    // check if CIs have choices
+    if ( fHaig )
+    {
+        Ivy_ManForEachCi( p, pObj, i )
+            if ( pObj->pEquiv )
+                printf( "CI %d has a choice, which will not be visualized.\n", pObj->Id );
+    }
+    // clean the levels
+    Ivy_ManForEachObj( p, pObj, i )
+        pObj->Level = 0;
+    // compute the levels
+    LevelMax = 0;
+    Ivy_ManForEachCo( p, pObj, i )
+    {
+        Ivy_ManSetLevels_rec( Ivy_ObjFanin0(pObj), fHaig );
+        LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level );
+    }
+    // compute levels of nodes without fanout
+    Ivy_ManForEachObj( p, pObj, i )
+        if ( (Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj)) && Ivy_ObjRefs(pObj) == 0 )
+        {
+            Ivy_ManSetLevels_rec( pObj, fHaig );
+            LevelMax = IVY_MAX( LevelMax, (int)pObj->Level );
+        }
+    // clean the marks
+    Ivy_ManForEachObj( p, pObj, i )
+        Ivy_ObjClearMarkA(pObj);
+    return LevelMax;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyDsd.c b/abc-build/src/aig/ivy/ivyDsd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyDsd.c
@@ -0,0 +1,831 @@
+/**CFile****************************************************************
+
+  FileName    [ivyDsd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Disjoint-support decomposition.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyDsd.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// decomposition types
+typedef enum { 
+    IVY_DEC_PI,             // 0: var
+    IVY_DEC_CONST1,         // 1: CONST1
+    IVY_DEC_BUF,            // 2: BUF
+    IVY_DEC_AND,            // 3: AND
+    IVY_DEC_EXOR,           // 4: EXOR
+    IVY_DEC_MUX,            // 5: MUX
+    IVY_DEC_MAJ,            // 6: MAJ
+    IVY_DEC_PRIME           // 7: undecomposable
+} Ivy_DecType_t;
+
+typedef struct Ivy_Dec_t_ Ivy_Dec_t;
+struct Ivy_Dec_t_
+{
+    unsigned  Type   : 4;   // the node type (PI, CONST1, AND, EXOR, MUX, PRIME)
+    unsigned  fCompl : 1;   // shows if node is complemented (root node only)
+    unsigned  nFans  : 3;   // the number of fanins
+    unsigned  Fan0   : 4;   // fanin 0
+    unsigned  Fan1   : 4;   // fanin 1 
+    unsigned  Fan2   : 4;   // fanin 2
+    unsigned  Fan3   : 4;   // fanin 3 
+    unsigned  Fan4   : 4;   // fanin 4 
+    unsigned  Fan5   : 4;   // fanin 5
+};
+
+static inline int        Ivy_DecToInt( Ivy_Dec_t m )        { union { Ivy_Dec_t x; int y; } v; v.x = m; return v.y;  }
+static inline Ivy_Dec_t  Ivy_IntToDec( int m )              { union { Ivy_Dec_t x; int y; } v; v.y = m; return v.x;  }
+static inline void       Ivy_DecClear( Ivy_Dec_t * pNode )  { *pNode = Ivy_IntToDec(0);                              }
+
+//static inline int        Ivy_DecToInt( Ivy_Dec_t Node )     { return *((int *)&Node);       }
+//static inline Ivy_Dec_t  Ivy_IntToDec( int Node )           { return *((Ivy_Dec_t *)&Node); }
+//static inline void       Ivy_DecClear( Ivy_Dec_t * pNode )  { *((int *)pNode) = 0;          }
+
+
+static unsigned s_Masks[6][2] = {
+    { 0x55555555, 0xAAAAAAAA },
+    { 0x33333333, 0xCCCCCCCC },
+    { 0x0F0F0F0F, 0xF0F0F0F0 },
+    { 0x00FF00FF, 0xFF00FF00 },
+    { 0x0000FFFF, 0xFFFF0000 },
+    { 0x00000000, 0xFFFFFFFF }
+};
+
+static inline int        Ivy_TruthWordCountOnes( unsigned uWord )
+{
+    uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555);
+    uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333);
+    uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F);
+    uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF);
+    return  (uWord & 0x0000FFFF) + (uWord>>16);
+}
+
+static inline int        Ivy_TruthCofactorIsConst( unsigned uTruth, int Var, int Cof, int Const )
+{
+    if ( Const == 0 )
+        return (uTruth & s_Masks[Var][Cof]) == 0;
+    else
+        return (uTruth & s_Masks[Var][Cof]) == s_Masks[Var][Cof];
+}
+
+static inline int        Ivy_TruthCofactorIsOne( unsigned uTruth, int Var )
+{
+    return (uTruth & s_Masks[Var][0]) == 0;
+}
+
+static inline unsigned   Ivy_TruthCofactor( unsigned uTruth, int Var )
+{
+    unsigned uCofactor = uTruth & s_Masks[Var >> 1][(Var & 1) == 0];
+    int Shift = (1 << (Var >> 1));
+    if ( Var & 1 )
+        return uCofactor | (uCofactor << Shift);
+    return uCofactor | (uCofactor >> Shift);
+}
+
+static inline unsigned   Ivy_TruthCofactor2( unsigned uTruth, int Var0, int Var1 )
+{
+    return Ivy_TruthCofactor( Ivy_TruthCofactor(uTruth, Var0), Var1 );
+}
+
+// returns 1 if the truth table depends on this var (var is regular interger var)
+static inline int        Ivy_TruthDepends( unsigned uTruth, int Var )
+{
+    return Ivy_TruthCofactor(uTruth, Var << 1) != Ivy_TruthCofactor(uTruth, (Var << 1) | 1);
+}
+
+static inline void       Ivy_DecSetVar( Ivy_Dec_t * pNode, int iNum, unsigned Var )
+{
+    assert( iNum >= 0 && iNum <= 5 );
+    switch( iNum )
+    {
+        case 0: pNode->Fan0 = Var; break;
+        case 1: pNode->Fan1 = Var; break;
+        case 2: pNode->Fan2 = Var; break;
+        case 3: pNode->Fan3 = Var; break;
+        case 4: pNode->Fan4 = Var; break;
+        case 5: pNode->Fan5 = Var; break;
+    }
+}
+
+static inline unsigned   Ivy_DecGetVar( Ivy_Dec_t * pNode, int iNum )
+{
+    assert( iNum >= 0 && iNum <= 5 );
+    switch( iNum )
+    {
+        case 0: return pNode->Fan0;
+        case 1: return pNode->Fan1;
+        case 2: return pNode->Fan2;
+        case 3: return pNode->Fan3;
+        case 4: return pNode->Fan4;
+        case 5: return pNode->Fan5;
+    }
+    return ~0;
+}
+
+static int   Ivy_TruthDecompose_rec( unsigned uTruth, Vec_Int_t * vTree );
+static int   Ivy_TruthRecognizeMuxMaj( unsigned uTruth, int * pSupp, int nSupp, Vec_Int_t * vTree );
+
+//int nTruthDsd;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes DSD of truth table of 5 variables or less.]
+
+  Description [Returns 1 if the function is a constant or is fully 
+  DSD decomposable using AND/EXOR/MUX gates.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_TruthDsd( unsigned uTruth, Vec_Int_t * vTree )
+{
+    Ivy_Dec_t Node;
+    int i, RetValue;
+    // set the PI variables
+    Vec_IntClear( vTree );
+    for ( i = 0; i < 5; i++ )
+        Vec_IntPush( vTree, 0 );
+    // check if it is a constant
+    if ( uTruth == 0 || ~uTruth == 0 )
+    {
+        Ivy_DecClear( &Node );
+        Node.Type = IVY_DEC_CONST1;
+        Node.fCompl = (uTruth == 0);
+        Vec_IntPush( vTree, Ivy_DecToInt(Node) );
+        return 1;
+    }
+    // perform the decomposition
+    RetValue = Ivy_TruthDecompose_rec( uTruth, vTree );
+    if ( RetValue == -1 )
+        return 0;
+    // get the topmost node
+    if ( (RetValue >> 1) < 5 )
+    { // add buffer
+        Ivy_DecClear( &Node );
+        Node.Type = IVY_DEC_BUF;
+        Node.fCompl = (RetValue & 1);
+        Node.Fan0 = ((RetValue >> 1) << 1);
+        Vec_IntPush( vTree, Ivy_DecToInt(Node) );
+    }
+    else if ( RetValue & 1 )
+    { // check if the topmost node has to be complemented
+        Node = Ivy_IntToDec( Vec_IntPop(vTree) );
+        assert( Node.fCompl == 0 );
+        Node.fCompl = (RetValue & 1);
+        Vec_IntPush( vTree, Ivy_DecToInt(Node) );
+    }
+    if ( uTruth != Ivy_TruthDsdCompute(vTree) )
+        printf( "Verification failed.\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes DSD of truth table.]
+
+  Description [Returns the number of topmost decomposition node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_TruthDecompose_rec( unsigned uTruth, Vec_Int_t * vTree )
+{
+    Ivy_Dec_t Node;
+    int Supp[5], Vars0[5], Vars1[5], Vars2[5], * pVars;
+    int nSupp, Count0, Count1, Count2, nVars, RetValue, fCompl, i;
+    unsigned uTruthCof, uCof0, uCof1;
+
+    // get constant confactors
+    Count0 = Count1 = Count2 = nSupp = 0;
+    for ( i = 0; i < 5; i++ )
+    {
+        if ( Ivy_TruthCofactorIsConst(uTruth, i, 0, 0) )
+            Vars0[Count0++] = (i << 1) | 0;
+        else if ( Ivy_TruthCofactorIsConst(uTruth, i, 1, 0) )
+            Vars0[Count0++] = (i << 1) | 1;
+        else if ( Ivy_TruthCofactorIsConst(uTruth, i, 0, 1) )
+            Vars1[Count1++] = (i << 1) | 0;
+        else if ( Ivy_TruthCofactorIsConst(uTruth, i, 1, 1) )
+            Vars1[Count1++] = (i << 1) | 1;
+        else
+        {
+            uCof0 = Ivy_TruthCofactor( uTruth, (i << 1) | 1 );
+            uCof1 = Ivy_TruthCofactor( uTruth, (i << 1) | 0 );
+            if ( uCof0 == ~uCof1 )
+                Vars2[Count2++] = (i << 1) | 0;
+            else if ( uCof0 != uCof1 )
+                Supp[nSupp++] = i;
+        }
+    }
+    assert( Count0 == 0 || Count1 == 0 );
+    assert( Count0 == 0 || Count2 == 0 );
+    assert( Count1 == 0 || Count2 == 0 );
+
+    // consider the case of a single variable
+    if ( Count0 == 1 && nSupp == 0 )
+        return Vars0[0];
+
+    // consider more complex decompositions
+    if ( Count0 == 0 && Count1 == 0 && Count2 == 0 )
+        return Ivy_TruthRecognizeMuxMaj( uTruth, Supp, nSupp, vTree );
+
+    // extract the nodes
+    Ivy_DecClear( &Node );
+    if ( Count0 > 0 )
+        nVars = Count0, pVars = Vars0, Node.Type = IVY_DEC_AND,  fCompl = 0;
+    else if ( Count1 > 0 )
+        nVars = Count1, pVars = Vars1, Node.Type = IVY_DEC_AND,  fCompl = 1, uTruth = ~uTruth;
+    else if ( Count2 > 0 )
+        nVars = Count2, pVars = Vars2, Node.Type = IVY_DEC_EXOR, fCompl = 0;
+    else 
+        assert( 0 );
+    Node.nFans = nVars+(nSupp>0);
+
+    // compute cofactor
+    uTruthCof = uTruth;
+    for ( i = 0; i < nVars; i++ )
+    {
+        uTruthCof = Ivy_TruthCofactor( uTruthCof, pVars[i] );
+        Ivy_DecSetVar( &Node, i, pVars[i] );
+    }
+
+    if ( Node.Type == IVY_DEC_EXOR )
+        fCompl ^= ((Node.nFans & 1) == 0);
+
+    if ( nSupp > 0 )
+    {
+        assert( uTruthCof != 0 && ~uTruthCof != 0 );
+        // call recursively
+        RetValue = Ivy_TruthDecompose_rec( uTruthCof, vTree );
+        // quit if non-decomposable
+        if ( RetValue == -1 )
+            return -1;
+        // remove the complement from the child if the node is EXOR
+        if ( Node.Type == IVY_DEC_EXOR && (RetValue & 1) )
+        {
+            fCompl ^= 1;
+            RetValue ^= 1;
+        }
+        // set the new decomposition
+        Ivy_DecSetVar( &Node, nVars, RetValue );
+    }
+    else if ( Node.Type == IVY_DEC_EXOR )
+        fCompl ^= (uTruthCof == 0);
+
+    Vec_IntPush( vTree, Ivy_DecToInt(Node) );
+    return ((Vec_IntSize(vTree)-1) << 1) | fCompl;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns a non-negative number if the truth table is a MUX.]
+
+  Description [If the truth table is a MUX, returns the variable as follows:
+  first, control variable; second, positive cofactor; third, negative cofactor.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_TruthRecognizeMuxMaj( unsigned uTruth, int * pSupp, int nSupp, Vec_Int_t * vTree )
+{
+    Ivy_Dec_t Node;
+    int i, k, RetValue0, RetValue1;
+    unsigned uCof0, uCof1, Num;
+    char Count[3];
+    assert( nSupp >= 3 );
+    // start the node
+    Ivy_DecClear( &Node );
+    Node.Type = IVY_DEC_MUX;
+    Node.nFans = 3;
+    // try each of the variables
+    for ( i = 0; i < nSupp; i++ )
+    {
+        // get the cofactors with respect to these variables
+        uCof0 = Ivy_TruthCofactor( uTruth, (pSupp[i] << 1) | 1 );
+        uCof1 = Ivy_TruthCofactor( uTruth,  pSupp[i] << 1 );
+        // go through all other variables and make sure 
+        // each of them belongs to the support of one cofactor
+        for ( k = 0; k < nSupp; k++ )
+        {
+            if ( k == i )
+                continue;
+            if ( Ivy_TruthDepends(uCof0, pSupp[k]) && Ivy_TruthDepends(uCof1, pSupp[k]) )
+                break;
+        }
+        if ( k < nSupp )
+            continue;
+        // MUX decomposition exists
+        RetValue0 = Ivy_TruthDecompose_rec( uCof0, vTree );
+        if ( RetValue0 == -1 )
+            break;
+        RetValue1 = Ivy_TruthDecompose_rec( uCof1, vTree );
+        if ( RetValue1 == -1 )
+            break;
+        // both of them exist; create the node
+        Ivy_DecSetVar( &Node, 0, pSupp[i] << 1 );
+        Ivy_DecSetVar( &Node, 1, RetValue1 );
+        Ivy_DecSetVar( &Node, 2, RetValue0 );
+        Vec_IntPush( vTree, Ivy_DecToInt(Node) );
+        return ((Vec_IntSize(vTree)-1) << 1) | 0;
+    }
+    // check majority gate
+    if ( nSupp > 3 )
+        return -1;
+    if ( Ivy_TruthWordCountOnes(uTruth) != 16 )
+        return -1;
+    // this is a majority gate; determine polarity
+    Node.Type = IVY_DEC_MAJ;
+    Count[0] = Count[1] = Count[2] = 0;
+    for ( i = 0; i < 8; i++ )
+    {
+        Num = 0;
+        for ( k = 0; k < 3; k++ )
+            if ( i & (1 << k) )
+                Num |= (1 << pSupp[k]);
+        assert( Num < 32 );
+        if ( (uTruth & (1 << Num)) == 0 )
+            continue;
+        for ( k = 0; k < 3; k++ )
+            if ( i & (1 << k) )
+                Count[k]++;
+    }
+    assert( Count[0] == 1 || Count[0] == 3 );
+    assert( Count[1] == 1 || Count[1] == 3 );
+    assert( Count[2] == 1 || Count[2] == 3 );
+    Ivy_DecSetVar( &Node, 0, (pSupp[0] << 1)|(Count[0] == 1) );
+    Ivy_DecSetVar( &Node, 1, (pSupp[1] << 1)|(Count[1] == 1) );
+    Ivy_DecSetVar( &Node, 2, (pSupp[2] << 1)|(Count[2] == 1) );
+    Vec_IntPush( vTree, Ivy_DecToInt(Node) );
+    return ((Vec_IntSize(vTree)-1) << 1) | 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table of decomposition tree for verification.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Ivy_TruthDsdCompute_rec( int iNode, Vec_Int_t * vTree )
+{
+    unsigned uTruthChild, uTruthTotal;
+    int Var, i;
+    // get the node
+    Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) );
+    // compute the node function
+    if ( Node.Type == IVY_DEC_CONST1 )
+        return s_Masks[5][ !Node.fCompl ];
+    if ( Node.Type == IVY_DEC_PI )
+        return s_Masks[iNode][ !Node.fCompl ];
+    if ( Node.Type == IVY_DEC_BUF )
+    {
+        uTruthTotal = Ivy_TruthDsdCompute_rec( Node.Fan0 >> 1, vTree );
+        return Node.fCompl? ~uTruthTotal : uTruthTotal;
+    }
+    if ( Node.Type == IVY_DEC_AND )
+    {
+        uTruthTotal = s_Masks[5][1];
+        for ( i = 0; i < (int)Node.nFans; i++ )
+        {
+            Var = Ivy_DecGetVar( &Node, i );
+            uTruthChild = Ivy_TruthDsdCompute_rec( Var >> 1, vTree );
+            uTruthTotal = (Var & 1)? uTruthTotal & ~uTruthChild : uTruthTotal & uTruthChild;
+        }
+        return Node.fCompl? ~uTruthTotal : uTruthTotal;
+    }
+    if ( Node.Type == IVY_DEC_EXOR )
+    {
+        uTruthTotal = 0;
+        for ( i = 0; i < (int)Node.nFans; i++ )
+        {
+            Var = Ivy_DecGetVar( &Node, i );
+            uTruthTotal ^= Ivy_TruthDsdCompute_rec( Var >> 1, vTree );
+            assert( (Var & 1) == 0 );
+        }
+        return Node.fCompl? ~uTruthTotal : uTruthTotal;
+    }
+    assert( Node.fCompl == 0 );
+    if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ )
+    {
+        unsigned uTruthChildC, uTruthChild1, uTruthChild0;
+        int VarC, Var1, Var0;
+        VarC = Ivy_DecGetVar( &Node, 0 );
+        Var1 = Ivy_DecGetVar( &Node, 1 );
+        Var0 = Ivy_DecGetVar( &Node, 2 );
+        uTruthChildC = Ivy_TruthDsdCompute_rec( VarC >> 1, vTree );
+        uTruthChild1 = Ivy_TruthDsdCompute_rec( Var1 >> 1, vTree );
+        uTruthChild0 = Ivy_TruthDsdCompute_rec( Var0 >> 1, vTree );
+        assert( Node.Type == IVY_DEC_MAJ || (VarC & 1) == 0 );
+        uTruthChildC = (VarC & 1)? ~uTruthChildC : uTruthChildC;
+        uTruthChild1 = (Var1 & 1)? ~uTruthChild1 : uTruthChild1;
+        uTruthChild0 = (Var0 & 1)? ~uTruthChild0 : uTruthChild0;
+        if ( Node.Type == IVY_DEC_MUX )
+            return (uTruthChildC & uTruthChild1) | (~uTruthChildC & uTruthChild0);
+        else
+            return (uTruthChildC & uTruthChild1) | (uTruthChildC & uTruthChild0) | (uTruthChild1 & uTruthChild0);
+    }
+    assert( 0 );
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table of decomposition tree for verification.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Ivy_TruthDsdCompute( Vec_Int_t * vTree )
+{
+    return Ivy_TruthDsdCompute_rec( Vec_IntSize(vTree)-1, vTree );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the decomposition tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_TruthDsdPrint_rec( FILE * pFile, int iNode, Vec_Int_t * vTree )
+{
+    int Var, i;
+    // get the node
+    Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) );
+    // compute the node function
+    if ( Node.Type == IVY_DEC_CONST1 )
+        fprintf( pFile, "Const1%s", (Node.fCompl? "\'" : "") );
+    else if ( Node.Type == IVY_DEC_PI )
+        fprintf( pFile, "%c%s", 'a' + iNode, (Node.fCompl? "\'" : "") );
+    else if ( Node.Type == IVY_DEC_BUF )
+    {
+        Ivy_TruthDsdPrint_rec( pFile, Node.Fan0 >> 1, vTree );
+        fprintf( pFile, "%s", (Node.fCompl? "\'" : "") );
+    }
+    else if ( Node.Type == IVY_DEC_AND )
+    {
+        fprintf( pFile, "AND(" );
+        for ( i = 0; i < (int)Node.nFans; i++ )
+        {
+            Var = Ivy_DecGetVar( &Node, i );
+            Ivy_TruthDsdPrint_rec( pFile, Var >> 1, vTree );
+            fprintf( pFile, "%s", (Var & 1)? "\'" : "" );
+            if ( i != (int)Node.nFans-1 )
+                fprintf( pFile, "," );
+        }
+        fprintf( pFile, ")%s", (Node.fCompl? "\'" : "") );
+    }
+    else if ( Node.Type == IVY_DEC_EXOR )
+    {
+        fprintf( pFile, "EXOR(" );
+        for ( i = 0; i < (int)Node.nFans; i++ )
+        {
+            Var = Ivy_DecGetVar( &Node, i );
+            Ivy_TruthDsdPrint_rec( pFile, Var >> 1, vTree );
+            if ( i != (int)Node.nFans-1 )
+                fprintf( pFile, "," );
+            assert( (Var & 1) == 0 );
+        }
+        fprintf( pFile, ")%s", (Node.fCompl? "\'" : "") );
+    }
+    else if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ )
+    {
+        int VarC, Var1, Var0;
+        assert( Node.fCompl == 0 );
+        VarC = Ivy_DecGetVar( &Node, 0 );
+        Var1 = Ivy_DecGetVar( &Node, 1 );
+        Var0 = Ivy_DecGetVar( &Node, 2 );
+        fprintf( pFile, "%s", (Node.Type == IVY_DEC_MUX)? "MUX(" : "MAJ(" );
+        Ivy_TruthDsdPrint_rec( pFile, VarC >> 1, vTree );
+        fprintf( pFile, "%s", (VarC & 1)? "\'" : "" );
+        fprintf( pFile, "," );
+        Ivy_TruthDsdPrint_rec( pFile, Var1 >> 1, vTree );
+        fprintf( pFile, "%s", (Var1 & 1)? "\'" : "" );
+        fprintf( pFile, "," );
+        Ivy_TruthDsdPrint_rec( pFile, Var0 >> 1, vTree );
+        fprintf( pFile, "%s", (Var0 & 1)? "\'" : "" );
+        fprintf( pFile, ")" );
+    }
+    else assert( 0 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the decomposition tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_TruthDsdPrint( FILE * pFile, Vec_Int_t * vTree )
+{
+    fprintf( pFile, "F = " );
+    Ivy_TruthDsdPrint_rec( pFile, Vec_IntSize(vTree)-1, vTree );
+    fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implement DSD in the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_ManDsdConstruct_rec( Ivy_Man_t * p, Vec_Int_t * vFront, int iNode, Vec_Int_t * vTree )
+{
+    Ivy_Obj_t * pResult, * pChild, * pNodes[16];
+    int Var, i;
+    // get the node
+    Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) );
+    // compute the node function
+    if ( Node.Type == IVY_DEC_CONST1 )
+        return Ivy_NotCond( Ivy_ManConst1(p), Node.fCompl );
+    if ( Node.Type == IVY_DEC_PI )
+    {
+        pResult = Ivy_ManObj( p, Vec_IntEntry(vFront, iNode) );
+        return Ivy_NotCond( pResult, Node.fCompl );
+    }
+    if ( Node.Type == IVY_DEC_BUF )
+    {
+        pResult = Ivy_ManDsdConstruct_rec( p, vFront, Node.Fan0 >> 1, vTree );
+        return Ivy_NotCond( pResult, Node.fCompl );
+    }
+    if ( Node.Type == IVY_DEC_AND || Node.Type == IVY_DEC_EXOR )
+    {
+        for ( i = 0; i < (int)Node.nFans; i++ )
+        {
+            Var = Ivy_DecGetVar( &Node, i );
+            assert( Node.Type == IVY_DEC_AND || (Var & 1) == 0 );
+            pChild = Ivy_ManDsdConstruct_rec( p, vFront, Var >> 1, vTree );
+            pChild = Ivy_NotCond( pChild, (Var & 1) );
+            pNodes[i] = pChild;
+        }
+
+//        Ivy_MultiEval( pNodes, Node.nFans, Node.Type == IVY_DEC_AND ? IVY_AND : IVY_EXOR );
+
+        pResult = Ivy_Multi( p, pNodes, Node.nFans, Node.Type == IVY_DEC_AND ? IVY_AND : IVY_EXOR );
+        return Ivy_NotCond( pResult, Node.fCompl );
+    }
+    assert( Node.fCompl == 0 );
+    if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ )
+    {
+        int VarC, Var1, Var0;
+        VarC = Ivy_DecGetVar( &Node, 0 );
+        Var1 = Ivy_DecGetVar( &Node, 1 );
+        Var0 = Ivy_DecGetVar( &Node, 2 );
+        pNodes[0] = Ivy_ManDsdConstruct_rec( p, vFront, VarC >> 1, vTree );
+        pNodes[1] = Ivy_ManDsdConstruct_rec( p, vFront, Var1 >> 1, vTree );
+        pNodes[2] = Ivy_ManDsdConstruct_rec( p, vFront, Var0 >> 1, vTree );
+        assert( Node.Type == IVY_DEC_MAJ || (VarC & 1) == 0 );
+        pNodes[0] = Ivy_NotCond( pNodes[0], (VarC & 1) );
+        pNodes[1] = Ivy_NotCond( pNodes[1], (Var1 & 1) );
+        pNodes[2] = Ivy_NotCond( pNodes[2], (Var0 & 1) );
+        if ( Node.Type == IVY_DEC_MUX )
+            return Ivy_Mux( p, pNodes[0], pNodes[1], pNodes[2] );
+        else
+            return Ivy_Maj( p, pNodes[0], pNodes[1], pNodes[2] );
+    }
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implement DSD in the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_ManDsdConstruct( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vTree )
+{
+    int Entry, i;
+    // implement latches on the frontier (TEMPORARY!!!)
+    Vec_IntForEachEntry( vFront, Entry, i )
+        Vec_IntWriteEntry( vFront, i, Ivy_LeafId(Entry) );
+    // recursively construct the tree
+    return Ivy_ManDsdConstruct_rec( p, vFront, Vec_IntSize(vTree)-1, vTree );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_TruthDsdComputePrint( unsigned uTruth )
+{
+    static Vec_Int_t * vTree = NULL;
+    if ( vTree == NULL )
+        vTree = Vec_IntAlloc( 12 );
+    if ( Ivy_TruthDsd( uTruth, vTree ) )
+        Ivy_TruthDsdPrint( stdout, vTree );
+    else
+        printf( "Undecomposable\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_TruthTestOne( unsigned uTruth )
+{
+    static int Counter = 0;
+    static Vec_Int_t * vTree = NULL;
+    // decompose
+    if ( vTree == NULL )
+        vTree = Vec_IntAlloc( 12 );
+
+    if ( !Ivy_TruthDsd( uTruth, vTree ) )
+    {
+//        printf( "Undecomposable\n" );
+    }
+    else
+    {
+//        nTruthDsd++;
+        printf( "%5d : ", Counter++ );
+        Extra_PrintBinary( stdout, &uTruth, 32 );
+        printf( "  " );
+        Ivy_TruthDsdPrint( stdout, vTree );
+        if ( uTruth != Ivy_TruthDsdCompute(vTree) )
+            printf( "Verification failed.\n" );
+    }
+//    Vec_IntFree( vTree );
+}
+
+#if 0
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_TruthTest()
+{
+    FILE * pFile;
+    char Buffer[100];
+    unsigned uTruth;
+    int i;
+
+    pFile = fopen( "npn4.txt", "r" );
+    for ( i = 0; i < 222; i++ )
+//    pFile = fopen( "npn5.txt", "r" );
+//    for ( i = 0; i < 616126; i++ )
+    {
+        fscanf( pFile, "%s", Buffer );
+        Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 );
+//        Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 );
+        uTruth |= (uTruth << 16);
+//        uTruth = ~uTruth;
+        Ivy_TruthTestOne( uTruth );
+    }
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_TruthTest3()
+{
+    FILE * pFile;
+    char Buffer[100];
+    unsigned uTruth;
+    int i;
+
+    pFile = fopen( "npn3.txt", "r" );
+    for ( i = 0; i < 14; i++ )
+    {
+        fscanf( pFile, "%s", Buffer );
+        Extra_ReadHexadecimal( &uTruth, Buffer+2, 3 );
+        uTruth = uTruth | (uTruth << 8) | (uTruth << 16) | (uTruth << 24);
+        Ivy_TruthTestOne( uTruth );
+    }
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_TruthTest5()
+{
+    FILE * pFile;
+    char Buffer[100];
+    unsigned uTruth;
+    int i;
+
+//    pFile = fopen( "npn4.txt", "r" );
+//    for ( i = 0; i < 222; i++ )
+    pFile = fopen( "npn5.txt", "r" );
+    for ( i = 0; i < 616126; i++ )
+    {
+        fscanf( pFile, "%s", Buffer );
+//        Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 );
+        Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 );
+//        uTruth |= (uTruth << 16);
+//        uTruth = ~uTruth;
+        Ivy_TruthTestOne( uTruth );
+    }
+    fclose( pFile );
+}
+
+#endif
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyFanout.c b/abc-build/src/aig/ivy/ivyFanout.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyFanout.c
@@ -0,0 +1,314 @@
+/**CFile****************************************************************
+
+  FileName    [ivyFanout.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Representation of the fanouts.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyFanout.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// getting hold of the next fanout of the node
+static inline Ivy_Obj_t * Ivy_ObjNextFanout( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout )
+{
+    assert( !Ivy_IsComplement(pObj) );
+    assert( !Ivy_IsComplement(pFanout) );
+    if ( pFanout == NULL )
+        return NULL;
+    if ( Ivy_ObjFanin0(pFanout) == pObj )
+        return pFanout->pNextFan0;
+    assert( Ivy_ObjFanin1(pFanout) == pObj );
+    return pFanout->pNextFan1;
+}
+
+// getting hold of the previous fanout of the node
+static inline Ivy_Obj_t * Ivy_ObjPrevFanout( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout )
+{
+    assert( !Ivy_IsComplement(pObj) );
+    assert( !Ivy_IsComplement(pFanout) );
+    if ( pFanout == NULL )
+        return NULL;
+    if ( Ivy_ObjFanin0(pFanout) == pObj )
+        return pFanout->pPrevFan0;
+    assert( Ivy_ObjFanin1(pFanout) == pObj );
+    return pFanout->pPrevFan1;
+}
+
+// getting hold of the place where the next fanout will be attached
+static inline Ivy_Obj_t ** Ivy_ObjNextFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout )
+{
+    assert( !Ivy_IsComplement(pObj) );
+    assert( !Ivy_IsComplement(pFanout) );
+    if ( Ivy_ObjFanin0(pFanout) == pObj )
+        return &pFanout->pNextFan0;
+    assert( Ivy_ObjFanin1(pFanout) == pObj );
+    return &pFanout->pNextFan1;
+}
+
+// getting hold of the place where the next fanout will be attached
+static inline Ivy_Obj_t ** Ivy_ObjPrevFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout )
+{
+    assert( !Ivy_IsComplement(pObj) );
+    assert( !Ivy_IsComplement(pFanout) );
+    if ( Ivy_ObjFanin0(pFanout) == pObj )
+        return &pFanout->pPrevFan0;
+    assert( Ivy_ObjFanin1(pFanout) == pObj );
+    return &pFanout->pPrevFan1;
+}
+
+// getting hold of the place where the next fanout will be attached
+static inline Ivy_Obj_t ** Ivy_ObjPrevNextFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout )
+{
+    Ivy_Obj_t * pTemp;
+    assert( !Ivy_IsComplement(pObj) );
+    assert( !Ivy_IsComplement(pFanout) );
+    pTemp = Ivy_ObjPrevFanout(pObj, pFanout);
+    if ( pTemp == NULL )
+        return &pObj->pFanout;
+    if ( Ivy_ObjFanin0(pTemp) == pObj )
+        return &pTemp->pNextFan0;
+    assert( Ivy_ObjFanin1(pTemp) == pObj );
+    return &pTemp->pNextFan1;
+}
+
+// getting hold of the place where the next fanout will be attached
+static inline Ivy_Obj_t ** Ivy_ObjNextPrevFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout )
+{
+    Ivy_Obj_t * pTemp;
+    assert( !Ivy_IsComplement(pObj) );
+    assert( !Ivy_IsComplement(pFanout) );
+    pTemp = Ivy_ObjNextFanout(pObj, pFanout);
+    if ( pTemp == NULL )
+        return NULL;
+    if ( Ivy_ObjFanin0(pTemp) == pObj )
+        return &pTemp->pPrevFan0;
+    assert( Ivy_ObjFanin1(pTemp) == pObj );
+    return &pTemp->pPrevFan1;
+}
+
+// iterator through the fanouts of the node
+#define Ivy_ObjForEachFanoutInt( pObj, pFanout )                 \
+    for ( pFanout = (pObj)->pFanout; pFanout;                    \
+          pFanout = Ivy_ObjNextFanout(pObj, pFanout) )
+
+// safe iterator through the fanouts of the node
+#define Ivy_ObjForEachFanoutIntSafe( pObj, pFanout, pFanout2 )   \
+    for ( pFanout  = (pObj)->pFanout,                            \
+          pFanout2 = Ivy_ObjNextFanout(pObj, pFanout);           \
+          pFanout;                                               \
+          pFanout  = pFanout2,                                   \
+          pFanout2 = Ivy_ObjNextFanout(pObj, pFanout) )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the fanout representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManStartFanout( Ivy_Man_t * p )
+{
+    Ivy_Obj_t * pObj;
+    int i;
+    assert( !p->fFanout );
+    p->fFanout = 1;
+    Ivy_ManForEachObj( p, pObj, i )
+    {
+        if ( Ivy_ObjFanin0(pObj) )
+            Ivy_ObjAddFanout( p, Ivy_ObjFanin0(pObj), pObj );
+        if ( Ivy_ObjFanin1(pObj) )
+            Ivy_ObjAddFanout( p, Ivy_ObjFanin1(pObj), pObj );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the fanout representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManStopFanout( Ivy_Man_t * p )
+{
+    Ivy_Obj_t * pObj;
+    int i;
+    assert( p->fFanout );
+    p->fFanout = 0;
+    Ivy_ManForEachObj( p, pObj, i )
+        pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add the fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ObjAddFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanout )
+{
+    assert( p->fFanout );
+    if ( pFanin->pFanout )
+    {
+        *Ivy_ObjNextFanoutPlace(pFanin, pFanout) = pFanin->pFanout;
+        *Ivy_ObjPrevFanoutPlace(pFanin, pFanin->pFanout) = pFanout;
+    }
+    pFanin->pFanout = pFanout;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes the fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ObjDeleteFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanout )
+{
+    Ivy_Obj_t ** ppPlace1, ** ppPlace2, ** ppPlaceN;
+    assert( pFanin->pFanout != NULL );
+
+    ppPlace1 = Ivy_ObjNextFanoutPlace(pFanin, pFanout);
+    ppPlaceN = Ivy_ObjPrevNextFanoutPlace(pFanin, pFanout);
+    assert( *ppPlaceN == pFanout );
+    if ( ppPlaceN )
+        *ppPlaceN = *ppPlace1;
+
+    ppPlace2 = Ivy_ObjPrevFanoutPlace(pFanin, pFanout);
+    ppPlaceN = Ivy_ObjNextPrevFanoutPlace(pFanin, pFanout);
+    assert( ppPlaceN == NULL || *ppPlaceN == pFanout );
+    if ( ppPlaceN )
+        *ppPlaceN = *ppPlace2;
+
+    *ppPlace1 = NULL;
+    *ppPlace2 = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces the fanout of pOld to be pFanoutNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ObjPatchFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanoutOld, Ivy_Obj_t * pFanoutNew )
+{
+    Ivy_Obj_t ** ppPlace;
+    ppPlace = Ivy_ObjPrevNextFanoutPlace(pFanin, pFanoutOld);
+    assert( *ppPlace == pFanoutOld );
+    if ( ppPlace )
+        *ppPlace = pFanoutNew;
+    ppPlace = Ivy_ObjNextPrevFanoutPlace(pFanin, pFanoutOld);
+    assert( ppPlace == NULL || *ppPlace == pFanoutOld );
+    if ( ppPlace )
+        *ppPlace = pFanoutNew;
+    // assuming that pFanoutNew already points to the next fanout
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts iteration through the fanouts.]
+
+  Description [Copies the currently available fanouts into the array.]
+               
+  SideEffects [Can be used while the fanouts are being removed.]
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ObjCollectFanouts( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vArray )
+{
+    Ivy_Obj_t * pFanout;
+    assert( p->fFanout );
+    assert( !Ivy_IsComplement(pObj) );
+    Vec_PtrClear( vArray );
+    Ivy_ObjForEachFanoutInt( pObj, pFanout )
+        Vec_PtrPush( vArray, pFanout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads one fanout.]
+
+  Description [Returns fanout if there is only one fanout.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_ObjReadFirstFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+    return pObj->pFanout;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads one fanout.]
+
+  Description [Returns fanout if there is only one fanout.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ObjFanoutNum( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+    Ivy_Obj_t * pFanout;
+    int Counter = 0;
+    Ivy_ObjForEachFanoutInt( pObj, pFanout )
+        Counter++;
+    return Counter;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyFastMap.c b/abc-build/src/aig/ivy/ivyFastMap.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyFastMap.c
@@ -0,0 +1,1569 @@
+/**CFile****************************************************************
+
+  FileName    [ivyFastMap.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Fast FPGA mapping.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyFastMap.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define IVY_INFINITY   10000
+
+typedef struct Ivy_SuppMan_t_ Ivy_SuppMan_t;
+struct Ivy_SuppMan_t_ 
+{
+    int         nLimit;    // the limit on the number of inputs
+    int         nObjs;     // the number of entries
+    int         nSize;     // size of each entry in bytes
+    char *      pMem;      // memory allocated
+    Vec_Vec_t * vLuts;     // the array of nodes used in the mapping
+};
+
+typedef struct Ivy_Supp_t_ Ivy_Supp_t;
+struct Ivy_Supp_t_ 
+{
+    char        nSize;     // the number of support nodes
+    char        fMark;     // multipurpose mask
+    char        fMark2;    // multipurpose mask 
+    char        fMark3;    // multipurpose mask 
+    int         nRefs;     // the number of references
+    short       Delay;     // the delay of the node
+    short       DelayR;    // the reverse delay of the node
+    int         pArray[0]; // the support nodes
+};
+
+static inline Ivy_Supp_t * Ivy_ObjSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )      
+{ 
+    return (Ivy_Supp_t *)(((Ivy_SuppMan_t*)pAig->pData)->pMem + pObj->Id * ((Ivy_SuppMan_t*)pAig->pData)->nSize); 
+}
+static inline Ivy_Supp_t * Ivy_ObjSuppStart( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) 
+{ 
+    Ivy_Supp_t * pSupp;
+    pSupp = Ivy_ObjSupp( pAig, pObj );
+    pSupp->fMark = 0;
+    pSupp->Delay = 0;
+    pSupp->nSize = 1;
+    pSupp->pArray[0] = pObj->Id;
+    return pSupp;
+}
+
+static void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, abctime Time, char * pStr );
+static int  Ivy_FastMapDelay( Ivy_Man_t * pAig );
+static int  Ivy_FastMapArea( Ivy_Man_t * pAig );
+static void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit );
+static void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit );
+static int  Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit );
+static void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter );
+static void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit );
+static int  Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj );
+static int  Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj );
+static int  Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj );
+static void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld );
+static int  Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj );
+static int  Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj );
+
+
+extern abctime s_MappingTime;
+extern int s_MappingMem;
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fast K-LUT mapping of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapPerform( Ivy_Man_t * pAig, int nLimit, int fRecovery, int fVerbose )
+{
+    Ivy_SuppMan_t * pMan;
+    Ivy_Obj_t * pObj;
+    int i, Delay, Area;
+    abctime clk, clkTotal = Abc_Clock();
+    // start the memory for supports
+    pMan = ABC_ALLOC( Ivy_SuppMan_t, 1 );
+    memset( pMan, 0, sizeof(Ivy_SuppMan_t) );
+    pMan->nLimit = nLimit;
+    pMan->nObjs  = Ivy_ManObjIdMax(pAig) + 1;
+    pMan->nSize  = sizeof(Ivy_Supp_t) + nLimit * sizeof(int);
+    pMan->pMem   = (char *)ABC_ALLOC( char, pMan->nObjs * pMan->nSize );
+    memset( pMan->pMem, 0, pMan->nObjs * pMan->nSize );
+    pMan->vLuts  = Vec_VecAlloc( 100 );
+    pAig->pData  = pMan;
+clk = Abc_Clock();
+    // set the PI mapping
+    Ivy_ObjSuppStart( pAig, Ivy_ManConst1(pAig) );
+    Ivy_ManForEachPi( pAig, pObj, i )
+        Ivy_ObjSuppStart( pAig, pObj );
+    // iterate through all nodes in the topological order
+    Ivy_ManForEachNode( pAig, pObj, i )
+        Ivy_FastMapNode( pAig, pObj, nLimit );
+    // find the best arrival time and area
+    Delay = Ivy_FastMapDelay( pAig );
+    Area = Ivy_FastMapArea(pAig);
+    if ( fVerbose )
+        Ivy_FastMapPrint( pAig, Delay, Area, Abc_Clock() - clk, "Delay oriented mapping: " );
+
+// 2-1-2 (doing 2-1-2-1-2 improves 0.5%)
+
+    if ( fRecovery )
+    {
+clk = Abc_Clock();
+    Ivy_FastMapRequired( pAig, Delay, 0 );
+    // remap the nodes
+    Ivy_FastMapRecover( pAig, nLimit );
+    Delay = Ivy_FastMapDelay( pAig );
+    Area = Ivy_FastMapArea(pAig);
+    if ( fVerbose )
+        Ivy_FastMapPrint( pAig, Delay, Area, Abc_Clock() - clk, "Area recovery 2       : " );
+
+clk = Abc_Clock();
+    Ivy_FastMapRequired( pAig, Delay, 0 );
+    // iterate through all nodes in the topological order
+    Ivy_ManForEachNode( pAig, pObj, i )
+        Ivy_FastMapNodeArea( pAig, pObj, nLimit );
+    Delay = Ivy_FastMapDelay( pAig );
+    Area = Ivy_FastMapArea(pAig);
+    if ( fVerbose )
+        Ivy_FastMapPrint( pAig, Delay, Area, Abc_Clock() - clk, "Area recovery 1       : " );
+
+clk = Abc_Clock();
+    Ivy_FastMapRequired( pAig, Delay, 0 );
+    // remap the nodes
+    Ivy_FastMapRecover( pAig, nLimit );
+    Delay = Ivy_FastMapDelay( pAig );
+    Area = Ivy_FastMapArea(pAig);
+    if ( fVerbose )
+        Ivy_FastMapPrint( pAig, Delay, Area, Abc_Clock() - clk, "Area recovery 2       : " );
+    }
+
+
+    s_MappingTime = Abc_Clock() - clkTotal;
+    s_MappingMem = pMan->nObjs * pMan->nSize;
+/*
+    {
+        Vec_Ptr_t * vNodes;
+        vNodes = Vec_PtrAlloc( 100 );
+        Vec_VecForEachEntry( Ivy_Obj_t *, pMan->vLuts, pObj, i, k )
+            Vec_PtrPush( vNodes, pObj );
+        Ivy_ManShow( pAig, 0, vNodes );
+        Vec_PtrFree( vNodes );
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans memory used for decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapStop( Ivy_Man_t * pAig )
+{
+    Ivy_SuppMan_t * p = (Ivy_SuppMan_t *)pAig->pData;
+    Vec_VecFree( p->vLuts );
+    ABC_FREE( p->pMem );
+    ABC_FREE( p );
+    pAig->pData = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints statistics.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, abctime Time, char * pStr )
+{
+    printf( "%s : Delay = %3d. Area = %6d. ", pStr, Delay, Area );
+    ABC_PRT( "Time", Time );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes delay after LUT mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FastMapDelay( Ivy_Man_t * pAig )
+{
+    Ivy_Supp_t * pSupp;
+    Ivy_Obj_t * pObj;
+    int i, DelayMax = 0;
+    Ivy_ManForEachPo( pAig, pObj, i )
+    {
+        pObj = Ivy_ObjFanin0(pObj);
+        if ( !Ivy_ObjIsNode(pObj) )
+            continue;
+        pSupp = Ivy_ObjSupp( pAig, pObj );
+        if ( DelayMax < pSupp->Delay )
+            DelayMax = pSupp->Delay;
+    }
+    return DelayMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area after mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FastMapArea_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Vec_t * vLuts )
+{
+    Ivy_Supp_t * pSupp;
+    int i, Counter;
+    pSupp = Ivy_ObjSupp( pAig, pObj );
+    // skip visited nodes and PIs
+    if ( pSupp->fMark || pSupp->nSize == 1 )
+        return 0;
+    pSupp->fMark = 1;
+    // compute the area of this node
+    Counter = 0;
+    for ( i = 0; i < pSupp->nSize; i++ )
+        Counter += Ivy_FastMapArea_rec( pAig, Ivy_ManObj(pAig, pSupp->pArray[i]), vLuts );
+    // add the node to the array of LUTs
+    Vec_VecPush( vLuts, pSupp->Delay, pObj );
+    return 1 + Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area after mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FastMapArea( Ivy_Man_t * pAig )
+{
+    Vec_Vec_t * vLuts;
+    Ivy_Obj_t * pObj;
+    int i, Counter = 0;
+    // get the array to store the nodes
+    vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts;
+    Vec_VecClear( vLuts );
+    // explore starting from each node
+    Ivy_ManForEachPo( pAig, pObj, i )
+        Counter += Ivy_FastMapArea_rec( pAig, Ivy_ObjFanin0(pObj), vLuts );
+    // clean the marks
+    Ivy_ManForEachNode( pAig, pObj, i )
+        Ivy_ObjSupp( pAig, pObj )->fMark = 0;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fast mapping for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Ivy_ObjIsNodeInt1( Ivy_Obj_t * pObj )
+{
+    return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) == 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fast mapping for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Ivy_ObjIsNodeInt2( Ivy_Obj_t * pObj )
+{
+    return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) <= 2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fast mapping for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntRemoveDup( int * pArray, int nSize )
+{
+    int i, k;
+    if ( nSize < 2 )
+        return nSize;
+    for ( i = k = 1; i < nSize; i++ )
+        if ( pArray[i] != pArray[i-1] )
+            pArray[k++] = pArray[i];
+    return k;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fast mapping for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapNodeArea2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit )
+{
+    static int Store[32], StoreSize;
+    static char Supp0[16], Supp1[16];
+    static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0;
+    static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1;
+    Ivy_Obj_t * pFanin0, * pFanin1;
+    Ivy_Supp_t * pSupp0, * pSupp1, * pSupp;
+    int RetValue, DelayOld;
+    assert( nLimit <= 32 );
+    assert( Ivy_ObjIsNode(pObj) );
+    // get the fanins
+    pFanin0 = Ivy_ObjFanin0(pObj);
+    pFanin1 = Ivy_ObjFanin1(pObj);
+    // get the supports
+    pSupp0 = Ivy_ObjSupp( pAig, pFanin0 );
+    pSupp1 = Ivy_ObjSupp( pAig, pFanin1 );
+    pSupp  = Ivy_ObjSupp( pAig, pObj );
+    assert( pSupp->fMark == 0 );
+    // get the old delay of the node
+    DelayOld = Ivy_FastMapNodeDelay(pAig, pObj);
+    assert( DelayOld <= pSupp->DelayR );
+    // copy the current cut
+    memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize );
+    StoreSize = pSupp->nSize;
+    // get the fanin support
+    if ( Ivy_ObjRefs(pFanin0) > 1 && pSupp0->Delay < pSupp->DelayR )
+    {
+        pSupp0 = pTemp0;
+        pSupp0->nSize = 1;
+        pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj);
+    }
+    // get the fanin support
+    if ( Ivy_ObjRefs(pFanin1) > 1 && pSupp1->Delay < pSupp->DelayR )
+    {
+        pSupp1 = pTemp1;
+        pSupp1->nSize = 1;
+        pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj);
+    }
+    // merge the cuts
+    if ( pSupp0->nSize < pSupp1->nSize )
+        RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit );
+    else
+        RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit );
+    if ( !RetValue )
+    {
+        pSupp->nSize = 2;
+        pSupp->pArray[0] = Ivy_ObjFaninId0(pObj);
+        pSupp->pArray[1] = Ivy_ObjFaninId1(pObj);
+    }
+    // check the resulting delay
+    pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj);
+    if ( pSupp->Delay > pSupp->DelayR )
+    {
+        pSupp->nSize = StoreSize;
+        memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize );
+        pSupp->Delay = DelayOld;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fast mapping for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit )
+{
+    static int Store[32], StoreSize;
+    static char Supp0[16], Supp1[16];
+    static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0;
+    static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1;
+    Ivy_Obj_t * pFanin0, * pFanin1;
+    Ivy_Supp_t * pSupp0, * pSupp1, * pSupp;
+    int RetValue, DelayOld, RefsOld;
+    int AreaBef, AreaAft;
+    assert( nLimit <= 32 );
+    assert( Ivy_ObjIsNode(pObj) );
+    // get the fanins
+    pFanin0 = Ivy_ObjFanin0(pObj);
+    pFanin1 = Ivy_ObjFanin1(pObj);
+    // get the supports
+    pSupp0 = Ivy_ObjSupp( pAig, pFanin0 );
+    pSupp1 = Ivy_ObjSupp( pAig, pFanin1 );
+    pSupp  = Ivy_ObjSupp( pAig, pObj );
+    assert( pSupp->fMark == 0 );
+
+    // get the area
+    if ( pSupp->nRefs == 0 )
+        AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj );
+    else
+        AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+//    if ( AreaBef == 1 )
+//        return;
+
+    // deref the cut if the node is refed
+    if ( pSupp->nRefs != 0 )
+        Ivy_FastMapNodeDeref( pAig, pObj );
+
+    // get the old delay of the node
+    DelayOld = Ivy_FastMapNodeDelay(pAig, pObj);
+    assert( DelayOld <= pSupp->DelayR );
+    // copy the current cut
+    memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize );
+    StoreSize = pSupp->nSize;
+    // get the fanin support
+    if ( Ivy_ObjRefs(pFanin0) > 2 && pSupp0->Delay < pSupp->DelayR )
+//    if ( pSupp0->nRefs > 0 && pSupp0->Delay < pSupp->DelayR ) // this leads to 2% worse results
+    {
+        pSupp0 = pTemp0;
+        pSupp0->nSize = 1;
+        pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj);
+    }
+    // get the fanin support
+    if ( Ivy_ObjRefs(pFanin1) > 2 && pSupp1->Delay < pSupp->DelayR )
+//    if ( pSupp1->nRefs > 0 && pSupp1->Delay < pSupp->DelayR )
+    {
+        pSupp1 = pTemp1;
+        pSupp1->nSize = 1;
+        pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj);
+    }
+    // merge the cuts
+    if ( pSupp0->nSize < pSupp1->nSize )
+        RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit );
+    else
+        RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit );
+    if ( !RetValue )
+    {
+        pSupp->nSize = 2;
+        pSupp->pArray[0] = Ivy_ObjFaninId0(pObj);
+        pSupp->pArray[1] = Ivy_ObjFaninId1(pObj);
+    }
+
+    // check the resulting delay
+    pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj);
+
+    RefsOld = pSupp->nRefs; pSupp->nRefs = 0;
+    AreaAft = Ivy_FastMapNodeAreaDerefed( pAig, pObj );
+    pSupp->nRefs = RefsOld;
+
+    if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR )
+//    if ( pSupp->Delay > pSupp->DelayR )
+    {
+        pSupp->nSize = StoreSize;
+        memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize );
+        pSupp->Delay = DelayOld;
+//        printf( "-" );
+    }
+//    else
+//        printf( "+" );
+
+    if ( pSupp->nRefs != 0 )
+        Ivy_FastMapNodeRef( pAig, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fast mapping for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit )
+{
+    Ivy_Supp_t * pSupp0, * pSupp1, * pSupp;
+    int fFaninParam = 2;
+    int RetValue;
+    assert( Ivy_ObjIsNode(pObj) );
+    // get the supports
+    pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) );
+    pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) );
+    pSupp  = Ivy_ObjSupp( pAig, pObj );
+    pSupp->fMark = 0;
+    // get the delays
+    if ( pSupp0->Delay == pSupp1->Delay )
+        pSupp->Delay = (pSupp0->Delay == 0) ? pSupp0->Delay + 1: pSupp0->Delay;
+    else if ( pSupp0->Delay > pSupp1->Delay )
+    {
+        pSupp->Delay = pSupp0->Delay;
+        pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) );
+        pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj);
+    }
+    else // if ( pSupp0->Delay < pSupp1->Delay )
+    {
+        pSupp->Delay = pSupp1->Delay;
+        pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) );
+        pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj);
+    }
+    // merge the cuts
+    if ( pSupp0->nSize < pSupp1->nSize )
+        RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit );
+    else
+        RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit );
+    if ( !RetValue )
+    {
+        pSupp->Delay++;
+        if ( fFaninParam == 2 )
+        {
+            pSupp->nSize = 2;
+            pSupp->pArray[0] = Ivy_ObjFaninId0(pObj);
+            pSupp->pArray[1] = Ivy_ObjFaninId1(pObj);
+        }
+        else if ( fFaninParam == 3 )
+        {
+            Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB;
+            pFanin0 = Ivy_ObjFanin0(pObj);
+            pFanin1 = Ivy_ObjFanin1(pObj);
+            pSupp->nSize = 0;
+            // process the first fanin
+            if ( Ivy_ObjIsNodeInt1(pFanin0) )
+            {
+                pFaninA = Ivy_ObjFanin0(pFanin0);
+                pFaninB = Ivy_ObjFanin1(pFanin0);
+                if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) )
+                    pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin0);
+                else
+                {
+                    pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninA);
+                    pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninB);
+                }
+            }
+            else
+                pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin0);
+            // process the second fanin
+            if ( Ivy_ObjIsNodeInt1(pFanin1) )
+            {
+                pFaninA = Ivy_ObjFanin0(pFanin1);
+                pFaninB = Ivy_ObjFanin1(pFanin1);
+                if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) )
+                    pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin1);
+                else
+                {
+                    pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninA);
+                    pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninB);
+                }
+            }
+            else
+                pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin1);
+            // sort the fanins
+            Vec_IntSelectSort( pSupp->pArray, pSupp->nSize );
+            pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize );
+            assert( pSupp->pArray[0] < pSupp->pArray[1] );
+        }
+        else if ( fFaninParam == 4 )
+        {
+            Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB;
+            pFanin0 = Ivy_ObjFanin0(pObj);
+            pFanin1 = Ivy_ObjFanin1(pObj);
+            pSupp->nSize = 0;
+            // consider the case when exactly one of them is internal
+            if ( Ivy_ObjIsNodeInt1(pFanin0) ^ Ivy_ObjIsNodeInt1(pFanin1) )
+            {
+                pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) );
+                pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) );
+                if ( Ivy_ObjIsNodeInt1(pFanin0) && pSupp0->nSize < nLimit )
+                {
+                    pSupp->Delay = IVY_MAX( pSupp0->Delay, pSupp1->Delay + 1 );
+                    pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) );
+                    pSupp1->pArray[0] = Ivy_ObjId(pFanin1);
+                    // merge the cuts
+                    RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit );
+                    assert( RetValue );
+                    assert( pSupp->nSize > 1 );
+                    return;
+                }
+                if ( Ivy_ObjIsNodeInt1(pFanin1) && pSupp1->nSize < nLimit )
+                {
+                    pSupp->Delay = IVY_MAX( pSupp1->Delay, pSupp0->Delay + 1 );
+                    pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) );
+                    pSupp0->pArray[0] = Ivy_ObjId(pFanin0);
+                    // merge the cuts
+                    RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit );
+                    assert( RetValue );
+                    assert( pSupp->nSize > 1 );
+                    return;
+                }
+            }
+            // process the first fanin
+            if ( Ivy_ObjIsNodeInt1(pFanin0) )
+            {
+                pFaninA = Ivy_ObjFanin0(pFanin0);
+                pFaninB = Ivy_ObjFanin1(pFanin0);
+                if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) )
+                    pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin0);
+                else
+                {
+                    pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninA);
+                    pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninB);
+                }
+            }
+            else
+                pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin0);
+            // process the second fanin
+            if ( Ivy_ObjIsNodeInt1(pFanin1) )
+            {
+                pFaninA = Ivy_ObjFanin0(pFanin1);
+                pFaninB = Ivy_ObjFanin1(pFanin1);
+                if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) )
+                    pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin1);
+                else
+                {
+                    pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninA);
+                    pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninB);
+                }
+            }
+            else
+                pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin1);
+            // sort the fanins
+            Vec_IntSelectSort( pSupp->pArray, pSupp->nSize );
+            pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize );
+            assert( pSupp->pArray[0] < pSupp->pArray[1] );
+            assert( pSupp->nSize > 1 );
+        }
+    }
+    assert( pSupp->Delay > 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two supports]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit )
+{ 
+    int i, k, c;
+    assert( pSupp0->nSize >= pSupp1->nSize );
+    // the case of the largest cut sizes
+    if ( pSupp0->nSize == nLimit && pSupp1->nSize == nLimit )
+    {
+        for ( i = 0; i < pSupp0->nSize; i++ )
+            if ( pSupp0->pArray[i] != pSupp1->pArray[i] )
+                return 0;
+        for ( i = 0; i < pSupp0->nSize; i++ )
+            pSupp->pArray[i] = pSupp0->pArray[i];
+        pSupp->nSize = pSupp0->nSize;
+        return 1;
+    }
+    // the case when one of the cuts is the largest
+    if ( pSupp0->nSize == nLimit )
+    {
+        for ( i = 0; i < pSupp1->nSize; i++ )
+        {
+            for ( k = pSupp0->nSize - 1; k >= 0; k-- )
+                if ( pSupp0->pArray[k] == pSupp1->pArray[i] )
+                    break;
+            if ( k == -1 ) // did not find
+                return 0;
+        }
+        for ( i = 0; i < pSupp0->nSize; i++ )
+            pSupp->pArray[i] = pSupp0->pArray[i];
+        pSupp->nSize = pSupp0->nSize;
+        return 1;
+    }
+
+    // compare two cuts with different numbers
+    i = k = 0;
+    for ( c = 0; c < nLimit; c++ )
+    {
+        if ( k == pSupp1->nSize )
+        {
+            if ( i == pSupp0->nSize )
+            {
+                pSupp->nSize = c;
+                return 1;
+            }
+            pSupp->pArray[c] = pSupp0->pArray[i++];
+            continue;
+        }
+        if ( i == pSupp0->nSize )
+        {
+            if ( k == pSupp1->nSize )
+            {
+                pSupp->nSize = c;
+                return 1;
+            }
+            pSupp->pArray[c] = pSupp1->pArray[k++];
+            continue;
+        }
+        if ( pSupp0->pArray[i] < pSupp1->pArray[k] )
+        {
+            pSupp->pArray[c] = pSupp0->pArray[i++];
+            continue;
+        }
+        if ( pSupp0->pArray[i] > pSupp1->pArray[k] )
+        {
+            pSupp->pArray[c] = pSupp1->pArray[k++];
+            continue;
+        }
+        pSupp->pArray[c] = pSupp0->pArray[i++]; 
+        k++;
+    }
+    if ( i < pSupp0->nSize || k < pSupp1->nSize )
+        return 0;
+    pSupp->nSize = c;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates integer vector with the support of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapReadSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Int_t * vLeaves )
+{
+    Ivy_Supp_t * pSupp;
+    pSupp = Ivy_ObjSupp( pAig, pObj );
+    vLeaves->nCap   = 8;
+    vLeaves->nSize  = pSupp->nSize;
+    vLeaves->pArray = pSupp->pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the required times of the intermediate nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapRequired_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Ivy_Obj_t * pRoot, int DelayR )
+{
+    Ivy_Supp_t * pSupp;
+    pSupp = Ivy_ObjSupp( pAig, pObj );
+    if ( pObj != pRoot && (pSupp->nRefs > 0 || Ivy_ObjIsCi(pObj)) )
+        return;
+    Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin0(pObj), pRoot, DelayR );
+    Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin1(pObj), pRoot, DelayR );
+//    assert( pObj == pRoot || pSupp->DelayR == IVY_INFINITY );
+    pSupp->DelayR = DelayR;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the required times for each node.]
+
+  Description [Sets reference counters for each node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter )
+{
+    Vec_Vec_t * vLuts;
+    Vec_Ptr_t * vNodes;
+    Ivy_Obj_t * pObj;
+    Ivy_Supp_t * pSupp, * pSuppF;
+    int i, k, c;
+    // clean the required times
+    Ivy_ManForEachPi( pAig, pObj, i )
+    {
+        pSupp = Ivy_ObjSupp( pAig, pObj );
+        pSupp->DelayR = IVY_INFINITY;
+        pSupp->nRefs = 0;
+    }
+    Ivy_ManForEachNode( pAig, pObj, i )
+    {
+        pSupp = Ivy_ObjSupp( pAig, pObj );
+        pSupp->DelayR = IVY_INFINITY;
+        pSupp->nRefs = 0;
+    }
+    // set the required times of the POs
+    Ivy_ManForEachPo( pAig, pObj, i )
+    {
+        pSupp = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) );
+        pSupp->DelayR = Delay;
+        pSupp->nRefs++;
+    }
+    // get the levelized nodes used in the mapping
+    vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts;
+    // propagate the required times
+    Vec_VecForEachLevelReverse( vLuts, vNodes, i )
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, k )
+    {
+        pSupp = Ivy_ObjSupp( pAig, pObj );
+        assert( pSupp->nRefs > 0 );
+        for ( c = 0; c < pSupp->nSize; c++ )
+        {
+            pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) );
+            pSuppF->DelayR = IVY_MIN( pSuppF->DelayR, pSupp->DelayR - 1 );
+            pSuppF->nRefs++;
+        }
+    }
+/*
+    // print out some of the required times
+    Ivy_ManForEachPi( pAig, pObj, i )
+    {
+        pSupp = Ivy_ObjSupp( pAig, pObj );
+        printf( "%d ", pSupp->DelayR );
+    }
+    printf( "\n" );    
+*/
+
+    if ( fSetInter )
+    {
+        // set the required times of the intermediate nodes
+        Vec_VecForEachLevelReverse( vLuts, vNodes, i )
+        Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, k )
+        {
+            pSupp = Ivy_ObjSupp( pAig, pObj );
+            Ivy_FastMapRequired_rec( pAig, pObj, pObj, pSupp->DelayR ); 
+        }
+        // make sure that all required times are assigned
+        Ivy_ManForEachNode( pAig, pObj, i )
+        {
+            pSupp = Ivy_ObjSupp( pAig, pObj );
+            assert( pSupp->DelayR < IVY_INFINITY );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs area recovery for each node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit )
+{
+    Vec_Ptr_t * vFront, * vFrontOld;
+    Ivy_Obj_t * pObj;
+    int i;
+    vFront = Vec_PtrAlloc( nLimit );
+    vFrontOld = Vec_PtrAlloc( nLimit );
+    Ivy_ManCleanTravId( pAig );
+    // iterate through all nodes in the topological order
+    Ivy_ManForEachNode( pAig, pObj, i )
+        Ivy_FastMapNodeRecover( pAig, pObj, nLimit, vFront, vFrontOld );
+    Vec_PtrFree( vFrontOld );
+    Vec_PtrFree( vFront );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the delay of the cut rooted at this node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+    Ivy_Supp_t * pSupp, * pSuppF;
+    int c, Delay = 0;
+    pSupp = Ivy_ObjSupp( pAig, pObj );
+    for ( c = 0; c < pSupp->nSize; c++ )
+    {
+        pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) );
+        Delay = IVY_MAX( Delay, pSuppF->Delay );
+    }
+    return 1 + Delay;
+}
+
+
+/**function*************************************************************
+
+  synopsis    [References the cut.]
+
+  description [This procedure is similar to the procedure NodeReclaim.]
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+int Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+    Ivy_Supp_t * pSupp, * pSuppF;
+    Ivy_Obj_t * pNodeChild;
+    int aArea, i;
+    // start the area of this cut
+    aArea = 1;
+    // go through the children
+    pSupp = Ivy_ObjSupp( pAig, pObj );
+    assert( pSupp->nSize > 1 );
+    for ( i = 0; i < pSupp->nSize; i++ )
+    {
+        pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]);
+        pSuppF = Ivy_ObjSupp( pAig, pNodeChild );
+        assert( pSuppF->nRefs >= 0 );
+        if ( pSuppF->nRefs++ > 0 )  
+            continue;
+        if ( pSuppF->nSize == 1 ) 
+            continue;
+        aArea += Ivy_FastMapNodeRef( pAig, pNodeChild );
+    }
+    return aArea;
+}
+
+/**function*************************************************************
+
+  synopsis    [Dereferences the cut.]
+
+  description [This procedure is similar to the procedure NodeRecusiveDeref.]
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+int Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+    Ivy_Supp_t * pSupp, * pSuppF;
+    Ivy_Obj_t * pNodeChild;
+    int aArea, i;
+    // start the area of this cut
+    aArea = 1;
+    // go through the children
+    pSupp = Ivy_ObjSupp( pAig, pObj );
+    assert( pSupp->nSize > 1 );
+    for ( i = 0; i < pSupp->nSize; i++ )
+    {
+        pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]);
+        pSuppF = Ivy_ObjSupp( pAig, pNodeChild );
+        assert( pSuppF->nRefs > 0 );
+        if ( --pSuppF->nRefs > 0 )  
+            continue;
+        if ( pSuppF->nSize == 1 ) 
+            continue;
+        aArea += Ivy_FastMapNodeDeref( pAig, pNodeChild );
+    }
+    return aArea;
+}
+
+/**function*************************************************************
+
+  synopsis    [Computes the exact area associated with the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+int Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+    Ivy_Supp_t * pSupp;
+    int aResult, aResult2;
+    if ( Ivy_ObjIsCi(pObj) )
+        return 0;
+    assert( Ivy_ObjIsNode(pObj) );
+    pSupp = Ivy_ObjSupp( pAig, pObj );
+    assert( pSupp->nRefs > 0 );
+    aResult  = Ivy_FastMapNodeDeref( pAig, pObj );
+    aResult2 = Ivy_FastMapNodeRef( pAig, pObj );
+    assert( aResult == aResult2 );
+    return aResult;
+}
+
+/**function*************************************************************
+
+  synopsis    [Computes the exact area associated with the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+int Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+    Ivy_Supp_t * pSupp;
+    int aResult, aResult2;
+    if ( Ivy_ObjIsCi(pObj) )
+        return 0;
+    assert( Ivy_ObjIsNode(pObj) );
+    pSupp = Ivy_ObjSupp( pAig, pObj );
+    assert( pSupp->nRefs == 0 );
+    aResult2 = Ivy_FastMapNodeRef( pAig, pObj );
+    aResult  = Ivy_FastMapNodeDeref( pAig, pObj );
+    assert( aResult == aResult2 );
+    return aResult;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of nodes with no external fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FastMapCutCost( Ivy_Man_t * pAig, Vec_Ptr_t * vFront )
+{
+    Ivy_Supp_t * pSuppF;
+    Ivy_Obj_t * pFanin;
+    int i, Counter = 0;
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i )
+    {
+        pSuppF = Ivy_ObjSupp( pAig, pFanin );
+        if ( pSuppF->nRefs == 0 )
+            Counter++;
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs area recovery for each node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapMark_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+    if ( Ivy_ObjIsTravIdCurrent(pAig, pObj) )
+        return;
+    assert( Ivy_ObjIsNode(pObj) );
+    Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin0(pObj) );
+    Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin1(pObj) );
+    Ivy_ObjSetTravIdCurrent(pAig, pObj);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the number of fanins will grow.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FastMapNodeWillGrow( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+    Ivy_Obj_t * pFanin0, * pFanin1;
+    assert( Ivy_ObjIsNode(pObj) );
+    pFanin0 = Ivy_ObjFanin0(pObj);
+    pFanin1 = Ivy_ObjFanin1(pObj);
+    return !Ivy_ObjIsTravIdCurrent(pAig, pFanin0) && !Ivy_ObjIsTravIdCurrent(pAig, pFanin1);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the increase in the number of fanins with no external refs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FastMapNodeFaninCost( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+    Ivy_Supp_t * pSuppF;
+    Ivy_Obj_t * pFanin;
+    int Counter = 0;
+    assert( Ivy_ObjIsNode(pObj) );
+    // check if the node has external refs
+    pSuppF = Ivy_ObjSupp( pAig, pObj );
+    if ( pSuppF->nRefs == 0 )
+        Counter--;
+    // increment the number of fanins without external refs
+    pFanin = Ivy_ObjFanin0(pObj);
+    pSuppF = Ivy_ObjSupp( pAig, pFanin );
+    if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 )
+        Counter++;
+    // increment the number of fanins without external refs
+    pFanin = Ivy_ObjFanin1(pObj);
+    pSuppF = Ivy_ObjSupp( pAig, pFanin );
+    if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 )
+        Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the frontier.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapNodeFaninUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront )
+{
+    Ivy_Obj_t * pFanin;
+    assert( Ivy_ObjIsNode(pObj) );
+    Vec_PtrRemove( vFront, pObj );
+    pFanin = Ivy_ObjFanin0(pObj);
+    if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) )
+    {
+        Ivy_ObjSetTravIdCurrent(pAig, pFanin);
+        Vec_PtrPush( vFront, pFanin );
+    }
+    pFanin = Ivy_ObjFanin1(pObj);
+    if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) )
+    {
+        Ivy_ObjSetTravIdCurrent(pAig, pFanin);
+        Vec_PtrPush( vFront, pFanin );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compacts the number of external refs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FastMapNodeFaninCompact0( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront )
+{
+    Ivy_Obj_t * pFanin;
+    int i;
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i )
+    {
+        if ( Ivy_ObjIsCi(pFanin) )
+            continue;
+        if ( Ivy_FastMapNodeWillGrow(pAig, pFanin) )
+            continue;
+        if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 )
+        {
+            Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront );
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compacts the number of external refs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FastMapNodeFaninCompact1( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront )
+{
+    Ivy_Obj_t * pFanin;
+    int i;
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i )
+    {
+        if ( Ivy_ObjIsCi(pFanin) )
+            continue;
+        if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) < 0 )
+        {
+            Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront );
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compacts the number of external refs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FastMapNodeFaninCompact2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront )
+{
+    Ivy_Obj_t * pFanin;
+    int i;
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i )
+    {
+        if ( Ivy_ObjIsCi(pFanin) )
+            continue;
+        if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 )
+        {
+            Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront );
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compacts the number of external refs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FastMapNodeFaninCompact_int( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront )
+{
+    if ( Ivy_FastMapNodeFaninCompact0(pAig, pObj, nLimit, vFront) )
+        return 1;
+    if (  Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact1(pAig, pObj, nLimit, vFront) )
+        return 1;
+    if ( Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact2(pAig, pObj, nLimit, vFront) )
+        return 1;
+    assert( Vec_PtrSize(vFront) <= nLimit );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compacts the number of external refs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapNodeFaninCompact( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront )
+{
+    while ( Ivy_FastMapNodeFaninCompact_int( pAig, pObj, nLimit, vFront ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares node mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapNodePrepare( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld )
+{
+    Ivy_Supp_t * pSupp;
+    Ivy_Obj_t * pFanin;
+    int i;
+    pSupp = Ivy_ObjSupp( pAig, pObj );
+    // expand the cut downwards from the given place
+    Vec_PtrClear( vFront );
+    Vec_PtrClear( vFrontOld );
+    Ivy_ManIncrementTravId( pAig );
+    for ( i = 0; i < pSupp->nSize; i++ )
+    {
+        pFanin = Ivy_ManObj(pAig, pSupp->pArray[i]);
+        Vec_PtrPush( vFront, pFanin );
+        Vec_PtrPush( vFrontOld, pFanin );
+        Ivy_ObjSetTravIdCurrent( pAig, pFanin );
+    }
+    // mark the nodes in the cone
+    Ivy_FastMapMark_rec( pAig, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the frontier.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapNodeUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront )
+{
+    Ivy_Supp_t * pSupp;
+    Ivy_Obj_t * pFanin;
+    int i;
+    pSupp = Ivy_ObjSupp( pAig, pObj );
+    // deref node's cut
+    Ivy_FastMapNodeDeref( pAig, pObj );
+    // update the node's cut
+    pSupp->nSize = Vec_PtrSize(vFront);
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i )
+        pSupp->pArray[i] = pFanin->Id;
+    // ref the new cut
+    Ivy_FastMapNodeRef( pAig, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs area recovery for each node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapNodeRecover2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld )
+{
+    Ivy_Supp_t * pSupp;
+    int CostBef, CostAft;
+    int AreaBef, AreaAft;
+    pSupp = Ivy_ObjSupp( pAig, pObj );
+//    if ( pSupp->nRefs == 0 )
+//        return;
+    if ( pSupp->nRefs == 0 )
+        AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj );
+    else
+        AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+    // get the area
+    if ( AreaBef == 1 )
+        return;
+
+    if ( pSupp->nRefs == 0 )
+    {
+        pSupp->nRefs = 1000000;
+        Ivy_FastMapNodeRef( pAig, pObj );
+    }
+    // the cut is non-trivial
+    Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld );
+    // iteratively modify the cut
+    CostBef = Ivy_FastMapCutCost( pAig, vFront );
+    Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront );
+    CostAft = Ivy_FastMapCutCost( pAig, vFront );
+    assert( CostBef >= CostAft );
+    // update the node
+    Ivy_FastMapNodeUpdate( pAig, pObj, vFront );
+    // get the new area
+    AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+    if ( AreaAft > AreaBef )
+    {
+        Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld );
+        AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+        assert( AreaAft == AreaBef );
+    }
+    if ( pSupp->nRefs == 1000000 )
+    {
+        pSupp->nRefs = 0;
+        Ivy_FastMapNodeDeref( pAig, pObj );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs area recovery for each node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld )
+{
+    Ivy_Supp_t * pSupp;
+    int CostBef, CostAft;
+    int AreaBef, AreaAft;
+    int DelayOld;
+    pSupp = Ivy_ObjSupp( pAig, pObj );
+    DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj );
+    assert( pSupp->Delay <= pSupp->DelayR );
+    if ( pSupp->nRefs == 0 )
+        return;
+    // get the area
+    AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+//    if ( AreaBef == 1 )
+//        return;
+    // the cut is non-trivial
+    Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld );
+    // iteratively modify the cut
+    Ivy_FastMapNodeDeref( pAig, pObj );
+    CostBef = Ivy_FastMapCutCost( pAig, vFront );
+    Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront );
+    CostAft = Ivy_FastMapCutCost( pAig, vFront );
+    Ivy_FastMapNodeRef( pAig, pObj );
+    assert( CostBef >= CostAft );
+    // update the node
+    Ivy_FastMapNodeUpdate( pAig, pObj, vFront );
+    pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj );
+    // get the new area
+    AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+    if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR )
+    {
+        Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld );
+        AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+        assert( AreaAft == AreaBef );
+        pSupp->Delay = DelayOld;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs area recovery for each node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FastMapNodeRecover4( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld )
+{
+    Ivy_Supp_t * pSupp;
+    int CostBef, CostAft;
+    int AreaBef, AreaAft;
+    int DelayOld;
+    pSupp = Ivy_ObjSupp( pAig, pObj );
+    DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj );
+    assert( pSupp->Delay <= pSupp->DelayR );
+//    if ( pSupp->nRefs == 0 )
+//        return;
+//    AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+    // get the area
+    if ( pSupp->nRefs == 0 )
+        AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj );
+    else
+        AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+    if ( AreaBef == 1 )
+        return;
+
+    if ( pSupp->nRefs == 0 )
+    {
+        pSupp->nRefs = 1000000;
+        Ivy_FastMapNodeRef( pAig, pObj );
+    }
+    // the cut is non-trivial
+    Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld );
+    // iteratively modify the cut
+    CostBef = Ivy_FastMapCutCost( pAig, vFront );
+    Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront );
+    CostAft = Ivy_FastMapCutCost( pAig, vFront );
+    assert( CostBef >= CostAft );
+    // update the node
+    Ivy_FastMapNodeUpdate( pAig, pObj, vFront );
+    pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj );
+    // get the new area
+    AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+    if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR )
+    {
+        Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld );
+        AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+        assert( AreaAft == AreaBef );
+        pSupp->Delay = DelayOld;
+    }
+    if ( pSupp->nRefs == 1000000 )
+    {
+        pSupp->nRefs = 0;
+        Ivy_FastMapNodeDeref( pAig, pObj );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyFraig.c b/abc-build/src/aig/ivy/ivyFraig.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyFraig.c
@@ -0,0 +1,2968 @@
+/**CFile****************************************************************
+
+  FileName    [ivyFraig.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Functional reduction of AIGs]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyFraig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <math.h>
+
+#include "sat/bsat/satSolver.h"
+#include "misc/extra/extra.h"
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ivy_FraigMan_t_        Ivy_FraigMan_t;
+typedef struct Ivy_FraigSim_t_        Ivy_FraigSim_t;
+typedef struct Ivy_FraigList_t_       Ivy_FraigList_t;
+
+struct Ivy_FraigList_t_
+{
+    Ivy_Obj_t *         pHead;
+    Ivy_Obj_t *         pTail;
+    int                 nItems;
+};
+
+struct Ivy_FraigSim_t_
+{
+    int                 Type;
+    Ivy_FraigSim_t *    pNext;
+    Ivy_FraigSim_t *    pFanin0;
+    Ivy_FraigSim_t *    pFanin1;
+    unsigned            pData[0];
+};
+
+struct Ivy_FraigMan_t_
+{
+    // general info 
+    Ivy_FraigParams_t * pParams;        // various parameters
+    // temporary backtrack limits because "ABC_INT64_T" cannot be defined in Ivy_FraigParams_t ...
+    ABC_INT64_T              nBTLimitGlobal; // global limit on the number of backtracks
+    ABC_INT64_T              nInsLimitGlobal;// global limit on the number of clause inspects
+    // AIG manager
+    Ivy_Man_t *         pManAig;        // the starting AIG manager
+    Ivy_Man_t *         pManFraig;      // the final AIG manager
+    // simulation information
+    int                 nSimWords;      // the number of words
+    char *              pSimWords;      // the simulation info
+    Ivy_FraigSim_t *    pSimStart;      // the list of simulation info for internal nodes
+    // counter example storage
+    int                 nPatWords;      // the number of words in the counter example
+    unsigned *          pPatWords;      // the counter example
+    int *               pPatScores;     // the scores of each pattern
+    // equivalence classes 
+    Ivy_FraigList_t     lClasses;       // equivalence classes
+    Ivy_FraigList_t     lCand;          // candidatates
+    int                 nPairs;         // the number of pairs of nodes
+    // equivalence checking
+    sat_solver *        pSat;           // SAT solver
+    int                 nSatVars;       // the number of variables currently used
+    Vec_Ptr_t *         vPiVars;        // the PIs of the cone used 
+    // other 
+    ProgressBar *       pProgress;
+    // statistics
+    int                 nSimRounds;
+    int                 nNodesMiter;
+    int                 nClassesZero;
+    int                 nClassesBeg;
+    int                 nClassesEnd;
+    int                 nPairsBeg;
+    int                 nPairsEnd;
+    int                 nSatCalls;
+    int                 nSatCallsSat;
+    int                 nSatCallsUnsat;
+    int                 nSatProof;
+    int                 nSatFails;
+    int                 nSatFailsReal;
+    // runtime
+    abctime             timeSim;
+    abctime             timeTrav;
+    abctime             timeSat;
+    abctime             timeSatUnsat;
+    abctime             timeSatSat;
+    abctime             timeSatFail;
+    abctime             timeRef;
+    abctime             timeTotal;
+    abctime             time1;
+    abctime             time2;
+};
+
+typedef struct Prove_ParamsStruct_t_      Prove_Params_t;
+struct Prove_ParamsStruct_t_
+{
+    // general parameters
+    int     fUseFraiging;          // enables fraiging
+    int     fUseRewriting;         // enables rewriting
+    int     fUseBdds;              // enables BDD construction when other methods fail
+    int     fVerbose;              // prints verbose stats
+    // iterations
+    int     nItersMax;             // the number of iterations
+    // mitering 
+    int     nMiteringLimitStart;   // starting mitering limit
+    float   nMiteringLimitMulti;   // multiplicative coefficient to increase the limit in each iteration
+    // rewriting 
+    int     nRewritingLimitStart;  // the number of rewriting iterations
+    float   nRewritingLimitMulti;  // multiplicative coefficient to increase the limit in each iteration
+    // fraiging 
+    int     nFraigingLimitStart;   // starting backtrack(conflict) limit
+    float   nFraigingLimitMulti;   // multiplicative coefficient to increase the limit in each iteration
+    // last-gasp BDD construction
+    int     nBddSizeLimit;         // the number of BDD nodes when construction is aborted
+    int     fBddReorder;           // enables dynamic BDD variable reordering
+    // last-gasp mitering
+    int     nMiteringLimitLast;    // final mitering limit
+    // global SAT solver limits
+    ABC_INT64_T  nTotalBacktrackLimit;  // global limit on the number of backtracks
+    ABC_INT64_T  nTotalInspectLimit;    // global limit on the number of clause inspects
+    // global resources applied
+    ABC_INT64_T  nTotalBacktracksMade;  // the total number of backtracks made
+    ABC_INT64_T  nTotalInspectsMade;    // the total number of inspects made
+};
+
+static inline Ivy_FraigSim_t * Ivy_ObjSim( Ivy_Obj_t * pObj )                            { return (Ivy_FraigSim_t *)pObj->pFanout;  }
+static inline Ivy_Obj_t * Ivy_ObjClassNodeLast( Ivy_Obj_t * pObj )                       { return pObj->pNextFan0;  }
+static inline Ivy_Obj_t * Ivy_ObjClassNodeRepr( Ivy_Obj_t * pObj )                       { return pObj->pNextFan0;  }
+static inline Ivy_Obj_t * Ivy_ObjClassNodeNext( Ivy_Obj_t * pObj )                       { return pObj->pNextFan1;  }
+static inline Ivy_Obj_t * Ivy_ObjNodeHashNext( Ivy_Obj_t * pObj )                        { return pObj->pPrevFan0;  }
+static inline Ivy_Obj_t * Ivy_ObjEquivListNext( Ivy_Obj_t * pObj )                       { return pObj->pPrevFan0;  }
+static inline Ivy_Obj_t * Ivy_ObjEquivListPrev( Ivy_Obj_t * pObj )                       { return pObj->pPrevFan1;  }
+static inline Ivy_Obj_t * Ivy_ObjFraig( Ivy_Obj_t * pObj )                               { return pObj->pEquiv;     }
+static inline int         Ivy_ObjSatNum( Ivy_Obj_t * pObj )                              { return (int)(ABC_PTRUINT_T)pObj->pNextFan0;         }
+static inline Vec_Ptr_t * Ivy_ObjFaninVec( Ivy_Obj_t * pObj )                            { return (Vec_Ptr_t *)pObj->pNextFan1; }
+
+static inline void        Ivy_ObjSetSim( Ivy_Obj_t * pObj, Ivy_FraigSim_t * pSim )       { pObj->pFanout = (Ivy_Obj_t *)pSim; }
+static inline void        Ivy_ObjSetClassNodeLast( Ivy_Obj_t * pObj, Ivy_Obj_t * pLast ) { pObj->pNextFan0 = pLast; }
+static inline void        Ivy_ObjSetClassNodeRepr( Ivy_Obj_t * pObj, Ivy_Obj_t * pRepr ) { pObj->pNextFan0 = pRepr; }
+static inline void        Ivy_ObjSetClassNodeNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pNextFan1 = pNext; }
+static inline void        Ivy_ObjSetNodeHashNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext )  { pObj->pPrevFan0 = pNext; }
+static inline void        Ivy_ObjSetEquivListNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pPrevFan0 = pNext; }
+static inline void        Ivy_ObjSetEquivListPrev( Ivy_Obj_t * pObj, Ivy_Obj_t * pPrev ) { pObj->pPrevFan1 = pPrev; }
+static inline void        Ivy_ObjSetFraig( Ivy_Obj_t * pObj, Ivy_Obj_t * pNode )         { pObj->pEquiv    = pNode; }
+static inline void        Ivy_ObjSetSatNum( Ivy_Obj_t * pObj, int Num )                  { pObj->pNextFan0 = (Ivy_Obj_t *)(ABC_PTRUINT_T)Num;     }
+static inline void        Ivy_ObjSetFaninVec( Ivy_Obj_t * pObj, Vec_Ptr_t * vFanins )    { pObj->pNextFan1 = (Ivy_Obj_t *)vFanins; }
+
+static inline unsigned    Ivy_ObjRandomSim()                       { return (rand() << 24) ^ (rand() << 12) ^ rand(); }
+
+// iterate through equivalence classes
+#define Ivy_FraigForEachEquivClass( pList, pEnt )                 \
+    for ( pEnt = pList;                                           \
+          pEnt;                                                   \
+          pEnt = Ivy_ObjEquivListNext(pEnt) )
+#define Ivy_FraigForEachEquivClassSafe( pList, pEnt, pEnt2 )      \
+    for ( pEnt = pList,                                           \
+          pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL;         \
+          pEnt;                                                   \
+          pEnt = pEnt2,                                           \
+          pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL )
+// iterate through nodes in one class
+#define Ivy_FraigForEachClassNode( pClass, pEnt )                 \
+    for ( pEnt = pClass;                                          \
+          pEnt;                                                   \
+          pEnt = Ivy_ObjClassNodeNext(pEnt) )
+// iterate through nodes in the hash table
+#define Ivy_FraigForEachBinNode( pBin, pEnt )                     \
+    for ( pEnt = pBin;                                            \
+          pEnt;                                                   \
+          pEnt = Ivy_ObjNodeHashNext(pEnt) )
+
+static Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams );
+static Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams );
+static Ivy_Man_t *   Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, ABC_INT64_T nBTLimitGlobal, ABC_INT64_T nInsLimitGlobal, ABC_INT64_T * pnSatConfs, ABC_INT64_T * pnSatInspects );
+static void          Ivy_FraigPrint( Ivy_FraigMan_t * p );
+static void          Ivy_FraigStop( Ivy_FraigMan_t * p );
+static void          Ivy_FraigSimulate( Ivy_FraigMan_t * p );
+static void          Ivy_FraigSweep( Ivy_FraigMan_t * p );
+static Ivy_Obj_t *   Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld );
+static int           Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 );
+static int           Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj );
+static void          Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 );
+static int           Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew );
+static void          Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew );
+static int           Ivy_FraigMiterStatus( Ivy_Man_t * pMan );
+static void          Ivy_FraigMiterProve( Ivy_FraigMan_t * p );
+static void          Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, abctime clk, int fVerbose );
+static int *         Ivy_FraigCreateModel( Ivy_FraigMan_t * p );
+
+static int Ivy_FraigNodesAreEquivBdd( Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2 );
+static int Ivy_FraigCheckCone( Ivy_FraigMan_t * pGlo, Ivy_Man_t * p, Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2, int nConfLimit );
+
+static ABC_INT64_T s_nBTLimitGlobal = 0;
+static ABC_INT64_T s_nInsLimitGlobal = 0;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the default solving parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigParamsDefault( Ivy_FraigParams_t * pParams )
+{
+    memset( pParams, 0, sizeof(Ivy_FraigParams_t) );
+    pParams->nSimWords        =      32;  // the number of words in the simulation info
+    pParams->dSimSatur        =   0.005;  // the ratio of refined classes when saturation is reached
+    pParams->fPatScores       =       0;  // enables simulation pattern scoring
+    pParams->MaxScore         =      25;  // max score after which resimulation is used
+    pParams->fDoSparse        =       1;  // skips sparse functions
+//    pParams->dActConeRatio    =    0.05;  // the ratio of cone to be bumped
+//    pParams->dActConeBumpMax  =     5.0;  // the largest bump of activity
+    pParams->dActConeRatio    =     0.3;  // the ratio of cone to be bumped
+    pParams->dActConeBumpMax  =    10.0;  // the largest bump of activity
+
+    pParams->nBTLimitNode     =     100;  // conflict limit at a node
+    pParams->nBTLimitMiter    =  500000;  // conflict limit at an output
+//    pParams->nBTLimitGlobal   =       0;  // conflict limit global
+//    pParams->nInsLimitGlobal  =       0;  // inspection limit global
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs combinational equivalence checking for the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FraigProve( Ivy_Man_t ** ppManAig, void * pPars )
+{
+    Prove_Params_t * pParams = (Prove_Params_t *)pPars;
+    Ivy_FraigParams_t Params, * pIvyParams = &Params; 
+    Ivy_Man_t * pManAig, * pManTemp;
+    int RetValue, nIter;
+    abctime clk;//, Counter;
+    ABC_INT64_T nSatConfs = 0, nSatInspects = 0;
+
+    // start the network and parameters
+    pManAig = *ppManAig;
+    Ivy_FraigParamsDefault( pIvyParams );
+    pIvyParams->fVerbose = pParams->fVerbose;
+    pIvyParams->fProve = 1;
+
+    if ( pParams->fVerbose )
+    {
+        printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n",
+            pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" );
+        printf( "Miter = %d (%3.1f).  Rwr = %d (%3.1f).  Fraig = %d (%3.1f).  Last = %d.\n", 
+            pParams->nMiteringLimitStart,  pParams->nMiteringLimitMulti, 
+            pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti,
+            pParams->nFraigingLimitStart,  pParams->nFraigingLimitMulti, pParams->nMiteringLimitLast );
+    }
+
+    // if SAT only, solve without iteration
+    if ( !pParams->fUseRewriting && !pParams->fUseFraiging )
+    {
+        clk = Abc_Clock();
+        pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig);
+        pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams );  Ivy_ManStop( pManTemp );
+        RetValue = Ivy_FraigMiterStatus( pManAig );
+        Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose );
+        *ppManAig = pManAig;
+        return RetValue;
+    }
+
+    if ( Ivy_ManNodeNum(pManAig) < 500 )
+    {
+        // run the first mitering
+        clk = Abc_Clock();
+        pIvyParams->nBTLimitMiter = pParams->nMiteringLimitStart / Ivy_ManPoNum(pManAig);
+        pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams );  Ivy_ManStop( pManTemp );
+        RetValue = Ivy_FraigMiterStatus( pManAig );
+        Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose );
+        if ( RetValue >= 0 )
+        {
+            *ppManAig = pManAig;
+            return RetValue;
+        }
+    }
+
+    // check the current resource limits
+    RetValue = -1;
+    for ( nIter = 0; nIter < pParams->nItersMax; nIter++ )
+    {
+        if ( pParams->fVerbose )
+        {
+            printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1, 
+                 (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), 
+                 (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) );
+            fflush( stdout );
+        }
+
+        // try rewriting
+        if ( pParams->fUseRewriting )
+        { // bug in Ivy_NodeFindCutsAll() when leaves are identical!
+/*
+            clk = Abc_Clock();
+            Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter));
+            pManAig = Ivy_ManRwsat( pManAig, 0 );  
+            RetValue = Ivy_FraigMiterStatus( pManAig );
+            Ivy_FraigMiterPrint( pManAig, "Rewriting  ", clk, pParams->fVerbose );
+*/
+        }
+        if ( RetValue >= 0 )
+            break;
+
+        // catch the situation when ref pattern detects the bug
+        RetValue = Ivy_FraigMiterStatus( pManAig );
+        if ( RetValue >= 0 )
+            break;
+
+        // try fraiging followed by mitering
+        if ( pParams->fUseFraiging )
+        {
+            clk = Abc_Clock();
+            pIvyParams->nBTLimitNode  = (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter));
+            pIvyParams->nBTLimitMiter = 1 + (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)) / Ivy_ManPoNum(pManAig);
+            pManAig = Ivy_FraigPerform_int( pManTemp = pManAig, pIvyParams, pParams->nTotalBacktrackLimit, pParams->nTotalInspectLimit, &nSatConfs, &nSatInspects );  Ivy_ManStop( pManTemp );
+            RetValue = Ivy_FraigMiterStatus( pManAig );
+            Ivy_FraigMiterPrint( pManAig, "Fraiging   ", clk, pParams->fVerbose );
+        }
+        if ( RetValue >= 0 )
+            break;
+
+        // add to the number of backtracks and inspects
+        pParams->nTotalBacktracksMade += nSatConfs;
+        pParams->nTotalInspectsMade   += nSatInspects;
+        // check if global resource limit is reached
+        if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) ||
+             (pParams->nTotalInspectLimit   && pParams->nTotalInspectsMade   >= pParams->nTotalInspectLimit) )
+        {
+            printf( "Reached global limit on conflicts/inspects. Quitting.\n" );
+            *ppManAig = pManAig;
+            return -1;
+        }
+    }    
+/*
+    if ( RetValue < 0 )
+    {
+        if ( pParams->fVerbose )
+        {
+            printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast );
+            fflush( stdout );
+        }
+        clk = Abc_Clock();
+        pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig);
+        if ( pParams->nTotalBacktrackLimit )
+            s_nBTLimitGlobal  = pParams->nTotalBacktrackLimit - pParams->nTotalBacktracksMade;
+        if ( pParams->nTotalInspectLimit )
+            s_nInsLimitGlobal = pParams->nTotalInspectLimit -   pParams->nTotalInspectsMade;        
+        pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams );  Ivy_ManStop( pManTemp );
+        s_nBTLimitGlobal  = 0;
+        s_nInsLimitGlobal = 0;        
+        RetValue = Ivy_FraigMiterStatus( pManAig );
+        Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose );
+        // make sure that the sover never returns "undecided" when infinite resource limits are set
+        if( RetValue == -1 && pParams->nTotalInspectLimit == 0 &&
+            pParams->nTotalBacktrackLimit == 0 )
+        {
+            extern void Prove_ParamsPrint( Prove_Params_t * pParams );
+            Prove_ParamsPrint( pParams );
+            printf("ERROR: ABC has returned \"undecided\" in spite of no limits...\n");
+            exit(1);
+        }
+    }
+*/
+    // assign the model if it was proved by rewriting (const 1 miter)
+    if ( RetValue == 0 && pManAig->pData == NULL )
+    {
+        pManAig->pData = ABC_ALLOC( int, Ivy_ManPiNum(pManAig) );
+        memset( pManAig->pData, 0, sizeof(int) * Ivy_ManPiNum(pManAig) );
+    }
+    *ppManAig = pManAig;
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, ABC_INT64_T nBTLimitGlobal, ABC_INT64_T nInsLimitGlobal, ABC_INT64_T * pnSatConfs, ABC_INT64_T * pnSatInspects )
+{ 
+    Ivy_FraigMan_t * p;
+    Ivy_Man_t * pManAigNew;
+    abctime clk;
+    if ( Ivy_ManNodeNum(pManAig) == 0 )
+        return Ivy_ManDup(pManAig);
+clk = Abc_Clock();
+    assert( Ivy_ManLatchNum(pManAig) == 0 );
+    p = Ivy_FraigStart( pManAig, pParams );
+    // set global limits
+    p->nBTLimitGlobal  = nBTLimitGlobal;
+    p->nInsLimitGlobal = nInsLimitGlobal; 
+    
+    Ivy_FraigSimulate( p );
+    Ivy_FraigSweep( p );
+    pManAigNew = p->pManFraig;
+p->timeTotal = Abc_Clock() - clk;
+    if ( pnSatConfs )
+        *pnSatConfs = p->pSat? p->pSat->stats.conflicts : 0;
+    if ( pnSatInspects )
+        *pnSatInspects = p->pSat? p->pSat->stats.inspects : 0;
+    Ivy_FraigStop( p );
+    return pManAigNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_FraigPerform( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams )
+{
+    Ivy_FraigMan_t * p;
+    Ivy_Man_t * pManAigNew;
+    abctime clk;
+    if ( Ivy_ManNodeNum(pManAig) == 0 )
+        return Ivy_ManDup(pManAig);
+clk = Abc_Clock();
+    assert( Ivy_ManLatchNum(pManAig) == 0 );
+    p = Ivy_FraigStart( pManAig, pParams );
+    Ivy_FraigSimulate( p );
+    Ivy_FraigSweep( p );
+    pManAigNew = p->pManFraig;
+p->timeTotal = Abc_Clock() - clk;
+    Ivy_FraigStop( p );
+    return pManAigNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Applies brute-force SAT to the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_FraigMiter( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams )
+{
+    Ivy_FraigMan_t * p;
+    Ivy_Man_t * pManAigNew;
+    Ivy_Obj_t * pObj;
+    int i;
+    abctime clk;
+clk = Abc_Clock();
+    assert( Ivy_ManLatchNum(pManAig) == 0 );
+    p = Ivy_FraigStartSimple( pManAig, pParams );
+    // set global limits
+    p->nBTLimitGlobal  = s_nBTLimitGlobal;
+    p->nInsLimitGlobal = s_nInsLimitGlobal; 
+    // duplicate internal nodes
+    Ivy_ManForEachNode( p->pManAig, pObj, i )
+        pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) );
+    // try to prove each output of the miter
+    Ivy_FraigMiterProve( p );
+    // add the POs
+    Ivy_ManForEachPo( p->pManAig, pObj, i )
+        Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) );
+    // clean the new manager
+    Ivy_ManForEachObj( p->pManFraig, pObj, i )
+    {
+        if ( Ivy_ObjFaninVec(pObj) )
+            Vec_PtrFree( Ivy_ObjFaninVec(pObj) );
+        pObj->pNextFan0 = pObj->pNextFan1 = NULL;
+    }
+    // remove dangling nodes 
+    Ivy_ManCleanup( p->pManFraig );
+    pManAigNew = p->pManFraig;
+p->timeTotal = Abc_Clock() - clk;
+
+//printf( "Final nodes = %6d. ", Ivy_ManNodeNum(pManAigNew) );
+//ABC_PRT( "Time", p->timeTotal );
+    Ivy_FraigStop( p );
+    return pManAigNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the fraiging manager without simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams )
+{
+    Ivy_FraigMan_t * p;
+    // allocat the fraiging manager
+    p = ABC_ALLOC( Ivy_FraigMan_t, 1 );
+    memset( p, 0, sizeof(Ivy_FraigMan_t) );
+    p->pParams   = pParams;
+    p->pManAig   = pManAig;
+    p->pManFraig = Ivy_ManStartFrom( pManAig );
+    p->vPiVars   = Vec_PtrAlloc( 100 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the fraiging manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams )
+{
+    Ivy_FraigMan_t * p;
+    Ivy_FraigSim_t * pSims;
+    Ivy_Obj_t * pObj;
+    int i, k, EntrySize;
+    // clean the fanout representation
+    Ivy_ManForEachObj( pManAig, pObj, i )
+//        pObj->pEquiv = pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL;
+        assert( !pObj->pEquiv && !pObj->pFanout );
+    // allocat the fraiging manager
+    p = ABC_ALLOC( Ivy_FraigMan_t, 1 );
+    memset( p, 0, sizeof(Ivy_FraigMan_t) );
+    p->pParams   = pParams;
+    p->pManAig   = pManAig;
+    p->pManFraig = Ivy_ManStartFrom( pManAig );
+    // allocate simulation info
+    p->nSimWords    = pParams->nSimWords;
+//    p->pSimWords    = ABC_ALLOC( unsigned, Ivy_ManObjNum(pManAig) * p->nSimWords ); 
+    EntrySize    = sizeof(Ivy_FraigSim_t) + sizeof(unsigned) * p->nSimWords;
+    p->pSimWords = (char *)ABC_ALLOC( char, Ivy_ManObjNum(pManAig) * EntrySize ); 
+    memset( p->pSimWords, 0, EntrySize );
+    k = 0;
+    Ivy_ManForEachObj( pManAig, pObj, i )
+    {
+        pSims = (Ivy_FraigSim_t *)(p->pSimWords + EntrySize * k++);
+        pSims->pNext = NULL;
+        if ( Ivy_ObjIsNode(pObj) )
+        {
+            if ( p->pSimStart == NULL )
+                p->pSimStart = pSims;
+            else
+                ((Ivy_FraigSim_t *)(p->pSimWords + EntrySize * (k-2)))->pNext = pSims;
+            pSims->pFanin0 = Ivy_ObjSim( Ivy_ObjFanin0(pObj) );
+            pSims->pFanin1 = Ivy_ObjSim( Ivy_ObjFanin1(pObj) );
+            pSims->Type = (Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) << 2) | (Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)) << 1) | pObj->fPhase;
+        }
+        else
+        {
+            pSims->pFanin0 = NULL;
+            pSims->pFanin1 = NULL;
+            pSims->Type = 0;
+        }
+        Ivy_ObjSetSim( pObj, pSims );
+    }
+    assert( k == Ivy_ManObjNum(pManAig) );
+    // allocate storage for sim pattern
+    p->nPatWords  = Ivy_BitWordNum( Ivy_ManPiNum(pManAig) );
+    p->pPatWords  = ABC_ALLOC( unsigned, p->nPatWords ); 
+    p->pPatScores = ABC_ALLOC( int, 32 * p->nSimWords ); 
+    p->vPiVars    = Vec_PtrAlloc( 100 );
+    // set random number generator
+    srand( 0xABCABC );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the fraiging manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigStop( Ivy_FraigMan_t * p )
+{
+    if ( p->pParams->fVerbose )
+        Ivy_FraigPrint( p );
+    if ( p->vPiVars ) Vec_PtrFree( p->vPiVars );
+    if ( p->pSat ) sat_solver_delete( p->pSat );
+    ABC_FREE( p->pPatScores );
+    ABC_FREE( p->pPatWords );
+    ABC_FREE( p->pSimWords );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats for the fraiging manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigPrint( Ivy_FraigMan_t * p )
+{
+    double nMemory;
+    nMemory = (double)Ivy_ManObjNum(p->pManAig)*p->nSimWords*sizeof(unsigned)/(1<<20);
+    printf( "SimWords = %d. Rounds = %d. Mem = %0.2f MB.  ", p->nSimWords, p->nSimRounds, nMemory );
+    printf( "Classes: Beg = %d. End = %d.\n", p->nClassesBeg, p->nClassesEnd );
+//    printf( "Limits: BTNode = %d. BTMiter = %d.\n", p->pParams->nBTLimitNode, p->pParams->nBTLimitMiter );
+    printf( "Proof = %d. Counter-example = %d. Fail = %d. FailReal = %d. Zero = %d.\n", 
+        p->nSatProof, p->nSatCallsSat, p->nSatFails, p->nSatFailsReal, p->nClassesZero );
+    printf( "Final = %d. Miter = %d. Total = %d. Mux = %d. (Exor = %d.) SatVars = %d.\n", 
+        Ivy_ManNodeNum(p->pManFraig), p->nNodesMiter, Ivy_ManNodeNum(p->pManAig), 0, 0, p->nSatVars );
+    if ( p->pSat ) Sat_SolverPrintStats( stdout, p->pSat );
+    ABC_PRT( "AIG simulation  ", p->timeSim  );
+    ABC_PRT( "AIG traversal   ", p->timeTrav  );
+    ABC_PRT( "SAT solving     ", p->timeSat   );
+    ABC_PRT( "    Unsat       ", p->timeSatUnsat );
+    ABC_PRT( "    Sat         ", p->timeSatSat   );
+    ABC_PRT( "    Fail        ", p->timeSatFail  );
+    ABC_PRT( "Class refining  ", p->timeRef   );
+    ABC_PRT( "TOTAL RUNTIME   ", p->timeTotal );
+    if ( p->time1 ) { ABC_PRT( "time1           ", p->time1 ); }
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns random patterns to the PI node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_NodeAssignRandom( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj )
+{
+    Ivy_FraigSim_t * pSims;
+    int i;
+    assert( Ivy_ObjIsPi(pObj) );
+    pSims = Ivy_ObjSim(pObj);
+    for ( i = 0; i < p->nSimWords; i++ )
+        pSims->pData[i] = Ivy_ObjRandomSim();
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns constant patterns to the PI node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_NodeAssignConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int fConst1 )
+{
+    Ivy_FraigSim_t * pSims;
+    int i;
+    assert( Ivy_ObjIsPi(pObj) );
+    pSims = Ivy_ObjSim(pObj);
+    for ( i = 0; i < p->nSimWords; i++ )
+        pSims->pData[i] = fConst1? ~(unsigned)0 : 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assings random simulation info for the PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigAssignRandom( Ivy_FraigMan_t * p )
+{
+    Ivy_Obj_t * pObj;
+    int i;
+    Ivy_ManForEachPi( p->pManAig, pObj, i )
+        Ivy_NodeAssignRandom( p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assings distance-1 simulation info for the PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigAssignDist1( Ivy_FraigMan_t * p, unsigned * pPat )
+{
+    Ivy_Obj_t * pObj;
+    int i, Limit;
+    Ivy_ManForEachPi( p->pManAig, pObj, i )
+    {
+        Ivy_NodeAssignConst( p, pObj, Ivy_InfoHasBit(pPat, i) );
+//        printf( "%d", Ivy_InfoHasBit(pPat, i) );
+    }
+//    printf( "\n" );
+
+    Limit = IVY_MIN( Ivy_ManPiNum(p->pManAig), p->nSimWords * 32 - 1 );
+    for ( i = 0; i < Limit; i++ )
+        Ivy_InfoXorBit( Ivy_ObjSim( Ivy_ManPi(p->pManAig,i) )->pData, i+1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation info is composed of all zeros.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_NodeHasZeroSim( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj )
+{
+    Ivy_FraigSim_t * pSims;
+    int i;
+    pSims = Ivy_ObjSim(pObj);
+    for ( i = 0; i < p->nSimWords; i++ )
+        if ( pSims->pData[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation info is composed of all zeros.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_NodeComplementSim( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj )
+{
+    Ivy_FraigSim_t * pSims;
+    int i;
+    pSims = Ivy_ObjSim(pObj);
+    for ( i = 0; i < p->nSimWords; i++ )
+        pSims->pData[i] = ~pSims->pData[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation infos are equal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_NodeCompareSims( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 )
+{
+    Ivy_FraigSim_t * pSims0, * pSims1;
+    int i;
+    pSims0 = Ivy_ObjSim(pObj0);
+    pSims1 = Ivy_ObjSim(pObj1);
+    for ( i = 0; i < p->nSimWords; i++ )
+        if ( pSims0->pData[i] != pSims1->pData[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_NodeSimulateSim( Ivy_FraigMan_t * p, Ivy_FraigSim_t * pSims )
+{
+    unsigned * pData, * pData0, * pData1;
+    int i;
+    pData  = pSims->pData;
+    pData0 = pSims->pFanin0->pData;
+    pData1 = pSims->pFanin1->pData;
+    switch( pSims->Type )
+    {
+    case 0:
+        for ( i = 0; i < p->nSimWords; i++ )
+            pData[i] = (pData0[i] & pData1[i]);
+        break;
+    case 1:
+        for ( i = 0; i < p->nSimWords; i++ )
+            pData[i] = ~(pData0[i] & pData1[i]);
+        break;
+    case 2:
+        for ( i = 0; i < p->nSimWords; i++ )
+            pData[i] = (pData0[i] & ~pData1[i]);
+        break;
+    case 3:
+        for ( i = 0; i < p->nSimWords; i++ )
+            pData[i] = (~pData0[i] | pData1[i]);
+        break;
+    case 4:
+        for ( i = 0; i < p->nSimWords; i++ )
+            pData[i] = (~pData0[i] & pData1[i]);
+        break;
+    case 5:
+        for ( i = 0; i < p->nSimWords; i++ )
+            pData[i] = (pData0[i] | ~pData1[i]);
+        break;
+    case 6:
+        for ( i = 0; i < p->nSimWords; i++ )
+            pData[i] = ~(pData0[i] | pData1[i]);
+        break;
+    case 7:
+        for ( i = 0; i < p->nSimWords; i++ )
+            pData[i] = (pData0[i] | pData1[i]);
+        break;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_NodeSimulate( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj )
+{
+    Ivy_FraigSim_t * pSims, * pSims0, * pSims1;
+    int fCompl, fCompl0, fCompl1, i;
+    assert( !Ivy_IsComplement(pObj) );
+    // get hold of the simulation information
+    pSims  = Ivy_ObjSim(pObj);
+    pSims0 = Ivy_ObjSim(Ivy_ObjFanin0(pObj));
+    pSims1 = Ivy_ObjSim(Ivy_ObjFanin1(pObj));
+    // get complemented attributes of the children using their random info
+    fCompl  = pObj->fPhase;
+    fCompl0 = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj));
+    fCompl1 = Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj));
+    // simulate
+    if ( fCompl0 && fCompl1 )
+    {
+        if ( fCompl )
+            for ( i = 0; i < p->nSimWords; i++ )
+                pSims->pData[i] = (pSims0->pData[i] | pSims1->pData[i]);
+        else
+            for ( i = 0; i < p->nSimWords; i++ )
+                pSims->pData[i] = ~(pSims0->pData[i] | pSims1->pData[i]);
+    }
+    else if ( fCompl0 && !fCompl1 )
+    {
+        if ( fCompl )
+            for ( i = 0; i < p->nSimWords; i++ )
+                pSims->pData[i] = (pSims0->pData[i] | ~pSims1->pData[i]);
+        else
+            for ( i = 0; i < p->nSimWords; i++ )
+                pSims->pData[i] = (~pSims0->pData[i] & pSims1->pData[i]);
+    }
+    else if ( !fCompl0 && fCompl1 )
+    {
+        if ( fCompl )
+            for ( i = 0; i < p->nSimWords; i++ )
+                pSims->pData[i] = (~pSims0->pData[i] | pSims1->pData[i]);
+        else
+            for ( i = 0; i < p->nSimWords; i++ )
+                pSims->pData[i] = (pSims0->pData[i] & ~pSims1->pData[i]);
+    }
+    else // if ( !fCompl0 && !fCompl1 )
+    {
+        if ( fCompl )
+            for ( i = 0; i < p->nSimWords; i++ )
+                pSims->pData[i] = ~(pSims0->pData[i] & pSims1->pData[i]);
+        else
+            for ( i = 0; i < p->nSimWords; i++ )
+                pSims->pData[i] = (pSims0->pData[i] & pSims1->pData[i]);
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash value using simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Ivy_NodeHash( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj )
+{
+    static int s_FPrimes[128] = { 
+        1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 
+        1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 
+        2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 
+        2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 
+        3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 
+        3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 
+        4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 
+        4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 
+        5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 
+        6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 
+        6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 
+        7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 
+        8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+    };
+    Ivy_FraigSim_t * pSims;
+    unsigned uHash;
+    int i;
+    assert( p->nSimWords <= 128 );
+    uHash = 0;
+    pSims  = Ivy_ObjSim(pObj);
+    for ( i = 0; i < p->nSimWords; i++ )
+        uHash ^= pSims->pData[i] * s_FPrimes[i];
+    return uHash;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates AIG manager.]
+
+  Description [Assumes that the PI simulation info is attached.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigSimulateOne( Ivy_FraigMan_t * p )
+{
+    Ivy_Obj_t * pObj;
+    int i;
+    abctime clk;
+clk = Abc_Clock();
+    Ivy_ManForEachNode( p->pManAig, pObj, i )
+    {
+        Ivy_NodeSimulate( p, pObj );
+/*
+        if ( Ivy_ObjFraig(pObj) == NULL )
+            printf( "%3d --- -- %d  :  ", pObj->Id, pObj->fPhase );
+        else
+            printf( "%3d %3d %2d %d  :  ", pObj->Id, Ivy_Regular(Ivy_ObjFraig(pObj))->Id, Ivy_ObjSatNum(Ivy_Regular(Ivy_ObjFraig(pObj))), pObj->fPhase );
+        Extra_PrintBinary( stdout, Ivy_ObjSim(pObj), 30 );
+        printf( "\n" );
+*/
+    }
+p->timeSim += Abc_Clock() - clk;
+p->nSimRounds++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates AIG manager.]
+
+  Description [Assumes that the PI simulation info is attached.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigSimulateOneSim( Ivy_FraigMan_t * p )
+{
+    Ivy_FraigSim_t * pSims;
+    abctime clk;
+clk = Abc_Clock();
+    for ( pSims = p->pSimStart; pSims; pSims = pSims->pNext )
+        Ivy_NodeSimulateSim( p, pSims );
+p->timeSim += Abc_Clock() - clk;
+p->nSimRounds++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one node to the equivalence class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_NodeAddToClass( Ivy_Obj_t * pClass, Ivy_Obj_t * pObj )
+{
+    if ( Ivy_ObjClassNodeNext(pClass) == NULL )
+        Ivy_ObjSetClassNodeNext( pClass, pObj );
+    else
+        Ivy_ObjSetClassNodeNext( Ivy_ObjClassNodeLast(pClass), pObj );
+    Ivy_ObjSetClassNodeLast( pClass, pObj );
+    Ivy_ObjSetClassNodeRepr( pObj, pClass );
+    Ivy_ObjSetClassNodeNext( pObj, NULL );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds equivalence class to the list of classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigAddClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass )
+{
+    if ( pList->pHead == NULL )
+    {
+        pList->pHead = pClass;
+        pList->pTail = pClass;
+        Ivy_ObjSetEquivListPrev( pClass, NULL );
+        Ivy_ObjSetEquivListNext( pClass, NULL ); 
+    }
+    else
+    {
+        Ivy_ObjSetEquivListNext( pList->pTail, pClass ); 
+        Ivy_ObjSetEquivListPrev( pClass, pList->pTail );
+        Ivy_ObjSetEquivListNext( pClass, NULL ); 
+        pList->pTail = pClass;
+    }
+    pList->nItems++;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Updates the list of classes after base class has split.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigInsertClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pBase, Ivy_Obj_t * pClass )
+{
+    Ivy_ObjSetEquivListPrev( pClass, pBase );
+    Ivy_ObjSetEquivListNext( pClass, Ivy_ObjEquivListNext(pBase) ); 
+    if ( Ivy_ObjEquivListNext(pBase) )
+        Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pBase), pClass );
+    Ivy_ObjSetEquivListNext( pBase, pClass ); 
+    if ( pList->pTail == pBase )
+        pList->pTail = pClass;
+    pList->nItems++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes equivalence class from the list of classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigRemoveClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass )
+{
+    if ( pList->pHead == pClass )
+        pList->pHead = Ivy_ObjEquivListNext(pClass);
+    if ( pList->pTail == pClass )
+        pList->pTail = Ivy_ObjEquivListPrev(pClass);
+    if ( Ivy_ObjEquivListPrev(pClass) )
+        Ivy_ObjSetEquivListNext( Ivy_ObjEquivListPrev(pClass), Ivy_ObjEquivListNext(pClass) ); 
+    if ( Ivy_ObjEquivListNext(pClass) )
+        Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pClass), Ivy_ObjEquivListPrev(pClass) );
+    Ivy_ObjSetEquivListNext( pClass, NULL ); 
+    Ivy_ObjSetEquivListPrev( pClass, NULL );
+    pClass->fMarkA = 0;
+    pList->nItems--;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of pairs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FraigCountPairsClasses( Ivy_FraigMan_t * p )
+{
+    Ivy_Obj_t * pClass, * pNode;
+    int nPairs = 0, nNodes;
+    return nPairs;
+
+    Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass )
+    {
+        nNodes = 0;
+        Ivy_FraigForEachClassNode( pClass, pNode )
+            nNodes++;
+        nPairs += nNodes * (nNodes - 1) / 2;
+    }
+    return nPairs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates initial simulation classes.]
+
+  Description [Assumes that simulation info is assigned.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigCreateClasses( Ivy_FraigMan_t * p )
+{
+    Ivy_Obj_t ** pTable;
+    Ivy_Obj_t * pObj, * pConst1, * pBin, * pEntry;
+    int i, nTableSize;
+    unsigned Hash;
+    pConst1 = Ivy_ManConst1(p->pManAig);
+    // allocate the table
+    nTableSize = Ivy_ManObjNum(p->pManAig) / 2 + 13;
+    pTable = ABC_ALLOC( Ivy_Obj_t *, nTableSize ); 
+    memset( pTable, 0, sizeof(Ivy_Obj_t *) * nTableSize );
+    // collect nodes into the table
+    Ivy_ManForEachObj( p->pManAig, pObj, i )
+    {
+        if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) )
+            continue;
+        Hash = Ivy_NodeHash( p, pObj );
+        if ( Hash == 0 && Ivy_NodeHasZeroSim( p, pObj ) )
+        {
+            Ivy_NodeAddToClass( pConst1, pObj );
+            continue;
+        }
+        // add the node to the table
+        pBin = pTable[Hash % nTableSize];
+        Ivy_FraigForEachBinNode( pBin, pEntry )
+            if ( Ivy_NodeCompareSims( p, pEntry, pObj ) )
+            {
+                Ivy_NodeAddToClass( pEntry, pObj );
+                break;
+            }
+        // check if the entry was added
+        if ( pEntry )
+            continue;
+        Ivy_ObjSetNodeHashNext( pObj, pBin );
+        pTable[Hash % nTableSize] = pObj;
+    }
+    // collect non-trivial classes
+    assert( p->lClasses.pHead == NULL );
+    Ivy_ManForEachObj( p->pManAig, pObj, i )
+    {
+        if ( !Ivy_ObjIsConst1(pObj) && !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) )
+            continue;
+        Ivy_ObjSetNodeHashNext( pObj, NULL );
+        if ( Ivy_ObjClassNodeRepr(pObj) == NULL )
+        {
+            assert( Ivy_ObjClassNodeNext(pObj) == NULL );
+            continue;
+        }
+        // recognize the head of the class
+        if ( Ivy_ObjClassNodeNext( Ivy_ObjClassNodeRepr(pObj) ) != NULL )
+            continue;
+        // clean the class representative and add it to the list
+        Ivy_ObjSetClassNodeRepr( pObj, NULL );
+        Ivy_FraigAddClass( &p->lClasses, pObj );
+    }
+    // free the table
+    ABC_FREE( pTable );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively refines the class after simulation.]
+
+  Description [Returns 1 if the class has changed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FraigRefineClass_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass )
+{
+    Ivy_Obj_t * pClassNew, * pListOld, * pListNew, * pNode;
+    int RetValue = 0;
+    // check if there is refinement
+    pListOld = pClass;
+    Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClass), pClassNew )
+    {
+        if ( !Ivy_NodeCompareSims(p, pClass, pClassNew) )
+        {
+            if ( p->pParams->fPatScores )
+                Ivy_FraigAddToPatScores( p, pClass, pClassNew );
+            break;
+        }
+        pListOld = pClassNew;
+    }
+    if ( pClassNew == NULL )
+        return 0;
+    // set representative of the new class
+    Ivy_ObjSetClassNodeRepr( pClassNew, NULL );
+    // start the new list
+    pListNew = pClassNew;
+    // go through the remaining nodes and sort them into two groups:
+    // (1) matches of the old node; (2) non-matches of the old node
+    Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClassNew), pNode )
+        if ( Ivy_NodeCompareSims( p, pClass, pNode ) )
+        {
+            Ivy_ObjSetClassNodeNext( pListOld, pNode );
+            pListOld = pNode;
+        }
+        else
+        {
+            Ivy_ObjSetClassNodeNext( pListNew, pNode );
+            Ivy_ObjSetClassNodeRepr( pNode, pClassNew );
+            pListNew = pNode;
+        }
+    // finish both lists
+    Ivy_ObjSetClassNodeNext( pListNew, NULL );
+    Ivy_ObjSetClassNodeNext( pListOld, NULL );
+    // update the list of classes
+    Ivy_FraigInsertClass( &p->lClasses, pClass, pClassNew );
+    // if the old class is trivial, remove it
+    if ( Ivy_ObjClassNodeNext(pClass) == NULL )
+        Ivy_FraigRemoveClass( &p->lClasses, pClass );
+    // if the new class is trivial, remove it; otherwise, try to refine it
+    if ( Ivy_ObjClassNodeNext(pClassNew) == NULL )
+        Ivy_FraigRemoveClass( &p->lClasses, pClassNew );
+    else
+        RetValue = Ivy_FraigRefineClass_rec( p, pClassNew );
+    return RetValue + 1;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Creates the counter-example from the successful pattern.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigCheckOutputSimsSavePattern( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj )
+{ 
+    Ivy_FraigSim_t * pSims;
+    int i, k, BestPat, * pModel;
+    // find the word of the pattern
+    pSims = Ivy_ObjSim(pObj);
+    for ( i = 0; i < p->nSimWords; i++ )
+        if ( pSims->pData[i] )
+            break;
+    assert( i < p->nSimWords );
+    // find the bit of the pattern
+    for ( k = 0; k < 32; k++ )
+        if ( pSims->pData[i] & (1 << k) )
+            break;
+    assert( k < 32 );
+    // determine the best pattern
+    BestPat = i * 32 + k;
+    // fill in the counter-example data
+    pModel = ABC_ALLOC( int, Ivy_ManPiNum(p->pManFraig) );
+    Ivy_ManForEachPi( p->pManAig, pObj, i )
+    {
+        pModel[i] = Ivy_InfoHasBit(Ivy_ObjSim(pObj)->pData, BestPat);
+//        printf( "%d", pModel[i] );
+    }
+//    printf( "\n" );
+    // set the model
+    assert( p->pManFraig->pData == NULL );
+    p->pManFraig->pData = pModel;
+    return;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the one of the output is already non-constant 0.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FraigCheckOutputSims( Ivy_FraigMan_t * p )
+{
+    Ivy_Obj_t * pObj;
+    int i;
+    // make sure the reference simulation pattern does not detect the bug
+//    pObj = Ivy_ManPo( p->pManAig, 0 );
+    Ivy_ManForEachPo( p->pManAig, pObj, i )
+    {
+        assert( Ivy_ObjFanin0(pObj)->fPhase == (unsigned)Ivy_ObjFaninC0(pObj) ); // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) == 0
+        // complement simulation info
+//        if ( Ivy_ObjFanin0(pObj)->fPhase ^ Ivy_ObjFaninC0(pObj) ) // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj))
+//            Ivy_NodeComplementSim( p, Ivy_ObjFanin0(pObj) );
+        // check 
+        if ( !Ivy_NodeHasZeroSim( p, Ivy_ObjFanin0(pObj) ) )
+        {
+            // create the counter-example from this pattern
+            Ivy_FraigCheckOutputSimsSavePattern( p, Ivy_ObjFanin0(pObj) );
+            return 1;
+        }
+        // complement simulation info
+//        if ( Ivy_ObjFanin0(pObj)->fPhase ^ Ivy_ObjFaninC0(pObj) )
+//            Ivy_NodeComplementSim( p, Ivy_ObjFanin0(pObj) );
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines the classes after simulation.]
+
+  Description [Assumes that simulation info is assigned. Returns the
+  number of classes refined.]
+               
+  SideEffects [Large equivalence class of constant 0 may cause problems.]
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FraigRefineClasses( Ivy_FraigMan_t * p )
+{
+    Ivy_Obj_t * pClass, * pClass2;
+    int RetValue, Counter = 0;
+    abctime clk;
+    // check if some outputs already became non-constant
+    // this is a special case when computation can be stopped!!!
+    if ( p->pParams->fProve )
+        Ivy_FraigCheckOutputSims( p );
+    if ( p->pManFraig->pData )
+        return 0;
+    // refine the classed
+clk = Abc_Clock();
+    Ivy_FraigForEachEquivClassSafe( p->lClasses.pHead, pClass, pClass2 )
+    {
+        if ( pClass->fMarkA )
+            continue;
+        RetValue = Ivy_FraigRefineClass_rec( p, pClass );
+        Counter += ( RetValue > 0 );
+//if ( Ivy_ObjIsConst1(pClass) )
+//printf( "%d ", RetValue );
+//if ( Ivy_ObjIsConst1(pClass) )
+//    p->time1 += Abc_Clock() - clk;
+    }
+p->timeRef += Abc_Clock() - clk;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print the class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigPrintClass( Ivy_Obj_t * pClass )
+{
+    Ivy_Obj_t * pObj;
+    printf( "Class {" );
+    Ivy_FraigForEachClassNode( pClass, pObj )
+        printf( " %d(%d)%c", pObj->Id, pObj->Level, pObj->fPhase? '+' : '-' );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of elements in the class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FraigCountClassNodes( Ivy_Obj_t * pClass )
+{
+    Ivy_Obj_t * pObj;
+    int Counter = 0;
+    Ivy_FraigForEachClassNode( pClass, pObj )
+        Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints simulation classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigPrintSimClasses( Ivy_FraigMan_t * p )
+{
+    Ivy_Obj_t * pClass;
+    Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass )
+    {
+//        Ivy_FraigPrintClass( pClass );
+        printf( "%d ", Ivy_FraigCountClassNodes( pClass ) );
+    }
+//    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generated const 0 pattern.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigSavePattern0( Ivy_FraigMan_t * p )
+{
+    memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [[Generated const 1 pattern.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigSavePattern1( Ivy_FraigMan_t * p )
+{
+    memset( p->pPatWords, 0xff, sizeof(unsigned) * p->nPatWords );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generates the counter-example satisfying the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Ivy_FraigCreateModel( Ivy_FraigMan_t * p )
+{
+    int * pModel;
+    Ivy_Obj_t * pObj;
+    int i;
+    pModel = ABC_ALLOC( int, Ivy_ManPiNum(p->pManFraig) );
+    Ivy_ManForEachPi( p->pManFraig, pObj, i )
+//        pModel[i] = ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True );
+        pModel[i] = ( p->pSat->model[Ivy_ObjSatNum(pObj)] == l_True );
+    return pModel;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Copy pattern from the solver into the internal storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigSavePattern( Ivy_FraigMan_t * p )
+{
+    Ivy_Obj_t * pObj;
+    int i;
+    memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+    Ivy_ManForEachPi( p->pManFraig, pObj, i )
+//    Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPiVars, pObj, i )
+//        if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True )
+        if ( p->pSat->model[Ivy_ObjSatNum(pObj)] == l_True )
+            Ivy_InfoSetBit( p->pPatWords, i );
+//            Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Copy pattern from the solver into the internal storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigSavePattern2( Ivy_FraigMan_t * p )
+{
+    Ivy_Obj_t * pObj;
+    int i;
+    memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+//    Ivy_ManForEachPi( p->pManFraig, pObj, i )
+    Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPiVars, pObj, i )
+//        if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True )
+        if ( p->pSat->model[Ivy_ObjSatNum(pObj)] == l_True )
+//            Ivy_InfoSetBit( p->pPatWords, i );
+            Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Copy pattern from the solver into the internal storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigSavePattern3( Ivy_FraigMan_t * p )
+{
+    Ivy_Obj_t * pObj;
+    int i;
+    for ( i = 0; i < p->nPatWords; i++ )
+        p->pPatWords[i] = Ivy_ObjRandomSim();
+    Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPiVars, pObj, i )
+//        if ( Ivy_InfoHasBit( p->pPatWords, pObj->Id - 1 ) ^ (p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True) )
+        if ( Ivy_InfoHasBit( p->pPatWords, pObj->Id - 1 ) ^ sat_solver_var_value(p->pSat, Ivy_ObjSatNum(pObj)) )
+            Ivy_InfoXorBit( p->pPatWords, pObj->Id - 1 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs simulation of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigSimulate( Ivy_FraigMan_t * p )
+{
+    int nChanges, nClasses;
+    // start the classes
+    Ivy_FraigAssignRandom( p );
+    Ivy_FraigSimulateOne( p );
+    Ivy_FraigCreateClasses( p );
+//printf( "Starting classes = %5d.   Pairs = %6d.\n", p->lClasses.nItems, Ivy_FraigCountPairsClasses(p) );
+    // refine classes by walking 0/1 patterns
+    Ivy_FraigSavePattern0( p );
+    Ivy_FraigAssignDist1( p, p->pPatWords );
+    Ivy_FraigSimulateOne( p );
+    nChanges = Ivy_FraigRefineClasses( p );
+    if ( p->pManFraig->pData )
+        return;
+//printf( "Refined classes  = %5d.   Changes = %4d.   Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) );
+    Ivy_FraigSavePattern1( p );
+    Ivy_FraigAssignDist1( p, p->pPatWords );
+    Ivy_FraigSimulateOne( p );
+    nChanges = Ivy_FraigRefineClasses( p );
+    if ( p->pManFraig->pData )
+        return;
+//printf( "Refined classes  = %5d.   Changes = %4d.   Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) );
+    // refine classes by random simulation
+    do {
+        Ivy_FraigAssignRandom( p );
+        Ivy_FraigSimulateOne( p );
+        nClasses = p->lClasses.nItems;
+        nChanges = Ivy_FraigRefineClasses( p );
+        if ( p->pManFraig->pData )
+            return;
+//printf( "Refined classes  = %5d.   Changes = %4d.   Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) );
+    } while ( (double)nChanges / nClasses > p->pParams->dSimSatur );
+//    Ivy_FraigPrintSimClasses( p );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans pattern scores.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigCleanPatScores( Ivy_FraigMan_t * p )
+{
+    int i, nLimit = p->nSimWords * 32;
+    for ( i = 0; i < nLimit; i++ )
+        p->pPatScores[i] = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds to pattern scores.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew )
+{
+    Ivy_FraigSim_t * pSims0, * pSims1;
+    unsigned uDiff;
+    int i, w;
+    // get hold of the simulation information
+    pSims0 = Ivy_ObjSim(pClass);
+    pSims1 = Ivy_ObjSim(pClassNew);
+    // iterate through the differences and record the score
+    for ( w = 0; w < p->nSimWords; w++ )
+    {
+        uDiff = pSims0->pData[w] ^ pSims1->pData[w];
+        if ( uDiff == 0 )
+            continue;
+        for ( i = 0; i < 32; i++ )
+            if ( uDiff & ( 1 << i ) )
+                p->pPatScores[w*32+i]++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Selects the best pattern.]
+
+  Description [Returns 1 if such pattern is found.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FraigSelectBestPat( Ivy_FraigMan_t * p )
+{
+    Ivy_FraigSim_t * pSims;
+    Ivy_Obj_t * pObj;
+    int i, nLimit = p->nSimWords * 32, MaxScore = 0, BestPat = -1;
+    for ( i = 1; i < nLimit; i++ )
+    {
+        if ( MaxScore < p->pPatScores[i] )
+        {
+            MaxScore = p->pPatScores[i];
+            BestPat = i;
+        }
+    }
+    if ( MaxScore == 0 )
+        return 0;
+//    if ( MaxScore > p->pParams->MaxScore )
+//    printf( "Max score is %3d.  ", MaxScore );
+    // copy the best pattern into the selected pattern
+    memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+    Ivy_ManForEachPi( p->pManAig, pObj, i )
+    {
+        pSims = Ivy_ObjSim(pObj);
+        if ( Ivy_InfoHasBit(pSims->pData, BestPat) )
+            Ivy_InfoSetBit(p->pPatWords, i);
+    }
+    return MaxScore;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulates fraiging manager after finding a counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigResimulate( Ivy_FraigMan_t * p )
+{
+    int nChanges;
+    Ivy_FraigAssignDist1( p, p->pPatWords );
+    Ivy_FraigSimulateOne( p );
+    if ( p->pParams->fPatScores )
+        Ivy_FraigCleanPatScores( p );
+    nChanges = Ivy_FraigRefineClasses( p );
+    if ( p->pManFraig->pData )
+        return;
+    if ( nChanges < 1 )
+        printf( "Error: A counter-example did not refine classes!\n" );
+    assert( nChanges >= 1 );
+//printf( "Refined classes! = %5d.   Changes = %4d.\n", p->lClasses.nItems, nChanges );
+    if ( !p->pParams->fPatScores )
+        return;
+
+    // perform additional simulation using dist1 patterns derived from successful patterns
+    while ( Ivy_FraigSelectBestPat(p) > p->pParams->MaxScore )
+    {
+        Ivy_FraigAssignDist1( p, p->pPatWords );
+        Ivy_FraigSimulateOne( p );
+        Ivy_FraigCleanPatScores( p );
+        nChanges = Ivy_FraigRefineClasses( p );
+        if ( p->pManFraig->pData )
+            return;
+//printf( "Refined class!!! = %5d.   Changes = %4d.   Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) );
+        if ( nChanges == 0 )
+            break;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the status of the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, abctime clk, int fVerbose )
+{
+    if ( !fVerbose )
+        return;
+    printf( "Nodes = %7d.  Levels = %4d.  ", Ivy_ManNodeNum(pNtk), Ivy_ManLevels(pNtk) );
+    ABC_PRT( pString, Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports the status of the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FraigMiterStatus( Ivy_Man_t * pMan )
+{
+    Ivy_Obj_t * pObj, * pObjNew;
+    int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0;
+    if ( pMan->pData )
+        return 0;
+    Ivy_ManForEachPo( pMan, pObj, i )
+    {
+        pObjNew = Ivy_ObjChild0(pObj);
+        // check if the output is constant 1
+        if ( pObjNew == pMan->pConst1 )
+        {
+            CountNonConst0++;
+            continue;
+        }
+        // check if the output is constant 0
+        if ( pObjNew == Ivy_Not(pMan->pConst1) )
+        {
+            CountConst0++;
+            continue;
+        }
+/*
+        // check if the output is a primary input
+        if ( Ivy_ObjIsPi(Ivy_Regular(pObjNew)) )
+        {
+            CountNonConst0++;
+            continue;
+        }
+*/
+        // check if the output can be constant 0
+        if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) )
+        {
+            CountNonConst0++;
+            continue;
+        }
+        CountUndecided++;
+    }
+/*
+    if ( p->pParams->fVerbose )
+    {
+        printf( "Miter has %d outputs. ", Ivy_ManPoNum(p->pManAig) );
+        printf( "Const0 = %d.  ", CountConst0 );
+        printf( "NonConst0 = %d.  ", CountNonConst0 );
+        printf( "Undecided = %d.  ", CountUndecided );
+        printf( "\n" );
+    }
+*/
+    if ( CountNonConst0 )
+        return 0;
+    if ( CountUndecided )
+        return -1;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tries to prove each output of the miter until encountering a sat output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigMiterProve( Ivy_FraigMan_t * p )
+{
+    Ivy_Obj_t * pObj, * pObjNew;
+    int i, RetValue;
+    abctime clk = Abc_Clock();
+    int fVerbose = 0;
+    Ivy_ManForEachPo( p->pManAig, pObj, i )
+    {
+        if ( i && fVerbose )
+        {
+            ABC_PRT( "Time", Abc_Clock() -clk );
+        }
+        pObjNew = Ivy_ObjChild0Equiv(pObj);
+        // check if the output is constant 1
+        if ( pObjNew == p->pManFraig->pConst1 )
+        {
+            if ( fVerbose )
+                printf( "Output %2d (out of %2d) is constant 1.  ", i, Ivy_ManPoNum(p->pManAig) );
+            // assing constant 0 model
+            p->pManFraig->pData = ABC_ALLOC( int, Ivy_ManPiNum(p->pManFraig) );
+            memset( p->pManFraig->pData, 0, sizeof(int) * Ivy_ManPiNum(p->pManFraig) );
+            break;
+        }
+        // check if the output is constant 0
+        if ( pObjNew == Ivy_Not(p->pManFraig->pConst1) )
+        {
+            if ( fVerbose )
+                printf( "Output %2d (out of %2d) is already constant 0.  ", i, Ivy_ManPoNum(p->pManAig) );
+            continue;
+        }
+        // check if the output can be constant 0
+        if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) )
+        {
+            if ( fVerbose )
+                printf( "Output %2d (out of %2d) cannot be constant 0.  ", i, Ivy_ManPoNum(p->pManAig) );
+            // assing constant 0 model
+            p->pManFraig->pData = ABC_ALLOC( int, Ivy_ManPiNum(p->pManFraig) );
+            memset( p->pManFraig->pData, 0, sizeof(int) * Ivy_ManPiNum(p->pManFraig) );
+            break;
+        }
+/*
+        // check the representative of this node
+        pRepr = Ivy_ObjClassNodeRepr(Ivy_ObjFanin0(pObj));
+        if ( Ivy_Regular(pRepr) != p->pManAig->pConst1 )
+            printf( "Representative is not constant 1.\n" );
+        else
+            printf( "Representative is constant 1.\n" );
+*/
+        // try to prove the output constant 0
+        RetValue = Ivy_FraigNodeIsConst( p, Ivy_Regular(pObjNew) );
+        if ( RetValue == 1 )  // proved equivalent
+        {
+            if ( fVerbose )
+                printf( "Output %2d (out of %2d) was proved constant 0.  ", i, Ivy_ManPoNum(p->pManAig) );
+            // set the constant miter
+            Ivy_ObjFanin0(pObj)->pEquiv = Ivy_NotCond( p->pManFraig->pConst1, !Ivy_ObjFaninC0(pObj) );
+            continue;
+        }
+        if ( RetValue == -1 ) // failed
+        {
+            if ( fVerbose )
+                printf( "Output %2d (out of %2d) has timed out at %d backtracks.  ", i, Ivy_ManPoNum(p->pManAig), p->pParams->nBTLimitMiter );
+            continue;
+        }
+        // proved satisfiable
+        if ( fVerbose )
+            printf( "Output %2d (out of %2d) was proved NOT a constant 0.  ", i, Ivy_ManPoNum(p->pManAig) );
+        // create the model
+        p->pManFraig->pData = Ivy_FraigCreateModel(p);
+        break;
+    }
+    if ( fVerbose )
+    {
+        ABC_PRT( "Time", Abc_Clock() -clk );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigSweep( Ivy_FraigMan_t * p )
+{
+    Ivy_Obj_t * pObj;//, * pTemp;
+    int i, k = 0;
+p->nClassesZero = p->lClasses.pHead? (Ivy_ObjIsConst1(p->lClasses.pHead) ? Ivy_FraigCountClassNodes(p->lClasses.pHead) : 0) : 0;
+p->nClassesBeg  = p->lClasses.nItems;
+    // duplicate internal nodes
+    p->pProgress = Extra_ProgressBarStart( stdout, Ivy_ManNodeNum(p->pManAig) );
+    Ivy_ManForEachNode( p->pManAig, pObj, i )
+    {
+        Extra_ProgressBarUpdate( p->pProgress, k++, NULL );
+        // default to simple strashing if simulation detected a counter-example for a PO
+        if ( p->pManFraig->pData )
+            pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) );
+        else
+            pObj->pEquiv = Ivy_FraigAnd( p, pObj );
+        assert( pObj->pEquiv != NULL );
+//        pTemp = Ivy_Regular(pObj->pEquiv);
+//        assert( Ivy_Regular(pObj->pEquiv)->Type );
+    }
+    Extra_ProgressBarStop( p->pProgress );
+p->nClassesEnd = p->lClasses.nItems;
+    // try to prove the outputs of the miter
+    p->nNodesMiter = Ivy_ManNodeNum(p->pManFraig);
+//    Ivy_FraigMiterStatus( p->pManFraig );
+    if ( p->pParams->fProve && p->pManFraig->pData == NULL )
+        Ivy_FraigMiterProve( p );
+    // add the POs
+    Ivy_ManForEachPo( p->pManAig, pObj, i )
+        Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) );
+    // clean the old manager
+    Ivy_ManForEachObj( p->pManAig, pObj, i )
+        pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL;
+    // clean the new manager
+    Ivy_ManForEachObj( p->pManFraig, pObj, i )
+    {
+        if ( Ivy_ObjFaninVec(pObj) )
+            Vec_PtrFree( Ivy_ObjFaninVec(pObj) );
+        pObj->pNextFan0 = pObj->pNextFan1 = NULL;
+        pObj->pEquiv = NULL;
+    }
+    // remove dangling nodes 
+    Ivy_ManCleanup( p->pManFraig );
+    // clean up the class marks
+    Ivy_FraigForEachEquivClass( p->lClasses.pHead, pObj )
+        pObj->fMarkA = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for one node.]
+
+  Description [Returns the fraiged node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld )
+{ 
+    Ivy_Obj_t * pObjNew, * pFanin0New, * pFanin1New, * pObjReprNew;
+    int RetValue;
+    // get the fraiged fanins
+    pFanin0New = Ivy_ObjChild0Equiv(pObjOld);
+    pFanin1New = Ivy_ObjChild1Equiv(pObjOld);
+    // get the candidate fraig node
+    pObjNew = Ivy_And( p->pManFraig, pFanin0New, pFanin1New );
+    // get representative of this class
+    if ( Ivy_ObjClassNodeRepr(pObjOld) == NULL || // this is a unique node
+         (!p->pParams->fDoSparse && Ivy_ObjClassNodeRepr(pObjOld) == p->pManAig->pConst1) ) // this is a sparse node
+    {
+//        assert( Ivy_Regular(pFanin0New) != Ivy_Regular(pFanin1New) );
+//        assert( pObjNew != Ivy_Regular(pFanin0New) );
+//        assert( pObjNew != Ivy_Regular(pFanin1New) );
+        return pObjNew;
+    }
+    // get the fraiged representative
+    pObjReprNew = Ivy_ObjFraig(Ivy_ObjClassNodeRepr(pObjOld));
+    // if the fraiged nodes are the same return
+    if ( Ivy_Regular(pObjNew) == Ivy_Regular(pObjReprNew) )
+        return pObjNew;
+    assert( Ivy_Regular(pObjNew) != Ivy_ManConst1(p->pManFraig) );
+//    printf( "Node = %d. Repr = %d.\n", pObjOld->Id, Ivy_ObjClassNodeRepr(pObjOld)->Id );
+
+    // they are different (the counter-example is in p->pPatWords)
+    RetValue = Ivy_FraigNodesAreEquiv( p, Ivy_Regular(pObjReprNew), Ivy_Regular(pObjNew) );
+    if ( RetValue == 1 )  // proved equivalent
+    {
+        // mark the class as proved
+        if ( Ivy_ObjClassNodeNext(pObjOld) == NULL )
+            Ivy_ObjClassNodeRepr(pObjOld)->fMarkA = 1;
+        return Ivy_NotCond( pObjReprNew, pObjOld->fPhase ^ Ivy_ObjClassNodeRepr(pObjOld)->fPhase );
+    }
+    if ( RetValue == -1 ) // failed
+        return pObjNew;
+    // simulate the counter-example and return the new node
+    Ivy_FraigResimulate( p );
+    return pObjNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints variable activity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigPrintActivity( Ivy_FraigMan_t * p )
+{
+    int i;
+    for ( i = 0; i < p->nSatVars; i++ )
+        printf( "%d %d  ", i, p->pSat->activity[i] );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Runs equivalence test for the two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew )
+{
+    int pLits[4], RetValue, RetValue1, nBTLimit;
+    abctime clk; //, clk2 = Abc_Clock();
+
+    // make sure the nodes are not complemented
+    assert( !Ivy_IsComplement(pNew) );
+    assert( !Ivy_IsComplement(pOld) );
+    assert( pNew != pOld );
+
+    // if at least one of the nodes is a failed node, perform adjustments:
+    // if the backtrack limit is small, simply skip this node
+    // if the backtrack limit is > 10, take the quare root of the limit
+    nBTLimit = p->pParams->nBTLimitNode;
+    if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) )
+    {
+        p->nSatFails++;
+        // fail immediately
+//        return -1;
+        if ( nBTLimit <= 10 )
+            return -1;
+        nBTLimit = (int)pow(nBTLimit, 0.7);
+    }
+    p->nSatCalls++;
+
+    // make sure the solver is allocated and has enough variables
+    if ( p->pSat == NULL )
+    {
+        p->pSat = sat_solver_new();
+        sat_solver_setnvars( p->pSat, 1000 );
+        p->pSat->factors = ABC_CALLOC( double, p->pSat->cap );
+        p->nSatVars = 1;
+        // var 0 is reserved for const1 node - add the clause
+//        pLits[0] = toLit( 0 );
+//        sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+    }
+
+    // if the nodes do not have SAT variables, allocate them
+    Ivy_FraigNodeAddToSolver( p, pOld, pNew );
+
+    // prepare variable activity
+    Ivy_FraigSetActivityFactors( p, pOld, pNew ); 
+
+    // solve under assumptions
+    // A = 1; B = 0     OR     A = 1; B = 1 
+clk = Abc_Clock();
+    pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 0 );
+    pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase );
+//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
+    RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, 
+        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, 
+        p->nBTLimitGlobal, p->nInsLimitGlobal );
+p->timeSat += Abc_Clock() - clk;
+    if ( RetValue1 == l_False )
+    {
+p->timeSatUnsat += Abc_Clock() - clk;
+        pLits[0] = lit_neg( pLits[0] );
+        pLits[1] = lit_neg( pLits[1] );
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+        // continue solving the other implication
+        p->nSatCallsUnsat++;
+    }
+    else if ( RetValue1 == l_True )
+    {
+p->timeSatSat += Abc_Clock() - clk;
+        Ivy_FraigSavePattern( p );
+        p->nSatCallsSat++;
+        return 0;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+p->timeSatFail += Abc_Clock() - clk;
+/*
+        if ( nBTLimit > 1000 )
+        {
+            RetValue = Ivy_FraigCheckCone( p, p->pManFraig, pOld, pNew, nBTLimit );
+            if ( RetValue != -1 )
+                return RetValue;
+        }
+*/
+        // mark the node as the failed node
+        if ( pOld != p->pManFraig->pConst1 ) 
+            pOld->fFailTfo = 1;
+        pNew->fFailTfo = 1;
+        p->nSatFailsReal++;
+        return -1;
+    }
+
+    // if the old node was constant 0, we already know the answer
+    if ( pOld == p->pManFraig->pConst1 )
+    {
+        p->nSatProof++;
+        return 1;
+    }
+
+    // solve under assumptions
+    // A = 0; B = 1     OR     A = 0; B = 0 
+clk = Abc_Clock();
+    pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 1 );
+    pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase ^ pNew->fPhase );
+    RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, 
+        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, 
+        p->nBTLimitGlobal, p->nInsLimitGlobal );
+p->timeSat += Abc_Clock() - clk;
+    if ( RetValue1 == l_False )
+    {
+p->timeSatUnsat += Abc_Clock() - clk;
+        pLits[0] = lit_neg( pLits[0] );
+        pLits[1] = lit_neg( pLits[1] );
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+        p->nSatCallsUnsat++;
+    }
+    else if ( RetValue1 == l_True )
+    {
+p->timeSatSat += Abc_Clock() - clk;
+        Ivy_FraigSavePattern( p );
+        p->nSatCallsSat++;
+        return 0;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+p->timeSatFail += Abc_Clock() - clk;
+/*
+        if ( nBTLimit > 1000 )
+        {
+            RetValue = Ivy_FraigCheckCone( p, p->pManFraig, pOld, pNew, nBTLimit );
+            if ( RetValue != -1 )
+                return RetValue;
+        }
+*/
+        // mark the node as the failed node
+        pOld->fFailTfo = 1;
+        pNew->fFailTfo = 1;
+        p->nSatFailsReal++;
+        return -1;
+    }
+/*
+    // check BDD proof
+    {
+        int RetVal;
+        ABC_PRT( "Sat", Abc_Clock() - clk2 );
+        clk2 = Abc_Clock();
+        RetVal = Ivy_FraigNodesAreEquivBdd( pOld, pNew );
+//        printf( "%d ", RetVal );
+        assert( RetVal );
+        ABC_PRT( "Bdd", Abc_Clock() - clk2 );
+        printf( "\n" );
+    }
+*/
+    // return SAT proof
+    p->nSatProof++;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Runs equivalence test for one node.]
+
+  Description [Returns the fraiged node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pNew )
+{
+    int pLits[2], RetValue1;
+    abctime clk;
+    int RetValue;
+
+    // make sure the nodes are not complemented
+    assert( !Ivy_IsComplement(pNew) );
+    assert( pNew != p->pManFraig->pConst1 );
+    p->nSatCalls++;
+
+    // make sure the solver is allocated and has enough variables
+    if ( p->pSat == NULL )
+    {
+        p->pSat = sat_solver_new();
+        sat_solver_setnvars( p->pSat, 1000 );
+        p->pSat->factors = ABC_CALLOC( double, p->pSat->cap );
+        p->nSatVars = 1;
+        // var 0 is reserved for const1 node - add the clause
+//        pLits[0] = toLit( 0 );
+//        sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+    }
+
+    // if the nodes do not have SAT variables, allocate them
+    Ivy_FraigNodeAddToSolver( p, NULL, pNew );
+
+    // prepare variable activity
+    Ivy_FraigSetActivityFactors( p, NULL, pNew ); 
+
+    // solve under assumptions
+clk = Abc_Clock();
+    pLits[0] = toLitCond( Ivy_ObjSatNum(pNew), pNew->fPhase );
+    RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 1, 
+        (ABC_INT64_T)p->pParams->nBTLimitMiter, (ABC_INT64_T)0, 
+        p->nBTLimitGlobal, p->nInsLimitGlobal );
+p->timeSat += Abc_Clock() - clk;
+    if ( RetValue1 == l_False )
+    {
+p->timeSatUnsat += Abc_Clock() - clk;
+        pLits[0] = lit_neg( pLits[0] );
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+        assert( RetValue );
+        // continue solving the other implication
+        p->nSatCallsUnsat++;
+    }
+    else if ( RetValue1 == l_True )
+    {
+p->timeSatSat += Abc_Clock() - clk;
+        if ( p->pPatWords )
+            Ivy_FraigSavePattern( p );
+        p->nSatCallsSat++;
+        return 0;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+p->timeSatFail += Abc_Clock() - clk;
+/*
+        if ( p->pParams->nBTLimitMiter > 1000 )
+        {
+            RetValue = Ivy_FraigCheckCone( p, p->pManFraig, p->pManFraig->pConst1, pNew, p->pParams->nBTLimitMiter );
+            if ( RetValue != -1 )
+                return RetValue;
+        }
+*/
+        // mark the node as the failed node
+        pNew->fFailTfo = 1;
+        p->nSatFailsReal++;
+        return -1;
+    }
+
+    // return SAT proof
+    p->nSatProof++;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Addes clauses to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigAddClausesMux( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode )
+{
+    Ivy_Obj_t * pNodeI, * pNodeT, * pNodeE;
+    int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE;
+
+    assert( !Ivy_IsComplement( pNode ) );
+    assert( Ivy_ObjIsMuxType( pNode ) );
+    // get nodes (I = if, T = then, E = else)
+    pNodeI = Ivy_ObjRecognizeMux( pNode, &pNodeT, &pNodeE );
+    // get the variable numbers
+    VarF = Ivy_ObjSatNum(pNode);
+    VarI = Ivy_ObjSatNum(pNodeI);
+    VarT = Ivy_ObjSatNum(Ivy_Regular(pNodeT));
+    VarE = Ivy_ObjSatNum(Ivy_Regular(pNodeE));
+    // get the complementation flags
+    fCompT = Ivy_IsComplement(pNodeT);
+    fCompE = Ivy_IsComplement(pNodeE);
+
+    // f = ITE(i, t, e)
+
+    // i' + t' + f
+    // i' + t  + f'
+    // i  + e' + f
+    // i  + e  + f'
+
+    // create four clauses
+    pLits[0] = toLitCond(VarI, 1);
+    pLits[1] = toLitCond(VarT, 1^fCompT);
+    pLits[2] = toLitCond(VarF, 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarI, 1);
+    pLits[1] = toLitCond(VarT, 0^fCompT);
+    pLits[2] = toLitCond(VarF, 1);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarI, 0);
+    pLits[1] = toLitCond(VarE, 1^fCompE);
+    pLits[2] = toLitCond(VarF, 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarI, 0);
+    pLits[1] = toLitCond(VarE, 0^fCompE);
+    pLits[2] = toLitCond(VarF, 1);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+
+    // two additional clauses
+    // t' & e' -> f'
+    // t  & e  -> f 
+
+    // t  + e   + f'
+    // t' + e'  + f 
+
+    if ( VarT == VarE )
+    {
+//        assert( fCompT == !fCompE );
+        return;
+    }
+
+    pLits[0] = toLitCond(VarT, 0^fCompT);
+    pLits[1] = toLitCond(VarE, 0^fCompE);
+    pLits[2] = toLitCond(VarF, 1);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarT, 1^fCompT);
+    pLits[1] = toLitCond(VarE, 1^fCompE);
+    pLits[2] = toLitCond(VarF, 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Addes clauses to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigAddClausesSuper( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode, Vec_Ptr_t * vSuper )
+{
+    Ivy_Obj_t * pFanin;
+    int * pLits, nLits, RetValue, i;
+    assert( !Ivy_IsComplement(pNode) );
+    assert( Ivy_ObjIsNode( pNode ) );
+    // create storage for literals
+    nLits = Vec_PtrSize(vSuper) + 1;
+    pLits = ABC_ALLOC( int, nLits );
+    // suppose AND-gate is A & B = C
+    // add !A => !C   or   A + !C
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vSuper, pFanin, i )
+    {
+        pLits[0] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), Ivy_IsComplement(pFanin));
+        pLits[1] = toLitCond(Ivy_ObjSatNum(pNode), 1);
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+    }
+    // add A & B => C   or   !A + !B + C
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vSuper, pFanin, i )
+        pLits[i] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), !Ivy_IsComplement(pFanin));
+    pLits[nLits-1] = toLitCond(Ivy_ObjSatNum(pNode), 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits );
+    assert( RetValue );
+    ABC_FREE( pLits );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigCollectSuper_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes )
+{
+    // if the new node is complemented or a PI, another gate begins
+    if ( Ivy_IsComplement(pObj) || Ivy_ObjIsPi(pObj) || (!fFirst && Ivy_ObjRefs(pObj) > 1) || 
+         (fUseMuxes && Ivy_ObjIsMuxType(pObj)) )
+    {
+        Vec_PtrPushUnique( vSuper, pObj );
+        return;
+    }
+    // go through the branches
+    Ivy_FraigCollectSuper_rec( Ivy_ObjChild0(pObj), vSuper, 0, fUseMuxes );
+    Ivy_FraigCollectSuper_rec( Ivy_ObjChild1(pObj), vSuper, 0, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Ivy_FraigCollectSuper( Ivy_Obj_t * pObj, int fUseMuxes )
+{
+    Vec_Ptr_t * vSuper;
+    assert( !Ivy_IsComplement(pObj) );
+    assert( !Ivy_ObjIsPi(pObj) );
+    vSuper = Vec_PtrAlloc( 4 );
+    Ivy_FraigCollectSuper_rec( pObj, vSuper, 1, fUseMuxes );
+    return vSuper;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the solver clause database.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigObjAddToFrontier( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vFrontier )
+{
+    assert( !Ivy_IsComplement(pObj) );
+    if ( Ivy_ObjSatNum(pObj) )
+        return;
+    assert( Ivy_ObjSatNum(pObj) == 0 );
+    assert( Ivy_ObjFaninVec(pObj) == NULL );
+    if ( Ivy_ObjIsConst1(pObj) )
+        return;
+//printf( "Assigning node %d number %d\n", pObj->Id, p->nSatVars );
+    Ivy_ObjSetSatNum( pObj, p->nSatVars++ );
+    if ( Ivy_ObjIsNode(pObj) )
+        Vec_PtrPush( vFrontier, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the solver clause database.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew )
+{ 
+    Vec_Ptr_t * vFrontier, * vFanins;
+    Ivy_Obj_t * pNode, * pFanin;
+    int i, k, fUseMuxes = 1;
+    assert( pOld || pNew );
+    // quit if CNF is ready
+    if ( (!pOld || Ivy_ObjFaninVec(pOld)) && (!pNew || Ivy_ObjFaninVec(pNew)) )
+        return;
+    // start the frontier
+    vFrontier = Vec_PtrAlloc( 100 );
+    if ( pOld ) Ivy_FraigObjAddToFrontier( p, pOld, vFrontier );
+    if ( pNew ) Ivy_FraigObjAddToFrontier( p, pNew, vFrontier );
+    // explore nodes in the frontier
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFrontier, pNode, i )
+    {
+        // create the supergate
+        assert( Ivy_ObjSatNum(pNode) );
+        assert( Ivy_ObjFaninVec(pNode) == NULL );
+        if ( fUseMuxes && Ivy_ObjIsMuxType(pNode) )
+        {
+            vFanins = Vec_PtrAlloc( 4 );
+            Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin0(pNode) ) );
+            Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin1(pNode) ) );
+            Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin0(pNode) ) );
+            Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin1(pNode) ) );
+            Vec_PtrForEachEntry( Ivy_Obj_t *, vFanins, pFanin, k )
+                Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier );
+            Ivy_FraigAddClausesMux( p, pNode );
+        }
+        else
+        {
+            vFanins = Ivy_FraigCollectSuper( pNode, fUseMuxes );
+            Vec_PtrForEachEntry( Ivy_Obj_t *, vFanins, pFanin, k )
+                Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier );
+            Ivy_FraigAddClausesSuper( p, pNode, vFanins );
+        }
+        assert( Vec_PtrSize(vFanins) > 1 );
+        Ivy_ObjSetFaninVec( pNode, vFanins );
+    }
+    Vec_PtrFree( vFrontier );
+    sat_solver_simplify( p->pSat );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets variable activities in the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FraigSetActivityFactors_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int LevelMin, int LevelMax )
+{
+    Vec_Ptr_t * vFanins;
+    Ivy_Obj_t * pFanin;
+    int i, Counter = 0;
+    assert( !Ivy_IsComplement(pObj) );
+    assert( Ivy_ObjSatNum(pObj) );
+    // skip visited variables
+    if ( Ivy_ObjIsTravIdCurrent(p->pManFraig, pObj) )
+        return 0;
+    Ivy_ObjSetTravIdCurrent(p->pManFraig, pObj);
+    // add the PI to the list
+    if ( pObj->Level <= (unsigned)LevelMin || Ivy_ObjIsPi(pObj) )
+        return 0;
+    // set the factor of this variable
+    // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pParams->dActConeBumpMax / ThisBump
+    p->pSat->factors[Ivy_ObjSatNum(pObj)] = p->pParams->dActConeBumpMax * (pObj->Level - LevelMin)/(LevelMax - LevelMin);
+    veci_push(&p->pSat->act_vars, Ivy_ObjSatNum(pObj));
+    // explore the fanins
+    vFanins = Ivy_ObjFaninVec( pObj );
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFanins, pFanin, i )
+        Counter += Ivy_FraigSetActivityFactors_rec( p, Ivy_Regular(pFanin), LevelMin, LevelMax );
+    return 1 + Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets variable activities in the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew )
+{
+    int LevelMin, LevelMax;
+    abctime clk;
+    assert( pOld || pNew );
+clk = Abc_Clock(); 
+    // reset the active variables
+    veci_resize(&p->pSat->act_vars, 0);
+    // prepare for traversal
+    Ivy_ManIncrementTravId( p->pManFraig );
+    // determine the min and max level to visit
+    assert( p->pParams->dActConeRatio > 0 && p->pParams->dActConeRatio < 1 );
+    LevelMax = IVY_MAX( (pNew ? pNew->Level : 0), (pOld ? pOld->Level : 0) );
+    LevelMin = (int)(LevelMax * (1.0 - p->pParams->dActConeRatio));
+    // traverse
+    if ( pOld && !Ivy_ObjIsConst1(pOld) )
+        Ivy_FraigSetActivityFactors_rec( p, pOld, LevelMin, LevelMax );
+    if ( pNew && !Ivy_ObjIsConst1(pNew) )
+        Ivy_FraigSetActivityFactors_rec( p, pNew, LevelMin, LevelMax );
+//Ivy_FraigPrintActivity( p );
+p->timeTrav += Abc_Clock() - clk;
+    return 1;
+}
+
+ABC_NAMESPACE_IMPL_END
+
+#include "bdd/cudd/cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks equivalence using BDDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Ivy_FraigNodesAreEquivBdd_int( DdManager * dd, DdNode * bFunc, Vec_Ptr_t * vFront, int Level )
+{
+    DdNode ** pFuncs;
+    DdNode * bFuncNew;
+    Vec_Ptr_t * vTemp;
+    Ivy_Obj_t * pObj, * pFanin;
+    int i, NewSize;
+    // create new frontier
+    vTemp = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, i )
+    {
+        if ( (int)pObj->Level != Level )
+        {
+            pObj->fMarkB = 1;
+            pObj->TravId = Vec_PtrSize(vTemp);
+            Vec_PtrPush( vTemp, pObj );
+            continue;
+        }
+
+        pFanin = Ivy_ObjFanin0(pObj);
+        if ( pFanin->fMarkB == 0 )
+        {
+            pFanin->fMarkB = 1;
+            pFanin->TravId = Vec_PtrSize(vTemp);
+            Vec_PtrPush( vTemp, pFanin );
+        }
+
+        pFanin = Ivy_ObjFanin1(pObj);
+        if ( pFanin->fMarkB == 0 )
+        {
+            pFanin->fMarkB = 1;
+            pFanin->TravId = Vec_PtrSize(vTemp);
+            Vec_PtrPush( vTemp, pFanin );
+        }
+    }
+    // collect the permutation
+    NewSize = IVY_MAX(dd->size, Vec_PtrSize(vTemp));
+    pFuncs = ABC_ALLOC( DdNode *, NewSize );
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, i )
+    {
+        if ( (int)pObj->Level != Level )
+            pFuncs[i] = Cudd_bddIthVar( dd, pObj->TravId );
+        else
+            pFuncs[i] = Cudd_bddAnd( dd, 
+                Cudd_NotCond( Cudd_bddIthVar(dd, Ivy_ObjFanin0(pObj)->TravId), Ivy_ObjFaninC0(pObj) ),
+                Cudd_NotCond( Cudd_bddIthVar(dd, Ivy_ObjFanin1(pObj)->TravId), Ivy_ObjFaninC1(pObj) ) );
+        Cudd_Ref( pFuncs[i] );
+    }
+    // add the remaining vars
+    assert( NewSize == dd->size );
+    for ( i = Vec_PtrSize(vFront); i < dd->size; i++ )
+    {
+        pFuncs[i] = Cudd_bddIthVar( dd, i );
+        Cudd_Ref( pFuncs[i] );
+    }
+
+    // create new
+    bFuncNew = Cudd_bddVectorCompose( dd, bFunc, pFuncs ); Cudd_Ref( bFuncNew );
+    // clean trav Id
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vTemp, pObj, i )
+    {
+        pObj->fMarkB = 0;
+        pObj->TravId = 0;
+    }
+    // deref
+    for ( i = 0; i < dd->size; i++ )
+        Cudd_RecursiveDeref( dd, pFuncs[i] );
+    ABC_FREE( pFuncs );
+
+    ABC_FREE( vFront->pArray );
+    *vFront = *vTemp;
+
+    vTemp->nCap = vTemp->nSize = 0;
+    vTemp->pArray = NULL;
+    Vec_PtrFree( vTemp );
+
+    Cudd_Deref( bFuncNew );
+    return bFuncNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks equivalence using BDDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FraigNodesAreEquivBdd( Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2 )
+{
+    static DdManager * dd = NULL;
+    DdNode * bFunc, * bTemp;
+    Vec_Ptr_t * vFront;
+    Ivy_Obj_t * pObj;
+    int i, RetValue, Iter, Level;
+    // start the manager
+    if ( dd == NULL )
+        dd = Cudd_Init( 50, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    // create front
+    vFront = Vec_PtrAlloc( 100 );
+    Vec_PtrPush( vFront, pObj1 );
+    Vec_PtrPush( vFront, pObj2 );
+    // get the function
+    bFunc = Cudd_bddXor( dd, Cudd_bddIthVar(dd,0), Cudd_bddIthVar(dd,1) );  Cudd_Ref( bFunc );
+    bFunc = Cudd_NotCond( bFunc, pObj1->fPhase != pObj2->fPhase );
+    // try running BDDs
+    for ( Iter = 0; ; Iter++ )
+    {
+        // find max level
+        Level = 0;
+        Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, i )
+            if ( Level < (int)pObj->Level )
+                Level = (int)pObj->Level;
+        if ( Level == 0 )
+            break;            
+        bFunc = Ivy_FraigNodesAreEquivBdd_int( dd, bTemp = bFunc, vFront, Level ); Cudd_Ref( bFunc );
+        Cudd_RecursiveDeref( dd, bTemp );
+        if ( bFunc == Cudd_ReadLogicZero(dd) ) // proved
+            {printf( "%d", Iter ); break;}
+        if ( Cudd_DagSize(bFunc) > 1000 )
+            {printf( "b" ); break;}
+        if ( dd->size > 120 )
+            {printf( "s" ); break;}
+        if ( Iter > 50 )
+            {printf( "i" ); break;}
+    }
+    if ( bFunc == Cudd_ReadLogicZero(dd) ) // unsat
+        RetValue = 1;
+    else if ( Level == 0 ) // sat
+        RetValue = 0;
+    else 
+        RetValue = -1; // spaceout/timeout
+    Cudd_RecursiveDeref( dd, bFunc );
+    Vec_PtrFree( vFront );
+    return RetValue;
+}
+
+ABC_NAMESPACE_IMPL_END
+
+#include "aig/aig/aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_FraigExtractCone_rec( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vLeaves, Vec_Int_t * vNodes )
+{
+    if ( pNode->fMarkB )
+        return;
+    pNode->fMarkB = 1;
+    if ( Ivy_ObjIsPi(pNode) )
+    {
+        Vec_IntPush( vLeaves, pNode->Id );
+        return;
+    }
+    assert( Ivy_ObjIsAnd(pNode) );
+    Ivy_FraigExtractCone_rec( p, Ivy_ObjFanin0(pNode), vLeaves, vNodes );
+    Ivy_FraigExtractCone_rec( p, Ivy_ObjFanin1(pNode), vLeaves, vNodes );
+    Vec_IntPush( vNodes, pNode->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks equivalence using BDDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Ivy_FraigExtractCone( Ivy_Man_t * p, Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2, Vec_Int_t * vLeaves )
+{
+    Aig_Man_t * pMan;
+    Aig_Obj_t * pMiter;
+    Vec_Int_t * vNodes;
+    Ivy_Obj_t * pObjIvy;
+    int i;
+    // collect nodes
+    vNodes  = Vec_IntAlloc( 100 );
+    Ivy_ManConst1(p)->fMarkB = 1;
+    Ivy_FraigExtractCone_rec( p, pObj1, vLeaves, vNodes );
+    Ivy_FraigExtractCone_rec( p, pObj2, vLeaves, vNodes );
+    Ivy_ManConst1(p)->fMarkB = 0;
+    // create new manager
+    pMan = Aig_ManStart( 1000 );
+    Ivy_ManConst1(p)->pEquiv = (Ivy_Obj_t *)Aig_ManConst1(pMan);
+    Ivy_ManForEachNodeVec( p, vLeaves, pObjIvy, i )
+    {
+        pObjIvy->pEquiv = (Ivy_Obj_t *)Aig_ObjCreateCi( pMan );
+        pObjIvy->fMarkB = 0;
+    }
+    // duplicate internal nodes
+    Ivy_ManForEachNodeVec( p, vNodes, pObjIvy, i )
+    {
+
+        pObjIvy->pEquiv = (Ivy_Obj_t *)Aig_And( pMan, (Aig_Obj_t *)Ivy_ObjChild0Equiv(pObjIvy), (Aig_Obj_t *)Ivy_ObjChild1Equiv(pObjIvy) );
+        pObjIvy->fMarkB = 0;
+
+        pMiter = (Aig_Obj_t *)pObjIvy->pEquiv;
+        assert( pMiter->fPhase == pObjIvy->fPhase );
+    }
+    // create the PO
+    pMiter = Aig_Exor( pMan, (Aig_Obj_t *)pObj1->pEquiv, (Aig_Obj_t *)pObj2->pEquiv );
+    pMiter = Aig_NotCond( pMiter, Aig_Regular(pMiter)->fPhase ^ Aig_IsComplement(pMiter) );
+
+/*
+printf( "Polarity = %d\n", pMiter->fPhase );
+    if ( Ivy_ObjIsConst1(pObj1) || Ivy_ObjIsConst1(pObj2) )
+    {
+        pMiter = Aig_NotCond( pMiter, 1 );
+printf( "***************\n" );
+    }
+*/
+    pMiter = Aig_ObjCreateCo( pMan, pMiter );
+//printf( "Polarity = %d\n", pMiter->fPhase );
+    Aig_ManCleanup( pMan );
+    Vec_IntFree( vNodes );
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks equivalence using BDDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_FraigCheckCone( Ivy_FraigMan_t * pGlo, Ivy_Man_t * p, Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2, int nConfLimit )
+{
+    extern int Fra_FraigSat( Aig_Man_t * pMan, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose );
+    Vec_Int_t * vLeaves;
+    Aig_Man_t * pMan;
+    Aig_Obj_t * pObj;
+    int i, RetValue;
+    vLeaves  = Vec_IntAlloc( 100 );
+    pMan     = Ivy_FraigExtractCone( p, pObj1, pObj2, vLeaves );
+    RetValue = Fra_FraigSat( pMan, nConfLimit, 0, 0, 0, 0, 0, 0, 0, 1 ); 
+    if ( RetValue == 0 )
+    {
+        int Counter = 0;
+        memset( pGlo->pPatWords, 0, sizeof(unsigned) * pGlo->nPatWords );
+        Aig_ManForEachCi( pMan, pObj, i )
+            if ( ((int *)pMan->pData)[i] )
+            {
+                int iObjIvy = Vec_IntEntry( vLeaves, i );
+                assert( iObjIvy > 0 && iObjIvy <= Ivy_ManPiNum(p) );
+                Ivy_InfoSetBit( pGlo->pPatWords, iObjIvy-1 );
+//printf( "%d ", iObjIvy );
+Counter++;
+            }
+        assert( Counter > 0 );
+    }
+    Vec_IntFree( vLeaves );
+    if ( RetValue == 1 )
+        printf( "UNSAT\n" );
+    else if ( RetValue == 0 )
+        printf( "SAT\n" );
+    else if ( RetValue == -1 )
+        printf( "UNDEC\n" );
+
+//    p->pModel = (int *)pMan->pData, pMan2->pData = NULL;
+    Aig_ManStop( pMan );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyHaig.c b/abc-build/src/aig/ivy/ivyHaig.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyHaig.c
@@ -0,0 +1,535 @@
+/**CFile****************************************************************
+
+  FileName    [ivyHaig.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [HAIG management procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyHaig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+/* 
+    HAIGing rules in working AIG:
+    - Each node in the working AIG has a pointer to the corresponding node in HAIG 
+      (this node is not necessarily the representative of the equivalence class of HAIG nodes)
+    - This pointer is complemented if the AIG node and its corresponding HAIG node have different phase
+
+    Choice node rules in HAIG:
+    - Equivalent nodes are linked into a ring
+    - Exactly one node in the ring has fanouts (this node is called the representative)
+    - The pointer going from a node to the next node in the ring is complemented 
+      if the first node is complemented, compared to the representative node of the equivalence class
+    - (consequence of the above) The representative node always has non-complemented pointer to the next node
+    - New nodes are inserted into the ring immediately after the representative node
+*/
+
+// returns the representative node of the given HAIG node
+static inline Ivy_Obj_t * Ivy_HaigObjRepr( Ivy_Obj_t * pObj )
+{
+    Ivy_Obj_t * pTemp;
+    assert( !Ivy_IsComplement(pObj) );
+    // if the node has no equivalent node or has fanout, it is representative
+    if ( pObj->pEquiv == NULL || Ivy_ObjRefs(pObj) > 0 )
+        return pObj;
+    // the node belongs to a class and is not a representative
+    // complemented edge (pObj->pEquiv) tells if it is complemented w.r.t. the repr
+    for ( pTemp = Ivy_Regular(pObj->pEquiv); pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+        if ( Ivy_ObjRefs(pTemp) > 0 )
+            break;
+    // return the representative node
+    assert( Ivy_ObjRefs(pTemp) > 0 );
+    return Ivy_NotCond( pTemp, Ivy_IsComplement(pObj->pEquiv) );
+}
+
+// counts the number of nodes in the equivalence class
+static inline int Ivy_HaigObjCountClass( Ivy_Obj_t * pObj )
+{
+    Ivy_Obj_t * pTemp;
+    int Counter;
+    assert( !Ivy_IsComplement(pObj) );
+    assert( Ivy_ObjRefs(pObj) > 0 );
+    if ( pObj->pEquiv == NULL )
+        return 1;
+    assert( !Ivy_IsComplement(pObj->pEquiv) );
+    Counter = 1;
+    for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+        Counter++;
+    return Counter;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts HAIG for the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManHaigStart( Ivy_Man_t * p, int fVerbose )
+{
+    Vec_Int_t * vLatches;
+    Ivy_Obj_t * pObj;
+    int i;
+    assert( p->pHaig == NULL );
+    p->pHaig = Ivy_ManDup( p );
+
+    if ( fVerbose )
+    {
+        printf( "Starting : " );
+        Ivy_ManPrintStats( p->pHaig );
+    }
+
+    // collect latches of design D and set their values to be DC
+    vLatches = Vec_IntAlloc( 100 );
+    Ivy_ManForEachLatch( p->pHaig, pObj, i )
+    {
+        pObj->Init = IVY_INIT_DC;
+        Vec_IntPush( vLatches, pObj->Id );
+    }
+    p->pHaig->pData = vLatches;
+/*
+    {
+        int x;
+        Ivy_ManShow( p, 0, NULL );
+        Ivy_ManShow( p->pHaig, 1, NULL );
+        x = 0;
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the HAIG to the newly created manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew )
+{
+    Ivy_Obj_t * pObj;
+    int i;
+    assert( p->pHaig != NULL );
+    Ivy_ManConst1(pNew)->pEquiv = Ivy_ManConst1(p)->pEquiv;
+    Ivy_ManForEachPi( pNew, pObj, i )
+        pObj->pEquiv = Ivy_ManPi( p, i )->pEquiv;
+    pNew->pHaig = p->pHaig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops HAIG for the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManHaigStop( Ivy_Man_t * p )
+{
+    Ivy_Obj_t * pObj;
+    int i;
+    assert( p->pHaig != NULL );
+    Vec_IntFree( (Vec_Int_t *)p->pHaig->pData );
+    Ivy_ManStop( p->pHaig );
+    p->pHaig = NULL;
+    // remove dangling pointers to the HAIG objects
+    Ivy_ManForEachObj( p, pObj, i )
+        pObj->pEquiv = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new node in HAIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+    Ivy_Obj_t * pEquiv0, * pEquiv1;
+    assert( p->pHaig != NULL );
+    assert( !Ivy_IsComplement(pObj) );
+    if ( Ivy_ObjType(pObj) == IVY_BUF )
+        pObj->pEquiv = Ivy_ObjChild0Equiv(pObj);
+    else if ( Ivy_ObjType(pObj) == IVY_LATCH )
+    {
+//        pObj->pEquiv = Ivy_Latch( p->pHaig, Ivy_ObjChild0Equiv(pObj), pObj->Init );
+        pEquiv0 = Ivy_ObjChild0Equiv(pObj);
+        pEquiv0 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv0)), Ivy_IsComplement(pEquiv0) );
+        pObj->pEquiv = Ivy_Latch( p->pHaig, pEquiv0, (Ivy_Init_t)pObj->Init );
+    }
+    else if ( Ivy_ObjType(pObj) == IVY_AND )
+    {
+//        pObj->pEquiv = Ivy_And( p->pHaig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) );
+        pEquiv0 = Ivy_ObjChild0Equiv(pObj);
+        pEquiv0 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv0)), Ivy_IsComplement(pEquiv0) );
+        pEquiv1 = Ivy_ObjChild1Equiv(pObj);
+        pEquiv1 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv1)), Ivy_IsComplement(pEquiv1) );
+        pObj->pEquiv = Ivy_And( p->pHaig, pEquiv0, pEquiv1 );
+    }
+    else assert( 0 );
+    // make sure the node points to the representative
+//    pObj->pEquiv = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObj->pEquiv)), Ivy_IsComplement(pObj->pEquiv) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the old node is in the TFI of the new node.]
+
+  Description [] 
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ObjIsInTfi_rec( Ivy_Obj_t * pObjNew, Ivy_Obj_t * pObjOld, int Levels )
+{
+    if ( pObjNew == pObjOld )
+        return 1;
+    if ( Levels == 0 || Ivy_ObjIsCi(pObjNew) || Ivy_ObjIsConst1(pObjNew) )
+        return 0;
+    if ( Ivy_ObjIsInTfi_rec( Ivy_ObjFanin0(pObjNew), pObjOld, Levels - 1 ) )
+        return 1;
+    if ( Ivy_ObjIsNode(pObjNew) && Ivy_ObjIsInTfi_rec( Ivy_ObjFanin1(pObjNew), pObjOld, Levels - 1 ) )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the pair of equivalent nodes in HAIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew )
+{
+    Ivy_Obj_t * pObjOldHaig, * pObjNewHaig;
+    Ivy_Obj_t * pObjOldHaigR, * pObjNewHaigR;
+    int fCompl;
+//printf( "\nCreating choice for %d and %d in AIG\n", pObjOld->Id, Ivy_Regular(pObjNew)->Id );
+
+    assert( p->pHaig != NULL );
+    assert( !Ivy_IsComplement(pObjOld) );
+    // get pointers to the representatives of pObjOld and pObjNew
+    pObjOldHaig = pObjOld->pEquiv;
+    pObjNewHaig = Ivy_NotCond( Ivy_Regular(pObjNew)->pEquiv, Ivy_IsComplement(pObjNew) );
+    // get the classes
+    pObjOldHaig = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObjOldHaig)), Ivy_IsComplement(pObjOldHaig) );
+    pObjNewHaig = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObjNewHaig)), Ivy_IsComplement(pObjNewHaig) );
+    // get regular pointers
+    pObjOldHaigR = Ivy_Regular(pObjOldHaig);
+    pObjNewHaigR = Ivy_Regular(pObjNewHaig);
+    // check if there is phase difference between them
+    fCompl = (Ivy_IsComplement(pObjOldHaig) != Ivy_IsComplement(pObjNewHaig));
+    // if the class is the same, nothing to do
+    if ( pObjOldHaigR == pObjNewHaigR )
+        return;
+    // if the second node belongs to a class, do not merge classes (for the time being)
+    if ( Ivy_ObjRefs(pObjOldHaigR) == 0 || pObjNewHaigR->pEquiv != NULL || 
+        Ivy_ObjRefs(pObjNewHaigR) > 0 ) //|| Ivy_ObjIsInTfi_rec(pObjNewHaigR, pObjOldHaigR, 10) )
+    {
+/*
+        if ( pObjNewHaigR->pEquiv != NULL )
+            printf( "c" );
+        if ( Ivy_ObjRefs(pObjNewHaigR) > 0 )
+            printf( "f" );
+        printf( " " );
+*/
+        p->pHaig->nClassesSkip++;
+        return;
+    }
+
+    // add this node to the class of pObjOldHaig
+    assert( Ivy_ObjRefs(pObjOldHaigR) > 0 );
+    assert( !Ivy_IsComplement(pObjOldHaigR->pEquiv) );
+    if ( pObjOldHaigR->pEquiv == NULL )
+        pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl );
+    else
+        pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR->pEquiv, fCompl );
+    pObjOldHaigR->pEquiv = pObjNewHaigR;
+//printf( "Setting choice node %d -> %d.\n", pObjOldHaigR->Id, pObjNewHaigR->Id );
+    // update the class of the new node
+//    Ivy_Regular(pObjNew)->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl ^ Ivy_IsComplement(pObjNew) );
+//printf( "Creating choice for %d and %d in HAIG\n", pObjOldHaigR->Id, pObjNewHaigR->Id );
+
+//    if ( pObjOldHaigR->Id == 13 )
+//    {
+//        Ivy_ManShow( p, 0 );
+//        Ivy_ManShow( p->pHaig, 1 );
+//    }
+//    if ( !Ivy_ManIsAcyclic( p->pHaig ) )
+//        printf( "HAIG contains a cycle\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of choices and choice nodes in HAIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManHaigCountChoices( Ivy_Man_t * p, int * pnChoices )
+{
+    Ivy_Obj_t * pObj;
+    int nChoices, nChoiceNodes, Counter, i;
+    assert( p->pHaig != NULL );
+    nChoices = nChoiceNodes = 0;
+    Ivy_ManForEachObj( p->pHaig, pObj, i )
+    {
+        if ( Ivy_ObjIsTerm(pObj) || i == 0 )
+            continue;
+        if ( Ivy_ObjRefs(pObj) == 0 )
+            continue;
+        Counter = Ivy_HaigObjCountClass( pObj );
+        nChoiceNodes += (int)(Counter > 1);
+        nChoices += Counter - 1;
+//        if ( Counter > 1 )
+//            printf( "Choice node %d %s\n", pObj->Id, Ivy_ObjIsLatch(pObj)? "(latch)": "" );
+    }
+    *pnChoices = nChoices;
+    return nChoiceNodes;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Prints statistics of the HAIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManHaigPostprocess( Ivy_Man_t * p, int fVerbose )
+{
+    int nChoices, nChoiceNodes;
+
+    assert( p->pHaig != NULL );
+
+    if ( fVerbose )
+    {
+        printf( "Final    : " );
+        Ivy_ManPrintStats( p );
+        printf( "HAIG     : " );
+        Ivy_ManPrintStats( p->pHaig );
+
+        // print choice node stats
+        nChoiceNodes = Ivy_ManHaigCountChoices( p, &nChoices );
+        printf( "Total choice nodes = %d. Total choices = %d. Skipped classes = %d.\n", 
+            nChoiceNodes, nChoices, p->pHaig->nClassesSkip ); 
+    }
+
+    if ( Ivy_ManIsAcyclic( p->pHaig ) )
+    {
+        if ( fVerbose )
+            printf( "HAIG is acyclic\n" );
+    }
+    else
+        printf( "HAIG contains a cycle\n" );
+
+//    if ( fVerbose )
+//        Ivy_ManHaigSimulate( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Applies the simulation rules.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Ivy_Init_t Ivy_ManHaigSimulateAnd( Ivy_Init_t In0, Ivy_Init_t In1 )
+{
+    assert( In0 != IVY_INIT_NONE && In1 != IVY_INIT_NONE );
+    if ( In0 == IVY_INIT_DC || In1 == IVY_INIT_DC )
+        return IVY_INIT_DC;
+    if ( In0 == IVY_INIT_1 && In1 == IVY_INIT_1 )
+        return IVY_INIT_1;
+    return IVY_INIT_0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Applies the simulation rules.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Ivy_Init_t Ivy_ManHaigSimulateChoice( Ivy_Init_t In0, Ivy_Init_t In1 )
+{
+    assert( In0 != IVY_INIT_NONE && In1 != IVY_INIT_NONE );
+    if ( (In0 == IVY_INIT_0 && In1 == IVY_INIT_1) || (In0 == IVY_INIT_1 && In1 == IVY_INIT_0) )
+    {
+         printf( "Compatibility fails.\n" );
+         return IVY_INIT_0;
+    }
+    if ( In0 == IVY_INIT_DC && In1 == IVY_INIT_DC )
+        return IVY_INIT_DC;
+    if ( In0 != IVY_INIT_DC )
+        return In0;
+    return In1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulate HAIG using modified 3-valued simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManHaigSimulate( Ivy_Man_t * p )
+{
+    Vec_Int_t * vNodes, * vLatches, * vLatchesD;
+    Ivy_Obj_t * pObj, * pTemp;
+    Ivy_Init_t In0, In1;
+    int i, k, Counter;
+    int fVerbose = 0;
+
+    // check choices
+    Ivy_ManCheckChoices( p );
+
+    // switch to HAIG
+    assert( p->pHaig != NULL );
+    p = p->pHaig;
+
+if ( fVerbose )
+Ivy_ManForEachPi( p, pObj, i )
+printf( "Setting PI %d\n", pObj->Id );
+
+    // collect latches and nodes in the DFS order
+    vNodes = Ivy_ManDfsSeq( p, &vLatches );
+
+if ( fVerbose )
+Ivy_ManForEachNodeVec( p, vNodes, pObj, i )
+printf( "Collected node %d with fanins %d and %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id );
+
+    // set the PI values
+    Ivy_ManConst1(p)->Init = IVY_INIT_1;
+    Ivy_ManForEachPi( p, pObj, i )
+        pObj->Init = IVY_INIT_0;
+
+    // set the latch values
+    Ivy_ManForEachNodeVec( p, vLatches, pObj, i )
+        pObj->Init = IVY_INIT_DC;
+    // set the latches of D to be determinate
+    vLatchesD = (Vec_Int_t *)p->pData;
+    Ivy_ManForEachNodeVec( p, vLatchesD, pObj, i )
+        pObj->Init = IVY_INIT_0;
+
+    // perform several rounds of simulation
+    for ( k = 0; k < 10; k++ )
+    {
+        // count the number of non-determinate values
+        Counter = 0;
+        Ivy_ManForEachNodeVec( p, vLatches, pObj, i )
+            Counter += ( pObj->Init == IVY_INIT_DC );
+        printf( "Iter %d : Non-determinate = %d\n", k, Counter );    
+        
+        // simulate the internal nodes
+        Ivy_ManForEachNodeVec( p, vNodes, pObj, i )
+        {
+if ( fVerbose )
+printf( "Processing node %d with fanins %d and %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id );
+            In0 = Ivy_InitNotCond( (Ivy_Init_t)Ivy_ObjFanin0(pObj)->Init, Ivy_ObjFaninC0(pObj) );
+            In1 = Ivy_InitNotCond( (Ivy_Init_t)Ivy_ObjFanin1(pObj)->Init, Ivy_ObjFaninC1(pObj) );
+            pObj->Init = Ivy_ManHaigSimulateAnd( In0, In1 );
+            // simulate the equivalence class if the node is a representative
+            if ( pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 )
+            {
+if ( fVerbose )
+printf( "Processing choice node %d\n", pObj->Id );
+                In0 = (Ivy_Init_t)pObj->Init;
+                assert( !Ivy_IsComplement(pObj->pEquiv) );
+                for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+                {
+if ( fVerbose )
+printf( "Processing secondary node %d\n", pTemp->Id );
+                    In1 = Ivy_InitNotCond( (Ivy_Init_t)pTemp->Init, Ivy_IsComplement(pTemp->pEquiv) );
+                    In0 = Ivy_ManHaigSimulateChoice( In0, In1 );
+                }
+                pObj->Init = In0;
+            }
+        }
+
+        // simulate the latches
+        Ivy_ManForEachNodeVec( p, vLatches, pObj, i )
+        {
+            pObj->Level = Ivy_ObjFanin0(pObj)->Init;
+if ( fVerbose )
+printf( "Using latch %d with fanin %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id );
+        }
+        Ivy_ManForEachNodeVec( p, vLatches, pObj, i )
+            pObj->Init = pObj->Level, pObj->Level = 0;
+    }
+    // free arrays
+    Vec_IntFree( vNodes );
+    Vec_IntFree( vLatches );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyMan.c b/abc-build/src/aig/ivy/ivyMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyMan.c
@@ -0,0 +1,552 @@
+/**CFile****************************************************************
+
+  FileName    [ivyMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [AIG manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManStart()
+{
+    Ivy_Man_t * p;
+    // start the manager
+    p = ABC_ALLOC( Ivy_Man_t, 1 );
+    memset( p, 0, sizeof(Ivy_Man_t) );
+    // perform initializations
+    p->Ghost.Id   = -1;
+    p->nTravIds   =  1;
+    p->fCatchExor =  1;
+    // allocate arrays for nodes
+    p->vPis = Vec_PtrAlloc( 100 );
+    p->vPos = Vec_PtrAlloc( 100 );
+    p->vBufs = Vec_PtrAlloc( 100 );
+    p->vObjs = Vec_PtrAlloc( 100 );
+    // prepare the internal memory manager
+    Ivy_ManStartMemory( p );
+    // create the constant node
+    p->pConst1 = Ivy_ManFetchMemory( p );
+    p->pConst1->fPhase = 1;
+    Vec_PtrPush( p->vObjs, p->pConst1 );
+    p->nCreated = 1;
+    // start the table
+    p->nTableSize = 10007;
+    p->pTable = ABC_ALLOC( int, p->nTableSize );
+    memset( p->pTable, 0, sizeof(int) * p->nTableSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManStartFrom( Ivy_Man_t * p )
+{
+    Ivy_Man_t * pNew;
+    Ivy_Obj_t * pObj;
+    int i;
+    // create the new manager
+    pNew = Ivy_ManStart();
+    // create the PIs
+    Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew);
+    Ivy_ManForEachPi( p, pObj, i )
+        pObj->pEquiv = Ivy_ObjCreatePi(pNew);
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p )
+{
+    Vec_Int_t * vNodes, * vLatches;
+    Ivy_Man_t * pNew;
+    Ivy_Obj_t * pObj;
+    int i;
+    // collect latches and nodes in the DFS order
+    vNodes = Ivy_ManDfsSeq( p, &vLatches );
+    // create the new manager
+    pNew = Ivy_ManStart();
+    // create the PIs
+    Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew);
+    Ivy_ManForEachPi( p, pObj, i )
+        pObj->pEquiv = Ivy_ObjCreatePi(pNew);
+    // create the fake PIs for latches
+    Ivy_ManForEachNodeVec( p, vLatches, pObj, i )
+        pObj->pEquiv = Ivy_ObjCreatePi(pNew);
+    // duplicate internal nodes
+    Ivy_ManForEachNodeVec( p, vNodes, pObj, i )
+        if ( Ivy_ObjIsBuf(pObj) )
+            pObj->pEquiv = Ivy_ObjChild0Equiv(pObj);
+        else
+            pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) );
+    // add the POs
+    Ivy_ManForEachPo( p, pObj, i )
+        Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(pObj) );
+    // transform additional PI nodes into latches and connect them
+    Ivy_ManForEachNodeVec( p, vLatches, pObj, i )
+    {
+        assert( !Ivy_ObjFaninC0(pObj) );
+        pObj->pEquiv->Type = IVY_LATCH;
+        pObj->pEquiv->Init = pObj->Init;
+        Ivy_ObjConnect( pNew, pObj->pEquiv, Ivy_ObjChild0Equiv(pObj), NULL );
+    }
+    // shrink the arrays
+    Vec_PtrShrink( pNew->vPis, Ivy_ManPiNum(p) );
+    // update the counters of different objects
+    pNew->nObjs[IVY_PI] -= Ivy_ManLatchNum(p);
+    pNew->nObjs[IVY_LATCH] += Ivy_ManLatchNum(p);
+    // free arrays
+    Vec_IntFree( vNodes );
+    Vec_IntFree( vLatches );
+    // make sure structural hashing did not change anything
+    assert( Ivy_ManNodeNum(p)  == Ivy_ManNodeNum(pNew) );
+    assert( Ivy_ManLatchNum(p) == Ivy_ManLatchNum(pNew) );
+    // check the resulting network
+    if ( !Ivy_ManCheck(pNew) )
+        printf( "Ivy_ManMakeSeq(): The check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManFrames( Ivy_Man_t * pMan, int nLatches, int nFrames, int fInit, Vec_Ptr_t ** pvMapping )
+{
+    Vec_Ptr_t * vMapping;
+    Ivy_Man_t * pNew;
+    Ivy_Obj_t * pObj;
+    int i, f, nPis, nPos, nIdMax;
+    assert( Ivy_ManLatchNum(pMan) == 0 );
+    assert( nFrames > 0 );
+    // prepare the mapping
+    nPis = Ivy_ManPiNum(pMan) - nLatches;
+    nPos = Ivy_ManPoNum(pMan) - nLatches;
+    nIdMax = Ivy_ManObjIdMax(pMan);
+    // create the new manager
+    pNew = Ivy_ManStart();
+    // set the starting values of latch inputs
+    for ( i = 0; i < nLatches; i++ )
+        Ivy_ManPo(pMan, nPos+i)->pEquiv = fInit? Ivy_Not(Ivy_ManConst1(pNew)) : Ivy_ObjCreatePi(pNew);
+    // add timeframes
+    vMapping = Vec_PtrStart( nIdMax * nFrames + 1 );
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // create PIs
+        Ivy_ManConst1(pMan)->pEquiv = Ivy_ManConst1(pNew);
+        for ( i = 0; i < nPis; i++ )
+            Ivy_ManPi(pMan, i)->pEquiv = Ivy_ObjCreatePi(pNew);
+        // transfer values to latch outputs
+        for ( i = 0; i < nLatches; i++ )
+            Ivy_ManPi(pMan, nPis+i)->pEquiv = Ivy_ManPo(pMan, nPos+i)->pEquiv;
+        // perform strashing
+        Ivy_ManForEachNode( pMan, pObj, i )
+            pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) );
+        // create POs
+        for ( i = 0; i < nPos; i++ )
+            Ivy_ManPo(pMan, i)->pEquiv = Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, i)) );
+        // set the results of latch inputs
+        for ( i = 0; i < nLatches; i++ )
+            Ivy_ManPo(pMan, nPos+i)->pEquiv = Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, nPos+i));
+        // save the pointers in this frame
+        Ivy_ManForEachObj( pMan, pObj, i )
+            Vec_PtrWriteEntry( vMapping, f * nIdMax + i, pObj->pEquiv );
+    }
+    // connect latches
+    if ( !fInit )
+        for ( i = 0; i < nLatches; i++ )
+            Ivy_ObjCreatePo( pNew, Ivy_ManPo(pMan, nPos+i)->pEquiv );
+    // remove dangling nodes
+    Ivy_ManCleanup(pNew);
+    *pvMapping = vMapping;
+    // check the resulting network
+    if ( !Ivy_ManCheck(pNew) )
+        printf( "Ivy_ManFrames(): The check has failed.\n" );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManStop( Ivy_Man_t * p )
+{
+    if ( p->time1 ) { ABC_PRT( "Update lev  ", p->time1 ); }
+    if ( p->time2 ) { ABC_PRT( "Update levR ", p->time2 ); }
+//    Ivy_TableProfile( p );
+//    if ( p->vFanouts )  Ivy_ManStopFanout( p );
+    if ( p->vChunks )   Ivy_ManStopMemory( p );
+    if ( p->vRequired ) Vec_IntFree( p->vRequired );
+    if ( p->vPis )      Vec_PtrFree( p->vPis );
+    if ( p->vPos )      Vec_PtrFree( p->vPos );
+    if ( p->vBufs )     Vec_PtrFree( p->vBufs );
+    if ( p->vObjs )     Vec_PtrFree( p->vObjs );
+    ABC_FREE( p->pTable );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes nodes without fanout.]
+
+  Description [Returns the number of dangling nodes removed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManCleanup( Ivy_Man_t * p )
+{
+    Ivy_Obj_t * pNode;
+    int i, nNodesOld;
+    nNodesOld = Ivy_ManNodeNum(p);
+    Ivy_ManForEachObj( p, pNode, i )
+        if ( Ivy_ObjIsNode(pNode) || Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) )
+            if ( Ivy_ObjRefs(pNode) == 0 )
+                Ivy_ObjDelete_rec( p, pNode, 1 );
+//printf( "Cleanup removed %d nodes.\n", nNodesOld - Ivy_ManNodeNum(p) );
+    return nNodesOld - Ivy_ManNodeNum(p);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks nodes reachable from the given one.]
+
+  Description [Returns the number of dangling nodes removed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManCleanupSeq_rec( Ivy_Obj_t * pObj )
+{
+    if ( Ivy_ObjIsMarkA(pObj) )
+        return;
+    Ivy_ObjSetMarkA(pObj);
+    if ( pObj->pFanin0 != NULL )
+        Ivy_ManCleanupSeq_rec( Ivy_ObjFanin0(pObj) );
+    if ( pObj->pFanin1 != NULL )
+        Ivy_ManCleanupSeq_rec( Ivy_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes logic that does not feed into POs.]
+
+  Description [Returns the number of dangling nodes removed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManCleanupSeq( Ivy_Man_t * p )
+{
+    Vec_Ptr_t * vNodes;
+    Ivy_Obj_t * pObj;
+    int i, RetValue;
+    // mark the constant and PIs
+    Ivy_ObjSetMarkA( Ivy_ManConst1(p) );
+    Ivy_ManForEachPi( p, pObj, i )
+        Ivy_ObjSetMarkA( pObj );
+    // mark nodes visited from POs
+    Ivy_ManForEachPo( p, pObj, i )
+        Ivy_ManCleanupSeq_rec( pObj );
+    // collect unmarked nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    Ivy_ManForEachObj( p, pObj, i )
+    {
+        if ( Ivy_ObjIsMarkA(pObj) )
+            Ivy_ObjClearMarkA(pObj);
+        else
+            Vec_PtrPush( vNodes, pObj );
+    }
+    if ( Vec_PtrSize(vNodes) == 0 )
+    {
+        Vec_PtrFree( vNodes );
+//printf( "Sequential sweep cleaned out %d nodes.\n", 0 );
+        return 0;
+    }
+    // disconnect the marked objects
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, i )
+        Ivy_ObjDisconnect( p, pObj );
+    // remove the dangling objects
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, i )
+    {
+        assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsLatch(pObj) || Ivy_ObjIsBuf(pObj) );
+        assert( Ivy_ObjRefs(pObj) == 0 );
+        // update node counters of the manager
+        p->nObjs[pObj->Type]--;
+        p->nDeleted++;
+        // delete buffer from the array of buffers
+        if ( p->fFanout && Ivy_ObjIsBuf(pObj) )
+            Vec_PtrRemove( p->vBufs, pObj );
+        // free the node
+        Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL );
+        Ivy_ManRecycleMemory( p, pObj );
+    }
+    // return the number of nodes freed
+    RetValue = Vec_PtrSize(vNodes);
+    Vec_PtrFree( vNodes );
+//printf( "Sequential sweep cleaned out %d nodes.\n", RetValue );
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if latches form self-loop.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManLatchIsSelfFeed_rec( Ivy_Obj_t * pLatch, Ivy_Obj_t * pLatchRoot )
+{
+    if ( !Ivy_ObjIsLatch(pLatch) && !Ivy_ObjIsBuf(pLatch) )
+        return 0;
+    if ( pLatch == pLatchRoot )
+        return 1;
+    return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatchRoot );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if latches form self-loop.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManLatchIsSelfFeed( Ivy_Obj_t * pLatch )
+{
+    if ( !Ivy_ObjIsLatch(pLatch) )
+        return 0;
+    return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatch );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of dangling nodes removed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+int Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel )
+{
+    Ivy_Obj_t * pNode;
+    int LimitFactor = 100;
+    int NodeBeg = Ivy_ManNodeNum(p);
+    int nSteps;
+    for ( nSteps = 0; Vec_PtrSize(p->vBufs) > 0; nSteps++ )
+    {
+        pNode = (Ivy_Obj_t *)Vec_PtrEntryLast(p->vBufs);
+        while ( Ivy_ObjIsBuf(pNode) )
+            pNode = Ivy_ObjReadFirstFanout( p, pNode );
+        // check if this buffer should remain
+        if ( Ivy_ManLatchIsSelfFeed(pNode) )
+        {
+            Vec_PtrPop(p->vBufs);
+            continue;
+        }
+//printf( "Propagating buffer %d with input %d and output %d\n", Ivy_ObjFaninId0(pNode), Ivy_ObjFaninId0(Ivy_ObjFanin0(pNode)), pNode->Id );
+//printf( "Latch num %d\n", Ivy_ManLatchNum(p) );
+        Ivy_NodeFixBufferFanins( p, pNode, fUpdateLevel );
+        if ( nSteps > NodeBeg * LimitFactor )
+        {
+            printf( "Structural hashing is not finished after %d forward latch moves.\n", NodeBeg * LimitFactor );
+            printf( "This circuit cannot be forward-retimed completely. Quitting.\n" );
+            break;
+        }
+    }
+//    printf( "Number of steps = %d. Nodes beg = %d. Nodes end = %d.\n", nSteps, NodeBeg, Ivy_ManNodeNum(p) );
+    return nSteps;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManPrintStats( Ivy_Man_t * p )
+{
+    printf( "PI/PO = %d/%d ", Ivy_ManPiNum(p), Ivy_ManPoNum(p) );
+    printf( "A = %7d. ",       Ivy_ManAndNum(p) );
+    printf( "L = %5d. ",       Ivy_ManLatchNum(p) );
+//    printf( "X = %d. ",       Ivy_ManExorNum(p) );
+//    printf( "B = %3d. ",       Ivy_ManBufNum(p) );
+    printf( "MaxID = %7d. ",   Ivy_ManObjIdMax(p) );
+//    printf( "Cre = %d. ",     p->nCreated );
+//    printf( "Del = %d. ",     p->nDeleted );
+    printf( "Lev = %3d. ",     Ivy_ManLatchNum(p)? -1 : Ivy_ManLevels(p) );
+    printf( "\n" );
+    fflush( stdout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts a combinational AIG manager into a sequential one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManMakeSeq( Ivy_Man_t * p, int nLatches, int * pInits )
+{
+    Ivy_Obj_t * pObj, * pLatch;
+    Ivy_Init_t Init;
+    int i;
+    if ( nLatches == 0 )
+        return;
+    assert( nLatches < Ivy_ManPiNum(p) && nLatches < Ivy_ManPoNum(p) );
+    assert( Ivy_ManPiNum(p) == Vec_PtrSize(p->vPis) );
+    assert( Ivy_ManPoNum(p) == Vec_PtrSize(p->vPos) );
+    assert( Vec_PtrSize( p->vBufs ) == 0 );
+    // create fanouts
+    if ( p->fFanout == 0 )
+        Ivy_ManStartFanout( p );
+    // collect the POs to be converted into latches
+    for ( i = 0; i < nLatches; i++ )
+    {
+        // get the latch value
+        Init = pInits? (Ivy_Init_t)pInits[i] : IVY_INIT_0;
+        // create latch
+        pObj = Ivy_ManPo( p, Ivy_ManPoNum(p) - nLatches + i );
+        pLatch = Ivy_Latch( p, Ivy_ObjChild0(pObj), Init );
+        Ivy_ObjDisconnect( p, pObj );
+        // recycle the old PO object
+        Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL );
+        Ivy_ManRecycleMemory( p, pObj );
+        // convert the corresponding PI to a buffer and connect it to the latch
+        pObj = Ivy_ManPi( p, Ivy_ManPiNum(p) - nLatches + i );
+        pObj->Type = IVY_BUF;
+        Ivy_ObjConnect( p, pObj, pLatch, NULL );
+        // save the buffer
+        Vec_PtrPush( p->vBufs, pObj );
+    }
+    // shrink the arrays
+    Vec_PtrShrink( p->vPis, Ivy_ManPiNum(p) - nLatches );
+    Vec_PtrShrink( p->vPos, Ivy_ManPoNum(p) - nLatches );
+    // update the counters of different objects
+    p->nObjs[IVY_PI] -= nLatches;
+    p->nObjs[IVY_PO] -= nLatches;
+    p->nObjs[IVY_BUF] += nLatches;
+    p->nDeleted -= 2 * nLatches;
+    // remove dangling nodes
+    Ivy_ManCleanup(p);
+    Ivy_ManCleanupSeq(p);
+/* 
+    // check for dangling nodes
+    Ivy_ManForEachObj( p, pObj, i )
+        if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsPo(pObj) && !Ivy_ObjIsConst1(pObj) )
+        {
+            assert( Ivy_ObjRefs(pObj) > 0 );
+            assert( Ivy_ObjRefs(pObj) == Ivy_ObjFanoutNum(p, pObj) );
+        }
+*/
+    // perform hashing by propagating the buffers
+    Ivy_ManPropagateBuffers( p, 0 );
+    if ( Ivy_ManBufNum(p) )
+        printf( "The number of remaining buffers is %d.\n", Ivy_ManBufNum(p) );
+    // fix the levels
+    Ivy_ManResetLevels( p );
+    // check the resulting network
+    if ( !Ivy_ManCheck(p) )
+        printf( "Ivy_ManMakeSeq(): The check has failed.\n" );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyMem.c b/abc-build/src/aig/ivy/ivyMem.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyMem.c
@@ -0,0 +1,121 @@
+/**CFile****************************************************************
+
+  FileName    [ivyMem.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Memory management for the AIG nodes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyMem.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// memory management
+#define IVY_PAGE_SIZE      12        // page size containing 2^IVY_PAGE_SIZE nodes
+#define IVY_PAGE_MASK    4095        // page bitmask (2^IVY_PAGE_SIZE)-1
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the internal memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManStartMemory( Ivy_Man_t * p )
+{
+    p->vChunks = Vec_PtrAlloc( 128 );
+    p->vPages = Vec_PtrAlloc( 128 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the internal memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManStopMemory( Ivy_Man_t * p )
+{
+    void * pMemory;
+    int i;
+    Vec_PtrForEachEntry( void *, p->vChunks, pMemory, i )
+        ABC_FREE( pMemory );
+    Vec_PtrFree( p->vChunks );
+    Vec_PtrFree( p->vPages );
+    p->pListFree = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates additional memory for the nodes.]
+
+  Description [Allocates IVY_PAGE_SIZE nodes. Aligns memory by 32 bytes. 
+  Records the pointer to the AIG manager in the -1 entry.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManAddMemory( Ivy_Man_t * p )
+{
+    char * pMemory;
+    int i, nBytes;
+    int EntrySizeMax = 128;
+    assert( sizeof(Ivy_Obj_t) <= EntrySizeMax );
+    assert( p->pListFree == NULL );
+//    assert( (Ivy_ManObjNum(p) & IVY_PAGE_MASK) == 0 );
+    // allocate new memory page
+    nBytes = sizeof(Ivy_Obj_t) * (1<<IVY_PAGE_SIZE) + EntrySizeMax;
+    pMemory = ABC_ALLOC( char, nBytes );
+    Vec_PtrPush( p->vChunks, pMemory );
+    // align memory at the 32-byte boundary
+    pMemory = pMemory + EntrySizeMax - (((int)(ABC_PTRUINT_T)pMemory) & (EntrySizeMax-1));
+    // remember the manager in the first entry
+    Vec_PtrPush( p->vPages, pMemory );
+    // break the memory down into nodes
+    p->pListFree = (Ivy_Obj_t *)pMemory;
+    for ( i = 1; i <= IVY_PAGE_MASK; i++ )
+    {
+        *((char **)pMemory) = pMemory + sizeof(Ivy_Obj_t);
+        pMemory += sizeof(Ivy_Obj_t);
+    }
+    *((char **)pMemory) = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyMulti.c b/abc-build/src/aig/ivy/ivyMulti.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyMulti.c
@@ -0,0 +1,312 @@
+/**CFile****************************************************************
+
+  FileName    [ivyMulti.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Constructing multi-input AND/EXOR gates.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define IVY_EVAL_LIMIT    128
+
+typedef struct Ivy_Eva_t_ Ivy_Eva_t;
+struct Ivy_Eva_t_
+{
+    Ivy_Obj_t * pArg;     // the argument node
+    unsigned    Mask;     // the mask of covered nodes
+    int         Weight;   // the number of covered nodes
+};
+
+static void Ivy_MultiPrint( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals );
+static int Ivy_MultiCover( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs a balanced tree while taking sharing into account.]
+
+  Description [Returns 1 if the implementation exists.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_MultiPlus( Ivy_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSols )
+{
+    static Ivy_Eva_t pEvals[IVY_EVAL_LIMIT];
+    Ivy_Eva_t * pEval, * pFan0, * pFan1;
+    Ivy_Obj_t * pObj = NULL; // Suppress "might be used uninitialized"
+    Ivy_Obj_t * pTemp;
+    int nEvals, nEvalsOld, i, k, x, nLeaves;
+    unsigned uMaskAll;
+
+    // consider special cases
+    nLeaves = Vec_PtrSize(vLeaves);
+    assert( nLeaves > 2 );
+    if ( nLeaves > 32 || nLeaves + Vec_PtrSize(vCone) > IVY_EVAL_LIMIT )
+        return 0;
+//    if ( nLeaves == 1 )
+//        return Vec_PtrEntry( vLeaves, 0 );
+//    if ( nLeaves == 2 )
+//        return Ivy_Oper( Vec_PtrEntry(vLeaves, 0), Vec_PtrEntry(vLeaves, 1), Type );
+
+    // set the leaf entries
+    uMaskAll = ((1 << nLeaves) - 1);
+    nEvals = 0;
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vLeaves, pObj, i )
+    {
+        pEval = pEvals + nEvals;
+        pEval->pArg   = pObj;
+        pEval->Mask   = (1 << nEvals);
+        pEval->Weight = 1;
+        // mark the leaf
+        Ivy_Regular(pObj)->TravId = nEvals;
+        nEvals++;
+    }
+
+    // propagate masks through the cone
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pObj, i )
+    {
+        pObj->TravId = nEvals + i;
+        if ( Ivy_ObjIsBuf(pObj) )
+            pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask;
+        else
+            pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask | pEvals[Ivy_ObjFanin1(pObj)->TravId].Mask;
+    }
+
+    // set the internal entries
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pObj, i )
+    {
+        if ( i == Vec_PtrSize(vCone) - 1 )
+            break;
+        // skip buffers
+        if ( Ivy_ObjIsBuf(pObj) )
+            continue;
+        // skip nodes without external fanout
+        if ( Ivy_ObjRefs(pObj) == 0 )
+            continue;
+        assert( !Ivy_IsComplement(pObj) );
+        pEval = pEvals + nEvals;
+        pEval->pArg   = pObj;
+        pEval->Mask   = pEvals[pObj->TravId].Mask;
+        pEval->Weight = Extra_WordCountOnes(pEval->Mask);
+        // mark the node
+        pObj->TravId = nEvals;
+        nEvals++;
+    }
+
+    // find the available nodes
+    nEvalsOld = nEvals;
+    for ( i = 1; i < nEvals; i++ )
+    for ( k = 0; k < i; k++ )
+    {
+        pFan0 = pEvals + i;
+        pFan1 = pEvals + k;
+        pTemp = Ivy_TableLookup(p, Ivy_ObjCreateGhost(p, pFan0->pArg, pFan1->pArg, Type, IVY_INIT_NONE));
+        // skip nodes in the cone
+        if ( pTemp == NULL || pTemp->fMarkB )
+            continue;
+        // skip the leaves
+        for ( x = 0; x < nLeaves; x++ )
+            if ( pTemp == Ivy_Regular((Ivy_Obj_t *)vLeaves->pArray[x]) )
+                break;
+        if ( x < nLeaves )
+            continue;
+        pEval = pEvals + nEvals;
+        pEval->pArg   = pTemp;
+        pEval->Mask   = pFan0->Mask | pFan1->Mask;
+        pEval->Weight = (pFan0->Mask & pFan1->Mask) ? Extra_WordCountOnes(pEval->Mask) : pFan0->Weight + pFan1->Weight;
+        // save the argument
+        pObj->TravId = nEvals;
+        nEvals++;
+        // quit if the number of entries exceeded the limit
+        if ( nEvals == IVY_EVAL_LIMIT )
+            goto Outside;
+        // quit if we found an acceptable implementation
+        if ( pEval->Mask == uMaskAll )
+            goto Outside;
+    }
+Outside:
+
+//    Ivy_MultiPrint( pEvals, nLeaves, nEvals );
+    if ( !Ivy_MultiCover( p, pEvals, nLeaves, nEvals, nLimit, vSols ) )
+        return 0;
+    assert( Vec_PtrSize( vSols ) > 0 );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes how many uncovered ones this one covers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_MultiPrint( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals )
+{
+    Ivy_Eva_t * pEval;
+    int i, k;
+    for ( i = nLeaves; i < nEvals; i++ )
+    {
+        pEval = pEvals + i;
+        printf( "%2d  (id = %5d)  : |", i-nLeaves, Ivy_ObjId(pEval->pArg) );
+        for ( k = 0; k < nLeaves; k++ )
+        {
+            if ( pEval->Mask & (1 << k) )
+                printf( "+" );
+            else
+                printf( " " );
+        }
+        printf( "|  Lev = %d.\n", Ivy_ObjLevel(pEval->pArg) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes how many uncovered ones this one covers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Ivy_MultiWeight( unsigned uMask, int nMaskOnes, unsigned uFound )
+{
+    assert( uMask & ~uFound );
+    if ( (uMask & uFound) == 0 )
+        return nMaskOnes;
+    return Extra_WordCountOnes( uMask & ~uFound );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the cover.]
+
+  Description [Returns 1 if the cover is found.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_MultiCover( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols )
+{
+    int fVerbose = 0;
+    Ivy_Eva_t * pEval;
+    Ivy_Eva_t * pEvalBest = NULL; // Suppress "might be used uninitialized"
+    unsigned uMaskAll, uFound, uTemp;
+    int i, k, BestK;
+    int WeightBest = -1; // Suppress "might be used uninitialized"
+    int WeightCur;
+    int LevelBest = -1; // Suppress "might be used uninitialized"
+    int LevelCur;
+    uMaskAll = (nLeaves == 32)? (~(unsigned)0) : ((1 << nLeaves) - 1);
+    uFound = 0;
+    // solve the covering problem
+    if ( fVerbose )
+    printf( "Solution:  " );
+    Vec_PtrClear( vSols );
+    for ( i = 0; i < nLimit; i++ )
+    {
+        BestK = -1;
+        for ( k = nEvals - 1; k >= 0; k-- )
+        {
+            pEval = pEvals + k;
+            if ( (pEval->Mask & ~uFound) == 0 )
+                continue;
+            if ( BestK == -1 )
+            {
+                BestK      = k;
+                pEvalBest  = pEval;
+                WeightBest = Ivy_MultiWeight( pEvalBest->Mask, pEvalBest->Weight, uFound );
+                LevelBest  = Ivy_ObjLevel( Ivy_Regular(pEvalBest->pArg) );
+                continue;
+            }
+            // compare BestK and the new one (k)
+            WeightCur = Ivy_MultiWeight( pEval->Mask, pEval->Weight, uFound );
+            LevelCur = Ivy_ObjLevel( Ivy_Regular(pEval->pArg) );
+            if ( WeightBest < WeightCur || 
+                (WeightBest == WeightCur && LevelBest > LevelCur) )
+            {
+                BestK      = k;
+                pEvalBest  = pEval;
+                WeightBest = WeightCur;
+                LevelBest  = LevelCur;
+            }
+        }
+        assert( BestK != -1 );
+        // if the cost is only 1, take the leaf
+        if ( WeightBest == 1 && BestK >= nLeaves )
+        {
+            uTemp = (pEvalBest->Mask & ~uFound);
+            for ( k = 0; k < nLeaves; k++ )
+                if ( uTemp & (1 << k) )
+                    break;
+            assert( k < nLeaves );
+            BestK     = k;
+            pEvalBest = pEvals + BestK;
+        }
+        if ( fVerbose )
+        {
+            if ( BestK < nLeaves )
+                printf( "L(%d) ", BestK );
+            else
+                printf( "%d ", BestK - nLeaves );
+        }
+        // update the found set
+        Vec_PtrPush( vSols, pEvalBest->pArg );
+        uFound |= pEvalBest->Mask;
+        if ( uFound == uMaskAll )
+            break;
+    }
+    if ( uFound == uMaskAll )
+    {
+        if ( fVerbose )
+            printf( "  Found \n\n" );
+        return 1;
+    }
+    else
+    {
+        if ( fVerbose )
+            printf( "  Not found \n\n" );
+        return 0;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyMulti8.c b/abc-build/src/aig/ivy/ivyMulti8.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyMulti8.c
@@ -0,0 +1,432 @@
+/**CFile****************************************************************
+
+  FileName    [ivyMulti.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Constructing multi-input AND/EXOR gates.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ivy_Eval_t_ Ivy_Eval_t;
+struct Ivy_Eval_t_
+{
+    unsigned Mask   :  5;  // the mask of covered nodes
+    unsigned Weight :  3;  // the number of covered nodes
+    unsigned Cost   :  4;  // the number of overlapping nodes
+    unsigned Level  : 12;  // the level of this node
+    unsigned Fan0   :  4;  // the first fanin
+    unsigned Fan1   :  4;  // the second fanin
+};
+
+static Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
+static void        Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs );
+static int         Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode );
+static Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs the well-balanced tree of gates.]
+
+  Description [Disregards levels and possible logic sharing.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Multi_rec( Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type )
+{
+    Ivy_Obj_t * pObj1, * pObj2;
+    if ( nObjs == 1 )
+        return ppObjs[0];
+    pObj1 = Ivy_Multi_rec( ppObjs,           nObjs/2,         Type );
+    pObj2 = Ivy_Multi_rec( ppObjs + nObjs/2, nObjs - nObjs/2, Type );
+    return Ivy_Oper( pObj1, pObj2, Type );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs a balanced tree while taking sharing into account.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Multi( Ivy_Obj_t ** pArgsInit, int nArgs, Ivy_Type_t Type )
+{
+    static char NumBits[32] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5};
+    static Ivy_Eval_t pEvals[15+15*14/2];
+    static Ivy_Obj_t * pArgs[16];
+    Ivy_Eval_t * pEva, * pEvaBest;
+    int nArgsNew, nEvals, i, k;
+    Ivy_Obj_t * pTemp;
+
+    // consider the case of one argument
+    assert( nArgs > 0 );
+    if ( nArgs == 1 )
+        return pArgsInit[0];
+    // consider the case of two arguments
+    if ( nArgs == 2 )
+        return Ivy_Oper( pArgsInit[0], pArgsInit[1], Type );
+
+//Ivy_MultiEval( pArgsInit, nArgs, Type ); printf( "\n" );
+
+    // set the initial ones
+    for ( i = 0; i < nArgs; i++ )
+    {
+        pArgs[i] = pArgsInit[i];
+        pEva = pEvals + i;
+        pEva->Mask   = (1 << i);
+        pEva->Weight = 1;
+        pEva->Cost   = 0; 
+        pEva->Level  = Ivy_Regular(pArgs[i])->Level; 
+        pEva->Fan0   = 0; 
+        pEva->Fan1   = 0; 
+    }
+
+    // find the available nodes
+    pEvaBest = pEvals;
+    nArgsNew = nArgs;
+    for ( i = 1; i < nArgsNew; i++ )
+    for ( k = 0; k < i; k++ )
+        if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE)) )
+        {
+            pEva = pEvals + nArgsNew;
+            pEva->Mask   = pEvals[k].Mask | pEvals[i].Mask;
+            pEva->Weight = NumBits[pEva->Mask];
+            pEva->Cost   = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask]; 
+            pEva->Level  = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level); 
+            pEva->Fan0   = k; 
+            pEva->Fan1   = i; 
+//            assert( pEva->Level == (unsigned)Ivy_ObjLevel(pTemp) );
+            // compare
+            if ( pEvaBest->Weight < pEva->Weight ||
+                 pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost ||
+                 pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level )
+                 pEvaBest = pEva;
+            // save the argument
+            pArgs[nArgsNew++] = pTemp;
+            if ( nArgsNew == 15 )
+                goto Outside;
+        }
+Outside:
+
+//    printf( "Best = %d.\n", pEvaBest - pEvals );
+
+    // the case of no common nodes
+    if ( nArgsNew == nArgs )
+    {
+        Ivy_MultiSort( pArgs, nArgs );
+        return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
+    }
+    // the case of one common node
+    if ( nArgsNew == nArgs + 1 )
+    {
+        assert( pEvaBest - pEvals == nArgs );
+        k = 0;
+        for ( i = 0; i < nArgs; i++ )
+            if ( i != (int)pEvaBest->Fan0 && i != (int)pEvaBest->Fan1 )
+                pArgs[k++] = pArgs[i];
+        pArgs[k++] = pArgs[nArgs];
+        assert( k == nArgs - 1 );
+        nArgs = k;
+        Ivy_MultiSort( pArgs, nArgs );
+        return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
+    }
+    // the case when there is a node that covers everything
+    if ( (int)pEvaBest->Mask == ((1 << nArgs) - 1) )
+        return Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type ); 
+
+    // evaluate node pairs
+    nEvals = nArgsNew;
+    for ( i = 1; i < nArgsNew; i++ )
+    for ( k = 0; k < i; k++ )
+    {
+        pEva = pEvals + nEvals;
+        pEva->Mask   = pEvals[k].Mask | pEvals[i].Mask;
+        pEva->Weight = NumBits[pEva->Mask];
+        pEva->Cost   = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask]; 
+        pEva->Level  = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level); 
+        pEva->Fan0   = k; 
+        pEva->Fan1   = i; 
+        // compare
+        if ( pEvaBest->Weight < pEva->Weight ||
+             pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost ||
+             pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level )
+             pEvaBest = pEva;
+        // save the argument
+        nEvals++;
+    }
+    assert( pEvaBest - pEvals >= nArgsNew );
+
+//    printf( "Used (%d, %d).\n", pEvaBest->Fan0, pEvaBest->Fan1 );
+
+    // get the best implementation
+    pTemp = Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type );
+
+    // collect those not covered by EvaBest
+    k = 0;
+    for ( i = 0; i < nArgs; i++ )
+        if ( (pEvaBest->Mask & (1 << i)) == 0 )
+            pArgs[k++] = pArgs[i];
+    pArgs[k++] = pTemp;
+    assert( k == nArgs - (int)pEvaBest->Weight + 1 );
+    nArgs = k;
+    Ivy_MultiSort( pArgs, nArgs );
+    return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements multi-input AND/EXOR operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
+{
+    Ivy_Obj_t * pNode0, * pNode1;
+    if ( iNum < nArgs )
+        return pArgs[iNum];
+    pNode0 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan0, pArgs, nArgs, Type );
+    pNode1 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan1, pArgs, nArgs, Type );
+    return Ivy_Oper( pNode0, pNode1, Type );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Selection-sorts the nodes in the decreasing over of level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs )
+{
+    Ivy_Obj_t * pTemp;
+    int i, j, iBest;
+
+    for ( i = 0; i < nArgs-1; i++ )
+    {
+        iBest = i;
+        for ( j = i+1; j < nArgs; j++ )
+            if ( Ivy_Regular(pArgs[j])->Level > Ivy_Regular(pArgs[iBest])->Level )
+                iBest = j;
+        pTemp = pArgs[i]; 
+        pArgs[i] = pArgs[iBest]; 
+        pArgs[iBest] = pTemp;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts a new node in the order by levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode )
+{
+    Ivy_Obj_t * pNode1, * pNode2;
+    int i;
+    // try to find the node in the array
+    for ( i = 0; i < nArgs; i++ )
+        if ( pArray[i] == pNode )
+            return nArgs;
+    // put the node last
+    pArray[nArgs++] = pNode;
+    // find the place to put the new node
+    for ( i = nArgs-1; i > 0; i-- )
+    {
+        pNode1 = pArray[i  ];
+        pNode2 = pArray[i-1];
+        if ( Ivy_Regular(pNode1)->Level <= Ivy_Regular(pNode2)->Level )
+            break;
+        pArray[i  ] = pNode2;
+        pArray[i-1] = pNode1;
+    }
+    return nArgs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Balances the array recursively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
+{
+    Ivy_Obj_t * pNodeNew;
+    // consider the case of one argument
+    assert( nArgs > 0 );
+    if ( nArgs == 1 )
+        return pArgs[0];
+    // consider the case of two arguments
+    if ( nArgs == 2 )
+        return Ivy_Oper( pArgs[0], pArgs[1], Type );
+    // get the last two nodes
+    pNodeNew = Ivy_Oper( pArgs[nArgs-1], pArgs[nArgs-2], Type );
+    // add the new node
+    nArgs = Ivy_MultiPushUniqueOrderByLevel( pArgs, nArgs - 2, pNodeNew );
+    return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements multi-input AND/EXOR operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
+{
+    Ivy_Obj_t * pTemp;
+    int i, k;
+    int nArgsOld = nArgs;
+    for ( i = 0; i < nArgs; i++ )
+        printf( "%d[%d] ", i, Ivy_Regular(pArgs[i])->Level );
+    for ( i = 1; i < nArgs; i++ )
+        for ( k = 0; k < i; k++ )
+        {
+            pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE));
+            if ( pTemp != NULL )
+            {
+                printf( "%d[%d]=(%d,%d) ", nArgs, Ivy_Regular(pTemp)->Level, k, i );
+                pArgs[nArgs++] = pTemp;
+            }
+        }
+    printf( "     ((%d/%d))    ", nArgsOld, nArgs-nArgsOld );
+    return NULL;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Old code.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Multi1( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
+{
+    Ivy_Obj_t * pArgsRef[5], * pTemp;
+    int i, k, m, nArgsNew, Counter = 0;
+ 
+    
+//Ivy_MultiEval( pArgs, nArgs, Type );  printf( "\n" );
+
+
+    assert( Type == IVY_AND || Type == IVY_EXOR );
+    assert( nArgs > 0 );
+    if ( nArgs == 1 )
+        return pArgs[0];
+
+    // find the nodes with more than one fanout
+    nArgsNew = 0;
+    for ( i = 0; i < nArgs; i++ )
+        if ( Ivy_ObjRefs( Ivy_Regular(pArgs[i]) ) > 0 )
+            pArgsRef[nArgsNew++] = pArgs[i];
+
+    // go through pairs
+    if ( nArgsNew >= 2 )
+    for ( i = 0; i < nArgsNew; i++ )
+    for ( k = i + 1; k < nArgsNew; k++ )
+        if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) )
+            Counter++;
+//    printf( "%d", Counter );
+            
+    // go through pairs
+    if ( nArgsNew >= 2 )
+    for ( i = 0; i < nArgsNew; i++ )
+    for ( k = i + 1; k < nArgsNew; k++ )
+        if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) )
+        {
+            nArgsNew = 0;
+            for ( m = 0; m < nArgs; m++ )
+                if ( pArgs[m] != pArgsRef[i] && pArgs[m] != pArgsRef[k] )
+                    pArgs[nArgsNew++] = pArgs[m];
+            pArgs[nArgsNew++] = pTemp;
+            assert( nArgsNew == nArgs - 1 );
+            return Ivy_Multi1( pArgs, nArgsNew, Type );
+        }
+    return Ivy_Multi_rec( pArgs, nArgs, Type );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Old code.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Multi2( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
+{
+    assert( Type == IVY_AND || Type == IVY_EXOR );
+    assert( nArgs > 0 );
+    return Ivy_Multi_rec( pArgs, nArgs, Type );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyObj.c b/abc-build/src/aig/ivy/ivyObj.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyObj.c
@@ -0,0 +1,481 @@
+/**CFile****************************************************************
+
+  FileName    [ivyObj.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Adding/removing objects.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyObj.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Create the new node assuming it does not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_ObjCreatePi( Ivy_Man_t * p )
+{
+    return Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, NULL, NULL, IVY_PI, IVY_INIT_NONE) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the new node assuming it does not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_ObjCreatePo( Ivy_Man_t * p, Ivy_Obj_t * pDriver )
+{
+    return Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pDriver, NULL, IVY_PO, IVY_INIT_NONE) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the new node assuming it does not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost )
+{
+    Ivy_Obj_t * pObj;
+    assert( !Ivy_IsComplement(pGhost) );
+    assert( Ivy_ObjIsGhost(pGhost) );
+    assert( Ivy_TableLookup(p, pGhost) == NULL );
+    // get memory for the new object
+    pObj = Ivy_ManFetchMemory( p );
+    assert( Ivy_ObjIsNone(pObj) );
+    pObj->Id = Vec_PtrSize(p->vObjs);
+    Vec_PtrPush( p->vObjs, pObj );
+    // add basic info (fanins, compls, type, init)
+    pObj->Type = pGhost->Type;
+    pObj->Init = pGhost->Init;
+    // add connections
+    Ivy_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 );
+    // compute level
+    if ( Ivy_ObjIsNode(pObj) )
+        pObj->Level = Ivy_ObjLevelNew(pObj);
+    else if ( Ivy_ObjIsLatch(pObj) )
+        pObj->Level = 0;
+    else if ( Ivy_ObjIsOneFanin(pObj) )
+        pObj->Level = Ivy_ObjFanin0(pObj)->Level;
+    else if ( !Ivy_ObjIsPi(pObj) )
+        assert( 0 );
+    // create phase
+    if ( Ivy_ObjIsNode(pObj) )
+        pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) & Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj));
+    else if ( Ivy_ObjIsOneFanin(pObj) )
+        pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj));
+    // set the fail TFO flag
+    if ( Ivy_ObjIsNode(pObj) )
+        pObj->fFailTfo = Ivy_ObjFanin0(pObj)->fFailTfo | Ivy_ObjFanin1(pObj)->fFailTfo;
+    // mark the fanins in a special way if the node is EXOR
+    if ( Ivy_ObjIsExor(pObj) )
+    {
+        Ivy_ObjFanin0(pObj)->fExFan = 1;
+        Ivy_ObjFanin1(pObj)->fExFan = 1;
+    }
+    // add PIs/POs to the arrays
+    if ( Ivy_ObjIsPi(pObj) )
+        Vec_PtrPush( p->vPis, pObj );
+    else if ( Ivy_ObjIsPo(pObj) )
+        Vec_PtrPush( p->vPos, pObj );
+//    else if ( Ivy_ObjIsBuf(pObj) )
+//        Vec_PtrPush( p->vBufs, pObj );
+    if ( p->vRequired && Vec_IntSize(p->vRequired) <= pObj->Id )
+        Vec_IntFillExtra( p->vRequired, 2 * Vec_IntSize(p->vRequired), 1000000 );
+    // update node counters of the manager
+    p->nObjs[Ivy_ObjType(pObj)]++;
+    p->nCreated++;
+
+//    printf( "Adding %sAIG node: ", p->pHaig==NULL? "H":" " );
+//    Ivy_ObjPrintVerbose( p, pObj, p->pHaig==NULL );
+//    printf( "\n" );
+
+    // if HAIG is defined, create a corresponding node
+    if ( p->pHaig )
+        Ivy_ManHaigCreateObj( p, pObj );
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Connect the object to the fanin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ObjConnect( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFan0, Ivy_Obj_t * pFan1 )
+{
+    assert( !Ivy_IsComplement(pObj) );
+    assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || pFan1 != NULL );
+    // add the first fanin
+    pObj->pFanin0 = pFan0;
+    pObj->pFanin1 = pFan1;
+    // increment references of the fanins and add their fanouts
+    if ( Ivy_ObjFanin0(pObj) != NULL )
+    {
+        Ivy_ObjRefsInc( Ivy_ObjFanin0(pObj) );
+        if ( p->fFanout )
+            Ivy_ObjAddFanout( p, Ivy_ObjFanin0(pObj), pObj );
+    }
+    if ( Ivy_ObjFanin1(pObj) != NULL )
+    {
+        Ivy_ObjRefsInc( Ivy_ObjFanin1(pObj) );
+        if ( p->fFanout )
+            Ivy_ObjAddFanout( p, Ivy_ObjFanin1(pObj), pObj );
+    }
+    // add the node to the structural hash table
+    Ivy_TableInsert( p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Connect the object to the fanin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ObjDisconnect( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+    assert( !Ivy_IsComplement(pObj) );
+    assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || Ivy_ObjFanin1(pObj) != NULL );
+    // remove connections
+    if ( pObj->pFanin0 != NULL )
+    {
+        Ivy_ObjRefsDec(Ivy_ObjFanin0(pObj));
+        if ( p->fFanout )
+            Ivy_ObjDeleteFanout( p, Ivy_ObjFanin0(pObj), pObj );
+    }
+    if ( pObj->pFanin1 != NULL )
+    {
+        Ivy_ObjRefsDec(Ivy_ObjFanin1(pObj));
+        if ( p->fFanout )
+            Ivy_ObjDeleteFanout( p, Ivy_ObjFanin1(pObj), pObj );
+    }
+    assert( pObj->pNextFan0 == NULL );
+    assert( pObj->pNextFan1 == NULL );
+    assert( pObj->pPrevFan0 == NULL );
+    assert( pObj->pPrevFan1 == NULL );
+    // remove the node from the structural hash table
+    Ivy_TableDelete( p, pObj );
+    // add the first fanin
+    pObj->pFanin0 = NULL;
+    pObj->pFanin1 = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces the first fanin of the node by the new fanin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ObjPatchFanin0( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFaninNew )
+{
+    Ivy_Obj_t * pFaninOld;
+    assert( !Ivy_IsComplement(pObj) );
+    pFaninOld = Ivy_ObjFanin0(pObj);
+    // decrement ref and remove fanout
+    Ivy_ObjRefsDec( pFaninOld );
+    if ( p->fFanout )
+        Ivy_ObjDeleteFanout( p, pFaninOld, pObj );
+    // update the fanin
+    pObj->pFanin0 = pFaninNew;
+    // increment ref and add fanout
+    Ivy_ObjRefsInc( Ivy_Regular(pFaninNew) );
+    if ( p->fFanout )
+        Ivy_ObjAddFanout( p, Ivy_Regular(pFaninNew), pObj );
+    // get rid of old fanin
+    if ( !Ivy_ObjIsPi(pFaninOld) && !Ivy_ObjIsConst1(pFaninOld) && Ivy_ObjRefs(pFaninOld) == 0 )
+        Ivy_ObjDelete_rec( p, pFaninOld, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop )
+{
+    assert( !Ivy_IsComplement(pObj) );
+    assert( Ivy_ObjRefs(pObj) == 0 || !fFreeTop );
+    // update node counters of the manager
+    p->nObjs[pObj->Type]--;
+    p->nDeleted++;
+    // remove connections
+    Ivy_ObjDisconnect( p, pObj );
+    // remove PIs/POs from the arrays
+    if ( Ivy_ObjIsPi(pObj) )
+        Vec_PtrRemove( p->vPis, pObj );
+    else if ( Ivy_ObjIsPo(pObj) )
+        Vec_PtrRemove( p->vPos, pObj );
+    else if ( p->fFanout && Ivy_ObjIsBuf(pObj) )
+        Vec_PtrRemove( p->vBufs, pObj );
+    // clean and recycle the entry
+    if ( fFreeTop )
+    {
+        // free the node
+        Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL );
+        Ivy_ManRecycleMemory( p, pObj );
+    }
+    else
+    {
+        int nRefsOld = pObj->nRefs;
+        Ivy_Obj_t * pFanout = pObj->pFanout;
+        Ivy_ObjClean( pObj );
+        pObj->pFanout = pFanout;
+        pObj->nRefs = nRefsOld;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the MFFC of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop )
+{
+    Ivy_Obj_t * pFanin0, * pFanin1;
+    assert( !Ivy_IsComplement(pObj) );
+    assert( !Ivy_ObjIsNone(pObj) );
+    if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsPi(pObj) )
+        return;
+    pFanin0 = Ivy_ObjFanin0(pObj);
+    pFanin1 = Ivy_ObjFanin1(pObj);
+    Ivy_ObjDelete( p, pObj, fFreeTop );
+    if ( pFanin0 && !Ivy_ObjIsNone(pFanin0) && Ivy_ObjRefs(pFanin0) == 0 )
+        Ivy_ObjDelete_rec( p, pFanin0, 1 );
+    if ( pFanin1 && !Ivy_ObjIsNone(pFanin1) && Ivy_ObjRefs(pFanin1) == 0 )
+        Ivy_ObjDelete_rec( p, pFanin1, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces one object by another.]
+
+  Description [Both objects are currently in the manager. The new object
+  (pObjNew) should be used instead of the old object (pObjOld). If the 
+  new object is complemented or used, the buffer is added.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel )
+{
+    int nRefsOld;//, clk;
+    // the object to be replaced cannot be complemented
+    assert( !Ivy_IsComplement(pObjOld) );
+    // the object to be replaced cannot be a terminal
+    assert( Ivy_ObjIsNone(pObjOld) || !Ivy_ObjIsPi(pObjOld) );
+    // the object to be used cannot be a PO or assert
+    assert( !Ivy_ObjIsBuf(Ivy_Regular(pObjNew)) );
+    // the object cannot be the same
+    assert( pObjOld != Ivy_Regular(pObjNew) );
+//printf( "Replacing %d by %d.\n", Ivy_Regular(pObjOld)->Id, Ivy_Regular(pObjNew)->Id );
+
+    // if HAIG is defined, create the choice node
+    if ( p->pHaig )
+    {
+//        if ( pObjOld->Id == 31 )
+//        {
+//            Ivy_ManShow( p, 0 );
+//            Ivy_ManShow( p->pHaig, 1 );
+//        }
+        Ivy_ManHaigCreateChoice( p, pObjOld, pObjNew );
+    }
+    // if the new object is complemented or already used, add the buffer
+    if ( Ivy_IsComplement(pObjNew) || Ivy_ObjIsLatch(pObjNew) || Ivy_ObjRefs(pObjNew) > 0 || Ivy_ObjIsPi(pObjNew) || Ivy_ObjIsConst1(pObjNew) )
+        pObjNew = Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pObjNew, NULL, IVY_BUF, IVY_INIT_NONE) );
+    assert( !Ivy_IsComplement(pObjNew) );
+    if ( fUpdateLevel )
+    {
+//clk = Abc_Clock();
+        // if the new node's arrival time is different, recursively update arrival time of the fanouts
+        if ( p->fFanout && !Ivy_ObjIsBuf(pObjNew) && pObjOld->Level != pObjNew->Level )
+        {
+            assert( Ivy_ObjIsNode(pObjOld) );
+            pObjOld->Level = pObjNew->Level;
+            Ivy_ObjUpdateLevel_rec( p, pObjOld );
+        }
+//p->time1 += Abc_Clock() - clk;
+        // if the new node's required time has changed, recursively update required time of the fanins
+//clk = Abc_Clock();
+        if ( p->vRequired )
+        {
+            int ReqNew = Vec_IntEntry(p->vRequired, pObjOld->Id);
+            if ( ReqNew < Vec_IntEntry(p->vRequired, pObjNew->Id) )
+            {
+                Vec_IntWriteEntry( p->vRequired, pObjNew->Id, ReqNew );
+                Ivy_ObjUpdateLevelR_rec( p, pObjNew, ReqNew );
+            }
+        }
+//p->time2 += Abc_Clock() - clk;
+    }
+    // delete the old object
+    if ( fDeleteOld )
+        Ivy_ObjDelete_rec( p, pObjOld, fFreeTop );
+    // make sure object is not pointing to itself
+    assert( Ivy_ObjFanin0(pObjNew) == NULL || pObjOld != Ivy_ObjFanin0(pObjNew) );
+    assert( Ivy_ObjFanin1(pObjNew) == NULL || pObjOld != Ivy_ObjFanin1(pObjNew) );
+    // make sure the old node has no fanin fanout pointers
+    if ( p->fFanout )
+    {
+        assert( pObjOld->pFanout != NULL );
+        assert( pObjNew->pFanout == NULL );
+        pObjNew->pFanout = pObjOld->pFanout;
+    }
+    // transfer the old object
+    assert( Ivy_ObjRefs(pObjNew) == 0 );
+    nRefsOld = pObjOld->nRefs;  
+    Ivy_ObjOverwrite( pObjOld, pObjNew );
+    pObjOld->nRefs = nRefsOld;
+    // patch the fanout of the fanins 
+    if ( p->fFanout )
+    {
+        Ivy_ObjPatchFanout( p, Ivy_ObjFanin0(pObjOld), pObjNew, pObjOld );
+        if ( Ivy_ObjFanin1(pObjOld) )
+        Ivy_ObjPatchFanout( p, Ivy_ObjFanin1(pObjOld), pObjNew, pObjOld );
+    }
+    // update the hash table
+    Ivy_TableUpdate( p, pObjNew, pObjOld->Id );
+    // recycle the object that was taken over by pObjOld
+    Vec_PtrWriteEntry( p->vObjs, pObjNew->Id, NULL );
+    Ivy_ManRecycleMemory( p, pObjNew );
+    // if the new node is the buffer propagate it
+    if ( p->fFanout && Ivy_ObjIsBuf(pObjOld) )
+        Vec_PtrPush( p->vBufs, pObjOld );
+//    Ivy_ManCheckFanouts( p );
+//    printf( "\n" );
+/*
+    if ( p->pHaig )
+    {
+        int x;
+        Ivy_ManShow( p, 0, NULL );
+        Ivy_ManShow( p->pHaig, 1, NULL );
+        x = 0;
+    }
+*/
+//    if ( Ivy_ManCheckFanoutNums(p) )
+//    {
+//        int x = 0;
+//    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fixes buffer fanins.]
+
+  Description [This situation happens because NodeReplace is a lazy
+  procedure, which does not propagate the change to the fanouts but
+  instead records the change in the form of a buf/inv node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_NodeFixBufferFanins( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel )
+{
+    Ivy_Obj_t * pFanReal0, * pFanReal1, * pResult;
+    if ( Ivy_ObjIsPo(pNode) )
+    {
+        if ( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) )
+            return;
+        pFanReal0 = Ivy_ObjReal( Ivy_ObjChild0(pNode) );
+        Ivy_ObjPatchFanin0( p, pNode, pFanReal0 );
+//        Ivy_ManCheckFanouts( p );
+        return;
+    }
+    if ( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) && !Ivy_ObjIsBuf(Ivy_ObjFanin1(pNode)) )
+        return;
+    // get the real fanins
+    pFanReal0 = Ivy_ObjReal( Ivy_ObjChild0(pNode) );
+    pFanReal1 = Ivy_ObjReal( Ivy_ObjChild1(pNode) );
+    // get the new node
+    if ( Ivy_ObjIsNode(pNode) )
+        pResult = Ivy_Oper( p, pFanReal0, pFanReal1, Ivy_ObjType(pNode) );
+    else if ( Ivy_ObjIsLatch(pNode) )
+        pResult = Ivy_Latch( p, pFanReal0, Ivy_ObjInit(pNode) );
+    else 
+        assert( 0 );
+
+//printf( "===== Replacing %d by %d.\n", pNode->Id, pResult->Id );
+//Ivy_ObjPrintVerbose( p, pNode, 0 );   printf( "\n" );
+//Ivy_ObjPrintVerbose( p, pResult, 0 ); printf( "\n" );
+
+    // perform the replacement
+    Ivy_ObjReplace( p, pNode, pResult, 1, 0, fUpdateLevel ); 
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyOper.c b/abc-build/src/aig/ivy/ivyOper.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyOper.c
@@ -0,0 +1,298 @@
+/**CFile****************************************************************
+
+  FileName    [ivyOper.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [AIG operations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyOper.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// procedure to detect an EXOR gate
+static inline int Ivy_ObjIsExorType( Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Obj_t ** ppFan0, Ivy_Obj_t ** ppFan1 )
+{
+    if ( !Ivy_IsComplement(p0) || !Ivy_IsComplement(p1) )
+        return 0;
+    p0 = Ivy_Regular(p0);
+    p1 = Ivy_Regular(p1);
+    if ( !Ivy_ObjIsAnd(p0) || !Ivy_ObjIsAnd(p1) )
+        return 0;
+    if ( Ivy_ObjFanin0(p0) != Ivy_ObjFanin0(p1) || Ivy_ObjFanin1(p0) != Ivy_ObjFanin1(p1) )
+        return 0;
+    if ( Ivy_ObjFaninC0(p0) == Ivy_ObjFaninC0(p1) || Ivy_ObjFaninC1(p0) == Ivy_ObjFaninC1(p1) )
+        return 0;
+    *ppFan0 = Ivy_ObjChild0(p0);
+    *ppFan1 = Ivy_ObjChild1(p0);
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Perform one operation.]
+
+  Description [The argument nodes can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Oper( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type )
+{
+    if ( Type == IVY_AND )
+        return Ivy_And( p, p0, p1 );
+    if ( Type == IVY_EXOR )
+        return Ivy_Exor( p, p0, p1 );
+    assert( 0 );
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs canonicization step.]
+
+  Description [The argument nodes can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_And( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 )
+{
+//    Ivy_Obj_t * pFan0, * pFan1;
+    // check trivial cases
+    if ( p0 == p1 )
+        return p0;
+    if ( p0 == Ivy_Not(p1) )
+        return Ivy_Not(p->pConst1);
+    if ( Ivy_Regular(p0) == p->pConst1 )
+        return p0 == p->pConst1 ? p1 : Ivy_Not(p->pConst1);
+    if ( Ivy_Regular(p1) == p->pConst1 )
+        return p1 == p->pConst1 ? p0 : Ivy_Not(p->pConst1);
+    // check if it can be an EXOR gate
+//    if ( Ivy_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) )
+//        return Ivy_CanonExor( pFan0, pFan1 );
+    return Ivy_CanonAnd( p, p0, p1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs canonicization step.]
+
+  Description [The argument nodes can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Exor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 )
+{
+/*
+    // check trivial cases
+    if ( p0 == p1 )
+        return Ivy_Not(p->pConst1);
+    if ( p0 == Ivy_Not(p1) )
+        return p->pConst1;
+    if ( Ivy_Regular(p0) == p->pConst1 )
+        return Ivy_NotCond( p1, p0 == p->pConst1 );
+    if ( Ivy_Regular(p1) == p->pConst1 )
+        return Ivy_NotCond( p0, p1 == p->pConst1 );
+    // check the table
+    return Ivy_CanonExor( p, p0, p1 );
+*/
+    return Ivy_Or( p, Ivy_And(p, p0, Ivy_Not(p1)), Ivy_And(p, Ivy_Not(p0), p1) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements Boolean OR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Or( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 )
+{
+    return Ivy_Not( Ivy_And( p, Ivy_Not(p0), Ivy_Not(p1) ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements ITE operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Mux( Ivy_Man_t * p, Ivy_Obj_t * pC, Ivy_Obj_t * p1, Ivy_Obj_t * p0 )
+{
+    Ivy_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp;
+    int Count0, Count1;
+    // consider trivial cases
+    if ( p0 == Ivy_Not(p1) )
+        return Ivy_Exor( p, pC, p0 );
+    // other cases can be added
+    // implement the first MUX (F = C * x1 + C' * x0)
+    pTempA1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pC,          p1, IVY_AND, IVY_INIT_NONE) );
+    pTempA2 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pC), p0, IVY_AND, IVY_INIT_NONE) );
+    if ( pTempA1 && pTempA2 )
+    {
+        pTemp = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pTempA1), Ivy_Not(pTempA2), IVY_AND, IVY_INIT_NONE) );
+        if ( pTemp ) return Ivy_Not(pTemp);
+    }
+    Count0 = (pTempA1 != NULL) + (pTempA2 != NULL);
+    // implement the second MUX (F' = C * x1' + C' * x0')
+    pTempB1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pC,          Ivy_Not(p1), IVY_AND, IVY_INIT_NONE) );
+    pTempB2 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pC), Ivy_Not(p0), IVY_AND, IVY_INIT_NONE) );
+    if ( pTempB1 && pTempB2 )
+    {
+        pTemp = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pTempB1), Ivy_Not(pTempB2), IVY_AND, IVY_INIT_NONE) );
+        if ( pTemp ) return pTemp;
+    }
+    Count1 = (pTempB1 != NULL) + (pTempB2 != NULL);
+    // compare and decide which one to implement
+    if ( Count0 >= Count1 )
+    {
+        pTempA1 = pTempA1? pTempA1 : Ivy_And(p, pC,          p1);
+        pTempA2 = pTempA2? pTempA2 : Ivy_And(p, Ivy_Not(pC), p0);
+        return Ivy_Or( p, pTempA1, pTempA2 );
+    }
+    pTempB1 = pTempB1? pTempB1 : Ivy_And(p, pC,          Ivy_Not(p1));
+    pTempB2 = pTempB2? pTempB2 : Ivy_And(p, Ivy_Not(pC), Ivy_Not(p0));
+    return Ivy_Not( Ivy_Or( p, pTempB1, pTempB2 ) );
+
+//    return Ivy_Or( Ivy_And(pC, p1), Ivy_And(Ivy_Not(pC), p0) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements ITE operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Maj( Ivy_Man_t * p, Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * pC )
+{
+    return Ivy_Or( p, Ivy_Or(p, Ivy_And(p, pA, pB), Ivy_And(p, pA, pC)), Ivy_And(p, pB, pC) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs the well-balanced tree of gates.]
+
+  Description [Disregards levels and possible logic sharing.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Multi_rec( Ivy_Man_t * p, Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type )
+{
+    Ivy_Obj_t * pObj1, * pObj2;
+    if ( nObjs == 1 )
+        return ppObjs[0];
+    pObj1 = Ivy_Multi_rec( p, ppObjs,           nObjs/2,         Type );
+    pObj2 = Ivy_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type );
+    return Ivy_Oper( p, pObj1, pObj2, Type );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Old code.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Multi( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
+{
+    assert( Type == IVY_AND || Type == IVY_EXOR );
+    assert( nArgs > 0 );
+    return Ivy_Multi_rec( p, pArgs, nArgs, Type );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Miter( Ivy_Man_t * p, Vec_Ptr_t * vPairs )
+{
+    int i;
+    assert( vPairs->nSize > 0 );
+    assert( vPairs->nSize % 2 == 0 );
+    // go through the cubes of the node's SOP
+    for ( i = 0; i < vPairs->nSize; i += 2 )
+        vPairs->pArray[i/2] = Ivy_Not( Ivy_Exor( p, (Ivy_Obj_t *)vPairs->pArray[i], (Ivy_Obj_t *)vPairs->pArray[i+1] ) );
+    vPairs->nSize = vPairs->nSize/2;
+    return Ivy_Not( Ivy_Multi_rec( p, (Ivy_Obj_t **)vPairs->pArray, vPairs->nSize, IVY_AND ) );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Performs canonicization step.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Latch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init )
+{
+    return Ivy_CanonLatch( p, pObj, Init );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyResyn.c b/abc-build/src/aig/ivy/ivyResyn.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyResyn.c
@@ -0,0 +1,201 @@
+/**CFile****************************************************************
+
+  FileName    [ivyResyn.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [AIG rewriting script.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyResyn.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs several passes of rewriting on the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManResyn0( Ivy_Man_t * pMan, int fUpdateLevel, int fVerbose )
+{
+    abctime clk;
+    Ivy_Man_t * pTemp;
+
+if ( fVerbose ) { printf( "Original:\n" ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = Abc_Clock();
+    pMan = Ivy_ManBalance( pMan, fUpdateLevel );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+//    Ivy_ManRewriteAlg( pMan, fUpdateLevel, 0 );
+clk = Abc_Clock();
+    Ivy_ManRewritePre( pMan, fUpdateLevel, 0, 0 );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = Abc_Clock();
+    pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel );
+    Ivy_ManStop( pTemp );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs several passes of rewriting on the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManResyn( Ivy_Man_t * pMan, int fUpdateLevel, int fVerbose )
+{
+    abctime clk;
+    Ivy_Man_t * pTemp;
+
+if ( fVerbose ) { printf( "Original:\n" ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = Abc_Clock();
+    pMan = Ivy_ManBalance( pMan, fUpdateLevel );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+//    Ivy_ManRewriteAlg( pMan, fUpdateLevel, 0 );
+clk = Abc_Clock();
+    Ivy_ManRewritePre( pMan, fUpdateLevel, 0, 0 );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = Abc_Clock();
+    pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel );
+    Ivy_ManStop( pTemp );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+//    Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 );
+clk = Abc_Clock();
+    Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = Abc_Clock();
+    pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel );
+    Ivy_ManStop( pTemp );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+//    Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 );
+clk = Abc_Clock();
+    Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = Abc_Clock();
+    pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel );
+    Ivy_ManStop( pTemp );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs several passes of rewriting on the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManRwsat( Ivy_Man_t * pMan, int fVerbose )
+{
+    abctime clk;
+    Ivy_Man_t * pTemp;
+
+if ( fVerbose ) { printf( "Original:\n" ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = Abc_Clock();
+    Ivy_ManRewritePre( pMan, 0, 0, 0 );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = Abc_Clock();
+    pMan = Ivy_ManBalance( pTemp = pMan, 0 );
+//    pMan = Ivy_ManDup( pTemp = pMan );
+    Ivy_ManStop( pTemp );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+/*
+clk = Abc_Clock();
+    Ivy_ManRewritePre( pMan, 0, 0, 0 );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = Abc_Clock();
+    pMan = Ivy_ManBalance( pTemp = pMan, 0 );
+    Ivy_ManStop( pTemp );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+*/
+    return pMan;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyRwr.c b/abc-build/src/aig/ivy/ivyRwr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyRwr.c
@@ -0,0 +1,618 @@
+/**CFile****************************************************************
+
+  FileName    [ivyRwt.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Rewriting based on precomputation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyRwt.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+#include "bool/deco/deco.h"
+#include "opt/rwt/rwt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums );
+static int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost );
+static Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, 
+    Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth );
+
+static int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax );
+static void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs incremental rewriting of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose )
+{
+    Rwt_Man_t * pManRwt;
+    Ivy_Obj_t * pNode;
+    int i, nNodes, nGain;
+    abctime clk, clkStart = Abc_Clock();
+    // start the rewriting manager
+    pManRwt = Rwt_ManStart( 0 );
+    p->pData = pManRwt;
+    if ( pManRwt == NULL )
+        return 0; 
+    // create fanouts
+    if ( fUpdateLevel && p->fFanout == 0 )
+        Ivy_ManStartFanout( p );
+    // compute the reverse levels if level update is requested
+    if ( fUpdateLevel )
+        Ivy_ManRequiredLevels( p );
+    // set the number of levels
+//    p->nLevelMax = Ivy_ManLevels( p );
+    // resynthesize each node once
+    nNodes = Ivy_ManObjIdMax(p);
+    Ivy_ManForEachNode( p, pNode, i )
+    {
+        // fix the fanin buffer problem
+        Ivy_NodeFixBufferFanins( p, pNode, 1 );
+        if ( Ivy_ObjIsBuf(pNode) )
+            continue;
+        // stop if all nodes have been tried once
+        if ( i > nNodes )
+            break;
+        // for each cut, try to resynthesize it
+        nGain = Ivy_NodeRewrite( p, pManRwt, pNode, fUpdateLevel, fUseZeroCost );
+        if ( nGain > 0 || (nGain == 0 && fUseZeroCost) )
+        {
+            Dec_Graph_t * pGraph = (Dec_Graph_t *)Rwt_ManReadDecs(pManRwt);
+            int fCompl           = Rwt_ManReadCompl(pManRwt);
+/*
+            {
+                Ivy_Obj_t * pObj;
+                int i;
+                printf( "USING: (" );
+                Vec_PtrForEachEntry( Ivy_Obj_t *, Rwt_ManReadLeaves(pManRwt), pObj, i )
+                    printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pObj)) );
+                printf( ")   Gain = %d.\n", nGain );
+            }
+            if ( nGain > 0 )
+            { // print stats on the MFFC
+                extern void Ivy_NodeMffcConeSuppPrint( Ivy_Obj_t * pNode );
+                printf( "Node %6d : Gain = %4d  ", pNode->Id, nGain );
+                Ivy_NodeMffcConeSuppPrint( pNode );
+            }
+*/
+            // complement the FF if needed
+clk = Abc_Clock();
+            if ( fCompl ) Dec_GraphComplement( pGraph );
+            Ivy_GraphUpdateNetwork( p, pNode, pGraph, fUpdateLevel, nGain );
+            if ( fCompl ) Dec_GraphComplement( pGraph );
+Rwt_ManAddTimeUpdate( pManRwt, Abc_Clock() - clk );
+        }
+    }
+Rwt_ManAddTimeTotal( pManRwt, Abc_Clock() - clkStart );
+    // print stats
+    if ( fVerbose )
+        Rwt_ManPrintStats( pManRwt );
+    // delete the managers
+    Rwt_ManStop( pManRwt );
+    p->pData = NULL;
+    // fix the levels
+    if ( fUpdateLevel )
+        Vec_IntFree( p->vRequired ), p->vRequired = NULL;
+    else
+        Ivy_ManResetLevels( p );
+    // check
+    if ( (i = Ivy_ManCleanup(p)) )
+        printf( "Cleanup after rewriting removed %d dangling nodes.\n", i );
+    if ( !Ivy_ManCheck(p) )
+        printf( "Ivy_ManRewritePre(): The check has failed.\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs rewriting for one node.]
+
+  Description [This procedure considers all the cuts computed for the node
+  and tries to rewrite each of them using the "forest" of different AIG
+  structures precomputed and stored in the RWR manager. 
+  Determines the best rewriting and computes the gain in the number of AIG
+  nodes in the final network. In the end, p->vFanins contains information 
+  about the best cut that can be used for rewriting, while p->pGraph gives 
+  the decomposition dag (represented using decomposition graph data structure).
+  Returns gain in the number of nodes or -1 if node cannot be rewritten.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost )
+{
+    int fVeryVerbose = 0;
+    Dec_Graph_t * pGraph;
+    Ivy_Store_t * pStore;
+    Ivy_Cut_t * pCut;
+    Ivy_Obj_t * pFanin;
+    unsigned uPhase;
+    unsigned uTruthBest = 0; // Suppress "might be used uninitialized"
+    unsigned uTruth;
+    char * pPerm;
+    int Required, nNodesSaved;
+    int nNodesSaveCur = -1; // Suppress "might be used uninitialized"
+    int i, c, GainCur, GainBest = -1;
+    abctime clk, clk2;
+
+    p->nNodesConsidered++;
+    // get the required times
+    Required = fUpdateLevel? Vec_IntEntry( pMan->vRequired, pNode->Id ) : 1000000;
+    // get the node's cuts
+clk = Abc_Clock();
+    pStore = Ivy_NodeFindCutsAll( pMan, pNode, 5 );
+p->timeCut += Abc_Clock() - clk;
+
+    // go through the cuts
+clk = Abc_Clock();
+    for ( c = 1; c < pStore->nCuts; c++ )
+    {
+        pCut = pStore->pCuts + c;
+        // consider only 4-input cuts
+        if ( pCut->nSize != 4 )
+            continue;
+        // skip the cuts with buffers
+        for ( i = 0; i < (int)pCut->nSize; i++ )
+            if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, pCut->pArray[i]) ) )
+                break;
+        if ( i != pCut->nSize )
+        {
+            p->nCutsBad++;
+            continue;
+        }
+        p->nCutsGood++;
+        // get the fanin permutation
+clk2 = Abc_Clock();
+        uTruth = 0xFFFF & Ivy_NodeGetTruth( pNode, pCut->pArray, pCut->nSize );  // truth table
+p->timeTruth += Abc_Clock() - clk2;
+        pPerm = p->pPerms4[ (int) p->pPerms[uTruth] ];
+        uPhase = p->pPhases[uTruth];
+        // collect fanins with the corresponding permutation/phase
+        Vec_PtrClear( p->vFaninsCur );
+        Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 );
+        for ( i = 0; i < (int)pCut->nSize; i++ )
+        {
+            pFanin = Ivy_ManObj( pMan, pCut->pArray[(int)pPerm[i]] );
+            assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) );
+            pFanin = Ivy_NotCond(pFanin, ((uPhase & (1<<i)) > 0) );
+            Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin );
+        }
+clk2 = Abc_Clock();
+/*
+        printf( "Considering: (" );
+        Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i )
+            printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pFanin)) );
+        printf( ")\n" );
+*/
+        // mark the fanin boundary 
+        Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i )
+            Ivy_ObjRefsInc( Ivy_Regular(pFanin) );
+        // label MFFC with current ID
+        Ivy_ManIncrementTravId( pMan );
+        nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode );
+        // unmark the fanin boundary
+        Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i )
+            Ivy_ObjRefsDec( Ivy_Regular(pFanin) );
+p->timeMffc += Abc_Clock() - clk2;
+
+        // evaluate the cut
+clk2 = Abc_Clock();
+        pGraph = Rwt_CutEvaluate( pMan, p, pNode, p->vFaninsCur, nNodesSaved, Required, &GainCur, uTruth );
+p->timeEval += Abc_Clock() - clk2;
+
+        // check if the cut is better than the current best one
+        if ( pGraph != NULL && GainBest < GainCur )
+        {
+            // save this form
+            nNodesSaveCur = nNodesSaved;
+            GainBest  = GainCur;
+            p->pGraph  = pGraph;
+            p->fCompl = ((uPhase & (1<<4)) > 0);
+            uTruthBest = uTruth;
+            // collect fanins in the
+            Vec_PtrClear( p->vFanins );
+            Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i )
+                Vec_PtrPush( p->vFanins, pFanin );
+        }
+    }
+p->timeRes += Abc_Clock() - clk;
+
+    if ( GainBest == -1 )
+        return -1;
+
+//    printf( "%d", nNodesSaveCur - GainBest );
+/*
+    if ( GainBest > 0 )
+    {
+        if ( Rwt_CutIsintean( pNode, p->vFanins ) )
+            printf( "b" );
+        else
+        {
+            printf( "Node %d : ", pNode->Id );
+            Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFanins, pFanin, i )
+                printf( "%d ", Ivy_Regular(pFanin)->Id );
+            printf( "a" );
+        }
+    }
+*/
+/*
+    if ( GainBest > 0 )
+        if ( p->fCompl )
+            printf( "c" );
+        else
+            printf( "." );
+*/
+
+    // copy the leaves
+    Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFanins, pFanin, i )
+        Dec_GraphNode((Dec_Graph_t *)p->pGraph, i)->pFunc = pFanin;
+
+    p->nScores[p->pMap[uTruthBest]]++;
+    p->nNodesGained += GainBest;
+    if ( fUseZeroCost || GainBest > 0 )
+        p->nNodesRewritten++;
+
+    // report the progress
+    if ( fVeryVerbose && GainBest > 0 )
+    {
+        printf( "Node %6d :   ", Ivy_ObjId(pNode) );
+        printf( "Fanins = %d. ", p->vFanins->nSize );
+        printf( "Save = %d.  ", nNodesSaveCur );
+        printf( "Add = %d.  ",  nNodesSaveCur-GainBest );
+        printf( "GAIN = %d.  ", GainBest );
+        printf( "Cone = %d.  ", p->pGraph? Dec_GraphNodeNum((Dec_Graph_t *)p->pGraph) : 0 );
+        printf( "Class = %d.  ", p->pMap[uTruthBest] );
+        printf( "\n" );
+    }
+    return GainBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Ivy_NodeGetTruth_rec( Ivy_Obj_t * pObj, int * pNums, int nNums )
+{
+    static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+    unsigned uTruth0, uTruth1;
+    int i;
+    for ( i = 0; i < nNums; i++ )
+        if ( pObj->Id == pNums[i] )
+            return uMasks[i];
+    assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) );
+    uTruth0 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin0(pObj), pNums, nNums );
+    if ( Ivy_ObjFaninC0(pObj) )
+        uTruth0 = ~uTruth0;
+    if ( Ivy_ObjIsBuf(pObj) )
+        return uTruth0;
+    uTruth1 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin1(pObj), pNums, nNums );
+    if ( Ivy_ObjFaninC1(pObj) )
+        uTruth1 = ~uTruth1;
+    return uTruth0 & uTruth1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums )
+{
+    assert( nNums < 6 );
+    return Ivy_NodeGetTruth_rec( pObj, pNums, nNums );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth )
+{
+    Vec_Ptr_t * vSubgraphs;
+    Dec_Graph_t * pGraphBest = NULL; // Suppress "might be used uninitialized"
+    Dec_Graph_t * pGraphCur;
+    Rwt_Node_t * pNode, * pFanin;
+    int nNodesAdded, GainBest, i, k;
+    // find the matching class of subgraphs
+    vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] );
+    p->nSubgraphs += vSubgraphs->nSize;
+    // determine the best subgraph
+    GainBest = -1;
+    Vec_PtrForEachEntry( Rwt_Node_t *, vSubgraphs, pNode, i )
+    {
+        // get the current graph
+        pGraphCur = (Dec_Graph_t *)pNode->pNext;
+        // copy the leaves
+        Vec_PtrForEachEntry( Rwt_Node_t *, vFaninsCur, pFanin, k )
+            Dec_GraphNode(pGraphCur, k)->pFunc = pFanin;
+        // detect how many unlabeled nodes will be reused
+        nNodesAdded = Ivy_GraphToNetworkCount( pMan, pRoot, pGraphCur, nNodesSaved, LevelMax );
+        if ( nNodesAdded == -1 )
+            continue;
+        assert( nNodesSaved >= nNodesAdded );
+        // count the gain at this node
+        if ( GainBest < nNodesSaved - nNodesAdded )
+        {
+            GainBest   = nNodesSaved - nNodesAdded;
+            pGraphBest = pGraphCur;
+        }
+    }
+    if ( GainBest == -1 )
+        return NULL;
+    *pGainBest = GainBest;
+    return pGraphBest;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of new nodes added when using this graph.]
+
+  Description [AIG nodes for the fanins should be assigned to pNode->pFunc 
+  of the leaves of the graph before calling this procedure. 
+  Returns -1 if the number of nodes and levels exceeded the given limit or 
+  the number of levels exceeded the maximum allowed level.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax )
+{
+    Dec_Node_t * pNode, * pNode0, * pNode1;
+    Ivy_Obj_t * pAnd, * pAnd0, * pAnd1;
+    int i, Counter, LevelNew, LevelOld;
+    // check for constant function or a literal
+    if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) )
+        return 0;
+    // set the levels of the leaves
+    Dec_GraphForEachLeaf( pGraph, pNode, i )
+        pNode->Level = Ivy_Regular((Ivy_Obj_t *)pNode->pFunc)->Level;
+    // compute the AIG size after adding the internal nodes
+    Counter = 0;
+    Dec_GraphForEachNode( pGraph, pNode, i )
+    {
+        // get the children of this node
+        pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node );
+        pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node );
+        // get the AIG nodes corresponding to the children 
+        pAnd0 = (Ivy_Obj_t *)pNode0->pFunc; 
+        pAnd1 = (Ivy_Obj_t *)pNode1->pFunc; 
+        if ( pAnd0 && pAnd1 )
+        {
+            // if they are both present, find the resulting node
+            pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl );
+            pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl );
+            pAnd  = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) );
+            // return -1 if the node is the same as the original root
+            if ( Ivy_Regular(pAnd) == pRoot )
+                return -1;
+        }
+        else
+            pAnd = NULL;
+        // count the number of added nodes
+        if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) )
+        {
+            if ( ++Counter > NodeMax )
+                return -1;
+        }
+        // count the number of new levels
+        LevelNew = 1 + RWT_MAX( pNode0->Level, pNode1->Level );
+        if ( pAnd )
+        {
+            if ( Ivy_Regular(pAnd) == p->pConst1 )
+                LevelNew = 0;
+            else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd0) )
+                LevelNew = (int)Ivy_Regular(pAnd0)->Level;
+            else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd1) )
+                LevelNew = (int)Ivy_Regular(pAnd1)->Level;
+            LevelOld = (int)Ivy_Regular(pAnd)->Level;
+//            assert( LevelNew == LevelOld );
+        }
+        if ( LevelNew > LevelMax )
+            return -1;
+        pNode->pFunc = pAnd;
+        pNode->Level = LevelNew;
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the decomposition graph into the AIG.]
+
+  Description [AIG nodes for the fanins should be assigned to pNode->pFunc
+  of the leaves of the graph before calling this procedure.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_GraphToNetwork( Ivy_Man_t * p, Dec_Graph_t * pGraph )
+{
+    Ivy_Obj_t * pAnd0, * pAnd1;
+    Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized"
+    int i;
+    // check for constant function
+    if ( Dec_GraphIsConst(pGraph) )
+        return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) );
+    // check for a literal
+    if ( Dec_GraphIsVar(pGraph) )
+        return Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
+    // build the AIG nodes corresponding to the AND gates of the graph
+    Dec_GraphForEachNode( pGraph, pNode, i )
+    {
+        pAnd0 = Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); 
+        pAnd1 = Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); 
+        pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 );
+    }
+    // complement the result if necessary
+    return Ivy_NotCond( (Ivy_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces MFFC of the node by the new factored form.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain )
+{
+    Ivy_Obj_t * pRootNew;
+    int nNodesNew, nNodesOld, Required;
+    Required = fUpdateLevel? Vec_IntEntry( p->vRequired, pRoot->Id ) : 1000000;
+    nNodesOld = Ivy_ManNodeNum(p);
+    // create the new structure of nodes
+    pRootNew = Ivy_GraphToNetwork( p, pGraph );
+    assert( (int)Ivy_Regular(pRootNew)->Level <= Required );
+//    if ( Ivy_Regular(pRootNew)->Level == Required )
+//        printf( "Difference %d.\n", Ivy_Regular(pRootNew)->Level - Required );
+    // remove the old nodes
+//    Ivy_AigReplace( pMan->pManFunc, pRoot, pRootNew, fUpdateLevel );
+/*
+    if ( Ivy_IsComplement(pRootNew) )
+        printf( "c" );
+    else
+        printf( "d" );
+    if ( Ivy_ObjRefs(Ivy_Regular(pRootNew)) > 0 )
+        printf( "%d", Ivy_ObjRefs(Ivy_Regular(pRootNew)) );
+    printf( " " );
+*/
+    Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 1 );
+    // compare the gains
+    nNodesNew = Ivy_ManNodeNum(p);
+    assert( nGain <= nNodesOld - nNodesNew );
+    // propagate the buffer
+    Ivy_ManPropagateBuffers( p, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces MFFC of the node by the new factored form.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_GraphUpdateNetwork3( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain )
+{
+    Ivy_Obj_t * pRootNew, * pFanin;
+    int nNodesNew, nNodesOld, i, nRefsOld;
+    nNodesOld = Ivy_ManNodeNum(p);
+
+//printf( "Before = %d. ", Ivy_ManNodeNum(p) );
+    // mark the cut
+    Vec_PtrForEachEntry( Ivy_Obj_t *, ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i )
+        Ivy_ObjRefsInc( Ivy_Regular(pFanin) );
+    // deref the old cone
+    nRefsOld = pRoot->nRefs;  
+    pRoot->nRefs = 0;
+    Ivy_ObjDelete_rec( p, pRoot, 0 );
+    pRoot->nRefs = nRefsOld;
+    // unmark the cut
+    Vec_PtrForEachEntry( Ivy_Obj_t *, ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i )
+        Ivy_ObjRefsDec( Ivy_Regular(pFanin) );
+//printf( "Deref = %d. ", Ivy_ManNodeNum(p) );
+ 
+    // create the new structure of nodes
+    pRootNew = Ivy_GraphToNetwork( p, pGraph );
+//printf( "Create = %d. ", Ivy_ManNodeNum(p) );
+    // remove the old nodes
+//    Ivy_AigReplace( pMan->pManFunc, pRoot, pRootNew, fUpdateLevel );
+/*
+    if ( Ivy_IsComplement(pRootNew) )
+        printf( "c" );
+    else
+        printf( "d" );
+    if ( Ivy_ObjRefs(Ivy_Regular(pRootNew)) > 0 )
+        printf( "%d", Ivy_ObjRefs(Ivy_Regular(pRootNew)) );
+    printf( " " );
+*/
+    Ivy_ObjReplace( p, pRoot, pRootNew, 0, 0, 1 );
+//printf( "Replace = %d. ", Ivy_ManNodeNum(p) );
+
+    // delete remaining dangling nodes
+    Vec_PtrForEachEntry( Ivy_Obj_t *, ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i )
+    {
+        pFanin = Ivy_Regular(pFanin);
+        if ( !Ivy_ObjIsNone(pFanin) && Ivy_ObjRefs(pFanin) == 0 )
+            Ivy_ObjDelete_rec( p, pFanin, 1 );
+    }
+//printf( "Deref = %d. ", Ivy_ManNodeNum(p) );
+//printf( "\n" );
+
+    // compare the gains
+    nNodesNew = Ivy_ManNodeNum(p);
+    assert( nGain <= nNodesOld - nNodesNew );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyRwrAlg.c b/abc-build/src/aig/ivy/ivyRwrAlg.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyRwrAlg.c
@@ -0,0 +1,413 @@
+/**CFile****************************************************************
+
+  FileName    [ivyRwrAlg.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Algebraic AIG rewriting.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyRwrAlg.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone );
+static Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost );
+static int Ivy_NodeCountMffc( Ivy_Obj_t * pNode );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Algebraic AIG rewriting.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost )
+{
+    Vec_Int_t * vRequired;
+    Vec_Ptr_t * vFront, * vLeaves, * vCone, * vSol;
+    Ivy_Obj_t * pObj, * pResult;
+    int i, RetValue, LevelR, nNodesOld;
+    int CountUsed, CountUndo;
+    vRequired = fUpdateLevel? Ivy_ManRequiredLevels( p ) : NULL;
+    vFront    = Vec_PtrAlloc( 100 );
+    vLeaves   = Vec_PtrAlloc( 100 );
+    vCone     = Vec_PtrAlloc( 100 );
+    vSol      = Vec_PtrAlloc( 100 );
+    // go through the nodes in the topological order
+    CountUsed = CountUndo = 0;
+    nNodesOld = Ivy_ManObjIdNext(p);
+    Ivy_ManForEachObj( p, pObj, i )
+    {
+        assert( !Ivy_ObjIsBuf(pObj) );
+        if ( i >= nNodesOld )
+            break;
+        // skip no-nodes and MUX roots
+        if ( !Ivy_ObjIsNode(pObj) || Ivy_ObjIsExor(pObj) || Ivy_ObjIsMuxType(pObj) )
+            continue;
+//        if ( pObj->Id > 297 ) // 296 --- 297 
+//            break;
+        if ( pObj->Id == 297 )
+        {
+            int x = 0;
+        }
+        // get the largest algebraic cut
+        RetValue = Ivy_ManFindAlgCut( pObj, vFront, vLeaves, vCone );
+        // the case of a trivial tree cut
+        if ( RetValue == 1 )
+            continue;
+        // the case of constant 0 cone
+        if ( RetValue == -1 )
+        {
+            Ivy_ObjReplace( pObj, Ivy_ManConst0(p), 1, 0, 1 ); 
+            continue;
+        }
+        assert( Vec_PtrSize(vLeaves) > 2 );
+        // get the required level for this node
+        LevelR = vRequired? Vec_IntEntry(vRequired, pObj->Id) : 1000000;
+        // create a new cone
+        pResult = Ivy_NodeRewriteAlg( pObj, vFront, vLeaves, vCone, vSol, LevelR, fUseZeroCost );
+        if ( pResult == NULL || pResult == pObj )
+            continue;
+        assert( Vec_PtrSize(vSol) == 1 || !Ivy_IsComplement(pResult) );
+        if ( Ivy_ObjLevel(Ivy_Regular(pResult)) > LevelR && Ivy_ObjRefs(Ivy_Regular(pResult)) == 0 )
+            Ivy_ObjDelete_rec(Ivy_Regular(pResult), 1), CountUndo++;
+        else
+            Ivy_ObjReplace( pObj, pResult, 1, 0, 1 ), CountUsed++; 
+    }
+    printf( "Used = %d. Undo = %d.\n", CountUsed, CountUndo );
+    Vec_PtrFree( vFront );
+    Vec_PtrFree( vCone );
+    Vec_PtrFree( vSol );
+    if ( vRequired ) Vec_IntFree( vRequired );
+    if ( i = Ivy_ManCleanup(p) )
+        printf( "Cleanup after rewriting removed %d dangling nodes.\n", i );
+    if ( !Ivy_ManCheck(p) )
+        printf( "Ivy_ManRewriteAlg(): The check has failed.\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Analizes one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost )
+{
+    int fVerbose = 0;
+    Ivy_Obj_t * pTemp;
+    int k, Counter, nMffc, RetValue;
+
+    if ( fVerbose )
+    {
+        if ( Ivy_ObjIsExor(pObj) )
+            printf( "x " );
+        else
+            printf( "  " );
+    }
+
+/*       
+    printf( "%d ", Vec_PtrSize(vFront) );
+    printf( "( " );
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, k )
+        printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) );
+    printf( ")\n" );
+*/
+    // collect nodes in the cone
+    if ( Ivy_ObjIsExor(pObj) )
+        Ivy_ManCollectCone( pObj, vFront, vCone );
+    else
+        Ivy_ManCollectCone( pObj, vLeaves, vCone );
+
+    // deref nodes in the cone
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pTemp, k )
+    {
+        Ivy_ObjRefsDec( Ivy_ObjFanin0(pTemp) );
+        Ivy_ObjRefsDec( Ivy_ObjFanin1(pTemp) );
+        pTemp->fMarkB = 1;
+    }
+
+    // count the MFFC size
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, k )
+        Ivy_Regular(pTemp)->fMarkA = 1;
+    nMffc = Ivy_NodeCountMffc( pObj );
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, k )
+        Ivy_Regular(pTemp)->fMarkA = 0;
+
+    if ( fVerbose )
+    {
+    Counter = 0;
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pTemp, k )
+        Counter += (Ivy_ObjRefs(pTemp) > 0);
+    printf( "%5d : Leaves = %2d. Cone = %2d. ConeRef = %2d.   Mffc = %d.   Lev = %d.  LevR = %d.\n", 
+        pObj->Id, Vec_PtrSize(vFront), Vec_PtrSize(vCone), Counter-1, nMffc, Ivy_ObjLevel(pObj), LevelR );
+    }
+/*
+    printf( "Leaves:" );
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vLeaves, pTemp, k )
+        printf( " %d%s", Ivy_Regular(pTemp)->Id, Ivy_IsComplement(pTemp)? "\'" : "" );
+    printf( "\n" );
+    printf( "Cone:\n" );
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pTemp, k )
+        printf( " %5d = %d%s %d%s\n", pTemp->Id,
+            Ivy_ObjFaninId0(pTemp), Ivy_ObjFaninC0(pTemp)? "\'" : "",
+            Ivy_ObjFaninId1(pTemp), Ivy_ObjFaninC1(pTemp)? "\'" : "" );
+*/
+
+    RetValue = Ivy_MultiPlus( vLeaves, vCone, Ivy_ObjType(pObj), nMffc + fUseZeroCost, vSols );
+
+    // ref nodes in the cone
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pTemp, k )
+    {
+        Ivy_ObjRefsInc( Ivy_ObjFanin0(pTemp) );
+        Ivy_ObjRefsInc( Ivy_ObjFanin1(pTemp) );
+        pTemp->fMarkA = 0;
+        pTemp->fMarkB = 0;
+    }
+
+    if ( !RetValue )
+        return NULL;
+
+    if ( Vec_PtrSize( vSols ) == 1 )
+        return Vec_PtrEntry( vSols, 0 );
+    return Ivy_NodeBalanceBuildSuper( vSols, Ivy_ObjType(pObj), 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison for node pointers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_NodeCountMffc_rec( Ivy_Obj_t * pNode )
+{
+    if ( Ivy_ObjRefs(pNode) > 0 || Ivy_ObjIsCi(pNode) || pNode->fMarkA )
+        return 0;
+    assert( pNode->fMarkB );
+    pNode->fMarkA = 1;
+//    printf( "%d ", pNode->Id );
+    if ( Ivy_ObjIsBuf(pNode) )
+        return Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) );
+    return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison for node pointers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_NodeCountMffc( Ivy_Obj_t * pNode )
+{
+    assert( pNode->fMarkB );
+    return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison for node pointers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManFindAlgCutCompare( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 )
+{
+    if ( *pp1 < *pp2 )
+        return -1;
+    if ( *pp1 > *pp2 )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computing one algebraic cut.]
+
+  Description [Returns 1 if the tree-leaves of this node where traversed 
+  and found to have no external references (and have not been collected). 
+  Returns 0 if the tree-leaves have external references and are collected.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManFindAlgCut_rec( Ivy_Obj_t * pObj, Ivy_Type_t Type, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone )
+{
+    int RetValue0, RetValue1;
+    Ivy_Obj_t * pObjR = Ivy_Regular(pObj);
+    assert( !Ivy_ObjIsBuf(pObjR) );
+    assert( Type != IVY_EXOR || !Ivy_IsComplement(pObj) );
+
+    // make sure the node is not visited twice in different polarities
+    if ( Ivy_IsComplement(pObj) )
+    { // if complemented, mark B
+        if ( pObjR->fMarkA )
+            return -1;
+        pObjR->fMarkB = 1;
+    }
+    else
+    { // if non-complicated, mark A
+        if ( pObjR->fMarkB )
+            return -1;
+        pObjR->fMarkA = 1;
+    }
+    Vec_PtrPush( vCone, pObjR );
+
+    // if the node is the end of the tree, return
+    if ( Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Type )
+    {
+        if ( Ivy_ObjRefs(pObjR) == 1 )
+            return 1;
+        assert( Ivy_ObjRefs(pObjR) > 1 );
+        Vec_PtrPush( vFront, pObj );
+        return 0;
+    }
+
+    // branch on the node
+    assert( !Ivy_IsComplement(pObj) );
+    assert( Ivy_ObjIsNode(pObj) );
+    // what if buffer has more than one fanout???
+    RetValue0 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild0(pObj) ), Type, vFront, vCone );
+    RetValue1 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild1(pObj) ), Type, vFront, vCone );
+    if ( RetValue0 == -1 || RetValue1 == -1 )
+        return -1;
+
+    // the case when both have no external references
+    if ( RetValue0 && RetValue1 )
+    {
+        if ( Ivy_ObjRefs(pObj) == 1 )
+            return 1;
+        assert( Ivy_ObjRefs(pObj) > 1 );
+        Vec_PtrPush( vFront, pObj );
+        return 0;
+    }
+    // the case when one of them has external references
+    if ( RetValue0 )
+        Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild0(pObj) ) );
+    if ( RetValue1 )
+        Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild1(pObj) ) );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computing one algebraic cut.]
+
+  Description [Algebraic cut stops when we hit (a) CI, (b) complemented edge,
+  (c) boundary of different gates. Returns 1 if this is a pure tree.
+  Returns -1 if the contant 0 is detected. Return 0 if the array can be used.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone )
+{
+    Ivy_Obj_t * pObj, * pPrev;
+    int RetValue, i;
+    assert( !Ivy_IsComplement(pRoot) );
+    assert( Ivy_ObjIsNode(pRoot) );
+    // clear the frontier and collect the nodes
+    Vec_PtrClear( vCone );
+    Vec_PtrClear( vFront );
+    Vec_PtrClear( vLeaves );
+    RetValue = Ivy_ManFindAlgCut_rec( pRoot, Ivy_ObjType(pRoot), vFront, vCone );
+    // clean the marks
+    Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pObj, i )
+        pObj->fMarkA = pObj->fMarkB = 0;
+    // quit if the same node is found in both polarities
+    if ( RetValue == -1 )
+        return -1;
+    // return if the node is the root of a tree
+    if ( RetValue == 1 )
+        return 1;
+    // return if the cut is composed of two nodes
+    if ( Vec_PtrSize(vFront) <= 2 )
+        return 1;
+    // sort the entries in increasing order
+    Vec_PtrSort( vFront, (int (*)(void))Ivy_ManFindAlgCutCompare );
+    // remove duplicates from vFront and save the nodes in vLeaves
+    pPrev = Vec_PtrEntry(vFront, 0);
+    Vec_PtrPush( vLeaves, pPrev );
+    Vec_PtrForEachEntryStart( Ivy_Obj_t *, vFront, pObj, i, 1 )
+    {
+        // compare current entry and the previous entry
+        if ( pObj == pPrev )
+        {
+            if ( Ivy_ObjIsExor(pRoot) ) // A <+> A = 0
+            {
+                // vLeaves are no longer structural support of pRoot!!!
+                Vec_PtrPop(vLeaves);  
+                pPrev = Vec_PtrSize(vLeaves) == 0 ? NULL : Vec_PtrEntryLast(vLeaves);
+            }
+            continue;
+        }
+        if ( pObj == Ivy_Not(pPrev) )
+        {
+            assert( Ivy_ObjIsAnd(pRoot) );
+            return -1;
+        }
+        pPrev = pObj;
+        Vec_PtrPush( vLeaves, pObj );
+    }
+    if ( Vec_PtrSize(vLeaves) == 0 )
+        return -1;
+    if ( Vec_PtrSize(vLeaves) <= 2 )
+        return 1;
+    return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivySeq.c b/abc-build/src/aig/ivy/ivySeq.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivySeq.c
@@ -0,0 +1,1142 @@
+/**CFile****************************************************************
+
+  FileName    [ivySeq.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+ 
+  Revision    [$Id: ivySeq.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+#include "bool/deco/deco.h"
+#include "opt/rwt/rwt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost );
+static void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm );
+static unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums );
+static Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth );
+static int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax );
+static Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph );
+static void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain );
+static Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves );
+
+static inline int Ivy_CutHashValue( int NodeId )  { return 1 << (NodeId % 31); }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+//int nMoves;
+//int nMovesS;
+//int nClauses;
+//int timeInv;
+
+/**Function*************************************************************
+
+  Synopsis    [Performs incremental rewriting of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose )
+{ 
+    Rwt_Man_t * pManRwt;
+    Ivy_Obj_t * pNode;
+    int i, nNodes, nGain;
+    abctime clk, clkStart = Abc_Clock();
+
+    // set the DC latch values
+    Ivy_ManForEachLatch( p, pNode, i )
+        pNode->Init = IVY_INIT_DC;
+    // start the rewriting manager
+    pManRwt = Rwt_ManStart( 0 );
+    p->pData = pManRwt;
+    if ( pManRwt == NULL )
+        return 0; 
+    // create fanouts
+    if ( p->fFanout == 0 )
+        Ivy_ManStartFanout( p );
+    // resynthesize each node once
+    nNodes = Ivy_ManObjIdMax(p);
+    Ivy_ManForEachNode( p, pNode, i )
+    {
+        assert( !Ivy_ObjIsBuf(pNode) );
+        assert( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) );
+        assert( !Ivy_ObjIsBuf(Ivy_ObjFanin1(pNode)) );
+        // fix the fanin buffer problem
+//        Ivy_NodeFixBufferFanins( p, pNode );
+//        if ( Ivy_ObjIsBuf(pNode) )
+//            continue;
+        // stop if all nodes have been tried once
+        if ( i > nNodes ) 
+            break;
+        // for each cut, try to resynthesize it
+        nGain = Ivy_NodeRewriteSeq( p, pManRwt, pNode, fUseZeroCost );
+        if ( nGain > 0 || (nGain == 0 && fUseZeroCost) )
+        {
+            Dec_Graph_t * pGraph = (Dec_Graph_t *)Rwt_ManReadDecs(pManRwt);
+            int fCompl           = Rwt_ManReadCompl(pManRwt);
+            // complement the FF if needed
+clk = Abc_Clock();
+            if ( fCompl ) Dec_GraphComplement( pGraph );
+            Ivy_GraphUpdateNetworkSeq( p, pNode, pGraph, nGain );
+            if ( fCompl ) Dec_GraphComplement( pGraph );
+Rwt_ManAddTimeUpdate( pManRwt, Abc_Clock() - clk );
+        }
+    }
+Rwt_ManAddTimeTotal( pManRwt, Abc_Clock() - clkStart );
+    // print stats
+    if ( fVerbose )
+        Rwt_ManPrintStats( pManRwt );
+    // delete the managers
+    Rwt_ManStop( pManRwt );
+    p->pData = NULL;
+    // fix the levels
+    Ivy_ManResetLevels( p );
+//    if ( Ivy_ManCheckFanoutNums(p) )
+//        printf( "Ivy_ManRewritePre(): The check has failed.\n" );
+    // check
+    if ( !Ivy_ManCheck(p) )
+        printf( "Ivy_ManRewritePre(): The check has failed.\n" );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs rewriting for one node.]
+
+  Description [This procedure considers all the cuts computed for the node
+  and tries to rewrite each of them using the "forest" of different AIG
+  structures precomputed and stored in the RWR manager. 
+  Determines the best rewriting and computes the gain in the number of AIG
+  nodes in the final network. In the end, p->vFanins contains information 
+  about the best cut that can be used for rewriting, while p->pGraph gives 
+  the decomposition dag (represented using decomposition graph data structure).
+  Returns gain in the number of nodes or -1 if node cannot be rewritten.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost )
+{
+    int fVeryVerbose = 0;
+    Dec_Graph_t * pGraph;
+    Ivy_Store_t * pStore;
+    Ivy_Cut_t * pCut;
+    Ivy_Obj_t * pFanin;//, * pFanout;
+    Vec_Ptr_t * vFanout;
+    unsigned uPhase;
+    unsigned uTruthBest = 0; // Suppress "might be used uninitialized"
+    unsigned uTruth;//, nNewClauses;
+    char * pPerm;
+    int nNodesSaved;
+    int nNodesSaveCur = -1; // Suppress "might be used uninitialized"
+    int i, c, GainCur, GainBest = -1;
+    abctime clk, clk2;//, clk3;
+
+    p->nNodesConsidered++;
+    // get the node's cuts
+clk = Abc_Clock();
+    pStore = Ivy_CutComputeForNode( pMan, pNode, 5 );
+p->timeCut += Abc_Clock() - clk;
+
+    // go through the cuts
+clk = Abc_Clock();
+    vFanout = Vec_PtrAlloc( 100 );
+    for ( c = 1; c < pStore->nCuts; c++ )
+    {
+        pCut = pStore->pCuts + c;
+        // consider only 4-input cuts
+        if ( pCut->nSize != 4 )
+            continue;
+        // skip the cuts with buffers
+        for ( i = 0; i < (int)pCut->nSize; i++ )
+            if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, Ivy_LeafId(pCut->pArray[i])) ) )
+                break;
+        if ( i != pCut->nSize )
+        {
+            p->nCutsBad++;
+            continue;
+        }
+        p->nCutsGood++;
+        // get the fanin permutation
+clk2 = Abc_Clock();
+        uTruth = 0xFFFF & Ivy_CutGetTruth( pMan, pNode, pCut->pArray, pCut->nSize );  // truth table
+p->timeTruth += Abc_Clock() - clk2;
+        pPerm = p->pPerms4[ (int)p->pPerms[uTruth] ];
+        uPhase = p->pPhases[uTruth];
+        // collect fanins with the corresponding permutation/phase
+        Vec_PtrClear( p->vFaninsCur );
+        Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 );
+        for ( i = 0; i < (int)pCut->nSize; i++ )
+        {
+            pFanin = Ivy_ManObj( pMan, Ivy_LeafId( pCut->pArray[(int)pPerm[i]] ) );
+            assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) || Ivy_ObjIsConst1(pFanin) );
+            pFanin = Ivy_NotCond(pFanin, ((uPhase & (1<<i)) > 0) );
+            Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin );
+        }
+clk2 = Abc_Clock();
+        // mark the fanin boundary 
+        Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i )
+            Ivy_ObjRefsInc( Ivy_Regular(pFanin) );
+        // label MFFC with current ID
+        Ivy_ManIncrementTravId( pMan );
+        nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode );
+        // label fanouts with the current ID
+//        Ivy_ObjForEachFanout( pMan, pNode, vFanout, pFanout, i )
+//            Ivy_ObjSetTravIdCurrent( pMan, pFanout );
+        // unmark the fanin boundary
+        Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i )
+            Ivy_ObjRefsDec( Ivy_Regular(pFanin) );
+p->timeMffc += Abc_Clock() - clk2;
+
+        // evaluate the cut
+clk2 = Abc_Clock();
+        pGraph = Rwt_CutEvaluateSeq( pMan, p, pNode, pCut, pPerm, p->vFaninsCur, nNodesSaved, &GainCur, uTruth );
+p->timeEval += Abc_Clock() - clk2;
+
+
+        // check if the cut is better than the current best one
+        if ( pGraph != NULL && GainBest < GainCur )
+        {
+            // save this form
+            nNodesSaveCur = nNodesSaved;
+            GainBest   = GainCur;
+            p->pGraph  = pGraph;
+            p->pCut    = pCut;
+            p->pPerm   = pPerm;
+            p->fCompl  = ((uPhase & (1<<4)) > 0);
+            uTruthBest = uTruth;
+            // collect fanins in the
+            Vec_PtrClear( p->vFanins );
+            Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i )
+                Vec_PtrPush( p->vFanins, pFanin );
+        }
+    }
+    Vec_PtrFree( vFanout );
+p->timeRes += Abc_Clock() - clk;
+
+    if ( GainBest == -1 )
+        return -1;
+/*
+    {
+    Ivy_Cut_t * pCut = p->pCut;
+    printf( "Node %5d. Using cut : {", Ivy_ObjId(pNode) );
+    for ( i = 0; i < pCut->nSize; i++ )
+        printf( " %d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) );
+    printf( " }\n" );
+    }
+*/
+
+//clk3 = Abc_Clock();
+//nNewClauses = Ivy_CutTruthPrint( pMan, p->pCut, uTruth );
+//timeInv += Abc_Clock() - clk;
+
+//    nClauses += nNewClauses;
+//    nMoves++;
+//    if ( nNewClauses > 0 )
+//        nMovesS++;
+
+    // copy the leaves
+    Ivy_GraphPrepare( (Dec_Graph_t *)p->pGraph, (Ivy_Cut_t *)p->pCut, p->vFanins, p->pPerm );
+
+    p->nScores[p->pMap[uTruthBest]]++;
+    p->nNodesGained += GainBest;
+    if ( fUseZeroCost || GainBest > 0 )
+        p->nNodesRewritten++;
+
+/*
+    if ( GainBest > 0 )
+    {
+        Ivy_Cut_t * pCut = p->pCut;
+        printf( "Node %5d. Using cut : {", Ivy_ObjId(pNode) );
+        for ( i = 0; i < pCut->nSize; i++ )
+            printf( " %5d(%2d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) );
+        printf( " }\n" );
+    }
+*/
+
+    // report the progress
+    if ( fVeryVerbose && GainBest > 0 )
+    {
+        printf( "Node %6d :   ", Ivy_ObjId(pNode) );
+        printf( "Fanins = %d. ", p->vFanins->nSize );
+        printf( "Save = %d.  ", nNodesSaveCur );
+        printf( "Add = %d.  ",  nNodesSaveCur-GainBest );
+        printf( "GAIN = %d.  ", GainBest );
+        printf( "Cone = %d.  ", p->pGraph? Dec_GraphNodeNum((Dec_Graph_t *)p->pGraph) : 0 );
+        printf( "Class = %d.  ", p->pMap[uTruthBest] );
+        printf( "\n" );
+    }
+    return GainBest;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth )
+{
+    Vec_Ptr_t * vSubgraphs;
+    Dec_Graph_t * pGraphBest = NULL; // Suppress "might be used uninitialized"
+    Dec_Graph_t * pGraphCur;
+    Rwt_Node_t * pNode;
+    int nNodesAdded, GainBest, i;
+    // find the matching class of subgraphs
+    vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] );
+    p->nSubgraphs += vSubgraphs->nSize;
+    // determine the best subgraph
+    GainBest = -1;
+    Vec_PtrForEachEntry( Rwt_Node_t *, vSubgraphs, pNode, i )
+    {
+        // get the current graph
+        pGraphCur = (Dec_Graph_t *)pNode->pNext;
+
+//        if ( pRoot->Id == 8648 )
+//        Dec_GraphPrint( stdout, pGraphCur, NULL, NULL );
+        // copy the leaves
+//        Vec_PtrForEachEntry( Ivy_Obj_t *, vFaninsCur, pFanin, k )
+//            Dec_GraphNode(pGraphCur, k)->pFunc = pFanin;
+        Ivy_GraphPrepare( pGraphCur, pCut, vFaninsCur, pPerm );
+
+        // detect how many unlabeled nodes will be reused
+        nNodesAdded = Ivy_GraphToNetworkSeqCountSeq( pMan, pRoot, pGraphCur, nNodesSaved );
+        if ( nNodesAdded == -1 )
+            continue;
+        assert( nNodesSaved >= nNodesAdded );
+        // count the gain at this node
+        if ( GainBest < nNodesSaved - nNodesAdded )
+        {
+            GainBest   = nNodesSaved - nNodesAdded;
+            pGraphBest = pGraphCur;
+        }
+    }
+    if ( GainBest == -1 )
+        return NULL;
+    *pGainBest = GainBest;
+    return pGraphBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm )
+{
+    Dec_Node_t * pNode, * pNode0, * pNode1;
+    int i;
+    assert( Dec_GraphLeaveNum(pGraph) == pCut->nSize );
+    assert( Vec_PtrSize(vFanins) == pCut->nSize );
+    // label the leaves with latch numbers
+    Dec_GraphForEachLeaf( pGraph, pNode, i )
+    {
+        pNode->pFunc = Vec_PtrEntry( vFanins, i );
+        pNode->nLat2 = Ivy_LeafLat( pCut->pArray[(int)pPerm[i]] );
+    }
+    // propagate latches through the nodes
+    Dec_GraphForEachNode( pGraph, pNode, i )
+    {
+        // get the children of this node
+        pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node );
+        pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node );
+        // distribute the latches
+        pNode->nLat2 = IVY_MIN( pNode0->nLat2, pNode1->nLat2 );
+        pNode->nLat0 = pNode0->nLat2 - pNode->nLat2;
+        pNode->nLat1 = pNode1->nLat2 - pNode->nLat2;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of new nodes added when using this graph.]
+
+  Description [AIG nodes for the fanins should be assigned to pNode->pFunc 
+  of the leaves of the graph before calling this procedure. 
+  Returns -1 if the number of nodes and levels exceeded the given limit or 
+  the number of levels exceeded the maximum allowed level.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax )
+{
+    Dec_Node_t * pNode, * pNode0, * pNode1;
+    Ivy_Obj_t * pAnd, * pAnd0, * pAnd1;
+    int i, k, Counter, fCompl;
+    // check for constant function or a literal
+    if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) )
+        return 0;
+    // compute the AIG size after adding the internal nodes
+    Counter = 0;
+    Dec_GraphForEachNode( pGraph, pNode, i )
+    {
+        // get the children of this node
+        pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node );
+        pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node );
+        // get the AIG nodes corresponding to the children 
+        pAnd0 = (Ivy_Obj_t *)pNode0->pFunc; 
+        pAnd1 = (Ivy_Obj_t *)pNode1->pFunc; 
+        // skip the latches
+        for ( k = 0; pAnd0 && k < (int)pNode->nLat0; k++ )
+        {
+            fCompl = Ivy_IsComplement(pAnd0);
+            pAnd0 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd0), NULL, IVY_LATCH, IVY_INIT_DC) );
+            if ( pAnd0 )
+                pAnd0 = Ivy_NotCond( pAnd0, fCompl );
+        }
+        for ( k = 0; pAnd1 && k < (int)pNode->nLat1; k++ )
+        {
+            fCompl = Ivy_IsComplement(pAnd1);
+            pAnd1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd1), NULL, IVY_LATCH, IVY_INIT_DC) );
+            if ( pAnd1 )
+                pAnd1 = Ivy_NotCond( pAnd1, fCompl );
+        }
+        // get the new node
+        if ( pAnd0 && pAnd1 )
+        {
+            // if they are both present, find the resulting node
+            pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl );
+            pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl );
+            assert( !Ivy_ObjIsLatch(Ivy_Regular(pAnd0)) || !Ivy_ObjIsLatch(Ivy_Regular(pAnd1)) );
+            if ( Ivy_Regular(pAnd0) == Ivy_Regular(pAnd1) || Ivy_ObjIsConst1(Ivy_Regular(pAnd0)) || Ivy_ObjIsConst1(Ivy_Regular(pAnd1)) )
+                pAnd = Ivy_And( p, pAnd0, pAnd1 );
+            else
+                pAnd = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) );
+            // return -1 if the node is the same as the original root
+            if ( Ivy_Regular(pAnd) == pRoot )
+                return -1;
+        }
+        else
+            pAnd = NULL;
+        // count the number of added nodes
+        if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) )
+        {
+            if ( ++Counter > NodeMax )
+                return -1;
+        }
+        pNode->pFunc = pAnd;
+    }
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the decomposition graph into the AIG.]
+
+  Description [AIG nodes for the fanins should be assigned to pNode->pFunc
+  of the leaves of the graph before calling this procedure.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph )
+{
+    Ivy_Obj_t * pAnd0, * pAnd1;
+    Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized"
+    int i, k;
+    // check for constant function
+    if ( Dec_GraphIsConst(pGraph) )
+        return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) );
+    // check for a literal
+    if ( Dec_GraphIsVar(pGraph) )
+    {
+        // get the variable node
+        pNode = Dec_GraphVar(pGraph);
+        // add the remaining latches
+        for ( k = 0; k < (int)pNode->nLat2; k++ )
+            pNode->pFunc = Ivy_Latch( p, (Ivy_Obj_t *)pNode->pFunc, IVY_INIT_DC );
+        return Ivy_NotCond( (Ivy_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) );
+    }
+    // build the AIG nodes corresponding to the AND gates of the graph
+    Dec_GraphForEachNode( pGraph, pNode, i )
+    {
+        pAnd0 = Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); 
+        pAnd1 = Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); 
+        // add the latches
+        for ( k = 0; k < (int)pNode->nLat0; k++ )
+            pAnd0 = Ivy_Latch( p, pAnd0, IVY_INIT_DC );
+        for ( k = 0; k < (int)pNode->nLat1; k++ )
+            pAnd1 = Ivy_Latch( p, pAnd1, IVY_INIT_DC );
+        // create the node
+        pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 );
+    }
+    // add the remaining latches
+    for ( k = 0; k < (int)pNode->nLat2; k++ )
+        pNode->pFunc = Ivy_Latch( p, (Ivy_Obj_t *)pNode->pFunc, IVY_INIT_DC );
+    // complement the result if necessary
+    return Ivy_NotCond( (Ivy_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces MFFC of the node by the new factored form.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain )
+{
+    Ivy_Obj_t * pRootNew;
+    int nNodesNew, nNodesOld;
+    nNodesOld = Ivy_ManNodeNum(p);
+    // create the new structure of nodes
+    pRootNew = Ivy_GraphToNetworkSeq( p, pGraph );
+    Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 0 );
+    // compare the gains
+    nNodesNew = Ivy_ManNodeNum(p);
+    assert( nGain <= nNodesOld - nNodesNew );
+    // propagate the buffer
+    Ivy_ManPropagateBuffers( p, 0 );
+}
+
+
+
+
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Ivy_CutGetTruth_rec( Ivy_Man_t * p, int Leaf, int * pNums, int nNums )
+{
+    static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+    unsigned uTruth0, uTruth1;
+    Ivy_Obj_t * pObj;
+    int i;
+    for ( i = 0; i < nNums; i++ )
+        if ( Leaf == pNums[i] )
+            return uMasks[i];
+    pObj = Ivy_ManObj( p, Ivy_LeafId(Leaf) );
+    if ( Ivy_ObjIsLatch(pObj) )
+    {
+        assert( !Ivy_ObjFaninC0(pObj) );
+        Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) + 1 );
+        return Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums );
+    }
+    assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) );
+    Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) );
+    uTruth0 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums );
+    if ( Ivy_ObjFaninC0(pObj) )
+        uTruth0 = ~uTruth0;
+    if ( Ivy_ObjIsBuf(pObj) )
+        return uTruth0;
+    Leaf = Ivy_LeafCreate( Ivy_ObjFaninId1(pObj), Ivy_LeafLat(Leaf) );
+    uTruth1 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums );
+    if ( Ivy_ObjFaninC1(pObj) )
+        uTruth1 = ~uTruth1;
+    return uTruth0 & uTruth1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums )
+{
+    assert( Ivy_ObjIsNode(pObj) );
+    assert( nNums < 6 );
+    return Ivy_CutGetTruth_rec( p, Ivy_LeafCreate(pObj->Id, 0), pNums, nNums );
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the cut can be constructed; 0 otherwise.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Ivy_CutPrescreen( Ivy_Cut_t * pCut, int Id0, int Id1 )
+{
+    int i;
+    if ( pCut->nSize < pCut->nSizeMax )
+        return 1;
+    for ( i = 0; i < pCut->nSize; i++ )
+        if ( pCut->pArray[i] == Id0 || pCut->pArray[i] == Id1 )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives new cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Ivy_CutDeriveNew2( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 )
+{
+    unsigned uHash = 0;
+    int i, k;
+    assert( pCut->nSize > 0 );
+    assert( IdNew0 < IdNew1 );
+    for ( i = k = 0; i < pCut->nSize; i++ )
+    {
+        if ( pCut->pArray[i] == IdOld )
+            continue;
+        if ( IdNew0 >= 0 )
+        {
+            if ( IdNew0 <= pCut->pArray[i] )
+            {
+                if ( IdNew0 < pCut->pArray[i] )
+                {
+                    if ( k == pCut->nSizeMax )
+                        return 0;
+                    pCutNew->pArray[ k++ ] = IdNew0;
+                    uHash |= Ivy_CutHashValue( IdNew0 );
+                }
+                IdNew0 = -1;
+            }
+        }
+        if ( IdNew1 >= 0 )
+        {
+            if ( IdNew1 <= pCut->pArray[i] )
+            {
+                if ( IdNew1 < pCut->pArray[i] )
+                {
+                    if ( k == pCut->nSizeMax )
+                        return 0;
+                    pCutNew->pArray[ k++ ] = IdNew1;
+                    uHash |= Ivy_CutHashValue( IdNew1 );
+                }
+                IdNew1 = -1;
+            }
+        }
+        if ( k == pCut->nSizeMax )
+            return 0;
+        pCutNew->pArray[ k++ ] = pCut->pArray[i];
+        uHash |= Ivy_CutHashValue( pCut->pArray[i] );
+    }
+    if ( IdNew0 >= 0 )
+    {
+        if ( k == pCut->nSizeMax )
+            return 0;
+        pCutNew->pArray[ k++ ] = IdNew0;
+        uHash |= Ivy_CutHashValue( IdNew0 );
+    }
+    if ( IdNew1 >= 0 )
+    {
+        if ( k == pCut->nSizeMax )
+            return 0;
+        pCutNew->pArray[ k++ ] = IdNew1;
+        uHash |= Ivy_CutHashValue( IdNew1 );
+    }
+    pCutNew->nSize = k;
+    pCutNew->uHash = uHash;
+    assert( pCutNew->nSize <= pCut->nSizeMax );
+    for ( i = 1; i < pCutNew->nSize; i++ )
+        assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives new cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Ivy_CutDeriveNew( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 )
+{
+    unsigned uHash = 0;
+    int i, k; 
+    assert( pCut->nSize > 0 );
+    assert( IdNew0 < IdNew1 );
+    for ( i = k = 0; i < pCut->nSize; i++ )
+    {
+        if ( pCut->pArray[i] == IdOld )
+            continue;
+        if ( IdNew0 <= pCut->pArray[i] )
+        {
+            if ( IdNew0 < pCut->pArray[i] )
+            {
+                pCutNew->pArray[ k++ ] = IdNew0;
+                uHash |= Ivy_CutHashValue( IdNew0 );
+            }
+            IdNew0 = 0x7FFFFFFF;
+        }
+        if ( IdNew1 <= pCut->pArray[i] )
+        {
+            if ( IdNew1 < pCut->pArray[i] )
+            {
+                pCutNew->pArray[ k++ ] = IdNew1;
+                uHash |= Ivy_CutHashValue( IdNew1 );
+            }
+            IdNew1 = 0x7FFFFFFF;
+        }
+        pCutNew->pArray[ k++ ] = pCut->pArray[i];
+        uHash |= Ivy_CutHashValue( pCut->pArray[i] );
+    }
+    if ( IdNew0 < 0x7FFFFFFF )
+    {
+        pCutNew->pArray[ k++ ] = IdNew0;
+        uHash |= Ivy_CutHashValue( IdNew0 );
+    }
+    if ( IdNew1 < 0x7FFFFFFF )
+    {
+        pCutNew->pArray[ k++ ] = IdNew1;
+        uHash |= Ivy_CutHashValue( IdNew1 );
+    }
+    pCutNew->nSize = k;
+    pCutNew->uHash = uHash;
+    assert( pCutNew->nSize <= pCut->nSizeMax );
+//    for ( i = 1; i < pCutNew->nSize; i++ )
+//        assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the hash value of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut )
+{
+    int i;
+    pCut->uHash = 0;
+    for ( i = 0; i < pCut->nSize; i++ )
+        pCut->uHash |= (1 << (pCut->pArray[i] % 31));
+    return pCut->uHash;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives new cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Ivy_CutDeriveNew3( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 )
+{
+    int i, k; 
+    assert( pCut->nSize > 0 );
+    assert( IdNew0 < IdNew1 );
+    for ( i = k = 0; i < pCut->nSize; i++ )
+    {
+        if ( pCut->pArray[i] == IdOld )
+            continue;
+        if ( IdNew0 <= pCut->pArray[i] )
+        {
+            if ( IdNew0 < pCut->pArray[i] )
+                pCutNew->pArray[ k++ ] = IdNew0;
+            IdNew0 = 0x7FFFFFFF;
+        }
+        if ( IdNew1 <= pCut->pArray[i] )
+        {
+            if ( IdNew1 < pCut->pArray[i] )
+                pCutNew->pArray[ k++ ] = IdNew1;
+            IdNew1 = 0x7FFFFFFF;
+        }
+        pCutNew->pArray[ k++ ] = pCut->pArray[i];
+    }
+    if ( IdNew0 < 0x7FFFFFFF )
+        pCutNew->pArray[ k++ ] = IdNew0;
+    if ( IdNew1 < 0x7FFFFFFF )
+        pCutNew->pArray[ k++ ] = IdNew1;
+    pCutNew->nSize = k;
+    assert( pCutNew->nSize <= pCut->nSizeMax );
+    Ivy_NodeCutHash( pCutNew );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pDom is contained in pCut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut )
+{
+    int i, k;
+    for ( i = 0; i < pDom->nSize; i++ )
+    {
+        assert( i==0 || pDom->pArray[i-1] < pDom->pArray[i] );
+        for ( k = 0; k < pCut->nSize; k++ )
+            if ( pDom->pArray[i] == pCut->pArray[k] )
+                break;
+        if ( k == pCut->nSize ) // node i in pDom is not contained in pCut
+            return 0;
+    }
+    // every node in pDom is contained in pCut
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check if the cut exists.]
+
+  Description [Returns 1 if the cut exists.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_CutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew )
+{
+    Ivy_Cut_t * pCut;
+    int i, k;
+    assert( pCutNew->uHash );
+    // try to find the cut
+    for ( i = 0; i < pCutStore->nCuts; i++ )
+    {
+        pCut = pCutStore->pCuts + i;
+        if ( pCut->nSize == 0 )
+            continue;
+        if ( pCut->nSize == pCutNew->nSize )
+        {
+            if ( pCut->uHash == pCutNew->uHash )
+            {
+                for ( k = 0; k < pCutNew->nSize; k++ )
+                    if ( pCut->pArray[k] != pCutNew->pArray[k] )
+                        break;
+                if ( k == pCutNew->nSize )
+                    return 1;
+            }
+            continue;
+        }
+        if ( pCut->nSize < pCutNew->nSize )
+        {
+            // skip the non-contained cuts
+            if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash )
+                continue;
+            // check containment seriously
+            if ( Ivy_CutCheckDominance( pCut, pCutNew ) )
+                return 1;
+            continue;
+        }
+        // check potential containment of other cut
+
+        // skip the non-contained cuts
+        if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash )
+            continue;
+        // check containment seriously
+        if ( Ivy_CutCheckDominance( pCutNew, pCut ) )
+        {
+            // remove the current cut
+            pCut->nSize = 0;
+        }
+    }
+    assert( pCutStore->nCuts < pCutStore->nCutsMax );
+    // add the cut
+    pCut = pCutStore->pCuts + pCutStore->nCuts++;
+    *pCut = *pCutNew;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compresses the cut representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_CutCompactAll( Ivy_Store_t * pCutStore )
+{
+    Ivy_Cut_t * pCut;
+    int i, k;
+    pCutStore->nCutsM = 0;
+    for ( i = k = 0; i < pCutStore->nCuts; i++ )
+    {
+        pCut = pCutStore->pCuts + i;
+        if ( pCut->nSize == 0 )
+            continue;
+        if ( pCut->nSize < pCut->nSizeMax )
+            pCutStore->nCutsM++;
+        pCutStore->pCuts[k++] = *pCut;
+    }
+    pCutStore->nCuts = k;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_CutPrintForNode( Ivy_Cut_t * pCut )
+{
+    int i;
+    assert( pCut->nSize > 0 );
+    printf( "%d : {", pCut->nSize );
+    for ( i = 0; i < pCut->nSize; i++ )
+        printf( " %d", pCut->pArray[i] );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_CutPrintForNodes( Ivy_Store_t * pCutStore )
+{
+    int i;
+    printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] );
+    for ( i = 0; i < pCutStore->nCuts; i++ )
+        Ivy_CutPrintForNode( pCutStore->pCuts + i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+static inline int Ivy_CutReadLeaf( Ivy_Obj_t * pFanin )
+{
+    int nLats, iLeaf;
+    assert( !Ivy_IsComplement(pFanin) );
+    if ( !Ivy_ObjIsLatch(pFanin) )
+        return Ivy_LeafCreate( pFanin->Id, 0 );
+    iLeaf = Ivy_CutReadLeaf(Ivy_ObjFanin0(pFanin));
+    nLats = Ivy_LeafLat(iLeaf);
+    assert( nLats < IVY_LEAF_MASK );
+    return 1 + iLeaf;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves )
+{
+    static Ivy_Store_t CutStore, * pCutStore = &CutStore;
+    Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut;
+    Ivy_Obj_t * pLeaf;
+    int i, k, Temp, nLats, iLeaf0, iLeaf1;
+
+    assert( nLeaves <= IVY_CUT_INPUT );
+
+    // start the structure
+    pCutStore->nCuts = 0;
+    pCutStore->nCutsMax = IVY_CUT_LIMIT;
+    // start the trivial cut
+    pCutNew->uHash = 0;
+    pCutNew->nSize = 1;
+    pCutNew->nSizeMax = nLeaves;
+    pCutNew->pArray[0] = Ivy_LeafCreate( pObj->Id, 0 );
+    pCutNew->uHash = Ivy_CutHashValue( pCutNew->pArray[0] );
+    // add the trivial cut
+    pCutStore->pCuts[pCutStore->nCuts++] = *pCutNew;
+    assert( pCutStore->nCuts == 1 );
+
+    // explore the cuts
+    for ( i = 0; i < pCutStore->nCuts; i++ )
+    {
+        // expand this cut
+        pCut = pCutStore->pCuts + i;
+        if ( pCut->nSize == 0 )
+            continue;
+        for ( k = 0; k < pCut->nSize; k++ )
+        {
+            pLeaf = Ivy_ManObj( p, Ivy_LeafId(pCut->pArray[k]) );
+            if ( Ivy_ObjIsCi(pLeaf) || Ivy_ObjIsConst1(pLeaf) )
+                continue;
+            assert( Ivy_ObjIsNode(pLeaf) );
+            nLats = Ivy_LeafLat(pCut->pArray[k]);
+
+            // get the fanins fanins
+            iLeaf0 = Ivy_CutReadLeaf( Ivy_ObjFanin0(pLeaf) );
+            iLeaf1 = Ivy_CutReadLeaf( Ivy_ObjFanin1(pLeaf) );
+            assert( nLats + Ivy_LeafLat(iLeaf0) < IVY_LEAF_MASK && nLats + Ivy_LeafLat(iLeaf1) < IVY_LEAF_MASK );
+            iLeaf0 = nLats + iLeaf0;
+            iLeaf1 = nLats + iLeaf1;
+            if ( !Ivy_CutPrescreen( pCut, iLeaf0, iLeaf1 ) )
+                continue;
+            // the given cut exist
+            if ( iLeaf0 > iLeaf1 )
+                Temp = iLeaf0, iLeaf0 = iLeaf1, iLeaf1 = Temp;
+            // create the new cut
+            if ( !Ivy_CutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf0, iLeaf1 ) )
+                continue;
+            // add the cut
+            Ivy_CutFindOrAddFilter( pCutStore, pCutNew );
+            if ( pCutStore->nCuts == IVY_CUT_LIMIT )
+                break;
+        }
+        if ( pCutStore->nCuts == IVY_CUT_LIMIT )
+            break;
+    }
+    if ( pCutStore->nCuts == IVY_CUT_LIMIT )
+        pCutStore->fSatur = 1;
+    else
+        pCutStore->fSatur = 0;
+//    printf( "%d ", pCutStore->nCuts );
+    Ivy_CutCompactAll( pCutStore );
+//    printf( "%d \n", pCutStore->nCuts );
+//    Ivy_CutPrintForNodes( pCutStore );
+    return pCutStore;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_CutComputeAll( Ivy_Man_t * p, int nInputs )
+{
+    Ivy_Store_t * pStore;
+    Ivy_Obj_t * pObj;
+    int i, nCutsTotal, nCutsTotalM, nNodeTotal, nNodeOver;
+    abctime clk = Abc_Clock();
+    if ( nInputs > IVY_CUT_INPUT )
+    {
+        printf( "Cannot compute cuts for more than %d inputs.\n", IVY_CUT_INPUT );
+        return;
+    }
+    nNodeTotal = nNodeOver = 0;
+    nCutsTotal = nCutsTotalM = -Ivy_ManNodeNum(p);
+    Ivy_ManForEachObj( p, pObj, i )
+    {
+        if ( !Ivy_ObjIsNode(pObj) )
+            continue;
+        pStore = Ivy_CutComputeForNode( p, pObj, nInputs );
+        nCutsTotal  += pStore->nCuts;
+        nCutsTotalM += pStore->nCutsM;
+        nNodeOver   += pStore->fSatur;
+        nNodeTotal++;
+    }
+    printf( "All = %6d. Minus = %6d. Triv = %6d.   Node = %6d. Satur = %6d.  ", 
+        nCutsTotal, nCutsTotalM, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyShow.c b/abc-build/src/aig/ivy/ivyShow.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyShow.c
@@ -0,0 +1,343 @@
+/**CFile****************************************************************
+
+  FileName    [ivyShow.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Visualization of HAIG.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyShow.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold )
+{
+    extern void Abc_ShowFile( char * FileNameDot );
+    static int Counter = 0;
+    char FileNameDot[200];
+    FILE * pFile;
+    // create the file name
+//    Ivy_ShowGetFileName( pMan->pName, FileNameDot );
+    sprintf( FileNameDot, "temp%02d.dot", Counter++ );
+    // check that the file can be opened
+    if ( (pFile = fopen( FileNameDot, "w" )) == NULL )
+    {
+        fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot );
+        return;
+    }
+    fclose( pFile );
+    // generate the file
+    Ivy_WriteDotAig( pMan, FileNameDot, fHaig, vBold );
+    // visualize the file 
+    Abc_ShowFile( FileNameDot );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the graph structure of AIG for DOT.]
+
+  Description [Useful for graph visualization using tools such as GraphViz: 
+  http://www.graphviz.org/]
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold )
+{
+    FILE * pFile;
+    Ivy_Obj_t * pNode, * pTemp, * pPrev;
+    int LevelMax, Level, i;
+
+    if ( Ivy_ManNodeNum(pMan) > 200 )
+    {
+        fprintf( stdout, "Cannot visualize AIG with more than 200 nodes.\n" );
+        return;
+    }
+    if ( (pFile = fopen( pFileName, "w" )) == NULL )
+    {
+        fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName );
+        return;
+    }
+
+    // mark the nodes
+    if ( vBold )
+        Vec_PtrForEachEntry( Ivy_Obj_t *, vBold, pNode, i )
+            pNode->fMarkB = 1;
+
+    // compute levels
+    LevelMax = 1 + Ivy_ManSetLevels( pMan, fHaig );
+
+    // write the DOT header
+    fprintf( pFile, "# %s\n",  "AIG structure generated by IVY package" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "digraph AIG {\n" );
+    fprintf( pFile, "size = \"7.5,10\";\n" );
+//  fprintf( pFile, "ranksep = 0.5;\n" );
+//  fprintf( pFile, "nodesep = 0.5;\n" );
+    fprintf( pFile, "center = true;\n" );
+//  fprintf( pFile, "orientation = landscape;\n" );
+//  fprintf( pFile, "edge [fontsize = 10];\n" );
+//  fprintf( pFile, "edge [dir = none];\n" );
+    fprintf( pFile, "edge [dir = back];\n" );
+    fprintf( pFile, "\n" );
+
+    // labels on the left of the picture
+    fprintf( pFile, "{\n" );
+    fprintf( pFile, "  node [shape = plaintext];\n" );
+    fprintf( pFile, "  edge [style = invis];\n" );
+    fprintf( pFile, "  LevelTitle1 [label=\"\"];\n" );
+    fprintf( pFile, "  LevelTitle2 [label=\"\"];\n" );
+    // generate node names with labels
+    for ( Level = LevelMax; Level >= 0; Level-- )
+    {
+        // the visible node name
+        fprintf( pFile, "  Level%d", Level );
+        fprintf( pFile, " [label = " );
+        // label name
+        fprintf( pFile, "\"" );
+        fprintf( pFile, "\"" );
+        fprintf( pFile, "];\n" );
+    }
+
+    // genetate the sequence of visible/invisible nodes to mark levels
+    fprintf( pFile, "  LevelTitle1 ->  LevelTitle2 ->" );
+    for ( Level = LevelMax; Level >= 0; Level-- )
+    {
+        // the visible node name
+        fprintf( pFile, "  Level%d",  Level );
+        // the connector
+        if ( Level != 0 )
+            fprintf( pFile, " ->" );
+        else
+            fprintf( pFile, ";" );
+    }
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    // generate title box on top
+    fprintf( pFile, "{\n" );
+    fprintf( pFile, "  rank = same;\n" );
+    fprintf( pFile, "  LevelTitle1;\n" );
+    fprintf( pFile, "  title1 [shape=plaintext,\n" );
+    fprintf( pFile, "          fontsize=20,\n" );
+    fprintf( pFile, "          fontname = \"Times-Roman\",\n" );
+    fprintf( pFile, "          label=\"" );
+    fprintf( pFile, "%s", "AIG structure visualized by ABC" );
+    fprintf( pFile, "\\n" );
+    fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" );
+    fprintf( pFile, "Time was %s. ",  Extra_TimeStamp() );
+    fprintf( pFile, "\"\n" );
+    fprintf( pFile, "         ];\n" );
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    // generate statistics box
+    fprintf( pFile, "{\n" );
+    fprintf( pFile, "  rank = same;\n" );
+    fprintf( pFile, "  LevelTitle2;\n" );
+    fprintf( pFile, "  title2 [shape=plaintext,\n" );
+    fprintf( pFile, "          fontsize=18,\n" );
+    fprintf( pFile, "          fontname = \"Times-Roman\",\n" );
+    fprintf( pFile, "          label=\"" );
+    fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Ivy_ManNodeNum(pMan), LevelMax );
+    fprintf( pFile, "\\n" );
+    fprintf( pFile, "\"\n" );
+    fprintf( pFile, "         ];\n" );
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    // generate the COs
+    fprintf( pFile, "{\n" );
+    fprintf( pFile, "  rank = same;\n" );
+    // the labeling node of this level
+    fprintf( pFile, "  Level%d;\n",  LevelMax );
+    // generate the CO nodes
+    Ivy_ManForEachCo( pMan, pNode, i )
+    {
+        if ( fHaig || pNode->pEquiv == NULL )
+            fprintf( pFile, "  Node%d%s [label = \"%d%s\"", pNode->Id, 
+                (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") );
+        else
+            fprintf( pFile, "  Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, 
+                (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":""), 
+                    Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" );
+        fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"invtriangle") );
+        fprintf( pFile, ", color = coral, fillcolor = coral" );
+        fprintf( pFile, "];\n" );
+    }
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    // generate nodes of each rank
+    for ( Level = LevelMax - 1; Level > 0; Level-- )
+    {
+        fprintf( pFile, "{\n" );
+        fprintf( pFile, "  rank = same;\n" );
+        // the labeling node of this level
+        fprintf( pFile, "  Level%d;\n",  Level );
+        Ivy_ManForEachObj( pMan, pNode, i )
+        {
+            if ( (int)pNode->Level != Level )
+                continue;
+            if ( fHaig || pNode->pEquiv == NULL )
+                fprintf( pFile, "  Node%d [label = \"%d\"", pNode->Id, pNode->Id );
+            else 
+                fprintf( pFile, "  Node%d [label = \"%d(%d%s)\"", pNode->Id, pNode->Id, 
+                    Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" );
+            fprintf( pFile, ", shape = ellipse" );
+            if ( vBold && pNode->fMarkB )
+                fprintf( pFile, ", style = filled" );
+            fprintf( pFile, "];\n" );
+        }
+        fprintf( pFile, "}" );
+        fprintf( pFile, "\n" );
+        fprintf( pFile, "\n" );
+    }
+
+    // generate the CI nodes
+    fprintf( pFile, "{\n" );
+    fprintf( pFile, "  rank = same;\n" );
+    // the labeling node of this level
+    fprintf( pFile, "  Level%d;\n",  0 );
+    // generate constant node
+    if ( Ivy_ObjRefs(Ivy_ManConst1(pMan)) > 0 )
+    {
+        pNode = Ivy_ManConst1(pMan);
+        // check if the costant node is present
+        fprintf( pFile, "  Node%d [label = \"Const1\"", pNode->Id );
+        fprintf( pFile, ", shape = ellipse" );
+        fprintf( pFile, ", color = coral, fillcolor = coral" );
+        fprintf( pFile, "];\n" );
+    }
+    // generate the CI nodes
+    Ivy_ManForEachCi( pMan, pNode, i )
+    {
+        if ( fHaig || pNode->pEquiv == NULL )
+            fprintf( pFile, "  Node%d%s [label = \"%d%s\"", pNode->Id, 
+                (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":"") );
+        else
+            fprintf( pFile, "  Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, 
+                (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":""), 
+                    Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" );
+        fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"triangle") );
+        fprintf( pFile, ", color = coral, fillcolor = coral" );
+        fprintf( pFile, "];\n" );
+    }
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    // generate invisible edges from the square down
+    fprintf( pFile, "title1 -> title2 [style = invis];\n" );
+    Ivy_ManForEachCo( pMan, pNode, i )
+        fprintf( pFile, "title2 -> Node%d%s [style = invis];\n", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") );
+
+    // generate edges
+    Ivy_ManForEachObj( pMan, pNode, i )
+    {
+        if ( !Ivy_ObjIsNode(pNode) && !Ivy_ObjIsCo(pNode) && !Ivy_ObjIsBuf(pNode) )
+            continue;
+        // generate the edge from this node to the next
+        fprintf( pFile, "Node%d%s",  pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") );
+        fprintf( pFile, " -> " );
+        fprintf( pFile, "Node%d%s",  Ivy_ObjFaninId0(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin0(pNode))? "_out":"") );
+        fprintf( pFile, " [" );
+        fprintf( pFile, "style = %s", Ivy_ObjFaninC0(pNode)? "dotted" : "bold" );
+//        if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL0(pNode) > 0 )
+//        fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) );
+        fprintf( pFile, "]" );
+        fprintf( pFile, ";\n" );
+        if ( !Ivy_ObjIsNode(pNode) )
+            continue;
+        // generate the edge from this node to the next
+        fprintf( pFile, "Node%d",  pNode->Id );
+        fprintf( pFile, " -> " );
+        fprintf( pFile, "Node%d%s",  Ivy_ObjFaninId1(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin1(pNode))? "_out":"") );
+        fprintf( pFile, " [" );
+        fprintf( pFile, "style = %s", Ivy_ObjFaninC1(pNode)? "dotted" : "bold" );
+//        if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL1(pNode) > 0 )
+//        fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) );
+        fprintf( pFile, "]" );
+        fprintf( pFile, ";\n" );
+        // generate the edges between the equivalent nodes
+        if ( fHaig && pNode->pEquiv && Ivy_ObjRefs(pNode) > 0 )
+        {
+            pPrev = pNode;
+            for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Ivy_Regular(pTemp->pEquiv) )
+            {
+                fprintf( pFile, "Node%d",  pPrev->Id );
+                fprintf( pFile, " -> " );
+                fprintf( pFile, "Node%d",  pTemp->Id );
+                fprintf( pFile, " [style = %s]", Ivy_IsComplement(pTemp->pEquiv)? "dotted" : "bold" );
+                fprintf( pFile, ";\n" );
+                pPrev = pTemp;
+            }
+            // connect the last node with the first
+            fprintf( pFile, "Node%d",  pPrev->Id );
+            fprintf( pFile, " -> " );
+            fprintf( pFile, "Node%d",  pNode->Id );
+            fprintf( pFile, " [style = %s]", Ivy_IsComplement(pPrev->pEquiv)? "dotted" : "bold" );
+            fprintf( pFile, ";\n" );
+        }
+    }
+
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+    fclose( pFile );
+
+    // unmark nodes
+    if ( vBold )
+        Vec_PtrForEachEntry( Ivy_Obj_t *, vBold, pNode, i )
+            pNode->fMarkB = 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyTable.c b/abc-build/src/aig/ivy/ivyTable.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyTable.c
@@ -0,0 +1,272 @@
+/**CFile****************************************************************
+
+  FileName    [ivyTable.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Structural hashing table.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006. ]
+
+  Revision    [$Id: ivyTable.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// hashing the node
+static unsigned Ivy_Hash( Ivy_Obj_t * pObj, int TableSize ) 
+{
+    unsigned Key = Ivy_ObjIsExor(pObj) * 1699;
+    Key ^= Ivy_ObjFaninId0(pObj) * 7937;
+    Key ^= Ivy_ObjFaninId1(pObj) * 2971;
+    Key ^= Ivy_ObjFaninC0(pObj) * 911;
+    Key ^= Ivy_ObjFaninC1(pObj) * 353;
+    Key ^= Ivy_ObjInit(pObj) * 911;
+    return Key % TableSize;
+}
+
+// returns the place where this node is stored (or should be stored)
+static int * Ivy_TableFind( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+    int i;
+    assert( Ivy_ObjIsHash(pObj) );
+    for ( i = Ivy_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize )
+        if ( p->pTable[i] == pObj->Id )
+            break;
+    return p->pTable + i;
+}
+
+static void         Ivy_TableResize( Ivy_Man_t * p );
+static unsigned int Cudd_PrimeAig( unsigned int  p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    [Checks if node with the given attributes is in the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_TableLookup( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+    Ivy_Obj_t * pEntry;
+    int i;
+    assert( !Ivy_IsComplement(pObj) );
+    if ( !Ivy_ObjIsHash(pObj) )
+        return NULL;
+    assert( Ivy_ObjIsLatch(pObj) || Ivy_ObjFaninId0(pObj) > 0 );
+    assert( Ivy_ObjFaninId1(pObj) == 0 || Ivy_ObjFaninId0(pObj) < Ivy_ObjFaninId1(pObj) );
+    if ( Ivy_ObjFanin0(pObj)->nRefs == 0 || (Ivy_ObjChild1(pObj) && Ivy_ObjFanin1(pObj)->nRefs == 0) )
+        return NULL;
+    for ( i = Ivy_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize )
+    {
+        pEntry = Ivy_ManObj( p, p->pTable[i] );
+        if ( Ivy_ObjChild0(pEntry) == Ivy_ObjChild0(pObj) && 
+             Ivy_ObjChild1(pEntry) == Ivy_ObjChild1(pObj) && 
+             Ivy_ObjInit(pEntry) == Ivy_ObjInit(pObj) && 
+             Ivy_ObjType(pEntry) == Ivy_ObjType(pObj) )
+            return pEntry;
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the node to the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_TableInsert( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+    int * pPlace;
+    assert( !Ivy_IsComplement(pObj) );
+    if ( !Ivy_ObjIsHash(pObj) )
+        return;
+    if ( (pObj->Id & 63) == 0 )
+    {
+        if ( p->nTableSize < 2 * Ivy_ManHashObjNum(p) )
+            Ivy_TableResize( p );
+    }
+    pPlace = Ivy_TableFind( p, pObj );
+    assert( *pPlace == 0 );
+    *pPlace = pObj->Id;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the node from the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_TableDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+    Ivy_Obj_t * pEntry;
+    int i, * pPlace;
+    assert( !Ivy_IsComplement(pObj) );
+    if ( !Ivy_ObjIsHash(pObj) )
+        return;
+    pPlace = Ivy_TableFind( p, pObj );
+    assert( *pPlace == pObj->Id ); // node should be in the table
+    *pPlace = 0;
+    // rehash the adjacent entries
+    i = pPlace - p->pTable;
+    for ( i = (i+1) % p->nTableSize; p->pTable[i]; i = (i+1) % p->nTableSize )
+    {
+        pEntry = Ivy_ManObj( p, p->pTable[i] );
+        p->pTable[i] = 0;
+        Ivy_TableInsert( p, pEntry );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the table to point to the new node.]
+
+  Description [If the old node (pObj) is in the table, updates the table
+  to point to an object with different ID (ObjIdNew). The table should
+  not contain an object with ObjIdNew (this is currently not checked).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_TableUpdate( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ObjIdNew )
+{
+    int * pPlace;
+    assert( !Ivy_IsComplement(pObj) );
+    if ( !Ivy_ObjIsHash(pObj) )
+        return;
+    pPlace = Ivy_TableFind( p, pObj );
+    assert( *pPlace == pObj->Id ); // node should be in the table
+    *pPlace = ObjIdNew; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of nodes in the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_TableCountEntries( Ivy_Man_t * p )
+{
+    int i, Counter = 0;
+    for ( i = 0; i < p->nTableSize; i++ )
+        Counter += (p->pTable[i] != 0);
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the table.]
+
+  Description [Typically this procedure should not be called.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_TableResize( Ivy_Man_t * p )
+{
+    int * pTableOld, * pPlace;
+    int nTableSizeOld, Counter, nEntries, e;
+    abctime clk;
+clk = Abc_Clock();
+    // save the old table
+    pTableOld = p->pTable;
+    nTableSizeOld = p->nTableSize;
+    // get the new table
+    p->nTableSize = Abc_PrimeCudd( 5 * Ivy_ManHashObjNum(p) ); 
+    p->pTable = ABC_ALLOC( int, p->nTableSize );
+    memset( p->pTable, 0, sizeof(int) * p->nTableSize );
+    // rehash the entries from the old table
+    Counter = 0;
+    for ( e = 0; e < nTableSizeOld; e++ )
+    {
+        if ( pTableOld[e] == 0 )
+            continue;
+        Counter++;
+        // get the place where this entry goes in the table table
+        pPlace = Ivy_TableFind( p, Ivy_ManObj(p, pTableOld[e]) );
+        assert( *pPlace == 0 ); // should not be in the table
+        *pPlace = pTableOld[e];
+    }
+    nEntries = Ivy_ManHashObjNum(p);
+//    assert( Counter == nEntries );
+//    printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize );
+//    ABC_PRT( "Time", Abc_Clock() - clk );
+    // replace the table and the parameters
+    ABC_FREE( pTableOld );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Profiles the hash table.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Ivy_TableProfile( Ivy_Man_t * p )
+{
+    int i, Counter = 0;
+    for ( i = 0; i < p->nTableSize; i++ )
+    {
+        if ( p->pTable[i] )
+            Counter++;
+        else if ( Counter )
+        {
+            printf( "%d ", Counter );
+            Counter = 0;
+        }
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivyUtil.c b/abc-build/src/aig/ivy/ivyUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivyUtil.c
@@ -0,0 +1,824 @@
+/**CFile****************************************************************
+
+  FileName    [ivyUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    [Various procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivyUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Increments the current traversal ID of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManIncrementTravId( Ivy_Man_t * p )
+{
+    if ( p->nTravIds >= (1<<30)-1 - 1000 )
+        Ivy_ManCleanTravId( p );
+    p->nTravIds++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the DFS ordering of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManCleanTravId( Ivy_Man_t * p )
+{
+    Ivy_Obj_t * pObj;
+    int i;
+    p->nTravIds = 1;
+    Ivy_ManForEachObj( p, pObj, i )
+        pObj->TravId = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManCollectCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vNodes )
+{
+    if ( pNode->fMarkA )
+        return;
+    pNode->fMarkA = 1;
+    assert( Ivy_ObjIsAnd(pNode) || Ivy_ObjIsExor(pNode) );
+    Ivy_ManCollectCut_rec( p, Ivy_ObjFanin0(pNode), vNodes );
+    Ivy_ManCollectCut_rec( p, Ivy_ObjFanin1(pNode), vNodes );
+    Vec_IntPush( vNodes, pNode->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table of the cut.]
+
+  Description [Does not modify the array of leaves. Uses array vTruth to store 
+  temporary truth tables. The returned pointer should be used immediately.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes )
+{
+    int i, Leaf;
+    // collect and mark the leaves
+    Vec_IntClear( vNodes );
+    Vec_IntForEachEntry( vLeaves, Leaf, i )
+    {
+        Vec_IntPush( vNodes, Leaf );
+        Ivy_ManObj(p, Leaf)->fMarkA = 1;
+    }
+    // collect and mark the nodes
+    Ivy_ManCollectCut_rec( p, pRoot, vNodes );
+    // clean the nodes
+    Vec_IntForEachEntry( vNodes, Leaf, i )
+        Ivy_ManObj(p, Leaf)->fMarkA = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the pointer to the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Ivy_ObjGetTruthStore( int ObjNum, Vec_Int_t * vTruth )
+{
+   return ((unsigned *)Vec_IntArray(vTruth)) + 8 * ObjNum;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManCutTruthOne( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vTruth, int nWords )
+{
+    unsigned * pTruth, * pTruth0, * pTruth1;
+    int i;
+    pTruth  = Ivy_ObjGetTruthStore( pNode->TravId, vTruth );
+    pTruth0 = Ivy_ObjGetTruthStore( Ivy_ObjFanin0(pNode)->TravId, vTruth );
+    pTruth1 = Ivy_ObjGetTruthStore( Ivy_ObjFanin1(pNode)->TravId, vTruth );
+    if ( Ivy_ObjIsExor(pNode) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = pTruth0[i] ^ pTruth1[i];
+    else if ( !Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = pTruth0[i] & pTruth1[i];
+    else if ( !Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = pTruth0[i] & ~pTruth1[i];
+    else if ( Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ~pTruth0[i] & pTruth1[i];
+    else // if ( Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ~pTruth0[i] & ~pTruth1[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table of the cut.]
+
+  Description [Does not modify the array of leaves. Uses array vTruth to store 
+  temporary truth tables. The returned pointer should be used immediately.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth )
+{
+    static unsigned uTruths[8][8] = { // elementary truth tables
+        { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA },
+        { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC },
+        { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 },
+        { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 },
+        { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, 
+        { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, 
+        { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, 
+        { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } 
+    };
+    int i, Leaf;
+    // collect the cut
+    Ivy_ManCollectCut( p, pRoot, vLeaves, vNodes );
+    // set the node numbers
+    Vec_IntForEachEntry( vNodes, Leaf, i )
+        Ivy_ManObj(p, Leaf)->TravId = i;
+    // alloc enough memory
+    Vec_IntClear( vTruth );
+    Vec_IntGrow( vTruth, 8 * Vec_IntSize(vNodes) );
+    // set the elementary truth tables
+    Vec_IntForEachEntry( vLeaves, Leaf, i )
+        memcpy( Ivy_ObjGetTruthStore(i, vTruth), uTruths[i], 8 * sizeof(unsigned) );
+    // compute truths for other nodes
+    Vec_IntForEachEntryStart( vNodes, Leaf, i, Vec_IntSize(vLeaves) )
+        Ivy_ManCutTruthOne( p, Ivy_ManObj(p, Leaf), vTruth, 8 );
+    return Ivy_ObjGetTruthStore( pRoot->TravId, vTruth );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect the latches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p )
+{
+    Vec_Int_t * vLatches;
+    Ivy_Obj_t * pObj;
+    int i;
+    vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) );
+    Ivy_ManForEachLatch( p, pObj, i )
+        Vec_IntPush( vLatches, pObj->Id );
+    return vLatches;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect the latches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManLevels( Ivy_Man_t * p )
+{
+    Ivy_Obj_t * pObj;
+    int i, LevelMax = 0;
+    Ivy_ManForEachPo( p, pObj, i )
+        LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level );
+    return LevelMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect the latches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ManResetLevels_rec( Ivy_Obj_t * pObj )
+{
+    if ( pObj->Level || Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) )
+        return pObj->Level;
+    if ( Ivy_ObjIsBuf(pObj) )
+        return pObj->Level = Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) );
+    assert( Ivy_ObjIsNode(pObj) );
+    Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) );
+    Ivy_ManResetLevels_rec( Ivy_ObjFanin1(pObj) );
+    return pObj->Level = Ivy_ObjLevelNew( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect the latches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManResetLevels( Ivy_Man_t * p )
+{
+    Ivy_Obj_t * pObj;
+    int i;
+    Ivy_ManForEachObj( p, pObj, i )
+        pObj->Level = 0;
+    Ivy_ManForEachCo( p, pObj, i )
+        Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [References/references the node and returns MFFC size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ObjRefDeref( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fReference, int fLabel )
+{
+    Ivy_Obj_t * pNode0, * pNode1;
+    int Counter;
+    // label visited nodes
+    if ( fLabel )
+        Ivy_ObjSetTravIdCurrent( p, pNode );
+    // skip the CI
+    if ( Ivy_ObjIsPi(pNode) )
+        return 0;
+    assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsBuf(pNode) || Ivy_ObjIsLatch(pNode) );
+    // process the internal node
+    pNode0 = Ivy_ObjFanin0(pNode);
+    pNode1 = Ivy_ObjFanin1(pNode);
+    Counter = Ivy_ObjIsNode(pNode);
+    if ( fReference )
+    {
+        if ( pNode0->nRefs++ == 0 )
+            Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel );
+        if ( pNode1 && pNode1->nRefs++ == 0 )
+            Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel );
+    }
+    else
+    {
+        assert( pNode0->nRefs > 0 );
+        assert( pNode1 == NULL || pNode1->nRefs > 0 );
+        if ( --pNode0->nRefs == 0 )
+            Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel );
+        if ( pNode1 && --pNode1->nRefs == 0 )
+            Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel );
+    }
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Labels MFFC with the current label.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pNode )
+{
+    int nConeSize1, nConeSize2;
+    assert( !Ivy_IsComplement( pNode ) );
+    assert( Ivy_ObjIsNode( pNode ) );
+    nConeSize1 = Ivy_ObjRefDeref( p, pNode, 0, 1 ); // dereference
+    nConeSize2 = Ivy_ObjRefDeref( p, pNode, 1, 0 ); // reference
+    assert( nConeSize1 == nConeSize2 );
+    assert( nConeSize1 > 0 );
+    return nConeSize1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively updates fanout levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+    Ivy_Obj_t * pFanout;
+    Vec_Ptr_t * vFanouts;
+    int i, LevelNew;
+    assert( p->fFanout );
+    assert( Ivy_ObjIsNode(pObj) );
+    vFanouts = Vec_PtrAlloc( 10 );
+    Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i )
+    {
+        if ( Ivy_ObjIsCo(pFanout) )
+        {
+//            assert( (int)Ivy_ObjFanin0(pFanout)->Level <= p->nLevelMax );
+            continue;
+        }
+        LevelNew = Ivy_ObjLevelNew( pFanout );
+        if ( (int)pFanout->Level == LevelNew )
+            continue;
+        pFanout->Level = LevelNew;
+        Ivy_ObjUpdateLevel_rec( p, pFanout );
+    }
+    Vec_PtrFree( vFanouts );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the new required level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ObjLevelRNew( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+    Ivy_Obj_t * pFanout;
+    Vec_Ptr_t * vFanouts;
+    int i, Required, LevelNew = 1000000;
+    assert( p->fFanout && p->vRequired );
+    vFanouts = Vec_PtrAlloc( 10 );
+    Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i )
+    {
+        Required = Vec_IntEntry(p->vRequired, pFanout->Id);
+        LevelNew = IVY_MIN( LevelNew, Required );
+    }
+    Vec_PtrFree( vFanouts );
+    return LevelNew - 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively updates fanout levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew )
+{
+    Ivy_Obj_t * pFanin;
+    if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) )
+        return;
+    assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) );
+    // process the first fanin
+    pFanin = Ivy_ObjFanin0(pObj);
+    if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 )
+    {
+        Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 );
+        Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 );
+    }
+    if ( Ivy_ObjIsBuf(pObj) )
+        return;
+    // process the second fanin
+    pFanin = Ivy_ObjFanin1(pObj);
+    if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 )
+    {
+        Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 );
+        Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node is the root of MUX or EXOR/NEXOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_ObjIsMuxType( Ivy_Obj_t * pNode )
+{
+    Ivy_Obj_t * pNode0, * pNode1;
+    // check that the node is regular
+    assert( !Ivy_IsComplement(pNode) );
+    // if the node is not AND, this is not MUX
+    if ( !Ivy_ObjIsAnd(pNode) )
+        return 0;
+    // if the children are not complemented, this is not MUX
+    if ( !Ivy_ObjFaninC0(pNode) || !Ivy_ObjFaninC1(pNode) )
+        return 0;
+    // get children
+    pNode0 = Ivy_ObjFanin0(pNode);
+    pNode1 = Ivy_ObjFanin1(pNode);
+    // if the children are not ANDs, this is not MUX
+    if ( !Ivy_ObjIsAnd(pNode0) || !Ivy_ObjIsAnd(pNode1) )
+        return 0;
+    // otherwise the node is MUX iff it has a pair of equal grandchildren
+    return (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1))) || 
+           (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1))) ||
+           (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1))) ||
+           (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1)));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recognizes what nodes are control and data inputs of a MUX.]
+
+  Description [If the node is a MUX, returns the control variable C.
+  Assigns nodes T and E to be the then and else variables of the MUX. 
+  Node C is never complemented. Nodes T and E can be complemented.
+  This function also recognizes EXOR/NEXOR gates as MUXes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pNode, Ivy_Obj_t ** ppNodeT, Ivy_Obj_t ** ppNodeE )
+{
+    Ivy_Obj_t * pNode0, * pNode1;
+    assert( !Ivy_IsComplement(pNode) );
+    assert( Ivy_ObjIsMuxType(pNode) );
+    // get children
+    pNode0 = Ivy_ObjFanin0(pNode);
+    pNode1 = Ivy_ObjFanin1(pNode);
+    // find the control variable
+//    if ( pNode1->p1 == Fraig_Not(pNode2->p1) )
+    if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1)) )
+    {
+//        if ( Fraig_IsComplement(pNode1->p1) )
+        if ( Ivy_ObjFaninC0(pNode0) )
+        { // pNode2->p1 is positive phase of C
+            *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2);
+            *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2);
+            return Ivy_ObjChild0(pNode1);//pNode2->p1;
+        }
+        else
+        { // pNode1->p1 is positive phase of C
+            *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2);
+            *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2);
+            return Ivy_ObjChild0(pNode0);//pNode1->p1;
+        }
+    }
+//    else if ( pNode1->p1 == Fraig_Not(pNode2->p2) )
+    else if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1)) )
+    {
+//        if ( Fraig_IsComplement(pNode1->p1) )
+        if ( Ivy_ObjFaninC0(pNode0) )
+        { // pNode2->p2 is positive phase of C
+            *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1);
+            *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2);
+            return Ivy_ObjChild1(pNode1);//pNode2->p2;
+        }
+        else
+        { // pNode1->p1 is positive phase of C
+            *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2);
+            *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1);
+            return Ivy_ObjChild0(pNode0);//pNode1->p1;
+        }
+    }
+//    else if ( pNode1->p2 == Fraig_Not(pNode2->p1) )
+    else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1)) )
+    {
+//        if ( Fraig_IsComplement(pNode1->p2) )
+        if ( Ivy_ObjFaninC1(pNode0) )
+        { // pNode2->p1 is positive phase of C
+            *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2);
+            *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1);
+            return Ivy_ObjChild0(pNode1);//pNode2->p1;
+        }
+        else
+        { // pNode1->p2 is positive phase of C
+            *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1);
+            *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2);
+            return Ivy_ObjChild1(pNode0);//pNode1->p2;
+        }
+    }
+//    else if ( pNode1->p2 == Fraig_Not(pNode2->p2) )
+    else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1)) )
+    {
+//        if ( Fraig_IsComplement(pNode1->p2) )
+        if ( Ivy_ObjFaninC1(pNode0) )
+        { // pNode2->p2 is positive phase of C
+            *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1);
+            *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1);
+            return Ivy_ObjChild1(pNode1);//pNode2->p2;
+        }
+        else
+        { // pNode1->p2 is positive phase of C
+            *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1);
+            *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1);
+            return Ivy_ObjChild1(pNode0);//pNode1->p2;
+        }
+    }
+    assert( 0 ); // this is not MUX
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the real fanin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj )
+{
+    Ivy_Obj_t * pFanin;
+    if ( pObj == NULL || !Ivy_ObjIsBuf( Ivy_Regular(pObj) ) )
+        return pObj;
+    pFanin = Ivy_ObjReal( Ivy_ObjChild0(Ivy_Regular(pObj)) );
+    return Ivy_NotCond( pFanin, Ivy_IsComplement(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints node in HAIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig )
+{
+    Ivy_Obj_t * pTemp;
+    int fShowFanouts = 0;
+    assert( !Ivy_IsComplement(pObj) );
+    printf( "Node %5d : ", Ivy_ObjId(pObj) );
+    if ( Ivy_ObjIsConst1(pObj) )
+        printf( "constant 1" );
+    else if ( Ivy_ObjIsPi(pObj) )
+        printf( "PI" );
+    else if ( Ivy_ObjIsPo(pObj) )
+        printf( "PO" );
+    else if ( Ivy_ObjIsLatch(pObj) )
+        printf( "latch (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") );
+    else if ( Ivy_ObjIsBuf(pObj) )
+        printf( "buffer (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") );
+    else
+        printf( "AND( %5d%s, %5d%s )", 
+            Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " "), 
+            Ivy_ObjFanin1(pObj)->Id, (Ivy_ObjFaninC1(pObj)? "\'" : " ") );
+    printf( " (refs = %3d)", Ivy_ObjRefs(pObj) );
+    if ( fShowFanouts )
+    {
+        Vec_Ptr_t * vFanouts;
+        Ivy_Obj_t * pFanout;
+        int i;
+        vFanouts = Vec_PtrAlloc( 10 );
+        printf( "\nFanouts:\n" );
+        Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i )
+        {
+            printf( "    " );
+            printf( "Node %5d : ", Ivy_ObjId(pFanout) );
+            if ( Ivy_ObjIsPo(pFanout) )
+                printf( "PO" );
+            else if ( Ivy_ObjIsLatch(pFanout) )
+                printf( "latch (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") );
+            else if ( Ivy_ObjIsBuf(pFanout) )
+                printf( "buffer (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") );
+            else
+                printf( "AND( %5d%s, %5d%s )", 
+                    Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " "), 
+                    Ivy_ObjFanin1(pFanout)->Id, (Ivy_ObjFaninC1(pFanout)? "\'" : " ") );
+            printf( "\n" );
+        }
+        Vec_PtrFree( vFanouts );
+        return;
+    }
+    if ( !fHaig )
+    {
+        if ( pObj->pEquiv == NULL )
+            printf( " HAIG node not given" );
+        else
+            printf( " HAIG node = %d%s", Ivy_Regular(pObj->pEquiv)->Id, (Ivy_IsComplement(pObj->pEquiv)? "\'" : " ") );
+        return;
+    }
+    if ( pObj->pEquiv == NULL )
+        return;
+    // there are choices
+    if ( Ivy_ObjRefs(pObj) > 0 )
+    {
+        // print equivalence class
+        printf( "  { %5d ", pObj->Id );
+        assert( !Ivy_IsComplement(pObj->pEquiv) );
+        for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+            printf( " %5d%s", pTemp->Id, (Ivy_IsComplement(pTemp->pEquiv)? "\'" : " ") );
+        printf( " }" );
+        return;
+    }
+    // this is a secondary node
+    for ( pTemp = Ivy_Regular(pObj->pEquiv); Ivy_ObjRefs(pTemp) == 0; pTemp = Ivy_Regular(pTemp->pEquiv) );
+    assert( Ivy_ObjRefs(pTemp) > 0 );
+    printf( "  class of %d", pTemp->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints node in HAIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig )
+{
+    Vec_Int_t * vNodes;
+    Ivy_Obj_t * pObj;
+    int i;
+    printf( "PIs: " );
+    Ivy_ManForEachPi( p, pObj, i )
+        printf( " %d", pObj->Id );
+    printf( "\n" );
+    printf( "POs: " );
+    Ivy_ManForEachPo( p, pObj, i )
+        printf( " %d", pObj->Id );
+    printf( "\n" );
+    printf( "Latches: " );
+    Ivy_ManForEachLatch( p, pObj, i )
+        printf( " %d=%d%s", pObj->Id, Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") );
+    printf( "\n" );
+    vNodes = Ivy_ManDfsSeq( p, NULL );
+    Ivy_ManForEachNodeVec( p, vNodes, pObj, i )
+        Ivy_ObjPrintVerbose( p, pObj, fHaig ), printf( "\n" );
+    printf( "\n" );
+    Vec_IntFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs incremental rewriting of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_CutTruthPrint2( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth )
+{
+    int i;
+    printf( "Trying cut : {" );
+    for ( i = 0; i < pCut->nSize; i++ )
+        printf( " %6d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) );
+    printf( " }   " );
+    Extra_PrintBinary( stdout, &uTruth, 16 );  printf( "\n" );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs incremental rewriting of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ivy_CutTruthPrint( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth )
+{
+    Vec_Ptr_t * vArray;
+    Ivy_Obj_t * pObj, * pFanout;
+    int nLatches = 0;
+    int nPresent = 0;
+    int i, k;
+    int fVerbose = 0;
+
+    if ( fVerbose )
+        printf( "Trying cut : {" );
+    for ( i = 0; i < pCut->nSize; i++ )
+    {
+        if ( fVerbose )
+            printf( " %6d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) );
+        nLatches += Ivy_LeafLat(pCut->pArray[i]);
+    }
+    if ( fVerbose )
+        printf( " }   " );
+    if ( fVerbose )
+        printf( "Latches = %d. ", nLatches );
+
+    // check if there are latches on the fanout edges
+    vArray = Vec_PtrAlloc( 100 );
+    for ( i = 0; i < pCut->nSize; i++ )
+    {
+        pObj = Ivy_ManObj( p, Ivy_LeafId(pCut->pArray[i]) );
+        Ivy_ObjForEachFanout( p, pObj, vArray, pFanout, k )
+        {
+            if ( Ivy_ObjIsLatch(pFanout) )
+            {
+                nPresent++;
+                break;
+            }
+        }
+    }
+    Vec_PtrSize( vArray );
+    if ( fVerbose )
+    {
+        printf( "Present = %d. ", nPresent );
+        if ( nLatches > nPresent )
+            printf( "Clauses = %d. ", 2*(nLatches - nPresent) );
+        printf( "\n" );
+    }
+    return ( nLatches > nPresent ) ? 2*(nLatches - nPresent) : 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/ivy_.c b/abc-build/src/aig/ivy/ivy_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/ivy_.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+  FileName    [ivy_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [And-Inverter Graph package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 11, 2006.]
+
+  Revision    [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/ivy/module.make b/abc-build/src/aig/ivy/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/ivy/module.make
@@ -0,0 +1,22 @@
+SRC +=	src/aig/ivy/ivyBalance.c \
+	src/aig/ivy/ivyCanon.c \
+	src/aig/ivy/ivyCheck.c \
+	src/aig/ivy/ivyCut.c \
+	src/aig/ivy/ivyCutTrav.c \
+	src/aig/ivy/ivyDfs.c \
+	src/aig/ivy/ivyDsd.c \
+	src/aig/ivy/ivyFanout.c \
+	src/aig/ivy/ivyFastMap.c \
+	src/aig/ivy/ivyFraig.c \
+	src/aig/ivy/ivyHaig.c \
+	src/aig/ivy/ivyMan.c \
+	src/aig/ivy/ivyMem.c \
+	src/aig/ivy/ivyMulti.c \
+	src/aig/ivy/ivyObj.c \
+	src/aig/ivy/ivyOper.c \
+	src/aig/ivy/ivyResyn.c \
+	src/aig/ivy/ivyRwr.c \
+	src/aig/ivy/ivySeq.c \
+	src/aig/ivy/ivyShow.c \
+	src/aig/ivy/ivyTable.c \
+	src/aig/ivy/ivyUtil.c
diff --git a/abc-build/src/aig/miniaig/abcapis.h b/abc-build/src/aig/miniaig/abcapis.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/miniaig/abcapis.h
@@ -0,0 +1,74 @@
+/**CFile****************************************************************
+
+  FileName    [abcapis.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Include this file in the external code calling ABC.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 29, 2012.]
+
+  Revision    [$Id: abcapis.h,v 1.00 2012/09/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef MINI_AIG__abc_apis_h
+#define MINI_AIG__abc_apis_h
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+// procedures to start and stop the ABC framework
+extern void   Abc_Start();
+extern void   Abc_Stop();
+
+// procedures to get the ABC framework (pAbc) and execute commands in it
+extern void * Abc_FrameGetGlobalFrame();
+extern int    Cmd_CommandExecute( void * pAbc, char * pCommandLine );
+
+// procedures to input/output 'mini AIG'
+extern void   Abc_NtkInputMiniAig( void * pAbc, void * pMiniAig );
+extern void * Abc_NtkOutputMiniAig( void * pAbc );
+
+// procedures to set CI/CO arrival/required times
+extern void   Abc_NtkSetCiArrivalTime( void * pAbc, int iCi, float Rise, float Fall );
+extern void   Abc_NtkSetCoRequiredTime( void * pAbc, int iCo, float Rise, float Fall );
+
+// procedures to return the mapped network
+extern int *  Abc_NtkOutputMiniMapping( void * pAbc );
+extern void   Abc_NtkPrintMiniMapping( int * pArray );
+
+// procedures to access verifization status and a counter-example
+extern int    Abc_FrameReadProbStatus( void * pAbc );   
+extern void * Abc_FrameReadCex( void * pAbc );    
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/aig/miniaig/miniaig.h b/abc-build/src/aig/miniaig/miniaig.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/miniaig/miniaig.h
@@ -0,0 +1,276 @@
+/**CFile****************************************************************
+
+  FileName    [miniaig.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Minimalistic AIG package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 29, 2012.]
+
+  Revision    [$Id: miniaig.h,v 1.00 2012/09/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef MINI_AIG__mini_aig_h
+#define MINI_AIG__mini_aig_h
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+#define MINI_AIG_NULL       (0x7FFFFFFF)
+#define MINI_AIG_START_SIZE (0x000000FF)
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Mini_Aig_t_       Mini_Aig_t;
+struct Mini_Aig_t_ 
+{
+    int           nCap;
+    int           nSize;
+    int           nRegs;
+    int *         pArray;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+// memory management
+#define MINI_AIG_ALLOC(type, num)     ((type *) malloc(sizeof(type) * (num)))
+#define MINI_AIG_CALLOC(type, num)    ((type *) calloc((num), sizeof(type)))
+#define MINI_AIG_FALLOC(type, num)    ((type *) memset(malloc(sizeof(type) * (num)), 0xff, sizeof(type) * (num)))
+#define MINI_AIG_FREE(obj)            ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#define MINI_AIG_REALLOC(type, obj, num) \
+        ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
+         ((type *) malloc(sizeof(type) * (num))))
+
+// internal procedures
+static void Mini_AigGrow( Mini_Aig_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pArray = MINI_AIG_REALLOC( int, p->pArray, nCapMin ); 
+    assert( p->pArray );
+    p->nCap   = nCapMin;
+}
+static void Mini_AigPush( Mini_Aig_t * p, int Lit0, int Lit1 )
+{
+    if ( p->nSize + 2 > p->nCap )
+    {
+        if ( p->nCap < MINI_AIG_START_SIZE )
+            Mini_AigGrow( p, MINI_AIG_START_SIZE );
+        else
+            Mini_AigGrow( p, 2 * p->nCap );
+    }
+    p->pArray[p->nSize++] = Lit0;
+    p->pArray[p->nSize++] = Lit1;
+}
+
+// accessing fanins
+static int Mini_AigNodeFanin0( Mini_Aig_t * p, int Id )
+{
+    assert( Id >= 0 && 2*Id < p->nSize );
+    return p->pArray[2*Id];
+}
+static int Mini_AigNodeFanin1( Mini_Aig_t * p, int Id )
+{
+    assert( Id >= 0 && 2*Id < p->nSize );
+    return p->pArray[2*Id+1];
+}
+
+// working with variables and literals
+static int      Mini_AigVar2Lit( int Var, int fCompl )         { return Var + Var + fCompl;   }
+static int      Mini_AigLit2Var( int Lit )                     { return Lit >> 1;             }
+static int      Mini_AigLitIsCompl( int Lit )                  { return Lit & 1;              }
+static int      Mini_AigLitNot( int Lit )                      { return Lit ^ 1;              }
+static int      Mini_AigLitNotCond( int Lit, int c )           { return Lit ^ (int)(c > 0);   }
+static int      Mini_AigLitRegular( int Lit )                  { return Lit & ~01;            }
+
+static int      Mini_AigLitConst0()                            { return 0;                    }
+static int      Mini_AigLitConst1()                            { return 1;                    }
+static int      Mini_AigLitIsConst0( int Lit )                 { return Lit == 0;             }
+static int      Mini_AigLitIsConst1( int Lit )                 { return Lit == 1;             }
+static int      Mini_AigLitIsConst( int Lit )                  { return Lit == 0 || Lit == 1; }
+
+static int      Mini_AigNodeNum( Mini_Aig_t * p )              { return p->nSize/2;           }
+static int      Mini_AigNodeIsConst( Mini_Aig_t * p, int Id )  { assert( Id >= 0 ); return Id == 0; }
+static int      Mini_AigNodeIsPi( Mini_Aig_t * p, int Id )     { assert( Id >= 0 ); return Id > 0 && Mini_AigNodeFanin0( p, Id ) == MINI_AIG_NULL; }
+static int      Mini_AigNodeIsPo( Mini_Aig_t * p, int Id )     { assert( Id >= 0 ); return Id > 0 && Mini_AigNodeFanin0( p, Id ) != MINI_AIG_NULL && Mini_AigNodeFanin1( p, Id ) == MINI_AIG_NULL; }
+static int      Mini_AigNodeIsAnd( Mini_Aig_t * p, int Id )    { assert( Id >= 0 ); return Id > 0 && Mini_AigNodeFanin0( p, Id ) != MINI_AIG_NULL && Mini_AigNodeFanin1( p, Id ) != MINI_AIG_NULL; }
+
+// working with sequential AIGs
+static int      Mini_AigRegNum( Mini_Aig_t * p )               { return p->nRegs;             }
+static void     Mini_AigSetRegNum( Mini_Aig_t * p, int n )     { p->nRegs = n;                }
+
+// iterators through objects
+#define Mini_AigForEachPi( p, i )  for (i = 1; i < Mini_AigNodeNum(p); i++) if ( !Mini_AigNodeIsPi(p, i) ) {} else 
+#define Mini_AigForEachPo( p, i )  for (i = 1; i < Mini_AigNodeNum(p); i++) if ( !Mini_AigNodeIsPo(p, i) ) {} else 
+#define Mini_AigForEachAnd( p, i ) for (i = 1; i < Mini_AigNodeNum(p); i++) if ( !Mini_AigNodeIsAnd(p, i) ) {} else
+
+
+// constructor/destructor
+static Mini_Aig_t * Mini_AigStart()
+{
+    Mini_Aig_t * p;
+    p = MINI_AIG_CALLOC( Mini_Aig_t, 1 );
+    p->nCap   = MINI_AIG_START_SIZE;
+    p->pArray = MINI_AIG_ALLOC( int, p->nCap );
+    Mini_AigPush( p, MINI_AIG_NULL, MINI_AIG_NULL );
+    return p;
+}
+static void Mini_AigStop( Mini_Aig_t * p )
+{
+    MINI_AIG_FREE( p->pArray );
+    MINI_AIG_FREE( p );
+}
+static void Mini_AigPrintStats( Mini_Aig_t * p )
+{
+    int i, nPis, nPos, nNodes;
+    nPis = 0;
+    Mini_AigForEachPi( p, i )
+        nPis++;
+    nPos = 0;
+    Mini_AigForEachPo( p, i )
+        nPos++;
+    nNodes = 0;
+    Mini_AigForEachAnd( p, i )
+        nNodes++;
+    printf( "PI = %d. PO = %d. Node = %d.\n", nPis, nPos, nNodes );
+}
+
+// serialization
+static void Mini_AigDump( Mini_Aig_t * p, char * pFileName )
+{
+    FILE * pFile;
+    int RetValue;
+    pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file for writing \"%s\".\n", pFileName );
+        return;
+    }
+    RetValue = fwrite( &p->nSize, sizeof(int), 1, pFile );
+    RetValue = fwrite( &p->nRegs, sizeof(int), 1, pFile );
+    RetValue = fwrite( p->pArray, sizeof(int), p->nSize, pFile );
+    fclose( pFile );
+}
+static Mini_Aig_t * Mini_AigLoad( char * pFileName )
+{
+    Mini_Aig_t * p;
+    FILE * pFile;
+    int RetValue, nSize;
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file for reading \"%s\".\n", pFileName );
+        return NULL;
+    }
+    RetValue = fread( &nSize, sizeof(int), 1, pFile );
+    p = MINI_AIG_CALLOC( Mini_Aig_t, 1 );
+    p->nSize = p->nCap = nSize;
+    p->pArray = MINI_AIG_ALLOC( int, p->nCap );
+    RetValue = fread( &p->nRegs, sizeof(int), 1, pFile );
+    RetValue = fread( p->pArray, sizeof(int), p->nSize, pFile );
+    fclose( pFile );
+    return p;
+}
+
+
+// creating nodes 
+// (constant node is created when AIG manager is created)
+static int Mini_AigCreatePi( Mini_Aig_t * p )
+{
+    int Lit = p->nSize;
+    Mini_AigPush( p, MINI_AIG_NULL, MINI_AIG_NULL );
+    return Lit;
+}
+static int Mini_AigCreatePo( Mini_Aig_t * p, int Lit0 )
+{
+    int Lit = p->nSize;
+    assert( Lit0 >= 0 && Lit0 < Lit );
+    Mini_AigPush( p, Lit0, MINI_AIG_NULL );
+    return Lit;
+}
+
+// boolean operations
+static int Mini_AigAnd( Mini_Aig_t * p, int Lit0, int Lit1 )
+{
+    int Lit = p->nSize;
+    assert( Lit0 >= 0 && Lit0 < Lit );
+    assert( Lit1 >= 0 && Lit1 < Lit );
+    Mini_AigPush( p, Lit0, Lit1 );
+    return Lit;
+}
+static int Mini_AigOr( Mini_Aig_t * p, int Lit0, int Lit1 )
+{
+    return Mini_AigLitNot( Mini_AigAnd( p, Mini_AigLitNot(Lit0), Mini_AigLitNot(Lit1) ) );
+}
+static int Mini_AigMux( Mini_Aig_t * p, int LitC, int Lit1, int Lit0 )
+{
+    int Res0 = Mini_AigAnd( p, LitC, Lit1 );
+    int Res1 = Mini_AigAnd( p, Mini_AigLitNot(LitC), Lit0 );
+    return Mini_AigOr( p, Res0, Res1 );
+}
+static int Mini_AigXor( Mini_Aig_t * p, int Lit0, int Lit1 )
+{
+    return Mini_AigMux( p, Lit0, Mini_AigLitNot(Lit1), Lit1 );
+}
+
+// procedure to check the topological order during AIG construction
+static int Mini_AigCheck( Mini_Aig_t * p )
+{
+    int status = 1;
+    int i, iFaninLit0, iFaninLit1;
+    Mini_AigForEachAnd( p, i )
+    {
+        // get the fanin literals of this AND node
+        iFaninLit0 = Mini_AigNodeFanin0( p, i );
+        iFaninLit1 = Mini_AigNodeFanin1( p, i );
+        // compare the fanin literals with the literal of the current node (2 * i)
+        if ( iFaninLit0 >= 2 * i )
+            printf( "Fanin0 of AND node %d is not in a topological order.\n", i ), status = 0;
+        if ( iFaninLit1 >= 2 * i )
+            printf( "Fanin0 of AND node %d is not in a topological order.\n", i ), status = 0;
+    }
+    Mini_AigForEachPo( p, i )
+    {
+        // get the fanin literal of this PO node
+        iFaninLit0 = Mini_AigNodeFanin0( p, i );
+        // compare the fanin literal with the literal of the current node (2 * i)
+        if ( iFaninLit0 >= 2 * i )
+            printf( "Fanin0 of PO node %d is not in a topological order.\n", i ), status = 0;
+    }
+    return status;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/aig/miniaig/module.make b/abc-build/src/aig/miniaig/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/miniaig/module.make
@@ -0,0 +1,1 @@
+SRC += 
diff --git a/abc-build/src/aig/saig/module.make b/abc-build/src/aig/saig/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/module.make
@@ -0,0 +1,26 @@
+SRC +=  src/aig/saig/saigCone.c \
+	src/aig/saig/saigConstr.c \
+	src/aig/saig/saigConstr2.c \
+	src/aig/saig/saigDual.c \
+	src/aig/saig/saigDup.c \
+	src/aig/saig/saigInd.c \
+	src/aig/saig/saigIoa.c \
+	src/aig/saig/saigIso.c \
+	src/aig/saig/saigIsoFast.c \
+	src/aig/saig/saigIsoSlow.c \
+	src/aig/saig/saigMiter.c \
+	src/aig/saig/saigOutDec.c \
+	src/aig/saig/saigPhase.c \
+	src/aig/saig/saigRetFwd.c \
+	src/aig/saig/saigRetMin.c \
+	src/aig/saig/saigRetStep.c \
+	src/aig/saig/saigScl.c \
+	src/aig/saig/saigSimFast.c \
+	src/aig/saig/saigSimMv.c \
+	src/aig/saig/saigSimSeq.c \
+	src/aig/saig/saigStrSim.c \
+	src/aig/saig/saigSwitch.c \
+	src/aig/saig/saigSynch.c \
+	src/aig/saig/saigTempor.c \
+	src/aig/saig/saigTrans.c \
+	src/aig/saig/saigWnd.c
diff --git a/abc-build/src/aig/saig/saig.h b/abc-build/src/aig/saig/saig.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saig.h
@@ -0,0 +1,200 @@
+/**CFile****************************************************************
+
+  FileName    [saig.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saig.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__saig__saig_h
+#define ABC__aig__saig__saig_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "aig/aig/aig.h"
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Sec_MtrStatus_t_ Sec_MtrStatus_t;
+struct Sec_MtrStatus_t_
+{
+    int         nInputs;      // the total number of inputs
+    int         nNodes;       // the total number of nodes
+    int         nOutputs;     // the total number of outputs
+    int         nUnsat;       // the number of UNSAT outputs
+    int         nSat;         // the number of SAT outputs
+    int         nUndec;       // the number of undecided outputs
+    int         iOut;         // the satisfied output
+}; 
+ 
+typedef struct Saig_ParBbr_t_ Saig_ParBbr_t;
+struct Saig_ParBbr_t_
+{
+    int         TimeLimit;
+    int         nBddMax;
+    int         nIterMax;
+    int         fPartition;
+    int         fReorder;
+    int         fReorderImage;
+    int         fVerbose;
+    int         fSilent;
+    int         fSkipOutCheck;// skip output checking
+    int         iFrame;       // explored up to this frame
+};
+
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int          Saig_ManPiNum( Aig_Man_t * p )                     { return p->nTruePis;                     }
+static inline int          Saig_ManPoNum( Aig_Man_t * p )                     { return p->nTruePos;                     }
+static inline int          Saig_ManCiNum( Aig_Man_t * p )                     { return p->nTruePis + p->nRegs;          }
+static inline int          Saig_ManCoNum( Aig_Man_t * p )                     { return p->nTruePos + p->nRegs;          }
+static inline int          Saig_ManRegNum( Aig_Man_t * p )                    { return p->nRegs;                        }
+static inline int          Saig_ManConstrNum( Aig_Man_t * p )                 { return p->nConstrs;                     }
+static inline Aig_Obj_t *  Saig_ManLo( Aig_Man_t * p, int i )                 { return (Aig_Obj_t *)Vec_PtrEntry(p->vCis, Saig_ManPiNum(p)+i);   }
+static inline Aig_Obj_t *  Saig_ManLi( Aig_Man_t * p, int i )                 { return (Aig_Obj_t *)Vec_PtrEntry(p->vCos, Saig_ManPoNum(p)+i);   }
+
+static inline int          Saig_ObjIsPi( Aig_Man_t * p, Aig_Obj_t * pObj )    { return Aig_ObjIsCi(pObj) && Aig_ObjCioId(pObj) < Saig_ManPiNum(p); }
+static inline int          Saig_ObjIsPo( Aig_Man_t * p, Aig_Obj_t * pObj )    { return Aig_ObjIsCo(pObj) && Aig_ObjCioId(pObj) < Saig_ManPoNum(p); }
+static inline int          Saig_ObjIsLo( Aig_Man_t * p, Aig_Obj_t * pObj )    { return Aig_ObjIsCi(pObj) && Aig_ObjCioId(pObj) >= Saig_ManPiNum(p); }
+static inline int          Saig_ObjIsLi( Aig_Man_t * p, Aig_Obj_t * pObj )    { return Aig_ObjIsCo(pObj) && Aig_ObjCioId(pObj) >= Saig_ManPoNum(p); }
+static inline Aig_Obj_t *  Saig_ObjLoToLi( Aig_Man_t * p, Aig_Obj_t * pObj )  { assert(Saig_ObjIsLo(p, pObj)); return (Aig_Obj_t *)Vec_PtrEntry(p->vCos, Saig_ManPoNum(p)+Aig_ObjCioId(pObj)-Saig_ManPiNum(p));   }
+static inline Aig_Obj_t *  Saig_ObjLiToLo( Aig_Man_t * p, Aig_Obj_t * pObj )  { assert(Saig_ObjIsLi(p, pObj)); return (Aig_Obj_t *)Vec_PtrEntry(p->vCis, Saig_ManPiNum(p)+Aig_ObjCioId(pObj)-Saig_ManPoNum(p));   }
+static inline int          Saig_ObjRegId( Aig_Man_t * p, Aig_Obj_t * pObj )   { if ( Saig_ObjIsLo(p, pObj) ) return Aig_ObjCioId(pObj)-Saig_ManPiNum(p); if ( Saig_ObjIsLi(p, pObj) ) return Aig_ObjCioId(pObj)-Saig_ManPoNum(p); else assert(0);  return -1; }
+
+// iterator over the primary inputs/outputs
+#define Saig_ManForEachPi( p, pObj, i )                                           \
+    Vec_PtrForEachEntryStop( Aig_Obj_t *, p->vCis, pObj, i, Saig_ManPiNum(p) )
+#define Saig_ManForEachPo( p, pObj, i )                                           \
+    Vec_PtrForEachEntryStop( Aig_Obj_t *, p->vCos, pObj, i, Saig_ManPoNum(p) )
+// iterator over the latch inputs/outputs
+#define Saig_ManForEachLo( p, pObj, i )                                           \
+    for ( i = 0; (i < Saig_ManRegNum(p)) && (((pObj) = (Aig_Obj_t *)Vec_PtrEntry(p->vCis, i+Saig_ManPiNum(p))), 1); i++ )
+#define Saig_ManForEachLi( p, pObj, i )                                           \
+    for ( i = 0; (i < Saig_ManRegNum(p)) && (((pObj) = (Aig_Obj_t *)Vec_PtrEntry(p->vCos, i+Saig_ManPoNum(p))), 1); i++ )
+// iterator over the latch input and outputs
+#define Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )                               \
+    for ( i = 0; (i < Saig_ManRegNum(p)) && (((pObjLi) = Saig_ManLi(p, i)), 1)    \
+        && (((pObjLo)=Saig_ManLo(p, i)), 1); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== saigCone.c ==========================================================*/
+extern void              Saig_ManPrintCones( Aig_Man_t * p );
+/*=== saigConstr.c ==========================================================*/
+extern Aig_Man_t *       Saig_ManDupUnfoldConstrs( Aig_Man_t * pAig );
+extern Aig_Man_t *       Saig_ManDupFoldConstrs( Aig_Man_t * pAig, Vec_Int_t * vConstrs );
+extern int               Saig_ManDetectConstrTest( Aig_Man_t * p );
+extern void              Saig_ManDetectConstrFuncTest( Aig_Man_t * p, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose );
+/*=== saigConstr2.c ==========================================================*/
+extern Aig_Man_t *       Saig_ManDupFoldConstrsFunc( Aig_Man_t * pAig, int fCompl, int fVerbose );
+extern Aig_Man_t *       Saig_ManDupUnfoldConstrsFunc( Aig_Man_t * pAig, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose );
+// -- jlong -- begin
+extern Aig_Man_t *       Saig_ManDupFoldConstrsFunc2( Aig_Man_t * pAig, int fCompl, int fVerbose, int typeII_cnt );
+extern Aig_Man_t *       Saig_ManDupUnfoldConstrsFunc2( Aig_Man_t * pAig, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose , int * typeII_cnt);
+// --jlong -- end
+
+/*=== saigDual.c ==========================================================*/
+extern Aig_Man_t *       Saig_ManDupDual( Aig_Man_t * pAig, Vec_Int_t * vDcFlops, int nDualPis, int fDualFfs, int fMiterFfs, int fComplPo, int fCheckZero, int fCheckOne );
+extern void              Saig_ManBlockPo( Aig_Man_t * pAig, int nCycles );
+/*=== saigDup.c ==========================================================*/
+extern Aig_Man_t *       Saig_ManDupOrpos( Aig_Man_t * p );
+extern Aig_Man_t *       Saig_ManCreateEquivMiter( Aig_Man_t * pAig, Vec_Int_t * vPairs );
+extern Aig_Man_t *       Saig_ManDupAbstraction( Aig_Man_t * pAig, Vec_Int_t * vFlops );
+extern int               Saig_ManVerifyCex( Aig_Man_t * pAig, Abc_Cex_t * p );
+extern Abc_Cex_t *       Saig_ManExtendCex( Aig_Man_t * pAig, Abc_Cex_t * p );
+extern int               Saig_ManFindFailedPoCex( Aig_Man_t * pAig, Abc_Cex_t * p );
+extern Aig_Man_t *       Saig_ManDupWithPhase( Aig_Man_t * pAig, Vec_Int_t * vInit );
+extern Aig_Man_t *       Saig_ManDupCones( Aig_Man_t * pAig, int * pPos, int nPos );
+/*=== saigHaig.c ==========================================================*/
+extern Aig_Man_t *       Saig_ManHaigRecord( Aig_Man_t * p, int nIters, int nSteps, int fRetimingOnly, int fAddBugs, int fUseCnf, int fVerbose );
+/*=== saigInd.c ==========================================================*/
+extern int               Saig_ManInduction( Aig_Man_t * p, int nTimeOut, int nFramesMax, int nConfMax, int fUnique, int fUniqueAll, int fGetCex, int fVerbose, int fVeryVerbose );
+/*=== saigIoa.c ==========================================================*/
+extern void              Saig_ManDumpBlif( Aig_Man_t * p, char * pFileName );
+extern Aig_Man_t *       Saig_ManReadBlif( char * pFileName );
+/*=== saigIso.c ==========================================================*/
+extern Vec_Int_t *       Saig_ManFindIsoPerm( Aig_Man_t * pAig, int fVerbose );
+extern Aig_Man_t *       Saig_ManDupIsoCanonical( Aig_Man_t * pAig, int fVerbose );
+extern Aig_Man_t *       Saig_ManIsoReduce( Aig_Man_t * pAig, Vec_Ptr_t ** pvCosEquivs, int fVerbose );
+/*=== saigIsoFast.c ==========================================================*/
+extern Vec_Vec_t *       Saig_IsoDetectFast( Aig_Man_t * pAig );
+/*=== saigMiter.c ==========================================================*/
+extern Sec_MtrStatus_t   Sec_MiterStatus( Aig_Man_t * p );
+extern Aig_Man_t *       Saig_ManCreateMiter( Aig_Man_t * p1, Aig_Man_t * p2, int Oper );
+extern Aig_Man_t *       Saig_ManCreateMiterComb( Aig_Man_t * p1, Aig_Man_t * p2, int Oper );
+extern Aig_Man_t *       Saig_ManDualRail( Aig_Man_t * p, int fMiter );
+extern Aig_Man_t *       Saig_ManCreateMiterTwo( Aig_Man_t * pOld, Aig_Man_t * pNew, int nFrames );
+extern int               Saig_ManDemiterSimple( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 );
+extern int               Saig_ManDemiterSimpleDiff( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 );
+extern int               Saig_ManDemiterDual( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 );
+extern int               Ssw_SecSpecialMiter( Aig_Man_t * p0, Aig_Man_t * p1, int nFrames, int fVerbose );
+extern int               Saig_ManDemiterNew( Aig_Man_t * pMan );
+/*=== saigOutdec.c ==========================================================*/
+extern Aig_Man_t *       Saig_ManDecPropertyOutput( Aig_Man_t * pAig, int nLits, int fVerbose );
+/*=== saigPhase.c ==========================================================*/
+extern Aig_Man_t *       Saig_ManPhaseAbstract( Aig_Man_t * p, Vec_Int_t * vInits, int nFrames, int nPref, int fIgnore, int fPrint, int fVerbose );
+/*=== saigRetFwd.c ==========================================================*/
+extern void              Saig_ManMarkAutonomous( Aig_Man_t * p );
+extern Aig_Man_t *       Saig_ManRetimeForward( Aig_Man_t * p, int nMaxIters, int fVerbose );
+/*=== saigRetMin.c ==========================================================*/
+extern Aig_Man_t *       Saig_ManRetimeDupForward( Aig_Man_t * p, Vec_Ptr_t * vCut );
+extern Aig_Man_t *       Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose );
+/*=== saigRetStep.c ==========================================================*/
+extern int               Saig_ManRetimeSteps( Aig_Man_t * p, int nSteps, int fForward, int fAddBugs );
+/*=== saigScl.c ==========================================================*/
+extern void              Saig_ManReportUselessRegisters( Aig_Man_t * pAig );
+/*=== saigSimMv.c ==========================================================*/
+extern Vec_Ptr_t *       Saig_MvManSimulate( Aig_Man_t * pAig, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose );
+/*=== saigStrSim.c ==========================================================*/
+extern Vec_Int_t *       Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter );
+/*=== saigSwitch.c ==========================================================*/
+extern Vec_Int_t *       Saig_ManComputeSwitchProb2s( Aig_Man_t * p, int nFrames, int nPref, int fProbOne );
+/*=== saigSynch.c ==========================================================*/
+extern Aig_Man_t *       Saig_ManDupInitZero( Aig_Man_t * p );
+/*=== saigTrans.c ==========================================================*/
+extern Aig_Man_t *       Saig_ManTimeframeSimplify( Aig_Man_t * pAig, int nFrames, int nFramesMax, int fInit, int fVerbose );
+/*=== saigWnd.c ==========================================================*/
+extern Aig_Man_t *       Saig_ManWindowExtract( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist );
+extern Aig_Man_t *       Saig_ManWindowInsert( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist, Aig_Man_t * pWnd );
+extern Aig_Obj_t *       Saig_ManFindPivot( Aig_Man_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/aig/saig/saigCone.c b/abc-build/src/aig/saig/saigCone.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigCone.c
@@ -0,0 +1,181 @@
+/**CFile****************************************************************
+
+  FileName    [saigCone.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Cone of influence computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigCone.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the support size of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManSupport_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vSupp )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Aig_ObjIsConst1(pObj) )
+        return;
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        if ( Saig_ObjIsLo(p,pObj) )
+        {
+            pObj = Saig_ManLi( p, Aig_ObjCioId(pObj)-Saig_ManPiNum(p) );
+            Vec_PtrPush( vSupp, pObj );
+        }
+        return;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    Saig_ManSupport_rec( p, Aig_ObjFanin0(pObj), vSupp );
+    Saig_ManSupport_rec( p, Aig_ObjFanin1(pObj), vSupp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the support size of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_ManSupport( Aig_Man_t * p, Vec_Ptr_t * vNodes )
+{
+    Vec_Ptr_t * vSupp;
+    Aig_Obj_t * pObj;
+    int i;
+    vSupp = Vec_PtrAlloc( 100 );
+    Aig_ManIncrementTravId( p );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        assert( Aig_ObjIsCo(pObj) );
+        Saig_ManSupport_rec( p, Aig_ObjFanin0(pObj), vSupp );
+    }
+    return vSupp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints information about cones of influence of the POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManPrintConeOne( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Vec_Ptr_t * vPrev, * vCur, * vTotal;
+    int s, i, nCurNew, nCurPrev, nCurOld;
+    assert( Saig_ObjIsPo(p, pObj) );
+    // start the array
+    vPrev = Vec_PtrAlloc( 100 );
+    Vec_PtrPush( vPrev, pObj );
+    // get the current support
+    vCur = Saig_ManSupport( p, vPrev );  
+    Vec_PtrClear( vPrev );
+    printf( "    PO %3d  ", Aig_ObjCioId(pObj) );
+    // continue computing supports as long as there are now nodes
+    vTotal = Vec_PtrAlloc( 100 );
+    for ( s = 0; ; s++ )
+    {
+        // classify current into those new, prev, and older 
+        nCurNew = nCurPrev = nCurOld = 0;
+        Vec_PtrForEachEntry( Aig_Obj_t *, vCur, pObj, i )
+        {
+            if ( Vec_PtrFind(vTotal, pObj) == -1 )
+            {
+                Vec_PtrPush( vTotal, pObj );
+                nCurNew++;
+            }
+            else if ( Vec_PtrFind(vPrev, pObj) >= 0 )
+                nCurPrev++;
+            else
+                nCurOld++;
+        }
+        assert( nCurNew + nCurPrev + nCurOld == Vec_PtrSize(vCur) );
+        // print the result
+        printf( "%d:%d %d=%d+%d+%d  ", s, Vec_PtrSize(vTotal), Vec_PtrSize(vCur), nCurNew, nCurPrev, nCurOld ); 
+        if ( nCurNew == 0 )
+            break;
+        // compute one more step
+        Vec_PtrFree( vPrev );
+        vCur = Saig_ManSupport( p, vPrev = vCur );
+    }
+    printf( "\n" );
+    Vec_PtrFree( vPrev );
+    Vec_PtrFree( vCur );
+    Vec_PtrFree( vTotal );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints information about cones of influence of the POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManPrintCones( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    printf( "The format of this print-out: For each PO, x:a b=c+d+e, where \n" );
+    printf( "- x is the time-frame counting back from the PO\n" );
+    printf( "- a is the total number of registers in the COI of the PO so far\n" );
+    printf( "- b is the number of registers in the COI of the PO in this time-frame\n" );
+    printf( "- c is the number of registers in b that are new (appear for the first time)\n" );
+    printf( "- d is the number of registers in b in common with the previous time-frame\n" );
+    printf( "- e is the number of registers in b in common with other time-frames\n" );
+    Aig_ManSetCioIds( p );
+    Saig_ManForEachPo( p, pObj, i )
+        Saig_ManPrintConeOne( p, pObj );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigConstr.c b/abc-build/src/aig/saig/saigConstr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigConstr.c
@@ -0,0 +1,484 @@
+/**CFile****************************************************************
+
+  FileName    [saigConstr.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Structural constraint detection.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigConstr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver.h"
+#include "bool/kit/kit.h"
+#include "aig/ioa/ioa.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/*
+    Property holds iff it is const 0.
+    Constraint holds iff it is const 0.
+
+    The following structure is used for folding constraints:
+    - the output of OR gate is 0 as long as all constraints hold
+    - as soon as one constraint fail, the property output becomes 0 forever
+      because the flop becomes 1 and it stays 1 forever
+
+
+       property output
+
+             |
+          |-----|
+          | and |
+          |-----|
+           |   |
+           |  / \
+           | /inv\
+           | -----
+       ____|   |_________________________
+       |             |                  |
+      / \       -----------             |   
+     /   \      |   or    |             |
+    /     \     -----------             |
+   / logic \     |   |   |              |
+  /  cone   \    |   |   |              |
+ /___________\   |   |   |              |
+                 |   | ------           |   
+                 |   | |flop| (init=0)  |
+                 |   | ------           |
+                 |   |   |              |
+                 |   |   |______________| 
+                 |   |
+                 c1  c2 
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_DetectConstrCollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper )
+{
+    // if the new node is complemented or a PI, another gate begins
+    if ( Aig_IsComplement(pObj) || !Aig_ObjIsNode(pObj) )//|| (Aig_ObjRefs(pObj) > 1) )
+    {
+        Vec_PtrPushUnique( vSuper, Aig_Not(pObj) );
+        return;
+    }
+    // go through the branches
+    Saig_DetectConstrCollectSuper_rec( Aig_ObjChild0(pObj), vSuper );
+    Saig_DetectConstrCollectSuper_rec( Aig_ObjChild1(pObj), vSuper );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_DetectConstrCollectSuper( Aig_Obj_t * pObj )
+{
+    Vec_Ptr_t * vSuper;
+    assert( !Aig_IsComplement(pObj) );
+    assert( Aig_ObjIsAnd(pObj) );
+    vSuper = Vec_PtrAlloc( 4 );
+    Saig_DetectConstrCollectSuper_rec( Aig_ObjChild0(pObj), vSuper );
+    Saig_DetectConstrCollectSuper_rec( Aig_ObjChild1(pObj), vSuper );
+    return vSuper;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns NULL if not contained, or array with unique entries.]
+
+  Description [Returns NULL if vSuper2 is not contained in vSuper. Otherwise
+  returns the array of entries in vSuper that are not found in vSuper2.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_ManDetectConstrCheckCont( Vec_Ptr_t * vSuper, Vec_Ptr_t * vSuper2 )
+{
+    Vec_Ptr_t * vUnique;
+    Aig_Obj_t * pObj, * pObj2;
+    int i;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSuper2, pObj2, i )
+        if ( Vec_PtrFind( vSuper, pObj2 ) == -1 )
+            return 0;
+    vUnique = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pObj, i )
+        if ( Vec_PtrFind( vSuper2, pObj ) == -1 )
+            Vec_PtrPush( vUnique, pObj );
+    return vUnique;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detects constraints using structural methods.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManDetectConstr( Aig_Man_t * p, int iOut, Vec_Ptr_t ** pvOuts, Vec_Ptr_t ** pvCons )
+{
+    Vec_Ptr_t * vSuper, * vSuper2 = NULL, * vUnique;
+    Aig_Obj_t * pObj, * pObj2, * pFlop;
+    int i, nFlops, RetValue;
+    assert( iOut >= 0 && iOut < Saig_ManPoNum(p) );
+    *pvOuts = NULL;
+    *pvCons = NULL;
+    pObj = Aig_ObjChild0( Aig_ManCo(p, iOut) );
+    if ( pObj == Aig_ManConst0(p) )
+    {
+        vUnique = Vec_PtrStart( 1 );
+        Vec_PtrWriteEntry( vUnique, 0, Aig_ManConst1(p) );
+        *pvOuts = vUnique;
+        *pvCons = Vec_PtrAlloc( 0 );
+        return -1;
+    }
+    if ( Aig_IsComplement(pObj) || !Aig_ObjIsNode(pObj) )
+    {
+        printf( "The output is not an AND.\n" );
+        return 0;
+    }
+    vSuper = Saig_DetectConstrCollectSuper( pObj );
+    assert( Vec_PtrSize(vSuper) >= 2 );
+    nFlops = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pObj, i )
+        nFlops += Saig_ObjIsLo( p, Aig_Regular(pObj) );
+    if ( nFlops == 0 )
+    {
+        printf( "There is no flop outputs.\n" );
+        Vec_PtrFree( vSuper );
+        return 0;
+    }
+    // try flops 
+    vUnique = NULL;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pObj, i )
+    {
+        pFlop = Aig_Regular( pObj );
+        if ( !Saig_ObjIsLo(p, pFlop) )
+            continue;
+        pFlop = Saig_ObjLoToLi( p, pFlop );
+        pObj2 = Aig_ObjChild0( pFlop );
+        if ( !Aig_IsComplement(pObj2) || !Aig_ObjIsNode(Aig_Regular(pObj2)) )
+            continue;
+        vSuper2 = Saig_DetectConstrCollectSuper( Aig_Regular(pObj2) );
+        // every node in vSuper2 should appear in vSuper
+        vUnique = Saig_ManDetectConstrCheckCont( vSuper, vSuper2 );
+        if ( vUnique != NULL )
+        {
+///           assert( !Aig_IsComplement(pObj) );
+ //           assert( Vec_PtrFind( vSuper2, pObj ) >= 0 );
+            if ( Aig_IsComplement(pObj) )
+            {
+                printf( "Special flop input is complemented.\n" );
+                Vec_PtrFreeP( &vUnique );
+                Vec_PtrFree( vSuper2 );
+                break;
+            }
+            if ( Vec_PtrFind( vSuper2, pObj ) == -1 )
+            {
+                printf( "Cannot find special flop about the inputs of OR gate.\n" );
+                Vec_PtrFreeP( &vUnique );
+                Vec_PtrFree( vSuper2 );
+                break;
+            }
+            // remove the flop output
+            Vec_PtrRemove( vSuper2, pObj );
+            break;
+        }
+        Vec_PtrFree( vSuper2 );
+    }
+    Vec_PtrFree( vSuper );
+    if ( vUnique == NULL )
+    {
+        printf( "There is no structural constraints.\n" );
+        return 0;
+    }
+    // vUnique contains unique entries
+    // vSuper2 contains the supergate
+    printf( "Output %d : Structural analysis found %d original properties and %d constraints.\n", 
+        iOut, Vec_PtrSize(vUnique), Vec_PtrSize(vSuper2) );
+    // remember the number of constraints
+    RetValue = Vec_PtrSize(vSuper2);
+    // make the AND of properties 
+//    Vec_PtrFree( vUnique );
+//    Vec_PtrFree( vSuper2 );
+    *pvOuts = vUnique;
+    *pvCons = vSuper2;
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure used for sorting nodes by ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManDupCompare( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 )
+{
+    int Diff = Aig_ObjToLit(*pp1) - Aig_ObjToLit(*pp2);
+    if ( Diff < 0 )
+        return -1;
+    if ( Diff > 0 ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG while unfolding constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManDupUnfoldConstrs( Aig_Man_t * pAig )
+{
+    Vec_Ptr_t * vOutsAll, * vConsAll;
+    Vec_Ptr_t * vOuts, * vCons, * vCons0;
+    Aig_Man_t * pAigNew;
+    Aig_Obj_t * pMiter, * pObj;
+    int i, k, RetValue;
+    // detect constraints for each output
+    vOutsAll = Vec_PtrAlloc( Saig_ManPoNum(pAig) );
+    vConsAll = Vec_PtrAlloc( Saig_ManPoNum(pAig) );
+    Saig_ManForEachPo( pAig, pObj, i )
+    {
+        RetValue = Saig_ManDetectConstr( pAig, i, &vOuts, &vCons );
+        if ( RetValue == 0 )
+        {
+            Vec_PtrFreeP( &vOuts );
+            Vec_PtrFreeP( &vCons );
+            Vec_VecFree( (Vec_Vec_t *)vOutsAll );
+            Vec_VecFree( (Vec_Vec_t *)vConsAll );
+            return Aig_ManDupDfs( pAig );
+        }
+        Vec_PtrSort( vOuts, (int (*)(void))Saig_ManDupCompare );
+        Vec_PtrSort( vCons, (int (*)(void))Saig_ManDupCompare );
+        Vec_PtrPush( vOutsAll, vOuts );
+        Vec_PtrPush( vConsAll, vCons );
+    }
+    // check if constraints are compatible
+    vCons0 = (Vec_Ptr_t *)Vec_PtrEntry( vConsAll, 0 );
+    Vec_PtrForEachEntry( Vec_Ptr_t *, vConsAll, vCons, i )
+        if ( Vec_PtrSize(vCons) )
+            vCons0 = vCons;
+    Vec_PtrForEachEntry( Vec_Ptr_t *, vConsAll, vCons, i )
+    {
+        // Constant 0 outputs are always compatible (vOuts stores the negation)
+        vOuts = (Vec_Ptr_t *)Vec_PtrEntry( vOutsAll, i );
+        if ( Vec_PtrSize(vOuts) == 1 && (Aig_Obj_t *)Vec_PtrEntry( vOuts, 0 ) == Aig_ManConst1(pAig) )
+            continue;
+        if ( !Vec_PtrEqual(vCons0, vCons) )
+            break;
+    }
+    if ( i < Vec_PtrSize(vConsAll) )
+    {
+        printf( "Collected constraints are not compatible.\n" );
+        Vec_VecFree( (Vec_Vec_t *)vOutsAll );
+        Vec_VecFree( (Vec_Vec_t *)vConsAll );
+        return Aig_ManDupDfs( pAig );
+    }
+
+    // start the new manager
+    pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) );
+    pAigNew->pName = Abc_UtilStrsav( pAig->pName );
+    // map the constant node
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew );
+    // create variables for PIs
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pAigNew );
+    // add internal nodes of this frame
+    Aig_ManForEachNode( pAig, pObj, i )
+        pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // transform each output
+    Vec_PtrForEachEntry( Vec_Ptr_t *, vOutsAll, vOuts, i )
+    {
+        // AND the outputs
+        pMiter = Aig_ManConst1( pAigNew );
+        Vec_PtrForEachEntry( Aig_Obj_t *, vOuts, pObj, k )
+            pMiter = Aig_And( pAigNew, pMiter, Aig_Not(Aig_ObjRealCopy(pObj)) );
+        Aig_ObjCreateCo( pAigNew, pMiter );
+    }
+    // add constraints
+    pAigNew->nConstrs = Vec_PtrSize(vCons0);
+    Vec_PtrForEachEntry( Aig_Obj_t *, vCons0, pObj, i )
+        Aig_ObjCreateCo( pAigNew, Aig_ObjRealCopy(pObj) );
+    // transfer to register outputs
+    Saig_ManForEachLi( pAig, pObj, i )
+        Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) );
+//    Vec_PtrFreeP( &vOuts );
+//    Vec_PtrFreeP( &vCons );
+    Vec_VecFree( (Vec_Vec_t *)vOutsAll );
+    Vec_VecFree( (Vec_Vec_t *)vConsAll );
+
+    Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) );
+    Aig_ManCleanup( pAigNew );
+    Aig_ManSeqCleanup( pAigNew );
+    return pAigNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG while folding in the constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManDupFoldConstrs( Aig_Man_t * pAig, Vec_Int_t * vConstrs )
+{
+    Aig_Man_t * pAigNew;
+    Aig_Obj_t * pMiter, * pFlopOut, * pFlopIn, * pObj;
+    int Entry, i;
+    assert( Saig_ManRegNum(pAig) > 0 );
+    // start the new manager
+    pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) );
+    pAigNew->pName = Abc_UtilStrsav( pAig->pName );
+    // map the constant node
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew );
+    // create variables for PIs
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pAigNew );
+    // add internal nodes of this frame
+    Aig_ManForEachNode( pAig, pObj, i )
+        pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+
+    // OR the constraint outputs
+    pMiter = Aig_ManConst0( pAigNew );
+    Vec_IntForEachEntry( vConstrs, Entry, i )
+    {
+        assert( Entry > 0 && Entry < Saig_ManPoNum(pAig) );
+        pObj = Aig_ManCo( pAig, Entry );
+        pMiter = Aig_Or( pAigNew, pMiter, Aig_ObjChild0Copy(pObj) );
+    }
+    // create additional flop
+    pFlopOut = Aig_ObjCreateCi( pAigNew );
+    pFlopIn  = Aig_Or( pAigNew, pMiter, pFlopOut );
+
+    // create primary output
+    Saig_ManForEachPo( pAig, pObj, i )
+    {
+        pMiter = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_Not(pFlopIn) );
+        Aig_ObjCreateCo( pAigNew, pMiter );
+    }
+
+    // transfer to register outputs
+    Saig_ManForEachLi( pAig, pObj, i )
+        Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) );
+    // create additional flop 
+    Aig_ObjCreateCo( pAigNew, pFlopIn );
+
+    Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig)+1 );
+    Aig_ManCleanup( pAigNew );
+    Aig_ManSeqCleanup( pAigNew );
+    return pAigNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Tests the above two procedures.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManFoldConstrTest( Aig_Man_t * pAig )
+{
+    Aig_Man_t * pAig1, * pAig2;
+    Vec_Int_t * vConstrs;
+    // unfold constraints
+    pAig1 = Saig_ManDupUnfoldConstrs( pAig );
+    // create the constraint list
+    vConstrs = Vec_IntStartNatural( Saig_ManPoNum(pAig1) );
+    Vec_IntRemove( vConstrs, 0 );
+    // fold constraints back
+    pAig2 = Saig_ManDupFoldConstrs( pAig1, vConstrs );
+    Vec_IntFree( vConstrs );
+    // compare the two AIGs
+    Ioa_WriteAiger( pAig2, "test.aig", 0, 0 );
+    Aig_ManStop( pAig1 );
+    Aig_ManStop( pAig2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Experiment with the above procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManDetectConstrTest( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vOuts, * vCons;
+    int RetValue = Saig_ManDetectConstr( p, 0, &vOuts, &vCons );
+    Vec_PtrFreeP( &vOuts );
+    Vec_PtrFreeP( &vCons );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigConstr2.c b/abc-build/src/aig/saig/saigConstr2.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigConstr2.c
@@ -0,0 +1,1013 @@
+/**CFile****************************************************************
+
+  FileName    [saigConstr2.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Functional constraint detection.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigConstr2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver.h"
+#include "bool/kit/kit.h"
+#include "misc/bar/bar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline Aig_Obj_t * Aig_ObjFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i )                       { return pObjMap[nFs*pObj->Id + i];  }
+static inline void        Aig_ObjSetFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { pObjMap[nFs*pObj->Id + i] = pNode; }
+
+static inline Aig_Obj_t * Aig_ObjChild0Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin0(pObj)? Aig_NotCond(Aig_ObjFrames(pObjMap,nFs,Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL;  }
+static inline Aig_Obj_t * Aig_ObjChild1Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin1(pObj)? Aig_NotCond(Aig_ObjFrames(pObjMap,nFs,Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL;  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    [Returns the probability of POs being 1 under rand seq sim.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManProfileConstraints( Aig_Man_t * p, int nWords, int nFrames, int fVerbose )
+{
+    Vec_Ptr_t * vInfo;
+    Vec_Int_t * vProbs, * vProbs2;
+    Aig_Obj_t * pObj, * pObjLi;
+    unsigned * pInfo, * pInfo0, * pInfo1, * pInfoMask, * pInfoMask2;
+    int i, w, f, RetValue = 1;
+    abctime clk = Abc_Clock();
+    if ( fVerbose )
+        printf( "Simulating %d nodes and %d flops for %d frames with %d words... ", 
+            Aig_ManNodeNum(p), Aig_ManRegNum(p), nFrames, nWords );
+    Aig_ManRandom( 1 );
+    vInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p)+2, nWords );
+    Vec_PtrCleanSimInfo( vInfo, 0, nWords );
+    vProbs  = Vec_IntStart( Saig_ManPoNum(p) );
+    vProbs2 = Vec_IntStart( Saig_ManPoNum(p) );
+    // start the constant
+    pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(Aig_ManConst1(p)) );
+    for ( w = 0; w < nWords; w++ )
+        pInfo[w] = ~0;
+    // start the flop inputs
+    Saig_ManForEachLi( p, pObj, i )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) );
+        for ( w = 0; w < nWords; w++ )
+            pInfo[w] = 0;
+    }
+    // get the info mask
+    pInfoMask  = (unsigned *)Vec_PtrEntry( vInfo, Aig_ManObjNumMax(p) );    // PO failed
+    pInfoMask2 = (unsigned *)Vec_PtrEntry( vInfo, Aig_ManObjNumMax(p)+1 );  // constr failed
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // assign primary inputs
+        Saig_ManForEachPi( p, pObj, i )
+        {
+            pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) );
+            for ( w = 0; w < nWords; w++ )
+                pInfo[w] = Aig_ManRandom( 0 );
+        }
+        // move the flop values
+        Saig_ManForEachLiLo( p, pObjLi, pObj, i )
+        {
+            pInfo  = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) );
+            pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObjLi) );
+            for ( w = 0; w < nWords; w++ )
+                pInfo[w] = pInfo0[w];
+        }
+        // simulate the nodes
+        Aig_ManForEachNode( p, pObj, i )
+        {
+            pInfo  = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) );
+            pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjFaninId0(pObj) );
+            pInfo1 = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjFaninId1(pObj) );
+            if ( Aig_ObjFaninC0(pObj) )
+            {
+                if (  Aig_ObjFaninC1(pObj) )
+                    for ( w = 0; w < nWords; w++ )
+                        pInfo[w] = ~(pInfo0[w] | pInfo1[w]);
+                else 
+                    for ( w = 0; w < nWords; w++ )
+                        pInfo[w] = ~pInfo0[w] & pInfo1[w];
+            }
+            else 
+            {
+                if (  Aig_ObjFaninC1(pObj) )
+                    for ( w = 0; w < nWords; w++ )
+                        pInfo[w] = pInfo0[w] & ~pInfo1[w];
+                else 
+                    for ( w = 0; w < nWords; w++ )
+                        pInfo[w] = pInfo0[w] & pInfo1[w];
+            }
+        }
+        // clean the mask
+        for ( w = 0; w < nWords; w++ )
+            pInfoMask[w] = pInfoMask2[w] = 0;
+        // simulate the primary outputs
+        Aig_ManForEachCo( p, pObj, i )
+        {
+            pInfo  = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) );
+            pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjFaninId0(pObj) );
+            if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) || i >= Saig_ManPoNum(p) )
+            {
+                if ( Aig_ObjFaninC0(pObj) )
+                {
+                    for ( w = 0; w < nWords; w++ )
+                        pInfo[w] = ~pInfo0[w];
+                }
+                else 
+                {
+                    for ( w = 0; w < nWords; w++ )
+                        pInfo[w] = pInfo0[w];
+                }
+            }
+            else
+            {
+                if ( Aig_ObjFaninC0(pObj) )
+                {
+                    for ( w = 0; w < nWords; w++ )
+                        pInfo[w] |= ~pInfo0[w];
+                }
+                else 
+                {
+                    for ( w = 0; w < nWords; w++ )
+                        pInfo[w] |= pInfo0[w];
+                }
+            }
+            // collect patterns when one of the outputs fails
+            if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) )
+            {
+                for ( w = 0; w < nWords; w++ )
+                    pInfoMask[w] |= pInfo[w];
+            }
+            else if ( i < Saig_ManPoNum(p) )
+            {
+                for ( w = 0; w < nWords; w++ )
+                    pInfoMask2[w] |= pInfo[w];
+            }
+        }
+        // compare the PO values (mask=1 => out=0) or UNSAT(mask=1 & out=1)
+        Saig_ManForEachPo( p, pObj, i )
+        {
+            pInfo  = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) );
+            for ( w = 0; w < nWords; w++ )
+                Vec_IntAddToEntry( vProbs, i, Aig_WordCountOnes(pInfo[w]) );
+            if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) )
+            {
+                // chek the output
+                for ( w = 0; w < nWords; w++ )
+                    if ( pInfo[w] & ~pInfoMask2[w] ) 
+                        break;
+                if ( w == nWords )
+                    continue;
+                printf( "Primary output %d fails on some input patterns.\n", i );
+            }
+            else
+            {
+                // collect patterns that block the POs
+                for ( w = 0; w < nWords; w++ )
+                    Vec_IntAddToEntry( vProbs2, i, Aig_WordCountOnes(pInfo[w] & pInfoMask[w]) );
+            }
+        }
+    }
+    if ( fVerbose )
+        Abc_PrintTime( 1, "T", Abc_Clock() - clk );
+    // print the state
+    if ( fVerbose )
+    {
+        Saig_ManForEachPo( p, pObj, i )
+        {
+            if ( i < Saig_ManPoNum(p) - Saig_ManConstrNum(p) )
+                printf( "Primary output :  " );
+            else
+                printf( "Constraint %3d :  ", i-(Saig_ManPoNum(p) - Saig_ManConstrNum(p))  );
+            printf( "ProbOne = %f  ",  (float)Vec_IntEntry(vProbs,  i)/(32*nWords*nFrames) );
+            printf( "ProbOneC = %f  ", (float)Vec_IntEntry(vProbs2, i)/(32*nWords*nFrames) );
+            printf( "AllZeroValue = %d ", Aig_ObjPhase(pObj) );
+            printf( "\n" );
+        }
+    }
+
+    // print the states
+    Vec_PtrFree( vInfo );
+    Vec_IntFree( vProbs );
+    Vec_IntFree( vProbs2 );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates COI of the property output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManCreateIndMiter( Aig_Man_t * pAig, Vec_Vec_t * vCands )
+{
+    int nFrames = 2;
+    Vec_Ptr_t * vNodes;
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew;
+    Aig_Obj_t ** pObjMap;
+    int i, f, k;
+
+    // create mapping for the frames nodes
+    pObjMap  = ABC_CALLOC( Aig_Obj_t *, nFrames * Aig_ManObjNumMax(pAig) );
+
+    // start the fraig package
+    pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames );
+    pFrames->pName = Abc_UtilStrsav( pAig->pName );
+    pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec );
+    // map constant nodes
+    for ( f = 0; f < nFrames; f++ )
+        Aig_ObjSetFrames( pObjMap, nFrames, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) );
+    // create PI nodes for the frames
+    for ( f = 0; f < nFrames; f++ )
+        Aig_ManForEachPiSeq( pAig, pObj, i )
+            Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, Aig_ObjCreateCi(pFrames) );
+    // set initial state for the latches
+    Aig_ManForEachLoSeq( pAig, pObj, i )
+        Aig_ObjSetFrames( pObjMap, nFrames, pObj, 0, Aig_ObjCreateCi(pFrames) );
+
+    // add timeframes
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // add internal nodes of this frame
+        Aig_ManForEachNode( pAig, pObj, i )
+        {
+            pObjNew = Aig_And( pFrames, Aig_ObjChild0Frames(pObjMap,nFrames,pObj,f), Aig_ObjChild1Frames(pObjMap,nFrames,pObj,f) );
+            Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew );
+        }
+        // set the latch inputs and copy them into the latch outputs of the next frame
+        Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i )
+        {
+            pObjNew = Aig_ObjChild0Frames(pObjMap,nFrames,pObjLi,f);
+            if ( f < nFrames - 1 )
+                Aig_ObjSetFrames( pObjMap, nFrames, pObjLo, f+1, pObjNew );
+        }
+    }
+
+    // go through the candidates
+    Vec_VecForEachLevel( vCands, vNodes, i )
+    {
+        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k )
+        {
+            Aig_Obj_t * pObjR  = Aig_Regular(pObj);
+            Aig_Obj_t * pNode0 = pObjMap[nFrames*Aig_ObjId(pObjR)+0];
+            Aig_Obj_t * pNode1 = pObjMap[nFrames*Aig_ObjId(pObjR)+1];
+            Aig_Obj_t * pFan0  = Aig_NotCond( pNode0,  Aig_IsComplement(pObj) );
+            Aig_Obj_t * pFan1  = Aig_NotCond( pNode1, !Aig_IsComplement(pObj) );
+            Aig_Obj_t * pMiter = Aig_And( pFrames, pFan0, pFan1 );
+            Aig_ObjCreateCo( pFrames, pMiter );
+        }
+    }
+    Aig_ManCleanup( pFrames );
+    ABC_FREE( pObjMap );
+
+//Aig_ManShow( pAig, 0, NULL );
+//Aig_ManShow( pFrames, 0, NULL );
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs inductive check for one of the constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManFilterUsingIndOne_new( Aig_Man_t * p, Aig_Man_t * pFrame, sat_solver * pSat, Cnf_Dat_t * pCnf, int nConfs, int nProps, int Counter )
+{
+    Aig_Obj_t * pObj;
+    int Lit, status;
+    pObj = Aig_ManCo( pFrame, Counter );
+    Lit  = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 );
+    status = sat_solver_solve( pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfs, 0, 0, 0 );
+    if ( status == l_False )
+        return 1;
+    if ( status == l_Undef )
+    {
+//        printf( "Solver returned undecided.\n" );
+        return 0;
+    }
+    assert( status == l_True );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detects constraints functionally.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManFilterUsingInd( Aig_Man_t * p, Vec_Vec_t * vCands, int nConfs, int nProps, int fVerbose )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Man_t * pFrames;
+    sat_solver * pSat;
+    Cnf_Dat_t * pCnf;
+    Aig_Obj_t * pObj;
+    int i, k, k2, Counter;
+/*
+    Vec_VecForEachLevel( vCands, vNodes, i )
+        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k )
+            printf( "%d ", Aig_ObjId(Aig_Regular(pObj)) );
+    printf( "\n" );
+*/
+    // create timeframes
+//    pFrames = Saig_ManUnrollInd( p );
+    pFrames = Saig_ManCreateIndMiter( p, vCands );
+    assert( Aig_ManCoNum(pFrames) == Vec_VecSizeSize(vCands) );
+    // start the SAT solver
+    pCnf = Cnf_DeriveSimple( pFrames, Aig_ManCoNum(pFrames) );
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+    // check candidates
+    if ( fVerbose )
+        printf( "Filtered cands:  " );
+    Counter = 0;
+    Vec_VecForEachLevel( vCands, vNodes, i )
+    {
+        k2 = 0;
+        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k )
+        {
+            if ( Saig_ManFilterUsingIndOne_new( p, pFrames, pSat, pCnf, nConfs, nProps, Counter++ ) )
+//            if ( Saig_ManFilterUsingIndOne_old( p, pSat, pCnf, nConfs, pObj ) )
+            {
+                Vec_PtrWriteEntry( vNodes, k2++, pObj );
+                if ( fVerbose )
+                    printf( "%d:%s%d  ", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) );
+            }
+        }
+        Vec_PtrShrink( vNodes, k2 );
+    }
+    if ( fVerbose )
+        printf( "\n" );
+    // clean up
+    Cnf_DataFree( pCnf );
+    sat_solver_delete( pSat );
+    if ( fVerbose )
+        Aig_ManPrintStats( pFrames );
+    Aig_ManStop( pFrames );
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates COI of the property output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManUnrollCOI_( Aig_Man_t * p, int nFrames )
+{
+    Aig_Man_t * pFrames;
+    Aig_Obj_t ** pObjMap;
+    int i;
+//Aig_Man_t * Aig_ManFrames( Aig_Man_t * pAig, int nFrames, int fInit, int fOuts, int fRegs, int fEnlarge, Aig_Obj_t *** ppObjMap )
+    pFrames = Aig_ManFrames( p, nFrames, 0, 1, 1, 0, &pObjMap );
+    for ( i = 0; i < nFrames * Aig_ManObjNumMax(p); i++ )
+        if ( pObjMap[i] && Aig_ObjIsNone( Aig_Regular(pObjMap[i]) ) )
+            pObjMap[i] = NULL;
+    assert( p->pObjCopies == NULL );
+    p->pObjCopies = pObjMap;
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates COI of the property output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManUnrollCOI( Aig_Man_t * pAig, int nFrames )
+{
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew;
+    Aig_Obj_t ** pObjMap;
+    int i, f;
+    // create mapping for the frames nodes
+    pObjMap = ABC_CALLOC( Aig_Obj_t *, nFrames * Aig_ManObjNumMax(pAig) );
+    // start the fraig package
+    pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames );
+    pFrames->pName = Abc_UtilStrsav( pAig->pName );
+    pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec );
+    // map constant nodes
+    for ( f = 0; f < nFrames; f++ )
+        Aig_ObjSetFrames( pObjMap, nFrames, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) );
+    // create PI nodes for the frames
+    for ( f = 0; f < nFrames; f++ )
+        Aig_ManForEachPiSeq( pAig, pObj, i )
+            Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, Aig_ObjCreateCi(pFrames) );
+    // set initial state for the latches
+    Aig_ManForEachLoSeq( pAig, pObj, i )
+        Aig_ObjSetFrames( pObjMap, nFrames, pObj, 0, Aig_ObjCreateCi(pFrames) );
+    // add timeframes
+    for ( f = 0; f < nFrames; f++ )
+    {
+        Aig_ManForEachNode( pAig, pObj, i )
+        {
+            pObjNew = Aig_And( pFrames, Aig_ObjChild0Frames(pObjMap,nFrames,pObj,f), Aig_ObjChild1Frames(pObjMap,nFrames,pObj,f) );
+            Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew );
+        }
+        // set the latch inputs and copy them into the latch outputs of the next frame
+        Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i )
+        {
+            pObjNew = Aig_ObjChild0Frames(pObjMap,nFrames,pObjLi,f);
+            if ( f < nFrames - 1 )
+                Aig_ObjSetFrames( pObjMap, nFrames, pObjLo, f+1, pObjNew );
+        }
+    }
+    // create the only output
+    for ( f = nFrames-1; f < nFrames; f++ )
+    {
+        Aig_ManForEachPoSeq( pAig, pObj, i )
+        {
+            pObjNew = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Frames(pObjMap,nFrames,pObj,f) );
+            Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew );
+        }
+    }
+    // created lots of dangling nodes - no sweeping!
+    //Aig_ManCleanup( pFrames );
+    assert( pAig->pObjCopies == NULL );
+    pAig->pObjCopies = pObjMap;
+    return pFrames;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects and saves values of the SAT variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_CollectSatValues( sat_solver * pSat, Cnf_Dat_t * pCnf, Vec_Ptr_t * vInfo, int * piPat )
+{
+    Aig_Obj_t * pObj;
+    unsigned * pInfo;
+    int i;
+    Aig_ManForEachObj( pCnf->pMan, pObj, i )
+    {
+        if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
+            continue;
+        assert( pCnf->pVarNums[i] > 0 );
+        pInfo = (unsigned *)Vec_PtrEntry( vInfo, i );
+        if ( Abc_InfoHasBit(pInfo, *piPat) != sat_solver_var_value(pSat, pCnf->pVarNums[i]) )
+            Abc_InfoXorBit(pInfo, *piPat);
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Runs the SAT test for the node in one polarity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_DetectTryPolarity( sat_solver * pSat, int nConfs, int nProps, Cnf_Dat_t * pCnf, Aig_Obj_t * pObj, int iPol, Vec_Ptr_t * vInfo, int * piPat, int fVerbose )
+{
+    Aig_Obj_t * pOut = Aig_ManCo( pCnf->pMan, 0 );
+    int status, Lits[2];
+//    ABC_INT64_T nOldConfs = pSat->stats.conflicts;
+//    ABC_INT64_T nOldImps = pSat->stats.propagations;
+    Lits[0] = toLitCond( pCnf->pVarNums[Aig_ObjId(pOut)], 0 );
+    Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !iPol );
+    status = sat_solver_solve( pSat, Lits, Lits + 2, (ABC_INT64_T)nConfs, (ABC_INT64_T)nProps, 0, 0 );
+    if ( status == l_False )
+    {
+//        printf( "u%d(%d) ", (int)(pSat->stats.conflicts-nOldConfs), (int)(pSat->stats.propagations-nOldImps) );
+        return 1;
+    }
+    if ( status == l_Undef )
+    {
+//        printf( "Solver returned undecided.\n" );
+        return 0;
+    }
+//    printf( "s%d(%d) ", (int)(pSat->stats.conflicts-nOldConfs), (int)(pSat->stats.propagations-nOldImps) );
+    assert( status == l_True );
+    Saig_CollectSatValues( pSat, pCnf, vInfo, piPat );
+    (*piPat)++;
+    if ( *piPat == Vec_PtrReadWordsSimInfo(vInfo) * 32 )
+    {
+        if ( fVerbose )
+            printf( "Warning: Reached the limit on the number of patterns.\n" );
+        *piPat = 0;
+    }
+    return 0;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of variables implied by the output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Ssw_ManFindDirectImplications( Aig_Man_t * p, int nFrames, int nConfs, int nProps, int fVerbose )
+{
+    Vec_Vec_t * vCands = NULL;
+    Vec_Ptr_t * vNodes;
+    Cnf_Dat_t * pCnf;
+    sat_solver * pSat;
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj, * pRepr, * pReprR;
+    int i, f, k, value;
+    vCands = Vec_VecAlloc( nFrames );
+
+    // perform unrolling
+    pFrames = Saig_ManUnrollCOI( p, nFrames );
+    assert( Aig_ManCoNum(pFrames) == 1 );
+    // start the SAT solver
+    pCnf = Cnf_DeriveSimple( pFrames, 0 );
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+    if ( pSat != NULL )
+    {
+        Aig_ManIncrementTravId( p );
+        for ( f = 0; f < nFrames; f++ )
+        {
+            Aig_ManForEachObj( p, pObj, i )
+            {
+                if ( !Aig_ObjIsCand(pObj) )
+                    continue;
+                if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+                    continue;
+                // get the node from timeframes
+                pRepr  = p->pObjCopies[nFrames*i + nFrames-1-f];
+                pReprR = Aig_Regular(pRepr);
+                if ( pCnf->pVarNums[Aig_ObjId(pReprR)] < 0 )
+                    continue;
+//                value = pSat->assigns[ pCnf->pVarNums[Aig_ObjId(pReprR)] ];
+                value = sat_solver_get_var_value( pSat, pCnf->pVarNums[Aig_ObjId(pReprR)] );
+                if ( value == l_Undef )
+                    continue;
+                // label this node as taken
+                Aig_ObjSetTravIdCurrent(p, pObj);
+                if ( Saig_ObjIsLo(p, pObj) )
+                    Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin0(Saig_ObjLoToLi(p, pObj)) );
+                // remember the node
+                Vec_VecPush( vCands, f, Aig_NotCond( pObj, (value == l_True) ^ Aig_IsComplement(pRepr) ) );
+        //        printf( "%s%d ", (value == l_False)? "":"!", i );
+            }
+        }
+    //    printf( "\n" );
+        sat_solver_delete( pSat );
+    }
+    Aig_ManStop( pFrames );
+    Cnf_DataFree( pCnf );
+
+    if ( fVerbose )
+    {
+        printf( "Found %3d candidates.\n", Vec_VecSizeSize(vCands) );
+        Vec_VecForEachLevel( vCands, vNodes, k )
+        {
+            printf( "Level %d. Cands  =%d    ", k, Vec_PtrSize(vNodes) );
+//            Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+//                printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) );
+            printf( "\n" );
+        }
+    }
+
+    ABC_FREE( p->pObjCopies );
+    Saig_ManFilterUsingInd( p, vCands, nConfs, nProps, fVerbose );
+    if ( Vec_VecSizeSize(vCands) )
+        printf( "Found %3d constraints after filtering.\n", Vec_VecSizeSize(vCands) );
+    if ( fVerbose )
+    {
+        Vec_VecForEachLevel( vCands, vNodes, k )
+        {
+            printf( "Level %d. Constr =%d    ", k, Vec_PtrSize(vNodes) );
+//            Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+//                printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) );
+            printf( "\n" );
+        }
+    }
+
+    return vCands;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Detects constraints functionally.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Saig_ManDetectConstrFunc( Aig_Man_t * p, int nFrames, int nConfs, int nProps, int fVerbose )
+{
+    int iPat = 0, nWordsAlloc = 16;
+    Bar_Progress_t * pProgress = NULL;
+    Vec_Vec_t * vCands = NULL;
+    Vec_Ptr_t * vInfo, * vNodes;
+    Aig_Obj_t * pObj, * pRepr, * pObjNew;
+    Aig_Man_t * pFrames;
+    sat_solver * pSat;
+    Cnf_Dat_t * pCnf;
+    unsigned * pInfo;
+    int i, j, k, Lit, status, nCands = 0;
+    assert( Saig_ManPoNum(p) == 1 );
+    if ( Saig_ManPoNum(p) != 1 )
+    {
+        printf( "The number of outputs is different from 1.\n" );
+        return NULL;
+    }
+//printf( "Implications = %d.\n", Ssw_ManCountImplications(p, nFrames) );
+
+    // perform unrolling
+    pFrames = Saig_ManUnrollCOI( p, nFrames );
+    assert( Aig_ManCoNum(pFrames) == 1 );
+    if ( fVerbose )
+    {
+        printf( "Detecting constraints with %d frames, %d conflicts, and %d propagations.\n", nFrames, nConfs, nProps );
+        printf( "Frames: " );
+        Aig_ManPrintStats( pFrames );
+    }
+//    Aig_ManShow( pFrames, 0, NULL );
+
+    // start the SAT solver
+    pCnf = Cnf_DeriveSimple( pFrames, Aig_ManCoNum(pFrames) );
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+//printf( "Implications = %d.\n", pSat->qhead );
+
+    // solve the original problem
+    Lit = toLitCond( pCnf->pVarNums[Aig_ObjId(Aig_ManCo(pFrames,0))], 0 );
+    status = sat_solver_solve( pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfs, 0, 0, 0 );
+    if ( status == l_False )
+    {
+        printf( "The problem is trivially UNSAT (inductive with k=%d).\n", nFrames-1 );
+        Cnf_DataFree( pCnf );
+        sat_solver_delete( pSat );
+        Aig_ManStop( pFrames );
+        return NULL;
+    }
+    if ( status == l_Undef )
+    {
+        printf( "Solver could not solve the original problem.\n" );
+        Cnf_DataFree( pCnf );
+        sat_solver_delete( pSat );
+        Aig_ManStop( pFrames );
+        return NULL;
+    }
+    assert( status == l_True );
+
+    // create simulation info
+    vInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(pFrames), nWordsAlloc );
+    Vec_PtrCleanSimInfo( vInfo, 0, nWordsAlloc );
+    Saig_CollectSatValues( pSat, pCnf, vInfo, &iPat );
+    Aig_ManForEachObj( pFrames, pObj, i )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry( vInfo, i );
+        if ( pInfo[0] & 1 )
+            memset( (char*)pInfo, 0xff, 4*nWordsAlloc );
+    }
+//    Aig_ManShow( pFrames, 0, NULL );
+//    Aig_ManShow( p, 0, NULL );
+
+    // consider the nodes for ci=>!Out and label when it holds
+    pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(pFrames) );
+    Aig_ManCleanMarkAB( pFrames );
+    Aig_ManForEachObj( pFrames, pObj, i )
+    {
+        if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
+            continue;
+        Bar_ProgressUpdate( pProgress, i, NULL );
+        // check if the node is available in both polarities
+        pInfo = (unsigned *)Vec_PtrEntry( vInfo, i );
+        for ( k = 0; k < nWordsAlloc; k++ )
+            if ( pInfo[k] != ~0 )
+                break;
+        if ( k == nWordsAlloc )
+        {
+            if ( Saig_DetectTryPolarity(pSat, nConfs, nProps, pCnf, pObj, 0, vInfo, &iPat, fVerbose) ) // !pObj is a constr
+            {
+                pObj->fMarkA = 1, nCands++;
+//                printf( "!%d  ", Aig_ObjId(pObj) );
+            }
+            continue;
+        }
+        for ( k = 0; k < nWordsAlloc; k++ )
+            if ( pInfo[k] != 0 )
+                break;
+        if ( k == nWordsAlloc )
+        {
+            if ( Saig_DetectTryPolarity(pSat, nConfs, nProps, pCnf, pObj, 1, vInfo, &iPat, fVerbose) ) //  pObj is a constr
+            {
+                pObj->fMarkB = 1, nCands++;
+//                printf( "%d  ", Aig_ObjId(pObj) );
+            }
+            continue;
+        }
+    }
+    Bar_ProgressStop( pProgress );
+    if ( nCands )
+    {
+
+//        printf( "\n" );
+        if ( fVerbose )
+            printf( "Found %3d classes of candidates.\n", nCands );
+        vCands = Vec_VecAlloc( nFrames );
+        for ( k = 0; k < nFrames; k++ )
+        {
+            Aig_ManForEachObj( p, pObj, i )
+            {
+                if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
+                    continue;
+                pRepr = p->pObjCopies[nFrames*i + nFrames-1-k];
+//                pRepr = p->pObjCopies[nFrames*i + k];
+                if ( pRepr == NULL )
+                    continue;
+                if ( Aig_Regular(pRepr)->fMarkA ) // !pObj is a constr
+                {
+                    pObjNew = Aig_NotCond(pObj, !Aig_IsComplement(pRepr));
+
+                    for ( j = 0; j < k; j++ )
+                        if ( Vec_PtrFind( Vec_VecEntry(vCands, j), pObjNew ) >= 0 )
+                            break;
+                    if ( j == k )
+                        Vec_VecPush( vCands, k, pObjNew );
+//                    printf( "%d->!%d ", Aig_ObjId(Aig_Regular(pRepr)), Aig_ObjId(pObj) );
+                }
+                else if ( Aig_Regular(pRepr)->fMarkB ) //  pObj is a constr
+                {
+                    pObjNew = Aig_NotCond(pObj,  Aig_IsComplement(pRepr));
+
+                    for ( j = 0; j < k; j++ )
+                        if ( Vec_PtrFind( Vec_VecEntry(vCands, j), pObjNew ) >= 0  )
+                            break;
+                    if ( j == k )
+                        Vec_VecPush( vCands, k, pObjNew );
+//                    printf( "%d->%d ", Aig_ObjId(Aig_Regular(pRepr)), Aig_ObjId(pObj) );
+                }
+            }
+        }
+
+//        printf( "\n" );
+        if ( fVerbose )
+        {
+            printf( "Found %3d candidates.\n", Vec_VecSizeSize(vCands) );
+            Vec_VecForEachLevel( vCands, vNodes, k )
+            {
+                printf( "Level %d. Cands  =%d    ", k, Vec_PtrSize(vNodes) );
+//                Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+//                    printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) );
+                printf( "\n" );
+            }
+        }
+
+        ABC_FREE( p->pObjCopies );
+        Saig_ManFilterUsingInd( p, vCands, nConfs, nProps, fVerbose );
+        if ( Vec_VecSizeSize(vCands) )
+            printf( "Found %3d constraints after filtering.\n", Vec_VecSizeSize(vCands) );
+        if ( fVerbose )
+        {
+            Vec_VecForEachLevel( vCands, vNodes, k )
+            {
+                printf( "Level %d. Constr =%d    ", k, Vec_PtrSize(vNodes) );
+//                Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+//                    printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) );
+                printf( "\n" );
+            }
+        }
+    }
+    Vec_PtrFree( vInfo );
+    Cnf_DataFree( pCnf );
+    sat_solver_delete( pSat );
+    Aig_ManCleanMarkAB( pFrames );
+    Aig_ManStop( pFrames );
+    return vCands;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Experimental procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManDetectConstrFuncTest( Aig_Man_t * p, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose )
+{
+    Vec_Vec_t * vCands;
+    if ( fOldAlgo )
+        vCands = Saig_ManDetectConstrFunc( p, nFrames, nConfs, nProps, fVerbose );
+    else
+        vCands = Ssw_ManFindDirectImplications( p, nFrames, nConfs, nProps, fVerbose );
+    Vec_VecFreeP( &vCands );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG while unfolding constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManDupUnfoldConstrsFunc( Aig_Man_t * pAig, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose )
+{
+    Aig_Man_t * pNew;
+    Vec_Vec_t * vCands;
+    Vec_Ptr_t * vNodes, * vNewFlops;
+    Aig_Obj_t * pObj;
+    int i, j, k, nNewFlops;
+    if ( fOldAlgo )
+        vCands = Saig_ManDetectConstrFunc( pAig, nFrames, nConfs, nProps, fVerbose );
+    else
+        vCands = Ssw_ManFindDirectImplications( pAig, nFrames, nConfs, nProps, fVerbose );
+    if ( vCands == NULL || Vec_VecSizeSize(vCands) == 0 )
+    {
+        Vec_VecFreeP( &vCands );
+        return Aig_ManDupDfs( pAig );
+    }
+    // create new manager
+    pNew = Aig_ManDupWithoutPos( pAig );
+    pNew->nConstrs = pAig->nConstrs + Vec_VecSizeSize(vCands);
+    // add normal POs
+    Saig_ManForEachPo( pAig, pObj, i )
+        Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    // create constraint outputs
+    vNewFlops = Vec_PtrAlloc( 100 );
+    Vec_VecForEachLevel( vCands, vNodes, i )
+    {
+        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k )
+        {
+            Vec_PtrPush( vNewFlops, Aig_ObjRealCopy(pObj) );
+            for ( j = 0; j < i; j++ )
+                Vec_PtrPush( vNewFlops, Aig_ObjCreateCi(pNew) );
+            Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrPop(vNewFlops) );
+        }
+    }
+    // add latch outputs
+    Saig_ManForEachLi( pAig, pObj, i )
+        Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    // add new latch outputs
+    nNewFlops = 0;
+    Vec_VecForEachLevel( vCands, vNodes, i )
+    {
+        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k )
+        {
+            for ( j = 0; j < i; j++ )
+                Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vNewFlops, nNewFlops++) );
+        }
+    }
+    assert( nNewFlops == Vec_PtrSize(vNewFlops) );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) + nNewFlops );
+    Vec_VecFreeP( &vCands );
+    Vec_PtrFree( vNewFlops );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG while unfolding constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManDupFoldConstrsFunc( Aig_Man_t * pAig, int fCompl, int fVerbose )
+{
+    Aig_Man_t * pAigNew;
+    Aig_Obj_t * pMiter, * pFlopOut, * pFlopIn, * pObj;
+    int i;
+    if ( Aig_ManConstrNum(pAig) == 0 )
+        return Aig_ManDupDfs( pAig );
+    assert( Aig_ManConstrNum(pAig) < Saig_ManPoNum(pAig) );
+    // start the new manager
+    pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) );
+    pAigNew->pName = Abc_UtilStrsav( pAig->pName );
+    pAigNew->pSpec = Abc_UtilStrsav( pAig->pSpec );
+    // map the constant node
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew );
+    // create variables for PIs
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pAigNew );
+    // add internal nodes of this frame
+    Aig_ManForEachNode( pAig, pObj, i )
+        pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+
+    // OR the constraint outputs
+    pMiter = Aig_ManConst0( pAigNew );
+    Saig_ManForEachPo( pAig, pObj, i )
+    {
+        if ( i < Saig_ManPoNum(pAig)-Aig_ManConstrNum(pAig) )
+            continue;
+        pMiter = Aig_Or( pAigNew, pMiter, Aig_NotCond( Aig_ObjChild0Copy(pObj), fCompl ) );
+    }
+
+    // create additional flop
+    if ( Saig_ManRegNum(pAig) > 0 )
+    {
+        pFlopOut = Aig_ObjCreateCi( pAigNew );
+        pFlopIn  = Aig_Or( pAigNew, pMiter, pFlopOut );
+    }
+    else 
+        pFlopIn = pMiter;
+
+    // create primary output
+    Saig_ManForEachPo( pAig, pObj, i )
+    {
+        if ( i >= Saig_ManPoNum(pAig)-Aig_ManConstrNum(pAig) )
+            continue;
+        pMiter = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_Not(pFlopIn) );
+        Aig_ObjCreateCo( pAigNew, pMiter );
+    }
+
+    // transfer to register outputs
+    Saig_ManForEachLi( pAig, pObj, i )
+        Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) );
+
+    // create additional flop 
+    if ( Saig_ManRegNum(pAig) > 0 )
+    {
+        Aig_ObjCreateCo( pAigNew, pFlopIn );
+        Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig)+1 );
+    }
+
+    // perform cleanup
+    Aig_ManCleanup( pAigNew );
+    Aig_ManSeqCleanup( pAigNew );
+    return pAigNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "saigUnfold2.c"
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigDual.c b/abc-build/src/aig/saig/saigDual.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigDual.c
@@ -0,0 +1,240 @@
+/**CFile****************************************************************
+
+  FileName    [saigDual.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Various duplication procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigDual.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline void        Saig_ObjSetDual( Vec_Ptr_t * vCopies, int Id, int fPos, Aig_Obj_t * pItem ) { Vec_PtrWriteEntry( vCopies, 2*Id+fPos, pItem );         }
+static inline Aig_Obj_t * Saig_ObjDual( Vec_Ptr_t * vCopies, int Id, int fPos )                       { return (Aig_Obj_t *)Vec_PtrEntry( vCopies, 2*Id+fPos ); }
+
+static inline void        Saig_ObjDualFanin( Aig_Man_t * pAigNew, Vec_Ptr_t * vCopies, Aig_Obj_t * pObj, int iFanin, Aig_Obj_t ** ppRes0, Aig_Obj_t ** ppRes1 ) {
+
+    Aig_Obj_t * pTemp0, * pTemp1, * pCare;
+    int fCompl;
+    assert( iFanin == 0 || iFanin == 1 );
+    if ( iFanin == 0 )
+    {
+        pTemp0 = Saig_ObjDual( vCopies, Aig_ObjFaninId0(pObj), 0 );
+        pTemp1 = Saig_ObjDual( vCopies, Aig_ObjFaninId0(pObj), 1 );
+        fCompl = Aig_ObjFaninC0( pObj );
+    }
+    else
+    {
+        pTemp0 = Saig_ObjDual( vCopies, Aig_ObjFaninId1(pObj), 0 );
+        pTemp1 = Saig_ObjDual( vCopies, Aig_ObjFaninId1(pObj), 1 );
+        fCompl = Aig_ObjFaninC1( pObj );
+    }
+    if ( fCompl )
+    {
+        pCare   = Aig_Or( pAigNew, pTemp0, pTemp1 );
+        *ppRes0 = Aig_And( pAigNew, pTemp1, pCare );
+        *ppRes1 = Aig_And( pAigNew, pTemp0, pCare );
+    }
+    else
+    {
+        *ppRes0 = pTemp0;
+        *ppRes1 = pTemp1;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms sequential AIG into dual-rail miter.]
+
+  Description [Transforms sequential AIG into a miter encoding ternary
+  problem formulated as follows "none of the POs has a ternary value".
+  Interprets the first nDualPis as having ternary value.  Sets flops
+  to have ternary intial value when fDualFfs is set to 1.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManDupDual( Aig_Man_t * pAig, Vec_Int_t * vDcFlops, int nDualPis, int fDualFfs, int fMiterFfs, int fComplPo, int fCheckZero, int fCheckOne )
+{
+    Vec_Ptr_t * vCopies;
+    Aig_Man_t * pAigNew;
+    Aig_Obj_t * pObj, * pTemp0, * pTemp1, * pTemp2, * pTemp3, * pCare, * pMiter;
+    int i;
+    assert( Saig_ManPoNum(pAig) > 0 );
+    assert( nDualPis >= 0 && nDualPis <= Saig_ManPiNum(pAig) );
+    assert( vDcFlops == NULL || Vec_IntSize(vDcFlops) == Aig_ManRegNum(pAig) );
+    vCopies = Vec_PtrStart( 2*Aig_ManObjNum(pAig) );
+    // start the new manager
+    pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) );
+    pAigNew->pName = Abc_UtilStrsav( pAig->pName );
+    // map the constant node
+    Saig_ObjSetDual( vCopies, 0, 0, Aig_ManConst0(pAigNew) );
+    Saig_ObjSetDual( vCopies, 0, 1, Aig_ManConst1(pAigNew) );
+    // create variables for PIs
+    Aig_ManForEachCi( pAig, pObj, i )
+    {
+        if ( i < nDualPis )
+        {
+            pTemp0 = Aig_ObjCreateCi( pAigNew );
+            pTemp1 = Aig_ObjCreateCi( pAigNew );
+        }
+        else if ( i < Saig_ManPiNum(pAig) )
+        {
+            pTemp1 = Aig_ObjCreateCi( pAigNew );
+            pTemp0 = Aig_Not( pTemp1 );
+        }
+        else
+        {
+            pTemp0 = Aig_ObjCreateCi( pAigNew );
+            pTemp1 = Aig_ObjCreateCi( pAigNew );
+            if ( vDcFlops )
+                pTemp0 = Aig_NotCond( pTemp0, !Vec_IntEntry(vDcFlops, i-Saig_ManPiNum(pAig)) );
+            else
+                pTemp0 = Aig_NotCond( pTemp0, !fDualFfs );
+        }
+        Saig_ObjSetDual( vCopies, Aig_ObjId(pObj), 0, Aig_And(pAigNew, pTemp0, Aig_Not(pTemp1)) );
+        Saig_ObjSetDual( vCopies, Aig_ObjId(pObj), 1, Aig_And(pAigNew, pTemp1, Aig_Not(pTemp0)) );
+    }
+    // create internal nodes
+    Aig_ManForEachNode( pAig, pObj, i )
+    {
+        Saig_ObjDualFanin( pAigNew, vCopies, pObj, 0, &pTemp0, &pTemp1 );
+        Saig_ObjDualFanin( pAigNew, vCopies, pObj, 1, &pTemp2, &pTemp3 );
+        Saig_ObjSetDual( vCopies, Aig_ObjId(pObj), 0, Aig_Or (pAigNew, pTemp0, pTemp2) );
+        Saig_ObjSetDual( vCopies, Aig_ObjId(pObj), 1, Aig_And(pAigNew, pTemp1, pTemp3) );
+    }
+    // create miter and flops
+    pMiter = Aig_ManConst0(pAigNew);
+    if ( fMiterFfs )
+    {
+        Saig_ManForEachLi( pAig, pObj, i )
+        {
+            Saig_ObjDualFanin( pAigNew, vCopies, pObj, 0, &pTemp0, &pTemp1 );
+            if ( fCheckZero )
+            {
+                pCare  = Aig_And( pAigNew, pTemp0, Aig_Not(pTemp1) );
+                pMiter = Aig_Or( pAigNew, pMiter, pCare );
+            }
+            else if ( fCheckOne )
+            {
+                pCare  = Aig_And( pAigNew, Aig_Not(pTemp0), pTemp1 );
+                pMiter = Aig_Or( pAigNew, pMiter, pCare );
+            }
+            else // check X
+            {
+                pCare  = Aig_And( pAigNew, Aig_Not(pTemp0), Aig_Not(pTemp1) );
+                pMiter = Aig_Or( pAigNew, pMiter, pCare );
+            }
+        }
+    }
+    else
+    {
+        Saig_ManForEachPo( pAig, pObj, i )
+        {
+            Saig_ObjDualFanin( pAigNew, vCopies, pObj, 0, &pTemp0, &pTemp1 );
+            if ( fCheckZero )
+            {
+                pCare  = Aig_And( pAigNew, pTemp0, Aig_Not(pTemp1) );
+                pMiter = Aig_Or( pAigNew, pMiter, pCare );
+            }
+            else if ( fCheckOne )
+            {
+                pCare  = Aig_And( pAigNew, Aig_Not(pTemp0), pTemp1 );
+                pMiter = Aig_Or( pAigNew, pMiter, pCare );
+            }
+            else // check X
+            {
+                pCare  = Aig_And( pAigNew, Aig_Not(pTemp0), Aig_Not(pTemp1) );
+                pMiter = Aig_Or( pAigNew, pMiter, pCare );
+            }
+        }
+    }
+    // create PO
+    pMiter = Aig_NotCond( pMiter, fComplPo );
+    Aig_ObjCreateCo( pAigNew, pMiter );
+    // create flops
+    Saig_ManForEachLi( pAig, pObj, i )
+    {
+        Saig_ObjDualFanin( pAigNew, vCopies, pObj, 0, &pTemp0, &pTemp1 );
+        if ( vDcFlops )
+            pTemp0 = Aig_NotCond( pTemp0, !Vec_IntEntry(vDcFlops, i) );
+        else
+            pTemp0 = Aig_NotCond( pTemp0, !fDualFfs );
+        Aig_ObjCreateCo( pAigNew, pTemp0 );
+        Aig_ObjCreateCo( pAigNew, pTemp1 );
+    }
+    // set the flops
+    Aig_ManSetRegNum( pAigNew, 2 * Aig_ManRegNum(pAig) );
+    Aig_ManCleanup( pAigNew );
+    Vec_PtrFree( vCopies );
+    return pAigNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms sequential AIG to block the PO for N cycles.]
+
+  Description [This procedure should be applied to a safety property 
+  miter to make the propetry 'true' (const 0) during the first N cycles.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManBlockPo( Aig_Man_t * pAig, int nCycles )
+{
+    Aig_Obj_t * pObj, * pCond, * pPrev, * pTemp;
+    int i;
+    assert( nCycles > 0 );
+    // add N flops (assuming 1-hot encoding of cycles)
+    pPrev = Aig_ManConst1(pAig);
+    pCond = Aig_ManConst1(pAig);
+    for ( i = 0; i < nCycles; i++ )
+    {
+        Aig_ObjCreateCo( pAig, pPrev );
+        pPrev = Aig_ObjCreateCi( pAig );
+        pCond = Aig_And( pAig, pCond, pPrev );
+    }
+    // update the POs
+    Saig_ManForEachPo( pAig, pObj, i )
+    {
+        pTemp = Aig_And( pAig, Aig_ObjChild0(pObj), pCond );
+        Aig_ObjPatchFanin0( pAig, pObj, pTemp );
+    }
+    // set the flops
+    Aig_ManSetRegNum( pAig, Aig_ManRegNum(pAig) + nCycles );
+    Aig_ManCleanup( pAig );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigDup.c b/abc-build/src/aig/saig/saigDup.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigDup.c
@@ -0,0 +1,531 @@
+/**CFile****************************************************************
+
+  FileName    [saigDup.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Various duplication procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigDup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates while ORing the POs of sequential circuit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManDupOrpos( Aig_Man_t * pAig )
+{
+    Aig_Man_t * pAigNew;
+    Aig_Obj_t * pObj, * pMiter;
+    int i;
+    if ( pAig->nConstrs > 0 )
+    {
+        printf( "The AIG manager should have no constraints.\n" );
+        return NULL;
+    }
+    // start the new manager
+    pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) );
+    pAigNew->pName = Abc_UtilStrsav( pAig->pName );
+    pAigNew->nConstrs = pAig->nConstrs;
+    // map the constant node
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew );
+    // create variables for PIs
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pAigNew );
+    // add internal nodes of this frame
+    Aig_ManForEachNode( pAig, pObj, i )
+        pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // create PO of the circuit
+    pMiter = Aig_ManConst0( pAigNew );
+    Saig_ManForEachPo( pAig, pObj, i )
+        pMiter = Aig_Or( pAigNew, pMiter, Aig_ObjChild0Copy(pObj) );
+    Aig_ObjCreateCo( pAigNew, pMiter );
+    // transfer to register outputs
+    Saig_ManForEachLi( pAig, pObj, i )
+        Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) );
+    Aig_ManCleanup( pAigNew );
+    Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) );
+    return pAigNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates while ORing the POs of sequential circuit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManCreateEquivMiter( Aig_Man_t * pAig, Vec_Int_t * vPairs )
+{
+    Aig_Man_t * pAigNew;
+    Aig_Obj_t * pObj, * pObj2, * pMiter;
+    int i;
+    if ( pAig->nConstrs > 0 )
+    {
+        printf( "The AIG manager should have no constraints.\n" );
+        return NULL;
+    }
+    // start the new manager
+    pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) );
+    pAigNew->pName = Abc_UtilStrsav( pAig->pName );
+    pAigNew->nConstrs = pAig->nConstrs;
+    // map the constant node
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew );
+    // create variables for PIs
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pAigNew );
+    // add internal nodes of this frame
+    Aig_ManForEachNode( pAig, pObj, i )
+        pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // create POs
+    assert( Vec_IntSize(vPairs) % 2 == 0 );
+    Aig_ManForEachObjVec( vPairs, pAig, pObj, i )
+    {
+        pObj2  = Aig_ManObj( pAig, Vec_IntEntry(vPairs, ++i) );
+        pMiter = Aig_Exor( pAigNew, (Aig_Obj_t *)pObj->pData, (Aig_Obj_t *)pObj2->pData );
+        pMiter = Aig_NotCond( pMiter, pObj->fPhase ^ pObj2->fPhase );
+        Aig_ObjCreateCo( pAigNew, pMiter );
+    }
+    // transfer to register outputs
+    Saig_ManForEachLi( pAig, pObj, i )
+        Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) );
+    Aig_ManCleanup( pAigNew );
+    Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) );
+    return pAigNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Trims the model by removing PIs without fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManTrimPis( Aig_Man_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i, fAllPisHaveNoRefs;
+    // check the refs of PIs    
+    fAllPisHaveNoRefs = 1;
+    Saig_ManForEachPi( p, pObj, i )
+        if ( pObj->nRefs )
+            fAllPisHaveNoRefs = 0;
+    // start the new manager
+    pNew = Aig_ManStart( Aig_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->nConstrs = p->nConstrs;
+    // start mapping of the CI numbers
+    pNew->vCiNumsOrig = Vec_IntAlloc( Aig_ManCiNum(p) );
+    // map const and primary inputs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+        if ( fAllPisHaveNoRefs || pObj->nRefs || Saig_ObjIsLo(p, pObj) )
+        {
+            pObj->pData = Aig_ObjCreateCi( pNew );
+            Vec_IntPush( pNew->vCiNumsOrig, Vec_IntEntry(p->vCiNumsOrig, i) );
+        }
+    Aig_ManForEachNode( p, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    Aig_ManForEachCo( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager recursively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Saig_ManAbstractionDfs_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj )
+{
+    if ( pObj->pData )
+        return (Aig_Obj_t *)pObj->pData;
+    Saig_ManAbstractionDfs_rec( pNew, Aig_ObjFanin0(pObj) );
+    Saig_ManAbstractionDfs_rec( pNew, Aig_ObjFanin1(pObj) );
+    return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs abstraction of the AIG to preserve the included flops.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManDupAbstraction( Aig_Man_t * p, Vec_Int_t * vFlops )
+{ 
+    Aig_Man_t * pNew;//, * pTemp;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i, Entry;
+    Aig_ManCleanData( p );
+    // start the new manager
+    pNew = Aig_ManStart( 5000 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    // map the constant node
+    Aig_ManConst1(p)->pData = Aig_ManConst1( pNew );
+    // label included flops
+    Vec_IntForEachEntry( vFlops, Entry, i )
+    {
+        pObjLi = Saig_ManLi( p, Entry );
+        assert( pObjLi->fMarkA == 0 );
+        pObjLi->fMarkA = 1;
+        pObjLo = Saig_ManLo( p, Entry );
+        assert( pObjLo->fMarkA == 0 );
+        pObjLo->fMarkA = 1;
+    }
+    // create variables for PIs
+    assert( p->vCiNumsOrig == NULL );
+    pNew->vCiNumsOrig = Vec_IntAlloc( Aig_ManCiNum(p) );
+    Aig_ManForEachCi( p, pObj, i )
+        if ( !pObj->fMarkA )
+        {
+            pObj->pData = Aig_ObjCreateCi( pNew );
+            Vec_IntPush( pNew->vCiNumsOrig, i );
+        }
+    // create variables for LOs
+    Aig_ManForEachCi( p, pObj, i )
+        if ( pObj->fMarkA )
+        {
+            pObj->fMarkA = 0;
+            pObj->pData = Aig_ObjCreateCi( pNew );
+            Vec_IntPush( pNew->vCiNumsOrig, i );
+        }
+    // add internal nodes 
+//    Aig_ManForEachNode( p, pObj, i )
+//        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // create POs
+    Saig_ManForEachPo( p, pObj, i )
+    {
+        Saig_ManAbstractionDfs_rec( pNew, Aig_ObjFanin0(pObj) );
+        Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    }
+    // create LIs
+    Aig_ManForEachCo( p, pObj, i )
+        if ( pObj->fMarkA )
+        {
+            pObj->fMarkA = 0;
+            Saig_ManAbstractionDfs_rec( pNew, Aig_ObjFanin0(pObj) );
+            Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+        }
+    Aig_ManSetRegNum( pNew, Vec_IntSize(vFlops) );
+    Aig_ManSeqCleanup( pNew );
+    // remove PIs without fanout
+//    pNew = Saig_ManTrimPis( pTemp = pNew );
+//    Aig_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulates the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManVerifyCex( Aig_Man_t * pAig, Abc_Cex_t * p )
+{
+    Aig_Obj_t * pObj, * pObjRi, * pObjRo;
+    int RetValue, i, k, iBit = 0;
+    Aig_ManCleanMarkB(pAig);
+    Aig_ManConst1(pAig)->fMarkB = 1;
+    Saig_ManForEachLo( pAig, pObj, i )
+        pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++);
+    for ( i = 0; i <= p->iFrame; i++ )
+    {
+        Saig_ManForEachPi( pAig, pObj, k )
+            pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++);
+        Aig_ManForEachNode( pAig, pObj, k )
+            pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & 
+                           (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj));
+        Aig_ManForEachCo( pAig, pObj, k )
+            pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj);
+        if ( i == p->iFrame )
+            break;
+        Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k )
+            pObjRo->fMarkB = pObjRi->fMarkB;
+    }
+    assert( iBit == p->nBits );
+    RetValue = Aig_ManCo(pAig, p->iPo)->fMarkB;
+    Aig_ManCleanMarkB(pAig);
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulates the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Saig_ManExtendCex( Aig_Man_t * pAig, Abc_Cex_t * p )
+{
+    Abc_Cex_t * pNew;
+    Aig_Obj_t * pObj, * pObjRi, * pObjRo;
+    int RetValue, i, k, iBit = 0;
+    // create new counter-example
+    pNew = Abc_CexAlloc( 0, Aig_ManCiNum(pAig), p->iFrame + 1 );
+    pNew->iPo = p->iPo;
+    pNew->iFrame = p->iFrame;
+    // simulate the AIG
+    Aig_ManCleanMarkB(pAig);
+    Aig_ManConst1(pAig)->fMarkB = 1;
+    Saig_ManForEachLo( pAig, pObj, i )
+        pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++);
+    for ( i = 0; i <= p->iFrame; i++ )
+    {
+        Saig_ManForEachPi( pAig, pObj, k )
+            pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++);
+        ///////// write PI+LO values ////////////
+        Aig_ManForEachCi( pAig, pObj, k )
+            if ( pObj->fMarkB )
+                Abc_InfoSetBit(pNew->pData, Aig_ManCiNum(pAig)*i + k);
+        /////////////////////////////////////////
+        Aig_ManForEachNode( pAig, pObj, k )
+            pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & 
+                           (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj));
+        Aig_ManForEachCo( pAig, pObj, k )
+            pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj);
+        if ( i == p->iFrame )
+            break;
+        Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k )
+            pObjRo->fMarkB = pObjRi->fMarkB;
+    }
+    assert( iBit == p->nBits );
+    RetValue = Aig_ManCo(pAig, p->iPo)->fMarkB;
+    Aig_ManCleanMarkB(pAig);
+    if ( RetValue == 0 )
+        printf( "Saig_ManExtendCex(): The counter-example is invalid!!!\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulates the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManFindFailedPoCex( Aig_Man_t * pAig, Abc_Cex_t * p )
+{
+    Aig_Obj_t * pObj, * pObjRi, * pObjRo;
+    int RetValue, i, k, iBit = 0;
+    Aig_ManCleanMarkB(pAig);
+    Aig_ManConst1(pAig)->fMarkB = 1;
+    Saig_ManForEachLo( pAig, pObj, i )
+        pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++);
+    for ( i = 0; i <= p->iFrame; i++ )
+    {
+        Saig_ManForEachPi( pAig, pObj, k )
+            pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++);
+        Aig_ManForEachNode( pAig, pObj, k )
+            pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & 
+                           (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj));
+        Aig_ManForEachCo( pAig, pObj, k )
+            pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj);
+        if ( i == p->iFrame )
+            break;
+        Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k )
+            pObjRo->fMarkB = pObjRi->fMarkB;
+    }
+    assert( iBit == p->nBits );
+    // remember the number of failed output
+    RetValue = -1;
+    Saig_ManForEachPo( pAig, pObj, i )
+        if ( pObj->fMarkB )
+        {
+            RetValue = i;
+            break;
+        }
+    Aig_ManCleanMarkB(pAig);
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates while ORing the POs of sequential circuit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManDupWithPhase( Aig_Man_t * pAig, Vec_Int_t * vInit )
+{
+    Aig_Man_t * pAigNew;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( Aig_ManRegNum(pAig) <= Vec_IntSize(vInit) );
+    // start the new manager
+    pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) );
+    pAigNew->pName = Abc_UtilStrsav( pAig->pName );
+    pAigNew->nConstrs = pAig->nConstrs;
+    // map the constant node
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew );
+    // create variables for PIs
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pAigNew );
+    // update the flop variables
+    Saig_ManForEachLo( pAig, pObj, i )
+        pObj->pData = Aig_NotCond( (Aig_Obj_t *)pObj->pData, Vec_IntEntry(vInit, i) );
+    // add internal nodes of this frame
+    Aig_ManForEachNode( pAig, pObj, i )
+        pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // transfer to register outputs
+    Saig_ManForEachPo( pAig, pObj, i )
+        Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) );
+    // update the flop variables
+    Saig_ManForEachLi( pAig, pObj, i )
+        Aig_ObjCreateCo( pAigNew, Aig_NotCond(Aig_ObjChild0Copy(pObj), Vec_IntEntry(vInit, i)) );
+    // finalize
+    Aig_ManCleanup( pAigNew );
+    Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) );
+    return pAigNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Copy an AIG structure related to the selected POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManDupCones_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vRoots )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Aig_ObjIsNode(pObj) )
+    {
+        Saig_ManDupCones_rec( p, Aig_ObjFanin0(pObj), vLeaves, vNodes, vRoots );
+        Saig_ManDupCones_rec( p, Aig_ObjFanin1(pObj), vLeaves, vNodes, vRoots );
+        Vec_PtrPush( vNodes, pObj );
+    }
+    else if ( Aig_ObjIsCo(pObj) )
+        Saig_ManDupCones_rec( p, Aig_ObjFanin0(pObj), vLeaves, vNodes, vRoots );
+    else if ( Saig_ObjIsLo(p, pObj) )
+        Vec_PtrPush( vRoots, Saig_ObjLoToLi(p, pObj) );
+    else if ( Saig_ObjIsPi(p, pObj) )
+        Vec_PtrPush( vLeaves, pObj );
+    else assert( 0 );
+}
+Aig_Man_t * Saig_ManDupCones( Aig_Man_t * pAig, int * pPos, int nPos )
+{
+    Aig_Man_t * pAigNew;
+    Vec_Ptr_t * vLeaves, * vNodes, * vRoots;
+    Aig_Obj_t * pObj;
+    int i;
+
+    // collect initial POs
+    vLeaves = Vec_PtrAlloc( 100 );
+    vNodes = Vec_PtrAlloc( 100 );
+    vRoots = Vec_PtrAlloc( 100 );
+    for ( i = 0; i < nPos; i++ )
+        Vec_PtrPush( vRoots, Aig_ManCo(pAig, pPos[i]) );
+
+    // mark internal nodes
+    Aig_ManIncrementTravId( pAig );
+    Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i )
+        Saig_ManDupCones_rec( pAig, pObj, vLeaves, vNodes, vRoots );
+
+    // start the new manager
+    pAigNew = Aig_ManStart( Vec_PtrSize(vNodes) );
+    pAigNew->pName = Abc_UtilStrsav( pAig->pName );
+    // map the constant node
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew );
+    // create PIs
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pAigNew );
+    // create LOs
+    Vec_PtrForEachEntryStart( Aig_Obj_t *, vRoots, pObj, i, nPos )
+        Saig_ObjLiToLo(pAig, pObj)->pData = Aig_ObjCreateCi( pAigNew );
+    // create internal nodes
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // create COs
+    Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i )
+        Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) );
+    // finalize
+    Aig_ManSetRegNum( pAigNew, Vec_PtrSize(vRoots)-nPos );
+    Vec_PtrFree( vLeaves );
+    Vec_PtrFree( vNodes );
+    Vec_PtrFree( vRoots );
+    return pAigNew;
+
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigGlaCba.c b/abc-build/src/aig/saig/saigGlaCba.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigGlaCba.c
@@ -0,0 +1,840 @@
+/**CFile****************************************************************
+
+  FileName    [saigGlaCba.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Gate level abstraction.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigGlaCba.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+#include "sat/bsat/satSolver.h"
+#include "sat/cnf/cnf.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Aig_Gla1Man_t_ Aig_Gla1Man_t;
+struct Aig_Gla1Man_t_
+{
+    // user data
+    Aig_Man_t *    pAig;
+    int            nConfLimit;
+    int            nFramesMax;
+    int            fVerbose;
+    // unrolling
+    int            nFrames;
+    Vec_Int_t *    vObj2Vec;   // maps obj ID into its vec ID
+    Vec_Int_t *    vVec2Var;   // maps vec ID into its sat Var (nFrames per vec ID)
+    Vec_Int_t *    vVar2Inf;   // maps sat Var into its frame and obj ID
+    // abstraction
+    Vec_Int_t *    vAssigned;  // collects objects whose SAT variables have been created
+    Vec_Int_t *    vIncluded;  // maps obj ID into its status (0=unused; 1=included in abstraction)
+    // components
+    Vec_Int_t *    vPis;       // primary inputs
+    Vec_Int_t *    vPPis;      // pseudo primary inputs
+    Vec_Int_t *    vFlops;     // flops
+    Vec_Int_t *    vNodes;     // nodes
+    // CNF computation
+    Vec_Ptr_t *    vLeaves;
+    Vec_Ptr_t *    vVolume;
+    Vec_Int_t *    vCover;
+    Vec_Ptr_t *    vObj2Cnf;
+    Vec_Int_t *    vLits;
+    // SAT solver
+    sat_solver *   pSat;
+    // statistics
+    clock_t        timeSat;
+    clock_t        timeRef;
+    clock_t        timeTotal;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Adds constant to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_Gla1AddConst( sat_solver * pSat, int iVar, int fCompl )
+{
+    lit Lit = toLitCond( iVar, fCompl );
+    if ( !sat_solver_addclause( pSat, &Lit, &Lit + 1 ) )
+        return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds buffer to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_Gla1AddBuffer( sat_solver * pSat, int iVar0, int iVar1, int fCompl )
+{
+    lit Lits[2];
+
+    Lits[0] = toLitCond( iVar0, 0 );
+    Lits[1] = toLitCond( iVar1, !fCompl );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVar0, 1 );
+    Lits[1] = toLitCond( iVar1, fCompl );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+        return 0;
+
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds buffer to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_Gla1AddNode( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 )
+{
+    lit Lits[3];
+
+    Lits[0] = toLitCond( iVar, 1 );
+    Lits[1] = toLitCond( iVar0, fCompl0 );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVar, 1 );
+    Lits[1] = toLitCond( iVar1, fCompl1 );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVar, 0 );
+    Lits[1] = toLitCond( iVar0, !fCompl0 );
+    Lits[2] = toLitCond( iVar1, !fCompl1 );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) )
+        return 0;
+
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives abstraction components (PIs, PPIs, flops, nodes).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_Gla1CollectAbstr( Aig_Gla1Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, Entry;
+/*
+    // make sure every neighbor of included objects is assigned a variable
+    Vec_IntForEachEntry( p->vIncluded, Entry, i )
+    {
+        if ( Entry == 0 )
+            continue;
+        assert( Entry == 1 );
+        pObj = Aig_ManObj( p->pAig, i );
+        if ( Vec_IntFind( p->vAssigned, Aig_ObjId(pObj) ) == -1 )
+            printf( "Aig_Gla1CollectAbstr(): Object not found\n" );
+        if ( Aig_ObjIsNode(pObj) )
+        {
+            if ( Vec_IntFind( p->vAssigned, Aig_ObjFaninId0(pObj) ) == -1 )
+                printf( "Aig_Gla1CollectAbstr(): Node's fanin is not found\n" );
+            if ( Vec_IntFind( p->vAssigned, Aig_ObjFaninId1(pObj) ) == -1 )
+                printf( "Aig_Gla1CollectAbstr(): Node's fanin is not found\n" );
+        }
+        else if ( Saig_ObjIsLo(p->pAig, pObj) ) 
+        {
+            Aig_Obj_t * pObjLi;
+            pObjLi = Saig_ObjLoToLi(p->pAig, pObj);
+            if ( Vec_IntFind( p->vAssigned, Aig_ObjFaninId0(pObjLi) ) == -1 )
+                printf( "Aig_Gla1CollectAbstr(): Flop's fanin is not found\n" );
+        }
+        else assert( Aig_ObjIsConst1(pObj) );
+    }
+*/
+    Vec_IntClear( p->vPis );
+    Vec_IntClear( p->vPPis );
+    Vec_IntClear( p->vFlops );
+    Vec_IntClear( p->vNodes );
+    Vec_IntForEachEntryReverse( p->vAssigned, Entry, i )
+    {
+        pObj = Aig_ManObj( p->pAig, Entry );
+        if ( Saig_ObjIsPi(p->pAig, pObj) )
+            Vec_IntPush( p->vPis, Aig_ObjId(pObj) );
+        else if ( !Vec_IntEntry(p->vIncluded, Aig_ObjId(pObj)) )
+            Vec_IntPush( p->vPPis, Aig_ObjId(pObj) );
+        else if ( Aig_ObjIsNode(pObj) )
+            Vec_IntPush( p->vNodes, Aig_ObjId(pObj) );
+        else if ( Saig_ObjIsLo(p->pAig, pObj) )
+            Vec_IntPush( p->vFlops, Aig_ObjId(pObj) );
+        else assert( Aig_ObjIsConst1(pObj) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager recursively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_Gla1DeriveAbs_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj )
+{
+    if ( pObj->pData )
+        return;
+    assert( Aig_ObjIsNode(pObj) );
+    Aig_Gla1DeriveAbs_rec( pNew, Aig_ObjFanin0(pObj) );
+    Aig_Gla1DeriveAbs_rec( pNew, Aig_ObjFanin1(pObj) );
+    pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives abstraction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_Gla1DeriveAbs( Aig_Gla1Man_t * p )
+{ 
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i, RetValue;
+    assert( Saig_ManPoNum(p->pAig) == 1 );
+    // start the new manager
+    pNew = Aig_ManStart( 5000 );
+    pNew->pName = Abc_UtilStrsav( p->pAig->pName );
+    // create constant
+    Aig_ManCleanData( p->pAig );
+    Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew);
+    // create PIs
+    Aig_ManForEachObjVec( p->vPis, p->pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi(pNew);
+    // create additional PIs
+    Aig_ManForEachObjVec( p->vPPis, p->pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi(pNew);
+    // create ROs
+    Aig_ManForEachObjVec( p->vFlops, p->pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi(pNew);
+    // create internal nodes
+    Aig_ManForEachObjVec( p->vNodes, p->pAig, pObj, i )
+//        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+        Aig_Gla1DeriveAbs_rec( pNew, pObj );
+    // create PO
+    Saig_ManForEachPo( p->pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    // create RIs
+    Aig_ManForEachObjVec( p->vFlops, p->pAig, pObj, i )
+    {
+        assert( Saig_ObjIsLo(p->pAig, pObj) );
+        pObj = Saig_ObjLoToLi( p->pAig, pObj );
+        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    }
+    Aig_ManSetRegNum( pNew, Vec_IntSize(p->vFlops) );
+    // clean up
+    RetValue = Aig_ManCleanup( pNew );
+    if ( RetValue > 0 )
+        printf( "Aig_Gla1DeriveAbs(): Internal error! Object count mismatch.\n" );
+    assert( RetValue == 0 );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds existing SAT variable or creates a new one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_Gla1FetchVecId( Aig_Gla1Man_t * p, Aig_Obj_t * pObj )
+{
+    int i, iVecId;
+    iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) );
+    if ( iVecId == 0 )
+    {
+        iVecId = Vec_IntSize( p->vVec2Var ) / p->nFrames;
+        for ( i = 0; i < p->nFrames; i++ )
+            Vec_IntPush( p->vVec2Var, 0 );
+        Vec_IntWriteEntry( p->vObj2Vec, Aig_ObjId(pObj), iVecId );
+        Vec_IntPushOrderReverse( p->vAssigned, Aig_ObjId(pObj) );
+    }
+    return iVecId;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds existing SAT variable or creates a new one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_Gla1FetchVar( Aig_Gla1Man_t * p, Aig_Obj_t * pObj, int k )
+{
+    int iVecId, iSatVar;
+    assert( k < p->nFrames );
+    iVecId  = Aig_Gla1FetchVecId( p, pObj );
+    iSatVar = Vec_IntEntry( p->vVec2Var, iVecId * p->nFrames + k );
+    if ( iSatVar == 0 )
+    {
+        iSatVar = Vec_IntSize( p->vVar2Inf ) / 2;
+        Vec_IntPush( p->vVar2Inf, Aig_ObjId(pObj) );
+        Vec_IntPush( p->vVar2Inf, k );
+        Vec_IntWriteEntry( p->vVec2Var, iVecId * p->nFrames + k, iSatVar );
+        sat_solver_setnvars( p->pSat, iSatVar + 1 );
+    }
+    return iSatVar;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds CNF for the given object in the given frame.]
+
+  Description [Returns 0, if the solver becames UNSAT.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_Gla1ObjAddToSolver( Aig_Gla1Man_t * p, Aig_Obj_t * pObj, int k )
+{
+    if ( k == p->nFrames )
+    {
+        int i, j, nVecIds = Vec_IntSize( p->vVec2Var ) / p->nFrames;
+        Vec_Int_t * vVec2VarNew = Vec_IntAlloc( 4 * nVecIds * p->nFrames );
+        for ( i = 0; i < nVecIds; i++ )
+        {
+            for ( j = 0; j < p->nFrames; j++ )
+                Vec_IntPush( vVec2VarNew, Vec_IntEntry( p->vVec2Var, i * p->nFrames + j ) );
+            for ( j = 0; j < p->nFrames; j++ )
+                Vec_IntPush( vVec2VarNew, i ? 0 : -1 );
+        }
+        Vec_IntFree( p->vVec2Var );
+        p->vVec2Var = vVec2VarNew;
+        p->nFrames *= 2;
+    }
+    assert( k < p->nFrames );
+    assert( Vec_IntEntry(p->vIncluded, Aig_ObjId(pObj)) );
+    if ( Aig_ObjIsConst1(pObj) )
+        return Aig_Gla1AddConst( p->pSat, Aig_Gla1FetchVar(p, pObj, k), 0 );
+    if ( Saig_ObjIsLo(p->pAig, pObj) )
+    {
+        Aig_Obj_t * pObjLi = Saig_ObjLoToLi(p->pAig, pObj);
+        if ( k == 0 )
+        {
+            Aig_Gla1FetchVecId( p, Aig_ObjFanin0(pObjLi) );
+            return Aig_Gla1AddConst( p->pSat, Aig_Gla1FetchVar(p, pObj, k), 1 );
+        }
+        return Aig_Gla1AddBuffer( p->pSat, Aig_Gla1FetchVar(p, pObj, k), 
+                   Aig_Gla1FetchVar(p, Aig_ObjFanin0(pObjLi), k-1), 
+                   Aig_ObjFaninC0(pObjLi) );
+    }
+    else
+    { 
+        Vec_Int_t * vClauses;
+        int i, Entry;
+        assert( Aig_ObjIsNode(pObj) );
+        if ( p->vObj2Cnf == NULL )
+            return Aig_Gla1AddNode( p->pSat, Aig_Gla1FetchVar(p, pObj, k), 
+                       Aig_Gla1FetchVar(p, Aig_ObjFanin0(pObj), k), 
+                       Aig_Gla1FetchVar(p, Aig_ObjFanin1(pObj), k), 
+                       Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) );
+        // derive clauses
+        assert( pObj->fMarkA );
+        vClauses = (Vec_Int_t *)Vec_PtrEntry( p->vObj2Cnf, Aig_ObjId(pObj) );
+        if ( vClauses == NULL )
+        {
+            Vec_PtrWriteEntry( p->vObj2Cnf, Aig_ObjId(pObj), (vClauses = Vec_IntAlloc(16)) );
+            Cnf_ComputeClauses( p->pAig, pObj, p->vLeaves, p->vVolume, NULL, p->vCover, vClauses );
+        }
+        // derive variables
+        Cnf_CollectLeaves( pObj, p->vLeaves, 0 );
+        Vec_PtrForEachEntry( Aig_Obj_t *, p->vLeaves, pObj, i )
+            Aig_Gla1FetchVar( p, pObj, k );
+        // translate clauses
+        assert( Vec_IntSize(vClauses) >= 2 );
+        assert( Vec_IntEntry(vClauses, 0) == 0 );
+        Vec_IntForEachEntry( vClauses, Entry, i )
+        {
+            if ( Entry == 0 )
+            {
+                Vec_IntClear( p->vLits );
+                continue;
+            }
+            Vec_IntPush( p->vLits, (Entry & 1) ^ (2 * Aig_Gla1FetchVar(p, Aig_ManObj(p->pAig, Entry >> 1), k)) );
+            if ( i == Vec_IntSize(vClauses) - 1 || Vec_IntEntry(vClauses, i+1) == 0 )
+            {
+                if ( !sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntArray(p->vLits)+Vec_IntSize(p->vLits) ) )
+                    return 0;
+            }
+        }       
+        return 1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of neighbors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_Gla1CollectAssigned( Aig_Gla1Man_t * p, Vec_Int_t * vGateClasses )
+{
+    Aig_Obj_t * pObj;
+    int i, Entry;
+    Vec_IntForEachEntryReverse( vGateClasses, Entry, i )
+    {
+        if ( Entry == 0 )
+            continue;
+        assert( Entry == 1 );
+        pObj = Aig_ManObj( p->pAig, i );
+        Aig_Gla1FetchVecId( p, pObj );
+        if ( Aig_ObjIsNode(pObj) )
+        {
+            Aig_Gla1FetchVecId( p, Aig_ObjFanin0(pObj) );
+            Aig_Gla1FetchVecId( p, Aig_ObjFanin1(pObj) );
+        }
+        else if ( Saig_ObjIsLo(p->pAig, pObj) )
+            Aig_Gla1FetchVecId( p, Aig_ObjFanin0(Saig_ObjLoToLi(p->pAig, pObj)) );
+        else assert( Aig_ObjIsConst1(pObj) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Gla1Man_t * Aig_Gla1ManStart( Aig_Man_t * pAig, Vec_Int_t * vGateClassesOld, int fNaiveCnf )
+{
+    Aig_Gla1Man_t * p;
+    int i;
+
+    p = ABC_CALLOC( Aig_Gla1Man_t, 1 );
+    p->pAig      = pAig;
+    p->nFrames   = 32;
+
+    // unrolling
+    p->vObj2Vec  = Vec_IntStart( Aig_ManObjNumMax(pAig) );
+    p->vVec2Var  = Vec_IntAlloc( 1 << 20 );
+    p->vVar2Inf  = Vec_IntAlloc( 1 << 20 );
+
+    // skip first vector ID
+    for ( i = 0; i < p->nFrames; i++ )
+        Vec_IntPush( p->vVec2Var, -1 );
+    // skip  first SAT variable
+    Vec_IntPush( p->vVar2Inf, -1 );
+    Vec_IntPush( p->vVar2Inf, -1 );
+
+    // abstraction
+    p->vAssigned = Vec_IntAlloc( 1000 );
+    if ( vGateClassesOld )
+    {
+        p->vIncluded = Vec_IntDup( vGateClassesOld );
+        Aig_Gla1CollectAssigned( p, vGateClassesOld );
+        assert( fNaiveCnf );
+    }
+    else
+        p->vIncluded = Vec_IntStart( Aig_ManObjNumMax(pAig) );
+
+    // components
+    p->vPis      = Vec_IntAlloc( 1000 );
+    p->vPPis     = Vec_IntAlloc( 1000 );
+    p->vFlops    = Vec_IntAlloc( 1000 );
+    p->vNodes    = Vec_IntAlloc( 1000 );
+
+    // CNF computation
+    if ( !fNaiveCnf )
+    {
+        p->vLeaves   = Vec_PtrAlloc( 100 );
+        p->vVolume   = Vec_PtrAlloc( 100 );
+        p->vCover    = Vec_IntAlloc( 1 << 16 );
+        p->vObj2Cnf  = Vec_PtrStart( Aig_ManObjNumMax(pAig) );
+        p->vLits     = Vec_IntAlloc( 100 );
+        Cnf_DeriveFastMark( pAig );
+    }
+
+    // start the SAT solver
+    p->pSat = sat_solver_new();
+    sat_solver_setnvars( p->pSat, 256 );
+    return p;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_Gla1ManStop( Aig_Gla1Man_t * p )
+{
+    Vec_IntFreeP( &p->vObj2Vec );
+    Vec_IntFreeP( &p->vVec2Var );
+    Vec_IntFreeP( &p->vVar2Inf );
+
+    Vec_IntFreeP( &p->vAssigned );
+    Vec_IntFreeP( &p->vIncluded );
+
+    Vec_IntFreeP( &p->vPis );
+    Vec_IntFreeP( &p->vPPis );
+    Vec_IntFreeP( &p->vFlops );
+    Vec_IntFreeP( &p->vNodes );
+
+    if ( p->vObj2Cnf )
+    {
+        Vec_PtrFreeP( &p->vLeaves );
+        Vec_PtrFreeP( &p->vVolume );
+        Vec_IntFreeP( &p->vCover );
+        Vec_VecFreeP( (Vec_Vec_t **)&p->vObj2Cnf );
+        Vec_IntFreeP( &p->vLits );
+        Aig_ManCleanMarkA( p->pAig );
+    }
+
+    if ( p->pSat )
+        sat_solver_delete( p->pSat );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Aig_Gla1DeriveCex( Aig_Gla1Man_t * p, int iFrame )
+{
+    Abc_Cex_t * pCex;
+    Aig_Obj_t * pObj;
+    int i, f, iVecId, iSatId;
+    pCex = Abc_CexAlloc( Vec_IntSize(p->vFlops), Vec_IntSize(p->vPis) + Vec_IntSize(p->vPPis), iFrame+1 );
+    pCex->iFrame = iFrame;
+    Aig_ManForEachObjVec( p->vPis, p->pAig, pObj, i )
+    {
+        iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) );
+        assert( iVecId > 0 );
+        for ( f = 0; f <= iFrame; f++ )
+        {
+            iSatId = Vec_IntEntry( p->vVec2Var, iVecId * p->nFrames + f );
+            if ( iSatId == 0 )
+                continue;
+            assert( iSatId > 0 );
+            if ( sat_solver_var_value(p->pSat, iSatId) )
+                Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + i );
+        }
+    }
+    Aig_ManForEachObjVec( p->vPPis, p->pAig, pObj, i )
+    {
+        iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) );
+        assert( iVecId > 0 );
+        for ( f = 0; f <= iFrame; f++ )
+        {
+            iSatId = Vec_IntEntry( p->vVec2Var, iVecId * p->nFrames + f );
+            if ( iSatId == 0 )
+                continue;
+            assert( iSatId > 0 );
+            if ( sat_solver_var_value(p->pSat, iSatId) )
+                Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + Vec_IntSize(p->vPis) + i );
+        }
+    }
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints current abstraction statistics.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_Gla1PrintAbstr( Aig_Gla1Man_t * p, int f, int r, int v, int c )
+{
+    if ( r == 0 )
+        printf( "== %3d ==", f );
+    else
+        printf( "         " );
+    printf( " %4d  PI =%6d  PPI =%6d  FF =%6d  Node =%6d  Var =%7d  Conf =%6d\n", 
+        r, Vec_IntSize(p->vPis), Vec_IntSize(p->vPPis), Vec_IntSize(p->vFlops), Vec_IntSize(p->vNodes), v, c );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints current abstraction statistics.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_Gla1ExtendIncluded( Aig_Gla1Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, k;
+    Aig_ManForEachNode( p->pAig, pObj, i )
+    {
+        if ( !Vec_IntEntry( p->vIncluded, i ) )
+            continue;
+        Cnf_ComputeClauses( p->pAig, pObj, p->vLeaves, p->vVolume, NULL, p->vCover, p->vNodes );
+        Vec_PtrForEachEntry( Aig_Obj_t *, p->vVolume, pObj, k )
+        {
+            assert( Aig_ObjId(pObj) <= i );
+            Vec_IntWriteEntry( p->vIncluded, Aig_ObjId(pObj), 1 );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs gate-level localization abstraction.]
+
+  Description [Returns array of objects included in the abstraction. This array
+  may contain only const1, flop outputs, and internal nodes, that is, objects
+  that should have clauses added to the SAT solver.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Aig_Gla1ManPerform( Aig_Man_t * pAig, Vec_Int_t * vGateClassesOld, int nStart, int nFramesMax, int nConfLimit, int TimeLimit, int fNaiveCnf, int fVerbose, int * piFrame )
+{
+    Vec_Int_t * vResult = NULL;
+    Aig_Gla1Man_t * p;
+    Aig_Man_t * pAbs;
+    Aig_Obj_t * pObj;
+    Abc_Cex_t * pCex;
+    Vec_Int_t * vPPiRefine;
+    int f, g, r, i, iSatVar, Lit, Entry, RetValue;
+    int nConfBef, nConfAft;
+    clock_t clk, clkTotal = clock();
+    clock_t nTimeToStop = TimeLimit ? TimeLimit * CLOCKS_PER_SEC + clock(): 0;
+    assert( Saig_ManPoNum(pAig) == 1 );
+
+    if ( nFramesMax == 0 )
+        nFramesMax = ABC_INFINITY;
+
+    if ( fVerbose )
+    {
+        if ( TimeLimit )
+            printf( "Abstracting from frame %d to frame %d with timeout %d sec.\n", nStart, nFramesMax, TimeLimit );
+        else
+            printf( "Abstracting from frame %d to frame %d with no timeout.\n", nStart, nFramesMax );
+    }
+
+    // start the solver
+    p = Aig_Gla1ManStart( pAig, vGateClassesOld, fNaiveCnf );
+    p->nFramesMax = nFramesMax;
+    p->nConfLimit = nConfLimit;
+    p->fVerbose   = fVerbose;
+
+    // include constant node
+    Vec_IntWriteEntry( p->vIncluded, 0, 1 );
+    Aig_Gla1FetchVecId( p, Aig_ManConst1(pAig) );
+
+    // set runtime limit
+    if ( TimeLimit )
+        sat_solver_set_runtime_limit( p->pSat, nTimeToStop );
+
+    // iterate over the timeframes
+    for ( f = 0; f < nFramesMax; f++ )
+    {
+        // initialize abstraction in this timeframe
+        Aig_ManForEachObjVec( p->vAssigned, pAig, pObj, i )
+            if ( Vec_IntEntry(p->vIncluded, Aig_ObjId(pObj)) )
+                if ( !Aig_Gla1ObjAddToSolver( p, pObj, f ) )
+                    printf( "Error!  SAT solver became UNSAT.\n" );
+
+        // skip checking if we are not supposed to
+        if ( f < nStart )
+            continue;
+
+        // create output literal to represent property failure
+        pObj    = Aig_ManCo( pAig, 0 );
+        iSatVar = Aig_Gla1FetchVar( p, Aig_ObjFanin0(pObj), f );
+        Lit     = toLitCond( iSatVar, Aig_ObjFaninC0(pObj) );
+
+        // try solving the abstraction
+        Aig_Gla1CollectAbstr( p );
+        for ( r = 0; r < ABC_INFINITY; r++ )
+        {
+            // try to find a counter-example
+            clk = clock();
+            nConfBef = p->pSat->stats.conflicts;
+            RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, 
+                (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+            nConfAft = p->pSat->stats.conflicts;
+            p->timeSat += clock() - clk;
+            if ( RetValue != l_True )
+            {
+                if ( fVerbose )
+                {
+                    if ( r == 0 )
+                        printf( "== %3d ==", f );
+                    else
+                        printf( "         " );
+                    if ( TimeLimit && clock() > nTimeToStop )
+                        printf( "       SAT solver timed out after %d seconds.\n", TimeLimit );
+                    else if ( RetValue != l_False )
+                        printf( "       SAT solver returned UNDECIDED after %5d conflicts.\n", nConfAft - nConfBef );
+                    else
+                    {
+                        printf( "       SAT solver returned UNSAT after %5d conflicts.  ", nConfAft - nConfBef );
+                        Abc_PrintTime( 1, "Total time", clock() - clkTotal );
+                    }
+                }
+                break;
+            }
+            clk = clock();
+            // derive abstraction
+            pAbs = Aig_Gla1DeriveAbs( p );
+            // derive counter-example
+            pCex = Aig_Gla1DeriveCex( p, f );
+            // verify the counter-example
+            RetValue = Saig_ManVerifyCex( pAbs, pCex );
+            if ( RetValue == 0 )
+                printf( "Error!  CEX is invalid.\n" );
+            // perform refinement
+            vPPiRefine = Saig_ManCbaFilterInputs( pAbs, Vec_IntSize(p->vPis), pCex, 0 );
+            Vec_IntForEachEntry( vPPiRefine, Entry, i )
+            {
+                pObj = Aig_ManObj( pAig, Vec_IntEntry(p->vPPis, Entry) );
+                assert( Aig_ObjIsNode(pObj) || Saig_ObjIsLo(p->pAig, pObj) );
+                assert( Vec_IntEntry( p->vIncluded, Aig_ObjId(pObj) ) == 0 );
+                Vec_IntWriteEntry( p->vIncluded, Aig_ObjId(pObj), 1 );
+                for ( g = 0; g <= f; g++ )
+                    if ( !Aig_Gla1ObjAddToSolver( p, pObj, g ) )
+                        printf( "Error!  SAT solver became UNSAT.\n" );
+            }
+            if ( Vec_IntSize(vPPiRefine) == 0 )
+            {
+                Vec_IntFreeP( &p->vIncluded );
+                Vec_IntFree( vPPiRefine );
+                Aig_ManStop( pAbs );
+                Abc_CexFree( pCex );
+                break;
+            }
+            Vec_IntFree( vPPiRefine );
+            Aig_ManStop( pAbs );
+            Abc_CexFree( pCex );
+            p->timeRef += clock() - clk;
+
+            // prepare abstraction
+            Aig_Gla1CollectAbstr( p );
+            if ( fVerbose )
+                Aig_Gla1PrintAbstr( p, f, r, p->pSat->size, nConfAft - nConfBef );
+        }
+        if ( RetValue != l_False )
+            break;
+    }
+    p->timeTotal = clock() - clkTotal;
+    if ( f == nFramesMax )
+        printf( "Finished %d frames without exceeding conflict limit (%d).\n", f, nConfLimit );
+    else if ( p->vIncluded == NULL )
+        printf( "The problem is SAT in frame %d. The CEX is currently not produced.\n", f );
+    else
+        printf( "Ran out of conflict limit (%d) at frame %d.\n", nConfLimit, f );
+    *piFrame = f;
+    // print stats
+    if ( fVerbose )
+    {
+        ABC_PRTP( "Sat   ", p->timeSat,   p->timeTotal );
+        ABC_PRTP( "Ref   ", p->timeRef,   p->timeTotal );
+        ABC_PRTP( "Total ", p->timeTotal, p->timeTotal );
+    }
+    // prepare return value
+    if ( !fNaiveCnf && p->vIncluded )
+        Aig_Gla1ExtendIncluded( p );
+    vResult = p->vIncluded;  p->vIncluded = NULL;
+    Aig_Gla1ManStop( p );
+    return vResult;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigGlaPba.c b/abc-build/src/aig/saig/saigGlaPba.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigGlaPba.c
@@ -0,0 +1,589 @@
+/**CFile****************************************************************
+
+  FileName    [saigGlaPba.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Gate level abstraction.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigGlaPba.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include "saig.h"
+#include "sat/bsat/satSolver.h"
+#include "sat/bsat/satStore.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Aig_Gla2Man_t_ Aig_Gla2Man_t;
+struct Aig_Gla2Man_t_
+{
+    // user data
+    Aig_Man_t *    pAig;
+    int            nStart;
+    int            nFramesMax;
+    int            fVerbose;
+    // unrolling
+    Vec_Int_t *    vObj2Vec;   // maps obj ID into its vec ID
+    Vec_Int_t *    vVec2Var;   // maps vec ID into its sat Var (nFrames per vec ID)
+    Vec_Int_t *    vVar2Inf;   // maps sat Var into its frame and obj ID
+    // clause mapping
+    Vec_Int_t *    vCla2Obj;   // maps clause into its root object
+    Vec_Int_t *    vCla2Fra;   // maps clause into its frame
+    Vec_Int_t *    vVec2Use;   // maps vec ID into its used frames (nFrames per vec ID)
+    // SAT solver
+    sat_solver *   pSat;
+    // statistics
+    clock_t        timePre;
+    clock_t        timeSat;
+    clock_t        timeTotal;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    [Adds constant to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_Gla2AddConst( sat_solver * pSat, int iVar, int fCompl )
+{
+    lit Lit = toLitCond( iVar, fCompl );
+    if ( !sat_solver_addclause( pSat, &Lit, &Lit + 1 ) )
+        return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds buffer to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_Gla2AddBuffer( sat_solver * pSat, int iVar0, int iVar1, int fCompl )
+{
+    lit Lits[2];
+
+    Lits[0] = toLitCond( iVar0, 0 );
+    Lits[1] = toLitCond( iVar1, !fCompl );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVar0, 1 );
+    Lits[1] = toLitCond( iVar1, fCompl );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+        return 0;
+
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds buffer to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_Gla2AddNode( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 )
+{
+    lit Lits[3];
+
+    Lits[0] = toLitCond( iVar, 1 );
+    Lits[1] = toLitCond( iVar0, fCompl0 );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVar, 1 );
+    Lits[1] = toLitCond( iVar1, fCompl1 );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVar, 0 );
+    Lits[1] = toLitCond( iVar0, !fCompl0 );
+    Lits[2] = toLitCond( iVar1, !fCompl1 );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) )
+        return 0;
+
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds existing SAT variable or creates a new one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_Gla2FetchVar( Aig_Gla2Man_t * p, Aig_Obj_t * pObj, int k )
+{
+    int i, iVecId, iSatVar;
+    assert( k < p->nFramesMax );
+    iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) );
+    if ( iVecId == 0 )
+    {
+        iVecId = Vec_IntSize( p->vVec2Var ) / p->nFramesMax;
+        for ( i = 0; i < p->nFramesMax; i++ )
+            Vec_IntPush( p->vVec2Var, 0 );
+        Vec_IntWriteEntry( p->vObj2Vec, Aig_ObjId(pObj), iVecId );
+    }
+    iSatVar = Vec_IntEntry( p->vVec2Var, iVecId * p->nFramesMax + k );
+    if ( iSatVar == 0 )
+    {
+        iSatVar = Vec_IntSize( p->vVar2Inf ) / 2;
+        Vec_IntPush( p->vVar2Inf, Aig_ObjId(pObj) );
+        Vec_IntPush( p->vVar2Inf, k );
+        Vec_IntWriteEntry( p->vVec2Var, iVecId * p->nFramesMax + k, iSatVar );
+    }
+    return iSatVar;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns variables to the AIG nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_Gla2AssignVars_rec( Aig_Gla2Man_t * p, Aig_Obj_t * pObj, int f )
+{
+    int nVars = Vec_IntSize(p->vVar2Inf);
+    Aig_Gla2FetchVar( p, pObj, f );
+    if ( nVars == Vec_IntSize(p->vVar2Inf) )
+        return;
+    if ( Aig_ObjIsConst1(pObj) )
+        return;
+    if ( Saig_ObjIsPo( p->pAig, pObj ) )
+    {
+        Aig_Gla2AssignVars_rec( p, Aig_ObjFanin0(pObj), f );
+        return;
+    }
+    if ( Aig_ObjIsCi( pObj ) )
+    {
+        if ( Saig_ObjIsLo(p->pAig, pObj) && f > 0 )
+            Aig_Gla2AssignVars_rec( p, Aig_ObjFanin0( Saig_ObjLoToLi(p->pAig, pObj) ), f-1 );
+        return;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    Aig_Gla2AssignVars_rec( p, Aig_ObjFanin0(pObj), f );
+    Aig_Gla2AssignVars_rec( p, Aig_ObjFanin1(pObj), f );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_Gla2CreateSatSolver( Aig_Gla2Man_t * p )
+{
+    Vec_Int_t * vPoLits;
+    Aig_Obj_t * pObj;
+    int i, f, ObjId, nVars, RetValue = 1;
+
+    // assign variables
+    for ( f = p->nFramesMax - 1; f >= 0; f-- )
+//    for ( f = 0; f < p->nFramesMax; f++ )
+        Aig_Gla2AssignVars_rec( p, Aig_ManCo(p->pAig, 0), f );
+
+    // create SAT solver
+    p->pSat = sat_solver_new();
+    sat_solver_store_alloc( p->pSat ); 
+    sat_solver_setnvars( p->pSat, Vec_IntSize(p->vVar2Inf)/2 );
+
+    // add clauses
+    nVars = Vec_IntSize( p->vVar2Inf );
+    Vec_IntForEachEntryDouble( p->vVar2Inf, ObjId, f, i )
+    {
+        if ( ObjId == -1 )
+            continue;
+        pObj = Aig_ManObj( p->pAig, ObjId );
+        if ( Aig_ObjIsNode(pObj) )
+        {
+            RetValue &= Aig_Gla2AddNode( p->pSat, Aig_Gla2FetchVar(p, pObj, f), 
+                                                  Aig_Gla2FetchVar(p, Aig_ObjFanin0(pObj), f), 
+                                                  Aig_Gla2FetchVar(p, Aig_ObjFanin1(pObj), f), 
+                                                  Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) );
+            Vec_IntPush( p->vCla2Obj, ObjId );
+            Vec_IntPush( p->vCla2Obj, ObjId );
+            Vec_IntPush( p->vCla2Obj, ObjId );
+
+            Vec_IntPush( p->vCla2Fra, f );
+            Vec_IntPush( p->vCla2Fra, f );
+            Vec_IntPush( p->vCla2Fra, f );
+        }
+        else if ( Saig_ObjIsLo(p->pAig, pObj) )
+        {
+            if ( f == 0 )
+            {
+                RetValue &= Aig_Gla2AddConst( p->pSat, Aig_Gla2FetchVar(p, pObj, f), 1 );
+                Vec_IntPush( p->vCla2Obj, ObjId );
+
+                Vec_IntPush( p->vCla2Fra, f );
+            }
+            else
+            {
+                Aig_Obj_t * pObjLi = Saig_ObjLoToLi(p->pAig, pObj);
+                RetValue &= Aig_Gla2AddBuffer( p->pSat, Aig_Gla2FetchVar(p, pObj, f), 
+                                                        Aig_Gla2FetchVar(p, Aig_ObjFanin0(pObjLi), f-1), 
+                                                        Aig_ObjFaninC0(pObjLi) );
+                Vec_IntPush( p->vCla2Obj, ObjId );
+                Vec_IntPush( p->vCla2Obj, ObjId );
+
+                Vec_IntPush( p->vCla2Fra, f );
+                Vec_IntPush( p->vCla2Fra, f );
+            }
+        }
+        else if ( Saig_ObjIsPo(p->pAig, pObj) )
+        {
+            RetValue &= Aig_Gla2AddBuffer( p->pSat, Aig_Gla2FetchVar(p, pObj, f), 
+                                                    Aig_Gla2FetchVar(p, Aig_ObjFanin0(pObj), f), 
+                                                    Aig_ObjFaninC0(pObj) );
+            Vec_IntPush( p->vCla2Obj, ObjId );
+            Vec_IntPush( p->vCla2Obj, ObjId );
+
+            Vec_IntPush( p->vCla2Fra, f );
+            Vec_IntPush( p->vCla2Fra, f );
+        }
+        else if ( Aig_ObjIsConst1(pObj) )
+        {
+            RetValue &= Aig_Gla2AddConst( p->pSat, Aig_Gla2FetchVar(p, pObj, f), 0 );
+            Vec_IntPush( p->vCla2Obj, ObjId );
+
+            Vec_IntPush( p->vCla2Fra, f );
+        }
+        else assert( Saig_ObjIsPi(p->pAig, pObj) );
+    }
+
+    // add output clause
+    vPoLits = Vec_IntAlloc( p->nFramesMax );
+    for ( f = p->nStart; f < p->nFramesMax; f++ )
+        Vec_IntPush( vPoLits, 2 * Aig_Gla2FetchVar(p, Aig_ManCo(p->pAig, 0), f) );
+    RetValue &= sat_solver_addclause( p->pSat, Vec_IntArray(vPoLits), Vec_IntArray(vPoLits) + Vec_IntSize(vPoLits) );
+    Vec_IntFree( vPoLits );
+    Vec_IntPush( p->vCla2Obj, 0 );
+    Vec_IntPush( p->vCla2Fra, 0 );
+    assert( Vec_IntSize(p->vCla2Fra) == Vec_IntSize(p->vCla2Obj) );
+
+    assert( nVars == Vec_IntSize(p->vVar2Inf) );
+    assert( ((Sto_Man_t *)p->pSat->pStore)->nClauses == Vec_IntSize(p->vCla2Obj) );
+//    Sto_ManDumpClauses( ((Sto_Man_t *)p->pSat->pStore), "temp_sto.cnf" );
+    sat_solver_store_mark_roots( p->pSat ); 
+
+    if ( p->fVerbose )
+        printf( "The resulting SAT problem contains %d variables and %d clauses.\n", 
+            p->pSat->size, p->pSat->stats.clauses );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Gla2Man_t * Aig_Gla2ManStart( Aig_Man_t * pAig, int nStart, int nFramesMax, int fVerbose )
+{
+    Aig_Gla2Man_t * p;
+    int i;
+
+    p = ABC_CALLOC( Aig_Gla2Man_t, 1 );
+    p->pAig       = pAig;
+
+    p->vObj2Vec   = Vec_IntStart( Aig_ManObjNumMax(pAig) );
+    p->vVec2Var   = Vec_IntAlloc( 1 << 20 );
+    p->vVar2Inf   = Vec_IntAlloc( 1 << 20 );
+    p->vCla2Obj   = Vec_IntAlloc( 1 << 20 );
+    p->vCla2Fra   = Vec_IntAlloc( 1 << 20 );
+
+    // skip first vector ID
+    p->nStart     = nStart;
+    p->nFramesMax = nFramesMax;
+    p->fVerbose   = fVerbose;
+    for ( i = 0; i < p->nFramesMax; i++ )
+        Vec_IntPush( p->vVec2Var, -1 );
+
+    // skip  first SAT variable
+    Vec_IntPush( p->vVar2Inf, -1 );
+    Vec_IntPush( p->vVar2Inf, -1 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_Gla2ManStop( Aig_Gla2Man_t * p )
+{
+    Vec_IntFreeP( &p->vObj2Vec );
+    Vec_IntFreeP( &p->vVec2Var );
+    Vec_IntFreeP( &p->vVar2Inf );
+    Vec_IntFreeP( &p->vCla2Obj );
+    Vec_IntFreeP( &p->vCla2Fra );
+    Vec_IntFreeP( &p->vVec2Use );
+
+    if ( p->pSat )
+        sat_solver_delete( p->pSat );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the set of clauses involved in the UNSAT core.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_AbsSolverUnsatCore( sat_solver * pSat, int nConfMax, int fVerbose, int * piRetValue )
+{
+    Vec_Int_t * vCore;
+    void * pSatCnf; 
+    Intp_Man_t * pManProof;
+    int RetValue;
+    clock_t clk = clock();
+    if ( piRetValue )
+        *piRetValue = -1;
+    // solve the problem
+    RetValue = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( RetValue == l_Undef )
+    {
+        printf( "Conflict limit is reached.\n" );
+        return NULL;
+    }
+    if ( RetValue == l_True )
+    {
+        printf( "The BMC problem is SAT.\n" );
+        if ( piRetValue )
+            *piRetValue = 0;
+        return NULL;
+    }
+    if ( fVerbose )
+    {
+        printf( "SAT solver returned UNSAT after %7d conflicts.      ", (int)pSat->stats.conflicts );
+        Abc_PrintTime( 1, "Time", clock() - clk );
+    }
+    assert( RetValue == l_False );
+    pSatCnf = sat_solver_store_release( pSat ); 
+    // derive the UNSAT core
+    clk = clock();
+    pManProof = Intp_ManAlloc();
+    vCore = (Vec_Int_t *)Intp_ManUnsatCore( pManProof, (Sto_Man_t *)pSatCnf, 0, 0 );
+    Intp_ManFree( pManProof );
+    if ( fVerbose )
+    {
+        printf( "SAT core contains %8d clauses (out of %8d).   ", Vec_IntSize(vCore), sat_solver_nclauses(pSat) );
+        Abc_PrintTime( 1, "Time", clock() - clk );
+    }
+    Sto_ManFree( (Sto_Man_t *)pSatCnf );
+    return vCore;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects abstracted objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Aig_Gla2ManCollect( Aig_Gla2Man_t * p, Vec_Int_t * vCore )
+{
+    Vec_Int_t * vResult;
+    Aig_Obj_t * pObj;
+    int i, ClaId, iVecId;
+//    p->vVec2Use = Vec_IntStart( Vec_IntSize(p->vVec2Var) );
+
+    vResult = Vec_IntStart( Aig_ManObjNumMax(p->pAig) );
+    Vec_IntWriteEntry( vResult, 0, 1 ); // add const1
+    Vec_IntForEachEntry( vCore, ClaId, i )
+    {
+        pObj = Aig_ManObj( p->pAig, Vec_IntEntry(p->vCla2Obj, ClaId) );
+        if ( Saig_ObjIsPi(p->pAig, pObj) || Saig_ObjIsPo(p->pAig, pObj) || Aig_ObjIsConst1(pObj) )
+            continue;
+        assert( Saig_ObjIsLo(p->pAig, pObj) || Aig_ObjIsNode(pObj) );
+        Vec_IntWriteEntry( vResult, Aig_ObjId(pObj), 1 );
+/*
+        // add flop inputs with multiple fanouts
+        if ( Saig_ObjIsLo(p->pAig, pObj) )
+        {
+            Aig_Obj_t * pObjLi = Saig_ObjLoToLi(p->pAig, pObj);
+            if ( !Saig_ObjIsPi(p->pAig, Aig_ObjFanin0(pObjLi)) )
+//            if ( Aig_ObjRefs( Aig_ObjFanin0(pObjLi) ) > 1 )
+                Vec_IntWriteEntry( vResult, Aig_ObjFaninId0(pObjLi), 1 );
+        }
+        else
+        {
+            if ( !Saig_ObjIsPi(p->pAig, Aig_ObjFanin0(pObj)) )
+                Vec_IntWriteEntry( vResult, Aig_ObjFaninId0(pObj), 1 );
+            if ( !Saig_ObjIsPi(p->pAig, Aig_ObjFanin1(pObj)) )
+                Vec_IntWriteEntry( vResult, Aig_ObjFaninId1(pObj), 1 );
+        }
+*/
+        if ( p->vVec2Use )
+        {
+            iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) );
+            Vec_IntWriteEntry( p->vVec2Use, iVecId * p->nFramesMax + Vec_IntEntry(p->vCla2Fra, ClaId), 1 );
+        }
+    }
+//    printf( "Number of entries %d\n", Vec_IntCountPositive(vResult) );
+
+    // count the number of objects in each frame
+    if ( p->vVec2Use )
+    {
+        Vec_Int_t * vCounts = Vec_IntStart( p->nFramesMax );
+        int v, f, Entry, nVecIds = Vec_IntSize(p->vVec2Use) / p->nFramesMax;
+        for ( f = 0; f < p->nFramesMax; f++ )
+        for ( v = 0; v < nVecIds; v++ )
+            if ( Vec_IntEntry( p->vVec2Use, v * p->nFramesMax + f ) )
+                Vec_IntAddToEntry( vCounts, f, 1 );
+        Vec_IntForEachEntry( vCounts, Entry, f )
+            printf( "%d ", Entry );
+        printf( "\n" );
+        Vec_IntFree( vCounts );
+    }
+    return vResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs gate-level localization abstraction.]
+
+  Description [Returns array of objects included in the abstraction. This array
+  may contain only const1, flop outputs, and internal nodes, that is, objects
+  that should have clauses added to the SAT solver.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Aig_Gla2ManPerform( Aig_Man_t * pAig, int nStart, int nFramesMax, int nConfLimit, int TimeLimit, int fSkipRand, int fVerbose )
+{
+    Aig_Gla2Man_t * p;
+    Vec_Int_t * vCore, * vResult;
+    clock_t nTimeToStop = TimeLimit ? TimeLimit * CLOCKS_PER_SEC + clock(): 0;
+    clock_t clk, clk2 = clock();
+    assert( Saig_ManPoNum(pAig) == 1 );
+
+    if ( fVerbose )
+    {
+        if ( TimeLimit )
+            printf( "Abstracting from frame %d to frame %d with timeout %d sec.\n", nStart, nFramesMax, TimeLimit );
+        else
+            printf( "Abstracting from frame %d to frame %d with no timeout.\n", nStart, nFramesMax );
+    }
+
+    // start the solver
+    clk = clock();
+    p = Aig_Gla2ManStart( pAig, nStart, nFramesMax, fVerbose );
+    if ( !Aig_Gla2CreateSatSolver( p ) )
+    {
+        printf( "Error!  SAT solver became UNSAT.\n" );
+        Aig_Gla2ManStop( p );
+        return NULL;
+    }
+    sat_solver_set_random( p->pSat, fSkipRand );
+    p->timePre += clock() - clk;
+
+    // set runtime limit
+    if ( TimeLimit )
+        sat_solver_set_runtime_limit( p->pSat, nTimeToStop );
+
+    // compute UNSAT core
+    clk = clock();
+    vCore = Saig_AbsSolverUnsatCore( p->pSat, nConfLimit, fVerbose, NULL );
+    if ( vCore == NULL )
+    {
+        Aig_Gla2ManStop( p );
+        return NULL;
+    }
+    p->timeSat += clock() - clk;
+    p->timeTotal += clock() - clk2;
+
+    // print stats
+    if ( fVerbose )
+    {
+        ABC_PRTP( "Pre   ", p->timePre,   p->timeTotal );
+        ABC_PRTP( "Sat   ", p->timeSat,   p->timeTotal );
+        ABC_PRTP( "Total ", p->timeTotal, p->timeTotal );
+    }
+
+    // prepare return value
+    vResult = Aig_Gla2ManCollect( p, vCore );
+    Vec_IntFree( vCore );
+    Aig_Gla2ManStop( p );
+    return vResult;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigGlaPba2.c b/abc-build/src/aig/saig/saigGlaPba2.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigGlaPba2.c
@@ -0,0 +1,558 @@
+/**CFile****************************************************************
+
+  FileName    [saigGlaPba.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Gate level abstraction.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigGlaPba.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include "saig.h"
+#include "sat/bsat/satSolver2.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Aig_Gla3Man_t_ Aig_Gla3Man_t;
+struct Aig_Gla3Man_t_
+{
+    // user data
+    Aig_Man_t *    pAig;
+    int            nStart;
+    int            nFramesMax;
+    int            fVerbose;
+    // unrolling
+    Vec_Int_t *    vObj2Vec;   // maps obj ID into its vec ID
+    Vec_Int_t *    vVec2Var;   // maps vec ID into its sat Var (nFrames per vec ID)
+    Vec_Int_t *    vVar2Inf;   // maps sat Var into its frame and obj ID
+    // clause mapping
+    Vec_Int_t *    vCla2Obj;   // maps clause into its root object
+    Vec_Int_t *    vCla2Fra;   // maps clause into its frame
+    Vec_Int_t *    vVec2Use;   // maps vec ID into its used frames (nFrames per vec ID)
+    // SAT solver
+    sat_solver2 *  pSat;
+    // statistics
+    clock_t        timePre;
+    clock_t        timeSat;
+    clock_t        timeTotal;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+#define ABC_CPS 1000
+
+/**Function*************************************************************
+
+  Synopsis    [Adds constant to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_Gla3AddConst( sat_solver2 * pSat, int iVar, int fCompl )
+{
+    lit Lit = toLitCond( iVar, fCompl );
+    if ( !sat_solver2_addclause( pSat, &Lit, &Lit + 1, 0 ) )
+        return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds buffer to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_Gla3AddBuffer( sat_solver2 * pSat, int iVar0, int iVar1, int fCompl )
+{
+    lit Lits[2];
+
+    Lits[0] = toLitCond( iVar0, 0 );
+    Lits[1] = toLitCond( iVar1, !fCompl );
+    if ( !sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVar0, 1 );
+    Lits[1] = toLitCond( iVar1, fCompl );
+    if ( !sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ) )
+        return 0;
+
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds buffer to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Aig_Gla3AddNode( sat_solver2 * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 )
+{
+    lit Lits[3];
+
+    Lits[0] = toLitCond( iVar, 1 );
+    Lits[1] = toLitCond( iVar0, fCompl0 );
+    if ( !sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVar, 1 );
+    Lits[1] = toLitCond( iVar1, fCompl1 );
+    if ( !sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVar, 0 );
+    Lits[1] = toLitCond( iVar0, !fCompl0 );
+    Lits[2] = toLitCond( iVar1, !fCompl1 );
+    if ( !sat_solver2_addclause( pSat, Lits, Lits + 3, 0 ) )
+        return 0;
+
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds existing SAT variable or creates a new one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_Gla3FetchVar( Aig_Gla3Man_t * p, Aig_Obj_t * pObj, int k )
+{
+    int i, iVecId, iSatVar;
+    assert( k < p->nFramesMax );
+    iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) );
+    if ( iVecId == 0 )
+    {
+        iVecId = Vec_IntSize( p->vVec2Var ) / p->nFramesMax;
+        for ( i = 0; i < p->nFramesMax; i++ )
+            Vec_IntPush( p->vVec2Var, 0 );
+        Vec_IntWriteEntry( p->vObj2Vec, Aig_ObjId(pObj), iVecId );
+    }
+    iSatVar = Vec_IntEntry( p->vVec2Var, iVecId * p->nFramesMax + k );
+    if ( iSatVar == 0 )
+    {
+        iSatVar = Vec_IntSize( p->vVar2Inf ) / 2;
+        Vec_IntPush( p->vVar2Inf, Aig_ObjId(pObj) );
+        Vec_IntPush( p->vVar2Inf, k );
+        Vec_IntWriteEntry( p->vVec2Var, iVecId * p->nFramesMax + k, iSatVar );
+    }
+    return iSatVar;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns variables to the AIG nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_Gla3AssignVars_rec( Aig_Gla3Man_t * p, Aig_Obj_t * pObj, int f )
+{
+    int nVars = Vec_IntSize(p->vVar2Inf);
+    Aig_Gla3FetchVar( p, pObj, f );
+    if ( nVars == Vec_IntSize(p->vVar2Inf) )
+        return;
+    if ( Aig_ObjIsConst1(pObj) )
+        return;
+    if ( Saig_ObjIsPo( p->pAig, pObj ) )
+    {
+        Aig_Gla3AssignVars_rec( p, Aig_ObjFanin0(pObj), f );
+        return;
+    }
+    if ( Aig_ObjIsCi( pObj ) )
+    {
+        if ( Saig_ObjIsLo(p->pAig, pObj) && f > 0 )
+            Aig_Gla3AssignVars_rec( p, Aig_ObjFanin0( Saig_ObjLoToLi(p->pAig, pObj) ), f-1 );
+        return;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    Aig_Gla3AssignVars_rec( p, Aig_ObjFanin0(pObj), f );
+    Aig_Gla3AssignVars_rec( p, Aig_ObjFanin1(pObj), f );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_Gla3CreateSatSolver( Aig_Gla3Man_t * p )
+{
+    Vec_Int_t * vPoLits;
+    Aig_Obj_t * pObj;
+    int i, f, ObjId, nVars, RetValue = 1;
+
+    // assign variables
+    for ( f = p->nFramesMax - 1; f >= 0; f-- )
+        Aig_Gla3AssignVars_rec( p, Aig_ManCo(p->pAig, 0), f );
+
+    // create SAT solver
+    p->pSat = sat_solver2_new();
+    sat_solver2_setnvars( p->pSat, Vec_IntSize(p->vVar2Inf)/2 );
+
+    // add clauses
+    nVars = Vec_IntSize( p->vVar2Inf );
+    Vec_IntForEachEntryDouble( p->vVar2Inf, ObjId, f, i )
+    {
+        if ( ObjId == -1 )
+            continue;
+        pObj = Aig_ManObj( p->pAig, ObjId );
+        if ( Aig_ObjIsNode(pObj) )
+        {
+            Aig_Gla3AddNode( p->pSat, Aig_Gla3FetchVar(p, pObj, f), 
+                                      Aig_Gla3FetchVar(p, Aig_ObjFanin0(pObj), f), 
+                                      Aig_Gla3FetchVar(p, Aig_ObjFanin1(pObj), f), 
+                                      Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) );
+            Vec_IntPush( p->vCla2Obj, ObjId );
+            Vec_IntPush( p->vCla2Obj, ObjId );
+            Vec_IntPush( p->vCla2Obj, ObjId );
+
+            Vec_IntPush( p->vCla2Fra, f );
+            Vec_IntPush( p->vCla2Fra, f );
+            Vec_IntPush( p->vCla2Fra, f );
+        }
+        else if ( Saig_ObjIsLo(p->pAig, pObj) )
+        {
+            if ( f == 0 )
+            {
+                Aig_Gla3AddConst( p->pSat, Aig_Gla3FetchVar(p, pObj, f), 1 );
+                Vec_IntPush( p->vCla2Obj, ObjId );
+
+                Vec_IntPush( p->vCla2Fra, f );
+            }
+            else
+            {
+                Aig_Obj_t * pObjLi = Saig_ObjLoToLi(p->pAig, pObj);
+                Aig_Gla3AddBuffer( p->pSat, Aig_Gla3FetchVar(p, pObj, f), 
+                                            Aig_Gla3FetchVar(p, Aig_ObjFanin0(pObjLi), f-1), 
+                                            Aig_ObjFaninC0(pObjLi) );
+                Vec_IntPush( p->vCla2Obj, ObjId );
+                Vec_IntPush( p->vCla2Obj, ObjId );
+
+                Vec_IntPush( p->vCla2Fra, f );
+                Vec_IntPush( p->vCla2Fra, f );
+            }
+        }
+        else if ( Saig_ObjIsPo(p->pAig, pObj) )
+        {
+            Aig_Gla3AddBuffer( p->pSat, Aig_Gla3FetchVar(p, pObj, f), 
+                                        Aig_Gla3FetchVar(p, Aig_ObjFanin0(pObj), f), 
+                                        Aig_ObjFaninC0(pObj) );
+            Vec_IntPush( p->vCla2Obj, ObjId );
+            Vec_IntPush( p->vCla2Obj, ObjId );
+
+            Vec_IntPush( p->vCla2Fra, f );
+            Vec_IntPush( p->vCla2Fra, f );
+        }
+        else if ( Aig_ObjIsConst1(pObj) )
+        {
+            Aig_Gla3AddConst( p->pSat, Aig_Gla3FetchVar(p, pObj, f), 0 );
+            Vec_IntPush( p->vCla2Obj, ObjId );
+
+            Vec_IntPush( p->vCla2Fra, f );
+        }
+        else assert( Saig_ObjIsPi(p->pAig, pObj) );
+    }
+
+    // add output clause
+    vPoLits = Vec_IntAlloc( p->nFramesMax );
+    for ( f = p->nStart; f < p->nFramesMax; f++ )
+        Vec_IntPush( vPoLits, 2 * Aig_Gla3FetchVar(p, Aig_ManCo(p->pAig, 0), f) );
+    sat_solver2_addclause( p->pSat, Vec_IntArray(vPoLits), Vec_IntArray(vPoLits) + Vec_IntSize(vPoLits), 0 );
+    Vec_IntFree( vPoLits );
+    Vec_IntPush( p->vCla2Obj, 0 );
+    Vec_IntPush( p->vCla2Fra, 0 );
+    assert( Vec_IntSize(p->vCla2Fra) == Vec_IntSize(p->vCla2Obj) );
+    assert( nVars == Vec_IntSize(p->vVar2Inf) );
+    assert( Vec_IntSize(p->vCla2Obj) == (int)p->pSat->stats.clauses+1 );
+    if ( p->fVerbose )
+        printf( "The resulting SAT problem contains %d variables and %d clauses.\n", 
+            p->pSat->size, p->pSat->stats.clauses );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Gla3Man_t * Aig_Gla3ManStart( Aig_Man_t * pAig, int nStart, int nFramesMax, int fVerbose )
+{
+    Aig_Gla3Man_t * p;
+    int i;
+
+    p = ABC_CALLOC( Aig_Gla3Man_t, 1 );
+    p->pAig       = pAig;
+
+    p->vObj2Vec   = Vec_IntStart( Aig_ManObjNumMax(pAig) );
+    p->vVec2Var   = Vec_IntAlloc( 1 << 20 );
+    p->vVar2Inf   = Vec_IntAlloc( 1 << 20 );
+    p->vCla2Obj   = Vec_IntAlloc( 1 << 20 ); Vec_IntPush( p->vCla2Obj, -1 );
+    p->vCla2Fra   = Vec_IntAlloc( 1 << 20 ); Vec_IntPush( p->vCla2Fra, -1 );
+
+    // skip first vector ID
+    p->nStart     = nStart;
+    p->nFramesMax = nFramesMax;
+    p->fVerbose   = fVerbose;
+    for ( i = 0; i < p->nFramesMax; i++ )
+        Vec_IntPush( p->vVec2Var, -1 );
+
+    // skip  first SAT variable
+    Vec_IntPush( p->vVar2Inf, -1 );
+    Vec_IntPush( p->vVar2Inf, -1 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_Gla3ManStop( Aig_Gla3Man_t * p )
+{
+    Vec_IntFreeP( &p->vObj2Vec );
+    Vec_IntFreeP( &p->vVec2Var );
+    Vec_IntFreeP( &p->vVar2Inf );
+    Vec_IntFreeP( &p->vCla2Obj );
+    Vec_IntFreeP( &p->vCla2Fra );
+    Vec_IntFreeP( &p->vVec2Use );
+
+    if ( p->pSat )
+        sat_solver2_delete( p->pSat );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the set of clauses involved in the UNSAT core.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Aig_Gla3ManUnsatCore( sat_solver2 * pSat, int nConfMax, int fVerbose, int * piRetValue )
+{
+    Vec_Int_t * vCore;
+    int RetValue;
+    clock_t clk = clock();
+    if ( piRetValue )
+        *piRetValue = -1;
+    // solve the problem
+    RetValue = sat_solver2_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( RetValue == l_Undef )
+    {
+        printf( "Conflict limit is reached.\n" );
+        return NULL;
+    }
+    if ( RetValue == l_True )
+    {
+        printf( "The BMC problem is SAT.\n" );
+        if ( piRetValue )
+            *piRetValue = 0;
+        return NULL;
+    }
+    if ( fVerbose )
+    {
+        printf( "SAT solver returned UNSAT after %7d conflicts.      ", (int)pSat->stats.conflicts );
+        Abc_PrintTime( 1, "Time", clock() - clk );
+    }
+    assert( RetValue == l_False );
+
+    // derive the UNSAT core
+    clk = clock();
+    vCore = (Vec_Int_t *)Sat_ProofCore( pSat );
+    if ( fVerbose )
+    {
+        printf( "SAT core contains %8d clauses (out of %8d).   ", Vec_IntSize(vCore), sat_solver2_nclauses(pSat) );
+        Abc_PrintTime( 1, "Time", clock() - clk );
+    }
+    return vCore;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects abstracted objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Aig_Gla3ManCollect( Aig_Gla3Man_t * p, Vec_Int_t * vCore )
+{
+    Vec_Int_t * vResult;
+    Aig_Obj_t * pObj;
+    int i, ClaId, iVecId;
+//    p->vVec2Use = Vec_IntStart( Vec_IntSize(p->vVec2Var) );
+
+    vResult = Vec_IntStart( Aig_ManObjNumMax(p->pAig) );
+    Vec_IntWriteEntry( vResult, 0, 1 ); // add const1
+    Vec_IntForEachEntry( vCore, ClaId, i )
+    {
+        pObj = Aig_ManObj( p->pAig, Vec_IntEntry(p->vCla2Obj, ClaId) );
+        if ( Saig_ObjIsPi(p->pAig, pObj) || Saig_ObjIsPo(p->pAig, pObj) || Aig_ObjIsConst1(pObj) )
+            continue;
+        assert( Saig_ObjIsLo(p->pAig, pObj) || Aig_ObjIsNode(pObj) );
+        Vec_IntWriteEntry( vResult, Aig_ObjId(pObj), 1 );
+        if ( p->vVec2Use )
+        {
+            iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) );
+            Vec_IntWriteEntry( p->vVec2Use, iVecId * p->nFramesMax + Vec_IntEntry(p->vCla2Fra, ClaId), 1 );
+        }
+    }
+    // count the number of objects in each frame
+    if ( p->vVec2Use )
+    {
+        Vec_Int_t * vCounts = Vec_IntStart( p->nFramesMax );
+        int v, f, Entry, nVecIds = Vec_IntSize(p->vVec2Use) / p->nFramesMax;
+        for ( f = 0; f < p->nFramesMax; f++ )
+        for ( v = 0; v < nVecIds; v++ )
+            if ( Vec_IntEntry( p->vVec2Use, v * p->nFramesMax + f ) )
+                Vec_IntAddToEntry( vCounts, f, 1 );
+        Vec_IntForEachEntry( vCounts, Entry, f )
+            printf( "%d ", Entry );
+        printf( "\n" );
+        Vec_IntFree( vCounts );
+    }
+    return vResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs gate-level localization abstraction.]
+
+  Description [Returns array of objects included in the abstraction. This array
+  may contain only const1, flop outputs, and internal nodes, that is, objects
+  that should have clauses added to the SAT solver.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Aig_Gla3ManPerform( Aig_Man_t * pAig, int nStart, int nFramesMax, int nConfLimit, int TimeLimit, int fSkipRand, int fVerbose )
+{
+    Aig_Gla3Man_t * p;
+    Vec_Int_t * vCore, * vResult;
+    clock_t clk, clk2 = clock();
+    assert( Saig_ManPoNum(pAig) == 1 );
+
+    if ( fVerbose )
+    {
+        if ( TimeLimit )
+            printf( "Abstracting from frame %d to frame %d with timeout %d sec.\n", nStart, nFramesMax, TimeLimit );
+        else
+            printf( "Abstracting from frame %d to frame %d with no timeout.\n", nStart, nFramesMax );
+    }
+
+    // start the solver
+    clk = clock();
+    p = Aig_Gla3ManStart( pAig, nStart, nFramesMax, fVerbose );
+    if ( !Aig_Gla3CreateSatSolver( p ) )
+    {
+        printf( "Error!  SAT solver became UNSAT.\n" );
+        Aig_Gla3ManStop( p );
+        return NULL;
+    }
+    p->pSat->fNotUseRandom = fSkipRand;
+    p->timePre += clock() - clk;
+
+    // set runtime limit
+    if ( TimeLimit )
+        sat_solver2_set_runtime_limit( p->pSat, TimeLimit * CLOCKS_PER_SEC + clock() );
+
+    // compute UNSAT core
+    clk = clock();
+    vCore = Aig_Gla3ManUnsatCore( p->pSat, nConfLimit, fVerbose, NULL );
+    if ( vCore == NULL )
+    {
+        Aig_Gla3ManStop( p );
+        return NULL;
+    }
+    p->timeSat += clock() - clk;
+    p->timeTotal += clock() - clk2;
+
+    // print stats
+    if ( fVerbose )
+    {
+        ABC_PRTP( "Pre   ", p->timePre,   p->timeTotal );
+        ABC_PRTP( "Sat   ", p->timeSat,   p->timeTotal );
+        ABC_PRTP( "Total ", p->timeTotal, p->timeTotal );
+    }
+
+    // prepare return value
+    vResult = Aig_Gla3ManCollect( p, vCore );
+    Vec_IntFree( vCore );
+    Aig_Gla3ManStop( p );
+    return vResult;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigInd.c b/abc-build/src/aig/saig/saigInd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigInd.c
@@ -0,0 +1,409 @@
+/**CFile****************************************************************
+
+  FileName    [saigLoc.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [K-step induction for one property only.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigLoc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if two state are equal.]
+
+  Description [Array vState contains indexes of CNF variables for each
+  flop in the first N time frames (0 < i < k, i < N, k < N).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManStatesAreEqual( sat_solver * pSat, Vec_Int_t * vState, int nRegs, int i, int k )
+{
+    int * pStateI = (int *)Vec_IntArray(vState) + nRegs * i;
+    int * pStateK = (int *)Vec_IntArray(vState) + nRegs * k;
+    int v;
+    assert( i && k && i < k );
+    assert( nRegs * k <= Vec_IntSize(vState) );
+    // check if the states are available
+    for ( v = 0; v < nRegs; v++ )
+        if ( pStateI[v] >= 0 && pStateK[v] == -1 )
+            return 0;
+/*
+    printf( "\nchecking uniqueness\n" );
+    printf( "%3d : ", i );
+    for ( v = 0; v < nRegs; v++ )
+        printf( "%d", sat_solver_var_value(pSat, pStateI[v]) );
+    printf( "\n" );
+
+    printf( "%3d : ", k );
+    for ( v = 0; v < nRegs; v++ )
+        printf( "%d", sat_solver_var_value(pSat, pStateK[v]) );
+    printf( "\n" );
+*/
+    for ( v = 0; v < nRegs; v++ )
+        if ( pStateI[v] >= 0 )
+        {
+            if ( sat_solver_var_value(pSat, pStateI[v]) != sat_solver_var_value(pSat, pStateK[v]) )
+                return 0;
+        }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add uniqueness constraint.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManAddUniqueness( sat_solver * pSat, Vec_Int_t * vState, int nRegs, int i, int k, int * pnSatVarNum, int * pnClauses, int fVerbose )
+{
+    int * pStateI = (int *)Vec_IntArray(vState) + nRegs * i;
+    int * pStateK = (int *)Vec_IntArray(vState) + nRegs * k;
+    int v, iVars, nSatVarsOld, RetValue, * pClause;
+    assert( i && k && i < k );
+    assert( nRegs * k <= Vec_IntSize(vState) );
+    // check if the states are available
+    for ( v = 0; v < nRegs; v++ )
+        if ( pStateI[v] >= 0 && pStateK[v] == -1 )
+        {
+            if ( fVerbose )
+                printf( "Cannot constrain an incomplete state.\n" );
+            return 0;
+        }
+    // add XORs
+    nSatVarsOld = *pnSatVarNum;
+    for ( v = 0; v < nRegs; v++ )
+        if ( pStateI[v] >= 0 )
+        {
+            *pnClauses += 4;
+            RetValue = Cnf_DataAddXorClause( pSat, pStateI[v], pStateK[v], (*pnSatVarNum)++ );
+            if ( RetValue == 0 )
+            {
+                if ( fVerbose )
+                    printf( "SAT solver became UNSAT after adding a uniqueness constraint.\n" );
+                return 1;
+            }
+        }
+    // add OR clause
+    (*pnClauses)++;
+    iVars = 0;
+    pClause = ABC_ALLOC( int, nRegs );
+    for ( v = nSatVarsOld; v < *pnSatVarNum; v++ )
+        pClause[iVars++] = toLitCond( v, 0 );
+    assert( iVars <= nRegs );
+    RetValue = sat_solver_addclause( pSat, pClause, pClause + iVars );
+    ABC_FREE( pClause );
+    if ( RetValue == 0 )
+    {
+        if ( fVerbose )
+            printf( "SAT solver became UNSAT after adding a uniqueness constraint.\n" );
+        return 1;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs induction by unrolling timeframes backward.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManInduction( Aig_Man_t * p, int nTimeOut, int nFramesMax, int nConfMax, int fUnique, int fUniqueAll, int fGetCex, int fVerbose, int fVeryVerbose )
+{
+    sat_solver * pSat;
+    Aig_Man_t * pAigPart = NULL;
+    Cnf_Dat_t * pCnfPart = NULL;
+    Vec_Int_t * vTopVarNums, * vState, * vTopVarIds = NULL;
+    Vec_Ptr_t * vTop, * vBot;
+    Aig_Obj_t * pObjPi, * pObjPiCopy, * pObjPo;
+    int i, k, f, Lits[2], status = -1, RetValue, nSatVarNum, nConfPrev;
+    int nOldSize, iReg, iLast, fAdded, nConstrs = 0, nClauses = 0;
+    abctime clk, nTimeToStop = nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock() : 0;
+    assert( fUnique == 0 || fUniqueAll == 0 );
+    assert( Saig_ManPoNum(p) == 1 );
+    Aig_ManSetCioIds( p );
+
+    // start the top by including the PO
+    vBot = Vec_PtrAlloc( 100 );
+    vTop = Vec_PtrAlloc( 100 );
+    vState = Vec_IntAlloc( 1000 );
+    Vec_PtrPush( vTop, Aig_ManCo(p, 0) );
+    // start the array of CNF variables
+    vTopVarNums = Vec_IntAlloc( 100 );
+    // start the solver
+    pSat = sat_solver_new();
+    sat_solver_setnvars( pSat, 1000 );
+
+    // set runtime limit
+    if ( nTimeToStop )
+        sat_solver_set_runtime_limit( pSat, nTimeToStop );
+
+    // iterate backward unrolling
+    RetValue = -1;
+    nSatVarNum = 0;
+    if ( fVerbose )
+        printf( "Induction parameters: FramesMax = %5d. ConflictMax = %6d.\n", nFramesMax, nConfMax );
+    for ( f = 0; ; f++ )
+    { 
+        if ( f > 0 )
+        {
+            Aig_ManStop( pAigPart );
+            Cnf_DataFree( pCnfPart );
+        }
+        clk = Abc_Clock();
+        // get the bottom
+        Aig_SupportNodes( p, (Aig_Obj_t **)Vec_PtrArray(vTop), Vec_PtrSize(vTop), vBot );
+        // derive AIG for the part between top and bottom
+        pAigPart = Aig_ManDupSimpleDfsPart( p, vBot, vTop );
+        // convert it into CNF
+        pCnfPart = Cnf_Derive( pAigPart, Aig_ManCoNum(pAigPart) );
+        Cnf_DataLift( pCnfPart, nSatVarNum );
+        nSatVarNum += pCnfPart->nVars;
+        nClauses   += pCnfPart->nClauses;
+
+        // remember top frame var IDs
+        if ( fGetCex && vTopVarIds == NULL )
+        {
+            vTopVarIds = Vec_IntStartFull( Aig_ManCiNum(p) );
+            Aig_ManForEachCi( p, pObjPi, i )
+            {
+                if ( pObjPi->pData == NULL )
+                    continue;
+                pObjPiCopy = (Aig_Obj_t *)pObjPi->pData;
+                assert( Aig_ObjIsCi(pObjPiCopy) );
+                if ( Saig_ObjIsPi(p, pObjPi) )
+                    Vec_IntWriteEntry( vTopVarIds, Aig_ObjCioId(pObjPi) + Saig_ManRegNum(p), pCnfPart->pVarNums[Aig_ObjId(pObjPiCopy)] );
+                else if ( Saig_ObjIsLo(p, pObjPi) )
+                    Vec_IntWriteEntry( vTopVarIds, Aig_ObjCioId(pObjPi) - Saig_ManPiNum(p), pCnfPart->pVarNums[Aig_ObjId(pObjPiCopy)] );
+                else assert( 0 );
+            }
+        }
+
+        // stitch variables of top and bot
+        assert( Aig_ManCoNum(pAigPart)-1 == Vec_IntSize(vTopVarNums) );
+        Aig_ManForEachCo( pAigPart, pObjPo, i )
+        {
+            if ( i == 0 )
+            {
+                // do not perform inductive strengthening
+//                if ( f > 0 )
+//                    continue;
+                // add topmost literal
+                Lits[0] = toLitCond( pCnfPart->pVarNums[pObjPo->Id], f>0 );
+                if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) )
+                    assert( 0 );
+                nClauses++;
+                continue;
+            }
+            Lits[0] = toLitCond( Vec_IntEntry(vTopVarNums, i-1), 0 );
+            Lits[1] = toLitCond( pCnfPart->pVarNums[pObjPo->Id], 1 );
+            if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+                assert( 0 );
+            Lits[0] = toLitCond( Vec_IntEntry(vTopVarNums, i-1), 1 );
+            Lits[1] = toLitCond( pCnfPart->pVarNums[pObjPo->Id], 0 );
+            if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+                assert( 0 );
+            nClauses += 2;
+        }
+        // add CNF to the SAT solver
+        for ( i = 0; i < pCnfPart->nClauses; i++ )
+            if ( !sat_solver_addclause( pSat, pCnfPart->pClauses[i], pCnfPart->pClauses[i+1] ) )
+                break;
+        if ( i < pCnfPart->nClauses )
+        {
+//            printf( "SAT solver became UNSAT after adding clauses.\n" );
+            RetValue = 1;
+            break;
+        }
+
+        // create new set of POs to derive new top
+        Vec_PtrClear( vTop );
+        Vec_PtrPush( vTop, Aig_ManCo(p, 0) );
+        Vec_IntClear( vTopVarNums );
+        nOldSize = Vec_IntSize(vState);
+        Vec_IntFillExtra( vState, nOldSize + Aig_ManRegNum(p), -1 );
+        Vec_PtrForEachEntry( Aig_Obj_t *, vBot, pObjPi, i )
+        {
+            assert( Aig_ObjIsCi(pObjPi) );
+            if ( Saig_ObjIsLo(p, pObjPi) )
+            {
+                pObjPiCopy = (Aig_Obj_t *)pObjPi->pData;
+                assert( pObjPiCopy != NULL );
+                Vec_PtrPush( vTop, Saig_ObjLoToLi(p, pObjPi) );
+                Vec_IntPush( vTopVarNums, pCnfPart->pVarNums[pObjPiCopy->Id] );
+
+                iReg = pObjPi->CioId - Saig_ManPiNum(p);
+                assert( iReg >= 0 && iReg < Aig_ManRegNum(p) );
+                Vec_IntWriteEntry( vState, nOldSize+iReg, pCnfPart->pVarNums[pObjPiCopy->Id] );
+            }
+        } 
+        assert( Vec_IntSize(vState)%Aig_ManRegNum(p) == 0 );
+        iLast = Vec_IntSize(vState)/Aig_ManRegNum(p);
+        if ( fUniqueAll )
+        {
+            for ( i = 1; i < iLast-1; i++ )
+            {
+                nConstrs++;
+                if ( fVeryVerbose )
+                    printf( "Adding constaint for state %2d and state %2d.\n", i, iLast-1 );
+                if ( Saig_ManAddUniqueness( pSat, vState, Aig_ManRegNum(p), i, iLast-1, &nSatVarNum, &nClauses, fVerbose ) )
+                    break;
+            }
+            if ( i < iLast-1 )
+            {
+                RetValue = 1;
+                break;
+            }
+        }
+
+nextrun:
+        fAdded = 0;
+        // run the SAT solver
+        nConfPrev = pSat->stats.conflicts;
+        status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfMax, 0, 0, 0 );
+        if ( fVerbose )
+        {
+            printf( "Frame %4d : PI =%5d. PO =%5d. AIG =%5d. Var =%7d. Clau =%7d. Conf =%7d. ",
+                f, Aig_ManCiNum(pAigPart), Aig_ManCoNum(pAigPart), Aig_ManNodeNum(pAigPart), 
+                nSatVarNum, nClauses, (int)pSat->stats.conflicts-nConfPrev );
+            ABC_PRT( "Time", Abc_Clock() - clk );
+        }
+        if ( status == l_Undef )
+            break;
+        if ( status == l_False )
+        {
+            RetValue = 1;
+            break;
+        }
+        assert( status == l_True );
+        // the problem is SAT - add more clauses
+        if ( fVeryVerbose )
+        {
+            Vec_IntForEachEntry( vState, iReg, i )
+            {
+                if ( i && (i % Aig_ManRegNum(p)) == 0 )
+                    printf( "\n" );
+                if ( (i % Aig_ManRegNum(p)) == 0 )
+                    printf( "       State %3d : ", i/Aig_ManRegNum(p) );
+                printf( "%c", (iReg >= 0) ? ('0' + sat_solver_var_value(pSat, iReg)) : 'x' );
+            }
+            printf( "\n" );
+        }
+        if ( nFramesMax && f == nFramesMax - 1 )
+        {
+            // derive counter-example
+            assert( status == l_True );
+            if ( fGetCex )
+            {
+                int VarNum, iBit = 0;
+                Abc_Cex_t * pCex = Abc_CexAlloc( Aig_ManRegNum(p)-1, Saig_ManPiNum(p), 1 );
+                pCex->iFrame = 0;
+                pCex->iPo = 0;
+                Vec_IntForEachEntryStart( vTopVarIds, VarNum, i, 1 )
+                {
+                    if ( VarNum >= 0 && sat_solver_var_value( pSat, VarNum ) )
+                        Abc_InfoSetBit( pCex->pData, iBit );
+                    iBit++;
+                }
+                assert( iBit == pCex->nBits );
+                Abc_CexFree( p->pSeqModel );
+                p->pSeqModel = pCex;
+            }
+            break;
+        }
+        if ( fUnique )
+        {
+            for ( i = 1; i < iLast; i++ )
+            {
+                for ( k = i+1; k < iLast; k++ )
+                {
+                    if ( !Saig_ManStatesAreEqual( pSat, vState, Aig_ManRegNum(p), i, k ) )
+                        continue;
+                    nConstrs++;
+                    fAdded = 1;
+                    if ( fVeryVerbose )
+                        printf( "Adding constaint for state %2d and state %2d.\n", i, k );
+                    if ( Saig_ManAddUniqueness( pSat, vState, Aig_ManRegNum(p), i, k, &nSatVarNum, &nClauses, fVerbose ) )
+                        break;
+                }
+                if ( k < iLast )
+                    break;
+            }
+            if ( i < iLast )
+            {
+                RetValue = 1;
+                break;
+            }
+        }
+        if ( fAdded )
+            goto nextrun;
+    }
+    if ( fVerbose )
+    {
+        if ( nTimeToStop && Abc_Clock() >= nTimeToStop )
+            printf( "Timeout (%d sec) was reached during iteration %d.\n", nTimeOut, f+1 );
+        else if ( status == l_Undef )
+            printf( "Conflict limit (%d) was reached during iteration %d.\n", nConfMax, f+1 );
+        else if ( fUnique || fUniqueAll )
+            printf( "Completed %d interations and added %d uniqueness constraints.\n", f+1, nConstrs );
+        else
+            printf( "Completed %d interations.\n", f+1 );
+    }
+    // cleanup
+    sat_solver_delete( pSat );
+    Aig_ManStop( pAigPart );
+    Cnf_DataFree( pCnfPart );
+    Vec_IntFree( vTopVarNums );
+    Vec_PtrFree( vTop );
+    Vec_PtrFree( vBot );
+    Vec_IntFree( vState );
+    Vec_IntFreeP( &vTopVarIds );
+    return RetValue;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigIoa.c b/abc-build/src/aig/saig/saigIoa.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigIoa.c
@@ -0,0 +1,405 @@
+/**CFile****************************************************************
+
+  FileName    [saigIoa.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Input/output for sequential AIGs using BLIF files.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigIoa.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <math.h>
+#include "saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Saig_ObjName( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    static char Buffer[16];
+    if ( Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(pObj) )
+        sprintf( Buffer, "n%0*d", Abc_Base10Log(Aig_ManObjNumMax(p)), Aig_ObjId(pObj) );
+    else if ( Saig_ObjIsPi(p, pObj) )
+        sprintf( Buffer, "pi%0*d", Abc_Base10Log(Saig_ManPiNum(p)), Aig_ObjCioId(pObj) );
+    else if ( Saig_ObjIsPo(p, pObj) )
+        sprintf( Buffer, "po%0*d", Abc_Base10Log(Saig_ManPoNum(p)), Aig_ObjCioId(pObj) );
+    else if ( Saig_ObjIsLo(p, pObj) )
+        sprintf( Buffer, "lo%0*d", Abc_Base10Log(Saig_ManRegNum(p)), Aig_ObjCioId(pObj) - Saig_ManPiNum(p) );
+    else if ( Saig_ObjIsLi(p, pObj) )
+        sprintf( Buffer, "li%0*d", Abc_Base10Log(Saig_ManRegNum(p)), Aig_ObjCioId(pObj) - Saig_ManPoNum(p) );
+    else 
+        assert( 0 );
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManDumpBlif( Aig_Man_t * p, char * pFileName )
+{
+    FILE * pFile;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i;
+    if ( Aig_ManCoNum(p) == 0 )
+    {
+        printf( "Aig_ManDumpBlif(): AIG manager does not have POs.\n" );
+        return;
+    }
+    Aig_ManSetCioIds( p );
+    // write input file
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        printf( "Saig_ManDumpBlif(): Cannot open file for writing.\n" );
+        return;
+    }
+    fprintf( pFile, "# BLIF file written by procedure Saig_ManDumpBlif()\n" );
+    fprintf( pFile, "# If unedited, this file can be read by Saig_ManReadBlif()\n" );
+    fprintf( pFile, "# AIG stats: pi=%d po=%d reg=%d and=%d obj=%d maxid=%d\n", 
+        Saig_ManPiNum(p), Saig_ManPoNum(p), Saig_ManRegNum(p), 
+        Aig_ManNodeNum(p), Aig_ManObjNum(p), Aig_ManObjNumMax(p) );
+    fprintf( pFile, ".model %s\n", p->pName );
+    // write primary inputs
+    fprintf( pFile, ".inputs" );
+    Aig_ManForEachPiSeq( p, pObj, i )
+        fprintf( pFile, " %s", Saig_ObjName(p, pObj) );
+    fprintf( pFile, "\n" );
+    // write primary outputs
+    fprintf( pFile, ".outputs" );
+    Aig_ManForEachPoSeq( p, pObj, i )
+        fprintf( pFile, " %s", Saig_ObjName(p, pObj) );
+    fprintf( pFile, "\n" );
+    // write registers
+    if ( Aig_ManRegNum(p) )
+    {
+        Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )
+        {
+            fprintf( pFile, ".latch" );
+            fprintf( pFile, " %s", Saig_ObjName(p, pObjLi) );
+            fprintf( pFile, " %s", Saig_ObjName(p, pObjLo) );
+            fprintf( pFile, " 0\n" );
+        }
+    } 
+    // check if constant is used
+    if ( Aig_ObjRefs(Aig_ManConst1(p)) )
+        fprintf( pFile, ".names %s\n 1\n", Saig_ObjName(p, Aig_ManConst1(p)) );
+    // write the nodes in the DFS order
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        fprintf( pFile, ".names" );
+        fprintf( pFile, " %s", Saig_ObjName(p, Aig_ObjFanin0(pObj)) );
+        fprintf( pFile, " %s", Saig_ObjName(p, Aig_ObjFanin1(pObj)) );
+        fprintf( pFile, " %s", Saig_ObjName(p, pObj) );
+        fprintf( pFile, "\n%d%d 1\n", !Aig_ObjFaninC0(pObj), !Aig_ObjFaninC1(pObj) );
+    }
+    // write the POs
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        fprintf( pFile, ".names" );
+        fprintf( pFile, " %s", Saig_ObjName(p, Aig_ObjFanin0(pObj)) );
+        fprintf( pFile, " %s", Saig_ObjName(p, pObj) );
+        fprintf( pFile, "\n%d 1\n", !Aig_ObjFaninC0(pObj) );
+    }
+    fprintf( pFile, ".end\n" );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads one token from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Saig_ManReadToken( FILE * pFile )
+{
+    static char Buffer[1000];
+    if ( fscanf( pFile, "%s", Buffer ) == 1 )
+        return Buffer;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the corresponding number.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManReadNumber( Aig_Man_t * p, char * pToken )
+{
+    if ( pToken[0] == 'n' )
+        return atoi( pToken + 1 );
+    if ( pToken[0] == 'p' )
+        return atoi( pToken + 2 );
+    if ( pToken[0] == 'l' )
+        return atoi( pToken + 2 );
+    assert( 0 );
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the corresponding node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Saig_ManReadNode( Aig_Man_t * p, int * pNum2Id, char * pToken )
+{
+    int Num;
+    if ( pToken[0] == 'n' )
+    {
+        Num = atoi( pToken + 1 );
+        return Aig_ManObj( p, pNum2Id[Num] );
+    }
+    if ( pToken[0] == 'p' )
+    {
+        pToken++;
+        if ( pToken[0] == 'i' )
+        {
+            Num = atoi( pToken + 1 );
+            return Aig_ManCi( p, Num );
+        }
+        if ( pToken[0] == 'o' )
+            return NULL;
+        assert( 0 );
+        return NULL;
+    }
+    if ( pToken[0] == 'l' )
+    {
+        pToken++;
+        if ( pToken[0] == 'o' )
+        {
+            Num = atoi( pToken + 1 );
+            return Saig_ManLo( p, Num );
+        }
+        if ( pToken[0] == 'i' )
+            return NULL;
+        assert( 0 );
+        return NULL;
+    }
+    assert( 0 );
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads BLIF previously dumped by Saig_ManDumpBlif().]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManReadBlif( char * pFileName )
+{
+    FILE * pFile;
+    Aig_Man_t * p;
+    Aig_Obj_t * pFanin0, * pFanin1, * pNode;
+    char * pToken;
+    int i, nPis, nPos, nRegs, Number;
+    int * pNum2Id = NULL;  // mapping of node numbers in the file into AIG node IDs
+    // open the file
+    pFile = fopen( pFileName, "r" );
+    if ( pFile == NULL )
+    {
+        printf( "Saig_ManReadBlif(): Cannot open file for reading.\n" );
+        return NULL;
+    }
+    // skip through the comments
+    for ( i = 0; (pToken = Saig_ManReadToken( pFile )) && pToken[0] != '.'; i++ );
+    if ( pToken == NULL ) 
+        { printf( "Saig_ManReadBlif(): Error 1.\n" ); return NULL; }
+    // get he model
+    pToken = Saig_ManReadToken( pFile );
+    if ( pToken == NULL ) 
+        { printf( "Saig_ManReadBlif(): Error 2.\n" ); return NULL; }
+    // start the package
+    p = Aig_ManStart( 10000 );
+    p->pName = Abc_UtilStrsav( pToken );
+    p->pSpec = Abc_UtilStrsav( pFileName );
+    // count PIs
+    pToken = Saig_ManReadToken( pFile );
+    if ( pToken == NULL || strcmp( pToken, ".inputs" ) ) 
+        { printf( "Saig_ManReadBlif(): Error 3.\n" ); Aig_ManStop(p); return NULL; }
+    for ( nPis = 0; (pToken = Saig_ManReadToken( pFile )) && pToken[0] != '.'; nPis++ );
+    // count POs
+    if ( pToken == NULL || strcmp( pToken, ".outputs" ) ) 
+        { printf( "Saig_ManReadBlif(): Error 4.\n" ); Aig_ManStop(p); return NULL; }
+    for ( nPos = 0; (pToken = Saig_ManReadToken( pFile )) && pToken[0] != '.'; nPos++ );
+    // count latches
+    if ( pToken == NULL ) 
+        { printf( "Saig_ManReadBlif(): Error 5.\n" ); Aig_ManStop(p); return NULL; }
+    for ( nRegs = 0; strcmp( pToken, ".latch" ) == 0; nRegs++ )
+    {
+        pToken = Saig_ManReadToken( pFile );
+        if ( pToken == NULL ) 
+            { printf( "Saig_ManReadBlif(): Error 6.\n" ); Aig_ManStop(p); return NULL; }
+        pToken = Saig_ManReadToken( pFile );
+        if ( pToken == NULL ) 
+            { printf( "Saig_ManReadBlif(): Error 7.\n" ); Aig_ManStop(p); return NULL; }
+        pToken = Saig_ManReadToken( pFile );
+        if ( pToken == NULL ) 
+            { printf( "Saig_ManReadBlif(): Error 8.\n" ); Aig_ManStop(p); return NULL; }
+        pToken = Saig_ManReadToken( pFile );
+        if ( pToken == NULL ) 
+            { printf( "Saig_ManReadBlif(): Error 9.\n" ); Aig_ManStop(p); return NULL; }
+    }
+    // create PIs and LOs
+    for ( i = 0; i < nPis + nRegs; i++ )
+        Aig_ObjCreateCi( p );
+    Aig_ManSetRegNum( p, nRegs );
+    // create nodes
+    for ( i = 0; strcmp( pToken, ".names" ) == 0; i++ )
+    {
+        // first token
+        pToken = Saig_ManReadToken( pFile );
+        if ( i == 0 && pToken[0] == 'n' )
+        { // constant node
+            // read 1
+            pToken = Saig_ManReadToken( pFile );
+            if ( pToken == NULL || strcmp( pToken, "1" ) ) 
+                { printf( "Saig_ManReadBlif(): Error 10.\n" ); Aig_ManStop(p); return NULL; }
+            // read next
+            pToken = Saig_ManReadToken( pFile );
+            if ( pToken == NULL ) 
+                { printf( "Saig_ManReadBlif(): Error 11.\n" ); Aig_ManStop(p); return NULL; }
+            continue;
+        }
+        pFanin0 = Saig_ManReadNode( p, pNum2Id, pToken );
+
+        // second token
+        pToken = Saig_ManReadToken( pFile );
+        if ( (pToken[0] == 'p' && pToken[1] == 'o') || (pToken[0] == 'l' && pToken[1] == 'i') )
+        { // buffer
+            // read complemented attribute
+            pToken = Saig_ManReadToken( pFile );
+            if ( pToken == NULL ) 
+                { printf( "Saig_ManReadBlif(): Error 12.\n" ); Aig_ManStop(p); return NULL; }
+            if ( pToken[0] == '0' )
+                pFanin0 = Aig_Not(pFanin0);
+            // read 1
+            pToken = Saig_ManReadToken( pFile );
+            if ( pToken == NULL || strcmp( pToken, "1" ) ) 
+                { printf( "Saig_ManReadBlif(): Error 13.\n" ); Aig_ManStop(p); return NULL; }
+            Aig_ObjCreateCo( p, pFanin0 );
+            // read next
+            pToken = Saig_ManReadToken( pFile );
+            if ( pToken == NULL ) 
+                { printf( "Saig_ManReadBlif(): Error 14.\n" ); Aig_ManStop(p); return NULL; }
+            continue;
+        }
+
+        // third token
+        // regular node
+        pFanin1 = Saig_ManReadNode( p, pNum2Id, pToken );
+        pToken = Saig_ManReadToken( pFile );
+        Number = Saig_ManReadNumber( p, pToken );
+        // allocate mapping
+        if ( pNum2Id == NULL )
+        {
+//            extern double pow( double x, double y );
+            int Size = (int)pow(10.0, (double)(strlen(pToken) - 1));
+            pNum2Id = ABC_CALLOC( int, Size );
+        }
+
+        // other tokens
+        // get the complemented attributes
+        pToken = Saig_ManReadToken( pFile );
+        if ( pToken == NULL ) 
+            { printf( "Saig_ManReadBlif(): Error 15.\n" ); Aig_ManStop(p); return NULL; }
+        if ( pToken[0] == '0' )
+            pFanin0 = Aig_Not(pFanin0);
+        if ( pToken[1] == '0' )
+            pFanin1 = Aig_Not(pFanin1);
+        // read 1
+        pToken = Saig_ManReadToken( pFile );
+        if ( pToken == NULL || strcmp( pToken, "1" ) ) 
+            { printf( "Saig_ManReadBlif(): Error 16.\n" ); Aig_ManStop(p); return NULL; }
+        // read next
+        pToken = Saig_ManReadToken( pFile );
+        if ( pToken == NULL ) 
+            { printf( "Saig_ManReadBlif(): Error 17.\n" ); Aig_ManStop(p); return NULL; }
+
+        // create new node
+        pNode = Aig_And( p, pFanin0, pFanin1 );
+        if ( Aig_IsComplement(pNode) )
+            { printf( "Saig_ManReadBlif(): Error 18.\n" ); Aig_ManStop(p); return NULL; }
+        // set mapping
+        pNum2Id[ Number ] = pNode->Id;
+    }
+    if ( pToken == NULL || strcmp( pToken, ".end" ) ) 
+        { printf( "Saig_ManReadBlif(): Error 19.\n" ); Aig_ManStop(p); return NULL; }
+    if ( nPos + nRegs != Aig_ManCoNum(p) ) 
+        { printf( "Saig_ManReadBlif(): Error 20.\n" ); Aig_ManStop(p); return NULL; }
+    // add non-node objects to the mapping
+    Aig_ManForEachCi( p, pNode, i )
+        pNum2Id[pNode->Id] = pNode->Id;
+//    ABC_FREE( pNum2Id );
+    p->pData = pNum2Id;
+    // check the new manager
+    Aig_ManSetRegNum( p, nRegs );
+    if ( !Aig_ManCheck(p) )
+        printf( "Saig_ManReadBlif(): Check has failed.\n" );
+    return p;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigIso.c b/abc-build/src/aig/saig/saigIso.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigIso.c
@@ -0,0 +1,628 @@
+/**CFile****************************************************************
+
+  FileName    [saigIso.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Sequential cleanup.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigIso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig/ioa/ioa.h"
+#include "saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Find the canonical permutation of the COs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManFindIsoPermCos( Aig_Man_t * pAig, Vec_Int_t * vPermCis )
+{
+    extern int Iso_ObjCompareByData( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 );
+    Vec_Int_t * vPermCos;
+    Aig_Obj_t * pObj, * pFanin;
+    int i, Entry, Diff;
+    assert( Vec_IntSize(vPermCis) == Aig_ManCiNum(pAig) );
+    vPermCos = Vec_IntAlloc( Aig_ManCoNum(pAig) );
+    if ( Saig_ManPoNum(pAig) == 1 )
+        Vec_IntPush( vPermCos, 0 );
+    else
+    {
+        Vec_Ptr_t * vRoots = Vec_PtrAlloc( Saig_ManPoNum(pAig) );
+        Saig_ManForEachPo( pAig, pObj, i )
+        {
+            pFanin = Aig_ObjFanin0(pObj);
+            assert( Aig_ObjIsConst1(pFanin) || pFanin->iData > 0 );
+            pObj->iData = Abc_Var2Lit( pFanin->iData, Aig_ObjFaninC0(pObj) );
+            Vec_PtrPush( vRoots, pObj );
+        }
+        Vec_PtrSort( vRoots, (int (*)(void))Iso_ObjCompareByData );
+        Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i )
+            Vec_IntPush( vPermCos, Aig_ObjCioId(pObj) );
+        Vec_PtrFree( vRoots );
+    }
+    // add flop outputs
+    Diff = Saig_ManPoNum(pAig) - Saig_ManPiNum(pAig);
+    Vec_IntForEachEntryStart( vPermCis, Entry, i, Saig_ManPiNum(pAig) )
+        Vec_IntPush( vPermCos, Entry + Diff );
+    return vPermCos;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs canonical duplication of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManDupIsoCanonical_rec( Aig_Man_t * pNew, Aig_Man_t * pAig, Aig_Obj_t * pObj )
+{
+    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(pAig, pObj);
+    assert( Aig_ObjIsNode(pObj) );
+    if ( !Aig_ObjIsNode(Aig_ObjFanin0(pObj)) || !Aig_ObjIsNode(Aig_ObjFanin1(pObj)) )
+    {
+        Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin0(pObj) );
+        Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin1(pObj) );
+    }
+    else
+    {
+        assert( Aig_ObjFanin0(pObj)->iData != Aig_ObjFanin1(pObj)->iData );
+        if ( Aig_ObjFanin0(pObj)->iData < Aig_ObjFanin1(pObj)->iData )
+        {
+            Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin0(pObj) );
+            Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin1(pObj) );
+        }
+        else
+        {
+            Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin1(pObj) );
+            Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin0(pObj) );
+        }
+    }
+    pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs canonical duplication of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManDupIsoCanonical( Aig_Man_t * pAig, int fVerbose )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    Vec_Int_t * vPerm, * vPermCo;
+    int i, Entry;
+    // derive permutations
+    vPerm   = Saig_ManFindIsoPerm( pAig, fVerbose );
+    vPermCo = Saig_ManFindIsoPermCos( pAig, vPerm );
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManNodeNum(pAig) );
+    pNew->pName = Abc_UtilStrsav( pAig->pName );
+    Aig_ManIncrementTravId( pAig );
+    // create constant
+    pObj = Aig_ManConst1(pAig);
+    pObj->pData = Aig_ManConst1(pNew);
+    Aig_ObjSetTravIdCurrent( pAig, pObj );
+    // create PIs
+    Vec_IntForEachEntry( vPerm, Entry, i )
+    {
+        pObj = Aig_ManCi(pAig, Entry);
+        pObj->pData = Aig_ObjCreateCi(pNew);
+        Aig_ObjSetTravIdCurrent( pAig, pObj );
+    }
+    // traverse from the POs
+    Vec_IntForEachEntry( vPermCo, Entry, i )
+    {
+        pObj = Aig_ManCo(pAig, Entry);
+        Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin0(pObj) );
+    }
+    // create POs
+    Vec_IntForEachEntry( vPermCo, Entry, i )
+    {
+        pObj = Aig_ManCo(pAig, Entry);
+        Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    }
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) );
+    Vec_IntFreeP( &vPerm );
+    Vec_IntFreeP( &vPermCo );
+    return pNew;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks structural equivalence of AIG1 and AIG2.]
+
+  Description [Returns 1 if AIG1 and AIG2 are structurally equivalent 
+  under this mapping.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Iso_ManCheckMapping( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vMap2to1, int fVerbose )
+{
+    Aig_Obj_t * pObj, * pFanin0, * pFanin1;
+    int i;
+    assert( Aig_ManCiNum(pAig1) == Aig_ManCiNum(pAig2) );
+    assert( Aig_ManCoNum(pAig1) == Aig_ManCoNum(pAig2) );
+    assert( Aig_ManRegNum(pAig1) == Aig_ManRegNum(pAig2) );
+    assert( Aig_ManNodeNum(pAig1) == Aig_ManNodeNum(pAig2) );
+    Aig_ManCleanData( pAig1 );
+    // map const and PI nodes
+    Aig_ManConst1(pAig2)->pData = Aig_ManConst1(pAig1);
+    Aig_ManForEachCi( pAig2, pObj, i )
+        pObj->pData = Aig_ManCi( pAig1, Vec_IntEntry(vMap2to1, i) );
+    // try internal nodes
+    Aig_ManForEachNode( pAig2, pObj, i )
+    {
+        pFanin0 = Aig_ObjChild0Copy( pObj );
+        pFanin1 = Aig_ObjChild1Copy( pObj );
+        pObj->pData = Aig_TableLookupTwo( pAig1, pFanin0, pFanin1 );
+        if ( pObj->pData == NULL )
+        {
+            if ( fVerbose )
+                printf( "Structural equivalence failed at node %d.\n", i );
+            return 0;
+        }
+    }
+    // make sure the first PO points to the same node
+    if ( Aig_ManCoNum(pAig1)-Aig_ManRegNum(pAig1) == 1 && Aig_ObjChild0Copy(Aig_ManCo(pAig2, 0)) != Aig_ObjChild0(Aig_ManCo(pAig1, 0)) )
+    {
+        if ( fVerbose )
+            printf( "Structural equivalence failed at primary output 0.\n" );
+        return 0;
+    }
+    return 1;    
+}
+
+//static int s_Counter;
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Iso_ManNegEdgeNum( Aig_Man_t * pAig )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    if ( pAig->nComplEdges > 0 )
+        return pAig->nComplEdges;
+    Aig_ManForEachObj( pAig, pObj, i )
+        if ( Aig_ObjIsNode(pObj) )
+        {
+            Counter += Aig_ObjFaninC0(pObj);
+            Counter += Aig_ObjFaninC1(pObj);
+        }
+        else if ( Aig_ObjIsCo(pObj) )
+            Counter += Aig_ObjFaninC0(pObj);
+    return (pAig->nComplEdges = Counter);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds mapping of CIs of AIG2 into those of AIG1.]
+
+  Description [Returns the mapping of CIs of the two AIGs, or NULL
+  if there is no mapping.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Iso_ManFindMapping( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vPerm1_, Vec_Int_t * vPerm2_, int fVerbose )
+{
+    Vec_Int_t * vPerm1, * vPerm2, * vInvPerm2;
+    int i, Entry;
+    if ( Aig_ManCiNum(pAig1) != Aig_ManCiNum(pAig2) )
+        return NULL;
+    if ( Aig_ManCoNum(pAig1) != Aig_ManCoNum(pAig2) )
+        return NULL;
+    if ( Aig_ManRegNum(pAig1) != Aig_ManRegNum(pAig2) )
+        return NULL;
+    if ( Aig_ManNodeNum(pAig1) != Aig_ManNodeNum(pAig2) )
+        return NULL;
+    if ( Aig_ManLevelNum(pAig1) != Aig_ManLevelNum(pAig2) )
+        return NULL;
+//    if ( Iso_ManNegEdgeNum(pAig1) != Iso_ManNegEdgeNum(pAig2) )
+//        return NULL;
+//    s_Counter++;
+
+    if ( fVerbose ) 
+        printf( "AIG1:\n" );
+    vPerm1 = vPerm1_ ? vPerm1_ : Saig_ManFindIsoPerm( pAig1, fVerbose );
+    if ( fVerbose )
+        printf( "AIG1:\n" );
+    vPerm2 = vPerm2_ ? vPerm2_ : Saig_ManFindIsoPerm( pAig2, fVerbose );
+    if ( vPerm1_ )
+        assert( Vec_IntSize(vPerm1_) == Aig_ManCiNum(pAig1) );
+    if ( vPerm2_ )
+        assert( Vec_IntSize(vPerm2_) == Aig_ManCiNum(pAig2) );
+    // find canonical permutation
+    // vPerm1/vPerm2 give canonical order of CIs of AIG1/AIG2
+    vInvPerm2 = Vec_IntInvert( vPerm2, -1 );
+    Vec_IntForEachEntry( vInvPerm2, Entry, i )
+    {
+        assert( Entry >= 0 && Entry < Aig_ManCiNum(pAig1) );
+        Vec_IntWriteEntry( vInvPerm2, i, Vec_IntEntry(vPerm1, Entry) );
+    }
+    if ( vPerm1_ == NULL )
+        Vec_IntFree( vPerm1 );
+    if ( vPerm2_ == NULL )
+        Vec_IntFree( vPerm2 );
+    // check if they are indeed equivalent
+    if ( !Iso_ManCheckMapping( pAig1, pAig2, vInvPerm2, fVerbose ) )
+        Vec_IntFreeP( &vInvPerm2 );
+    return vInvPerm2;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Iso_ManFilterPos_old( Aig_Man_t * pAig, int fVerbose )
+{
+    int fVeryVerbose = 0;
+    Vec_Ptr_t * vParts, * vPerms, * vAigs;
+    Vec_Int_t * vPos, * vMap;
+    Aig_Man_t * pPart, * pTemp;
+    int i, k, nPos;
+
+    // derive AIG for each PO
+    nPos = Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig);
+    vParts = Vec_PtrAlloc( nPos );
+    vPerms = Vec_PtrAlloc( nPos );
+    for ( i = 0; i < nPos; i++ )
+    {
+        pPart = Saig_ManDupCones( pAig, &i, 1 );
+        vMap  = Saig_ManFindIsoPerm( pPart, fVeryVerbose );
+        Vec_PtrPush( vParts, pPart ); 
+        Vec_PtrPush( vPerms, vMap );
+    }
+//    s_Counter = 0;
+
+    // check AIGs for each PO
+    vAigs = Vec_PtrAlloc( 1000 );
+    vPos  = Vec_IntAlloc( 1000 );
+    Vec_PtrForEachEntry( Aig_Man_t *, vParts, pPart, i )
+    {
+        if ( fVeryVerbose )
+        {
+            printf( "AIG %4d : ", i );
+            Aig_ManPrintStats( pPart );
+        }
+        Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, k )
+        {
+            if ( fVeryVerbose )
+                printf( "Comparing AIG %4d and AIG %4d.  ", Vec_IntEntry(vPos,k), i );
+            vMap = Iso_ManFindMapping( pTemp, pPart, 
+                (Vec_Int_t *)Vec_PtrEntry(vPerms, Vec_IntEntry(vPos,k)), 
+                (Vec_Int_t *)Vec_PtrEntry(vPerms, i),
+                fVeryVerbose );
+            if ( vMap != NULL )
+            {
+                if ( fVeryVerbose )
+                    printf( "Found match\n" );
+//                if ( fVerbose )
+//                    printf( "Found match for AIG %4d and AIG %4d.\n", Vec_IntEntry(vPos,k), i );
+                Vec_IntFree( vMap );
+                break;
+            }
+            if ( fVeryVerbose )
+                printf( "No match.\n" );
+        }
+        if ( k == Vec_PtrSize(vAigs) )
+        {
+            Vec_PtrPush( vAigs, pPart );
+            Vec_IntPush( vPos, i );
+        }
+    }
+    // delete AIGs
+    Vec_PtrForEachEntry( Aig_Man_t *, vParts, pPart, i )
+        Aig_ManStop( pPart );
+    Vec_PtrFree( vParts );
+    Vec_PtrForEachEntry( Vec_Int_t *, vPerms, vMap, i )
+        Vec_IntFree( vMap );
+    Vec_PtrFree( vPerms );
+    // derive the resulting AIG
+    pPart = Saig_ManDupCones( pAig, Vec_IntArray(vPos), Vec_IntSize(vPos) );
+    Vec_PtrFree( vAigs );
+    Vec_IntFree( vPos );
+
+//    printf( "The number of all checks %d.  Complex checks %d.\n", nPos*(nPos-1)/2, s_Counter );
+    return pPart;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Takes multi-output sequential AIG.]
+
+  Description [Returns candidate equivalence classes of POs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Iso_StoCompareVecStr( Vec_Str_t ** p1, Vec_Str_t ** p2 )
+{
+    return Vec_StrCompareVec( *p1, *p2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Iso_ManFilterPos( Aig_Man_t * pAig, Vec_Ptr_t ** pvPosEquivs, int fVerbose )
+{
+//    int fVeryVerbose = 0;
+    Aig_Man_t * pPart, * pTemp;
+    Vec_Ptr_t * vBuffers, * vClasses;
+    Vec_Int_t * vLevel, * vRemain;
+    Vec_Str_t * vStr, * vPrev;
+    int i, nPos;
+    abctime clk = Abc_Clock();
+    abctime clkDup = 0, clkAig = 0, clkIso = 0, clk2;
+    *pvPosEquivs = NULL;
+
+    // derive AIG for each PO
+    nPos = Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig);
+    vBuffers = Vec_PtrAlloc( nPos );
+    for ( i = 0; i < nPos; i++ )
+    {
+        if ( i % 100 == 0 )
+            printf( "%6d finished...\r", i );
+
+        clk2 = Abc_Clock();
+        pPart = Saig_ManDupCones( pAig, &i, 1 );
+        clkDup += Abc_Clock() - clk2;
+
+        clk2 = Abc_Clock();
+        pTemp = Saig_ManDupIsoCanonical( pPart, 0 );
+        clkIso += Abc_Clock() - clk2;
+
+        clk2 = Abc_Clock();
+        vStr  = Ioa_WriteAigerIntoMemoryStr( pTemp );
+        clkAig += Abc_Clock() - clk2;
+
+        Vec_PtrPush( vBuffers, vStr );
+        Aig_ManStop( pTemp );
+        Aig_ManStop( pPart );
+        // remember the output number in nCap (attention: hack!)
+        vStr->nCap = i;
+    }
+//    s_Counter = 0;
+    if ( fVerbose )
+    {
+    Abc_PrintTime( 1, "Duplicate time", clkDup );
+    Abc_PrintTime( 1, "Isomorph  time", clkIso );
+    Abc_PrintTime( 1, "AIGER     time", clkAig );
+    }
+
+    // sort the infos
+    clk = Abc_Clock();
+    Vec_PtrSort( vBuffers, (int (*)(void))Iso_StoCompareVecStr );
+
+    // create classes
+    clk = Abc_Clock();
+    vClasses = Vec_PtrAlloc( Saig_ManPoNum(pAig) );
+    // start the first class
+    Vec_PtrPush( vClasses, (vLevel = Vec_IntAlloc(4)) );
+    vPrev = (Vec_Str_t *)Vec_PtrEntry( vBuffers, 0 );
+    Vec_IntPush( vLevel, vPrev->nCap );
+    // consider other classes
+    Vec_PtrForEachEntryStart( Vec_Str_t *, vBuffers, vStr, i, 1 )
+    {
+        if ( Vec_StrCompareVec(vPrev, vStr) )
+            Vec_PtrPush( vClasses, Vec_IntAlloc(4) );
+        vLevel = (Vec_Int_t *)Vec_PtrEntryLast( vClasses );
+        Vec_IntPush( vLevel, vStr->nCap );
+        vPrev = vStr;
+    }
+    Vec_VecFree( (Vec_Vec_t *)vBuffers );
+
+    if ( fVerbose )
+    Abc_PrintTime( 1, "Sorting   time", Abc_Clock() - clk );
+//    Abc_PrintTime( 1, "Traversal time", time_Trav );
+
+    // report the results
+//    Vec_VecPrintInt( (Vec_Vec_t *)vClasses );
+//    printf( "Devided %d outputs into %d cand equiv classes.\n", Saig_ManPoNum(pAig), Vec_PtrSize(vClasses) );
+/*
+    if ( fVerbose )
+    {
+        Vec_PtrForEachEntry( Vec_Int_t *, vClasses, vLevel, i )
+            if ( Vec_IntSize(vLevel) > 1 )
+                printf( "%d ", Vec_IntSize(vLevel) );
+            else
+                nUnique++;
+        printf( " Unique = %d\n", nUnique );
+    }
+*/
+
+    // canonicize order
+    Vec_PtrForEachEntry( Vec_Int_t *, vClasses, vLevel, i )
+        Vec_IntSort( vLevel, 0 );
+     Vec_VecSortByFirstInt( (Vec_Vec_t *)vClasses, 0 );
+       
+    // collect the first ones
+    vRemain = Vec_IntAlloc( 100 );
+    Vec_PtrForEachEntry( Vec_Int_t *, vClasses, vLevel, i )
+        Vec_IntPush( vRemain, Vec_IntEntry(vLevel, 0) );
+
+    // derive the resulting AIG
+    pPart = Saig_ManDupCones( pAig, Vec_IntArray(vRemain), Vec_IntSize(vRemain) );
+    Vec_IntFree( vRemain );
+
+//    return (Vec_Vec_t *)vClasses;
+//    Vec_VecFree( (Vec_Vec_t *)vClasses );
+    *pvPosEquivs = vClasses;
+    return pPart;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Iso_ManTest( Aig_Man_t * pAig, int fVerbose )
+{
+    Vec_Int_t * vPerm;
+    abctime clk = Abc_Clock();
+    vPerm = Saig_ManFindIsoPerm( pAig, fVerbose );
+    Vec_IntFree( vPerm );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManIsoReduce( Aig_Man_t * pAig, Vec_Ptr_t ** pvPosEquivs, int fVerbose )
+{ 
+    Aig_Man_t * pPart;
+    abctime clk = Abc_Clock();
+    pPart = Iso_ManFilterPos( pAig, pvPosEquivs, fVerbose );
+    printf( "Reduced %d outputs to %d outputs.  ", Saig_ManPoNum(pAig), Saig_ManPoNum(pPart) );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    if ( fVerbose && *pvPosEquivs && Saig_ManPoNum(pAig) != Vec_PtrSize(*pvPosEquivs) )
+    {
+        printf( "Nontrivial classes:\n" );
+        Vec_VecPrintInt( (Vec_Vec_t *)*pvPosEquivs, 1 );
+    }
+//    Aig_ManStopP( &pPart );
+    return pPart;
+}
+
+ABC_NAMESPACE_IMPL_END
+
+#include "base/abc/abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Iso_ManTest888( Aig_Man_t * pAig1, int fVerbose )
+{
+    extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+    extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan );
+    Abc_Ntk_t * pNtk;
+    Aig_Man_t * pAig2;
+    Vec_Int_t * vMap;
+    
+    pNtk = Abc_NtkFromAigPhase( pAig1 );
+    Abc_NtkPermute( pNtk, 1, 0, 1, NULL );
+    pAig2 = Abc_NtkToDar( pNtk, 0, 1 );
+    Abc_NtkDelete( pNtk );
+
+    vMap = Iso_ManFindMapping( pAig1, pAig2, NULL, NULL, fVerbose );
+    Aig_ManStop( pAig2 );
+
+    if ( vMap != NULL )
+    {
+        printf( "Mapping of AIGs is found.\n" );
+        if ( fVerbose )
+            Vec_IntPrint( vMap );
+    }
+    else
+        printf( "Mapping of AIGs is NOT found.\n" );
+    Vec_IntFreeP( &vMap );
+    return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigIsoFast.c b/abc-build/src/aig/saig/saigIsoFast.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigIsoFast.c
@@ -0,0 +1,353 @@
+/**CFile****************************************************************
+
+  FileName    [aigIsoFast.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Graph isomorphism package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigIsoFast.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define AIG_ISO_NUM 16
+
+typedef struct Iso_Dat_t_ Iso_Dat_t;
+struct Iso_Dat_t_
+{
+    unsigned      nFiNeg    :  3;
+    unsigned      nFoNeg    :  2;
+    unsigned      nFoPos    :  2;
+    unsigned      Fi0Lev    :  3;
+    unsigned      Fi1Lev    :  3;
+    unsigned      Level     :  3;
+    unsigned      fVisit    : 16;
+};
+
+typedef struct Iso_Dat2_t_ Iso_Dat2_t;
+struct Iso_Dat2_t_
+{
+    unsigned      Data      : 16;
+};
+
+typedef struct Iso_Sto_t_ Iso_Sto_t;
+struct Iso_Sto_t_
+{
+    Aig_Man_t *   pAig;       // user's AIG manager
+    int           nObjs;      // number of objects
+    Iso_Dat_t *   pData;      // data for each object
+    Vec_Int_t *   vVisited;   // visited nodes
+    Vec_Ptr_t *   vRoots;     // root nodes
+    Vec_Int_t *   vPlaces;    // places in the counter lists
+    int *         pCounters;  // counters    
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Iso_Sto_t * Iso_StoStart( Aig_Man_t * pAig )
+{
+    Iso_Sto_t * p;
+    p = ABC_CALLOC( Iso_Sto_t, 1 );
+    p->pAig      = pAig;
+    p->nObjs     = Aig_ManObjNumMax( pAig );
+    p->pData     = ABC_CALLOC( Iso_Dat_t, p->nObjs );
+    p->vVisited  = Vec_IntStart( 1000 );
+    p->vPlaces   = Vec_IntStart( 1000 );
+    p->vRoots    = Vec_PtrStart( 1000 );
+    p->pCounters = ABC_CALLOC( int, (1 << AIG_ISO_NUM) );
+    return p;
+}
+void Iso_StoStop( Iso_Sto_t * p )
+{
+    Vec_IntFree( p->vPlaces );
+    Vec_IntFree( p->vVisited );
+    Vec_PtrFree( p->vRoots );
+    ABC_FREE( p->pCounters );
+    ABC_FREE( p->pData );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect statistics about one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Iso_StoCollectInfo_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int fCompl, Vec_Int_t * vVisited, Iso_Dat_t * pData, Vec_Ptr_t * vRoots )
+{
+    Iso_Dat_t * pThis = pData + Aig_ObjId(pObj);
+    assert( Aig_ObjIsCi(pObj) || Aig_ObjIsNode(pObj) );
+    if ( pThis->fVisit )
+    {
+        if ( fCompl )
+            pThis->nFoNeg++;
+        else
+            pThis->nFoPos++;
+        return;
+    }
+    assert( *((int *)pThis) == 0 );
+    pThis->fVisit = 1;
+    if ( fCompl )
+        pThis->nFoNeg++;
+    else
+        pThis->nFoPos++;
+    pThis->Level = pObj->Level;
+    pThis->nFiNeg = Aig_ObjFaninC0(pObj) + Aig_ObjFaninC1(pObj);
+    if ( Aig_ObjIsNode(pObj) )
+    {
+        if ( Aig_ObjFaninC0(pObj) < Aig_ObjFaninC1(pObj) || (Aig_ObjFaninC0(pObj) == Aig_ObjFaninC1(pObj) && Aig_ObjFanin0(pObj)->Level < Aig_ObjFanin1(pObj)->Level) )
+        {
+            pThis->Fi0Lev = pObj->Level - Aig_ObjFanin0(pObj)->Level;
+            pThis->Fi1Lev = pObj->Level - Aig_ObjFanin1(pObj)->Level;
+        }
+        else
+        {
+            pThis->Fi0Lev = pObj->Level - Aig_ObjFanin1(pObj)->Level;
+            pThis->Fi1Lev = pObj->Level - Aig_ObjFanin0(pObj)->Level;
+        }
+        Iso_StoCollectInfo_rec( p, Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj), vVisited, pData, vRoots );
+        Iso_StoCollectInfo_rec( p, Aig_ObjFanin1(pObj), Aig_ObjFaninC1(pObj), vVisited, pData, vRoots );
+    }
+    else if ( Saig_ObjIsLo(p, pObj) )
+    {
+        pThis->Fi0Lev = 1;
+        pThis->Fi1Lev = 0;
+        Vec_PtrPush( vRoots, Saig_ObjLoToLi(p, pObj) );
+    }
+    else if ( Saig_ObjIsPi(p, pObj) )
+    {
+        pThis->Fi0Lev = 0;
+        pThis->Fi1Lev = 0;
+    }
+    else
+        assert( 0 );
+    assert( pThis->nFoNeg + pThis->nFoPos );
+    Vec_IntPush( vVisited, Aig_ObjId(pObj) );
+}
+
+//static abctime time_Trav = 0;
+
+/**Function*************************************************************
+
+  Synopsis    [Collect statistics about one output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Iso_StoCollectInfo( Iso_Sto_t * p, Aig_Obj_t * pPo )
+{
+    int fVerboseShow = 0;
+    Vec_Int_t * vInfo;
+    Iso_Dat2_t * pData2 = (Iso_Dat2_t *)p->pData;
+    Aig_Man_t * pAig = p->pAig;
+    Aig_Obj_t * pObj;
+    int i, Value, Entry, * pPerm;
+//    abctime clk = Abc_Clock();
+
+    assert( Aig_ObjIsCo(pPo) );
+
+    // collect initial POs
+    Vec_IntClear( p->vVisited );
+    Vec_PtrClear( p->vRoots );
+    Vec_PtrPush( p->vRoots, pPo );
+
+    // mark internal nodes
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vRoots, pObj, i )
+        if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) )
+            Iso_StoCollectInfo_rec( pAig, Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj), p->vVisited, p->pData, p->vRoots );
+//    time_Trav += Abc_Clock() - clk;
+
+    // count how many times each data entry appears
+    Vec_IntClear( p->vPlaces );
+    Vec_IntForEachEntry( p->vVisited, Entry, i )
+    {
+        Value = pData2[Entry].Data;
+//        assert( Value > 0 );
+        if ( p->pCounters[Value]++ == 0 )
+            Vec_IntPush( p->vPlaces, Value );
+//        pData2[Entry].Data = 0;
+        *((int *)(p->pData + Entry)) = 0;
+    }
+
+    // collect non-trivial counters
+    Vec_IntClear( p->vVisited );
+    Vec_IntForEachEntry( p->vPlaces, Entry, i )
+    {
+        assert( p->pCounters[Entry] );
+        Vec_IntPush( p->vVisited, p->pCounters[Entry] );
+        p->pCounters[Entry] = 0;
+    }
+//    printf( "%d ", Vec_IntSize(p->vVisited) );
+
+    // sort the costs in the increasing order
+    pPerm = Abc_MergeSortCost( Vec_IntArray(p->vVisited), Vec_IntSize(p->vVisited) );
+    assert( Vec_IntEntry(p->vVisited, pPerm[0]) <= Vec_IntEntry(p->vVisited, pPerm[Vec_IntSize(p->vVisited)-1]) );
+
+    // create information
+    vInfo = Vec_IntAlloc( Vec_IntSize(p->vVisited) );
+    for ( i = Vec_IntSize(p->vVisited)-1; i >= 0; i-- )
+    {
+        Entry = Vec_IntEntry( p->vVisited, pPerm[i] );
+        Entry = (Entry << AIG_ISO_NUM) | Vec_IntEntry( p->vPlaces, pPerm[i] );
+        Vec_IntPush( vInfo, Entry );
+    }
+    ABC_FREE( pPerm );
+
+    // show the final result
+    if ( fVerboseShow )
+    Vec_IntForEachEntry( vInfo, Entry, i )
+    {
+        Iso_Dat2_t Data = { Entry & 0xFFFF };
+        Iso_Dat_t * pData = (Iso_Dat_t *)&Data;
+
+        printf( "%6d : ", i );
+        printf( "Freq =%6d ", Entry >> 16 );
+
+        printf( "FiNeg =%3d ", pData->nFiNeg );
+        printf( "FoNeg =%3d ", pData->nFoNeg );
+        printf( "FoPos =%3d ", pData->nFoPos );
+        printf( "Fi0L  =%3d ", pData->Fi0Lev );
+        printf( "Fi1L  =%3d ", pData->Fi1Lev );
+        printf( "Lev   =%3d ", pData->Level  );
+        printf( "\n" );
+    }
+    return vInfo;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Takes multi-output sequential AIG.]
+
+  Description [Returns candidate equivalence classes of POs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Iso_StoCompareVecInt( Vec_Int_t ** p1, Vec_Int_t ** p2 )
+{
+    return Vec_IntCompareVec( *p1, *p2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Takes multi-output sequential AIG.]
+
+  Description [Returns candidate equivalence classes of POs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Saig_IsoDetectFast( Aig_Man_t * pAig )
+{
+    Iso_Sto_t * pMan;
+    Aig_Obj_t * pObj;
+    Vec_Ptr_t * vClasses, * vInfos;
+    Vec_Int_t * vInfo, * vPrev, * vLevel;
+    int i, Number, nUnique = 0;
+    abctime clk = Abc_Clock();
+
+    // collect infos and remember their number
+    pMan = Iso_StoStart( pAig );
+    vInfos = Vec_PtrAlloc( Saig_ManPoNum(pAig) );
+    Saig_ManForEachPo( pAig, pObj, i )
+    {
+        vInfo = Iso_StoCollectInfo(pMan, pObj);
+        Vec_IntPush( vInfo, i );
+        Vec_PtrPush( vInfos, vInfo );
+    }
+    Iso_StoStop( pMan );
+    Abc_PrintTime( 1, "Info computation time", Abc_Clock() - clk );
+
+    // sort the infos
+    clk = Abc_Clock();
+    Vec_PtrSort( vInfos, (int (*)(void))Iso_StoCompareVecInt );
+
+    // create classes
+    clk = Abc_Clock();
+    vClasses = Vec_PtrAlloc( Saig_ManPoNum(pAig) );
+    // start the first class
+    Vec_PtrPush( vClasses, (vLevel = Vec_IntAlloc(4)) );
+    vPrev = (Vec_Int_t *)Vec_PtrEntry( vInfos, 0 );
+    Vec_IntPush( vLevel, Vec_IntPop(vPrev) );
+    // consider other classes
+    Vec_PtrForEachEntryStart( Vec_Int_t *, vInfos, vInfo, i, 1 )
+    {
+        Number = Vec_IntPop( vInfo );
+        if ( Vec_IntCompareVec(vPrev, vInfo) )
+            Vec_PtrPush( vClasses, Vec_IntAlloc(4) );
+        vLevel = (Vec_Int_t *)Vec_PtrEntryLast( vClasses );
+        Vec_IntPush( vLevel, Number );
+        vPrev = vInfo;
+    }
+    Vec_VecFree( (Vec_Vec_t *)vInfos );
+    Abc_PrintTime( 1, "Sorting time", Abc_Clock() - clk );
+//    Abc_PrintTime( 1, "Traversal time", time_Trav );
+
+    // report the results
+//    Vec_VecPrintInt( (Vec_Vec_t *)vClasses );
+    printf( "Devided %d outputs into %d cand equiv classes.\n", Saig_ManPoNum(pAig), Vec_PtrSize(vClasses) );
+
+    Vec_PtrForEachEntry( Vec_Int_t *, vClasses, vLevel, i )
+        if ( Vec_IntSize(vLevel) > 1 )
+            printf( "%d ", Vec_IntSize(vLevel) );
+        else
+            nUnique++;
+    printf( " Unique = %d\n", nUnique );
+
+//    return (Vec_Vec_t *)vClasses;
+    Vec_VecFree( (Vec_Vec_t *)vClasses );
+    return NULL;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigIsoSlow.c b/abc-build/src/aig/saig/saigIsoSlow.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigIsoSlow.c
@@ -0,0 +1,1224 @@
+/**CFile****************************************************************
+
+  FileName    [aigIso.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG package.]
+
+  Synopsis    [Graph isomorphism package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: aigIso.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/*
+#define ISO_MASK 0x3FF
+static int s_1kPrimes[ISO_MASK+1] = 
+{
+    901403,984877,908741,966307,924437,965639,918787,931067,982621,917669,981473,936407,990487,926077,922897,970861,
+    942317,961747,979717,978947,940157,987821,981221,917713,983083,992231,928253,961187,991817,927643,923129,934291,
+    998071,967567,961087,988661,910031,930481,904489,974167,941351,959911,963811,921463,900161,934489,905629,930653,
+    901819,909457,939871,924083,915113,937969,928457,946291,973787,912869,994093,959279,905803,995219,949903,911011,
+    986707,995053,930583,955511,928307,930889,968729,911507,949043,939359,961679,918041,937681,909091,963913,923539,
+    929587,953347,917573,913037,995387,976483,986239,946949,922489,917887,957553,931529,929813,949567,941683,905161,
+    928819,932417,900089,935903,926587,914467,967361,944833,945881,941741,915949,903407,904157,971863,993893,963607,
+    918943,912463,980957,962963,968089,904513,963763,907363,904097,904093,991343,918347,986983,986659,935819,903569,
+    929171,913933,999749,923123,961531,935861,915053,994853,943511,969923,927191,968333,949391,950959,968311,991409,
+    911681,987101,904027,975259,907399,946223,907259,900409,957221,901063,974657,912337,979001,970147,982301,968213,
+    923959,964219,935443,950161,989251,936127,985679,958159,930077,971899,944857,956083,914293,941981,909481,909047,
+    960527,958183,970687,914827,949051,928159,933551,964423,914041,915869,929953,901367,914219,975551,912391,917809,
+    991499,904781,949153,959887,961957,970943,947741,941263,984541,951437,984301,947423,905761,964913,971357,927709,
+    916441,941933,956993,988243,921197,905453,922081,950813,946331,998561,929023,937421,956231,907651,977897,905491,
+    960173,931837,955217,911951,990643,971021,949439,988453,996781,951497,906011,944309,911293,917123,983803,928097,
+    977747,928703,949957,919189,925513,923953,904997,986351,930689,902009,912007,906757,955793,926803,906809,962743,
+    911917,909329,949021,974651,959083,945367,905137,948377,931757,945409,920279,915007,960121,920609,946163,946391,
+    928903,932951,944329,901529,959809,918469,978643,911159,982573,965411,962233,911269,953273,974437,907589,992269,
+    929399,980431,905693,968267,970481,911089,950557,913799,920407,974489,909863,918529,975277,929323,971549,969181,
+    972787,964267,939971,943763,940483,971501,921637,945341,955211,920701,978349,969041,929861,904103,908539,995369,
+    995567,917471,908879,993821,947783,954599,978463,914519,942869,947263,988343,914657,956987,903641,943343,991063,
+    985403,926327,982829,958439,942017,960353,944987,934793,948971,999331,990767,915199,912211,946459,997019,965059,
+    924907,983233,943273,945359,919613,933883,928927,942763,994087,996211,918971,924871,938491,957139,918839,914629,
+    974329,900577,952823,941641,900461,946997,983123,935149,923693,908419,995651,912871,987067,920201,913921,929209,
+    962509,974599,972001,920273,922099,951781,958549,909971,975133,937207,929941,961397,980677,923579,980081,942199,
+    940319,942979,912349,942691,986989,947711,972343,932663,937877,940369,919571,927187,981439,932353,952313,915947,
+    915851,974041,989381,921029,997013,999199,914801,918751,997327,992843,982133,932051,964861,903979,937463,916781,
+    944389,986719,958369,961451,917767,954367,949853,934939,958807,975797,949699,957097,980773,969989,934907,909281,
+    904679,909833,991741,946769,908381,932447,957889,981697,905701,919033,999023,993541,912953,911719,934603,925019,
+    989341,912269,917789,981049,959149,989909,960521,952183,922627,936253,910957,972047,945037,940399,928313,928471,
+    962459,959947,927541,917333,926899,911837,985631,955127,922729,911171,900511,926251,918209,943477,955277,959773,
+    971039,917353,955313,930301,990799,957731,917519,938507,988111,911657,999721,968917,934537,903073,921703,966227,
+    904661,998213,954307,931309,909331,933643,910099,958627,914533,902903,950149,972721,915157,969037,988219,944137,
+    976411,952873,964787,970927,968963,920741,975187,966817,982909,975281,931907,959267,980711,924617,975691,962309,
+    976307,932209,989921,907969,947927,932207,945397,948929,904903,938563,961691,977671,963173,927149,951061,966547,
+    937661,983597,948139,948041,982759,941093,993703,910097,902347,990307,978217,996763,904919,924641,902299,929549,
+    977323,975071,932917,996293,925579,925843,915487,917443,999541,943043,919109,959879,912173,986339,939193,939599,
+    927077,977183,966521,959471,991943,985951,942187,932557,904297,972337,931751,964097,942341,966221,929113,960131,
+    906427,970133,996511,925637,971651,983443,981703,933613,939749,929029,958043,961511,957241,901079,950479,975493,
+    985799,909401,945601,911077,978359,948151,950333,968879,978727,961151,957823,950393,960293,915683,971513,915659,
+    943841,902477,916837,911161,958487,963691,949607,935707,987607,901613,972557,938947,931949,919021,982217,914737,
+    913753,971279,981683,915631,907807,970421,983173,916099,984587,912049,981391,947747,966233,932101,991733,969757,
+    904283,996601,979807,974419,964693,931537,917251,967961,910093,989321,988129,997307,963427,999221,962447,991171,
+    993137,914339,964973,908617,968567,920497,980719,949649,912239,907367,995623,906779,914327,918131,983113,962993,
+    977849,914941,932681,905713,932579,923977,965507,916469,984119,931981,998423,984407,993841,901273,910799,939847,
+    997153,971429,994927,912631,931657,968377,927833,920149,978041,947449,993233,927743,939737,975017,961861,984539,
+    938857,977437,950921,963659,923917,932983,922331,982393,983579,935537,914357,973051,904531,962077,990281,989231,
+    910643,948281,961141,911839,947413,923653,982801,903883,931943,930617,928679,962119,969977,926921,999773,954181,
+    963019,973411,918139,959719,918823,941471,931883,925273,918173,949453,946993,945457,959561,968857,935603,978283,
+    978269,947389,931267,902599,961189,947621,920039,964049,947603,913259,997811,943843,978277,972119,929431,918257,
+    991663,954043,910883,948797,929197,985057,990023,960961,967139,923227,923371,963499,961601,971591,976501,989959,
+    908731,951331,989887,925307,909299,949159,913447,969797,959449,976957,906617,901213,922667,953731,960199,960049,
+    985447,942061,955613,965443,947417,988271,945887,976369,919823,971353,962537,929963,920473,974177,903649,955777,
+    963877,973537,929627,994013,940801,985709,995341,936319,904681,945817,996617,953191,952859,934889,949513,965407,
+    988357,946801,970391,953521,905413,976187,968419,940669,908591,976439,915731,945473,948517,939181,935183,978067,
+    907663,967511,968111,981599,913907,933761,994933,980557,952073,906557,935621,914351,967903,949129,957917,971821,
+    925937,926179,955729,966871,960737,968521,949997,956999,961273,962683,990377,908851,932231,929749,932149,966971,
+    922079,978149,938453,958313,995381,906259,969503,922321,918947,972443,916411,935021,944429,928643,952199,918157,
+    917783,998497,944777,917771,936731,999953,975157,908471,989557,914189,933787,933157,938953,922931,986569,964363,
+    906473,963419,941467,946079,973561,957431,952429,965267,978473,924109,979529,991901,988583,918259,961991,978037,
+    938033,949967,986071,986333,974143,986131,963163,940553,950933,936587,923407,950357,926741,959099,914891,976231,
+    949387,949441,943213,915353,983153,975739,934243,969359,926557,969863,961097,934463,957547,916501,904901,928231,
+    903673,974359,932219,916933,996019,934399,955813,938089,907693,918223,969421,940903,940703,913027,959323,940993,
+    937823,906691,930841,923701,933259,911959,915601,960251,985399,914359,930827,950251,975379,903037,905783,971237
+};
+*/
+
+/*
+#define ISO_MASK 0x7F
+static int s_1kPrimes[ISO_MASK+1] = { 
+    1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 
+    1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 
+    2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 
+    2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 
+    3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 
+    3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 
+    4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 
+    4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 
+    5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 
+    6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 
+    6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 
+    7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 
+    8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+};
+*/
+
+/*
+#define ISO_MASK 0x7
+static int s_1kPrimes[ISO_MASK+1] = { 
+    12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741
+};
+*/
+
+#define ISO_MASK 0x3FF
+static int s_1kPrimes[ISO_MASK+1] = 
+//#define ISO_MASK 0xFF
+//static int s_1kPrimes[0x3FF+1] = 
+{
+    0x38c19891,0xde37b0ed,0xdebcd025,0xe19b7bbe,0x7e7ebd0e,0xaeed03a1,0x811230dc,0x10bfece0,
+    0xb3b23fb1,0x74176098,0xc34ec7c5,0x6bef8939,0xc40be5e3,0x2ab51a09,0xafc17cea,0x0dccc7a2,
+    0xdf7db34d,0x1009c96f,0x93fd7494,0x54385b33,0x6f36eed8,0xa1953f82,0xfbd1144a,0xde533a46,
+    0x23aa1cad,0x9a18943c,0xb65000d8,0x867e9974,0xe7880035,0xf9931ad4,0xcfca1e45,0x6b5aec96,
+    0xe9c1a119,0xfa4968c5,0x94cf93da,0xe8c9eac4,0x95884242,0x1bba52c7,0x9232c321,0x9cec8658,
+    0x984b6ad9,0x18a6eed3,0x950353e2,0x6222f6eb,0xdfbedd47,0xef0f9023,0xac932a26,0x590eaf55,
+    0x97d0a034,0xdc36cd2e,0x22736b37,0xdc9066b0,0x2eb2f98b,0x5d9c7baf,0x85747c9e,0x8aca1055,
+    0x50d66b74,0x2f01ae9e,0xa1a80123,0x3e1ce2dc,0xebedbc57,0x4e68bc34,0x855ee0cf,0x17275120,
+    0x2ae7f2df,0xf71039eb,0x7c283eec,0x70cd1137,0x7cf651f3,0xa87bfa7a,0x14d87f02,0xe82e197d,
+    0x8d8a5ebe,0x1e6a15dc,0x197d49db,0x5bab9c89,0x4b55dea7,0x55dede49,0x9a6a8080,0xe5e51035,
+    0xe148d658,0x8a17eb3b,0xe22e4b38,0xe5be2a9a,0xbe938cbb,0x3b981069,0x7f9c0c8e,0xf756df10,
+    0x8fa783f7,0x252062ce,0x3dc46b4b,0xf70f6432,0x3f378276,0x44b137a1,0x2bf74b77,0x04892ed6,
+    0xfd318de1,0xd58c235e,0x94c6d25b,0x7aa5f218,0x35c9e921,0x5732fbbb,0x06026481,0xf584a44f,
+    0x946e1b5f,0x8463d5b2,0x4ebca7b2,0x54887b15,0x08d1e804,0x5b22067d,0x794580f6,0xb351ea43,
+    0xbce555b9,0x19ae2194,0xd32f1396,0x6fc1a7f1,0x1fd8a867,0x3a89fdb0,0xea49c61c,0x25f8a879,
+    0xde1e6437,0x7c74afca,0x8ba63e50,0xb1572074,0xe4655092,0xdb6f8b1c,0xc2955f3c,0x327f85ba,
+    0x60a17021,0x95bd261d,0xdea94f28,0x04528b65,0xbe0109cc,0x26dd5688,0x6ab2729d,0xc4f029ce,
+    0xacf7a0be,0x4c912f55,0x34c06e65,0x4fbb938e,0x1533fb5f,0x03da06bd,0x48262889,0xc2523d7d,
+    0x28a71d57,0x89f9713a,0xf574c551,0x7a99deb5,0x52834d91,0x5a6f4484,0xc67ba946,0x13ae698f,
+    0x3e390f34,0x34fc9593,0x894c7932,0x6cf414a3,0xdb7928ab,0x13a3b8a3,0x4b381c1d,0xa10b54cb,
+    0x55359d9d,0x35a3422a,0x58d1b551,0x0fd4de20,0x199eb3f4,0x167e09e2,0x3ee6a956,0x5371a7fa,
+    0xd424efda,0x74f521c5,0xcb899ff6,0x4a42e4f4,0x747917b6,0x4b08df0b,0x090c7a39,0x11e909e4,
+    0x258e2e32,0xd9fad92d,0x48fe5f69,0x0545cde6,0x55937b37,0x9b4ae4e4,0x1332b40e,0xc3792351,
+    0xaff982ef,0x4dba132a,0x38b81ef1,0x28e641bf,0x227208c1,0xec4bbe37,0xc4e1821c,0x512c9d09,
+    0xdaef1257,0xb63e7784,0x043e04d7,0x9c2cea47,0x45a0e59a,0x281315ca,0x849f0aac,0xa4071ed3,
+    0x0ef707b3,0xfe8dac02,0x12173864,0x471f6d46,0x24a53c0a,0x35ab9265,0xbbf77406,0xa2144e79,
+    0xb39a884a,0x0baf5b6d,0xcccee3dd,0x12c77584,0x2907325b,0xfd1adcd2,0xd16ee972,0x345ad6c1,
+    0x315ebe66,0xc7ad2b8d,0x99e82c8d,0xe52da8c8,0xba50f1d3,0x66689cd8,0x2e8e9138,0x43e15e74,
+    0xf1ced14d,0x188ec52a,0xe0ef3cbb,0xa958aedc,0x4107a1bc,0x5a9e7a3e,0x3bde939f,0xb5b28d5a,
+    0x596fe848,0xe85ad00c,0x0b6b3aae,0x44503086,0x25b5695c,0xc0c31dcd,0x5ee617f0,0x74d40c3a,
+    0xd2cb2b9f,0x1e19f5fa,0x81e24faf,0xa01ed68f,0xcee172fc,0x7fdf2e4d,0x002f4774,0x664f82dd,
+    0xc569c39a,0xa2d4dcbe,0xaadea306,0xa4c947bf,0xa413e4e3,0x81fb5486,0x8a404970,0x752c980c,
+    0x98d1d881,0x5c932c1e,0xeee65dfb,0x37592cdd,0x0fd4e65b,0xad1d383f,0x62a1452f,0x8872f68d,
+    0xb58c919b,0x345c8ee3,0xb583a6d6,0x43d72cb3,0x77aaa0aa,0xeb508242,0xf2db64f8,0x86294328,
+    0x82211731,0x1239a9d5,0x673ba5de,0xaf4af007,0x44203b19,0x2399d955,0xa175cd12,0x595928a7,
+    0x6918928b,0xde3126bb,0x6c99835c,0x63ba1fa2,0xdebbdff0,0x3d02e541,0xd6f7aac6,0xe80b4cd0,
+    0xd0fa29f1,0x804cac5e,0x2c226798,0x462f624c,0xad05b377,0x22924fcd,0xfbea205c,0x1b47586d,
+    0x214d04ab,0xe093e487,0x10607ada,0x42b261cc,0x1a85e0f6,0xb851bfc3,0x77d5591c,0xda13f344,
+    0xc39c4c00,0xe60d75fc,0x7edae36a,0x3e4ac3ec,0x8bc38db4,0xe848dce9,0xb2407d4d,0x0d79c61e,
+    0x1e6c293a,0x7bc30986,0xdf18cb8f,0x23003172,0x6948e3fa,0x9b7e4f09,0x14b3b339,0x9c8078c2,
+    0x9a47c29f,0x85bb45ec,0x9ca35a93,0xd7db5227,0x1d9b0a10,0xb7fbbfe9,0x05b72426,0x6f30b2fa,
+    0x9fb44078,0xedffd3f8,0x1b02b7bc,0x43e3cfd3,0x0d44293e,0x25c8d552,0xedd3f85d,0x6f921c8c,
+    0x953cca0c,0x9c975b70,0xc6bd0b53,0x4f204f3e,0xa3cc69cc,0xceec390b,0x34905626,0x82ad5d41,
+    0xe46589a5,0x7989841d,0x045d7d9f,0xe49b7b2f,0x46baf101,0x996f92de,0x427566c8,0x918a1ee1,
+    0xf4baa589,0x6bdff7c7,0x3c6936ea,0xe85bfb70,0x5d96ea26,0x6d5a8991,0x7f0a528d,0x852f0634,
+    0x2ec04501,0x5ca15c35,0xd8695e7a,0x456876c7,0x52e97b83,0x34b4c5ed,0x54d73fbb,0x44a6be01,
+    0xf8019155,0x33d55a31,0x3fe51c99,0xe1cb94fd,0x8c39cd60,0xd585efba,0x2765579b,0xb8f7ed12,
+    0xbb04b2cd,0xd8859981,0xd966988d,0xa68bfeda,0x73110705,0x38d6aec0,0x613bc275,0xc7283c2d,
+    0xe051d0b1,0x32b8c2ee,0x0e73fb9e,0x7ab05c25,0x6ff652b9,0x45aeabc6,0x6be1a891,0x5b43531b,
+    0xcd711248,0x2b777d40,0x46956d16,0x474355a8,0xe872d6c6,0xe4158d96,0xabe03036,0x5b4fd9a4,
+    0xeceba1db,0xaac9713f,0xe953153b,0xf44a9229,0x460cba72,0xfd13fdf6,0x8bbf82ae,0xaf55778f,
+    0xa447a5b2,0x98b647b3,0x5f351c57,0x69d0bb71,0xf14d2706,0x78b1a3af,0x7206c73f,0x3f5cd4a6,
+    0x5c0e4515,0xdb46a663,0x10c3a9b0,0x8eda7748,0x52bb44c9,0x3df62689,0xc83e2732,0xf36c99af,
+    0x7ec7a94c,0x5c823718,0x6586e58e,0x4b726e75,0xcfe03a05,0x34eb2f4b,0xf4eec9cf,0xb38d6d73,
+    0x71fafa9e,0x0371a29a,0xc405f83b,0x889f49c2,0xd1443000,0x469665bf,0x609ed65d,0x67c8f9ba,
+    0x9d2f6055,0xb91b8eb1,0x96c809fe,0x2d6ab0f5,0xc16d4f04,0x590171ab,0x73d67526,0xf724e44c,
+    0x6aef02b7,0x6489a325,0x4458401e,0x22d94ad7,0x05e5be57,0x5634fad8,0x951fcf70,0x4baad7f0,
+    0x40c1090d,0xedc28abd,0x343cc6e4,0x4ff7c030,0x0734a641,0x2635a90e,0x2e000c84,0x4b617a70,
+    0x872e9c9e,0x3dceeb42,0xd0fcc398,0x9cc9b9c8,0x2de02f0c,0xaf0e2614,0xa60253aa,0xe0517492,
+    0xa7bde4b4,0x3bb66d7d,0x7f215e82,0xf259de66,0xe17380fe,0xdbc718b4,0x66abcc29,0xf0826e1f,
+    0x08f60995,0xce81b933,0xa832c0e9,0x37aed7d4,0x8a75c261,0x916627b4,0xd486a04b,0x64fd0fde,
+    0x1261328a,0xe037772f,0xb5b71117,0x55d04bd8,0x8f6c1c7b,0xb9f5fcdd,0x5918f756,0x25c90099,
+    0x2e8787db,0x58e14e38,0x0d397852,0x32c8e33b,0x5ae2b795,0x3a7b3ff7,0x5eebf893,0x1aeee816,
+    0xc2ef31d0,0x1d86e615,0x183f1de3,0xb89d46c4,0x525ebbf6,0xfe0198ca,0x4986cc4a,0x2a75701e,
+    0x382158b1,0x192ee88f,0x3e512912,0xcd571c3d,0xdf694fe8,0xec8ead1d,0x83719ac3,0x3f654079,
+    0xf6a623c5,0x33e1fc6e,0xe7f7c426,0x5bff0f6c,0x698a9bb1,0xec2a29ba,0x75358b45,0x40c6ffef,
+    0x6605bb55,0x53a8c97a,0x7bba1569,0x499bc51b,0x5849c89a,0xe6ddb267,0x8659c719,0x14a05548,
+    0xeec648a9,0x618af87a,0x62214521,0x7f36e610,0x152efeeb,0xc2b0f0ed,0x1d657588,0xa5fcec4b,
+    0xf872f109,0x46903038,0x04b57b97,0xe5d51b14,0x06c264ec,0x68aa8d14,0xa4e1bed8,0xdae169c2,
+    0xeb90debd,0xe8c11a7a,0xcafce013,0x63820cee,0x948c23e5,0xc1d42ea3,0x8256c951,0x9b587773,
+    0x2fa8380c,0x30255e09,0x1a809cdc,0xe1446068,0x2714621d,0xb3347d64,0x1f4cbf3d,0xd068bc26,
+    0x2c422740,0x06c4a3ad,0x5dc9d63c,0x4724bf48,0x28e34add,0x27d5221d,0xe349c7e2,0x6119e0a5,
+    0x4ae7d29f,0x53a7912d,0xfc5db779,0x7d28d357,0xfd80036d,0x06bcc597,0x36d70a8a,0x37738cb7,
+    0xf11e6272,0xfdd5d153,0x5dc666dc,0x6b5a415d,0x1073b415,0x36f30d9a,0x807daf7b,0x387f6823,
+    0x8970fe00,0xee560be5,0xea8c0bad,0xfac2b422,0xc845861d,0xa181a2ee,0x29c4dffd,0x4d441bb2,
+    0x7a64cf93,0x0c33e6ac,0x0a35d034,0x1067d26d,0x8c7da0cc,0x2d6e2d5a,0x9932c25a,0x5fca4e2c,
+    0x2c82fd71,0x41730b70,0x244bdbb9,0x96514307,0xc6a32a6b,0xc4c256a7,0x38517fd8,0x541aa859,
+    0x0752afe3,0x741e22f9,0xa2565483,0x7588b0b9,0xdd404e42,0x4d86c49d,0x6fa93fc1,0x163bd200,
+    0x745d0d31,0x8d3dd20e,0xebdc64db,0x9315c149,0x39db3299,0xb0c22004,0xa4c0295b,0x8b3573eb,
+    0xd92a40a3,0x73d6c379,0x67673309,0xdaff1d7f,0x42fcfeb8,0xd57c11a4,0x402066ef,0x9d1134e0,
+    0x9f417081,0x10f49e00,0x7e7ee855,0x314e6d25,0x602bdbe6,0xa4be4045,0xac511dc4,0x33d6bda8,
+    0x2f2bc412,0x4b9c0b6c,0x98aaab06,0x7f0a5801,0xfbf1f16d,0x058f54ae,0x4fd97724,0x348cb50b,
+    0xef6f659f,0x0cd8b184,0x1d71a666,0xae3c87dd,0x7bd56793,0xe0f8f6a8,0x90429c55,0x8a3cc4d0,
+    0x49957b70,0x3baf3912,0x755efebb,0xa5eca17f,0x486065a1,0x1dffcefb,0xd914b3a0,0x1ced93c1,
+    0xa4262dcd,0xc12a4adc,0x08f6de4e,0x4c204faf,0xca1815de,0xa4af836f,0x91d5e44d,0xd2a7caa4,
+    0x68a9a3fe,0x844f8dac,0x3fc36c67,0x8be23937,0x69879d94,0x5d0dbecb,0x1f0f59a4,0x94721142,
+    0xfca6064a,0x6d28aa48,0x804cd04e,0x4a3906de,0x8e352509,0x302326d9,0xed4937ed,0x4a570e63,
+    0xcaa57efb,0x64bd4878,0x3419334a,0x712e5f6b,0x9fa9d687,0x06f8645f,0x620ca96f,0xdc5d6cce,
+    0x392f3257,0x52140f06,0xc4b3bda4,0xe8c7eba7,0x066bd754,0xc5941f26,0xe6dfd573,0x328dd14d,
+    0xb1cb4ba7,0x1d37a9b8,0x96a195a5,0x970e535a,0x290351b8,0x570000f6,0xe14ae341,0x35ede6a6,
+    0x9a02f032,0xaf2ebb58,0x146be492,0x670b3e4b,0x72fa6cfd,0xa243af97,0xbbd5fc21,0xcb8852a2,
+    0x5d5b4a42,0xeefff0ac,0xa59ad1b6,0x3ec55544,0x48d64f69,0x9065d3d0,0xdd09485b,0xdd63bd09,
+    0x605e811d,0xc4b4ed7d,0xb0b58558,0x0644400b,0x12222346,0x086f146a,0xad6dee36,0x5488d1a3,
+    0x0c93bc0c,0x18555d92,0x9f4427bf,0xa590a66a,0x3a630fda,0xf1681c2e,0x948a16fb,0x16fe3338,
+    0xc9832357,0xd1e8e6b5,0xd9cfe034,0x05b22f26,0x27233c6e,0x355890e1,0xfbe6eaf3,0x0dcd8e8f,
+    0x00b5df46,0xd97730ac,0xc6dfd8ff,0x0cb1840a,0x41e9d249,0xbb471b4e,0x480b8f63,0x1ffe8871,
+    0x17b11821,0x1709e440,0xcefb3668,0xa4954ddd,0xf03ef8b5,0x6b3e633c,0xe5813096,0x3697c9a6,
+    0x7800f52f,0x73a7aa39,0x59ac23b7,0xb4663166,0x9ca9d6f8,0x2d441072,0x38cef3d3,0x39a3faf6,
+    0x89299fb9,0xd558295f,0xcf79c633,0x232dd96e,0xadb2955b,0xe962cbb9,0xab7c0061,0x1027c329,
+    0xb4b43e07,0x25240a7a,0x98ea4825,0xdbf2edbd,0x8be15d26,0x879f3cd9,0xa4138089,0xa32dcb06,
+    0x602af961,0x4b13f451,0x1c87d0d5,0xc3bb141b,0x9ebf55a1,0xef030a9a,0x8d199b93,0xdabcbb56,
+    0xf412f80f,0x302e90ad,0xc4d9878b,0xc392f650,0x4fd3a614,0x0a96ddc4,0xcd1878c7,0x9ddd3ae1,
+    0xdaf46458,0xba7c8656,0xf667948f,0xc37e3c23,0x04a577c6,0xbe615f1e,0xcc97406c,0xd497f16f,
+    0x79586586,0xd2057d14,0x1bb92028,0xab888e5e,0x26bef100,0xf46b3671,0xf21f1acc,0x67f288c8,
+    0x39c722df,0x61d21eaf,0x9c5853a0,0x63b693c7,0x1ea53c0a,0x95bc0a85,0xa7372f2d,0x3ef6a6b3,
+    0x82c9c4ac,0x4dea10ee,0xdfcb543d,0xd412f427,0x53e27f2c,0x875d8422,0x5367a7d8,0x41acf3fa,
+    0xbce47234,0x8056fb9a,0x4e9a4c48,0xe4a45945,0x2cfee3ae,0xb4554b10,0x5e37a915,0x591b1963,
+    0x4fa255c1,0xe01c897b,0x504e6208,0x7c7368eb,0x13808fd7,0x02ac0816,0x30305d2c,0x6c4bbdb7,
+    0xa48a9599,0x57466059,0x4c6ebfc7,0x8587ccdf,0x6ff0abf0,0x5b6b63fe,0x31d9ec64,0x63458abd,
+    0x21245905,0xccdb28fc,0xac828acb,0xe5e82bea,0xa7d76141,0xa699038e,0xcaba7e06,0x2710253f,
+    0x2ff9c94d,0x26e48a2c,0xd713ec5e,0x869f2ed4,0x25bcd712,0xcb3e918f,0x615c3a5a,0x9fb43903,
+    0x37900eb9,0x4f682db0,0x35a80dc6,0x4eb27c65,0x502735ab,0xb163b4c8,0x604649a8,0xb23a6cd3,
+    0x9f715091,0x2e6fbb51,0x2ec9144b,0x272cbe65,0x90a0a453,0x420e1503,0x2d00d338,0x4aa96675,
+    0xd025b61c,0xab02d9d7,0x2afe2a37,0xf8129b9b,0x4db04c54,0x654a5c06,0x3213ff51,0x4e09d0b1,
+    0x333369a3,0xae27310a,0x91d076d0,0xa96ebcd0,0xefde54f4,0x021c309a,0xd506f53d,0xa5635251,
+    0x2f23916e,0x1fe86bb1,0xcbc62160,0x2147c8cc,0xdeb3e47c,0x028e3987,0x8061de42,0x39be931b,
+    0x2b7e54c5,0xe64d2f96,0x4069522d,0x4aa66857,0x83b62634,0x4ba72095,0x9aade2a9,0xf1223cd9,
+    0x91cbddf0,0xec5d237f,0x593f3280,0x0b924439,0x446f4063,0xc66f8d8c,0x8b7128ba,0xb597f451,
+    0xc8925236,0x1720f235,0x7cd2e9a0,0x4c130339,0x8a665a52,0x5bef2733,0xba35d9bc,0x6d26644c,
+    0x385cdce1,0x509e4280,0x12aa9ed7,0xf5314d21,0xbe249d4a,0xf32e9753,0x91821cf9,0x01d63491,
+    0x49afa237,0x80e0bc27,0x844d796b,0xeff5ccb7,0x46303091,0x743484b4,0x77de1ab7,0x5ab00bea,
+    0x6316cd81,0x8ded07f4,0x3845a3a5,0x206625c4,0x8c123c6f,0xc80a971e,0xd4d4fa3f,0x5eba911d,
+    0xee168406,0x61cdcbad,0x981a44cd,0x718d030f,0xf653e92e,0xd5b77859,0x11e9e5d9,0xf6fe6ff3,
+    0x5239f010,0xe289b21b,0x0b52832b,0xca700c62,0xee7a5e15,0x8543ce2c,0x94a703cc,0x0b844d34,
+    0xf70638e5,0xfa286206,0xf8778906,0x1419e883,0xdb0fc46b,0xbeb74261,0xc6957b62,0x8352d2a8,
+    0x460586ce,0x90b28336,0xc9107ea8,0x3590403b,0x259a4279,0x6a1a7bbe,0x0f3b76e1,0x4872a716,
+    0xa5bfff13,0x8b30be72,0xe5a68957,0x17dbbc52,0x33a40187,0x7074220c,0xd8221b92,0x40ec7448,
+    0x7dbbcdfc,0xd5a9bb83,0xb4c0d25c,0xa0040390,0x6fb429dc,0xb8cede12,0x87d193bd,0x55c6e004
+};
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define ISO_NUM_INTS 3
+
+typedef struct Iso_Obj_t_ Iso_Obj_t;
+struct Iso_Obj_t_
+{
+    // hashing entries (related to the parameter ISO_NUM_INTS!)
+    unsigned      Level     : 30;
+    unsigned      nFinNeg   :  2;
+    unsigned      FaninSig;
+    unsigned      FanoutSig;
+    // other data
+    int           iNext;          // hash table entry
+    int           iClass;         // next one in class
+    int           Id;             // unique ID
+};
+
+typedef struct Iso_Man_t_ Iso_Man_t;
+struct Iso_Man_t_
+{
+    Aig_Man_t *   pAig;           // user's AIG manager
+    Iso_Obj_t *   pObjs;          // isomorphism objects
+    int           nObjIds;        // counter of object IDs
+    int           nClasses;       // total number of classes
+    int           nEntries;       // total number of entries
+    int           nSingles;       // total number of singletons
+    int           nObjs;          // total objects
+    int           nBins;          // hash table size
+    int *         pBins;          // hash table 
+    Vec_Ptr_t *   vSingles;       // singletons 
+    Vec_Ptr_t *   vClasses;       // other classes
+    Vec_Ptr_t *   vTemp1;         // other classes
+    Vec_Ptr_t *   vTemp2;         // other classes
+    abctime       timeHash;
+    abctime       timeFout;
+    abctime       timeSort;
+    abctime       timeOther;
+    abctime       timeTotal;
+};
+
+static inline Iso_Obj_t *  Iso_ManObj( Iso_Man_t * p, int i )            { assert( i >= 0 && i < p->nObjs ); return i ? p->pObjs + i : NULL;                }
+static inline int          Iso_ObjId( Iso_Man_t * p, Iso_Obj_t * pObj )  { assert( pObj > p->pObjs && pObj < p->pObjs + p->nObjs ); return pObj - p->pObjs; }
+static inline Aig_Obj_t *  Iso_AigObj( Iso_Man_t * p, Iso_Obj_t * q )    { return Aig_ManObj( p->pAig, Iso_ObjId(p, q) );                                   }
+
+#define Iso_ManForEachObj( p, pObj, i )   \
+    for ( i = 1; (i < p->nObjs) && ((pObj) = Iso_ManObj(p, i)); i++ ) if ( pIso->Level == -1 ) {} else
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+//extern void Iso_ReadPrimes( char * pFileName );
+//Iso_ReadPrimes( "primes.txt" );
+
+/**Function*************************************************************
+
+  Synopsis    [Read primes from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Iso_ReadPrimes( char * pFileName )
+{
+    FILE * pFile;
+    int Nums[10000];
+    int i, j, Temp, nSize = 0;
+    // read the numbers
+    pFile = fopen( pFileName, "rb" );
+    while ( fscanf( pFile, "%d", Nums + nSize++ ) == 1 );
+    fclose( pFile );
+    assert( nSize >= (1<<10) );
+    // randomly permute
+    srand( 111 );
+    for ( i = 0; i < nSize; i++ )
+    {
+        j = rand() % nSize;
+        Temp = Nums[i];
+        Nums[i] = Nums[j];
+        Nums[j] = Temp;
+    }
+    // write out
+    for ( i = 0; i < 64; i++ )
+    {
+        printf( "    " );
+        for ( j = 0; j < 16; j++ )
+            printf( "%d,", Nums[i*16+j] );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read primes from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Iso_FindNumbers()
+{
+    unsigned Nums[1024];
+    unsigned char * pNums = (unsigned char *)Nums;
+    int i, j;
+    srand( 111 );
+    for ( i = 0; i < 1024 * 4; i++ )
+        pNums[i] = (unsigned char)rand();
+    // write out
+    for ( i = 0; i < 128; i++ )
+    {
+        printf( "    " );
+        for ( j = 0; j < 8; j++ )
+            printf( "0x%08x,", Nums[i*8+j] );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Iso_ManObjCount_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int * pnNodes, int * pnEdges )
+{
+    if ( Aig_ObjIsCi(pObj) )
+        return;
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    Iso_ManObjCount_rec( p, Aig_ObjFanin0(pObj), pnNodes, pnEdges );
+    Iso_ManObjCount_rec( p, Aig_ObjFanin1(pObj), pnNodes, pnEdges );
+    (*pnEdges) += Aig_ObjFaninC0(pObj) + Aig_ObjFaninC1(pObj);
+    (*pnNodes)++;
+}
+void Iso_ManObjCount( Aig_Man_t * p, Aig_Obj_t * pObj, int * pnNodes, int * pnEdges )
+{
+    assert( Aig_ObjIsNode(pObj) );
+    *pnNodes = *pnEdges = 0;
+    Aig_ManIncrementTravId( p );
+    Iso_ManObjCount_rec( p, pObj, pnNodes, pnEdges );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Iso_Man_t * Iso_ManStart( Aig_Man_t * pAig )
+{
+    Iso_Man_t * p;
+    p = ABC_CALLOC( Iso_Man_t, 1 );
+    p->pAig     = pAig;
+    p->nObjs    = Aig_ManObjNumMax( pAig );
+    p->pObjs    = ABC_CALLOC( Iso_Obj_t, p->nObjs );
+    p->nBins    = Abc_PrimeCudd( p->nObjs );
+    p->pBins    = ABC_CALLOC( int, p->nBins );    
+    p->vSingles = Vec_PtrAlloc( 1000 );
+    p->vClasses = Vec_PtrAlloc( 1000 );
+    p->vTemp1   = Vec_PtrAlloc( 1000 );
+    p->vTemp2   = Vec_PtrAlloc( 1000 );
+    p->nObjIds  = 1;
+    return p;
+}
+void Iso_ManStop( Iso_Man_t * p, int fVerbose )
+{
+    if ( fVerbose )
+    {
+        p->timeOther = p->timeTotal - p->timeHash - p->timeFout;
+        ABC_PRTP( "Building ", p->timeFout,               p->timeTotal );
+        ABC_PRTP( "Hashing  ", p->timeHash-p->timeSort,   p->timeTotal );
+        ABC_PRTP( "Sorting  ", p->timeSort,               p->timeTotal );
+        ABC_PRTP( "Other    ", p->timeOther,              p->timeTotal );
+        ABC_PRTP( "TOTAL    ", p->timeTotal,              p->timeTotal );
+    }
+    Vec_PtrFree( p->vTemp1 );
+    Vec_PtrFree( p->vTemp2 );
+    Vec_PtrFree( p->vClasses );
+    Vec_PtrFree( p->vSingles );
+    ABC_FREE( p->pBins );
+    ABC_FREE( p->pObjs );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compares two objects by their signature.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Iso_ObjCompare( Iso_Obj_t ** pp1, Iso_Obj_t ** pp2 )
+{
+    return -memcmp( *pp1, *pp2, sizeof(int) * ISO_NUM_INTS );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares two objects by their ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Iso_ObjCompareByData( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 )
+{
+    Aig_Obj_t * pIso1 = *pp1;
+    Aig_Obj_t * pIso2 = *pp2;
+    assert( Aig_ObjIsCi(pIso1) || Aig_ObjIsCo(pIso1) );
+    assert( Aig_ObjIsCi(pIso2) || Aig_ObjIsCo(pIso2) );
+    return pIso1->iData - pIso2->iData;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Iso_ObjHash( Iso_Obj_t * pIso, int nBins )
+{
+    static unsigned BigPrimes[8] = {12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741};
+    unsigned * pArray = (unsigned *)pIso;
+    unsigned i, Value = 0;
+    assert( ISO_NUM_INTS < 8 );
+    for ( i = 0; i < ISO_NUM_INTS; i++ )
+        Value ^= BigPrimes[i] * pArray[i];
+    return Value % nBins;
+}
+static inline int Iso_ObjHashAdd( Iso_Man_t * p, Iso_Obj_t * pIso )
+{
+    Iso_Obj_t * pThis;
+    int * pPlace = p->pBins + Iso_ObjHash( pIso, p->nBins );
+    p->nEntries++;
+    for ( pThis = Iso_ManObj(p, *pPlace); 
+          pThis; pPlace = &pThis->iNext, 
+          pThis = Iso_ManObj(p, *pPlace) )
+        if ( Iso_ObjCompare( &pThis, &pIso ) == 0 ) // equal signatures
+        {
+            if ( pThis->iClass == 0 )
+            {
+                p->nClasses++;
+                p->nSingles--;
+            }
+            // add to the list
+            pIso->iClass = pThis->iClass;
+            pThis->iClass = Iso_ObjId( p, pIso );
+            return 1;
+        }
+    // create new list
+    *pPlace = Iso_ObjId( p, pIso );
+    p->nSingles++;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Iso_ManCollectClasses( Iso_Man_t * p )
+{
+    Iso_Obj_t * pIso;
+    int i;
+    abctime clk = Abc_Clock();
+    Vec_PtrClear( p->vSingles );
+    Vec_PtrClear( p->vClasses );
+    for ( i = 0; i < p->nBins; i++ )
+    {
+        for ( pIso = Iso_ManObj(p, p->pBins[i]); pIso; pIso = Iso_ManObj(p, pIso->iNext) )
+        {
+            assert( pIso->Id == 0 );
+            if ( pIso->iClass )
+                Vec_PtrPush( p->vClasses, pIso );
+            else 
+                Vec_PtrPush( p->vSingles, pIso );
+        }
+    }
+    clk = Abc_Clock();
+    Vec_PtrSort( p->vSingles, (int (*)(void))Iso_ObjCompare );
+    Vec_PtrSort( p->vClasses, (int (*)(void))Iso_ObjCompare );
+    p->timeSort += Abc_Clock() - clk;
+    assert( Vec_PtrSize(p->vSingles) == p->nSingles );
+    assert( Vec_PtrSize(p->vClasses) == p->nClasses );
+    // assign IDs to singletons
+    Vec_PtrForEachEntry( Iso_Obj_t *, p->vSingles, pIso, i )
+        if ( pIso->Id == 0 )
+            pIso->Id = p->nObjIds++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Iso_Man_t * Iso_ManCreate( Aig_Man_t * pAig )
+{
+    int fUseXor = 0;
+    Iso_Man_t * p;
+    Iso_Obj_t * pIso, * pIsoF;
+    Aig_Obj_t * pObj, * pObjLi;
+    int i;
+    p = Iso_ManStart( pAig );
+
+    // create TFI signatures
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+        if ( Aig_ObjIsCo(pObj) )
+            continue;
+        pIso = p->pObjs + i;
+        pIso->Level = pObj->Level;
+//        pIso->nFinNeg = Aig_ObjFaninC0(pObj) + Aig_ObjFaninC1(pObj);
+
+        assert( pIso->FaninSig == 0 );
+        assert( pIso->FanoutSig == 0 );
+        if ( fUseXor )
+        {
+            if ( Aig_ObjIsNode(pObj) )
+            {
+                pIsoF = p->pObjs + Aig_ObjFaninId0(pObj);
+                pIso->FaninSig ^= pIsoF->FaninSig;
+                pIso->FaninSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK];
+
+                pIsoF = p->pObjs + Aig_ObjFaninId1(pObj);
+                pIso->FaninSig ^= pIsoF->FaninSig;
+                pIso->FaninSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC1(pObj)) & ISO_MASK];
+            }
+        }
+        else
+        {
+            if ( Aig_ObjIsNode(pObj) )
+            {
+                pIsoF = p->pObjs + Aig_ObjFaninId0(pObj);
+                pIso->FaninSig += pIsoF->FaninSig;
+                pIso->FaninSig += pIso->Level * s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK];
+
+                pIsoF = p->pObjs + Aig_ObjFaninId1(pObj);
+                pIso->FaninSig += pIsoF->FaninSig;
+                pIso->FaninSig += pIso->Level * s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC1(pObj)) & ISO_MASK];
+            }
+        }
+    }
+
+    // create TFO signatures
+    Aig_ManForEachObjReverse( pAig, pObj, i )
+    {
+        if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) )
+            continue;
+        pIso = p->pObjs + i;
+        if ( fUseXor )
+        {
+            if ( Aig_ObjIsNode(pObj) )
+            {
+                pIsoF = p->pObjs + Aig_ObjFaninId0(pObj);
+                pIsoF->FanoutSig ^= pIso->FanoutSig;
+                pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK];
+
+                pIsoF = p->pObjs + Aig_ObjFaninId1(pObj);
+                pIsoF->FanoutSig ^= pIso->FanoutSig;
+                pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC1(pObj)) & ISO_MASK];
+            }
+            else if ( Aig_ObjIsCo(pObj) )
+            {
+                pIsoF = p->pObjs + Aig_ObjFaninId0(pObj);
+                pIsoF->FanoutSig ^= pIso->FanoutSig;
+                pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK];
+            }
+        }
+        else
+        {
+            if ( Aig_ObjIsNode(pObj) )
+            {
+                pIsoF = p->pObjs + Aig_ObjFaninId0(pObj);
+                pIsoF->FanoutSig += pIso->FanoutSig;
+                pIsoF->FanoutSig += pIso->Level * s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK];
+
+                pIsoF = p->pObjs + Aig_ObjFaninId1(pObj);
+                pIsoF->FanoutSig += pIso->FanoutSig;
+                pIsoF->FanoutSig += pIso->Level * s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC1(pObj)) & ISO_MASK];
+            }
+            else if ( Aig_ObjIsCo(pObj) )
+            {
+                pIsoF = p->pObjs + Aig_ObjFaninId0(pObj);
+                pIsoF->FanoutSig += pIso->FanoutSig;
+                pIsoF->FanoutSig += pIso->Level * s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK];
+            }
+        }
+    }
+
+    // consider flops
+    Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObj, i )
+    {
+        if ( Aig_ObjFaninId0(pObjLi) == 0 ) // ignore constant!
+            continue;
+        pIso  = Iso_ManObj( p, Aig_ObjId(pObj) );
+        pIsoF = Iso_ManObj( p, Aig_ObjFaninId0(pObjLi) );
+
+        assert( pIso->FaninSig == 0 );
+        pIso->FaninSig = pIsoF->FaninSig;
+
+//        assert( pIsoF->FanoutSig == 0 );
+        pIsoF->FanoutSig += pIso->FanoutSig;
+    }
+/*
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+        pIso = p->pObjs + i;
+        Aig_ObjPrint( pAig, pObj );
+        printf( "Lev = %4d.  Pos = %4d.  FaninSig = %10d.  FanoutSig = %10d.\n", 
+            pIso->Level, pIso->nFinNeg, pIso->FaninSig, pIso->FanoutSig );
+    }
+*/
+    // add to the hash table
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+        if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) )
+            continue;
+        pIso = p->pObjs + i;
+        Iso_ObjHashAdd( p, pIso );
+    }
+    // derive classes for the first time
+    Iso_ManCollectClasses( p );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates adjacency lists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Iso_ManAssignAdjacency( Iso_Man_t * p )
+{
+    int fUseXor = 0;
+    Iso_Obj_t * pIso, * pIsoF;
+    Aig_Obj_t * pObj, * pObjLi;
+    int i;
+
+    // create TFI signatures
+    Aig_ManForEachObj( p->pAig, pObj, i )
+    {
+        pIso = p->pObjs + i;
+        pIso->FaninSig = 0;
+        pIso->FanoutSig = 0;
+
+        if ( Aig_ObjIsCo(pObj) )
+            continue;
+        if ( fUseXor )
+        {
+            if ( Aig_ObjIsNode(pObj) )
+            {
+                pIsoF = p->pObjs + Aig_ObjFaninId0(pObj);
+                pIso->FaninSig ^= pIsoF->FaninSig;
+                if ( pIsoF->Id )
+                    pIso->FaninSig ^= s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK];
+
+                pIsoF = p->pObjs + Aig_ObjFaninId1(pObj);
+                pIso->FaninSig ^= pIsoF->FaninSig;
+                if ( pIsoF->Id )
+                    pIso->FaninSig ^= s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC1(pObj)) & ISO_MASK];
+            }
+        }
+        else
+        {
+            if ( Aig_ObjIsNode(pObj) )
+            {
+                pIsoF = p->pObjs + Aig_ObjFaninId0(pObj);
+                pIso->FaninSig += pIsoF->FaninSig;
+                if ( pIsoF->Id )
+                    pIso->FaninSig += pIsoF->Id * s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK];
+
+                pIsoF = p->pObjs + Aig_ObjFaninId1(pObj);
+                pIso->FaninSig += pIsoF->FaninSig;
+                if ( pIsoF->Id )
+                    pIso->FaninSig += pIsoF->Id * s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC1(pObj)) & ISO_MASK];
+            }
+        }
+    }
+    // create TFO signatures
+    Aig_ManForEachObjReverse( p->pAig, pObj, i )
+    {
+        if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) )
+            continue;
+        pIso = p->pObjs + i;
+        assert( !Aig_ObjIsCo(pObj) || pIso->Id == 0 );
+        if ( fUseXor )
+        {
+            if ( Aig_ObjIsNode(pObj) )
+            {
+                pIsoF = p->pObjs + Aig_ObjFaninId0(pObj);
+                pIsoF->FanoutSig ^= pIso->FanoutSig;
+                if ( pIso->Id )
+                    pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK];
+
+                pIsoF = p->pObjs + Aig_ObjFaninId1(pObj);
+                pIsoF->FanoutSig ^= pIso->FanoutSig;
+                if ( pIso->Id )
+                    pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC1(pObj)) & ISO_MASK];
+            }
+            else if ( Aig_ObjIsCo(pObj) )
+            {
+                pIsoF = p->pObjs + Aig_ObjFaninId0(pObj);
+                pIsoF->FanoutSig ^= pIso->FanoutSig;
+                if ( pIso->Id )
+                    pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK];
+            }
+        }
+        else
+        {
+            if ( Aig_ObjIsNode(pObj) )
+            {
+                pIsoF = p->pObjs + Aig_ObjFaninId0(pObj);
+                pIsoF->FanoutSig += pIso->FanoutSig;
+                if ( pIso->Id )
+                    pIsoF->FanoutSig += pIso->Id * s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK];
+
+                pIsoF = p->pObjs + Aig_ObjFaninId1(pObj);
+                pIsoF->FanoutSig += pIso->FanoutSig;
+                if ( pIso->Id )
+                    pIsoF->FanoutSig += pIso->Id * s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC1(pObj)) & ISO_MASK];
+            }
+            else if ( Aig_ObjIsCo(pObj) )
+            {
+                pIsoF = p->pObjs + Aig_ObjFaninId0(pObj);
+                pIsoF->FanoutSig += pIso->FanoutSig;
+                if ( pIso->Id )
+                    pIsoF->FanoutSig += pIso->Id * s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK];
+            }
+        }
+    }
+
+    // consider flops
+    Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObj, i )
+    {
+        if ( Aig_ObjFaninId0(pObjLi) == 0 ) // ignore constant!
+            continue;
+        pIso  = Iso_ManObj( p, Aig_ObjId(pObj) );
+        pIsoF = Iso_ManObj( p, Aig_ObjFaninId0(pObjLi) );
+        assert( pIso->FaninSig == 0 );
+//        assert( pIsoF->FanoutSig == 0 );
+
+        if ( fUseXor )
+        {
+            pIso->FaninSig = pIsoF->FaninSig;
+            if ( pIsoF->Id )
+                pIso->FaninSig ^= s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC0(pObjLi)) & ISO_MASK];
+
+            pIsoF->FanoutSig += pIso->FanoutSig;
+            if ( pIso->Id )
+                pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObjLi)) & ISO_MASK];
+        }
+        else
+        {
+            pIso->FaninSig = pIsoF->FaninSig;
+            if ( pIsoF->Id )
+                pIso->FaninSig += pIsoF->Id * s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC0(pObjLi)) & ISO_MASK];
+
+            pIsoF->FanoutSig += pIso->FanoutSig;
+            if ( pIso->Id )
+                pIsoF->FanoutSig += pIso->Id * s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObjLi)) & ISO_MASK];
+        }
+    }
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Iso_ManPrintClasseSizes( Iso_Man_t * p )
+{
+    Iso_Obj_t * pIso, * pTemp;
+    int i, Counter;
+    Vec_PtrForEachEntry( Iso_Obj_t *, p->vClasses, pIso, i )
+    {
+        Counter = 0;
+        for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) )
+            Counter++;
+        printf( "%d ", Counter );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Iso_ManPrintClasses( Iso_Man_t * p, int fVerbose, int fVeryVerbose )
+{
+    int fOnlyCis = 0;
+    Iso_Obj_t * pIso, * pTemp;
+    int i;
+
+    // count unique objects
+    if ( fVerbose )
+        printf( "Total objects =%7d.  Entries =%7d.  Classes =%7d.  Singles =%7d.\n", 
+            p->nObjs, p->nEntries, p->nClasses, p->nSingles );
+
+    if ( !fVeryVerbose )
+        return;
+
+    printf( "Non-trivial classes:\n" );
+    Vec_PtrForEachEntry( Iso_Obj_t *, p->vClasses, pIso, i )
+    {
+        if ( fOnlyCis && pIso->Level > 0 )
+            continue;
+
+        printf( "%5d : {", i );
+        for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) )
+        {
+            if ( fOnlyCis )
+                printf( " %d", Aig_ObjCioId( Iso_AigObj(p, pTemp) ) );
+            else
+            {
+                Aig_Obj_t * pObj = Iso_AigObj(p, pTemp);
+                if ( Aig_ObjIsNode(pObj) )
+                    printf( " %d{%s%d(%d),%s%d(%d)}", Iso_ObjId(p, pTemp), 
+                        Aig_ObjFaninC0(pObj)? "-": "+", Aig_ObjFaninId0(pObj), Aig_ObjLevel(Aig_ObjFanin0(pObj)), 
+                        Aig_ObjFaninC1(pObj)? "-": "+", Aig_ObjFaninId1(pObj), Aig_ObjLevel(Aig_ObjFanin1(pObj)) );
+                else
+                    printf( " %d", Iso_ObjId(p, pTemp) );
+            }
+            printf( "(%d)", pTemp->Level );
+        }        
+        printf( " }\n" );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Iso_ManRehashClassNodes( Iso_Man_t * p )
+{
+    Iso_Obj_t * pIso, * pTemp;
+    int i;
+    // collect nodes
+    Vec_PtrClear( p->vTemp1 );
+    Vec_PtrClear( p->vTemp2 );
+    Vec_PtrForEachEntry( Iso_Obj_t *, p->vClasses, pIso, i )
+    {
+        for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) )
+            if ( pTemp->Id == 0 )
+                Vec_PtrPush( p->vTemp1, pTemp );
+            else
+                Vec_PtrPush( p->vTemp2, pTemp );
+    }
+    // clean and add nodes
+    p->nClasses = 0;       // total number of classes
+    p->nEntries = 0;       // total number of entries
+    p->nSingles = 0;       // total number of singletons
+    memset( p->pBins, 0, sizeof(int) * p->nBins );
+    Vec_PtrForEachEntry( Iso_Obj_t *, p->vTemp1, pTemp, i )
+    {
+        assert( pTemp->Id == 0 );
+        pTemp->iClass = pTemp->iNext = 0;
+        Iso_ObjHashAdd( p, pTemp );
+    }
+    Vec_PtrForEachEntry( Iso_Obj_t *, p->vTemp2, pTemp, i )
+    {
+        assert( pTemp->Id != 0 );
+        pTemp->iClass = pTemp->iNext = 0;
+    }
+    // collect new classes
+    Iso_ManCollectClasses( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find nodes with the min number of edges.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Iso_Obj_t * Iso_ManFindBestObj( Iso_Man_t * p, Iso_Obj_t * pIso )
+{
+    Iso_Obj_t * pTemp, * pBest = NULL;
+    int nNodesBest = -1, nNodes;
+    int nEdgesBest = -1, nEdges;
+    assert( pIso->Id == 0 );
+    if ( pIso->Level == 0 )
+        return pIso;
+    for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) )
+    {
+        assert( pTemp->Id == 0 );
+        Iso_ManObjCount( p->pAig, Iso_AigObj(p, pTemp), &nNodes, &nEdges );
+//        printf( "%d,%d ", nNodes, nEdges );
+        if ( nNodesBest < nNodes || (nNodesBest == nNodes && nEdgesBest < nEdges) )
+        {
+            nNodesBest = nNodes;
+            nEdgesBest = nEdges;
+            pBest = pTemp;
+        }
+    }
+//    printf( "\n" );
+    return pBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find nodes with the min number of edges.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Iso_ManBreakTies( Iso_Man_t * p, int fVerbose )
+{
+    int fUseOneBest = 0;
+    Iso_Obj_t * pIso, * pTemp;
+    int i, LevelStart = 0;
+    pIso = (Iso_Obj_t *)Vec_PtrEntry( p->vClasses, 0 );
+    LevelStart = pIso->Level;
+    if ( fVerbose )
+        printf( "Best level %d\n", LevelStart ); 
+    Vec_PtrForEachEntry( Iso_Obj_t *, p->vClasses, pIso, i )
+    {
+        if ( (int)pIso->Level < LevelStart )
+            break;
+        if ( !fUseOneBest )
+        {
+            for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) )
+            {
+                assert( pTemp->Id ==  0 );
+                pTemp->Id = p->nObjIds++;
+            }
+            continue;
+        }
+        if ( pIso->Level == 0 )//&& pIso->nFoutPos + pIso->nFoutNeg == 0 )
+        {
+            for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) )
+                pTemp->Id = p->nObjIds++;
+            continue;
+        }
+        pIso = Iso_ManFindBestObj( p, pIso );
+        pIso->Id = p->nObjIds++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finalizes unification of combinational outputs.]
+
+  Description [Assigns IDs to the unclassified CIs in the order of obj IDs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Iso_ManFinalize( Iso_Man_t * p )
+{
+    Vec_Int_t * vRes;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( p->nClasses == 0 );
+    assert( Vec_PtrSize(p->vClasses) == 0 );
+    // set canonical numbers
+    Aig_ManForEachObj( p->pAig, pObj, i )
+    {
+        if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) )
+        {
+            pObj->iData = -1;
+            continue;
+        }
+        pObj->iData = Iso_ManObj(p, Aig_ObjId(pObj))->Id;
+        assert( pObj->iData > 0 );
+    }
+    Aig_ManConst1(p->pAig)->iData = 0;
+    // assign unique IDs to the CIs
+    Vec_PtrClear( p->vTemp1 );
+    Vec_PtrClear( p->vTemp2 );
+    Aig_ManForEachCi( p->pAig, pObj, i )
+    {
+        assert( pObj->iData > 0 );
+        if ( Aig_ObjCioId(pObj) >= Aig_ManCiNum(p->pAig) - Aig_ManRegNum(p->pAig) ) // flop
+            Vec_PtrPush( p->vTemp2, pObj );
+        else // PI
+            Vec_PtrPush( p->vTemp1, pObj );
+    }
+    // sort CIs by their IDs
+    Vec_PtrSort( p->vTemp1, (int (*)(void))Iso_ObjCompareByData );
+    Vec_PtrSort( p->vTemp2, (int (*)(void))Iso_ObjCompareByData );
+    // create the result
+    vRes = Vec_IntAlloc( Aig_ManCiNum(p->pAig) );
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vTemp1, pObj, i )
+        Vec_IntPush( vRes, Aig_ObjCioId(pObj) );
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vTemp2, pObj, i )
+        Vec_IntPush( vRes, Aig_ObjCioId(pObj) );
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find nodes with the min number of edges.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Iso_ManDumpOneClass( Iso_Man_t * p )
+{
+    Vec_Ptr_t * vNodes = Vec_PtrAlloc( 100 );
+    Iso_Obj_t * pIso, * pTemp;
+    Aig_Man_t * pNew = NULL;
+    assert( p->nClasses > 0 );
+    pIso = (Iso_Obj_t *)Vec_PtrEntry( p->vClasses, 0 );
+    assert( pIso->Id == 0 );
+    for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) )
+    {
+        assert( pTemp->Id == 0 );
+        Vec_PtrPush( vNodes, Iso_AigObj(p, pTemp) );
+    }
+    pNew = Aig_ManDupNodes( p->pAig, vNodes );
+    Vec_PtrFree( vNodes );
+    Aig_ManShow( pNew, 0, NULL ); 
+    Aig_ManStopP( &pNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds canonical permutation of CIs and assigns unique IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManFindIsoPerm( Aig_Man_t * pAig, int fVerbose )
+{
+    int fVeryVerbose = 0;
+    Vec_Int_t * vRes;
+    Iso_Man_t * p;
+    abctime clk = Abc_Clock(), clk2 = Abc_Clock();
+    p = Iso_ManCreate( pAig );
+    p->timeFout += Abc_Clock() - clk;
+    Iso_ManPrintClasses( p, fVerbose, fVeryVerbose );
+    while ( p->nClasses )
+    {
+        // assign adjacency to classes
+        clk = Abc_Clock();
+        Iso_ManAssignAdjacency( p );
+        p->timeFout += Abc_Clock() - clk;
+        // rehash the class nodes
+        clk = Abc_Clock();
+        Iso_ManRehashClassNodes( p );
+        p->timeHash += Abc_Clock() - clk;
+        Iso_ManPrintClasses( p, fVerbose, fVeryVerbose );
+        // force refinement
+        while ( p->nSingles == 0 && p->nClasses )
+        {
+//            Iso_ManPrintClasseSizes( p );
+            // assign IDs to the topmost level of classes
+            Iso_ManBreakTies( p, fVerbose );
+            // assign adjacency to classes
+            clk = Abc_Clock();
+            Iso_ManAssignAdjacency( p );
+            p->timeFout += Abc_Clock() - clk;
+            // rehash the class nodes
+            clk = Abc_Clock();
+            Iso_ManRehashClassNodes( p );
+            p->timeHash += Abc_Clock() - clk;
+            Iso_ManPrintClasses( p, fVerbose, fVeryVerbose );
+        }
+    }
+    p->timeTotal = Abc_Clock() - clk2;
+//    printf( "IDs assigned = %d.  Objects = %d.\n", p->nObjIds, 1+Aig_ManCiNum(p->pAig)+Aig_ManNodeNum(p->pAig) );
+    assert( p->nObjIds == 1+Aig_ManCiNum(p->pAig)+Aig_ManNodeNum(p->pAig) );
+//    if ( p->nClasses )
+//        Iso_ManDumpOneClass( p );
+    vRes = Iso_ManFinalize( p );
+    Iso_ManStop( p, fVerbose );
+    return vRes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigMiter.c b/abc-build/src/aig/saig/saigMiter.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigMiter.c
@@ -0,0 +1,1317 @@
+/**CFile****************************************************************
+
+  FileName    [saigMiter.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Computes sequential miter of two sequential AIGs.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigMiter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+#include "proof/fra/fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+ 
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the status of the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Sec_MtrStatus_t Sec_MiterStatus( Aig_Man_t * p )
+{
+    Sec_MtrStatus_t Status;
+    Aig_Obj_t * pObj, * pChild;
+    int i;
+    memset( &Status, 0, sizeof(Sec_MtrStatus_t) );
+    Status.iOut = -1;
+    Status.nInputs  = Saig_ManPiNum( p );
+    Status.nNodes   = Aig_ManNodeNum( p );
+    Status.nOutputs = Saig_ManPoNum(p);
+    Saig_ManForEachPo( p, pObj, i )
+    {
+        pChild = Aig_ObjChild0(pObj);
+        // check if the output is constant 0
+        if ( pChild == Aig_ManConst0(p) )
+            Status.nUnsat++;
+        // check if the output is constant 1
+        else if ( pChild == Aig_ManConst1(p) )
+        {
+            Status.nSat++;
+            if ( Status.iOut == -1 )
+                Status.iOut = i;
+        }
+        // check if the output is a primary input
+        else if ( Saig_ObjIsPi(p, Aig_Regular(pChild)) )
+        {
+            Status.nSat++;
+            if ( Status.iOut == -1 )
+                Status.iOut = i;
+        }
+    // check if the output is 1 for the 0000 pattern
+        else if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) )
+        {
+            Status.nSat++;
+            if ( Status.iOut == -1 )
+                Status.iOut = i;
+        }
+        else
+            Status.nUndec++;
+    }
+    return Status;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates sequential miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManCreateMiter( Aig_Man_t * p0, Aig_Man_t * p1, int Oper )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( Saig_ManRegNum(p0) > 0 || Saig_ManRegNum(p1) > 0 );
+    assert( Saig_ManPiNum(p0) == Saig_ManPiNum(p1) );
+    assert( Saig_ManPoNum(p0) == Saig_ManPoNum(p1) );
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p0) + Aig_ManObjNumMax(p1) );
+    pNew->pName = Abc_UtilStrsav( "miter" );
+    Aig_ManCleanData( p0 );
+    Aig_ManCleanData( p1 );
+    // map constant nodes
+    Aig_ManConst1(p0)->pData = Aig_ManConst1(pNew);
+    Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew);
+    // map primary inputs
+    Saig_ManForEachPi( p0, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    Saig_ManForEachPi( p1, pObj, i )
+        pObj->pData = Aig_ManCi( pNew, i );
+    // map register outputs
+    Saig_ManForEachLo( p0, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    Saig_ManForEachLo( p1, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    // map internal nodes
+    Aig_ManForEachNode( p0, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    Aig_ManForEachNode( p1, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // create primary outputs
+    Saig_ManForEachPo( p0, pObj, i )
+    {
+        if ( Oper == 0 ) // XOR
+            pObj = Aig_Exor( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild0Copy(Aig_ManCo(p1,i)) );
+        else if ( Oper == 1 ) // implication is PO(p0) -> PO(p1)  ...  complement is PO(p0) & !PO(p1) 
+            pObj = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_Not(Aig_ObjChild0Copy(Aig_ManCo(p1,i))) );
+        else
+            assert( 0 );
+        Aig_ObjCreateCo( pNew, pObj );
+    }
+    // create register inputs
+    Saig_ManForEachLi( p0, pObj, i )
+        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    Saig_ManForEachLi( p1, pObj, i )
+        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    // cleanup
+    Aig_ManSetRegNum( pNew, Saig_ManRegNum(p0) + Saig_ManRegNum(p1) );
+//    Aig_ManCleanup( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates combinational miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManCreateMiterComb( Aig_Man_t * p0, Aig_Man_t * p1, int Oper )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( Aig_ManCiNum(p0) == Aig_ManCiNum(p1) );
+    assert( Aig_ManCoNum(p0) == Aig_ManCoNum(p1) );
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p0) + Aig_ManObjNumMax(p1) );
+    pNew->pName = Abc_UtilStrsav( "miter" );
+    // map constant nodes
+    Aig_ManConst1(p0)->pData = Aig_ManConst1(pNew);
+    Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew);
+    // map primary inputs and register outputs
+    Aig_ManForEachCi( p0, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    Aig_ManForEachCi( p1, pObj, i )
+        pObj->pData = Aig_ManCi( pNew, i );
+    // map internal nodes
+    Aig_ManForEachNode( p0, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    Aig_ManForEachNode( p1, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // create primary outputs
+    Aig_ManForEachCo( p0, pObj, i )
+    {
+        if ( Oper == 0 ) // XOR
+            pObj = Aig_Exor( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild0Copy(Aig_ManCo(p1,i)) );
+        else if ( Oper == 1 ) // implication is PO(p0) -> PO(p1)  ...  complement is PO(p0) & !PO(p1) 
+            pObj = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_Not(Aig_ObjChild0Copy(Aig_ManCo(p1,i))) );
+        else
+            assert( 0 );
+        Aig_ObjCreateCo( pNew, pObj );
+    }
+    // cleanup
+    Aig_ManSetRegNum( pNew, 0 );
+    Aig_ManCleanup( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives dual-rail AIG.]
+
+  Description [Orders nodes as follows: PIs, ANDs, POs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_AndDualRail( Aig_Man_t * pNew, Aig_Obj_t * pObj, Aig_Obj_t ** ppData, Aig_Obj_t ** ppNext )
+{
+    Aig_Obj_t * pFanin0 = Aig_ObjFanin0(pObj);
+    Aig_Obj_t * pFanin1 = Aig_ObjFanin1(pObj);
+    Aig_Obj_t * p0Data = Aig_ObjFaninC0(pObj)? pFanin0->pNext              : (Aig_Obj_t *)pFanin0->pData;
+    Aig_Obj_t * p0Next = Aig_ObjFaninC0(pObj)? (Aig_Obj_t *)pFanin0->pData : pFanin0->pNext;
+    Aig_Obj_t * p1Data = Aig_ObjFaninC1(pObj)? pFanin1->pNext              : (Aig_Obj_t *)pFanin1->pData;
+    Aig_Obj_t * p1Next = Aig_ObjFaninC1(pObj)? (Aig_Obj_t *)pFanin1->pData : pFanin1->pNext;
+    *ppData = Aig_Or( pNew, 
+        Aig_And(pNew, p0Data, Aig_Not(p0Next)),
+        Aig_And(pNew, p1Data, Aig_Not(p1Next)) );
+    *ppNext = Aig_And( pNew, 
+        Aig_And(pNew, Aig_Not(p0Data), p0Next),
+        Aig_And(pNew, Aig_Not(p1Data), p1Next) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives dual-rail AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManDualRail( Aig_Man_t * p, int fMiter )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pMiter;
+    int i;
+    Aig_ManCleanData( p );
+    Aig_ManCleanNext( p );
+    // create the new manager
+    pNew = Aig_ManStart( 4*Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // create the PIs 
+    Aig_ManConst1(p)->pData = Aig_ManConst0(pNew);
+    Aig_ManConst1(p)->pNext = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+    {
+        pObj->pData = Aig_ObjCreateCi( pNew );
+        pObj->pNext = Aig_ObjCreateCi( pNew );
+    }
+    // duplicate internal nodes
+    Aig_ManForEachNode( p, pObj, i )
+        Saig_AndDualRail( pNew, pObj, (Aig_Obj_t **)&pObj->pData, &pObj->pNext );
+    // add the POs
+    if ( fMiter )
+    {
+        pMiter = Aig_ManConst1(pNew);
+        Saig_ManForEachLo( p, pObj, i )
+        {
+            pMiter = Aig_And( pNew, pMiter, 
+                Aig_Or(pNew, (Aig_Obj_t *)pObj->pData, pObj->pNext) );
+        } 
+        Aig_ObjCreateCo( pNew, pMiter );
+        Saig_ManForEachLi( p, pObj, i )
+        {
+            if ( !Aig_ObjFaninC0(pObj) )
+            {
+                Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData );
+                Aig_ObjCreateCo( pNew, Aig_ObjFanin0(pObj)->pNext );
+            }
+            else
+            {
+                Aig_ObjCreateCo( pNew, Aig_ObjFanin0(pObj)->pNext );
+                Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData );
+            }
+        }
+    }
+    else
+    {
+        Aig_ManForEachCo( p, pObj, i )
+        {
+            if ( !Aig_ObjFaninC0(pObj) )
+            {
+                Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData );
+                Aig_ObjCreateCo( pNew, Aig_ObjFanin0(pObj)->pNext );
+            }
+            else
+            {
+                Aig_ObjCreateCo( pNew, Aig_ObjFanin0(pObj)->pNext );
+                Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData );
+            }
+        }
+    }
+    Aig_ManSetRegNum( pNew, 2*Aig_ManRegNum(p) );
+    Aig_ManCleanData( p );
+    Aig_ManCleanNext( p );
+    Aig_ManCleanup( pNew );
+    // check the resulting network
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManDupSimple(): The check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create combinational timeframes by unrolling sequential circuits.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManUnrollTwo( Aig_Man_t * pBot, Aig_Man_t * pTop, int nFrames )
+{
+    Aig_Man_t * p, * pAig;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i, f;
+//    assert( nFrames > 1 );
+    assert( Saig_ManPiNum(pBot) == Saig_ManPiNum(pTop) );
+    assert( Saig_ManPoNum(pBot) == Saig_ManPoNum(pTop) );
+    assert( Saig_ManRegNum(pBot) == Saig_ManRegNum(pTop) );
+    assert( Saig_ManRegNum(pBot) > 0 || Saig_ManRegNum(pTop) > 0 );
+    // start timeframes
+    p = Aig_ManStart( nFrames * Abc_MaxInt(Aig_ManObjNumMax(pBot), Aig_ManObjNumMax(pTop)) );
+    p->pName = Abc_UtilStrsav( "frames" );
+    // create variables for register outputs
+    pAig = pBot;
+    Saig_ManForEachLo( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( p );
+    // add timeframes
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // create PI nodes for this frame
+        Aig_ManConst1(pAig)->pData = Aig_ManConst1( p );
+        Saig_ManForEachPi( pAig, pObj, i )
+            pObj->pData = Aig_ObjCreateCi( p );
+        // add internal nodes of this frame
+        Aig_ManForEachNode( pAig, pObj, i )
+            pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+        if ( f == nFrames - 1 )
+        {
+            // create POs for this frame
+            Aig_ManForEachCo( pAig, pObj, i )
+                Aig_ObjCreateCo( p, Aig_ObjChild0Copy(pObj) );
+            break;
+        }
+        // create POs for this frame
+        Saig_ManForEachPo( pAig, pObj, i )
+            Aig_ObjCreateCo( p, Aig_ObjChild0Copy(pObj) );
+        // save register inputs
+        Saig_ManForEachLi( pAig, pObj, i )
+            pObj->pData = Aig_ObjChild0Copy(pObj);
+        // transfer to register outputs
+        Saig_ManForEachLiLo(  pAig, pObjLi, pObjLo, i )
+            pObjLo->pData = pObjLi->pData;
+        if ( f == 0 )
+        {
+            // transfer from pOld to pNew
+            Saig_ManForEachLo( pAig, pObj, i )
+                Saig_ManLo(pTop, i)->pData = pObj->pData;
+            pAig = pTop;
+        }
+    }
+    Aig_ManCleanup( p );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG while creating POs from the set.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupNodesAll( Aig_Man_t * p, Vec_Ptr_t * vSet )
+{
+    Aig_Man_t * pNew, * pCopy;
+    Aig_Obj_t * pObj;
+    int i;
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    Aig_ManForEachNode( p, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+//    Saig_ManForEachPo( p, pObj, i )
+//        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSet, pObj, i )
+        Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_Regular(pObj)->pData, Aig_IsComplement(pObj)) );
+    Saig_ManForEachLi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    Aig_ManSetRegNum( pNew, Saig_ManRegNum(p) );
+    // cleanup and return a copy
+    Aig_ManSeqCleanup( pNew );
+    pCopy = Aig_ManDupSimpleDfs( pNew );
+    Aig_ManStop( pNew );
+    return pCopy;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG while creating POs from the set.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupNodesHalf( Aig_Man_t * p, Vec_Ptr_t * vSet, int iPart )
+{
+    Aig_Man_t * pNew, * pCopy;
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManCleanData( p );
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Saig_ManForEachPi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    if ( iPart == 0 )
+    {
+        Saig_ManForEachLo( p, pObj, i )
+            if ( i < Saig_ManRegNum(p)/2 )
+                pObj->pData = Aig_ObjCreateCi( pNew );
+    }
+    else
+    {
+        Saig_ManForEachLo( p, pObj, i )
+            if ( i >= Saig_ManRegNum(p)/2 )
+                pObj->pData = Aig_ObjCreateCi( pNew );
+    }
+    Aig_ManForEachNode( p, pObj, i )
+        if ( Aig_ObjFanin0(pObj)->pData && Aig_ObjFanin1(pObj)->pData )
+            pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+//    Saig_ManForEachPo( p, pObj, i )
+//        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSet, pObj, i )
+    {
+        assert( Aig_Regular(pObj)->pData != NULL );
+        Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_Regular(pObj)->pData, Aig_IsComplement(pObj)) );
+    }
+    if ( iPart == 0 )
+    {
+        Saig_ManForEachLi( p, pObj, i )
+            if ( i < Saig_ManRegNum(p)/2 )
+                pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    }
+    else
+    {
+        Saig_ManForEachLi( p, pObj, i )
+            if ( i >= Saig_ManRegNum(p)/2 )
+                pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    }
+    Aig_ManSetRegNum( pNew, Saig_ManRegNum(p)/2 );
+    // cleanup and return a copy
+//    Aig_ManSeqCleanup( pNew );
+    Aig_ManCleanup( pNew );
+    pCopy = Aig_ManDupSimpleDfs( pNew );
+    Aig_ManStop( pNew );
+    return pCopy;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG to have constant-0 initial state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManDemiterSimple( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 )
+{
+    Vec_Ptr_t * vSet0, * vSet1;
+    Aig_Obj_t * pObj, * pFanin, * pObj0, * pObj1;
+    int i, Counter = 0;
+    assert( Saig_ManRegNum(p) % 2 == 0 );
+    vSet0 = Vec_PtrAlloc( Saig_ManPoNum(p) );
+    vSet1 = Vec_PtrAlloc( Saig_ManPoNum(p) );
+    Saig_ManForEachPo( p, pObj, i )
+    {
+        pFanin = Aig_ObjFanin0(pObj);
+        if ( Aig_ObjIsConst1( pFanin ) )
+        {
+            if ( !Aig_ObjFaninC0(pObj) )
+                printf( "The output number %d of the miter is constant 1.\n", i );
+            Counter++;
+            continue;
+        }
+        if ( !Aig_ObjIsNode(pFanin) || !Aig_ObjRecognizeExor( pFanin, &pObj0, &pObj1 ) )
+        {
+            printf( "The miter cannot be demitered.\n" );
+            Vec_PtrFree( vSet0 );
+            Vec_PtrFree( vSet1 );
+            return 0;
+        }
+        if ( Aig_ObjFaninC0(pObj) )
+            pObj0 = Aig_Not(pObj0);
+
+//        printf( "%d %d  ", Aig_Regular(pObj0)->Id, Aig_Regular(pObj1)->Id );
+        if ( Aig_Regular(pObj0)->Id < Aig_Regular(pObj1)->Id )
+        {
+            Vec_PtrPush( vSet0, pObj0 );
+            Vec_PtrPush( vSet1, pObj1 );
+        }
+        else
+        {
+            Vec_PtrPush( vSet0, pObj1 );
+            Vec_PtrPush( vSet1, pObj0 );
+        }
+    }
+//    printf( "Miter has %d constant outputs.\n", Counter );
+//    printf( "\n" );
+    if ( ppAig0 )
+    {
+        *ppAig0 = Aig_ManDupNodesHalf( p, vSet0, 0 );
+        ABC_FREE( (*ppAig0)->pName );
+        (*ppAig0)->pName = Abc_UtilStrsav( "part0" );
+    }
+    if ( ppAig1 )
+    {
+        *ppAig1 = Aig_ManDupNodesHalf( p, vSet1, 1 );
+        ABC_FREE( (*ppAig1)->pName );
+        (*ppAig1)->pName = Abc_UtilStrsav( "part1" );
+    }
+    Vec_PtrFree( vSet0 );
+    Vec_PtrFree( vSet1 );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if PO can be demitered.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManDemiterMarkPos( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManCleanMarkAB( p );
+    Saig_ManForEachLo( p, pObj, i )
+        if ( i < Saig_ManRegNum(p)/2 )
+            pObj->fMarkA = 1;
+        else
+            pObj->fMarkB = 1;
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        pObj->fMarkA = Aig_ObjFanin0(pObj)->fMarkA | Aig_ObjFanin1(pObj)->fMarkA;
+        pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB | Aig_ObjFanin1(pObj)->fMarkB;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if PO can be demitered.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManDemiterCheckPo( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t ** ppPo0, Aig_Obj_t ** ppPo1 )
+{
+    Aig_Obj_t * pFanin, * pObj0, * pObj1, * pObjR0, * pObjR1;
+    assert( Saig_ObjIsPo(p, pObj) );
+    pFanin = Aig_ObjFanin0( pObj );
+    if ( Aig_ObjIsConst1(pFanin) )
+    {
+        if ( !Aig_ObjFaninC0(pObj) )
+            return 0;
+        *ppPo0 = Aig_ManConst0(p);
+        *ppPo1 = Aig_ManConst0(p);
+        return 1;
+    }
+    if ( !Aig_ObjIsNode(pFanin) )
+        return 0;
+    if ( !Aig_ObjRecognizeExor( pFanin, &pObj0, &pObj1 ) )
+        return 0;
+    if ( Aig_ObjFaninC0(pObj) )
+        pObj0 = Aig_Not(pObj0);
+    // make sure they can reach only one
+    pObjR0 = Aig_Regular(pObj0);
+    pObjR1 = Aig_Regular(pObj1);
+    if ( (pObjR0->fMarkA && pObjR0->fMarkB) || (pObjR1->fMarkA && pObjR1->fMarkB) || 
+         (pObjR0->fMarkA && pObjR1->fMarkA) || (pObjR0->fMarkB && pObjR1->fMarkB) )
+         return 0;
+
+    if ( pObjR1->fMarkA && !pObjR0->fMarkA )
+    {
+        *ppPo0 = pObj1;
+        *ppPo1 = pObj0;
+    }
+    else if ( pObjR0->fMarkA && !pObjR1->fMarkA )
+    {
+        *ppPo0 = pObj0;
+        *ppPo1 = pObj1;
+    }
+    else
+    {
+/*
+printf( "%d", pObjR0->fMarkA );
+printf( "%d", pObjR0->fMarkB );
+printf( ":" );
+printf( "%d", pObjR1->fMarkA );
+printf( "%d", pObjR1->fMarkB );
+printf( "   " );
+*/
+        if ( Aig_Regular(pObj0)->Id < Aig_Regular(pObj1)->Id )
+        {
+            *ppPo0 = pObj0;
+            *ppPo1 = pObj1;
+        }
+        else
+        {
+            *ppPo0 = pObj1;
+            *ppPo1 = pObj0;
+        }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if AIG can be demitered.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManDemiterSimpleDiff( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 )
+{
+    Vec_Ptr_t * vSet0, * vSet1;
+    Aig_Obj_t * pObj, * pObj0, * pObj1;
+    int i;
+    if ( Aig_ManRegNum(p) == 0 || (Aig_ManRegNum(p) & 1) )
+        return 0;
+    Saig_ManDemiterMarkPos( p );
+    vSet0 = Vec_PtrAlloc( Saig_ManPoNum(p) );
+    vSet1 = Vec_PtrAlloc( Saig_ManPoNum(p) );
+    Saig_ManForEachPo( p, pObj, i )
+    {
+        if ( !Saig_ManDemiterCheckPo( p, pObj, &pObj0, &pObj1 ) )
+        {
+            Vec_PtrFree( vSet0 );
+            Vec_PtrFree( vSet1 );
+            Aig_ManCleanMarkAB( p );
+            return 0;
+        }
+        Vec_PtrPush( vSet0, pObj0 );
+        Vec_PtrPush( vSet1, pObj1 );
+    }
+    // create new AIG
+    *ppAig0 = Aig_ManDupNodesHalf( p, vSet0, 0 );
+    ABC_FREE( (*ppAig0)->pName );
+    (*ppAig0)->pName = Abc_UtilStrsav( "part0" );
+    // create new AIGs
+    *ppAig1 = Aig_ManDupNodesHalf( p, vSet1, 1 );
+    ABC_FREE( (*ppAig1)->pName );
+    (*ppAig1)->pName = Abc_UtilStrsav( "part1" );
+    // cleanup
+    Vec_PtrFree( vSet0 );
+    Vec_PtrFree( vSet1 );
+    Aig_ManCleanMarkAB( p );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if AIG can be demitered.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManDemiterDual( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 )
+{
+    Aig_Man_t * pTemp;
+    Aig_Obj_t * pObj;
+    int i, k;
+
+    if ( p->pFanData )
+        Aig_ManFanoutStop( p );
+
+    k = 0;
+    pTemp = Aig_ManDupSimple( p );
+    Saig_ManForEachPo( pTemp, pObj, i )
+    {
+        if ( i & 1 )
+            Aig_ObjDeletePo( pTemp, pObj );
+        else
+            Vec_PtrWriteEntry( pTemp->vCos, k++, pObj );
+    }
+    Saig_ManForEachLi( pTemp, pObj, i )
+        Vec_PtrWriteEntry( pTemp->vCos, k++, pObj );
+    Vec_PtrShrink( pTemp->vCos, k );
+    pTemp->nTruePos = k - Saig_ManRegNum(pTemp);
+    Aig_ManSeqCleanup( pTemp );
+    *ppAig0 = Aig_ManDupSimple( pTemp );
+    Aig_ManStop( pTemp );
+
+    k = 0;
+    pTemp = Aig_ManDupSimple( p );
+    Saig_ManForEachPo( pTemp, pObj, i )
+    {
+        if ( i & 1 )
+            Vec_PtrWriteEntry( pTemp->vCos, k++, pObj );
+        else
+            Aig_ObjDeletePo( pTemp, pObj );
+    }
+    Saig_ManForEachLi( pTemp, pObj, i )
+        Vec_PtrWriteEntry( pTemp->vCos, k++, pObj );
+    Vec_PtrShrink( pTemp->vCos, k );
+    pTemp->nTruePos = k - Saig_ManRegNum(pTemp);
+    Aig_ManSeqCleanup( pTemp );
+    *ppAig1 = Aig_ManDupSimple( pTemp );
+    Aig_ManStop( pTemp );
+
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG to have constant-0 initial state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManDemiterSimpleDiff_old( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 )
+{
+    Vec_Ptr_t * vSet0, * vSet1;
+    Aig_Obj_t * pObj, * pFanin, * pObj0, * pObj1;
+    int i, Counter = 0;
+//    assert( Saig_ManRegNum(p) % 2 == 0 );
+    vSet0 = Vec_PtrAlloc( Saig_ManPoNum(p) );
+    vSet1 = Vec_PtrAlloc( Saig_ManPoNum(p) );
+    Saig_ManForEachPo( p, pObj, i )
+    {
+        pFanin = Aig_ObjFanin0(pObj);
+        if ( Aig_ObjIsConst1( pFanin ) )
+        {
+            if ( !Aig_ObjFaninC0(pObj) )
+                printf( "The output number %d of the miter is constant 1.\n", i );
+            Counter++;
+            continue;
+        } 
+        if ( !Aig_ObjIsNode(pFanin) || !Aig_ObjRecognizeExor( pFanin, &pObj0, &pObj1 ) )
+        {
+/*
+            printf( "The miter cannot be demitered.\n" );
+            Vec_PtrFree( vSet0 );
+            Vec_PtrFree( vSet1 );
+            return 0;
+*/
+            printf( "The output number %d cannot be demitered.\n", i );
+            continue;
+        }
+        if ( Aig_ObjFaninC0(pObj) )
+            pObj0 = Aig_Not(pObj0);
+
+//        printf( "%d %d  ", Aig_Regular(pObj0)->Id, Aig_Regular(pObj1)->Id );
+        if ( Aig_Regular(pObj0)->Id < Aig_Regular(pObj1)->Id )
+        {
+            Vec_PtrPush( vSet0, pObj0 );
+            Vec_PtrPush( vSet1, pObj1 );
+        }
+        else
+        {
+            Vec_PtrPush( vSet0, pObj1 );
+            Vec_PtrPush( vSet1, pObj0 );
+        }
+    }
+//    printf( "Miter has %d constant outputs.\n", Counter );
+//    printf( "\n" );
+    if ( ppAig0 )
+    {
+        *ppAig0 = Aig_ManDupNodesAll( p, vSet0 );
+        ABC_FREE( (*ppAig0)->pName );
+        (*ppAig0)->pName = Abc_UtilStrsav( "part0" );
+    }
+    if ( ppAig1 )
+    {
+        *ppAig1 = Aig_ManDupNodesAll( p, vSet1 );
+        ABC_FREE( (*ppAig1)->pName );
+        (*ppAig1)->pName = Abc_UtilStrsav( "part1" );
+    }
+    Vec_PtrFree( vSet0 );
+    Vec_PtrFree( vSet1 );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Labels logic reachable from the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManDemiterLabel_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int Value )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Value ) 
+        pObj->fMarkB = 1;
+    else
+        pObj->fMarkA = 1;
+    if ( Saig_ObjIsPi(p, pObj) )
+        return;
+    if ( Saig_ObjIsLo(p, pObj) )
+    {
+        Saig_ManDemiterLabel_rec( p, Aig_ObjFanin0( Saig_ObjLoToLi(p, pObj) ), Value );
+        return;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    Saig_ManDemiterLabel_rec( p, Aig_ObjFanin0(pObj), Value );
+    Saig_ManDemiterLabel_rec( p, Aig_ObjFanin1(pObj), Value );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the first labeled register encountered during traversal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Saig_ManGetLabeledRegister_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pResult;
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return NULL;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Saig_ObjIsPi(p, pObj) )
+        return NULL;
+    if ( Saig_ObjIsLo(p, pObj) )
+    {
+        if ( pObj->fMarkA || pObj->fMarkB )
+            return pObj;
+        return Saig_ManGetLabeledRegister_rec( p, Aig_ObjFanin0( Saig_ObjLoToLi(p, pObj) ) );
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    pResult = Saig_ManGetLabeledRegister_rec( p, Aig_ObjFanin0(pObj) );
+    if ( pResult )
+        return pResult;
+    return Saig_ManGetLabeledRegister_rec( p, Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG to have constant-0 initial state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManDemiter( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 )
+{
+    Vec_Ptr_t * vPairs, * vSet0, * vSet1;
+    Aig_Obj_t * pObj, * pObj0, * pObj1, * pFlop0, * pFlop1;
+    int i, Counter;
+    assert( Saig_ManRegNum(p) > 0 );
+    Aig_ManSetCioIds( p );
+    // check if demitering is possible
+    vPairs = Vec_PtrAlloc( 2 * Saig_ManPoNum(p) );
+    Saig_ManForEachPo( p, pObj, i )
+    {
+        if ( !Aig_ObjRecognizeExor( Aig_ObjFanin0(pObj), &pObj0, &pObj1 ) )
+        {
+            Vec_PtrFree( vPairs );
+            return 0;
+        }
+        Vec_PtrPush( vPairs, pObj0 );
+        Vec_PtrPush( vPairs, pObj1 );
+    }
+    // start array of outputs
+    vSet0 = Vec_PtrAlloc( Saig_ManPoNum(p) );
+    vSet1 = Vec_PtrAlloc( Saig_ManPoNum(p) );
+    // get the first pair of outputs
+    pObj0 = (Aig_Obj_t *)Vec_PtrEntry( vPairs, 0 );
+    pObj1 = (Aig_Obj_t *)Vec_PtrEntry( vPairs, 1 );
+    // label registers reachable from the outputs
+    Aig_ManIncrementTravId( p );
+    Saig_ManDemiterLabel_rec( p, Aig_Regular(pObj0), 0 );
+    Vec_PtrPush( vSet0, pObj0 );
+    Aig_ManIncrementTravId( p );
+    Saig_ManDemiterLabel_rec( p, Aig_Regular(pObj1), 1 );
+    Vec_PtrPush( vSet1, pObj1 );
+    // find where each output belongs
+    for ( i = 2; i < Vec_PtrSize(vPairs); i += 2 )
+    {
+        pObj0 = (Aig_Obj_t *)Vec_PtrEntry( vPairs, i   );
+        pObj1 = (Aig_Obj_t *)Vec_PtrEntry( vPairs, i+1 );
+
+        Aig_ManIncrementTravId( p );
+        pFlop0 = Saig_ManGetLabeledRegister_rec( p, Aig_Regular(pObj0) );
+
+        Aig_ManIncrementTravId( p );
+        pFlop1 = Saig_ManGetLabeledRegister_rec( p, Aig_Regular(pObj1) );
+
+        if ( (pFlop0->fMarkA && pFlop0->fMarkB) || (pFlop1->fMarkA && pFlop1->fMarkB) || 
+             (pFlop0->fMarkA && pFlop1->fMarkA) || (pFlop0->fMarkB && pFlop1->fMarkB)  )
+            printf( "Ouput pair %4d: Difficult case...\n", i/2 );
+
+        if ( pFlop0->fMarkB )
+        {
+            Saig_ManDemiterLabel_rec( p, pObj0, 1 );
+            Vec_PtrPush( vSet0, pObj0 );
+        }
+        else // if ( pFlop0->fMarkA ) or none
+        {
+            Saig_ManDemiterLabel_rec( p, pObj0, 0 );
+            Vec_PtrPush( vSet1, pObj0 );
+        }
+
+        if ( pFlop1->fMarkB )
+        {
+            Saig_ManDemiterLabel_rec( p, pObj1, 1 );
+            Vec_PtrPush( vSet0, pObj1 );
+        }
+        else // if ( pFlop1->fMarkA ) or none
+        {
+            Saig_ManDemiterLabel_rec( p, pObj1, 0 );
+            Vec_PtrPush( vSet1, pObj1 );
+        }
+    }
+    // check if there are any flops in common
+    Counter = 0;
+    Saig_ManForEachLo( p, pObj, i )
+        if ( pObj->fMarkA && pObj->fMarkB )
+            Counter++;
+    if ( Counter > 0 )
+        printf( "The miters contains %d flops reachable from both AIGs.\n", Counter );
+
+    // produce two miters
+    if ( ppAig0 )
+    {
+        assert( 0 );
+        *ppAig0 = Aig_ManDupNodesHalf( p, vSet0, 0 ); // not ready
+        ABC_FREE( (*ppAig0)->pName );
+        (*ppAig0)->pName = Abc_UtilStrsav( "part0" );
+    }
+    if ( ppAig1 )
+    {
+        assert( 0 );
+        *ppAig1 = Aig_ManDupNodesHalf( p, vSet1, 1 ); // not ready
+        ABC_FREE( (*ppAig1)->pName );
+        (*ppAig1)->pName = Abc_UtilStrsav( "part1" );
+    }
+    Vec_PtrFree( vSet0 );
+    Vec_PtrFree( vSet1 );
+    Vec_PtrFree( vPairs );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Create specialized miter by unrolling two circuits.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManCreateMiterTwo( Aig_Man_t * pOld, Aig_Man_t * pNew, int nFrames )
+{
+    Aig_Man_t * pFrames0, * pFrames1, * pMiter;
+//    assert( Aig_ManNodeNum(pOld) <= Aig_ManNodeNum(pNew) );
+    pFrames0 = Saig_ManUnrollTwo( pOld, pOld, nFrames );
+    pFrames1 = Saig_ManUnrollTwo( pNew, pOld, nFrames );
+    pMiter = Saig_ManCreateMiterComb( pFrames0, pFrames1, 0 );
+    Aig_ManStop( pFrames0 );
+    Aig_ManStop( pFrames1 );
+    return pMiter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulates counter-example and returns the failed output number.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SecCexResimulate( Aig_Man_t * p, int * pModel, int * pnOutputs )
+{
+    Aig_Obj_t * pObj;
+    int i, RetValue = -1;
+    *pnOutputs = 0;
+    Aig_ManConst1(p)->fMarkA = 1;
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->fMarkA = pModel[i];
+    Aig_ManForEachNode( p, pObj, i )
+        pObj->fMarkA = ( Aig_ObjFanin0(pObj)->fMarkA ^ Aig_ObjFaninC0(pObj) ) & 
+                      ( Aig_ObjFanin1(pObj)->fMarkA ^ Aig_ObjFaninC1(pObj) );
+    Aig_ManForEachCo( p, pObj, i )
+        pObj->fMarkA = Aig_ObjFanin0(pObj)->fMarkA ^ Aig_ObjFaninC0(pObj);
+    Aig_ManForEachCo( p, pObj, i )
+        if ( pObj->fMarkA )
+        {
+            if ( RetValue == -1 )
+                RetValue = i;
+            (*pnOutputs)++;
+        }
+    Aig_ManCleanMarkA(p);
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces SEC to CEC for the special case of seq synthesis.]
+
+  Description [The first circuit (pPart0) should be circuit before synthesis.
+  The second circuit (pPart1) should be circuit after synthesis.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SecSpecial( Aig_Man_t * pPart0, Aig_Man_t * pPart1, int nFrames, int fVerbose )
+{
+//    extern int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose );
+    int iOut, nOuts;
+    Aig_Man_t * pMiterCec;
+    int RetValue;
+    abctime clkTotal = Abc_Clock();
+    if ( fVerbose )
+    {
+        Aig_ManPrintStats( pPart0 );
+        Aig_ManPrintStats( pPart1 );
+    }
+//    Aig_ManDumpBlif( pPart0, "file0.blif", NULL, NULL );
+//    Aig_ManDumpBlif( pPart1, "file1.blif", NULL, NULL );
+//    assert( Aig_ManNodeNum(pPart0) <= Aig_ManNodeNum(pPart1) );
+/*
+    if ( Aig_ManNodeNum(pPart0) >= Aig_ManNodeNum(pPart1) )
+    {
+        printf( "Warning: The design after synthesis is smaller!\n" );
+        printf( "This warning may indicate that the order of designs is changed.\n" );
+        printf( "The solver expects the original design as first argument and\n" );
+        printf( "the modified design as the second argument in \"absec\".\n" );
+    }
+*/
+    // create two-level miter
+    pMiterCec = Saig_ManCreateMiterTwo( pPart0, pPart1, nFrames );
+    if ( fVerbose )
+    {
+        Aig_ManPrintStats( pMiterCec );
+//        Aig_ManDumpBlif( pMiterCec, "miter01.blif", NULL, NULL );
+//        printf( "The new miter is written into file \"%s\".\n", "miter01.blif" );
+    }
+    // run CEC on this miter
+    RetValue = Fra_FraigCec( &pMiterCec, 100000, fVerbose );
+    // transfer model if given
+//    if ( pNtk2 == NULL )
+//        pNtk1->pModel = pMiterCec->pData, pMiterCec->pData = NULL;
+    // report the miter
+    if ( RetValue == 1 )
+    {
+        printf( "Networks are equivalent.   " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+    }
+    else if ( RetValue == 0 )
+    {
+        printf( "Networks are NOT EQUIVALENT.   " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+        if ( pMiterCec->pData == NULL )
+            printf( "Counter-example is not available.\n" );
+        else
+        {
+            iOut = Ssw_SecCexResimulate( pMiterCec, (int *)pMiterCec->pData, &nOuts );
+            if ( iOut == -1 )
+                printf( "Counter-example verification has failed.\n" );
+            else 
+            {
+                if ( iOut < Saig_ManPoNum(pPart0) * nFrames )
+                    printf( "Primary output %d has failed in frame %d.\n", 
+                        iOut%Saig_ManPoNum(pPart0), iOut/Saig_ManPoNum(pPart0) );
+                else
+                    printf( "Flop input %d has failed in the last frame.\n", 
+                        iOut - Saig_ManPoNum(pPart0) * nFrames );
+                printf( "The counter-example detected %d incorrect POs or flop inputs.\n", nOuts );
+            }
+        }
+    }
+    else
+    {
+        printf( "Networks are UNDECIDED.   " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+    }
+    fflush( stdout );
+    Aig_ManStop( pMiterCec );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces SEC to CEC for the special case of seq synthesis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SecSpecialMiter( Aig_Man_t * p0, Aig_Man_t * p1, int nFrames, int fVerbose )
+{
+    Aig_Man_t * pPart0, * pPart1;
+    int RetValue;
+    if ( fVerbose )
+        printf( "Performing sequential verification using combinational A/B miter.\n" );
+    // consider the case when a miter is given
+    if ( p1 == NULL )
+    {
+        if ( fVerbose )
+        {
+            Aig_ManPrintStats( p0 );
+        }
+        // demiter the miter
+        if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) )
+        {
+            printf( "Demitering has failed.\n" );
+            return -1;
+        }
+        if ( Aig_ManRegNum(pPart0) != Aig_ManRegNum(pPart1) )
+        {
+            Aig_ManStop( pPart0 );
+            Aig_ManStop( pPart1 );
+            printf( "After demitering AIGs have different number of flops. Quitting.\n" );
+            return -1;
+        }
+    }
+    else
+    {
+        pPart0 = Aig_ManDupSimple( p0 );
+        pPart1 = Aig_ManDupSimple( p1 );
+    }
+    if ( fVerbose )
+    {
+//        Aig_ManPrintStats( pPart0 );
+//        Aig_ManPrintStats( pPart1 );
+        if ( p1 == NULL )
+        {
+//        Aig_ManDumpBlif( pPart0, "part0.blif", NULL, NULL );
+//        Aig_ManDumpBlif( pPart1, "part1.blif", NULL, NULL );
+//        printf( "The result of demitering is written into files \"%s\" and \"%s\".\n", "part0.blif", "part1.blif" );
+        }
+    }
+    assert( Aig_ManRegNum(pPart0) > 0 );
+    assert( Aig_ManRegNum(pPart1) > 0 );
+    assert( Saig_ManPiNum(pPart0) == Saig_ManPiNum(pPart1) );
+    assert( Saig_ManPoNum(pPart0) == Saig_ManPoNum(pPart1) );
+    assert( Aig_ManRegNum(pPart0) == Aig_ManRegNum(pPart1) );
+    RetValue = Ssw_SecSpecial( pPart0, pPart1, nFrames, fVerbose );
+    if ( RetValue != 1 && Aig_ManNodeNum(pPart0) >= Aig_ManNodeNum(pPart1) )
+        RetValue = Ssw_SecSpecial( pPart1, pPart0, nFrames, fVerbose );
+    Aig_ManStop( pPart0 );
+    Aig_ManStop( pPart1 );
+    return RetValue;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs demitering of the network.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManDemiterNew( Aig_Man_t * pMan )
+{
+    Vec_Ptr_t * vSuper, * vSupp0, * vSupp1;
+    Aig_Obj_t * pObj, * pTemp, * pFan0, * pFan1;
+    int i, k;
+    vSuper = Vec_PtrAlloc( 100 );
+    Saig_ManForEachPo( pMan, pObj, i )
+    {
+        if ( pMan->nConstrs && i >= Saig_ManPoNum(pMan) - pMan->nConstrs )
+            break;
+        printf( "Output %3d : ", i );
+        if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) )
+        {
+            if ( !Aig_ObjFaninC0(pObj) )
+                printf( "Const1\n" );
+            else
+                printf( "Const0\n" );
+            continue;
+        }
+        if ( !Aig_ObjIsNode(Aig_ObjFanin0(pObj)) )
+        {
+            printf( "Terminal\n" );
+            continue;
+        }
+        // check AND
+        if ( !Aig_ObjFaninC0(pObj) )
+        { 
+            printf( "AND  " );
+            if ( Aig_ObjRecognizeExor(Aig_ObjFanin0(pObj), &pFan0, &pFan1) )
+                printf( " Yes" );
+            else
+                printf( " No" );
+            printf( "\n" );
+            continue;
+        }
+        // check OR
+        Aig_ObjCollectSuper( Aig_ObjFanin0(pObj), vSuper );
+        printf( "OR with %d inputs    ", Vec_PtrSize(vSuper) );
+        if ( Vec_PtrSize(vSuper) == 2 )
+        {
+            if ( Aig_ObjRecognizeExor(Aig_ObjFanin0(pObj), &pFan0, &pFan1) )
+            {
+                printf( " Yes" );
+                printf( "\n" );
+
+                vSupp0 = Aig_Support( pMan, Aig_Regular(pFan0) );
+                Vec_PtrForEachEntry( Aig_Obj_t *, vSupp0, pTemp, k )
+                    if ( Saig_ObjIsLo(pMan, pTemp) )
+                        printf( " %d", Aig_ObjCioId(pTemp) );
+                printf( "\n" );
+                Vec_PtrFree( vSupp0 );
+
+                vSupp1 = Aig_Support( pMan, Aig_Regular(pFan1) );
+                Vec_PtrForEachEntry( Aig_Obj_t *, vSupp1, pTemp, k )
+                    if ( Saig_ObjIsLo(pMan, pTemp) )
+                        printf( " %d", Aig_ObjCioId(pTemp) );
+                printf( "\n" );
+                Vec_PtrFree( vSupp1 );
+            }
+            else
+                printf( " No" );
+            printf( "\n" );
+            continue;
+        }
+/*
+        Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pTemp, k )
+            if ( Aig_ObjRecognizeExor(Aig_Regular(pTemp), &pFan0, &pFan1) )
+            {
+                printf( " Yes" );
+                if ( Aig_IsComplement(pTemp) )
+                    pFan0 = Aig_Not(pFan0);
+            }
+            else
+                printf( " No" );
+*/
+        printf( "\n" );
+    }
+    Vec_PtrFree( vSuper );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigOutDec.c b/abc-build/src/aig/saig/saigOutDec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigOutDec.c
@@ -0,0 +1,205 @@
+/**CFile****************************************************************
+
+  FileName    [saigOutDec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Output cone decomposition.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigOutDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs decomposition of the property output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_ManFindPrimes( Aig_Man_t * pAig, int nLits, int fVerbose )
+{
+    Cnf_Dat_t * pCnf;
+    sat_solver * pSat;
+    Aig_Obj_t * pObj0, * pObj1, * pRoot, * pMiter;
+    Vec_Ptr_t * vPrimes, * vNodes;
+    Vec_Int_t * vCube, * vMarks;
+    int i0, i1, m, RetValue, Lits[10];
+    int fCompl0, fCompl1, nNodes1, nNodes2;
+    assert( nLits == 1 || nLits == 2 );
+    assert( nLits < 10 );
+
+    // create SAT solver
+    pCnf = Cnf_DeriveSimple( pAig, Aig_ManCoNum(pAig) ); 
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+
+    // collect nodes in the property output cone
+    pMiter = Aig_ManCo( pAig, 0 );
+    pRoot  = Aig_ObjFanin0( pMiter );
+    vNodes = Aig_ManDfsNodes( pAig, &pRoot, 1 );
+    // sort nodes by level and remove the last few
+ 
+    // try single nodes
+    vPrimes = Vec_PtrAlloc( 100 );
+    // create assumptions
+    vMarks = Vec_IntStart( Vec_PtrSize(vNodes) );
+    Lits[0] = toLitCond( pCnf->pVarNums[Aig_ObjId(pMiter)], 1 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj0, i0 )
+    if ( pObj0 != pRoot )
+    {
+        // create assumptions
+        Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj0)], pObj0->fPhase );
+        // solve the problem
+        RetValue = sat_solver_solve( pSat, Lits, Lits+2, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        if ( RetValue == l_False )
+        {
+            vCube = Vec_IntAlloc( 1 );
+            Vec_IntPush( vCube, toLitCond(Aig_ObjId(pObj0), pObj0->fPhase) );
+            Vec_PtrPush( vPrimes, vCube );
+            if ( fVerbose )
+            printf( "Adding prime %d%c\n", Aig_ObjId(pObj0),  pObj0->fPhase?'-':'+' );
+            Vec_IntWriteEntry( vMarks, i0, 1 );
+        }
+    }
+    nNodes1 = Vec_PtrSize(vPrimes);
+    if ( nLits > 1 )
+    {
+        // try adding second literal
+        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj0, i0 )
+        if ( pObj0 != pRoot )
+        Vec_PtrForEachEntryStart( Aig_Obj_t *, vNodes, pObj1, i1, i0+1 )
+        if ( pObj1 != pRoot )
+        {
+            if ( Vec_IntEntry(vMarks,i0) || Vec_IntEntry(vMarks,i1) )
+                continue;
+            for ( m = 0; m < 3; m++ )
+            {
+                fCompl0 =  m & 1;
+                fCompl1 = (m >> 1) & 1;
+                // create assumptions
+                Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj0)], fCompl0 ^ pObj0->fPhase );
+                Lits[2] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj1)], fCompl1 ^ pObj1->fPhase );
+                // solve the problem
+                RetValue = sat_solver_solve( pSat, Lits, Lits+3, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+                if ( RetValue == l_False )
+                {
+                    vCube = Vec_IntAlloc( 2 );
+                    Vec_IntPush( vCube, toLitCond(Aig_ObjId(pObj0), fCompl0 ^ pObj0->fPhase) );
+                    Vec_IntPush( vCube, toLitCond(Aig_ObjId(pObj1), fCompl1 ^ pObj1->fPhase) );
+                    Vec_PtrPush( vPrimes, vCube );
+                    if ( fVerbose )
+                    printf( "Adding prime %d%c %d%c\n", 
+                        Aig_ObjId(pObj0), (fCompl0 ^ pObj0->fPhase)?'-':'+', 
+                        Aig_ObjId(pObj1), (fCompl1 ^ pObj1->fPhase)?'-':'+' );
+                    break;
+                }
+            }
+        }
+    }
+    nNodes2 = Vec_PtrSize(vPrimes) - nNodes1;
+
+    printf( "Property cone size = %6d    1-lit primes = %5d    2-lit primes = %5d\n", 
+        Vec_PtrSize(vNodes), nNodes1, nNodes2 );
+
+    // clean up
+    sat_solver_delete( pSat );
+    Cnf_DataFree( pCnf );
+    Vec_PtrFree( vNodes );
+    Vec_IntFree( vMarks );
+    return vPrimes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs decomposition of the property output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManDecPropertyOutput( Aig_Man_t * pAig, int nLits, int fVerbose )
+{
+    Aig_Man_t * pAigNew = NULL;
+    Aig_Obj_t * pObj, * pMiter;
+    Vec_Ptr_t * vPrimes;
+    Vec_Int_t * vCube;
+    int i, k, Lit;
+
+    // compute primes of the comb output function
+    vPrimes = Saig_ManFindPrimes( pAig, nLits, fVerbose );
+
+    // start the new manager
+    pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) );
+    pAigNew->pName = Abc_UtilStrsav( pAig->pName );
+    pAigNew->nConstrs = pAig->nConstrs;
+    // map the constant node
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew );
+    // create variables for PIs
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pAigNew );
+    // add internal nodes of this frame
+    Aig_ManForEachNode( pAig, pObj, i )
+        pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // create original POs of the circuit
+    Saig_ManForEachPo( pAig, pObj, i )
+        Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) );
+    // create prime POs of the circuit
+    if ( vPrimes )
+    Vec_PtrForEachEntry( Vec_Int_t *, vPrimes, vCube, k )
+    {
+        pMiter = Aig_ManConst1( pAigNew );
+        Vec_IntForEachEntry( vCube, Lit, i )
+        {
+            pObj = Aig_NotCond( Aig_ObjCopy(Aig_ManObj(pAig, Abc_Lit2Var(Lit))), Abc_LitIsCompl(Lit) );
+            pMiter = Aig_And( pAigNew, pMiter, pObj );
+        }
+        Aig_ObjCreateCo( pAigNew, pMiter );
+    }
+    // transfer to register outputs
+    Saig_ManForEachLi( pAig, pObj, i )
+        Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) );
+    Aig_ManCleanup( pAigNew );
+    Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) );
+
+    Vec_VecFreeP( (Vec_Vec_t **)&vPrimes );
+    return pAigNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigPhase.c b/abc-build/src/aig/saig/saigPhase.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigPhase.c
@@ -0,0 +1,1081 @@
+/**CFile****************************************************************
+
+  FileName    [saigPhase.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Automated phase abstraction.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigPhase.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+    The algorithm is described in the paper: Per Bjesse and Jim Kukula,
+    "Automatic Phase Abstraction for Formal Verification", ICCAD 2005
+    http://www.iccad.com/data2/iccad/iccad_05acceptedpapers.nsf/9cfb1ebaaf59043587256a6a00031f78/1701ecf34b149e958725702f00708828?OpenDocument
+*/
+
+// the maximum number of cycles of termiry simulation
+#define TSIM_MAX_ROUNDS    10000
+#define TSIM_ONE_SERIES     3000
+
+#define SAIG_XVS0   1
+#define SAIG_XVS1   2
+#define SAIG_XVSX   3
+
+static inline int  Saig_XsimConvertValue( int v )  { return v == 0? SAIG_XVS0 : (v == 1? SAIG_XVS1 : (v == 2? SAIG_XVSX : -1));  }
+
+static inline void Saig_ObjSetXsim( Aig_Obj_t * pObj, int Value )  { pObj->nCuts = Value;  }
+static inline int  Saig_ObjGetXsim( Aig_Obj_t * pObj )             { return pObj->nCuts;   }
+static inline int  Saig_XsimInv( int Value )   
+{ 
+    if ( Value == SAIG_XVS0 )
+        return SAIG_XVS1;
+    if ( Value == SAIG_XVS1 )
+        return SAIG_XVS0;
+    assert( Value == SAIG_XVSX );       
+    return SAIG_XVSX;
+}
+static inline int  Saig_XsimAnd( int Value0, int Value1 )   
+{ 
+    if ( Value0 == SAIG_XVS0 || Value1 == SAIG_XVS0 )
+        return SAIG_XVS0;
+    if ( Value0 == SAIG_XVSX || Value1 == SAIG_XVSX )
+        return SAIG_XVSX;
+    assert( Value0 == SAIG_XVS1 && Value1 == SAIG_XVS1 );
+    return SAIG_XVS1;
+}
+static inline int  Saig_XsimRand2()   
+{
+    return (Aig_ManRandom(0) & 1) ? SAIG_XVS1 : SAIG_XVS0;
+}
+static inline int  Saig_XsimRand3()   
+{
+    int RetValue;
+    do { 
+        RetValue = Aig_ManRandom(0) & 3; 
+    } while ( RetValue == 0 );
+    return RetValue;
+}
+static inline int  Saig_ObjGetXsimFanin0( Aig_Obj_t * pObj )       
+{ 
+    int RetValue;
+    RetValue = Saig_ObjGetXsim(Aig_ObjFanin0(pObj));
+    return Aig_ObjFaninC0(pObj)? Saig_XsimInv(RetValue) : RetValue;
+}
+static inline int  Saig_ObjGetXsimFanin1( Aig_Obj_t * pObj )       
+{ 
+    int RetValue;
+    RetValue = Saig_ObjGetXsim(Aig_ObjFanin1(pObj));
+    return Aig_ObjFaninC1(pObj)? Saig_XsimInv(RetValue) : RetValue;
+}
+static inline void Saig_XsimPrint( FILE * pFile, int Value )   
+{ 
+    if ( Value == SAIG_XVS0 )
+    {
+        fprintf( pFile, "0" );
+        return;
+    }
+    if ( Value == SAIG_XVS1 )
+    {
+        fprintf( pFile, "1" );
+        return;
+    }
+    assert( Value == SAIG_XVSX );       
+    fprintf( pFile, "x" );
+}
+
+// simulation manager
+typedef struct Saig_Tsim_t_ Saig_Tsim_t;
+struct Saig_Tsim_t_
+{
+    Aig_Man_t *      pAig;              // the original AIG manager
+    int              nWords;            // the number of words in the states
+    // ternary state representation
+    Vec_Ptr_t *      vStates;           // the collection of ternary states
+    Aig_MmFixed_t *  pMem;              // memory for ternary states
+    int              nPrefix;           // prefix of the ternary state space
+    int              nCycle;            // cycle of the ternary state space
+    int              nNonXRegs;         // the number of candidate registers
+    Vec_Int_t *      vNonXRegs;         // the candidate registers
+    // hash table for terminary states
+    unsigned **      pBins;
+    int              nBins;
+};
+
+static inline unsigned * Saig_TsiNext( unsigned * pState, int nWords )                      { return *((unsigned **)(pState + nWords));  }
+static inline void       Saig_TsiSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; }
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Saig_Tsim_t * Saig_TsiStart( Aig_Man_t * pAig )
+{
+    Saig_Tsim_t * p;
+    p = (Saig_Tsim_t *)ABC_ALLOC( char, sizeof(Saig_Tsim_t) );
+    memset( p, 0, sizeof(Saig_Tsim_t) );
+    p->pAig    = pAig;
+    p->nWords  = Abc_BitWordNum( 2*Aig_ManRegNum(pAig) );
+    p->vStates = Vec_PtrAlloc( 1000 );
+    p->pMem    = Aig_MmFixedStart( sizeof(unsigned) * p->nWords + sizeof(unsigned *), 10000 );
+    p->nBins   = Abc_PrimeCudd(TSIM_MAX_ROUNDS/2);
+    p->pBins   = ABC_ALLOC( unsigned *, p->nBins );
+    memset( p->pBins, 0, sizeof(unsigned *) * p->nBins );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_TsiStop( Saig_Tsim_t * p )
+{
+    if ( p->vNonXRegs )
+        Vec_IntFree( p->vNonXRegs );
+    Aig_MmFixedStop( p->pMem, 0 );
+    Vec_PtrFree( p->vStates );
+    ABC_FREE( p->pBins );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash value of the node using its simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_TsiStateHash( unsigned * pState, int nWords, int nTableSize )
+{
+    static int s_FPrimes[128] = { 
+        1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 
+        1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 
+        2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 
+        2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 
+        3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 
+        3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 
+        4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 
+        4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 
+        5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 
+        6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 
+        6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 
+        7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 
+        8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+    };
+    unsigned uHash;
+    int i;
+    uHash = 0;
+    for ( i = 0; i < nWords; i++ )
+        uHash ^= pState[i] * s_FPrimes[i & 0x7F];
+    return uHash % nTableSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count non-X-valued registers in the simulation data.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_TsiCountNonXValuedRegisters( Saig_Tsim_t * p, int nPref )
+{
+    unsigned * pState;
+    int nRegs = p->pAig->nRegs;
+    int Value, i, k;
+    assert( p->vNonXRegs == NULL );
+    p->vNonXRegs = Vec_IntAlloc( 10 );
+    for ( i = 0; i < nRegs; i++ )
+    {
+        Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, k, nPref )
+        {
+            Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i );
+            assert( Value != 0 );
+            if ( Value == SAIG_XVSX )
+                break;
+        }
+        if ( k == Vec_PtrSize(p->vStates) )
+            Vec_IntPush( p->vNonXRegs, i );
+    }
+    return Vec_IntSize(p->vNonXRegs);
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Computes flops that are stuck-at constant.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_TsiComputeTransient( Saig_Tsim_t * p, int nPref )
+{
+    Vec_Int_t * vCounters;
+    unsigned * pState;
+    int ValueThis = -1, ValuePrev = -1, StepPrev = -1;
+    int i, k, nRegs = p->pAig->nRegs;
+    vCounters = Vec_IntStart( nPref );
+    for ( i = 0; i < nRegs; i++ )
+    {
+        Vec_PtrForEachEntry( unsigned *, p->vStates, pState, k )
+        {
+            ValueThis = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i );
+//printf( "%s", (ValueThis == 1)? "0" : ((ValueThis == 2)? "1" : "x") );
+            assert( ValueThis != 0 );
+            if ( ValuePrev != ValueThis )
+            {
+                ValuePrev = ValueThis;
+                StepPrev  = k;
+            }
+        }
+//printf( "\n" );
+        if ( ValueThis == SAIG_XVSX )
+            continue;
+        if ( StepPrev >= nPref )
+            continue;
+        Vec_IntAddToEntry( vCounters, StepPrev, 1 );
+    }
+    Vec_IntForEachEntry( vCounters, ValueThis, i )
+    {
+        if ( ValueThis == 0 )
+            continue;
+//        printf( "%3d : %3d\n", i, ValueThis );
+    }
+    return vCounters;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count non-X-valued registers in the simulation data.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_TsiPrintTraces( Saig_Tsim_t * p, int nWords, int nPrefix, int nLoop )
+{
+    unsigned * pState;
+    int nRegs = p->pAig->nRegs;
+    int Value, i, k, Counter = 0;
+    printf( "Ternary traces for each flop:\n" );
+    printf( "      : " );
+    for ( i = 0; i < Vec_PtrSize(p->vStates) - nLoop - 1; i++ )
+        printf( "%d", i%10 );
+    printf( "  " );
+    for ( i = 0; i < nLoop; i++ )
+        printf( "%d", i%10 );
+    printf( "\n" );
+    for ( i = 0; i < nRegs; i++ )
+    {
+/*
+        Vec_PtrForEachEntry( unsigned *, p->vStates, pState, k )
+        {
+            Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i );
+            if ( Value == SAIG_XVSX )
+                break;
+        }
+        if ( k == Vec_PtrSize(p->vStates) )
+            Counter++;
+        else
+            continue;
+*/
+
+        // print trace
+//        printf( "%5d : %5d %5d  ", Counter, i, Saig_ManLo(p->pAig, i)->Id );
+        printf( "%5d : ", Counter++ );
+        Vec_PtrForEachEntryStop( unsigned *, p->vStates, pState, k, Vec_PtrSize(p->vStates)-1 )
+        {
+            Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i );
+            if ( Value == SAIG_XVS0 )
+                printf( "0" );
+            else if ( Value == SAIG_XVS1 )
+                printf( "1" );
+            else if ( Value == SAIG_XVSX )
+                printf( "x" );
+            else
+                assert( 0 );
+            if ( k == nPrefix - 1 )
+                printf( "  " );
+        }
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of the state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_TsiComputePrefix( Saig_Tsim_t * p, unsigned * pState, int nWords )
+{
+    unsigned * pEntry, * pPrev;
+    int Hash, i;
+    Hash = Saig_TsiStateHash( pState, nWords, p->nBins );
+    for ( pEntry = p->pBins[Hash]; pEntry; pEntry = Saig_TsiNext(pEntry, nWords) )
+        if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) )
+        {
+            Vec_PtrForEachEntry( unsigned *, p->vStates, pPrev, i )
+            {
+                if ( pPrev == pEntry )
+                    return i;
+            }
+            assert( 0 );
+            return -1;
+        }
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the value exists in the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_TsiStateLookup( Saig_Tsim_t * p, unsigned * pState, int nWords )
+{
+    unsigned * pEntry;
+    int Hash;
+    Hash = Saig_TsiStateHash( pState, nWords, p->nBins );
+    for ( pEntry = p->pBins[Hash]; pEntry; pEntry = Saig_TsiNext(pEntry, nWords) )
+        if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts value into the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_TsiStateInsert( Saig_Tsim_t * p, unsigned * pState, int nWords )
+{
+    int Hash = Saig_TsiStateHash( pState, nWords, p->nBins );
+    assert( !Saig_TsiStateLookup( p, pState, nWords ) );
+    Saig_TsiSetNext( pState, nWords, p->pBins[Hash] );
+    p->pBins[Hash] = pState;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts value into the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Saig_TsiStateNew( Saig_Tsim_t * p )
+{
+    unsigned * pState;
+    pState = (unsigned *)Aig_MmFixedEntryFetch( p->pMem );
+    memset( pState, 0, sizeof(unsigned) * p->nWords );
+    Vec_PtrPush( p->vStates, pState );
+    return pState;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts value into the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_TsiStatePrint( Saig_Tsim_t * p, unsigned * pState )
+{
+    int i, Value, nZeros = 0, nOnes = 0, nDcs = 0;
+    for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ )
+    {
+        Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i );
+        if ( Value == SAIG_XVS0 )
+            printf( "0" ), nZeros++;
+        else if ( Value == SAIG_XVS1 )
+            printf( "1" ), nOnes++;
+        else if ( Value == SAIG_XVSX )
+            printf( "x" ), nDcs++;
+        else
+            assert( 0 );
+    }
+    printf( " (0=%5d, 1=%5d, x=%5d)\n", nZeros, nOnes, nDcs );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count constant values in the state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_TsiStateCount( Saig_Tsim_t * p, unsigned * pState )
+{
+    Aig_Obj_t * pObjLi, * pObjLo;
+    int i, Value, nCounter = 0;
+    Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i )
+    {
+        Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i );
+        nCounter += (Value == SAIG_XVS0 || Value == SAIG_XVS1);
+    }
+    return nCounter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count constant values in the state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_TsiStateOrAll( Saig_Tsim_t * pTsi, unsigned * pState )
+{
+    unsigned * pPrev;
+    int i, k;
+    Vec_PtrForEachEntry( unsigned *, pTsi->vStates, pPrev, i )
+    {
+        for ( k = 0; k < pTsi->nWords; k++ )
+            pState[k] |= pPrev[k];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cycles the circuit to create a new initial state.]
+
+  Description [Simulates the circuit with random input for the given 
+  number of timeframes to get a better initial state.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Saig_Tsim_t * Saig_ManReachableTernary( Aig_Man_t * p, Vec_Int_t * vInits, int fVerbose )
+{
+    Saig_Tsim_t * pTsi;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    unsigned * pState;
+    int i, f, Value, nCounter;
+    // allocate the simulation manager
+    pTsi = Saig_TsiStart( p );
+    // initialize the values
+    Saig_ObjSetXsim( Aig_ManConst1(p), SAIG_XVS1 );
+    Saig_ManForEachPi( p, pObj, i )
+        Saig_ObjSetXsim( pObj, SAIG_XVSX );
+    if ( vInits )
+    {
+        Saig_ManForEachLo( p, pObj, i )
+            Saig_ObjSetXsim( pObj, Saig_XsimConvertValue(Vec_IntEntry(vInits, i)) );
+    }
+    else 
+    {
+        Saig_ManForEachLo( p, pObj, i )
+            Saig_ObjSetXsim( pObj, SAIG_XVS0 );
+    }
+    // simulate for the given number of timeframes
+    for ( f = 0; f < TSIM_MAX_ROUNDS; f++ )
+    {
+        // collect this state
+        pState = Saig_TsiStateNew( pTsi );
+        Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
+        {
+            Value = Saig_ObjGetXsim(pObjLo);
+            if ( Value & 1 )
+                Abc_InfoSetBit( pState, 2 * i );
+            if ( Value & 2 )
+                Abc_InfoSetBit( pState, 2 * i + 1 );
+        }
+//        printf( "%d ", Saig_TsiStateCount(pTsi, pState) );
+//        Saig_TsiStatePrint( pTsi, pState );
+        // check if this state exists
+        if ( Saig_TsiStateLookup( pTsi, pState, pTsi->nWords ) )
+        {
+            if ( fVerbose )
+                printf( "Ternary simulation converged after %d iterations.\n", f );
+            return pTsi;
+        }
+        // insert this state
+        Saig_TsiStateInsert( pTsi, pState, pTsi->nWords );
+        // simulate internal nodes
+        Aig_ManForEachNode( p, pObj, i )
+            Saig_ObjSetXsim( pObj, Saig_XsimAnd(Saig_ObjGetXsimFanin0(pObj), Saig_ObjGetXsimFanin1(pObj)) );
+        // transfer the latch values
+        Saig_ManForEachLi( p, pObj, i )
+            Saig_ObjSetXsim( pObj, Saig_ObjGetXsimFanin0(pObj) );
+        nCounter = 0;
+        Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
+        {
+            if ( f < TSIM_ONE_SERIES )
+                Saig_ObjSetXsim( pObjLo, Saig_ObjGetXsim(pObjLi) );
+            else
+            {
+                if ( Saig_ObjGetXsim(pObjLi) != Saig_ObjGetXsim(pObjLo) )
+                    Saig_ObjSetXsim( pObjLo, SAIG_XVSX );
+            }
+            nCounter += (Saig_ObjGetXsim(pObjLo) == SAIG_XVS0);
+        }
+    }
+    printf( "Saig_ManReachableTernary(): Did not reach a fixed point after %d iterations (not a bug).\n", TSIM_MAX_ROUNDS );
+    Saig_TsiStop( pTsi );
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Analize initial value of the selected register.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManAnalizeControl( Aig_Man_t * p, int Reg )
+{
+    Aig_Obj_t * pObj, * pReg, * pCtrl, * pAnd;
+    int i;
+    pReg = Saig_ManLo( p, Reg );
+    pCtrl = Saig_ManLo( p, Saig_ManRegNum(p)-1 );
+    assert( pReg->Id < pCtrl->Id );
+    // find a node pointing to both
+    pAnd = NULL;
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        if ( Aig_ObjFanin0(pObj) == pReg && Aig_ObjFanin1(pObj) == pCtrl )
+        {
+            pAnd = pObj;
+            break;
+        }
+    }
+    if ( pAnd == NULL )
+    {
+        printf( "Register is not found.\n" );
+        return;
+    }
+    printf( "Clock-like register: \n" );
+    Aig_ObjPrint( p, pReg );
+    printf( "\n" );
+    printf( "Control register: \n" );
+    Aig_ObjPrint( p, pCtrl );
+    printf( "\n" );
+    printf( "Their fanout: \n" );
+    Aig_ObjPrint( p, pAnd );
+    printf( "\n" );
+ 
+    // find the fanouts of pAnd
+    printf( "Fanouts of the fanout: \n" );
+    Aig_ManForEachObj( p, pObj, i )
+        if ( Aig_ObjFanin0(pObj) == pAnd || Aig_ObjFanin1(pObj) == pAnd )
+        {
+            Aig_ObjPrint( p, pObj );
+            printf( "\n" );
+        }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the registers to phase-abstract.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManFindRegisters( Saig_Tsim_t * pTsi, int nFrames, int fIgnore, int fVerbose )
+{
+    int Values[257] = {0};
+    unsigned * pState;
+    int r, i, k, Reg, Value;
+    int nTests = pTsi->nPrefix + 2 * pTsi->nCycle;
+    assert( nFrames <= 256 );
+    r = 0;
+    Vec_IntForEachEntry( pTsi->vNonXRegs, Reg, i )
+    {
+        for ( k = 0; k < nTests; k++ )
+        {
+            if ( k < pTsi->nPrefix + pTsi->nCycle )
+                pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, k );
+            else
+                pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, k - pTsi->nCycle );
+            Value = (Abc_InfoHasBit( pState, 2 * Reg + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * Reg );
+            assert( Value == SAIG_XVS0 || Value == SAIG_XVS1 );
+            if ( k < nFrames || (fIgnore && k == nFrames) )
+                Values[k % nFrames] = Value;
+            else if ( Values[k % nFrames] != Value )
+                break;
+        }
+        if ( k < nTests )
+            continue;
+        // skip stuck at
+        if ( fIgnore )
+        {
+            for ( k = 1; k < nFrames; k++ )
+                if ( Values[k] != Values[0] )
+                    break;
+            if ( k == nFrames )
+                continue;
+        }
+        // report useful register
+        Vec_IntWriteEntry( pTsi->vNonXRegs, r++, Reg );
+        if ( fVerbose )
+        {
+            printf( "Register %5d has generator: [", Reg );
+            for ( k = 0; k < nFrames; k++ )
+                Saig_XsimPrint( stdout, Values[k] );
+            printf( "]\n" );
+
+            if ( fVerbose )
+            Saig_ManAnalizeControl( pTsi->pAig, Reg );
+        }
+    }
+    Vec_IntShrink( pTsi->vNonXRegs, r );
+    if ( fVerbose )
+        printf( "Found %3d useful registers.\n", Vec_IntSize(pTsi->vNonXRegs) );
+    return Vec_IntSize(pTsi->vNonXRegs);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Mapping of AIG nodes into frames nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Aig_Obj_t * Saig_ObjFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i )                       { return pObjMap[nFs*pObj->Id + i];  }
+static inline void        Saig_ObjSetFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { pObjMap[nFs*pObj->Id + i] = pNode; }
+
+static inline Aig_Obj_t * Saig_ObjChild0Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin0(pObj)? Aig_NotCond(Saig_ObjFrames(pObjMap,nFs,Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL;  }
+static inline Aig_Obj_t * Saig_ObjChild1Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin1(pObj)? Aig_NotCond(Saig_ObjFrames(pObjMap,nFs,Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL;  }
+
+/**Function*************************************************************
+
+  Synopsis    [Performs phase abstraction by unrolling the circuit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManPerformAbstraction( Saig_Tsim_t * pTsi, int nFrames, int fVerbose )
+{
+    Aig_Man_t * pFrames, * pAig = pTsi->pAig;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew;
+    Aig_Obj_t ** pObjMap;
+    unsigned * pState;
+    int i, f, Reg, Value;
+
+    assert( Vec_IntSize(pTsi->vNonXRegs) > 0 );
+
+    // create mapping for the frames nodes
+    pObjMap = ABC_ALLOC( Aig_Obj_t *, nFrames * Aig_ManObjNumMax(pAig) );
+    memset( pObjMap, 0, sizeof(Aig_Obj_t *) * nFrames * Aig_ManObjNumMax(pAig) );
+
+    // start the fraig package
+    pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames );
+    pFrames->pName = Abc_UtilStrsav( pAig->pName );
+    pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec );
+    // map constant nodes
+    for ( f = 0; f < nFrames; f++ )
+        Saig_ObjSetFrames( pObjMap, nFrames, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) );
+    // create PI nodes for the frames
+    for ( f = 0; f < nFrames; f++ )
+        Aig_ManForEachPiSeq( pAig, pObj, i )
+            Saig_ObjSetFrames( pObjMap, nFrames, pObj, f, Aig_ObjCreateCi(pFrames) );
+    // create the latches
+    Aig_ManForEachLoSeq( pAig, pObj, i )
+        Saig_ObjSetFrames( pObjMap, nFrames, pObj, 0, Aig_ObjCreateCi(pFrames) );
+
+    // add timeframes
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // replace abstracted registers by constants
+        Vec_IntForEachEntry( pTsi->vNonXRegs, Reg, i )
+        {
+            pObj = Saig_ManLo( pAig, Reg );
+            pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, f );
+            Value = (Abc_InfoHasBit( pState, 2 * Reg + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * Reg );
+            assert( Value == SAIG_XVS0 || Value == SAIG_XVS1 );
+            pObjNew = (Value == SAIG_XVS1)? Aig_ManConst1(pFrames) : Aig_ManConst0(pFrames);
+            Saig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew );
+        }
+        // add internal nodes of this frame
+        Aig_ManForEachNode( pAig, pObj, i ) 
+        {
+            pObjNew = Aig_And( pFrames, Saig_ObjChild0Frames(pObjMap,nFrames,pObj,f), Saig_ObjChild1Frames(pObjMap,nFrames,pObj,f) );
+            Saig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew );
+        }
+        // set the latch inputs and copy them into the latch outputs of the next frame
+        Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i )
+        {
+            pObjNew = Saig_ObjChild0Frames(pObjMap,nFrames,pObjLi,f);
+            if ( f < nFrames - 1 )
+                Saig_ObjSetFrames( pObjMap, nFrames, pObjLo, f+1, pObjNew );
+        }
+    }
+    for ( f = 0; f < nFrames; f++ )
+    {
+        Aig_ManForEachPoSeq( pAig, pObj, i )
+        {
+            pObjNew = Aig_ObjCreateCo( pFrames, Saig_ObjChild0Frames(pObjMap,nFrames,pObj,f) );
+            Saig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew );
+        }
+    }
+    pFrames->nRegs = pAig->nRegs;
+    pFrames->nTruePis = Aig_ManCiNum(pFrames) - Aig_ManRegNum(pFrames); 
+    pFrames->nTruePos = Aig_ManCoNum(pFrames) - Aig_ManRegNum(pFrames); 
+    Aig_ManForEachLiSeq( pAig, pObj, i )
+    {
+        pObjNew = Aig_ObjCreateCo( pFrames, Saig_ObjChild0Frames(pObjMap,nFrames,pObj,nFrames-1) );
+        Saig_ObjSetFrames( pObjMap, nFrames, pObj, nFrames-1, pObjNew );
+    }
+//Aig_ManPrintStats( pFrames );
+    Aig_ManSeqCleanup( pFrames );
+//Aig_ManPrintStats( pFrames );
+//    Aig_ManCiCleanup( pFrames );
+//Aig_ManPrintStats( pFrames );
+    ABC_FREE( pObjMap );
+    return pFrames;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs automated phase abstraction.]
+
+  Description [Takes the AIG manager and the array of initial states.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManPhaseFrameNum( Aig_Man_t * p, Vec_Int_t * vInits )
+{
+    Saig_Tsim_t * pTsi;
+    int nFrames, nPrefix;
+    assert( Saig_ManRegNum(p) );
+    assert( Saig_ManPiNum(p) );
+    assert( Saig_ManPoNum(p) );
+    // perform terminary simulation
+    pTsi = Saig_ManReachableTernary( p, vInits, 0 );
+    if ( pTsi == NULL )
+        return 1;
+    // derive information
+    nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords );
+    nFrames = Vec_PtrSize(pTsi->vStates) - 1 - nPrefix;
+    Saig_TsiStop( pTsi );
+    // potentially, may need to reduce nFrames if nPrefix is less than nFrames
+    return nFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs automated phase abstraction.]
+
+  Description [Takes the AIG manager and the array of initial states.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManPhasePrefixLength( Aig_Man_t * p, int fVerbose, int fVeryVerbose, Vec_Int_t ** pvTrans )
+{
+    Saig_Tsim_t * pTsi;
+    int nFrames, nPrefix, nNonXRegs;
+    assert( Saig_ManRegNum(p) );
+    assert( Saig_ManPiNum(p) );
+    assert( Saig_ManPoNum(p) );
+    // perform terminary simulation
+    pTsi = Saig_ManReachableTernary( p, NULL, 0 );
+    if ( pTsi == NULL )
+        return 0;
+    // derive information
+    nPrefix   = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords );
+    nFrames   = Vec_PtrSize(pTsi->vStates) - 1 - nPrefix;
+    nNonXRegs = Saig_TsiCountNonXValuedRegisters( pTsi, nPrefix );
+
+    if ( pvTrans )
+        *pvTrans = Saig_TsiComputeTransient( pTsi, nPrefix );
+
+    // print statistics
+    if ( fVerbose )
+        printf( "Lead = %5d. Loop = %5d.  Total flops = %5d. Binary flops = %5d.\n", nPrefix, nFrames, p->nRegs, nNonXRegs );
+    if ( fVeryVerbose )
+        Saig_TsiPrintTraces( pTsi, pTsi->nWords, nPrefix, nFrames );
+    Saig_TsiStop( pTsi );
+    // potentially, may need to reduce nFrames if nPrefix is less than nFrames
+    return nPrefix;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs automated phase abstraction.]
+
+  Description [Takes the AIG manager and the array of initial states.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManPhaseAbstract( Aig_Man_t * p, Vec_Int_t * vInits, int nFrames, int nPref, int fIgnore, int fPrint, int fVerbose )
+{
+    Aig_Man_t * pNew = NULL;
+    Saig_Tsim_t * pTsi;
+    assert( Saig_ManRegNum(p) );
+    assert( Saig_ManPiNum(p) );
+    assert( Saig_ManPoNum(p) );
+    // perform terminary simulation
+    pTsi = Saig_ManReachableTernary( p, vInits, fVerbose );
+    if ( pTsi == NULL )
+        return NULL;
+    // derive information
+    pTsi->nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords );
+    pTsi->nCycle = Vec_PtrSize(pTsi->vStates) - 1 - pTsi->nPrefix;
+    pTsi->nNonXRegs = Saig_TsiCountNonXValuedRegisters(pTsi, Abc_MinInt(pTsi->nPrefix,nPref));
+    // print statistics
+    if ( fVerbose )
+    {
+        printf( "Lead = %5d. Loop = %5d.  Total flops = %5d. Binary flops = %5d.\n", 
+            pTsi->nPrefix, pTsi->nCycle, p->nRegs, pTsi->nNonXRegs );
+        if ( pTsi->nNonXRegs < 100 && Vec_PtrSize(pTsi->vStates) < 80 )
+            Saig_TsiPrintTraces( pTsi, pTsi->nWords, pTsi->nPrefix, pTsi->nCycle );
+    }
+    if ( fPrint )
+        printf( "Print-out finished. Phase assignment is not performed.\n" );
+    else if ( nFrames < 2 )
+        printf( "The number of frames is less than 2. Phase assignment is not performed.\n" );
+    else if ( nFrames > 256 )
+        printf( "The number of frames is more than 256. Phase assignment is not performed.\n" );
+    else if ( pTsi->nCycle == 1 )
+        printf( "The cycle of ternary states is trivial. Phase abstraction cannot be done.\n" );
+    else if ( pTsi->nCycle % nFrames != 0 )
+        printf( "The cycle (%d) is not modulo the number of frames (%d). Phase abstraction cannot be done.\n", pTsi->nCycle, nFrames );
+    else if ( pTsi->nNonXRegs == 0 )
+        printf( "All registers have X-valued states. Phase abstraction cannot be done.\n" );
+    else if ( !Saig_ManFindRegisters( pTsi, nFrames, fIgnore, fVerbose ) )
+        printf( "There is no registers to abstract with %d frames.\n", nFrames );
+    else
+        pNew = Saig_ManPerformAbstraction( pTsi, nFrames, fVerbose );
+    Saig_TsiStop( pTsi );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs automated phase abstraction.]
+
+  Description [Takes the AIG manager and the array of initial states.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManPhaseAbstractAuto( Aig_Man_t * p, int fVerbose )
+{
+    Aig_Man_t * pNew = NULL;
+    Saig_Tsim_t * pTsi;
+    int fPrint = 0;
+    int nFrames;
+    assert( Saig_ManRegNum(p) );
+    assert( Saig_ManPiNum(p) );
+    assert( Saig_ManPoNum(p) );
+    // perform terminary simulation
+    pTsi = Saig_ManReachableTernary( p, NULL, fVerbose );
+    if ( pTsi == NULL )
+        return NULL;
+    // derive information
+    pTsi->nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords );
+    pTsi->nCycle = Vec_PtrSize(pTsi->vStates) - 1 - pTsi->nPrefix;
+    pTsi->nNonXRegs = Saig_TsiCountNonXValuedRegisters(pTsi, 0);
+    // print statistics
+    if ( fVerbose )
+    {
+        printf( "Lead = %5d. Loop = %5d.  Total flops = %5d. Binary flops = %5d.\n", 
+            pTsi->nPrefix, pTsi->nCycle, p->nRegs, pTsi->nNonXRegs );
+        if ( pTsi->nNonXRegs < 100 && Vec_PtrSize(pTsi->vStates) < 80 )
+            Saig_TsiPrintTraces( pTsi, pTsi->nWords, pTsi->nPrefix, pTsi->nCycle );
+    }
+    nFrames = pTsi->nCycle;
+    if ( fPrint )
+    {
+        printf( "Print-out finished. Phase assignment is not performed.\n" );
+    }
+    else if ( nFrames < 2 )
+    {
+//        printf( "The number of frames is less than 2. Phase assignment is not performed.\n" );
+    }
+    else if ( nFrames > 256 )
+    {
+//        printf( "The number of frames is more than 256. Phase assignment is not performed.\n" );
+    }
+    else if ( pTsi->nCycle == 1 )
+    {
+//        printf( "The cycle of ternary states is trivial. Phase abstraction cannot be done.\n" );
+    }
+    else if ( pTsi->nCycle % nFrames != 0 )
+    {
+//        printf( "The cycle (%d) is not modulo the number of frames (%d). Phase abstraction cannot be done.\n", pTsi->nCycle, nFrames );
+    }
+    else if ( pTsi->nNonXRegs == 0 )
+    {
+//        printf( "All registers have X-valued states. Phase abstraction cannot be done.\n" );
+    }
+    else if ( !Saig_ManFindRegisters( pTsi, nFrames, 0, fVerbose ) )
+    {
+//        printf( "There is no registers to abstract with %d frames.\n", nFrames );
+    }
+    else
+        pNew = Saig_ManPerformAbstraction( pTsi, nFrames, fVerbose );
+    Saig_TsiStop( pTsi );
+    if ( pNew == NULL )
+        pNew = Aig_ManDupSimple( p );
+    if ( Aig_ManCiNum(pNew) == Aig_ManRegNum(pNew) )
+    {
+        Aig_ManStop( pNew);
+        pNew = Aig_ManDupSimple( p );
+    }
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CEX for the original AIG from CEX of the unrolled AIG.]
+
+  Description [The number of PIs of the given CEX should divide by the number 
+  of PIs of the original AIG without a remainder.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Saig_PhaseTranslateCex( Aig_Man_t * p, Abc_Cex_t * pCex )
+{
+    Abc_Cex_t * pNew;
+    int i, k, iFrame, nFrames;
+    // make sure the PI count of the AIG is a multiple of the PI count of the CEX
+    // if this is not true, the CEX is not derived as the result of unrolling of pAig
+    // or the unrolled CEX went through transformations that change the PI count
+    if ( pCex->nPis % Saig_ManPiNum(p) != 0 )
+    {
+        printf( "The PI count in the AIG and in the CEX do not match.\n" );
+        return NULL;
+    }
+    // get the number of unrolled frames
+    nFrames = pCex->nPis / Saig_ManPiNum(p);
+    // get the frame where it fails
+    iFrame = pCex->iFrame * nFrames + pCex->iPo / Saig_ManPoNum(p);
+    // start a new CEX (assigns: p->nRegs, p->nPis, p->nBits)
+    pNew = Abc_CexAlloc( Saig_ManRegNum(p), Saig_ManPiNum(p), iFrame+1 );
+    assert( pNew->nBits == pNew->nPis * (iFrame + 1) + pNew->nRegs );
+    // now assign the failed frame and the failed PO (p->iFrame and p->iPo)
+    pNew->iFrame = iFrame;
+    pNew->iPo    = pCex->iPo % Saig_ManPoNum(p);
+    // copy the bit data
+    for ( i = pCex->nRegs, k = pNew->nRegs; k < pNew->nBits; k++, i++ )
+        if ( Abc_InfoHasBit( pCex->pData, i ) )
+            Abc_InfoSetBit( pNew->pData, k );
+    assert( i <= pCex->nBits );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigRefSat.c b/abc-build/src/aig/saig/saigRefSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigRefSat.c
@@ -0,0 +1,986 @@
+/**CFile****************************************************************
+
+  FileName    [saigRefSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [SAT based refinement of a counter-example.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigRefSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// local manager
+typedef struct Saig_RefMan_t_ Saig_RefMan_t;
+struct Saig_RefMan_t_
+{
+    // user data
+    Aig_Man_t * pAig;       // user's AIG
+    Abc_Cex_t * pCex;       // user's CEX
+    int         nInputs;    // the number of first inputs to skip
+    int         fVerbose;   // verbose flag
+    // unrolling
+    Aig_Man_t * pFrames;    // unrolled timeframes
+    Vec_Int_t * vMapPiF2A;  // mapping of frame PIs into real PIs
+};
+
+// performs ternary simulation
+extern int Saig_ManSimDataInit( Aig_Man_t * p, Abc_Cex_t * pCex, Vec_Ptr_t * vSimInfo, Vec_Int_t * vRes );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Maps array of frame PI IDs into array of original PI IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_RefManReason2Inputs( Saig_RefMan_t * p, Vec_Int_t * vReasons )
+{
+    Vec_Int_t * vOriginal, * vVisited;
+    int i, Entry;
+    vOriginal = Vec_IntAlloc( Saig_ManPiNum(p->pAig) ); 
+    vVisited = Vec_IntStart( Saig_ManPiNum(p->pAig) );
+    Vec_IntForEachEntry( vReasons, Entry, i )
+    {
+        int iInput = Vec_IntEntry( p->vMapPiF2A, 2*Entry );
+        assert( iInput >= 0 && iInput < Aig_ManCiNum(p->pAig) );
+        if ( Vec_IntEntry(vVisited, iInput) == 0 )
+            Vec_IntPush( vOriginal, iInput );
+        Vec_IntAddToEntry( vVisited, iInput, 1 );
+    }
+    Vec_IntFree( vVisited );
+    return vOriginal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Saig_RefManReason2Cex( Saig_RefMan_t * p, Vec_Int_t * vReasons )
+{
+    Abc_Cex_t * pCare;
+    int i, Entry, iInput, iFrame;
+    pCare = Abc_CexDup( p->pCex, p->pCex->nRegs );
+    memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) );
+    Vec_IntForEachEntry( vReasons, Entry, i )
+    {
+        assert( Entry >= 0 && Entry < Aig_ManCiNum(p->pFrames) );
+        iInput = Vec_IntEntry( p->vMapPiF2A, 2*Entry );
+        iFrame = Vec_IntEntry( p->vMapPiF2A, 2*Entry+1 );
+        Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput );
+    }
+    return pCare;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns reasons for the property to fail.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_RefManFindReason_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vPrios, Vec_Int_t * vReasons )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        Vec_IntPush( vReasons, Aig_ObjCioId(pObj) );
+        return;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    if ( pObj->fPhase )
+    {
+        Saig_RefManFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons );
+        Saig_RefManFindReason_rec( p, Aig_ObjFanin1(pObj), vPrios, vReasons );
+    }
+    else
+    {
+        int fPhase0 = Aig_ObjFaninC0(pObj) ^ Aig_ObjFanin0(pObj)->fPhase;
+        int fPhase1 = Aig_ObjFaninC1(pObj) ^ Aig_ObjFanin1(pObj)->fPhase;
+        assert( !fPhase0 || !fPhase1 );
+        if ( !fPhase0 && fPhase1 )
+            Saig_RefManFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons );
+        else if ( fPhase0 && !fPhase1 )
+            Saig_RefManFindReason_rec( p, Aig_ObjFanin1(pObj), vPrios, vReasons );
+        else 
+        {
+            int iPrio0 = Vec_IntEntry( vPrios, Aig_ObjFaninId0(pObj) );
+            int iPrio1 = Vec_IntEntry( vPrios, Aig_ObjFaninId1(pObj) );
+            if ( iPrio0 <= iPrio1 )
+                Saig_RefManFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons );
+            else
+                Saig_RefManFindReason_rec( p, Aig_ObjFanin1(pObj), vPrios, vReasons );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns reasons for the property to fail.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_RefManFindReason( Saig_RefMan_t * p )
+{
+    Aig_Obj_t * pObj;
+    Vec_Int_t * vPrios, * vPi2Prio, * vReasons;
+    int i, CountPrios;
+
+    vPi2Prio = Vec_IntStartFull( Saig_ManPiNum(p->pAig) );
+    vPrios   = Vec_IntStartFull( Aig_ManObjNumMax(p->pFrames) );
+
+    // set PI values according to CEX
+    CountPrios = 0;
+    Aig_ManConst1(p->pFrames)->fPhase = 1;
+    Aig_ManForEachCi( p->pFrames, pObj, i )
+    {
+        int iInput = Vec_IntEntry( p->vMapPiF2A, 2*i );
+        int iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 );
+        pObj->fPhase = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput );
+        // assign priority
+        if ( Vec_IntEntry(vPi2Prio, iInput) == ~0 )
+            Vec_IntWriteEntry( vPi2Prio, iInput, CountPrios++ );
+//        Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), Vec_IntEntry(vPi2Prio, iInput) );
+        Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), i );
+    }
+//    printf( "Priority numbers = %d.\n", CountPrios );
+    Vec_IntFree( vPi2Prio );
+
+    // traverse and set the priority
+    Aig_ManForEachNode( p->pFrames, pObj, i )
+    {
+        int fPhase0 = Aig_ObjFaninC0(pObj) ^ Aig_ObjFanin0(pObj)->fPhase;
+        int fPhase1 = Aig_ObjFaninC1(pObj) ^ Aig_ObjFanin1(pObj)->fPhase;
+        int iPrio0  = Vec_IntEntry( vPrios, Aig_ObjFaninId0(pObj) );
+        int iPrio1  = Vec_IntEntry( vPrios, Aig_ObjFaninId1(pObj) );
+        pObj->fPhase = fPhase0 && fPhase1;
+        if ( fPhase0 && fPhase1 ) // both are one
+            Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), Abc_MaxInt(iPrio0, iPrio1) );
+        else if ( !fPhase0 && fPhase1 ) 
+            Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), iPrio0 );
+        else if ( fPhase0 && !fPhase1 )
+            Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), iPrio1 );
+        else // both are zero
+            Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), Abc_MinInt(iPrio0, iPrio1) );
+    }
+    // check the property output
+    pObj = Aig_ManCo( p->pFrames, 0 );
+    assert( (int)Aig_ObjFanin0(pObj)->fPhase == Aig_ObjFaninC0(pObj) );
+
+    // select the reason
+    vReasons = Vec_IntAlloc( 100 );
+    Aig_ManIncrementTravId( p->pFrames );
+    if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) )
+        Saig_RefManFindReason_rec( p->pFrames, Aig_ObjFanin0(pObj), vPrios, vReasons );
+    Vec_IntFree( vPrios );
+    return vReasons;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collect nodes in the unrolled timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManUnrollCollect_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vObjs, Vec_Int_t * vRoots )
+{
+    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(pAig, pObj);
+    if ( Aig_ObjIsCo(pObj) )
+        Saig_ManUnrollCollect_rec( pAig, Aig_ObjFanin0(pObj), vObjs, vRoots );
+    else if ( Aig_ObjIsNode(pObj) )
+    {
+        Saig_ManUnrollCollect_rec( pAig, Aig_ObjFanin0(pObj), vObjs, vRoots );
+        Saig_ManUnrollCollect_rec( pAig, Aig_ObjFanin1(pObj), vObjs, vRoots );
+    }
+    if ( vRoots && Saig_ObjIsLo( pAig, pObj ) )
+        Vec_IntPush( vRoots, Aig_ObjId( Saig_ObjLoToLi(pAig, pObj) ) );
+    Vec_IntPush( vObjs, Aig_ObjId(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive unrolled timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManUnrollWithCex( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, Vec_Int_t ** pvMapPiF2A )
+{
+    Aig_Man_t * pFrames;     // unrolled timeframes
+    Vec_Vec_t * vFrameCos;   // the list of COs per frame
+    Vec_Vec_t * vFrameObjs;  // the list of objects per frame
+    Vec_Int_t * vRoots, * vObjs;
+    Aig_Obj_t * pObj;
+    int i, f;
+    // sanity checks
+    assert( Saig_ManPiNum(pAig) == pCex->nPis );
+    assert( Saig_ManRegNum(pAig) == pCex->nRegs );
+    assert( pCex->iPo >= 0 && pCex->iPo < Saig_ManPoNum(pAig) );
+
+    // map PIs of the unrolled frames into PIs of the original design
+    *pvMapPiF2A = Vec_IntAlloc( 1000 );
+
+    // collect COs and Objs visited in each frame
+    vFrameCos  = Vec_VecStart( pCex->iFrame+1 );
+    vFrameObjs = Vec_VecStart( pCex->iFrame+1 );
+    // initialized the topmost frame
+    pObj = Aig_ManCo( pAig, pCex->iPo );
+    Vec_VecPushInt( vFrameCos, pCex->iFrame, Aig_ObjId(pObj) );
+    for ( f = pCex->iFrame; f >= 0; f-- )
+    {
+        // collect nodes starting from the roots
+        Aig_ManIncrementTravId( pAig );
+        vRoots = Vec_VecEntryInt( vFrameCos, f );
+        Aig_ManForEachObjVec( vRoots, pAig, pObj, i )
+            Saig_ManUnrollCollect_rec( pAig, pObj, 
+                Vec_VecEntryInt(vFrameObjs, f),
+                (Vec_Int_t *)(f ? Vec_VecEntry(vFrameCos, f-1) : NULL) );
+    }
+
+    // derive unrolled timeframes
+    pFrames = Aig_ManStart( 10000 );
+    pFrames->pName = Abc_UtilStrsav( pAig->pName );
+    pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec );
+    // initialize the flops 
+    Saig_ManForEachLo( pAig, pObj, i )
+        pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Abc_InfoHasBit(pCex->pData, i) );
+    // iterate through the frames
+    for ( f = 0; f <= pCex->iFrame; f++ )
+    {
+        // construct
+        vObjs = Vec_VecEntryInt( vFrameObjs, f );
+        Aig_ManForEachObjVec( vObjs, pAig, pObj, i )
+        {
+            if ( Aig_ObjIsNode(pObj) )
+                pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+            else if ( Aig_ObjIsCo(pObj) )
+                pObj->pData = Aig_ObjChild0Copy(pObj);
+            else if ( Aig_ObjIsConst1(pObj) )
+                pObj->pData = Aig_ManConst1(pFrames);
+            else if ( Saig_ObjIsPi(pAig, pObj) )
+            {
+                if ( Aig_ObjCioId(pObj) < nInputs )
+                {
+                    int iBit = pCex->nRegs + f * pCex->nPis + Aig_ObjCioId(pObj);
+                    pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Abc_InfoHasBit(pCex->pData, iBit) );
+                }
+                else
+                {
+                    pObj->pData = Aig_ObjCreateCi( pFrames );
+                    Vec_IntPush( *pvMapPiF2A, Aig_ObjCioId(pObj) );
+                    Vec_IntPush( *pvMapPiF2A, f );
+                }
+            }
+        }
+        if ( f == pCex->iFrame )
+            break;
+        // transfer
+        vRoots = Vec_VecEntryInt( vFrameCos, f );
+        Aig_ManForEachObjVec( vRoots, pAig, pObj, i )
+            Saig_ObjLiToLo( pAig, pObj )->pData = pObj->pData;
+    }
+    // create output
+    pObj = Aig_ManCo( pAig, pCex->iPo );
+    Aig_ObjCreateCo( pFrames, Aig_Not((Aig_Obj_t *)pObj->pData) );
+    Aig_ManSetRegNum( pFrames, 0 );
+    // cleanup
+    Vec_VecFree( vFrameCos );
+    Vec_VecFree( vFrameObjs );
+    // finallize
+    Aig_ManCleanup( pFrames );
+    // return
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates refinement manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Saig_RefMan_t * Saig_RefManStart( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, int fVerbose )
+{
+    Saig_RefMan_t * p;
+    p = ABC_CALLOC( Saig_RefMan_t, 1 );
+    p->pAig = pAig;
+    p->pCex = pCex;
+    p->nInputs = nInputs;
+    p->fVerbose = fVerbose;
+    p->pFrames = Saig_ManUnrollWithCex( pAig, pCex, nInputs, &p->vMapPiF2A );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Destroys refinement manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_RefManStop( Saig_RefMan_t * p )
+{
+    Aig_ManStopP( &p->pFrames );
+    Vec_IntFreeP( &p->vMapPiF2A );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets phase bits in the timeframe AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_RefManSetPhases( Saig_RefMan_t * p, Abc_Cex_t * pCare, int fValue1 )
+{
+    Aig_Obj_t * pObj;
+    int i, iFrame, iInput;
+    Aig_ManConst1( p->pFrames )->fPhase = 1;
+    Aig_ManForEachCi( p->pFrames, pObj, i )
+    {
+        iInput = Vec_IntEntry( p->vMapPiF2A, 2*i );
+        iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 );
+        pObj->fPhase = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput );
+        // update value if it is a don't-care
+        if ( pCare && !Abc_InfoHasBit( pCare->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ) )
+            pObj->fPhase = fValue1;
+    }
+    Aig_ManForEachNode( p->pFrames, pObj, i )
+        pObj->fPhase = ( Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj) )
+                     & ( Aig_ObjFanin1(pObj)->fPhase ^ Aig_ObjFaninC1(pObj) );
+    Aig_ManForEachCo( p->pFrames, pObj, i )
+        pObj->fPhase = ( Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj) );
+    pObj = Aig_ManCo( p->pFrames, 0 );
+    return pObj->fPhase;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tries to remove literals from abstraction.]
+
+  Description [The literals are sorted more desirable first.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Saig_RefManOrderLiterals( Saig_RefMan_t * p, Vec_Int_t * vVar2PiId, Vec_Int_t * vAssumps )
+{
+    Vec_Vec_t * vLits;
+    Vec_Int_t * vVar2New;
+    int i, Entry, iInput, iFrame;
+    // collect literals
+    vLits = Vec_VecAlloc( 100 );
+    vVar2New = Vec_IntStartFull( Saig_ManPiNum(p->pAig) );
+    Vec_IntForEachEntry( vAssumps, Entry, i )
+    {
+        int iPiNum = Vec_IntEntry( vVar2PiId, lit_var(Entry) );
+        assert( iPiNum >= 0 && iPiNum < Aig_ManCiNum(p->pFrames) );
+        iInput = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum );
+        iFrame = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum+1 );
+//        Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput );
+        if ( Vec_IntEntry( vVar2New, iInput ) == ~0 )
+            Vec_IntWriteEntry( vVar2New, iInput, Vec_VecSize(vLits) );
+        Vec_VecPushInt( vLits, Vec_IntEntry( vVar2New, iInput ), Entry );
+    }
+    Vec_IntFree( vVar2New );
+    return vLits;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Generate the care set using SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Saig_RefManCreateCex( Saig_RefMan_t * p, Vec_Int_t * vVar2PiId, Vec_Int_t * vAssumps )
+{
+    Abc_Cex_t * pCare;
+    int i, Entry, iInput, iFrame;
+    // create counter-example
+    pCare = Abc_CexDup( p->pCex, p->pCex->nRegs );
+    memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) );
+    Vec_IntForEachEntry( vAssumps, Entry, i )
+    {
+        int iPiNum = Vec_IntEntry( vVar2PiId, lit_var(Entry) );
+        assert( iPiNum >= 0 && iPiNum < Aig_ManCiNum(p->pFrames) );
+        iInput = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum );
+        iFrame = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum+1 );
+        Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput );
+    }
+    return pCare;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generate the care set using SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Saig_RefManRunSat( Saig_RefMan_t * p, int fNewOrder )
+{
+    int nConfLimit = 1000000;
+    Abc_Cex_t * pCare;
+    Cnf_Dat_t * pCnf;
+    sat_solver * pSat;
+    Aig_Obj_t * pObj;
+    Vec_Vec_t * vLits = NULL;
+    Vec_Int_t * vAssumps, * vVar2PiId;
+    int i, k, Entry, RetValue;//, f = 0, Counter = 0;
+    int nCoreLits, * pCoreLits;
+    clock_t clk = clock();
+    // create CNF
+    assert( Aig_ManRegNum(p->pFrames) == 0 );
+//    pCnf = Cnf_Derive( p->pFrames, 0 ); // too slow
+    pCnf = Cnf_DeriveSimple( p->pFrames, 0 );
+    RetValue = Saig_RefManSetPhases( p, NULL, 0 );
+    if ( RetValue )
+    {
+        printf( "Constructed frames are incorrect.\n" );
+        Cnf_DataFree( pCnf );
+        return NULL;
+    }
+    Cnf_DataTranformPolarity( pCnf, 0 );
+    // create SAT solver
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+    if ( pSat == NULL )
+    {
+        Cnf_DataFree( pCnf );
+        return NULL;
+    }
+//Abc_PrintTime( 1, "Preparing", clock() - clk );
+    // look for a true counter-example
+    if ( p->nInputs > 0 )
+    {
+        RetValue = sat_solver_solve( pSat, NULL, NULL, 
+            (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        if ( RetValue == l_False )
+        {
+            printf( "The problem is trivially UNSAT. The CEX is real.\n" );
+            // create counter-example
+            pCare = Abc_CexDup( p->pCex, p->pCex->nRegs );
+            memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) );
+            return pCare;
+        }
+        // the problem is SAT - it is expected
+    }
+    // create assumptions
+    vVar2PiId = Vec_IntStartFull( pCnf->nVars );
+    vAssumps = Vec_IntAlloc( Aig_ManCiNum(p->pFrames) );
+    Aig_ManForEachCi( p->pFrames, pObj, i )
+    {
+//        RetValue = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput );
+//        Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !RetValue ) );
+        Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 1 ) );
+        Vec_IntWriteEntry( vVar2PiId, pCnf->pVarNums[Aig_ObjId(pObj)], i );
+    }
+
+    // reverse the order of assumptions
+//    if ( fNewOrder )
+//    Vec_IntReverseOrder( vAssumps );
+
+    if ( fNewOrder )
+    {
+        // create literals
+        vLits = Saig_RefManOrderLiterals( p, vVar2PiId, vAssumps );
+        // sort literals
+        Vec_VecSort( vLits, 1 );
+        // save literals
+        Vec_IntClear( vAssumps );
+        Vec_VecForEachEntryInt( vLits, Entry, i, k )
+            Vec_IntPush( vAssumps, Entry );
+
+        for ( i = 0; i < Vec_VecSize(vLits); i++ )
+            printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) );
+        printf( "\n" );
+
+        if ( p->fVerbose )
+            printf( "Total PIs = %d. Essential PIs = %d.\n", 
+                Saig_ManPiNum(p->pAig) - p->nInputs, Vec_VecSize(vLits) );
+    }
+
+    // solve
+clk = clock();
+    RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), 
+        (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+//Abc_PrintTime( 1, "Solving", clock() - clk );
+    if ( RetValue != l_False )
+    {
+        if ( RetValue == l_True )
+            printf( "Internal Error!!! The resulting problem is SAT.\n" );
+        else
+            printf( "Internal Error!!! SAT solver timed out.\n" );
+        Cnf_DataFree( pCnf );
+        sat_solver_delete( pSat );
+        Vec_IntFree( vAssumps );
+        Vec_IntFree( vVar2PiId );
+        return NULL;
+    }
+    assert( RetValue == l_False ); // UNSAT
+
+    // get relevant SAT literals
+    nCoreLits = sat_solver_final( pSat, &pCoreLits );
+    assert( nCoreLits > 0 );
+    if ( p->fVerbose )
+    printf( "AnalizeFinal selected %d assumptions (out of %d). Conflicts = %d.\n", 
+        nCoreLits, Vec_IntSize(vAssumps), (int)pSat->stats.conflicts );
+
+    // save literals
+    Vec_IntClear( vAssumps );
+    for ( i = 0; i < nCoreLits; i++ )
+        Vec_IntPush( vAssumps, pCoreLits[i] );
+
+
+    // create literals
+    vLits = Saig_RefManOrderLiterals( p, vVar2PiId, vAssumps );
+    // sort literals
+//    Vec_VecSort( vLits, 0 );
+    // save literals
+    Vec_IntClear( vAssumps );
+    Vec_VecForEachEntryInt( vLits, Entry, i, k )
+        Vec_IntPush( vAssumps, Entry );
+
+//    for ( i = 0; i < Vec_VecSize(vLits); i++ )
+//        printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) );
+//    printf( "\n" );
+
+    if ( p->fVerbose )
+        printf( "Total PIs = %d. Essential PIs = %d.\n", 
+            Saig_ManPiNum(p->pAig) - p->nInputs, Vec_VecSize(vLits) );
+/*
+    // try assumptions in different order
+    RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), 
+        (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", 
+        Vec_IntSize(vAssumps), (RetValue == l_False ? "UNSAT" : "SAT"), (int)pSat->stats.conflicts );
+
+    // create different sets of assumptions
+    Counter = Vec_VecSize(vLits);
+    for ( f = 0; f < Vec_VecSize(vLits); f++ )
+    {
+        Vec_IntClear( vAssumps );
+        Vec_VecForEachEntryInt( vLits, Entry, i, k )
+            if ( i != f )
+                Vec_IntPush( vAssumps, Entry );
+
+        // try the new assumptions
+        RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), 
+            (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", 
+            Vec_IntSize(vAssumps), RetValue == l_False ? "UNSAT" : "SAT", (int)pSat->stats.conflicts );
+        if ( RetValue != l_False )
+            continue;
+
+        // UNSAT - remove literals
+        Vec_IntClear( Vec_VecEntryInt(vLits, f) );
+        Counter--;
+    }
+
+    for ( i = 0; i < Vec_VecSize(vLits); i++ )
+        printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) );
+    printf( "\n" );
+
+    if ( p->fVerbose )
+        printf( "Total PIs = %d. Essential PIs = %d.\n", 
+            Saig_ManPiNum(p->pAig) - p->nInputs, Counter );
+
+    // save literals
+    Vec_IntClear( vAssumps );
+    Vec_VecForEachEntryInt( vLits, Entry, i, k )
+        Vec_IntPush( vAssumps, Entry );
+*/
+    // create counter-example
+    pCare = Saig_RefManCreateCex( p, vVar2PiId, vAssumps );
+
+    // cleanup
+    Cnf_DataFree( pCnf );
+    sat_solver_delete( pSat );
+    Vec_IntFree( vAssumps );
+    Vec_IntFree( vVar2PiId );
+    Vec_VecFreeP( &vLits );
+
+    // verify counter-example
+    RetValue = Saig_RefManSetPhases( p, pCare, 0 );
+    if ( RetValue )
+        printf( "Reduced CEX verification has failed.\n" );
+    RetValue = Saig_RefManSetPhases( p, pCare, 1 );
+    if ( RetValue )
+        printf( "Reduced CEX verification has failed.\n" );
+    return pCare;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []               
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_RefManRefineWithSat( Saig_RefMan_t * p, Vec_Int_t * vAigPis )
+{
+    int nConfLimit = 1000000;
+    Cnf_Dat_t * pCnf;
+    sat_solver * pSat;
+    Aig_Obj_t * pObj;
+    Vec_Vec_t * vLits;
+    Vec_Int_t * vReasons, * vAssumps, * vVisited, * vVar2PiId;
+    int i, k, f, Entry, RetValue, Counter;
+
+    // create CNF and SAT solver
+    pCnf = Cnf_DeriveSimple( p->pFrames, 0 );
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+    if ( pSat == NULL )
+    {
+        Cnf_DataFree( pCnf );
+        return NULL;
+    }
+
+    // mark used AIG inputs
+    vVisited = Vec_IntStart( Saig_ManPiNum(p->pAig) );
+    Vec_IntForEachEntry( vAigPis, Entry, i )
+    {
+        assert( Entry >= 0 && Entry < Aig_ManCiNum(p->pAig) );
+        Vec_IntWriteEntry( vVisited, Entry, 1 );
+    }
+
+    // create assumptions
+    vVar2PiId = Vec_IntStartFull( pCnf->nVars );
+    vAssumps = Vec_IntAlloc( Aig_ManCiNum(p->pFrames) );
+    Aig_ManForEachCi( p->pFrames, pObj, i )
+    {
+        int iInput = Vec_IntEntry( p->vMapPiF2A, 2*i );
+        int iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 );
+        if ( Vec_IntEntry(vVisited, iInput) == 0 )
+            continue;
+        RetValue = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput );
+        Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !RetValue ) );
+//        Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 1 ) );
+        Vec_IntWriteEntry( vVar2PiId, pCnf->pVarNums[Aig_ObjId(pObj)], i );
+    }
+    Vec_IntFree( vVisited );
+
+    // try assumptions in different order
+    RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), 
+        (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", 
+        Vec_IntSize(vAssumps), (RetValue == l_False ? "UNSAT" : "SAT"), (int)pSat->stats.conflicts );
+
+/*
+    // AnalizeFinal does not work because it implications propagate directly
+    // and SAT solver does not kick in (the number of conflicts in 0).
+
+    // count the number of lits in the unsat core
+    {
+        int nCoreLits, * pCoreLits;
+        nCoreLits = sat_solver_final( pSat, &pCoreLits );
+        assert( nCoreLits > 0 );
+
+        // count the number of flops
+        vVisited = Vec_IntStart( Saig_ManPiNum(p->pAig) );
+        for ( i = 0; i < nCoreLits; i++ )
+        {
+            int iPiNum = Vec_IntEntry( vVar2PiId, lit_var(pCoreLits[i]) );
+            int iInput = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum );
+            int iFrame = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum+1 );
+            Vec_IntWriteEntry( vVisited, iInput, 1 );
+        }
+        // count the number of entries
+        Counter = 0;
+        Vec_IntForEachEntry( vVisited, Entry, i )
+            Counter += Entry;
+        Vec_IntFree( vVisited );
+
+//        if ( p->fVerbose )
+        printf( "AnalizeFinal: Assumptions %d (out of %d). Essential PIs = %d. Conflicts = %d.\n", 
+            nCoreLits, Vec_IntSize(vAssumps), Counter, (int)pSat->stats.conflicts );
+    }
+*/
+
+    // derive literals
+    vLits = Saig_RefManOrderLiterals( p, vVar2PiId, vAssumps );
+    for ( i = 0; i < Vec_VecSize(vLits); i++ )
+        printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) );
+    printf( "\n" );
+
+    // create different sets of assumptions
+    Counter = Vec_VecSize(vLits);
+    for ( f = 0; f < Vec_VecSize(vLits); f++ )
+    {
+        Vec_IntClear( vAssumps );
+        Vec_VecForEachEntryInt( vLits, Entry, i, k )
+            if ( i != f )
+                Vec_IntPush( vAssumps, Entry );
+
+        // try the new assumptions
+        RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), 
+            (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", 
+            Vec_IntSize(vAssumps), RetValue == l_False ? "UNSAT" : "SAT", (int)pSat->stats.conflicts );
+        if ( RetValue != l_False )
+            continue;
+
+        // UNSAT - remove literals
+        Vec_IntClear( Vec_VecEntryInt(vLits, f) );
+        Counter--;
+    }
+
+    for ( i = 0; i < Vec_VecSize(vLits); i++ )
+        printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) );
+    printf( "\n" );
+
+    // create assumptions
+    Vec_IntClear( vAssumps );
+    Vec_VecForEachEntryInt( vLits, Entry, i, k )
+        Vec_IntPush( vAssumps, Entry );
+
+    // try assumptions in different order
+    RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), 
+        (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", 
+        Vec_IntSize(vAssumps), (RetValue == l_False ? "UNSAT" : "SAT"), (int)pSat->stats.conflicts );
+
+//    if ( p->fVerbose )
+//        printf( "Total PIs = %d. Essential PIs = %d.\n", 
+//            Saig_ManPiNum(p->pAig) - p->nInputs, Counter );
+
+
+    // transform assumptions into reasons
+    vReasons = Vec_IntAlloc( 100 );
+    Vec_IntForEachEntry( vAssumps, Entry, i )
+    {
+        int iPiNum = Vec_IntEntry( vVar2PiId, lit_var(Entry) );
+        assert( iPiNum >= 0 && iPiNum < Aig_ManCiNum(p->pFrames) );
+        Vec_IntPush( vReasons, iPiNum );
+    }
+
+    // cleanup
+    Cnf_DataFree( pCnf );
+    sat_solver_delete( pSat );
+    Vec_IntFree( vAssumps );
+    Vec_IntFree( vVar2PiId );
+    Vec_VecFreeP( &vLits );
+
+    return vReasons;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [SAT-based refinement of the counter-example.]
+
+  Description [The first parameter (nInputs) indicates how many first 
+  primary inputs to skip without considering as care candidates.]
+               
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Saig_ManFindCexCareBits( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, int fNewOrder, int fVerbose )
+{
+    Saig_RefMan_t * p;
+    Vec_Int_t * vReasons;
+    Abc_Cex_t * pCare;
+    clock_t clk = clock();
+
+    clk = clock();
+    p = Saig_RefManStart( pAig, pCex, nInputs, fVerbose );
+    vReasons = Saig_RefManFindReason( p );
+
+if ( fVerbose )
+Aig_ManPrintStats( p->pFrames );
+
+//    if ( fVerbose )
+    {
+        Vec_Int_t * vRes = Saig_RefManReason2Inputs( p, vReasons );
+        printf( "Frame PIs = %4d (essential = %4d)   AIG PIs = %4d (essential = %4d)   ",
+            Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), 
+            Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) );
+ABC_PRT( "Time", clock() - clk );
+
+        Vec_IntFree( vRes );
+
+/*
+        ////////////////////////////////////
+        Vec_IntFree( vReasons );
+        vReasons = Saig_RefManRefineWithSat( p, vRes );
+        ////////////////////////////////////
+
+        Vec_IntFree( vRes );
+        vRes = Saig_RefManReason2Inputs( p, vReasons );
+        printf( "Frame PIs = %4d (essential = %4d)   AIG PIs = %4d (essential = %4d)   ",
+            Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), 
+            Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) );
+
+        Vec_IntFree( vRes );
+ABC_PRT( "Time", clock() - clk );
+*/
+    }
+
+    pCare = Saig_RefManReason2Cex( p, vReasons );
+    Vec_IntFree( vReasons );
+    Saig_RefManStop( p );
+
+if ( fVerbose )
+Abc_CexPrintStats( pCex );
+if ( fVerbose )
+Abc_CexPrintStats( pCare );
+
+    return pCare;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of PIs for flops that should not be absracted.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManExtendCounterExampleTest3( Aig_Man_t * pAig, int iFirstFlopPi, Abc_Cex_t * pCex, int fVerbose )
+{
+    Saig_RefMan_t * p;
+    Vec_Int_t * vRes, * vReasons;
+    clock_t clk;
+    if ( Saig_ManPiNum(pAig) != pCex->nPis )
+    {
+        printf( "Saig_ManExtendCounterExampleTest3(): The PI count of AIG (%d) does not match that of cex (%d).\n", 
+            Aig_ManCiNum(pAig), pCex->nPis );
+        return NULL;
+    }
+
+clk = clock();
+
+    p = Saig_RefManStart( pAig, pCex, iFirstFlopPi, fVerbose );
+    vReasons = Saig_RefManFindReason( p );
+    vRes = Saig_RefManReason2Inputs( p, vReasons );
+
+//    if ( fVerbose )
+    {
+        printf( "Frame PIs = %4d (essential = %4d)   AIG PIs = %4d (essential = %4d)   ",
+            Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), 
+            Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) );
+ABC_PRT( "Time", clock() - clk );
+    }
+
+/*
+    ////////////////////////////////////
+    Vec_IntFree( vReasons );
+    vReasons = Saig_RefManRefineWithSat( p, vRes );
+    ////////////////////////////////////
+
+    // derive new result
+    Vec_IntFree( vRes );
+    vRes = Saig_RefManReason2Inputs( p, vReasons );
+//    if ( fVerbose )
+    {
+        printf( "Frame PIs = %4d (essential = %4d)   AIG PIs = %4d (essential = %4d)   ",
+            Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), 
+            Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) );
+ABC_PRT( "Time", clock() - clk );
+    }
+*/
+
+    Vec_IntFree( vReasons );
+    Saig_RefManStop( p );
+    return vRes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigRetFwd.c b/abc-build/src/aig/saig/saigRetFwd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigRetFwd.c
@@ -0,0 +1,248 @@
+/**CFile****************************************************************
+
+  FileName    [saigRetFwd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Most-forward retiming.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigRetFwd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline Aig_Obj_t * Aig_ObjFanoutStatic( Aig_Obj_t * pObj, int i )               { return ((Aig_Obj_t **)pObj->pData)[i];             }
+static inline void        Aig_ObjSetFanoutStatic( Aig_Obj_t * pObj, Aig_Obj_t * pFan ) { ((Aig_Obj_t **)pObj->pData)[pObj->nRefs++] = pFan; }
+
+#define Aig_ObjForEachFanoutStatic( pObj, pFan, i )                        \
+    for ( i = 0; (i < (int)(pObj)->nRefs) && ((pFan) = Aig_ObjFanoutStatic(pObj, i)); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocate static fanout for all nodes in the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t ** Aig_ManStaticFanoutStart( Aig_Man_t * p )
+{
+    Aig_Obj_t ** ppFanouts, * pObj;
+    int i, nFanouts, nFanoutsAlloc;
+    // allocate fanouts
+    nFanoutsAlloc = 2 * Aig_ManObjNumMax(p) - Aig_ManCiNum(p) - Aig_ManCoNum(p);
+    ppFanouts = ABC_ALLOC( Aig_Obj_t *, nFanoutsAlloc );
+    // mark up storage
+    nFanouts = 0;
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        pObj->pData = ppFanouts + nFanouts;
+        nFanouts += pObj->nRefs;  
+        pObj->nRefs = 0;
+    }
+    assert( nFanouts < nFanoutsAlloc ); 
+    // add fanouts
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( Aig_ObjChild0(pObj) )
+            Aig_ObjSetFanoutStatic( Aig_ObjFanin0(pObj), pObj );
+        if ( Aig_ObjChild1(pObj) )
+            Aig_ObjSetFanoutStatic( Aig_ObjFanin1(pObj), pObj );
+    }
+    return ppFanouts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the objects reachable from the given object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManMarkAutonomous_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pFanout;
+    int i;
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    Aig_ObjForEachFanoutStatic( pObj, pFanout, i )
+        Aig_ManMarkAutonomous_rec( p, pFanout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks with current trav ID nodes reachable from Const1 and PIs.]
+
+  Description [Returns the number of unreachable registers.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManMarkAutonomous( Aig_Man_t * p )
+{
+    Aig_Obj_t ** ppFanouts;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i;
+    // temporarily connect register outputs to register inputs
+    Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
+    {
+        pObjLo->pFanin0 = pObjLi;
+        pObjLi->nRefs = 1;
+    }
+    // mark nodes reachable from Const1 and PIs
+    Aig_ManIncrementTravId( p );
+    ppFanouts = Aig_ManStaticFanoutStart( p );
+    Aig_ManMarkAutonomous_rec( p, Aig_ManConst1(p) );
+    Saig_ManForEachPi( p, pObj, i )
+        Aig_ManMarkAutonomous_rec( p, pObj );
+    ABC_FREE( ppFanouts );
+    // disconnect LIs/LOs and label unreachable registers
+    Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
+    {
+        assert( pObjLo->pFanin0 && pObjLi->nRefs == 1 );
+        pObjLo->pFanin0 = NULL;
+        pObjLi->nRefs = 0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the cut for forward retiming.]
+
+  Description [Assumes topological ordering of the nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManRetimeForwardOne( Aig_Man_t * p, int * pnRegFixed, int * pnRegMoves )
+{
+    Aig_Man_t * pNew;
+    Vec_Ptr_t * vCut;
+    Aig_Obj_t * pObj, * pFanin;
+    int i;
+    // mark the retimable nodes
+    Saig_ManMarkAutonomous( p );
+    // mark the retimable registers with the fresh trav ID
+    Aig_ManIncrementTravId( p );
+    *pnRegFixed = 0;
+    Saig_ManForEachLo( p, pObj, i )
+        if ( Aig_ObjIsTravIdPrevious(p, pObj) )
+            Aig_ObjSetTravIdCurrent(p, pObj);
+        else
+            (*pnRegFixed)++;
+    // mark all the nodes that can be retimed forward
+    *pnRegMoves = 0;
+    Aig_ManForEachNode( p, pObj, i )
+        if ( Aig_ObjIsTravIdCurrent(p, Aig_ObjFanin0(pObj)) && Aig_ObjIsTravIdCurrent(p, Aig_ObjFanin1(pObj)) )
+        {
+            Aig_ObjSetTravIdCurrent(p, pObj);
+            (*pnRegMoves)++;
+        }
+    // mark the remaining registers
+    Saig_ManForEachLo( p, pObj, i )
+        Aig_ObjSetTravIdCurrent(p, pObj);
+    // find the cut (all such marked objects that fanout into unmarked nodes)
+    vCut = Vec_PtrAlloc( 1000 );
+    Aig_ManIncrementTravId( p );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( Aig_ObjIsTravIdPrevious(p, pObj) )
+            continue;
+        pFanin = Aig_ObjFanin0(pObj);
+        if ( pFanin && Aig_ObjIsTravIdPrevious(p, pFanin) )
+        {
+            Vec_PtrPush( vCut, pFanin );
+            Aig_ObjSetTravIdCurrent( p, pFanin );
+        }
+        pFanin = Aig_ObjFanin1(pObj);
+        if ( pFanin && Aig_ObjIsTravIdPrevious(p, pFanin) )
+        {
+            Vec_PtrPush( vCut, pFanin );
+            Aig_ObjSetTravIdCurrent( p, pFanin );
+        }
+    }
+    // finally derive the new manager
+    pNew = Saig_ManRetimeDupForward( p, vCut );
+    Vec_PtrFree( vCut );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the cut for forward retiming.]
+
+  Description [Assumes topological ordering of the nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManRetimeForward( Aig_Man_t * p, int nMaxIters, int fVerbose )
+{
+    Aig_Man_t * pNew, * pTemp;
+    int i, nRegFixed, nRegMoves = 1;
+    abctime clk;
+    pNew = p;
+    for ( i = 0; i < nMaxIters && nRegMoves > 0; i++ )
+    {
+        clk = Abc_Clock();
+        pNew = Saig_ManRetimeForwardOne( pTemp = pNew, &nRegFixed, &nRegMoves );
+        if ( fVerbose )
+        {
+            printf( "%2d : And = %6d. Reg = %5d. Unret = %5d. Move = %6d. ", 
+                i + 1, Aig_ManNodeNum(pTemp), Aig_ManRegNum(pTemp), nRegFixed, nRegMoves );
+            ABC_PRT( "Time", Abc_Clock() - clk );
+        }
+        if ( pTemp != p )
+            Aig_ManStop( pTemp );
+    }
+    clk = Abc_Clock();
+    pNew = Aig_ManReduceLaches( pNew, fVerbose );
+    if ( fVerbose )
+    {
+        ABC_PRT( "Register sharing time", Abc_Clock() - clk );
+    }
+    return pNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigRetMin.c b/abc-build/src/aig/saig/saigRetMin.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigRetMin.c
@@ -0,0 +1,705 @@
+/**CFile****************************************************************
+
+  FileName    [saigRetMin.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Min-area retiming for the AIG.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigRetMin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+#include "opt/nwk/nwk.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver.h"
+#include "sat/bsat/satStore.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the initial state after backward retiming.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManRetimeInitState( Aig_Man_t * p )
+{
+    int nConfLimit = 1000000;
+    Vec_Int_t * vCiIds, * vInit = NULL;
+    Cnf_Dat_t * pCnf;
+    sat_solver * pSat;
+    Aig_Obj_t * pObj;
+    int i, RetValue, * pModel;
+    // solve the SAT problem
+    pCnf = Cnf_DeriveSimpleForRetiming( p );
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+    if ( pSat == NULL )
+    {
+        Cnf_DataFree( pCnf );
+        return NULL;
+    }
+    RetValue = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    assert( RetValue != l_Undef );
+    // create counter-example
+    if ( RetValue == l_True )
+    {
+        // accumulate SAT variables of the CIs
+        vCiIds = Vec_IntAlloc( Aig_ManCiNum(p) );
+        Aig_ManForEachCi( p, pObj, i )
+            Vec_IntPush( vCiIds, pCnf->pVarNums[pObj->Id] );
+        // create the model
+        pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize );
+        vInit = Vec_IntAllocArray( pModel, Aig_ManCiNum(p) );
+        Vec_IntFree( vCiIds );
+    }
+    sat_solver_delete( pSat );
+    Cnf_DataFree( pCnf );
+    return vInit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Uses UNSAT core to find the part of AIG to be excluded.]
+
+  Description [Returns the number of the PO that appears in the UNSAT core.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManRetimeUnsatCore( Aig_Man_t * p, int fVerbose )
+{
+    int fVeryVerbose = 0;
+    int nConfLimit = 1000000;
+    void * pSatCnf = NULL; 
+    Intp_Man_t * pManProof;
+    Vec_Int_t * vCore = NULL;
+    Cnf_Dat_t * pCnf;
+    sat_solver * pSat;
+    Aig_Obj_t * pObj;
+    int * pClause1, * pClause2, * pLit, * pVars;
+    int i, RetValue, iBadPo, iClause, nVars, nPos;
+    // create the SAT solver
+    pCnf = Cnf_DeriveSimpleForRetiming( p );
+    pSat = sat_solver_new();
+    sat_solver_store_alloc( pSat ); 
+    sat_solver_setnvars( pSat, pCnf->nVars );
+    for ( i = 0; i < pCnf->nClauses; i++ )
+    {
+        if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
+        {
+            Cnf_DataFree( pCnf );
+            sat_solver_delete( pSat );
+            return -1;
+        }
+    }
+    sat_solver_store_mark_roots( pSat ); 
+    // solve the problem
+    RetValue = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    assert( RetValue != l_Undef );
+    assert( RetValue == l_False );
+    pSatCnf = sat_solver_store_release( pSat ); 
+    sat_solver_delete( pSat );
+    // derive the UNSAT core
+    pManProof = Intp_ManAlloc();
+    vCore = (Vec_Int_t *)Intp_ManUnsatCore( pManProof, (Sto_Man_t *)pSatCnf, 0, fVeryVerbose );
+    Intp_ManFree( pManProof );
+    Sto_ManFree( (Sto_Man_t *)pSatCnf );
+    // derive the set of variables on which the core depends
+    // collect the variable numbers
+    nVars = 0;
+    pVars = ABC_ALLOC( int, pCnf->nVars );
+    memset( pVars, 0, sizeof(int) * pCnf->nVars );
+    Vec_IntForEachEntry( vCore, iClause, i )
+    {
+        pClause1 = pCnf->pClauses[iClause];
+        pClause2 = pCnf->pClauses[iClause+1];
+        for ( pLit = pClause1; pLit < pClause2; pLit++ )
+        {
+            if ( pVars[ (*pLit) >> 1 ] == 0 )
+                nVars++;
+            pVars[ (*pLit) >> 1 ] = 1;
+            if ( fVeryVerbose )
+            printf( "%s%d ", ((*pLit) & 1)? "-" : "+", (*pLit) >> 1 );
+        }
+        if ( fVeryVerbose )
+        printf( "\n" );
+    }
+    // collect the nodes
+    if ( fVeryVerbose ) {
+      Aig_ManForEachObj( p, pObj, i )
+          if ( pCnf->pVarNums[pObj->Id] >= 0 && pVars[ pCnf->pVarNums[pObj->Id] ] == 1 )
+          {
+              Aig_ObjPrint( p, pObj );
+              printf( "\n" );
+          }
+    }
+    // pick the first PO in the list
+    nPos = 0;
+    iBadPo = -1;
+    Aig_ManForEachCo( p, pObj, i )
+        if ( pCnf->pVarNums[pObj->Id] >= 0 && pVars[ pCnf->pVarNums[pObj->Id] ] == 1 )
+        {
+            if ( iBadPo == -1 )
+                iBadPo = i;
+            nPos++;
+        }
+    if ( fVerbose )
+        printf( "UNSAT core: %d clauses, %d variables, %d POs.  ", Vec_IntSize(vCore), nVars, nPos );
+    ABC_FREE( pVars );
+    Vec_IntFree( vCore );
+    Cnf_DataFree( pCnf );
+    return iBadPo;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the TFI cone with the current traversal ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManMarkCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    if ( pObj == NULL )
+        return;
+    if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
+        return;
+    Aig_ObjSetTravIdCurrent( p, pObj );
+    Saig_ManMarkCone_rec( p, Aig_ObjFanin0(pObj) );
+    Saig_ManMarkCone_rec( p, Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of nodes to get registers after retiming.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManRetimeCountCut( Aig_Man_t * p, Vec_Ptr_t * vCut )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj, * pFanin;
+    int i, RetValue;
+    // mark the cones
+    Aig_ManIncrementTravId( p );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i )
+        Saig_ManMarkCone_rec( p, pObj );
+    // collect the new cut
+    vNodes = Vec_PtrAlloc( 1000 );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+            continue;
+        pFanin = Aig_ObjFanin0( pObj );
+        if ( pFanin && !pFanin->fMarkA && Aig_ObjIsTravIdCurrent(p, pFanin) )
+        {
+            Vec_PtrPush( vNodes, pFanin );
+            pFanin->fMarkA = 1;
+        }
+        pFanin = Aig_ObjFanin1( pObj );
+        if ( pFanin && !pFanin->fMarkA && Aig_ObjIsTravIdCurrent(p, pFanin) )
+        {
+            Vec_PtrPush( vNodes, pFanin );
+            pFanin->fMarkA = 1;
+        }
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        pObj->fMarkA = 0;
+    RetValue = Vec_PtrSize( vNodes );
+    Vec_PtrFree( vNodes );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG recursively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManRetimeDup_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj )
+{
+    if ( pObj->pData )
+        return;
+    assert( Aig_ObjIsNode(pObj) );
+    Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) );
+    Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin1(pObj) );
+    pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG while retiming the registers to the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManRetimeDupForward( Aig_Man_t * p, Vec_Ptr_t * vCut )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i;
+    // mark the cones under the cut
+//    assert( Vec_PtrSize(vCut) == Saig_ManRetimeCountCut(p, vCut) );
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nRegs = Vec_PtrSize(vCut);
+    pNew->nTruePis = p->nTruePis;
+    pNew->nTruePos = p->nTruePos;
+    // create the true PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Saig_ManForEachPi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    // create the registers
+    Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i )
+        pObj->pData = Aig_NotCond( Aig_ObjCreateCi(pNew), pObj->fPhase );
+    // duplicate logic above the cut
+    Aig_ManForEachCo( p, pObj, i )
+        Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) );
+    // create the true POs
+    Saig_ManForEachPo( p, pObj, i )
+        Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    // remember value in LI
+    Saig_ManForEachLi( p, pObj, i )
+        pObj->pData = Aig_ObjChild0Copy(pObj);
+    // transfer values from the LIs to the LOs
+    Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
+        pObjLo->pData = pObjLi->pData;
+    // erase the data values on the internal nodes of the cut
+    Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i )
+        if ( Aig_ObjIsNode(pObj) )
+            pObj->pData = NULL;
+    // duplicate logic below the cut
+    Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i )
+    {
+        Saig_ManRetimeDup_rec( pNew, pObj );
+        Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)pObj->pData, pObj->fPhase) );
+    }
+    Aig_ManCleanup( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG while retiming the registers to the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManRetimeDupBackward( Aig_Man_t * p, Vec_Ptr_t * vCut, Vec_Int_t * vInit )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i;
+    // mark the cones under the cut
+//    assert( Vec_PtrSize(vCut) == Saig_ManRetimeCountCut(p, vCut) );
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nRegs = Vec_PtrSize(vCut);
+    pNew->nTruePis = p->nTruePis;
+    pNew->nTruePos = p->nTruePos;
+    // create the true PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Saig_ManForEachPi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    // create the registers
+    Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i )
+        pObj->pData = Aig_NotCond( Aig_ObjCreateCi(pNew), vInit?Vec_IntEntry(vInit,i):0 );
+    // duplicate logic above the cut and remember values
+    Saig_ManForEachLi( p, pObj, i )
+    {
+        Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) );
+        pObj->pData = Aig_ObjChild0Copy(pObj);
+    }
+    // transfer values from the LIs to the LOs
+    Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
+        pObjLo->pData = pObjLi->pData;
+    // erase the data values on the internal nodes of the cut
+    Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i )
+        if ( Aig_ObjIsNode(pObj) )
+            pObj->pData = NULL;
+    // replicate the data on the constant node and the PIs
+    pObj = Aig_ManConst1(p);
+    pObj->pData = Aig_ManConst1(pNew);
+    Saig_ManForEachPi( p, pObj, i )
+        pObj->pData = Aig_ManCi( pNew, i );
+    // duplicate logic below the cut
+    Saig_ManForEachPo( p, pObj, i )
+    {
+        Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) );
+        Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i )
+    {
+        Saig_ManRetimeDup_rec( pNew, pObj );
+        Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)pObj->pData, vInit?Vec_IntEntry(vInit,i):0) );
+    }
+    Aig_ManCleanup( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives AIG for the initial state computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManRetimeDupInitState( Aig_Man_t * p, Vec_Ptr_t * vCut )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    // mark the cones under the cut
+//    assert( Vec_PtrSize(vCut) == Saig_ManRetimeCountCut(p, vCut) );
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    // create the true PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    // create the registers
+    Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i )
+        pObj->pData = Aig_ObjCreateCi(pNew);
+    // duplicate logic above the cut and create POs
+    Saig_ManForEachLi( p, pObj, i )
+    {
+        Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) );
+        Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    }
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of bad registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_ManGetRegistersToExclude( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj, * pFanin;
+    int i, Diffs;
+    assert( Saig_ManRegNum(p) > 0 );
+    Saig_ManForEachLi( p, pObj, i )
+    {
+        pFanin = Aig_ObjFanin0(pObj);
+        if ( !Aig_ObjFaninC0(pObj) )
+            pFanin->fMarkA = 1;
+        else
+            pFanin->fMarkB = 1;
+    }
+    Diffs = 0;
+    Saig_ManForEachLi( p, pObj, i )
+    {
+        pFanin = Aig_ObjFanin0(pObj);
+        Diffs += pFanin->fMarkA && pFanin->fMarkB;
+    }
+    vNodes = Vec_PtrAlloc( 100 );
+    if ( Diffs > 0 )
+    {
+        Saig_ManForEachLi( p, pObj, i )
+        {
+            pFanin = Aig_ObjFanin0(pObj);
+            if ( pFanin->fMarkA && pFanin->fMarkB )
+                Vec_PtrPush( vNodes, pObj );
+        }
+        assert( Vec_PtrSize(vNodes) == Diffs );
+    }
+    Saig_ManForEachLi( p, pObj, i )
+    {
+        pFanin = Aig_ObjFanin0(pObj);
+        pFanin->fMarkA = pFanin->fMarkB = 0;
+    }
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Hides the registers that cannot be backward retimed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManHideBadRegs( Aig_Man_t * p, Vec_Ptr_t * vBadRegs )
+{
+    Vec_Ptr_t * vPisNew, * vPosNew;
+    Aig_Obj_t * pObjLi, * pObjLo;
+    int nTruePi, nTruePo, nBadRegs, i;
+    if ( Vec_PtrSize(vBadRegs) == 0 )
+        return 0;
+    // attached LOs to LIs
+    Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
+        pObjLi->pData = pObjLo;
+    // reorder them by putting bad registers first
+    vPisNew = Vec_PtrDup( p->vCis );
+    vPosNew = Vec_PtrDup( p->vCos );
+    nTruePi = Aig_ManCiNum(p) - Aig_ManRegNum(p);
+    nTruePo = Aig_ManCoNum(p) - Aig_ManRegNum(p);
+    assert( nTruePi == p->nTruePis );
+    assert( nTruePo == p->nTruePos );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vBadRegs, pObjLi, i )
+    {
+        Vec_PtrWriteEntry( vPisNew, nTruePi++, pObjLi->pData );
+        Vec_PtrWriteEntry( vPosNew, nTruePo++, pObjLi );
+        pObjLi->fMarkA = 1;
+    }
+    Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
+    {
+        if ( pObjLi->fMarkA )
+        {
+            pObjLi->fMarkA = 0;
+            continue;
+        }
+        Vec_PtrWriteEntry( vPisNew, nTruePi++, pObjLo );
+        Vec_PtrWriteEntry( vPosNew, nTruePo++, pObjLi );
+    }
+    // check the sizes
+    assert( nTruePi == Aig_ManCiNum(p) );
+    assert( nTruePo == Aig_ManCoNum(p) );
+    // transfer the arrays
+    Vec_PtrFree( p->vCis ); p->vCis = vPisNew;
+    Vec_PtrFree( p->vCos ); p->vCos = vPosNew;
+    // update the PIs
+    nBadRegs = Vec_PtrSize(vBadRegs);
+    p->nRegs -= nBadRegs;
+    p->nTruePis += nBadRegs;
+    p->nTruePos += nBadRegs;
+    return nBadRegs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Exposes bad registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManExposeBadRegs( Aig_Man_t * p, int nBadRegs )
+{
+    p->nRegs += nBadRegs;
+    p->nTruePis -= nBadRegs;
+    p->nTruePos -= nBadRegs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs min-area retiming backward with initial state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManRetimeMinAreaBackward( Aig_Man_t * pNew, int fVerbose )
+{
+    Aig_Man_t * pInit, * pFinal;
+    Vec_Ptr_t * vBadRegs, * vCut;
+    Vec_Int_t * vInit;
+    int iBadReg;
+    // transform the AIG to have no bad registers
+    vBadRegs = Saig_ManGetRegistersToExclude( pNew );
+    if ( fVerbose && Vec_PtrSize(vBadRegs) )
+        printf( "Excluding %d registers that cannot be backward retimed.\n", Vec_PtrSize(vBadRegs) ); 
+    while ( 1 )
+    {
+        Saig_ManHideBadRegs( pNew, vBadRegs );
+        Vec_PtrFree( vBadRegs );
+        // compute cut
+        vCut = Nwk_ManDeriveRetimingCut( pNew, 0, fVerbose );
+        if ( Vec_PtrSize(vCut) >= Aig_ManRegNum(pNew) )
+        {
+            Vec_PtrFree( vCut );
+            return NULL;
+        }
+        // derive the initial state
+        pInit = Saig_ManRetimeDupInitState( pNew, vCut );
+        vInit = Saig_ManRetimeInitState( pInit );
+        if ( vInit != NULL )
+        {
+            pFinal = Saig_ManRetimeDupBackward( pNew, vCut, vInit );
+            Vec_IntFree( vInit );
+            Vec_PtrFree( vCut );
+            Aig_ManStop( pInit );
+            return pFinal;
+        }
+        Vec_PtrFree( vCut );
+        // there is no initial state - find the offending output
+        iBadReg = Saig_ManRetimeUnsatCore( pInit, fVerbose );
+        Aig_ManStop( pInit );
+        if ( fVerbose )
+            printf( "Excluding register %d.\n", iBadReg ); 
+        // prepare to remove this output
+        vBadRegs = Vec_PtrAlloc( 1 );
+        Vec_PtrPush( vBadRegs, Aig_ManCo( pNew, Saig_ManPoNum(pNew) + iBadReg ) );
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs min-area retiming.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose )
+{
+    Vec_Ptr_t * vCut;
+    Aig_Man_t * pNew, * pTemp, * pCopy;
+    int i, fChanges;
+    pNew = Aig_ManDupSimple( p );
+    // perform several iterations of forward retiming
+    fChanges = 0;
+    if ( !fBackwardOnly )
+    for ( i = 0; i < nMaxIters; i++ )
+    {
+        if ( Saig_ManRegNum(pNew) == 0 )
+            break;
+        vCut = Nwk_ManDeriveRetimingCut( pNew, 1, fVerbose );
+        if ( Vec_PtrSize(vCut) >= Aig_ManRegNum(pNew) )
+        {
+            if ( fVerbose && !fChanges )
+                printf( "Forward retiming cannot reduce registers.\n" );
+            Vec_PtrFree( vCut );
+            break;
+        }
+        pNew = Saig_ManRetimeDupForward( pTemp = pNew, vCut );
+        Aig_ManStop( pTemp );
+        Vec_PtrFree( vCut );
+        if ( fVerbose )
+            Aig_ManReportImprovement( p, pNew );
+        fChanges = 1;
+    }
+    // perform several iterations of backward retiming
+    fChanges = 0;
+    if ( !fForwardOnly && !fInitial )
+    for ( i = 0; i < nMaxIters; i++ )
+    {
+        if ( Saig_ManRegNum(pNew) == 0 )
+            break;
+        vCut = Nwk_ManDeriveRetimingCut( pNew, 0, fVerbose );
+        if ( Vec_PtrSize(vCut) >= Aig_ManRegNum(pNew) )
+        {
+            if ( fVerbose && !fChanges )
+                printf( "Backward retiming cannot reduce registers.\n" );
+            Vec_PtrFree( vCut );
+            break;
+        }
+        pNew = Saig_ManRetimeDupBackward( pTemp = pNew, vCut, NULL );
+        Aig_ManStop( pTemp );
+        Vec_PtrFree( vCut );
+        if ( fVerbose )
+            Aig_ManReportImprovement( p, pNew );
+        fChanges = 1;
+    }
+    else if ( !fForwardOnly && fInitial )
+    for ( i = 0; i < nMaxIters; i++ )
+    {
+        if ( Saig_ManRegNum(pNew) == 0 )
+            break;
+        pCopy = Aig_ManDupSimple( pNew );
+        pTemp = Saig_ManRetimeMinAreaBackward( pCopy, fVerbose );
+        Aig_ManStop( pCopy );
+        if ( pTemp == NULL )
+        {
+            if ( fVerbose && !fChanges )
+                printf( "Backward retiming cannot reduce registers.\n" );
+            break;
+        }
+        Saig_ManExposeBadRegs( pTemp, Saig_ManPoNum(pTemp) - Saig_ManPoNum(pNew) );
+        Aig_ManStop( pNew );
+        pNew = pTemp;
+        if ( fVerbose )
+            Aig_ManReportImprovement( p, pNew );
+        fChanges = 1;
+    }
+    if ( !fForwardOnly && !fInitial && fChanges )
+        printf( "Assuming const-0 init-state after backward retiming. Result will not verify.\n" );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigRetStep.c b/abc-build/src/aig/saig/saigRetStep.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigRetStep.c
@@ -0,0 +1,236 @@
+/**CFile****************************************************************
+
+  FileName    [saigRetStep.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Implementation of retiming steps.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigRetStep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one retiming step forward.]
+
+  Description [Returns the pointer to the register output after retiming.]
+               
+  SideEffects [Remember to run Aig_ManSetCioIds() in advance.]
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Saig_ManRetimeNodeFwd( Aig_Man_t * p, Aig_Obj_t * pObj, int fMakeBug )
+{
+    Aig_Obj_t * pFanin0, * pFanin1;
+    Aig_Obj_t * pInput0, * pInput1;
+    Aig_Obj_t * pObjNew, * pObjLi, * pObjLo;
+    int fCompl;
+
+    assert( Saig_ManRegNum(p) > 0 );
+    assert( Aig_ObjIsNode(pObj) );
+
+    // get the fanins
+    pFanin0 = Aig_ObjFanin0(pObj);
+    pFanin1 = Aig_ObjFanin1(pObj);
+    // skip of they are not primary inputs
+    if ( !Aig_ObjIsCi(pFanin0) || !Aig_ObjIsCi(pFanin1) )
+        return NULL;
+
+    // skip of they are not register outputs
+    if ( !Saig_ObjIsLo(p, pFanin0) || !Saig_ObjIsLo(p, pFanin1) )
+        return NULL;
+    assert( Aig_ObjCioId(pFanin0) > 0 );
+    assert( Aig_ObjCioId(pFanin1) > 0 );
+
+    // skip latch guns
+    if ( !Aig_ObjIsTravIdCurrent(p, pFanin0) && !Aig_ObjIsTravIdCurrent(p, pFanin1) )
+        return NULL;
+
+    // get the inputs of these registers
+    pInput0 = Saig_ManLi( p, Aig_ObjCioId(pFanin0) - Saig_ManPiNum(p) );
+    pInput1 = Saig_ManLi( p, Aig_ObjCioId(pFanin1) - Saig_ManPiNum(p) );
+    pInput0 = Aig_ObjChild0( pInput0 );
+    pInput1 = Aig_ObjChild0( pInput1 );
+    pInput0 = Aig_NotCond( pInput0, Aig_ObjFaninC0(pObj) );
+    pInput1 = Aig_NotCond( pInput1, Aig_ObjFaninC1(pObj) );
+    // get the condition when the register should be complemetned
+    fCompl = Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj);
+
+    if ( fMakeBug )
+    {
+        printf( "Introducing bug during retiming.\n" );
+        pInput1 = Aig_Not( pInput1 );
+    }
+
+    // create new node
+    pObjNew = Aig_And( p, pInput0, pInput1 );
+
+    // create new register input
+    pObjLi = Aig_ObjCreateCo( p, Aig_NotCond(pObjNew, fCompl) );
+    pObjLi->CioId = Aig_ManCoNum(p) - 1;
+
+    // create new register output
+    pObjLo = Aig_ObjCreateCi( p );
+    pObjLo->CioId = Aig_ManCiNum(p) - 1;
+    p->nRegs++;
+
+    // make sure the register is retimable.
+    Aig_ObjSetTravIdCurrent(p, pObjLo);
+
+//printf( "Reg = %4d. Reg = %4d. Compl = %d. Phase = %d.\n", 
+//       pFanin0->PioNum, pFanin1->PioNum, Aig_IsComplement(pObjNew), fCompl );
+
+    // return register output
+    return Aig_NotCond( pObjLo, fCompl );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one retiming step backward.]
+
+  Description [Returns the pointer to node after retiming.]
+               
+  SideEffects [Remember to run Aig_ManSetCioIds() in advance.]
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Saig_ManRetimeNodeBwd( Aig_Man_t * p, Aig_Obj_t * pObjLo )
+{
+    Aig_Obj_t * pFanin0, * pFanin1;
+    Aig_Obj_t * pLo0New, * pLo1New;
+    Aig_Obj_t * pLi0New, * pLi1New;
+    Aig_Obj_t * pObj, * pObjNew, * pObjLi;
+    int fCompl0, fCompl1;
+
+    assert( Saig_ManRegNum(p) > 0 );
+    assert( Aig_ObjCioId(pObjLo) > 0 );
+    assert( Saig_ObjIsLo(p, pObjLo) );
+
+    // get the corresponding latch input
+    pObjLi = Saig_ManLi( p, Aig_ObjCioId(pObjLo) - Saig_ManPiNum(p) );
+
+    // get the node
+    pObj = Aig_ObjFanin0(pObjLi);
+    if ( !Aig_ObjIsNode(pObj) )
+        return NULL;
+
+    // get the fanins
+    pFanin0 = Aig_ObjFanin0(pObj);
+    pFanin1 = Aig_ObjFanin1(pObj);
+
+    // get the complemented attributes of the fanins
+    fCompl0 = Aig_ObjFaninC0(pObj) ^ Aig_ObjFaninC0(pObjLi);
+    fCompl1 = Aig_ObjFaninC1(pObj) ^ Aig_ObjFaninC0(pObjLi);
+
+    // create latch inputs
+    pLi0New = Aig_ObjCreateCo( p, Aig_NotCond(pFanin0, fCompl0) );
+    pLi0New->CioId = Aig_ManCoNum(p) - 1;
+    pLi1New = Aig_ObjCreateCo( p, Aig_NotCond(pFanin1, fCompl1) );
+    pLi1New->CioId = Aig_ManCoNum(p) - 1;
+
+    // create latch outputs
+    pLo0New = Aig_ObjCreateCi(p);
+    pLo0New->CioId = Aig_ManCiNum(p) - 1;
+    pLo1New = Aig_ObjCreateCi(p);
+    pLo1New->CioId = Aig_ManCiNum(p) - 1;
+    pLo0New = Aig_NotCond( pLo0New, fCompl0 );
+    pLo1New = Aig_NotCond( pLo1New, fCompl1 );
+    p->nRegs += 2;
+
+    // create node
+    pObjNew = Aig_And( p, pLo0New, pLo1New );
+//    assert( pObjNew->fPhase == 0 );
+    return pObjNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs the given number of retiming steps.]
+
+  Description [Returns the pointer to node after retiming.]
+               
+  SideEffects [Remember to run Aig_ManSetCioIds() in advance.]
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManRetimeSteps( Aig_Man_t * p, int nSteps, int fForward, int fAddBugs )
+{
+    Aig_Obj_t * pObj, * pObjNew;
+    int RetValue, s, i;
+    Aig_ManSetCioIds( p );
+    Aig_ManFanoutStart( p );
+    p->fCreatePios = 1;
+    if ( fForward )
+    {
+        Saig_ManMarkAutonomous( p );
+        for ( s = 0; s < nSteps; s++ )
+        {
+            Aig_ManForEachNode( p, pObj, i )
+            {
+                pObjNew = Saig_ManRetimeNodeFwd( p, pObj, fAddBugs && (s == 10) );
+//                pObjNew = Saig_ManRetimeNodeFwd( p, pObj, 0 );
+                if ( pObjNew == NULL )
+                    continue;
+                Aig_ObjReplace( p, pObj, pObjNew, 0 );
+                break;
+            }
+            if ( i == Vec_PtrSize(p->vObjs) )
+                break;
+        }
+    }
+    else
+    {
+        for ( s = 0; s < nSteps; s++ )
+        {
+            Saig_ManForEachLo( p, pObj, i )
+            {
+                pObjNew = Saig_ManRetimeNodeBwd( p, pObj );
+                if ( pObjNew == NULL )
+                    continue;
+                Aig_ObjReplace( p, pObj, pObjNew, 0 );
+                break;
+            }
+            if ( i == Vec_PtrSize(p->vObjs) )
+                break;
+        }
+    }
+    p->fCreatePios = 0;
+    Aig_ManFanoutStop( p );
+    RetValue = Aig_ManCleanup( p );
+    assert( RetValue == 0 );
+    Aig_ManSetRegNum( p, p->nRegs ); 
+    return s;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigScl.c b/abc-build/src/aig/saig/saigScl.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigScl.c
@@ -0,0 +1,115 @@
+/**CFile****************************************************************
+
+  FileName    [saigScl.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Sequential cleanup.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigScl.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Report registers useless for SEC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManReportUselessRegisters( Aig_Man_t * pAig )
+{
+    Aig_Obj_t * pObj, * pDriver;
+    int i, Counter1, Counter2;
+    // set PIO numbers
+    Aig_ManSetCioIds( pAig );
+    // check how many POs are driven by a register whose ref count is 1
+    Counter1 = 0;
+    Saig_ManForEachPo( pAig, pObj, i )
+    {
+        pDriver = Aig_ObjFanin0(pObj);
+        if ( Saig_ObjIsLo(pAig, pDriver) && Aig_ObjRefs(pDriver) == 1 )
+            Counter1++;
+    }
+    // check how many PIs have ref count 1 and drive a register
+    Counter2 = 0;
+    Saig_ManForEachLi( pAig, pObj, i )
+    {
+        pDriver = Aig_ObjFanin0(pObj);
+        if ( Saig_ObjIsPi(pAig, pDriver) && Aig_ObjRefs(pDriver) == 1 )
+            Counter2++;
+    }
+    if ( Counter1 )
+        printf( "Network has %d (out of %d) registers driving POs.\n", Counter1, Saig_ManRegNum(pAig) );
+    if ( Counter2 )
+        printf( "Network has %d (out of %d) registers driven by PIs.\n", Counter2, Saig_ManRegNum(pAig) );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Report the number of pairs of complemented registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManReportComplements( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pFanin;
+    int i, Counter = 0;
+    assert( Aig_ManRegNum(p) > 0 );
+    Aig_ManForEachObj( p, pObj, i )
+        assert( !pObj->fMarkA );
+    Aig_ManForEachLiSeq( p, pObj, i )
+    {
+        pFanin = Aig_ObjFanin0(pObj);
+        if ( pFanin->fMarkA )
+            Counter++;
+        else
+            pFanin->fMarkA = 1;
+    }
+    // count fanins that have both attributes
+    Aig_ManForEachLiSeq( p, pObj, i )
+    {
+        pFanin = Aig_ObjFanin0(pObj);
+        pFanin->fMarkA = 0;
+    }
+    return Counter;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigSimFast.c b/abc-build/src/aig/saig/saigSimFast.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigSimFast.c
@@ -0,0 +1,451 @@
+/**CFile****************************************************************
+
+  FileName    [saigSimFast.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Fast sequential AIG simulator.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigSimFast.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// the AIG manager
+typedef struct Faig_Man_t_ Faig_Man_t;
+struct Faig_Man_t_
+{
+    // parameters
+    int            nPis;
+    int            nPos;
+    int            nCis;
+    int            nCos;
+    int            nFfs;
+    int            nNos;
+    // offsets
+    int            nPis1;
+    int            nCis1;
+    int            nCisNos1;
+    int            nCisNosPos1;
+    int            nObjs;
+    // allocated data
+    int            nWords;
+    int            pObjs[0];
+};
+
+static inline int  Faig_CheckIdPi( Faig_Man_t * p, int i )    { return i >= 1 && i < p->nPis1;                     }
+static inline int  Faig_CheckIdLo( Faig_Man_t * p, int i )    { return i >= p->nPis1 && i < p->nCis1;              }
+static inline int  Faig_CheckIdNo( Faig_Man_t * p, int i )    { return i >= p->nCis1 && i < p->nCisNos1;           }
+static inline int  Faig_CheckIdPo( Faig_Man_t * p, int i )    { return i >= p->nCisNos1 && i < p->nCisNosPos1;     }
+static inline int  Faig_CheckIdLi( Faig_Man_t * p, int i )    { return i >= p->nCisNosPos1 && i < p->nObjs;        }
+static inline int  Faig_CheckIdCo( Faig_Man_t * p, int i )    { return i >= p->nCisNos1 && i < p->nObjs;           }
+static inline int  Faig_CheckIdObj( Faig_Man_t * p, int i )   { return i >= 0 && i < p->nObjs;                     }
+
+static inline int  Faig_ObjIdToNumPi( Faig_Man_t * p, int i ) { assert( Faig_CheckIdPi(p,i) ); return i - 1;              }
+static inline int  Faig_ObjIdToNumLo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLo(p,i) ); return i - p->nPis1;       }
+static inline int  Faig_ObjIdToNumNo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdNo(p,i) ); return i - p->nCis1;       }
+static inline int  Faig_ObjIdToNumPo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdPo(p,i) ); return i - p->nCisNos1;    }
+static inline int  Faig_ObjIdToNumLi( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLi(p,i) ); return i - p->nCisNosPos1; }
+static inline int  Faig_ObjIdToNumCo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdCo(p,i) ); return i - p->nCisNos1;    }
+
+static inline int  Faig_ObjLoToLi( Faig_Man_t * p, int i )    { assert( Faig_CheckIdLo(p,i) ); return p->nObjs - (p->nCis1 - i); }
+static inline int  Faig_ObjLiToLo( Faig_Man_t * p, int i )    { assert( Faig_CheckIdLi(p,i) ); return p->nCis1 - (p->nObjs - i); }
+
+static inline int  Faig_NodeChild0( Faig_Man_t * p, int n )   { return p->pObjs[n<<1];             }
+static inline int  Faig_NodeChild1( Faig_Man_t * p, int n )   { return p->pObjs[(n<<1)+1];         }
+static inline int  Faig_CoChild0( Faig_Man_t * p, int n )     { return p->pObjs[(p->nNos<<1)+n];   }
+static inline int  Faig_ObjFaninC( int iFan )                 { return iFan & 1;                   }
+static inline int  Faig_ObjFanin( int iFan )                  { return iFan >> 1;                  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the manager is correct.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Faig_ManIsCorrect( Aig_Man_t * pAig )
+{
+    return Aig_ManObjNumMax(pAig) == 
+        1 + Aig_ManCiNum(pAig) + Aig_ManNodeNum(pAig) + Aig_ManCoNum(pAig);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates fast simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Faig_Man_t * Faig_ManAlloc( Aig_Man_t * pAig )
+{
+    Faig_Man_t * p;
+    int nWords;
+//    assert( Faig_ManIsCorrect(pAig) );
+    nWords = 2 * Aig_ManNodeNum(pAig) + Aig_ManCoNum(pAig);
+    p = (Faig_Man_t *)ABC_ALLOC( char, sizeof(Faig_Man_t) + sizeof(int) * nWords );
+//printf( "Allocating %7.2f MB.\n", 1.0 * (sizeof(Faig_Man_t) + sizeof(int) * nWords)/(1<<20) );
+    memset( p, 0, sizeof(Faig_Man_t) );
+    p->nPis   = Aig_ManCiNum(pAig) - Aig_ManRegNum(pAig);
+    p->nPos   = Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig);
+    p->nCis   = Aig_ManCiNum(pAig);
+    p->nCos   = Aig_ManCoNum(pAig);
+    p->nFfs   = Aig_ManRegNum(pAig);
+    p->nNos   = Aig_ManNodeNum(pAig);
+    // offsets
+    p->nPis1  = p->nPis + 1;
+    p->nCis1  = p->nCis + 1;
+    p->nCisNos1 = p->nCis + p->nNos + 1;
+    p->nCisNosPos1 = p->nCis + p->nNos + p->nPos + 1;
+    p->nObjs  = p->nCis + p->nNos + p->nCos + 1;
+    p->nWords = nWords;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates fast simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Faig_Man_t * Faig_ManCreate( Aig_Man_t * pAig )
+{
+    Faig_Man_t * p;
+    Aig_Obj_t * pObj;
+    int i, iWord = 0;
+    p = Faig_ManAlloc( pAig );
+    Aig_ManForEachNode( pAig, pObj, i )
+    {
+        p->pObjs[iWord++] = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj);
+        p->pObjs[iWord++] = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj);
+    }
+    Aig_ManForEachCo( pAig, pObj, i )
+        p->pObjs[iWord++] = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj);
+    assert( iWord == p->nWords );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Faig_SimulateNode( Faig_Man_t * p, int Id, unsigned * pSimInfo )
+{
+    int n = Faig_ObjIdToNumNo( p, Id );
+    int iFan0 = Faig_NodeChild0( p, n );
+    int iFan1 = Faig_NodeChild1( p, n );
+    if ( Faig_ObjFaninC(iFan0) && Faig_ObjFaninC(iFan1) )
+        return ~(pSimInfo[Faig_ObjFanin(iFan0)] | pSimInfo[Faig_ObjFanin(iFan1)]);
+    if ( Faig_ObjFaninC(iFan0) && !Faig_ObjFaninC(iFan1) )
+        return (~pSimInfo[Faig_ObjFanin(iFan0)] & pSimInfo[Faig_ObjFanin(iFan1)]);
+    if ( !Faig_ObjFaninC(iFan0) && Faig_ObjFaninC(iFan1) )
+        return (pSimInfo[Faig_ObjFanin(iFan0)] & ~pSimInfo[Faig_ObjFanin(iFan1)]);
+    // if ( !Faig_ObjFaninC(iFan0) && !Faig_ObjFaninC(iFan1) )
+    return (pSimInfo[Faig_ObjFanin(iFan0)] & pSimInfo[Faig_ObjFanin(iFan1)]);
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Faig_SimulateCo( Faig_Man_t * p, int Id, unsigned * pSimInfo )
+{
+    int n = Faig_ObjIdToNumCo( p, Id );
+    int iFan0 = Faig_CoChild0( p, n );
+    if ( Faig_ObjFaninC(iFan0) )
+        return ~pSimInfo[Faig_ObjFanin(iFan0)];
+    // if ( !Faig_ObjFaninC(iFan0) )
+    return pSimInfo[Faig_ObjFanin(iFan0)];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Faig_SimulateRandomShift( unsigned uOld )
+{
+    return (uOld << 16) | ((uOld ^ Aig_ManRandom(0)) & 0xffff);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Faig_SimulateTransferShift( unsigned uOld, unsigned uNew )
+{
+    return (uOld << 16) | (uNew & 0xffff);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates the timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Faig_ManSimulateFrames( Faig_Man_t * p, int nFrames, int nPref, int fTrans )
+{
+    int * pNumOnes = ABC_CALLOC( int, p->nObjs );
+    unsigned * pSimInfo = ABC_ALLOC( unsigned, p->nObjs );
+    int f, i;
+//printf( "Allocating %7.2f MB.\n", 1.0 * 4 * p->nObjs/(1<<20) );
+//printf( "Allocating %7.2f MB.\n", 1.0 * 4 * p->nObjs/(1<<20) );
+    // set constant 1
+    pSimInfo[0] = ~0;
+    for ( f = 0; f < nFrames; f++ )
+    {
+        if ( fTrans )
+        {
+            for ( i = 1; i < p->nPis1; i++ )
+                pSimInfo[i] = f? Faig_SimulateRandomShift( pSimInfo[i] ) : Aig_ManRandom( 0 );
+            for (      ; i < p->nCis1; i++ )
+                pSimInfo[i] = f? Faig_SimulateTransferShift( pSimInfo[i], pSimInfo[Faig_ObjLoToLi(p,i)] ) : 0;
+        }
+        else
+        {
+            for ( i = 1; i < p->nPis1; i++ )
+                pSimInfo[i] = Aig_ManRandom( 0 );
+            for (      ; i < p->nCis1; i++ )
+                pSimInfo[i] = f? pSimInfo[Faig_ObjLoToLi(p,i)] : 0;
+        }
+        for (      ; i < p->nCisNos1; i++ )
+            pSimInfo[i] = Faig_SimulateNode( p, i, pSimInfo );
+        for (      ; i < p->nObjs; i++ )
+            pSimInfo[i] = Faig_SimulateCo( p, i, pSimInfo );
+        if ( f < nPref )
+            continue;
+        if ( fTrans )
+        {
+            for ( i = 0; i < p->nObjs; i++ )
+                pNumOnes[i] += Aig_WordCountOnes( (pSimInfo[i] ^ (pSimInfo[i] >> 16)) & 0xffff );
+        }
+        else
+        {
+            for ( i = 0; i < p->nObjs; i++ )
+                pNumOnes[i] += Aig_WordCountOnes( pSimInfo[i] );
+        }
+    }
+    ABC_FREE( pSimInfo );
+    return pNumOnes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes switching activity of one node.]
+
+  Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Faig_ManComputeSwitching( int nOnes, int nSimWords )
+{
+    int nTotal = 32 * nSimWords;
+    return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes switching activity of one node.]
+
+  Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Faig_ManComputeProbOne( int nOnes, int nSimWords )
+{
+    int nTotal = 32 * nSimWords;
+    return (float)nOnes / nTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Faig_ManComputeSwitchProbs4( Aig_Man_t * p, int nFrames, int nPref, int fProbOne )
+{
+    int fTrans = 1;
+    Faig_Man_t * pAig;
+    Vec_Int_t * vSwitching;
+    int * pProbs;
+    float * pSwitching;
+    int nFramesReal;
+    abctime clk;//, clkTotal = Abc_Clock();
+    if ( fProbOne )
+        fTrans = 0;
+    vSwitching = Vec_IntStart( Aig_ManObjNumMax(p) );
+    pSwitching = (float *)vSwitching->pArray;
+clk = Abc_Clock();
+    pAig = Faig_ManCreate( p );
+//ABC_PRT( "\nCreation  ", Abc_Clock() - clk );
+    Aig_ManRandom( 1 );
+    // get the number of  frames to simulate
+    // if the parameter "seqsimframes" is defined, use it
+    // otherwise, use the given number of frames "nFrames"
+    nFramesReal = nFrames;
+    if ( Abc_FrameReadFlag("seqsimframes") )
+        nFramesReal = atoi( Abc_FrameReadFlag("seqsimframes") );
+    if ( nFramesReal <= nPref )
+    {
+        printf( "The total number of frames (%d) should exceed prefix (%d).\n", nFramesReal, nPref );
+        printf( "Setting the total number of frames to be %d.\n", nFrames );
+        nFramesReal = nFrames;
+    }
+//printf( "Simulating %d frames.\n", nFramesReal );
+clk = Abc_Clock();
+    pProbs = Faig_ManSimulateFrames( pAig, nFramesReal, nPref, fTrans );
+//ABC_PRT( "Simulation", Abc_Clock() - clk );
+clk = Abc_Clock();
+    if ( fTrans )
+    {
+        Aig_Obj_t * pObj;
+        int i, Counter = 0;
+        pObj = Aig_ManConst1(p);
+        pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 );
+        Aig_ManForEachCi( p, pObj, i )
+            pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 );
+        Aig_ManForEachNode( p, pObj, i )
+            pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 );
+        Aig_ManForEachCo( p, pObj, i )
+            pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 );
+        assert( Counter == pAig->nObjs );
+    }
+    else if ( fProbOne )
+    {
+        Aig_Obj_t * pObj;
+        int i, Counter = 0;
+        pObj = Aig_ManConst1(p);
+        pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref );
+        Aig_ManForEachCi( p, pObj, i )
+            pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref );
+        Aig_ManForEachNode( p, pObj, i )
+            pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref );
+        Aig_ManForEachCo( p, pObj, i )
+            pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref );
+        assert( Counter == pAig->nObjs );
+    }
+    else 
+    {
+        Aig_Obj_t * pObj;
+        int i, Counter = 0;
+        pObj = Aig_ManConst1(p);
+        pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref );
+        Aig_ManForEachCi( p, pObj, i )
+            pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref );
+        Aig_ManForEachNode( p, pObj, i )
+            pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref );
+        Aig_ManForEachCo( p, pObj, i )
+            pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref );
+        assert( Counter == pAig->nObjs );
+    }
+    ABC_FREE( pProbs );
+    ABC_FREE( pAig );
+//ABC_PRT( "Switch    ", Abc_Clock() - clk );
+//ABC_PRT( "TOTAL     ", Abc_Clock() - clkTotal );
+    return vSwitching;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes probability of switching (or of being 1).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManComputeSwitchProb3s( Aig_Man_t * p, int nFrames, int nPref, int fProbOne )
+{
+//    return Faig_ManComputeSwitchProbs( p, nFrames, nPref, fProbOne );
+    return NULL;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigSimMv.c b/abc-build/src/aig/saig/saigSimMv.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigSimMv.c
@@ -0,0 +1,956 @@
+/**CFile****************************************************************
+
+  FileName    [saigSimMv.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Multi-valued simulation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigSimMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define SAIG_DIFF_VALUES  8
+#define SAIG_UNDEF_VALUE  0x1ffffffe  //536870910
+
+// old AIG
+typedef struct Saig_MvObj_t_ Saig_MvObj_t;
+struct Saig_MvObj_t_
+{
+    int              iFan0;
+    int              iFan1;
+    unsigned         Type   :  3;
+    unsigned         Value  : 29;
+};
+
+// new AIG
+typedef struct Saig_MvAnd_t_ Saig_MvAnd_t;
+struct Saig_MvAnd_t_
+{
+    int              iFan0;
+    int              iFan1;
+    int              iNext;
+};
+
+// simulation manager
+typedef struct Saig_MvMan_t_ Saig_MvMan_t;
+struct Saig_MvMan_t_
+{
+    // user data
+    Aig_Man_t *      pAig;         // original AIG    
+    // parameters
+    int              nStatesMax;   // maximum number of states
+    int              nLevelsMax;   // maximum number of levels
+    int              nValuesMax;   // maximum number of values
+    int              nFlops;       // number of flops
+    // compacted AIG
+    Saig_MvObj_t *   pAigOld;      // AIG objects
+    Vec_Ptr_t *      vFlops;       // collected flops
+    Vec_Int_t *      vXFlops;      // flops that had at least one X-value
+    Vec_Ptr_t *      vTired;       // collected flops
+    unsigned *       pTStates;     // hash table for states
+    int              nTStatesSize; // hash table size
+    Aig_MmFixed_t *  pMemStates;   // memory for states
+    Vec_Ptr_t *      vStates;      // reached states
+    int *            pRegsUndef;   // count the number of undef values
+    int **           pRegsValues;  // write the first different values
+    int *            nRegsValues;  // count the number of different values
+    int              nRUndefs;     // the number of undef registers
+    int              nRValues[SAIG_DIFF_VALUES+1]; // the number of registers with given values
+    // internal AIG
+    Saig_MvAnd_t *   pAigNew;      // AIG nodes
+    int              nObjsAlloc;   // the number of objects allocated 
+    int              nObjs;        // the number of objects
+    int              nPis;         // the number of primary inputs
+    int *            pTNodes;      // hash table
+    int              nTNodesSize;  // hash table size
+    unsigned char *  pLevels;      // levels of AIG nodes
+};
+
+static inline int    Saig_MvObjFaninC0( Saig_MvObj_t * pObj )  { return pObj->iFan0 & 1;           }
+static inline int    Saig_MvObjFaninC1( Saig_MvObj_t * pObj )  { return pObj->iFan1 & 1;           }
+static inline int    Saig_MvObjFanin0( Saig_MvObj_t * pObj )   { return pObj->iFan0 >> 1;          }
+static inline int    Saig_MvObjFanin1( Saig_MvObj_t * pObj )   { return pObj->iFan1 >> 1;          }
+
+static inline int    Saig_MvConst0()                           { return 1;                         }
+static inline int    Saig_MvConst1()                           { return 0;                         }
+static inline int    Saig_MvConst( int c )                     { return !c;                        }
+static inline int    Saig_MvUndef()                            { return SAIG_UNDEF_VALUE;          }
+
+static inline int    Saig_MvIsConst0( int iNode )              { return iNode == 1;                }
+static inline int    Saig_MvIsConst1( int iNode )              { return iNode == 0;                }
+static inline int    Saig_MvIsConst( int iNode )               { return iNode  < 2;                }
+static inline int    Saig_MvIsUndef( int iNode )               { return iNode == SAIG_UNDEF_VALUE; }
+
+static inline int    Saig_MvRegular( int iNode )               { return (iNode & ~01);             }
+static inline int    Saig_MvNot( int iNode )                   { return (iNode ^  01);             }
+static inline int    Saig_MvNotCond( int iNode, int c )        { return (iNode ^ (c));             }
+static inline int    Saig_MvIsComplement( int iNode )          { return (int)(iNode & 01);         }
+
+static inline int    Saig_MvLit2Var( int iNode )               { return (iNode >> 1);              }
+static inline int    Saig_MvVar2Lit( int iVar )                { return (iVar << 1);               }
+static inline int    Saig_MvLev( Saig_MvMan_t * p, int iNode ) { return p->pLevels[iNode >> 1];    }
+
+// iterator over compacted objects
+#define Saig_MvManForEachObj( pAig, pEntry ) \
+    for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates reduced manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Saig_MvObj_t * Saig_ManCreateReducedAig( Aig_Man_t * p, Vec_Ptr_t ** pvFlops )
+{
+    Saig_MvObj_t * pAig, * pEntry;
+    Aig_Obj_t * pObj;
+    int i;
+    *pvFlops = Vec_PtrAlloc( Aig_ManRegNum(p) );
+    pAig = ABC_CALLOC( Saig_MvObj_t, Aig_ManObjNumMax(p)+1 );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        pEntry = pAig + i;
+        pEntry->Type = pObj->Type;
+        if ( Aig_ObjIsCi(pObj) || i == 0 )
+        {
+            if ( Saig_ObjIsLo(p, pObj) )
+            {
+                pEntry->iFan0 = (Saig_ObjLoToLi(p, pObj)->Id << 1);
+                pEntry->iFan1 = -1;
+                Vec_PtrPush( *pvFlops, pEntry );
+            }
+            continue;
+        }
+        pEntry->iFan0 = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj);
+        if ( Aig_ObjIsCo(pObj) )
+            continue;
+        assert( Aig_ObjIsNode(pObj) );
+        pEntry->iFan1 = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj);
+    }
+    pEntry = pAig + Aig_ManObjNumMax(p);
+    pEntry->Type = AIG_OBJ_VOID;
+    return pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Saig_MvCreateObj( Saig_MvMan_t * p, int iFan0, int iFan1 )
+{
+    Saig_MvAnd_t * pNode;
+    if ( p->nObjs == p->nObjsAlloc )
+    {
+        p->pAigNew = ABC_REALLOC( Saig_MvAnd_t, p->pAigNew, 2*p->nObjsAlloc );
+        p->pLevels = ABC_REALLOC( unsigned char, p->pLevels, 2*p->nObjsAlloc );
+        p->nObjsAlloc *= 2;
+    }
+    pNode = p->pAigNew + p->nObjs;
+    pNode->iFan0 = iFan0;
+    pNode->iFan1 = iFan1;
+    pNode->iNext = 0;
+    if ( iFan0 || iFan1 )
+        p->pLevels[p->nObjs] = 1 + Abc_MaxInt( Saig_MvLev(p, iFan0), Saig_MvLev(p, iFan1) );
+    else
+        p->pLevels[p->nObjs] = 0, p->nPis++;
+    return p->nObjs++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates multi-valued simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Saig_MvMan_t * Saig_MvManStart( Aig_Man_t * pAig, int nFramesSatur )
+{
+    Saig_MvMan_t * p;
+    int i;
+    assert( Aig_ManRegNum(pAig) > 0 );
+    p = (Saig_MvMan_t *)ABC_ALLOC( Saig_MvMan_t, 1 );
+    memset( p, 0, sizeof(Saig_MvMan_t) );
+    // set parameters
+    p->pAig         = pAig;
+    p->nStatesMax   = 2 * nFramesSatur + 100;
+    p->nLevelsMax   = 4;
+    p->nValuesMax   = SAIG_DIFF_VALUES;
+    p->nFlops       = Aig_ManRegNum(pAig);
+    // compacted AIG
+    p->pAigOld      = Saig_ManCreateReducedAig( pAig, &p->vFlops );
+    p->nTStatesSize = Abc_PrimeCudd( p->nStatesMax );
+    p->pTStates     = ABC_CALLOC( unsigned, p->nTStatesSize );
+    p->pMemStates   = Aig_MmFixedStart( sizeof(int) * (p->nFlops+1), p->nStatesMax );
+    p->vStates      = Vec_PtrAlloc( p->nStatesMax );
+    Vec_PtrPush( p->vStates, NULL );
+    p->pRegsUndef   = ABC_CALLOC( int, p->nFlops );
+    p->pRegsValues  = ABC_ALLOC( int *, p->nFlops );
+    p->pRegsValues[0] = ABC_ALLOC( int, p->nValuesMax * p->nFlops );
+    for ( i = 1; i < p->nFlops; i++ )
+        p->pRegsValues[i] = p->pRegsValues[i-1] + p->nValuesMax;
+    p->nRegsValues  = ABC_CALLOC( int, p->nFlops );
+    p->vTired       = Vec_PtrAlloc( 100 );
+    // internal AIG
+    p->nObjsAlloc   = 1000000;
+    p->pAigNew      = ABC_ALLOC( Saig_MvAnd_t, p->nObjsAlloc );
+    p->nTNodesSize  = Abc_PrimeCudd( p->nObjsAlloc / 3 );
+    p->pTNodes      = ABC_CALLOC( int, p->nTNodesSize );
+    p->pLevels      = ABC_ALLOC( unsigned char, p->nObjsAlloc );
+    Saig_MvCreateObj( p, 0, 0 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Destroys multi-valued simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_MvManStop( Saig_MvMan_t * p )
+{
+    Aig_MmFixedStop( p->pMemStates, 0 );
+    Vec_PtrFree( p->vStates );
+    Vec_IntFreeP( &p->vXFlops );
+    Vec_PtrFree( p->vFlops );
+    Vec_PtrFree( p->vTired );
+    ABC_FREE( p->pRegsValues[0] );
+    ABC_FREE( p->pRegsValues );
+    ABC_FREE( p->nRegsValues );
+    ABC_FREE( p->pRegsUndef );
+    ABC_FREE( p->pAigOld );
+    ABC_FREE( p->pTStates );
+    ABC_FREE( p->pAigNew );
+    ABC_FREE( p->pTNodes );
+    ABC_FREE( p->pLevels );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Hashing the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Saig_MvHash( int iFan0, int iFan1, int TableSize ) 
+{
+    unsigned Key = 0;
+    assert( iFan0 < iFan1 );
+    Key ^= Saig_MvLit2Var(iFan0) * 7937;
+    Key ^= Saig_MvLit2Var(iFan1) * 2971;
+    Key ^= Saig_MvIsComplement(iFan0) * 911;
+    Key ^= Saig_MvIsComplement(iFan1) * 353;
+    return (int)(Key % TableSize);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the place where this node is stored (or should be stored).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int * Saig_MvTableFind( Saig_MvMan_t * p, int iFan0, int iFan1 )
+{
+    Saig_MvAnd_t * pEntry;
+    int * pPlace = p->pTNodes + Saig_MvHash( iFan0, iFan1, p->nTNodesSize );
+    for ( pEntry = (*pPlace)? p->pAigNew + *pPlace : NULL; pEntry; 
+          pPlace = &pEntry->iNext, pEntry = (*pPlace)? p->pAigNew + *pPlace : NULL )
+              if ( pEntry->iFan0 == iFan0 && pEntry->iFan1 == iFan1 )
+                  break;
+    return pPlace;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs an AND-operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Saig_MvAnd( Saig_MvMan_t * p, int iFan0, int iFan1, int fFirst )
+{
+    if ( iFan0 == iFan1 )
+        return iFan0;
+    if ( iFan0 == Saig_MvNot(iFan1) )
+        return Saig_MvConst0();
+    if ( Saig_MvIsConst(iFan0) )
+        return Saig_MvIsConst1(iFan0) ? iFan1 : Saig_MvConst0();
+    if ( Saig_MvIsConst(iFan1) )
+        return Saig_MvIsConst1(iFan1) ? iFan0 : Saig_MvConst0();
+    if ( Saig_MvIsUndef(iFan0) || Saig_MvIsUndef(iFan1) )
+        return Saig_MvUndef();
+//    if ( Saig_MvLev(p, iFan0) >= p->nLevelsMax || Saig_MvLev(p, iFan1) >= p->nLevelsMax )
+//        return Saig_MvUndef();
+
+    // go undef after the first frame
+    if ( !fFirst )
+        return Saig_MvUndef();
+
+    if ( iFan0 > iFan1 )
+    {
+        int Temp = iFan0;
+        iFan0 = iFan1;
+        iFan1 = Temp;
+    }
+    {
+        int * pPlace;
+        pPlace = Saig_MvTableFind( p, iFan0, iFan1 );
+        if ( *pPlace == 0 )
+        {
+            if ( pPlace >= (int*)p->pAigNew && pPlace < (int*)(p->pAigNew + p->nObjsAlloc) )
+            {
+                int iPlace = pPlace - (int*)p->pAigNew;
+                int iNode  = Saig_MvCreateObj( p, iFan0, iFan1 );
+                ((int*)p->pAigNew)[iPlace] = iNode;
+                return Saig_MvVar2Lit( iNode );
+            }
+            else
+                *pPlace = Saig_MvCreateObj( p, iFan0, iFan1 );
+        }
+        return Saig_MvVar2Lit( *pPlace );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagates one edge.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Saig_MvSimulateValue0( Saig_MvObj_t * pAig, Saig_MvObj_t * pObj )
+{
+    Saig_MvObj_t * pObj0 = pAig + Saig_MvObjFanin0(pObj);
+    if ( Saig_MvIsUndef( pObj0->Value ) )
+        return Saig_MvUndef();
+    return Saig_MvNotCond( pObj0->Value, Saig_MvObjFaninC0(pObj) );
+}
+static inline int Saig_MvSimulateValue1( Saig_MvObj_t * pAig, Saig_MvObj_t * pObj )
+{
+    Saig_MvObj_t * pObj1 = pAig + Saig_MvObjFanin1(pObj);
+    if ( Saig_MvIsUndef( pObj1->Value ) )
+        return Saig_MvUndef();
+    return Saig_MvNotCond( pObj1->Value, Saig_MvObjFaninC1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints MV state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_MvPrintState( int Iter, Saig_MvMan_t * p )
+{
+    Saig_MvObj_t * pEntry;
+    int i;
+    printf( "%3d : ", Iter );
+    Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i )
+    {
+        if ( pEntry->Value == SAIG_UNDEF_VALUE )
+            printf( "    *" );
+        else
+            printf( "%5d", pEntry->Value );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one iteration of simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_MvSimulateFrame( Saig_MvMan_t * p, int fFirst, int fVerbose )
+{
+    Saig_MvObj_t * pEntry;
+    int i;
+    Saig_MvManForEachObj( p->pAigOld, pEntry )
+    {
+        if ( pEntry->Type == AIG_OBJ_AND )
+        {
+            pEntry->Value = Saig_MvAnd( p, 
+                Saig_MvSimulateValue0(p->pAigOld, pEntry),
+                Saig_MvSimulateValue1(p->pAigOld, pEntry), fFirst );
+        }
+        else if ( pEntry->Type == AIG_OBJ_CO )
+            pEntry->Value = Saig_MvSimulateValue0(p->pAigOld, pEntry);
+        else if ( pEntry->Type == AIG_OBJ_CI )
+        {
+            if ( pEntry->iFan1 == 0 ) // true PI
+            {
+                if ( fFirst )
+                    pEntry->Value = Saig_MvVar2Lit( Saig_MvCreateObj( p, 0, 0 ) );
+                else
+                    pEntry->Value = SAIG_UNDEF_VALUE;
+            }
+//            else if ( fFirst ) // register output
+//                pEntry->Value = Saig_MvConst0();
+//            else
+//                pEntry->Value = Saig_MvSimulateValue0(p->pAigOld, pEntry);
+        }
+        else if ( pEntry->Type == AIG_OBJ_CONST1 )
+            pEntry->Value = Saig_MvConst1();
+        else if ( pEntry->Type != AIG_OBJ_NONE )
+            assert( 0 );
+    }
+    // transfer to registers
+    Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i )
+        pEntry->Value = Saig_MvSimulateValue0( p->pAigOld, pEntry );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash value of the node using its simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_MvSimHash( unsigned * pState, int nFlops, int TableSize )
+{
+    static int s_SPrimes[16] = { 
+     1610612741,
+     805306457,
+     402653189,
+     201326611,
+     100663319,
+     50331653,
+     25165843,
+     12582917,
+     6291469,
+     3145739,
+     1572869,
+     786433,
+     393241,
+     196613,
+     98317,
+     49157
+    };
+    unsigned uHash = 0;
+    int i;
+    for ( i = 0; i < nFlops; i++ )
+        uHash ^= pState[i] * s_SPrimes[i & 0xF];
+    return (int)(uHash % TableSize);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the place where this state is stored (or should be stored).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned * Saig_MvSimTableFind( Saig_MvMan_t * p, unsigned * pState )
+{
+    unsigned * pEntry;
+    unsigned * pPlace = p->pTStates + Saig_MvSimHash( pState+1, p->nFlops, p->nTStatesSize );
+    for ( pEntry = (*pPlace)? (unsigned *)Vec_PtrEntry(p->vStates, *pPlace) : NULL; pEntry; 
+          pPlace = pEntry, pEntry = (*pPlace)? (unsigned *)Vec_PtrEntry(p->vStates, *pPlace) : NULL )
+              if ( memcmp( pEntry+1, pState+1, sizeof(int)*p->nFlops ) == 0 )
+                  break;
+    return pPlace;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Saves current state.]
+
+  Description [Returns -1 if there is no fixed point.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_MvSaveState( Saig_MvMan_t * p )
+{
+    Saig_MvObj_t * pEntry;
+    unsigned * pState, * pPlace;
+    int i;
+    pState = (unsigned *)Aig_MmFixedEntryFetch( p->pMemStates );
+    pState[0] = 0;
+    Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i )
+        pState[i+1] = pEntry->Value;
+    pPlace = Saig_MvSimTableFind( p, pState );
+    if ( *pPlace )
+        return *pPlace;
+    *pPlace = Vec_PtrSize( p->vStates );
+    Vec_PtrPush( p->vStates, pState );
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs multi-valued simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_MvManPostProcess( Saig_MvMan_t * p, int iState )
+{
+    Saig_MvObj_t * pEntry;
+    unsigned * pState;
+    int i, k, j, nTotal = 0, iFlop;
+    Vec_Int_t * vUniques = Vec_IntAlloc( 100 );
+    Vec_Int_t * vCounter = Vec_IntAlloc( 100 );
+    // count registers that never became undef
+    Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i )
+        if ( p->pRegsUndef[i] == 0 )
+            nTotal++;
+    printf( "The number of registers that never became undef = %d. (Total = %d.)\n", nTotal, p->nFlops );
+    Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i )
+    {
+        if ( p->pRegsUndef[i] )
+            continue;
+        Vec_IntForEachEntry( vUniques, iFlop, k )
+        {
+            Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, j, 1 )
+                if ( pState[iFlop+1] != pState[i+1] )
+                    break;
+            if ( j == Vec_PtrSize(p->vStates) )
+            {
+                Vec_IntAddToEntry( vCounter, k, 1 );
+                break;
+            }
+        }
+        if ( k == Vec_IntSize(vUniques) )
+        {
+            Vec_IntPush( vUniques, i );
+            Vec_IntPush( vCounter, 1 );
+        }
+    }
+    Vec_IntForEachEntry( vUniques, iFlop, i )
+    {
+        printf( "FLOP %5d : (%3d) ", iFlop, Vec_IntEntry(vCounter,i) );
+/*
+        for ( k = 0; k < p->nRegsValues[iFlop]; k++ )
+            if ( p->pRegsValues[iFlop][k] == SAIG_UNDEF_VALUE )
+                printf( "* " );
+            else
+                printf( "%d ", p->pRegsValues[iFlop][k] );
+        printf( "\n" );
+*/
+        Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, k, 1 )
+        {
+            if ( k == iState+1 )
+                printf( " # " );
+            if ( pState[iFlop+1] == SAIG_UNDEF_VALUE )
+                printf( "*" );
+            else
+                printf( "%d", pState[iFlop+1] );
+        }
+        printf( "\n" );
+//        if ( ++Counter == 10 )
+//            break;
+    }
+
+    Vec_IntFree( vUniques );
+    Vec_IntFree( vCounter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs multi-valued simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_MvManFindXFlops( Saig_MvMan_t * p )
+{
+    Vec_Int_t * vXFlops;
+    unsigned * pState;
+    int i, k;
+    vXFlops = Vec_IntStart( p->nFlops );
+    Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, i, 1 )
+    {
+        for ( k = 0; k < p->nFlops; k++ )
+            if ( Saig_MvIsUndef(pState[k+1]) )
+                Vec_IntWriteEntry( vXFlops, k, 1 );
+    }
+    return vXFlops;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the flop is an oscilator.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_MvManCheckOscilator( Saig_MvMan_t * p, int iFlop )
+{
+    Vec_Int_t * vValues;
+    unsigned * pState;
+    int k, Per, Entry;
+    // collect values of this flop
+    vValues = Vec_IntAlloc( 100 );
+    Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, k, 1 )
+    {
+        Vec_IntPush( vValues, pState[iFlop+1] );
+//printf( "%d ", pState[iFlop+1] );
+    }
+//printf( "\n" );
+    assert( Saig_MvIsConst0( Vec_IntEntry(vValues,0) ) );
+    // look for constants
+    for ( Per = 0; Per < Vec_IntSize(vValues)/2; Per++ )
+    {
+        // find the first non-const0
+        Vec_IntForEachEntryStart( vValues, Entry, Per, Per )
+            if ( !Saig_MvIsConst0(Entry) )
+                break;
+        if ( Per == Vec_IntSize(vValues) )
+            break;
+        // find the first const0
+        Vec_IntForEachEntryStart( vValues, Entry, Per, Per )
+            if ( Saig_MvIsConst0(Entry) )
+                break;
+        if ( Per == Vec_IntSize(vValues) )
+            break;
+        // try to determine period
+        assert( Saig_MvIsConst0( Vec_IntEntry(vValues,Per) ) );
+        for ( k = Per; k < Vec_IntSize(vValues); k++ )
+            if ( Vec_IntEntry(vValues, k-Per) != Vec_IntEntry(vValues, k) )
+                break;
+        if ( k < Vec_IntSize(vValues) )
+            continue;
+        Vec_IntFree( vValues );
+//printf( "Period = %d\n", Per );
+        return Per;
+    }
+    Vec_IntFree( vValues );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns const0 and binary flops.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_MvManFindConstBinaryFlops( Saig_MvMan_t * p, Vec_Int_t ** pvBinary )
+{
+    unsigned * pState;
+    Vec_Int_t * vBinary, * vConst0;
+    int i, k, fConst0;
+    // detect constant flops
+    vConst0 = Vec_IntAlloc( p->nFlops );
+    vBinary = Vec_IntAlloc( p->nFlops );
+    for ( k = 0; k < p->nFlops; k++ )
+    {
+        // check if this flop is constant 0 in all states
+        fConst0 = 1;
+        Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, i, 1 )
+        {
+            if ( !Saig_MvIsConst0(pState[k+1]) )
+                fConst0 = 0;
+            if ( Saig_MvIsUndef(pState[k+1]) )
+                break;
+        }
+        if ( i < Vec_PtrSize(p->vStates) )
+            continue;
+        // the flop is binary-valued        
+        if ( fConst0 ) 
+            Vec_IntPush( vConst0, k );
+        else
+            Vec_IntPush( vBinary, k );
+    }
+    *pvBinary = vBinary;
+    return vConst0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find oscilators.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_MvManFindOscilators( Saig_MvMan_t * p, Vec_Int_t ** pvConst0 )
+{
+    Vec_Int_t * vBinary, * vOscils;
+    int Entry, i;
+    // detect constant flops
+    *pvConst0 = Saig_MvManFindConstBinaryFlops( p, &vBinary );
+    // check binary flops
+    vOscils = Vec_IntAlloc( 100 );
+    Vec_IntForEachEntry( vBinary, Entry, i )
+        if ( Saig_MvManCheckOscilator( p, Entry ) )
+            Vec_IntPush( vOscils, Entry );
+    Vec_IntFree( vBinary );
+    return vOscils;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find constants and oscilators.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_MvManCreateNextSkip( Saig_MvMan_t * p )
+{
+    Vec_Int_t * vConst0, * vOscils, * vXFlops;
+    int i, Entry;
+    vOscils = Saig_MvManFindOscilators( p, &vConst0 );
+//printf( "Found %d constants and %d oscilators.\n", Vec_IntSize(vConst0), Vec_IntSize(vOscils) );
+    vXFlops = Vec_IntAlloc( p->nFlops );
+    Vec_IntFill( vXFlops, p->nFlops, 1 );
+    Vec_IntForEachEntry( vConst0, Entry, i )
+        Vec_IntWriteEntry( vXFlops, Entry, 0 );
+    Vec_IntForEachEntry( vOscils, Entry, i )
+        Vec_IntWriteEntry( vXFlops, Entry, 0 );
+    Vec_IntFree( vOscils );
+    Vec_IntFree( vConst0 );
+    return vXFlops;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds equivalent flops.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_MvManDeriveMap( Saig_MvMan_t * p, int fVerbose )
+{
+    Vec_Int_t * vConst0, * vBinValued;
+    Vec_Ptr_t * vMap = NULL;
+    Aig_Obj_t * pObj;
+    unsigned * pState;
+    int i, k, j, FlopK, FlopJ;
+    int Counter1 = 0, Counter2 = 0;
+    // prepare CI map
+    vMap = Vec_PtrAlloc( Aig_ManCiNum(p->pAig) );
+    Aig_ManForEachCi( p->pAig, pObj, i )
+        Vec_PtrPush( vMap, pObj );
+    // detect constant flops
+    vConst0 = Saig_MvManFindConstBinaryFlops( p, &vBinValued );
+    // set constants
+    Vec_IntForEachEntry( vConst0, FlopK, k )
+    {
+        Vec_PtrWriteEntry( vMap, Saig_ManPiNum(p->pAig) + FlopK, Aig_ManConst0(p->pAig) );
+        Counter1++;
+    }
+    Vec_IntFree( vConst0 ); 
+
+    // detect equivalent (non-ternary flops)
+    Vec_IntForEachEntry( vBinValued, FlopK, k )
+    if ( FlopK >= 0 )
+    Vec_IntForEachEntryStart( vBinValued, FlopJ, j, k+1 )
+    if ( FlopJ >= 0 )
+    {
+        // check if they are equal
+        Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, i, 1 )
+            if ( pState[FlopK+1] != pState[FlopJ+1] )
+                break;
+        if ( i < Vec_PtrSize(p->vStates) )
+            continue;
+        // set the equivalence
+        Vec_PtrWriteEntry( vMap, Saig_ManPiNum(p->pAig) + FlopJ, Saig_ManLo(p->pAig, FlopK) );
+        Vec_IntWriteEntry( vBinValued, j, -1 );
+        Counter2++;
+    }
+    if ( fVerbose )
+    printf( "Detected %d const0 flops and %d pairs of equiv binary flops.\n", Counter1, Counter2 );
+    Vec_IntFree( vBinValued );
+    if ( Counter1 == 0 && Counter2 == 0 )
+        Vec_PtrFreeP( &vMap );
+    return vMap;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs multi-valued simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_MvManSimulate( Aig_Man_t * pAig, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose )
+{
+    Vec_Ptr_t * vMap;
+    Saig_MvMan_t * p;
+    Saig_MvObj_t * pEntry;
+    int f, i, iState;
+    abctime clk = Abc_Clock();
+    assert( nFramesSymb >= 1 && nFramesSymb <= nFramesSatur );
+
+    // start manager
+    p = Saig_MvManStart( pAig, nFramesSatur );
+if ( fVerbose )
+ABC_PRT( "Constructing the problem", Abc_Clock() - clk );
+
+    // initialize registers
+    Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i )
+        pEntry->Value = Saig_MvConst0();
+    Saig_MvSaveState( p );
+    if ( fVeryVerbose )
+        Saig_MvPrintState( 0, p );
+    // simulate until convergence
+    clk = Abc_Clock();
+    for ( f = 0; ; f++ )
+    { 
+        if ( f == nFramesSatur )
+        {
+            if ( fVerbose )
+            printf( "Begining to saturate simulation after %d frames\n", f );
+            // find all flops that have at least one X value in the past and set them to X forever
+            p->vXFlops = Saig_MvManFindXFlops( p );            
+        }
+        if ( f == 2 * nFramesSatur )
+        {
+            if ( fVerbose )
+            printf( "Agressively saturating simulation after %d frames\n", f );
+            Vec_IntFree( p->vXFlops );
+            p->vXFlops = Saig_MvManCreateNextSkip( p );
+        }
+        // retire some flops
+        if ( p->vXFlops )
+        {
+            Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i )
+                if ( Vec_IntEntry( p->vXFlops, i ) )
+                    pEntry->Value = SAIG_UNDEF_VALUE;
+        }
+        // simulate timeframe
+        Saig_MvSimulateFrame( p, (int)(f < nFramesSymb), fVerbose );
+        // save and print state
+        iState = Saig_MvSaveState( p );
+        if ( fVeryVerbose )
+            Saig_MvPrintState( f+1, p );
+        if ( iState >= 0 )
+        {
+            if ( fVerbose )
+            printf( "Converged after %d frames with lasso in state %d. Cycle = %d.\n", f+1, iState-1, f+2-iState );
+//            printf( "Total number of PIs = %d. AND nodes = %d.\n", p->nPis, p->nObjs - p->nPis );
+            break;
+        }
+    }
+//    printf( "Coverged after %d frames.\n", f );
+if ( fVerbose )
+ABC_PRT( "Multi-valued simulation", Abc_Clock() - clk );
+    // implement equivalences
+//    Saig_MvManPostProcess( p, iState-1 );
+    vMap = Saig_MvManDeriveMap( p, fVerbose );
+    Saig_MvManStop( p );
+//    return Aig_ManDupSimple( pAig );
+    return vMap;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigSimSeq.c b/abc-build/src/aig/saig/saigSimSeq.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigSimSeq.c
@@ -0,0 +1,518 @@
+/**CFile****************************************************************
+
+  FileName    [saigSimSeq.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Fast sequential AIG simulator.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigSimSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+#include "proof/ssw/ssw.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// combinational simulation manager
+typedef struct Raig_Man_t_ Raig_Man_t;
+struct Raig_Man_t_
+{
+    // parameters
+    Aig_Man_t *     pAig;         // the AIG to be used for simulation
+    int             nWords;       // the number of words to simulate
+    // AIG representation
+    int             nPis;         // the number of primary inputs
+    int             nPos;         // the number of primary outputs
+    int             nCis;         // the number of combinational inputs
+    int             nCos;         // the number of combinational outputs
+    int             nNodes;       // the number of internal nodes
+    int             nObjs;        // nCis + nNodes + nCos + 2
+    int *           pFans0;       // fanin0 for all objects
+    int *           pFans1;       // fanin1 for all objects
+    Vec_Int_t *     vCis2Ids;     // mapping of CIs into their PI ids
+    Vec_Int_t *     vLos;         // register outputs
+    Vec_Int_t *     vLis;         // register inputs
+    // simulation info
+    int *           pRefs;        // reference counter for each node
+    unsigned *      pSims;        // simlulation information for each node
+    // recycable memory
+    unsigned *      pMems;        // allocated simulaton memory
+    int             nWordsAlloc;  // the number of allocated entries
+    int             nMems;        // the number of used entries  
+    int             nMemsMax;     // the max number of used entries 
+    int             MemFree;      // next free entry
+};
+
+static inline int  Raig_Var2Lit( int Var, int fCompl )  { return Var + Var + fCompl; }
+static inline int  Raig_Lit2Var( int Lit )              { return Lit >> 1;           }
+static inline int  Raig_LitIsCompl( int Lit )           { return Lit & 1;            }
+static inline int  Raig_LitNot( int Lit )               { return Lit ^ 1;            }
+static inline int  Raig_LitNotCond( int Lit, int c )    { return Lit ^ (int)(c > 0); }
+static inline int  Raig_LitRegular( int Lit )           { return Lit & ~01;          }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Find the PO corresponding to the PO driver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Raig_ManFindPo( Aig_Man_t * pAig, int iNode )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Saig_ManForEachPo( pAig, pObj, i )
+        if ( pObj->iData == iNode )
+            return i;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates fast simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Raig_ManCreate_rec( Raig_Man_t * p, Aig_Obj_t * pObj )
+{
+    int iFan0, iFan1;
+    assert( !Aig_IsComplement(pObj) );
+    if ( pObj->iData )
+        return pObj->iData;
+    assert( !Aig_ObjIsConst1(pObj) );
+    if ( Aig_ObjIsNode(pObj) )
+    {
+        iFan0 = Raig_ManCreate_rec( p, Aig_ObjFanin0(pObj) );
+        iFan0 = (iFan0 << 1) | Aig_ObjFaninC0(pObj);
+        iFan1 = Raig_ManCreate_rec( p, Aig_ObjFanin1(pObj) );
+        iFan1 = (iFan1 << 1) | Aig_ObjFaninC1(pObj);
+    }
+    else if ( Aig_ObjIsCo(pObj) )
+    {
+        iFan0 = Raig_ManCreate_rec( p, Aig_ObjFanin0(pObj) );
+        iFan0 = (iFan0 << 1) | Aig_ObjFaninC0(pObj);
+        iFan1 = 0;
+    }
+    else
+    {
+        iFan0 = iFan1 = 0;
+        Vec_IntPush( p->vCis2Ids, Aig_ObjCioId(pObj) );
+    }
+    p->pFans0[p->nObjs] = iFan0;
+    p->pFans1[p->nObjs] = iFan1;
+    p->pRefs[p->nObjs] = Aig_ObjRefs(pObj);
+    return pObj->iData = p->nObjs++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates fast simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Raig_Man_t * Raig_ManCreate( Aig_Man_t * pAig )
+{
+    Raig_Man_t * p;
+    Aig_Obj_t * pObj;
+    int i, nObjs;
+    Aig_ManCleanData( pAig );
+    p = (Raig_Man_t *)ABC_ALLOC( Raig_Man_t, 1 );
+    memset( p, 0, sizeof(Raig_Man_t) );
+    p->pAig = pAig;
+    p->nPis = Saig_ManPiNum(pAig);
+    p->nPos = Saig_ManPoNum(pAig);
+    p->nCis = Aig_ManCiNum(pAig);
+    p->nCos = Aig_ManCoNum(pAig);
+    p->nNodes = Aig_ManNodeNum(pAig);
+    nObjs = p->nCis + p->nCos + p->nNodes + 2;
+    p->pFans0 = ABC_ALLOC( int, nObjs );
+    p->pFans1 = ABC_ALLOC( int, nObjs );
+    p->pRefs = ABC_ALLOC( int, nObjs );
+    p->pSims = ABC_CALLOC( unsigned, nObjs );
+    p->vCis2Ids = Vec_IntAlloc( Aig_ManCiNum(pAig) );
+    // add objects (0=unused; 1=const1)
+    p->nObjs = 2;
+    pObj = Aig_ManConst1( pAig );
+    pObj->iData = 1;
+    Aig_ManForEachCi( pAig, pObj, i )
+        if ( Aig_ObjRefs(pObj) == 0 )
+            Raig_ManCreate_rec( p, pObj );
+    Aig_ManForEachCo( pAig, pObj, i )
+        Raig_ManCreate_rec( p, pObj );
+    assert( Vec_IntSize(p->vCis2Ids) == Aig_ManCiNum(pAig) );
+    assert( p->nObjs == nObjs );
+    // collect flop outputs
+    p->vLos = Vec_IntAlloc( Aig_ManRegNum(pAig) );
+    Saig_ManForEachLo( pAig, pObj, i )
+        Vec_IntPush( p->vLos, pObj->iData );
+    // collect flop inputs
+    p->vLis = Vec_IntAlloc( Aig_ManRegNum(pAig) );
+    Saig_ManForEachLi( pAig, pObj, i )
+    {
+        Vec_IntPush( p->vLis, pObj->iData );
+        assert( p->pRefs[ pObj->iData ] == 0 );
+        p->pRefs[ pObj->iData ]++;
+    }
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates fast simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Raig_ManDelete( Raig_Man_t * p )
+{
+    Vec_IntFree( p->vCis2Ids );
+    Vec_IntFree( p->vLos );
+    Vec_IntFree( p->vLis );
+    ABC_FREE( p->pFans0 );
+    ABC_FREE( p->pFans1 );
+    ABC_FREE( p->pRefs );
+    ABC_FREE( p->pSims );
+    ABC_FREE( p->pMems );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [References simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Raig_ManSimRef( Raig_Man_t * p, int i )
+{
+    unsigned * pSim;
+    assert( i > 1 );
+    assert( p->pSims[i] == 0 );
+    if ( p->MemFree == 0 )
+    {
+        unsigned * pPlace, Ent;
+        if ( p->nWordsAlloc == 0 )
+        {
+            assert( p->pMems == NULL );
+            p->nWordsAlloc = (1<<17); // -> 1Mb
+            p->nMems = 1;
+        }
+        p->nWordsAlloc *= 2;
+        p->pMems = ABC_REALLOC( unsigned, p->pMems, p->nWordsAlloc );
+        memset( p->pMems, 0xff, sizeof(unsigned) * (p->nWords + 1) );
+        pPlace = (unsigned *)&p->MemFree;
+        for ( Ent = p->nMems * (p->nWords + 1); 
+              Ent + p->nWords + 1 < (unsigned)p->nWordsAlloc; 
+              Ent += p->nWords + 1 )
+        {
+            *pPlace = Ent;
+            pPlace = p->pMems + Ent;
+        }
+        *pPlace = 0;
+    }
+    p->pSims[i] = p->MemFree;
+    pSim = p->pMems + p->MemFree;
+    p->MemFree = pSim[0];
+    pSim[0] = p->pRefs[i];
+    p->nMems++;
+    if ( p->nMemsMax < p->nMems )
+        p->nMemsMax = p->nMems;
+    return pSim;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dereference simulaton info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Raig_ManSimDeref( Raig_Man_t * p, int i )
+{
+    unsigned * pSim;
+    assert( i );
+    if ( i == 1 ) // const 1
+        return p->pMems;
+    assert( p->pSims[i] > 0 );
+    pSim = p->pMems + p->pSims[i];
+    if ( --pSim[0] == 0 )
+    {
+        pSim[0] = p->MemFree;
+        p->MemFree = p->pSims[i];
+        p->pSims[i] = 0;
+        p->nMems--;
+    }
+    return pSim;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one round.]
+
+  Description [Returns the number of PO entry if failed; 0 otherwise.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Raig_ManSimulateRound( Raig_Man_t * p, int fMiter, int fFirst, int * piPat )
+{ 
+    unsigned * pRes0, * pRes1, * pRes;
+    int i, w, nCis, nCos, iFan0, iFan1, iPioNum;
+    // nove the values to the register outputs
+    Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i )
+    {
+        if ( iPioNum < p->nPis )
+            continue;
+        pRes = Raig_ManSimRef( p, Vec_IntEntry(p->vLos, iPioNum-p->nPis) );
+        if ( fFirst )
+            memset( pRes + 1, 0, sizeof(unsigned) * p->nWords );
+        else
+        {
+            pRes0 = Raig_ManSimDeref( p, Vec_IntEntry(p->vLis, iPioNum-p->nPis) );
+            for ( w = 1; w <= p->nWords; w++ )
+                pRes[w] = pRes0[w];
+        }
+        // handle unused PIs
+        if ( pRes[0] == 0 ) 
+        {
+            pRes[0] = 1;
+            Raig_ManSimDeref( p, Vec_IntEntry(p->vLos, iPioNum-p->nPis) );
+        }
+    }
+    // simulate the logic
+    nCis = nCos = 0;
+    for ( i = 2; i < p->nObjs; i++ )
+    {
+        if ( p->pFans0[i] == 0 ) // ci always has zero first fanin
+        {
+            iPioNum = Vec_IntEntry( p->vCis2Ids, nCis );
+            if ( iPioNum < p->nPis )
+            {
+                pRes = Raig_ManSimRef( p, i );
+                for ( w = 1; w <= p->nWords; w++ )
+                    pRes[w] = Aig_ManRandom( 0 );
+                // handle unused PIs
+                if ( pRes[0] == 0 ) 
+                {
+                    pRes[0] = 1;
+                    Raig_ManSimDeref( p, i );
+                }
+            }
+            else
+                assert( Vec_IntEntry(p->vLos, iPioNum-p->nPis) == i );
+            nCis++;
+            continue;
+        }
+        if ( p->pFans1[i] == 0 ) // co always has non-zero 1st fanin and zero 2nd fanin
+        {
+            pRes0 = Raig_ManSimDeref( p, Raig_Lit2Var(p->pFans0[i]) );
+            if ( nCos < p->nPos && fMiter )
+            {
+                unsigned Const = Raig_LitIsCompl(p->pFans0[i])? ~0 : 0;
+                for ( w = 1; w <= p->nWords; w++ )
+                    if ( pRes0[w] != Const )
+                    {
+                        *piPat = 32*(w-1) + Aig_WordFindFirstBit( pRes0[w] ^ Const );
+                        return i;
+                    }
+            }
+            else
+            {
+                pRes = Raig_ManSimRef( p, i );
+                assert( pRes[0] == 1 );
+                if ( Raig_LitIsCompl(p->pFans0[i]) )
+                    for ( w = 1; w <= p->nWords; w++ )
+                        pRes[w] = ~pRes0[w];
+                else
+                    for ( w = 1; w <= p->nWords; w++ )
+                        pRes[w] = pRes0[w];
+            }
+            nCos++;
+            continue;
+        }
+        pRes  = Raig_ManSimRef( p, i );
+        assert( pRes[0] > 0 );
+        iFan0 = p->pFans0[i];
+        iFan1 = p->pFans1[i];
+        pRes0 = Raig_ManSimDeref( p, Raig_Lit2Var(p->pFans0[i]) );
+        pRes1 = Raig_ManSimDeref( p, Raig_Lit2Var(p->pFans1[i]) );
+        if ( Raig_LitIsCompl(iFan0) && Raig_LitIsCompl(iFan1) )
+            for ( w = 1; w <= p->nWords; w++ )
+                pRes[w] = ~(pRes0[w] | pRes1[w]);
+        else if ( Raig_LitIsCompl(iFan0) && !Raig_LitIsCompl(iFan1) )
+            for ( w = 1; w <= p->nWords; w++ )
+                pRes[w] = ~pRes0[w] & pRes1[w];
+        else if ( !Raig_LitIsCompl(iFan0) && Raig_LitIsCompl(iFan1) )
+            for ( w = 1; w <= p->nWords; w++ )
+                pRes[w] = pRes0[w] & ~pRes1[w];
+        else if ( !Raig_LitIsCompl(iFan0) && !Raig_LitIsCompl(iFan1) )
+            for ( w = 1; w <= p->nWords; w++ )
+                pRes[w] = pRes0[w] & pRes1[w];
+    }
+    assert( nCis == p->nCis );
+    assert( nCos == p->nCos );
+    assert( p->nMems == 1 + Vec_IntSize(p->vLis) );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Raig_ManGenerateCounter( Aig_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat, Vec_Int_t * vCis2Ids )
+{
+    Abc_Cex_t * p;
+    unsigned * pData;
+    int f, i, w, iPioId, Counter;
+    p = Abc_CexAlloc( Aig_ManRegNum(pAig), Saig_ManPiNum(pAig), iFrame+1 );
+    p->iFrame = iFrame;
+    p->iPo = iOut;
+    // fill in the binary data
+    Aig_ManRandom( 1 );
+    Counter = p->nRegs;
+    pData = ABC_ALLOC( unsigned, nWords );
+    for ( f = 0; f <= iFrame; f++, Counter += p->nPis )
+    for ( i = 0; i < Aig_ManCiNum(pAig); i++ )
+    {
+        iPioId = Vec_IntEntry( vCis2Ids, i );
+        if ( iPioId >= p->nPis )
+            continue;
+        for ( w = 0; w < nWords; w++ )
+            pData[w] = Aig_ManRandom( 0 );
+        if ( Abc_InfoHasBit( pData, iPat ) )
+            Abc_InfoSetBit( p->pData, Counter + iPioId );
+    }
+    ABC_FREE( pData );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the bug is detected, 0 otherwise.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Raig_ManSimulate( Aig_Man_t * pAig, int nWords, int nIters, int TimeLimit, int fMiter, int fVerbose )
+{
+    Raig_Man_t * p;
+    Sec_MtrStatus_t Status;
+    int i, iPat, RetValue = 0;
+    abctime clk, clkTotal = Abc_Clock();
+    assert( Aig_ManRegNum(pAig) > 0 );
+    Status = Sec_MiterStatus( pAig );
+    if ( Status.nSat > 0 )
+    {
+        printf( "Miter is trivially satisfiable (output %d).\n", Status.iOut );
+        return 1;
+    }
+    if ( Status.nUndec == 0 )
+    {
+        printf( "Miter is trivially unsatisfiable.\n" );
+        return 0;
+    }
+    Aig_ManRandom( 1 );
+    p = Raig_ManCreate( pAig );
+    p->nWords = nWords;
+    // iterate through objects
+    for ( i = 0; i < nIters; i++ )
+    {
+        clk = Abc_Clock();
+        RetValue = Raig_ManSimulateRound( p, fMiter, i==0, &iPat );
+        if ( fVerbose )
+        {
+            printf( "Frame %4d out of %4d and timeout %3d sec. ", i+1, nIters, TimeLimit );
+            printf("Time = %7.2f sec\r", (1.0*Abc_Clock()-clkTotal)/CLOCKS_PER_SEC);
+        }
+        if ( RetValue > 0 )
+        {
+            int iOut = Raig_ManFindPo(p->pAig, RetValue);
+            assert( pAig->pSeqModel == NULL );
+            pAig->pSeqModel = Raig_ManGenerateCounter( pAig, i, iOut, nWords, iPat, p->vCis2Ids );
+            if ( fVerbose )
+            printf( "Miter is satisfiable after simulation (output %d).\n", iOut );
+            break;
+        }
+        if ( (Abc_Clock() - clk)/CLOCKS_PER_SEC >= TimeLimit )
+        {
+            printf( "No bug detected after %d frames with time limit %d seconds.\n", i+1, TimeLimit );
+            break;
+        }
+    }
+    if ( fVerbose )
+    {
+        printf( "Maxcut = %8d.  AigMem = %7.2f MB.  SimMem = %7.2f MB.  ", 
+            p->nMemsMax, 
+            1.0*(p->nObjs * 16)/(1<<20), 
+            1.0*(p->nMemsMax * 4 * (nWords+1))/(1<<20) );
+        ABC_PRT( "Total time", Abc_Clock() - clkTotal );
+    }
+    Raig_ManDelete( p );
+    return RetValue > 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigStrSim.c b/abc-build/src/aig/saig/saigStrSim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigStrSim.c
@@ -0,0 +1,976 @@
+/**CFile****************************************************************
+
+  FileName    [saigStrSim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Structural matching using simulation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigStrSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+#include "proof/ssw/ssw.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define SAIG_WORDS  16
+
+static inline Aig_Obj_t *  Saig_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj )                       { return ppNexts[pObj->Id];  }
+static inline void         Saig_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash value of the node using its simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Saig_StrSimHash( Aig_Obj_t * pObj )
+{
+    static int s_SPrimes[128] = {
+        1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459,
+        1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997,
+        2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543,
+        2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089,
+        3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671,
+        3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243,
+        4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871,
+        4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471,
+        5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073,
+        6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689,
+        6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309,
+        7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933,
+        8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+    };
+    unsigned * pSims;
+    unsigned uHash = 0;
+    int i;
+    assert( SAIG_WORDS <= 128 );
+    pSims = (unsigned *)pObj->pData;
+    for ( i = 0; i < SAIG_WORDS; i++ )
+        uHash ^= pSims[i] * s_SPrimes[i & 0x7F];
+    return uHash;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash value of the node using its simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_StrSimIsEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+    unsigned * pSims0 = (unsigned *)pObj0->pData;
+    unsigned * pSims1 = (unsigned *)pObj1->pData;
+    int i;
+    for ( i = 0; i < SAIG_WORDS; i++ )
+        if ( pSims0[i] != pSims1[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation info is zero.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_StrSimIsZero( Aig_Obj_t * pObj )
+{
+    unsigned * pSims = (unsigned *)pObj->pData;
+    int i;
+    for ( i = 0; i < SAIG_WORDS; i++ )
+        if ( pSims[i] != 0 )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation info is one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_StrSimIsOne( Aig_Obj_t * pObj )
+{
+    unsigned * pSims = (unsigned *)pObj->pData;
+    int i;
+    for ( i = 0; i < SAIG_WORDS; i++ )
+        if ( pSims[i] != ~0 )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns random simulation info.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_StrSimAssignRandom( Aig_Obj_t * pObj )
+{
+    unsigned * pSims = (unsigned *)pObj->pData;
+    int i;
+    for ( i = 0; i < SAIG_WORDS; i++ )
+        pSims[i] = Aig_ManRandom(0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns constant 0 simulation info.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_StrSimAssignOne( Aig_Obj_t * pObj )
+{
+    unsigned * pSims = (unsigned *)pObj->pData;
+    int i;
+    for ( i = 0; i < SAIG_WORDS; i++ )
+        pSims[i] = ~0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns constant 0 simulation info.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_StrSimAssignZeroInit( Aig_Obj_t * pObj )
+{
+    unsigned * pSims = (unsigned *)pObj->pData;
+    pSims[0] = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulated one node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_StrSimulateNode( Aig_Obj_t * pObj, int i )
+{
+    unsigned * pSims  = (unsigned *)pObj->pData;
+    unsigned * pSims0 = (unsigned *)Aig_ObjFanin0(pObj)->pData;
+    unsigned * pSims1 = (unsigned *)Aig_ObjFanin1(pObj)->pData;
+    if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) )
+        pSims[i] = ~(pSims0[i] | pSims1[i]);
+    else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) )
+        pSims[i] = (~pSims0[i] & pSims1[i]);
+    else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) )
+        pSims[i] = (pSims0[i] & ~pSims1[i]);
+    else // if ( !Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) )
+        pSims[i] = (pSims0[i] & pSims1[i]);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Saves output of one node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_StrSimSaveOutput( Aig_Obj_t * pObj, int i )
+{
+    unsigned * pSims = (unsigned *)pObj->pData;
+    unsigned * pSims0 = (unsigned *)Aig_ObjFanin0(pObj)->pData;
+    if ( Aig_ObjFaninC0(pObj) )
+        pSims[i] = ~pSims0[i];
+    else
+        pSims[i] = pSims0[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers simulation output to another node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_StrSimTransfer( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+    unsigned * pSims0 = (unsigned *)pObj0->pData;
+    unsigned * pSims1 = (unsigned *)pObj1->pData;
+    int i;
+    for ( i = 0; i < SAIG_WORDS; i++ )
+        pSims1[i] = pSims0[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers simulation output to another node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_StrSimTransferNext( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int i )
+{
+    unsigned * pSims0 = (unsigned *)pObj0->pData;
+    unsigned * pSims1 = (unsigned *)pObj1->pData;
+    assert( i < SAIG_WORDS - 1 );
+    pSims1[i+1] = pSims0[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform one round of simulation.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_StrSimulateRound( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+    Aig_Obj_t * pObj0, * pObj1;
+    int f, i;
+    // simulate the nodes
+    Aig_ManForEachObj( p0, pObj0, i )
+    {
+        if ( !Aig_ObjIsCi(pObj0) && !Aig_ObjIsNode(pObj0) )
+           continue;
+        pObj1 = Aig_ObjRepr(p0, pObj0);
+        if ( pObj1 == NULL )
+            continue;
+        assert( Aig_ObjRepr(p1, pObj1) == pObj0 );
+        Saig_StrSimAssignRandom( pObj0 );
+        Saig_StrSimTransfer( pObj0, pObj1 );
+    }
+    // simulate the timeframes
+    for ( f = 0; f < SAIG_WORDS; f++ )
+    {
+        // simulate the first AIG
+        Aig_ManForEachNode( p0, pObj0, i )
+            if ( Aig_ObjRepr(p0, pObj0) == NULL )
+                Saig_StrSimulateNode( pObj0, f );
+        Saig_ManForEachLi( p0, pObj0, i )
+            Saig_StrSimSaveOutput( pObj0, f );
+        if ( f < SAIG_WORDS - 1 )
+            Saig_ManForEachLiLo( p0, pObj0, pObj1, i )
+                Saig_StrSimTransferNext( pObj0, pObj1, f );
+        // simulate the second AIG
+        Aig_ManForEachNode( p1, pObj1, i )
+            if ( Aig_ObjRepr(p1, pObj1) == NULL )
+                Saig_StrSimulateNode( pObj1, f );
+        Saig_ManForEachLi( p1, pObj1, i )
+            Saig_StrSimSaveOutput( pObj1, f );
+        if ( f < SAIG_WORDS - 1 )
+            Saig_ManForEachLiLo( p1, pObj1, pObj0, i )
+                Saig_StrSimTransferNext( pObj1, pObj0, f );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the entry exists in the table.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Saig_StrSimTableLookup( Aig_Obj_t ** ppTable, Aig_Obj_t ** ppNexts, int nTableSize, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pEntry;
+    int iEntry;
+    // find the hash entry
+    iEntry = Saig_StrSimHash( pObj ) % nTableSize;
+    // check if there are nodes with this signatures
+    for ( pEntry = ppTable[iEntry]; pEntry; pEntry = Saig_ObjNext(ppNexts,pEntry) )
+        if ( Saig_StrSimIsEqual( pEntry, pObj ) )
+            return pEntry;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the entry into the table.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_StrSimTableInsert( Aig_Obj_t ** ppTable, Aig_Obj_t ** ppNexts, int nTableSize, Aig_Obj_t * pObj )
+{
+    // find the hash entry
+    int iEntry = Saig_StrSimHash( pObj ) % nTableSize;
+    // check if there are nodes with this signatures
+    if ( ppTable[iEntry] == NULL )
+        ppTable[iEntry] = pObj;
+    else
+    {
+        Saig_ObjSetNext( ppNexts, pObj, Saig_ObjNext(ppNexts, ppTable[iEntry]) );
+        Saig_ObjSetNext( ppNexts, ppTable[iEntry], pObj );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform one round of matching.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_StrSimDetectUnique( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+    Aig_Obj_t ** ppTable, ** ppNexts, ** ppCands;
+    Aig_Obj_t * pObj, * pEntry;
+    int i, nTableSize, Counter;
+
+    // allocate the hash table hashing simulation info into nodes
+    nTableSize = Abc_PrimeCudd( Aig_ManObjNum(p0)/2 );
+    ppTable = ABC_CALLOC( Aig_Obj_t *, nTableSize );
+    ppNexts = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p0) );
+    ppCands = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p0) );
+
+    // hash nodes of the first AIG
+    Aig_ManForEachObj( p0, pObj, i )
+    {
+        if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) )
+            continue;
+        if ( Aig_ObjRepr(p0, pObj) )
+            continue;
+        if ( Saig_StrSimIsZero(pObj) || Saig_StrSimIsOne(pObj) )
+            continue;
+        // check if the entry exists
+        pEntry = Saig_StrSimTableLookup( ppTable, ppNexts, nTableSize, pObj );
+        if ( pEntry == NULL ) // insert
+            Saig_StrSimTableInsert( ppTable, ppNexts, nTableSize, pObj );
+        else // mark the entry as not unique
+            pEntry->fMarkA = 1;
+    }
+
+    // hash nodes from the second AIG
+    Aig_ManForEachObj( p1, pObj, i )
+    {
+        if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) )
+            continue;
+        if ( Aig_ObjRepr(p1, pObj) )
+            continue;
+        if ( Saig_StrSimIsZero(pObj) || Saig_StrSimIsOne(pObj) )
+            continue;
+        // check if the entry exists
+        pEntry = Saig_StrSimTableLookup( ppTable, ppNexts, nTableSize, pObj );
+        if ( pEntry == NULL ) // skip
+            continue;
+        // if there is no candidate, label it
+        if ( Saig_ObjNext( ppCands, pEntry ) == NULL )
+            Saig_ObjSetNext( ppCands, pEntry, pObj );
+        else // mark the entry as not unique
+            pEntry->fMarkA = 1;
+    }
+
+    // create representatives for the unique entries
+    Counter = 0;
+    for ( i = 0; i < nTableSize; i++ )
+        for ( pEntry = ppTable[i]; pEntry; pEntry = Saig_ObjNext(ppNexts,pEntry) )
+            if ( !pEntry->fMarkA && (pObj = Saig_ObjNext( ppCands, pEntry )) )
+            {
+//                assert( Aig_ObjIsNode(pEntry) == Aig_ObjIsNode(pObj) );
+                if ( Aig_ObjType(pEntry) != Aig_ObjType(pObj) )
+                    continue;
+                Aig_ObjSetRepr( p0, pEntry, pObj );
+                Aig_ObjSetRepr( p1, pObj, pEntry );
+                Counter++;
+            }
+
+    // cleanup
+    Aig_ManCleanMarkA( p0 );
+    ABC_FREE( ppTable );
+    ABC_FREE( ppNexts );
+    ABC_FREE( ppCands );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of matched flops.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_StrSimCountMatchedFlops( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    Saig_ManForEachLo( p, pObj, i )
+        if ( Aig_ObjRepr(p, pObj) )
+            Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of matched nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_StrSimCountMatchedNodes( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    Aig_ManForEachNode( p, pObj, i )
+        if ( Aig_ObjRepr(p, pObj) )
+            Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs structural matching of two AIGs using simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_StrSimPrepareAig( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManReprStart( p, Aig_ManObjNumMax(p) );
+    // allocate simulation info
+    p->pData2 = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p), SAIG_WORDS );
+    Aig_ManForEachObj( p, pObj, i )
+        pObj->pData = Vec_PtrEntry( (Vec_Ptr_t *)p->pData2, i );
+    // set simulation info for constant1 and register outputs
+    Saig_StrSimAssignOne( Aig_ManConst1(p) );
+    Saig_ManForEachLo( p, pObj, i )
+        Saig_StrSimAssignZeroInit( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs structural matching of two AIGs using simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_StrSimSetInitMatching( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+    Aig_Obj_t * pObj0, * pObj1;
+    int i;
+    pObj0 = Aig_ManConst1( p0 );
+    pObj1 = Aig_ManConst1( p1 );
+    Aig_ObjSetRepr( p0, pObj0, pObj1 );
+    Aig_ObjSetRepr( p1, pObj1, pObj0 );
+    Saig_ManForEachPi( p0, pObj0, i )
+    {
+        pObj1 = Aig_ManCi( p1, i );
+        Aig_ObjSetRepr( p0, pObj0, pObj1 );
+        Aig_ObjSetRepr( p1, pObj1, pObj0 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs structural matching of two AIGs using simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_StrSimSetFinalMatching( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+    Aig_Obj_t * pObj0, * pObj1;
+    Aig_Obj_t * pFanin00, * pFanin01;
+    Aig_Obj_t * pFanin10, * pFanin11;
+    int i, CountAll = 0, CountNot = 0;
+    Aig_ManIncrementTravId( p0 );
+    Aig_ManForEachObj( p0, pObj0, i )
+    {
+        pObj1 = Aig_ObjRepr( p0, pObj0 );
+        if ( pObj1 == NULL )
+            continue;
+        CountAll++;
+        assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) );
+        if ( Aig_ObjIsNode(pObj0) )
+        {
+            assert( Aig_ObjIsNode(pObj1) );
+            pFanin00 = Aig_ObjFanin0(pObj0);
+            pFanin01 = Aig_ObjFanin1(pObj0);
+            pFanin10 = Aig_ObjFanin0(pObj1);
+            pFanin11 = Aig_ObjFanin1(pObj1);
+            if ( Aig_ObjRepr(p0, pFanin00) != pFanin10 ||
+                 Aig_ObjRepr(p0, pFanin01) != pFanin11 )
+            {
+                Aig_ObjSetTravIdCurrent(p0, pObj0);
+                CountNot++;
+            }
+        }
+        else if ( Saig_ObjIsLo(p0, pObj0) )
+        {
+            assert( Saig_ObjIsLo(p1, pObj1) );
+            pFanin00 = Aig_ObjFanin0( Saig_ObjLoToLi(p0, pObj0) );
+            pFanin10 = Aig_ObjFanin0( Saig_ObjLoToLi(p1, pObj1) );
+            if ( Aig_ObjRepr(p0, pFanin00) != pFanin10 )
+            {
+                Aig_ObjSetTravIdCurrent(p0, pObj0);
+                CountNot++;
+            }
+        }
+    }
+    // remove irrelevant matches
+    Aig_ManForEachObj( p0, pObj0, i )
+    {
+        pObj1 = Aig_ObjRepr( p0, pObj0 );
+        if ( pObj1 == NULL )
+            continue;
+        assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) );
+        if ( Aig_ObjIsTravIdCurrent( p0, pObj0 ) )
+        {
+            Aig_ObjSetRepr( p0, pObj0, NULL );
+            Aig_ObjSetRepr( p1, pObj1, NULL );
+        }
+    }
+    Abc_Print( 1, "Total matches = %6d.  Wrong matches = %6d.  Ratio = %5.2f %%\n",
+        CountAll, CountNot, 100.0*CountNot/CountAll );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of dangling nodes removed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_StrSimSetContiguousMatching_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pFanout;
+    int i, iFanout = -1;
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Saig_ObjIsPo( p, pObj ) )
+        return;
+    if ( Saig_ObjIsLi( p, pObj ) )
+    {
+        Saig_StrSimSetContiguousMatching_rec( p, Saig_ObjLiToLo(p, pObj) );
+        return;
+    }
+    assert( Aig_ObjIsCi(pObj) || Aig_ObjIsNode(pObj) );
+    if ( Aig_ObjRepr(p, pObj) == NULL )
+        return;
+    // go through the fanouts
+    Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
+        Saig_StrSimSetContiguousMatching_rec( p, pFanout );
+    // go through the fanins
+    if ( !Aig_ObjIsCi( pObj ) )
+    {
+        Saig_StrSimSetContiguousMatching_rec( p, Aig_ObjFanin0(pObj) );
+        Saig_StrSimSetContiguousMatching_rec( p, Aig_ObjFanin1(pObj) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs structural matching of two AIGs using simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_StrSimSetContiguousMatching( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+    Aig_Obj_t * pObj0, * pObj1;
+    int i, CountAll = 0, CountNot = 0;
+    // mark nodes reachable through the PIs
+    Aig_ManIncrementTravId( p0 );
+    Aig_ObjSetTravIdCurrent( p0, Aig_ManConst1(p0) );
+    Saig_ManForEachPi( p0, pObj0, i )
+        Saig_StrSimSetContiguousMatching_rec( p0, pObj0 );
+    // remove irrelevant matches
+    Aig_ManForEachObj( p0, pObj0, i )
+    {
+        pObj1 = Aig_ObjRepr( p0, pObj0 );
+        if ( pObj1 == NULL )
+            continue;
+        CountAll++;
+        assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) );
+        if ( !Aig_ObjIsTravIdCurrent( p0, pObj0 ) )
+        {
+            Aig_ObjSetRepr( p0, pObj0, NULL );
+            Aig_ObjSetRepr( p1, pObj1, NULL );
+            CountNot++;
+        }
+    }
+    Abc_Print( 1, "Total matches = %6d.  Wrong matches = %6d.  Ratio = %5.2f %%\n",
+        CountAll, CountNot, 100.0*CountNot/CountAll );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Establishes relationship between nodes using pairing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_StrSimMatchingExtendOne( Aig_Man_t * p, Vec_Ptr_t * vNodes )
+{
+    Aig_Obj_t * pNext, * pObj;
+    int i, k, iFan = -1;
+    Vec_PtrClear( vNodes );
+    Aig_ManIncrementTravId( p );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
+            continue;
+        if ( Aig_ObjRepr( p, pObj ) != NULL )
+            continue;
+        if ( Saig_ObjIsLo(p, pObj) )
+        {
+            pNext = Saig_ObjLoToLi(p, pObj);
+            pNext = Aig_ObjFanin0(pNext);
+            if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) && !Aig_ObjIsConst1(pNext) )
+            {
+                Aig_ObjSetTravIdCurrent(p, pNext);
+                Vec_PtrPush( vNodes, pNext );
+            }
+        }
+        if ( Aig_ObjIsNode(pObj) )
+        {
+            pNext = Aig_ObjFanin0(pObj);
+            if ( Aig_ObjRepr( p, pNext )&& !Aig_ObjIsTravIdCurrent(p, pNext) )
+            {
+                Aig_ObjSetTravIdCurrent(p, pNext);
+                Vec_PtrPush( vNodes, pNext );
+            }
+            pNext = Aig_ObjFanin1(pObj);
+            if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) )
+            {
+                Aig_ObjSetTravIdCurrent(p, pNext);
+                Vec_PtrPush( vNodes, pNext );
+            }
+        }
+        Aig_ObjForEachFanout( p, pObj, pNext, iFan, k )
+        {
+            if ( Saig_ObjIsPo(p, pNext) )
+                continue;
+            if ( Saig_ObjIsLi(p, pNext) )
+                pNext = Saig_ObjLiToLo(p, pNext);
+            if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) )
+            {
+                Aig_ObjSetTravIdCurrent(p, pNext);
+                Vec_PtrPush( vNodes, pNext );
+            }
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Establishes relationship between nodes using pairing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_StrSimMatchingCountUnmached( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
+            continue;
+        if ( Aig_ObjRepr( p, pObj ) != NULL )
+            continue;
+        Counter++;
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Establishes relationship between nodes using pairing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_StrSimMatchingExtend( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose )
+{
+    Vec_Ptr_t * vNodes0, * vNodes1;
+    Aig_Obj_t * pNext0, * pNext1;
+    int d, k;
+    vNodes0 = Vec_PtrAlloc( 1000 );
+    vNodes1 = Vec_PtrAlloc( 1000 );
+    if ( fVerbose )
+    {
+        int nUnmached = Ssw_StrSimMatchingCountUnmached(p0);
+        Abc_Print( 1, "Extending islands by %d steps:\n", nDist );
+        Abc_Print( 1, "%2d : Total = %6d. Unmatched = %6d.  Ratio = %6.2f %%\n",
+            0, Aig_ManCiNum(p0) + Aig_ManNodeNum(p0),
+            nUnmached, 100.0 * nUnmached/(Aig_ManCiNum(p0) + Aig_ManNodeNum(p0)) );
+    }
+    for ( d = 0; d < nDist; d++ )
+    {
+        Ssw_StrSimMatchingExtendOne( p0, vNodes0 );
+        Ssw_StrSimMatchingExtendOne( p1, vNodes1 );
+        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pNext0, k )
+        {
+            pNext1 = Aig_ObjRepr( p0, pNext0 );
+            if ( pNext1 == NULL )
+                continue;
+            assert( pNext0 == Aig_ObjRepr( p1, pNext1 ) );
+            if ( Saig_ObjIsPi(p1, pNext1) )
+                continue;
+            Aig_ObjSetRepr( p0, pNext0, NULL );
+            Aig_ObjSetRepr( p1, pNext1, NULL );
+        }
+        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pNext1, k )
+        {
+            pNext0 = Aig_ObjRepr( p1, pNext1 );
+            if ( pNext0 == NULL )
+                continue;
+            assert( pNext1 == Aig_ObjRepr( p0, pNext0 ) );
+            if ( Saig_ObjIsPi(p0, pNext0) )
+                continue;
+            Aig_ObjSetRepr( p0, pNext0, NULL );
+            Aig_ObjSetRepr( p1, pNext1, NULL );
+        }
+        if ( fVerbose )
+        {
+            int nUnmached = Ssw_StrSimMatchingCountUnmached(p0);
+            Abc_Print( 1, "%2d : Total = %6d. Unmatched = %6d.  Ratio = %6.2f %%\n",
+                d+1, Aig_ManCiNum(p0) + Aig_ManNodeNum(p0),
+                nUnmached, 100.0 * nUnmached/(Aig_ManCiNum(p0) + Aig_ManNodeNum(p0)) );
+        }
+    }
+    Vec_PtrFree( vNodes0 );
+    Vec_PtrFree( vNodes1 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs structural matching of two AIGs using simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter )
+{
+    extern Aig_Man_t * Saig_ManWindowExtractMiter( Aig_Man_t * p0, Aig_Man_t * p1 );
+
+    Vec_Int_t * vPairs;
+    Aig_Man_t * pPart0, * pPart1;
+    Aig_Obj_t * pObj0, * pObj1;
+    int i, nMatches;
+    abctime clk, clkTotal = Abc_Clock();
+    Aig_ManRandom( 1 );
+    // consider the case when a miter is given
+    if ( p1 == NULL )
+    {
+        if ( fVerbose )
+        {
+            Aig_ManPrintStats( p0 );
+        }
+        // demiter the miter
+        if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) )
+        {
+            Abc_Print( 1, "Demitering has failed.\n" );
+            return NULL;
+        }
+    }
+    else
+    {
+        pPart0 = Aig_ManDupSimple( p0 );
+        pPart1 = Aig_ManDupSimple( p1 );
+    }
+    if ( fVerbose )
+    {
+        Aig_ManPrintStats( pPart0 );
+        Aig_ManPrintStats( pPart1 );
+    }
+    // start simulation 
+    Saig_StrSimPrepareAig( pPart0 );
+    Saig_StrSimPrepareAig( pPart1 );
+    Saig_StrSimSetInitMatching( pPart0, pPart1 );
+    if ( fVerbose )
+    {
+        Abc_Print( 1, "Allocated %6.2f MB to simulate the first AIG.\n",
+            1.0 * Aig_ManObjNumMax(pPart0) * SAIG_WORDS * sizeof(unsigned) / (1<<20) );
+        Abc_Print( 1, "Allocated %6.2f MB to simulate the second AIG.\n",
+            1.0 * Aig_ManObjNumMax(pPart1) * SAIG_WORDS * sizeof(unsigned) / (1<<20) );
+    }
+    // iterate matching
+    nMatches = 1;
+    for ( i = 0; nMatches > 0; i++ )
+    {
+        clk = Abc_Clock();
+        Saig_StrSimulateRound( pPart0, pPart1 );
+        nMatches = Saig_StrSimDetectUnique( pPart0, pPart1 );
+        if ( fVerbose )
+        {
+            int nFlops = Saig_StrSimCountMatchedFlops(pPart0);
+            int nNodes = Saig_StrSimCountMatchedNodes(pPart0);
+            Abc_Print( 1, "%3d : Match =%6d.  FF =%6d. (%6.2f %%)  Node =%6d. (%6.2f %%)  ",
+                i, nMatches,
+                nFlops, 100.0*nFlops/Aig_ManRegNum(pPart0),
+                nNodes, 100.0*nNodes/Aig_ManNodeNum(pPart0) );
+            ABC_PRT( "Time", Abc_Clock() - clk );
+        }
+        if ( i == 20 )
+            break;
+    }
+    // cleanup
+    Vec_PtrFree( (Vec_Ptr_t *)pPart0->pData2 ); pPart0->pData2 = NULL;
+    Vec_PtrFree( (Vec_Ptr_t *)pPart1->pData2 ); pPart1->pData2 = NULL;
+    // extend the islands
+    Aig_ManFanoutStart( pPart0 );
+    Aig_ManFanoutStart( pPart1 );
+    if ( nDist )
+        Ssw_StrSimMatchingExtend( pPart0, pPart1, nDist, fVerbose );
+    Saig_StrSimSetFinalMatching( pPart0, pPart1 );
+//    Saig_StrSimSetContiguousMatching( pPart0, pPart1 );
+    // copy the results into array
+    vPairs = Vec_IntAlloc( 2*Aig_ManObjNumMax(pPart0) );
+    Aig_ManForEachObj( pPart0, pObj0, i )
+    {
+        pObj1 = Aig_ObjRepr(pPart0, pObj0);
+        if ( pObj1 == NULL )
+            continue;
+        assert( pObj0 == Aig_ObjRepr(pPart1, pObj1) );
+        Vec_IntPush( vPairs, pObj0->Id );
+        Vec_IntPush( vPairs, pObj1->Id );
+    }
+    // this procedure adds matching of PO and LI
+    if ( ppMiter )
+        *ppMiter = Saig_ManWindowExtractMiter( pPart0, pPart1 );
+    Aig_ManFanoutStop( pPart0 );
+    Aig_ManFanoutStop( pPart1 );
+    Aig_ManStop( pPart0 );
+    Aig_ManStop( pPart1 );
+    ABC_PRT( "Total runtime", Abc_Clock() - clkTotal );
+    return vPairs;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/aig/saig/saigSwitch.c b/abc-build/src/aig/saig/saigSwitch.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigSwitch.c
@@ -0,0 +1,573 @@
+/**CFile****************************************************************
+
+  FileName    [saigSwitch.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Returns switching propabilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Saig_SimObj_t_ Saig_SimObj_t;
+struct Saig_SimObj_t_
+{
+    int      iFan0;
+    int      iFan1;
+    unsigned Type   :  8;
+    unsigned Number : 24;
+    unsigned pData[1];
+};
+
+static inline int Saig_SimObjFaninC0( Saig_SimObj_t * pObj )  { return pObj->iFan0 & 1;  }
+static inline int Saig_SimObjFaninC1( Saig_SimObj_t * pObj )  { return pObj->iFan1 & 1;  }
+static inline int Saig_SimObjFanin0( Saig_SimObj_t * pObj )   { return pObj->iFan0 >> 1; }
+static inline int Saig_SimObjFanin1( Saig_SimObj_t * pObj )   { return pObj->iFan1 >> 1; }
+
+//typedef struct Aig_CMan_t_ Aig_CMan_t;
+
+//static Aig_CMan_t * Aig_CManCreate( Aig_Man_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates fast simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Saig_SimObj_t * Saig_ManCreateMan( Aig_Man_t * p )
+{
+    Saig_SimObj_t * pAig, * pEntry;
+    Aig_Obj_t * pObj;
+    int i;
+    pAig = ABC_CALLOC( Saig_SimObj_t, Aig_ManObjNumMax(p)+1 );
+//    printf( "Allocating %7.2f MB.\n", 1.0 * sizeof(Saig_SimObj_t) * (Aig_ManObjNumMax(p)+1)/(1<<20) );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        pEntry = pAig + i;
+        pEntry->Type = pObj->Type;
+        if ( Aig_ObjIsCi(pObj) || i == 0 )
+        {
+            if ( Saig_ObjIsLo(p, pObj) )
+            {
+                pEntry->iFan0 = (Saig_ObjLoToLi(p, pObj)->Id << 1);
+                pEntry->iFan1 = -1;
+            }
+            continue;
+        }
+        pEntry->iFan0 = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj);
+        if ( Aig_ObjIsCo(pObj) )
+            continue;
+        assert( Aig_ObjIsNode(pObj) );
+        pEntry->iFan1 = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj);
+    }
+    pEntry = pAig + Aig_ManObjNumMax(p);
+    pEntry->Type = AIG_OBJ_VOID;
+    return pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulated one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Saig_ManSimulateNode2( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj )
+{
+    Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj );
+    Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pObj );
+    if ( Saig_SimObjFaninC0(pObj) && Saig_SimObjFaninC1(pObj) )
+        pObj->pData[0] = ~(pObj0->pData[0] | pObj1->pData[0]);
+    else if ( Saig_SimObjFaninC0(pObj) && !Saig_SimObjFaninC1(pObj) )
+        pObj->pData[0] = (~pObj0->pData[0] & pObj1->pData[0]);
+    else if ( !Saig_SimObjFaninC0(pObj) && Saig_SimObjFaninC1(pObj) )
+        pObj->pData[0] = (pObj0->pData[0] & ~pObj1->pData[0]);
+    else // if ( !Saig_SimObjFaninC0(pObj) && !Saig_SimObjFaninC1(pObj) )
+        pObj->pData[0] = (pObj0->pData[0] & pObj1->pData[0]);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulated one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Saig_ManSimulateNode( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj )
+{
+    Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj );
+    Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pObj );
+    pObj->pData[0] = (Saig_SimObjFaninC0(pObj)? ~pObj0->pData[0] : pObj0->pData[0])
+        & (Saig_SimObjFaninC1(pObj)? ~pObj1->pData[0] : pObj1->pData[0]);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulated buffer/inverter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Saig_ManSimulateOneInput( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj )
+{
+    Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj );
+    if ( Saig_SimObjFaninC0(pObj) )
+        pObj->pData[0] = ~pObj0->pData[0];
+    else // if ( !Saig_SimObjFaninC0(pObj) )
+        pObj->pData[0] = pObj0->pData[0];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates the timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManSimulateFrames( Saig_SimObj_t * pAig, int nFrames, int nPref )
+{
+    Saig_SimObj_t * pEntry;
+    int f;
+    for ( f = 0; f < nFrames; f++ )
+    {
+        for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ )
+        {
+            if ( pEntry->Type == AIG_OBJ_AND )
+                Saig_ManSimulateNode( pAig, pEntry );
+            else if ( pEntry->Type == AIG_OBJ_CO )
+                Saig_ManSimulateOneInput( pAig, pEntry );
+            else if ( pEntry->Type == AIG_OBJ_CI )
+            {
+                if ( pEntry->iFan0 == 0 ) // true PI
+                    pEntry->pData[0] = Aig_ManRandom( 0 );
+                else if ( f > 0 ) // register output
+                    Saig_ManSimulateOneInput( pAig, pEntry );
+            }
+            else if ( pEntry->Type == AIG_OBJ_CONST1 )
+                pEntry->pData[0] = ~0;
+            else if ( pEntry->Type != AIG_OBJ_NONE )
+                assert( 0 );
+            if ( f >= nPref )
+                pEntry->Number += Aig_WordCountOnes( pEntry->pData[0] );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes switching activity of one node.]
+
+  Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Saig_ManComputeSwitching( int nOnes, int nSimWords )
+{
+    int nTotal = 32 * nSimWords;
+    return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes switching activity of one node.]
+
+  Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Saig_ManComputeProbOne( int nOnes, int nSimWords )
+{
+    int nTotal = 32 * nSimWords;
+    return (float)nOnes / nTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes switching activity of one node.]
+
+  Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Saig_ManComputeProbOnePlus( int nOnes, int nSimWords, int fCompl )
+{
+    int nTotal = 32 * nSimWords;
+    if ( fCompl )
+        return (float)(nTotal-nOnes) / nTotal;
+    else
+        return (float)nOnes / nTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute switching probabilities of all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManComputeSwitchProb4s( Aig_Man_t * p, int nFrames, int nPref, int fProbOne )
+{
+    Saig_SimObj_t * pAig, * pEntry;
+    Vec_Int_t * vSwitching;
+    float * pSwitching;
+    int nFramesReal;
+    abctime clk;//, clkTotal = Abc_Clock();
+    vSwitching = Vec_IntStart( Aig_ManObjNumMax(p) );
+    pSwitching = (float *)vSwitching->pArray;
+clk = Abc_Clock();
+    pAig = Saig_ManCreateMan( p );
+//ABC_PRT( "\nCreation  ", Abc_Clock() - clk );
+
+    Aig_ManRandom( 1 );
+    // get the number of  frames to simulate
+    // if the parameter "seqsimframes" is defined, use it
+    // otherwise, use the given number of frames "nFrames"
+    nFramesReal = nFrames;
+    if ( Abc_FrameReadFlag("seqsimframes") )
+        nFramesReal = atoi( Abc_FrameReadFlag("seqsimframes") );
+    if ( nFramesReal <= nPref )
+    {
+        printf( "The total number of frames (%d) should exceed prefix (%d).\n", nFramesReal, nPref );\
+        printf( "Setting the total number of frames to be %d.\n", nFrames );
+        nFramesReal = nFrames;
+    }
+//printf( "Simulating %d frames.\n", nFramesReal );
+clk = Abc_Clock();
+    Saig_ManSimulateFrames( pAig, nFramesReal, nPref );
+//ABC_PRT( "Simulation", Abc_Clock() - clk );
+clk = Abc_Clock();
+    for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ )
+    {
+/*
+        if ( pEntry->Type == AIG_OBJ_AND )
+        {
+        Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pEntry );
+        Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pEntry );
+        printf( "%5.2f = %5.2f * %5.2f  (%7.4f)\n", 
+            Saig_ManComputeProbOnePlus( pEntry->Number, nFrames - nPref, 0 ),
+            Saig_ManComputeProbOnePlus( pObj0->Number, nFrames - nPref, Saig_SimObjFaninC0(pEntry) ),
+            Saig_ManComputeProbOnePlus( pObj1->Number, nFrames - nPref, Saig_SimObjFaninC1(pEntry) ),
+            Saig_ManComputeProbOnePlus( pEntry->Number, nFrames - nPref, 0 ) -
+            Saig_ManComputeProbOnePlus( pObj0->Number, nFrames - nPref, Saig_SimObjFaninC0(pEntry) ) *
+            Saig_ManComputeProbOnePlus( pObj1->Number, nFrames - nPref, Saig_SimObjFaninC1(pEntry) )
+            );
+        }
+*/
+        if ( fProbOne )
+            pSwitching[pEntry-pAig] = Saig_ManComputeProbOne( pEntry->Number, nFramesReal - nPref );
+        else
+            pSwitching[pEntry-pAig] = Saig_ManComputeSwitching( pEntry->Number, nFramesReal - nPref );
+//printf( "%3d : %7.2f\n", pEntry-pAig, pSwitching[pEntry-pAig] );
+    }
+    ABC_FREE( pAig );
+//ABC_PRT( "Switch    ", Abc_Clock() - clk );
+//ABC_PRT( "TOTAL     ", Abc_Clock() - clkTotal );
+
+//    Aig_CManCreate( p );
+    return vSwitching;
+}
+
+
+
+
+typedef struct Aig_CMan_t_ Aig_CMan_t;
+struct Aig_CMan_t_
+{
+    // parameters
+    int             nIns;
+    int             nNodes;
+    int             nOuts;
+    // current state
+    int             iNode;
+    int             iDiff0;
+    int             iDiff1;
+    unsigned char * pCur;
+    // stored data
+    int             iPrev;
+    int             nBytes;
+    unsigned char   Data[0];
+};
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_CMan_t * Aig_CManStart( int nIns, int nNodes, int nOuts )
+{
+    Aig_CMan_t * p;
+    p = (Aig_CMan_t *)ABC_ALLOC( char, sizeof(Aig_CMan_t) + 2*(2*nNodes + nOuts) );
+    memset( p, 0, sizeof(Aig_CMan_t) );
+    // set parameters
+    p->nIns = nIns;
+    p->nOuts = nOuts;
+    p->nNodes = nNodes;
+    p->nBytes = 2*(2*nNodes + nOuts);
+    // prepare the manager
+    p->iNode = 1 + p->nIns;
+    p->iPrev = -1;
+    p->pCur = p->Data;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_CManStop( Aig_CMan_t * p )
+{
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_CManRestart( Aig_CMan_t * p )
+{
+    assert( p->iNode == 1 + p->nIns + p->nNodes + p->nOuts );
+    p->iNode = 1 + p->nIns;
+    p->iPrev = -1;
+    p->pCur = p->Data;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_CManStoreNum( Aig_CMan_t * p, unsigned x )
+{
+    while ( x & ~0x7f )
+    {
+        *p->pCur++ = (x & 0x7f) | 0x80;
+        x >>= 7;
+    }
+    *p->pCur++ = x;
+    assert( p->pCur - p->Data < p->nBytes - 10 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_CManRestoreNum( Aig_CMan_t * p )
+{
+    int ch, i, x = 0;
+    for ( i = 0; (ch = *p->pCur++) & 0x80; i++ )
+        x |= (ch & 0x7f) << (7 * i);
+    return x | (ch << (7 * i));
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_CManAddNode( Aig_CMan_t * p, int iFan0, int iFan1 )
+{
+    assert( iFan0 < iFan1 );
+    assert( iFan1 < (p->iNode << 1) );
+    Aig_CManStoreNum( p, (p->iNode++ << 1) - iFan1 );
+    Aig_CManStoreNum( p, iFan1 - iFan0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_CManAddPo( Aig_CMan_t * p, int iFan0 )
+{
+    if ( p->iPrev == -1 )
+        Aig_CManStoreNum( p, p->iNode - iFan0 );
+    else if ( p->iPrev <= iFan0 )
+        Aig_CManStoreNum( p, (iFan0 - p->iPrev) << 1 );
+    else 
+        Aig_CManStoreNum( p,((p->iPrev - iFan0) << 1) | 1 );
+    p->iPrev = iFan0;
+    p->iNode++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_CManGetNode( Aig_CMan_t * p, int * piFan0, int * piFan1 )
+{
+    *piFan1 = (p->iNode++ << 1) - Aig_CManRestoreNum( p );
+    *piFan0 = *piFan1 - Aig_CManRestoreNum( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_CManGetPo( Aig_CMan_t * p )
+{
+    int Num = Aig_CManRestoreNum( p );
+    if ( p->iPrev == -1 )
+        p->iPrev = p->iNode;
+    p->iNode++;
+    if ( Num & 1 )
+        return p->iPrev = p->iPrev + (Num >> 1);
+    return p->iPrev = p->iPrev - (Num >> 1);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute switching probabilities of all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_CMan_t * Aig_CManCreate( Aig_Man_t * p )
+{
+    Aig_CMan_t * pCMan;
+    Aig_Obj_t * pObj;
+    int i;
+    pCMan = Aig_CManStart( Aig_ManCiNum(p), Aig_ManNodeNum(p), Aig_ManCoNum(p) );
+    Aig_ManForEachNode( p, pObj, i )
+        Aig_CManAddNode( pCMan, 
+            (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj), 
+            (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj) );
+    Aig_ManForEachCo( p, pObj, i )
+        Aig_CManAddPo( pCMan, 
+            (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj) ); 
+    printf( "\nBytes alloc = %5d.  Bytes used = %7d.  Ave per node = %4.2f. \n", 
+        pCMan->nBytes, (int)(pCMan->pCur - pCMan->Data), 
+        1.0 * (pCMan->pCur - pCMan->Data) / (pCMan->nNodes + pCMan->nOuts ) );
+//    Aig_CManStop( pCMan );
+    return pCMan;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigSynch.c b/abc-build/src/aig/saig/saigSynch.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigSynch.c
@@ -0,0 +1,665 @@
+/**CFile****************************************************************
+
+  FileName    [saigSynch.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Computation of synchronizing sequence.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigSynch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+//        0  1  x
+//       00 01 11
+// 0  00 00 00 00
+// 1  01 00 01 11
+// x  11 00 11 11
+
+static inline unsigned Saig_SynchNot( unsigned w )
+{
+    return w^((~(w&(w>>1)))&0x55555555);
+}
+static inline unsigned Saig_SynchAnd( unsigned u, unsigned w )
+{
+    return (u&w)|((((u&(u>>1)&w&~(w>>1))|(w&(w>>1)&u&~(u>>1)))&0x55555555)<<1);
+}
+static inline unsigned Saig_SynchRandomBinary() 
+{ 
+    return Aig_ManRandom(0) & 0x55555555;               
+}
+static inline unsigned Saig_SynchRandomTernary() 
+{ 
+    unsigned w = Aig_ManRandom(0);
+    return w^((~w)&(w>>1)&0x55555555);        
+}
+static inline unsigned Saig_SynchTernary( int v ) 
+{
+    assert( v == 0 || v == 1 || v == 3 );
+    return v? ((v==1)? 0x55555555 : 0xffffffff) : 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Initializes registers to the ternary state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_SynchSetConstant1( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords )
+{
+    Aig_Obj_t * pObj;
+    unsigned * pSim;
+    int w;
+    pObj = Aig_ManConst1( pAig );
+    pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id );
+    for ( w = 0; w < nWords; w++ )
+        pSim[w] = 0x55555555;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Initializes registers to the ternary state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_SynchInitRegsTernary( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords )
+{
+    Aig_Obj_t * pObj;
+    unsigned * pSim;
+    int i, w;
+    Saig_ManForEachLo( pAig, pObj, i )
+    {
+        pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id );
+        for ( w = 0; w < nWords; w++ )
+            pSim[w] = 0xffffffff;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Initializes registers to the given binary state.]
+
+  Description [The binary state is stored in pObj->fMarkA.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_SynchInitRegsBinary( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords )
+{
+    Aig_Obj_t * pObj;
+    unsigned * pSim;
+    int i, w;
+    Saig_ManForEachLo( pAig, pObj, i )
+    {
+        pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id );
+        for ( w = 0; w < nWords; w++ )
+            pSim[w] = Saig_SynchTernary( pObj->fMarkA );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Initializes random binary primary inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_SynchInitPisRandom( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords )
+{
+    Aig_Obj_t * pObj;
+    unsigned * pSim;
+    int i, w;
+    Saig_ManForEachPi( pAig, pObj, i )
+    {
+        pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id );
+        for ( w = 0; w < nWords; w++ )
+            pSim[w] = Saig_SynchRandomBinary();
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Initializes random binary primary inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_SynchInitPisGiven( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords, char * pValues )
+{
+    Aig_Obj_t * pObj;
+    unsigned * pSim;
+    int i, w;
+    Saig_ManForEachPi( pAig, pObj, i )
+    {
+        pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id );
+        for ( w = 0; w < nWords; w++ )
+            pSim[w] = Saig_SynchTernary( pValues[i] );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs ternary simulation of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_SynchTernarySimulate( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords )
+{
+    Aig_Obj_t * pObj;
+    unsigned * pSim0, * pSim1, * pSim;
+    int i, w;
+    // simulate nodes
+    Aig_ManForEachNode( pAig, pObj, i )
+    {
+        pSim  = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id );
+        pSim0 = (unsigned *)Vec_PtrEntry( vSimInfo, Aig_ObjFaninId0(pObj) );
+        pSim1 = (unsigned *)Vec_PtrEntry( vSimInfo, Aig_ObjFaninId1(pObj) );
+        if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) )
+        {
+            for ( w = 0; w < nWords; w++ )
+                pSim[w] = Saig_SynchAnd( Saig_SynchNot(pSim0[w]), Saig_SynchNot(pSim1[w]) );
+        }
+        else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) )
+        {
+            for ( w = 0; w < nWords; w++ )
+                pSim[w] = Saig_SynchAnd( pSim0[w], Saig_SynchNot(pSim1[w]) );
+        }
+        else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) )
+        {
+            for ( w = 0; w < nWords; w++ )
+                pSim[w] = Saig_SynchAnd( Saig_SynchNot(pSim0[w]), pSim1[w] );
+        }
+        else // if ( !Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) )
+        {
+            for ( w = 0; w < nWords; w++ )
+                pSim[w] = Saig_SynchAnd( pSim0[w], pSim1[w] );
+        }
+    }
+    // transfer values to register inputs
+    Saig_ManForEachLi( pAig, pObj, i )
+    {
+        pSim  = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id );
+        pSim0 = (unsigned *)Vec_PtrEntry( vSimInfo, Aig_ObjFaninId0(pObj) );
+        if ( Aig_ObjFaninC0(pObj) )
+        {
+            for ( w = 0; w < nWords; w++ )
+                pSim[w] = Saig_SynchNot( pSim0[w] );
+        }
+        else
+        {
+            for ( w = 0; w < nWords; w++ )
+                pSim[w] = pSim0[w];
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs ternary simulation of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_SynchTernaryTransferState( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords )
+{
+    Aig_Obj_t * pObjLi, * pObjLo;
+    unsigned * pSim0, * pSim1;
+    int i, w;
+    Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+    {
+        pSim0 = (unsigned *)Vec_PtrEntry( vSimInfo, pObjLi->Id );
+        pSim1 = (unsigned *)Vec_PtrEntry( vSimInfo, pObjLo->Id );
+        for ( w = 0; w < nWords; w++ )
+            pSim1[w] = pSim0[w];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of Xs in the smallest ternary pattern.]
+
+  Description [Returns the number of this pattern.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_SynchCountX( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords, int * piPat )
+{
+    Aig_Obj_t * pObj;
+    unsigned * pSim;
+    int * pCounters, i, w, b;
+    int iPatBest, iTernMin;
+    // count the number of ternary values in each pattern
+    pCounters = ABC_CALLOC( int, nWords * 16 );
+    Saig_ManForEachLi( pAig, pObj, i )
+    {
+        pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id );
+        for ( w = 0; w < nWords; w++ )
+            for ( b = 0; b < 16; b++ )
+                if ( ((pSim[w] >> (b << 1)) & 3) == 3 )
+                    pCounters[16 * w + b]++;
+    }
+    // get the best pattern
+    iPatBest = -1;
+    iTernMin = 1 + Saig_ManRegNum(pAig);
+    for ( b = 0; b < 16 * nWords; b++ )
+        if ( iTernMin > pCounters[b] )
+        {
+            iTernMin = pCounters[b];
+            iPatBest = b;
+            if ( iTernMin == 0 )
+                break;
+        }
+    ABC_FREE( pCounters );
+    *piPat = iPatBest;
+    return iTernMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Saves the best pattern found and initializes the registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_SynchSavePattern( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords, int iPat, Vec_Str_t * vSequence )
+{
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    unsigned * pSim;
+    int Counter, Value, i, w;
+    assert( iPat < 16 * nWords );
+    Saig_ManForEachPi( pAig, pObj, i )
+    {
+        pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id );
+        Value = (pSim[iPat>>4] >> ((iPat&0xf) << 1)) & 3;
+        Vec_StrPush( vSequence, (char)Value );
+//        printf( "%d ", Value );
+    }
+//    printf( "\n" );
+    Counter = 0;
+    Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+    {
+        pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObjLi->Id );
+        Value = (pSim[iPat>>4] >> ((iPat&0xf) << 1)) & 3;
+        Counter += (Value == 3);
+        // save patern in the same register
+        pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObjLo->Id );
+        for ( w = 0; w < nWords; w++ )
+            pSim[w] = Saig_SynchTernary( Value );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implement synchronizing sequence.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_SynchSequenceRun( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, Vec_Str_t * vSequence, int fTernary )
+{
+    unsigned * pSim;
+    Aig_Obj_t * pObj;
+    int Counter, nIters, Value, i;
+    assert( Vec_StrSize(vSequence) % Saig_ManPiNum(pAig) == 0 );
+    nIters = Vec_StrSize(vSequence) / Saig_ManPiNum(pAig);
+    Saig_SynchSetConstant1( pAig, vSimInfo, 1 );
+    if ( fTernary )
+        Saig_SynchInitRegsTernary( pAig, vSimInfo, 1 ); 
+    else
+        Saig_SynchInitRegsBinary( pAig, vSimInfo, 1 ); 
+    for ( i = 0; i < nIters; i++ )
+    {
+        Saig_SynchInitPisGiven( pAig, vSimInfo, 1, Vec_StrArray(vSequence) + i * Saig_ManPiNum(pAig) );
+        Saig_SynchTernarySimulate( pAig, vSimInfo, 1 );
+        Saig_SynchTernaryTransferState( pAig, vSimInfo, 1 );
+    }
+    // save the resulting state in the registers
+    Counter = 0;
+    Saig_ManForEachLo( pAig, pObj, i )
+    {
+        pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id );
+        Value = pSim[0] & 3;
+        assert( Value != 2 );
+        Counter += (Value == 3);
+        pObj->fMarkA = Value;
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determines synchronizing sequence using ternary simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Saig_SynchSequence( Aig_Man_t * pAig, int nWords )
+{
+    int nStepsMax = 100;  // the maximum number of simulation steps
+    int nTriesMax = 100;  // the maximum number of attempts at each step
+    int fVerify   =   1;  // verify the resulting pattern
+    Vec_Str_t * vSequence;
+    Vec_Ptr_t * vSimInfo;
+    int nTerPrev, nTerCur = 0, nTerCur2;
+    int iPatBest, RetValue, s, t;
+    assert( Saig_ManRegNum(pAig) > 0 );
+    // reset random numbers
+    Aig_ManRandom( 1 );
+    // start the sequence
+    vSequence = Vec_StrAlloc( 20 * Saig_ManRegNum(pAig) );
+    // create sim info and init registers
+    vSimInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(pAig), nWords );
+    Saig_SynchSetConstant1( pAig, vSimInfo, nWords );
+    // iterate over the timeframes
+    nTerPrev = Saig_ManRegNum(pAig);
+    Saig_SynchInitRegsTernary( pAig, vSimInfo, nWords );
+    for ( s = 0; s < nStepsMax && nTerPrev > 0; s++ )
+    {
+        for ( t = 0; t < nTriesMax; t++ )
+        {
+            Saig_SynchInitPisRandom( pAig, vSimInfo, nWords );
+            Saig_SynchTernarySimulate( pAig, vSimInfo, nWords );
+            nTerCur = Saig_SynchCountX( pAig, vSimInfo, nWords, &iPatBest );
+            if ( nTerCur < nTerPrev )
+                break;
+        }
+        if ( t == nTriesMax )
+            break;
+        nTerCur2 = Saig_SynchSavePattern( pAig, vSimInfo, nWords, iPatBest, vSequence );
+        assert( nTerCur == nTerCur2 );
+        nTerPrev = nTerCur;
+    }
+    if ( nTerPrev > 0 )
+    {
+        printf( "Count not initialize %d registers.\n", nTerPrev );
+        Vec_PtrFree( vSimInfo );
+        Vec_StrFree( vSequence );
+        return NULL;
+    }
+    // verify that the sequence is correct
+    if ( fVerify )
+    {
+        RetValue = Saig_SynchSequenceRun( pAig, vSimInfo, vSequence, 1 );
+        assert( RetValue == 0 );
+        Aig_ManCleanMarkA( pAig );
+    }
+    Vec_PtrFree( vSimInfo );
+    return vSequence;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG to have constant-0 initial state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManDupInitZero( Aig_Man_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Saig_ManForEachPi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    Saig_ManForEachLo( p, pObj, i )
+        pObj->pData = Aig_NotCond( Aig_ObjCreateCi( pNew ), pObj->fMarkA );
+    Aig_ManForEachNode( p, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    Saig_ManForEachPo( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    Saig_ManForEachLi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCo( pNew, Aig_NotCond( Aig_ObjChild0Copy(pObj), pObj->fMarkA ) );
+    Aig_ManSetRegNum( pNew, Saig_ManRegNum(p) );
+    assert( Aig_ManNodeNum(pNew) == Aig_ManNodeNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determines synchronizing sequence using ternary simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_SynchSequenceApply( Aig_Man_t * pAig, int nWords, int fVerbose )
+{
+    Aig_Man_t * pAigZero;
+    Vec_Str_t * vSequence;
+    Vec_Ptr_t * vSimInfo;
+    int RetValue;
+    abctime clk;
+
+clk = Abc_Clock();
+    // derive synchronization sequence
+    vSequence = Saig_SynchSequence( pAig, nWords );
+    if ( vSequence == NULL )
+        printf( "Design 1: Synchronizing sequence is not found. " );
+    else if ( fVerbose )
+        printf( "Design 1: Synchronizing sequence of length %4d is found. ", Vec_StrSize(vSequence) / Saig_ManPiNum(pAig) );
+    if ( fVerbose )
+    {
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    else
+        printf( "\n" );
+    if ( vSequence == NULL )
+    {
+        printf( "Quitting synchronization.\n" );
+        return NULL;
+    }
+
+    // apply synchronization sequence
+    vSimInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(pAig), 1 );
+    RetValue = Saig_SynchSequenceRun( pAig, vSimInfo, vSequence, 1 );
+    assert( RetValue == 0 );
+    // duplicate 
+    pAigZero = Saig_ManDupInitZero( pAig );
+    // cleanup
+    Vec_PtrFree( vSimInfo );
+    Vec_StrFree( vSequence );
+    Aig_ManCleanMarkA( pAig );
+    return pAigZero;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates SEC miter for two designs without initial state.]
+
+  Description [The designs (pAig1 and pAig2) are assumed to have ternary 
+  initial state. Determines synchronizing sequences using ternary simulation.
+  Simulates the sequences on both designs to come up with equivalent binary 
+  initial states. Create seq miter for the designs starting in these states.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_Synchronize( Aig_Man_t * pAig1, Aig_Man_t * pAig2, int nWords, int fVerbose )
+{
+    Aig_Man_t * pAig1z, * pAig2z, * pMiter;
+    Vec_Str_t * vSeq1, * vSeq2;
+    Vec_Ptr_t * vSimInfo;
+    int RetValue;
+    abctime clk;
+/*
+    {
+        unsigned u = Saig_SynchRandomTernary();
+        unsigned w = Saig_SynchRandomTernary();
+        unsigned x = Saig_SynchNot( u );
+        unsigned y = Saig_SynchNot( w );
+        unsigned z = Saig_SynchAnd( x, y );
+
+        Extra_PrintBinary( stdout, &u, 32 );  printf( "\n" );
+        Extra_PrintBinary( stdout, &w, 32 );  printf( "\n" );  printf( "\n" );
+        Extra_PrintBinary( stdout, &x, 32 );  printf( "\n" );
+        Extra_PrintBinary( stdout, &y, 32 );  printf( "\n" );  printf( "\n" );
+        Extra_PrintBinary( stdout, &z, 32 );  printf( "\n" );
+    }
+*/
+    // report statistics
+    if ( fVerbose )
+    {
+        printf( "Design 1: " );
+        Aig_ManPrintStats( pAig1 );
+        printf( "Design 2: " );
+        Aig_ManPrintStats( pAig2 );
+    }
+
+    // synchronize the first design
+    clk = Abc_Clock();
+    vSeq1 = Saig_SynchSequence( pAig1, nWords );
+    if ( vSeq1 == NULL )
+        printf( "Design 1: Synchronizing sequence is not found. " );
+    else if ( fVerbose )
+        printf( "Design 1: Synchronizing sequence of length %4d is found. ", Vec_StrSize(vSeq1) / Saig_ManPiNum(pAig1) );
+    if ( fVerbose )
+    {
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    else
+        printf( "\n" );
+
+    // synchronize the first design
+    clk = Abc_Clock();
+    vSeq2 = Saig_SynchSequence( pAig2, nWords );
+    if ( vSeq2 == NULL )
+        printf( "Design 2: Synchronizing sequence is not found. " );
+    else if ( fVerbose )
+        printf( "Design 2: Synchronizing sequence of length %4d is found. ", Vec_StrSize(vSeq2) / Saig_ManPiNum(pAig2) );
+    if ( fVerbose )
+    {
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    else
+        printf( "\n" );
+
+    // quit if one of the designs cannot be synchronized
+    if ( vSeq1 == NULL || vSeq2 == NULL )
+    {
+        printf( "Quitting synchronization.\n" );
+        if ( vSeq1 ) Vec_StrFree( vSeq1 );
+        if ( vSeq2 ) Vec_StrFree( vSeq2 );
+        return NULL;
+    }
+    clk = Abc_Clock();
+    vSimInfo = Vec_PtrAllocSimInfo( Abc_MaxInt( Aig_ManObjNumMax(pAig1), Aig_ManObjNumMax(pAig2) ), 1 );
+
+    // process Design 1
+    RetValue = Saig_SynchSequenceRun( pAig1, vSimInfo, vSeq1, 1 );
+    assert( RetValue == 0 );
+    RetValue = Saig_SynchSequenceRun( pAig1, vSimInfo, vSeq2, 0 );
+    assert( RetValue == 0 );
+
+    // process Design 2
+    RetValue = Saig_SynchSequenceRun( pAig2, vSimInfo, vSeq2, 1 );
+    assert( RetValue == 0 );
+
+    // duplicate designs
+    pAig1z = Saig_ManDupInitZero( pAig1 );
+    pAig2z = Saig_ManDupInitZero( pAig2 );
+    pMiter = Saig_ManCreateMiter( pAig1z, pAig2z, 0 );
+    Aig_ManCleanup( pMiter );
+    Aig_ManStop( pAig1z );
+    Aig_ManStop( pAig2z );
+
+    // cleanup
+    Vec_PtrFree( vSimInfo );
+    Vec_StrFree( vSeq1 );
+    Vec_StrFree( vSeq2 );
+    Aig_ManCleanMarkA( pAig1 );
+    Aig_ManCleanMarkA( pAig2 );
+
+    if ( fVerbose )
+    {
+        printf( "Miter of the synchronized designs is constructed.         " );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    return pMiter;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigTempor.c b/abc-build/src/aig/saig/saigTempor.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigTempor.c
@@ -0,0 +1,256 @@
+/**CFile****************************************************************
+
+  FileName    [saigTempor.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Temporal decomposition.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigTempor.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+#include "sat/bmc/bmc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates initialized timeframes for temporal decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManTemporFrames( Aig_Man_t * pAig, int nFrames )
+{
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i, f;
+    // start the frames package
+    Aig_ManCleanData( pAig );
+    pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames );
+    pFrames->pName = Abc_UtilStrsav( pAig->pName );
+    // initiliaze the flops
+    Saig_ManForEachLo( pAig, pObj, i )
+        pObj->pData = Aig_ManConst0(pFrames);
+    // for each timeframe
+    for ( f = 0; f < nFrames; f++ )
+    {
+        Aig_ManConst1(pAig)->pData = Aig_ManConst1(pFrames);
+        Saig_ManForEachPi( pAig, pObj, i )
+            pObj->pData = Aig_ObjCreateCi(pFrames);
+        Aig_ManForEachNode( pAig, pObj, i )
+            pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+        Aig_ManForEachCo( pAig, pObj, i )
+            pObj->pData = Aig_ObjChild0Copy(pObj);
+        Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+            pObjLo->pData = pObjLi->pData;
+    }
+    // create POs for the flop inputs
+    Saig_ManForEachLi( pAig, pObj, i )
+        Aig_ObjCreateCo( pFrames, (Aig_Obj_t *)pObj->pData );
+    Aig_ManCleanup( pFrames );
+    return pFrames;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManTemporDecompose( Aig_Man_t * pAig, int nFrames )
+{
+    Aig_Man_t * pAigNew, * pFrames;
+    Aig_Obj_t * pObj, * pReset;
+    int i;
+    if ( pAig->nConstrs > 0 )
+    {
+        printf( "The AIG manager should have no constraints.\n" );
+        return NULL;
+    }
+    // create initialized timeframes
+    pFrames = Saig_ManTemporFrames( pAig, nFrames );
+    assert( Aig_ManCoNum(pFrames) == Aig_ManRegNum(pAig) );
+
+    // start the new manager
+    Aig_ManCleanData( pAig );
+    pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) );
+    pAigNew->pName = Abc_UtilStrsav( pAig->pName );
+    // map the constant node and primary inputs
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew );
+    Saig_ManForEachPi( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pAigNew );
+
+    // insert initialization logic
+    Aig_ManConst1(pFrames)->pData = Aig_ManConst1( pAigNew );
+    Aig_ManForEachCi( pFrames, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pAigNew );
+    Aig_ManForEachNode( pFrames, pObj, i )
+        pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    Aig_ManForEachCo( pFrames, pObj, i )
+        pObj->pData = Aig_ObjChild0Copy(pObj);
+
+    // create reset latch (the first one among the latches)
+    pReset = Aig_ObjCreateCi( pAigNew );
+
+    // create flop output values
+    Saig_ManForEachLo( pAig, pObj, i )
+        pObj->pData = Aig_Mux( pAigNew, pReset, Aig_ObjCreateCi(pAigNew), (Aig_Obj_t *)Aig_ManCo(pFrames, i)->pData );
+    Aig_ManStop( pFrames );
+
+    // add internal nodes of this frame
+    Aig_ManForEachNode( pAig, pObj, i )
+        pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // create primary outputs
+    Saig_ManForEachPo( pAig, pObj, i )
+        Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) );
+
+    // create reset latch (the first one among the latches)
+    Aig_ObjCreateCo( pAigNew, Aig_ManConst1(pAigNew) );
+    // create latch inputs
+    Saig_ManForEachLi( pAig, pObj, i )
+        Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) );
+
+    // finalize
+    Aig_ManCleanup( pAigNew );
+    Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig)+1 ); // + reset latch (011111...)
+    return pAigNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find index of first non-zero entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Vec_IntLastNonZeroBeforeLimit( Vec_Int_t * vTemp, int Limit )
+{
+    int Entry, i;
+    if ( vTemp == NULL )
+        return -1;
+    Vec_IntForEachEntryReverse( vTemp, Entry, i )
+    {
+        if ( i >= Limit )
+            continue;
+        if ( Entry )
+            return i;
+    }
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManTempor( Aig_Man_t * pAig, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fUseTransSigs, int fVerbose, int fVeryVerbose )
+{ 
+    extern int Saig_ManPhasePrefixLength( Aig_Man_t * p, int fVerbose, int fVeryVerbose, Vec_Int_t ** pvTrans );
+
+    Vec_Int_t * vTransSigs = NULL;
+    int RetValue, nFramesFinished = -1;
+    assert( nFrames >= 0 ); 
+    if ( nFrames == 0 )
+    {
+        nFrames = Saig_ManPhasePrefixLength( pAig, fVerbose, fVeryVerbose, &vTransSigs );
+        if ( nFrames == 0 )
+        {
+            Vec_IntFreeP( &vTransSigs );
+            printf( "The leading sequence has length 0. Temporal decomposition is not performed.\n" );
+            return NULL;
+        }
+        if ( nFrames == 1 )
+        {
+            Vec_IntFreeP( &vTransSigs );
+            printf( "The leading sequence has length 1. Temporal decomposition is not performed.\n" );
+            return NULL;
+        }
+        if ( fUseTransSigs )
+        {
+            int Entry, i, iLast = -1;
+            Vec_IntForEachEntry( vTransSigs, Entry, i )
+                iLast = Entry ? i :iLast;
+            if ( iLast > 0 && iLast < nFrames )
+            {
+                Abc_Print( 1, "Reducing frame count from %d to %d to fit the last transient.\n", nFrames, iLast );
+                nFrames = iLast;
+            }
+        }
+        Abc_Print( 1, "Using computed frame number (%d).\n", nFrames );
+    }
+    else
+        Abc_Print( 1, "Using user-given frame number (%d).\n", nFrames );
+    // run BMC2
+    if ( fUseBmc )
+    {
+        RetValue = Saig_BmcPerform( pAig, 0, nFrames, 2000, TimeOut, nConfLimit, 0, fVerbose, 0, &nFramesFinished, 0 );
+        if ( RetValue == 0 )
+        {
+            Vec_IntFreeP( &vTransSigs );
+            printf( "A cex found in the first %d frames.\n", nFrames );
+            return NULL;
+        }
+        if ( nFramesFinished + 1 < nFrames )
+        {
+            int iLastBefore = Vec_IntLastNonZeroBeforeLimit( vTransSigs, nFramesFinished );
+            if ( iLastBefore < 1 || !fUseTransSigs )
+            {
+                Vec_IntFreeP( &vTransSigs );
+                printf( "BMC for %d frames could not be completed. A cex may exist!\n", nFrames );
+                return NULL;
+            }
+            assert( iLastBefore < nFramesFinished );
+            printf( "BMC succeeded to frame %d. Adjusting frame count to be (%d) based on the last transient signal.\n", nFramesFinished, iLastBefore );
+            nFrames = iLastBefore;
+        }
+    }
+    Vec_IntFreeP( &vTransSigs );
+    return Saig_ManTemporDecompose( pAig, nFrames );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigTrans.c b/abc-build/src/aig/saig/saigTrans.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigTrans.c
@@ -0,0 +1,428 @@
+/**CFile****************************************************************
+
+  FileName    [saigTrans.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Dynamic simplication of the transition relation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigTrans.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+#include "proof/fra/fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/* 
+    A similar approach is presented in the his paper:
+    A. Kuehlmann. Dynamic transition relation simplification for 
+    bounded property checking. ICCAD'04, pp. 50-57.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Maps a node/frame into a node of a different manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Saig_ManStartMap1( Aig_Man_t * p, int nFrames )
+{
+    Vec_Int_t * vMap;
+    int i;
+    assert( p->pData == NULL );
+    vMap = Vec_IntAlloc( Aig_ManObjNumMax(p) * nFrames );
+    for ( i = 0; i < vMap->nCap; i++ )
+        vMap->pArray[i] = -1;
+    vMap->nSize = vMap->nCap;
+    p->pData = vMap;
+}
+static inline void Saig_ManStopMap1( Aig_Man_t * p )
+{
+    assert( p->pData != NULL );
+    Vec_IntFree( (Vec_Int_t *)p->pData );
+    p->pData = NULL;
+}
+static inline int Saig_ManHasMap1( Aig_Man_t * p )
+{
+    return (int)(p->pData != NULL);
+}
+static inline void Saig_ManSetMap1( Aig_Man_t * p, Aig_Obj_t * pOld, int f1, Aig_Obj_t * pNew ) 
+{
+    Vec_Int_t * vMap = (Vec_Int_t *)p->pData;
+    int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id;
+    assert( !Aig_IsComplement(pOld) );
+    assert( !Aig_IsComplement(pNew) );
+    Vec_IntWriteEntry( vMap, nOffset, pNew->Id );
+}
+static inline int Saig_ManGetMap1( Aig_Man_t * p, Aig_Obj_t * pOld, int f1 )
+{
+    Vec_Int_t * vMap = (Vec_Int_t *)p->pData;
+    int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id;
+    return Vec_IntEntry( vMap, nOffset );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Maps a node/frame into a node/frame of a different manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Saig_ManStartMap2( Aig_Man_t * p, int nFrames )
+{
+    Vec_Int_t * vMap;
+    int i;
+    assert( p->pData2 == NULL );
+    vMap = Vec_IntAlloc( Aig_ManObjNumMax(p) * nFrames * 2 );
+    for ( i = 0; i < vMap->nCap; i++ )
+        vMap->pArray[i] = -1;
+    vMap->nSize = vMap->nCap;
+    p->pData2 = vMap;
+}
+static inline void Saig_ManStopMap2( Aig_Man_t * p )
+{
+    assert( p->pData2 != NULL );
+    Vec_IntFree( (Vec_Int_t *)p->pData2 );
+    p->pData2 = NULL;
+}
+static inline int Saig_ManHasMap2( Aig_Man_t * p )
+{
+    return (int)(p->pData2 != NULL);
+}
+static inline void Saig_ManSetMap2( Aig_Man_t * p, Aig_Obj_t * pOld, int f1, Aig_Obj_t * pNew, int f2 ) 
+{
+    Vec_Int_t * vMap = (Vec_Int_t *)p->pData2;
+    int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id;
+    assert( !Aig_IsComplement(pOld) );
+    assert( !Aig_IsComplement(pNew) );
+    Vec_IntWriteEntry( vMap, 2*nOffset + 0, pNew->Id );
+    Vec_IntWriteEntry( vMap, 2*nOffset + 1, f2 );
+}
+static inline int Saig_ManGetMap2( Aig_Man_t * p, Aig_Obj_t * pOld, int f1, int * pf2 )
+{
+    Vec_Int_t * vMap = (Vec_Int_t *)p->pData2;
+    int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id;
+    *pf2 = Vec_IntEntry( vMap, 2*nOffset + 1 );
+    return Vec_IntEntry( vMap, 2*nOffset );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create mapping for the first nFrames timeframes of pAig.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManCreateMapping( Aig_Man_t * pAig, Aig_Man_t * pFrames, int nFrames )
+{
+    Aig_Obj_t * pObj, * pObjFrame, * pObjRepr;
+    int i, f, iNum, iFrame;
+    assert( pFrames->pReprs != NULL ); // mapping from nodes into their representatives
+    // start step mapping for both orignal manager and fraig
+    Saig_ManStartMap2( pAig, nFrames );
+    Saig_ManStartMap2( pFrames, 1 );
+    // for each object in each frame
+    for ( f = 0; f < nFrames; f++ )
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+        // get the frame object
+        iNum = Saig_ManGetMap1( pAig, pObj, f );
+        pObjFrame = Aig_ManObj( pFrames, iNum );
+        // if the node has no prototype, map it into itself
+        if ( pObjFrame == NULL )
+        {
+            Saig_ManSetMap2( pAig, pObj, f, pObj, f );
+            continue;
+        }
+        // get the representative object
+        pObjRepr = Aig_ObjRepr( pFrames, pObjFrame );
+        if ( pObjRepr == NULL )
+            pObjRepr = pObjFrame;
+        // check if this is the first time this object is reached
+        if ( Saig_ManGetMap2( pFrames, pObjRepr, 0, &iFrame ) == -1 )
+            Saig_ManSetMap2( pFrames, pObjRepr, 0, pObj, f );
+        // set the map for the main object
+        iNum = Saig_ManGetMap2( pFrames, pObjRepr, 0, &iFrame );
+        Saig_ManSetMap2( pAig, pObj, f, Aig_ManObj(pAig, iNum), iFrame );
+    }
+    Saig_ManStopMap2( pFrames );
+    assert( Saig_ManHasMap2(pAig) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Unroll without initialization.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManFramesNonInitial( Aig_Man_t * pAig, int nFrames )
+{
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i, f;
+    assert( Saig_ManRegNum(pAig) > 0 );
+    // start node map
+    Saig_ManStartMap1( pAig, nFrames ); 
+    // start the new manager
+    pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames );
+    // map the constant node
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames );
+    // create variables for register outputs
+    Saig_ManForEachLo( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pFrames );
+    // add timeframes
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // create PI nodes for this frame
+        Saig_ManForEachPi( pAig, pObj, i )
+            pObj->pData = Aig_ObjCreateCi( pFrames );
+        // add internal nodes of this frame
+        Aig_ManForEachNode( pAig, pObj, i )
+            pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+        // create POs for this frame
+        Saig_ManForEachPo( pAig, pObj, i )
+            pObj->pData = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) );
+        // save register inputs
+        Saig_ManForEachLi( pAig, pObj, i )
+            pObj->pData = Aig_ObjChild0Copy(pObj);
+        // save the mapping
+        Aig_ManForEachObj( pAig, pObj, i )
+        {
+            assert( pObj->pData != NULL );
+            Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) );
+        }
+        // quit if the last frame
+        if ( f == nFrames - 1 )
+            break;
+        // transfer to register outputs
+        Saig_ManForEachLiLo(  pAig, pObjLi, pObjLo, i )
+            pObjLo->pData = pObjLi->pData;
+    }
+    // remember register outputs
+    Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+        Aig_ObjCreateCo( pFrames, (Aig_Obj_t *)pObjLi->pData );
+    Aig_ManCleanup( pFrames );
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Unroll with initialization and mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManFramesInitialMapped( Aig_Man_t * pAig, int nFrames, int nFramesMax, int fInit )
+{
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pRepr;
+    int i, f, iNum1, iNum2, iFrame2;
+    assert( nFrames <= nFramesMax );
+    assert( Saig_ManRegNum(pAig) > 0 );
+    // start node map
+    Saig_ManStartMap1( pAig, nFramesMax );
+    // start the new manager
+    pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFramesMax );
+    // create variables for register outputs
+    if ( fInit )
+    {
+        Saig_ManForEachLo( pAig, pObj, i )
+        {
+            pObj->pData = Aig_ManConst0( pFrames );
+            Saig_ManSetMap1( pAig, pObj, 0, Aig_Regular((Aig_Obj_t *)pObj->pData) );
+        }
+    }
+    else
+    {
+        // create PIs first
+        for ( f = 0; f < nFramesMax; f++ )
+            Saig_ManForEachPi( pAig, pObj, i )
+                Aig_ObjCreateCi( pFrames );
+        // create registers second
+        Saig_ManForEachLo( pAig, pObj, i )
+        {
+            pObj->pData = Aig_ObjCreateCi( pFrames );
+            Saig_ManSetMap1( pAig, pObj, 0, Aig_Regular((Aig_Obj_t *)pObj->pData) );
+        }
+    }
+    // add timeframes
+    for ( f = 0; f < nFramesMax; f++ )
+    {
+        // map the constant node
+        pObj = Aig_ManConst1(pAig);
+        pObj->pData = Aig_ManConst1( pFrames );
+        Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) );
+        // create PI nodes for this frame
+        Saig_ManForEachPi( pAig, pObj, i )
+        {
+            if ( fInit )
+                pObj->pData = Aig_ObjCreateCi( pFrames );
+            else
+                pObj->pData = Aig_ManCi( pFrames, f * Saig_ManPiNum(pAig) + i );
+            Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) );
+        }
+        // add internal nodes of this frame
+        Aig_ManForEachNode( pAig, pObj, i )
+        {
+            pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+            Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) );
+            if ( !Saig_ManHasMap2(pAig) )
+                continue;
+            if ( f < nFrames )
+            {
+                // get the mapping for this node
+                iNum2 = Saig_ManGetMap2( pAig, pObj, f, &iFrame2 );
+            }
+            else
+            {
+                // get the mapping for this node
+                iNum2 = Saig_ManGetMap2( pAig, pObj, nFrames-1, &iFrame2 );
+                iFrame2 += f - (nFrames-1);
+            }
+            assert( iNum2 != -1 );
+            assert( f >= iFrame2 );
+            // get the corresponding frames node
+            iNum1 = Saig_ManGetMap1( pAig, Aig_ManObj(pAig, iNum2), iFrame2 );
+            pRepr = Aig_ManObj( pFrames, iNum1 );
+            // compare the phases of these nodes
+            pObj->pData = Aig_NotCond( pRepr, pRepr->fPhase ^ Aig_ObjPhaseReal((Aig_Obj_t *)pObj->pData) );
+        }
+        // create POs for this frame
+        Saig_ManForEachPo( pAig, pObj, i )
+        {
+            pObj->pData = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) );
+            Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) );
+        }
+        // save register inputs
+        Saig_ManForEachLi( pAig, pObj, i )
+        {
+            pObj->pData = Aig_ObjChild0Copy(pObj);
+            Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) );
+        }
+        // quit if the last frame
+        if ( f == nFramesMax - 1 )
+            break;
+        // transfer to register outputs
+        Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+        {
+            pObjLo->pData = pObjLi->pData;
+            if ( !fInit )
+                Saig_ManSetMap1( pAig, pObjLo, f+1, Aig_Regular((Aig_Obj_t *)pObjLo->pData) );
+        }
+    }
+    if ( !fInit )
+    {
+        // create registers
+        Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+            Aig_ObjCreateCo( pFrames, (Aig_Obj_t *)pObjLi->pData );
+        // set register number
+        Aig_ManSetRegNum( pFrames, pAig->nRegs );
+    }
+    Aig_ManCleanup( pFrames );
+    Saig_ManStopMap1( pAig );
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements dynamic simplification.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManTimeframeSimplify( Aig_Man_t * pAig, int nFrames, int nFramesMax, int fInit, int fVerbose )
+{
+//    extern Aig_Man_t * Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax, int fProve );
+    Aig_Man_t * pFrames, * pFraig, * pRes1, * pRes2;
+    abctime clk;
+    // create uninitialized timeframes with map1
+    pFrames = Saig_ManFramesNonInitial( pAig, nFrames );
+    // perform fraiging for the unrolled timeframes
+clk = Abc_Clock();
+    pFraig = Fra_FraigEquivence( pFrames, 1000, 0 );
+    // report the results
+    if ( fVerbose )
+    {
+        Aig_ManPrintStats( pFrames );
+        Aig_ManPrintStats( pFraig );
+ABC_PRT( "Fraiging", Abc_Clock() - clk );
+    }
+    Aig_ManStop( pFraig );
+    assert( pFrames->pReprs != NULL );
+    // create AIG with map2
+    Saig_ManCreateMapping( pAig, pFrames, nFrames );
+    Aig_ManStop( pFrames );
+    Saig_ManStopMap1( pAig );
+    // create reduced initialized timeframes
+clk = Abc_Clock();
+    pRes2 = Saig_ManFramesInitialMapped( pAig, nFrames, nFramesMax, fInit );
+ABC_PRT( "Mapped", Abc_Clock() - clk );
+    // free mapping
+    Saig_ManStopMap2( pAig );
+clk = Abc_Clock();
+    pRes1 = Saig_ManFramesInitialMapped( pAig, nFrames, nFramesMax, fInit );
+ABC_PRT( "Normal", Abc_Clock() - clk );
+    // report the results
+    if ( fVerbose )
+    {
+        Aig_ManPrintStats( pRes1 );
+        Aig_ManPrintStats( pRes2 );
+    }
+    Aig_ManStop( pRes1 );
+    assert( !Saig_ManHasMap1(pAig) );
+    assert( !Saig_ManHasMap2(pAig) );
+    return pRes2;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saigUnfold2.c b/abc-build/src/aig/saig/saigUnfold2.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigUnfold2.c
@@ -0,0 +1,497 @@
+
+int  Saig_ManFilterUsingIndOne2( Aig_Man_t * p, Aig_Man_t * pFrame, sat_solver * pSat, Cnf_Dat_t * pCnf, int nConfs, int nProps, int Counter 
+                                 , int type_ /* jlong --  */
+                                 )
+{
+  Aig_Obj_t * pObj;
+  int Lit, status;
+  pObj = Aig_ManCo( pFrame, Counter*3+type_ ); /* which co */
+  Lit  = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 );
+  status = sat_solver_solve( pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfs, 0, 0, 0 );
+  if ( status == l_False )	/* unsat */
+      return status;
+  if ( status == l_Undef )
+    {
+      printf( "Solver returned undecided.\n" );
+      return status;
+    }
+  assert( status == l_True );
+  return status;
+}
+
+Aig_Man_t * Saig_ManCreateIndMiter2( Aig_Man_t * pAig, Vec_Vec_t * vCands )
+{
+  int nFrames = 3;
+    Vec_Ptr_t * vNodes;
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew;
+    Aig_Obj_t ** pObjMap;
+    int i, f, k;
+
+    // create mapping for the frames nodes
+    pObjMap  = ABC_CALLOC( Aig_Obj_t *, nFrames * Aig_ManObjNumMax(pAig) );
+
+    // start the fraig package
+    pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames );
+    pFrames->pName = Abc_UtilStrsav( pAig->pName );
+    pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec );
+    // map constant nodes
+    for ( f = 0; f < nFrames; f++ )
+        Aig_ObjSetFrames( pObjMap, nFrames, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) );
+    // create PI nodes for the frames
+    for ( f = 0; f < nFrames; f++ )
+        Aig_ManForEachPiSeq( pAig, pObj, i )
+            Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, Aig_ObjCreateCi(pFrames) );
+    // set initial state for the latches
+    Aig_ManForEachLoSeq( pAig, pObj, i )
+        Aig_ObjSetFrames( pObjMap, nFrames, pObj, 0, Aig_ObjCreateCi(pFrames) );
+
+    // add timeframes
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // add internal nodes of this frame
+        Aig_ManForEachNode( pAig, pObj, i )
+        {
+            pObjNew = Aig_And( pFrames, Aig_ObjChild0Frames(pObjMap,nFrames,pObj,f), Aig_ObjChild1Frames(pObjMap,nFrames,pObj,f) );
+            Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew );
+        }
+        // set the latch inputs and copy them into the latch outputs of the next frame
+        Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i )
+        {
+            pObjNew = Aig_ObjChild0Frames(pObjMap,nFrames,pObjLi,f);
+            if ( f < nFrames - 1 )
+                Aig_ObjSetFrames( pObjMap, nFrames, pObjLo, f+1, pObjNew );
+        }
+    }
+    
+    // go through the candidates
+    Vec_VecForEachLevel( vCands, vNodes, i )
+    {
+        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k )
+        {
+            Aig_Obj_t * pObjR  = Aig_Regular(pObj);
+            Aig_Obj_t * pNode0 = pObjMap[nFrames*Aig_ObjId(pObjR)+0];
+            Aig_Obj_t * pNode1 = pObjMap[nFrames*Aig_ObjId(pObjR)+1];
+	    {
+	      Aig_Obj_t * pFan0  = Aig_NotCond( pNode0,  Aig_IsComplement(pObj) );
+	      Aig_Obj_t * pFan1  = Aig_NotCond( pNode1, !Aig_IsComplement(pObj) );
+	      Aig_Obj_t * pMiter = Aig_And( pFrames, pFan0, pFan1 );
+	      Aig_ObjCreateCo( pFrames, pMiter );
+	    
+	    /* need to check p & Xp is satisfiable */
+	    /* jlong -- begin */
+          {
+	      Aig_Obj_t * pMiter2 = Aig_And( pFrames, pFan0, Aig_Not(pFan1));
+	      Aig_ObjCreateCo( pFrames, pMiter2 ); 
+          }
+        /* jlong -- end  */
+	    }
+
+	    {			/* jlong -- begin */
+	      Aig_Obj_t * pNode2 = pObjMap[nFrames*Aig_ObjId(pObjR)+2];
+	      Aig_Obj_t * pFan0  = Aig_NotCond( pNode0,  Aig_IsComplement(pObj) );
+	      Aig_Obj_t * pFan1  = Aig_NotCond( pNode1,  Aig_IsComplement(pObj) );
+	      Aig_Obj_t * pFan2  = Aig_NotCond( pNode2, !Aig_IsComplement(pObj) );
+	      Aig_Obj_t * pMiter = Aig_And( pFrames, Aig_And(pFrames, pFan0, pFan1 ), pFan2);
+	      Aig_ObjCreateCo( pFrames, pMiter ); /* jlong -- end  */
+	    }
+
+        }
+    }
+    Aig_ManCleanup( pFrames );
+    ABC_FREE( pObjMap );
+
+//Aig_ManShow( pAig, 0, NULL );
+//Aig_ManShow( pFrames, 0, NULL );
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+   Synopsis    [Detects constraints functionally.]
+
+   Description []
+               
+   SideEffects []
+
+   SeeAlso     []
+
+***********************************************************************/
+void Saig_ManFilterUsingInd2( Aig_Man_t * p, Vec_Vec_t * vCands, int nConfs, int nProps, int fVerbose )
+{
+  Vec_Ptr_t * vNodes;
+  Aig_Man_t * pFrames;
+  sat_solver * pSat;
+  Cnf_Dat_t * pCnf;
+  Aig_Obj_t * pObj;
+  int i, k, k2, Counter;
+  /*
+    Vec_VecForEachLevel( vCands, vNodes, i )
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k )
+    printf( "%d ", Aig_ObjId(Aig_Regular(pObj)) );
+    printf( "\n" );
+  */
+  // create timeframes 
+  //    pFrames = Saig_ManUnrollInd( p );
+  pFrames = Saig_ManCreateIndMiter2( p, vCands );
+  assert( Aig_ManCoNum(pFrames) == Vec_VecSizeSize(vCands)*3 );
+  // start the SAT solver
+  pCnf = Cnf_DeriveSimple( pFrames, Aig_ManCoNum(pFrames) );
+  pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+  // check candidates
+  if ( fVerbose )
+    printf( "Filtered cands:  \n" );
+  Counter = 0;
+  Vec_VecForEachLevel( vCands, vNodes, i )
+    {
+      assert(i==0);             /* only one item */
+      k2 = 0;
+      Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k )
+        {
+          if ( Saig_ManFilterUsingIndOne2( p, pFrames, pSat, pCnf, nConfs, nProps, Counter++ , 0) == l_False)
+            //            if ( Saig_ManFilterUsingIndOne_old( p, pSat, pCnf, nConfs, pObj ) )
+            {
+              Vec_PtrWriteEntry( vNodes, k2++, pObj );
+              if ( fVerbose )
+                printf( "%d:%s%d \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) );
+              printf( " type I : %d:%s%d \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) );
+              Vec_PtrPush(p->unfold2_type_I, pObj);
+            }
+          /* jlong -- begin  */
+          else if ( Saig_ManFilterUsingIndOne2( p, pFrames, pSat, pCnf, nConfs, nProps, Counter-1 , 1) == l_True ) /* can be self-conflicting */
+            {
+              if ( Saig_ManFilterUsingIndOne2( p, pFrames, pSat, pCnf, nConfs, nProps, Counter-1 , 2) == l_False ){
+                //Vec_PtrWriteEntry( vNodes, k2++, pObj );
+                if ( fVerbose )
+                  printf( "%d:%s%d  \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) );
+                printf( " type II: %d:%s%d  \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) );
+                Vec_PtrWriteEntry( vNodes, k2++, pObj ); /* add type II constraints */
+                Vec_PtrPush(p->unfold2_type_II, pObj);
+              }
+            }
+          /* jlong -- end  */
+        }
+      Vec_PtrShrink( vNodes, k2 );
+    }
+
+  // clean up
+  Cnf_DataFree( pCnf );
+  sat_solver_delete( pSat );
+  if ( fVerbose )
+    Aig_ManPrintStats( pFrames );
+  Aig_ManStop( pFrames );
+}
+
+
+/**Function*************************************************************
+
+   Synopsis    [Returns the number of variables implied by the output.]
+
+   Description []
+               
+   SideEffects []
+
+   SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Ssw_ManFindDirectImplications2( Aig_Man_t * p, int nFrames, int nConfs, int nProps, int fVerbose )
+{
+  Vec_Vec_t * vCands = NULL;
+  Vec_Ptr_t * vNodes;
+  Cnf_Dat_t * pCnf;
+  sat_solver * pSat;
+  Aig_Man_t * pFrames;
+  Aig_Obj_t * pObj, * pRepr, * pReprR;
+  int i, f, k, value;
+  assert(nFrames == 1);
+  vCands = Vec_VecAlloc( nFrames );
+  assert(nFrames == 1);
+  // perform unrolling
+  pFrames = Saig_ManUnrollCOI( p, nFrames );
+  assert( Aig_ManCoNum(pFrames) == 1 );
+  // start the SAT solver
+  pCnf = Cnf_DeriveSimple( pFrames, 0 );
+  pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+  if ( pSat != NULL )
+    {
+      Aig_ManIncrementTravId( p );
+      for ( f = 0; f < nFrames; f++ )
+        {
+          Aig_ManForEachObj( p, pObj, i )
+            {
+              if ( !Aig_ObjIsCand(pObj) )
+                continue;
+              //--jlong : also use internal nodes as well
+              /* if ( !Aig_ObjIsCi(pObj) ) */
+              /*   continue; */ 
+              if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+                continue;
+              // get the node from timeframes
+              pRepr  = p->pObjCopies[nFrames*i + nFrames-1-f];
+              pReprR = Aig_Regular(pRepr);
+              if ( pCnf->pVarNums[Aig_ObjId(pReprR)] < 0 )
+                continue;
+              //                value = pSat->assigns[ pCnf->pVarNums[Aig_ObjId(pReprR)] ];
+              value = sat_solver_get_var_value( pSat, pCnf->pVarNums[Aig_ObjId(pReprR)] );
+              if ( value == l_Undef )
+                continue;
+              // label this node as taken
+              Aig_ObjSetTravIdCurrent(p, pObj);
+              if ( Saig_ObjIsLo(p, pObj) )
+                Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin0(Saig_ObjLoToLi(p, pObj)) );
+              // remember the node
+              Vec_VecPush( vCands, f, Aig_NotCond( pObj, (value == l_True) ^ Aig_IsComplement(pRepr) ) );
+              //        printf( "%s%d ", (value == l_False)? "":"!", i );
+            }
+        }
+      //    printf( "\n" );
+      sat_solver_delete( pSat );
+    }
+  Aig_ManStop( pFrames );
+  Cnf_DataFree( pCnf );
+
+  if ( fVerbose )
+    {
+      printf( "Found %3d candidates.\n", Vec_VecSizeSize(vCands) );
+      Vec_VecForEachLevel( vCands, vNodes, k )
+        {
+          printf( "Level %d. Cands  =%d    ", k, Vec_PtrSize(vNodes) );
+          //            Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+          //                printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) );
+          printf( "\n" );
+        }
+    }
+
+  ABC_FREE( p->pObjCopies );
+  /* -- jlong -- this does the SAT proof of the constraints */
+  Saig_ManFilterUsingInd2( p, vCands, nConfs, nProps, fVerbose );
+  if ( Vec_VecSizeSize(vCands) )
+    printf( "Found %3d constraints after filtering.\n", Vec_VecSizeSize(vCands) );
+  if ( fVerbose )
+    {
+      Vec_VecForEachLevel( vCands, vNodes, k )
+        {
+          printf( "Level %d. Constr =%d    ", k, Vec_PtrSize(vNodes) );
+          //            Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+          //                printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) );
+          printf( "\n" );
+        }
+    }
+  
+  return vCands;
+}
+
+/**Function*************************************************************
+
+   Synopsis    [Duplicates the AIG while unfolding constraints.]
+
+   Description []
+               
+   SideEffects []
+
+   SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManDupUnfoldConstrsFunc2( Aig_Man_t * pAig, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose , int * typeII_cnt){
+  Aig_Man_t * pNew;
+  Vec_Vec_t * vCands;
+  Vec_Ptr_t  * vNewFlops;
+  Aig_Obj_t * pObj;
+  int i,  k, nNewFlops;
+  const int fCompl = 0 ;
+  if ( fOldAlgo )
+    vCands = Saig_ManDetectConstrFunc( pAig, nFrames, nConfs, nProps, fVerbose );
+  else
+    vCands = Ssw_ManFindDirectImplications2( pAig, nFrames, nConfs, nProps, fVerbose );
+  if ( vCands == NULL || Vec_VecSizeSize(vCands) == 0 )
+    {
+      Vec_VecFreeP( &vCands );
+      return Aig_ManDupDfs( pAig );
+    }
+  // create new manager
+  pNew = Aig_ManDupWithoutPos( pAig ); /* good */
+  pNew->nConstrs = pAig->nConstrs + Vec_VecSizeSize(vCands);
+  pNew->nConstrs = pAig->nConstrs + Vec_PtrSize(pAig->unfold2_type_II)
+    + Vec_PtrSize(pAig->unfold2_type_I);
+  //  pNew->nConstrsTypeII  = Vec_PtrSize(pAig->unfold2_type_II);
+  *typeII_cnt = Vec_PtrSize(pAig->unfold2_type_II);
+
+  /* new set of registers */
+  
+  // add normal POs
+  Saig_ManForEachPo( pAig, pObj, i )
+    Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+  // create constraint outputs
+  vNewFlops = Vec_PtrAlloc( 100 );
+
+
+  Vec_PtrForEachEntry(Aig_Obj_t * , pAig->unfold2_type_I, pObj, k){
+    Aig_Obj_t * x = Aig_ObjRealCopy(pObj);
+    Aig_ObjCreateCo(pNew, x);
+  }
+   
+  Vec_PtrForEachEntry(Aig_Obj_t * , pAig->unfold2_type_II, pObj, k){
+    Aig_Obj_t * type_II_latch
+      = Aig_ObjCreateCi(pNew); /* will get connected later; */
+    Aig_Obj_t * x = Aig_ObjRealCopy(pObj);
+    
+    Aig_Obj_t * n = Aig_And(pNew, 
+                            Aig_NotCond(type_II_latch, fCompl),
+                            Aig_NotCond(x, fCompl));
+    Aig_ObjCreateCo(pNew, n);//Aig_Not(n));
+  }                   
+  
+  // add latch outputs
+  Saig_ManForEachLi( pAig, pObj, i )
+    Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+  
+  Vec_PtrForEachEntry(Aig_Obj_t * , pAig->unfold2_type_II, pObj, k){
+    Aig_Obj_t * x = Aig_ObjRealCopy(pObj);
+    Aig_ObjCreateCo(pNew, x);
+  }                   
+
+  // add new latch outputs
+  nNewFlops = Vec_PtrSize(pAig->unfold2_type_II);
+  //assert( nNewFlops == Vec_PtrSize(vNewFlops) );
+  Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) + nNewFlops );
+  printf("#reg after unfold2: %d\n", Aig_ManRegNum(pAig) + nNewFlops );
+  Vec_VecFreeP( &vCands );
+  Vec_PtrFree( vNewFlops );
+  return pNew;
+
+}
+
+/**Function*************************************************************
+
+   Synopsis    [Duplicates the AIG while unfolding constraints.]
+
+   Description []
+               
+   SideEffects []
+
+   SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManDupFoldConstrsFunc2( Aig_Man_t * pAig, int fCompl, int fVerbose , 
+                                         int typeII_cnt)
+{
+  Aig_Man_t * pAigNew;
+  Aig_Obj_t * pMiter, * pFlopOut, * pFlopIn, * pObj;
+  int i, typeII_cc, type_II;
+  if ( Aig_ManConstrNum(pAig) == 0 )
+    return Aig_ManDupDfs( pAig );
+  assert( Aig_ManConstrNum(pAig) < Saig_ManPoNum(pAig) );
+  // start the new manager
+  pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) );
+  pAigNew->pName = Abc_UtilStrsav( pAig->pName );
+  pAigNew->pSpec = Abc_UtilStrsav( pAig->pSpec );
+  // map the constant node
+  Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew );
+  // create variables for PIs
+  Aig_ManForEachCi( pAig, pObj, i )
+    pObj->pData = Aig_ObjCreateCi( pAigNew );
+  // add internal nodes of this frame
+  Aig_ManForEachNode( pAig, pObj, i )
+    pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+
+  // OR the constraint outputs
+  pMiter = Aig_ManConst0( pAigNew );
+  typeII_cc = 0;//typeII_cnt;
+  typeII_cnt = 0;  
+  type_II = 0;
+    
+  Saig_ManForEachPo( pAig, pObj, i )
+    {
+      
+      if ( i < Saig_ManPoNum(pAig)-Aig_ManConstrNum(pAig) )
+        continue;
+      if (i + typeII_cnt >= Saig_ManPoNum(pAig) ) {
+        type_II = 1;
+      }
+      /*  now we got the constraint */
+      if (type_II) {
+
+        Aig_Obj_t * type_II_latch
+          = Aig_ObjCreateCi(pAigNew); /* will get connected later; */
+        pMiter = Aig_Or(pAigNew, pMiter, 
+                        Aig_And(pAigNew, 
+                                Aig_NotCond(type_II_latch, fCompl),
+                                Aig_NotCond( Aig_ObjChild0Copy(pObj), fCompl ) )
+                        );
+        printf( "modeling typeII : %d:%s%d \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) );
+      } else 
+        pMiter = Aig_Or( pAigNew, pMiter, Aig_NotCond( Aig_ObjChild0Copy(pObj), fCompl ) );
+    }
+
+  // create additional flop
+  if ( Saig_ManRegNum(pAig) > 0 )
+    {
+      pFlopOut = Aig_ObjCreateCi( pAigNew );
+      pFlopIn  = Aig_Or( pAigNew, pMiter, pFlopOut );
+    }
+  else 
+    pFlopIn = pMiter;
+
+  // create primary output
+  Saig_ManForEachPo( pAig, pObj, i )
+    {
+      if ( i >= Saig_ManPoNum(pAig)-Aig_ManConstrNum(pAig) )
+        continue;
+      pMiter = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_Not(pFlopIn) );
+      Aig_ObjCreateCo( pAigNew, pMiter );
+    }
+
+  // transfer to register outputs
+  {
+    /* the same for type I and type II */
+    Aig_Obj_t * pObjLi, *pObjLo;
+
+    Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )	{
+      if( i + typeII_cc < Aig_ManRegNum(pAig)) {
+        Aig_Obj_t *c = Aig_Mux(pAigNew, Aig_Not(pFlopIn), 
+                               Aig_ObjChild0Copy(pObjLi) ,
+                               pObjLo->pData);
+        Aig_ObjCreateCo( pAigNew, c);
+      } else {
+        printf ( "skipping: reg%d\n", i);
+        Aig_ObjCreateCo( pAigNew,Aig_ObjChild0Copy(pObjLi));
+      }
+    }
+
+  }
+  if(0)Saig_ManForEachLi( pAig, pObj, i ) {
+      Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) );
+    }
+  Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) );
+    
+  type_II = 0;
+  Saig_ManForEachPo( pAig, pObj, i )
+    {
+	
+      if ( i < Saig_ManPoNum(pAig)-Aig_ManConstrNum(pAig) )
+        continue;
+      if (i + typeII_cnt >= Saig_ManPoNum(pAig) ) {
+        type_II = 1;
+      }
+      /*  now we got the constraint */
+      if (type_II) {
+        Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj));
+        Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAigNew)+1 );
+        printf( "Latch for typeII : %d:%s%d \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) );
+      }
+    }
+
+     
+  // create additional flop 
+
+  if ( Saig_ManRegNum(pAig) > 0 )
+    {
+      Aig_ObjCreateCo( pAigNew, pFlopIn );
+      Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAigNew)+1 );
+    }
+  printf("#reg after fold2: %d\n", Aig_ManRegNum(pAigNew));
+  // perform cleanup
+  Aig_ManCleanup( pAigNew );
+  Aig_ManSeqCleanup( pAigNew );
+  return pAigNew;
+}
diff --git a/abc-build/src/aig/saig/saigWnd.c b/abc-build/src/aig/saig/saigWnd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saigWnd.c
@@ -0,0 +1,816 @@
+/**CFile****************************************************************
+
+  FileName    [saigWnd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Sequential windowing.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigWnd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of PI/internal nodes.]
+
+  Description [Marks all the visited nodes with the current ID.
+  Does not collect constant node and PO/LI nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManWindowOutline_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist, Vec_Ptr_t * vNodes, int * pDists )
+{
+    Aig_Obj_t * pMatch, * pFanout;
+    int fCollected, iFanout = -1, i;
+    if ( nDist == 0 )
+        return;
+    if ( pDists[pObj->Id] >= nDist )
+        return;
+    pDists[pObj->Id] = nDist;
+    fCollected = Aig_ObjIsTravIdCurrent( p, pObj );
+    Aig_ObjSetTravIdCurrent( p, pObj );    
+    if ( Aig_ObjIsConst1(pObj) )
+        return;
+    if ( Saig_ObjIsPo(p, pObj) )
+        return;
+    if ( Saig_ObjIsLi(p, pObj) )
+    {
+        pMatch = Saig_ObjLiToLo( p, pObj );
+        if ( !Aig_ObjIsTravIdCurrent( p, pMatch ) )
+            Saig_ManWindowOutline_rec( p, pMatch, nDist, vNodes, pDists );
+        Saig_ManWindowOutline_rec( p, Aig_ObjFanin0(pObj), nDist-1, vNodes, pDists );
+        return;
+    }
+    if ( !fCollected )
+        Vec_PtrPush( vNodes, pObj );
+    if ( Saig_ObjIsPi(p, pObj) )
+        return;
+    if ( Saig_ObjIsLo(p, pObj) )
+    {
+        pMatch = Saig_ObjLoToLi( p, pObj );
+        if ( !Aig_ObjIsTravIdCurrent( p, pMatch ) )
+            Saig_ManWindowOutline_rec( p, pMatch, nDist, vNodes, pDists );
+        Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
+            Saig_ManWindowOutline_rec( p, pFanout, nDist-1, vNodes, pDists );
+        return;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    Saig_ManWindowOutline_rec( p, Aig_ObjFanin0(pObj), nDist-1, vNodes, pDists );
+    Saig_ManWindowOutline_rec( p, Aig_ObjFanin1(pObj), nDist-1, vNodes, pDists );
+    Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
+        Saig_ManWindowOutline_rec( p, pFanout, nDist-1, vNodes, pDists );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of PI/internal nodes.]
+
+  Description [Marks all the visited nodes with the current ID.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_ManWindowOutline( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObjLi, * pObjLo;
+    int * pDists, i;
+    pDists = ABC_CALLOC( int, Aig_ManObjNumMax(p) );
+    vNodes = Vec_PtrAlloc( 1000 );
+    Aig_ManIncrementTravId( p );
+    Saig_ManWindowOutline_rec( p, pObj, nDist, vNodes, pDists );
+    Vec_PtrSort( vNodes, (int (*)(void))Aig_ObjCompareIdIncrease );
+    // make sure LI/LO are labeled/unlabeled mutually
+    Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
+        assert( Aig_ObjIsTravIdCurrent(p, pObjLi) == 
+                Aig_ObjIsTravIdCurrent(p, pObjLo) );
+    ABC_FREE( pDists );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node has unlabeled fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Saig_ObjHasUnlabeledFanout( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pFanout;
+    int iFanout = -1, i;
+    Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
+        if ( Saig_ObjIsPo(p, pFanout) || !Aig_ObjIsTravIdCurrent(p, pFanout) )
+            return pFanout;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects primary inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_ManWindowCollectPis( Aig_Man_t * p, Vec_Ptr_t * vNodes )
+{
+    Vec_Ptr_t * vNodesPi;
+    Aig_Obj_t * pObj, * pMatch, * pFanin;
+    int i;
+    vNodesPi = Vec_PtrAlloc( 1000 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        if ( Saig_ObjIsPi(p, pObj) )
+        {
+            assert( pObj->pData == NULL );
+            Vec_PtrPush( vNodesPi, pObj );
+        }
+        else if ( Saig_ObjIsLo(p, pObj) )
+        {
+            pMatch = Saig_ObjLoToLi( p, pObj );
+            pFanin = Aig_ObjFanin0(pMatch);
+            if ( !Aig_ObjIsTravIdCurrent(p, pFanin) && pFanin->pData == NULL )
+                Vec_PtrPush( vNodesPi, pFanin );
+        }
+        else
+        {
+            assert( Aig_ObjIsNode(pObj) );
+            pFanin = Aig_ObjFanin0(pObj);
+            if ( !Aig_ObjIsTravIdCurrent(p, pFanin) && pFanin->pData == NULL )
+                Vec_PtrPush( vNodesPi, pFanin );
+            pFanin = Aig_ObjFanin1(pObj);
+            if ( !Aig_ObjIsTravIdCurrent(p, pFanin) && pFanin->pData == NULL )
+                Vec_PtrPush( vNodesPi, pFanin );
+        }
+    }
+    return vNodesPi;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects primary outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_ManWindowCollectPos( Aig_Man_t * p, Vec_Ptr_t * vNodes, Vec_Ptr_t ** pvPointers )
+{
+    Vec_Ptr_t * vNodesPo;
+    Aig_Obj_t * pObj, * pPointer;
+    int i;
+    vNodesPo = Vec_PtrAlloc( 1000 );
+    if ( pvPointers )
+        *pvPointers = Vec_PtrAlloc( 1000 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        if ( (pPointer = Saig_ObjHasUnlabeledFanout(p, pObj)) )
+        {
+            Vec_PtrPush( vNodesPo, pObj );
+            if ( pvPointers )
+                Vec_PtrPush( *pvPointers, pPointer );
+        }
+    }
+    return vNodesPo;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Extracts the window AIG from the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManWindowExtractNodes( Aig_Man_t * p, Vec_Ptr_t * vNodes )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pMatch;
+    Vec_Ptr_t * vNodesPi, * vNodesPo;
+    int i, nRegCount;
+    Aig_ManCleanData( p ); 
+    // create the new manager
+    pNew = Aig_ManStart( Vec_PtrSize(vNodes) );
+    pNew->pName = Abc_UtilStrsav( "wnd" );
+    pNew->pSpec = NULL;
+    // map constant nodes
+    pObj = Aig_ManConst1( p );
+    pObj->pData = Aig_ManConst1( pNew );
+    // create real PIs
+    vNodesPi = Saig_ManWindowCollectPis( p, vNodes );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodesPi, pObj, i )
+        pObj->pData = Aig_ObjCreateCi(pNew);
+    Vec_PtrFree( vNodesPi );
+    // create register outputs
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        if ( Saig_ObjIsLo(p, pObj) )
+            pObj->pData = Aig_ObjCreateCi(pNew);
+    }
+    // create internal nodes
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        if ( Aig_ObjIsNode(pObj) )
+            pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    }
+    // create POs
+    vNodesPo = Saig_ManWindowCollectPos( p, vNodes, NULL );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodesPo, pObj, i )
+        Aig_ObjCreateCo( pNew, (Aig_Obj_t *)pObj->pData );
+    Vec_PtrFree( vNodesPo );
+    // create register inputs
+    nRegCount = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        if ( Saig_ObjIsLo(p, pObj) )
+        {
+            pMatch = Saig_ObjLoToLi( p, pObj );
+            Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pMatch) );
+            nRegCount++;
+        }
+    }
+    Aig_ManSetRegNum( pNew, nRegCount );
+    Aig_ManCleanup( pNew );
+    return pNew;
+}
+
+static void Saig_ManWindowInsertSmall_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjSmall, 
+     Vec_Ptr_t * vBigNode2SmallPo, Vec_Ptr_t * vSmallPi2BigNode );
+
+/**Function*************************************************************
+
+  Synopsis    [Adds nodes for the big manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManWindowInsertBig_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjBig, 
+         Vec_Ptr_t * vBigNode2SmallPo, Vec_Ptr_t * vSmallPi2BigNode )
+{
+    Aig_Obj_t * pMatch;
+    if ( pObjBig->pData )
+        return;
+    if ( (pMatch = (Aig_Obj_t *)Vec_PtrEntry( vBigNode2SmallPo, pObjBig->Id )) )
+    {
+        Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin0(pMatch), vBigNode2SmallPo, vSmallPi2BigNode );
+        pObjBig->pData = Aig_ObjChild0Copy(pMatch);
+        return;        
+    }
+    assert( Aig_ObjIsNode(pObjBig) );
+    Saig_ManWindowInsertBig_rec( pNew, Aig_ObjFanin0(pObjBig), vBigNode2SmallPo, vSmallPi2BigNode );
+    Saig_ManWindowInsertBig_rec( pNew, Aig_ObjFanin1(pObjBig), vBigNode2SmallPo, vSmallPi2BigNode );
+    pObjBig->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObjBig), Aig_ObjChild1Copy(pObjBig) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds nodes for the small manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManWindowInsertSmall_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjSmall, 
+         Vec_Ptr_t * vBigNode2SmallPo, Vec_Ptr_t * vSmallPi2BigNode )
+{
+    Aig_Obj_t * pMatch;
+    if ( pObjSmall->pData )
+        return;
+    if ( (pMatch = (Aig_Obj_t *)Vec_PtrEntry( vSmallPi2BigNode, pObjSmall->Id )) )
+    {
+        Saig_ManWindowInsertBig_rec( pNew, pMatch, vBigNode2SmallPo, vSmallPi2BigNode );
+        pObjSmall->pData = pMatch->pData;
+        return;        
+    }
+    assert( Aig_ObjIsNode(pObjSmall) );
+    Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin0(pObjSmall), vBigNode2SmallPo, vSmallPi2BigNode );
+    Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin1(pObjSmall), vBigNode2SmallPo, vSmallPi2BigNode );
+    pObjSmall->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObjSmall), Aig_ObjChild1Copy(pObjSmall) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Extracts the network from the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManWindowInsertNodes( Aig_Man_t * p, Vec_Ptr_t * vNodes, Aig_Man_t * pWnd )
+{
+    Aig_Man_t * pNew;
+    Vec_Ptr_t * vBigNode2SmallPo, * vSmallPi2BigNode;
+    Vec_Ptr_t * vNodesPi, * vNodesPo;
+    Aig_Obj_t * pObj;
+    int i;
+
+    // set mapping of small PIs into big nodes
+    vSmallPi2BigNode = Vec_PtrStart( Aig_ManObjNumMax(pWnd) ); 
+    vNodesPi = Saig_ManWindowCollectPis( p, vNodes );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodesPi, pObj, i )
+        Vec_PtrWriteEntry( vSmallPi2BigNode, Aig_ManCi(pWnd, i)->Id, pObj );
+    assert( i == Saig_ManPiNum(pWnd) );
+    Vec_PtrFree( vNodesPi );
+
+    // set mapping of big nodes into small POs
+    vBigNode2SmallPo = Vec_PtrStart( Aig_ManObjNumMax(p) ); 
+    vNodesPo = Saig_ManWindowCollectPos( p, vNodes, NULL );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodesPo, pObj, i )
+        Vec_PtrWriteEntry( vBigNode2SmallPo, pObj->Id, Aig_ManCo(pWnd, i) );
+    assert( i == Saig_ManPoNum(pWnd) );
+    Vec_PtrFree( vNodesPo );
+
+    // create the new manager
+    Aig_ManCleanData( p ); 
+    Aig_ManCleanData( pWnd ); 
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // map constant nodes
+    pObj = Aig_ManConst1( p );
+    pObj->pData = Aig_ManConst1( pNew );
+    pObj = Aig_ManConst1( pWnd );
+    pObj->pData = Aig_ManConst1( pNew );
+
+    // create real PIs
+    Aig_ManForEachCi( p, pObj, i )
+        if ( Saig_ObjIsPi(p, pObj) || !Aig_ObjIsTravIdCurrent(p, pObj) )
+            pObj->pData = Aig_ObjCreateCi(pNew);
+    // create additional latch outputs
+    Saig_ManForEachLo( pWnd, pObj, i )
+        pObj->pData = Aig_ObjCreateCi(pNew);
+
+    // create internal nodes starting from the big
+    Aig_ManForEachCo( p, pObj, i )
+        if ( Saig_ObjIsPo(p, pObj) || !Aig_ObjIsTravIdCurrent(p, pObj) )
+        {
+            Saig_ManWindowInsertBig_rec( pNew, Aig_ObjFanin0(pObj), vBigNode2SmallPo, vSmallPi2BigNode );
+            pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+        }
+    // create internal nodes starting from the small
+    Saig_ManForEachLi( pWnd, pObj, i )
+    {
+        Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin0(pObj), vBigNode2SmallPo, vSmallPi2BigNode );
+        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    }
+    Vec_PtrFree( vBigNode2SmallPo );
+    Vec_PtrFree( vSmallPi2BigNode );
+    // set the new number of registers
+    assert( Aig_ManCiNum(pNew) - Aig_ManCiNum(p) == Aig_ManCoNum(pNew) - Aig_ManCoNum(p) );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) + (Aig_ManCiNum(pNew) - Aig_ManCiNum(p)) );
+    Aig_ManCleanup( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find a good object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Saig_ManFindPivot( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter;
+    if ( Aig_ManRegNum(p) > 0 )
+    {
+        if ( Aig_ManRegNum(p) == 1 )
+            return Saig_ManLo( p, 0 );
+        Saig_ManForEachLo( p, pObj, i )
+        {
+            if ( i == Aig_ManRegNum(p)/2 )
+                return pObj;
+        }
+    }
+    else
+    {
+        Counter = 0;
+        assert( Aig_ManNodeNum(p) > 1 );
+        Aig_ManForEachNode( p, pObj, i )
+        {
+            if ( Counter++ == Aig_ManNodeNum(p)/2 )
+                return pObj;
+        }
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes sequential window of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManWindowExtract( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist )
+{
+    Aig_Man_t * pWnd;
+    Vec_Ptr_t * vNodes;
+    Aig_ManFanoutStart( p );
+    vNodes = Saig_ManWindowOutline( p, pObj, nDist );
+    pWnd = Saig_ManWindowExtractNodes( p, vNodes );
+    Vec_PtrFree( vNodes );
+    Aig_ManFanoutStop( p );
+    return pWnd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes sequential window of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManWindowInsert( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist, Aig_Man_t * pWnd )
+{
+    Aig_Man_t * pNew, * pWndTest;
+    Vec_Ptr_t * vNodes;
+    Aig_ManFanoutStart( p );
+
+    vNodes = Saig_ManWindowOutline( p, pObj, nDist );
+    pWndTest = Saig_ManWindowExtractNodes( p, vNodes );
+    if ( Saig_ManPiNum(pWndTest) != Saig_ManPiNum(pWnd) ||
+         Saig_ManPoNum(pWndTest) != Saig_ManPoNum(pWnd) )
+    {
+        printf( "The window cannot be reinserted because PI/PO counts do not match.\n" );
+        Aig_ManStop( pWndTest );
+        Vec_PtrFree( vNodes );
+        Aig_ManFanoutStop( p );
+        return NULL;
+    }
+    Aig_ManStop( pWndTest );
+    Vec_PtrFree( vNodes );
+
+    // insert the nodes
+    Aig_ManCleanData( p ); 
+    vNodes = Saig_ManWindowOutline( p, pObj, nDist );
+    pNew = Saig_ManWindowInsertNodes( p, vNodes, pWnd );
+    Vec_PtrFree( vNodes );
+    Aig_ManFanoutStop( p );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tests the above computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManWindowTest( Aig_Man_t * p )
+{
+    int nDist = 3;
+    Aig_Man_t * pWnd, * pNew;
+    Aig_Obj_t * pPivot;
+    pPivot = Saig_ManFindPivot( p );
+    assert( pPivot != NULL );
+    pWnd = Saig_ManWindowExtract( p, pPivot, nDist );
+    pNew = Saig_ManWindowInsert( p, pPivot, nDist, pWnd );
+    Aig_ManStop( pWnd );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the nodes that are not linked to each other.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_ManCollectedDiffNodes( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj0, * pObj1;
+    int i;
+    // collect nodes that are not linked
+    Aig_ManIncrementTravId( p0 );
+    vNodes = Vec_PtrAlloc( 1000 );
+    Aig_ManForEachObj( p0, pObj0, i )
+    {
+        pObj1 = Aig_ObjRepr( p0, pObj0 );
+        if ( pObj1 != NULL )
+        {
+            assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) );   
+            continue;
+        }
+        // mark and collect unmatched objects
+        Aig_ObjSetTravIdCurrent( p0, pObj0 ); 
+        if ( Aig_ObjIsNode(pObj0) || Aig_ObjIsCi(pObj0) )
+            Vec_PtrPush( vNodes, pObj0 );
+    }
+    // make sure LI/LO are labeled/unlabeled mutually
+    Saig_ManForEachLiLo( p0, pObj0, pObj1, i )
+        assert( Aig_ObjIsTravIdCurrent(p0, pObj0) == 
+                Aig_ObjIsTravIdCurrent(p0, pObj1) );
+    return vNodes;
+}
+         
+/**Function*************************************************************
+
+  Synopsis    [Creates PIs of the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManWindowCreatePis( Aig_Man_t * pNew, Aig_Man_t * p0, Aig_Man_t * p1, Vec_Ptr_t * vNodes0 )
+{
+    Aig_Obj_t * pObj, * pMatch, * pFanin;
+    int i, Counter = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pObj, i )
+    {
+        if ( Saig_ObjIsLo(p0, pObj) )
+        {
+            pMatch = Saig_ObjLoToLi( p0, pObj );
+            pFanin = Aig_ObjFanin0(pMatch);
+            if ( !Aig_ObjIsTravIdCurrent(p0, pFanin) && pFanin->pData == NULL )
+            {
+                pFanin->pData = Aig_ObjCreateCi(pNew);
+                pMatch = Aig_ObjRepr( p0, pFanin );
+                assert( pFanin == Aig_ObjRepr( p1, pMatch ) );
+                assert( pMatch != NULL );
+                pMatch->pData = pFanin->pData;
+                Counter++;
+            }
+        }
+        else
+        {
+            assert( Aig_ObjIsNode(pObj) );
+            pFanin = Aig_ObjFanin0(pObj);
+            if ( !Aig_ObjIsTravIdCurrent(p0, pFanin) && pFanin->pData == NULL )
+            {
+                pFanin->pData = Aig_ObjCreateCi(pNew);
+                pMatch = Aig_ObjRepr( p0, pFanin );
+                assert( pFanin == Aig_ObjRepr( p1, pMatch ) );
+                assert( pMatch != NULL );
+                pMatch->pData = pFanin->pData;
+                Counter++;
+            }
+            pFanin = Aig_ObjFanin1(pObj);
+            if ( !Aig_ObjIsTravIdCurrent(p0, pFanin) && pFanin->pData == NULL )
+            {
+                pFanin->pData = Aig_ObjCreateCi(pNew);
+                pMatch = Aig_ObjRepr( p0, pFanin );
+                assert( pFanin == Aig_ObjRepr( p1, pMatch ) );
+                assert( pMatch != NULL );
+                pMatch->pData = pFanin->pData;
+                Counter++;
+            }
+        }
+    }
+//    printf( "Added %d primary inputs.\n", Counter );
+}
+        
+/**Function*************************************************************
+
+  Synopsis    [Creates POs of the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManWindowCreatePos( Aig_Man_t * pNew, Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+    Aig_Obj_t * pObj0, * pObj1, * pMiter;
+    Aig_Obj_t * pFanin0, * pFanin1;
+    int i;
+    Aig_ManForEachObj( p0, pObj0, i )
+    {
+        if ( Aig_ObjIsTravIdCurrent(p0, pObj0) )
+            continue;
+        if ( Aig_ObjIsConst1(pObj0) )
+            continue;
+        if ( Aig_ObjIsCi(pObj0) )
+            continue;
+        pObj1 = Aig_ObjRepr( p0, pObj0 );
+        assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) );
+        if ( Aig_ObjIsCo(pObj0) )
+        {
+            pFanin0 = Aig_ObjFanin0(pObj0);
+            pFanin1 = Aig_ObjFanin0(pObj1);
+            assert( Aig_ObjIsTravIdCurrent(p0, pFanin0) ==
+                    Aig_ObjIsTravIdCurrent(p1, pFanin1) );
+            if ( Aig_ObjIsTravIdCurrent(p0, pFanin0) )
+            {
+                pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pFanin0->pData, (Aig_Obj_t *)pFanin1->pData );
+                Aig_ObjCreateCo( pNew, pMiter );
+            }
+        }
+        else
+        {
+            assert( Aig_ObjIsNode(pObj0) );
+
+            pFanin0 = Aig_ObjFanin0(pObj0);
+            pFanin1 = Aig_ObjFanin0(pObj1);
+            assert( Aig_ObjIsTravIdCurrent(p0, pFanin0) ==
+                    Aig_ObjIsTravIdCurrent(p1, pFanin1) );
+            if ( Aig_ObjIsTravIdCurrent(p0, pFanin0) )
+            {
+                pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pFanin0->pData, (Aig_Obj_t *)pFanin1->pData );
+                Aig_ObjCreateCo( pNew, pMiter );
+            }
+
+            pFanin0 = Aig_ObjFanin1(pObj0);
+            pFanin1 = Aig_ObjFanin1(pObj1);
+            assert( Aig_ObjIsTravIdCurrent(p0, pFanin0) ==
+                    Aig_ObjIsTravIdCurrent(p1, pFanin1) );
+            if ( Aig_ObjIsTravIdCurrent(p0, pFanin0) )
+            {
+                pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pFanin0->pData, (Aig_Obj_t *)pFanin1->pData );
+                Aig_ObjCreateCo( pNew, pMiter );
+            }
+        }
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Extracts the window AIG from the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManWindowExtractMiter( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj0, * pObj1, * pMatch0, * pMatch1;
+    Vec_Ptr_t * vNodes0, * vNodes1;
+    int i, nRegCount;
+    // add matching of POs and LIs
+    Saig_ManForEachPo( p0, pObj0, i )
+    {
+        pObj1 = Aig_ManCo( p1, i );
+        Aig_ObjSetRepr( p0, pObj0, pObj1 );
+        Aig_ObjSetRepr( p1, pObj1, pObj0 );
+    }
+    Saig_ManForEachLi( p0, pObj0, i )
+    {
+        pMatch0 = Saig_ObjLiToLo( p0, pObj0 );
+        pMatch1 = Aig_ObjRepr( p0, pMatch0 );
+        if ( pMatch1 == NULL )
+            continue;
+        assert( pMatch0 == Aig_ObjRepr( p1, pMatch1 ) );
+        pObj1 = Saig_ObjLoToLi( p1, pMatch1 );
+        Aig_ObjSetRepr( p0, pObj0, pObj1 );
+        Aig_ObjSetRepr( p1, pObj1, pObj0 );
+    }
+    // clean the markings
+    Aig_ManCleanData( p0 ); 
+    Aig_ManCleanData( p1 ); 
+    // collect nodes that are not linked
+    vNodes0 = Saig_ManCollectedDiffNodes( p0, p1 );
+    vNodes1 = Saig_ManCollectedDiffNodes( p1, p0 );
+    // create the new manager
+    pNew = Aig_ManStart( Vec_PtrSize(vNodes0) + Vec_PtrSize(vNodes1) );
+    pNew->pName = Abc_UtilStrsav( "wnd" );
+    pNew->pSpec = NULL;
+    // map constant nodes
+    pObj0 = Aig_ManConst1( p0 );
+    pObj0->pData = Aig_ManConst1( pNew );
+    pObj1 = Aig_ManConst1( p1 );
+    pObj1->pData = Aig_ManConst1( pNew );
+    // create real PIs
+    Saig_ManWindowCreatePis( pNew, p0, p1, vNodes0 );
+    Saig_ManWindowCreatePis( pNew, p1, p0, vNodes1 );
+    // create register outputs
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pObj0, i )
+    {
+        if ( Saig_ObjIsLo(p0, pObj0) )
+            pObj0->pData = Aig_ObjCreateCi(pNew);
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pObj1, i )
+    {
+        if ( Saig_ObjIsLo(p1, pObj1) )
+            pObj1->pData = Aig_ObjCreateCi(pNew);
+    }
+    // create internal nodes
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pObj0, i )
+    {
+        if ( Aig_ObjIsNode(pObj0) )
+            pObj0->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj0), Aig_ObjChild1Copy(pObj0) );
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pObj1, i )
+    {
+        if ( Aig_ObjIsNode(pObj1) )
+            pObj1->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj1), Aig_ObjChild1Copy(pObj1) );
+    }
+    // create POs
+    Saig_ManWindowCreatePos( pNew, p0, p1 );
+//    Saig_ManWindowCreatePos( pNew, p1, p0 );
+    // create register inputs
+    nRegCount = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pObj0, i )
+    {
+        if ( Saig_ObjIsLo(p0, pObj0) )
+        {
+            pMatch0 = Saig_ObjLoToLi( p0, pObj0 );
+            Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pMatch0) );
+            nRegCount++;
+        }
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pObj1, i )
+    {
+        if ( Saig_ObjIsLo(p1, pObj1) )
+        {
+            pMatch1 = Saig_ObjLoToLi( p1, pObj1 );
+            Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pMatch1) );
+            nRegCount++;
+        }
+    }
+    Aig_ManSetRegNum( pNew, nRegCount );
+    Aig_ManCleanup( pNew );
+    Vec_PtrFree( vNodes0 );
+    Vec_PtrFree( vNodes1 );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/aig/saig/saig_.c b/abc-build/src/aig/saig/saig_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/aig/saig/saig_.c
@@ -0,0 +1,52 @@
+/**CFile****************************************************************
+
+  FileName    [saig_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saig_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abc.h b/abc-build/src/base/abc/abc.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abc.h
@@ -0,0 +1,1023 @@
+/**CFile****************************************************************
+
+  FileName    [abc.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abc.h,v 1.1 2008/05/14 22:13:11 wudenni Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__base__abc__abc_h
+#define ABC__base__abc__abc_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+#include "aig/hop/hop.h"
+#include "aig/gia/gia.h"
+#include "misc/st/st.h"
+#include "misc/st/stmm.h"
+#include "misc/nm/nm.h"
+#include "misc/mem/mem.h"
+#include "misc/util/utilCex.h"
+#include "misc/extra/extra.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+// network types
+typedef enum { 
+    ABC_NTK_NONE = 0,   // 0:  unknown
+    ABC_NTK_NETLIST,    // 1:  network with PIs/POs, latches, nodes, and nets
+    ABC_NTK_LOGIC,      // 2:  network with PIs/POs, latches, and nodes
+    ABC_NTK_STRASH,     // 3:  structurally hashed AIG (two input AND gates with c-attributes on edges)
+    ABC_NTK_OTHER       // 4:  unused
+} Abc_NtkType_t;
+
+// network functionality
+typedef enum { 
+    ABC_FUNC_NONE = 0,  // 0:  unknown
+    ABC_FUNC_SOP,       // 1:  sum-of-products
+    ABC_FUNC_BDD,       // 2:  binary decision diagrams
+    ABC_FUNC_AIG,       // 3:  and-inverter graphs
+    ABC_FUNC_MAP,       // 4:  standard cell library
+    ABC_FUNC_BLIFMV,    // 5:  BLIF-MV node functions
+    ABC_FUNC_BLACKBOX,  // 6:  black box about which nothing is known
+    ABC_FUNC_OTHER      // 7:  unused
+} Abc_NtkFunc_t;
+
+// Supported type/functionality combinations:
+/*------------------------------------------|
+|           |  SOP  |  BDD  |  AIG  |  Map  |
+|-----------|-------|-------|-------|-------|
+|  Netlist  |   x   |       |   x   |   x   |
+|-----------|-------|-------|-------|-------|
+|  Logic    |   x   |   x   |   x   |   x   |
+|-----------|-------|-------|-------|-------|
+|  Strash   |       |       |   x   |       |
+--------------------------------------------|*/
+
+// object types
+typedef enum { 
+    ABC_OBJ_NONE = 0,   //  0:  unknown
+    ABC_OBJ_CONST1,     //  1:  constant 1 node (AIG only)
+    ABC_OBJ_PI,         //  2:  primary input terminal
+    ABC_OBJ_PO,         //  3:  primary output terminal
+    ABC_OBJ_BI,         //  4:  box input terminal
+    ABC_OBJ_BO,         //  5:  box output terminal
+    ABC_OBJ_NET,        //  6:  net
+    ABC_OBJ_NODE,       //  7:  node
+    ABC_OBJ_LATCH,      //  8:  latch
+    ABC_OBJ_WHITEBOX,   //  9:  box with known contents
+    ABC_OBJ_BLACKBOX,   // 10:  box with unknown contents
+    ABC_OBJ_NUMBER      // 11:  unused
+} Abc_ObjType_t;
+
+// latch initial values
+typedef enum { 
+    ABC_INIT_NONE = 0,  // 0:  unknown
+    ABC_INIT_ZERO,      // 1:  zero
+    ABC_INIT_ONE,       // 2:  one
+    ABC_INIT_DC,        // 3:  don't-care
+    ABC_INIT_OTHER      // 4:  unused
+} Abc_InitType_t;
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Abc_Des_t_       Abc_Des_t;
+typedef struct Abc_Ntk_t_       Abc_Ntk_t;
+typedef struct Abc_Obj_t_       Abc_Obj_t;
+typedef struct Abc_Aig_t_       Abc_Aig_t;
+typedef struct Abc_ManTime_t_   Abc_ManTime_t;
+typedef struct Abc_ManCut_t_    Abc_ManCut_t;
+typedef struct Abc_Time_t_      Abc_Time_t;
+
+struct Abc_Time_t_
+{
+    float             Rise;
+    float             Fall;
+};
+
+struct Abc_Obj_t_     // 48/72 bytes (32-bits/64-bits)
+{
+    Abc_Ntk_t *       pNtk;          // the host network
+    Abc_Obj_t *       pNext;         // the next pointer in the hash table
+    int               Id;            // the object ID
+    unsigned          Type    :  4;  // the object type
+    unsigned          fMarkA  :  1;  // the multipurpose mark
+    unsigned          fMarkB  :  1;  // the multipurpose mark
+    unsigned          fMarkC  :  1;  // the multipurpose mark
+    unsigned          fPhase  :  1;  // the flag to mark the phase of equivalent node
+    unsigned          fExor   :  1;  // marks AIG node that is a root of EXOR
+    unsigned          fPersist:  1;  // marks the persistant AIG node
+    unsigned          fCompl0 :  1;  // complemented attribute of the first fanin in the AIG
+    unsigned          fCompl1 :  1;  // complemented attribute of the second fanin in the AIG 
+    unsigned          Level   : 20;  // the level of the node
+    Vec_Int_t         vFanins;       // the array of fanins
+    Vec_Int_t         vFanouts;      // the array of fanouts
+    union { void *    pData;         // the network specific data
+      int             iData; };      // (SOP, BDD, gate, equiv class, etc)
+    union { void *    pTemp;         // temporary store for user's data
+      Abc_Obj_t *     pCopy;         // the copy of this object
+      int             iTemp;
+      float           dTemp; };
+};
+
+struct Abc_Ntk_t_ 
+{
+    // general information 
+    Abc_NtkType_t     ntkType;       // type of the network
+    Abc_NtkFunc_t     ntkFunc;       // functionality of the network
+    char *            pName;         // the network name
+    char *            pSpec;         // the name of the spec file if present
+    Nm_Man_t *        pManName;      // name manager (stores names of objects)
+    // components of the network
+    Vec_Ptr_t *       vObjs;         // the array of all objects (net, nodes, latches, etc)
+    Vec_Ptr_t *       vPis;          // the array of primary inputs
+    Vec_Ptr_t *       vPos;          // the array of primary outputs
+    Vec_Ptr_t *       vCis;          // the array of combinational inputs  (PIs, latches)
+    Vec_Ptr_t *       vCos;          // the array of combinational outputs (POs, asserts, latches)
+    Vec_Ptr_t *       vPios;         // the array of PIOs
+    Vec_Ptr_t *       vBoxes;        // the array of boxes
+    Vec_Ptr_t *       vLtlProperties;
+    // the number of living objects
+    int nObjCounts[ABC_OBJ_NUMBER];  // the number of objects by type
+    int               nObjs;         // the number of live objs
+    int               nConstrs;      // the number of constraints
+    int               nBarBufs;      // the number of barrier buffers
+    // the backup network and the step number
+    Abc_Ntk_t *       pNetBackup;    // the pointer to the previous backup network
+    int               iStep;         // the generation number for the given network
+    // hierarchy
+    Abc_Des_t *       pDesign;       // design (hierarchical networks only)     
+    Abc_Ntk_t *       pAltView;      // alternative structural view of the network
+    int               fHieVisited;   // flag to mark the visited network
+    int               fHiePath;      // flag to mark the network on the path
+    int               Id;            // model ID
+    double            dTemp;         // temporary value
+    // miscellaneous data members
+    int               nTravIds;      // the unique traversal IDs of nodes
+    Vec_Int_t         vTravIds;      // trav IDs of the objects
+    Mem_Fixed_t *     pMmObj;        // memory manager for objects
+    Mem_Step_t *      pMmStep;       // memory manager for arrays
+    void *            pManFunc;      // functionality manager (AIG manager, BDD manager, or memory manager for SOPs)
+    Abc_ManTime_t *   pManTime;      // the timing manager (for mapped networks) stores arrival/required times for all nodes
+    void *            pManCut;       // the cut manager (for AIGs) stores information about the cuts computed for the nodes
+    float             AndGateDelay;  // an average estimated delay of one AND gate
+    int               LevelMax;      // maximum number of levels
+    Vec_Int_t *       vLevelsR;      // level in the reverse topological order (for AIGs)
+    Vec_Ptr_t *       vSupps;        // CO support information
+    int *             pModel;        // counter-example (for miters)
+    Abc_Cex_t *       pSeqModel;     // counter-example (for sequential miters)
+    Vec_Ptr_t *       vSeqModelVec;  // vector of counter-examples (for sequential miters)
+    Abc_Ntk_t *       pExdc;         // the EXDC network (if given)
+    void *            pExcare;       // the EXDC network (if given)
+    void *            pData;         // misc
+    Abc_Ntk_t *       pCopy;         // copy of this network
+    void *            pBSMan;        // application manager
+    void *            pSCLib;        // SC library
+    Vec_Int_t *       vGates;        // SC library gates
+    Vec_Int_t *       vPhases;       // fanins phases in the mapped netlist
+    char *            pWLoadUsed;    // wire load model used
+    float *           pLutTimes;     // arrivals/requireds/slacks using LUT-delay model
+    Vec_Ptr_t *       vOnehots;      // names of one-hot-encoded registers
+    Vec_Int_t *       vObjPerm;      // permutation saved
+    Vec_Int_t *       vTopo;
+    Vec_Ptr_t *       vAttrs;        // managers of various node attributes (node functionality, global BDDs, etc)
+    Vec_Int_t *       vNameIds;      // name IDs
+};
+
+struct Abc_Des_t_ 
+{
+    char *            pName;         // the name of the library
+    void *            pManFunc;      // functionality manager for the nodes
+    Vec_Ptr_t *       vTops;         // the array of top-level modules
+    Vec_Ptr_t *       vModules;      // the array of modules
+    st__table *        tModules;      // the table hashing module names into their networks
+    Abc_Des_t *       pLibrary;      // the library used to map this design
+    void *            pGenlib;       // the genlib library used to map this design
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+// transforming floats into ints and back
+static inline unsigned    Abc_InfoRandomWord()                       { return ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())); } // #define RAND_MAX 0x7fff
+static inline void        Abc_InfoRandom( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = Abc_InfoRandomWord();   } 
+static inline void        Abc_InfoClear( unsigned * p, int nWords )  { memset( p, 0, sizeof(unsigned) * nWords );   } 
+static inline void        Abc_InfoFill( unsigned * p, int nWords )   { memset( p, 0xff, sizeof(unsigned) * nWords );} 
+static inline void        Abc_InfoNot( unsigned * p, int nWords )    { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = ~p[i];   } 
+static inline int         Abc_InfoIsZero( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) if ( p[i] )  return 0; return 1; } 
+static inline int         Abc_InfoIsOne( unsigned * p, int nWords )  { int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~p[i] ) return 0; return 1; } 
+static inline void        Abc_InfoCopy( unsigned * p, unsigned * q, int nWords )   { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i]  = q[i];  } 
+static inline void        Abc_InfoAnd( unsigned * p, unsigned * q, int nWords )    { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] &= q[i];  } 
+static inline void        Abc_InfoOr( unsigned * p, unsigned * q, int nWords )     { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] |= q[i];  } 
+static inline void        Abc_InfoXor( unsigned * p, unsigned * q, int nWords )    { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] ^= q[i];  } 
+static inline int         Abc_InfoIsOrOne( unsigned * p, unsigned * q, int nWords ){ int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~(p[i] | q[i]) ) return 0; return 1; } 
+static inline int         Abc_InfoIsOrOne3( unsigned * p, unsigned * q, unsigned * r, int nWords ){ int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~(p[i] | q[i] | r[i]) ) return 0; return 1; } 
+
+// checking the network type
+static inline int         Abc_NtkIsNetlist( Abc_Ntk_t * pNtk )       { return pNtk->ntkType == ABC_NTK_NETLIST;     }
+static inline int         Abc_NtkIsLogic( Abc_Ntk_t * pNtk )         { return pNtk->ntkType == ABC_NTK_LOGIC;       }
+static inline int         Abc_NtkIsStrash( Abc_Ntk_t * pNtk )        { return pNtk->ntkType == ABC_NTK_STRASH;      }
+
+static inline int         Abc_NtkHasSop( Abc_Ntk_t * pNtk )          { return pNtk->ntkFunc == ABC_FUNC_SOP;        }
+static inline int         Abc_NtkHasBdd( Abc_Ntk_t * pNtk )          { return pNtk->ntkFunc == ABC_FUNC_BDD;        }
+static inline int         Abc_NtkHasAig( Abc_Ntk_t * pNtk )          { return pNtk->ntkFunc == ABC_FUNC_AIG;        }
+static inline int         Abc_NtkHasMapping( Abc_Ntk_t * pNtk )      { return pNtk->ntkFunc == ABC_FUNC_MAP;        }
+static inline int         Abc_NtkHasBlifMv( Abc_Ntk_t * pNtk )       { return pNtk->ntkFunc == ABC_FUNC_BLIFMV;     }
+static inline int         Abc_NtkHasBlackbox( Abc_Ntk_t * pNtk )     { return pNtk->ntkFunc == ABC_FUNC_BLACKBOX;   }
+
+static inline int         Abc_NtkIsSopNetlist( Abc_Ntk_t * pNtk )    { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_NTK_NETLIST;  }
+static inline int         Abc_NtkIsAigNetlist( Abc_Ntk_t * pNtk )    { return pNtk->ntkFunc == ABC_FUNC_AIG && pNtk->ntkType == ABC_NTK_NETLIST;  }
+static inline int         Abc_NtkIsMappedNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_NTK_NETLIST;  }
+static inline int         Abc_NtkIsBlifMvNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLIFMV && pNtk->ntkType == ABC_NTK_NETLIST;  }
+static inline int         Abc_NtkIsSopLogic( Abc_Ntk_t * pNtk )      { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_NTK_LOGIC  ;  }
+static inline int         Abc_NtkIsBddLogic( Abc_Ntk_t * pNtk )      { return pNtk->ntkFunc == ABC_FUNC_BDD && pNtk->ntkType == ABC_NTK_LOGIC  ;  }
+static inline int         Abc_NtkIsAigLogic( Abc_Ntk_t * pNtk )      { return pNtk->ntkFunc == ABC_FUNC_AIG && pNtk->ntkType == ABC_NTK_LOGIC  ;  }
+static inline int         Abc_NtkIsMappedLogic( Abc_Ntk_t * pNtk )   { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_NTK_LOGIC  ;  }
+
+// reading data members of the network
+static inline char *      Abc_NtkName( Abc_Ntk_t * pNtk )            { return pNtk->pName;            }
+static inline char *      Abc_NtkSpec( Abc_Ntk_t * pNtk )            { return pNtk->pSpec;            }
+static inline Abc_Ntk_t * Abc_NtkExdc( Abc_Ntk_t * pNtk )            { return pNtk->pExdc;            }
+static inline Abc_Ntk_t * Abc_NtkBackup( Abc_Ntk_t * pNtk )          { return pNtk->pNetBackup;       }
+static inline int         Abc_NtkStep  ( Abc_Ntk_t * pNtk )          { return pNtk->iStep;            }
+
+// setting data members of the network
+static inline void        Abc_NtkSetName  ( Abc_Ntk_t * pNtk, char * pName )           { pNtk->pName      = pName;      } 
+static inline void        Abc_NtkSetSpec  ( Abc_Ntk_t * pNtk, char * pName )           { pNtk->pSpec      = pName;      } 
+static inline void        Abc_NtkSetBackup( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNetBackup ) { pNtk->pNetBackup = pNetBackup; }
+static inline void        Abc_NtkSetStep  ( Abc_Ntk_t * pNtk, int iStep )              { pNtk->iStep      = iStep;      }
+
+// getting the number of objects 
+static inline int         Abc_NtkObjNum( Abc_Ntk_t * pNtk )          { return pNtk->nObjs;                        }
+static inline int         Abc_NtkObjNumMax( Abc_Ntk_t * pNtk )       { return Vec_PtrSize(pNtk->vObjs);           }
+static inline int         Abc_NtkPiNum( Abc_Ntk_t * pNtk )           { return Vec_PtrSize(pNtk->vPis);            }
+static inline int         Abc_NtkPoNum( Abc_Ntk_t * pNtk )           { return Vec_PtrSize(pNtk->vPos);            }
+static inline int         Abc_NtkCiNum( Abc_Ntk_t * pNtk )           { return Vec_PtrSize(pNtk->vCis);            }
+static inline int         Abc_NtkCoNum( Abc_Ntk_t * pNtk )           { return Vec_PtrSize(pNtk->vCos);            }
+static inline int         Abc_NtkBoxNum( Abc_Ntk_t * pNtk )          { return Vec_PtrSize(pNtk->vBoxes);          }
+static inline int         Abc_NtkBiNum( Abc_Ntk_t * pNtk )           { return pNtk->nObjCounts[ABC_OBJ_BI];       }
+static inline int         Abc_NtkBoNum( Abc_Ntk_t * pNtk )           { return pNtk->nObjCounts[ABC_OBJ_BO];       }
+static inline int         Abc_NtkNetNum( Abc_Ntk_t * pNtk )          { return pNtk->nObjCounts[ABC_OBJ_NET];      }
+static inline int         Abc_NtkNodeNum( Abc_Ntk_t * pNtk )         { return pNtk->nObjCounts[ABC_OBJ_NODE];     }
+static inline int         Abc_NtkLatchNum( Abc_Ntk_t * pNtk )        { return pNtk->nObjCounts[ABC_OBJ_LATCH];    }
+static inline int         Abc_NtkWhiteboxNum( Abc_Ntk_t * pNtk )     { return pNtk->nObjCounts[ABC_OBJ_WHITEBOX]; }
+static inline int         Abc_NtkBlackboxNum( Abc_Ntk_t * pNtk )     { return pNtk->nObjCounts[ABC_OBJ_BLACKBOX]; }
+static inline int         Abc_NtkIsComb( Abc_Ntk_t * pNtk )          { return Abc_NtkLatchNum(pNtk) == 0;                   }
+static inline int         Abc_NtkHasOnlyLatchBoxes(Abc_Ntk_t * pNtk ){ return Abc_NtkLatchNum(pNtk) == Abc_NtkBoxNum(pNtk); }
+static inline int         Abc_NtkConstrNum( Abc_Ntk_t * pNtk )       { return pNtk->nConstrs;                     }
+
+// creating simple objects
+extern ABC_DLL Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type );
+static inline Abc_Obj_t * Abc_NtkCreatePi( Abc_Ntk_t * pNtk )        { return Abc_NtkCreateObj( pNtk, ABC_OBJ_PI );         }
+static inline Abc_Obj_t * Abc_NtkCreatePo( Abc_Ntk_t * pNtk )        { return Abc_NtkCreateObj( pNtk, ABC_OBJ_PO );         }
+static inline Abc_Obj_t * Abc_NtkCreateBi( Abc_Ntk_t * pNtk )        { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BI );         }
+static inline Abc_Obj_t * Abc_NtkCreateBo( Abc_Ntk_t * pNtk )        { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BO );         }
+static inline Abc_Obj_t * Abc_NtkCreateNet( Abc_Ntk_t * pNtk )       { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NET );        }
+static inline Abc_Obj_t * Abc_NtkCreateNode( Abc_Ntk_t * pNtk )      { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NODE );       }
+static inline Abc_Obj_t * Abc_NtkCreateLatch( Abc_Ntk_t * pNtk )     { return Abc_NtkCreateObj( pNtk, ABC_OBJ_LATCH );      }
+static inline Abc_Obj_t * Abc_NtkCreateWhitebox( Abc_Ntk_t * pNtk )  { return Abc_NtkCreateObj( pNtk, ABC_OBJ_WHITEBOX );   }
+static inline Abc_Obj_t * Abc_NtkCreateBlackbox( Abc_Ntk_t * pNtk )  { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BLACKBOX );   }
+
+// reading objects
+static inline Abc_Obj_t * Abc_NtkObj( Abc_Ntk_t * pNtk, int i )      { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vObjs, i );   }
+static inline Abc_Obj_t * Abc_NtkPi( Abc_Ntk_t * pNtk, int i )       { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPis, i );    }
+static inline Abc_Obj_t * Abc_NtkPo( Abc_Ntk_t * pNtk, int i )       { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPos, i );    }
+static inline Abc_Obj_t * Abc_NtkCi( Abc_Ntk_t * pNtk, int i )       { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, i );    }
+static inline Abc_Obj_t * Abc_NtkCo( Abc_Ntk_t * pNtk, int i )       { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, i );    }
+static inline Abc_Obj_t * Abc_NtkBox( Abc_Ntk_t * pNtk, int i )      { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vBoxes, i );  }
+
+// working with complemented attributes of objects
+static inline int         Abc_ObjIsComplement( Abc_Obj_t * p )       { return (int )((ABC_PTRUINT_T)p & (ABC_PTRUINT_T)01);             }
+static inline Abc_Obj_t * Abc_ObjRegular( Abc_Obj_t * p )            { return (Abc_Obj_t *)((ABC_PTRUINT_T)p & ~(ABC_PTRUINT_T)01);     }
+static inline Abc_Obj_t * Abc_ObjNot( Abc_Obj_t * p )                { return (Abc_Obj_t *)((ABC_PTRUINT_T)p ^  (ABC_PTRUINT_T)01);     }
+static inline Abc_Obj_t * Abc_ObjNotCond( Abc_Obj_t * p, int c )     { return (Abc_Obj_t *)((ABC_PTRUINT_T)p ^  (ABC_PTRUINT_T)(c!=0)); }
+
+// reading data members of the object
+static inline unsigned    Abc_ObjType( Abc_Obj_t * pObj )            { return pObj->Type;               }
+static inline unsigned    Abc_ObjId( Abc_Obj_t * pObj )              { return pObj->Id;                 }
+static inline int         Abc_ObjLevel( Abc_Obj_t * pObj )           { return pObj->Level;              }
+static inline Vec_Int_t * Abc_ObjFaninVec( Abc_Obj_t * pObj )        { return &pObj->vFanins;           }
+static inline Vec_Int_t * Abc_ObjFanoutVec( Abc_Obj_t * pObj )       { return &pObj->vFanouts;          }
+static inline Abc_Obj_t * Abc_ObjCopy( Abc_Obj_t * pObj )            { return pObj->pCopy;              }
+static inline Abc_Ntk_t * Abc_ObjNtk( Abc_Obj_t * pObj )             { return pObj->pNtk;               }
+static inline Abc_Ntk_t * Abc_ObjModel( Abc_Obj_t * pObj )           { assert( pObj->Type == ABC_OBJ_WHITEBOX ); return (Abc_Ntk_t *)pObj->pData;   }
+static inline void *      Abc_ObjData( Abc_Obj_t * pObj )            { return pObj->pData;              }
+static inline Abc_Obj_t * Abc_ObjEquiv( Abc_Obj_t * pObj )           { return (Abc_Obj_t *)pObj->pData; }
+static inline Abc_Obj_t * Abc_ObjCopyCond( Abc_Obj_t * pObj )        { return Abc_ObjRegular(pObj)->pCopy? Abc_ObjNotCond(Abc_ObjRegular(pObj)->pCopy, Abc_ObjIsComplement(pObj)) : NULL;  }
+
+// setting data members of the network
+static inline void        Abc_ObjSetLevel( Abc_Obj_t * pObj, int Level )         { pObj->Level =  Level;    } 
+static inline void        Abc_ObjSetCopy( Abc_Obj_t * pObj, Abc_Obj_t * pCopy )  { pObj->pCopy =  pCopy;    } 
+static inline void        Abc_ObjSetData( Abc_Obj_t * pObj, void * pData )       { pObj->pData =  pData;    } 
+
+// checking the object type
+static inline int         Abc_ObjIsNone( Abc_Obj_t * pObj )          { return pObj->Type == ABC_OBJ_NONE;    }
+static inline int         Abc_ObjIsPi( Abc_Obj_t * pObj )            { return pObj->Type == ABC_OBJ_PI;      }
+static inline int         Abc_ObjIsPo( Abc_Obj_t * pObj )            { return pObj->Type == ABC_OBJ_PO;      }
+static inline int         Abc_ObjIsBi( Abc_Obj_t * pObj )            { return pObj->Type == ABC_OBJ_BI;      }
+static inline int         Abc_ObjIsBo( Abc_Obj_t * pObj )            { return pObj->Type == ABC_OBJ_BO;      }
+static inline int         Abc_ObjIsCi( Abc_Obj_t * pObj )            { return pObj->Type == ABC_OBJ_PI || pObj->Type == ABC_OBJ_BO; }
+static inline int         Abc_ObjIsCo( Abc_Obj_t * pObj )            { return pObj->Type == ABC_OBJ_PO || pObj->Type == ABC_OBJ_BI; }
+static inline int         Abc_ObjIsTerm( Abc_Obj_t * pObj )          { return Abc_ObjIsCi(pObj) || Abc_ObjIsCo(pObj); }
+static inline int         Abc_ObjIsNet( Abc_Obj_t * pObj )           { return pObj->Type == ABC_OBJ_NET;     }
+static inline int         Abc_ObjIsNode( Abc_Obj_t * pObj )          { return pObj->Type == ABC_OBJ_NODE;    }
+static inline int         Abc_ObjIsLatch( Abc_Obj_t * pObj )         { return pObj->Type == ABC_OBJ_LATCH;   }
+static inline int         Abc_ObjIsBox( Abc_Obj_t * pObj )           { return pObj->Type == ABC_OBJ_LATCH || pObj->Type == ABC_OBJ_WHITEBOX || pObj->Type == ABC_OBJ_BLACKBOX; }
+static inline int         Abc_ObjIsWhitebox( Abc_Obj_t * pObj )      { return pObj->Type == ABC_OBJ_WHITEBOX;}
+static inline int         Abc_ObjIsBlackbox( Abc_Obj_t * pObj )      { return pObj->Type == ABC_OBJ_BLACKBOX;}
+static inline int         Abc_ObjIsBarBuf( Abc_Obj_t * pObj )        { assert( Abc_NtkIsMappedLogic(pObj->pNtk) ); return Vec_IntSize(&pObj->vFanins) == 1 && pObj->pData == NULL;  }
+static inline void        Abc_ObjBlackboxToWhitebox( Abc_Obj_t * pObj ) { assert( Abc_ObjIsBlackbox(pObj) ); pObj->Type = ABC_OBJ_WHITEBOX; pObj->pNtk->nObjCounts[ABC_OBJ_BLACKBOX]--; pObj->pNtk->nObjCounts[ABC_OBJ_WHITEBOX]++; }
+
+// working with fanin/fanout edges
+static inline int         Abc_ObjFaninNum( Abc_Obj_t * pObj )        { return pObj->vFanins.nSize;     }
+static inline int         Abc_ObjFanoutNum( Abc_Obj_t * pObj )       { return pObj->vFanouts.nSize;    }
+static inline int         Abc_ObjFaninId( Abc_Obj_t * pObj, int i)   { return pObj->vFanins.pArray[i]; }
+static inline int         Abc_ObjFaninId0( Abc_Obj_t * pObj )        { return pObj->vFanins.pArray[0]; }
+static inline int         Abc_ObjFaninId1( Abc_Obj_t * pObj )        { return pObj->vFanins.pArray[1]; }
+static inline int         Abc_ObjFanoutEdgeNum( Abc_Obj_t * pObj, Abc_Obj_t * pFanout )  { assert( Abc_NtkHasAig(pObj->pNtk) );  if ( Abc_ObjFaninId0(pFanout) == pObj->Id ) return 0; if ( Abc_ObjFaninId1(pFanout) == pObj->Id ) return 1; assert( 0 ); return -1;  }
+static inline Abc_Obj_t * Abc_ObjFanout( Abc_Obj_t * pObj, int i )   { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[i] ];  }
+static inline Abc_Obj_t * Abc_ObjFanout0( Abc_Obj_t * pObj )         { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[0] ];  }
+static inline Abc_Obj_t * Abc_ObjFanin( Abc_Obj_t * pObj, int i )    { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[i] ];   }
+static inline Abc_Obj_t * Abc_ObjFanin0( Abc_Obj_t * pObj )          { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[0] ];   }
+static inline Abc_Obj_t * Abc_ObjFanin1( Abc_Obj_t * pObj )          { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[1] ];   }
+static inline Abc_Obj_t * Abc_ObjFanin0Ntk( Abc_Obj_t * pObj )       { return (Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanin0(pObj)  : pObj);  }
+static inline Abc_Obj_t * Abc_ObjFanout0Ntk( Abc_Obj_t * pObj )      { return (Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanout0(pObj) : pObj);  }
+static inline int         Abc_ObjFaninC0( Abc_Obj_t * pObj )         { return pObj->fCompl0;                                                }
+static inline int         Abc_ObjFaninC1( Abc_Obj_t * pObj )         { return pObj->fCompl1;                                                }
+static inline int         Abc_ObjFaninC( Abc_Obj_t * pObj, int i )   { assert( i >=0 && i < 2 ); return i? pObj->fCompl1 : pObj->fCompl0;   }
+static inline void        Abc_ObjSetFaninC( Abc_Obj_t * pObj, int i ){ assert( i >=0 && i < 2 ); if ( i ) pObj->fCompl1 = 1; else pObj->fCompl0 = 1; }
+static inline void        Abc_ObjXorFaninC( Abc_Obj_t * pObj, int i ){ assert( i >=0 && i < 2 ); if ( i ) pObj->fCompl1^= 1; else pObj->fCompl0^= 1; }
+static inline Abc_Obj_t * Abc_ObjChild( Abc_Obj_t * pObj, int i )    { return Abc_ObjNotCond( Abc_ObjFanin(pObj,i), Abc_ObjFaninC(pObj,i) );}
+static inline Abc_Obj_t * Abc_ObjChild0( Abc_Obj_t * pObj )          { return Abc_ObjNotCond( Abc_ObjFanin0(pObj), Abc_ObjFaninC0(pObj) );  }
+static inline Abc_Obj_t * Abc_ObjChild1( Abc_Obj_t * pObj )          { return Abc_ObjNotCond( Abc_ObjFanin1(pObj), Abc_ObjFaninC1(pObj) );  }
+static inline Abc_Obj_t * Abc_ObjChildCopy( Abc_Obj_t * pObj, int i ){ return Abc_ObjNotCond( Abc_ObjFanin(pObj,i)->pCopy, Abc_ObjFaninC(pObj,i) );  }
+static inline Abc_Obj_t * Abc_ObjChild0Copy( Abc_Obj_t * pObj )      { return Abc_ObjNotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) );    }
+static inline Abc_Obj_t * Abc_ObjChild1Copy( Abc_Obj_t * pObj )      { return Abc_ObjNotCond( Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC1(pObj) );    }
+static inline Abc_Obj_t * Abc_ObjChild0Data( Abc_Obj_t * pObj )      { return Abc_ObjNotCond( (Abc_Obj_t *)Abc_ObjFanin0(pObj)->pData, Abc_ObjFaninC0(pObj) );    }
+static inline Abc_Obj_t * Abc_ObjChild1Data( Abc_Obj_t * pObj )      { return Abc_ObjNotCond( (Abc_Obj_t *)Abc_ObjFanin1(pObj)->pData, Abc_ObjFaninC1(pObj) );    }
+static inline Abc_Obj_t * Abc_ObjFromLit( Abc_Ntk_t * p, int iLit )  { return Abc_ObjNotCond( Abc_NtkObj(p, Abc_Lit2Var(iLit)), Abc_LitIsCompl(iLit) );           }
+static inline int         Abc_ObjToLit( Abc_Obj_t * p )              { return Abc_Var2Lit( Abc_ObjId(Abc_ObjRegular(p)), Abc_ObjIsComplement(p) );                }
+static inline int         Abc_ObjFaninPhase( Abc_Obj_t * p, int i )  { assert(p->pNtk->vPhases); assert( i >= 0 && i < Abc_ObjFaninNum(p) ); return (Vec_IntEntry(p->pNtk->vPhases, Abc_ObjId(p)) >> i) & 1;  } 
+static inline void        Abc_ObjFaninFlipPhase( Abc_Obj_t * p,int i){ assert(p->pNtk->vPhases); assert( i >= 0 && i < Abc_ObjFaninNum(p) ); *Vec_IntEntryP(p->pNtk->vPhases, Abc_ObjId(p)) ^= (1 << i);      } 
+
+// checking the AIG node types
+static inline int         Abc_AigNodeIsConst( Abc_Obj_t * pNode )    { assert(Abc_NtkIsStrash(Abc_ObjRegular(pNode)->pNtk));  return Abc_ObjRegular(pNode)->Type == ABC_OBJ_CONST1;       }
+static inline int         Abc_AigNodeIsAnd( Abc_Obj_t * pNode )      { assert(!Abc_ObjIsComplement(pNode)); assert(Abc_NtkIsStrash(pNode->pNtk)); return Abc_ObjFaninNum(pNode) == 2;                         }
+static inline int         Abc_AigNodeIsChoice( Abc_Obj_t * pNode )   { assert(!Abc_ObjIsComplement(pNode)); assert(Abc_NtkIsStrash(pNode->pNtk)); return pNode->pData != NULL && Abc_ObjFanoutNum(pNode) > 0; }
+
+// handling persistent nodes
+static inline int         Abc_NodeIsPersistant( Abc_Obj_t * pNode )    { assert( Abc_AigNodeIsAnd(pNode) ); return pNode->fPersist; } 
+static inline void        Abc_NodeSetPersistant( Abc_Obj_t * pNode )   { assert( Abc_AigNodeIsAnd(pNode) ); pNode->fPersist = 1;    } 
+static inline void        Abc_NodeClearPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); pNode->fPersist = 0;    } 
+
+// working with the traversal ID
+static inline void        Abc_NtkIncrementTravId( Abc_Ntk_t * p )           { if (!p->vTravIds.pArray) Vec_IntFill(&p->vTravIds, Abc_NtkObjNumMax(p)+500, 0); p->nTravIds++; assert(p->nTravIds < (1<<30));  }
+static inline int         Abc_NodeTravId( Abc_Obj_t * p )                   { return Vec_IntGetEntry(&Abc_ObjNtk(p)->vTravIds, Abc_ObjId(p));                       }
+static inline void        Abc_NodeSetTravId( Abc_Obj_t * p, int TravId )    { Vec_IntSetEntry(&Abc_ObjNtk(p)->vTravIds, Abc_ObjId(p), TravId );                     }
+static inline void        Abc_NodeSetTravIdCurrent( Abc_Obj_t * p )         { Abc_NodeSetTravId( p, Abc_ObjNtk(p)->nTravIds );                                      }
+static inline void        Abc_NodeSetTravIdPrevious( Abc_Obj_t * p )        { Abc_NodeSetTravId( p, Abc_ObjNtk(p)->nTravIds-1 );                                    }
+static inline int         Abc_NodeIsTravIdCurrent( Abc_Obj_t * p )          { return (Abc_NodeTravId(p) == Abc_ObjNtk(p)->nTravIds);                                }
+static inline int         Abc_NodeIsTravIdPrevious( Abc_Obj_t * p )         { return (Abc_NodeTravId(p) == Abc_ObjNtk(p)->nTravIds-1);                              }
+static inline void        Abc_NodeSetTravIdCurrentId( Abc_Ntk_t * p, int i) { Vec_IntSetEntry(&p->vTravIds, i, p->nTravIds );                                       }
+static inline int         Abc_NodeIsTravIdCurrentId( Abc_Ntk_t * p, int i)  { return (Vec_IntGetEntry(&p->vTravIds, i) == p->nTravIds);                             }
+
+// checking initial state of the latches
+static inline void        Abc_LatchSetInitNone( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_NONE;                       }
+static inline void        Abc_LatchSetInit0( Abc_Obj_t * pLatch )    { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_ZERO;                       }
+static inline void        Abc_LatchSetInit1( Abc_Obj_t * pLatch )    { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_ONE;                        }
+static inline void        Abc_LatchSetInitDc( Abc_Obj_t * pLatch )   { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_DC;                         }
+static inline int         Abc_LatchIsInitNone( Abc_Obj_t * pLatch )  { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_NONE;               }
+static inline int         Abc_LatchIsInit0( Abc_Obj_t * pLatch )     { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_ZERO;               }
+static inline int         Abc_LatchIsInit1( Abc_Obj_t * pLatch )     { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_ONE;                }
+static inline int         Abc_LatchIsInitDc( Abc_Obj_t * pLatch )    { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_DC;                 }
+static inline int         Abc_LatchInit( Abc_Obj_t * pLatch )        { assert(Abc_ObjIsLatch(pLatch)); return (int)(ABC_PTRINT_T)pLatch->pData;                     }
+
+// global BDDs of the nodes
+static inline void *      Abc_NtkGlobalBdd( Abc_Ntk_t * pNtk )          { return Vec_PtrEntry(pNtk->vAttrs, VEC_ATTR_GLOBAL_BDD);                                   }
+static inline void *      Abc_NtkGlobalBddMan( Abc_Ntk_t * pNtk )       { return Vec_AttMan( (Vec_Att_t *)Abc_NtkGlobalBdd(pNtk) );                                 }
+static inline void **     Abc_NtkGlobalBddArray( Abc_Ntk_t * pNtk )     { return Vec_AttArray( (Vec_Att_t *)Abc_NtkGlobalBdd(pNtk) );                               }
+static inline void *      Abc_ObjGlobalBdd( Abc_Obj_t * pObj )          { return Vec_AttEntry( (Vec_Att_t *)Abc_NtkGlobalBdd(pObj->pNtk), pObj->Id );               }
+static inline void        Abc_ObjSetGlobalBdd( Abc_Obj_t * pObj, void * bF )   { Vec_AttWriteEntry( (Vec_Att_t *)Abc_NtkGlobalBdd(pObj->pNtk), pObj->Id, bF );      }
+
+// MV variables of the nodes
+static inline void *      Abc_NtkMvVar( Abc_Ntk_t * pNtk )              { return Vec_PtrEntry(pNtk->vAttrs, VEC_ATTR_MVVAR);                                        }
+static inline void *      Abc_NtkMvVarMan( Abc_Ntk_t * pNtk )           { return Abc_NtkMvVar(pNtk)? Vec_AttMan( (Vec_Att_t *)Abc_NtkMvVar(pNtk) ) : NULL;          }
+static inline void *      Abc_ObjMvVar( Abc_Obj_t * pObj )              { return Abc_NtkMvVar(pObj->pNtk)? Vec_AttEntry( (Vec_Att_t *)Abc_NtkMvVar(pObj->pNtk), pObj->Id ) : NULL; }
+static inline int         Abc_ObjMvVarNum( Abc_Obj_t * pObj )           { return (Abc_NtkMvVar(pObj->pNtk) && Abc_ObjMvVar(pObj))? *((int*)Abc_ObjMvVar(pObj)) : 2; }
+static inline void        Abc_ObjSetMvVar( Abc_Obj_t * pObj, void * pV) { Vec_AttWriteEntry( (Vec_Att_t *)Abc_NtkMvVar(pObj->pNtk), pObj->Id, pV );                 }
+
+////////////////////////////////////////////////////////////////////////
+///                        ITERATORS                                 ///
+////////////////////////////////////////////////////////////////////////
+
+// objects of the network
+#define Abc_NtkForEachObj( pNtk, pObj, i )                                                         \
+    for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pObj) = Abc_NtkObj(pNtk, i)), 1); i++ )    \
+        if ( (pObj) == NULL ) {} else
+#define Abc_NtkForEachObjReverse( pNtk, pNode, i )                                                 \
+    for ( i = Vec_PtrSize((pNtk)->vObjs) - 1; (i >= 0) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i-- ) \
+        if ( (pNode) == NULL ) {} else
+#define Abc_NtkForEachObjVec( vIds, pNtk, pObj, i )                                                \
+    for ( i = 0; i < Vec_IntSize(vIds) && (((pObj) = Abc_NtkObj(pNtk, Vec_IntEntry(vIds,i))), 1); i++ ) \
+        if ( (pObj) == NULL ) {} else
+#define Abc_NtkForEachObjVecStart( vIds, pNtk, pObj, i, Start )                                    \
+    for ( i = Start; i < Vec_IntSize(vIds) && (((pObj) = Abc_NtkObj(pNtk, Vec_IntEntry(vIds,i))), 1); i++ ) \
+        if ( (pObj) == NULL ) {} else
+#define Abc_NtkForEachNet( pNtk, pNet, i )                                                         \
+    for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNet) = Abc_NtkObj(pNtk, i)), 1); i++ )    \
+        if ( (pNet) == NULL || !Abc_ObjIsNet(pNet) ) {} else
+#define Abc_NtkForEachNode( pNtk, pNode, i )                                                       \
+    for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ )   \
+        if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) ) {} else
+#define Abc_NtkForEachNode1( pNtk, pNode, i )                                                      \
+    for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ )   \
+        if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) || !Abc_ObjFaninNum(pNode) ) {} else
+#define Abc_NtkForEachNodeReverse( pNtk, pNode, i )                                                \
+    for ( i = Vec_PtrSize((pNtk)->vObjs) - 1; (i >= 0) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i-- ) \
+        if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) ) {} else
+#define Abc_NtkForEachNodeReverse1( pNtk, pNode, i )                                               \
+    for ( i = Vec_PtrSize((pNtk)->vObjs) - 1; (i >= 0) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i-- ) \
+        if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) || !Abc_ObjFaninNum(pNode) ) {} else
+#define Abc_NtkForEachGate( pNtk, pNode, i )                                                       \
+    for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ )   \
+        if ( (pNode) == NULL || !Abc_ObjIsGate(pNode) ) {} else
+#define Abc_AigForEachAnd( pNtk, pNode, i )                                                        \
+    for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ )   \
+        if ( (pNode) == NULL || !Abc_AigNodeIsAnd(pNode) ) {} else
+#define Abc_NtkForEachNodeCi( pNtk, pNode, i )                                                       \
+    for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ )   \
+        if ( (pNode) == NULL || (!Abc_ObjIsNode(pNode) && !Abc_ObjIsCi(pNode)) ) {} else
+#define Abc_NtkForEachNodeCo( pNtk, pNode, i )                                                       \
+    for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ )   \
+        if ( (pNode) == NULL || (!Abc_ObjIsNode(pNode) && !Abc_ObjIsCo(pNode)) ) {} else
+// various boxes
+#define Abc_NtkForEachBox( pNtk, pObj, i )                                                         \
+    for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ )
+#define Abc_NtkForEachLatch( pNtk, pObj, i )                                                       \
+    for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ )   \
+        if ( !Abc_ObjIsLatch(pObj) ) {} else
+#define Abc_NtkForEachLatchInput( pNtk, pObj, i )                                                  \
+    for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)); i++ )                                          \
+        if ( !(Abc_ObjIsLatch(Abc_NtkBox(pNtk, i)) && (((pObj) = Abc_ObjFanin0(Abc_NtkBox(pNtk, i))), 1)) ) {} else
+#define Abc_NtkForEachLatchOutput( pNtk, pObj, i )                                                 \
+    for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)); i++ )                                          \
+        if ( !(Abc_ObjIsLatch(Abc_NtkBox(pNtk, i)) && (((pObj) = Abc_ObjFanout0(Abc_NtkBox(pNtk, i))), 1)) ) {} else
+#define Abc_NtkForEachWhitebox( pNtk, pObj, i )                                                    \
+    for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ )   \
+        if ( !Abc_ObjIsWhitebox(pObj) ) {} else
+#define Abc_NtkForEachBlackbox( pNtk, pObj, i )                                                    \
+    for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ )   \
+        if ( !Abc_ObjIsBlackbox(pObj) ) {} else
+// inputs and outputs
+#define Abc_NtkForEachPi( pNtk, pPi, i )                                                           \
+    for ( i = 0; (i < Abc_NtkPiNum(pNtk)) && (((pPi) = Abc_NtkPi(pNtk, i)), 1); i++ )
+#define Abc_NtkForEachCi( pNtk, pCi, i )                                                           \
+    for ( i = 0; (i < Abc_NtkCiNum(pNtk)) && (((pCi) = Abc_NtkCi(pNtk, i)), 1); i++ )
+#define Abc_NtkForEachPo( pNtk, pPo, i )                                                           \
+    for ( i = 0; (i < Abc_NtkPoNum(pNtk)) && (((pPo) = Abc_NtkPo(pNtk, i)), 1); i++ )
+#define Abc_NtkForEachCo( pNtk, pCo, i )                                                           \
+    for ( i = 0; (i < Abc_NtkCoNum(pNtk)) && (((pCo) = Abc_NtkCo(pNtk, i)), 1); i++ )
+#define Abc_NtkForEachLiPo( pNtk, pCo, i )                                                         \
+    for ( i = 0; (i < Abc_NtkCoNum(pNtk)) && (((pCo) = Abc_NtkCo(pNtk, i < pNtk->nBarBufs ? Abc_NtkCoNum(pNtk) - pNtk->nBarBufs + i : i - pNtk->nBarBufs)), 1); i++ )
+// fanin and fanouts
+#define Abc_ObjForEachFanin( pObj, pFanin, i )                                                     \
+    for ( i = 0; (i < Abc_ObjFaninNum(pObj)) && (((pFanin) = Abc_ObjFanin(pObj, i)), 1); i++ )
+#define Abc_ObjForEachFanout( pObj, pFanout, i )                                                   \
+    for ( i = 0; (i < Abc_ObjFanoutNum(pObj)) && (((pFanout) = Abc_ObjFanout(pObj, i)), 1); i++ )
+// cubes and literals
+#define Abc_CubeForEachVar( pCube, Value, i )                                                      \
+    for ( i = 0; (pCube[i] != ' ') && (Value = pCube[i]); i++ )           
+#define Abc_SopForEachCube( pSop, nFanins, pCube )                                                 \
+    for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 )
+#define Abc_SopForEachCubePair( pSop, nFanins, pCube, pCube2 )                                     \
+    Abc_SopForEachCube( pSop, nFanins, pCube )                                                     \
+    Abc_SopForEachCube( pCube + (nFanins) + 3, nFanins, pCube2 )
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== abcAig.c ==========================================================*/
+extern ABC_DLL Abc_Aig_t *        Abc_AigAlloc( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_AigFree( Abc_Aig_t * pMan );
+extern ABC_DLL int                Abc_AigCleanup( Abc_Aig_t * pMan );
+extern ABC_DLL int                Abc_AigCheck( Abc_Aig_t * pMan );
+extern ABC_DLL int                Abc_AigLevel( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Obj_t *        Abc_AigConst1( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Obj_t *        Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
+extern ABC_DLL Abc_Obj_t *        Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
+extern ABC_DLL Abc_Obj_t *        Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType );
+extern ABC_DLL Abc_Obj_t *        Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, Abc_Obj_t * pE, int * pType );
+extern ABC_DLL Abc_Obj_t *        Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
+extern ABC_DLL Abc_Obj_t *        Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
+extern ABC_DLL Abc_Obj_t *        Abc_AigMux( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * p1, Abc_Obj_t * p0 );
+extern ABC_DLL Abc_Obj_t *        Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs, int fImplic );
+extern ABC_DLL void               Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int  fUpdateLevel );
+extern ABC_DLL void               Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pOld );
+extern ABC_DLL void               Abc_AigRehash( Abc_Aig_t * pMan );
+extern ABC_DLL int                Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode );
+extern ABC_DLL int                Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode );
+extern ABC_DLL void               Abc_AigPrintNode( Abc_Obj_t * pNode );
+extern ABC_DLL int                Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot );
+extern ABC_DLL void               Abc_AigCheckFaninOrder( Abc_Aig_t * pMan );
+extern ABC_DLL void               Abc_AigSetNodePhases( Abc_Ntk_t * pNtk );
+extern ABC_DLL Vec_Ptr_t *        Abc_AigUpdateStart( Abc_Aig_t * pMan, Vec_Ptr_t ** pvUpdatedNets );
+extern ABC_DLL void               Abc_AigUpdateStop( Abc_Aig_t * pMan );
+extern ABC_DLL void               Abc_AigUpdateReset( Abc_Aig_t * pMan );
+/*=== abcAttach.c ==========================================================*/
+extern ABC_DLL int                Abc_NtkAttach( Abc_Ntk_t * pNtk );
+/*=== abcBarBuf.c ==========================================================*/
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkToBarBufs( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkFromBarBufs( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkBarBufsToBuffers( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkBarBufsFromBuffers( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtk );
+/*=== abcBlifMv.c ==========================================================*/
+extern ABC_DLL void               Abc_NtkStartMvVars( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic );
+extern ABC_DLL int                Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk );
+extern ABC_DLL char *             Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 );
+extern ABC_DLL int                Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 );
+/*=== abcBalance.c ==========================================================*/
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkBalance( Abc_Ntk_t * pNtk, int  fDuplicate, int  fSelective, int  fUpdateLevel );
+/*=== abcCheck.c ==========================================================*/
+extern ABC_DLL int                Abc_NtkCheck( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkCheckRead( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkDoCheck( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj );
+extern ABC_DLL int                Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb );
+extern ABC_DLL int                Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk );
+/*=== abcCollapse.c ==========================================================*/
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose );
+/*=== abcCut.c ==========================================================*/
+extern ABC_DLL void *             Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree );
+extern ABC_DLL void *             Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree );
+extern ABC_DLL void               Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fFirst );
+extern ABC_DLL void *             Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj );
+extern ABC_DLL void               Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj );
+/*=== abcDar.c ============================================================*/
+extern ABC_DLL int                Abc_NtkPhaseFrameNum( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkDarPrintCone( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkBalanceExor( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchConst, int fLatchEqual, int fSaveNames, int fUseMvSweep, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose );
+/*=== abcDelay.c ==========================================================*/
+extern ABC_DLL float              Abc_NtkDelayTraceLut( Abc_Ntk_t * pNtk, int fUseLutLib );
+/*=== abcDfs.c ==========================================================*/
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkDfs( Abc_Ntk_t * pNtk, int fCollectAll );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkDfsReverse( Abc_Ntk_t * pNtk );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkDfsReverseNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkDfsReverseNodesContained( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkDfsSeq( Abc_Ntk_t * pNtk );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkDfsSeqReverse( Abc_Ntk_t * pNtk );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkDfsIterNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkDfsHie( Abc_Ntk_t * pNtk, int fCollectAll );
+extern ABC_DLL int                Abc_NtkIsDfsOrdered( Abc_Ntk_t * pNtk );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkSupport( Abc_Ntk_t * pNtk );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes );
+extern ABC_DLL Vec_Ptr_t *        Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll, int fCollectCos );
+extern ABC_DLL Vec_Ptr_t *        Abc_AigDfsMap( Abc_Ntk_t * pNtk );
+extern ABC_DLL Vec_Vec_t *        Abc_DfsLevelized( Abc_Obj_t * pNode, int  fTfi );
+extern ABC_DLL Vec_Vec_t *        Abc_NtkLevelize( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkLevel( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkLevelReverse( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk );
+extern ABC_DLL Vec_Ptr_t *        Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis );
+/*=== abcFanio.c ==========================================================*/
+extern ABC_DLL void               Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin );
+extern ABC_DLL void               Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin );
+extern ABC_DLL void               Abc_ObjRemoveFanins( Abc_Obj_t * pObj );
+extern ABC_DLL void               Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFaninNew );
+extern ABC_DLL Abc_Obj_t *        Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc_ObjType_t Type );
+extern ABC_DLL void               Abc_ObjTransferFanout( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew );
+extern ABC_DLL void               Abc_ObjReplace( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew );
+extern ABC_DLL int                Abc_ObjFanoutFaninNum( Abc_Obj_t * pFanout, Abc_Obj_t * pFanin );
+/*=== abcFanOrder.c ==========================================================*/
+extern ABC_DLL int                Abc_NtkMakeLegit( Abc_Ntk_t * pNtk );
+/*=== abcFraig.c ==========================================================*/
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc );
+extern ABC_DLL void *             Abc_NtkToFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkFraigTrust( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkFraigStore( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkFraigRestore();
+extern ABC_DLL void               Abc_NtkFraigStoreClean();
+/*=== abcFunc.c ==========================================================*/
+extern ABC_DLL int                Abc_NtkSopToBdd( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fDirect );
+extern ABC_DLL void               Abc_NodeBddToCnf( Abc_Obj_t * pNode, Mem_Flex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 );
+extern ABC_DLL void               Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkSopToAig( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkAigToBdd( Abc_Ntk_t * pNtk );
+extern ABC_DLL Gia_Man_t *        Abc_NtkAigToGia( Abc_Ntk_t * p );
+extern ABC_DLL int                Abc_NtkMapToSop( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkToSop( Abc_Ntk_t * pNtk, int fDirect );
+extern ABC_DLL int                Abc_NtkToBdd( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkToAig( Abc_Ntk_t * pNtk );
+/*=== abcHaig.c ==========================================================*/
+extern ABC_DLL int                Abc_NtkHaigStart( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkHaigStop( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkHaigUse( Abc_Ntk_t * pNtk );
+/*=== abcHie.c ==========================================================*/
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkConvertBlackboxes( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL );
+extern ABC_DLL void               Abc_NtkPrintBoxInfo( Abc_Ntk_t * pNtk );
+/*=== abcLatch.c ==========================================================*/
+extern ABC_DLL int                Abc_NtkLatchIsSelfFeed( Abc_Obj_t * pLatch );
+extern ABC_DLL int                Abc_NtkCountSelfFeedLatches( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk );
+extern ABC_DLL Vec_Int_t *        Abc_NtkCollectLatchValues( Abc_Ntk_t * pNtk );
+extern ABC_DLL char *             Abc_NtkCollectLatchValuesStr( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkAddLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pDriver, Abc_InitType_t Init );
+extern ABC_DLL void               Abc_NtkConvertDcLatches( Abc_Ntk_t * pNtk );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkConverLatchNamesIntoNumbers( Abc_Ntk_t * pNtk );
+ /*=== abcLib.c ==========================================================*/
+extern ABC_DLL Abc_Des_t *        Abc_DesCreate( char * pName );
+extern ABC_DLL void               Abc_DesCleanManPointer( Abc_Des_t * p, void * pMan );
+extern ABC_DLL void               Abc_DesFree( Abc_Des_t * p, Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Des_t *        Abc_DesDup( Abc_Des_t * p );
+extern ABC_DLL void               Abc_DesPrint( Abc_Des_t * p );
+extern ABC_DLL int                Abc_DesAddModel( Abc_Des_t * p, Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Ntk_t *        Abc_DesFindModelByName( Abc_Des_t * p, char * pName );
+extern ABC_DLL int                Abc_DesFindTopLevelModels( Abc_Des_t * p );
+extern ABC_DLL Abc_Ntk_t *        Abc_DesDeriveRoot( Abc_Des_t * p );
+/*=== abcLog.c ==========================================================*/
+extern ABC_DLL void               Abc_NtkWriteLogFile( char * pFileName, Abc_Cex_t * pSeqCex, int Status, int nFrames, char * pCommand );
+/*=== abcMap.c ==========================================================*/
+extern ABC_DLL Abc_Obj_t *        Abc_NtkFetchTwinNode( Abc_Obj_t * pNode );
+/*=== abcMiter.c ==========================================================*/
+extern ABC_DLL int                Abc_NtkMinimumBase( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NodeMinimumBase( Abc_Obj_t * pNode );
+extern ABC_DLL int                Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode );
+/*=== abcMiter.c ==========================================================*/
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize, int fImplic, int fMulti );
+extern ABC_DLL void               Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pNode );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkMiterAnd( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOr, int fCompl2 );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkMiterQuantifyPis( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter );
+extern ABC_DLL void               Abc_NtkMiterReport( Abc_Ntk_t * pMiter );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial, int fVerbose );
+extern ABC_DLL int                Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd, int fXor );
+/*=== abcNames.c ====================================================*/
+extern ABC_DLL char *             Abc_ObjName( Abc_Obj_t * pNode );
+extern ABC_DLL char *             Abc_ObjAssignName( Abc_Obj_t * pObj, char * pName, char * pSuffix );
+extern ABC_DLL char *             Abc_ObjNamePrefix( Abc_Obj_t * pObj, char * pPrefix );
+extern ABC_DLL char *             Abc_ObjNameSuffix( Abc_Obj_t * pObj, char * pSuffix );
+extern ABC_DLL char *             Abc_ObjNameDummy( char * pPrefix, int Num, int nDigits );
+extern ABC_DLL void               Abc_NtkTrasferNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
+extern ABC_DLL void               Abc_NtkTrasferNamesNoLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
+extern ABC_DLL Vec_Ptr_t *        Abc_NodeGetFaninNames( Abc_Obj_t * pNode );
+extern ABC_DLL Vec_Ptr_t *        Abc_NodeGetFakeNames( int nNames );
+extern ABC_DLL void               Abc_NodeFreeNames( Vec_Ptr_t * vNames );
+extern ABC_DLL char **            Abc_NtkCollectCioNames( Abc_Ntk_t * pNtk, int fCollectCos );
+extern ABC_DLL int                Abc_NodeCompareNames( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 );
+extern ABC_DLL void               Abc_NtkOrderObjsByName( Abc_Ntk_t * pNtk, int fComb );
+extern ABC_DLL void               Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkShortNames( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkStartNameIds( Abc_Ntk_t * p );
+extern ABC_DLL void               Abc_NtkTransferNameIds( Abc_Ntk_t * p, Abc_Ntk_t * pNew );
+extern ABC_DLL void               Abc_NtkUpdateNameIds( Abc_Ntk_t * p );
+/*=== abcNetlist.c ==========================================================*/
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkToLogic( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkToNetlist( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk );
+/*=== abcNtbdd.c ==========================================================*/
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkDeriveFromBdd( void * dd, void * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk );
+extern ABC_DLL void *             Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDropInternal, int fReorder, int fVerbose );
+extern ABC_DLL void *             Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan );
+extern ABC_DLL int                Abc_NtkSizeOfGlobalBdds( Abc_Ntk_t * pNtk );
+/*=== abcNtk.c ==========================================================*/
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func );
+extern ABC_DLL void               Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkStartRead( char * pName );
+extern ABC_DLL void               Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkDup( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkDupDfs( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkDupTransformMiter( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fUseAllCis );
+extern ABC_DLL void               Abc_NtkAppendToCone( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkCreateWithNode( char * pSop );
+extern ABC_DLL void               Abc_NtkDelete( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkMakeComb( Abc_Ntk_t * pNtk, int fRemoveLatches );
+extern ABC_DLL void               Abc_NtkPermute( Abc_Ntk_t * pNtk, int fInputs, int fOutputs, int fFlops, char * pFlopPermFile );
+extern ABC_DLL void               Abc_NtkUnpermute( Abc_Ntk_t * pNtk );
+/*=== abcObj.c ==========================================================*/
+extern ABC_DLL Abc_Obj_t *        Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type );
+extern ABC_DLL void               Abc_ObjRecycle( Abc_Obj_t * pObj );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type );
+extern ABC_DLL void               Abc_NtkDeleteObj( Abc_Obj_t * pObj );
+extern ABC_DLL void               Abc_NtkDeleteObjPo( Abc_Obj_t * pObj );
+extern ABC_DLL void               Abc_NtkDeleteObj_rec( Abc_Obj_t * pObj, int fOnlyNodes );
+extern ABC_DLL void               Abc_NtkDeleteAll_rec( Abc_Obj_t * pObj );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkDupBox( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pBox, int fCopyName );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkCloneObj( Abc_Obj_t * pNode );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkFindNet( Abc_Ntk_t * pNtk, char * pName );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkFindCi( Abc_Ntk_t * pNtk, char * pName );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins );
+extern ABC_DLL Abc_Obj_t *        Abc_NtkCreateNodeMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 );
+extern ABC_DLL int                Abc_NodeIsConst( Abc_Obj_t * pNode );
+extern ABC_DLL int                Abc_NodeIsConst0( Abc_Obj_t * pNode );    
+extern ABC_DLL int                Abc_NodeIsConst1( Abc_Obj_t * pNode );    
+extern ABC_DLL int                Abc_NodeIsBuf( Abc_Obj_t * pNode );    
+extern ABC_DLL int                Abc_NodeIsInv( Abc_Obj_t * pNode );    
+extern ABC_DLL void               Abc_NodeComplement( Abc_Obj_t * pNode );
+extern ABC_DLL void               Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin );
+/*=== abcOdc.c ==========================================================*/
+typedef struct Odc_Man_t_         Odc_Man_t;
+extern ABC_DLL Odc_Man_t *        Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose );
+extern ABC_DLL void               Abc_NtkDontCareClear( Odc_Man_t * p );
+extern ABC_DLL void               Abc_NtkDontCareFree( Odc_Man_t * p );
+extern ABC_DLL int                Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth );
+/*=== abcPrint.c ==========================================================*/
+extern ABC_DLL float              Abc_NtkMfsTotalSwitching( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower, int fGlitch, int fSkipBuf );
+extern ABC_DLL void               Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintFlops );
+extern ABC_DLL void               Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk, int fUsePis );
+extern ABC_DLL void               Abc_NtkPrintFanioNew( FILE * pFile, Abc_Ntk_t * pNtk, int fMffc );
+extern ABC_DLL void               Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode );
+extern ABC_DLL void               Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames );
+extern ABC_DLL void               Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames );
+extern ABC_DLL void               Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes, int fVerbose );
+extern ABC_DLL void               Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode );
+extern ABC_DLL void               Abc_NtkPrintSkews( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintAll );
+extern ABC_DLL void               Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj );
+extern ABC_DLL void               Abc_NtkShow6VarFunc( char * pF0, char * pF1 );
+/*=== abcProve.c ==========================================================*/
+extern ABC_DLL int                Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pParams );
+extern ABC_DLL int                Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars );
+/*=== abcRec3.c ==========================================================*/
+extern ABC_DLL void               Abc_NtkRecStart3( Gia_Man_t * p, int nVars, int nCuts, int fFuncOnly, int fVerbose );
+extern ABC_DLL void               Abc_NtkRecStop3();
+extern ABC_DLL void               Abc_NtkRecAdd3( Abc_Ntk_t * pNtk, int fUseSOPB );
+extern ABC_DLL void               Abc_NtkRecPs3(int fPrintLib);
+extern ABC_DLL Gia_Man_t *        Abc_NtkRecGetGia3();
+extern ABC_DLL int                Abc_NtkRecIsRunning3();
+extern ABC_DLL void               Abc_NtkRecLibMerge3(Gia_Man_t * pGia);
+extern ABC_DLL int                Abc_NtkRecInputNum3();
+//extern ABC_DLL void               Abc_NtkRecFilter3(int nLimit);
+/*=== abcReconv.c ==========================================================*/
+extern ABC_DLL Abc_ManCut_t *     Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop );
+extern ABC_DLL void               Abc_NtkManCutStop( Abc_ManCut_t * p );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkManCutReadCutSmall( Abc_ManCut_t * p );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkManCutReadVisited( Abc_ManCut_t * p );
+extern ABC_DLL Vec_Ptr_t *        Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, int  fContain );
+extern ABC_DLL void               Abc_NodeConeCollect( Abc_Obj_t ** ppRoots, int nRoots, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited, int fIncludeFanins );
+extern ABC_DLL Vec_Ptr_t *        Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins, int LevelMax );
+/*=== abcRefs.c ==========================================================*/
+extern ABC_DLL int                Abc_NodeMffcSize( Abc_Obj_t * pNode );
+extern ABC_DLL int                Abc_NodeMffcSizeSupp( Abc_Obj_t * pNode );
+extern ABC_DLL int                Abc_NodeMffcSizeStop( Abc_Obj_t * pNode );
+extern ABC_DLL int                Abc_NodeMffcLabelAig( Abc_Obj_t * pNode );
+extern ABC_DLL int                Abc_NodeMffcLabel( Abc_Obj_t * pNode );
+extern ABC_DLL void               Abc_NodeMffcConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp );
+extern ABC_DLL int                Abc_NodeDeref_rec( Abc_Obj_t * pNode );
+extern ABC_DLL int                Abc_NodeRef_rec( Abc_Obj_t * pNode );
+/*=== abcRefactor.c ==========================================================*/
+extern ABC_DLL int                Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, int  fUpdateLevel, int  fUseZeros, int  fUseDcs, int  fVerbose );
+/*=== abcRewrite.c ==========================================================*/
+extern ABC_DLL int                Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable );
+/*=== abcSat.c ==========================================================*/
+extern ABC_DLL int                Abc_NtkMiterSat( Abc_Ntk_t * pNtk, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fVerbose, ABC_INT64_T * pNumConfs, ABC_INT64_T * pNumInspects );
+extern ABC_DLL void *             Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fAllPrimes );
+/*=== abcSop.c ==========================================================*/
+extern ABC_DLL char *             Abc_SopRegister( Mem_Flex_t * pMan, char * pName );
+extern ABC_DLL char *             Abc_SopStart( Mem_Flex_t * pMan, int nCubes, int nVars );
+extern ABC_DLL char *             Abc_SopCreateConst0( Mem_Flex_t * pMan );
+extern ABC_DLL char *             Abc_SopCreateConst1( Mem_Flex_t * pMan );
+extern ABC_DLL char *             Abc_SopCreateAnd2( Mem_Flex_t * pMan, int fCompl0, int fCompl1 );
+extern ABC_DLL char *             Abc_SopCreateAnd( Mem_Flex_t * pMan, int nVars, int * pfCompl );
+extern ABC_DLL char *             Abc_SopCreateNand( Mem_Flex_t * pMan, int nVars );
+extern ABC_DLL char *             Abc_SopCreateOr( Mem_Flex_t * pMan, int nVars, int * pfCompl );
+extern ABC_DLL char *             Abc_SopCreateOrMultiCube( Mem_Flex_t * pMan, int nVars, int * pfCompl );
+extern ABC_DLL char *             Abc_SopCreateNor( Mem_Flex_t * pMan, int nVars );
+extern ABC_DLL char *             Abc_SopCreateXor( Mem_Flex_t * pMan, int nVars );
+extern ABC_DLL char *             Abc_SopCreateXorSpecial( Mem_Flex_t * pMan, int nVars );
+extern ABC_DLL char *             Abc_SopCreateNxor( Mem_Flex_t * pMan, int nVars );
+extern ABC_DLL char *             Abc_SopCreateMux( Mem_Flex_t * pMan );
+extern ABC_DLL char *             Abc_SopCreateInv( Mem_Flex_t * pMan );
+extern ABC_DLL char *             Abc_SopCreateBuf( Mem_Flex_t * pMan );
+extern ABC_DLL char *             Abc_SopCreateFromTruth( Mem_Flex_t * pMan, int nVars, unsigned * pTruth );
+extern ABC_DLL char *             Abc_SopCreateFromIsop( Mem_Flex_t * pMan, int nVars, Vec_Int_t * vCover );
+extern ABC_DLL int                Abc_SopGetCubeNum( char * pSop );
+extern ABC_DLL int                Abc_SopGetLitNum( char * pSop );
+extern ABC_DLL int                Abc_SopGetVarNum( char * pSop );
+extern ABC_DLL int                Abc_SopGetPhase( char * pSop );
+extern ABC_DLL int                Abc_SopGetIthCareLit( char * pSop, int i );
+extern ABC_DLL void               Abc_SopComplement( char * pSop );
+extern ABC_DLL void               Abc_SopComplementVar( char * pSop, int iVar );
+extern ABC_DLL int                Abc_SopIsComplement( char * pSop );
+extern ABC_DLL int                Abc_SopIsConst0( char * pSop );
+extern ABC_DLL int                Abc_SopIsConst1( char * pSop );
+extern ABC_DLL int                Abc_SopIsBuf( char * pSop );
+extern ABC_DLL int                Abc_SopIsInv( char * pSop );
+extern ABC_DLL int                Abc_SopIsAndType( char * pSop );
+extern ABC_DLL int                Abc_SopIsOrType( char * pSop );
+extern ABC_DLL int                Abc_SopIsExorType( char * pSop );
+extern ABC_DLL int                Abc_SopCheck( char * pSop, int nFanins );
+extern ABC_DLL char *             Abc_SopFromTruthBin( char * pTruth );
+extern ABC_DLL char *             Abc_SopFromTruthHex( char * pTruth );
+extern ABC_DLL char *             Abc_SopEncoderPos( Mem_Flex_t * pMan, int iValue, int nValues );
+extern ABC_DLL char *             Abc_SopEncoderLog( Mem_Flex_t * pMan, int iBit, int nValues );
+extern ABC_DLL char *             Abc_SopDecoderPos( Mem_Flex_t * pMan, int nValues );
+extern ABC_DLL char *             Abc_SopDecoderLog( Mem_Flex_t * pMan, int nValues );
+extern ABC_DLL word               Abc_SopToTruth( char * pSop, int nInputs );
+extern ABC_DLL void               Abc_SopToTruth7( char * pSop, int nInputs, word r[2] );
+extern ABC_DLL void               Abc_SopToTruthBig( char * pSop, int nInputs, word ** pVars, word * pCube, word * pRes );
+/*=== abcStrash.c ==========================================================*/
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkRestrash( Abc_Ntk_t * pNtk, int fCleanup );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkRestrashZero( Abc_Ntk_t * pNtk, int fCleanup );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkStrash( Abc_Ntk_t * pNtk, int fAllNodes, int fCleanup, int fRecord );
+extern ABC_DLL Abc_Obj_t *        Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int fRecord );
+extern ABC_DLL int                Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos );
+extern ABC_DLL Abc_Ntk_t *        Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels );
+/*=== abcSweep.c ==========================================================*/
+extern ABC_DLL int                Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose );
+extern ABC_DLL int                Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose );
+extern ABC_DLL int                Abc_NtkCleanupNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, int fVerbose );
+extern ABC_DLL int                Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fLatchSweep, int fAutoSweep, int fVerbose );
+extern ABC_DLL int                Abc_NtkSweepBufsInvs( Abc_Ntk_t * pNtk, int fVerbose );
+/*=== abcTiming.c ==========================================================*/
+extern ABC_DLL Abc_Time_t *       Abc_NtkReadDefaultArrival( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Time_t *       Abc_NtkReadDefaultRequired( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Time_t *       Abc_NodeReadArrival( Abc_Obj_t * pNode );
+extern ABC_DLL Abc_Time_t *       Abc_NodeReadRequired( Abc_Obj_t * pNode );
+extern ABC_DLL float              Abc_NodeReadArrivalAve( Abc_Obj_t * pNode );
+extern ABC_DLL float              Abc_NodeReadRequiredAve( Abc_Obj_t * pNode );
+extern ABC_DLL float              Abc_NodeReadArrivalWorst( Abc_Obj_t * pNode );
+extern ABC_DLL float              Abc_NodeReadRequiredWorst( Abc_Obj_t * pNode );
+extern ABC_DLL Abc_Time_t *       Abc_NtkReadDefaultInputDrive( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Time_t *       Abc_NtkReadDefaultOutputLoad( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Time_t *       Abc_NodeReadInputDrive( Abc_Ntk_t * pNtk, int iPi );
+extern ABC_DLL Abc_Time_t *       Abc_NodeReadOutputLoad( Abc_Ntk_t * pNtk, int iPo );
+extern ABC_DLL float              Abc_NodeReadInputDriveWorst( Abc_Ntk_t * pNtk, int iPi );
+extern ABC_DLL float              Abc_NodeReadOutputLoadWorst( Abc_Ntk_t * pNtk, int iPo );
+extern ABC_DLL void               Abc_NtkTimeSetDefaultArrival( Abc_Ntk_t * pNtk, float Rise, float Fall );
+extern ABC_DLL void               Abc_NtkTimeSetDefaultRequired( Abc_Ntk_t * pNtk, float Rise, float Fall );
+extern ABC_DLL void               Abc_NtkTimeSetArrival( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall );
+extern ABC_DLL void               Abc_NtkTimeSetRequired( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall );
+extern ABC_DLL void               Abc_NtkTimeSetDefaultInputDrive( Abc_Ntk_t * pNtk, float Rise, float Fall );
+extern ABC_DLL void               Abc_NtkTimeSetDefaultOutputLoad( Abc_Ntk_t * pNtk, float Rise, float Fall );
+extern ABC_DLL void               Abc_NtkTimeSetInputDrive( Abc_Ntk_t * pNtk, int PiNum, float Rise, float Fall );
+extern ABC_DLL void               Abc_NtkTimeSetOutputLoad( Abc_Ntk_t * pNtk, int PoNum, float Rise, float Fall );
+extern ABC_DLL void               Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkOld );
+extern ABC_DLL void               Abc_ManTimeStop( Abc_ManTime_t * p );
+extern ABC_DLL void               Abc_ManTimeDup( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew );
+extern ABC_DLL void               Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtk );
+extern ABC_DLL float *            Abc_NtkGetCiArrivalFloats( Abc_Ntk_t * pNtk );
+extern ABC_DLL float *            Abc_NtkGetCoRequiredFloats( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Time_t *       Abc_NtkGetCiArrivalTimes( Abc_Ntk_t * pNtk );
+extern ABC_DLL Abc_Time_t *       Abc_NtkGetCoRequiredTimes( Abc_Ntk_t * pNtk );
+extern ABC_DLL float              Abc_NtkDelayTrace( Abc_Ntk_t * pNtk, Abc_Obj_t * pOut, Abc_Obj_t * pIn, int fPrint );
+extern ABC_DLL int                Abc_ObjLevelNew( Abc_Obj_t * pObj );
+extern ABC_DLL int                Abc_ObjReverseLevelNew( Abc_Obj_t * pObj );
+extern ABC_DLL int                Abc_ObjRequiredLevel( Abc_Obj_t * pObj );
+extern ABC_DLL int                Abc_ObjReverseLevel( Abc_Obj_t * pObj );
+extern ABC_DLL void               Abc_ObjSetReverseLevel( Abc_Obj_t * pObj, int LevelR );
+extern ABC_DLL void               Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease );
+extern ABC_DLL void               Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels );
+extern ABC_DLL void               Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels );
+extern ABC_DLL void               Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels );
+/*=== abcUtil.c ==========================================================*/
+extern ABC_DLL void *             Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan );
+extern ABC_DLL void               Abc_NtkOrderCisCos( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkGetCubePairNum( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkGetLitNum( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkGetLitFactNum( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkGetBddNodeNum( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkGetAigNodeNum( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkGetClauseNum( Abc_Ntk_t * pNtk );
+extern ABC_DLL double             Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkGetExorNum( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkGetBufNum( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkGetFanoutMax( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkGetTotalFanins( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkCleanCopy( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkCleanCopy_rec( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkCleanData( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkFillTemp( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkCountCopy( Abc_Ntk_t * pNtk );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkSaveCopy( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkLoadCopy( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCopies );
+extern ABC_DLL void               Abc_NtkCleanNext( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkCleanNext_rec( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkCleanMarkA( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkCleanMarkB( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkCleanMarkC( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkCleanMarkAB( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkCleanMarkABC( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NodeFindFanin( Abc_Obj_t * pNode, Abc_Obj_t * pFanin );
+extern ABC_DLL Abc_Obj_t *        Abc_NodeFindCoFanout( Abc_Obj_t * pNode );
+extern ABC_DLL Abc_Obj_t *        Abc_NodeFindNonCoFanout( Abc_Obj_t * pNode );
+extern ABC_DLL Abc_Obj_t *        Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode );
+extern ABC_DLL int                Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, int  fDuplicate );
+extern ABC_DLL void               Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode );
+extern ABC_DLL int                Abc_NodeIsExorType( Abc_Obj_t * pNode );
+extern ABC_DLL int                Abc_NodeIsMuxType( Abc_Obj_t * pNode );
+extern ABC_DLL int                Abc_NodeIsMuxControlType( Abc_Obj_t * pNode );
+extern ABC_DLL Abc_Obj_t *        Abc_NodeRecognizeMux( Abc_Obj_t * pNode, Abc_Obj_t ** ppNodeT, Abc_Obj_t ** ppNodeE );
+extern ABC_DLL int                Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc, Abc_Ntk_t ** ppNtk1, Abc_Ntk_t ** ppNtk2, int * pfDelete1, int * pfDelete2 );
+extern ABC_DLL void               Abc_NodeCollectFanins( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes );
+extern ABC_DLL void               Abc_NodeCollectFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkCollectLatches( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NodeCompareLevelsIncrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 );
+extern ABC_DLL int                Abc_NodeCompareLevelsDecrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 );
+extern ABC_DLL Vec_Int_t *        Abc_NtkFanoutCounts( Abc_Ntk_t * pNtk );
+extern ABC_DLL Vec_Ptr_t *        Abc_NtkCollectObjects( Abc_Ntk_t * pNtk );
+extern ABC_DLL Vec_Int_t *        Abc_NtkGetCiIds( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkReassignIds( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_ObjPointerCompare( void ** pp1, void ** pp2 );
+extern ABC_DLL void               Abc_NtkTransferCopy( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkInvertConstraints( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkPrintCiLevels( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkReverseTopoOrder( Abc_Ntk_t * pNtk );
+extern ABC_DLL int                Abc_NtkIsTopo( Abc_Ntk_t * pNtk );
+extern ABC_DLL void               Abc_NtkTransferPhases( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk );
+
+
+/*=== abcVerify.c ==========================================================*/
+extern ABC_DLL int *              Abc_NtkVerifyGetCleanModel( Abc_Ntk_t * pNtk, int nFrames );
+extern ABC_DLL int *              Abc_NtkVerifySimulatePattern( Abc_Ntk_t * pNtk, int * pModel );
+extern ABC_DLL int                Abc_NtkIsTrueCex( Abc_Ntk_t * pNtk, Abc_Cex_t * pCex );
+extern ABC_DLL int                Abc_NtkIsValidCex( Abc_Ntk_t * pNtk, Abc_Cex_t * pCex );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/base/abc/abcAig.c b/abc-build/src/base/abc/abcAig.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcAig.c
@@ -0,0 +1,1505 @@
+/**CFile****************************************************************
+
+  FileName    [abcAig.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Simple structural hashing package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/*
+    AIG is an And-Inv Graph with structural hashing.
+    It is always structurally hashed. It means that at any time:
+    - for each AND gate, there are no other AND gates with the same children
+    - the constants are propagated
+    - there is no single-input nodes (inverters/buffers)
+    Additionally the following invariants are satisfied:
+    - there are no dangling nodes (the nodes without fanout)
+    - the level of each AND gate reflects the levels of this fanins
+    - the EXOR-status of each node is up-to-date
+    - the AND nodes are in the topological order
+    - the constant 1 node has always number 0 in the object list
+    The operations that are performed on AIGs:
+    - building new nodes (Abc_AigAnd)
+    - performing elementary Boolean operations (Abc_AigOr, Abc_AigXor, etc)
+    - replacing one node by another (Abc_AigReplace)
+    - propagating constants (Abc_AigReplace)
+    When AIG is duplicated, the new graph is structurally hashed too.
+    If this repeated hashing leads to fewer nodes, it means the original
+    AIG was not strictly hashed (one of the conditions above is violated).
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// the simple AIG manager
+struct Abc_Aig_t_
+{
+    Abc_Ntk_t *       pNtkAig;           // the AIG network
+    Abc_Obj_t *       pConst1;           // the constant 1 object (not a node!)
+    Abc_Obj_t **      pBins;             // the table bins
+    int               nBins;             // the size of the table
+    int               nEntries;          // the total number of entries in the table
+    Vec_Ptr_t *       vNodes;            // the temporary array of nodes
+    Vec_Ptr_t *       vStackReplaceOld;  // the nodes to be replaced
+    Vec_Ptr_t *       vStackReplaceNew;  // the nodes to be used for replacement
+    Vec_Vec_t *       vLevels;           // the nodes to be updated
+    Vec_Vec_t *       vLevelsR;          // the nodes to be updated
+    Vec_Ptr_t *       vAddedCells;       // the added nodes
+    Vec_Ptr_t *       vUpdatedNets;      // the nodes whose fanouts have changed
+
+    int               nStrash0;
+    int               nStrash1;
+    int               nStrash5;
+    int               nStrash2;
+};
+
+// iterators through the entries in the linked lists of nodes
+#define Abc_AigBinForEachEntry( pBin, pEnt )                   \
+    for ( pEnt = pBin;                                         \
+          pEnt;                                                \
+          pEnt = pEnt->pNext )
+#define Abc_AigBinForEachEntrySafe( pBin, pEnt, pEnt2 )        \
+    for ( pEnt = pBin,                                         \
+          pEnt2 = pEnt? pEnt->pNext: NULL;                     \
+          pEnt;                                                \
+          pEnt = pEnt2,                                        \
+          pEnt2 = pEnt? pEnt->pNext: NULL )
+
+// hash key for the structural hash table
+//static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; }
+//static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)((a)->Id + (b)->Id) * ((a)->Id + (b)->Id + 1) / 2) % TableSize; }
+
+// hashing the node
+static unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) 
+{
+    unsigned Key = 0;
+    Key ^= Abc_ObjRegular(p0)->Id * 7937;
+    Key ^= Abc_ObjRegular(p1)->Id * 2971;
+    Key ^= Abc_ObjIsComplement(p0) * 911;
+    Key ^= Abc_ObjIsComplement(p1) * 353;
+    return Key % TableSize;
+}
+
+// structural hash table procedures
+static Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
+static Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, Abc_Obj_t * pAnd );
+static void        Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis );
+static void        Abc_AigResize( Abc_Aig_t * pMan );
+// incremental AIG procedures
+static void        Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel );
+static void        Abc_AigUpdateLevel_int( Abc_Aig_t * pMan );
+static void        Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan );
+static void        Abc_AigRemoveFromLevelStructure( Vec_Vec_t * vStruct, Abc_Obj_t * pNode );
+static void        Abc_AigRemoveFromLevelStructureR( Vec_Vec_t * vStruct, Abc_Obj_t * pNode );
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the local AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig )
+{
+    Abc_Aig_t * pMan;
+    // start the manager
+    pMan = ABC_ALLOC( Abc_Aig_t, 1 );
+    memset( pMan, 0, sizeof(Abc_Aig_t) );
+    // allocate the table
+    pMan->nBins    = Abc_PrimeCudd( 10000 );
+    pMan->pBins    = ABC_ALLOC( Abc_Obj_t *, pMan->nBins );
+    memset( pMan->pBins, 0, sizeof(Abc_Obj_t *) * pMan->nBins );
+    pMan->vNodes   = Vec_PtrAlloc( 100 );
+    pMan->vLevels  = Vec_VecAlloc( 100 );
+    pMan->vLevelsR = Vec_VecAlloc( 100 );
+    pMan->vStackReplaceOld = Vec_PtrAlloc( 100 );
+    pMan->vStackReplaceNew = Vec_PtrAlloc( 100 );
+    // create the constant node
+    assert( pNtkAig->vObjs->nSize == 0 );
+    pMan->pConst1 = Abc_NtkCreateObj( pNtkAig, ABC_OBJ_NODE );
+    pMan->pConst1->Type = ABC_OBJ_CONST1;
+    pMan->pConst1->fPhase = 1;
+    pNtkAig->nObjCounts[ABC_OBJ_NODE]--;
+    // save the current network
+    pMan->pNtkAig = pNtkAig;
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the local AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AigFree( Abc_Aig_t * pMan )
+{
+    assert( Vec_PtrSize( pMan->vStackReplaceOld ) == 0 );
+    assert( Vec_PtrSize( pMan->vStackReplaceNew ) == 0 );
+    // free the table
+    if ( pMan->vAddedCells )
+        Vec_PtrFree( pMan->vAddedCells );
+    if ( pMan->vUpdatedNets )
+        Vec_PtrFree( pMan->vUpdatedNets );
+    Vec_VecFree( pMan->vLevels );
+    Vec_VecFree( pMan->vLevelsR );
+    Vec_PtrFree( pMan->vStackReplaceOld );
+    Vec_PtrFree( pMan->vStackReplaceNew );
+    Vec_PtrFree( pMan->vNodes );
+    ABC_FREE( pMan->pBins );
+    ABC_FREE( pMan );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of dangling nodes removed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_AigCleanup( Abc_Aig_t * pMan )
+{
+    Vec_Ptr_t * vDangles;
+    Abc_Obj_t * pAnd;
+    int i, nNodesOld;
+//    printf( "Strash0 = %d.  Strash1 = %d.  Strash100 = %d.  StrashM = %d.\n", 
+//        pMan->nStrash0, pMan->nStrash1, pMan->nStrash5, pMan->nStrash2 );
+    nNodesOld = pMan->nEntries;
+    // collect the AND nodes that do not fanout
+    vDangles = Vec_PtrAlloc( 100 );
+    for ( i = 0; i < pMan->nBins; i++ )
+        Abc_AigBinForEachEntry( pMan->pBins[i], pAnd )
+            if ( Abc_ObjFanoutNum(pAnd) == 0 )
+                Vec_PtrPush( vDangles, pAnd );
+    // process the dangling nodes and their MFFCs
+    Vec_PtrForEachEntry( Abc_Obj_t *, vDangles, pAnd, i )
+        Abc_AigDeleteNode( pMan, pAnd );
+    Vec_PtrFree( vDangles );
+    return nNodesOld - pMan->nEntries;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Makes sure that every node in the table is in the network and vice versa.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_AigCheck( Abc_Aig_t * pMan )
+{
+    Abc_Obj_t * pObj, * pAnd;
+    int i, nFanins, Counter;
+    Abc_NtkForEachNode( pMan->pNtkAig, pObj, i )
+    {
+        nFanins = Abc_ObjFaninNum(pObj);
+        if ( nFanins == 0 )
+        {
+            if ( !Abc_AigNodeIsConst(pObj) )
+            {
+                printf( "Abc_AigCheck: The AIG has non-standard constant nodes.\n" );
+                return 0;
+            }
+            continue;
+        }
+        if ( nFanins == 1 )
+        {
+            printf( "Abc_AigCheck: The AIG has single input nodes.\n" );
+            return 0;
+        }
+        if ( nFanins > 2 )
+        {
+            printf( "Abc_AigCheck: The AIG has non-standard nodes.\n" );
+            return 0;
+        }
+        if ( pObj->Level != 1 + (unsigned)Abc_MaxInt( Abc_ObjFanin0(pObj)->Level, Abc_ObjFanin1(pObj)->Level ) )
+            printf( "Abc_AigCheck: Node \"%s\" has level that does not agree with the fanin levels.\n", Abc_ObjName(pObj) );
+        pAnd = Abc_AigAndLookup( pMan, Abc_ObjChild0(pObj), Abc_ObjChild1(pObj) );
+        if ( pAnd != pObj )
+            printf( "Abc_AigCheck: Node \"%s\" is not in the structural hashing table.\n", Abc_ObjName(pObj) );
+    }
+    // count the number of nodes in the table
+    Counter = 0;
+    for ( i = 0; i < pMan->nBins; i++ )
+        Abc_AigBinForEachEntry( pMan->pBins[i], pAnd )
+            Counter++;
+    if ( Counter != Abc_NtkNodeNum(pMan->pNtkAig) )
+    {
+        printf( "Abc_AigCheck: The number of nodes in the structural hashing table is wrong.\n" );
+        return 0;
+    }
+    // if the node is a choice node, nodes in its class should not have fanouts
+    Abc_NtkForEachNode( pMan->pNtkAig, pObj, i )
+        if ( Abc_AigNodeIsChoice(pObj) )
+            for ( pAnd = (Abc_Obj_t *)pObj->pData; pAnd; pAnd = (Abc_Obj_t *)pAnd->pData )
+                if ( Abc_ObjFanoutNum(pAnd) > 0 )
+                {
+                    printf( "Abc_AigCheck: Representative %s", Abc_ObjName(pAnd) );
+                    printf( " of choice node %s has %d fanouts.\n", Abc_ObjName(pObj), Abc_ObjFanoutNum(pAnd) );
+                    return 0;
+                }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the number of logic levels not counting PIs/POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_AigLevel( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, LevelsMax;
+    assert( Abc_NtkIsStrash(pNtk) );
+    if ( pNtk->nBarBufs )
+        return Abc_NtkLevel( pNtk );
+    // perform the traversal
+    LevelsMax = 0;
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        if ( LevelsMax < (int)Abc_ObjFanin0(pNode)->Level )
+            LevelsMax = (int)Abc_ObjFanin0(pNode)->Level;
+    return LevelsMax;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs canonicization step.]
+
+  Description [The argument nodes can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
+{
+    Abc_Obj_t * pAnd;
+    unsigned Key;
+    // check if it is a good time for table resizing
+    if ( pMan->nEntries > 2 * pMan->nBins )
+        Abc_AigResize( pMan );
+    // order the arguments
+    if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id )
+        pAnd = p0, p0 = p1, p1 = pAnd;
+    // create the new node
+    pAnd = Abc_NtkCreateNode( pMan->pNtkAig );
+    Abc_ObjAddFanin( pAnd, p0 );
+    Abc_ObjAddFanin( pAnd, p1 );
+    // set the level of the new node
+    pAnd->Level  = 1 + Abc_MaxInt( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level ); 
+    pAnd->fExor  = Abc_NodeIsExorType(pAnd);
+    pAnd->fPhase = (Abc_ObjIsComplement(p0) ^ Abc_ObjRegular(p0)->fPhase) & (Abc_ObjIsComplement(p1) ^ Abc_ObjRegular(p1)->fPhase);
+    // add the node to the corresponding linked list in the table
+    Key = Abc_HashKey2( p0, p1, pMan->nBins );
+    pAnd->pNext      = pMan->pBins[Key];
+    pMan->pBins[Key] = pAnd;
+    pMan->nEntries++;
+    // create the cuts if defined
+//    if ( pAnd->pNtk->pManCut )
+//        Abc_NodeGetCuts( pAnd->pNtk->pManCut, pAnd );
+    pAnd->pCopy = NULL;
+    // add the node to the list of updated nodes
+    if ( pMan->vAddedCells )
+        Vec_PtrPush( pMan->vAddedCells, pAnd );
+    return pAnd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs canonicization step.]
+
+  Description [The argument nodes can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, Abc_Obj_t * pAnd )
+{
+    Abc_Obj_t * pTemp;
+    unsigned Key;
+    assert( !Abc_ObjIsComplement(pAnd) );
+    // order the arguments
+    if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id )
+        pTemp = p0, p0 = p1, p1 = pTemp;
+    // create the new node
+    Abc_ObjAddFanin( pAnd, p0 );
+    Abc_ObjAddFanin( pAnd, p1 );
+    // set the level of the new node
+    pAnd->Level      = 1 + Abc_MaxInt( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level ); 
+    pAnd->fExor      = Abc_NodeIsExorType(pAnd);
+    // add the node to the corresponding linked list in the table
+    Key = Abc_HashKey2( p0, p1, pMan->nBins );
+    pAnd->pNext      = pMan->pBins[Key];
+    pMan->pBins[Key] = pAnd;
+    pMan->nEntries++;
+    // create the cuts if defined
+//    if ( pAnd->pNtk->pManCut )
+//        Abc_NodeGetCuts( pAnd->pNtk->pManCut, pAnd );
+    pAnd->pCopy = NULL;
+    // add the node to the list of updated nodes
+//    if ( pMan->vAddedCells )
+//        Vec_PtrPush( pMan->vAddedCells, pAnd );
+    return pAnd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs canonicization step.]
+
+  Description [The argument nodes can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
+{
+    Abc_Obj_t * pAnd, * pConst1;
+    unsigned Key;
+    assert( Abc_ObjRegular(p0)->pNtk->pManFunc == pMan );
+    assert( Abc_ObjRegular(p1)->pNtk->pManFunc == pMan );
+    // check for trivial cases
+    pConst1 = Abc_AigConst1(pMan->pNtkAig);
+    if ( p0 == p1 )
+        return p0;
+    if ( p0 == Abc_ObjNot(p1) )
+        return Abc_ObjNot(pConst1);
+    if ( Abc_ObjRegular(p0) == pConst1 )
+    {
+        if ( p0 == pConst1 )
+            return p1;
+        return Abc_ObjNot(pConst1);
+    }
+    if ( Abc_ObjRegular(p1) == pConst1 )
+    {
+        if ( p1 == pConst1 )
+            return p0;
+        return Abc_ObjNot(pConst1);
+    }
+/*
+    {
+        int nFans0 = Abc_ObjFanoutNum( Abc_ObjRegular(p0) );
+        int nFans1 = Abc_ObjFanoutNum( Abc_ObjRegular(p1) );
+        if ( nFans0 == 0 || nFans1 == 0 )
+            pMan->nStrash0++;
+        else if ( nFans0 == 1 || nFans1 == 1 )
+            pMan->nStrash1++;
+        else if ( nFans0 <= 100 && nFans1 <= 100 )
+            pMan->nStrash5++;
+        else
+            pMan->nStrash2++;
+    }
+*/
+    {
+        int nFans0 = Abc_ObjFanoutNum( Abc_ObjRegular(p0) );
+        int nFans1 = Abc_ObjFanoutNum( Abc_ObjRegular(p1) );
+        if ( nFans0 == 0 || nFans1 == 0 )
+            return NULL;
+    }
+
+    // order the arguments
+    if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id )
+        pAnd = p0, p0 = p1, p1 = pAnd;
+    // get the hash key for these two nodes
+    Key = Abc_HashKey2( p0, p1, pMan->nBins );
+    // find the matching node in the table
+    Abc_AigBinForEachEntry( pMan->pBins[Key], pAnd )
+        if ( p0 == Abc_ObjChild0(pAnd) && p1 == Abc_ObjChild1(pAnd) )
+        {
+//            assert( Abc_ObjFanoutNum(Abc_ObjRegular(p0)) && Abc_ObjFanoutNum(p1) );
+             return pAnd;
+        }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the gate implementing EXOR of the two arguments if it exists.]
+
+  Description [The argument nodes can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType )
+{
+    Abc_Obj_t * pNode1, * pNode2, * pNode;
+    // set the flag to zero
+    if ( pType ) *pType = 0;
+    // check the case of XOR(a,b) = OR(ab, a'b')'
+    if ( (pNode1 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), Abc_ObjNot(p1))) &&
+         (pNode2 = Abc_AigAndLookup(pMan, p0, p1)) ) 
+    {
+        pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+        if ( pNode && pType ) *pType = 1;
+        return pNode;
+    }
+    // check the case of XOR(a,b) = OR(a'b, ab')
+    if ( (pNode1 = Abc_AigAndLookup(pMan, p0, Abc_ObjNot(p1))) &&
+         (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), p1)) ) 
+    {
+        pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+        return pNode? Abc_ObjNot(pNode) : NULL;
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the gate implementing EXOR of the two arguments if it exists.]
+
+  Description [The argument nodes can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, Abc_Obj_t * pE, int * pType )
+{
+    Abc_Obj_t * pNode1, * pNode2, * pNode;
+    // set the flag to zero
+    if ( pType ) *pType = 0;
+    // check the case of MUX(c,t,e) = OR(ct', c'e')'
+    if ( (pNode1 = Abc_AigAndLookup(pMan, pC, Abc_ObjNot(pT))) &&
+         (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), Abc_ObjNot(pE))) ) 
+    {
+        pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+        if ( pNode && pType ) *pType = 1;
+        return pNode;
+    }
+    // check the case of MUX(c,t,e) = OR(ct, c'e)
+    if ( (pNode1 = Abc_AigAndLookup(pMan, pC, pT)) &&
+         (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), pE)) ) 
+    {
+        pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+        return pNode? Abc_ObjNot(pNode) : NULL;
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes an AIG node from the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis )
+{
+    Abc_Obj_t * pAnd, * pAnd0, * pAnd1, ** ppPlace;
+    unsigned Key;
+    assert( !Abc_ObjIsComplement(pThis) );
+    assert( Abc_ObjIsNode(pThis) );
+    assert( Abc_ObjFaninNum(pThis) == 2 );
+    assert( pMan->pNtkAig == pThis->pNtk );
+    // get the hash key for these two nodes
+    pAnd0 = Abc_ObjRegular( Abc_ObjChild0(pThis) );
+    pAnd1 = Abc_ObjRegular( Abc_ObjChild1(pThis) );
+    Key = Abc_HashKey2( Abc_ObjChild0(pThis), Abc_ObjChild1(pThis), pMan->nBins );
+    // find the matching node in the table
+    ppPlace = pMan->pBins + Key;
+    Abc_AigBinForEachEntry( pMan->pBins[Key], pAnd )
+    {
+        if ( pAnd != pThis )
+        {
+            ppPlace = &pAnd->pNext;
+            continue;
+        }
+        *ppPlace = pAnd->pNext;
+        break;
+    }
+    assert( pAnd == pThis );
+    pMan->nEntries--;
+    // delete the cuts if defined
+    if ( pThis->pNtk->pManCut )
+        Abc_NodeFreeCuts( pThis->pNtk->pManCut, pThis );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the hash table of AIG nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AigResize( Abc_Aig_t * pMan )
+{
+    Abc_Obj_t ** pBinsNew;
+    Abc_Obj_t * pEnt, * pEnt2;
+    int nBinsNew, Counter, i;
+    abctime clk;
+    unsigned Key;
+
+clk = Abc_Clock();
+    // get the new table size
+    nBinsNew = Abc_PrimeCudd( 3 * pMan->nBins ); 
+    // allocate a new array
+    pBinsNew = ABC_ALLOC( Abc_Obj_t *, nBinsNew );
+    memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * nBinsNew );
+    // rehash the entries from the old table
+    Counter = 0;
+    for ( i = 0; i < pMan->nBins; i++ )
+        Abc_AigBinForEachEntrySafe( pMan->pBins[i], pEnt, pEnt2 )
+        {
+            Key = Abc_HashKey2( Abc_ObjChild0(pEnt), Abc_ObjChild1(pEnt), nBinsNew );
+            pEnt->pNext   = pBinsNew[Key];
+            pBinsNew[Key] = pEnt;
+            Counter++;
+        }
+    assert( Counter == pMan->nEntries );
+//    printf( "Increasing the structural table size from %6d to %6d. ", pMan->nBins, nBinsNew );
+//    ABC_PRT( "Time", Abc_Clock() - clk );
+    // replace the table and the parameters
+    ABC_FREE( pMan->pBins );
+    pMan->pBins = pBinsNew;
+    pMan->nBins = nBinsNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the hash table of AIG nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AigRehash( Abc_Aig_t * pMan )
+{
+    Abc_Obj_t ** pBinsNew;
+    Abc_Obj_t * pEnt, * pEnt2;
+    int * pArray;
+    unsigned Key;
+    int Counter, Temp, i;
+
+    // allocate a new array
+    pBinsNew = ABC_ALLOC( Abc_Obj_t *, pMan->nBins );
+    memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * pMan->nBins );
+    // rehash the entries from the old table
+    Counter = 0;
+    for ( i = 0; i < pMan->nBins; i++ )
+        Abc_AigBinForEachEntrySafe( pMan->pBins[i], pEnt, pEnt2 )
+        {
+            // swap the fanins if needed
+            pArray = pEnt->vFanins.pArray;
+            if ( pArray[0] > pArray[1] )
+            {
+                Temp = pArray[0];
+                pArray[0] = pArray[1];
+                pArray[1] = Temp;
+                Temp = pEnt->fCompl0;
+                pEnt->fCompl0 = pEnt->fCompl1;
+                pEnt->fCompl1 = Temp;
+            }
+            // rehash the node
+            Key = Abc_HashKey2( Abc_ObjChild0(pEnt), Abc_ObjChild1(pEnt), pMan->nBins );
+            pEnt->pNext   = pBinsNew[Key];
+            pBinsNew[Key] = pEnt;
+            Counter++;
+        }
+    assert( Counter == pMan->nEntries );
+    // replace the table and the parameters
+    ABC_FREE( pMan->pBins );
+    pMan->pBins = pBinsNew;
+}
+
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs canonicization step.]
+
+  Description [The argument nodes can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigConst1( Abc_Ntk_t * pNtk )
+{
+    assert( Abc_NtkIsStrash(pNtk) );
+    return ((Abc_Aig_t *)pNtk->pManFunc)->pConst1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs canonicization step.]
+
+  Description [The argument nodes can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
+{
+    Abc_Obj_t * pAnd;
+    if ( (pAnd = Abc_AigAndLookup( pMan, p0, p1 )) )
+        return pAnd;
+    return Abc_AigAndCreate( pMan, p0, p1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements Boolean OR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
+{
+    return Abc_ObjNot( Abc_AigAnd( pMan, Abc_ObjNot(p0), Abc_ObjNot(p1) ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements Boolean XOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
+{
+    return Abc_AigOr( pMan, Abc_AigAnd(pMan, p0, Abc_ObjNot(p1)), 
+                            Abc_AigAnd(pMan, p1, Abc_ObjNot(p0)) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements Boolean XOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigMux( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * p1, Abc_Obj_t * p0 )
+{
+    return Abc_AigOr( pMan, Abc_AigAnd(pMan, pC, p1), Abc_AigAnd(pMan, Abc_ObjNot(pC), p0) );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Implements the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigMiter_rec( Abc_Aig_t * pMan, Abc_Obj_t ** ppObjs, int nObjs )
+{
+    Abc_Obj_t * pObj1, * pObj2;
+    if ( nObjs == 1 )
+        return ppObjs[0];
+    pObj1 = Abc_AigMiter_rec( pMan, ppObjs,           nObjs/2 );
+    pObj2 = Abc_AigMiter_rec( pMan, ppObjs + nObjs/2, nObjs - nObjs/2 );
+    return Abc_AigOr( pMan, pObj1, pObj2 );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Implements the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs, int fImplic )
+{
+    int i;
+    if ( vPairs->nSize == 0 )
+        return Abc_ObjNot( Abc_AigConst1(pMan->pNtkAig) );
+    assert( vPairs->nSize % 2 == 0 );
+    // go through the cubes of the node's SOP
+    if ( fImplic )
+    {
+        for ( i = 0; i < vPairs->nSize; i += 2 )
+            vPairs->pArray[i/2] = Abc_AigAnd( pMan, (Abc_Obj_t *)vPairs->pArray[i], Abc_ObjNot((Abc_Obj_t *)vPairs->pArray[i+1]) );
+    }
+    else
+    {
+        for ( i = 0; i < vPairs->nSize; i += 2 )
+            vPairs->pArray[i/2] = Abc_AigXor( pMan, (Abc_Obj_t *)vPairs->pArray[i], (Abc_Obj_t *)vPairs->pArray[i+1] );
+    }
+    vPairs->nSize = vPairs->nSize/2;
+    return Abc_AigMiter_rec( pMan, (Abc_Obj_t **)vPairs->pArray, vPairs->nSize );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Implements the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigMiter2( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs )
+{
+    Abc_Obj_t * pMiter, * pXor;
+    int i;
+    assert( vPairs->nSize % 2 == 0 );
+    // go through the cubes of the node's SOP
+    pMiter = Abc_ObjNot( Abc_AigConst1(pMan->pNtkAig) );
+    for ( i = 0; i < vPairs->nSize; i += 2 )
+    {
+        pXor   = Abc_AigXor( pMan, (Abc_Obj_t *)vPairs->pArray[i], (Abc_Obj_t *)vPairs->pArray[i+1] );
+        pMiter = Abc_AigOr( pMan, pMiter, pXor );
+    }
+    return pMiter;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces one AIG node by the other.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel )
+{
+    assert( Vec_PtrSize(pMan->vStackReplaceOld) == 0 );
+    assert( Vec_PtrSize(pMan->vStackReplaceNew) == 0 );
+    Vec_PtrPush( pMan->vStackReplaceOld, pOld );
+    Vec_PtrPush( pMan->vStackReplaceNew, pNew );
+    assert( !Abc_ObjIsComplement(pOld) );
+    // process the replacements
+    while ( Vec_PtrSize(pMan->vStackReplaceOld) )
+    {
+        pOld = (Abc_Obj_t *)Vec_PtrPop( pMan->vStackReplaceOld );
+        pNew = (Abc_Obj_t *)Vec_PtrPop( pMan->vStackReplaceNew );
+        Abc_AigReplace_int( pMan, pOld, pNew, fUpdateLevel );
+    }
+    if ( fUpdateLevel )
+    {
+        Abc_AigUpdateLevel_int( pMan );
+        if ( pMan->pNtkAig->vLevelsR ) 
+            Abc_AigUpdateLevelR_int( pMan );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs internal replacement step.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel )
+{
+    Abc_Obj_t * pFanin1, * pFanin2, * pFanout, * pFanoutNew, * pFanoutFanout;
+    int k, v, iFanin; 
+    // make sure the old node is regular and has fanouts
+    // (the new node can be complemented and can have fanouts)
+    assert( !Abc_ObjIsComplement(pOld) );
+    assert( Abc_ObjFanoutNum(pOld) > 0 );
+    // look at the fanouts of old node
+    Abc_NodeCollectFanouts( pOld, pMan->vNodes );
+    Vec_PtrForEachEntry( Abc_Obj_t *, pMan->vNodes, pFanout, k )
+    {
+        if ( Abc_ObjIsCo(pFanout) )
+        {
+            Abc_ObjPatchFanin( pFanout, pOld, pNew );
+            continue;
+        }
+        // find the old node as a fanin of this fanout
+        iFanin = Vec_IntFind( &pFanout->vFanins, pOld->Id );
+        assert( iFanin == 0 || iFanin == 1 );
+        // get the new fanin
+        pFanin1 = Abc_ObjNotCond( pNew, Abc_ObjFaninC(pFanout, iFanin) );
+        assert( Abc_ObjRegular(pFanin1) != pFanout );
+        // get another fanin
+        pFanin2 = Abc_ObjChild( pFanout, iFanin ^ 1 );
+        assert( Abc_ObjRegular(pFanin2) != pFanout );
+        // check if the node with these fanins exists
+        if ( (pFanoutNew = Abc_AigAndLookup( pMan, pFanin1, pFanin2 )) )
+        { // such node exists (it may be a constant)
+            // schedule replacement of the old fanout by the new fanout
+            Vec_PtrPush( pMan->vStackReplaceOld, pFanout );
+            Vec_PtrPush( pMan->vStackReplaceNew, pFanoutNew );
+            continue;
+        }
+        // such node does not exist - modify the old fanout node 
+        // (this way the change will not propagate all the way to the COs)
+        assert( Abc_ObjRegular(pFanin1) != Abc_ObjRegular(pFanin2) );             
+
+        // if the node is in the level structure, remove it
+        if ( pFanout->fMarkA )
+            Abc_AigRemoveFromLevelStructure( pMan->vLevels, pFanout );
+        // if the node is in the level structure, remove it
+        if ( pFanout->fMarkB )
+            Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pFanout );
+
+        // remove the old fanout node from the structural hashing table
+        Abc_AigAndDelete( pMan, pFanout );
+        // remove the fanins of the old fanout
+        Abc_ObjRemoveFanins( pFanout );
+        // recreate the old fanout with new fanins and add it to the table
+        Abc_AigAndCreateFrom( pMan, pFanin1, pFanin2, pFanout );
+        assert( Abc_AigNodeIsAcyclic(pFanout, pFanout) );
+
+        if ( fUpdateLevel )
+        {
+            // schedule the updated fanout for updating direct level
+            assert( pFanout->fMarkA == 0 );
+            pFanout->fMarkA = 1;
+            Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout );
+            // schedule the updated fanout for updating reverse level
+            if ( pMan->pNtkAig->vLevelsR ) 
+            {
+                assert( pFanout->fMarkB == 0 );
+                pFanout->fMarkB = 1;
+                Vec_VecPush( pMan->vLevelsR, Abc_ObjReverseLevel(pFanout), pFanout );
+            }
+        }
+
+        // the fanout has changed, update EXOR status of its fanouts
+        Abc_ObjForEachFanout( pFanout, pFanoutFanout, v )
+            if ( Abc_AigNodeIsAnd(pFanoutFanout) )
+                pFanoutFanout->fExor = Abc_NodeIsExorType(pFanoutFanout);
+    }
+    // if the node has no fanouts left, remove its MFFC
+    if ( Abc_ObjFanoutNum(pOld) == 0 )
+        Abc_AigDeleteNode( pMan, pOld );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs internal deletion step.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pNode0, * pNode1, * pTemp;
+    int i, k;
+
+    // make sure the node is regular and dangling
+    assert( !Abc_ObjIsComplement(pNode) );
+    assert( Abc_ObjIsNode(pNode) );
+    assert( Abc_ObjFaninNum(pNode) == 2 );
+    assert( Abc_ObjFanoutNum(pNode) == 0 );
+
+    // when deleting an old node that is scheduled for replacement, remove it from the replacement queue
+    Vec_PtrForEachEntry( Abc_Obj_t *, pMan->vStackReplaceOld, pTemp, i )
+        if ( pNode == pTemp )
+        {
+            // remove the entry from the replacement array
+            for ( k = i; k < pMan->vStackReplaceOld->nSize - 1; k++ )
+            {
+                pMan->vStackReplaceOld->pArray[k] = pMan->vStackReplaceOld->pArray[k+1];
+                pMan->vStackReplaceNew->pArray[k] = pMan->vStackReplaceNew->pArray[k+1];
+            }
+            pMan->vStackReplaceOld->nSize--;
+            pMan->vStackReplaceNew->nSize--;
+        }
+
+    // when deleting a new node that should replace another node, do not delete
+    Vec_PtrForEachEntry( Abc_Obj_t *, pMan->vStackReplaceNew, pTemp, i )
+        if ( pNode == Abc_ObjRegular(pTemp) )
+            return;
+
+    // remember the node's fanins
+    pNode0 = Abc_ObjFanin0( pNode );
+    pNode1 = Abc_ObjFanin1( pNode );
+
+    // add the node to the list of updated nodes
+    if ( pMan->vUpdatedNets )
+    {
+        Vec_PtrPushUnique( pMan->vUpdatedNets, pNode0 );
+        Vec_PtrPushUnique( pMan->vUpdatedNets, pNode1 );
+    }
+
+    // remove the node from the table
+    Abc_AigAndDelete( pMan, pNode );
+    // if the node is in the level structure, remove it
+    if ( pNode->fMarkA )
+        Abc_AigRemoveFromLevelStructure( pMan->vLevels, pNode );
+    if ( pNode->fMarkB )
+        Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pNode );
+    // remove the node from the network
+    Abc_NtkDeleteObj( pNode );
+
+    // call recursively for the fanins
+    if ( Abc_ObjIsNode(pNode0) && pNode0->vFanouts.nSize == 0 )
+        Abc_AigDeleteNode( pMan, pNode0 );
+    if ( Abc_ObjIsNode(pNode1) && pNode1->vFanouts.nSize == 0 )
+        Abc_AigDeleteNode( pMan, pNode1 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the level of the node after it has changed.]
+
+  Description [This procedure is based on the observation that
+  after the node's level has changed, the fanouts levels can change too, 
+  but the new fanout levels are always larger than the node's level.
+  As a result, we can accumulate the nodes to be updated in the queue
+  and process them in the increasing order of levels.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan )
+{
+    Abc_Obj_t * pNode, * pFanout;
+    Vec_Ptr_t * vVec;
+    int LevelNew, i, k, v;
+
+    // go through the nodes and update the level of their fanouts
+    Vec_VecForEachLevel( pMan->vLevels, vVec, i )
+    {
+        if ( Vec_PtrSize(vVec) == 0 )
+            continue;
+        Vec_PtrForEachEntry( Abc_Obj_t *, vVec, pNode, k )
+        {
+            if ( pNode == NULL )
+                continue;
+            assert( Abc_ObjIsNode(pNode) );
+            assert( (int)pNode->Level == i );
+            // clean the mark
+            assert( pNode->fMarkA == 1 );
+            pNode->fMarkA = 0;
+            // iterate through the fanouts
+            Abc_ObjForEachFanout( pNode, pFanout, v )
+            {
+                if ( Abc_ObjIsCo(pFanout) )
+                    continue;
+                // get the new level of this fanout
+                LevelNew = 1 + Abc_MaxInt( Abc_ObjFanin0(pFanout)->Level, Abc_ObjFanin1(pFanout)->Level );
+                assert( LevelNew > i );
+                if ( (int)pFanout->Level == LevelNew ) // no change
+                    continue;
+                // if the fanout is present in the data structure, pull it out
+                if ( pFanout->fMarkA )
+                    Abc_AigRemoveFromLevelStructure( pMan->vLevels, pFanout );
+                // update the fanout level
+                pFanout->Level = LevelNew;
+                // add the fanout to the data structure to update its fanouts
+                assert( pFanout->fMarkA == 0 );
+                pFanout->fMarkA = 1;
+                Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout );
+            }
+        }
+        Vec_PtrClear( vVec );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the level of the node after it has changed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan )
+{
+    Abc_Obj_t * pNode, * pFanin, * pFanout;
+    Vec_Ptr_t * vVec;
+    int LevelNew, i, k, v, j;
+
+    // go through the nodes and update the level of their fanouts
+    Vec_VecForEachLevel( pMan->vLevelsR, vVec, i )
+    {
+        if ( Vec_PtrSize(vVec) == 0 )
+            continue;
+        Vec_PtrForEachEntry( Abc_Obj_t *, vVec, pNode, k )
+        {
+            if ( pNode == NULL )
+                continue;
+            assert( Abc_ObjIsNode(pNode) );
+            assert( Abc_ObjReverseLevel(pNode) == i );
+            // clean the mark
+            assert( pNode->fMarkB == 1 );
+            pNode->fMarkB = 0;
+            // iterate through the fanins
+            Abc_ObjForEachFanin( pNode, pFanin, v )
+            {
+                if ( Abc_ObjIsCi(pFanin) )
+                    continue;
+                // get the new reverse level of this fanin
+                LevelNew = 0;
+                Abc_ObjForEachFanout( pFanin, pFanout, j )
+                    if ( LevelNew < Abc_ObjReverseLevel(pFanout) )
+                        LevelNew = Abc_ObjReverseLevel(pFanout);
+                LevelNew += 1;
+                assert( LevelNew > i );
+                if ( Abc_ObjReverseLevel(pFanin) == LevelNew ) // no change
+                    continue;
+                // if the fanin is present in the data structure, pull it out
+                if ( pFanin->fMarkB )
+                    Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pFanin );
+                // update the reverse level
+                Abc_ObjSetReverseLevel( pFanin, LevelNew );
+                // add the fanin to the data structure to update its fanins
+                assert( pFanin->fMarkB == 0 );
+                pFanin->fMarkB = 1;
+                Vec_VecPush( pMan->vLevelsR, LevelNew, pFanin );
+            }
+        }
+        Vec_PtrClear( vVec );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes the node from the level structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AigRemoveFromLevelStructure( Vec_Vec_t * vStruct, Abc_Obj_t * pNode )
+{
+    Vec_Ptr_t * vVecTemp;
+    Abc_Obj_t * pTemp;
+    int m;
+    assert( pNode->fMarkA );
+    vVecTemp = Vec_VecEntry( vStruct, pNode->Level );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vVecTemp, pTemp, m )
+    {
+        if ( pTemp != pNode )
+            continue;
+        Vec_PtrWriteEntry( vVecTemp, m, NULL );
+        break;
+    }
+    assert( m < Vec_PtrSize(vVecTemp) ); // found
+    pNode->fMarkA = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes the node from the level structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AigRemoveFromLevelStructureR( Vec_Vec_t * vStruct, Abc_Obj_t * pNode )
+{
+    Vec_Ptr_t * vVecTemp;
+    Abc_Obj_t * pTemp;
+    int m;
+    assert( pNode->fMarkB );
+    vVecTemp = Vec_VecEntry( vStruct, Abc_ObjReverseLevel(pNode) );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vVecTemp, pTemp, m )
+    {
+        if ( pTemp != pNode )
+            continue;
+        Vec_PtrWriteEntry( vVecTemp, m, NULL );
+        break;
+    }
+    assert( m < Vec_PtrSize(vVecTemp) ); // found
+    pNode->fMarkB = 0;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node has at least one complemented fanout.]
+
+  Description [A fanout is complemented if the fanout's fanin edge pointing
+  to the given node is complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanout;
+    int i, iFanin;
+    Abc_ObjForEachFanout( pNode, pFanout, i )
+    {
+        iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id );
+        assert( iFanin >= 0 );
+        if ( Abc_ObjFaninC( pFanout, iFanin ) )
+            return 1;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node has at least one complemented fanout.]
+
+  Description [A fanout is complemented if the fanout's fanin edge pointing
+  to the given node is complemented. Only the fanouts with current TravId
+  are counted.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanout;
+    int i, iFanin;
+    Abc_ObjForEachFanout( pNode, pFanout, i )
+    {
+        if ( !Abc_NodeIsTravIdCurrent(pFanout) )
+            continue;
+        iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id );
+        assert( iFanin >= 0 );
+        if ( Abc_ObjFaninC( pFanout, iFanin ) )
+            return 1;
+    }
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the AIG node for debugging purposes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AigPrintNode( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pNodeR = Abc_ObjRegular(pNode);
+    if ( Abc_ObjIsCi(pNodeR) )
+    {
+        printf( "CI %4s%s.\n", Abc_ObjName(pNodeR), Abc_ObjIsComplement(pNode)? "\'" : "" );
+        return;
+    }
+    if ( Abc_AigNodeIsConst(pNodeR) )
+    {
+        printf( "Constant 1 %s.\n", Abc_ObjIsComplement(pNode)? "(complemented)" : ""  );
+        return;
+    }
+    // print the node's function
+    printf( "%7s%s", Abc_ObjName(pNodeR),                Abc_ObjIsComplement(pNode)? "\'" : "" );
+    printf( " = " );
+    printf( "%7s%s", Abc_ObjName(Abc_ObjFanin0(pNodeR)), Abc_ObjFaninC0(pNodeR)?     "\'" : "" );
+    printf( " * " );
+    printf( "%7s%s", Abc_ObjName(Abc_ObjFanin1(pNodeR)), Abc_ObjFaninC1(pNodeR)?     "\'" : "" );
+    printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Check if the node has a combination loop of depth 1 or 2.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot )
+{
+    Abc_Obj_t * pFanin0, * pFanin1;
+    Abc_Obj_t * pChild00, * pChild01;
+    Abc_Obj_t * pChild10, * pChild11;
+    if ( !Abc_AigNodeIsAnd(pNode) )
+        return 1;
+    pFanin0 = Abc_ObjFanin0(pNode);
+    pFanin1 = Abc_ObjFanin1(pNode);
+    if ( pRoot == pFanin0 || pRoot == pFanin1 )
+        return 0;
+    if ( Abc_ObjIsCi(pFanin0) )
+    {
+        pChild00 = NULL;
+        pChild01 = NULL;
+    }
+    else
+    {
+        pChild00 = Abc_ObjFanin0(pFanin0);
+        pChild01 = Abc_ObjFanin1(pFanin0);
+        if ( pRoot == pChild00 || pRoot == pChild01 )
+            return 0;
+    }
+    if ( Abc_ObjIsCi(pFanin1) )
+    {
+        pChild10 = NULL;
+        pChild11 = NULL;
+    }
+    else
+    {
+        pChild10 = Abc_ObjFanin0(pFanin1);
+        pChild11 = Abc_ObjFanin1(pFanin1);
+        if ( pRoot == pChild10 || pRoot == pChild11 )
+            return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the hash table of AIG nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AigCheckFaninOrder( Abc_Aig_t * pMan )
+{
+    Abc_Obj_t * pEnt;
+    int i;
+    for ( i = 0; i < pMan->nBins; i++ )
+        Abc_AigBinForEachEntry( pMan->pBins[i], pEnt )
+        {
+            if ( Abc_ObjRegular(Abc_ObjChild0(pEnt))->Id > Abc_ObjRegular(Abc_ObjChild1(pEnt))->Id )
+            {
+//                int i0 = Abc_ObjRegular(Abc_ObjChild0(pEnt))->Id;
+//                int i1 = Abc_ObjRegular(Abc_ObjChild1(pEnt))->Id;
+                printf( "Node %d has incorrect ordering of fanins.\n", pEnt->Id );
+            }
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the correct phase of the nodes.]
+
+  Description [The AIG nodes should be in the DFS order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AigSetNodePhases( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    assert( Abc_NtkIsDfsOrdered(pNtk) );
+    Abc_AigConst1(pNtk)->fPhase = 1;
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        pObj->fPhase = 0;
+    Abc_NtkForEachLatchOutput( pNtk, pObj, i )
+        pObj->fPhase = Abc_LatchIsInit1(pObj);
+    Abc_AigForEachAnd( pNtk, pObj, i )
+        pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)) & (Abc_ObjFanin1(pObj)->fPhase ^ Abc_ObjFaninC1(pObj));
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj));
+    Abc_NtkForEachLatchInput( pNtk, pObj, i )
+        pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj));
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Start the update list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_AigUpdateStart( Abc_Aig_t * pMan, Vec_Ptr_t ** pvUpdatedNets )
+{
+    assert( pMan->vAddedCells == NULL );
+    pMan->vAddedCells  = Vec_PtrAlloc( 1000 );
+    pMan->vUpdatedNets = Vec_PtrAlloc( 1000 );
+    *pvUpdatedNets = pMan->vUpdatedNets;
+    return pMan->vAddedCells;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Start the update list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AigUpdateStop( Abc_Aig_t * pMan )
+{
+    assert( pMan->vAddedCells != NULL );
+    Vec_PtrFree( pMan->vAddedCells );
+    Vec_PtrFree( pMan->vUpdatedNets );
+    pMan->vAddedCells = NULL;
+    pMan->vUpdatedNets = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Start the update list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AigUpdateReset( Abc_Aig_t * pMan )
+{
+    assert( pMan->vAddedCells != NULL );
+    Vec_PtrClear( pMan->vAddedCells );
+    Vec_PtrClear( pMan->vUpdatedNets );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Start the update list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_AigCountNext( Abc_Aig_t * pMan )
+{
+    Abc_Obj_t * pAnd;
+    int i, Counter = 0, CounterTotal = 0;
+    // count how many nodes have pNext set
+    for ( i = 0; i < pMan->nBins; i++ )
+        Abc_AigBinForEachEntry( pMan->pBins[i], pAnd )
+        {
+            Counter += (pAnd->pNext != NULL);
+            CounterTotal++;
+        }
+    printf( "Counter = %d.  Nodes = %d.  Ave = %6.2f\n", Counter, CounterTotal, 1.0 * CounterTotal/pMan->nBins );
+    return Counter;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+void Abc_NtkHelloWorld( Abc_Ntk_t * pNtk )
+{
+    printf( "Hello, World!\n" );
+}
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcBarBuf.c b/abc-build/src/base/abc/abcBarBuf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcBarBuf.c
@@ -0,0 +1,513 @@
+/**CFile****************************************************************
+
+  FileName    [abcHie.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Procedures to handle hierarchy.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcHie.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define ABC_OBJ_VOID ((Abc_Obj_t *)(ABC_PTRINT_T)1)
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the the hie design has no duplicated networks.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheckSingleInstance( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pTemp, * pModel;
+    Abc_Obj_t * pBox;
+    int i, k, RetValue = 1;
+    if ( pNtk->pDesign == NULL )
+        return 1;
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i )
+        pTemp->fHieVisited = 0;
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i )
+        Abc_NtkForEachBox( pTemp, pBox, k )
+        {
+            pModel = (Abc_Ntk_t *)pBox->pData;
+            if ( pModel == NULL )
+                continue;
+            if ( Abc_NtkLatchNum(pModel) > 0 )
+            {
+                printf( "Network \"%s\" contains %d flops.\n",                     
+                    Abc_NtkName(pNtk), Abc_NtkLatchNum(pModel) );
+                RetValue = 0;
+            }
+            if ( pModel->fHieVisited )
+            {
+                printf( "Network \"%s\" contains box \"%s\" whose model \"%s\" is instantiated more than once.\n", 
+                    Abc_NtkName(pNtk), Abc_ObjName(pBox), Abc_NtkName(pModel) );
+                RetValue = 0;
+            }
+            pModel->fHieVisited = 1;
+        }
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i )
+        pTemp->fHieVisited = 0;
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect PIs and POs of internal networks in the topo order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCollectPiPos_rec( Abc_Obj_t * pNet, Vec_Ptr_t * vLiMaps, Vec_Ptr_t * vLoMaps )
+{
+    extern int Abc_NtkCollectPiPos_int( Abc_Obj_t * pBox, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLiMaps, Vec_Ptr_t * vLoMaps );
+    Abc_Obj_t * pObj, * pFanin; 
+    int i, Counter = 0;
+    assert( Abc_ObjIsNet(pNet) );
+    if ( Abc_NodeIsTravIdCurrent( pNet ) )
+        return 0;
+    Abc_NodeSetTravIdCurrent( pNet );
+    pObj = Abc_ObjFanin0(pNet);
+    if ( Abc_ObjIsNode(pObj) )
+        Abc_ObjForEachFanin( pObj, pFanin, i )
+            Counter += Abc_NtkCollectPiPos_rec( pFanin, vLiMaps, vLoMaps );
+    if ( Abc_ObjIsNode(pObj) )
+        return Counter;
+    if ( Abc_ObjIsBo(pObj) )
+        pObj = Abc_ObjFanin0(pObj);
+    assert( Abc_ObjIsBox(pObj) );
+    Abc_ObjForEachFanout( pObj, pFanin, i )
+        Abc_NodeSetTravIdCurrent( Abc_ObjFanout0(pFanin) );
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        Counter += Abc_NtkCollectPiPos_rec( Abc_ObjFanin0(pFanin), vLiMaps, vLoMaps );
+    Counter += Abc_NtkCollectPiPos_int( pObj, Abc_ObjModel(pObj), vLiMaps, vLoMaps );
+    return Counter;
+}
+int Abc_NtkCollectPiPos_int( Abc_Obj_t * pBox, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLiMaps, Vec_Ptr_t * vLoMaps )
+{
+    Abc_Obj_t * pObj; 
+    int i, Counter = 0;
+    // mark primary inputs
+    Abc_NtkIncrementTravId( pNtk );
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        Abc_NodeSetTravIdCurrent( Abc_ObjFanout0(pObj) );
+    // add primary inputs
+    if ( pBox )
+    {
+        Abc_ObjForEachFanin( pBox, pObj, i )
+            Vec_PtrPush( vLiMaps, pObj );
+        Abc_NtkForEachPi( pNtk, pObj, i )
+            Vec_PtrPush( vLoMaps, pObj );
+    }
+    // visit primary outputs
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        Counter += Abc_NtkCollectPiPos_rec( Abc_ObjFanin0(pObj), vLiMaps, vLoMaps );
+    // add primary outputs
+    if ( pBox )
+    {
+        Abc_NtkForEachPo( pNtk, pObj, i )
+            Vec_PtrPush( vLiMaps, pObj );
+        Abc_ObjForEachFanout( pBox, pObj, i )
+            Vec_PtrPush( vLoMaps, pObj );
+        Counter++;
+    }
+    return Counter;
+}
+int Abc_NtkCollectPiPos( Abc_Ntk_t * pNtk, Vec_Ptr_t ** pvLiMaps, Vec_Ptr_t ** pvLoMaps )
+{
+    assert( Abc_NtkIsNetlist(pNtk) );
+    *pvLiMaps = Vec_PtrAlloc( 1000 );
+    *pvLoMaps = Vec_PtrAlloc( 1000 );
+    return Abc_NtkCollectPiPos_int( NULL, pNtk, *pvLiMaps, *pvLoMaps );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives logic network with barbufs from the netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkToBarBufs_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNet )
+{
+    Abc_Obj_t * pObj, * pFanin; 
+    int i;
+    assert( Abc_ObjIsNet(pNet) );
+    if ( pNet->pCopy )
+        return pNet->pCopy;
+    pObj = Abc_ObjFanin0(pNet);
+    assert( Abc_ObjIsNode(pObj) );
+    pNet->pCopy = Abc_NtkDupObj( pNtkNew, pObj, 0 );
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        Abc_ObjAddFanin( pObj->pCopy, Abc_NtkToBarBufs_rec(pNtkNew, pFanin) );
+    return pNet->pCopy;
+}
+Abc_Ntk_t * Abc_NtkToBarBufs( Abc_Ntk_t * pNtk )
+{
+    char Buffer[1000];
+    Vec_Ptr_t * vLiMaps, * vLoMaps;
+    Abc_Ntk_t * pNtkNew, * pTemp;
+    Abc_Obj_t * pLatch, * pObjLi, * pObjLo;
+    Abc_Obj_t * pObj, * pLiMap, * pLoMap;
+    int i, k, nBoxes;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    if ( !Abc_NtkCheckSingleInstance(pNtk) )
+        return NULL;
+    assert( pNtk->pDesign != NULL );
+    // start the network
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, pNtk->ntkFunc, 1 );
+    pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+    pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+    // clone CIs/CIs/boxes
+    Abc_NtkCleanCopy_rec( pNtk );
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        Abc_ObjFanout0(pObj)->pCopy = Abc_NtkDupObj( pNtkNew, pObj, 1 );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        Abc_NtkDupObj( pNtkNew, pObj, 1 );
+    // create latches and transfer copy labels
+    nBoxes = Abc_NtkCollectPiPos( pNtk, &vLiMaps, &vLoMaps );
+    Vec_PtrForEachEntryTwo( Abc_Obj_t *, vLiMaps, Abc_Obj_t *, vLoMaps, pLiMap, pLoMap, i )
+    {
+        pObjLi = Abc_NtkCreateBi(pNtkNew);
+        pLatch = Abc_NtkCreateLatch(pNtkNew);
+        pObjLo = Abc_NtkCreateBo(pNtkNew);
+        Abc_ObjAddFanin( pLatch, pObjLi );
+        Abc_ObjAddFanin( pObjLo, pLatch );
+        pLatch->pData = (void *)ABC_INIT_ZERO;
+        pTemp = NULL;
+        if ( Abc_ObjFanin0(pLiMap)->pNtk != pNtk )
+            pTemp = Abc_ObjFanin0(pLiMap)->pNtk;
+        else if ( Abc_ObjFanout0(pLoMap)->pNtk != pNtk )
+            pTemp = Abc_ObjFanout0(pLoMap)->pNtk;
+        else assert( 0 );
+        sprintf( Buffer, "_%s_in", Abc_NtkName(pTemp) );
+        Abc_ObjAssignName( pObjLi, Abc_ObjName(Abc_ObjFanin0(pLiMap)), Buffer );
+        sprintf( Buffer, "_%s_out", Abc_NtkName(pTemp) );
+        Abc_ObjAssignName( pObjLo, Abc_ObjName(Abc_ObjFanout0(pLoMap)), Buffer );
+        pLiMap->pCopy = pObjLi;
+        Abc_ObjFanout0(pLoMap)->pCopy = pObjLo;
+        assert( Abc_ObjIsNet(Abc_ObjFanout0(pLoMap)) );
+    }
+    Vec_PtrFree( vLiMaps );
+    Vec_PtrFree( vLoMaps );
+    // rebuild networks
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i )
+        Abc_NtkForEachCo( pTemp, pObj, k )
+            Abc_ObjAddFanin( pObj->pCopy, Abc_NtkToBarBufs_rec(pNtkNew, Abc_ObjFanin0(pObj)) );
+    pNtkNew->nBarBufs = Abc_NtkLatchNum(pNtkNew);
+    printf( "Hierarchy reader flattened %d instances of logic boxes and introduced %d barbufs.\n", nBoxes, pNtkNew->nBarBufs );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the logic with barbufs into a hierarchical network.]
+
+  Description [The base network is the original hierarchical network. The
+  second argument is the optimized network with barbufs.  This procedure
+  reconstructs the original hierarcical network which adding logic from
+  the optimized network.  It is assumed that the PIs/POs of the original
+  network one-to-one mapping with the flops of the optimized network.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkFromBarBufs_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin; 
+    int i;
+    if ( pObj->pCopy )
+        return pObj->pCopy;
+    Abc_NtkDupObj( pNtkNew, pObj, 0 );
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        Abc_ObjAddFanin( pObj->pCopy, Abc_NtkFromBarBufs_rec(pNtkNew, pFanin) );
+    return pObj->pCopy;
+}
+Abc_Ntk_t * Abc_NtkFromBarBufs( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew, * pTemp;
+    Vec_Ptr_t * vLiMaps, * vLoMaps;
+    Abc_Obj_t * pObj, * pLiMap, * pLoMap;
+    int i, k;
+    assert( pNtkBase->pDesign != NULL );
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_NtkIsNetlist(pNtkBase) );
+    assert( Abc_NtkLatchNum(pNtkBase) == 0 );
+    assert( Abc_NtkLatchNum(pNtk) == pNtk->nBarBufs );
+    assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+    assert( Abc_NtkBlackboxNum(pNtk) == 0 );
+    assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkBase) );
+    assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkBase) );
+    // start networks
+    Abc_NtkCleanCopy_rec( pNtkBase );
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkBase->pDesign->vModules, pTemp, i )
+        pTemp->pCopy = Abc_NtkStartFrom( pTemp, pNtk->ntkType, pNtk->ntkFunc );
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkBase->pDesign->vModules, pTemp, i )
+        pTemp->pCopy->pAltView = pTemp->pAltView ? pTemp->pAltView->pCopy : NULL;
+    // update box models
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkBase->pDesign->vModules, pTemp, i )
+        Abc_NtkForEachBox( pTemp, pObj, k )
+            if ( Abc_ObjIsWhitebox(pObj) || Abc_ObjIsBlackbox(pObj) )
+                pObj->pCopy->pData = Abc_ObjModel(pObj)->pCopy;
+    // create the design
+    pNtkNew = pNtkBase->pCopy;
+    pNtkNew->pDesign = Abc_DesCreate( pNtkBase->pDesign->pName );
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkBase->pDesign->vModules, pTemp, i )
+        Abc_DesAddModel( pNtkNew->pDesign, pTemp->pCopy );
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkBase->pDesign->vTops, pTemp, i )
+        Vec_PtrPush( pNtkNew->pDesign->vTops, pTemp->pCopy );
+    assert( Vec_PtrEntry(pNtkNew->pDesign->vTops, 0) == pNtkNew );
+    // transfer copy attributes to pNtk
+    Abc_NtkCleanCopy( pNtk );
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        pObj->pCopy = Abc_NtkPi(pNtkNew, i);
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        pObj->pCopy = Abc_NtkPo(pNtkNew, i);
+    Abc_NtkCollectPiPos( pNtkBase, &vLiMaps, &vLoMaps );
+    assert( Vec_PtrSize(vLiMaps) == Abc_NtkLatchNum(pNtk) );
+    assert( Vec_PtrSize(vLoMaps) == Abc_NtkLatchNum(pNtk) );
+    Vec_PtrForEachEntryTwo( Abc_Obj_t *, vLiMaps, Abc_Obj_t *, vLoMaps, pLiMap, pLoMap, i )
+    {
+        pObj = Abc_NtkBox( pNtk, i );
+        Abc_ObjFanin0(pObj)->pCopy = pLiMap->pCopy; 
+        Abc_ObjFanout0(pObj)->pCopy = pLoMap->pCopy; 
+    }
+    Vec_PtrFree( vLiMaps );
+    Vec_PtrFree( vLoMaps );
+    // create internal nodes
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Abc_ObjAddFanin( pObj->pCopy, Abc_NtkFromBarBufs_rec(pObj->pCopy->pNtk, Abc_ObjFanin0(pObj)) );
+    // transfer net names
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        if ( Abc_ObjFanoutNum(pObj->pCopy) == 0 ) // handle PI without fanout
+            Abc_ObjAddFanin( Abc_NtkCreateNet(pObj->pCopy->pNtk), pObj->pCopy );
+        Nm_ManStoreIdName( pObj->pCopy->pNtk->pManName, Abc_ObjFanout0(pObj->pCopy)->Id, Abc_ObjFanout0(pObj->pCopy)->Type, Abc_ObjName(Abc_ObjFanout0(pObj)), NULL );
+    }
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Nm_ManStoreIdName( pObj->pCopy->pNtk->pManName, Abc_ObjFanin0(pObj->pCopy)->Id, Abc_ObjFanin0(pObj->pCopy)->Type, Abc_ObjName(Abc_ObjFanin0(pObj)), NULL );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect nodes in the barbuf-friendly order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkToBarBufsCollect_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pFanin; 
+    int i;
+    if ( Abc_NodeIsTravIdCurrent( pObj ) )
+        return;
+    Abc_NodeSetTravIdCurrent( pObj );
+    assert( Abc_ObjIsNode(pObj) );
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        Abc_NtkToBarBufsCollect_rec( pFanin, vNodes );
+    Vec_PtrPush( vNodes, pObj );
+}
+Vec_Ptr_t * Abc_NtkToBarBufsCollect( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj;
+    int i;
+    assert( Abc_NtkIsLogic(pNtk) );
+    assert( pNtk->nBarBufs > 0 );
+    assert( pNtk->nBarBufs == Abc_NtkLatchNum(pNtk) );
+    vNodes = Vec_PtrAlloc( Abc_NtkObjNum(pNtk) );
+    Abc_NtkIncrementTravId( pNtk );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        if ( i >= Abc_NtkCiNum(pNtk) - pNtk->nBarBufs )
+            break;
+        Vec_PtrPush( vNodes, pObj );
+        Abc_NodeSetTravIdCurrent( pObj );
+    }
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        if ( i < Abc_NtkCoNum(pNtk) - pNtk->nBarBufs )
+            continue;
+        Abc_NtkToBarBufsCollect_rec( Abc_ObjFanin0(pObj), vNodes );
+        Vec_PtrPush( vNodes, pObj );
+        Vec_PtrPush( vNodes, Abc_ObjFanout0(pObj) );
+        Vec_PtrPush( vNodes, Abc_ObjFanout0(Abc_ObjFanout0(pObj)) );
+        Abc_NodeSetTravIdCurrent( pObj );
+        Abc_NodeSetTravIdCurrent( Abc_ObjFanout0(pObj) );
+        Abc_NodeSetTravIdCurrent( Abc_ObjFanout0(Abc_ObjFanout0(pObj)) );
+    }
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        if ( i >= Abc_NtkCoNum(pNtk) - pNtk->nBarBufs )
+            break;
+        Abc_NtkToBarBufsCollect_rec( Abc_ObjFanin0(pObj), vNodes );
+        Vec_PtrPush( vNodes, pObj );
+        Abc_NodeSetTravIdCurrent( pObj );
+    }
+    assert( Vec_PtrSize(vNodes) == Abc_NtkObjNum(pNtk) );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count barrier buffers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCountBarBufs( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i, Counter = 0;
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        Counter += Abc_ObjIsBarBuf( pObj );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network to dedicated barbufs and back.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkBarBufsToBuffers( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k;
+    assert( Abc_NtkIsLogic(pNtk) );
+    assert( pNtk->pDesign == NULL );
+    assert( pNtk->nBarBufs > 0 );
+    assert( pNtk->nBarBufs == Abc_NtkLatchNum(pNtk) );
+    vNodes = Abc_NtkToBarBufsCollect( pNtk );
+    // start the network
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, pNtk->ntkFunc, 1 );
+    pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+    pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+    // create objects
+    Abc_NtkCleanCopy( pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        if ( Abc_ObjIsPi(pObj) )
+            Abc_NtkDupObj( pNtkNew, pObj, 1 );
+        else if ( Abc_ObjIsPo( pObj) )
+            Abc_ObjAddFanin( Abc_NtkDupObj(pNtkNew, pObj, 1), Abc_ObjFanin0(pObj)->pCopy );
+        else if ( Abc_ObjIsBi(pObj) || Abc_ObjIsBo(pObj) )
+            pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy;
+        else if ( Abc_ObjIsLatch(pObj) )
+            Abc_ObjAddFanin( (pObj->pCopy = Abc_NtkCreateNode(pNtkNew)), Abc_ObjFanin0(pObj)->pCopy );
+        else if ( Abc_ObjIsNode(pObj) )
+        {
+            Abc_NtkDupObj( pNtkNew, pObj, 1 );
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+        }
+        else assert( 0 );
+    }
+    Vec_PtrFree( vNodes );
+    return pNtkNew;
+}
+Abc_Ntk_t * Abc_NtkBarBufsFromBuffers( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObj, * pFanin, * pLatch;
+    int i, k, nBarBufs;
+    assert( Abc_NtkIsLogic(pNtkBase) );
+    assert( Abc_NtkIsLogic(pNtk) );
+    assert( pNtkBase->nBarBufs == Abc_NtkLatchNum(pNtkBase) );
+    // start the network
+    pNtkNew = Abc_NtkStartFrom( pNtkBase, pNtk->ntkType, pNtk->ntkFunc );
+    // transfer PI pointers
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        pObj->pCopy = Abc_NtkPi(pNtkNew, i);
+    // assuming that the order/number of barbufs remains the same
+    nBarBufs = 0;
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        if ( Abc_ObjIsBarBuf(pObj) )
+        {
+            pLatch = Abc_NtkBox(pNtkNew, nBarBufs++);
+            Abc_ObjAddFanin( Abc_ObjFanin0(pLatch), Abc_ObjFanin0(pObj)->pCopy );
+            pObj->pCopy = Abc_ObjFanout0(pLatch);
+        }
+        else
+        {
+            Abc_NtkDupObj( pNtkNew, pObj, 1 );
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+        }
+    }
+    assert( nBarBufs == pNtkBase->nBarBufs );
+    // connect POs
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        Abc_ObjAddFanin( Abc_NtkPo(pNtkNew, i), Abc_ObjFanin0(pObj)->pCopy );
+    return pNtkNew;
+}
+Abc_Ntk_t * Abc_NtkBarBufsOnOffTest( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew, * pNtkNew2;
+    pNtkNew  = Abc_NtkBarBufsToBuffers( pNtk );
+    pNtkNew2 = Abc_NtkBarBufsFromBuffers( pNtk, pNtkNew );
+    Abc_NtkDelete( pNtkNew );
+    return pNtkNew2;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcBlifMv.c b/abc-build/src/base/abc/abcBlifMv.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcBlifMv.c
@@ -0,0 +1,1162 @@
+/**CFile****************************************************************
+
+  FileName    [abcBlifMv.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Procedures to process BLIF-MV networks and AIGs.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcBlifMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the Mv-Var manager.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ) 
+{
+    Vec_Att_t * pAttMan;
+    assert( Abc_NtkMvVar(pNtk) == NULL );
+    pAttMan = Vec_AttAlloc( Abc_NtkObjNumMax(pNtk) + 1, Mem_FlexStart(), (void(*)(void*))Mem_FlexStop, NULL, NULL );
+    Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_MVVAR, pAttMan );
+//printf( "allocing attr\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the Mv-Var manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk ) 
+{ 
+    Mem_Flex_t * pUserMan;
+    pUserMan = (Mem_Flex_t *)Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, 0 ); 
+    Mem_FlexStop( pUserMan, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicate the MV variable.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues )
+{
+    Mem_Flex_t * pFlex;
+    struct temp 
+    { 
+        int nValues; 
+        char ** pNames; 
+    } * pVarStruct;
+    assert( nValues > 1 );
+    // skip binary signals
+    if ( nValues == 2 )
+        return;
+    // skip already assigned signals
+    if ( Abc_ObjMvVar(pObj) != NULL )
+        return;
+    // create the structure
+    pFlex = (Mem_Flex_t *)Abc_NtkMvVarMan( pObj->pNtk );
+    pVarStruct = (struct temp *)Mem_FlexEntryFetch( pFlex, sizeof(struct temp) );
+    pVarStruct->nValues = nValues;
+    pVarStruct->pNames = NULL;
+    Abc_ObjSetMvVar( pObj, pVarStruct );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes the BLIF-MV netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_StringGetNumber( char ** ppStr )
+{
+    char * pStr = *ppStr;
+    int Number = 0;
+    assert( *pStr >= '0' && *pStr <= '9' );
+    for ( ; *pStr >= '0' && *pStr <= '9'; pStr++ )
+        Number = 10 * Number + *pStr - '0';
+    *ppStr = pStr;
+    return Number;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes one node in the BLIF-MV netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeStrashBlifMv( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj )
+{
+    int fAddFreeVars = 1;
+    char * pSop;
+    Abc_Obj_t ** pValues, ** pValuesF, ** pValuesF2;
+    Abc_Obj_t * pTemp, * pTemp2, * pFanin, * pFanin2, * pNet;
+    int k, v, Def, DefIndex, Index, nValues, nValuesF, nValuesF2;
+
+    // start the output values
+    assert( Abc_ObjIsNode(pObj) );
+    pNet = Abc_ObjFanout0(pObj);
+    nValues = Abc_ObjMvVarNum(pNet);
+    pValues = ABC_ALLOC( Abc_Obj_t *, nValues );
+    for ( k = 0; k < nValues; k++ )
+        pValues[k] = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
+
+    // get the BLIF-MV formula
+    pSop = (char *)pObj->pData;
+    // skip the value line
+//    while ( *pSop++ != '\n' );
+
+    // handle the constant
+    if ( Abc_ObjFaninNum(pObj) == 0 )
+    {
+        // skip the default if present
+        if ( *pSop == 'd' )
+            while ( *pSop++ != '\n' );
+        // skip space if present
+        if ( *pSop == ' ' )
+            pSop++;
+        // assume don't-care constant to be zero
+        if ( *pSop == '-' )
+            Index = 0;
+        else
+            Index = Abc_StringGetNumber( &pSop );
+        assert( Index < nValues );
+        ////////////////////////////////////////////
+        // adding free variables for binary ND-constants
+        if ( fAddFreeVars && nValues == 2 && *pSop == '-' )
+        {
+            pValues[1] = Abc_NtkCreatePi(pNtkNew);
+            pValues[0] = Abc_ObjNot( pValues[1] );
+            Abc_ObjAssignName( pValues[1], "free_var_", Abc_ObjName(pValues[1]) );
+        }
+        else
+            pValues[Index] = Abc_AigConst1(pNtkNew);
+        ////////////////////////////////////////////
+        // save the values in the fanout net
+        pNet->pCopy = (Abc_Obj_t *)pValues;
+        return 1;
+    }
+
+    // parse the default line
+    Def = DefIndex = -1;
+    if ( *pSop == 'd' )
+    {
+        pSop++;
+        if ( *pSop == '=' )
+        {
+            pSop++;
+            DefIndex = Abc_StringGetNumber( &pSop );
+            assert( DefIndex < Abc_ObjFaninNum(pObj) );
+        }
+        else if ( *pSop == '-' )
+        {
+            pSop++;
+            Def = 0;
+        }
+        else
+        {
+            Def = Abc_StringGetNumber( &pSop );
+            assert( Def < nValues );
+        }
+        assert( *pSop == '\n' );
+        pSop++;
+    }
+
+    // convert the values
+    while ( *pSop )
+    {
+        // extract the values for each cube
+        pTemp = Abc_AigConst1(pNtkNew); 
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+        {
+            if ( *pSop == '-' )
+            {
+                pSop += 2;
+                continue;
+            }
+            if ( *pSop == '!' )
+            {
+                ABC_FREE( pValues );
+                printf( "Abc_NodeStrashBlifMv(): Cannot handle complement in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) );
+                return 0;
+            }
+            if ( *pSop == '{' )
+            {
+                ABC_FREE( pValues );
+                printf( "Abc_NodeStrashBlifMv(): Cannot handle braces in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) );
+                return 0;
+            }
+            // get the value set
+            nValuesF = Abc_ObjMvVarNum(pFanin);
+            pValuesF = (Abc_Obj_t **)pFanin->pCopy;
+            if ( *pSop == '(' )
+            {
+                pSop++;
+                pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
+                while ( *pSop != ')' )
+                {
+                    Index = Abc_StringGetNumber( &pSop );
+                    assert( Index < nValuesF );
+                    pTemp2 = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pTemp2, pValuesF[Index] );
+                    assert( *pSop == ')' || *pSop == ',' );
+                    if ( *pSop == ',' )
+                        pSop++;
+                }
+                assert( *pSop == ')' );
+                pSop++;
+            }
+            else if ( *pSop == '=' )
+            {
+                pSop++;
+                // get the fanin index
+                Index = Abc_StringGetNumber( &pSop );
+                assert( Index < Abc_ObjFaninNum(pObj) );
+                assert( Index != k );
+                // get the fanin
+                pFanin2 = Abc_ObjFanin( pObj, Index );
+                nValuesF2 = Abc_ObjMvVarNum(pFanin2);
+                pValuesF2 = (Abc_Obj_t **)pFanin2->pCopy;
+                // create the sum of products of values
+                assert( nValuesF == nValuesF2 );
+                pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
+                for ( v = 0; v < nValues; v++ )
+                    pTemp2 = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pTemp2, Abc_AigAnd((Abc_Aig_t *)pNtkNew->pManFunc, pValuesF[v], pValuesF2[v]) );
+            }
+            else
+            {
+                Index = Abc_StringGetNumber( &pSop );
+                assert( Index < nValuesF );
+                pTemp2 = pValuesF[Index];
+            }
+            // compute the compute
+            pTemp = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pTemp, pTemp2 );
+            // advance the reading point
+            assert( *pSop == ' ' );
+            pSop++;
+        }
+        // check if the output value is an equal construct
+        if ( *pSop == '=' )
+        {
+            pSop++;
+            // get the output value
+            Index = Abc_StringGetNumber( &pSop );
+            assert( Index < Abc_ObjFaninNum(pObj) );
+            // add values of the given fanin with the given cube
+            pFanin = Abc_ObjFanin( pObj, Index );
+            nValuesF = Abc_ObjMvVarNum(pFanin);
+            pValuesF = (Abc_Obj_t **)pFanin->pCopy;
+            assert( nValuesF == nValues ); // should be guaranteed by the parser
+            for ( k = 0; k < nValuesF; k++ )
+                pValues[k] = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pValues[k], Abc_AigAnd((Abc_Aig_t *)pNtkNew->pManFunc, pTemp, pValuesF[k]) );
+        }
+        else
+        {
+            // get the output value
+            Index = Abc_StringGetNumber( &pSop );
+            assert( Index < nValues );
+            pValues[Index] = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pValues[Index], pTemp );
+        }
+        // advance the reading point
+        assert( *pSop == '\n' );
+        pSop++;
+    }
+
+    // compute the default value
+    if ( Def >= 0 || DefIndex >= 0 )
+    {
+        pTemp = Abc_AigConst1(pNtkNew);
+        for ( k = 0; k < nValues; k++ )
+        {
+            if ( k == Def )
+                continue;
+            pTemp = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pTemp, Abc_ObjNot(pValues[k]) );
+        }
+
+        // assign the default value
+        if ( Def >= 0 )
+            pValues[Def] = pTemp;
+        else
+        {
+            assert( DefIndex >= 0 );
+            // add values of the given fanin with the given cube
+            pFanin = Abc_ObjFanin( pObj, DefIndex );
+            nValuesF = Abc_ObjMvVarNum(pFanin);
+            pValuesF = (Abc_Obj_t **)pFanin->pCopy;
+            assert( nValuesF == nValues ); // should be guaranteed by the parser
+            for ( k = 0; k < nValuesF; k++ )
+                pValues[k] = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pValues[k], Abc_AigAnd((Abc_Aig_t *)pNtkNew->pManFunc, pTemp, pValuesF[k]) );
+        }
+
+    }
+
+    // save the values in the fanout net
+    pNet->pCopy = (Abc_Obj_t *)pValues;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns name with index.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_NtkConvertAssignName( Abc_Obj_t * pObj, Abc_Obj_t * pNet, int Index )
+{
+    char Suffix[16];
+    assert( Abc_ObjIsTerm(pObj) );
+    assert( Abc_ObjIsNet(pNet) );
+    sprintf( Suffix, "[%d]", Index );
+    Abc_ObjAssignName( pObj, Abc_ObjName(pNet), Suffix );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes the BLIF-MV netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk )
+{
+    int fUsePositional = 0;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t ** pBits;
+    Abc_Obj_t ** pValues;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObj, * pTemp, * pBit, * pNet;
+    int i, k, v, nValues, nValuesMax, nBits;
+    int nCount1, nCount2;
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_NtkHasBlifMv(pNtk) );
+    assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+    assert( Abc_NtkBlackboxNum(pNtk) == 0 );
+
+    // get the largest number of values
+    nValuesMax = 2;
+    Abc_NtkForEachNet( pNtk, pObj, i )
+    {
+        nValues = Abc_ObjMvVarNum(pObj);
+        if ( nValuesMax < nValues )
+            nValuesMax = nValues;
+    }
+    nBits = Abc_Base2Log( nValuesMax );
+    pBits = ABC_ALLOC( Abc_Obj_t *, nBits );
+
+    // clean the node copy fields
+    Abc_NtkCleanCopy( pNtk );
+    // collect the nodes
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+
+    // start the network
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    // duplicate the name and the spec
+    pNtkNew->pName = Extra_UtilStrsav( pNtk->pName );
+//    pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName );
+
+    nCount1 = nCount2 = 0;
+    // encode the CI nets
+    Abc_NtkIncrementTravId( pNtk );
+    if ( fUsePositional )
+    {
+        Abc_NtkForEachCi( pNtk, pObj, i )
+        {
+            if ( !Abc_ObjIsPi(pObj) )
+                continue;
+            pNet = Abc_ObjFanout0(pObj);
+            nValues = Abc_ObjMvVarNum(pNet);
+            pValues = ABC_ALLOC( Abc_Obj_t *, nValues );
+            // create PIs for the values
+            for ( v = 0; v < nValues; v++ )
+            {
+                pValues[v] = Abc_NtkCreatePi( pNtkNew );
+                if ( nValuesMax == 2 )
+                    Abc_ObjAssignName( pValues[v], Abc_ObjName(pNet), NULL );
+                else
+                    Abc_NtkConvertAssignName( pValues[v], pNet, v );
+            }
+            // save the values in the fanout net
+            pNet->pCopy = (Abc_Obj_t *)pValues;
+            // mark the net
+            Abc_NodeSetTravIdCurrent( pNet );
+        }
+        Abc_NtkForEachCi( pNtk, pObj, i )
+        {
+            if ( Abc_ObjIsPi(pObj) )
+                continue;
+            pNet = Abc_ObjFanout0(pObj);
+            nValues = Abc_ObjMvVarNum(pNet);
+            pValues = ABC_ALLOC( Abc_Obj_t *, nValues );
+            // create PIs for the values
+            for ( v = 0; v < nValues; v++ )
+            {
+                pValues[v] = Abc_NtkCreateBo( pNtkNew );
+                if ( nValuesMax == 2 )
+                    Abc_ObjAssignName( pValues[v], Abc_ObjName(pNet), NULL );
+                else
+                    Abc_NtkConvertAssignName( pValues[v], pNet, v );
+                nCount1++;
+            }
+            // save the values in the fanout net
+            pNet->pCopy = (Abc_Obj_t *)pValues;
+            // mark the net
+            Abc_NodeSetTravIdCurrent( pNet );
+        }
+    }
+    else
+    {
+        Abc_NtkForEachCi( pNtk, pObj, i )
+        {
+            if ( !Abc_ObjIsPi(pObj) )
+                continue;
+            pNet = Abc_ObjFanout0(pObj);
+            nValues = Abc_ObjMvVarNum(pNet);
+            pValues = ABC_ALLOC( Abc_Obj_t *, nValues );
+            // create PIs for the encoding bits
+            nBits = Abc_Base2Log( nValues );
+            for ( k = 0; k < nBits; k++ )
+            {
+                pBits[k] = Abc_NtkCreatePi( pNtkNew );
+                if ( nValuesMax == 2 )
+                    Abc_ObjAssignName( pBits[k], Abc_ObjName(pNet), NULL );
+                else
+                    Abc_NtkConvertAssignName( pBits[k], pNet, k );
+            }
+            // encode the values
+            for ( v = 0; v < nValues; v++ )
+            {
+                pValues[v] = Abc_AigConst1(pNtkNew);
+                for ( k = 0; k < nBits; k++ )
+                {
+                    pBit = Abc_ObjNotCond( pBits[k], (v&(1<<k)) == 0 );
+                    pValues[v] = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pValues[v], pBit );
+                }
+            }
+            // save the values in the fanout net
+            pNet->pCopy = (Abc_Obj_t *)pValues;
+            // mark the net
+            Abc_NodeSetTravIdCurrent( pNet );
+        }
+        Abc_NtkForEachCi( pNtk, pObj, i )
+        {
+            if ( Abc_ObjIsPi(pObj) )
+                continue;
+            pNet = Abc_ObjFanout0(pObj);
+            nValues = Abc_ObjMvVarNum(pNet);
+            pValues = ABC_ALLOC( Abc_Obj_t *, nValues );
+            // create PIs for the encoding bits
+            nBits = Abc_Base2Log( nValues );
+            for ( k = 0; k < nBits; k++ )
+            {
+                pBits[k] = Abc_NtkCreateBo( pNtkNew );
+                if ( nValuesMax == 2 )
+                    Abc_ObjAssignName( pBits[k], Abc_ObjName(pNet), NULL );
+                else
+                    Abc_NtkConvertAssignName( pBits[k], pNet, k );
+                nCount1++;
+            }
+            // encode the values
+            for ( v = 0; v < nValues; v++ )
+            {
+                pValues[v] = Abc_AigConst1(pNtkNew);
+                for ( k = 0; k < nBits; k++ )
+                {
+                    pBit = Abc_ObjNotCond( pBits[k], (v&(1<<k)) == 0 );
+                    pValues[v] = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pValues[v], pBit );
+                }
+            }
+            // save the values in the fanout net
+            pNet->pCopy = (Abc_Obj_t *)pValues;
+            // mark the net
+            Abc_NodeSetTravIdCurrent( pNet );
+        }
+    }
+
+    // process nodes in the topological order
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        if ( !Abc_NodeStrashBlifMv( pNtkNew, pObj ) )
+        {
+            Abc_NtkDelete( pNtkNew );
+            return NULL;
+        }
+    Vec_PtrFree( vNodes );
+
+    // encode the CO nets
+    if ( fUsePositional )
+    {
+        Abc_NtkForEachCo( pNtk, pObj, i )
+        {
+            if ( !Abc_ObjIsPo(pObj) )
+                continue;
+            pNet = Abc_ObjFanin0(pObj);
+            // skip marked nets
+//            if ( Abc_NodeIsTravIdCurrent(pNet) )
+//                continue;
+//            Abc_NodeSetTravIdCurrent( pNet );
+            nValues = Abc_ObjMvVarNum(pNet);
+            pValues = (Abc_Obj_t **)pNet->pCopy;
+            for ( v = 0; v < nValues; v++ )
+            {
+                pTemp = Abc_NtkCreatePo( pNtkNew );
+                Abc_ObjAddFanin( pTemp, pValues[v] );
+                if ( nValuesMax == 2 )
+                    Abc_ObjAssignName( pTemp, Abc_ObjName(pNet), NULL );
+                else
+                    Abc_NtkConvertAssignName( pTemp, pNet, v );
+            }
+        }
+        Abc_NtkForEachCo( pNtk, pObj, i )
+        {
+            if ( Abc_ObjIsPo(pObj) )
+                continue;
+            pNet = Abc_ObjFanin0(pObj);
+            // skip marked nets
+//            if ( Abc_NodeIsTravIdCurrent(pNet) )
+//                continue;
+//            Abc_NodeSetTravIdCurrent( pNet );
+            nValues = Abc_ObjMvVarNum(pNet);
+            pValues = (Abc_Obj_t **)pNet->pCopy;
+            for ( v = 0; v < nValues; v++ )
+            {
+                pTemp = Abc_NtkCreateBi( pNtkNew );
+                Abc_ObjAddFanin( pTemp, pValues[v] );
+                if ( nValuesMax == 2 )
+                    Abc_ObjAssignName( pTemp, Abc_ObjName(pNet), NULL );
+                else
+                    Abc_NtkConvertAssignName( pTemp, pNet, v );
+                nCount2++;
+            }
+        }
+    }
+    else // if ( fPositional == 0 )
+    {
+        Abc_NtkForEachCo( pNtk, pObj, i )
+        {
+            if ( !Abc_ObjIsPo(pObj) )
+                continue;
+            pNet = Abc_ObjFanin0(pObj);
+            // skip marked nets
+//            if ( Abc_NodeIsTravIdCurrent(pNet) )
+//                continue;
+//            Abc_NodeSetTravIdCurrent( pNet );
+            nValues = Abc_ObjMvVarNum(pNet);
+            pValues = (Abc_Obj_t **)pNet->pCopy;
+            nBits = Abc_Base2Log( nValues );
+            for ( k = 0; k < nBits; k++ )
+            {
+                pBit = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
+                for ( v = 0; v < nValues; v++ )
+                    if ( v & (1<<k) )
+                        pBit = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pBit, pValues[v] );
+                pTemp = Abc_NtkCreatePo( pNtkNew );
+                Abc_ObjAddFanin( pTemp, pBit );
+                if ( nValuesMax == 2 )
+                    Abc_ObjAssignName( pTemp, Abc_ObjName(pNet), NULL );
+                else
+                    Abc_NtkConvertAssignName( pTemp, pNet, k );
+            }
+        }
+        Abc_NtkForEachCo( pNtk, pObj, i )
+        {
+            if ( Abc_ObjIsPo(pObj) )
+                continue;
+            pNet = Abc_ObjFanin0(pObj);
+            // skip marked nets
+//            if ( Abc_NodeIsTravIdCurrent(pNet) )
+//                continue;
+//            Abc_NodeSetTravIdCurrent( pNet );
+            nValues = Abc_ObjMvVarNum(pNet);
+            pValues = (Abc_Obj_t **)pNet->pCopy;
+            nBits = Abc_Base2Log( nValues );
+            for ( k = 0; k < nBits; k++ )
+            {
+                pBit = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
+                for ( v = 0; v < nValues; v++ )
+                    if ( v & (1<<k) )
+                        pBit = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pBit, pValues[v] );
+                pTemp = Abc_NtkCreateBi( pNtkNew );
+                Abc_ObjAddFanin( pTemp, pBit );
+                if ( nValuesMax == 2 )
+                    Abc_ObjAssignName( pTemp, Abc_ObjName(pNet), NULL );
+                else
+                    Abc_NtkConvertAssignName( pTemp, pNet, k );
+                nCount2++;
+            }
+        }
+    }
+
+    if ( Abc_NtkLatchNum(pNtk) )
+    {
+        Vec_Ptr_t * vTemp;
+        Abc_Obj_t * pLatch, * pObjLi, * pObjLo;
+        int i;
+        // move free vars to the front among the PIs
+        vTemp = Vec_PtrAlloc( Vec_PtrSize(pNtkNew->vPis) );
+        Abc_NtkForEachPi( pNtkNew, pObj, i )
+            if ( strncmp( Abc_ObjName(pObj), "free_var_", 9 ) == 0 )
+                Vec_PtrPush( vTemp, pObj );
+        Abc_NtkForEachPi( pNtkNew, pObj, i )
+            if ( strncmp( Abc_ObjName(pObj), "free_var_", 9 ) != 0 )
+                Vec_PtrPush( vTemp, pObj );
+        assert( Vec_PtrSize(vTemp) == Vec_PtrSize(pNtkNew->vPis) );
+        Vec_PtrFree( pNtkNew->vPis );
+        pNtkNew->vPis = vTemp;
+        // move free vars to the front among the CIs
+        vTemp = Vec_PtrAlloc( Vec_PtrSize(pNtkNew->vCis) );
+        Abc_NtkForEachCi( pNtkNew, pObj, i )
+            if ( strncmp( Abc_ObjName(pObj), "free_var_", 9 ) == 0 )
+                Vec_PtrPush( vTemp, pObj );
+        Abc_NtkForEachCi( pNtkNew, pObj, i )
+            if ( strncmp( Abc_ObjName(pObj), "free_var_", 9 ) != 0 )
+                Vec_PtrPush( vTemp, pObj );
+        assert( Vec_PtrSize(vTemp) == Vec_PtrSize(pNtkNew->vCis) );
+        Vec_PtrFree( pNtkNew->vCis );
+        pNtkNew->vCis = vTemp;
+        // create registers
+        assert( nCount1 == nCount2 );
+        for ( i = 0; i < nCount1; i++ )
+        {
+            // create latch
+            pLatch = Abc_NtkCreateLatch( pNtkNew );
+            Abc_LatchSetInit0( pLatch );
+            Abc_ObjAssignName( pLatch, Abc_ObjName(pLatch), NULL );
+            // connect
+            pObjLi = Abc_NtkCo( pNtkNew, Abc_NtkCoNum(pNtkNew)-nCount1+i );
+            pObjLo = Abc_NtkCi( pNtkNew, Abc_NtkCiNum(pNtkNew)-nCount1+i );
+            Abc_ObjAddFanin( pLatch, pObjLi );
+            Abc_ObjAddFanin( pObjLo, pLatch );
+        }
+    }
+
+    // cleanup
+    ABC_FREE( pBits );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( pObj->pCopy )
+            ABC_FREE( pObj->pCopy );
+
+    // remove dangling nodes
+    i = Abc_AigCleanup((Abc_Aig_t *)pNtkNew->pManFunc);
+//    printf( "Cleanup removed %d nodes.\n", i );
+//    Abc_NtkReassignIds( pNtkNew );
+
+    // check integrity
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        fprintf( stdout, "Abc_NtkStrashBlifMv(): Network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Extract the MV-skeleton of the BLIF-MV network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkSkeletonBlifMv( Abc_Ntk_t * pNtk )
+{
+    int fUsePositional = 0;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObj, * pNet, * pNetNew, * pNodeNew, * pTermNew, * pBoxNew;
+    int i, k, v, nValues, nBits;
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_NtkHasBlifMv(pNtk) );
+    assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+    assert( Abc_NtkBlackboxNum(pNtk) == 0 );
+
+    // clean the node copy fields
+    Abc_NtkCleanCopy( pNtk );
+
+    // start the network
+    pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+    // duplicate the name and the spec
+    pNtkNew->pName = Extra_UtilStrsav( pNtk->pName );
+    pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName );
+    // create the internal box (it is important to put it first!)
+    pBoxNew = Abc_NtkCreateWhitebox( pNtkNew );
+    // create PIs and their nets
+    Abc_NtkForEachPi( pNtk, pObj, i )
+    {
+        Abc_NtkDupObj( pNtkNew, pObj, 0 );
+        pNet = Abc_ObjFanout0(pObj);
+        Abc_NtkDupObj( pNtkNew, pNet, 1 );
+        Abc_ObjAddFanin( pNet->pCopy, pObj->pCopy );
+    }
+    // create POs and their nets
+    Abc_NtkForEachPo( pNtk, pObj, i )
+    {
+        Abc_NtkDupObj( pNtkNew, pObj, 0 );
+        pNet = Abc_ObjFanin0(pObj);
+        if ( pNet->pCopy == NULL )
+            Abc_NtkDupObj( pNtkNew, pNet, 1 );
+        Abc_ObjAddFanin( pObj->pCopy, pNet->pCopy );
+    }
+    // create latches
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+    {
+        Abc_NtkDupBox( pNtkNew, pObj, 0 );
+        // latch outputs
+        pNet = Abc_ObjFanout0(Abc_ObjFanout0(pObj));
+        assert( pNet->pCopy == NULL );
+        Abc_NtkDupObj( pNtkNew, pNet, 1 );
+        Abc_ObjAddFanin( pNet->pCopy, Abc_ObjFanout0(pObj)->pCopy );
+        // latch inputs
+        pNet = Abc_ObjFanin0(Abc_ObjFanin0(pObj));
+        if ( pNet->pCopy == NULL )
+            Abc_NtkDupObj( pNtkNew, pNet, 1 );
+        Abc_ObjAddFanin( Abc_ObjFanin0(pObj)->pCopy, pNet->pCopy );
+    }
+
+    // encode the CI nets
+    Abc_NtkIncrementTravId( pNtk );
+    if ( fUsePositional )
+    {
+        Abc_NtkForEachCi( pNtk, pObj, i )
+        {
+            pNet = Abc_ObjFanout0(pObj);
+            nValues = Abc_ObjMvVarNum(pNet);
+            for ( v = 0; v < nValues; v++ )
+            {
+                pNodeNew = Abc_NtkCreateNode( pNtkNew );
+                pNodeNew->pData = Abc_SopEncoderPos( (Mem_Flex_t *)pNtkNew->pManFunc, v, nValues );
+                pNetNew = Abc_NtkCreateNet( pNtkNew );
+                pTermNew = Abc_NtkCreateBi( pNtkNew );
+                Abc_ObjAddFanin( pNodeNew, pNet->pCopy );
+                Abc_ObjAddFanin( pNetNew, pNodeNew );
+                Abc_ObjAddFanin( pTermNew, pNetNew );
+                Abc_ObjAddFanin( pBoxNew, pTermNew );
+            }
+            // mark the net
+            Abc_NodeSetTravIdCurrent( pNet );
+        }
+    }
+    else
+    {
+        Abc_NtkForEachCi( pNtk, pObj, i )
+        {
+            pNet = Abc_ObjFanout0(pObj);
+            nValues = Abc_ObjMvVarNum(pNet);
+            nBits = Abc_Base2Log( nValues );
+            for ( k = 0; k < nBits; k++ )
+            {
+                pNodeNew = Abc_NtkCreateNode( pNtkNew );
+                pNodeNew->pData = Abc_SopEncoderLog( (Mem_Flex_t *)pNtkNew->pManFunc, k, nValues );
+                pNetNew = Abc_NtkCreateNet( pNtkNew );
+                pTermNew = Abc_NtkCreateBi( pNtkNew );
+                Abc_ObjAddFanin( pNodeNew, pNet->pCopy );
+                Abc_ObjAddFanin( pNetNew, pNodeNew );
+                Abc_ObjAddFanin( pTermNew, pNetNew );
+                Abc_ObjAddFanin( pBoxNew, pTermNew );
+            }
+            // mark the net
+            Abc_NodeSetTravIdCurrent( pNet );
+        }
+    }
+
+    // encode the CO nets
+    if ( fUsePositional )
+    {
+        Abc_NtkForEachCo( pNtk, pObj, i )
+        {
+            pNet = Abc_ObjFanin0(pObj);
+            // skip marked nets
+            if ( Abc_NodeIsTravIdCurrent(pNet) )
+                continue;
+            Abc_NodeSetTravIdCurrent( pNet );
+            nValues = Abc_ObjMvVarNum(pNet);
+            pNodeNew = Abc_NtkCreateNode( pNtkNew );
+            pNodeNew->pData = Abc_SopDecoderPos( (Mem_Flex_t *)pNtkNew->pManFunc, nValues );
+            for ( v = 0; v < nValues; v++ )
+            {
+                pTermNew = Abc_NtkCreateBo( pNtkNew );
+                pNetNew = Abc_NtkCreateNet( pNtkNew );
+                Abc_ObjAddFanin( pTermNew, pBoxNew );
+                Abc_ObjAddFanin( pNetNew, pTermNew );
+                Abc_ObjAddFanin( pNodeNew, pNetNew );
+            }
+            Abc_ObjAddFanin( pNet->pCopy, pNodeNew );
+        }
+    }
+    else
+    {
+        Abc_NtkForEachCo( pNtk, pObj, i )
+        {
+            pNet = Abc_ObjFanin0(pObj);
+            // skip marked nets
+            if ( Abc_NodeIsTravIdCurrent(pNet) )
+                continue;
+            Abc_NodeSetTravIdCurrent( pNet );
+            nValues = Abc_ObjMvVarNum(pNet);
+            nBits = Abc_Base2Log( nValues );
+            pNodeNew = Abc_NtkCreateNode( pNtkNew );
+            pNodeNew->pData = Abc_SopDecoderLog( (Mem_Flex_t *)pNtkNew->pManFunc, nValues );
+            for ( k = 0; k < nBits; k++ )
+            {
+                pTermNew = Abc_NtkCreateBo( pNtkNew );
+                pNetNew = Abc_NtkCreateNet( pNtkNew );
+                Abc_ObjAddFanin( pTermNew, pBoxNew );
+                Abc_ObjAddFanin( pNetNew, pTermNew );
+                Abc_ObjAddFanin( pNodeNew, pNetNew );
+            }
+            Abc_ObjAddFanin( pNet->pCopy, pNodeNew );
+        }
+    }
+
+    // if it is a BLIF-MV netlist transfer the values of all nets
+    if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) )
+    {
+        if ( Abc_NtkMvVar( pNtkNew ) == NULL )
+            Abc_NtkStartMvVars( pNtkNew );
+        Abc_NtkForEachNet( pNtk, pObj, i )
+            if ( pObj->pCopy )
+                Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) );
+    }
+
+    // check integrity
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        fprintf( stdout, "Abc_NtkSkeletonBlifMv(): Network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts processed network into original base MV network.]
+
+  Description [The original network remembers the interface of combinational 
+  logic (PIs/POs/latches names and values). The processed network may 
+  be binary or multi-valued (currently, multi-value is not supported). 
+  The resulting network has the same interface as the original network 
+  while the internal logic is the same as that of the processed network.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic )
+{
+    Abc_Ntk_t * pNtkSkel, * pNtkNew;
+    Abc_Obj_t * pBox;
+
+    assert( Abc_NtkIsNetlist(pNtkBase) );
+    assert( Abc_NtkHasBlifMv(pNtkBase) );
+    assert( Abc_NtkWhiteboxNum(pNtkBase) == 0 );
+    assert( Abc_NtkBlackboxNum(pNtkBase) == 0 );
+
+    assert( Abc_NtkIsNetlist(pNtkLogic) );
+    assert( Abc_NtkHasBlifMv(pNtkLogic) );
+    assert( Abc_NtkWhiteboxNum(pNtkLogic) == 0 );
+    assert( Abc_NtkBlackboxNum(pNtkLogic) == 0 );
+
+    // extract the skeleton of the old network
+    pNtkSkel = Abc_NtkSkeletonBlifMv( pNtkBase );
+
+    // set the implementation of the box to be the same as the processed network
+    assert( Abc_NtkWhiteboxNum(pNtkSkel) == 1 );
+    pBox = Abc_NtkBox( pNtkSkel, 0 );
+    assert( Abc_ObjIsWhitebox(pBox) );
+    assert( pBox->pData == NULL );
+    assert( Abc_ObjFaninNum(pBox) == Abc_NtkPiNum(pNtkLogic) );
+    assert( Abc_ObjFanoutNum(pBox) == Abc_NtkPoNum(pNtkLogic) );
+    pBox->pData = pNtkLogic;
+
+    // flatten the hierarchy to insert the processed network
+    pNtkNew = Abc_NtkFlattenLogicHierarchy( pNtkSkel );
+    pBox->pData = NULL;
+    Abc_NtkDelete( pNtkSkel );
+    return pNtkNew;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts SOP netlist into BLIF-MV netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk )
+{
+    Mem_Flex_t * pMmFlex;
+    Abc_Obj_t * pNode;
+    Vec_Str_t * vCube;
+    char * pSop0, * pSop1, * pBlifMv, * pCube, * pCur;
+    int Value, nCubes, nSize, i, k;
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+    if ( !Abc_NtkToBdd(pNtk) )
+    {
+        printf( "Converting logic functions to BDDs has failed.\n" );
+        return 0;
+    }
+
+    pMmFlex = Mem_FlexStart();
+    vCube   = Vec_StrAlloc( 100 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        // convert BDD into cubes for on-set and off-set
+        Abc_NodeBddToCnf( pNode, pMmFlex, vCube, 0, &pSop0, &pSop1 );
+        // allocate room for the MV-SOP
+        nCubes = Abc_SopGetCubeNum(pSop0) + Abc_SopGetCubeNum(pSop1);
+        nSize = nCubes*(2*Abc_ObjFaninNum(pNode) + 2)+1;
+        pBlifMv = Mem_FlexEntryFetch( pMmFlex, nSize );
+        // add the cubes
+        pCur = pBlifMv;
+        Abc_SopForEachCube( pSop0, Abc_ObjFaninNum(pNode), pCube )
+        {
+            Abc_CubeForEachVar( pCube, Value, k )
+            {
+                *pCur++ = Value;
+                *pCur++ = ' ';
+            }
+            *pCur++ = '0';
+            *pCur++ = '\n';
+        }
+        Abc_SopForEachCube( pSop1, Abc_ObjFaninNum(pNode), pCube )
+        {
+            Abc_CubeForEachVar( pCube, Value, k )
+            {
+                *pCur++ = Value;
+                *pCur++ = ' ';
+            }
+            *pCur++ = '1';
+            *pCur++ = '\n';
+        }
+        *pCur++ = 0;
+        assert( pCur - pBlifMv == nSize );
+        // update the node representation
+        Cudd_RecursiveDeref( (DdManager *)pNtk->pManFunc, (DdNode *)pNode->pData );
+        pNode->pData = pBlifMv;
+    }
+
+    // update the functionality type
+    pNtk->ntkFunc = ABC_FUNC_BLIFMV;
+    Cudd_Quit( (DdManager *)pNtk->pManFunc );
+    pNtk->pManFunc = pMmFlex;
+
+    Vec_StrFree( vCube );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts SOP into MV-SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 )
+{
+    char * pMvSop, * pCur;
+    unsigned uCube;
+    int nCubes, nSize, Value, i, k;
+    // consider the case of the constant node
+    if ( Vec_IntSize(vSop0) == 0 || Vec_IntSize(vSop1) == 0 )
+    {
+        // (temporary) create a tautology cube
+        pMvSop = ABC_ALLOC( char, nVars + 3 );
+        for ( k = 0; k < nVars; k++ )
+            pMvSop[k] = '-';
+        pMvSop[nVars] = '0' + (int)(Vec_IntSize(vSop1) > 0);
+        pMvSop[nVars+1] = '\n';
+        pMvSop[nVars+2] = 0;
+        return pMvSop;
+    }
+    // find the total number of cubes
+    nCubes = Vec_IntSize(vSop0) + Vec_IntSize(vSop1);
+    // find the size of the MVSOP represented as a C-string
+    // (each cube has nVars variables + one output literal + end-of-line,
+    // and the string is zero-terminated)
+    nSize = nCubes * (nVars + 2) + 1; 
+    // allocate memory
+    pMvSop = pCur = ABC_ALLOC( char, nSize );
+    // fill in the negative polarity cubes
+    Vec_IntForEachEntry( vSop0, uCube, i )
+    {
+        for ( k = 0; k < nVars; k++ )
+        {
+            Value = (uCube >> (2*k)) & 3;
+            if ( Value == 1 )
+                *pCur++ = '0';
+            else if ( Value == 2 )
+                *pCur++ = '1';
+            else if ( Value == 0 )
+                *pCur++ = '-';
+            else
+                assert( 0 );
+        }
+        *pCur++ = '0';
+        *pCur++ = '\n';
+    }
+    // fill in the positive polarity cubes
+    Vec_IntForEachEntry( vSop1, uCube, i )
+    {
+        for ( k = 0; k < nVars; k++ )
+        {
+            Value = (uCube >> (2*k)) & 3;
+            if ( Value == 1 )
+                *pCur++ = '0';
+            else if ( Value == 2 )
+                *pCur++ = '1';
+            else if ( Value == 0 )
+                *pCur++ = '-';
+            else
+                assert( 0 );
+        }
+        *pCur++ = '1';
+        *pCur++ = '\n';
+    }
+    *pCur++ = 0;
+    assert( pCur - pMvSop == nSize );
+    return pMvSop;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [A prototype of internal cost evaluation procedure.]
+
+  Description [This procedure takes the number of variables (nVars),
+  the array of values of the inputs and the output (pVarValues) 
+  (note that this array has nVars+1 entries), and an MV-SOP represented
+  as a C-string with one charater for each literal, including inputs
+  and output. Each cube is terminated with the new-line character ('\n').
+  The string is zero-terminated.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeEvalMvCostInternal( int nVars, int * pVarValues, char * pMvSop ) 
+{
+    // for now, return the number of cubes in the MV-SOP
+    int Counter = 0;
+    while ( *pMvSop ) Counter += (*pMvSop++ == '\n');
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates the cost of the cut.]
+
+  Description [The Boolean function of the cut is specified by two SOPs, 
+  which represent the negative/positive polarities of the cut function.
+  Converts these two SOPs into a mutually-agreed-upon representation 
+  to be passed to the internal cost-evaluation procedure (see the above
+  prototype Abc_NodeEvalMvCostInternal).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ) 
+{
+    char * pMvSop;
+    int * pVarValues;
+    int i, RetValue;
+    // collect the input and output values (currently, they are binary)
+    pVarValues = ABC_ALLOC( int, nVars + 1 );
+    for ( i = 0; i <= nVars; i++ )
+        pVarValues[i] = 2;
+    // prepare MV-SOP for evaluation
+    pMvSop = Abc_NodeConvertSopToMvSop( nVars, vSop0, vSop1 );
+    // have a look at the MV-SOP:
+//    printf( "%s\n", pMvSop );
+    // get the result of internal cost evaluation
+    RetValue = Abc_NodeEvalMvCostInternal( nVars, pVarValues, pMvSop );
+    // cleanup
+    ABC_FREE( pVarValues );
+    ABC_FREE( pMvSop );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcCheck.c b/abc-build/src/base/abc/abcCheck.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcCheck.c
@@ -0,0 +1,946 @@
+/**CFile****************************************************************
+
+  FileName    [abcCheck.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Consistency checking procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "base/main/main.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_NtkCheckNames( Abc_Ntk_t * pNtk );
+static int Abc_NtkCheckPis( Abc_Ntk_t * pNtk );
+static int Abc_NtkCheckPos( Abc_Ntk_t * pNtk );
+//static int Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj );
+static int Abc_NtkCheckNet( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet );
+static int Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode );
+static int Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch );
+
+static int Abc_NtkComparePis( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb );
+static int Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb );
+static int Abc_NtkCompareLatches( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb );
+
+static inline char * Abc_ObjNameNet( Abc_Obj_t * pObj ) { return (Abc_ObjIsNode(pObj) && Abc_NtkIsNetlist(pObj->pNtk)) ? Abc_ObjName(Abc_ObjFanout0(pObj)) : Abc_ObjName(pObj); }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the integrity of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheck( Abc_Ntk_t * pNtk )
+{ 
+   return !Abc_FrameIsFlagEnabled( "check" ) || Abc_NtkDoCheck( pNtk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the integrity of the network after reading.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheckRead( Abc_Ntk_t * pNtk )
+{
+   return !Abc_FrameIsFlagEnabled( "checkread" ) || Abc_NtkDoCheck( pNtk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the integrity of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDoCheck( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj, * pNet, * pNode;
+    int i;
+
+    // check network types
+    if ( !Abc_NtkIsNetlist(pNtk) && !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) )
+    {
+        fprintf( stdout, "NetworkCheck: Unknown network type.\n" );
+        return 0;
+    }
+    if ( !Abc_NtkHasSop(pNtk) && !Abc_NtkHasBdd(pNtk) && !Abc_NtkHasAig(pNtk) && !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlifMv(pNtk) && !Abc_NtkHasBlackbox(pNtk) )
+    {
+        fprintf( stdout, "NetworkCheck: Unknown functionality type.\n" );
+        return 0;
+    }
+    if ( Abc_NtkHasMapping(pNtk) )
+    {
+        if ( pNtk->pManFunc != Abc_FrameReadLibGen() )
+        {
+            fprintf( stdout, "NetworkCheck: The library of the mapped network is not the global library.\n" );
+            return 0;
+        }
+    }
+
+    if ( Abc_NtkHasOnlyLatchBoxes(pNtk) )
+    {
+        // check CI/CO numbers
+        if ( Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) != Abc_NtkCiNum(pNtk) )
+        {
+            fprintf( stdout, "NetworkCheck: Number of CIs does not match number of PIs and latches.\n" );
+            fprintf( stdout, "One possible reason is that latches are added twice:\n" );
+            fprintf( stdout, "in procedure Abc_NtkCreateObj() and in the user's code.\n" );
+            return 0;
+        }
+        if ( Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk) != Abc_NtkCoNum(pNtk) )
+        {
+            fprintf( stdout, "NetworkCheck: Number of COs does not match number of POs, asserts, and latches.\n" );
+            fprintf( stdout, "One possible reason is that latches are added twice:\n" );
+            fprintf( stdout, "in procedure Abc_NtkCreateObj() and in the user's code.\n" );
+            return 0;
+        }
+    }
+
+    // check the names
+    if ( !Abc_NtkCheckNames( pNtk ) )
+        return 0;
+
+    // check PIs and POs
+    Abc_NtkCleanCopy( pNtk );
+    if ( !Abc_NtkCheckPis( pNtk ) )
+        return 0;
+    if ( !Abc_NtkCheckPos( pNtk ) )
+        return 0;
+
+    if ( Abc_NtkHasBlackbox(pNtk) )
+        return 1;
+
+    // check the connectivity of objects
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( !Abc_NtkCheckObj( pNtk, pObj ) )
+            return 0;
+
+    // if it is a netlist change nets and latches
+    if ( Abc_NtkIsNetlist(pNtk) )
+    {
+        if ( Abc_NtkNetNum(pNtk) == 0 )
+            fprintf( stdout, "NetworkCheck: Warning! Netlist has no nets.\n" );
+        // check the nets
+        Abc_NtkForEachNet( pNtk, pNet, i )
+            if ( !Abc_NtkCheckNet( pNtk, pNet ) )
+                return 0;
+    }
+    else
+    {
+        if ( Abc_NtkNetNum(pNtk) != 0 )
+        {
+            fprintf( stdout, "NetworkCheck: A network that is not a netlist has nets.\n" );
+            return 0;
+        }
+    }
+
+    // check the nodes
+    if ( Abc_NtkIsStrash(pNtk) )
+        Abc_AigCheck( (Abc_Aig_t *)pNtk->pManFunc );
+    else
+    {
+        Abc_NtkForEachNode( pNtk, pNode, i )
+            if ( !Abc_NtkCheckNode( pNtk, pNode ) )
+                return 0;
+    }
+
+    // check the latches
+    Abc_NtkForEachLatch( pNtk, pNode, i )
+        if ( !Abc_NtkCheckLatch( pNtk, pNode ) )
+            return 0;
+
+    // finally, check for combinational loops
+//  clk = Abc_Clock();
+    if ( !Abc_NtkIsAcyclic( pNtk ) )
+    {
+        fprintf( stdout, "NetworkCheck: Network contains a combinational loop.\n" );
+        return 0;
+    }
+//  ABC_PRT( "Acyclic  ", Abc_Clock() - clk );
+
+    // check the EXDC network if present
+    if ( pNtk->pExdc )
+        Abc_NtkCheck( pNtk->pExdc );
+/*
+    // check the hierarchy
+    if ( Abc_NtkIsNetlist(pNtk) && pNtk->tName2Model )
+    {
+        stmm_generator * gen;
+        Abc_Ntk_t * pNtkTemp;
+        char * pName;
+        // check other networks
+        stmm_foreach_item( pNtk->tName2Model, gen, &pName, (char **)&pNtkTemp )
+        {
+            pNtkTemp->fHiePath = pNtkTemp->fHieVisited = 0;
+            if ( !Abc_NtkCheck( pNtkTemp ) )
+                return 0;
+        }
+        // check acyclic dependency of the models
+        if ( !Abc_NtkIsAcyclicHierarchy( pNtk ) )
+        {
+            fprintf( stdout, "NetworkCheck: Network hierarchical dependences contains a cycle.\n" );
+            return 0;
+        }
+    }
+*/
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the names.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheckNames( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj = NULL; // Ensure pObj isn't used uninitialized.
+    Vec_Int_t * vNameIds;
+    char * pName;
+    int i, NameId;
+
+    if ( Abc_NtkIsNetlist(pNtk) )
+        return 1;
+
+    // check that each CI/CO has a name
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        pObj = Abc_ObjFanout0Ntk(pObj);
+        if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL )
+        {
+            fprintf( stdout, "NetworkCheck: CI with ID %d is in the network but not in the name table.\n", pObj->Id );
+            return 0;
+        }
+    }
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        pObj = Abc_ObjFanin0Ntk(pObj);
+        if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL )
+        {
+            fprintf( stdout, "NetworkCheck: CO with ID %d is in the network but not in the name table.\n", pObj->Id );
+            return 0;
+        }
+    }
+
+    assert(pObj); // pObj should point to something here.
+
+    // return the array of all IDs, which have names
+    vNameIds = Nm_ManReturnNameIds( pNtk->pManName );
+    // make sure that these IDs correspond to live objects
+    Vec_IntForEachEntry( vNameIds, NameId, i )
+    {
+        if ( Vec_PtrEntry( pNtk->vObjs, NameId ) == NULL )
+        {
+            Vec_IntFree( vNameIds );
+            pName = Nm_ManFindNameById(pObj->pNtk->pManName, NameId);
+            fprintf( stdout, "NetworkCheck: Object with ID %d is deleted but its name \"%s\" remains in the name table.\n", NameId, pName );
+            return 0;
+        }
+    }
+    Vec_IntFree( vNameIds );
+
+    // make sure the CI names are unique
+    if ( !Abc_NtkCheckUniqueCiNames(pNtk) )
+        return 0;
+
+    // make sure the CO names are unique
+    if ( !Abc_NtkCheckUniqueCoNames(pNtk) )
+        return 0;
+
+    // make sure that if a CO has the same name as a CI, they point directly
+    if ( !Abc_NtkCheckUniqueCioNames(pNtk) )
+        return 0;
+
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the PIs of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheckPis( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+
+    // check that PIs are indeed PIs
+    Abc_NtkForEachPi( pNtk, pObj, i )
+    {
+        if ( !Abc_ObjIsPi(pObj) )
+        {
+            fprintf( stdout, "NetworkCheck: Object \"%s\" (id=%d) is in the PI list but is not a PI.\n", Abc_ObjName(pObj), pObj->Id );
+            return 0;
+        }
+        if ( pObj->pData )
+        {
+            fprintf( stdout, "NetworkCheck: A PI \"%s\" has a logic function.\n", Abc_ObjName(pObj) );
+            return 0;
+        }
+        if ( Abc_ObjFaninNum(pObj) > 0 )
+        {
+            fprintf( stdout, "NetworkCheck: A PI \"%s\" has fanins.\n", Abc_ObjName(pObj) );
+            return 0;
+        }
+        pObj->pCopy = (Abc_Obj_t *)1;
+    }
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        if ( pObj->pCopy == NULL && Abc_ObjIsPi(pObj) )
+        {
+            fprintf( stdout, "NetworkCheck: Object \"%s\" (id=%d) is a PI but is not in the PI list.\n", Abc_ObjName(pObj), pObj->Id );
+            return 0;
+        }
+        pObj->pCopy = NULL;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the POs of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheckPos( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+
+    // check that POs are indeed POs
+    Abc_NtkForEachPo( pNtk, pObj, i )
+    {
+        if ( !Abc_ObjIsPo(pObj) )
+        {
+            fprintf( stdout, "NetworkCheck: Net \"%s\" (id=%d) is in the PO list but is not a PO.\n", Abc_ObjName(pObj), pObj->Id );
+            return 0;
+        }
+        if ( pObj->pData )
+        {
+            fprintf( stdout, "NetworkCheck: A PO \"%s\" has a logic function.\n", Abc_ObjName(pObj) );
+            return 0;
+        }
+        if ( Abc_ObjFaninNum(pObj) != 1 )
+        {
+            fprintf( stdout, "NetworkCheck: A PO \"%s\" does not have one fanin (but %d).\n", Abc_ObjName(pObj), Abc_ObjFaninNum(pObj) );
+            return 0;
+        }
+        if ( Abc_ObjFanoutNum(pObj) > 0 )
+        {
+            fprintf( stdout, "NetworkCheck: A PO \"%s\" has %d fanout(s).\n", Abc_ObjName(pObj), Abc_ObjFanoutNum(pObj) );
+            return 0;
+        }
+        pObj->pCopy = (Abc_Obj_t *)1;
+    }
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        if ( pObj->pCopy == NULL && Abc_ObjIsPo(pObj) )
+        {
+            fprintf( stdout, "NetworkCheck: Net \"%s\" (id=%d) is in a PO but is not in the PO list.\n", Abc_ObjName(pObj), pObj->Id );
+            return 0;
+        }
+        pObj->pCopy = NULL;
+    }
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the connectivity of the object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin, * pFanout;
+    int Value = 1;
+    int i, k;
+
+    // check the network
+    if ( pObj->pNtk != pNtk )
+    {
+        fprintf( stdout, "NetworkCheck: Object \"%s\" does not belong to the network.\n", Abc_ObjName(pObj) );
+        return 0;
+    }
+    // check the object ID
+    if ( pObj->Id < 0 || (int)pObj->Id >= Abc_NtkObjNumMax(pNtk) )
+    {
+        fprintf( stdout, "NetworkCheck: Object \"%s\" has incorrect ID.\n", Abc_ObjName(pObj) );
+        return 0;
+    }
+
+    if ( !Abc_FrameIsFlagEnabled("checkfio") )
+        return Value;
+
+    // go through the fanins of the object and make sure fanins have this object as a fanout
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+    {
+        if ( Vec_IntFind( &pFanin->vFanouts, pObj->Id ) == -1 )
+        {
+            fprintf( stdout, "NodeCheck: Object \"%s\" has fanin ", Abc_ObjName(pObj) );
+            fprintf( stdout, "\"%s\" but the fanin does not have it as a fanout.\n", Abc_ObjName(pFanin) );
+            Value = 0;
+        }
+    }
+    // go through the fanouts of the object and make sure fanouts have this object as a fanin
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+    {
+        if ( Vec_IntFind( &pFanout->vFanins, pObj->Id ) == -1 )
+        {
+            fprintf( stdout, "NodeCheck: Object \"%s\" has fanout ", Abc_ObjName(pObj) );
+            fprintf( stdout, "\"%s\" but the fanout does not have it as a fanin.\n", Abc_ObjName(pFanout) );
+            Value = 0;
+        }
+    }
+
+    // make sure fanins are not duplicated
+    for ( i = 0; i < pObj->vFanins.nSize; i++ )
+        for ( k = i + 1; k < pObj->vFanins.nSize; k++ )
+            if ( pObj->vFanins.pArray[k] == pObj->vFanins.pArray[i] )
+            {
+                printf( "Warning: Node %s has", Abc_ObjName(pObj) );
+                printf( " duplicated fanin %s.\n", Abc_ObjName(Abc_ObjFanin(pObj,k)) );
+            }
+
+    // save time: do not check large fanout lists
+    if ( pObj->vFanouts.nSize > 100 )
+        return Value;
+
+    // make sure fanouts are not duplicated
+    for ( i = 0; i < pObj->vFanouts.nSize; i++ )
+        for ( k = i + 1; k < pObj->vFanouts.nSize; k++ )
+            if ( pObj->vFanouts.pArray[k] == pObj->vFanouts.pArray[i] )
+            {
+                printf( "Warning: Node %s has", Abc_ObjName(pObj) );
+                printf( " duplicated fanout %s.\n", Abc_ObjName(Abc_ObjFanout(pObj,k)) );
+            }
+
+    return Value;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the integrity of a net.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheckNet( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet )
+{
+    if ( Abc_ObjFaninNum(pNet) == 0 )
+    {
+        fprintf( stdout, "NetworkCheck: Net \"%s\" is not driven.\n", Abc_ObjName(pNet) );
+        return 0;
+    }
+    if ( Abc_ObjFaninNum(pNet) > 1 )
+    {
+        fprintf( stdout, "NetworkCheck: Net \"%s\" has more than one driver.\n", Abc_ObjName(pNet) );
+        return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the integrity of a node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode )
+{
+    // detect internal nodes that do not have nets
+    if ( Abc_NtkIsNetlist(pNtk) && Abc_ObjFanoutNum(pNode) == 0 )
+    {
+        fprintf( stdout, "Node (id = %d) has no net to drive.\n", pNode->Id );
+        return 0;
+    }
+    // the node should have a function assigned unless it is an AIG
+    if ( pNode->pData == NULL )
+    {
+        fprintf( stdout, "NodeCheck: An internal node \"%s\" does not have a logic function.\n", Abc_ObjNameNet(pNode) );
+        return 0;
+    }
+    // the netlist and SOP logic network should have SOPs
+    if ( Abc_NtkHasSop(pNtk) )
+    {
+        if ( !Abc_SopCheck( (char *)pNode->pData, Abc_ObjFaninNum(pNode) ) )
+        {
+            fprintf( stdout, "NodeCheck: SOP check for node \"%s\" has failed.\n", Abc_ObjNameNet(pNode) );
+            return 0;
+        }
+    }
+    else if ( Abc_NtkHasBdd(pNtk) )
+    {
+        int nSuppSize = Cudd_SupportSize((DdManager *)pNtk->pManFunc, (DdNode *)pNode->pData);
+        if ( nSuppSize > Abc_ObjFaninNum(pNode) )
+        {
+            fprintf( stdout, "NodeCheck: BDD of the node \"%s\" has incorrect support size.\n", Abc_ObjNameNet(pNode) );
+            return 0;
+        }
+    }
+    else if ( !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlifMv(pNtk) && !Abc_NtkHasAig(pNtk) )
+    {
+        assert( 0 );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the integrity of a latch.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch )
+{
+    int Value = 1;
+    // check whether the object is a latch
+    if ( !Abc_ObjIsLatch(pLatch) )
+    {
+        fprintf( stdout, "NodeCheck: Latch \"%s\" is in a latch list but is not a latch.\n", Abc_ObjName(pLatch) );
+        Value = 0;
+    }
+    // make sure the latch has a reasonable return value
+    if ( (int)(ABC_PTRINT_T)pLatch->pData < ABC_INIT_ZERO || (int)(ABC_PTRINT_T)pLatch->pData > ABC_INIT_DC )
+    {
+        fprintf( stdout, "NodeCheck: Latch \"%s\" has incorrect reset value (%d).\n", 
+            Abc_ObjName(pLatch), (int)(ABC_PTRINT_T)pLatch->pData );
+        Value = 0;
+    }
+    // make sure the latch has only one fanin
+    if ( Abc_ObjFaninNum(pLatch) != 1 )
+    {
+        fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanins.\n", Abc_ObjName(pLatch), Abc_ObjFaninNum(pLatch) );
+        Value = 0;
+    }
+    // make sure the latch has only one fanout
+    if ( Abc_ObjFanoutNum(pLatch) != 1 )
+    {
+        fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanouts.\n", Abc_ObjName(pLatch), Abc_ObjFanoutNum(pLatch) );
+        Value = 0;
+    }
+    // make sure the latch input has only one fanin
+    if ( Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) != 1 )
+    {
+        fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanins.\n", 
+            Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) );
+        Value = 0;
+    }
+    // make sure the latch input has only one fanout
+    if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) != 1 )
+    {
+        fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanouts.\n", 
+            Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) );
+        Value = 0;
+    }
+    // make sure the latch output has only one fanin
+    if ( Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) != 1 )
+    {
+        fprintf( stdout, "NodeCheck: Output of latch \"%s\" has wrong number (%d) of fanins.\n", 
+            Abc_ObjName(Abc_ObjFanout0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) );
+        Value = 0;
+    }
+    return Value;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the PIs of the two networks.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkComparePis( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
+{
+    Abc_Obj_t * pObj1;
+    int i;
+    if ( Abc_NtkPiNum(pNtk1) != Abc_NtkPiNum(pNtk2) )
+    {
+        printf( "Networks have different number of primary inputs.\n" );
+        return 0;
+    }
+    // for each PI of pNet1 find corresponding PI of pNet2 and reorder them
+    Abc_NtkForEachPi( pNtk1, pObj1, i )
+    {
+        if ( strcmp( Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPi(pNtk2,i)) ) != 0 )
+        {
+            printf( "Primary input #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", 
+                i, Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPi(pNtk2,i)) );
+            return 0;
+        }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the POs of the two networks.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
+{
+    Abc_Obj_t * pObj1;
+    int i;
+    if ( Abc_NtkPoNum(pNtk1) != Abc_NtkPoNum(pNtk2) )
+    {
+        printf( "Networks have different number of primary outputs.\n" );
+        return 0;
+    }
+    // for each PO of pNet1 find corresponding PO of pNet2 and reorder them
+    Abc_NtkForEachPo( pNtk1, pObj1, i )
+    {
+        if ( strcmp( Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPo(pNtk2,i)) ) != 0 )
+        {
+            printf( "Primary output #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", 
+                i, Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPo(pNtk2,i)) );
+            return 0;
+        }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the latches of the two networks.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCompareBoxes( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
+{
+    Abc_Obj_t * pObj1;
+    int i;
+    assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) );
+    assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) );
+    if ( !fComb )
+        return 1;
+    if ( Abc_NtkBoxNum(pNtk1) != Abc_NtkBoxNum(pNtk2) )
+    {
+        printf( "Networks have different number of latches.\n" );
+        return 0;
+    }
+    // for each PI of pNet1 find corresponding PI of pNet2 and reorder them
+    Abc_NtkForEachBox( pNtk1, pObj1, i )
+    {
+        if ( strcmp( Abc_ObjName(Abc_ObjFanout0(pObj1)), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pNtk2,i))) ) != 0 )
+        {
+            printf( "Box #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", 
+                i, Abc_ObjName(Abc_ObjFanout0(pObj1)), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pNtk2,i))) );
+            return 0;
+        }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the signals of the networks.]
+
+  Description []
+               
+  SideEffects [Ordering POs by name is a very bad idea! It destroys
+  the natural order of the logic in the circuit.]
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb )
+{
+    Abc_NtkOrderObjsByName( pNtk1, fComb );
+    Abc_NtkOrderObjsByName( pNtk2, fComb );
+    if ( !Abc_NtkComparePis( pNtk1, pNtk2, fComb ) )
+        return 0;
+    if ( !fOnlyPis )
+    {
+        if ( !Abc_NtkCompareBoxes( pNtk1, pNtk2, fComb ) )
+            return 0;
+        if ( !Abc_NtkComparePos( pNtk1, pNtk2, fComb ) )
+            return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 0 if the network hierachy contains a cycle.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkIsAcyclicHierarchy_rec( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNext;
+    Abc_Obj_t * pObj;
+    int i;
+    // return if visited
+    if ( pNtk->fHieVisited )
+        return 1;
+    pNtk->fHieVisited = 1;
+    // return if black box
+    if ( Abc_NtkHasBlackbox(pNtk) )
+        return 1;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    // go through all the children networks
+    Abc_NtkForEachBox( pNtk, pObj, i )
+    {
+        if ( Abc_ObjIsLatch(pObj) )
+            continue;
+        pNtkNext = (Abc_Ntk_t *)pObj->pData;
+        assert( pNtkNext != NULL );
+        if ( pNtkNext->fHiePath )
+            return 0;
+        pNtk->fHiePath = 1;
+        if ( !Abc_NtkIsAcyclicHierarchy_rec( pNtkNext ) )
+            return 0;
+        pNtk->fHiePath = 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 0 if the network hierachy contains a cycle.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pTemp;
+    int i, RetValue;
+    assert( Abc_NtkIsNetlist(pNtk) && pNtk->pDesign );
+    // clear the modules
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i )
+        pTemp->fHieVisited = pTemp->fHiePath = 0;
+    // traverse
+    pNtk->fHiePath = 1;
+    RetValue = Abc_NtkIsAcyclicHierarchy_rec( pNtk );
+    pNtk->fHiePath = 0;
+    // clear the modules
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i )
+        pTemp->fHieVisited = pTemp->fHiePath = 0;
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 0 if CI names are repeated.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkNamesCompare( char ** pName1, char ** pName2 )
+{
+    return strcmp( *pName1, *pName2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 0 if CI names are repeated.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNames;
+    Abc_Obj_t * pObj;
+    int i, fRetValue = 1;
+    assert( !Abc_NtkIsNetlist(pNtk) );
+    vNames = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        Vec_PtrPush( vNames, Abc_ObjName(pObj) );
+    Vec_PtrSort( vNames, (int (*)())Abc_NtkNamesCompare );
+    for ( i = 1; i < Abc_NtkCiNum(pNtk); i++ )
+        if ( !strcmp( (const char *)Vec_PtrEntry(vNames,i-1), (const char *)Vec_PtrEntry(vNames,i) ) )
+        {
+            printf( "Abc_NtkCheck: Repeated CI names: %s and %s.\n", (char*)Vec_PtrEntry(vNames,i-1), (char*)Vec_PtrEntry(vNames,i) );
+            fRetValue = 0;
+        }
+    Vec_PtrFree( vNames );
+    return fRetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 0 if CO names are repeated.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNames;
+    Abc_Obj_t * pObj;
+    int i, fRetValue = 1;
+    assert( !Abc_NtkIsNetlist(pNtk) );
+    vNames = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Vec_PtrPush( vNames, Abc_ObjName(pObj) );
+    Vec_PtrSort( vNames, (int (*)())Abc_NtkNamesCompare );
+    for ( i = 1; i < Abc_NtkCoNum(pNtk); i++ )
+    {
+//        printf( "%s\n", Vec_PtrEntry(vNames,i) );
+        if ( !strcmp( (const char *)Vec_PtrEntry(vNames,i-1), (const char *)Vec_PtrEntry(vNames,i) ) )
+        {
+            printf( "Abc_NtkCheck: Repeated CO names: %s and %s.\n", (char*)Vec_PtrEntry(vNames,i-1), (char*)Vec_PtrEntry(vNames,i) );
+            fRetValue = 0;
+        }
+    }
+    Vec_PtrFree( vNames );
+    return fRetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 0 if there is a pair of CI/CO with the same name and logic in between.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj, * pObjCi, * pFanin;
+    int i, nCiId, fRetValue = 1;
+    assert( !Abc_NtkIsNetlist(pNtk) );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        nCiId = Nm_ManFindIdByNameTwoTypes( pNtk->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO );
+        if ( nCiId == -1 )
+            continue;
+        pObjCi = Abc_NtkObj( pNtk, nCiId );
+        assert( !strcmp( Abc_ObjName(pObj), Abc_ObjName(pObjCi) ) );
+        pFanin = Abc_ObjFanin0(pObj);
+        if ( pFanin != pObjCi )
+        {
+            printf( "Abc_NtkCheck: A CI/CO pair share the name (%s) but do not link directly. The name of the CO fanin is %s.\n", 
+                Abc_ObjName(pObj), Abc_ObjName(Abc_ObjFanin0(pObj)) );
+            fRetValue = 0;
+        }
+    }
+    return fRetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcDfs.c b/abc-build/src/base/abc/abcDfs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcDfs.c
@@ -0,0 +1,1525 @@
+/**CFile****************************************************************
+
+  FileName    [abcDfs.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Procedures that use depth-first search.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcDfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DFS for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    assert( !Abc_ObjIsNet(pNode) );
+    // if this node is already visited, skip
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return;
+    // mark the node as visited
+    Abc_NodeSetTravIdCurrent( pNode );
+    // skip the CI
+    if ( Abc_ObjIsCi(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsConst(pNode)) )
+        return;
+    assert( Abc_ObjIsNode( pNode ) || Abc_ObjIsBox( pNode ) );
+    // visit the transitive fanin of the node
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+//        pFanin = Abc_ObjFanin( pNode, Abc_ObjFaninNum(pNode)-1-i );
+        Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(pFanin), vNodes );
+    }
+    // add the node after the fanins have been added
+    Vec_PtrPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the DFS ordered array of logic nodes.]
+
+  Description [Collects only the internal nodes, leaving out CIs and CO.
+  However it marks with the current TravId both CIs and COs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfs( Abc_Ntk_t * pNtk, int fCollectAll )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj;
+    int i;
+    // set the traversal ID
+    Abc_NtkIncrementTravId( pNtk );
+    // start the array of nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        Abc_NodeSetTravIdCurrent( pObj );
+        Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes );
+    }
+    // collect dangling nodes if asked to
+    if ( fCollectAll )
+    {
+        Abc_NtkForEachNode( pNtk, pObj, i )
+            if ( !Abc_NodeIsTravIdCurrent(pObj) )
+                Abc_NtkDfs_rec( pObj, vNodes );
+    }
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the DFS ordered array of logic nodes.]
+
+  Description [Collects only the internal nodes, leaving out PIs, POs and latches.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes )
+{
+    Vec_Ptr_t * vNodes;
+    int i;
+    // set the traversal ID
+    Abc_NtkIncrementTravId( pNtk );
+    // start the array of nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    // go through the PO nodes and call for each of them
+    for ( i = 0; i < nNodes; i++ )
+    {
+        if ( Abc_NtkIsStrash(pNtk) && Abc_AigNodeIsConst(ppNodes[i]) )
+            continue;
+        if ( Abc_ObjIsCo(ppNodes[i]) )
+        {
+            Abc_NodeSetTravIdCurrent(ppNodes[i]);
+            Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(ppNodes[i])), vNodes );
+        }
+        else if ( Abc_ObjIsNode(ppNodes[i]) || Abc_ObjIsCi(ppNodes[i]) )
+            Abc_NtkDfs_rec( ppNodes[i], vNodes );
+    }
+    return vNodes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DFS for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    assert( !Abc_ObjIsNet(pNode) );
+    // if this node is already visited, skip
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return;
+    // mark the node as visited
+    Abc_NodeSetTravIdCurrent( pNode );
+    // skip the CI
+    if ( Abc_ObjIsCo(pNode) )
+        return;
+    assert( Abc_ObjIsNode( pNode ) );
+    // visit the transitive fanin of the node
+    pNode = Abc_ObjFanout0Ntk(pNode);
+    Abc_ObjForEachFanout( pNode, pFanout, i )
+        Abc_NtkDfsReverse_rec( pFanout, vNodes );
+    // add the node after the fanins have been added
+    Vec_PtrPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the reverse DFS ordered array of logic nodes.]
+
+  Description [Collects only the internal nodes, leaving out CIs/COs.
+  However it marks both CIs and COs with the current TravId.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj, * pFanout;
+    int i, k;
+    // set the traversal ID
+    Abc_NtkIncrementTravId( pNtk );
+    // start the array of nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        Abc_NodeSetTravIdCurrent( pObj );
+        pObj = Abc_ObjFanout0Ntk(pObj);
+        Abc_ObjForEachFanout( pObj, pFanout, k )
+            Abc_NtkDfsReverse_rec( pFanout, vNodes );
+    }
+    // add constant nodes in the end
+    if ( !Abc_NtkIsStrash(pNtk) ) {
+        Abc_NtkForEachNode( pNtk, pObj, i )
+            if ( Abc_NodeIsConst(pObj) )
+                Vec_PtrPush( vNodes, pObj );
+    }
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DFS for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDfsReverseNodes_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    assert( !Abc_ObjIsNet(pNode) );
+    // if this node is already visited, skip
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return;
+    // mark the node as visited
+    Abc_NodeSetTravIdCurrent( pNode );
+    // skip the CI
+    if ( Abc_ObjIsCo(pNode) )
+        return;
+    assert( Abc_ObjIsNode( pNode ) );
+    // visit the transitive fanin of the node
+    pNode = Abc_ObjFanout0Ntk(pNode);
+    Abc_ObjForEachFanout( pNode, pFanout, i )
+        Abc_NtkDfsReverseNodes_rec( pFanout, vNodes );
+    // add the node after the fanins have been added
+//    Vec_PtrPush( vNodes, pNode );
+    Vec_PtrFillExtra( vNodes, pNode->Level + 1, NULL );
+    pNode->pCopy = (Abc_Obj_t *)Vec_PtrEntry( vNodes, pNode->Level );
+    Vec_PtrWriteEntry( vNodes, pNode->Level, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the levelized array of TFO nodes.]
+
+  Description [Collects the levelized array of internal nodes, leaving out CIs/COs.
+  However it marks both CIs and COs with the current TravId.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsReverseNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj, * pFanout;
+    int i, k;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // set the traversal ID
+    Abc_NtkIncrementTravId( pNtk );
+    // start the array of nodes
+    vNodes = Vec_PtrStart( Abc_AigLevel(pNtk) + 1 );
+    for ( i = 0; i < nNodes; i++ )
+    {
+        pObj = ppNodes[i];
+        assert( Abc_ObjIsCi(pObj) );
+        Abc_NodeSetTravIdCurrent( pObj );
+        pObj = Abc_ObjFanout0Ntk(pObj);
+        Abc_ObjForEachFanout( pObj, pFanout, k )
+            Abc_NtkDfsReverseNodes_rec( pFanout, vNodes );
+    }
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the levelized array of TFO nodes.]
+
+  Description [Collects the levelized array of internal nodes, leaving out CIs/COs.
+  However it marks both CIs and COs with the current TravId.
+  Collects only the nodes whose support does not exceed the set of given CI nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsReverseNodesContained( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj, * pFanout, * pFanin;
+    int i, k, m, nLevels;
+    // set the levels
+    nLevels = Abc_NtkLevel( pNtk );
+    // set the traversal ID
+    Abc_NtkIncrementTravId( pNtk );
+    // start the array of nodes
+    vNodes = Vec_PtrStart( nLevels + 2 );
+    for ( i = 0; i < nNodes; i++ )
+    {
+        pObj = ppNodes[i];
+        assert( Abc_ObjIsCi(pObj) );
+        Abc_NodeSetTravIdCurrent( pObj );
+        // add to the array
+        assert( pObj->Level == 0 );
+        pObj->pCopy = (Abc_Obj_t *)Vec_PtrEntry( vNodes, pObj->Level );
+        Vec_PtrWriteEntry( vNodes, pObj->Level, pObj );
+    }
+    // iterate through the levels
+    for ( i = 0; i <= nLevels; i++ )
+    {
+        // iterate through the nodes on each level
+        for ( pObj = (Abc_Obj_t *)Vec_PtrEntry(vNodes, i); pObj; pObj = pObj->pCopy )
+        {
+            // iterate through the fanouts of each node
+            Abc_ObjForEachFanout( pObj, pFanout, k )
+            {
+                // skip visited nodes
+                if ( Abc_NodeIsTravIdCurrent(pFanout) )
+                    continue;
+                // visit the fanins of this fanout
+                Abc_ObjForEachFanin( pFanout, pFanin, m )
+                {
+                    if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+                        break;
+                }
+                if ( m < Abc_ObjFaninNum(pFanout) )
+                    continue;
+                // all fanins are already collected
+
+                // mark the node as visited
+                Abc_NodeSetTravIdCurrent( pFanout );
+                // handle the COs
+                if ( Abc_ObjIsCo(pFanout) )
+                    pFanout->Level = nLevels + 1;
+                // add to the array
+                pFanout->pCopy = (Abc_Obj_t *)Vec_PtrEntry( vNodes, pFanout->Level );
+                Vec_PtrWriteEntry( vNodes, pFanout->Level, pFanout );
+                // handle the COs
+                if ( Abc_ObjIsCo(pFanout) )
+                    pFanout->Level = 0;
+            }
+        }
+    }
+    return vNodes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DFS for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDfsSeq_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    // if this node is already visited, skip
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return;
+    // mark the node as visited
+    Abc_NodeSetTravIdCurrent( pNode );
+    // visit the transitive fanin of the node
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        Abc_NtkDfsSeq_rec( pFanin, vNodes );
+    // add the node after the fanins have been added
+    Vec_PtrPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of nodes and latches reachable from POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsSeq( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj;
+    int i;
+    assert( !Abc_NtkIsNetlist(pNtk) );
+    // set the traversal ID
+    Abc_NtkIncrementTravId( pNtk );
+    // start the array of nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        Abc_NtkDfsSeq_rec( pObj, vNodes );
+    // mark the PIs
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        Abc_NtkDfsSeq_rec( pObj, vNodes );
+    return vNodes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DFS for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDfsSeqReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    // if this node is already visited, skip
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return;
+    // mark the node as visited
+    Abc_NodeSetTravIdCurrent( pNode );
+    // visit the transitive fanin of the node
+    Abc_ObjForEachFanout( pNode, pFanout, i )
+        Abc_NtkDfsSeqReverse_rec( pFanout, vNodes );
+    // add the node after the fanins have been added
+    Vec_PtrPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of nodes and latches reachable from POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsSeqReverse( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj;
+    int i;
+    assert( !Abc_NtkIsNetlist(pNtk) );
+    // set the traversal ID
+    Abc_NtkIncrementTravId( pNtk );
+    // start the array of nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        Abc_NtkDfsSeqReverse_rec( pObj, vNodes );
+    // mark the logic feeding into POs
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        Abc_NtkDfsSeq_rec( pObj, vNodes );
+    return vNodes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Iterative version of the DFS procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDfs_iter( Vec_Ptr_t * vStack, Abc_Obj_t * pRoot, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pNode, * pFanin;
+    int iFanin;
+    // if this node is already visited, skip
+    if ( Abc_NodeIsTravIdCurrent( pRoot ) )
+        return;
+    // mark the node as visited
+    Abc_NodeSetTravIdCurrent( pRoot );
+    // skip the CI
+    if ( Abc_ObjIsCi(pRoot) || (Abc_NtkIsStrash(pRoot->pNtk) && Abc_AigNodeIsConst(pRoot)) )
+        return;
+    // add the CI
+    Vec_PtrClear( vStack );
+    Vec_PtrPush( vStack, pRoot );
+    Vec_PtrPush( vStack, (void *)0 );
+    while ( Vec_PtrSize(vStack) > 0 )
+    {
+        // get the node and its fanin
+        iFanin = (int)(ABC_PTRINT_T)Vec_PtrPop(vStack);
+        pNode  = (Abc_Obj_t *)Vec_PtrPop(vStack);
+        assert( !Abc_ObjIsNet(pNode) );
+        // add it to the array of nodes if we finished
+        if ( iFanin == Abc_ObjFaninNum(pNode) )
+        {
+            Vec_PtrPush( vNodes, pNode );
+            continue;
+        }
+        // explore the next fanin
+        Vec_PtrPush( vStack, pNode );
+        Vec_PtrPush( vStack, (void *)(ABC_PTRINT_T)(iFanin+1) );
+        // get the fanin
+        pFanin = Abc_ObjFanin0Ntk( Abc_ObjFanin(pNode,iFanin) );
+        // if this node is already visited, skip
+        if ( Abc_NodeIsTravIdCurrent( pFanin ) )
+            continue;
+        // mark the node as visited
+        Abc_NodeSetTravIdCurrent( pFanin );
+        // skip the CI
+        if ( Abc_ObjIsCi(pFanin) || (Abc_NtkIsStrash(pFanin->pNtk) && Abc_AigNodeIsConst(pFanin)) )
+            continue;
+        Vec_PtrPush( vStack, pFanin );
+        Vec_PtrPush( vStack, (void *)0 );   
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the DFS ordered array of logic nodes.]
+
+  Description [Collects only the internal nodes, leaving CIs and CO.
+  However it marks with the current TravId both CIs and COs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll )
+{
+    Vec_Ptr_t * vNodes, * vStack;
+    Abc_Obj_t * pObj;
+    int i;
+    // set the traversal ID
+    Abc_NtkIncrementTravId( pNtk );
+    // start the array of nodes
+    vNodes = Vec_PtrAlloc( 1000 );
+    vStack = Vec_PtrAlloc( 1000 );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        Abc_NodeSetTravIdCurrent( pObj );
+        Abc_NtkDfs_iter( vStack, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes );
+    }
+    // collect dangling nodes if asked to
+    if ( fCollectAll )
+    { 
+        Abc_NtkForEachNode( pNtk, pObj, i )
+            if ( !Abc_NodeIsTravIdCurrent(pObj) )
+                Abc_NtkDfs_iter( vStack, pObj, vNodes );
+    }
+    Vec_PtrFree( vStack );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the DFS ordered array of logic nodes.]
+
+  Description [Collects only the internal nodes, leaving CIs and CO.
+  However it marks with the current TravId both CIs and COs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsIterNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots )
+{
+    Vec_Ptr_t * vNodes, * vStack;
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkIncrementTravId( pNtk );
+    vNodes = Vec_PtrAlloc( 1000 );
+    vStack = Vec_PtrAlloc( 1000 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+        if ( !Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pObj)) )
+            Abc_NtkDfs_iter( vStack, Abc_ObjRegular(pObj), vNodes );
+    Vec_PtrFree( vStack );
+    return vNodes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DFS for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDfsHie_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    // if this node is already visited, skip
+    if ( Abc_NodeIsTravIdCurrent( pObj ) )
+        return;
+    // mark the node as visited
+    Abc_NodeSetTravIdCurrent( pObj );
+    // visit the transitive fanin of the node
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        Abc_NtkDfsHie_rec( pFanin, vNodes );
+    // add the node after the fanins have been added
+    Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the DFS ordered array of all objects.]
+
+  Description [This procedure collects everything from POs to PIs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsHie( Abc_Ntk_t * pNtk, int fCollectAll )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj;
+    int i;
+    // set the traversal ID
+    Abc_NtkIncrementTravId( pNtk );
+    // start the array of nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        Abc_NtkDfsHie_rec( pObj, vNodes );
+    // collect dangling nodes if asked to
+    if ( fCollectAll )
+    {
+        Abc_NtkForEachObj( pNtk, pObj, i )
+            if ( !Abc_NodeIsTravIdCurrent(pObj) )
+                Abc_NtkDfs_rec( pObj, vNodes );
+    }
+    return vNodes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the ordering of nodes is DFS.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkIsDfsOrdered( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode, * pFanin;
+    int i, k;
+    // set the traversal ID
+    Abc_NtkIncrementTravId( pNtk );
+    // mark the CIs
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        Abc_NodeSetTravIdCurrent( pNode );
+    // go through the nodes
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        // check the fanins of the node
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+            if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+                return 0;
+        // check the choices of the node
+        if ( Abc_NtkIsStrash(pNtk) && Abc_AigNodeIsChoice(pNode) )
+            for ( pFanin = (Abc_Obj_t *)pNode->pData; pFanin; pFanin = (Abc_Obj_t *)pFanin->pData )
+                if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+                    return 0;
+        // mark the node as visited
+        Abc_NodeSetTravIdCurrent( pNode );
+    }
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DFS for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkNodeSupport_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    assert( !Abc_ObjIsNet(pNode) );
+    // if this node is already visited, skip
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return;
+    // mark the node as visited
+    Abc_NodeSetTravIdCurrent( pNode );
+    // collect the CI
+    if ( Abc_ObjIsCi(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_ObjFaninNum(pNode) == 0) )
+    {
+        Vec_PtrPush( vNodes, pNode );
+        return;
+    }
+    assert( Abc_ObjIsNode( pNode ) );
+    // visit the transitive fanin of the node
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        Abc_NtkNodeSupport_rec( Abc_ObjFanin0Ntk(pFanin), vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the set of CI nodes in the support of the given nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkSupport( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNode;
+    int i;
+    // set the traversal ID
+    Abc_NtkIncrementTravId( pNtk );
+    // start the array of nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    // go through the PO nodes and call for each of them
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        Abc_NtkNodeSupport_rec( Abc_ObjFanin0(pNode), vNodes );
+    // add unused CIs
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        if ( !Abc_NodeIsTravIdCurrent( pNode ) )
+            Vec_PtrPush( vNodes, pNode );
+    assert( Vec_PtrSize(vNodes) == Abc_NtkCiNum(pNtk) );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the set of CI nodes in the support of the given nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes )
+{
+    Vec_Ptr_t * vNodes;
+    int i;
+    // set the traversal ID
+    Abc_NtkIncrementTravId( pNtk );
+    // start the array of nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    // go through the PO nodes and call for each of them
+    for ( i = 0; i < nNodes; i++ )
+        if ( Abc_ObjIsCo(ppNodes[i]) )
+            Abc_NtkNodeSupport_rec( Abc_ObjFanin0(ppNodes[i]), vNodes );
+        else
+            Abc_NtkNodeSupport_rec( ppNodes[i], vNodes );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes support size of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ObjSuppSize_rec( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin;
+    int i, Counter = 0;
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return 0;
+    Abc_NodeSetTravIdCurrent(pObj);
+    if ( Abc_ObjIsPi(pObj) )
+        return 1;
+    assert( Abc_ObjIsNode(pObj) || Abc_ObjIsBox(pObj) );
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        Counter += Abc_ObjSuppSize_rec( pFanin );
+    return Counter;
+}
+/**Function*************************************************************
+
+  Synopsis    [Computes support size of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ObjSuppSize( Abc_Obj_t * pObj )
+{
+    Abc_NtkIncrementTravId( Abc_ObjNtk(pObj) );
+    return Abc_ObjSuppSize_rec( pObj );
+}
+/**Function*************************************************************
+
+  Synopsis    [Computes support size of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkSuppSizeTest( Abc_Ntk_t * p )
+{
+    Abc_Obj_t * pObj;
+    int i, Counter = 0;
+    abctime clk = Abc_Clock();
+    Abc_NtkForEachObj( p, pObj, i )
+        if ( Abc_ObjIsNode(pObj) )
+            Counter += (Abc_ObjSuppSize(pObj) <= 16);
+    printf( "Nodes with small support %d (out of %d)\n", Counter, Abc_NtkNodeNum(p) );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the sum total of supports of all outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSupportSum( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vSupp;
+    Abc_Obj_t * pObj;
+    int i, nTotalSupps = 0;
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
+        nTotalSupps += Vec_PtrSize( vSupp );
+        Vec_PtrFree( vSupp );
+    }
+    printf( "Total supports = %d.\n", nTotalSupps );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DFS for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AigDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    // if this node is already visited, skip
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return;
+    // mark the node as visited
+    Abc_NodeSetTravIdCurrent( pNode );
+    // skip the PI
+    if ( Abc_ObjIsCi(pNode) || Abc_AigNodeIsConst(pNode) )
+        return;
+    assert( Abc_ObjIsNode( pNode ) );
+    // visit the transitive fanin of the node
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        Abc_AigDfs_rec( pFanin, vNodes );
+    // visit the equivalent nodes
+    if ( Abc_AigNodeIsChoice( pNode ) )
+        for ( pFanin = (Abc_Obj_t *)pNode->pData; pFanin; pFanin = (Abc_Obj_t *)pFanin->pData )
+            Abc_AigDfs_rec( pFanin, vNodes );
+    // add the node after the fanins have been added
+    Vec_PtrPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the DFS ordered array of logic nodes.]
+
+  Description [Collects only the internal nodes, leaving out CIs/COs.
+  However it marks both CIs and COs with the current TravId.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll, int fCollectCos )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNode;
+    int i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // set the traversal ID
+    Abc_NtkIncrementTravId( pNtk );
+    // start the array of nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    // go through the PO nodes and call for each of them
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        Abc_AigDfs_rec( Abc_ObjFanin0(pNode), vNodes );
+        Abc_NodeSetTravIdCurrent( pNode );
+        if ( fCollectCos )
+            Vec_PtrPush( vNodes, pNode );
+    }
+    // collect dangling nodes if asked to
+    if ( fCollectAll )
+    {
+        Abc_NtkForEachNode( pNtk, pNode, i )
+            if ( !Abc_NodeIsTravIdCurrent(pNode) )
+                Abc_AigDfs_rec( pNode, vNodes );
+    }
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the DFS ordered array of logic nodes.]
+
+  Description [Collects only the internal nodes, leaving out CIs/COs.
+  However it marks both CIs and COs with the current TravId.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_AigDfsMap( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNode;
+    int i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // set the traversal ID
+    Abc_NtkIncrementTravId( pNtk );
+    // start the array of nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    // collect cones of barbufs
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        if ( i < Abc_NtkCoNum(pNtk) - pNtk->nBarBufs )
+            continue;
+        Abc_AigDfs_rec( Abc_ObjFanin0(pNode), vNodes );
+        Abc_NodeSetTravIdCurrent( pNode );
+        // collect latch as a placeholder
+        assert( Abc_ObjIsLatch(Abc_ObjFanout0(pNode)) );
+        Vec_PtrPush( vNodes, Abc_ObjFanout0(pNode) );
+    }
+    // collect nodes of real POs
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        if ( i >= Abc_NtkCoNum(pNtk) - pNtk->nBarBufs )
+            break;
+        Abc_AigDfs_rec( Abc_ObjFanin0(pNode), vNodes );
+        assert( Abc_ObjIsCo(pNode) );
+        Abc_NodeSetTravIdCurrent( pNode );
+    }
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes in the DFS manner by level.]
+
+  Description [The number of levels should be set!!!]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Vec_t * vLevels )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    // if this node is already visited, skip
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return;
+    // mark the node as visited
+    Abc_NodeSetTravIdCurrent( pNode );
+    // skip the terminals
+    if ( Abc_ObjIsCo(pNode) )
+        return;
+    assert( Abc_ObjIsNode(pNode) );
+    // add the node to the structure
+    Vec_VecPush( vLevels, pNode->Level, pNode );
+    // visit the TFO
+    Abc_ObjForEachFanout( pNode, pFanout, i )
+        Abc_DfsLevelizedTfo_rec( pFanout, vLevels );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes in the DFS manner by level.]
+
+  Description [The number of levels should be set!!!]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, int fTfi )
+{
+    Vec_Vec_t * vLevels;
+    Abc_Obj_t * pFanout;
+    int i;
+    assert( fTfi == 0 );
+    assert( !Abc_NtkIsNetlist(pNode->pNtk) );
+    // set the traversal ID
+    Abc_NtkIncrementTravId( pNode->pNtk );
+    vLevels = Vec_VecAlloc( 100 );
+    if ( Abc_ObjIsNode(pNode) )
+        Abc_DfsLevelizedTfo_rec( pNode, vLevels );
+    else
+    {
+        assert( Abc_ObjIsCi(pNode) );
+        Abc_NodeSetTravIdCurrent( pNode );
+        Abc_ObjForEachFanout( pNode, pFanout, i )
+            Abc_DfsLevelizedTfo_rec( pFanout, vLevels );
+    }
+    return vLevels;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively counts the number of logic levels of one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkLevel_rec( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pNext;
+    int i, Level;
+    assert( !Abc_ObjIsNet(pNode) );
+    // skip the PI
+    if ( Abc_ObjIsCi(pNode) )
+        return pNode->Level;
+    assert( Abc_ObjIsNode( pNode ) || pNode->Type == ABC_OBJ_CONST1);
+    // if this node is already visited, return
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return pNode->Level;
+    // mark the node as visited
+    Abc_NodeSetTravIdCurrent( pNode );
+    // visit the transitive fanin
+    pNode->Level = 0;
+    Abc_ObjForEachFanin( pNode, pNext, i )
+    {
+        Level = Abc_NtkLevel_rec( Abc_ObjFanin0Ntk(pNext) );
+        if ( pNode->Level < (unsigned)Level )
+            pNode->Level = Level;
+    }
+    if ( Abc_ObjFaninNum(pNode) > 0 )
+        pNode->Level++;
+    return pNode->Level;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively counts the number of logic levels of one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkLevelReverse_rec( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pNext;
+    int i, Level;
+    assert( !Abc_ObjIsNet(pNode) );
+    // skip the PI
+    if ( Abc_ObjIsCo(pNode) )
+        return pNode->Level;
+    assert( Abc_ObjIsNode( pNode ) || pNode->Type == ABC_OBJ_CONST1);
+    // if this node is already visited, return
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return pNode->Level;
+    // mark the node as visited
+    Abc_NodeSetTravIdCurrent( pNode );
+    // visit the transitive fanin
+    pNode->Level = 0;
+    Abc_ObjForEachFanout( pNode, pNext, i )
+    {
+        Level = Abc_NtkLevelReverse_rec( Abc_ObjFanout0Ntk(pNext) );
+        if ( pNode->Level < (unsigned)Level )
+            pNode->Level = Level;
+    }
+    if ( Abc_ObjFaninNum(pNode) > 0 )
+        pNode->Level++;
+    return pNode->Level;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the number of logic levels not counting PIs/POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Abc_NtkLevelize( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    Vec_Vec_t * vLevels;
+    int nLevels, i;
+    nLevels = Abc_NtkLevel( pNtk );
+    vLevels = Vec_VecStart( nLevels + 1 );
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        assert( (int)pObj->Level <= nLevels );
+        Vec_VecPush( vLevels, pObj->Level, pObj );
+    }
+    return vLevels;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the number of logic levels not counting PIs/POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkLevel( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, LevelsMax;
+    // set the CI levels
+    if ( pNtk->pManTime == NULL || pNtk->AndGateDelay <= 0 )
+        Abc_NtkForEachCi( pNtk, pNode, i )
+            pNode->Level = 0;
+    else
+        Abc_NtkForEachCi( pNtk, pNode, i )
+            pNode->Level = (int)(Abc_NodeReadArrivalWorst(pNode) / pNtk->AndGateDelay);
+    // perform the traversal
+    LevelsMax = 0;
+    Abc_NtkIncrementTravId( pNtk );
+    if ( pNtk->nBarBufs == 0 )
+    {
+        Abc_NtkForEachNode( pNtk, pNode, i )
+        {
+            Abc_NtkLevel_rec( pNode );
+            if ( LevelsMax < (int)pNode->Level )
+                LevelsMax = (int)pNode->Level;
+        }
+    }
+    else
+    {
+        Abc_NtkForEachLiPo( pNtk, pNode, i )
+        {
+            Abc_Obj_t * pDriver = Abc_ObjFanin0(pNode);
+            Abc_NtkLevel_rec( pDriver );
+            if ( LevelsMax < (int)pDriver->Level )
+                LevelsMax = (int)pDriver->Level;
+            // transfer the delay
+            if ( i < pNtk->nBarBufs )
+                Abc_ObjFanout0(Abc_ObjFanout0(pNode))->Level = pDriver->Level;
+        }
+    }
+    return LevelsMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the number of logic levels not counting PIs/POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkLevelReverse( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, LevelsMax;
+    // set the CO levels to zero
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        pNode->Level = 0;
+    // perform the traversal
+    LevelsMax = 0;
+    Abc_NtkIncrementTravId( pNtk );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        Abc_NtkLevelReverse_rec( pNode );
+        if ( LevelsMax < (int)pNode->Level )
+            LevelsMax = (int)pNode->Level;
+    }
+    return LevelsMax;
+}
+
+ 
+/**Function*************************************************************
+
+  Synopsis    [Recursively detects combinational loops.]
+
+  Description []
+                
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode )
+{
+    Abc_Ntk_t * pNtk = pNode->pNtk;
+    Abc_Obj_t * pFanin;
+    int fAcyclic, i;
+    assert( !Abc_ObjIsNet(pNode) );
+    if ( Abc_ObjIsCi(pNode) || Abc_ObjIsBox(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsConst(pNode)) )
+        return 1;
+    assert( Abc_ObjIsNode(pNode) );
+    // make sure the node is not visited
+    assert( !Abc_NodeIsTravIdPrevious(pNode) );
+    // check if the node is part of the combinational loop
+    if ( Abc_NodeIsTravIdCurrent(pNode) )
+    {
+        fprintf( stdout, "Network \"%s\" contains combinational loop!\n", Abc_NtkName(pNtk) );
+        fprintf( stdout, "Node \"%s\" is encountered twice on the following path to the COs:\n", Abc_ObjName(pNode) );
+        return 0;
+    }
+    // mark this node as a node on the current path
+    Abc_NodeSetTravIdCurrent( pNode );
+    // visit the transitive fanin
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    { 
+        pFanin = Abc_ObjFanin0Ntk(pFanin);
+        // make sure there is no mixing of networks
+        assert( pFanin->pNtk == pNode->pNtk );
+        // check if the fanin is visited
+        if ( Abc_NodeIsTravIdPrevious(pFanin) ) 
+            continue;
+        // traverse the fanin's cone searching for the loop
+        if ( (fAcyclic = Abc_NtkIsAcyclic_rec(pFanin)) )
+            continue;
+        // return as soon as the loop is detected
+        fprintf( stdout, " %s ->", Abc_ObjName(pFanin) );
+        return 0;
+    }
+    // visit choices
+    if ( Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsChoice(pNode) )
+    {
+        for ( pFanin = (Abc_Obj_t *)pNode->pData; pFanin; pFanin = (Abc_Obj_t *)pFanin->pData )
+        {
+            // check if the fanin is visited
+            if ( Abc_NodeIsTravIdPrevious(pFanin) ) 
+                continue;
+            // traverse the fanin's cone searching for the loop
+            if ( (fAcyclic = Abc_NtkIsAcyclic_rec(pFanin)) )
+                continue;
+            // return as soon as the loop is detected
+            fprintf( stdout, " %s", Abc_ObjName(pFanin) );
+            fprintf( stdout, " (choice of %s) -> ", Abc_ObjName(pNode) );
+            return 0;
+        }
+    }
+    // mark this node as a visited node
+    Abc_NodeSetTravIdPrevious( pNode );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detects combinational loops.]
+
+  Description [This procedure is based on the idea suggested by Donald Chai. 
+  As we traverse the network and visit the nodes, we need to distinquish 
+  three types of nodes: (1) those that are visited for the first time, 
+  (2) those that have been visited in this traversal but are currently not 
+  on the traversal path, (3) those that have been visited and are currently 
+  on the travesal path. When the node of type (3) is encountered, it means 
+  that there is a combinational loop. To mark the three types of nodes, 
+  two new values of the traversal IDs are used.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int fAcyclic;
+    int i;
+    // set the traversal ID for this DFS ordering
+    Abc_NtkIncrementTravId( pNtk );   
+    Abc_NtkIncrementTravId( pNtk );   
+    // pNode->TravId == pNet->nTravIds      means "pNode is on the path"
+    // pNode->TravId == pNet->nTravIds - 1  means "pNode is visited but is not on the path"
+    // pNode->TravId <  pNet->nTravIds - 1  means "pNode is not visited"
+    // traverse the network to detect cycles
+    fAcyclic = 1;
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        pNode = Abc_ObjFanin0Ntk(Abc_ObjFanin0(pNode));
+        if ( Abc_NodeIsTravIdPrevious(pNode) )
+            continue;
+        // traverse the output logic cone
+        if ( (fAcyclic = Abc_NtkIsAcyclic_rec(pNode)) )
+            continue;
+        // stop as soon as the first loop is detected
+        fprintf( stdout, " CO \"%s\"\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+        break;
+    }
+    return fAcyclic;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Analyses choice nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeSetChoiceLevel_rec( Abc_Obj_t * pNode, int fMaximum )
+{
+    Abc_Obj_t * pTemp;
+    int Level1, Level2, Level, LevelE;
+    // skip the visited node
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return (int)(ABC_PTRINT_T)pNode->pCopy;
+    Abc_NodeSetTravIdCurrent( pNode );
+    // compute levels of the children nodes
+    Level1 = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin0(pNode), fMaximum );
+    Level2 = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin1(pNode), fMaximum );
+    Level  = 1 + Abc_MaxInt( Level1, Level2 );
+    if ( pNode->pData )
+    {
+        LevelE = Abc_NodeSetChoiceLevel_rec( (Abc_Obj_t *)pNode->pData, fMaximum );
+        if ( fMaximum )
+            Level = Abc_MaxInt( Level, LevelE );
+        else
+            Level = Abc_MinInt( Level, LevelE );
+        // set the level of all equivalent nodes to be the same minimum
+        for ( pTemp = (Abc_Obj_t *)pNode->pData; pTemp; pTemp = (Abc_Obj_t *)pTemp->pData )
+            pTemp->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Level;
+    }
+    pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Level;
+    return Level;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resets the levels of the nodes in the choice graph.]
+
+  Description [Makes the level of the choice nodes to be equal to the
+  maximum of the level of the nodes in the equivalence class. This way
+  sorting by level leads to the reverse topological order, which is
+  needed for the required time computation.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_AigSetChoiceLevels( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i, LevelMax, LevelCur;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // set the new travid counter
+    Abc_NtkIncrementTravId( pNtk );
+    // set levels of the CI and constant
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        Abc_NodeSetTravIdCurrent( pObj );
+        pObj->pCopy = NULL;
+    }
+    pObj = Abc_AigConst1( pNtk );
+    Abc_NodeSetTravIdCurrent( pObj );
+    pObj->pCopy = NULL;
+    // set levels of all other nodes
+    LevelMax = 0;
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        LevelCur = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin0(pObj), 1 );
+        LevelMax = Abc_MaxInt( LevelMax, LevelCur );
+    }
+    return LevelMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns nodes by level from the smallest to the largest.]
+
+  Description [Correctly handles the case of choice nodes, by first
+  spreading them out across several levels and then collecting.]
+               
+  SideEffects [What happens with dangling nodes???]
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis )
+{
+    Vec_Ptr_t * vNodes, * vLevels;
+    Abc_Obj_t * pNode, ** ppHead;
+    int LevelMax, i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // set the correct levels
+    Abc_NtkCleanCopy( pNtk );
+    LevelMax = Abc_AigSetChoiceLevels( pNtk );
+    // relink nodes by level
+    vLevels = Vec_PtrStart( LevelMax + 1 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        ppHead = ((Abc_Obj_t **)vLevels->pArray) + (int)(ABC_PTRINT_T)pNode->pCopy;
+        pNode->pCopy = *ppHead;
+        *ppHead = pNode;
+    }
+    // recollect nodes
+    vNodes = Vec_PtrStart( Abc_NtkNodeNum(pNtk) );
+    Vec_PtrForEachEntryStart( Abc_Obj_t *, vLevels, pNode, i, !fCollectCis )
+        for ( ; pNode; pNode = pNode->pCopy )
+            Vec_PtrPush( vNodes, pNode );
+    Vec_PtrFree( vLevels );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of nodes in the subgraph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ObjSugraphSize( Abc_Obj_t * pObj )
+{
+    if ( Abc_ObjIsCi(pObj) )
+        return 0;
+    if ( Abc_ObjFanoutNum(pObj) > 1 )
+        return 0;
+    return 1 + Abc_ObjSugraphSize(Abc_ObjFanin0(pObj)) + 
+        Abc_ObjSugraphSize(Abc_ObjFanin1(pObj));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints subgraphs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkPrintSubraphSizes( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        if ( Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsExorType(pObj) )
+            printf( "%d(%d) ", 1 + Abc_ObjSugraphSize(Abc_ObjFanin0(pObj)) + 
+                Abc_ObjSugraphSize(Abc_ObjFanin1(pObj)), Abc_ObjFanoutNum(pObj) );
+    printf( "\n" );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcFanOrder.c b/abc-build/src/base/abc/abcFanOrder.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcFanOrder.c
@@ -0,0 +1,479 @@
+/**CFile****************************************************************
+
+  FileName    [abcFanOrder.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Fanin ordering procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcFanOrder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reorder fanins of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkOrderFaninsById( Abc_Ntk_t * pNtk )
+{
+    Vec_Int_t * vOrder;
+    Vec_Str_t * vStore;
+    Abc_Obj_t * pNode;
+    char * pSop, * pSopNew;
+    char * pCube, * pCubeNew;
+    int nVars, i, v, * pOrder;
+    assert( Abc_NtkHasSop(pNtk) );
+    vOrder = Vec_IntAlloc( 100 );
+    vStore = Vec_StrAlloc( 100 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        pSop = (char *)pNode->pData;
+        nVars = Abc_SopGetVarNum(pSop);
+        assert( nVars == Abc_ObjFaninNum(pNode) );
+        Vec_IntClear( vOrder );
+        for ( v = 0; v < nVars; v++ )
+            Vec_IntPush( vOrder, v );
+        pOrder = Vec_IntArray(vOrder);
+        Vec_IntSelectSortCost( pOrder, nVars, &pNode->vFanins );
+        // copy the cover
+        Vec_StrGrow( vStore, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 );
+        memcpy( Vec_StrArray(vStore), pSop, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 );
+        pSopNew = pCubeNew = pSop;
+        pSop = Vec_StrArray(vStore);
+        // generate permuted one
+        Abc_SopForEachCube( pSop, nVars, pCube )
+        {
+            for ( v = 0; v < nVars; v++ )
+                pCubeNew[v] = '-';
+            for ( v = 0; v < nVars; v++ )
+                if ( pCube[pOrder[v]] == '0' )
+                    pCubeNew[v] = '0';
+                else if ( pCube[pOrder[v]] == '1' )
+                    pCubeNew[v] = '1';
+            pCubeNew += nVars + 3;
+        }
+        pNode->pData = pSopNew;
+        Vec_IntSort( &pNode->vFanins, 0 );
+//        Vec_IntPrint( vOrder );
+    }
+    Vec_IntFree( vOrder );
+    Vec_StrFree( vStore );
+}
+void Abc_NtkOrderFaninsByLitCount( Abc_Ntk_t * pNtk )
+{
+    Vec_Int_t * vOrder;
+    Vec_Int_t * vCounts;
+    Vec_Int_t * vFanins;
+    Vec_Str_t * vStore;
+    Abc_Obj_t * pNode;
+    char * pSop, * pSopNew;
+    char * pCube, * pCubeNew;
+    int nVars, i, v, * pOrder;
+    assert( Abc_NtkHasSop(pNtk) );
+    vOrder = Vec_IntAlloc( 100 );
+    vStore = Vec_StrAlloc( 100 );
+    vCounts = Vec_IntAlloc( 100 );
+    vFanins = Vec_IntAlloc( 100 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        pSop = (char *)pNode->pData;
+        nVars = Abc_SopGetVarNum(pSop);
+        assert( nVars == Abc_ObjFaninNum(pNode) );
+        // count literals
+        Vec_IntFill( vCounts, nVars, 0 );
+        Abc_SopForEachCube( pSop, nVars, pCube )
+            for ( v = 0; v < nVars; v++ )
+                if ( pCube[v] != '-' )
+                    Vec_IntAddToEntry( vCounts, v, 1 );
+        // find good order
+        Vec_IntClear( vOrder );
+        for ( v = 0; v < nVars; v++ )
+            Vec_IntPush( vOrder, v );
+        pOrder = Vec_IntArray(vOrder);
+        Vec_IntSelectSortCost( pOrder, nVars, vCounts );
+        // copy the cover
+        Vec_StrGrow( vStore, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 );
+        memcpy( Vec_StrArray(vStore), pSop, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 );
+        pSopNew = pCubeNew = pSop;
+        pSop = Vec_StrArray(vStore);
+        // generate permuted one
+        Abc_SopForEachCube( pSop, nVars, pCube )
+        {
+            for ( v = 0; v < nVars; v++ )
+                pCubeNew[v] = '-';
+            for ( v = 0; v < nVars; v++ )
+                if ( pCube[pOrder[v]] == '0' )
+                    pCubeNew[v] = '0';
+                else if ( pCube[pOrder[v]] == '1' )
+                    pCubeNew[v] = '1';
+            pCubeNew += nVars + 3;
+        }
+        pNode->pData = pSopNew;
+        // generate the fanin order
+        Vec_IntClear( vFanins );
+        for ( v = 0; v < nVars; v++ )
+            Vec_IntPush( vFanins, Abc_ObjFaninId( pNode, pOrder[v] ) );
+        Vec_IntClear( &pNode->vFanins );
+        Vec_IntAppend( &pNode->vFanins, vFanins );
+    }
+    Vec_IntFree( vFanins );
+    Vec_IntFree( vCounts );
+    Vec_IntFree( vOrder );
+    Vec_StrFree( vStore );
+}
+void Abc_NtkOrderFaninsByLitCountAndCubeCount( Abc_Ntk_t * pNtk )
+{
+    // assuming that the fanins are sorted by the number of literals in each cube
+    // this procedure sorts the literals appearing only once by the number of their cube
+    Vec_Int_t * vOrder;
+    Vec_Int_t * vCounts;
+    Vec_Int_t * vFanins;
+    Vec_Int_t * vCubeNum;
+    Vec_Str_t * vStore;
+    Abc_Obj_t * pNode;
+    char * pSop, * pSopNew;
+    char * pCube, * pCubeNew;
+    int nVars, i, v, iCube, * pOrder;
+    assert( Abc_NtkHasSop(pNtk) );
+    vStore = Vec_StrAlloc( 100 );
+    vOrder = Vec_IntAlloc( 100 );
+    vCounts = Vec_IntAlloc( 100 );
+    vFanins = Vec_IntAlloc( 100 );
+    vCubeNum = Vec_IntAlloc( 100 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        pSop = (char *)pNode->pData;
+        nVars = Abc_SopGetVarNum(pSop);
+        assert( nVars == Abc_ObjFaninNum(pNode) );
+        // count literals and remember the cube where each literal appears
+        Vec_IntFill( vCounts, nVars, 0 );
+        Vec_IntFill( vCubeNum, nVars, 0 );
+        iCube = 0;
+        Abc_SopForEachCube( pSop, nVars, pCube )
+        {
+            for ( v = 0; v < nVars; v++ )
+                if ( pCube[v] != '-' )
+                {
+                    Vec_IntAddToEntry( vCounts, v, 1 );
+                    Vec_IntWriteEntry( vCubeNum, v, iCube );
+                }
+            iCube++;
+        }
+        // create new order
+        for ( v = 0; v < nVars; v++ )
+            if ( Vec_IntEntry(vCounts, v) == 1 )
+                Vec_IntWriteEntry( vCounts, v, Vec_IntEntry(vCubeNum, v) );
+            else
+                Vec_IntWriteEntry( vCounts, v, ABC_INFINITY );
+        // find good order
+        Vec_IntClear( vOrder );
+        for ( v = 0; v < nVars; v++ )
+            Vec_IntPush( vOrder, v );
+        pOrder = Vec_IntArray(vOrder);
+        Vec_IntSelectSortCost( pOrder, nVars, vCounts );
+        // copy the cover
+        Vec_StrGrow( vStore, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 );
+        memcpy( Vec_StrArray(vStore), pSop, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 );
+        pSopNew = pCubeNew = pSop;
+        pSop = Vec_StrArray(vStore);
+        // generate permuted one
+        Abc_SopForEachCube( pSop, nVars, pCube )
+        {
+            for ( v = 0; v < nVars; v++ )
+                pCubeNew[v] = '-';
+            for ( v = 0; v < nVars; v++ )
+                if ( pCube[pOrder[v]] == '0' )
+                    pCubeNew[v] = '0';
+                else if ( pCube[pOrder[v]] == '1' )
+                    pCubeNew[v] = '1';
+            pCubeNew += nVars + 3;
+        }
+        pNode->pData = pSopNew;
+        // generate the fanin order
+        Vec_IntClear( vFanins );
+        for ( v = 0; v < nVars; v++ )
+            Vec_IntPush( vFanins, Abc_ObjFaninId( pNode, pOrder[v] ) );
+        Vec_IntClear( &pNode->vFanins );
+        Vec_IntAppend( &pNode->vFanins, vFanins );
+    }
+    Vec_IntFree( vCubeNum );
+    Vec_IntFree( vFanins );
+    Vec_IntFree( vCounts );
+    Vec_IntFree( vOrder );
+    Vec_StrFree( vStore );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Split large nodes by dividing their SOPs in half.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeSplitLarge( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pNode1, * pNode2, * pFanin;
+    int CutPoint, nVars = Abc_ObjFaninNum(pNode);
+    int i, nCubes = Abc_SopGetCubeNum((char *)pNode->pData);
+    pNode1 = Abc_NtkDupObj( pNode->pNtk, pNode, 0 );
+    pNode2 = Abc_NtkDupObj( pNode->pNtk, pNode, 0 );
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        Abc_ObjAddFanin( pNode1, pFanin );
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        Abc_ObjAddFanin( pNode2, pFanin );    
+    // update the node
+    Abc_ObjRemoveFanins( pNode );
+    Abc_ObjAddFanin( pNode, pNode1 );
+    Abc_ObjAddFanin( pNode, pNode2 );
+    pNode->pData = Abc_SopCreateOr( (Mem_Flex_t *)pNode->pNtk->pManFunc, 2, NULL );
+    // update covers of the nodes
+    assert( nCubes > 1 );
+    CutPoint = (nCubes / 2) * (nVars + 3);
+    ((char *)pNode1->pData)[CutPoint] = 0;
+    pNode2->pData = (char *)pNode2->pData + CutPoint;
+}
+void Abc_NtkSplitLarge( Abc_Ntk_t * pNtk, int nFaninsMax, int nCubesMax )
+{
+    Abc_Obj_t * pNode;
+    int nObjOld = Abc_NtkObjNumMax(pNtk);
+    int i, nCubes;
+    assert( Abc_NtkHasSop(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        if ( i == nObjOld )
+            break;
+        nCubes = Abc_SopGetCubeNum((char *)pNode->pData);
+        if ( (Abc_ObjFaninNum(pNode) > nFaninsMax && nCubes > 1) || nCubes > nCubesMax )
+            Abc_NodeSplitLarge( pNode );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts the cubes in a topological order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCompareCubes( char ** pp1, char ** pp2 )
+{
+    return strcmp( *pp1, *pp2 );
+}
+void Abc_NodeSortCubes( Abc_Obj_t * pNode, Vec_Ptr_t * vCubes, Vec_Str_t * vStore )
+{
+    char * pCube, * pPivot;
+    char * pSop = (char *)pNode->pData;
+    int i, nVars = Abc_ObjFaninNum(pNode);
+    Vec_PtrClear( vCubes );
+    Abc_SopForEachCube( pSop, nVars, pCube )
+    {
+        assert( pCube[nVars] == ' ' );
+        pCube[nVars] = 0;
+        Vec_PtrPush( vCubes, pCube );
+    }
+    Vec_PtrSort( vCubes, (int (*)())Abc_NodeCompareCubes );
+    Vec_StrGrow( vStore, Vec_PtrSize(vCubes) * (nVars + 3) );
+    pPivot = Vec_StrArray( vStore );
+    Vec_PtrForEachEntry( char *, vCubes, pCube, i )
+    {
+        assert( pCube[nVars] == 0 );
+        pCube[nVars] = ' ';
+        memcpy( pPivot, pCube, nVars + 3 );
+        pPivot += nVars + 3;
+    }
+    memcpy( pSop, Vec_StrArray(vStore), Vec_PtrSize(vCubes) * (nVars + 3) );
+}
+void Abc_NtkSortCubes( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vCubes;
+    Vec_Str_t * vStore;
+    Abc_Obj_t * pNode;
+    int i;
+    assert( Abc_NtkHasSop(pNtk) );
+    vCubes = Vec_PtrAlloc( 1000 );
+    vStore = Vec_StrAlloc( 1000 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        Abc_NodeSortCubes( pNode, vCubes, vStore );
+    Vec_StrFree( vStore );
+    Vec_PtrFree( vCubes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts fanins of each node to make SOPs more readable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSortSops( Abc_Ntk_t * pNtk )
+{
+    Abc_NtkOrderFaninsByLitCount( pNtk );
+    Abc_NtkSortCubes( pNtk );
+    Abc_NtkOrderFaninsByLitCountAndCubeCount( pNtk );
+    Abc_NtkSortCubes( pNtk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Makes cover legitimate for "fast_extract".]
+
+  Description [Iteratively removes distance-1 and contained cubes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_CubeContain( char * pCube1, char * pCube2, int nVars )
+{
+    int v, fCont12 = 1, fCont21 = 1;
+    for ( v = 0; v < nVars; v++ )
+    {
+        if ( pCube1[v] == pCube2[v] )
+            continue;
+        if ( pCube1[v] == '-' )
+            fCont21 = 0;
+        else if ( pCube2[v] == '-' )
+            fCont12 = 0;
+        else
+            return 0;
+        if ( !fCont21 && !fCont21 )
+            return 0;
+    }
+    assert( fCont21 || fCont12 );
+    return (fCont21 << 1) | fCont12;
+}
+int Abc_NodeMakeSCCFree( Abc_Obj_t * pNode )
+{
+    char * pSop = (char *)pNode->pData;
+    char * pCube, * pCube2, * pSopNew;
+    int nVars = Abc_ObjFaninNum(pNode);
+    int Status, nCount = 0;
+    Abc_SopForEachCubePair( pSop, nVars, pCube, pCube2 )
+    {
+        if ( pCube[0] == 'z' || pCube2[0] == 'z' )
+            continue;
+        Status = Abc_CubeContain( pCube, pCube2, nVars );
+        nCount += (int)(Status > 0);
+        if ( Status & 1 )
+            pCube2[0] = 'z';
+        else if ( Status & 2 )
+            pCube[0] = 'z';
+    }
+    if ( nCount == 0 )
+        return 0;
+    // create new cover
+    pSopNew = (char *)pNode->pData;
+    Abc_SopForEachCube( pSop, nVars, pCube )
+    {
+        if ( pCube[0] == 'z' )
+            continue;
+        memcpy( pSopNew, pCube, nVars + 3 );
+        pSopNew += nVars + 3;
+    }
+    *pSopNew = 0;
+    return 1;
+}
+void Abc_NodeMakeDist1Free( Abc_Obj_t * pNode )
+{
+    char * pSop = (char *)pNode->pData;
+    char * pCube, * pCube2;
+    int i, nVars = Abc_ObjFaninNum(pNode);
+    Abc_SopForEachCube( pSop, nVars, pCube )
+    Abc_SopForEachCube( pCube + nVars + 3, nVars, pCube2 )
+    {
+        int Counter = 0, iDiff = -1;
+        for ( i = 0; i < nVars; i++ )
+            if ( pCube[i] != pCube2[i] )
+                Counter++, iDiff = i;
+        if ( Counter == 1 && ((pCube[iDiff] == '0' && pCube2[iDiff] == '1') || (pCube[iDiff] == '1' && pCube2[iDiff] == '0')) )
+            pCube[iDiff] = pCube2[iDiff] = '-';
+    }
+}
+void Abc_NodeCheckDist1Free( Abc_Obj_t * pNode )
+{
+    char * pSop = (char *)pNode->pData;
+    char * pCube, * pCube2;
+    int i, nVars = Abc_ObjFaninNum(pNode);
+    Abc_SopForEachCube( pSop, nVars, pCube )
+    Abc_SopForEachCube( pSop, nVars, pCube2 )
+    {
+        int Counter = 0;
+        if ( pCube == pCube2 )
+            continue;
+        for ( i = 0; i < nVars; i++ )
+            if ( pCube[i] != pCube2[i] )
+                Counter++;
+        assert( Counter > 1 );
+    }
+}
+int Abc_NodeMakeLegit( Abc_Obj_t * pNode )
+{
+    int i, fChanges = 1;
+    for ( i = 0; fChanges; i++ )
+    {
+        Abc_NodeMakeDist1Free( pNode );
+        fChanges = Abc_NodeMakeSCCFree( pNode );
+    }
+//    Abc_NodeCheckDist1Free( pNode );
+    return i > 1;
+}
+int Abc_NtkMakeLegit( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, Counter = 0;
+    assert( Abc_NtkHasSop(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        Counter += Abc_NodeMakeLegit( pNode );
+    if ( Counter )
+        Abc_Print( 0, "%d nodes were made dist1-cube-free and/or single-cube-containment-free.\n", Counter );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcFanio.c b/abc-build/src/base/abc/abcFanio.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcFanio.c
@@ -0,0 +1,338 @@
+/**CFile****************************************************************
+
+  FileName    [abcFanio.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Various procedures to connect fanins/fanouts.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcFanio.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntPushMem( Mem_Step_t * pMemMan, Vec_Int_t * p, int Entry )
+{
+    if ( p->nSize == p->nCap )
+    {
+        int * pArray;
+        int i;
+
+        if ( p->nSize == 0 )
+            p->nCap = 1;
+        if ( pMemMan )
+            pArray = (int *)Mem_StepEntryFetch( pMemMan, p->nCap * 8 );
+        else
+            pArray = ABC_ALLOC( int, p->nCap * 2 );
+        if ( p->pArray )
+        {
+            for ( i = 0; i < p->nSize; i++ )
+                pArray[i] = p->pArray[i];
+            if ( pMemMan )
+                Mem_StepEntryRecycle( pMemMan, (char *)p->pArray, p->nCap * 4 );
+            else
+                ABC_FREE( p->pArray );
+        }
+        p->nCap *= 2;
+        p->pArray = pArray;
+    }
+    p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates fanout/fanin relationship between the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin )
+{
+    Abc_Obj_t * pFaninR = Abc_ObjRegular(pFanin);
+    assert( !Abc_ObjIsComplement(pObj) );
+    assert( pObj->pNtk == pFaninR->pNtk );
+    assert( pObj->Id >= 0 && pFaninR->Id >= 0 );
+    assert( !Abc_ObjIsPi(pObj) && !Abc_ObjIsPo(pFaninR) );    // fanin of PI or fanout of PO
+    assert( !Abc_ObjIsCo(pObj) || !Abc_ObjFaninNum(pObj) );  // CO with two fanins
+    assert( !Abc_ObjIsNet(pObj) || !Abc_ObjFaninNum(pObj) ); // net with two fanins
+    Vec_IntPushMem( pObj->pNtk->pMmStep, &pObj->vFanins,     pFaninR->Id );
+    Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninR->vFanouts, pObj->Id    );
+    if ( Abc_ObjIsComplement(pFanin) )
+        Abc_ObjSetFaninC( pObj, Abc_ObjFaninNum(pObj)-1 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Destroys fanout/fanin relationship between the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin )
+{
+    assert( !Abc_ObjIsComplement(pObj) );
+    assert( !Abc_ObjIsComplement(pFanin) );
+    assert( pObj->pNtk == pFanin->pNtk );
+    assert( pObj->Id >= 0 && pFanin->Id >= 0 );
+    if ( !Vec_IntRemove( &pObj->vFanins, pFanin->Id ) )
+    {
+        printf( "The obj %d is not found among the fanins of obj %d ...\n", pFanin->Id, pObj->Id );
+        return;
+    }
+    if ( !Vec_IntRemove( &pFanin->vFanouts, pObj->Id ) )
+    {
+        printf( "The obj %d is not found among the fanouts of obj %d ...\n", pObj->Id, pFanin->Id );
+        return;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Destroys fanout/fanin relationship between the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ObjRemoveFanins( Abc_Obj_t * pObj )
+{
+    Vec_Int_t * vFaninsOld;
+    Abc_Obj_t * pFanin;
+    int k;
+    // remove old fanins
+    vFaninsOld = &pObj->vFanins;
+    for ( k = vFaninsOld->nSize - 1; k >= 0; k-- )
+    {
+        pFanin = Abc_NtkObj( pObj->pNtk, vFaninsOld->pArray[k] );
+        Abc_ObjDeleteFanin( pObj, pFanin );
+    }
+    pObj->fCompl0 = 0;
+    pObj->fCompl1 = 0;
+    assert( vFaninsOld->nSize == 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces a fanin of the node.]
+
+  Description [The node is pObj. An old fanin of this node (pFaninOld) has to be
+  replaced by a new fanin (pFaninNew). Assumes that the node and the old fanin 
+  are not complemented. The new fanin can be complemented. In this case, the
+  polarity of the new fanin will change, compared to the polarity of the old fanin.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFaninNew )
+{
+    Abc_Obj_t * pFaninNewR = Abc_ObjRegular(pFaninNew);
+    int iFanin;//, nLats;//, fCompl;
+    assert( !Abc_ObjIsComplement(pObj) );
+    assert( !Abc_ObjIsComplement(pFaninOld) );
+    assert( pFaninOld != pFaninNewR );
+//    assert( pObj != pFaninOld );
+//    assert( pObj != pFaninNewR );
+    assert( pObj->pNtk == pFaninOld->pNtk );
+    assert( pObj->pNtk == pFaninNewR->pNtk );
+    if ( (iFanin = Vec_IntFind( &pObj->vFanins, pFaninOld->Id )) == -1 )
+    {
+        printf( "Node %s is not among", Abc_ObjName(pFaninOld) );
+        printf( " the fanins of node %s...\n", Abc_ObjName(pObj) );
+        return;
+    }
+
+    // remember the attributes of the old fanin
+//    fCompl = Abc_ObjFaninC(pObj, iFanin);
+    // replace the old fanin entry by the new fanin entry (removes attributes)
+    Vec_IntWriteEntry( &pObj->vFanins, iFanin, pFaninNewR->Id );
+    // set the attributes of the new fanin
+//    if ( fCompl ^ Abc_ObjIsComplement(pFaninNew) )
+//        Abc_ObjSetFaninC( pObj, iFanin );
+    if ( Abc_ObjIsComplement(pFaninNew) )
+        Abc_ObjXorFaninC( pObj, iFanin );
+
+//    if ( Abc_NtkIsSeq(pObj->pNtk) && (nLats = Seq_ObjFaninL(pObj, iFanin)) )
+//        Seq_ObjSetFaninL( pObj, iFanin, nLats );
+    // update the fanout of the fanin
+    if ( !Vec_IntRemove( &pFaninOld->vFanouts, pObj->Id ) )
+    {
+        printf( "Node %s is not among", Abc_ObjName(pObj) );
+        printf( " the fanouts of its old fanin %s...\n", Abc_ObjName(pFaninOld) );
+//        return;
+    }
+    Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninNewR->vFanouts, pObj->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts one-input node of the type specified between the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc_ObjType_t Type )
+{
+    Abc_Obj_t * pNodeNew;
+    int iFanoutIndex, iFaninIndex;
+    // find pNodeOut among the fanouts of pNodeIn
+    if ( (iFanoutIndex = Vec_IntFind( &pNodeIn->vFanouts, pNodeOut->Id )) == -1 )
+    {
+        printf( "Node %s is not among", Abc_ObjName(pNodeOut) );
+        printf( " the fanouts of node %s...\n", Abc_ObjName(pNodeIn) );
+        return NULL;
+    }
+    // find pNodeIn among the fanins of pNodeOut
+    if ( (iFaninIndex = Vec_IntFind( &pNodeOut->vFanins, pNodeIn->Id )) == -1 )
+    {
+        printf( "Node %s is not among", Abc_ObjName(pNodeIn) );
+        printf( " the fanins of node %s...\n", Abc_ObjName(pNodeOut) );
+        return NULL;
+    }
+    // create the new node
+    pNodeNew = Abc_NtkCreateObj( pNodeIn->pNtk, Type );
+    // add pNodeIn as fanin and pNodeOut as fanout
+    Vec_IntPushMem( pNodeNew->pNtk->pMmStep, &pNodeNew->vFanins,  pNodeIn->Id  );
+    Vec_IntPushMem( pNodeNew->pNtk->pMmStep, &pNodeNew->vFanouts, pNodeOut->Id );
+    // update the fanout of pNodeIn
+    Vec_IntWriteEntry( &pNodeIn->vFanouts, iFanoutIndex, pNodeNew->Id );
+    // update the fanin of pNodeOut
+    Vec_IntWriteEntry( &pNodeOut->vFanins, iFaninIndex, pNodeNew->Id );
+    return pNodeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers fanout from the old node to the new node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ObjTransferFanout( Abc_Obj_t * pNodeFrom, Abc_Obj_t * pNodeTo )
+{
+    Vec_Ptr_t * vFanouts;
+    int nFanoutsOld, i;
+    assert( !Abc_ObjIsComplement(pNodeFrom) );
+    assert( !Abc_ObjIsComplement(pNodeTo) );
+    assert( !Abc_ObjIsPo(pNodeFrom) && !Abc_ObjIsPo(pNodeTo) );
+    assert( pNodeFrom->pNtk == pNodeTo->pNtk );
+    assert( pNodeFrom != pNodeTo );
+    assert( !Abc_ObjIsNode(pNodeFrom) || Abc_ObjFanoutNum(pNodeFrom) > 0 );
+    // get the fanouts of the old node
+    nFanoutsOld = Abc_ObjFanoutNum(pNodeTo);
+    vFanouts = Vec_PtrAlloc( nFanoutsOld );
+    Abc_NodeCollectFanouts( pNodeFrom, vFanouts );
+    // patch the fanin of each of them
+    for ( i = 0; i < vFanouts->nSize; i++ )
+        Abc_ObjPatchFanin( (Abc_Obj_t *)vFanouts->pArray[i], pNodeFrom, pNodeTo );
+    assert( Abc_ObjFanoutNum(pNodeFrom) == 0 );
+    assert( Abc_ObjFanoutNum(pNodeTo) == nFanoutsOld + vFanouts->nSize );
+    Vec_PtrFree( vFanouts );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces the node by a new node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ObjReplace( Abc_Obj_t * pNodeOld, Abc_Obj_t * pNodeNew )
+{
+    assert( !Abc_ObjIsComplement(pNodeOld) );
+    assert( !Abc_ObjIsComplement(pNodeNew) );
+    assert( pNodeOld->pNtk == pNodeNew->pNtk );
+    assert( pNodeOld != pNodeNew );
+    assert( Abc_ObjFanoutNum(pNodeOld) > 0 );
+    // transfer the fanouts to the old node
+    Abc_ObjTransferFanout( pNodeOld, pNodeNew );
+    // remove the old node
+    Abc_NtkDeleteObj_rec( pNodeOld, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the index of the fanin in the fanin list of the fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ObjFanoutFaninNum( Abc_Obj_t * pFanout, Abc_Obj_t * pFanin )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_ObjForEachFanin( pFanout, pObj, i )
+        if ( pObj == pFanin )
+            return i;
+    return -1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcFunc.c b/abc-build/src/base/abc/abcFunc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcFunc.c
@@ -0,0 +1,1201 @@
+/**CFile****************************************************************
+
+  FileName    [abcFunc.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Transformations between different functionality representations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcFunc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "base/main/main.h"
+#include "map/mio/mio.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define ABC_MUX_CUBES   100000
+
+static int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase );
+static DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot);
+static Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop );
+
+extern int Abc_CountZddCubes( DdManager * dd, DdNode * zCover );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the node from SOP to BDD representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop, DdNode ** pbVars )
+{
+    DdNode * bSum, * bCube, * bTemp, * bVar;
+    char * pCube;
+    int nVars, Value, v;
+
+    // start the cover
+    nVars = Abc_SopGetVarNum(pSop);
+    bSum = Cudd_ReadLogicZero(dd);   Cudd_Ref( bSum );
+    if ( Abc_SopIsExorType(pSop) )
+    {
+        for ( v = 0; v < nVars; v++ )
+        {
+            bSum  = Cudd_bddXor( dd, bTemp = bSum, pbVars? pbVars[v] : Cudd_bddIthVar(dd, v) );   Cudd_Ref( bSum );
+            Cudd_RecursiveDeref( dd, bTemp );
+        }
+    }
+    else
+    {
+        // check the logic function of the node
+        Abc_SopForEachCube( pSop, nVars, pCube )
+        {
+            bCube = Cudd_ReadOne(dd);   Cudd_Ref( bCube );
+            Abc_CubeForEachVar( pCube, Value, v )
+            {
+                if ( Value == '0' )
+                    bVar = Cudd_Not( pbVars? pbVars[v] : Cudd_bddIthVar( dd, v ) );
+                else if ( Value == '1' )
+                    bVar = pbVars? pbVars[v] : Cudd_bddIthVar( dd, v );
+                else
+                    continue;
+                bCube  = Cudd_bddAnd( dd, bTemp = bCube, bVar );   Cudd_Ref( bCube );
+                Cudd_RecursiveDeref( dd, bTemp );
+            }
+            bSum = Cudd_bddOr( dd, bTemp = bSum, bCube );   
+            Cudd_Ref( bSum );
+            Cudd_RecursiveDeref( dd, bTemp );
+            Cudd_RecursiveDeref( dd, bCube );
+        }
+    }
+    // complement the result if necessary
+    bSum = Cudd_NotCond( bSum, !Abc_SopGetPhase(pSop) );
+    Cudd_Deref( bSum );
+    return bSum;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from SOP to BDD representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    DdManager * dd, * ddTemp = NULL;
+    Vec_Int_t * vFanins = NULL;
+    int nFaninsMax, i, k, iVar;
+ 
+    assert( Abc_NtkHasSop(pNtk) ); 
+
+    // start the functionality manager
+    nFaninsMax = Abc_NtkGetFaninMax( pNtk );
+    if ( nFaninsMax == 0 )
+        printf( "Warning: The network has only constant nodes.\n" );
+    dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+
+    // start temporary manager for reordered local functions
+    if ( nFaninsMax > 10 )
+    {
+        ddTemp = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+        Cudd_AutodynEnable( ddTemp,  CUDD_REORDER_SYMM_SIFT );
+        vFanins = Vec_IntAlloc( nFaninsMax );
+    }
+
+    // convert each node from SOP to BDD
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        assert( pNode->pData );
+        if ( Abc_ObjFaninNum(pNode) > 10 )
+        {
+            DdNode * pFunc = Abc_ConvertSopToBdd( ddTemp, (char *)pNode->pData, NULL );
+            if ( pFunc == NULL )
+            {
+                printf( "Abc_NtkSopToBdd: Error while converting SOP into BDD.\n" );
+                return 0;
+            }
+            Cudd_Ref( pFunc );
+            // find variable mapping
+            Vec_IntFill( vFanins, Abc_ObjFaninNum(pNode), -1 );
+            for ( k = iVar = 0; k < nFaninsMax; k++ )
+                if ( ddTemp->invperm[k] < Abc_ObjFaninNum(pNode) )
+                    Vec_IntWriteEntry( vFanins, ddTemp->invperm[k], iVar++ );
+            assert( iVar == Abc_ObjFaninNum(pNode) );
+            // transfer to the main manager
+            pNode->pData = Extra_TransferPermute( ddTemp, dd, pFunc, Vec_IntArray(vFanins) );
+            Cudd_Ref( (DdNode *)pNode->pData );
+            Cudd_RecursiveDeref( ddTemp, pFunc );
+            // update variable order
+            Vec_IntClear( vFanins );
+            for ( k = 0; k < nFaninsMax; k++ )
+                if ( ddTemp->invperm[k] < Abc_ObjFaninNum(pNode) )
+                    Vec_IntPush( vFanins, Vec_IntEntry(&pNode->vFanins, ddTemp->invperm[k]) );
+            for ( k = 0; k < Abc_ObjFaninNum(pNode); k++ )
+                Vec_IntWriteEntry( &pNode->vFanins, k, Vec_IntEntry(vFanins, k) );
+        }
+        else
+        {
+            pNode->pData = Abc_ConvertSopToBdd( dd, (char *)pNode->pData, NULL );
+            if ( pNode->pData == NULL )
+            {
+                printf( "Abc_NtkSopToBdd: Error while converting SOP into BDD.\n" );
+                return 0;
+            }
+            Cudd_Ref( (DdNode *)pNode->pData );
+        }
+    }
+
+    if ( ddTemp )
+    {
+//        printf( "Reorderings performed = %d.\n", Cudd_ReadReorderings(ddTemp) );
+        Extra_StopManager( ddTemp );
+    }
+    Vec_IntFreeP( &vFanins );
+    Mem_FlexStop( (Mem_Flex_t *)pNtk->pManFunc, 0 );
+    pNtk->pManFunc = dd;
+
+    // update the network type
+    pNtk->ntkFunc = ABC_FUNC_BDD;
+    return 1;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the node from BDD to SOP representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_ConvertBddToSop( Mem_Flex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, int fAllPrimes, Vec_Str_t * vCube, int fMode )
+{
+    int fVerify = 0;
+    char * pSop;
+    DdNode * bFuncNew, * bCover, * zCover, * zCover0, * zCover1;
+    int nCubes, nCubes0, nCubes1, fPhase;
+
+    assert( bFuncOn == bFuncOnDc || Cudd_bddLeq( dd, bFuncOn, bFuncOnDc ) );
+    if ( Cudd_IsConstant(bFuncOn) || Cudd_IsConstant(bFuncOnDc) )
+    {
+        if ( fMode == -1 ) // if the phase is not known, write constant 1
+            fMode = 1;
+        Vec_StrFill( vCube, nFanins, '-' );
+        Vec_StrPush( vCube, '\0' );
+        if ( pMan )
+            pSop = Mem_FlexEntryFetch( pMan, nFanins + 4 );
+        else
+            pSop = ABC_ALLOC( char, nFanins + 4 );
+        if ( bFuncOn == Cudd_ReadOne(dd) )
+            sprintf( pSop, "%s %d\n", vCube->pArray, fMode );
+        else
+            sprintf( pSop, "%s %d\n", vCube->pArray, !fMode );
+        return pSop;
+    }
+
+
+    if ( fMode == -1 )
+    { // try both phases
+        assert( fAllPrimes == 0 );
+
+        // get the ZDD of the negative polarity
+        bCover = Cudd_zddIsop( dd, Cudd_Not(bFuncOnDc), Cudd_Not(bFuncOn), &zCover0 );
+        Cudd_Ref( zCover0 );
+        Cudd_Ref( bCover );
+        Cudd_RecursiveDeref( dd, bCover );
+        nCubes0 = Abc_CountZddCubes( dd, zCover0 );
+
+        // get the ZDD of the positive polarity
+        bCover = Cudd_zddIsop( dd, bFuncOn, bFuncOnDc, &zCover1 );
+        Cudd_Ref( zCover1 );
+        Cudd_Ref( bCover );
+        Cudd_RecursiveDeref( dd, bCover );
+        nCubes1 = Abc_CountZddCubes( dd, zCover1 );
+
+        // compare the number of cubes
+        if ( nCubes1 <= nCubes0 )
+        { // use positive polarity
+            nCubes = nCubes1;
+            zCover = zCover1;
+            Cudd_RecursiveDerefZdd( dd, zCover0 );
+            fPhase = 1;
+        }
+        else
+        { // use negative polarity
+            nCubes = nCubes0;
+            zCover = zCover0;
+            Cudd_RecursiveDerefZdd( dd, zCover1 );
+            fPhase = 0;
+        }
+    }
+    else if ( fMode == 0 )
+    {
+        // get the ZDD of the negative polarity
+        if ( fAllPrimes )
+        {
+            zCover = Extra_zddPrimes( dd, Cudd_Not(bFuncOnDc) ); 
+            Cudd_Ref( zCover );
+        }
+        else
+        {
+            bCover = Cudd_zddIsop( dd, Cudd_Not(bFuncOnDc), Cudd_Not(bFuncOn), &zCover );
+            Cudd_Ref( zCover );
+            Cudd_Ref( bCover );
+            Cudd_RecursiveDeref( dd, bCover );
+        }
+        nCubes = Abc_CountZddCubes( dd, zCover );
+        fPhase = 0;
+    }
+    else if ( fMode == 1 )
+    {
+        // get the ZDD of the positive polarity
+        if ( fAllPrimes )
+        {
+            zCover = Extra_zddPrimes( dd, bFuncOnDc ); 
+            Cudd_Ref( zCover );
+        }
+        else
+        {
+            bCover = Cudd_zddIsop( dd, bFuncOn, bFuncOnDc, &zCover );
+            Cudd_Ref( zCover );
+            Cudd_Ref( bCover );
+            Cudd_RecursiveDeref( dd, bCover );
+        }
+        nCubes = Abc_CountZddCubes( dd, zCover );
+        fPhase = 1;
+    }
+    else
+    {
+        assert( 0 );
+    }
+
+    if ( nCubes > ABC_MUX_CUBES )
+    {
+        Cudd_RecursiveDerefZdd( dd, zCover );
+        printf( "The number of cubes exceeded the predefined limit (%d).\n", ABC_MUX_CUBES );
+        return NULL;
+    }
+
+    // allocate memory for the cover
+    if ( pMan )
+        pSop = Mem_FlexEntryFetch( pMan, (nFanins + 3) * nCubes + 1 );
+    else 
+        pSop = ABC_ALLOC( char, (nFanins + 3) * nCubes + 1 );
+    pSop[(nFanins + 3) * nCubes] = 0;
+    // create the SOP
+    Vec_StrFill( vCube, nFanins, '-' );
+    Vec_StrPush( vCube, '\0' );
+    Abc_ConvertZddToSop( dd, zCover, pSop, nFanins, vCube, fPhase );
+    Cudd_RecursiveDerefZdd( dd, zCover );
+
+    // verify
+    if ( fVerify )
+    {
+        bFuncNew = Abc_ConvertSopToBdd( dd, pSop, NULL );  Cudd_Ref( bFuncNew );
+        if ( bFuncOn == bFuncOnDc )
+        {
+            if ( bFuncNew != bFuncOn )
+                printf( "Verification failed.\n" );
+        }
+        else
+        {
+            if ( !Cudd_bddLeq(dd, bFuncOn, bFuncNew) || !Cudd_bddLeq(dd, bFuncNew, bFuncOnDc) )
+                printf( "Verification failed.\n" );
+        }
+        Cudd_RecursiveDeref( dd, bFuncNew );
+    }
+    return pSop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from BDD to SOP representation.]
+
+  Description [If the flag is set to 1, forces the direct phase of all covers.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fDirect )
+{
+    extern void Abc_NtkSortSops( Abc_Ntk_t * pNtk );
+    Abc_Obj_t * pNode;
+    Mem_Flex_t * pManNew;
+    DdManager * dd = (DdManager *)pNtk->pManFunc;
+    DdNode * bFunc;
+    Vec_Str_t * vCube;
+    int i, fMode;
+
+    if ( fDirect )
+        fMode = 1;
+    else
+        fMode = -1;
+
+    assert( Abc_NtkHasBdd(pNtk) );
+    if ( dd->size > 0 )
+    Cudd_zddVarsFromBddVars( dd, 2 );
+    // create the new manager
+    pManNew = Mem_FlexStart();
+
+    // go through the objects
+    vCube = Vec_StrAlloc( 100 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        assert( pNode->pData );
+        bFunc = (DdNode *)pNode->pData;
+        pNode->pNext = (Abc_Obj_t *)Abc_ConvertBddToSop( pManNew, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), 0, vCube, fMode );
+        if ( pNode->pNext == NULL )
+        {
+            Mem_FlexStop( pManNew, 0 );
+            Abc_NtkCleanNext( pNtk );
+//            printf( "Converting from BDDs to SOPs has failed.\n" );
+            Vec_StrFree( vCube );
+            return 0;
+        }
+    }
+    Vec_StrFree( vCube );
+
+    // update the network type
+    pNtk->ntkFunc = ABC_FUNC_SOP;
+    // set the new manager
+    pNtk->pManFunc = pManNew;
+    // transfer from next to data
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        Cudd_RecursiveDeref( dd, (DdNode *)pNode->pData );
+        pNode->pData = pNode->pNext;
+        pNode->pNext = NULL;
+    }
+
+    // check for remaining references in the package
+    Extra_StopManager( dd );
+
+    // reorder fanins and cubes to make SOPs more human-readable
+    Abc_NtkSortSops( pNtk );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derive the SOP from the ZDD representation of the cubes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ConvertZddToSop_rec( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase, int * pnCubes )
+{
+    DdNode * zC0, * zC1, * zC2;
+    int Index;
+
+    if ( zCover == dd->zero )
+        return;
+    if ( zCover == dd->one )
+    {
+        char * pCube;
+        pCube = pSop + (*pnCubes) * (nFanins + 3);
+        sprintf( pCube, "%s %d\n", vCube->pArray, fPhase );
+        (*pnCubes)++;
+        return;
+    }
+    Index = zCover->index/2;
+    assert( Index < nFanins );
+    extraDecomposeCover( dd, zCover, &zC0, &zC1, &zC2 );
+    vCube->pArray[Index] = '0';
+    Abc_ConvertZddToSop_rec( dd, zC0, pSop, nFanins, vCube, fPhase, pnCubes );
+    vCube->pArray[Index] = '1';
+    Abc_ConvertZddToSop_rec( dd, zC1, pSop, nFanins, vCube, fPhase, pnCubes );
+    vCube->pArray[Index] = '-';
+    Abc_ConvertZddToSop_rec( dd, zC2, pSop, nFanins, vCube, fPhase, pnCubes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive the BDD for the function in the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase )
+{
+    int nCubes = 0;
+    Abc_ConvertZddToSop_rec( dd, zCover, pSop, nFanins, vCube, fPhase, &nCubes );
+    return nCubes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the SOPs of the negative and positive phase of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Mem_Flex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 )
+{
+    assert( Abc_NtkHasBdd(pNode->pNtk) ); 
+    *ppSop0 = Abc_ConvertBddToSop( pMmMan, (DdManager *)pNode->pNtk->pManFunc, (DdNode *)pNode->pData, (DdNode *)pNode->pData, Abc_ObjFaninNum(pNode), fAllPrimes, vCube, 0 );
+    *ppSop1 = Abc_ConvertBddToSop( pMmMan, (DdManager *)pNode->pNtk->pManFunc, (DdNode *)pNode->pData, (DdNode *)pNode->pData, Abc_ObjFaninNum(pNode), fAllPrimes, vCube, 1 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Removes complemented SOP covers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk )
+{
+    DdManager * dd;
+    DdNode * bFunc;
+    Vec_Str_t * vCube;
+    Abc_Obj_t * pNode;
+    int nFaninsMax, fFound, i;
+
+    assert( Abc_NtkHasSop(pNtk) );
+
+    // check if there are nodes with complemented SOPs
+    fFound = 0;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        if ( Abc_SopIsComplement((char *)pNode->pData) )
+        {
+            fFound = 1;
+            break;
+        }
+    if ( !fFound )
+        return;
+
+    // start the BDD package
+    nFaninsMax = Abc_NtkGetFaninMax( pNtk );
+    if ( nFaninsMax == 0 )
+        printf( "Warning: The network has only constant nodes.\n" );
+    dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+
+    // change the cover of negated nodes
+    vCube = Vec_StrAlloc( 100 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        if ( Abc_SopIsComplement((char *)pNode->pData) )
+        {
+            bFunc = Abc_ConvertSopToBdd( dd, (char *)pNode->pData, NULL );  Cudd_Ref( bFunc );
+            pNode->pData = Abc_ConvertBddToSop( (Mem_Flex_t *)pNtk->pManFunc, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), 0, vCube, 1 );
+            Cudd_RecursiveDeref( dd, bFunc );
+            assert( !Abc_SopIsComplement((char *)pNode->pData) );
+        }
+    Vec_StrFree( vCube );
+    Extra_StopManager( dd );
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of paths in the ZDD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_CountZddCubes_rec( DdManager * dd, DdNode * zCover, int * pnCubes )
+{
+    DdNode * zC0, * zC1, * zC2;
+    if ( zCover == dd->zero )
+        return;
+    if ( zCover == dd->one )
+    {
+        (*pnCubes)++;
+        return;
+    }
+    if ( (*pnCubes) > ABC_MUX_CUBES )
+        return;
+    extraDecomposeCover( dd, zCover, &zC0, &zC1, &zC2 );
+    Abc_CountZddCubes_rec( dd, zC0, pnCubes );
+    Abc_CountZddCubes_rec( dd, zC1, pnCubes );
+    Abc_CountZddCubes_rec( dd, zC2, pnCubes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of paths in the ZDD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CountZddCubes( DdManager * dd, DdNode * zCover )
+{
+    int nCubes = 0;
+    Abc_CountZddCubes_rec( dd, zCover, &nCubes );
+    return nCubes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from SOP to AIG representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkSopToAig( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    Hop_Man_t * pMan;
+    int i;
+
+    assert( Abc_NtkHasSop(pNtk) ); 
+
+    // make dist1-free and SCC-free
+//    Abc_NtkMakeLegit( pNtk );
+
+    // start the functionality manager
+    pMan = Hop_ManStart();
+
+    // convert each node from SOP to BDD
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        assert( pNode->pData );
+        pNode->pData = Abc_ConvertSopToAig( pMan, (char *)pNode->pData );
+        if ( pNode->pData == NULL )
+        {
+            Hop_ManStop( pMan );
+            printf( "Abc_NtkSopToAig: Error while converting SOP into AIG.\n" );
+            return 0;
+        }
+    }
+    Mem_FlexStop( (Mem_Flex_t *)pNtk->pManFunc, 0 );
+    pNtk->pManFunc = pMan;
+
+    // update the network type
+    pNtk->ntkFunc = ABC_FUNC_AIG;
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes one logic node using its SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Abc_ConvertSopToAigInternal( Hop_Man_t * pMan, char * pSop )
+{
+    Hop_Obj_t * pAnd, * pSum;
+    int i, Value, nFanins;
+    char * pCube;
+    // get the number of variables
+    nFanins = Abc_SopGetVarNum(pSop);
+    if ( Abc_SopIsExorType(pSop) )
+    {
+        pSum = Hop_ManConst0(pMan); 
+        for ( i = 0; i < nFanins; i++ )
+            pSum = Hop_Exor( pMan, pSum, Hop_IthVar(pMan,i) );
+    }
+    else
+    {
+        // go through the cubes of the node's SOP
+        pSum = Hop_ManConst0(pMan); 
+        Abc_SopForEachCube( pSop, nFanins, pCube )
+        {
+            // create the AND of literals
+            pAnd = Hop_ManConst1(pMan);
+            Abc_CubeForEachVar( pCube, Value, i )
+            {
+                if ( Value == '1' )
+                    pAnd = Hop_And( pMan, pAnd, Hop_IthVar(pMan,i) );
+                else if ( Value == '0' )
+                    pAnd = Hop_And( pMan, pAnd, Hop_Not(Hop_IthVar(pMan,i)) );
+            }
+            // add to the sum of cubes
+            pSum = Hop_Or( pMan, pSum, pAnd );
+        }
+    }
+    // decide whether to complement the result
+    if ( Abc_SopIsComplement(pSop) )
+        pSum = Hop_Not(pSum);
+    return pSum;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from AIG to BDD representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop )
+{
+    extern Hop_Obj_t * Dec_GraphFactorSop( Hop_Man_t * pMan, char * pSop );
+    int fUseFactor = 1;
+    // consider the constant node
+    if ( Abc_SopGetVarNum(pSop) == 0 )
+        return Hop_NotCond( Hop_ManConst1(pMan), Abc_SopIsConst0(pSop) );
+    // decide when to use factoring
+    if ( fUseFactor && Abc_SopGetVarNum(pSop) > 2 && Abc_SopGetCubeNum(pSop) > 1 && !Abc_SopIsExorType(pSop) )
+        return Dec_GraphFactorSop( pMan, pSop );
+    return Abc_ConvertSopToAigInternal( pMan, pSop );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from AIG to BDD representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    Hop_Man_t * pMan;
+    DdManager * dd, * ddTemp = NULL;
+    Vec_Int_t * vFanins = NULL;
+    int nFaninsMax, i, k, iVar;
+
+    assert( Abc_NtkHasAig(pNtk) ); 
+
+    // start the functionality manager
+    nFaninsMax = Abc_NtkGetFaninMax( pNtk );
+    if ( nFaninsMax == 0 )
+        printf( "Warning: The network has only constant nodes.\n" );
+
+    dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+
+    // start temporary manager for reordered local functions
+    ddTemp = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    Cudd_AutodynEnable( ddTemp,  CUDD_REORDER_SYMM_SIFT );
+    vFanins = Vec_IntAlloc( nFaninsMax );
+
+    // set the mapping of elementary AIG nodes into the elementary BDD nodes
+    pMan = (Hop_Man_t *)pNtk->pManFunc;
+    assert( Hop_ManPiNum(pMan) >= nFaninsMax ); 
+    for ( i = 0; i < nFaninsMax; i++ )
+        Hop_ManPi(pMan, i)->pData = Cudd_bddIthVar(ddTemp, i);
+
+    // convert each node from SOP to BDD
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        DdNode * pFunc = Abc_ConvertAigToBdd( ddTemp, (Hop_Obj_t *)pNode->pData );
+        if ( pFunc == NULL )
+        {
+            printf( "Abc_NtkAigToBdd: Error while converting AIG into BDD.\n" );
+            return 0;
+        }
+        Cudd_Ref( pFunc );
+        // find variable mapping
+        Vec_IntFill( vFanins, Abc_ObjFaninNum(pNode), -1 );
+        for ( k = iVar = 0; k < nFaninsMax; k++ )
+            if ( ddTemp->invperm[k] < Abc_ObjFaninNum(pNode) )
+                Vec_IntWriteEntry( vFanins, ddTemp->invperm[k], iVar++ );
+        assert( iVar == Abc_ObjFaninNum(pNode) );
+        // transfer to the main manager
+        pNode->pData = Extra_TransferPermute( ddTemp, dd, pFunc, Vec_IntArray(vFanins) );
+        Cudd_Ref( (DdNode *)pNode->pData );
+        Cudd_RecursiveDeref( ddTemp, pFunc );
+        // update variable order
+        Vec_IntClear( vFanins );
+        for ( k = 0; k < nFaninsMax; k++ )
+            if ( ddTemp->invperm[k] < Abc_ObjFaninNum(pNode) )
+                Vec_IntPush( vFanins, Vec_IntEntry(&pNode->vFanins, ddTemp->invperm[k]) );
+        for ( k = 0; k < Abc_ObjFaninNum(pNode); k++ )
+            Vec_IntWriteEntry( &pNode->vFanins, k, Vec_IntEntry(vFanins, k) );
+    }
+
+//    printf( "Reorderings performed = %d.\n", Cudd_ReadReorderings(ddTemp) );
+    Extra_StopManager( ddTemp );
+    Vec_IntFreeP( &vFanins );
+    Hop_ManStop( (Hop_Man_t *)pNtk->pManFunc );
+    pNtk->pManFunc = dd;
+
+    // update the network type
+    pNtk->ntkFunc = ABC_FUNC_BDD;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Construct BDDs and mark AIG nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ConvertAigToBdd_rec1( DdManager * dd, Hop_Obj_t * pObj )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+        return;
+    Abc_ConvertAigToBdd_rec1( dd, Hop_ObjFanin0(pObj) ); 
+    Abc_ConvertAigToBdd_rec1( dd, Hop_ObjFanin1(pObj) );
+    pObj->pData = Cudd_bddAnd( dd, (DdNode *)Hop_ObjChild0Copy(pObj), (DdNode *)Hop_ObjChild1Copy(pObj) ); 
+    Cudd_Ref( (DdNode *)pObj->pData );
+    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjSetMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dereference BDDs and unmark AIG nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ConvertAigToBdd_rec2( DdManager * dd, Hop_Obj_t * pObj )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) )
+        return;
+    Abc_ConvertAigToBdd_rec2( dd, Hop_ObjFanin0(pObj) ); 
+    Abc_ConvertAigToBdd_rec2( dd, Hop_ObjFanin1(pObj) );
+    Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+    pObj->pData = NULL;
+    assert( Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjClearMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from AIG to BDD representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot )
+{
+    DdNode * bFunc;
+    // check the case of a constant
+    if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) )
+        return Cudd_NotCond( Cudd_ReadOne(dd), Hop_IsComplement(pRoot) );
+    // construct BDD
+    Abc_ConvertAigToBdd_rec1( dd, Hop_Regular(pRoot) );
+    // hold on to the result
+    bFunc = Cudd_NotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );  Cudd_Ref( bFunc );
+    // dereference BDD
+    Abc_ConvertAigToBdd_rec2( dd, Hop_Regular(pRoot) );
+    // return the result
+    Cudd_Deref( bFunc );
+    return bFunc;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from AIG to GIA representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ConvertAigToGia_rec1( Gia_Man_t * p, Hop_Obj_t * pObj )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+        return;
+    Abc_ConvertAigToGia_rec1( p, Hop_ObjFanin0(pObj) ); 
+    Abc_ConvertAigToGia_rec1( p, Hop_ObjFanin1(pObj) );
+    pObj->iData = Gia_ManAppendAnd2( p, Hop_ObjChild0CopyI(pObj), Hop_ObjChild1CopyI(pObj) );
+    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjSetMarkA( pObj );
+}
+void Abc_ConvertAigToGia_rec2( Hop_Obj_t * pObj )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) )
+        return;
+    Abc_ConvertAigToGia_rec2( Hop_ObjFanin0(pObj) ); 
+    Abc_ConvertAigToGia_rec2( Hop_ObjFanin1(pObj) );
+    assert( Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjClearMarkA( pObj );
+}
+int Abc_ConvertAigToGia( Gia_Man_t * p, Hop_Obj_t * pRoot )
+{
+    assert( !Hop_IsComplement(pRoot) );
+    if ( Hop_ObjIsConst1( pRoot ) )
+        return 1;
+    Abc_ConvertAigToGia_rec1( p, pRoot );
+    Abc_ConvertAigToGia_rec2( pRoot );
+    return pRoot->iData;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from AIG to BDD representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Abc_NtkAigToGia( Abc_Ntk_t * p )
+{
+    Gia_Man_t * pNew;
+    Hop_Man_t * pHopMan;
+    Hop_Obj_t * pHopObj;
+    Vec_Int_t * vMapping;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNode, * pFanin;
+    int i, k, nObjs;
+    assert( Abc_NtkIsAigLogic(p) );
+    pHopMan = (Hop_Man_t *)p->pManFunc;
+    // create new manager
+    pNew = Gia_ManStart( 10000 );
+    pNew->pName = Abc_UtilStrsav( Abc_NtkName(p) );
+    Abc_NtkCleanCopy( p );
+    Hop_ManConst1(pHopMan)->iData = 1;
+    // create primary inputs
+    Abc_NtkForEachCi( p, pNode, i )
+        pNode->iTemp = Gia_ManAppendCi(pNew);
+    // find the number of objects
+    nObjs = 1 + Abc_NtkCiNum(p) + Abc_NtkCoNum(p);
+    Abc_NtkForEachNode( p, pNode, i )
+        nObjs += Hop_DagSize( (Hop_Obj_t *)pNode->pData );
+    vMapping = Vec_IntStart( nObjs );
+    // iterate through nodes used in the mapping
+    vNodes = Abc_NtkDfs( p, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+            Hop_ManPi(pHopMan, k)->iData = pFanin->iTemp;
+        pHopObj = Hop_Regular( (Hop_Obj_t *)pNode->pData );
+        if ( Hop_DagSize(pHopObj) > 0 )
+        {
+            assert( Abc_ObjFaninNum(pNode) <= Hop_ManPiNum(pHopMan) );
+            Abc_ConvertAigToGia( pNew, pHopObj );
+            if ( !Gia_ObjIsAnd(Gia_ManObj(pNew, Abc_Lit2Var(pHopObj->iData))) )
+                continue;
+            if ( Vec_IntEntry(vMapping, Abc_Lit2Var(pHopObj->iData)) )
+                continue;
+            Vec_IntWriteEntry( vMapping, Abc_Lit2Var(pHopObj->iData), Vec_IntSize(vMapping) );
+            Vec_IntPush( vMapping, Abc_ObjFaninNum(pNode) );
+            Abc_ObjForEachFanin( pNode, pFanin, k )
+                Vec_IntPush( vMapping, Abc_Lit2Var(pFanin->iTemp)  );
+            Vec_IntPush( vMapping, Abc_Lit2Var(pHopObj->iData) );
+        }
+        pNode->iTemp = Abc_LitNotCond( pHopObj->iData, Hop_IsComplement( (Hop_Obj_t *)pNode->pData ) );
+    }
+    Vec_PtrFree( vNodes );
+    // create primary outputs
+    Abc_NtkForEachCo( p, pNode, i )
+        Gia_ManAppendCo( pNew, Abc_ObjFanin0(pNode)->iTemp );
+    Gia_ManSetRegNum( pNew, Abc_NtkLatchNum(p) );
+    // finish mapping 
+    assert( Gia_ManObjNum(pNew) <= nObjs );
+    assert( pNew->vMapping == NULL );
+    pNew->vMapping = vMapping;
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Construct BDDs and mark AIG nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ConvertAigToAig_rec( Abc_Ntk_t * pNtkAig, Hop_Obj_t * pObj )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+        return;
+    Abc_ConvertAigToAig_rec( pNtkAig, Hop_ObjFanin0(pObj) ); 
+    Abc_ConvertAigToAig_rec( pNtkAig, Hop_ObjFanin1(pObj) );
+    pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) ); 
+    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjSetMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from AIG to BDD representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_ConvertAigToAig( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pObjOld )
+{
+    Hop_Man_t * pHopMan;
+    Hop_Obj_t * pRoot;
+    Abc_Obj_t * pFanin;
+    int i;
+    // get the local AIG
+    pHopMan = (Hop_Man_t *)pObjOld->pNtk->pManFunc;
+    pRoot = (Hop_Obj_t *)pObjOld->pData;
+    // check the case of a constant
+    if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) )
+        return Abc_ObjNotCond( Abc_AigConst1(pNtkAig), Hop_IsComplement(pRoot) );
+    // assign the fanin nodes
+    Abc_ObjForEachFanin( pObjOld, pFanin, i )
+    {
+        assert( pFanin->pCopy != NULL );
+        Hop_ManPi(pHopMan, i)->pData = pFanin->pCopy;
+    }
+    // construct the AIG
+    Abc_ConvertAigToAig_rec( pNtkAig, Hop_Regular(pRoot) );
+    Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
+    // return the result
+    return Abc_ObjNotCond( (Abc_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );  
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Unmaps the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMapToSop( Abc_Ntk_t * pNtk )
+{
+    extern void * Abc_FrameReadLibGen();                    
+    Abc_Obj_t * pNode;
+    char * pSop;
+    int i;
+
+    assert( Abc_NtkHasMapping(pNtk) );
+    // update the functionality manager
+    assert( pNtk->pManFunc == Abc_FrameReadLibGen() );
+    pNtk->pManFunc = Mem_FlexStart();
+    pNtk->ntkFunc  = ABC_FUNC_SOP;
+    // update the nodes
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        pSop = Mio_GateReadSop((Mio_Gate_t *)pNode->pData);
+        assert( Abc_SopGetVarNum(pSop) == Abc_ObjFaninNum(pNode) );
+        pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, pSop );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts SOP functions into BLIF-MV functions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkSopToBlifMv( Abc_Ntk_t * pNtk )
+{
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Convers logic network to the SOP form.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkToSop( Abc_Ntk_t * pNtk, int fDirect )
+{
+    assert( !Abc_NtkIsStrash(pNtk) );
+    if ( Abc_NtkHasSop(pNtk) )
+    {
+        if ( !fDirect )
+            return 1;
+        if ( !Abc_NtkSopToBdd(pNtk) )
+            return 0;
+        return Abc_NtkBddToSop(pNtk, fDirect);
+    }
+    if ( Abc_NtkHasMapping(pNtk) )
+        return Abc_NtkMapToSop(pNtk);
+    if ( Abc_NtkHasBdd(pNtk) )
+        return Abc_NtkBddToSop(pNtk, fDirect);
+    if ( Abc_NtkHasAig(pNtk) )
+    {
+        if ( !Abc_NtkAigToBdd(pNtk) )
+            return 0;
+        return Abc_NtkBddToSop(pNtk, fDirect);
+    }
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Convers logic network to the SOP form.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkToBdd( Abc_Ntk_t * pNtk )
+{
+    assert( !Abc_NtkIsStrash(pNtk) );
+    if ( Abc_NtkHasBdd(pNtk) )
+        return 1;
+    if ( Abc_NtkHasMapping(pNtk) )
+    {
+        Abc_NtkMapToSop(pNtk);
+        return Abc_NtkSopToBdd(pNtk);
+    }
+    if ( Abc_NtkHasSop(pNtk) )
+    {
+        Abc_NtkSopToAig(pNtk);
+        return Abc_NtkAigToBdd(pNtk);
+    }
+    if ( Abc_NtkHasAig(pNtk) )
+        return Abc_NtkAigToBdd(pNtk);
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Convers logic network to the SOP form.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkToAig( Abc_Ntk_t * pNtk )
+{
+    assert( !Abc_NtkIsStrash(pNtk) );
+    if ( Abc_NtkHasAig(pNtk) )
+        return 1;
+    if ( Abc_NtkHasMapping(pNtk) )
+    {
+        Abc_NtkMapToSop(pNtk);
+        return Abc_NtkSopToAig(pNtk);
+    }
+    if ( Abc_NtkHasBdd(pNtk) )
+    {
+        if ( !Abc_NtkBddToSop(pNtk,0) )
+            return 0;
+        return Abc_NtkSopToAig(pNtk);
+    }
+    if ( Abc_NtkHasSop(pNtk) )
+        return Abc_NtkSopToAig(pNtk);
+    assert( 0 );
+    return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcHie.c b/abc-build/src/base/abc/abcHie.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcHie.c
@@ -0,0 +1,842 @@
+/**CFile****************************************************************
+
+  FileName    [abcHie.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Procedures to handle hierarchy.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcHie.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively flattens logic hierarchy of the netlist.]
+
+  Description [When this procedure is called, the PI/PO nets of the old 
+  netlist point to the corresponding nets of the flattened netlist.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFlattenLogicHierarchy2_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, int * pCounter )
+{
+    char Suffix[2000] = {0};
+    Abc_Ntk_t * pNtkModel;
+    Abc_Obj_t * pObj, * pTerm, * pNet, * pFanin;
+    int i, k;
+
+    // process the blackbox
+    if ( Abc_NtkHasBlackbox(pNtk) )
+    {
+        // duplicate the blackbox
+        assert( Abc_NtkBoxNum(pNtk) == 1 );
+        pObj = Abc_NtkBox( pNtk, 0 );
+        Abc_NtkDupBox( pNtkNew, pObj, 1 );
+        pObj->pCopy->pData = pNtk;
+
+        // connect blackbox fanins to the PI nets
+        assert( Abc_ObjFaninNum(pObj->pCopy) == Abc_NtkPiNum(pNtk) );
+        Abc_NtkForEachPi( pNtk, pTerm, i )
+            Abc_ObjAddFanin( Abc_ObjFanin(pObj->pCopy,i), Abc_ObjFanout0(pTerm)->pCopy );
+
+        // connect blackbox fanouts to the PO nets
+        assert( Abc_ObjFanoutNum(pObj->pCopy) == Abc_NtkPoNum(pNtk) );
+        Abc_NtkForEachPo( pNtk, pTerm, i )
+            Abc_ObjAddFanin( Abc_ObjFanin0(pTerm)->pCopy, Abc_ObjFanout(pObj->pCopy,i) );
+        return;
+    }
+
+    (*pCounter)++;
+
+    // create the suffix, which will be appended to the internal names
+    if ( *pCounter )
+        sprintf( Suffix, "_%s_%d", Abc_NtkName(pNtk), *pCounter );
+
+    // duplicate nets of all boxes, including latches
+    Abc_NtkForEachBox( pNtk, pObj, i )
+    {
+        Abc_ObjForEachFanin( pObj, pTerm, k )
+        {
+            pNet = Abc_ObjFanin0(pTerm);
+            if ( pNet->pCopy )
+                continue;
+            pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) );
+        }
+        Abc_ObjForEachFanout( pObj, pTerm, k )
+        {
+            pNet = Abc_ObjFanout0(pTerm);
+            if ( pNet->pCopy )
+                continue;
+            pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) );
+        }
+    }
+
+    // mark objects that will not be used
+    Abc_NtkIncrementTravId( pNtk );
+    Abc_NtkForEachPi( pNtk, pTerm, i )
+        Abc_NodeSetTravIdCurrent( pTerm );
+    Abc_NtkForEachPo( pNtk, pTerm, i )
+    {
+        Abc_NodeSetTravIdCurrent( pTerm );
+        // if the netlist has net names beginning with "abc_property_"
+        // these names will be addes as primary outputs of the network
+        pNet = Abc_ObjFanin0(pTerm);
+        if ( strncmp( Abc_ObjName(pNet), "abc_property", 12 ) )
+            continue;
+        Abc_ObjAddFanin( Abc_NtkCreatePo(pNet->pCopy->pNtk), pNet->pCopy );
+        if ( Nm_ManFindNameById(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id) )
+            Nm_ManDeleteIdName(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id);
+        Abc_ObjAssignName( pNet->pCopy, Abc_ObjName(pNet), Suffix );
+    }
+    Abc_NtkForEachBox( pNtk, pObj, i )
+    {
+        if ( Abc_ObjIsLatch(pObj) )
+            continue;
+        Abc_NodeSetTravIdCurrent( pObj );
+        Abc_ObjForEachFanin( pObj, pTerm, k )
+            Abc_NodeSetTravIdCurrent( pTerm );
+        Abc_ObjForEachFanout( pObj, pTerm, k )
+            Abc_NodeSetTravIdCurrent( pTerm );
+    }
+
+    // duplicate objects that do not have prototypes yet
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        if ( Abc_NodeIsTravIdCurrent(pObj) )
+            continue;
+        if ( pObj->pCopy )
+            continue;
+        Abc_NtkDupObj( pNtkNew, pObj, 0 );
+    }
+
+    // connect objects
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( !Abc_NodeIsTravIdCurrent(pObj) )
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+                    Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+
+    // call recursively
+    Abc_NtkForEachBox( pNtk, pObj, i )
+    {
+        if ( Abc_ObjIsLatch(pObj) )
+            continue;
+        pNtkModel = (Abc_Ntk_t *)pObj->pData;
+        // check the match between the number of actual and formal parameters
+        assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) );
+        assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) );
+        // clean the node copy fields
+        Abc_NtkCleanCopy( pNtkModel );
+        // map PIs/POs
+        Abc_ObjForEachFanin( pObj, pTerm, k )
+            Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->pCopy = Abc_ObjFanin0(pTerm)->pCopy;
+        Abc_ObjForEachFanout( pObj, pTerm, k )
+            Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->pCopy = Abc_ObjFanout0(pTerm)->pCopy;
+        // call recursively
+        Abc_NtkFlattenLogicHierarchy2_rec( pNtkNew, pNtkModel, pCounter );
+    }
+
+    // if it is a BLIF-MV netlist transfer the values of all nets
+    if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) )
+    {
+        if ( Abc_NtkMvVar( pNtkNew ) == NULL )
+            Abc_NtkStartMvVars( pNtkNew );
+        Abc_NtkForEachNet( pNtk, pObj, i )
+            Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Flattens the logic hierarchy of the netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy2( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pTerm, * pNet;
+    int i, Counter;
+    extern Abc_Des_t * Abc_DesDupBlackboxes( Abc_Des_t * p, Abc_Ntk_t * pNtkSave );
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+    // start the network
+    pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+    // duplicate the name and the spec
+    pNtkNew->pName = Abc_UtilStrsav(pNtk->pName);
+    pNtkNew->pSpec = Abc_UtilStrsav(pNtk->pSpec);
+
+    // clean the node copy fields
+    Abc_NtkCleanCopy( pNtk );
+
+    // duplicate PIs/POs and their nets
+    Abc_NtkForEachPi( pNtk, pTerm, i )
+    {
+        Abc_NtkDupObj( pNtkNew, pTerm, 0 );
+        pNet = Abc_ObjFanout0( pTerm );
+        pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) );
+        Abc_ObjAddFanin( pNet->pCopy, pTerm->pCopy );
+    }
+    Abc_NtkForEachPo( pNtk, pTerm, i )
+    {
+        Abc_NtkDupObj( pNtkNew, pTerm, 0 );
+        pNet = Abc_ObjFanin0( pTerm );
+        pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) );
+        Abc_ObjAddFanin( pTerm->pCopy, pNet->pCopy );
+    }
+
+    // recursively flatten hierarchy, create internal logic, add new PI/PO names if there are black boxes
+    Counter = -1;
+    Abc_NtkFlattenLogicHierarchy2_rec( pNtkNew, pNtk, &Counter );
+    printf( "Hierarchy reader flattened %d instances of logic boxes and left %d black boxes.\n", 
+        Counter, Abc_NtkBlackboxNum(pNtkNew) );
+
+    if ( pNtk->pDesign )
+    {
+        // pass on the design
+        assert( Vec_PtrEntry(pNtk->pDesign->vTops, 0) == pNtk );
+        pNtkNew->pDesign = Abc_DesDupBlackboxes( pNtk->pDesign, pNtkNew );
+        // update the pointers
+        Abc_NtkForEachBlackbox( pNtkNew, pTerm, i )
+            pTerm->pData = ((Abc_Ntk_t *)pTerm->pData)->pCopy;
+    }
+
+    // we may have added property outputs
+    Abc_NtkOrderCisCos( pNtkNew );
+
+    // copy the timing information
+//    Abc_ManTimeDup( pNtk, pNtkNew );
+    // duplicate EXDC 
+    if ( pNtk->pExdc )
+        printf( "EXDC is not transformed.\n" );
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        fprintf( stdout, "Abc_NtkFlattenLogicHierarchy2(): Network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively flattens logic hierarchy of the netlist.]
+
+  Description [When this procedure is called, the PI/PO nets of the old 
+  netlist point to the corresponding nets of the flattened netlist.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFlattenLogicHierarchy_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, int * pCounter, Vec_Str_t * vPref )
+{
+    Abc_Ntk_t * pNtkModel;
+    Abc_Obj_t * pObj, * pTerm, * pNet, * pFanin;
+    int i, k, Length;
+
+    // process the blackbox
+    if ( Abc_NtkHasBlackbox(pNtk) )
+    {
+        // duplicate the blackbox
+        assert( Abc_NtkBoxNum(pNtk) == 1 );
+        pObj = Abc_NtkBox( pNtk, 0 );
+        Abc_NtkDupBox( pNtkNew, pObj, 1 );
+        pObj->pCopy->pData = pNtk;
+
+        // connect blackbox fanins to the PI nets
+        assert( Abc_ObjFaninNum(pObj->pCopy) == Abc_NtkPiNum(pNtk) );
+        Abc_NtkForEachPi( pNtk, pTerm, i )
+            Abc_ObjAddFanin( Abc_ObjFanin(pObj->pCopy,i), Abc_ObjFanout0(pTerm)->pCopy );
+
+        // connect blackbox fanouts to the PO nets
+        assert( Abc_ObjFanoutNum(pObj->pCopy) == Abc_NtkPoNum(pNtk) );
+        Abc_NtkForEachPo( pNtk, pTerm, i )
+            Abc_ObjAddFanin( Abc_ObjFanin0(pTerm)->pCopy, Abc_ObjFanout(pObj->pCopy,i) );
+        return;
+    }
+
+    (*pCounter)++;
+
+    // create the suffix, which will be appended to the internal names
+    if ( *pCounter )
+    {
+        char Buffer[20];
+        sprintf( Buffer, "(%d)", *pCounter );
+        Vec_StrPrintStr( vPref, Buffer );
+    }
+    Vec_StrPush( vPref, '|' );
+    Vec_StrPush( vPref, 0 );
+
+    // duplicate nets of all boxes, including latches
+    Abc_NtkForEachBox( pNtk, pObj, i )
+    {
+        Abc_ObjForEachFanin( pObj, pTerm, k )
+        {
+            pNet = Abc_ObjFanin0(pTerm);
+            if ( pNet->pCopy )
+                continue;
+            pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNamePrefix(pNet, Vec_StrArray(vPref)) );
+        }
+        Abc_ObjForEachFanout( pObj, pTerm, k )
+        {
+            pNet = Abc_ObjFanout0(pTerm);
+            if ( pNet->pCopy )
+                continue;
+            pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNamePrefix(pNet, Vec_StrArray(vPref)) );
+        }
+    }
+
+    // mark objects that will not be used
+    Abc_NtkIncrementTravId( pNtk );
+    Abc_NtkForEachPi( pNtk, pTerm, i )
+        Abc_NodeSetTravIdCurrent( pTerm );
+    Abc_NtkForEachPo( pNtk, pTerm, i )
+    {
+        Abc_NodeSetTravIdCurrent( pTerm );
+        // if the netlist has net names beginning with "abc_property_"
+        // these names will be addes as primary outputs of the network
+        pNet = Abc_ObjFanin0(pTerm);
+        if ( strncmp( Abc_ObjName(pNet), "abc_property", 12 ) )
+            continue;
+        Abc_ObjAddFanin( Abc_NtkCreatePo(pNet->pCopy->pNtk), pNet->pCopy );
+        if ( Nm_ManFindNameById(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id) )
+            Nm_ManDeleteIdName(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id);
+        Abc_ObjAssignName( pNet->pCopy, Vec_StrArray(vPref), Abc_ObjName(pNet) );
+    }
+    Abc_NtkForEachBox( pNtk, pObj, i )
+    {
+        if ( Abc_ObjIsLatch(pObj) )
+            continue;
+        Abc_NodeSetTravIdCurrent( pObj );
+        Abc_ObjForEachFanin( pObj, pTerm, k )
+            Abc_NodeSetTravIdCurrent( pTerm );
+        Abc_ObjForEachFanout( pObj, pTerm, k )
+            Abc_NodeSetTravIdCurrent( pTerm );
+    }
+
+    // duplicate objects that do not have prototypes yet
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        if ( Abc_NodeIsTravIdCurrent(pObj) )
+            continue;
+        if ( pObj->pCopy )
+            continue;
+        Abc_NtkDupObj( pNtkNew, pObj, 0 );
+    }
+
+    // connect objects
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( !Abc_NodeIsTravIdCurrent(pObj) )
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+                    Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+
+    // call recursively
+    Vec_StrPop( vPref );
+    Length = Vec_StrSize( vPref );
+    Abc_NtkForEachBox( pNtk, pObj, i )
+    {
+        if ( Abc_ObjIsLatch(pObj) )
+            continue;
+        pNtkModel = (Abc_Ntk_t *)pObj->pData;
+        // check the match between the number of actual and formal parameters
+        assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) );
+        assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) );
+        // clean the node copy fields
+        Abc_NtkCleanCopy( pNtkModel );
+        // map PIs/POs
+        Abc_ObjForEachFanin( pObj, pTerm, k )
+            Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->pCopy = Abc_ObjFanin0(pTerm)->pCopy;
+        Abc_ObjForEachFanout( pObj, pTerm, k )
+            Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->pCopy = Abc_ObjFanout0(pTerm)->pCopy;
+        // create name
+        Vec_StrShrink( vPref, Length );
+        Vec_StrPrintStr( vPref, Abc_NtkName(pNtkModel) );
+        // call recursively
+        Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtkModel, pCounter, vPref );
+    }
+
+    // if it is a BLIF-MV netlist transfer the values of all nets
+    if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) )
+    {
+        if ( Abc_NtkMvVar( pNtkNew ) == NULL )
+            Abc_NtkStartMvVars( pNtkNew );
+        Abc_NtkForEachNet( pNtk, pObj, i )
+            Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 0 if CI names are repeated.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCompareNames( Abc_Ntk_t ** p1, Abc_Ntk_t ** p2 )
+{
+    return strcmp( Abc_NtkName(*p1), Abc_NtkName(*p2) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints information about boxes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintBoxInfo( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vMods;
+    Abc_Ntk_t * pModel, * pBoxModel;
+    Abc_Obj_t * pObj;
+    Vec_Int_t * vCounts;
+    int i, k, Num;
+    if ( pNtk->pDesign == NULL || pNtk->pDesign->vModules == NULL )
+    {
+//        printf( "There is no hierarchy information.\n" );
+        return;
+    }
+    // sort models by name
+    vMods = pNtk->pDesign->vModules;
+    Vec_PtrSort( vMods, (int(*)())Abc_NtkCompareNames );
+//    Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i )
+//        printf( "%s\n", Abc_NtkName(pModel) );
+
+    // swap the first model
+    Num = Vec_PtrFind( vMods, pNtk );
+    assert( Num >= 0 && Num < Vec_PtrSize(vMods) );
+    pBoxModel = (Abc_Ntk_t *)Vec_PtrEntry(vMods, 0);
+    Vec_PtrWriteEntry(vMods, 0, (Abc_Ntk_t *)Vec_PtrEntry(vMods, Num) );
+    Vec_PtrWriteEntry(vMods, Num, pBoxModel );
+
+    // print models
+    vCounts = Vec_IntStart( Vec_PtrSize(vMods) );
+    Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i )
+    {
+        if ( Abc_NtkBoxNum(pModel) == 0 )
+            continue;
+        Vec_IntFill( vCounts, Vec_IntSize(vCounts), 0 );
+        Abc_NtkForEachBox( pModel, pObj, k )
+        {
+            pBoxModel = (Abc_Ntk_t *)pObj->pData;
+            if ( pBoxModel == NULL )
+                continue;
+            Num = Vec_PtrFind( vMods, pBoxModel );
+            assert( Num >= 0 && Num < Vec_PtrSize(vMods) );
+            Vec_IntAddToEntry( vCounts, Num, 1 );
+        }
+
+//        Abc_NtkPrintStats( pModel, 0, 0, 0, 0, 0, 0, 0, 0 );
+        printf( "MODULE  " );
+        printf( "%-30s : ", Abc_NtkName(pModel) );
+        printf( "PI=%6d ", Abc_NtkPiNum(pModel) );
+        printf( "PO=%6d ", Abc_NtkPoNum(pModel) );
+        printf( "BB=%6d ", Abc_NtkBoxNum(pModel) );
+        printf( "ND=%6d ", Abc_NtkNodeNum(pModel) ); // sans constants
+        printf( "Lev=%5d ", Abc_NtkLevel(pModel) );
+        printf( "\n" );
+
+        Vec_IntForEachEntry( vCounts, Num, k )
+            if ( Num )
+                printf( "%15d : %s\n", Num, Abc_NtkName((Abc_Ntk_t *)Vec_PtrEntry(vMods, k)) );
+    }
+    Vec_IntFree( vCounts );
+    Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i )
+    {
+        if ( Abc_NtkBoxNum(pModel) != 0 )
+            continue;
+        printf( "MODULE   " );
+        printf( "%-30s : ", Abc_NtkName(pModel) );
+        printf( "PI=%6d ", Abc_NtkPiNum(pModel) );
+        printf( "PO=%6d ", Abc_NtkPoNum(pModel) );
+        printf( "BB=%6d ", Abc_NtkBoxNum(pModel) );
+        printf( "ND=%6d ", Abc_NtkNodeNum(pModel) );
+        printf( "Lev=%5d ", Abc_NtkLevel(pModel) );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Flattens the logic hierarchy of the netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk )
+{
+    extern Abc_Des_t * Abc_DesDupBlackboxes( Abc_Des_t * p, Abc_Ntk_t * pNtkSave );
+    Vec_Str_t * vPref;
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pTerm, * pNet;
+    int i, Counter = -1;
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+//    Abc_NtkPrintBoxInfo( pNtk );
+
+    // start the network
+    pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+    // duplicate the name and the spec
+    pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+    pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+
+    // clean the node copy fields
+    Abc_NtkCleanCopy( pNtk );
+
+    // duplicate PIs/POs and their nets
+    Abc_NtkForEachPi( pNtk, pTerm, i )
+    {
+        Abc_NtkDupObj( pNtkNew, pTerm, 0 );
+        pNet = Abc_ObjFanout0( pTerm );
+        pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) );
+        Abc_ObjAddFanin( pNet->pCopy, pTerm->pCopy );
+    }
+    Abc_NtkForEachPo( pNtk, pTerm, i )
+    {
+        Abc_NtkDupObj( pNtkNew, pTerm, 0 );
+        pNet = Abc_ObjFanin0( pTerm );
+        pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) );
+        Abc_ObjAddFanin( pTerm->pCopy, pNet->pCopy );
+    }
+
+    // recursively flatten hierarchy, create internal logic, add new PI/PO names if there are black boxes
+    vPref = Vec_StrAlloc( 1000 );
+    Vec_StrPrintStr( vPref, Abc_NtkName(pNtk) );
+    Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtk, &Counter, vPref );
+    printf( "Hierarchy reader flattened %d instances of logic boxes and left %d black boxes.\n", 
+        Counter, Abc_NtkBlackboxNum(pNtkNew) );
+    Vec_StrFree( vPref );
+
+    if ( pNtk->pDesign )
+    {
+        // pass on the design
+        assert( Vec_PtrEntry(pNtk->pDesign->vTops, 0) == pNtk );
+        pNtkNew->pDesign = Abc_DesDupBlackboxes( pNtk->pDesign, pNtkNew );
+        // update the pointers
+        Abc_NtkForEachBlackbox( pNtkNew, pTerm, i )
+            pTerm->pData = ((Abc_Ntk_t *)pTerm->pData)->pCopy;
+    }
+
+    // we may have added property outputs
+    Abc_NtkOrderCisCos( pNtkNew );
+
+    // copy the timing information
+//    Abc_ManTimeDup( pNtk, pNtkNew );
+    // duplicate EXDC 
+    if ( pNtk->pExdc )
+        printf( "EXDC is not transformed.\n" );
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        fprintf( stdout, "Abc_NtkFlattenLogicHierarchy(): Network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Extracts blackboxes by making them into additional PIs/POs.]
+
+  Description [The input netlist has not logic hierarchy. The resulting
+  netlist has additional PIs/POs for each blackbox input/output.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkConvertBlackboxes( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObj, * pNet, * pFanin, * pTerm;
+    int i, k;
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+
+    // start the network
+    pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+    // duplicate the name and the spec
+    pNtkNew->pName = Extra_UtilStrsav( pNtk->pName );
+    pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec );
+
+    // clean the node copy fields
+    Abc_NtkCleanCopy( pNtk );
+
+    // mark the nodes that should not be connected
+    Abc_NtkIncrementTravId( pNtk );
+    Abc_NtkForEachBlackbox( pNtk, pObj, i )
+        Abc_NodeSetTravIdCurrent( pObj );
+    Abc_NtkForEachCi( pNtk, pTerm, i )
+        Abc_NodeSetTravIdCurrent( pTerm );
+    Abc_NtkForEachCo( pNtk, pTerm, i )
+        Abc_NodeSetTravIdCurrent( pTerm );
+    // unmark PIs and LIs/LOs
+    Abc_NtkForEachPi( pNtk, pTerm, i )
+        Abc_NodeSetTravIdPrevious( pTerm );
+    Abc_NtkForEachLatchInput( pNtk, pTerm, i )
+        Abc_NodeSetTravIdPrevious( pTerm );
+    Abc_NtkForEachLatchOutput( pNtk, pTerm, i )
+        Abc_NodeSetTravIdPrevious( pTerm );
+    // copy the box outputs
+    Abc_NtkForEachBlackbox( pNtk, pObj, i )
+        Abc_ObjForEachFanout( pObj, pTerm, k )
+            pTerm->pCopy = Abc_NtkCreatePi( pNtkNew );
+
+    // duplicate other objects
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( !Abc_NodeIsTravIdCurrent(pObj) )
+            Abc_NtkDupObj( pNtkNew, pObj, Abc_ObjIsNet(pObj) );
+
+    // connect all objects
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( !Abc_NodeIsTravIdCurrent(pObj) )
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+
+    // create unique PO for each net feeding into blackboxes or POs
+    Abc_NtkIncrementTravId( pNtk );
+    Abc_NtkForEachCo( pNtk, pTerm, i )
+    {
+        // skip latch inputs
+        assert( Abc_ObjFanoutNum(pTerm) <= 1 );
+        if ( Abc_ObjFanoutNum(pTerm) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pTerm)) )
+            continue;
+        // check if the net is visited
+        pNet = Abc_ObjFanin0(pTerm);
+        if ( Abc_NodeIsTravIdCurrent(pNet) )
+            continue;
+        // create PO
+        Abc_NodeSetTravIdCurrent( pNet );
+        Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNet->pCopy );
+    }
+
+    // check integrity
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        fprintf( stdout, "Abc_NtkConvertBlackboxes(): Network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts blackboxes into the netlist.]
+
+  Description [The first arg is the netlist with blackboxes without logic hierarchy.
+  The second arg is a non-hierarchical netlist derived from the above netlist after processing.
+  This procedure create a new netlist, which is comparable to the original netlist with
+  blackboxes, except that it contains logic nodes from the netlist after processing.]
+               
+  SideEffects [This procedure silently assumes that blackboxes appear
+  only in the top-level model. If they appear in other models as well, 
+  the name of the model and its number were appended to the names of 
+  blackbox inputs/outputs.]
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL )
+{
+    Abc_Des_t * pDesign;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObjH, * pObjL, * pNetH, * pNetL, * pTermH;
+    int i, k;
+
+    assert( Abc_NtkIsNetlist(pNtkH) );
+    assert( Abc_NtkWhiteboxNum(pNtkH) == 0 );
+    assert( Abc_NtkBlackboxNum(pNtkH) > 0 );
+
+    assert( Abc_NtkIsNetlist(pNtkL) );
+    assert( Abc_NtkWhiteboxNum(pNtkL) == 0 );
+    assert( Abc_NtkBlackboxNum(pNtkL) == 0 );
+
+    // prepare the logic network for copying
+    Abc_NtkCleanCopy( pNtkL );
+
+    // start the network
+    pNtkNew = Abc_NtkAlloc( pNtkL->ntkType, pNtkL->ntkFunc, 1 );
+    // duplicate the name and the spec
+    pNtkNew->pName = Extra_UtilStrsav( pNtkH->pName );
+    pNtkNew->pSpec = Extra_UtilStrsav( pNtkH->pSpec );
+
+    // make sure every PI/PO has a PI/PO in the processed network
+    Abc_NtkForEachPi( pNtkH, pObjH, i )
+    {
+        pNetH = Abc_ObjFanout0(pObjH);
+        pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) );
+        if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) )
+        {
+            printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the PI %s.\n", Abc_ObjName(pNetH) );
+            Abc_NtkDelete( pNtkNew );
+            return NULL;
+        }
+        if ( pNetL->pCopy )
+        {
+            printf( "Error in Abc_NtkInsertNewLogic(): Primary input %s is repeated twice.\n", Abc_ObjName(pNetH) );
+            Abc_NtkDelete( pNtkNew );
+            return NULL;
+        }
+        // create the new net
+        pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) );
+        Abc_NtkDupObj( pNtkNew, Abc_ObjFanin0(pNetL), 0 );
+    }
+
+    // make sure every BB has a PI/PO in the processed network
+    Abc_NtkForEachBlackbox( pNtkH, pObjH, i )
+    {
+        // duplicate the box 
+        Abc_NtkDupBox( pNtkNew, pObjH, 0 );
+        pObjH->pCopy->pData = pObjH->pData;
+        // create PIs
+        Abc_ObjForEachFanout( pObjH, pTermH, k )
+        {
+            pNetH = Abc_ObjFanout0( pTermH );
+            pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) );
+            if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) )
+            {
+                printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the inpout %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) );
+                Abc_NtkDelete( pNtkNew );
+                return NULL;
+            }
+            if ( pNetL->pCopy )
+            {
+                printf( "Error in Abc_NtkInsertNewLogic(): Box output %s is repeated twice.\n", Abc_ObjName(pNetH) );
+                Abc_NtkDelete( pNtkNew );
+                return NULL;
+            }
+            // create net and map the PI
+            pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) );
+            Abc_ObjFanin0(pNetL)->pCopy = pTermH->pCopy;
+        }
+    }
+
+    Abc_NtkForEachPo( pNtkH, pObjH, i )
+    {
+        pNetH = Abc_ObjFanin0(pObjH);
+        pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) );
+        if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) )
+        {
+            printf( "Error in Abc_NtkInsertNewLogic(): There is no PO corresponding to the PO %s.\n", Abc_ObjName(pNetH) );
+            Abc_NtkDelete( pNtkNew );
+            return NULL;
+        }
+        if ( pNetL->pCopy )
+            continue;
+        // create the new net
+        pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) );
+        Abc_NtkDupObj( pNtkNew, Abc_ObjFanout0(pNetL), 0 );
+    }
+    Abc_NtkForEachBlackbox( pNtkH, pObjH, i )
+    {
+        Abc_ObjForEachFanin( pObjH, pTermH, k )
+        {
+            char * pName;
+            pNetH = Abc_ObjFanin0( pTermH );
+            pName = Abc_ObjName(pNetH);
+            pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) );
+            if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) )
+            {
+                printf( "There is no PO corresponding to the input %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) );
+                Abc_NtkDelete( pNtkNew );
+                return NULL;
+            }
+            // create net and map the PO
+            if ( pNetL->pCopy )
+            {
+                if ( Abc_ObjFanout0(pNetL)->pCopy == NULL )
+                    Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy;
+                else
+                    Abc_ObjAddFanin( pTermH->pCopy, pNetL->pCopy );
+                continue;
+            }
+            pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) );
+            Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy;
+        }
+    }
+
+    // duplicate other objects of the logic network
+    Abc_NtkForEachObj( pNtkL, pObjL, i )
+        if ( pObjL->pCopy == NULL && !Abc_ObjIsPo(pObjL) ) // skip POs feeding into PIs
+            Abc_NtkDupObj( pNtkNew, pObjL, Abc_ObjIsNet(pObjL) );
+
+    // connect objects
+    Abc_NtkForEachObj( pNtkL, pObjL, i )
+        Abc_ObjForEachFanin( pObjL, pNetL, k )
+            if ( pObjL->pCopy )
+                Abc_ObjAddFanin( pObjL->pCopy, pNetL->pCopy );
+
+    // transfer the design
+    pDesign = pNtkH->pDesign;  pNtkH->pDesign = NULL;
+    assert( Vec_PtrEntry( pDesign->vModules, 0 ) == pNtkH );
+    Vec_PtrWriteEntry( pDesign->vModules, 0, pNtkNew );
+    pNtkNew->pDesign = pDesign;
+
+    // check integrity
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        fprintf( stdout, "Abc_NtkInsertNewLogic(): Network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcHieCec.c b/abc-build/src/base/abc/abcHieCec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcHieCec.c
@@ -0,0 +1,764 @@
+/**CFile****************************************************************
+
+  FileName    [abcHieCec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Hierarchical CEC manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcHieCec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "base/io/ioAbc.h"
+#include "aig/gia/gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define Abc_ObjForEachFaninReal( pObj, pFanin, i )          \
+    for ( i = 0; (i < Abc_ObjFaninNum(pObj)) && (((pFanin) = Abc_ObjFaninReal(pObj, i)), 1); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the real faniin of the object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Abc_Obj_t * Abc_ObjFaninReal( Abc_Obj_t * pObj, int i )    
+{
+    Abc_Obj_t * pRes;
+    if ( Abc_ObjIsBox(pObj) )
+        pRes = Abc_ObjFanin0( Abc_ObjFanin0( Abc_ObjFanin(pObj, i) ) );
+    else
+    {
+        assert( Abc_ObjIsPo(pObj) || Abc_ObjIsNode(pObj) );
+        pRes = Abc_ObjFanin0( Abc_ObjFanin(pObj, i) );
+    }
+    if ( Abc_ObjIsBo(pRes) )
+        return Abc_ObjFanin0(pRes);
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DFS for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDfsBoxes_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    if ( Abc_ObjIsPi(pNode) )
+        return;
+    assert( Abc_ObjIsNode(pNode) || Abc_ObjIsBox(pNode) );
+    // if this node is already visited, skip
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return;
+    Abc_NodeSetTravIdCurrent( pNode );
+    // visit the transitive fanin of the node
+    Abc_ObjForEachFaninReal( pNode, pFanin, i )
+        Abc_NtkDfsBoxes_rec( pFanin, vNodes );
+    // add the node after the fanins have been added
+    Vec_PtrPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of node and boxes reachable from POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsBoxes( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj;
+    int i;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    // set the traversal ID
+    Abc_NtkIncrementTravId( pNtk );
+    // start the array of nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        Abc_NtkDfsBoxes_rec( Abc_ObjFaninReal(pObj, 0), vNodes );
+    return vNodes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes one logic node using its SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDeriveFlatGiaSop( Gia_Man_t * pGia, int * gFanins, char * pSop )
+{
+    char * pCube;
+    int gAnd, gSum;
+    int i, Value, nFanins;
+    // get the number of variables
+    nFanins = Abc_SopGetVarNum(pSop);
+    if ( Abc_SopIsExorType(pSop) )
+    {
+        gSum = 0; 
+        for ( i = 0; i < nFanins; i++ )
+            gSum = Gia_ManHashXor( pGia, gSum, gFanins[i] );
+    }
+    else
+    {
+        // go through the cubes of the node's SOP
+        gSum = 0; 
+        Abc_SopForEachCube( pSop, nFanins, pCube )
+        {
+            // create the AND of literals
+            gAnd = 1;
+            Abc_CubeForEachVar( pCube, Value, i )
+            {
+                if ( Value == '1' )
+                    gAnd = Gia_ManHashAnd( pGia, gAnd, gFanins[i] );
+                else if ( Value == '0' )
+                    gAnd = Gia_ManHashAnd( pGia, gAnd, Abc_LitNot(gFanins[i]) );
+            }
+            // add to the sum of cubes
+            gSum = Gia_ManHashAnd( pGia, Abc_LitNot(gSum), Abc_LitNot(gAnd) );
+            gSum = Abc_LitNot( gSum );
+        }
+    }
+    // decide whether to complement the result
+    if ( Abc_SopIsComplement(pSop) )
+        gSum = Abc_LitNot(gSum);
+    return gSum;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Flattens the logic hierarchy of the netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDeriveFlatGia_rec( Gia_Man_t * pGia, Abc_Ntk_t * pNtk )
+{
+    int gFanins[16];
+    Vec_Ptr_t * vOrder = (Vec_Ptr_t *)pNtk->pData;
+    Abc_Obj_t * pObj, * pTerm;
+    Abc_Ntk_t * pNtkModel;
+    int i, k;
+    Abc_NtkForEachPi( pNtk, pTerm, i )
+        assert( Abc_ObjFanout0(pTerm)->iTemp >= 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i )
+    {
+        if ( Abc_ObjIsNode(pObj) )
+        {
+            char * pSop = (char *)pObj->pData;
+/*
+            int nLength = strlen(pSop);
+            if ( nLength == 4 ) // buf/inv
+            {
+                assert( pSop[2] == '1' );
+                assert( pSop[0] == '0' || pSop[0] == '1' );
+                assert( Abc_ObjFanin0(pObj)->iTemp >= 0 );
+                Abc_ObjFanout0(pObj)->iTemp = Abc_LitNotCond( Abc_ObjFanin0(pObj)->iTemp, pSop[0]=='0' );
+                continue;
+            }
+            if ( nLength == 5 ) // and2
+            {
+                assert( pSop[3] == '1' );
+                assert( pSop[0] == '0' || pSop[0] == '1' );
+                assert( pSop[1] == '0' || pSop[1] == '1' );
+                assert( Abc_ObjFanin0(pObj)->iTemp >= 0 );
+                assert( Abc_ObjFanin1(pObj)->iTemp >= 0 );
+                Abc_ObjFanout0(pObj)->iTemp = Gia_ManHashAnd( pGia, 
+                    Abc_LitNotCond( Abc_ObjFanin0(pObj)->iTemp, pSop[0]=='0' ),
+                    Abc_LitNotCond( Abc_ObjFanin1(pObj)->iTemp, pSop[1]=='0' )
+                    );
+                continue;
+            }
+*/
+            assert( Abc_ObjFaninNum(pObj) <= 16 );
+            assert( Abc_ObjFaninNum(pObj) == Abc_SopGetVarNum(pSop) );
+            Abc_ObjForEachFanin( pObj, pTerm, k )
+            {
+                gFanins[k] = pTerm->iTemp;
+                assert( gFanins[k] >= 0 );
+            }
+            Abc_ObjFanout0(pObj)->iTemp = Abc_NtkDeriveFlatGiaSop( pGia, gFanins, pSop );
+            continue;
+        }
+        assert( Abc_ObjIsBox(pObj) );
+        pNtkModel = (Abc_Ntk_t *)pObj->pData;
+        Abc_NtkFillTemp( pNtkModel );
+        // check the match between the number of actual and formal parameters
+        assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) );
+        assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) );
+        // assign PIs
+        Abc_ObjForEachFanin( pObj, pTerm, k )
+            Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->iTemp = Abc_ObjFanin0(pTerm)->iTemp;
+        // call recursively
+        Abc_NtkDeriveFlatGia_rec( pGia, pNtkModel );
+        // assign POs
+        Abc_ObjForEachFanout( pObj, pTerm, k )
+            Abc_ObjFanout0(pTerm)->iTemp = Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->iTemp;
+    }
+    Abc_NtkForEachPo( pNtk, pTerm, i )
+        assert( Abc_ObjFanin0(pTerm)->iTemp >= 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Flattens the logic hierarchy of the netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Abc_NtkDeriveFlatGia( Abc_Ntk_t * pNtk )
+{
+    Gia_Man_t * pTemp, * pGia = NULL;
+    Abc_Obj_t * pTerm;
+    int i;
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( !Abc_NtkLatchNum(pNtk) );
+    Abc_NtkFillTemp( pNtk );
+    // start the network
+    pGia = Gia_ManStart( (1<<16) );
+    pGia->pName = Abc_UtilStrsav( Abc_NtkName(pNtk) );
+    pGia->pSpec = Abc_UtilStrsav( Abc_NtkSpec(pNtk) );
+    Gia_ManHashAlloc( pGia );
+    // create PIs
+    Abc_NtkForEachPi( pNtk, pTerm, i )
+        Abc_ObjFanout0(pTerm)->iTemp = Gia_ManAppendCi( pGia );
+    // recursively flatten hierarchy
+    Abc_NtkDeriveFlatGia_rec( pGia, pNtk );
+    // create POs
+    Abc_NtkForEachPo( pNtk, pTerm, i )
+        Gia_ManAppendCo( pGia, Abc_ObjFanin0(pTerm)->iTemp );
+    // prepare return value
+    Gia_ManHashStop( pGia );
+    Gia_ManSetRegNum( pGia, 0 );
+    pGia = Gia_ManCleanup( pTemp = pGia );
+    Gia_ManStop( pTemp );
+    return pGia;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the total number of AIG nodes before flattening.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCountAndNodes( Vec_Ptr_t * vOrder )
+{
+    Gia_Man_t * pGiaBox;
+    Abc_Ntk_t * pNtkModel;
+    Abc_Obj_t * pObj;
+    int i, Counter = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i )
+    {
+        if ( Abc_ObjIsNode(pObj) )
+        {
+            Counter++;
+            continue;
+        }
+        assert( Abc_ObjIsBox(pObj) );
+        pNtkModel = (Abc_Ntk_t *)pObj->pData;
+        pGiaBox   = (Gia_Man_t *)pNtkModel->pData;
+        Counter  += Gia_ManAndNum(pGiaBox);
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Flattens the logic hierarchy of the netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Abc_NtkDeriveFlatGia2Derive( Abc_Ntk_t * pNtk, Vec_Ptr_t * vOrder )
+{
+    int gFanins[16];
+    Abc_Ntk_t * pNtkModel;
+    Gia_Man_t * pGiaBox, * pGia = NULL;
+    Gia_Obj_t * pGiaObj;
+    Abc_Obj_t * pTerm, * pObj;
+    int i, k;
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( !Abc_NtkLatchNum(pNtk) );
+    Abc_NtkFillTemp( pNtk );
+
+    // start the network
+    pGia = Gia_ManStart( (1<<15) );
+    pGia->pName = Abc_UtilStrsav( Abc_NtkName(pNtk) );
+    pGia->pSpec = Abc_UtilStrsav( Abc_NtkSpec(pNtk) );
+    Gia_ManHashAlloc( pGia );
+    // create PIs
+    Abc_NtkForEachPi( pNtk, pTerm, i )
+        Abc_ObjFanout0(pTerm)->iTemp = Gia_ManAppendCi( pGia );
+    // recursively flatten hierarchy
+    Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i )
+    {
+        if ( Abc_ObjIsNode(pObj) )
+        {
+            char * pSop = (char *)pObj->pData;
+            assert( Abc_ObjFaninNum(pObj) <= 16 );
+            assert( Abc_ObjFaninNum(pObj) == Abc_SopGetVarNum(pSop) );
+            Abc_ObjForEachFanin( pObj, pTerm, k )
+            {
+                gFanins[k] = pTerm->iTemp;
+                assert( gFanins[k] >= 0 );
+            }
+            Abc_ObjFanout0(pObj)->iTemp = Abc_NtkDeriveFlatGiaSop( pGia, gFanins, pSop );
+            continue;
+        }
+        assert( Abc_ObjIsBox(pObj) );
+        pNtkModel = (Abc_Ntk_t *)pObj->pData;
+        // check the match between the number of actual and formal parameters
+        assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) );
+        assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) );
+/*
+        // assign PIs
+        Abc_ObjForEachFanin( pObj, pTerm, k )
+            Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->iTemp = Abc_ObjFanin0(pTerm)->iTemp;
+        // call recursively
+        Abc_NtkDeriveFlatGia_rec( pGia, pNtkModel );
+        // assign POs
+        Abc_ObjForEachFanout( pObj, pTerm, k )
+            Abc_ObjFanout0(pTerm)->iTemp = Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->iTemp;
+*/ 
+        // duplicate the AIG
+        pGiaBox = (Gia_Man_t *)pNtkModel->pData;
+        assert( Abc_ObjFaninNum(pObj) == Gia_ManPiNum(pGiaBox) );
+        assert( Abc_ObjFanoutNum(pObj) == Gia_ManPoNum(pGiaBox) );
+        Gia_ManFillValue( pGiaBox );
+        Gia_ManConst0(pGiaBox)->Value = 0;
+        Abc_ObjForEachFanin( pObj, pTerm, k )
+            Gia_ManPi(pGiaBox, k)->Value = Abc_ObjFanin0(pTerm)->iTemp;
+        Gia_ManForEachAnd( pGiaBox, pGiaObj, k )
+            pGiaObj->Value = Gia_ManHashAnd( pGia, Gia_ObjFanin0Copy(pGiaObj), Gia_ObjFanin1Copy(pGiaObj) );
+        Abc_ObjForEachFanout( pObj, pTerm, k )
+            Abc_ObjFanout0(pTerm)->iTemp = Gia_ObjFanin0Copy(Gia_ManPo(pGiaBox, k));
+    }
+    // create POs
+    Abc_NtkForEachPo( pNtk, pTerm, i )
+        Gia_ManAppendCo( pGia, Abc_ObjFanin0(pTerm)->iTemp );
+    // prepare return value
+    Gia_ManHashStop( pGia );
+    Gia_ManSetRegNum( pGia, 0 );
+    pGia = Gia_ManCleanup( pGiaBox = pGia );
+    Gia_ManStop( pGiaBox );
+
+    printf( "%8d -> ", Abc_NtkCountAndNodes(vOrder) );
+    Gia_ManPrintStats( pGia, NULL );
+    return pGia;
+}
+/*
+void Abc_NtkDeriveFlatGia2_rec( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vOrder;
+    Abc_Obj_t * pObj;
+    int i;
+    if ( pNtk->pData != NULL )
+        return;
+    vOrder = Abc_NtkDfsBoxes( pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i )
+        if ( Abc_ObjIsBox(pObj) )
+            Abc_NtkDeriveFlatGia2_rec( (Abc_Ntk_t *)pObj->pData );
+    pNtk->pData = Abc_NtkDeriveFlatGia2Derive( pNtk, vOrder );
+    Vec_PtrFree( vOrder );
+}
+
+Gia_Man_t * Abc_NtkDeriveFlatGia2( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vMods;
+    Abc_Ntk_t * pModel;
+    Gia_Man_t * pGia = NULL;
+    int i;
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( !Abc_NtkLatchNum(pNtk) );
+
+    vMods = pNtk->pDesign->vModules;
+    Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i )
+        pModel->pData = NULL;
+
+    Abc_NtkDeriveFlatGia2_rec( pNtk );
+    pGia = pNtk->pData;  pNtk->pData = NULL;
+    
+    Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i )
+        Gia_ManStopP( (Gia_Man_t **)&pModel->pData );
+
+    return pGia;
+}
+*/
+Gia_Man_t * Abc_NtkDeriveFlatGia2( Abc_Ntk_t * pNtk, Vec_Ptr_t * vModels )
+{ 
+    Vec_Ptr_t * vOrder;
+    Abc_Ntk_t * pModel = NULL;
+    Gia_Man_t * pGia = NULL;
+    int i;
+
+    Vec_PtrForEachEntry( Abc_Ntk_t *, vModels, pModel, i )
+    {
+        vOrder = Abc_NtkDfsBoxes( pModel );
+        pModel->pData = Abc_NtkDeriveFlatGia2Derive( pModel, vOrder );
+        Vec_PtrFree( vOrder );
+    }
+
+    pGia = (Gia_Man_t *)pModel->pData;  pModel->pData = NULL;
+
+    Vec_PtrForEachEntry( Abc_Ntk_t *, vModels, pModel, i )
+        Gia_ManStopP( (Gia_Man_t **)&pModel->pData );
+
+    return pGia;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collect models in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCollectHie_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vModels )
+{
+    Vec_Ptr_t * vOrder;
+    Abc_Obj_t * pObj;
+    int i;
+    if ( pNtk->iStep >= 0 )
+        return;
+    vOrder = Abc_NtkDfsBoxes( pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i )
+        if ( Abc_ObjIsBox(pObj) && (Abc_Ntk_t *)pObj->pData != pNtk )
+            Abc_NtkCollectHie_rec( (Abc_Ntk_t *)pObj->pData, vModels );
+    Vec_PtrFree( vOrder );
+    pNtk->iStep = Vec_PtrSize(vModels);
+    Vec_PtrPush( vModels, pNtk );
+}
+
+Vec_Ptr_t * Abc_NtkCollectHie( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vMods, * vResult;
+    Abc_Ntk_t * pModel;
+    int i;
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( !Abc_NtkLatchNum(pNtk) );
+
+    vResult = Vec_PtrAlloc( 1000 );
+    if ( pNtk->pDesign == NULL )
+    {
+        Vec_PtrPush( vResult, pNtk );
+        return vResult;
+    }
+
+    vMods = pNtk->pDesign->vModules;
+    Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i )
+        pModel->iStep = -1;
+
+    Abc_NtkCollectHie_rec( pNtk, vResult );
+    return vResult;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of intstances.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCountInst_rec( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vOrder;
+    Abc_Obj_t * pObj;
+    int i, Counter = 0;
+    if ( pNtk->iStep >= 0 )
+        return pNtk->iStep;
+    vOrder = Abc_NtkDfsBoxes( pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i )
+        if ( Abc_ObjIsBox(pObj) && (Abc_Ntk_t *)pObj->pData != pNtk )
+            Counter += Abc_NtkCountInst_rec( (Abc_Ntk_t *)pObj->pData );
+    Vec_PtrFree( vOrder );
+    return pNtk->iStep = 1 + Counter;
+}
+
+void Abc_NtkCountInst( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vMods;
+    Abc_Ntk_t * pModel;
+    int i, Counter;
+
+    if ( pNtk->pDesign == NULL )
+        Counter = Abc_NtkNodeNum(pNtk);
+    else
+    {
+        vMods = pNtk->pDesign->vModules;
+        Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i )
+            pModel->iStep = -1;
+        Counter = Abc_NtkCountInst_rec( pNtk );
+    }
+    printf( "Instances = %10d.\n", Counter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+double Abc_NtkCountNodes_rec( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vOrder;
+    Abc_Obj_t * pObj;
+    double Counter = 0;
+    int i;
+    if ( pNtk->dTemp >= 0 )
+        return pNtk->dTemp;
+    vOrder = Abc_NtkDfsBoxes( pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i )
+        if ( Abc_ObjIsNode(pObj) )
+            Counter++;
+        else if ( Abc_ObjIsBox(pObj) && (Abc_Ntk_t *)pObj->pData != pNtk )
+            Counter += Abc_NtkCountNodes_rec( (Abc_Ntk_t *)pObj->pData );
+    Vec_PtrFree( vOrder );
+    return pNtk->dTemp = Counter;
+}
+
+void Abc_NtkCountNodes( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vMods;
+    Abc_Ntk_t * pModel;
+    double Counter;
+    int i;
+
+    if ( pNtk->pDesign == NULL )
+        Counter = Abc_NtkNodeNum(pNtk);
+    else
+    {
+        vMods = pNtk->pDesign->vModules;
+        Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i )
+            pModel->dTemp = -1;
+        Counter = Abc_NtkCountNodes_rec( pNtk );
+    }
+    printf( "Nodes = %.0f\n", Counter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if there is a recursive definition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheckRecursive( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vMods;
+    Abc_Ntk_t * pModel;
+    Abc_Obj_t * pObj;
+    int i, k, RetValue = 0;
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( !Abc_NtkLatchNum(pNtk) );
+
+    if ( pNtk->pDesign == NULL )
+        return RetValue;
+
+    vMods = pNtk->pDesign->vModules;
+    Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i )
+    {
+        Abc_NtkForEachObj( pModel, pObj, k )
+            if ( Abc_ObjIsBox(pObj) && pObj->pData == (void *)pModel )
+            {
+                printf( "WARNING: Model \"%s\" contains a recursive defition.\n", Abc_NtkName(pModel) );
+                RetValue = 1;
+                break;
+            }
+    }
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs hierarchical equivalence checking.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Abc_NtkHieCecTest( char * pFileName, int fVerbose )
+{
+    int fUseTest = 1;
+    int fUseNew = 0;
+    int fCheck = 1;
+    Vec_Ptr_t * vMods, * vOrder;
+    Abc_Ntk_t * pNtk, * pModel;
+    Gia_Man_t * pGia;
+    int i;
+    abctime clk = Abc_Clock();
+
+    // read hierarchical netlist
+    pNtk = Io_ReadBlifMv( pFileName, 0, fCheck );
+    if ( pNtk == NULL )
+    {
+        printf( "Reading BLIF file has failed.\n" );
+        return NULL;
+    }
+    if ( pNtk->pDesign == NULL || pNtk->pDesign->vModules == NULL )
+    {
+        printf( "There is no hierarchy information.\n" );
+//        Abc_NtkDelete( pNtk );
+//        return NULL;
+    }
+    Abc_PrintTime( 1, "Reading file", Abc_Clock() - clk );
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( !Abc_NtkLatchNum(pNtk) );
+/*
+    if ( pNtk->pDesign != NULL )
+    {
+        clk = Abc_Clock();
+        Abc_NtkCountNodes( pNtk );
+        Abc_PrintTime( 1, "Count nodes", Abc_Clock() - clk );
+    }
+*/
+    // print stats
+    if ( fVerbose )
+        Abc_NtkPrintBoxInfo( pNtk );
+
+    // test the new data-structure
+    if ( fUseTest )
+    {
+        extern Gia_Man_t * Au_ManDeriveTest( Abc_Ntk_t * pRoot );
+        Gia_Man_t * pGia;
+        pGia = Au_ManDeriveTest( pNtk );
+        Abc_NtkDelete( pNtk );
+        return pGia;
+    }
+
+    if ( Abc_NtkCheckRecursive(pNtk) )
+        return NULL;
+
+    if ( fUseNew )
+    {
+        clk = Abc_Clock();
+        vOrder = Abc_NtkCollectHie( pNtk );
+        Abc_PrintTime( 1, "Collect DFS ", Abc_Clock() - clk );
+
+        // derive GIA
+        clk = Abc_Clock();
+        pGia = Abc_NtkDeriveFlatGia2( pNtk, vOrder );
+        Abc_PrintTime( 1, "Deriving GIA", Abc_Clock() - clk );
+        Gia_ManPrintStats( pGia, NULL );
+    //    Gia_ManStop( pGia );
+ 
+        Vec_PtrFree( vOrder );
+    }
+    else
+    {
+        // order nodes/boxes of all models
+        vMods = pNtk->pDesign->vModules;
+        Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i )
+            pModel->pData = Abc_NtkDfsBoxes( pModel );
+
+        // derive GIA
+        clk = Abc_Clock();
+        pGia = Abc_NtkDeriveFlatGia( pNtk );
+        Abc_PrintTime( 1, "Deriving GIA", Abc_Clock() - clk );
+        Gia_ManPrintStats( pGia, NULL );
+
+        // clean nodes/boxes of all nodes
+        Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i )
+            Vec_PtrFree( (Vec_Ptr_t *)pModel->pData );
+    }
+
+    clk = Abc_Clock();
+    Abc_NtkCountInst( pNtk );
+    Abc_PrintTime( 1, "Gather stats", Abc_Clock() - clk );
+
+    Abc_NtkDelete( pNtk );
+    return pGia;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcHieNew.c b/abc-build/src/base/abc/abcHieNew.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcHieNew.c
@@ -0,0 +1,1635 @@
+/**CFile****************************************************************
+
+  FileName    [abcHieNew.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [New hierarchy manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcHieNew.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+#include "misc/util/utilNam.h"
+#include "misc/extra/extra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define AU_MAX_FANINS 0x1FFFFFFF
+ 
+typedef enum { 
+    AU_OBJ_NONE,           // 0: non-existent object
+    AU_OBJ_CONST0,         // 1: constant node
+    AU_OBJ_PI,             // 2: primary input
+    AU_OBJ_PO,             // 3: primary output
+    AU_OBJ_FAN,            // 4: box output
+    AU_OBJ_FLOP,           // 5: flip-flop
+    AU_OBJ_BOX,            // 6: box
+    AU_OBJ_NODE,           // 7: logic node
+    AU_OBJ_VOID            // 8: placeholder
+} Au_Type_t;
+
+
+typedef struct Au_Man_t_   Au_Man_t;
+typedef struct Au_Ntk_t_   Au_Ntk_t;
+typedef struct Au_Obj_t_   Au_Obj_t;
+
+struct Au_Obj_t_ // 16 bytes
+{
+    unsigned               Func    : 30;       // functionality
+    unsigned               Value   :  2;       // node value
+    unsigned               Type    :  3;       // object type
+    unsigned               nFanins : 29;       // fanin count (related to AU_MAX_FANIN_NUM)
+    int                    Fanins[2];          // fanin literals
+};
+
+struct Au_Ntk_t_ 
+{
+    char *                 pName;              // model name
+    Au_Man_t *             pMan;               // model manager
+    int                    Id;                 // model ID
+    // objects
+    Vec_Int_t              vPis;               // primary inputs (CI id -> handle)
+    Vec_Int_t              vPos;               // primary outputs (CI id -> handle)
+    Vec_Int_t              vObjs;              // internal nodes (obj id -> handle)
+    int                    nObjs[AU_OBJ_VOID]; // counter of objects of each type
+    // memory for objects
+    Vec_Ptr_t *            vChunks;            // memory pages
+    Vec_Ptr_t              vPages;             // memory pages
+    int                    iHandle;            // currently available ID
+    int                    nObjsAlloc;         // the total number of objects allocated
+    int                    nObjsUsed;          // the number of useful entries
+    // object attributes
+    int                    nTravIds;           // counter of traversal IDs
+    Vec_Int_t              vTravIds;           // trav IDs of the objects
+    Vec_Int_t              vCopies;            // object copies
+    // structural hashing
+    int                    nHTable;            // hash table size
+    int *                  pHTable;            // hash table
+    Au_Obj_t *             pConst0;            // constant node
+    // statistics
+    int                    fMark;
+    double                 nBoxes;
+    double                 nNodes;
+    double                 nPorts;
+    double                 nNodeAnds;
+    double                 nNodeXors;
+    double                 nNodeMuxs;
+};
+
+struct Au_Man_t_ 
+{
+    char *                 pName;              // the name of the library
+    Vec_Ptr_t              vNtks;              // the array of modules
+    Abc_Nam_t *            pFuncs;             // hashing functions into integers
+    int                    nRefs;              // reference counter
+    // statistics
+    int                    nGiaObjMax;         // max number of GIA objects
+    double                 nPortsC0;           // const ports
+    double                 nPortsC1;           // const ports
+    double                 nPortsNC;           // non-const ports
+};
+
+
+static inline int          Au_Var2Lit( int Var, int fCompl )             { return Var + Var + fCompl;                       }
+static inline int          Au_Lit2Var( int Lit )                         { return Lit >> 1;                                 }
+static inline int          Au_LitIsCompl( int Lit )                      { return Lit & 1;                                  }
+static inline int          Au_LitNot( int Lit )                          { return Lit ^ 1;                                  }
+static inline int          Au_LitNotCond( int Lit, int c )               { return Lit ^ (int)(c > 0);                       }
+static inline int          Au_LitRegular( int Lit )                      { return Lit & ~01;                                }
+
+static inline Au_Obj_t *   Au_Regular( Au_Obj_t * p )                    { return (Au_Obj_t *)((ABC_PTRUINT_T)(p) & ~01);   }
+static inline Au_Obj_t *   Au_Not( Au_Obj_t * p )                        { return (Au_Obj_t *)((ABC_PTRUINT_T)(p) ^  01);   }
+static inline Au_Obj_t *   Au_NotCond( Au_Obj_t * p, int c )             { return (Au_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c));   }
+static inline int          Au_IsComplement( Au_Obj_t * p )               { return (int)((ABC_PTRUINT_T)(p) & 01);           }
+ 
+static inline char *       Au_UtilStrsav( char * s )                     { return s ? strcpy(ABC_ALLOC(char, strlen(s)+1), s) : NULL;             }
+
+static inline char *       Au_ManName( Au_Man_t * p )                    { return p->pName;                                                       }
+static inline int          Au_ManNtkNum( Au_Man_t * p )                  { return Vec_PtrSize(&p->vNtks) - 1;                                     }
+static inline Au_Ntk_t *   Au_ManNtk( Au_Man_t * p, int i )              { return (Au_Ntk_t *)Vec_PtrEntry(&p->vNtks, i);                         }
+static inline Au_Ntk_t *   Au_ManNtkRoot( Au_Man_t * p )                 { return Au_ManNtk( p, 1 );                                              }
+
+static inline char *       Au_NtkName( Au_Ntk_t * p )                    { return p->pName;                                                       }
+static inline Au_Man_t *   Au_NtkMan( Au_Ntk_t * p )                     { return p->pMan;                                                        }
+static inline int          Au_NtkPiNum( Au_Ntk_t * p )                   { return p->nObjs[AU_OBJ_PI];                                            } 
+static inline int          Au_NtkPoNum( Au_Ntk_t * p )                   { return p->nObjs[AU_OBJ_PO];                                            } 
+static inline int          Au_NtkFanNum( Au_Ntk_t * p )                  { return p->nObjs[AU_OBJ_FAN];                                           } 
+static inline int          Au_NtkFlopNum( Au_Ntk_t * p )                 { return p->nObjs[AU_OBJ_FLOP];                                          } 
+static inline int          Au_NtkBoxNum( Au_Ntk_t * p )                  { return p->nObjs[AU_OBJ_BOX];                                           } 
+static inline int          Au_NtkNodeNum( Au_Ntk_t * p )                 { return p->nObjs[AU_OBJ_NODE];                                          } 
+static inline int          Au_NtkObjNumMax( Au_Ntk_t * p )               { return (Vec_PtrSize(&p->vPages) - 1) * (1 << 12) + p->iHandle;         } 
+static inline int          Au_NtkObjNum( Au_Ntk_t * p )                  { return Vec_IntSize(&p->vObjs);                                         } 
+static inline Au_Obj_t *   Au_NtkObj( Au_Ntk_t * p, int h )              { return (Au_Obj_t *)p->vPages.pArray[h >> 12] + (h & 0xFFF);            }
+
+static inline Au_Obj_t *   Au_NtkPi( Au_Ntk_t * p, int i )               { return Au_NtkObj(p, Vec_IntEntry(&p->vPis, i));                        }
+static inline Au_Obj_t *   Au_NtkPo( Au_Ntk_t * p, int i )               { return Au_NtkObj(p, Vec_IntEntry(&p->vPos, i));                        }
+static inline Au_Obj_t *   Au_NtkObjI( Au_Ntk_t * p, int i )             { return Au_NtkObj(p, Vec_IntEntry(&p->vObjs, i));                       }
+
+static inline int          Au_ObjIsNone( Au_Obj_t * p )                  { return p->Type == AU_OBJ_NONE;                                         } 
+static inline int          Au_ObjIsConst0( Au_Obj_t * p )                { return p->Type == AU_OBJ_CONST0;                                       } 
+static inline int          Au_ObjIsPi( Au_Obj_t * p )                    { return p->Type == AU_OBJ_PI;                                           } 
+static inline int          Au_ObjIsPo( Au_Obj_t * p )                    { return p->Type == AU_OBJ_PO;                                           } 
+static inline int          Au_ObjIsFan( Au_Obj_t * p )                   { return p->Type == AU_OBJ_FAN;                                          } 
+static inline int          Au_ObjIsFlop( Au_Obj_t * p )                  { return p->Type == AU_OBJ_FLOP;                                         } 
+static inline int          Au_ObjIsBox( Au_Obj_t * p )                   { return p->Type == AU_OBJ_BOX;                                          } 
+static inline int          Au_ObjIsNode( Au_Obj_t * p )                  { return p->Type == AU_OBJ_NODE;                                         }
+static inline int          Au_ObjIsTerm( Au_Obj_t * p )                  { return p->Type >= AU_OBJ_PI && p->Type <= AU_OBJ_FLOP;                 } 
+
+static inline char *       Au_ObjBase( Au_Obj_t * p )                    { return (char *)p - ((ABC_PTRINT_T)p & 0x3FF);                          } 
+static inline Au_Ntk_t *   Au_ObjNtk( Au_Obj_t * p )                     { return ((Au_Ntk_t **)Au_ObjBase(p))[0];                                } 
+static inline int          Au_ObjId( Au_Obj_t * p )                      { return ((int *)Au_ObjBase(p))[2] | (((ABC_PTRINT_T)p & 0x3FF) >> 4);   }
+static inline int          Au_ObjPioNum( Au_Obj_t * p )                  { assert(Au_ObjIsTerm(p)); return p->Fanins[p->nFanins];                 }
+static inline int          Au_ObjFunc( Au_Obj_t * p )                    { return p->Func;                                                        }
+static inline Au_Ntk_t *   Au_ObjModel( Au_Obj_t * p )                   { assert(Au_ObjIsFan(p)||Au_ObjIsBox(p)); return Au_ManNtk(Au_NtkMan(Au_ObjNtk(p)), p->Func); }
+
+static inline int          Au_ObjFaninNum( Au_Obj_t * p )                { return p->nFanins;                                                     }
+static inline int          Au_ObjFaninId( Au_Obj_t * p, int i )          { assert(i >= 0 && i < (int)p->nFanins && p->Fanins[i]); return Au_Lit2Var(p->Fanins[i]);     }
+static inline int          Au_ObjFaninId0( Au_Obj_t * p )                { return Au_ObjFaninId(p, 0);                                                                 }
+static inline int          Au_ObjFaninId1( Au_Obj_t * p )                { return Au_ObjFaninId(p, 1);                                                                 }
+static inline int          Au_ObjFaninId2( Au_Obj_t * p )                { return Au_ObjFaninId(p, 2);                                                                 }
+static inline Au_Obj_t *   Au_ObjFanin( Au_Obj_t * p, int i )            { return Au_NtkObj(Au_ObjNtk(p), Au_ObjFaninId(p, i));                                        }
+static inline Au_Obj_t *   Au_ObjFanin0( Au_Obj_t * p )                  { return Au_ObjFanin( p, 0 );                                                                 }
+static inline Au_Obj_t *   Au_ObjFanin1( Au_Obj_t * p )                  { return Au_ObjFanin( p, 1 );                                                                 }
+static inline Au_Obj_t *   Au_ObjFanin2( Au_Obj_t * p )                  { return Au_ObjFanin( p, 2 );                                                                 }
+static inline int          Au_ObjFaninC( Au_Obj_t * p, int i )           { assert(i >= 0 && i < (int)p->nFanins && p->Fanins[i]); return Au_LitIsCompl(p->Fanins[i]);  }
+static inline int          Au_ObjFaninC0( Au_Obj_t * p )                 { return Au_ObjFaninC(p, 0);                                                                  }
+static inline int          Au_ObjFaninC1( Au_Obj_t * p )                 { return Au_ObjFaninC(p, 1);                                                                  }
+static inline int          Au_ObjFaninC2( Au_Obj_t * p )                 { return Au_ObjFaninC(p, 2);                                                                  }
+static inline int          Au_ObjFaninLit( Au_Obj_t * p, int i )         { assert(i >= 0 && i < (int)p->nFanins && p->Fanins[i]); return p->Fanins[i];                 }
+static inline void         Au_ObjSetFanin( Au_Obj_t * p, int i, int f )  { assert(f > 0 && p->Fanins[i] == 0); p->Fanins[i] = Au_Var2Lit(f,0);                         }
+static inline void         Au_ObjSetFaninLit( Au_Obj_t * p, int i, int f){ assert(f >= 0 && p->Fanins[i] == 0); p->Fanins[i] = f;                                      }
+
+static inline int          Au_BoxFanoutNum( Au_Obj_t * p )               { assert(Au_ObjIsBox(p)); return p->Fanins[p->nFanins];                                       }
+static inline int          Au_BoxFanoutId( Au_Obj_t * p, int i )         { assert(i >= 0 && i < Au_BoxFanoutNum(p)); return p->Fanins[p->nFanins+1+i];                 }
+static inline Au_Obj_t *   Au_BoxFanout( Au_Obj_t * p, int i )           { return Au_NtkObj(Au_ObjNtk(p), Au_BoxFanoutId(p, i));                                       }
+
+static inline int          Au_ObjCopy( Au_Obj_t * p )                    { return Vec_IntEntry( &Au_ObjNtk(p)->vCopies, Au_ObjId(p) );                                 }
+static inline void         Au_ObjSetCopy( Au_Obj_t * p, int c )          { Vec_IntWriteEntry( &Au_ObjNtk(p)->vCopies, Au_ObjId(p), c );                                }
+
+static inline int          Au_ObjFanout( Au_Obj_t * p, int i )           { assert(p->Type == AU_OBJ_BOX && i >= 0 && i < p->Fanins[p->nFanins] && p->Fanins[i]); return p->Fanins[p->nFanins + 1 + i];             }
+static inline void         Au_ObjSetFanout( Au_Obj_t * p, int i, int f ) { assert(p->Type == AU_OBJ_BOX && i >= 0 && i < p->Fanins[p->nFanins] && p->Fanins[i] == 0 && f > 0); p->Fanins[p->nFanins + 1 + i] = f;  }
+
+static inline void         Au_NtkIncrementTravId( Au_Ntk_t * p )            { if (p->vTravIds.pArray == NULL) Vec_IntFill(&p->vTravIds, Au_NtkObjNumMax(p)+500, 0); p->nTravIds++; assert(p->nTravIds < (1<<30));  }
+static inline void         Au_ObjSetTravIdCurrent( Au_Obj_t * p )           { Vec_IntSetEntry(&Au_ObjNtk(p)->vTravIds, Au_ObjId(p), Au_ObjNtk(p)->nTravIds );                        }
+static inline void         Au_ObjSetTravIdPrevious( Au_Obj_t * p )          { Vec_IntSetEntry(&Au_ObjNtk(p)->vTravIds, Au_ObjId(p), Au_ObjNtk(p)->nTravIds-1 );                      }
+static inline int          Au_ObjIsTravIdCurrent( Au_Obj_t * p )            { return (Vec_IntGetEntry(&Au_ObjNtk(p)->vTravIds, Au_ObjId(p)) == Au_ObjNtk(p)->nTravIds);              }
+static inline int          Au_ObjIsTravIdPrevious( Au_Obj_t * p )           { return (Vec_IntGetEntry(&Au_ObjNtk(p)->vTravIds, Au_ObjId(p)) == Au_ObjNtk(p)->nTravIds-1);            }
+static inline void         Au_ObjSetTravIdCurrentId( Au_Ntk_t * p, int Id ) { Vec_IntSetEntry(&p->vTravIds, Id, p->nTravIds );                                                       }
+static inline int          Au_ObjIsTravIdCurrentId( Au_Ntk_t * p, int Id )  { return (Vec_IntGetEntry(&p->vTravIds, Id) == p->nTravIds);                                             }
+
+#define Au_ManForEachNtk( p, pNtk, i )           \
+    for ( i = 1; (i < Vec_PtrSize(&p->vNtks))   && (((pNtk) = Au_ManNtk(p, i)), 1); i++ ) 
+#define Au_ManForEachNtkReverse( p, pNtk, i )    \
+    for ( i = Vec_PtrSize(&p->vNtks) - 1;(i>=1) && (((pNtk) = Au_ManNtk(p, i)), 1); i-- ) 
+
+#define Au_ObjForEachFaninId( pObj, hFanin, i )  \
+    for ( i = 0; (i < Au_ObjFaninNum(pObj))     && (((hFanin) = Au_ObjFaninId(pObj, i)), 1); i++ )  
+#define Au_BoxForEachFanoutId( pObj, hFanout, i) \
+    for ( i = 0; (i < Au_BoxFanoutNum(pObj))    && (((hFanout) = Au_BoxFanoutId(pObj, i)), 1); i++ )
+
+#define Au_ObjForEachFanin( pObj, pFanin, i )    \
+    for ( i = 0; (i < Au_ObjFaninNum(pObj))     && (((pFanin) = Au_ObjFanin(pObj, i)), 1); i++ )  
+#define Au_BoxForEachFanout( pObj, pFanout, i)   \
+    for ( i = 0; (i < Au_BoxFanoutNum(pObj))    && (((pFanout) = Au_BoxFanout(pObj, i)), 1); i++ )
+
+#define Au_NtkForEachPi( p, pObj, i )            \
+    for ( i = 0; (i < Vec_IntSize(&p->vPis))    && (((pObj) = Au_NtkPi(p, i)), 1); i++ )
+#define Au_NtkForEachPo( p, pObj, i )            \
+    for ( i = 0; (i < Vec_IntSize(&p->vPos))    && (((pObj) = Au_NtkPo(p, i)), 1); i++ )
+#define Au_NtkForEachObj( p, pObj, i )           \
+    for ( i = 0; (i < Vec_IntSize(&p->vObjs))   && (((pObj) = Au_NtkObjI(p, i)), 1); i++ )
+#define Au_NtkForEachNode( p, pObj, i )           \
+    for ( i = 0; (i < Vec_IntSize(&p->vObjs))   && (((pObj) = Au_NtkObjI(p, i)), 1); i++ ) if ( !Au_ObjIsNode(pObj) ) {} else
+#define Au_NtkForEachBox( p, pObj, i )           \
+    for ( i = 0; (i < Vec_IntSize(&p->vObjs))   && (((pObj) = Au_NtkObjI(p, i)), 1); i++ ) if ( !Au_ObjIsBox(pObj) ) {} else
+
+
+
+extern void Au_ManAddNtk( Au_Man_t * pMan, Au_Ntk_t * p );
+extern void Au_ManFree( Au_Man_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Working with models.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Au_Ntk_t * Au_NtkAlloc( Au_Man_t * pMan, char * pName )
+{
+    Au_Ntk_t * p;
+    p = ABC_CALLOC( Au_Ntk_t, 1 );
+    p->pName = Au_UtilStrsav( pName );
+    p->vChunks = Vec_PtrAlloc( 111 );
+    Vec_IntGrow( &p->vPis,  111 );
+    Vec_IntGrow( &p->vPos,  111 );
+    Vec_IntGrow( &p->vObjs, 1111 );
+    Vec_PtrGrow( &p->vPages, 11 );
+    Au_ManAddNtk( pMan, p );
+    return p;
+}
+void Au_NtkFree( Au_Ntk_t * p )
+{
+    Au_ManFree( p->pMan );
+    Vec_PtrFreeFree( p->vChunks );
+    ABC_FREE( p->vCopies.pArray );
+    ABC_FREE( p->vPages.pArray );
+    ABC_FREE( p->vObjs.pArray );
+    ABC_FREE( p->vPis.pArray );
+    ABC_FREE( p->vPos.pArray );
+    ABC_FREE( p->pHTable );
+    ABC_FREE( p->pName );
+    ABC_FREE( p );
+}
+int Au_NtkMemUsage( Au_Ntk_t * p )
+{
+    int Mem = sizeof(Au_Ntk_t);
+    Mem += 4 * p->vPis.nCap;
+    Mem += 4 * p->vPos.nCap;
+    Mem += 4 * p->vObjs.nCap;
+    Mem += 16 * p->nObjsAlloc;
+    return Mem;
+}
+void Au_NtkPrintStats( Au_Ntk_t * p )
+{
+    printf( "%-30s:",        Au_NtkName(p) );
+    printf( " i/o =%6d/%6d", Au_NtkPiNum(p), Au_NtkPoNum(p) );
+    if ( Au_NtkFlopNum(p) )
+        printf( "  lat =%5d",    Au_NtkFlopNum(p) );
+    printf( "  nd =%6d",     Au_NtkNodeNum(p) );
+//    if ( Au_NtkBoxNum(p) )
+        printf( "  box =%5d",    Au_NtkBoxNum(p) );
+    printf( "  obj =%7d",    Au_NtkObjNum(p) );
+//    printf( "  max =%7d",    Au_NtkObjNumMax(p) );
+//    printf( "  use =%7d",    p->nObjsUsed );
+    printf( " %5.1f %%",     100.0 * (Au_NtkObjNumMax(p) - Au_NtkObjNum(p)) / Au_NtkObjNumMax(p) );
+    printf( " %6.1f MB",     1.0 * Au_NtkMemUsage(p) / (1 << 20) );
+    printf( " %5.1f %%",     100.0 * (p->nObjsAlloc - p->nObjsUsed) / p->nObjsAlloc );
+    printf( "\n" );
+}
+void Au_NtkCleanCopy( Au_Ntk_t * p )
+{
+    Vec_IntFill( &p->vCopies, Au_NtkObjNumMax(p), -1 );
+}
+int Au_NtkNodeNumFunc( Au_Ntk_t * p, int Func )
+{
+    Au_Obj_t * pObj;
+    int i, Counter = 0;
+    if ( p->pMan && p->pMan->pFuncs )
+        return 0;
+    Au_NtkForEachNode( p, pObj, i )
+    {
+        Counter += (pObj->Func == (unsigned)Func);
+//        printf( "%d ", pObj->Func );
+    }
+//    printf( "\n" );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Working with manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Au_Man_t * Au_ManAlloc( char * pName )
+{
+    Au_Man_t * p;
+    p = ABC_CALLOC( Au_Man_t, 1 );
+    p->pName = Au_UtilStrsav( pName );
+    Vec_PtrGrow( &p->vNtks,  111 );
+    Vec_PtrPush( &p->vNtks, NULL );
+    return p;
+}
+void Au_ManFree( Au_Man_t * p )
+{
+    assert( p->nRefs > 0 );
+    if ( --p->nRefs > 0 )
+        return;
+    if ( p->pFuncs )
+        Abc_NamStop( p->pFuncs );
+    ABC_FREE( p->vNtks.pArray );
+    ABC_FREE( p->pName );
+    ABC_FREE( p );
+}
+void Au_ManDelete( Au_Man_t * p )
+{
+    Au_Ntk_t * pNtk;
+    int i;
+    Au_ManForEachNtk( p, pNtk, i )
+        Au_NtkFree( pNtk );
+}
+int Au_ManFindNtk( Au_Man_t * p, char * pName )
+{
+    Au_Ntk_t * pNtk;
+    int i;
+    Au_ManForEachNtk( p, pNtk, i )
+        if ( !strcmp(Au_NtkName(pNtk), pName) )
+            return i;
+    return -1;
+}
+Au_Ntk_t * Au_ManFindNtkP( Au_Man_t * p, char * pName )
+{
+    int iNtk = Au_ManFindNtk( p, pName );
+    if ( iNtk == -1 )
+        return NULL;
+    return Au_ManNtk( p, iNtk );
+}
+void Au_ManAddNtk( Au_Man_t * pMan, Au_Ntk_t * p )
+{
+    assert( Au_ManFindNtk(pMan, Au_NtkName(p)) == -1 );
+    p->pMan = pMan; pMan->nRefs++;
+    p->Id = Vec_PtrSize( &pMan->vNtks );
+    Vec_PtrPush( &pMan->vNtks, p );
+}
+int Au_ManMemUsage( Au_Man_t * p )
+{
+    Au_Ntk_t * pNtk;
+    int i, Mem = 0;
+    Au_ManForEachNtk( p, pNtk, i )
+        Mem += 16 * pNtk->nObjsAlloc;
+    return Mem;
+}
+int Au_ManMemUsageUseful( Au_Man_t * p )
+{
+    Au_Ntk_t * pNtk;
+    int i, Mem = 0;
+    Au_ManForEachNtk( p, pNtk, i )
+        Mem += 16 * pNtk->nObjsUsed;
+    return Mem;
+}
+void Au_ManPrintStats( Au_Man_t * p )
+{
+    Au_Ntk_t * pNtk;
+    int i;
+    if ( Vec_PtrSize(&p->vNtks) > 2 )
+        printf( "Design %-13s\n", Au_ManName(p) );
+    Au_ManForEachNtk( p, pNtk, i )
+        Au_NtkPrintStats( pNtk );
+    printf( "Different functions = %d. ", p->pFuncs ? Abc_NamObjNumMax(p->pFuncs) : 0 );
+    printf( "Memory = %.1f MB",  1.0 * Au_ManMemUsage(p) / (1 << 20) );
+    printf( " %5.1f %%",       100.0 * (Au_ManMemUsage(p) - Au_ManMemUsageUseful(p)) / Au_ManMemUsage(p) );
+    printf( "\n" );
+//    if ( p->pFuncs )
+//        Abc_NamPrint( p->pFuncs );
+}
+
+void Au_ManReorderModels_rec( Au_Ntk_t * pNtk, Vec_Int_t * vOrder )
+{
+    Au_Ntk_t * pBoxModel;
+    Au_Obj_t * pObj;
+    int k;
+    if ( pNtk->fMark )
+        return;
+    pNtk->fMark = 1;
+    Au_NtkForEachBox( pNtk, pObj, k )
+    {
+        pBoxModel = Au_ObjModel(pObj);
+        if ( pBoxModel == NULL || pBoxModel == pNtk )
+            continue;
+        Au_ManReorderModels_rec( pBoxModel, vOrder );
+    }
+    Vec_IntPush( vOrder, pNtk->Id );
+}
+void Au_ManReorderModels( Au_Man_t * p, Au_Ntk_t * pRoot )
+{
+    Vec_Ptr_t * vNtksNew;
+    Vec_Int_t * vOrder, * vTemp;
+    Au_Ntk_t * pNtk, * pBoxModel;
+    Au_Obj_t * pBox, * pFan;
+    int i, k, j, Entry;
+    Au_ManForEachNtk( p, pNtk, i )
+        pNtk->fMark = 0;
+    // collect networks in the DFS order
+    vOrder = Vec_IntAlloc( Au_ManNtkNum(p)+1 );
+    Vec_IntPush( vOrder, 0 );
+    Au_ManReorderModels_rec( pRoot, vOrder );
+    assert( Vec_IntEntryLast(vOrder) == pRoot->Id );
+    // add unconnected ones
+    Vec_IntPop( vOrder );
+    Au_ManForEachNtk( p, pNtk, i )
+        if ( pNtk->fMark == 0 )
+            Vec_IntPush( vOrder, pNtk->Id );
+    Vec_IntPush( vOrder, pRoot->Id );
+    assert( Vec_IntSize(vOrder) == Au_ManNtkNum(p)+1 );
+    // reverse order
+    vOrder->nSize--;
+    vOrder->pArray++;
+    Vec_IntReverseOrder( vOrder ); 
+    vOrder->pArray--;
+    vOrder->nSize++;
+    // compute new order
+    vNtksNew = Vec_PtrAlloc( Au_ManNtkNum(p)+1 );
+    Vec_IntForEachEntry( vOrder, Entry, i )
+        Vec_PtrPush( vNtksNew, Au_ManNtk(p, Entry) );
+    // invert order
+    assert( Vec_IntEntry(vOrder, 1) == pRoot->Id );
+    vOrder = Vec_IntInvert( vTemp = vOrder, 0 );
+    Vec_IntFree( vTemp );
+    assert( Vec_IntEntry(vOrder, 1) == pRoot->Id );
+    // update model numbers
+    Au_ManForEachNtk( p, pNtk, i )
+    {
+        pNtk->Id = Vec_IntEntry( vOrder, pNtk->Id );
+        Au_NtkForEachBox( pNtk, pBox, k )
+        {
+            pBox->Func = Vec_IntEntry( vOrder, pBox->Func );
+            assert( pBox->Func > 0 );
+            Au_BoxForEachFanout( pBox, pFan, j )
+                pFan->Func = pBox->Func;
+        }
+    }
+    // update
+    ABC_FREE( p->vNtks.pArray );
+    p->vNtks.pArray = vNtksNew->pArray;
+    vNtksNew->pArray = NULL;
+    Vec_PtrFree( vNtksNew );
+    // verify
+    Au_ManForEachNtk( p, pNtk, i )
+        Au_NtkForEachBox( pNtk, pBox, k )
+        {
+            pBoxModel = Au_ObjModel(pBox);
+            if ( pBoxModel == NULL || pBoxModel == pNtk )
+                continue;
+            assert( !pBox->Func || pBox->Func >= (unsigned)pNtk->Id );
+            assert( Au_ObjFaninNum(pBox) == Au_NtkPiNum(pBoxModel) );
+            assert( Au_BoxFanoutNum(pBox) == Au_NtkPoNum(pBoxModel) );
+        }
+    Vec_IntFree( vOrder );
+}
+void Au_ManCountThings( Au_Man_t * p )
+{
+    Au_Ntk_t * pNtk, * pBoxModel;
+    Au_Obj_t * pBox;
+    int i, k;//, clk = Abc_Clock();
+    Au_ManForEachNtkReverse( p, pNtk, i )
+    {
+        pNtk->nBoxes = Au_NtkBoxNum(pNtk);
+        pNtk->nNodes = Au_NtkNodeNum(pNtk);
+        pNtk->nPorts = Au_NtkPiNum(pNtk) + Au_NtkPoNum(pNtk);
+        pNtk->nNodeAnds = Au_NtkNodeNumFunc( pNtk, 1 );
+        pNtk->nNodeXors = Au_NtkNodeNumFunc( pNtk, 2 );
+        pNtk->nNodeMuxs = Au_NtkNodeNumFunc( pNtk, 3 );
+//        assert( pNtk->nNodes == pNtk->nNodeAnds + pNtk->nNodeXors + pNtk->nNodeMuxs );
+//        printf( "adding %.0f nodes of model %s\n", pNtk->nNodes, Au_NtkName(pNtk) );
+        Au_NtkForEachBox( pNtk, pBox, k )
+        {
+            pBoxModel = Au_ObjModel(pBox);
+            if ( pBoxModel == NULL || pBoxModel == pNtk )
+                continue;
+            assert( Au_ObjFaninNum(pBox) == Au_NtkPiNum(pBoxModel) );
+            assert( Au_BoxFanoutNum(pBox) == Au_NtkPoNum(pBoxModel) );
+            assert( pBoxModel->Id > pNtk->Id );
+            assert( pBoxModel->nPorts > 0 );
+            pNtk->nBoxes += pBoxModel->nBoxes;
+            pNtk->nNodes += pBoxModel->nNodes;
+            pNtk->nPorts += pBoxModel->nPorts;
+            pNtk->nNodeAnds += pBoxModel->nNodeAnds;
+            pNtk->nNodeXors += pBoxModel->nNodeXors;
+            pNtk->nNodeMuxs += pBoxModel->nNodeMuxs;
+//            printf( "    adding %.0f nodes of model %s\n", pBoxModel->nNodes, Au_NtkName(pBoxModel) );
+        }
+//        printf( "total %.0f nodes in model %s\n", pNtk->nNodes, Au_NtkName(pNtk) );
+    }
+    pNtk = Au_ManNtkRoot(p);
+    printf( "Total nodes = %15.0f. Total instances = %15.0f. Total ports = %15.0f.\n", 
+//    printf( "Total nodes = %.2e. Total instances = %.2e. Total ports = %.2e.\n", 
+        pNtk->nNodes, pNtk->nBoxes, pNtk->nPorts );
+//    printf( "Total ANDs  = %15.0f. Total XORs      = %15.0f. Total MUXes = %15.0f.\n", 
+//    printf( "Total ANDs  = %.2e. Total XORs      = %.2e. Total MUXes = %.2e.  ", 
+//        pNtk->nNodeAnds, pNtk->nNodeXors, pNtk->nNodeMuxs );
+    printf( "Total ANDs  = %15.0f.\n", pNtk->nNodeAnds );
+    printf( "Total XORs  = %15.0f.\n", pNtk->nNodeXors );
+    printf( "Total MUXes = %15.0f.\n", pNtk->nNodeMuxs );
+//    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+
+int Au_NtkCompareNames( Au_Ntk_t ** p1, Au_Ntk_t ** p2 )
+{
+    return strcmp( Au_NtkName(*p1), Au_NtkName(*p2) );
+}
+void Au_ManPrintBoxInfo( Au_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vMods;
+    Au_Ntk_t * pModel, * pBoxModel;
+    Au_Obj_t * pObj;
+    Vec_Int_t * vCounts;
+    int i, k, Num;
+    if ( pNtk->pMan == NULL )
+    {
+        printf( "There is no hierarchy information.\n" );
+        return;
+    }
+    vMods = &pNtk->pMan->vNtks;
+
+/*
+    vMods->nSize--;
+    vMods->pArray++;
+    // sort models by name
+    Vec_PtrSort( vMods, (int(*)())Au_NtkCompareNames );
+    // swap the first model
+    Num = Vec_PtrFind( vMods, pNtk );
+    assert( Num >= 0 && Num < Vec_PtrSize(vMods) );
+    pBoxModel = (Au_Ntk_t *)Vec_PtrEntry(vMods, 0);
+    Vec_PtrWriteEntry(vMods, 0, (Au_Ntk_t *)Vec_PtrEntry(vMods, Num) );
+    Vec_PtrWriteEntry(vMods, Num, pBoxModel );
+    vMods->pArray--;
+    vMods->nSize++;
+*/
+
+//    Vec_PtrForEachEntry( Au_Ntk_t *, vMods, pModel, i )
+//        printf( "%s\n", Au_NtkName(pModel) );
+
+    // print models
+    vCounts = Vec_IntStart( Vec_PtrSize(vMods) );
+    Vec_PtrForEachEntryStart( Au_Ntk_t *, vMods, pModel, i, 1 )
+    {
+        if ( Au_NtkBoxNum(pModel) == 0 )
+            continue;
+        Vec_IntFill( vCounts, Vec_IntSize(vCounts), 0 );
+        Au_NtkForEachBox( pModel, pObj, k )
+        {
+            pBoxModel = Au_ObjModel(pObj);
+            if ( pBoxModel == NULL || pBoxModel == pModel )
+                continue;
+            Num = Vec_PtrFind( vMods, pBoxModel );
+            assert( Num >= 0 && Num < Vec_PtrSize(vMods) );
+            Vec_IntAddToEntry( vCounts, Num, 1 );
+        }
+
+//        Au_NtkPrintStats( pModel, 0, 0, 0, 0, 0, 0, 0 );
+        printf( "MODULE  " );
+        printf( "%-30s : ", Au_NtkName(pModel) );
+        printf( "PI=%6d ", Au_NtkPiNum(pModel) );
+        printf( "PO=%6d ", Au_NtkPoNum(pModel) );
+        printf( "BB=%6d ", Au_NtkBoxNum(pModel) );
+        printf( "ND=%6d ", Au_NtkNodeNum(pModel) ); // sans constants
+//        printf( "Lev=%5d ", Au_NtkLevel(pModel) );
+        printf( "\n" );
+
+        Vec_IntForEachEntry( vCounts, Num, k )
+            if ( Num )
+                printf( "%15d : %s\n", Num, Au_NtkName((Au_Ntk_t *)Vec_PtrEntry(vMods, k)) );
+    }
+    Vec_IntFree( vCounts );
+    Vec_PtrForEachEntryStart( Au_Ntk_t *, vMods, pModel, i, 1 )
+    {
+        if ( Au_NtkBoxNum(pModel) != 0 )
+            continue;
+        printf( "MODULE  " );
+        printf( "%-30s : ", Au_NtkName(pModel) );
+        printf( "PI=%6d ", Au_NtkPiNum(pModel) );
+        printf( "PO=%6d ", Au_NtkPoNum(pModel) );
+        printf( "BB=%6d ", Au_NtkBoxNum(pModel) );
+        printf( "ND=%6d ", Au_NtkNodeNum(pModel) );
+//        printf( "Lev=%5d ", Au_NtkLevel(pModel) );
+        printf( "\n" );
+    }
+}
+int Au_NtkCompareSign( Au_Ntk_t ** p1, Au_Ntk_t ** p2 )
+{
+    if ( Au_NtkPiNum(*p1) - Au_NtkPiNum(*p2) != 0 )
+        return Au_NtkPiNum(*p1) - Au_NtkPiNum(*p2);
+    else
+        return Au_NtkPoNum(*p1) - Au_NtkPoNum(*p2);
+}
+void Au_ManPrintBoxInfoSorted( Au_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vMods, * vModsNew;
+    Au_Ntk_t * pModel;
+    int i;
+    if ( pNtk->pMan == NULL )
+    {
+        printf( "There is no hierarchy information.\n" );
+        return;
+    }
+    vMods = &pNtk->pMan->vNtks;
+
+    vMods->nSize--;
+    vMods->pArray++;
+    vModsNew = Vec_PtrDup( vMods );
+    vMods->pArray--;
+    vMods->nSize++;
+
+    Vec_PtrSort( vModsNew, (int(*)())Au_NtkCompareSign );
+    Vec_PtrForEachEntryStart( Au_Ntk_t *, vModsNew, pModel, i, 1 )
+    {
+        printf( "MODULE  " );
+        printf( "%-30s : ", Au_NtkName(pModel) );
+        printf( "PI=%6d ", Au_NtkPiNum(pModel) );
+        printf( "PO=%6d ", Au_NtkPoNum(pModel) );
+        printf( "BB=%6d ", Au_NtkBoxNum(pModel) );
+        printf( "ND=%6d ", Au_NtkNodeNum(pModel) );
+        printf( "\n" );
+    }
+    Vec_PtrFree( vModsNew );
+}
+
+int Au_NtkCheckRecursive( Au_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vMods;
+    Au_Ntk_t * pModel;
+    Au_Obj_t * pObj;
+    int i, k, RetValue = 0;
+
+    if ( pNtk->pMan == NULL )
+    {
+        printf( "There is no hierarchy information.\n" );
+        return RetValue;
+    }
+
+    vMods = &pNtk->pMan->vNtks;
+    Vec_PtrForEachEntryStart( Au_Ntk_t *, vMods, pModel, i, 1 )
+    {
+        Au_NtkForEachObj( pModel, pObj, k )
+            if ( Au_ObjIsBox(pObj) && Au_ObjModel(pObj) == pModel )
+            {
+                printf( "WARNING: Model \"%s\" contains a recursive defition.\n", Au_NtkName(pModel) );
+                RetValue = 1;
+                break;
+            }
+    }
+    return RetValue;
+}
+
+// count the number of support variables
+int Au_ObjSuppSize_rec( Au_Ntk_t * p, int Id )
+{
+    Au_Obj_t * pObj;
+    int i, iFanin, Counter = 0;
+    if ( Au_ObjIsTravIdCurrentId(p, Id) )
+        return 0;
+    Au_ObjSetTravIdCurrentId(p, Id);
+    pObj = Au_NtkObj( p, Id );
+    if ( Au_ObjIsPi(pObj) )
+        return 1;
+    assert( Au_ObjIsNode(pObj) || Au_ObjIsBox(pObj) || Au_ObjIsFan(pObj) );
+    Au_ObjForEachFaninId( pObj, iFanin, i )
+        Counter += Au_ObjSuppSize_rec( p, iFanin );
+    return Counter;
+}
+int Au_ObjSuppSize( Au_Obj_t * pObj )
+{
+    Au_Ntk_t * p = Au_ObjNtk(pObj);
+    Au_NtkIncrementTravId( p );
+    return Au_ObjSuppSize_rec( p, Au_ObjId(pObj) );
+}
+/*
+// this version is 50% slower than above
+int Au_ObjSuppSize_rec( Au_Obj_t * pObj )
+{
+    Au_Obj_t * pFanin;
+    int i, Counter = 0;
+    if ( Au_ObjIsTravIdCurrent(pObj) )
+        return 0;
+    Au_ObjSetTravIdCurrent(pObj);
+    if ( Au_ObjIsPi(pObj) )
+        return 1;
+    assert( Au_ObjIsNode(pObj) || Au_ObjIsBox(pObj) || Au_ObjIsFan(pObj) );
+    Au_ObjForEachFanin( pObj, pFanin, i )
+        Counter += Au_ObjSuppSize_rec( pFanin );
+    return Counter;
+}
+int Au_ObjSuppSize( Au_Obj_t * pObj )
+{
+    Au_NtkIncrementTravId( Au_ObjNtk(pObj) );
+    return Au_ObjSuppSize_rec( pObj );
+}
+*/
+int Au_NtkSuppSizeTest( Au_Ntk_t * p )
+{
+    Au_Obj_t * pObj;
+    int i, Counter = 0;
+    Au_NtkForEachObj( p, pObj, i )
+        if ( Au_ObjIsNode(pObj) )
+            Counter += (Au_ObjSuppSize(pObj) <= 16);
+    printf( "Nodes with small support %d (out of %d)\n", Counter, Au_NtkNodeNum(p) );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns memory for the next object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Au_NtkInsertHeader( Au_Ntk_t * p )
+{
+    Au_Obj_t * pMem = (Au_Obj_t *)Vec_PtrEntryLast( &p->vPages );
+    assert( (((ABC_PTRINT_T)(pMem + p->iHandle) & 0x3FF) >> 4) == 0 );
+    ((Au_Ntk_t **)(pMem + p->iHandle))[0] = p;
+    ((int *)(pMem + p->iHandle))[2] = ((Vec_PtrSize(&p->vPages) - 1) << 12) | (p->iHandle & 0xFC0);
+    p->iHandle++;
+}
+int Au_NtkAllocObj( Au_Ntk_t * p, int nFanins, int Type )
+{
+    Au_Obj_t * pMem, * pObj, * pTemp;
+    int nObjInt = ((2+nFanins) >> 2) + (((2+nFanins) & 3) > 0);
+    int Id, nObjIntReal = nObjInt;
+    if ( nObjInt > 63 )
+        nObjInt = 63 + 64 * (((nObjInt-63) >> 6) + (((nObjInt-63) & 63) > 0));
+    if ( Vec_PtrSize(&p->vPages) == 0 || p->iHandle + nObjInt > (1 << 12) )
+    {
+        if ( nObjInt + 64 > (1 << 12) )
+            pMem = ABC_CALLOC( Au_Obj_t, nObjInt + 64 ), p->nObjsAlloc += nObjInt + 64;
+        else
+            pMem = ABC_CALLOC( Au_Obj_t, (1 << 12) + 64 ), p->nObjsAlloc += (1 << 12) + 64;
+        Vec_PtrPush( p->vChunks, pMem );
+        if ( ((ABC_PTRINT_T)pMem & 0xF) )
+            pMem = (Au_Obj_t *)((char *)pMem + 16 - ((ABC_PTRINT_T)pMem & 0xF));
+        assert( ((ABC_PTRINT_T)pMem & 0xF) == 0 );
+        p->iHandle = (((ABC_PTRINT_T)pMem & 0x3FF) >> 4);
+        if ( p->iHandle )
+        {
+            pMem += 64 - (p->iHandle & 63);
+            p->iHandle = 0; 
+        }
+        Vec_PtrPush( &p->vPages, pMem );
+        Au_NtkInsertHeader( p );
+    }
+    else
+    {
+        pMem = (Au_Obj_t *)Vec_PtrEntryLast( &p->vPages );
+        if ( (p->iHandle & 63) == 0 || nObjInt > (64 - (p->iHandle & 63)) )
+        {
+            if ( p->iHandle & 63 )
+                p->iHandle += 64 - (p->iHandle & 63); 
+            Au_NtkInsertHeader( p );
+        }
+        if ( p->iHandle + nObjInt > (1 << 12) )
+            return Au_NtkAllocObj( p, nFanins, Type );
+    }
+    pObj = pMem + p->iHandle;
+    assert( *((int *)pObj) == 0 );
+    pObj->nFanins = nFanins;
+    p->nObjs[pObj->Type = Type]++;
+    if ( Type == AU_OBJ_PI )
+    {
+        Au_ObjSetFaninLit( pObj, 0, Vec_IntSize(&p->vPis) );
+        Vec_IntPush( &p->vPis, Au_ObjId(pObj) );
+    }
+    else if ( Type == AU_OBJ_PO )
+    {
+        Au_ObjSetFaninLit( pObj, 1, Vec_IntSize(&p->vPos) );
+        Vec_IntPush( &p->vPos, Au_ObjId(pObj) );
+    }
+    p->iHandle += nObjInt;
+    p->nObjsUsed += nObjIntReal;
+
+    Id = Au_ObjId(pObj);
+    Vec_IntPush( &p->vObjs, Id );
+    pTemp = Au_NtkObj( p, Id );
+    assert( pTemp == pObj );
+    return Id;
+}
+int Au_NtkCreateConst0( Au_Ntk_t * pNtk )
+{
+    return Au_NtkAllocObj( pNtk, 0, AU_OBJ_CONST0 );
+}
+int Au_NtkCreatePi( Au_Ntk_t * pNtk )
+{
+    return Au_NtkAllocObj( pNtk, 0, AU_OBJ_PI );
+}
+int Au_NtkCreatePo( Au_Ntk_t * pNtk, int iFanin )
+{
+    int Id = Au_NtkAllocObj( pNtk, 1, AU_OBJ_PO );
+    if ( iFanin )
+        Au_ObjSetFaninLit( Au_NtkObj(pNtk, Id), 0, iFanin );
+    return Id;
+}
+int Au_NtkCreateFan( Au_Ntk_t * pNtk, int iFanin, int iFanout, int iModel )
+{
+    int Id = Au_NtkAllocObj( pNtk, 1, AU_OBJ_FAN );
+    Au_Obj_t * p = Au_NtkObj( pNtk, Id );
+    if ( iFanin )
+        Au_ObjSetFaninLit( p, 0, iFanin );
+    Au_ObjSetFaninLit( p, 1, iFanout );
+    p->Func = iModel;
+    return Id;
+}
+int Au_NtkCreateNode( Au_Ntk_t * pNtk, Vec_Int_t * vFanins, int iFunc )
+{
+    int i, iFanin;
+    int Id = Au_NtkAllocObj( pNtk, Vec_IntSize(vFanins), AU_OBJ_NODE );
+    Au_Obj_t * p = Au_NtkObj( pNtk, Id );
+    Vec_IntForEachEntry( vFanins, iFanin, i )
+        Au_ObjSetFaninLit( p, i, iFanin );
+    p->Func = iFunc;
+    return Id;
+}
+int Au_NtkCreateBox( Au_Ntk_t * pNtk, Vec_Int_t * vFanins, int nFanouts, int iModel )
+{
+    int i, iFanin, nFanins = Vec_IntSize(vFanins);
+    int Id = Au_NtkAllocObj( pNtk, nFanins + 1 + nFanouts, AU_OBJ_BOX );
+    Au_Obj_t * p = Au_NtkObj( pNtk, Id );
+    Vec_IntForEachEntry( vFanins, iFanin, i )
+        Au_ObjSetFaninLit( p, i, iFanin );
+    Au_ObjSetFaninLit( p, nFanins, nFanouts );
+    for ( i = 0; i < nFanouts; i++ )
+        Au_ObjSetFaninLit( p, nFanins + 1 + i, Au_NtkCreateFan(pNtk, Au_Var2Lit(Id,0), i, iModel) );
+    p->nFanins = nFanins;
+    p->Func = iModel;
+    assert( iModel > 0 );
+    return Id;
+}
+
+/*
+ * 0/1 would denote false/true respectively.
+ * Signals would be even numbers, and negation would be handled by xor with 1.
+ * The output signal for each gate or subckt could be implicitly generated just use the next signal number.
+ * For ranges, we could use "start:cnt" to denote the sequence "start, start+2, ..., start + 2*(cnt- 1)".
+    - "cnt" seems more intuitive when signals are restricted to even numbers.
+ * We'd have subckts and specialized gates .and, .xor, and .mux.
+
+Here is a small example:
+
+.model test
+.inputs 3 # Inputs 2 4 6
+.subckt and3 3 1 2:3 # 8 is implicit output
+.outputs 1 8
+.end
+
+.model and3
+.inputs 3 # Inputs 2 4 6
+.and 2 4 # 8 output
+.and 6 8 # 10 output
+.outputs 1 10
+.end
+*/
+
+/**Function*************************************************************
+
+  Synopsis    [Reads one entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Au_NtkRemapNum( Vec_Int_t * vNum2Obj, int Num )
+{
+    return Au_Var2Lit(Vec_IntEntry(vNum2Obj, Au_Lit2Var(Num)), Au_LitIsCompl(Num));
+}
+/**Function*************************************************************
+
+  Synopsis    [Reads one entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Au_NtkParseCBlifNum( Vec_Int_t * vFanins, char * pToken, Vec_Int_t * vNum2Obj )
+{
+    char * pCur;
+    int Num1, Num2, i;
+    assert( pToken[0] >= '0' && pToken[0] <= '9' );
+    Num1 = atoi( pToken );
+    for ( pCur = pToken; *pCur; pCur++ )
+        if ( *pCur == ':' )
+        {
+            Num2 = atoi( pCur+1 );
+            for ( i = 0; i < Num2; i++ )
+                Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num1 + i + i) );
+            return;
+        }
+        else if ( *pCur == '*' )
+        {
+            Num2 = atoi( pCur+1 );
+            for ( i = 0; i < Num2; i++ )
+                Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num1) );
+            return;
+        }
+    assert( *pCur == 0 );
+    Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num1) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses CBLIF file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Au_Ntk_t * Au_NtkParseCBlif( char * pFileName )
+{
+    FILE * pFile;
+    Au_Man_t * pMan;
+    Au_Ntk_t * pRoot = NULL;
+    Au_Obj_t * pBox, * pFan;
+    char * pBuffer, * pCur;
+    Vec_Int_t * vLines, * vNum2Obj, * vFanins;
+    int i, k, j, Id, nInputs, nOutputs;
+    int Line, Num, Func;
+    // read the file
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\".\n", pFileName );
+        return NULL;
+    }
+    pBuffer = Extra_FileRead( pFile );
+    fclose( pFile );
+    // split into lines
+    vLines = Vec_IntAlloc( 1000 );
+    Vec_IntPush( vLines, 0 );
+    for ( pCur = pBuffer; *pCur; pCur++ )
+        if ( *pCur == '\n' )
+        {
+            *pCur = 0;
+            Vec_IntPush( vLines, pCur - pBuffer + 1 );
+        }
+    // start the manager
+    pMan = Au_ManAlloc( pFileName );
+    // parse the lines
+    vNum2Obj = Vec_IntAlloc( 1000 );
+    vFanins = Vec_IntAlloc( 1000 );
+    Vec_IntForEachEntry( vLines, Line, i )
+    {
+        pCur = strtok( pBuffer + Line, " \t\r" );
+        if ( pCur == NULL || *pCur == '#' )
+            continue;
+        if ( *pCur != '.' )
+        {
+            printf( "Cannot read directive in line %d: \"%s\".\n", i, pBuffer + Line );
+            continue;
+        }
+        Vec_IntClear( vFanins );
+        if ( !strcmp(pCur, ".and") )
+        {
+            for ( k = 0; k < 2; k++ )
+            {
+                pCur = strtok( NULL, " \t\r" );
+                Num  = atoi( pCur );
+                Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num) );
+            }
+            Id = Au_NtkCreateNode( pRoot, vFanins, 1 );
+            Vec_IntPush( vNum2Obj, Id );
+        }
+        else if ( !strcmp(pCur, ".xor") )
+        {
+            for ( k = 0; k < 2; k++ )
+            {
+                pCur = strtok( NULL, " \t\r" );
+                Num  = atoi( pCur );
+                Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num) );
+            }
+            Id = Au_NtkCreateNode( pRoot, vFanins, 2 );
+            Vec_IntPush( vNum2Obj, Id );
+        }
+        else if ( !strcmp(pCur, ".mux") )
+        {
+            for ( k = 0; k < 3; k++ )
+            {
+                pCur = strtok( NULL, " \t\r" );
+                Num  = atoi( pCur );
+                Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num) );
+            }
+            Id = Au_NtkCreateNode( pRoot, vFanins, 3 );
+            Vec_IntPush( vNum2Obj, Id );
+        }
+        else if ( !strcmp(pCur, ".subckt") )
+        {
+            pCur = strtok( NULL, " \t\r" );
+            Func = pCur - pBuffer;
+            pCur = strtok( NULL, " \t\r" );
+            nInputs = atoi( pCur );
+            pCur = strtok( NULL, " \t\r" );
+            nOutputs = atoi( pCur );
+            while ( 1 )
+            {
+                pCur = strtok( NULL, " \t\r" );
+                if ( pCur == NULL || *pCur == '#' )
+                    break;
+                Au_NtkParseCBlifNum( vFanins, pCur, vNum2Obj );
+            }
+            assert( Vec_IntSize(vFanins) == nInputs );
+            Id = Au_NtkCreateBox( pRoot, vFanins, nOutputs, Func );
+            pBox = Au_NtkObj( pRoot, Id );
+            Au_BoxForEachFanoutId( pBox, Num, k )
+                Vec_IntPush( vNum2Obj, Num );
+        }
+        else if ( !strcmp(pCur, ".model") )
+        {
+            pCur  = strtok( NULL, " \t\r" );
+            pRoot = Au_NtkAlloc( pMan, pCur );
+            Id    = Au_NtkCreateConst0( pRoot );
+            Vec_IntClear( vNum2Obj );
+            Vec_IntPush( vNum2Obj, Id );
+        }
+        else if ( !strcmp(pCur, ".inputs") )
+        {
+            pCur = strtok( NULL, " \t\r" );
+            Num  = atoi( pCur );
+            for ( k = 0; k < Num; k++ )
+                Vec_IntPush( vNum2Obj, Au_NtkCreatePi(pRoot) );
+        }
+        else if ( !strcmp(pCur, ".outputs") )
+        {
+            pCur = strtok( NULL, " \t\r" );
+            nOutputs = atoi( pCur );
+            while ( 1 )
+            {
+                pCur = strtok( NULL, " \t\r" );
+                if ( pCur == NULL || *pCur == '#' )
+                    break; 
+                Au_NtkParseCBlifNum( vFanins, pCur, vNum2Obj );
+            }
+            assert( Vec_IntSize(vFanins) == nOutputs );
+            Vec_IntForEachEntry( vFanins, Num, k )
+                Au_NtkCreatePo( pRoot, Num );
+        }
+        else if ( strcmp(pCur, ".end") )
+            printf( "Unknown directive in line %d: \"%s\".\n", i, pBuffer + Line );
+    }
+    Vec_IntFree( vFanins );
+    Vec_IntFree( vNum2Obj );
+    Vec_IntFree( vLines );
+    // set pointers to models
+    Au_ManForEachNtk( pMan, pRoot, i )
+        Au_NtkForEachBox( pRoot, pBox, k )
+        {
+            pBox->Func = Au_ManFindNtk( pMan, pBuffer + pBox->Func );
+            assert( pBox->Func > 0 );
+            Au_BoxForEachFanout( pBox, pFan, j )
+                pFan->Func = pBox->Func;
+        }
+    ABC_FREE( pBuffer );
+    // order models in topological order
+    pRoot = Au_ManNtkRoot( pMan );
+    Au_ManReorderModels( pMan, pRoot );
+    return pRoot;
+}
+
+ABC_NAMESPACE_IMPL_END
+
+#include "abc.h"
+#include "aig/gia/gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+extern Vec_Ptr_t * Abc_NtkDfsBoxes( Abc_Ntk_t * pNtk );
+extern int Abc_NtkDeriveFlatGiaSop( Gia_Man_t * pGia, int * gFanins, char * pSop );
+extern int Abc_NtkCheckRecursive( Abc_Ntk_t * pNtk );
+
+/**Function*************************************************************
+
+  Synopsis    [Flattens the logic hierarchy of the netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Au_NtkDeriveFlatGia_rec( Gia_Man_t * pGia, Au_Ntk_t * p )
+{ 
+    Au_Obj_t * pObj, * pTerm;
+    int i, k, Lit;
+    Au_NtkForEachPi( p, pTerm, i )
+        assert( Au_ObjCopy(pTerm) >= 0 );
+    if ( strcmp(Au_NtkName(p), "ref_egcd") == 0 )
+    {
+        printf( "Replacing one instance of recursive model \"%s\" by a black box.\n", "ref_egcd" );
+        Au_NtkForEachPo( p, pTerm, i )
+            Au_ObjSetCopy( pTerm, Gia_ManAppendCi(pGia) );
+        return;
+    }
+    Au_NtkForEachObj( p, pObj, i )
+    {
+        if ( Au_ObjIsNode(pObj) )
+        {
+            if ( p->pMan->pFuncs )
+            {
+                int gFanins[16];
+                char * pSop = Abc_NamStr( p->pMan->pFuncs, pObj->Func );
+                assert( Au_ObjFaninNum(pObj) <= 16 );
+                assert( Au_ObjFaninNum(pObj) == Abc_SopGetVarNum(pSop) );
+                Au_ObjForEachFanin( pObj, pTerm, k )
+                {
+                    gFanins[k] = Au_ObjCopy(pTerm);
+                    assert( gFanins[k] >= 0 );
+                }
+                Lit = Abc_NtkDeriveFlatGiaSop( pGia, gFanins, pSop );
+            }
+            else
+            {
+                int Lit0, Lit1, Lit2;
+                assert( pObj->Func >= 1 && pObj->Func <= 3 );
+                Lit0 = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin0(pObj)), Au_ObjFaninC0(pObj) );
+                Lit1 = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin1(pObj)), Au_ObjFaninC1(pObj) );
+                if ( pObj->Func == 1 )
+                    Lit = Gia_ManHashAnd( pGia, Lit0, Lit1 );
+                else if ( pObj->Func == 2 )
+                    Lit = Gia_ManHashXor( pGia, Lit0, Lit1 );
+                else if ( pObj->Func == 3 )
+                {
+                    Lit2 = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin2(pObj)), Au_ObjFaninC2(pObj) );
+                    Lit = Gia_ManHashMux( pGia, Lit0, Lit1, Lit2 );
+                }
+                else assert( 0 ); 
+            } 
+            assert( Lit >= 0 );
+            Au_ObjSetCopy( pObj, Lit );
+        }
+        else if ( Au_ObjIsBox(pObj) )
+        {
+            Au_Ntk_t * pModel = Au_ObjModel(pObj);
+            Au_NtkCleanCopy( pModel );
+            // check the match between the number of actual and formal parameters
+            assert( Au_ObjFaninNum(pObj) == Au_NtkPiNum(pModel) );
+            assert( Au_BoxFanoutNum(pObj) == Au_NtkPoNum(pModel) );
+            // assign PIs
+            Au_ObjForEachFanin( pObj, pTerm, k )
+                Au_ObjSetCopy( Au_NtkPi(pModel, k), Au_ObjCopy(pTerm) );
+            // call recursively
+            Au_NtkDeriveFlatGia_rec( pGia, pModel );
+            // assign POs
+            Au_BoxForEachFanout( pObj, pTerm, k )
+                Au_ObjSetCopy( pTerm, Au_ObjCopy(Au_NtkPo(pModel, k)) );
+        }
+        else if ( Au_ObjIsConst0(pObj) )
+            Au_ObjSetCopy( pObj, 0 );
+            
+    }
+    Au_NtkForEachPo( p, pTerm, i )
+    {
+        Lit = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin0(pTerm)), Au_ObjFaninC0(pTerm) );
+        Au_ObjSetCopy( pTerm, Lit );
+    }
+    Au_NtkForEachPo( p, pTerm, i )
+        assert( Au_ObjCopy(pTerm) >= 0 );
+//    p->pMan->nGiaObjMax = Abc_MaxInt( p->pMan->nGiaObjMax, Gia_ManObjNum(pGia) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Flattens the logic hierarchy of the netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Au_NtkDeriveFlatGia( Au_Ntk_t * p )
+{
+    Gia_Man_t * pTemp, * pGia = NULL;
+    Au_Obj_t * pTerm;
+    int i;
+    printf( "Collapsing model \"%s\"...\n", Au_NtkName(p) );
+    Au_NtkCleanCopy( p );
+    // start the network
+    pGia = Gia_ManStart( (1<<16) );
+    pGia->pName = Abc_UtilStrsav( Au_NtkName(p) );
+//    pGia->pSpec = Abc_UtilStrsav( Au_NtkSpec(p) );
+    Gia_ManHashAlloc( pGia );
+    Gia_ManFlipVerbose( pGia );
+    // create PIs
+    Au_NtkForEachPi( p, pTerm, i )
+        Au_ObjSetCopy( pTerm, Gia_ManAppendCi(pGia) );
+    // recursively flatten hierarchy
+    Au_NtkDeriveFlatGia_rec( pGia, p );
+    // create POs
+    Au_NtkForEachPo( p, pTerm, i )
+        Gia_ManAppendCo( pGia, Au_ObjCopy(pTerm) );
+    // prepare return value
+//    Gia_ManHashProfile( pGia );
+    Gia_ManHashStop( pGia );
+    Gia_ManSetRegNum( pGia, 0 );
+    pGia = Gia_ManCleanup( pTemp = pGia );
+    Gia_ManStop( pTemp );
+    return pGia;
+}
+
+
+// ternary simulation
+#define AU_VAL0   1
+#define AU_VAL1   2
+#define AU_VALX   3
+
+static inline void Au_ObjSetXsim( Au_Obj_t * pObj, int Value )  { pObj->Value = Value;  }
+static inline int  Au_ObjGetXsim( Au_Obj_t * pObj )             { return pObj->Value;   }
+static inline int  Au_XsimInv( int Value )   
+{ 
+    if ( Value == AU_VAL0 )
+        return AU_VAL1;
+    if ( Value == AU_VAL1 )
+        return AU_VAL0;
+    assert( Value == AU_VALX );       
+    return AU_VALX;
+}
+static inline int  Au_XsimAnd( int Value0, int Value1 )   
+{ 
+    if ( Value0 == AU_VAL0 || Value1 == AU_VAL0 )
+        return AU_VAL0;
+    if ( Value0 == AU_VALX || Value1 == AU_VALX )
+        return AU_VALX;
+    assert( Value0 == AU_VAL1 && Value1 == AU_VAL1 );
+    return AU_VAL1;
+}
+static inline int  Au_XsimXor( int Value0, int Value1 )   
+{ 
+    if ( Value0 == AU_VALX || Value1 == AU_VALX )
+        return AU_VALX;
+    if ( (Value0 == AU_VAL0) == (Value1 == AU_VAL0) )
+        return AU_VAL0;
+    return AU_VAL1;
+}
+static inline int  Au_XsimMux( int ValueC, int Value1, int Value0 )   
+{ 
+    if ( ValueC == AU_VAL0 )
+        return Value0;
+    if ( ValueC == AU_VAL1 )
+        return Value1;
+    if ( Value0 == AU_VAL0 && Value1 == AU_VAL0 )
+        return AU_VAL0;
+    if ( Value0 == AU_VAL1 && Value1 == AU_VAL1 )
+        return AU_VAL1;
+    return AU_VALX;
+}
+static inline int  Au_ObjGetXsimFan0( Au_Obj_t * pObj )       
+{ 
+    int Value = Au_ObjGetXsim( Au_ObjFanin0(pObj) );
+    return Au_ObjFaninC0(pObj) ? Au_XsimInv(Value) : Value;
+}
+static inline int  Au_ObjGetXsimFan1( Au_Obj_t * pObj )       
+{ 
+    int Value = Au_ObjGetXsim( Au_ObjFanin1(pObj) );
+    return Au_ObjFaninC1(pObj) ? Au_XsimInv(Value) : Value;
+}
+static inline int  Au_ObjGetXsimFan2( Au_Obj_t * pObj )       
+{ 
+    int Value = Au_ObjGetXsim( Au_ObjFanin2(pObj) );
+    return Au_ObjFaninC2(pObj) ? Au_XsimInv(Value) : Value;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Flattens the logic hierarchy of the netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Au_NtkTerSimulate_rec( Au_Ntk_t * p )
+{ 
+    Au_Obj_t * pObj = NULL, * pTerm;
+    int i, k;
+    Au_NtkForEachPi( p, pTerm, i )
+    {
+        assert( Au_ObjGetXsim(pTerm) > 0 );
+        if ( Au_ObjGetXsim(pTerm) == AU_VALX )
+            p->pMan->nPortsNC++;
+        else if ( Au_ObjGetXsim(pTerm) == AU_VAL0 )
+            p->pMan->nPortsC0++;
+        else
+            p->pMan->nPortsC1++;
+    }
+    if ( strcmp(Au_NtkName(p), "ref_egcd") == 0 )
+    {
+        printf( "Replacing one instance of recursive model \"%s\" by a black box.\n", "ref_egcd" );
+        Au_NtkForEachPo( p, pTerm, i )
+            Au_ObjSetXsim( pTerm, AU_VALX );
+        return;
+    }
+    Au_NtkForEachObj( p, pObj, i )
+    {
+        if ( Au_ObjIsNode(pObj) )
+        {
+            if ( pObj->Func == 1 )
+                Au_ObjSetXsim( pObj, Au_XsimAnd(Au_ObjGetXsimFan0(pObj), Au_ObjGetXsimFan1(pObj)) );
+            else if ( pObj->Func == 2 )
+                Au_ObjSetXsim( pObj, Au_XsimXor(Au_ObjGetXsimFan0(pObj), Au_ObjGetXsimFan1(pObj)) );
+            else if ( pObj->Func == 3 )
+                Au_ObjSetXsim( pObj, Au_XsimMux(Au_ObjGetXsimFan0(pObj), Au_ObjGetXsimFan1(pObj), Au_ObjGetXsimFan2(pObj)) );
+            else assert( 0 );
+        }
+        else if ( Au_ObjIsBox(pObj) )
+        {
+            Au_Ntk_t * pModel = Au_ObjModel(pObj);
+            // check the match between the number of actual and formal parameters
+            assert( Au_ObjFaninNum(pObj) == Au_NtkPiNum(pModel) );
+            assert( Au_BoxFanoutNum(pObj) == Au_NtkPoNum(pModel) );
+            // assign PIs
+            Au_ObjForEachFanin( pObj, pTerm, k )
+                Au_ObjSetXsim( Au_NtkPi(pModel, k), Au_ObjGetXsim(pTerm) );
+            // call recursively
+            Au_NtkTerSimulate_rec( pModel );
+            // assign POs
+            Au_BoxForEachFanout( pObj, pTerm, k )
+                Au_ObjSetXsim( pTerm, Au_ObjGetXsim(Au_NtkPo(pModel, k)) );
+        }
+        else if ( Au_ObjIsConst0(pObj) )
+            Au_ObjSetXsim( pObj, AU_VAL0 );
+            
+    }
+    Au_NtkForEachPo( p, pTerm, i )
+        Au_ObjSetXsim( pTerm, Au_ObjGetXsimFan0(pObj) );
+    Au_NtkForEachPo( p, pTerm, i )
+    {
+        assert( Au_ObjGetXsim(pTerm) > 0 );
+        if ( Au_ObjGetXsim(pTerm) == AU_VALX )
+            p->pMan->nPortsNC++;
+        else if ( Au_ObjGetXsim(pTerm) == AU_VAL0 )
+            p->pMan->nPortsC0++;
+        else
+            p->pMan->nPortsC1++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Flattens the logic hierarchy of the netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Au_NtkTerSimulate( Au_Ntk_t * p )
+{
+    Au_Obj_t * pTerm;
+    int i, Counter[2] = {0};
+    assert( p->pMan->pFuncs == NULL );
+    printf( "Collapsing model \"%s\"...\n", Au_NtkName(p) );
+    // create PIs
+    Au_NtkForEachPi( p, pTerm, i )
+        Au_ObjSetXsim( pTerm, AU_VALX );
+    // recursively flatten hierarchy
+    p->pMan->nPortsC0 = 0;
+    p->pMan->nPortsC1 = 0;
+    p->pMan->nPortsNC = 0;
+    Au_NtkTerSimulate_rec( p );
+    // analyze outputs
+    Au_NtkForEachPo( p, pTerm, i )
+        if ( Au_ObjGetXsim(pTerm) == AU_VAL0 )
+            Counter[0]++;
+        else if ( Au_ObjGetXsim(pTerm) == AU_VAL1 )
+            Counter[1]++;
+    // print results
+    printf( "Const0 outputs =%15d. Const1 outputs =%15d.  Total outputs =%15d.\n", 
+        Counter[0], Counter[1], Au_NtkPoNum(p) );
+    printf( "Const0 ports =  %.0f. Const1  ports =  %.0f. Non-const ports=  %.0f.  Total ports =  %.0f.\n", 
+        p->pMan->nPortsC0, p->pMan->nPortsC1, p->pMan->nPortsNC, p->pMan->nPortsC0 + p->pMan->nPortsC1 + p->pMan->nPortsNC );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates ABC network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Au_Ntk_t * Au_NtkDerive( Au_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vOrder )
+{
+    Au_Ntk_t * p;
+    Au_Obj_t * pAuObj;
+    Abc_Obj_t * pObj, * pTerm;
+//    Vec_Ptr_t * vOrder;
+    Vec_Int_t * vFanins;
+    int i, k, iFunc;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    Abc_NtkCleanCopy( pNtk );
+    p = Au_NtkAlloc( pMan, Abc_NtkName(pNtk) );
+    // copy PIs
+    Abc_NtkForEachPi( pNtk, pTerm, i )
+        Abc_ObjFanout0(pTerm)->iTemp = Au_NtkCreatePi(p);
+    // copy nodes and boxes
+    vFanins = Vec_IntAlloc( 100 );
+//    vOrder = Abc_NtkDfsBoxes( pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i )
+    {
+        Vec_IntClear( vFanins );
+        if ( Abc_ObjIsNode(pObj) )
+        {
+            Abc_ObjForEachFanin( pObj, pTerm, k )
+                Vec_IntPush( vFanins, Au_Var2Lit(pTerm->iTemp, 0) );
+            iFunc = Abc_NamStrFindOrAdd( pMan->pFuncs, (char *)pObj->pData, NULL );
+            Abc_ObjFanout0(pObj)->iTemp = Au_NtkCreateNode(p, vFanins, iFunc);
+            continue;
+        }
+        assert( Abc_ObjIsBox(pObj) );
+        Abc_ObjForEachFanin( pObj, pTerm, k )
+            Vec_IntPush( vFanins, Au_Var2Lit(Abc_ObjFanin0(pTerm)->iTemp, 0) );
+        pObj->iTemp = Au_NtkCreateBox(p, vFanins, Abc_ObjFanoutNum(pObj), ((Abc_Ntk_t *)pObj->pData)->iStep );
+        pAuObj = Au_NtkObj(p, pObj->iTemp);
+        Abc_ObjForEachFanout( pObj, pTerm, k )
+            Abc_ObjFanout0(pTerm)->iTemp = Au_ObjFanout(pAuObj, k);
+    }
+//    Vec_PtrFree( vOrder );
+    Vec_IntFree( vFanins );
+    // copy POs
+    Abc_NtkForEachPo( pNtk, pTerm, i )
+        Au_NtkCreatePo( p, Au_Var2Lit(Abc_ObjFanin0(pTerm)->iTemp, 0) );
+//    Au_NtkPrintStats( p );
+    return p;
+}
+
+Gia_Man_t * Au_ManDeriveTest( Abc_Ntk_t * pRoot )
+{
+    extern Vec_Ptr_t * Abc_NtkCollectHie( Abc_Ntk_t * pNtk );
+
+//    char * pModelName = NULL;
+    char * pModelName = "path_0_r_x_lhs";
+    Gia_Man_t * pGia = NULL;
+    Vec_Ptr_t * vOrder, * vModels;
+    Abc_Ntk_t * pMod;
+    Au_Man_t * pMan;
+    Au_Ntk_t * pNtk = NULL;
+    abctime clk1, clk2 = 0, clk3 = 0, clk = Abc_Clock();
+    int i;
+
+    clk1 = Abc_Clock();
+    pMan = Au_ManAlloc( pRoot->pDesign ? pRoot->pDesign->pName : pRoot->pName );
+    pMan->pFuncs = Abc_NamStart( 100, 16 );
+    clk2 += Abc_Clock() - clk1;
+
+    vModels = Abc_NtkCollectHie( pRoot );
+    Vec_PtrForEachEntry( Abc_Ntk_t *, vModels, pMod, i )
+    {
+        vOrder = Abc_NtkDfsBoxes( pMod );
+
+        clk1 = Abc_Clock();
+        pNtk = Au_NtkDerive( pMan, pMod, vOrder );
+        pMod->iStep = pNtk->Id;
+        pMod->pData = pNtk;
+        clk2 += Abc_Clock() - clk1;
+
+        Vec_PtrFree( vOrder );
+    }
+    Vec_PtrFree( vModels );
+    // order models in topological order
+    Au_ManReorderModels( pMan, pNtk );
+
+    // print statistics
+    Au_ManPrintStats( pMan );
+    Au_ManCountThings( pNtk->pMan );
+
+    // select network
+    if ( pModelName )
+    {
+        pNtk = Au_ManFindNtkP( pMan, pModelName );
+        if ( pNtk == NULL )
+            printf( "Could not find module \"%s\".\n", pModelName );
+    }
+    if ( pNtk == NULL )
+        pNtk = (Au_Ntk_t *)pRoot->pData;
+
+  
+//    if ( !Abc_NtkCheckRecursive(pRoot) )
+    {
+        clk1 = Abc_Clock();
+        pGia = Au_NtkDeriveFlatGia( pNtk );
+        clk3 = Abc_Clock() - clk1;
+//        printf( "GIA objects max = %d.\n", pMan->nGiaObjMax );
+    }
+
+//    clk1 = Abc_Clock();
+//    Au_NtkSuppSizeTest( (Au_Ntk_t *)pRoot->pData );
+//    clk4 = Abc_Clock() - clk1;
+
+    clk1 = Abc_Clock();
+    Au_ManDelete( pMan );
+    clk2 += Abc_Clock() - clk1;
+    
+    Abc_PrintTime( 1, "Time all ", Abc_Clock() - clk );
+    Abc_PrintTime( 1, "Time new ", clk2 );
+    Abc_PrintTime( 1, "Time GIA ", clk3 );
+//    Abc_PrintTime( 1, "Time supp", clk4 );
+    return pGia;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs hierarchical equivalence checking.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Abc_NtkHieCecTest2( char * pFileName, char * pModelName, int fVerbose )
+{
+    int fSimulation = 0;
+    Gia_Man_t * pGia = NULL;
+    Au_Ntk_t * pNtk, * pNtkClp = NULL;
+    abctime clk1 = 0, clk = Abc_Clock();
+
+    // read hierarchical netlist
+    pNtk = Au_NtkParseCBlif( pFileName );
+    if ( pNtk == NULL )
+    {
+        printf( "Reading CBLIF file has failed.\n" );
+        return NULL;
+    }
+    if ( pNtk->pMan == NULL || pNtk->pMan->vNtks.pArray == NULL )
+    {
+        printf( "There is no hierarchy information.\n" );
+        Au_NtkFree( pNtk );
+        return NULL;
+    }
+    Abc_PrintTime( 1, "Reading file", Abc_Clock() - clk );
+
+    if ( fVerbose )
+    {
+        Au_ManPrintBoxInfo( pNtk );
+//    Au_ManPrintBoxInfoSorted( pNtk );
+        Au_ManPrintStats( pNtk->pMan );
+    }
+    Au_ManCountThings( pNtk->pMan );
+
+    // select network
+    if ( pModelName )
+        pNtkClp = Au_ManFindNtkP( pNtk->pMan, pModelName );
+    if ( pNtkClp == NULL )
+        pNtkClp = pNtk;
+
+    // check if the model is recursive
+    Au_NtkCheckRecursive( pNtkClp );
+
+    // collapse
+    clk1 = Abc_Clock();
+    if ( fSimulation )
+    {
+        Au_NtkTerSimulate( pNtkClp );
+        Abc_PrintTime( 1, "Time sim ", Abc_Clock() - clk1 );
+    }
+    else
+    {
+        pGia = Au_NtkDeriveFlatGia( pNtkClp );
+        Abc_PrintTime( 1, "Time GIA ", Abc_Clock() - clk1 );
+    }
+
+    // delete
+    Au_ManDelete( pNtk->pMan );
+    Abc_PrintTime( 1, "Time all ", Abc_Clock() - clk );
+    return pGia;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcInt.h b/abc-build/src/base/abc/abcInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcInt.h
@@ -0,0 +1,60 @@
+/**CFile****************************************************************
+
+  FileName    [abcInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__base__abc__abcInt_h
+#define ABC__base__abc__abcInt_h
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+#define ABC_NUM_STEPS  10
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/abc-build/src/base/abc/abcLatch.c b/abc-build/src/base/abc/abcLatch.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcLatch.c
@@ -0,0 +1,772 @@
+/**CFile****************************************************************
+
+  FileName    [abcLatch.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Procedures working with latches.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcLatch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if latches form self-loop.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkLatchIsSelfFeed_rec( Abc_Obj_t * pLatch, Abc_Obj_t * pLatchRoot )
+{
+    Abc_Obj_t * pFanin;
+    assert( Abc_ObjIsLatch(pLatch) );
+    if ( pLatch == pLatchRoot )
+        return 1;
+    pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch));
+    if ( !Abc_ObjIsBo(pFanin) || !Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) )
+        return 0;
+    return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if latches form self-loop.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkLatchIsSelfFeed( Abc_Obj_t * pLatch )
+{
+    Abc_Obj_t * pFanin;
+    assert( Abc_ObjIsLatch(pLatch) );
+    pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch));
+    if ( !Abc_ObjIsBo(pFanin) || !Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) )
+        return 0;
+    return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if latches form self-loop.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCountSelfFeedLatches( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pLatch;
+    int i, Counter;
+    Counter = 0;
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+//        if ( Abc_NtkLatchIsSelfFeed(pLatch) && Abc_ObjFanoutNum(pLatch) > 1 )
+//            printf( "Fanouts = %d.\n", Abc_ObjFanoutNum(pLatch) );
+        Counter += Abc_NtkLatchIsSelfFeed( pLatch );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces self-feeding latches by latches with constant inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pLatch, * pConst1;
+    int i, Counter;
+    Counter = 0;
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+        if ( Abc_NtkLatchIsSelfFeed( pLatch ) )
+        {
+            if ( Abc_NtkIsStrash(pNtk) )
+                pConst1 = Abc_AigConst1(pNtk);
+            else
+                pConst1 = Abc_NtkCreateNodeConst1(pNtk);
+            Abc_ObjPatchFanin( Abc_ObjFanin0(pLatch), Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pConst1 );
+            Counter++;
+        }
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Pipelines the network with latches.]
+
+  Description []
+               
+  SideEffects [Does not check the names of the added latches!!!]
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj, * pLatch, * pFanin, * pFanout;
+    int i, k, nTotal, nDigits;
+    if ( nLatches < 1 )
+        return;
+    nTotal = nLatches * Abc_NtkPiNum(pNtk);
+    nDigits = Abc_Base10Log( nTotal );
+    vNodes = Vec_PtrAlloc( 100 );
+    Abc_NtkForEachPi( pNtk, pObj, i )
+    {
+        // remember current fanins of the PI
+        Abc_NodeCollectFanouts( pObj, vNodes );
+        // create the latches
+        for ( pFanin = pObj, k = 0; k < nLatches; k++, pFanin = pLatch )
+        {
+            pLatch = Abc_NtkCreateLatch( pNtk );
+            Abc_ObjAddFanin( pLatch, pFanin );
+            Abc_LatchSetInitDc( pLatch );
+            // create the name of the new latch
+            Abc_ObjAssignName( pLatch, Abc_ObjNameDummy("LL", i*nLatches + k, nDigits), NULL );
+        }
+        // patch the PI fanouts
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pFanout, k )
+            Abc_ObjPatchFanin( pFanout, pObj, pFanin );
+    }
+    Vec_PtrFree( vNodes );
+    Abc_NtkLogicMakeSimpleCos( pNtk, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes one logic node using its SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkCollectLatchValues( Abc_Ntk_t * pNtk )
+{
+    Vec_Int_t * vValues;
+    Abc_Obj_t * pLatch;
+    int i;
+    vValues = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) );
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+        Vec_IntPush( vValues, Abc_LatchIsInit1(pLatch) );
+    return vValues;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives latch init string.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_NtkCollectLatchValuesStr( Abc_Ntk_t * pNtk )
+{
+    char * pInits;
+    Abc_Obj_t * pLatch;
+    int i;
+    pInits = ABC_ALLOC( char, Abc_NtkLatchNum(pNtk) + 1 );
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+        if ( Abc_LatchIsInit0(pLatch) )
+            pInits[i] = '0';
+        else if ( Abc_LatchIsInit1(pLatch) )
+            pInits[i] = '1';
+        else if ( Abc_LatchIsInitDc(pLatch) )
+            pInits[i] = 'x';
+        else
+            assert( 0 );
+    }
+    pInits[i] = 0;
+    return pInits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes one logic node using its SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues )
+{
+    Abc_Obj_t * pLatch;
+    int i;
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+        pLatch->pData = (void *)(ABC_PTRINT_T)(vValues? (Vec_IntEntry(vValues,i)? ABC_INIT_ONE : ABC_INIT_ZERO) : ABC_INIT_DC);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates latch with the given initial value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkAddLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pDriver, Abc_InitType_t Init )
+{
+    Abc_Obj_t * pLatchOut, * pLatch, * pLatchIn;
+    pLatchOut = Abc_NtkCreateBo(pNtk);
+    pLatch    = Abc_NtkCreateLatch(pNtk);
+    pLatchIn  = Abc_NtkCreateBi(pNtk);
+    Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_lo" );
+    Abc_ObjAssignName( pLatchIn,  Abc_ObjName(pLatch), "_li" );
+    Abc_ObjAddFanin( pLatchOut, pLatch );
+    Abc_ObjAddFanin( pLatch, pLatchIn );
+    if ( pDriver )
+    Abc_ObjAddFanin( pLatchIn, pDriver );
+    pLatch->pData = (void *)Init;
+    return pLatchOut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates MUX.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkNodeConvertToMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0, Abc_Obj_t * pMux )
+{
+    assert( Abc_NtkIsLogic(pNtk) );
+    Abc_ObjAddFanin( pMux, pNodeC );
+    Abc_ObjAddFanin( pMux, pNode1 );
+    Abc_ObjAddFanin( pMux, pNode0 );
+    if ( Abc_NtkHasSop(pNtk) )
+        pMux->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, "11- 1\n0-1 1\n" );
+    else if ( Abc_NtkHasBdd(pNtk) )
+        pMux->pData = Cudd_bddIte((DdManager *)pNtk->pManFunc,Cudd_bddIthVar((DdManager *)pNtk->pManFunc,0),Cudd_bddIthVar((DdManager *)pNtk->pManFunc,1),Cudd_bddIthVar((DdManager *)pNtk->pManFunc,2)), Cudd_Ref( (DdNode *)pMux->pData );
+    else if ( Abc_NtkHasAig(pNtk) )
+        pMux->pData = Hop_Mux((Hop_Man_t *)pNtk->pManFunc,Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,0),Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,1),Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,2));
+    else
+        assert( 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts registers with DC values into additional PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkConvertDcLatches( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pCtrl, * pLatch, * pMux, * pPi;
+    Abc_InitType_t Init = ABC_INIT_ZERO;
+    int i, fFound = 0, Counter;
+    // check if there are latches with DC values
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+        if ( Abc_LatchIsInitDc(pLatch) )
+        {
+            fFound = 1;
+            break;
+        }
+    if ( !fFound )
+        return;
+    // add control latch
+    pCtrl = Abc_NtkAddLatch( pNtk, Abc_NtkCreateNodeConst1(pNtk), Init );
+    // add fanouts for each latch with DC values
+    Counter = 0;
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+        if ( !Abc_LatchIsInitDc(pLatch) )
+            continue;
+        // change latch value
+        pLatch->pData = (void *)Init;
+        // if the latch output has the same name as a PO, rename it
+        if ( Abc_NodeFindCoFanout( Abc_ObjFanout0(pLatch) ) )
+        {
+            Nm_ManDeleteIdName( pLatch->pNtk->pManName, Abc_ObjFanout0(pLatch)->Id );
+            Abc_ObjAssignName( Abc_ObjFanout0(pLatch), Abc_ObjName(pLatch), "_lo" );
+        }
+        // create new PIs
+        pPi = Abc_NtkCreatePi( pNtk );
+        Abc_ObjAssignName( pPi, Abc_ObjName(pLatch), "_pi" );
+        // create a new node and transfer fanout from latch output to the new node
+        pMux = Abc_NtkCreateNode( pNtk );
+        Abc_ObjTransferFanout( Abc_ObjFanout0(pLatch), pMux );
+        // convert the node into a mux
+        Abc_NtkNodeConvertToMux( pNtk, pCtrl, Abc_ObjFanout0(pLatch), pPi, pMux );
+        Counter++;
+    }
+    printf( "The number of converted latches with DC values = %d.\n", Counter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfors the array of latch names into that of latch numbers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkConverLatchNamesIntoNumbers( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vResult, * vNames;
+    Vec_Int_t * vNumbers;
+    Abc_Obj_t * pObj;
+    char * pName;
+    int i, k, Num;
+    if ( pNtk->vOnehots == NULL )
+        return NULL;
+    // set register numbers
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        pObj->pNext = (Abc_Obj_t *)(ABC_PTRINT_T)i;
+    // add the numbers
+    vResult = Vec_PtrAlloc( Vec_PtrSize(pNtk->vOnehots) );
+    Vec_PtrForEachEntry( Vec_Ptr_t *, pNtk->vOnehots, vNames, i )
+    {
+        vNumbers = Vec_IntAlloc( Vec_PtrSize(vNames) );
+        Vec_PtrForEachEntry( char *, vNames, pName, k )
+        {
+            Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BO );
+            if ( Num < 0 )
+                continue;
+            pObj = Abc_NtkObj( pNtk, Num );
+            if ( Abc_ObjFaninNum(pObj) != 1 || !Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) )
+                continue;
+            Vec_IntPush( vNumbers, (int)(ABC_PTRINT_T)pObj->pNext );
+        }
+        if ( Vec_IntSize( vNumbers ) > 1 )
+        {
+            Vec_PtrPush( vResult, vNumbers );
+printf( "Converted %d one-hot registers.\n", Vec_IntSize(vNumbers) );
+        }
+        else
+            Vec_IntFree( vNumbers );
+    }
+    // clean the numbers
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        pObj->pNext = NULL;
+    return vResult;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Converts registers with DC values into additional PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkConvertOnehot( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObj, * pFanin, * pObjNew, * pObjLiNew, * pObjLoNew;
+    int i, k, nFlops, nStates, iState, pfCompl[32];
+    assert( Abc_NtkIsLogic(pNtk) );
+    nFlops = Abc_NtkLatchNum(pNtk);
+    if ( nFlops == 0 )
+        return Abc_NtkDup( pNtk );
+    if ( nFlops > 16 )
+    {
+        printf( "Cannot reencode %d flops because it will lead to 2^%d states.\n", nFlops, nFlops );
+        return NULL;
+    }
+    // check if there are latches with DC values
+    iState = 0;
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+    {
+        if ( Abc_LatchIsInitDc(pObj) )
+        {
+            printf( "Cannot process logic network with don't-care init values. Run \"zero\".\n" );
+            return NULL;
+        }
+        if ( Abc_LatchIsInit1(pObj) )
+            iState |= (1 << i);
+    }
+    // transfer logic to SOPs
+    Abc_NtkToSop( pNtk, 0 );
+    // create new network
+    pNtkNew = Abc_NtkStartFromNoLatches( pNtk, pNtk->ntkType, pNtk->ntkFunc );
+    nStates = (1 << nFlops);
+    for ( i = 0; i < nStates; i++ )
+    {
+        pObjNew   = Abc_NtkCreateLatch( pNtkNew );
+        pObjLiNew = Abc_NtkCreateBi( pNtkNew );
+        pObjLoNew = Abc_NtkCreateBo( pNtkNew );
+        Abc_ObjAddFanin( pObjNew, pObjLiNew );
+        Abc_ObjAddFanin( pObjLoNew, pObjNew );
+        if ( i == iState )
+            Abc_LatchSetInit1( pObjNew );
+        else
+            Abc_LatchSetInit0( pObjNew );
+    }
+    Abc_NtkAddDummyBoxNames( pNtkNew );
+    assert( Abc_NtkLatchNum(pNtkNew) == nStates );
+    assert( Abc_NtkPiNum(pNtkNew) == Abc_NtkPiNum(pNtk) );
+    assert( Abc_NtkPoNum(pNtkNew) == Abc_NtkPoNum(pNtk) );
+    assert( Abc_NtkCiNum(pNtkNew) == Abc_NtkPiNum(pNtkNew) + nStates );
+    assert( Abc_NtkCoNum(pNtkNew) == Abc_NtkPoNum(pNtkNew) + nStates );
+    assert( Abc_NtkCiNum(pNtk) == Abc_NtkPiNum(pNtk) + nFlops );
+    assert( Abc_NtkCoNum(pNtk) == Abc_NtkPoNum(pNtk) + nFlops );
+    // create hot-to-log transformers
+    for ( i = 0; i < nFlops; i++ ) 
+    {
+        pObjNew = Abc_NtkCreateNode( pNtkNew );
+        for ( k = 0; k < nStates; k++ )
+            if ( (k >> i) & 1 )
+                Abc_ObjAddFanin( pObjNew, Abc_NtkCi(pNtkNew, Abc_NtkPiNum(pNtkNew)+k) );
+        assert( Abc_ObjFaninNum(pObjNew) == nStates/2 );
+        pObjNew->pData = Abc_SopCreateOr( (Mem_Flex_t *)pNtkNew->pManFunc, nStates/2, NULL );
+        // save the new flop
+        pObj = Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i );
+        pObj->pCopy = pObjNew;
+    }
+    // duplicate the nodes
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        pObj->pCopy = Abc_NtkDupObj( pNtkNew, pObj, 1 );
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+    }
+    Vec_PtrFree( vNodes );
+    // connect the POs
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        Abc_ObjAddFanin( pObj->pCopy, Abc_ObjNotCond(Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj)) );
+    // write entries into the nodes
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        pObj->pCopy = Abc_ObjNotCond(Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj));
+    // create log-to-hot transformers
+    for ( k = 0; k < nStates; k++ )
+    {
+        pObjNew = Abc_NtkCreateNode( pNtkNew );
+        for ( i = 0; i < nFlops; i++ )
+        {
+            pObj = Abc_NtkCo( pNtk, Abc_NtkPoNum(pNtk) + i );
+            Abc_ObjAddFanin( pObjNew, Abc_ObjRegular(pObj->pCopy) );
+            pfCompl[i] = Abc_ObjIsComplement(pObj->pCopy) ^ !((k >> i) & 1);
+        }
+        pObjNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, nFlops, pfCompl );
+        // connect it to the flop input
+        Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, Abc_NtkPoNum(pNtkNew)+k), pObjNew );
+    }
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkConvertOnehot(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+ABC_NAMESPACE_IMPL_END
+
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs retiming with classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Abc_NtkRetimeWithClassesAig( Aig_Man_t * pMan, Vec_Int_t * vClasses, Vec_Int_t ** pvClasses, int fVerbose )
+{
+    Aig_Man_t * pManNew;
+    Gia_Man_t * pGia, * pGiaNew;
+    pGia = Gia_ManFromAigSimple( pMan );
+    assert( Gia_ManRegNum(pGia) == Vec_IntSize(vClasses) );
+    pGia->vFlopClasses = vClasses;
+    pGiaNew = Gia_ManRetimeForward( pGia, 10, fVerbose );
+    *pvClasses = pGiaNew->vFlopClasses; 
+    pGiaNew->vFlopClasses = NULL;
+    pManNew = Gia_ManToAig( pGiaNew, 0 );
+    Gia_ManStop( pGiaNew );
+    Gia_ManStop( pGia );
+    return pManNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs retiming with classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRetimeWithClassesNtk( Abc_Ntk_t * pNtk, Vec_Int_t * vClasses, Vec_Int_t ** pvClasses, int fVerbose )
+{
+    extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+    extern Abc_Ntk_t * Abc_NtkFromDarSeqSweep( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan );
+    Abc_Ntk_t * pNtkAig, * pNtkAigRet, * pNtkRes;
+    Aig_Man_t * pMan, * pManNew;
+    pNtkAig    = Abc_NtkStrash( pNtk, 0, 1, 0 );
+    pMan       = Abc_NtkToDar( pNtkAig, 0, 1 );
+    pManNew    = Abc_NtkRetimeWithClassesAig( pMan, vClasses, pvClasses, fVerbose );
+    pNtkAigRet = Abc_NtkFromDarSeqSweep( pNtkAig, pManNew );
+    pNtkRes    = Abc_NtkToLogic( pNtkAigRet );
+    Abc_NtkDelete( pNtkAigRet );
+    Abc_NtkDelete( pNtkAig );
+    Aig_ManStop( pManNew );
+    Aig_ManStop( pMan );
+    return pNtkRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns self-loops back into the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTransformBack( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, Vec_Ptr_t * vControls, Vec_Int_t * vClasses )
+{
+    Abc_Obj_t * pObj, * pNodeNew, * pCtrl, * pDriver;
+    int i, Class;
+    assert( Abc_NtkPoNum(pNtkOld) == Abc_NtkPoNum(pNtkNew) );
+    // match the POs of the old into new
+    Abc_NtkForEachPo( pNtkOld, pObj, i )
+        pObj->pCopy = Abc_NtkPo( pNtkNew, i );
+    // remap the flops
+    Vec_PtrForEachEntry( Abc_Obj_t *, vControls, pObj, i )
+    {
+        assert( Abc_ObjIsPo(pObj) && pObj->pNtk == pNtkOld );
+        Vec_PtrWriteEntry( vControls, i, pObj->pCopy );
+    }
+    // create self-loops
+    assert( Abc_NtkLatchNum(pNtkNew) == Vec_IntSize(vClasses) );
+    Abc_NtkForEachLatch( pNtkNew, pObj, i )
+    {
+        Class = Vec_IntEntry( vClasses, i );
+        if ( Class == -1 )
+            continue;
+        pDriver = Abc_ObjFanin0(Abc_ObjFanin0(pObj));
+        pCtrl = (Abc_Obj_t *)Vec_PtrEntry( vControls, Class );
+        pCtrl = Abc_ObjFanin0( pCtrl );
+        pNodeNew = Abc_NtkCreateNode( pNtkNew );
+        Abc_ObjAddFanin( pNodeNew, pCtrl );
+        Abc_ObjAddFanin( pNodeNew, pDriver );
+        Abc_ObjAddFanin( pNodeNew, Abc_ObjFanout0(pObj) );
+        Abc_ObjSetData( pNodeNew, Abc_SopRegister((Mem_Flex_t *)pNtkNew->pManFunc, "0-1 1\n11- 1\n") );
+        Abc_ObjPatchFanin( Abc_ObjFanin0(pObj), pDriver, pNodeNew );
+    }
+    // remove the useless POs
+    Vec_PtrForEachEntry( Abc_Obj_t *, vControls, pObj, i )
+        Abc_NtkDeleteObj( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Classify flops.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCRetime( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    Abc_Ntk_t * pNtkNew;
+    Vec_Ptr_t * vControls;
+    Vec_Int_t * vFlopClasses, * vFlopClassesNew;
+    Abc_Obj_t * pObj, * pDriver, * pFlopOut, * pObjPo;
+    int i, iFlop, CountN = 0, Count2 = 0, Count1 = 0, Count0 = 0;
+
+    // duplicate the AIG
+    pNtk = Abc_NtkDup( pNtk );
+
+    // update registers
+    vControls    = Vec_PtrAlloc( 100 );
+    vFlopClasses = Vec_IntAlloc( 100 );
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+    {
+        pFlopOut = Abc_ObjFanout0(pObj);
+        pDriver = Abc_ObjFanin0( Abc_ObjFanin0(pObj) );
+        if ( Abc_ObjFaninNum(pDriver) != 3 )
+        {
+            Vec_IntPush( vFlopClasses, -1 );
+            CountN++;
+            continue;
+        }
+        if ( Abc_ObjFanin(pDriver, 1) != pFlopOut && Abc_ObjFanin(pDriver, 2) != pFlopOut )
+        {
+            Vec_IntPush( vFlopClasses, -1 );
+            Count2++;
+            continue;
+        }
+        if ( Abc_ObjFanin(pDriver, 1) == pFlopOut )
+        {
+            Vec_IntPush( vFlopClasses, -1 );
+            Count1++;
+            continue;
+        }
+        assert( Abc_ObjFanin(pDriver, 2) == pFlopOut );
+        Count0++;
+        Vec_PtrPushUnique( vControls, Abc_ObjFanin0(pDriver) );
+        // set the flop class
+        iFlop = Vec_PtrFind( vControls, Abc_ObjFanin0(pDriver) );
+        Vec_IntPush( vFlopClasses, iFlop );
+        // update
+        Abc_ObjPatchFanin( Abc_ObjFanin0(pObj), pDriver, Abc_ObjFanin(pDriver, 1) );
+    }
+    if ( Count1 )
+        printf( "Opposite phase enable is present in %d flops (out of %d).\n", Count1, Abc_NtkLatchNum(pNtk) );
+    if ( fVerbose )
+    printf( "CountN = %4d. Count2 = %4d. Count1 = %4d. Count0 = %4d. Ctrls = %d.\n", 
+        CountN, Count2, Count1, Count0, Vec_PtrSize(vControls) );
+
+    // add the controls to the list of POs
+    Vec_PtrForEachEntry( Abc_Obj_t *, vControls, pObj, i )
+    {
+        pObjPo = Abc_NtkCreatePo( pNtk );
+        Abc_ObjAddFanin( pObjPo, pObj );
+        Abc_ObjAssignName( pObjPo, Abc_ObjName(pObjPo), NULL );
+        Vec_PtrWriteEntry( vControls, i, pObjPo );
+    }
+    Abc_NtkOrderCisCos( pNtk );
+    Abc_NtkCleanup( pNtk, fVerbose );
+
+    // performs retiming with classes
+    pNtkNew = Abc_NtkRetimeWithClassesNtk( pNtk, vFlopClasses, &vFlopClassesNew, fVerbose );
+    Abc_NtkTransformBack( pNtk, pNtkNew, vControls, vFlopClassesNew );
+//    assert( Abc_NtkPoNum(pNtkNew) == Abc_NtkPoNum(pNtk) );
+    Abc_NtkDelete( pNtk );
+
+    Vec_PtrFree( vControls );
+//    Vec_IntFree( vFlopClasses );
+    Vec_IntFree( vFlopClassesNew );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulates CEX and return the ID of the PO that failed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkVerifyCex( Abc_Ntk_t * pNtk, Abc_Cex_t * p )
+{
+    Abc_Obj_t * pObj;
+    int RetValue, i, k, iBit = 0;
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( p->nPis  == Abc_NtkPiNum(pNtk) );
+    assert( p->nRegs == Abc_NtkLatchNum(pNtk) );
+    Abc_NtkCleanMarkC( pNtk );
+    Abc_AigConst1(pNtk)->fMarkC = 1;
+    // initialize flops
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        Abc_ObjFanout0(pObj)->fMarkC = Abc_InfoHasBit(p->pData, iBit++);
+    // simulate timeframes
+    for ( i = 0; i <= p->iFrame; i++ )
+    {
+        Abc_NtkForEachPi( pNtk, pObj, k )
+            pObj->fMarkC = Abc_InfoHasBit(p->pData, iBit++);
+        Abc_NtkForEachNode( pNtk, pObj, k )
+            pObj->fMarkC = (Abc_ObjFanin0(pObj)->fMarkC ^ Abc_ObjFaninC0(pObj)) & 
+                           (Abc_ObjFanin1(pObj)->fMarkC ^ Abc_ObjFaninC1(pObj));
+        Abc_NtkForEachCo( pNtk, pObj, k )
+            pObj->fMarkC = Abc_ObjFanin0(pObj)->fMarkC ^ Abc_ObjFaninC0(pObj);
+        Abc_NtkForEachLatch( pNtk, pObj, k )
+            Abc_ObjFanout0(pObj)->fMarkC = Abc_ObjFanin0(pObj)->fMarkC;
+    }
+    assert( iBit == p->nBits );
+    // figure out the number of failed output
+    RetValue = -1;
+    Abc_NtkForEachPo( pNtk, pObj, i )
+	{
+        if ( pObj->fMarkC )
+        {
+            RetValue = i;
+            break;
+        }
+	}
+    Abc_NtkCleanMarkC( pNtk );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcLib.c b/abc-build/src/base/abc/abcLib.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcLib.c
@@ -0,0 +1,400 @@
+/**CFile****************************************************************
+
+  FileName    [abcLib.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Functions to manipulate verilog libraries.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Create the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Des_t * Abc_DesCreate( char * pName )
+{
+    Abc_Des_t * p;
+    p = ABC_ALLOC( Abc_Des_t, 1 );
+    memset( p, 0, sizeof(Abc_Des_t) );
+    p->pName    = Abc_UtilStrsav( pName );
+    p->tModules = st__init_table( strcmp, st__strhash );
+    p->vTops    = Vec_PtrAlloc( 100 );
+    p->vModules = Vec_PtrAlloc( 100 );
+    p->pManFunc = Hop_ManStart();
+    p->pLibrary = NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes all pointers to the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_DesCleanManPointer( Abc_Des_t * p, void * pMan )
+{
+    Abc_Ntk_t * pTemp;
+    int i;
+    if ( p == NULL )
+        return;
+    if ( p->pManFunc == pMan )
+        p->pManFunc = NULL;
+    Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pTemp, i )
+        if ( pTemp->pManFunc == pMan )
+            pTemp->pManFunc = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_DesFree( Abc_Des_t * p, Abc_Ntk_t * pNtkSave )
+{
+    Abc_Ntk_t * pNtk;
+    int i;
+    if ( p->pName )
+        ABC_FREE( p->pName );
+    if ( p->pManFunc )
+        Hop_ManStop( (Hop_Man_t *)p->pManFunc );
+    if ( p->tModules )
+        st__free_table( p->tModules );
+    if ( p->vModules )
+    {
+        Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtk, i )
+        {
+            if ( pNtk == pNtkSave )
+                continue;
+            pNtk->pDesign = NULL;
+            if ( (pNtkSave && pNtk->pManFunc == pNtkSave->pManFunc) || (pNtk->pManFunc == p->pManFunc) )
+                pNtk->pManFunc = NULL;
+            Abc_NtkDelete( pNtk );
+        }
+        Vec_PtrFree( p->vModules );
+    }
+    if ( p->vTops )
+        Vec_PtrFree( p->vTops );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicated the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Des_t * Abc_DesDup( Abc_Des_t * p )
+{
+    Abc_Des_t * pNew;
+    Abc_Ntk_t * pTemp;
+    Abc_Obj_t * pObj;
+    int i, k;
+    pNew = Abc_DesCreate( p->pName );
+    Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pTemp, i )
+        Abc_DesAddModel( pNew, Abc_NtkDup(pTemp) );
+    Vec_PtrForEachEntry( Abc_Ntk_t *, p->vTops, pTemp, i )
+        Vec_PtrPush( pNew->vTops, pTemp->pCopy );
+    Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pTemp, i )
+        pTemp->pCopy->pAltView = pTemp->pAltView ? pTemp->pAltView->pCopy : NULL;
+    // update box models
+    Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pTemp, i )
+        Abc_NtkForEachBox( pTemp, pObj, k )
+            if ( Abc_ObjIsWhitebox(pObj) || Abc_ObjIsBlackbox(pObj) )
+                pObj->pCopy->pData = Abc_ObjModel(pObj)->pCopy;
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Des_t * Abc_DesDupBlackboxes( Abc_Des_t * p, Abc_Ntk_t * pNtkSave )
+{
+    Abc_Des_t * pNew;
+    Abc_Ntk_t * pNtkTemp;
+    int i;
+    assert( Vec_PtrSize(p->vTops) > 0 );
+    assert( Vec_PtrSize(p->vModules) > 1 );
+    pNew = Abc_DesCreate( p->pName );
+//    pNew->pManFunc = pNtkSave->pManFunc;
+    Vec_PtrPush( pNew->vTops, pNtkSave );
+    Vec_PtrPush( pNew->vModules, pNtkSave );
+    Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtkTemp, i )
+        if ( Abc_NtkHasBlackbox( pNtkTemp ) )
+            Vec_PtrPush( pNew->vModules, Abc_NtkDup(pNtkTemp) );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_DesPrint( Abc_Des_t * p )
+{
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pObj;
+    int i, k;
+    printf( "Models of design %s:\n", p->pName );
+    Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtk, i )
+    {
+        printf( "%2d : %20s   ", i+1, pNtk->pName );
+        printf( "nd = %6d   lat = %6d   whitebox = %3d   blackbox = %3d\n", 
+            Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk), 
+            Abc_NtkWhiteboxNum(pNtk), Abc_NtkBlackboxNum(pNtk) );
+        if ( Abc_NtkBlackboxNum(pNtk) == 0 )
+            continue;
+        Abc_NtkForEachWhitebox( pNtk, pObj, k )
+            printf( "     %20s (whitebox)\n", Abc_NtkName((Abc_Ntk_t *)pObj->pData) );
+        Abc_NtkForEachBlackbox( pNtk, pObj, k )
+            printf( "     %20s (blackbox)\n", Abc_NtkName((Abc_Ntk_t *)pObj->pData) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_DesAddModel( Abc_Des_t * p, Abc_Ntk_t * pNtk )
+{
+    if ( st__is_member( p->tModules, (char *)pNtk->pName ) )
+        return 0;
+    st__insert( p->tModules, (char *)pNtk->pName, (char *)pNtk );
+    assert( pNtk->Id == 0 );
+    pNtk->Id = Vec_PtrSize(p->vModules);
+    Vec_PtrPush( p->vModules, pNtk );
+    pNtk->pDesign = p;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_DesFindModelByName( Abc_Des_t * p, char * pName )
+{
+    Abc_Ntk_t * pNtk;
+    if ( ! st__is_member( p->tModules, (char *)pName ) )
+        return NULL;
+    st__lookup( p->tModules, (char *)pName, (char **)&pNtk );
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_DesDeriveRoot( Abc_Des_t * p )
+{
+    Abc_Ntk_t * pNtk;
+    if ( Vec_PtrSize(p->vModules) > 1 )
+    {
+        printf( "The design includes more than one module and is currently not used.\n" );
+        return NULL;
+    }
+    pNtk = (Abc_Ntk_t *)Vec_PtrEntry( p->vModules, 0 );  Vec_PtrClear( p->vModules );
+    pNtk->pManFunc = p->pManFunc;           p->pManFunc = NULL;
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detects the top-level models.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_DesFindTopLevelModels( Abc_Des_t * p )
+{
+    Abc_Ntk_t * pNtk, * pNtkBox;
+    Abc_Obj_t * pObj;
+    int i, k;
+    assert( Vec_PtrSize( p->vModules ) > 0 );
+    // clear the models
+    Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtk, i )
+        pNtk->fHieVisited = 0;
+    // mark all the models reachable from other models
+    Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtk, i )
+    {
+        Abc_NtkForEachBox( pNtk, pObj, k )
+        {
+            if ( Abc_ObjIsLatch(pObj) )
+                continue;
+            if ( pObj->pData == NULL )
+                continue;
+            pNtkBox = (Abc_Ntk_t *)pObj->pData;
+            pNtkBox->fHieVisited = 1;
+        }
+    }
+    // collect the models that are not marked
+    Vec_PtrClear( p->vTops );
+    Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtk, i )
+    {
+        if ( pNtk->fHieVisited == 0 )
+            Vec_PtrPush( p->vTops, pNtk );
+        else
+            pNtk->fHieVisited = 0;
+    }
+    return Vec_PtrSize( p->vTops );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derive the AIG of the logic in the netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeStrashUsingNetwork_rec( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    assert( !Abc_ObjIsNet(pObj) );
+    if ( pObj->pCopy )
+        return;
+    // call for the fanins
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        Abc_NodeStrashUsingNetwork_rec( pNtkAig, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)) );
+    // compute for the node
+    pObj->pCopy = Abc_NodeStrash( pNtkAig, pObj, 0 );
+    // set for the fanout net
+    Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive the AIG of the logic in the netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeStrashUsingNetwork( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pBox )
+{ 
+    Abc_Ntk_t * pNtkGate;
+    Abc_Obj_t * pObj;
+    unsigned * pPolarity;
+    int i, fCompl;
+    assert( Abc_ObjIsBox(pBox) );
+    pNtkGate = (Abc_Ntk_t *)pBox->pData;
+    pPolarity = (unsigned *)pBox->pNext;
+    assert( Abc_NtkIsNetlist(pNtkGate) );
+    assert( Abc_NtkLatchNum(pNtkGate) == 0 );
+    Abc_NtkCleanCopy( pNtkGate );
+    // set the PI values
+    Abc_NtkForEachPi( pNtkGate, pObj, i )
+    {
+        fCompl = (pPolarity && Abc_InfoHasBit(pPolarity, i));
+        pObj->pCopy = Abc_ObjNotCond( Abc_ObjFanin(pBox,i)->pCopy, fCompl );
+        Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy;
+    }
+    // build recursively and set the PO values
+    Abc_NtkForEachPo( pNtkGate, pObj, i )
+    {
+        Abc_NodeStrashUsingNetwork_rec( pNtkAig, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)) );
+        Abc_ObjFanout(pBox,i)->pCopy = Abc_ObjFanin0(pObj)->pCopy;
+    }
+//printf( "processing %d\n", pBox->Id );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcMinBase.c b/abc-build/src/base/abc/abcMinBase.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcMinBase.c
@@ -0,0 +1,684 @@
+/**CFile****************************************************************
+
+  FileName    [abcMinBase.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Makes nodes of the network minimum base.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcMinBase.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+static int Abc_NodeSupport( DdNode * bFunc, Vec_Str_t * vSupport, int nVars );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Makes nodes minimum base.]
+
+  Description [Returns the number of changed nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, Counter;
+    assert( Abc_NtkIsBddLogic(pNtk) );
+    Counter = 0;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        Counter += Abc_NodeMinimumBase( pNode );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Makes one node minimum base.]
+
+  Description [Returns 1 if the node is changed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeMinimumBase( Abc_Obj_t * pNode )
+{
+    Vec_Str_t * vSupport;
+    Vec_Ptr_t * vFanins;
+    DdNode * bTemp;
+    int i, nVars;
+
+    assert( Abc_NtkIsBddLogic(pNode->pNtk) );
+    assert( Abc_ObjIsNode(pNode) );
+
+    // compute support
+    vSupport = Vec_StrAlloc( 10 );
+    nVars = Abc_NodeSupport( Cudd_Regular(pNode->pData), vSupport, Abc_ObjFaninNum(pNode) );
+    if ( nVars == Abc_ObjFaninNum(pNode) )
+    {
+        Vec_StrFree( vSupport );
+        return 0;
+    }
+
+    // remove unused fanins
+    vFanins = Vec_PtrAlloc( Abc_ObjFaninNum(pNode) );
+    Abc_NodeCollectFanins( pNode, vFanins );
+    for ( i = 0; i < vFanins->nSize; i++ )
+        if ( vSupport->pArray[i] == 0 )
+            Abc_ObjDeleteFanin( pNode, (Abc_Obj_t *)vFanins->pArray[i] );
+    assert( nVars == Abc_ObjFaninNum(pNode) );
+
+    // update the function of the node
+    pNode->pData = Extra_bddRemapUp( (DdManager *)pNode->pNtk->pManFunc, bTemp = (DdNode *)pNode->pData );   Cudd_Ref( (DdNode *)pNode->pData );
+    Cudd_RecursiveDeref( (DdManager *)pNode->pNtk->pManFunc, bTemp );
+    Vec_PtrFree( vFanins );
+    Vec_StrFree( vSupport );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Makes nodes of the network fanin-dup-free.]
+
+  Description [Returns the number of pairs of duplicated fanins.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, Counter;
+    assert( Abc_NtkIsBddLogic(pNtk) );
+    Counter = 0;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        Counter += Abc_NodeRemoveDupFanins( pNode );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes one pair of duplicated fanins if present.]
+
+  Description [Returns 1 if the node is changed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeRemoveDupFanins_int( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin1, * pFanin2;
+    int i, k;
+    assert( Abc_NtkIsBddLogic(pNode->pNtk) );
+    assert( Abc_ObjIsNode(pNode) );
+    // make sure fanins are not duplicated
+    Abc_ObjForEachFanin( pNode, pFanin2, i )
+    {
+        Abc_ObjForEachFanin( pNode, pFanin1, k )
+        {
+            if ( k >= i )
+                break;
+            if ( pFanin1 == pFanin2 )
+            {
+                DdManager * dd = (DdManager *)pNode->pNtk->pManFunc;
+                DdNode * bVar1 = Cudd_bddIthVar( dd, i );
+                DdNode * bVar2 = Cudd_bddIthVar( dd, k );
+                DdNode * bTrans, * bTemp;
+                bTrans = Cudd_bddXnor( dd, bVar1, bVar2 ); Cudd_Ref( bTrans );
+                pNode->pData = Cudd_bddAndAbstract( dd, bTemp = (DdNode *)pNode->pData, bTrans, bVar2 ); Cudd_Ref( (DdNode *)pNode->pData );
+                Cudd_RecursiveDeref( dd, bTemp );
+                Cudd_RecursiveDeref( dd, bTrans );
+                Abc_NodeMinimumBase( pNode );
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes duplicated fanins if present.]
+
+  Description [Returns the number of fanins removed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode )
+{
+    int Counter = 0;
+    while ( Abc_NodeRemoveDupFanins_int(pNode) )
+        Counter++;
+    return Counter;
+}
+/**Function*************************************************************
+
+  Synopsis    [Computes support of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeSupport_rec( DdNode * bFunc, Vec_Str_t * vSupport )
+{
+    if ( cuddIsConstant(bFunc) || Cudd_IsComplement(bFunc->next) )
+        return;
+    vSupport->pArray[ bFunc->index ] = 1;
+    Abc_NodeSupport_rec( cuddT(bFunc), vSupport );
+    Abc_NodeSupport_rec( Cudd_Regular(cuddE(bFunc)), vSupport );
+    bFunc->next = Cudd_Not(bFunc->next);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes support of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeSupportClear_rec( DdNode * bFunc )
+{
+    if ( !Cudd_IsComplement(bFunc->next) )
+        return;
+    bFunc->next = Cudd_Regular(bFunc->next);
+    if ( cuddIsConstant(bFunc) )
+        return;
+    Abc_NodeSupportClear_rec( cuddT(bFunc) );
+    Abc_NodeSupportClear_rec( Cudd_Regular(cuddE(bFunc)) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes support of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeSupport( DdNode * bFunc, Vec_Str_t * vSupport, int nVars )
+{
+    int Counter, i;
+    // compute the support by marking the BDD
+    Vec_StrFill( vSupport, nVars, 0 );
+    Abc_NodeSupport_rec( bFunc, vSupport );
+    // clear the marak
+    Abc_NodeSupportClear_rec( bFunc );
+    // get the number of support variables
+    Counter = 0;
+    for ( i = 0; i < nVars; i++ )
+        Counter += vSupport->pArray[i];
+    return Counter;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Find the number of unique variables after collapsing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCheckDupFanin( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, int * piFanin )
+{
+    Abc_Obj_t * pObj;
+    int i, Counter = 0;
+    Abc_ObjForEachFanin( pFanout, pObj, i )
+        if ( pObj == pFanin )
+        {
+            if ( piFanin )
+                *piFanin = i;
+            Counter++;
+        }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the number of unique variables after collapsing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCollapseSuppSize( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Vec_PtrClear( vFanins );
+    Abc_ObjForEachFanin( pFanout, pObj, i )
+        if ( pObj != pFanin )
+            Vec_PtrPushUnique( vFanins, pObj );
+    Abc_ObjForEachFanin( pFanin, pObj, i )
+        Vec_PtrPushUnique( vFanins, pObj );
+    return Vec_PtrSize( vFanins );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the index of the new fanin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ObjFaninNumberNew( Vec_Ptr_t * vFanins, Abc_Obj_t * pFanin )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i )
+        if ( pObj == pFanin )
+            return i;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the permutation map for the given node into the new order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCollapsePermMap( Abc_Obj_t * pNode, Abc_Obj_t * pSkip, Vec_Ptr_t * vFanins, int * pPerm )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    for ( i = 0; i < Vec_PtrSize(vFanins); i++ )
+        pPerm[i] = i;
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        if ( pFanin == pSkip )
+            continue;
+        pPerm[i] = Abc_ObjFaninNumberNew( vFanins, pFanin );
+        if ( pPerm[i] == -1 )
+            return 0;
+    }
+    return 1;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Eliminates the nodes into their fanouts if the node size does not exceed this number.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NodeCollapseFunc( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins, int * pPermFanin, int * pPermFanout )
+{
+    DdManager * dd = (DdManager *)pFanin->pNtk->pManFunc;
+    DdNode * bVar, * bFunc0, * bFunc1, * bTemp, * bFanin, * bFanout;
+    int RetValue, nSize, iFanin;
+    // can only eliminate if fanin occurs in the fanin list of the fanout exactly once
+    if ( Abc_NodeCheckDupFanin( pFanin, pFanout, &iFanin ) != 1 )
+        return NULL;
+    // find the new number of fanins after collapsing
+    nSize = Abc_NodeCollapseSuppSize( pFanin, pFanout, vFanins );
+    bVar = Cudd_bddIthVar( dd, nSize - 1 );
+    assert( nSize <= dd->size );
+    // find the permutation after collapsing
+    RetValue = Abc_NodeCollapsePermMap( pFanin, NULL, vFanins, pPermFanin );
+    assert( RetValue );
+    RetValue = Abc_NodeCollapsePermMap( pFanout, pFanin, vFanins, pPermFanout );
+    assert( RetValue );
+    // cofactor the local function of the node
+    bVar   = Cudd_bddIthVar( dd, iFanin );
+    bFunc0 = Cudd_Cofactor( dd, (DdNode *)pFanout->pData, Cudd_Not(bVar) ); Cudd_Ref( bFunc0 );
+    bFunc1 = Cudd_Cofactor( dd, (DdNode *)pFanout->pData, bVar );           Cudd_Ref( bFunc1 );
+    // find the permutation after collapsing
+    bFunc0 = Cudd_bddPermute( dd, bTemp = bFunc0, pPermFanout );  Cudd_Ref( bFunc0 );
+    Cudd_RecursiveDeref( dd, bTemp ); 
+    bFunc1 = Cudd_bddPermute( dd, bTemp = bFunc1, pPermFanout );  Cudd_Ref( bFunc1 );
+    Cudd_RecursiveDeref( dd, bTemp );
+    bFanin = Cudd_bddPermute( dd, (DdNode *)pFanin->pData, pPermFanin );    Cudd_Ref( bFanin );
+    // create the new function
+    bFanout = Cudd_bddIte( dd, bFanin, bFunc1, bFunc0 );          Cudd_Ref( bFanout );
+    Cudd_RecursiveDeref( dd, bFanin );
+    Cudd_RecursiveDeref( dd, bFunc1 );
+    Cudd_RecursiveDeref( dd, bFunc0 );
+    Cudd_Deref( bFanout );
+    return bFanout;
+}
+int Abc_NodeCollapse( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins, int * pPermFanin, int * pPermFanout )
+{
+    Abc_Obj_t * pFanoutNew, * pObj;
+    DdNode * bFanoutNew;
+    int i;
+    assert( Abc_NtkIsBddLogic(pFanin->pNtk) );
+    assert( Abc_ObjIsNode(pFanin) );
+    assert( Abc_ObjIsNode(pFanout) );
+    bFanoutNew = Abc_NodeCollapseFunc( pFanin, pFanout, vFanins, pPermFanin, pPermFanout );  
+    if ( bFanoutNew == NULL )
+        return 0;
+    Cudd_Ref( bFanoutNew );
+    // create the new node
+    pFanoutNew = Abc_NtkCreateNode( pFanin->pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i )
+        Abc_ObjAddFanin( pFanoutNew, pObj );
+    pFanoutNew->pData = bFanoutNew;
+    // minimize the node
+    Abc_NodeMinimumBase( pFanoutNew );
+    // transfer the fanout
+    Abc_ObjTransferFanout( pFanout, pFanoutNew );
+    assert( Abc_ObjFanoutNum( pFanout ) == 0 );
+    Abc_NtkDeleteObj_rec( pFanout, 1 );
+    return 1;
+}
+int Abc_NtkEliminate( Abc_Ntk_t * pNtk, int nMaxSize, int fReverse, int fVerbose )
+{
+    extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose );
+    Vec_Ptr_t * vFanouts, * vFanins, * vNodes;
+    Abc_Obj_t * pNode, * pFanout;
+    int * pPermFanin, * pPermFanout;
+    int RetValue, i, k;
+    assert( nMaxSize > 0 );
+    assert( Abc_NtkIsLogic(pNtk) ); 
+    // convert network to BDD representation
+    if ( !Abc_NtkToBdd(pNtk) )
+    {
+        fprintf( stdout, "Converting to BDD has failed.\n" );
+        return 0;
+    }
+    // prepare nodes for sweeping
+    Abc_NtkRemoveDupFanins( pNtk );
+    Abc_NtkMinimumBase( pNtk );
+    Abc_NtkCleanup( pNtk, 0 );
+    // get the nodes in the given order
+    vNodes = fReverse? Abc_NtkDfsReverse( pNtk ) : Abc_NtkDfs( pNtk, 0 );
+    // go through the nodes and decide is they can be eliminated
+    pPermFanin = ABC_ALLOC( int, nMaxSize + 1000 );
+    pPermFanout = ABC_ALLOC( int, nMaxSize + 1000 );
+    vFanins = Vec_PtrAlloc( 1000 );
+    vFanouts = Vec_PtrAlloc( 1000 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( !Abc_ObjIsNode(pNode) ) // skip deleted nodes
+            continue;
+        if ( Abc_NodeFindCoFanout(pNode) != NULL )
+            continue;
+        if ( Abc_ObjFaninNum(pNode) > nMaxSize )
+            continue;
+        Abc_ObjForEachFanout( pNode, pFanout, k )
+            if ( Abc_NodeCollapseSuppSize(pNode, pFanout, vFanins) > nMaxSize )
+                break;
+        if ( k < Abc_ObjFanoutNum(pNode) )
+            continue;
+        // perform elimination
+        Abc_NodeCollectFanouts( pNode, vFanouts );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, k )
+        {
+            if ( fVerbose )
+                printf( "Collapsing fanin %5d (supp =%2d) into fanout %5d (supp =%2d) ",
+                    Abc_ObjId(pNode), Abc_ObjFaninNum(pNode), Abc_ObjId(pFanout), Abc_ObjFaninNum(pFanout) ); 
+            RetValue = Abc_NodeCollapse( pNode, pFanout, vFanins, pPermFanin, pPermFanout );
+            assert( RetValue );
+            if ( fVerbose )
+            {
+                Abc_Obj_t * pNodeNew = Abc_NtkObj( pNtk, Abc_NtkObjNumMax(pNtk) - 1 );
+                if ( pNodeNew )
+                    printf( "resulting in node %5d (supp =%2d).\n", Abc_ObjId(pNodeNew), Abc_ObjFaninNum(pNodeNew) );
+            }
+        }
+    }
+    Abc_NtkBddReorder( pNtk, 0 );
+    Vec_PtrFree( vFanins );
+    Vec_PtrFree( vFanouts );
+    Vec_PtrFree( vNodes );
+    ABC_FREE( pPermFanin );
+    ABC_FREE( pPermFanout );
+    return 1;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Check how many times fanin appears in the FF of the fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCountAppearances( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout )
+{
+    Hop_Man_t * pMan = (Hop_Man_t *)pFanin->pNtk->pManFunc;
+    int iFanin = Abc_NodeFindFanin( pFanout, pFanin );
+    assert( iFanin >= 0 && iFanin < Hop_ManPiNum(pMan) );
+    return Hop_ObjFanoutCount( (Hop_Obj_t *)pFanout->pData, Hop_IthVar(pMan, iFanin) );
+}
+int Abc_NodeCountAppearancesAll( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanout;
+    int i, Count = 0;
+    Abc_ObjForEachFanout( pNode, pFanout, i )
+        Count += Abc_NodeCountAppearances( pNode, pFanout );
+    return Count;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs traditional eliminate -1.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Abc_NodeCollapseFunc1( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins, int * pPermFanin, int * pPermFanout )
+{
+    Hop_Man_t * pMan = (Hop_Man_t *)pFanin->pNtk->pManFunc;
+    Hop_Obj_t * bFanin, * bFanout;
+    int RetValue, nSize, iFanin;
+    // can only eliminate if fanin occurs in the fanin list of the fanout exactly once
+    if ( Abc_NodeCheckDupFanin( pFanin, pFanout, &iFanin ) != 1 )
+        return NULL;
+    // find the new number of fanins after collapsing
+    nSize = Abc_NodeCollapseSuppSize( pFanin, pFanout, vFanins );
+    Hop_IthVar( pMan, nSize ); // use additional var for fanin variable
+    assert( nSize + 1 <= Hop_ManPiNum(pMan) );
+    // find the permutation after collapsing
+    RetValue = Abc_NodeCollapsePermMap( pFanin, NULL, vFanins, pPermFanin );
+    assert( RetValue );
+    RetValue = Abc_NodeCollapsePermMap( pFanout, pFanin, vFanins, pPermFanout );
+    assert( RetValue );
+    // include fanin's variable
+    pPermFanout[iFanin] = nSize;
+    // create new function of fanin and fanout
+    bFanin  = Hop_Permute( pMan, (Hop_Obj_t *)pFanin->pData,  Abc_ObjFaninNum(pFanin),  pPermFanin );
+    bFanout = Hop_Permute( pMan, (Hop_Obj_t *)pFanout->pData, Abc_ObjFaninNum(pFanout), pPermFanout );
+    // compose fanin into fanout
+    return Hop_Compose( pMan, bFanout, bFanin, nSize );
+}
+int Abc_NodeCollapse1( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins, int * pPermFanin, int * pPermFanout )
+{
+    Abc_Obj_t * pFanoutNew, * pObj;
+    Hop_Obj_t * bFanoutNew;
+    int i;
+    assert( Abc_NtkIsAigLogic(pFanin->pNtk) );
+    assert( Abc_ObjIsNode(pFanin) );
+    assert( Abc_ObjIsNode(pFanout) );
+    bFanoutNew = Abc_NodeCollapseFunc1( pFanin, pFanout, vFanins, pPermFanin, pPermFanout );  
+    if ( bFanoutNew == NULL )
+        return 0;
+    // create the new node
+    pFanoutNew = Abc_NtkCreateNode( pFanin->pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i )
+        Abc_ObjAddFanin( pFanoutNew, pObj );
+    pFanoutNew->pData = bFanoutNew;
+    // transfer the fanout
+    Abc_ObjTransferFanout( pFanout, pFanoutNew );
+    assert( Abc_ObjFanoutNum( pFanout ) == 0 );
+    Abc_NtkDeleteObj_rec( pFanout, 1 );
+    return 1;
+}
+int Abc_NodeIsExor( Abc_Obj_t * pNode )
+{
+    Hop_Man_t * pMan;
+    word Truth;
+    if ( Abc_ObjFaninNum(pNode) < 3 || Abc_ObjFaninNum(pNode) > 6 )
+        return 0;
+    pMan = (Hop_Man_t *)pNode->pNtk->pManFunc;
+    Truth = Hop_ManComputeTruth6( pMan, (Hop_Obj_t *)pNode->pData, Abc_ObjFaninNum(pNode) );
+    if ( Truth == 0x6666666666666666 || Truth == 0x9999999999999999 || 
+         Truth == 0x9696969696969696 || Truth == 0x6969696969696969 || 
+         Truth == 0x6996699669966996 || Truth == 0x9669966996699669 || 
+         Truth == 0x9669699696696996 || Truth == 0x6996966969969669 ||
+         Truth == 0x6996966996696996 || Truth == 0x9669699669969669 )
+         return 1;
+    return 0;
+}
+int Abc_NtkEliminate1One( Abc_Ntk_t * pNtk, int ElimValue, int nMaxSize, int fReverse, int fVerbose )
+{
+    Vec_Ptr_t * vFanouts, * vFanins, * vNodes;
+    Abc_Obj_t * pNode, * pFanout;
+    int * pPermFanin, * pPermFanout;
+    int RetValue, i, k;
+    assert( nMaxSize > 0 );
+    assert( Abc_NtkIsLogic(pNtk) ); 
+    // convert network to BDD representation
+    if ( !Abc_NtkToAig(pNtk) )
+    {
+        fprintf( stdout, "Converting to AIG has failed.\n" );
+        return 0;
+    }
+    // get the nodes in the given order
+    vNodes = fReverse? Abc_NtkDfsReverse( pNtk ) : Abc_NtkDfs( pNtk, 0 );
+    // go through the nodes and decide is they can be eliminated
+    pPermFanin = ABC_ALLOC( int, nMaxSize + 1000 );
+    pPermFanout = ABC_ALLOC( int, nMaxSize + 1000 );
+    vFanins = Vec_PtrAlloc( 1000 );
+    vFanouts = Vec_PtrAlloc( 1000 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( !Abc_ObjIsNode(pNode) ) // skip deleted nodes
+            continue;
+        if ( Abc_NodeFindCoFanout(pNode) != NULL )
+            continue;
+        if ( Abc_ObjFaninNum(pNode) > nMaxSize )
+            continue;
+        if ( Abc_NodeIsExor(pNode) )
+            continue;
+        // skip nodes with more than one fanout
+//        if ( Abc_ObjFanoutNum(pNode) != 1 ) 
+//            continue;
+        // skip nodes that appear in the FF of their fanout more than once
+        if ( Abc_NodeCountAppearancesAll( pNode ) > ElimValue + 2 ) 
+            continue;       
+        Abc_ObjForEachFanout( pNode, pFanout, k )
+            if ( Abc_NodeCollapseSuppSize(pNode, pFanout, vFanins) > nMaxSize )
+                break;
+        if ( k < Abc_ObjFanoutNum(pNode) )
+            continue;
+        // perform elimination
+        Abc_NodeCollectFanouts( pNode, vFanouts );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, k )
+        {
+            if ( fVerbose )
+                printf( "Collapsing fanin %5d (supp =%2d) into fanout %5d (supp =%2d) ",
+                    Abc_ObjId(pNode), Abc_ObjFaninNum(pNode), Abc_ObjId(pFanout), Abc_ObjFaninNum(pFanout) ); 
+            RetValue = Abc_NodeCollapse1( pNode, pFanout, vFanins, pPermFanin, pPermFanout );
+            assert( RetValue );
+            if ( fVerbose )
+            {
+                Abc_Obj_t * pNodeNew = Abc_NtkObj( pNtk, Abc_NtkObjNumMax(pNtk) - 1 );
+                if ( pNodeNew )
+                    printf( "resulting in node %5d (supp =%2d).\n", Abc_ObjId(pNodeNew), Abc_ObjFaninNum(pNodeNew) );
+            }
+        }
+    }
+    Vec_PtrFree( vFanins );
+    Vec_PtrFree( vFanouts );
+    Vec_PtrFree( vNodes );
+    ABC_FREE( pPermFanin );
+    ABC_FREE( pPermFanout );
+    return 1;
+}
+int Abc_NtkEliminate1( Abc_Ntk_t * pNtk, int ElimValue, int nMaxSize, int nIterMax, int fReverse, int fVerbose )
+{
+    int i;
+    for ( i = 0; i < nIterMax; i++ )
+    {
+        int nNodes = Abc_NtkNodeNum(pNtk);
+//        printf( "%d ", nNodes );
+        if ( !Abc_NtkEliminate1One(pNtk, ElimValue, nMaxSize, fReverse, fVerbose) )
+            return 0;
+        if ( nNodes == Abc_NtkNodeNum(pNtk) )
+            break;
+    }
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcNames.c b/abc-build/src/base/abc/abcNames.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcNames.c
@@ -0,0 +1,639 @@
+/**CFile****************************************************************
+
+  FileName    [abcNames.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Procedures working with net and node names.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcNames.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the unique name for the object.]
+
+  Description [If the name previously did not exist, creates a new unique
+  name but does not assign this name to the object. The temporary unique
+  name is stored in a static buffer inside this procedure. It is important 
+  that the name is used before the function is called again!]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_ObjName( Abc_Obj_t * pObj )
+{
+    return Nm_ManCreateUniqueName( pObj->pNtk->pManName, pObj->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns the given name to the object.]
+
+  Description [The object should not have a name assigned. The same
+  name may be used for several objects, which they share the same net
+  in the original netlist. (For example, latch output and primary output 
+  may have the same name.) This procedure returns the pointer to the 
+  internally stored representation of the given name.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_ObjAssignName( Abc_Obj_t * pObj, char * pName, char * pSuffix )
+{
+    assert( pName != NULL );
+    return Nm_ManStoreIdName( pObj->pNtk->pManName, pObj->Id, pObj->Type, pName, pSuffix );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Appends name to the prefix]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_ObjNamePrefix( Abc_Obj_t * pObj, char * pPrefix )
+{
+    static char Buffer[2000];
+    sprintf( Buffer, "%s%s", pPrefix, Abc_ObjName(pObj) );
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Appends suffic to the name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_ObjNameSuffix( Abc_Obj_t * pObj, char * pSuffix )
+{
+    static char Buffer[2000];
+    sprintf( Buffer, "%s%s", Abc_ObjName(pObj), pSuffix );
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the dummy PI name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_ObjNameDummy( char * pPrefix, int Num, int nDigits )
+{
+    static char Buffer[2000];
+    sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num );
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tranfers names to the old network.]
+
+  Description [Assumes that the new nodes are attached using pObj->pCopy.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTrasferNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) );
+    assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) );
+    assert( Abc_NtkBoxNum(pNtk) == Abc_NtkBoxNum(pNtkNew) );
+    assert( Nm_ManNumEntries(pNtk->pManName) > 0 );
+    assert( Nm_ManNumEntries(pNtkNew->pManName) == 0 );
+    // copy the CI/CO/box names
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL );
+    Abc_NtkForEachCo( pNtk, pObj, i ) 
+        Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL );
+    Abc_NtkForEachBox( pNtk, pObj, i ) 
+        Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tranfers names to the old network.]
+
+  Description [Assumes that the new nodes are attached using pObj->pCopy.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTrasferNamesNoLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) );
+    assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) );
+    assert( Nm_ManNumEntries(pNtk->pManName) > 0 );
+    assert( Nm_ManNumEntries(pNtkNew->pManName) == 0 );
+    // copy the CI/CO/box name and skip latches and theirs inputs/outputs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        if ( Abc_ObjFaninNum(pObj) == 0 || !Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) )
+            Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL );
+    Abc_NtkForEachCo( pNtk, pObj, i ) 
+        if ( Abc_ObjFanoutNum(pObj) == 0 || !Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) )
+            Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL );
+    Abc_NtkForEachBox( pNtk, pObj, i ) 
+        if ( !Abc_ObjIsLatch(pObj) )
+            Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gets fanin node names.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pFanin;
+    int i;
+    vNodes = Vec_PtrAlloc( 100 );
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        Vec_PtrPush( vNodes, Abc_UtilStrsav(Abc_ObjName(pFanin)) );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gets fanin node names.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NodeGetFakeNames( int nNames )
+{
+    Vec_Ptr_t * vNames;
+    char Buffer[5];
+    int i;
+
+    vNames = Vec_PtrAlloc( nNames );
+    for ( i = 0; i < nNames; i++ )
+    {
+        if ( nNames < 26 )
+        {
+            Buffer[0] = 'a' + i;
+            Buffer[1] = 0;
+        }
+        else
+        {
+            Buffer[0] = 'a' + i%26;
+            Buffer[1] = '0' + i/26;
+            Buffer[2] = 0;
+        }
+        Vec_PtrPush( vNames, Extra_UtilStrsav(Buffer) );
+    }
+    return vNames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gets fanin node names.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeFreeNames( Vec_Ptr_t * vNames )
+{
+    int i;
+    if ( vNames == NULL )
+        return;
+    for ( i = 0; i < vNames->nSize; i++ )
+        ABC_FREE( vNames->pArray[i] );
+    Vec_PtrFree( vNames );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the CI or CO names.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char ** Abc_NtkCollectCioNames( Abc_Ntk_t * pNtk, int fCollectCos )
+{
+    Abc_Obj_t * pObj;
+    char ** ppNames;
+    int i;
+    if ( fCollectCos )
+    {
+        ppNames = ABC_ALLOC( char *, Abc_NtkCoNum(pNtk) );
+        Abc_NtkForEachCo( pNtk, pObj, i )
+            ppNames[i] = Abc_ObjName(pObj);
+    }
+    else
+    {
+        ppNames = ABC_ALLOC( char *, Abc_NtkCiNum(pNtk) );
+        Abc_NtkForEachCi( pNtk, pObj, i )
+            ppNames[i] = Abc_ObjName(pObj);
+    }
+    return ppNames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure used for sorting the nodes in decreasing order of levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCompareNames( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 )
+{
+    int Diff = strcmp( (char *)(*pp1)->pCopy, (char *)(*pp2)->pCopy );
+    if ( Diff < 0 )
+        return -1;
+    if ( Diff > 0 ) 
+        return 1;
+    Diff = (*pp1)->Id - (*pp2)->Id;
+    if ( Diff < 0 )
+        return -1;
+    if ( Diff > 0 ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Orders PIs/POs/latches alphabetically.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkOrderObjsByName( Abc_Ntk_t * pNtk, int fComb )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
+    // temporarily store the names in the copy field
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj);
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj);
+    Abc_NtkForEachBox( pNtk, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(Abc_ObjFanout0(pObj));
+    // order objects alphabetically
+    qsort( (void *)Vec_PtrArray(pNtk->vPis), Vec_PtrSize(pNtk->vPis), sizeof(Abc_Obj_t *), 
+        (int (*)(const void *, const void *)) Abc_NodeCompareNames );
+    qsort( (void *)Vec_PtrArray(pNtk->vPos), Vec_PtrSize(pNtk->vPos), sizeof(Abc_Obj_t *), 
+        (int (*)(const void *, const void *)) Abc_NodeCompareNames );
+    // if the comparison if combinational (latches as PIs/POs), order them too
+    if ( fComb )
+        qsort( (void *)Vec_PtrArray(pNtk->vBoxes), Vec_PtrSize(pNtk->vBoxes), sizeof(Abc_Obj_t *), 
+            (int (*)(const void *, const void *)) Abc_NodeCompareNames );
+    // order CIs/COs first PIs/POs(Asserts) then latches
+    Abc_NtkOrderCisCos( pNtk );
+    // clean the copy fields
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        pObj->pCopy = NULL;
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        pObj->pCopy = NULL;
+    Abc_NtkForEachBox( pNtk, pObj, i )
+        pObj->pCopy = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds dummy names.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int nDigits, i;
+    nDigits = Abc_Base10Log( Abc_NtkPiNum(pNtk) );
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        Abc_ObjAssignName( pObj, Abc_ObjNameDummy("pi", i, nDigits), NULL );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds dummy names.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int nDigits, i;
+    nDigits = Abc_Base10Log( Abc_NtkPoNum(pNtk) );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        Abc_ObjAssignName( pObj, Abc_ObjNameDummy("po", i, nDigits), NULL );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds dummy names.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk )
+{
+    char * pName, PrefLi[100], PrefLo[100];
+    Abc_Obj_t * pObj;
+    int nDigits, i, k, CountCur, CountMax = 0;
+    // if PIs/POs already have nodes with what looks like latch names
+    // we need to add different prefix for the new latches
+    Abc_NtkForEachPi( pNtk, pObj, i )
+    {
+        CountCur = 0;
+        pName = Abc_ObjName(pObj);
+        for ( k = 0; pName[k]; k++ )
+            if ( pName[k] == 'l' )
+                CountCur++;
+            else
+                break;
+        CountMax = Abc_MaxInt( CountMax, CountCur );
+    }
+    Abc_NtkForEachPo( pNtk, pObj, i )
+    {
+        CountCur = 0;
+        pName = Abc_ObjName(pObj);
+        for ( k = 0; pName[k]; k++ )
+            if ( pName[k] == 'l' )
+                CountCur++;
+            else
+                break;
+        CountMax = Abc_MaxInt( CountMax, CountCur );
+    }
+//printf( "CountMax = %d\n", CountMax );
+    assert( CountMax < 100-2 );
+    for ( i = 0; i <= CountMax; i++ )
+        PrefLi[i] = PrefLo[i] = 'l';
+    PrefLi[i] = 'i';
+    PrefLo[i] = 'o';
+    PrefLi[i+1] = 0;
+    PrefLo[i+1] = 0;
+    // create latch names
+    assert( !Abc_NtkIsNetlist(pNtk) );
+    nDigits = Abc_Base10Log( Abc_NtkLatchNum(pNtk) );
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+    {
+        Abc_ObjAssignName( pObj, Abc_ObjNameDummy("l", i, nDigits), NULL );
+        Abc_ObjAssignName( Abc_ObjFanin0(pObj),  Abc_ObjNameDummy(PrefLi, i, nDigits), NULL );
+        Abc_ObjAssignName( Abc_ObjFanout0(pObj), Abc_ObjNameDummy(PrefLo, i, nDigits), NULL );
+    }
+/*
+    nDigits = Abc_Base10Log( Abc_NtkBlackboxNum(pNtk) );
+    Abc_NtkForEachBlackbox( pNtk, pObj, i )
+    {
+        pName = Abc_ObjAssignName( pObj, Abc_ObjNameDummy("B", i, nDigits), NULL );
+        nDigitsF = Abc_Base10Log( Abc_ObjFaninNum(pObj) );
+        Abc_ObjForEachFanin( pObj, pTerm, k )
+            Abc_ObjAssignName( Abc_ObjFanin0(pObj), pName, Abc_ObjNameDummy("i", k, nDigitsF) );
+        nDigitsF = Abc_Base10Log( Abc_ObjFanoutNum(pObj) );
+        Abc_ObjForEachFanout( pObj, pTerm, k )
+            Abc_ObjAssignName( Abc_ObjFanin0(pObj), pName, Abc_ObjNameDummy("o", k, nDigitsF) );
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces names by short names.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkShortNames( Abc_Ntk_t * pNtk )
+{
+    Nm_ManFree( pNtk->pManName );
+    pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk) + Abc_NtkBoxNum(pNtk) );
+    Abc_NtkAddDummyPiNames( pNtk );
+    Abc_NtkAddDummyPoNames( pNtk );
+    Abc_NtkAddDummyBoxNames( pNtk );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Saves name IDs into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkStartNameIds( Abc_Ntk_t * p )
+{
+    char pFileName[1000];
+    FILE * pFile;
+    Abc_Obj_t * pObj, * pFanin;
+    Vec_Ptr_t * vNodes;
+    int i, Counter = 1;
+    assert( Abc_NtkIsNetlist(p) );
+    assert( p->vNameIds == NULL );
+    assert( strlen(p->pSpec) < 1000 );
+    sprintf( pFileName, "%s_%s_names.txt", Extra_FileNameGenericAppend(p->pSpec,""), Extra_FileNameExtension(p->pSpec) );
+    pFile = fopen( pFileName, "wb" );
+    p->vNameIds = Vec_IntStart( Abc_NtkObjNumMax(p) );
+    // add inputs
+    Abc_NtkForEachCi( p, pObj, i )
+        fprintf( pFile, "%s            \n", Abc_ObjName(Abc_ObjFanout0(pObj)) ), Vec_IntWriteEntry(p->vNameIds, Abc_ObjId(pObj), 2*Counter++);
+    // add outputs
+    Abc_NtkForEachCo( p, pObj, i )
+    {
+        pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pObj));
+        if ( !Vec_IntEntry(p->vNameIds, Abc_ObjId(pFanin)) )
+            fprintf( pFile, "%s            \n", Abc_ObjName(Abc_ObjFanout0(pFanin)) ), Vec_IntWriteEntry(p->vNameIds, Abc_ObjId(pFanin), 2*Counter++);
+    }
+    // add nodes in a topo order
+    vNodes = Abc_NtkDfs( p, 1 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        if ( !Vec_IntEntry(p->vNameIds, Abc_ObjId(pObj)) )
+            fprintf( pFile, "%s            \n", Abc_ObjName(Abc_ObjFanout0(pObj)) ), Vec_IntWriteEntry(p->vNameIds, Abc_ObjId(pObj), 2*Counter++);
+    Vec_PtrFree( vNodes );
+    fclose( pFile );
+    // transfer driver node names to COs
+    Abc_NtkForEachCo( p, pObj, i )
+    {
+        pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pObj));
+        Vec_IntWriteEntry( p->vNameIds, Abc_ObjId(pObj), Vec_IntEntry(p->vNameIds, Abc_ObjId(pFanin)) );
+        Vec_IntWriteEntry( p->vNameIds, Abc_ObjId(pFanin), 0 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Remaps the AIG from the old manager into the new manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTransferNameIds( Abc_Ntk_t * p, Abc_Ntk_t * pNew )
+{
+    Abc_Obj_t * pObj, * pObjNew;
+    int i;
+    assert( p->vNameIds != NULL );
+    assert( pNew->vNameIds == NULL );
+    pNew->vNameIds = Vec_IntStart( Abc_NtkObjNumMax(pNew) );
+//    Abc_NtkForEachCi( p, pObj, i )
+//        printf( "%d ", Vec_IntEntry(p->vNameIds, Abc_ObjId(pObj)) );
+//    printf( "\n" );
+    Abc_NtkForEachObj( p, pObj, i )
+        if ( pObj->pCopy && i < Vec_IntSize(p->vNameIds) && Vec_IntEntry(p->vNameIds, i) )
+        {
+            pObjNew = Abc_ObjRegular(pObj->pCopy);
+            assert( Abc_ObjNtk(pObjNew) == pNew );
+            if ( Abc_ObjIsCi(pObjNew) && !Abc_ObjIsCi(pObj) ) // do not overwrite CI name by internal node name
+                continue;
+            Vec_IntWriteEntry( pNew->vNameIds, Abc_ObjId(pObjNew), Vec_IntEntry(p->vNameIds, i) ^ Abc_ObjIsComplement(pObj->pCopy) );
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates file with name IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkUpdateNameIds( Abc_Ntk_t * p )
+{
+    char pFileName[1000];
+    Vec_Int_t * vStarts;
+    Abc_Obj_t * pObj;
+    FILE * pFile;
+    int i, c, iVar, fCompl, fSeenSpace, Counter = 0;
+    assert( !Abc_NtkIsNetlist(p) );
+    assert( strlen(p->pSpec) < 1000 );
+    assert( p->vNameIds != NULL );
+    sprintf( pFileName, "%s_%s_names.txt", Extra_FileNameGenericAppend(p->pSpec,""), Extra_FileNameExtension(p->pSpec) );
+    pFile = fopen( pFileName, "r+" );
+    // collect info about lines
+    fSeenSpace = 0;
+    vStarts = Vec_IntAlloc( 1000 );
+    Vec_IntPush( vStarts, -1 );
+    while ( (c = fgetc(pFile)) != EOF && ++Counter )
+        if ( c == ' ' && !fSeenSpace )
+            Vec_IntPush(vStarts, Counter), fSeenSpace = 1;
+        else if ( c == '\n' )
+            fSeenSpace = 0;
+    // add info about names
+    Abc_NtkForEachObj( p, pObj, i )
+    {
+        if ( i == 0 || i >= Vec_IntSize(p->vNameIds) || !Vec_IntEntry(p->vNameIds, i) )
+            continue;
+        iVar = Abc_Lit2Var( Vec_IntEntry(p->vNameIds, i) );
+        fCompl = Abc_LitIsCompl( Vec_IntEntry(p->vNameIds, i) );
+        assert( iVar < Vec_IntSize(vStarts) );
+        fseek( pFile, Vec_IntEntry(vStarts, iVar), SEEK_SET );
+        fprintf( pFile, "%s%d", fCompl? "-":"", i );
+    }
+    printf( "Saved %d names into file \"%s\".\n", Vec_IntSize(vStarts)-1, pFileName );
+    fclose( pFile );
+    Vec_IntFree( vStarts );
+    Vec_IntFreeP( &p->vNameIds );
+//    Abc_NtkForEachObj( p, pObj, i )
+//        Abc_ObjPrint( stdout, pObj );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcNetlist.c b/abc-build/src/base/abc/abcNetlist.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcNetlist.c
@@ -0,0 +1,505 @@
+/**CFile****************************************************************
+
+  FileName    [abcNetlist.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Transforms netlist into a logic network and vice versa.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcNetlist.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "base/main/main.h"
+//#include "seq.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkAddPoBuffers( Abc_Ntk_t * pNtk );
+static Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk );
+static Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk );
+static Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Transform the netlist into a logic network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k;
+    // consider the case of the AIG
+    if ( Abc_NtkIsStrash(pNtk) )
+        return Abc_NtkAigToLogicSop( pNtk );
+    assert( Abc_NtkIsNetlist(pNtk) );
+    // consider simple case when there is hierarchy
+//    assert( pNtk->pDesign == NULL );
+    assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+    assert( Abc_NtkBlackboxNum(pNtk) == 0 );
+    // start the network
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, pNtk->ntkFunc );
+    // duplicate the nodes 
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        Abc_NtkDupObj(pNtkNew, pObj, 0);
+    // reconnect the internal nodes in the new network
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pFanin)->pCopy );
+    // collect the CO nodes
+    Abc_NtkFinalize( pNtk, pNtkNew );
+    // fix the problem with CO pointing directly to CIs
+    Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+    // duplicate EXDC 
+    if ( pNtk->pExdc )
+        pNtkNew->pExdc = Abc_NtkToLogic( pNtk->pExdc );
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkToLogic(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transform the logic network into a netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew, * pNtkTemp; 
+    assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
+    if ( Abc_NtkIsStrash(pNtk) )
+    {
+        pNtkTemp = Abc_NtkAigToLogicSop(pNtk);
+        pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp );
+        Abc_NtkDelete( pNtkTemp );
+        return pNtkNew;
+    }
+    return Abc_NtkLogicToNetlist( pNtk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the AIG into the netlist.]
+
+  Description [This procedure does not copy the choices.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew, * pNtkTemp; 
+    assert( Abc_NtkIsStrash(pNtk) );
+    pNtkTemp = Abc_NtkAigToLogicSopBench( pNtk );
+    pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp );
+    Abc_NtkDelete( pNtkTemp );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transform the logic network into a netlist.]
+
+  Description [The logic network given to this procedure should
+  have exactly the same structure as the resulting netlist. The COs
+  can only point to CIs if they have identical names. Otherwise, 
+  they should have a node between them, even if this node is 
+  inverter or buffer.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pObj, * pNet, * pDriver, * pFanin;
+    int i, k;
+
+    assert( Abc_NtkIsLogic(pNtk) );
+
+    // remove dangling nodes
+    Abc_NtkCleanup( pNtk, 0 );
+
+    // make sure the CO names are unique
+    Abc_NtkCheckUniqueCiNames( pNtk );
+    Abc_NtkCheckUniqueCoNames( pNtk );
+    Abc_NtkCheckUniqueCioNames( pNtk );
+
+//    assert( Abc_NtkLogicHasSimpleCos(pNtk) );
+    if ( !Abc_NtkLogicHasSimpleCos(pNtk) )
+    {
+        if ( !Abc_FrameReadFlag("silentmode") )
+            printf( "Abc_NtkLogicToNetlist() warning: The network is converted to have simple COs.\n" );
+        Abc_NtkLogicMakeSimpleCos( pNtk, 0 );
+    }
+
+    // start the netlist by creating PI/PO/Latch objects
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_NETLIST, pNtk->ntkFunc );
+    // create the CI nets and remember them in the new CI nodes
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) );
+        Abc_ObjAddFanin( pNet, pObj->pCopy );
+        pObj->pCopy->pCopy = pNet;
+    }
+    // duplicate all nodes
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        Abc_NtkDupObj(pNtkNew, pObj, 0);
+    // first add the nets to the CO drivers
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        pDriver = Abc_ObjFanin0(pObj);
+        if ( Abc_ObjIsCi(pDriver) )
+        {
+            assert( !strcmp( Abc_ObjName(pDriver), Abc_ObjName(pObj) ) );
+            Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy );
+            continue;
+        }
+        assert( Abc_ObjIsNode(pDriver) );
+        // if the CO driver has no net, create it
+        if ( pDriver->pCopy->pCopy == NULL )
+        {
+            // create the CO net and connect it to CO
+            pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) );
+            Abc_ObjAddFanin( pObj->pCopy, pNet );
+            // connect the CO net to the new driver and remember it in the new driver
+            Abc_ObjAddFanin( pNet, pDriver->pCopy );
+            pDriver->pCopy->pCopy = pNet;
+        }
+        else
+        {
+            assert( !strcmp( Abc_ObjName(pDriver->pCopy->pCopy), Abc_ObjName(pObj) ) );
+            Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy );
+        }
+    }
+    // create the missing nets
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        if ( pObj->pCopy->pCopy ) // the net of the new object is already created
+            continue;
+        // create the new net
+        pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); // here we create ridiculous names net line "n48", where 48 is the ID of the node
+        Abc_ObjAddFanin( pNet, pObj->pCopy );
+        pObj->pCopy->pCopy = pNet;
+    }
+    // connect nodes to the fanins nets
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy );
+    // duplicate EXDC 
+    if ( pNtk->pExdc )
+        pNtkNew->pExdc = Abc_NtkToNetlist( pNtk->pExdc );
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkLogicToNetlist(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the AIG into the logic network with SOPs.]
+
+  Description [Correctly handles the case of choice nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk )
+{
+    extern int Abc_NtkLogicMakeSimpleCos2( Abc_Ntk_t * pNtk, int fDuplicate );
+
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pObj, * pFanin, * pNodeNew;
+    Vec_Int_t * vInts;
+    int i, k, fChoices = 0;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // start the network
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+    // if the constant node is used, duplicate it
+    pObj = Abc_AigConst1(pNtk);
+    if ( Abc_ObjFanoutNum(pObj) > 0 )
+        pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew);
+    // duplicate the nodes and create node functions
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        Abc_NtkDupObj(pNtkNew, pObj, 0);
+        pObj->pCopy->pData = Abc_SopCreateAnd2( (Mem_Flex_t *)pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+    }
+    // create the choice nodes
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        if ( !Abc_AigNodeIsChoice(pObj) )
+            continue;
+        // create an OR gate
+        pNodeNew = Abc_NtkCreateNode(pNtkNew);
+        // add fanins
+        vInts = Vec_IntAlloc( 10 );
+        for ( pFanin = pObj; pFanin; pFanin = (Abc_Obj_t *)pFanin->pData )
+        {
+            Vec_IntPush( vInts, (int)(pObj->fPhase != pFanin->fPhase) );
+            Abc_ObjAddFanin( pNodeNew, pFanin->pCopy );
+        }
+        // create the logic function
+        pNodeNew->pData = Abc_SopCreateOrMultiCube( (Mem_Flex_t *)pNtkNew->pManFunc, Vec_IntSize(vInts), Vec_IntArray(vInts) );
+        // set the new node
+        pObj->pCopy->pCopy = pNodeNew;
+        Vec_IntFree( vInts );
+        fChoices = 1;
+    }
+    // connect the internal nodes
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            if ( pFanin->pCopy->pCopy )
+                Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy );
+            else
+                Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+    // connect the COs
+//    Abc_NtkFinalize( pNtk, pNtkNew );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        pFanin = Abc_ObjFanin0(pObj);
+        if ( pFanin->pCopy->pCopy )
+            pNodeNew = Abc_ObjNotCond(pFanin->pCopy->pCopy, Abc_ObjFaninC0(pObj));
+        else
+            pNodeNew = Abc_ObjNotCond(pFanin->pCopy, Abc_ObjFaninC0(pObj));
+        Abc_ObjAddFanin( pObj->pCopy, pNodeNew );
+    }
+
+    // fix the problem with complemented and duplicated CO edges
+    if ( fChoices )
+        Abc_NtkLogicMakeSimpleCos2( pNtkNew, 0 );
+    else
+        Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+    // duplicate the EXDC Ntk
+    if ( pNtk->pExdc )
+    {
+        if ( Abc_NtkIsStrash(pNtk->pExdc) )
+            pNtkNew->pExdc = Abc_NtkAigToLogicSop( pNtk->pExdc );
+        else
+            pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+    }
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkAigToLogicSop(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the AIG into the logic network with SOPs for bench writing.]
+
+  Description [This procedure does not copy the choices.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pObj, * pFanin;
+    Vec_Ptr_t * vNodes;
+    int i, k;
+    assert( Abc_NtkIsStrash(pNtk) );
+    if ( Abc_NtkGetChoiceNum(pNtk) )
+        printf( "Warning: Choice nodes are skipped.\n" );
+    // start the network
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+    // collect the nodes to be used (marks all nodes with current TravId)
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    // create inverters for the constant node
+    pObj = Abc_AigConst1(pNtk);
+    if ( Abc_ObjFanoutNum(pObj) > 0 )
+        pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew);
+    if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) )
+        pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy );
+    // create inverters for the CIs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) )
+            pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy );
+    // duplicate the nodes, create node functions, and inverters
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        Abc_NtkDupObj( pNtkNew, pObj, 0 );
+        pObj->pCopy->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, 2, NULL );
+        if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) )
+            pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy );
+    }
+    // connect the objects
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+        {
+            if ( Abc_ObjFaninC( pObj, k ) )
+                Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy );
+            else
+                Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+        }
+    Vec_PtrFree( vNodes );
+    // connect the COs
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        pFanin = Abc_ObjFanin0(pObj);
+        if ( Abc_ObjFaninC0( pObj ) )
+            Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy );
+        else
+            Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+    }
+    // fix the problem with complemented and duplicated CO edges
+    Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+    // duplicate the EXDC Ntk
+    if ( pNtk->pExdc )
+        printf( "Warning: The EXDc network is skipped.\n" );
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkAigToLogicSopBench(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the AIG into the logic network with SOPs for bench writing.]
+
+  Description [This procedure does not copy the choices.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkAigToLogicSopNand( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pObj, * pFanin;
+    Vec_Ptr_t * vNodes;
+    int i, k;
+    assert( Abc_NtkIsStrash(pNtk) );
+    if ( Abc_NtkGetChoiceNum(pNtk) )
+        printf( "Warning: Choice nodes are skipped.\n" );
+    // convert complemented edges
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            if ( Abc_ObjIsNode(pFanin) )
+                Abc_ObjXorFaninC( pObj, k );
+    // start the network
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+    // collect the nodes to be used (marks all nodes with current TravId)
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    // create inverters for the constant node
+    pObj = Abc_AigConst1(pNtk);
+    if ( Abc_ObjFanoutNum(pObj) > 0 )
+        pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew);
+    if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) )
+        pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy );
+    // create inverters for the CIs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) )
+            pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy );
+    // duplicate the nodes, create node functions, and inverters
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        Abc_NtkDupObj( pNtkNew, pObj, 0 );
+        pObj->pCopy->pData = Abc_SopCreateNand( (Mem_Flex_t *)pNtkNew->pManFunc, 2 );
+        if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) )
+            pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy );
+    }
+    // connect the objects
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+        {
+            if ( Abc_ObjFaninC( pObj, k ) )
+                Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy );
+            else
+                Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+        }
+    Vec_PtrFree( vNodes );
+    // connect the COs
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        pFanin = Abc_ObjFanin0(pObj);
+        if ( Abc_ObjFaninC0( pObj ) )
+            Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy );
+        else
+            Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+    }
+    // fix the problem with complemented and duplicated CO edges
+    Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+    // convert complemented edges
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            if ( Abc_ObjIsNode(pFanin) )
+                Abc_ObjXorFaninC( pObj, k );
+    // duplicate the EXDC Ntk
+    if ( pNtk->pExdc )
+        printf( "Warning: The EXDc network is skipped.\n" );
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkAigToLogicSopBench(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds buffers for each PO.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkAddPoBuffers( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj, * pFanin, * pFaninNew;
+    int i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+    {
+        pFanin = Abc_ObjChild0(pObj);
+        pFaninNew = Abc_NtkCreateNode(pNtk);
+        Abc_ObjAddFanin( pFaninNew, pFanin );
+        Abc_ObjPatchFanin( pObj, pFanin, pFaninNew );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcNtk.c b/abc-build/src/base/abc/abcNtk.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcNtk.c
@@ -0,0 +1,2119 @@
+/**CFile****************************************************************
+
+  FileName    [abcNtk.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Network creation/duplication/deletion procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcNtk.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "abcInt.h"
+#include "base/main/main.h"
+#include "map/mio/mio.h"
+#include "aig/gia/gia.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new Ntk.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan )
+{
+    Abc_Ntk_t * pNtk;
+    pNtk = ABC_ALLOC( Abc_Ntk_t, 1 );
+    memset( pNtk, 0, sizeof(Abc_Ntk_t) );
+    pNtk->ntkType     = Type;
+    pNtk->ntkFunc     = Func;
+    // start the object storage
+    pNtk->vObjs       = Vec_PtrAlloc( 100 );
+    pNtk->vPios       = Vec_PtrAlloc( 100 );
+    pNtk->vPis        = Vec_PtrAlloc( 100 );
+    pNtk->vPos        = Vec_PtrAlloc( 100 );
+    pNtk->vCis        = Vec_PtrAlloc( 100 );
+    pNtk->vCos        = Vec_PtrAlloc( 100 );
+    pNtk->vBoxes      = Vec_PtrAlloc( 100 );
+	pNtk->vLtlProperties = Vec_PtrAlloc( 100 );
+    // start the memory managers
+    pNtk->pMmObj      = fUseMemMan? Mem_FixedStart( sizeof(Abc_Obj_t) ) : NULL;
+    pNtk->pMmStep     = fUseMemMan? Mem_StepStart( ABC_NUM_STEPS ) : NULL;
+    // get ready to assign the first Obj ID
+    pNtk->nTravIds    = 1;
+    // start the functionality manager
+    if ( !Abc_NtkIsStrash(pNtk) )
+        Vec_PtrPush( pNtk->vObjs, NULL );
+    if ( Abc_NtkIsStrash(pNtk) )
+        pNtk->pManFunc = Abc_AigAlloc( pNtk );
+    else if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) )
+        pNtk->pManFunc = Mem_FlexStart();
+    else if ( Abc_NtkHasBdd(pNtk) )
+        pNtk->pManFunc = Cudd_Init( 20, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    else if ( Abc_NtkHasAig(pNtk) )
+        pNtk->pManFunc = Hop_ManStart();
+    else if ( Abc_NtkHasMapping(pNtk) )
+        pNtk->pManFunc = Abc_FrameReadLibGen();
+    else if ( !Abc_NtkHasBlackbox(pNtk) )
+        assert( 0 );
+    // name manager
+    pNtk->pManName = Nm_ManCreate( 200 );
+    // attribute manager
+    pNtk->vAttrs = Vec_PtrStart( VEC_ATTR_TOTAL_NUM );
+    // estimated AndGateDelay
+    pNtk->AndGateDelay = 0.0;
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts a new network using existing network as a model.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func )
+{
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pObj;
+    int fCopyNames, i;
+    if ( pNtk == NULL )
+        return NULL;
+    // decide whether to copy the names
+    fCopyNames = ( Type != ABC_NTK_NETLIST );
+    // start the network
+    pNtkNew = Abc_NtkAlloc( Type, Func, 1 );
+    pNtkNew->nConstrs   = pNtk->nConstrs;
+    pNtkNew->nBarBufs   = pNtk->nBarBufs;
+    // duplicate the name and the spec
+    pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+    pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+    // clean the node copy fields
+    Abc_NtkCleanCopy( pNtk );
+    // map the constant nodes
+    if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) )
+        Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+    // clone CIs/CIs/boxes
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        Abc_NtkDupObj( pNtkNew, pObj, fCopyNames );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        Abc_NtkDupObj( pNtkNew, pObj, fCopyNames );
+    Abc_NtkForEachBox( pNtk, pObj, i )
+        Abc_NtkDupBox( pNtkNew, pObj, fCopyNames );
+    // transfer logic level
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->pCopy->Level = pObj->Level;
+    // transfer the names
+//    Abc_NtkTrasferNames( pNtk, pNtkNew );
+    Abc_ManTimeDup( pNtk, pNtkNew );
+    if ( pNtk->vOnehots )
+        pNtkNew->vOnehots = (Vec_Ptr_t *)Vec_VecDupInt( (Vec_Vec_t *)pNtk->vOnehots );
+    if ( pNtk->pSeqModel )
+        pNtkNew->pSeqModel = Abc_CexDup( pNtk->pSeqModel, Abc_NtkLatchNum(pNtk) );
+    if ( pNtk->vObjPerm )
+        pNtkNew->vObjPerm = Vec_IntDup( pNtk->vObjPerm );
+    pNtkNew->AndGateDelay = pNtk->AndGateDelay;
+    // initialize logic level of the CIs
+    if ( pNtk->AndGateDelay != 0.0 && pNtk->pManTime != NULL && pNtk->ntkType != ABC_NTK_STRASH && Type == ABC_NTK_STRASH )
+    {
+        Abc_NtkForEachCi( pNtk, pObj, i )
+            pObj->pCopy->Level = (int)(Abc_NodeReadArrivalAve(pObj) / pNtk->AndGateDelay);
+    }
+    // check that the CI/CO/latches are copied correctly
+    assert( Abc_NtkCiNum(pNtk)    == Abc_NtkCiNum(pNtkNew) );
+    assert( Abc_NtkCoNum(pNtk)    == Abc_NtkCoNum(pNtkNew) );
+    assert( Abc_NtkLatchNum(pNtk) == Abc_NtkLatchNum(pNtkNew) );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts a new network using existing network as a model.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkStartFromWithLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func, int nLatches )
+{
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pObj, * pNode0, * pNode1;
+    int fCopyNames, i;
+    if ( pNtk == NULL )
+        return NULL;
+    assert( Abc_NtkLatchNum(pNtk) == 0 );
+    // decide whether to copy the names
+    fCopyNames = ( Type != ABC_NTK_NETLIST );
+    // start the network
+    pNtkNew = Abc_NtkAlloc( Type, Func, 1 );
+    pNtkNew->nConstrs   = pNtk->nConstrs;
+    pNtkNew->nBarBufs   = pNtk->nBarBufs;
+    // duplicate the name and the spec
+    pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+    pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+    // clean the node copy fields
+    Abc_NtkCleanCopy( pNtk );
+    // map the constant nodes
+    if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) )
+        Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+    // clone CIs/CIs/boxes
+    for ( i = 0; i < Abc_NtkPiNum(pNtk)-nLatches; i++ )
+        Abc_NtkDupObj( pNtkNew, Abc_NtkPi(pNtk, i), fCopyNames );
+    for ( i = 0; i < Abc_NtkPoNum(pNtk)-nLatches; i++ )
+        Abc_NtkDupObj( pNtkNew, Abc_NtkPo(pNtk, i), fCopyNames );
+    for ( i = 0; i < nLatches; i++ )
+    {
+        pObj = Abc_NtkCreateLatch(pNtkNew);
+        Abc_LatchSetInit0( pObj );
+        pNode0 = Abc_NtkCreateBi(pNtkNew);
+        Abc_NtkPo(pNtk, Abc_NtkPoNum(pNtk)-nLatches+i)->pCopy = pNode0;
+        pNode1 = Abc_NtkCreateBo(pNtkNew);
+        Abc_NtkPi(pNtk, Abc_NtkPiNum(pNtk)-nLatches+i)->pCopy = pNode1;
+        Abc_ObjAddFanin( pObj, pNode0 );
+        Abc_ObjAddFanin( pNode1, pObj );
+        Abc_ObjAssignName( pNode0, Abc_ObjName(pNode0), NULL );
+        Abc_ObjAssignName( pNode1, Abc_ObjName(pNode1), NULL );
+    }
+    // transfer logic level
+//    Abc_NtkForEachCi( pNtk, pObj, i )
+//        pObj->pCopy->Level = pObj->Level;
+    // transfer the names
+//    Abc_NtkTrasferNames( pNtk, pNtkNew );
+    Abc_ManTimeDup( pNtk, pNtkNew );
+    if ( pNtk->vOnehots )
+        pNtkNew->vOnehots = (Vec_Ptr_t *)Vec_VecDupInt( (Vec_Vec_t *)pNtk->vOnehots );
+    if ( pNtk->pSeqModel )
+        pNtkNew->pSeqModel = Abc_CexDup( pNtk->pSeqModel, Abc_NtkLatchNum(pNtk) );
+    if ( pNtk->vObjPerm )
+        pNtkNew->vObjPerm = Vec_IntDup( pNtk->vObjPerm );
+    pNtkNew->AndGateDelay = pNtk->AndGateDelay;
+    // initialize logic level of the CIs
+    if ( pNtk->AndGateDelay != 0.0 && pNtk->pManTime != NULL && pNtk->ntkType != ABC_NTK_STRASH && Type == ABC_NTK_STRASH )
+    {
+        Abc_NtkForEachCi( pNtk, pObj, i )
+            pObj->pCopy->Level = (int)(Abc_NodeReadArrivalAve(pObj) / pNtk->AndGateDelay);
+    }
+    // check that the CI/CO/latches are copied correctly
+    assert( Abc_NtkCiNum(pNtk)    == Abc_NtkCiNum(pNtkNew) );
+    assert( Abc_NtkCoNum(pNtk)    == Abc_NtkCoNum(pNtkNew) );
+    assert( nLatches              == Abc_NtkLatchNum(pNtkNew) );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts a new network using existing network as a model.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func )
+{
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pObj;
+    int i;
+    if ( pNtk == NULL )
+        return NULL;
+    assert( Type != ABC_NTK_NETLIST );
+    // start the network
+    pNtkNew = Abc_NtkAlloc( Type, Func, 1 );
+    pNtkNew->nConstrs   = pNtk->nConstrs;
+    pNtkNew->nBarBufs   = pNtk->nBarBufs;
+    // duplicate the name and the spec
+    pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+    pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+    // clean the node copy fields
+    Abc_NtkCleanCopy( pNtk );
+    // map the constant nodes
+    if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) )
+        Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+    // clone CIs/CIs/boxes
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        Abc_NtkDupObj( pNtkNew, pObj, 1 );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        Abc_NtkDupObj( pNtkNew, pObj, 1 );
+    Abc_NtkForEachBox( pNtk, pObj, i )
+    {
+        if ( Abc_ObjIsLatch(pObj) )
+            continue;
+        Abc_NtkDupBox(pNtkNew, pObj, 1);
+    }
+    if ( pNtk->vObjPerm )
+        pNtkNew->vObjPerm = Vec_IntDup( pNtk->vObjPerm );
+    pNtkNew->AndGateDelay = pNtk->AndGateDelay;
+    // transfer the names
+//    Abc_NtkTrasferNamesNoLatches( pNtk, pNtkNew );
+    Abc_ManTimeDup( pNtk, pNtkNew );
+    // check that the CI/CO/latches are copied correctly
+    assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) );
+    assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finalizes the network using the existing network as a model.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
+{
+    Abc_Obj_t * pObj, * pDriver, * pDriverNew;
+    int i;
+    // set the COs of the strashed network
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        pDriver    = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pObj) );
+        pDriverNew = Abc_ObjNotCond(pDriver->pCopy, Abc_ObjFaninC0(pObj));
+        Abc_ObjAddFanin( pObj->pCopy, pDriverNew );
+    }
+    // duplicate timing manager
+    if ( pNtk->pManTime )
+        Abc_NtkTimeInitialize( pNtkNew, pNtk );
+    if ( pNtk->vPhases )
+        Abc_NtkTransferPhases( pNtkNew, pNtk );
+    if ( pNtk->pWLoadUsed )
+        pNtkNew->pWLoadUsed = Abc_UtilStrsav( pNtk->pWLoadUsed );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts a new network using existing network as a model.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkStartRead( char * pName )
+{
+    Abc_Ntk_t * pNtkNew; 
+    // allocate the empty network
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 );
+    // set the specs
+    pNtkNew->pName = Extra_FileNameGeneric(pName);
+    pNtkNew->pSpec = Extra_UtilStrsav(pName);
+    if ( pNtkNew->pName == NULL || strlen(pNtkNew->pName) == 0 )
+    {
+        ABC_FREE( pNtkNew->pName );
+        pNtkNew->pName = Extra_UtilStrsav("unknown");
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finalizes the network using the existing network as a model.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pBox, * pObj, * pTerm, * pNet;
+    int i;
+    if ( Abc_NtkHasBlackbox(pNtk) && Abc_NtkBoxNum(pNtk) == 0 )
+    {
+        pBox = Abc_NtkCreateBlackbox(pNtk);
+        Abc_NtkForEachPi( pNtk, pObj, i )
+        {
+            pTerm = Abc_NtkCreateBi(pNtk);
+            Abc_ObjAddFanin( pTerm, Abc_ObjFanout0(pObj) );
+            Abc_ObjAddFanin( pBox, pTerm );
+        }
+        Abc_NtkForEachPo( pNtk, pObj, i )
+        {
+            pTerm = Abc_NtkCreateBo(pNtk);
+            Abc_ObjAddFanin( pTerm, pBox );
+            Abc_ObjAddFanin( Abc_ObjFanin0(pObj), pTerm );
+        }
+        return;
+    }
+    assert( Abc_NtkIsNetlist(pNtk) );
+
+    // check if constant 0 net is used
+    pNet = Abc_NtkFindNet( pNtk, "1\'b0" );
+    if ( pNet )
+    {
+        if ( Abc_ObjFanoutNum(pNet) == 0 )
+            Abc_NtkDeleteObj(pNet);
+        else if ( Abc_ObjFaninNum(pNet) == 0 )
+            Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(pNtk) );
+    }
+    // check if constant 1 net is used
+    pNet = Abc_NtkFindNet( pNtk, "1\'b1" );
+    if ( pNet )
+    {
+        if ( Abc_ObjFanoutNum(pNet) == 0 )
+            Abc_NtkDeleteObj(pNet);
+        else if ( Abc_ObjFaninNum(pNet) == 0 )
+            Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst1(pNtk) );
+    }
+    // fix the net drivers
+    Abc_NtkFixNonDrivenNets( pNtk );
+
+    // reorder the CI/COs to PI/POs first
+    Abc_NtkOrderCisCos( pNtk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicate the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k;
+    if ( pNtk == NULL )
+        return NULL;
+    // start the network
+    pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc );
+    // copy the internal nodes
+    if ( Abc_NtkIsStrash(pNtk) )
+    {
+        // copy the AND gates
+        Abc_AigForEachAnd( pNtk, pObj, i )
+            pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+        // relink the choice nodes
+        Abc_AigForEachAnd( pNtk, pObj, i )
+            if ( pObj->pData )
+                pObj->pCopy->pData = ((Abc_Obj_t *)pObj->pData)->pCopy;
+        // relink the CO nodes
+        Abc_NtkForEachCo( pNtk, pObj, i )
+            Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
+        // get the number of nodes before and after
+        if ( Abc_NtkNodeNum(pNtk) != Abc_NtkNodeNum(pNtkNew) )
+            printf( "Warning: Structural hashing during duplication reduced %d nodes (this is a minor bug).\n",
+                Abc_NtkNodeNum(pNtk) - Abc_NtkNodeNum(pNtkNew) );
+    }
+    else
+    {
+        // duplicate the nets and nodes (CIs/COs/latches already dupped)
+        Abc_NtkForEachObj( pNtk, pObj, i )
+            if ( pObj->pCopy == NULL )
+                Abc_NtkDupObj(pNtkNew, pObj, Abc_NtkHasBlackbox(pNtk) && Abc_ObjIsNet(pObj));
+        // reconnect all objects (no need to transfer attributes on edges)
+        Abc_NtkForEachObj( pNtk, pObj, i )
+            if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) )
+                Abc_ObjForEachFanin( pObj, pFanin, k )
+                    Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+    }
+    // duplicate the EXDC Ntk
+    if ( pNtk->pExdc )
+        pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+    if ( pNtk->pExcare )
+        pNtkNew->pExcare = Abc_NtkDup( (Abc_Ntk_t *)pNtk->pExcare );
+    // duplicate timing manager
+    if ( pNtk->pManTime )
+        Abc_NtkTimeInitialize( pNtkNew, pNtk );
+    if ( pNtk->vPhases )
+        Abc_NtkTransferPhases( pNtkNew, pNtk );
+    if ( pNtk->pWLoadUsed )
+        pNtkNew->pWLoadUsed = Abc_UtilStrsav( pNtk->pWLoadUsed );
+    // check correctness
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" );
+    pNtk->pCopy = pNtkNew;
+    return pNtkNew;
+}
+Abc_Ntk_t * Abc_NtkDupDfs( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k;
+    if ( pNtk == NULL )
+        return NULL;
+    assert( !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsNetlist(pNtk) );
+    // start the network
+    pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc );
+    // copy the internal nodes
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        Abc_NtkDupObj( pNtkNew, pObj, 0 );
+    Vec_PtrFree( vNodes );
+    // reconnect all objects (no need to transfer attributes on edges)
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) )
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                if ( pObj->pCopy && pFanin->pCopy )
+                    Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+    // duplicate the EXDC Ntk
+    if ( pNtk->pExdc )
+        pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+    if ( pNtk->pExcare )
+        pNtkNew->pExcare = Abc_NtkDup( (Abc_Ntk_t *)pNtk->pExcare );
+    // duplicate timing manager
+    if ( pNtk->pManTime )
+        Abc_NtkTimeInitialize( pNtkNew, pNtk );
+    if ( pNtk->vPhases )
+        Abc_NtkTransferPhases( pNtkNew, pNtk );
+    if ( pNtk->pWLoadUsed )
+        pNtkNew->pWLoadUsed = Abc_UtilStrsav( pNtk->pWLoadUsed );
+    // check correctness
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" );
+    pNtk->pCopy = pNtkNew;
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicate the AIG while adding latches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRestrashWithLatches( Abc_Ntk_t * pNtk, int nLatches )
+{
+    Abc_Ntk_t * pNtkAig;
+    Abc_Obj_t * pObj;
+    int i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // start the new network (constants and CIs of the old network will point to the their counterparts in the new network)
+    pNtkAig = Abc_NtkStartFromWithLatches( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG, nLatches );
+    // restrash the nodes (assuming a topological order of the old network)
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+    // finalize the network
+    Abc_NtkFinalize( pNtk, pNtkAig );
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pNtkAig ) )
+    {
+        printf( "Abc_NtkStrash: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkAig );
+        return NULL;
+    }
+    return pNtkAig;
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicate the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDupTransformMiter( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObj, * pObj2, * pMiter;
+    int i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // start the network
+    pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+    pNtkNew->nConstrs   = pNtk->nConstrs;
+    pNtkNew->nBarBufs   = pNtk->nBarBufs;
+    // duplicate the name and the spec
+    pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+    pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+    // clean the node copy fields
+    Abc_NtkCleanCopy( pNtk );
+    // map the constant nodes
+     Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+    // clone CIs/CIs/boxes
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        Abc_NtkDupObj( pNtkNew, pObj, 1 );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        Abc_NtkDupObj( pNtkNew, pObj, 1 ), i++;
+    Abc_NtkForEachBox( pNtk, pObj, i )
+        Abc_NtkDupBox( pNtkNew, pObj, 1 );
+    // copy the AND gates
+    Abc_AigForEachAnd( pNtk, pObj, i )
+        pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+    // create new miters
+    Abc_NtkForEachPo( pNtk, pObj, i )
+    {
+        pObj2 = Abc_NtkPo( pNtk, ++i );
+        pMiter = Abc_AigXor( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Copy(pObj2) );
+        Abc_ObjAddFanin( pObj->pCopy, pMiter );
+    }
+    Abc_NtkForEachLatchInput( pNtk, pObj, i )
+        Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
+    // cleanup
+    Abc_AigCleanup( (Abc_Aig_t *)pNtkNew->pManFunc );
+    // check that the CI/CO/latches are copied correctly
+    assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) );
+    assert( Abc_NtkPoNum(pNtk) == 2*Abc_NtkPoNum(pNtkNew) );
+    assert( Abc_NtkLatchNum(pNtk) == Abc_NtkLatchNum(pNtkNew) );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicate the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDouble( Abc_Ntk_t * pNtk )
+{
+    char Buffer[500];
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k;
+    assert( Abc_NtkIsLogic(pNtk) );
+
+    // start the network
+    pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+    sprintf( Buffer, "%s%s", pNtk->pName, "_2x" );
+    pNtkNew->pName = Extra_UtilStrsav(Buffer);
+
+    // clean the node copy fields
+    Abc_NtkCleanCopy( pNtk );
+    // clone CIs/CIs/boxes
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        Abc_NtkDupObj( pNtkNew, pObj, 0 );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        Abc_NtkDupObj( pNtkNew, pObj, 0 );
+    Abc_NtkForEachBox( pNtk, pObj, i )
+        Abc_NtkDupBox( pNtkNew, pObj, 0 );
+    // copy the internal nodes
+    // duplicate the nets and nodes (CIs/COs/latches already dupped)
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( pObj->pCopy == NULL )
+            Abc_NtkDupObj(pNtkNew, pObj, 0);
+    // reconnect all objects (no need to transfer attributes on edges)
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) )
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+
+    // clean the node copy fields
+    Abc_NtkCleanCopy( pNtk );
+    // clone CIs/CIs/boxes
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        Abc_NtkDupObj( pNtkNew, pObj, 0 );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        Abc_NtkDupObj( pNtkNew, pObj, 0 );
+    Abc_NtkForEachBox( pNtk, pObj, i )
+        Abc_NtkDupBox( pNtkNew, pObj, 0 );
+    // copy the internal nodes
+    // duplicate the nets and nodes (CIs/COs/latches already dupped)
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( pObj->pCopy == NULL )
+            Abc_NtkDupObj(pNtkNew, pObj, 0);
+    // reconnect all objects (no need to transfer attributes on edges)
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) )
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+
+    // assign names
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        Abc_ObjAssignName( Abc_NtkCi(pNtkNew,                      i), "1_", Abc_ObjName(pObj) );
+        Abc_ObjAssignName( Abc_NtkCi(pNtkNew, Abc_NtkCiNum(pNtk) + i), "2_", Abc_ObjName(pObj) );
+    }
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        Abc_ObjAssignName( Abc_NtkCo(pNtkNew,                      i), "1_", Abc_ObjName(pObj) );
+        Abc_ObjAssignName( Abc_NtkCo(pNtkNew, Abc_NtkCoNum(pNtk) + i), "2_", Abc_ObjName(pObj) );
+    }
+    Abc_NtkOrderCisCos( pNtkNew );
+
+    // perform the final check
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicate the bottom levels of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkBottom( Abc_Ntk_t * pNtk, int Level )
+{
+    char Buffer[500];
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k;
+    assert( Abc_NtkIsLogic(pNtk) );
+    assert( Abc_NtkLatchNum(pNtk) == 0 );
+
+    // start the network
+    pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+    sprintf( Buffer, "%s%s", pNtk->pName, "_bot" );
+    pNtkNew->pName = Extra_UtilStrsav(Buffer);
+
+    // clean the node copy fields
+    Abc_NtkCleanCopy( pNtk );
+    // clone CIs/CIs/boxes
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        Abc_NtkDupObj( pNtkNew, pObj, 1 );
+
+    // copy the internal nodes
+    // duplicate the nets and nodes (CIs/COs/latches already dupped)
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( pObj->pCopy == NULL && Abc_ObjIsNode(pObj) && Abc_ObjLevel(pObj) <= Level )
+            Abc_NtkDupObj(pNtkNew, pObj, 0);
+    // reconnect all objects (no need to transfer attributes on edges)
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            if ( pObj->pCopy && pFanin->pCopy )
+                Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+
+    // create new primary outputs
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            if ( !pObj->pCopy && pFanin->pCopy && Abc_ObjIsNode(pFanin) )
+            {
+                Abc_Obj_t * pNodeNew = Abc_NtkCreatePo(pNtkNew);
+                Abc_ObjAddFanin( pNodeNew, pFanin->pCopy );
+                Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNodeNew), NULL );
+            }
+
+    // perform the final check
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkBottom(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Attaches the second network at the bottom of the first.]
+
+  Description [Returns the first network. Deletes the second network.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkAttachBottom( Abc_Ntk_t * pNtkTop, Abc_Ntk_t * pNtkBottom )
+{
+    Abc_Obj_t * pObj, * pFanin, * pBuffer;
+    Vec_Ptr_t * vNodes;
+    int i, k;
+    assert( pNtkBottom != NULL );
+    if ( pNtkTop == NULL )
+        return pNtkBottom;
+    // make sure the networks are combinational
+    assert( Abc_NtkPiNum(pNtkTop) == Abc_NtkCiNum(pNtkTop) );
+    assert( Abc_NtkPiNum(pNtkBottom) == Abc_NtkCiNum(pNtkBottom) );
+    // make sure the POs of the bottom correspond to the PIs of the top
+    assert( Abc_NtkPoNum(pNtkBottom) == Abc_NtkPiNum(pNtkTop) );
+    assert( Abc_NtkPiNum(pNtkBottom) <  Abc_NtkPiNum(pNtkTop) );
+    // add buffers for the PIs of the top - save results in the POs of the bottom
+    Abc_NtkForEachPi( pNtkTop, pObj, i )
+    {
+        pBuffer = Abc_NtkCreateNodeBuf( pNtkTop, NULL );
+        Abc_ObjTransferFanout( pObj, pBuffer );
+        Abc_NtkPo(pNtkBottom, i)->pCopy = pBuffer;
+    }
+    // remove useless PIs of the top
+    for ( i = Abc_NtkPiNum(pNtkTop) - 1; i >= Abc_NtkPiNum(pNtkBottom); i-- )
+        Abc_NtkDeleteObj( Abc_NtkPi(pNtkTop, i) );
+    assert( Abc_NtkPiNum(pNtkBottom) == Abc_NtkPiNum(pNtkTop) );
+    // copy the bottom network
+    Abc_NtkForEachPi( pNtkBottom, pObj, i )
+        Abc_NtkPi(pNtkBottom, i)->pCopy = Abc_NtkPi(pNtkTop, i);
+    // construct all nodes
+    vNodes = Abc_NtkDfs( pNtkBottom, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        Abc_NtkDupObj(pNtkTop, pObj, 0);
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+    }
+    Vec_PtrFree( vNodes );
+    // connect the POs
+    Abc_NtkForEachPo( pNtkBottom, pObj, i )
+        Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pObj)->pCopy );
+    // delete old network
+    Abc_NtkDelete( pNtkBottom );
+    // return the network
+    if ( !Abc_NtkCheck( pNtkTop ) )
+        fprintf( stdout, "Abc_NtkAttachBottom(): Network check has failed.\n" );
+    return pNtkTop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the network composed of one logic cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis )
+{
+    Abc_Ntk_t * pNtkNew; 
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj, * pFanin, * pNodeCoNew;
+    char Buffer[1000];
+    int i, k;
+
+    assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
+    assert( Abc_ObjIsNode(pNode) || (Abc_NtkIsStrash(pNtk) && (Abc_AigNodeIsConst(pNode) || Abc_ObjIsCi(pNode)))  ); 
+    
+    // start the network
+    pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+    // set the name
+    sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName );
+    pNtkNew->pName = Extra_UtilStrsav(Buffer);
+
+    // establish connection between the constant nodes
+    if ( Abc_NtkIsStrash(pNtk) )
+        Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+
+    // collect the nodes in the TFI of the output (mark the TFI)
+    vNodes = Abc_NtkDfsNodes( pNtk, &pNode, 1 );
+    // create the PIs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS
+        {
+            pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+            Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+        }
+    }
+    // add the PO corresponding to this output
+    pNodeCoNew = Abc_NtkCreatePo( pNtkNew );
+    Abc_ObjAssignName( pNodeCoNew, pNodeName, NULL );
+    // copy the nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        // if it is an AIG, add to the hash table
+        if ( Abc_NtkIsStrash(pNtk) )
+        {
+            pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+        }
+        else
+        {
+            Abc_NtkDupObj( pNtkNew, pObj, 0 );
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+        }
+    }
+    // connect the internal nodes to the new CO
+    Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy );
+    Vec_PtrFree( vNodes );
+
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the network composed of several logic cones.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fUseAllCis )
+{
+    Abc_Ntk_t * pNtkNew; 
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj, * pFanin, * pNodeCoNew;
+    char Buffer[1000];
+    int i, k;
+
+    assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
+    
+    // start the network
+    pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+    // set the name
+    sprintf( Buffer, "%s_part", pNtk->pName );
+    pNtkNew->pName = Extra_UtilStrsav(Buffer);
+
+    // establish connection between the constant nodes
+    if ( Abc_NtkIsStrash(pNtk) )
+        Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+
+    // collect the nodes in the TFI of the output (mark the TFI)
+    vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) );
+
+    // create the PIs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS
+        {
+            pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+            Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+        }
+    }
+
+    // copy the nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        // if it is an AIG, add to the hash table
+        if ( Abc_NtkIsStrash(pNtk) )
+        {
+            pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+        }
+        else
+        {
+            Abc_NtkDupObj( pNtkNew, pObj, 0 );
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+        }
+    }
+    Vec_PtrFree( vNodes );
+
+    // add the POs corresponding to the root nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+    {
+        // create the PO node
+        pNodeCoNew = Abc_NtkCreatePo( pNtkNew );
+        // connect the internal nodes to the new CO
+        if ( Abc_ObjIsCo(pObj) )
+            Abc_ObjAddFanin( pNodeCoNew, Abc_ObjChild0Copy(pObj) );
+        else
+            Abc_ObjAddFanin( pNodeCoNew, pObj->pCopy );
+        // assign the name
+        Abc_ObjAssignName( pNodeCoNew, Abc_ObjName(pObj), NULL );
+    }
+
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkCreateConeArray(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds new nodes to the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkAppendToCone( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj;
+    int i, iNodeId;
+
+    assert( Abc_NtkIsStrash(pNtkNew) );
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    // collect the nodes in the TFI of the output (mark the TFI)
+    vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) );
+
+    // establish connection between the constant nodes
+    Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+
+    // create the PIs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        // skip CIs that are not used
+        if ( !Abc_NodeIsTravIdCurrent(pObj) )
+            continue;
+        // find the corresponding CI in the new network
+        iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO );
+        if ( iNodeId == -1 )
+        {
+            pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+            Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+        }
+        else
+            pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId );
+    }
+
+    // copy the nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+    Vec_PtrFree( vNodes );
+
+    // do not add the COs
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkAppendToCone(): Network check has failed.\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the network composed of MFFC of one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName )
+{
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pObj, * pFanin, * pNodeCoNew;
+    Vec_Ptr_t * vCone, * vSupp;
+    char Buffer[1000];
+    int i, k;
+
+    assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
+    assert( Abc_ObjIsNode(pNode) ); 
+    
+    // start the network
+    pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+    // set the name
+    sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName );
+    pNtkNew->pName = Extra_UtilStrsav(Buffer);
+
+    // establish connection between the constant nodes
+    if ( Abc_NtkIsStrash(pNtk) )
+        Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+
+    // collect the nodes in MFFC
+    vCone = Vec_PtrAlloc( 100 );
+    vSupp = Vec_PtrAlloc( 100 );
+    Abc_NodeDeref_rec( pNode );
+    Abc_NodeMffcConeSupp( pNode, vCone, vSupp );
+    Abc_NodeRef_rec( pNode );
+    // create the PIs
+    Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i )
+    {
+        pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+        Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+    }
+    // create the PO
+    pNodeCoNew = Abc_NtkCreatePo( pNtkNew );
+    Abc_ObjAssignName( pNodeCoNew, pNodeName, NULL );
+    // copy the nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, i )
+    {
+        // if it is an AIG, add to the hash table
+        if ( Abc_NtkIsStrash(pNtk) )
+        {
+            pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+        }
+        else
+        {
+            Abc_NtkDupObj( pNtkNew, pObj, 0 );
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+        }
+    }
+    // connect the topmost node
+    Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy );
+    Vec_PtrFree( vCone );
+    Vec_PtrFree( vSupp );
+
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkCreateMffc(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the miter composed of one multi-output cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pObj, * pFinal, * pOther, * pNodePo;
+    int i;
+
+    assert( Abc_NtkIsLogic(pNtk) );
+    
+    // start the network
+    Abc_NtkCleanCopy( pNtk );
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+
+    // collect the nodes in the TFI of the output
+    vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)vRoots->pArray, vRoots->nSize );
+    // create the PIs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+        Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+    }
+    // copy the nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        pObj->pCopy = Abc_NodeStrash( pNtkNew, pObj, 0 );
+    Vec_PtrFree( vNodes );
+
+    // add the PO
+    pFinal = Abc_AigConst1( pNtkNew );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+    {
+        if ( Abc_ObjIsCo(pObj) )
+            pOther = Abc_ObjFanin0(pObj)->pCopy;
+        else
+            pOther = pObj->pCopy;
+        if ( Vec_IntEntry(vValues, i) == 0 )
+            pOther = Abc_ObjNot(pOther);
+        pFinal = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pFinal, pOther );
+    }
+
+    // add the PO corresponding to this output
+    pNodePo = Abc_NtkCreatePo( pNtkNew );
+    Abc_ObjAddFanin( pNodePo, pFinal );
+    Abc_ObjAssignName( pNodePo, "miter", NULL );
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkCreateTarget(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the network composed of one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode )
+{    
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pFanin, * pNodePo;
+    int i;
+    // start the network
+    pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+    pNtkNew->pName = Extra_UtilStrsav(Abc_ObjName(pNode));
+    // add the PIs corresponding to the fanins of the node
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        pFanin->pCopy = Abc_NtkCreatePi( pNtkNew );
+        Abc_ObjAssignName( pFanin->pCopy, Abc_ObjName(pFanin), NULL );
+    }
+    // duplicate and connect the node
+    pNode->pCopy = Abc_NtkDupObj( pNtkNew, pNode, 0 );
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        Abc_ObjAddFanin( pNode->pCopy, pFanin->pCopy );
+    // create the only PO
+    pNodePo = Abc_NtkCreatePo( pNtkNew );
+    Abc_ObjAddFanin( pNodePo, pNode->pCopy );
+    Abc_ObjAssignName( pNodePo, Abc_ObjName(pNode), NULL );
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkCreateFromNode(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the network composed of one node with the given SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop )
+{    
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pFanin, * pNode, * pNodePo;
+    Vec_Ptr_t * vNames;
+    int i, nVars;
+    // start the network
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+    pNtkNew->pName = Extra_UtilStrsav("ex");
+    // create PIs
+    Vec_PtrPush( pNtkNew->vObjs, NULL );
+    nVars = Abc_SopGetVarNum( pSop );
+    vNames = Abc_NodeGetFakeNames( nVars );
+    for ( i = 0; i < nVars; i++ )
+        Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), (char *)Vec_PtrEntry(vNames, i), NULL );
+    Abc_NodeFreeNames( vNames );
+    // create the node, add PIs as fanins, set the function
+    pNode = Abc_NtkCreateNode( pNtkNew );
+    Abc_NtkForEachPi( pNtkNew, pFanin, i )
+        Abc_ObjAddFanin( pNode, pFanin );
+    pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, pSop );
+    // create the only PO
+    pNodePo = Abc_NtkCreatePo(pNtkNew);
+    Abc_ObjAddFanin( pNodePo, pNode );
+    Abc_ObjAssignName( pNodePo, "F", NULL );
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkCreateWithNode(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the Ntk.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDelete( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    void * pAttrMan;
+    int TotalMemory, i;
+//    int LargePiece = (4 << ABC_NUM_STEPS);
+    if ( pNtk == NULL )
+        return;
+    // free EXDC Ntk
+    if ( pNtk->pExdc )
+        Abc_NtkDelete( pNtk->pExdc );
+    if ( pNtk->pExcare )
+        Abc_NtkDelete( (Abc_Ntk_t *)pNtk->pExcare );
+    // dereference the BDDs
+    if ( Abc_NtkHasBdd(pNtk) )
+    {
+        Abc_NtkForEachNode( pNtk, pObj, i )
+            Cudd_RecursiveDeref( (DdManager *)pNtk->pManFunc, (DdNode *)pObj->pData );
+    }
+    // make sure all the marks are clean
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        // free large fanout arrays
+//        if ( pNtk->pMmObj && pObj->vFanouts.nCap * 4 > LargePiece )
+//            ABC_FREE( pObj->vFanouts.pArray );
+        // these flags should be always zero
+        // if this is not true, something is wrong somewhere
+        assert( pObj->fMarkA == 0 );
+        assert( pObj->fMarkB == 0 );
+        assert( pObj->fMarkC == 0 );
+    }
+    // free the nodes
+    if ( pNtk->pMmStep == NULL )
+    {
+        Abc_NtkForEachObj( pNtk, pObj, i )
+        {
+            ABC_FREE( pObj->vFanouts.pArray );
+            ABC_FREE( pObj->vFanins.pArray );
+        }
+    }
+    if ( pNtk->pMmObj == NULL )
+    {
+        Abc_NtkForEachObj( pNtk, pObj, i )
+            ABC_FREE( pObj );
+    }
+        
+    // free the arrays
+    Vec_PtrFree( pNtk->vPios );
+    Vec_PtrFree( pNtk->vPis );
+    Vec_PtrFree( pNtk->vPos );
+    Vec_PtrFree( pNtk->vCis );
+    Vec_PtrFree( pNtk->vCos );
+    Vec_PtrFree( pNtk->vObjs );
+    Vec_PtrFree( pNtk->vBoxes );
+    ABC_FREE( pNtk->vTravIds.pArray );
+    if ( pNtk->vLevelsR ) Vec_IntFree( pNtk->vLevelsR );
+    ABC_FREE( pNtk->pModel );
+    ABC_FREE( pNtk->pSeqModel );
+    if ( pNtk->vSeqModelVec )
+        Vec_PtrFreeFree( pNtk->vSeqModelVec );
+    TotalMemory  = 0;
+    TotalMemory += pNtk->pMmObj? Mem_FixedReadMemUsage(pNtk->pMmObj)  : 0;
+    TotalMemory += pNtk->pMmStep? Mem_StepReadMemUsage(pNtk->pMmStep) : 0;
+//    fprintf( stdout, "The total memory allocated internally by the network = %0.2f MB.\n", ((double)TotalMemory)/(1<<20) );
+    // free the storage 
+    if ( pNtk->pMmObj )
+        Mem_FixedStop( pNtk->pMmObj, 0 );
+    if ( pNtk->pMmStep )
+        Mem_StepStop ( pNtk->pMmStep, 0 );
+    // name manager
+    Nm_ManFree( pNtk->pManName );
+    // free the timing manager
+    if ( pNtk->pManTime )
+        Abc_ManTimeStop( pNtk->pManTime );
+    Vec_IntFreeP( &pNtk->vPhases );
+    // start the functionality manager
+    if ( Abc_NtkIsStrash(pNtk) )
+        Abc_AigFree( (Abc_Aig_t *)pNtk->pManFunc );
+    else if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) )
+        Mem_FlexStop( (Mem_Flex_t *)pNtk->pManFunc, 0 );
+    else if ( Abc_NtkHasBdd(pNtk) )
+        Extra_StopManager( (DdManager *)pNtk->pManFunc );
+    else if ( Abc_NtkHasAig(pNtk) )
+        { if ( pNtk->pManFunc ) Hop_ManStop( (Hop_Man_t *)pNtk->pManFunc ); }
+    else if ( Abc_NtkHasMapping(pNtk) )
+        pNtk->pManFunc = NULL;
+    else if ( !Abc_NtkHasBlackbox(pNtk) )
+        assert( 0 );
+    // free the hierarchy
+    if ( pNtk->pDesign )
+    {
+        Abc_DesFree( pNtk->pDesign, pNtk );
+        pNtk->pDesign = NULL;
+    }
+//    if ( pNtk->pBlackBoxes ) 
+//        Vec_IntFree( pNtk->pBlackBoxes );
+    // free node attributes
+    Vec_PtrForEachEntry( Abc_Obj_t *, pNtk->vAttrs, pAttrMan, i )
+        if ( pAttrMan )
+            Vec_AttFree( (Vec_Att_t *)pAttrMan, 1 );
+    assert( pNtk->pSCLib == NULL );
+    Vec_IntFreeP( &pNtk->vGates );
+    Vec_PtrFree( pNtk->vAttrs );
+    Vec_IntFreeP( &pNtk->vNameIds );
+    ABC_FREE( pNtk->pWLoadUsed );
+    ABC_FREE( pNtk->pName );
+    ABC_FREE( pNtk->pSpec );
+    ABC_FREE( pNtk->pLutTimes );
+    if ( pNtk->vOnehots )
+        Vec_VecFree( (Vec_Vec_t *)pNtk->vOnehots );
+    Vec_PtrFreeP( &pNtk->vLtlProperties );
+    Vec_IntFreeP( &pNtk->vObjPerm );
+    Vec_IntFreeP( &pNtk->vTopo );
+    ABC_FREE( pNtk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the verilog file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk )
+{ 
+    Vec_Ptr_t * vNets;
+    Abc_Obj_t * pNet, * pNode;
+    int i;
+
+    if ( Abc_NtkNodeNum(pNtk) == 0 && Abc_NtkBoxNum(pNtk) == 0 )
+        return;
+
+    // special case
+    pNet = Abc_NtkFindNet( pNtk, "[_c1_]" );
+    if ( pNet != NULL )
+    {
+        pNode = Abc_NtkCreateNodeConst1( pNtk );
+        Abc_ObjAddFanin( pNet, pNode );
+    }
+
+    // check for non-driven nets
+    vNets = Vec_PtrAlloc( 100 );
+    Abc_NtkForEachNet( pNtk, pNet, i )
+    {
+        if ( Abc_ObjFaninNum(pNet) > 0 )
+            continue;
+        // add the constant 0 driver
+        pNode = Abc_NtkCreateNodeConst0( pNtk );
+        // add the fanout net
+        Abc_ObjAddFanin( pNet, pNode );
+        // add the net to those for which the warning will be printed
+        Vec_PtrPush( vNets, pNet );
+    }
+
+    // print the warning
+    if ( vNets->nSize > 0 )
+    {
+        printf( "Warning: Constant-0 drivers added to %d non-driven nets in network \"%s\":\n", Vec_PtrSize(vNets), pNtk->pName );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNets, pNet, i )
+        {
+            printf( "%s%s", (i? ", ": ""), Abc_ObjName(pNet) );
+            if ( i == 3 )
+            {
+                if ( Vec_PtrSize(vNets) > 3 )
+                    printf( " ..." );
+                break;
+            }
+        }
+        printf( "\n" );
+    }
+    Vec_PtrFree( vNets );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network to combinational.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMakeComb( Abc_Ntk_t * pNtk, int fRemoveLatches )
+{
+    Abc_Obj_t * pObj;
+    int i;
+
+    if ( Abc_NtkIsComb(pNtk) )
+        return;
+
+    assert( !Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
+
+    // detach the latches
+//    Abc_NtkForEachLatch( pNtk, pObj, i )
+    Vec_PtrForEachEntryReverse( Abc_Obj_t *, pNtk->vBoxes, pObj, i )
+        Abc_NtkDeleteObj( pObj );
+    assert( Abc_NtkLatchNum(pNtk) == 0 );
+    assert( Abc_NtkBoxNum(pNtk) == 0 );
+
+    // move CIs to become PIs
+    Vec_PtrClear( pNtk->vPis );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        if ( Abc_ObjIsBo(pObj) )
+        {
+            pObj->Type = ABC_OBJ_PI;
+            pNtk->nObjCounts[ABC_OBJ_PI]++;
+            pNtk->nObjCounts[ABC_OBJ_BO]--;
+        }
+        Vec_PtrPush( pNtk->vPis, pObj );
+    }
+    assert( Abc_NtkBoNum(pNtk) == 0 );
+
+    if ( fRemoveLatches )
+    {
+        // remove registers
+        Vec_Ptr_t * vBos;
+        vBos = Vec_PtrAlloc( 100 );
+        Vec_PtrClear( pNtk->vPos );
+        Abc_NtkForEachCo( pNtk, pObj, i )
+            if ( Abc_ObjIsBi(pObj) )
+                Vec_PtrPush( vBos, pObj );
+            else
+                Vec_PtrPush( pNtk->vPos, pObj );
+        // remove COs
+        Vec_PtrFree( pNtk->vCos );
+        pNtk->vCos = NULL;
+        // remove the BOs
+        Vec_PtrForEachEntry( Abc_Obj_t *, vBos, pObj, i )
+            Abc_NtkDeleteObj( pObj );
+        Vec_PtrFree( vBos );
+        // create COs
+        pNtk->vCos = Vec_PtrDup( pNtk->vPos );
+        // cleanup
+        if ( Abc_NtkIsLogic(pNtk) )
+            Abc_NtkCleanup( pNtk, 0 );
+        else if ( Abc_NtkIsStrash(pNtk) )
+            Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc );
+        else
+            assert( 0 );
+    }
+    else
+    {
+        // move COs to become POs
+        Vec_PtrClear( pNtk->vPos );
+        Abc_NtkForEachCo( pNtk, pObj, i )
+        {
+            if ( Abc_ObjIsBi(pObj) )
+            {
+                pObj->Type = ABC_OBJ_PO;
+                pNtk->nObjCounts[ABC_OBJ_PO]++;
+                pNtk->nObjCounts[ABC_OBJ_BI]--;
+            }
+            Vec_PtrPush( pNtk->vPos, pObj );
+        }
+    }
+    assert( Abc_NtkBiNum(pNtk) == 0 );
+
+    if ( !Abc_NtkCheck( pNtk ) )
+        fprintf( stdout, "Abc_NtkMakeComb(): Network check has failed.\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network to sequential.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMakeSeq( Abc_Ntk_t * pNtk, int nLatchesToAdd )
+{
+    Abc_Obj_t * pObjLi, * pObjLo, * pObj;
+    int i;
+    assert( Abc_NtkBoxNum(pNtk) == 0 );
+    if ( !Abc_NtkIsComb(pNtk) )
+    {
+        printf( "The network is a not a combinational one.\n" );
+        return;
+    }
+    if ( nLatchesToAdd >= Abc_NtkPiNum(pNtk) )
+    {
+        printf( "The number of latches is more or equal than the number of PIs.\n" );
+        return;
+    }
+    if ( nLatchesToAdd >= Abc_NtkPoNum(pNtk) )
+    {
+        printf( "The number of latches is more or equal than the number of POs.\n" );
+        return;
+    }
+
+    // move the last PIs to become CIs
+    Vec_PtrClear( pNtk->vPis );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        if ( i < Abc_NtkCiNum(pNtk) - nLatchesToAdd )
+        {
+            Vec_PtrPush( pNtk->vPis, pObj );
+            continue;
+        }
+        pObj->Type = ABC_OBJ_BO;
+        pNtk->nObjCounts[ABC_OBJ_PI]--;
+        pNtk->nObjCounts[ABC_OBJ_BO]++;
+    }
+
+    // move the last POs to become COs
+    Vec_PtrClear( pNtk->vPos );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        if ( i < Abc_NtkCoNum(pNtk) - nLatchesToAdd )
+        {
+            Vec_PtrPush( pNtk->vPos, pObj );
+            continue;
+        }
+        pObj->Type = ABC_OBJ_BI;
+        pNtk->nObjCounts[ABC_OBJ_PO]--;
+        pNtk->nObjCounts[ABC_OBJ_BI]++;
+    }
+
+    // create latches
+    for ( i = 0; i < nLatchesToAdd; i++ )
+    {
+        pObjLo = Abc_NtkCi( pNtk, Abc_NtkCiNum(pNtk) - nLatchesToAdd + i );
+        pObjLi = Abc_NtkCo( pNtk, Abc_NtkCoNum(pNtk) - nLatchesToAdd + i );
+        pObj = Abc_NtkCreateLatch( pNtk );
+        Abc_ObjAddFanin( pObj, pObjLi );
+        Abc_ObjAddFanin( pObjLo, pObj );
+        Abc_LatchSetInit0( pObj );
+    }
+
+    if ( !Abc_NtkCheck( pNtk ) )
+        fprintf( stdout, "Abc_NtkMakeSeq(): Network check has failed.\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Removes all POs, except one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMakeOnePo( Abc_Ntk_t * pNtkInit, int Output, int nRange )
+{
+    Abc_Ntk_t * pNtk;
+    Vec_Ptr_t * vPosLeft;
+    Vec_Ptr_t * vCosLeft;
+    Abc_Obj_t * pNodePo;
+    int i;
+    assert( !Abc_NtkIsNetlist(pNtkInit) );
+    assert( Abc_NtkHasOnlyLatchBoxes(pNtkInit) );
+    if ( Output < 0 || Output >= Abc_NtkPoNum(pNtkInit) )
+    {
+        printf( "PO index is incorrect.\n" );
+        return NULL;
+    }
+
+    pNtk = Abc_NtkDup( pNtkInit );
+    if ( Abc_NtkPoNum(pNtk) == 1 )
+        return pNtk;
+
+    if ( nRange < 1 )
+        nRange = 1;
+
+    // filter POs
+    vPosLeft = Vec_PtrAlloc( nRange );
+    Abc_NtkForEachPo( pNtk, pNodePo, i )
+        if ( i < Output || i >= Output + nRange )
+            Abc_NtkDeleteObjPo( pNodePo );
+        else
+            Vec_PtrPush( vPosLeft, pNodePo );
+    // filter COs
+    vCosLeft = Vec_PtrDup( vPosLeft );
+    for ( i = Abc_NtkPoNum(pNtk); i < Abc_NtkCoNum(pNtk); i++ )
+        Vec_PtrPush( vCosLeft, Abc_NtkCo(pNtk, i) );
+    // update arrays
+    Vec_PtrFree( pNtk->vPos );  pNtk->vPos = vPosLeft;
+    Vec_PtrFree( pNtk->vCos );  pNtk->vCos = vCosLeft;
+
+    // clean the network
+    if ( Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc );
+        printf( "Run sequential cleanup (\"scl\") to get rid of dangling logic.\n" );
+    }
+    else
+    {
+        printf( "Run sequential cleanup (\"st; scl\") to get rid of dangling logic.\n" );
+    }
+
+    if ( !Abc_NtkCheck( pNtk ) )
+        fprintf( stdout, "Abc_NtkMakeComb(): Network check has failed.\n" );
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes POs with suppsize less than 2 and PIs without fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkTrim( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i, k, m;
+
+    // filter POs
+    k = m = 0;
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {  
+        if ( Abc_ObjIsPo(pObj) )
+        {
+            // remove constant nodes and PI pointers
+            if ( Abc_ObjFaninNum(Abc_ObjFanin0(pObj)) == 0 )
+            {
+                Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) );
+                if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 0 && !Abc_ObjIsPi(Abc_ObjFanin0(pObj)) )
+                    Abc_NtkDeleteObj_rec( Abc_ObjFanin0(pObj), 1 );
+                pNtk->vObjs->pArray[pObj->Id] = NULL;
+                pObj->Id = (1<<26)-1;
+                pNtk->nObjCounts[pObj->Type]--;
+                pNtk->nObjs--;
+                Abc_ObjRecycle( pObj );
+                continue;
+            }
+            // remove buffers/inverters of PIs
+            if ( Abc_ObjFaninNum(Abc_ObjFanin0(pObj)) == 1 )
+            {
+                if ( Abc_ObjIsPi(Abc_ObjFanin0(Abc_ObjFanin0(pObj))) )
+                {
+                    Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) );
+                    if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 0 )
+                        Abc_NtkDeleteObj_rec( Abc_ObjFanin0(pObj), 1 );
+                    pNtk->vObjs->pArray[pObj->Id] = NULL;
+                    pObj->Id = (1<<26)-1;
+                    pNtk->nObjCounts[pObj->Type]--;
+                    pNtk->nObjs--;
+                    Abc_ObjRecycle( pObj );
+                    continue;
+                }
+            }
+            Vec_PtrWriteEntry( pNtk->vPos, m++, pObj );
+        }
+        Vec_PtrWriteEntry( pNtk->vCos, k++, pObj );
+    }
+    Vec_PtrShrink( pNtk->vPos, m );
+    Vec_PtrShrink( pNtk->vCos, k );
+
+    // filter PIs
+    k = m = 0;
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        if ( Abc_ObjIsPi(pObj) )
+        {
+            if ( Abc_ObjFanoutNum(pObj) == 0 )
+            {
+                pNtk->vObjs->pArray[pObj->Id] = NULL;
+                pObj->Id = (1<<26)-1;
+                pNtk->nObjCounts[pObj->Type]--;
+                pNtk->nObjs--;
+                Abc_ObjRecycle( pObj );
+                continue;
+            }
+            Vec_PtrWriteEntry( pNtk->vPis, m++, pObj );
+        }
+        Vec_PtrWriteEntry( pNtk->vCis, k++, pObj );
+    }
+    Vec_PtrShrink( pNtk->vPis, m );
+    Vec_PtrShrink( pNtk->vCis, k );
+
+    return Abc_NtkDup( pNtk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDropSatOutputs( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCexes, int fVerbose )
+{
+    Abc_Obj_t * pObj, * pConst0, * pFaninNew;
+    int i, Counter = 0;
+    assert( Vec_PtrSize(vCexes) == Abc_NtkPoNum(pNtk) );
+    pConst0 = Abc_ObjNot( Abc_AigConst1(pNtk) );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+    {
+        if ( Vec_PtrEntry( vCexes, i ) == NULL )
+            continue;
+        Counter++;
+        pFaninNew = Abc_ObjNotCond( pConst0, Abc_ObjFaninC0(pObj) );
+        Abc_ObjPatchFanin( pObj, Abc_ObjFanin0(pObj), pFaninNew );
+        assert( Abc_ObjChild0(pObj) == pConst0 );
+        // if a PO is driven by a latch, they have the same name...
+//        if ( Abc_ObjIsBo(pObj) )
+//            Nm_ManDeleteIdName( pNtk->pManName, Abc_ObjId(pObj) );
+    }
+    if ( fVerbose )
+        printf( "Logic cones of %d POs have been replaced by constant 0.\n", Counter );
+    Counter = Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc );
+//    printf( "Cleanup removed %d nodes.\n", Counter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDropOneOutput( Abc_Ntk_t * pNtk, int iOutput, int fSkipSweep, int fUseConst1 )
+{
+    Abc_Obj_t * pObj, * pConst0, * pFaninNew;
+    pObj = Abc_NtkPo( pNtk, iOutput );
+    if ( Abc_ObjFanin0(pObj) == Abc_AigConst1(pNtk) )
+    {
+        if ( !Abc_ObjFaninC0(pObj) ^ fUseConst1 )
+            Abc_ObjXorFaninC( pObj, 0 );
+        return;
+    }
+    pConst0 = Abc_ObjNotCond( Abc_AigConst1(pNtk), !fUseConst1 );
+    pFaninNew = Abc_ObjNotCond( pConst0, Abc_ObjFaninC0(pObj) );
+    Abc_ObjPatchFanin( pObj, Abc_ObjFanin0(pObj), pFaninNew );
+    assert( Abc_ObjChild0(pObj) == pConst0 );
+    if ( fSkipSweep )
+        return;
+    Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSwapOneOutput( Abc_Ntk_t * pNtk, int iOutput )
+{
+    Abc_Obj_t * pObj1, * pObj2;
+    Abc_Obj_t * pChild1Old, * pChild2Old;
+    Abc_Obj_t * pChild1, * pChild2;
+    if ( iOutput == 0 )
+        return;
+    pObj1      = Abc_NtkPo( pNtk, 0 );
+    pObj2      = Abc_NtkPo( pNtk, iOutput );
+    if ( Abc_ObjFanin0(pObj1) == Abc_ObjFanin0(pObj2) )
+    {
+        if ( Abc_ObjFaninC0(pObj1) ^ Abc_ObjFaninC0(pObj2) )
+        {
+            Abc_ObjXorFaninC( pObj1, 0 );
+            Abc_ObjXorFaninC( pObj2, 0 );
+        }
+        return;
+    }
+    pChild1Old = Abc_ObjChild0( pObj1 );
+    pChild2Old = Abc_ObjChild0( pObj2 );
+    pChild1    = Abc_ObjNotCond( pChild1Old, Abc_ObjFaninC0(pObj2) );
+    pChild2    = Abc_ObjNotCond( pChild2Old, Abc_ObjFaninC0(pObj1) );
+    Abc_ObjPatchFanin( pObj1, Abc_ObjFanin0(pObj1), pChild2 );
+    Abc_ObjPatchFanin( pObj2, Abc_ObjFanin0(pObj2), pChild1 );
+    assert( Abc_ObjChild0(pObj1) == pChild2Old );
+    assert( Abc_ObjChild0(pObj2) == pChild1Old );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkRemovePo( Abc_Ntk_t * pNtk, int iOutput, int fRemoveConst0 )
+{
+    Abc_Obj_t * pObj = Abc_NtkPo(pNtk, iOutput);
+    if ( Abc_ObjFanin0(pObj) == Abc_AigConst1(pNtk) && Abc_ObjFaninC0(pObj) == fRemoveConst0 )
+        Abc_NtkDeleteObj( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkReadFlopPerm( char * pFileName, int nFlops )
+{
+    char Buffer[1000];
+    FILE * pFile;
+    Vec_Int_t * vFlops;
+    int iFlop = -1;
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open input file \"%s\".\n", pFileName );
+        return NULL;
+    }
+    vFlops = Vec_IntAlloc( nFlops );
+    while ( fgets( Buffer, 1000, pFile ) != NULL )
+    {
+        if ( Buffer[0] == ' ' || Buffer[0] == '\r' || Buffer[0] == '\n' )
+            continue;
+        iFlop = atoi( Buffer );
+        if ( iFlop < 0 || iFlop >= nFlops )
+        {
+            printf( "Flop ID (%d) is out of range.\n", iFlop );
+            fclose( pFile );
+            Vec_IntFree( vFlops );
+            return NULL;
+        }
+        Vec_IntPush( vFlops, iFlop );
+    }
+    fclose( pFile );
+    if ( Vec_IntSize(vFlops) != nFlops )
+    {
+        printf( "The number of flops read in from file (%d) is different from the number of flops in the circuit (%d).\n", iFlop, nFlops );
+        Vec_IntFree( vFlops );
+        return NULL;
+    }
+    return vFlops;    
+}
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPermute( Abc_Ntk_t * pNtk, int fInputs, int fOutputs, int fFlops, char * pFlopPermFile )
+{
+    Abc_Obj_t * pTemp;
+    Vec_Int_t * vInputs, * vOutputs, * vFlops, * vTemp;
+    int i, k, Entry;
+    // start permutation arrays
+    if ( pFlopPermFile )
+    {
+        vFlops = Abc_NtkReadFlopPerm( pFlopPermFile, Abc_NtkLatchNum(pNtk) );
+        if ( vFlops == NULL )
+            return;
+        fInputs  = 0;
+        fOutputs = 0;
+        fFlops   = 0;
+    }
+    else
+        vFlops   = Vec_IntStartNatural( Abc_NtkLatchNum(pNtk) );
+    vInputs  = Vec_IntStartNatural( Abc_NtkPiNum(pNtk) );
+    vOutputs = Vec_IntStartNatural( Abc_NtkPoNum(pNtk) );
+    // permute inputs
+    if ( fInputs )
+    for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ )
+    {
+        k = rand() % Abc_NtkPiNum(pNtk);
+        // swap indexes
+        Entry = Vec_IntEntry( vInputs, i );
+        Vec_IntWriteEntry( vInputs, i, Vec_IntEntry(vInputs, k) );
+        Vec_IntWriteEntry( vInputs, k, Entry );
+        // swap PIs
+        pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPis, i );
+        Vec_PtrWriteEntry( pNtk->vPis, i, Vec_PtrEntry(pNtk->vPis, k) );
+        Vec_PtrWriteEntry( pNtk->vPis, k, pTemp );
+        // swap CIs
+        pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, i );
+        Vec_PtrWriteEntry( pNtk->vCis, i, Vec_PtrEntry(pNtk->vCis, k) );
+        Vec_PtrWriteEntry( pNtk->vCis, k, pTemp );
+//printf( "Swapping PIs %d and %d.\n", i, k );
+    }
+    // permute outputs
+    if ( fOutputs )
+    for ( i = 0; i < Abc_NtkPoNum(pNtk); i++ )
+    {
+        k = rand() % Abc_NtkPoNum(pNtk);
+        // swap indexes
+        Entry = Vec_IntEntry( vOutputs, i );
+        Vec_IntWriteEntry( vOutputs, i, Vec_IntEntry(vOutputs, k) );
+        Vec_IntWriteEntry( vOutputs, k, Entry );
+        // swap POs
+        pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPos, i );
+        Vec_PtrWriteEntry( pNtk->vPos, i, Vec_PtrEntry(pNtk->vPos, k) );
+        Vec_PtrWriteEntry( pNtk->vPos, k, pTemp );
+        // swap COs
+        pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, i );
+        Vec_PtrWriteEntry( pNtk->vCos, i, Vec_PtrEntry(pNtk->vCos, k) );
+        Vec_PtrWriteEntry( pNtk->vCos, k, pTemp );
+//printf( "Swapping POs %d and %d.\n", i, k );
+    }
+    // permute flops
+    assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) );
+    if ( fFlops )
+    for ( i = 0; i < Abc_NtkLatchNum(pNtk); i++ )
+    {
+        k = rand() % Abc_NtkLatchNum(pNtk);
+        // swap indexes
+        Entry = Vec_IntEntry( vFlops, i );
+        Vec_IntWriteEntry( vFlops, i, Vec_IntEntry(vFlops, k) );
+        Vec_IntWriteEntry( vFlops, k, Entry );
+        // swap flops
+        pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vBoxes, i );
+        Vec_PtrWriteEntry( pNtk->vBoxes, i, Vec_PtrEntry(pNtk->vBoxes, k) );
+        Vec_PtrWriteEntry( pNtk->vBoxes, k, pTemp );
+        // swap CIs
+        pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+i );
+        Vec_PtrWriteEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+i, Vec_PtrEntry(pNtk->vCis, Abc_NtkPiNum(pNtk)+k) );
+        Vec_PtrWriteEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+k, pTemp );
+        // swap COs
+        pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+i );
+        Vec_PtrWriteEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+i, Vec_PtrEntry(pNtk->vCos, Abc_NtkPoNum(pNtk)+k) );
+        Vec_PtrWriteEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+k, pTemp );
+
+//printf( "Swapping flops %d and %d.\n", i, k );
+    }
+    // invert arrays
+    vInputs = Vec_IntInvert( vTemp = vInputs, -1 );
+    Vec_IntFree( vTemp );
+    vOutputs = Vec_IntInvert( vTemp = vOutputs, -1 );
+    Vec_IntFree( vTemp );
+    vFlops = Vec_IntInvert( vTemp = vFlops, -1 );
+    Vec_IntFree( vTemp );
+    // pack the results into the output array
+    Vec_IntFreeP( &pNtk->vObjPerm );
+    pNtk->vObjPerm = Vec_IntAlloc( Abc_NtkPiNum(pNtk) + Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk) );
+    Vec_IntForEachEntry( vInputs, Entry, i )
+        Vec_IntPush( pNtk->vObjPerm, Entry );
+    Vec_IntForEachEntry( vOutputs, Entry, i )
+        Vec_IntPush( pNtk->vObjPerm, Entry );
+    Vec_IntForEachEntry( vFlops, Entry, i )
+        Vec_IntPush( pNtk->vObjPerm, Entry );
+    // cleanup
+    Vec_IntFree( vInputs );
+    Vec_IntFree( vOutputs );
+    Vec_IntFree( vFlops );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkUnpermute( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vTemp, * vTemp2, * vLatch;
+    int i, * pInputs, * pOutputs, * pFlops;
+    if ( pNtk->vObjPerm == NULL )
+    {
+        printf( "Abc_NtkUnpermute(): Initial permutation is not available.\n" );
+        return;
+    }
+    assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) );
+    // get reverve permutation
+    pInputs  = Vec_IntArray( pNtk->vObjPerm );
+    pOutputs = pInputs  + Abc_NtkPiNum(pNtk);
+    pFlops   = pOutputs + Abc_NtkPoNum(pNtk);
+    // create new PI array
+    vTemp = Vec_PtrAlloc( Abc_NtkPiNum(pNtk) );
+    for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ )
+        Vec_PtrPush( vTemp, Abc_NtkPi(pNtk, pInputs[i]) );
+    Vec_PtrFreeP( &pNtk->vPis );
+    pNtk->vPis = vTemp;
+    // create new PO array
+    vTemp = Vec_PtrAlloc( Abc_NtkPoNum(pNtk) );
+    for ( i = 0; i < Abc_NtkPoNum(pNtk); i++ )
+        Vec_PtrPush( vTemp, Abc_NtkPo(pNtk, pOutputs[i]) );
+    Vec_PtrFreeP( &pNtk->vPos );
+    pNtk->vPos = vTemp;
+    // create new CI/CO arrays
+    vTemp  = Vec_PtrDup( pNtk->vPis );
+    vTemp2 = Vec_PtrDup( pNtk->vPos );
+    vLatch = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) );
+    for ( i = 0; i < Abc_NtkLatchNum(pNtk); i++ )
+    {
+//printf( "Setting flop %d to be %d.\n", i, pFlops[i] );
+        Vec_PtrPush( vTemp,  Abc_NtkCi(pNtk, Abc_NtkPiNum(pNtk) + pFlops[i]) );
+        Vec_PtrPush( vTemp2, Abc_NtkCo(pNtk, Abc_NtkPoNum(pNtk) + pFlops[i]) );
+        Vec_PtrPush( vLatch, Abc_NtkBox(pNtk, pFlops[i]) );
+    }
+    Vec_PtrFreeP( &pNtk->vCis );
+    Vec_PtrFreeP( &pNtk->vCos );
+    Vec_PtrFreeP( &pNtk->vBoxes );
+    pNtk->vCis   = vTemp;
+    pNtk->vCos   = vTemp2;
+    pNtk->vBoxes = vLatch;
+    // cleanup
+    Vec_IntFreeP( &pNtk->vObjPerm );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkNodeDup( Abc_Ntk_t * pNtkInit, int nLimit, int fVerbose )
+{
+    Vec_Ptr_t * vNodes, * vFanouts;
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pObj, * pObjNew, * pFanin, * pFanout;
+    int i, k;
+    pNtk = Abc_NtkDup( pNtkInit );
+    vNodes = Vec_PtrAlloc( 100 );
+    vFanouts = Vec_PtrAlloc( 100 );
+    do
+    {
+        Vec_PtrClear( vNodes );
+        Abc_NtkForEachNode( pNtk, pObj, i )
+            if ( Abc_ObjFanoutNum(pObj) >= nLimit )
+                Vec_PtrPush( vNodes, pObj );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        {
+            pObjNew = Abc_NtkDupObj( pNtk, pObj, 0 );
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                Abc_ObjAddFanin( pObjNew, pFanin );
+            Abc_NodeCollectFanouts( pObj, vFanouts );
+            Vec_PtrShrink( vFanouts, nLimit / 2 );
+            Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, k )
+                Abc_ObjPatchFanin( pFanout, pObj, pObjNew );
+        }
+        if ( fVerbose )
+            printf( "Duplicated %d nodes.\n", Vec_PtrSize(vNodes) );
+    }
+    while ( Vec_PtrSize(vNodes) > 0 );
+    Vec_PtrFree( vFanouts );
+    Vec_PtrFree( vNodes );
+    return pNtk;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcObj.c b/abc-build/src/base/abc/abcObj.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcObj.c
@@ -0,0 +1,1040 @@
+/**CFile****************************************************************
+
+  FileName    [abcObj.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Object creation/duplication/deletion procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcObj.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "abcInt.h"
+#include "base/main/main.h"
+#include "map/mio/mio.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type )
+{
+    Abc_Obj_t * pObj;
+    if ( pNtk->pMmObj )
+        pObj = (Abc_Obj_t *)Mem_FixedEntryFetch( pNtk->pMmObj );
+    else
+        pObj = (Abc_Obj_t *)ABC_ALLOC( Abc_Obj_t, 1 );
+    memset( pObj, 0, sizeof(Abc_Obj_t) );
+    pObj->pNtk = pNtk;
+    pObj->Type = Type;
+    pObj->Id   = -1;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ObjRecycle( Abc_Obj_t * pObj )
+{
+    Abc_Ntk_t * pNtk = pObj->pNtk;
+//    int LargePiece = (4 << ABC_NUM_STEPS);
+    // free large fanout arrays
+//    if ( pNtk->pMmStep && pObj->vFanouts.nCap * 4 > LargePiece )
+//        free( pObj->vFanouts.pArray );
+    if ( pNtk->pMmStep == NULL )
+    {
+        ABC_FREE( pObj->vFanouts.pArray );
+        ABC_FREE( pObj->vFanins.pArray );
+    }
+    // clean the memory to make deleted object distinct from the live one
+    memset( pObj, 0, sizeof(Abc_Obj_t) );
+    // recycle the object
+    if ( pNtk->pMmObj )
+        Mem_FixedEntryRecycle( pNtk->pMmObj, (char *)pObj );
+    else
+        ABC_FREE( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the node to the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type )
+{
+    Abc_Obj_t * pObj;
+    // create new object, assign ID, and add to the array
+    pObj = Abc_ObjAlloc( pNtk, Type );
+    pObj->Id = pNtk->vObjs->nSize;
+    Vec_PtrPush( pNtk->vObjs, pObj );
+    pNtk->nObjCounts[Type]++;
+    pNtk->nObjs++;
+    // perform specialized operations depending on the object type
+    switch (Type)
+    {
+        case ABC_OBJ_NONE:   
+            assert(0); 
+            break;
+        case ABC_OBJ_CONST1: 
+            assert(0); 
+            break;
+        case ABC_OBJ_PI:
+//            pObj->iTemp = Vec_PtrSize(pNtk->vCis);
+            Vec_PtrPush( pNtk->vPis, pObj );
+            Vec_PtrPush( pNtk->vCis, pObj );
+            break;
+        case ABC_OBJ_PO:     
+//            pObj->iTemp = Vec_PtrSize(pNtk->vCos);
+            Vec_PtrPush( pNtk->vPos, pObj );
+            Vec_PtrPush( pNtk->vCos, pObj );
+            break;
+        case ABC_OBJ_BI:     
+            if ( pNtk->vCos ) Vec_PtrPush( pNtk->vCos, pObj );
+            break;
+        case ABC_OBJ_BO:     
+            if ( pNtk->vCis ) Vec_PtrPush( pNtk->vCis, pObj );
+            break;
+        case ABC_OBJ_NET:  
+        case ABC_OBJ_NODE: 
+            break;
+        case ABC_OBJ_LATCH:     
+            pObj->pData = (void *)ABC_INIT_NONE;
+        case ABC_OBJ_WHITEBOX:     
+        case ABC_OBJ_BLACKBOX:     
+            if ( pNtk->vBoxes ) Vec_PtrPush( pNtk->vBoxes, pObj );
+            break;
+        default:
+            assert(0); 
+            break;
+    }
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the object from the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDeleteObj( Abc_Obj_t * pObj )
+{
+    Abc_Ntk_t * pNtk = pObj->pNtk;
+    Vec_Ptr_t * vNodes;
+    int i;
+    assert( !Abc_ObjIsComplement(pObj) );
+    // remove from the table of names
+    if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) )
+        Nm_ManDeleteIdName(pObj->pNtk->pManName, pObj->Id);
+    // delete fanins and fanouts
+    vNodes = Vec_PtrAlloc( 100 );
+    Abc_NodeCollectFanouts( pObj, vNodes );
+    for ( i = 0; i < vNodes->nSize; i++ )
+        Abc_ObjDeleteFanin( (Abc_Obj_t *)vNodes->pArray[i], pObj );
+    Abc_NodeCollectFanins( pObj, vNodes );
+    for ( i = 0; i < vNodes->nSize; i++ )
+        Abc_ObjDeleteFanin( pObj, (Abc_Obj_t *)vNodes->pArray[i] );
+    Vec_PtrFree( vNodes );
+    // remove from the list of objects
+    Vec_PtrWriteEntry( pNtk->vObjs, pObj->Id, NULL );
+    pObj->Id = (1<<26)-1;
+    pNtk->nObjCounts[pObj->Type]--;
+    pNtk->nObjs--;
+    // perform specialized operations depending on the object type
+    switch (pObj->Type)
+    {
+        case ABC_OBJ_NONE:   
+            assert(0); 
+            break;
+        case ABC_OBJ_CONST1: 
+            assert(0); 
+            break;
+        case ABC_OBJ_PI:     
+            Vec_PtrRemove( pNtk->vPis, pObj );
+            Vec_PtrRemove( pNtk->vCis, pObj );
+            break;
+        case ABC_OBJ_PO:     
+            Vec_PtrRemove( pNtk->vPos, pObj );
+            Vec_PtrRemove( pNtk->vCos, pObj );
+            break;
+        case ABC_OBJ_BI:     
+            if ( pNtk->vCos ) Vec_PtrRemove( pNtk->vCos, pObj );
+            break;
+        case ABC_OBJ_BO:     
+            if ( pNtk->vCis ) Vec_PtrRemove( pNtk->vCis, pObj );
+            break;
+        case ABC_OBJ_NET:  
+            break;
+        case ABC_OBJ_NODE: 
+            if ( Abc_NtkHasBdd(pNtk) )
+                Cudd_RecursiveDeref( (DdManager *)pNtk->pManFunc, (DdNode *)pObj->pData );
+            pObj->pData = NULL;
+            break;
+        case ABC_OBJ_LATCH:     
+        case ABC_OBJ_WHITEBOX:     
+        case ABC_OBJ_BLACKBOX:     
+            if ( pNtk->vBoxes ) Vec_PtrRemove( pNtk->vBoxes, pObj );
+            break;
+        default:
+            assert(0); 
+            break;
+    }
+    // recycle the object memory
+    Abc_ObjRecycle( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the PO from the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDeleteObjPo( Abc_Obj_t * pObj )
+{
+    assert( Abc_ObjIsPo(pObj) );
+    // remove from the table of names
+    if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) )
+        Nm_ManDeleteIdName(pObj->pNtk->pManName, pObj->Id);
+    // delete fanins
+    Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) );
+    // remove from the list of objects
+    Vec_PtrWriteEntry( pObj->pNtk->vObjs, pObj->Id, NULL );
+    pObj->Id = (1<<26)-1;
+    pObj->pNtk->nObjCounts[pObj->Type]--;
+    pObj->pNtk->nObjs--;
+    // recycle the object memory
+    Abc_ObjRecycle( pObj );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the node and MFFC of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDeleteObj_rec( Abc_Obj_t * pObj, int fOnlyNodes )
+{
+    Vec_Ptr_t * vNodes;
+    int i;
+    assert( !Abc_ObjIsComplement(pObj) );
+    assert( !Abc_ObjIsPi(pObj) );
+    assert( Abc_ObjFanoutNum(pObj) == 0 );
+    // delete fanins and fanouts
+    vNodes = Vec_PtrAlloc( 100 );
+    Abc_NodeCollectFanins( pObj, vNodes );
+    Abc_NtkDeleteObj( pObj );
+    if ( fOnlyNodes )
+    {
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+            if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) == 0 )
+                Abc_NtkDeleteObj_rec( pObj, fOnlyNodes );
+    }
+    else
+    {
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+            if ( !Abc_ObjIsPi(pObj) && Abc_ObjFanoutNum(pObj) == 0 )
+                Abc_NtkDeleteObj_rec( pObj, fOnlyNodes );
+    }
+    Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the node and MFFC of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDeleteAll_rec( Abc_Obj_t * pObj )
+{
+    Vec_Ptr_t * vNodes;
+    int i;
+    assert( !Abc_ObjIsComplement(pObj) );
+    assert( Abc_ObjFanoutNum(pObj) == 0 );
+    // delete fanins and fanouts
+    vNodes = Vec_PtrAlloc( 100 );
+    Abc_NodeCollectFanins( pObj, vNodes );
+    Abc_NtkDeleteObj( pObj );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        if ( !Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) == 0 )
+            Abc_NtkDeleteAll_rec( pObj );
+    Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicate the Obj.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName )
+{
+    Abc_Obj_t * pObjNew;
+    // create the new object
+    pObjNew = Abc_NtkCreateObj( pNtkNew, (Abc_ObjType_t)pObj->Type );
+    // transfer names of the terminal objects
+    if ( fCopyName )
+    {
+        if ( Abc_ObjIsCi(pObj) )
+        {
+            if ( !Abc_NtkIsNetlist(pNtkNew) )
+                Abc_ObjAssignName( pObjNew, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL );
+        }
+        else if ( Abc_ObjIsCo(pObj) )
+        {
+            if ( !Abc_NtkIsNetlist(pNtkNew) )
+            {
+                if ( Abc_ObjIsPo(pObj) )
+                    Abc_ObjAssignName( pObjNew, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL );
+                else
+                {
+                    assert( Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) );
+                    Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL );
+                }
+            }
+        }
+        else if ( Abc_ObjIsBox(pObj) || Abc_ObjIsNet(pObj) )
+            Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL );
+    }
+    // copy functionality/names
+    if ( Abc_ObjIsNode(pObj) ) // copy the function if functionality is compatible
+    {
+        if ( pNtkNew->ntkFunc == pObj->pNtk->ntkFunc ) 
+        {
+            if ( Abc_NtkIsStrash(pNtkNew) ) 
+            {}
+            else if ( Abc_NtkHasSop(pNtkNew) || Abc_NtkHasBlifMv(pNtkNew) )
+                pObjNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, (char *)pObj->pData );
+            else if ( Abc_NtkHasBdd(pNtkNew) )
+                pObjNew->pData = Cudd_bddTransfer((DdManager *)pObj->pNtk->pManFunc, (DdManager *)pNtkNew->pManFunc, (DdNode *)pObj->pData), Cudd_Ref((DdNode *)pObjNew->pData);
+            else if ( Abc_NtkHasAig(pNtkNew) )
+                pObjNew->pData = Hop_Transfer((Hop_Man_t *)pObj->pNtk->pManFunc, (Hop_Man_t *)pNtkNew->pManFunc, (Hop_Obj_t *)pObj->pData, Abc_ObjFaninNum(pObj));
+            else if ( Abc_NtkHasMapping(pNtkNew) )
+                pObjNew->pData = pObj->pData;
+            else assert( 0 );
+        }
+    }
+    else if ( Abc_ObjIsNet(pObj) ) // copy the name
+    {
+    }
+    else if ( Abc_ObjIsLatch(pObj) ) // copy the reset value
+        pObjNew->pData = pObj->pData;
+    // transfer HAIG
+//    pObjNew->pEquiv = pObj->pEquiv;
+    // remember the new node in the old node
+    pObj->pCopy = pObjNew;
+    return pObjNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the latch with its input/output terminals.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkDupBox( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pBox, int fCopyName )
+{
+    Abc_Obj_t * pTerm, * pBoxNew;
+    int i;
+    assert( Abc_ObjIsBox(pBox) );
+    // duplicate the box 
+    pBoxNew = Abc_NtkDupObj( pNtkNew, pBox, fCopyName );
+    // duplicate the fanins and connect them
+    Abc_ObjForEachFanin( pBox, pTerm, i )
+        Abc_ObjAddFanin( pBoxNew, Abc_NtkDupObj(pNtkNew, pTerm, fCopyName) );
+    // duplicate the fanouts and connect them
+    Abc_ObjForEachFanout( pBox, pTerm, i )
+        Abc_ObjAddFanin( Abc_NtkDupObj(pNtkNew, pTerm, fCopyName), pBoxNew );
+    return pBoxNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Clones the objects in the same network but does not assign its function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkCloneObj( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pClone, * pFanin;
+    int i;
+    pClone = Abc_NtkCreateObj( pObj->pNtk, (Abc_ObjType_t)pObj->Type );   
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        Abc_ObjAddFanin( pClone, pFanin );
+    return pClone;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the net with the given name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName )
+{
+    Abc_Obj_t * pObj;
+    int Num;
+    // try to find the terminal
+    Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PO );
+    if ( Num >= 0 )
+        return Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) );
+    Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BI );
+    if ( Num >= 0 )
+        return Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) );
+    Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_NODE );
+    if ( Num >= 0 )
+        return Abc_NtkObj( pNtk, Num );
+    // find the internal node
+    if ( pName[0] != 'n' )
+    {
+        printf( "Name \"%s\" is not found among CO or node names (internal names often look as \"n<num>\").\n", pName );
+        return NULL;
+    }
+    Num = atoi( pName + 1 );
+    if ( Num < 0 || Num >= Abc_NtkObjNumMax(pNtk) )
+    {
+        printf( "The node \"%s\" with ID %d is not in the current network.\n", pName, Num );
+        return NULL;
+    }
+    pObj = Abc_NtkObj( pNtk, Num );
+    if ( pObj == NULL )
+    {
+        printf( "The node \"%s\" with ID %d has been removed from the current network.\n", pName, Num );
+        return NULL;
+    }
+    if ( !Abc_ObjIsNode(pObj) )
+    {
+        printf( "Object with ID %d is not a node.\n", Num );
+        return NULL;
+    }
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the net with the given name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkFindNet( Abc_Ntk_t * pNtk, char * pName )
+{
+    Abc_Obj_t * pNet;
+    int ObjId;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    ObjId = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_NET );
+    if ( ObjId == -1 )
+        return NULL;
+    pNet = Abc_NtkObj( pNtk, ObjId );
+    return pNet;
+}
+
+/**Function*************************************************************
+
+ Synopsis    [Returns CI with the given name.]
+
+ Description []
+              
+ SideEffects []
+
+ SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkFindCi( Abc_Ntk_t * pNtk, char * pName )
+{
+    int Num;
+    assert( !Abc_NtkIsNetlist(pNtk) );
+    Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PI );
+    if ( Num >= 0 )
+        return Abc_NtkObj( pNtk, Num );
+    Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BO );
+    if ( Num >= 0 )
+        return Abc_NtkObj( pNtk, Num );
+    return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis    [Returns CO with the given name.]
+
+ Description []
+              
+ SideEffects []
+
+ SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName )
+{
+    int Num;
+    assert( !Abc_NtkIsNetlist(pNtk) );
+    Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PO );
+    if ( Num >= 0 )
+        return Abc_NtkObj( pNtk, Num );
+    Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BI );
+    if ( Num >= 0 )
+        return Abc_NtkObj( pNtk, Num );
+    return NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds or creates the net.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName )
+{
+    Abc_Obj_t * pNet;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    if ( pName && (pNet = Abc_NtkFindNet( pNtk, pName )) )
+        return pNet;
+//printf( "Creating net %s.\n", pName );
+    // create a new net
+    pNet = Abc_NtkCreateNet( pNtk );
+    if ( pName )
+        Nm_ManStoreIdName( pNtk->pManName, pNet->Id, pNet->Type, pName, NULL );
+    return pNet;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates constant 0 node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
+    pNode = Abc_NtkCreateNode( pNtk );   
+    if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) )
+        pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 0\n" );
+    else if ( Abc_NtkHasBdd(pNtk) )
+        pNode->pData = Cudd_ReadLogicZero((DdManager *)pNtk->pManFunc), Cudd_Ref( (DdNode *)pNode->pData );
+    else if ( Abc_NtkHasAig(pNtk) )
+        pNode->pData = Hop_ManConst0((Hop_Man_t *)pNtk->pManFunc);
+    else if ( Abc_NtkHasMapping(pNtk) )
+        pNode->pData = Mio_LibraryReadConst0((Mio_Library_t *)Abc_FrameReadLibGen());
+    else if ( !Abc_NtkHasBlackbox(pNtk) )
+        assert( 0 );
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates constant 1 node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
+    pNode = Abc_NtkCreateNode( pNtk );   
+    if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) )
+        pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 1\n" );
+    else if ( Abc_NtkHasBdd(pNtk) )
+        pNode->pData = Cudd_ReadOne((DdManager *)pNtk->pManFunc), Cudd_Ref( (DdNode *)pNode->pData );
+    else if ( Abc_NtkHasAig(pNtk) )
+        pNode->pData = Hop_ManConst1((Hop_Man_t *)pNtk->pManFunc);
+    else if ( Abc_NtkHasMapping(pNtk) )
+        pNode->pData = Mio_LibraryReadConst1((Mio_Library_t *)Abc_FrameReadLibGen());
+    else if ( !Abc_NtkHasBlackbox(pNtk) )
+        assert( 0 );
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates inverter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin )
+{
+    Abc_Obj_t * pNode;
+    assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
+    pNode = Abc_NtkCreateNode( pNtk );   
+    if ( pFanin ) Abc_ObjAddFanin( pNode, pFanin );
+    if ( Abc_NtkHasSop(pNtk) )
+        pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, "0 1\n" );
+    else if ( Abc_NtkHasBdd(pNtk) )
+        pNode->pData = Cudd_Not(Cudd_bddIthVar((DdManager *)pNtk->pManFunc,0)), Cudd_Ref( (DdNode *)pNode->pData );
+    else if ( Abc_NtkHasAig(pNtk) )
+        pNode->pData = Hop_Not(Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,0));
+    else if ( Abc_NtkHasMapping(pNtk) )
+        pNode->pData = Mio_LibraryReadInv((Mio_Library_t *)Abc_FrameReadLibGen());
+    else
+        assert( 0 );
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates buffer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin )
+{
+    Abc_Obj_t * pNode;
+    assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
+    pNode = Abc_NtkCreateNode( pNtk ); 
+    if ( pFanin ) Abc_ObjAddFanin( pNode, pFanin );
+    if ( Abc_NtkHasSop(pNtk) )
+        pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, "1 1\n" );
+    else if ( Abc_NtkHasBdd(pNtk) )
+        pNode->pData = Cudd_bddIthVar((DdManager *)pNtk->pManFunc,0), Cudd_Ref( (DdNode *)pNode->pData );
+    else if ( Abc_NtkHasAig(pNtk) )
+        pNode->pData = Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,0);
+    else if ( Abc_NtkHasMapping(pNtk) )
+        pNode->pData = Mio_LibraryReadBuf((Mio_Library_t *)Abc_FrameReadLibGen());
+    else
+        assert( 0 );
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates AND.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
+    pNode = Abc_NtkCreateNode( pNtk );   
+    for ( i = 0; i < vFanins->nSize; i++ )
+        Abc_ObjAddFanin( pNode, (Abc_Obj_t *)vFanins->pArray[i] );
+    if ( Abc_NtkHasSop(pNtk) )
+        pNode->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtk->pManFunc, Vec_PtrSize(vFanins), NULL );
+    else if ( Abc_NtkHasBdd(pNtk) )
+        pNode->pData = Extra_bddCreateAnd( (DdManager *)pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref((DdNode *)pNode->pData); 
+    else if ( Abc_NtkHasAig(pNtk) )
+        pNode->pData = Hop_CreateAnd( (Hop_Man_t *)pNtk->pManFunc, Vec_PtrSize(vFanins) ); 
+    else
+        assert( 0 );
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates OR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
+    pNode = Abc_NtkCreateNode( pNtk );   
+    for ( i = 0; i < vFanins->nSize; i++ )
+        Abc_ObjAddFanin( pNode, (Abc_Obj_t *)vFanins->pArray[i] );
+    if ( Abc_NtkHasSop(pNtk) )
+        pNode->pData = Abc_SopCreateOr( (Mem_Flex_t *)pNtk->pManFunc, Vec_PtrSize(vFanins), NULL );
+    else if ( Abc_NtkHasBdd(pNtk) )
+        pNode->pData = Extra_bddCreateOr( (DdManager *)pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref((DdNode *)pNode->pData); 
+    else if ( Abc_NtkHasAig(pNtk) )
+        pNode->pData = Hop_CreateOr( (Hop_Man_t *)pNtk->pManFunc, Vec_PtrSize(vFanins) ); 
+    else
+        assert( 0 );
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates EXOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
+    pNode = Abc_NtkCreateNode( pNtk );   
+    for ( i = 0; i < vFanins->nSize; i++ )
+        Abc_ObjAddFanin( pNode, (Abc_Obj_t *)vFanins->pArray[i] );
+    if ( Abc_NtkHasSop(pNtk) )
+        pNode->pData = Abc_SopCreateXorSpecial( (Mem_Flex_t *)pNtk->pManFunc, Vec_PtrSize(vFanins) );
+    else if ( Abc_NtkHasBdd(pNtk) )
+        pNode->pData = Extra_bddCreateExor( (DdManager *)pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref((DdNode *)pNode->pData); 
+    else if ( Abc_NtkHasAig(pNtk) )
+        pNode->pData = Hop_CreateExor( (Hop_Man_t *)pNtk->pManFunc, Vec_PtrSize(vFanins) ); 
+    else
+        assert( 0 );
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates MUX.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkCreateNodeMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 )
+{
+    Abc_Obj_t * pNode;
+    assert( Abc_NtkIsLogic(pNtk) );
+    pNode = Abc_NtkCreateNode( pNtk );   
+    Abc_ObjAddFanin( pNode, pNodeC );
+    Abc_ObjAddFanin( pNode, pNode1 );
+    Abc_ObjAddFanin( pNode, pNode0 );
+    if ( Abc_NtkHasSop(pNtk) )
+        pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, "11- 1\n0-1 1\n" );
+    else if ( Abc_NtkHasBdd(pNtk) )
+        pNode->pData = Cudd_bddIte((DdManager *)pNtk->pManFunc,Cudd_bddIthVar((DdManager *)pNtk->pManFunc,0),Cudd_bddIthVar((DdManager *)pNtk->pManFunc,1),Cudd_bddIthVar((DdManager *)pNtk->pManFunc,2)), Cudd_Ref( (DdNode *)pNode->pData );
+    else if ( Abc_NtkHasAig(pNtk) )
+        pNode->pData = Hop_Mux((Hop_Man_t *)pNtk->pManFunc,Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,0),Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,1),Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,2));
+    else
+        assert( 0 );
+    return pNode;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node is a constant 0 node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeIsConst( Abc_Obj_t * pNode )    
+{ 
+    assert( Abc_NtkIsLogic(pNode->pNtk) || Abc_NtkIsNetlist(pNode->pNtk) );
+    return Abc_ObjIsNode(pNode) && Abc_ObjFaninNum(pNode) == 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node is a constant 0 node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeIsConst0( Abc_Obj_t * pNode )    
+{ 
+    Abc_Ntk_t * pNtk = pNode->pNtk;
+    assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_ObjIsNode(pNode) );      
+    if ( !Abc_NodeIsConst(pNode) )
+        return 0;
+    if ( Abc_NtkHasSop(pNtk) )
+        return Abc_SopIsConst0((char *)pNode->pData);
+    if ( Abc_NtkHasBdd(pNtk) )
+        return Cudd_IsComplement(pNode->pData);
+    if ( Abc_NtkHasAig(pNtk) )
+        return Hop_IsComplement((Hop_Obj_t *)pNode->pData)? 1:0;
+    if ( Abc_NtkHasMapping(pNtk) )
+        return pNode->pData == Mio_LibraryReadConst0((Mio_Library_t *)Abc_FrameReadLibGen());
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node is a constant 1 node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeIsConst1( Abc_Obj_t * pNode )    
+{ 
+    Abc_Ntk_t * pNtk = pNode->pNtk;
+    assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_ObjIsNode(pNode) );      
+    if ( !Abc_NodeIsConst(pNode) )
+        return 0;
+    if ( Abc_NtkHasSop(pNtk) )
+        return Abc_SopIsConst1((char *)pNode->pData);
+    if ( Abc_NtkHasBdd(pNtk) )
+        return !Cudd_IsComplement(pNode->pData);
+    if ( Abc_NtkHasAig(pNtk) )
+        return !Hop_IsComplement((Hop_Obj_t *)pNode->pData);
+    if ( Abc_NtkHasMapping(pNtk) )
+        return pNode->pData == Mio_LibraryReadConst1((Mio_Library_t *)Abc_FrameReadLibGen());
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node is a buffer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeIsBuf( Abc_Obj_t * pNode )    
+{ 
+    Abc_Ntk_t * pNtk = pNode->pNtk;
+    assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_ObjIsNode(pNode) ); 
+    if ( Abc_ObjFaninNum(pNode) != 1 )
+        return 0;
+    if ( Abc_NtkHasSop(pNtk) )
+        return Abc_SopIsBuf((char *)pNode->pData);
+    if ( Abc_NtkHasBdd(pNtk) )
+        return !Cudd_IsComplement(pNode->pData);
+    if ( Abc_NtkHasAig(pNtk) )
+        return !Hop_IsComplement((Hop_Obj_t *)pNode->pData);
+    if ( Abc_NtkHasMapping(pNtk) )
+        return pNode->pData == Mio_LibraryReadBuf((Mio_Library_t *)Abc_FrameReadLibGen());
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node is an inverter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeIsInv( Abc_Obj_t * pNode )    
+{ 
+    Abc_Ntk_t * pNtk = pNode->pNtk;
+    assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_ObjIsNode(pNode) ); 
+    if ( Abc_ObjFaninNum(pNode) != 1 )
+        return 0;
+    if ( Abc_NtkHasSop(pNtk) )
+        return Abc_SopIsInv((char *)pNode->pData);
+    if ( Abc_NtkHasBdd(pNtk) )
+        return Cudd_IsComplement(pNode->pData);
+    if ( Abc_NtkHasAig(pNtk) )
+        return Hop_IsComplement((Hop_Obj_t *)pNode->pData)? 1:0;
+    if ( Abc_NtkHasMapping(pNtk) )
+        return pNode->pData == Mio_LibraryReadInv((Mio_Library_t *)Abc_FrameReadLibGen());
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Complements the local functions of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeComplement( Abc_Obj_t * pNode )
+{
+    assert( Abc_NtkIsLogic(pNode->pNtk) || Abc_NtkIsNetlist(pNode->pNtk) );
+    assert( Abc_ObjIsNode(pNode) ); 
+    if ( Abc_NtkHasSop(pNode->pNtk) )
+        Abc_SopComplement( (char *)pNode->pData );
+    else if ( Abc_NtkHasAig(pNode->pNtk) )
+        pNode->pData = Hop_Not( (Hop_Obj_t *)pNode->pData );
+    else if ( Abc_NtkHasBdd(pNode->pNtk) )
+        pNode->pData = Cudd_Not( pNode->pData );
+    else
+        assert( 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Changes the polarity of one fanin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin )
+{
+    int iFanin;
+    if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 )
+    {
+        printf( "Node %s should be among", Abc_ObjName(pFanin) );
+        printf( " the fanins of node %s...\n", Abc_ObjName(pNode) );
+        return;
+    }
+    if ( Abc_NtkHasSop(pNode->pNtk) )
+        Abc_SopComplementVar( (char *)pNode->pData, iFanin );
+    else if ( Abc_NtkHasAig(pNode->pNtk) )
+        pNode->pData = Hop_Complement( (Hop_Man_t *)pNode->pNtk->pManFunc, (Hop_Obj_t *)pNode->pData, iFanin );
+    else if ( Abc_NtkHasBdd(pNode->pNtk) )
+    {
+        DdManager * dd = (DdManager *)pNode->pNtk->pManFunc;
+        DdNode * bVar, * bCof0, * bCof1;
+        bVar = Cudd_bddIthVar( dd, iFanin );
+        bCof0 = Cudd_Cofactor( dd, (DdNode *)pNode->pData, Cudd_Not(bVar) );   Cudd_Ref( bCof0 );
+        bCof1 = Cudd_Cofactor( dd, (DdNode *)pNode->pData, bVar );             Cudd_Ref( bCof1 );
+        Cudd_RecursiveDeref( dd, (DdNode *)pNode->pData );
+        pNode->pData = Cudd_bddIte( dd, bVar, bCof0, bCof1 );        Cudd_Ref( (DdNode *)pNode->pData );
+        Cudd_RecursiveDeref( dd, bCof0 );
+        Cudd_RecursiveDeref( dd, bCof1 );
+    }
+    else
+        assert( 0 );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcRefs.c b/abc-build/src/base/abc/abcRefs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcRefs.c
@@ -0,0 +1,457 @@
+/**CFile****************************************************************
+
+  FileName    [abcRefs.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Procedures using reference counting of the AIG nodes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcRefs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_NodeRefDeref( Abc_Obj_t * pNode, int fReference, int fLabel );
+static int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, int fReference );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the MFFC size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeMffcSize( Abc_Obj_t * pNode )
+{
+    int nConeSize1, nConeSize2;
+//    assert( Abc_NtkIsStrash(pNode->pNtk) );
+//    assert( !Abc_ObjIsComplement( pNode ) );
+    assert( Abc_ObjIsNode( pNode ) );
+    if ( Abc_ObjFaninNum(pNode) == 0 )
+        return 0;
+    nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0 ); // dereference
+    nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference
+    assert( nConeSize1 == nConeSize2 );
+    assert( nConeSize1 > 0 );
+    return nConeSize1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the MFFC size while stopping at the complemented edges.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode )
+{
+    int nConeSize1, nConeSize2;
+    assert( Abc_NtkIsStrash(pNode->pNtk) );
+    assert( !Abc_ObjIsComplement( pNode ) );
+    assert( Abc_ObjIsNode( pNode ) );
+    if ( Abc_ObjFaninNum(pNode) == 0 )
+        return 0;
+    nConeSize1 = Abc_NodeRefDerefStop( pNode, 0 ); // dereference
+    nConeSize2 = Abc_NodeRefDerefStop( pNode, 1 ); // reference
+    assert( nConeSize1 == nConeSize2 );
+    assert( nConeSize1 > 0 );
+    return nConeSize1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Labels MFFC with the current traversal ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeMffcLabelAig( Abc_Obj_t * pNode )
+{
+    int nConeSize1, nConeSize2;
+    assert( Abc_NtkIsStrash(pNode->pNtk) );
+    assert( !Abc_ObjIsComplement( pNode ) );
+    assert( Abc_ObjIsNode( pNode ) );
+    if ( Abc_ObjFaninNum(pNode) == 0 )
+        return 0;
+    nConeSize1 = Abc_NodeRefDeref( pNode, 0, 1 ); // dereference
+    nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference
+    assert( nConeSize1 == nConeSize2 );
+    assert( nConeSize1 > 0 );
+    return nConeSize1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [References/references the node and returns MFFC size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeRefDeref( Abc_Obj_t * pNode, int fReference, int fLabel )
+{
+    Abc_Obj_t * pNode0, * pNode1;
+    int Counter;
+    // label visited nodes
+    if ( fLabel )
+        Abc_NodeSetTravIdCurrent( pNode );
+    // skip the CI
+    if ( Abc_ObjIsCi(pNode) )
+        return 0;
+    // process the internal node
+    pNode0 = Abc_ObjFanin0(pNode);
+    pNode1 = Abc_ObjFanin1(pNode);
+    Counter = 1;
+    if ( fReference )
+    {
+        if ( pNode0->vFanouts.nSize++ == 0 )
+            Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel );
+        if ( pNode1->vFanouts.nSize++ == 0 )
+            Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel );
+    }
+    else
+    {
+        assert( pNode0->vFanouts.nSize > 0 );
+        assert( pNode1->vFanouts.nSize > 0 );
+        if ( --pNode0->vFanouts.nSize == 0 )
+            Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel );
+        if ( --pNode1->vFanouts.nSize == 0 )
+            Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel );
+    }
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [References/references the node and returns MFFC size.]
+
+  Description [Stops at the complemented edges.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, int fReference )
+{
+    Abc_Obj_t * pNode0, * pNode1;
+    int Counter;
+    // skip the CI
+    if ( Abc_ObjIsCi(pNode) )
+        return 0;
+    // process the internal node
+    pNode0 = Abc_ObjFanin0(pNode);
+    pNode1 = Abc_ObjFanin1(pNode);
+    Counter = 1;
+    if ( fReference )
+    {
+        if ( !Abc_ObjFaninC0(pNode) && pNode0->vFanouts.nSize++ == 0 )
+            Counter += Abc_NodeRefDerefStop( pNode0, fReference );
+        if ( !Abc_ObjFaninC1(pNode) && pNode1->vFanouts.nSize++ == 0 )
+            Counter += Abc_NodeRefDerefStop( pNode1, fReference );
+    }
+    else
+    {
+        assert( pNode0->vFanouts.nSize > 0 );
+        assert( pNode1->vFanouts.nSize > 0 );
+        if ( !Abc_ObjFaninC0(pNode) && --pNode0->vFanouts.nSize == 0 )
+            Counter += Abc_NodeRefDerefStop( pNode0, fReference );
+        if ( !Abc_ObjFaninC1(pNode) && --pNode1->vFanouts.nSize == 0 )
+            Counter += Abc_NodeRefDerefStop( pNode1, fReference );
+    }
+    return Counter;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences the node's MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeDeref_rec( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    int i, Counter = 1;
+    if ( Abc_ObjIsCi(pNode) )
+        return 0;
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        assert( pFanin->vFanouts.nSize > 0 );
+        if ( --pFanin->vFanouts.nSize == 0 )
+            Counter += Abc_NodeDeref_rec( pFanin );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [References the node's MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeRef_rec( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    int i, Counter = 1;
+    if ( Abc_ObjIsCi(pNode) )
+        return 0;
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        if ( pFanin->vFanouts.nSize++ == 0 )
+            Counter += Abc_NodeRef_rec( pFanin );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the internal and boundary nodes in the derefed MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeMffcConeSupp_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp, int fTopmost )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    // skip visited nodes
+    if ( Abc_NodeIsTravIdCurrent(pNode) )
+        return;
+    Abc_NodeSetTravIdCurrent(pNode);
+    // add to the new support nodes
+    if ( !fTopmost && (Abc_ObjIsCi(pNode) || pNode->vFanouts.nSize > 0) )
+    {
+        if ( vSupp ) Vec_PtrPush( vSupp, pNode );
+        return;
+    }
+    // recur on the children
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        Abc_NodeMffcConeSupp_rec( pFanin, vCone, vSupp, 0 );
+    // collect the internal node
+    if ( vCone ) Vec_PtrPush( vCone, pNode );
+//    printf( "%d ", pNode->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the support of the derefed MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeMffcConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp )
+{
+    assert( Abc_ObjIsNode(pNode) );
+    assert( !Abc_ObjIsComplement(pNode) );
+    if ( vCone ) Vec_PtrClear( vCone );
+    if ( vSupp ) Vec_PtrClear( vSupp );
+    Abc_NtkIncrementTravId( pNode->pNtk );
+    Abc_NodeMffcConeSupp_rec( pNode, vCone, vSupp, 1 );
+//    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the support of the derefed MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeMffcConeSuppPrint( Abc_Obj_t * pNode )
+{
+    Vec_Ptr_t * vCone, * vSupp;
+    Abc_Obj_t * pObj;
+    int i;
+    vCone = Vec_PtrAlloc( 100 );
+    vSupp = Vec_PtrAlloc( 100 );
+    Abc_NodeDeref_rec( pNode );
+    Abc_NodeMffcConeSupp( pNode, vCone, vSupp );
+    Abc_NodeRef_rec( pNode );
+    printf( "Node = %6s : Supp = %3d  Cone = %3d  (", 
+        Abc_ObjName(pNode), Vec_PtrSize(vSupp), Vec_PtrSize(vCone) );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, i )
+        printf( " %s", Abc_ObjName(pObj) );
+    printf( " )\n" );
+    Vec_PtrFree( vCone );
+    Vec_PtrFree( vSupp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the internal nodes of the MFFC limited by cut.]
+
+  Description []
+               
+  SideEffects [Increments the trav ID and marks visited nodes.]
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeMffcInside( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vInside )
+{
+    Abc_Obj_t * pObj;
+    int i, Count1, Count2;
+    // increment the fanout counters for the leaves
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+        pObj->vFanouts.nSize++;
+    // dereference the node
+    Count1 = Abc_NodeDeref_rec( pNode );
+    // collect the nodes inside the MFFC
+    Abc_NodeMffcConeSupp( pNode, vInside, NULL );
+    // reference it back
+    Count2 = Abc_NodeRef_rec( pNode );
+    assert( Count1 == Count2 );
+    // remove the extra counters
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+        pObj->vFanouts.nSize--;
+    return Count1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the internal nodes of the MFFC limited by cut.]
+
+  Description []
+               
+  SideEffects [Increments the trav ID and marks visited nodes.]
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NodeMffcInsideCollect( Abc_Obj_t * pNode )
+{
+    Vec_Ptr_t * vInside;
+    int Count1, Count2;
+    // dereference the node
+    Count1 = Abc_NodeDeref_rec( pNode );
+    // collect the nodes inside the MFFC
+    vInside = Vec_PtrAlloc( 10 );
+    Abc_NodeMffcConeSupp( pNode, vInside, NULL );
+    // reference it back
+    Count2 = Abc_NodeRef_rec( pNode );
+    assert( Count1 == Count2 );
+    return vInside;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the internal and boundary nodes in the derefed MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeMffcLabel_rec( Abc_Obj_t * pNode, int fTopmost )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    // add to the new support nodes
+    if ( !fTopmost && (Abc_ObjIsCi(pNode) || pNode->vFanouts.nSize > 0) )
+        return;
+    // skip visited nodes
+    if ( Abc_NodeIsTravIdCurrent(pNode) )
+        return;
+    Abc_NodeSetTravIdCurrent(pNode);
+    // recur on the children
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        Abc_NodeMffcLabel_rec( pFanin, 0 );
+    // collect the internal node
+//    printf( "%d ", pNode->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the internal nodes of the MFFC limited by cut.]
+
+  Description []
+               
+  SideEffects [Increments the trav ID and marks visited nodes.]
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeMffcLabel( Abc_Obj_t * pNode )
+{
+    int Count1, Count2;
+    // dereference the node
+    Count1 = Abc_NodeDeref_rec( pNode );
+    // collect the nodes inside the MFFC
+    Abc_NtkIncrementTravId( pNode->pNtk );
+    Abc_NodeMffcLabel_rec( pNode, 1 );
+    // reference it back
+    Count2 = Abc_NodeRef_rec( pNode );
+    assert( Count1 == Count2 );
+    return Count1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcShow.c b/abc-build/src/base/abc/abcShow.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcShow.c
@@ -0,0 +1,446 @@
+/**CFile****************************************************************
+
+  FileName    [abcShow.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Visualization procedures using DOT software and GSView.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcShow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifdef WIN32
+#include <process.h> 
+#else
+#include <unistd.h>
+#endif
+
+
+#include "abc.h"
+#include "base/main/main.h"
+#include "base/io/ioAbc.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern void Abc_ShowFile( char * FileNameDot );
+static void Abc_ShowGetFileName( char * pName, char * pBuffer );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Visualizes BDD of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeShowBdd( Abc_Obj_t * pNode )
+{
+    FILE * pFile;
+    Vec_Ptr_t * vNamesIn;
+    char FileNameDot[200];
+    char * pNameOut;
+
+    assert( Abc_NtkIsBddLogic(pNode->pNtk) );
+    // create the file name
+    Abc_ShowGetFileName( Abc_ObjName(pNode), FileNameDot );
+    // check that the file can be opened
+    if ( (pFile = fopen( FileNameDot, "w" )) == NULL )
+    {
+        fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot );
+        return;
+    }
+
+    // set the node names 
+    vNamesIn = Abc_NodeGetFaninNames( pNode );
+    pNameOut = Abc_ObjName(pNode);
+    Cudd_DumpDot( (DdManager *)pNode->pNtk->pManFunc, 1, (DdNode **)&pNode->pData, (char **)vNamesIn->pArray, &pNameOut, pFile );
+    Abc_NodeFreeNames( vNamesIn );
+    Abc_NtkCleanCopy( pNode->pNtk );
+    fclose( pFile );
+
+    // visualize the file 
+    Abc_ShowFile( FileNameDot );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Visualizes BDD of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeShowBddOne( DdManager * dd, DdNode * bFunc )
+{
+    char * FileNameDot = "temp.dot";
+    FILE * pFile;
+    if ( (pFile = fopen( FileNameDot, "w" )) == NULL )
+    {
+        fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot );
+        return;
+    }
+    Cudd_DumpDot( dd, 1, (DdNode **)&bFunc, NULL, NULL, pFile );
+    fclose( pFile );
+    Abc_ShowFile( FileNameDot );
+}
+/**Function*************************************************************
+
+  Synopsis    [Visualizes a reconvergence driven cut at the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax )
+{
+    FILE * pFile;
+    char FileNameDot[200];
+    Abc_ManCut_t * p;
+    Vec_Ptr_t * vCutSmall;
+    Vec_Ptr_t * vCutLarge;
+    Vec_Ptr_t * vInside;
+    Vec_Ptr_t * vNodesTfo;
+    Abc_Obj_t * pTemp;
+    int i;
+
+    assert( Abc_NtkIsStrash(pNode->pNtk) );
+
+    // start the cut computation manager
+    p = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, ABC_INFINITY );
+    // get the recovergence driven cut
+    vCutSmall = Abc_NodeFindCut( p, pNode, 1 );
+    // get the containing cut
+    vCutLarge = Abc_NtkManCutReadCutLarge( p );
+    // get the array for the inside nodes
+    vInside = Abc_NtkManCutReadVisited( p );
+    // get the inside nodes of the containing cone
+    Abc_NodeConeCollect( &pNode, 1, vCutLarge, vInside, 1 );
+
+    // add the nodes in the TFO 
+    vNodesTfo = Abc_NodeCollectTfoCands( p, pNode, vCutSmall, ABC_INFINITY );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodesTfo, pTemp, i )
+        Vec_PtrPushUnique( vInside, pTemp );
+
+    // create the file name
+    Abc_ShowGetFileName( Abc_ObjName(pNode), FileNameDot );
+    // check that the file can be opened
+    if ( (pFile = fopen( FileNameDot, "w" )) == NULL )
+    {
+        fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot );
+        return;
+    }
+    // add the root node to the cone (for visualization)
+    Vec_PtrPush( vCutSmall, pNode );
+    // write the DOT file
+    Io_WriteDotNtk( pNode->pNtk, vInside, vCutSmall, FileNameDot, 0, 0 );
+    // stop the cut computation manager
+    Abc_NtkManCutStop( p );
+
+    // visualize the file 
+    Abc_ShowFile( FileNameDot );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Visualizes AIG with choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkShow( Abc_Ntk_t * pNtk0, int fGateNames, int fSeq, int fUseReverse )
+{
+    FILE * pFile;
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pNode;
+    Vec_Ptr_t * vNodes;
+    int nBarBufs;
+    char FileNameDot[200];
+    int i;
+
+    assert( Abc_NtkIsStrash(pNtk0) || Abc_NtkIsLogic(pNtk0) );
+    if ( Abc_NtkIsStrash(pNtk0) && Abc_NtkGetChoiceNum(pNtk0) )
+    {
+        printf( "Temporarily visualization of AIGs with choice nodes is disabled.\n" );
+        return;
+    }
+    // create the file name
+    Abc_ShowGetFileName( pNtk0->pName, FileNameDot );
+    // check that the file can be opened
+    if ( (pFile = fopen( FileNameDot, "w" )) == NULL )
+    {
+        fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot );
+        return;
+    }
+    fclose( pFile );
+
+
+    // convert to logic SOP
+    pNtk = Abc_NtkDup( pNtk0 );
+    if ( Abc_NtkIsLogic(pNtk) && !Abc_NtkHasMapping(pNtk) )
+        Abc_NtkToSop( pNtk, 0 );
+
+    // collect all nodes in the network
+    vNodes = Vec_PtrAlloc( 100 );
+    Abc_NtkForEachObj( pNtk, pNode, i )
+        Vec_PtrPush( vNodes, pNode );
+    // write the DOT file
+    nBarBufs = pNtk->nBarBufs;
+    pNtk->nBarBufs = 0;
+    if ( fSeq )
+        Io_WriteDotSeq( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse );
+    else
+        Io_WriteDotNtk( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse );
+    pNtk->nBarBufs = nBarBufs;
+    Vec_PtrFree( vNodes );
+
+    // visualize the file 
+    Abc_ShowFile( FileNameDot );
+    Abc_NtkDelete( pNtk );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Shows the given DOT file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ShowFile( char * FileNameDot )
+{
+    FILE * pFile;
+    char * FileGeneric;
+    char FileNamePs[200];
+    char CommandDot[1000];
+    char * pDotName;
+    char * pDotNameWin = "dot.exe";
+    char * pDotNameUnix = "dot";
+    char * pGsNameWin = "gsview32.exe";
+    char * pGsNameUnix = "gv";
+    int RetValue;
+
+    // get DOT names from the resource file
+    if ( Abc_FrameReadFlag("dotwin") )
+        pDotNameWin = Abc_FrameReadFlag("dotwin");
+    if ( Abc_FrameReadFlag("dotunix") )
+        pDotNameUnix = Abc_FrameReadFlag("dotunix");
+
+#ifdef WIN32
+    pDotName = pDotNameWin;
+#else
+    pDotName = pDotNameUnix;
+#endif
+
+    // check if the input DOT file is okay
+    if ( (pFile = fopen( FileNameDot, "r" )) == NULL )
+    {
+        fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot );
+        return;
+    }
+    fclose( pFile );
+
+    // create the PostScript file name
+    FileGeneric = Extra_FileNameGeneric( FileNameDot );
+    sprintf( FileNamePs,  "%s.ps",  FileGeneric ); 
+    ABC_FREE( FileGeneric );
+
+    // generate the PostScript file using DOT
+    sprintf( CommandDot,  "%s -Tps -o %s %s", pDotName, FileNamePs, FileNameDot ); 
+    RetValue = system( CommandDot );
+    if ( RetValue == -1 )
+    {
+        fprintf( stdout, "Command \"%s\" did not succeed.\n", CommandDot );
+        return;
+    }
+    // check that the input PostScript file is okay
+    if ( (pFile = fopen( FileNamePs, "r" )) == NULL )
+    {
+        fprintf( stdout, "Cannot open intermediate file \"%s\".\n", FileNamePs );
+        return;
+    }
+    fclose( pFile ); 
+
+
+    // get GSVIEW names from the resource file
+    if ( Abc_FrameReadFlag("gsviewwin") )
+        pGsNameWin = Abc_FrameReadFlag("gsviewwin");
+    if ( Abc_FrameReadFlag("gsviewunix") )
+        pGsNameUnix = Abc_FrameReadFlag("gsviewunix");
+
+    // spawn the viewer
+#ifdef WIN32
+    _unlink( FileNameDot );
+    if ( _spawnl( _P_NOWAIT, pGsNameWin, pGsNameWin, FileNamePs, NULL ) == -1 )
+        if ( _spawnl( _P_NOWAIT, "C:\\Program Files\\Ghostgum\\gsview\\gsview32.exe", 
+            "C:\\Program Files\\Ghostgum\\gsview\\gsview32.exe", FileNamePs, NULL ) == -1 )
+        {
+            fprintf( stdout, "Cannot find \"%s\".\n", pGsNameWin );
+            return;
+        }
+#else
+    {
+        char CommandPs[1000];
+        unlink( FileNameDot );
+        sprintf( CommandPs,  "%s %s &", pGsNameUnix, FileNamePs ); 
+        if ( system( CommandPs ) == -1 )
+        {
+            fprintf( stdout, "Cannot execute \"%s\".\n", CommandPs );
+            return;
+        }
+    }
+#endif
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the DOT file name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ShowGetFileName( char * pName, char * pBuffer )
+{
+    char * pCur;
+    // creat the file name
+    sprintf( pBuffer, "%s.dot", pName );
+    // get rid of not-alpha-numeric characters
+    for ( pCur = pBuffer; *pCur; pCur++ )
+        if ( !((*pCur >= '0' && *pCur <= '9') || (*pCur >= 'a' && *pCur <= 'z') || 
+               (*pCur >= 'A' && *pCur <= 'Z') || (*pCur == '.')) )
+            *pCur = '_';
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkWriteFlopDependency( Abc_Ntk_t * pNtk, char * pFileName )
+{
+    FILE * pFile;
+    Vec_Ptr_t * vSupp;
+    Abc_Obj_t * pObj, * pTemp;
+    int i, k, Count;
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open input file %s.\n", pFileName );
+        return;
+    }
+    fprintf( pFile, "# Flop dependency for \"%s\" generated by ABC on %s\n", Abc_NtkName(pNtk), Extra_TimeStamp() );
+    fprintf( pFile, "digraph G {\n" );
+    fprintf( pFile, "  graph [splines=true overlap=false];\n" );
+    fprintf( pFile, "  size = \"7.5,10\";\n" );
+    fprintf( pFile, "  center = true;\n" );
+//    fprintf( pFile, "  edge [len=3,dir=forward];\n" );
+    fprintf( pFile, "  edge [dir=forward];\n" );
+    Abc_NtkForEachLatchInput( pNtk, pObj, i )
+    {
+        Abc_ObjFanout0( Abc_ObjFanout0(pObj) )->iTemp = i;
+        vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
+        Count = 0;
+        Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pTemp, k )
+            Count += Abc_ObjIsPi(pTemp);
+        Vec_PtrFree( vSupp );
+        fprintf( pFile, "  { rank = same; %d [label=\"%d(%d)\"]; }\n", i, i, Count );
+    }
+    Abc_NtkForEachLatchInput( pNtk, pObj, i )
+    {
+        vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
+        Count = 0;
+        Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pTemp, k )
+            if ( !Abc_ObjIsPi(pTemp) )
+                fprintf( pFile, "  %4d -> %4d\n", pTemp->iTemp, i );
+        Vec_PtrFree( vSupp );
+    }
+    fprintf( pFile, "}\n" );
+    fclose( pFile );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Visualizes AIG with choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkShowFlopDependency( Abc_Ntk_t * pNtk )
+{
+    FILE * pFile;
+    char FileNameDot[200];
+    assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) );
+    // create the file name
+    Abc_ShowGetFileName( pNtk->pName, FileNameDot );
+    // check that the file can be opened
+    if ( (pFile = fopen( FileNameDot, "w" )) == NULL )
+    {
+        fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot );
+        return;
+    }
+    fclose( pFile );
+    // write the DOT file
+    Abc_NtkWriteFlopDependency( pNtk, FileNameDot );
+    // visualize the file 
+    Abc_ShowFile( FileNameDot );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcSop.c b/abc-build/src/base/abc/abcSop.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcSop.c
@@ -0,0 +1,1322 @@
+/**CFile****************************************************************
+
+  FileName    [abcSop.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Implementation of a simple SOP representation of nodes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcSop.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/* 
+    The SOPs in this package are represented using char * strings.
+    For example, the SOP of the node: 
+
+       .names c d0 d1 MUX
+       01- 1
+       1-1 1
+
+    is the string: "01- 1\n1-1 1\n" where '\n' is a single char.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Registers the cube string with the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopRegister( Mem_Flex_t * pMan, char * pName )
+{
+    char * pRegName;
+    if ( pName == NULL ) return NULL;
+    pRegName = Mem_FlexEntryFetch( pMan, strlen(pName) + 1 );
+    strcpy( pRegName, pName );
+    return pRegName;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the constant 1 cover with the given number of variables and cubes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopStart( Mem_Flex_t * pMan, int nCubes, int nVars )
+{
+    char * pSopCover, * pCube;
+    int i, Length;
+
+    Length = nCubes * (nVars + 3);
+    pSopCover = Mem_FlexEntryFetch( pMan, Length + 1 );
+    memset( pSopCover, '-', Length );
+    pSopCover[Length] = 0;
+
+    for ( i = 0; i < nCubes; i++ )
+    {
+        pCube = pSopCover + i * (nVars + 3);
+        pCube[nVars + 0] = ' ';
+        pCube[nVars + 1] = '1';
+        pCube[nVars + 2] = '\n';
+    }
+    return pSopCover;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the constant 1 cover with 0 variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopCreateConst1( Mem_Flex_t * pMan )
+{
+    return Abc_SopRegister( pMan, " 1\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the constant 1 cover with 0 variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopCreateConst0( Mem_Flex_t * pMan )
+{
+    return Abc_SopRegister( pMan, " 0\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the AND2 cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopCreateAnd2( Mem_Flex_t * pMan, int fCompl0, int fCompl1 )
+{
+    char Buffer[6];
+    Buffer[0] = '1' - fCompl0;
+    Buffer[1] = '1' - fCompl1;
+    Buffer[2] = ' ';
+    Buffer[3] = '1';
+    Buffer[4] = '\n';
+    Buffer[5] = 0;
+    return Abc_SopRegister( pMan, Buffer );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the multi-input AND cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopCreateAnd( Mem_Flex_t * pMan, int nVars, int * pfCompl )
+{
+    char * pSop;
+    int i;
+    pSop = Abc_SopStart( pMan, 1, nVars );
+    for ( i = 0; i < nVars; i++ )
+        pSop[i] = '1' - (pfCompl? pfCompl[i] : 0);
+    pSop[nVars + 1] = '1';
+    return pSop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the multi-input NAND cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopCreateNand( Mem_Flex_t * pMan, int nVars )
+{
+    char * pSop;
+    int i;
+    pSop = Abc_SopStart( pMan, 1, nVars );
+    for ( i = 0; i < nVars; i++ )
+        pSop[i] = '1';
+    pSop[nVars + 1] = '0';
+    return pSop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the multi-input OR cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopCreateOr( Mem_Flex_t * pMan, int nVars, int * pfCompl )
+{
+    char * pSop;
+    int i;
+    pSop = Abc_SopStart( pMan, 1, nVars );
+    for ( i = 0; i < nVars; i++ )
+        pSop[i] = '0' + (pfCompl? pfCompl[i] : 0);
+    pSop[nVars + 1] = '0';
+    return pSop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the multi-input OR cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopCreateOrMultiCube( Mem_Flex_t * pMan, int nVars, int * pfCompl )
+{
+    char * pSop, * pCube;
+    int i;
+    pSop = Abc_SopStart( pMan, nVars, nVars );
+    i = 0;
+    Abc_SopForEachCube( pSop, nVars, pCube )
+    {
+        pCube[i] = '1' - (pfCompl? pfCompl[i] : 0);
+        i++;
+    }
+    return pSop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the multi-input NOR cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopCreateNor( Mem_Flex_t * pMan, int nVars )
+{
+    char * pSop;
+    int i;
+    pSop = Abc_SopStart( pMan, 1, nVars );
+    for ( i = 0; i < nVars; i++ )
+        pSop[i] = '0';
+    return pSop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the multi-input XOR cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopCreateXor( Mem_Flex_t * pMan, int nVars )
+{
+    assert( nVars == 2 );
+    return Abc_SopRegister(pMan, "01 1\n10 1\n");
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the multi-input XOR cover (special case).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopCreateXorSpecial( Mem_Flex_t * pMan, int nVars )
+{
+    char * pSop;
+    pSop = Abc_SopCreateAnd( pMan, nVars, NULL );
+    pSop[nVars+1] = 'x';
+    assert( pSop[nVars+2] == '\n' );
+    return pSop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the multi-input XNOR cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopCreateNxor( Mem_Flex_t * pMan, int nVars )
+{
+    assert( nVars == 2 );
+    return Abc_SopRegister(pMan, "11 1\n00 1\n");
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the MUX cover.]
+
+  Description [The first input of MUX is the control. The second input
+  is DATA1. The third input is DATA0.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopCreateMux( Mem_Flex_t * pMan )
+{
+    return Abc_SopRegister(pMan, "11- 1\n0-1 1\n");
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the inv cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopCreateInv( Mem_Flex_t * pMan )
+{
+    return Abc_SopRegister(pMan, "0 1\n");
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the buf cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopCreateBuf( Mem_Flex_t * pMan )
+{
+    return Abc_SopRegister(pMan, "1 1\n");
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the arbitrary cover from the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopCreateFromTruth( Mem_Flex_t * pMan, int nVars, unsigned * pTruth )
+{
+    char * pSop, * pCube;
+    int nMints, Counter, i, k;
+    // count the number of true minterms
+    Counter = 0;
+    nMints = (1 << nVars);
+    for ( i = 0; i < nMints; i++ )
+        Counter += ((pTruth[i>>5] & (1 << (i&31))) > 0);
+    // SOP is not well-defined if the truth table is constant 0
+    assert( Counter > 0 );
+    if ( Counter == 0 )
+        return NULL;
+    // start the cover
+    pSop = Abc_SopStart( pMan, Counter, nVars );
+    // create true minterms
+    Counter = 0;
+    for ( i = 0; i < nMints; i++ )
+        if ( (pTruth[i>>5] & (1 << (i&31))) > 0 )
+        {
+            pCube = pSop + Counter * (nVars + 3);
+            for ( k = 0; k < nVars; k++ )
+                pCube[k] = '0' + ((i & (1 << k)) > 0);
+            Counter++;
+        }
+    return pSop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the cover from the ISOP computed from TT.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopCreateFromIsop( Mem_Flex_t * pMan, int nVars, Vec_Int_t * vCover )
+{
+    char * pSop, * pCube;
+    int i, k, Entry, Literal;
+    assert( Vec_IntSize(vCover) > 0 );
+    if ( Vec_IntSize(vCover) == 0 )
+        return NULL;
+    // start the cover
+    pSop = Abc_SopStart( pMan, Vec_IntSize(vCover), nVars );
+    // create cubes
+    Vec_IntForEachEntry( vCover, Entry, i )
+    {
+        pCube = pSop + i * (nVars + 3);
+        for ( k = 0; k < nVars; k++ )
+        {
+            Literal = 3 & (Entry >> (k << 1));
+            if ( Literal == 1 )
+                pCube[k] = '0';
+            else if ( Literal == 2 )
+                pCube[k] = '1';
+            else if ( Literal != 0 )
+                assert( 0 );
+        }
+    }
+    return pSop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the cover from the ISOP computed from TT.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SopToIsop( char * pSop, Vec_Int_t * vCover )
+{
+    char * pCube;
+    int k, nVars, Entry;
+    nVars = Abc_SopGetVarNum( pSop );
+    assert( nVars > 0 );
+    // create cubes
+    Vec_IntClear( vCover );
+    for ( pCube = pSop; *pCube; pCube += nVars + 3 )
+    {
+        Entry = 0;
+        for ( k = nVars - 1; k >= 0; k-- )
+            if ( pCube[k] == '0' )
+                Entry = (Entry << 2) | 1;
+            else if ( pCube[k] == '1' )
+                Entry = (Entry << 2) | 2;
+            else if ( pCube[k] == '-' )
+                Entry = (Entry << 2);
+            else 
+                assert( 0 );
+        Vec_IntPush( vCover, Entry );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the number of cubes in the cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SopGetCubeNum( char * pSop )
+{
+    char * pCur;
+    int nCubes = 0;
+    if ( pSop == NULL )
+        return 0;
+    for ( pCur = pSop; *pCur; pCur++ )
+        nCubes += (*pCur == '\n');
+    return nCubes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the number of SOP literals in the cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SopGetLitNum( char * pSop )
+{
+    char * pCur;
+    int nLits = 0;
+    if ( pSop == NULL )
+        return 0;
+    for ( pCur = pSop; *pCur; pCur++ )
+    {
+        nLits  -= (*pCur == '\n');
+        nLits  += (*pCur == '0' || *pCur == '1');
+    }
+    return nLits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the number of variables in the cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SopGetVarNum( char * pSop )
+{
+    char * pCur;
+    for ( pCur = pSop; *pCur != '\n'; pCur++ )
+        if ( *pCur == 0 )
+            return -1;
+    return pCur - pSop - 2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the phase of the cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SopGetPhase( char * pSop )
+{
+    int nVars = Abc_SopGetVarNum( pSop );
+    if ( pSop[nVars+1] == '0' || pSop[nVars+1] == 'n' )
+        return 0;
+    if ( pSop[nVars+1] == '1' || pSop[nVars+1] == 'x' )
+        return 1;
+    assert( 0 );
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the i-th literal of the cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SopGetIthCareLit( char * pSop, int i )
+{
+    char * pCube;
+    int nVars;
+    nVars = Abc_SopGetVarNum( pSop );
+    Abc_SopForEachCube( pSop, nVars, pCube )
+        if ( pCube[i] != '-' )
+            return pCube[i] - '0';
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SopComplement( char * pSop )
+{
+    char * pCur;
+    for ( pCur = pSop; *pCur; pCur++ )
+        if ( *pCur == '\n' )
+        {
+            if ( *(pCur - 1) == '0' )
+                *(pCur - 1) = '1';
+            else if ( *(pCur - 1) == '1' )
+                *(pCur - 1) = '0';
+            else if ( *(pCur - 1) == 'x' )
+                *(pCur - 1) = 'n';
+            else if ( *(pCur - 1) == 'n' )
+                *(pCur - 1) = 'x';
+            else
+                assert( 0 );
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SopComplementVar( char * pSop, int iVar )
+{
+    char * pCube;
+    int nVars = Abc_SopGetVarNum(pSop);
+    assert( iVar < nVars );
+    Abc_SopForEachCube( pSop, nVars, pCube )
+    {
+        if ( pCube[iVar] == '0' )
+            pCube[iVar] = '1';
+        else if ( pCube[iVar] == '1' )
+            pCube[iVar] = '0';
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SopIsComplement( char * pSop )
+{
+    char * pCur;
+    for ( pCur = pSop; *pCur; pCur++ )
+        if ( *pCur == '\n' )
+            return (int)(*(pCur - 1) == '0' || *(pCur - 1) == 'n');
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the cover is constant 0.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SopIsConst0( char * pSop )
+{
+    return pSop[0] == ' ' && pSop[1] == '0';
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the cover is constant 1.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SopIsConst1( char * pSop )
+{
+    return pSop[0] == ' ' && pSop[1] == '1';
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the cover is constant 1.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SopIsBuf( char * pSop )
+{
+    if ( pSop[4] != 0 )
+        return 0;
+    if ( (pSop[0] == '1' && pSop[2] == '1') || (pSop[0] == '0' && pSop[2] == '0') )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the cover is constant 1.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SopIsInv( char * pSop )
+{
+    if ( pSop[4] != 0 )
+        return 0;
+    if ( (pSop[0] == '0' && pSop[2] == '1') || (pSop[0] == '1' && pSop[2] == '0') )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the cover is AND with possibly complemented inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SopIsAndType( char * pSop )
+{
+    char * pCur;
+    if ( Abc_SopGetCubeNum(pSop) != 1 )
+        return 0;
+    for ( pCur = pSop; *pCur != ' '; pCur++ )
+        if ( *pCur == '-' )
+            return 0;
+    if ( pCur[1] != '1' )
+        return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the cover is OR with possibly complemented inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SopIsOrType( char * pSop )
+{
+    char * pCube, * pCur;
+    int nVars, nLits;
+    nVars = Abc_SopGetVarNum( pSop );
+    if ( nVars != Abc_SopGetCubeNum(pSop) )
+        return 0;
+    Abc_SopForEachCube( pSop, nVars, pCube )
+    {
+        // count the number of literals in the cube
+        nLits = 0;
+        for ( pCur = pCube; *pCur != ' '; pCur++ )
+            nLits += ( *pCur != '-' );
+        if ( nLits != 1 )
+            return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SopIsExorType( char * pSop )
+{
+    char * pCur;
+    for ( pCur = pSop; *pCur; pCur++ )
+        if ( *pCur == '\n' )
+            return (int)(*(pCur - 1) == 'x' || *(pCur - 1) == 'n');
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SopCheck( char * pSop, int nFanins )
+{
+    char * pCubes, * pCubesOld;
+    int fFound0 = 0, fFound1 = 0;
+
+    // check the logic function of the node
+    for ( pCubes = pSop; *pCubes; pCubes++ )
+    {
+        // get the end of the next cube
+        for ( pCubesOld = pCubes; *pCubes != ' '; pCubes++ );
+        // compare the distance
+        if ( pCubes - pCubesOld != nFanins )
+        {
+            fprintf( stdout, "Abc_SopCheck: SOP has a mismatch between its cover size (%d) and its fanin number (%d).\n",
+                (int)(ABC_PTRDIFF_T)(pCubes - pCubesOld), nFanins );
+            return 0;
+        }
+        // check the output values for this cube
+        pCubes++;
+        if ( *pCubes == '0' )
+            fFound0 = 1;
+        else if ( *pCubes == '1' )
+            fFound1 = 1;
+        else if ( *pCubes != 'x' && *pCubes != 'n' )
+        {
+            fprintf( stdout, "Abc_SopCheck: SOP has a strange character (%c) in the output part of its cube.\n", *pCubes );
+            return 0;
+        }
+        // check the last symbol (new line)
+        pCubes++;
+        if ( *pCubes != '\n' )
+        {
+            fprintf( stdout, "Abc_SopCheck: SOP has a cube without new line in the end.\n" );
+            return 0;
+        }
+    }
+    if ( fFound0 && fFound1 )
+    {
+        fprintf( stdout, "Abc_SopCheck: SOP has cubes in both phases.\n" );
+        return 0;
+    }
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives SOP from the truth table representation.]
+
+  Description [Truth table is expected to be in the hexadecimal notation.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopFromTruthBin( char * pTruth )
+{
+    char * pSopCover, * pCube;
+    int nTruthSize, nVars, Digit, Length, Mint, i, b;
+    Vec_Int_t * vMints;
+
+    // get the number of variables
+    nTruthSize = strlen(pTruth);
+    nVars = Abc_Base2Log( nTruthSize );
+    if ( nTruthSize != (1 << (nVars)) )
+    {
+        printf( "String %s does not look like a truth table of a %d-variable function.\n", pTruth, nVars );
+        return NULL;
+    }
+
+    // collect the on-set minterms
+    vMints = Vec_IntAlloc( 100 );
+    for ( i = 0; i < nTruthSize; i++ )
+    {
+        if ( pTruth[i] >= '0' && pTruth[i] <= '1' )
+            Digit = pTruth[i] - '0';
+        else
+        {
+            Vec_IntFree( vMints );
+            printf( "String %s does not look like a binary representation of the truth table.\n", pTruth );
+            return NULL;
+        }
+        if ( Digit == 1 )
+            Vec_IntPush( vMints, nTruthSize - 1 - i );
+    }
+    if ( Vec_IntSize( vMints ) == 0 || Vec_IntSize( vMints ) == nTruthSize )
+    {
+        Vec_IntFree( vMints );
+        printf( "Cannot create constant function.\n" );
+        return NULL;
+    }
+
+    // create the SOP representation of the minterms
+    Length = Vec_IntSize(vMints) * (nVars + 3);
+    pSopCover = ABC_ALLOC( char, Length + 1 );
+    pSopCover[Length] = 0;
+    Vec_IntForEachEntry( vMints, Mint, i )
+    {
+        pCube = pSopCover + i * (nVars + 3);
+        for ( b = 0; b < nVars; b++ )
+            if ( Mint & (1 << (nVars-1-b)) )
+//            if ( Mint & (1 << b) )
+                pCube[b] = '1';
+            else
+                pCube[b] = '0';
+        pCube[nVars + 0] = ' ';
+        pCube[nVars + 1] = '1';
+        pCube[nVars + 2] = '\n';
+    }
+    Vec_IntFree( vMints );
+    return pSopCover;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives SOP from the truth table representation.]
+
+  Description [Truth table is expected to be in the hexadecimal notation.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopFromTruthHex( char * pTruth )
+{
+    char * pSopCover, * pCube;
+    int nTruthSize, nVars, Digit, Length, Mint, i, b;
+    Vec_Int_t * vMints;
+
+    // get the number of variables
+    nTruthSize = strlen(pTruth);
+    nVars = (nTruthSize < 2) ? 2 : Abc_Base2Log(nTruthSize) + 2;
+    if ( nTruthSize != (1 << (nVars-2)) )
+    {
+        printf( "String %s does not look like a truth table of a %d-variable function.\n", pTruth, nVars );
+        return NULL;
+    }
+
+    // collect the on-set minterms
+    vMints = Vec_IntAlloc( 100 );
+    for ( i = 0; i < nTruthSize; i++ )
+    {
+        if ( pTruth[i] >= '0' && pTruth[i] <= '9' )
+            Digit = pTruth[i] - '0';
+        else if ( pTruth[i] >= 'a' && pTruth[i] <= 'f' )
+            Digit = 10 + pTruth[i] - 'a';
+        else if ( pTruth[i] >= 'A' && pTruth[i] <= 'F' )
+            Digit = 10 + pTruth[i] - 'A';
+        else
+        {
+            printf( "String %s does not look like a hexadecimal representation of the truth table.\n", pTruth );
+            return NULL;
+        }
+        for ( b = 0; b < 4; b++ )
+            if ( Digit & (1 << b) )
+                Vec_IntPush( vMints, 4*(nTruthSize-1-i)+b );
+    }
+
+    // create the SOP representation of the minterms
+    Length = Vec_IntSize(vMints) * (nVars + 3);
+    pSopCover = ABC_ALLOC( char, Length + 1 );
+    pSopCover[Length] = 0;
+    Vec_IntForEachEntry( vMints, Mint, i )
+    {
+        pCube = pSopCover + i * (nVars + 3);
+        for ( b = 0; b < nVars; b++ )
+//            if ( Mint & (1 << (nVars-1-b)) )
+            if ( Mint & (1 << b) )
+                pCube[b] = '1';
+            else
+                pCube[b] = '0';
+        pCube[nVars + 0] = ' ';
+        pCube[nVars + 1] = '1';
+        pCube[nVars + 2] = '\n';
+    }
+/*
+    // create TT representation
+    {
+        extern void Bdc_ManDecomposeTest( unsigned uTruth, int nVars );
+        unsigned uTruth = 0;
+        int nVarsAll = 4;
+        assert( nVarsAll == 4 );
+        assert( nVars <= nVarsAll );
+        Vec_IntForEachEntry( vMints, Mint, i )
+            uTruth |= (1 << Mint);
+//        uTruth = uTruth | (uTruth << 8) | (uTruth << 16) | (uTruth << 24);
+        uTruth = uTruth | (uTruth << 16);
+        Bdc_ManDecomposeTest( uTruth, nVarsAll );
+    }
+*/
+    Vec_IntFree( vMints );
+    return pSopCover;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates one encoder node.]
+
+  Description [Produces MV-SOP for BLIF-MV representation.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopEncoderPos( Mem_Flex_t * pMan, int iValue, int nValues )
+{
+    char Buffer[32];
+    assert( iValue < nValues );
+    sprintf( Buffer, "d0\n%d 1\n", iValue );
+    return Abc_SopRegister( pMan, Buffer );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates one encoder node.]
+
+  Description [Produces MV-SOP for BLIF-MV representation.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopEncoderLog( Mem_Flex_t * pMan, int iBit, int nValues )
+{
+    char * pResult;
+    Vec_Str_t * vSop;
+    int v, Counter, fFirst = 1, nBits = Abc_Base2Log(nValues);
+    assert( iBit < nBits );
+    // count the number of literals
+    Counter = 0;
+    for ( v = 0; v < nValues; v++ )
+        Counter += ( (v & (1 << iBit)) > 0 );
+    // create the cover
+    vSop = Vec_StrAlloc( 100 );
+    Vec_StrPrintStr( vSop, "d0\n" );
+    if ( Counter > 1 )
+        Vec_StrPrintStr( vSop, "(" );
+    for ( v = 0; v < nValues; v++ )
+        if ( v & (1 << iBit) )
+        {
+            if ( fFirst )
+                fFirst = 0;
+            else
+                Vec_StrPush( vSop, ',' );
+            Vec_StrPrintNum( vSop, v );
+        }
+    if ( Counter > 1 )
+        Vec_StrPrintStr( vSop, ")" );
+    Vec_StrPrintStr( vSop, " 1\n" );
+    Vec_StrPush( vSop, 0 );
+    pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) );
+    Vec_StrFree( vSop );
+    return pResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the decoder node.]
+
+  Description [Produces MV-SOP for BLIF-MV representation.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopDecoderPos( Mem_Flex_t * pMan, int nValues )
+{
+    char * pResult;
+    Vec_Str_t * vSop;
+    int i, k;
+    assert( nValues > 1 );
+    vSop = Vec_StrAlloc( 100 );
+    for ( i = 0; i < nValues; i++ )
+    {
+        for ( k = 0; k < nValues; k++ )
+        {
+            if ( k == i )
+                Vec_StrPrintStr( vSop, "1 " );
+            else
+                Vec_StrPrintStr( vSop, "- " );
+        }
+        Vec_StrPrintNum( vSop, i );
+        Vec_StrPush( vSop, '\n' );
+    }
+    Vec_StrPush( vSop, 0 );
+    pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) );
+    Vec_StrFree( vSop );
+    return pResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the decover node.]
+
+  Description [Produces MV-SOP for BLIF-MV representation.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopDecoderLog( Mem_Flex_t * pMan, int nValues )
+{
+    char * pResult;
+    Vec_Str_t * vSop;
+    int i, b, nBits = Abc_Base2Log(nValues);
+    assert( nValues > 1 && nValues <= (1<<nBits) );
+    vSop = Vec_StrAlloc( 100 );
+    for ( i = 0; i < nValues; i++ )
+    {
+        for ( b = 0; b < nBits; b++ )
+        {
+            Vec_StrPrintNum( vSop, (int)((i & (1 << b)) > 0) );
+            Vec_StrPush( vSop, ' ' );
+        }
+        Vec_StrPrintNum( vSop, i );
+        Vec_StrPush( vSop, '\n' );
+    }
+    Vec_StrPush( vSop, 0 );
+    pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) );
+    Vec_StrFree( vSop );
+    return pResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table of the node.]
+ 
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word Abc_SopToTruth( char * pSop, int nInputs )
+{
+    static word Truth[8] = {
+        ABC_CONST(0xAAAAAAAAAAAAAAAA),
+        ABC_CONST(0xCCCCCCCCCCCCCCCC),
+        ABC_CONST(0xF0F0F0F0F0F0F0F0),
+        ABC_CONST(0xFF00FF00FF00FF00),
+        ABC_CONST(0xFFFF0000FFFF0000),
+        ABC_CONST(0xFFFFFFFF00000000),
+        ABC_CONST(0x0000000000000000),
+        ABC_CONST(0xFFFFFFFFFFFFFFFF)
+    };
+    word Cube, Result = 0;
+    int v, lit = 0;
+    int nVars = Abc_SopGetVarNum(pSop);
+    assert( nVars >= 0 && nVars <= 6 );
+    assert( nVars == nInputs );
+    do {
+        Cube = Truth[7];
+        for ( v = 0; v < nVars; v++, lit++ )
+        {
+            if ( pSop[lit] == '1' )
+                Cube &=  Truth[v];
+            else if ( pSop[lit] == '0' )
+                Cube &= ~Truth[v];
+            else if ( pSop[lit] != '-' )
+                assert( 0 );
+        }
+        Result |= Cube;
+        assert( pSop[lit] == ' ' );
+        lit++;
+        lit++;
+        assert( pSop[lit] == '\n' );
+        lit++;
+    } while ( pSop[lit] );
+    if ( Abc_SopIsComplement(pSop) )
+        Result = ~Result;
+    return Result;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table of the node.]
+ 
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SopToTruth7( char * pSop, int nInputs, word r[2] )
+{
+    static word Truth[7][2] = {
+        {ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA)},
+        {ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC)},
+        {ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0)},
+        {ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00)},
+        {ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000)},
+        {ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000)},
+        {ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF)},
+    };
+    word Cube[2];
+    int v, lit = 0;
+    int nVars = Abc_SopGetVarNum(pSop);
+    assert( nVars >= 0 && nVars <= 7 );
+    assert( nVars == nInputs );
+    r[0] = r[1] = 0;
+    do {
+        Cube[0] = Cube[1] = ~(word)0;
+        for ( v = 0; v < nVars; v++, lit++ )
+        {
+            if ( pSop[lit] == '1' )
+            {
+                Cube[0] &=  Truth[v][0];
+                Cube[1] &=  Truth[v][1];
+            }
+            else if ( pSop[lit] == '0' )
+            {
+                Cube[0] &= ~Truth[v][0];
+                Cube[1] &= ~Truth[v][1];
+            }
+            else if ( pSop[lit] != '-' )
+                assert( 0 );
+        }
+        r[0] |= Cube[0];
+        r[1] |= Cube[1];
+        assert( pSop[lit] == ' ' );
+        lit++;
+        lit++;
+        assert( pSop[lit] == '\n' );
+        lit++;
+    } while ( pSop[lit] );
+    if ( Abc_SopIsComplement(pSop) )
+    {
+        r[0] = ~r[0];
+        r[1] = ~r[1];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table of the node.]
+ 
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SopToTruthBig( char * pSop, int nInputs, word ** pVars, word * pCube, word * pRes )
+{
+    int nVars = Abc_SopGetVarNum(pSop);
+    int nWords = nVars <= 6 ? 1 : 1 << (nVars-6);
+    int v, i, lit = 0;
+    assert( nVars >= 0 && nVars <= 16 );
+    assert( nVars == nInputs );
+    for ( i = 0; i < nWords; i++ )
+        pRes[i] = 0;
+    do {
+        for ( i = 0; i < nWords; i++ )
+            pCube[i] = ~(word)0;
+        for ( v = 0; v < nVars; v++, lit++ )
+        {
+            if ( pSop[lit] == '1' )
+            {
+                for ( i = 0; i < nWords; i++ )
+                    pCube[i] &= pVars[v][i];
+            }
+            else if ( pSop[lit] == '0' )
+            {
+                for ( i = 0; i < nWords; i++ )
+                    pCube[i] &= ~pVars[v][i];
+            }
+            else if ( pSop[lit] != '-' )
+                assert( 0 );
+        }
+        for ( i = 0; i < nWords; i++ )
+            pRes[i] |= pCube[i];
+        assert( pSop[lit] == ' ' );
+        lit++;
+        lit++;
+        assert( pSop[lit] == '\n' );
+        lit++;
+    } while ( pSop[lit] );
+    if ( Abc_SopIsComplement(pSop) )
+    {
+        for ( i = 0; i < nWords; i++ )
+            pRes[i] = ~pRes[i];
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abcUtil.c b/abc-build/src/base/abc/abcUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abcUtil.c
@@ -0,0 +1,2852 @@
+/**CFile****************************************************************
+
+  FileName    [abcUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Various utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "base/main/main.h"
+#include "map/mio/mio.h"
+#include "bool/dec/dec.h"
+#include "misc/extra/extraBdd.h"
+#include "opt/fxu/fxu.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Frees one attribute manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan ) 
+{  
+    void * pUserMan;
+    Vec_Att_t * pAttrMan;
+    pAttrMan = (Vec_Att_t *)Vec_PtrEntry( pNtk->vAttrs, Attr );
+    Vec_PtrWriteEntry( pNtk->vAttrs, Attr, NULL );
+    pUserMan = Vec_AttFree( pAttrMan, fFreeMan );
+    return pUserMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Order CI/COs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkOrderCisCos( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj, * pTerm;
+    int i, k;
+    Vec_PtrClear( pNtk->vCis );
+    Vec_PtrClear( pNtk->vCos );
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        Vec_PtrPush( pNtk->vCis, pObj );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        Vec_PtrPush( pNtk->vCos, pObj );
+    Abc_NtkForEachBox( pNtk, pObj, i )
+    {
+        if ( Abc_ObjIsLatch(pObj) )
+            continue;
+        Abc_ObjForEachFanin( pObj, pTerm, k )
+            Vec_PtrPush( pNtk->vCos, pTerm );
+        Abc_ObjForEachFanout( pObj, pTerm, k )
+            Vec_PtrPush( pNtk->vCis, pTerm );
+    }
+    Abc_NtkForEachBox( pNtk, pObj, i )
+    {
+        if ( !Abc_ObjIsLatch(pObj) )
+            continue;
+        Abc_ObjForEachFanin( pObj, pTerm, k )
+            Vec_PtrPush( pNtk->vCos, pTerm );
+        Abc_ObjForEachFanout( pObj, pTerm, k )
+            Vec_PtrPush( pNtk->vCis, pTerm );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the number of cubes of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, nCubes = 0;
+    assert( Abc_NtkHasSop(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        if ( Abc_NodeIsConst(pNode) )
+            continue;
+        assert( pNode->pData );
+        nCubes += Abc_SopGetCubeNum( (char *)pNode->pData );
+    }
+    return nCubes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the number of cubes of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkGetCubePairNum( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, nCubes, nCubePairs = 0;
+    assert( Abc_NtkHasSop(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        if ( Abc_NodeIsConst(pNode) )
+            continue;
+        assert( pNode->pData );
+        nCubes = Abc_SopGetCubeNum( (char *)pNode->pData );
+        nCubePairs += nCubes * (nCubes - 1) / 2;
+    }
+    return nCubePairs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the number of literals in the SOPs of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkGetLitNum( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, nLits = 0;
+    assert( Abc_NtkHasSop(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        assert( pNode->pData );
+        nLits += Abc_SopGetLitNum( (char *)pNode->pData );
+    }
+    return nLits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of literals in the factored forms.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkGetLitFactNum( Abc_Ntk_t * pNtk )
+{
+    Dec_Graph_t * pFactor;
+    Abc_Obj_t * pNode;
+    int nNodes, i;
+    assert( Abc_NtkHasSop(pNtk) );
+    nNodes = 0;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        if ( Abc_NodeIsConst(pNode) )
+            continue;
+        pFactor = Dec_Factor( (char *)pNode->pData );
+        nNodes += 1 + Dec_GraphNodeNum(pFactor);
+        Dec_GraphFree( pFactor );
+    }
+    return nNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of nodes with more than 1 reference.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkGetMultiRefNum( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int nNodes, i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    nNodes = 0;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        nNodes += (int)(Abc_ObjFanoutNum(pNode) > 1);
+    return nNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the number of BDD nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkGetBddNodeNum( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, nNodes = 0;
+    assert( Abc_NtkIsBddLogic(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        assert( pNode->pData );
+        if ( Abc_ObjFaninNum(pNode) < 2 )
+            continue;
+        nNodes += pNode->pData? -1 + Cudd_DagSize( (DdNode *)pNode->pData ) : 0;
+    }
+    return nNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the number of BDD nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkGetAigNodeNum( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, nNodes = 0;
+    assert( Abc_NtkIsAigLogic(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        assert( pNode->pData );
+        if ( Abc_ObjFaninNum(pNode) < 2 )
+            continue;
+//printf( "%d ", Hop_DagSize( pNode->pData ) );
+        nNodes += pNode->pData? Hop_DagSize( (Hop_Obj_t *)pNode->pData ) : 0;
+    }
+    return nNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the number of BDD nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkGetClauseNum( Abc_Ntk_t * pNtk )
+{
+    extern int Abc_CountZddCubes( DdManager * dd, DdNode * zCover );
+    Abc_Obj_t * pNode;
+    DdNode * bCover, * zCover, * bFunc;
+    DdManager * dd = (DdManager *)pNtk->pManFunc;
+    int i, nClauses = 0;
+    assert( Abc_NtkIsBddLogic(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        assert( pNode->pData );
+        bFunc = (DdNode *)pNode->pData;
+
+        bCover = Cudd_zddIsop( dd, bFunc, bFunc, &zCover );  
+        Cudd_Ref( bCover );
+        Cudd_Ref( zCover );
+        nClauses += Abc_CountZddCubes( dd, zCover );
+        Cudd_RecursiveDeref( dd, bCover );
+        Cudd_RecursiveDerefZdd( dd, zCover );
+
+        bCover = Cudd_zddIsop( dd, Cudd_Not(bFunc), Cudd_Not(bFunc), &zCover );  
+        Cudd_Ref( bCover );
+        Cudd_Ref( zCover );
+        nClauses += Abc_CountZddCubes( dd, zCover );
+        Cudd_RecursiveDeref( dd, bCover );
+        Cudd_RecursiveDerefZdd( dd, zCover );
+    }
+    return nClauses;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the area of the mapped circuit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+double Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    double TotalArea;
+    int i;
+    assert( Abc_NtkHasMapping(pNtk) );
+    TotalArea = 0.0;
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+//        assert( pObj->pData );
+        if ( pObj->pData == NULL )
+        {
+            printf( "Node without mapping is encountered.\n" );
+            continue;
+        }
+        TotalArea += Mio_GateReadArea( (Mio_Gate_t *)pObj->pData );
+        // assuming that twin gates follow each other
+        if ( Abc_NtkFetchTwinNode(pObj) )
+            i++;
+    }
+    return TotalArea;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of exors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, Counter = 0;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        Counter += pNode->fExor;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of exors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, Counter = 0;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        Counter += Abc_NodeIsMuxType(pNode);
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of exors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkGetBufNum( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, Counter = 0;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        Counter += (Abc_ObjFaninNum(pNode) == 1);
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if it is an AIG with choice nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, Counter;
+    if ( !Abc_NtkIsStrash(pNtk) )
+        return 0;
+    Counter = 0;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        Counter += Abc_AigNodeIsChoice( pNode );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the maximum number of fanins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, nFaninsMax = 0;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        if ( nFaninsMax < Abc_ObjFaninNum(pNode) )
+            nFaninsMax = Abc_ObjFaninNum(pNode);
+    }
+    return nFaninsMax;
+}
+int Abc_NtkGetFanoutMax( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, nFaninsMax = 0;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        if ( nFaninsMax < Abc_ObjFanoutNum(pNode) )
+            nFaninsMax = Abc_ObjFanoutNum(pNode);
+    }
+    return nFaninsMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the total number of all fanins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkGetTotalFanins( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, nFanins = 0;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        nFanins += Abc_ObjFaninNum(pNode);
+    return nFanins;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the copy field of all objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCleanCopy( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->pCopy = NULL;
+}
+void Abc_NtkCleanCopy_rec( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj; 
+    int i;
+    Abc_NtkCleanCopy( pNtk );
+    Abc_NtkForEachBox( pNtk, pObj, i )
+        Abc_NtkCleanCopy_rec( Abc_ObjModel(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the copy field of all objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCleanData( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->pData = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the copy field of all objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFillTemp( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->iTemp = -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of nodes having non-trivial copies.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCountCopy( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i, Counter = 0;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        if ( Abc_ObjIsNode(pObj) )
+            Counter += (pObj->pCopy != NULL);
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Saves copy field of the objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkSaveCopy( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vCopies;
+    Abc_Obj_t * pObj;
+    int i;
+    vCopies = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        Vec_PtrWriteEntry( vCopies, i, pObj->pCopy );
+    return vCopies;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Loads copy field of the objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkLoadCopy( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCopies )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)Vec_PtrEntry( vCopies, i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the copy field of all objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCleanNext( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->pNext = NULL;
+}
+void Abc_NtkCleanNext_rec( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj; 
+    int i;
+    Abc_NtkCleanNext( pNtk );
+    Abc_NtkForEachBox( pNtk, pObj, i )
+        Abc_NtkCleanNext_rec( Abc_ObjModel(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the copy field of all objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCleanMarkA( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->fMarkA = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the copy field of all objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCleanMarkB( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->fMarkB = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the copy field of all objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCleanMarkC( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->fMarkC = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the copy field of all objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCleanMarkAB( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->fMarkA = pObj->fMarkB = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the copy field of all objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCleanMarkABC( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->fMarkA = pObj->fMarkB = pObj->fMarkC = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the index of the given fanin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeFindFanin( Abc_Obj_t * pNode, Abc_Obj_t * pFanin )
+{
+    Abc_Obj_t * pThis;
+    int i;
+    Abc_ObjForEachFanin( pNode, pThis, i )
+        if ( pThis == pFanin )
+            return i;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the internal node has CO fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFindCoFanout( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    Abc_ObjForEachFanout( pNode, pFanout, i )
+        if ( Abc_ObjIsCo(pFanout) )
+            return pFanout;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the internal node has CO fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFindNonCoFanout( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    Abc_ObjForEachFanout( pNode, pFanout, i )
+        if ( !Abc_ObjIsCo(pFanout) )
+            return pFanout;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the internal node has CO drivers with the same name.]
+
+  Description [Checks if the internal node can borrow its name from CO fanouts. 
+  This is possible if all COs with non-complemented fanin edge pointing to this 
+  node have the same name.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanout, * pFanoutCo;
+    int i;
+    pFanoutCo = NULL;
+    Abc_ObjForEachFanout( pNode, pFanout, i )
+    {
+        if ( !Abc_ObjIsCo(pFanout) )
+            continue;
+        if ( Abc_ObjFaninC0(pFanout) )
+            continue;
+        if ( pFanoutCo == NULL )
+        {
+            assert( Abc_ObjFaninNum(pFanout) == 1 );
+            assert( Abc_ObjFanin0(pFanout) == pNode );
+            pFanoutCo = pFanout;
+            continue;
+        }
+        if ( strcmp( Abc_ObjName(pFanoutCo), Abc_ObjName(pFanout) ) ) // they have diff names
+            return NULL;
+    }
+    return pFanoutCo;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fixes the CO driver problem.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFixCoDriverProblem( Abc_Obj_t * pDriver, Abc_Obj_t * pNodeCo, int fDuplicate )
+{
+    Abc_Ntk_t * pNtk = pDriver->pNtk;
+    Abc_Obj_t * pDriverNew, * pFanin;
+    int k;
+    if ( fDuplicate && !Abc_ObjIsCi(pDriver) )
+    {
+        pDriverNew = Abc_NtkDupObj( pNtk, pDriver, 0 ); 
+        Abc_ObjForEachFanin( pDriver, pFanin, k )
+            Abc_ObjAddFanin( pDriverNew, pFanin );
+        if ( Abc_ObjFaninC0(pNodeCo) )
+        {
+            // change polarity of the duplicated driver
+            Abc_NodeComplement( pDriverNew );
+            Abc_ObjXorFaninC( pNodeCo, 0 );
+        }
+    }
+    else
+    {
+        // add inverters and buffers when necessary
+        if ( Abc_ObjFaninC0(pNodeCo) )
+        {
+            pDriverNew = Abc_NtkCreateNodeInv( pNtk, pDriver );
+            Abc_ObjXorFaninC( pNodeCo, 0 );
+        }
+        else
+            pDriverNew = Abc_NtkCreateNodeBuf( pNtk, pDriver );        
+    }
+    // update the fanin of the PO node
+    Abc_ObjPatchFanin( pNodeCo, pDriver, pDriverNew );
+    assert( Abc_ObjFanoutNum(pDriverNew) == 1 );
+    // remove the old driver if it dangles
+    // (this happens when the duplicated driver had only one complemented fanout)
+    if ( Abc_ObjFanoutNum(pDriver) == 0 )
+        Abc_NtkDeleteObj( pDriver );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if COs of a logic network are simple.]
+
+  Description [The COs of a logic network are simple under three conditions:
+  (1) The edge from CO to its driver is not complemented.
+  (2) If CI is a driver of a CO, they have the same name.]
+  (3) If two COs share the same driver, they have the same name.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode, * pDriver;
+    int i;
+    assert( Abc_NtkIsLogic(pNtk) );
+    Abc_NtkIncrementTravId( pNtk );
+    Abc_NtkForEachCo( pNtk, pNode, i ) 
+    {
+        // if the driver is complemented, this is an error
+        pDriver = Abc_ObjFanin0(pNode);
+        if ( Abc_ObjFaninC0(pNode) )
+            return 0;
+        // if the driver is a CI and has different name, this is an error
+        if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) )
+            return 0;
+        // if the driver is visited for the first time, remember the CO name
+        if ( !Abc_NodeIsTravIdCurrent(pDriver) )
+        {
+            pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode);
+            Abc_NodeSetTravIdCurrent(pDriver);
+            continue;
+        }
+        // the driver has second CO - if they have different name, this is an error
+        if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names
+            return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the network to have simple COs.]
+
+  Description [The COs of a logic network are simple under three conditions:
+  (1) The edge from CO to its driver is not complemented.
+  (2) If CI is a driver of a CO, they have the same name.]
+  (3) If two COs share the same driver, they have the same name.
+  In some cases, such as FPGA mapping, we prevent the increase in delay
+  by duplicating the driver nodes, rather than adding invs/bufs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkLogicMakeSimpleCos2( Abc_Ntk_t * pNtk, int fDuplicate )
+{
+    Abc_Obj_t * pNode, * pDriver;
+    int i, nDupGates = 0;
+    assert( Abc_NtkIsLogic(pNtk) );
+    Abc_NtkIncrementTravId( pNtk );
+    Abc_NtkForEachCo( pNtk, pNode, i ) 
+    {
+        // if the driver is complemented, this is an error
+        pDriver = Abc_ObjFanin0(pNode);
+        if ( Abc_ObjFaninC0(pNode) )
+        {
+            Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate );
+            nDupGates++;
+            continue;
+        }
+        // if the driver is a CI and has different name, this is an error
+        if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) )
+        {
+            Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate );
+            nDupGates++;
+            continue;
+        }
+        // if the driver is visited for the first time, remember the CO name
+        if ( !Abc_NodeIsTravIdCurrent(pDriver) )
+        {
+            pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode);
+            Abc_NodeSetTravIdCurrent(pDriver);
+            continue;
+        }
+        // the driver has second CO - if they have different name, this is an error
+        if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names
+        {
+            Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate );
+            nDupGates++;
+            continue;
+        }
+    }
+    assert( Abc_NtkLogicHasSimpleCos(pNtk) );
+    return nDupGates;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the network to have simple COs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, int fDuplicate )
+{
+    Vec_Ptr_t * vDrivers, * vCoTerms;
+    Abc_Obj_t * pNode, * pDriver, * pDriverNew, * pFanin;
+    int i, k, LevelMax, nTotal = 0;
+    assert( Abc_NtkIsLogic(pNtk) );
+    LevelMax = Abc_NtkLevel(pNtk);
+
+    // fix constant drivers
+    Abc_NtkForEachCo( pNtk, pNode, i ) 
+    {
+        pDriver = Abc_ObjFanin0(pNode);
+        if ( !Abc_NodeIsConst(pDriver) )
+            continue;
+        pDriverNew = (Abc_ObjFaninC0(pNode) == Abc_NodeIsConst0(pDriver)) ? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk);
+        if ( Abc_ObjFaninC0(pNode) )
+            Abc_ObjXorFaninC( pNode, 0 );
+        Abc_ObjPatchFanin( pNode, pDriver, pDriverNew );
+        if ( Abc_ObjFanoutNum(pDriver) == 0 )
+            Abc_NtkDeleteObj( pDriver );
+    }
+
+    // collect drivers pointed by complemented edges
+    vDrivers = Vec_PtrAlloc( 100 );
+    Abc_NtkIncrementTravId( pNtk );
+    Abc_NtkForEachCo( pNtk, pNode, i ) 
+    {
+        if ( !Abc_ObjFaninC0(pNode) )
+            continue;
+        pDriver = Abc_ObjFanin0(pNode);
+        if ( Abc_NodeIsTravIdCurrent(pDriver) )
+            continue;
+        Abc_NodeSetTravIdCurrent(pDriver);
+        Vec_PtrPush( vDrivers, pDriver );
+    }
+    // fix complemented drivers
+    if ( Vec_PtrSize(vDrivers) > 0 )
+    {
+        int nDupGates = 0, nDupInvs = 0, nDupChange = 0;
+        Vec_Ptr_t * vFanouts = Vec_PtrAlloc( 100 );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vDrivers, pDriver, i )
+        {
+            int fHasDir = 0, fHasInv = 0, fHasOther = 0;
+            Abc_ObjForEachFanout( pDriver, pNode, k )
+            {
+                if ( !Abc_ObjIsCo(pNode) )
+                {
+                    assert( !Abc_ObjFaninC0(pNode) );
+                    fHasOther = 1;
+                    continue;
+                }
+                if ( Abc_ObjFaninC0(pNode) )
+                    fHasInv = 1;
+                else //if ( Abc_ObjFaninC0(pNode) )
+                    fHasDir = 1;
+            }
+            assert( fHasInv );
+            if ( Abc_ObjIsCi(pDriver) || fHasDir || (fHasOther && Abc_NtkHasMapping(pNtk)) ) // cannot change
+            {
+                // duplicate if critical
+                if ( fDuplicate && Abc_ObjIsNode(pDriver) && Abc_ObjLevel(pDriver) == LevelMax )
+                {
+                    pDriverNew = Abc_NtkDupObj( pNtk, pDriver, 0 ); 
+                    Abc_ObjForEachFanin( pDriver, pFanin, k )
+                        Abc_ObjAddFanin( pDriverNew, pFanin );
+                    Abc_NodeComplement( pDriverNew );
+                    nDupGates++;
+                }
+                else // add inverter
+                {
+                    pDriverNew = Abc_NtkCreateNodeInv( pNtk, pDriver );
+                    nDupInvs++;
+                }
+                // collect CO fanouts to be redirected to the new node
+                Vec_PtrClear( vFanouts );
+                Abc_ObjForEachFanout( pDriver, pNode, k )
+                    if ( Abc_ObjIsCo(pNode) && Abc_ObjFaninC0(pNode) )
+                        Vec_PtrPush( vFanouts, pNode );
+                assert( Vec_PtrSize(vFanouts) > 0 );
+                Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pNode, k )
+                {
+                    Abc_ObjXorFaninC( pNode, 0 );
+                    Abc_ObjPatchFanin( pNode, pDriver, pDriverNew );
+                    assert( Abc_ObjIsCi(pDriver) || Abc_ObjFanoutNum(pDriver) > 0 );
+                }
+            }
+            else // can change
+            {
+                // change polarity of the driver
+                assert( Abc_ObjIsNode(pDriver) );
+                Abc_NodeComplement( pDriver );
+                Abc_ObjForEachFanout( pDriver, pNode, k )
+                {
+                    if ( Abc_ObjIsCo(pNode) )
+                    {
+                        assert( Abc_ObjFaninC0(pNode) );
+                        Abc_ObjXorFaninC( pNode, 0 );
+                    }
+                    else if ( Abc_ObjIsNode(pNode) )
+                        Abc_NodeComplementInput( pNode, pDriver );
+                    else assert( 0 );
+                }
+                nDupChange++;
+            }
+        }
+        Vec_PtrFree( vFanouts );
+//        printf( "Resolving inverted CO drivers: Invs = %d. Dups = %d. Changes = %d.\n",
+//            nDupInvs, nDupGates, nDupChange );
+        nTotal += nDupInvs + nDupGates;
+    }
+    Vec_PtrFree( vDrivers );
+
+    // collect COs that needs fixing by adding buffers or duplicating
+    vCoTerms = Vec_PtrAlloc( 100 );
+    Abc_NtkIncrementTravId( pNtk );
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        // if the driver is a CI and has different name, this is an error
+        pDriver = Abc_ObjFanin0(pNode);
+        if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) )
+        {
+            Vec_PtrPush( vCoTerms, pNode );
+            continue;
+        }
+        // if the driver is visited for the first time, remember the CO name
+        if ( !Abc_NodeIsTravIdCurrent(pDriver) )
+        {
+            pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode);
+            Abc_NodeSetTravIdCurrent(pDriver);
+            continue;
+        }
+        // the driver has second CO - if they have different name, this is an error
+        if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names
+        {
+            Vec_PtrPush( vCoTerms, pNode );
+            continue;
+        }
+    }
+    // fix duplication problem
+    if ( Vec_PtrSize(vCoTerms) > 0 )
+    {
+        int nDupBufs = 0, nDupGates = 0;
+        Vec_PtrForEachEntry( Abc_Obj_t *, vCoTerms, pNode, i )
+        {
+            pDriver = Abc_ObjFanin0(pNode);
+            // duplicate if critical
+            if ( fDuplicate && Abc_ObjIsNode(pDriver) && Abc_ObjLevel(pDriver) == LevelMax )
+            {
+                pDriverNew = Abc_NtkDupObj( pNtk, pDriver, 0 ); 
+                Abc_ObjForEachFanin( pDriver, pFanin, k )
+                    Abc_ObjAddFanin( pDriverNew, pFanin );
+                nDupGates++;
+            }
+            else // add buffer
+            {
+                pDriverNew = Abc_NtkCreateNodeBuf( pNtk, pDriver );
+                nDupBufs++;
+            }
+            // swing the PO
+            Abc_ObjPatchFanin( pNode, pDriver, pDriverNew );
+            assert( Abc_ObjIsCi(pDriver) || Abc_ObjFanoutNum(pDriver) > 0 );
+        }
+//        printf( "Resolving shared CO drivers: Bufs = %d. Dups = %d.\n", nDupBufs, nDupGates );
+        nTotal += nDupBufs + nDupGates;
+    }
+    Vec_PtrFree( vCoTerms );
+    return nTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts a new node in the order by levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pNode1, * pNode2;
+    int i;
+    if ( Vec_PtrPushUnique(p, pNode) )
+        return;
+    // find the p of the node
+    for ( i = p->nSize-1; i > 0; i-- )
+    {
+        pNode1 = (Abc_Obj_t *)p->pArray[i  ];
+        pNode2 = (Abc_Obj_t *)p->pArray[i-1];
+        if ( Abc_ObjRegular(pNode1)->Level <= Abc_ObjRegular(pNode2)->Level )
+            break;
+        p->pArray[i  ] = pNode2;
+        p->pArray[i-1] = pNode1;
+    }
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node is the root of EXOR/NEXOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeIsExorType( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pNode0, * pNode1;
+    // check that the node is regular
+    assert( !Abc_ObjIsComplement(pNode) );
+    // if the node is not AND, this is not EXOR
+    if ( !Abc_AigNodeIsAnd(pNode) )
+        return 0;
+    // if the children are not complemented, this is not EXOR
+    if ( !Abc_ObjFaninC0(pNode) || !Abc_ObjFaninC1(pNode) )
+        return 0;
+    // get children
+    pNode0 = Abc_ObjFanin0(pNode);
+    pNode1 = Abc_ObjFanin1(pNode);
+    // if the children are not ANDs, this is not EXOR
+    if ( Abc_ObjFaninNum(pNode0) != 2 || Abc_ObjFaninNum(pNode1) != 2 )
+        return 0;
+    // this is AIG, which means the fanins should be ordered
+    assert( Abc_ObjFaninId0(pNode0) != Abc_ObjFaninId1(pNode1) || 
+            Abc_ObjFaninId0(pNode1) != Abc_ObjFaninId1(pNode0) );
+    // if grand children are not the same, this is not EXOR
+    if ( Abc_ObjFaninId0(pNode0) != Abc_ObjFaninId0(pNode1) ||
+         Abc_ObjFaninId1(pNode0) != Abc_ObjFaninId1(pNode1) )
+         return 0;
+    // finally, if the complemented edges are matched, this is not EXOR
+    if ( Abc_ObjFaninC0(pNode0) == Abc_ObjFaninC0(pNode1) || 
+         Abc_ObjFaninC1(pNode0) == Abc_ObjFaninC1(pNode1) )
+         return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node is the root of MUX or EXOR/NEXOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeIsMuxType( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pNode0, * pNode1;
+    // check that the node is regular
+    assert( !Abc_ObjIsComplement(pNode) );
+    // if the node is not AND, this is not MUX
+    if ( !Abc_AigNodeIsAnd(pNode) )
+        return 0;
+    // if the children are not complemented, this is not MUX
+    if ( !Abc_ObjFaninC0(pNode) || !Abc_ObjFaninC1(pNode) )
+        return 0;
+    // get children
+    pNode0 = Abc_ObjFanin0(pNode);
+    pNode1 = Abc_ObjFanin1(pNode);
+    // if the children are not ANDs, this is not MUX
+    if ( !Abc_AigNodeIsAnd(pNode0) || !Abc_AigNodeIsAnd(pNode1) )
+        return 0;
+    // otherwise the node is MUX iff it has a pair of equal grandchildren with opposite polarity
+    return (Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC0(pNode1))) || 
+           (Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC1(pNode1))) ||
+           (Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC0(pNode1))) ||
+           (Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC1(pNode1)));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node is the root of MUX or EXOR/NEXOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCountMuxes( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    int Counter = 0;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        Counter += Abc_NodeIsMuxType( pNode );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node is the control type of the MUX.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeIsMuxControlType( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pNode0, * pNode1;
+    // check that the node is regular
+    assert( !Abc_ObjIsComplement(pNode) );
+    // skip the node that do not have two fanouts
+    if ( Abc_ObjFanoutNum(pNode) != 2 )
+        return 0;
+    // get the fanouts
+    pNode0 = Abc_ObjFanout( pNode, 0 );
+    pNode1 = Abc_ObjFanout( pNode, 1 );
+    // if they have more than one fanout, we are not interested
+    if ( Abc_ObjFanoutNum(pNode0) != 1 ||  Abc_ObjFanoutNum(pNode1) != 1 )
+        return 0;
+    // if the fanouts have the same fanout, this is MUX or EXOR (or a redundant gate (CA)(CB))
+    return Abc_ObjFanout0(pNode0) == Abc_ObjFanout0(pNode1);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recognizes what nodes are control and data inputs of a MUX.]
+
+  Description [If the node is a MUX, returns the control variable C.
+  Assigns nodes T and E to be the then and else variables of the MUX. 
+  Node C is never complemented. Nodes T and E can be complemented.
+  This function also recognizes EXOR/NEXOR gates as MUXes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeRecognizeMux( Abc_Obj_t * pNode, Abc_Obj_t ** ppNodeT, Abc_Obj_t ** ppNodeE )
+{
+    Abc_Obj_t * pNode0, * pNode1;
+    assert( !Abc_ObjIsComplement(pNode) );
+    assert( Abc_NodeIsMuxType(pNode) );
+    // get children
+    pNode0 = Abc_ObjFanin0(pNode);
+    pNode1 = Abc_ObjFanin1(pNode);
+    // find the control variable
+//    if ( pNode1->p1 == Fraig_Not(pNode2->p1) )
+    if ( Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC0(pNode1)) )
+    {
+//        if ( Fraig_IsComplement(pNode1->p1) )
+        if ( Abc_ObjFaninC0(pNode0) )
+        { // pNode2->p1 is positive phase of C
+            *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2);
+            *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2);
+            return Abc_ObjChild0(pNode1);//pNode2->p1;
+        }
+        else
+        { // pNode1->p1 is positive phase of C
+            *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2);
+            *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2);
+            return Abc_ObjChild0(pNode0);//pNode1->p1;
+        }
+    }
+//    else if ( pNode1->p1 == Fraig_Not(pNode2->p2) )
+    else if ( Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC1(pNode1)) )
+    {
+//        if ( Fraig_IsComplement(pNode1->p1) )
+        if ( Abc_ObjFaninC0(pNode0) )
+        { // pNode2->p2 is positive phase of C
+            *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1);
+            *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2);
+            return Abc_ObjChild1(pNode1);//pNode2->p2;
+        }
+        else
+        { // pNode1->p1 is positive phase of C
+            *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2);
+            *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1);
+            return Abc_ObjChild0(pNode0);//pNode1->p1;
+        }
+    }
+//    else if ( pNode1->p2 == Fraig_Not(pNode2->p1) )
+    else if ( Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC0(pNode1)) )
+    {
+//        if ( Fraig_IsComplement(pNode1->p2) )
+        if ( Abc_ObjFaninC1(pNode0) )
+        { // pNode2->p1 is positive phase of C
+            *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2);
+            *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1);
+            return Abc_ObjChild0(pNode1);//pNode2->p1;
+        }
+        else
+        { // pNode1->p2 is positive phase of C
+            *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1);
+            *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2);
+            return Abc_ObjChild1(pNode0);//pNode1->p2;
+        }
+    }
+//    else if ( pNode1->p2 == Fraig_Not(pNode2->p2) )
+    else if ( Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC1(pNode1)) )
+    {
+//        if ( Fraig_IsComplement(pNode1->p2) )
+        if ( Abc_ObjFaninC1(pNode0) )
+        { // pNode2->p2 is positive phase of C
+            *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1);
+            *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1);
+            return Abc_ObjChild1(pNode1);//pNode2->p2;
+        }
+        else
+        { // pNode1->p2 is positive phase of C
+            *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1);
+            *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1);
+            return Abc_ObjChild1(pNode0);//pNode1->p2;
+        }
+    }
+    assert( 0 ); // this is not MUX
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares two network for a two-argument command similar to "verify".]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc, 
+    Abc_Ntk_t ** ppNtk1, Abc_Ntk_t ** ppNtk2, int * pfDelete1, int * pfDelete2 )
+{
+    int fCheck = 1;
+    FILE * pFile;
+    Abc_Ntk_t * pNtk1, * pNtk2, * pNtkTemp;
+    int util_optind = 0;
+
+    *pfDelete1 = 0;
+    *pfDelete2 = 0;
+    if ( argc == util_optind ) 
+    { // use the spec
+        if ( pNtk == NULL )
+        {
+            fprintf( pErr, "Empty current network.\n" );
+            return 0;
+        }
+        if ( pNtk->pSpec == NULL )
+        {
+            fprintf( pErr, "The external spec is not given.\n" );
+            return 0;
+        }
+        pFile = fopen( pNtk->pSpec, "r" );
+        if ( pFile == NULL )
+        {
+            fprintf( pErr, "Cannot open the external spec file \"%s\".\n", pNtk->pSpec );
+            return 0;
+        }
+        else
+            fclose( pFile );
+        pNtk1 = Abc_NtkDup(pNtk);
+        pNtk2 = Io_Read( pNtk->pSpec, Io_ReadFileType(pNtk->pSpec), fCheck, 0 );
+        if ( pNtk2 == NULL )
+            return 0;
+        *pfDelete1 = 1;
+        *pfDelete2 = 1;
+    }
+    else if ( argc == util_optind + 1 ) 
+    {
+        if ( pNtk == NULL )
+        {
+            fprintf( pErr, "Empty current network.\n" );
+            return 0;
+        }
+        pNtk1 = Abc_NtkDup(pNtk);
+        pNtk2 = Io_Read( argv[util_optind], Io_ReadFileType(argv[util_optind]), fCheck, 0 );
+        if ( pNtk2 == NULL )
+            return 0;
+        *pfDelete1 = 1;
+        *pfDelete2 = 1;
+    }
+    else if ( argc == util_optind + 2 ) 
+    {
+        pNtk1 = Io_Read( argv[util_optind], Io_ReadFileType(argv[util_optind]), fCheck, 0 );
+        if ( pNtk1 == NULL )
+            return 0;
+        pNtk2 = Io_Read( argv[util_optind+1], Io_ReadFileType(argv[util_optind+1]), fCheck, 0 );
+        if ( pNtk2 == NULL )
+        {
+            Abc_NtkDelete( pNtk1 );
+            return 0;
+        }
+        *pfDelete1 = 1;
+        *pfDelete2 = 1;
+    }
+    else
+    {
+        fprintf( pErr, "Wrong number of arguments.\n" );
+        return 0;
+    }
+
+    // make sure the networks are strashed
+    if ( !Abc_NtkIsStrash(pNtk1) )
+    {
+        pNtkTemp = Abc_NtkStrash( pNtk1, 0, 1, 0 );
+        if ( *pfDelete1 )
+            Abc_NtkDelete( pNtk1 );
+        pNtk1 = pNtkTemp;
+        *pfDelete1 = 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk2) )
+    {
+        pNtkTemp = Abc_NtkStrash( pNtk2, 0, 1, 0 );
+        if ( *pfDelete2 )
+            Abc_NtkDelete( pNtk2 );
+        pNtk2 = pNtkTemp;
+        *pfDelete2 = 1;
+    }
+
+    *ppNtk1 = pNtk1;
+    *ppNtk2 = pNtk2;
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if it is an AIG with choice nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeCollectFanins( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    Vec_PtrClear(vNodes);
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        Vec_PtrPush( vNodes, pFanin );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if it is an AIG with choice nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeCollectFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    Vec_PtrClear(vNodes);
+    Abc_ObjForEachFanout( pNode, pFanout, i )
+        Vec_PtrPush( vNodes, pFanout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects all latches in the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkCollectLatches( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vLatches;
+    Abc_Obj_t * pObj;
+    int i;
+    vLatches = Vec_PtrAlloc( 10 );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        Vec_PtrPush( vLatches, pObj );
+    return vLatches;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure used for sorting the nodes in increasing order of levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCompareLevelsIncrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 )
+{
+    int Diff = Abc_ObjRegular(*pp1)->Level - Abc_ObjRegular(*pp2)->Level;
+    if ( Diff < 0 )
+        return -1;
+    if ( Diff > 0 ) 
+        return 1;
+    Diff = Abc_ObjRegular(*pp1)->Id - Abc_ObjRegular(*pp2)->Id;
+    if ( Diff < 0 )
+        return -1;
+    if ( Diff > 0 ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure used for sorting the nodes in decreasing order of levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCompareLevelsDecrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 )
+{
+    int Diff = Abc_ObjRegular(*pp1)->Level - Abc_ObjRegular(*pp2)->Level;
+    if ( Diff > 0 )
+        return -1;
+    if ( Diff < 0 ) 
+        return 1;
+    Diff = Abc_ObjRegular(*pp1)->Id - Abc_ObjRegular(*pp2)->Id;
+    if ( Diff > 0 )
+        return -1;
+    if ( Diff < 0 ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the array of fanout counters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkFanoutCounts( Abc_Ntk_t * pNtk )
+{
+    Vec_Int_t * vFanNums;
+    Abc_Obj_t * pObj;
+    int i;
+    vFanNums = Vec_IntAlloc( 0 );
+    Vec_IntFill( vFanNums, Abc_NtkObjNumMax(pNtk), -1 );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( Abc_ObjIsCi(pObj) || Abc_ObjIsNode(pObj) )
+            Vec_IntWriteEntry( vFanNums, i, Abc_ObjFanoutNum(pObj) );
+    return vFanNums;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects all objects into one array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkCollectObjects( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNode;
+    int i;
+    vNodes = Vec_PtrAlloc( 100 );
+    Abc_NtkForEachObj( pNtk, pNode, i )
+        Vec_PtrPush( vNodes, pNode );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of CI IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkGetCiIds( Abc_Ntk_t * pNtk )
+{
+    Vec_Int_t * vCiIds;
+    Abc_Obj_t * pObj;
+    int i;
+    vCiIds = Vec_IntAlloc( Abc_NtkCiNum(pNtk) );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        Vec_IntPush( vCiIds, pObj->Id );
+    return vCiIds;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Puts the nodes into the DFS order and reassign their IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkReassignIds( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Vec_Ptr_t * vObjsNew;
+    Abc_Obj_t * pNode, * pTemp, * pConst1;
+    int i, k;
+    assert( Abc_NtkIsStrash(pNtk) );
+//printf( "Total = %d. Current = %d.\n", Abc_NtkObjNumMax(pNtk), Abc_NtkObjNum(pNtk) );
+    // start the array of objects with new IDs
+    vObjsNew = Vec_PtrAlloc( pNtk->nObjs );
+    // put constant node first
+    pConst1 = Abc_AigConst1(pNtk);
+    assert( pConst1->Id == 0 );
+    Vec_PtrPush( vObjsNew, pConst1 );
+    // put PI nodes next
+    Abc_NtkForEachPi( pNtk, pNode, i )
+    {
+        pNode->Id = Vec_PtrSize( vObjsNew );
+        Vec_PtrPush( vObjsNew, pNode );
+    }
+    // put PO nodes next
+    Abc_NtkForEachPo( pNtk, pNode, i )
+    {
+        pNode->Id = Vec_PtrSize( vObjsNew );
+        Vec_PtrPush( vObjsNew, pNode );
+    }
+    // put latches and their inputs/outputs next
+    Abc_NtkForEachBox( pNtk, pNode, i )
+    {
+        pNode->Id = Vec_PtrSize( vObjsNew );
+        Vec_PtrPush( vObjsNew, pNode );
+        Abc_ObjForEachFanin( pNode, pTemp, k )
+        {
+            pTemp->Id = Vec_PtrSize( vObjsNew );
+            Vec_PtrPush( vObjsNew, pTemp );
+        }
+        Abc_ObjForEachFanout( pNode, pTemp, k )
+        {
+            pTemp->Id = Vec_PtrSize( vObjsNew );
+            Vec_PtrPush( vObjsNew, pTemp );
+        }
+    }
+    // finally, internal nodes in the DFS order
+    vNodes = Abc_AigDfs( pNtk, 1, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( pNode == pConst1 )
+            continue;
+        pNode->Id = Vec_PtrSize( vObjsNew );
+        Vec_PtrPush( vObjsNew, pNode );
+    }
+    Vec_PtrFree( vNodes );
+    assert( Vec_PtrSize(vObjsNew) == pNtk->nObjs );
+
+    // update the fanin/fanout arrays
+    Abc_NtkForEachObj( pNtk, pNode, i )
+    {
+        Abc_ObjForEachFanin( pNode, pTemp, k )
+            pNode->vFanins.pArray[k] = pTemp->Id;
+        Abc_ObjForEachFanout( pNode, pTemp, k )
+            pNode->vFanouts.pArray[k] = pTemp->Id;
+    }
+
+    // replace the array of objs
+    Vec_PtrFree( pNtk->vObjs );
+    pNtk->vObjs = vObjsNew;
+
+    // rehash the AIG
+    Abc_AigRehash( (Abc_Aig_t *)pNtk->pManFunc );
+
+    // update the name manager!!!
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detect cases when non-trivial FF matching is possible.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDetectMatching( Abc_Ntk_t * pNtk )
+{
+/*
+    Abc_Obj_t * pLatch, * pFanin;
+    int i, nTFFs, nJKFFs;
+    nTFFs = nJKFFs = 0;
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+        pFanin = Abc_ObjFanin0(pLatch);
+        if ( Abc_ObjFaninNum(pFanin) != 2 )
+            continue;
+        if ( Abc_NodeIsExorType(pLatch) )
+        {
+            if ( Abc_ObjFanin0(Abc_ObjFanin0(pFanin)) == pLatch ||
+                 Abc_ObjFanin1(Abc_ObjFanin0(pFanin)) == pLatch )
+                 nTFFs++;
+        }
+        if ( Abc_ObjFaninNum( Abc_ObjFanin0(pFanin) ) != 2 || 
+             Abc_ObjFaninNum( Abc_ObjFanin1(pFanin) ) != 2 )
+            continue;
+
+        if ( (Abc_ObjFanin0(Abc_ObjFanin0(pFanin)) == pLatch ||
+              Abc_ObjFanin1(Abc_ObjFanin0(pFanin)) == pLatch) && 
+             (Abc_ObjFanin0(Abc_ObjFanin1(pFanin)) == pLatch ||
+              Abc_ObjFanin1(Abc_ObjFanin1(pFanin)) == pLatch) )
+        {
+            nJKFFs++;
+        }
+    }
+    printf( "D = %6d.   T = %6d.   JK = %6d.  (%6.2f %%)\n", 
+        Abc_NtkLatchNum(pNtk), nTFFs, nJKFFs, 100.0 * nJKFFs / Abc_NtkLatchNum(pNtk) );
+*/
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the pointers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ObjPointerCompare( void ** pp1, void ** pp2 )
+{
+    if ( *pp1 < *pp2 )
+        return -1;
+    if ( *pp1 > *pp2 ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adjusts the copy pointers.]
+
+  Description [This procedure assumes that the network was transformed
+  into another network, which was in turn transformed into yet another
+  network. It makes the pCopy pointers of the original network point to
+  the objects of the yet another network.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTransferCopy( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( !Abc_ObjIsNet(pObj) )
+            pObj->pCopy = pObj->pCopy? Abc_ObjCopyCond(pObj->pCopy) : NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Increaments the cut counter.]
+
+  Description [Returns 1 if it becomes equal to the ref counter.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_ObjCrossCutInc( Abc_Obj_t * pObj )
+{
+//    pObj->pCopy = (void *)(((int)pObj->pCopy)++);
+    int Value = (int)(ABC_PTRINT_T)pObj->pCopy;
+    pObj->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)(Value + 1);
+    return (int)(ABC_PTRINT_T)pObj->pCopy == Abc_ObjFanoutNum(pObj);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes cross-cut of the circuit.]
+
+  Description [Returns 1 if it is the last visit to the node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCrossCut_rec( Abc_Obj_t * pObj, int * pnCutSize, int * pnCutSizeMax )
+{
+    Abc_Obj_t * pFanin;
+    int i, nDecrem = 0;
+    int fReverse = 0;
+    if ( Abc_ObjIsCi(pObj) )
+        return 0;
+    // if visited, increment visit counter 
+    if ( Abc_NodeIsTravIdCurrent( pObj ) )
+        return Abc_ObjCrossCutInc( pObj );
+    Abc_NodeSetTravIdCurrent( pObj );
+    // visit the fanins
+    if ( !Abc_ObjIsCi(pObj) )
+    {
+        if ( fReverse )
+        {
+            Abc_ObjForEachFanin( pObj, pFanin, i )
+            {
+                pFanin = Abc_ObjFanin( pObj, Abc_ObjFaninNum(pObj) - 1 - i );
+                nDecrem += Abc_NtkCrossCut_rec( pFanin, pnCutSize, pnCutSizeMax );
+            }
+        }
+        else
+        {
+            Abc_ObjForEachFanin( pObj, pFanin, i )
+                nDecrem += Abc_NtkCrossCut_rec( pFanin, pnCutSize, pnCutSizeMax );
+        }
+    }
+    // count the node
+    (*pnCutSize)++;
+    if ( *pnCutSizeMax < *pnCutSize )
+        *pnCutSizeMax = *pnCutSize;
+    (*pnCutSize) -= nDecrem;
+    return Abc_ObjCrossCutInc( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes cross-cut of the circuit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCrossCut( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int nCutSize = 0, nCutSizeMax = 0;
+    int i;
+    Abc_NtkCleanCopy( pNtk );
+    Abc_NtkIncrementTravId( pNtk );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        Abc_NtkCrossCut_rec( pObj, &nCutSize, &nCutSizeMax );
+        nCutSize--;
+    }
+    assert( nCutSize == 0 );
+    printf( "Max cross cut size = %6d.  Ratio = %6.2f %%\n", nCutSizeMax, 100.0 * nCutSizeMax/Abc_NtkObjNum(pNtk) );
+    return nCutSizeMax;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints all 3-var functions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrint256()
+{
+    FILE * pFile;
+    unsigned i;
+    pFile = fopen( "4varfs.txt", "w" );
+    for ( i = 1; i < (1<<16)-1; i++ )
+    {
+        fprintf( pFile, "read_truth " );
+        Extra_PrintBinary( pFile, &i, 16 );
+        fprintf( pFile, "; clp; st; w 1.blif; map; cec 1.blif\n" );
+    }
+    fclose( pFile );
+}
+
+
+static     int * pSupps;
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the supergates by their level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCompareConesCompare( int * pNum1, int * pNum2 )
+{
+    if ( pSupps[*pNum1] > pSupps[*pNum2] )
+        return -1;
+    if ( pSupps[*pNum1] < pSupps[*pNum2] )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Analyze choice node support.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCompareCones( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vSupp, * vNodes, * vReverse;
+    Abc_Obj_t * pObj, * pTemp;
+    int Iter, i, k, Counter, CounterCos, CounterCosNew;
+    int * pPerms;
+
+    // sort COs by support size
+    pPerms = ABC_ALLOC( int, Abc_NtkCoNum(pNtk) );
+    pSupps = ABC_ALLOC( int, Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        pPerms[i] = i;
+        vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
+        pSupps[i] = Vec_PtrSize(vSupp);
+        Vec_PtrFree( vSupp );
+    }
+    qsort( (void *)pPerms, Abc_NtkCoNum(pNtk), sizeof(int), (int (*)(const void *, const void *)) Abc_NtkCompareConesCompare );
+
+    // consider COs in this order
+    Iter = 0;
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        pObj = Abc_NtkCo( pNtk, pPerms[i] );
+        if ( pObj->fMarkA )
+            continue;
+        Iter++;
+
+        vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
+        vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 );
+        vReverse = Abc_NtkDfsReverseNodesContained( pNtk, (Abc_Obj_t **)Vec_PtrArray(vSupp), Vec_PtrSize(vSupp) );
+        // count the number of nodes in the reverse cone
+        Counter = 0;
+        for ( k = 1; k < Vec_PtrSize(vReverse) - 1; k++ )
+            for ( pTemp = (Abc_Obj_t *)Vec_PtrEntry(vReverse, k); pTemp; pTemp = (Abc_Obj_t *)pTemp->pCopy )
+                Counter++;
+        CounterCos = CounterCosNew = 0;
+        for ( pTemp = (Abc_Obj_t *)Vec_PtrEntryLast(vReverse); pTemp; pTemp = (Abc_Obj_t *)pTemp->pCopy )
+        {
+            assert( Abc_ObjIsCo(pTemp) );
+            CounterCos++;
+            if ( pTemp->fMarkA == 0 )
+                CounterCosNew++;
+            pTemp->fMarkA = 1;
+        }
+        // print statistics
+        printf( "%4d CO %5d :  Supp = %5d.  Lev = %3d.  Cone = %5d.  Rev = %5d.  COs = %3d (%3d).\n",
+            Iter, pPerms[i], Vec_PtrSize(vSupp), Abc_ObjLevel(Abc_ObjFanin0(pObj)), Vec_PtrSize(vNodes), Counter, CounterCos, CounterCosNew );
+
+        if ( Vec_PtrSize(vSupp) < 10 )
+        {
+            // free arrays
+            Vec_PtrFree( vSupp );
+            Vec_PtrFree( vNodes );
+            Vec_PtrFree( vReverse );
+            break;
+        }
+
+        // free arrays
+        Vec_PtrFree( vSupp );
+        Vec_PtrFree( vNodes );
+        Vec_PtrFree( vReverse );
+
+    }
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        pObj->fMarkA = 0;
+
+    ABC_FREE( pPerms );
+    ABC_FREE( pSupps );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Analyze choice node support.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCompareSupports( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vSupp;
+    Abc_Obj_t * pObj, * pTemp;
+    int i, nNodesOld;
+    assert( Abc_NtkIsStrash(pNtk) );
+    Abc_AigForEachAnd( pNtk, pObj, i )
+    {
+        if ( !Abc_AigNodeIsChoice(pObj) )
+            continue;
+
+        vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
+        nNodesOld = Vec_PtrSize(vSupp);
+        Vec_PtrFree( vSupp );
+
+        for ( pTemp = (Abc_Obj_t *)pObj->pData; pTemp; pTemp = (Abc_Obj_t *)pTemp->pData )
+        {
+            vSupp = Abc_NtkNodeSupport( pNtk, &pTemp, 1 );
+            if ( nNodesOld != Vec_PtrSize(vSupp) )
+                printf( "Choice orig = %3d  Choice new = %3d\n", nNodesOld, Vec_PtrSize(vSupp) );
+            Vec_PtrFree( vSupp );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Complements the constraint outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkInvertConstraints( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    if ( Abc_NtkConstrNum(pNtk) == 0 )
+        return;
+    Abc_NtkForEachPo( pNtk, pObj, i )
+    {
+        if ( i >= Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk) )
+            Abc_ObjXorFaninC( pObj, 0 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintCiLevels( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        printf( "%c=%d ", 'a'+i, pObj->Level );
+    printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if all other fanouts of pFanin are below pNode.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkAddBuffsEval( Abc_Obj_t * pNode, Abc_Obj_t * pFanin )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    Abc_ObjForEachFanout( pFanin, pFanout, i )
+        if ( pFanout != pNode && pFanout->Level >= pNode->Level )
+            return 0;
+    return 1;
+}
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if there exist a fanout of pFanin higher than pNode.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkAddBuffsEval2( Abc_Obj_t * pNode, Abc_Obj_t * pFanin )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    Abc_ObjForEachFanout( pFanin, pFanout, i )
+        if ( pFanout != pNode && pFanout->Level > pNode->Level )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkAddBuffsOne( Vec_Ptr_t * vBuffs, Abc_Obj_t * pFanin, int Level, int nLevelMax )
+{
+    Abc_Obj_t * pBuffer;
+    assert( Level - 1 >= Abc_ObjLevel(pFanin) );
+    pBuffer = (Abc_Obj_t *)Vec_PtrEntry( vBuffs, Abc_ObjId(pFanin) * nLevelMax + Level );
+    if ( pBuffer == NULL )
+    {
+        if ( Level - 1 == Abc_ObjLevel(pFanin) )
+            pBuffer = pFanin;
+        else
+            pBuffer = Abc_NtkAddBuffsOne( vBuffs, pFanin, Level - 1, nLevelMax );
+        pBuffer = Abc_NtkCreateNodeBuf( Abc_ObjNtk(pFanin), pBuffer ); 
+        Vec_PtrWriteEntry( vBuffs, Abc_ObjId(pFanin) * nLevelMax + Level, pBuffer );
+    }
+    return pBuffer;
+}
+Abc_Ntk_t * Abc_NtkAddBuffsInt( Abc_Ntk_t * pNtkInit, int fReverse, int nImprove, int fVerbose )
+{
+    Vec_Ptr_t * vBuffs;
+    Abc_Ntk_t * pNtk = Abc_NtkDup( pNtkInit );
+    Abc_Obj_t * pObj, * pFanin, * pBuffer;
+    int i, k, Iter, nLevelMax = Abc_NtkLevel( pNtk );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        pObj->Level = nLevelMax + 1;
+    if ( fReverse )
+    {
+        Vec_Ptr_t * vNodes = Abc_NtkDfs( pNtk, 1 );
+        assert( nLevelMax < (1<<18) );
+        Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pObj, i )
+        {
+            pObj->Level = (1<<18);
+            Abc_ObjForEachFanout( pObj, pFanin, k )
+                pObj->Level = Abc_MinInt( pFanin->Level - 1, pObj->Level );
+            assert( pObj->Level > 0 );
+        }
+        Abc_NtkForEachCi( pNtk, pObj, i )
+            pObj->Level = 0;
+
+        // move the nodes down one step at a time
+        for ( Iter = 0; Iter < nImprove; Iter++ )
+        {
+            int Counter = 0, TotalGain = 0;
+            Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+            {
+                int CountGain = -1;
+                assert( pObj->Level > 0 );
+                Abc_ObjForEachFanin( pObj, pFanin, k )
+                {
+                    assert( pFanin->Level < pObj->Level );
+                    if ( pFanin->Level + 1 == pObj->Level )
+                        break;
+                }
+                if ( k < Abc_ObjFaninNum(pObj) ) // cannot move
+                    continue;
+                Abc_ObjForEachFanin( pObj, pFanin, k )
+                    CountGain += Abc_NtkAddBuffsEval( pObj, pFanin );
+                if ( CountGain >= 0 ) // can move
+                {
+                    pObj->Level--;
+                    Counter++;
+                    TotalGain += CountGain;
+                }
+            }
+            if ( fVerbose )
+                printf( "Shifted %5d nodes down with total gain %5d.\n", Counter, TotalGain );
+            if ( Counter == 0 )
+                break;
+        }
+        Vec_PtrFree( vNodes );
+    }
+    else
+    {
+        // move the nodes up one step at a time
+        Vec_Ptr_t * vNodes = Abc_NtkDfs( pNtk, 1 );
+        for ( Iter = 0; Iter < nImprove; Iter++ )
+        {
+            int Counter = 0, TotalGain = 0;
+            Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pObj, i )
+            {
+                int CountGain = 1;
+                assert( pObj->Level <= (unsigned)nLevelMax );
+                Abc_ObjForEachFanout( pObj, pFanin, k )
+                {
+                    assert( pFanin->Level > pObj->Level );
+                    if ( pFanin->Level == pObj->Level + 1 )
+                        break;
+                }
+                if ( k < Abc_ObjFanoutNum(pObj) ) // cannot move
+                    continue;
+                Abc_ObjForEachFanin( pObj, pFanin, k )
+                    CountGain -= !Abc_NtkAddBuffsEval2( pObj, pFanin );
+                if ( CountGain >= 0 ) // can move
+                {
+                    pObj->Level++;
+                    Counter++;
+                    TotalGain += CountGain;
+                }
+            } 
+            if ( fVerbose )
+                printf( "Shifted %5d nodes up with total gain %5d.\n", Counter, TotalGain );
+            if ( Counter == 0 )
+                break;
+        }
+        Vec_PtrFree( vNodes );
+    }
+    vBuffs = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) * (nLevelMax + 1) );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        if ( i == Vec_PtrSize(vBuffs) / (nLevelMax + 1) )
+            break;
+        if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsCo(pObj) )
+            continue;
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+        {
+            assert( Abc_ObjLevel(pObj) - 1 >= Abc_ObjLevel(pFanin) );
+            if ( Abc_ObjLevel(pObj) - 1 == Abc_ObjLevel(pFanin) )
+                continue;
+            pBuffer = Abc_NtkAddBuffsOne( vBuffs, pFanin, Abc_ObjLevel(pObj) - 1, nLevelMax );
+            Abc_ObjPatchFanin( pObj, pFanin, pBuffer );
+        }
+    }
+    Vec_PtrFree( vBuffs );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        pObj->Level = 0;
+    return pNtk;
+}
+Abc_Ntk_t * Abc_NtkAddBuffs( Abc_Ntk_t * pNtkInit, int fDirect, int fReverse, int nImprove, int fVerbose )
+{
+    Abc_Ntk_t * pNtkD, * pNtkR;
+    if ( fDirect )
+        return Abc_NtkAddBuffsInt( pNtkInit, 0, nImprove, fVerbose );
+    if ( fReverse )
+        return Abc_NtkAddBuffsInt( pNtkInit, 1, nImprove, fVerbose );
+    pNtkD = Abc_NtkAddBuffsInt( pNtkInit, 0, nImprove, fVerbose );
+    pNtkR = Abc_NtkAddBuffsInt( pNtkInit, 1, nImprove, fVerbose );
+    if ( Abc_NtkNodeNum(pNtkD) < Abc_NtkNodeNum(pNtkR) )
+    {
+        Abc_NtkDelete( pNtkR );
+        return pNtkD;
+    }
+    else
+    {
+        Abc_NtkDelete( pNtkD );
+        return pNtkR;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes max delay using log(n) delay model.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Abc_NtkComputeDelay( Abc_Ntk_t * pNtk )
+{
+    static double GateDelays[20] = { 1.00, 1.00, 2.00, 2.58, 3.00, 3.32, 3.58, 3.81, 4.00, 4.17, 4.32, 4.46, 4.58, 4.70, 4.81, 4.91, 5.00, 5.09, 5.17, 5.25 };
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj, * pFanin;
+    float DelayMax, Delays[15] = {0};
+    int nFaninMax, i, k;
+    // calculate relative gate delays
+    nFaninMax = Abc_NtkGetFaninMax( pNtk );
+    assert( nFaninMax > 1 && nFaninMax < 15 );
+    for ( i = 0; i <= nFaninMax; i++ )
+        Delays[i] = GateDelays[i]/GateDelays[nFaninMax];
+    // set max CI delay
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->dTemp = 0.0;
+    // compute delays for each node
+    vNodes = Abc_NtkDfs( pNtk, 1 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        pObj->dTemp = 0.0;
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            pObj->dTemp = Abc_MaxFloat( pObj->dTemp, pFanin->dTemp );
+        pObj->dTemp += Delays[Abc_ObjFaninNum(pObj)];
+    }
+    Vec_PtrFree( vNodes );
+    DelayMax = 0.0;
+    // find max CO delay
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        DelayMax = Abc_MaxFloat( DelayMax, Abc_ObjFanin0(pObj)->dTemp );
+    return DelayMax;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeSopToCubes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew )
+{
+    Abc_Obj_t * pNodeOr, * pNodeNew, * pFanin;
+    char * pCube, * pSop = (char *)pNodeOld->pData;
+    int v, Value, nVars = Abc_ObjFaninNum(pNodeOld), nFanins;
+    // create the root node
+    if ( Abc_SopGetCubeNum(pSop) < 2 )
+    {
+        pNodeNew = Abc_NtkDupObj( pNtkNew, pNodeOld, 0 );
+        Abc_ObjForEachFanin( pNodeOld, pFanin, v )
+            Abc_ObjAddFanin( pNodeNew, pFanin->pCopy );
+        assert( pNodeOld->pCopy == pNodeNew );
+        return;
+    }
+    // add the OR gate
+    pNodeOr = Abc_NtkCreateNode( pNtkNew );
+    pNodeOr->pData = Abc_SopCreateOr( (Mem_Flex_t *)pNtkNew->pManFunc, Abc_SopGetCubeNum(pSop), NULL );
+    // check the logic function of the node
+    Abc_SopForEachCube( pSop, nVars, pCube )
+    {
+        nFanins = 0;
+        Abc_CubeForEachVar( pCube, Value, v )
+            if ( Value == '0' || Value == '1' )
+                nFanins++;
+        assert( nFanins > 0 );
+        // create node
+        pNodeNew = Abc_NtkCreateNode( pNtkNew );
+        pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, nFanins, NULL );
+        nFanins = 0;
+        Abc_CubeForEachVar( pCube, Value, v )
+        {
+            if ( Value != '0' && Value != '1' )
+                continue;
+            Abc_ObjAddFanin( pNodeNew, Abc_ObjFanin(pNodeOld, v)->pCopy );
+            if ( Value == '0' )
+                Abc_SopComplementVar( (char *)pNodeNew->pData, nFanins );
+            nFanins++;
+        }
+        Abc_ObjAddFanin( pNodeOr, pNodeNew );
+    }
+    // check the complement
+    if ( Abc_SopIsComplement(pSop) )
+        Abc_SopComplement( (char *)pNodeOr->pData );
+    // mark the old node with the new one
+    assert( pNodeOld->pCopy == NULL );
+    pNodeOld->pCopy = pNodeOr;
+}
+Abc_Ntk_t * Abc_NtkSopToCubes( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pNode;
+    Vec_Ptr_t * vNodes;
+    int i;
+    assert( Abc_NtkIsSopLogic(pNtk) );
+    Abc_NtkCleanCopy( pNtk );
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+    // perform conversion in the topological order
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        Abc_NodeSopToCubes( pNode, pNtkNew );
+    Vec_PtrFree( vNodes );
+    // make sure everything is okay
+    Abc_NtkFinalize( pNtk, pNtkNew );
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkSopToCubes: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates precomputed reverse topological order for each node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int  Abc_NtkTopoHasBeg( Abc_Obj_t * p )  { return Vec_IntEntry(p->pNtk->vTopo, 2*Abc_ObjId(p)  );       }
+static inline int  Abc_NtkTopoHasEnd( Abc_Obj_t * p )  { return Vec_IntEntry(p->pNtk->vTopo, 2*Abc_ObjId(p)+1);       }
+
+static inline void Abc_NtkTopoSetBeg( Abc_Obj_t * p )  { Vec_IntWriteEntry(p->pNtk->vTopo, 2*Abc_ObjId(p)  , Vec_IntSize(p->pNtk->vTopo));  }
+static inline void Abc_NtkTopoSetEnd( Abc_Obj_t * p )  { Vec_IntWriteEntry(p->pNtk->vTopo, 2*Abc_ObjId(p)+1, Vec_IntSize(p->pNtk->vTopo));  }
+
+void Abc_NtkReverseTopoOrder_rec( Abc_Obj_t * pObj, int fThisIsPivot )
+{
+    Abc_Obj_t * pNext, * pPivot = NULL;
+    int i;
+    if ( Abc_NodeIsTravIdCurrent( pObj ) )
+        return;
+    Abc_NodeSetTravIdCurrent( pObj );
+    if ( Abc_ObjIsPo(pObj) )
+    {
+        Vec_IntPush( pObj->pNtk->vTopo, Abc_ObjId(pObj) );
+        return;
+    }
+    assert( Abc_ObjIsNode(pObj) );
+    // mark begining
+    if ( fThisIsPivot )
+        Abc_NtkTopoSetBeg( pObj );        
+    // find fanout without topo
+    Abc_ObjForEachFanout( pObj, pNext, i )
+        if ( !Abc_NtkTopoHasBeg(pNext) )
+        { 
+            assert( !Abc_NtkTopoHasEnd(pNext) );
+            Abc_NtkReverseTopoOrder_rec( pNext, 1 );
+            pPivot = pNext;
+            break;
+        }
+    Abc_ObjForEachFanout( pObj, pNext, i )
+        if ( pNext != pPivot )
+            Abc_NtkReverseTopoOrder_rec( pNext, 0 );
+    // mark end
+    if ( fThisIsPivot )
+        Abc_NtkTopoSetEnd( pObj );
+    // save current node        
+    Vec_IntPush( pObj->pNtk->vTopo, Abc_ObjId(pObj) );
+}
+void Abc_NtkReverseTopoOrder( Abc_Ntk_t * p )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    assert( p->vTopo == NULL );
+    p->vTopo = Vec_IntAlloc( 10 * Abc_NtkObjNumMax(p) );
+    Vec_IntFill( p->vTopo, 2 * Abc_NtkObjNumMax(p), 0 );
+    Abc_NtkForEachNode( p, pObj, i )
+    {
+        if ( Abc_NtkTopoHasBeg(pObj) )
+            continue;
+        Abc_NtkIncrementTravId( p );        
+        Abc_NtkReverseTopoOrder_rec( pObj, 1 );
+    }
+    printf( "Nodes = %d.   Size = %d.  Ratio = %f.\n", 
+        Abc_NtkNodeNum(p), Vec_IntSize(p->vTopo), 1.0*Vec_IntSize(p->vTopo)/Abc_NtkNodeNum(p) );
+}
+
+void Abc_NtkReverse_rec( Abc_Obj_t * pObj, Vec_Int_t * vVisited )
+{
+    Abc_Obj_t * pNext;
+    int i;
+    if ( Abc_NodeIsTravIdCurrent( pObj ) )
+        return;
+    Abc_NodeSetTravIdCurrent( pObj );
+    Abc_ObjForEachFanout( pObj, pNext, i )
+        Abc_NtkReverse_rec( pNext, vVisited );
+    Vec_IntPush( vVisited, Abc_ObjId(pObj) );
+}
+void Abc_NtkReverseTopoOrderTest( Abc_Ntk_t * p )
+{
+    Vec_Int_t * vVisited;
+    Abc_Obj_t * pObj;
+    int i;//, k, iBeg, iEnd;
+    abctime clk = Abc_Clock();
+    Abc_NtkReverseTopoOrder( p );
+/*
+    printf( "Reverse topological order for nodes:\n" );
+    Abc_NtkForEachNode( p, pObj, i )
+    {
+        iBeg = Abc_NtkTopoHasBeg( pObj );
+        iEnd = Abc_NtkTopoHasEnd( pObj );
+        printf( "Node %4d : ", Abc_ObjId(pObj) );
+        for ( k = iEnd - 1; k >= iBeg; k-- )
+            printf( "%d ", Vec_IntEntry(p->vTopo, k) );
+        printf( "\n" );
+    }
+*/
+    Vec_IntFreeP( &p->vTopo );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    // compute regular fanout orders
+    clk = Abc_Clock();
+    vVisited = Vec_IntAlloc( 1000 );
+    Abc_NtkForEachNode( p, pObj, i )
+    {
+        Vec_IntClear( vVisited );
+        Abc_NtkIncrementTravId( p ); 
+        Abc_NtkReverse_rec( pObj, vVisited );
+    }
+    Vec_IntFree( vVisited );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts multi-output PLA into an AIG with logic sharing.]
+
+  Description [The first argument is an array of char*-strings representing
+  individual output of a multi-output PLA. The number of inputs (nInputs) 
+  and the number of outputs (nOutputs) are the second and third arguments. 
+  This procedure returns the AIG manager with the given number of inputs 
+  and outputs representing the PLA as a logic network with sharing.
+  
+  For example, if the original PLA is 
+    1000 10
+    0110 01
+    0011 01
+  the individual PLA for each the two outputs should be
+    1000 1
+  and
+    0110 1
+    0011 1
+
+  Reprsentation in terms of two char*-strings will be:
+    char * pPlas[2] = { "1000 1\n", "0110 1\n0011 1\n" };              
+  The call to the procedure may look as follows:
+    Abc_Ntk_t * pNtkAig = Abc_NtkFromPla( pPlas, 4, 2 );]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromPla( char ** pPlas, int nInputs, int nOutputs )
+{
+    Fxu_Data_t Params, * p = &Params;
+    Abc_Ntk_t * pNtkSop, * pNtkAig; 
+    Abc_Obj_t * pNode, * pFanin;
+    int i, k;
+    // allocate logic network with SOP local functions
+    pNtkSop = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+    pNtkSop->pName = Extra_FileNameGeneric("pla");
+    // create primary inputs/outputs
+    for ( i = 0; i < nInputs; i++ )
+        Abc_NtkCreatePi( pNtkSop );
+    for ( i = 0; i < nOutputs; i++ )
+        Abc_NtkCreatePo( pNtkSop );
+    Abc_NtkAddDummyPiNames( pNtkSop );
+    Abc_NtkAddDummyPoNames( pNtkSop );
+    // create internal nodes
+    for ( i = 0; i < nOutputs; i++ )
+    {
+        pNode = Abc_NtkCreateNode( pNtkSop );
+        Abc_NtkForEachPi( pNtkSop, pFanin, k )
+            Abc_ObjAddFanin( pNode, pFanin );
+        pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkSop->pManFunc, pPlas[i] );
+        Abc_ObjAddFanin( Abc_NtkPo(pNtkSop, i), pNode );
+        // check that the number of inputs is the same
+        assert( Abc_SopGetVarNum((char*)pNode->pData) == nInputs );
+    }
+    if ( !Abc_NtkCheck( pNtkSop ) )
+        fprintf( stdout, "Abc_NtkFromPla(): Network check has failed.\n" );
+    // perform fast_extract
+    Abc_NtkSetDefaultFxParams( p );
+    Abc_NtkFastExtract( pNtkSop, p );
+    Abc_NtkFxuFreeInfo( p );
+    // convert to an AIG
+    pNtkAig = Abc_NtkStrash( pNtkSop, 0, 1, 0 );
+    Abc_NtkDelete( pNtkSop );
+    return pNtkAig;
+}
+void Abc_NtkFromPlaTest()
+{
+    char * pPlas[2] = { "1000 1\n", "0110 1\n0011 1\n" };
+    Abc_Ntk_t * pNtkAig = Abc_NtkFromPla( pPlas, 4, 2 );
+    Io_WriteBlifLogic( pNtkAig, "temp.blif", 0 );
+    Abc_NtkDelete( pNtkAig );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the logic network is in the topological order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkSplitSop( Abc_Ntk_t * pNtk, int nCubesMax, int fVerbose )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pObj, * pFanin, * pObjNew, * pObjNewRoot;
+    int i, k, j, nCubes, nCubesThis, nSplits;
+    char * pSopStr, * pSopStr2, * pTempSop, Symb;
+    if ( pNtk == NULL )
+        return NULL;
+    assert( !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsNetlist(pNtk) );
+    // start the network
+    pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc );
+    // copy the internal nodes
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        assert( Abc_ObjIsNode(pObj) );
+        pObjNewRoot = Abc_NtkDupObj( pNtkNew, pObj, 0 );
+        nCubes = Abc_SopGetCubeNum( (char *)pObj->pData );
+        if ( nCubes <= nCubesMax )
+        {            
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+            continue;
+        }
+        nSplits = (nCubes / nCubesMax) + (int)(nCubes % nCubesMax > 0);
+        pSopStr = (char *)pObjNewRoot->pData;
+        pObjNewRoot->pData = Abc_SopCreateOr((Mem_Flex_t *)pNtkNew->pManFunc, nSplits, NULL);
+        if ( Abc_SopIsComplement(pSopStr) )
+        {
+            Abc_SopComplement( pSopStr );
+            Abc_SopComplement( (char *)pObjNewRoot->pData );
+        }
+        pTempSop = (char *)pObj->pData; pObj->pData = (char *)"?";
+        for ( j = 0; j < nSplits; j++ )
+        {
+            // clone the node
+            pObjNew = Abc_NtkDupObj( pNtkNew, pObj, 0 );
+            Abc_ObjAddFanin( pObjNewRoot, pObjNew );
+            // get its cubes
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+            // create SOP for this node
+            nCubesThis = (j < nCubes / nCubesMax) ? nCubesMax : nCubes % nCubesMax;
+            pSopStr2 = pSopStr + (Abc_ObjFaninNum(pObj) + 3) * nCubesThis;
+            Symb = *pSopStr2; *pSopStr2 = 0;
+            pObjNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, pSopStr );
+            *pSopStr2 = Symb;
+            pSopStr = pSopStr2;
+        }
+        // update 
+        pObj->pData = pTempSop;
+        pObj->pCopy = pObjNewRoot;
+    }
+    Vec_PtrFree( vNodes );
+    Abc_NtkFinalize( pNtk, pNtkNew );
+    // check correctness
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" );
+    pNtk->pCopy = pNtkNew;
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the logic network is in the topological order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkIsTopo( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k, Counter = 0;
+    Abc_NtkIncrementTravId( pNtk );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        Abc_NodeSetTravIdCurrent(pObj);
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        // check if fanins are in the topo order
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+                break;
+        if ( k != Abc_ObjFaninNum(pObj) )
+        {
+            if ( Counter++ == 0 )
+                printf( "Node %d is out of topo order.\n", Abc_ObjId(pObj) );
+        }
+        Abc_NodeSetTravIdCurrent(pObj);
+    }
+    if ( Counter )
+        printf( "Topological order does not hold for %d internal nodes.\n", Counter );
+    return (int)(Counter == 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers phase information to the new network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTransferPhases( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    assert( pNtk->vPhases != NULL );
+    assert( Vec_IntSize(pNtk->vPhases) == Abc_NtkObjNumMax(pNtk) );
+    assert( pNtkNew->vPhases == NULL );
+    pNtkNew->vPhases = Vec_IntStart( Abc_NtkObjNumMax(pNtkNew) );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( pObj->pCopy && !Abc_ObjIsNone( (Abc_Obj_t *)pObj->pCopy ) )
+            Vec_IntWriteEntry( pNtkNew->vPhases, Abc_ObjId( (Abc_Obj_t *)pObj->pCopy ), Vec_IntEntry(pNtk->vPhases, i) );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/abc_.c b/abc-build/src/base/abc/abc_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/abc_.c
@@ -0,0 +1,52 @@
+/**CFile****************************************************************
+
+  FileName    [abc_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abc/module.make b/abc-build/src/base/abc/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abc/module.make
@@ -0,0 +1,22 @@
+SRC +=	src/base/abc/abcAig.c \
+	src/base/abc/abcBarBuf.c \
+	src/base/abc/abcBlifMv.c \
+	src/base/abc/abcCheck.c \
+	src/base/abc/abcDfs.c \
+	src/base/abc/abcFanio.c \
+	src/base/abc/abcFanOrder.c \
+	src/base/abc/abcFunc.c \
+	src/base/abc/abcHie.c \
+	src/base/abc/abcHieCec.c \
+	src/base/abc/abcHieNew.c \
+	src/base/abc/abcLatch.c \
+	src/base/abc/abcLib.c \
+	src/base/abc/abcMinBase.c \
+	src/base/abc/abcNames.c \
+	src/base/abc/abcNetlist.c \
+	src/base/abc/abcNtk.c \
+	src/base/abc/abcObj.c \
+	src/base/abc/abcRefs.c \
+	src/base/abc/abcShow.c \
+	src/base/abc/abcSop.c \
+	src/base/abc/abcUtil.c
diff --git a/abc-build/src/base/abci/abc.c b/abc-build/src/base/abci/abc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abc.c
@@ -0,0 +1,36403 @@
+/**CFile****************************************************************
+ 
+  FileName    [abc.c] 
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+  
+  Synopsis    [Command file.]
+
+  Author      [Alan Mishchenko]
+   
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/main.h"
+#include "base/main/mainInt.h"
+#include "proof/fraig/fraig.h"
+#include "opt/fxu/fxu.h"
+#include "opt/cut/cut.h"
+#include "map/fpga/fpga.h"
+#include "map/if/if.h"
+#include "opt/sim/sim.h"
+#include "opt/res/res.h"
+#include "opt/lpk/lpk.h"
+#include "aig/gia/giaAig.h"
+#include "opt/dar/dar.h"
+#include "opt/mfs/mfs.h"
+#include "proof/fra/fra.h"
+#include "aig/saig/saig.h"
+#include "proof/int/int.h"
+#include "proof/dch/dch.h"
+#include "proof/ssw/ssw.h"
+#include "opt/cgt/cgt.h"
+#include "bool/kit/kit.h"
+#include "map/amap/amap.h"
+#include "opt/ret/retInt.h"
+#include "sat/cnf/cnf.h"
+#include "proof/cec/cec.h"
+#include "proof/pdr/pdr.h"
+#include "misc/tim/tim.h"
+#include "proof/llb/llb.h"
+#include "proof/bbr/bbr.h"
+#include "map/cov/cov.h"
+#include "base/cmd/cmd.h"
+#include "proof/abs/abs.h"
+#include "sat/bmc/bmc.h"
+#include "proof/ssc/ssc.h"
+#include "opt/sfm/sfm.h"
+#include "bool/rpo/rpo.h"
+#include "map/mpm/mpm.h"
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_CommandPrintStats             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintExdc              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintIo                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintLatch             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintFanio             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintMffc              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintFactor            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintLevel             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintSupport           ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintSymms             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintUnate             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintAuto              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintKMap              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintGates             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintSharing           ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintXCut              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintDsd               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintCone              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintMiter             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintStatus            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintDelay             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandShow                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandShowBdd                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandShowCut                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandCollapse               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandStrash                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBalance                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandMuxStruct              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandMulti                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRenode                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCleanup                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSweep                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFastExtract            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandEliminate              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDisjoint               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandLutpack                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandLutmin                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+//static int Abc_CommandImfs                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandMfs                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandMfs2                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTrace                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSpeedup                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPowerdown              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAddBuffs               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+//static int Abc_CommandMerge                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTestDec                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTestNpn                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTestRPO                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandRewrite                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRefactor               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRestructure            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandResubstitute           ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRr                     ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCascade                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandExtract                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandVarMin                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandLogic                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandComb                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandMiter                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDemiter                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandOrPos                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAndPos                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandZeroPo                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSwapPos                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRemovePo               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDropSat                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAddPi                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAppend                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPutOnTop               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFrames                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDFrames                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSop                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBdd                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAig                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandReorder                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBidec                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandOrder                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandMuxes                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCubes                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSplitSop               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandExtSeqDcs              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandReach                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCone                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandNode                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTopmost                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTopAnd                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTrim                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandShortNames             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandExdcFree               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandExdcGet                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandExdcSet                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCareSet                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCut                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandEspresso               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandGen                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandGenFsm                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCover                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDouble                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandInter                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBb2Wb                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandOutdec                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandNodeDup                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTestColor              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTest                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandQuaVar                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandQuaRel                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandQuaReach               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSenseInput             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandNpnLoad                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandNpnSave                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandSendAig                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSendStatus             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandIStrash                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandICut                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIRewrite               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDRewrite               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDRefactor              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDc2                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDChoice                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDch                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDrwsat                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIRewriteSeq            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIResyn                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandISat                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIFraig                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDFraig                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCSweep                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDProve                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbSec                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSimSec                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandMatch                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+//static int Abc_CommandHaig                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandQbf                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandFraig                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigTrust             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigStore             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigRestore           ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigClean             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigSweep             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigDress             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandRecStart3              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRecStop3               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRecPs3                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRecAdd3                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRecDump3               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRecMerge3              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandMap                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAmap                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandUnmap                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAttach                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSuperChoice            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSuperChoiceLut         ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+//static int Abc_CommandFpga                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+//static int Abc_CommandFpgaFast               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIf                     ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIfif                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandDsdSave                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDsdLoad                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDsdFree                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDsdPs                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDsdTune                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDsdMerge               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDsdClean               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandScut                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandInit                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandZero                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandUndc                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandOneHot                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPipe                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSeq                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandUnseq                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRetime                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDRetime                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFlowRetime             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCRetime                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSeqFpga                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSeqMap                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSeqSweep               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSeqSweep2              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTestSeqSweep           ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTestScorr              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandLcorr                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSeqCleanup             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCycle                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandXsim                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSim                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSim3                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDarPhase               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSynch                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandClockGate              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandExtWin                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandInsWin                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPermute                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandUnpermute              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCubeEnum               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandCec                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDCec                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDSec                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSat                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDSat                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPSat                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandProve                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIProve                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDebug                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBmc                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBmc2                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBmc3                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBmcInter               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIndcut                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandEnlarge                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTempor                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandInduction              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandConstr                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandUnfold                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFold                   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandUnfold2                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFold2                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBm                     ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBm2                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSaucy                  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTestCex                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPdr                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandReconcile              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCexSave                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCexLoad                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCexCut                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCexMerge               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+//static int Abc_CommandCexMin                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDualRail               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBlockPo                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIso                    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandTraceStart             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTraceCheck             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandAbc9Get                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Put                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Read               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9ReadBlif           ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9ReadCBlif          ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9ReadStg            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Write              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Ps                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9PFan               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9PSig               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Status             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9MuxProfile         ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Show               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Strash             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Topand             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Add1Hot            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Cof                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Trim               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Dfs                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Sim                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Sim3               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Resim              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9SpecI              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Equiv              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Equiv2             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Equiv3             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Semi               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Times              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Frames             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Retime             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Enable             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Dc2                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Bidec              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Shrink             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Fx                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Balance            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9BalanceLut         ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Syn2               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Syn3               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Syn4               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9False              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Miter              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Miter2             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Append             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Scl                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Lcorr              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Scorr              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Choice             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Sat                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Fraig              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9CFraig             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Srm                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Srm2               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Filter             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Reduce             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9EquivMark          ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9EquivFilter        ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Cec                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Verify             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Sweep              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Force              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Embed              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Sopb               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9If                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Iff                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9If2                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Jf                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Kf                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Lf                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Mf                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Nf                 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Struct             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Trace              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Speedup            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Era                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Dch                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Rpm                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9BackReach          ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Posplit            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9ReachM             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9ReachP             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9ReachN             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9ReachY             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Undo               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Iso                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9CexInfo            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Cycle              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Cone               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Slice              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9PoPart             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9GroupProve         ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9MultiProve         ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9SplitProve         ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Bmc                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9BCore              ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9ICheck             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9SatTest            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9FFTest             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Inse               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Maxi               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Bmci               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9PoXsim             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Demiter            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+//static int Abc_CommandAbc9PoPart2            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+//static int Abc_CommandAbc9CexCut             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+//static int Abc_CommandAbc9CexMerge           ( Abc_Frame_t * pAbc, int argc, char ** argv );
+//static int Abc_CommandAbc9CexMin             ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandAbc9AbsDerive          ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9AbsRefine          ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9GlaDerive          ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9GlaRefine          ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9GlaShrink          ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Gla                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Vta                ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Vta2Gla            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Gla2Vta            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Fla2Gla            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Gla2Fla            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandAbc9Test               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+extern int Abc_CommandAbcLivenessToSafety    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+extern int Abc_CommandAbcLivenessToSafetySim ( Abc_Frame_t * pAbc, int argc, char ** argv );
+extern int Abc_CommandAbcLivenessToSafetyWithLTL( Abc_Frame_t * pAbc, int argc, char ** argv );
+extern int Abc_CommandCS_kLiveness           ( Abc_Frame_t * pAbc, int argc, char ** argv );
+extern int Abc_CommandNChooseK               ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameReplaceCex( Abc_Frame_t * pAbc, Abc_Cex_t ** ppCex )
+{
+    // update CEX
+    ABC_FREE( pAbc->pCex );
+    pAbc->pCex = *ppCex;
+    *ppCex = NULL;
+    // remove CEX vector
+    if ( pAbc->vCexVec )
+    {
+        Vec_PtrFreeFree( pAbc->vCexVec );
+        pAbc->vCexVec = NULL;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameReplaceCexVec( Abc_Frame_t * pAbc, Vec_Ptr_t ** pvCexVec )
+{
+    // update CEX vector
+    if ( pAbc->vCexVec )
+        Vec_PtrFreeFree( pAbc->vCexVec );
+    pAbc->vCexVec = *pvCexVec;
+    *pvCexVec = NULL;
+    // remove CEX
+    ABC_FREE( pAbc->pCex );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameReplacePoEquivs( Abc_Frame_t * pAbc, Vec_Ptr_t ** pvPoEquivs )
+{
+    if ( pAbc->vPoEquivs )
+        Vec_VecFree( (Vec_Vec_t *)pAbc->vPoEquivs );
+    pAbc->vPoEquivs = *pvPoEquivs;
+    *pvPoEquivs = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameReplacePoStatuses( Abc_Frame_t * pAbc, Vec_Int_t ** pvStatuses )
+{
+    if ( pAbc->vStatuses )
+        Vec_IntFree( pAbc->vStatuses );
+    pAbc->vStatuses = *pvStatuses;
+    *pvStatuses = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives array of statuses from the array of CEXes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_FrameDeriveStatusArray( Vec_Ptr_t * vCexes )
+{
+    Vec_Int_t * vStatuses;
+    Abc_Cex_t * pCex;
+    int i;
+    if ( vCexes == NULL )
+        return NULL;
+    vStatuses = Vec_IntAlloc( Vec_PtrSize(vCexes) );
+    Vec_IntFill( vStatuses, Vec_PtrSize(vCexes), -1 ); // assume UNDEC
+    Vec_PtrForEachEntry( Abc_Cex_t *, vCexes, pCex, i )
+        if ( pCex != NULL )
+            Vec_IntWriteEntry( vStatuses, i, 0 ); // set this output as SAT
+    return vStatuses;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameClearDesign()
+{
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameUpdateGia( Abc_Frame_t * pAbc, Gia_Man_t * pNew )
+{
+    if ( pNew == NULL )
+    {
+        Abc_Print( -1, "Abc_FrameUpdateGia(): Tranformation has failed.\n" );
+        return;
+    }
+    if ( Gia_ManPoNum(pNew) == 0 )
+        Abc_Print( 0, "The current GIA has no primary outputs. Some commands may not work correctly.\n" );
+    if ( pNew == pAbc->pGia )
+        return;
+    // transfer names
+    if (!pNew->vNamesIn && pAbc->pGia && pAbc->pGia->vNamesIn && Gia_ManCiNum(pNew) == Vec_PtrSize(pAbc->pGia->vNamesIn))
+    {
+        pNew->vNamesIn = pAbc->pGia->vNamesIn;
+        pAbc->pGia->vNamesIn = NULL;
+    }
+    if (!pNew->vNamesOut && pAbc->pGia && pAbc->pGia->vNamesOut && Gia_ManCoNum(pNew) == Vec_PtrSize(pAbc->pGia->vNamesOut))
+    {
+        pNew->vNamesOut = pAbc->pGia->vNamesOut;
+        pAbc->pGia->vNamesOut = NULL;
+    }
+    // update
+    if ( pAbc->pGia2 )
+        Gia_ManStop( pAbc->pGia2 );
+    pAbc->pGia2 = pAbc->pGia;
+    pAbc->pGia  = pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Abc_FrameGetGia( Abc_Frame_t * pAbc )
+{
+    Gia_Man_t * pGia;
+    if ( pAbc->pGia2 )
+        Gia_ManStop( pAbc->pGia2 );
+    pAbc->pGia2 = NULL;
+    pGia = pAbc->pGia;
+    pAbc->pGia = NULL;
+    return pGia;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_Init( Abc_Frame_t * pAbc )
+{
+    Cmd_CommandAdd( pAbc, "Printing",     "print_stats",   Abc_CommandPrintStats,       0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_exdc",    Abc_CommandPrintExdc,        0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_io",      Abc_CommandPrintIo,          0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_latch",   Abc_CommandPrintLatch,       0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_fanio",   Abc_CommandPrintFanio,       0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_mffc",    Abc_CommandPrintMffc,        0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_factor",  Abc_CommandPrintFactor,      0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_level",   Abc_CommandPrintLevel,       0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_supp",    Abc_CommandPrintSupport,     0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_symm",    Abc_CommandPrintSymms,       0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_unate",   Abc_CommandPrintUnate,       0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_auto",    Abc_CommandPrintAuto,        0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_kmap",    Abc_CommandPrintKMap,        0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_gates",   Abc_CommandPrintGates,       0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_sharing", Abc_CommandPrintSharing,     0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_xcut",    Abc_CommandPrintXCut,        0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_dsd",     Abc_CommandPrintDsd,         0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_cone",    Abc_CommandPrintCone,        0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_miter",   Abc_CommandPrintMiter,       0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_status",  Abc_CommandPrintStatus,      0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_delay",   Abc_CommandPrintDelay,       0 );
+
+    Cmd_CommandAdd( pAbc, "Printing",     "show",          Abc_CommandShow,             0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "show_bdd",      Abc_CommandShowBdd,          0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "show_cut",      Abc_CommandShowCut,          0 );
+
+    Cmd_CommandAdd( pAbc, "Synthesis",    "collapse",      Abc_CommandCollapse,         1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "strash",        Abc_CommandStrash,           1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "balance",       Abc_CommandBalance,          1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "mux_struct",    Abc_CommandMuxStruct,        1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "multi",         Abc_CommandMulti,            1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "renode",        Abc_CommandRenode,           1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "cleanup",       Abc_CommandCleanup,          1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "sweep",         Abc_CommandSweep,            1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "fx",            Abc_CommandFastExtract,      1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "eliminate",     Abc_CommandEliminate,        1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "dsd",           Abc_CommandDisjoint,         1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "lutpack",       Abc_CommandLutpack,          1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "lutmin",        Abc_CommandLutmin,           1 );
+//    Cmd_CommandAdd( pAbc, "Synthesis",    "imfs",          Abc_CommandImfs,             1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "mfs",           Abc_CommandMfs,              1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "mfs2",          Abc_CommandMfs2,             1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "trace",         Abc_CommandTrace,            0 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "speedup",       Abc_CommandSpeedup,          1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "powerdown",     Abc_CommandPowerdown,        1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "addbuffs",      Abc_CommandAddBuffs,         1 );
+//    Cmd_CommandAdd( pAbc, "Synthesis",    "merge",         Abc_CommandMerge,            1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "testdec",       Abc_CommandTestDec,          0 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "testnpn",       Abc_CommandTestNpn,          0 );
+    Cmd_CommandAdd( pAbc, "LogiCS",       "testrpo",       Abc_CommandTestRPO,          0 );
+
+    Cmd_CommandAdd( pAbc, "Synthesis",    "rewrite",       Abc_CommandRewrite,          1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "refactor",      Abc_CommandRefactor,         1 );
+//    Cmd_CommandAdd( pAbc, "Synthesis",    "restructure",   Abc_CommandRestructure,      1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "resub",         Abc_CommandResubstitute,     1 );
+//    Cmd_CommandAdd( pAbc, "Synthesis",    "rr",            Abc_CommandRr,               1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "cascade",       Abc_CommandCascade,          1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "extract",       Abc_CommandExtract,          1 );
+    Cmd_CommandAdd( pAbc, "Synthesis",    "varmin",        Abc_CommandVarMin,           0 );
+
+    Cmd_CommandAdd( pAbc, "Various",      "logic",         Abc_CommandLogic,            1 );
+    Cmd_CommandAdd( pAbc, "Various",      "comb",          Abc_CommandComb,             1 );
+    Cmd_CommandAdd( pAbc, "Various",      "miter",         Abc_CommandMiter,            1 );
+    Cmd_CommandAdd( pAbc, "Various",      "demiter",       Abc_CommandDemiter,          1 );
+    Cmd_CommandAdd( pAbc, "Various",      "orpos",         Abc_CommandOrPos,            1 );
+    Cmd_CommandAdd( pAbc, "Various",      "andpos",        Abc_CommandAndPos,           1 );
+    Cmd_CommandAdd( pAbc, "Various",      "zeropo",        Abc_CommandZeroPo,           1 );
+    Cmd_CommandAdd( pAbc, "Various",      "swappos",       Abc_CommandSwapPos,          1 );
+    Cmd_CommandAdd( pAbc, "Various",      "removepo",      Abc_CommandRemovePo,         1 );
+    Cmd_CommandAdd( pAbc, "Various",      "dropsat",       Abc_CommandDropSat,          1 );
+    Cmd_CommandAdd( pAbc, "Various",      "addpi",         Abc_CommandAddPi,            1 );
+    Cmd_CommandAdd( pAbc, "Various",      "append",        Abc_CommandAppend,           1 );
+    Cmd_CommandAdd( pAbc, "Various",      "putontop",      Abc_CommandPutOnTop,         1 );
+    Cmd_CommandAdd( pAbc, "Various",      "frames",        Abc_CommandFrames,           1 );
+    Cmd_CommandAdd( pAbc, "Various",      "dframes",       Abc_CommandDFrames,          1 );
+    Cmd_CommandAdd( pAbc, "Various",      "sop",           Abc_CommandSop,              0 );
+    Cmd_CommandAdd( pAbc, "Various",      "bdd",           Abc_CommandBdd,              0 );
+    Cmd_CommandAdd( pAbc, "Various",      "aig",           Abc_CommandAig,              0 );
+    Cmd_CommandAdd( pAbc, "Various",      "reorder",       Abc_CommandReorder,          0 );
+    Cmd_CommandAdd( pAbc, "Various",      "bidec",         Abc_CommandBidec,            1 );
+    Cmd_CommandAdd( pAbc, "Various",      "order",         Abc_CommandOrder,            0 );
+    Cmd_CommandAdd( pAbc, "Various",      "muxes",         Abc_CommandMuxes,            1 );
+    Cmd_CommandAdd( pAbc, "Various",      "cubes",         Abc_CommandCubes,            1 );
+    Cmd_CommandAdd( pAbc, "Various",      "splitsop",      Abc_CommandSplitSop,         1 );
+    Cmd_CommandAdd( pAbc, "Various",      "ext_seq_dcs",   Abc_CommandExtSeqDcs,        0 );
+    Cmd_CommandAdd( pAbc, "Various",      "reach",         Abc_CommandReach,            0 );
+    Cmd_CommandAdd( pAbc, "Various",      "cone",          Abc_CommandCone,             1 );
+    Cmd_CommandAdd( pAbc, "Various",      "node",          Abc_CommandNode,             1 );
+    Cmd_CommandAdd( pAbc, "Various",      "topmost",       Abc_CommandTopmost,          1 );
+    Cmd_CommandAdd( pAbc, "Various",      "topand",        Abc_CommandTopAnd,          1 );
+    Cmd_CommandAdd( pAbc, "Various",      "trim",          Abc_CommandTrim,             1 );
+    Cmd_CommandAdd( pAbc, "Various",      "short_names",   Abc_CommandShortNames,       0 );
+    Cmd_CommandAdd( pAbc, "Various",      "exdc_free",     Abc_CommandExdcFree,         1 );
+    Cmd_CommandAdd( pAbc, "Various",      "exdc_get",      Abc_CommandExdcGet,          1 );
+    Cmd_CommandAdd( pAbc, "Various",      "exdc_set",      Abc_CommandExdcSet,          1 );
+    Cmd_CommandAdd( pAbc, "Various",      "care_set",      Abc_CommandCareSet,          1 );
+    Cmd_CommandAdd( pAbc, "Various",      "cut",           Abc_CommandCut,              0 );
+    Cmd_CommandAdd( pAbc, "Various",      "espresso",      Abc_CommandEspresso,         1 );
+    Cmd_CommandAdd( pAbc, "Various",      "gen",           Abc_CommandGen,              0 );
+    Cmd_CommandAdd( pAbc, "Various",      "genfsm",        Abc_CommandGenFsm,           0 );
+    Cmd_CommandAdd( pAbc, "Various",      "cover",         Abc_CommandCover,            1 );
+    Cmd_CommandAdd( pAbc, "Various",      "double",        Abc_CommandDouble,           1 );
+    Cmd_CommandAdd( pAbc, "Various",      "inter",         Abc_CommandInter,            1 );
+    Cmd_CommandAdd( pAbc, "Various",      "bb2wb",         Abc_CommandBb2Wb,            0 );
+    Cmd_CommandAdd( pAbc, "Various",      "outdec",        Abc_CommandOutdec,           1 );
+    Cmd_CommandAdd( pAbc, "Various",      "nodedup",       Abc_CommandNodeDup,          1 );
+    Cmd_CommandAdd( pAbc, "Various",      "testcolor",     Abc_CommandTestColor,        0 );
+    Cmd_CommandAdd( pAbc, "Various",      "test",          Abc_CommandTest,             0 );
+//    Cmd_CommandAdd( pAbc, "Various",      "qbf_solve",     Abc_CommandTest,               0 );
+
+    Cmd_CommandAdd( pAbc, "Various",      "qvar",          Abc_CommandQuaVar,           1 );
+    Cmd_CommandAdd( pAbc, "Various",      "qrel",          Abc_CommandQuaRel,           1 );
+    Cmd_CommandAdd( pAbc, "Various",      "qreach",        Abc_CommandQuaReach,         1 );
+    Cmd_CommandAdd( pAbc, "Various",      "senseinput",    Abc_CommandSenseInput,       1 );
+    Cmd_CommandAdd( pAbc, "Various",      "npnload",       Abc_CommandNpnLoad,          0 );
+    Cmd_CommandAdd( pAbc, "Various",      "npnsave",       Abc_CommandNpnSave,          0 );
+
+    Cmd_CommandAdd( pAbc, "Various",      "send_aig",      Abc_CommandSendAig,          0 );
+    Cmd_CommandAdd( pAbc, "Various",      "send_status",   Abc_CommandSendStatus,       0 );
+
+    Cmd_CommandAdd( pAbc, "New AIG",      "istrash",       Abc_CommandIStrash,          1 );
+    Cmd_CommandAdd( pAbc, "New AIG",      "icut",          Abc_CommandICut,             0 );
+    Cmd_CommandAdd( pAbc, "New AIG",      "irw",           Abc_CommandIRewrite,         1 );
+    Cmd_CommandAdd( pAbc, "New AIG",      "drw",           Abc_CommandDRewrite,         1 );
+    Cmd_CommandAdd( pAbc, "New AIG",      "drf",           Abc_CommandDRefactor,        1 );
+    Cmd_CommandAdd( pAbc, "New AIG",      "dc2",           Abc_CommandDc2,              1 );
+    Cmd_CommandAdd( pAbc, "New AIG",      "dchoice",       Abc_CommandDChoice,          1 );
+    Cmd_CommandAdd( pAbc, "New AIG",      "dch",           Abc_CommandDch,              1 );
+    Cmd_CommandAdd( pAbc, "New AIG",      "drwsat",        Abc_CommandDrwsat,           1 );
+    Cmd_CommandAdd( pAbc, "New AIG",      "irws",          Abc_CommandIRewriteSeq,      1 );
+    Cmd_CommandAdd( pAbc, "New AIG",      "iresyn",        Abc_CommandIResyn,           1 );
+    Cmd_CommandAdd( pAbc, "New AIG",      "isat",          Abc_CommandISat,             1 );
+    Cmd_CommandAdd( pAbc, "New AIG",      "ifraig",        Abc_CommandIFraig,           1 );
+    Cmd_CommandAdd( pAbc, "New AIG",      "dfraig",        Abc_CommandDFraig,           1 );
+    Cmd_CommandAdd( pAbc, "New AIG",      "csweep",        Abc_CommandCSweep,           1 );
+//    Cmd_CommandAdd( pAbc, "New AIG",      "haig",          Abc_CommandHaig,             1 );
+    Cmd_CommandAdd( pAbc, "New AIG",      "qbf",           Abc_CommandQbf,              0 );
+
+    Cmd_CommandAdd( pAbc, "Fraiging",     "fraig",         Abc_CommandFraig,            1 );
+    Cmd_CommandAdd( pAbc, "Fraiging",     "fraig_trust",   Abc_CommandFraigTrust,       1 );
+    Cmd_CommandAdd( pAbc, "Fraiging",     "fraig_store",   Abc_CommandFraigStore,       0 );
+    Cmd_CommandAdd( pAbc, "Fraiging",     "fraig_restore", Abc_CommandFraigRestore,     1 );
+    Cmd_CommandAdd( pAbc, "Fraiging",     "fraig_clean",   Abc_CommandFraigClean,       0 );
+    Cmd_CommandAdd( pAbc, "Fraiging",     "fraig_sweep",   Abc_CommandFraigSweep,       1 );
+    Cmd_CommandAdd( pAbc, "Fraiging",     "dress",         Abc_CommandFraigDress,       1 );
+
+    Cmd_CommandAdd( pAbc, "Choicing",     "rec_start3",    Abc_CommandRecStart3,        0 );
+    Cmd_CommandAdd( pAbc, "Choicing",     "rec_stop3",     Abc_CommandRecStop3,         0 );
+    Cmd_CommandAdd( pAbc, "Choicing",     "rec_ps3",       Abc_CommandRecPs3,           0 );
+    Cmd_CommandAdd( pAbc, "Choicing",     "rec_add3",      Abc_CommandRecAdd3,          0 );
+    Cmd_CommandAdd( pAbc, "Choicing",     "rec_dump3",     Abc_CommandRecDump3,         0 );
+    Cmd_CommandAdd( pAbc, "Choicing",     "rec_merge3",    Abc_CommandRecMerge3,        0 );
+
+    Cmd_CommandAdd( pAbc, "SC mapping",   "map",           Abc_CommandMap,              1 );
+    Cmd_CommandAdd( pAbc, "SC mapping",   "amap",          Abc_CommandAmap,             1 );
+    Cmd_CommandAdd( pAbc, "SC mapping",   "unmap",         Abc_CommandUnmap,            1 );
+    Cmd_CommandAdd( pAbc, "SC mapping",   "attach",        Abc_CommandAttach,           1 );
+    Cmd_CommandAdd( pAbc, "SC mapping",   "superc",        Abc_CommandSuperChoice,      1 );
+    Cmd_CommandAdd( pAbc, "SC mapping",   "supercl",       Abc_CommandSuperChoiceLut,   1 );
+
+//    Cmd_CommandAdd( pAbc, "FPGA mapping", "fpga",          Abc_CommandFpga,             1 );
+//    Cmd_CommandAdd( pAbc, "FPGA mapping", "ffpga",         Abc_CommandFpgaFast,         1 );
+    Cmd_CommandAdd( pAbc, "FPGA mapping", "if",            Abc_CommandIf,               1 );
+    Cmd_CommandAdd( pAbc, "FPGA mapping", "ifif",          Abc_CommandIfif,             1 );
+
+    Cmd_CommandAdd( pAbc, "DSD manager",  "dsd_save",      Abc_CommandDsdSave,          0 );
+    Cmd_CommandAdd( pAbc, "DSD manager",  "dsd_load",      Abc_CommandDsdLoad,          0 );
+    Cmd_CommandAdd( pAbc, "DSD manager",  "dsd_free",      Abc_CommandDsdFree,          0 );
+    Cmd_CommandAdd( pAbc, "DSD manager",  "dsd_ps",        Abc_CommandDsdPs,            0 );
+    Cmd_CommandAdd( pAbc, "DSD manager",  "dsd_tune",      Abc_CommandDsdTune,          0 );
+    Cmd_CommandAdd( pAbc, "DSD manager",  "dsd_merge",     Abc_CommandDsdMerge,         0 );
+    Cmd_CommandAdd( pAbc, "DSD manager",  "dsd_clean",     Abc_CommandDsdClean,         0 );
+
+//    Cmd_CommandAdd( pAbc, "Sequential",   "scut",          Abc_CommandScut,             0 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "init",          Abc_CommandInit,             1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "zero",          Abc_CommandZero,             1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "undc",          Abc_CommandUndc,             1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "onehot",        Abc_CommandOneHot,           1 );
+//    Cmd_CommandAdd( pAbc, "Sequential",   "pipe",          Abc_CommandPipe,             1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "retime",        Abc_CommandRetime,           1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "dretime",       Abc_CommandDRetime,          1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "fretime",       Abc_CommandFlowRetime,       1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "cretime",       Abc_CommandCRetime,          1 );
+//    Cmd_CommandAdd( pAbc, "Sequential",   "sfpga",         Abc_CommandSeqFpga,          1 );
+//    Cmd_CommandAdd( pAbc, "Sequential",   "smap",          Abc_CommandSeqMap,           1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "ssweep",        Abc_CommandSeqSweep,         1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "scorr",         Abc_CommandSeqSweep2,        1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "testssw",       Abc_CommandTestSeqSweep,     0 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "testscorr",     Abc_CommandTestScorr,        0 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "lcorr",         Abc_CommandLcorr,            1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "scleanup",      Abc_CommandSeqCleanup,       1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "cycle",         Abc_CommandCycle,            1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "xsim",          Abc_CommandXsim,             0 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "sim",           Abc_CommandSim,              0 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "sim3",          Abc_CommandSim3,             0 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "phase",         Abc_CommandDarPhase,         1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "synch",         Abc_CommandSynch,            1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "clockgate",     Abc_CommandClockGate,        1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "extwin",        Abc_CommandExtWin,           1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "inswin",        Abc_CommandInsWin,           1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "permute",       Abc_CommandPermute,          1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "unpermute",     Abc_CommandUnpermute,        1 );
+    Cmd_CommandAdd( pAbc, "Sequential",   "cubeenum",      Abc_CommandCubeEnum,         0 );
+
+    Cmd_CommandAdd( pAbc, "Verification", "cec",           Abc_CommandCec,              0 );
+    Cmd_CommandAdd( pAbc, "Verification", "dcec",          Abc_CommandDCec,             0 );
+    Cmd_CommandAdd( pAbc, "Verification", "dsec",          Abc_CommandDSec,             0 );
+    Cmd_CommandAdd( pAbc, "Verification", "dprove",        Abc_CommandDProve,           0 );
+    Cmd_CommandAdd( pAbc, "Verification", "absec",         Abc_CommandAbSec,            0 );
+    Cmd_CommandAdd( pAbc, "Verification", "simsec",        Abc_CommandSimSec,           0 );
+    Cmd_CommandAdd( pAbc, "Verification", "match",         Abc_CommandMatch,            0 );
+    Cmd_CommandAdd( pAbc, "Verification", "sat",           Abc_CommandSat,              0 );
+    Cmd_CommandAdd( pAbc, "Verification", "dsat",          Abc_CommandDSat,             0 );
+    Cmd_CommandAdd( pAbc, "Verification", "psat",          Abc_CommandPSat,             0 );
+    Cmd_CommandAdd( pAbc, "Verification", "prove",         Abc_CommandProve,            1 );
+    Cmd_CommandAdd( pAbc, "Verification", "iprove",        Abc_CommandIProve,           1 );
+    Cmd_CommandAdd( pAbc, "Verification", "debug",         Abc_CommandDebug,            0 );
+    Cmd_CommandAdd( pAbc, "Verification", "bmc",           Abc_CommandBmc,              0 );
+    Cmd_CommandAdd( pAbc, "Verification", "bmc2",          Abc_CommandBmc2,             0 );
+    Cmd_CommandAdd( pAbc, "Verification", "bmc3",          Abc_CommandBmc3,             1 );
+    Cmd_CommandAdd( pAbc, "Verification", "int",           Abc_CommandBmcInter,         1 );
+    Cmd_CommandAdd( pAbc, "Verification", "indcut",        Abc_CommandIndcut,           0 );
+    Cmd_CommandAdd( pAbc, "Verification", "enlarge",       Abc_CommandEnlarge,          1 );
+    Cmd_CommandAdd( pAbc, "Verification", "tempor",        Abc_CommandTempor,           1 );
+    Cmd_CommandAdd( pAbc, "Verification", "ind",           Abc_CommandInduction,        0 );
+    Cmd_CommandAdd( pAbc, "Verification", "constr",        Abc_CommandConstr,           0 );
+    Cmd_CommandAdd( pAbc, "Verification", "unfold",        Abc_CommandUnfold,           1 );
+    Cmd_CommandAdd( pAbc, "Verification", "fold",          Abc_CommandFold,             1 );
+    Cmd_CommandAdd( pAbc, "Verification", "unfold2",       Abc_CommandUnfold2,          1 );    // jlong 
+    Cmd_CommandAdd( pAbc, "Verification", "fold2",         Abc_CommandFold2,            1 );    // jlong 
+    Cmd_CommandAdd( pAbc, "Verification", "bm",            Abc_CommandBm,               1 );
+    Cmd_CommandAdd( pAbc, "Verification", "bm2",           Abc_CommandBm2,              1 );
+    Cmd_CommandAdd( pAbc, "Verification", "saucy3",        Abc_CommandSaucy,            1 );
+    Cmd_CommandAdd( pAbc, "Verification", "testcex",       Abc_CommandTestCex,          0 );
+    Cmd_CommandAdd( pAbc, "Verification", "pdr",           Abc_CommandPdr,              0 );
+    Cmd_CommandAdd( pAbc, "Verification", "reconcile",     Abc_CommandReconcile,        1 );
+    Cmd_CommandAdd( pAbc, "Verification", "cexsave",       Abc_CommandCexSave,          0 );
+    Cmd_CommandAdd( pAbc, "Verification", "cexload",       Abc_CommandCexLoad,          0 );
+    Cmd_CommandAdd( pAbc, "Verification", "cexcut",        Abc_CommandCexCut,           0 );
+    Cmd_CommandAdd( pAbc, "Verification", "cexmerge",      Abc_CommandCexMerge,         0 );
+//    Cmd_CommandAdd( pAbc, "Verification", "cexmin",        Abc_CommandCexMin,           0 );
+    Cmd_CommandAdd( pAbc, "Verification", "dualrail",      Abc_CommandDualRail,         1 );
+    Cmd_CommandAdd( pAbc, "Verification", "blockpo",       Abc_CommandBlockPo,          1 );
+    Cmd_CommandAdd( pAbc, "Verification", "iso",           Abc_CommandIso,              1 );
+
+    Cmd_CommandAdd( pAbc, "ABC9",         "&get",          Abc_CommandAbc9Get,          0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&put",          Abc_CommandAbc9Put,          0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&r",            Abc_CommandAbc9Read,         0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&read_blif",    Abc_CommandAbc9ReadBlif,     0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&read_cblif",   Abc_CommandAbc9ReadCBlif,    0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&read_stg",     Abc_CommandAbc9ReadStg,      0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&w",            Abc_CommandAbc9Write,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&ps",           Abc_CommandAbc9Ps,           0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&pfan",         Abc_CommandAbc9PFan,         0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&psig",         Abc_CommandAbc9PSig,         0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&status",       Abc_CommandAbc9Status,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&mux_profile",  Abc_CommandAbc9MuxProfile,   0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&show",         Abc_CommandAbc9Show,         0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&st",           Abc_CommandAbc9Strash,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&topand",       Abc_CommandAbc9Topand,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&add1hot",      Abc_CommandAbc9Add1Hot,      0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&cof",          Abc_CommandAbc9Cof,          0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&trim",         Abc_CommandAbc9Trim,         0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&dfs",          Abc_CommandAbc9Dfs,          0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&sim",          Abc_CommandAbc9Sim,          0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&sim3",         Abc_CommandAbc9Sim3,         0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&resim",        Abc_CommandAbc9Resim,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&speci",        Abc_CommandAbc9SpecI,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&equiv",        Abc_CommandAbc9Equiv,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&equiv2",       Abc_CommandAbc9Equiv2,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&equiv3",       Abc_CommandAbc9Equiv3,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&semi",         Abc_CommandAbc9Semi,         0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&times",        Abc_CommandAbc9Times,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&frames",       Abc_CommandAbc9Frames,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&retime",       Abc_CommandAbc9Retime,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&enable",       Abc_CommandAbc9Enable,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&dc2",          Abc_CommandAbc9Dc2,          0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&bidec",        Abc_CommandAbc9Bidec,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&shrink",       Abc_CommandAbc9Shrink,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&fx",           Abc_CommandAbc9Fx,           0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&b",            Abc_CommandAbc9Balance,      0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&blut",         Abc_CommandAbc9BalanceLut,   0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&syn2",         Abc_CommandAbc9Syn2,         0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&syn3",         Abc_CommandAbc9Syn3,         0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&syn4",         Abc_CommandAbc9Syn4,         0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&false",        Abc_CommandAbc9False,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&miter",        Abc_CommandAbc9Miter,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&miter2",       Abc_CommandAbc9Miter2,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&append",       Abc_CommandAbc9Append,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&scl",          Abc_CommandAbc9Scl,          0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&lcorr",        Abc_CommandAbc9Lcorr,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&scorr",        Abc_CommandAbc9Scorr,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&choice",       Abc_CommandAbc9Choice,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&sat",          Abc_CommandAbc9Sat,          0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&fraig",        Abc_CommandAbc9Fraig,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&cfraig",       Abc_CommandAbc9CFraig,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&srm",          Abc_CommandAbc9Srm,          0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&srm2",         Abc_CommandAbc9Srm2,         0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&filter",       Abc_CommandAbc9Filter,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&reduce",       Abc_CommandAbc9Reduce,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&equiv_mark",   Abc_CommandAbc9EquivMark,    0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&equiv_filter", Abc_CommandAbc9EquivFilter,  0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&cec",          Abc_CommandAbc9Cec,          0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&verify",       Abc_CommandAbc9Verify,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&sweep",        Abc_CommandAbc9Sweep,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&force",        Abc_CommandAbc9Force,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&embed",        Abc_CommandAbc9Embed,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&sopb",         Abc_CommandAbc9Sopb,         0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&if",           Abc_CommandAbc9If,           0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&iff",          Abc_CommandAbc9Iff,          0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&if2",          Abc_CommandAbc9If2,          0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&jf",           Abc_CommandAbc9Jf,           0 );
+#ifdef ABC_USE_PTHREADS
+    Cmd_CommandAdd( pAbc, "ABC9",         "&kf",           Abc_CommandAbc9Kf,           0 );
+#endif
+    Cmd_CommandAdd( pAbc, "ABC9",         "&lf",           Abc_CommandAbc9Lf,           0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&mf",           Abc_CommandAbc9Mf,           0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&nf",           Abc_CommandAbc9Nf,           0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&struct",       Abc_CommandAbc9Struct,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&trace",        Abc_CommandAbc9Trace,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&speedup",      Abc_CommandAbc9Speedup,      0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&era",          Abc_CommandAbc9Era,          0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&dch",          Abc_CommandAbc9Dch,          0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&rpm",          Abc_CommandAbc9Rpm,          0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&back_reach",   Abc_CommandAbc9BackReach,    0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&posplit",      Abc_CommandAbc9Posplit,      0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&reachm",       Abc_CommandAbc9ReachM,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&reachp",       Abc_CommandAbc9ReachP,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&reachn",       Abc_CommandAbc9ReachN,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&reachy",       Abc_CommandAbc9ReachY,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&undo",         Abc_CommandAbc9Undo,         0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&iso",          Abc_CommandAbc9Iso,          0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&cexinfo",      Abc_CommandAbc9CexInfo,      0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&cycle",        Abc_CommandAbc9Cycle,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&cone",         Abc_CommandAbc9Cone,         0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&slice",        Abc_CommandAbc9Slice,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&popart",       Abc_CommandAbc9PoPart,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&gprove",       Abc_CommandAbc9GroupProve,   0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&mprove",       Abc_CommandAbc9MultiProve,   0 );
+#ifdef ABC_USE_PTHREADS
+    Cmd_CommandAdd( pAbc, "ABC9",         "&splitprove",   Abc_CommandAbc9SplitProve,   0 );
+#endif
+    Cmd_CommandAdd( pAbc, "ABC9",         "&bmc",          Abc_CommandAbc9Bmc,          0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&bcore",        Abc_CommandAbc9BCore,        0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&icheck",       Abc_CommandAbc9ICheck,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&sattest",      Abc_CommandAbc9SatTest,      0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&fftest",       Abc_CommandAbc9FFTest,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&inse",         Abc_CommandAbc9Inse,         0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&maxi",         Abc_CommandAbc9Maxi,         0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&bmci",         Abc_CommandAbc9Bmci,         0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&poxsim",       Abc_CommandAbc9PoXsim,       0 );
+    Cmd_CommandAdd( pAbc, "ABC9",         "&demiter",      Abc_CommandAbc9Demiter,      0 );
+//    Cmd_CommandAdd( pAbc, "ABC9",         "&popart2",      Abc_CommandAbc9PoPart2,      0 );
+//    Cmd_CommandAdd( pAbc, "ABC9",         "&cexcut",       Abc_CommandAbc9CexCut,       0 );
+//    Cmd_CommandAdd( pAbc, "ABC9",         "&cexmerge",     Abc_CommandAbc9CexMerge,     0 );
+//    Cmd_CommandAdd( pAbc, "ABC9",         "&cexmin",       Abc_CommandAbc9CexMin,       0 );
+
+    Cmd_CommandAdd( pAbc, "Abstraction",  "&abs_derive",   Abc_CommandAbc9AbsDerive,    0 );
+    Cmd_CommandAdd( pAbc, "Abstraction",  "&abs_refine",   Abc_CommandAbc9AbsRefine,    0 );
+    Cmd_CommandAdd( pAbc, "Abstraction",  "&gla_derive",   Abc_CommandAbc9GlaDerive,    0 );
+    Cmd_CommandAdd( pAbc, "Abstraction",  "&gla_refine",   Abc_CommandAbc9GlaRefine,    0 );
+    Cmd_CommandAdd( pAbc, "Abstraction",  "&gla_shrink",   Abc_CommandAbc9GlaShrink,    0 );
+    Cmd_CommandAdd( pAbc, "Abstraction",  "&gla",          Abc_CommandAbc9Gla,          0 );
+    Cmd_CommandAdd( pAbc, "Abstraction",  "&vta",          Abc_CommandAbc9Vta,          0 );
+    Cmd_CommandAdd( pAbc, "Abstraction",  "&vta_gla",      Abc_CommandAbc9Vta2Gla,      0 );
+    Cmd_CommandAdd( pAbc, "Abstraction",  "&gla_vta",      Abc_CommandAbc9Gla2Vta,      0 );
+    Cmd_CommandAdd( pAbc, "Abstraction",  "&fla_gla",      Abc_CommandAbc9Fla2Gla,      0 );
+    Cmd_CommandAdd( pAbc, "Abstraction",  "&gla_fla",      Abc_CommandAbc9Gla2Fla,      0 );
+
+    Cmd_CommandAdd( pAbc, "Liveness",     "l2s",           Abc_CommandAbcLivenessToSafety,        0 );
+    Cmd_CommandAdd( pAbc, "Liveness",     "l2ssim",        Abc_CommandAbcLivenessToSafetySim,     0 );
+    Cmd_CommandAdd( pAbc, "Liveness",     "l3s",           Abc_CommandAbcLivenessToSafetyWithLTL, 0 );
+    Cmd_CommandAdd( pAbc, "Liveness",     "kcs",           Abc_CommandCS_kLiveness,               0 );
+    Cmd_CommandAdd( pAbc, "Liveness",     "nck",           Abc_CommandNChooseK,                   0 );
+
+    Cmd_CommandAdd( pAbc, "ABC9",         "&test",         Abc_CommandAbc9Test,         0 );
+    {
+//        extern Mf_ManTruthCount();
+//        Mf_ManTruthCount();
+    }
+
+    {
+        extern void Dar_LibStart();
+        Dar_LibStart();
+    }
+    {
+//        extern void Dau_DsdTest();
+//        Dau_DsdTest();
+//        extern void If_ManSatTest();
+//        If_ManSatTest();
+    }
+
+    if ( Sdm_ManCanRead() )
+        Sdm_ManRead();
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_End( Abc_Frame_t * pAbc )
+{
+    extern Abc_Frame_t * Abc_FrameGetGlobalFrame();
+    Abc_FrameClearDesign();
+    Cnf_ManFree();
+    {
+        extern int Abc_NtkCompareAndSaveBest( Abc_Ntk_t * pNtk );
+        Abc_NtkCompareAndSaveBest( NULL );
+    }
+    {
+        extern void Dar_LibStop();
+        Dar_LibStop();
+    }
+    {
+        extern void Aig_RManQuit();
+        Aig_RManQuit();
+    }
+    {
+        extern void Npn_ManClean();
+        Npn_ManClean();
+    }
+    {
+        extern void Sdm_ManQuit();
+        Sdm_ManQuit();
+    }
+    Abc_NtkFraigStoreClean();
+    if ( Abc_FrameGetGlobalFrame()->pGia )
+        Gia_ManStop( Abc_FrameGetGlobalFrame()->pGia );
+    if ( Abc_FrameGetGlobalFrame()->pGia2 )
+        Gia_ManStop( Abc_FrameGetGlobalFrame()->pGia2 );
+    if ( Abc_NtkRecIsRunning3() )
+        Abc_NtkRecStop3();
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int fFactor;
+    int fSaveBest;
+    int fDumpResult;
+    int fUseLutLib;
+    int fPrintTime;
+    int fPrintMuxes;
+    int fPower;
+    int fGlitch;
+    int fSkipBuf;
+    int c;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set the defaults
+    fFactor   = 0;
+    fSaveBest = 0;
+    fDumpResult = 0;
+    fUseLutLib = 0;
+    fPrintTime = 0;
+    fPrintMuxes = 0;
+    fPower = 0;
+    fGlitch = 0;
+    fSkipBuf = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "fbdltmpgsh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'f':
+            fFactor ^= 1;
+            break;
+        case 'b':
+            fSaveBest ^= 1;
+            break;
+        case 'd':
+            fDumpResult ^= 1;
+            break;
+        case 'l':
+            fUseLutLib ^= 1;
+            break;
+        case 't':
+            fPrintTime ^= 1;
+            break;
+        case 'm':
+            fPrintMuxes ^= 1;
+            break;
+        case 'p':
+            fPower ^= 1;
+            break;
+        case 'g':
+            fGlitch ^= 1;
+            break;
+        case 's':
+            fSkipBuf ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) && fUseLutLib )
+    {
+        Abc_Print( -1, "Cannot print LUT delay for a non-logic network.\n" );
+        return 1;
+    }
+    Abc_NtkPrintStats( pNtk, fFactor, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf );
+    if ( fPrintTime )
+    {
+        pAbc->TimeTotal += pAbc->TimeCommand;
+        Abc_Print( 1, "elapse: %3.2f seconds, total: %3.2f seconds\n", pAbc->TimeCommand, pAbc->TimeTotal );
+        pAbc->TimeCommand = 0.0;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_stats [-fbdltmpgsh]\n" );
+    Abc_Print( -2, "\t        prints the network statistics\n" );
+    Abc_Print( -2, "\t-f    : toggles printing the literal count in the factored forms [default = %s]\n", fFactor? "yes": "no" );
+    Abc_Print( -2, "\t-b    : toggles saving the best logic network in \"best.blif\" [default = %s]\n", fSaveBest? "yes": "no" );
+    Abc_Print( -2, "\t-d    : toggles dumping network into file \"<input_file_name>_dump.blif\" [default = %s]\n", fDumpResult? "yes": "no" );
+    Abc_Print( -2, "\t-l    : toggles printing delay of LUT mapping using LUT library [default = %s]\n", fSaveBest? "yes": "no" );
+    Abc_Print( -2, "\t-t    : toggles printing runtime statistics [default = %s]\n", fPrintTime? "yes": "no" );
+    Abc_Print( -2, "\t-m    : toggles printing MUX statistics [default = %s]\n", fPrintMuxes? "yes": "no" );
+    Abc_Print( -2, "\t-p    : toggles printing power dissipation due to switching [default = %s]\n", fPower? "yes": "no" );
+    Abc_Print( -2, "\t-g    : toggles printing percentage of increased power due to glitching [default = %s]\n", fGlitch? "yes": "no" );
+    Abc_Print( -2, "\t-s    : toggles not counting single-output nodes as nodes [default = %s]\n", fSkipBuf? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintExdc( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkTemp;
+    double Percentage;
+    int fShort;
+    int c;
+    int fPrintDc;
+    extern double Abc_NtkSpacePercentage( Abc_Obj_t * pNode );
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set the defaults
+    fShort  = 1;
+    fPrintDc = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "sdh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 's':
+            fShort ^= 1;
+            break;
+        case 'd':
+            fPrintDc ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( pNtk->pExdc == NULL )
+    {
+        Abc_Print( -1, "Network has no EXDC.\n" );
+        return 1;
+    }
+
+    if ( fPrintDc )
+    {
+        if ( !Abc_NtkIsStrash(pNtk->pExdc) )
+        {
+            pNtkTemp = Abc_NtkStrash(pNtk->pExdc, 0, 0, 0);
+            Percentage = Abc_NtkSpacePercentage( Abc_ObjChild0( Abc_NtkPo(pNtkTemp, 0) ) );
+            Abc_NtkDelete( pNtkTemp );
+        }
+        else
+            Percentage = Abc_NtkSpacePercentage( Abc_ObjChild0( Abc_NtkPo(pNtk->pExdc, 0) ) );
+
+        Abc_Print( 1, "EXDC network statistics: " );
+        Abc_Print( 1, "(" );
+        if ( Percentage > 0.05 && Percentage < 99.95 )
+            Abc_Print( 1, "%.2f", Percentage );
+        else if ( Percentage > 0.000005 && Percentage < 99.999995 )
+            Abc_Print( 1, "%.6f", Percentage );
+        else
+            Abc_Print( 1, "%f", Percentage );
+        Abc_Print( 1, " %% don't-cares)\n" );
+    }
+    else
+        Abc_Print( 1, "EXDC network statistics: \n" );
+    Abc_NtkPrintStats( pNtk->pExdc, 0, 0, 0, 0, 0, 0, 0, 0 );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_exdc [-dh]\n" );
+    Abc_Print( -2, "\t        prints the EXDC network statistics\n" );
+    Abc_Print( -2, "\t-d    : toggles printing don't-care percentage [default = %s]\n", fPrintDc? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Abc_Obj_t * pNode;
+    int c, fPrintFlops = 1;
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "fh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'f':
+            fPrintFlops ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( argc > globalUtilOptind + 1 )
+    {
+        Abc_Print( -1, "Wrong number of auguments.\n" );
+        goto usage;
+    }
+
+    if ( argc == globalUtilOptind + 1 )
+    {
+        pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+        if ( pNode == NULL )
+        {
+            Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+            return 1;
+        }
+        Abc_NodePrintFanio( stdout, pNode );
+        return 0;
+    }
+    // print the nodes
+    Abc_NtkPrintIo( stdout, pNtk, fPrintFlops );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_io [-fh] <node>\n" );
+    Abc_Print( -2, "\t        prints the PIs/POs/flops or fanins/fanouts of a node\n" );
+    Abc_Print( -2, "\t-f    : toggles printing flops [default = %s]\n", fPrintFlops? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    Abc_Print( -2, "\tnode  : the node to print fanins/fanouts\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintLatch( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fPrintSccs;
+    extern void Abc_NtkPrintSccs( Abc_Ntk_t * pNtk, int fVerbose );
+
+    // set defaults
+    fPrintSccs = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 's':
+            fPrintSccs ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    // print the nodes
+    Abc_NtkPrintLatch( stdout, pNtk );
+    if ( fPrintSccs )
+        Abc_NtkPrintSccs( pNtk, 0 );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_latch [-sh]\n" );
+    Abc_Print( -2, "\t        prints information about latches\n" );
+    Abc_Print( -2, "\t-s    : toggles printing SCCs of registers [default = %s]\n", fPrintSccs? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintFanio( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fUsePis   = 0;
+    int fMffc     = 0;
+    int fVerbose  = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "imvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'i':
+            fUsePis ^= 1;
+            break;
+        case 'm':
+            fMffc ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    // print the nodes
+    if ( fVerbose )
+        Abc_NtkPrintFanio( stdout, pNtk, fUsePis );
+    else
+        Abc_NtkPrintFanioNew( stdout, pNtk, fMffc );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_fanio [-imvh]\n" );
+    Abc_Print( -2, "\t        prints the statistics about fanins/fanouts of all nodes\n" );
+    Abc_Print( -2, "\t-i    : toggles considering fanouts of primary inputs only [default = %s]\n", fUsePis? "yes": "no" );
+    Abc_Print( -2, "\t-m    : toggles printing MFFC sizes instead of fanouts [default = %s]\n", fMffc? "yes": "no" );
+    Abc_Print( -2, "\t-v    : toggles verbose way of printing the stats [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintMffc( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    extern void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk );
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    // print the nodes
+    Abc_NtkPrintMffc( stdout, pNtk );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_mffc [-h]\n" );
+    Abc_Print( -2, "\t        prints the MFFC of each node in the network\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Abc_Obj_t * pNode;
+    int c;
+    int fUseRealNames;
+
+    // set defaults
+    fUseRealNames = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'n':
+            fUseRealNames ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsSopLogic(pNtk) )
+    {
+        Abc_Print( -1, "Printing factored forms can be done for SOP networks.\n" );
+        return 1;
+    }
+
+    if ( argc > globalUtilOptind + 1 )
+    {
+        Abc_Print( -1, "Wrong number of auguments.\n" );
+        goto usage;
+    }
+
+    if ( argc == globalUtilOptind + 1 )
+    {
+        pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+        if ( pNode == NULL )
+        {
+            Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+            return 1;
+        }
+        Abc_NodePrintFactor( stdout, pNode, fUseRealNames );
+        return 0;
+    }
+    // print the nodes
+    Abc_NtkPrintFactor( stdout, pNtk, fUseRealNames );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_factor [-nh] <node>\n" );
+    Abc_Print( -2, "\t        prints the factored forms of nodes\n" );
+    Abc_Print( -2, "\t-n    : toggles real/dummy fanin names [default = %s]\n", fUseRealNames? "real": "dummy" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    Abc_Print( -2, "\tnode  : (optional) one node to consider\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Abc_Obj_t * pNode;
+    int c;
+    int fListNodes;
+    int fProfile;
+    int fVerbose;
+
+    // set defaults
+    fListNodes = 0;
+    fProfile   = 1;
+    fVerbose   = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "npvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'n':
+            fListNodes ^= 1;
+            break;
+        case 'p':
+            fProfile ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !fProfile && !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for AIGs (run \"strash\").\n" );
+        return 1;
+    }
+
+    if ( argc > globalUtilOptind + 1 )
+    {
+        Abc_Print( -1, "Wrong number of auguments.\n" );
+        goto usage;
+    }
+
+    if ( argc == globalUtilOptind + 1 )
+    {
+        pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+        if ( pNode == NULL )
+        {
+            Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+            return 1;
+        }
+        Abc_NodePrintLevel( stdout, pNode );
+        return 0;
+    }
+    // process all COs
+    Abc_NtkPrintLevel( stdout, pNtk, fProfile, fListNodes, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_level [-npvh] <node>\n" );
+    Abc_Print( -2, "\t        prints information about node level and cone size\n" );
+    Abc_Print( -2, "\t-n    : toggles printing nodes by levels [default = %s]\n", fListNodes? "yes": "no" );
+    Abc_Print( -2, "\t-p    : toggles printing level profile [default = %s]\n", fProfile? "yes": "no" );
+    Abc_Print( -2, "\t-v    : enable verbose output [default = %s].\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    Abc_Print( -2, "\tnode  : (optional) one node to consider\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Vec_Ptr_t * vSuppFun;
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fStruct;
+    int fVerbose;
+    int fVeryVerbose;
+    extern Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose );
+    extern void Abc_NtkPrintStrSupports( Abc_Ntk_t * pNtk, int fMatrix );
+
+    // set defaults
+    fStruct = 1;
+    fVerbose = 0;
+    fVeryVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "svwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 's':
+            fStruct ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    // print support information
+    if ( fStruct )
+    {
+        Abc_NtkPrintStrSupports( pNtk, fVeryVerbose );
+        return 0;
+    }
+
+    if ( !Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for combinational networks (run \"comb\").\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for AIGs (run \"strash\").\n" );
+        return 1;
+    }
+    vSuppFun = Sim_ComputeFunSupp( pNtk, fVerbose );
+    ABC_FREE( vSuppFun->pArray[0] );
+    Vec_PtrFree( vSuppFun );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_supp [-svwh]\n" );
+    Abc_Print( -2, "\t        prints the supports of the CO nodes\n" );
+    Abc_Print( -2, "\t-s    : toggle printing structural support only [default = %s].\n", fStruct? "yes": "no" );
+    Abc_Print( -2, "\t-v    : enable verbose output [default = %s].\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w    : enable printing CI/CO dependency matrix [default = %s].\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fUseBdds;
+    int fNaive;
+    int fReorder;
+    int fVerbose;
+    extern void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose );
+
+    // set defaults
+    fUseBdds = 0;
+    fNaive   = 0;
+    fReorder = 1;
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "bnrvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'b':
+            fUseBdds ^= 1;
+            break;
+        case 'n':
+            fNaive ^= 1;
+            break;
+        case 'r':
+            fReorder ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for combinational networks (run \"comb\").\n" );
+        return 1;
+    }
+    if ( Abc_NtkIsStrash(pNtk) )
+        Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose );
+    else
+    {
+        pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+        Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose );
+        Abc_NtkDelete( pNtk );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_symm [-bnrvh]\n" );
+    Abc_Print( -2, "\t         computes symmetries of the PO functions\n" );
+    Abc_Print( -2, "\t-b     : toggle BDD-based or SAT-based computations [default = %s].\n", fUseBdds? "BDD": "SAT" );
+    Abc_Print( -2, "\t-n     : enable naive BDD-based computation [default = %s].\n", fNaive? "yes": "no" );
+    Abc_Print( -2, "\t-r     : enable dynamic BDD variable reordering [default = %s].\n", fReorder? "yes": "no" );
+    Abc_Print( -2, "\t-v     : enable verbose output [default = %s].\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintUnate( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fUseBdds;
+    int fUseNaive;
+    int fVerbose;
+    extern void Abc_NtkPrintUnate( Abc_Ntk_t * pNtk, int fUseBdds, int fUseNaive, int fVerbose );
+
+    // set defaults
+    fUseBdds  = 1;
+    fUseNaive = 0;
+    fVerbose  = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "bnvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'b':
+            fUseBdds ^= 1;
+            break;
+        case 'n':
+            fUseNaive ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for AIGs (run \"strash\").\n" );
+        return 1;
+    }
+    Abc_NtkPrintUnate( pNtk, fUseBdds, fUseNaive, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_unate [-bnvh]\n" );
+    Abc_Print( -2, "\t         computes unate variables of the PO functions\n" );
+    Abc_Print( -2, "\t-b     : toggle BDD-based or SAT-based computations [default = %s].\n", fUseBdds? "BDD": "SAT" );
+    Abc_Print( -2, "\t-n     : toggle naive BDD-based computation [default = %s].\n", fUseNaive? "yes": "no" );
+    Abc_Print( -2, "\t-v     : enable verbose output [default = %s].\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintAuto( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int Output;
+    int fNaive;
+    int fVerbose;
+    extern void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose );
+
+    // set defaults
+    Output   = -1;
+    fNaive   = 0;
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Onvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'O':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            Output = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Output < 0 )
+                goto usage;
+            break;
+        case 'n':
+            fNaive ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for AIGs (run \"strash\").\n" );
+        return 1;
+    }
+
+
+    Abc_NtkAutoPrint( pNtk, Output, fNaive, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_auto [-O <num>] [-nvh]\n" );
+    Abc_Print( -2, "\t           computes autosymmetries of the PO functions\n" );
+    Abc_Print( -2, "\t-O <num> : (optional) the 0-based number of the output [default = all]\n");
+    Abc_Print( -2, "\t-n       : enable naive BDD-based computation [default = %s].\n", fNaive? "yes": "no" );
+    Abc_Print( -2, "\t-v       : enable verbose output [default = %s].\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintKMap( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Abc_Obj_t * pNode;
+    int c;
+    int fUseRealNames;
+
+    extern void Abc_NodePrintKMap( Abc_Obj_t * pNode, int fUseRealNames );
+
+    // set defaults
+    fUseRealNames = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'n':
+            fUseRealNames ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( argc == globalUtilOptind + 2 )
+    {
+        Abc_NtkShow6VarFunc( argv[globalUtilOptind], argv[globalUtilOptind+1] );
+        return 0;
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "Visualization of Karnaugh maps works for logic networks.\n" );
+        return 1;
+    }
+    if ( argc > globalUtilOptind + 1 )
+    {
+        Abc_Print( -1, "Wrong number of auguments.\n" );
+        goto usage;
+    }
+    if ( argc == globalUtilOptind )
+    {
+        pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) );
+        if ( !Abc_ObjIsNode(pNode) )
+        {
+            Abc_Print( -1, "The driver \"%s\" of the first PO is not an internal node.\n", Abc_ObjName(pNode) );
+            return 1;
+        }
+    }
+    else
+    {
+        pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+        if ( pNode == NULL )
+        {
+            Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+            return 1;
+        }
+    }
+    Abc_NtkToBdd(pNtk);
+    Abc_NodePrintKMap( pNode, fUseRealNames );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_kmap [-nh] <node>\n" );
+    Abc_Print( -2, "\t        shows the truth table of the node\n" );
+    Abc_Print( -2, "\t-n    : toggles real/dummy fanin names [default = %s]\n", fUseRealNames? "real": "dummy" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    Abc_Print( -2, "\t<node>: the node to consider (default = the driver of the first PO)\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintGates( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fUseLibrary;
+
+    extern void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary );
+
+    // set defaults
+    fUseLibrary = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'l':
+            fUseLibrary ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkHasAig(pNtk) )
+    {
+        Abc_Print( -1, "Printing gates does not work for AIGs and sequential AIGs.\n" );
+        return 1;
+    }
+
+    Abc_NtkPrintGates( pNtk, fUseLibrary );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_gates [-lh]\n" );
+    Abc_Print( -2, "\t        prints statistics about gates used in the network\n" );
+    Abc_Print( -2, "\t-l    : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintSharing( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fUseLibrary;
+
+    extern void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk );
+
+    // set defaults
+    fUseLibrary = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'l':
+            fUseLibrary ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    Abc_NtkPrintSharing( pNtk );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_sharing [-h]\n" );
+    Abc_Print( -2, "\t        prints the number of shared nodes in the TFI cones of the COs\n" );
+//    Abc_Print( -2, "\t-l    : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintXCut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fUseLibrary;
+
+    extern int Abc_NtkCrossCut( Abc_Ntk_t * pNtk );
+
+    // set defaults
+    fUseLibrary = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'l':
+            fUseLibrary ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    Abc_NtkCrossCut( pNtk );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_xcut [-h]\n" );
+    Abc_Print( -2, "\t        prints the size of the cross cut of the current network\n" );
+//    Abc_Print( -2, "\t-l    : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintDsd( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fCofactor;
+    int nCofLevel;
+    int fProfile;
+    int fPrintDec;
+
+    extern void Kit_DsdTest( unsigned * pTruth, int nVars );
+    extern void Kit_DsdPrintCofactors( unsigned * pTruth, int nVars, int nCofLevel, int fVerbose );
+    extern void Dau_DecTrySets( word * p, int nVars, int fVerbose );
+
+    // set defaults
+    nCofLevel = 1;
+    fCofactor = 0;
+    fProfile  = 0;
+    fPrintDec = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Npcdh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nCofLevel = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nCofLevel < 0 )
+                goto usage;
+            break;
+        case 'p':
+            fProfile ^= 1;
+            break;
+        case 'c':
+            fCofactor ^= 1;
+            break;
+        case 'd':
+            fPrintDec ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    // get the truth table of the first output
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "Currently works only for logic networks.\n" );
+        return 1;
+    }
+    Abc_NtkToAig( pNtk );
+    // convert it to truth table
+    {
+        Abc_Obj_t * pObj = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) );
+        Vec_Int_t * vMemory;
+        unsigned * pTruth;
+        if ( !Abc_ObjIsNode(pObj) )
+        {
+            Abc_Print( -1, "The fanin of the first PO node does not have a logic function.\n" );
+            return 1;
+        }
+        if ( Abc_ObjFaninNum(pObj) > 16 )
+        {
+            Abc_Print( -1, "Currently works only for up to 16 inputs.\n" );
+            return 1;
+        }
+        vMemory = Vec_IntAlloc(0);
+        pTruth = Hop_ManConvertAigToTruth( (Hop_Man_t *)pNtk->pManFunc, Hop_Regular((Hop_Obj_t *)pObj->pData), Abc_ObjFaninNum(pObj), vMemory, 0 );
+        if ( Hop_IsComplement((Hop_Obj_t *)pObj->pData) )
+            Extra_TruthNot( pTruth, pTruth, Abc_ObjFaninNum(pObj) );
+//        Extra_PrintBinary( stdout, pTruth, 1 << Abc_ObjFaninNum(pObj) );
+//        Abc_Print( -1, "\n" );
+        if ( fPrintDec )//&&Abc_ObjFaninNum(pObj) <= 6 )
+        {
+            word * pTruthW = (word *)pTruth;
+            if ( Abc_ObjFaninNum(pObj) < 6 )
+                pTruthW[0] = Abc_Tt6Stretch( pTruthW[0], Abc_ObjFaninNum(pObj) );
+            Dau_DecTrySets( (word *)pTruth, Abc_ObjFaninNum(pObj), 1 );
+        }
+        if ( fProfile )
+            Kit_TruthPrintProfile( pTruth, Abc_ObjFaninNum(pObj) );
+        else if ( fCofactor )
+            Kit_DsdPrintCofactors( pTruth, Abc_ObjFaninNum(pObj), nCofLevel, 1 );
+        else
+            Kit_DsdTest( pTruth, Abc_ObjFaninNum(pObj) );
+        Vec_IntFree( vMemory );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_dsd [-pcdh] [-N <num>]\n" );
+    Abc_Print( -2, "\t           print DSD formula for a single-output function with less than 16 variables\n" );
+    Abc_Print( -2, "\t-p       : toggle printing profile [default = %s]\n", fProfile? "yes": "no" );
+    Abc_Print( -2, "\t-c       : toggle recursive cofactoring [default = %s]\n", fCofactor? "yes": "no" );
+    Abc_Print( -2, "\t-d       : toggle printing decompositions [default = %s]\n", fPrintDec? "yes": "no" );
+    Abc_Print( -2, "\t-N <num> : the number of levels to cofactor [default = %d]\n", nCofLevel );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintCone( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fUseLibrary;
+
+    // set defaults
+    fUseLibrary = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'l':
+            fUseLibrary ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkLatchNum(pNtk) == 0 )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 1;
+    }
+    Abc_NtkDarPrintCone( pNtk );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_cone [-h]\n" );
+    Abc_Print( -2, "\t        prints cones of influence info for each primary output\n" );
+//    Abc_Print( -2, "\t-l    : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintMiter( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fUseLibrary;
+
+    extern void Abc_NtkPrintMiter( Abc_Ntk_t * pNtk );
+
+    // set defaults
+    fUseLibrary = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'l':
+            fUseLibrary ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "The network is should be structurally hashed.\n" );
+        return 1;
+    }
+    Abc_NtkPrintMiter( pNtk );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_miter [-h]\n" );
+    Abc_Print( -2, "\t        prints the status of the miter\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintStatus( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c, fShort = 1;
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 's':
+            fShort ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    Abc_Print( 1,"Status = %d  Frames = %d   ", pAbc->Status, pAbc->nFrames );
+    if ( pAbc->pCex == NULL && pAbc->vCexVec == NULL )
+        Abc_Print( 1,"Cex is not defined.\n" );
+    else
+    {
+        if ( pAbc->pCex )
+            Abc_CexPrintStats( pAbc->pCex );
+        if ( pAbc->vCexVec )
+        {
+            Abc_Cex_t * pTemp;
+            int nCexes = 0;
+            int Counter = 0;
+            printf( "\n" );
+            Vec_PtrForEachEntry( Abc_Cex_t *, pAbc->vCexVec, pTemp, c )
+            {
+                if ( pTemp == (void *)(ABC_PTRINT_T)1 )
+                {
+                    Counter++;
+                    continue;
+                }
+                if ( pTemp )
+                {
+                    printf( "%4d : ", ++nCexes );
+                    Abc_CexPrintStats( pTemp );
+                }
+            }
+            if ( Counter )
+                printf( "In total, %d (out of %d) outputs are \"sat\" but CEXes are not recorded.\n", Counter, Vec_PtrSize(pAbc->vCexVec) );
+        }
+    }
+    if ( pAbc->vStatuses )
+    {
+        if ( fShort )
+        {
+            printf( "Status array contains %d SAT, %d UNSAT, and %d UNDEC entries (out of %d).", 
+                Vec_IntCountEntry(pAbc->vStatuses, 0), Vec_IntCountEntry(pAbc->vStatuses, 1), 
+                Vec_IntCountEntry(pAbc->vStatuses, -1), Vec_IntSize(pAbc->vStatuses) );
+        }
+        else
+        {
+            int i, Entry;
+            Vec_IntForEachEntry( pAbc->vStatuses, Entry, i )
+                printf( "%d=%d  ", i, Entry );
+        }
+        printf( "\n" );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_status [-sh]\n" );
+    Abc_Print( -2, "\t        prints verification status\n" );
+    Abc_Print( -2, "\t-s    : toggle using short print-out [default = %s]\n", fShort? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintDelay( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Abc_Obj_t * pObjIn = NULL, * pObjOut = NULL;
+    int c;
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsMappedLogic(pNtk) )
+    {
+        Abc_Print( -1, "Delay trace works only for network mapped into standard cells.\n" );
+        return 1;
+    }
+    if ( argc > globalUtilOptind + 2 )
+    {
+        Abc_Print( -1, "Wrong number of auguments.\n" );
+        goto usage;
+    }
+    // collect the first name (PO name)
+    if ( argc >= globalUtilOptind + 1 )
+    {
+        int Num = Nm_ManFindIdByName( pNtk->pManName, argv[globalUtilOptind], ABC_OBJ_PO );
+        if ( Num < 0 )
+            Num = Nm_ManFindIdByName( pNtk->pManName, argv[globalUtilOptind], ABC_OBJ_BI );
+        if ( Num >= 0 )
+            pObjOut = Abc_NtkObj( pNtk, Num );
+        if ( pObjOut == NULL )
+        {
+            Abc_Print( 1, "Cannot find combinational output \"%s\".\n", argv[globalUtilOptind] );
+            return 1;
+        }
+    }
+    // collect the second name (PI name)
+    if ( argc == globalUtilOptind + 2 )
+    {
+        int Num = Nm_ManFindIdByName( pNtk->pManName, argv[globalUtilOptind+1], ABC_OBJ_PI );
+        if ( Num < 0 )
+            Num = Nm_ManFindIdByName( pNtk->pManName, argv[globalUtilOptind+1], ABC_OBJ_BO );
+        if ( Num >= 0 )
+            pObjIn = Abc_NtkObj( pNtk, Num );
+        if ( pObjIn == NULL )
+        {
+            Abc_Print( 1, "Cannot find combinational input \"%s\".\n", argv[globalUtilOptind+1] );
+            return 1;
+        }
+    }
+    Abc_NtkDelayTrace( pNtk, pObjOut, pObjIn, 1 );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: print_delay [-h] <CO_name> <CI_name>\n" );
+    Abc_Print( -2, "\t            prints one critical path of the mapped network\n" );
+    Abc_Print( -2, "\t-h        : print the command usage\n");
+    Abc_Print( -2, "\t<CO_name> : (optional) the sink of the critical path (primary output or flop input)\n");
+    Abc_Print( -2, "\t<CI_name> : (optional) the source of the critical path (primary input or flop output)\n");
+    Abc_Print( -2, "\t            (if CO and/or CI are not given, uses the most critical ones)\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fSeq;
+    int fGateNames;
+    int fUseReverse;
+    int fFlopDep;
+    extern void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse );
+    extern void Abc_NtkShowFlopDependency( Abc_Ntk_t * pNtk );
+
+    // set defaults
+    fSeq        = 0;
+    fGateNames  = 0;
+    fUseReverse = 1;
+    fFlopDep    = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "rsgfh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'r':
+            fUseReverse ^= 1;
+            break;
+        case 's':
+            fSeq ^= 1;
+            break;
+        case 'g':
+            fGateNames ^= 1;
+            break;
+        case 'f':
+            fFlopDep ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( fFlopDep )
+        Abc_NtkShowFlopDependency( pNtk );
+    else
+        Abc_NtkShow( pNtk, fGateNames, fSeq, fUseReverse );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: show [-srgfh]\n" );
+    Abc_Print( -2, "       visualizes the network structure using DOT and GSVIEW\n" );
+#ifdef WIN32
+    Abc_Print( -2, "       \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" );
+    Abc_Print( -2, "       (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" );
+#endif
+    Abc_Print( -2, "\t-s    : toggles visualization of sequential networks [default = %s].\n", fSeq? "yes": "no" );
+    Abc_Print( -2, "\t-r    : toggles ordering nodes in reverse order [default = %s].\n", fUseReverse? "yes": "no" );
+    Abc_Print( -2, "\t-g    : toggles printing gate names for mapped network [default = %s].\n", fGateNames? "yes": "no" );
+    Abc_Print( -2, "\t-f    : toggles visualizing flop dependency graph [default = %s].\n", fFlopDep? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Abc_Obj_t * pNode;
+    int c;
+    extern void Abc_NodeShowBdd( Abc_Obj_t * pNode );
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsBddLogic(pNtk) )
+    {
+        Abc_Print( -1, "Visualizing BDDs can only be done for logic BDD networks (run \"bdd\").\n" );
+        return 1;
+    }
+
+    if ( argc > globalUtilOptind + 1 )
+    {
+        Abc_Print( -1, "Wrong number of auguments.\n" );
+        goto usage;
+    }
+    if ( argc == globalUtilOptind )
+    {
+        pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) );
+        if ( !Abc_ObjIsNode(pNode) )
+        {
+            Abc_Print( -1, "The driver \"%s\" of the first PO is not an internal node.\n", Abc_ObjName(pNode) );
+            return 1;
+        }
+    }
+    else
+    {
+        pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+        if ( pNode == NULL )
+        {
+            Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+            return 1;
+        }
+    }
+    Abc_NodeShowBdd( pNode );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: show_bdd [-h] <node>\n" );
+    Abc_Print( -2, "       visualizes the BDD of a node using DOT and GSVIEW\n" );
+#ifdef WIN32
+    Abc_Print( -2, "       \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" );
+    Abc_Print( -2, "       (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" );
+#endif
+    Abc_Print( -2, "\t<node>: the node to consider [default = the driver of the first PO]\n");
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Abc_Obj_t * pNode;
+    int c;
+    int nNodeSizeMax;
+    int nConeSizeMax;
+    extern void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax );
+
+    // set defaults
+    nNodeSizeMax = 10;
+    nConeSizeMax = ABC_INFINITY;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "NCh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nNodeSizeMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nNodeSizeMax < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConeSizeMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConeSizeMax < 0 )
+                goto usage;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Visualizing cuts only works for AIGs (run \"strash\").\n" );
+        return 1;
+    }
+    if ( argc != globalUtilOptind + 1 )
+    {
+        Abc_Print( -1, "Wrong number of auguments.\n" );
+        goto usage;
+    }
+
+    pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+    if ( pNode == NULL )
+    {
+        Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+        return 1;
+    }
+    Abc_NodeShowCut( pNode, nNodeSizeMax, nConeSizeMax );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: show_cut [-N <num>] [-C <num>] [-h] <node>\n" );
+    Abc_Print( -2, "             visualizes the cut of a node using DOT and GSVIEW\n" );
+#ifdef WIN32
+    Abc_Print( -2, "             \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" );
+    Abc_Print( -2, "             (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" );
+#endif
+    Abc_Print( -2, "\t-N <num> : the max size of the cut to be computed [default = %d]\n", nNodeSizeMax );
+    Abc_Print( -2, "\t-C <num> : the max support of the containing cone [default = %d]\n", nConeSizeMax );
+    Abc_Print( -2, "\t<node>   : the node to consider\n");
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int fVerbose;
+    int fBddSizeMax;
+    int fDualRail;
+    int fReorder;
+    int c;
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set defaults
+    fVerbose = 0;
+    fReorder = 1;
+    fDualRail = 0;
+    fBddSizeMax = ABC_INFINITY;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Brdvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'B':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            fBddSizeMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( fBddSizeMax < 0 )
+                goto usage;
+            break;
+        case 'd':
+            fDualRail ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'r':
+            fReorder ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Can only collapse a logic network or an AIG.\n" );
+        return 1;
+    }
+
+    // get the new network
+    if ( Abc_NtkIsStrash(pNtk) )
+        pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose );
+    else
+    {
+        pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+        pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose );
+        Abc_NtkDelete( pNtk );
+    }
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Collapsing has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: collapse [-B <num>] [-rdvh]\n" );
+    Abc_Print( -2, "\t          collapses the network by constructing global BDDs\n" );
+    Abc_Print( -2, "\t-B <num>: limit on live BDD nodes during collapsing [default = %d]\n", fBddSizeMax );
+    Abc_Print( -2, "\t-r      : toggles dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" );
+    Abc_Print( -2, "\t-d      : toggles dual-rail collapsing mode [default = %s]\n", fDualRail? "yes": "no" );
+    Abc_Print( -2, "\t-v      : print verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h      : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    Abc_Obj_t * pObj;
+    int c;
+    int fAllNodes;
+    int fRecord;
+    int fCleanup;
+    int fComplOuts;
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fAllNodes = 0;
+    fCleanup  = 1;
+    fRecord   = 0;
+    fComplOuts= 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "acrih" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'a':
+            fAllNodes ^= 1;
+            break;
+        case 'c':
+            fCleanup ^= 1;
+            break;
+        case 'r':
+            fRecord ^= 1;
+            break;
+        case 'i':
+            fComplOuts ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    // get the new network
+    pNtkRes = Abc_NtkStrash( pNtk, fAllNodes, fCleanup, fRecord );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Strashing has failed.\n" );
+        return 1;
+    }
+    if ( fComplOuts )
+    Abc_NtkForEachPo( pNtkRes, pObj, c )
+        Abc_ObjXorFaninC( pObj, 0 );
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: strash [-acrih]\n" );
+    Abc_Print( -2, "\t        transforms combinational logic into an AIG\n" );
+    Abc_Print( -2, "\t-a    : toggles between using all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "DFS" );
+    Abc_Print( -2, "\t-c    : toggles cleanup to remove the dagling AIG nodes [default = %s]\n", fCleanup? "all": "DFS" );
+    Abc_Print( -2, "\t-r    : toggles using the record of AIG subgraphs [default = %s]\n", fRecord? "yes": "no" );
+    Abc_Print( -2, "\t-i    : toggles complementing the POs of the AIG [default = %s]\n", fComplOuts? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp;
+    int c;
+    int fDuplicate;
+    int fSelective;
+    int fUpdateLevel;
+    int fExor;
+    int fVerbose;
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set defaults
+    fDuplicate   = 0;
+    fSelective   = 0;
+    fUpdateLevel = 1;
+    fExor        = 0;
+    fVerbose     = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ldsxvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'l':
+            fUpdateLevel ^= 1;
+            break;
+        case 'd':
+            fDuplicate ^= 1;
+            break;
+        case 's':
+            fSelective ^= 1;
+            break;
+        case 'x':
+            fExor ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    // get the new network
+    if ( Abc_NtkIsStrash(pNtk) )
+    {
+        if ( fExor )
+            pNtkRes = Abc_NtkBalanceExor( pNtk, fUpdateLevel, fVerbose );
+        else
+            pNtkRes = Abc_NtkBalance( pNtk, fDuplicate, fSelective, fUpdateLevel );
+    }
+    else
+    {
+        pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+        if ( pNtkTemp == NULL )
+        {
+            Abc_Print( -1, "Strashing before balancing has failed.\n" );
+            return 1;
+        }
+        if ( fExor )
+            pNtkRes = Abc_NtkBalanceExor( pNtkTemp, fUpdateLevel, fVerbose );
+        else
+            pNtkRes = Abc_NtkBalance( pNtkTemp, fDuplicate, fSelective, fUpdateLevel );
+        Abc_NtkDelete( pNtkTemp );
+    }
+
+    // check if balancing worked
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Balancing has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: balance [-ldsxvh]\n" );
+    Abc_Print( -2, "\t        transforms the current network into a well-balanced AIG\n" );
+    Abc_Print( -2, "\t-l    : toggle minimizing the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+    Abc_Print( -2, "\t-d    : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" );
+    Abc_Print( -2, "\t-s    : toggle duplication on the critical paths [default = %s]\n", fSelective? "yes": "no" );
+    Abc_Print( -2, "\t-x    : toggle balancing multi-input EXORs [default = %s]\n", fExor? "yes": "no" );
+    Abc_Print( -2, "\t-v    : print verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandMuxStruct( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int fVerbose;
+
+    extern Abc_Ntk_t * Abc_NtkMuxRestructure( Abc_Ntk_t * pNtk, int fVerbose );
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set defaults
+    fVerbose     = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    // get the new network
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Does not work for a logic network.\n" );
+        return 1;
+    }
+    // check if balancing worked
+//    pNtkRes = Abc_NtkMuxRestructure( pNtk, fVerbose );
+    pNtkRes = NULL;
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "MUX restructuring has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: mux_struct [-vh]\n" );
+    Abc_Print( -2, "\t        performs MUX restructuring of the current network\n" );
+    Abc_Print( -2, "\t-v    : print verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandMulti( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int nThresh, nFaninMax, c;
+    int fCnf;
+    int fMulti;
+    int fSimple;
+    int fFactor;
+    extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set defaults
+    nThresh   =  1;
+    nFaninMax = 20;
+    fCnf      =  0;
+    fMulti    =  1;
+    fSimple   =  0;
+    fFactor   =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "TFmcsfh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nThresh = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nThresh < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFaninMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFaninMax < 0 )
+                goto usage;
+            break;
+        case 'c':
+            fCnf ^= 1;
+            break;
+        case 'm':
+            fMulti ^= 1;
+            break;
+        case 's':
+            fSimple ^= 1;
+            break;
+        case 'f':
+            fFactor ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Cannot renode a network that is not an AIG (run \"strash\").\n" );
+        return 1;
+    }
+
+    // get the new network
+    pNtkRes = Abc_NtkMulti( pNtk, nThresh, nFaninMax, fCnf, fMulti, fSimple, fFactor );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Renoding has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: multi [-TF <num>] [-msfch]\n" );
+    Abc_Print( -2, "\t          transforms an AIG into a logic network by creating larger nodes\n" );
+    Abc_Print( -2, "\t-F <num>: the maximum fanin size after renoding [default = %d]\n", nFaninMax );
+    Abc_Print( -2, "\t-T <num>: the threshold for AIG node duplication [default = %d]\n", nThresh );
+    Abc_Print( -2, "\t          (an AIG node is the root of a new node after renoding\n" );
+    Abc_Print( -2, "\t          if this leads to duplication of no more than %d AIG nodes,\n", nThresh );
+    Abc_Print( -2, "\t          that is, if [(numFanouts(Node)-1) * size(MFFC(Node))] <= %d)\n", nThresh );
+    Abc_Print( -2, "\t-m      : creates multi-input AND graph [default = %s]\n", fMulti? "yes": "no" );
+    Abc_Print( -2, "\t-s      : creates a simple AIG (no renoding) [default = %s]\n", fSimple? "yes": "no" );
+    Abc_Print( -2, "\t-f      : creates a factor-cut network [default = %s]\n", fFactor? "yes": "no" );
+    Abc_Print( -2, "\t-c      : performs renoding to derive the CNF [default = %s]\n", fCnf? "yes": "no" );
+    Abc_Print( -2, "\t-h      : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int nLutSize, nCutsMax, c;
+    int nFlowIters, nAreaIters;
+    int fArea;
+    int fUseBdds;
+    int fUseSops;
+    int fUseCnfs;
+    int fUseMv;
+    int fVerbose;
+    extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nLutSize, int nCutsMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set defaults
+    nLutSize   =  8;
+    nCutsMax   =  4;
+    nFlowIters =  1;
+    nAreaIters =  1;
+    fArea      =  0;
+    fUseBdds   =  0;
+    fUseSops   =  0;
+    fUseCnfs   =  0;
+    fUseMv     =  0;
+    fVerbose   =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAabscivh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLutSize < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nCutsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nCutsMax < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nFlowIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFlowIters < 0 )
+                goto usage;
+            break;
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nAreaIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nAreaIters < 0 )
+                goto usage;
+            break;
+        case 'a':
+            fArea ^= 1;
+            break;
+        case 'b':
+            fUseBdds ^= 1;
+            break;
+        case 's':
+            fUseSops ^= 1;
+            break;
+        case 'c':
+            fUseCnfs ^= 1;
+            break;
+        case 'i':
+            fUseMv ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( fUseBdds + fUseSops + fUseCnfs + fUseMv > 1 )
+    {
+        Abc_Print( -1, "Cannot optimize two parameters at the same time.\n" );
+        return 1;
+    }
+
+    if ( nLutSize < 2 || nLutSize > IF_MAX_FUNC_LUTSIZE )
+    {
+        Abc_Print( -1, "Incorrect LUT size (%d).\n", nLutSize );
+        return 1;
+    }
+
+    if ( nCutsMax < 1 || nCutsMax >= (1<<12) )
+    {
+        Abc_Print( -1, "Incorrect number of cuts.\n" );
+        return 1;
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Cannot renode a network that is not an AIG (run \"strash\").\n" );
+        return 1;
+    }
+
+    // get the new network
+    pNtkRes = Abc_NtkRenode( pNtk, nLutSize, nCutsMax, nFlowIters, nAreaIters, fArea, fUseBdds, fUseSops, fUseCnfs, fUseMv, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Renoding has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: renode [-KCFA <num>] [-sbciav]\n" );
+    Abc_Print( -2, "\t          transforms the AIG into a logic network with larger nodes\n" );
+    Abc_Print( -2, "\t          while minimizing the number of FF literals of the node SOPs\n" );
+    Abc_Print( -2, "\t-K <num>: the max cut size for renoding (2 < num < %d) [default = %d]\n", IF_MAX_FUNC_LUTSIZE+1, nLutSize );
+    Abc_Print( -2, "\t-C <num>: the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCutsMax );
+    Abc_Print( -2, "\t-F <num>: the number of area flow recovery iterations (num >= 0) [default = %d]\n", nFlowIters );
+    Abc_Print( -2, "\t-A <num>: the number of exact area recovery iterations (num >= 0) [default = %d]\n", nAreaIters );
+    Abc_Print( -2, "\t-s      : toggles minimizing SOP cubes instead of FF lits [default = %s]\n", fUseSops? "yes": "no" );
+    Abc_Print( -2, "\t-b      : toggles minimizing BDD nodes instead of FF lits [default = %s]\n", fUseBdds? "yes": "no" );
+    Abc_Print( -2, "\t-c      : toggles minimizing CNF clauses instead of FF lits [default = %s]\n", fUseCnfs? "yes": "no" );
+    Abc_Print( -2, "\t-i      : toggles minimizing MV-SOP instead of FF lits [default = %s]\n", fUseMv? "yes": "no" );
+    Abc_Print( -2, "\t-a      : toggles area-oriented mapping [default = %s]\n", fArea? "yes": "no" );
+    Abc_Print( -2, "\t-v      : print verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h      : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCleanup( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int fCleanupPis;
+    int fCleanupPos;
+    int fVerbose;
+
+    extern Abc_Ntk_t * Abc_NtkDarCleanupAig( Abc_Ntk_t * pNtk, int fCleanupPis, int fCleanupPos, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set defaults
+    fCleanupPis = 1;
+    fCleanupPos = 1;
+    fVerbose    = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "iovh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'i':
+            fCleanupPis ^= 1;
+            break;
+        case 'o':
+            fCleanupPos ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkIsStrash(pNtk) )
+    {
+        if ( !fCleanupPos && !fCleanupPos )
+        {
+            Abc_Print( -1, "Cleanup for PIs and POs is not enabled.\n" );
+            pNtkRes = Abc_NtkDup( pNtk );
+        }
+        else
+            pNtkRes = Abc_NtkDarCleanupAig( pNtk, fCleanupPis, fCleanupPos, fVerbose );
+    }
+    else
+    {
+        Abc_NtkCleanup( pNtk, fVerbose );
+        pNtkRes = Abc_NtkDup( pNtk );
+    }
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Cleanup has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: cleanup [-iovh]\n" );
+    Abc_Print( -2, "\t        for logic networks, removes dangling combinatinal logic\n" );
+    Abc_Print( -2, "\t        for AIGs, removes PIs w/o fanout and POs driven by const-0\n" );
+    Abc_Print( -2, "\t-i    : toggles removing PIs without fanout [default = %s]\n", fCleanupPis? "yes": "no" );
+    Abc_Print( -2, "\t-o    : toggles removing POs with const-0 drivers [default = %s]\n", fCleanupPos? "yes": "no" );
+    Abc_Print( -2, "\t-v    : print verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fSingle = 0;
+    int fVerbose = 0;
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 's':
+            fSingle ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "The classical (SIS-like) sweep can only be performed on a logic network.\n" );
+        return 1;
+    }
+    // modify the current network
+    if ( fSingle )
+        Abc_NtkSweepBufsInvs( pNtk, fVerbose );
+    else
+        Abc_NtkSweep( pNtk, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: sweep [-svh]\n" );
+    Abc_Print( -2, "\t        removes dangling nodes; propagates constant, buffers, inverters\n" );
+    Abc_Print( -2, "\t-s    : toggle sweeping buffers/inverters only [default = %s]\n", fSingle? "yes": "no" );
+    Abc_Print( -2, "\t-v    : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern int Abc_NtkFxPerform( Abc_Ntk_t * pNtk, int nNewNodesMax, int nLitCountMax, int fVerbose, int fVeryVerbose );
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Fxu_Data_t Params, * p = &Params;
+    int c, fNewAlgo = 1;
+    // set the defaults
+    Abc_NtkSetDefaultFxParams( p );
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "SDNWMsdzcnvwh")) != EOF )
+    {
+        switch (c)
+        {
+            case 'S':
+                if ( globalUtilOptind >= argc )
+                {
+                    Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                    goto usage;
+                }
+                p->nSingleMax = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( p->nSingleMax < 0 )
+                    goto usage;
+                break;
+            case 'D':
+                if ( globalUtilOptind >= argc )
+                {
+                    Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                    goto usage;
+                }
+                p->nPairsMax = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( p->nPairsMax < 0 )
+                    goto usage;
+                break;
+            case 'N':
+                if ( globalUtilOptind >= argc )
+                {
+                    Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                    goto usage;
+                }
+                p->nNodesExt = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( p->nNodesExt < 0 )
+                    goto usage;
+                break;
+            case 'W':
+                if ( globalUtilOptind >= argc )
+                {
+                    Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                    goto usage;
+                }
+                p->WeightMin = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( p->WeightMin < 0 )
+                    goto usage;
+                break;
+            case 'M':
+                if ( globalUtilOptind >= argc )
+                {
+                    Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
+                    goto usage;
+                }
+                p->LitCountMax = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( p->LitCountMax < 0 )
+                    goto usage;
+                break;
+            case 's':
+                p->fOnlyS ^= 1;
+                break;
+            case 'd':
+                p->fOnlyD ^= 1;
+                break;
+            case 'z':
+                p->fUse0 ^= 1;
+                break;
+            case 'c':
+                p->fUseCompl ^= 1;
+                break;
+            case 'n':
+                fNewAlgo ^= 1;
+                break;
+            case 'v':
+                p->fVerbose ^= 1;
+                break;
+            case 'w':
+                p->fVeryVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+                break;
+            default:
+                goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkNodeNum(pNtk) == 0 )
+    {
+        Abc_Print( -1, "The network does not have internal nodes.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "Fast extract can only be applied to a logic network (run \"renode\" or \"if\").\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsSopLogic(pNtk) )
+    {
+        Abc_Print( -1, "Fast extract can only be applied to a logic network with SOP local functions (run \"bdd; sop\").\n" );
+        return 1;
+    }
+
+    // the nodes to be merged are linked into the special linked list
+    if ( fNewAlgo )
+        Abc_NtkFxPerform( pNtk, p->nNodesExt, p->LitCountMax, p->fVerbose, p->fVeryVerbose );
+    else
+        Abc_NtkFastExtract( pNtk, p );
+    Abc_NtkFxuFreeInfo( p );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: fx [-SDNWM <num>] [-sdzcnvwh]\n");
+    Abc_Print( -2, "\t           performs unate fast extract on the current network\n");
+    Abc_Print( -2, "\t-S <num> : max number of single-cube divisors to consider [default = %d]\n", p->nSingleMax );
+    Abc_Print( -2, "\t-D <num> : max number of double-cube divisors to consider [default = %d]\n", p->nPairsMax );
+    Abc_Print( -2, "\t-N <num> : max number of divisors to extract during this run [default = %d]\n", p->nNodesExt );
+    Abc_Print( -2, "\t-W <num> : lower bound on the weight of divisors to extract [default = %d]\n", p->WeightMin );
+    Abc_Print( -2, "\t-M <num> : upper bound on literal count of divisors to extract [default = %d]\n", p->LitCountMax );
+    Abc_Print( -2, "\t-s       : use only single-cube divisors [default = %s]\n", p->fOnlyS? "yes": "no" );
+    Abc_Print( -2, "\t-d       : use only double-cube divisors [default = %s]\n", p->fOnlyD? "yes": "no" );
+    Abc_Print( -2, "\t-z       : use zero-weight divisors [default = %s]\n", p->fUse0? "yes": "no" );
+    Abc_Print( -2, "\t-c       : use complement in the binary case [default = %s]\n", p->fUseCompl? "yes": "no" );
+    Abc_Print( -2, "\t-n       : use new implementation of fast extract [default = %s]\n", fNewAlgo? "yes": "no" );
+    Abc_Print( -2, "\t-v       : print verbose information [default = %s]\n", p->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : print additional information [default = %s]\n", p->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandEliminate( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int ElimValue;
+    int nMaxSize;
+    int nIterMax;
+    int fGreedy;
+    int fReverse;
+    int fVerbose;
+    int c;
+    extern int Abc_NtkEliminate( Abc_Ntk_t * pNtk, int nMaxSize, int fReverse, int fVerbose );
+    extern int Abc_NtkEliminate1( Abc_Ntk_t * pNtk, int ElimValue, int nMaxSize, int nIterMax, int fReverse, int fVerbose );
+
+    // set the defaults
+    ElimValue = -1;
+    nMaxSize  = 12;
+    nIterMax  =  1;
+    fGreedy   =  0;
+    fReverse  =  0;
+    fVerbose  =  0;
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "VNIgrvh")) != EOF )
+    {
+        switch (c)
+        {
+            case 'V':
+                if ( globalUtilOptind >= argc )
+                {
+                    Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer that is -1 or larger.\n" );
+                    goto usage;
+                }
+                ElimValue = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( ElimValue < -1 )
+                    goto usage;
+                break;
+            case 'N':
+                if ( globalUtilOptind >= argc )
+                {
+                    Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" );
+                    goto usage;
+                }
+                nMaxSize = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( nMaxSize <= 0 )
+                    goto usage;
+                break;
+            case 'I':
+                if ( globalUtilOptind >= argc )
+                {
+                    Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" );
+                    goto usage;
+                }
+                nIterMax = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( nIterMax <= 0 )
+                    goto usage;
+                break;
+            case 'g':
+                fGreedy ^= 1;
+                break;
+            case 'r':
+                fReverse ^= 1;
+                break;
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+                break;
+            default:
+                goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( Abc_NtkNodeNum(pNtk) == 0 )
+    {
+        Abc_Print( -1, "The network does not have internal nodes.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "This command can only be applied to a logic network (run \"renode\" or \"if\").\n" );
+        return 1;
+    }
+
+    if ( fGreedy )
+        Abc_NtkEliminate( pNtk, nMaxSize, fReverse, fVerbose );
+    else
+        Abc_NtkEliminate1( pNtk, ElimValue, nMaxSize, nIterMax, fReverse, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: eliminate [-VNI <num>] [-grvh]\n");
+    Abc_Print( -2, "\t           traditional \"eliminate -1\", which collapses the node into its fanout\n");
+    Abc_Print( -2, "\t           if the node's variable appears in the fanout's factored form only once\n");
+    Abc_Print( -2, "\t-V <num> : the \"value\" parameter used by \"eliminate\" in SIS [default = %d]\n", ElimValue );
+    Abc_Print( -2, "\t-N <num> : the maximum node support after collapsing [default = %d]\n", nMaxSize );
+    Abc_Print( -2, "\t-I <num> : the maximum number of iterations [default = %d]\n", nIterMax );
+    Abc_Print( -2, "\t-g       : toggle using greedy eliminate (without \"value\") [default = %s]\n", fGreedy? "yes": "no" );
+    Abc_Print( -2, "\t-r       : use the reverse topological order [default = %s]\n", fReverse? "yes": "no" );
+    Abc_Print( -2, "\t-v       : print verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes, * pNtkNew;
+    int fGlobal, fRecursive, fVerbose, fPrint, fShort, c;
+
+    extern Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, int fVerbose, int fPrint, int fShort );
+    extern int         Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, int fVerbose, int fRecursive );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fGlobal    = 1;
+    fRecursive = 0;
+    fVerbose   = 0;
+    fPrint     = 0;
+    fShort     = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "grvpsh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'g':
+                fGlobal ^= 1;
+                break;
+            case 'r':
+                fRecursive ^= 1;
+                break;
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'p':
+                fPrint ^= 1;
+                break;
+            case 's':
+                fShort ^= 1;
+                break;
+            case 'h':
+                goto usage;
+                break;
+            default:
+                goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( fGlobal )
+    {
+//        Abc_Print( 0, "Performing DSD of global functions of the network.\n" );
+        // get the new network
+        if ( !Abc_NtkIsStrash(pNtk) )
+        {
+            pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 );
+            pNtkRes = Abc_NtkDsdGlobal( pNtkNew, fVerbose, fPrint, fShort );
+            Abc_NtkDelete( pNtkNew );
+        }
+        else
+        {
+            pNtkRes = Abc_NtkDsdGlobal( pNtk, fVerbose, fPrint, fShort );
+        }
+        if ( pNtkRes == NULL )
+        {
+            Abc_Print( -1, "Global DSD has failed.\n" );
+            return 1;
+        }
+        // replace the current network
+        Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    }
+    else if ( fRecursive )
+    {
+        if ( !Abc_NtkIsBddLogic( pNtk ) )
+        {
+            Abc_Print( -1, "This command is only applicable to logic BDD networks.\n" );
+            return 1;
+        }
+        if ( fVerbose )
+            Abc_Print( 1, "Performing recursive DSD and MUX decomposition of local functions.\n" );
+        if ( !Abc_NtkDsdLocal( pNtk, fVerbose, fRecursive ) )
+            Abc_Print( -1, "Recursive DSD has failed.\n" );
+    }
+    else
+    {
+        if ( !Abc_NtkIsBddLogic( pNtk ) )
+        {
+            Abc_Print( -1, "This command is only applicable to logic BDD networks (run \"bdd\").\n" );
+            return 1;
+        }
+        if ( fVerbose )
+            Abc_Print( 1, "Performing simple non-recursive DSD of local functions.\n" );
+        if ( !Abc_NtkDsdLocal( pNtk, fVerbose, fRecursive ) )
+            Abc_Print( -1, "Simple DSD of local functions has failed.\n" );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dsd [-grvpsh]\n" );
+    Abc_Print( -2, "\t     decomposes the network using disjoint-support decomposition\n" );
+    Abc_Print( -2, "\t-g     : toggle DSD of global and local functions [default = %s]\n", fGlobal? "global": "local" );
+    Abc_Print( -2, "\t-r     : toggle recursive DSD/MUX and simple DSD [default = %s]\n", fRecursive? "recursive DSD/MUX": "simple DSD" );
+    Abc_Print( -2, "\t-v     : prints DSD statistics and runtime [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-p     : prints DSD structure to the standard output [default = %s]\n", fPrint? "yes": "no" );
+    Abc_Print( -2, "\t-s     : use short PI names when printing DSD structure [default = %s]\n", fShort? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandLutpack( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Lpk_Par_t Pars, * pPars = &Pars;
+    int c;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    memset( pPars, 0, sizeof(Lpk_Par_t) );
+    pPars->nLutsMax     =  4; // (N) the maximum number of LUTs in the structure
+    pPars->nLutsOver    =  3; // (Q) the maximum number of LUTs not in the MFFC
+    pPars->nVarsShared  =  0; // (S) the maximum number of shared variables (crossbars)
+    pPars->nGrowthLevel =  0; // (L) the maximum number of increased levels
+    pPars->fSatur       =  1;
+    pPars->fZeroCost    =  0;
+    pPars->fFirst       =  0;
+    pPars->fOldAlgo     =  0;
+    pPars->fVerbose     =  0;
+    pPars->fVeryVerbose =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "NQSLszfovwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nLutsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLutsMax < 2 || pPars->nLutsMax > 8 )
+                goto usage;
+            break;
+        case 'Q':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-Q\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nLutsOver = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLutsOver < 0 || pPars->nLutsOver > 8 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nVarsShared = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nVarsShared < 0 || pPars->nVarsShared > 4 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nGrowthLevel = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY )
+                goto usage;
+            break;
+        case 's':
+            pPars->fSatur ^= 1;
+            break;
+        case 'z':
+            pPars->fZeroCost ^= 1;
+            break;
+        case 'f':
+            pPars->fFirst ^= 1;
+            break;
+        case 'o':
+            pPars->fOldAlgo ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "This command can only be applied to a logic network.\n" );
+        return 1;
+    }
+    if ( pPars->nVarsShared < 0 || pPars->nVarsShared > 3 )
+    {
+        Abc_Print( -1, "The number of shared variables (%d) is not in the range 0 <= S <= 3.\n", pPars->nVarsShared );
+        return 1;
+    }
+
+    // modify the current network
+    if ( !Lpk_Resynthesize( pNtk, pPars ) )
+    {
+        Abc_Print( -1, "Resynthesis has failed.\n" );
+        return 1;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: lutpack [-NQSL <num>] [-szfovwh]\n" );
+    Abc_Print( -2, "\t           performs \"rewriting\" for LUT network;\n" );
+    Abc_Print( -2, "\t           determines LUT size as the max fanin count of a node;\n" );
+    Abc_Print( -2, "\t           if the network is not LUT-mapped, packs it into 6-LUTs\n" );
+    Abc_Print( -2, "\t           (there is another command for resynthesis after LUT mapping, \"imfs\")\n" );
+    Abc_Print( -2, "\t-N <num> : the max number of LUTs in the structure (2 <= num) [default = %d]\n", pPars->nLutsMax );
+    Abc_Print( -2, "\t-Q <num> : the max number of LUTs not in MFFC (0 <= num) [default = %d]\n", pPars->nLutsOver );
+    Abc_Print( -2, "\t-S <num> : the max number of LUT inputs shared (0 <= num <= 3) [default = %d]\n", pPars->nVarsShared );
+    Abc_Print( -2, "\t-L <num> : max level increase after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel );
+    Abc_Print( -2, "\t-s       : toggle iteration till saturation [default = %s]\n", pPars->fSatur? "yes": "no" );
+    Abc_Print( -2, "\t-z       : toggle zero-cost replacements [default = %s]\n", pPars->fZeroCost? "yes": "no" );
+    Abc_Print( -2, "\t-f       : toggle using only first node and first cut [default = %s]\n", pPars->fFirst? "yes": "no" );
+    Abc_Print( -2, "\t-o       : toggle using old implementation [default = %s]\n", pPars->fOldAlgo? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggle detailed printout of decomposed functions [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandLutmin( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int nLutSize;
+    int fVerbose;
+    extern Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nLutSize = 4;
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Kvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    // modify the current network
+    pNtkRes = Abc_NtkLutmin( pNtk, nLutSize, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "The command has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: lutmin [-K <num>] [-vh]\n" );
+    Abc_Print( -2, "\t           perform FPGA mapping while minimizing the LUT count\n" );
+    Abc_Print( -2, "\t           as described in the paper T. Sasao and A. Mishchenko:\n" );
+    Abc_Print( -2, "\t           \"On the number of LUTs to implement logic functions\".\n" );
+    Abc_Print( -2, "\t-K <num> : the LUT size to use for the mapping (2 <= num) [default = %d]\n", nLutSize );
+    Abc_Print( -2, "\t-v       : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+#if 0
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandImfs( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Res_Par_t Pars, * pPars = &Pars;
+    int c;
+
+    // set defaults
+    pPars->nWindow      = 62;
+    pPars->nCands       =  5;
+    pPars->nSimWords    =  4;
+    pPars->nGrowthLevel =  0;
+    pPars->fArea        =  0;
+    pPars->fVerbose     =  0;
+    pPars->fVeryVerbose =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "WSCLavwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nWindow = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nWindow < 1 || pPars->nWindow > 99 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nSimWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nSimWords < 1 || pPars->nSimWords > 256 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nCands = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nCands < 0 || pPars->nCands > ABC_INFINITY )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nGrowthLevel = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY )
+                goto usage;
+            break;
+        case 'a':
+            pPars->fArea ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "This command can only be applied to a logic network.\n" );
+        return 1;
+    }
+
+    // modify the current network
+    if ( !Abc_NtkResynthesize( pNtk, pPars ) )
+    {
+        Abc_Print( -1, "Resynthesis has failed.\n" );
+        return 1;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: imfs [-W <NM>] [-LCS <num>] [-avwh]\n" );
+    Abc_Print( -2, "\t           performs resubstitution-based resynthesis with interpolation\n" );
+    Abc_Print( -2, "\t           (there is another command for resynthesis after LUT mapping, \"lutpack\")\n" );
+    Abc_Print( -2, "\t-W <NM>  : fanin/fanout levels (NxM) of the window (00 <= NM <= 99) [default = %d%d]\n", pPars->nWindow/10, pPars->nWindow%10 );
+    Abc_Print( -2, "\t-C <num> : the max number of resub candidates (1 <= n) [default = %d]\n", pPars->nCands );
+    Abc_Print( -2, "\t-S <num> : the number of simulation words (1 <= n <= 256) [default = %d]\n", pPars->nSimWords );
+    Abc_Print( -2, "\t-L <num> : the max increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel );
+    Abc_Print( -2, "\t-a       : toggle optimization for area only [default = %s]\n", pPars->fArea? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggle printout subgraph statistics [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+#endif
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandMfs( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Mfs_Par_t Pars, * pPars = &Pars;
+    int c;
+    // set defaults
+    Abc_NtkMfsParsDefault( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCdraestpgvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nWinTfoLevs = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nWinTfoLevs < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFanoutsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFanoutsMax < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nDepthMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nDepthMax < 0 )
+                goto usage;
+            break;
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nWinMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nWinMax < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nGrowthLevel = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'd':
+            pPars->fRrOnly ^= 1;
+            break;
+        case 'r':
+            pPars->fResub ^= 1;
+            break;
+        case 'a':
+            pPars->fArea ^= 1;
+            break;
+        case 'e':
+            pPars->fMoreEffort ^= 1;
+            break;
+        case 's':
+            pPars->fSwapEdge ^= 1;
+            break;
+        case 't':
+            pPars->fOneHotness ^= 1;
+            break;
+        case 'p':
+            pPars->fPower ^= 1;
+            break;
+        case 'g':
+            pPars->fGiaSat ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "This command can only be applied to a logic network.\n" );
+        return 1;
+    }
+
+    // modify the current network
+    if ( !Abc_NtkMfs( pNtk, pPars ) )
+    {
+        Abc_Print( -1, "Resynthesis has failed.\n" );
+        return 1;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: mfs [-WFDMLC <num>] [-draestpgvh]\n" );
+    Abc_Print( -2, "\t           performs don't-care-based optimization of logic networks\n" );
+    Abc_Print( -2, "\t-W <num> : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nWinTfoLevs );
+    Abc_Print( -2, "\t-F <num> : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutsMax );
+    Abc_Print( -2, "\t-D <num> : the max depth nodes to try (0 = no limit) [default = %d]\n", pPars->nDepthMax );
+    Abc_Print( -2, "\t-M <num> : the max node count of windows to consider (0 = no limit) [default = %d]\n", pPars->nWinMax );
+    Abc_Print( -2, "\t-L <num> : the max increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel );
+    Abc_Print( -2, "\t-C <num> : the max number of conflicts in one SAT run (0 = no limit) [default = %d]\n", pPars->nBTLimit );
+    Abc_Print( -2, "\t-d       : toggle performing redundancy removal [default = %s]\n", pPars->fRrOnly? "yes": "no" );
+    Abc_Print( -2, "\t-r       : toggle resubstitution and dc-minimization [default = %s]\n", pPars->fResub? "resub": "dc-min" );
+    Abc_Print( -2, "\t-a       : toggle minimizing area or area+edges [default = %s]\n", pPars->fArea? "area": "area+edges" );
+    Abc_Print( -2, "\t-e       : toggle high-effort resubstitution [default = %s]\n", pPars->fMoreEffort? "yes": "no" );
+    Abc_Print( -2, "\t-s       : toggle evaluation of edge swapping [default = %s]\n", pPars->fSwapEdge? "yes": "no" );
+    Abc_Print( -2, "\t-t       : toggle using artificial one-hotness conditions [default = %s]\n", pPars->fOneHotness? "yes": "no" );
+    Abc_Print( -2, "\t-p       : toggle power-aware optimization [default = %s]\n", pPars->fPower? "yes": "no" );
+    Abc_Print( -2, "\t-g       : toggle using new SAT solver [default = %s]\n", pPars->fGiaSat? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandMfs2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern int Abc_NtkPerformMfs( Abc_Ntk_t * pNtk, Sfm_Par_t * pPars );
+    extern int Abc_NtkMfsAfterICheck( Abc_Ntk_t * p, int nFrames, int nFramesAdd, Vec_Int_t * vFlops, Sfm_Par_t * pPars );
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Sfm_Par_t Pars, * pPars = &Pars;
+    int c, fIndDCs = 0, fUseAllFfs = 0, nFramesAdd = 0;
+    // set defaults
+    Sfm_ParSetDefault( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCZNIdaeijvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nTfoLevMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nTfoLevMax < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFanoutMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFanoutMax < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nDepthMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nDepthMax < 0 )
+                goto usage;
+            break;
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nWinSizeMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nWinSizeMax < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nGrowthLevel = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nGrowthLevel < -ABC_INFINITY || pPars->nGrowthLevel > ABC_INFINITY )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'Z':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-Z\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFirstFixed = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFirstFixed < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nNodesMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nNodesMax < 0 )
+                goto usage;
+            break;
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFramesAdd = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFramesAdd < 0 )
+                goto usage;
+            break;
+        case 'd':
+            pPars->fRrOnly ^= 1;
+            break;
+        case 'a':
+            pPars->fArea ^= 1;
+            break;
+        case 'e':
+            pPars->fMoreEffort ^= 1;
+            break;
+        case 'i':
+            fIndDCs ^= 1;
+            break;
+        case 'j':
+            fUseAllFfs ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "This command can only be applied to a logic network.\n" );
+        return 1;
+    }
+    if ( fIndDCs )
+    {
+        if ( fUseAllFfs )
+        {
+            pAbc->nIndFrames = 1;
+            Vec_IntFreeP( &pAbc->vIndFlops );
+            pAbc->vIndFlops = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) );
+            Vec_IntFill( pAbc->vIndFlops, Abc_NtkLatchNum(pNtk), 1 );
+        }
+        if ( pAbc->nIndFrames <= 0 )
+        {
+            Abc_Print( -1, "The number of k-inductive frames is not specified.\n" );
+            return 0;
+        }
+        if ( pAbc->vIndFlops == NULL )
+        {
+            Abc_Print( -1, "The set of k-inductive flops is not specified.\n" );
+            return 0;
+        }
+        if ( Vec_IntSize(pAbc->vIndFlops) != Abc_NtkLatchNum(pNtk) )
+        {
+            Abc_Print( -1, "The saved flop count (%d) does not match that of the current network (%d).\n", 
+                Vec_IntSize(pAbc->vIndFlops), Abc_NtkLatchNum(pNtk) );
+            return 0;
+        }
+        // modify the current network
+        if ( !Abc_NtkMfsAfterICheck( pNtk, pAbc->nIndFrames, nFramesAdd, pAbc->vIndFlops, pPars ) )
+        {
+            Abc_Print( -1, "Resynthesis has failed.\n" );
+            return 1;
+        }
+        if ( fUseAllFfs )
+        {
+            pAbc->nIndFrames = 0;
+            Vec_IntFreeP( &pAbc->vIndFlops );
+        }
+    }
+    else
+    {
+        // modify the current network
+        if ( !Abc_NtkPerformMfs( pNtk, pPars ) )
+        {
+            Abc_Print( -1, "Resynthesis has failed.\n" );
+            return 1;
+        }
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: mfs2 [-WFDMLCZNI <num>] [-daeijvwh]\n" );
+    Abc_Print( -2, "\t           performs don't-care-based optimization of logic networks\n" );
+    Abc_Print( -2, "\t-W <num> : the number of levels in the TFO cone (0 <= num) [default = %d]\n",             pPars->nTfoLevMax );
+    Abc_Print( -2, "\t-F <num> : the max number of fanouts to skip (1 <= num) [default = %d]\n",                pPars->nFanoutMax );
+    Abc_Print( -2, "\t-D <num> : the max depth nodes to try (0 = no limit) [default = %d]\n",                   pPars->nDepthMax );
+    Abc_Print( -2, "\t-M <num> : the max node count of windows to consider (0 = no limit) [default = %d]\n",    pPars->nWinSizeMax );
+    Abc_Print( -2, "\t-L <num> : the max increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel );
+    Abc_Print( -2, "\t-C <num> : the max number of conflicts in one SAT run (0 = no limit) [default = %d]\n",   pPars->nBTLimit );
+    Abc_Print( -2, "\t-Z <num> : treat the first <num> logic nodes as fixed (0 = none) [default = %d]\n",       pPars->nFirstFixed );
+    Abc_Print( -2, "\t-N <num> : the max number of nodes to try (0 = all) [default = %d]\n",                    pPars->nNodesMax );
+    Abc_Print( -2, "\t-d       : toggle performing redundancy removal [default = %s]\n",                        pPars->fRrOnly? "yes": "no" );
+    Abc_Print( -2, "\t-a       : toggle minimizing area or area+edges [default = %s]\n",                        pPars->fArea? "area": "area+edges" );
+    Abc_Print( -2, "\t-e       : toggle high-effort resubstitution [default = %s]\n",                           pPars->fMoreEffort? "yes": "no" );
+    Abc_Print( -2, "\t-i       : toggle using inductive don't-cares [default = %s]\n",                          fIndDCs? "yes": "no" );
+    Abc_Print( -2, "\t-j       : toggle using all flops when \"-i\" is enabled [default = %s]\n",               fUseAllFfs? "yes": "no" );
+    Abc_Print( -2, "\t-I       : the number of additional frames inserted [default = %d]\n",                    nFramesAdd );
+    Abc_Print( -2, "\t-v       : toggle printing optimization summary [default = %s]\n",                        pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggle printing detailed stats for each node [default = %s]\n",                pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandTrace( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fUseLutLib;
+    int fVerbose;
+    extern void Abc_NtkDelayTracePrint( Abc_Ntk_t * pNtk, int fUseLutLib, int fVerbose );
+
+    // set defaults
+    fUseLutLib = 0;
+    fVerbose   = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "lvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'l':
+            fUseLutLib ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "This command can only be applied to a logic network.\n" );
+        return 1;
+    }
+
+    // modify the current network
+    Abc_NtkDelayTracePrint( pNtk, fUseLutLib, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: trace [-lvh]\n" );
+    Abc_Print( -2, "\t           performs delay trace of LUT-mapped network\n" );
+    Abc_Print( -2, "\t-l       : toggle using unit- or LUT-library-delay model [default = %s]\n", fUseLutLib? "lib": "unit" );
+    Abc_Print( -2, "\t-v       : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSpeedup( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int fUseLutLib;
+    int Percentage;
+    int Degree;
+    int fVerbose;
+    int fVeryVerbose;
+    extern Abc_Ntk_t * Abc_NtkSpeedup( Abc_Ntk_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose );
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set defaults
+    fUseLutLib = 0;
+    Percentage = 5;
+    Degree     = 2;
+    fVerbose   = 0;
+    fVeryVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "PNlvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            Percentage = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Percentage < 1 || Percentage > 100 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            Degree = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Degree < 1 || Degree > 5 )
+                goto usage;
+            break;
+        case 'l':
+            fUseLutLib ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "This command can only be applied to a logic network.\n" );
+        return 1;
+    }
+
+    // modify the current network
+    pNtkRes = Abc_NtkSpeedup( pNtk, fUseLutLib, Percentage, Degree, fVerbose, fVeryVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "The command has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: speedup [-PN <num>] [-lvwh]\n" );
+    Abc_Print( -2, "\t           transforms LUT-mapped network into an AIG with choices;\n" );
+    Abc_Print( -2, "\t           the choices are added to speedup the next round of mapping\n" );
+    Abc_Print( -2, "\t-P <num> : delay delta defining critical path for library model [default = %d%%]\n", Percentage );
+    Abc_Print( -2, "\t-N <num> : the max critical path degree for resynthesis (0 < num < 6) [default = %d]\n", Degree );
+    Abc_Print( -2, "\t-l       : toggle using unit- or LUT-library-delay model [default = %s]\n", fUseLutLib? "lib" : "unit" );
+    Abc_Print( -2, "\t-v       : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggle printing detailed stats for each node [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPowerdown( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int fUseLutLib;
+    int Percentage;
+    int Degree;
+    int fVerbose;
+    int fVeryVerbose;
+    extern Abc_Ntk_t * Abc_NtkPowerdown( Abc_Ntk_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fUseLutLib = 0;
+    Percentage =10;
+    Degree     = 2;
+    fVerbose   = 0;
+    fVeryVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "PNlvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            Percentage = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Percentage < 1 || Percentage > 100 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            Degree = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Degree < 1 || Degree > 5 )
+                goto usage;
+            break;
+        case 'l':
+            fUseLutLib ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "This command can only be applied to a logic network.\n" );
+        return 1;
+    }
+
+    // modify the current network
+    pNtkRes = Abc_NtkPowerdown( pNtk, fUseLutLib, Percentage, Degree, fVerbose, fVeryVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "The command has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: powerdown [-PN <num>] [-vwh]\n" );
+    Abc_Print( -2, "\t           transforms LUT-mapped network into an AIG with choices;\n" );
+    Abc_Print( -2, "\t           the choices are added to power down the next round of mapping\n" );
+    Abc_Print( -2, "\t-P <num> : switching propability delta defining power critical edges [default = %d%%]\n", Percentage );
+    Abc_Print( -2, "\t           (e.g. 5% means hot wires switch with probability: 0.45 <= p <= 0.50 (max)\n" );
+    Abc_Print( -2, "\t-N <num> : the max critical path degree for resynthesis (0 < num < 6) [default = %d]\n", Degree );
+//    Abc_Print( -2, "\t-l       : toggle using unit- or LUT-library-delay model [default = %s]\n", fUseLutLib? "lib" : "unit" );
+    Abc_Print( -2, "\t-v       : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggle printing detailed stats for each node [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAddBuffs( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Abc_Ntk_t * Abc_NtkAddBuffs( Abc_Ntk_t * pNtk, int fDirect, int fReverse, int nImprove, int fVerbose );
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Abc_Ntk_t * pNtkRes;
+    int fDirect;
+    int fReverse;
+    int nImprove;
+    int c, fVerbose;
+
+    fDirect  = 0;
+    fReverse = 0;
+    nImprove = 1000;
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Idrvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nImprove = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nImprove < 0 )
+                goto usage;
+            break;
+        case 'd':
+            fDirect ^= 1;
+            break;
+        case 'r':
+            fReverse ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "This command can only be applied to a logic network.\n" );
+        return 1;
+    }
+
+    // modify the current network
+    pNtkRes = Abc_NtkAddBuffs( pNtk, fDirect, fReverse, nImprove, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "The command has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: addbuffs [-I num] [-drvh]\n" );
+    Abc_Print( -2, "\t           adds buffers to create balanced CI/CO paths\n" );
+    Abc_Print( -2, "\t-I <num> : the number of refinement iterations [default = %d]\n", nImprove );
+    Abc_Print( -2, "\t-d       : toggle using only CI-to-CO levelized order [default = %s]\n", fDirect? "yes": "no" );
+    Abc_Print( -2, "\t-r       : toggle using only CO-to-C1 levelized order [default = %s]\n", fReverse? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+#if 0
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandMerge( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Nwk_LMPars_t Pars, * pPars = &Pars;
+    Vec_Int_t * vResult;
+    int c;
+    extern Vec_Int_t * Abc_NtkLutMerge( Abc_Ntk_t * pNtk, Nwk_LMPars_t * pPars );
+    // set defaults
+    memset( pPars, 0, sizeof(Nwk_LMPars_t) );
+    pPars->nMaxLutSize    = 5;   // the max LUT size for merging (N=5)
+    pPars->nMaxSuppSize   = 5;   // the max total support size after merging (S=5)
+    pPars->nMaxDistance   = 3;   // the max number of nodes separating LUTs
+    pPars->nMaxLevelDiff  = 2;   // the max difference in levels
+    pPars->nMaxFanout     = 100; // the max number of fanouts to traverse
+    pPars->fUseDiffSupp   = 0;   // enables the use of nodes with different support
+    pPars->fUseTfiTfo     = 0;   // enables the use of TFO/TFO nodes as candidates
+    pPars->fVeryVerbose   = 0;   // enables additional verbose output
+    pPars->fVerbose       = 1;   // enables verbose output
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "NSDLFscvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nMaxLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nMaxLutSize < 2 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nMaxSuppSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nMaxSuppSize < 2 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nMaxDistance = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nMaxDistance < 2 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nMaxLevelDiff = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nMaxLevelDiff < 2 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nMaxFanout = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nMaxFanout < 2 )
+                goto usage;
+            break;
+        case 's':
+            pPars->fUseDiffSupp ^= 1;
+            break;
+        case 'c':
+            pPars->fUseTfiTfo ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL || !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "Abc_CommandMerge(): There is no mapped network to merge LUTs.\n" );
+        return 1;
+    }
+
+    vResult = Abc_NtkLutMerge( pNtk, pPars );
+    Vec_IntFree( vResult );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: merge [-NSDLF <num>] [-scwvh]\n" );
+    Abc_Print( -2, "\t           creates pairs of topologically-related LUTs\n" );
+    Abc_Print( -2, "\t-N <num> : the max LUT size for merging (1 < num) [default = %d]\n", pPars->nMaxLutSize );
+    Abc_Print( -2, "\t-S <num> : the max total support size after merging (1 < num) [default = %d]\n", pPars->nMaxSuppSize );
+    Abc_Print( -2, "\t-D <num> : the max distance in terms of LUTs (0 < num) [default = %d]\n", pPars->nMaxDistance );
+    Abc_Print( -2, "\t-L <num> : the max difference in levels (0 <= num) [default = %d]\n", pPars->nMaxLevelDiff );
+    Abc_Print( -2, "\t-F <num> : the max number of fanouts to stop traversal (0 < num) [default = %d]\n", pPars->nMaxFanout );
+    Abc_Print( -2, "\t-s       : toggle the use of nodes without support overlap [default = %s]\n", pPars->fUseDiffSupp? "yes" : "no" );
+    Abc_Print( -2, "\t-c       : toggle the use of TFI/TFO nodes as candidates [default = %s]\n", pPars->fUseTfiTfo? "yes" : "no" );
+    Abc_Print( -2, "\t-w       : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+#endif
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandTestDec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern int Abc_DecTest( char * pFileName, int DecType, int nVarNum, int fVerbose );
+    char * pFileName;
+    int c;
+    int fVerbose = 0;
+    int DecType = 0;
+    int nVarNum = -1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ANvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            DecType = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( DecType < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nVarNum = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nVarNum < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+    {
+        Abc_Print( 1,"Input file is not given.\n" );
+        return 0;
+    }
+    if ( nVarNum >= 0 && nVarNum < 6 )
+    {
+        Abc_Print( 1,"The number of variables cannot be less than 6.\n" );
+        return 0;
+    }
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // call the testbench
+    Abc_DecTest( pFileName, DecType, nVarNum, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: testdec [-AN <num>] [-vh] <file>\n" );
+    Abc_Print( -2, "\t           testbench for Boolean decomposition algorithms\n" );
+    Abc_Print( -2, "\t-A <num> : decomposition algorithm [default = %d]\n", DecType );
+    Abc_Print( -2, "\t               0: none (reading and writing the file)\n" );
+    Abc_Print( -2, "\t               1: algebraic factoring applied to ISOP\n" );
+    Abc_Print( -2, "\t               2: bi-decomposition with cofactoring\n" );
+    Abc_Print( -2, "\t               3: disjoint-support decomposition with cofactoring\n" );
+    Abc_Print( -2, "\t               4: updated disjoint-support decomposition with cofactoring\n" );
+    Abc_Print( -2, "\t               5: enumerating decomposable variable sets\n" );
+    Abc_Print( -2, "\t-N <num> : the number of support variables (binary files only) [default = unused]\n" );
+    Abc_Print( -2, "\t-v       : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    Abc_Print( -2, "\t<file>   : a text file with truth tables in hexadecimal, listed one per line,\n");
+    Abc_Print( -2, "\t           or a binary file with an array of truth tables (in this case,\n");
+    Abc_Print( -2, "\t           -N <num> is required to determine how many functions are stored)\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandTestNpn( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern int Abc_NpnTest( char * pFileName, int NpnType, int nVarNum, int fDumpRes, int fBinary, int fVerbose );
+    char * pFileName;
+    int c;
+    int fVerbose = 0;
+    int NpnType = 0;
+    int nVarNum = -1;
+    int fDumpRes = 0;
+    int fBinary = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ANdbvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            NpnType = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( NpnType < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nVarNum = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nVarNum < 0 )
+                goto usage;
+            break;
+        case 'd':
+            fDumpRes ^= 1;
+            break;
+        case 'b':
+            fBinary ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+    {
+        Abc_Print( 1,"Input file is not given.\n" );
+        return 0;
+    }
+    if ( nVarNum >= 0 && nVarNum < 6 )
+    {
+        Abc_Print( 1,"The number of variables cannot be less than 6.\n" );
+        return 0;
+    }
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // call the testbench
+    Abc_NpnTest( pFileName, NpnType, nVarNum, fDumpRes, fBinary, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: testnpn [-AN <num>] [-dbvh] <file>\n" );
+    Abc_Print( -2, "\t           testbench for computing (semi-)canonical forms\n" );
+    Abc_Print( -2, "\t           of completely-specified Boolean functions up to 16 varibles\n" );
+    Abc_Print( -2, "\t-A <num> : semi-caninical form computation algorithm [default = %d]\n", NpnType );
+    Abc_Print( -2, "\t               0: uniqifying truth tables\n" );
+    Abc_Print( -2, "\t               1: exact NPN canonical form by brute-force enumeration\n" );
+    Abc_Print( -2, "\t               2: semi-canonical form by counting 1s in cofactors\n" );
+    Abc_Print( -2, "\t               3: Jake's hybrid semi-canonical form (fast)\n" );
+    Abc_Print( -2, "\t               4: Jake's hybrid semi-canonical form (high-effort)\n" );
+    Abc_Print( -2, "\t               5: new fast hybrid semi-canonical form\n" );
+    Abc_Print( -2, "\t               6: new phase canonical form\n" );
+    Abc_Print( -2, "\t-N <num> : the number of support variables (binary files only) [default = unused]\n" );
+    Abc_Print( -2, "\t-d       : toggle dumping resulting functions into a file [default = %s]\n", fDumpRes? "yes": "no" );
+    Abc_Print( -2, "\t-b       : toggle dumping in binary format [default = %s]\n", fBinary? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    Abc_Print( -2, "\t<file>   : a text file with truth tables in hexadecimal, listed one per line,\n");
+    Abc_Print( -2, "\t           or a binary file with an array of truth tables (in this case,\n");
+    Abc_Print( -2, "\t           -N <num> is required to determine how many functions are stored)\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandTestRPO(Abc_Frame_t * pAbc, int argc, char ** argv) {
+    extern int Abc_RpoTest(char * pFileName, int nVarNum, int nThreshold, int fVerbose);
+    char * pFileName;
+    int c;
+    int nVarNum = -1;
+    int fVerbose = 0;
+    int nThreshold = -1;
+    Extra_UtilGetoptReset();
+    while ((c = Extra_UtilGetopt(argc, argv, "TNvh")) != EOF) {
+        switch (c) {
+            case 'N':
+                if (globalUtilOptind >= argc) {
+                    Abc_Print(-1, "Command line switch \"-N\" should be followed by an integer.\n");
+                    goto usage;
+                }
+                nVarNum = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if (nVarNum < 0)
+                    goto usage;
+                break;
+            case 'T':
+                if (globalUtilOptind >= argc) {
+                    Abc_Print(-1, "Command line switch \"-T\" should be followed by an integer.\n");
+                    goto usage;
+                }
+                nThreshold = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if (nThreshold < 0)
+                    goto usage;
+                break;
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if (argc != globalUtilOptind + 1) 
+    {
+        Abc_Print(1, "Input file is not given.\n");
+        goto usage;
+    }
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // call the testbench
+    Abc_RpoTest( pFileName, nVarNum, nThreshold, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print(-2, "usage: testrpo [-NT <num>] [-vh] <file>\n");
+    Abc_Print(-2, "\t           RPO algorithm developed and implemented by Mayler G. A. Martins,\n");
+    Abc_Print(-2, "\t           Vinicius Callegaro, Renato P. Ribas and Andre' I. Reis\n");
+    Abc_Print(-2, "\t           at Federal University of Rio Grande do Sul, Porto Alegre, Brazil\n");
+    Abc_Print(-2, "\t-N <num> : the number of support variables (binary files only) [default = unused]\n");
+    Abc_Print(-2, "\t-T <num> : the number of recursions accepted before abort [default = INFINITE]\n");
+    Abc_Print(-2, "\t-v       : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no");
+    Abc_Print(-2, "\t-h       : print the command usage\n");
+    Abc_Print(-2, "\t<file>   : a text file with truth tables in hexadecimal, listed one per line,\n");
+    Abc_Print(-2, "\t           or a binary file with an array of truth tables (in this case,\n");
+    Abc_Print(-2, "\t           -N <num> is required to determine how many functions are stored)\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fUpdateLevel;
+    int fPrecompute;
+    int fUseZeros;
+    int fVerbose;
+    int fVeryVerbose;
+    int fPlaceEnable;
+    // external functions
+    extern void Rwr_Precompute();
+
+    // set defaults
+    fUpdateLevel = 1;
+    fPrecompute  = 0;
+    fUseZeros    = 0;
+    fVerbose     = 0;
+    fVeryVerbose = 0;
+    fPlaceEnable = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "lxzvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'l':
+            fUpdateLevel ^= 1;
+            break;
+        case 'x':
+            fPrecompute ^= 1;
+            break;
+        case 'z':
+            fUseZeros ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'p':
+            fPlaceEnable ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( fPrecompute )
+    {
+        Rwr_Precompute();
+        return 0;
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" );
+        return 1;
+    }
+    if ( Abc_NtkGetChoiceNum(pNtk) )
+    {
+        Abc_Print( -1, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" );
+        return 1;
+    }
+
+    // modify the current network
+    if ( !Abc_NtkRewrite( pNtk, fUpdateLevel, fUseZeros, fVerbose, fVeryVerbose, fPlaceEnable ) )
+    {
+        Abc_Print( -1, "Rewriting has failed.\n" );
+        return 1;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: rewrite [-lzvwh]\n" );
+    Abc_Print( -2, "\t         performs technology-independent rewriting of the AIG\n" );
+    Abc_Print( -2, "\t-l     : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+    Abc_Print( -2, "\t-z     : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle printout subgraph statistics [default = %s]\n", fVeryVerbose? "yes": "no" );
+//    Abc_Print( -2, "\t-p     : toggle placement-aware rewriting [default = %s]\n", fPlaceEnable? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int nNodeSizeMax;
+    int nConeSizeMax;
+    int fUpdateLevel;
+    int fUseZeros;
+    int fUseDcs;
+    int fVerbose;
+    extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose );
+
+    // set defaults
+    nNodeSizeMax = 10;
+    nConeSizeMax = 16;
+    fUpdateLevel =  1;
+    fUseZeros    =  0;
+    fUseDcs      =  0;
+    fVerbose     =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "NClzdvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nNodeSizeMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nNodeSizeMax < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConeSizeMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConeSizeMax < 0 )
+                goto usage;
+            break;
+        case 'l':
+            fUpdateLevel ^= 1;
+            break;
+        case 'z':
+            fUseZeros ^= 1;
+            break;
+        case 'd':
+            fUseDcs ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" );
+        return 1;
+    }
+    if ( Abc_NtkGetChoiceNum(pNtk) )
+    {
+        Abc_Print( -1, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" );
+        return 1;
+    }
+
+    if ( fUseDcs && nNodeSizeMax >= nConeSizeMax )
+    {
+        Abc_Print( -1, "For don't-care to work, containing cone should be larger than collapsed node.\n" );
+        return 1;
+    }
+
+    // modify the current network
+    if ( !Abc_NtkRefactor( pNtk, nNodeSizeMax, nConeSizeMax, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ) )
+    {
+        Abc_Print( -1, "Refactoring has failed.\n" );
+        return 1;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: refactor [-NC <num>] [-lzdvh]\n" );
+    Abc_Print( -2, "\t           performs technology-independent refactoring of the AIG\n" );
+    Abc_Print( -2, "\t-N <num> : the max support of the collapsed node [default = %d]\n", nNodeSizeMax );
+    Abc_Print( -2, "\t-C <num> : the max support of the containing cone [default = %d]\n", nConeSizeMax );
+    Abc_Print( -2, "\t-l       : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+    Abc_Print( -2, "\t-z       : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" );
+    Abc_Print( -2, "\t-d       : toggle using don't-cares [default = %s]\n", fUseDcs? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandRestructure( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int nCutsMax;
+    int fUpdateLevel;
+    int fUseZeros;
+    int fVerbose;
+    extern int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutsMax, int fUpdateLevel, int fUseZeros, int fVerbose );
+
+    // set defaults
+    nCutsMax      =  5;
+    fUpdateLevel =  0;
+    fUseZeros    =  0;
+    fVerbose     =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Klzvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nCutsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nCutsMax < 0 )
+                goto usage;
+            break;
+        case 'l':
+            fUpdateLevel ^= 1;
+            break;
+        case 'z':
+            fUseZeros ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( nCutsMax < 4 || nCutsMax > CUT_SIZE_MAX )
+    {
+        Abc_Print( -1, "Can only compute the cuts for %d <= K <= %d.\n", 4, CUT_SIZE_MAX );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" );
+        return 1;
+    }
+    if ( Abc_NtkGetChoiceNum(pNtk) )
+    {
+        Abc_Print( -1, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" );
+        return 1;
+    }
+
+    // modify the current network
+    if ( !Abc_NtkRestructure( pNtk, nCutsMax, fUpdateLevel, fUseZeros, fVerbose ) )
+    {
+        Abc_Print( -1, "Refactoring has failed.\n" );
+        return 1;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: restructure [-K <num>] [-lzvh]\n" );
+    Abc_Print( -2, "\t           performs technology-independent restructuring of the AIG\n" );
+    Abc_Print( -2, "\t-K <num> : the max cut size (%d <= num <= %d) [default = %d]\n",   CUT_SIZE_MIN, CUT_SIZE_MAX, nCutsMax );
+    Abc_Print( -2, "\t-l       : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+    Abc_Print( -2, "\t-z       : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int RS_CUT_MIN =  4;
+    int RS_CUT_MAX = 16;
+    int c;
+    int nCutsMax;
+    int nNodesMax;
+    int nLevelsOdc;
+    int fUpdateLevel;
+    int fUseZeros;
+    int fVerbose;
+    int fVeryVerbose;
+    extern int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutsMax, int nNodesMax, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose );
+
+    // set defaults
+    nCutsMax     =  8;
+    nNodesMax    =  1;
+    nLevelsOdc   =  0;
+    fUpdateLevel =  1;
+    fUseZeros    =  0;
+    fVerbose     =  0;
+    fVeryVerbose =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "KNFlzvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nCutsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nCutsMax < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nNodesMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nNodesMax < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLevelsOdc = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLevelsOdc < 0 )
+                goto usage;
+            break;
+        case 'l':
+            fUpdateLevel ^= 1;
+            break;
+        case 'z':
+            fUseZeros ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( nCutsMax < RS_CUT_MIN || nCutsMax > RS_CUT_MAX )
+    {
+        Abc_Print( -1, "Can only compute cuts for %d <= K <= %d.\n", RS_CUT_MIN, RS_CUT_MAX );
+        return 1;
+    }
+    if ( nNodesMax < 0 || nNodesMax > 3 )
+    {
+        Abc_Print( -1, "Can only resubstitute at most 3 nodes.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" );
+        return 1;
+    }
+    if ( Abc_NtkGetChoiceNum(pNtk) )
+    {
+        Abc_Print( -1, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" );
+        return 1;
+    }
+
+    // modify the current network
+    if ( !Abc_NtkResubstitute( pNtk, nCutsMax, nNodesMax, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose ) )
+    {
+        Abc_Print( -1, "Refactoring has failed.\n" );
+        return 1;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: resub [-KN <num>] [-lzvwh]\n" );
+    Abc_Print( -2, "\t           performs technology-independent restructuring of the AIG\n" );
+    Abc_Print( -2, "\t-K <num> : the max cut size (%d <= num <= %d) [default = %d]\n", RS_CUT_MIN, RS_CUT_MAX, nCutsMax );
+    Abc_Print( -2, "\t-N <num> : the max number of nodes to add (0 <= num <= 3) [default = %d]\n", nNodesMax );
+    Abc_Print( -2, "\t-F <num> : the number of fanout levels for ODC computation [default = %d]\n", nLevelsOdc );
+    Abc_Print( -2, "\t-l       : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+    Abc_Print( -2, "\t-z       : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggle verbose printout of ODC computation [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandRr( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c, Window;
+    int nFaninLevels;
+    int nFanoutLevels;
+    int fUseFanouts;
+    int fVerbose;
+    extern int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose );
+
+    // set defaults
+    nFaninLevels  = 3;
+    nFanoutLevels = 3;
+    fUseFanouts   = 0;
+    fVerbose      = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Wfvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            Window = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Window < 0 )
+                goto usage;
+            nFaninLevels  = Window / 10;
+            nFanoutLevels = Window % 10;
+            break;
+        case 'f':
+            fUseFanouts ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" );
+        return 1;
+    }
+    if ( Abc_NtkGetChoiceNum(pNtk) )
+    {
+        Abc_Print( -1, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" );
+        return 1;
+    }
+
+    // modify the current network
+    if ( !Abc_NtkRR( pNtk, nFaninLevels, nFanoutLevels, fUseFanouts, fVerbose ) )
+    {
+        Abc_Print( -1, "Redundancy removal has failed.\n" );
+        return 1;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: rr [-W NM] [-fvh]\n" );
+    Abc_Print( -2, "\t         removes combinational redundancies in the current network\n" );
+    Abc_Print( -2, "\t-W NM  : window size: TFI (N) and TFO (M) logic levels [default = %d%d]\n", nFaninLevels, nFanoutLevels );
+    Abc_Print( -2, "\t-f     : toggle RR w.r.t. fanouts [default = %s]\n", fUseFanouts? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCascade( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c, nLutSize;
+    int fCheck;
+    int fVerbose;
+    extern Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose );
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set defaults
+    nLutSize = 12;
+    fCheck   = 0;
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Kcvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLutSize < 0 )
+                goto usage;
+            break;
+        case 'c':
+            fCheck ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Can only collapse a logic network or an AIG.\n" );
+        return 1;
+    }
+
+    // get the new network
+    if ( Abc_NtkIsStrash(pNtk) )
+        pNtkRes = Abc_NtkCascade( pNtk, nLutSize, fCheck, fVerbose );
+    else
+    {
+        pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+        pNtkRes = Abc_NtkCascade( pNtk, nLutSize, fCheck, fVerbose );
+        Abc_NtkDelete( pNtk );
+    }
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Cascade synthesis has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: cascade [-K <num>] [-cvh]\n" );
+    Abc_Print( -2, "\t           performs LUT cascade synthesis for the current network\n" );
+    Abc_Print( -2, "\t-K <num> : the number of LUT inputs [default = %d]\n", nLutSize );
+    Abc_Print( -2, "\t-c       : check equivalence after synthesis [default = %s]\n", fCheck? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    Abc_Print( -2, "\t           \n");
+    Abc_Print( -2, "  A lookup-table cascade is a programmable architecture developed by\n");
+    Abc_Print( -2, "  Professor Tsutomu Sasao (sasao@cse.kyutech.ac.jp) at Kyushu Institute\n");
+    Abc_Print( -2, "  of Technology. This work received Takeda Techno-Entrepreneurship Award:\n");
+    Abc_Print( -2, "  http://www.lsi-cad.com/sasao/photo/takeda.html\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandExtract( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Abc_Ntk_t * Abc_NtkShareXor( Abc_Ntk_t * pNtk, int nMultiSize, int fAnd, int fVerbose );
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c, nMultiSize, fAnd, fVerbose;
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set defaults
+    nMultiSize = 3;
+    fAnd       = 0;
+    fVerbose   = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Kavh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nMultiSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nMultiSize < 0 )
+                goto usage;
+            break;
+        case 'a':
+            fAnd ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Can only collapse a logic network or an AIG.\n" );
+        return 1;
+    }
+    // get the new network
+    pNtkRes = Abc_NtkShareXor( pNtk, nMultiSize, fAnd, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Cascade synthesis has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: extract [-K <num>] [-avh]\n" );
+    Abc_Print( -2, "\t           extracts shared logic from multi-input gates\n" );
+    Abc_Print( -2, "\t-K <num> : the minimum gate size to consider for extraction [default = %d]\n", nMultiSize );
+    Abc_Print( -2, "\t-a       : toggle multi-input XOR vs multi-input AND [default = %s]\n", fAnd? "AND": "XOR" );
+    Abc_Print( -2, "\t-v       : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandVarMin( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Abc_SuppTest( int nOnes, int nVars, int fUseSimple, int fCheck, int fVerbose );
+    extern void Abc_SuppReadMinTest( char * pFileName );
+    int nOnes      =  4;
+    int nVars      = 20;
+    int fUseSimple =  0;
+    int fCheck     =  0;
+    int fVerbose   =  0;
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "MNocvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nOnes = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nOnes < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nVars = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nVars < 0 )
+                goto usage;
+            break;
+        case 'o':
+            fUseSimple ^= 1;
+            break;
+        case 'c':
+            fCheck ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    // get the file name
+    if ( argc == globalUtilOptind + 1 )
+    {
+        Abc_SuppReadMinTest( argv[globalUtilOptind] );
+        return 0;
+    }
+    Abc_SuppTest( nOnes, nVars, fUseSimple, fCheck, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: varmin [-MN <num>] [-ocvh]\n" );
+    Abc_Print( -2, "\t           performs support minimization\n" );
+    Abc_Print( -2, "\t-M <num> : the number of ones in the combination [default = %d]\n", nOnes );
+    Abc_Print( -2, "\t-N <num> : the number of variables in the problem [default = %d]\n", nVars );
+    Abc_Print( -2, "\t-o       : toggle computing reduced difference matrix [default = %s]\n", fUseSimple? "yes": "no" );
+    Abc_Print( -2, "\t-c       : toggle verifying the final result [default = %s]\n", fCheck? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash( pNtk ) )
+    {
+        Abc_Print( -1, "This command is only applicable to strashed networks.\n" );
+        return 1;
+    }
+
+    // get the new network
+    pNtkRes = Abc_NtkToLogic( pNtk );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Converting to a logic network has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: logic [-h]\n" );
+    Abc_Print( -2, "\t        transforms an AIG into a logic network with SOPs\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandComb( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int fRemoveLatches;
+    int nLatchesToAdd;
+    extern void Abc_NtkMakeSeq( Abc_Ntk_t * pNtk, int nLatchesToAdd );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fRemoveLatches = 0;
+    nLatchesToAdd = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Llh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLatchesToAdd = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLatchesToAdd < 0 )
+                goto usage;
+            break;
+        case 'l':
+            fRemoveLatches ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkIsComb(pNtk) && nLatchesToAdd == 0 )
+    {
+        Abc_Print( -1, "The network is already combinational.\n" );
+        return 0;
+    }
+    if ( !Abc_NtkIsComb(pNtk) && nLatchesToAdd != 0 )
+    {
+        Abc_Print( -1, "The network is already combinational.\n" );
+        return 0;
+    }
+
+    // get the new network
+    pNtkRes = Abc_NtkDup( pNtk );
+    if ( nLatchesToAdd )
+        Abc_NtkMakeSeq( pNtkRes, nLatchesToAdd );
+    else
+        Abc_NtkMakeComb( pNtkRes, fRemoveLatches );
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: comb [-L <num>] [-lh]\n" );
+    Abc_Print( -2, "\t           converts comb network into seq, and vice versa\n" );
+    Abc_Print( -2, "\t-L <num> : number of latches to add to comb network (0 = do not add) [default = %d]\n", nLatchesToAdd );
+    Abc_Print( -2, "\t-l       : toggle converting latches to PIs/POs or removing them [default = %s]\n", fRemoveLatches? "remove": "convert" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char Buffer[32];
+    Abc_Ntk_t * pNtk, * pNtk1, * pNtk2, * pNtkRes;
+    int fDelete1, fDelete2;
+    char ** pArgvNew;
+    int nArgcNew;
+    int c;
+    int fCheck;
+    int fComb;
+    int fImplic;
+    int fMulti;
+    int nPartSize;
+    int fTrans;
+    int fIgnoreNames;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set defaults
+    fComb  = 0;
+    fCheck = 1;
+    fImplic = 0;
+    fMulti = 0;
+    nPartSize = 0;
+    fTrans = 0;
+    fIgnoreNames = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Pcmitnh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nPartSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nPartSize < 0 )
+                goto usage;
+            break;
+        case 'c':
+            fComb ^= 1;
+            break;
+        case 'm':
+            fMulti ^= 1;
+            break;
+        case 'i':
+            fImplic ^= 1;
+            break;
+        case 't':
+            fTrans ^= 1;
+            break;
+        case 'n':
+            fIgnoreNames ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( fTrans )
+    {
+        if ( (Abc_NtkPoNum(pNtk) & 1) == 1 )
+        {
+            Abc_Print( -1, "Abc_CommandMiter(): The number of outputs should be even.\n" );
+            return 0;
+        }
+        // replace the current network
+        pNtkRes = Abc_NtkDupTransformMiter( pNtk );
+        Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+        Abc_Print( 1, "The miter (current network) is transformed by XORing POs pair-wise.\n" );
+        return 0;
+    }
+
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+        return 1;
+
+    if ( fIgnoreNames )
+    {
+        if ( !fDelete1 )
+        {
+            pNtk1 = Abc_NtkStrash( pNtk1, 0, 1, 0 );
+            fDelete1 = 1;
+        }
+        if ( !fDelete2 )
+        {
+            pNtk2 = Abc_NtkStrash( pNtk2, 0, 1, 0 );
+            fDelete2 = 1;
+        }
+        Abc_NtkShortNames( pNtk1 );
+        Abc_NtkShortNames( pNtk2 );
+    }
+    // compute the miter
+    pNtkRes = Abc_NtkMiter( pNtk1, pNtk2, fComb, nPartSize, fImplic, fMulti );
+    if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+    if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+
+    // get the new network
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Miter computation has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    if ( nPartSize == 0 )
+        strcpy( Buffer, "unused" );
+    else
+        sprintf(Buffer, "%d", nPartSize );
+    Abc_Print( -2, "usage: miter [-P <num>] [-cimtnh] <file1> <file2>\n" );
+    Abc_Print( -2, "\t           computes the miter of the two circuits\n" );
+    Abc_Print( -2, "\t-P <num> : output partition size [default = %s]\n", Buffer );
+    Abc_Print( -2, "\t-c       : toggles deriving combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" );
+    Abc_Print( -2, "\t-i       : toggles deriving implication miter (file1 => file2) [default = %s]\n", fImplic? "yes": "no" );
+    Abc_Print( -2, "\t-m       : toggles creating multi-output miter [default = %s]\n", fMulti? "yes": "no" );
+    Abc_Print( -2, "\t-t       : toggle XORing pair-wise POs of the miter [default = %s]\n", fTrans? "yes": "no" );
+    Abc_Print( -2, "\t-n       : toggle ignoring names when matching CIs/COs [default = %s]\n", fIgnoreNames? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    Abc_Print( -2, "\tfile1    : (optional) the file with the first network\n");
+    Abc_Print( -2, "\tfile2    : (optional) the file with the second network\n");
+    Abc_Print( -2, "\t           if no files are given, uses the current network and its spec\n");
+    Abc_Print( -2, "\t           if one file is given, uses the current network and the file\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDemiter( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c, fDual, fVerbose;
+    extern int Abc_NtkDarDemiter( Abc_Ntk_t * pNtk );
+    extern int Abc_NtkDarDemiterDual( Abc_Ntk_t * pNtk, int fVerbose );
+    // set defaults
+    fDual = 0;
+    fVerbose = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "dvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'd':
+            fDual ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "The network is not strashed.\n" );
+        return 1;
+    }
+
+    if ( fDual )
+    {
+        if ( (Abc_NtkPoNum(pNtk) & 1) )
+        {
+            Abc_Print( -1, "The number of POs should be even.\n" );
+            return 0;
+        }
+        if ( !Abc_NtkDarDemiterDual( pNtk, fVerbose ) )
+        {
+            Abc_Print( -1, "Demitering has failed.\n" );
+            return 1;
+        }
+        return 0;
+    }
+/*
+    if ( Abc_NtkPoNum(pNtk) != 1 )
+    {
+        Abc_Print( -1, "The network is not a single-output miter.\n" );
+        return 1;
+    }
+    if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) )
+    {
+        Abc_Print( -1, "The miter's PO is not an EXOR.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkDemiter( pNtk ) )
+    {
+        Abc_Print( -1, "Demitering has failed.\n" );
+        return 1;
+    }
+*/
+    // get the new network
+    if ( !Abc_NtkDarDemiter( pNtk ) )
+    {
+        Abc_Print( -1, "Demitering has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+//    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: demiter [-dvh]\n" );
+    Abc_Print( -2, "\t        splits sequential miter into two circuits\n" );
+    Abc_Print( -2, "\t-d    : expects a dual-output miter (without XORs) [default = %s]\n", fDual? "yes": "no" );
+    Abc_Print( -2, "\t-v    : toggles outputting verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandOrPos( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);//, * pNtkRes;
+    int fReverse = 0;
+    int fComb = 0;
+    int fXor = 0;
+    int c;
+    extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd, int fXor );
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "rxh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'r':
+            fReverse ^= 1;
+            break;
+        case 'x':
+            fXor ^= 1;
+            break;
+        case 'c':
+            fComb ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "The network is not strashed.\n" );
+        return 1;
+    }
+    // get the new network
+    if ( fReverse )
+    {
+        extern Aig_Man_t * Abc_NtkToDarBmc( Abc_Ntk_t * pNtk, Vec_Int_t ** pvMap );
+        Aig_Man_t * pMan = Abc_NtkToDarBmc( pNtk, NULL );
+        Abc_Ntk_t * pNtkRes = Abc_NtkFromAigPhase( pMan );
+        Aig_ManStop( pMan );
+        // perform expansion
+        if ( Abc_NtkPoNum(pNtk) != Abc_NtkPoNum(pNtkRes) )
+            Abc_Print( 1,"Expanded %d outputs into %d outputs using OR decomposition.\n", Abc_NtkPoNum(pNtk), Abc_NtkPoNum(pNtkRes) );
+        else
+            Abc_Print( 1,"The output(s) cannot be structurally decomposed.\n" );
+        // clear counter-example
+        if ( pAbc->pCex )
+            ABC_FREE( pAbc->pCex );
+        // replace the current network
+        ABC_FREE( pNtkRes->pName );
+        pNtkRes->pName = Extra_UtilStrsav(pNtk->pName);
+        Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    }
+    else
+    {
+        if ( !Abc_NtkCombinePos( pNtk, 0, fXor ) )
+        {
+            Abc_Print( -1, "ORing the POs has failed.\n" );
+            return 1;
+        }
+        // update counter-example
+        if ( pAbc->pCex )
+            pAbc->pCex->iPo = 0;
+        // replace the current network
+    //    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: orpos [-rxh]\n" );
+    Abc_Print( -2, "\t        creates single-output miter by ORing the POs of the current network\n" );
+    Abc_Print( -2, "\t-r    : performs the reverse transform (OR decomposition) [default = %s]\n", fReverse? "yes": "no" );
+    Abc_Print( -2, "\t-x    : toggles combining the PO using XOR [default = %s]\n", fXor? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAndPos( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);//, * pNtkRes;
+    int fComb = 0;
+    int c;
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'c':
+            fComb ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "The network is not strashed.\n" );
+        return 1;
+    }
+
+    if ( Abc_NtkPoNum(pNtk) == 1 )
+    {
+        Abc_Print( -1, "The network already has one PO.\n" );
+        return 1;
+    }
+
+    if ( Abc_NtkLatchNum(pNtk) )
+    {
+        Abc_Print( -1, "The miter has latches. ORing is not performed.\n" );
+        return 1;
+    }
+
+    // get the new network
+    if ( !Abc_NtkCombinePos( pNtk, 1, 0 ) )
+    {
+        Abc_Print( -1, "ANDing the POs has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+//    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: andpos [-h]\n" );
+    Abc_Print( -2, "\t        creates single-output miter by ANDing the POs of the current network\n" );
+//    Abc_Print( -2, "\t-c    : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandZeroPo( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);//, * pNtkRes = NULL;
+    int c, iOutput = -1;
+    int fSkipSweep = 0;
+    int fUseConst1 = 0;
+    extern void Abc_NtkDropOneOutput( Abc_Ntk_t * pNtk, int iOutput, int fSkipSweep, int fUseConst1 );
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Nsoh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iOutput = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iOutput < 0 )
+                goto usage;
+            break;
+        case 's':
+            fSkipSweep ^= 1;
+            break;
+        case 'o':
+            fUseConst1 ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "The network is not strashed.\n" );
+        return 1;
+    }
+    if ( iOutput < 0 )
+    {
+        Abc_Print( -1, "The output index is not specified.\n" );
+        return 1;
+    }
+    if ( iOutput >= Abc_NtkPoNum(pNtk) )
+    {
+        Abc_Print( -1, "The output index is larger than the allowed POs.\n" );
+        return 1;
+    }
+
+    // get the new network
+//    pNtkRes = Abc_NtkDup( pNtk );
+//    Abc_NtkDropOneOutput( pNtkRes, iOutput );
+//    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    Abc_NtkDropOneOutput( pNtk, iOutput, fSkipSweep, fUseConst1 );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: zeropo [-N <num>] [-soh]\n" );
+    Abc_Print( -2, "\t           replaces the PO driver by constant 0\n" );
+    Abc_Print( -2, "\t-N <num> : the zero-based index of the PO to replace [default = %d]\n", iOutput );
+    Abc_Print( -2, "\t-s       : performs comb sweep after removimg a PO [default = %s]\n", !fSkipSweep? "yes": "no" );
+    Abc_Print( -2, "\t-o       : toggles using const 1 instead of const 0 [default = %s]\n", fUseConst1? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSwapPos( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes;
+    int c, iOutput = -1;
+    extern void Abc_NtkSwapOneOutput( Abc_Ntk_t * pNtk, int iOutput );
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iOutput = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iOutput < 0 )
+                goto usage;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "The network is not strashed.\n" );
+        return 1;
+    }
+    if ( iOutput < 0 )
+    {
+        Abc_Print( -1, "The output index is not specified.\n" );
+        return 1;
+    }
+    if ( iOutput >= Abc_NtkPoNum(pNtk) )
+    {
+        Abc_Print( -1, "The output index is larger than the allowed POs.\n" );
+        return 1;
+    }
+
+    // get the new network
+    pNtkRes = Abc_NtkDup( pNtk );
+    Abc_NtkSwapOneOutput( pNtkRes, iOutput );
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: swappos [-N <num>] [-h]\n" );
+    Abc_Print( -2, "\t           swap the 0-th PO with the <num>-th PO\n" );
+    Abc_Print( -2, "\t-N <num> : the zero-based index of the PO to swap [default = %d]\n", iOutput );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandRemovePo( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);//, * pNtkRes = NULL;
+    int c, iOutput = -1;
+    int fRemoveConst0 = 1;
+    extern void Abc_NtkRemovePo( Abc_Ntk_t * pNtk, int iOutput, int fRemoveConst0 );
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Nzh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iOutput = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iOutput < 0 )
+                goto usage;
+            break;
+        case 'z':
+            fRemoveConst0 ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "The network is not strashed.\n" );
+        return 1;
+    }
+    if ( iOutput < 0 )
+    {
+        Abc_Print( -1, "The output index is not specified.\n" );
+        return 1;
+    }
+    if ( iOutput >= Abc_NtkPoNum(pNtk) )
+    {
+        Abc_Print( -1, "The output index is larger than the allowed POs.\n" );
+        return 1;
+    }
+
+    // get the new network
+//    pNtkRes = Abc_NtkDup( pNtk );
+//    Abc_NtkRemovePo( pNtkRes, iOutput );
+//    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    Abc_NtkRemovePo( pNtk, iOutput, fRemoveConst0 );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: removepo [-N <num>] [-zh]\n" );
+    Abc_Print( -2, "\t           remove PO with number <num> if it is const0\n" );
+    Abc_Print( -2, "\t-N <num> : the zero-based index of the PO to remove [default = %d]\n", iOutput );
+    Abc_Print( -2, "\t-z       : toggle removing const1 instead of const0 [default = %s]\n", fRemoveConst0? "const0": "const1" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDropSat( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Abc_NtkDropSatOutputs( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCexes, int fVerbose );
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes = NULL;
+    int fNoSweep = 0;
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 's':
+            fNoSweep ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for AIGs (run \"strash\").\n" );
+        return 1;
+    }
+    if ( pAbc->vCexVec == NULL )
+    {
+        Abc_Print( -1, "CEX array is not defined. Run \"bmc3 -az\", \"sim3 -az\", or \"pdr -az\".\n" );
+        return 1;
+    }
+    if ( Vec_PtrSize(pAbc->vCexVec) != Abc_NtkPoNum(pNtk) )
+    {
+        Abc_Print( -1, "CEX array size (%d) does not match the number of outputs (%d).\n", Vec_PtrSize(pAbc->vCexVec), Abc_NtkPoNum(pNtk) );
+        return 1;
+    }
+    Abc_NtkDropSatOutputs( pNtk, pAbc->vCexVec, fVerbose );
+    if ( !fNoSweep )
+    {
+        pNtkRes = Abc_NtkDarLatchSweep( pNtk, 1, 1, 1, 0, -1, -1, 0, 0 );
+        if ( pNtkRes == NULL )
+        {
+            Abc_Print( -1, "Removing SAT outputs has failed.\n" );
+            return 1;
+        }
+        Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dropsat [-sh]\n" );
+    Abc_Print( -2, "\t         replaces satisfiable POs by constant 0 and cleans up the AIG\n" );
+    Abc_Print( -2, "\t-s     : toggles skipping sequential sweep [default = %s]\n", fNoSweep? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAddPi( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes;
+    int c;
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    // get the new network
+    pNtkRes = Abc_NtkDup( pNtk );
+    if ( Abc_NtkPiNum(pNtkRes) == 0 )
+    {
+        Abc_Obj_t * pObj = Abc_NtkCreatePi( pNtkRes );
+        Abc_ObjAssignName( pObj, "dummy_pi", NULL );
+        Abc_NtkOrderCisCos( pNtkRes );
+    }
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: addpi [-h]\n" );
+    Abc_Print( -2, "\t         if the network has no PIs, add one dummy PI\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAppend( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtk2;
+    char * FileName;
+    int fComb = 0;
+    int c;
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'c':
+            fComb ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    // get the second network
+    if ( argc != globalUtilOptind + 1 )
+    {
+        Abc_Print( -1, "The network to append is not given.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "The base network should be strashed for the appending to work.\n" );
+        return 1;
+    }
+
+    // read the second network
+    FileName = argv[globalUtilOptind];
+    pNtk2 = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 );
+    if ( pNtk2 == NULL )
+        return 1;
+
+    // check if the second network is combinational
+    if ( Abc_NtkLatchNum(pNtk2) )
+    {
+        Abc_NtkDelete( pNtk2 );
+        Abc_Print( -1, "The second network has latches. Appending does not work for such networks.\n" );
+        return 0;
+    }
+
+    // get the new network
+    if ( !Abc_NtkAppend( pNtk, pNtk2, 1 ) )
+    {
+        Abc_NtkDelete( pNtk2 );
+        Abc_Print( -1, "Appending the networks failed.\n" );
+        return 1;
+    }
+    Abc_NtkDelete( pNtk2 );
+    // sweep dangling logic
+    Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc );
+    // replace the current network
+//    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: append [-h] <file>\n" );
+    Abc_Print( -2, "\t         appends a combinational network on top of the current network\n" );
+//    Abc_Print( -2, "\t-c     : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : file name with the second network\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPutOnTop( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Abc_Ntk_t * Abc_NtkPutOnTop( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtk2 );
+
+    Abc_Ntk_t * pNtk, * pNtk2, * pNtkRes;
+    char * FileName;
+    int fComb = 0;
+    int c;
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'c':
+            fComb ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    // get the second network
+    if ( argc != globalUtilOptind + 1 )
+    {
+        Abc_Print( -1, "The network to append is not given.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "The base network should be in the logic form.\n" );
+        return 1;
+    }
+
+    // check if the second network is combinational
+    if ( Abc_NtkLatchNum(pNtk) )
+    {
+        Abc_Print( -1, "The current network has latches. This command does not work for such networks.\n" );
+        return 0;
+    }
+
+    // read the second network
+    FileName = argv[globalUtilOptind];
+    pNtk2 = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 );
+    if ( pNtk2 == NULL )
+        return 1;
+
+    // check if the second network is combinational
+    if ( Abc_NtkLatchNum(pNtk2) )
+    {
+        Abc_NtkDelete( pNtk2 );
+        Abc_Print( -1, "The second network has latches. This command does not work for such networks.\n" );
+        return 0;
+    }
+    // compare inputs/outputs
+    if ( Abc_NtkPoNum(pNtk) != Abc_NtkPiNum(pNtk2) )
+    {
+        Abc_NtkDelete( pNtk2 );
+        Abc_Print( -1, "The PO count (%d) of the first network is not equal to PI count (%d) of the second network.\n", Abc_NtkPoNum(pNtk), Abc_NtkPiNum(pNtk2) );
+        return 0;
+    }
+
+    // get the new network
+    pNtkRes = Abc_NtkPutOnTop( pNtk, pNtk2 );
+    Abc_NtkDelete( pNtk2 );
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: putontop [-h] <file>\n" );
+    Abc_Print( -2, "\t         connects PIs of network in <file> to POs of current network\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : file name with the second network\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandFrames( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkTemp, * pNtkRes;
+    int nFrames;
+    int fInitial;
+    int fVerbose;
+    int c;
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set defaults
+    nFrames  = 5;
+    fInitial = 0;
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Fivh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames <= 0 )
+                goto usage;
+            break;
+        case 'i':
+            fInitial ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    // get the new network
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+        pNtkRes  = Abc_NtkFrames( pNtkTemp, nFrames, fInitial, fVerbose );
+        Abc_NtkDelete( pNtkTemp );
+    }
+    else
+        pNtkRes  = Abc_NtkFrames( pNtk, nFrames, fInitial, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Unrolling the network has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: frames [-F <num>] [-ivh]\n" );
+    Abc_Print( -2, "\t           unrolls the network for a number of time frames\n" );
+    Abc_Print( -2, "\t-F <num> : the number of frames to unroll [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-i       : toggles initializing the first frame [default = %s]\n", fInitial? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggles outputting verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDFrames( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkTemp, * pNtkRes;
+    int nPrefix;
+    int nFrames;
+    int fInitial;
+    int fVerbose;
+    int c;
+
+    extern Abc_Ntk_t * Abc_NtkDarFrames( Abc_Ntk_t * pNtk, int nPrefix, int nFrames, int fInitial, int fVerbose );
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set defaults
+    nPrefix  = 5;
+    nFrames  = 5;
+    fInitial = 0;
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "NFivh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nPrefix = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nPrefix <= 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames <= 0 )
+                goto usage;
+            break;
+        case 'i':
+            fInitial ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( nPrefix > nFrames )
+    {
+        Abc_Print( -1, "Prefix (%d) cannot be more than the number of frames (%d).\n", nPrefix, nFrames );
+        return 1;
+    }
+
+    // get the new network
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+        pNtkRes  = Abc_NtkDarFrames( pNtkTemp, nPrefix, nFrames, fInitial, fVerbose );
+        Abc_NtkDelete( pNtkTemp );
+    }
+    else
+        pNtkRes  = Abc_NtkDarFrames( pNtk, nPrefix, nFrames, fInitial, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Unrolling the network has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dframes [-NF <num>] [-ivh]\n" );
+    Abc_Print( -2, "\t         unrolls the network with simplification\n" );
+    Abc_Print( -2, "\t-N num : the number of frames to use as prefix [default = %d]\n", nPrefix );
+    Abc_Print( -2, "\t-F num : the number of frames to unroll [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-i     : toggles initializing the first frame [default = %s]\n", fInitial? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggles outputting verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int fDirect;
+    int c;
+
+    // set defaults
+    fDirect = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'd':
+            fDirect ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "Converting to SOP is possible only for logic networks.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkToSop(pNtk, fDirect) )
+    {
+        Abc_Print( -1, "Converting to SOP has failed.\n" );
+        return 1;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: sop [-dh]\n" );
+    Abc_Print( -2, "\t         converts node functions to SOP\n" );
+    Abc_Print( -2, "\t-d     : toggles using both phases or only positive [default = %s]\n", fDirect? "direct": "both" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int fReorder = 1;
+    int c;
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "rh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'r':
+            fReorder ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "Converting to BDD is possible only for logic networks.\n" );
+        return 1;
+    }
+    if ( Abc_NtkIsBddLogic(pNtk) )
+    {
+        Abc_Print( -1, "The logic network is already in the BDD form.\n" );
+        return 0;
+    }
+    if ( !Abc_NtkToBdd(pNtk) )
+    {
+        Abc_Print( -1, "Converting to BDD has failed.\n" );
+        return 1;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: bdd [-rh]\n" );
+    Abc_Print( -2, "\t         converts node functions to BDD\n" );
+    Abc_Print( -2, "\t-r     : toggles enabling dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "Converting to AIG is possible only for logic networks.\n" );
+        return 1;
+    }
+    if ( Abc_NtkIsAigLogic(pNtk) )
+    {
+        Abc_Print( -1, "The logic network is already in the AIG form.\n" );
+        return 0;
+    }
+    if ( !Abc_NtkToAig(pNtk) )
+    {
+        Abc_Print( -1, "Converting to AIG has failed.\n" );
+        return 1;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: aig [-h]\n" );
+    Abc_Print( -2, "\t         converts node functions to AIG\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandReorder( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fVerbose;
+    extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose );
+
+    // set defaults
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    // get the new network
+    if ( !Abc_NtkIsBddLogic(pNtk) )
+    {
+        Abc_Print( -1, "Variable reordering is possible when node functions are BDDs (run \"bdd\").\n" );
+        return 1;
+    }
+    Abc_NtkBddReorder( pNtk, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: reorder [-vh]\n" );
+    Abc_Print( -2, "\t         reorders local functions of the nodes using sifting\n" );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandBidec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fVerbose;
+    extern void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose );
+
+    // set defaults
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    // get the new network
+    if ( !Abc_NtkIsAigLogic(pNtk) )
+    {
+        Abc_Print( -1, "Bi-decomposition only works when node functions are AIGs (run \"aig\").\n" );
+        return 1;
+    }
+    Abc_NtkBidecResyn( pNtk, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: bidec [-vh]\n" );
+    Abc_Print( -2, "\t         applies bi-decomposition to local functions of the nodes\n" );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandOrder( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    FILE * pFile;
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    char * pFileName;
+    int c;
+    int fReverse;
+    int fVerbose;
+    extern void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose );
+    extern void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose );
+
+    // set defaults
+    fReverse = 0;
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'r':
+            fReverse ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+//    if ( Abc_NtkLatchNum(pNtk) > 0 )
+//    {
+//        Abc_Print( -1, "Currently this procedure does not work for sequential networks.\n" );
+//        return 1;
+//    }
+
+    // if the var order file is given, implement this order
+    pFileName = NULL;
+    if ( argc == globalUtilOptind + 1 )
+    {
+        pFileName = argv[globalUtilOptind];
+        pFile = fopen( pFileName, "r" );
+        if ( pFile == NULL )
+        {
+            Abc_Print( -1, "Cannot open file \"%s\" with the BDD variable order.\n", pFileName );
+            return 1;
+        }
+        fclose( pFile );
+    }
+    if ( pFileName )
+        Abc_NtkImplementCiOrder( pNtk, pFileName, fReverse, fVerbose );
+    else
+        Abc_NtkFindCiOrder( pNtk, fReverse, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: order [-rvh] <file>\n" );
+    Abc_Print( -2, "\t         computes a good static CI variable order\n" );
+    Abc_Print( -2, "\t-r     : toggle reverse ordering [default = %s]\n", fReverse? "yes": "no" );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : (optional) file with the given variable order\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsBddLogic(pNtk) )
+    {
+        Abc_Print( -1, "Only a BDD logic network can be converted to MUXes.\n" );
+        return 1;
+    }
+
+    // get the new network
+    pNtkRes = Abc_NtkBddToMuxes( pNtk );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Converting to MUXes has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: muxes [-h]\n" );
+    Abc_Print( -2, "\t        converts the current network into a network derived by\n" );
+    Abc_Print( -2, "\t        replacing all nodes by DAGs isomorphic to the local BDDs\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCubes( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Abc_Ntk_t * Abc_NtkSopToCubes( Abc_Ntk_t * pNtk );
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsSopLogic(pNtk) )
+    {
+        Abc_Print( -1, "Only a SOP logic network can be transformed into cubes.\n" );
+        return 1;
+    }
+
+    // get the new network
+    pNtkRes = Abc_NtkSopToCubes( pNtk );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Converting to cubes has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: cubes [-h]\n" );
+    Abc_Print( -2, "\t        converts the current network into a network derived by creating\n" );
+    Abc_Print( -2, "\t        a separate node for each product and sum in the local SOPs\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSplitSop( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Abc_Ntk_t * Abc_NtkSplitSop( Abc_Ntk_t * pNtk, int nCubesMax, int fVerbose );
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c, fVerbose = 0, nCubesMax = 100;
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Nvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nCubesMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nCubesMax < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsSopLogic(pNtk) )
+    {
+        Abc_Print( -1, "Only a SOP logic network can be transformed into cubes.\n" );
+        return 1;
+    }
+
+    // get the new network
+    pNtkRes = Abc_NtkSplitSop( pNtk, nCubesMax, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Converting to cubes has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: splitsop [-N num] [-vh]\n" );
+    Abc_Print( -2, "\t         splits nodes whose SOP size is larger than the given one\n" );
+    Abc_Print( -2, "\t-N num : the maximum number of cubes after splitting [default = %d]\n", nCubesMax );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandExtSeqDcs( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fVerbose;
+    extern int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNet, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkLatchNum(pNtk) == 0 )
+    {
+        Abc_Print( -1, "The current network has no latches.\n" );
+        return 0;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Extracting sequential don't-cares works only for AIGs (run \"strash\").\n" );
+        return 0;
+    }
+    if ( !Abc_NtkExtractSequentialDcs( pNtk, fVerbose ) )
+    {
+        Abc_Print( -1, "Extracting sequential don't-cares has failed.\n" );
+        return 1;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: ext_seq_dcs [-vh]\n" );
+    Abc_Print( -2, "\t         create EXDC network using unreachable states\n" );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandReach( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Saig_ParBbr_t Pars, * pPars = &Pars;
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    char * pLogFileName = NULL;
+
+    extern int Abc_NtkDarReach( Abc_Ntk_t * pNtk, Saig_ParBbr_t * pPars );
+
+    // set defaults
+    Bbr_ManSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "TBFLproyvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeLimit < 0 )
+                goto usage;
+            break;
+        case 'B':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBddMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBddMax < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nIterMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nIterMax < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pLogFileName = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'p':
+            pPars->fPartition ^= 1;
+            break;
+        case 'r':
+            pPars->fReorder ^= 1;
+            break;
+        case 'o':
+            pPars->fReorderImage ^= 1;
+            break;
+        case 'y':
+            pPars->fSkipOutCheck ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkLatchNum(pNtk) == 0 )
+    {
+        Abc_Print( -1, "The current network has no latches.\n" );
+        return 0;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Reachability analysis works only for AIGs (run \"strash\").\n" );
+        return 1;
+    }
+    pAbc->Status  = Abc_NtkDarReach( pNtk, pPars );
+    pAbc->nFrames = pPars->iFrame;
+    Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel );
+    if ( pLogFileName )
+        Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "reach" );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: reach [-TBF num] [-L file] [-proyvh]\n" );
+    Abc_Print( -2, "\t         verifies sequential miter using BDD-based reachability\n" );
+    Abc_Print( -2, "\t-T num : approximate time limit in seconds (0=infinite) [default = %d]\n", pPars->TimeLimit );
+    Abc_Print( -2, "\t-B num : max number of nodes in the intermediate BDDs [default = %d]\n", pPars->nBddMax );
+    Abc_Print( -2, "\t-F num : max number of reachability iterations [default = %d]\n", pPars->nIterMax );
+    Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" );
+    Abc_Print( -2, "\t-p     : enable partitioned image computation [default = %s]\n", pPars->fPartition? "yes": "no" );
+    Abc_Print( -2, "\t-r     : enable dynamic BDD variable reordering [default = %s]\n", pPars->fReorder? "yes": "no" );
+    Abc_Print( -2, "\t-o     : toggles BDD variable reordering during image computation [default = %s]\n", pPars->fReorderImage? "yes": "no" );
+    Abc_Print( -2, "\t-y     : skip checking property outputs [default = %s]\n", pPars->fSkipOutCheck? "yes": "no" );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCone( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    Abc_Obj_t * pNode, * pNodeCo;
+    int c;
+    int fUseAllCis;
+    int fUseMffc;
+    int fSeq;
+    int Output;
+    int nRange;
+
+    extern Abc_Ntk_t * Abc_NtkMakeOnePo( Abc_Ntk_t * pNtk, int Output, int nRange );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fUseAllCis = 0;
+    fUseMffc = 0;
+    fSeq = 0;
+    Output = -1;
+    nRange = -1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ORmash" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'O':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            Output = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Output < 0 )
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nRange = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nRange < 0 )
+                goto usage;
+            break;
+        case 'm':
+            fUseMffc ^= 1;
+            break;
+        case 'a':
+            fUseAllCis ^= 1;
+            break;
+        case 's':
+            fSeq ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Currently can only be applied to the logic network or an AIG.\n" );
+        return 1;
+    }
+
+    if ( argc > globalUtilOptind + 1 )
+    {
+        Abc_Print( -1, "Wrong number of auguments.\n" );
+        goto usage;
+    }
+
+    pNodeCo = NULL;
+    if ( argc == globalUtilOptind + 1 )
+    {
+        pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+        if ( pNode == NULL )
+        {
+            Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+            return 1;
+        }
+        if ( fUseMffc )
+            pNtkRes = Abc_NtkCreateMffc( pNtk, pNode, argv[globalUtilOptind] );
+        else
+            pNtkRes = Abc_NtkCreateCone( pNtk, pNode, argv[globalUtilOptind], fUseAllCis );
+    }
+    else
+    {
+        if ( Output == -1 )
+        {
+            Abc_Print( -1, "The node is not specified.\n" );
+            return 1;
+        }
+        if ( Output >= Abc_NtkCoNum(pNtk) )
+        {
+            Abc_Print( -1, "The 0-based output number (%d) is larger than the number of outputs (%d).\n", Output, Abc_NtkCoNum(pNtk) );
+            return 1;
+        }
+        pNodeCo = Abc_NtkCo( pNtk, Output );
+        if ( fSeq )
+            pNtkRes = Abc_NtkMakeOnePo( pNtk, Output, nRange );
+        else if ( fUseMffc )
+            pNtkRes = Abc_NtkCreateMffc( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo) );
+        else
+            pNtkRes = Abc_NtkCreateCone( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo), fUseAllCis );
+    }
+    if ( pNodeCo && Abc_ObjFaninC0(pNodeCo) && !fSeq )
+    {
+        Abc_NtkPo(pNtkRes, 0)->fCompl0  ^= 1;
+//        Abc_Print( -1, "The extracted cone represents the complement function of the CO.\n" );
+    }
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Writing the logic cone of one node has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: cone [-OR num] [-amsh] <name>\n" );
+    Abc_Print( -2, "\t         replaces the current network by one logic cone\n" );
+    Abc_Print( -2, "\t-a     : toggle keeping all CIs or structral support only [default = %s]\n", fUseAllCis? "all": "structural" );
+    Abc_Print( -2, "\t-m     : toggle keeping only MFFC or complete TFI cone [default = %s]\n", fUseMffc? "MFFC": "TFI cone" );
+    Abc_Print( -2, "\t-s     : toggle comb or sequential cone (works with \"-O num\") [default = %s]\n", fSeq? "seq": "comb" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t-O num : (optional) the 0-based number of the CO to extract\n");
+    Abc_Print( -2, "\t-R num : (optional) the number of outputs to extract\n");
+    Abc_Print( -2, "\tname   : (optional) the name of the node to extract\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandNode( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    Abc_Obj_t * pNode;
+    int c;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+       case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "Currently can only be applied to a logic network.\n" );
+        return 1;
+    }
+
+    if ( argc != globalUtilOptind + 1 )
+    {
+        Abc_Print( -1, "Wrong number of auguments.\n" );
+        goto usage;
+    }
+
+    pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+    if ( pNode == NULL )
+    {
+        Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+        return 1;
+    }
+
+    pNtkRes = Abc_NtkCreateFromNode( pNtk, pNode );
+//    pNtkRes = Abc_NtkDeriveFromBdd( pNtk->pManFunc, pNode->pData, NULL, NULL );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Splitting one node has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: node [-h] <name>\n" );
+    Abc_Print( -2, "\t         replaces the current network by the network composed of one node\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\tname   : the node name\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandTopmost( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c, nLevels;
+    extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nLevels = 10;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLevels = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLevels < 0 )
+                goto usage;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" );
+        return 0;
+    }
+
+    if ( Abc_NtkLatchNum(pNtk) > 0 )
+    {
+        Abc_Print( -1, "Currently can only works for combinational circuits.\n" );
+        return 0;
+    }
+    if ( Abc_NtkPoNum(pNtk) != 1 )
+    {
+        Abc_Print( -1, "Currently expects a single-output miter.\n" );
+        return 0;
+    }
+
+    pNtkRes = Abc_NtkTopmost( pNtk, nLevels );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "The command has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: topmost [-N num] [-h]\n" );
+    Abc_Print( -2, "\t         replaces the current network by several of its topmost levels\n" );
+    Abc_Print( -2, "\t-N num : max number of levels [default = %d]\n", nLevels );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\tname   : the node name\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandTopAnd( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    extern Abc_Ntk_t * Abc_NtkTopAnd( Abc_Ntk_t * pNtk );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" );
+        return 0;
+    }
+
+    if ( Abc_NtkLatchNum(pNtk) > 0 )
+    {
+        Abc_Print( -1, "Currently can only works for combinational circuits.\n" );
+        return 0;
+    }
+    if ( Abc_NtkPoNum(pNtk) != 1 )
+    {
+        Abc_Print( -1, "Currently expects a single-output miter.\n" );
+        return 0;
+    }
+    if ( Abc_ObjFaninC0(Abc_NtkPo(pNtk, 0)) )
+    {
+        Abc_Print( -1, "The PO driver is complemented. AND-decomposition is impossible.\n" );
+        return 0;
+    }
+    if ( !Abc_ObjIsNode(Abc_ObjChild0(Abc_NtkPo(pNtk, 0))) )
+    {
+        Abc_Print( -1, "The PO driver is not a node. AND-decomposition is impossible.\n" );
+        return 0;
+    }
+    pNtkRes = Abc_NtkTopAnd( pNtk );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "The command has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: topand [-h]\n" );
+    Abc_Print( -2, "\t         performs AND-decomposition of single-output combinational miter\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\tname   : the node name\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandTrim( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    Gia_Man_t * pGia, * pNew;
+    Aig_Man_t * pAig;
+    int c;
+    pNtk = Abc_FrameReadNtk(pAbc);
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Trimming works only for AIGs (run \"strash\").\n" );
+        return 1;
+    }
+    // convert to GIA
+    pAig = Abc_NtkToDar( pNtk, 0, 1 );
+    pGia = Gia_ManFromAigSimple( pAig );
+    Aig_ManStop( pAig );
+    // perform trimming
+    pNew = Gia_ManDupTrimmed( pGia, 1, 1, 0, -1 );
+    Gia_ManStop( pGia );
+    // convert back
+    pAig = Gia_ManToAigSimple( pNew );
+    Gia_ManStop( pNew );
+    pNtkRes = Abc_NtkFromAigPhase( pAig );
+    Aig_ManStop( pAig );
+    // duplicate the name and the spec
+    ABC_FREE( pNtkRes->pName );
+    ABC_FREE( pNtkRes->pSpec );
+    pNtkRes->pName = Extra_UtilStrsav(pNtk->pName);
+    pNtkRes->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: trim [-h]\n" );
+    Abc_Print( -2, "\t         removes POs fed by constants and PIs w/o fanout\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandShortNames( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    Abc_NtkShortNames( pNtk );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: short_names [-h]\n" );
+    Abc_Print( -2, "\t         replaces PI/PO/latch names by short char strings\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandExdcFree( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( pNtk->pExdc == NULL )
+    {
+        Abc_Print( -1, "The network has no EXDC.\n" );
+        return 1;
+    }
+
+    Abc_NtkDelete( pNtk->pExdc );
+    pNtk->pExdc = NULL;
+
+    // replace the current network
+    pNtkRes = Abc_NtkDup( pNtk );
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: exdc_free [-h]\n" );
+    Abc_Print( -2, "\t         frees the EXDC network of the current network\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandExdcGet( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( pNtk->pExdc == NULL )
+    {
+        Abc_Print( -1, "The network has no EXDC.\n" );
+        return 1;
+    }
+
+    // replace the current network
+    pNtkRes = Abc_NtkDup( pNtk->pExdc );
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: exdc_get [-h]\n" );
+    Abc_Print( -2, "\t         replaces the current network by the EXDC of the current network\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandExdcSet( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    FILE * pFile;
+    Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes;
+    char * FileName;
+    int c;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( argc != globalUtilOptind + 1 )
+    {
+        goto usage;
+    }
+
+    // get the input file name
+    FileName = argv[globalUtilOptind];
+    if ( (pFile = fopen( FileName, "r" )) == NULL )
+    {
+        Abc_Print( -1, "Cannot open input file \"%s\". ", FileName );
+        if ( (FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" )) )
+            Abc_Print( 1, "Did you mean \"%s\"?", FileName );
+        Abc_Print( 1, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+
+    // set the new network
+    pNtkNew = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 );
+    if ( pNtkNew == NULL )
+    {
+        Abc_Print( -1, "Reading network from file has failed.\n" );
+        return 1;
+    }
+
+    // replace the EXDC
+    if ( pNtk->pExdc )
+    {
+        Abc_NtkDelete( pNtk->pExdc );
+        pNtk->pExdc = NULL;
+    }
+    pNtkRes = Abc_NtkDup( pNtk );
+    pNtkRes->pExdc = pNtkNew;
+
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: exdc_set [-h] <file>\n" );
+    Abc_Print( -2, "\t         sets the network from file as EXDC for the current network\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : file with the new EXDC network\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCareSet( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    FILE * pFile;
+    Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes;
+    char * FileName;
+    int c;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( argc != globalUtilOptind + 1 )
+    {
+        goto usage;
+    }
+
+    // get the input file name
+    FileName = argv[globalUtilOptind];
+    if ( (pFile = fopen( FileName, "r" )) == NULL )
+    {
+        Abc_Print( -1, "Cannot open input file \"%s\". ", FileName );
+        if ( (FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" )) )
+            Abc_Print( 1, "Did you mean \"%s\"?", FileName );
+        Abc_Print( 1, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+
+    // set the new network
+    pNtkNew = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 );
+    if ( pNtkNew == NULL )
+    {
+        Abc_Print( -1, "Reading network from file has failed.\n" );
+        return 1;
+    }
+
+    // replace the EXDC
+    if ( pNtk->pExcare )
+    {
+        Abc_NtkDelete( (Abc_Ntk_t *)pNtk->pExcare );
+        pNtk->pExcare = NULL;
+    }
+    pNtkRes = Abc_NtkDup( pNtk );
+    pNtkRes->pExcare = pNtkNew;
+
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: care_set [-h] <file>\n" );
+    Abc_Print( -2, "\t         sets the network from file as a care for the current network\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : file with the new care network\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Cut_Params_t Params, * pParams = &Params;
+    Cut_Man_t * pCutMan;
+    Cut_Oracle_t * pCutOracle = NULL;
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fOracle;
+    extern Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams );
+    extern void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * pCutOracle );
+
+    // set defaults
+    fOracle = 0;
+    memset( pParams, 0, sizeof(Cut_Params_t) );
+    pParams->nVarsMax    = 5;     // the max cut size ("k" of the k-feasible cuts)
+    pParams->nKeepMax    = 1000;  // the max number of cuts kept at a node
+    pParams->fTruth      = 1;     // compute truth tables
+    pParams->fFilter     = 1;     // filter dominated cuts
+    pParams->fDrop       = 0;     // drop cuts on the fly
+    pParams->fDag        = 1;     // compute DAG cuts
+    pParams->fTree       = 0;     // compute tree cuts
+    pParams->fGlobal     = 0;     // compute global cuts
+    pParams->fLocal      = 0;     // compute local cuts
+    pParams->fFancy      = 0;     // compute something fancy
+    pParams->fRecordAig  = 1;     // compute something fancy
+    pParams->fMap        = 0;     // compute mapping delay
+    pParams->fAdjust     = 0;     // removes useless fanouts
+    pParams->fNpnSave    = 0;     // enables dumping truth tables
+    pParams->fVerbose    = 0;     // the verbosiness flag
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "KMtfdxyglzamjvosh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nVarsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nVarsMax < 0 )
+                goto usage;
+            break;
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nKeepMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nKeepMax < 0 )
+                goto usage;
+            break;
+        case 't':
+            pParams->fTruth ^= 1;
+            break;
+        case 'f':
+            pParams->fFilter ^= 1;
+            break;
+        case 'd':
+            pParams->fDrop ^= 1;
+            break;
+        case 'x':
+            pParams->fDag ^= 1;
+            break;
+        case 'y':
+            pParams->fTree ^= 1;
+            break;
+        case 'g':
+            pParams->fGlobal ^= 1;
+            break;
+        case 'l':
+            pParams->fLocal ^= 1;
+            break;
+        case 'z':
+            pParams->fFancy ^= 1;
+            break;
+        case 'a':
+            pParams->fRecordAig ^= 1;
+            break;
+        case 'm':
+            pParams->fMap ^= 1;
+            break;
+        case 'j':
+            pParams->fAdjust ^= 1;
+            break;
+        case 'v':
+            pParams->fVerbose ^= 1;
+            break;
+        case 'o':
+            fOracle ^= 1;
+            break;
+        case 's':
+            pParams->fNpnSave ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Cut computation is available only for AIGs (run \"strash\").\n" );
+        return 1;
+    }
+    if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX )
+    {
+        Abc_Print( -1, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX );
+        return 1;
+    }
+    if ( pParams->fDag && pParams->fTree )
+    {
+        Abc_Print( -1, "Cannot compute both DAG cuts and tree cuts at the same time.\n" );
+        return 1;
+    }
+
+    if ( pParams->fNpnSave )
+    {
+        pParams->nVarsMax = 6;
+        pParams->fTruth = 1;
+    }
+
+    if ( fOracle )
+        pParams->fRecord = 1;
+    pCutMan = Abc_NtkCuts( pNtk, pParams );
+    if ( fOracle )
+        pCutOracle = Cut_OracleStart( pCutMan );
+    Cut_ManStop( pCutMan );
+    if ( fOracle )
+    {
+        assert(pCutOracle);
+        Abc_NtkCutsOracle( pNtk, pCutOracle );
+        Cut_OracleStop( pCutOracle );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: cut [-K num] [-M num] [-tfdcovamjsvh]\n" );
+    Abc_Print( -2, "\t         computes k-feasible cuts for the AIG\n" );
+    Abc_Print( -2, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n",     CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax );
+    Abc_Print( -2, "\t-M num : max number of cuts stored at a node [default = %d]\n",        pParams->nKeepMax );
+    Abc_Print( -2, "\t-t     : toggle truth table computation [default = %s]\n",             pParams->fTruth?   "yes": "no" );
+    Abc_Print( -2, "\t-f     : toggle filtering of duplicated/dominated [default = %s]\n",   pParams->fFilter?  "yes": "no" );
+    Abc_Print( -2, "\t-d     : toggle dropping when fanouts are done [default = %s]\n",      pParams->fDrop?    "yes": "no" );
+    Abc_Print( -2, "\t-x     : toggle computing only DAG cuts [default = %s]\n",             pParams->fDag?     "yes": "no" );
+    Abc_Print( -2, "\t-y     : toggle computing only tree cuts [default = %s]\n",            pParams->fTree?    "yes": "no" );
+    Abc_Print( -2, "\t-g     : toggle computing only global cuts [default = %s]\n",          pParams->fGlobal?  "yes": "no" );
+    Abc_Print( -2, "\t-l     : toggle computing only local cuts [default = %s]\n",           pParams->fLocal?   "yes": "no" );
+    Abc_Print( -2, "\t-z     : toggle fancy computations [default = %s]\n",                  pParams->fFancy?   "yes": "no" );
+    Abc_Print( -2, "\t-a     : toggle recording cut functions [default = %s]\n",             pParams->fRecordAig?"yes": "no" );
+    Abc_Print( -2, "\t-m     : toggle delay-oriented FPGA mapping [default = %s]\n",         pParams->fMap?     "yes": "no" );
+    Abc_Print( -2, "\t-j     : toggle removing fanouts due to XOR/MUX [default = %s]\n",     pParams->fAdjust?  "yes": "no" );
+    Abc_Print( -2, "\t-s     : toggle creating library of 6-var functions [default = %s]\n", pParams->fNpnSave?  "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n",        pParams->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandScut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Cut_Params_t Params, * pParams = &Params;
+    Cut_Man_t * pCutMan;
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    extern Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams );
+
+    // set defaults
+    memset( pParams, 0, sizeof(Cut_Params_t) );
+    pParams->nVarsMax  = 5;     // the max cut size ("k" of the k-feasible cuts)
+    pParams->nKeepMax  = 1000;  // the max number of cuts kept at a node
+    pParams->fTruth    = 0;     // compute truth tables
+    pParams->fFilter   = 1;     // filter dominated cuts
+    pParams->fSeq      = 1;     // compute sequential cuts
+    pParams->fVerbose  = 0;     // the verbosiness flag
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "KMtvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nVarsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nVarsMax < 0 )
+                goto usage;
+            break;
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nKeepMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nKeepMax < 0 )
+                goto usage;
+            break;
+        case 't':
+            pParams->fTruth ^= 1;
+            break;
+        case 'v':
+            pParams->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+/*
+    if ( !Abc_NtkIsSeq(pNtk) )
+    {
+        Abc_Print( -1, "Sequential cuts can be computed for sequential AIGs (run \"seq\").\n" );
+        return 1;
+    }
+*/
+    if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX )
+    {
+        Abc_Print( -1, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX );
+        return 1;
+    }
+
+    pCutMan = Abc_NtkSeqCuts( pNtk, pParams );
+    Cut_ManStop( pCutMan );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: scut [-K num] [-M num] [-tvh]\n" );
+    Abc_Print( -2, "\t         computes k-feasible cuts for the sequential AIG\n" );
+    Abc_Print( -2, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n",   CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax );
+    Abc_Print( -2, "\t-M num : max number of cuts stored at a node [default = %d]\n",      pParams->nKeepMax );
+    Abc_Print( -2, "\t-t     : toggle truth table computation [default = %s]\n",           pParams->fTruth?   "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n",      pParams->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandEspresso( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fVerbose;
+    extern void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose );
+
+    if ( argc == 2 && !strcmp(argv[1], "-h") )
+    {
+        Abc_Print( -2, "The espresso command is currently disabled.\n" );
+        return 1;
+    }
+
+    Abc_Print( -1, "This command is currently disabled.\n" );
+    return 0;
+
+    // set defaults
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "SOP minimization is possible for logic networks (run \"renode\").\n" );
+        return 1;
+    }
+//    Abc_NtkEspresso( pNtk, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: espresso [-vh]\n" );
+    Abc_Print( -2, "\t         minimizes SOPs of the local functions using Espresso\n" );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+//    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int nVars;    // the number of variables
+    int nLutSize = -1; // the size of LUTs
+    int nLuts = -1;    // the number of LUTs
+    int fAdder;
+    int fSorter;
+    int fMesh;
+    int fMulti;
+    int fFpga;
+    int fOneHot;
+    int fRandom;
+    int fVerbose;
+    char * FileName;
+    char Command[1000];
+    extern void Abc_GenAdder( char * pFileName, int nVars );
+    extern void Abc_GenSorter( char * pFileName, int nVars );
+    extern void Abc_GenMesh( char * pFileName, int nVars );
+    extern void Abc_GenMulti( char * pFileName, int nVars );
+    extern void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars );
+    extern void Abc_GenOneHot( char * pFileName, int nVars );
+    extern void Abc_GenRandom( char * pFileName, int nPis );
+
+    // set defaults
+    nVars = 8;
+    fAdder = 0;
+    fSorter = 0;
+    fMesh = 0;
+    fMulti = 0;
+    fFpga = 0;
+    fOneHot = 0;
+    fRandom = 0;
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "NKLasemftrvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nVars = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nVars < 0 )
+                goto usage;
+            break;
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLutSize < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLuts = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLuts < 0 )
+                goto usage;
+            break;
+        case 'a':
+            fAdder ^= 1;
+            break;
+        case 's':
+            fSorter ^= 1;
+            break;
+        case 'e':
+            fMesh ^= 1;
+            break;
+        case 'm':
+            fMulti ^= 1;
+            break;
+        case 'f':
+            fFpga ^= 1;
+            break;
+        case 't':
+            fOneHot ^= 1;
+            break;
+        case 'r':
+            fRandom ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( argc != globalUtilOptind + 1 )
+    {
+        goto usage;
+    }
+    if ( nVars < 1 )
+    {
+        Abc_Print( -1, "The number of variables should be a positive integer.\n" );
+        return 0;
+    }
+    // get the input file name
+    FileName = argv[globalUtilOptind];
+    if ( fAdder )
+        Abc_GenAdder( FileName, nVars );
+    else if ( fSorter )
+        Abc_GenSorter( FileName, nVars );
+    else if ( fMesh )
+        Abc_GenMesh( FileName, nVars );
+    else if ( fMulti )
+        Abc_GenMulti( FileName, nVars );
+    else if ( fFpga )
+        Abc_GenFpga( FileName, nLutSize, nLuts, nVars );
+//        Abc_GenFpga( FileName, 2, 2, 3 );
+//        Abc_GenFpga( FileName, 3, 2, 5 );
+    else if ( fOneHot )
+        Abc_GenOneHot( FileName, nVars );
+    else if ( fRandom )
+        Abc_GenRandom( FileName, nVars );
+    else
+    {
+        Abc_Print( -1, "Type of circuit is not specified.\n" );
+        return 0;
+    }
+    // read the file just produced
+    sprintf(Command, "read %s", FileName );
+    Cmd_CommandExecute( pAbc, Command );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: gen [-NKL num] [-asemftrvh] <file>\n" );
+    Abc_Print( -2, "\t         generates simple circuits\n" );
+    Abc_Print( -2, "\t-N num : the number of variables [default = %d]\n", nVars );
+    Abc_Print( -2, "\t-K num : the LUT size (to be used with switch -f) [default = %d]\n", nLutSize );
+    Abc_Print( -2, "\t-L num : the LUT count (to be used with switch -f) [default = %d]\n", nLuts );
+    Abc_Print( -2, "\t-a     : generate ripple-carry adder [default = %s]\n", fAdder? "yes": "no" );
+    Abc_Print( -2, "\t-s     : generate a sorter [default = %s]\n", fSorter? "yes": "no" );
+    Abc_Print( -2, "\t-e     : generate a mesh [default = %s]\n", fMesh? "yes": "no" );
+    Abc_Print( -2, "\t-m     : generate a multiplier [default = %s]\n", fMulti? "yes": "no" );
+    Abc_Print( -2, "\t-f     : generate a LUT FPGA structure [default = %s]\n", fFpga? "yes": "no" );
+    Abc_Print( -2, "\t-t     : generate one-hotness conditions [default = %s]\n", fOneHot? "yes": "no" );
+    Abc_Print( -2, "\t-r     : generate random single-output function [default = %s]\n", fRandom? "yes": "no" );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : output file name\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandGenFsm( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Abc_GenFsm( char * pFileName, int nIns, int nOuts, int nStates, int nLines, int ProbI, int ProbO );
+    int c, nIns, nOuts, nStates, nLines, ProbI, ProbO, fVerbose;
+    char * FileName;
+    // set defaults
+    nIns     =   30;
+    nOuts    =    1;
+    nStates  =   20;
+    nLines   =  100;
+    ProbI    =   10;
+    ProbO    =  100;
+    fVerbose =    0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "IOSLPQvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nIns = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nIns < 0 )
+                goto usage;
+            break;
+        case 'O':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nOuts = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nOuts < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nStates = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nStates < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLines = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLines < 0 )
+                goto usage;
+            break;
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            ProbI = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( ProbI < 0 )
+                goto usage;
+            break;
+        case 'Q':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-Q\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            ProbO = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( ProbO < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( argc != globalUtilOptind + 1 )
+    {
+        goto usage;
+    }
+    if ( nIns < 1 || nStates < 1 || nLines < 1 || ProbI < 1 || ProbO < 1 )
+    {
+        Abc_Print( -1, "The number of inputs. states, lines, and probablity should be positive integers.\n" );
+        goto usage;
+    }
+    // get the input file name
+    FileName = argv[globalUtilOptind];
+    Abc_GenFsm( FileName, nIns, nOuts, nStates, nLines, ProbI, ProbO );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: genfsm [-IOSLPQ num] [-vh] <file>\n" );
+    Abc_Print( -2, "\t         generates random FSM in KISS format\n" );
+    Abc_Print( -2, "\t-I num : the number of input variables [default = %d]\n", nIns );
+    Abc_Print( -2, "\t-O num : the number of output variables [default = %d]\n", nOuts );
+    Abc_Print( -2, "\t-S num : the number of state variables [default = %d]\n", nStates );
+    Abc_Print( -2, "\t-L num : the number of lines (product terms) [default = %d]\n", nLines );
+    Abc_Print( -2, "\t-P num : percentage propability of a variable present in the input cube [default = %d]\n", ProbI );
+    Abc_Print( -2, "\t-Q num : percentage propability of a variable present in the output cube [default = %d]\n", ProbO );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : output file name\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCover( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int fVerbose;
+    int fUseSop;
+    int fUseEsop;
+    int fUseInvs;
+    int nFaninMax;
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set defaults
+    fUseSop   =  1;
+    fUseEsop  =  0;
+    fVerbose  =  0;
+    fUseInvs  =  1;
+    nFaninMax =  8;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Nsxivh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFaninMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFaninMax < 0 )
+                goto usage;
+            break;
+        case 's':
+            fUseSop ^= 1;
+            break;
+        case 'x':
+            fUseEsop ^= 1;
+            break;
+        case 'i':
+            fUseInvs ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Only works for strashed networks.\n" );
+        return 1;
+    }
+
+    // run the command
+    pNtkRes = Abc_NtkSopEsopCover( pNtk, nFaninMax, fUseEsop, fUseSop, fUseInvs, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: cover [-N num] [-sxvh]\n" );
+    Abc_Print( -2, "\t         decomposition into a network of SOP/ESOP PLAs\n" );
+    Abc_Print( -2, "\t-N num : maximum number of inputs [default = %d]\n", nFaninMax );
+    Abc_Print( -2, "\t-s     : toggle the use of SOPs [default = %s]\n", fUseSop? "yes": "no" );
+    Abc_Print( -2, "\t-x     : toggle the use of ESOPs [default = %s]\n", fUseEsop? "yes": "no" );
+//    Abc_Print( -2, "\t-i     : toggle the use of interters [default = %s]\n", fUseInvs? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandInter( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtk1, * pNtk2, * pNtkRes = NULL;
+    char ** pArgvNew;
+    int nArgcNew;
+    int c, fDelete1, fDelete2;
+    int fRelation;
+    int fVerbose;
+    extern Abc_Ntk_t * Abc_NtkInter( Abc_Ntk_t * pNtkOn, Abc_Ntk_t * pNtkOff, int fRelation, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fRelation = 0;
+    fVerbose  = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'r':
+            fRelation ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+        return 1;
+    if ( nArgcNew == 0 )
+    {
+        Abc_Obj_t * pObj;
+        int i;
+        Abc_Print( -1, "Deriving new circuit structure for the current network.\n" );
+        Abc_NtkForEachPo( pNtk2, pObj, i )
+            Abc_ObjXorFaninC( pObj, 0 );
+    }
+    if ( fRelation && Abc_NtkCoNum(pNtk1) != 1 )
+    {
+        Abc_Print( -1, "Computation of interplants as a relation only works for single-output functions.\n" );
+        Abc_Print( -1, "Use command \"cone\" to extract one output cone from the multi-output network.\n" );
+    }
+    else
+        pNtkRes = Abc_NtkInter( pNtk1, pNtk2, fRelation, fVerbose );
+    if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+    if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: inter [-rvh] <onset.blif> <offset.blif>\n" );
+    Abc_Print( -2, "\t         derives interpolant of two networks representing onset and offset;\n" );
+    Abc_Print( -2, "\t-r     : toggle computing interpolant as a relation [default = %s]\n", fRelation? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t         \n" );
+    Abc_Print( -2, "\t         Comments:\n" );
+    Abc_Print( -2, "\t         \n" );
+    Abc_Print( -2, "\t         The networks given on the command line should have the same CIs/COs.\n" );
+    Abc_Print( -2, "\t         If only one network is given on the command line, this network\n" );
+    Abc_Print( -2, "\t         is assumed to be the offset, while the current network is the onset.\n" );
+    Abc_Print( -2, "\t         If no network is given on the command line, the current network is\n" );
+    Abc_Print( -2, "\t         assumed to be the onset and its complement is taken to be the offset.\n" );
+    Abc_Print( -2, "\t         The resulting interpolant is stored as the current network.\n" );
+    Abc_Print( -2, "\t         To verify that the interpolant agrees with the onset and the offset,\n" );
+    Abc_Print( -2, "\t         save it in file \"inter.blif\" and run the following:\n" );
+    Abc_Print( -2, "\t         (a) \"miter -i <onset.blif> <inter.blif>; iprove\"\n" );
+    Abc_Print( -2, "\t         (b) \"miter -i <inter.blif> <offset_inv.blif>; iprove\"\n" );
+    Abc_Print( -2, "\t         where <offset_inv.blif> is the network derived by complementing the\n" );
+    Abc_Print( -2, "\t         outputs of <offset.blif>: \"r <offset.blif>; st -i; w <offset_inv.blif>\"\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDouble( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int nFrames;
+    int fVerbose;
+    extern Abc_Ntk_t * Abc_NtkDouble( Abc_Ntk_t * pNtk );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nFrames    = 50;
+    fVerbose   =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsSopLogic(pNtk) )
+    {
+        Abc_Print( -1, "Only works for logic SOP networks.\n" );
+        return 1;
+    }
+
+    pNtkRes = Abc_NtkDouble( pNtk );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: double [-vh]\n" );
+    Abc_Print( -2, "\t         puts together two parallel copies of the current network\n" );
+//    Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandBb2Wb( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Abc_NtkConvertBb2Wb( char * pFileNameIn, char * pFileNameOut, int fSeq, int fVerbose );
+    int c;
+    int fSeq;
+    int fVerbose;
+    // set defaults
+    fSeq = 0;
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 's':
+            fSeq ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 2 )
+    {
+        Abc_Print( -1, "Expecting two files names on the command line.\n" );
+        goto usage;
+    }
+    Abc_NtkConvertBb2Wb( argv[globalUtilOptind], argv[globalUtilOptind+1], fSeq, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: bb2wb [-svh] <file_in> <file_out>\n" );
+    Abc_Print( -2, "\t             replaces black boxes by white boxes with AND functions\n" );
+    Abc_Print( -2, "\t             (file names should have standard extensions, e.g. \"blif\")\n" );
+    Abc_Print( -2, "\t-s         : toggle using sequential white boxes [default = %s]\n", fSeq? "yes": "no" );
+    Abc_Print( -2, "\t-v         : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h         : print the command usage\n");
+    Abc_Print( -2, "\t<file_in>  : input file with design containing black boxes\n");
+    Abc_Print( -2, "\t<file_out> : output file with design containing white boxes\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandOutdec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Abc_Ntk_t * Abc_NtkDarOutdec( Abc_Ntk_t * pNtk, int nLits, int fVerbose );
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Abc_Ntk_t * pNtkRes;
+    int c, nLits = 1;
+    int fVerbose = 0;
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Lvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLits = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLits < 1 || nLits > 2 )
+            {
+                Abc_Print( 1,"Currently, command \"outdec\" works for 1-lit and 2-lit primes only.\n" );
+                goto usage;
+            }
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Only works for strashed networks.\n" );
+        return 1;
+    }
+    pNtkRes = Abc_NtkDarOutdec( pNtk, nLits, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: outdec [-Lvh]\n" );
+    Abc_Print( -2, "\t         performs prime decomposition of the first output\n" );
+    Abc_Print( -2, "\t-L num : the number of literals in the primes [default = %d]\n", nLits );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandNodeDup( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Abc_Ntk_t * Abc_NtkNodeDup( Abc_Ntk_t * pNtk, int nLimit, int fVerbose );
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Abc_Ntk_t * pNtkRes;
+    int c, nLimit = 30;
+    int fVerbose = 0;
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Nvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Only works for logic networks.\n" );
+        return 1;
+    }
+    if ( nLimit < 2 )
+    {
+        Abc_Print( -1, "The fanout limit should be more than 1.\n" );
+        return 1;
+    }
+    pNtkRes = Abc_NtkNodeDup( pNtk, nLimit, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: nodedup [-Nvh]\n" );
+    Abc_Print( -2, "\t         duplicates internal nodes with high fanout\n" );
+    Abc_Print( -2, "\t-N num : the number of fanouts to start duplication [default = %d]\n", nLimit );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandTestColor( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Abc_ColorTest();
+    Abc_ColorTest();
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int nCutMax      =  1;
+    int nLeafMax     =  4;
+    int nDivMax      =  2;
+    int nDecMax      = 20;
+    int nNumOnes     =  4;
+    int fNewAlgo     =  0;
+    int fNewOrder    =  0;
+    int fVerbose     =  0;
+    int fVeryVerbose =  0;
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "CKDNMaovwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nCutMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nCutMax < 0 )
+                goto usage;
+            break;
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLeafMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLeafMax < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nDivMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nDivMax < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nDecMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nDecMax < 0 )
+                goto usage;
+            break;
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nNumOnes = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nNumOnes < 0 )
+                goto usage;
+            break;
+        case 'a':
+            fNewAlgo ^= 1;
+            break;
+        case 'o':
+            fNewOrder ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+/*
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for logic networks.\n" );
+        return 1;
+    }
+*/
+/*
+    if ( Abc_NtkLatchNum(pNtk) == 0 )
+    {
+        Abc_Print( -1, "Only works for sequential networks.\n" );
+        return 1;
+    }
+*/
+
+/*
+    if ( pNtk )
+    {
+        extern Abc_Ntk_t * Au_ManPerformTest( Abc_Ntk_t * p, int nCutMax, int nLeafMax, int nDivMax, int nDecMax, int fVerbose, int fVeryVerbose );
+        Abc_Ntk_t * pNtkRes = Au_ManPerformTest( pNtk, nCutMax, nLeafMax, nDivMax, nDecMax, fVerbose, fVeryVerbose );
+        if ( pNtkRes == NULL )
+        {
+            Abc_Print( -1, "Command has failed.\n" );
+            return 1;
+        }
+        Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    }
+*/
+/*
+    if ( pNtk )
+    {
+        Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 );
+        Saig_ManBmcTerSimTestPo( pAig );
+        Aig_ManStop( pAig );
+    }
+*/
+/*
+    if ( !Abc_NtkIsTopo(pNtk) )
+    {
+        Abc_Print( -1, "Current network is not in a topological order.\n" );
+        return 1;
+    }
+*/
+//    if ( pNtk )
+//        Abc_NtkMakeLegit( pNtk ); 
+    {
+//        extern void Ifd_ManDsdTest();
+//        Ifd_ManDsdTest();
+    }
+/*
+    {
+        extern void Abc_EnumerateCubeStates();
+        extern void Abc_EnumerateCubeStatesZdd();
+        if ( fNewAlgo )
+            Abc_EnumerateCubeStatesZdd();
+        else
+            Abc_EnumerateCubeStates();
+        return 0;
+    }
+*/
+    {
+//        extern void Abc_EnumerateFuncs( int nDecMax, int nDivMax, int fVerbose );
+//        Abc_EnumerateFuncs( nDecMax, nDivMax, fVerbose );
+    }
+/*
+    if ( fNewAlgo )
+    {
+        extern void Abc_SuppTest( int nOnes, int nVars, int fUseSimple, int fCheck, int fVerbose );
+        Abc_SuppTest( nNumOnes, nDecMax, fNewOrder, 0, fVerbose );
+    }
+    else
+    {
+        extern void Bmc_EcoMiterTest();
+        Bmc_EcoMiterTest();
+    }
+*/
+
+    {
+//        extern void Nf_ManPrepareLibraryTest();
+//        Nf_ManPrepareLibraryTest();
+//        return 0;
+    }
+
+    if ( pNtk )
+    {
+        extern Abc_Ntk_t * Abc_NtkBarBufsOnOffTest( Abc_Ntk_t * pNtk );
+        Abc_Ntk_t * pNtkRes = Abc_NtkBarBufsOnOffTest( pNtk );
+//        extern Abc_Ntk_t * Abc_NtkPcmTest( Abc_Ntk_t * pNtk, int fNewAlgo, int fVerbose );
+//        extern Abc_Ntk_t * Abc_NtkPcmTestAig( Abc_Ntk_t * pNtk, int fVerbose );
+//        Abc_Ntk_t * pNtkRes;
+//        if ( Abc_NtkIsLogic(pNtk) )
+//            pNtkRes = Abc_NtkPcmTest( pNtk, fNewAlgo, fVerbose );
+//        else
+//            pNtkRes = Abc_NtkPcmTestAig( pNtk, fVerbose );
+        if ( pNtkRes == NULL )
+        {
+            Abc_Print( -1, "Command has failed.\n" );
+            return 1;
+        }
+        Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    }
+    return 0;
+usage:
+    Abc_Print( -2, "usage: test [-CKDNM] [-aovwh] <file_name>\n" );
+    Abc_Print( -2, "\t         testbench for new procedures\n" );
+    Abc_Print( -2, "\t-C num : the max number of cuts [default = %d]\n", nCutMax );
+    Abc_Print( -2, "\t-K num : the max number of leaves [default = %d]\n", nLeafMax );
+    Abc_Print( -2, "\t-D num : the max number of divisors [default = %d]\n", nDivMax );
+    Abc_Print( -2, "\t-N num : the max number of node inputs [default = %d]\n", nDecMax );
+    Abc_Print( -2, "\t-M num : the max number of ones in the vector [default = %d]\n", nNumOnes );
+    Abc_Print( -2, "\t-a     : toggle using new algorithm [default = %s]\n", fNewAlgo? "yes": "no" );
+    Abc_Print( -2, "\t-o     : toggle using new ordering [default = %s]\n", fNewOrder? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle printing very verbose information [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandQuaVar( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c, iVar, fUniv, fVerbose, RetValue;
+    extern int Abc_NtkQuantify( Abc_Ntk_t * pNtk, int fUniv, int iVar, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    iVar = 0;
+    fUniv = 0;
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Iuvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iVar = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iVar < 0 )
+                goto usage;
+            break;
+        case 'u':
+            fUniv ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkGetChoiceNum( pNtk ) )
+    {
+        Abc_Print( -1, "This command cannot be applied to an AIG with choice nodes.\n" );
+        return 1;
+    }
+
+    // get the strashed network
+    pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 );
+    RetValue = Abc_NtkQuantify( pNtkRes, fUniv, iVar, fVerbose );
+    // clean temporary storage for the cofactors
+    Abc_NtkCleanData( pNtkRes );
+    Abc_AigCleanup( (Abc_Aig_t *)pNtkRes->pManFunc );
+    // check the result
+    if ( !RetValue )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: qvar [-I num] [-uvh]\n" );
+    Abc_Print( -2, "\t         quantifies one variable using the AIG\n" );
+    Abc_Print( -2, "\t-I num : the zero-based index of a variable to quantify [default = %d]\n", iVar );
+    Abc_Print( -2, "\t-u     : toggle universal quantification [default = %s]\n", fUniv? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandQuaRel( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c, iVar, fInputs, fVerbose;
+    extern Abc_Ntk_t * Abc_NtkTransRel( Abc_Ntk_t * pNtk, int fInputs, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    iVar = 0;
+    fInputs = 1;
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Iqvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iVar = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iVar < 0 )
+                goto usage;
+            break;
+        case 'q':
+            fInputs ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkGetChoiceNum( pNtk ) )
+    {
+        Abc_Print( -1, "This command cannot be applied to an AIG with choice nodes.\n" );
+        return 1;
+    }
+    if ( Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for sequential circuits.\n" );
+        return 1;
+    }
+
+    // get the strashed network
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 );
+        pNtkRes = Abc_NtkTransRel( pNtk, fInputs, fVerbose );
+        Abc_NtkDelete( pNtk );
+    }
+    else
+        pNtkRes = Abc_NtkTransRel( pNtk, fInputs, fVerbose );
+    // check if the result is available
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: qrel [-qvh]\n" );
+    Abc_Print( -2, "\t         computes transition relation of the sequential network\n" );
+//    Abc_Print( -2, "\t-I num : the zero-based index of a variable to quantify [default = %d]\n", iVar );
+    Abc_Print( -2, "\t-q     : perform quantification of inputs [default = %s]\n", fInputs? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandQuaReach( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c, nIters, fVerbose;
+    extern Abc_Ntk_t * Abc_NtkReachability( Abc_Ntk_t * pNtk, int nIters, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nIters   = 256;
+    fVerbose =   0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nIters < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkGetChoiceNum( pNtk ) )
+    {
+        Abc_Print( -1, "This command cannot be applied to an AIG with choice nodes.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for combinational transition relations.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for strashed networks.\n" );
+        return 1;
+    }
+    if ( Abc_NtkPoNum(pNtk) > 1 )
+    {
+        Abc_Print( -1, "The transition relation should have one output.\n" );
+        return 1;
+    }
+    if ( Abc_NtkPiNum(pNtk) % 2 != 0 )
+    {
+        Abc_Print( -1, "The transition relation should have an even number of inputs.\n" );
+        return 1;
+    }
+
+    pNtkRes = Abc_NtkReachability( pNtk, nIters, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: qreach [-I num] [-vh]\n" );
+    Abc_Print( -2, "\t         computes unreachable states using AIG-based quantification\n" );
+    Abc_Print( -2, "\t         assumes that the current network is a transition relation\n" );
+    Abc_Print( -2, "\t         assumes that the initial state is composed of all zeros\n" );
+    Abc_Print( -2, "\t-I num : the number of image computations to perform [default = %d]\n", nIters );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSenseInput( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Vec_Int_t * vResult;
+    int c, nConfLim, fVerbose;
+
+    extern Vec_Int_t * Abc_NtkSensitivity( Abc_Ntk_t * pNtk, int nConfLim, int fVerbose );
+    // set defaults
+    nConfLim   = 1000;
+    fVerbose   =    1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Cvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfLim = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfLim < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkGetChoiceNum( pNtk ) )
+    {
+        Abc_Print( -1, "This command cannot be applied to an AIG with choice nodes.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for combinational transition relations.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for strashed networks.\n" );
+        return 1;
+    }
+    if ( Abc_NtkPoNum(pNtk) < 2 )
+    {
+        Abc_Print( -1, "The network should have at least two outputs.\n" );
+        return 1;
+    }
+
+    vResult = Abc_NtkSensitivity( pNtk, nConfLim, fVerbose );
+    Vec_IntFree( vResult );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: senseinput [-C num] [-vh]\n" );
+    Abc_Print( -2, "\t         computes sensitivity of POs to PIs under constraint\n" );
+    Abc_Print( -2, "\t         constraint should be represented as the last PO\n" );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", nConfLim );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandIStrash( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp;
+    int c;
+    extern Abc_Ntk_t * Abc_NtkIvyStrash( Abc_Ntk_t * pNtk );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        pNtkTemp = Abc_NtkStrash( pNtk, 0, 1, 0 );
+        pNtkRes = Abc_NtkIvyStrash( pNtkTemp );
+        Abc_NtkDelete( pNtkTemp );
+    }
+    else
+        pNtkRes = Abc_NtkIvyStrash( pNtk );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: istrash [-h]\n" );
+    Abc_Print( -2, "\t         perform sequential structural hashing\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandICut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c, nInputs;
+    extern void Abc_NtkIvyCuts( Abc_Ntk_t * pNtk, int nInputs );
+
+    // set defaults
+    nInputs = 5;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Kh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nInputs = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nInputs < 0 )
+                goto usage;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for strashed networks.\n" );
+        return 1;
+    }
+
+    Abc_NtkIvyCuts( pNtk, nInputs );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: icut [-K num] [-h]\n" );
+    Abc_Print( -2, "\t         computes sequential cuts of the given size\n" );
+    Abc_Print( -2, "\t-K num : the number of cut inputs (2 <= num <= 6) [default = %d]\n", nInputs );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandIRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c, fUpdateLevel, fUseZeroCost, fVerbose;
+    extern Abc_Ntk_t * Abc_NtkIvyRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeroCost, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fUpdateLevel = 1;
+    fUseZeroCost = 0;
+    fVerbose     = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'l':
+            fUpdateLevel ^= 1;
+            break;
+        case 'z':
+            fUseZeroCost ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for strashed networks.\n" );
+        return 1;
+    }
+
+    pNtkRes = Abc_NtkIvyRewrite( pNtk, fUpdateLevel, fUseZeroCost, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: irw [-lzvh]\n" );
+    Abc_Print( -2, "\t         perform combinational AIG rewriting\n" );
+    Abc_Print( -2, "\t-l     : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+    Abc_Print( -2, "\t-z     : toggle using zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    Dar_RwrPar_t Pars, * pPars = &Pars;
+    int c;
+
+    extern Abc_Ntk_t * Abc_NtkDRewrite( Abc_Ntk_t * pNtk, Dar_RwrPar_t * pPars );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Dar_ManDefaultRwrParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "CNflzrvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nCutsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nCutsMax < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nSubgMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nSubgMax < 0 )
+                goto usage;
+            break;
+        case 'f':
+            pPars->fFanout ^= 1;
+            break;
+        case 'l':
+            pPars->fUpdateLevel ^= 1;
+            break;
+        case 'z':
+            pPars->fUseZeros ^= 1;
+            break;
+        case 'r':
+            pPars->fRecycle ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for strashed networks.\n" );
+        return 1;
+    }
+    pNtkRes = Abc_NtkDRewrite( pNtk, pPars );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: drw [-C num] [-N num] [-lfzrvwh]\n" );
+    Abc_Print( -2, "\t         performs combinational AIG rewriting\n" );
+    Abc_Print( -2, "\t-C num : the max number of cuts at a node [default = %d]\n", pPars->nCutsMax );
+    Abc_Print( -2, "\t-N num : the max number of subgraphs tried [default = %d]\n", pPars->nSubgMax );
+    Abc_Print( -2, "\t-l     : toggle preserving the number of levels [default = %s]\n", pPars->fUpdateLevel? "yes": "no" );
+    Abc_Print( -2, "\t-f     : toggle representing fanouts [default = %s]\n", pPars->fFanout? "yes": "no" );
+    Abc_Print( -2, "\t-z     : toggle using zero-cost replacements [default = %s]\n", pPars->fUseZeros? "yes": "no" );
+    Abc_Print( -2, "\t-r     : toggle using cut recycling [default = %s]\n", pPars->fRecycle? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle very verbose printout [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    Dar_RefPar_t Pars, * pPars = &Pars;
+    int c;
+
+    extern Abc_Ntk_t * Abc_NtkDRefactor( Abc_Ntk_t * pNtk, Dar_RefPar_t * pPars );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Dar_ManDefaultRefParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "MKCelzvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nMffcMin = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nMffcMin < 0 )
+                goto usage;
+            break;
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nLeafMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLeafMax < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nCutsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nCutsMax < 0 )
+                goto usage;
+            break;
+        case 'e':
+            pPars->fExtend ^= 1;
+            break;
+        case 'l':
+            pPars->fUpdateLevel ^= 1;
+            break;
+        case 'z':
+            pPars->fUseZeros ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for strashed networks.\n" );
+        return 1;
+    }
+    if ( pPars->nLeafMax < 4 || pPars->nLeafMax > 15 )
+    {
+        Abc_Print( -1, "This command only works for cut sizes 4 <= K <= 15.\n" );
+        return 1;
+    }
+    pNtkRes = Abc_NtkDRefactor( pNtk, pPars );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: drf [-M num] [-K num] [-C num] [-elzvwh]\n" );
+    Abc_Print( -2, "\t         performs combinational AIG refactoring\n" );
+    Abc_Print( -2, "\t-M num : the min MFFC size to attempt refactoring [default = %d]\n", pPars->nMffcMin );
+    Abc_Print( -2, "\t-K num : the max number of cuts leaves [default = %d]\n", pPars->nLeafMax );
+    Abc_Print( -2, "\t-C num : the max number of cuts to try at a node [default = %d]\n", pPars->nCutsMax );
+    Abc_Print( -2, "\t-e     : toggle extending tbe cut below MFFC [default = %s]\n", pPars->fExtend? "yes": "no" );
+    Abc_Print( -2, "\t-l     : toggle preserving the number of levels [default = %s]\n", pPars->fUpdateLevel? "yes": "no" );
+    Abc_Print( -2, "\t-z     : toggle using zero-cost replacements [default = %s]\n", pPars->fUseZeros? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle very verbose printout [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDc2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int fBalance, fVerbose, fUpdateLevel, fFanout, fPower, c;
+
+    extern Abc_Ntk_t * Abc_NtkDC2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fBalance     = 0;
+    fVerbose     = 0;
+    fUpdateLevel = 0;
+    fFanout      = 1;
+    fPower       = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "blfpvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'b':
+            fBalance ^= 1;
+            break;
+        case 'l':
+            fUpdateLevel ^= 1;
+            break;
+        case 'f':
+            fFanout ^= 1;
+            break;
+        case 'p':
+            fPower ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for strashed networks.\n" );
+        return 1;
+    }
+    pNtkRes = Abc_NtkDC2( pNtk, fBalance, fUpdateLevel, fFanout, fPower, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dc2 [-blfpvh]\n" );
+    Abc_Print( -2, "\t         performs combinational AIG optimization\n" );
+    Abc_Print( -2, "\t-b     : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" );
+    Abc_Print( -2, "\t-l     : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" );
+    Abc_Print( -2, "\t-f     : toggle representing fanouts [default = %s]\n", fFanout? "yes": "no" );
+    Abc_Print( -2, "\t-p     : toggle power-aware rewriting [default = %s]\n", fPower? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDChoice( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int fBalance, fVerbose, fUpdateLevel, fConstruct, c;
+    int nConfMax, nLevelMax;
+
+    extern Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fBalance     = 1;
+    fUpdateLevel = 1;
+    fConstruct   = 0;
+    nConfMax     = 1000;
+    nLevelMax    = 0;
+    fVerbose     = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "CLblcvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfMax < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLevelMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLevelMax < 0 )
+                goto usage;
+            break;
+        case 'b':
+            fBalance ^= 1;
+            break;
+        case 'l':
+            fUpdateLevel ^= 1;
+            break;
+        case 'c':
+            fConstruct ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for strashed networks.\n" );
+        return 1;
+    }
+    pNtkRes = Abc_NtkDChoice( pNtk, fBalance, fUpdateLevel, fConstruct, nConfMax, nLevelMax, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dchoice [-C num] [-L num] [-blcvh]\n" );
+    Abc_Print( -2, "\t         performs partitioned choicing using new AIG package\n" );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", nConfMax );
+    Abc_Print( -2, "\t-L num : the max level of nodes to consider (0 = not used) [default = %d]\n", nLevelMax );
+    Abc_Print( -2, "\t-b     : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" );
+    Abc_Print( -2, "\t-l     : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" );
+    Abc_Print( -2, "\t-c     : toggle constructive computation of choices [default = %s]\n", fConstruct? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDch( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Dch_Pars_t Pars, * pPars = &Pars;
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    extern Abc_Ntk_t * Abc_NtkDch( Abc_Ntk_t * pNtk, Dch_Pars_t * pPars );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Dch_ManSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptgcfrvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nWords < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nSatVarMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nSatVarMax < 0 )
+                goto usage;
+            break;
+        case 's':
+            pPars->fSynthesis ^= 1;
+            break;
+        case 'p':
+            pPars->fPower ^= 1;
+            break;
+        case 't':
+            pPars->fSimulateTfo ^= 1;
+            break;
+        case 'g':
+            pPars->fUseGia ^= 1;
+            break;
+        case 'c':
+            pPars->fUseCSat ^= 1;
+            break;
+        case 'f':
+            pPars->fLightSynth ^= 1;
+            break;
+        case 'r':
+            pPars->fSkipRedSupp ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for strashed networks.\n" );
+        return 1;
+    }
+    pNtkRes = Abc_NtkDch( pNtk, pPars );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dch [-WCS num] [-sptgcfrvh]\n" );
+    Abc_Print( -2, "\t         computes structural choices using a new approach\n" );
+    Abc_Print( -2, "\t-W num : the max number of simulation words [default = %d]\n", pPars->nWords );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit );
+    Abc_Print( -2, "\t-S num : the max number of SAT variables [default = %d]\n", pPars->nSatVarMax );
+    Abc_Print( -2, "\t-s     : toggle synthesizing three snapshots [default = %s]\n", pPars->fSynthesis? "yes": "no" );
+    Abc_Print( -2, "\t-p     : toggle power-aware rewriting [default = %s]\n", pPars->fPower? "yes": "no" );
+    Abc_Print( -2, "\t-t     : toggle simulation of the TFO classes [default = %s]\n", pPars->fSimulateTfo? "yes": "no" );
+    Abc_Print( -2, "\t-g     : toggle using GIA to prove equivalences [default = %s]\n", pPars->fUseGia? "yes": "no" );
+    Abc_Print( -2, "\t-c     : toggle using circuit-based SAT vs. MiniSat [default = %s]\n", pPars->fUseCSat? "yes": "no" );
+    Abc_Print( -2, "\t-f     : toggle using faster logic synthesis [default = %s]\n", pPars->fLightSynth? "yes": "no" );
+    Abc_Print( -2, "\t-r     : toggle skipping choices with redundant support [default = %s]\n", pPars->fSkipRedSupp? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDrwsat( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int fBalance, fVerbose, c;
+
+    extern Abc_Ntk_t * Abc_NtkDrwsat( Abc_Ntk_t * pNtk, int fBalance, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fBalance = 0;
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "bvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'b':
+            fBalance ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for strashed networks.\n" );
+        return 1;
+    }
+    pNtkRes = Abc_NtkDrwsat( pNtk, fBalance, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: drwsat [-bvh]\n" );
+    Abc_Print( -2, "\t         performs combinational AIG optimization for SAT\n" );
+    Abc_Print( -2, "\t-b     : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandIRewriteSeq( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c, fUpdateLevel, fUseZeroCost, fVerbose;
+    extern Abc_Ntk_t * Abc_NtkIvyRewriteSeq( Abc_Ntk_t * pNtk, int fUseZeroCost, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fUpdateLevel = 0;
+    fUseZeroCost = 0;
+    fVerbose     = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'l':
+            fUpdateLevel ^= 1;
+            break;
+        case 'z':
+            fUseZeroCost ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for strashed networks.\n" );
+        return 1;
+    }
+
+    pNtkRes = Abc_NtkIvyRewriteSeq( pNtk, fUseZeroCost, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: irws [-zvh]\n" );
+    Abc_Print( -2, "\t         perform sequential AIG rewriting\n" );
+//    Abc_Print( -2, "\t-l     : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+    Abc_Print( -2, "\t-z     : toggle using zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandIResyn( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c, fUpdateLevel, fVerbose;
+    extern Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fUpdateLevel = 1;
+    fVerbose     = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'l':
+            fUpdateLevel ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for strashed networks.\n" );
+        return 1;
+    }
+
+    pNtkRes = Abc_NtkIvyResyn( pNtk, fUpdateLevel, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: iresyn [-lvh]\n" );
+    Abc_Print( -2, "\t         performs combinational resynthesis\n" );
+    Abc_Print( -2, "\t-l     : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandISat( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c, fUpdateLevel, fVerbose;
+    int nConfLimit;
+
+    extern Abc_Ntk_t * Abc_NtkIvySat( Abc_Ntk_t * pNtk, int nConfLimit, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nConfLimit   = 100000;
+    fUpdateLevel = 1;
+    fVerbose     = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Clzvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfLimit < 0 )
+                goto usage;
+            break;
+        case 'l':
+            fUpdateLevel ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for strashed networks.\n" );
+        return 1;
+    }
+
+    pNtkRes = Abc_NtkIvySat( pNtk, nConfLimit, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: isat [-C num] [-vh]\n" );
+    Abc_Print( -2, "\t         tries to prove the miter constant 0\n" );
+    Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n",    nConfLimit );
+//    Abc_Print( -2, "\t-l     : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandIFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c, fProve, fVerbose, fDoSparse;
+    int nConfLimit;
+    int nPartSize;
+    int nLevelMax;
+
+    extern Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose );
+    extern Abc_Ntk_t * Abc_NtkDarFraigPart( Abc_Ntk_t * pNtk, int nPartSize, int nConfLimit, int nLevelMax, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nPartSize    = 0;
+    nLevelMax    = 0;
+    nConfLimit   = 100;
+    fDoSparse    = 0;
+    fProve       = 0;
+    fVerbose     = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "PCLspvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nPartSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nPartSize < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfLimit < 0 )
+                goto usage;
+            break;
+         case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLevelMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLevelMax < 0 )
+                goto usage;
+            break;
+        case 's':
+            fDoSparse ^= 1;
+            break;
+        case 'p':
+            fProve ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for strashed networks.\n" );
+        return 1;
+    }
+
+    if ( nPartSize > 0 )
+        pNtkRes = Abc_NtkDarFraigPart( pNtk, nPartSize, nConfLimit, nLevelMax, fVerbose );
+    else
+        pNtkRes = Abc_NtkIvyFraig( pNtk, nConfLimit, fDoSparse, fProve, 0, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: ifraig [-P num] [-C num] [-L num] [-spvh]\n" );
+    Abc_Print( -2, "\t         performs fraiging using a new method\n" );
+    Abc_Print( -2, "\t-P num : partition size (0 = partitioning is not used) [default = %d]\n", nPartSize );
+    Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+    Abc_Print( -2, "\t-L num : limit on node level to fraig (0 = fraig all nodes) [default = %d]\n", nLevelMax );
+    Abc_Print( -2, "\t-s     : toggle considering sparse functions [default = %s]\n", fDoSparse? "yes": "no" );
+    Abc_Print( -2, "\t-p     : toggle proving the miter outputs [default = %s]\n", fProve? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c, nConfLimit, fDoSparse, fProve, fSpeculate, fChoicing, fVerbose;
+
+    extern Abc_Ntk_t * Abc_NtkDarFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fSpeculate, int fChoicing, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nConfLimit   = 100;
+    fDoSparse    = 1;
+    fProve       = 0;
+    fSpeculate   = 0;
+    fChoicing    = 0;
+    fVerbose     = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Csprcvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfLimit < 0 )
+                goto usage;
+            break;
+        case 's':
+            fDoSparse ^= 1;
+            break;
+        case 'p':
+            fProve ^= 1;
+            break;
+        case 'r':
+            fSpeculate ^= 1;
+            break;
+        case 'c':
+            fChoicing ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for strashed networks.\n" );
+        return 1;
+    }
+
+    pNtkRes = Abc_NtkDarFraig( pNtk, nConfLimit, fDoSparse, fProve, 0, fSpeculate, fChoicing, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dfraig [-C num] [-sprcvh]\n" );
+    Abc_Print( -2, "\t         performs fraiging using a new method\n" );
+    Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+    Abc_Print( -2, "\t-s     : toggle considering sparse functions [default = %s]\n", fDoSparse? "yes": "no" );
+    Abc_Print( -2, "\t-p     : toggle proving the miter outputs [default = %s]\n", fProve? "yes": "no" );
+    Abc_Print( -2, "\t-r     : toggle speculative reduction [default = %s]\n", fSpeculate? "yes": "no" );
+    Abc_Print( -2, "\t-c     : toggle accumulation of choices [default = %s]\n", fChoicing? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c, nCutsMax, nLeafMax, fVerbose;
+
+    extern Abc_Ntk_t * Abc_NtkCSweep( Abc_Ntk_t * pNtk, int nCutsMax, int nLeafMax, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nCutsMax  =  8;
+    nLeafMax  =  6;
+    fVerbose  =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "CKvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nCutsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nCutsMax < 0 )
+                goto usage;
+            break;
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLeafMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLeafMax < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( nCutsMax < 2 )
+    {
+        Abc_Print( -1, "The number of cuts cannot be less than 2.\n" );
+        return 1;
+    }
+
+    if ( nLeafMax < 3 || nLeafMax > 16 )
+    {
+        Abc_Print( -1, "The number of leaves is infeasible.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for strashed networks.\n" );
+        return 1;
+    }
+
+    pNtkRes = Abc_NtkCSweep( pNtk, nCutsMax, nLeafMax, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: csweep [-C num] [-K num] [-vh]\n" );
+    Abc_Print( -2, "\t         performs cut sweeping using a new method\n" );
+    Abc_Print( -2, "\t-C num : limit on the number of cuts (C >= 2) [default = %d]\n", nCutsMax );
+    Abc_Print( -2, "\t-K num : limit on the cut size (3 <= K <= 16) [default = %d]\n", nLeafMax );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandIProve( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Prove_Params_t Params, * pParams = &Params;
+    Abc_Ntk_t * pNtk, * pNtkTemp;
+    int c, RetValue, iOut = -1;
+    abctime clk;
+
+    extern int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Prove_ParamsSetDefault( pParams );
+    pParams->fUseRewriting = 1;
+    pParams->fVerbose      = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "NCFGLIrfbvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nItersMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nItersMax < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nMiteringLimitStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nMiteringLimitStart < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nFraigingLimitStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nFraigingLimitStart < 0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nFraigingLimitMulti = (float)atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nFraigingLimitMulti < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nMiteringLimitLast = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nMiteringLimitLast < 0 )
+                goto usage;
+            break;
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nTotalInspectLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nTotalInspectLimit < 0 )
+                goto usage;
+            break;
+        case 'r':
+            pParams->fUseRewriting ^= 1;
+            break;
+        case 'f':
+            pParams->fUseFraiging ^= 1;
+            break;
+        case 'b':
+            pParams->fUseBdds ^= 1;
+            break;
+        case 'v':
+            pParams->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( Abc_NtkLatchNum(pNtk) > 0 )
+    {
+        Abc_Print( -1, "The network has registers. Use \"dprove\".\n" );
+        return 1;
+    }
+
+    clk = Abc_Clock();
+
+    if ( Abc_NtkIsStrash(pNtk) )
+        pNtkTemp = Abc_NtkDup( pNtk );
+    else
+        pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+
+    RetValue = Abc_NtkIvyProve( &pNtkTemp, pParams );
+
+    // verify that the pattern is correct
+    if ( RetValue == 0 )
+    {
+        Abc_Obj_t * pObj;
+        int i;
+        int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtkTemp->pModel );
+        Abc_NtkForEachCo( pNtk, pObj, i )
+            if ( pSimInfo[i] == 1 )
+            {
+                iOut = i;
+                break;
+            }
+        if ( i == Abc_NtkCoNum(pNtk) )
+            Abc_Print( 1, "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" );
+        ABC_FREE( pSimInfo );
+    }
+    pAbc->Status = RetValue;
+    if ( RetValue == -1 )
+        Abc_Print( 1, "UNDECIDED      " );
+    else if ( RetValue == 0 )
+        Abc_Print( 1, "SATISFIABLE (output = %d) ", iOut );
+    else
+        Abc_Print( 1, "UNSATISFIABLE  " );
+    //Abc_Print( -1, "\n" );
+
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp );
+    // update counter example
+    if ( RetValue == 0 && Abc_NtkLatchNum(pNtkTemp) == 0 )
+    {
+        Abc_Cex_t * pCex = Abc_CexDeriveFromCombModel( pNtkTemp->pModel, Abc_NtkPiNum(pNtkTemp), 0, iOut );
+        Abc_FrameReplaceCex( pAbc, &pCex );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: iprove [-NCFGLI num] [-rfbvh]\n" );
+    Abc_Print( -2, "\t         performs CEC using a new method\n" );
+    Abc_Print( -2, "\t-N num : max number of iterations [default = %d]\n", pParams->nItersMax );
+    Abc_Print( -2, "\t-C num : max starting number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitStart );
+    Abc_Print( -2, "\t-F num : max starting number of conflicts in fraiging [default = %d]\n", pParams->nFraigingLimitStart );
+    Abc_Print( -2, "\t-G num : multiplicative coefficient for fraiging [default = %d]\n", (int)pParams->nFraigingLimitMulti );
+    Abc_Print( -2, "\t-L num : max last-gasp number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitLast );
+    Abc_Print( -2, "\t-I num : max number of clause inspections in all SAT calls [default = %d]\n", (int)pParams->nTotalInspectLimit );
+    Abc_Print( -2, "\t-r     : toggle the use of rewriting [default = %s]\n", pParams->fUseRewriting? "yes": "no" );
+    Abc_Print( -2, "\t-f     : toggle the use of FRAIGing [default = %s]\n", pParams->fUseFraiging? "yes": "no" );
+    Abc_Print( -2, "\t-b     : toggle the use of BDDs [default = %s]\n", pParams->fUseBdds? "yes": "no" );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+int Abc_CommandHaig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    FILE * stdout, * pErr;
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int nIters;
+    int nSteps;
+    int fRetimingOnly;
+    int fAddBugs;
+    int fUseCnf;
+    int fVerbose;
+
+    extern Abc_Ntk_t * Abc_NtkDarHaigRecord( Abc_Ntk_t * pNtk, int nIters, int nSteps, int fRetimingOnly, int fAddBugs, int fUseCnf, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+
+
+    // set defaults
+    nIters        = 3;
+    nSteps        = 3000;
+    fRetimingOnly = 0;
+    fAddBugs      = 0;
+    fUseCnf       = 0;
+    fVerbose      = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ISrbcvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nIters < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nSteps = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nSteps < 0 )
+                goto usage;
+            break;
+        case 'r':
+            fRetimingOnly ^= 1;
+            break;
+        case 'b':
+            fAddBugs ^= 1;
+            break;
+        case 'c':
+            fUseCnf ^= 1;
+            break;
+        case 'v':
+            fUseCnf ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for strashed networks.\n" );
+        return 1;
+    }
+
+    pNtkRes = Abc_NtkDarHaigRecord( pNtk, nIters, nSteps, fRetimingOnly, fAddBugs, fUseCnf, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: haig [-IS num] [-rbcvh]\n" );
+    Abc_Print( -2, "\t         run a few rounds of comb+seq synthesis to test HAIG recording\n" );
+    Abc_Print( -2, "\t         the current network is set to be the result of synthesis performed\n" );
+    Abc_Print( -2, "\t         (this network can be verified using command \"dsec\")\n" );
+    Abc_Print( -2, "\t         HAIG is written out into the file \"haig.blif\"\n" );
+    Abc_Print( -2, "\t         (this HAIG can be proved using \"r haig.blif; st; dprove -abc -F 16\")\n" );
+    Abc_Print( -2, "\t-I num : the number of rounds of comb+seq synthesis [default = %d]\n", nIters );
+    Abc_Print( -2, "\t-S num : the number of forward retiming moves performed [default = %d]\n", nSteps );
+    Abc_Print( -2, "\t-r     : toggle the use of retiming only [default = %s]\n", fRetimingOnly? "yes": "no" );
+    Abc_Print( -2, "\t-b     : toggle bug insertion [default = %s]\n", fAddBugs? "yes": "no" );
+    Abc_Print( -2, "\t-c     : enable CNF-based proof (no speculative reduction) [default = %s]\n", fUseCnf? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+*/
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandQbf( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int nPars;
+    int nIters;
+    int fDumpCnf;
+    int fVerbose;
+
+    extern void Abc_NtkQbf( Abc_Ntk_t * pNtk, int nPars, int nIters, int fDumpCnf, int fVerbose );
+    // set defaults
+    nPars    =  -1;
+    nIters   = 500;
+    fDumpCnf =   0;
+    fVerbose =   1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "PIdvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nPars = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nPars < 0 )
+                goto usage;
+            break;
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nIters < 0 )
+                goto usage;
+            break;
+        case 'd':
+            fDumpCnf ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "Works only for combinational networks.\n" );
+        return 1;
+    }
+    if ( Abc_NtkPoNum(pNtk) != 1 )
+    {
+        Abc_Print( -1, "The miter should have one primary output.\n" );
+        return 1;
+    }
+    if ( !(nPars > 0 && nPars < Abc_NtkPiNum(pNtk)) )
+    {
+        Abc_Print( -1, "The number of paramter variables is invalid (should be > 0 and < PI num).\n" );
+        return 1;
+    }
+    if ( Abc_NtkIsStrash(pNtk) )
+        Abc_NtkQbf( pNtk, nPars, nIters, fDumpCnf, fVerbose );
+    else
+    {
+        pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 );
+        Abc_NtkQbf( pNtk, nPars, nIters, fDumpCnf, fVerbose );
+        Abc_NtkDelete( pNtk );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: qbf [-PI num] [-dvh]\n" );
+    Abc_Print( -2, "\t         solves QBF problem EpVxM(p,x)\n" );
+    Abc_Print( -2, "\t-P num : number of parameters p (should be the first PIs) [default = %d]\n", nPars );
+    Abc_Print( -2, "\t-I num : quit after the given iteration even if unsolved [default = %d]\n", nIters );
+    Abc_Print( -2, "\t-d     : toggle dumping QDIMACS file instead of solving [default = %s]\n", fDumpCnf? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandNpnLoad( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Npn_ManLoad( char * pFileName );
+    char * pFileName;
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    pFileName = argv[globalUtilOptind];
+    Npn_ManLoad( pFileName );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: npnload <filename>\n" );
+    Abc_Print( -2, "\t         loads previously saved 6-input function library from file\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandNpnSave( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Npn_ManSave( char * pFileName );
+    char * pFileName;
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    pFileName = argv[globalUtilOptind];
+    Npn_ManSave( pFileName );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: npnsave <filename>\n" );
+    Abc_Print( -2, "\t         saves current 6-input function library into file\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSendAig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+//    const int BRIDGE_NETLIST = 106;
+//    const int BRIDGE_ABS_NETLIST = 107;
+
+    int c, fAndSpace = 1, fAbsNetlist = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'a':
+            fAndSpace ^= 1;
+            break;
+        case 'b':
+            fAbsNetlist ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( !Abc_FrameIsBridgeMode() )
+    {
+        Abc_Print( -1, "The bridge mode is not available.\n" );
+        return 1;
+    }
+    if ( fAndSpace )
+    {
+        if ( pAbc->pGia == NULL )
+        {
+            Abc_Print( -1, "There is no AIG in the &-space.\n" );
+            return 1;
+        }
+        Gia_ManToBridgeAbsNetlist( stdout, pAbc->pGia, fAbsNetlist ? BRIDGE_ABS_NETLIST : BRIDGE_NETLIST );
+    }
+    else
+    {
+        Aig_Man_t * pAig;
+        Gia_Man_t * pGia;
+        if ( pAbc->pNtkCur == NULL )
+        {
+            Abc_Print( -1, "There is no network in the main-space.\n" );
+            return 1;
+        }
+        if ( !Abc_NtkIsStrash(pAbc->pNtkCur) )
+        {
+            Abc_Print( -1, "The main-space network is not an AIG.\n" );
+            return 1;
+        }
+        pAig = Abc_NtkToDar( pAbc->pNtkCur, 0, 1 );
+        pGia = Gia_ManFromAig( pAig );
+        Aig_ManStop( pAig );
+        Gia_ManToBridgeAbsNetlist( stdout, pGia, fAbsNetlist ? BRIDGE_ABS_NETLIST : BRIDGE_NETLIST  );
+        Gia_ManStop( pGia );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: send_aig -a\n" );
+    Abc_Print( -2, "\t         sends current AIG to the bridge\n" );
+    Abc_Print( -2, "\t-a     : toggle sending AIG from &-space [default = %s]\n", fAndSpace? "yes": "no" );
+    Abc_Print( -2, "\t-b     : toggle sending netlist tagged as \"abstraction\". [default = %s]\n", fAbsNetlist? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSendStatus( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern int Gia_ManToBridgeResult( FILE * pFile, int Result, Abc_Cex_t * pCex, int iPoProved );
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( !Abc_FrameIsBridgeMode() )
+    {
+        Abc_Print( -1, "The bridge mode is not available.\n" );
+        return 1;
+    }
+    if ( pAbc->Status == 0 && pAbc->pCex == NULL )
+    {
+        Abc_Print( -1, "Status is \"sat\", but current CEX is not available.\n" );
+        return 1;
+    }
+    Gia_ManToBridgeResult( stdout, pAbc->Status, pAbc->pCex, 0 );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: send_status\n" );
+    Abc_Print( -2, "\t         sends current status to the bridge\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char Buffer[100];
+    Fraig_Params_t Params, * pParams = &Params;
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int fAllNodes;
+    int fExdc;
+    int c;
+    int fPartition = 0;
+    extern void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fExdc     = 0;
+    fAllNodes = 0;
+    memset( pParams, 0, sizeof(Fraig_Params_t) );
+    pParams->nPatsRand  = 2048; // the number of words of random simulation info
+    pParams->nPatsDyna  = 2048; // the number of words of dynamic simulation info
+    pParams->nBTLimit   =  100; // the max number of backtracks to perform
+    pParams->fFuncRed   =    1; // performs only one level hashing
+    pParams->fFeedBack  =    1; // enables solver feedback
+    pParams->fDist1Pats =    1; // enables distance-1 patterns
+    pParams->fDoSparse  =    1; // performs equiv tests for sparse functions
+    pParams->fChoicing  =    0; // enables recording structural choices
+    pParams->fTryProve  =    0; // tries to solve the final miter
+    pParams->fVerbose   =    0; // the verbosiness flag
+    pParams->fVerboseP  =    0; // the verbosiness flag
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "RDCrscptvaeh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nPatsRand = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nPatsRand < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nPatsDyna = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nPatsDyna < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nBTLimit < 0 )
+                goto usage;
+            break;
+
+        case 'r':
+            pParams->fFuncRed ^= 1;
+            break;
+        case 's':
+            pParams->fDoSparse ^= 1;
+            break;
+        case 'c':
+            pParams->fChoicing ^= 1;
+            break;
+        case 'p':
+            pParams->fTryProve ^= 1;
+            break;
+        case 'v':
+            pParams->fVerbose ^= 1;
+            break;
+        case 't':
+            fPartition ^= 1;
+            break;
+        case 'a':
+            fAllNodes ^= 1;
+            break;
+        case 'e':
+            fExdc ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Can only fraig a logic network or an AIG.\n" );
+        return 1;
+    }
+
+    // report the proof
+    pParams->fVerboseP = pParams->fTryProve;
+
+    // get the new network
+    if ( fPartition )
+    {
+        pNtkRes = Abc_NtkDup( pNtk );
+        if ( Abc_NtkIsStrash(pNtk) )
+            Abc_NtkFraigPartitionedTime( pNtk, &Params );
+        else
+        {
+            pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes, 0 );
+            Abc_NtkFraigPartitionedTime( pNtk, &Params );
+            Abc_NtkDelete( pNtk );
+        }
+    }
+    else
+    {
+        if ( Abc_NtkIsStrash(pNtk) )
+            pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes, fExdc );
+        else
+        {
+            pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes, 0 );
+            pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes, fExdc );
+            Abc_NtkDelete( pNtk );
+        }
+    }
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Fraiging has failed.\n" );
+        return 1;
+    }
+
+    if ( pParams->fTryProve ) // report the result
+        Abc_NtkMiterReport( pNtkRes );
+
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    sprintf(Buffer, "%d", pParams->nBTLimit );
+    Abc_Print( -2, "usage: fraig [-R num] [-D num] [-C num] [-rscpvtah]\n" );
+    Abc_Print( -2, "\t         transforms a logic network into a functionally reduced AIG\n" );
+    Abc_Print( -2, "\t         (known bugs: takes an UNSAT miter and returns a SAT one)\n");
+    Abc_Print( -2, "\t         (there are newer fraiging commands, \"ifraig\" and \"dfraig\")\n" );
+    Abc_Print( -2, "\t-R num : number of random patterns (127 < num < 32769) [default = %d]\n",     pParams->nPatsRand );
+    Abc_Print( -2, "\t-D num : number of systematic patterns (127 < num < 32769) [default = %d]\n", pParams->nPatsDyna );
+    Abc_Print( -2, "\t-C num : number of backtracks for one SAT problem [default = %s]\n",    pParams->nBTLimit==-1? "infinity" : Buffer );
+    Abc_Print( -2, "\t-r     : toggle functional reduction [default = %s]\n",                 pParams->fFuncRed? "yes": "no" );
+    Abc_Print( -2, "\t-s     : toggle considering sparse functions [default = %s]\n",         pParams->fDoSparse? "yes": "no" );
+    Abc_Print( -2, "\t-c     : toggle accumulation of choices [default = %s]\n",              pParams->fChoicing? "yes": "no" );
+    Abc_Print( -2, "\t-p     : toggle proving the miter outputs [default = %s]\n",              pParams->fTryProve? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n",                       pParams->fVerbose?  "yes": "no" );
+    Abc_Print( -2, "\t-e     : toggle functional sweeping using EXDC [default = %s]\n",       fExdc? "yes": "no" );
+    Abc_Print( -2, "\t-a     : toggle between all nodes and DFS nodes [default = %s]\n",      fAllNodes? "all": "dfs" );
+    Abc_Print( -2, "\t-t     : toggle using partitioned representation [default = %s]\n",     fPartition? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandFraigTrust( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int fDuplicate;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fDuplicate = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'd':
+            fDuplicate ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    // get the new network
+    pNtkRes = Abc_NtkFraigTrust( pNtk );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Fraiging in the trust mode has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: fraig_trust [-h]\n" );
+    Abc_Print( -2, "\t        transforms the current network into an AIG assuming it is FRAIG with choices\n" );
+//    Abc_Print( -2, "\t-d    : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandFraigStore( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fDuplicate;
+
+    // set defaults
+    fDuplicate = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'd':
+            fDuplicate ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    // get the new network
+    if ( !Abc_NtkFraigStore( pNtk ) )
+    {
+        Abc_Print( -1, "Fraig storing has failed.\n" );
+        return 1;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: fraig_store [-h]\n" );
+    Abc_Print( -2, "\t        saves the current network in the AIG database\n" );
+//    Abc_Print( -2, "\t-d    : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandFraigRestore( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int fDuplicate;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fDuplicate = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'd':
+            fDuplicate ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    // get the new network
+    pNtkRes = Abc_NtkFraigRestore();
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Fraig restoring has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: fraig_restore [-h]\n" );
+    Abc_Print( -2, "\t        makes the current network by fraiging the AIG database\n" );
+//    Abc_Print( -2, "\t-d    : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandFraigClean( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+//    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fDuplicate;
+    // set defaults
+    fDuplicate = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'd':
+            fDuplicate ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    Abc_NtkFraigStoreClean();
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: fraig_clean [-h]\n" );
+    Abc_Print( -2, "\t        cleans the internal FRAIG storage\n" );
+//    Abc_Print( -2, "\t-d    : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandFraigSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fUseInv;
+    int fExdc;
+    int fVerbose;
+    int fVeryVerbose;
+    extern int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose );
+    // set defaults
+    fUseInv   = 1;
+    fExdc     = 0;
+    fVerbose  = 0;
+    fVeryVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ievwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'i':
+            fUseInv ^= 1;
+            break;
+        case 'e':
+            fExdc ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Cannot sweep AIGs (use \"fraig\").\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "Transform the current network into a logic network.\n" );
+        return 1;
+    }
+    // modify the current network
+    if ( !Abc_NtkFraigSweep( pNtk, fUseInv, fExdc, fVerbose, fVeryVerbose ) )
+    {
+        Abc_Print( -1, "Sweeping has failed.\n" );
+        return 1;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: fraig_sweep [-evwh]\n" );
+    Abc_Print( -2, "\t        performs technology-dependent sweep\n" );
+    Abc_Print( -2, "\t-e    : toggle functional sweeping using EXDC [default = %s]\n", fExdc? "yes": "no" );
+    Abc_Print( -2, "\t-v    : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w    : prints equivalence class information [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandFraigDress( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Abc_NtkDress( Abc_Ntk_t * pNtk, char * pFileName, int fVerbose );
+    extern void Abc_NtkDress2( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConflictLimit, int fVerbose );
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtk2;
+    char * pFileName;
+    int c;
+    int nConfs;
+    int fVerbose;
+    // set defaults
+    nConfs   = 1000;
+    fVerbose =    0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Cvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfs = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfs < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for logic networks.\n" );
+        return 1;
+    }
+    if ( argc != globalUtilOptind && argc != globalUtilOptind + 1 )
+        goto usage;
+    if ( argc == globalUtilOptind && Abc_NtkSpec(pNtk) == NULL )
+    {
+        Abc_Print( -1, "The current network has no spec.\n" );
+        return 1;
+    }
+    // get the input file name
+    pFileName = (argc == globalUtilOptind + 1) ? argv[globalUtilOptind] : Abc_NtkSpec(pNtk);
+    // modify the current network
+//    Abc_NtkDress( pNtk, pFileName, fVerbose );
+    pNtk2 = Io_Read( pFileName, Io_ReadFileType(pFileName), 1, 0 );
+    Abc_NtkDress2( pNtk, pNtk2, nConfs, fVerbose );
+    Abc_NtkDelete( pNtk2 );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dress [-C num] [-vh] <file>\n" );
+    Abc_Print( -2, "\t         transfers internal node names from file to the current network\n" );
+    Abc_Print( -2, "\t<file> : network with names (if not given, the current network spec is used)\n" );
+    Abc_Print( -2, "\t-C num : the maximum number of conflicts at each node [default = %d]\n", nConfs );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandRecStart3( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char * FileName, * pTemp;
+    char ** pArgvNew;
+    int c, nArgcNew;
+    FILE * pFile;
+    Gia_Man_t * pGia = NULL;
+    int nVars = 6;
+    int nCuts = 32;
+    int fFuncOnly = 0;
+    int fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "KCfvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nVars = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nVars < 1 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nCuts = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nCuts < 1 )
+                goto usage;
+            break;
+        case 'f':
+            fFuncOnly ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( !(nVars >= 3 && nVars <= 16) )
+    {
+        Abc_Print( -1, "The range of allowed values is 3 <= K <= 16.\n" );
+        return 0;
+    }
+    if ( Abc_NtkRecIsRunning3() )
+    {
+        Abc_Print( -1, "The AIG subgraph recording is already started.\n" );
+        return 0;
+    }
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( nArgcNew != 1 )
+        Abc_Print( 1, "File name is not given on the command line. Starting a new record.\n" );
+    else
+    {
+        // get the input file name
+        FileName = pArgvNew[0];
+        // fix the wrong symbol
+        for ( pTemp = FileName; *pTemp; pTemp++ )
+            if ( *pTemp == '>' )
+                *pTemp = '\\';
+        if ( (pFile = fopen( FileName, "r" )) == NULL )
+        {
+            Abc_Print( -1, "Cannot open input file \"%s\". ", FileName );
+            if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) )
+                Abc_Print( 1, "Did you mean \"%s\"?", FileName );
+            Abc_Print( 1, "\n" );
+            return 1;
+        }
+        fclose( pFile );
+        pGia = Gia_AigerRead( FileName, 1, 0 );
+        if ( pGia == NULL )
+        {
+            Abc_Print( -1, "Reading AIGER has failed.\n" );
+            return 0;
+        }
+    }
+    Abc_NtkRecStart3( pGia, nVars, nCuts, fFuncOnly, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: rec_start3 [-K num] [-C num] [-fvh] <file>\n" );
+    Abc_Print( -2, "\t         starts recording AIG subgraphs (should be called for\n" );
+    Abc_Print( -2, "\t         an empty network or after reading in a previous record)\n" );
+    Abc_Print( -2, "\t-K num : the largest number of inputs [default = %d]\n", nVars );
+    Abc_Print( -2, "\t-C num : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCuts );
+    Abc_Print( -2, "\t-f     : toggles recording functions without AIG subgraphs [default = %s]\n", fFuncOnly? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : AIGER file with the library\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandRecStop3( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( !Abc_NtkRecIsRunning3() )
+    {
+        Abc_Print( -1, "This command works only after calling \"rec_start3\".\n" );
+        return 0;
+    }
+    Abc_NtkRecStop3();
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: rec_stop3 [-h]\n" );
+    Abc_Print( -2, "\t        cleans the internal storage for AIG subgraphs\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandRecPs3( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c, fPrintLib = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ph" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'p':
+            fPrintLib ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( !Abc_NtkRecIsRunning3() )
+    {
+        Abc_Print( -1, "This command works for AIGs only after calling \"rec_start2\".\n" );
+        return 0;
+    }
+    Abc_NtkRecPs3(fPrintLib);
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: rec_ps3 [-h]\n" );
+    Abc_Print( -2, "\t        prints statistics about the recorded AIG subgraphs\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandRecAdd3( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fUseSOPB = 0;
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "gh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'g':
+            fUseSOPB = 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works for AIGs.\n" );
+        return 0;
+    }
+    if ( !Abc_NtkRecIsRunning3() )
+    {
+        Abc_Print( -1, "This command works for AIGs after calling \"rec_start2\".\n" );
+        return 0;
+    }
+    Abc_NtkRecAdd3( pNtk, fUseSOPB );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: rec_add3 [-h]\n" );
+    Abc_Print( -2, "\t        adds subgraphs from the current network to the set\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandRecDump3( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Abc_NtkRecDumpTt3( char * pFileName, int fBinary );
+    char * FileName;
+    char ** pArgvNew;
+    int nArgcNew;
+    Gia_Man_t * pGia;
+    int fAscii = 0;
+    int fBinary = 0;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "abh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'a':
+            fAscii ^= 1;
+            break;
+        case 'b':
+            fBinary ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( !Abc_NtkRecIsRunning3() )
+    {
+        Abc_Print( -1, "The AIG subgraph recording is not started.\n" );
+        return 1;
+    }
+
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( nArgcNew != 1 )
+    {
+        Abc_Print( -1, "File name is not given on the command line.\n" );
+        return 1;
+    }
+    // get the input file name
+    FileName = pArgvNew[0];
+    if ( fAscii )
+        Abc_NtkRecDumpTt3( FileName, 0 );
+    else if ( fBinary )
+        Abc_NtkRecDumpTt3( FileName, 1 );
+    else
+    {
+        pGia = Abc_NtkRecGetGia3();
+        if( pGia == NULL )
+        {
+            Abc_Print( 0, "Library AIG is not available.\n" );
+            return 1;
+        }
+        if( Gia_ManPoNum(pGia) == 0 )
+        {
+            Abc_Print( 0, "No structure in the library.\n" );
+            return 1;
+        }
+        Gia_AigerWrite( pGia, FileName, 0, 0 );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: rec_dump3 [-abh] <file>\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t-a     : toggles dumping TTs into an ASCII file [default = %s]\n", fAscii? "yes": "no" );
+    Abc_Print( -2, "\t-b     : toggles dumping TTs into a binary file [default = %s]\n", fBinary? "yes": "no" );
+    Abc_Print( -2, "\t<file> : AIGER file to write the library\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandRecMerge3( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c;
+    char * FileName, * pTemp;
+    char ** pArgvNew;
+    int nArgcNew;
+    FILE * pFile;
+    Gia_Man_t * pGia = NULL;
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( !Abc_NtkRecIsRunning3() )
+    {
+        Abc_Print( -1, "This command works for AIGs only after calling \"rec_start3\".\n" );
+        return 0;
+    }
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( nArgcNew != 1 )
+    {
+        Abc_Print( -1, "File name is not given on the command line.\n" );
+        return 1;
+    }
+    else
+    {
+        // get the input file name
+        FileName = pArgvNew[0];
+        // fix the wrong symbol
+        for ( pTemp = FileName; *pTemp; pTemp++ )
+            if ( *pTemp == '>' )
+                *pTemp = '\\';
+        if ( (pFile = fopen( FileName, "r" )) == NULL )
+        {
+            Abc_Print( -1, "Cannot open input file \"%s\". ", FileName );
+            if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) )
+                Abc_Print( 1, "Did you mean \"%s\"?", FileName );
+            Abc_Print( 1, "\n" );
+            return 1;
+        }
+        fclose( pFile );
+        pGia = Gia_AigerRead( FileName, 1, 0 );
+        if ( pGia == NULL )
+        {
+            Abc_Print( -1, "Reading AIGER has failed.\n" );
+            return 0;
+        }
+    }
+    Abc_NtkRecLibMerge3(pGia);
+    Gia_ManStop( pGia );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: rec_merge3 [-h] <file>\n" );
+    Abc_Print( -2, "\t         merge libraries\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : AIGER file with the library\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    char Buffer[100];
+    double DelayTarget;
+    double AreaMulti;
+    double DelayMulti;
+    float LogFan = 0;
+    float Slew = 0; // choose based on the library
+    float Gain = 250;
+    int nGatesMin = 4;
+    int fAreaOnly;
+    int fRecovery;
+    int fSweep;
+    int fSwitching;
+    int fVerbose;
+    int c;
+    extern Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, double AreaMulti, double DelayMulti, float LogFan, float Slew, float Gain, int nGatesMin, int fRecovery, int fSwitching, int fVerbose );
+    extern int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    DelayTarget =-1;
+    AreaMulti   = 0;
+    DelayMulti  = 0;
+    fAreaOnly   = 0;
+    fRecovery   = 1;
+    fSweep      = 0;
+    fSwitching  = 0;
+    fVerbose    = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "DABFSGMarspvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            DelayTarget = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( DelayTarget <= 0.0 )
+                goto usage;
+            break;
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            AreaMulti = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            break;
+        case 'B':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-B\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            DelayMulti = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            LogFan = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( LogFan < 0.0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            Slew = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Slew <= 0.0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            Gain = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Gain <= 0.0 )
+                goto usage;
+            break;
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nGatesMin = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nGatesMin < 0 ) 
+                goto usage;
+            break;
+        case 'a':
+            fAreaOnly ^= 1;
+            break;
+        case 'r':
+            fRecovery ^= 1;
+            break;
+        case 's':
+            fSweep ^= 1;
+            break;
+        case 'p':
+            fSwitching ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( fAreaOnly )
+        DelayTarget = ABC_INFINITY;
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+        if ( pNtk == NULL )
+        {
+            Abc_Print( -1, "Strashing before mapping has failed.\n" );
+            return 1;
+        }
+        pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
+        Abc_NtkDelete( pNtkRes );
+        if ( pNtk == NULL )
+        {
+            Abc_Print( -1, "Balancing before mapping has failed.\n" );
+            return 1;
+        }
+        Abc_Print( 0, "The network was strashed and balanced before mapping.\n" );
+        // get the new network
+        pNtkRes = Abc_NtkMap( pNtk, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fVerbose );
+        if ( pNtkRes == NULL )
+        {
+            Abc_NtkDelete( pNtk );
+            Abc_Print( -1, "Mapping has failed.\n" );
+            return 1;
+        }
+        Abc_NtkDelete( pNtk );
+    }
+    else
+    {
+        // get the new network
+        pNtkRes = Abc_NtkMap( pNtk, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fVerbose );
+        if ( pNtkRes == NULL )
+        {
+            Abc_Print( -1, "Mapping has failed.\n" );
+            return 1;
+        }
+    }
+
+    if ( fSweep )
+    {
+        Abc_NtkFraigSweep( pNtkRes, 0, 0, 0, 0 );
+        if ( Abc_NtkHasMapping(pNtkRes) )
+        {
+            pNtkRes = Abc_NtkDupDfs( pNtk = pNtkRes );
+            Abc_NtkDelete( pNtk );
+        }
+    }
+
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    if ( DelayTarget == -1 )
+        sprintf(Buffer, "not used" );
+    else
+        sprintf(Buffer, "%.3f", DelayTarget );
+    Abc_Print( -2, "usage: map [-DABFSG float] [-M num] [-arspvh]\n" );
+    Abc_Print( -2, "\t           performs standard cell mapping of the current network\n" );
+    Abc_Print( -2, "\t-D float : sets the global required times [default = %s]\n", Buffer );
+    Abc_Print( -2, "\t-A float : \"area multiplier\" to bias gate selection [default = %.2f]\n", AreaMulti );
+    Abc_Print( -2, "\t-B float : \"delay multiplier\" to bias gate selection [default = %.2f]\n", DelayMulti );
+    Abc_Print( -2, "\t-F float : the logarithmic fanout delay parameter [default = %.2f]\n", LogFan );
+    Abc_Print( -2, "\t-S float : the slew parameter used to generate the library [default = %.2f]\n", Slew );
+    Abc_Print( -2, "\t-G float : the gain parameter used to generate the library [default = %.2f]\n", Gain );
+    Abc_Print( -2, "\t-M num   : skip gate classes whose size is less than this [default = %d]\n", nGatesMin );
+    Abc_Print( -2, "\t-a       : toggles area-only mapping [default = %s]\n", fAreaOnly? "yes": "no" );
+    Abc_Print( -2, "\t-r       : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" );
+    Abc_Print( -2, "\t-s       : toggles sweep after mapping [default = %s]\n", fSweep? "yes": "no" );
+    Abc_Print( -2, "\t-p       : optimizes power by minimizing switching [default = %s]\n", fSwitching? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAmap( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Amap_Par_t Pars, * pPars = &Pars;
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int fSweep;
+    int c;
+    extern Abc_Ntk_t * Abc_NtkDarAmap( Abc_Ntk_t * pNtk, Amap_Par_t * pPars );
+    extern int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fSweep = 0;
+    Amap_ManSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FACEQmxisvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->nIterFlow = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nIterFlow < 0 )
+                goto usage;
+            break;
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->nIterArea = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nIterArea < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->nCutsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nCutsMax < 0 )
+                goto usage;
+            break;
+        case 'E':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-E\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->fEpsilon = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->fEpsilon < 0.0 || pPars->fEpsilon > 1.0 )
+                goto usage;
+            break;
+        case 'Q':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-Q\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->fADratio = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->fADratio < 0.0 )
+                goto usage;
+            break;
+        case 'm':
+            pPars->fUseMuxes ^= 1;
+            break;
+        case 'x':
+            pPars->fUseXors ^= 1;
+            break;
+        case 'i':
+            pPars->fFreeInvs ^= 1;
+            break;
+        case 's':
+            fSweep ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+        if ( pNtk == NULL )
+        {
+            Abc_Print( -1, "Strashing before mapping has failed.\n" );
+            return 1;
+        }
+        pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
+        Abc_NtkDelete( pNtkRes );
+        if ( pNtk == NULL )
+        {
+            Abc_Print( -1, "Balancing before mapping has failed.\n" );
+            return 1;
+        }
+        Abc_Print( 0, "The network was strashed and balanced before mapping.\n" );
+        // get the new network
+        pNtkRes = Abc_NtkDarAmap( pNtk, pPars );
+        if ( pNtkRes == NULL )
+        {
+            Abc_NtkDelete( pNtk );
+            Abc_Print( -1, "Mapping has failed.\n" );
+            return 1;
+        }
+        Abc_NtkDelete( pNtk );
+    }
+    else
+    {
+        // get the new network
+        pNtkRes = Abc_NtkDarAmap( pNtk, pPars );
+        if ( pNtkRes == NULL )
+        {
+            Abc_Print( -1, "Mapping has failed.\n" );
+            return 1;
+        }
+    }
+
+    if ( fSweep )
+    {
+        Abc_NtkFraigSweep( pNtkRes, 0, 0, 0, 0 );
+        if ( Abc_NtkHasMapping(pNtkRes) )
+        {
+            pNtkRes = Abc_NtkDupDfs( pNtk = pNtkRes );
+            Abc_NtkDelete( pNtk );
+        }
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: amap [-FAC <num>] [-EQ <float>] [-mxisvh]\n" );
+    Abc_Print( -2, "\t           performs standard cell mapping of the current network\n" );
+    Abc_Print( -2, "\t-F num   : the number of iterations of area flow [default = %d]\n", pPars->nIterFlow );
+    Abc_Print( -2, "\t-A num   : the number of iterations of exact area [default = %d]\n", pPars->nIterArea );
+    Abc_Print( -2, "\t-C num   : the maximum number of cuts at a node [default = %d]\n", pPars->nCutsMax );
+    Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->fEpsilon );
+    Abc_Print( -2, "\t-Q float : area/delay preference ratio [default = %.2f (area-only)] \n", pPars->fADratio );
+    Abc_Print( -2, "\t-m       : toggles using MUX matching [default = %s]\n", pPars->fUseMuxes? "yes": "no" );
+    Abc_Print( -2, "\t-x       : toggles using XOR matching [default = %s]\n", pPars->fUseXors? "yes": "no" );
+    Abc_Print( -2, "\t-i       : toggles assuming inverters are free [default = %s]\n", pPars->fFreeInvs? "yes": "no" );
+    Abc_Print( -2, "\t-s       : toggles sweep after mapping [default = %s]\n", fSweep? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandUnmap( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkHasMapping(pNtk) )
+    {
+        Abc_Print( -1, "Cannot unmap the network that is not mapped.\n" );
+        return 1;
+    }
+
+    // get the new network
+    if ( !Abc_NtkMapToSop( pNtk ) )
+    {
+        Abc_Print( -1, "Unmapping has failed.\n" );
+        return 1;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: unmap [-h]\n" );
+    Abc_Print( -2, "\t        replaces the library gates by the logic nodes represented using SOPs\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAttach( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsSopLogic(pNtk) )
+    {
+        Abc_Print( -1, "Can only attach gates if the nodes have SOP representations.\n" );
+        return 1;
+    }
+
+    // get the new network
+    if ( !Abc_NtkAttach( pNtk ) )
+    {
+        Abc_Print( -1, "Attaching gates has failed.\n" );
+        return 1;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: attach [-h]\n" );
+    Abc_Print( -2, "\t        replaces the SOP functions by the gates from the library\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSuperChoice( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    extern Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Superchoicing works only for the AIG representation (run \"strash\").\n" );
+        return 1;
+    }
+
+    // get the new network
+    pNtkRes = Abc_NtkSuperChoice( pNtk );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Superchoicing has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: superc [-h]\n" );
+    Abc_Print( -2, "\t      performs superchoicing\n" );
+    Abc_Print( -2, "\t      (accumulate: \"r file.blif; rsup; b; sc; f -ac; wb file_sc.blif\")\n" );
+    Abc_Print( -2, "\t      (map without supergate library: \"r file_sc.blif; ft; map\")\n" );
+    Abc_Print( -2, "\t-h  : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSuperChoiceLut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int nLutSize;
+    int nCutSizeMax;
+    int fVerbose;
+    extern int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fVerbose = 1;
+    nLutSize = 4;
+    nCutSizeMax = 10;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "KNh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLutSize < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nCutSizeMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nCutSizeMax < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Superchoicing works only for the AIG representation (run \"strash\").\n" );
+        return 1;
+    }
+
+    // convert the network into the SOP network
+    pNtkRes = Abc_NtkToLogic( pNtk );
+
+    // get the new network
+    if ( !Abc_NtkSuperChoiceLut( pNtkRes, nLutSize, nCutSizeMax, fVerbose ) )
+    {
+        Abc_NtkDelete( pNtkRes );
+        Abc_Print( -1, "Superchoicing has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: supercl [-K num] [-N num] [-vh]\n" );
+    Abc_Print( -2, "\t        performs superchoicing for K-LUTs\n" );
+    Abc_Print( -2, "\t        (accumulate: \"r file.blif; b; scl; f -ac; wb file_sc.blif\")\n" );
+    Abc_Print( -2, "\t        (FPGA map: \"r file_sc.blif; ft; read_lut lutlibK; fpga\")\n" );
+    Abc_Print( -2, "\t-K num : the number of LUT inputs [default = %d]\n", nLutSize );
+    Abc_Print( -2, "\t-N num : the max size of the cut [default = %d]\n", nCutSizeMax );
+    Abc_Print( -2, "\t-v     : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+#if 0 
+int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char Buffer[100];
+    char LutSize[100];
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int fRecovery;
+    int fSwitching;
+    int fLatchPaths;
+    int fVerbose;
+    int nLutSize;
+    float DelayTarget;
+
+    extern Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int fSwitching, int fLatchPaths, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fRecovery   = 1;
+    fSwitching  = 0;
+    fLatchPaths = 0;
+    fVerbose    = 0;
+    DelayTarget =-1;
+    nLutSize    =-1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "aplvhDK" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'a':
+            fRecovery ^= 1;
+            break;
+        case 'p':
+            fSwitching ^= 1;
+            break;
+        case 'l':
+            fLatchPaths ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            DelayTarget = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( DelayTarget <= 0.0 )
+                goto usage;
+            break;
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLutSize < 0 )
+                goto usage;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    // create the new LUT library
+    if ( nLutSize >= 3 && nLutSize <= 10 )
+        Fpga_SetSimpleLutLib( nLutSize );
+/*
+    else
+    {
+        Abc_Print( -1, "Cannot perform FPGA mapping with LUT size %d.\n", nLutSize );
+        return 1;
+    }
+*/
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        // strash and balance the network
+        pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+        if ( pNtk == NULL )
+        {
+            Abc_Print( -1, "Strashing before FPGA mapping has failed.\n" );
+            return 1;
+        }
+        pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
+        Abc_NtkDelete( pNtkRes );
+        if ( pNtk == NULL )
+        {
+            Abc_Print( -1, "Balancing before FPGA mapping has failed.\n" );
+            return 1;
+        }
+        Abc_Print( 1, "The network was strashed and balanced before FPGA mapping.\n" );
+        // get the new network
+        pNtkRes = Abc_NtkFpga( pNtk, DelayTarget, fRecovery, fSwitching, fLatchPaths, fVerbose );
+        if ( pNtkRes == NULL )
+        {
+            Abc_NtkDelete( pNtk );
+            Abc_Print( -1, "FPGA mapping has failed.\n" );
+            return 1;
+        }
+        Abc_NtkDelete( pNtk );
+    }
+    else
+    {
+        // get the new network
+        pNtkRes = Abc_NtkFpga( pNtk, DelayTarget, fRecovery, fSwitching, fLatchPaths, fVerbose );
+        if ( pNtkRes == NULL )
+        {
+            Abc_Print( -1, "FPGA mapping has failed.\n" );
+            return 1;
+        }
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    if ( DelayTarget == -1 )
+        sprintf(Buffer, "best possible" );
+    else
+        sprintf(Buffer, "%.2f", DelayTarget );
+    if ( nLutSize == -1 )
+        sprintf(LutSize, "library" );
+    else
+        sprintf(LutSize, "%d", nLutSize );
+    Abc_Print( -2, "usage: fpga [-D float] [-K num] [-aplvh]\n" );
+    Abc_Print( -2, "\t           performs FPGA mapping of the current network\n" );
+    Abc_Print( -2, "\t-a       : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" );
+    Abc_Print( -2, "\t-p       : optimizes power by minimizing switching activity [default = %s]\n", fSwitching? "yes": "no" );
+    Abc_Print( -2, "\t-l       : optimizes latch paths for delay, other paths for area [default = %s]\n", fLatchPaths? "yes": "no" );
+    Abc_Print( -2, "\t-D float : sets the required time for the mapping [default = %s]\n", Buffer );
+    Abc_Print( -2, "\t-K num   : the number of LUT inputs (2 < num < 11) [default = %s]%s\n", LutSize, (nLutSize == -1 ? " (type \"print_lut\")" : "") );
+    Abc_Print( -2, "\t-v       : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : prints the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandFpgaFast( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char Buffer[100];
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int fRecovery;
+    int fVerbose;
+    int nLutSize;
+    float DelayTarget;
+
+    extern Abc_Ntk_t * Abc_NtkFpgaFast( Abc_Ntk_t * pNtk, int nLutSize, int fRecovery, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fRecovery   = 1;
+    fVerbose    = 0;
+    DelayTarget =-1;
+    nLutSize    = 5;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "avhDK" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'a':
+            fRecovery ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            DelayTarget = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( DelayTarget <= 0.0 )
+                goto usage;
+            break;
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLutSize < 0 )
+                goto usage;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        // strash and balance the network
+        pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+        if ( pNtk == NULL )
+        {
+            Abc_Print( -1, "Strashing before FPGA mapping has failed.\n" );
+            return 1;
+        }
+        pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
+        Abc_NtkDelete( pNtkRes );
+        if ( pNtk == NULL )
+        {
+            Abc_Print( -1, "Balancing before FPGA mapping has failed.\n" );
+            return 1;
+        }
+        Abc_Print( 1, "The network was strashed and balanced before FPGA mapping.\n" );
+        // get the new network
+        pNtkRes = Abc_NtkFpgaFast( pNtk, nLutSize, fRecovery, fVerbose );
+        if ( pNtkRes == NULL )
+        {
+            Abc_NtkDelete( pNtk );
+            Abc_Print( -1, "FPGA mapping has failed.\n" );
+            return 1;
+        }
+        Abc_NtkDelete( pNtk );
+    }
+    else
+    {
+        // get the new network
+        pNtkRes = Abc_NtkFpgaFast( pNtk, nLutSize, fRecovery, fVerbose );
+        if ( pNtkRes == NULL )
+        {
+            Abc_Print( -1, "FPGA mapping has failed.\n" );
+            return 1;
+        }
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    if ( DelayTarget == -1 )
+        sprintf(Buffer, "not used" );
+    else
+        sprintf(Buffer, "%.2f", DelayTarget );
+    Abc_Print( -2, "usage: ffpga [-K num] [-avh]\n" );
+    Abc_Print( -2, "\t           performs fast FPGA mapping of the current network\n" );
+    Abc_Print( -2, "\t-a       : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" );
+//    Abc_Print( -2, "\t-D float : sets the required time for the mapping [default = %s]\n", Buffer );
+    Abc_Print( -2, "\t-K num   : the number of LUT inputs (2 < num < 32) [default = %d]\n", nLutSize );
+    Abc_Print( -2, "\t-v       : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : prints the command usage\n");
+    return 1;
+}
+#endif
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
+    char Buffer[100], LutSize[100];
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    If_Par_t Pars, * pPars = &Pars;
+    int c;
+    pNtk = Abc_FrameReadNtk(pAbc);
+    If_ManSetDefaultPars( pPars );
+    pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut();
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGNDEWSTqaflepmrsdbgxyojiktncvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLutSize < 0 )
+                goto usage;
+            // if the LUT size is specified, disable library
+            pPars->pLutLib = NULL;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nCutsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nCutsMax < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nFlowIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFlowIters < 0 )
+                goto usage;
+            break;
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nAreaIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nAreaIters < 0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by a positive integer no less than 3.\n" );
+                goto usage;
+            }
+            pPars->nGateSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nGateSize < 2 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer no less than 3.\n" );
+                goto usage;
+            }
+            pPars->nNonDecLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nNonDecLimit < 2 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->DelayTarget = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->DelayTarget <= 0.0 )
+                goto usage;
+            break;
+        case 'E':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-E\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->Epsilon = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->Epsilon < 0.0 || pPars->Epsilon > 1.0 )
+                goto usage;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->WireDelay = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->WireDelay < 0.0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by string.\n" );
+                goto usage;
+            }
+            pPars->pLutStruct = argv[globalUtilOptind];
+            globalUtilOptind++;
+            if ( strlen(pPars->pLutStruct) != 2 && strlen(pPars->pLutStruct) != 3 )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by a 2- or 3-char string (e.g. \"44\" or \"555\").\n" );
+                goto usage;
+            }
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by a positive integer 0,1,or 2.\n" );
+                goto usage;
+            }
+            pPars->nStructType = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nStructType < 0 || pPars->nStructType > 2 )
+                goto usage;
+            break;
+        case 'q':
+            pPars->fPreprocess ^= 1;
+            break;
+        case 'a':
+            pPars->fArea ^= 1;
+            break;
+        case 'r':
+            pPars->fExpRed ^= 1;
+            break;
+        case 'f':
+            pPars->fFancy ^= 1;
+            break;
+        case 'l':
+            pPars->fLatchPaths ^= 1;
+            break;
+        case 'e':
+            pPars->fEdge ^= 1;
+            break;
+        case 'p':
+            pPars->fPower ^= 1;
+            break;
+        case 'm':
+            pPars->fCutMin ^= 1;
+            break;
+        case 's':
+            pPars->fDelayOptLut ^= 1;
+            break;
+        case 'd':
+            pPars->fBidec ^= 1;
+            break;
+        case 'b':
+            pPars->fUseBat ^= 1;
+            break;
+        case 'g':
+            pPars->fDelayOpt ^= 1;
+            break;
+        case 'x':
+            pPars->fDsdBalance ^= 1;
+            break;
+        case 'y':
+            pPars->fUserRecLib ^= 1;
+            break;
+        case 'o':
+            pPars->fUseBuffs ^= 1;
+            break;
+        case 'j':
+            pPars->fEnableCheck07 ^= 1;
+            break;
+        case 'i':
+            pPars->fEnableCheck08 ^= 1;
+            break;
+        case 'k':
+            pPars->fEnableCheck10 ^= 1;
+            break;
+        case 't':
+            pPars->fDoAverage ^= 1;
+            break;
+        case 'n':
+            pPars->fUseDsd ^= 1;
+            break;
+        case 'c':
+            pPars->fUseTtPerm ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( pPars->nLutSize == -1 )
+    {
+        if ( pPars->pLutLib == NULL )
+        {
+            Abc_Print( -1, "The LUT library is not given.\n" );
+            return 1;
+        }
+        pPars->nLutSize = pPars->pLutLib->LutMax;
+    }
+
+    if ( pPars->nLutSize < 2 || pPars->nLutSize > IF_MAX_LUTSIZE )
+    {
+        Abc_Print( -1, "Incorrect LUT size (%d).\n", pPars->nLutSize );
+        return 1;
+    }
+
+    if ( pPars->nCutsMax < 1 || pPars->nCutsMax >= (1<<12) )
+    {
+        Abc_Print( -1, "Incorrect number of cuts.\n" );
+        return 1;
+    }
+
+    // enable truth table computation if choices are selected
+    if ( (c = Abc_NtkGetChoiceNum( pNtk )) )
+    {
+//        if ( !Abc_FrameReadFlag("silentmode") )
+//            Abc_Print( 0, "Performing LUT mapping with %d choices.\n", c );
+        pPars->fExpRed = 0;
+    }
+
+    if ( pPars->fUseBat )
+    {
+        if ( pPars->nLutSize < 4 || pPars->nLutSize > 6 )
+        {
+            Abc_Print( -1, "This feature only works for {4,5,6}-LUTs.\n" );
+            return 1;
+        }
+        pPars->fCutMin = 1;
+    }
+
+    if ( pPars->fEnableCheck07 + pPars->fEnableCheck08 + pPars->fEnableCheck10 + (pPars->pLutStruct != NULL) > 1 )
+    {
+        Abc_Print( -1, "Only one additional check can be performed at the same time.\n" );
+        return 1;
+    }
+    if ( pPars->fEnableCheck07 )
+    {
+        if ( pPars->nLutSize < 6 || pPars->nLutSize > 7 )
+        {
+            Abc_Print( -1, "This feature only works for {6,7}-LUTs.\n" );
+            return 1;
+        }
+        pPars->pFuncCell = If_CutPerformCheck07;
+        pPars->fCutMin = 1;
+    }
+    if ( pPars->fEnableCheck08 )
+    {
+        if ( pPars->nLutSize < 6 || pPars->nLutSize > 8 )
+        {
+            Abc_Print( -1, "This feature only works for {6,7,8}-LUTs.\n" );
+            return 1;
+        }
+        pPars->pFuncCell = If_CutPerformCheck08;
+        pPars->fCutMin = 1;
+    }
+    if ( pPars->fEnableCheck10 )
+    {
+        if ( pPars->nLutSize < 6 || pPars->nLutSize > 10 )
+        {
+            Abc_Print( -1, "This feature only works for {6,7,8,9,10}-LUTs.\n" );
+            return 1;
+        }
+        pPars->pFuncCell = If_CutPerformCheck10;
+        pPars->fCutMin = 1;
+    }
+    if ( pPars->pLutStruct )
+    {
+        if ( pPars->fDsdBalance )
+        {
+            Abc_Print( -1, "Incompatible options (-S and -x).\n" );
+            return 1;
+        }
+        if ( pPars->nLutSize < 6 || pPars->nLutSize > 16 )
+        {
+            Abc_Print( -1, "This feature only works for [6;16]-LUTs.\n" );
+            return 1;
+        }
+        pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheck16;
+        pPars->fCutMin = 1;
+    }
+
+    // enable truth table computation if cut minimization is selected
+    if ( pPars->fCutMin )
+    {
+        pPars->fTruth = 1;
+        pPars->fExpRed = 0;
+    }
+    // modify the subgraph recording
+    if ( pPars->fUserRecLib )
+    {
+        pPars->fTruth      =  1;
+        pPars->fCutMin     =  1;
+        pPars->fExpRed     =  0;
+        pPars->fUsePerm    =  1;
+        pPars->pLutLib     =  NULL;
+    }
+    // modify for delay optimization
+    if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut )
+    {
+        pPars->fTruth      =  1;
+        pPars->fCutMin     =  1;
+        pPars->fExpRed     =  0;
+        pPars->fUseDsd     =  pPars->fDsdBalance || pPars->fDelayOptLut;
+        pPars->pLutLib     =  NULL;
+    }
+    // modify for delay optimization
+    if ( pPars->nGateSize > 0 )
+    {
+        pPars->fTruth      =  1;
+        pPars->fCutMin     =  1;
+        pPars->fExpRed     =  0;
+        pPars->fUsePerm    =  1;
+        pPars->pLutLib     =  NULL;
+        pPars->nLutSize    =  pPars->nGateSize;
+    }
+
+    if ( pPars->fUseDsd || pPars->fUseTtPerm )
+    {
+        pPars->fTruth      =  1;
+        pPars->fCutMin     =  1;
+        pPars->fExpRed     =  0;
+    }
+
+    if ( pPars->fUseDsd )
+    {
+        int LutSize = (pPars->pLutStruct && pPars->pLutStruct[2] == 0)? pPars->pLutStruct[0] - '0' : 0;
+        If_DsdMan_t * p = (If_DsdMan_t *)Abc_FrameReadManDsd();
+        if ( pPars->pLutStruct && pPars->pLutStruct[2] != 0 )
+        {
+            printf( "DSD only works for LUT structures XY.\n" );
+            return 0;
+        }
+        if ( p && pPars->nLutSize > If_DsdManVarNum(p) )
+        {
+            printf( "DSD manager has incompatible number of variables.\n" );
+            return 0;
+        }
+        if ( p && LutSize != If_DsdManLutSize(p) && !pPars->fDsdBalance )
+        {
+            printf( "DSD manager has different LUT size.\n" );
+            return 0;
+        }
+        if ( p == NULL )
+            Abc_FrameSetManDsd( If_DsdManAlloc(pPars->nLutSize, LutSize) );
+    }
+
+    if ( pPars->fUserRecLib )
+    {
+        if ( !Abc_NtkRecIsRunning3() )
+        {
+            printf( "LMS manager is not running (use \"rec_start3\").\n" );
+            return 0;
+        }
+        if ( Abc_NtkRecInputNum3() != pPars->nLutSize )
+        {
+            printf( "The number of library inputs (%d) different from the K parameters (%d).\n", Abc_NtkRecInputNum3(), pPars->nLutSize );
+            return 0;
+        }
+    }
+ 
+    // complain if truth tables are requested but the cut size is too large
+    if ( pPars->fTruth && pPars->nLutSize > IF_MAX_FUNC_LUTSIZE )
+    {
+        Abc_Print( -1, "Truth tables cannot be computed for LUT larger than %d inputs.\n", IF_MAX_FUNC_LUTSIZE );
+        return 1;
+    }
+
+    // disable cut-expansion if edge-based heuristics are selected
+//    if ( pPars->fEdge )
+//        pPars->fExpRed = 0;
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        // strash and balance the network
+        pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+        if ( pNtk == NULL )
+        {
+            Abc_Print( -1, "Strashing before FPGA mapping has failed.\n" );
+            return 1;
+        }
+        pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
+        Abc_NtkDelete( pNtkRes );
+        if ( pNtk == NULL )
+        {
+            Abc_Print( -1, "Balancing before FPGA mapping has failed.\n" );
+            return 1;
+        }
+        if ( !Abc_FrameReadFlag("silentmode") )
+            Abc_Print( 1, "The network was strashed and balanced before FPGA mapping.\n" );
+        // get the new network
+        pNtkRes = Abc_NtkIf( pNtk, pPars );
+        if ( pNtkRes == NULL )
+        {
+            Abc_NtkDelete( pNtk );
+            Abc_Print( -1, "FPGA mapping has failed.\n" );
+            return 0;
+        }
+        Abc_NtkDelete( pNtk );
+    }
+    else
+    {
+        // get the new network
+        pNtkRes = Abc_NtkIf( pNtk, pPars );
+        if ( pNtkRes == NULL )
+        {
+            Abc_Print( -1, "FPGA mapping has failed.\n" );
+            return 0;
+        }
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    if ( pPars->DelayTarget == -1 )
+        sprintf(Buffer, "best possible" );
+    else
+        sprintf(Buffer, "%.2f", pPars->DelayTarget );
+    if ( pPars->nLutSize == -1 )
+        sprintf(LutSize, "library" );
+    else
+        sprintf(LutSize, "%d", pPars->nLutSize );
+    Abc_Print( -2, "usage: if [-KCFANGT num] [-DEW float] [-S str] [-qarlepmsdbgxyojiktncvh]\n" );
+    Abc_Print( -2, "\t           performs FPGA technology mapping of the network\n" );
+    Abc_Print( -2, "\t-K num   : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize );
+    Abc_Print( -2, "\t-C num   : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax );
+    Abc_Print( -2, "\t-F num   : the number of area flow recovery iterations (num >= 0) [default = %d]\n", pPars->nFlowIters );
+    Abc_Print( -2, "\t-A num   : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters );
+    Abc_Print( -2, "\t-N num   : the max size of non-decomposable nodes [default = unused]\n", pPars->nNonDecLimit );
+    Abc_Print( -2, "\t-G num   : the max AND/OR gate size for mapping (0 = unused) [default = %d]\n", pPars->nGateSize );
+    Abc_Print( -2, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer );
+    Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon );
+    Abc_Print( -2, "\t-W float : sets wire delay between adjects LUTs [default = %f]\n", pPars->WireDelay );
+    Abc_Print( -2, "\t-S str   : string representing the LUT structure [default = %s]\n", pPars->pLutStruct ? pPars->pLutStruct : "not used" );
+    Abc_Print( -2, "\t-T num   : the type of LUT structures [default = any]\n", pPars->nStructType );
+    Abc_Print( -2, "\t-q       : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" );
+    Abc_Print( -2, "\t-a       : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" );
+    Abc_Print( -2, "\t-r       : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" );
+    Abc_Print( -2, "\t-l       : optimizes latch paths for delay, other paths for area [default = %s]\n", pPars->fLatchPaths? "yes": "no" );
+    Abc_Print( -2, "\t-e       : uses edge-based cut selection heuristics [default = %s]\n", pPars->fEdge? "yes": "no" );
+    Abc_Print( -2, "\t-p       : uses power-aware cut selection heuristics [default = %s]\n", pPars->fPower? "yes": "no" );
+    Abc_Print( -2, "\t-m       : enables cut minimization by removing vacuous variables [default = %s]\n", pPars->fCutMin? "yes": "no" );
+    Abc_Print( -2, "\t-s       : toggles delay-oriented mapping used with -S <NN> [default = %s]\n", pPars->fDelayOptLut? "yes": "no" );
+    Abc_Print( -2, "\t-d       : toggles deriving local AIGs using bi-decomposition [default = %s]\n", pPars->fBidec? "yes": "no" );
+    Abc_Print( -2, "\t-b       : toggles the use of one special feature [default = %s]\n", pPars->fUseBat? "yes": "no" );
+    Abc_Print( -2, "\t-g       : toggles delay optimization by SOP balancing [default = %s]\n", pPars->fDelayOpt? "yes": "no" );
+    Abc_Print( -2, "\t-x       : toggles delay optimization by DSD balancing [default = %s]\n", pPars->fDsdBalance? "yes": "no" );
+    Abc_Print( -2, "\t-y       : toggles delay optimization with recorded library [default = %s]\n", pPars->fUserRecLib? "yes": "no" );
+    Abc_Print( -2, "\t-o       : toggles using buffers to decouple combinational outputs [default = %s]\n", pPars->fUseBuffs? "yes": "no" );
+    Abc_Print( -2, "\t-j       : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck07? "yes": "no" );
+    Abc_Print( -2, "\t-i       : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck08? "yes": "no" );
+    Abc_Print( -2, "\t-k       : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck10? "yes": "no" );
+    Abc_Print( -2, "\t-t       : toggles optimizing average rather than maximum level [default = %s]\n", pPars->fDoAverage? "yes": "no" );
+    Abc_Print( -2, "\t-n       : toggles computing DSDs of the cut functions [default = %s]\n", pPars->fUseDsd? "yes": "no" );
+    Abc_Print( -2, "\t-c       : toggles computing truth tables in a new way [default = %s]\n", pPars->fUseTtPerm? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : prints the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandIfif( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Abc_NtkPerformIfif( Abc_Ntk_t * pNtk, Ifif_Par_t * pPars );
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Ifif_Par_t Pars, * pPars = &Pars;
+    int c, fError;
+
+    pPars->nLutSize     =  -1;    // the LUT size
+    pPars->pLutLib      = (If_LibLut_t *)Abc_FrameReadLibLut();       // the LUT library
+    pPars->DelayWire    = (float)0.5;    // wire delay
+    pPars->nDegree      =   0;    // structure degree
+    pPars->fCascade     =   0;    // cascade
+    pPars->fVerbose     =   0;    // verbose
+    pPars->fVeryVerbose =   0;    // verbose
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "DNcvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->DelayWire = atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->DelayWire < 0.0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->nDegree = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nDegree < 0 )
+                goto usage;
+            break;
+        case 'c':
+            pPars->fCascade ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "Need mapped network.\n" );
+        return 1;
+    }
+    if ( pPars->pLutLib == NULL )
+    {
+        Abc_Print( -1, "LUT library is not given.\n" );
+        return 1;
+    }
+
+    pPars->nLutSize = Abc_NtkGetFaninMax( pNtk );
+    if ( pPars->nLutSize > pPars->pLutLib->LutMax )
+    {
+        Abc_Print( -1, "The max node size (%d) exceeds the LUT size (%d).\n", pPars->nLutSize, pPars->pLutLib->LutMax );
+        return 1;
+    }
+    if ( pPars->nLutSize < pPars->pLutLib->LutMax )
+        Abc_Print( 0, "Node size (%d) is less than LUT size (%d).\n", pPars->nLutSize, pPars->pLutLib->LutMax );
+    // check delay information
+    fError = 0;
+    for ( c = 0; c < pPars->pLutLib->LutMax; c++ )
+    {
+        pPars->pLutDelays[c] = ( pPars->pLutLib->fVarPinDelays ? pPars->pLutLib->pLutDelays[pPars->pLutLib->LutMax][c] : pPars->pLutLib->pLutDelays[pPars->pLutLib->LutMax][0] );
+        if ( pPars->DelayWire >= pPars->pLutDelays[c] )
+        {
+            fError = 1;
+            printf(" Wire delay (%.2f) exceeds pin+wire delay (%.2f) for pin %d in the LUT library.\n", pPars->DelayWire, pPars->pLutDelays[c], c );
+        }
+    }
+    if ( fError )
+        return 1;
+
+    // call the mapper
+    Abc_NtkPerformIfif( pNtk, pPars );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: ifif [-DNcvwh]\n" );
+    Abc_Print( -2, "\t           technology mapper into N-node K-LUT structures\n" );
+    Abc_Print( -2, "\t           (takes a LUT network and maps it into a delay-optimal network\n" );
+    Abc_Print( -2, "\t            of N-node K-LUT structures using the current LUT library)\n" );
+    Abc_Print( -2, "\t-D float : wire delay (should be less than the LUT delay) [default = %.2f]\n", pPars->DelayWire );
+    Abc_Print( -2, "\t-N num   : degree of the LUT structure [default = %d]\n", pPars->nDegree );
+    Abc_Print( -2, "\t-c       : toggles using LUT cascade vs LUT cluster [default = %s]\n", pPars->fCascade? "cascade": "cluster" );
+    Abc_Print( -2, "\t-v       : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggles very verbose output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDsdSave( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char * FileName;
+    char ** pArgvNew;
+    int nArgcNew;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( !Abc_FrameReadManDsd() )
+    {
+        Abc_Print( -1, "The DSD manager is not started.\n" );
+        return 1;
+    }
+
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( nArgcNew != 1 )
+    {
+        Abc_Print( -1, "File name is not given on the command line.\n" );
+        return 1;
+    }
+    // get the input file name
+    FileName = (nArgcNew == 1) ? pArgvNew[0] : NULL;
+    If_DsdManSave( (If_DsdMan_t *)Abc_FrameReadManDsd(), FileName );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dsd_save [-h] <file>\n" );
+    Abc_Print( -2, "\t         saves DSD manager into a file\n");
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : (optional) file name to write\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDsdLoad( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char * FileName, * pTemp;
+    char ** pArgvNew;
+    int c, nArgcNew;
+    FILE * pFile;
+    If_DsdMan_t * pDsdMan;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( nArgcNew != 1 )
+    {
+        Abc_Print( -1, "File name is not given on the command line.\n" );
+        return 1;
+    }
+    // get the input file name
+    FileName = pArgvNew[0];
+    // fix the wrong symbol
+    for ( pTemp = FileName; *pTemp; pTemp++ )
+        if ( *pTemp == '>' )
+            *pTemp = '\\';
+    if ( (pFile = fopen( FileName, "r" )) == NULL )
+    {
+        Abc_Print( -1, "Cannot open input file \"%s\". ", FileName );
+        if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) )
+            Abc_Print( 1, "Did you mean \"%s\"?", FileName );
+        Abc_Print( 1, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+    Abc_FrameSetManDsd( NULL );
+    pDsdMan = If_DsdManLoad(FileName);
+    if ( pDsdMan == NULL )
+        return 1;
+    Abc_FrameSetManDsd( pDsdMan );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dsd_load [-h] <file>\n" );
+    Abc_Print( -2, "\t         loads DSD manager from file\n");
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : file name to read\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDsdFree( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( !Abc_FrameReadManDsd() )
+    {
+        Abc_Print( 1, "The DSD manager is not started.\n" );
+        return 0;
+    }
+    Abc_FrameSetManDsd( NULL );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dsd_ps [-h]\n" );
+    Abc_Print( -2, "\t        deletes DSD manager\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDsdPs( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c, Number = 0, Support = 0, fOccurs = 0, fTtDump = 0, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "NSotvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            Number = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Number < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            Support = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Support < 0 )
+                goto usage;
+            break;
+        case 'o':
+            fOccurs ^= 1;
+            break;
+        case 't':
+            fTtDump ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( !Abc_FrameReadManDsd() )
+    {
+        Abc_Print( 1, "The DSD manager is not started.\n" );
+        return 0;
+    }
+    If_DsdManPrint( (If_DsdMan_t *)Abc_FrameReadManDsd(), NULL, Number, Support, fOccurs, fTtDump, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dsd_ps [-NS num] [-ovh]\n" );
+    Abc_Print( -2, "\t         prints statistics of DSD manager\n" );
+    Abc_Print( -2, "\t-N num : show structures whose ID divides by N [default = %d]\n",   Number );
+    Abc_Print( -2, "\t-S num : show structures whose support size is S [default = %d]\n", Support );
+    Abc_Print( -2, "\t-o     : toggles printing occurence distribution [default = %s]\n", fOccurs? "yes": "no" );
+    Abc_Print( -2, "\t-t     : toggles dumping truth tables [default = %s]\n",            fTtDump? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggles verbose output [default = %s]\n",                  fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDsdTune( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c, fVerbose = 0, fFast = 0, fAdd = 0, fSpec = 0, LutSize = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Kfasvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            LutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( LutSize < 4 || LutSize > 6 )
+                goto usage;
+            break;
+        case 'f':
+            fFast ^= 1;
+            break;
+        case 'a':
+            fAdd ^= 1;
+            break;
+        case 's':
+            fSpec ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( !Abc_FrameReadManDsd() )
+    {
+        Abc_Print( 1, "The DSD manager is not started.\n" );
+        return 0;
+    }
+    If_DsdManTune( (If_DsdMan_t *)Abc_FrameReadManDsd(), LutSize, fFast, fAdd, fSpec, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dsd_tune [-K num] [-fasvh]\n" );
+    Abc_Print( -2, "\t         tunes DSD manager for the given LUT size\n" );
+    Abc_Print( -2, "\t-K num : LUT size used for tuning [default = %d]\n",        LutSize );
+    Abc_Print( -2, "\t-f     : toggles using fast check [default = %s]\n",        fFast? "yes": "no" );
+    Abc_Print( -2, "\t-a     : toggles adding tuning to the current one [default = %s]\n",    fAdd? "yes": "no" );
+    Abc_Print( -2, "\t-s     : toggles using specialized check [default = %s]\n", fSpec? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggles verbose output [default = %s]\n",          fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDsdMerge( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char * FileName, * pTemp;
+    char ** pArgvNew;
+    int c, nArgcNew;
+    FILE * pFile;
+    If_DsdMan_t * pDsdMan;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( !Abc_FrameReadManDsd() )
+    {
+        Abc_Print( 1, "The DSD manager is not started.\n" );
+        return 0;
+    }
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( nArgcNew != 1 )
+    {
+        Abc_Print( -1, "File name is not given on the command line.\n" );
+        return 1;
+    }
+    // get the input file name
+    FileName = pArgvNew[0];
+    // fix the wrong symbol
+    for ( pTemp = FileName; *pTemp; pTemp++ )
+        if ( *pTemp == '>' )
+            *pTemp = '\\';
+    if ( (pFile = fopen( FileName, "r" )) == NULL )
+    {
+        Abc_Print( -1, "Cannot open input file \"%s\". ", FileName );
+        if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) )
+            Abc_Print( 1, "Did you mean \"%s\"?", FileName );
+        Abc_Print( 1, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+    pDsdMan = If_DsdManLoad(FileName);
+    if ( pDsdMan == NULL )
+        return 1;
+    If_DsdManMerge( (If_DsdMan_t *)Abc_FrameReadManDsd(), pDsdMan );
+    If_DsdManFree( pDsdMan, 0 );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dsd_merge [-h] <file>\n" );
+    Abc_Print( -2, "\t         merges DSD manager from file with the current one\n");
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : file name to read\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDsdClean( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( !Abc_FrameReadManDsd() )
+    {
+        Abc_Print( 1, "The DSD manager is not started.\n" );
+        return 0;
+    }
+    If_DsdManClean( (If_DsdMan_t *)Abc_FrameReadManDsd(), fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dsd_clean [-K num] [-vh]\n" );
+    Abc_Print( -2, "\t         cleans the occurrence counters\n" );
+    Abc_Print( -2, "\t-v     : toggles verbose output [default = %s]\n",          fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandInit( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Abc_Obj_t * pObj;
+    int c, i;
+    int fZeros;
+    int fOnes;
+    int fRandom;
+    int fDontCare;
+    char * pInitStr;
+    // set defaults
+    fZeros    = 0;
+    fOnes     = 0;
+    fRandom   = 0;
+    fDontCare = 0;
+    pInitStr  = NULL;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Szordh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pInitStr = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'z':
+            fZeros ^= 1;
+            break;
+        case 'o':
+            fOnes ^= 1;
+            break;
+        case 'r':
+            fRandom ^= 1;
+            break;
+        case 'd':
+            fDontCare ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "The current network is combinational.\n" );
+        return 0;
+    }
+
+    if ( pInitStr != NULL )
+    {
+        if ( (int)strlen(pInitStr) != Abc_NtkLatchNum(pNtk) )
+        {
+            Abc_Print( -1, "The length of init string (%d) differs from the number of flops (%d).\n", strlen(pInitStr), Abc_NtkLatchNum(pNtk) );
+            return 1;
+        }
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+            if ( pInitStr[i] == '0' )
+                Abc_LatchSetInit0( pObj );
+            else if ( pInitStr[i] == '1' )
+                Abc_LatchSetInit1( pObj );
+            else 
+                Abc_LatchSetInitDc( pObj );
+        return 0;
+    }
+
+    if ( fZeros )
+    {
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+            Abc_LatchSetInit0( pObj );
+    }
+    else if ( fOnes )
+    {
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+            Abc_LatchSetInit1( pObj );
+    }
+    else if ( fRandom )
+    {
+        srand( time(NULL) );
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+            if ( rand() & 1 )
+                Abc_LatchSetInit1( pObj );
+            else
+                Abc_LatchSetInit0( pObj );
+    }
+    else if ( fDontCare )
+    {
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+            Abc_LatchSetInitDc( pObj );
+    }
+    else
+        Abc_Print( -1, "The initial states remain unchanged.\n" );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: init [-zordh] [-S <init_string>]\n" );
+    Abc_Print( -2, "\t         resets initial states of all latches\n" );
+    Abc_Print( -2, "\t-z     : set zeros initial states [default = %s]\n", fZeros? "yes": "no" );
+    Abc_Print( -2, "\t-o     : set ones initial states [default = %s]\n", fOnes? "yes": "no" );
+    Abc_Print( -2, "\t-d     : set don't-care initial states [default = %s]\n", fDontCare? "yes": "no" );
+    Abc_Print( -2, "\t-r     : set random initial states [default = %s]\n", fRandom? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t-S str : (optional) initial state  [default = unused]\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandZero( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "The current network is combinational.\n" );
+        return 0;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for AIGs.\n" );
+        return 0;
+    }
+
+    // get the new network
+    pNtkRes = Abc_NtkRestrashZero( pNtk, 0 );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Converting to sequential AIG has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: zero [-h]\n" );
+    Abc_Print( -2, "\t        converts latches to have const-0 initial value\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandUndc( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c, fUseCex = 0;
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'c':
+            fUseCex ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( fUseCex )
+    {
+        char * pInit; 
+        Abc_Cex_t * pTemp;
+        int k, nFlopsX = 0;
+        if ( pAbc->pCex == NULL )
+        {
+            Abc_Print( -1, "Current CEX is not available.\n" );
+            return 1;
+        }
+        pInit = Abc_NtkCollectLatchValuesStr( pAbc->pNtkCur );
+        // count the number of X-valued flops
+        for ( k = 0; k < Abc_NtkLatchNum(pAbc->pNtkCur); k++ )
+            nFlopsX += (int)(pInit[k] == 'x');
+        // compare this value
+        if ( Abc_NtkPiNum(pNtk) + nFlopsX != pAbc->pCex->nPis )
+        {
+            Abc_Print( -1, "The number of PIs (%d) plus X-valued flops (%d) in the original network does not match the number of PIs in the current CEX (%d).\n", 
+                Abc_NtkPiNum(pNtk), Abc_NtkLatchNum(pNtk), pAbc->pCex->nPis );
+            return 1;
+        }
+        pAbc->pCex = Abc_CexTransformUndc( pTemp = pAbc->pCex, pInit );
+        assert( pAbc->pCex->nPis == Abc_NtkPiNum(pAbc->pNtkCur) );
+        assert( pAbc->pCex->nRegs == Abc_NtkLatchNum(pAbc->pNtkCur) );
+        Abc_CexFree( pTemp );
+        ABC_FREE( pInit );
+        return 0;
+    }
+
+    if ( Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "The current network is combinational.\n" );
+        return 0;
+    }
+
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for logic networks.\n" );
+        return 0;
+    }
+
+    // get the new network
+    Abc_NtkConvertDcLatches( pNtk );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: undc [-ch]\n" );
+    Abc_Print( -2, "\t        converts latches with DC init values into free PIs\n" );
+    Abc_Print( -2, "\t-c    : toggles transforming CEX after \"logic;undc;st;zero\" [default = %s]\n", fUseCex? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandOneHot( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    extern Abc_Ntk_t * Abc_NtkConvertOnehot( Abc_Ntk_t * pNtk );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "The current network is combinational.\n" );
+        return 0;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for logic networks.\n" );
+        return 0;
+    }
+    // get the new network
+    pNtkRes = Abc_NtkConvertOnehot( pNtk );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Converting to one-hot encoding has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: onehot [-h]\n" );
+    Abc_Print( -2, "\t        converts natural encoding into one-hot encoding\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPipe( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int nLatches;
+    extern void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches );
+    // set defaults
+    nLatches = 5;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Lh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nLatches = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLatches < 0 )
+                goto usage;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "The current network is combinational.\n" );
+        return 0;
+    }
+
+    // update the network
+    Abc_NtkLatchPipe( pNtk, nLatches );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: pipe [-L num] [-h]\n" );
+    Abc_Print( -2, "\t         inserts the given number of latches at each PI for pipelining\n" );
+    Abc_Print( -2, "\t-L num : the number of latches to insert [default = %d]\n", nLatches );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSeq( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( Abc_NtkLatchNum(pNtk) == 0 )
+    {
+        Abc_Print( -1, "The network has no latches.\n" );
+        return 0;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Conversion to sequential AIG works only for combinational AIGs (run \"strash\").\n" );
+        return 1;
+    }
+
+    // get the new network
+//    pNtkRes = Abc_NtkAigToSeq( pNtk );
+    pNtkRes = NULL;
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Converting to sequential AIG has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: seq [-h]\n" );
+    Abc_Print( -2, "\t        converts AIG into sequential AIG\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandUnseq( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int fShare;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fShare = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 's':
+            fShare ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+/*
+    if ( !Abc_NtkIsSeq(pNtk) )
+    {
+        Abc_Print( -1, "Conversion to combinational AIG works only for sequential AIG (run \"seq\").\n" );
+        return 1;
+    }
+*/
+    // share the latches on the fanout edges
+//    if ( fShare )
+//        Seq_NtkShareFanouts(pNtk);
+
+    // get the new network
+//    pNtkRes = Abc_NtkSeqToLogicSop( pNtk );
+    pNtkRes = NULL;
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Converting sequential AIG into an SOP logic network has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: unseq [-sh]\n" );
+    Abc_Print( -2, "\t        converts sequential AIG into an SOP logic network\n" );
+    Abc_Print( -2, "\t-s    : toggle sharing latches [default = %s]\n", fShare? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c, nMaxIters;
+    int fForward;
+    int fBackward;
+    int fOneStep;
+    int fVerbose;
+    int Mode;
+    int nDelayLim;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Mode      =  5;
+    nDelayLim =  0;
+    fForward  =  0;
+    fBackward =  0;
+    fOneStep  =  0;
+    fVerbose  =  0;
+    nMaxIters = 15;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "MDfbsvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            Mode = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Mode < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nDelayLim = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nDelayLim < 0 )
+                goto usage;
+            break;
+        case 'f':
+            fForward ^= 1;
+            break;
+        case 'b':
+            fBackward ^= 1;
+            break;
+        case 's':
+            fOneStep ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( fForward && fBackward )
+    {
+        Abc_Print( -1, "Only one switch \"-f\" or \"-b\" can be selected at a time.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkLatchNum(pNtk) )
+    {
+//        Abc_Print( -1, "The network has no latches. Retiming is not performed.\n" );
+        return 0;
+    }
+
+    if ( Mode < 0 || Mode > 6 )
+    {
+        Abc_Print( -1, "The mode (%d) is incorrect. Retiming is not performed.\n", Mode );
+        return 0;
+    }
+
+    if ( Abc_NtkIsStrash(pNtk) )
+    {
+        if ( Abc_NtkGetChoiceNum(pNtk) )
+        {
+            Abc_Print( -1, "Retiming with choice nodes is not implemented.\n" );
+            return 0;
+        }
+        // convert the network into an SOP network
+        pNtkRes = Abc_NtkToLogic( pNtk );
+        // perform the retiming
+        Abc_NtkRetime( pNtkRes, Mode, nDelayLim, fForward, fBackward, fOneStep, fVerbose );
+        // replace the current network
+        Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+        return 0;
+    }
+
+    // get the network in the SOP form
+    if ( !Abc_NtkToSop(pNtk, 0) )
+    {
+        Abc_Print( -1, "Converting to SOPs has failed.\n" );
+        return 0;
+    }
+
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "The network is not a logic network. Retiming is not performed.\n" );
+        return 0;
+    }
+
+    // perform the retiming
+    Abc_NtkRetime( pNtk, Mode, nDelayLim, fForward, fBackward, fOneStep, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: retime [-MD num] [-fbvh]\n" );
+    Abc_Print( -2, "\t         retimes the current network using one of the algorithms:\n" );
+    Abc_Print( -2, "\t             1: most forward retiming\n" );
+    Abc_Print( -2, "\t             2: most backward retiming\n" );
+    Abc_Print( -2, "\t             3: forward and backward min-area retiming\n" );
+    Abc_Print( -2, "\t             4: forward and backward min-delay retiming\n" );
+    Abc_Print( -2, "\t             5: mode 3 followed by mode 4\n" );
+    Abc_Print( -2, "\t             6: Pan's optimum-delay retiming using binary search\n" );
+    Abc_Print( -2, "\t-M num : the retiming algorithm to use [default = %d]\n", Mode );
+    Abc_Print( -2, "\t-D num : the minimum delay target (0=unused) [default = %d]\n", nDelayLim );
+    Abc_Print( -2, "\t-f     : enables forward-only retiming in modes 3,4,5 [default = %s]\n", fForward? "yes": "no" );
+    Abc_Print( -2, "\t-b     : enables backward-only retiming in modes 3,4,5 [default = %s]\n", fBackward? "yes": "no" );
+    Abc_Print( -2, "\t-s     : enables retiming one step only in mode 4 [default = %s]\n", fOneStep? "yes": "no" );
+    Abc_Print( -2, "\t-v     : enables verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+//    Abc_Print( -2, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters );
+//    Abc_Print( -2, "\t-f     : toggle forward retiming (for AIGs) [default = %s]\n", fForward? "yes": "no" );
+//    Abc_Print( -2, "\t-b     : toggle backward retiming (for AIGs) [default = %s]\n", fBackward? "yes": "no" );
+//    Abc_Print( -2, "\t-i     : toggle computation of initial state [default = %s]\n", fInitial? "yes": "no" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int fMinArea;
+    int fForwardOnly;
+    int fBackwardOnly;
+    int fInitial;
+    int nStepsMax;
+    int fFastAlgo;
+    int fVerbose;
+    int c, nMaxIters;
+    extern Abc_Ntk_t * Abc_NtkDarRetime( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose );
+    extern Abc_Ntk_t * Abc_NtkDarRetimeF( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose );
+    extern Abc_Ntk_t * Abc_NtkDarRetimeMinArea( Abc_Ntk_t * pNtk, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose );
+    extern Abc_Ntk_t * Abc_NtkDarRetimeMostFwd( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fMinArea  = 1;
+    fForwardOnly = 0;
+    fBackwardOnly = 0;
+    fInitial = 1;
+    nStepsMax = 100000;
+    fFastAlgo = 0;
+    nMaxIters = 20;
+    fVerbose  = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "NSmfbiavh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nMaxIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nMaxIters < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nStepsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nStepsMax < 0 )
+                goto usage;
+            break;
+        case 'm':
+            fMinArea ^= 1;
+            break;
+        case 'f':
+            fForwardOnly ^= 1;
+            break;
+        case 'b':
+            fBackwardOnly ^= 1;
+            break;
+        case 'i':
+            fInitial ^= 1;
+            break;
+        case 'a':
+            fFastAlgo ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkLatchNum(pNtk) )
+    {
+//        Abc_Print( -1, "The network has no latches. Retiming is not performed.\n" );
+        return 0;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for structrally hashed networks. Run \"st\".\n" );
+        return 0;
+    }
+
+    // perform the retiming
+    if ( fMinArea )
+        pNtkRes = Abc_NtkDarRetimeMinArea( pNtk, nMaxIters, fForwardOnly, fBackwardOnly, fInitial, fVerbose );
+    else if ( fFastAlgo )
+        pNtkRes = Abc_NtkDarRetime( pNtk, nStepsMax, fVerbose );
+    else
+//        pNtkRes = Abc_NtkDarRetimeF( pNtk, nStepsMax, fVerbose );
+        pNtkRes = Abc_NtkDarRetimeMostFwd( pNtk, nMaxIters, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Retiming has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dretime [-NS num] [-mfbiavh]\n" );
+    Abc_Print( -2, "\t         new implementation of min-area (or most-forward) retiming\n" );
+    Abc_Print( -2, "\t-m     : toggle min-area retiming and most-forward retiming [default = %s]\n", fMinArea? "min-area": "most-fwd" );
+    Abc_Print( -2, "\t-f     : enables forward-only retiming [default = %s]\n", fForwardOnly? "yes": "no" );
+    Abc_Print( -2, "\t-b     : enables backward-only retiming [default = %s]\n", fBackwardOnly? "yes": "no" );
+    Abc_Print( -2, "\t-i     : enables init state computation [default = %s]\n", fInitial? "yes": "no" );
+    Abc_Print( -2, "\t-N num : the max number of one-frame iterations to perform [default = %d]\n", nMaxIters );
+    Abc_Print( -2, "\t-S num : the max number of forward retiming steps to perform [default = %d]\n", nStepsMax );
+    Abc_Print( -2, "\t-a     : enables a fast most-forward algorithm [default = %s]\n", fFastAlgo? "yes": "no" );
+    Abc_Print( -2, "\t-v     : enables verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandFlowRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c, nMaxIters;
+    int fForward;
+    int fBackward;
+    int fVerbose;
+    int fComputeInit, fGuaranteeInit, fBlockConst;
+    int fFastButConservative;
+    int maxDelay;
+
+    if ( argc == 2 && !strcmp(argv[1], "-h") )
+    {
+        Abc_Print( -2, "The fretime command is temporarily disabled.\n" );
+        return 1;
+    }
+
+    Abc_Print( -1, "This command is temporarily disabled.\n" );
+    return 0;
+//    extern Abc_Ntk_t* Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose,
+//                                             int fComputeInit, int fGuaranteeInit, int fBlockConst,
+//                                             int fForward, int fBackward, int nMaxIters,
+//                                             int maxDelay, int fFastButConservative);
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fForward  =  0;
+    fFastButConservative = 0;
+    fBackward =  0;
+    fComputeInit =  1;
+    fGuaranteeInit =  0;
+    fVerbose  =  0;
+    fBlockConst  =  0;
+    nMaxIters = 999;
+    maxDelay  = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "MDfcgbkivh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nMaxIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nMaxIters < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            maxDelay = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( maxDelay < 0 )
+                goto usage;
+           break;
+        case 'f':
+            fForward ^= 1;
+            break;
+        case 'c':
+            fFastButConservative ^= 1;
+            break;
+        case 'i':
+            fComputeInit ^= 1;
+            break;
+        case 'b':
+            fBackward ^= 1;
+            break;
+        case 'g':
+            fGuaranteeInit ^= 1;
+            break;
+        case 'k':
+            fBlockConst ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( fForward && fBackward )
+    {
+        Abc_Print( -1, "Only one switch \"-f\" or \"-b\" can be selected at a time.\n" );
+        return 1;
+    }
+
+    if ( fGuaranteeInit && !fComputeInit )
+    {
+      Abc_Print( -1, "Initial state guarantee (-g) requires initial state computation (-i).\n" );
+      return 1;
+    }
+
+    if ( !Abc_NtkLatchNum(pNtk) )
+    {
+//        Abc_Print( -1, "The network has no latches. Retiming is not performed.\n" );
+        return 0;
+    }
+
+    if ( Abc_NtkGetChoiceNum(pNtk) )
+      {
+        Abc_Print( -1, "Retiming with choice nodes is not implemented.\n" );
+        return 0;
+      }
+
+    // perform the retiming
+//    pNtkRes = Abc_FlowRetime_MinReg( pNtk, fVerbose, fComputeInit,
+//                                     fGuaranteeInit, fBlockConst,
+//                                     fForward, fBackward,
+//                                     nMaxIters, maxDelay, fFastButConservative );
+
+    if (pNtkRes != pNtk)
+      Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: fretime [-M num] [-D num] [-fbvih]\n" );
+    Abc_Print( -2, "\t         retimes the current network using flow-based algorithm\n" );
+    Abc_Print( -2, "\t-M num : the maximum number of iterations [default = %d]\n", nMaxIters );
+    Abc_Print( -2, "\t-D num : the maximum delay [default = none]\n" );
+    Abc_Print( -2, "\t-i     : enables init state computation [default = %s]\n", fComputeInit? "yes": "no" );
+    Abc_Print( -2, "\t-k     : blocks retiming over const nodes [default = %s]\n", fBlockConst? "yes": "no" );
+    Abc_Print( -2, "\t-g     : guarantees init state computation [default = %s]\n", fGuaranteeInit? "yes": "no" );
+    Abc_Print( -2, "\t-c     : very fast (but conserv.) delay constraints [default = %s]\n", fFastButConservative? "yes": "no" );
+    Abc_Print( -2, "\t-f     : enables forward-only retiming  [default = %s]\n", fForward? "yes": "no" );
+    Abc_Print( -2, "\t-b     : enables backward-only retiming [default = %s]\n", fBackward? "yes": "no" );
+    Abc_Print( -2, "\t-v     : enables verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int fVerbose;
+    extern Abc_Ntk_t * Abc_NtkCRetime( Abc_Ntk_t * pNtk, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fVerbose    = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Only works for logic networks.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkLatchNum(pNtk) )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    // modify the current network
+    pNtkRes = Abc_NtkCRetime( pNtk, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Sequential cleanup has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: cretime [-vh]\n" );
+    Abc_Print( -2, "\t         performs most-forward retiming with equiv classes\n" );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSeqFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes;
+    int c, nMaxIters;
+    int fVerbose;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nMaxIters = 15;
+    fVerbose  =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nMaxIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nMaxIters < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( Abc_NtkHasAig(pNtk) )
+    {
+/*
+        // quit if there are choice nodes
+        if ( Abc_NtkGetChoiceNum(pNtk) )
+        {
+            Abc_Print( -1, "Currently cannot map/retime networks with choice nodes.\n" );
+            return 0;
+        }
+*/
+//        if ( Abc_NtkIsStrash(pNtk) )
+//            pNtkNew = Abc_NtkAigToSeq(pNtk);
+//        else
+//            pNtkNew = Abc_NtkDup(pNtk);
+        pNtkNew = NULL;
+    }
+    else
+    {
+        // strash and balance the network
+        pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 );
+        if ( pNtkNew == NULL )
+        {
+            Abc_Print( -1, "Strashing before FPGA mapping/retiming has failed.\n" );
+            return 1;
+        }
+
+        pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 );
+        Abc_NtkDelete( pNtkRes );
+        if ( pNtkNew == NULL )
+        {
+            Abc_Print( -1, "Balancing before FPGA mapping has failed.\n" );
+            return 1;
+        }
+
+        // convert into a sequential AIG
+//        pNtkNew = Abc_NtkAigToSeq( pNtkRes = pNtkNew );
+        pNtkNew = NULL;
+        Abc_NtkDelete( pNtkRes );
+        if ( pNtkNew == NULL )
+        {
+            Abc_Print( -1, "Converting into a seq AIG before FPGA mapping/retiming has failed.\n" );
+            return 1;
+        }
+
+        Abc_Print( 1, "The network was strashed and balanced before FPGA mapping/retiming.\n" );
+    }
+
+    // get the new network
+//    pNtkRes = Seq_NtkFpgaMapRetime( pNtkNew, nMaxIters, fVerbose );
+    pNtkRes = NULL;
+    if ( pNtkRes == NULL )
+    {
+//        Abc_Print( -1, "Sequential FPGA mapping has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return 0;
+    }
+    Abc_NtkDelete( pNtkNew );
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: sfpga [-I num] [-vh]\n" );
+    Abc_Print( -2, "\t         performs integrated sequential FPGA mapping/retiming\n" );
+    Abc_Print( -2, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSeqMap( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes;
+    int c, nMaxIters;
+    int fVerbose;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nMaxIters = 15;
+    fVerbose  =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nMaxIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nMaxIters < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( Abc_NtkHasAig(pNtk) )
+    {
+/*
+        // quit if there are choice nodes
+        if ( Abc_NtkGetChoiceNum(pNtk) )
+        {
+            Abc_Print( -1, "Currently cannot map/retime networks with choice nodes.\n" );
+            return 0;
+        }
+*/
+//        if ( Abc_NtkIsStrash(pNtk) )
+//            pNtkNew = Abc_NtkAigToSeq(pNtk);
+//        else
+//            pNtkNew = Abc_NtkDup(pNtk);
+        pNtkNew = NULL;
+    }
+    else
+    {
+        // strash and balance the network
+        pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 );
+        if ( pNtkNew == NULL )
+        {
+            Abc_Print( -1, "Strashing before SC mapping/retiming has failed.\n" );
+            return 1;
+        }
+
+        pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 );
+        Abc_NtkDelete( pNtkRes );
+        if ( pNtkNew == NULL )
+        {
+            Abc_Print( -1, "Balancing before SC mapping/retiming has failed.\n" );
+            return 1;
+        }
+
+        // convert into a sequential AIG
+//        pNtkNew = Abc_NtkAigToSeq( pNtkRes = pNtkNew );
+        pNtkNew = NULL;
+        Abc_NtkDelete( pNtkRes );
+        if ( pNtkNew == NULL )
+        {
+            Abc_Print( -1, "Converting into a seq AIG before SC mapping/retiming has failed.\n" );
+            return 1;
+        }
+
+        Abc_Print( -1, "The network was strashed and balanced before SC mapping/retiming.\n" );
+    }
+
+    // get the new network
+//    pNtkRes = Seq_MapRetime( pNtkNew, nMaxIters, fVerbose );
+    pNtkRes = NULL;
+    if ( pNtkRes == NULL )
+    {
+//        Abc_Print( -1, "Sequential FPGA mapping has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return 0;
+    }
+    Abc_NtkDelete( pNtkNew );
+
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: smap [-I num] [-vh]\n" );
+    Abc_Print( -2, "\t         performs integrated sequential standard-cell mapping/retiming\n" );
+    Abc_Print( -2, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSeqSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    Fra_Ssw_t Pars, * pPars = &Pars;
+    int c;
+    extern Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, Fra_Ssw_t * pPars );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    pPars->nPartSize  = 0;
+    pPars->nOverSize  = 0;
+    pPars->nFramesP   = 0;
+    pPars->nFramesK   = 1;
+    pPars->nMaxImps   = 5000;
+    pPars->nMaxLevs   = 0;
+    pPars->fUseImps   = 0;
+    pPars->fRewrite   = 0;
+    pPars->fFraiging  = 0;
+    pPars->fLatchCorr = 0;
+    pPars->fWriteImps = 0;
+    pPars->fUse1Hot   = 0;
+    pPars->fVerbose   = 0;
+    pPars->TimeLimit  = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "PQNFILirfletvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nPartSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nPartSize < 2 )
+                goto usage;
+            break;
+        case 'Q':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-Q\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nOverSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nOverSize < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesP = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesP < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesK = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesK <= 0 )
+                goto usage;
+            break;
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nMaxImps = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nMaxImps <= 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nMaxLevs = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nMaxLevs <= 0 )
+                goto usage;
+            break;
+        case 'i':
+            pPars->fUseImps ^= 1;
+            break;
+        case 'r':
+            pPars->fRewrite ^= 1;
+            break;
+        case 'f':
+            pPars->fFraiging ^= 1;
+            break;
+        case 'l':
+            pPars->fLatchCorr ^= 1;
+            break;
+        case 'e':
+            pPars->fWriteImps ^= 1;
+            break;
+        case 't':
+            pPars->fUse1Hot ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" );
+        return 0;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for structrally hashed networks. Run \"st\".\n" );
+        return 0;
+    }
+
+    if ( pPars->nFramesK > 1 && pPars->fUse1Hot )
+    {
+        Abc_Print( -1, "Currrently can only use one-hotness for simple induction (K=1).\n" );
+        return 0;
+    }
+
+    if ( pPars->nFramesP && pPars->fUse1Hot )
+    {
+        Abc_Print( -1, "Currrently can only use one-hotness without prefix.\n" );
+        return 0;
+    }
+
+    // get the new network
+    pNtkRes = Abc_NtkDarSeqSweep( pNtk, pPars );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Sequential sweeping has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: ssweep [-PQNFL <num>] [-lrfetvh]\n" );
+    Abc_Print( -2, "\t         performs sequential sweep using K-step induction\n" );
+    Abc_Print( -2, "\t-P num : max partition size (0 = no partitioning) [default = %d]\n", pPars->nPartSize );
+    Abc_Print( -2, "\t-Q num : partition overlap (0 = no overlap) [default = %d]\n", pPars->nOverSize );
+    Abc_Print( -2, "\t-N num : number of time frames to use as the prefix [default = %d]\n", pPars->nFramesP );
+    Abc_Print( -2, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", pPars->nFramesK );
+    Abc_Print( -2, "\t-L num : max number of levels to consider (0=all) [default = %d]\n", pPars->nMaxLevs );
+//    Abc_Print( -2, "\t-I num : max number of implications to consider [default = %d]\n", pPars->nMaxImps );
+//    Abc_Print( -2, "\t-i     : toggle using implications [default = %s]\n", pPars->fUseImps? "yes": "no" );
+    Abc_Print( -2, "\t-l     : toggle latch correspondence only [default = %s]\n", pPars->fLatchCorr? "yes": "no" );
+    Abc_Print( -2, "\t-r     : toggle AIG rewriting [default = %s]\n", pPars->fRewrite? "yes": "no" );
+    Abc_Print( -2, "\t-f     : toggle fraiging (combinational SAT sweeping) [default = %s]\n", pPars->fFraiging? "yes": "no" );
+    Abc_Print( -2, "\t-e     : toggle writing implications as assertions [default = %s]\n", pPars->fWriteImps? "yes": "no" );
+    Abc_Print( -2, "\t-t     : toggle using one-hotness conditions [default = %s]\n", pPars->fUse1Hot? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    Ssw_Pars_t Pars, * pPars = &Pars;
+    int nConstrs = 0;
+    int c;
+    extern Abc_Ntk_t * Abc_NtkDarSeqSweep2( Abc_Ntk_t * pNtk, Ssw_Pars_t * pPars );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Ssw_ManSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLSIVMNcmplkofdseqvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nPartSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nPartSize < 2 )
+                goto usage;
+            break;
+        case 'Q':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-Q\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nOverSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nOverSize < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesK = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesK <= 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBTLimit <= 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nMaxLevs = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nMaxLevs <= 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesAddSim = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesAddSim < 0 )
+                goto usage;
+            break;
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nItersStop = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nItersStop < 0 )
+                goto usage;
+            break;
+        case 'V':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nSatVarMax2 = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nSatVarMax2 < 0 )
+                goto usage;
+            break;
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRecycleCalls2 = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRecycleCalls2 < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConstrs = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConstrs < 0 )
+                goto usage;
+            break;
+        case 'c':
+            pPars->fConstrs ^= 1;
+            break;
+        case 'm':
+            pPars->fMergeFull ^= 1;
+            break;
+        case 'p':
+            pPars->fPolarFlip ^= 1;
+            break;
+        case 'l':
+            pPars->fLatchCorr ^= 1;
+            break;
+        case 'k':
+            pPars->fConstCorr ^= 1;
+            break;
+        case 'o':
+            pPars->fOutputCorr ^= 1;
+            break;
+        case 'f':
+            pPars->fSemiFormal ^= 1;
+            break;
+        case 'd':
+            pPars->fDynamic ^= 1;
+            break;
+        case 's':
+            pPars->fLocalSim ^= 1;
+            break;
+        case 'e':
+            pPars->fEquivDump ^= 1;
+            break;
+        case 'q':
+            pPars->fStopWhenGone ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fFlopVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" );
+        return 0;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for structrally hashed networks. Run \"st\".\n" );
+        return 0;
+    }
+
+    if ( Abc_NtkPiNum(pNtk) == 0 )
+    {
+        Abc_Print( 0, "This command works only for designs with primary inputs.\n" );
+        return 0;
+    }
+
+    // if constraints are to be used, network should have no constraints
+    if ( nConstrs > 0 )
+    {
+        if ( Abc_NtkConstrNum(pNtk) > 0 )
+        {
+            Abc_Print( -1, "The network already has %d constraints.\n", Abc_NtkConstrNum(pNtk) );
+            return 0;
+        }
+        else
+        {
+            Abc_Print( 0, "Setting the number of constraints to be %d.\n", nConstrs );
+            pNtk->nConstrs = nConstrs;
+        }
+    }
+
+    if ( pPars->fConstrs )
+    {
+        if ( Abc_NtkConstrNum(pNtk) > 0 )
+            Abc_Print( 0, "Performing scorr with %d constraints.\n", Abc_NtkConstrNum(pNtk) );
+        else
+            Abc_Print( 0, "Performing constraint-based scorr without constraints.\n" );
+    }
+
+    // get the new network
+    pNtkRes = Abc_NtkDarSeqSweep2( pNtk, pPars );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Sequential sweeping has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: scorr [-PQFCLSIVMN <num>] [-cmplkodseqvwh]\n" );
+    Abc_Print( -2, "\t         performs sequential sweep using K-step induction\n" );
+    Abc_Print( -2, "\t-P num : max partition size (0 = no partitioning) [default = %d]\n", pPars->nPartSize );
+    Abc_Print( -2, "\t-Q num : partition overlap (0 = no overlap) [default = %d]\n", pPars->nOverSize );
+    Abc_Print( -2, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", pPars->nFramesK );
+    Abc_Print( -2, "\t-C num : max number of conflicts at a node (0=inifinite) [default = %d]\n", pPars->nBTLimit );
+    Abc_Print( -2, "\t-L num : max number of levels to consider (0=all) [default = %d]\n", pPars->nMaxLevs );
+    Abc_Print( -2, "\t-N num : number of last POs treated as constraints (0=none) [default = %d]\n", pPars->fConstrs );
+    Abc_Print( -2, "\t-S num : additional simulation frames for c-examples (0=none) [default = %d]\n", pPars->nFramesAddSim );
+    Abc_Print( -2, "\t-I num : iteration number to stop and output SR-model (-1=none) [default = %d]\n", pPars->nItersStop );
+    Abc_Print( -2, "\t-V num : min var num needed to recycle the SAT solver [default = %d]\n", pPars->nSatVarMax2 );
+    Abc_Print( -2, "\t-M num : min call num needed to recycle the SAT solver [default = %d]\n", pPars->nRecycleCalls2 );
+    Abc_Print( -2, "\t-N num : set last <num> POs to be constraints (use with -c) [default = %d]\n", nConstrs );
+    Abc_Print( -2, "\t-c     : toggle using explicit constraints [default = %s]\n", pPars->fConstrs? "yes": "no" );
+    Abc_Print( -2, "\t-m     : toggle full merge if constraints are present [default = %s]\n", pPars->fMergeFull? "yes": "no" );
+    Abc_Print( -2, "\t-p     : toggle alighning polarity of SAT variables [default = %s]\n", pPars->fPolarFlip? "yes": "no" );
+    Abc_Print( -2, "\t-l     : toggle doing latch correspondence [default = %s]\n", pPars->fLatchCorr? "yes": "no" );
+    Abc_Print( -2, "\t-k     : toggle doing constant correspondence [default = %s]\n", pPars->fConstCorr? "yes": "no" );
+    Abc_Print( -2, "\t-o     : toggle doing \'PO correspondence\' [default = %s]\n", pPars->fOutputCorr? "yes": "no" );
+//    Abc_Print( -2, "\t-f     : toggle filtering using iterative BMC [default = %s]\n", pPars->fSemiFormal? "yes": "no" );
+    Abc_Print( -2, "\t-d     : toggle dynamic addition of constraints [default = %s]\n", pPars->fDynamic? "yes": "no" );
+    Abc_Print( -2, "\t-s     : toggle local simulation in the cone of influence [default = %s]\n", pPars->fLocalSim? "yes": "no" );
+    Abc_Print( -2, "\t-e     : toggle dumping disproved internal equivalences [default = %s]\n", pPars->fEquivDump? "yes": "no" );
+    Abc_Print( -2, "\t-q     : toggle quitting when PO is not a constant candidate [default = %s]\n", pPars->fStopWhenGone? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle printout of flop equivalences [default = %s]\n", pPars->fFlopVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandTestSeqSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char * pFileName;
+    Fra_Ssw_t Pars, * pPars = &Pars;
+    int c;
+//    extern Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, Fra_Ssw_t * pPars );
+    extern int Fra_FraigInductionTest( char * pFileName, Fra_Ssw_t * pParams );
+
+    // set defaults
+    pPars->nPartSize  = 0;
+    pPars->nOverSize  = 0;
+    pPars->nFramesP   = 0;
+    pPars->nFramesK   = 1;
+    pPars->nMaxImps   = 5000;
+    pPars->nMaxLevs   = 0;
+    pPars->fUseImps   = 0;
+    pPars->fRewrite   = 0;
+    pPars->fFraiging  = 0;
+    pPars->fLatchCorr = 0;
+    pPars->fWriteImps = 0;
+    pPars->fUse1Hot   = 0;
+    pPars->fVerbose   = 0;
+    pPars->TimeLimit  = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "PQNFILirfletvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nPartSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nPartSize < 2 )
+                goto usage;
+            break;
+        case 'Q':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-Q\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nOverSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nOverSize < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesP = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesP < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesK = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesK <= 0 )
+                goto usage;
+            break;
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nMaxImps = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nMaxImps <= 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nMaxLevs = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nMaxLevs <= 0 )
+                goto usage;
+            break;
+        case 'i':
+            pPars->fUseImps ^= 1;
+            break;
+        case 'r':
+            pPars->fRewrite ^= 1;
+            break;
+        case 'f':
+            pPars->fFraiging ^= 1;
+            break;
+        case 'l':
+            pPars->fLatchCorr ^= 1;
+            break;
+        case 'e':
+            pPars->fWriteImps ^= 1;
+            break;
+        case 't':
+            pPars->fUse1Hot ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    // get the input file name
+    if ( argc == globalUtilOptind + 1 )
+        pFileName = argv[globalUtilOptind];
+    else
+    {
+        Abc_Print( -1, "File name should be given on the command line.\n" );
+        return 1;
+    }
+    Fra_FraigInductionTest( pFileName, pPars );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: testssw [-PQNFL num] [-lrfetvh] <file>\n" );
+    Abc_Print( -2, "\t         performs sequential sweep using K-step induction\n" );
+    Abc_Print( -2, "\t         (outputs a file with a set of pairs of equivalent nodes)\n" );
+    Abc_Print( -2, "\t-P num : max partition size (0 = no partitioning) [default = %d]\n", pPars->nPartSize );
+    Abc_Print( -2, "\t-Q num : partition overlap (0 = no overlap) [default = %d]\n", pPars->nOverSize );
+    Abc_Print( -2, "\t-N num : number of time frames to use as the prefix [default = %d]\n", pPars->nFramesP );
+    Abc_Print( -2, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", pPars->nFramesK );
+    Abc_Print( -2, "\t-L num : max number of levels to consider (0=all) [default = %d]\n", pPars->nMaxLevs );
+//    Abc_Print( -2, "\t-I num : max number of implications to consider [default = %d]\n", pPars->nMaxImps );
+//    Abc_Print( -2, "\t-i     : toggle using implications [default = %s]\n", pPars->fUseImps? "yes": "no" );
+    Abc_Print( -2, "\t-l     : toggle latch correspondence only [default = %s]\n", pPars->fLatchCorr? "yes": "no" );
+    Abc_Print( -2, "\t-r     : toggle AIG rewriting [default = %s]\n", pPars->fRewrite? "yes": "no" );
+    Abc_Print( -2, "\t-f     : toggle fraiging (combinational SAT sweeping) [default = %s]\n", pPars->fFraiging? "yes": "no" );
+    Abc_Print( -2, "\t-e     : toggle writing implications as assertions [default = %s]\n", pPars->fWriteImps? "yes": "no" );
+    Abc_Print( -2, "\t-t     : toggle using one-hotness conditions [default = %s]\n", pPars->fUse1Hot? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandTestScorr( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Abc_Ntk_t * Abc_NtkTestScorr( char * pFileNameIn, char * pFileNameOut, int nStepsMax, int nBTLimit, int fNewAlgo, int fFlopOnly, int fFfNdOnly, int fVerbose );
+
+    Abc_Ntk_t * pNtkRes;
+    int c;
+    int nConfMax;
+    int nStepsMax;
+    int fNewAlgo;
+    int fFlopOnly;
+    int fFfNdOnly;
+    int fVerbose;
+    // set defaults
+    nConfMax  = 100;
+    nStepsMax =  -1;
+    fNewAlgo  =   0;
+    fFlopOnly =   0;
+    fFfNdOnly =   0;
+    fVerbose  =   0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "CSnfsvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfMax < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nStepsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nStepsMax < 0 )
+                goto usage;
+            break;
+        case 'n':
+            fNewAlgo ^= 1;
+            break;
+        case 'f':
+            fFlopOnly ^= 1;
+            break;
+        case 's':
+            fFfNdOnly ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 2 )
+    {
+        Abc_Print( -1, "Expecting two files names on the command line.\n" );
+        goto usage;
+    }
+    if ( fFlopOnly && fFfNdOnly )
+    {
+        Abc_Print( -1, "These two options (-f and -s) are incompatible.\n" );
+        goto usage;
+    }
+    // get the new network
+    pNtkRes = Abc_NtkTestScorr( argv[globalUtilOptind], argv[globalUtilOptind+1], nStepsMax, nConfMax, fNewAlgo, fFlopOnly, fFfNdOnly, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Sequential sweeping has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: testscorr [-CS num] [-nfsvh] <file_in> <file_out>\n" );
+    Abc_Print( -2, "\t             outputs the list of sequential equivalences into a file\n" );
+    Abc_Print( -2, "\t             (if <file_in> is in BENCH, init state file should be the same directory)\n" );
+    Abc_Print( -2, "\t-C num     : limit on the number of conflicts [default = %d]\n", nConfMax );
+    Abc_Print( -2, "\t-S num     : limit on refinement iterations (-1=no limit, 0=after BMC, etc) [default = %d]\n", nStepsMax );
+    Abc_Print( -2, "\t-n         : toggle between \"scorr\" and \"&scorr\" [default = %s]\n", fNewAlgo? "&scorr": "scorr" );
+    Abc_Print( -2, "\t-f         : toggle reporting only flop/flop equivs [default = %s]\n", fFlopOnly? "yes": "no" );
+    Abc_Print( -2, "\t-s         : toggle reporting only flop/flop and flop/node equivs [default = %s]\n", fFfNdOnly? "yes": "no" );
+    Abc_Print( -2, "\t-v         : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h         : print the command usage\n");
+    Abc_Print( -2, "\t<file_in>  : input file with design for sequential equivalence computation\n");
+    Abc_Print( -2, "\t<file_out> : output file with the list of pairs of equivalent signals\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandLcorr( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int nFramesP;
+    int nConfMax;
+    int nVarsMax;
+    int fNewAlgor;
+    int fVerbose;
+    extern Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose );
+    extern Abc_Ntk_t * Abc_NtkDarLcorrNew( Abc_Ntk_t * pNtk, int nVarsMax, int nConfMax, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+
+
+    // set defaults
+    nFramesP   =     0;
+    nConfMax   =  1000;
+    nVarsMax   =  1000;
+    fNewAlgor  =     1;
+    fVerbose   =     0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "PCSnvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFramesP = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFramesP < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfMax < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nVarsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nVarsMax < 0 )
+                goto usage;
+            break;
+        case 'n':
+            fNewAlgor ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" );
+        return 0;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for structrally hashed networks. Run \"st\".\n" );
+        return 0;
+    }
+
+    // get the new network
+    if ( fNewAlgor )
+        pNtkRes = Abc_NtkDarLcorrNew( pNtk, nVarsMax, nConfMax, fVerbose );
+    else
+        pNtkRes = Abc_NtkDarLcorr( pNtk, nFramesP, nConfMax, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Sequential sweeping has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: lcorr [-PCS num] [-nvh]\n" );
+    Abc_Print( -2, "\t         computes latch correspondence using 1-step induction\n" );
+    Abc_Print( -2, "\t-P num : number of time frames to use as the prefix [default = %d]\n", nFramesP );
+    Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfMax );
+    Abc_Print( -2, "\t-S num : the max number of SAT variables [default = %d]\n", nVarsMax );
+    Abc_Print( -2, "\t-n     : toggle using new algorithm [default = %s]\n", fNewAlgor? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int c;
+    int fLatchConst  =   1;
+    int fLatchEqual  =   1;
+    int fSaveNames   =   1;
+    int fUseMvSweep  =   0;
+    int nFramesSymb  =   1;
+    int nFramesSatur = 512;
+    int fVerbose     =   0;
+    int fVeryVerbose =   0;
+    pNtk = Abc_FrameReadNtk(pAbc);
+
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "cenmFSvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'c':
+            fLatchConst ^= 1;
+            break;
+        case 'e':
+            fLatchEqual ^= 1;
+            break;
+        case 'n':
+            fSaveNames ^= 1;
+            break;
+        case 'm':
+            fUseMvSweep ^= 1;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFramesSymb = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFramesSymb < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFramesSatur = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFramesSatur < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Only works for structrally hashed networks.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkLatchNum(pNtk) )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    // modify the current network
+    pNtkRes = Abc_NtkDarLatchSweep( pNtk, fLatchConst, fLatchEqual, fSaveNames, fUseMvSweep, nFramesSymb, nFramesSatur, fVerbose, fVeryVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Sequential cleanup has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: scleanup [-cenmFSvwh]\n" );
+    Abc_Print( -2, "\t         performs sequential cleanup of the current network\n" );
+    Abc_Print( -2, "\t         by removing nodes and latches that do not feed into POs\n" );
+    Abc_Print( -2, "\t-c     : sweep stuck-at latches detected by ternary simulation [default = %s]\n", fLatchConst? "yes": "no" );
+    Abc_Print( -2, "\t-e     : merge equal latches (same data inputs and init states) [default = %s]\n", fLatchEqual? "yes": "no" );
+    Abc_Print( -2, "\t-n     : toggle preserving latch names [default = %s]\n", fSaveNames? "yes": "no" );
+    Abc_Print( -2, "\t-m     : toggle using hybrid ternary/symbolic simulation [default = %s]\n", fUseMvSweep? "yes": "no" );
+    Abc_Print( -2, "\t-F num : the number of first frames simulated symbolically [default = %d]\n", nFramesSymb );
+    Abc_Print( -2, "\t-S num : the number of frames when symbolic saturation begins [default = %d]\n", nFramesSatur );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle very verbose output [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCycle( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int nFrames;
+    int fUseXval;
+    int fVerbose;
+    extern void Abc_NtkCycleInitState( Abc_Ntk_t * pNtk, int nFrames, int fUseXval, int fVerbose );
+    extern void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose );
+    // set defaults
+    nFrames    = 100;
+    fUseXval   =   0;
+    fVerbose   =   0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Fxvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'x':
+            fUseXval ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsSopLogic(pNtk) )
+    {
+        Abc_Print( -1, "Only works for strashed networks or logic SOP networks.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkLatchNum(pNtk) )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    if ( fUseXval && !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "X-valued simulation only works for AIGs. Run \"strash\".\n" );
+        return 0;
+    }
+    if ( fUseXval )
+        Abc_NtkCycleInitState( pNtk, nFrames, 1, fVerbose );
+    else if ( Abc_NtkIsStrash(pNtk) )
+        Abc_NtkCycleInitState( pNtk, nFrames, 0, fVerbose );
+    else
+        Abc_NtkCycleInitStateSop( pNtk, nFrames, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: cycle [-F num] [-xvh]\n" );
+    Abc_Print( -2, "\t         cycles sequential circuit for the given number of timeframes\n" );
+    Abc_Print( -2, "\t         to derive a new initial state (which may be on the envelope)\n" );
+    Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-x     : use x-valued primary inputs [default = %s]\n", fUseXval? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandXsim( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int nFrames;
+    int fXInputs;
+    int fXState;
+    int fVerbose;
+    extern void Abc_NtkXValueSimulate( Abc_Ntk_t * pNtk, int nFrames, int fXInputs, int fXState, int fVerbose );
+    // set defaults
+    nFrames    = 10;
+    fXInputs   =  0;
+    fXState    =  0;
+    fVerbose   =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Fisvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'i':
+            fXInputs ^= 1;
+            break;
+        case 's':
+            fXState ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Only works for strashed networks.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkLatchNum(pNtk) )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    Abc_NtkXValueSimulate( pNtk, nFrames, fXInputs, fXState, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: xsim [-F num] [-isvh]\n" );
+    Abc_Print( -2, "\t         performs X-valued simulation of the AIG\n" );
+    Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-i     : toggle X-valued representation of inputs [default = %s]\n", fXInputs? "yes": "no" );
+    Abc_Print( -2, "\t-s     : toggle X-valued representation of state [default = %s]\n", fXState? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSim( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int fNew;
+    int fComb;
+    int nFrames;
+    int nWords;
+    int TimeOut;
+    int fMiter;
+    int fVerbose;
+    char * pFileSim;
+    extern int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int TimeOut, int fNew, int fMiter, int fVerbose, char * pFileSim );
+    // set defaults
+    fNew       =  0;
+    fComb      =  0;
+    nFrames    = 32;
+    nWords     =  8;
+    TimeOut    = 30;
+    fMiter     =  1;
+    fVerbose   =  0;
+    pFileSim   = NULL;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FWTAnmvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nWords < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            TimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( TimeOut < 0 )
+                goto usage;
+            break;
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pFileSim = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'n':
+            fNew ^= 1;
+            break;
+        case 'm':
+            fMiter ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Only works for strashed networks.\n" );
+        return 1;
+    }
+    if ( pFileSim != NULL && Abc_NtkLatchNum(pNtk) )
+    {
+        Abc_Print( -1, "Currently simulation with user-specified patterns works only for comb miters.\n" );
+        return 1;
+    }
+    ABC_FREE( pNtk->pSeqModel );
+    pAbc->Status = Abc_NtkDarSeqSim( pNtk, nFrames, nWords, TimeOut, fNew, fMiter, fVerbose, pFileSim );
+    Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: sim [-FWT num] [-A file] [-nmvh]\n" );
+    Abc_Print( -2, "\t          performs random simulation of the sequential miter\n" );
+    Abc_Print( -2, "\t-F num  : the number of frames to simulate [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-W num  : the number of words to simulate [default = %d]\n", nWords );
+    Abc_Print( -2, "\t-T num  : approximate runtime limit in seconds [default = %d]\n", TimeOut );
+    Abc_Print( -2, "\t-A file : text file name with user's patterns [default = random simulation]\n" );
+    Abc_Print( -2, "\t          (patterns are listed, one per line, as sequences of 0s and 1s)\n" );
+    Abc_Print( -2, "\t-n      : toggle new vs. old implementation [default = %s]\n", fNew? "new": "old" );
+    Abc_Print( -2, "\t-m      : toggle miter vs. any circuit [default = %s]\n", fMiter? "miter": "circuit" );
+    Abc_Print( -2, "\t-v      : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h      : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSim3( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern int Abc_NtkDarSeqSim3( Abc_Ntk_t * pNtk, Ssw_RarPars_t * pPars );
+    Ssw_RarPars_t Pars, * pPars = &Pars;
+    Abc_Ntk_t * pNtkRes, * pNtk = Abc_FrameReadNtk(pAbc);
+    Vec_Ptr_t * vSeqModelVec; 
+    int c;
+    Ssw_RarSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FWBRSNTGadivzh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFrames < 0 )
+                goto usage;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nWords < 0 )
+                goto usage;
+            break;
+        case 'B':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBinSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBinSize < 0 )
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRounds = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRounds < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRestart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRestart < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRandSeed = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRandSeed < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeOut < 0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeOutGap = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeOutGap < 0 )
+                goto usage;
+            break;
+        case 'a':
+            pPars->fSolveAll ^= 1;
+            break;
+        case 'd':
+            pPars->fDropSatOuts ^= 1;
+            break;
+        case 'i':
+            pPars->fSetLastState ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'z':
+            pPars->fNotVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Only works for strashed networks.\n" );
+        return 1;
+    }
+    if ( Abc_NtkLatchNum(pNtk) == 0 )
+    {
+        Abc_Print( -1, "Only works for sequential networks.\n" );
+        return 1;
+    }
+    ABC_FREE( pNtk->pSeqModel );
+    pAbc->Status = Abc_NtkDarSeqSim3( pNtk, pPars );
+    Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel );
+    vSeqModelVec = pNtk->vSeqModelVec;  pNtk->vSeqModelVec = NULL;
+    if ( pPars->fSetLastState && pAbc->pNtkCur->pData )
+    {
+        Abc_Obj_t * pObj;
+        Vec_Int_t * vInit = (Vec_Int_t *)pAbc->pNtkCur->pData;
+        pAbc->pNtkCur->pData = NULL;
+        Abc_NtkForEachLatch( pAbc->pNtkCur, pObj, c )
+            if ( Vec_IntEntry(vInit, c) )
+                Abc_LatchSetInit1( pObj );
+        Vec_IntFree( vInit );
+        pNtkRes = Abc_NtkRestrashZero( pAbc->pNtkCur, 0 );
+        if ( pNtkRes == NULL )
+        {
+            Abc_Print( -1, "Removing SAT outputs has failed.\n" );
+            return 1;
+        }
+        Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+        pNtk = Abc_FrameReadNtk(pAbc);
+    }
+    if ( pPars->fSolveAll && pPars->fDropSatOuts )
+    {
+        if ( vSeqModelVec == NULL )
+            Abc_Print( 1,"The array of counter-examples is not available.\n" );
+        else if ( Vec_PtrSize(vSeqModelVec) != Abc_NtkPoNum(pNtk) )
+            Abc_Print( 1,"The array size does not match the number of outputs.\n" );
+        else
+        {
+            extern void Abc_NtkDropSatOutputs( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCexes, int fVerbose );
+            Abc_NtkDropSatOutputs( pNtk, vSeqModelVec, pPars->fVerbose );
+            pNtkRes = Abc_NtkDarLatchSweep( pNtk, 1, 1, 1, 0, -1, -1, 0, 0 );
+            if ( pNtkRes == NULL )
+            {
+                Abc_Print( -1, "Removing SAT outputs has failed.\n" );
+                return 1;
+            }
+            Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+        }
+    }
+    if ( vSeqModelVec )
+    {
+        Abc_FrameReplaceCexVec( pAbc, &vSeqModelVec );
+        pAbc->nFrames = -1;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: sim3 [-FWBRSNTG num] [-advzh]\n" );
+    Abc_Print( -2, "\t         performs random simulation of the sequential miter\n" );
+    Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n",                         pPars->nFrames );
+    Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n",                          pPars->nWords );
+    Abc_Print( -2, "\t-B num : the number of flops in one bin [default = %d]\n",                           pPars->nBinSize );
+    Abc_Print( -2, "\t-R num : the number of simulation rounds [default = %d]\n",                          pPars->nRounds );
+    Abc_Print( -2, "\t-S num : the number of rounds before a restart [default = %d]\n",                    pPars->nRestart );
+    Abc_Print( -2, "\t-N num : random number seed (1 <= num <= 1000) [default = %d]\n",                    pPars->nRandSeed );
+    Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n",                     pPars->TimeOut );
+    Abc_Print( -2, "\t-G num : approximate runtime gap in seconds since the last CEX [default = %d]\n",    pPars->TimeOutGap );
+    Abc_Print( -2, "\t-a     : toggle solving all outputs (do not stop when one is SAT) [default = %s]\n", pPars->fSolveAll?    "yes": "no" );
+    Abc_Print( -2, "\t-d     : toggle dropping (replacing by 0) SAT outputs [default = %s]\n",             pPars->fDropSatOuts? "yes": "no" );
+    Abc_Print( -2, "\t-i     : toggle changing init state to a last rare state [default = %s]\n",          pPars->fVerbose?     "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n",                      pPars->fVerbose?     "yes": "no" );
+    Abc_Print( -2, "\t-z     : toggle suppressing report about solved outputs [default = %s]\n",           pPars->fNotVerbose?  "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDarPhase( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int nFrames, nPref;
+    int fIgnore;
+    int fPrint;
+    int fUpdateCex;
+    int c, fVerbose;
+    extern Abc_Ntk_t * Abc_NtkPhaseAbstract( Abc_Ntk_t * pNtk, int nFrames, int nPref, int fIgnore, int fPrint, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nFrames     = 0;
+    nPref       = 0;
+    fIgnore     = 0;
+    fPrint      = 0;
+    fUpdateCex  = 0;
+    fVerbose    = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FPipcvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nPref = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nPref < 0 )
+                goto usage;
+            break;
+        case 'i':
+            fIgnore ^= 1;
+            break;
+        case 'p':
+            fPrint ^= 1;
+            break;
+        case 'c':
+            fUpdateCex ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Only works for structrally hashed networks.\n" );
+        return 1;
+    }
+    if ( fUpdateCex )
+    {
+        Abc_Cex_t * pCexNew;
+        if ( pAbc->pCex == NULL )
+        {
+            Abc_Print( -1, "Counter-example is not available.\n" );
+            return 1;
+        }
+        if ( pAbc->pCex->nPis % Abc_NtkPiNum(pNtk) != 0 )
+        {
+            Abc_Print( -1, "PI count of the CEX is not a multiple of PI count of the current AIG.\n" );
+            return 1;
+        }
+        pCexNew = Abc_CexTransformPhase( pAbc->pCex, Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkLatchNum(pNtk) );
+        {
+            Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 );
+            Gia_Man_t * pGia = Gia_ManFromAig( pAig );
+            int iPo = Gia_ManSetFailedPoCex( pGia, pCexNew );
+            Gia_ManStop( pGia );
+            Aig_ManStop( pAig );
+            if ( iPo == -1 )
+            {
+                Abc_Print( -1, "The counter-example does not fail any of the outputs of the original AIG.\n" );
+                return 1;
+            }
+        }
+        Abc_FrameReplaceCex( pAbc, &pCexNew );
+        return 0;
+    }
+    if ( !Abc_NtkLatchNum(pNtk) )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    if ( fPrint )
+    {
+        Abc_NtkPhaseAbstract( pNtk, 0, nPref, fIgnore, 1, fVerbose );
+        return 0;
+    }
+    // modify the current network
+    pNtkRes = Abc_NtkPhaseAbstract( pNtk, nFrames, nPref, fIgnore, 0, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+//        Abc_Print( -1, "Phase abstraction has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: phase [-FP <num>] [-ipcvh]\n" );
+    Abc_Print( -2, "\t         performs sequential cleanup of the current network\n" );
+    Abc_Print( -2, "\t         by removing nodes and latches that do not feed into POs\n" );
+    Abc_Print( -2, "\t-F num : the number of frames to abstract [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-P num : the number of prefix frames to skip [default = %d]\n", nPref );
+    Abc_Print( -2, "\t-i     : toggle ignoring the initial state [default = %s]\n", fIgnore? "yes": "no" );
+    Abc_Print( -2, "\t-p     : toggle printing statistics about generators [default = %s]\n", fPrint? "yes": "no" );
+    Abc_Print( -2, "\t-c     : update the current CEX derived for a new AIG after \"phase\"\n" );
+    Abc_Print( -2, "\t         to match the current AIG (the one before \"phase\") [default = %s]\n", fUpdateCex? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSynch( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtkRes, * pNtk1, * pNtk2, * pNtk;
+    char ** pArgvNew;
+    int nArgcNew;
+    int fDelete1, fDelete2;
+    int c;
+    int nWords;
+    int fVerbose;
+
+    extern Abc_Ntk_t * Abc_NtkDarSynch( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nWords, int fVerbose );
+    extern Abc_Ntk_t * Abc_NtkDarSynchOne( Abc_Ntk_t * pNtk, int nWords, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nWords   =  32;
+    fVerbose =   1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Wvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nWords <= 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( nArgcNew == 0 )
+    {
+        if ( pNtk == NULL )
+        {
+            Abc_Print( -1, "Empty network.\n" );
+            return 1;
+        }
+        pNtkRes = Abc_NtkDarSynchOne( pNtk, nWords, fVerbose );
+    }
+    else
+    {
+        if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+            return 1;
+        if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 )
+        {
+            if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+            if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+            Abc_Print( -1, "The network has no latches..\n" );
+            return 0;
+        }
+
+        // modify the current network
+        pNtkRes = Abc_NtkDarSynch( pNtk1, pNtk2, nWords, fVerbose );
+        if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+        if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+    }
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Synchronization has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: synch [-W <num>] [-vh] <file1> <file2>\n" );
+    Abc_Print( -2, "\t         derives and applies synchronization sequence\n" );
+    Abc_Print( -2, "\t-W num : the number of simulation words [default = %d]\n", nWords );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\tfile1  : (optional) the file with the first design\n");
+    Abc_Print( -2, "\tfile2  : (optional) the file with the second design\n\n");
+    Abc_Print( -2, "\t         If no designs are given on the command line,\n" );
+    Abc_Print( -2, "\t         assumes the current network has no initial state,\n" );
+    Abc_Print( -2, "\t         derives synchronization sequence and applies it.\n\n" );
+    Abc_Print( -2, "\t         If two designs are given on the command line\n" );
+    Abc_Print( -2, "\t         assumes both of them have no initial state,\n" );
+    Abc_Print( -2, "\t         derives sequences for both designs, synchorinizes\n" );
+    Abc_Print( -2, "\t         them, and creates SEC miter comparing two designs.\n\n" );
+    Abc_Print( -2, "\t         If only one design is given on the command line,\n" );
+    Abc_Print( -2, "\t         considers the second design to be the current network,\n" );
+    Abc_Print( -2, "\t         and derives SEC miter for them, as described above.\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandClockGate( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Cgt_Par_t Pars, * pPars = &Pars;
+    Abc_Ntk_t * pNtkRes, * pNtk, * pNtkCare;
+    int c;
+
+    extern Abc_Ntk_t * Abc_NtkDarClockGate( Abc_Ntk_t * pNtk, Abc_Ntk_t * pCare, Cgt_Par_t * pPars );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Cgt_SetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "LNDCVKavwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nLevelMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLevelMax <= 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nCandMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nCandMax <= 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nOdcMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nOdcMax <= 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nConfMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nConfMax <= 0 )
+                goto usage;
+            break;
+        case 'V':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nVarsMin = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nVarsMin <= 0 )
+                goto usage;
+            break;
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFlopsMin = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFlopsMin <= 0 )
+                goto usage;
+            break;
+        case 'a':
+            pPars->fAreaOnly ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( argc == globalUtilOptind + 1 )
+    {
+        pNtkCare = Io_Read( argv[globalUtilOptind], Io_ReadFileType(argv[globalUtilOptind]), 1, 0 );
+        if ( pNtkCare == NULL )
+        {
+            Abc_Print( -1, "Reading care network has failed.\n" );
+            return 1;
+        }
+        // modify the current network
+        pNtkRes = Abc_NtkDarClockGate( pNtk, pNtkCare, pPars );
+        Abc_NtkDelete( pNtkCare );
+    }
+    else if ( argc == globalUtilOptind )
+    {
+        pNtkRes = Abc_NtkDarClockGate( pNtk, NULL, pPars );
+    }
+    else
+    {
+        Abc_Print( -1, "Wrong number of arguments.\n" );
+        return 0;
+    }
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Clock gating has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: clockgate [-LNDCVK <num>] [-avwh] <file>\n" );
+    Abc_Print( -2, "\t         sequential clock gating with observability don't-cares\n" );
+    Abc_Print( -2, "\t-L num : max level number of a clock gate [default = %d]\n", pPars->nLevelMax );
+    Abc_Print( -2, "\t-N num : max number of candidates for a flop [default = %d]\n", pPars->nCandMax );
+    Abc_Print( -2, "\t-D num : max number of ODC levels to consider [default = %d]\n", pPars->nOdcMax );
+    Abc_Print( -2, "\t-C num : max number of conflicts at a node [default = %d]\n", pPars->nConfMax );
+    Abc_Print( -2, "\t-V num : min number of vars to recycle SAT solver [default = %d]\n", pPars->nVarsMin );
+    Abc_Print( -2, "\t-K num : min number of flops to recycle SAT solver [default = %d]\n", pPars->nFlopsMin );
+    Abc_Print( -2, "\t-a     : toggle minimizing area-only [default = %s]\n", pPars->fAreaOnly? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle even more detailed output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\tfile   : (optional) constraints for primary inputs and register outputs\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandExtWin( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtkRes, * pNtk;
+    int c;
+    int nObjId;
+    int nDist;
+    int fVerbose;
+
+    extern Abc_Ntk_t * Abc_NtkDarExtWin( Abc_Ntk_t * pNtk, int nObjId, int nDist, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nObjId   = -1;
+    nDist    =  5;
+    fVerbose =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "NDvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nObjId = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nObjId <= 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nDist = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nDist <= 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Only works for structrally hashed networks.\n" );
+        return 1;
+    }
+
+    if ( argc != globalUtilOptind )
+    {
+        Abc_Print( -1, "Not enough command-line arguments.\n" );
+        return 1;
+    }
+    // modify the current network
+    pNtkRes = Abc_NtkDarExtWin( pNtk, nObjId, nDist, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Extracting sequential window has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: extwin [-ND <num>] [-vh]\n" );
+    Abc_Print( -2, "\t         extracts sequential window from the AIG\n" );
+    Abc_Print( -2, "\t-N num : the ID of the object to use as the center [default = %d]\n", nObjId );
+    Abc_Print( -2, "\t-D num : the \"radius\" of the window [default = %d]\n", nDist );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandInsWin( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtkRes, * pNtk, * pNtkCare;
+    int c;
+    int nObjId;
+    int nDist;
+    int fVerbose;
+
+    extern Abc_Ntk_t * Abc_NtkDarInsWin( Abc_Ntk_t * pNtk, Abc_Ntk_t * pWnd, int nObjId, int nDist, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nObjId   = -1;
+    nDist    =  5;
+    fVerbose =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "NDvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nObjId = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nObjId <= 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nDist = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nDist <= 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Only works for structrally hashed networks.\n" );
+        return 1;
+    }
+
+    if ( argc != globalUtilOptind + 1 )
+    {
+        Abc_Print( -1, "Not enough command-line arguments.\n" );
+        return 1;
+    }
+    pNtkCare = Io_Read( argv[globalUtilOptind], Io_ReadFileType(argv[globalUtilOptind]), 1, 0 );
+    if ( pNtkCare == NULL )
+    {
+        Abc_Print( -1, "Reading care network has failed.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtkCare) )
+    {
+        Abc_Ntk_t * pNtkTemp;
+        pNtkCare = Abc_NtkStrash( pNtkTemp = pNtkCare, 0, 1, 0 );
+        Abc_NtkDelete( pNtkTemp );
+    }
+    // modify the current network
+    pNtkRes = Abc_NtkDarInsWin( pNtk, pNtkCare, nObjId, nDist, fVerbose );
+    Abc_NtkDelete( pNtkCare );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Inserting sequential window has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: inswin [-ND <num>] [-vh] <file>\n" );
+    Abc_Print( -2, "\t         inserts sequential window into the AIG\n" );
+    Abc_Print( -2, "\t-N num : the ID of the object to use as the center [default = %d]\n", nObjId );
+    Abc_Print( -2, "\t-D num : the \"radius\" of the window [default = %d]\n", nDist );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\tfile   : file with the AIG to be inserted\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPermute( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Abc_Ntk_t * Abc_NtkRestrashRandom( Abc_Ntk_t * pNtk );
+    Abc_Ntk_t * pNtk = pAbc->pNtkCur, * pNtkRes = NULL;
+    char * pFlopPermFile = NULL;
+    int fInputs = 1;
+    int fOutputs = 1;
+    int fFlops = 1;
+    int fNodes = 1;
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Fiofnh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pFlopPermFile = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'i':
+            fInputs ^= 1;
+            break;
+        case 'o':
+            fOutputs ^= 1;
+            break;
+        case 'f':
+            fFlops ^= 1;
+            break;
+        case 'n':
+            fNodes ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            Abc_Print( -2, "Unknown switch.\n");
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( fNodes && !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "To permute nodes, the network should be structurally hashed.\n" );
+        return 1;
+    }
+    if ( fNodes )
+        pNtkRes = Abc_NtkRestrashRandom( pNtk );
+    else
+        pNtkRes = Abc_NtkDup( pNtk );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command \"permute\" has failed.\n" );
+        return 1;
+    }
+    Abc_NtkPermute( pNtkRes, fInputs, fOutputs, fFlops, pFlopPermFile );
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: permute [-iofnh] [-F filename]\n" );
+    Abc_Print( -2, "\t                performs random permutation of inputs/outputs/flops\n" );
+    Abc_Print( -2, "\t-i            : toggle permuting primary inputs [default = %s]\n", fInputs? "yes": "no" );
+    Abc_Print( -2, "\t-o            : toggle permuting primary outputs [default = %s]\n", fOutputs? "yes": "no" );
+    Abc_Print( -2, "\t-f            : toggle permuting flip-flops [default = %s]\n", fFlops? "yes": "no" );
+    Abc_Print( -2, "\t-n            : toggle deriving new topological ordering of nodes [default = %s]\n", fNodes? "yes": "no" );
+    Abc_Print( -2, "\t-h            : print the command usage\n");
+    Abc_Print( -2, "\t-F <filename> : (optional) file with the flop permutation\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandUnpermute( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = pAbc->pNtkCur, * pNtkRes = NULL;
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            Abc_Print( -2, "Unknown switch.\n");
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    pNtkRes = Abc_NtkDup( pNtk );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Command \"unpermute\" has failed.\n" );
+        return 1;
+    }
+    Abc_NtkUnpermute( pNtkRes );
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: unpermute [-h]\n" );
+    Abc_Print( -2, "\t        restores inputs/outputs/flops before the last permutation\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCubeEnum( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Abc_EnumerateCubeStates();
+    extern void Abc_EnumerateCubeStatesZdd();
+    int c, fZddAlgo = 0, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "zvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'z':
+            fZddAlgo ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            Abc_Print( -2, "Unknown switch.\n");
+            goto usage;
+        }
+    }
+    if ( fZddAlgo )
+        Abc_EnumerateCubeStatesZdd();
+    else
+        Abc_EnumerateCubeStates();
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: cubeenum [-vh]\n" );
+    Abc_Print( -2, "\t         enumerates reachable states of 2x2x2 cube\n" );
+    Abc_Print( -2, "\t         (http://en.wikipedia.org/wiki/Pocket_Cube)\n" );
+    Abc_Print( -2, "\t-z     : toggle using ZDD-based algorithm [default = %s]\n", fZddAlgo? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char Buffer[16];
+    Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
+    int fDelete1, fDelete2;
+    char ** pArgvNew;
+    int nArgcNew;
+    int c;
+    int fSat;
+    int fVerbose;
+    int nSeconds;
+    int nPartSize;
+    int nConfLimit;
+    int nInsLimit;
+    int fPartition;
+    int fIgnoreNames;
+
+    extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit );
+    extern void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose );
+    extern void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose );
+    extern void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fSat     =  0;
+    fVerbose =  0;
+    nSeconds = 20;
+    nPartSize  = 0;
+    nConfLimit = 10000;
+    nInsLimit  = 0;
+    fPartition = 0;
+    fIgnoreNames = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "TCIPpsnvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nSeconds = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nSeconds < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfLimit < 0 )
+                goto usage;
+            break;
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nInsLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nInsLimit < 0 )
+                goto usage;
+            break;
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nPartSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nPartSize < 0 )
+                goto usage;
+            break;
+        case 'p':
+            fPartition ^= 1;
+            break;
+        case 's':
+            fSat ^= 1;
+            break;
+        case 'n':
+            fIgnoreNames ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk && pNtk->vPhases != NULL )
+    {
+        Abc_Print( -1, "Cannot compare networks with phases defined.\n" );
+        return 1;
+    }
+
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+        return 1;
+
+    if ( fIgnoreNames )
+    {
+        if ( !fDelete1 )
+        {
+            pNtk1 = Abc_NtkStrash( pNtk1, 0, 1, 0 );
+            fDelete1 = 1;
+        }
+        if ( !fDelete2 )
+        {
+            pNtk2 = Abc_NtkStrash( pNtk2, 0, 1, 0 );
+            fDelete2 = 1;
+        }
+        Abc_NtkShortNames( pNtk1 );
+        Abc_NtkShortNames( pNtk2 );
+    }
+
+    // perform equivalence checking
+    if ( fPartition )
+        Abc_NtkCecFraigPartAuto( pNtk1, pNtk2, nSeconds, fVerbose );
+    else if ( nPartSize )
+        Abc_NtkCecFraigPart( pNtk1, pNtk2, nSeconds, nPartSize, fVerbose );
+    else if ( fSat )
+        Abc_NtkCecSat( pNtk1, pNtk2, nConfLimit, nInsLimit );
+    else
+        Abc_NtkCecFraig( pNtk1, pNtk2, nSeconds, fVerbose );
+
+    if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+    if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+    return 0;
+
+usage:
+    if ( nPartSize == 0 )
+        strcpy( Buffer, "unused" );
+    else
+        sprintf(Buffer, "%d", nPartSize );
+    Abc_Print( -2, "usage: cec [-T num] [-C num] [-I num] [-P num] [-psnvh] <file1> <file2>\n" );
+    Abc_Print( -2, "\t         performs combinational equivalence checking\n" );
+    Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds );
+    Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n",    nConfLimit );
+    Abc_Print( -2, "\t-I num : limit on the number of clause inspections [default = %d]\n", nInsLimit );
+    Abc_Print( -2, "\t-P num : partition size for multi-output networks [default = %s]\n", Buffer );
+    Abc_Print( -2, "\t-p     : toggle automatic partitioning [default = %s]\n", fPartition? "yes": "no" );
+    Abc_Print( -2, "\t-s     : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" );
+    Abc_Print( -2, "\t-n     : toggle ignoring names when matching CIs/COs [default = %s]\n", fIgnoreNames? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\tfile1  : (optional) the file with the first network\n");
+    Abc_Print( -2, "\tfile2  : (optional) the file with the second network\n");
+    Abc_Print( -2, "\t         if no files are given, uses the current network and its spec\n");
+    Abc_Print( -2, "\t         if one file is given, uses the current network and the file\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDCec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
+    int fDelete1, fDelete2;
+    char ** pArgvNew;
+    int nArgcNew;
+    int c;
+    int fSat;
+    int fVerbose;
+    int nSeconds;
+    int nConfLimit;
+    int nInsLimit;
+    int fPartition;
+    int fMiter;
+
+    extern int Abc_NtkDSat( Abc_Ntk_t * pNtk, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fAlignPol, int fAndOuts, int fNewSolver, int fVerbose );
+    extern int Abc_NtkDarCec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int fPartition, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fSat     =  0;
+    fVerbose =  0;
+    nSeconds = 20;
+    nConfLimit = 10000;
+    nInsLimit  = 0;
+    fPartition = 0;
+    fMiter     = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "TCIpmsvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nSeconds = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nSeconds < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfLimit < 0 )
+                goto usage;
+            break;
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nInsLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nInsLimit < 0 )
+                goto usage;
+            break;
+        case 'p':
+            fPartition ^= 1;
+            break;
+        case 'm':
+            fMiter ^= 1;
+            break;
+        case 's':
+            fSat ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( fMiter )
+    {
+        if ( pNtk == NULL )
+        {
+            Abc_Print( -1, "Empty network.\n" );
+            return 1;
+        }
+        if ( Abc_NtkIsStrash(pNtk) )
+        {
+            pNtk1 = pNtk;
+            fDelete1 = 0;
+        }
+        else
+        {
+            pNtk1 = Abc_NtkStrash( pNtk, 0, 1, 0 );
+            fDelete1 = 1;
+        }
+        pNtk2 = NULL;
+        fDelete2 = 0;
+    }
+    else
+    {
+        if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+            return 1;
+    }
+
+    if ( (pNtk1 && Abc_NtkLatchNum(pNtk1)) || (pNtk2 && Abc_NtkLatchNum(pNtk2)) )
+    {
+        if ( pNtk1 && fDelete1 ) Abc_NtkDelete( pNtk1 );
+        if ( pNtk2 && fDelete2 ) Abc_NtkDelete( pNtk2 );
+        Abc_Print( -1, "Currently this command only works for networks without latches. Run \"comb\".\n" );
+        return 1;
+    }
+
+    // perform equivalence checking
+    if ( fSat && fMiter )
+        Abc_NtkDSat( pNtk1, nConfLimit, nInsLimit, 0, 0, 0, 0, 0, 0, fVerbose );
+    else
+        Abc_NtkDarCec( pNtk1, pNtk2, nConfLimit, fPartition, fVerbose );
+
+    if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+    if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dcec [-T num] [-C num] [-I num] [-mpsvh] <file1> <file2>\n" );
+    Abc_Print( -2, "\t         performs combinational equivalence checking\n" );
+    Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds );
+    Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n",    nConfLimit );
+    Abc_Print( -2, "\t-I num : limit on the number of clause inspections [default = %d]\n", nInsLimit );
+    Abc_Print( -2, "\t-m     : toggle working on two networks or a miter [default = %s]\n", fMiter? "miter": "two networks" );
+    Abc_Print( -2, "\t-p     : toggle automatic partitioning [default = %s]\n", fPartition? "yes": "no" );
+    Abc_Print( -2, "\t-s     : toggle \"SAT only\" (miter) or \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" );
+    Abc_Print( -2, "\t-v     : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\tfile1  : (optional) the file with the first network\n");
+    Abc_Print( -2, "\tfile2  : (optional) the file with the second network\n");
+    Abc_Print( -2, "\t         if no files are given, uses the current network and its spec\n");
+    Abc_Print( -2, "\t         if one file is given, uses the current network and the file\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDSec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Fra_Sec_t SecPar, * pSecPar = &SecPar;
+    Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
+    int fDelete1, fDelete2;
+    char ** pArgvNew;
+    int nArgcNew;
+    int c;
+    int fIgnoreNames;
+
+    extern void Fra_SecSetDefaultParams( Fra_Sec_t * p );
+    extern int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Fra_Sec_t * p );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Fra_SecSetDefaultParams( pSecPar );
+    pSecPar->TimeLimit = 0;
+    fIgnoreNames = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FTarmfnwvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pSecPar->nFramesMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pSecPar->nFramesMax < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pSecPar->TimeLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pSecPar->TimeLimit < 0 )
+                goto usage;
+            break;
+        case 'a':
+            pSecPar->fPhaseAbstract ^= 1;
+            break;
+        case 'r':
+            pSecPar->fRetimeFirst ^= 1;
+            break;
+        case 'm':
+            pSecPar->fRetimeRegs ^= 1;
+            break;
+        case 'f':
+            pSecPar->fFraiging ^= 1;
+            break;
+        case 'n':
+            fIgnoreNames ^= 1;
+            break;
+        case 'w':
+            pSecPar->fVeryVerbose ^= 1;
+            break;
+        case 'v':
+            pSecPar->fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+        return 1;
+    if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 )
+    {
+        if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+        if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+        Abc_Print( -1, "The network has no latches. Used combinational command \"cec\".\n" );
+        return 0;
+    }
+
+    if ( fIgnoreNames )
+    {
+        if ( !fDelete1 )
+        {
+            pNtk1 = Abc_NtkStrash( pNtk1, 0, 1, 0 );
+            fDelete1 = 1;
+        }
+        if ( !fDelete2 )
+        {
+            pNtk2 = Abc_NtkStrash( pNtk2, 0, 1, 0 );
+            fDelete2 = 1;
+        }
+        Abc_NtkShortNames( pNtk1 );
+        Abc_NtkShortNames( pNtk2 );
+    }
+
+    // perform verification
+    Abc_NtkDarSec( pNtk1, pNtk2, pSecPar );
+
+    if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+    if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dsec [-F num] [-T num] [-armfnwvh] <file1> <file2>\n" );
+    Abc_Print( -2, "\t         performs inductive sequential equivalence checking\n" );
+    Abc_Print( -2, "\t-F num : the limit on the depth of induction [default = %d]\n", pSecPar->nFramesMax );
+    Abc_Print( -2, "\t-T num : the approximate runtime limit (in seconds) [default = %d]\n", pSecPar->TimeLimit );
+    Abc_Print( -2, "\t-a     : toggles the use of phase abstraction [default = %s]\n", pSecPar->fPhaseAbstract? "yes": "no" );
+    Abc_Print( -2, "\t-r     : toggles forward retiming at the beginning [default = %s]\n", pSecPar->fRetimeFirst? "yes": "no" );
+    Abc_Print( -2, "\t-m     : toggles min-register retiming [default = %s]\n", pSecPar->fRetimeRegs? "yes": "no" );
+    Abc_Print( -2, "\t-f     : toggles the internal use of fraiging [default = %s]\n", pSecPar->fFraiging? "yes": "no" );
+    Abc_Print( -2, "\t-n     : toggle ignoring names when matching PIs/POs [default = %s]\n", fIgnoreNames? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggles verbose output [default = %s]\n", pSecPar->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggles additional verbose output [default = %s]\n", pSecPar->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\tfile1  : (optional) the file with the first network\n");
+    Abc_Print( -2, "\tfile2  : (optional) the file with the second network\n");
+    Abc_Print( -2, "\t         if no files are given, uses the current network and its spec\n");
+    Abc_Print( -2, "\t         if one file is given, uses the current network and the file\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDProve( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Fra_Sec_t SecPar, * pSecPar = &SecPar;
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    char * pLogFileName = NULL;
+    int nBmcFramesMax = 20;
+    int nBmcConfMax = 2000;
+
+    extern void Fra_SecSetDefaultParams( Fra_Sec_t * p );
+    extern int Abc_NtkDarProve( Abc_Ntk_t * pNtk, Fra_Sec_t * pSecPar, int nBmcFramesMax, int nBmcConfMax );
+    // set defaults
+    Fra_SecSetDefaultParams( pSecPar );
+//    pSecPar->TimeLimit = 300;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "cbAEFCGDVBRTLarmfijkoupwvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'c':
+            pSecPar->fTryComb ^= 1;
+            break;
+        case 'b':
+            pSecPar->fTryBmc ^= 1;
+            break;
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nBmcFramesMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nBmcFramesMax < 0 )
+                goto usage;
+            break;
+        case 'E':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-E\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nBmcConfMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nBmcConfMax < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pSecPar->nFramesMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pSecPar->nFramesMax < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pSecPar->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pSecPar->nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pSecPar->nBTLimitGlobal = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pSecPar->nBTLimitGlobal < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pSecPar->nBTLimitInter = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pSecPar->nBTLimitInter < 0 )
+                goto usage;
+            break;
+        case 'V':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pSecPar->nBddVarsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pSecPar->nBddVarsMax < 0 )
+                goto usage;
+            break;
+        case 'B':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pSecPar->nBddMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pSecPar->nBddMax < 0 )
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pSecPar->nBddIterMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pSecPar->nBddIterMax < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pSecPar->nPdrTimeout = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pSecPar->nPdrTimeout < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pLogFileName = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'a':
+            pSecPar->fPhaseAbstract ^= 1;
+            break;
+        case 'r':
+            pSecPar->fRetimeFirst ^= 1;
+            break;
+        case 'm':
+            pSecPar->fRetimeRegs ^= 1;
+            break;
+        case 'f':
+            pSecPar->fFraiging ^= 1;
+            break;
+        case 'i':
+            pSecPar->fInduction ^= 1;
+            break;
+        case 'j':
+            pSecPar->fInterpolation ^= 1;
+            break;
+        case 'k':
+            pSecPar->fInterSeparate ^= 1;
+            break;
+        case 'o':
+            pSecPar->fReorderImage ^= 1;
+            break;
+        case 'u':
+            pSecPar->fReadUnsolved ^= 1;
+            break;
+        case 'p':
+            pSecPar->fUsePdr ^= 1;
+            break;
+        case 'w':
+            pSecPar->fVeryVerbose ^= 1;
+            break;
+        case 'v':
+            pSecPar->fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for structrally hashed networks. Run \"st\".\n" );
+        return 0;
+    }
+
+    // perform verification
+    pAbc->Status = Abc_NtkDarProve( pNtk, pSecPar, nBmcFramesMax, nBmcConfMax );
+    Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel );
+    if ( pLogFileName )
+        Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "dprove" );
+
+    // read back the resulting unsolved reduced sequential miter
+    if ( pSecPar->fReadUnsolved && pSecPar->nSMnumber >= 0 )
+    {
+        char FileName[100];
+        sprintf(FileName, "sm%02d.aig", pSecPar->nSMnumber );
+        pNtk = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 );
+        if ( pNtk == NULL )
+            Abc_Print( -1, "Cannot read back unsolved reduced sequential miter \"%s\",\n", FileName );
+        else
+            Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dprove [-AEFCGDVBRT num] [-L file] [-cbarmfijoupvwh]\n" );
+    Abc_Print( -2, "\t         performs SEC on the sequential miter\n" );
+    Abc_Print( -2, "\t-A num : the limit on the depth of BMC [default = %d]\n", nBmcFramesMax );
+    Abc_Print( -2, "\t-E num : the conflict limit during BMC [default = %d]\n", nBmcConfMax );
+    Abc_Print( -2, "\t-F num : the limit on the depth of induction [default = %d]\n", pSecPar->nFramesMax );
+    Abc_Print( -2, "\t-C num : the conflict limit at a node during induction [default = %d]\n", pSecPar->nBTLimit );
+    Abc_Print( -2, "\t-G num : the global conflict limit during induction [default = %d]\n", pSecPar->nBTLimitGlobal );
+    Abc_Print( -2, "\t-D num : the conflict limit during interpolation [default = %d]\n", pSecPar->nBTLimitInter );
+    Abc_Print( -2, "\t-V num : the flop count limit for BDD-based reachablity [default = %d]\n", pSecPar->nBddVarsMax );
+    Abc_Print( -2, "\t-B num : the BDD size limit in BDD-based reachablity [default = %d]\n", pSecPar->nBddMax );
+    Abc_Print( -2, "\t-R num : the max number of reachability iterations [default = %d]\n", pSecPar->nBddIterMax );
+    Abc_Print( -2, "\t-T num : the timeout for property directed reachability [default = %d]\n", pSecPar->nPdrTimeout );
+    Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" );
+    Abc_Print( -2, "\t-c     : toggles using CEC before attempting SEC [default = %s]\n", pSecPar->fTryComb? "yes": "no" );
+    Abc_Print( -2, "\t-b     : toggles using BMC before attempting SEC [default = %s]\n", pSecPar->fTryBmc? "yes": "no" );
+    Abc_Print( -2, "\t-a     : toggles the use of phase abstraction [default = %s]\n", pSecPar->fPhaseAbstract? "yes": "no" );
+    Abc_Print( -2, "\t-r     : toggles forward retiming at the beginning [default = %s]\n", pSecPar->fRetimeFirst? "yes": "no" );
+    Abc_Print( -2, "\t-m     : toggles min-register retiming [default = %s]\n", pSecPar->fRetimeRegs? "yes": "no" );
+    Abc_Print( -2, "\t-f     : toggles the internal use of fraiging [default = %s]\n", pSecPar->fFraiging? "yes": "no" );
+    Abc_Print( -2, "\t-i     : toggles the use of induction [default = %s]\n", pSecPar->fInduction? "yes": "no" );
+    Abc_Print( -2, "\t-j     : toggles the use of interpolation [default = %s]\n", pSecPar->fInterpolation? "yes": "no" );
+    Abc_Print( -2, "\t-k     : toggles applying interpolation to each output [default = %s]\n", pSecPar->fInterSeparate? "yes": "no" );
+    Abc_Print( -2, "\t-o     : toggles using BDD variable reordering during image computation [default = %s]\n", pSecPar->fReorderImage? "yes": "no" );
+    Abc_Print( -2, "\t-u     : toggles reading back unsolved reduced sequential miter [default = %s]\n", pSecPar->fReadUnsolved? "yes": "no" );
+    Abc_Print( -2, "\t-p     : toggles trying property directed reachability in the end [default = %s]\n", pSecPar->fUsePdr? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggles verbose output [default = %s]\n", pSecPar->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggles additional verbose output [default = %s]\n", pSecPar->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\tCommand \"dprove\" can also be used for sequential synthesis (dprove -brjopu)\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbSec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
+    int fDelete1, fDelete2;
+    char ** pArgvNew;
+    int nArgcNew;
+    int fMiter, nFrames, fVerbose, c;
+
+    extern int Abc_NtkDarAbSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fMiter   = 1;
+    nFrames  = 2;
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Fmvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'm':
+            fMiter ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( fMiter )
+    {
+//        pNtk = Io_Read( argv[globalUtilOptind], Io_ReadFileType(argv[globalUtilOptind]), 1, 0 );
+        if ( argc == globalUtilOptind + 1 )
+        {
+            Abc_Print( -1, "The miter cannot be given on the command line. Use \"read\".\n" );
+            return 0;
+        }
+        if ( !Abc_NtkIsStrash(pNtk) )
+        {
+            Abc_Print( -1, "The miter should be structurally hashed. Use \"st\"\n" );
+            return 0;
+        }
+        if ( Abc_NtkDarAbSec( pNtk, NULL, nFrames, fVerbose ) == 1 )
+            pAbc->Status = 1;
+        else
+            pAbc->Status = -1;
+    }
+    else
+    {
+        pArgvNew = argv + globalUtilOptind;
+        nArgcNew = argc - globalUtilOptind;
+        if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+            return 1;
+        if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 )
+        {
+            if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+            if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+            Abc_Print( -1, "The network has no latches. Used combinational command \"cec\".\n" );
+            return 0;
+        }
+        // perform verification
+        if ( Abc_NtkDarAbSec( pNtk1, pNtk2, nFrames, fVerbose ) == 1 )
+            pAbc->Status = 1;
+        else
+            pAbc->Status = -1;
+        if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+        if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: absec [-F num] [-mv] <file1> <file2>\n" );
+    Abc_Print( -2, "\t         performs SEC by applying CEC to several timeframes\n" );
+    Abc_Print( -2, "\t-F num : the total number of timeframes to use [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-m     : toggles miter vs. two networks [default = %s]\n", fMiter? "miter": "two networks" );
+    Abc_Print( -2, "\t-v     : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\tfile1  : (optional) the file with the first network\n");
+    Abc_Print( -2, "\tfile2  : (optional) the file with the second network\n");
+    Abc_Print( -2, "\t         if no files are given, uses the current network and its spec\n");
+    Abc_Print( -2, "\t         if one file is given, uses the current network and the file\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSimSec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Ssw_Pars_t Pars, * pPars = &Pars;
+    Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
+    int fDelete1, fDelete2;
+    char ** pArgvNew;
+    int nArgcNew, c;
+    int fMiter;
+
+    extern int Abc_NtkDarSimSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Ssw_Pars_t * pPars );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fMiter = 1;
+    Ssw_ManSetDefaultParams( pPars );
+    pPars->fPartSigCorr = 1;
+    pPars->fVerbose     = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FDcymvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesK = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesK < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nIsleDist = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nIsleDist < 0 )
+                goto usage;
+            break;
+        case 'm':
+            fMiter ^= 1;
+            break;
+        case 'c':
+            pPars->fPartSigCorr ^= 1;
+            break;
+        case 'y':
+            pPars->fDumpSRInit ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( fMiter )
+    {
+//        Abc_Ntk_t * pNtkA, * pNtkB;
+        if ( !Abc_NtkIsStrash(pNtk) )
+        {
+            Abc_Print( -1, "This command works only for structrally hashed networks. Run \"st\".\n" );
+            return 0;
+        }
+        Abc_NtkDarSimSec( pNtk, NULL, pPars );
+/*
+        pNtkA = Abc_NtkDup( pNtk );
+        pNtkB = Abc_NtkDup( pNtk );
+        Abc_NtkDarSimSec( pNtkA, pNtkB, pPars );
+        Abc_NtkDelete( pNtkA );
+        Abc_NtkDelete( pNtkB );
+*/
+    }
+    else
+    {
+        pArgvNew = argv + globalUtilOptind;
+        nArgcNew = argc - globalUtilOptind;
+        if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+            return 1;
+        if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 )
+        {
+            if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+            if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+            Abc_Print( -1, "The network has no latches. Used combinational command \"cec\".\n" );
+            return 0;
+        }
+        // perform verification
+        Abc_NtkDarSimSec( pNtk1, pNtk2, pPars );
+        if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+        if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: simsec [-FD num] [-mcyv] <file1> <file2>\n" );
+    Abc_Print( -2, "\t         performs SEC using structural similarity\n" );
+    Abc_Print( -2, "\t-F num : the limit on the depth of induction [default = %d]\n", pPars->nFramesK );
+    Abc_Print( -2, "\t-D num : the distance for extending islands [default = %d]\n", pPars->nIsleDist );
+    Abc_Print( -2, "\t-m     : toggles miter vs. two networks [default = %s]\n", fMiter? "miter": "two networks" );
+    Abc_Print( -2, "\t-c     : uses partial vs. full signal correspondence [default = %s]\n", pPars->fPartSigCorr? "partial": "full" );
+    Abc_Print( -2, "\t-y     : dumps speculatively reduced miter of the classes [default = %s]\n", pPars->fDumpSRInit? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\tfile1  : (optional) the file with the first network\n");
+    Abc_Print( -2, "\tfile2  : (optional) the file with the second network\n");
+    Abc_Print( -2, "\t         if no files are given, uses the current network and its spec\n");
+    Abc_Print( -2, "\t         if one file is given, uses the current network and the file\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandMatch( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtk1, * pNtk2, * pNtkRes;
+    int fDelete1, fDelete2;
+    char ** pArgvNew;
+    int nArgcNew, c;
+    int fMiter;
+    int nDist;
+    int fVerbose;
+
+    extern Abc_Ntk_t * Abc_NtkDarMatch( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nDist, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fMiter = 0;
+    nDist = 0;
+    fVerbose = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Dmvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nDist = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nDist < 0 )
+                goto usage;
+            break;
+        case 'm':
+            fMiter ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( fMiter )
+    {
+//        Abc_Ntk_t * pNtkA, * pNtkB;
+        if ( !Abc_NtkIsStrash(pNtk) )
+        {
+            Abc_Print( -1, "This command works only for structrally hashed networks. Run \"st\".\n" );
+            return 0;
+        }
+        pNtkRes = Abc_NtkDarMatch( pNtk, NULL, nDist, fVerbose );
+/*
+        pNtkA = Abc_NtkDup( pNtk );
+        pNtkB = Abc_NtkDup( pNtk );
+        Abc_NtkDarSimSec( pNtkA, pNtkB, pPars );
+        Abc_NtkDelete( pNtkA );
+        Abc_NtkDelete( pNtkB );
+*/
+    }
+    else
+    {
+        pArgvNew = argv + globalUtilOptind;
+        nArgcNew = argc - globalUtilOptind;
+        if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+            return 1;
+        if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 )
+        {
+            if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+            if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+            Abc_Print( -1, "The network has no latches. Used combinational command \"cec\".\n" );
+            return 0;
+        }
+        // perform verification
+        pNtkRes = Abc_NtkDarMatch( pNtk1, pNtk2, nDist, fVerbose );
+        if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+        if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+    }
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Matching has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: match [-D num] [-mv] <file1> <file2>\n" );
+    Abc_Print( -2, "\t         detects structural similarity using simulation\n" );
+    Abc_Print( -2, "\t         replaces the current network by the miter of differences\n" );
+    Abc_Print( -2, "\t-D num : the distance for extending differences [default = %d]\n", nDist );
+    Abc_Print( -2, "\t-m     : toggles miter vs. two networks [default = %s]\n", fMiter? "miter": "two networks" );
+    Abc_Print( -2, "\t-v     : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\tfile1  : (optional) the file with the first network\n");
+    Abc_Print( -2, "\tfile2  : (optional) the file with the second network\n");
+    Abc_Print( -2, "\t         if no files are given, uses the current network and its spec\n");
+    Abc_Print( -2, "\t         if one file is given, uses the current network and the file\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int RetValue;
+    int fVerbose;
+    int nConfLimit;
+    int nInsLimit;
+    abctime clk;
+    // set defaults
+    fVerbose   = 0;
+    nConfLimit = 0;
+    nInsLimit  = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "CIvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfLimit < 0 )
+                goto usage;
+            break;
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nInsLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nInsLimit < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkLatchNum(pNtk) > 0 )
+    {
+        Abc_Print( -1, "Currently can only solve the miter for combinational circuits.\n" );
+        return 0;
+    }
+
+    clk = Abc_Clock();
+    if ( Abc_NtkIsStrash(pNtk) )
+    {
+        RetValue = Abc_NtkMiterSat( pNtk, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, fVerbose, NULL, NULL );
+    }
+    else
+    {
+        assert( Abc_NtkIsLogic(pNtk) );
+        Abc_NtkToBdd( pNtk );
+        RetValue = Abc_NtkMiterSat( pNtk, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, fVerbose, NULL, NULL );
+    }
+
+    // verify that the pattern is correct
+    if ( RetValue == 0 && Abc_NtkPoNum(pNtk) == 1 )
+    {
+        //int i;
+        //Abc_Obj_t * pObj;
+        int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtk->pModel );
+        if ( pSimInfo[0] != 1 )
+            Abc_Print( 1, "ERROR in Abc_NtkMiterSat(): Generated counter example is invalid.\n" );
+        ABC_FREE( pSimInfo );
+        /*
+        // print model
+        Abc_NtkForEachPi( pNtk, pObj, i )
+        {
+            Abc_Print( -1, "%d", (int)(pNtk->pModel[i] > 0) );
+            if ( i == 70 )
+                break;
+        }
+        Abc_Print( -1, "\n" );
+        */
+    }
+    pAbc->Status = RetValue;
+    if ( RetValue == -1 )
+        Abc_Print( 1, "UNDECIDED      " );
+    else if ( RetValue == 0 )
+        Abc_Print( 1, "SATISFIABLE    " );
+    else
+        Abc_Print( 1, "UNSATISFIABLE  " );
+    //Abc_Print( -1, "\n" );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: sat [-C num] [-I num] [-vh]\n" );
+    Abc_Print( -2, "\t         solves the combinational miter using SAT solver MiniSat-1.14\n" );
+    Abc_Print( -2, "\t         derives CNF from the current network and leave it unchanged\n" );
+    Abc_Print( -2, "\t         (there is also a newer SAT solving command \"dsat\")\n" );
+    Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n",    nConfLimit );
+    Abc_Print( -2, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDSat( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int RetValue;
+    int fAlignPol;
+    int fAndOuts;
+    int fNewSolver;
+    int fVerbose;
+    int nConfLimit;
+    int nLearnedStart;
+    int nLearnedDelta;
+    int nLearnedPerce;
+    int nInsLimit;
+    abctime clk;
+
+    extern int Abc_NtkDSat( Abc_Ntk_t * pNtk, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fAlignPol, int fAndOuts, int fNewSolver, int fVerbose );
+    // set defaults
+    fAlignPol  = 0;
+    fAndOuts   = 0;
+    fNewSolver = 0;
+    fVerbose   = 0;
+    nConfLimit = 0;
+    nInsLimit  = 0;
+    nLearnedStart = 0;
+    nLearnedDelta = 0;
+    nLearnedPerce = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "CILDEpanvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfLimit < 0 )
+                goto usage;
+            break;
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nInsLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nInsLimit < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLearnedStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLearnedStart < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLearnedDelta = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLearnedDelta < 0 )
+                goto usage;
+            break;
+        case 'E':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-E\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLearnedPerce = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLearnedPerce < 0 )
+                goto usage;
+            break;
+        case 'p':
+            fAlignPol ^= 1;
+            break;
+        case 'a':
+            fAndOuts ^= 1;
+            break;
+        case 'n':
+            fNewSolver ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( argc == globalUtilOptind + 1 )
+    {
+        extern int Cnf_DataSolveFromFile( char * pFileName, int nConfLimit, int fVerbose );
+        // get the input file name
+        char * pFileName = argv[globalUtilOptind];
+        FILE * pFile = fopen( pFileName, "rb" );
+        if ( pFile == NULL )
+        {
+            printf( "Cannot open file \"%s\" for writing.\n", pFileName );
+            return 0;
+        }
+        fclose( pFile );
+        Cnf_DataSolveFromFile( pFileName, nConfLimit, fVerbose );
+        return 0;
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkLatchNum(pNtk) > 0 )
+    {
+        Abc_Print( -1, "Currently can only solve the miter for combinational circuits.\n" );
+        return 0;
+    }
+
+    if ( Abc_NtkPoNum(pNtk) != 1 )
+    {
+        Abc_Print( -1, "Currently expects a single-output miter.\n" );
+        return 0;
+    }
+
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" );
+        return 0;
+    }
+    clk = Abc_Clock();
+    RetValue = Abc_NtkDSat( pNtk, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, nLearnedStart, nLearnedDelta, nLearnedPerce, fAlignPol, fAndOuts, fNewSolver, fVerbose );
+    // verify that the pattern is correct
+    if ( RetValue == 0 && Abc_NtkPoNum(pNtk) == 1 )
+    {
+        int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtk->pModel );
+        if ( pSimInfo[0] != 1 )
+            Abc_Print( 1, "ERROR in Abc_NtkMiterSat(): Generated counter example is invalid.\n" );
+        ABC_FREE( pSimInfo );
+        pAbc->pCex = Abc_CexCreate( 0, Abc_NtkPiNum(pNtk), pNtk->pModel, 0, 0, 0 );
+    }
+    pAbc->Status = RetValue;
+    if ( RetValue == -1 )
+        Abc_Print( 1, "UNDECIDED      " );
+    else if ( RetValue == 0 )
+        Abc_Print( 1, "SATISFIABLE    " );
+    else
+        Abc_Print( 1, "UNSATISFIABLE  " );
+    //Abc_Print( -1, "\n" );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dsat [-CILDE num] [-panvh]\n" );
+    Abc_Print( -2, "\t         solves the combinational miter using SAT solver MiniSat-1.14\n" );
+    Abc_Print( -2, "\t         derives CNF from the current network and leave it unchanged\n" );
+    Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n",    nConfLimit );
+    Abc_Print( -2, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit );
+    Abc_Print( -2, "\t-L num : starting value for learned clause removal [default = %d]\n", nLearnedStart );
+    Abc_Print( -2, "\t-D num : delta value for learned clause removal [default = %d]\n", nLearnedDelta );
+    Abc_Print( -2, "\t-E num : ratio percentage for learned clause removal [default = %d]\n", nLearnedPerce );
+    Abc_Print( -2, "\t-p     : alighn polarity of SAT variables [default = %s]\n", fAlignPol? "yes": "no" );
+    Abc_Print( -2, "\t-a     : toggle ANDing/ORing of miter outputs [default = %s]\n", fAndOuts? "ANDing": "ORing" );
+    Abc_Print( -2, "\t-n     : toggle using new solver [default = %s]\n", fNewSolver? "yes": "no" );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPSat( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int RetValue;
+    int c;
+    int nAlgo;
+    int nPartSize;
+    int nConfPart;
+    int nConfTotal;
+    int fAlignPol;
+    int fSynthesize;
+    int fVerbose;
+    abctime clk;
+
+    extern int Abc_NtkPartitionedSat( Abc_Ntk_t * pNtk, int nAlgo, int nPartSize, int nConfPart, int nConfTotal, int fAlignPol, int fSynthesize, int fVerbose );
+    // set defaults
+    nAlgo       =        0;
+    nPartSize   =    10000;
+    nConfPart   =        0;
+    nConfTotal  =  1000000;
+    fAlignPol   =        1;
+    fSynthesize =        0;
+    fVerbose    =        1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "APCpsvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nAlgo = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nAlgo < 0 )
+                goto usage;
+            break;
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nPartSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nPartSize < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfTotal = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfTotal < 0 )
+                goto usage;
+            break;
+        case 'p':
+            fAlignPol ^= 1;
+            break;
+        case 's':
+            fSynthesize ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkLatchNum(pNtk) > 0 )
+    {
+        Abc_Print( -1, "Currently can only solve the miter for combinational circuits.\n" );
+        return 0;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" );
+        return 0;
+    }
+
+    clk = Abc_Clock();
+    RetValue = Abc_NtkPartitionedSat( pNtk, nAlgo, nPartSize, nConfPart, nConfTotal, fAlignPol, fSynthesize, fVerbose );
+    // verify that the pattern is correct
+    if ( RetValue == 0 && Abc_NtkPoNum(pNtk) == 1 )
+    {
+        //int i;
+        //Abc_Obj_t * pObj;
+        int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtk->pModel );
+        if ( pSimInfo[0] != 1 )
+            Abc_Print( 1, "ERROR in Abc_NtkMiterSat(): Generated counter example is invalid.\n" );
+        ABC_FREE( pSimInfo );
+        /*
+        // print model
+        Abc_NtkForEachPi( pNtk, pObj, i )
+        {
+            Abc_Print( -1, "%d", (int)(pNtk->pModel[i] > 0) );
+            if ( i == 70 )
+                break;
+        }
+        Abc_Print( -1, "\n" );
+        */
+    }
+
+    if ( RetValue == -1 )
+        Abc_Print( 1, "UNDECIDED      " );
+    else if ( RetValue == 0 )
+        Abc_Print( 1, "SATISFIABLE    " );
+    else
+        Abc_Print( 1, "UNSATISFIABLE  " );
+    //Abc_Print( -1, "\n" );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: psat [-APC num] [-psvh]\n" );
+    Abc_Print( -2, "\t         solves the combinational miter using partitioning\n" );
+    Abc_Print( -2, "\t         (derives CNF from the current network and leave it unchanged)\n" );
+    Abc_Print( -2, "\t         for multi-output miters, tries to prove that the AND of POs is always 0\n" );
+    Abc_Print( -2, "\t         (if POs should be ORed instead of ANDed, use command \"orpos\")\n" );
+    Abc_Print( -2, "\t-A num : partitioning algorithm [default = %d]\n", nAlgo );
+    Abc_Print( -2, "\t         0 : no partitioning\n" );
+    Abc_Print( -2, "\t         1 : partitioning by level\n" );
+    Abc_Print( -2, "\t         2 : DFS post-order\n" );
+    Abc_Print( -2, "\t         3 : DFS pre-order\n" );
+    Abc_Print( -2, "\t         4 : bit-slicing\n" );
+    Abc_Print( -2, "\t         partitions are ordered by level (high level first)\n" );
+    Abc_Print( -2, "\t-P num : limit on the partition size [default = %d]\n", nPartSize );
+    Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfTotal );
+    Abc_Print( -2, "\t-p     : align polarity of SAT variables [default = %s]\n", fAlignPol? "yes": "no" );
+    Abc_Print( -2, "\t-s     : apply logic synthesis to each partition [default = %s]\n", fSynthesize? "yes": "no" );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandProve( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkTemp;
+    Prove_Params_t Params, * pParams = &Params;
+    int c, RetValue;
+    abctime clk;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    Prove_ParamsSetDefault( pParams );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "NCFGLIrfbvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nItersMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nItersMax < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nMiteringLimitStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nMiteringLimitStart < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nFraigingLimitStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nFraigingLimitStart < 0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nFraigingLimitMulti = (float)atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nFraigingLimitMulti < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nMiteringLimitLast = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nMiteringLimitLast < 0 )
+                goto usage;
+            break;
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pParams->nTotalInspectLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pParams->nTotalInspectLimit < 0 )
+                goto usage;
+            break;
+        case 'r':
+            pParams->fUseRewriting ^= 1;
+            break;
+        case 'f':
+            pParams->fUseFraiging ^= 1;
+            break;
+        case 'b':
+            pParams->fUseBdds ^= 1;
+            break;
+        case 'v':
+            pParams->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkLatchNum(pNtk) > 0 )
+    {
+        Abc_Print( -1, "Currently can only solve the miter for combinational circuits.\n" );
+        return 0;
+    }
+    if ( Abc_NtkCoNum(pNtk) != 1 )
+    {
+        Abc_Print( -1, "Currently can only solve the miter with one output.\n" );
+        return 0;
+    }
+    clk = Abc_Clock();
+
+    if ( Abc_NtkIsStrash(pNtk) )
+        pNtkTemp = Abc_NtkDup( pNtk );
+    else
+        pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+
+    RetValue = Abc_NtkMiterProve( &pNtkTemp, pParams );
+
+    // verify that the pattern is correct
+    if ( RetValue == 0 )
+    {
+        int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtkTemp->pModel );
+        if ( pSimInfo[0] != 1 )
+            Abc_Print( 1, "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" );
+        ABC_FREE( pSimInfo );
+    }
+    pAbc->Status = RetValue;
+    if ( RetValue == -1 )
+        Abc_Print( 1, "UNDECIDED      " );
+    else if ( RetValue == 0 )
+        Abc_Print( 1, "SATISFIABLE    " );
+    else
+        Abc_Print( 1, "UNSATISFIABLE  " );
+    //Abc_Print( -1, "\n" );
+
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: prove [-NCFGLI num] [-rfbvh]\n" );
+    Abc_Print( -2, "\t         solves combinational miter by rewriting, FRAIGing, and SAT\n" );
+    Abc_Print( -2, "\t         replaces the current network by the cone modified by rewriting\n" );
+    Abc_Print( -2, "\t         (there is also newer CEC command \"iprove\")\n" );
+    Abc_Print( -2, "\t-N num : max number of iterations [default = %d]\n", pParams->nItersMax );
+    Abc_Print( -2, "\t-C num : max starting number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitStart );
+    Abc_Print( -2, "\t-F num : max starting number of conflicts in fraiging [default = %d]\n", pParams->nFraigingLimitStart );
+    Abc_Print( -2, "\t-G num : multiplicative coefficient for fraiging [default = %d]\n", (int)pParams->nFraigingLimitMulti );
+    Abc_Print( -2, "\t-L num : max last-gasp number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitLast );
+    Abc_Print( -2, "\t-I num : max number of clause inspections in all SAT calls [default = %d]\n", (int)pParams->nTotalInspectLimit );
+    Abc_Print( -2, "\t-r     : toggle the use of rewriting [default = %s]\n", pParams->fUseRewriting? "yes": "no" );
+    Abc_Print( -2, "\t-f     : toggle the use of FRAIGing [default = %s]\n", pParams->fUseFraiging? "yes": "no" );
+    Abc_Print( -2, "\t-b     : toggle the use of BDDs [default = %s]\n", pParams->fUseBdds? "yes": "no" );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDebug( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    extern void Abc_NtkAutoDebug( Abc_Ntk_t * pNtk, int (*pFuncError) (Abc_Ntk_t *) );
+    extern int Abc_NtkRetimeDebug( Abc_Ntk_t * pNtk );
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "This command is applicable to logic networks.\n" );
+        return 1;
+    }
+
+    Abc_NtkAutoDebug( pNtk, Abc_NtkRetimeDebug );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: debug [-h]\n" );
+    Abc_Print( -2, "\t        performs automated debugging of the given procedure\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandBmc( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int nFrames;
+    int nSizeMax;
+    int nBTLimit;
+    int nBTLimitAll;
+    int nNodeDelta;
+    int fRewrite;
+    int fNewAlgo;
+    int nCofFanLit;
+    int fVerbose;
+    int iFrames;
+    char * pLogFileName = NULL;
+
+    extern int Abc_NtkDarBmc( Abc_Ntk_t * pNtk, int nStart, int nFrames, int nSizeMax, int nNodeDelta, int nTimeOut, int nBTLimit, int nBTLimitAll, int fRewrite, int fNewAlgo, int fOrDecomp, int nCofFanLit, int fVerbose, int * piFrames );
+    // set defaults
+    nFrames     =       20;
+    nSizeMax    =   100000;
+    nBTLimit    =        0;
+    nBTLimitAll =        0;
+    nNodeDelta  =     1000;
+    fRewrite    =        0;
+    fNewAlgo    =        1;
+    nCofFanLit  =        0;
+    fVerbose    =        0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FNCGDLrvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nSizeMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nSizeMax < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nBTLimitAll = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nBTLimitAll < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nNodeDelta = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nNodeDelta < 0 )
+                goto usage;
+            break;
+/*
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nCofFanLit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nCofFanLit < 0 )
+                goto usage;
+            break;
+*/
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pLogFileName = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'r':
+            fRewrite ^= 1;
+            break;
+        case 'a':
+            fNewAlgo ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" );
+        return 0;
+    }
+    if ( Abc_NtkLatchNum(pNtk) == 0 )
+    {
+        Abc_Print( -1, "Does not work for combinational networks.\n" );
+        return 0;
+    }
+    pAbc->Status = Abc_NtkDarBmc( pNtk, 0, nFrames, nSizeMax, nNodeDelta, 0, nBTLimit, nBTLimitAll, fRewrite, fNewAlgo, 0, nCofFanLit, fVerbose, &iFrames );
+    pAbc->nFrames = iFrames;
+    Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel );
+    if ( pLogFileName )
+        Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "bmc" );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: bmc [-FNC num] [-L file] [-rcvh]\n" );
+    Abc_Print( -2, "\t         performs bounded model checking with static unrolling\n" );
+    Abc_Print( -2, "\t-F num : the number of time frames [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-N num : the max number of nodes in the frames [default = %d]\n", nSizeMax );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", nBTLimit );
+//    Abc_Print( -2, "\t-L num : the limit on fanout count of resets/enables to cofactor [default = %d]\n", nCofFanLit );
+    Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" );
+    Abc_Print( -2, "\t-r     : toggle the use of rewriting [default = %s]\n", fRewrite? "yes": "no" );
+//    Abc_Print( -2, "\t-a     : toggle SAT sweeping and SAT solving [default = %s]\n", fNewAlgo? "SAT solving": "SAT sweeping" );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandBmc2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    int nStart;
+    int nFrames;
+    int nSizeMax;
+    int nBTLimit;
+    int nBTLimitAll;
+    int nNodeDelta;
+    int nTimeOut;
+    int fRewrite;
+    int fNewAlgo;
+    int fOrDecomp;
+    int fVerbose;
+    int iFrames;
+    char * pLogFileName = NULL;
+
+    extern int Abc_NtkDarBmc( Abc_Ntk_t * pNtk, int nStart, int nFrames, int nSizeMax, int nNodeDelta, int nTimeOut, int nBTLimit, int nBTLimitAll, int fRewrite, int fNewAlgo, int fOrDecomp, int nCofFanLit, int fVerbose, int * piFrames );
+
+    // set defaults
+    nStart      =        0;
+    nFrames     =        0;
+    nSizeMax    =   200000;
+    nBTLimit    =        0;
+    nBTLimitAll =        0;
+    nNodeDelta  =     2000;
+    nTimeOut    =        0;
+    fRewrite    =        0;
+    fNewAlgo    =        0;
+    fOrDecomp   =        0;
+    fVerbose    =        0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "SFNTCGDLruvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nStart < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nSizeMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nSizeMax < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nTimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nTimeOut < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nBTLimitAll = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nBTLimitAll < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nNodeDelta = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nNodeDelta < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pLogFileName = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'r':
+            fRewrite ^= 1;
+            break;
+        case 'a':
+            fNewAlgo ^= 1;
+            break;
+        case 'u':
+            fOrDecomp ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" );
+        return 0;
+    }
+    if ( Abc_NtkLatchNum(pNtk) == 0 )
+    {
+        Abc_Print( -1, "Does not work for combinational networks.\n" );
+        return 0;
+    }
+    pAbc->Status = Abc_NtkDarBmc( pNtk, nStart, nFrames, nSizeMax, nNodeDelta, nTimeOut, nBTLimit, nBTLimitAll, fRewrite, fNewAlgo, fOrDecomp, 0, fVerbose, &iFrames );
+    pAbc->nFrames = iFrames;
+    Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel );
+    if ( pLogFileName )
+        Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "bmc2" );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: bmc2 [-SFTCGD num] [-L file] [-uvh]\n" );
+    Abc_Print( -2, "\t         performs bounded model checking with dynamic unrolling\n" );
+    Abc_Print( -2, "\t-S num : the starting time frame [default = %d]\n", nStart );
+    Abc_Print( -2, "\t-F num : the max number of time frames (0 = unused) [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nTimeOut );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", nBTLimit );
+    Abc_Print( -2, "\t-G num : the max number of conflicts globally [default = %d]\n", nBTLimitAll );
+    Abc_Print( -2, "\t-D num : the delta in the number of nodes [default = %d]\n", nNodeDelta );
+    Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" );
+    Abc_Print( -2, "\t-u     : toggle performing structural OR-decomposition [default = %s]\n", fOrDecomp? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandBmc3( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern int Abc_NtkDarBmc3( Abc_Ntk_t * pNtk, Saig_ParBmc_t * pPars, int fOrDecomp );
+    Saig_ParBmc_t Pars, * pPars = &Pars;
+    Abc_Ntk_t * pNtkRes, * pNtk = Abc_FrameReadNtk(pAbc);
+    Vec_Ptr_t * vSeqModelVec = NULL;
+    Vec_Int_t * vStatuses = NULL;
+    char * pLogFileName = NULL;
+    int fOrDecomp = 0;
+    int c;
+    Saig_ParBmcSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "SFTHGCDJIPQRLWaxdruvzh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nStart < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesMax < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nTimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nTimeOut < 0 )
+                goto usage;
+            break;
+        case 'H':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-H\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nTimeOutOne = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nTimeOutOne < 0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nTimeOutGap = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nTimeOutGap < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nConfLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nConfLimit < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nConfLimitJump = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nConfLimitJump < 0 )
+                goto usage;
+            break;
+        case 'J':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-J\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesJump = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesJump < 0 )
+                goto usage;
+            break;
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nPisAbstract = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nPisAbstract < 0 )
+                goto usage;
+            break;
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nLearnedStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLearnedStart < 0 )
+                goto usage;
+            break;
+        case 'Q':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-Q\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nLearnedDelta = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLearnedDelta < 0 )
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nLearnedPerce = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLearnedPerce < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pLogFileName = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pPars->pLogFileName = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'a':
+            pPars->fSolveAll ^= 1;
+            break;
+        case 'x':
+            pPars->fStoreCex ^= 1;
+            break;
+        case 'd':
+            pPars->fDropSatOuts ^= 1;
+            break;
+        case 'u':
+            fOrDecomp ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'z':
+            pPars->fNotVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" );
+        return 0;
+    }
+    if ( Abc_NtkLatchNum(pNtk) == 0 )
+    {
+        Abc_Print( -1, "Does not work for combinational networks.\n" );
+        return 0;
+    }
+    if ( Abc_NtkConstrNum(pNtk) > 0 )
+    {
+        Abc_Print( -1, "Constraints have to be folded (use \"fold\").\n" );
+        return 0;
+    }
+    pPars->fUseBridge = pAbc->fBridgeMode;
+    pAbc->Status = Abc_NtkDarBmc3( pNtk, pPars, fOrDecomp );
+    pAbc->nFrames = pNtk->vSeqModelVec ? -1 : pPars->iFrame;
+    if ( pLogFileName )
+        Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "bmc3" );
+    vSeqModelVec = pNtk->vSeqModelVec;  pNtk->vSeqModelVec = NULL;
+    if ( pPars->fSolveAll && pPars->fDropSatOuts )
+    {
+        if ( vSeqModelVec == NULL )
+            Abc_Print( 1,"The array of counter-examples is not available.\n" );
+        else if ( Vec_PtrSize(vSeqModelVec) != Abc_NtkPoNum(pNtk) )
+            Abc_Print( 1,"The array size does not match the number of outputs.\n" );
+        else
+        {
+            extern void Abc_NtkDropSatOutputs( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCexes, int fVerbose );
+            Abc_NtkDropSatOutputs( pNtk, vSeqModelVec, pPars->fVerbose );
+            pNtkRes = Abc_NtkDarLatchSweep( pNtk, 1, 1, 1, 0, -1, -1, 0, 0 );
+            if ( pNtkRes == NULL )
+            {
+                Abc_Print( -1, "Removing SAT outputs has failed.\n" );
+                return 1;
+            }
+            Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+        }
+    }
+    vStatuses = Abc_FrameDeriveStatusArray( vSeqModelVec );
+    Abc_FrameReplacePoStatuses( pAbc, &vStatuses );        
+    if ( vSeqModelVec )
+        Abc_FrameReplaceCexVec( pAbc, &vSeqModelVec );
+    else
+        Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: bmc3 [-SFTHGCDJIPQR num] [-LW file] [-axduvzh]\n" );
+    Abc_Print( -2, "\t         performs bounded model checking with dynamic unrolling\n" );
+    Abc_Print( -2, "\t-S num : the starting time frame [default = %d]\n", pPars->nStart );
+    Abc_Print( -2, "\t-F num : the max number of time frames (0 = unused) [default = %d]\n",      pPars->nFramesMax );
+    Abc_Print( -2, "\t-T num : runtime limit, in seconds [default = %d]\n",                       pPars->nTimeOut );
+    Abc_Print( -2, "\t-H num : runtime limit per output, in miliseconds (with \"-a\") [default = %d]\n",    pPars->nTimeOutOne );
+    Abc_Print( -2, "\t-G num : runtime gap since the last CEX, in seconds [default = %d]\n",      pPars->nTimeOutGap );
+    Abc_Print( -2, "\t-C num : max conflicts at an output [default = %d]\n",                      pPars->nConfLimit );
+    Abc_Print( -2, "\t-D num : max conflicts after jumping (0 = infinity) [default = %d]\n",      pPars->nConfLimitJump );
+    Abc_Print( -2, "\t-J num : the number of timeframes to jump (0 = not used) [default = %d]\n", pPars->nFramesJump );
+    Abc_Print( -2, "\t-I num : the number of PIs to abstract [default = %d]\n",                   pPars->nPisAbstract );
+    Abc_Print( -2, "\t-P num : the max number of learned clauses to keep (0=unused) [default = %d]\n", pPars->nLearnedStart );
+    Abc_Print( -2, "\t-Q num : delta value for learned clause removal [default = %d]\n",          pPars->nLearnedDelta );
+    Abc_Print( -2, "\t-R num : percentage to keep for learned clause removal [default = %d]\n",   pPars->nLearnedPerce );
+    Abc_Print( -2, "\t-L file: the log file name [default = %s]\n",                               pLogFileName ? pLogFileName : "no logging" );
+    Abc_Print( -2, "\t-W file: the log file name with per-output details [default = %s]\n",       pPars->pLogFileName ? pPars->pLogFileName : "no logging" );
+    Abc_Print( -2, "\t-a     : solve all outputs (do not stop when one is SAT) [default = %s]\n", pPars->fSolveAll? "yes": "no" );
+    Abc_Print( -2, "\t-x     : toggle storing CEXes when solving all outputs [default = %s]\n",   pPars->fStoreCex? "yes": "no" );
+    Abc_Print( -2, "\t-d     : toggle dropping (replacing by 0) SAT outputs [default = %s]\n",    pPars->fDropSatOuts? "yes": "no" );
+    Abc_Print( -2, "\t-u     : toggle performing structural OR-decomposition [default = %s]\n",   fOrDecomp? "yes": "not" );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n",                           pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-z     : toggle suppressing report about solved outputs [default = %s]\n",  pPars->fNotVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandBmcInter( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Inter_ManParams_t Pars, * pPars = &Pars;
+    Abc_Ntk_t * pNtkRes, * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    char * pLogFileName = NULL;
+
+    extern int Abc_NtkDarBmcInter( Abc_Ntk_t * pNtk, Inter_ManParams_t * pPars, Abc_Ntk_t ** ppNtkRes );
+    // set defaults
+    Inter_ManSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "CFTKLIrtpomcgbqkdivh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesMax < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nSecLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nSecLimit < 0 )
+                goto usage;
+            break;
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesK = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesK < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pLogFileName = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pPars->pFileName = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'r':
+            pPars->fRewrite ^= 1;
+            break;
+        case 't':
+            pPars->fTransLoop ^= 1;
+            break;
+        case 'p':
+            pPars->fUsePudlak ^= 1;
+            break;
+        case 'o':
+            pPars->fUseOther ^= 1;
+            break;
+        case 'm':
+            pPars->fUseMiniSat ^= 1;
+            break;
+        case 'c':
+            pPars->fCheckKstep ^= 1;
+            break;
+        case 'g':
+            pPars->fUseBias ^= 1;
+            break;
+        case 'b':
+            pPars->fUseBackward ^= 1;
+            break;
+        case 'q':
+            pPars->fUseTwoFrames ^= 1;
+            break;
+        case 'k':
+            pPars->fUseSeparate ^= 1;
+            break;
+        case 'd':
+            pPars->fDropSatOuts ^= 1;
+            break;
+        case 'i':
+            pPars->fDropInvar ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" );
+        return 0;
+    }
+    if ( Abc_NtkLatchNum(pNtk) == 0 )
+    {
+        Abc_Print( -1, "Does not work for combinational networks.\n" );
+        return 0;
+    }
+    if ( Abc_NtkConstrNum(pNtk) > 0 )
+    {
+        Abc_Print( -1, "Cannot run interpolation with constraints. Use \"fold\".\n" );
+        return 0;
+    }
+    if ( Abc_NtkPoNum(pNtk)-Abc_NtkConstrNum(pNtk) != 1 )
+    {
+        if ( Abc_NtkConstrNum(pNtk) > 0 )
+        {
+            Abc_Print( 1,"Cannot solve multiple-output miter with constraints.\n" );
+            return 0;
+        }
+        if ( pPars->fUseSeparate )
+        {
+            Abc_Print( 0, "Each of %d outputs will be solved separately.\n", Abc_NtkPoNum(pNtk) );
+            pAbc->Status = Abc_NtkDarBmcInter( pNtk, pPars, &pNtkRes );
+            Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel );
+            if ( pNtkRes == NULL )
+            {
+                Abc_Print( -1, "Generating resulting network has failed.\n" );
+                return 0;
+            }
+            Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+        }
+        else
+        {
+            Abc_Ntk_t * pNtkNew = Abc_NtkDup( pNtk );
+            Abc_Print( 0, "All %d outputs will be ORed together.\n", Abc_NtkPoNum(pNtk) );
+            if ( !Abc_NtkCombinePos( pNtkNew, 0, 0 ) )
+            {
+                Abc_NtkDelete( pNtkNew );
+                Abc_Print( -1, "ORing outputs has failed.\n" );
+                return 0;
+            }
+            pAbc->Status = Abc_NtkDarBmcInter( pNtkNew, pPars, NULL );
+            if ( pAbc->Status == 0 )
+            {
+                Aig_Man_t * pMan = Abc_NtkToDar( pNtk, 0, 1 );
+                pNtkNew->pSeqModel->iPo = Saig_ManFindFailedPoCex( pMan, pNtkNew->pSeqModel );
+                Aig_ManStop( pMan );
+            }
+            Abc_FrameReplaceCex( pAbc, &pNtkNew->pSeqModel );
+            Abc_NtkDelete( pNtkNew );
+        }
+        pAbc->nFrames = -1;
+    }
+    else
+    {
+        pAbc->Status  = Abc_NtkDarBmcInter( pNtk, pPars, NULL );
+        pAbc->nFrames = pPars->iFrameMax;
+        Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel );
+    }
+    if ( pLogFileName )
+        Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "int" );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: int [-CFTK num] [-LI file] [-irtpomcgbqkdvh]\n" );
+    Abc_Print( -2, "\t         uses interpolation to prove the property\n" );
+    Abc_Print( -2, "\t-C num : the limit on conflicts for one SAT run [default = %d]\n", pPars->nBTLimit );
+    Abc_Print( -2, "\t-F num : the limit on number of frames to unroll [default = %d]\n", pPars->nFramesMax );
+    Abc_Print( -2, "\t-T num : the limit on runtime per output in seconds [default = %d]\n", pPars->nSecLimit );
+    Abc_Print( -2, "\t-K num : the number of steps in inductive checking [default = %d]\n", pPars->nFramesK );
+    Abc_Print( -2, "\t         (K = 1 works in all cases; K > 1 works without -t and -b)\n" );
+    Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" );
+    Abc_Print( -2, "\t-I file: the file name for dumping interpolant [default = \"%s\"]\n", pPars->pFileName ? pPars->pFileName : "invar.aig" );
+    Abc_Print( -2, "\t-i     : toggle dumping interpolant/invariant into a file [default = %s]\n", pPars->fDropInvar? "yes": "no" );
+    Abc_Print( -2, "\t-r     : toggle rewriting of the unrolled timeframes [default = %s]\n", pPars->fRewrite? "yes": "no" );
+    Abc_Print( -2, "\t-t     : toggle adding transition into the initial state [default = %s]\n", pPars->fTransLoop? "yes": "no" );
+    Abc_Print( -2, "\t-p     : toggle using original Pudlak's interpolation procedure [default = %s]\n", pPars->fUsePudlak? "yes": "no" );
+    Abc_Print( -2, "\t-o     : toggle using optimized Pudlak's interpolation procedure [default = %s]\n", pPars->fUseOther? "yes": "no" );
+    Abc_Print( -2, "\t-m     : toggle using MiniSat-1.14p (now, Windows-only) [default = %s]\n", pPars->fUseMiniSat? "yes": "no" );
+    Abc_Print( -2, "\t-c     : toggle using inductive containment check [default = %s]\n", pPars->fCheckKstep? "yes": "no" );
+    Abc_Print( -2, "\t-g     : toggle using bias for global variables using SAT [default = %s]\n", pPars->fUseBias? "yes": "no" );
+    Abc_Print( -2, "\t-b     : toggle using backward interpolation (works with -t) [default = %s]\n", pPars->fUseBackward? "yes": "no" );
+    Abc_Print( -2, "\t-q     : toggle using property in two last timeframes [default = %s]\n", pPars->fUseTwoFrames? "yes": "no" );
+    Abc_Print( -2, "\t-k     : toggle solving each output separately [default = %s]\n", pPars->fUseSeparate? "yes": "no" );
+    Abc_Print( -2, "\t-d     : toggle dropping (replacing by 0) SAT outputs (with -k is used) [default = %s]\n", pPars->fDropSatOuts? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandIndcut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int nFrames;
+    int nPref;
+    int nClauses;
+    int nLutSize;
+    int nLevels;
+    int nCutsMax;
+    int nBatches;
+    int fStepUp;
+    int fBmc;
+    int fRegs;
+    int fTarget;
+    int fVerbose;
+    int fVeryVerbose;
+    int c;
+    extern int Abc_NtkDarClau( Abc_Ntk_t * pNtk, int nFrames, int nPref, int nClauses, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRegs, int fTarget, int fVerbose, int fVeryVerbose );
+    // set defaults
+    nFrames      =    1;
+    nPref        =    0;
+    nClauses     = 5000;
+    nLutSize     =    4;
+    nLevels      =    8;
+    nCutsMax     =   16;
+    nBatches     =    1;
+    fStepUp      =    0;
+    fBmc         =    1;
+    fRegs        =    1;
+    fTarget      =    1;
+    fVerbose     =    0;
+    fVeryVerbose =    0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FPCMLNBsbrtvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nPref = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nPref < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nClauses = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nClauses < 0 )
+                goto usage;
+            break;
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLutSize < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLevels = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLevels < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nCutsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nCutsMax < 0 )
+                goto usage;
+            break;
+        case 'B':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nBatches = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nBatches < 0 )
+                goto usage;
+            break;
+        case 's':
+            fStepUp ^= 1;
+            break;
+        case 'b':
+            fBmc ^= 1;
+            break;
+        case 'r':
+            fRegs ^= 1;
+            break;
+        case 't':
+            fTarget ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" );
+        return 0;
+    }
+    if ( nLutSize > 12 )
+    {
+        Abc_Print( -1, "The cut size should be not exceed 12.\n" );
+        return 0;
+    }
+    Abc_NtkDarClau( pNtk, nFrames, nPref, nClauses, nLutSize, nLevels, nCutsMax, nBatches, fStepUp, fBmc, fRegs, fTarget, fVerbose, fVeryVerbose );
+    return 0;
+usage:
+    Abc_Print( -2, "usage: indcut [-FPCMLNB num] [-sbrtvh]\n" );
+    Abc_Print( -2, "\t         K-step induction strengthened with cut properties\n" );
+    Abc_Print( -2, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-P num : number of time frames in the prefix (0=no prefix) [default = %d]\n", nPref );
+    Abc_Print( -2, "\t-C num : the max number of clauses to use for strengthening [default = %d]\n", nClauses );
+    Abc_Print( -2, "\t-M num : the cut size (2 <= M <= 12) [default = %d]\n", nLutSize );
+    Abc_Print( -2, "\t-L num : the max number of levels for cut computation [default = %d]\n", nLevels );
+    Abc_Print( -2, "\t-N num : the max number of cuts to compute at a node [default = %d]\n", nCutsMax );
+    Abc_Print( -2, "\t-B num : the max number of invariant batches to try [default = %d]\n", nBatches );
+    Abc_Print( -2, "\t-s     : toggle increment cut size in each batch [default = %s]\n", fStepUp? "yes": "no" );
+    Abc_Print( -2, "\t-b     : toggle enabling BMC check [default = %s]\n", fBmc? "yes": "no" );
+    Abc_Print( -2, "\t-r     : toggle enabling register clauses [default = %s]\n", fRegs? "yes": "no" );
+    Abc_Print( -2, "\t-t     : toggle proving target / computing don't-cares [default = %s]\n", fTarget? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+//    Abc_Print( -2, "\t-w     : toggle printing very verbose information [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandEnlarge( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int nFrames;
+    int fVerbose;
+    int c;
+    extern Abc_Ntk_t * Abc_NtkDarEnlarge( Abc_Ntk_t * pNtk, int nFrames, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nFrames      = 5;
+    fVerbose     = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 1 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" );
+        return 0;
+    }
+
+    // modify the current network
+    pNtkRes = Abc_NtkDarEnlarge( pNtk, nFrames, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Target enlargement has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+usage:
+    Abc_Print( -2, "usage: enlarge [-F <num>] [-vh]\n" );
+    Abc_Print( -2, "\t           performs structural K-step target enlargement\n" );
+    Abc_Print( -2, "\t-F <num> : the number of timeframes to unroll (<num> > 0) [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-v       : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandTempor( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Abc_Ntk_t * Abc_NtkDarTempor( Abc_Ntk_t * pNtk, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fUseTransSigs, int fVerbose, int fVeryVerbose );
+    Abc_Ntk_t * pNtkRes, * pNtk = Abc_FrameReadNtk(pAbc);
+    int nFrames       =       0;
+    int TimeOut       =     300;
+    int nConfMax      =  100000;
+    int fUseBmc       =       1;
+    int fUseTransSigs =       0;
+    int fUpdateCex    =       0;
+    int fVerbose      =       0;
+    int fVeryVerbose  =       0;
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FTCbscvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            TimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( TimeOut < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfMax < 0 )
+                goto usage;
+            break;
+        case 'b':
+            fUseBmc ^= 1;
+            break;
+        case 's':
+            fUseTransSigs ^= 1;
+            break;
+        case 'c':
+            fUpdateCex ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -2, "There is no current network.\n");
+        return 0;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -2, "The current network is not an AIG (run \"strash\").\n");
+        return 0;
+    }
+    if ( Abc_NtkLatchNum(pNtk) == 0 )
+    {
+        Abc_Print( -2, "The current network is combinational.\n");
+        return 0;
+    }
+    if ( fUpdateCex )
+    {
+        Abc_Cex_t * pCexNew;
+        if ( pAbc->pCex == NULL )
+        {
+            Abc_Print( -1, "Counter-example is not available.\n" );
+            return 1;
+        }
+        if ( pAbc->pCex->nPis % Abc_NtkPiNum(pNtk) != 0 )
+        {
+            Abc_Print( -1, "PI count of the CEX is not a multiple of PI count of the current AIG.\n" );
+            return 1;
+        }
+        pCexNew = Abc_CexTransformTempor( pAbc->pCex, Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkLatchNum(pNtk) );
+        Abc_FrameReplaceCex( pAbc, &pCexNew );
+        return 0;
+    }
+    // modify the current network
+    pNtkRes = Abc_NtkDarTempor( pNtk, nFrames, TimeOut, nConfMax, fUseBmc, fUseTransSigs, fVerbose, fVeryVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "Temporal decomposition has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: tempor [-FTC <num>] [-bscvwh]\n" );
+    Abc_Print( -2, "\t           performs temporal decomposition\n" );
+    Abc_Print( -2, "\t-F <num> : init logic timeframe count (0 = use leading length) [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-T <num> : runtime limit in seconds for BMC (0=unused) [default = %d]\n", TimeOut );
+    Abc_Print( -2, "\t-C <num> : max number of SAT conflicts in BMC (0=unused) [default = %d]\n", nConfMax );
+    Abc_Print( -2, "\t-b       : toggle running BMC2 on the init frames [default = %s]\n", fUseBmc? "yes": "no" );
+    Abc_Print( -2, "\t-s       : toggle using transient signals [default = %s]\n", fUseTransSigs? "yes": "no" );
+    Abc_Print( -2, "\t-c       : update the current CEX derived for a new AIG after \"tempor\"\n" );
+    Abc_Print( -2, "\t           to match the current AIG (the one before \"tempor\") [default = %s]\n", fUpdateCex? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggle printing verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggle printing ternary state space [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandInduction( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int nTimeOut;
+    int nFramesMax;
+    int nConfMax;
+    int fUnique;
+    int fUniqueAll;
+    int fGetCex;
+    int fVerbose;
+    int fVeryVerbose;
+    int c;
+    extern int Abc_NtkDarInduction( Abc_Ntk_t * pNtk, int nTimeOut, int nFramesMax, int nConfMax, int fUnique, int fUniqueAll, int fGetCex, int fVerbose, int fVeryVerbose );
+    // set defaults
+    nTimeOut     =     0;
+    nFramesMax   =     0;
+    nConfMax     =     0;
+    fUnique      =     0;
+    fUniqueAll   =     0;
+    fGetCex      =     0;
+    fVerbose     =     0;
+    fVeryVerbose =     0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FCTuaxvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFramesMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFramesMax < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfMax < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nTimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nTimeOut < 0 )
+                goto usage;
+            break;
+        case 'u':
+            fUnique ^= 1;
+            break;
+        case 'a':
+            fUniqueAll ^= 1;
+            break;
+        case 'x':
+            fGetCex ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" );
+        return 0;
+    }
+    if ( Abc_NtkPoNum(pNtk) != 1 )
+    {
+        Abc_Print( -1, "Currently this command works only for single-output miter.\n" );
+        return 0;
+    }
+    if ( fUnique && fUniqueAll )
+    {
+        Abc_Print( -1, "Only one of the options, \"-u\" or \"-a\", should be selected.\n" );
+        return 0;
+    }
+
+    // modify the current network
+    pAbc->Status = Abc_NtkDarInduction( pNtk, nTimeOut, nFramesMax, nConfMax, fUnique, fUniqueAll, fGetCex, fVerbose, fVeryVerbose );
+    if ( fGetCex )
+    {
+        Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel );
+        Abc_Print( 1,"The current CEX in ABC is set to be the CEX to induction.\n" );
+    }
+    return 0;
+usage:
+    Abc_Print( -2, "usage: ind [-FCT num] [-uaxvwh]\n" );
+    Abc_Print( -2, "\t         runs the inductive case of the K-step induction\n" );
+    Abc_Print( -2, "\t-F num : the max number of timeframes [default = %d]\n", nFramesMax );
+    Abc_Print( -2, "\t-C num : the max number of conflicts by SAT solver [default = %d]\n", nConfMax );
+    Abc_Print( -2, "\t-T num : the limit on runtime per output in seconds [default = %d]\n", nTimeOut );
+    Abc_Print( -2, "\t-u     : toggle adding uniqueness constraints on demand [default = %s]\n", fUnique? "yes": "no" );
+    Abc_Print( -2, "\t-a     : toggle adding uniqueness constraints always [default = %s]\n", fUniqueAll? "yes": "no" );
+    Abc_Print( -2, "\t-x     : toggle returning CEX to induction for the top frame [default = %s]\n", fGetCex? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle printing additional verbose information [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandConstr( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk;
+    int c;
+    int nFrames;
+    int nConfs;
+    int nProps;
+    int fRemove;
+    int fStruct;
+    int fInvert;
+    int fOldAlgo;
+    int fVerbose;
+    int nConstrs;
+    extern void Abc_NtkDarConstr( Abc_Ntk_t * pNtk, int nFrames, int nConfs, int nProps, int fStruct, int fOldAlgo, int fVerbose );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nFrames   =      1;
+    nConfs    =   1000;
+    nProps    =   1000;
+    fRemove   =      0;
+    fStruct   =      0;
+    fInvert   =      0;
+    fOldAlgo  =      0;
+    fVerbose  =      0;
+    nConstrs  =     -1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FCPNrsiavh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfs = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfs < 0 )
+                goto usage;
+            break;
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nProps = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nProps < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConstrs = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConstrs < 0 )
+                goto usage;
+            break;
+        case 'r':
+            fRemove ^= 1;
+            break;
+        case 's':
+            fStruct ^= 1;
+            break;
+        case 'i':
+            fInvert ^= 1;
+            break;
+        case 'a':
+            fOldAlgo ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" );
+        return 0;
+    }
+    if ( fRemove )
+    {
+        if ( Abc_NtkConstrNum(pNtk) == 0 )
+        {
+            Abc_Print( -1, "Constraints are not defined.\n" );
+            return 0;
+        }
+        Abc_Print( 1, "Constraints are converted to be primary outputs.\n" );
+        pNtk->nConstrs = 0;
+        return 0;
+    }
+    // consider the case of manual constraint definition
+    if ( nConstrs >= 0 )
+    {
+        if ( Abc_NtkIsComb(pNtk) )
+            Abc_Print( 0, "The network is combinational.\n" );
+        if ( Abc_NtkConstrNum(pNtk) > 0 )
+            Abc_Print( 0, "The network currently has %d constraints.\n", Abc_NtkConstrNum(pNtk) );
+        if ( nConstrs >= Abc_NtkPoNum(pNtk) )
+        {
+            Abc_Print( -1, "The number of constraints specified (%d) should be less than POs (%d).\n", nConstrs, Abc_NtkPoNum(pNtk) );
+            return 0;
+        }
+        Abc_Print( 1, "Setting the last %d POs as constraint outputs.\n", nConstrs );
+        pNtk->nConstrs = nConstrs;
+        return 0;
+    }
+    // consider the case of already defined constraints
+    if ( Abc_NtkConstrNum(pNtk) > 0 )
+    {
+        extern void Abc_NtkDarConstrProfile( Abc_Ntk_t * pNtk, int fVerbose );
+        if ( fInvert )
+        {
+            Abc_NtkInvertConstraints( pNtk );
+            if ( Abc_NtkConstrNum(pNtk) == 1 )
+                Abc_Print( 1, "The output of %d constraint is complemented.\n", Abc_NtkConstrNum(pNtk) );
+            else
+                Abc_Print( 1, "The outputs of %d constraints are complemented.\n", Abc_NtkConstrNum(pNtk) );
+        }
+        if ( fVerbose )
+            Abc_NtkDarConstrProfile( pNtk, fVerbose );
+        return 0;
+    }
+    if ( Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    // detect constraints using functional/structural methods
+    Abc_NtkDarConstr( pNtk, nFrames, nConfs, nProps, fStruct, fOldAlgo, fVerbose );
+    return 0;
+usage:
+    Abc_Print( -2, "usage: constr [-FCPN num] [-risavh]\n" );
+    Abc_Print( -2, "\t         a toolkit for constraint manipulation\n" );
+    Abc_Print( -2, "\t         if constraints are absent, detect them functionally\n" );
+    Abc_Print( -2, "\t         if constraints are present, profiles them using random simulation\n" );
+    Abc_Print( -2, "\t-F num : the max number of timeframes to consider [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-C num : the max number of conflicts in SAT solving [default = %d]\n", nConfs );
+    Abc_Print( -2, "\t-P num : the max number of propagations in SAT solving [default = %d]\n", nProps );
+    Abc_Print( -2, "\t-N num : manually set the last <num> POs to be constraints [default = %d]\n", nConstrs );
+    Abc_Print( -2, "\t-r     : manually remove the constraints [default = %s]\n", fRemove? "yes": "no" );
+    Abc_Print( -2, "\t-i     : toggle inverting already defined constraints [default = %s]\n", fInvert? "yes": "no" );
+    Abc_Print( -2, "\t-s     : toggle using structural detection methods [default = %s]\n", fStruct? "yes": "no" );
+    Abc_Print( -2, "\t-a     : toggle fast implication detection [default = %s]\n", !fOldAlgo? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandUnfold( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int nFrames;
+    int nConfs;
+    int nProps;
+    int fStruct;
+    int fOldAlgo;
+    int fVerbose;
+    int c;
+    extern Abc_Ntk_t * Abc_NtkDarUnfold( Abc_Ntk_t * pNtk, int nFrames, int nConfs, int nProps, int fStruct, int fOldAlgo, int fVerbose );
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nFrames   =      1;
+    nConfs    =   1000;
+    nProps    =   1000;
+    fStruct   =      0;
+    fOldAlgo  =      0;
+    fVerbose  =      0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FCPsavh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfs = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfs < 0 )
+                goto usage;
+            break;
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nProps = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nProps < 0 )
+                goto usage;
+            break;
+        case 's':
+            fStruct ^= 1;
+            break;
+        case 'a':
+            fOldAlgo ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkIsComb(pNtk) && Abc_NtkPoNum(pNtk) > 1 )
+    {
+        Abc_Print( -1, "Combinational miter has more than one PO.\n" );
+        return 0;
+    }
+    if ( Abc_NtkIsComb(pNtk) )
+    {
+        extern Gia_Man_t * Gia_ManDupWithConstr( Gia_Man_t * p );
+        Gia_Man_t * pNew;
+        Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 0 );
+        Gia_Man_t * pGia = Gia_ManFromAigSimple( pAig );
+        Aig_ManStop( pAig );
+        pNew = Gia_ManDupWithConstr( pGia );
+        if ( pNew == NULL )
+        {
+            Abc_Print( -1, "Cannot extract constrains from the miter.\n" );
+            return 0;
+        }
+        Gia_ManStop( pGia );
+        pAig = Gia_ManToAigSimple( pNew );
+        Gia_ManStop( pNew );
+        pNtkRes = Abc_NtkFromAigPhase( pAig );
+        Aig_ManStop( pAig );
+        ABC_FREE( pNtkRes->pName );
+        pNtkRes->pName = Extra_UtilStrsav( pNtk->pName );
+        // replace the current network
+        Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+        return 0;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" );
+        return 0;
+    }
+    if ( Abc_NtkConstrNum(pNtk) > 0 )
+    {
+        Abc_Print( -1, "Constraints are already extracted.\n" );
+        return 0;
+    }
+    if ( Abc_NtkPoNum(pNtk) > 1 && !fStruct )
+    {
+        Abc_Print( -1, "Functional constraint extraction works for single-output miters (use \"orpos\").\n" );
+        return 0;
+    }
+    // modify the current network
+    pNtkRes = Abc_NtkDarUnfold( pNtk, nFrames, nConfs, nProps, fStruct, fOldAlgo, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( 1,"Transformation has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+usage:
+    Abc_Print( -2, "usage: unfold [-FCP num] [-savh]\n" );
+    Abc_Print( -2, "\t         unfold hidden constraints as separate outputs\n" );
+    Abc_Print( -2, "\t-F num : the max number of timeframes to consider [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-C num : the max number of conflicts in SAT solving [default = %d]\n", nConfs );
+    Abc_Print( -2, "\t-P num : the max number of constraint propagations [default = %d]\n", nProps );
+    Abc_Print( -2, "\t-s     : toggle detecting structural constraints [default = %s]\n", fStruct? "yes": "no" );
+    Abc_Print( -2, "\t-a     : toggle fast implication detection [default = %s]\n", !fOldAlgo? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandFold( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int fCompl;
+    int fVerbose;
+    int c;
+    extern Abc_Ntk_t * Abc_NtkDarFold( Abc_Ntk_t * pNtk, int fCompl, int fVerbose );
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fCompl    =   0;
+    fVerbose  =   0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "cvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'c':
+            fCompl ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" );
+        return 0;
+    }
+    if ( Abc_NtkConstrNum(pNtk) == 0 )
+    {
+        Abc_Print( 0, "The network has no constraints.\n" );
+        return 0;
+    }
+    if ( Abc_NtkIsComb(pNtk) )
+        Abc_Print( 0, "The network is combinational.\n" );
+    // modify the current network
+    pNtkRes = Abc_NtkDarFold( pNtk, fCompl, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( 1,"Transformation has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+usage:
+    Abc_Print( -2, "usage: fold [-cvh]\n" );
+    Abc_Print( -2, "\t         folds constraints represented as separate outputs\n" );
+    Abc_Print( -2, "\t-c     : toggle complementing constraints while folding [default = %s]\n", fCompl? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandBm( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    FILE * pOut, * pErr;
+    Abc_Ntk_t *pNtk, *pNtk1, *pNtk2;
+    int fDelete1, fDelete2;
+    char ** pArgvNew;
+    int c, nArgcNew;
+    int p_equivalence = FALSE;
+    extern void bmGateWay( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int p_equivalence );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Ph" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        case 'P':
+            p_equivalence = 1;
+            break;
+        default:
+            Abc_Print( -2, "Unknown switch.\n");
+            goto usage;
+        }
+    }
+
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew , &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+        return 1;
+
+    if( (unsigned)Abc_NtkPiNum(pNtk1) != (unsigned)Abc_NtkPiNum(pNtk2) || (unsigned)Abc_NtkPoNum(pNtk1) != (unsigned)Abc_NtkPoNum(pNtk2) )
+    {
+        Abc_Print( -2, "Mismatch in the number of inputs or outputs\n");
+        if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+        if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+        return 1;
+    }
+
+    bmGateWay( pNtk1, pNtk2, p_equivalence );
+
+    if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+    if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: bm [-P] <file1> <file2>\n" );
+    Abc_Print( -2, "\t        performs Boolean matching (P-equivalence & PP-equivalence)\n" );
+    Abc_Print( -2, "\t        for equivalent circuits, I/O matches are printed in IOmatch.txt\n" );
+    Abc_Print( -2, "\t-P    : performs P-equivalnce checking\n");
+    Abc_Print( -2, "\t        default is PP-equivalence checking (when -P is not provided)\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    Abc_Print( -2, "\tfile1 : the file with the first network\n");
+    Abc_Print( -2, "\tfile2 : the file with the second network\n");
+
+    Abc_Print( -2, "\t        \n" );
+    Abc_Print( -2, "\t        This command was contributed by Hadi Katebi from U Michigan.\n" );
+    Abc_Print( -2, "\t        The paper describing the method: H. Katebi and I. L. Markov.\n" );
+    Abc_Print( -2, "\t        \"Large-scale Boolean matching\". Proc. DATE 2010. \n" );
+    Abc_Print( -2, "\t        http://www.eecs.umich.edu/~imarkov/pubs/conf/date10-match.pdf\n" );
+//    Abc_Print( -2, "\t        \n" );
+
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandBm2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{   
+    FILE * pOut, * pErr;
+    Abc_Ntk_t *pNtk, *pNtk1, *pNtk2;
+    int fDelete1, fDelete2; 
+    Abc_Obj_t * pObj;
+    char ** pArgvNew;
+    int c, nArgcNew, i; 
+
+    extern void saucyGateWay( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodePo, FILE * gFile, int fBooleanMatching,
+                              int fLookForSwaps, int fFixOutputs, int fFixInputs, int fQuiet, int fPrintTree);
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);  
+    
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;        
+        default:
+            Abc_Print( -2, "Unknown switch.\n");
+            goto usage;
+        }
+    }
+    
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew , &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+        return 1;
+        
+    if( (unsigned)Abc_NtkPiNum(pNtk1) != (unsigned)Abc_NtkPiNum(pNtk2) || 
+        (unsigned)Abc_NtkPoNum(pNtk1) != (unsigned)Abc_NtkPoNum(pNtk2) )
+    {
+        Abc_Print( -2, "Mismatch in the number of inputs or outputs\n");
+        Abc_Print( -2, "*** Networks are NOT equivalent ***\n");
+        if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+        if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+        return 1;
+    }
+    
+    Abc_NtkPermute(pNtk2, 1, 1, 0, NULL );
+    Abc_NtkShortNames(pNtk2);
+
+    Abc_NtkForEachCi( pNtk1, pObj, i ) {
+        char * newName = Abc_ObjNamePrefix( pObj, "N1:" );
+        Nm_ManDeleteIdName( pNtk1->pManName, pObj->Id);
+        Abc_ObjAssignName( pObj, newName, NULL );
+    }
+    Abc_NtkForEachCo( pNtk1, pObj, i ) {
+        char * newName = Abc_ObjNamePrefix( pObj, "N1:" );
+        Nm_ManDeleteIdName( pNtk1->pManName, pObj->Id);
+        Abc_ObjAssignName( pObj, newName, NULL );
+    }
+
+    Abc_NtkForEachCi( pNtk2, pObj, i ) {
+        char * newName = Abc_ObjNamePrefix( pObj, "N2:" );
+        Nm_ManDeleteIdName( pNtk2->pManName, pObj->Id);
+        Abc_ObjAssignName( pObj, newName, NULL );
+    }
+    Abc_NtkForEachCo( pNtk2, pObj, i ) {
+        char * newName = Abc_ObjNamePrefix( pObj, "N2:" );
+        Nm_ManDeleteIdName( pNtk2->pManName, pObj->Id);
+        Abc_ObjAssignName( pObj, newName, NULL );
+    }
+
+    Abc_NtkAppend( pNtk1, pNtk2, 1 );
+    saucyGateWay( pNtk1, NULL, NULL, 1, 0, 0, 0, 0, 0);
+
+    if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+    if ( fDelete2 ) Abc_NtkDelete( pNtk2 );     
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: bm2  <file1> <file2>\n" );
+    Abc_Print( -2, "\t        performs Boolean matching (PP-equivalence)\n" );
+    Abc_Print( -2, "\t        for equivalent circuits, permutation that maps one circuit\n" );
+    Abc_Print( -2, "\t        to another is printed to standard output (PIs and POs of the\n" );
+    Abc_Print( -2, "\t        first network have prefix \"N1:\", while PIs and POs of the\n" ); 
+    Abc_Print( -2, "\t        second network have prefix \"N2:\")\n" ); 
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    Abc_Print( -2, "\tfile1 : the file with the first network\n");
+    Abc_Print( -2, "\tfile2 : the file with the second network\n");
+
+    Abc_Print( -2, "\t        \n" );
+    Abc_Print( -2, "\t        This command was contributed by Hadi Katebi from U Michigan.\n" );
+    Abc_Print( -2, "\t        The paper describing the method: H. Katebi, K. Sakallah and\n");
+    Abc_Print( -2, "\t        I. L. Markov.\n" );
+    Abc_Print( -2, "\t        \"Generalized Boolean Symmetries Through Nested Partition\n");
+    Abc_Print( -2, "\t        Refinement\". Proc. ICCAD 2013. \n" );
+    //Abc_Print( -2, "\t        http://www.eecs.umich.edu/~imarkov/pubs/conf/date10-match.pdf\n" );
+//    Abc_Print( -2, "\t        \n" );
+
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandSaucy( Abc_Frame_t * pAbc, int argc, char ** argv )
+{   
+    Abc_Ntk_t *pNtk;
+    char * outputName = NULL;
+    FILE * gFile = NULL;
+    int fOutputsOneAtTime = 0;
+    int fFixOutputs = 0;
+    int fFixInputs = 0;
+    int fLookForSwaps = 0;
+    int fQuiet = 0;
+    int fPrintTree = 0;
+    int c;
+
+    extern void saucyGateWay( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodePo, FILE * gFile, int fBooleanMatching,
+                              int fLookForSwaps, int fFixOutputs, int fFixInputs, int fQuiet, int fPrintTree);
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "OFiosqvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'O':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-O\" should be followed by an output name or the keyword all.\n" );
+                goto usage;
+            }
+            outputName = argv[globalUtilOptind];
+            if ( !strcmp(argv[globalUtilOptind], "all") )
+                fOutputsOneAtTime ^= 1;
+            globalUtilOptind++;         
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by a file name.\n" );
+                goto usage;
+            }           
+            if ( (gFile = fopen( argv[globalUtilOptind], "w" )) == NULL )
+            {
+                Abc_Print( -1, "Cannot create output file \"%s\". ", argv[globalUtilOptind] );              
+                return 1;
+            }
+            globalUtilOptind++;         
+            break;
+        case 'i':
+            fFixOutputs ^= 1;
+            break;
+        case 'o':
+            fFixInputs ^= 1;
+            break;
+        case 's':
+            fLookForSwaps ^= 1;
+            break;
+        case 'q':
+            fQuiet ^= 1;
+            break;
+        case 'v':
+            fPrintTree ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            Abc_Print( -2, "Unknown switch.\n");
+            goto usage;
+        }
+    }    
+    
+    pNtk = Abc_FrameReadNtk(pAbc);  
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command works only for AIGs (run \"strash\").\n" );
+        return 1;
+    }
+
+    pNtk = Abc_NtkDup( pNtk );
+    Abc_NtkOrderObjsByName( pNtk, 1 );
+
+    if (fOutputsOneAtTime) {
+        int i;
+        Abc_Obj_t * pNodePo;
+        FILE * hadi = fopen("hadi.txt", "w");
+        Abc_NtkForEachPo( pNtk, pNodePo, i ) {
+            printf("Ouput %s\n\n", Abc_ObjName(pNodePo));
+            saucyGateWay( pNtk, pNodePo, gFile, 0, fLookForSwaps, fFixOutputs, fFixInputs, fQuiet, fPrintTree );
+            printf("----------------------------------------\n");           
+        }
+        fclose(hadi);
+    } else if (outputName != NULL) {
+        int i;
+        Abc_Obj_t * pNodePo;        
+        Abc_NtkForEachPo( pNtk, pNodePo, i ) {
+            if (!strcmp(Abc_ObjName(pNodePo), outputName)) {
+                saucyGateWay( pNtk, pNodePo, gFile, 0, fLookForSwaps, fFixOutputs, fFixInputs, fQuiet, fPrintTree );
+                Abc_NtkDelete( pNtk );
+                return 0;
+            }   
+        }
+        Abc_Print( -1, "Output not found\n" );
+        return 1;       
+    } else
+        saucyGateWay( pNtk, NULL, gFile, 0, fLookForSwaps, fFixOutputs, fFixInputs, fQuiet, fPrintTree );
+
+    if (gFile != NULL) fclose(gFile);
+    Abc_NtkDelete( pNtk );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: saucy3 [-O <name>] [-F <file>] [-iosqvh]\n\n" );
+    Abc_Print( -2, "\t            computes functional symmetries of the netowrk\n" );
+    Abc_Print( -2, "\t            prints symmetry generators to the standard output\n" );   
+    Abc_Print( -2, "\t-O <name> : (optional) compute symmetries only for output given by name\n");
+    Abc_Print( -2, "\t            only inputs in the output cone are permuted\n");  
+    Abc_Print( -2, "\t            (special case) name=all, compute symmetries for each\n" );
+    Abc_Print( -2, "\t            output, but only one output at a time\n" );
+    Abc_Print( -2, "\t            [default = compute symmetries by permuting all I/Os]\n" );
+    Abc_Print( -2, "\t-F <file> : print symmetry generators to file [default = stdout]\n");
+    Abc_Print( -2, "\t-i        : permute just the inputs (fix the outputs) [default = no]\n");
+    Abc_Print( -2, "\t-o        : permute just the outputs (fix the inputs) [default = no]\n");
+    Abc_Print( -2, "\t-s        : only look for swaps of inputs [default = no]\n");
+    Abc_Print( -2, "\t-q        : quiet (do not print symmetry generators) [default = no]\n");
+    Abc_Print( -2, "\t-v        : verbose (print the search tree) [default = no]\n");   
+    Abc_Print( -2, "\t-h        : print the command usage\n"); 
+
+    Abc_Print( -2, "\t            \n" );
+    Abc_Print( -2, "\t            This command was contributed by Hadi Katebi from U Michigan.\n" );
+    Abc_Print( -2, "\t            The paper describing the method: H. Katebi, K. Sakallah and\n");
+    Abc_Print( -2, "\t            I. L. Markov.\n" );
+    Abc_Print( -2, "\t            \"Generalized Boolean Symmetries Through Nested Partition\n");
+    Abc_Print( -2, "\t            Refinement\". Proc. ICCAD 2013. \n" );
+    //Abc_Print( -2, "\t          http://www.eecs.umich.edu/~imarkov/pubs/conf/date10-match.pdf\n" );
+    Abc_Print( -2, "\t            Saucy webpage: http://vlsicad.eecs.umich.edu/BK/SAUCY/\n" );
+
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandTestCex( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk;
+    int c;
+    int nOutputs = 0;
+    int fCheckAnd = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Oah" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'O':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nOutputs = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nOutputs < 0 )
+                goto usage;
+            break;
+        case 'a':
+            fCheckAnd ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            Abc_Print( -2, "Unknown switch.\n");
+            goto usage;
+        }
+    }
+
+    if ( pAbc->pCex == NULL )
+    {
+        Abc_Print( 1, "There is no current cex.\n");
+        return 0;
+    }
+
+    if ( !fCheckAnd )
+    {
+        // check the main AIG
+        pNtk = Abc_FrameReadNtk(pAbc);
+        if ( pNtk == NULL )
+            Abc_Print( 1, "Main AIG: There is no current network.\n");
+        else if ( !Abc_NtkIsStrash(pNtk) )
+            Abc_Print( 1, "Main AIG: The current network is not an AIG.\n");
+        else if ( Abc_NtkPiNum(pNtk) != pAbc->pCex->nPis )
+            Abc_Print( 1, "Main AIG: The number of PIs (%d) is different from cex (%d).\n", Abc_NtkPiNum(pNtk), pAbc->pCex->nPis );
+        else
+        {
+            extern int Abc_NtkVerifyCex( Abc_Ntk_t * pNtk, Abc_Cex_t * p );
+            int iPoOld = pAbc->pCex->iPo;
+            pAbc->pCex->iPo = Abc_NtkVerifyCex( pNtk, pAbc->pCex );
+            if ( pAbc->pCex->iPo == -1 )
+                Abc_Print( 1, "Main AIG: The cex does not fail any outputs.\n" );
+            else if ( iPoOld != pAbc->pCex->iPo )
+                Abc_Print( 1, "Main AIG: The cex refined PO %d instead of PO %d.\n", pAbc->pCex->iPo, iPoOld );
+            else
+                Abc_Print( 1, "Main AIG: The cex is correct.\n" );
+        }
+    }
+    else
+    {
+        // check the AND AIG
+        if ( pAbc->pGia == NULL )
+            Abc_Print( 1, "And  AIG: There is no current network.\n");
+        else if ( Gia_ManPiNum(pAbc->pGia) != pAbc->pCex->nPis )
+            Abc_Print( 1, "And  AIG: The number of PIs (%d) is different from cex (%d).\n", Gia_ManPiNum(pAbc->pGia), pAbc->pCex->nPis );
+        else
+        {
+            int iPoOld = pAbc->pCex->iPo;
+            pAbc->pCex->iPo = Gia_ManFindFailedPoCex( pAbc->pGia, pAbc->pCex, nOutputs );
+            if ( pAbc->pCex->iPo == -1 )
+                Abc_Print( 1, "And  AIG: The cex does not fail any outputs.\n" );
+            else if ( iPoOld != pAbc->pCex->iPo )
+                Abc_Print( 1, "And  AIG: The cex refined PO %d instead of PO %d.\n", pAbc->pCex->iPo, iPoOld );
+            else
+                Abc_Print( 1, "And  AIG: The cex is correct.\n" );
+        }
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: testcex [-O num] [-ah]\n" );
+    Abc_Print( -2, "\t         tests the current cex against the current AIG or the &-AIG\n" );
+    Abc_Print( -2, "\t-O num : the number of real POs in the PO list [default = %d]\n", nOutputs );
+    Abc_Print( -2, "\t-a     : toggle checking the current AIG or the &-AIG [default = %s]\n", fCheckAnd ? "&-AIG": "current AIG" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPdr( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern int Abc_NtkDarPdr( Abc_Ntk_t * pNtk, Pdr_Par_t * pPars );
+    Pdr_Par_t Pars, * pPars = &Pars;
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    Pdr_ManSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "MFCRTHGaxrmsipdgvwzh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRecycle = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRecycle < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFrameMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFrameMax < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nConfLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nConfLimit < 0 )
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRestLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRestLimit < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nTimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nTimeOut < 0 )
+                goto usage;
+            break;
+        case 'H':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-H\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nTimeOutOne = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nTimeOutOne < 0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nTimeOutGap = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nTimeOutGap < 0 )
+                goto usage;
+            break;
+        case 'a':
+            pPars->fSolveAll ^= 1;
+            break;
+        case 'x':
+            pPars->fStoreCex ^= 1;
+            break;
+        case 'r':
+            pPars->fTwoRounds ^= 1;
+            break;
+        case 'm':
+            pPars->fMonoCnf ^= 1;
+            break;
+        case 's':
+            pPars->fShortest ^= 1;
+            break;
+        case 'i':
+            pPars->fShiftStart ^= 1;
+            break;
+        case 'p':
+            pPars->fReuseProofOblig ^= 1;
+            break;
+        case 'd':
+            pPars->fDumpInv ^= 1;
+            break;
+        case 'g':
+            pPars->fSkipGeneral ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'z':
+            pPars->fNotVerbose ^= 1;
+            break;
+        case 'h':
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -2, "There is no current network.\n");
+        return 0;
+    }
+    if ( Abc_NtkLatchNum(pNtk) == 0 )
+    {
+        Abc_Print( -2, "The current network is combinational.\n");
+        return 0;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -2, "The current network is not an AIG (run \"strash\").\n");
+        return 0;
+    }
+    // run the procedure
+    pPars->fUseBridge = pAbc->fBridgeMode;
+    pAbc->Status  = Abc_NtkDarPdr( pNtk, pPars );
+    pAbc->nFrames = pNtk->vSeqModelVec ? -1 : pPars->iFrame;
+    Abc_FrameReplacePoStatuses( pAbc, &pPars->vOutMap );
+    if ( pNtk->vSeqModelVec )
+        Abc_FrameReplaceCexVec( pAbc, &pNtk->vSeqModelVec );
+    else
+        Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: pdr [-MFCRTHG <num>] [-axrmsipdgvwzh]\n" );
+    Abc_Print( -2, "\t         model checking using property directed reachability (aka IC3)\n" );
+    Abc_Print( -2, "\t         pioneered by Aaron Bradley (http://ecee.colorado.edu/~bradleya/ic3/)\n" );
+    Abc_Print( -2, "\t         with improvements by Niklas Een (http://een.se/niklas/)\n" );
+    Abc_Print( -2, "\t-M num : limit on unused vars to trigger SAT solver recycling [default = %d]\n",       pPars->nRecycle );
+    Abc_Print( -2, "\t-F num : limit on timeframes explored to stop computation [default = %d]\n",           pPars->nFrameMax );
+    Abc_Print( -2, "\t-C num : limit on conflicts in one SAT call (0 = no limit) [default = %d]\n",          pPars->nConfLimit );
+    Abc_Print( -2, "\t-R num : limit on proof obligations before a restart (0 = no limit) [default = %d]\n", pPars->nRestLimit );
+    Abc_Print( -2, "\t-T num : runtime limit, in seconds (0 = no limit) [default = %d]\n",                   pPars->nTimeOut );
+    Abc_Print( -2, "\t-H num : runtime limit per output, in miliseconds (with \"-a\") [default = %d]\n",     pPars->nTimeOutOne );
+    Abc_Print( -2, "\t-G num : runtime gap since the last CEX (0 = no limit) [default = %d]\n",              pPars->nTimeOutGap );
+    Abc_Print( -2, "\t-a     : toggle solving all outputs even if one of them is SAT [default = %s]\n",      pPars->fSolveAll? "yes": "no" );
+    Abc_Print( -2, "\t-x     : toggle storing CEXes when solving all outputs [default = %s]\n",              pPars->fStoreCex? "yes": "no" );
+    Abc_Print( -2, "\t-r     : toggle using more effort in generalization [default = %s]\n",                 pPars->fTwoRounds? "yes": "no" );
+    Abc_Print( -2, "\t-m     : toggle using monolythic CNF computation [default = %s]\n",                    pPars->fMonoCnf? "yes": "no" );
+    Abc_Print( -2, "\t-s     : toggle creating only shortest counter-examples [default = %s]\n",             pPars->fShortest? "yes": "no" );
+    Abc_Print( -2, "\t-i     : toggle clause pushing from an intermediate timeframe [default = %s]\n",       pPars->fShiftStart? "yes": "no" );
+    Abc_Print( -2, "\t-p     : toggle reusing proof-obligations in the last timeframe [default = %s]\n",     pPars->fReuseProofOblig? "yes": "no" );
+    Abc_Print( -2, "\t-d     : toggle dumping invariant (valid if init state is all-0) [default = %s]\n",    pPars->fDumpInv? "yes": "no" );
+    Abc_Print( -2, "\t-g     : toggle skipping expensive generalization step [default = %s]\n",              pPars->fSkipGeneral? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing optimization summary [default = %s]\n",                       pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle printing detailed stats default = %s]\n",                              pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-z     : toggle suppressing report about solved outputs [default = %s]\n",             pPars->fNotVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandReconcile( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Abc_Cex_t * Llb4_Nonlin4NormalizeCex( Aig_Man_t * pAigOrg, Aig_Man_t * pAigRpm, Abc_Cex_t * pCexRpm );
+    Abc_Cex_t * pCex;
+    Abc_Ntk_t * pNtk1 = NULL, * pNtk2 = NULL;
+    Aig_Man_t * pAig1 = NULL, * pAig2 = NULL;
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            Abc_Print( -2, "Unknown switch.\n");
+            goto usage;
+        }
+    }
+
+    if ( argc != globalUtilOptind + 2 && argc != globalUtilOptind )
+    {
+        Abc_Print( 1,"Does not seen to have two files names as arguments.\n" );
+        return 1;
+    }
+    if ( pAbc->pCex == NULL )
+    {
+        Abc_Print( 1,"There is no current counter-example.\n" );
+        return 1;
+    }
+
+    if ( argc == globalUtilOptind + 2 )
+    {
+        // derive networks
+        pNtk1 = Io_Read( argv[globalUtilOptind], Io_ReadFileType(argv[globalUtilOptind]), 1, 0 );
+        if ( pNtk1 == NULL )
+            return 1;
+        pNtk2 = Io_Read( argv[globalUtilOptind+1], Io_ReadFileType(argv[globalUtilOptind+1]), 1, 0 );
+        if ( pNtk2 == NULL )
+        {
+            Abc_NtkDelete( pNtk1 );
+            return 1;
+        }
+        // create counter-examples
+        pAig1 = Abc_NtkToDar( pNtk1, 0, 0 );
+        pAig2 = Abc_NtkToDar( pNtk2, 0, 0 );
+    }
+    else if ( argc == globalUtilOptind )
+    {
+        if ( pAbc->pNtkCur == NULL )
+        {
+            Abc_Print( 1, "There is no AIG in the main-space.\n");
+            return 0;
+        }
+        if ( pAbc->pGia == NULL )
+        {
+            Abc_Print( 1, "There is no AIG in the &-space.\n");
+            return 0;
+        }
+        // create counter-examples
+        pAig1 = Abc_NtkToDar( pAbc->pNtkCur, 0, 0 );
+        pAig2 = Gia_ManToAigSimple( pAbc->pGia );
+    }
+    else assert( 0 );
+    pCex = Llb4_Nonlin4NormalizeCex( pAig1, pAig2, pAbc->pCex );
+    Aig_ManStop( pAig1 );
+    Aig_ManStop( pAig2 );
+    if ( pNtk2 )  Abc_NtkDelete( pNtk2 );
+    if ( pCex == NULL )
+    {
+        Abc_Print( 1,"Counter-example computation has failed.\n" );
+        if ( pNtk1 )  Abc_NtkDelete( pNtk1 );
+        return 1;
+    }
+
+    // replace the current network
+    if ( pNtk1 )
+        Abc_FrameReplaceCurrentNetwork( pAbc, pNtk1 );
+    // update the counter-example
+    pAbc->nFrames = pCex->iFrame;
+    Abc_FrameReplaceCex( pAbc, &pCex );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: reconcile [-h] <fileOrigin> <fileReparam>\n" );
+    Abc_Print( -2, "\t        reconciles current CEX with <fileOrigin>\n" );
+    Abc_Print( -2, "\t        More specifically:\n" );
+    Abc_Print( -2, "\t        (i) assumes that <fileReparam> is an AIG derived by input\n" );
+    Abc_Print( -2, "\t        reparametrization of <fileOrigin> without seq synthesis;\n" );
+    Abc_Print( -2, "\t        (ii) assumes that current CEX is valid for <fileReparam>;\n" );
+    Abc_Print( -2, "\t        (iii) derives new CEX for <fileOrigin> and sets this CEX\n" );
+    Abc_Print( -2, "\t        and <fileOrigin> to be current CEX and current network\n" );
+    Abc_Print( -2, "\t<fileOrigin>   : file name with the original AIG\n");
+    Abc_Print( -2, "\t<fileReparam>  : file name with the reparametrized AIG\n");
+    Abc_Print( -2, "\t        (if both file names are not given on the command line,\n");
+    Abc_Print( -2, "\t        original/reparam AIG has to be in the main-space/&-space)\n");
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCexSave( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pCex == NULL )
+    {
+        Abc_Print( -1, "Current CEX is not available..\n" );
+        return 1;
+    }
+    ABC_FREE( pAbc->pCex2 );
+    pAbc->pCex2 = Abc_CexDup( pAbc->pCex, -1 );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: cexsave [-h]\n" );
+    Abc_Print( -2, "\t        saves the current CEX into the internal storage\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCexLoad( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pCex2 == NULL )
+    {
+        Abc_Print( -1, "Saved CEX is not available.\n" );
+        return 1;
+    }
+    ABC_FREE( pAbc->pCex );
+    pAbc->pCex = Abc_CexDup( pAbc->pCex2, -1 );
+    // update status
+    pAbc->nFrames = pAbc->pCex2->iFrame;
+    pAbc->Status = 0;
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: cexload [-h]\n" );
+    Abc_Print( -2, "\t        loads the current CEX from the internal storage\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCexCut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtkNew;
+    int c, iFrStart = 0;
+    int iFrStop     = ABC_INFINITY;
+    int fCombOnly   = 0;
+    int fUseOne     = 0;
+    int fAllFrames  = 0;
+    int fVerbose    = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FGcnmvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iFrStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iFrStart < 0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iFrStop = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iFrStop < 0 )
+                goto usage;
+            break;
+        case 'c':
+            fCombOnly ^= 1;
+            break;
+        case 'n':
+            fUseOne ^= 1;
+            break;
+        case 'm':
+            fAllFrames ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            Abc_Print( -2, "Unknown switch.\n");
+            goto usage;
+        }
+    }
+
+    if ( pAbc->pCex == NULL )
+    {
+        Abc_Print( 1, "There is no current cex.\n");
+        return 0;
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        Abc_Print( 1, "There is no AIG in the &-space.\n");
+        return 0;
+    }
+    if ( !Abc_NtkIsStrash(pAbc->pNtkCur) )
+    {
+        Abc_Print( 1, "Current network is not an AIG.\n");
+        return 0;
+    }
+    if ( iFrStop == ABC_INFINITY )
+        iFrStop = pAbc->pCex->iFrame;
+
+    {
+        Aig_Man_t * pAig = Abc_NtkToDar( pAbc->pNtkCur, 0, 1 );
+        Aig_Man_t * pAigNew = Bmc_AigTargetStates( pAig, pAbc->pCex, iFrStart, iFrStop, fCombOnly, fUseOne, fAllFrames, fVerbose );
+        Aig_ManStop( pAig );
+        if ( pAigNew == NULL )
+        {
+            Abc_Print( 1, "Command has failed.\n");
+            return 0;
+        }
+        pNtkNew = Abc_NtkFromAigPhase( pAigNew );
+        pNtkNew->pName = Extra_UtilStrsav( pAbc->pNtkCur->pName );
+        Aig_ManStop( pAigNew );
+        // update the network
+        Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew );
+    }
+/*
+    pGiaNew = Bmc_GiaTargetStates( pAbc->pGia, pAbc->pCex, iFrStart, iFrStop, fCombOnly, fUseOne, fVerbose );
+    if ( pGiaNew == NULL )
+    {
+        Abc_Print( 1, "Command has failed.\n");
+        return 0;
+    }
+    Abc_FrameUpdateGia( pAbc, pGiaNew );
+*/
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: cexcut [-FG num] [-cnmvh]\n" );
+    Abc_Print( -2, "\t         creates logic for bad states using the current CEX\n" );
+    Abc_Print( -2, "\t-F num : 0-based number of the starting frame [default = %d]\n", iFrStart );
+    Abc_Print( -2, "\t-G num : 0-based number of the ending frame [default = %d]\n",   iFrStop );
+    Abc_Print( -2, "\t-c     : toggle outputting unate combinational circuit [default = %s]\n",  fCombOnly? "yes": "no" );
+    Abc_Print( -2, "\t-n     : toggle generating only one bad state [default = %s]\n", fUseOne? "yes": "no" );
+    Abc_Print( -2, "\t-m     : toggle generating bad states for all frames after G [default = %s]\n", fAllFrames? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n",  fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCexMerge( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Cex_t * pCexNew;
+    int c;
+    int iFrStart = 0;
+    int iFrStop  = ABC_INFINITY;
+    int fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FGvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iFrStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iFrStart < 0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iFrStop = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iFrStop < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            Abc_Print( -2, "Unknown switch.\n");
+            goto usage;
+        }
+    }
+
+    if ( pAbc->pCex == NULL )
+    {
+        Abc_Print( 1, "There is no current cex.\n");
+        return 0;
+    }
+    if ( pAbc->pCex2 == NULL )
+    {
+        Abc_Print( 1, "There is no saved cex.\n");
+        return 0;
+    }
+    if ( iFrStop - iFrStart + pAbc->pCex->iPo < pAbc->pCex->iFrame )
+    {
+        Abc_Print( 1, "Current CEX does not allow to shorten the saved CEX.\n");
+        return 0;
+    }
+    pCexNew = Abc_CexMerge( pAbc->pCex2, pAbc->pCex, iFrStart, iFrStop );
+    if ( pCexNew == NULL )
+    {
+        Abc_Print( 1, "Merging CEXes has failed.\n");
+        return 0;
+    }
+    // replace the saved CEX
+    ABC_FREE( pAbc->pCex2 );
+    pAbc->pCex2 = pCexNew;
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: cexmerge [-FG num] [-vh]\n" );
+    Abc_Print( -2, "\t         merges the current CEX into the saved one\n" );
+    Abc_Print( -2, "\t         and sets the resulting CEX as the saved one\n" );
+    Abc_Print( -2, "\t-F num : 0-based number of the starting frame [default = %d]\n", iFrStart );
+    Abc_Print( -2, "\t-G num : 0-based number of the ending frame [default = %d]\n",   iFrStop );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandCexMin( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk;
+    Abc_Cex_t * vCexNew = NULL;
+    int c;
+    int nConfLimit = 1000;
+    int nRounds    =    1;
+    int fVerbose   =    0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "CRvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfLimit < 0 )
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nRounds = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nRounds < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            Abc_Print( -2, "Unknown switch.\n");
+            goto usage;
+        }
+    }
+
+    if ( pAbc->pCex == NULL )
+    {
+        Abc_Print( 1, "There is no current cex.\n");
+        return 0;
+    }
+
+    // check the main AIG
+    pNtk = Abc_FrameReadNtk(pAbc);
+    if ( pNtk == NULL )
+        Abc_Print( 1, "Main AIG: There is no current network.\n");
+    else if ( !Abc_NtkIsStrash(pNtk) )
+        Abc_Print( 1, "Main AIG: The current network is not an AIG.\n");
+    else if ( Abc_NtkPiNum(pNtk) != pAbc->pCex->nPis )
+        Abc_Print( 1, "Main AIG: The number of PIs (%d) is different from cex (%d).\n", Abc_NtkPiNum(pNtk), pAbc->pCex->nPis );
+//      else if ( Abc_NtkLatchNum(pNtk) != pAbc->pCex->nRegs )
+//          Abc_Print( 1, "Main AIG: The number of registers (%d) is different from cex (%d).\n", Abc_NtkLatchNum(pNtk), pAbc->pCex->nRegs );
+//      else if ( Abc_NtkPoNum(pNtk) <= pAbc->pCex->iPo )
+//          Abc_Print( 1, "Main AIG: The number of POs (%d) is less than the PO index in cex (%d).\n", Abc_NtkPoNum(pNtk), pAbc->pCex->iPo );
+    else
+    {
+        Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 );
+        Gia_Man_t * pGia = Gia_ManFromAigSimple( pAig );
+//        if ( !Gia_ManVerifyCex( pGia, pAbc->pCex, 0 ) )
+        int iPoOld = pAbc->pCex->iPo;
+        pAbc->pCex->iPo = Gia_ManFindFailedPoCex( pGia, pAbc->pCex, 0 );
+        Gia_ManStop( pGia );
+        if ( pAbc->pCex->iPo == -1 )
+        {
+            pAbc->pCex->iPo = iPoOld;
+            Abc_Print( -1, "Main AIG: The cex does not fail any outputs.\n" );
+            return 0;
+        }
+        else if ( iPoOld != pAbc->pCex->iPo )
+            Abc_Print( 0, "Main AIG: The cex refined PO %d instead of PO %d.\n", pAbc->pCex->iPo, iPoOld );
+        // perform minimization
+        vCexNew = Saig_ManCexMinPerform( pAig, pAbc->pCex );
+        Aig_ManStop( pAig );
+        Abc_CexFree( vCexNew );
+//        Abc_FrameReplaceCex( pAbc, &vCexNew );
+
+//        Abc_Print( 1,"Implementation of this command is not finished.\n" );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: cexmin [-CR num] [-vh]\n" );
+    Abc_Print( -2, "\t         reduces the length of the counter-example\n" );
+    Abc_Print( -2, "\t-C num : the maximum number of conflicts [default = %d]\n", nConfLimit );
+    Abc_Print( -2, "\t-R num : the number of minimization rounds [default = %d]\n", nRounds );
+    Abc_Print( -2, "\t-v     : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandDualRail( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Vec_Int_t * Abc_NtkFindDcLatches( Abc_Ntk_t * pNtk );
+    Abc_Ntk_t * pNtk, * pNtkNew = NULL;
+    Aig_Man_t * pAig, * pAigNew;
+    Vec_Int_t * vDcFlops = NULL;
+    int c;
+    int nDualPis   = 0;
+    int fDualFfs   = 0;
+    int fDualDcFfs = 0;
+    int fMiterFfs  = 0;
+    int fComplPo   = 0;
+    int fCheckZero = 0;
+    int fCheckOne  = 0;
+    int fVerbose   = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Itxfczovh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nDualPis = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nDualPis < 0 )
+                goto usage;
+            break;
+        case 't':
+            fDualFfs ^= 1;
+            break;
+        case 'x':
+            fDualDcFfs ^= 1;
+            break;
+        case 'f':
+            fMiterFfs ^= 1;
+            break;
+        case 'c':
+            fComplPo ^= 1;
+            break;
+        case 'z':
+            fCheckZero ^= 1;
+            break;
+        case 'o':
+            fCheckOne ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            Abc_Print( -2, "Unknown switch.\n");
+            goto usage;
+        }
+    }
+
+    // check the main AIG
+    pNtk = Abc_FrameReadNtk(pAbc);
+    if ( pNtk == NULL )
+    {
+        Abc_Print( 1, "Main AIG: There is no current network.\n");
+        return 0;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( 1, "Main AIG: The current network is not an AIG.\n");
+        return 0;
+    }
+
+    if ( fDualDcFfs )
+        vDcFlops = Abc_NtkFindDcLatches( pNtk );
+
+    // transform
+    pAig = Abc_NtkToDar( pNtk, 0, 1 );
+    pAigNew = Saig_ManDupDual( pAig, vDcFlops, nDualPis, fDualFfs, fMiterFfs, fComplPo, fCheckZero, fCheckOne );
+    Aig_ManStop( pAig );
+    pNtkNew = Abc_NtkFromAigPhase( pAigNew );
+    pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+    Aig_ManStop( pAigNew );
+    Vec_IntFreeP( &vDcFlops );
+
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: dualrail [-I num] [-txfczovh]\n" );
+    Abc_Print( -2, "\t         transforms the current AIG into a dual-rail miter\n" );
+    Abc_Print( -2, "\t         expressing the property \"at least one PO has ternary value\"\n" );
+    Abc_Print( -2, "\t         (to compute an initialization sequence, use switches \"-tfc\")\n" );
+    Abc_Print( -2, "\t-I num : the number of first PIs interpreted as ternary [default = %d]\n", nDualPis );
+    Abc_Print( -2, "\t-t     : toggle ternary flop init values for all flops [default = %s]\n", fDualFfs? "yes": "const0 init values" );
+    Abc_Print( -2, "\t-x     : toggle ternary flop init values for DC-valued flops [default = %s]\n", fDualDcFfs? "yes": "const0 init values" );
+    Abc_Print( -2, "\t-f     : toggle mitering flops instead of POs [default = %s]\n", fMiterFfs? "flops": "POs" );
+    Abc_Print( -2, "\t-c     : toggle complementing the miter output [default = %s]\n", fComplPo? "yes": "no" );
+    Abc_Print( -2, "\t-z     : toggle checking PO==0 instead of PO==X [default = %s]\n", fCheckZero? "yes": "no" );
+    Abc_Print( -2, "\t-o     : toggle checking PO==1 instead of PO==X [default = %s]\n", fCheckOne? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandBlockPo( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkNew = NULL;
+    Aig_Man_t * pAig;
+    int c;
+    int nCycles = 0;
+    int fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nCycles = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nCycles < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            Abc_Print( -2, "Unknown switch.\n");
+            goto usage;
+        }
+    }
+
+    // check the main AIG
+    pNtk = Abc_FrameReadNtk(pAbc);
+    if ( pNtk == NULL )
+    {
+        Abc_Print( 1, "Main AIG: There is no current network.\n");
+        return 0;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( 1, "Main AIG: The current network is not an AIG.\n");
+        return 0;
+    }
+    if ( nCycles == 0 )
+    {
+        Abc_Print( 1, "The number of time frame is 0. The circuit is left unchanged.\n" );
+        return 0;
+    }
+
+    // transform
+    pAig = Abc_NtkToDar( pNtk, 0, 1 );
+    Saig_ManBlockPo( pAig, nCycles );
+    pNtkNew = Abc_NtkFromAigPhase( pAig );
+    Aig_ManStop( pAig );
+    // transfer the name
+    pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+    pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: blockpo [-F num] [-fvh]\n" );
+    Abc_Print( -2, "\t         forces the miter outputs to be \"true\" in the first F frames\n" );
+    Abc_Print( -2, "\t-F num : the number of time frames [default = %d]\n", nCycles );
+    Abc_Print( -2, "\t-v     : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandIso( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkNew = NULL;
+    Aig_Man_t * pAig, * pTemp;
+    Vec_Ptr_t * vPosEquivs = NULL;
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            Abc_Print( -2, "Unknown switch.\n");
+            goto usage;
+        }
+    }
+
+    // check the main AIG
+    pNtk = Abc_FrameReadNtk(pAbc);
+    if ( pNtk == NULL )
+    {
+        Abc_Print( 1, "Main AIG: There is no current network.\n");
+        return 0;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( 1, "Main AIG: The current network is not an AIG.\n");
+        return 0;
+    }
+    if ( Abc_NtkPoNum(pNtk) == 1 )
+    {
+        Abc_Print( 1, "Current AIG has only one PO. Transformation is not performed.\n");
+        return 0;
+    }
+
+    // transform
+    pAig = Abc_NtkToDar( pNtk, 0, 1 );
+    pTemp = Saig_ManIsoReduce( pAig, &vPosEquivs, fVerbose );
+    pNtkNew = Abc_NtkFromAigPhase( pTemp );
+    Aig_ManStop( pTemp );
+    Aig_ManStop( pAig );
+
+    // update the internal storage of PO equivalences
+    Abc_FrameReplacePoEquivs( pAbc, &vPosEquivs );
+
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: iso [-vh]\n" );
+    Abc_Print( -2, "\t         removes POs with isomorphic sequential COI\n" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandTraceStart( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command is applicable to AIGs.\n" );
+        return 1;
+    }
+/*
+    Abc_HManStart();
+    if ( !Abc_HManPopulate( pNtk ) )
+    {
+        Abc_Print( -1, "Failed to start the tracing database.\n" );
+        return 1;
+    }
+*/
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: trace_start [-h]\n" );
+    Abc_Print( -2, "\t        starts verification tracing\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandTraceCheck( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "This command is applicable to AIGs.\n" );
+        return 1;
+    }
+/*
+    if ( !Abc_HManIsRunning(pNtk) )
+    {
+        Abc_Print( -1, "The tracing database is not available.\n" );
+        return 1;
+    }
+
+    if ( !Abc_HManVerify( 1, pNtk->Id ) )
+        Abc_Print( -1, "Verification failed.\n" );
+    Abc_HManStop();
+*/
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: trace_check [-h]\n" );
+    Abc_Print( -2, "\t        checks the current network using verification trace\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Read( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pAig;
+    FILE * pFile;
+    char ** pArgvNew;
+    char * FileName, * pTemp;
+    int c, nArgcNew;
+    int fUseMini = 0;
+    int fVerbose = 0;
+    int fSkipStrash = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "smvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 's':
+            fSkipStrash ^= 1;
+            break;
+        case 'm':
+            fUseMini ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( nArgcNew != 1 )
+    {
+        Abc_Print( -1, "There is no file name.\n" );
+        return 1;
+    }
+
+    // get the input file name
+    FileName = pArgvNew[0];
+    // fix the wrong symbol
+    for ( pTemp = FileName; *pTemp; pTemp++ )
+        if ( *pTemp == '>' )
+            *pTemp = '\\';
+    if ( (pFile = fopen( FileName, "r" )) == NULL )
+    {
+        Abc_Print( -1, "Cannot open input file \"%s\". ", FileName );
+        if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", ".blif", ".pla", ".eqn", ".bench" )) )
+            Abc_Print( 1, "Did you mean \"%s\"?", FileName );
+        Abc_Print( 1, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+
+    if ( fUseMini )
+        pAig = Gia_ManReadMiniAig( FileName );
+    else
+        pAig = Gia_AigerRead( FileName, fSkipStrash, 0 );
+    Abc_FrameUpdateGia( pAbc, pAig );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &r [-smvh] <file>\n" );
+    Abc_Print( -2, "\t         reads the current AIG from the AIGER file\n" );
+    Abc_Print( -2, "\t-s     : toggles structural hashing while reading [default = %s]\n", !fSkipStrash? "yes": "no" );
+    Abc_Print( -2, "\t-m     : toggles reading MiniAIG rather than AIGER file [default = %s]\n", fUseMini? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : the file name\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9ReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Gia_Man_t * Abc_NtkHieCecTest( char * pFileName, int fVerbose );
+    Gia_Man_t * pAig;
+    FILE * pFile;
+    char ** pArgvNew;
+    char * FileName, * pTemp;
+    int nArgcNew;
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( nArgcNew != 1 )
+    {
+        Abc_Print( -1, "There is no file name.\n" );
+        return 1;
+    }
+
+    // get the input file name
+    FileName = pArgvNew[0];
+    // fix the wrong symbol
+    for ( pTemp = FileName; *pTemp; pTemp++ )
+        if ( *pTemp == '>' )
+            *pTemp = '\\';
+    if ( (pFile = fopen( FileName, "r" )) == NULL )
+    {
+        Abc_Print( -1, "Cannot open input file \"%s\". ", FileName );
+        if ( (FileName = Extra_FileGetSimilarName( FileName, ".blif", NULL, NULL, NULL, NULL )) )
+            Abc_Print( 1, "Did you mean \"%s\"?", FileName );
+        Abc_Print( 1, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+
+    pAig = Abc_NtkHieCecTest( FileName, fVerbose );
+    Abc_FrameUpdateGia( pAbc, pAig );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &read_blif [-vh] <file>\n" );
+    Abc_Print( -2, "\t         a specialized reader for hierarchical BLIF files\n" );
+    Abc_Print( -2, "\t         (for general-purpose BLIFs, please use \"read_blif\")\n" );
+    Abc_Print( -2, "\t-v     : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : the file name\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9ReadCBlif( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Gia_Man_t * Abc_NtkHieCecTest2( char * pFileName, char * pModelName, int fVerbose );
+    Gia_Man_t * pAig;
+    FILE * pFile;
+    char ** pArgvNew;
+    char * FileName, * pTemp;
+    char * pModelName = NULL;
+    int nArgcNew;
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Mvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pModelName = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( nArgcNew != 1 )
+    {
+        Abc_Print( -1, "There is no file name.\n" );
+        return 1;
+    }
+
+    // get the input file name
+    FileName = pArgvNew[0];
+    // fix the wrong symbol
+    for ( pTemp = FileName; *pTemp; pTemp++ )
+        if ( *pTemp == '>' )
+            *pTemp = '\\';
+    if ( (pFile = fopen( FileName, "r" )) == NULL )
+    {
+        Abc_Print( -1, "Cannot open input file \"%s\". ", FileName );
+        if ( (FileName = Extra_FileGetSimilarName( FileName, ".cblif", NULL, NULL, NULL, NULL )) )
+            Abc_Print( 1, "Did you mean \"%s\"?", FileName );
+        Abc_Print( 1, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+
+    pAig = Abc_NtkHieCecTest2( FileName, pModelName, fVerbose );
+    Abc_FrameUpdateGia( pAbc, pAig );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &read_cblif [-M name] [-vh] <file>\n" );
+    Abc_Print( -2, "\t         reads CBLIF file and collapse it into an AIG\n" );
+    Abc_Print( -2, "\t-M name: module name to collapse [default = <root_module>]\n" );
+    Abc_Print( -2, "\t-v     : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : the file name\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9ReadStg( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pAig;
+    FILE * pFile;
+    char * FileName, ** pArgvNew;
+    int c, nArgcNew;
+    int kHot = 1;
+    int fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Kvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            kHot = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( kHot < 1 || kHot > 5 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( nArgcNew != 1 )
+    {
+        Abc_Print( -1, "There is no file name.\n" );
+        return 1;
+    }
+
+    // get the input file name
+    FileName = pArgvNew[0];
+    if ( (pFile = fopen( FileName, "r" )) == NULL )
+    {
+        Abc_Print( -1, "Cannot open input file \"%s\". ", FileName );
+        return 1;
+    }
+    fclose( pFile );
+
+    pAig = Gia_ManStgRead( FileName, kHot, fVerbose );
+    Abc_FrameUpdateGia( pAbc, pAig );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &read_stg [-K <num>] [-vh] <file>\n" );
+    Abc_Print( -2, "\t         reads STG file and generates K-hot-encoded AIG\n" );
+    Abc_Print( -2, "\t-K num : the K parameter for hotness of the encoding (1 <= K <= 5) [default = %d]\n", kHot );
+    Abc_Print( -2, "\t-v     : toggles printing state codes [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : the file name\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Get( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Aig_Man_t * Abc_NtkToDarChoices( Abc_Ntk_t * pNtk );
+    extern Vec_Ptr_t * Abc_NtkCollectCiNames( Abc_Ntk_t * pNtk );
+    extern Vec_Ptr_t * Abc_NtkCollectCoNames( Abc_Ntk_t * pNtk );
+    Abc_Ntk_t * pStrash;
+    Aig_Man_t * pAig;
+    Gia_Man_t * pGia, * pTemp;
+    char * pInits;
+    int c, fMapped = 0, fNames = 0, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "mnvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'm':
+            fMapped ^= 1;
+            break;
+        case 'n':
+            fNames ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        Abc_Print( -1, "There is no current network\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash( pAbc->pNtkCur ) )
+    {
+        if ( fMapped )
+        {
+            assert( Abc_NtkIsLogic(pAbc->pNtkCur) );
+            Abc_NtkToAig( pAbc->pNtkCur );
+            pGia = Abc_NtkAigToGia( pAbc->pNtkCur );
+        }
+        else
+        {
+            // derive comb GIA
+            pStrash = Abc_NtkStrash( pAbc->pNtkCur, 0, 1, 0 );
+            pAig = Abc_NtkToDar( pStrash, 0, 0 );
+            Abc_NtkDelete( pStrash );
+            pGia = Gia_ManFromAig( pAig );
+            Aig_ManStop( pAig );
+            // perform undc/zero
+            pInits = Abc_NtkCollectLatchValuesStr( pAbc->pNtkCur );
+            pGia = Gia_ManDupZeroUndc( pTemp = pGia, pInits, fVerbose );
+            Gia_ManStop( pTemp );
+            ABC_FREE( pInits );
+        }
+    }
+    else
+    {
+        if ( Abc_NtkGetChoiceNum(pAbc->pNtkCur) )
+            pAig = Abc_NtkToDarChoices( pAbc->pNtkCur );
+        else
+            pAig = Abc_NtkToDar( pAbc->pNtkCur, 0, 1 );
+        pGia = Gia_ManFromAig( pAig );
+        Aig_ManStop( pAig );
+    }
+    // replace
+    if ( fNames )
+    {
+        pGia->vNamesIn  = Abc_NtkCollectCiNames( pAbc->pNtkCur );
+        pGia->vNamesOut = Abc_NtkCollectCoNames( pAbc->pNtkCur );
+    }
+    Abc_FrameUpdateGia( pAbc, pGia );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &get [-mnvh] <file>\n" );
+    Abc_Print( -2, "\t         converts the current network into GIA and moves it to the &-space\n" );
+    Abc_Print( -2, "\t         (if the network is a sequential logic network, normalizes the flops\n" );
+    Abc_Print( -2, "\t         to have const-0 initial values, equivalent to \"undc; st; zero\")\n" );
+    Abc_Print( -2, "\t-m     : toggles preserving the current mapping [default = %s]\n", fMapped? "yes": "no" );
+    Abc_Print( -2, "\t-n     : toggles saving CI/CO names of the AIG [default = %s]\n", fNames? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : the file name\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Abc_Ntk_t * Abc_NtkFromDarChoices( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan );
+    Aig_Man_t * pMan;
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c, fVerbose = 0;
+    int fStatusClear = 1;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 's':
+            fStatusClear ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Gia_ManHasMapping(pAbc->pGia) )
+    {
+        extern Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p );
+        pNtk = Abc_NtkFromMappedGia( pAbc->pGia );
+    }
+    else if ( Gia_ManHasCellMapping(pAbc->pGia) )
+    {
+        extern Abc_Ntk_t * Abc_NtkFromCellMappedGia( Gia_Man_t * p );
+        pNtk = Abc_NtkFromCellMappedGia( pAbc->pGia );
+    }
+    else if ( Gia_ManHasDangling(pAbc->pGia) == 0 )
+    {
+        pMan = Gia_ManToAig( pAbc->pGia, 0 );
+        pNtk = Abc_NtkFromAigPhase( pMan );
+        pNtk->pName = Extra_UtilStrsav(pMan->pName);
+        Aig_ManStop( pMan );
+    }
+    else
+    {
+        Abc_Ntk_t * pNtkNoCh;
+//        Abc_Print( -1, "Transforming AIG with %d choice nodes.\n", Gia_ManEquivCountClasses(pAbc->pGia) );
+        // create network without choices
+        pMan = Gia_ManToAig( pAbc->pGia, 0 );
+        pNtkNoCh = Abc_NtkFromAigPhase( pMan );
+        pNtkNoCh->pName = Extra_UtilStrsav(pMan->pName);
+        Aig_ManStop( pMan );
+        // derive network with choices
+        pMan = Gia_ManToAig( pAbc->pGia, 1 );
+        pNtk = Abc_NtkFromDarChoices( pNtkNoCh, pMan );
+        Abc_NtkDelete( pNtkNoCh );
+        Aig_ManStop( pMan );
+    }
+    // transfer PI names to pNtk
+    if ( pAbc->pGia->vNamesIn )
+    {
+        Abc_Obj_t * pObj;
+        int i;
+        Abc_NtkForEachCi( pNtk, pObj, i ) {
+            if (i < Vec_PtrSize(pAbc->pGia->vNamesIn)) {
+                Nm_ManDeleteIdName(pNtk->pManName, pObj->Id);
+                Abc_ObjAssignName( pObj, (char *)Vec_PtrEntry(pAbc->pGia->vNamesIn, i), NULL );
+            }
+        }
+    }
+    // transfer PO names to pNtk
+    if ( pAbc->pGia->vNamesOut )
+    {
+        Abc_Obj_t * pObj;
+        int i;
+        Abc_NtkForEachCo( pNtk, pObj, i ) {
+            if (i < Vec_PtrSize(pAbc->pGia->vNamesOut)) {
+                Nm_ManDeleteIdName(pNtk->pManName, pObj->Id);
+                Abc_ObjAssignName( pObj, (char *)Vec_PtrEntry(pAbc->pGia->vNamesOut, i), NULL );
+            }
+        }
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+    if ( fStatusClear )
+        Abc_FrameClearVerifStatus( pAbc );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &put [-svh]\n" );
+    Abc_Print( -2, "\t         transfer the current network into the old ABC\n" );
+    Abc_Print( -2, "\t-s     : toggle clearning verification status [default = %s]\n", fStatusClear? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char * pFileName;
+    char ** pArgvNew;
+    int c, nArgcNew;
+    int fUnique = 0;
+    int fMiniAig = 0;
+    int fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "umvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'u':
+            fUnique ^= 1;
+            break;
+        case 'm':
+            fMiniAig ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( nArgcNew != 1 )
+    {
+        Abc_Print( -1, "There is no file name.\n" );
+        return 1;
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Write(): There is no AIG to write.\n" );
+        return 1;
+    }
+    pFileName = argv[globalUtilOptind];
+    if ( fUnique )
+    {
+        Gia_Man_t * pGia = Gia_ManIsoCanonicize( pAbc->pGia, fVerbose );
+        Gia_AigerWriteSimple( pGia, pFileName );
+        Gia_ManStop( pGia );
+    }
+    else if ( fMiniAig )
+        Gia_ManWriteMiniAig( pAbc->pGia, pFileName );
+    else
+        Gia_AigerWrite( pAbc->pGia, pFileName, 0, 0 );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &w [-umvh] <file>\n" );
+    Abc_Print( -2, "\t         writes the current AIG into the AIGER file\n" );
+    Abc_Print( -2, "\t-u     : toggle writing canonical AIG structure [default = %s]\n", fUnique? "yes" : "no" );
+    Abc_Print( -2, "\t-m     : toggle writing MiniAIG rather than AIGER [default = %s]\n", fMiniAig? "yes" : "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : the file name\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Ps( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gps_Par_t Pars, * pPars = &Pars;
+    int c;
+    memset( pPars, 0, sizeof(Gps_Par_t) );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Dtpcnlmash" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 't':
+            pPars->fTents ^= 1;
+            break;
+        case 'p':
+            pPars->fSwitch ^= 1;
+            break;
+        case 'c':
+            pPars->fCut ^= 1;
+            break;
+        case 'n':
+            pPars->fNpn ^= 1;
+            break;
+        case 'l':
+            pPars->fLutProf ^= 1;
+            break;
+        case 'm':
+            pPars->fMuxXor ^= 1;
+            break;
+        case 'a':
+            pPars->fMiter ^= 1;
+            break;
+        case 's':
+            pPars->fSkipMap ^= 1;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pPars->pDumpFile = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Ps(): There is no AIG.\n" );
+        return 1;
+    }
+    Gia_ManPrintStats( pAbc->pGia, pPars );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &ps [-tpcnlmash] [-D file]\n" );
+    Abc_Print( -2, "\t          prints stats of the current AIG\n" );
+    Abc_Print( -2, "\t-t      : toggle printing BMC tents [default = %s]\n",                pPars->fTents? "yes": "no" );
+    Abc_Print( -2, "\t-p      : toggle printing switching activity [default = %s]\n",       pPars->fSwitch? "yes": "no" );
+    Abc_Print( -2, "\t-c      : toggle printing the size of frontier cut [default = %s]\n", pPars->fCut? "yes": "no" );
+    Abc_Print( -2, "\t-n      : toggle printing NPN classes of functions [default = %s]\n", pPars->fNpn? "yes": "no" );
+    Abc_Print( -2, "\t-l      : toggle printing LUT size profile [default = %s]\n",         pPars->fLutProf? "yes": "no" );
+    Abc_Print( -2, "\t-m      : toggle printing MUX/XOR statistics [default = %s]\n",       pPars->fMuxXor? "yes": "no" );
+    Abc_Print( -2, "\t-a      : toggle printing miter statistics [default = %s]\n",         pPars->fMiter? "yes": "no" );
+    Abc_Print( -2, "\t-s      : skip mapping statistics even if mapped [default = %s]\n",   pPars->fSkipMap? "yes": "no" );
+    Abc_Print( -2, "\t-D file : file name to dump statistics [default = none]\n" );
+    Abc_Print( -2, "\t-h      : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9PFan( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c;
+    int nNodes = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nNodes = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nNodes < 0 )
+                goto usage;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9PFan(): There is no AIG.\n" );
+        return 1;
+    }
+    Gia_ManPrintFanio( pAbc->pGia, nNodes );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &pfan [-N num] [-h]\n" );
+    Abc_Print( -2, "\t         prints fanin/fanout statistics\n" );
+    Abc_Print( -2, "\t-N num : the number of high-fanout nodes to explore [default = %d]\n", nNodes );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9PSig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c;
+    int fSetReset = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "rh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'r':
+            fSetReset ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9PSigs(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9PSigs(): Works only for sequential circuits.\n" );
+        return 1;
+    }
+    Gia_ManDetectSeqSignals( pAbc->pGia, fSetReset, 1 );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &psig [-rh]\n" );
+    Abc_Print( -2, "\t         prints enable/set/reset statistics\n" );
+    Abc_Print( -2, "\t-r     : toggle printing set/reset signals [default = %s]\n", fSetReset? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Status( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Status(): There is no AIG.\n" );
+        return 1;
+    }
+    Gia_ManPrintMiterStatus( pAbc->pGia );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &status [-h]\n" );
+    Abc_Print( -2, "\t         prints status of the miter\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9MuxProfile( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Gia_ManMuxProfiling( Gia_Man_t * p );
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9MuxProfile(): There is no AIG.\n" );
+        return 1;
+    }
+    Gia_ManMuxProfiling( pAbc->pGia );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &mux_profile [-h]\n" );
+    Abc_Print( -2, "\t         profile MUXes appearing in the design\n" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Show( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Aig_Man_t * pMan;
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Show(): There is no AIG.\n" );
+        return 1;
+    }
+    pMan = Gia_ManToAigSimple( pAbc->pGia );
+    Aig_ManShow( pMan, 0, NULL );
+    Aig_ManStop( pMan );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &show [-h]\n" );
+    Abc_Print( -2, "\t        shows the current AIG using GSView\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Strash( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c, Limit = 2;
+    int fAddStrash = 0;
+    int fCollapse = 0;
+    int fAddMuxes = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Lacmh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            Limit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Limit < 0 )
+                goto usage;
+            break;
+        case 'a':
+            fAddStrash ^= 1;
+            break;
+        case 'c':
+            fCollapse ^= 1;
+            break;
+        case 'm':
+            fAddMuxes ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Strash(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManHasMapping(pAbc->pGia) )
+    {
+        pTemp = (Gia_Man_t *)Dsm_ManDeriveGia( pAbc->pGia, fAddMuxes );
+        if ( !Abc_FrameReadFlag("silentmode") )
+            printf( "Performed delay-oriented unmapping.\n" );
+    }
+    else if ( fAddMuxes )
+    {
+        if ( pAbc->pGia->pMuxes )
+        {
+            Abc_Print( -1, "Abc_CommandAbc9Strash(): The AIG already has MUXes.\n" );
+            return 1;
+        }
+        pTemp = Gia_ManDupMuxes( pAbc->pGia, Limit );
+        if ( !Abc_FrameReadFlag("silentmode") )
+            printf( "Generated AND/XOR/MUX graph.\n" );
+    }
+    else if ( fCollapse && pAbc->pGia->pAigExtra )
+    {
+        Gia_Man_t * pNew = Gia_ManDupUnnormalize( pAbc->pGia );
+        pNew->pManTime = pAbc->pGia->pManTime;
+        pTemp = Gia_ManDupCollapse( pNew, pAbc->pGia->pAigExtra, NULL );
+        pNew->pManTime = NULL;
+        Gia_ManStop( pNew );
+        if ( !Abc_FrameReadFlag("silentmode") )
+            printf( "Collapsed AIG with boxes with logic of the boxes.\n" );
+    }
+    else if ( pAbc->pGia->pMuxes )
+    {
+        pTemp = Gia_ManDupNoMuxes( pAbc->pGia );
+        if ( !Abc_FrameReadFlag("silentmode") )
+            printf( "Generated AIG from AND/XOR/MUX graph.\n" );
+    }
+    else
+    {
+        pTemp = Gia_ManRehash( pAbc->pGia, fAddStrash );
+        if ( !Abc_FrameReadFlag("silentmode") )
+            printf( "Rehashed the current AIG.\n" );
+    }
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &st [-L num] [-acmh]\n" );
+    Abc_Print( -2, "\t         performs structural hashing\n" );
+    Abc_Print( -2, "\t-a     : toggle additional hashing [default = %s]\n", fAddStrash? "yes": "no" );
+    Abc_Print( -2, "\t-c     : toggle collapsing hierarchical AIG [default = %s]\n", fCollapse? "yes": "no" );
+    Abc_Print( -2, "\t-m     : toggle converting to larger gates [default = %s]\n", fAddMuxes? "yes": "no" );
+    Abc_Print( -2, "\t-L num : create MUX when sum of refs does not exceed this limit [default = %d]\n", Limit );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Topand( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c, fVerbose = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Topand(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) > 0 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Topand(): Can only be applied to a combinational miter.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManDupTopAnd( pAbc->pGia, fVerbose );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &topand [-vh]\n" );
+    Abc_Print( -2, "\t        performs AND decomposition for combinational miter\n" );
+    Abc_Print( -2, "\t-v    : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Add1Hot( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c, fVerbose = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Add1Hot(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManDupOneHot( pAbc->pGia );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &add1hot [-vh]\n" );
+    Abc_Print( -2, "\t        adds 1-hotness constraints as additional primary outputs\n" );
+    Abc_Print( -2, "\t-v    : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Cof( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c, fVerbose = 0;
+    int iVar = 0, nLimFan = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "VLvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'V':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iVar = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iVar < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLimFan = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLimFan < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Cof(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( nLimFan )
+    {
+        Abc_Print( -1, "Cofactoring all variables whose fanout count is higher than %d.\n", nLimFan );
+        pTemp = Gia_ManDupCofAll( pAbc->pGia, nLimFan, fVerbose );
+        Abc_FrameUpdateGia( pAbc, pTemp );
+    }
+    else if ( iVar )
+    {
+        Abc_Print( -1, "Cofactoring one variable with object ID %d.\n", iVar );
+        pTemp = Gia_ManDupCof( pAbc->pGia, iVar );
+        Abc_FrameUpdateGia( pAbc, pTemp );
+    }
+    else
+    {
+        Abc_Print( -1, "One of the paramters, -V <num> or -L <num>, should be set on the command line.\n" );
+        goto usage;
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &cof [-VL num] [-vh]\n" );
+    Abc_Print( -2, "\t         performs cofactoring w.r.t. variable(s)\n" );
+    Abc_Print( -2, "\t-V num : the zero-based ID of one variable to cofactor [default = %d]\n", iVar );
+    Abc_Print( -2, "\t-L num : cofactor vars with fanout count higher than this [default = %d]\n", nLimFan );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Trim( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp, * pTemp2;
+    int c;
+    int OutValue = -1;
+    int fTrimCis = 1;
+    int fTrimCos = 1;
+    int fDualOut = 0;
+    int fPoFedByPi = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Viocdh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'V':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            OutValue = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( OutValue < 0 )
+                goto usage;
+            break;
+        case 'i':
+            fTrimCis ^= 1;
+            break;
+        case 'o':
+            fTrimCos ^= 1;
+            break;
+        case 'c':
+            fPoFedByPi ^= 1;
+            break;
+        case 'd':
+            fDualOut ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Trim(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManDupTrimmed( pAbc->pGia, fTrimCis, fTrimCos, fDualOut, OutValue );
+    if ( fPoFedByPi )
+    {
+        extern Gia_Man_t * Gia_ManDupTrimmed2( Gia_Man_t * p );
+        pTemp = Gia_ManDupTrimmed2( pTemp2 = pTemp );
+        Gia_ManStop( pTemp2 );
+    }
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &trim [-V num] [-iocdh]\n" );
+    Abc_Print( -2, "\t         removes PIs without fanout and PO driven by constants\n" );
+    Abc_Print( -2, "\t-V num : the value (0 or 1) of POs to remove [default = both]\n" );
+    Abc_Print( -2, "\t-i     : toggle removing PIs [default = %s]\n", fTrimCis? "yes": "no" );
+    Abc_Print( -2, "\t-o     : toggle removing POs [default = %s]\n", fTrimCos? "yes": "no" );
+    Abc_Print( -2, "\t-c     : toggle additionally removing POs fed by PIs [default = %s]\n", fPoFedByPi? "yes": "no" );
+    Abc_Print( -2, "\t-d     : toggle using dual-output miter [default = %s]\n", fDualOut? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Dfs( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c;
+    int fNormal  = 0;
+    int fReverse = 0;
+    int fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "nrvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'n':
+            fNormal ^= 1;
+            break;
+        case 'r':
+            fReverse ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Dfs(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( fNormal )
+    {
+        pTemp = Gia_ManDupOrderAiger( pAbc->pGia );
+        if ( fVerbose )
+            Abc_Print( -1, "AIG objects are reordered as follows: CIs, ANDs, COs.\n" );
+    }
+    else if ( fReverse )
+    {
+        pTemp = Gia_ManDupOrderDfsReverse( pAbc->pGia );
+        if ( fVerbose )
+            Abc_Print( -1, "AIG objects are reordered in the reserve DFS order.\n" );
+    }
+    else
+    {
+        pTemp = Gia_ManDupOrderDfs( pAbc->pGia );
+        if ( fVerbose )
+            Abc_Print( -1, "AIG objects are reordered in the DFS order.\n" );
+    }
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &dfs [-nrvh]\n" );
+    Abc_Print( -2, "\t        orders objects in the DFS order\n" );
+    Abc_Print( -2, "\t-n    : toggle using normalized ordering [default = %s]\n", fNormal? "yes": "no" );
+    Abc_Print( -2, "\t-r    : toggle using reverse DFS ordering [default = %s]\n", fReverse? "yes": "no" );
+    Abc_Print( -2, "\t-v    : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Sim( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_ParSim_t Pars, * pPars = &Pars;
+    char * pFileName = NULL;
+    int c;
+    Gia_ManSimSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FWNTImvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nIters < 0 )
+                goto usage;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nWords < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->RandSeed = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->RandSeed < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeLimit < 0 )
+                goto usage;
+            break;
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pFileName = argv[globalUtilOptind];
+            globalUtilOptind++;
+            if ( pFileName == NULL )
+                goto usage;
+            break;
+        case 'm':
+            pPars->fCheckMiter ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Sim(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    if ( pFileName != NULL )
+    {
+        extern void Gia_ManSimSimulatePattern( Gia_Man_t * p, char * pFileIn, char * pFileOut );
+        char pFileNameOut[1000];
+        char * pNameGeneric = Extra_FileNameGeneric(pFileName);
+        assert( strlen(pNameGeneric) < 900 );
+        sprintf( pFileNameOut, "%s_out.%s", pNameGeneric, Extra_FileNameExtension(pFileName) );
+        ABC_FREE( pNameGeneric );
+        Gia_ManSimSimulatePattern( pAbc->pGia, pFileName, pFileNameOut );
+        return 1;
+    }
+
+    pAbc->nFrames = -1;
+    if ( Gia_ManSimSimulate( pAbc->pGia, pPars ) )
+        pAbc->Status =  0;
+    else
+        pAbc->Status = -1;
+    Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq );
+//    if ( pLogFileName )
+//        Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "&sim" );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &sim [-FWNT num] [-mvh] -I <file>\n" );
+    Abc_Print( -2, "\t         performs random simulation of the sequential miter\n" );
+    Abc_Print( -2, "\t         (if candidate equivalences are defined, performs refinement)\n" );
+    Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", pPars->nIters );
+    Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", pPars->nWords );
+    Abc_Print( -2, "\t-N num : random number seed (1 <= num <= 1000) [default = %d]\n", pPars->RandSeed );
+    Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeLimit );
+    Abc_Print( -2, "\t-m     : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t-I file: (optional) file with input patterns (one line per frame, as many as PIs)\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Sim3( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern int Ssw_RarSimulateGia( Gia_Man_t * p, Ssw_RarPars_t * pPars );
+    Ssw_RarPars_t Pars, * pPars = &Pars;
+    int c;
+    Ssw_RarSetDefaultParams( pPars );
+    // parse command line
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FWBRSNTGgvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFrames < 0 )
+                goto usage;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nWords < 0 )
+                goto usage;
+            break;
+        case 'B':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBinSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBinSize < 0 )
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRounds = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRounds < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRestart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRestart < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRandSeed = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRandSeed < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeOut < 0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeOutGap = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeOutGap < 0 )
+                goto usage;
+            break;
+        case 'g':
+            pPars->fUseFfGrouping ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Sim3(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Sim3(): This command works only for sequential AIGs.\n" );
+        return 0;
+    }
+    pAbc->Status = Ssw_RarSimulateGia( pAbc->pGia, pPars );
+    Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &sim3 [-FWBRNT num] [-gvh]\n" );
+    Abc_Print( -2, "\t         performs random simulation of the sequential miter\n" );
+    Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n",       pPars->nFrames );
+    Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n",        pPars->nWords );
+    Abc_Print( -2, "\t-B num : the number of flops in one bin [default = %d]\n",         pPars->nBinSize );
+    Abc_Print( -2, "\t-R num : the number of simulation rounds [default = %d]\n",        pPars->nRounds );
+    Abc_Print( -2, "\t-S num : the number of rounds before a restart [default = %d]\n",  pPars->nRestart );
+    Abc_Print( -2, "\t-N num : random number seed (1 <= num <= 1000) [default = %d]\n",  pPars->nRandSeed );
+    Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n",   pPars->TimeOut );
+    Abc_Print( -2, "\t-g     : toggle heuristic flop grouping [default = %s]\n",    pPars->fUseFfGrouping? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n",    pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Resim( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Cec_ParSim_t Pars, * pPars = &Pars;
+    int c, RetValue;
+    Cec_ManSimSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Fmvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFrames < 0 )
+                goto usage;
+            break;
+        case 'm':
+            pPars->fCheckMiter ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Resim(): There is no AIG.\n" );
+        return 1;
+    }
+    RetValue = Cec_ManSeqResimulateCounter( pAbc->pGia, pPars, pAbc->pCex );
+    pAbc->Status  = RetValue ? 0 : -1;
+    pAbc->nFrames = pAbc->pCex->iFrame;
+//    Abc_FrameReplaceCex( pAbc, &pAbc->pCex );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &resim [-F num] [-mvh]\n" );
+    Abc_Print( -2, "\t         resimulates equivalence classes using counter-example\n" );
+    Abc_Print( -2, "\t-F num : the number of additinal frames to simulate [default = %d]\n", pPars->nFrames );
+    Abc_Print( -2, "\t-m     : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9SpecI( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern int Gia_CommandSpecI( Gia_Man_t * pGia, int nFrames, int nBTLimit, int fUseStart, int fCheckMiter, int fVerbose );
+    int nFrames     =   100;
+    int nBTLimit    = 25000;
+    int fUseStart   =     1;
+    int fCheckMiter =     1;
+    int fVerbose    =     0;
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FCfmvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'f':
+            fUseStart ^= 1;
+            break;
+        case 'm':
+            fCheckMiter ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9SpecI(): There is no AIG.\n" );
+        return 1;
+    }
+    Gia_CommandSpecI( pAbc->pGia, nFrames, nBTLimit, fUseStart, fCheckMiter, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &speci [-FC num] [-fmvh]\n" );
+    Abc_Print( -2, "\t         refines equivalence classes using speculative reduction\n" );
+    Abc_Print( -2, "\t-F num : the max number of time frames [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", nBTLimit );
+    Abc_Print( -2, "\t-f     : toggle starting BMC from a later frame [default = %s]\n", fUseStart? "yes": "no" );
+    Abc_Print( -2, "\t-m     : toggle miter vs. any circuit [default = %s]\n", fCheckMiter? "miter": "circuit" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Equiv( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Cec_ParSim_t Pars, * pPars = &Pars;
+    int c;
+    Cec_ManSimSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "WFRSTsmdvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nWords < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFrames < 0 )
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRounds = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRounds < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nNonRefines = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nNonRefines < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeLimit < 0 )
+                goto usage;
+            break;
+        case 's':
+            pPars->fSeqSimulate ^= 1;
+            break;
+        case 'm':
+            pPars->fCheckMiter ^= 1;
+            break;
+        case 'd':
+            pPars->fDualOut ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Equiv(): There is no AIG.\n" );
+        return 1;
+    }
+    Cec_ManSimulation( pAbc->pGia, pPars );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &equiv [-WFRST num] [-smdvh]\n" );
+    Abc_Print( -2, "\t         computes candidate equivalence classes\n" );
+    Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", pPars->nWords );
+    Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", pPars->nFrames );
+    Abc_Print( -2, "\t-R num : the max number of simulation rounds [default = %d]\n", pPars->nRounds );
+    Abc_Print( -2, "\t-S num : the max number of rounds w/o refinement to stop [default = %d]\n", pPars->nNonRefines );
+    Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeLimit );
+    Abc_Print( -2, "\t-s     : toggle seq vs. comb simulation [default = %s]\n", pPars->fSeqSimulate? "yes": "no" );
+    Abc_Print( -2, "\t-m     : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" );
+    Abc_Print( -2, "\t-d     : toggle using two POs intead of XOR [default = %s]\n", pPars->fDualOut? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Equiv2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Ssw_SignalFilterGia( Gia_Man_t * p, int nFramesMax, int nConfMax, int nRounds, int TimeLimit, int TimeLimit2, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose );
+    int nFramesMax =   20;
+    int nConfMax   =  500;
+    int nRounds    =   10;
+    int TimeLimit  =    0;
+    int TimeLimit2 =    0;
+    int fUseCex    =    0;
+    int fLatchOnly =    0;
+    int fVerbose   =    0;
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FCRTSxlvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFramesMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFramesMax < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfMax < 0 )
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nRounds = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nRounds < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            TimeLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( TimeLimit < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            TimeLimit2 = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( TimeLimit2 < 0 )
+                goto usage;
+            break;
+        case 'x':
+            fUseCex ^= 1;
+            break;
+        case 'l':
+            fLatchOnly ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Equiv2(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( 0, "Abc_CommandAbc9Equiv2(): There is no flops. Nothing is done.\n" );
+        return 0;
+    }
+    if ( fUseCex )
+    {
+        if ( pAbc->pCex == NULL )
+        {
+            Abc_Print( 0, "Abc_CommandAbc9Equiv2(): Counter-example is not available.\n" );
+            return 0;
+        }
+        if ( pAbc->pCex->nPis != Gia_ManPiNum(pAbc->pGia) )
+        {
+            Abc_Print( -1, "Abc_CommandAbc9Equiv2(): The number of PIs differs in cex (%d) and in AIG (%d).\n",
+                pAbc->pCex->nPis, Gia_ManPiNum(pAbc->pGia) );
+            return 1;
+        }
+    }
+    Ssw_SignalFilterGia( pAbc->pGia, nFramesMax, nConfMax, nRounds, TimeLimit, TimeLimit2, fUseCex? pAbc->pCex: NULL, fLatchOnly, fVerbose );
+    pAbc->Status  = -1;
+//    pAbc->nFrames = pAbc->pCex->iFrame;
+//    Abc_FrameReplaceCex( pAbc, &pAbc->pCex );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &equiv2 [-FCRTS num] [-xlvh]\n" );
+    Abc_Print( -2, "\t         computes candidate equivalence classes\n" );
+    Abc_Print( -2, "\t-F num : the max number of frames for BMC [default = %d]\n", nFramesMax );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", nConfMax );
+    Abc_Print( -2, "\t-R num : the max number of BMC rounds [default = %d]\n", nRounds );
+    Abc_Print( -2, "\t-T num : runtime limit in seconds for all rounds [default = %d]\n", TimeLimit );
+    Abc_Print( -2, "\t-S num : runtime limit in seconds for one round [default = %d]\n", TimeLimit2 );
+    Abc_Print( -2, "\t-x     : toggle using the current cex to perform refinement [default = %s]\n", fUseCex? "yes": "no" );
+    Abc_Print( -2, "\t-l     : toggle considering only latch output equivalences [default = %s]\n", fLatchOnly? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Equiv3( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern int Ssw_RarSignalFilterGia( Gia_Man_t * p, Ssw_RarPars_t * pPars );
+    Ssw_RarPars_t Pars, * pPars = &Pars;
+    int c;
+    Ssw_RarSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FWBRSNTmxlvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFrames < 0 )
+                goto usage;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nWords < 0 )
+                goto usage;
+            break;
+        case 'B':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBinSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBinSize < 0 )
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRounds = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRounds < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRestart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRestart < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRandSeed = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRandSeed < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeOut < 0 )
+                goto usage;
+            break;
+        case 'm':
+            pPars->fMiter ^= 1;
+            break;
+        case 'x':
+            pPars->fUseCex ^= 1;
+            break;
+        case 'l':
+            pPars->fLatchOnly ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Equiv3(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( 0, "Abc_CommandAbc9Equiv3(): There is no flops. Nothing is done.\n" );
+        return 0;
+    }
+    if ( pPars->fUseCex )
+    {
+        if ( pPars->fMiter )
+        {
+            Abc_Print( 0, "Abc_CommandAbc9Equiv3(): Considering the miter as a circuit because the CEX is given.\n" );
+            pPars->fMiter = 0;
+        }
+        if ( pAbc->pCex == NULL )
+        {
+            Abc_Print( 0, "Abc_CommandAbc9Equiv3(): Counter-example is not available.\n" );
+            return 0;
+        }
+        if ( pAbc->pCex->nPis != Gia_ManPiNum(pAbc->pGia) )
+        {
+            Abc_Print( -1, "Abc_CommandAbc9Equiv3(): The number of PIs differs in cex (%d) and in AIG (%d).\n",
+                pAbc->pCex->nPis, Gia_ManPiNum(pAbc->pGia) );
+            return 1;
+        }
+        pPars->pCex = pAbc->pCex;
+    }
+    pAbc->Status = Ssw_RarSignalFilterGia( pAbc->pGia, pPars );
+//    pAbc->nFrames = pAbc->pGia->pCexSeq->iFrame;
+    Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &equiv3 [-FWRSNT num] [-mxlvh]\n" );
+    Abc_Print( -2, "\t         computes candidate equivalence classes\n" );
+    Abc_Print( -2, "\t-F num : the max number of frames for BMC [default = %d]\n",                   pPars->nFrames );
+    Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n",                    pPars->nWords );
+    Abc_Print( -2, "\t-R num : the max number of simulation rounds [default = %d]\n",                pPars->nRounds );
+    Abc_Print( -2, "\t-S num : the number of rounds before a restart [default = %d]\n",              pPars->nRestart );
+    Abc_Print( -2, "\t-N num : random number seed (1 <= num <= 1000) [default = %d]\n",              pPars->nRandSeed );
+    Abc_Print( -2, "\t-T num : runtime limit in seconds for all rounds [default = %d]\n",            pPars->TimeOut );
+    Abc_Print( -2, "\t-m     : toggle miter vs. any circuit [default = %s]\n",                       pPars->fMiter? "miter": "circuit" );
+    Abc_Print( -2, "\t-x     : toggle using the current CEX to perform refinement [default = %s]\n", pPars->fUseCex? "yes": "no" );
+    Abc_Print( -2, "\t-l     : toggle considering only latch output equivalences [default = %s]\n",  pPars->fLatchOnly? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n",                pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Semi( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Cec_ParSmf_t Pars, * pPars = &Pars;
+    int c;
+    Cec_ManSmfSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "WRFSMCTmdvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nWords < 0 )
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRounds = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRounds < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFrames < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nNonRefines = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nNonRefines < 0 )
+                goto usage;
+            break;
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nMinOutputs = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nMinOutputs < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeLimit < 0 )
+                goto usage;
+            break;
+        case 'm':
+            pPars->fCheckMiter ^= 1;
+            break;
+        case 'd':
+            pPars->fDualOut ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Resim(): There is no AIG.\n" );
+        return 1;
+    }
+    Cec_ManSeqSemiformal( pAbc->pGia, pPars );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &semi [-WRFSMCT num] [-mdvh]\n" );
+    Abc_Print( -2, "\t         performs semiformal refinement of equivalence classes\n" );
+    Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", pPars->nWords );
+    Abc_Print( -2, "\t-R num : the max number of rounds to simulate [default = %d]\n", pPars->nRounds );
+    Abc_Print( -2, "\t-F num : the max number of frames to unroll [default = %d]\n", pPars->nFrames );
+    Abc_Print( -2, "\t-S num : the max number of rounds w/o refinement to stop [default = %d]\n", pPars->nNonRefines );
+    Abc_Print( -2, "\t-M num : the min number of outputs of bounded SRM [default = %d]\n", pPars->nMinOutputs );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit );
+    Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeLimit );
+    Abc_Print( -2, "\t-m     : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" );
+    Abc_Print( -2, "\t-d     : toggle using two POs intead of XOR [default = %s]\n", pPars->fDualOut? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Times( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c, nTimes = 2, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Nvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nTimes = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nTimes < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Times(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManDupTimes( pAbc->pGia, nTimes );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &times [-N <num>] [-vh]\n" );
+    Abc_Print( -2, "\t         creates several \"parallel\" copies of the design\n" );
+    Abc_Print( -2, "\t-N num : number of copies to create [default = %d]\n", nTimes );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Frames( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Gia_Man_t * Gia_ManFrames2( Gia_Man_t * pAig, Gia_ParFra_t * pPars );
+
+    Gia_Man_t * pTemp;
+    Gia_ParFra_t Pars, * pPars = &Pars;
+    int c;
+    int nCofFanLit = 0;
+    int fNewAlgo = 0;
+    int fInitSpecial = 0;
+    Gia_ManFraSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FLsoibavh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFrames < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nCofFanLit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nCofFanLit < 0 )
+                goto usage;
+            break;
+        case 's':
+            pPars->fDisableSt ^= 1;
+            break;
+        case 'o':
+            pPars->fOrPos ^= 1;
+            break;
+        case 'i':
+            pPars->fInit ^= 1;
+            break;
+        case 'b':
+            fInitSpecial ^= 1;
+            break;
+        case 'a':
+            fNewAlgo ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Frames(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    if ( fInitSpecial )
+        pTemp = Gia_ManFramesInitSpecial( pAbc->pGia, pPars->nFrames, pPars->fVerbose );
+    else if ( nCofFanLit )
+        pTemp = Gia_ManUnrollAndCofactor( pAbc->pGia, pPars->nFrames, nCofFanLit, pPars->fVerbose );
+    else if ( fNewAlgo )
+        pTemp = Gia_ManFrames2( pAbc->pGia, pPars );
+    else
+        pTemp = Gia_ManFrames( pAbc->pGia, pPars );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &frames [-FL <num>] [-soibavh]\n" );
+    Abc_Print( -2, "\t         unrolls the design for several timeframes\n" );
+    Abc_Print( -2, "\t-F num : the number of frames to unroll [default = %d]\n", pPars->nFrames );
+    Abc_Print( -2, "\t-L num : the limit on fanout count of resets/enables to cofactor [default = %d]\n", nCofFanLit );
+    Abc_Print( -2, "\t-s     : toggle disabling structural hashing [default = %s]\n", pPars->fDisableSt? "yes": "no" );
+    Abc_Print( -2, "\t-o     : toggle ORing corresponding POs [default = %s]\n", pPars->fOrPos? "yes": "no" );
+    Abc_Print( -2, "\t-i     : toggle initializing registers [default = %s]\n", pPars->fInit? "yes": "no" );
+    Abc_Print( -2, "\t-b     : toggle computing special AIG for BMC [default = %s]\n", fInitSpecial? "yes": "no" );
+    Abc_Print( -2, "\t-a     : toggle using new algorithm [default = %s]\n", fNewAlgo? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Retime( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c;
+    int nMaxIters = 100;
+    int fVerbose  =   0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Nvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nMaxIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nMaxIters < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Retime(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    pTemp = Gia_ManRetimeForward( pAbc->pGia, nMaxIters, fVerbose );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &retime [-N <num>] [-vh]\n" );
+    Abc_Print( -2, "\t         performs most-forward retiming\n" );
+    Abc_Print( -2, "\t-N num : the number of incremental iterations [default = %d]\n", nMaxIters );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Enable( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c;
+    int fRemove  = 0;
+    int fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'r':
+            fRemove ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Enable(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( fRemove )
+        pTemp = Gia_ManRemoveEnables( pAbc->pGia );
+    else
+        pTemp = Gia_ManDupSelf( pAbc->pGia );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &enable [-rvh]\n" );
+    Abc_Print( -2, "\t         adds or removes flop enable signals\n" );
+    Abc_Print( -2, "\t-r     : toggle adding vs. removing enables [default = %s]\n", fRemove? "remove": "add" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Dc2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c, fVerbose = 0;
+    int fUpdateLevel = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "lvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'l':
+            fUpdateLevel ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Dc2(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManCompress2( pAbc->pGia, fUpdateLevel, fVerbose );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &dc2 [-lvh]\n" );
+    Abc_Print( -2, "\t         performs heavy rewriting of the AIG\n" );
+    Abc_Print( -2, "\t-l     : toggle level update during rewriting [default = %s]\n", fUpdateLevel? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Bidec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c, fVerbose = 0;
+    int fUpdateLevel = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "lvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'l':
+            fUpdateLevel ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Bidec(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( !Gia_ManHasMapping(pAbc->pGia) )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Bidec(): Mapping of the AIG is not defined.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManPerformBidec( pAbc->pGia, fVerbose );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &bidec [-vh]\n" );
+    Abc_Print( -2, "\t         performs heavy rewriting of the AIG\n" );
+//    Abc_Print( -2, "\t-l     : toggle level update during rewriting [default = %s]\n", fUpdateLevel? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Shrink( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp = NULL;
+    int nLutSize;
+    int c,fVerbose = 0;
+    int fKeepLevel = 0;
+    int nFanoutMax = 50;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Nlvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by a char string.\n" );
+                goto usage;
+            }
+            nFanoutMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFanoutMax < 0 )
+                goto usage;
+            break;
+        case 'l':
+            fKeepLevel ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Shrink(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( !Gia_ManHasMapping(pAbc->pGia) )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Shrink(): Mapping of the AIG is not defined.\n" );
+        return 1;
+    }
+    nLutSize = Gia_ManLutSizeMax( pAbc->pGia );
+    if ( nLutSize <= 4 )
+        pTemp = Gia_ManMapShrink4( pAbc->pGia, fKeepLevel, fVerbose );
+    else if ( nLutSize <= 6 )
+        pTemp = Gia_ManMapShrink6( pAbc->pGia, nFanoutMax, fKeepLevel, fVerbose );
+    else
+        Abc_Print( -1, "Abc_CommandAbc9Shrink(): Works only for 4-LUTs and 6-LUTs.\n" );
+    if ( pTemp )
+        Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &shrink [-N num] [-lvh]\n" );
+    Abc_Print( -2, "\t         performs fast shrinking using current mapping\n" );
+    Abc_Print( -2, "\t-N num : the max fanout count to skip a divisor [default = %d]\n", nFanoutMax );
+    Abc_Print( -2, "\t-l     : toggle level update during shrinking [default = %s]\n", fKeepLevel? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Fx( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int nNewNodesMax = 1000000;
+    int LitCountMax  =       0;
+    int fReverse     =       0;
+    int c, fVerbose  =       0;
+    int fVeryVerbose =       0;
+    // set the defaults
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "NMrvwh")) != EOF )
+    {
+        switch (c)
+        {
+            case 'N':
+                if ( globalUtilOptind >= argc )
+                {
+                    Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                    goto usage;
+                }
+                nNewNodesMax = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( nNewNodesMax < 0 )
+                    goto usage;
+                break;
+            case 'M':
+                if ( globalUtilOptind >= argc )
+                {
+                    Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
+                    goto usage;
+                }
+                LitCountMax = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( LitCountMax < 0 )
+                    goto usage;
+                break;
+            case 'r':
+                fReverse ^= 1;
+                break;
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'w':
+                fVeryVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+                break;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Shrink(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( !Gia_ManHasMapping(pAbc->pGia) )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Shrink(): Mapping of the AIG is not defined.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManPerformFx( pAbc->pGia, nNewNodesMax, LitCountMax, fReverse, fVerbose, fVeryVerbose );
+    if ( pTemp != NULL )
+        Abc_FrameUpdateGia( pAbc, pTemp );
+    else
+        Abc_Print( -1, "Abc_CommandAbc9Fx(): Command has failed.\n" );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &fx [-NM <num>] [-vh]\n");
+    Abc_Print( -2, "\t           extract shared logic using the classical \"fast_extract\" algorithm\n");
+    Abc_Print( -2, "\t-N <num> : max number of divisors to extract during this run [default = %d]\n", nNewNodesMax );
+    Abc_Print( -2, "\t-M <num> : upper bound on literal count of divisors to extract [default = %d]\n", LitCountMax );
+    Abc_Print( -2, "\t-r       : reversing variable order during ISOP computation [default = %s]\n", fReverse? "yes": "no" );
+    Abc_Print( -2, "\t-v       : print verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggle printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Balance( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp = NULL;
+    int nNewNodesMax = ABC_INFINITY;
+    int fDelayOnly   = 0;
+    int fSimpleAnd   = 0;
+    int fKeepLevel   = 0;
+    int c, fVerbose  = 0;
+    int fVeryVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Ndalvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by a char string.\n" );
+                goto usage;
+            }
+            nNewNodesMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nNewNodesMax < 0 )
+                goto usage;
+            break;
+        case 'd':
+            fDelayOnly ^= 1;
+            break;
+        case 'a':
+            fSimpleAnd ^= 1;
+            break;
+        case 'l':
+            fKeepLevel ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Balance(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( fDelayOnly )
+        pTemp = Gia_ManBalance( pAbc->pGia, fSimpleAnd, fVerbose );
+    else
+        pTemp = Gia_ManAreaBalance( pAbc->pGia, fSimpleAnd, nNewNodesMax, fVerbose, fVeryVerbose );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &b [-N num] [-davwh]\n" );
+    Abc_Print( -2, "\t         performs AIG balancing to reduce delay and area\n" );
+    Abc_Print( -2, "\t-N num : the max fanout count to skip a divisor [default = %d]\n", nNewNodesMax );
+    Abc_Print( -2, "\t-d     : toggle delay only balancing [default = %s]\n", fDelayOnly? "yes": "no" );
+    Abc_Print( -2, "\t-a     : toggle using AND instead of AND/XOR/MUX [default = %s]\n", fSimpleAnd? "yes": "no" );
+//    Abc_Print( -2, "\t-l     : toggle level update during shrinking [default = %s]\n", fKeepLevel? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9BalanceLut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Gia_Man_t * Gia_ManBalanceLut( Gia_Man_t * p, int nLutSize, int nCutNum, int fVerbose );
+    extern Gia_Man_t * Gia_ManLutBalance( Gia_Man_t * p, int nLutSize, int fUseMuxes, int fRecursive, int fOptArea, int fVerbose );
+    Gia_Man_t * pTemp = NULL;
+    int fUseOld      = 0;
+    int nLutSize     = 6;
+    int nCutNum      = 8;
+    int fUseMuxes    = 1;
+    int fRecursive   = 1;
+    int fOptArea     = 1;
+    int c, fVerbose  = 0;
+    int fVeryVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "KCnmravwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by a char string.\n" );
+                goto usage;
+            }
+            nLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLutSize < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by a char string.\n" );
+                goto usage;
+            }
+            nCutNum = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nCutNum < 0 )
+                goto usage;
+            break;
+        case 'n':
+            fUseOld ^= 1;
+            break;
+        case 'm':
+            fUseMuxes ^= 1;
+            break;
+        case 'r':
+            fRecursive ^= 1;
+            break;
+        case 'a':
+            fOptArea ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9BalanceLut(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( fUseOld )
+        pTemp = Gia_ManBalanceLut( pAbc->pGia, nLutSize, nCutNum, fVerbose );
+    else
+        pTemp = Gia_ManLutBalance( pAbc->pGia, nLutSize, fUseMuxes, fRecursive, fOptArea, fVerbose );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &blut [-KC num] [-mravh]\n" );
+    Abc_Print( -2, "\t           performs AIG balancing for the given LUT size\n" );
+    Abc_Print( -2, "\t-K num   : LUT size for the mapping (2 <= K <= %d) [default = %d]\n", 6, nLutSize );
+    Abc_Print( -2, "\t-C num   : the max number of priority cuts (1 <= C <= %d) [default = %d]\n", 8, nCutNum );
+    Abc_Print( -2, "\t-m       : toggle performing MUX restructuring [default = %s]\n", fUseMuxes? "yes": "no" );
+    Abc_Print( -2, "\t-r       : toggle performing recursive restructuring [default = %s]\n", fRecursive? "yes": "no" );
+    Abc_Print( -2, "\t-a       : toggle performing area-oriented restructuring [default = %s]\n", fOptArea? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+//    Abc_Print( -2, "\t-w       : toggle printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Syn2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c, fVerbose = 0;
+    int fOldAlgo = 0;
+    int fCoarsen = 1;
+    int fCutMin = 0;
+    int nRelaxRatio = 20;
+    int fVeryVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Rakmvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+		case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" );
+                return 0;
+            }
+			nRelaxRatio = atoi(argv[globalUtilOptind]);
+			globalUtilOptind++;
+			if ( nRelaxRatio < 0 ) 
+				goto usage;
+            break;
+        case 'a':
+            fOldAlgo ^= 1;
+            break;
+        case 'k':
+            fCoarsen ^= 1;
+            break;
+        case 'm':
+            fCutMin ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Syn2(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManAigSyn2( pAbc->pGia, fOldAlgo, fCoarsen, fCutMin, nRelaxRatio, fVerbose, fVeryVerbose );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &syn2 [-R num] [-akmlvh]\n" );
+    Abc_Print( -2, "\t           performs AIG optimization\n" );
+    Abc_Print( -2, "\t-R num   : the delay relaxation ratio (num >= 0) [default = %d]\n",  nRelaxRatio );
+    Abc_Print( -2, "\t-a       : toggles using the old algorithm [default = %s]\n",        fOldAlgo? "yes": "no" );
+    Abc_Print( -2, "\t-k       : toggles coarsening the subject graph [default = %s]\n",   fCoarsen? "yes": "no" );
+    Abc_Print( -2, "\t-m       : toggles cut minimization [default = %s]\n",               fCutMin? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggle printing verbose information [default = %s]\n",    fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggle printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Syn3( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c, fVerbose = 0;
+    int fVeryVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Syn3(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManAigSyn3( pAbc->pGia, fVerbose, fVeryVerbose );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &syn3 [-lvh]\n" );
+    Abc_Print( -2, "\t         performs AIG optimization\n" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Syn4( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c, fVerbose = 0;
+    int fVeryVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Syn4(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManAigSyn4( pAbc->pGia, fVerbose, fVeryVerbose );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &syn4 [-lvh]\n" );
+    Abc_Print( -2, "\t         performs AIG optimization\n" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9False( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Gia_Man_t * Gia_ManCheckFalse( Gia_Man_t * p, int nSlackMax, int nTimeOut, int fVerbose, int fVeryVerbose );
+    Gia_Man_t * pTemp;
+    int nSlackMax = 0;
+    int nTimeOut = 0;
+    int c, fVerbose = 0;
+    int fVeryVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "STvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by a char string.\n" );
+                goto usage;
+            }
+            nSlackMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nSlackMax < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by a char string.\n" );
+                goto usage;
+            }
+            nTimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nTimeOut < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9False(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManCheckFalse( pAbc->pGia, nSlackMax, nTimeOut, fVerbose, fVeryVerbose );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &false [-ST num] [-vwh]\n" );
+    Abc_Print( -2, "\t         detecting and elimintation false paths\n" );
+    Abc_Print( -2, "\t-S num : maximum slack to identify false paths [default = %d]\n",  nSlackMax );
+    Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n",   nTimeOut );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n",    fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Miter( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    FILE * pFile;
+    Gia_Man_t * pAux;
+    Gia_Man_t * pSecond;
+    char * FileName, * pTemp;
+    char ** pArgvNew;
+    int nArgcNew;
+    int c;
+    int nInsDup  = 0;
+    int fDualOut = 0;
+    int fSeq     = 0;
+    int fTrans   = 0;
+    int fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Idstvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by a char string.\n" );
+                goto usage;
+            }
+            nInsDup = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nInsDup < 0 )
+                goto usage;
+            break;
+        case 'd':
+            fDualOut ^= 1;
+            break;
+        case 's':
+            fSeq ^= 1;
+            break;
+        case 't':
+            fTrans ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( fTrans )
+    {
+        if ( (Gia_ManPoNum(pAbc->pGia) & 1) == 1 )
+        {
+            Abc_Print( -1, "Abc_CommandAbc9Miter(): The number of outputs should be even.\n" );
+            return 0;
+        }
+        if ( pAbc->pGia == NULL )
+        {
+            Abc_Print( -1, "Abc_CommandAbc9Miter(): There is no AIG.\n" );
+            return 1;
+        }
+        pAux = Gia_ManTransformMiter( pAbc->pGia );
+        Abc_FrameUpdateGia( pAbc, pAux );
+        Abc_Print( 1, "The miter (current AIG) is transformed by XORing POs pair-wise.\n" );
+        return 0;
+    }
+
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( nArgcNew != 1 )
+    {
+        Abc_Print( -1, "File name is not given on the command line.\n" );
+        return 1;
+    }
+
+    // get the input file name
+    FileName = pArgvNew[0];
+    // fix the wrong symbol
+    for ( pTemp = FileName; *pTemp; pTemp++ )
+        if ( *pTemp == '>' )
+            *pTemp = '\\';
+    if ( (pFile = fopen( FileName, "r" )) == NULL )
+    {
+        Abc_Print( -1, "Cannot open input file \"%s\". ", FileName );
+        if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) )
+            Abc_Print( 1, "Did you mean \"%s\"?", FileName );
+        Abc_Print( 1, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+    pSecond = Gia_AigerRead( FileName, 0, 0 );
+    if ( pSecond == NULL )
+    {
+        Abc_Print( -1, "Reading AIGER has failed.\n" );
+        return 0;
+    }
+    // compute the miter
+    pAux = Gia_ManMiter( pAbc->pGia, pSecond, nInsDup, fDualOut, fSeq, 0, fVerbose );
+    Gia_ManStop( pSecond );
+    Abc_FrameUpdateGia( pAbc, pAux );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &miter [-I num] [-dstvh] <file>\n" );
+    Abc_Print( -2, "\t         creates miter of two designs (current AIG vs. <file>)\n" );
+    Abc_Print( -2, "\t-I num : the number of last PIs to replicate [default = %d]\n", nInsDup );
+    Abc_Print( -2, "\t-d     : toggle creating dual-output miter [default = %s]\n", fDualOut? "yes": "no" );
+    Abc_Print( -2, "\t-s     : toggle creating sequential miter [default = %s]\n", fSeq? "yes": "no" );
+    Abc_Print( -2, "\t-t     : toggle XORing pair-wise POs of the miter [default = %s]\n", fTrans? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : AIGER file with the design to miter\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Miter2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    FILE * pFile;
+    Gia_Man_t * pAux;
+    char * FileName, * pTemp, * pInit;
+    char ** pArgvNew;
+    int nArgcNew;
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( nArgcNew != 1 )
+    {
+        Abc_Print( -1, "File name is not given on the command line.\n" );
+        return 1;
+    }
+    // get the input file name
+    FileName = pArgvNew[0];
+    // fix the wrong symbol
+    for ( pTemp = FileName; *pTemp; pTemp++ )
+        if ( *pTemp == '>' )
+            *pTemp = '\\';
+    if ( (pFile = fopen( FileName, "r" )) == NULL )
+    {
+        Abc_Print( -1, "Cannot open input file \"%s\". ", FileName );
+        if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) )
+            Abc_Print( 1, "Did you mean \"%s\"?", FileName );
+        Abc_Print( 1, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+    // extract string
+    pInit = Extra_FileReadContents( FileName );
+    Extra_StringClean( pInit, "01xX" );
+    if ( (int)strlen(pInit) != Gia_ManCiNum(pAbc->pGia) )
+    {
+        Abc_Print( -1, "Init string length (%d) differs from PI and flop count (%d).\n", strlen(pInit), Gia_ManCiNum(pAbc->pGia) );
+        ABC_FREE( pInit );
+        return 1;
+    }
+    // compute the miter
+    pAux = Gia_ManMiter2( pAbc->pGia, pInit, fVerbose );
+    ABC_FREE( pInit );
+    Abc_FrameUpdateGia( pAbc, pAux );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &miter2 [-vh] <file>\n" );
+    Abc_Print( -2, "\t         creates miter of two copies of the design\n" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : file name with flop initial values (0/1/x/X) [default = required]\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Append( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    FILE * pFile;
+    Gia_Man_t * pSecond;
+    char * FileName, * pTemp;
+    char ** pArgvNew;
+    int nArgcNew;
+    int c;
+    int fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( nArgcNew != 1 )
+    {
+        Abc_Print( -1, "File name is not given on the command line.\n" );
+        return 1;
+    }
+
+    // get the input file name
+    FileName = pArgvNew[0];
+    // fix the wrong symbol
+    for ( pTemp = FileName; *pTemp; pTemp++ )
+        if ( *pTemp == '>' )
+            *pTemp = '\\';
+    if ( (pFile = fopen( FileName, "r" )) == NULL )
+    {
+        Abc_Print( -1, "Cannot open input file \"%s\". ", FileName );
+        if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) )
+            Abc_Print( 1, "Did you mean \"%s\"?", FileName );
+        Abc_Print( 1, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+    pSecond = Gia_AigerRead( FileName, 0, 0 );
+    if ( pSecond == NULL )
+    {
+        Abc_Print( -1, "Reading AIGER has failed.\n" );
+        return 0;
+    }
+    // compute the miter
+    Gia_ManDupAppend( pAbc->pGia, pSecond );
+    Gia_ManStop( pSecond );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &append [-vh] <file>\n" );
+    Abc_Print( -2, "\t         appends <file> to the current AIG using new PIs and POs\n" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : AIGER file with the design to miter\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Scl( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c;
+    int fConst = 1;
+    int fEquiv = 1;
+    int fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "cevh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'c':
+            fConst ^= 1;
+            break;
+        case 'e':
+            fEquiv ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Scl(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManSeqStructSweep( pAbc->pGia, fConst, fEquiv, fVerbose );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &scl [-cevh]\n" );
+    Abc_Print( -2, "\t         performs structural sequential cleanup\n" );
+    Abc_Print( -2, "\t-c     : toggle removing stuck-at constant registers [default = %s]\n", fConst? "yes": "no" );
+    Abc_Print( -2, "\t-e     : toggle removing equivalent-driver registers [default = %s]\n", fEquiv? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Lcorr( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Cec_ParCor_t Pars, * pPars = &Pars;
+    Gia_Man_t * pTemp;
+    int c;
+    Cec_ManCorSetDefaultParams( pPars );
+    pPars->fLatchCorr = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FCPrcvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFrames < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nPrefix = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nPrefix < 0 )
+                goto usage;
+            break;
+        case 'r':
+            pPars->fUseRings ^= 1;
+            break;
+        case 'c':
+            pPars->fUseCSat ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Lcorr(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    pTemp = Cec_ManLSCorrespondence( pAbc->pGia, pPars );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &lcorr [-FCP num] [-rcvh]\n" );
+    Abc_Print( -2, "\t         performs latch correpondence computation\n" );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit );
+    Abc_Print( -2, "\t-F num : the number of timeframes in inductive case [default = %d]\n", pPars->nFrames );
+    Abc_Print( -2, "\t-P num : the number of timeframes in the prefix [default = %d]\n", pPars->nPrefix );
+    Abc_Print( -2, "\t-r     : toggle using implication rings during refinement [default = %s]\n", pPars->fUseRings? "yes": "no" );
+    Abc_Print( -2, "\t-c     : toggle using circuit-based SAT solver [default = %s]\n", pPars->fUseCSat? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Cec_ParCor_t Pars, * pPars = &Pars;
+    Gia_Man_t * pTemp;
+    int c;
+    Cec_ManCorSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FCPkrecqwvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFrames < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nPrefix = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nPrefix < 0 )
+                goto usage;
+            break;
+        case 'k':
+            pPars->fConstCorr ^= 1;
+            break;
+        case 'r':
+            pPars->fUseRings ^= 1;
+            break;
+        case 'e':
+            pPars->fMakeChoices ^= 1;
+            break;
+        case 'c':
+            pPars->fUseCSat ^= 1;
+            break;
+        case 'q':
+            pPars->fStopWhenGone ^= 1;
+            break;
+        case 'w':
+            pPars->fVerboseFlops ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Scorr(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    pTemp = Cec_ManLSCorrespondence( pAbc->pGia, pPars );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &scorr [-FCP num] [-krecqwvh]\n" );
+    Abc_Print( -2, "\t         performs signal correpondence computation\n" );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit );
+    Abc_Print( -2, "\t-F num : the number of timeframes in inductive case [default = %d]\n", pPars->nFrames );
+    Abc_Print( -2, "\t-P num : the number of timeframes in the prefix [default = %d]\n", pPars->nPrefix );
+    Abc_Print( -2, "\t-k     : toggle using constant correspondence [default = %s]\n", pPars->fConstCorr? "yes": "no" );
+    Abc_Print( -2, "\t-r     : toggle using implication rings during refinement [default = %s]\n", pPars->fUseRings? "yes": "no" );
+    Abc_Print( -2, "\t-e     : toggle using equivalences as choices [default = %s]\n", pPars->fMakeChoices? "yes": "no" );
+    Abc_Print( -2, "\t-c     : toggle using circuit-based SAT solver [default = %s]\n", pPars->fUseCSat? "yes": "no" );
+    Abc_Print( -2, "\t-q     : toggle quitting when PO is not a constant candidate [default = %s]\n", pPars->fStopWhenGone? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle printing verbose info about equivalent flops [default = %s]\n", pPars->fVerboseFlops? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Choice( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Cec_ParChc_t Pars, * pPars = &Pars;
+    Gia_Man_t * pTemp;
+    int c;
+    Cec_ManChcSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Ccvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'c':
+            pPars->fUseCSat ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Choice(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Cec_ManChoiceComputation( pAbc->pGia, pPars );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &choice [-C num] [-cvh]\n" );
+    Abc_Print( -2, "\t         performs computation of structural choices\n" );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit );
+    Abc_Print( -2, "\t-c     : toggle using circuit-based SAT solver [default = %s]\n", pPars->fUseCSat? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Sat( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Cec_ParSat_t ParsSat, * pPars = &ParsSat;
+    Gia_Man_t * pTemp;
+    int c;
+    int fCSat = 0;
+    Cec_ManSatSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "CSNnmtcvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nSatVarMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nSatVarMax < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nCallsRecycle = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nCallsRecycle < 0 )
+                goto usage;
+            break;
+        case 'n':
+            pPars->fNonChrono ^= 1;
+            break;
+        case 'm':
+            pPars->fCheckMiter ^= 1;
+            break;
+        case 't':
+            pPars->fLearnCls ^= 1;
+            break;
+        case 'c':
+            fCSat ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Sat(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( fCSat )
+    {
+        Vec_Int_t * vCounters;
+        Vec_Str_t * vStatus;
+        if ( pPars->fLearnCls )
+            vCounters = Tas_ManSolveMiterNc( pAbc->pGia, pPars->nBTLimit, &vStatus, pPars->fVerbose );
+        else if ( pPars->fNonChrono )
+            vCounters = Cbs_ManSolveMiterNc( pAbc->pGia, pPars->nBTLimit, &vStatus, pPars->fVerbose );
+        else
+            vCounters = Cbs_ManSolveMiter( pAbc->pGia, pPars->nBTLimit, &vStatus, pPars->fVerbose );
+        Vec_IntFree( vCounters );
+        Vec_StrFree( vStatus );
+    }
+    else
+    {
+        pTemp = Cec_ManSatSolving( pAbc->pGia, pPars );
+        Abc_FrameUpdateGia( pAbc, pTemp );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &sat [-CSN <num>] [-nmctvh]\n" );
+    Abc_Print( -2, "\t         performs SAT solving for the combinational outputs\n" );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit );
+    Abc_Print( -2, "\t-S num : the min number of variables to recycle the solver [default = %d]\n", pPars->nSatVarMax );
+    Abc_Print( -2, "\t-N num : the min number of calls to recycle the solver [default = %d]\n", pPars->nCallsRecycle );
+    Abc_Print( -2, "\t-n     : toggle using non-chronological backtracking [default = %s]\n", pPars->fNonChrono? "yes": "no" );
+    Abc_Print( -2, "\t-m     : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" );
+    Abc_Print( -2, "\t-c     : toggle using circuit-based SAT solver [default = %s]\n", fCSat? "yes": "no" );
+    Abc_Print( -2, "\t-t     : toggle using learning in curcuit-based solver [default = %s]\n", pPars->fLearnCls? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Cec_ParFra_t ParsFra, * pPars = &ParsFra;
+    Gia_Man_t * pTemp;
+    int c;
+    Cec_ManFraSetDefaultParams( pPars );
+    pPars->fSatSweeping = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "WRILDCrmdwvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nWords < 0 )
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRounds = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRounds < 0 )
+                goto usage;
+            break;
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nItersMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nItersMax < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nLevelMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLevelMax < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nDepthMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nDepthMax < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'r':
+            pPars->fRewriting ^= 1;
+            break;
+        case 'm':
+            pPars->fCheckMiter ^= 1;
+            break;
+        case 'd':
+            pPars->fDualOut ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Fraig(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Cec_ManSatSweeping( pAbc->pGia, pPars );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &fraig [-WRILDC <num>] [-rmdwvh]\n" );
+    Abc_Print( -2, "\t         performs combinational SAT sweeping\n" );
+    Abc_Print( -2, "\t-W num : the number of simulation words [default = %d]\n", pPars->nWords );
+    Abc_Print( -2, "\t-R num : the number of simulation rounds [default = %d]\n", pPars->nRounds );
+    Abc_Print( -2, "\t-I num : the number of sweeping iterations [default = %d]\n", pPars->nItersMax );
+    Abc_Print( -2, "\t-L num : the max number of levels of nodes to consider [default = %d]\n", pPars->nLevelMax );
+    Abc_Print( -2, "\t-D num : the max number of steps of speculative reduction [default = %d]\n", pPars->nDepthMax );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit );
+    Abc_Print( -2, "\t-r     : toggle the use of AIG rewriting [default = %s]\n", pPars->fRewriting? "yes": "no" );
+    Abc_Print( -2, "\t-m     : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" );
+    Abc_Print( -2, "\t-d     : toggle using double output miters [default = %s]\n", pPars->fDualOut? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle printing even more verbose information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9CFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c;
+    Ssc_Pars_t Pars, * pPars = &Pars;
+    Ssc_ManSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "WCacvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nWords < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'a':
+            pPars->fAppend ^= 1;
+            break;
+        case 'c':
+            pPars->fVerify ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9CFraig(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Ssc_PerformSweepingConstr( pAbc->pGia, pPars );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &cfraig [-WC <num>] [-acvh]\n" );
+    Abc_Print( -2, "\t         performs combinational SAT sweeping under constraints\n" );
+    Abc_Print( -2, "\t         which are present in the AIG or set manually using \"constr\"\n" );
+    Abc_Print( -2, "\t         (constraints are listed as last POs and true when they are 0)\n" );
+    Abc_Print( -2, "\t-W num : the number of simulation words [default = %d]\n", pPars->nWords );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit );
+    Abc_Print( -2, "\t-a     : toggle appending constraints to the result [default = %s]\n", pPars->fAppend? "yes": "no" );
+    Abc_Print( -2, "\t-c     : toggle performing internal verification [default = %s]\n", pPars->fVerify? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Srm( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char * pFileNameIn = NULL;
+    char pFileName[10] = "gsrm.aig", pFileName2[10] = "gsyn.aig";
+    Gia_Man_t * pTemp, * pAux;
+    int c, fVerbose = 0;
+    int fSynthesis = 0;
+    int fSpeculate = 1;
+    int fSkipSome = 0;
+    int fDualOut = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Adrsfvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pFileNameIn = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'd':
+            fDualOut ^= 1;
+            break;
+        case 'r':
+            fSynthesis ^= 1;
+            break;
+        case 's':
+            fSpeculate ^= 1;
+            break;
+        case 'f':
+            fSkipSome ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Srm(): There is no AIG.\n" );
+        return 1;
+    }
+    sprintf(pFileName,  "gsrm%s.aig", fSpeculate? "" : "s" );
+    sprintf(pFileName2, "gsyn%s.aig", fSpeculate? "" : "s" );
+    pTemp = Gia_ManSpecReduce( pAbc->pGia, fDualOut, fSynthesis, fSpeculate, fSkipSome, fVerbose );
+    if ( pTemp )
+    {
+        if ( fSpeculate )
+        {
+            pTemp = Gia_ManSeqStructSweep( pAux = pTemp, 1, 1, 0 );
+            Gia_ManStop( pAux );
+        }
+        Gia_AigerWrite( pTemp, pFileNameIn ? pFileNameIn : pFileName, 0, 0 );
+        Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", pFileName );
+        Gia_ManPrintStatsShort( pTemp );
+        Gia_ManStop( pTemp );
+    }
+    if ( fSynthesis )
+    {
+        pTemp = Gia_ManEquivReduce( pAbc->pGia, 1, fDualOut, 0, fVerbose );
+        if ( pTemp )
+        {
+            pTemp = Gia_ManSeqStructSweep( pAux = pTemp, 1, 1, 0 );
+            Gia_ManStop( pAux );
+
+            Gia_AigerWrite( pTemp, pFileName2, 0, 0 );
+            Abc_Print( 1, "Reduced original network was written into file \"%s\".\n", pFileName2 );
+            Gia_ManPrintStatsShort( pTemp );
+            Gia_ManStop( pTemp );
+        }
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &srm [-A file] [-drsfvh]\n" );
+    Abc_Print( -2, "\t          writes speculatively reduced model into file \"%s\"\n", pFileName );
+    Abc_Print( -2, "\t-A file : file name for dumping speculative-reduced model [default = \"gsrm.aig\"]\n" );
+    Abc_Print( -2, "\t-d      : toggle creating dual-output miter [default = %s]\n", fDualOut? "yes": "no" );
+    Abc_Print( -2, "\t-r      : toggle writing reduced network for synthesis [default = %s]\n", fSynthesis? "yes": "no" );
+    Abc_Print( -2, "\t-s      : toggle using speculation at the internal nodes [default = %s]\n", fSpeculate? "yes": "no" );
+    Abc_Print( -2, "\t-f      : toggle filtering to remove redundant equivalences [default = %s]\n", fSkipSome? "yes": "no" );
+    Abc_Print( -2, "\t-v      : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h      : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Srm2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char pFileName[10], * pFileName1, * pFileName2;
+    Gia_Man_t * pTemp, * pAux;
+    int fLatchA = 0, fLatchB = 0;
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "abvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'a':
+            fLatchA ^= 1;
+            break;
+        case 'b':
+            fLatchB ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Srm2(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( pAbc->pGia->pReprs == NULL || pAbc->pGia->pNexts == NULL )
+    {
+        Abc_Print( -1, "Equivalences are not defined.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 2 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Srm2(): Expecting two file names on the command line.\n" );
+        return 1;
+    }
+    // get the input file name
+    pFileName1 = argv[globalUtilOptind];
+    pFileName2 = argv[globalUtilOptind+1];
+    // create file name
+    sprintf(pFileName,  "gsrm.aig" );
+    pTemp = Gia_ManDup( pAbc->pGia );
+    // copy equivalences
+    pTemp->pReprs = ABC_ALLOC( Gia_Rpr_t, Gia_ManObjNum(pTemp) );
+    memcpy( pTemp->pReprs, pAbc->pGia->pReprs, sizeof(Gia_Rpr_t) * Gia_ManObjNum(pTemp) );
+    pTemp->pNexts = ABC_ALLOC( int, Gia_ManObjNum(pTemp) );
+    memcpy( pTemp->pNexts, pAbc->pGia->pNexts, sizeof(int) * Gia_ManObjNum(pTemp) );
+//Gia_ManPrintStats( pTemp, 0 );
+    // filter the classes
+    if ( !Gia_ManFilterEquivsForSpeculation( pTemp, pFileName1, pFileName2, fLatchA, fLatchB ) )
+    {
+        Gia_ManStop( pTemp );
+        Abc_Print( -1, "Filtering equivalences has failed.\n" );
+        return 1;
+    }
+//Gia_ManPrintStats( pTemp, 0 );
+    pTemp = Gia_ManSpecReduce( pAux = pTemp, 0, 0, 1, 0, 0 );
+    Gia_ManStop( pAux );
+    if ( pTemp )
+    {
+        pTemp = Gia_ManSeqStructSweep( pAux = pTemp, 1, 1, 0 );
+        Gia_ManStop( pAux );
+
+        Gia_AigerWrite( pTemp, pFileName, 0, 0 );
+        Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", pFileName );
+        Gia_ManPrintStatsShort( pTemp );
+        Gia_ManStop( pTemp );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &srm2 [-abvh] <PartA_FileName> <PartB_FileName>\n" );
+    Abc_Print( -2, "\t         writes speculatively reduced model into file \"%s\"\n", pFileName );
+    Abc_Print( -2, "\t         only preserves equivalences across PartA and PartB\n" );
+    Abc_Print( -2, "\t-a     : toggle using latches only in PartA [default = %s]\n", fLatchA? "yes": "no" );
+    Abc_Print( -2, "\t-b     : toggle using latches only in PartB [default = %s]\n", fLatchB? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Filter( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char * pFileName1 = NULL, * pFileName2 = NULL;
+    int fFlopsOnly = 0, fFlopsWith = 0;
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "fgvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'f':
+            fFlopsOnly ^= 1;
+            break;
+        case 'g':
+            fFlopsWith ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Srm2(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( pAbc->pGia->pReprs == NULL || pAbc->pGia->pNexts == NULL )
+    {
+        Abc_Print( -1, "Equivalences are not defined.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind && argc != globalUtilOptind + 2 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Srm2(): Expecting two file names on the command line.\n" );
+        return 1;
+    }
+    // filter using one of the choices
+    if ( fFlopsOnly ^ fFlopsWith )
+        Gia_ManFilterEquivsUsingLatches( pAbc->pGia, fFlopsOnly, fFlopsWith );
+    // get the input file name
+    if ( argc == globalUtilOptind + 2 )
+    {
+        pFileName1 = argv[globalUtilOptind];
+        pFileName2 = argv[globalUtilOptind+1];
+        if ( !Gia_ManFilterEquivsUsingParts( pAbc->pGia, pFileName1, pFileName2 ) )
+        {
+            Abc_Print( -1, "Filtering equivalences using PartA and PartB has failed.\n" );
+            return 1;
+        }
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &filter [-fgvh] <PartA_FileName> <PartB_FileName>\n" );
+    Abc_Print( -2, "\t         performs filtering of equivalence classes\n" );
+    Abc_Print( -2, "\t         (if Parts A/B are given, removes classes composed of one part)\n" );
+    Abc_Print( -2, "\t-f     : toggle removing all elements except flops [default = %s]\n", fFlopsOnly? "yes": "no" );
+    Abc_Print( -2, "\t-g     : toggle removing removing classes without flops [default = %s]\n", fFlopsWith? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Reduce( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp, * pTemp2;
+    int c, fVerbose = 0;
+    int fUseAll = 0;
+    int fDualOut = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "advh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'a':
+            fUseAll ^= 1;
+            break;
+        case 'd':
+            fDualOut ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Reduce(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( fUseAll )
+    {
+        pTemp = Gia_ManEquivReduce( pAbc->pGia, fUseAll, fDualOut, 0, fVerbose );
+        pTemp = Gia_ManSeqStructSweep( pTemp2 = pTemp, 1, 1, 0 );
+        Gia_ManStop( pTemp2 );
+    }
+    else
+        pTemp = Gia_ManEquivReduceAndRemap( pAbc->pGia, 1, fDualOut );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &reduce [-advh]\n" );
+    Abc_Print( -2, "\t         reduces the circuit using equivalence classes\n" );
+    Abc_Print( -2, "\t-a     : toggle merging all equivalences [default = %s]\n", fUseAll? "yes": "no" );
+    Abc_Print( -2, "\t-d     : toggle using dual-output merging [default = %s]\n", fDualOut? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9EquivMark( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Gia_ManEquivMark( Gia_Man_t * p, char * pFileName, int fSkipSome, int fVerbose );
+    char * pFileName;
+    int c, fVerbose = 0;
+    int fSkipSome = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "fvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'f':
+            fSkipSome ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9EquivMark(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    // mark equivalences
+    Gia_ManEquivMark( pAbc->pGia, pFileName, fSkipSome, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &equiv_mark [-fvh] <miter.aig>\n" );
+    Abc_Print( -2, "\t              marks equivalences using an external miter\n" );
+    Abc_Print( -2, "\t-f          : toggle the use of filtered equivalences [default = %s]\n", fSkipSome? "yes": "no" );
+    Abc_Print( -2, "\t-v          : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h          : print the command usage\n");
+    Abc_Print( -2, "\t<miter.aig> : file with the external miter to read\n");
+    Abc_Print( -2, "\t              \n" );
+    Abc_Print( -2, "\t              The external miter should be generated by &srm -s\n" );
+    Abc_Print( -2, "\t              and (partially) solved by any verification engine(s).\n" );
+    Abc_Print( -2, "\t              The external miter should have as many POs as\n" );
+    Abc_Print( -2, "\t              the number of POs in the current AIG plus\n" );
+    Abc_Print( -2, "\t              the number of equivalences in the current AIG.\n" );
+    Abc_Print( -2, "\t              If some POs are proved, the corresponding equivs\n" );
+    Abc_Print( -2, "\t              are marked as proved, to be reduced by &reduce.\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9EquivFilter( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Gia_ManEquivFilter( Gia_Man_t * p, Vec_Int_t * vPoIds, int fVerbose );
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9EquivFilter(): There is no AIG.\n" );
+        return 1;
+    }
+    Gia_ManEquivFilter( pAbc->pGia, pAbc->vAbcObjIds, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &equiv_filter [-vh]\n" );
+    Abc_Print( -2, "\t              filters equivalence candidates after disproving some SRM outputs\n" );
+    Abc_Print( -2, "\t              (the array of disproved outputs should be given as pAbc->vAbcObjIds)\n" );
+    Abc_Print( -2, "\t-v          : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h          : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Cec_ParCec_t ParsCec, * pPars = &ParsCec;
+    FILE * pFile;
+    Gia_Man_t * pSecond, * pMiter;
+    char * FileName, * pTemp;
+    char ** pArgvNew;
+    int c, nArgcNew, fMiter = 0;
+    int fDumpMiter = 0;
+    Cec_ManCecSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "CTmdvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeLimit < 0 )
+                goto usage;
+            break;
+        case 'm':
+            fMiter ^= 1;
+            break;
+        case 'd':
+            fDumpMiter ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( fMiter )
+    {
+        if ( Gia_ManPoNum(pAbc->pGia) & 1 )
+        {
+            Abc_Print( -1, "The dual-output miter should have an even number of outputs.\n" );
+            return 1;
+        }
+        Abc_Print( 1, "Assuming the current network is a double-output miter. (Conflict limit = %d.)\n", pPars->nBTLimit );
+        pAbc->Status = Cec_ManVerify( pAbc->pGia, pPars );
+        Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb );
+        return 0;
+    }
+
+    pArgvNew = argv + globalUtilOptind;
+    nArgcNew = argc - globalUtilOptind;
+    if ( nArgcNew != 1 )
+    {
+        if ( pAbc->pGia->pSpec == NULL )
+        {
+            Abc_Print( -1, "File name is not given on the command line.\n" );
+            return 1;
+        }
+        FileName = pAbc->pGia->pSpec;
+    }
+    else
+        FileName = pArgvNew[0];
+    // fix the wrong symbol
+    for ( pTemp = FileName; *pTemp; pTemp++ )
+        if ( *pTemp == '>' )
+            *pTemp = '\\';
+    if ( (pFile = fopen( FileName, "r" )) == NULL )
+    {
+        Abc_Print( -1, "Cannot open input file \"%s\". ", FileName );
+        if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) )
+            Abc_Print( 1, "Did you mean \"%s\"?", FileName );
+        Abc_Print( 1, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+    pSecond = Gia_AigerRead( FileName, 0, 0 );
+    if ( pSecond == NULL )
+    {
+        Abc_Print( -1, "Reading AIGER has failed.\n" );
+        return 0;
+    }
+    // compute the miter
+    pMiter = Gia_ManMiter( pAbc->pGia, pSecond, 0, 1, 0, 0, pPars->fVerbose );
+    if ( pMiter )
+    {
+        if ( fDumpMiter )
+        {
+            Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "cec_miter.aig" );
+            Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0 );
+        }
+        pAbc->Status = Cec_ManVerify( pMiter, pPars );
+        Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb );
+        Gia_ManStop( pMiter );
+    }
+    Gia_ManStop( pSecond );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &cec [-CT num] [-mdvh]\n" );
+    Abc_Print( -2, "\t         new combinational equivalence checker\n" );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit );
+    Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeLimit );
+    Abc_Print( -2, "\t-m     : toggle miter vs. two circuits [default = %s]\n", fMiter? "miter":"two circuits");
+    Abc_Print( -2, "\t-d     : toggle dumping dual-output miter [default = %s]\n", fDumpMiter? "yes":"no");
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes":"no");
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Verify( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Cec_ParCec_t ParsCec, * pPars = &ParsCec;
+    int c;
+    Cec_ManCecSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "CTvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeLimit < 0 )
+                goto usage;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    Gia_ManVerifyWithBoxes( pAbc->pGia, pPars );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &verify [-CT num] [-vh]\n" );
+    Abc_Print( -2, "\t         performs verification of combinational design\n" );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit );
+    Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeLimit );
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes":"no");
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Sweep( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    Dch_Pars_t Pars, * pPars = &Pars;
+    int c;
+    // set defaults
+    Dch_ManSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptfvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nWords < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nSatVarMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nSatVarMax < 0 )
+                goto usage;
+            break;
+        case 's':
+            pPars->fSynthesis ^= 1;
+            break;
+        case 'p':
+            pPars->fPower ^= 1;
+            break;
+        case 't':
+            pPars->fSimulateTfo ^= 1;
+            break;
+        case 'f':
+            pPars->fLightSynth ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Sweep(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManFraigSweep( pAbc->pGia, pPars );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &sweep [-WCS num] [-sptfvh]\n" );
+    Abc_Print( -2, "\t         computes structural choices using a new approach\n" );
+    Abc_Print( -2, "\t-W num : the max number of simulation words [default = %d]\n", pPars->nWords );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit );
+    Abc_Print( -2, "\t-S num : the max number of SAT variables [default = %d]\n", pPars->nSatVarMax );
+    Abc_Print( -2, "\t-s     : toggle synthesizing three snapshots [default = %s]\n", pPars->fSynthesis? "yes": "no" );
+    Abc_Print( -2, "\t-p     : toggle power-aware rewriting [default = %s]\n", pPars->fPower? "yes": "no" );
+    Abc_Print( -2, "\t-t     : toggle simulation of the TFO classes [default = %s]\n", pPars->fSimulateTfo? "yes": "no" );
+    Abc_Print( -2, "\t-f     : toggle using lighter logic synthesis [default = %s]\n", pPars->fLightSynth? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Force( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int nIters     = 20;
+    int fClustered =  1;
+    int fVerbose   =  1;
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Icvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nIters < 0 )
+                goto usage;
+            break;
+        case 'c':
+            fClustered ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Force(): There is no AIG.\n" );
+        return 1;
+    }
+    For_ManExperiment( pAbc->pGia, nIters, fClustered, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &force [-I <num>] [-cvh]\n" );
+    Abc_Print( -2, "\t         one-dimensional placement algorithm FORCE introduced by\n" );
+    Abc_Print( -2, "\t         F. A. Aloul, I. L. Markov, and K. A. Sakallah (GLSVLSI�03).\n" );
+    Abc_Print( -2, "\t-I num : the number of refinement iterations [default = %d]\n", nIters );
+    Abc_Print( -2, "\t-c     : toggle clustered representation [default = %s]\n", fClustered? "yes":"no");
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", fVerbose? "yes":"no");
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Embed( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Emb_Par_t Pars, * pPars = &Pars;
+    int c;
+    pPars->nDims      = 30;
+    pPars->nIters     = 10;
+    pPars->nSols      =  2;
+    pPars->fRefine    =  0;
+    pPars->fCluster   =  0;
+    pPars->fDump      =  0;
+    pPars->fDumpLarge =  0;
+    pPars->fShowImage =  0;
+    pPars->fVerbose   =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "DIrcdlsvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nDims = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nDims < 0 )
+                goto usage;
+            break;
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nIters < 0 )
+                goto usage;
+            break;
+        case 'r':
+            pPars->fRefine ^= 1;
+            break;
+        case 'c':
+            pPars->fCluster ^= 1;
+            break;
+        case 'd':
+            pPars->fDump ^= 1;
+            break;
+        case 'l':
+            pPars->fDumpLarge ^= 1;
+            break;
+        case 's':
+            pPars->fShowImage ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Embed(): There is no AIG.\n" );
+        return 1;
+    }
+    Gia_ManSolveProblem( pAbc->pGia, pPars );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &embed [-DI <num>] [-rdlscvh]\n" );
+    Abc_Print( -2, "\t         fast placement based on high-dimensional embedding from\n" );
+    Abc_Print( -2, "\t         D. Harel and Y. Koren, \"Graph drawing by high-dimensional\n" );
+    Abc_Print( -2, "\t         embedding\", J. Graph Algs & Apps, 2004, Vol 8(2), pp. 195-217\n" );
+    Abc_Print( -2, "\t-D num : the number of dimensions for embedding [default = %d]\n", pPars->nDims );
+    Abc_Print( -2, "\t-I num : the number of refinement iterations [default = %d]\n", pPars->nIters );
+    Abc_Print( -2, "\t-r     : toggle the use of refinement [default = %s]\n", pPars->fRefine? "yes":"no");
+    Abc_Print( -2, "\t-c     : toggle clustered representation [default = %s]\n", pPars->fCluster? "yes":"no");
+    Abc_Print( -2, "\t-d     : toggle dumping placement into a Gnuplot file [default = %s]\n", pPars->fDump? "yes":"no");
+    Abc_Print( -2, "\t-l     : toggle dumping Gnuplot for large placement [default = %s]\n", pPars->fDumpLarge? "yes":"no");
+    Abc_Print( -2, "\t-s     : toggle showing image if Gnuplot is installed [default = %s]\n", pPars->fShowImage? "yes":"no");
+    Abc_Print( -2, "\t-v     : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes":"no");
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Sopb( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int nLevelMax   = 0;
+    int nLevelRatio = 0;
+    int nCutNum     = 8;
+    int nRelaxRatio = 0;
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "LQCRvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLevelMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLevelMax < 0 )
+                goto usage;
+            break;
+        case 'Q':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-Q\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nLevelRatio = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLevelRatio < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nCutNum = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nCutNum < 0 )
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nRelaxRatio = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nRelaxRatio < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Sopb(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( nLevelMax || nLevelRatio )
+        pTemp = Gia_ManPerformSopBalanceWin( pAbc->pGia, nLevelMax, nLevelRatio, nCutNum, nRelaxRatio, fVerbose );
+    else
+        pTemp = Gia_ManPerformSopBalance( pAbc->pGia, nCutNum, nRelaxRatio, fVerbose );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &sopb [-LQCR num] [-vh]\n" );
+    Abc_Print( -2, "\t         performs SOP balancing\n" );
+    Abc_Print( -2, "\t-L num : optimize paths above this level [default = %d]\n", nLevelMax );
+    Abc_Print( -2, "\t-Q num : optimize paths falling into this window [default = %d]\n", nLevelRatio );
+    Abc_Print( -2, "\t-C num : the number of cuts at a node [default = %d]\n", nCutNum );
+    Abc_Print( -2, "\t-R num : the delay relaxation ratio (num >= 0) [default = %d]\n", nRelaxRatio );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char Buffer[200];
+    char LutSize[200];
+    Gia_Man_t * pNew;
+    If_Par_t Pars, * pPars = &Pars;
+    int c;
+    // set defaults
+    Gia_ManSetIfParsDefault( pPars );
+    if ( pAbc->pLibLut == NULL )
+    {
+        Abc_Print( -1, "LUT library is not given. Using default LUT library.\n" );
+        pAbc->pLibLut = If_LibLutSetSimple( 6 );
+    }
+    pPars->pLutLib = (If_LibLut_t *)pAbc->pLibLut;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRDEWSTqalepmrsdbgxyojikfuztncvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLutSize < 0 )
+                goto usage;
+            // if the LUT size is specified, disable library
+            pPars->pLutLib = NULL;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nCutsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nCutsMax < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nFlowIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFlowIters < 0 )
+                goto usage;
+            break;
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nAreaIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nAreaIters < 0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by a positive integer no less than 3.\n" );
+                goto usage;
+            }
+            pPars->nGateSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nGateSize < 2 )
+                goto usage;
+            break;
+		case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" );
+                return 0;
+            }
+			pPars->nRelaxRatio = atoi(argv[globalUtilOptind]);
+			globalUtilOptind++;
+			if ( pPars->nRelaxRatio < 0 ) 
+				goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->DelayTarget = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->DelayTarget <= 0.0 )
+                goto usage;
+            break;
+        case 'E':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-E\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->Epsilon = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->Epsilon < 0.0 || pPars->Epsilon > 1.0 )
+                goto usage;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->WireDelay = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->WireDelay < 0.0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by string.\n" );
+                goto usage;
+            }
+            pPars->pLutStruct = argv[globalUtilOptind];
+            globalUtilOptind++;
+            if ( strlen(pPars->pLutStruct) != 2 && strlen(pPars->pLutStruct) != 3 )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by a 2- or 3-char string (e.g. \"44\" or \"555\").\n" );
+                goto usage;
+            }
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by a positive integer 0,1,or 2.\n" );
+                goto usage;
+            }
+            pPars->nStructType = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nStructType < 0 || pPars->nStructType > 2 )
+                goto usage;
+            break;
+        case 'q':
+            pPars->fPreprocess ^= 1;
+            break;
+        case 'a':
+            pPars->fArea ^= 1;
+            break;
+        case 'r':
+            pPars->fExpRed ^= 1;
+            break;
+        case 'l':
+            pPars->fLatchPaths ^= 1;
+            break;
+        case 'e':
+            pPars->fEdge ^= 1;
+            break;
+        case 'p':
+            pPars->fPower ^= 1;
+            break;
+        case 'm':
+            pPars->fCutMin ^= 1;
+            break;
+        case 's':
+            pPars->fDelayOptLut ^= 1;
+            break;
+        case 'd':
+            pPars->fBidec ^= 1;
+            break;
+        case 'b':
+            pPars->fUseBat ^= 1;
+            break;
+        case 'g':
+            pPars->fDelayOpt ^= 1;
+            break;
+        case 'x':
+            pPars->fDsdBalance ^= 1;
+            break;
+        case 'y':
+            pPars->fUserRecLib ^= 1;
+            break;
+        case 'o':
+            pPars->fUseBuffs ^= 1;
+            break;
+        case 'j':
+            pPars->fEnableCheck07 ^= 1;
+            break;
+        case 'i':
+            pPars->fEnableCheck08 ^= 1;
+            break;
+        case 'k':
+            pPars->fEnableCheck10 ^= 1;
+            break;
+        case 'f':
+            pPars->fEnableCheck75 ^= 1;
+            break;
+        case 'u':
+            pPars->fEnableCheck75u ^= 1;
+            break;
+        case 'z':
+            pPars->fDeriveLuts ^= 1;
+            break;
+        case 't':
+            pPars->fDoAverage ^= 1;
+            break;
+        case 'n':
+            pPars->fUseDsd ^= 1;
+            break;
+        case 'c':
+            pPars->fUseTtPerm ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Empty GIA network.\n" );
+        return 1;
+    }
+
+    if ( pPars->nLutSize == -1 )
+    {
+        if ( pPars->pLutLib == NULL )
+        {
+            Abc_Print( -1, "The LUT library is not given.\n" );
+            return 1;
+        }
+        // get LUT size from the library
+        pPars->nLutSize = pPars->pLutLib->LutMax;
+        // if variable pin delay, force truth table computation
+//        if ( pPars->pLutLib->fVarPinDelays )
+//            pPars->fTruth = 1;
+    }
+
+    if ( pPars->nLutSize < 2 || pPars->nLutSize > IF_MAX_LUTSIZE )
+    {
+        Abc_Print( -1, "Incorrect LUT size (%d).\n", pPars->nLutSize );
+        return 1;
+    }
+
+    if ( pPars->nCutsMax < 1 || pPars->nCutsMax >= (1<<12) )
+    {
+        Abc_Print( -1, "Incorrect number of cuts.\n" );
+        return 1;
+    }
+
+    // enable truth table computation if choices are selected
+    if ( Gia_ManHasChoices(pAbc->pGia) )
+    {
+//        if ( !Abc_FrameReadFlag("silentmode") )
+//            Abc_Print( 0, "Performing LUT mapping with choices.\n" );
+        pPars->fExpRed = 0;
+    }
+
+    if ( pPars->fUseBat )
+    {
+        if ( pPars->nLutSize < 4 || pPars->nLutSize > 6 )
+        {
+            Abc_Print( -1, "This feature only works for {4,5,6}-LUTs.\n" );
+            return 1;
+        }
+        pPars->fCutMin = 1;
+    }
+
+    if ( pPars->fEnableCheck07 + pPars->fEnableCheck08 + pPars->fEnableCheck10 + pPars->fEnableCheck75 + pPars->fEnableCheck75u + (pPars->pLutStruct != NULL) > 1 )
+    {
+        Abc_Print( -1, "Only one additional check can be performed at the same time.\n" );
+        return 1;
+    }
+    if ( pPars->fEnableCheck07 )
+    {
+        if ( pPars->nLutSize < 6 || pPars->nLutSize > 7 )
+        {
+            Abc_Print( -1, "This feature only works for {6,7}-LUTs.\n" );
+            return 1;
+        }
+        pPars->pFuncCell = If_CutPerformCheck07;
+        pPars->fCutMin = 1;
+    }
+    if ( pPars->fEnableCheck08 )
+    {
+        if ( pPars->nLutSize < 6 || pPars->nLutSize > 8 )
+        {
+            Abc_Print( -1, "This feature only works for {6,7,8}-LUTs.\n" );
+            return 1;
+        }
+        pPars->pFuncCell = If_CutPerformCheck08;
+        pPars->fCutMin = 1;
+    }
+    if ( pPars->fEnableCheck10 )
+    {
+        if ( pPars->nLutSize < 6 || pPars->nLutSize > 10 )
+        {
+            Abc_Print( -1, "This feature only works for {6,7,8,9,10}-LUTs.\n" );
+            return 1;
+        }
+        pPars->pFuncCell = If_CutPerformCheck10;
+        pPars->fCutMin = 1;
+    }
+    if ( pPars->fEnableCheck75 || pPars->fEnableCheck75u )
+    {
+        if ( pPars->fEnableCheck75 && pPars->fEnableCheck75u )
+        {
+            Abc_Print( -1, "Switches -f and -u are not compatible.\n" );
+            return 1;
+        }
+        if ( pPars->nLutSize < 5 || pPars->nLutSize > 8 )
+        {
+            Abc_Print( -1, "This feature only works for {6,7,8}-LUTs.\n" );
+            return 1;
+        }
+        pPars->pFuncCell = If_CutPerformCheck75;
+        pPars->fCutMin = 1;
+    }
+    if ( pPars->pLutStruct )
+    {
+        if ( pPars->fDsdBalance )
+        {
+            Abc_Print( -1, "Incompatible options (-S and -x).\n" );
+            return 1;
+        }
+        if ( pPars->nLutSize < 6 || pPars->nLutSize > 16 )
+        {
+            Abc_Print( -1, "This feature only works for [6;16]-LUTs.\n" );
+            return 1;
+        }
+        pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheck16;
+        pPars->fCutMin = 1;
+    }
+
+    // enable truth table computation if cut minimization is selected
+    if ( pPars->fCutMin || pPars->fDeriveLuts )
+    {
+        pPars->fTruth = 1;
+        pPars->fExpRed = 0;
+        if ( pPars->pLutStruct == NULL )
+            pPars->fDeriveLuts = 1;
+    }
+    // modify the subgraph recording
+    if ( pPars->fUserRecLib )
+    {
+        pPars->fTruth      =  1;
+        pPars->fCutMin     =  1;
+        pPars->fExpRed     =  0;
+        pPars->fUsePerm    =  1;
+        pPars->pLutLib     =  NULL;
+    }
+    // modify for delay optimization
+    if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut )
+    {
+        pPars->fTruth      =  1;
+        pPars->fCutMin     =  1;
+        pPars->fExpRed     =  0;
+        pPars->fUseDsd     =  pPars->fDsdBalance || pPars->fDelayOptLut;
+        pPars->pLutLib     =  NULL;
+    }
+    // modify for delay optimization
+    if ( pPars->nGateSize > 0 )
+    {
+        pPars->fTruth      =  1;
+        pPars->fCutMin     =  1;
+        pPars->fExpRed     =  0;
+        pPars->fUsePerm    =  1;
+        pPars->pLutLib     =  NULL;
+        pPars->nLutSize    =  pPars->nGateSize;
+    }
+
+    if ( pPars->fUseDsd || pPars->fUseTtPerm )
+    {
+        pPars->fTruth      =  1;
+        pPars->fCutMin     =  1;
+        pPars->fExpRed     =  0;
+    }
+
+    if ( pPars->fUseDsd )
+    {
+        int LutSize = (pPars->pLutStruct && pPars->pLutStruct[2] == 0)? pPars->pLutStruct[0] - '0' : 0;
+        If_DsdMan_t * p = (If_DsdMan_t *)Abc_FrameReadManDsd();
+        if ( pPars->pLutStruct && pPars->pLutStruct[2] != 0 )
+        {
+            printf( "DSD only works for LUT structures XY.\n" );
+            return 0;
+        }
+        if ( p && pPars->nLutSize > If_DsdManVarNum(p) )
+        {
+            printf( "DSD manager has incompatible number of variables.\n" );
+            return 0;
+        }
+        if ( p && LutSize != If_DsdManLutSize(p) && !pPars->fDsdBalance )
+        {
+            printf( "DSD manager has different LUT size.\n" );
+            return 0;
+        }
+        if ( p == NULL )
+            Abc_FrameSetManDsd( If_DsdManAlloc(pPars->nLutSize, LutSize) );
+    }
+
+    if ( pPars->fUserRecLib )
+    {
+        if ( !Abc_NtkRecIsRunning3() )
+        {
+            printf( "LMS manager is not running (use \"rec_start3\").\n" );
+            return 0;
+        }
+        if ( Abc_NtkRecInputNum3() != pPars->nLutSize )
+        {
+            printf( "The number of library inputs (%d) different from the K parameters (%d).\n", Abc_NtkRecInputNum3(), pPars->nLutSize );
+            return 0;
+        }
+    }
+
+    // complain if truth tables are requested but the cut size is too large
+    if ( pPars->fTruth && pPars->nLutSize > IF_MAX_FUNC_LUTSIZE )
+    {
+        Abc_Print( -1, "Truth tables cannot be computed for LUT larger than %d inputs.\n", IF_MAX_FUNC_LUTSIZE );
+        return 1;
+    }
+    if ( pAbc->pGia->pManTime && pAbc->pLibBox == NULL )
+    {
+        Abc_Print( -1, "Design has boxes but box library is not entered.\n" );
+        return 1;
+    }
+
+    // perform mapping
+    pNew = Gia_ManPerformMapping( pAbc->pGia, pPars, 1 );
+    if ( pNew == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9If(): Mapping of GIA has failed.\n" );
+        return 1;
+    }
+    Abc_FrameUpdateGia( pAbc, pNew );
+    return 0;
+
+usage:
+    if ( pPars->DelayTarget == -1 )
+        sprintf(Buffer, "best possible" );
+    else
+        sprintf(Buffer, "%.2f", pPars->DelayTarget );
+    if ( pPars->nLutSize == -1 )
+        sprintf(LutSize, "library" );
+    else
+        sprintf(LutSize, "%d", pPars->nLutSize );
+    Abc_Print( -2, "usage: &if [-KCFAGRT num] [-DEW float] [-S str] [-qarlepmsdbgxyojikfuztncvh]\n" );
+    Abc_Print( -2, "\t           performs FPGA technology mapping of the network\n" );
+    Abc_Print( -2, "\t-K num   : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize );
+    Abc_Print( -2, "\t-C num   : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax );
+    Abc_Print( -2, "\t-F num   : the number of area flow recovery iterations (num >= 0) [default = %d]\n", pPars->nFlowIters );
+    Abc_Print( -2, "\t-A num   : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters );
+    Abc_Print( -2, "\t-G num   : the max AND/OR gate size for mapping (0 = unused) [default = %d]\n", pPars->nGateSize );
+    Abc_Print( -2, "\t-R num   : the delay relaxation ratio (num >= 0) [default = %d]\n", pPars->nRelaxRatio );
+    Abc_Print( -2, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer );
+    Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon );
+    Abc_Print( -2, "\t-W float : sets wire delay between adjects LUTs [default = %f]\n", pPars->WireDelay );
+    Abc_Print( -2, "\t-S str   : string representing the LUT structure [default = %s]\n", pPars->pLutStruct ? pPars->pLutStruct : "not used" );
+    Abc_Print( -2, "\t-T num   : the type of LUT structures [default = any]\n", pPars->nStructType );
+    Abc_Print( -2, "\t-q       : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" );
+    Abc_Print( -2, "\t-a       : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" );
+    Abc_Print( -2, "\t-r       : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" );
+    Abc_Print( -2, "\t-l       : optimizes latch paths for delay, other paths for area [default = %s]\n", pPars->fLatchPaths? "yes": "no" );
+    Abc_Print( -2, "\t-e       : uses edge-based cut selection heuristics [default = %s]\n", pPars->fEdge? "yes": "no" );
+    Abc_Print( -2, "\t-p       : uses power-aware cut selection heuristics [default = %s]\n", pPars->fPower? "yes": "no" );
+    Abc_Print( -2, "\t-m       : enables cut minimization by removing vacuous variables [default = %s]\n", pPars->fCutMin? "yes": "no" );
+    Abc_Print( -2, "\t-s       : toggles delay-oriented mapping used with -S <NN> [default = %s]\n", pPars->fDelayOptLut? "yes": "no" );
+    Abc_Print( -2, "\t-d       : toggles deriving local AIGs using bi-decomposition [default = %s]\n", pPars->fBidec? "yes": "no" );
+    Abc_Print( -2, "\t-b       : toggles the use of one special feature [default = %s]\n", pPars->fUseBat? "yes": "no" );
+    Abc_Print( -2, "\t-g       : toggles delay optimization by SOP balancing [default = %s]\n", pPars->fDelayOpt? "yes": "no" );
+    Abc_Print( -2, "\t-x       : toggles delay optimization by DSD balancing [default = %s]\n", pPars->fDsdBalance? "yes": "no" );
+    Abc_Print( -2, "\t-y       : toggles delay optimization with recorded library [default = %s]\n", pPars->fUserRecLib? "yes": "no" );
+    Abc_Print( -2, "\t-o       : toggles using buffers to decouple combinational outputs [default = %s]\n", pPars->fUseBuffs? "yes": "no" );
+    Abc_Print( -2, "\t-j       : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck07? "yes": "no" );
+    Abc_Print( -2, "\t-i       : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck08? "yes": "no" );
+    Abc_Print( -2, "\t-k       : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck10? "yes": "no" );
+    Abc_Print( -2, "\t-f       : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck75? "yes": "no" );
+    Abc_Print( -2, "\t-u       : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck75u? "yes": "no" );
+    Abc_Print( -2, "\t-z       : toggles deriving LUTs when mapping into LUT structures [default = %s]\n", pPars->fDeriveLuts? "yes": "no" );
+    Abc_Print( -2, "\t-t       : toggles optimizing average rather than maximum level [default = %s]\n", pPars->fDoAverage? "yes": "no" );
+    Abc_Print( -2, "\t-n       : toggles computing DSDs of the cut functions [default = %s]\n", pPars->fUseDsd? "yes": "no" );
+    Abc_Print( -2, "\t-c       : toggles computing truth tables in a new way [default = %s]\n", pPars->fUseTtPerm? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : prints the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Iff( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Gia_ManIffTest( Gia_Man_t * pGia, If_LibLut_t * pLib, int fVerbose );
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Iff(): There is no AIG to map.\n" );
+        return 1;
+    }
+    if ( !Gia_ManHasMapping(pAbc->pGia) )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Iff(): Mapping of the AIG is not defined.\n" );
+        return 1;
+    }
+    if ( pAbc->pLibLut == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Iff(): LUT library is not defined.\n" );
+        return 1;
+    }
+    Gia_ManIffTest( pAbc->pGia, (If_LibLut_t *)pAbc->pLibLut, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &iff [-vh]\n" );
+    Abc_Print( -2, "\t           performs structural mapping into LUT structures\n" );
+    Abc_Print( -2, "\t-v       : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9If2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Abc_Ntk_t * Mpm_ManCellMapping( Gia_Man_t * p, Mpm_Par_t * pPars, void * pMio );
+    extern Gia_Man_t * Mpm_ManLutMapping( Gia_Man_t * p, Mpm_Par_t * pPars );
+    char Buffer[200];
+    Abc_Ntk_t * pTemp;
+    Gia_Man_t * pNew;
+    Mpm_Par_t Pars, * pPars = &Pars;
+    int c, nLutSize = 6;
+    // set defaults
+    Mpm_ManSetParsDefault( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "KCDtmzrcuxvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nLutSize < 2 || nLutSize > 16 )
+            {
+                Abc_Print( -1, "LUT size %d is not supported.\n", nLutSize );
+                goto usage;
+            }
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nNumCuts = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nNumCuts < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->DelayTarget = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->DelayTarget <= 0.0 )
+                goto usage;
+            break;
+        case 't':
+            pPars->fUseGates ^= 1;
+            break;
+        case 'm':
+            pPars->fCutMin ^= 1;
+            break;
+        case 'z':
+            pPars->fDeriveLuts ^= 1;
+            break;
+        case 'r':
+            pPars->fOneRound ^= 1;
+            break;
+        case 'c':
+            pPars->fMap4Cnf ^= 1;
+            break;
+        case 'u':
+            pPars->fMap4Aig ^= 1;
+            break;
+        case 'x':
+            pPars->fMap4Gates ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Empty GIA network.\n" );
+        return 1;
+    }
+
+    if ( pPars->fMap4Cnf )
+        pPars->fUseDsd = 1;
+    if ( pPars->fCutMin )
+        pPars->fUseDsd = 1;
+//        pPars->fUseTruth = 1;
+    if ( pPars->fMap4Gates )
+    {
+        pPars->fUseDsd = 1;
+        if ( pAbc->pLibScl == NULL )
+        {
+            Abc_Print( -1, "There is no SCL library available.\n" );
+            return 1;
+        }
+        pPars->pScl = pAbc->pLibScl;
+    }
+    if ( pPars->fUseDsd || pPars->fUseTruth )
+        pPars->fDeriveLuts = 1;
+    if ( pPars->fUseDsd && nLutSize != 6 )
+    {
+        Abc_Print( -1, "Currently DSD can only be used with 6-input cuts.\n" );
+        return 1;
+    }
+    // perform mapping
+    assert( pPars->pLib == NULL );
+    if ( pPars->fMap4Gates )
+    {
+        if ( Abc_FrameReadLibGen() == NULL )
+        {
+            Abc_Print( -1, "There is no GENLIB library available.\n" );
+            return 1;
+        }
+        pPars->pLib = Mpm_LibLutSetSimple( nLutSize );
+        pTemp = Mpm_ManCellMapping( pAbc->pGia, pPars, Abc_FrameReadLibGen() );
+        Mpm_LibLutFree( pPars->pLib );
+        if ( pTemp == NULL )
+        {
+            Abc_Print( -1, "Abc_CommandAbc9If2(): Mapping into standard cells has failed.\n" );
+            return 1;
+        }
+        Abc_FrameReplaceCurrentNetwork( pAbc, pTemp );
+    }
+    else
+    {
+        pPars->pLib = Mpm_LibLutSetSimple( nLutSize );
+        pNew = Mpm_ManLutMapping( pAbc->pGia, pPars );
+        Mpm_LibLutFree( pPars->pLib );
+        if ( pNew == NULL )
+        {
+            Abc_Print( -1, "Abc_CommandAbc9If2(): Mapping into LUTs has failed.\n" );
+            return 1;
+        }
+        Abc_FrameUpdateGia( pAbc, pNew );
+    }
+    return 0;
+
+usage:
+    if ( pPars->DelayTarget == -1 )
+        sprintf(Buffer, "best possible" );
+    else
+        sprintf(Buffer, "%d", pPars->DelayTarget );
+    Abc_Print( -2, "usage: &if2 [-KCD num] [-tmzrcuxvwh]\n" );
+    Abc_Print( -2, "\t           performs technology mapping of the network\n" );
+    Abc_Print( -2, "\t-K num   : sets the LUT size for the mapping [default = %d]\n", nLutSize );
+    Abc_Print( -2, "\t-C num   : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nNumCuts );
+    Abc_Print( -2, "\t-D num   : sets the delay constraint for the mapping [default = %s]\n", Buffer );
+    Abc_Print( -2, "\t-t       : enables using AND/XOR/MUX nodes instead of simple AIG [default = %s]\n", pPars->fUseGates? "yes": "no" );
+    Abc_Print( -2, "\t-m       : enables cut minimization by removing vacuous variables [default = %s]\n", pPars->fCutMin? "yes": "no" );
+    Abc_Print( -2, "\t-z       : toggles deriving LUTs when mapping into LUT structures [default = %s]\n", pPars->fDeriveLuts? "yes": "no" );
+    Abc_Print( -2, "\t-r       : toggles using one round of mapping [default = %s]\n", pPars->fOneRound? "yes": "no" );
+    Abc_Print( -2, "\t-c       : toggles mapping for CNF computation [default = %s]\n", pPars->fMap4Cnf? "yes": "no" );
+    Abc_Print( -2, "\t-u       : toggles mapping for AIG computation [default = %s]\n", pPars->fMap4Aig? "yes": "no" );
+    Abc_Print( -2, "\t-x       : toggles mapping for standard cells [default = %s]\n", pPars->fMap4Gates? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggles very verbose output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : prints the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Jf( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char Buffer[200];
+    Jf_Par_t Pars, * pPars = &Pars;
+    Gia_Man_t * pNew; int c;
+    Jf_ManSetDefaultPars( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "KCDWaekmdcgvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLutSize < 2 || pPars->nLutSize > pPars->nLutSizeMax )
+            {
+                Abc_Print( -1, "LUT size %d is not supported.\n", pPars->nLutSize );
+                goto usage;
+            }
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nCutNum = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nCutNum < 1 || pPars->nCutNum > pPars->nCutNumMax )
+            {
+                Abc_Print( -1, "This number of cuts (%d) is not supported.\n", pPars->nCutNum );
+                goto usage;
+            }
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->DelayTarget = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->DelayTarget <= 0.0 )
+                goto usage;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nVerbLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nVerbLimit < 0 )
+                goto usage;
+            break;
+        case 'a':
+            pPars->fAreaOnly ^= 1;
+            break;
+        case 'e':
+            pPars->fOptEdge ^= 1;
+            break;
+        case 'k':
+            pPars->fCoarsen ^= 1;
+            break;
+        case 'm':
+            pPars->fCutMin ^= 1;
+            break;
+        case 'd':
+            pPars->fFuncDsd ^= 1;
+            break;
+        case 'c':
+            pPars->fGenCnf ^= 1;
+            break;
+        case 'g':
+            pPars->fPureAig ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Empty GIA network.\n" );
+        return 1;
+    }
+
+    if ( (pPars->fFuncDsd || pPars->fGenCnf) && pPars->nLutSize > 6 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Jf(): DSD computation works for LUT6 or less.\n" );
+        return 1;
+    }
+
+    if ( (pPars->fFuncDsd || pPars->fGenCnf) && !Sdm_ManCanRead() )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Jf(): Cannot input DSD data from file.\n" );
+        return 1;
+    }
+
+    pNew = Jf_ManPerformMapping( pAbc->pGia, pPars );
+    if ( pNew == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Jf(): Mapping into LUTs has failed.\n" );
+        return 1;
+    }
+    Abc_FrameUpdateGia( pAbc, pNew );
+    return 0;
+
+usage:
+    if ( pPars->DelayTarget == -1 )
+        sprintf(Buffer, "best possible" );
+    else
+        sprintf(Buffer, "%d", pPars->DelayTarget );
+    Abc_Print( -2, "usage: &jf [-KCDW num] [-akmdcgvwh]\n" );
+    Abc_Print( -2, "\t           performs technology mapping of the network\n" );
+    Abc_Print( -2, "\t-K num   : LUT size for the mapping (2 <= K <= %d) [default = %d]\n", pPars->nLutSizeMax, pPars->nLutSize );
+    Abc_Print( -2, "\t-C num   : the max number of priority cuts (1 <= C <= %d) [default = %d]\n", pPars->nCutNumMax, pPars->nCutNum );
+    Abc_Print( -2, "\t-D num   : sets the delay constraint for the mapping [default = %s]\n", Buffer );
+    Abc_Print( -2, "\t-W num   : min frequency when printing functions with \"-w\" [default = %d]\n", pPars->nVerbLimit );
+    Abc_Print( -2, "\t-a       : toggles area-oriented mapping [default = %s]\n", pPars->fAreaOnly? "yes": "no" );
+    Abc_Print( -2, "\t-e       : toggles edge vs node minimization [default = %s]\n", pPars->fOptEdge? "yes": "no" );
+    Abc_Print( -2, "\t-k       : toggles coarsening the subject graph [default = %s]\n", pPars->fCoarsen? "yes": "no" );
+    Abc_Print( -2, "\t-m       : toggles cut minimization [default = %s]\n", pPars->fCutMin? "yes": "no" );
+    Abc_Print( -2, "\t-d       : toggles using DSD to represent cut functions [default = %s]\n", pPars->fFuncDsd? "yes": "no" );
+    Abc_Print( -2, "\t-c       : toggles mapping for CNF generation [default = %s]\n", pPars->fGenCnf? "yes": "no" );
+    Abc_Print( -2, "\t-g       : toggles generating AIG without mapping [default = %s]\n", pPars->fPureAig? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggles very verbose output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : prints the command usage\n");
+    return 1;
+}
+
+#ifdef ABC_USE_PTHREADS
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Kf( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Kf_ManSetDefaultPars( Jf_Par_t * pPars );
+    extern Gia_Man_t * Kf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars );
+    char Buffer[200];
+    Jf_Par_t Pars, * pPars = &Pars;
+    Gia_Man_t * pNew; int c;
+    Kf_ManSetDefaultPars( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "KCPDWaekmdcgtsvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLutSize < 2 || pPars->nLutSize > pPars->nLutSizeMax )
+            {
+                Abc_Print( -1, "LUT size %d is not supported.\n", pPars->nLutSize );
+                goto usage;
+            }
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nCutNum = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nCutNum < 1 || pPars->nCutNum > pPars->nCutNumMax )
+            {
+                Abc_Print( -1, "This number of cuts (%d) is not supported.\n", pPars->nCutNum );
+                goto usage;
+            }
+            break;
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nProcNum = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nProcNum < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->DelayTarget = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->DelayTarget <= 0.0 )
+                goto usage;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nVerbLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nVerbLimit < 0 )
+                goto usage;
+            break;
+        case 'a':
+            pPars->fAreaOnly ^= 1;
+            break;
+        case 'e':
+            pPars->fOptEdge ^= 1;
+            break;
+        case 'k':
+            pPars->fCoarsen ^= 1;
+            break;
+        case 'm':
+            pPars->fCutMin ^= 1;
+            break;
+        case 'd':
+            pPars->fFuncDsd ^= 1;
+            break;
+        case 'c':
+            pPars->fGenCnf ^= 1;
+            break;
+        case 'g':
+            pPars->fPureAig ^= 1;
+            break;
+        case 't':
+            pPars->fCutHashing ^= 1;
+            break;
+        case 's':
+            pPars->fCutSimple ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Empty GIA network.\n" );
+        return 1;
+    }
+
+    pNew = Kf_ManPerformMapping( pAbc->pGia, pPars );
+    if ( pNew == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Kf(): Mapping into LUTs has failed.\n" );
+        return 1;
+    }
+    Abc_FrameUpdateGia( pAbc, pNew );
+    return 0;
+
+usage:
+    if ( pPars->DelayTarget == -1 )
+        sprintf(Buffer, "best possible" );
+    else
+        sprintf(Buffer, "%d", pPars->DelayTarget );
+    Abc_Print( -2, "usage: &kf [-KCPDW num] [-akmdcgtsvwh]\n" );
+    Abc_Print( -2, "\t           performs technology mapping of the network\n" );
+    Abc_Print( -2, "\t-K num   : LUT size for the mapping (2 <= K <= %d) [default = %d]\n", pPars->nLutSizeMax, pPars->nLutSize );
+    Abc_Print( -2, "\t-C num   : the max number of priority cuts (1 <= C <= %d) [default = %d]\n", pPars->nCutNumMax, pPars->nCutNum );
+    Abc_Print( -2, "\t-P num   : the number of cut computation processes (0 <= P <= %d) [default = %d]\n", pPars->nProcNumMax, pPars->nProcNum );
+    Abc_Print( -2, "\t-D num   : sets the delay constraint for the mapping [default = %s]\n", Buffer );
+    Abc_Print( -2, "\t-W num   : min frequency when printing functions with \"-w\" [default = %d]\n", pPars->nVerbLimit );
+    Abc_Print( -2, "\t-a       : toggles area-oriented mapping [default = %s]\n", pPars->fAreaOnly? "yes": "no" );
+    Abc_Print( -2, "\t-e       : toggles edge vs node minimization [default = %s]\n", pPars->fOptEdge? "yes": "no" );
+    Abc_Print( -2, "\t-k       : toggles coarsening the subject graph [default = %s]\n", pPars->fCoarsen? "yes": "no" );
+    Abc_Print( -2, "\t-m       : toggles cut minimization [default = %s]\n", pPars->fCutMin? "yes": "no" );
+    Abc_Print( -2, "\t-d       : toggles using DSD to represent cut functions [default = %s]\n", pPars->fFuncDsd? "yes": "no" );
+    Abc_Print( -2, "\t-c       : toggles mapping for CNF generation [default = %s]\n", pPars->fGenCnf? "yes": "no" );
+    Abc_Print( -2, "\t-g       : toggles generating AIG without mapping [default = %s]\n", pPars->fPureAig? "yes": "no" );
+    Abc_Print( -2, "\t-t       : toggles cut computation using hash table [default = %s]\n", pPars->fCutHashing? "yes": "no" );
+    Abc_Print( -2, "\t-s       : toggles cut computation using a simple method [default = %s]\n", pPars->fCutSimple? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggles very verbose output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : prints the command usage\n");
+    return 1;
+}
+#endif
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Lf( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char Buffer[200];
+    Jf_Par_t Pars, * pPars = &Pars;
+    Gia_Man_t * pNew; int c;
+    Lf_ManSetDefaultPars( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "KCFARLEDWaekmupgtvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLutSize < 2 || pPars->nLutSize > pPars->nLutSizeMax )
+            {
+                Abc_Print( -1, "LUT size %d is not supported.\n", pPars->nLutSize );
+                goto usage;
+            }
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nCutNum = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nCutNum < 1 || pPars->nCutNum > pPars->nCutNumMax )
+            {
+                Abc_Print( -1, "This number of cuts (%d) is not supported.\n", pPars->nCutNum );
+                goto usage;
+            }
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nRounds = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRounds < 0 )
+                goto usage;
+            break;
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nRoundsEla = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRoundsEla < 0 )
+                goto usage;
+            break;
+		case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" );
+                return 0;
+            }
+			pPars->nRelaxRatio = atoi(argv[globalUtilOptind]);
+			globalUtilOptind++;
+			if ( pPars->nRelaxRatio < 0 ) 
+				goto usage;
+            break;
+		case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" );
+                return 0;
+            }
+			pPars->nCoarseLimit = atoi(argv[globalUtilOptind]);
+			globalUtilOptind++;
+			if ( pPars->nCoarseLimit < 0 ) 
+				goto usage;
+            break;
+		case 'E':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( 1, "Command line switch \"-E\" should be followed by a floating point number.\n" );
+                return 0;
+            }
+			pPars->nAreaTuner = atoi(argv[globalUtilOptind]);
+			globalUtilOptind++;
+			if ( pPars->nAreaTuner < 0 ) 
+				goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->DelayTarget = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->DelayTarget <= 0.0 )
+                goto usage;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nVerbLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nVerbLimit < 0 )
+                goto usage;
+            break;
+        case 'a':
+            pPars->fAreaOnly ^= 1;
+            break;
+        case 'e':
+            pPars->fOptEdge ^= 1;
+            break;
+        case 'k':
+            pPars->fCoarsen ^= 1;
+            break;
+        case 'm':
+            pPars->fCutMin ^= 1;
+            break;
+        case 'u':
+            pPars->fUseMux7 ^= 1;
+            break;
+        case 'p':
+            pPars->fPower ^= 1;
+            break;
+        case 'g':
+            pPars->fPureAig ^= 1;
+            break;
+        case 't':
+            pPars->fDoAverage ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Empty GIA network.\n" );
+        return 1;
+    }
+
+    pNew = Lf_ManPerformMapping( pAbc->pGia, pPars );
+    if ( pNew == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Lf(): Mapping into LUTs has failed.\n" );
+        return 1;
+    }
+    Abc_FrameUpdateGia( pAbc, pNew );
+    return 0;
+
+usage:
+    if ( pPars->DelayTarget == -1 )
+        sprintf(Buffer, "best possible" );
+    else
+        sprintf(Buffer, "%d", pPars->DelayTarget );
+    Abc_Print( -2, "usage: &lf [-KCFARLED num] [-kmupgtvwh]\n" );
+    Abc_Print( -2, "\t           performs technology mapping of the network\n" );
+    Abc_Print( -2, "\t-K num   : LUT size for the mapping (2 <= K <= %d) [default = %d]\n", pPars->nLutSizeMax, pPars->nLutSize );
+    Abc_Print( -2, "\t-C num   : the max number of priority cuts (1 <= C <= %d) [default = %d]\n", pPars->nCutNumMax, pPars->nCutNum );
+    Abc_Print( -2, "\t-F num   : the number of area flow rounds [default = %d]\n", pPars->nRounds );
+    Abc_Print( -2, "\t-A num   : the number of exact area rounds [default = %d]\n", pPars->nRoundsEla );
+    Abc_Print( -2, "\t-R num   : the delay relaxation ratio (num >= 0) [default = %d]\n", pPars->nRelaxRatio );
+    Abc_Print( -2, "\t-L num   : the fanout limit for coarsening XOR/MUX (num >= 2) [default = %d]\n", pPars->nCoarseLimit );
+    Abc_Print( -2, "\t-E num   : the area/edge tradeoff parameter (0 <= num <= 100) [default = %d]\n", pPars->nAreaTuner );
+    Abc_Print( -2, "\t-D num   : sets the delay constraint for the mapping [default = %s]\n", Buffer );
+//    Abc_Print( -2, "\t-a       : toggles area-oriented mapping [default = %s]\n", pPars->fAreaOnly? "yes": "no" );
+    Abc_Print( -2, "\t-e       : toggles edge vs node minimization [default = %s]\n", pPars->fOptEdge? "yes": "no" );
+    Abc_Print( -2, "\t-k       : toggles coarsening the subject graph [default = %s]\n", pPars->fCoarsen? "yes": "no" );
+    Abc_Print( -2, "\t-m       : toggles cut minimization [default = %s]\n", pPars->fCutMin? "yes": "no" );
+    Abc_Print( -2, "\t-u       : toggles using additional MUXes [default = %s]\n", pPars->fUseMux7? "yes": "no" );
+    Abc_Print( -2, "\t-p       : toggles power-aware cut selection heuristics [default = %s]\n", pPars->fPower? "yes": "no" );
+    Abc_Print( -2, "\t-g       : toggles generating AIG without mapping [default = %s]\n", pPars->fPureAig? "yes": "no" );
+    Abc_Print( -2, "\t-t       : toggles optimizing average rather than maximum level [default = %s]\n", pPars->fDoAverage? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggles very verbose output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : prints the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Mf( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char Buffer[200];
+    Jf_Par_t Pars, * pPars = &Pars;
+    Gia_Man_t * pNew; int c;
+    Mf_ManSetDefaultPars( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "KCFARLEDWaekmcgvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLutSize < 2 || pPars->nLutSize > pPars->nLutSizeMax )
+            {
+                Abc_Print( -1, "LUT size %d is not supported.\n", pPars->nLutSize );
+                goto usage;
+            }
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nCutNum = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nCutNum < 1 || pPars->nCutNum > pPars->nCutNumMax )
+            {
+                Abc_Print( -1, "This number of cuts (%d) is not supported.\n", pPars->nCutNum );
+                goto usage;
+            }
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nRounds = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRounds < 0 )
+                goto usage;
+            break;
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nRoundsEla = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRoundsEla < 0 )
+                goto usage;
+            break;
+		case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" );
+                return 0;
+            }
+			pPars->nRelaxRatio = atoi(argv[globalUtilOptind]);
+			globalUtilOptind++;
+			if ( pPars->nRelaxRatio < 0 ) 
+				goto usage;
+            break;
+		case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" );
+                return 0;
+            }
+			pPars->nCoarseLimit = atoi(argv[globalUtilOptind]);
+			globalUtilOptind++;
+			if ( pPars->nCoarseLimit < 0 ) 
+				goto usage;
+            break;
+		case 'E':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( 1, "Command line switch \"-E\" should be followed by a floating point number.\n" );
+                return 0;
+            }
+			pPars->nAreaTuner = atoi(argv[globalUtilOptind]);
+			globalUtilOptind++;
+			if ( pPars->nAreaTuner < 0 ) 
+				goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->DelayTarget = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->DelayTarget <= 0.0 )
+                goto usage;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nVerbLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nVerbLimit < 0 )
+                goto usage;
+            break;
+        case 'a':
+            pPars->fAreaOnly ^= 1;
+            break;
+        case 'e':
+            pPars->fOptEdge ^= 1;
+            break;
+        case 'k':
+            pPars->fCoarsen ^= 1;
+            break;
+        case 'm':
+            pPars->fCutMin ^= 1;
+            break;
+        case 'c':
+            pPars->fGenCnf ^= 1;
+            break;
+        case 'g':
+            pPars->fPureAig ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Empty GIA network.\n" );
+        return 1;
+    }
+
+    pNew = Mf_ManPerformMapping( pAbc->pGia, pPars );
+    if ( pNew == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Lf(): Mapping into LUTs has failed.\n" );
+        return 1;
+    }
+    if ( pPars->fGenCnf )
+        Cnf_DataFree( pAbc->pGia->pData ), pAbc->pGia->pData = NULL;
+    Abc_FrameUpdateGia( pAbc, pNew );
+    return 0;
+
+usage:
+    if ( pPars->DelayTarget == -1 )
+        sprintf(Buffer, "best possible" );
+    else
+        sprintf(Buffer, "%d", pPars->DelayTarget );
+    Abc_Print( -2, "usage: &mf [-KCFARLED num] [-akmcgvwh]\n" );
+    Abc_Print( -2, "\t           performs technology mapping of the network\n" );
+    Abc_Print( -2, "\t-K num   : LUT size for the mapping (2 <= K <= %d) [default = %d]\n", pPars->nLutSizeMax, pPars->nLutSize );
+    Abc_Print( -2, "\t-C num   : the max number of priority cuts (1 <= C <= %d) [default = %d]\n", pPars->nCutNumMax, pPars->nCutNum );
+    Abc_Print( -2, "\t-F num   : the number of area flow rounds [default = %d]\n", pPars->nRounds );
+    Abc_Print( -2, "\t-A num   : the number of exact area rounds [default = %d]\n", pPars->nRoundsEla );
+    Abc_Print( -2, "\t-R num   : the delay relaxation ratio (num >= 0) [default = %d]\n", pPars->nRelaxRatio );
+    Abc_Print( -2, "\t-L num   : the fanout limit for coarsening XOR/MUX (num >= 2) [default = %d]\n", pPars->nCoarseLimit );
+    Abc_Print( -2, "\t-E num   : the area/edge tradeoff parameter (0 <= num <= 100) [default = %d]\n", pPars->nAreaTuner );
+    Abc_Print( -2, "\t-D num   : sets the delay constraint for the mapping [default = %s]\n", Buffer );
+    Abc_Print( -2, "\t-a       : toggles area-oriented mapping [default = %s]\n", pPars->fAreaOnly? "yes": "no" );
+    Abc_Print( -2, "\t-e       : toggles edge vs node minimization [default = %s]\n", pPars->fOptEdge? "yes": "no" );
+    Abc_Print( -2, "\t-k       : toggles coarsening the subject graph [default = %s]\n", pPars->fCoarsen? "yes": "no" );
+    Abc_Print( -2, "\t-m       : toggles cut minimization [default = %s]\n", pPars->fCutMin? "yes": "no" );
+    Abc_Print( -2, "\t-c       : toggles mapping for CNF generation [default = %s]\n", pPars->fGenCnf? "yes": "no" );
+    Abc_Print( -2, "\t-g       : toggles generating AIG without mapping [default = %s]\n", pPars->fPureAig? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggles very verbose output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : prints the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Nf( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Nf_ManSetDefaultPars( Jf_Par_t * pPars );
+    extern Gia_Man_t * Nf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars );
+    char Buffer[200];
+    Jf_Par_t Pars, * pPars = &Pars;
+    Gia_Man_t * pNew; int c;
+    Nf_ManSetDefaultPars( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "KCFARLEDWakvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'K':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nLutSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLutSize < 2 || pPars->nLutSize > pPars->nLutSizeMax )
+            {
+                Abc_Print( -1, "LUT size %d is not supported.\n", pPars->nLutSize );
+                goto usage;
+            }
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nCutNum = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nCutNum < 1 || pPars->nCutNum > pPars->nCutNumMax )
+            {
+                Abc_Print( -1, "This number of cuts (%d) is not supported.\n", pPars->nCutNum );
+                goto usage;
+            }
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nRounds = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRounds < 0 )
+                goto usage;
+            break;
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nRoundsEla = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRoundsEla < 0 )
+                goto usage;
+            break;
+		case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" );
+                return 0;
+            }
+			pPars->nRelaxRatio = atoi(argv[globalUtilOptind]);
+			globalUtilOptind++;
+			if ( pPars->nRelaxRatio < 0 ) 
+				goto usage;
+            break;
+		case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" );
+                return 0;
+            }
+			pPars->nCoarseLimit = atoi(argv[globalUtilOptind]);
+			globalUtilOptind++;
+			if ( pPars->nCoarseLimit < 0 ) 
+				goto usage;
+            break;
+		case 'E':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( 1, "Command line switch \"-E\" should be followed by a floating point number.\n" );
+                return 0;
+            }
+			pPars->nAreaTuner = atoi(argv[globalUtilOptind]);
+			globalUtilOptind++;
+			if ( pPars->nAreaTuner < 0 ) 
+				goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            pPars->DelayTarget = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->DelayTarget <= 0.0 )
+                goto usage;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nVerbLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nVerbLimit < 0 )
+                goto usage;
+            break;
+        case 'a':
+            pPars->fAreaOnly ^= 1;
+            break;
+        case 'k':
+            pPars->fCoarsen ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Empty GIA network.\n" );
+        return 1;
+    }
+    if ( Abc_FrameReadLibGen() == NULL )
+    {
+        Abc_Print( -1, "Current library is not available.\n" );
+        return 1;
+    }
+    pNew = Nf_ManPerformMapping( pAbc->pGia, pPars );
+    if ( pNew == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Nf(): Mapping into LUTs has failed.\n" );
+        return 1;
+    }
+    Abc_FrameUpdateGia( pAbc, pNew );
+    return 0;
+
+usage:
+    if ( pPars->DelayTarget == -1 )
+        sprintf(Buffer, "best possible" );
+    else
+        sprintf(Buffer, "%d", pPars->DelayTarget );
+    Abc_Print( -2, "usage: &nf [-KCFARLED num] [-akvwh]\n" );
+    Abc_Print( -2, "\t           performs technology mapping of the network\n" );
+    Abc_Print( -2, "\t-K num   : LUT size for the mapping (2 <= K <= %d) [default = %d]\n", pPars->nLutSizeMax, pPars->nLutSize );
+    Abc_Print( -2, "\t-C num   : the max number of priority cuts (1 <= C <= %d) [default = %d]\n", pPars->nCutNumMax, pPars->nCutNum );
+    Abc_Print( -2, "\t-F num   : the number of area flow rounds [default = %d]\n", pPars->nRounds );
+    Abc_Print( -2, "\t-A num   : the number of exact area rounds [default = %d]\n", pPars->nRoundsEla );
+    Abc_Print( -2, "\t-R num   : the delay relaxation ratio (num >= 0) [default = %d]\n", pPars->nRelaxRatio );
+    Abc_Print( -2, "\t-L num   : the fanout limit for coarsening XOR/MUX (num >= 2) [default = %d]\n", pPars->nCoarseLimit );
+    Abc_Print( -2, "\t-E num   : the area/edge tradeoff parameter (0 <= num <= 100) [default = %d]\n", pPars->nAreaTuner );
+    Abc_Print( -2, "\t-D num   : sets the delay constraint for the mapping [default = %s]\n", Buffer );
+    Abc_Print( -2, "\t-a       : toggles area-oriented mapping [default = %s]\n", pPars->fAreaOnly? "yes": "no" );
+    Abc_Print( -2, "\t-k       : toggles coarsening the subject graph [default = %s]\n", pPars->fCoarsen? "yes": "no" );
+    Abc_Print( -2, "\t-v       : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggles very verbose output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : prints the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Struct( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Gia_ManTestStruct( Gia_Man_t * p );
+    int c, fVerbose;
+    // set defaults
+    fVerbose   = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Struct(): There is no AIG to map.\n" );
+        return 1;
+    }
+    if ( !Gia_ManHasMapping(pAbc->pGia) )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Struct(): Mapping of the AIG is not defined.\n" );
+        return 1;
+    }
+    if ( Gia_ManLutSizeMax(pAbc->pGia) >= 8 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Struct(): Can only handle nodes with less than 8 inputs.\n" );
+        return 1;
+    }
+    Gia_ManTestStruct( pAbc->pGia );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &struct [-vh]\n" );
+    Abc_Print( -2, "\t           checks decomposition structures of the current mapping\n" );
+    Abc_Print( -2, "\t-v       : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Trace( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c;
+    int fUseLutLib;
+    int fVerbose;
+    // set defaults
+    fUseLutLib = 0;
+    fVerbose   = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "lvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'l':
+            fUseLutLib ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Speedup(): There is no AIG to map.\n" );
+        return 1;
+    }
+    if ( !Gia_ManHasMapping(pAbc->pGia) )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Speedup(): Mapping of the AIG is not defined.\n" );
+        return 1;
+    }
+    pAbc->pGia->pLutLib = fUseLutLib ? pAbc->pLibLut : NULL;
+    Gia_ManDelayTraceLutPrint( pAbc->pGia, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &trace [-lvh]\n" );
+    Abc_Print( -2, "\t           performs delay trace of LUT-mapped network\n" );
+    Abc_Print( -2, "\t-l       : toggle using unit- or LUT-library-delay model [default = %s]\n", fUseLutLib? "lib": "unit" );
+    Abc_Print( -2, "\t-v       : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Speedup( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int fUseLutLib;
+    int Percentage;
+    int Degree;
+    int fVerbose;
+    int c, fVeryVerbose;
+
+    // set defaults
+    fUseLutLib   = 0;
+    Percentage   = 5;
+    Degree       = 2;
+    fVerbose     = 0;
+    fVeryVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "PNlvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            Percentage = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Percentage < 1 || Percentage > 100 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            Degree = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Degree < 1 || Degree > 5 )
+                goto usage;
+            break;
+        case 'l':
+            fUseLutLib ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Speedup(): There is no AIG to map.\n" );
+        return 1;
+    }
+    if ( !Gia_ManHasMapping(pAbc->pGia) )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Speedup(): Mapping of the AIG is not defined.\n" );
+        return 1;
+    }
+    pAbc->pGia->pLutLib = fUseLutLib ? pAbc->pLibLut : NULL;
+    pTemp = Gia_ManSpeedup( pAbc->pGia, Percentage, Degree, fVerbose, fVeryVerbose );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &speedup [-P num] [-N num] [-lvwh]\n" );
+    Abc_Print( -2, "\t           transforms LUT-mapped network into an AIG with choices;\n" );
+    Abc_Print( -2, "\t           the choices are added to speedup the next round of mapping\n" );
+    Abc_Print( -2, "\t-P <num> : delay delta defining critical path for library model [default = %d%%]\n", Percentage );
+    Abc_Print( -2, "\t-N <num> : the max critical path degree for resynthesis (0 < num < 6) [default = %d]\n", Degree );
+    Abc_Print( -2, "\t-l       : toggle using unit- or LUT-library-delay model [default = %s]\n", fUseLutLib? "lib" : "unit" );
+    Abc_Print( -2, "\t-v       : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w       : toggle printing detailed stats for each node [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Era( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+//    Gia_Man_t * pTemp = NULL;
+    int c, fVerbose = 0;
+    int fUseCubes = 1;
+    int fDumpFile = 0;
+    int fMiter = 0;
+    int nStatesMax = 1000000000;
+    extern int Gia_ManCollectReachable( Gia_Man_t * pAig, int nStatesMax, int fMiter, int fDumpFile, int fVerbose );
+    extern int Gia_ManArePerform( Gia_Man_t * pAig, int nStatesMax, int fMiter, int fVerbose );
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Smcdvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nStatesMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nStatesMax < 0 )
+                goto usage;
+            break;
+        case 'm':
+            fMiter ^= 1;
+            break;
+        case 'c':
+            fUseCubes ^= 1;
+            break;
+        case 'd':
+            fDumpFile ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Era(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Era(): The network is combinational.\n" );
+        return 1;
+    }
+    if ( !fUseCubes && Gia_ManPiNum(pAbc->pGia) > 12 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Era(): The number of PIs (%d) should be no more than 12 when cubes are not used.\n", Gia_ManPiNum(pAbc->pGia) );
+        return 1;
+    }
+    if ( fUseCubes && !fDumpFile )
+        pAbc->Status = Gia_ManArePerform( pAbc->pGia, nStatesMax, fMiter, fVerbose );
+    else
+        pAbc->Status = Gia_ManCollectReachable( pAbc->pGia, nStatesMax, fMiter, fDumpFile, fVerbose );
+    Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &era [-S num] [-mcdvh]\n" );
+    Abc_Print( -2, "\t          explicit reachability analysis for small sequential AIGs\n" );
+    Abc_Print( -2, "\t-S num  : the max number of states (num > 0) [default = %d]\n", nStatesMax );
+    Abc_Print( -2, "\t-m      : stop when the miter output is 1 [default = %s]\n", fMiter? "yes": "no" );
+    Abc_Print( -2, "\t-c      : use state cubes instead of state minterms [default = %s]\n", fUseCubes? "yes": "no" );
+    Abc_Print( -2, "\t-d      : toggle dumping STG into a file [default = %s]\n", fDumpFile? "yes": "no" );
+    Abc_Print( -2, "\t-v      : print verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h      : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    Dch_Pars_t Pars, * pPars = &Pars;
+    int c;
+    // set defaults
+    Dch_ManSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptfvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nWords < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBTLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBTLimit < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nSatVarMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nSatVarMax < 0 )
+                goto usage;
+            break;
+        case 's':
+            pPars->fSynthesis ^= 1;
+            break;
+        case 'p':
+            pPars->fPower ^= 1;
+            break;
+        case 't':
+            pPars->fSimulateTfo ^= 1;
+            break;
+        case 'f':
+            pPars->fLightSynth ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Dch(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManPerformDch( pAbc->pGia, pPars );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &dch [-WCS num] [-sptfvh]\n" );
+    Abc_Print( -2, "\t         computes structural choices using a new approach\n" );
+    Abc_Print( -2, "\t-W num : the max number of simulation words [default = %d]\n", pPars->nWords );
+    Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit );
+    Abc_Print( -2, "\t-S num : the max number of SAT variables [default = %d]\n", pPars->nSatVarMax );
+    Abc_Print( -2, "\t-s     : toggle synthesizing three snapshots [default = %s]\n", pPars->fSynthesis? "yes": "no" );
+    Abc_Print( -2, "\t-p     : toggle power-aware rewriting [default = %s]\n", pPars->fPower? "yes": "no" );
+    Abc_Print( -2, "\t-t     : toggle simulation of the TFO classes [default = %s]\n", pPars->fSimulateTfo? "yes": "no" );
+    Abc_Print( -2, "\t-f     : toggle using lighter logic synthesis [default = %s]\n", pPars->fLightSynth? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Rpm( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c, nCutMax   = 16;
+    int fUseOldAlgo  =  0;
+    int fVerbose     =  0;
+    int fVeryVerbose =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Cavwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nCutMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nCutMax < 0 )
+                goto usage;
+            break;
+        case 'a':
+            fUseOldAlgo ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Rpm(): There is no AIG.\n" );
+        return 0;
+    }
+    if ( fUseOldAlgo )
+        pTemp = Abs_RpmPerformOld( pAbc->pGia, fVerbose );
+    else
+        pTemp = Abs_RpmPerform( pAbc->pGia, nCutMax, fVerbose, fVeryVerbose );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &rpm [-C num] [-avwh]\n" );
+    Abc_Print( -2, "\t         performs structural reparametrization\n" );
+    Abc_Print( -2, "\t-C num : max cut size for testing range equivalence [default = %d]\n", nCutMax );
+    Abc_Print( -2, "\t-a     : toggle using old algorithm [default = %s]\n", fUseOldAlgo? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle printing more verbose information [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9BackReach( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Gia_Man_t * Gia_ManCofTest( Gia_Man_t * pGia, int nFrameMax, int nConfMax, int nTimeMax, int fVerbose );
+
+    Gia_Man_t * pTemp = NULL;
+    int c, fVerbose = 0;
+    int nFrameMax = 1000000;
+    int nConfMax  = 1000000;
+    int nTimeMax  =      10;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FCTvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrameMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrameMax < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfMax < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nTimeMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nTimeMax < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9BackReach(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManPoNum(pAbc->pGia) != 1 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9BackReach(): The number of POs is different from 1.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManCofTest( pAbc->pGia, nFrameMax, nConfMax, nTimeMax, fVerbose );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &back_reach [-FCT <num>] [-vh]\n" );
+    Abc_Print( -2, "\t         performs backward reachability by circuit cofactoring\n" );
+    Abc_Print( -2, "\t-F num : the limit on the depth of induction [default = %d]\n", nFrameMax );
+    Abc_Print( -2, "\t-C num : the conflict limit at a node during induction [default = %d]\n", nConfMax );
+    Abc_Print( -2, "\t-T num : the timeout for property directed reachability [default = %d]\n", nTimeMax );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Posplit( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Aig_Man_t * Aig_ManSplit( Aig_Man_t * p, int nVars, int fVerbose );
+    Aig_Man_t * pMan, * pAux;
+    Gia_Man_t * pTemp = NULL;
+    int c, nVars = 5, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Nvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nVars = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nVars < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Posplit(): There is no AIG.\n" );
+        return 1;
+    }
+    pMan = Gia_ManToAigSimple( pAbc->pGia );
+    pMan = Aig_ManSplit( pAux = pMan, nVars, fVerbose );
+    Aig_ManStop( pAux );
+    if ( pMan != NULL )
+    {
+        pTemp = Gia_ManFromAigSimple( pMan );
+        Aig_ManStop( pMan );
+        Abc_FrameUpdateGia( pAbc, pTemp );
+    }
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &posplit [-N num] [-vh]\n" );
+    Abc_Print( -2, "\t         cofactors the property output w.r.t. a support subset\n" );
+    Abc_Print( -2, "\t         (the OR of new PO functions is equal to the original property)\n" );
+    Abc_Print( -2, "\t-N num : the number of random cofactoring variables [default = %d]\n", nVars );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9ReachM( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+//    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Gia_ParLlb_t Pars, * pPars = &Pars;
+    char * pLogFileName = NULL;
+    int c;
+    extern int Llb_ManModelCheckGia( Gia_Man_t * pGia, Gia_ParLlb_t * pPars );
+
+    // set defaults
+    Llb_ManSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "TBFCHSLripcsyzvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeLimit < 0 )
+                goto usage;
+            break;
+        case 'B':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBddMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBddMax < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nIterMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nIterMax < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nClusterMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nClusterMax < 0 )
+                goto usage;
+            break;
+        case 'H':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-H\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nHintDepth = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nHintDepth < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->HintFirst = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->HintFirst < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pLogFileName = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'r':
+            pPars->fReorder ^= 1;
+            break;
+        case 'i':
+            pPars->fIndConstr ^= 1;
+            break;
+        case 'p':
+            pPars->fUsePivots ^= 1;
+            break;
+        case 'c':
+            pPars->fCluster ^= 1;
+            break;
+        case 's':
+            pPars->fSchedule ^= 1;
+            break;
+        case 'y':
+            pPars->fSkipOutCheck ^= 1;
+            break;
+        case 'z':
+            pPars->fSkipReach ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9ReachM(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9ReachM(): The current AIG has no latches.\n" );
+        return 0;
+    }
+    if ( Gia_ManObjNum(pAbc->pGia) >= (1<<16) )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9ReachM(): Currently cannot handle AIGs with more than %d objects.\n", (1<<16) );
+        return 0;
+    }
+    pAbc->Status  = Llb_ManModelCheckGia( pAbc->pGia, pPars );
+    pAbc->nFrames = pPars->iFrame;
+    Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq );
+    if ( pLogFileName )
+        Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "&reachm" );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &reachm [-TBFCHS num] [-L file] [-ripcsyzvwh]\n" );
+    Abc_Print( -2, "\t         model checking via BDD-based reachability (dependence-matrix-based)\n" );
+    Abc_Print( -2, "\t-T num : approximate time limit in seconds (0=infinite) [default = %d]\n", pPars->TimeLimit );
+    Abc_Print( -2, "\t-B num : max number of nodes in the intermediate BDDs [default = %d]\n", pPars->nBddMax );
+    Abc_Print( -2, "\t-F num : max number of reachability iterations [default = %d]\n", pPars->nIterMax );
+    Abc_Print( -2, "\t-C num : max number of variables in a cluster [default = %d]\n", pPars->nClusterMax );
+    Abc_Print( -2, "\t-H num : max number of hints to use [default = %d]\n", pPars->nHintDepth );
+    Abc_Print( -2, "\t-S num : the number of the starting hint [default = %d]\n", pPars->HintFirst );
+    Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" );
+    Abc_Print( -2, "\t-r     : enable dynamic BDD variable reordering [default = %s]\n", pPars->fReorder? "yes": "no" );
+    Abc_Print( -2, "\t-i     : enable extraction of inductive constraints [default = %s]\n", pPars->fIndConstr? "yes": "no" );
+    Abc_Print( -2, "\t-p     : enable partitions for internal cut-points [default = %s]\n", pPars->fUsePivots? "yes": "no" );
+    Abc_Print( -2, "\t-c     : enable clustering of partitions [default = %s]\n", pPars->fCluster? "yes": "no" );
+    Abc_Print( -2, "\t-s     : enable scheduling of clusters [default = %s]\n", pPars->fSchedule? "yes": "no" );
+    Abc_Print( -2, "\t-y     : skip checking property outputs [default = %s]\n", pPars->fSkipOutCheck? "yes": "no" );
+    Abc_Print( -2, "\t-z     : skip reachability (run preparation phase only) [default = %s]\n", pPars->fSkipReach? "yes": "no" );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : prints dependency matrix [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9ReachP( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+//    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Gia_ParLlb_t Pars, * pPars = &Pars;
+    Aig_Man_t * pMan;
+    char * pLogFileName = NULL;
+    int c;
+    extern int Llb_ManReachMinCut( Aig_Man_t * pAig, Gia_ParLlb_t * pPars );
+
+    // set defaults
+    Llb_ManSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "NBFTLrbyzdvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nPartValue = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nPartValue < 0 )
+                goto usage;
+            break;
+        case 'B':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBddMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBddMax < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nIterMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nIterMax < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeLimit < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pLogFileName = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'r':
+            pPars->fReorder ^= 1;
+            break;
+        case 'b':
+            pPars->fBackward ^= 1;
+            break;
+        case 'y':
+            pPars->fSkipOutCheck ^= 1;
+            break;
+        case 'z':
+            pPars->fSkipReach ^= 1;
+            break;
+        case 'd':
+            pPars->fDumpReached ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9ReachP(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9ReachP(): The current AIG has no latches.\n" );
+        return 0;
+    }
+    if ( Gia_ManObjNum(pAbc->pGia) >= (1<<16) )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9ReachP(): Currently cannot handle AIGs with more than %d objects.\n", (1<<16) );
+        return 0;
+    }
+    pMan          = Gia_ManToAigSimple( pAbc->pGia );
+    pAbc->Status  = Llb_ManReachMinCut( pMan, pPars );
+    pAbc->nFrames = pPars->iFrame;
+    Abc_FrameReplaceCex( pAbc, &pMan->pSeqModel );
+    if ( pLogFileName )
+        Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "&reachp" );
+    Aig_ManStop( pMan );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &reachp [-NFT num] [-L file] [-rbyzdvwh]\n" );
+    Abc_Print( -2, "\t         model checking via BDD-based reachability (partitioning-based)\n" );
+    Abc_Print( -2, "\t-N num : partitioning value (MinVol=nANDs/N/2; MaxVol=nANDs/N) [default = %d]\n", pPars->nPartValue );
+//    Abc_Print( -2, "\t-B num : the BDD node increase when hints kick in [default = %d]\n", pPars->nBddMax );
+    Abc_Print( -2, "\t-F num : max number of reachability iterations [default = %d]\n", pPars->nIterMax );
+    Abc_Print( -2, "\t-T num : approximate time limit in seconds (0=infinite) [default = %d]\n", pPars->TimeLimit );
+    Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" );
+    Abc_Print( -2, "\t-r     : enable additional BDD var reordering before image [default = %s]\n", pPars->fReorder? "yes": "no" );
+    Abc_Print( -2, "\t-b     : perform backward reachability analysis [default = %s]\n", pPars->fBackward? "yes": "no" );
+    Abc_Print( -2, "\t-y     : skip checking property outputs [default = %s]\n", pPars->fSkipOutCheck? "yes": "no" );
+    Abc_Print( -2, "\t-z     : skip reachability (run preparation phase only) [default = %s]\n", pPars->fSkipReach? "yes": "no" );
+    Abc_Print( -2, "\t-d     : dump BDD of reached states into file \"reached.blif\" [default = %s]\n", pPars->fDumpReached? "yes": "no" );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : prints additional information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9ReachN( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+//    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Gia_ParLlb_t Pars, * pPars = &Pars;
+    Aig_Man_t * pMan;
+    char * pLogFileName = NULL;
+    int c;
+    extern int Llb_NonlinCoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars );
+
+    // set defaults
+    Llb_ManSetDefaultParams( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "BFTLryzvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'B':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBddMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBddMax < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nIterMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nIterMax < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeLimit < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pLogFileName = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'r':
+            pPars->fReorder ^= 1;
+            break;
+        case 'y':
+            pPars->fSkipOutCheck ^= 1;
+            break;
+        case 'z':
+            pPars->fSkipReach ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9ReachN(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9ReachN(): The current AIG has no latches.\n" );
+        return 0;
+    }
+    if ( Gia_ManObjNum(pAbc->pGia) >= (1<<16) )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9ReachN(): Currently cannot handle AIGs with more than %d objects.\n", (1<<16) );
+        return 0;
+    }
+    pMan          = Gia_ManToAigSimple( pAbc->pGia );
+    pAbc->Status  = Llb_NonlinCoreReach( pMan, pPars );
+    pAbc->nFrames = pPars->iFrame;
+    Abc_FrameReplaceCex( pAbc, &pMan->pSeqModel );
+    if ( pLogFileName )
+        Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "&reachn" );
+    Aig_ManStop( pMan );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &reachn [-BFT num] [-L file] [-ryzvh]\n" );
+    Abc_Print( -2, "\t         model checking via BDD-based reachability (non-linear-QS-based)\n" );
+    Abc_Print( -2, "\t-B num : the BDD node increase when hints kick in [default = %d]\n", pPars->nBddMax );
+    Abc_Print( -2, "\t-F num : max number of reachability iterations [default = %d]\n", pPars->nIterMax );
+    Abc_Print( -2, "\t-T num : approximate time limit in seconds (0=infinite) [default = %d]\n", pPars->TimeLimit );
+    Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" );
+    Abc_Print( -2, "\t-r     : enable additional BDD var reordering before image [default = %s]\n", pPars->fReorder? "yes": "no" );
+    Abc_Print( -2, "\t-y     : skip checking property outputs [default = %s]\n", pPars->fSkipOutCheck? "yes": "no" );
+    Abc_Print( -2, "\t-z     : skip reachability (run preparation phase only) [default = %s]\n", pPars->fSkipReach? "yes": "no" );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+//    Abc_Print( -2, "\t-w     : prints additional information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9ReachY( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+//    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Gia_ParLlb_t Pars, * pPars = &Pars;
+    Aig_Man_t * pMan;
+    char * pLogFileName = NULL;
+    int c;
+
+    // set defaults
+    Llb_ManSetDefaultParams( pPars );
+    pPars->fCluster = 0;
+    pPars->fReorder = 0;
+    pPars->nBddMax     = 100;
+    pPars->nClusterMax = 500;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "BCFTLbcryzvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'B':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nBddMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nBddMax < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nClusterMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nClusterMax < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nIterMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nIterMax < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeLimit < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pLogFileName = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'b':
+            pPars->fBackward ^= 1;
+            break;
+        case 'c':
+            pPars->fCluster ^= 1;
+            break;
+        case 'r':
+            pPars->fReorder ^= 1;
+            break;
+        case 'y':
+            pPars->fSkipOutCheck ^= 1;
+            break;
+        case 'z':
+            pPars->fSkipReach ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9ReachN(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9ReachN(): The current AIG has no latches.\n" );
+        return 0;
+    }
+/*
+    if ( Gia_ManObjNum(pAbc->pGia) >= (1<<16) )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9ReachN(): Currently cannot handle AIGs with more than %d objects.\n", (1<<16) );
+        return 0;
+    }
+*/
+    pMan          = Gia_ManToAigSimple( pAbc->pGia );
+    pAbc->Status  = Llb_Nonlin4CoreReach( pMan, pPars );
+    pAbc->nFrames = pPars->iFrame;
+    Abc_FrameReplaceCex( pAbc, &pMan->pSeqModel );
+    if ( pLogFileName )
+        Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "&reachy" );
+    Aig_ManStop( pMan );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &reachy [-BCFT num] [-L file] [-bcryzvh]\n" );
+    Abc_Print( -2, "\t         model checking via BDD-based reachability (non-linear-QS-based)\n" );
+    Abc_Print( -2, "\t-B num : the max BDD size to introduce cut points [default = %d]\n", pPars->nBddMax );
+    Abc_Print( -2, "\t-C num : the max BDD size to reparameterize/cluster [default = %d]\n", pPars->nClusterMax );
+    Abc_Print( -2, "\t-F num : max number of reachability iterations [default = %d]\n", pPars->nIterMax );
+    Abc_Print( -2, "\t-T num : approximate time limit in seconds (0=infinite) [default = %d]\n", pPars->TimeLimit );
+    Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" );
+    Abc_Print( -2, "\t-b     : enable using backward enumeration [default = %s]\n", pPars->fBackward? "yes": "no" );
+    Abc_Print( -2, "\t-c     : enable reparametrization clustering [default = %s]\n", pPars->fCluster? "yes": "no" );
+    Abc_Print( -2, "\t-r     : enable additional BDD var reordering before image [default = %s]\n", pPars->fReorder? "yes": "no" );
+    Abc_Print( -2, "\t-y     : skip checking property outputs [default = %s]\n", pPars->fSkipOutCheck? "yes": "no" );
+    Abc_Print( -2, "\t-z     : skip reachability (run preparation phase only) [default = %s]\n", pPars->fSkipReach? "yes": "no" );
+    Abc_Print( -2, "\t-v     : prints verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+//    Abc_Print( -2, "\t-w     : prints additional information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Undo( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c;
+    // set defaults
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Undo(): There is no design.\n" );
+        return 1;
+    }
+    if ( pAbc->pGia2 == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Undo(): There is no previously saved network.\n" );
+        return 1;
+    }
+    Gia_ManStop( pAbc->pGia );
+    pAbc->pGia = pAbc->pGia2;
+    pAbc->pGia2 = NULL;
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &undo [-h]\n" );
+    Abc_Print( -2, "\t        reverses the previous AIG transformation\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Iso( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pAig;
+    Vec_Ptr_t * vPosEquivs;
+//    Vec_Ptr_t * vPiPerms;
+    int c, fNewAlgo = 1, fEstimate = 0, fBetterQual = 0, fDualOut = 0, fVerbose = 0, fVeryVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "neqdvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'n':
+            fNewAlgo ^= 1;
+            break;
+        case 'e':
+            fEstimate ^= 1;
+            break;
+        case 'q':
+            fBetterQual ^= 1;
+            break;
+        case 'd':
+            fDualOut ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Iso(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManPoNum(pAbc->pGia) == 1 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Iso(): The AIG has only one PO. Isomorphism detection is not performed.\n" );
+        return 1;
+    }
+    if ( fNewAlgo )
+        pAig = Gia_ManIsoReduce2( pAbc->pGia, &vPosEquivs, NULL, fEstimate, fBetterQual, fDualOut, fVerbose, fVeryVerbose );
+    else
+        pAig = Gia_ManIsoReduce( pAbc->pGia, &vPosEquivs, NULL, fEstimate, fDualOut, fVerbose, fVeryVerbose );
+//    pAig = Gia_ManIsoReduce( pAbc->pGia, &vPosEquivs, &vPiPerms, 0, fDualOut, fVerbose, fVeryVerbose );
+//    Vec_VecFree( (Vec_Vec_t *)vPiPerms );
+    if ( pAig == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Iso(): Transformation has failed.\n" );
+        return 1;
+    }
+    // update the internal storage of PO equivalences
+    Abc_FrameReplacePoEquivs( pAbc, &vPosEquivs );
+    // update the AIG
+    Abc_FrameUpdateGia( pAbc, pAig );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &iso [-neqdvwh]\n" );
+    Abc_Print( -2, "\t         removes POs with isomorphic sequential COI\n" );
+    Abc_Print( -2, "\t-n     : toggle using new fast algorithm [default = %s]\n", fNewAlgo? "yes": "no" );
+    Abc_Print( -2, "\t-e     : toggle computing lower bound on equivalence classes [default = %s]\n", fEstimate? "yes": "no" );
+    Abc_Print( -2, "\t-q     : toggle improving quality at the expense of runtime [default = %s]\n", fBetterQual? "yes": "no" );
+    Abc_Print( -2, "\t-d     : toggle treating the current AIG as a dual-output miter [default = %s]\n", fDualOut? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle printing very verbose information [default = %s]\n", fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9CexInfo( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Bmc_CexTest( Gia_Man_t * p, Abc_Cex_t * pCex, int fVerbose );
+    int c, fDualOut = 0, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "dvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'd':
+            fDualOut ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9CexInfo(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( pAbc->pCex == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9CexInfo(): There is no CEX.\n" );
+        return 1;
+    }
+    Bmc_CexTest( pAbc->pGia, pAbc->pCex, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &cexinfo [-vh]\n" );
+    Abc_Print( -2, "\t         prints information about the current counter-example\n" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Cycle( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c, nFrames = 10, fUseCex = 0, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Fcvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'c':
+            fUseCex ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Cycle(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManDupCycled( pAbc->pGia, fUseCex ? pAbc->pCex : NULL, nFrames );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &cycle [-F num] [-cvh]\n" );
+    Abc_Print( -2, "\t         cycles sequential circuit for the given number of timeframes\n" );
+    Abc_Print( -2, "\t         to derive a new initial state (which may be on the envelope)\n" );
+    Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-c     : toggle using PI values from the current CEX [default = %s]\n", fUseCex? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Cone( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    Vec_Int_t * vPos;
+    int c, iOutNum = -1, nOutRange = 1, iPartNum = -1, fUseAllCis = 0, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ORPavh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'O':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iOutNum = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iOutNum < 0 )
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nOutRange = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nOutRange < 0 )
+                goto usage;
+            break;
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iPartNum = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iPartNum < 0 )
+                goto usage;
+            break;
+        case 'a':
+            fUseAllCis ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Cone(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( iPartNum >= 0 )
+    {
+        Vec_Int_t * vClass;
+        Vec_Vec_t * vClasses = (Vec_Vec_t *)pAbc->vPoEquivs;
+        if ( vClasses == NULL )
+        {
+            Abc_Print( -1, "Abc_CommandAbc9Cone(): Partitions are not defined.\n" );
+            return 1;
+        }
+        if ( iPartNum >= Vec_VecSize(vClasses) )
+        {
+            Abc_Print( -1, "Abc_CommandAbc9Cone(): Partition index exceed the array size.\n" );
+            return 1;
+        }
+        vClass = Vec_VecEntryInt( vClasses, iPartNum );
+        pTemp = Gia_ManDupCones( pAbc->pGia, Vec_IntArray(vClass), Vec_IntSize(vClass), !fUseAllCis );
+        if ( pTemp )
+            Abc_FrameUpdateGia( pAbc, pTemp );
+        return 0;
+    }
+    if ( iOutNum < 0 || iOutNum + nOutRange >= Gia_ManPoNum(pAbc->pGia) )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Cone(): Range of outputs to extract is incorrect.\n" );
+        return 1;
+    }
+    vPos = Vec_IntStartRange( iOutNum, nOutRange );
+    pTemp = Gia_ManDupCones( pAbc->pGia, Vec_IntArray(vPos), nOutRange, !fUseAllCis );
+    Vec_IntFree( vPos );
+    if ( pTemp )
+        Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &cone [-ORP num] [-avh]\n" );
+    Abc_Print( -2, "\t         extracting multi-output sequential logic cones\n" );
+    Abc_Print( -2, "\t-O num : the index of first PO to extract [default = %d]\n", iOutNum );
+    Abc_Print( -2, "\t-R num : (optional) the number of outputs to extract [default = %d]\n", nOutRange );
+    Abc_Print( -2, "\t-P num : (optional) the partition number to extract [default = %d]\n", iPartNum );
+    Abc_Print( -2, "\t-a     : toggle keeping all CIs or structral support only [default = %s]\n", fUseAllCis? "all": "structural" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Slice( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp;
+    int c, nSuppSize = 6, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Svh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nSuppSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nSuppSize < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Slice(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManDupSliced( pAbc->pGia, nSuppSize );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &slice [-S num] [-vh]\n" );
+    Abc_Print( -2, "\t         cuts the lower part of the AIG with nodes using their support\n" );
+    Abc_Print( -2, "\t-S num : the largest support size to keep in the slide [default = %d]\n", nSuppSize );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9PoPart( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Gia_Man_t * Gia_ManFindPoPartition( Gia_Man_t * p, int SelectShift, int fOnlyCis, int fSetLargest, int fVerbose, Vec_Ptr_t ** pvPosEquivs );
+    Gia_Man_t * pTemp;
+    Vec_Ptr_t * vPosEquivs = NULL;
+    int c, SelectShift = 0, fOnlyCis = 0, fSetLargest = 0, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Simvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            SelectShift = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( SelectShift < 0 )
+                goto usage;
+            break;
+        case 'i':
+            fOnlyCis ^= 1;
+            break;
+        case 'm':
+            fSetLargest ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9PoPart(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManFindPoPartition( pAbc->pGia, SelectShift, fOnlyCis, fSetLargest, fVerbose, &vPosEquivs );
+    if ( pTemp )
+        Abc_FrameUpdateGia( pAbc, pTemp );
+    Abc_FrameReplacePoEquivs( pAbc, &vPosEquivs );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &popart [-S num] [-imvh]\n" );
+    Abc_Print( -2, "\t         partitioning of POs into equivalence classes\n" );
+    Abc_Print( -2, "\t-S num : random seed to select the set of pivot nodes [default = %d]\n", SelectShift );
+    Abc_Print( -2, "\t       : (if the seed is 0, the nodes with max fanout counts are used)\n" );
+    Abc_Print( -2, "\t-i     : toggle allowing only CIs to be the pivots [default = %s]\n", fOnlyCis? "yes": "no" );
+    Abc_Print( -2, "\t-m     : toggle using the largest part as the current network [default = %s]\n", fSetLargest? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9PoPart2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Gia_Man_t * Gia_ManFindPoPartition2( Gia_Man_t * p, int iStartNum, int nDelta, int nOutsMin, int nOutsMax, int fSetLargest, int fVerbose, Vec_Ptr_t ** pvPosEquivs );
+    Gia_Man_t * pTemp = NULL;
+    Vec_Ptr_t * vPosEquivs = NULL;
+    int c, iStartNum = 0, nDelta = 10, nOutsMin = 100, nOutsMax = 1000, fSetLargest = 0, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "SDLUmvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iStartNum = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iStartNum < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nDelta = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nDelta < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nOutsMin = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nOutsMin < 0 )
+                goto usage;
+            break;
+        case 'U':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-U\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nOutsMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nOutsMax < 0 )
+                goto usage;
+            break;
+        case 'm':
+            fSetLargest ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9PoPart(): There is no AIG.\n" );
+        return 1;
+    }
+    pTemp = Gia_ManFindPoPartition2( pAbc->pGia, iStartNum, nDelta, nOutsMin, nOutsMax, fSetLargest, fVerbose, &vPosEquivs );
+    if ( pTemp )
+        Abc_FrameUpdateGia( pAbc, pTemp );
+    Abc_FrameReplacePoEquivs( pAbc, &vPosEquivs );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &popart2 [-SDLU num] [-mvh]\n" );
+    Abc_Print( -2, "\t         extracting multi-output sequential logic cones\n" );
+    Abc_Print( -2, "\t-S num : the index of the PO to start the cluster [default = %d]\n", iStartNum );
+    Abc_Print( -2, "\t-D num : the max increase in flop count after adding one PO [default = %d]\n", nDelta );
+    Abc_Print( -2, "\t-L num : the minimum number of POs in a cluster [default = %d]\n", nOutsMin );
+    Abc_Print( -2, "\t-U num : the maximum number of POs in a cluster [default = %d]\n", nOutsMax );
+    Abc_Print( -2, "\t-m     : toggle selecting the largest cluster [default = %s]\n", fSetLargest? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9GroupProve( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Vec_Int_t * Gia_ManGroupProve( Gia_Man_t * p, char * pCommLine, int nGroupSize, int fVerbose );
+    Vec_Int_t * vStatus;
+    char * pCommLine = NULL;
+    int c, nGroupSize = 1, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "GSvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nGroupSize = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nGroupSize <= 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pCommLine = argv[globalUtilOptind];
+            globalUtilOptind++;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9GroupProve(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( pCommLine == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9GroupProve(): Command line is not given.\n" );
+        return 1;
+    }
+    vStatus = Gia_ManGroupProve( pAbc->pGia, pCommLine, nGroupSize, fVerbose );
+    Vec_IntFree( vStatus );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &gprove [-GS num] [-vh]\n" );
+    Abc_Print( -2, "\t         proves multi-output testcase by splitting outputs into groups\n" );
+    Abc_Print( -2, "\t         (currently, group size more than one works only for \"bmc3\" and \"pdr\")\n" );
+    Abc_Print( -2, "\t-G num : the size of one group [default = %d]\n", nGroupSize );
+    Abc_Print( -2, "\t-S str : the command line to be executed for each group [default = %s]\n", pCommLine ? pCommLine : "none" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9MultiProve( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern int Gia_ManMultiProve( Gia_Man_t * p, Bmc_MulPar_t * pPars );
+    Vec_Int_t * vStatuses; int c;
+    Bmc_MulPar_t Pars, * pPars = &Pars;
+    memset( pPars, 0, sizeof(Bmc_MulPar_t) );
+    pPars->TimeOutGlo =  30;
+    pPars->TimeOutLoc =   2;
+    pPars->TimeOutInc = 100;
+    pPars->TimeOutGap =   0;
+    pPars->TimePerOut =   0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "TLMGHsdvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeOutGlo = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeOutGlo < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeOutLoc = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeOutLoc <= 0 )
+                goto usage;
+            break;
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeOutInc = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeOutInc <= 0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimeOutGap = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeOutGap <= 0 )
+                goto usage;
+            break;
+        case 'H':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-H\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->TimePerOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimePerOut <= 0 )
+                goto usage;
+            break;
+        case 's':
+            pPars->fUseSyn ^= 1;
+            break;
+        case 'd':
+            pPars->fDumpFinal ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9MultiProve(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9MultiProve(): The problem is combinational.\n" );
+        return 1;
+    }
+    pAbc->Status = Gia_ManMultiProve( pAbc->pGia, pPars );
+    vStatuses = Abc_FrameDeriveStatusArray( pAbc->pGia->vSeqModelVec );
+    Abc_FrameReplacePoStatuses( pAbc, &vStatuses );        
+    Abc_FrameReplaceCexVec( pAbc, &pAbc->pGia->vSeqModelVec );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &mprove [-TLMGH num] [-sdvwh]\n" );
+    Abc_Print( -2, "\t         proves multi-output testcase by applying several engines\n" );
+    Abc_Print( -2, "\t-T num : approximate global runtime limit in seconds [default = %d]\n",     pPars->TimeOutGlo );
+    Abc_Print( -2, "\t-L num : approximate local runtime limit in seconds [default = %d]\n",      pPars->TimeOutLoc );
+    Abc_Print( -2, "\t-M num : percentage of local runtime limit increase [default = %d]\n",      pPars->TimeOutInc );
+    Abc_Print( -2, "\t-G num : approximate gap runtime limit in seconds [default = %d]\n",        pPars->TimeOutGap );
+    Abc_Print( -2, "\t-H num : timeout per output in miliseconds [default = %d]\n",               pPars->TimePerOut );
+    Abc_Print( -2, "\t-s     : toggle using combinational synthesis [default = %s]\n",            pPars->fUseSyn?      "yes": "no" );
+    Abc_Print( -2, "\t-d     : toggle dumping invariant into a file [default = %s]\n",            pPars->fDumpFinal?   "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n",             pPars->fVerbose?     "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle printing additional verbose information [default = %s]\n",  pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+#ifdef ABC_USE_PTHREADS
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9SplitProve( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern int Cec_GiaSplitTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nIterMax, int LookAhead, int fVerbose, int fVeryVerbose );
+    int c, nProcs = 1, nTimeOut = 10, nIterMax = 0, LookAhead = 1, fVerbose = 0, fVeryVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "PTILvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nProcs = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nProcs <= 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nTimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nTimeOut <= 0 )
+                goto usage;
+            break;
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nIterMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nIterMax < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            LookAhead = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( LookAhead <= 0 || LookAhead > 100 )
+            {
+                Abc_Print( -1, "Look-ahead value (\"-L <num>\") should be between 1 and 100.\n", LookAhead );
+                goto usage;
+            }
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9SplitProve(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) > 0 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9SplitProve(): The problem is sequential.\n" );
+        return 1;
+    }
+    pAbc->Status = Cec_GiaSplitTest( pAbc->pGia, nProcs, nTimeOut, nIterMax, LookAhead, fVerbose, fVeryVerbose );
+    pAbc->pCex = pAbc->pGia->pCexComb;  pAbc->pGia->pCexComb = NULL;
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &splitprove [-PTIL num] [-vwh]\n" );
+    Abc_Print( -2, "\t         proves CEC problem by case-splitting\n" );
+    Abc_Print( -2, "\t-P num : the number of concurrent processes [default = %d]\n",          nProcs );
+    Abc_Print( -2, "\t-T num : runtime limit in seconds per subproblem [default = %d]\n",     nTimeOut );
+    Abc_Print( -2, "\t-I num : the max number of iterations (0 = infinity) [default = %d]\n", nIterMax );
+    Abc_Print( -2, "\t-L num : maximum look-ahead during cofactoring [default = %d]\n",       LookAhead );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n",         fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle printing more verbose information [default = %s]\n",    fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+#endif
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Bmc( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c;
+    Bmc_AndPar_t Pars, * pPars = &Pars;
+    memset( pPars, 0, sizeof(Bmc_AndPar_t) );
+    pPars->nStart        =    0;  // starting timeframe
+    pPars->nFramesMax    =    0;  // maximum number of timeframes 
+    pPars->nFramesAdd    =   50;  // the number of additional frames
+    pPars->nConfLimit    =    0;  // maximum number of conflicts at a node
+    pPars->nTimeOut      =    0;  // timeout in seconds
+    pPars->fLoadCnf      =    0;  // dynamic CNF loading
+    pPars->fDumpFrames   =    0;  // dump unrolled timeframes
+    pPars->fUseSynth     =    0;  // use synthesis
+    pPars->fUseOldCnf    =    0;  // use old CNF construction
+    pPars->fVerbose      =    0;  // verbose 
+    pPars->fVeryVerbose  =    0;  // very verbose 
+    pPars->fNotVerbose   =    0;  // skip line-by-line print-out 
+    pPars->iFrame        =    0;  // explored up to this frame
+    pPars->nFailOuts     =    0;  // the number of failed outputs
+    pPars->nDropOuts     =    0;  // the number of dropped outputs
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "SFATdscvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nStart < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesMax < 0 )
+                goto usage;
+            break;
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesAdd = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesAdd < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nTimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nTimeOut < 0 )
+                goto usage;
+            break;
+        case 'd':
+            pPars->fDumpFrames ^= 1;
+            break;
+        case 's':
+            pPars->fUseSynth ^= 1;
+            break;
+        case 'c':
+            pPars->fUseOldCnf ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Bmc(): There is no AIG.\n" );
+        return 0;
+    }
+    if ( !pPars->fUseOldCnf && !Sdm_ManCanRead() )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Bmc(): Cannot input precomputed DSD information.\n" );
+        return 0;
+    }
+    pAbc->Status  = Gia_ManBmcPerform( pAbc->pGia, pPars );
+    pAbc->nFrames = pPars->iFrame;
+    Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &bmc [-SFAT num] [-dscvwh]\n" );
+    Abc_Print( -2, "\t         performs bounded model checking\n" );
+    Abc_Print( -2, "\t-S num : the starting timeframe [default = %d]\n",                      pPars->nStart );
+    Abc_Print( -2, "\t-F num : the maximum number of timeframes [default = %d]\n",            pPars->nFramesMax );
+    Abc_Print( -2, "\t-A num : the number of additional frames to unroll [default = %d]\n",   pPars->nFramesAdd );
+    Abc_Print( -2, "\t-T num : approximate timeout in seconds [default = %d]\n",              pPars->nTimeOut );
+    Abc_Print( -2, "\t-d     : toggle dumping unfolded timeframes [default = %s]\n",          pPars->fDumpFrames?  "yes": "no" );
+    Abc_Print( -2, "\t-s     : toggle synthesizing unrolled timeframes [default = %s]\n",     pPars->fUseSynth?    "yes": "no" );
+    Abc_Print( -2, "\t-c     : toggle using old CNF computation [default = %s]\n",            pPars->fUseOldCnf?   "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n",         pPars->fVerbose?     "yes": "no" );
+    Abc_Print( -2, "\t-w     : toggle printing information about unfolding [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9BCore( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c;
+    Bmc_BCorePar_t Pars, * pPars = &Pars;
+    memset( pPars, 0, sizeof(Bmc_BCorePar_t) );
+    pPars->iFrame        =   10;  // timeframe
+    pPars->iOutput       =    0;  // property output
+    pPars->nTimeOut      =    0;  // timeout in seconds
+    pPars->pFilePivots   = NULL;  // file name with AIG IDs of pivot objects
+    pPars->pFileProof    = NULL;  // file name to write the resulting proof
+    pPars->fVerbose      =    0;  // verbose output
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FOTVvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->iFrame = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->iFrame < 0 )
+                goto usage;
+            break;
+        case 'O':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->iOutput = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->iOutput < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nTimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nTimeOut < 0 )
+                goto usage;
+            break;
+        case 'V':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-V\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pPars->pFilePivots = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9BCore(): There is no AIG.\n" );
+        return 0;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9BCore(): AIG has no registers.\n" );
+        return 0;
+    }
+    // get the file name
+    if ( pPars->pFilePivots != NULL )
+    {
+        FILE * pFile;
+        pFile = fopen( pPars->pFilePivots, "r" );
+        if ( pFile == NULL )
+        {
+            Abc_Print( -1, "Abc_CommandAbc9BCore(): Cannot open file \"%s\" with pivot node IDs.\n", pPars->pFilePivots );
+            return 0;
+        }
+        fclose( pFile );
+    }
+    // get the file name
+    if ( argc == globalUtilOptind + 1 )
+    {
+        FILE * pFile;
+        pPars->pFileProof = argv[globalUtilOptind];
+        pFile = fopen( pPars->pFileProof, "wb" );
+        if ( pFile == NULL )
+        {
+            Abc_Print( -1, "Abc_CommandAbc9BCore(): Cannot open file \"%s\" for writing the proof.\n", pPars->pFileProof );
+            return 0;
+        }
+        fclose( pFile );
+    }
+    Bmc_ManBCorePerform( pAbc->pGia, pPars );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &bcore [-FOTV num] [-vh] <file>\n" );
+    Abc_Print( -2, "\t         records UNSAT core of the BMC instance\n" );
+    Abc_Print( -2, "\t-F num : the zero-based index of a timeframe [default = %d]\n",         pPars->iFrame );
+    Abc_Print( -2, "\t-O num : the zero-based index of a primary output [default = %d]\n",    pPars->iOutput );
+    Abc_Print( -2, "\t-T num : approximate timeout in seconds [default = %d]\n",              pPars->nTimeOut );
+    Abc_Print( -2, "\t-V file: file name with AIG IDs of pivot variables [default = no pivots]\n" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n",         pPars->fVerbose?     "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : file name to write the resulting proof [default = stdout]\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9ICheck( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c, nFramesMax = 1, nTimeOut = 0, fEmpty = 0, fSearch = 1, fReverse = 0, fDump = 0, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "MTesrdvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFramesMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFramesMax <= 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nTimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nTimeOut < 0 )
+                goto usage;
+            break;
+        case 'e':
+            fEmpty ^= 1;
+            break;
+        case 's':
+            fSearch ^= 1;
+            break;
+        case 'r':
+            fReverse ^= 1;
+            break;
+        case 'd':
+            fDump ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9ICheck(): There is no AIG.\n" );
+        return 0;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9ICheck(): The AIG is combinational.\n" );
+        return 0;
+    }
+    Vec_IntFreeP( &pAbc->vIndFlops );
+    if ( fSearch )
+        pAbc->vIndFlops = Bmc_PerformISearch( pAbc->pGia, nFramesMax, nTimeOut, fReverse, fDump, fVerbose );
+    else
+        Bmc_PerformICheck( pAbc->pGia, nFramesMax, nTimeOut, fEmpty, fVerbose );
+    pAbc->nIndFrames = pAbc->vIndFlops ? nFramesMax : 0;
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &icheck [-MT num] [-esrdvh]\n" );
+    Abc_Print( -2, "\t         performs specialized induction check\n" );
+    Abc_Print( -2, "\t-M num : the number of timeframes used for induction [default = %d]\n",    nFramesMax );
+    Abc_Print( -2, "\t-T num : approximate global runtime limit in seconds [default = %d]\n",    nTimeOut );
+    Abc_Print( -2, "\t-e     : toggle using empty set of next-state functions [default = %s]\n", fEmpty? "yes": "no" );
+    Abc_Print( -2, "\t-s     : toggle searching for a minimal subset [default = %s]\n",          fSearch? "yes": "no" );
+    Abc_Print( -2, "\t-r     : toggle searching in the reverse order [default = %s]\n",          fReverse? "yes": "no" );
+    Abc_Print( -2, "\t-d     : toggle printing out the resulting set [default = %s]\n",          fDump? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n",            fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9SatTest( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Bmc_LoadTest( Gia_Man_t * pGia, int fLoadCnf, int fVerbose );
+    int c, fLoadCnf = 0, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "cvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'c':
+            fLoadCnf ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9SatTest(): There is no AIG.\n" );
+        return 0;
+    }
+    Bmc_LoadTest( pAbc->pGia, fLoadCnf, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &sattest [-cvh]\n" );
+    Abc_Print( -2, "\t         performs testing of dynamic CNF loading\n" );
+    Abc_Print( -2, "\t-c     : toggle dynamic CNF loading [default = %s]\n",          fLoadCnf? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9FFTest( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Gia_ParFfSetDefault( Bmc_ParFf_t * p );
+    extern void Gia_ManFaultTest( Gia_Man_t * p, Gia_Man_t * pG, Bmc_ParFf_t * pPars );
+    Bmc_ParFf_t Pars, * pPars = &Pars;
+    char * pFileName = NULL;
+    Gia_Man_t * pGold = NULL;
+    int c;
+    Gia_ParFfSetDefault( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ATSGsbduvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->Algo = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->Algo < 0 || pPars->Algo > 4 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nTimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nTimeOut < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by string.\n" );
+                goto usage;
+            }
+            pPars->pFormStr = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by string.\n" );
+                goto usage;
+            }
+            pFileName = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 's':
+            pPars->fStartPats ^= 1;
+            break;
+        case 'b':
+            pPars->fBasic ^= 1;
+            break;
+        case 'd':
+            pPars->fDump ^= 1;
+            break;
+        case 'u':
+            pPars->fDumpUntest ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pPars->Algo == 0 && pPars->pFormStr == NULL )
+    {
+        Abc_Print( -1, "Formula string (-S <str>) should be selected when algorithm is 0 (-A 0).\n" );
+        return 0;
+    }
+    if ( pPars->Algo != 0 && pPars->pFormStr != NULL )
+    {
+        Abc_Print( -1, "Algorithm should be 0 (-A 0) when formula string is selected (-S <str>).\n" );
+        return 0;
+    }
+    // get the file name
+    if ( argc == globalUtilOptind + 1 )
+    {
+        FILE * pFile;
+        pPars->pFileName = argv[globalUtilOptind];
+        pFile = fopen( pPars->pFileName, "r" );
+        if ( pFile == NULL )
+        {
+            Abc_Print( -1, "Cannot open file \"%s\" with the input test patterns.\n", pPars->pFileName );
+            return 0;
+        }
+        fclose( pFile );
+    }
+    // check other conditions
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9FFTest(): There is no AIG.\n" );
+        return 0;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 && pPars->Algo == 1 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9FFTest(): For delay testing, AIG should be sequential.\n" );
+        return 0;
+    }
+    // check if the file is valid
+    if ( pFileName )
+    {
+        FILE * pFile = fopen( pFileName, "r" );
+        if ( pFile == NULL )
+        {
+            Abc_Print( -1, "Abc_CommandAbc9FFTest(): File name \"%s\" with golden model is invalid.\n", pFileName );
+            return 0;
+        }
+        fclose( pFile );
+        pGold = Gia_AigerRead( pFileName, 0, 0 );
+        if ( pGold == NULL )
+        {
+            Abc_Print( -1, "Abc_CommandAbc9FFTest(): Cannot read file \"%s\" with golden model.\n", pFileName );
+            return 0;
+        }
+        if ( Gia_ManPiNum(pAbc->pGia) != Gia_ManPiNum(pGold) )
+        {
+            Gia_ManStop( pGold );
+            Abc_Print( -1, "Abc_CommandAbc9FFTest(): Old model and gold model have different number of PIs.\n" );
+            return 0;
+        }
+        if ( Gia_ManPoNum(pAbc->pGia) != Gia_ManPoNum(pGold) )
+        {
+            Gia_ManStop( pGold );
+            Abc_Print( -1, "Abc_CommandAbc9FFTest(): Old model and gold model have different number of POs.\n" );
+            return 0;
+        }
+        printf( "Entered spec AIG from file \"%s\".\n", pFileName );
+    }
+    Gia_ManFaultTest( pAbc->pGia, pGold ? pGold : pAbc->pGia, pPars );
+    Gia_ManStopP( &pGold );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &fftest [-AT num] [-sbduvh] <file> [-G file] [-S str]\n" );
+    Abc_Print( -2, "\t          performs functional fault test generation\n" );
+    Abc_Print( -2, "\t-A num  : selects fault model for all gates [default = %d]\n", pPars->Algo );
+    Abc_Print( -2, "\t                0: fault model is not selected (use -S str)\n" );
+    Abc_Print( -2, "\t                1: delay fault testing for sequential circuits\n" );
+    Abc_Print( -2, "\t                2: traditional stuck-at fault: -S (((a&b)&~p)|q)\n" );
+    Abc_Print( -2, "\t                3: complement fault: -S ((a&b)^p)\n" );
+    Abc_Print( -2, "\t                4: functionally observable fault\n" );
+    Abc_Print( -2, "\t-T num  : specifies approximate runtime limit in seconds [default = %d]\n",        pPars->nTimeOut );
+    Abc_Print( -2, "\t-s      : toggles starting with the all-0 and all-1 patterns [default = %s]\n",    pPars->fStartPats?  "yes": "no" );
+    Abc_Print( -2, "\t-b      : toggles testing for single faults only [default = %s]\n",                pPars->fBasic?      "yes": "no" );
+    Abc_Print( -2, "\t-d      : toggles dumping test patterns into file \"tests.txt\" [default = %s]\n", pPars->fDump?       "yes": "no" );
+    Abc_Print( -2, "\t-u      : toggles dumping untestable faults into \"untest.txt\" [default = %s]\n", pPars->fDumpUntest? "yes": "no" );
+    Abc_Print( -2, "\t-v      : toggles printing verbose information [default = %s]\n",                  pPars->fVerbose?    "yes": "no" );
+    Abc_Print( -2, "\t-h      : print the command usage\n");
+    Abc_Print( -2, "\t<file>  : (optional) file name with input test patterns\n\n");
+    Abc_Print( -2, "\t-G file : (optional) file name with the golden model\n\n");
+    Abc_Print( -2, "\t-S str  : (optional) string representing the fault model\n");
+    Abc_Print( -2, "\t          The following notations are used:\n");
+    Abc_Print( -2, "\t            Functional variables: {a,b} (both a and b are always present)\n");
+    Abc_Print( -2, "\t            Parameter variables: {p,q,r,s,t,u,v,w} (any number from 1 to 8)\n");
+    Abc_Print( -2, "\t            Boolean operators: AND(&), OR(|), XOR(^), MUX(?:), NOT(~)\n");
+    Abc_Print( -2, "\t            Parantheses should be used around each operator. Spaces not allowed.\n");
+    Abc_Print( -2, "\t            Complement (~) is only allowed before variables (use DeMorgan law).\n");
+    Abc_Print( -2, "\t            Examples:\n");
+    Abc_Print( -2, "\t              (((a&b)&~p)|q)        stuck-at-0/1 at the output\n");
+    Abc_Print( -2, "\t              (((a&~p)|q)&b)        stuck-at-0/1 at input a\n");
+    Abc_Print( -2, "\t              (((a|p)&(b|q))&~r)    stuck-at-1 at the inputs and stuck-at-0 at the output\n");
+    Abc_Print( -2, "\t              (((a&~p)&(b&~q))|r)   stuck-at-0 at the inputs and stuck-at-1 at the output\n");
+    Abc_Print( -2, "\t              ((a&b)^p)             complement at the output\n");
+    Abc_Print( -2, "\t              (((a^p)&(b^q))^r)     complement at the inputs and at the output\n");
+    Abc_Print( -2, "\t              (a?(b?~s:r):(b?q:p))  functionally observable fault at the output\n");
+    Abc_Print( -2, "\t              (p?(a|b):(a&b))       replace AND by OR\n");    
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Inse( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Vec_Int_t * Gia_ManInseTest( Gia_Man_t * p, Vec_Int_t * vInit, int nFrames, int nWords, int nTimeOut, int fSim, int fVerbose );
+    int c, nFrames = 10, nWords = 1000, nTimeOut = 0, fSim = 0, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FWTsvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nWords < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nTimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nTimeOut < 0 )
+                goto usage;
+            break;
+        case 's':
+            fSim ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Inse(): There is no AIG.\n" );
+        return 0;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Inse(): AIG is combinational.\n" );
+        return 0;
+    }
+    if ( pAbc->pGia->vInitClasses != NULL )
+    {
+        Abc_Print( 1, "Abc_CommandAbc9Inse(): All-0 initial state is assumed.\n" );
+        Vec_IntFreeP( &pAbc->pGia->vInitClasses );
+    }
+    pAbc->pGia->vInitClasses = Gia_ManInseTest( pAbc->pGia, NULL, nFrames, nWords, nTimeOut, fSim, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &inse [-FWT num] [-svh]\n" );
+    Abc_Print( -2, "\t         experimental procedure\n" );
+    Abc_Print( -2, "\t-F num : the number of timeframes [default = %d]\n",                    nFrames );
+    Abc_Print( -2, "\t-W num : the number of machine words [default = %d]\n",                 nWords );
+    Abc_Print( -2, "\t-T num : approximate global runtime limit in seconds [default = %d]\n", nTimeOut );
+    Abc_Print( -2, "\t-s     : toggles using ternary simulation [default = %s]\n",            fSim?     "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggles printing verbose information [default = %s]\n",        fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Maxi( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Vec_Int_t * Gia_ManMaxiTest( Gia_Man_t * p, Vec_Int_t * vInit, int nFrames, int nWords, int nTimeOut, int fSim, int fVerbose );
+    Vec_Int_t * vTemp;
+    int c, nFrames = 5, nWords = 1000, nTimeOut = 0, fSim = 0, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FWTsvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nWords < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nTimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nTimeOut < 0 )
+                goto usage;
+            break;
+        case 's':
+            fSim ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Maxi(): There is no AIG.\n" );
+        return 0;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Maxi(): AIG is combinational.\n" );
+        return 0;
+    }
+    pAbc->pGia->vInitClasses = Gia_ManMaxiTest( pAbc->pGia, vTemp = pAbc->pGia->vInitClasses, nFrames, nWords, nTimeOut, fSim, fVerbose );
+    Vec_IntFreeP( &vTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &maxi [-FWT num] [-svh]\n" );
+    Abc_Print( -2, "\t         experimental procedure\n" );
+    Abc_Print( -2, "\t-F num : the number of timeframes [default = %d]\n",                    nFrames );
+    Abc_Print( -2, "\t-W num : the number of machine words [default = %d]\n",                 nWords );
+    Abc_Print( -2, "\t-T num : approximate global runtime limit in seconds [default = %d]\n", nTimeOut );
+    Abc_Print( -2, "\t-s     : toggles using ternary simulation [default = %s]\n",            fSim?     "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggles printing verbose information [default = %s]\n",        fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Bmci( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern int Gia_ManBmciTest( Gia_Man_t * p, Vec_Int_t * vInit, int nFrames, int nWords, int nTimeOut, int fSim, int fVerbose );
+    int c, nFrames = 1000, nWords = 1000, nTimeOut = 0, fSim = 0, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FWTsvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nWords < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nTimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nTimeOut < 0 )
+                goto usage;
+            break;
+        case 's':
+            fSim ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Bmci(): There is no AIG.\n" );
+        return 0;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Bmci(): AIG is combinational.\n" );
+        return 0;
+    }
+    if ( pAbc->pGia->vInitClasses == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Bmci(): Init array is not given.\n" );
+        return 0;
+    }
+    Gia_ManBmciTest( pAbc->pGia, pAbc->pGia->vInitClasses, nFrames, nWords, nTimeOut, fSim, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &bmci [-FWT num] [-svh]\n" );
+    Abc_Print( -2, "\t         experimental procedure\n" );
+    Abc_Print( -2, "\t-F num : the number of timeframes [default = %d]\n",                    nFrames );
+    Abc_Print( -2, "\t-W num : the number of machine words [default = %d]\n",                 nWords );
+    Abc_Print( -2, "\t-T num : approximate global runtime limit in seconds [default = %d]\n", nTimeOut );
+    Abc_Print( -2, "\t-s     : toggles using ternary simulation [default = %s]\n",            fSim?     "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggles printing verbose information [default = %s]\n",        fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9PoXsim( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Vec_Int_t * Gia_ManPoXSim( Gia_Man_t * p, int nFrames, int fVerbose );
+    int c, nFrames = 1000, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Bmci(): There is no AIG.\n" );
+        return 0;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Bmci(): AIG is combinational.\n" );
+        return 0;
+    }
+    Vec_IntFreeP( &pAbc->vAbcObjIds );
+    pAbc->vAbcObjIds = Gia_ManPoXSim( pAbc->pGia, nFrames, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &poxsim [-F num] [-vh]\n" );
+    Abc_Print( -2, "\t         X-valued simulation of the multi-output sequential miter\n" );
+    Abc_Print( -2, "\t-F num : the number of timeframes [default = %d]\n",                    nFrames );
+    Abc_Print( -2, "\t-v     : toggles printing verbose information [default = %s]\n",        fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Demiter( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Gia_Man_t * Gia_ManDupDemiter( Gia_Man_t * p, int fVerbose );
+    Gia_Man_t * pTemp;
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Demiter(): There is no AIG.\n" );
+        return 0;
+    }
+    if ( Gia_ManPoNum(pAbc->pGia) != 1 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Demiter(): Miter should have one output.\n" );
+        return 0;
+    }
+    pTemp = Gia_ManDupDemiter( pAbc->pGia, fVerbose );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    if ( fVerbose )
+        Gia_ManPrintStatsMiter( pTemp, 0 );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &demiter [-vh]\n" );
+    Abc_Print( -2, "\t         decomposes a single-output miter\n" );
+    Abc_Print( -2, "\t-v     : toggles printing verbose information [default = %s]\n",  fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9CexCut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9CexMerge( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Cex_t * pCexNew;
+    int c;
+    int iFrStart = 0;
+    int iFrStop  = ABC_INFINITY;
+    int fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FGvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iFrStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iFrStart < 0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iFrStop = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iFrStop < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            Abc_Print( -2, "Unknown switch.\n");
+            goto usage;
+        }
+    }
+
+    if ( pAbc->pCex == NULL )
+    {
+        Abc_Print( 1, "There is no current cex.\n");
+        return 0;
+    }
+    if ( pAbc->pCex2 == NULL )
+    {
+        Abc_Print( 1, "There is no saved cex.\n");
+        return 0;
+    }
+    if ( iFrStop - iFrStart < pAbc->pCex->iFrame )
+    {
+        Abc_Print( 1, "Current CEX does not allow to shorten the saved CEX.\n");
+        return 0;
+    }
+    pCexNew = Abc_CexMerge( pAbc->pCex2, pAbc->pCex, iFrStart, iFrStop );
+    if ( pCexNew == NULL )
+    {
+        Abc_Print( 1, "Merging CEXes has failed.\n");
+        return 0;
+    }
+    // replace the saved CEX
+    ABC_FREE( pAbc->pCex2 );
+    pAbc->pCex2 = pCexNew;
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &cexmerge [-FG num] [-vh]\n" );
+    Abc_Print( -2, "\t         merges the current CEX into the saved one\n" );
+    Abc_Print( -2, "\t         and sets the resulting CEX as the saved one\n" );
+    Abc_Print( -2, "\t-F num : 0-based number of the starting frame [default = %d]\n", iFrStart );
+    Abc_Print( -2, "\t-G num : 0-based number of the ending frame [default = %d]\n",   iFrStop );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9CexMin( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Abc_Cex_t * Gia_ManCexMin( Gia_Man_t * p, Abc_Cex_t * pCex, int iFrameStart, int nRealPis, int fJustMax, int fUseAll, int fVerbose );
+    Abc_Cex_t * pCexNew;
+    int iFrameStart = 0;
+    int nRealPis = -1;
+    int fJustMax = 1;
+    int fUseAll = 0;
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FNjavh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iFrameStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iFrameStart < 0 )
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nRealPis = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nRealPis < 0 )
+                goto usage;
+            break;
+        case 'j':
+            fJustMax ^= 1;
+            break;
+        case 'a':
+            fUseAll ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9CexMin(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9CexMin(): The network is combinational.\n" );
+        return 0;
+    }
+    if ( pAbc->pCex == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9CexMin(): There is no counter-example.\n" );
+        return 1;
+    }
+    pCexNew = Gia_ManCexMin( pAbc->pGia, pAbc->pCex, iFrameStart, nRealPis, fJustMax, fUseAll, fVerbose );
+    if ( pCexNew )
+        Abc_FrameReplaceCex( pAbc, &pCexNew );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &cexmin [-FN num] [-javh]\n" );
+    Abc_Print( -2, "\t         minimizes a deep counter-example\n" );
+    Abc_Print( -2, "\t-F num : starting timeframe for minimization [default = %d]\n", iFrameStart );
+    Abc_Print( -2, "\t-N num : the number of real primary inputs [default = %d]\n", nRealPis );
+    Abc_Print( -2, "\t-j     : toggle computing all justifying assignments [default = %s]\n", fJustMax? "yes": "no" );
+    Abc_Print( -2, "\t-a     : toggle using all terminal objects [default = %s]\n", fUseAll? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9AbsDerive( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp = NULL;
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9AbsDerive(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    if ( pAbc->pGia->vFlopClasses == NULL )
+    {
+        Abc_Print( -1, "Abstraction flop map is missing.\n" );
+        return 0;
+    }
+    pTemp = Gia_ManDupAbsFlops( pAbc->pGia, pAbc->pGia->vFlopClasses );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &abs_derive [-vh]\n" );
+    Abc_Print( -2, "\t        derives abstracted model using the pre-computed flop map\n" );
+    Abc_Print( -2, "\t-v    : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9AbsRefine( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+//    Gia_Man_t * pTemp = NULL;
+    int c;
+    int nFfToAddMax = 0;
+    int fTryFour    = 1;
+    int fSensePath  = 0;
+    int fVerbose    = 0;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Mtsvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFfToAddMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFfToAddMax < 0 )
+                goto usage;
+            break;
+        case 't':
+            fTryFour ^= 1;
+            break;
+        case 's':
+            fSensePath ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9AbsRefine(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    if ( pAbc->pCex == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9AbsRefine(): There is no counter-example.\n" );
+        return 1;
+    }
+    pAbc->Status = Gia_ManCexAbstractionRefine( pAbc->pGia, pAbc->pCex, nFfToAddMax, fTryFour, fSensePath, fVerbose );
+    Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &abs_refine [-M <num>] [-tsvh]\n" );
+    Abc_Print( -2, "\t         refines the pre-computed flop map using the counter-example\n" );
+    Abc_Print( -2, "\t-M num : the max number of flops to add (0 = not used) [default = %d]\n", nFfToAddMax );
+    Abc_Print( -2, "\t-t     : toggle trying four abstractions instead of one [default = %s]\n", fTryFour? "yes": "no" );
+    Abc_Print( -2, "\t-s     : toggle using the path sensitization algorithm [default = %s]\n", fSensePath? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9GlaDerive( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Gia_Man_t * pTemp = NULL;
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9GlaDerive(): There is no AIG.\n" );
+        return 1;
+    }
+/*
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+*/
+    if ( pAbc->pGia->vGateClasses == NULL )
+    {
+        Abc_Print( -1, "Abstraction gate map is missing.\n" );
+        return 0;
+    }
+    pTemp = Gia_ManDupAbsGates( pAbc->pGia, pAbc->pGia->vGateClasses );
+    Gia_ManStop( pTemp );
+    pTemp = Gia_ManDupAbsGates( pAbc->pGia, pAbc->pGia->vGateClasses );
+    Abc_FrameUpdateGia( pAbc, pTemp );
+//    Abc_Print( 1,"This command is currently not enabled.\n" );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &gla_derive [-vh]\n" );
+    Abc_Print( -2, "\t        derives abstracted model using the pre-computed gate map\n" );
+    Abc_Print( -2, "\t-v    : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9GlaRefine( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern int Gia_ManNewRefine( Gia_Man_t * p, Abc_Cex_t * pCex, int iFrameStart, int iFrameExtra, int fVerbose );
+    int iFrameStart = 0;
+    int iFrameExtra = 0;
+    int fMinCut = 1;
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FGmvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iFrameStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iFrameStart < 0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            iFrameExtra = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( iFrameExtra < 0 )
+                goto usage;
+            break;
+        case 'm':
+            fMinCut ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9GlaRefine(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    if ( pAbc->pCex == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9GlaRefine(): There is no counter-example.\n" );
+        return 1;
+    }
+    pAbc->Status = Gia_ManNewRefine( pAbc->pGia, pAbc->pCex, iFrameStart, iFrameExtra, fVerbose );
+    Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &gla_refine [-FG num] [-vh]\n" );
+    Abc_Print( -2, "\t         refines the pre-computed gate map using the counter-example\n" );
+    Abc_Print( -2, "\t-F num : starting timeframe for suffix refinement [default = %d]\n", iFrameStart );
+    Abc_Print( -2, "\t-G num : the number of additional timeframes to try [default = %d]\n", iFrameExtra );
+//    Abc_Print( -2, "\t-m     : toggle using min-cut to derive the refinements [default = %s]\n", fMinCut? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9GlaShrink( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int fUsePdr = 0;
+    int fUseSat = 1;
+    int fUseBdd = 0;
+    int nFrameMax = 0;
+    int nTimeOut = 0;
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FTpsbvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrameMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrameMax < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nTimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nTimeOut < 0 )
+                goto usage;
+            break;
+        case 'p':
+            fUsePdr ^= 1;
+            break;
+        case 's':
+            fUseSat ^= 1;
+            break;
+        case 'b':
+            fUseBdd ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9GlaShrink(): There is no AIG.\n" );
+        return 1;
+    }
+    if ( pAbc->pGia->vGateClasses == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9GlaShrink(): There is no gate-level abstraction.\n" );
+        return 0;
+    }
+    Gia_ManShrinkGla( pAbc->pGia, nFrameMax, nTimeOut, fUsePdr, fUseSat, fUseBdd, fVerbose );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &gla_shrink [-FT num] [-psbvh]\n" );
+    Abc_Print( -2, "\t         shrinks the abstraction by removing redundant objects\n" );
+    Abc_Print( -2, "\t-F num : the maximum timeframe to check to [default = %d]\n", nFrameMax );
+    Abc_Print( -2, "\t-T num : the timeout per call, in seconds [default = %d]\n", nTimeOut );
+    Abc_Print( -2, "\t-p     : toggle using PDR for checking [default = %s]\n", fUsePdr? "yes": "no" );
+    Abc_Print( -2, "\t-s     : toggle using BMC for checking [default = %s]\n", fUseSat? "yes": "no" );
+    Abc_Print( -2, "\t-b     : toggle using BDDs for checking [default = %s]\n", fUseBdd? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Gla( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abs_Par_t Pars, * pPars = &Pars;
+    int c, fNewAlgo = 1;
+    Abs_ParSetDefaults( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FSCLDETRQPBAtfardmnscbpquwvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesMax < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesStart < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nConfLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nConfLimit < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nLearnedStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLearnedStart < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nLearnedDelta = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLearnedDelta < 0 )
+                goto usage;
+            break;
+        case 'E':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nLearnedPerce = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLearnedPerce < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nTimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nTimeOut < 0 )
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRatioMin = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRatioMin < 0 )
+                goto usage;
+            break;
+        case 'Q':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-Q\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRatioMin2 = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRatioMin2 < 0 )
+                goto usage;
+            break;
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRatioMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRatioMax < 0 )
+                goto usage;
+            break;
+        case 'B':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesNoChangeLim = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesNoChangeLim < 0 )
+                goto usage;
+            break;
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pPars->pFileVabs = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 't':
+            pPars->fUseTermVars ^= 1;
+            break;
+        case 'f':
+            pPars->fPropFanout ^= 1;
+            break;
+        case 'a':
+            pPars->fAddLayer ^= 1;
+            break;
+        case 'r':
+            pPars->fNewRefine ^= 1;
+            break;
+        case 'd':
+            pPars->fDumpVabs ^= 1;
+            break;
+        case 'm':
+            pPars->fDumpMabs ^= 1;
+            break;
+        case 'n':
+            fNewAlgo ^= 1;
+            break;
+        case 's':
+            pPars->fUseSkip ^= 1;
+            break;
+        case 'c':
+            pPars->fUseSimple ^= 1;
+            break;
+        case 'b':
+            pPars->fSkipHash ^= 1;
+            break;
+        case 'p':
+            pPars->fUseFullProof ^= 1;
+            break;
+        case 'q':
+            pPars->fCallProver ^= 1;
+            break;
+        case 'u':
+            pPars->fSimpProver ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "There is no AIG.\n" );
+        return 0;
+    }
+/*
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+*/
+    if ( Gia_ManPoNum(pAbc->pGia) > 1 )
+    {
+        Abc_Print( 1, "The network is more than one PO (run \"orpos\").\n" );
+        return 0;
+    }
+    if ( pPars->nFramesMax < 0 )
+    {
+        Abc_Print( 1, "The number of starting frames should be a positive integer.\n" );
+        return 0;
+    }
+    if ( pPars->nFramesMax && pPars->nFramesStart > pPars->nFramesMax )
+    {
+        Abc_Print( 1, "The starting frame is larger than the max number of frames.\n" );
+        return 0;
+    }
+    if ( fNewAlgo )
+        pAbc->Status = Gia_ManPerformGla( pAbc->pGia, pPars );
+    else
+        pAbc->Status  = Gia_ManPerformGlaOld( pAbc->pGia, pPars, 0 );
+    pAbc->nFrames = pPars->iFrame;
+    Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &gla [-FSCLDETRQPB num] [-A file] [-fardmnscbpquwvh]\n" );
+    Abc_Print( -2, "\t          fixed-time-frame gate-level proof- and cex-based abstraction\n" );
+    Abc_Print( -2, "\t-F num  : the max number of timeframes to unroll [default = %d]\n", pPars->nFramesMax );
+    Abc_Print( -2, "\t-S num  : the starting time frame (0=unused) [default = %d]\n", pPars->nFramesStart );
+    Abc_Print( -2, "\t-C num  : the max number of SAT solver conflicts (0=unused) [default = %d]\n", pPars->nConfLimit );
+    Abc_Print( -2, "\t-L num  : the max number of learned clauses to keep (0=unused) [default = %d]\n", pPars->nLearnedStart );
+    Abc_Print( -2, "\t-D num  : delta value for learned clause removal [default = %d]\n", pPars->nLearnedDelta );
+    Abc_Print( -2, "\t-E num  : ratio percentage for learned clause removal [default = %d]\n", pPars->nLearnedPerce );
+    Abc_Print( -2, "\t-T num  : an approximate timeout, in seconds [default = %d]\n", pPars->nTimeOut );
+    Abc_Print( -2, "\t-R num  : stop when abstraction size exceeds num %% (0<=num<=100) [default = %d]\n", pPars->nRatioMin );
+    Abc_Print( -2, "\t-Q num  : stop when abstraction size exceeds num %% during refinement (0<=num<=100) [default = %d]\n", pPars->nRatioMin2 );
+    Abc_Print( -2, "\t-P num  : maximum percentage of added objects before a restart (0<=num<=100) [default = %d]\n", pPars->nRatioMax );
+    Abc_Print( -2, "\t-B num  : the number of stable frames to call prover or dump abstraction [default = %d]\n", pPars->nFramesNoChangeLim );
+    Abc_Print( -2, "\t-A file : file name for dumping abstrated model [default = \"glabs.aig\"]\n" );
+    Abc_Print( -2, "\t-f      : toggle propagating fanout implications [default = %s]\n", pPars->fPropFanout? "yes": "no" );
+    Abc_Print( -2, "\t-a      : toggle refinement by adding one layers of gates [default = %s]\n", pPars->fAddLayer? "yes": "no" );
+    Abc_Print( -2, "\t-r      : toggle using improved refinement heuristics [default = %s]\n", pPars->fNewRefine? "yes": "no" );
+    Abc_Print( -2, "\t-d      : toggle dumping abstracted model into a file [default = %s]\n", pPars->fDumpVabs? "yes": "no" );
+    Abc_Print( -2, "\t-m      : toggle dumping abstraction map into a file [default = %s]\n", pPars->fDumpMabs? "yes": "no" );
+    Abc_Print( -2, "\t-n      : toggle using new algorithms [default = %s]\n", fNewAlgo? "yes": "no" );
+    Abc_Print( -2, "\t-s      : toggle skipping previously proved timeframes [default = %s]\n", pPars->fUseSkip? "yes": "no" );
+    Abc_Print( -2, "\t-c      : toggle using naive (2-input AND node) CNF encoding [default = %s]\n", pPars->fUseSimple? "yes": "no" );
+    Abc_Print( -2, "\t-b      : toggle CNF construction without hashing [default = %s]\n", pPars->fSkipHash? "yes": "no" );
+    Abc_Print( -2, "\t-p      : toggle using full-proof for UNSAT cores [default = %s]\n", pPars->fUseFullProof? "yes": "no" );
+    Abc_Print( -2, "\t-q      : toggle calling the prover [default = %s]\n", pPars->fCallProver? "yes": "no" );
+    Abc_Print( -2, "\t-u      : toggle enabling simplifation before calling the prover [default = %s]\n", pPars->fSimpProver? "yes": "no" );
+    Abc_Print( -2, "\t-v      : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-w      : toggle printing more verbose information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h      : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Vta( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abs_Par_t Pars, * pPars = &Pars;
+    int c;
+    Abs_ParSetDefaults( pPars );
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "FSPCLDETRAtradvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesMax < 0 )
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesStart < 0 )
+                goto usage;
+            break;
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nFramesPast = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nFramesPast < 0 )
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nConfLimit = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nConfLimit < 0 )
+                goto usage;
+            break;
+        case 'L':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nLearnedStart = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLearnedStart < 0 )
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nLearnedDelta = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLearnedDelta < 0 )
+                goto usage;
+            break;
+        case 'E':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-E\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nLearnedPerce = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nLearnedPerce < 0 )
+                goto usage;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nTimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nTimeOut < 0 )
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            pPars->nRatioMin = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nRatioMin < 0 )
+                goto usage;
+            break;
+        case 'A':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-A\" should be followed by a file name.\n" );
+                goto usage;
+            }
+            pPars->pFileVabs = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 't':
+            pPars->fUseTermVars ^= 1;
+            break;
+        case 'r':
+            pPars->fUseRollback ^= 1;
+            break;
+        case 'a':
+            pPars->fAddLayer ^= 1;
+            break;
+        case 'd':
+            pPars->fDumpVabs ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "There is no AIG.\n" );
+        return 0;
+    }
+    if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    if ( Gia_ManPoNum(pAbc->pGia) > 1 )
+    {
+        Abc_Print( 1, "The network is more than one PO (run \"orpos\").\n" );
+        return 0;
+    }
+    if ( pPars->nFramesMax < 0 )
+    {
+        Abc_Print( 1, "The number of starting frames should be a positive integer.\n" );
+        return 0;
+    }
+    if ( pPars->nFramesMax && pPars->nFramesStart > pPars->nFramesMax )
+    {
+        Abc_Print( 1, "The starting frame is larger than the max number of frames.\n" );
+        return 0;
+    }
+    pAbc->Status  = Gia_VtaPerform( pAbc->pGia, pPars );
+    pAbc->nFrames = pPars->iFrame;
+    Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &vta [-FSPCLDETR num] [-A file] [-tradvh]\n" );
+    Abc_Print( -2, "\t          variable-time-frame gate-level proof- and cex-based abstraction\n" );
+    Abc_Print( -2, "\t-F num  : the max number of timeframes to unroll [default = %d]\n", pPars->nFramesMax );
+    Abc_Print( -2, "\t-S num  : the starting time frame (0=unused) [default = %d]\n", pPars->nFramesStart );
+    Abc_Print( -2, "\t-P num  : the number of previous frames for UNSAT core [default = %d]\n", pPars->nFramesPast );
+    Abc_Print( -2, "\t-C num  : the max number of SAT solver conflicts (0=unused) [default = %d]\n", pPars->nConfLimit );
+    Abc_Print( -2, "\t-L num  : the max number of learned clauses to keep (0=unused) [default = %d]\n", pPars->nLearnedStart );
+    Abc_Print( -2, "\t-D num  : delta value for learned clause removal [default = %d]\n", pPars->nLearnedDelta );
+    Abc_Print( -2, "\t-E num  : ratio percentage for learned clause removal [default = %d]\n", pPars->nLearnedPerce );
+    Abc_Print( -2, "\t-T num  : an approximate timeout, in seconds [default = %d]\n", pPars->nTimeOut );
+    Abc_Print( -2, "\t-R num  : minimum percentage of abstracted objects (0<=num<=100) [default = %d]\n", pPars->nRatioMin );
+    Abc_Print( -2, "\t-A file : file name for dumping abstrated model [default = \"vabs.aig\"]\n" );
+    Abc_Print( -2, "\t-t      : toggle using terminal variables [default = %s]\n", pPars->fUseTermVars? "yes": "no" );
+    Abc_Print( -2, "\t-r      : toggle using rollback after the starting frames [default = %s]\n", pPars->fUseRollback? "yes": "no" );
+    Abc_Print( -2, "\t-a      : toggle refinement by adding one layers of gates [default = %s]\n", pPars->fAddLayer? "yes": "no" );
+    Abc_Print( -2, "\t-d      : toggle dumping abstracted model into a file [default = %s]\n", pPars->fDumpVabs? "yes": "no" );
+    Abc_Print( -2, "\t-v      : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h      : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Vta2Gla( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Vta2Gla(): There is no AIG.\n" );
+        return 0;
+    }
+    if ( pAbc->pGia->vObjClasses == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Vta2Gla(): There is no variable-time-frame abstraction is defined.\n" );
+        return 0;
+    }
+    Vec_IntFreeP( &pAbc->pGia->vGateClasses );
+    pAbc->pGia->vGateClasses = Gia_VtaConvertToGla( pAbc->pGia, pAbc->pGia->vObjClasses );
+    Vec_IntFreeP( &pAbc->pGia->vObjClasses );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &vta_gla [-vh]\n" );
+    Abc_Print( -2, "\t        maps variable- into fixed-time-frame gate-level abstraction\n" );
+    Abc_Print( -2, "\t-v    : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Gla2Vta( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c, fVerbose = 0;
+    int nFrames = pAbc->nFrames;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Gla2Vta(): There is no AIG.\n" );
+        return 0;
+    }
+    if ( pAbc->pGia->vGateClasses == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Gla2Vta(): There is no gate-level abstraction is defined.\n" );
+        return 0;
+    }
+    if ( pAbc->nFrames < 1 )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Gla2Vta(): The number of timeframes (%d) should be a positive integer.\n", nFrames );
+        return 0;
+    }
+    Vec_IntFreeP( &pAbc->pGia->vObjClasses );
+    pAbc->pGia->vObjClasses = Gia_VtaConvertFromGla( pAbc->pGia, pAbc->pGia->vGateClasses, nFrames );
+    Vec_IntFreeP( &pAbc->pGia->vGateClasses );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &gla_vta [-F num] [-vh]\n" );
+    Abc_Print( -2, "\t          maps fixed- into variable-time-frame gate-level abstraction\n" );
+    Abc_Print( -2, "\t-F num  : timeframes in the resulting variable-time-frame abstraction [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-v      : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h      : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Fla2Gla( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Fla2Gla(): There is no AIG.\n" );
+        return 0;
+    }
+    if ( pAbc->pGia->vFlopClasses == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Fla2Gla(): There is no gate-level abstraction is defined.\n" );
+        return 0;
+    }
+    Vec_IntFreeP( &pAbc->pGia->vGateClasses );
+    pAbc->pGia->vGateClasses = Gia_FlaConvertToGla( pAbc->pGia, pAbc->pGia->vFlopClasses );
+    Vec_IntFreeP( &pAbc->pGia->vFlopClasses );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &fla_gla [-vh]\n" );
+    Abc_Print( -2, "\t          maps flop-level into gate-level abstraction\n" );
+    Abc_Print( -2, "\t-v      : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h      : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Gla2Fla( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Gla2Fla(): There is no AIG.\n" );
+        return 0;
+    }
+    if ( pAbc->pGia->vGateClasses == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Gla2Fla(): There is no gate-level abstraction is defined.\n" );
+        return 0;
+    }
+    Vec_IntFreeP( &pAbc->pGia->vFlopClasses );
+    pAbc->pGia->vFlopClasses = Gia_GlaConvertToFla( pAbc->pGia, pAbc->pGia->vGateClasses );
+    Vec_IntFreeP( &pAbc->pGia->vGateClasses );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: &gla_fla [-vh]\n" );
+    Abc_Print( -2, "\t          maps gate-level into flop-level abstraction\n" );
+    Abc_Print( -2, "\t-v      : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h      : print the command usage\n");
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandAbc9Test( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+//    Gia_Man_t * pTemp = NULL;
+    int c, fVerbose = 0;
+    int nFrames = 5;
+    int fSwitch = 0;
+    int nWords = 1000;
+    int nProcs = 2;
+//    extern Gia_Man_t * Gia_VtaTest( Gia_Man_t * p );
+//    extern int Gia_ManSuppSizeTest( Gia_Man_t * p );
+//    extern void Gia_VtaTest( Gia_Man_t * p, int nFramesStart, int nFramesMax, int nConfMax, int nTimeMax, int fVerbose );
+//    extern void Gia_IsoTest( Gia_Man_t * p, int fVerbose );
+//    extern void Ga2_ManComputeTest( Gia_Man_t * p );
+//    extern void Bmc_CexTest( Gia_Man_t * p, Abc_Cex_t * pCex, int fVerbose );
+//    extern void Gia_IsoTest( Gia_Man_t * p, Abc_Cex_t * pCex, int fVerbose );
+//    extern void Unr_ManTest( Gia_Man_t * pGia, int nFrames );
+//    extern int Gia_ManVerify( Gia_Man_t * pGia );
+//    extern Gia_Man_t * Gia_ManOptimizeRing( Gia_Man_t * p );
+//    extern void Gia_ManCollectSeqTest( Gia_Man_t * p );
+//    extern Gia_Man_t * Gia_SweeperFraigTest( Gia_Man_t * p, int nWords, int nConfs, int fVerbose );
+//    extern Gia_Man_t * Bmc_CexDepthTest( Gia_Man_t * p, Abc_Cex_t * pCex, int nFrames, int fVerbose );
+//    extern Gia_Man_t * Bmc_CexTarget( Gia_Man_t * p, int nFrames );
+//    extern void Gia_ManMuxProfiling( Gia_Man_t * p );
+//    extern Gia_Man_t * Mig_ManTest( Gia_Man_t * pGia );
+//    extern Gia_Man_t * Gia_ManInterTest( Gia_Man_t * p );
+//    extern Gia_Man_t * Llb_ReachableStatesGia( Gia_Man_t * p );
+//    extern Gia_Man_t * Unm_ManTest( Gia_Man_t * pGia );
+//    extern void Agi_ManTest( Gia_Man_t * pGia );
+//    extern void Gia_ManCheckFalseTest( Gia_Man_t * p, int nSlackMax );
+//    extern void Gia_ParTest( Gia_Man_t * p, int nWords, int nProcs );
+//    extern void Gia_ManTisTest( Gia_Man_t * pInit );
+    extern void Gia_Iso3Test( Gia_Man_t * p );
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "WPFsvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nWords = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nWords < 0 )
+                goto usage;
+            break;
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nProcs = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nProcs < 0 )
+                goto usage;
+            break;
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nFrames = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nFrames < 0 )
+                goto usage;
+            break;
+        case 's':
+            fSwitch ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Test(): There is no AIG.\n" );
+        return 1;
+    }
+/*
+    if ( pAbc->pCex == NULL )
+    {
+        Abc_Print( -1, "Abc_CommandAbc9Test(): There is no CEX.\n" );
+        return 1;
+    }
+*/
+//    Gia_ManFrontTest( pAbc->pGia );
+//    Gia_ManReduceConst( pAbc->pGia, 1 );
+//    Sat_ManTest( pAbc->pGia, Gia_ManCo(pAbc->pGia, 0), 0 );
+//    Gia_ManTestDistance( pAbc->pGia );
+//    Gia_SatSolveTest( pAbc->pGia );
+//    For_ManExperiment( pAbc->pGia, 20, 1, 1 );
+//    Gia_ManUnrollSpecial( pAbc->pGia, 5, 100, 1 );
+//    pAbc->pGia = Gia_ManDupSelf( pTemp = pAbc->pGia );
+//    pAbc->pGia = Gia_ManRemoveEnables( pTemp = pAbc->pGia );
+//    Cbs_ManSolveTest( pAbc->pGia );
+//    pAbc->pGia = Gia_VtaTest( pTemp = pAbc->pGia );
+//    Gia_ManStopP( &pTemp );
+//    Gia_ManSuppSizeTest( pAbc->pGia );
+//    Gia_VtaTest( pAbc->pGia, 10, 100000, 0, 0, 1 );
+//    Gia_IsoTest( pAbc->pGia, fVerbose );
+//    Ga2_ManComputeTest( pAbc->pGia );
+//    Bmc_CexTest( pAbc->pGia, pAbc->pCex, fVerbose );
+//    Gia_IsoTest( pAbc->pGia, pAbc->pCex, 0 );
+//    Unr_ManTest( pAbc->pGia, nFrames );
+//    Gia_ManVerifyWithBoxes( pAbc->pGia );
+//    Gia_ManCollectSeqTest( pAbc->pGia );
+//    pTemp = Gia_ManOptimizeRing( pAbc->pGia );
+//    pTemp = Gia_SweeperFraigTest( pAbc->pGia, 4, 1000, 0 );
+//    Abc_FrameUpdateGia( pAbc, pTemp );
+//    pTemp = Bmc_CexDepthTest( pAbc->pGia, pAbc->pCex, nFrames, fVerbose );
+//    pTemp = Bmc_CexTarget( pAbc->pGia, nFrames );
+//    Abc_FrameUpdateGia( pAbc, pTemp );
+//    Gia_ManMuxProfiling( pAbc->pGia );
+//    pTemp = Mig_ManTest( pAbc->pGia );
+//    Abc_FrameUpdateGia( pAbc, pTemp );
+//    pTemp = Gia_ManInterTest( pAbc->pGia );
+//    Abc_FrameUpdateGia( pAbc, pTemp );
+//    pTemp = Llb_ReachableStatesGia( pAbc->pGia );
+//    Abc_FrameUpdateGia( pAbc, pTemp );
+//    Unm_ManTest( pAbc->pGia );
+//    Agi_ManTest( pAbc->pGia );
+//    Gia_ManResubTest( pAbc->pGia );
+//    Jf_ManTestCnf( pAbc->pGia );
+//    Gia_ManCheckFalseTest( pAbc->pGia, nFrames );
+//    Gia_ParTest( pAbc->pGia, nWords, nProcs );
+    Gia_Iso3Test( pAbc->pGia );
+//    printf( "\nThis command is currently disabled.\n\n" );
+
+    return 0;
+usage:
+    Abc_Print( -2, "usage: &test [-FW num] [-svh]\n" );
+    Abc_Print( -2, "\t        testing various procedures\n" );
+    Abc_Print( -2, "\t-F num: the number of timeframes [default = %d]\n", nFrames );
+    Abc_Print( -2, "\t-W num: the number of machine words [default = %d]\n", nWords );
+    Abc_Print( -2, "\t-s    : toggle enable (yes) vs. disable (no) [default = %s]\n", fSwitch? "yes": "no" );
+    Abc_Print( -2, "\t-v    : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "abciUnfold2.c"
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/base/abci/abcAttach.c b/abc-build/src/base/abci/abcAttach.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcAttach.c
@@ -0,0 +1,409 @@
+/**CFile****************************************************************
+
+  FileName    [abcAttach.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Attaches the library gates to the current network.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcAttach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/main.h"
+#include "map/mio/mio.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+#define    ATTACH_FULL             (~((unsigned)0))
+#define    ATTACH_MASK(n)         ((~((unsigned)0)) >> (32-(n)))
+
+static void Abc_AttachSetupTruthTables( unsigned uTruths[][2] );
+static void Abc_AttachComputeTruth( char * pSop, unsigned uTruthsIn[][2], unsigned * uTruthNode );
+static Mio_Gate_t * Abc_AttachFind( Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned * uTruthNode, int * Perm );
+static int Abc_AttachCompare( unsigned ** puTruthGates, int nGates, unsigned * uTruthNode );
+static int Abc_NodeAttach( Abc_Obj_t * pNode, Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned uTruths[][2] );
+static void Abc_TruthPermute( char * pPerm, int nVars, unsigned * uTruthNode, unsigned * uTruthPerm );
+
+static char ** s_pPerms = NULL;
+static int s_nPerms;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Attaches gates from the current library to the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkAttach( Abc_Ntk_t * pNtk )
+{
+    Mio_Library_t * pGenlib;
+    unsigned ** puTruthGates;
+    unsigned uTruths[6][2];
+    Abc_Obj_t * pNode;
+    Mio_Gate_t ** ppGates;
+    int nGates, nFanins, i;
+
+    assert( Abc_NtkIsSopLogic(pNtk) );
+
+    // check that the library is available
+    pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen();
+    if ( pGenlib == NULL )
+    {
+        printf( "The current library is not available.\n" );
+        return 0;
+    }
+
+    // start the truth tables
+    Abc_AttachSetupTruthTables( uTruths );
+    
+    // collect all the gates
+    ppGates = Mio_CollectRoots( pGenlib, 6, (float)1.0e+20, 1, &nGates, 0 );
+
+    // derive the gate truth tables
+    puTruthGates    = ABC_ALLOC( unsigned *, nGates );
+    puTruthGates[0] = ABC_ALLOC( unsigned, 2 * nGates );
+    for ( i = 1; i < nGates; i++ )
+        puTruthGates[i] = puTruthGates[i-1] + 2;
+    for ( i = 0; i < nGates; i++ )
+        Mio_DeriveTruthTable( ppGates[i], uTruths, Mio_GateReadPinNum(ppGates[i]), 6, puTruthGates[i] );
+
+    // assign the gates to pNode->pCopy
+    Abc_NtkCleanCopy( pNtk );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        nFanins = Abc_ObjFaninNum(pNode);
+        if ( nFanins == 0 )
+        {
+            if ( Abc_SopIsConst1((char *)pNode->pData) )
+                pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadConst1(pGenlib);
+            else
+                pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadConst0(pGenlib);
+        }
+        else if ( nFanins == 1 )
+        {
+            if ( Abc_SopIsBuf((char *)pNode->pData) )
+                pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadBuf(pGenlib);
+            else
+                pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadInv(pGenlib);
+        }
+        else if ( nFanins > 6 )
+        {
+            printf( "Cannot attach gate with more than 6 inputs to node %s.\n", Abc_ObjName(pNode) );
+            ABC_FREE( puTruthGates[0] );
+            ABC_FREE( puTruthGates );
+            ABC_FREE( ppGates );
+            return 0;
+        }
+        else if ( !Abc_NodeAttach( pNode, ppGates, puTruthGates, nGates, uTruths ) )
+        {
+            printf( "Could not attach the library gate to node %s.\n", Abc_ObjName(pNode) );
+            ABC_FREE( puTruthGates[0] );
+            ABC_FREE( puTruthGates );
+            ABC_FREE( ppGates );
+            return 0;
+        }
+    }
+    ABC_FREE( puTruthGates[0] );
+    ABC_FREE( puTruthGates );
+    ABC_FREE( ppGates );
+    ABC_FREE( s_pPerms );
+
+    // perform the final transformation
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        if ( pNode->pCopy == NULL )
+        {
+            printf( "Some elementary gates (constant, buffer, or inverter) are missing in the library.\n" );
+            return 0;
+        }
+    }
+
+    // replace SOP representation by the gate representation
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        pNode->pData = pNode->pCopy, pNode->pCopy = NULL;
+    pNtk->ntkFunc = ABC_FUNC_MAP;
+    Extra_MmFlexStop( (Extra_MmFlex_t *)pNtk->pManFunc );
+    pNtk->pManFunc = pGenlib;
+
+    printf( "Library gates are successfully attached to the nodes.\n" );
+
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtk ) )
+    {
+        printf( "Abc_NtkAttach: The network check has failed.\n" );
+        return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeAttach( Abc_Obj_t * pNode, Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned uTruths[][2] )
+{
+    int Perm[10];
+    int pTempInts[10];
+    unsigned uTruthNode[2];
+    Abc_Obj_t * pFanin;
+    Mio_Gate_t * pGate;
+    int nFanins, i;
+
+    // compute the node's truth table
+    Abc_AttachComputeTruth( (char *)pNode->pData, uTruths, uTruthNode );
+    // find the matching gate and permutation
+    pGate = Abc_AttachFind( ppGates, puTruthGates, nGates, uTruthNode, Perm );
+    if ( pGate == NULL )
+        return 0;
+    // permute the fanins
+    nFanins = Abc_ObjFaninNum(pNode);
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        pTempInts[i] = pFanin->Id;
+    for ( i = 0; i < nFanins; i++ )
+        pNode->vFanins.pArray[Perm[i]] = pTempInts[i];
+    // set the gate
+    pNode->pCopy = (Abc_Obj_t *)pGate;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets up the truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AttachSetupTruthTables( unsigned uTruths[][2] )
+{
+    int m, v;
+    for ( v = 0; v < 5; v++ )
+        uTruths[v][0] = 0;
+    // set up the truth tables
+    for ( m = 0; m < 32; m++ )
+        for ( v = 0; v < 5; v++ )
+            if ( m & (1 << v) )
+                uTruths[v][0] |= (1 << m);
+    // make adjustments for the case of 6 variables
+    for ( v = 0; v < 5; v++ )
+        uTruths[v][1] = uTruths[v][0];
+    uTruths[5][0] = 0;
+    uTruths[5][1] = ATTACH_FULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the truth table of the node's cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_AttachComputeTruth( char * pSop, unsigned uTruthsIn[][2], unsigned * uTruthRes )
+{
+//    Mvc_Cube_t * pCube;
+    unsigned uSignCube[2];
+    int Value;
+//    int nInputs = pCover->nBits/2;
+    int nInputs = 6;
+    int nFanins = Abc_SopGetVarNum(pSop);
+    char * pCube;
+    int k;
+
+    // make sure that the number of input truth tables in equal to the number of gate inputs
+    assert( nInputs < 7 );
+
+    // clean the resulting truth table
+    uTruthRes[0] = 0;
+    uTruthRes[1] = 0;
+    if ( nInputs < 6 )
+    {
+        // consider the case when only one unsigned can be used
+//        Mvc_CoverForEachCube( pCover, pCube )
+        Abc_SopForEachCube( pSop, nFanins, pCube )
+        {
+            uSignCube[0] = ATTACH_FULL;
+//            Mvc_CubeForEachVarValue( pCover, pCube, Var, Value )
+            Abc_CubeForEachVar( pCube, Value, k )
+            {
+                if ( Value == '0' )
+                    uSignCube[0] &= ~uTruthsIn[k][0];
+                else if ( Value == '1' )
+                    uSignCube[0] &=  uTruthsIn[k][0];
+            }
+            uTruthRes[0] |= uSignCube[0];
+        }
+        if ( Abc_SopGetPhase(pSop) == 0 )
+            uTruthRes[0] = ~uTruthRes[0];
+        if ( nInputs < 5 )
+            uTruthRes[0] &= ATTACH_MASK(1<<nInputs);
+    }
+    else
+    {
+        // consider the case when two unsigneds should be used
+//        Mvc_CoverForEachCube( pCover, pCube )
+        Abc_SopForEachCube( pSop, nFanins, pCube )
+        {
+            uSignCube[0] = ATTACH_FULL;
+            uSignCube[1] = ATTACH_FULL;
+//            Mvc_CubeForEachVarValue( pCover, pCube, Var, Value )
+            Abc_CubeForEachVar( pCube, Value, k )
+            {
+                if ( Value == '0' )
+                {
+                    uSignCube[0] &= ~uTruthsIn[k][0];
+                    uSignCube[1] &= ~uTruthsIn[k][1];
+                }
+                else if ( Value == '1' )
+                {
+                    uSignCube[0] &=  uTruthsIn[k][0];
+                    uSignCube[1] &=  uTruthsIn[k][1];
+                }
+            }
+            uTruthRes[0] |= uSignCube[0];
+            uTruthRes[1] |= uSignCube[1];
+        }
+
+        // complement if the SOP is complemented
+        if ( Abc_SopGetPhase(pSop) == 0 )
+        {
+            uTruthRes[0] = ~uTruthRes[0];
+            uTruthRes[1] = ~uTruthRes[1];
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the gate by truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mio_Gate_t * Abc_AttachFind( Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned * uTruthNode, int * Perm )
+{
+    unsigned uTruthPerm[2];
+    int i, v, iNum;
+
+    // try the gates without permutation
+    if ( (iNum = Abc_AttachCompare( puTruthGates, nGates, uTruthNode )) >= 0 )
+    {
+        for ( v = 0; v < 6; v++ )
+            Perm[v] = v;
+        return ppGates[iNum];
+    }
+    // get permutations
+    if ( s_pPerms == NULL )
+    {
+        s_pPerms = Extra_Permutations( 6 );
+        s_nPerms = Extra_Factorial( 6 );
+    }
+    // try permutations
+    for ( i = 0; i < s_nPerms; i++ )
+    {
+        Abc_TruthPermute( s_pPerms[i], 6, uTruthNode, uTruthPerm );
+        if ( (iNum = Abc_AttachCompare( puTruthGates, nGates, uTruthPerm )) >= 0 )
+        {
+            for ( v = 0; v < 6; v++ )
+                Perm[v] = (int)s_pPerms[i][v];
+            return ppGates[iNum];
+        }
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the gate by truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_AttachCompare( unsigned ** puTruthGates, int nGates, unsigned * uTruthNode )
+{
+    int i;
+    for ( i = 0; i < nGates; i++ )
+        if ( puTruthGates[i][0] == uTruthNode[0] && puTruthGates[i][1] == uTruthNode[1] )
+            return i;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Permutes the 6-input truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_TruthPermute( char * pPerm, int nVars, unsigned * uTruthNode, unsigned * uTruthPerm )
+{
+    int nMints, iMintPerm, iMint, v;
+    uTruthPerm[0] = uTruthPerm[1] = 0;
+    nMints = (1 << nVars);
+    for ( iMint = 0; iMint < nMints; iMint++ )
+    {
+        if ( (uTruthNode[iMint>>5] & (1 << (iMint&31))) == 0 )
+            continue;
+        iMintPerm = 0;
+        for ( v = 0; v < nVars; v++ )
+            if ( iMint & (1 << v) )
+                iMintPerm |= (1 << pPerm[v]);
+        uTruthPerm[iMintPerm>>5] |= (1 << (iMintPerm&31));     
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcAuto.c b/abc-build/src/base/abci/abcAuto.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcAuto.c
@@ -0,0 +1,245 @@
+/**CFile****************************************************************
+
+  FileName    [abcAuto.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Computation of autosymmetries.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcAuto.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkAutoPrintAll( DdManager * dd, int nInputs, DdNode * pbOutputs[], int nOutputs, char * pInputNames[], char * pOutputNames[], int fNaive );
+static void Abc_NtkAutoPrintOne( DdManager * dd, int nInputs, DdNode * pbOutputs[], int Output, char * pInputNames[], char * pOutputNames[], int fNaive );
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose )
+{
+	DdManager * dd;         // the BDD manager used to hold shared BDDs
+	DdNode ** pbGlobal;     // temporary storage for global BDDs
+	char ** pInputNames;    // pointers to the CI names
+	char ** pOutputNames;   // pointers to the CO names
+	int nOutputs, nInputs, i;
+    Vec_Ptr_t * vFuncsGlob;
+    Abc_Obj_t * pObj;
+
+    // compute the global BDDs
+    if ( Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, fVerbose) == NULL )
+        return;
+
+    // get information about the network
+    nInputs  = Abc_NtkCiNum(pNtk);
+    nOutputs = Abc_NtkCoNum(pNtk);
+//    dd       = pNtk->pManGlob;
+    dd = (DdManager *)Abc_NtkGlobalBddMan( pNtk );
+
+    // complement the global functions
+    vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) );
+    pbGlobal = (DdNode **)Vec_PtrArray( vFuncsGlob );
+
+    // get the network names
+    pInputNames = Abc_NtkCollectCioNames( pNtk, 0 );
+    pOutputNames = Abc_NtkCollectCioNames( pNtk, 1 );
+
+    // print the size of the BDDs
+    if ( fVerbose )
+        printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+
+	// allocate additional variables
+	for ( i = 0; i < nInputs; i++ )
+		Cudd_bddNewVar( dd );
+	assert( Cudd_ReadSize(dd) == 2 * nInputs );
+
+	// create ZDD variables in the manager
+	Cudd_zddVarsFromBddVars( dd, 2 );
+
+	// perform the analysis of the primary output functions for auto-symmetry
+	if ( Output == -1 )
+		Abc_NtkAutoPrintAll( dd, nInputs, pbGlobal, nOutputs, pInputNames, pOutputNames, fNaive );
+	else
+		Abc_NtkAutoPrintOne( dd, nInputs, pbGlobal, Output, pInputNames, pOutputNames, fNaive );
+
+	// deref the PO functions
+//    Abc_NtkFreeGlobalBdds( pNtk );
+	// stop the global BDD manager
+//    Extra_StopManager( pNtk->pManGlob );
+//    pNtk->pManGlob = NULL;
+    Abc_NtkFreeGlobalBdds( pNtk, 1 );
+    ABC_FREE( pInputNames );
+    ABC_FREE( pOutputNames );
+    Vec_PtrFree( vFuncsGlob );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkAutoPrintAll( DdManager * dd, int nInputs, DdNode * pbOutputs[], int nOutputs, char * pInputNames[], char * pOutputNames[], int fNaive )
+{
+	DdNode * bSpace1, * bSpace2, * bCanVars, * bReduced, * zEquations;
+	double nMints; 
+	int nSupp, SigCounter, o;
+
+	int nAutos;
+	int nAutoSyms;
+	int nAutoSymsMax;
+	int nAutoSymsMaxSupp;
+	int nAutoSymOuts;
+	int nSuppSizeMax;
+	abctime clk;
+	
+	nAutoSymOuts = 0;
+	nAutoSyms    = 0;
+	nAutoSymsMax = 0;
+	nAutoSymsMaxSupp = 0;
+	nSuppSizeMax = 0;
+	clk = Abc_Clock();
+
+	SigCounter = 0;
+	for ( o = 0; o < nOutputs; o++ )
+	{
+//		bSpace1  = Extra_bddSpaceFromFunctionFast( dd, pbOutputs[o] );           Cudd_Ref( bSpace1 );
+		bSpace1  = Extra_bddSpaceFromFunction( dd, pbOutputs[o], pbOutputs[o] ); Cudd_Ref( bSpace1 );
+		bCanVars = Extra_bddSpaceCanonVars( dd, bSpace1 );                       Cudd_Ref( bCanVars );
+		bReduced = Extra_bddSpaceReduce( dd, pbOutputs[o], bCanVars );           Cudd_Ref( bReduced );
+		zEquations = Extra_bddSpaceEquations( dd, bSpace1 );                     Cudd_Ref( zEquations );
+
+		nSupp  = Cudd_SupportSize( dd, bSpace1 );
+		nMints = Cudd_CountMinterm( dd, bSpace1, nSupp );
+		nAutos = Extra_Base2LogDouble(nMints);
+		printf( "Output #%3d: Inputs = %2d. AutoK = %2d.\n", o, nSupp, nAutos );
+
+		if ( nAutos > 0 )
+		{
+			nAutoSymOuts++;
+			nAutoSyms += nAutos;
+			if ( nAutoSymsMax < nAutos )
+			{
+				nAutoSymsMax = nAutos;
+				nAutoSymsMaxSupp = nSupp;
+			}
+		}
+		if ( nSuppSizeMax < nSupp )
+			nSuppSizeMax = nSupp;
+
+
+//ABC_PRB( dd, bCanVars );
+//ABC_PRB( dd, bReduced );
+//Cudd_PrintMinterm( dd, bReduced );
+//printf( "The equations are:\n" );
+//Cudd_zddPrintCover( dd, zEquations );
+//printf( "\n" );
+//fflush( stdout );
+
+		bSpace2 = Extra_bddSpaceFromMatrixPos( dd, zEquations );   Cudd_Ref( bSpace2 );
+//ABC_PRB( dd, bSpace1 );
+//ABC_PRB( dd, bSpace2 );
+		if ( bSpace1 != bSpace2 )
+			printf( "Spaces are NOT EQUAL!\n" );
+//		else
+//			printf( "Spaces are equal.\n" );
+	
+		Cudd_RecursiveDeref( dd, bSpace1 );
+		Cudd_RecursiveDeref( dd, bSpace2 );
+		Cudd_RecursiveDeref( dd, bCanVars );
+		Cudd_RecursiveDeref( dd, bReduced );
+		Cudd_RecursiveDerefZdd( dd, zEquations );
+	}
+
+	printf( "The cumulative statistics for all outputs:\n" );
+	printf( "Ins=%3d ",      nInputs );
+	printf( "InMax=%3d   ",  nSuppSizeMax );
+	printf( "Outs=%3d ",     nOutputs );
+	printf( "Auto=%3d   ",   nAutoSymOuts );
+	printf( "SumK=%3d ",     nAutoSyms );
+	printf( "KMax=%2d ",     nAutoSymsMax );
+	printf( "Supp=%3d   ",   nAutoSymsMaxSupp );
+	printf( "Time=%4.2f ", (float)(Abc_Clock() - clk)/(float)(CLOCKS_PER_SEC) );
+	printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkAutoPrintOne( DdManager * dd, int nInputs, DdNode * pbOutputs[], int Output, char * pInputNames[], char * pOutputNames[], int fNaive )
+{
+	DdNode * bSpace1, * bCanVars, * bReduced, * zEquations;
+	double nMints; 
+	int nSupp, SigCounter;
+	int nAutos;
+
+	SigCounter = 0;
+	bSpace1  = Extra_bddSpaceFromFunctionFast( dd, pbOutputs[Output] );                Cudd_Ref( bSpace1 );
+//	bSpace1  = Extra_bddSpaceFromFunction( dd, pbOutputs[Output], pbOutputs[Output] ); Cudd_Ref( bSpace1 );
+	bCanVars = Extra_bddSpaceCanonVars( dd, bSpace1 );                                 Cudd_Ref( bCanVars );
+	bReduced = Extra_bddSpaceReduce( dd, pbOutputs[Output], bCanVars );                Cudd_Ref( bReduced );
+	zEquations = Extra_bddSpaceEquations( dd, bSpace1 );                               Cudd_Ref( zEquations );
+
+	nSupp  = Cudd_SupportSize( dd, bSpace1 );
+	nMints = Cudd_CountMinterm( dd, bSpace1, nSupp );
+	nAutos = Extra_Base2LogDouble(nMints);
+	printf( "Output #%3d: Inputs = %2d. AutoK = %2d.\n", Output, nSupp, nAutos );
+
+	Cudd_RecursiveDeref( dd, bSpace1 );
+	Cudd_RecursiveDeref( dd, bCanVars );
+	Cudd_RecursiveDeref( dd, bReduced );
+	Cudd_RecursiveDerefZdd( dd, zEquations );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcBalance.c b/abc-build/src/base/abci/abcBalance.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcBalance.c
@@ -0,0 +1,629 @@
+/**CFile****************************************************************
+
+  FileName    [abcBalance.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Performs global balancing of the AIG by the number of levels.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcBalance.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+static void        Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, int fDuplicate, int fSelective, int fUpdateLevel );
+static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, int fDuplicate, int fSelective, int fUpdateLevel );
+static Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vSuper, int Level, int fDuplicate, int fSelective );
+static int         Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, int fFirst, int fDuplicate, int fSelective );
+static void        Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk );
+static Vec_Ptr_t * Abc_NodeBalanceConeExor( Abc_Obj_t * pNode );
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Balances the AIG network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, int fDuplicate, int fSelective, int fUpdateLevel )
+{
+//    extern void Abc_NtkHaigTranfer( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew );
+    Abc_Ntk_t * pNtkAig;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // compute the required times
+    if ( fSelective )
+    {
+        Abc_NtkStartReverseLevels( pNtk, 0 );
+        Abc_NtkMarkCriticalNodes( pNtk );
+    }
+    // perform balancing
+    pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+    // transfer HAIG
+//    Abc_NtkHaigTranfer( pNtk, pNtkAig );
+    // perform balancing
+    Abc_NtkBalancePerform( pNtk, pNtkAig, fDuplicate, fSelective, fUpdateLevel );
+    Abc_NtkFinalize( pNtk, pNtkAig );
+    Abc_AigCleanup( (Abc_Aig_t *)pNtkAig->pManFunc );
+    // undo the required times
+    if ( fSelective )
+    {
+        Abc_NtkStopReverseLevels( pNtk );
+        Abc_NtkCleanMarkA( pNtk );
+    }
+    if ( pNtk->pExdc )
+        pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pNtkAig ) )
+    {
+        printf( "Abc_NtkBalance: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkAig );
+        return NULL;
+    }
+//Abc_NtkPrintCiLevels( pNtkAig );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Balances the AIG network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, int fDuplicate, int fSelective, int fUpdateLevel )
+{
+    ProgressBar * pProgress;
+    Vec_Vec_t * vStorage;
+    Abc_Obj_t * pNode;
+    int i;
+    // transfer level
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        pNode->pCopy->Level = pNode->Level;
+    // set the level of PIs of AIG according to the arrival times of the old network
+    Abc_NtkSetNodeLevelsArrival( pNtk );
+    // allocate temporary storage for supergates
+    vStorage = Vec_VecStart( 10 );
+    // perform balancing of POs
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+    if ( pNtk->nBarBufs == 0 )
+    {
+        Abc_NtkForEachCo( pNtk, pNode, i )
+        {
+            Extra_ProgressBarUpdate( pProgress, i, NULL );
+            Abc_NodeBalance_rec( pNtkAig, Abc_ObjFanin0(pNode), vStorage, 0, fDuplicate, fSelective, fUpdateLevel );
+        }
+    }
+    else
+    {
+        Abc_NtkForEachLiPo( pNtk, pNode, i )
+        {
+            Extra_ProgressBarUpdate( pProgress, i, NULL );
+            Abc_NodeBalance_rec( pNtkAig, Abc_ObjFanin0(pNode), vStorage, 0, fDuplicate, fSelective, fUpdateLevel );
+            if ( i < pNtk->nBarBufs )
+                Abc_ObjFanout0(Abc_ObjFanout0(pNode))->Level = Abc_ObjFanin0(pNode)->Level;
+        }
+    }
+    Extra_ProgressBarStop( pProgress );
+    Vec_VecFree( vStorage );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the left bound on the next candidate to be paired.]
+
+  Description [The nodes in the array are in the decreasing order of levels. 
+  The last node in the array has the smallest level. By default it would be paired 
+  with the next node on the left. However, it may be possible to pair it with some
+  other node on the left, in such a way that the new node is shared. This procedure
+  finds the index of the left-most node, which can be paired with the last node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeBalanceFindLeft( Vec_Ptr_t * vSuper )
+{
+    Abc_Obj_t * pNodeRight, * pNodeLeft;
+    int Current;
+    // if two or less nodes, pair with the first
+    if ( Vec_PtrSize(vSuper) < 3 )
+        return 0;
+    // set the pointer to the one before the last
+    Current = Vec_PtrSize(vSuper) - 2;
+    pNodeRight = (Abc_Obj_t *)Vec_PtrEntry( vSuper, Current );
+    // go through the nodes to the left of this one
+    for ( Current--; Current >= 0; Current-- )
+    {
+        // get the next node on the left
+        pNodeLeft = (Abc_Obj_t *)Vec_PtrEntry( vSuper, Current );
+        // if the level of this node is different, quit the loop
+        if ( Abc_ObjRegular(pNodeLeft)->Level != Abc_ObjRegular(pNodeRight)->Level )
+            break;
+    }
+    Current++;    
+    // get the node, for which the equality holds
+    pNodeLeft = (Abc_Obj_t *)Vec_PtrEntry( vSuper, Current );
+    assert( Abc_ObjRegular(pNodeLeft)->Level == Abc_ObjRegular(pNodeRight)->Level );
+    return Current;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Moves closer to the end the node that is best for sharing.]
+
+  Description [If there is no node with sharing, randomly chooses one of 
+  the legal nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeBalancePermute( Abc_Ntk_t * pNtkNew, Vec_Ptr_t * vSuper, int LeftBound )
+{
+    Abc_Obj_t * pNode1, * pNode2, * pNode3;
+    int RightBound, i;
+    // get the right bound
+    RightBound = Vec_PtrSize(vSuper) - 2;
+    assert( LeftBound <= RightBound );
+    if ( LeftBound == RightBound )
+        return;
+    // get the two last nodes
+    pNode1 = (Abc_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 );
+    pNode2 = (Abc_Obj_t *)Vec_PtrEntry( vSuper, RightBound     );
+    // find the first node that can be shared
+    for ( i = RightBound; i >= LeftBound; i-- )
+    {
+        pNode3 = (Abc_Obj_t *)Vec_PtrEntry( vSuper, i );
+        if ( Abc_AigAndLookup( (Abc_Aig_t *)pNtkNew->pManFunc, pNode1, pNode3 ) )
+        {
+            if ( pNode3 == pNode2 )
+                return;
+            Vec_PtrWriteEntry( vSuper, i,          pNode2 );
+            Vec_PtrWriteEntry( vSuper, RightBound, pNode3 );
+            return;
+        }
+    }
+/*
+    // we did not find the node to share, randomize choice
+    {
+        int Choice = rand() % (RightBound - LeftBound + 1);
+        pNode3 = Vec_PtrEntry( vSuper, LeftBound + Choice );
+        if ( pNode3 == pNode2 )
+            return;
+        Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pNode2 );
+        Vec_PtrWriteEntry( vSuper, RightBound,         pNode3 );
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Rebalances the multi-input node rooted at pNodeOld.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_Vec_t * vStorage, int Level, int fDuplicate, int fSelective, int fUpdateLevel )
+{
+    Abc_Aig_t * pMan = (Abc_Aig_t *)pNtkNew->pManFunc;
+    Abc_Obj_t * pNodeNew, * pNode1, * pNode2;
+    Vec_Ptr_t * vSuper;
+    int i, LeftBound;
+    assert( !Abc_ObjIsComplement(pNodeOld) );
+    // return if the result if known
+    if ( pNodeOld->pCopy )
+        return pNodeOld->pCopy;
+    assert( Abc_ObjIsNode(pNodeOld) );
+    // get the implication supergate
+//    Abc_NodeBalanceConeExor( pNodeOld );
+    vSuper = Abc_NodeBalanceCone( pNodeOld, vStorage, Level, fDuplicate, fSelective );
+    if ( vSuper->nSize == 0 )
+    { // it means that the supergate contains two nodes in the opposite polarity
+        pNodeOld->pCopy = Abc_ObjNot(Abc_AigConst1(pNtkNew));
+        return pNodeOld->pCopy;
+    }
+    // for each old node, derive the new well-balanced node
+    for ( i = 0; i < vSuper->nSize; i++ )
+    {
+        pNodeNew = Abc_NodeBalance_rec( pNtkNew, Abc_ObjRegular((Abc_Obj_t *)vSuper->pArray[i]), vStorage, Level + 1, fDuplicate, fSelective, fUpdateLevel );
+        vSuper->pArray[i] = Abc_ObjNotCond( pNodeNew, Abc_ObjIsComplement((Abc_Obj_t *)vSuper->pArray[i]) );
+    }
+    if ( vSuper->nSize < 2 )
+        printf( "BUG!\n" );
+    // sort the new nodes by level in the decreasing order
+    Vec_PtrSort( vSuper, (int (*)(void))Abc_NodeCompareLevelsDecrease );
+    // balance the nodes
+    assert( vSuper->nSize > 1 );
+    while ( vSuper->nSize > 1 )
+    {
+        // find the left bound on the node to be paired
+        LeftBound = (!fUpdateLevel)? 0 : Abc_NodeBalanceFindLeft( vSuper );
+        // find the node that can be shared (if no such node, randomize choice)
+        Abc_NodeBalancePermute( pNtkNew, vSuper, LeftBound );
+        // pull out the last two nodes
+        pNode1 = (Abc_Obj_t *)Vec_PtrPop(vSuper);
+        pNode2 = (Abc_Obj_t *)Vec_PtrPop(vSuper);
+        Abc_VecObjPushUniqueOrderByLevel( vSuper, Abc_AigAnd(pMan, pNode1, pNode2) );
+    }
+    // make sure the balanced node is not assigned
+    assert( pNodeOld->pCopy == NULL );
+    // mark the old node with the new node
+    pNodeOld->pCopy = (Abc_Obj_t *)vSuper->pArray[0];
+    vSuper->nSize = 0;
+//    if ( Abc_ObjRegular(pNodeOld->pCopy) == Abc_AigConst1(pNtkNew) )
+//        printf( "Constant node\n" );
+//    assert( pNodeOld->Level >= Abc_ObjRegular(pNodeOld->pCopy)->Level );
+    return pNodeOld->pCopy;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the nodes in the cone delimited by fMarkA==1.]
+
+  Description [Returns -1 if the AND-cone has the same node in both polarities.
+  Returns 1 if the AND-cone has the same node in the same polarity. Returns 0
+  if the AND-cone has no repeated nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, int fDuplicate, int fSelective )
+{
+    Vec_Ptr_t * vNodes;
+    int RetValue, i;
+    assert( !Abc_ObjIsComplement(pNode) );
+    // extend the storage
+    if ( Vec_VecSize( vStorage ) <= Level )
+        Vec_VecPush( vStorage, Level, 0 );
+    // get the temporary array of nodes
+    vNodes = Vec_VecEntry( vStorage, Level );
+    Vec_PtrClear( vNodes );
+    // collect the nodes in the implication supergate
+    RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, fDuplicate, fSelective );
+    assert( vNodes->nSize > 1 );
+    // unmark the visited nodes
+    for ( i = 0; i < vNodes->nSize; i++ )
+        Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->fMarkB = 0;
+    // if we found the node and its complement in the same implication supergate, 
+    // return empty set of nodes (meaning that we should use constant-0 node)
+    if ( RetValue == -1 )
+        vNodes->nSize = 0;
+    return vNodes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the nodes in the cone delimited by fMarkA==1.]
+
+  Description [Returns -1 if the AND-cone has the same node in both polarities.
+  Returns 1 if the AND-cone has the same node in the same polarity. Returns 0
+  if the AND-cone has no repeated nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, int fFirst, int fDuplicate, int fSelective )
+{
+    int RetValue1, RetValue2, i;
+    // check if the node is visited
+    if ( Abc_ObjRegular(pNode)->fMarkB )
+    {
+        // check if the node occurs in the same polarity
+        for ( i = 0; i < vSuper->nSize; i++ )
+            if ( vSuper->pArray[i] == pNode )
+                return 1;
+        // check if the node is present in the opposite polarity
+        for ( i = 0; i < vSuper->nSize; i++ )
+            if ( vSuper->pArray[i] == Abc_ObjNot(pNode) )
+                return -1;
+        assert( 0 );
+        return 0;
+    }
+    // if the new node is complemented or a PI, another gate begins
+    if ( !fFirst && (Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || (!fDuplicate && !fSelective && (Abc_ObjFanoutNum(pNode) > 1)) || Vec_PtrSize(vSuper) > 10000) )
+    {
+        Vec_PtrPush( vSuper, pNode );
+        Abc_ObjRegular(pNode)->fMarkB = 1;
+        return 0;
+    }
+    assert( !Abc_ObjIsComplement(pNode) );
+    assert( Abc_ObjIsNode(pNode) );
+    // go through the branches
+    RetValue1 = Abc_NodeBalanceCone_rec( Abc_ObjChild0(pNode), vSuper, 0, fDuplicate, fSelective );
+    RetValue2 = Abc_NodeBalanceCone_rec( Abc_ObjChild1(pNode), vSuper, 0, fDuplicate, fSelective );
+    if ( RetValue1 == -1 || RetValue2 == -1 )
+        return -1;
+    // return 1 if at least one branch has a duplicate
+    return RetValue1 || RetValue2;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeBalanceConeExor_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, int fFirst )
+{
+    int RetValue1, RetValue2, i;
+    // check if the node occurs in the same polarity
+    for ( i = 0; i < vSuper->nSize; i++ )
+        if ( vSuper->pArray[i] == pNode )
+            return 1;
+    // if the new node is complemented or a PI, another gate begins
+    if ( !fFirst && (!pNode->fExor || !Abc_ObjIsNode(pNode)) )
+    {
+        Vec_PtrPush( vSuper, pNode );
+        return 0;
+    }
+    assert( !Abc_ObjIsComplement(pNode) );
+    assert( Abc_ObjIsNode(pNode) );
+    assert( pNode->fExor );
+    // go through the branches
+    RetValue1 = Abc_NodeBalanceConeExor_rec( Abc_ObjFanin0(Abc_ObjFanin0(pNode)), vSuper, 0 );
+    RetValue2 = Abc_NodeBalanceConeExor_rec( Abc_ObjFanin1(Abc_ObjFanin0(pNode)), vSuper, 0 );
+    if ( RetValue1 == -1 || RetValue2 == -1 )
+        return -1;
+    // return 1 if at least one branch has a duplicate
+    return RetValue1 || RetValue2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NodeBalanceConeExor( Abc_Obj_t * pNode )
+{
+    Vec_Ptr_t * vSuper;
+    if ( !pNode->fExor )
+        return NULL;
+    vSuper = Vec_PtrAlloc( 10 );
+    Abc_NodeBalanceConeExor_rec( pNode, vSuper, 1 );
+    printf( "%d ", Vec_PtrSize(vSuper) );
+    Vec_PtrFree( vSuper );
+    return NULL;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the nodes in the implication supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NodeFindCone_rec( Abc_Obj_t * pNode )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNodeC, * pNodeT, * pNodeE;
+    int RetValue, i;
+    assert( !Abc_ObjIsComplement(pNode) );
+    if ( Abc_ObjIsCi(pNode) )
+        return NULL;
+    // start the new array
+    vNodes = Vec_PtrAlloc( 4 );
+    // if the node is the MUX collect its fanins
+    if ( Abc_NodeIsMuxType(pNode) )
+    {
+        pNodeC = Abc_NodeRecognizeMux( pNode, &pNodeT, &pNodeE );
+        Vec_PtrPush( vNodes, Abc_ObjRegular(pNodeC) );
+        Vec_PtrPushUnique( vNodes, Abc_ObjRegular(pNodeT) );
+        Vec_PtrPushUnique( vNodes, Abc_ObjRegular(pNodeE) );
+    }
+    else
+    {
+        // collect the nodes in the implication supergate
+        RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, 1, 0 );
+        assert( vNodes->nSize > 1 );
+        // unmark the visited nodes
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+            Abc_ObjRegular(pNode)->fMarkB = 0;
+        // if we found the node and its complement in the same implication supergate, 
+        // return empty set of nodes (meaning that we should use constant-0 node)
+        if ( RetValue == -1 )
+            vNodes->nSize = 0;
+    }
+    // call for the fanin
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        pNode = Abc_ObjRegular(pNode);
+        if ( pNode->pCopy )
+            continue;
+        pNode->pCopy = (Abc_Obj_t *)Abc_NodeFindCone_rec( pNode );
+    }
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Attaches the implication supergates to internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    Abc_NtkCleanCopy( pNtk );
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        pNode = Abc_ObjFanin0(pNode);
+        if ( pNode->pCopy )
+            continue;
+        pNode->pCopy = (Abc_Obj_t *)Abc_NodeFindCone_rec( pNode );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Attaches the implication supergates to internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        if ( pNode->pCopy )
+        {
+            Vec_PtrFree( (Vec_Ptr_t *)pNode->pCopy );
+            pNode->pCopy = NULL;
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute levels of implication supergates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkBalanceLevel_rec( Abc_Obj_t * pNode )
+{
+    Vec_Ptr_t * vSuper;
+    Abc_Obj_t * pFanin;
+    int i, LevelMax;
+    assert( !Abc_ObjIsComplement(pNode) );
+    if ( pNode->Level > 0 )
+        return pNode->Level;
+    if ( Abc_ObjIsCi(pNode) )
+        return 0;
+    vSuper = (Vec_Ptr_t *)pNode->pCopy;
+    assert( vSuper != NULL );
+    LevelMax = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vSuper, pFanin, i )
+    {
+        pFanin = Abc_ObjRegular(pFanin);
+        Abc_NtkBalanceLevel_rec(pFanin);
+        if ( LevelMax < (int)pFanin->Level )
+            LevelMax = pFanin->Level;
+    }
+    pNode->Level = LevelMax + 1;
+    return pNode->Level;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compute levels of implication supergates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkBalanceLevel( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    Abc_NtkForEachObj( pNtk, pNode, i )
+        pNode->Level = 0;
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        Abc_NtkBalanceLevel_rec( Abc_ObjFanin0(pNode) );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the nodes on the critical and near critical paths.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, Counter = 0;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        if ( Abc_ObjRequiredLevel(pNode) - pNode->Level <= 1 )
+            pNode->fMarkA = 1, Counter++;
+    printf( "The number of nodes on the critical paths = %6d  (%5.2f %%)\n", Counter, 100.0 * Counter / Abc_NtkNodeNum(pNtk) );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcBidec.c b/abc-build/src/base/abci/abcBidec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcBidec.c
@@ -0,0 +1,156 @@
+/**CFile****************************************************************
+
+  FileName    [abcBidec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Interface to bi-decomposition.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcBidec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "bool/bdc/bdc.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline Hop_Obj_t * Bdc_FunCopyHop( Bdc_Fun_t * pObj )  { return Hop_NotCond( (Hop_Obj_t *)Bdc_FuncCopy(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) );  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Resynthesizes nodes using bi-decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb )
+{
+    unsigned * pTruth;
+    Bdc_Fun_t * pFunc;
+    int nNodes, i;
+    assert( nVars <= 16 );
+    // derive truth table
+    pTruth = Hop_ManConvertAigToTruth( pHop, Hop_Regular(pRoot), nVars, vTruth, 0 );
+    if ( Hop_IsComplement(pRoot) )
+        Extra_TruthNot( pTruth, pTruth, nVars );
+    // perform power-aware decomposition
+    if ( dProb >= 0.0 )
+    {
+        float Prob = (float)2.0 * dProb * (1.0 - dProb);
+        assert( Prob >= 0.0 && Prob <= 0.5 );
+        if ( Prob >= 0.4 )
+        {
+            Extra_TruthNot( puCare, puCare, nVars );
+            if ( dProb > 0.5 ) // more 1s than 0s
+                Extra_TruthOr( pTruth, pTruth, puCare, nVars );
+            else
+                Extra_TruthSharp( pTruth, pTruth, puCare, nVars );
+            Extra_TruthNot( puCare, puCare, nVars );
+            // decompose truth table
+            Bdc_ManDecompose( p, pTruth, NULL, nVars, NULL, 1000 );
+        }
+        else
+        {
+            // decompose truth table
+            Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 );
+        }
+    }
+    else
+    {
+        // decompose truth table
+        Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 );
+    }
+    // convert back into HOP
+    Bdc_FuncSetCopy( Bdc_ManFunc( p, 0 ), Hop_ManConst1( pHop ) );
+    for ( i = 0; i < nVars; i++ )
+        Bdc_FuncSetCopy( Bdc_ManFunc( p, i+1 ), Hop_ManPi( pHop, i ) );
+    nNodes = Bdc_ManNodeNum(p);
+    for ( i = nVars + 1; i < nNodes; i++ )
+    {
+        pFunc = Bdc_ManFunc( p, i );
+        Bdc_FuncSetCopy( pFunc, Hop_And( pHop, Bdc_FunCopyHop(Bdc_FuncFanin0(pFunc)), Bdc_FunCopyHop(Bdc_FuncFanin1(pFunc)) ) );
+    }
+    return Bdc_FunCopyHop( Bdc_ManRoot(p) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resynthesizes nodes using bi-decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    Bdc_Par_t Pars = {0}, * pPars = &Pars;
+    Bdc_Man_t * p;
+    Abc_Obj_t * pObj;
+    Vec_Int_t * vTruth;
+    int i, nGainTotal = 0, nNodes1, nNodes2;
+    abctime clk = Abc_Clock();
+    assert( Abc_NtkIsLogic(pNtk) );
+    if ( !Abc_NtkToAig(pNtk) )
+        return;
+    pPars->nVarsMax = Abc_NtkGetFaninMax( pNtk );
+    pPars->fVerbose = fVerbose;
+    if ( pPars->nVarsMax > 15 )
+    {
+        if ( fVerbose )
+        printf( "Resynthesis is not performed for nodes with more than 15 inputs.\n" );
+        pPars->nVarsMax = 15;
+    }
+    vTruth = Vec_IntAlloc( 0 );
+    p = Bdc_ManAlloc( pPars );
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        if ( Abc_ObjFaninNum(pObj) > 15 )
+            continue;
+        nNodes1 = Hop_DagSize((Hop_Obj_t *)pObj->pData);
+        pObj->pData = Abc_NodeIfNodeResyn( p, (Hop_Man_t *)pNtk->pManFunc, (Hop_Obj_t *)pObj->pData, Abc_ObjFaninNum(pObj), vTruth, NULL, -1.0 );
+        nNodes2 = Hop_DagSize((Hop_Obj_t *)pObj->pData);
+        nGainTotal += nNodes1 - nNodes2;
+    }
+    Bdc_ManFree( p );
+    Vec_IntFree( vTruth );
+    if ( fVerbose )
+    {
+    printf( "Total gain in AIG nodes = %d.  ", nGainTotal );
+    ABC_PRT( "Total runtime", Abc_Clock() - clk );
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcBm.c b/abc-build/src/base/abci/abcBm.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcBm.c
@@ -0,0 +1,2049 @@
+/**CFile****************************************************************
+
+  FileName    [bm.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Boolean Matching package.]
+
+  Synopsis    [Check P-equivalence and PP-equivalence of two circuits.]
+
+  Author      [Hadi Katebi]
+  
+  Affiliation [University of Michigan]
+
+  Date        [Ver. 1.0. Started - January, 2009.]
+
+  Revision    [No revisions so far]
+
+  Comments    [This is the cleaned up version of the code I used for DATE 2010 publication.]              
+			  [If you have any question or if you find a bug, contact me at hadik@umich.edu.]
+			  [I don't guarantee that I can fix all the bugs, but I can definitely point you to 
+			   the right direction so you can fix the bugs yourself].
+
+  Debugging   [There are some part of the code that are commented out. Those parts mostly print
+               the contents of the data structures to the standard output. Un-comment them if you 
+			   find them useful for debugging.]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "opt/sim/sim.h"
+#include "sat/bsat/satSolver.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+int match1by1(Abc_Ntk_t * pNtk1, Vec_Ptr_t ** nodesInLevel1, Vec_Int_t ** iMatch1, Vec_Int_t ** iDep1, Vec_Int_t * matchedInputs1, int * iGroup1, Vec_Int_t ** oMatch1, int * oGroup1,
+			   Abc_Ntk_t * pNtk2, Vec_Ptr_t ** nodesInLevel2, Vec_Int_t ** iMatch2, Vec_Int_t ** iDep2, Vec_Int_t * matchedInputs2, int * iGroup2, Vec_Int_t ** oMatch2, int * oGroup2,
+			   Vec_Int_t * matchedOutputs1, Vec_Int_t * matchedOutputs2, Vec_Int_t * oMatchedGroups, Vec_Int_t * iNonSingleton, int ii, int idx);
+
+int Abc_NtkBmSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Vec_Ptr_t * iMatchPairs, Vec_Ptr_t * oMatchPairs, Vec_Int_t * mismatch, int mode);
+
+void getDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep)
+{	
+	Vec_Ptr_t * vSuppFun;
+	int i, j;	
+	
+	vSuppFun = Sim_ComputeFunSupp(pNtk, 0);
+	for(i = 0; i < Abc_NtkPoNum(pNtk); i++) {
+		char * seg = (char *)vSuppFun->pArray[i];
+		
+		for(j = 0; j < Abc_NtkPiNum(pNtk); j+=8) {
+			if(((*seg) & 0x01) == 0x01)
+				Vec_IntPushOrder(oDep[i], j);
+			if(((*seg) & 0x02) == 0x02)
+				Vec_IntPushOrder(oDep[i], j+1);
+			if(((*seg) & 0x04) == 0x04)
+				Vec_IntPushOrder(oDep[i], j+2);
+			if(((*seg) & 0x08) == 0x08)
+				Vec_IntPushOrder(oDep[i], j+3);
+			if(((*seg) & 0x10) == 0x10)
+				Vec_IntPushOrder(oDep[i], j+4);
+			if(((*seg) & 0x20) == 0x20)
+				Vec_IntPushOrder(oDep[i], j+5);
+			if(((*seg) & 0x40) == 0x40)
+				Vec_IntPushOrder(oDep[i], j+6);
+			if(((*seg) & 0x80) == 0x80)
+				Vec_IntPushOrder(oDep[i], j+7);
+
+			seg++;
+		}
+	}
+
+	for(i = 0; i < Abc_NtkPoNum(pNtk); i++)
+		for(j = 0; j < Vec_IntSize(oDep[i]); j++)
+			Vec_IntPush(iDep[Vec_IntEntry(oDep[i], j)], i);	
+	
+
+	/*for(i = 0; i < Abc_NtkPoNum(pNtk); i++)
+	{
+		printf("Output %d: ", i);
+		for(j = 0; j < Vec_IntSize(oDep[i]); j++)
+			printf("%d ", Vec_IntEntry(oDep[i], j));
+		printf("\n");
+	}
+
+	printf("\n");
+
+	for(i = 0; i < Abc_NtkPiNum(pNtk); i++)
+	{
+		printf("Input %d: ", i);
+		for(j = 0; j < Vec_IntSize(iDep[i]); j++)
+			printf("%d ", Vec_IntEntry(iDep[i], j));
+		printf("\n");
+	}
+
+	printf("\n");	*/	
+}
+
+void initMatchList(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep, Vec_Int_t** iMatch, int* iLastItem, Vec_Int_t** oMatch, int* oLastItem, int* iGroup, int* oGroup, int p_equivalence)
+{
+	int i, j, curr;
+	Vec_Int_t** temp;
+
+	if(!p_equivalence) {
+		temp = ABC_ALLOC( Vec_Int_t*, Abc_NtkPiNum(pNtk)+1);
+
+		for(i = 0; i < Abc_NtkPiNum(pNtk)+1; i++)	
+			temp[i] = Vec_IntAlloc( 0 );	
+
+		for(i = 0; i < Abc_NtkPoNum(pNtk); i++)		
+			Vec_IntPush(temp[Vec_IntSize(oDep[i])], i);
+
+		curr = 0;
+		for(i = 0; i < Abc_NtkPiNum(pNtk)+1; i++)
+		{
+			if(Vec_IntSize(temp[i]) == 0)
+				Vec_IntFree( temp[i] );
+
+			else
+			{
+				oMatch[curr] = temp[i];
+				
+				for(j = 0; j < Vec_IntSize(temp[i]); j++)
+					oGroup[Vec_IntEntry(oMatch[curr], j)] = curr;
+			
+				curr++;
+			}
+		}
+
+		*oLastItem = curr;
+
+		ABC_FREE( temp );
+	}
+	else {
+		// the else part fixes the outputs for P-equivalence checking
+		for(i = 0; i < Abc_NtkPoNum(pNtk); i++)
+		{
+			Vec_IntPush(oMatch[i], i);
+			oGroup[i] = i;
+			(*oLastItem) = Abc_NtkPoNum(pNtk);
+		}
+	}
+		
+	/*for(j = 0; j < *oLastItem; j++)
+	{
+		printf("oMatch %d: ", j);
+		for(i = 0; i < Vec_IntSize(oMatch[j]); i++)
+			printf("%d ", Vec_IntEntry(oMatch[j], i));
+		printf("\n");
+	}
+
+	for(i = 0; i < Abc_NtkPoNum(pNtk); i++)
+		printf("%d: %d ", i, oGroup[i]);*/
+
+	//////////////////////////////////////////////////////////////////////////////
+
+	temp = ABC_ALLOC( Vec_Int_t*, Abc_NtkPoNum(pNtk)+1 );
+
+	for(i = 0; i < Abc_NtkPoNum(pNtk)+1; i++)	
+		temp[i] = Vec_IntAlloc( 0 );
+
+	for(i = 0; i < Abc_NtkPiNum(pNtk); i++)		
+		Vec_IntPush(temp[Vec_IntSize(iDep[i])], i);
+
+	curr = 0;
+	for(i = 0; i < Abc_NtkPoNum(pNtk)+1; i++)
+	{
+		if(Vec_IntSize(temp[i]) == 0)
+			Vec_IntFree( temp[i] );
+		else
+		{
+			iMatch[curr] = temp[i];
+			for(j = 0; j < Vec_IntSize(iMatch[curr]); j++)
+				iGroup[Vec_IntEntry(iMatch[curr], j)] = curr;
+			curr++;
+		}		
+	}
+
+	*iLastItem = curr;
+
+	ABC_FREE( temp );		
+
+	/*printf("\n");
+	for(j = 0; j < *iLastItem; j++)
+	{
+		printf("iMatch %d: ", j);
+		for(i = 0; i < Vec_IntSize(iMatch[j]); i++)
+			printf("%d ", Vec_IntEntry(iMatch[j], i));
+		printf("\n");
+	}
+
+	for(i = 0; i < Abc_NtkPiNum(pNtk); i++)
+		printf("%d: %d ", i, iGroup[i]);
+	printf("\n");*/
+}
+
+void iSortDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, int* oGroup)
+{
+	int i, j, k;	
+	Vec_Int_t * temp;	
+	Vec_Int_t * oGroupList;	
+
+	oGroupList = Vec_IntAlloc( 10 );
+
+	for(i = 0; i < Abc_NtkPiNum(pNtk); i++)
+	{
+		if(Vec_IntSize(iDep[i]) == 1)
+			continue;
+		
+		temp = Vec_IntAlloc( Vec_IntSize(iDep[i]) );		
+
+		for(j = 0; j < Vec_IntSize(iDep[i]); j++)
+			Vec_IntPushUniqueOrder(oGroupList, oGroup[Vec_IntEntry(iDep[i], j)]);
+
+		for(j = 0; j < Vec_IntSize(oGroupList); j++)
+		{
+			for(k = 0; k < Vec_IntSize(iDep[i]); k++)
+				if(oGroup[Vec_IntEntry(iDep[i], k)] == Vec_IntEntry(oGroupList, j))
+				{
+					Vec_IntPush( temp, Vec_IntEntry(iDep[i], k) );		
+					Vec_IntRemove( iDep[i], Vec_IntEntry(iDep[i], k) );
+					k--;
+				}
+		}		
+
+		Vec_IntFree( iDep[i] );		
+		iDep[i] = temp;
+		Vec_IntClear( oGroupList );
+
+		/*printf("Input %d: ", i);
+		for(j = 0; j < Vec_IntSize(iDep[i]); j++)
+			printf("%d ", Vec_IntEntry(iDep[i], j));
+		printf("\n");*/
+	}
+	
+	Vec_IntFree( oGroupList );
+}
+
+void oSortDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** oDep, int* iGroup)
+{
+	int i, j, k;	
+	Vec_Int_t * temp;
+	Vec_Int_t * iGroupList;	
+	
+	iGroupList = Vec_IntAlloc( 10 );
+
+	for(i = 0; i < Abc_NtkPoNum(pNtk); i++)
+	{
+		if(Vec_IntSize(oDep[i]) == 1)
+			continue;	
+		
+		temp = Vec_IntAlloc( Vec_IntSize(oDep[i]) );
+
+		for(j = 0; j < Vec_IntSize(oDep[i]); j++)
+			Vec_IntPushUniqueOrder(iGroupList, iGroup[Vec_IntEntry(oDep[i], j)]);		
+
+		for(j = 0; j < Vec_IntSize(iGroupList); j++)
+		{
+			for(k = 0; k < Vec_IntSize(oDep[i]); k++)
+				if(iGroup[Vec_IntEntry(oDep[i], k)] == Vec_IntEntry(iGroupList, j))
+				{
+					Vec_IntPush( temp, Vec_IntEntry(oDep[i], k) );
+					Vec_IntRemove( oDep[i], Vec_IntEntry(oDep[i], k) );
+					k--;
+				}
+		}
+
+		Vec_IntFree( oDep[i] );
+		oDep[i] = temp;
+		Vec_IntClear( iGroupList );
+
+		/*printf("Output %d: ", i);
+		for(j = 0; j < Vec_IntSize(oDep[i]); j++)
+			printf("%d ", Vec_IntEntry(oDep[i], j));
+		printf("\n");*/
+	}
+	
+	Vec_IntFree( iGroupList );
+}
+
+int oSplitByDep(Abc_Ntk_t *pNtk, Vec_Int_t** oDep, Vec_Int_t** oMatch, int* oGroup, int* oLastItem, int* iGroup)
+{
+	int i, j, k;
+	int numOfItemsAdded;
+	Vec_Int_t * array, * sortedArray;	
+
+	numOfItemsAdded = 0;
+
+	for(i = 0; i < *oLastItem; i++)
+	{
+		if(Vec_IntSize(oMatch[i]) == 1)
+			continue;
+
+		array = Vec_IntAlloc( Vec_IntSize(oMatch[i]) );
+		sortedArray = Vec_IntAlloc( Vec_IntSize(oMatch[i]) );
+
+		for(j = 0; j < Vec_IntSize(oMatch[i]); j++)
+		{
+			int factor, encode;
+
+			encode = 0;
+			factor = 1;	
+			
+			for(k = 0; k < Vec_IntSize(oDep[Vec_IntEntry(oMatch[i], j)]); k++)										
+				encode += iGroup[Vec_IntEntry(oDep[Vec_IntEntry(oMatch[i], j)], k)] * factor;						
+			
+			Vec_IntPush(array, encode);
+			Vec_IntPushUniqueOrder(sortedArray, encode);
+
+			if( encode < 0)
+				printf("WARNING! Integer overflow!");
+
+			//printf("%d ", Vec_IntEntry(array, j));
+		}				
+		
+		while( Vec_IntSize(sortedArray) > 1 )
+		{			
+			for(k = 0; k < Vec_IntSize(oMatch[i]); k++) 
+			{
+				if(Vec_IntEntry(array, k) == Vec_IntEntryLast(sortedArray))
+				{
+					Vec_IntPush(oMatch[*oLastItem+numOfItemsAdded], Vec_IntEntry(oMatch[i], k));
+					oGroup[Vec_IntEntry(oMatch[i], k)] = *oLastItem+numOfItemsAdded;
+					Vec_IntRemove( oMatch[i], Vec_IntEntry(oMatch[i], k) );		
+					Vec_IntRemove( array, Vec_IntEntry(array, k) );			
+					k--;
+				}	
+			}			
+			numOfItemsAdded++;
+			Vec_IntPop(sortedArray);						
+		}
+
+		Vec_IntFree( array );		
+		Vec_IntFree( sortedArray );		
+		//printf("\n");
+	}	
+
+	*oLastItem += numOfItemsAdded;
+
+	/*printf("\n");
+	for(j = 0; j < *oLastItem ; j++)
+	{
+		printf("oMatch %d: ", j);
+		for(i = 0; i < Vec_IntSize(oMatch[j]); i++)
+			printf("%d ", Vec_IntEntry(oMatch[j], i));
+		printf("\n");
+	}*/
+
+	return numOfItemsAdded;
+}
+
+int iSplitByDep(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** iMatch, int* iGroup, int* iLastItem, int* oGroup)
+{
+	int i, j, k;	
+	int numOfItemsAdded = 0;
+	Vec_Int_t * array, * sortedArray;	
+
+	for(i = 0; i < *iLastItem; i++)
+	{
+		if(Vec_IntSize(iMatch[i]) == 1)
+			continue;
+		
+		array = Vec_IntAlloc( Vec_IntSize(iMatch[i]) );
+		sortedArray = Vec_IntAlloc( Vec_IntSize(iMatch[i]) );
+
+		for(j = 0; j < Vec_IntSize(iMatch[i]); j++)
+		{		
+			int factor, encode;
+
+			encode = 0;
+			factor = 1;	
+			
+			for(k = 0; k < Vec_IntSize(iDep[Vec_IntEntry(iMatch[i], j)]); k++)							
+				encode += oGroup[Vec_IntEntry(iDep[Vec_IntEntry(iMatch[i], j)], k)] * factor;						
+
+			Vec_IntPush(array, encode);
+			Vec_IntPushUniqueOrder(sortedArray, encode);
+			
+			//printf("%d ", Vec_IntEntry(array, j));
+		}			
+				
+		while( Vec_IntSize(sortedArray) > 1 )
+		{			
+			for(k = 0; k < Vec_IntSize(iMatch[i]); k++) 
+			{
+				if(Vec_IntEntry(array, k) == Vec_IntEntryLast(sortedArray))
+				{
+					Vec_IntPush(iMatch[*iLastItem+numOfItemsAdded], Vec_IntEntry(iMatch[i], k));
+					iGroup[Vec_IntEntry(iMatch[i], k)] = *iLastItem+numOfItemsAdded;
+					Vec_IntRemove( iMatch[i], Vec_IntEntry(iMatch[i], k) );							
+					Vec_IntRemove( array, Vec_IntEntry(array, k) );	
+					k--;
+				}
+			}
+			numOfItemsAdded++;
+			Vec_IntPop(sortedArray);	
+		}
+
+		Vec_IntFree( array );		
+		Vec_IntFree( sortedArray );	
+		//printf("\n");
+	}	
+
+	*iLastItem += numOfItemsAdded;
+
+	/*printf("\n");
+	for(j = 0; j < *iLastItem ; j++)
+	{
+		printf("iMatch %d: ", j);
+		for(i = 0; i < Vec_IntSize(iMatch[j]); i++)
+			printf("%d ", Vec_IntEntry(iMatch[j], i));
+		printf("\n");
+	}*/
+
+	return numOfItemsAdded;	
+}
+
+Vec_Ptr_t ** findTopologicalOrder( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t ** vNodes;
+    Abc_Obj_t * pObj, * pFanout;
+    int i, k;    
+    
+	extern void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes );
+	
+	// start the array of nodes
+    vNodes = ABC_ALLOC(Vec_Ptr_t *, Abc_NtkPiNum(pNtk));
+	for(i = 0; i < Abc_NtkPiNum(pNtk); i++)
+		vNodes[i] = Vec_PtrAlloc(50);	
+	
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+		// set the traversal ID
+		Abc_NtkIncrementTravId( pNtk );
+        Abc_NodeSetTravIdCurrent( pObj );
+        pObj = Abc_ObjFanout0Ntk(pObj);
+        Abc_ObjForEachFanout( pObj, pFanout, k )
+            Abc_NtkDfsReverse_rec( pFanout, vNodes[i] );
+    }
+   
+    return vNodes;
+}
+
+
+int * Abc_NtkSimulateOneNode( Abc_Ntk_t * pNtk, int * pModel, int input, Vec_Ptr_t ** topOrder )
+{
+    Abc_Obj_t * pNode;
+	Vec_Ptr_t * vNodes;
+    int * pValues, Value0, Value1, i;
+   
+	vNodes = Vec_PtrAlloc( 50 );
+/*
+    printf( "Counter example: " );
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        printf( " %d", pModel[i] );
+    printf( "\n" );
+*/
+    // increment the trav ID
+    Abc_NtkIncrementTravId( pNtk );
+    // set the CI values     
+	Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)1;
+	pNode = Abc_NtkCi(pNtk, input);
+	pNode->iTemp = pModel[input];
+	
+    // simulate in the topological order	
+    for(i = Vec_PtrSize(topOrder[input])-1; i >= 0; i--)
+    {
+		pNode = (Abc_Obj_t *)Vec_PtrEntry(topOrder[input], i);		
+		
+        Value0 = ((int)(ABC_PTRUINT_T)Abc_ObjFanin0(pNode)->pCopy) ^ Abc_ObjFaninC0(pNode);
+        Value1 = ((int)(ABC_PTRUINT_T)Abc_ObjFanin1(pNode)->pCopy) ^ Abc_ObjFaninC1(pNode);
+        
+		if( pNode->iTemp != (Value0 & Value1))
+		{
+			pNode->iTemp = (Value0 & Value1);
+			Vec_PtrPush(vNodes, pNode);
+		}
+	
+    }	
+    // fill the output values
+    pValues = ABC_ALLOC( int, Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        pValues[i] = ((int)(ABC_PTRUINT_T)Abc_ObjFanin0(pNode)->pCopy) ^ Abc_ObjFaninC0(pNode);
+    
+	pNode = Abc_NtkCi(pNtk, input);
+	if(pNode->pCopy == (Abc_Obj_t *)1)
+		pNode->pCopy = (Abc_Obj_t *)0;
+	else
+		pNode->pCopy = (Abc_Obj_t *)1;
+
+	for(i = 0; i < Vec_PtrSize(vNodes); i++)
+	{
+		pNode = (Abc_Obj_t *)Vec_PtrEntry(vNodes, i);
+
+		if(pNode->pCopy == (Abc_Obj_t *)1)
+			pNode->pCopy = (Abc_Obj_t *)0;
+		else
+			pNode->pCopy = (Abc_Obj_t *)1;
+	}
+
+	Vec_PtrFree( vNodes );
+
+    return pValues;
+}
+
+int refineIOBySimulation(Abc_Ntk_t *pNtk, Vec_Int_t** iMatch, int* iLastItem, int * iGroup, Vec_Int_t** iDep, Vec_Int_t** oMatch, int* oLastItem, int * oGroup, Vec_Int_t** oDep, char * vPiValues, int * observability, Vec_Ptr_t ** topOrder)
+{
+	Abc_Obj_t * pObj;
+	int * pModel;//, ** pModel2;
+	int * output, * output2;
+	int lastItem;
+	int i, j, k;
+	Vec_Int_t * iComputedNum, * iComputedNumSorted;	
+	Vec_Int_t * oComputedNum;				// encoding the number of flips		
+	int factor;	
+	int isRefined = FALSE;	
+
+	pModel = ABC_ALLOC( int, Abc_NtkCiNum(pNtk) );	
+
+	Abc_NtkForEachPi( pNtk, pObj, i )
+		pModel[i] = vPiValues[i] - '0';
+	Abc_NtkForEachLatch( pNtk, pObj, i )
+		pModel[Abc_NtkPiNum(pNtk)+i] = pObj->iData - 1;
+
+	output = Abc_NtkVerifySimulatePattern( pNtk, pModel );	
+
+	oComputedNum = Vec_IntAlloc( Abc_NtkPoNum(pNtk) );
+	for(i = 0; i < Abc_NtkPoNum(pNtk); i++)
+		Vec_IntPush(oComputedNum, 0);
+	
+	/****************************************************************************************/
+	/********** group outputs that produce 1 and outputs that produce 0 together ************/	
+	
+	lastItem = *oLastItem;
+	for(i = 0; i < lastItem && (*oLastItem) != Abc_NtkPoNum(pNtk); i++)
+	{
+		int flag = FALSE;
+
+		if(Vec_IntSize(oMatch[i]) == 1)
+			continue;
+
+		for(j = 1; j < Vec_IntSize(oMatch[i]); j++)
+			if(output[Vec_IntEntry(oMatch[i], 0)] != output[Vec_IntEntry(oMatch[i], j)])
+			{
+				flag = TRUE;
+				break;
+			}
+
+		if(flag)
+		{
+			for(j = 0; j < Vec_IntSize(oMatch[i]); j++)
+				if(output[Vec_IntEntry(oMatch[i], j)])
+				{
+					Vec_IntPush(oMatch[*oLastItem], Vec_IntEntry(oMatch[i], j));
+					oGroup[Vec_IntEntry(oMatch[i], j)] = *oLastItem;	
+					Vec_IntRemove(oMatch[i], Vec_IntEntry(oMatch[i], j));	
+					j--;
+				}
+
+			(*oLastItem)++;
+		}
+	}
+
+	if( (*oLastItem) > lastItem )
+	{
+		isRefined = TRUE;
+		iSortDependencies(pNtk, iDep, oGroup);	
+	}
+
+	/****************************************************************************************/
+	/************* group inputs that make the same number of flips in outpus ****************/		
+
+	lastItem = *iLastItem;
+	for(i = 0; i < lastItem && (*iLastItem) != Abc_NtkPiNum(pNtk); i++)
+	{
+		int num;
+
+		if(Vec_IntSize(iMatch[i]) == 1)
+			continue;
+
+		iComputedNum = Vec_IntAlloc( Vec_IntSize(iMatch[i]) );
+		iComputedNumSorted = Vec_IntAlloc( Vec_IntSize(iMatch[i]) );	
+		
+		for(j = 0; j < Vec_IntSize(iMatch[i]); j++)
+		{
+			if( vPiValues[Vec_IntEntry(iMatch[i], j)] == '0' )				
+				pModel[Vec_IntEntry(iMatch[i], j)] = 1;
+			else 				
+				pModel[Vec_IntEntry(iMatch[i], j)] = 0;		
+			
+			//output2 = Abc_NtkVerifySimulatePattern( pNtk, pModel );	
+			output2 = Abc_NtkSimulateOneNode( pNtk, pModel, Vec_IntEntry(iMatch[i], j), topOrder );
+			
+			num = 0;
+			factor = 1;	
+			for(k = 0; k < Vec_IntSize(iDep[Vec_IntEntry(iMatch[i], j)]); k++)
+			{
+				int outputIndex = Vec_IntEntry(iDep[Vec_IntEntry(iMatch[i], j)], k);		
+
+				if(output2[outputIndex])
+					num += (oGroup[outputIndex] + 1) * factor;				
+			
+				if(output[outputIndex] != output2[outputIndex])
+				{
+					int temp = Vec_IntEntry(oComputedNum, outputIndex) + i + 1;
+					Vec_IntWriteEntry(oComputedNum, outputIndex, temp);	
+					observability[Vec_IntEntry(iMatch[i], j)]++;
+				}
+			}
+
+			Vec_IntPush(iComputedNum, num);
+			Vec_IntPushUniqueOrder(iComputedNumSorted, num);			
+
+			pModel[Vec_IntEntry(iMatch[i], j)] = vPiValues[Vec_IntEntry(iMatch[i], j)] - '0';
+			ABC_FREE( output2 );
+		}	
+
+		while( Vec_IntSize( iComputedNumSorted ) > 1 )
+		{
+			for(k = 0; k < Vec_IntSize(iMatch[i]); k++)
+			{							
+				if(Vec_IntEntry(iComputedNum, k) == Vec_IntEntryLast(iComputedNumSorted) )
+				{
+					Vec_IntPush(iMatch[*iLastItem], Vec_IntEntry(iMatch[i], k));
+					iGroup[Vec_IntEntry(iMatch[i], k)] = *iLastItem;
+					Vec_IntRemove( iMatch[i], Vec_IntEntry(iMatch[i], k) );
+					Vec_IntRemove( iComputedNum, Vec_IntEntry(iComputedNum, k) );		
+					k--;
+				}				
+			}
+			(*iLastItem)++;	
+			Vec_IntPop( iComputedNumSorted );
+		}	
+
+		Vec_IntFree( iComputedNum );
+		Vec_IntFree( iComputedNumSorted );
+	}
+
+	if( (*iLastItem) > lastItem )
+	{
+		isRefined = TRUE;
+		oSortDependencies(pNtk, oDep, iGroup);
+	}
+
+	/****************************************************************************************/
+	/********** encode the number of flips in each output by flipping the outputs ***********/
+	/********** and group all the outputs that have the same encoding         ***********/	
+
+	lastItem = *oLastItem;
+	for(i = 0; i < lastItem && (*oLastItem) != Abc_NtkPoNum(pNtk); i++)
+	{
+		Vec_Int_t * encode, * sortedEncode;				// encoding the number of flips					
+
+		if(Vec_IntSize(oMatch[i]) == 1)
+			continue;
+			
+		encode = Vec_IntAlloc( Vec_IntSize(oMatch[i]) );
+		sortedEncode = Vec_IntAlloc( Vec_IntSize(oMatch[i]) );					
+	
+		for(j = 0; j < Vec_IntSize(oMatch[i]); j++)
+		{
+			Vec_IntPush(encode, Vec_IntEntry(oComputedNum, Vec_IntEntry(oMatch[i], j)) );
+			Vec_IntPushUniqueOrder( sortedEncode, Vec_IntEntry(encode, j) );
+		}
+
+		while( Vec_IntSize(sortedEncode) > 1 )
+		{
+			for(j = 0; j < Vec_IntSize(oMatch[i]); j++)
+				if(Vec_IntEntry(encode, j) == Vec_IntEntryLast(sortedEncode))
+				{
+					Vec_IntPush(oMatch[*oLastItem], Vec_IntEntry(oMatch[i], j));
+					oGroup[Vec_IntEntry(oMatch[i], j)] = *oLastItem;
+					Vec_IntRemove( oMatch[i], Vec_IntEntry(oMatch[i], j) );
+					Vec_IntRemove( encode, Vec_IntEntry(encode, j) );
+					j --;
+				}				
+			
+			(*oLastItem)++;
+			Vec_IntPop( sortedEncode );
+		}
+
+		Vec_IntFree( encode );
+		Vec_IntFree( sortedEncode );
+	}
+
+	if( (*oLastItem) > lastItem )
+		isRefined = TRUE;	
+
+	ABC_FREE( pModel );
+	ABC_FREE( output );
+	Vec_IntFree( oComputedNum );
+
+	return isRefined;	
+}
+
+Abc_Ntk_t * Abc_NtkMiterBm( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Vec_Ptr_t * iCurrMatch, Vec_Ptr_t * oCurrMatch )
+{
+	char Buffer[1000];
+    Abc_Ntk_t * pNtkMiter;
+
+	pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName );
+    pNtkMiter->pName = Extra_UtilStrsav(Buffer);
+
+	//Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize );
+	{
+		Abc_Obj_t * pObj, * pObjNew;
+		int i;
+
+		Abc_AigConst1(pNtk1)->pCopy = Abc_AigConst1(pNtkMiter);
+		Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtkMiter);
+
+		// create new PIs and remember them in the old PIs
+		if(iCurrMatch == NULL)
+		{
+			Abc_NtkForEachCi( pNtk1, pObj, i )
+			{
+				pObjNew = Abc_NtkCreatePi( pNtkMiter );
+				// remember this PI in the old PIs
+				pObj->pCopy = pObjNew;
+				pObj = Abc_NtkCi(pNtk2, i);  
+				pObj->pCopy = pObjNew;
+				// add name
+				Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL );
+			}
+		}
+		else
+		{
+			for(i = 0; i < Vec_PtrSize( iCurrMatch ); i += 2)
+			{
+				pObjNew = Abc_NtkCreatePi( pNtkMiter );
+				pObj = (Abc_Obj_t *)Vec_PtrEntry(iCurrMatch, i);
+				pObj->pCopy = pObjNew;
+				pObj = (Abc_Obj_t *)Vec_PtrEntry(iCurrMatch, i+1);
+				pObj->pCopy = pObjNew;
+				// add name
+				Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL );
+			}
+		}
+
+        // create the only PO
+        pObjNew = Abc_NtkCreatePo( pNtkMiter );
+        // add the PO name
+        Abc_ObjAssignName( pObjNew, "miter", NULL );
+	}
+
+	// Abc_NtkMiterAddOne( pNtk1, pNtkMiter );
+	{
+		Abc_Obj_t * pNode;
+		int i;
+		assert( Abc_NtkIsDfsOrdered(pNtk1) );
+		Abc_AigForEachAnd( pNtk1, pNode, i )
+			pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+	}
+
+	// Abc_NtkMiterAddOne( pNtk2, pNtkMiter );
+	{
+		Abc_Obj_t * pNode;
+		int i;
+		assert( Abc_NtkIsDfsOrdered(pNtk2) );
+		Abc_AigForEachAnd( pNtk2, pNode, i )
+			pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+	}
+	
+	// Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize );	
+	{
+		Vec_Ptr_t * vPairs;
+		Abc_Obj_t * pMiter;
+		int i;
+
+		vPairs = Vec_PtrAlloc( 100 );
+	    
+		// collect the CO nodes for the miter
+		if(oCurrMatch != NULL)
+		{
+			for(i = 0; i < Vec_PtrSize( oCurrMatch ); i += 2)
+			{
+				Vec_PtrPush( vPairs, Abc_ObjChild0Copy((Abc_Obj_t *)Vec_PtrEntry(oCurrMatch, i)) );
+				Vec_PtrPush( vPairs, Abc_ObjChild0Copy((Abc_Obj_t *)Vec_PtrEntry(oCurrMatch, i+1)) );
+			}
+		}
+		else
+		{
+			Abc_Obj_t * pNode;
+
+			Abc_NtkForEachCo( pNtk1, pNode, i )
+			{
+				Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) );
+				pNode = Abc_NtkCo( pNtk2, i );
+				Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) );
+			}
+		}
+		
+	 pMiter = Abc_AigMiter( (Abc_Aig_t *)pNtkMiter->pManFunc, vPairs, 0 );
+	 Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter );
+	 Vec_PtrFree(vPairs);
+	}
+
+	//Abc_AigCleanup(pNtkMiter->pManFunc);
+	
+	return pNtkMiter;
+}
+
+int * pValues1__, * pValues2__;
+
+void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, Vec_Int_t * mismatch )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNode;    
+    int nErrors, nPrinted, i, iNode = -1;
+
+    assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) );
+    assert( Abc_NtkCoNum(pNtk1) == Abc_NtkCoNum(pNtk2) );
+    // get the CO values under this model
+    pValues1__ = Abc_NtkVerifySimulatePattern( pNtk1, pModel );
+    pValues2__ = Abc_NtkVerifySimulatePattern( pNtk2, pModel );
+    // count the mismatches
+    nErrors = 0;
+    for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ )
+        nErrors += (int)( pValues1__[i] != pValues2__[i] );
+    //printf( "Verification failed for at least %d outputs: ", nErrors );
+    // print the first 3 outputs
+    nPrinted = 0;
+    for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ )
+        if ( pValues1__[i] != pValues2__[i] )
+        {
+            if ( iNode == -1 )
+                iNode = i;
+            //printf( " %s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) );
+            if ( ++nPrinted == 3 )
+                break;
+        }
+    /*if ( nPrinted != nErrors )
+        printf( " ..." );
+    printf( "\n" );*/
+    // report mismatch for the first output
+    if ( iNode >= 0 )
+    {
+        /*printf( "Output %s: Value in Network1 = %d. Value in Network2 = %d.\n", 
+            Abc_ObjName(Abc_NtkCo(pNtk1,iNode)), pValues1[iNode], pValues2[iNode] );
+        printf( "Input pattern: " );*/
+        // collect PIs in the cone
+        pNode = Abc_NtkCo(pNtk1,iNode);
+        vNodes = Abc_NtkNodeSupport( pNtk1, &pNode, 1 );
+        // set the PI numbers
+        Abc_NtkForEachCi( pNtk1, pNode, i )
+            pNode->iTemp = i;
+        // print the model
+        pNode = (Abc_Obj_t *)Vec_PtrEntry( vNodes, 0 );
+        if ( Abc_ObjIsCi(pNode) )
+        {
+            Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+            {
+                assert( Abc_ObjIsCi(pNode) );
+                //printf( " %s=%d", Abc_ObjName(pNode), pModel[(int)pNode->pCopy] );
+				Vec_IntPush(mismatch, Abc_ObjId(pNode)-1);
+				Vec_IntPush(mismatch, pModel[(int)(size_t)pNode->pCopy]);
+            }
+        }
+        //printf( "\n" );
+        Vec_PtrFree( vNodes );
+    }
+    free( pValues1__ );
+    free( pValues2__ );
+}
+
+int Abc_NtkMiterSatBm( Abc_Ntk_t * pNtk, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fVerbose, ABC_INT64_T * pNumConfs, ABC_INT64_T * pNumInspects)
+{
+    static sat_solver * pSat = NULL;
+    lbool   status;
+    int RetValue;
+    abctime clk;	
+
+	extern int Abc_NodeAddClausesTop( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars );
+	extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk );	
+ 
+    if ( pNumConfs )
+        *pNumConfs = 0;
+    if ( pNumInspects )
+        *pNumInspects = 0;
+
+    assert( Abc_NtkLatchNum(pNtk) == 0 );
+
+//    if ( Abc_NtkPoNum(pNtk) > 1 )
+//        fprintf( stdout, "Warning: The miter has %d outputs. SAT will try to prove all of them.\n", Abc_NtkPoNum(pNtk) );
+
+    // load clauses into the sat_solver
+    clk = Abc_Clock();
+
+			
+		
+	pSat = (sat_solver *)Abc_NtkMiterSatCreate( pNtk, 0 );
+			
+    if ( pSat == NULL )
+        return 1;
+//printf( "%d \n", pSat->clauses.size );
+//sat_solver_delete( pSat );
+//return 1;
+
+//    printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
+//    PRT( "Time", Abc_Clock() - clk );
+
+    // simplify the problem
+    clk = Abc_Clock();
+    status = sat_solver_simplify(pSat);
+//    printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
+//    PRT( "Time", Abc_Clock() - clk );
+    if ( status == 0 )
+    {
+        sat_solver_delete( pSat );
+//        printf( "The problem is UNSATISFIABLE after simplification.\n" );
+        return 1;
+    }
+
+    // solve the miter
+    clk = Abc_Clock();
+    if ( fVerbose )
+        pSat->verbosity = 1;
+    status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( status == l_Undef )
+    {
+//        printf( "The problem timed out.\n" );
+        RetValue = -1;
+    }
+    else if ( status == l_True )
+    {
+//        printf( "The problem is SATISFIABLE.\n" );
+        RetValue = 0;
+    }
+    else if ( status == l_False )
+    {
+//        printf( "The problem is UNSATISFIABLE.\n" );
+        RetValue = 1;
+    }
+    else
+        assert( 0 );
+//    PRT( "SAT sat_solver time", Abc_Clock() - clk );
+//    printf( "The number of conflicts = %d.\n", (int)pSat->sat_solver_stats.conflicts );
+
+    // if the problem is SAT, get the counterexample
+    if ( status == l_True )
+    {
+//        Vec_Int_t * vCiIds = Abc_NtkGetCiIds( pNtk );
+        Vec_Int_t * vCiIds = Abc_NtkGetCiSatVarNums( pNtk );
+        pNtk->pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize );
+        Vec_IntFree( vCiIds );
+    }
+    // free the sat_solver
+    if ( fVerbose )
+        Sat_SolverPrintStats( stdout, pSat );
+
+    if ( pNumConfs )
+        *pNumConfs = (int)pSat->stats.conflicts;
+    if ( pNumInspects )
+        *pNumInspects = (int)pSat->stats.inspects;
+
+//sat_solver_store_write( pSat, "trace.cnf" );	
+	sat_solver_store_free( pSat );
+	sat_solver_delete( pSat );
+    return RetValue;
+}
+
+int Abc_NtkBmSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Vec_Ptr_t * iMatchPairs, Vec_Ptr_t * oMatchPairs, Vec_Int_t * mismatch, int mode)
+{    
+    extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );	
+
+	Abc_Ntk_t * pMiter = NULL;
+    Abc_Ntk_t * pCnf;
+    int RetValue;
+
+	// get the miter of the two networks
+	if( mode == 0 )
+	{
+		//Abc_NtkDelete( pMiter );
+		pMiter = Abc_NtkMiterBm( pNtk1, pNtk2, iMatchPairs, oMatchPairs );
+	}
+	else if( mode == 1 )		// add new outputs
+	{		
+		int i;
+		Abc_Obj_t * pObj;
+		Vec_Ptr_t * vPairs;
+		Abc_Obj_t * pNtkMiter;		
+
+		vPairs = Vec_PtrAlloc( 100 );
+
+		Abc_NtkForEachCo( pMiter, pObj, i )			
+			Abc_ObjRemoveFanins( pObj );
+
+		for(i = 0; i < Vec_PtrSize( oMatchPairs ); i += 2)
+		{
+			Vec_PtrPush( vPairs, Abc_ObjChild0Copy((Abc_Obj_t *)Vec_PtrEntry(oMatchPairs, i)) );
+			Vec_PtrPush( vPairs, Abc_ObjChild0Copy((Abc_Obj_t *)Vec_PtrEntry(oMatchPairs, i+1)) );
+		}
+		pNtkMiter = Abc_AigMiter( (Abc_Aig_t *)pMiter->pManFunc, vPairs, 0 );
+		Abc_ObjAddFanin( Abc_NtkPo(pMiter,0), pNtkMiter );	 
+		Vec_PtrFree( vPairs);
+	}
+	else if( mode == 2 )		// add some outputs
+	{
+
+	}
+	else if( mode == 3)			// remove all outputs
+	{
+	}
+
+	if ( pMiter == NULL )
+	{
+		printf("Miter computation has failed.");		
+		return -1;
+	}
+	RetValue = Abc_NtkMiterIsConstant( pMiter );
+	if ( RetValue == 0)
+	{		
+		/*printf("Networks are NOT EQUIVALENT after structural hashing.");	*/
+		// report the error    	
+		if(mismatch != NULL)
+		{
+			pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 );
+			Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel, mismatch );
+			ABC_FREE( pMiter->pModel );
+		}        
+		Abc_NtkDelete( pMiter );
+        return RetValue;
+	}
+	if( RetValue == 1 )
+	{		
+		/*printf("Networks are equivalent after structural hashing.");	*/
+		Abc_NtkDelete( pMiter );
+		return RetValue;
+	}
+
+	// convert the miter into a CNF
+	//if(mode == 0)
+	pCnf = Abc_NtkMulti( pMiter, 0, 100, 1, 0, 0, 0 );
+    Abc_NtkDelete( pMiter );
+    if ( pCnf == NULL )
+    {        
+		printf("Renoding for CNF has failed.");	
+        return -1;
+    }
+
+    // solve the CNF using the SAT solver
+    RetValue = Abc_NtkMiterSat( pCnf, (ABC_INT64_T)10000, (ABC_INT64_T)0, 0, NULL, NULL);
+    /*if ( RetValue == -1 )
+		printf("Networks are undecided (SAT solver timed out).");	
+    else if ( RetValue == 0 )        
+		printf("Networks are NOT EQUIVALENT after SAT.");	
+    else
+		printf("Networks are equivalent after SAT.");	*/
+	if ( mismatch != NULL && pCnf->pModel )
+        Abc_NtkVerifyReportError( pNtk1, pNtk2, pCnf->pModel, mismatch );
+
+    ABC_FREE( pCnf->pModel );
+    Abc_NtkDelete( pCnf );
+
+	return RetValue;
+}
+
+int checkEquivalence( Abc_Ntk_t * pNtk1, Vec_Int_t* matchedInputs1, Vec_Int_t * matchedOutputs1,
+					   Abc_Ntk_t * pNtk2, Vec_Int_t* matchedInputs2, Vec_Int_t * matchedOutputs2)
+{	
+	Vec_Ptr_t * iMatchPairs, * oMatchPairs;
+	int i;
+	int result;
+
+	iMatchPairs = Vec_PtrAlloc( Abc_NtkPiNum( pNtk1 ) * 2);
+	oMatchPairs = Vec_PtrAlloc( Abc_NtkPoNum( pNtk1 ) * 2);
+
+	for(i = 0; i < Abc_NtkPiNum(pNtk1); i++)
+	{	
+		Vec_PtrPush(iMatchPairs, Abc_NtkPi(pNtk2, Vec_IntEntry(matchedInputs2, i)));
+		Vec_PtrPush(iMatchPairs, Abc_NtkPi(pNtk1, Vec_IntEntry(matchedInputs1, i)));
+	}
+				
+
+	for(i = 0; i < Abc_NtkPoNum(pNtk1); i++)		
+	{
+		Vec_PtrPush(oMatchPairs, Abc_NtkPo(pNtk2, Vec_IntEntry(matchedOutputs2, i)));
+		Vec_PtrPush(oMatchPairs, Abc_NtkPo(pNtk1, Vec_IntEntry(matchedOutputs1, i)));
+	}		
+
+	result = Abc_NtkBmSat(pNtk1, pNtk2, iMatchPairs, oMatchPairs, NULL, 0);
+
+	if( result )
+		printf("*** Circuits are equivalent ***\n");
+	else
+		printf("*** Circuits are NOT equivalent ***\n");
+
+	Vec_PtrFree( iMatchPairs );
+	Vec_PtrFree( oMatchPairs );	
+
+	return result;
+}
+
+Abc_Ntk_t * computeCofactor(Abc_Ntk_t * pNtk, Vec_Ptr_t ** nodesInLevel, int * bitVector, Vec_Int_t * currInputs)
+{	
+	Abc_Ntk_t * subNtk;	
+	Abc_Obj_t * pObj, * pObjNew;
+	int i, j, numOfLevels;		
+
+	numOfLevels = Abc_AigLevel( pNtk );		// number of levels excludes PI/POs	
+
+	// start a new network
+	subNtk = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );    
+    subNtk->pName = Extra_UtilStrsav("subNtk");
+
+	Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(subNtk);	
+
+	// clean the node copy fields and mark the nodes that need to be copied to the new network
+    Abc_NtkCleanCopy( pNtk );
+
+	if(bitVector != NULL)
+	{
+		for(i = 0; i < Abc_NtkPiNum(pNtk); i++)
+			if(bitVector[i])
+			{
+				pObj = Abc_NtkPi(pNtk, i);
+				pObj->pCopy = (Abc_Obj_t *)(1);
+			}
+	}
+
+	for(i = 0; i < Vec_IntSize(currInputs); i++)
+	{
+		pObj = Abc_NtkPi(pNtk, Vec_IntEntry(currInputs, i));
+		pObjNew = Abc_NtkDupObj( subNtk, pObj, 1 );
+		pObj->pCopy = pObjNew;
+	}
+		
+
+	// i = 0 are the inputs and the inputs are not added to the 2d array ( nodesInLevel )
+	for( i = 0; i <= numOfLevels; i++ )	
+		for( j = 0; j < Vec_PtrSize( nodesInLevel[i] ); j++)
+		{
+			pObj = (Abc_Obj_t *)Vec_PtrEntry( nodesInLevel[i], j );
+
+			if(Abc_ObjChild0Copy(pObj) == NULL && Abc_ObjChild1Copy(pObj) == NULL)
+				pObj->pCopy = NULL;
+			else if(Abc_ObjChild0Copy(pObj) == NULL && Abc_ObjChild1Copy(pObj) == (void*)(1))
+				pObj->pCopy = NULL;
+			else if(Abc_ObjChild0Copy(pObj) == NULL && (Abc_ObjChild1Copy(pObj) != (NULL) && Abc_ObjChild1Copy(pObj) != (void*)(1)) )
+				pObj->pCopy = NULL;
+			else if(Abc_ObjChild0Copy(pObj) == (void*)(1) && Abc_ObjChild1Copy(pObj) == NULL)
+				pObj->pCopy = NULL;
+			else if(Abc_ObjChild0Copy(pObj) == (void*)(1) && Abc_ObjChild1Copy(pObj) == (void*)(1))
+				pObj->pCopy = (Abc_Obj_t *)(1);
+			else if(Abc_ObjChild0Copy(pObj) == (void*)(1) && (Abc_ObjChild1Copy(pObj) != (NULL) && Abc_ObjChild1Copy(pObj) != (void*)(1)) )
+				pObj->pCopy = Abc_ObjChild1Copy(pObj);
+			else if( (Abc_ObjChild0Copy(pObj) != (NULL) && Abc_ObjChild0Copy(pObj) != (void*)(1)) && Abc_ObjChild1Copy(pObj) == NULL )
+				pObj->pCopy = NULL;
+			else if( (Abc_ObjChild0Copy(pObj) != (NULL) && Abc_ObjChild0Copy(pObj) != (void*)(1)) && Abc_ObjChild1Copy(pObj) == (void*)(1) )
+				pObj->pCopy = Abc_ObjChild0Copy(pObj);
+			else if( (Abc_ObjChild0Copy(pObj) != (NULL) && Abc_ObjChild0Copy(pObj) != (void*)(1)) &&
+					 (Abc_ObjChild1Copy(pObj) != (NULL) && Abc_ObjChild1Copy(pObj) != (void*)(1)) )
+				pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)subNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );					
+		}	
+
+	for(i = 0; i < Abc_NtkPoNum(pNtk); i++)
+	{
+		pObj = Abc_NtkPo(pNtk, i);
+		pObjNew = Abc_NtkDupObj( subNtk, pObj, 1 );
+		
+		if( Abc_ObjChild0Copy(pObj) == NULL)
+		{
+			Abc_ObjAddFanin( pObjNew, Abc_AigConst1(subNtk));
+			pObjNew->fCompl0 = 1;
+		}
+		else if( Abc_ObjChild0Copy(pObj) == (void*)(1) )
+		{
+			Abc_ObjAddFanin( pObjNew, Abc_AigConst1(subNtk));
+			pObjNew->fCompl0 = 0;
+		}
+		else
+			Abc_ObjAddFanin( pObjNew, Abc_ObjChild0Copy(pObj) );
+	}
+
+	return subNtk;
+}
+
+FILE *matchFile;
+
+int matchNonSingletonOutputs(Abc_Ntk_t * pNtk1, Vec_Ptr_t ** nodesInLevel1, Vec_Int_t ** iMatch1, Vec_Int_t ** iDep1, Vec_Int_t * matchedInputs1, int * iGroup1, Vec_Int_t ** oMatch1, int * oGroup1,
+							  Abc_Ntk_t * pNtk2, Vec_Ptr_t ** nodesInLevel2, Vec_Int_t ** iMatch2, Vec_Int_t ** iDep2, Vec_Int_t * matchedInputs2, int * iGroup2, Vec_Int_t ** oMatch2, int * oGroup2,
+							  Vec_Int_t * matchedOutputs1, Vec_Int_t * matchedOutputs2, Vec_Int_t * oMatchedGroups, Vec_Int_t * iNonSingleton,						 
+							  Abc_Ntk_t * subNtk1, Abc_Ntk_t * subNtk2, Vec_Ptr_t * oMatchPairs,
+							  Vec_Int_t * oNonSingleton, int oI, int idx, int ii, int iidx)
+{		
+	static int MATCH_FOUND;
+	int i;
+	int j, temp;
+	Vec_Int_t * mismatch;		
+	int * skipList;	
+	static int counter = 0;
+
+	MATCH_FOUND = FALSE;
+	
+	if( oI == Vec_IntSize( oNonSingleton ) )
+	{
+		if( iNonSingleton != NULL)			
+			if( match1by1(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1,
+				          pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2,
+ 					      matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton, ii, iidx) )
+				MATCH_FOUND = TRUE;	
+
+		if( iNonSingleton == NULL)
+			MATCH_FOUND = TRUE;
+
+		return MATCH_FOUND;
+	}
+
+	i = Vec_IntEntry(oNonSingleton, oI);
+
+	mismatch = Vec_IntAlloc(10);
+	
+	skipList = ABC_ALLOC(int, Vec_IntSize(oMatch1[i]));
+
+	for(j = 0; j < Vec_IntSize(oMatch1[i]); j++)
+		skipList[j] = FALSE;
+
+	Vec_PtrPush(oMatchPairs, Abc_NtkPo(subNtk1, Vec_IntEntry(oMatch1[i], idx)) );
+	Vec_IntPush(matchedOutputs1, Vec_IntEntry(oMatch1[i], idx));
+
+	for(j = 0; j < Vec_IntSize( oMatch2[i] ) && MATCH_FOUND == FALSE; j++)
+	{
+		if( Vec_IntEntry(oMatch2[i], j) == -1 || skipList[j] == TRUE)
+			continue;
+
+		Vec_PtrPush(oMatchPairs, Abc_NtkPo(subNtk2, Vec_IntEntry(oMatch2[i], j)));
+		Vec_IntPush(matchedOutputs2, Vec_IntEntry(oMatch2[i], j));
+
+		counter++;		
+		if( Abc_NtkBmSat( subNtk1, subNtk2, NULL, oMatchPairs, mismatch, 0) )
+		{
+			/*fprintf(matchFile, "%s matched to %s\n", Abc_ObjName(Abc_NtkPo(pNtk1, Vec_IntEntry(oMatch1[i], idx))), 
+										 Abc_ObjName(Abc_NtkPo(pNtk2, Vec_IntEntry(oMatch2[i], j))));			*/
+
+			temp =  Vec_IntEntry(oMatch2[i], j);
+			Vec_IntWriteEntry(oMatch2[i], j, -1);
+			
+			if(idx != Vec_IntSize( oMatch1[i] ) - 1)
+				// call the same function with idx+1
+				matchNonSingletonOutputs(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1,
+										 pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2,
+										 matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton,						 
+										 subNtk1, subNtk2, oMatchPairs,
+										 oNonSingleton, oI, idx+1, ii, iidx);
+			else	
+				// call the same function with idx = 0 and oI++
+				matchNonSingletonOutputs(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1,
+										 pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2,
+										 matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton,						 
+										 subNtk1, subNtk2, oMatchPairs,
+										 oNonSingleton, oI+1, 0, ii, iidx);
+
+			Vec_IntWriteEntry(oMatch2[i], j, temp);
+		}		
+		else
+		{
+			int * output1, * output2;
+			int k;
+			Abc_Obj_t * pObj;
+			int * pModel;
+			char * vPiValues;			
+			
+
+			vPiValues = ABC_ALLOC( char,  Abc_NtkPiNum(subNtk1) + 1);
+			vPiValues[Abc_NtkPiNum(subNtk1)] = '\0';	
+			
+			for(k = 0; k < Abc_NtkPiNum(subNtk1); k++)
+				vPiValues[k] = '0';
+
+			for(k = 0; k < Vec_IntSize(mismatch); k += 2)			
+				vPiValues[Vec_IntEntry(mismatch, k)] = Vec_IntEntry(mismatch, k+1);						
+
+			pModel = ABC_ALLOC( int, Abc_NtkCiNum(subNtk1) );	
+
+			Abc_NtkForEachPi( subNtk1, pObj, k )
+				pModel[k] = vPiValues[k] - '0';
+			Abc_NtkForEachLatch( subNtk1, pObj, k )
+				pModel[Abc_NtkPiNum(subNtk1)+k] = pObj->iData - 1;			
+	
+			output1 = Abc_NtkVerifySimulatePattern( subNtk1, pModel );
+
+			Abc_NtkForEachLatch( subNtk2, pObj, k )
+				pModel[Abc_NtkPiNum(subNtk2)+k] = pObj->iData - 1;
+
+			output2 = Abc_NtkVerifySimulatePattern( subNtk2, pModel );
+			
+
+			for(k = 0; k < Vec_IntSize( oMatch1[i] ); k++)
+				if(output1[Vec_IntEntry(oMatch1[i], idx)] != output2[Vec_IntEntry(oMatch2[i], k)])
+				{
+					skipList[k] = TRUE;	
+					/*printf("Output is SKIPPED");*/
+				}
+				
+			ABC_FREE( vPiValues );
+			ABC_FREE( pModel );
+			ABC_FREE( output1 );
+			ABC_FREE( output2 );
+		}
+		
+		if(MATCH_FOUND == FALSE )
+		{
+			Vec_PtrPop(oMatchPairs);
+			Vec_IntPop(matchedOutputs2);
+		}
+	}
+
+	if(MATCH_FOUND == FALSE )
+	{
+		Vec_PtrPop(oMatchPairs);
+		Vec_IntPop(matchedOutputs1);
+	}
+
+	if(MATCH_FOUND && counter != 0)
+	{		
+		/*printf("Number of OUTPUT SAT instances = %d", counter);*/
+		counter = 0;
+	}
+
+	ABC_FREE( mismatch );
+	ABC_FREE( skipList );
+
+	return MATCH_FOUND;
+}
+
+int match1by1(Abc_Ntk_t * pNtk1, Vec_Ptr_t ** nodesInLevel1, Vec_Int_t ** iMatch1, Vec_Int_t ** iDep1, Vec_Int_t * matchedInputs1, int * iGroup1, Vec_Int_t ** oMatch1, int * oGroup1,
+			   Abc_Ntk_t * pNtk2, Vec_Ptr_t ** nodesInLevel2, Vec_Int_t ** iMatch2, Vec_Int_t ** iDep2, Vec_Int_t * matchedInputs2, int * iGroup2, Vec_Int_t ** oMatch2, int * oGroup2,
+			   Vec_Int_t * matchedOutputs1, Vec_Int_t * matchedOutputs2, Vec_Int_t * oMatchedGroups, Vec_Int_t * iNonSingleton, int ii, int idx)
+{
+	static int MATCH_FOUND = FALSE;
+	Abc_Ntk_t * subNtk1, * subNtk2;
+	Vec_Int_t * oNonSingleton;	
+	Vec_Ptr_t * oMatchPairs;
+	int * skipList;
+	int j, m;	
+	int i;		
+	static int counter = 0;
+
+	MATCH_FOUND = FALSE;
+
+	if( ii == Vec_IntSize(iNonSingleton) )
+	{
+		MATCH_FOUND = TRUE;
+		return TRUE;
+	}
+	
+	i = Vec_IntEntry(iNonSingleton, ii);
+
+	if( idx == Vec_IntSize(iMatch1[i]) )
+	{		
+		// call again with the next element in iNonSingleton
+		return match1by1(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1,
+				    	 pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2,
+						 matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton, ii+1, 0);			
+		
+	}	
+	
+	oNonSingleton = Vec_IntAlloc(10);
+	oMatchPairs = Vec_PtrAlloc(100);	
+	skipList = ABC_ALLOC(int, Vec_IntSize(iMatch1[i]));
+
+	for(j = 0; j < Vec_IntSize(iMatch1[i]); j++)
+		skipList[j] = FALSE;
+	
+	Vec_IntPush(matchedInputs1, Vec_IntEntry(iMatch1[i], idx));
+	idx++;
+	
+	if(idx == 1)
+	{
+		for(j = 0; j < Vec_IntSize(iDep1[Vec_IntEntryLast(iMatch1[i])]); j++)
+		{
+			if( Vec_IntSize(oMatch1[oGroup1[Vec_IntEntry(iDep1[Vec_IntEntryLast(iMatch1[i])], j)]]) == 1 ) 
+				continue;
+			if( Vec_IntFind( oMatchedGroups, oGroup1[Vec_IntEntry(iDep1[Vec_IntEntryLast(iMatch1[i])], j)]) != -1)
+				continue;
+			
+			Vec_IntPushUnique(oNonSingleton,  oGroup1[Vec_IntEntry(iDep1[Vec_IntEntryLast(iMatch1[i])], j)]);
+			Vec_IntPushUnique(oMatchedGroups, oGroup1[Vec_IntEntry(iDep1[Vec_IntEntryLast(iMatch1[i])], j)]);		
+		}
+	}
+
+	subNtk1 = computeCofactor(pNtk1, nodesInLevel1, NULL, matchedInputs1);
+
+	for(j = idx-1; j < Vec_IntSize(iMatch2[i]) && MATCH_FOUND == FALSE; j++)
+	{
+		int tempJ;
+		Vec_Int_t * mismatch;
+
+		if( skipList[j] )
+			continue;
+
+		mismatch = Vec_IntAlloc(10);
+
+		Vec_IntPush(matchedInputs2, Vec_IntEntry(iMatch2[i], j));		
+		
+		subNtk2 = computeCofactor(pNtk2, nodesInLevel2, NULL, matchedInputs2);			
+
+		for(m = 0; m < Vec_IntSize(matchedOutputs1); m++)
+		{
+			Vec_PtrPush(oMatchPairs, Abc_NtkPo(subNtk1, Vec_IntEntry(matchedOutputs1, m)));
+			Vec_PtrPush(oMatchPairs, Abc_NtkPo(subNtk2, Vec_IntEntry(matchedOutputs2, m)));
+		}
+
+		counter++;
+
+		if( Abc_NtkBmSat( subNtk2, subNtk1, NULL, oMatchPairs, mismatch, 0) )				
+		{
+			if(idx-1 != j)
+			{
+				tempJ = Vec_IntEntry(iMatch2[i], idx-1);
+				Vec_IntWriteEntry(iMatch2[i], idx-1, Vec_IntEntry(iMatch2[i], j));
+				Vec_IntWriteEntry(iMatch2[i], j, tempJ);
+			}
+
+			/*fprintf(matchFile, "%s matched to %s\n", Abc_ObjName(Abc_NtkPi(pNtk1, Vec_IntEntry(iMatch1[i], idx-1))), 
+										    		  Abc_ObjName(Abc_NtkPi(pNtk2, Vec_IntEntry(iMatch2[i], j))));*/
+
+			// we look for a match for outputs in oNonSingleton								
+			matchNonSingletonOutputs(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1,
+									 pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2,
+									 matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton,						 
+									 subNtk1, subNtk2, oMatchPairs, oNonSingleton, 0, 0, ii, idx);
+			
+			
+			if(idx-1 != j)
+			{
+				tempJ = Vec_IntEntry(iMatch2[i], idx-1);
+				Vec_IntWriteEntry(iMatch2[i], idx-1, Vec_IntEntry(iMatch2[i], j));
+				Vec_IntWriteEntry(iMatch2[i], j, tempJ);
+			}
+		}
+		else
+		{
+			Abc_Ntk_t * FpNtk1, * FpNtk2;
+			int * bitVector1, * bitVector2;
+			Vec_Int_t * currInputs1, * currInputs2;			
+			Vec_Ptr_t * vSupp;	
+			Abc_Obj_t * pObj;
+			int suppNum1 = 0;
+			int * suppNum2;			
+			
+			bitVector1 = ABC_ALLOC( int, Abc_NtkPiNum(pNtk1) );
+			bitVector2 = ABC_ALLOC( int, Abc_NtkPiNum(pNtk2) );
+
+			currInputs1 = Vec_IntAlloc(10);
+			currInputs2 = Vec_IntAlloc(10);		
+			
+			suppNum2 = ABC_ALLOC(int, Vec_IntSize(iMatch2[i])-idx+1);
+
+			for(m = 0; m < Abc_NtkPiNum(pNtk1); m++)
+			{
+				bitVector1[m] = 0;
+				bitVector2[m] = 0;
+			}
+
+			for(m = 0; m < Vec_IntSize(iMatch2[i])-idx+1; m++)						
+				suppNum2[m]= 0;			
+
+			// First of all set the value of the inputs that are already matched and are in mismatch
+			for(m = 0; m < Vec_IntSize(mismatch); m += 2)
+			{
+				int n = Vec_IntEntry(mismatch, m);
+					
+				bitVector1[Vec_IntEntry(matchedInputs1, n)] = Vec_IntEntry(mismatch, m+1);
+				bitVector2[Vec_IntEntry(matchedInputs2, n)] = Vec_IntEntry(mismatch, m+1);
+				
+			}
+			
+			for(m = idx-1; m < Vec_IntSize(iMatch1[i]); m++)
+			{
+				Vec_IntPush(currInputs1, Vec_IntEntry(iMatch1[i], m));
+				Vec_IntPush(currInputs2, Vec_IntEntry(iMatch2[i], m));
+			}
+
+			// Then add all the inputs that are not yet matched to the currInputs
+			for(m = 0; m < Abc_NtkPiNum(pNtk1); m++)
+			{
+				if(Vec_IntFind( matchedInputs1, m ) == -1)
+					Vec_IntPushUnique(currInputs1, m);
+
+				if(Vec_IntFind( matchedInputs2, m ) == -1)
+					Vec_IntPushUnique(currInputs2, m);
+			}
+
+			FpNtk1 = computeCofactor(pNtk1, nodesInLevel1, bitVector1, currInputs1);			
+			FpNtk2 = computeCofactor(pNtk2, nodesInLevel2, bitVector2, currInputs2);    
+
+			Abc_NtkForEachPo( FpNtk1, pObj, m )
+			{		
+				int n;
+				vSupp  = Abc_NtkNodeSupport( FpNtk1, &pObj, 1 );			    		
+				
+				for(n = 0; n < vSupp->nSize; n++)
+					if( Abc_ObjId((Abc_Obj_t *)vSupp->pArray[n]) == 1 )
+						suppNum1 += Vec_IntFind( matchedOutputs1, m) + 1;				
+						
+				Vec_PtrFree( vSupp );
+			}
+			
+			Abc_NtkForEachPo( FpNtk2, pObj, m )
+			{		
+				int n;
+				vSupp  = Abc_NtkNodeSupport( FpNtk2, &pObj, 1 );			    		
+				
+				for(n = 0; n < vSupp->nSize; n++)
+					if( (int)Abc_ObjId((Abc_Obj_t *)vSupp->pArray[n])-1 < (Vec_IntSize(iMatch2[i]))-idx+1 &&
+						(int)Abc_ObjId((Abc_Obj_t *)vSupp->pArray[n])-1 >= 0)
+						suppNum2[Abc_ObjId((Abc_Obj_t *)vSupp->pArray[n])-1] += Vec_IntFind( matchedOutputs2, m) + 1;				
+						
+				Vec_PtrFree( vSupp );
+			}
+
+			/*if(suppNum1 != 0)			
+				printf("Ntk1 is trigged");			
+
+			if(suppNum2[0] != 0)
+				printf("Ntk2 is trigged");*/
+
+			for(m = 0; m < Vec_IntSize(iMatch2[i])-idx+1; m++)
+				if(suppNum2[m] != suppNum1)
+				{
+					skipList[m+idx-1] = TRUE;					
+					/*printf("input is skipped");*/
+				}
+				
+			Abc_NtkDelete( FpNtk1 );
+			Abc_NtkDelete( FpNtk2 );
+			ABC_FREE( bitVector1 );	
+ 			ABC_FREE( bitVector2 );	
+			Vec_IntFree( currInputs1 );
+			Vec_IntFree( currInputs2 );			
+			ABC_FREE( suppNum2 );
+		}
+		
+		Vec_PtrClear(oMatchPairs);
+		Abc_NtkDelete( subNtk2 );
+		Vec_IntFree(mismatch);
+
+		//Vec_IntWriteEntry(iMatch2[i], j, tempJ);		
+		
+		if( MATCH_FOUND == FALSE )
+			Vec_IntPop(matchedInputs2);
+	}
+
+	if( MATCH_FOUND == FALSE )
+	{
+		Vec_IntPop(matchedInputs1);	
+		
+		if(idx == 1)
+		{
+			for(m = 0; m < Vec_IntSize(oNonSingleton); m++)
+				Vec_IntPop( oMatchedGroups );
+		}
+	}
+	
+	Vec_IntFree( oNonSingleton );	
+	Vec_PtrFree( oMatchPairs );	
+	ABC_FREE( skipList );
+	Abc_NtkDelete( subNtk1 );	
+
+	if(MATCH_FOUND && counter != 0)
+	{		
+		/*printf("Number of INPUT SAT instances = %d\n", counter);*/
+
+		counter = 0;
+	}
+
+	return MATCH_FOUND;
+}
+
+float refineBySAT(Abc_Ntk_t * pNtk1, Vec_Int_t ** iMatch1, int * iGroup1, Vec_Int_t ** iDep1, int* iLastItem1, Vec_Int_t ** oMatch1, int * oGroup1, Vec_Int_t ** oDep1, int* oLastItem1, int * observability1,
+				 Abc_Ntk_t * pNtk2, Vec_Int_t ** iMatch2, int * iGroup2, Vec_Int_t ** iDep2, int* iLastItem2, Vec_Int_t ** oMatch2, int * oGroup2, Vec_Int_t ** oDep2, int* oLastItem2, int * observability2)
+{
+	int i, j;	
+	Abc_Obj_t * pObj;
+	Vec_Int_t * iNonSingleton;
+	Vec_Int_t * matchedInputs1, * matchedInputs2;
+	Vec_Int_t * matchedOutputs1, * matchedOutputs2;
+	Vec_Ptr_t ** nodesInLevel1, ** nodesInLevel2;
+	Vec_Int_t * oMatchedGroups;
+	FILE *result;	
+	int matchFound;
+	abctime clk = Abc_Clock();
+	float satTime = 0.0;
+
+	/*matchFile = fopen("satmatch.txt", "w");*/
+	
+	iNonSingleton = Vec_IntAlloc(10);	
+	
+	matchedInputs1 = Vec_IntAlloc( Abc_NtkPiNum(pNtk1) );
+	matchedInputs2 = Vec_IntAlloc( Abc_NtkPiNum(pNtk2) );
+
+	matchedOutputs1 = Vec_IntAlloc( Abc_NtkPoNum(pNtk1) );
+	matchedOutputs2 = Vec_IntAlloc( Abc_NtkPoNum(pNtk2) );
+
+	nodesInLevel1 = ABC_ALLOC( Vec_Ptr_t *, Abc_AigLevel( pNtk1 ) + 1);	// why numOfLevels+1? because the inputs are in level 0
+	for(i = 0; i <= Abc_AigLevel( pNtk1 ); i++)
+		nodesInLevel1[i] = Vec_PtrAlloc( 20 );
+
+	// bucket sort the objects based on their levels
+	Abc_AigForEachAnd( pNtk1, pObj, i )	
+		Vec_PtrPush(nodesInLevel1[Abc_ObjLevel(pObj)], pObj);
+	
+	nodesInLevel2 = ABC_ALLOC( Vec_Ptr_t *, Abc_AigLevel( pNtk2 ) + 1);	// why numOfLevels+1? because the inputs are in level 0
+	for(i = 0; i <= Abc_AigLevel( pNtk2 ); i++)
+		nodesInLevel2[i] = Vec_PtrAlloc( 20 );
+
+	// bucket sort the objects based on their levels
+	Abc_AigForEachAnd( pNtk2, pObj, i )	
+		Vec_PtrPush(nodesInLevel2[Abc_ObjLevel(pObj)], pObj);	
+
+	oMatchedGroups = Vec_IntAlloc( 10 );
+
+	for(i = 0; i < *iLastItem1; i++)
+	{
+		if(Vec_IntSize(iMatch1[i]) == 1)
+		{
+			Vec_IntPush(matchedInputs1, Vec_IntEntryLast(iMatch1[i]));
+			Vec_IntPush(matchedInputs2, Vec_IntEntryLast(iMatch2[i]));		
+		}
+		else
+			Vec_IntPush(iNonSingleton, i);
+	}
+
+	for(i = 0; i < *oLastItem1; i++)
+	{
+		if(Vec_IntSize(oMatch1[i]) == 1)
+		{
+			Vec_IntPush(matchedOutputs1, Vec_IntEntryLast(oMatch1[i]));
+			Vec_IntPush(matchedOutputs2, Vec_IntEntryLast(oMatch2[i]));
+		}
+	}
+	
+	for(i = 0; i < Vec_IntSize(iNonSingleton) - 1; i++)
+	{
+		for(j = i + 1; j < Vec_IntSize(iNonSingleton); j++)		
+			if( observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, j)], 0)] > 
+				observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, i)], 0)] )
+			{				
+				int temp = Vec_IntEntry(iNonSingleton, i);
+				Vec_IntWriteEntry( iNonSingleton, i, Vec_IntEntry(iNonSingleton, j) );
+				Vec_IntWriteEntry( iNonSingleton, j, temp );				
+			}
+			else if( observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, j)], 0)] == 
+					 observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, i)], 0)] )
+			{
+				if( Vec_IntSize(iMatch2[Vec_IntEntry(iNonSingleton, j)]) < Vec_IntSize(iMatch2[Vec_IntEntry(iNonSingleton, i)]) )
+				{
+					int temp = Vec_IntEntry(iNonSingleton, i);
+					Vec_IntWriteEntry( iNonSingleton, i, Vec_IntEntry(iNonSingleton, j) );
+					Vec_IntWriteEntry( iNonSingleton, j, temp );				
+				}
+			}
+	}	
+
+	/*for(i = 0; i < Vec_IntSize(iNonSingleton) - 1; i++)
+	{
+		for(j = i + 1; j < Vec_IntSize(iNonSingleton); j++)		
+			if( Vec_IntSize(oDep2[oGroup2[Vec_IntEntryLast(iMatch2[Vec_IntEntry(iNonSingleton, j)])]]) > 
+				Vec_IntSize(oDep2[oGroup2[Vec_IntEntryLast(iMatch2[Vec_IntEntry(iNonSingleton, i)])]]) )
+			{				
+				int temp = Vec_IntEntry(iNonSingleton, i);
+				Vec_IntWriteEntry( iNonSingleton, i, Vec_IntEntry(iNonSingleton, j) );
+				Vec_IntWriteEntry( iNonSingleton, j, temp );				
+			}
+			else if( Vec_IntSize(oDep2[oGroup2[Vec_IntEntryLast(iMatch2[Vec_IntEntry(iNonSingleton, j)])]]) == 
+				Vec_IntSize(oDep2[oGroup2[Vec_IntEntryLast(iMatch2[Vec_IntEntry(iNonSingleton, i)])]]) )
+			{
+				if( observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, j)], 0)] > 
+						observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, i)], 0)] )
+				{
+					int temp = Vec_IntEntry(iNonSingleton, i);
+					Vec_IntWriteEntry( iNonSingleton, i, Vec_IntEntry(iNonSingleton, j) );
+					Vec_IntWriteEntry( iNonSingleton, j, temp );				
+				}
+			}
+	}*/
+
+	matchFound = match1by1(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1,
+						   pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2,
+						   matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton, 0, 0);
+
+	if( matchFound && Vec_IntSize(matchedOutputs1) != Abc_NtkPoNum(pNtk1) )
+	{
+		Vec_Int_t * oNonSingleton;
+		Vec_Ptr_t * oMatchPairs;
+		Abc_Ntk_t * subNtk1, * subNtk2;
+
+		oNonSingleton = Vec_IntAlloc( 10 );
+		
+		oMatchPairs = Vec_PtrAlloc(Abc_NtkPoNum(pNtk1) * 2);	
+
+		for(i = 0; i < *oLastItem1; i++)
+			if( Vec_IntSize(oMatch1[i]) > 1 && Vec_IntFind( oMatchedGroups, i) == -1 )
+				Vec_IntPush(oNonSingleton, i);
+			
+		subNtk1 = computeCofactor(pNtk1, nodesInLevel1, NULL, matchedInputs1);
+		subNtk2 = computeCofactor(pNtk2, nodesInLevel2, NULL, matchedInputs2);
+		
+		matchFound = matchNonSingletonOutputs(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1,
+								 pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup1, oMatch2, oGroup2,
+								 matchedOutputs1, matchedOutputs2, oMatchedGroups, NULL,						 
+								 subNtk1, subNtk2, oMatchPairs, oNonSingleton, 0, 0, 0, 0);
+
+		Vec_IntFree( oNonSingleton );		
+		Vec_PtrFree( oMatchPairs );
+
+		Abc_NtkDelete(subNtk1);
+		Abc_NtkDelete(subNtk2);
+	}
+
+	satTime = (float)(Abc_Clock() - clk)/(float)(CLOCKS_PER_SEC);	
+
+	if( matchFound )
+	{
+  		checkEquivalence( pNtk1, matchedInputs1, matchedOutputs1, pNtk2, matchedInputs2, matchedOutputs2);
+
+		result = fopen("IOmatch.txt", "w");
+
+		fprintf(result, "I/O = %d / %d \n\n", Abc_NtkPiNum(pNtk1), Abc_NtkPoNum(pNtk1));
+		
+		for(i = 0; i < Vec_IntSize(matchedInputs1) ; i++)
+  			fprintf(result, "{%s}\t{%s}\n", Abc_ObjName(Abc_NtkPi(pNtk1, Vec_IntEntry(matchedInputs1, i))), Abc_ObjName(Abc_NtkPi(pNtk2, Vec_IntEntry(matchedInputs2, i))) );									
+
+		fprintf(result, "\n-----------------------------------------\n");
+
+		for(i = 0; i < Vec_IntSize(matchedOutputs1) ; i++)
+			fprintf(result, "{%s}\t{%s}\n", Abc_ObjName(Abc_NtkPo(pNtk1, Vec_IntEntry(matchedOutputs1, i))), Abc_ObjName(Abc_NtkPo(pNtk2, Vec_IntEntry(matchedOutputs2, i))) );									
+
+		fclose( result );	
+	}
+
+	Vec_IntFree( matchedInputs1 );
+	Vec_IntFree( matchedInputs2 );
+	Vec_IntFree( matchedOutputs1 );
+	Vec_IntFree( matchedOutputs2 );
+	Vec_IntFree( iNonSingleton );
+	Vec_IntFree( oMatchedGroups );
+	
+	for(i = 0; i <= Abc_AigLevel( pNtk1 ); i++)	
+		Vec_PtrFree( nodesInLevel1[i] );
+	for(i = 0; i <= Abc_AigLevel( pNtk2 ); i++)	
+		Vec_PtrFree( nodesInLevel2[i] );
+	
+
+	ABC_FREE( nodesInLevel1 );
+	ABC_FREE( nodesInLevel2 );
+	/*fclose(matchFile);*/
+	
+	return satTime;
+}
+
+int checkListConsistency(Vec_Int_t ** iMatch1, Vec_Int_t ** oMatch1, Vec_Int_t ** iMatch2, Vec_Int_t ** oMatch2, int iLastItem1, int oLastItem1, int iLastItem2, int oLastItem2)
+{
+	//int i;
+
+	if(iLastItem1 != iLastItem2 || oLastItem1 != oLastItem2)
+		return FALSE;
+
+	/*for(i = 0; i < iLastItem1; i++) {
+		if(Vec_IntSize(iMatch1[i]) != Vec_IntSize(iMatch2[i]))
+			return FALSE;
+	}
+
+	for(i = 0; i < oLastItem1; i++) {
+		if(Vec_IntSize(oMatch1[i]) != Vec_IntSize(oMatch2[i]))
+			return FALSE;
+	}*/
+		
+	return TRUE;
+}
+
+
+void bmGateWay( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int p_equivalence )
+{	
+	Vec_Int_t ** iDep1, ** oDep1;
+	Vec_Int_t ** iDep2, ** oDep2;
+	Vec_Int_t ** iMatch1, ** oMatch1;
+	Vec_Int_t ** iMatch2, ** oMatch2;		
+	int * iGroup1, * oGroup1;
+	int * iGroup2, * oGroup2;
+	int iLastItem1, oLastItem1;
+	int iLastItem2, oLastItem2;	
+	int i, j;	
+	
+	char * vPiValues1, * vPiValues2;
+	int * observability1, * observability2;
+	abctime clk = Abc_Clock();
+	float initTime;
+	float simulTime;
+	float satTime;
+	Vec_Ptr_t ** topOrder1 = NULL, ** topOrder2 = NULL;
+
+	extern void getDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep);
+	extern void initMatchList(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep, Vec_Int_t** iMatch, int* iLastItem, Vec_Int_t** oMatch, int* oLastItem, int* iGroup, int* oGroup, int p_equivalence);		
+	extern void iSortDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, int* oGroup);
+	extern void oSortDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** oDep, int* iGroup);
+	extern int iSplitByDep(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** iMatch, int* iGroup, int* iLastItem, int* oGroup);
+	extern int oSplitByDep(Abc_Ntk_t *pNtk, Vec_Int_t** oDep, Vec_Int_t** oMatch, int* oGroup, int* oLastItem, int* iGroup);	
+	extern Vec_Ptr_t ** findTopologicalOrder(Abc_Ntk_t * pNtk);
+	extern int refineIOBySimulation(Abc_Ntk_t *pNtk, Vec_Int_t** iMatch, int* iLastItem, int * iGroup, Vec_Int_t** iDep, Vec_Int_t** oMatch, int* oLastItem, int * oGroup, Vec_Int_t** oDep, char * vPiValues, int * observability, Vec_Ptr_t ** topOrder);	
+	extern float refineBySAT(Abc_Ntk_t * pNtk1, Vec_Int_t ** iMatch1, int * iGroup1, Vec_Int_t ** iDep1, int* iLastItem1, Vec_Int_t ** oMatch1, int * oGroup1, Vec_Int_t ** oDep1, int* oLastItem1, int * observability1,
+							Abc_Ntk_t * pNtk2, Vec_Int_t ** iMatch2, int * iGroup2, Vec_Int_t ** iDep2, int* iLastItem2, Vec_Int_t ** oMatch2, int * oGroup2, Vec_Int_t ** oDep2, int* oLastItem2, int * observability2);				
+	int checkListConsistency(Vec_Int_t ** iMatch1, Vec_Int_t ** oMatch1, Vec_Int_t ** iMatch2, Vec_Int_t ** oMatch2, int iLastItem1, int oLastItem1, int iLastItem2, int oLastItem2);	
+
+	iDep1 = ABC_ALLOC( Vec_Int_t*,  (unsigned)Abc_NtkPiNum(pNtk1) );
+	oDep1 = ABC_ALLOC( Vec_Int_t*,  (unsigned)Abc_NtkPoNum(pNtk1) );
+
+	iDep2 = ABC_ALLOC( Vec_Int_t*,  (unsigned)Abc_NtkPiNum(pNtk2) );
+	oDep2 = ABC_ALLOC( Vec_Int_t*,  (unsigned)Abc_NtkPoNum(pNtk2) );
+
+	iMatch1 = ABC_ALLOC( Vec_Int_t*,  (unsigned)Abc_NtkPiNum(pNtk1) );
+	oMatch1 = ABC_ALLOC( Vec_Int_t*,  (unsigned)Abc_NtkPoNum(pNtk1) );
+
+	iMatch2 = ABC_ALLOC( Vec_Int_t*,  (unsigned)Abc_NtkPiNum(pNtk2) );
+	oMatch2 = ABC_ALLOC( Vec_Int_t*,  (unsigned)Abc_NtkPoNum(pNtk2) );		
+
+	iGroup1 = ABC_ALLOC( int, Abc_NtkPiNum(pNtk1) );
+	oGroup1 = ABC_ALLOC( int, Abc_NtkPoNum(pNtk1) );
+
+	iGroup2 = ABC_ALLOC( int, Abc_NtkPiNum(pNtk2) );
+	oGroup2 = ABC_ALLOC( int, Abc_NtkPoNum(pNtk2) );
+
+	vPiValues1 = ABC_ALLOC( char,  Abc_NtkPiNum(pNtk1) + 1);
+	vPiValues1[Abc_NtkPiNum(pNtk1)] = '\0';	
+
+	vPiValues2 = ABC_ALLOC( char,  Abc_NtkPiNum(pNtk2) + 1);
+	vPiValues2[Abc_NtkPiNum(pNtk2)] = '\0';	
+
+	observability1 = ABC_ALLOC(int, (unsigned)Abc_NtkPiNum(pNtk1));
+	observability2 = ABC_ALLOC(int, (unsigned)Abc_NtkPiNum(pNtk2));
+
+	for(i = 0; i < Abc_NtkPiNum(pNtk1); i++)
+	{		
+		iDep1[i] = Vec_IntAlloc( 1 );
+		iMatch1[i] = Vec_IntAlloc( 1 );
+
+		iDep2[i] = Vec_IntAlloc( 1 );
+		iMatch2[i] = Vec_IntAlloc( 1 );
+
+		vPiValues1[i] = '0';
+		vPiValues2[i] = '0';
+
+		observability1[i] = 0;
+		observability2[i] = 0;
+	}
+
+	for(i = 0; i < Abc_NtkPoNum(pNtk1); i++)
+	{
+		oDep1[i] = Vec_IntAlloc( 1 );
+		oMatch1[i] = Vec_IntAlloc( 1 );
+
+		oDep2[i] = Vec_IntAlloc( 1 );
+		oMatch2[i] = Vec_IntAlloc( 1 );
+	}	
+	
+	/************* Strashing ************/	
+	pNtk1 = Abc_NtkStrash( pNtk1, 0, 0, 0 );	
+	pNtk2 = Abc_NtkStrash( pNtk2, 0, 0, 0 );			
+	printf("Network  strashing is done!\n");	
+	/************************************/	
+	
+	/******* Getting Dependencies *******/	
+	getDependencies(pNtk1, iDep1, oDep1);
+	getDependencies(pNtk2, iDep2, oDep2);			
+	printf("Getting dependencies is done!\n");	
+	/************************************/
+
+	/***** Intializing match lists ******/	
+	initMatchList(pNtk1, iDep1, oDep1, iMatch1, &iLastItem1, oMatch1, &oLastItem1, iGroup1, oGroup1, p_equivalence);			
+	initMatchList(pNtk2, iDep2, oDep2, iMatch2, &iLastItem2, oMatch2, &oLastItem2, iGroup2, oGroup2, p_equivalence);	
+	printf("Initializing match lists is done!\n");		
+	/************************************/
+
+	if( !checkListConsistency(iMatch1, oMatch1, iMatch2, oMatch2, iLastItem1, oLastItem1, iLastItem2, oLastItem2) )
+	{
+		fprintf( stdout, "I/O dependencies of two circuits are different.\n");
+		goto freeAndExit;
+	}		
+
+	printf("Refining IOs by dependencies ...");				
+	// split match lists further by checking dependencies
+	do
+	{
+		int iNumOfItemsAdded = 1, oNumOfItemsAdded = 1;		
+
+		do
+		{	
+			if( oNumOfItemsAdded )
+			{
+				iSortDependencies(pNtk1, iDep1, oGroup1);
+				iSortDependencies(pNtk2, iDep2, oGroup2);
+			}
+			
+			if( iNumOfItemsAdded )
+			{
+				oSortDependencies(pNtk1, oDep1, iGroup1);
+				oSortDependencies(pNtk2, oDep2, iGroup2);
+			}
+
+			if( iLastItem1 < Abc_NtkPiNum(pNtk1) )
+			{				
+				iSplitByDep(pNtk1, iDep1, iMatch1, iGroup1, &iLastItem1, oGroup1);
+				if( oLastItem1 < Abc_NtkPoNum(pNtk1) )
+					oSplitByDep(pNtk1, oDep1, oMatch1, oGroup1, &oLastItem1, iGroup1);
+			}				
+
+			if( iLastItem2 < Abc_NtkPiNum(pNtk2) )
+			{				
+				iNumOfItemsAdded = iSplitByDep(pNtk2, iDep2, iMatch2, iGroup2, &iLastItem2, oGroup2);
+				if( oLastItem2 < Abc_NtkPoNum(pNtk2) )		
+					oNumOfItemsAdded = oSplitByDep(pNtk2, oDep2, oMatch2, oGroup2, &oLastItem2, iGroup2);
+				else
+					oNumOfItemsAdded = 0;
+			}
+			else
+				iNumOfItemsAdded = 0;							
+			
+			if(!checkListConsistency(iMatch1, oMatch1, iMatch2, oMatch2, iLastItem1, oLastItem1, iLastItem2, oLastItem2))
+			{
+				fprintf( stdout, "I/O dependencies of two circuits are different.\n");
+				goto freeAndExit;
+			}		
+		}while(iNumOfItemsAdded != 0 || oNumOfItemsAdded != 0);
+
+	}while(0);
+
+	printf(" done!\n");
+
+	initTime = ((float)(Abc_Clock() - clk)/(float)(CLOCKS_PER_SEC));	
+	clk = Abc_Clock();
+
+	topOrder1 = findTopologicalOrder(pNtk1);
+	topOrder2 = findTopologicalOrder(pNtk2);
+
+	printf("Refining IOs by simulation ...");				
+
+	do
+	{
+		int counter = 0;
+		int ioSuccess1, ioSuccess2;	
+		
+		do
+		{
+			for(i = 0; i < iLastItem1; i++)
+			{
+				int temp = (int)(SIM_RANDOM_UNSIGNED % 2);		
+				
+				if(Vec_IntSize(iMatch1[i]) != Vec_IntSize(iMatch2[i]))
+				{
+					fprintf( stdout, "Input refinement by simulation finds two circuits different.\n");				
+					goto freeAndExit;
+				}
+				
+				for(j = 0; j < Vec_IntSize(iMatch1[i]); j++)
+				{
+					vPiValues1[Vec_IntEntry(iMatch1[i], j)] = temp + '0';
+					vPiValues2[Vec_IntEntry(iMatch2[i], j)] = temp + '0';	
+				}			
+			}					
+			
+			ioSuccess1 = refineIOBySimulation(pNtk1, iMatch1, &iLastItem1, iGroup1, iDep1, oMatch1, &oLastItem1, oGroup1, oDep1, vPiValues1, observability1, topOrder1);				
+			ioSuccess2 = refineIOBySimulation(pNtk2, iMatch2, &iLastItem2, iGroup2, iDep2, oMatch2, &oLastItem2, oGroup2, oDep2, vPiValues2, observability2, topOrder2);
+			
+			if(ioSuccess1 && ioSuccess2)
+				counter = 0;
+			else
+				counter++;						
+			
+			if(ioSuccess1 != ioSuccess2 ||
+			   !checkListConsistency(iMatch1, oMatch1, iMatch2, oMatch2, iLastItem1, oLastItem1, iLastItem2, oLastItem2))
+			{
+				fprintf( stdout, "Input refinement by simulation finds two circuits different.\n");				
+				goto freeAndExit;
+			}
+		}while(counter <= 200);				
+		
+	}while(0);	
+
+	printf(" done!\n");
+	
+	simulTime = (float)(Abc_Clock() - clk)/(float)(CLOCKS_PER_SEC);
+	printf("SAT-based search started ...\n");
+
+	satTime = refineBySAT(pNtk1, iMatch1, iGroup1, iDep1, &iLastItem1, oMatch1, oGroup1, oDep1, &oLastItem1, observability1,
+		   					   pNtk2, iMatch2, iGroup2, iDep2, &iLastItem2, oMatch2, oGroup2, oDep2, &oLastItem2, observability2);
+
+	printf( "Init Time = %4.2f\n", initTime );	
+	printf( "Simulation Time = %4.2f\n", simulTime );
+	printf( "SAT Time = %4.2f\n", satTime );
+	printf( "Overall Time = %4.2f\n", initTime + simulTime + satTime );
+	
+freeAndExit:
+
+	for(i = 0; i < iLastItem1 ; i++)
+	{			
+		
+		Vec_IntFree( iMatch1[i] );
+		Vec_IntFree( iMatch2[i] );
+	}
+	
+	for(i = 0; i < oLastItem1 ; i++)
+	{			
+		
+		Vec_IntFree( oMatch1[i] );
+		Vec_IntFree( oMatch2[i] );
+	}
+
+	for(i = 0; i < Abc_NtkPiNum(pNtk1); i++)
+	{
+		Vec_IntFree( iDep1[i] );
+		Vec_IntFree( iDep2[i] );
+		if(topOrder1 != NULL) {
+			Vec_PtrFree( topOrder1[i] );
+			Vec_PtrFree( topOrder2[i] );
+		}
+	}
+
+	for(i = 0; i < Abc_NtkPoNum(pNtk1); i++)
+	{
+		Vec_IntFree( oDep1[i] );
+		Vec_IntFree( oDep2[i] );
+	}
+
+	ABC_FREE( iMatch1 );
+	ABC_FREE( iMatch2 );
+	ABC_FREE( oMatch1 );
+	ABC_FREE( oMatch2 );
+	ABC_FREE( iDep1 );
+	ABC_FREE( iDep2 );
+	ABC_FREE( oDep1 );
+	ABC_FREE( oDep2 );
+	ABC_FREE( iGroup1 );
+	ABC_FREE( iGroup2 );
+	ABC_FREE( oGroup1 );
+	ABC_FREE( oGroup2 );	
+	ABC_FREE( vPiValues1 );
+	ABC_FREE( vPiValues2 );
+	ABC_FREE( observability1 );
+	ABC_FREE( observability2 );
+	if(topOrder1 != NULL) {
+		ABC_FREE( topOrder1 );
+		ABC_FREE( topOrder2 );
+	}
+}ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcBmc.c b/abc-build/src/base/abci/abcBmc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcBmc.c
@@ -0,0 +1,122 @@
+/**CFile****************************************************************
+
+  FileName    [abcBmc.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Performs bounded model check.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcBmc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "aig/ivy/ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc );
+
+static void Abc_NtkBmcReport( Ivy_Man_t * pMan, Ivy_Man_t * pFrames, Ivy_Man_t * pFraig, Vec_Ptr_t * vMapping, int nFrames );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkBmc( Abc_Ntk_t * pNtk, int nFrames, int fInit, int fVerbose )
+{
+    Ivy_FraigParams_t Params, * pParams = &Params; 
+    Ivy_Man_t * pMan, * pFrames, * pFraig;
+    Vec_Ptr_t * vMapping;
+    // convert to IVY manager
+    pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+    // generate timeframes
+    pFrames = Ivy_ManFrames( pMan, Abc_NtkLatchNum(pNtk), nFrames, fInit, &vMapping );
+    // fraig the timeframes
+    Ivy_FraigParamsDefault( pParams );
+    pParams->nBTLimitNode = ABC_INFINITY;
+    pParams->fVerbose = 0;
+    pParams->fProve = 0;
+    pFraig = Ivy_FraigPerform( pFrames, pParams );
+printf( "Frames have %6d nodes.  ", Ivy_ManNodeNum(pFrames) );
+printf( "Fraig has %6d nodes.\n", Ivy_ManNodeNum(pFraig) );
+    // report the classes
+//    if ( fVerbose )
+//        Abc_NtkBmcReport( pMan, pFrames, pFraig, vMapping, nFrames );
+    // free stuff
+    Vec_PtrFree( vMapping );
+    Ivy_ManStop( pFraig );
+    Ivy_ManStop( pFrames );
+    Ivy_ManStop( pMan );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkBmcReport( Ivy_Man_t * pMan, Ivy_Man_t * pFrames, Ivy_Man_t * pFraig, Vec_Ptr_t * vMapping, int nFrames )
+{
+    Ivy_Obj_t * pFirst1, * pFirst2 = NULL, * pFirst3 = NULL;
+    int i, f, nIdMax, Prev2, Prev3;
+    nIdMax = Ivy_ManObjIdMax(pMan);
+    // check what is the number of nodes in each frame
+    Prev2 = Prev3 = 0;
+    for ( f = 0; f < nFrames; f++ )
+    {
+        Ivy_ManForEachNode( pMan, pFirst1, i )
+        {
+            pFirst2 = Ivy_Regular( (Ivy_Obj_t *)Vec_PtrEntry(vMapping, f * nIdMax + pFirst1->Id) );
+            if ( Ivy_ObjIsConst1(pFirst2) || pFirst2->Type == 0 )
+                continue;
+            pFirst3 = Ivy_Regular( pFirst2->pEquiv );
+            if ( Ivy_ObjIsConst1(pFirst3) || pFirst3->Type == 0 )
+                continue;
+            break;
+        }
+        assert(pFirst2);
+        assert(pFirst3);
+        if ( f )
+            printf( "Frame %3d :  Strash = %5d  Fraig = %5d\n", f, pFirst2->Id - Prev2, pFirst3->Id - Prev3 );
+        Prev2 = pFirst2->Id;
+        Prev3 = pFirst3->Id;   
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcCas.c b/abc-build/src/base/abci/abcCas.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcCas.c
@@ -0,0 +1,117 @@
+/**CFile****************************************************************
+
+  FileName    [abcCas.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Decomposition of shared BDDs into LUT cascade.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcCas.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/* 
+    This LUT cascade synthesis algorithm is described in the paper:
+    A. Mishchenko and T. Sasao, "Encoding of Boolean functions and its 
+    application to LUT cascade synthesis", Proc. IWLS '02, pp. 115-120.
+    http://www.eecs.berkeley.edu/~alanmi/publications/2002/iwls02_enc.pdf
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Abc_CascadeExperiment( char * pFileGeneric, DdManager * dd, DdNode ** pOutputs, int nInputs, int nOutputs, int nLutSize, int fCheck, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose )
+{
+    DdManager * dd;
+    DdNode ** ppOutputs;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pNode;
+    char * pFileGeneric;
+    int fBddSizeMax = 500000;
+    int i, fReorder = 1;
+    abctime clk = Abc_Clock();
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    // compute the global BDDs
+    if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL )
+        return NULL;
+
+    if ( fVerbose )
+    {
+        DdManager * dd = (DdManager *)Abc_NtkGlobalBddMan( pNtk );
+        printf( "Shared BDD size = %6d nodes.  ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+        ABC_PRT( "BDD construction time", Abc_Clock() - clk );
+    }
+
+    // collect global BDDs
+    dd = (DdManager *)Abc_NtkGlobalBddMan( pNtk );
+    ppOutputs = ABC_ALLOC( DdNode *, Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        ppOutputs[i] = (DdNode *)Abc_ObjGlobalBdd(pNode);
+
+    // call the decomposition
+    pFileGeneric = Extra_FileNameGeneric( pNtk->pSpec );
+    if ( !Abc_CascadeExperiment( pFileGeneric, dd, ppOutputs, Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), nLutSize, fCheck, fVerbose ) )
+    {
+        // the LUT size is too small
+    }
+
+    // for now, duplicate the network
+    pNtkNew = Abc_NtkDup( pNtk );
+
+    // cleanup
+    Abc_NtkFreeGlobalBdds( pNtk, 1 );
+    ABC_FREE( ppOutputs );
+    ABC_FREE( pFileGeneric );
+
+//    if ( pNtk->pExdc )
+//        pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkCollapse: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcCascade.c b/abc-build/src/base/abci/abcCascade.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcCascade.c
@@ -0,0 +1,1051 @@
+/**CFile****************************************************************
+
+  FileName    [abcCascade.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Collapsing the network into two-levels.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcCollapse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "bdd/reo/reo.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define BDD_FUNC_MAX 256
+
+//extern void Abc_NodeShowBddOne( DdManager * dd, DdNode * bFunc );
+extern DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop, DdNode ** pbVars );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derive BDD of the characteristic function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_ResBuildBdd( Abc_Ntk_t * pNtk, DdManager * dd )
+{
+    Vec_Ptr_t * vNodes, * vBdds, * vLocals;
+    Abc_Obj_t * pObj, * pFanin;
+    DdNode * bFunc, * bPart, * bTemp, * bVar;
+    int i, k;
+    assert( Abc_NtkIsSopLogic(pNtk) );
+    assert( Abc_NtkCoNum(pNtk) <= 3 );
+    vBdds = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        Vec_PtrWriteEntry( vBdds, Abc_ObjId(pObj), Cudd_bddIthVar(dd, i) );
+    // create internal node BDDs
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    vLocals = Vec_PtrAlloc( 6 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        if ( Abc_ObjFaninNum(pObj) == 0 )
+        {
+            bFunc = Cudd_NotCond( Cudd_ReadOne(dd), Abc_SopIsConst0((char *)pObj->pData) );  Cudd_Ref( bFunc );
+            Vec_PtrWriteEntry( vBdds, Abc_ObjId(pObj), bFunc );
+            continue;
+        }
+        Vec_PtrClear( vLocals );
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Vec_PtrPush( vLocals, Vec_PtrEntry(vBdds, Abc_ObjId(pFanin)) );
+        bFunc = Abc_ConvertSopToBdd( dd, (char *)pObj->pData, (DdNode **)Vec_PtrArray(vLocals) );  Cudd_Ref( bFunc );
+        Vec_PtrWriteEntry( vBdds, Abc_ObjId(pObj), bFunc );
+    }
+    Vec_PtrFree( vLocals );
+    // create char function
+    bFunc = Cudd_ReadOne( dd );  Cudd_Ref( bFunc );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        bVar  = Cudd_bddIthVar( dd, i + Abc_NtkCiNum(pNtk) );
+        bTemp = (DdNode *)Vec_PtrEntry( vBdds, Abc_ObjFaninId0(pObj) );
+        bPart = Cudd_bddXnor( dd, bTemp, bVar );          Cudd_Ref( bPart );
+        bFunc = Cudd_bddAnd( dd, bTemp = bFunc, bPart );  Cudd_Ref( bFunc );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bPart );
+    }
+    // dereference
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        Cudd_RecursiveDeref( dd, (DdNode *)Vec_PtrEntry(vBdds, Abc_ObjId(pObj)) );
+    Vec_PtrFree( vBdds );
+    Vec_PtrFree( vNodes );
+    // reorder
+    Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 );
+    Cudd_Deref( bFunc );
+    return bFunc;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Initializes variable partition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ResStartPart( int nInputs, unsigned uParts[], int nParts )
+{
+    int i, Group, Left, Shift = 0, Count = 0;
+    Group = nInputs / nParts;
+    Left  = nInputs % nParts;
+    for ( i = 0; i < Left; i++ )
+    {
+        uParts[i] = (~((~0) << (Group+1))) << Shift;
+        Shift += Group+1;
+    }
+    for (      ; i < nParts; i++ )
+    {
+        uParts[i] = (~((~0) << Group)) << Shift;
+        Shift += Group;
+    }
+    for ( i = 0; i < nParts; i++ )
+        Count += Extra_WordCountOnes( uParts[i] );
+    assert( Count == nInputs );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Initializes variable partition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ResStartPart2( int nInputs, unsigned uParts[], int nParts )
+{
+    int i, Count = 0;
+    for ( i = 0; i < nParts; i++ )
+        uParts[i] = 0;
+    for ( i = 0; i < nInputs; i++ )
+        uParts[i % nParts] |= (1 << i);
+    for ( i = 0; i < nParts; i++ )
+        Count += Extra_WordCountOnes( uParts[i] );
+    assert( Count == nInputs );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Returns one if unique pattern.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ResCheckUnique( char Pats[], int nPats, int pat )
+{
+    int i;
+    for ( i = 0; i < nPats; i++ )
+        if ( Pats[i] == pat )
+            return 0;
+    return 1;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Check if pattern is decomposable with non-strict.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ResCheckNonStrict( char Pattern[], int nVars, int nBits )
+{
+    static char Pat0[256], Pat1[256];
+    int v, m, nPats0, nPats1, nNumber = (1 << (nBits - 1));
+    int Result = 0;
+    for ( v = 0; v < nVars; v++ )
+    {
+        nPats0 = nPats1 = 0;
+        for ( m = 0; m < (1<<nVars); m++ )
+        {
+            if ( (m & (1 << v)) == 0 )
+            {
+                if ( Abc_ResCheckUnique( Pat0, nPats0, Pattern[m] ) )
+                {
+                    Pat0[ nPats0++ ] = Pattern[m];
+                    if ( nPats0 > nNumber )
+                        break;
+                }
+            }
+            else
+            {
+                if ( Abc_ResCheckUnique( Pat1, nPats1, Pattern[m] ) )
+                {
+                    Pat1[ nPats1++ ] = Pattern[m];
+                    if ( nPats1 > nNumber )
+                        break;
+                }
+            }
+        }
+        if ( m == (1<<nVars) )
+            Result++;
+    }
+    return Result;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the number of distinct cofactors in the BDD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ResCofCount( DdManager * dd, DdNode * bFunc, unsigned uMask, int * pCheck )
+{
+    static char Pattern[256];
+    DdNode * pbVars[32];
+    Vec_Ptr_t * vCofs;
+    DdNode * bCof, * bCube, * bTemp;
+    int i, k, Result, nVars = 0;
+    // collect variables
+    for ( i = 0; i < 32; i++ )
+        if ( uMask & (1 << i) )
+            pbVars[nVars++] = dd->vars[i];
+    assert( nVars <= 8 );
+    // compute cofactors
+    vCofs = Vec_PtrAlloc( 100 );
+    for ( i = 0; i < (1 << nVars); i++ )
+    {
+        bCube = Extra_bddBitsToCube( dd, i, nVars, pbVars, 1 );  Cudd_Ref( bCube );
+        bCof  = Cudd_Cofactor( dd, bFunc, bCube );               Cudd_Ref( bCof );
+        Cudd_RecursiveDeref( dd, bCube );
+        Vec_PtrForEachEntry( DdNode *, vCofs, bTemp, k )
+            if ( bTemp == bCof )
+                break;
+        if ( k < Vec_PtrSize(vCofs) )
+            Cudd_RecursiveDeref( dd, bCof );
+        else
+            Vec_PtrPush( vCofs, bCof );
+        Pattern[i] = k;
+    }
+    Result = Vec_PtrSize( vCofs );
+    Vec_PtrForEachEntry( DdNode *, vCofs, bCof, i )
+        Cudd_RecursiveDeref( dd, bCof );
+    Vec_PtrFree( vCofs );
+    if ( pCheck )
+    {
+        *pCheck = Abc_ResCheckNonStrict( Pattern, nVars, Abc_Base2Log(Result) );
+/*
+        if ( *pCheck == 1 && nVars == 4 && Result == 8 )
+        {
+            for ( i = 0; i < (1 << nVars); i++ )
+                printf( "%d ", Pattern[i] );
+            i = 0;
+        }
+*/
+    }
+    return Result;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes cost of the partition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ResCost( DdManager * dd, DdNode * bFunc, unsigned uMask, int * pnCofs, int * pCheck )
+{
+    int nCofs = Abc_ResCofCount( dd, bFunc, uMask, pCheck );
+    int n2Log = Abc_Base2Log( nCofs );
+    if ( pnCofs ) *pnCofs = nCofs;
+    return 10000 * n2Log + (nCofs - (1 << (n2Log-1))) * (nCofs - (1 << (n2Log-1)));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Migrates variables between the two groups.]
+
+  Description [Returns 1 if there is change.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ResMigrate( DdManager * dd, DdNode * bFunc, int nInputs, unsigned uParts[], int iPart1, int iPart2 )
+{
+    unsigned uParts2[2] = { uParts[iPart1], uParts[iPart2] };
+    int i, k, CostCur, CostBest, fChange = 0;
+    assert( (uParts[iPart1] & uParts[iPart2]) == 0 );
+    CostBest = Abc_ResCost( dd, bFunc, uParts[iPart1], NULL, NULL ) 
+             + Abc_ResCost( dd, bFunc, uParts[iPart2], NULL, NULL );
+    for ( i = 0; i < nInputs; i++ )
+    if ( uParts[iPart1] & (1 << i) )
+    {
+        for ( k = 0; k < nInputs; k++ )
+        if ( uParts[iPart2] & (1 << k) )
+        {
+            if ( i == k )
+                continue;
+            uParts[iPart1] ^= (1 << i) | (1 << k);
+            uParts[iPart2] ^= (1 << i) | (1 << k);
+            CostCur = Abc_ResCost( dd, bFunc, uParts[iPart1], NULL, NULL ) + Abc_ResCost( dd, bFunc, uParts[iPart2], NULL, NULL );
+            if ( CostCur < CostBest )
+            {
+                CostCur    = CostBest;
+                uParts2[0] = uParts[iPart1];
+                uParts2[1] = uParts[iPart2];
+                fChange = 1;
+            }
+            uParts[iPart1] ^= (1 << i) | (1 << k);
+            uParts[iPart2] ^= (1 << i) | (1 << k);
+        }
+    }
+    uParts[iPart1] = uParts2[0];
+    uParts[iPart2] = uParts2[1];
+    return fChange;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Migrates variables between the two groups.]
+
+  Description [Returns 1 if there is change.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ResPrint( DdManager * dd, DdNode * bFunc, int nInputs, unsigned uParts[], int nParts )
+{
+    int i, k, nCofs, Cost, CostAll = 0, fCheck;
+    for ( i = 0; i < nParts; i++ )
+    {
+        Cost = Abc_ResCost( dd, bFunc, uParts[i], &nCofs, &fCheck );
+        CostAll += Cost;
+        for ( k = 0; k < nInputs; k++ )
+            printf( "%c", (uParts[i] & (1 << k))? 'a' + k : '-' );
+        printf( " %2d %d-%d %6d   ", nCofs, Abc_Base2Log(nCofs), fCheck, Cost );
+    }
+    printf( "%4d\n", CostAll );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [PrintCompute the number of distinct cofactors in the BDD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ResPrintAllCofs( DdManager * dd, DdNode * bFunc, int nInputs, int nCofMax )
+{
+    int i, k, nBits, nCofs, Cost, fCheck;
+    for ( i = 0; i < (1<<nInputs); i++ )
+    {
+        nBits = Extra_WordCountOnes( i );
+        if ( nBits < 3 || nBits > 6 )
+            continue;
+        Cost = Abc_ResCost( dd, bFunc, i, &nCofs, &fCheck );
+        if ( nCofs > nCofMax )
+            continue;
+        for ( k = 0; k < nInputs; k++ )
+            printf( "%c", (i & (1 << k))? 'a' + k : '-' );
+        printf( "  n=%2d  c=%2d  l=%d-%d   %6d\n", 
+            Extra_WordCountOnes(i), nCofs, Abc_Base2Log(nCofs), fCheck, Cost );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the number of distinct cofactors in the BDD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ResSwapRandom( DdManager * dd, DdNode * bFunc, int nInputs, unsigned uParts[], int nParts, int nTimes )
+{
+    int i, k, n, iPart1, iPart2;
+    for ( n = 0; n < nTimes; )
+    {
+        // get the vars
+        i = k = 0;
+        while ( i == k )
+        {
+            i = rand() % nInputs;
+            k = rand() % nInputs;
+        }
+        // find the groups
+        for ( iPart1 = 0; iPart1 < nParts; iPart1++ )
+            if ( uParts[iPart1] & (1 << i) )
+                break;
+        for ( iPart2 = 0; iPart2 < nParts; iPart2++ )
+            if ( uParts[iPart2] & (1 << k) )
+                break;
+        if ( iPart1 == iPart2 )
+            continue;
+        // swap the vars
+        uParts[iPart1] ^= (1 << i) | (1 << k);
+        uParts[iPart2] ^= (1 << i) | (1 << k);
+        n++;
+//printf( "   " );
+//Abc_ResPrint( dd, bFunc, nInputs, uParts, nParts );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the number of distinct cofactors in the BDD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ResPartition( DdManager * dd, DdNode * bFunc, int nInputs )
+{
+    int nIters = 5;
+    unsigned uParts[10];
+    int i, fChange = 1;
+    int nSuppSize = Cudd_SupportSize( dd, bFunc );
+    printf( "Ins =%3d. Outs =%2d. Nodes =%3d. Supp =%2d.\n", 
+        nInputs, dd->size-nInputs, Cudd_DagSize(bFunc), nSuppSize );
+//Abc_ResPrintAllCofs( dd, bFunc, nInputs, 4 );
+
+    if ( nSuppSize <= 6 )
+    {
+        printf( "Support is less or equal than 6\n" );
+        return;
+    }
+    if ( nInputs <= 12 )
+    {
+        Abc_ResStartPart( nInputs, uParts, 2 );
+        Abc_ResPrint( dd, bFunc, nInputs, uParts, 2 );
+        for ( i = 0; i < nIters; i++ )
+        {
+            if ( i ) 
+            {
+                printf( "Randomizing... \n" );
+                Abc_ResSwapRandom( dd, bFunc, nInputs, uParts, 2, 20 );
+                Abc_ResPrint( dd, bFunc, nInputs, uParts, 2 );
+            }
+            fChange = 1;
+            while ( fChange )
+            {
+                fChange  = Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 1 );
+                Abc_ResPrint( dd, bFunc, nInputs, uParts, 2 );
+            }
+        }
+    }
+    else if ( nInputs > 12 && nInputs <= 18 )
+    {
+        Abc_ResStartPart( nInputs, uParts, 3 );
+        Abc_ResPrint( dd, bFunc, nInputs, uParts, 3 );
+        for ( i = 0; i < nIters; i++ )
+        {
+            if ( i ) 
+            {
+                printf( "Randomizing... \n" );
+                Abc_ResSwapRandom( dd, bFunc, nInputs, uParts, 3, 20 );
+                Abc_ResPrint( dd, bFunc, nInputs, uParts, 3 );
+            }
+            fChange = 1;
+            while ( fChange )
+            {
+                fChange  = Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 1 );
+                Abc_ResPrint( dd, bFunc, nInputs, uParts, 3 );
+                fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 2 );
+                Abc_ResPrint( dd, bFunc, nInputs, uParts, 3 );
+                fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 1, 2 );
+                Abc_ResPrint( dd, bFunc, nInputs, uParts, 3 );
+            }
+        }
+    }
+    else if ( nInputs > 18 && nInputs <= 24 )
+    {
+        Abc_ResStartPart( nInputs, uParts, 4 );
+        Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 );
+        for ( i = 0; i < nIters; i++ )
+        {
+            if ( i )
+            {
+                printf( "Randomizing... \n" );
+                Abc_ResSwapRandom( dd, bFunc, nInputs, uParts, 4, 20 );
+                Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 );
+            }
+            fChange = 1;
+            while ( fChange )
+            {
+                fChange  = Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 1 );
+                Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 );
+                fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 2 );
+                Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 );
+                fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 3 );
+                Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 );
+                fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 1, 2 );
+                Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 );
+                fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 1, 3 );
+                Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 );
+                fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 2, 3 );
+                Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 );
+            }
+        }
+    }
+//    else assert( 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the number of distinct cofactors in the BDD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ResPartitionTest( Abc_Ntk_t * pNtk )
+{
+    DdManager * dd;
+    DdNode * bFunc;
+    dd = Cudd_Init( Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    bFunc = Abc_ResBuildBdd( pNtk, dd );   Cudd_Ref( bFunc );
+    Abc_ResPartition( dd, bFunc, Abc_NtkCiNum(pNtk) );
+    Cudd_RecursiveDeref( dd, bFunc );
+    Extra_StopManager( dd );
+}
+
+
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the number of distinct cofactors in the BDD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkBddCofCount( DdManager * dd, DdNode * bFunc, DdNode ** pbVars, int nVars )
+{
+    Vec_Ptr_t * vCofs;
+    DdNode * bCof, * bCube;
+    int i, Result;
+    vCofs = Vec_PtrAlloc( 100 );
+    for ( i = 0; i < (1 << nVars); i++ )
+    {
+        bCube = Extra_bddBitsToCube( dd, i, nVars, pbVars, 1 );  Cudd_Ref( bCube );
+        bCof  = Cudd_Cofactor( dd, bFunc, bCube );               Cudd_Ref( bCof );
+        Cudd_RecursiveDeref( dd, bCube );
+        if ( Vec_PtrPushUnique( vCofs, bCof ) )
+            Cudd_RecursiveDeref( dd, bCof );
+    }
+    Result = Vec_PtrSize( vCofs );
+    Vec_PtrForEachEntry( DdNode *, vCofs, bCof, i )
+        Cudd_RecursiveDeref( dd, bCof );
+    Vec_PtrFree( vCofs );
+    return Result;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the number of distinct cofactors in the BDD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkExploreCofs2( DdManager * dd, DdNode * bFunc, DdNode ** pbVars, int nIns, int nLutSize )
+{
+    int i;
+    printf( "Inputs = %2d.  Nodes = %2d.  LutSize = %2d.\n", nIns, Cudd_DagSize(bFunc), nLutSize );
+    for ( i = 0; i <= nIns - nLutSize; i++ )
+        printf( "[%2d %2d] : %3d\n", i, i+nLutSize-1, Abc_NtkBddCofCount(dd, bFunc, dd->vars+i, nLutSize) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the number of distinct cofactors in the BDD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkExploreCofs( DdManager * dd, DdNode * bFunc, DdNode ** pbVars, int nIns, int nLutSize )
+{
+    DdManager * ddNew;
+    DdNode * bFuncNew;
+    DdNode * pbVarsNew[32];
+    int i, k, c, nCofs, nBits;
+
+    ddNew = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    Cudd_ShuffleHeap( ddNew, dd->invperm );
+    bFuncNew = Cudd_bddTransfer( dd, ddNew, bFunc );  Cudd_Ref( bFuncNew );
+
+    for ( i = 0; i < (1 << nIns); i++ )
+    {
+        nBits = Extra_WordCountOnes(i);
+        if ( nBits != nLutSize && nBits != nLutSize -1 && nBits != nLutSize -2  )
+            continue;
+        for ( c = k = 0; k < nIns; k++ )
+        {
+            if ( (i & (1 << k)) == 0 )
+                continue;
+//            pbVarsNew[c++] = pbVars[k];
+            pbVarsNew[c++] = ddNew->vars[k];
+        }
+        nCofs = Abc_NtkBddCofCount(ddNew, bFuncNew, pbVarsNew, c);
+        if ( nCofs > 8 )
+            continue;
+
+        for ( c = k = 0; k < nIns; k++ )
+        {
+            if ( (i & (1 << k)) == 0 )
+            {
+                printf( "-" );
+                continue;
+            }
+            printf( "%c", k + 'a' );
+        }
+        printf( " : %2d\n", nCofs );
+    }
+
+    Cudd_RecursiveDeref( ddNew, bFuncNew );
+    Extra_StopManager( ddNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the constant node corresponding to the encoded output value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NtkBddFindAddConst( DdManager * dd, DdNode * bFunc, int nOuts )
+{
+    int i, TermMask = 0;
+    DdNode * bFunc0, * bFunc1, * bConst0, * bConst1;
+    bConst0 = Cudd_ReadLogicZero( dd );
+    bConst1 = Cudd_ReadOne( dd );
+    for ( i = 0; i < nOuts; i++ )
+    {
+        if ( Cudd_IsComplement(bFunc) )
+        {
+            bFunc0 = Cudd_Not(Cudd_E(bFunc));
+            bFunc1 = Cudd_Not(Cudd_T(bFunc));
+        }
+        else
+        {
+            bFunc0 = Cudd_E(bFunc);
+            bFunc1 = Cudd_T(bFunc);
+        }
+        assert( bFunc0 == bConst0 || bFunc1 == bConst0 );
+        if ( bFunc0 == bConst0 )
+        {
+            TermMask ^= (1 << i);
+            bFunc = bFunc1;
+        }
+        else
+            bFunc = bFunc0;
+    }
+    assert( bFunc == bConst1 );
+    return Cudd_addConst( dd, TermMask );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively construct ADD for BDD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NtkBddToAdd_rec( DdManager * dd, DdNode * bFunc, int nOuts, stmm_table * tTable, int fCompl )
+{
+    DdNode * aFunc0, * aFunc1, * aFunc;
+    DdNode ** ppSlot;
+    assert( !Cudd_IsComplement(bFunc) );
+    if ( stmm_find_or_add( tTable, (char *)bFunc, (char ***)&ppSlot ) )
+        return *ppSlot;
+    if ( (int)bFunc->index >= Cudd_ReadSize(dd) - nOuts )
+    {
+        assert( Cudd_ReadPerm(dd, bFunc->index) >= Cudd_ReadSize(dd) - nOuts );
+        aFunc = Abc_NtkBddFindAddConst( dd, Cudd_NotCond(bFunc, fCompl), nOuts ); Cudd_Ref( aFunc );
+    }
+    else
+    {
+        aFunc0 = Abc_NtkBddToAdd_rec( dd, Cudd_Regular(cuddE(bFunc)), nOuts, tTable, fCompl ^ Cudd_IsComplement(cuddE(bFunc)) );
+        aFunc1 = Abc_NtkBddToAdd_rec( dd, cuddT(bFunc), nOuts, tTable, fCompl );                                                
+        aFunc  = Cudd_addIte( dd, Cudd_addIthVar(dd, bFunc->index), aFunc1, aFunc0 );  Cudd_Ref( aFunc );
+    }
+    return (*ppSlot = aFunc);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [R]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NtkBddToAdd( DdManager * dd, DdNode * bFunc, int nOuts )
+{
+    DdNode * aFunc, * aTemp, * bTemp;
+    stmm_table * tTable;
+    stmm_generator * gen;
+    tTable = stmm_init_table( st__ptrcmp, st__ptrhash );
+    aFunc = Abc_NtkBddToAdd_rec( dd, Cudd_Regular(bFunc), nOuts, tTable, Cudd_IsComplement(bFunc) );  
+    stmm_foreach_item( tTable, gen, (char **)&bTemp, (char **)&aTemp )
+        Cudd_RecursiveDeref( dd, aTemp );
+    stmm_free_table( tTable );
+    Cudd_Deref( aFunc );
+    return aFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively construct ADD for BDD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NtkAddToBdd_rec( DdManager * dd, DdNode * aFunc, int nIns, int nOuts, stmm_table * tTable )
+{
+    DdNode * bFunc0, * bFunc1, * bFunc;
+    DdNode ** ppSlot;
+    assert( !Cudd_IsComplement(aFunc) );
+    if ( stmm_find_or_add( tTable, (char *)aFunc, (char ***)&ppSlot ) )
+        return *ppSlot;
+    if ( Cudd_IsConstant(aFunc) )
+    {
+        assert( Cudd_ReadSize(dd) >= nIns + nOuts );
+        bFunc  = Extra_bddBitsToCube( dd, (int)Cudd_V(aFunc), nOuts, dd->vars + nIns, 1 );  Cudd_Ref( bFunc );
+    }
+    else
+    {
+        assert( aFunc->index < nIns );
+        bFunc0 = Abc_NtkAddToBdd_rec( dd, cuddE(aFunc), nIns, nOuts, tTable );
+        bFunc1 = Abc_NtkAddToBdd_rec( dd, cuddT(aFunc), nIns, nOuts, tTable );                                                
+        bFunc  = Cudd_bddIte( dd, Cudd_bddIthVar(dd, aFunc->index), bFunc1, bFunc0 );  Cudd_Ref( bFunc );
+    }
+    return (*ppSlot = bFunc);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [R]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NtkAddToBdd( DdManager * dd, DdNode * aFunc, int nIns, int nOuts )
+{
+    DdNode * bFunc, * bTemp, * aTemp;
+    stmm_table * tTable;
+    stmm_generator * gen;
+    tTable = stmm_init_table( st__ptrcmp, st__ptrhash );
+    bFunc = Abc_NtkAddToBdd_rec( dd, aFunc, nIns, nOuts, tTable );  
+    stmm_foreach_item( tTable, gen, (char **)&aTemp, (char **)&bTemp )
+        Cudd_RecursiveDeref( dd, bTemp );
+    stmm_free_table( tTable );
+    Cudd_Deref( bFunc );
+    return bFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the characteristic function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NtkBddDecCharFunc( DdManager * dd, DdNode ** pFuncs, int nOuts, int Mask, int nBits )
+{
+    DdNode * bFunc, * bTemp, * bExor, * bVar;
+    int i, Count = 0;
+    bFunc = Cudd_ReadOne( dd );  Cudd_Ref( bFunc );
+    for ( i = 0; i < nOuts; i++ )
+    {
+        if ( (Mask & (1 << i)) == 0 )
+            continue;
+        Count++;
+        bVar  = Cudd_bddIthVar( dd, dd->size - nOuts + i );
+        bExor = Cudd_bddXor( dd, pFuncs[i], bVar );                  Cudd_Ref( bExor );
+        bFunc = Cudd_bddAnd( dd, bTemp = bFunc, Cudd_Not(bExor) );   Cudd_Ref( bFunc );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bExor );
+    }
+    Cudd_Deref( bFunc );
+    assert( Count == nBits );
+    return bFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluate Sasao's decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NtkBddDecTry( reo_man * pReo, DdManager * dd, DdNode ** pFuncs, int nIns, int nOuts, int Mask, int nBits )
+{
+//    int fReorder = 0;
+    DdNode * bFunc;//, * aFunc, * aFuncNew;
+    // derive the characteristic function
+    bFunc = Abc_NtkBddDecCharFunc( dd, pFuncs, nOuts, Mask, nBits );    Cudd_Ref( bFunc );
+/*
+    // transfer to ADD
+    aFunc = Abc_NtkBddToAdd( dd, bFunc, nOuts );                        Cudd_Ref( aFunc );
+    Cudd_RecursiveDeref( dd, bFunc );
+//Abc_NodeShowBddOne( dd, aFunc );
+
+    // perform reordering for BDD width
+    if ( fReorder )
+    {
+        aFuncNew = Extra_Reorder( pReo, dd, aFunc, NULL );              Cudd_Ref( aFuncNew );
+        printf( "Before = %d.  After = %d.\n", Cudd_DagSize(aFunc), Cudd_DagSize(aFuncNew) );
+        Cudd_RecursiveDeref( dd, aFunc );
+    }
+    else
+        aFuncNew = aFunc;
+
+    // get back to BDD
+    bFunc = Abc_NtkAddToBdd( dd, aFuncNew, nIns, nOuts );  Cudd_Ref( bFunc );
+    Cudd_RecursiveDeref( dd, aFuncNew );
+//Abc_NodeShowBddOne( dd, bFunc );
+    // print the result
+//    reoProfileWidthPrint( pReo );
+*/
+    Cudd_Deref( bFunc );
+    return bFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluate Sasao's decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NtkBddDecInt( reo_man * pReo, DdManager * dd, DdNode ** pFuncs, int nIns, int nOuts )
+{
+/*
+    int i, k;
+    for ( i = 1; i <= nOuts; i++ )
+    {
+        for ( k = 0; k < (1<<nOuts); k++ )
+            if ( Extra_WordCountOnes(k) == i )
+            {
+                Extra_PrintBinary( stdout, (unsigned *)&k, nOuts );
+                Abc_NtkBddDecTry( pReo, dd, pFuncs, nOuts, k, i );
+                printf( "\n" );
+            }
+    }
+*/
+    return Abc_NtkBddDecTry( pReo, dd, pFuncs, nIns, nOuts, ~(1<<(32-nOuts)), nOuts );
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluate Sasao's decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCreateFromCharFunc( Abc_Ntk_t * pNtk, DdManager * dd, DdNode * bFunc )
+{    
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pNode, * pNodeNew, * pNodePo;
+    int i;
+    // start the network
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 );
+    pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+    // create inputs for CIs
+    pNodeNew = Abc_NtkCreateNode( pNtkNew );
+    Abc_NtkForEachCi( pNtk, pNode, i )
+    {
+        pNode->pCopy = Abc_NtkCreatePi( pNtkNew );
+        Abc_ObjAddFanin( pNodeNew, pNode->pCopy );
+        Abc_ObjAssignName( pNode->pCopy, Abc_ObjName(pNode), NULL );
+    }
+    // create inputs for COs
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        pNode->pCopy = Abc_NtkCreatePi( pNtkNew );
+        Abc_ObjAddFanin( pNodeNew, pNode->pCopy );
+        Abc_ObjAssignName( pNode->pCopy, Abc_ObjName(pNode), NULL );
+    }
+    // transfer BDD
+    pNodeNew->pData = Extra_TransferLevelByLevel( dd, (DdManager *)pNtkNew->pManFunc, bFunc ); Cudd_Ref( (DdNode *)pNodeNew->pData );
+    // transfer BDD into to be the local function
+    pNodePo = Abc_NtkCreatePo( pNtkNew );
+    Abc_ObjAddFanin( pNodePo, pNodeNew );
+    Abc_ObjAssignName( pNodePo, "out", NULL );
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkCreateFromCharFunc(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluate Sasao's decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkBddDec( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    int nBddSizeMax   = 1000000;
+    int fDropInternal =       0;
+    int fReorder      =       1;
+    Abc_Ntk_t * pNtkNew;
+    reo_man * pReo;
+    DdManager * dd;
+    DdNode * pFuncs[BDD_FUNC_MAX];
+    DdNode * bFunc;
+    Abc_Obj_t * pNode;
+    int i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( Abc_NtkCoNum(pNtk) <= BDD_FUNC_MAX );
+    dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, nBddSizeMax, fDropInternal, fReorder, fVerbose );
+    if ( dd == NULL )
+    {
+        Abc_Print( -1, "Construction of global BDDs has failed.\n" );
+        return NULL;
+    }
+    // collect global BDDs
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        pFuncs[i] = (DdNode *)Abc_ObjGlobalBdd(pNode);
+
+    // create new variables at the bottom
+    assert( dd->size == Abc_NtkCiNum(pNtk) );
+    for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ )
+        Cudd_addNewVarAtLevel( dd, dd->size );
+
+    // prepare reordering engine
+    pReo = Extra_ReorderInit( Abc_NtkCiNum(pNtk), 1000 );
+    Extra_ReorderSetMinimizationType( pReo, REO_MINIMIZE_WIDTH );
+    Extra_ReorderSetVerification( pReo, 1 );
+    Extra_ReorderSetVerbosity( pReo, 1 );
+
+    // derive characteristic function
+    bFunc = Abc_NtkBddDecInt( pReo, dd, pFuncs, Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk) );  Cudd_Ref( bFunc );
+    Extra_ReorderQuit( pReo );
+
+Abc_NtkExploreCofs( dd, bFunc, dd->vars, Abc_NtkCiNum(pNtk), 6 );
+
+    // create new network
+//    pNtkNew = Abc_NtkCreateFromCharFunc( pNtk, dd, bFunc );
+    pNtkNew = Abc_NtkDup( pNtk );
+
+    // cleanup
+    Cudd_RecursiveDeref( dd, bFunc );
+    Abc_NtkFreeGlobalBdds( pNtk, 1 );
+    return pNtkNew;
+}
+
+ABC_NAMESPACE_IMPL_END
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/abc-build/src/base/abci/abcCollapse.c b/abc-build/src/base/abci/abcCollapse.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcCollapse.c
@@ -0,0 +1,186 @@
+/**CFile****************************************************************
+
+  FileName    [abcCollapse.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Collapsing the network into two-levels.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcCollapse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk );
+static Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bFunc );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Collapses the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose )
+{
+    Abc_Ntk_t * pNtkNew;
+    abctime clk = Abc_Clock();
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    // compute the global BDDs
+    if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL )
+        return NULL;
+    if ( fVerbose )
+    {
+        DdManager * dd = (DdManager *)Abc_NtkGlobalBddMan( pNtk );
+        printf( "Shared BDD size = %6d nodes.  ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+        ABC_PRT( "BDD construction time", Abc_Clock() - clk );
+    }
+
+    // create the new network
+    pNtkNew = Abc_NtkFromGlobalBdds( pNtk );
+//    Abc_NtkFreeGlobalBdds( pNtk );
+    Abc_NtkFreeGlobalBdds( pNtk, 1 );
+    if ( pNtkNew == NULL )
+    {
+//        Cudd_Quit( pNtk->pManGlob );
+//        pNtk->pManGlob = NULL;
+        return NULL;
+    }
+//    Extra_StopManager( pNtk->pManGlob );
+//    pNtk->pManGlob = NULL;
+
+    // make the network minimum base
+    Abc_NtkMinimumBase( pNtkNew );
+
+    if ( pNtk->pExdc )
+        pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkCollapse: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+
+//int runtime1, runtime2;
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the network with the given global BDD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk )
+{
+//    extern void Extra_ShuffleTest( reo_man * p, DdManager * dd, DdNode * Func );
+//	reo_man * pReo;
+
+    ProgressBar * pProgress;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pNode, * pDriver, * pNodeNew;
+//    DdManager * dd = pNtk->pManGlob;
+    DdManager * dd = (DdManager *)Abc_NtkGlobalBddMan( pNtk );
+    int i;
+
+//    pReo = Extra_ReorderInit( Abc_NtkCiNum(pNtk), 1000 );
+//    runtime1 = runtime2 = 0;
+
+    // start the new network
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
+    // make sure the new manager has the same number of inputs
+    Cudd_bddIthVar( (DdManager *)pNtkNew->pManFunc, dd->size-1 );
+    // process the POs
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        pDriver = Abc_ObjFanin0(pNode);
+        if ( Abc_ObjIsCi(pDriver) && !strcmp(Abc_ObjName(pNode), Abc_ObjName(pDriver)) )
+        {
+            Abc_ObjAddFanin( pNode->pCopy, pDriver->pCopy );
+            continue;
+        }
+//        pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Vec_PtrEntry(pNtk->vFuncsGlob, i) );
+        pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, (DdNode *)Abc_ObjGlobalBdd(pNode) );
+        Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+
+//        Extra_ShuffleTest( pReo, dd, Abc_ObjGlobalBdd(pNode) );
+
+    }
+    Extra_ProgressBarStop( pProgress );
+
+//	Extra_ReorderQuit( pReo );
+//ABC_PRT( "Reo ", runtime1 );
+//ABC_PRT( "Cudd", runtime2 );
+
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the network with the given global BDD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bFunc )
+{
+    Abc_Obj_t * pNodeNew, * pTemp;
+    int i;
+    // create a new node
+    pNodeNew = Abc_NtkCreateNode( pNtkNew );
+    // add the fanins in the order, in which they appear in the reordered manager
+    Abc_NtkForEachCi( pNtkNew, pTemp, i )
+        Abc_ObjAddFanin( pNodeNew, Abc_NtkCi(pNtkNew, dd->invperm[i]) );
+    // transfer the function
+    pNodeNew->pData = Extra_TransferLevelByLevel( dd, (DdManager *)pNtkNew->pManFunc, bFunc );  Cudd_Ref( (DdNode *)pNodeNew->pData );
+    return pNodeNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcCut.c b/abc-build/src/base/abci/abcCut.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcCut.c
@@ -0,0 +1,700 @@
+/**CFile****************************************************************
+
+  FileName    [abcCut.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Interface to cut computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "opt/cut/cut.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq );
+static void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq );
+
+extern int nTotal, nGood, nEqual;
+
+static Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk );
+static int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCutsSubtractFanunt( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj, * pFan0, * pFan1, * pFanC;
+    int i, Counter = 0;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        if ( !Abc_NodeIsMuxType(pObj) )
+            continue;
+        pFanC = Abc_NodeRecognizeMux( pObj, &pFan1, &pFan0 );
+        pFanC = Abc_ObjRegular(pFanC);
+        pFan0 = Abc_ObjRegular(pFan0);
+        assert( pFanC->vFanouts.nSize > 1 );
+        pFanC->vFanouts.nSize--;
+        Counter++;
+        if ( Abc_NodeIsExorType(pObj) )
+        {
+            assert( pFan0->vFanouts.nSize > 1 );
+            pFan0->vFanouts.nSize--;
+            Counter++;
+        }
+    }
+    printf("Substracted %d fanouts\n", Counter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCutsAddFanunt( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj, * pFan0, * pFan1, * pFanC;
+    int i, Counter = 0;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        if ( !Abc_NodeIsMuxType(pObj) )
+            continue;
+        pFanC = Abc_NodeRecognizeMux( pObj, &pFan1, &pFan0 );
+        pFanC = Abc_ObjRegular(pFanC);
+        pFan0 = Abc_ObjRegular(pFan0);
+        pFanC->vFanouts.nSize++;
+        Counter++;
+        if ( Abc_NodeIsExorType(pObj) )
+        {
+            pFan0->vFanouts.nSize++;
+            Counter++;
+        }
+    }
+    printf("Added %d fanouts\n", Counter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
+{
+    ProgressBar * pProgress;
+    Cut_Man_t * p;
+    Cut_Cut_t * pList;
+    Abc_Obj_t * pObj, * pNode;
+    Vec_Ptr_t * vNodes;
+    Vec_Int_t * vChoices;
+    int i;
+    abctime clk = Abc_Clock();
+
+    extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk );
+    extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk );
+
+    if ( pParams->fAdjust )
+    Abc_NtkCutsSubtractFanunt( pNtk );
+
+    nTotal = nGood = nEqual = 0;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    // start the manager
+    pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
+    p = Cut_ManStart( pParams );
+    // compute node attributes if local or global cuts are requested
+    if ( pParams->fGlobal || pParams->fLocal )
+    {
+        extern Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk );
+        Cut_ManSetNodeAttrs( p, Abc_NtkGetNodeAttributes(pNtk) );
+    }
+    // prepare for cut dropping
+    if ( pParams->fDrop )
+        Cut_ManSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) );
+    // set cuts for PIs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        if ( Abc_ObjFanoutNum(pObj) > 0 )
+            Cut_NodeSetTriv( p, pObj->Id );
+    // compute cuts for internal nodes
+    vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs
+    vChoices = Vec_IntAlloc( 100 );
+    pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        // when we reached a CO, it is time to deallocate the cuts
+        if ( Abc_ObjIsCo(pObj) )
+        {
+            if ( pParams->fDrop )
+                Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+            continue;
+        }
+        // skip constant node, it has no cuts
+//        if ( Abc_NodeIsConst(pObj) )
+//            continue;
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        // compute the cuts to the internal node
+        pList = (Cut_Cut_t *)Abc_NodeGetCuts( p, pObj, pParams->fDag, pParams->fTree );
+        if ( pParams->fNpnSave && pList )
+        {
+            extern void Npn_ManSaveOne( unsigned * puTruth, int nVars );
+            Cut_Cut_t * pCut;
+            for ( pCut = pList; pCut; pCut = pCut->pNext )
+                if ( pCut->nLeaves >= 4 )
+                    Npn_ManSaveOne( Cut_CutReadTruth(pCut), pCut->nLeaves );
+        }
+        // consider dropping the fanins cuts
+        if ( pParams->fDrop )
+        {
+            Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+            Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId1(pObj) );
+        }
+        // add cuts due to choices
+        if ( Abc_AigNodeIsChoice(pObj) )
+        {
+            Vec_IntClear( vChoices );
+            for ( pNode = pObj; pNode; pNode = (Abc_Obj_t *)pNode->pData )
+                Vec_IntPush( vChoices, pNode->Id );
+            Cut_NodeUnionCuts( p, vChoices );
+        }
+    }
+    Extra_ProgressBarStop( pProgress );
+    Vec_PtrFree( vNodes );
+    Vec_IntFree( vChoices );
+    Cut_ManPrintStats( p );
+ABC_PRT( "TOTAL", Abc_Clock() - clk );
+//    printf( "Area = %d.\n", Abc_NtkComputeArea( pNtk, p ) );
+//Abc_NtkPrintCuts( p, pNtk, 0 );
+//    Cut_ManPrintStatsToFile( p, pNtk->pSpec, Abc_Clock() - clk );
+
+    // temporary printout of stats
+    if ( nTotal )
+    printf( "Total cuts = %d. Good cuts = %d.  Ratio = %5.2f\n", nTotal, nGood, ((double)nGood)/nTotal );
+    if ( pParams->fAdjust )
+    Abc_NtkCutsAddFanunt( pNtk );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cut computation using the oracle.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p )
+{
+    Abc_Obj_t * pObj;
+    Vec_Ptr_t * vNodes;
+    int i; //, clk = Abc_Clock();
+    int fDrop = Cut_OracleReadDrop(p);
+
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    // prepare cut droppping
+    if ( fDrop )
+        Cut_OracleSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) );
+
+    // set cuts for PIs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        if ( Abc_ObjFanoutNum(pObj) > 0 )
+            Cut_OracleNodeSetTriv( p, pObj->Id );
+
+    // compute cuts for internal nodes
+    vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        // when we reached a CO, it is time to deallocate the cuts
+        if ( Abc_ObjIsCo(pObj) )
+        {
+            if ( fDrop )
+                Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+            continue;
+        }
+        // skip constant node, it has no cuts
+//        if ( Abc_NodeIsConst(pObj) )
+//            continue;
+        // compute the cuts to the internal node
+        Cut_OracleComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),  
+                Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+        // consider dropping the fanins cuts
+        if ( fDrop )
+        {
+            Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+            Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId1(pObj) );
+        }
+    }
+    Vec_PtrFree( vNodes );
+//ABC_PRT( "Total", Abc_Clock() - clk );
+//Abc_NtkPrintCuts_( p, pNtk, 0 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
+{
+/*
+    Cut_Man_t *  p;
+    Abc_Obj_t * pObj, * pNode;
+    int i, nIters, fStatus;
+    Vec_Int_t * vChoices;
+    abctime clk = Abc_Clock();
+
+    assert( Abc_NtkIsSeq(pNtk) );
+    assert( pParams->fSeq );
+//    assert( Abc_NtkIsDfsOrdered(pNtk) );
+
+    // start the manager
+    pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
+    pParams->nCutSet = Abc_NtkCutSetNodeNum( pNtk );
+    p = Cut_ManStart( pParams );
+
+    // set cuts for the constant node and the PIs
+    pObj = Abc_AigConst1(pNtk);
+    if ( Abc_ObjFanoutNum(pObj) > 0 )
+        Cut_NodeSetTriv( p, pObj->Id );
+    Abc_NtkForEachPi( pNtk, pObj, i )
+    {
+//printf( "Setting trivial cut %d.\n", pObj->Id );
+        Cut_NodeSetTriv( p, pObj->Id );
+    }
+    // label the cutset nodes and set their number in the array
+    // assign the elementary cuts to the cutset nodes
+    Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+    {
+        assert( pObj->fMarkC == 0 );
+        pObj->fMarkC = 1;
+        pObj->pCopy = (Abc_Obj_t *)i;
+        Cut_NodeSetTriv( p, pObj->Id );
+//printf( "Setting trivial cut %d.\n", pObj->Id );
+    }
+
+    // process the nodes
+    vChoices = Vec_IntAlloc( 100 );
+    for ( nIters = 0; nIters < 10; nIters++ )
+    {
+//printf( "ITERATION %d:\n", nIters );
+        // compute the cuts for the internal nodes
+        Abc_AigForEachAnd( pNtk, pObj, i )
+        {
+            Abc_NodeGetCutsSeq( p, pObj, nIters==0 );
+            // add cuts due to choices
+            if ( Abc_AigNodeIsChoice(pObj) )
+            {
+                Vec_IntClear( vChoices );
+                for ( pNode = pObj; pNode; pNode = pNode->pData )
+                    Vec_IntPush( vChoices, pNode->Id );
+                Cut_NodeUnionCutsSeq( p, vChoices, (pObj->fMarkC ? (int)pObj->pCopy : -1), nIters==0 );
+            }
+        }
+        // merge the new cuts with the old cuts
+        Abc_NtkForEachPi( pNtk, pObj, i )
+            Cut_NodeNewMergeWithOld( p, pObj->Id );
+        Abc_AigForEachAnd( pNtk, pObj, i )
+            Cut_NodeNewMergeWithOld( p, pObj->Id );
+        // for the cutset, transfer temp cuts to new cuts
+        fStatus = 0;
+        Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+            fStatus |= Cut_NodeTempTransferToNew( p, pObj->Id, i );
+        if ( fStatus == 0 )
+            break;
+    }
+    Vec_IntFree( vChoices );
+
+    // if the status is not finished, transfer new to old for the cutset
+    Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+        Cut_NodeNewMergeWithOld( p, pObj->Id );
+
+    // transfer the old cuts to the new positions
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        Cut_NodeOldTransferToNew( p, pObj->Id );
+
+    // unlabel the cutset nodes
+    Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+        pObj->fMarkC = 0;
+if ( pParams->fVerbose )
+{
+    Cut_ManPrintStats( p );
+ABC_PRT( "TOTAL ", Abc_Clock() - clk );
+printf( "Converged after %d iterations.\n", nIters );
+}
+//Abc_NtkPrintCuts( p, pNtk, 1 );
+    return p;
+*/
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p )
+{
+    Abc_Obj_t * pObj;
+    int Counter, i;
+    Counter = 0;
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Counter += Cut_ManMappingArea_rec( p, Abc_ObjFaninId0(pObj) );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree )
+{
+    void * pList;
+    if ( (pList = Abc_NodeReadCuts( p, pObj )) )
+        return pList;
+    Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fDag, fTree );
+    Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fDag, fTree );
+    return Abc_NodeGetCuts( p, pObj, fDag, fTree );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree )
+{
+    Abc_Obj_t * pFanin;
+    int fDagNode, fTriv, TreeCode = 0;
+//    assert( Abc_NtkIsStrash(pObj->pNtk) );
+    assert( Abc_ObjFaninNum(pObj) == 2 );
+
+    // check if the node is a DAG node
+    fDagNode = (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj));
+    // increment the counter of DAG nodes
+    if ( fDagNode ) Cut_ManIncrementDagNodes( (Cut_Man_t *)p );
+    // add the trivial cut if the node is a DAG node, or if we compute all cuts
+    fTriv = fDagNode || !fDag;
+    // check if fanins are DAG nodes
+    if ( fTree )
+    {
+        pFanin = Abc_ObjFanin0(pObj);
+        TreeCode |=  (Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin));
+        pFanin = Abc_ObjFanin1(pObj);
+        TreeCode |= ((Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)) << 1);
+    }
+
+    // changes due to the global/local cut computation
+    {
+        Cut_Params_t * pParams = Cut_ManReadParams((Cut_Man_t *)p);
+        if ( pParams->fLocal )
+        {
+            Vec_Int_t * vNodeAttrs = Cut_ManReadNodeAttrs((Cut_Man_t *)p);
+            fDagNode = Vec_IntEntry( vNodeAttrs, pObj->Id );
+            if ( fDagNode ) Cut_ManIncrementDagNodes( (Cut_Man_t *)p );
+//            fTriv = fDagNode || !pParams->fGlobal;
+            fTriv = !Vec_IntEntry( vNodeAttrs, pObj->Id );
+            TreeCode = 0;
+            pFanin = Abc_ObjFanin0(pObj);
+            TreeCode |=  Vec_IntEntry( vNodeAttrs, pFanin->Id );
+            pFanin = Abc_ObjFanin1(pObj);
+            TreeCode |= (Vec_IntEntry( vNodeAttrs, pFanin->Id ) << 1);
+        }
+    }
+    return Cut_NodeComputeCuts( (Cut_Man_t *)p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),  
+        Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), fTriv, TreeCode );  
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fTriv )
+{
+/*
+    int CutSetNum;
+    assert( Abc_NtkIsSeq(pObj->pNtk) );
+    assert( Abc_ObjFaninNum(pObj) == 2 );
+    fTriv     = pObj->fMarkC ? 0 : fTriv;
+    CutSetNum = pObj->fMarkC ? (int)pObj->pCopy : -1;
+    Cut_NodeComputeCutsSeq( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),  
+        Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj), fTriv, CutSetNum );  
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj )
+{
+    return Cut_NodeReadCutsNew( (Cut_Man_t *)p, pObj->Id );  
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj )
+{
+    Cut_NodeFreeCuts( (Cut_Man_t *)p, pObj->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq )
+{
+    Cut_Cut_t * pList;
+    Abc_Obj_t * pObj;
+    int i;
+    printf( "Cuts of the network:\n" );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        pList = (Cut_Cut_t *)Abc_NodeReadCuts( (Cut_Man_t *)p, pObj );
+        printf( "Node %s:\n", Abc_ObjName(pObj) );
+        Cut_CutPrintList( pList, fSeq );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq )
+{
+    Cut_Cut_t * pList;
+    Abc_Obj_t * pObj;
+    pObj = Abc_NtkObj( pNtk, 2 * Abc_NtkObjNum(pNtk) / 3 );
+    pList = (Cut_Cut_t *)Abc_NodeReadCuts( (Cut_Man_t *)p, pObj );
+    printf( "Node %s:\n", Abc_ObjName(pObj) );
+    Cut_CutPrintList( pList, fSeq );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns global attributes randomly.]
+
+  Description [Old code.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ) 
+{
+    Vec_Int_t * vAttrs;
+//    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj;//, * pTemp;
+    int i;//, k;
+    int nNodesTotal = 0, nMffcsTotal = 0;
+    extern Vec_Ptr_t * Abc_NodeMffcInsideCollect( Abc_Obj_t * pNode );
+
+    vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
+//    Abc_NtkForEachCi( pNtk, pObj, i )
+//        Vec_IntWriteEntry( vAttrs, pObj->Id, 1 );
+
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        if ( Abc_ObjIsNode(pObj) )
+            nNodesTotal++;
+        if ( Abc_ObjIsCo(pObj) && Abc_ObjIsNode(Abc_ObjFanin0(pObj)) )
+            nMffcsTotal += Abc_NodeMffcSize( Abc_ObjFanin0(pObj) );
+//        if ( Abc_ObjIsNode(pObj) && (rand() % 4 == 0) )
+//        if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) && (rand() % 3 == 0) )
+        if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) )
+        {
+            int nMffc = Abc_NodeMffcSize(pObj);
+            nMffcsTotal += Abc_NodeMffcSize(pObj);
+//            printf( "%d ", nMffc );
+
+            if ( nMffc > 2 || Abc_ObjFanoutNum(pObj) > 8 )
+                Vec_IntWriteEntry( vAttrs, pObj->Id, 1 );
+        }
+    }
+/*
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        if ( Vec_IntEntry( vAttrs, pObj->Id ) )
+        {
+            vNodes = Abc_NodeMffcInsideCollect( pObj );
+            Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pTemp, k )
+                if ( pTemp != pObj )
+                    Vec_IntWriteEntry( vAttrs, pTemp->Id, 0 );
+            Vec_PtrFree( vNodes );
+        }
+    }
+*/
+    printf( "Total nodes = %d. Total MFFC nodes = %d.\n", nNodesTotal, nMffcsTotal );
+    return vAttrs; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns global attributes randomly.]
+
+  Description [Old code.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkSubDagSize_rec( Abc_Obj_t * pObj, Vec_Int_t * vAttrs ) 
+{
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return 0;
+    Abc_NodeSetTravIdCurrent(pObj);
+    if ( Vec_IntEntry( vAttrs, pObj->Id ) )
+        return 0;
+    if ( Abc_ObjIsCi(pObj) )
+        return 1;
+    assert( Abc_ObjFaninNum(pObj) == 2 );
+    return 1 + Abc_NtkSubDagSize_rec(Abc_ObjFanin0(pObj), vAttrs) +
+        Abc_NtkSubDagSize_rec(Abc_ObjFanin1(pObj), vAttrs);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns global attributes randomly.]
+
+  Description [Old code.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkGetNodeAttributes2( Abc_Ntk_t * pNtk ) 
+{
+    Vec_Int_t * vAttrs;
+    Abc_Obj_t * pObj;
+    int i, nSize;
+    assert( Abc_NtkIsDfsOrdered(pNtk) );
+    vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        // skip no-nodes and nodes without fanouts
+        if ( pObj->Id == 0 || !(Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)) )
+            continue;
+        // the node has more than one fanout - count its sub-DAG size
+        Abc_NtkIncrementTravId( pNtk );
+        nSize = Abc_NtkSubDagSize_rec( pObj, vAttrs );
+        if ( nSize > 15 )
+            Vec_IntWriteEntry( vAttrs, pObj->Id, 1 );
+    }
+    return vAttrs; 
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcDar.c b/abc-build/src/base/abci/abcDar.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcDar.c
@@ -0,0 +1,4676 @@
+/**CFile****************************************************************
+
+  FileName    [abcDar.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [DAG-aware rewriting.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcDar.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/main.h"
+#include "aig/gia/giaAig.h"
+#include "opt/dar/dar.h"
+#include "sat/cnf/cnf.h"
+#include "proof/fra/fra.h"
+#include "proof/fraig/fraig.h"
+#include "proof/int/int.h"
+#include "proof/dch/dch.h"
+#include "proof/ssw/ssw.h"
+#include "opt/cgt/cgt.h"
+#include "proof/bbr/bbr.h"
+#include "aig/gia/gia.h"
+#include "proof/cec/cec.h"
+#include "opt/csw/csw.h"
+#include "proof/pdr/pdr.h"
+#include "sat/bmc/bmc.h"
+#include "map/mio/mio.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ObjCompareById( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 )
+{
+    return Abc_ObjId(Abc_ObjRegular(*pp1)) - Abc_ObjId(Abc_ObjRegular(*pp2));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_CollectTopOr_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vSuper )
+{
+    if ( Abc_ObjIsComplement(pObj) || !Abc_ObjIsNode(pObj) )
+    {
+        Vec_PtrPush( vSuper, pObj );
+        return;
+    }
+    // go through the branches
+    Abc_CollectTopOr_rec( Abc_ObjChild0(pObj), vSuper );
+    Abc_CollectTopOr_rec( Abc_ObjChild1(pObj), vSuper );
+}
+void Abc_CollectTopOr( Abc_Obj_t * pObj, Vec_Ptr_t * vSuper )
+{
+    Vec_PtrClear( vSuper );
+    if ( Abc_ObjIsComplement(pObj) )
+    {
+        Abc_CollectTopOr_rec( Abc_ObjNot(pObj), vSuper );
+        Vec_PtrUniqify( vSuper, (int (*)())Abc_ObjCompareById );
+    }
+    else
+        Vec_PtrPush( vSuper, Abc_ObjNot(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from the AIG manager into ABC.]
+
+  Description [The returned map maps new PO IDs into old ones.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Abc_NtkToDarBmc( Abc_Ntk_t * pNtk, Vec_Int_t ** pvMap )
+{
+    Aig_Man_t * pMan;
+    Abc_Obj_t * pObj, * pTemp;
+    Vec_Ptr_t * vDrivers;
+    Vec_Ptr_t * vSuper;
+    int i, k, nDontCares;
+
+    // print warning about initial values
+    nDontCares = 0;
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        if ( Abc_LatchIsInitDc(pObj) )
+        {
+            Abc_LatchSetInit0(pObj);
+            nDontCares++;
+        }
+    if ( nDontCares )
+    {
+        Abc_Print( 1, "Warning: %d registers in this network have don't-care init values.\n", nDontCares );
+        Abc_Print( 1, "The don't-care are assumed to be 0. The result may not verify.\n" );
+        Abc_Print( 1, "Use command \"print_latch\" to see the init values of registers.\n" );
+        Abc_Print( 1, "Use command \"zero\" to convert or \"init\" to change the values.\n" );
+    }
+
+    // collect the drivers
+    vSuper   = Vec_PtrAlloc( 100 );
+    vDrivers = Vec_PtrAlloc( 100 );
+    if ( pvMap ) 
+    *pvMap   = Vec_IntAlloc( 100 );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+    {
+        if ( pNtk->nConstrs && i >= pNtk->nConstrs )
+        {
+            Vec_PtrPush( vDrivers, Abc_ObjNot(Abc_ObjChild0(pObj)) );
+            if ( pvMap )
+            Vec_IntPush( *pvMap, i );
+            continue;
+        }
+        Abc_CollectTopOr( Abc_ObjChild0(pObj), vSuper );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vSuper, pTemp, k )
+        {
+            Vec_PtrPush( vDrivers, pTemp );
+            if ( pvMap )
+            Vec_IntPush( *pvMap, i );
+        }       
+    }
+    Vec_PtrFree( vSuper );
+
+    // create network
+    pMan = Aig_ManStart( Abc_NtkNodeNum(pNtk) + 100 );
+    pMan->nConstrs = pNtk->nConstrs;
+    pMan->nBarBufs = pNtk->nBarBufs;
+    pMan->pName = Extra_UtilStrsav( pNtk->pName );
+    pMan->pSpec = Extra_UtilStrsav( pNtk->pSpec );
+    // transfer the pointers to the basic nodes
+    Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan);
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)Aig_ObjCreateCi(pMan);
+    // create flops
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        Abc_ObjFanout0(pObj)->pCopy = Abc_ObjNotCond( Abc_ObjFanout0(pObj)->pCopy, Abc_LatchIsInit1(pObj) );
+    // copy internal nodes
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)Aig_And( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj), (Aig_Obj_t *)Abc_ObjChild1Copy(pObj) );
+    // create the POs
+    Vec_PtrForEachEntry( Abc_Obj_t *, vDrivers, pTemp, k )
+        Aig_ObjCreateCo( pMan, (Aig_Obj_t *)Abc_ObjNotCond(Abc_ObjRegular(pTemp)->pCopy, !Abc_ObjIsComplement(pTemp)) );
+    Vec_PtrFree( vDrivers );
+    // create flops
+    Abc_NtkForEachLatchInput( pNtk, pObj, i )
+        Aig_ObjCreateCo( pMan, (Aig_Obj_t *)Abc_ObjNotCond(Abc_ObjChild0Copy(pObj), Abc_LatchIsInit1(Abc_ObjFanout0(pObj))) );
+
+    // remove dangling nodes
+    Aig_ManSetRegNum( pMan, Abc_NtkLatchNum(pNtk) );
+    Aig_ManCleanup( pMan );
+    if ( !Aig_ManCheck( pMan ) )
+    {
+        Abc_Print( 1, "Abc_NtkToDarBmc: AIG check has failed.\n" );
+        Aig_ManStop( pMan );
+        return NULL;
+    }
+    return pMan;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects information about what flops have unknown values.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkFindDcLatches( Abc_Ntk_t * pNtk )
+{
+    Vec_Int_t * vUnknown;
+    Abc_Obj_t * pObj;
+    int i;
+    vUnknown = Vec_IntStart( Abc_NtkLatchNum(pNtk) );
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        if ( Abc_LatchIsInitDc(pObj) )
+        {
+            Vec_IntWriteEntry( vUnknown, i, 1 );
+            Abc_LatchSetInit0(pObj);
+        }
+    return vUnknown;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from the AIG manager into ABC.]
+
+  Description [Assumes that registers are ordered after PIs/POs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Man_t * pMan;
+    Aig_Obj_t * pObjNew;
+    Abc_Obj_t * pObj;
+    int i, nNodes, nDontCares;
+    // make sure the latches follow PIs/POs
+    if ( fRegisters ) 
+    { 
+        assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) );
+        Abc_NtkForEachCi( pNtk, pObj, i )
+            if ( i < Abc_NtkPiNum(pNtk) )
+            {
+                assert( Abc_ObjIsPi(pObj) );
+                if ( !Abc_ObjIsPi(pObj) )
+                    Abc_Print( 1, "Abc_NtkToDar(): Temporary bug: The PI ordering is wrong!\n" );
+            }
+            else
+                assert( Abc_ObjIsBo(pObj) );
+        Abc_NtkForEachCo( pNtk, pObj, i )
+            if ( i < Abc_NtkPoNum(pNtk) )
+            {
+                assert( Abc_ObjIsPo(pObj) );
+                if ( !Abc_ObjIsPo(pObj) )
+                    Abc_Print( 1, "Abc_NtkToDar(): Temporary bug: The PO ordering is wrong!\n" );
+            }
+            else
+                assert( Abc_ObjIsBi(pObj) );
+        // print warning about initial values
+        nDontCares = 0;
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+            if ( Abc_LatchIsInitDc(pObj) )
+            {
+                Abc_LatchSetInit0(pObj);
+                nDontCares++;
+            }
+        if ( nDontCares )
+        {
+            Abc_Print( 1, "Warning: %d registers in this network have don't-care init values.\n", nDontCares );
+            Abc_Print( 1, "The don't-care are assumed to be 0. The result may not verify.\n" );
+            Abc_Print( 1, "Use command \"print_latch\" to see the init values of registers.\n" );
+            Abc_Print( 1, "Use command \"zero\" to convert or \"init\" to change the values.\n" );
+        }
+    }
+    // create the manager
+    pMan = Aig_ManStart( Abc_NtkNodeNum(pNtk) + 100 );
+    pMan->fCatchExor = fExors;
+    pMan->nConstrs = pNtk->nConstrs;
+    pMan->nBarBufs = pNtk->nBarBufs;
+    pMan->pName = Extra_UtilStrsav( pNtk->pName );
+    pMan->pSpec = Extra_UtilStrsav( pNtk->pSpec );
+    // transfer the pointers to the basic nodes
+    Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan);
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        pObj->pCopy = (Abc_Obj_t *)Aig_ObjCreateCi(pMan);
+        // initialize logic level of the CIs
+        ((Aig_Obj_t *)pObj->pCopy)->Level = pObj->Level;
+    }
+    // complement the 1-values registers
+    if ( fRegisters ) {
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+            if ( Abc_LatchIsInit1(pObj) )
+                Abc_ObjFanout0(pObj)->pCopy = Abc_ObjNot(Abc_ObjFanout0(pObj)->pCopy);
+    }
+    // perform the conversion of the internal nodes (assumes DFS ordering)
+//    pMan->fAddStrash = 1;
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+//    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        pObj->pCopy = (Abc_Obj_t *)Aig_And( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj), (Aig_Obj_t *)Abc_ObjChild1Copy(pObj) );
+//        Abc_Print( 1, "%d->%d ", pObj->Id, ((Aig_Obj_t *)pObj->pCopy)->Id );
+    }
+    Vec_PtrFree( vNodes );
+    pMan->fAddStrash = 0;
+    // create the POs
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Aig_ObjCreateCo( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj) );
+    // complement the 1-valued registers
+    Aig_ManSetRegNum( pMan, Abc_NtkLatchNum(pNtk) );
+    if ( fRegisters )
+        Aig_ManForEachLiSeq( pMan, pObjNew, i )
+            if ( Abc_LatchIsInit1(Abc_ObjFanout0(Abc_NtkCo(pNtk,i))) )
+                pObjNew->pFanin0 = Aig_Not(pObjNew->pFanin0);
+    // remove dangling nodes
+    nNodes = (Abc_NtkGetChoiceNum(pNtk) == 0)? Aig_ManCleanup( pMan ) : 0;
+    if ( !fExors && nNodes )
+        Abc_Print( 1, "Abc_NtkToDar(): Unexpected %d dangling nodes when converting to AIG!\n", nNodes );
+//Aig_ManDumpVerilog( pMan, "test.v" );
+    // save the number of registers
+    if ( fRegisters )
+    {
+        Aig_ManSetRegNum( pMan, Abc_NtkLatchNum(pNtk) );
+        pMan->vFlopNums = Vec_IntStartNatural( pMan->nRegs );
+//        pMan->vFlopNums = NULL;
+//        pMan->vOnehots = Abc_NtkConverLatchNamesIntoNumbers( pNtk );
+        if ( pNtk->vOnehots )
+            pMan->vOnehots = (Vec_Ptr_t *)Vec_VecDupInt( (Vec_Vec_t *)pNtk->vOnehots );
+    }
+    if ( !Aig_ManCheck( pMan ) )
+    {
+        Abc_Print( 1, "Abc_NtkToDar: AIG check has failed.\n" );
+        Aig_ManStop( pMan );
+        return NULL;
+    }
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from the AIG manager into ABC.]
+
+  Description [Assumes that registers are ordered after PIs/POs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Abc_NtkToDarChoices( Abc_Ntk_t * pNtk )
+{
+    Aig_Man_t * pMan;
+    Abc_Obj_t * pObj, * pPrev, * pFanin;
+    Vec_Ptr_t * vNodes;
+    int i;
+    vNodes = Abc_AigDfs( pNtk, 0, 0 );
+    // create the manager
+    pMan = Aig_ManStart( Abc_NtkNodeNum(pNtk) + 100 );
+    pMan->nConstrs = pNtk->nConstrs;
+    pMan->nBarBufs = pNtk->nBarBufs;
+    pMan->pName = Extra_UtilStrsav( pNtk->pName );
+    pMan->pSpec = Extra_UtilStrsav( pNtk->pSpec );
+    if ( Abc_NtkGetChoiceNum(pNtk) )
+    {
+        pMan->pEquivs = ABC_ALLOC( Aig_Obj_t *, Abc_NtkObjNum(pNtk) );
+        memset( pMan->pEquivs, 0, sizeof(Aig_Obj_t *) * Abc_NtkObjNum(pNtk) );
+    }
+    // transfer the pointers to the basic nodes
+    Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan);
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)Aig_ObjCreateCi(pMan);
+    // perform the conversion of the internal nodes (assumes DFS ordering)
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        pObj->pCopy = (Abc_Obj_t *)Aig_And( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj), (Aig_Obj_t *)Abc_ObjChild1Copy(pObj) );
+//        Abc_Print( 1, "%d->%d ", pObj->Id, ((Aig_Obj_t *)pObj->pCopy)->Id );
+        if ( Abc_AigNodeIsChoice( pObj ) )
+        {
+            for ( pPrev = pObj, pFanin = (Abc_Obj_t *)pObj->pData; pFanin; pPrev = pFanin, pFanin = (Abc_Obj_t *)pFanin->pData )
+                Aig_ObjSetEquiv( pMan, (Aig_Obj_t *)pPrev->pCopy, (Aig_Obj_t *)pFanin->pCopy );
+//            Aig_ManCreateChoice( pIfMan, (Aig_Obj_t *)pNode->pCopy );
+        }
+    }
+    Vec_PtrFree( vNodes );
+    // create the POs
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Aig_ObjCreateCo( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj) );
+    // complement the 1-valued registers
+    Aig_ManSetRegNum( pMan, 0 );
+    if ( !Aig_ManCheck( pMan ) )
+    {
+        Abc_Print( 1, "Abc_NtkToDar: AIG check has failed.\n" );
+        Aig_ManStop( pMan );
+        return NULL;
+    }
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from the AIG manager into ABC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Ntk_t * pNtkNew;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( pMan->nAsserts == 0 );
+//    assert( Aig_ManRegNum(pMan) == Abc_NtkLatchNum(pNtkOld) );
+    // perform strashing
+    pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
+    pNtkNew->nConstrs = pMan->nConstrs;
+    pNtkNew->nBarBufs = pNtkOld->nBarBufs;
+    // transfer the pointers to the basic nodes
+    Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
+    Aig_ManForEachCi( pMan, pObj, i )
+    {
+        pObj->pData = Abc_NtkCi(pNtkNew, i);
+        // initialize logic level of the CIs
+        ((Abc_Obj_t *)pObj->pData)->Level = pObj->Level;
+    }
+    // rebuild the AIG
+    vNodes = Aig_ManDfs( pMan, 1 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        if ( Aig_ObjIsBuf(pObj) )
+            pObj->pData = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj);
+        else
+            pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) );
+    Vec_PtrFree( vNodes );
+    // connect the PO nodes
+    Aig_ManForEachCo( pMan, pObj, i )
+    {
+        if ( pMan->nAsserts && i == Aig_ManCoNum(pMan) - pMan->nAsserts )
+            break;
+        Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) );
+    }
+    // if there are assertions, add them
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        Abc_Print( 1, "Abc_NtkFromDar(): Network check has failed.\n" );
+//Abc_NtkPrintCiLevels( pNtkNew );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from the AIG manager into ABC.]
+
+  Description [This procedure should be called after seq sweeping, 
+  which changes the number of registers.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromDarSeqSweep( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
+{
+    Vec_Ptr_t * vNodes; 
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObjNew, * pLatch;
+    Aig_Obj_t * pObj, * pObjLo, * pObjLi;
+    int i, iNodeId, nDigits; 
+    assert( pMan->nAsserts == 0 );
+    assert( pNtkOld->nBarBufs == 0 );
+//    assert( Aig_ManRegNum(pMan) != Abc_NtkLatchNum(pNtkOld) );
+    // perform strashing
+    pNtkNew = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
+    pNtkNew->nConstrs = pMan->nConstrs;
+    pNtkNew->nBarBufs = pMan->nBarBufs;
+    // consider the case of target enlargement
+    if ( Abc_NtkCiNum(pNtkNew) < Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan) )
+    {
+        for ( i = Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan) - Abc_NtkCiNum(pNtkNew); i > 0; i-- )
+        {
+            pObjNew = Abc_NtkCreatePi( pNtkNew );
+            Abc_ObjAssignName( pObjNew, Abc_ObjName(pObjNew), NULL );
+        }
+        Abc_NtkOrderCisCos( pNtkNew );
+    }
+    assert( Abc_NtkCiNum(pNtkNew) == Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan) );
+    assert( Abc_NtkCoNum(pNtkNew) == Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) );
+    // transfer the pointers to the basic nodes
+    Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
+    Aig_ManForEachPiSeq( pMan, pObj, i )
+        pObj->pData = Abc_NtkCi(pNtkNew, i);
+    // create as many latches as there are registers in the manager
+    Aig_ManForEachLiLoSeq( pMan, pObjLi, pObjLo, i )
+    {
+        pObjNew = Abc_NtkCreateLatch( pNtkNew );
+        pObjLi->pData = Abc_NtkCreateBi( pNtkNew );
+        pObjLo->pData = Abc_NtkCreateBo( pNtkNew );
+        Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)pObjLi->pData );
+        Abc_ObjAddFanin( (Abc_Obj_t *)pObjLo->pData, pObjNew );
+        Abc_LatchSetInit0( pObjNew );
+    }
+    // rebuild the AIG
+    vNodes = Aig_ManDfs( pMan, 1 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        if ( Aig_ObjIsBuf(pObj) )
+            pObj->pData = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj);
+        else
+            pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) );
+    Vec_PtrFree( vNodes );
+    // connect the PO nodes
+    Aig_ManForEachCo( pMan, pObj, i )
+    {
+//        if ( pMan->nAsserts && i == Aig_ManCoNum(pMan) - pMan->nAsserts )
+//            break;
+        iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(Abc_NtkCo(pNtkNew, i)), ABC_OBJ_PI, ABC_OBJ_BO );
+        if ( iNodeId >= 0 )
+            pObjNew = Abc_NtkObj( pNtkNew, iNodeId );
+        else
+            pObjNew = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj);
+        Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjNew );
+    }
+    if ( pMan->vFlopNums == NULL )
+        Abc_NtkAddDummyBoxNames( pNtkNew );
+    else
+    {
+/*
+        {
+            int i, k, iFlop, Counter = 0;
+            FILE * pFile;
+            pFile = fopen( "out.txt", "w" );
+            fAbc_Print( 1, pFile, "The total of %d registers were removed (out of %d):\n", 
+                Abc_NtkLatchNum(pNtkOld)-Vec_IntSize(pMan->vFlopNums), Abc_NtkLatchNum(pNtkOld) );
+            for ( i = 0; i < Abc_NtkLatchNum(pNtkOld); i++ )
+            {
+                Vec_IntForEachEntry( pMan->vFlopNums, iFlop, k )
+                {
+                    if ( i == iFlop )
+                        break;
+                }
+                if ( k == Vec_IntSize(pMan->vFlopNums) )
+                    fAbc_Print( 1, pFile, "%6d (%6d)  :  %s\n", ++Counter, i, Abc_ObjName( Abc_ObjFanout0(Abc_NtkBox(pNtkOld, i)) ) );
+            }
+            fclose( pFile );
+            //Abc_Print( 1, "\n" );
+        }
+*/
+        assert( Abc_NtkBoxNum(pNtkOld) == Abc_NtkLatchNum(pNtkOld) );
+        nDigits = Abc_Base10Log( Abc_NtkLatchNum(pNtkNew) );
+        Abc_NtkForEachLatch( pNtkNew, pObjNew, i )
+        {
+            pLatch = Abc_NtkBox( pNtkOld, Vec_IntEntry( pMan->vFlopNums, i ) );
+            iNodeId = Nm_ManFindIdByName( pNtkNew->pManName, Abc_ObjName(Abc_ObjFanout0(pLatch)), ABC_OBJ_PO );
+            if ( iNodeId >= 0 )
+            {
+                Abc_ObjAssignName( pObjNew, Abc_ObjNameDummy("l", i, nDigits), NULL );
+                Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjNameDummy("li", i, nDigits), NULL );
+                Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjNameDummy("lo", i, nDigits), NULL );
+//Abc_Print( 1, "happening   %s -> %s\n", Abc_ObjName(Abc_ObjFanin0(pObjNew)), Abc_ObjName(Abc_ObjFanout0(pObjNew)) );
+                continue;
+            }
+            Abc_ObjAssignName( pObjNew, Abc_ObjName(pLatch), NULL );
+            Abc_ObjAssignName( Abc_ObjFanin0(pObjNew),  Abc_ObjName(Abc_ObjFanin0(pLatch)), NULL );
+            Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pLatch)), NULL );
+        }
+    }
+    // if there are assertions, add them
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        Abc_Print( 1, "Abc_NtkFromDar(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from the AIG manager into ABC.]
+
+  Description [This procedure should be called after seq sweeping, 
+  which changes the number of registers.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan )
+{
+    Vec_Ptr_t * vNodes; 
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObjNew;
+    Aig_Obj_t * pObj, * pObjLo, * pObjLi;
+    int i; 
+    assert( pMan->nAsserts == 0 );
+    // perform strashing
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    pNtkNew->nConstrs = pMan->nConstrs;
+    pNtkNew->nBarBufs = pMan->nBarBufs;
+    // duplicate the name and the spec
+//    pNtkNew->pName = Extra_UtilStrsav(pMan->pName);
+//    pNtkNew->pSpec = Extra_UtilStrsav(pMan->pSpec);
+    Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
+    // create PIs
+    Aig_ManForEachPiSeq( pMan, pObj, i )
+    {
+        pObjNew = Abc_NtkCreatePi( pNtkNew );
+//        Abc_ObjAssignName( pObjNew, Abc_ObjName(pObjNew), NULL );
+        pObj->pData = pObjNew;
+    }
+    // create POs
+    Aig_ManForEachPoSeq( pMan, pObj, i )
+    {
+        pObjNew = Abc_NtkCreatePo( pNtkNew );
+//        Abc_ObjAssignName( pObjNew, Abc_ObjName(pObjNew), NULL );
+        pObj->pData = pObjNew;
+    }
+    assert( Abc_NtkCiNum(pNtkNew) == Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan) );
+    assert( Abc_NtkCoNum(pNtkNew) == Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) );
+    // create as many latches as there are registers in the manager
+    Aig_ManForEachLiLoSeq( pMan, pObjLi, pObjLo, i )
+    {
+        pObjNew = Abc_NtkCreateLatch( pNtkNew );
+        pObjLi->pData = Abc_NtkCreateBi( pNtkNew );
+        pObjLo->pData = Abc_NtkCreateBo( pNtkNew );
+        Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)pObjLi->pData );
+        Abc_ObjAddFanin( (Abc_Obj_t *)pObjLo->pData, pObjNew );
+        Abc_LatchSetInit0( pObjNew );
+//        Abc_ObjAssignName( (Abc_Obj_t *)pObjLi->pData, Abc_ObjName((Abc_Obj_t *)pObjLi->pData), NULL );
+//        Abc_ObjAssignName( (Abc_Obj_t *)pObjLo->pData, Abc_ObjName((Abc_Obj_t *)pObjLo->pData), NULL );
+    }
+    // rebuild the AIG
+    vNodes = Aig_ManDfs( pMan, 1 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        if ( Aig_ObjIsBuf(pObj) )
+            pObj->pData = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj);
+        else
+            pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) );
+    Vec_PtrFree( vNodes );
+    // connect the PO nodes
+    Aig_ManForEachCo( pMan, pObj, i )
+    {
+        pObjNew = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj);
+        Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjNew );
+    }
+
+    Abc_NtkAddDummyPiNames( pNtkNew );
+    Abc_NtkAddDummyPoNames( pNtkNew );
+    Abc_NtkAddDummyBoxNames( pNtkNew );
+
+    // check the resulting AIG
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        Abc_Print( 1, "Abc_NtkFromAigPhase(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates local function of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Abc_ObjHopFromGia_rec( Hop_Man_t * pHopMan, Gia_Man_t * p, int Id, Vec_Ptr_t * vCopies )
+{
+    Gia_Obj_t * pObj;
+    Hop_Obj_t * gFunc, * gFunc0, * gFunc1;
+    if ( Gia_ObjIsTravIdCurrentId(p, Id) )
+        return (Hop_Obj_t *)Vec_PtrEntry( vCopies, Id );
+    Gia_ObjSetTravIdCurrentId(p, Id);
+    pObj = Gia_ManObj(p, Id);
+    assert( Gia_ObjIsAnd(pObj) );
+    // compute the functions of the children
+    gFunc0 = Abc_ObjHopFromGia_rec( pHopMan, p, Gia_ObjFaninId0(pObj, Id), vCopies );
+    gFunc1 = Abc_ObjHopFromGia_rec( pHopMan, p, Gia_ObjFaninId1(pObj, Id), vCopies );
+    // get the function of the cut
+    gFunc  = Hop_And( pHopMan, Hop_NotCond(gFunc0, Gia_ObjFaninC0(pObj)), Hop_NotCond(gFunc1, Gia_ObjFaninC1(pObj)) );  
+    Vec_PtrWriteEntry( vCopies, Id, gFunc );
+    return gFunc;
+}
+Hop_Obj_t * Abc_ObjHopFromGia( Hop_Man_t * pHopMan, Gia_Man_t * p, int GiaId, Vec_Ptr_t * vCopies )
+{
+    int k, iFan;
+    assert( Gia_ObjIsLut(p, GiaId) );
+    assert( Gia_ObjLutSize(p, GiaId) > 0 );
+    Gia_ManIncrementTravId( p );
+    Gia_LutForEachFanin( p, GiaId, iFan, k )
+    {
+        Gia_ObjSetTravIdCurrentId(p, iFan);
+        Vec_PtrWriteEntry( vCopies, iFan, Hop_IthVar(pHopMan, k) );
+    }
+    return Abc_ObjHopFromGia_rec( pHopMan, p, GiaId, vCopies );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from the mapped GIA manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p )
+{
+    int fVerbose = 0;
+    int fDuplicate = 0;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObjNew, * pObjNewLi, * pObjNewLo, * pConst0 = NULL;
+    Gia_Obj_t * pObj, * pObjLi, * pObjLo;
+    Vec_Ptr_t * vReflect;
+    int i, k, iFan, nDupGates; 
+    assert( Gia_ManHasMapping(p) );
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_AIG, 1 );
+    // duplicate the name and the spec
+    pNtkNew->pName = Extra_UtilStrsav(p->pName);
+    pNtkNew->pSpec = Extra_UtilStrsav(p->pSpec);
+    Gia_ManFillValue( p );
+    // create constant
+    pConst0 = Abc_NtkCreateNodeConst0( pNtkNew );
+    Gia_ManConst0(p)->Value = Abc_ObjId(pConst0);
+    // create PIs
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->Value = Abc_ObjId( Abc_NtkCreatePi( pNtkNew ) );
+    // create POs
+    Gia_ManForEachPo( p, pObj, i )
+        pObj->Value = Abc_ObjId( Abc_NtkCreatePo( pNtkNew ) );
+    // create as many latches as there are registers in the manager
+    Gia_ManForEachRiRo( p, pObjLi, pObjLo, i )
+    {
+        pObjNew = Abc_NtkCreateLatch( pNtkNew );
+        pObjNewLi = Abc_NtkCreateBi( pNtkNew );
+        pObjNewLo = Abc_NtkCreateBo( pNtkNew );
+        Abc_ObjAddFanin( pObjNew, pObjNewLi );
+        Abc_ObjAddFanin( pObjNewLo, pObjNew );
+        pObjLi->Value = Abc_ObjId( pObjNewLi );
+        pObjLo->Value = Abc_ObjId( pObjNewLo );
+        Abc_LatchSetInit0( pObjNew );
+    }
+    // rebuild the AIG
+    vReflect = Vec_PtrStart( Gia_ManObjNum(p) );
+    Gia_ManForEachLut( p, i )
+    {
+        pObj = Gia_ManObj(p, i);
+        assert( pObj->Value == ~0 );
+        if ( Gia_ObjLutSize(p, i) == 0 )
+        {
+            pObj->Value = Abc_ObjId(pConst0);
+            continue;
+        }
+        pObjNew = Abc_NtkCreateNode( pNtkNew );
+        Gia_LutForEachFanin( p, i, iFan, k )
+            Abc_ObjAddFanin( pObjNew, Abc_NtkObj(pNtkNew, Gia_ObjValue(Gia_ManObj(p, iFan))) );
+        pObjNew->pData = Abc_ObjHopFromGia( (Hop_Man_t *)pNtkNew->pManFunc, p, i, vReflect );
+        pObj->Value = Abc_ObjId( pObjNew );
+    }
+    Vec_PtrFree( vReflect );
+    // connect the PO nodes
+    Gia_ManForEachCo( p, pObj, i )
+    {
+        pObjNew = Abc_NtkObj( pNtkNew, Gia_ObjValue(Gia_ObjFanin0(pObj)) );
+        Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), Abc_ObjNotCond( pObjNew, Gia_ObjFaninC0(pObj) ) );
+    }
+    // create names
+    Abc_NtkAddDummyPiNames( pNtkNew );
+    Abc_NtkAddDummyPoNames( pNtkNew );
+    Abc_NtkAddDummyBoxNames( pNtkNew );
+
+    // decouple the PO driver nodes to reduce the number of levels
+    nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, fDuplicate );
+    if ( fVerbose && nDupGates && !Abc_FrameReadFlag("silentmode") )
+    {
+        if ( !fDuplicate )
+            printf( "Added %d buffers/inverters to decouple the CO drivers.\n", nDupGates );
+        else
+            printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates );
+    }
+    // remove const node if it is not used
+    if ( !Abc_ObjIsNone(pConst0) && Abc_ObjFanoutNum(pConst0) == 0 )
+        Abc_NtkDeleteObj( pConst0 );
+
+    assert( Gia_ManPiNum(p) == Abc_NtkPiNum(pNtkNew) );
+    assert( Gia_ManPoNum(p) == Abc_NtkPoNum(pNtkNew) );
+    assert( Gia_ManRegNum(p) == Abc_NtkLatchNum(pNtkNew) );
+
+    // check the resulting AIG
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        Abc_Print( 1, "Abc_NtkFromMappedGia(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from the mapped GIA manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_NtkFromCellWrite( Vec_Int_t * vCopyLits, int i, int c, int Id )
+{
+    Vec_IntWriteEntry( vCopyLits, Abc_Var2Lit(i, c), Id );
+}
+static inline Abc_Obj_t * Abc_NtkFromCellRead( Abc_Ntk_t * p, Vec_Int_t * vCopyLits, int i, int c )
+{
+    Abc_Obj_t * pObjNew;
+    int iObjNew = Vec_IntEntry( vCopyLits, Abc_Var2Lit(i, c) );
+    if ( iObjNew >= 0 )
+        return Abc_NtkObj(p, iObjNew);
+    if ( i == 0 )
+        pObjNew = c ? Abc_NtkCreateNodeConst1(p) : Abc_NtkCreateNodeConst0(p);
+    else
+    {
+        iObjNew = Vec_IntEntry( vCopyLits, Abc_Var2Lit(i, !c) );   assert( iObjNew >= 0 );
+        pObjNew = Abc_NtkCreateNodeInv( p, Abc_NtkObj(p, iObjNew) );
+    }
+    Abc_NtkFromCellWrite( vCopyLits, i, c, Abc_ObjId(pObjNew) );
+    return pObjNew;
+}
+Abc_Ntk_t * Abc_NtkFromCellMappedGia( Gia_Man_t * p )
+{
+    int fVerbose = 1;
+    int fDuplicate = 1;
+    Abc_Ntk_t * pNtkNew;
+    Vec_Int_t * vCopyLits;
+    Abc_Obj_t * pObjNew, * pObjNewLi, * pObjNewLo;
+    Gia_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i, k, iLit, iFanLit, nDupGates, nCells; 
+    Mio_Cell_t * pCells = Mio_CollectRootsNewDefault( 6, &nCells, 0 );
+    assert( Gia_ManHasCellMapping(p) );
+    // start network
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_MAP, 1 );
+    pNtkNew->pName = Extra_UtilStrsav(p->pName);
+    pNtkNew->pSpec = Extra_UtilStrsav(p->pSpec);
+    assert( pNtkNew->pManFunc == Abc_FrameReadLibGen() );
+    vCopyLits = Vec_IntStartFull( 2*Gia_ManObjNum(p) );
+    // create PIs
+    Gia_ManForEachPi( p, pObj, i )
+        Abc_NtkFromCellWrite( vCopyLits, Gia_ObjId(p, pObj), 0, Abc_ObjId( Abc_NtkCreatePi( pNtkNew ) ) );
+    // create POs
+    Gia_ManForEachPo( p, pObj, i )
+        Abc_NtkFromCellWrite( vCopyLits, Gia_ObjId(p, pObj), 0, Abc_ObjId( Abc_NtkCreatePo( pNtkNew ) ) );
+    // create as many latches as there are registers in the manager
+    Gia_ManForEachRiRo( p, pObjLi, pObjLo, i )
+    {
+        pObjNew = Abc_NtkCreateLatch( pNtkNew );
+        pObjNewLi = Abc_NtkCreateBi( pNtkNew );
+        pObjNewLo = Abc_NtkCreateBo( pNtkNew );
+        Abc_ObjAddFanin( pObjNew, pObjNewLi );
+        Abc_ObjAddFanin( pObjNewLo, pObjNew );
+//        pObjLi->Value = Abc_ObjId( pObjNewLi );
+//        pObjLo->Value = Abc_ObjId( pObjNewLo );
+        Abc_NtkFromCellWrite( vCopyLits, Gia_ObjId(p, pObjLi), 0, Abc_ObjId( pObjNewLi ) );
+        Abc_NtkFromCellWrite( vCopyLits, Gia_ObjId(p, pObjLo), 0, Abc_ObjId( pObjNewLo ) );
+        Abc_LatchSetInit0( pObjNew );
+    }
+    // rebuild the AIG
+    Gia_ManForEachCell( p, iLit )
+    {
+        assert( Vec_IntEntry(vCopyLits, iLit) == -1 );
+        pObjNew = Abc_NtkCreateNode( pNtkNew );
+        Gia_CellForEachFanin( p, iLit, iFanLit, k )
+            Abc_ObjAddFanin( pObjNew, Abc_NtkFromCellRead(pNtkNew, vCopyLits, Abc_Lit2Var(iFanLit), Abc_LitIsCompl(iFanLit)) );
+        pObjNew->pData = Mio_LibraryReadGateByName( (Mio_Library_t *)pNtkNew->pManFunc, pCells[Gia_ObjCellId(p, iLit)].pName, NULL );
+        Abc_NtkFromCellWrite( vCopyLits, Abc_Lit2Var(iLit), Abc_LitIsCompl(iLit), Abc_ObjId(pObjNew) );
+    }
+    // connect the PO nodes
+    Gia_ManForEachCo( p, pObj, i )
+    {
+        pObjNew = Abc_NtkFromCellRead( pNtkNew, vCopyLits, Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninC0(pObj) );
+        Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjNew );
+    }
+    // create names
+    Abc_NtkAddDummyPiNames( pNtkNew );
+    Abc_NtkAddDummyPoNames( pNtkNew );
+    Abc_NtkAddDummyBoxNames( pNtkNew );
+
+    // decouple the PO driver nodes to reduce the number of levels
+    nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, fDuplicate );
+    if ( fVerbose && nDupGates && !Abc_FrameReadFlag("silentmode") )
+    {
+        if ( !fDuplicate )
+            printf( "Added %d buffers/inverters to decouple the CO drivers.\n", nDupGates );
+        else
+            printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates );
+    }
+    assert( Gia_ManPiNum(p) == Abc_NtkPiNum(pNtkNew) );
+    assert( Gia_ManPoNum(p) == Abc_NtkPoNum(pNtkNew) );
+    assert( Gia_ManRegNum(p) == Abc_NtkLatchNum(pNtkNew) );
+    Vec_IntFree( vCopyLits );
+    ABC_FREE( pCells );
+
+    // check the resulting AIG
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        Abc_Print( 1, "Abc_NtkFromMappedGia(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from the AIG manager into ABC.]
+
+  Description [This procedure should be called after seq sweeping, 
+  which changes the number of registers.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkAfterTrim( Aig_Man_t * pMan, Abc_Ntk_t * pNtkOld )
+{
+    Vec_Ptr_t * vNodes; 
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObjNew, * pObjOld;
+    Aig_Obj_t * pObj, * pObjLo, * pObjLi;
+    int i; 
+    assert( pMan->nAsserts == 0 );
+    assert( pNtkOld->nBarBufs == 0 );
+    assert( Aig_ManRegNum(pMan) <= Abc_NtkLatchNum(pNtkOld) );
+    assert( Saig_ManPiNum(pMan) <= Abc_NtkCiNum(pNtkOld) );
+    assert( Saig_ManPoNum(pMan) == Abc_NtkPoNum(pNtkOld) );
+    assert( pMan->vCiNumsOrig != NULL );
+    // perform strashing
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    pNtkNew->nConstrs = pMan->nConstrs;
+    pNtkNew->nBarBufs = pMan->nBarBufs;
+    // duplicate the name and the spec
+//    pNtkNew->pName = Extra_UtilStrsav(pMan->pName);
+//    pNtkNew->pSpec = Extra_UtilStrsav(pMan->pSpec);
+    Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
+    // create PIs
+    Aig_ManForEachPiSeq( pMan, pObj, i )
+    {
+        pObjNew = Abc_NtkCreatePi( pNtkNew );
+        pObj->pData = pObjNew;
+        // find the name
+        pObjOld = Abc_NtkCi( pNtkOld, Vec_IntEntry(pMan->vCiNumsOrig, i) );
+        Abc_ObjAssignName( pObjNew, Abc_ObjName(pObjOld), NULL );
+    }
+    // create POs
+    Aig_ManForEachPoSeq( pMan, pObj, i )
+    {
+        pObjNew = Abc_NtkCreatePo( pNtkNew );
+        pObj->pData = pObjNew;
+        // find the name
+        pObjOld = Abc_NtkCo( pNtkOld, i );
+        Abc_ObjAssignName( pObjNew, Abc_ObjName(pObjOld), NULL );
+    }
+    assert( Abc_NtkCiNum(pNtkNew) == Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan) );
+    assert( Abc_NtkCoNum(pNtkNew) == Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) );
+    // create as many latches as there are registers in the manager
+    Aig_ManForEachLiLoSeq( pMan, pObjLi, pObjLo, i )
+    {
+        pObjNew = Abc_NtkCreateLatch( pNtkNew );
+        pObjLi->pData = Abc_NtkCreateBi( pNtkNew );
+        pObjLo->pData = Abc_NtkCreateBo( pNtkNew );
+        Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)pObjLi->pData );
+        Abc_ObjAddFanin( (Abc_Obj_t *)pObjLo->pData, pObjNew );
+        Abc_LatchSetInit0( pObjNew );
+        // find the name
+        pObjOld = Abc_NtkCi( pNtkOld, Vec_IntEntry(pMan->vCiNumsOrig, Saig_ManPiNum(pMan)+i) );
+        Abc_ObjAssignName( (Abc_Obj_t *)pObjLo->pData, Abc_ObjName(pObjOld), NULL );
+        // find the name
+        pObjOld = Abc_NtkCo( pNtkOld, Saig_ManPoNum(pMan)+i );
+        Abc_ObjAssignName( (Abc_Obj_t *)pObjLi->pData, Abc_ObjName(pObjOld), NULL );
+    }
+    // rebuild the AIG
+    vNodes = Aig_ManDfs( pMan, 1 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        if ( Aig_ObjIsBuf(pObj) )
+            pObj->pData = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj);
+        else
+            pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) );
+    Vec_PtrFree( vNodes );
+    // connect the PO nodes
+    Aig_ManForEachCo( pMan, pObj, i )
+    {
+        pObjNew = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj);
+        Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjNew );
+    }
+    // check the resulting AIG
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        Abc_Print( 1, "Abc_NtkAfterTrim(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from the AIG manager into ABC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromDarChoices( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
+{
+    Abc_Ntk_t * pNtkNew;
+    Aig_Obj_t * pObj, * pTemp;
+    int i;
+    assert( pMan->pEquivs != NULL );
+    assert( Aig_ManBufNum(pMan) == 0 );
+    // perform strashing
+    pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
+    pNtkNew->nConstrs = pMan->nConstrs;
+    pNtkNew->nBarBufs = pNtkOld->nBarBufs;
+    // transfer the pointers to the basic nodes
+    Aig_ManCleanData( pMan );
+    Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
+    Aig_ManForEachCi( pMan, pObj, i )
+        pObj->pData = Abc_NtkCi(pNtkNew, i);
+    // rebuild the AIG
+    Aig_ManForEachNode( pMan, pObj, i )
+    {
+        pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) );
+        if ( (pTemp = Aig_ObjEquiv(pMan, pObj)) )
+        {
+            assert( pTemp->pData != NULL );
+            ((Abc_Obj_t *)pObj->pData)->pData = ((Abc_Obj_t *)pTemp->pData);
+        }
+    }
+    // connect the PO nodes
+    Aig_ManForEachCo( pMan, pObj, i )
+        Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) );
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        Abc_Print( 1, "Abc_NtkFromDar(): Network check has failed.\n" );
+
+    // verify topological order
+    if ( 0 )
+    {
+        Abc_Obj_t * pNode;
+        Abc_NtkForEachNode( pNtkNew, pNode, i )
+            if ( Abc_AigNodeIsChoice( pNode ) )
+            {
+                int Counter = 0;
+                for ( pNode = Abc_ObjEquiv(pNode); pNode; pNode = Abc_ObjEquiv(pNode) )
+                    Counter++;
+                printf( "%d ", Counter );
+            }
+        printf( "\n" );
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from the AIG manager into ABC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromDarSeq( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1;
+    Aig_Obj_t * pObj;
+    int i;
+//    assert( Aig_ManLatchNum(pMan) > 0 );
+    assert( pNtkOld->nBarBufs == 0 );
+    // perform strashing
+    pNtkNew = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
+    pNtkNew->nConstrs = pMan->nConstrs;
+    pNtkNew->nBarBufs = pMan->nBarBufs;
+    // transfer the pointers to the basic nodes
+    Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
+    Aig_ManForEachCi( pMan, pObj, i )
+        pObj->pData = Abc_NtkPi(pNtkNew, i);
+    // create latches of the new network
+    Aig_ManForEachObj( pMan, pObj, i )
+    {
+        pObjNew = Abc_NtkCreateLatch( pNtkNew );
+        pFaninNew0 = Abc_NtkCreateBi( pNtkNew );
+        pFaninNew1 = Abc_NtkCreateBo( pNtkNew );
+        Abc_ObjAddFanin( pObjNew, pFaninNew0 );
+        Abc_ObjAddFanin( pFaninNew1, pObjNew );
+        Abc_LatchSetInit0( pObjNew );
+        pObj->pData = Abc_ObjFanout0( pObjNew );
+    }
+    Abc_NtkAddDummyBoxNames( pNtkNew );
+    // rebuild the AIG
+    vNodes = Aig_ManDfs( pMan, 1 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        // add the first fanin
+        pObj->pData = pFaninNew0 = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj);
+        if ( Aig_ObjIsBuf(pObj) )
+            continue;
+        // add the second fanin
+        pFaninNew1 = (Abc_Obj_t *)Aig_ObjChild1Copy(pObj);
+        // create the new node
+        if ( Aig_ObjIsExor(pObj) )
+            pObj->pData = pObjNew = Abc_AigXor( (Abc_Aig_t *)pNtkNew->pManFunc, pFaninNew0, pFaninNew1 );
+        else
+            pObj->pData = pObjNew = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pFaninNew0, pFaninNew1 );
+    }
+    Vec_PtrFree( vNodes );
+    // connect the PO nodes
+    Aig_ManForEachCo( pMan, pObj, i )
+    {
+        pFaninNew = (Abc_Obj_t *)Aig_ObjChild0Copy( pObj );
+        Abc_ObjAddFanin( Abc_NtkPo(pNtkNew, i), pFaninNew );
+    }
+    // connect the latches
+    Aig_ManForEachObj( pMan, pObj, i )
+    {
+        pFaninNew = (Abc_Obj_t *)Aig_ObjChild0Copy( pObj );
+        Abc_ObjAddFanin( Abc_ObjFanin0(Abc_ObjFanin0((Abc_Obj_t *)pObj->pData)), pFaninNew );
+    }
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        Abc_Print( 1, "Abc_NtkFromIvySeq(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects CI of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkCollectCiNames( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Vec_Ptr_t * vNames;
+    vNames = Vec_PtrAlloc( 100 );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        Vec_PtrPush( vNames, Extra_UtilStrsav(Abc_ObjName(pObj)) );
+    return vNames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects CO of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkCollectCoNames( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Vec_Ptr_t * vNames;
+    vNames = Vec_PtrAlloc( 100 );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Vec_PtrPush( vNames, Extra_UtilStrsav(Abc_ObjName(pObj)) );
+    return vNames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect latch values.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkGetLatchValues( Abc_Ntk_t * pNtk )
+{
+    Vec_Int_t * vInits;
+    Abc_Obj_t * pLatch;
+    int i;
+    vInits = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) );
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+        if ( Abc_LatchIsInit0(pLatch) )
+            Vec_IntPush( vInits, 0 );
+        else if ( Abc_LatchIsInit1(pLatch) )
+            Vec_IntPush( vInits, 1 );
+        else if ( Abc_LatchIsInitDc(pLatch) )
+            Vec_IntPush( vInits, 2 );
+        else
+            assert( 0 );
+    }
+    return vInits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkAig = NULL;
+    Aig_Man_t * pMan;
+    extern void Fra_ManPartitionTest( Aig_Man_t * p, int nComLim );
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    // convert to the AIG manager
+    pMan = Abc_NtkToDar( pNtk, 0, 0 );
+    if ( pMan == NULL )
+        return NULL;
+
+    // perform computation
+//    Fra_ManPartitionTest( pMan, 4 );
+    pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+    Aig_ManStop( pMan );
+
+    // make sure everything is okay
+    if ( pNtkAig && !Abc_NtkCheck( pNtkAig ) )
+    {
+        Abc_Print( 1, "Abc_NtkDar: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkAig );
+        return NULL;
+    }
+    return pNtkAig;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fSpeculate, int fChoicing, int fVerbose )
+{
+    Fra_Par_t Pars, * pPars = &Pars; 
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkToDar( pNtk, 0, 0 );
+    if ( pMan == NULL )
+        return NULL;
+    Fra_ParamsDefault( pPars );
+    pPars->nBTLimitNode = nConfLimit;
+    pPars->fChoicing    = fChoicing;
+    pPars->fDoSparse    = fDoSparse;
+    pPars->fSpeculate   = fSpeculate;
+    pPars->fProve       = fProve;
+    pPars->fVerbose     = fVerbose;
+    pMan = Fra_FraigPerform( pTemp = pMan, pPars );
+    if ( fChoicing )
+        pNtkAig = Abc_NtkFromDarChoices( pNtk, pMan );
+    else
+        pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+    Aig_ManStop( pTemp );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarFraigPart( Abc_Ntk_t * pNtk, int nPartSize, int nConfLimit, int nLevelMax, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkToDar( pNtk, 0, 0 );
+    if ( pMan == NULL )
+        return NULL;
+    pMan = Aig_ManFraigPartitioned( pTemp = pMan, nPartSize, nConfLimit, nLevelMax, fVerbose );
+    Aig_ManStop( pTemp );
+    pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCSweep( Abc_Ntk_t * pNtk, int nCutsMax, int nLeafMax, int fVerbose )
+{
+//    extern Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose );
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkToDar( pNtk, 0, 0 );
+    if ( pMan == NULL )
+        return NULL;
+    pMan = Csw_Sweep( pTemp = pMan, nCutsMax, nLeafMax, fVerbose );
+    pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+    Aig_ManStop( pTemp );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDRewrite( Abc_Ntk_t * pNtk, Dar_RwrPar_t * pPars )
+{
+    Aig_Man_t * pMan, * pTemp;
+    Abc_Ntk_t * pNtkAig;
+    abctime clk;
+    assert( Abc_NtkIsStrash(pNtk) );
+    pMan = Abc_NtkToDar( pNtk, 0, 0 );
+    if ( pMan == NULL )
+        return NULL;
+//    Aig_ManPrintStats( pMan );
+/*
+//    Aig_ManSupports( pMan );
+    {
+        Vec_Vec_t * vParts;
+        vParts = Aig_ManPartitionSmart( pMan, 50, 1, NULL );
+        Vec_VecFree( vParts );
+    }
+*/
+    Dar_ManRewrite( pMan, pPars );
+//    pMan = Dar_ManBalance( pTemp = pMan, pPars->fUpdateLevel );
+//    Aig_ManStop( pTemp );
+
+clk = Abc_Clock();
+    pMan = Aig_ManDupDfs( pTemp = pMan ); 
+    Aig_ManStop( pTemp );
+//ABC_PRT( "time", Abc_Clock() - clk );
+
+//    Aig_ManPrintStats( pMan );
+    pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDRefactor( Abc_Ntk_t * pNtk, Dar_RefPar_t * pPars )
+{
+    Aig_Man_t * pMan, * pTemp;
+    Abc_Ntk_t * pNtkAig;
+    abctime clk;
+    assert( Abc_NtkIsStrash(pNtk) );
+    pMan = Abc_NtkToDar( pNtk, 0, 0 );
+    if ( pMan == NULL )
+        return NULL;
+//    Aig_ManPrintStats( pMan );
+
+    Dar_ManRefactor( pMan, pPars );
+//    pMan = Dar_ManBalance( pTemp = pMan, pPars->fUpdateLevel );
+//    Aig_ManStop( pTemp );
+
+clk = Abc_Clock();
+    pMan = Aig_ManDupDfs( pTemp = pMan ); 
+    Aig_ManStop( pTemp );
+//ABC_PRT( "time", Abc_Clock() - clk );
+
+//    Aig_ManPrintStats( pMan );
+    pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDC2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose )
+{
+    Aig_Man_t * pMan, * pTemp;
+    Abc_Ntk_t * pNtkAig;
+    abctime clk;
+    assert( Abc_NtkIsStrash(pNtk) );
+    pMan = Abc_NtkToDar( pNtk, 0, 0 );
+    if ( pMan == NULL )
+        return NULL;
+//    Aig_ManPrintStats( pMan );
+
+clk = Abc_Clock();
+    pMan = Dar_ManCompress2( pTemp = pMan, fBalance, fUpdateLevel, fFanout, fPower, fVerbose ); 
+    Aig_ManStop( pTemp );
+//ABC_PRT( "time", Abc_Clock() - clk );
+
+//    Aig_ManPrintStats( pMan );
+    pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose )
+{
+    Aig_Man_t * pMan, * pTemp;
+    Abc_Ntk_t * pNtkAig;
+    assert( Abc_NtkIsStrash(pNtk) );
+    pMan = Abc_NtkToDar( pNtk, 0, 0 );
+    if ( pMan == NULL )
+        return NULL;
+    pMan = Dar_ManChoice( pTemp = pMan, fBalance, fUpdateLevel, fConstruct, nConfMax, nLevelMax, fVerbose );
+    Aig_ManStop( pTemp );
+    pNtkAig = Abc_NtkFromDarChoices( pNtk, pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDch( Abc_Ntk_t * pNtk, Dch_Pars_t * pPars )
+{
+    extern Gia_Man_t * Dar_NewChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fLightSynth, int fVerbose );
+    extern Aig_Man_t * Cec_ComputeChoices( Gia_Man_t * pGia, Dch_Pars_t * pPars );
+
+    Aig_Man_t * pMan, * pTemp;
+    Abc_Ntk_t * pNtkAig;
+    Gia_Man_t * pGia;
+    abctime clk;
+    assert( Abc_NtkIsStrash(pNtk) );
+    pMan = Abc_NtkToDar( pNtk, 0, 0 );
+    if ( pMan == NULL )
+        return NULL;
+clk = Abc_Clock();
+    if ( pPars->fSynthesis )
+        pGia = Dar_NewChoiceSynthesis( pMan, 1, 1, pPars->fPower, pPars->fLightSynth, pPars->fVerbose );
+    else
+    {
+        pGia = Gia_ManFromAig( pMan );
+        Aig_ManStop( pMan );
+    }
+pPars->timeSynth = Abc_Clock() - clk;
+    if ( pPars->fUseGia )
+        pMan = Cec_ComputeChoices( pGia, pPars );
+    else
+    {
+        pMan = Gia_ManToAigSkip( pGia, 3 );
+        Gia_ManStop( pGia );
+        pMan = Dch_ComputeChoices( pTemp = pMan, pPars );
+        Aig_ManStop( pTemp );
+    }
+    pNtkAig = Abc_NtkFromDarChoices( pNtk, pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDrwsat( Abc_Ntk_t * pNtk, int fBalance, int fVerbose )
+{
+    Aig_Man_t * pMan, * pTemp;
+    Abc_Ntk_t * pNtkAig;
+    abctime clk;
+    assert( Abc_NtkIsStrash(pNtk) );
+    pMan = Abc_NtkToDar( pNtk, 0, 0 );
+    if ( pMan == NULL )
+        return NULL;
+//    Aig_ManPrintStats( pMan );
+
+clk = Abc_Clock();
+    pMan = Dar_ManRwsat( pTemp = pMan, fBalance, fVerbose ); 
+    Aig_ManStop( pTemp );
+//ABC_PRT( "time", Abc_Clock() - clk );
+
+//    Aig_ManPrintStats( pMan );
+    pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkConstructFromCnf( Abc_Ntk_t * pNtk, Cnf_Man_t * p, Vec_Ptr_t * vMapped )
+{
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pNode, * pNodeNew;
+    Aig_Obj_t * pObj, * pLeaf;
+    Cnf_Cut_t * pCut;
+    Vec_Int_t * vCover;
+    unsigned uTruth;
+    int i, k, nDupGates;
+    // create the new network
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+    // make the mapper point to the new network
+    Aig_ManConst1(p->pManAig)->pData = Abc_NtkCreateNodeConst1(pNtkNew);
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        Aig_ManCi(p->pManAig, i)->pData = pNode->pCopy;
+    // process the nodes in topological order
+    vCover = Vec_IntAlloc( 1 << 16 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vMapped, pObj, i )
+    {
+        // create new node
+        pNodeNew = Abc_NtkCreateNode( pNtkNew );
+        // add fanins according to the cut
+        pCut = (Cnf_Cut_t *)pObj->pData;
+        Cnf_CutForEachLeaf( p->pManAig, pCut, pLeaf, k )
+            Abc_ObjAddFanin( pNodeNew, (Abc_Obj_t *)pLeaf->pData );
+        // add logic function
+        if ( pCut->nFanins < 5 )
+        {
+            uTruth = 0xFFFF & *Cnf_CutTruth(pCut);
+            Cnf_SopConvertToVector( p->pSops[uTruth], p->pSopSizes[uTruth], vCover );
+            pNodeNew->pData = Abc_SopCreateFromIsop( (Mem_Flex_t *)pNtkNew->pManFunc, pCut->nFanins, vCover );
+        }
+        else
+            pNodeNew->pData = Abc_SopCreateFromIsop( (Mem_Flex_t *)pNtkNew->pManFunc, pCut->nFanins, pCut->vIsop[1] );
+        // save the node
+        pObj->pData = pNodeNew;
+    }
+    Vec_IntFree( vCover );
+    // add the CO drivers
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        pObj = Aig_ManCo(p->pManAig, i);
+        pNodeNew = Abc_ObjNotCond( (Abc_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+        Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+    }
+
+    // remove the constant node if not used
+    pNodeNew = (Abc_Obj_t *)Aig_ManConst1(p->pManAig)->pData;
+    if ( Abc_ObjFanoutNum(pNodeNew) == 0 )
+        Abc_NtkDeleteObj( pNodeNew );
+    // minimize the node
+//    Abc_NtkSweep( pNtkNew, 0 );
+    // decouple the PO driver nodes to reduce the number of levels
+    nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 );
+//    if ( nDupGates && If_ManReadVerbose(pIfMan) )
+//        Abc_Print( 1, "Duplicated %d gates to decouple the CO drivers.\n", nDupGates );
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        Abc_Print( 1, "Abc_NtkConstructFromCnf(): Network check has failed.\n" );
+    return pNtkNew;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName, int fFastAlgo, int fChangePol, int fVerbose )
+{
+//    Vec_Ptr_t * vMapped = NULL;
+    Aig_Man_t * pMan;
+//    Cnf_Man_t * pManCnf = NULL;
+    Cnf_Dat_t * pCnf;
+    Abc_Ntk_t * pNtkNew = NULL;
+    abctime clk = Abc_Clock();
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    // convert to the AIG manager
+    pMan = Abc_NtkToDar( pNtk, 0, 0 );
+    if ( pMan == NULL )
+        return NULL;
+    if ( !Aig_ManCheck( pMan ) )
+    {
+        Abc_Print( 1, "Abc_NtkDarToCnf: AIG check has failed.\n" );
+        Aig_ManStop( pMan );
+        return NULL;
+    }
+    // perform balance
+    if ( fVerbose )
+    Aig_ManPrintStats( pMan );
+
+    // derive CNF
+    if ( fFastAlgo )
+        pCnf = Cnf_DeriveFast( pMan, 0 );
+    else
+        pCnf = Cnf_Derive( pMan, 0 );
+
+    // adjust polarity
+    if ( fChangePol )
+        Cnf_DataTranformPolarity( pCnf, 0 );
+
+    // print stats
+//    if ( fVerbose )
+    {
+        Abc_Print( 1, "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d.   ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+
+/*
+    // write the network for verification
+    pManCnf = Cnf_ManRead();
+    vMapped = Cnf_ManScanMapping( pManCnf, 1, 0 );
+    pNtkNew = Abc_NtkConstructFromCnf( pNtk, pManCnf, vMapped );
+    Vec_PtrFree( vMapped );
+*/
+    // write CNF into a file
+    Cnf_DataWriteIntoFile( pCnf, pFileName, 0, NULL, NULL );
+    Cnf_DataFree( pCnf );
+    Cnf_ManFree();
+    Aig_ManStop( pMan );
+    return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Solves combinational miter using a SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDSat( Abc_Ntk_t * pNtk, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fAlignPol, int fAndOuts, int fNewSolver, int fVerbose )
+{
+    Aig_Man_t * pMan;
+    int RetValue;//, clk = Abc_Clock();
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( Abc_NtkLatchNum(pNtk) == 0 );
+//    assert( Abc_NtkPoNum(pNtk) == 1 );
+    pMan = Abc_NtkToDar( pNtk, 0, 0 );
+    RetValue = Fra_FraigSat( pMan, nConfLimit, nInsLimit, nLearnedStart, nLearnedDelta, nLearnedPerce, fAlignPol, fAndOuts, fNewSolver, fVerbose ); 
+    pNtk->pModel = (int *)pMan->pData, pMan->pData = NULL;
+    Aig_ManStop( pMan );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Solves combinational miter using a SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkPartitionedSat( Abc_Ntk_t * pNtk, int nAlgo, int nPartSize, int nConfPart, int nConfTotal, int fAlignPol, int fSynthesize, int fVerbose )
+{
+    extern int Aig_ManPartitionedSat( Aig_Man_t * pNtk, int nAlgo, int nPartSize, int nConfPart, int nConfTotal, int fAlignPol, int fSynthesize, int fVerbose );
+    Aig_Man_t * pMan;
+    int RetValue;//, clk = Abc_Clock();
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( Abc_NtkLatchNum(pNtk) == 0 );
+    pMan = Abc_NtkToDar( pNtk, 0, 0 );
+    RetValue = Aig_ManPartitionedSat( pMan, nAlgo, nPartSize, nConfPart, nConfTotal, fAlignPol, fSynthesize, fVerbose ); 
+    pNtk->pModel = (int *)pMan->pData, pMan->pData = NULL;
+    Aig_ManStop( pMan );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarCec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int fPartition, int fVerbose )
+{
+    Aig_Man_t * pMan, * pMan1, * pMan2;
+    Abc_Ntk_t * pMiter;
+    int RetValue;
+    abctime clkTotal = Abc_Clock();
+/*
+    {
+    extern void Cec_ManVerifyTwoAigs( Aig_Man_t * pAig0, Aig_Man_t * pAig1, int fVerbose );
+    Aig_Man_t * pAig0 = Abc_NtkToDar( pNtk1, 0, 0 );
+    Aig_Man_t * pAig1 = Abc_NtkToDar( pNtk2, 0, 0 );
+    Cec_ManVerifyTwoAigs( pAig0, pAig1, 1 );
+    Aig_ManStop( pAig0 );
+    Aig_ManStop( pAig1 );
+    return 1;
+    }
+*/
+    // cannot partition if it is already a miter
+    if ( pNtk2 == NULL && fPartition == 1 )
+    {
+        Abc_Print( 1, "Abc_NtkDarCec(): Switching to non-partitioned CEC for the miter.\n" );
+        fPartition = 0;
+    }
+
+    // if partitioning is selected, call partitioned CEC
+    if ( fPartition )
+    {
+        pMan1 = Abc_NtkToDar( pNtk1, 0, 0 );
+        pMan2 = Abc_NtkToDar( pNtk2, 0, 0 );
+        RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, nConfLimit, 100, 1, fVerbose );
+        Aig_ManStop( pMan1 );
+        Aig_ManStop( pMan2 );
+        goto finish;
+    }
+
+    if ( pNtk2 != NULL )
+    {
+        // get the miter of the two networks
+        pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0, 0, 0 );
+        if ( pMiter == NULL )
+        {
+            Abc_Print( 1, "Miter computation has failed.\n" );
+            return 0;
+        }
+    }
+    else
+    {
+        pMiter = Abc_NtkDup( pNtk1 );
+    }
+    RetValue = Abc_NtkMiterIsConstant( pMiter );
+    if ( RetValue == 0 )
+    {
+//        extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames );
+        Abc_Print( 1, "Networks are NOT EQUIVALENT after structural hashing.\n" );
+        // report the error
+        if ( pNtk2 == NULL )
+            pNtk1->pModel = Abc_NtkVerifyGetCleanModel( pNtk1, 1 );
+//        pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames );
+//        Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames );
+//        ABC_FREE( pMiter->pModel );
+        Abc_NtkDelete( pMiter );
+        return 0;
+    }
+    if ( RetValue == 1 )
+    {
+        Abc_NtkDelete( pMiter );
+        Abc_Print( 1, "Networks are equivalent after structural hashing.\n" );
+        return 1;
+    }
+
+    // derive the AIG manager
+    pMan = Abc_NtkToDar( pMiter, 0, 0 );
+    Abc_NtkDelete( pMiter );
+    if ( pMan == NULL )
+    {
+        Abc_Print( 1, "Converting miter into AIG has failed.\n" );
+        return -1;
+    }
+    // perform verification
+    RetValue = Fra_FraigCec( &pMan, 100000, fVerbose );
+    // transfer model if given
+    if ( pNtk2 == NULL )
+        pNtk1->pModel = (int *)pMan->pData, pMan->pData = NULL;
+    Aig_ManStop( pMan );
+
+finish:
+    // report the miter
+    if ( RetValue == 1 )
+    {
+        Abc_Print( 1, "Networks are equivalent.   " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+    }
+    else if ( RetValue == 0 )
+    {
+        Abc_Print( 1, "Networks are NOT EQUIVALENT.   " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+    }
+    else
+    {
+        Abc_Print( 1, "Networks are UNDECIDED.   " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+    }
+    fflush( stdout );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, Fra_Ssw_t * pPars )
+{
+    Fraig_Params_t Params;
+    Abc_Ntk_t * pNtkAig = NULL, * pNtkFraig;
+    Aig_Man_t * pMan, * pTemp;
+    abctime clk = Abc_Clock();
+
+    // preprocess the miter by fraiging it
+    // (note that for each functional class, fraiging leaves one representative;
+    // so fraiging does not reduce the number of functions represented by nodes
+    Fraig_ParamsSetDefault( &Params );
+    Params.nBTLimit = 100000;
+    if ( pPars->fFraiging && pPars->nPartSize == 0 )
+    {
+        pNtkFraig = Abc_NtkFraig( pNtk, &Params, 0, 0 );
+if ( pPars->fVerbose ) 
+{
+ABC_PRT( "Initial fraiging time", Abc_Clock() - clk );
+}
+    }
+    else
+        pNtkFraig = Abc_NtkDup( pNtk );
+
+    pMan = Abc_NtkToDar( pNtkFraig, 0, 1 );
+    Abc_NtkDelete( pNtkFraig );
+    if ( pMan == NULL )
+        return NULL;
+
+//    pPars->TimeLimit = 5.0;
+    pMan = Fra_FraigInduction( pTemp = pMan, pPars );
+    Aig_ManStop( pTemp );
+    if ( pMan )
+    {
+        if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) )
+            pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+        else
+        {
+            Abc_Obj_t * pObj;
+            int i;
+            pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+            Abc_NtkForEachLatch( pNtkAig, pObj, i )
+                Abc_LatchSetInit0( pObj );
+        }
+        Aig_ManStop( pMan );
+    }
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print Latch Equivalence Classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintLatchEquivClasses( Abc_Ntk_t * pNtk, Aig_Man_t * pAig )
+{
+    int header_dumped = 0;
+    int num_orig_latches = Abc_NtkLatchNum(pNtk);
+    char **pNames = ABC_ALLOC( char *, num_orig_latches );
+    int *p_irrelevant = ABC_ALLOC( int, num_orig_latches );
+    char * pFlopName, * pReprName;
+    Aig_Obj_t * pFlop, * pRepr;
+    Abc_Obj_t * pNtkFlop; 
+    int repr_idx;
+    int i;
+
+    Abc_NtkForEachLatch( pNtk, pNtkFlop, i )
+    {
+        char *temp_name = Abc_ObjName( Abc_ObjFanout0(pNtkFlop) );
+        pNames[i] = ABC_ALLOC( char , strlen(temp_name)+1);
+        strcpy(pNames[i], temp_name);
+    }
+    i = 0;
+    
+    Aig_ManSetCioIds( pAig );
+    Saig_ManForEachLo( pAig, pFlop, i )
+    {
+        p_irrelevant[i] = false;
+        
+        pFlopName = pNames[i];
+
+        pRepr = Aig_ObjRepr(pAig, pFlop);
+
+        if ( pRepr == NULL )
+        {
+            // Abc_Print( 1, "Nothing equivalent to flop %s\n", pFlopName);
+//            p_irrelevant[i] = true;
+            continue;
+        }
+
+        if (!header_dumped)
+        {
+            Abc_Print( 1, "Here are the flop equivalences:\n");
+            header_dumped = true;
+        }
+
+        // pRepr is representative of the equivalence class, to which pFlop belongs
+        if ( Aig_ObjIsConst1(pRepr) )
+        {
+            Abc_Print( 1, "Original flop %s is proved equivalent to constant.\n", pFlopName );
+            // Abc_Print( 1, "Original flop # %d is proved equivalent to constant.\n", i );
+            continue;
+        }
+
+        assert( Saig_ObjIsLo( pAig, pRepr ) );
+        repr_idx = Aig_ObjCioId(pRepr) - Saig_ManPiNum(pAig);
+        pReprName = pNames[repr_idx];
+        Abc_Print( 1, "Original flop %s is proved equivalent to flop %s.\n",  pFlopName, pReprName );
+        // Abc_Print( 1, "Original flop # %d is proved equivalent to flop # %d.\n",  i, repr_idx );
+    }
+
+    header_dumped = false;
+    for (i=0; i<num_orig_latches; ++i)
+    {
+        if (p_irrelevant[i])
+        {
+            if (!header_dumped)
+            {
+                Abc_Print( 1, "The following flops have been deemed irrelevant:\n");
+                header_dumped = true;
+            }
+            Abc_Print( 1, "%s ", pNames[i]);
+        }
+        
+        ABC_FREE(pNames[i]);
+    }
+    if (header_dumped)
+        Abc_Print( 1, "\n");
+    
+    ABC_FREE(pNames);
+    ABC_FREE(p_irrelevant);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarSeqSweep2( Abc_Ntk_t * pNtk, Ssw_Pars_t * pPars )
+{
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+
+    pMan = Ssw_SignalCorrespondence( pTemp = pMan, pPars );
+
+    if ( pPars->fFlopVerbose )
+        Abc_NtkPrintLatchEquivClasses(pNtk, pTemp);
+
+    Aig_ManStop( pTemp );
+    if ( pMan == NULL )
+        return NULL;
+
+    if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) )
+        pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+    else
+    {
+        Abc_Obj_t * pObj;
+        int i;
+        pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+        Abc_NtkForEachLatch( pNtkAig, pObj, i )
+            Abc_LatchSetInit0( pObj );
+    }
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes latch correspondence.]
+
+  Description [] 
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose )
+{
+    Aig_Man_t * pMan, * pTemp;
+    Abc_Ntk_t * pNtkAig = NULL;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+    pMan = Fra_FraigLatchCorrespondence( pTemp = pMan, nFramesP, nConfMax, 0, fVerbose, NULL, 0.0 );
+    Aig_ManStop( pTemp );
+    if ( pMan )
+    {
+        if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) )
+            pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+        else
+        {
+            Abc_Obj_t * pObj;
+            int i;
+            pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+            Abc_NtkForEachLatch( pNtkAig, pObj, i )
+                Abc_LatchSetInit0( pObj );
+        }
+        Aig_ManStop( pMan );
+    }
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes latch correspondence.]
+
+  Description [] 
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarLcorrNew( Abc_Ntk_t * pNtk, int nVarsMax, int nConfMax, int fVerbose )
+{
+    Ssw_Pars_t Pars, * pPars = &Pars;
+    Aig_Man_t * pMan, * pTemp;
+    Abc_Ntk_t * pNtkAig = NULL;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+    Ssw_ManSetDefaultParams( pPars );
+    pPars->fLatchCorrOpt = 1;
+    pPars->nBTLimit      = nConfMax;
+    pPars->nSatVarMax    = nVarsMax;
+    pPars->fVerbose      = fVerbose;
+    pMan = Ssw_SignalCorrespondence( pTemp = pMan, pPars );
+    Aig_ManStop( pTemp );
+    if ( pMan )
+    {
+        if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) )
+            pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+        else
+        {
+            Abc_Obj_t * pObj;
+            int i;
+            pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+            Abc_NtkForEachLatch( pNtkAig, pObj, i )
+                Abc_LatchSetInit0( pObj );
+        }
+        Aig_ManStop( pMan );
+    }
+    return pNtkAig;
+}
+
+/*
+#include <signal.h>
+#include "misc/util/utilMem.h"
+static void sigfunc( int signo ) 
+{
+    if (signo == SIGINT) {
+        Abc_Print( 1, "SIGINT received!\n");
+        s_fInterrupt = 1;
+    }
+}
+*/
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarBmc( Abc_Ntk_t * pNtk, int nStart, int nFrames, int nSizeMax, int nNodeDelta, int nTimeOut, int nBTLimit, int nBTLimitAll, int fRewrite, int fNewAlgo, int fOrDecomp, int nCofFanLit, int fVerbose, int * piFrames )
+{
+    Aig_Man_t * pMan;
+    Vec_Int_t * vMap = NULL;
+    int status, RetValue = -1;
+    abctime clk = Abc_Clock();
+    abctime nTimeLimit = nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0;
+    // derive the AIG manager
+    if ( fOrDecomp )
+        pMan = Abc_NtkToDarBmc( pNtk, &vMap );
+    else
+        pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+    {
+        Abc_Print( 1, "Converting miter into AIG has failed.\n" );
+        return RetValue;
+    }
+    assert( pMan->nRegs > 0 );
+    assert( vMap == NULL || Vec_IntSize(vMap) == Saig_ManPoNum(pMan) );
+    if ( fVerbose && vMap && Abc_NtkPoNum(pNtk) != Saig_ManPoNum(pMan) ) 
+        Abc_Print( 1, "Expanded %d outputs into %d outputs using OR decomposition.\n", Abc_NtkPoNum(pNtk), Saig_ManPoNum(pMan) );
+
+    // perform verification
+    if ( fNewAlgo ) // command 'bmc'
+    {
+        int iFrame;
+        RetValue = Saig_ManBmcSimple( pMan, nFrames, nSizeMax, nBTLimit, fRewrite, fVerbose, &iFrame, nCofFanLit );
+        if ( piFrames )
+            *piFrames = iFrame;
+        ABC_FREE( pNtk->pModel );
+        ABC_FREE( pNtk->pSeqModel );
+        pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL;
+        if ( RetValue == 1 )
+            Abc_Print( 1, "Incorrect return value.  " );
+        else if ( RetValue == -1 )
+        {
+            Abc_Print( 1, "No output asserted in %d frames. Resource limit reached ", Abc_MaxInt(iFrame+1,0) );
+            if ( nTimeLimit && Abc_Clock() > nTimeLimit )
+                Abc_Print( 1, "(timeout %d sec). ", nTimeLimit );
+            else
+                Abc_Print( 1, "(conf limit %d). ", nBTLimit );
+        }
+        else // if ( RetValue == 0 )
+        {
+            Abc_Cex_t * pCex = pNtk->pSeqModel;
+            Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", pCex->iPo, pNtk->pName, pCex->iFrame );
+        }
+ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    else
+    { 
+        RetValue = Saig_BmcPerform( pMan, nStart, nFrames, nNodeDelta, nTimeOut, nBTLimit, nBTLimitAll, fVerbose, 0, piFrames, 0 );
+        ABC_FREE( pNtk->pModel );
+        ABC_FREE( pNtk->pSeqModel );
+        pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL;
+    }
+    // verify counter-example
+    if ( pNtk->pSeqModel ) 
+    {
+        status = Saig_ManVerifyCex( pMan, pNtk->pSeqModel );
+        if ( status == 0 )
+            Abc_Print( 1, "Abc_NtkDarBmc(): Counter-example verification has FAILED.\n" );
+    }
+    Aig_ManStop( pMan );
+    // update the counter-example
+    if ( pNtk->pSeqModel && vMap )
+        pNtk->pSeqModel->iPo = Vec_IntEntry( vMap, pNtk->pSeqModel->iPo );
+    Vec_IntFreeP( &vMap );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarBmc3( Abc_Ntk_t * pNtk, Saig_ParBmc_t * pPars, int fOrDecomp )
+{
+    Aig_Man_t * pMan;
+    Vec_Int_t * vMap = NULL;
+    int status, RetValue = -1;
+    abctime clk = Abc_Clock();
+    abctime nTimeOut = pPars->nTimeOut ? pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0;
+    if ( fOrDecomp && !pPars->fSolveAll )
+        pMan = Abc_NtkToDarBmc( pNtk, &vMap );
+    else
+        pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+    {
+        Abc_Print( 1, "Converting miter into AIG has failed.\n" );
+        return RetValue;
+    }
+    assert( pMan->nRegs > 0 );
+    if ( pPars->fVerbose && vMap && Abc_NtkPoNum(pNtk) != Saig_ManPoNum(pMan) ) 
+        Abc_Print( 1, "Expanded %d outputs into %d outputs using OR decomposition.\n", Abc_NtkPoNum(pNtk), Saig_ManPoNum(pMan) );
+
+    RetValue = Saig_ManBmcScalable( pMan, pPars );
+    ABC_FREE( pNtk->pModel );
+    ABC_FREE( pNtk->pSeqModel );
+    pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL;
+    if ( !pPars->fSilent )
+    {
+        if ( RetValue == 1 )
+        {
+            Abc_Print( 1, "Explored all reachable states after completing %d frames.  ", 1<<Aig_ManRegNum(pMan) );
+        }
+        else if ( RetValue == -1 )
+        {
+            if ( pPars->nFailOuts == 0 )
+            {
+                Abc_Print( 1, "No output asserted in %d frames. Resource limit reached ", Abc_MaxInt(pPars->iFrame+1,0) );
+                if ( nTimeOut && Abc_Clock() > nTimeOut )
+                    Abc_Print( 1, "(timeout %d sec). ", pPars->nTimeOut );
+                else
+                    Abc_Print( 1, "(conf limit %d). ", pPars->nConfLimit );
+            }
+            else
+            {
+                Abc_Print( 1, "The total of %d outputs asserted in %d frames. Resource limit reached ", pPars->nFailOuts, pPars->iFrame );
+                if ( Abc_Clock() > nTimeOut )
+                    Abc_Print( 1, "(timeout %d sec). ", pPars->nTimeOut );
+                else
+                    Abc_Print( 1, "(conf limit %d). ", pPars->nConfLimit );
+            }
+        }
+        else // if ( RetValue == 0 )
+        {
+            if ( !pPars->fSolveAll )
+            {
+                Abc_Cex_t * pCex = pNtk->pSeqModel;
+                Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", pCex->iPo, pNtk->pName, pCex->iFrame );
+            }
+            else
+            {
+                int nOutputs = Saig_ManPoNum(pMan) - Saig_ManConstrNum(pMan);
+                if ( pMan->vSeqModelVec == NULL || Vec_PtrCountZero(pMan->vSeqModelVec) == nOutputs )
+                    Abc_Print( 1, "None of the %d outputs is found to be SAT", nOutputs );
+                else if ( Vec_PtrCountZero(pMan->vSeqModelVec) == 0 )
+                    Abc_Print( 1, "All %d outputs are found to be SAT", nOutputs );
+                else
+                {
+                    Abc_Print( 1, "Some outputs are SAT (%d out of %d)", nOutputs - Vec_PtrCountZero(pMan->vSeqModelVec), nOutputs );
+                    if ( pPars->nDropOuts )
+                        Abc_Print( 1, " while others timed out (%d out of %d)", pPars->nDropOuts, nOutputs );
+                }
+                Abc_Print( 1, " after %d frames", pPars->iFrame );
+                Abc_Print( 1, ".   " );
+            }
+        }
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    if ( RetValue == 0 && pPars->fSolveAll )
+    {
+        if ( pNtk->vSeqModelVec )
+            Vec_PtrFreeFree( pNtk->vSeqModelVec );
+        pNtk->vSeqModelVec = pMan->vSeqModelVec;  pMan->vSeqModelVec = NULL;
+    }
+    if ( pNtk->pSeqModel ) 
+    {
+        status = Saig_ManVerifyCex( pMan, pNtk->pSeqModel );
+        if ( status == 0 )
+            Abc_Print( 1, "Abc_NtkDarBmc3(): Counter-example verification has FAILED.\n" );
+    }
+    Aig_ManStop( pMan );
+    // update the counter-example
+    if ( pNtk->pSeqModel && vMap )
+        pNtk->pSeqModel->iPo = Vec_IntEntry( vMap, pNtk->pSeqModel->iPo );
+    Vec_IntFreeP( &vMap );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarBmcInter_int( Aig_Man_t * pMan, Inter_ManParams_t * pPars, Aig_Man_t ** ppNtkRes )
+{
+    int RetValue = -1, iFrame;
+    abctime clk = Abc_Clock();
+    int nTotalProvedSat = 0;
+    assert( pMan->nRegs > 0 );
+    if ( ppNtkRes )
+        *ppNtkRes = NULL;
+    if ( pPars->fUseSeparate )
+    {
+        Aig_Man_t * pTemp, * pAux;
+        Aig_Obj_t * pObjPo;
+        int i, Counter = 0;
+        Saig_ManForEachPo( pMan, pObjPo, i )
+        {
+            if ( Aig_ObjFanin0(pObjPo) == Aig_ManConst1(pMan) )
+                continue;
+            if ( pPars->fVerbose )
+                Abc_Print( 1, "Solving output %2d (out of %2d):\n", i, Saig_ManPoNum(pMan) );
+            pTemp = Aig_ManDupOneOutput( pMan, i, 1 );
+            pTemp = Aig_ManScl( pAux = pTemp, 1, 1, 0, -1, -1, 0, 0 );
+            Aig_ManStop( pAux );
+            if ( Aig_ManRegNum(pTemp) == 0 )
+            {
+                pTemp->pSeqModel = NULL;
+                RetValue = Fra_FraigSat( pTemp, pPars->nBTLimit, 0, 0, 0, 0, 0, 0, 0, 0 ); 
+                if ( pTemp->pData )
+                    pTemp->pSeqModel = Abc_CexCreate( Aig_ManRegNum(pMan), Saig_ManPiNum(pMan), (int *)pTemp->pData, 0, i, 1 );
+//                pNtk->pModel = pTemp->pData, pTemp->pData = NULL;
+            }
+            else
+                RetValue = Inter_ManPerformInterpolation( pTemp, pPars, &iFrame );
+            if ( pTemp->pSeqModel )
+            {
+                if ( pPars->fDropSatOuts )
+                {
+                    Abc_Print( 1, "Output %d proved SAT in frame %d (replacing by const 0 and continuing...)\n", i, pTemp->pSeqModel->iFrame );
+                    Aig_ObjPatchFanin0( pMan, pObjPo, Aig_ManConst0(pMan) );
+                    Aig_ManStop( pTemp );
+                    nTotalProvedSat++;
+                    continue;
+                }
+                else
+                {
+                    Abc_Cex_t * pCex;
+                    pCex = pMan->pSeqModel = pTemp->pSeqModel; pTemp->pSeqModel = NULL;
+                    pCex->iPo = i;
+                    Aig_ManStop( pTemp );
+                    break;
+                }
+            }
+            // if solved, remove the output
+            if ( RetValue == 1 )
+            {
+                Aig_ObjPatchFanin0( pMan, pObjPo, Aig_ManConst0(pMan) );
+//                    Abc_Print( 1, "Output %3d : Solved ", i );
+            }
+            else
+            {
+                Counter++;
+//                    Abc_Print( 1, "Output %3d : Undec  ", i );
+            }
+//                Aig_ManPrintStats( pTemp );
+            Aig_ManStop( pTemp );
+            Abc_Print( 1, "Solving output %3d (out of %3d) using interpolation.\r", i, Saig_ManPoNum(pMan) );
+        }
+        Aig_ManCleanup( pMan );
+        if ( pMan->pSeqModel == NULL )
+        {
+            Abc_Print( 1, "Interpolation left %d (out of %d) outputs unsolved              \n", Counter, Saig_ManPoNum(pMan) );
+            if ( Counter )
+                RetValue = -1;
+        }
+        if ( ppNtkRes )
+        {
+            pTemp = Aig_ManDupUnsolvedOutputs( pMan, 1 );
+            *ppNtkRes = Aig_ManScl( pTemp, 1, 1, 0, -1, -1, 0, 0 );
+            Aig_ManStop( pTemp );
+        }
+    }
+    else
+    {    
+        RetValue = Inter_ManPerformInterpolation( pMan, pPars, &iFrame );
+    }
+    if ( nTotalProvedSat )
+        Abc_Print( 1, "The total of %d outputs proved SAT and replaced by const 0 in this run.\n", nTotalProvedSat );
+    if ( RetValue == 1 )
+        Abc_Print( 1, "Property proved.  " );
+    else if ( RetValue == 0 )
+        Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.  ", pMan->pSeqModel ? pMan->pSeqModel->iPo : -1, pMan->pName, iFrame );
+    else if ( RetValue == -1 )
+        Abc_Print( 1, "Property UNDECIDED.  " );
+    else
+        assert( 0 );
+ABC_PRT( "Time", Abc_Clock() - clk );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarBmcInter( Abc_Ntk_t * pNtk, Inter_ManParams_t * pPars, Abc_Ntk_t ** ppNtkRes )
+{
+    Aig_Man_t * pMan;
+    int RetValue;
+    if ( ppNtkRes )
+        *ppNtkRes = NULL;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+    {
+        Abc_Print( 1, "Converting miter into AIG has failed.\n" );
+        return -1;
+    }
+    if ( pPars->fUseSeparate && ppNtkRes )
+    {
+        Aig_Man_t * pManNew;
+        RetValue = Abc_NtkDarBmcInter_int( pMan, pPars, &pManNew );
+        *ppNtkRes = Abc_NtkFromAigPhase( pManNew );
+        Aig_ManStop( pManNew );
+    }
+    else
+    {
+        RetValue = Abc_NtkDarBmcInter_int( pMan, pPars, NULL );
+    }
+    ABC_FREE( pNtk->pModel );
+    ABC_FREE( pNtk->pSeqModel );
+    pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL;
+    Aig_ManStop( pMan );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarDemiter( Abc_Ntk_t * pNtk )
+{ 
+    char * pFileNameGeneric, pFileName0[1000], pFileName1[1000];
+    Aig_Man_t * pMan, * pPart0, * pPart1;//, * pMiter;
+    // derive the AIG manager
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+    {
+        Abc_Print( 1, "Converting network into AIG has failed.\n" );
+        return 0;
+    }
+//    if ( !Saig_ManDemiterSimple( pMan, &pPart0, &pPart1 ) )
+    if ( !Saig_ManDemiterSimpleDiff( pMan, &pPart0, &pPart1 ) )
+    {
+        Aig_ManStop( pMan );
+        Abc_Print( 1, "Demitering has failed.\n" );
+        return 0;
+    }
+    // create file names
+    pFileNameGeneric = Extra_FileNameGeneric( pNtk->pSpec ? pNtk->pSpec : pNtk->pName );
+//    sprintf( pFileName0,  "%s%s",  pFileNameGeneric, "_part0.aig" ); 
+//    sprintf( pFileName1,  "%s%s",  pFileNameGeneric, "_part1.aig" ); 
+    sprintf( pFileName0,  "%s",  "part0.aig" ); 
+    sprintf( pFileName1,  "%s",  "part1.aig" ); 
+    ABC_FREE( pFileNameGeneric );
+    // dump files
+    Ioa_WriteAiger( pPart0, pFileName0, 0, 0 );
+    Ioa_WriteAiger( pPart1, pFileName1, 0, 0 );
+    Abc_Print( 1, "Demitering produced two files \"%s\" and \"%s\".\n", pFileName0, pFileName1 );
+    // create two-level miter
+//    pMiter = Saig_ManCreateMiterTwo( pPart0, pPart1, 2 );
+//    Aig_ManDumpBlif( pMiter, "miter01.blif", NULL, NULL );
+//    Aig_ManStop( pMiter );
+//    Abc_Print( 1, "The new miter is written into file \"%s\".\n", "miter01.blif" );
+    Aig_ManStop( pPart0 );
+    Aig_ManStop( pPart1 );
+    Aig_ManStop( pMan );
+    return 1;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarDemiterNew( Abc_Ntk_t * pNtk )
+{ 
+    char * pFileNameGeneric, pFileName0[1000], pFileName1[1000];
+    Aig_Man_t * pMan, * pPart0, * pPart1;//, * pMiter;
+    // derive the AIG manager
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+    {
+        Abc_Print( 1, "Converting network into AIG has failed.\n" );
+        return 0;
+    }
+
+    Saig_ManDemiterNew( pMan );
+    Aig_ManStop( pMan );
+    return 1;
+
+//    if ( !Saig_ManDemiterSimple( pMan, &pPart0, &pPart1 ) )
+    if ( !Saig_ManDemiterSimpleDiff( pMan, &pPart0, &pPart1 ) )
+    {
+        Abc_Print( 1, "Demitering has failed.\n" );
+        return 0;
+    }
+    // create file names
+    pFileNameGeneric = Extra_FileNameGeneric( pNtk->pSpec );
+    sprintf( pFileName0,  "%s%s",  pFileNameGeneric, "_part0.aig" ); 
+    sprintf( pFileName1,  "%s%s",  pFileNameGeneric, "_part1.aig" ); 
+    ABC_FREE( pFileNameGeneric );
+    // dump files
+    Ioa_WriteAiger( pPart0, pFileName0, 0, 0 );
+    Ioa_WriteAiger( pPart1, pFileName1, 0, 0 );
+    Abc_Print( 1, "Demitering produced two files \"%s\" and \"%s\".\n", pFileName0, pFileName1 );
+    // create two-level miter
+//    pMiter = Saig_ManCreateMiterTwo( pPart0, pPart1, 2 );
+//    Aig_ManDumpBlif( pMiter, "miter01.blif", NULL, NULL );
+//    Aig_ManStop( pMiter );
+//    Abc_Print( 1, "The new miter is written into file \"%s\".\n", "miter01.blif" );
+    Aig_ManStop( pPart0 );
+    Aig_ManStop( pPart1 );
+    Aig_ManStop( pMan );
+    return 1;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarDemiterDual( Abc_Ntk_t * pNtk, int fVerbose )
+{ 
+    char * pFileNameGeneric, pFileName0[1000], pFileName1[1000];
+    Aig_Man_t * pMan, * pPart0, * pPart1;//, * pMiter;
+    if ( (Abc_NtkPoNum(pNtk) & 1) )
+    {
+        Abc_Print( 1, "The number of POs should be even.\n" );
+        return 0;
+    }
+    // derive the AIG manager
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+    {
+        Abc_Print( 1, "Converting network into AIG has failed.\n" );
+        return 0;
+    }
+//    if ( !Saig_ManDemiterSimple( pMan, &pPart0, &pPart1 ) )
+    if ( !Saig_ManDemiterDual( pMan, &pPart0, &pPart1 ) )
+    {
+        Abc_Print( 1, "Demitering has failed.\n" );
+        return 0;
+    }
+    // create new AIG
+    ABC_FREE( pPart0->pName );
+    pPart0->pName = Abc_UtilStrsav( "part0" );
+    // create new AIGs
+    ABC_FREE( pPart1->pName );
+    pPart1->pName = Abc_UtilStrsav( "part1" );
+    // create file names
+    pFileNameGeneric = Extra_FileNameGeneric( pNtk->pSpec );
+//    sprintf( pFileName0,  "%s%s",  pFileNameGeneric, "_part0.aig" ); 
+//    sprintf( pFileName1,  "%s%s",  pFileNameGeneric, "_part1.aig" ); 
+    sprintf( pFileName0,  "%s",  "part0.aig" ); 
+    sprintf( pFileName1,  "%s",  "part1.aig" ); 
+    ABC_FREE( pFileNameGeneric );
+    Ioa_WriteAiger( pPart0, pFileName0, 0, 0 );
+    Ioa_WriteAiger( pPart1, pFileName1, 0, 0 );
+    Abc_Print( 1, "Demitering produced two files \"%s\" and \"%s\".\n", pFileName0, pFileName1 );
+    // dump files
+    if ( fVerbose )
+    {
+//        Abc_Print( 1, "Init:  " );
+        Aig_ManPrintStats( pMan );
+//        Abc_Print( 1, "Part1: " );
+        Aig_ManPrintStats( pPart0 );
+//        Abc_Print( 1, "Part2: " );
+        Aig_ManPrintStats( pPart1 );
+    }
+    // create two-level miter
+//    pMiter = Saig_ManCreateMiterTwo( pPart0, pPart1, 2 );
+//    Aig_ManDumpBlif( pMiter, "miter01.blif", NULL, NULL );
+//    Aig_ManStop( pMiter );
+//    Abc_Print( 1, "The new miter is written into file \"%s\".\n", "miter01.blif" );
+    Aig_ManStop( pPart0 );
+    Aig_ManStop( pPart1 );
+    Aig_ManStop( pMan );
+    return 1;
+} 
+ 
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarProve( Abc_Ntk_t * pNtk, Fra_Sec_t * pSecPar, int nBmcFramesMax, int nBmcConfMax )
+{
+    Aig_Man_t * pMan;
+    int iFrame = -1, RetValue = -1;
+    abctime clkTotal = Abc_Clock();
+    if ( pSecPar->fTryComb || Abc_NtkLatchNum(pNtk) == 0 )
+    {
+        Prove_Params_t Params, * pParams = &Params;
+        Abc_Ntk_t * pNtkComb;
+        int RetValue;
+        abctime clk = Abc_Clock();
+        if ( Abc_NtkLatchNum(pNtk) == 0 )
+            Abc_Print( 1, "The network has no latches. Running CEC.\n" );
+        // create combinational network
+        pNtkComb = Abc_NtkDup( pNtk );
+        Abc_NtkMakeComb( pNtkComb, 1 );
+        // solve it using combinational equivalence checking
+        Prove_ParamsSetDefault( pParams );
+        pParams->fVerbose = 1;
+        RetValue = Abc_NtkIvyProve( &pNtkComb, pParams );
+        // transfer model if given
+//        pNtk->pModel = pNtkComb->pModel; pNtkComb->pModel = NULL;
+        if ( RetValue == 0  && (Abc_NtkLatchNum(pNtk) == 0) )
+        {
+            pNtk->pModel = pNtkComb->pModel; pNtkComb->pModel = NULL;
+            Abc_Print( 1, "Networks are not equivalent.\n" );
+            ABC_PRT( "Time", Abc_Clock() - clk );
+            if ( pSecPar->fReportSolution )
+            {
+                Abc_Print( 1, "SOLUTION: FAIL       " );
+                ABC_PRT( "Time", Abc_Clock() - clkTotal );
+            }
+            return RetValue;
+        }
+        Abc_NtkDelete( pNtkComb );
+        // return the result, if solved
+        if ( RetValue == 1 )
+        {
+            Abc_Print( 1, "Networks are equivalent after CEC.   " );
+            ABC_PRT( "Time", Abc_Clock() - clk );
+            if ( pSecPar->fReportSolution )
+            {
+            Abc_Print( 1, "SOLUTION: PASS       " );
+            ABC_PRT( "Time", Abc_Clock() - clkTotal );
+            }
+            return RetValue;
+        }
+    }
+    // derive the AIG manager
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+    {
+        Abc_Print( 1, "Converting miter into AIG has failed.\n" );
+        return -1;
+    }
+    assert( pMan->nRegs > 0 );
+
+    if ( pSecPar->fTryBmc )
+    {
+        RetValue = Saig_BmcPerform( pMan, 0, nBmcFramesMax, 2000, 0, nBmcConfMax, 0, pSecPar->fVerbose, 0, &iFrame, 0 );
+        if ( RetValue == 0 )
+        {
+            Abc_Print( 1, "Networks are not equivalent.\n" );
+            if ( pSecPar->fReportSolution )
+            {
+                Abc_Print( 1, "SOLUTION: FAIL       " );
+                ABC_PRT( "Time", Abc_Clock() - clkTotal );
+            }
+            // return the counter-example generated
+            ABC_FREE( pNtk->pModel );
+            ABC_FREE( pNtk->pSeqModel );
+            pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL;
+            Aig_ManStop( pMan );
+            return RetValue;
+        }
+    } 
+    // perform verification
+    if ( pSecPar->fUseNewProver )
+    {
+        RetValue = Ssw_SecGeneralMiter( pMan, NULL );
+    }
+    else
+    {
+        RetValue = Fra_FraigSec( pMan, pSecPar, NULL );
+        ABC_FREE( pNtk->pModel );
+        ABC_FREE( pNtk->pSeqModel );
+        pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL;
+        if ( pNtk->pSeqModel )
+        {
+            Abc_Cex_t * pCex = pNtk->pSeqModel;
+            Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.\n", pCex->iPo, pNtk->pName, pCex->iFrame );
+            if ( !Saig_ManVerifyCex( pMan, pNtk->pSeqModel ) )
+                Abc_Print( 1, "Abc_NtkDarProve(): Counter-example verification has FAILED.\n" );
+        }
+    }
+    Aig_ManStop( pMan );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Fra_Sec_t * pSecPar )
+{
+//    Fraig_Params_t Params;
+    Aig_Man_t * pMan;
+    Abc_Ntk_t * pMiter;//, * pTemp;
+    int RetValue;
+ 
+    // get the miter of the two networks
+    pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0, 0, 0 );
+    if ( pMiter == NULL )
+    {
+        Abc_Print( 1, "Miter computation has failed.\n" );
+        return 0;
+    }
+    RetValue = Abc_NtkMiterIsConstant( pMiter );
+    if ( RetValue == 0 )
+    {
+        extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames );
+        Abc_Print( 1, "Networks are NOT EQUIVALENT after structural hashing.\n" );
+        // report the error
+        pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, pSecPar->nFramesMax );
+//        Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, pSecPar->nFramesMax );
+        ABC_FREE( pMiter->pModel );
+        Abc_NtkDelete( pMiter );
+        return 0;
+    }
+    if ( RetValue == 1 )
+    {
+        Abc_NtkDelete( pMiter );
+        Abc_Print( 1, "Networks are equivalent after structural hashing.\n" );
+        return 1;
+    }
+
+    // commented out because sometimes the problem became non-inductive
+/*
+    // preprocess the miter by fraiging it
+    // (note that for each functional class, fraiging leaves one representative;
+    // so fraiging does not reduce the number of functions represented by nodes
+    Fraig_ParamsSetDefault( &Params );
+    Params.nBTLimit = 100000;
+    pMiter = Abc_NtkFraig( pTemp = pMiter, &Params, 0, 0 );
+    Abc_NtkDelete( pTemp );
+    RetValue = Abc_NtkMiterIsConstant( pMiter );
+    if ( RetValue == 0 )
+    {
+        extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames );
+        Abc_Print( 1, "Networks are NOT EQUIVALENT after structural hashing.\n" );
+        // report the error
+        pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames );
+        Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames );
+        ABC_FREE( pMiter->pModel );
+        Abc_NtkDelete( pMiter );
+        return 0;
+    }
+    if ( RetValue == 1 )
+    {
+        Abc_NtkDelete( pMiter );
+        Abc_Print( 1, "Networks are equivalent after structural hashing.\n" );
+        return 1;
+    }
+*/
+    // derive the AIG manager
+    pMan = Abc_NtkToDar( pMiter, 0, 1 );
+    Abc_NtkDelete( pMiter );
+    if ( pMan == NULL )
+    {
+        Abc_Print( 1, "Converting miter into AIG has failed.\n" );
+        return -1;
+    }
+    assert( pMan->nRegs > 0 );
+
+    // perform verification
+    RetValue = Fra_FraigSec( pMan, pSecPar, NULL );
+    Aig_ManStop( pMan );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarPdr( Abc_Ntk_t * pNtk, Pdr_Par_t * pPars )
+{
+    int RetValue = -1;
+    abctime clk = Abc_Clock();
+    Aig_Man_t * pMan;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+    {
+        Abc_Print( 1, "Converting network into AIG has failed.\n" );
+        return -1;
+    }
+    RetValue = Pdr_ManSolve( pMan, pPars );
+    pPars->nDropOuts = Saig_ManPoNum(pMan) - pPars->nProveOuts - pPars->nFailOuts;
+    if ( !pPars->fSilent )
+    {
+        if ( pPars->fSolveAll )
+            Abc_Print( 1, "Properties:  All = %d. Proved = %d. Disproved = %d. Undecided = %d.   ", 
+                Saig_ManPoNum(pMan), pPars->nProveOuts, pPars->nFailOuts, pPars->nDropOuts );
+        else if ( RetValue == 1 )
+            Abc_Print( 1, "Property proved.  " );
+        else 
+        {
+            if ( RetValue == 0 )
+            {
+                if ( pMan->pSeqModel == NULL )
+                    Abc_Print( 1, "Abc_NtkDarPdr(): Counter-example is not available.\n" );
+                else
+                {
+                    Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.  ", pMan->pSeqModel->iPo, pNtk->pName, pMan->pSeqModel->iFrame );
+                    if ( !Saig_ManVerifyCex( pMan, pMan->pSeqModel ) )
+                        Abc_Print( 1, "Abc_NtkDarPdr(): Counter-example verification has FAILED.\n" );
+                }
+            }
+            else if ( RetValue == -1 )
+                Abc_Print( 1, "Property UNDECIDED.  " );
+            else
+                assert( 0 );
+        }
+        ABC_PRT( "Time", Abc_Clock() - clk );
+/*
+        Abc_Print( 1, "Status: " );
+        if ( pPars->pOutMap )
+        {
+            int i;
+            for ( i = 0; i < Saig_ManPoNum(pMan); i++ )
+                if ( pPars->pOutMap[i] == 1 )
+                    Abc_Print( 1, "%d=%s ", i, "unsat" );
+                else if ( pPars->pOutMap[i] == 0 )
+                    Abc_Print( 1, "%d=%s ", i, "sat" );
+                else if ( pPars->pOutMap[i] < 0 )
+                    Abc_Print( 1, "%d=%s ", i, "undec" );
+                else assert( 0 );
+        }
+        Abc_Print( 1, "\n" );
+*/
+    }
+    ABC_FREE( pNtk->pSeqModel );
+    pNtk->pSeqModel = pMan->pSeqModel;
+    pMan->pSeqModel = NULL;
+    if ( pNtk->vSeqModelVec )
+        Vec_PtrFreeFree( pNtk->vSeqModelVec );
+    pNtk->vSeqModelVec = pMan->vSeqModelVec;
+    pMan->vSeqModelVec = NULL;
+    Aig_ManStop( pMan );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD-based reachability analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarAbSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fVerbose )
+{
+    Aig_Man_t * pMan1, * pMan2 = NULL;
+    int RetValue;
+    // derive AIG manager
+    pMan1 = Abc_NtkToDar( pNtk1, 0, 1 );
+    if ( pMan1 == NULL )
+    {
+        Abc_Print( 1, "Converting miter into AIG has failed.\n" );
+        return -1;
+    }
+    assert( Aig_ManRegNum(pMan1) > 0 );
+    // derive AIG manager
+    if ( pNtk2 )
+    {
+        pMan2 = Abc_NtkToDar( pNtk2, 0, 1 );
+        if ( pMan2 == NULL )
+        {
+            Aig_ManStop( pMan1 );
+            Abc_Print( 1, "Converting miter into AIG has failed.\n" );
+            return -1;
+        }
+        assert( Aig_ManRegNum(pMan2) > 0 );
+        if ( Saig_ManPiNum(pMan1) != Saig_ManPiNum(pMan2) )
+        {
+            Aig_ManStop( pMan1 );
+            Aig_ManStop( pMan2 );
+            Abc_Print( 1, "The networks have different number of PIs.\n" );
+            return -1;
+        }
+        if ( Saig_ManPoNum(pMan1) != Saig_ManPoNum(pMan2) )
+        {
+            Aig_ManStop( pMan1 );
+            Aig_ManStop( pMan2 );
+            Abc_Print( 1, "The networks have different number of POs.\n" );
+            return -1;
+        }
+        if ( Aig_ManRegNum(pMan1) != Aig_ManRegNum(pMan2) )
+        {
+            Aig_ManStop( pMan1 );
+            Aig_ManStop( pMan2 );
+            Abc_Print( 1, "The networks have different number of flops.\n" );
+            return -1;
+        }
+    }
+    // perform verification
+    RetValue = Ssw_SecSpecialMiter( pMan1, pMan2, nFrames, fVerbose );
+    Aig_ManStop( pMan1 );
+    if ( pMan2 )
+        Aig_ManStop( pMan2 );
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarSimSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Ssw_Pars_t * pPars )
+{
+    Aig_Man_t * pMan1, * pMan2 = NULL;
+    int RetValue;
+    // derive AIG manager
+    pMan1 = Abc_NtkToDar( pNtk1, 0, 1 );
+    if ( pMan1 == NULL )
+    {
+        Abc_Print( 1, "Converting miter into AIG has failed.\n" );
+        return -1;
+    }
+    assert( Aig_ManRegNum(pMan1) > 0 );
+    // derive AIG manager
+    if ( pNtk2 )
+    {
+        pMan2 = Abc_NtkToDar( pNtk2, 0, 1 );
+        if ( pMan2 == NULL )
+        {
+            Abc_Print( 1, "Converting miter into AIG has failed.\n" );
+            return -1;
+        }
+        assert( Aig_ManRegNum(pMan2) > 0 );
+    }
+
+    // perform verification
+    RetValue = Ssw_SecWithSimilarity( pMan1, pMan2, pPars );
+    Aig_ManStop( pMan1 );
+    if ( pMan2 )
+        Aig_ManStop( pMan2 );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarMatch( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nDist, int fVerbose )
+{
+    extern Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter );
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan1, * pMan2 = NULL, * pManRes;
+    Vec_Int_t * vPairs;
+    assert( Abc_NtkIsStrash(pNtk1) );
+    // derive AIG manager
+    pMan1 = Abc_NtkToDar( pNtk1, 0, 1 );
+    if ( pMan1 == NULL )
+    {
+        Abc_Print( 1, "Converting miter into AIG has failed.\n" );
+        return NULL;
+    }
+    assert( Aig_ManRegNum(pMan1) > 0 );
+    // derive AIG manager
+    if ( pNtk2 )
+    {
+        pMan2 = Abc_NtkToDar( pNtk2, 0, 1 );
+        if ( pMan2 == NULL )
+        {
+            Abc_Print( 1, "Converting miter into AIG has failed.\n" );
+            return NULL;
+        }
+        assert( Aig_ManRegNum(pMan2) > 0 );
+    }
+
+    // perform verification
+    vPairs = Saig_StrSimPerformMatching( pMan1, pMan2, nDist, 1, &pManRes );
+    pNtkAig = Abc_NtkFromAigPhase( pManRes );
+    if ( vPairs )
+        Vec_IntFree( vPairs );
+    if ( pManRes )
+        Aig_ManStop( pManRes );
+    Aig_ManStop( pMan1 );
+    if ( pMan2 )
+        Aig_ManStop( pMan2 );
+    return pNtkAig;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchConst, int fLatchEqual, int fSaveNames, int fUseMvSweep, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose )
+{
+    extern void Aig_ManPrintControlFanouts( Aig_Man_t * p );
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+    if ( fSaveNames )
+    {
+        Aig_ManSeqCleanup( pMan );
+        if ( fLatchConst && pMan->nRegs )
+            pMan = Aig_ManConstReduce( pMan, fUseMvSweep, nFramesSymb, nFramesSatur, fVerbose, fVeryVerbose );
+        if ( fLatchEqual && pMan->nRegs )
+            pMan = Aig_ManReduceLaches( pMan, fVerbose );
+    }
+    else
+    {
+        if ( pMan->vFlopNums )
+            Vec_IntFree( pMan->vFlopNums );
+        pMan->vFlopNums = NULL;
+        pMan = Aig_ManScl( pTemp = pMan, fLatchConst, fLatchEqual, fUseMvSweep, nFramesSymb, nFramesSatur, fVerbose, fVeryVerbose );
+        Aig_ManStop( pTemp );
+    }
+
+    pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+//Aig_ManPrintControlFanouts( pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarRetime( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+//    Aig_ManReduceLachesCount( pMan );
+    if ( pMan->vFlopNums )
+        Vec_IntFree( pMan->vFlopNums ); 
+    pMan->vFlopNums = NULL;
+
+    pMan = Rtm_ManRetime( pTemp = pMan, 1, nStepsMax, fVerbose );
+    Aig_ManStop( pTemp );
+
+//    pMan = Aig_ManReduceLaches( pMan, 1 );
+//    pMan = Aig_ManConstReduce( pMan, 1, 0 );
+
+    pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarRetimeF( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+//    Aig_ManReduceLachesCount( pMan );
+    if ( pMan->vFlopNums )
+        Vec_IntFree( pMan->vFlopNums ); 
+    pMan->vFlopNums = NULL;
+
+    pMan = Aig_ManRetimeFrontier( pTemp = pMan, nStepsMax );
+    Aig_ManStop( pTemp );
+
+//    pMan = Aig_ManReduceLaches( pMan, 1 );
+//    pMan = Aig_ManConstReduce( pMan, 1, 0 );
+
+    pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarRetimeMostFwd( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose )
+{
+    extern Aig_Man_t * Saig_ManRetimeForward( Aig_Man_t * p, int nIters, int fVerbose );
+
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+//    Aig_ManReduceLachesCount( pMan );
+    if ( pMan->vFlopNums )
+        Vec_IntFree( pMan->vFlopNums ); 
+    pMan->vFlopNums = NULL;
+
+    pMan = Saig_ManRetimeForward( pTemp = pMan, nMaxIters, fVerbose );
+    Aig_ManStop( pTemp );
+
+//    pMan = Aig_ManReduceLaches( pMan, 1 );
+//    pMan = Aig_ManConstReduce( pMan, 1, 0 );
+
+    pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarRetimeMinArea( Abc_Ntk_t * pNtk, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose )
+{
+    extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose );
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+    if ( pMan->vFlopNums )
+        Vec_IntFree( pMan->vFlopNums ); 
+    pMan->vFlopNums = NULL;
+
+    pMan = Saig_ManRetimeMinArea( pTemp = pMan, nMaxIters, fForwardOnly, fBackwardOnly, fInitial, fVerbose );
+    Aig_ManStop( pTemp );
+
+    pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarRetimeStep( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan;
+    assert( Abc_NtkIsStrash(pNtk) );
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+    if ( pMan->vFlopNums )
+        Vec_IntFree( pMan->vFlopNums ); 
+    pMan->vFlopNums = NULL;
+
+    Aig_ManPrintStats(pMan);
+    Saig_ManRetimeSteps( pMan, 1000, 1, 0 );
+    Aig_ManPrintStats(pMan);
+
+    pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+Abc_Ntk_t * Abc_NtkDarHaigRecord( Abc_Ntk_t * pNtk, int nIters, int nSteps, int fRetimingOnly, int fAddBugs, int fUseCnf, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+    if ( pMan->vFlopNums )
+        Vec_IntFree( pMan->vFlopNums ); 
+    pMan->vFlopNums = NULL;
+
+    pMan = Saig_ManHaigRecord( pTemp = pMan, nIters, nSteps, fRetimingOnly, fAddBugs, fUseCnf, fVerbose );
+    Aig_ManStop( pTemp );
+
+    pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+*/
+
+/**Function*************************************************************
+
+  Synopsis    [Performs random simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int TimeOut, int fNew, int fMiter, int fVerbose, char * pFileSim )
+{
+    Aig_Man_t * pMan;
+    Abc_Cex_t * pCex;
+    int status, RetValue = -1;
+    abctime clk = Abc_Clock();
+    if ( Abc_NtkGetChoiceNum(pNtk) )
+    {
+        Abc_Print( 1, "Removing %d choices from the AIG.\n", Abc_NtkGetChoiceNum(pNtk) );
+        Abc_AigCleanup((Abc_Aig_t *)pNtk->pManFunc);
+    }
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( fNew )
+    {
+        Gia_Man_t * pGia;
+        Gia_ParSim_t Pars, * pPars = &Pars;
+        Gia_ManSimSetDefaultParams( pPars );
+        pPars->nWords = nWords;
+        pPars->nIters = nFrames;
+        pPars->TimeLimit = TimeOut;
+        pPars->fCheckMiter = fMiter;
+        pPars->fVerbose = fVerbose;
+        pGia = Gia_ManFromAig( pMan );
+        if ( Gia_ManSimSimulate( pGia, pPars ) )
+        { 
+            if ( pGia->pCexSeq )
+            {
+                Abc_Print( 1, "Simulation of %d frames with %d words asserted output %d in frame %d. ", 
+                    nFrames, nWords, pGia->pCexSeq->iPo, pGia->pCexSeq->iFrame );
+                status = Saig_ManVerifyCex( pMan, pGia->pCexSeq );
+                if ( status == 0 )
+                    Abc_Print( 1, "Abc_NtkDarSeqSim(): Counter-example verification has FAILED.\n" );
+            }
+            ABC_FREE( pNtk->pModel );
+            ABC_FREE( pNtk->pSeqModel );
+            pNtk->pSeqModel = pGia->pCexSeq; pGia->pCexSeq = NULL;
+            RetValue = 0;
+        }
+        else
+        {
+            Abc_Print( 1, "Simulation of %d frames with %d words did not assert the outputs.    ", 
+                nFrames, nWords );
+        }
+        Gia_ManStop( pGia );
+    }
+    else // comb/seq simulator
+    {
+        Fra_Sml_t * pSml;
+        if ( pFileSim != NULL )
+        {
+            assert( Abc_NtkLatchNum(pNtk) == 0 );
+            pSml = Fra_SmlSimulateCombGiven( pMan, pFileSim, fMiter, fVerbose );
+        }
+        else if ( Abc_NtkLatchNum(pNtk) == 0 )
+            pSml = Fra_SmlSimulateComb( pMan, nWords, fMiter );
+        else
+            pSml = Fra_SmlSimulateSeq( pMan, 0, nFrames, nWords, fMiter );
+        if ( pSml->fNonConstOut )
+        {
+            pCex = Fra_SmlGetCounterExample( pSml );
+            if ( pCex )
+            {
+                Abc_Print( 1, "Simulation of %d frame%s with %d word%s asserted output %d in frame %d. ", 
+                    pSml->nFrames, pSml->nFrames == 1 ? "": "s", 
+                    pSml->nWordsFrame, pSml->nWordsFrame == 1 ? "": "s", 
+                    pCex->iPo, pCex->iFrame );
+                status = Saig_ManVerifyCex( pMan, pCex );
+                if ( status == 0 )
+                    Abc_Print( 1, "Abc_NtkDarSeqSim(): Counter-example verification has FAILED.\n" );
+            }
+            ABC_FREE( pNtk->pModel );
+            ABC_FREE( pNtk->pSeqModel );
+            pNtk->pSeqModel = pCex;
+            RetValue = 0;
+        }
+        else
+        {
+            Abc_Print( 1, "Simulation of %d frames with %d words did not assert the outputs.    ", 
+                nFrames, nWords );
+        }
+        Fra_SmlStop( pSml );
+    }
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    Aig_ManStop( pMan );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs random simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarSeqSim3( Abc_Ntk_t * pNtk, Ssw_RarPars_t * pPars )
+{
+    Aig_Man_t * pMan;
+    int status, RetValue = -1;
+//    abctime clk = Abc_Clock();
+    if ( Abc_NtkGetChoiceNum(pNtk) )
+    {
+        Abc_Print( 1, "Removing %d choices from the AIG.\n", Abc_NtkGetChoiceNum(pNtk) );
+        Abc_AigCleanup((Abc_Aig_t *)pNtk->pManFunc);
+    }
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( Ssw_RarSimulate( pMan, pPars ) == 0 )
+    { 
+        if ( pMan->pSeqModel )
+        {
+//            Abc_Print( 1, "Simulation of %d frames with %d words asserted output %d in frame %d. ", 
+//                nFrames, nWords, pMan->pSeqModel->iPo, pMan->pSeqModel->iFrame );
+            status = Saig_ManVerifyCex( pMan, pMan->pSeqModel );
+            if ( status == 0 )
+                Abc_Print( 1, "Abc_NtkDarSeqSim(): Counter-example verification has FAILED.\n" );
+        }
+        ABC_FREE( pNtk->pModel );
+        ABC_FREE( pNtk->pSeqModel );
+        pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL;
+        RetValue = 0;
+    }
+    else
+    {
+//        Abc_Print( 1, "Simulation of %d frames with %d words did not assert the outputs.    ", 
+//            nFrames, nWords );
+    }
+    if ( pNtk->vSeqModelVec )
+        Vec_PtrFreeFree( pNtk->vSeqModelVec );
+    pNtk->vSeqModelVec = pMan->vSeqModelVec;  pMan->vSeqModelVec = NULL;
+//    ABC_PRT( "Time", Abc_Clock() - clk );
+    pNtk->pData = pMan->pData; pMan->pData = NULL;
+    Aig_ManStop( pMan );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarClau( Abc_Ntk_t * pNtk, int nFrames, int nPref, int nClauses, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRefs, int fTarget, int fVerbose, int fVeryVerbose )
+{
+    extern int Fra_Clau( Aig_Man_t * pMan, int nIters, int fVerbose, int fVeryVerbose );
+    extern int Fra_Claus( Aig_Man_t * pAig, int nFrames, int nPref, int nClauses, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRefs, int fTarget, int fVerbose, int fVeryVerbose );
+    Aig_Man_t * pMan;
+    if ( fTarget && Abc_NtkPoNum(pNtk) != 1 )
+    {
+        Abc_Print( 1, "The number of outputs should be 1.\n" );
+        return 1;
+    }
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return 1;
+//    Aig_ManReduceLachesCount( pMan );
+    if ( pMan->vFlopNums )
+        Vec_IntFree( pMan->vFlopNums ); 
+    pMan->vFlopNums = NULL;
+
+//    Fra_Clau( pMan, nStepsMax, fVerbose, fVeryVerbose );
+    Fra_Claus( pMan, nFrames, nPref, nClauses, nLutSize, nLevels, nCutsMax, nBatches, fStepUp, fBmc, fRefs, fTarget, fVerbose, fVeryVerbose );
+    Aig_ManStop( pMan );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs targe enlargement.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarEnlarge( Abc_Ntk_t * pNtk, int nFrames, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+    pMan = Aig_ManFrames( pTemp = pMan, nFrames, 0, 1, 1, 1, NULL );
+    Aig_ManStop( pTemp );
+    pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs targe enlargement.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarTempor( Abc_Ntk_t * pNtk, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fUseTransSigs, int fVerbose, int fVeryVerbose )
+{
+    extern Aig_Man_t * Saig_ManTempor( Aig_Man_t * pAig, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fUseTransSigs, int fVerbose, int fVeryVerbose );
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+    pTemp = Saig_ManTempor( pMan, nFrames, TimeOut, nConfLimit, fUseBmc, fUseTransSigs, fVerbose, fVeryVerbose );
+    Aig_ManStop( pMan );
+    if ( pTemp == NULL )
+        return Abc_NtkDup( pNtk );
+    pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pTemp );
+    Aig_ManStop( pTemp );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs induction for property only.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarInduction( Abc_Ntk_t * pNtk, int nTimeOut, int nFramesMax, int nConfMax, int fUnique, int fUniqueAll, int fGetCex, int fVerbose, int fVeryVerbose )
+{ 
+    Aig_Man_t * pMan;
+    abctime clkTotal = Abc_Clock();
+    int RetValue;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return -1;
+    RetValue = Saig_ManInduction( pMan, nTimeOut, nFramesMax, nConfMax, fUnique, fUniqueAll, fGetCex, fVerbose, fVeryVerbose );
+    if ( RetValue == 1 )
+    {
+        Abc_Print( 1, "Networks are equivalent.   " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+    }
+    else if ( RetValue == 0 )
+    {
+        Abc_Print( 1, "Networks are NOT EQUIVALENT.   " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+    }
+    else
+    {
+        Abc_Print( 1, "Networks are UNDECIDED.   " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+    }
+    if ( fGetCex )
+    {
+        ABC_FREE( pNtk->pModel );
+        ABC_FREE( pNtk->pSeqModel );
+        pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL;
+    }
+    Aig_ManStop( pMan );
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Interplates two networks.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkInterOne( Abc_Ntk_t * pNtkOn, Abc_Ntk_t * pNtkOff, int fRelation, int fVerbose )
+{
+    extern Aig_Man_t * Aig_ManInter( Aig_Man_t * pManOn, Aig_Man_t * pManOff, int fRelation, int fVerbose );
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pManOn, * pManOff, * pManAig;
+    if ( Abc_NtkCoNum(pNtkOn) != 1 || Abc_NtkCoNum(pNtkOff) != 1 )
+    {
+        Abc_Print( 1, "Currently works only for single-output networks.\n" );
+        return NULL;
+    }
+    if ( Abc_NtkCiNum(pNtkOn) != Abc_NtkCiNum(pNtkOff) )
+    {
+        Abc_Print( 1, "The number of PIs should be the same.\n" );
+        return NULL;
+    }
+    // create internal AIGs
+    pManOn = Abc_NtkToDar( pNtkOn, 0, 0 );
+    if ( pManOn == NULL )
+        return NULL;
+    pManOff = Abc_NtkToDar( pNtkOff, 0, 0 );
+    if ( pManOff == NULL )
+        return NULL;
+    // derive the interpolant
+    pManAig = Aig_ManInter( pManOn, pManOff, fRelation, fVerbose );
+    if ( pManAig == NULL )
+    {
+        Abc_Print( 1, "Interpolant computation failed.\n" );
+        return NULL;
+    }
+    Aig_ManStop( pManOn );
+    Aig_ManStop( pManOff );
+    // for the relation, add an extra input
+    if ( fRelation )
+    {
+        Abc_Obj_t * pObj;
+        pObj = Abc_NtkCreatePi( pNtkOff );
+        Abc_ObjAssignName( pObj, "New", NULL );
+    }
+    // create logic network
+    pNtkAig = Abc_NtkFromDar( pNtkOff, pManAig );
+    Aig_ManStop( pManAig );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fast interpolation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkInterFast( Abc_Ntk_t * pNtkOn, Abc_Ntk_t * pNtkOff, int fVerbose )
+{
+    extern void Aig_ManInterFast( Aig_Man_t * pManOn, Aig_Man_t * pManOff, int fVerbose );
+    Aig_Man_t * pManOn, * pManOff;
+    // create internal AIGs
+    pManOn = Abc_NtkToDar( pNtkOn, 0, 0 );
+    if ( pManOn == NULL )
+        return;
+    pManOff = Abc_NtkToDar( pNtkOff, 0, 0 );
+    if ( pManOff == NULL )
+        return;
+    Aig_ManInterFast( pManOn, pManOff, fVerbose );
+    Aig_ManStop( pManOn );
+    Aig_ManStop( pManOff );
+}
+
+abctime timeCnf;
+abctime timeSat;
+abctime timeInt;
+
+/**Function*************************************************************
+
+  Synopsis    [Interplates two networks.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkInter( Abc_Ntk_t * pNtkOn, Abc_Ntk_t * pNtkOff, int fRelation, int fVerbose )
+{
+    Abc_Ntk_t * pNtkOn1, * pNtkOff1, * pNtkInter1, * pNtkInter;
+    Abc_Obj_t * pObj;
+    int i; //, clk = Abc_Clock();
+    if ( Abc_NtkCoNum(pNtkOn) != Abc_NtkCoNum(pNtkOff) )
+    {
+        Abc_Print( 1, "Currently works only for networks with equal number of POs.\n" );
+        return NULL;
+    }
+    // compute the fast interpolation time
+//    Abc_NtkInterFast( pNtkOn, pNtkOff, fVerbose );
+    // consider the case of one output
+    if ( Abc_NtkCoNum(pNtkOn) == 1 )
+        return Abc_NtkInterOne( pNtkOn, pNtkOff, fRelation, fVerbose );
+    // start the new network
+    pNtkInter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    pNtkInter->pName = Extra_UtilStrsav(pNtkOn->pName);
+    Abc_NtkForEachPi( pNtkOn, pObj, i )
+        Abc_NtkDupObj( pNtkInter, pObj, 1 );
+    // process each POs separately
+timeCnf = 0;
+timeSat = 0;
+timeInt = 0;
+    Abc_NtkForEachCo( pNtkOn, pObj, i )
+    {
+        pNtkOn1 = Abc_NtkCreateCone( pNtkOn, Abc_ObjFanin0(pObj), Abc_ObjName(pObj), 1 );
+        if ( Abc_ObjFaninC0(pObj) )
+            Abc_ObjXorFaninC( Abc_NtkPo(pNtkOn1, 0), 0 );
+
+        pObj   = Abc_NtkCo(pNtkOff, i);
+        pNtkOff1 = Abc_NtkCreateCone( pNtkOff, Abc_ObjFanin0(pObj), Abc_ObjName(pObj), 1 );
+        if ( Abc_ObjFaninC0(pObj) )
+            Abc_ObjXorFaninC( Abc_NtkPo(pNtkOff1, 0), 0 );
+
+        if ( Abc_NtkNodeNum(pNtkOn1) == 0 )
+            pNtkInter1 = Abc_NtkDup( pNtkOn1 );
+        else if ( Abc_NtkNodeNum(pNtkOff1) == 0 )
+        {
+            pNtkInter1 = Abc_NtkDup( pNtkOff1 );
+            Abc_ObjXorFaninC( Abc_NtkPo(pNtkInter1, 0), 0 );
+        }
+        else
+            pNtkInter1 = Abc_NtkInterOne( pNtkOn1, pNtkOff1, 0, fVerbose );
+        if ( pNtkInter1 )
+        {
+            Abc_NtkAppend( pNtkInter, pNtkInter1, 1 );
+            Abc_NtkDelete( pNtkInter1 );
+        }
+
+        Abc_NtkDelete( pNtkOn1 );
+        Abc_NtkDelete( pNtkOff1 );
+    }
+//    ABC_PRT( "CNF", timeCnf );
+//    ABC_PRT( "SAT", timeSat );
+//    ABC_PRT( "Int", timeInt );
+//    ABC_PRT( "Slow interpolation time", Abc_Clock() - clk );
+
+    // return the network
+    if ( !Abc_NtkCheck( pNtkInter ) )
+        Abc_Print( 1, "Abc_NtkAttachBottom(): Network check has failed.\n" );
+    return pNtkInter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintSccs( Abc_Ntk_t * pNtk, int fVerbose )
+{
+//    extern Vec_Ptr_t * Aig_ManRegPartitionLinear( Aig_Man_t * pAig, int nPartSize );
+    Aig_Man_t * pMan;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return;
+    Aig_ManComputeSccs( pMan );
+//    Aig_ManRegPartitionLinear( pMan, 1000 );
+    Aig_ManStop( pMan );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarPrintCone( Abc_Ntk_t * pNtk )
+{
+    extern void Saig_ManPrintCones( Aig_Man_t * pAig );
+    Aig_Man_t * pMan;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return 0;
+    assert( Aig_ManRegNum(pMan) > 0 );
+    Saig_ManPrintCones( pMan );
+    Aig_ManStop( pMan );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkBalanceExor( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose )
+{
+    extern void Dar_BalancePrintStats( Aig_Man_t * p );
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;//, * pTemp2;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // derive AIG with EXORs
+    pMan = Abc_NtkToDar( pNtk, 1, 0 );
+    if ( pMan == NULL )
+        return NULL;
+//    Aig_ManPrintStats( pMan );
+    if ( fVerbose )
+        Dar_BalancePrintStats( pMan );
+    // perform balancing
+    pTemp = Dar_ManBalance( pMan, fUpdateLevel );
+//    Aig_ManPrintStats( pTemp );
+    // create logic network
+    pNtkAig = Abc_NtkFromDar( pNtk, pTemp );
+    Aig_ManStop( pTemp );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs phase abstraction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkPhaseAbstract( Abc_Ntk_t * pNtk, int nFrames, int nPref, int fIgnore, int fPrint, int fVerbose )
+{
+    extern Aig_Man_t * Saig_ManPhaseAbstract( Aig_Man_t * p, Vec_Int_t * vInits, int nFrames, int nPref, int fIgnore, int fPrint, int fVerbose );
+    Vec_Int_t * vInits;
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+    vInits = Abc_NtkGetLatchValues(pNtk);
+    pMan = Saig_ManPhaseAbstract( pTemp = pMan, vInits, nFrames, nPref, fIgnore, fPrint, fVerbose );
+    Vec_IntFree( vInits );
+    Aig_ManStop( pTemp );
+    if ( pMan == NULL )
+        return NULL;
+    pNtkAig = Abc_NtkFromAigPhase( pMan );
+//    pNtkAig->pName = Extra_UtilStrsav(pNtk->pName);
+//    pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs phase abstraction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkPhaseFrameNum( Abc_Ntk_t * pNtk )
+{
+    extern int Saig_ManPhaseFrameNum( Aig_Man_t * p, Vec_Int_t * vInits );
+    Vec_Int_t * vInits;
+    Aig_Man_t * pMan;
+    int nFrames;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return 1;
+    vInits = Abc_NtkGetLatchValues(pNtk);
+    nFrames = Saig_ManPhaseFrameNum( pMan, vInits );
+    Vec_IntFree( vInits );
+    Aig_ManStop( pMan );
+    return nFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs phase abstraction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarSynchOne( Abc_Ntk_t * pNtk, int nWords, int fVerbose )
+{
+    extern Aig_Man_t * Saig_SynchSequenceApply( Aig_Man_t * pAig, int nWords, int fVerbose );
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+    pMan = Saig_SynchSequenceApply( pTemp = pMan, nWords, fVerbose );
+    Aig_ManStop( pTemp );
+    if ( pMan == NULL )
+        return NULL;
+    pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs phase abstraction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarSynch( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nWords, int fVerbose )
+{
+    extern Aig_Man_t * Saig_Synchronize( Aig_Man_t * pAig1, Aig_Man_t * pAig2, int nWords, int fVerbose );
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan1, * pMan2, * pMan;
+    pMan1 = Abc_NtkToDar( pNtk1, 0, 1 );
+    if ( pMan1 == NULL )
+        return NULL;
+    pMan2 = Abc_NtkToDar( pNtk2, 0, 1 );
+    if ( pMan2 == NULL )
+    {
+        Aig_ManStop( pMan1 );
+        return NULL;
+    }
+    pMan = Saig_Synchronize( pMan1, pMan2, nWords, fVerbose );
+    Aig_ManStop( pMan1 );
+    Aig_ManStop( pMan2 );
+    if ( pMan == NULL )
+        return NULL;
+    pNtkAig = Abc_NtkFromAigPhase( pMan );
+//    pNtkAig->pName = Extra_UtilStrsav("miter");
+//    pNtkAig->pSpec = NULL;
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs phase abstraction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarClockGate( Abc_Ntk_t * pNtk, Abc_Ntk_t * pCare, Cgt_Par_t * pPars )
+{
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan1, * pMan2 = NULL, * pMan;
+    pMan1 = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan1 == NULL )
+        return NULL;
+    if ( pCare )
+    {
+        pMan2 = Abc_NtkToDar( pCare, 0, 0 );
+        if ( pMan2 == NULL )
+        {
+            Aig_ManStop( pMan1 );
+            return NULL;
+        }
+    }
+    pMan = Cgt_ClockGating( pMan1, pMan2, pPars );
+    Aig_ManStop( pMan1 );
+    if ( pMan2 )
+        Aig_ManStop( pMan2 );
+    if ( pMan == NULL )
+        return NULL;
+    pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs phase abstraction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarExtWin( Abc_Ntk_t * pNtk, int nObjId, int nDist, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan1, * pMan;
+    Aig_Obj_t * pObj;
+    pMan1 = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan1 == NULL )
+        return NULL;
+    if ( nObjId == -1 )
+    {
+        pObj = Saig_ManFindPivot( pMan1 );
+        Abc_Print( 1, "Selected object %d as a window pivot.\n", pObj->Id );
+    }
+    else
+    {
+        if ( nObjId >= Aig_ManObjNumMax(pMan1) )
+        {
+            Aig_ManStop( pMan1 );
+            Abc_Print( 1, "The ID is too large.\n" );
+            return NULL;
+        }
+        pObj = Aig_ManObj( pMan1, nObjId );
+        if ( pObj == NULL )
+        {
+            Aig_ManStop( pMan1 );
+            Abc_Print( 1, "Object with ID %d does not exist.\n", nObjId );
+            return NULL;
+        }
+        if ( !Saig_ObjIsLo(pMan1, pObj) && !Aig_ObjIsNode(pObj) )
+        {
+            Aig_ManStop( pMan1 );
+            Abc_Print( 1, "Object with ID %d is not a node or reg output.\n", nObjId );
+            return NULL;
+        }
+    }
+    pMan = Saig_ManWindowExtract( pMan1, pObj, nDist );
+    Aig_ManStop( pMan1 );
+    if ( pMan == NULL )
+        return NULL;
+    pNtkAig = Abc_NtkFromAigPhase( pMan );
+    pNtkAig->pName = Extra_UtilStrsav(pNtk->pName);
+    pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs phase abstraction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarInsWin( Abc_Ntk_t * pNtk, Abc_Ntk_t * pCare, int nObjId, int nDist, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan1, * pMan2 = NULL, * pMan;
+    Aig_Obj_t * pObj;
+    pMan1 = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan1 == NULL )
+        return NULL;
+    if ( nObjId == -1 )
+    {
+        pObj = Saig_ManFindPivot( pMan1 );
+        Abc_Print( 1, "Selected object %d as a window pivot.\n", pObj->Id );
+    }
+    else
+    {
+        if ( nObjId >= Aig_ManObjNumMax(pMan1) )
+        {
+            Aig_ManStop( pMan1 );
+            Abc_Print( 1, "The ID is too large.\n" );
+            return NULL;
+        }
+        pObj = Aig_ManObj( pMan1, nObjId );
+        if ( pObj == NULL )
+        {
+            Aig_ManStop( pMan1 );
+            Abc_Print( 1, "Object with ID %d does not exist.\n", nObjId );
+            return NULL;
+        }
+        if ( !Saig_ObjIsLo(pMan1, pObj) && !Aig_ObjIsNode(pObj) )
+        {
+            Aig_ManStop( pMan1 );
+            Abc_Print( 1, "Object with ID %d is not a node or reg output.\n", nObjId );
+            return NULL;
+        }
+    }
+    if ( pCare )
+    {
+        pMan2 = Abc_NtkToDar( pCare, 0, 0 );
+        if ( pMan2 == NULL )
+        {
+            Aig_ManStop( pMan1 );
+            return NULL;
+        }
+    }
+    pMan = Saig_ManWindowInsert( pMan1, pObj, nDist, pMan2 );
+    Aig_ManStop( pMan1 );
+    if ( pMan2 )
+        Aig_ManStop( pMan2 );
+    if ( pMan == NULL )
+        return NULL;
+    pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs phase abstraction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarFrames( Abc_Ntk_t * pNtk, int nPrefix, int nFrames, int fInit, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+    pMan = Saig_ManTimeframeSimplify( pTemp = pMan, nPrefix, nFrames, fInit, fVerbose );
+    Aig_ManStop( pTemp );
+    if ( pMan == NULL )
+        return NULL;
+    pNtkAig = Abc_NtkFromAigPhase( pMan );
+    pNtkAig->pName = Extra_UtilStrsav(pNtk->pName);
+    pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs phase abstraction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarCleanupAig( Abc_Ntk_t * pNtk, int fCleanupPis, int fCleanupPos, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+    if ( fCleanupPis )
+    {
+        int Temp = Aig_ManCiCleanup( pMan );
+        if ( fVerbose )
+            Abc_Print( 1, "Cleanup removed %d primary inputs without fanout.\n", Temp );                                                                     
+    }
+    if ( fCleanupPos )
+    {
+        int Temp = Aig_ManCoCleanup( pMan );
+        if ( fVerbose )
+            Abc_Print( 1, "Cleanup removed %d primary outputs driven by const-0.\n", Temp );                                                                     
+    }
+    pNtkAig = Abc_NtkFromAigPhase( pMan );
+    pNtkAig->pName = Extra_UtilStrsav(pNtk->pName);
+    pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD-based reachability analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDarReach( Abc_Ntk_t * pNtk, Saig_ParBbr_t * pPars )
+{
+    Aig_Man_t * pMan;
+    int RetValue;
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return -1;
+    RetValue = Aig_ManVerifyUsingBdds( pMan, pPars );
+    ABC_FREE( pNtk->pModel );
+    ABC_FREE( pNtk->pSeqModel );
+    pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL;
+    Aig_ManStop( pMan );
+    return RetValue;
+}
+
+ABC_NAMESPACE_IMPL_END
+
+#include "map/amap/amap.h"
+#include "map/mio/mio.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Amap_ManProduceNetwork( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMapping )
+{
+//    extern void * Abc_FrameReadLibGen();
+    Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
+    Amap_Out_t * pRes;
+    Vec_Ptr_t * vNodesNew;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pNodeNew, * pFaninNew;
+    int i, k, iPis, iPos, nDupGates;
+    // make sure gates exist in the current library
+    Vec_PtrForEachEntry( Amap_Out_t *, vMapping, pRes, i )
+        if ( pRes->pName && Mio_LibraryReadGateByName( pLib, pRes->pName, NULL ) == NULL )
+        {
+            Abc_Print( 1, "Current library does not contain gate \"%s\".\n", pRes->pName );
+            return NULL;
+        }
+    // create the network
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_MAP );
+    pNtkNew->pManFunc = pLib;
+    iPis = iPos = 0;
+    vNodesNew = Vec_PtrAlloc( Vec_PtrSize(vMapping) );
+    Vec_PtrForEachEntry( Amap_Out_t *, vMapping, pRes, i )
+    {
+        if ( pRes->Type == -1 )
+            pNodeNew = Abc_NtkCi( pNtkNew, iPis++ );
+        else if ( pRes->Type == 1 )
+            pNodeNew = Abc_NtkCo( pNtkNew, iPos++ );
+        else
+        {
+            pNodeNew = Abc_NtkCreateNode( pNtkNew );
+            pNodeNew->pData = Mio_LibraryReadGateByName( pLib, pRes->pName, NULL );
+        }
+        for ( k = 0; k < pRes->nFans; k++ )
+        {
+            pFaninNew = (Abc_Obj_t *)Vec_PtrEntry( vNodesNew, pRes->pFans[k] );
+            Abc_ObjAddFanin( pNodeNew, pFaninNew );
+        }
+        Vec_PtrPush( vNodesNew, pNodeNew );
+    }
+    Vec_PtrFree( vNodesNew );
+    assert( iPis == Abc_NtkCiNum(pNtkNew) );
+    assert( iPos == Abc_NtkCoNum(pNtkNew) );
+    // decouple the PO driver nodes to reduce the number of levels
+    nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+//    if ( nDupGates && Map_ManReadVerbose(pMan) )
+//        Abc_Print( 1, "Duplicated %d gates to decouple the CO drivers.\n", nDupGates );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarAmap( Abc_Ntk_t * pNtk, Amap_Par_t * pPars )
+{
+    extern Vec_Ptr_t * Amap_ManTest( Aig_Man_t * pAig, Amap_Par_t * pPars );
+    Vec_Ptr_t * vMapping;
+    Abc_Ntk_t * pNtkAig = NULL;
+    Aig_Man_t * pMan;
+    Aig_MmFlex_t * pMem;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    // convert to the AIG manager
+    pMan = Abc_NtkToDarChoices( pNtk );
+    if ( pMan == NULL )
+        return NULL;
+
+    // perform computation
+    vMapping = Amap_ManTest( pMan, pPars );
+    Aig_ManStop( pMan );
+    if ( vMapping == NULL )
+        return NULL;
+    pMem = (Aig_MmFlex_t *)Vec_PtrPop( vMapping );
+    pNtkAig = Amap_ManProduceNetwork( pNtk, vMapping );
+    Aig_MmFlexStop( pMem, 0 );
+    Vec_PtrFree( vMapping );
+
+    // make sure everything is okay
+    if ( pNtkAig && !Abc_NtkCheck( pNtkAig ) )
+    {
+        Abc_Print( 1, "Abc_NtkDar: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkAig );
+        return NULL;
+    }
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD-based reachability analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDarConstr( Abc_Ntk_t * pNtk, int nFrames, int nConfs, int nProps, int fStruct, int fOldAlgo, int fVerbose )
+{
+    Aig_Man_t * pMan;//, * pMan2;//, * pTemp;
+    assert( Abc_NtkIsStrash(pNtk) );
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return;
+    if ( fStruct )
+        Saig_ManDetectConstrTest( pMan );
+    else
+        Saig_ManDetectConstrFuncTest( pMan, nFrames, nConfs, nProps, fOldAlgo, fVerbose );
+    Aig_ManStop( pMan );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD-based reachability analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarOutdec( Abc_Ntk_t * pNtk, int nLits, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    assert( Abc_NtkIsStrash(pNtk) );
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+    pMan = Saig_ManDecPropertyOutput( pTemp = pMan, nLits, fVerbose );
+    Aig_ManStop( pTemp );
+    if ( pMan == NULL )
+        return NULL;
+    pNtkAig = Abc_NtkFromAigPhase( pMan );
+    pNtkAig->pName = Extra_UtilStrsav(pMan->pName);
+    pNtkAig->pSpec = Extra_UtilStrsav(pMan->pSpec);
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD-based reachability analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarUnfold( Abc_Ntk_t * pNtk, int nFrames, int nConfs, int nProps, int fStruct, int fOldAlgo, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    assert( Abc_NtkIsStrash(pNtk) );
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+    if ( fStruct )
+        pMan = Saig_ManDupUnfoldConstrs( pTemp = pMan );
+    else
+        pMan = Saig_ManDupUnfoldConstrsFunc( pTemp = pMan, nFrames, nConfs, nProps, fOldAlgo, fVerbose );
+    Aig_ManStop( pTemp );
+    if ( pMan == NULL )
+        return NULL;
+    pNtkAig = Abc_NtkFromAigPhase( pMan );
+    pNtkAig->pName = Extra_UtilStrsav(pMan->pName);
+    pNtkAig->pSpec = Extra_UtilStrsav(pMan->pSpec);
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD-based reachability analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarFold( Abc_Ntk_t * pNtk, int fCompl, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    assert( Abc_NtkIsStrash(pNtk) );
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+    pMan = Saig_ManDupFoldConstrsFunc( pTemp = pMan, fCompl, fVerbose );
+    Aig_ManStop( pTemp );
+    pNtkAig = Abc_NtkFromAigPhase( pMan );
+    pNtkAig->pName = Extra_UtilStrsav(pMan->pName);
+    pNtkAig->pSpec = Extra_UtilStrsav(pMan->pSpec);
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD-based reachability analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDarConstrProfile( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    extern int Ssw_ManProfileConstraints( Aig_Man_t * p, int nWords, int nFrames, int fVerbose );
+    extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne );
+    Aig_Man_t * pMan;
+//    Vec_Int_t * vProbOne;
+//    Aig_Obj_t * pObj;
+//    int i, Entry;
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( Abc_NtkConstrNum(pNtk) );
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return;
+    // value in the init state
+//    Abc_AigSetNodePhases( pNtk );
+/*
+    // derive probabilities
+    vProbOne = Saig_ManComputeSwitchProbs( pMan, 48, 16, 1 );
+    // iterate over the constraint outputs
+    Saig_ManForEachPo( pMan, pObj, i )
+    {
+        Entry = Vec_IntEntry( vProbOne, Aig_ObjId(pObj) );
+        if ( i < Saig_ManPoNum(pMan) - Saig_ManConstrNum(pMan) )
+            Abc_Print( 1, "Primary output :  ", i );
+        else
+            Abc_Print( 1, "Constraint %3d :  ", i-(Saig_ManPoNum(pMan) - Saig_ManConstrNum(pMan)) );
+        Abc_Print( 1, "ProbOne = %f  ", Abc_Int2Float(Entry) );
+        Abc_Print( 1, "AllZeroValue = %d ", Aig_ObjPhase(pObj) );
+        Abc_Print( 1, "\n" );
+    }
+*/
+    // double-check
+    Ssw_ManProfileConstraints( pMan, 16, 64, 1 );
+    Abc_Print( 1, "TwoFrameSatValue = %d.\n", Ssw_ManSetConstrPhases(pMan, 2, NULL) );
+    // clean up
+//    Vec_IntFree( vProbOne );
+    Aig_ManStop( pMan );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD-based reachability analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDarTest( Abc_Ntk_t * pNtk, int Num )
+{
+//    extern void Saig_ManDetectConstr( Aig_Man_t * p );
+//    extern void Saig_ManDetectConstrFuncTest( Aig_Man_t * p );
+//    extern void Saig_ManFoldConstrTest( Aig_Man_t * pAig );
+    extern void Llb_ManComputeDomsTest( Aig_Man_t * pAig, int Num );
+
+
+
+//    extern void Fsim_ManTest( Aig_Man_t * pAig );
+    extern Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter );
+//    Vec_Int_t * vPairs;
+    Aig_Man_t * pMan;//, * pMan2;//, * pTemp;
+    assert( Abc_NtkIsStrash(pNtk) );
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return;
+/*
+Aig_ManSetRegNum( pMan, pMan->nRegs );
+Aig_ManPrintStats( pMan );
+Saig_ManDumpBlif( pMan, "_temp_.blif" );
+Aig_ManStop( pMan );
+pMan = Saig_ManReadBlif( "_temp_.blif" );
+Aig_ManPrintStats( pMan );
+*/
+/*
+    Aig_ManSetRegNum( pMan, pMan->nRegs );
+    pTemp = Ssw_SignalCorrespondeceTestPairs( pMan );
+    Aig_ManStop( pTemp );
+*/
+
+/*
+//    Ssw_SecSpecialMiter( pMan, NULL, 2, 1 );
+    pMan2 = Aig_ManDupSimple(pMan);
+    vPairs = Saig_StrSimPerformMatching( pMan, pMan2, 0, 1, NULL );
+    Vec_IntFree( vPairs );
+    Aig_ManStop( pMan );
+    Aig_ManStop( pMan2 );
+*/
+//    Ioa_WriteAigerBufferTest( pMan, "test.aig", 0, 0 );
+//    Saig_ManFoldConstrTest( pMan );
+    {
+    extern void Saig_ManBmcSectionsTest( Aig_Man_t * p );
+    extern void Saig_ManBmcTerSimTest( Aig_Man_t * p );
+    extern void Saig_ManBmcSupergateTest( Aig_Man_t * p );
+    extern void Saig_ManBmcMappingTest( Aig_Man_t * p );
+//    Saig_ManBmcSectionsTest( pMan );
+//    Saig_ManBmcTerSimTest( pMan );
+//    Saig_ManBmcSupergateTest( pMan );
+//    Saig_ManBmcMappingTest( pMan );
+    }
+
+    {
+//        void Pdr_ManEquivClasses( Aig_Man_t * pMan );
+//        Pdr_ManEquivClasses( pMan );
+    }
+
+//    Llb_ManComputeDomsTest( pMan, Num );
+    {
+        extern void Llb_ManMinCutTest( Aig_Man_t * pMan, int Num );
+        extern void Llb_BddStructAnalysis( Aig_Man_t * pMan );
+        extern void Llb_NonlinExperiment( Aig_Man_t * pAig, int Num );
+//        Llb_BddStructAnalysis( pMan );
+        Llb_ManMinCutTest( pMan, Num );
+//        Llb_NonlinExperiment( pMan, Num );
+    }
+
+//    Saig_MvManSimulate( pMan, 1 );
+//    Saig_ManDetectConstr( pMan );
+//    Saig_ManDetectConstrFuncTest( pMan );
+
+//    Fsim_ManTest( pMan );
+    Aig_ManStop( pMan );
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD-based reachability analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarTestNtk( Abc_Ntk_t * pNtk )
+{
+//    extern Aig_Man_t * Saig_ManDualRail( Aig_Man_t * p, int fMiter );
+
+/*
+    extern Aig_Man_t * Ssw_SignalCorrespondeceTestPairs( Aig_Man_t * pAig );
+
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    assert( Abc_NtkIsStrash(pNtk) );
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+
+    Aig_ManSetRegNum( pMan, pMan->nRegs );
+    pMan = Ssw_SignalCorrespondeceTestPairs( pTemp = pMan );
+    Aig_ManStop( pTemp );
+    if ( pMan == NULL )
+        return NULL;
+
+    pNtkAig = Abc_NtkFromAigPhase( pMan );
+    pNtkAig->pName = Extra_UtilStrsav(pNtk->pName);
+    pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+    Aig_ManStop( pMan );
+    return pNtkAig;
+*/
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan;//, * pTemp;
+    assert( Abc_NtkIsStrash(pNtk) );
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+
+/*
+    Aig_ManSetRegNum( pMan, pMan->nRegs );
+    pMan = Saig_ManDualRail( pTemp = pMan, 1 );
+    Aig_ManStop( pTemp );
+    if ( pMan == NULL )
+        return NULL;
+
+    pNtkAig = Abc_NtkFromAigPhase( pMan );
+    pNtkAig->pName = Extra_UtilStrsav(pNtk->pName);
+    pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+    Aig_ManStop( pMan );
+*/
+
+    pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+    Aig_ManStop( pMan );
+
+    return pNtkAig;
+
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "abcDarUnfold2.c"
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcDarUnfold2.c b/abc-build/src/base/abci/abcDarUnfold2.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcDarUnfold2.c
@@ -0,0 +1,69 @@
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD-based reachability analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarFold2( Abc_Ntk_t * pNtk, int fCompl, int fVerbose , int);
+Abc_Ntk_t * Abc_NtkDarUnfold2( Abc_Ntk_t * pNtk, int nFrames, int nConfs, int nProps, int fStruct, int fOldAlgo, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    int typeII_cnt = 0;
+    assert( Abc_NtkIsStrash(pNtk) );
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+    if ( fStruct ){
+      assert(0);//pMan = Saig_ManDupUnfoldConstrs( pTemp = pMan );
+    }else
+      pMan = Saig_ManDupUnfoldConstrsFunc2( pTemp = pMan, nFrames, nConfs, nProps, fOldAlgo, fVerbose , &typeII_cnt);
+    Aig_ManStop( pTemp );
+    if ( pMan == NULL )
+        return NULL;
+    //    typeII_cnt = pMan->nConstrsTypeII;
+    pNtkAig = Abc_NtkFromAigPhase( pMan );
+    pNtkAig->pName = Extra_UtilStrsav(pMan->pName);
+    pNtkAig->pSpec = Extra_UtilStrsav(pMan->pSpec);
+    Aig_ManStop( pMan );
+
+    return pNtkAig;//Abc_NtkDarFold2(pNtkAig, 0, fVerbose, typeII_cnt);
+    
+    //return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD-based reachability analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarFold2( Abc_Ntk_t * pNtk, int fCompl, int fVerbose
+                             , int typeII_cnt
+                             )
+{
+    Abc_Ntk_t * pNtkAig;
+    Aig_Man_t * pMan, * pTemp;
+    assert( Abc_NtkIsStrash(pNtk) );
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan == NULL )
+        return NULL;
+    pMan = Saig_ManDupFoldConstrsFunc2( pTemp = pMan, fCompl, fVerbose, typeII_cnt );
+    Aig_ManStop( pTemp );
+    pNtkAig = Abc_NtkFromAigPhase( pMan );
+    pNtkAig->pName = Extra_UtilStrsav(pMan->pName);
+    pNtkAig->pSpec = Extra_UtilStrsav(pMan->pSpec);
+    Aig_ManStop( pMan );
+    return pNtkAig;
+}
+
diff --git a/abc-build/src/base/abci/abcDebug.c b/abc-build/src/base/abci/abcDebug.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcDebug.c
@@ -0,0 +1,213 @@
+/**CFile****************************************************************
+
+  FileName    [abcDebug.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Automated debugging procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcDebug.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/io/ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_NtkCountFaninsTotal( Abc_Ntk_t * pNtk );
+static Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtk, int ObjNum, int fConst1 );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Takes a network and a procedure to test.]
+
+  Description [The network demonstrates the bug in the procedure.
+  Procedure should return 1 if the bug is demonstrated.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkAutoDebug( Abc_Ntk_t * pNtk, int (*pFuncError) (Abc_Ntk_t *) )
+{
+    Abc_Ntk_t * pNtkMod;
+    char * pFileName = "bug_found.blif";
+    int i, nSteps, nIter, ModNum, RandNum = 1;
+    abctime clk, clkTotal = Abc_Clock();
+    assert( Abc_NtkIsLogic(pNtk) );
+    srand( 0x123123 );
+    // create internal copy of the network
+    pNtk = Abc_NtkDup(pNtk);
+    if ( !(*pFuncError)( pNtk ) )
+    {
+        printf( "The original network does not cause the bug. Quitting.\n" );
+        Abc_NtkDelete( pNtk );
+        return;
+    }
+    // perform incremental modifications
+    for ( nIter = 0; ; nIter++ )
+    {
+        clk = Abc_Clock();
+        // count how many ways of modifying the network exists
+        nSteps = 2 * Abc_NtkCountFaninsTotal(pNtk);
+        // try modifying the network as many times
+        RandNum ^= rand();
+        for ( i = 0; i < nSteps; i++ )
+        {
+            // get the shifted number of bug
+            ModNum = (i + RandNum) % nSteps;
+            // get the modified network
+            pNtkMod = Abc_NtkAutoDebugModify( pNtk, ModNum/2, ModNum%2 );
+            // write the network
+            Io_WriteBlifLogic( pNtk, "bug_temp.blif", 1 );   
+            // check if the bug is still there
+            if ( (*pFuncError)( pNtkMod ) ) // bug is still there
+            {
+                Abc_NtkDelete( pNtk );
+                pNtk = pNtkMod;
+                break;
+            }
+            else // no bug
+                Abc_NtkDelete( pNtkMod );
+        }
+        printf( "Iter %6d : Latches = %6d. Nodes = %6d. Steps = %6d. Error step = %3d.  ", 
+            nIter, Abc_NtkLatchNum(pNtk), Abc_NtkNodeNum(pNtk), nSteps, i );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+        if ( i == nSteps ) // could not modify it while preserving the bug
+            break;
+    }
+    // write out the final network
+    Io_WriteBlifLogic( pNtk, pFileName, 1 );
+    printf( "Final network written into file \"%s\". ", pFileName );
+    ABC_PRT( "Total time", Abc_Clock() - clkTotal );
+    Abc_NtkDelete( pNtk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the total number of fanins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCountFaninsTotal( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k, Counter = 0;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+        {
+            if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) )
+                continue;
+            if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 )
+                continue;
+            if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) )
+                continue;
+            Counter++;
+        }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the node and fanin to be modified.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkFindGivenFanin( Abc_Ntk_t * pNtk, int Step, Abc_Obj_t ** ppObj, Abc_Obj_t ** ppFanin )
+{
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k, Counter = 0;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+        {
+            if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) )
+                continue;
+            if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 )
+                continue;
+            if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) )
+                continue;
+            if ( Counter++ == Step )
+            {
+                *ppObj   = pObj;
+                *ppFanin = pFanin;
+                return 1;
+            }
+        }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform modification with the given number.]
+
+  Description [Modification consists of replacing the node by a constant.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtkInit, int Step, int fConst1 )
+{
+    extern void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose );
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pObj, * pFanin, * pConst;
+    // copy the network
+    pNtk = Abc_NtkDup( pNtkInit );
+    assert( Abc_NtkNodeNum(pNtk) == Abc_NtkNodeNum(pNtkInit) );
+    // find the object number
+    Abc_NtkFindGivenFanin( pNtk, Step, &pObj, &pFanin );
+    // consider special case 
+    if ( Abc_ObjIsPo(pObj) && Abc_NodeIsConst(pFanin) )
+    {
+        Abc_NtkDeleteAll_rec( pObj );
+        return pNtk;
+    }
+    // plug in a constant node
+    pConst = fConst1? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk);
+    Abc_ObjTransferFanout( pFanin, pConst );
+    Abc_NtkDeleteAll_rec( pFanin );
+
+    Abc_NtkSweep( pNtk, 0 );
+    Abc_NtkCleanupSeq( pNtk, 0, 0, 0 );
+    Abc_NtkToSop( pNtk, 0 );
+    Abc_NtkCycleInitStateSop( pNtk, 50, 0 );
+    return pNtk;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcDec.c b/abc-build/src/base/abci/abcDec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcDec.c
@@ -0,0 +1,641 @@
+/**CFile****************************************************************
+
+  FileName    [abcDec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Procedures for testing and comparing decomposition algorithms.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "misc/extra/extra.h"
+#include "misc/vec/vec.h"
+
+#include "bool/bdc/bdc.h"
+#include "bool/dec/dec.h"
+#include "bool/kit/kit.h"
+#include "opt/dau/dau.h"
+#include "misc/util/utilTruth.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+// decomposition type
+// 0 - none
+// 1 - factoring
+// 2 - bi-decomposition
+// 3 - DSD
+
+// data-structure to store a bunch of truth tables
+typedef struct Abc_TtStore_t_  Abc_TtStore_t;
+struct Abc_TtStore_t_ 
+{
+    int               nVars;
+    int               nWords;
+    int               nFuncs;
+    word **           pFuncs;
+};
+
+// read/write/flip i-th bit of a bit string table:
+static inline int     Abc_TruthGetBit( word * p, int i )         { return (int)(p[i>>6] >> (i & 63)) & 1;        }
+static inline void    Abc_TruthSetBit( word * p, int i )         { p[i>>6] |= (((word)1)<<(i & 63));             }
+static inline void    Abc_TruthXorBit( word * p, int i )         { p[i>>6] ^= (((word)1)<<(i & 63));             }
+
+// read/write k-th digit d of a hexadecimal number:
+static inline int     Abc_TruthGetHex( word * p, int k )         { return (int)(p[k>>4] >> ((k<<2) & 63)) & 15;  }
+static inline void    Abc_TruthSetHex( word * p, int k, int d )  { p[k>>4] |= (((word)d)<<((k<<2) & 63));        }
+static inline void    Abc_TruthXorHex( word * p, int k, int d )  { p[k>>4] ^= (((word)d)<<((k<<2) & 63));        }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+// read one hex character
+static inline int  Abc_TruthReadHexDigit( char HexChar )
+{
+    if ( HexChar >= '0' && HexChar <= '9' )
+        return HexChar - '0';
+    if ( HexChar >= 'A' && HexChar <= 'F' )
+        return HexChar - 'A' + 10;
+    if ( HexChar >= 'a' && HexChar <= 'f' )
+        return HexChar - 'a' + 10;
+    assert( 0 ); // not a hexadecimal symbol
+    return -1; // return value which makes no sense
+}
+
+// write one hex character
+static inline void Abc_TruthWriteHexDigit( FILE * pFile, int HexDigit )
+{
+    assert( HexDigit >= 0 && HexDigit < 16 );
+    if ( HexDigit < 10 )
+        fprintf( pFile, "%d", HexDigit );
+    else
+        fprintf( pFile, "%c", 'A' + HexDigit-10 );
+}
+
+// read one truth table in hexadecimal
+void Abc_TruthReadHex( word * pTruth, char * pString, int nVars )
+{
+    int nWords = (nVars < 7)? 1 : (1 << (nVars-6));
+    int k, Digit, nDigits = (nWords << 4);
+    char EndSymbol;
+    // skip the first 2 symbols if they are "0x"
+    if ( pString[0] == '0' && pString[1] == 'x' )
+        pString += 2;
+    // get the last symbol
+    EndSymbol = pString[nDigits];
+    // the end symbol of the TT (the one immediately following hex digits)
+    // should be one of the following: space, a new-line, or a zero-terminator
+    // (note that on Windows symbols '\r' can be inserted before each '\n')
+    assert( EndSymbol == ' ' || EndSymbol == '\n' || EndSymbol == '\r' || EndSymbol == '\0' );
+    // read hexadecimal digits in the reverse order
+    // (the last symbol in the string is the least significant digit)
+    for ( k = 0; k < nDigits; k++ )
+    {
+        Digit = Abc_TruthReadHexDigit( pString[nDigits - 1 - k] );
+        assert( Digit >= 0 && Digit < 16 );
+        Abc_TruthSetHex( pTruth, k, Digit );
+    }
+}
+
+// write one truth table in hexadecimal (do not add end-of-line!)
+void Abc_TruthWriteHex( FILE * pFile, word * pTruth, int nVars )
+{
+    int nDigits, Digit, k;
+    nDigits = (1 << (nVars-2));
+    for ( k = 0; k < nDigits; k++ )
+    {
+        Digit = Abc_TruthGetHex( pTruth, k );
+        assert( Digit >= 0 && Digit < 16 );
+        Abc_TruthWriteHexDigit( pFile, Digit );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocate/Deallocate storage for truth tables..]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_TtStore_t * Abc_TruthStoreAlloc( int nVars, int nFuncs )
+{
+    Abc_TtStore_t * p;
+    int i;
+    p = (Abc_TtStore_t *)malloc( sizeof(Abc_TtStore_t) );
+    p->nVars  =  nVars;
+    p->nWords = (nVars < 7) ? 1 : (1 << (nVars-6));
+    p->nFuncs =  nFuncs;
+    // alloc storage for 'nFuncs' truth tables as one chunk of memory
+    p->pFuncs = (word **)malloc( (sizeof(word *) + sizeof(word) * p->nWords) * p->nFuncs );
+    // assign and clean the truth table storage
+    p->pFuncs[0] = (word *)(p->pFuncs + p->nFuncs);
+    memset( p->pFuncs[0], 0, sizeof(word) * p->nWords * p->nFuncs );
+    // split it up into individual truth tables
+    for ( i = 1; i < p->nFuncs; i++ )
+        p->pFuncs[i] = p->pFuncs[i-1] + p->nWords;
+    return p;
+}
+Abc_TtStore_t * Abc_TruthStoreAlloc2( int nVars, int nFuncs, word * pBuffer )
+{
+    Abc_TtStore_t * p;
+    int i;
+    p = (Abc_TtStore_t *)malloc( sizeof(Abc_TtStore_t) );
+    p->nVars  =  nVars;
+    p->nWords = (nVars < 7) ? 1 : (1 << (nVars-6));
+    p->nFuncs =  nFuncs;
+    // alloc storage for 'nFuncs' truth tables as one chunk of memory
+    p->pFuncs = (word **)malloc( sizeof(word *) * p->nFuncs );
+    // assign and clean the truth table storage
+    p->pFuncs[0] = pBuffer;
+    // split it up into individual truth tables
+    for ( i = 1; i < p->nFuncs; i++ )
+        p->pFuncs[i] = p->pFuncs[i-1] + p->nWords;
+    return p;
+}
+void Abc_TtStoreFree( Abc_TtStore_t * p, int nVarNum )
+{
+    if ( nVarNum >= 0 )
+        ABC_FREE( p->pFuncs[0] );
+    ABC_FREE( p->pFuncs );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read file contents.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_FileSize( char * pFileName )
+{
+    FILE * pFile;
+    int nFileSize;
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\" for reading.\n", pFileName );
+        return -1;
+    }
+    // get the file size, in bytes
+    fseek( pFile, 0, SEEK_END );  
+    nFileSize = ftell( pFile );  
+    fclose( pFile );
+    return nFileSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read file contents.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_FileRead( char * pFileName )
+{
+    FILE * pFile;
+    char * pBuffer;
+    int nFileSize, RetValue;
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\" for reading.\n", pFileName );
+        return NULL;
+    }
+    // get the file size, in bytes
+    fseek( pFile, 0, SEEK_END );  
+    nFileSize = ftell( pFile );  
+    // move the file current reading position to the beginning
+    rewind( pFile ); 
+    // load the contents of the file into memory
+    pBuffer = (char *)malloc( nFileSize + 3 );
+    RetValue = fread( pBuffer, nFileSize, 1, pFile );
+    // add several empty lines at the end
+    // (these will be used to signal the end of parsing)
+    pBuffer[ nFileSize + 0] = '\n';
+    pBuffer[ nFileSize + 1] = '\n';
+    // terminate the string with '\0'
+    pBuffer[ nFileSize + 2] = '\0';
+    fclose( pFile );
+    return pBuffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determine the number of variables by reading the first line.]
+
+  Description [Determine the number of functions by counting the lines.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_TruthGetParams( char * pFileName, int * pnVars, int * pnTruths )
+{
+    char * pContents;
+    int i, nVars, nLines;
+    // prepare the output 
+    if ( pnVars )
+        *pnVars = 0;
+    if ( pnTruths )
+        *pnTruths = 0;
+    // read data from file
+    pContents = Abc_FileRead( pFileName );
+    if ( pContents == NULL )
+        return;
+    // count the number of symbols before the first space or new-line
+    // (note that on Windows symbols '\r' can be inserted before each '\n')
+    for ( i = 0; pContents[i]; i++ )
+        if ( pContents[i] == ' ' || pContents[i] == '\n' || pContents[i] == '\r' )
+            break;
+    if ( pContents[i] == 0 )
+        printf( "Strange, the input file does not have spaces and new-lines...\n" );
+
+    // acount for the fact that truth tables may have "0x" at the beginning of each line
+    if ( pContents[0] == '0' && pContents[1] == 'x' )
+        i = i - 2;
+
+    // determine the number of variables
+    for ( nVars = 0; nVars < 32; nVars++ )
+        if ( 4 * i == (1 << nVars) ) // the number of bits equal to the size of truth table
+            break;
+    if ( nVars < 2 || nVars > 16 )
+    {
+        printf( "Does not look like the input file contains truth tables...\n" );
+        return;
+    }
+    if ( pnVars )
+        *pnVars = nVars;
+
+    // determine the number of functions by counting the lines
+    nLines = 0;
+    for ( i = 0; pContents[i]; i++ )
+        nLines += (pContents[i] == '\n');
+    if ( pnTruths )
+        *pnTruths = nLines;
+    ABC_FREE( pContents );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Read truth tables from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_TruthStoreRead( char * pFileName, Abc_TtStore_t * p )
+{
+    char * pContents;
+    int i, nLines;
+    pContents = Abc_FileRead( pFileName );
+    if ( pContents == NULL )
+        return;
+    // here it is assumed (without checking!) that each line of the file 
+    // begins with a string of hexadecimal chars followed by space
+
+    // the file will be read till the first empty line (pContents[i] == '\n')
+    // (note that Abc_FileRead() added several empty lines at the end of the file contents)
+    for ( nLines = i = 0; pContents[i] != '\n'; )
+    {
+        // read one line
+        Abc_TruthReadHex( p->pFuncs[nLines++], &pContents[i], p->nVars );
+        // skip till after the end-of-line symbol
+        // (note that end-of-line symbol is also skipped)
+        while ( pContents[i++] != '\n' );
+    }
+    // adjust the number of functions read 
+    // (we may have allocated more storage because some lines in the file were empty)
+    assert( p->nFuncs >= nLines );
+    p->nFuncs = nLines;
+    ABC_FREE( pContents );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write truth tables into file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_TtStoreWrite( char * pFileName, Abc_TtStore_t * p, int fBinary )
+{
+    FILE * pFile;
+    char pBuffer[1000];
+    int i, nBytes = 8 * Abc_Truth6WordNum( p->nVars );
+    pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\" for writing.\n", pFileName );
+        return;
+    }
+    for ( i = 0; i < p->nFuncs; i++ )
+    {
+        if ( fBinary )
+            fwrite( p->pFuncs[i], nBytes, 1, pFile );
+        else
+        {
+            Abc_TruthWriteHex( pFile, p->pFuncs[i], p->nVars ), fprintf( pFile, "    " );
+            Dau_DsdDecompose( p->pFuncs[i], p->nVars, 0, (int)(p->nVars <= 10), pBuffer );
+            fprintf( pFile, "%s\n", pBuffer );
+        }
+    }
+    fclose( pFile );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Read truth tables from input file and write them into output file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_TtStore_t * Abc_TtStoreLoad( char * pFileName, int nVarNum )
+{ 
+    Abc_TtStore_t * p;
+    if ( nVarNum < 0 )
+    {
+        int nVars, nTruths;
+        // figure out how many truth table and how many variables
+        Abc_TruthGetParams( pFileName, &nVars, &nTruths );
+        if ( nVars < 2 || nVars > 16 || nTruths == 0 )
+            return NULL;
+        // allocate data-structure
+        p = Abc_TruthStoreAlloc( nVars, nTruths );
+        // read info from file
+        Abc_TruthStoreRead( pFileName, p );
+    }
+    else
+    { 
+        char * pBuffer;
+        int nFileSize = Abc_FileSize( pFileName );
+        int nBytes = (1 << (nVarNum-3));
+        int nTruths = nFileSize / nBytes;
+        if ( nFileSize == -1 )
+            return NULL;
+        assert( nVarNum >= 6 );
+        if ( nFileSize % nBytes != 0 ) 
+            Abc_Print( 0, "The file size (%d) is divided by the truth table size (%d) with remainder (%d).\n", 
+                nFileSize, nBytes, nFileSize % nBytes );
+        // read file contents
+        pBuffer = Abc_FileRead( pFileName );
+        // allocate data-structure
+        p = Abc_TruthStoreAlloc2( nVarNum, nTruths, (word *)pBuffer );
+    }
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read truth tables from input file and write them into output file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_TtStoreTest( char * pFileName )
+{ 
+    Abc_TtStore_t * p;
+    char * pFileInput  = pFileName;
+    char * pFileOutput = "out.txt";
+
+    // read info from file
+    p = Abc_TtStoreLoad( pFileInput, -1 );
+    if ( p == NULL )
+        return;
+
+    // write into another file
+    Abc_TtStoreWrite( pFileOutput, p, 0 );
+
+    // delete data-structure
+    Abc_TtStoreFree( p, -1 );
+    printf( "Input file \"%s\" was copied into output file \"%s\".\n", pFileInput, pFileOutput );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Apply decomposition to the truth table.]
+
+  Description [Returns the number of AIG nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_TruthDecPerform( Abc_TtStore_t * p, int DecType, int fVerbose )
+{
+    abctime clk = Abc_Clock();
+    int i, nNodes = 0;
+
+    char * pAlgoName = NULL;
+    if ( DecType == 1 )
+        pAlgoName = "factoring";
+    else if ( DecType == 2 )
+        pAlgoName = "bi-decomp";
+    else if ( DecType == 3 )
+        pAlgoName = "DSD";
+    else if ( DecType == 4 )
+        pAlgoName = "fast DSD";
+    else if ( DecType == 5 )
+        pAlgoName = "analysis";
+
+    if ( pAlgoName )
+        printf( "Applying %-10s to %8d func%s of %2d vars...  ",  
+            pAlgoName, p->nFuncs, (p->nFuncs == 1 ? "":"s"), p->nVars );
+    if ( fVerbose )
+        printf( "\n" );
+
+    if ( DecType == 1 )
+    {
+        // perform algebraic factoring and count AIG nodes
+        Dec_Graph_t * pFForm;
+        Vec_Int_t * vCover;
+        Vec_Str_t * vStr;
+        char * pSopStr;
+        vStr = Vec_StrAlloc( 10000 );
+        vCover = Vec_IntAlloc( 1 << 16 );
+        for ( i = 0; i < p->nFuncs; i++ )
+        {
+            if ( fVerbose )
+                printf( "%7d : ", i );
+            pSopStr = Kit_PlaFromTruthNew( (unsigned *)p->pFuncs[i], p->nVars, vCover, vStr );
+            pFForm = Dec_Factor( pSopStr );
+            nNodes += Dec_GraphNodeNum( pFForm );
+            if ( fVerbose )
+                Dec_GraphPrint( stdout, pFForm, NULL, NULL );
+            Dec_GraphFree( pFForm );
+        }
+        Vec_IntFree( vCover );
+        Vec_StrFree( vStr );
+    }
+    else if ( DecType == 2 )
+    {
+        // perform bi-decomposition and count AIG nodes
+        Bdc_Man_t * pManDec;
+        Bdc_Par_t Pars = {0}, * pPars = &Pars;
+        pPars->nVarsMax = p->nVars;
+        pManDec = Bdc_ManAlloc( pPars );
+        for ( i = 0; i < p->nFuncs; i++ )
+        {
+            if ( fVerbose )
+                printf( "%7d :      ", i );
+            Bdc_ManDecompose( pManDec, (unsigned *)p->pFuncs[i], NULL, p->nVars, NULL, 1000 );
+            nNodes += Bdc_ManAndNum( pManDec );
+            if ( fVerbose )
+                Bdc_ManDecPrint( pManDec );
+        }
+        Bdc_ManFree( pManDec );
+    }
+    else if ( DecType == 3 )
+    {
+        // perform disjoint-support decomposition and count AIG nodes
+        // (non-DSD blocks are decomposed into 2:1 MUXes, each counting as 3 AIG nodes)
+        Kit_DsdNtk_t * pNtk;
+        for ( i = 0; i < p->nFuncs; i++ )
+        {
+            if ( fVerbose )
+                printf( "%7d :      ", i );
+            pNtk = Kit_DsdDecomposeMux( (unsigned *)p->pFuncs[i], p->nVars, 3 );
+            if ( fVerbose )
+                Kit_DsdPrintExpanded( pNtk ), printf( "\n" );
+            nNodes += Kit_DsdCountAigNodes( pNtk );
+            Kit_DsdNtkFree( pNtk );
+        }
+    }
+    else if ( DecType == 4 )
+    {
+        char pDsd[DAU_MAX_STR];
+        for ( i = 0; i < p->nFuncs; i++ )
+        {
+            if ( fVerbose )
+                printf( "%7d :      ", i );
+            Dau_DsdDecompose( p->pFuncs[i], p->nVars, 0, 1, pDsd );
+            if ( fVerbose )
+                printf( "%s\n", pDsd );
+            nNodes += Dau_DsdCountAnds( pDsd );
+        }
+    }
+    else if ( DecType == 5 )
+    {
+        for ( i = 0; i < p->nFuncs; i++ )
+        {
+            extern void Dau_DecTrySets( word * pInit, int nVars, int fVerbose );
+            int nSuppSize = Abc_TtSupportSize( p->pFuncs[i], p->nVars );
+            if ( fVerbose )
+                printf( "%7d :      ", i );
+            Dau_DecTrySets( p->pFuncs[i], nSuppSize, fVerbose );
+            if ( fVerbose )
+                printf( "\n" );
+        }
+    }
+    else assert( 0 );
+
+    printf( "AIG nodes =%9d  ", nNodes );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Apply decomposition to truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_TruthDecTest( char * pFileName, int DecType, int nVarNum, int fVerbose )
+{
+    Abc_TtStore_t * p;
+
+    // allocate data-structure
+    p = Abc_TtStoreLoad( pFileName, nVarNum );
+
+    // consider functions from the file
+    Abc_TruthDecPerform( p, DecType, fVerbose );
+
+    // delete data-structure
+    Abc_TtStoreFree( p, nVarNum );
+//    printf( "Finished decomposing truth tables from file \"%s\".\n", pFileName );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Testbench for decomposition algorithms.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_DecTest( char * pFileName, int DecType, int nVarNum, int fVerbose )
+{
+    if ( fVerbose )
+        printf( "Using truth tables from file \"%s\"...\n", pFileName );
+    if ( DecType == 0 )
+        { if ( nVarNum < 0 ) Abc_TtStoreTest( pFileName ); }
+    else if ( DecType >= 1 && DecType <= 5 )
+        Abc_TruthDecTest( pFileName, DecType, nVarNum, fVerbose );
+    else
+        printf( "Unknown decomposition type value (%d).\n", DecType );
+    fflush( stdout );
+    return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcDress.c b/abc-build/src/base/abci/abcDress.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcDress.c
@@ -0,0 +1,214 @@
+/**CFile****************************************************************
+
+  FileName    [abcDress.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Transfers names from one netlist to the other.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcDress.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/io/ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static stmm_table * Abc_NtkDressDeriveMapping( Abc_Ntk_t * pNtk );
+static void         Abc_NtkDressTransferNames( Abc_Ntk_t * pNtk, stmm_table * tMapping, int fVerbose );
+
+extern Abc_Ntk_t *  Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers names from one netlist to the other.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDress( Abc_Ntk_t * pNtkLogic, char * pFileName, int fVerbose )
+{
+    Abc_Ntk_t * pNtkOrig, * pNtkLogicOrig;
+    Abc_Ntk_t * pMiter, * pMiterFraig;
+    stmm_table * tMapping;
+
+    assert( Abc_NtkIsLogic(pNtkLogic) );
+
+    // get the original netlist
+    pNtkOrig = Io_ReadNetlist( pFileName, Io_ReadFileType(pFileName), 1 );
+    if ( pNtkOrig == NULL )
+        return;
+    assert( Abc_NtkIsNetlist(pNtkOrig) );
+
+    Abc_NtkCleanCopy(pNtkLogic);
+    Abc_NtkCleanCopy(pNtkOrig);
+
+    // convert it into the logic network
+    pNtkLogicOrig = Abc_NtkToLogic( pNtkOrig );
+    // check that the networks have the same PIs/POs/latches
+    if ( !Abc_NtkCompareSignals( pNtkLogic, pNtkLogicOrig, 1, 1 ) )
+    {
+        Abc_NtkDelete( pNtkOrig );
+        Abc_NtkDelete( pNtkLogicOrig );
+        return;
+    }
+
+    // convert the current logic network into an AIG
+    pMiter = Abc_NtkStrash( pNtkLogic, 1, 0, 0 );
+
+    // convert it into the AIG and make the netlist point to the AIG
+    Abc_NtkAppend( pMiter, pNtkLogicOrig, 1 );
+    Abc_NtkTransferCopy( pNtkOrig );
+    Abc_NtkDelete( pNtkLogicOrig );
+
+if ( fVerbose ) 
+{
+printf( "After mitering:\n" );
+printf( "Logic:  Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkLogic), Abc_NtkCountCopy(pNtkLogic) );
+printf( "Orig:   Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkOrig),  Abc_NtkCountCopy(pNtkOrig) );
+}
+
+    // fraig the miter (miter nodes point to the fraiged miter)
+    pMiterFraig = Abc_NtkIvyFraig( pMiter, 100, 1, 0, 1, 0 );
+    // make netlists point to the fraiged miter
+    Abc_NtkTransferCopy( pNtkLogic );
+    Abc_NtkTransferCopy( pNtkOrig );
+    Abc_NtkDelete( pMiter );
+
+if ( fVerbose ) 
+{
+printf( "After fraiging:\n" );
+printf( "Logic:  Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkLogic), Abc_NtkCountCopy(pNtkLogic) );
+printf( "Orig:   Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkOrig),  Abc_NtkCountCopy(pNtkOrig) );
+}
+
+    // derive mapping from the fraiged nodes into their prototype nodes in the original netlist
+    tMapping = Abc_NtkDressDeriveMapping( pNtkOrig );
+
+    // transfer the names to the new netlist
+    Abc_NtkDressTransferNames( pNtkLogic, tMapping, fVerbose );
+
+    // clean up
+    stmm_free_table( tMapping );
+    Abc_NtkDelete( pMiterFraig );
+    Abc_NtkDelete( pNtkOrig );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the mapping from the fraig nodes point into the nodes of the netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+stmm_table * Abc_NtkDressDeriveMapping( Abc_Ntk_t * pNtk )
+{
+    stmm_table * tResult;
+    Abc_Obj_t * pNode, * pNodeMap, * pNodeFraig;
+    int i;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    tResult = stmm_init_table(stmm_ptrcmp,stmm_ptrhash);
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        // get the fraiged node
+        pNodeFraig = Abc_ObjRegular(pNode->pCopy);
+        // if this node is already mapped, skip
+        if ( stmm_is_member( tResult, (char *)pNodeFraig ) )
+            continue;
+        // get the mapping of this node
+        pNodeMap = Abc_ObjNotCond( pNode, Abc_ObjIsComplement(pNode->pCopy) );
+        // add the mapping
+        stmm_insert( tResult, (char *)pNodeFraig, (char *)pNodeMap );
+    }
+    return tResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Attaches the names of to the new netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDressTransferNames( Abc_Ntk_t * pNtk, stmm_table * tMapping, int fVerbose )
+{
+    Abc_Obj_t * pNet, * pNode, * pNodeMap, * pNodeFraig;
+    char * pName;
+    int i, Counter = 0, CounterInv = 0, CounterInit = stmm_count(tMapping);
+    assert( Abc_NtkIsLogic(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        // if the node already has a name, quit
+        pName = Nm_ManFindNameById( pNtk->pManName, pNode->Id );
+        if ( pName != NULL )
+            continue;
+        // get the fraiged node
+        pNodeFraig = Abc_ObjRegular(pNode->pCopy);
+        // find the matching node of the original netlist
+        if ( !stmm_lookup( tMapping, (char *)pNodeFraig, (char **)&pNodeMap ) )
+            continue;
+        // find the true match
+        pNodeMap = Abc_ObjNotCond( pNodeMap, Abc_ObjIsComplement(pNode->pCopy) );
+        // get the name
+        pNet = Abc_ObjFanout0(Abc_ObjRegular(pNodeMap));
+        pName = Nm_ManFindNameById( pNet->pNtk->pManName, pNet->Id );
+        assert( pName != NULL );
+        // set the name
+        if ( Abc_ObjIsComplement(pNodeMap) )
+        {
+            Abc_ObjAssignName( pNode, pName, "_inv" );
+            CounterInv++;
+        }
+        else
+        {
+            Abc_ObjAssignName( pNode, pName, NULL );
+            Counter++;
+        }
+        // remove the name
+        stmm_delete( tMapping, (char **)&pNodeFraig, (char **)&pNodeMap );
+    }
+    if ( fVerbose )
+    {
+        printf( "Total number of names collected = %5d.\n", CounterInit );
+        printf( "Total number of names assigned  = %5d. (Dir = %5d. Compl = %5d.)\n", 
+            Counter + CounterInv, Counter, CounterInv );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcDress2.c b/abc-build/src/base/abci/abcDress2.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcDress2.c
@@ -0,0 +1,435 @@
+/**CFile****************************************************************
+
+  FileName    [abcDressw.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Transfers names from one netlist to the other.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcDressw.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "aig/aig/aig.h"
+#include "proof/dch/dch.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+  Procedure Abc_NtkDressComputeEquivs() implemented in this file computes 
+  equivalence classes of objects of the two networks (pNtk1 and pNtk2).
+
+  It is possible that pNtk1 is the network before synthesis and pNtk2 is the
+  network after synthesis.  The equiv classes of nodes from these networks 
+  can be used to transfer the names from pNtk1 to pNtk2, or vice versa. 
+
+  The above procedure returns the array (Vec_Ptr_t) of integer arrays (Vec_Int_t).
+  Each of the integer arrays contains entries of one equivalence class.
+  Each entry (EquivId) contains the following information: 
+  (1) object ID, which is a number 'num', such that 0 <= 'num' < MaxId 
+      where MaxId is the largest ID of nodes in a network
+  (2) the polarity of the node, which is a binary number, 0 or 1, giving
+      the node's value when pattern (000...0) is applied to the inputs
+  (3) the number of the network, 0 or 1, which stands for pNtk1 and pNtk2, respectively
+  The first array in the array of arrays is empty, or contains nodes that 
+  are equivalent to a constant (if such nodes appear in the network).
+
+  Given EquivID defined above, use the APIs below to get its components.
+*/
+
+// declarations to be added to the application code
+extern int Abc_ObjEquivId2ObjId( int EquivId );
+extern int Abc_ObjEquivId2Polar( int EquivId );
+extern int Abc_ObjEquivId2NtkId( int EquivId );
+
+// definition that may remain in this file
+int Abc_ObjEquivId2ObjId( int EquivId ) { return  EquivId >> 2;      }
+int Abc_ObjEquivId2Polar( int EquivId ) { return (EquivId >> 1) & 1; }
+int Abc_ObjEquivId2NtkId( int EquivId ) { return  EquivId       & 1; }
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern Aig_Man_t *  Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+extern void         Dch_ComputeEquivalences( Aig_Man_t * pAig, Dch_Pars_t * pPars );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the dual-output miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManCreateDualOutputMiter( Aig_Man_t * p1, Aig_Man_t * p2 )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( Aig_ManCiNum(p1) == Aig_ManCiNum(p2) );
+    assert( Aig_ManCoNum(p1) == Aig_ManCoNum(p2) );
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p1) + Aig_ManObjNumMax(p2) );
+    // add first AIG
+    Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p1, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    Aig_ManForEachNode( p1, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // add second AIG
+    Aig_ManConst1(p2)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p2, pObj, i )
+        pObj->pData = Aig_ManCi( pNew, i );
+    Aig_ManForEachNode( p2, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // add the outputs
+    for ( i = 0; i < Aig_ManCoNum(p1); i++ )
+    {
+        Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(Aig_ManCo(p1, i)) );
+        Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(Aig_ManCo(p2, i)) );
+    }
+    Aig_ManCleanup( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets polarity attribute of each object in the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDressMapSetPolarity( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj, * pAnd;
+    int i;
+    // each node refers to the the strash copy whose polarity is set
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        if ( (pAnd = Abc_ObjRegular(pObj->pCopy)) && Abc_ObjType(pAnd) != ABC_OBJ_NONE ) // strashed object is present and legal
+            pObj->fPhase = pAnd->fPhase ^ Abc_ObjIsComplement(pObj->pCopy);
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create mapping of node IDs of pNtk into equiv classes of pMiter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkDressMapClasses( Aig_Man_t * pMiter, Abc_Ntk_t * pNtk )
+{
+    Vec_Int_t * vId2Lit;
+    Abc_Obj_t * pObj, * pAnd;
+    Aig_Obj_t * pObjMan, * pObjMiter, * pObjRepr;
+    int i;
+    vId2Lit = Vec_IntAlloc( 0 );
+    Vec_IntFill( vId2Lit, Abc_NtkObjNumMax(pNtk), -1 );
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        // get the pointer to the miter node corresponding to pObj
+        if ( (pAnd = Abc_ObjRegular(pObj->pCopy)) && Abc_ObjType(pAnd) != ABC_OBJ_NONE &&          // strashed node is present and legal
+             (pObjMan = Aig_Regular((Aig_Obj_t *)pAnd->pCopy)) && Aig_ObjType(pObjMan) != AIG_OBJ_NONE &&       // AIG node is present and legal
+             (pObjMiter = Aig_Regular((Aig_Obj_t *)pObjMan->pData)) && Aig_ObjType(pObjMiter) != AIG_OBJ_NONE ) // miter node is present and legal
+        {
+            // get the representative of the miter node
+            pObjRepr = Aig_ObjRepr( pMiter, pObjMiter );
+            pObjRepr = pObjRepr? pObjRepr : pObjMiter;
+            // map pObj (whose ID is i) into the repr node ID (i.e. equiv class)
+            Vec_IntWriteEntry( vId2Lit, i, Aig_ObjId(pObjRepr) );
+        }
+    }
+    return vId2Lit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the vector of given equivalence class of objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_ObjDressClass( Vec_Ptr_t * vRes, Vec_Int_t * vClass2Num, int Class )
+{
+    int ClassNumber;
+    assert( Class > 0 );
+    ClassNumber = Vec_IntEntry( vClass2Num, Class );
+    assert( ClassNumber != 0 );
+    if ( ClassNumber > 0 )
+        return (Vec_Int_t *)Vec_PtrEntry( vRes, ClassNumber ); // previous class
+    // create new class
+    Vec_IntWriteEntry( vClass2Num, Class, Vec_PtrSize(vRes) );
+    Vec_PtrPush( vRes, Vec_IntAlloc(4) );
+    return (Vec_Int_t *)Vec_PtrEntryLast( vRes ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the ID of a node in an equivalence class.]
+
+  Description [The ID is composed of three parts: object ID, followed
+  by one bit telling the phase of this node, followed by one bit
+  telling the network to which this node belongs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ObjDressMakeId( Abc_Ntk_t * pNtk, int ObjId, int iNtk )
+{
+    return (ObjId << 2) | (Abc_NtkObj(pNtk,ObjId)->fPhase << 1) | iNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes equivalence classes of objects in pNtk1 and pNtk2.]
+
+  Description [Internal procedure.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDressMapIds( Aig_Man_t * pMiter, Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
+{
+    Vec_Ptr_t * vRes;
+    Vec_Int_t * vId2Lit1, * vId2Lit2, * vCounts0, * vCounts1, * vClassC, * vClass2Num;
+    int i, Class;
+    // start the classes
+    vRes = Vec_PtrAlloc( 1000 );
+    // set polarity of the nodes
+    Abc_NtkDressMapSetPolarity( pNtk1 );
+    Abc_NtkDressMapSetPolarity( pNtk2 );
+    // create mapping of node IDs of pNtk1/pNtk2 into the IDs of equiv classes of pMiter
+    vId2Lit1 = Abc_NtkDressMapClasses( pMiter, pNtk1 );
+    vId2Lit2 = Abc_NtkDressMapClasses( pMiter, pNtk2 );
+    // count the number of nodes in each equivalence class
+    vCounts0 = Vec_IntStart( Aig_ManObjNumMax(pMiter) );
+    Vec_IntForEachEntry( vId2Lit1, Class, i )
+        if ( Class >= 0 )
+            Vec_IntAddToEntry( vCounts0, Class, 1 );
+    vCounts1 = Vec_IntStart( Aig_ManObjNumMax(pMiter) );
+    Vec_IntForEachEntry( vId2Lit2, Class, i )
+        if ( Class >= 0 )
+            Vec_IntAddToEntry( vCounts1, Class, 1 );
+    // get the costant class
+    vClassC = Vec_IntAlloc( 100 );
+    Vec_IntForEachEntry( vId2Lit1, Class, i )
+        if ( Class == 0 )
+            Vec_IntPush( vClassC, Abc_ObjDressMakeId(pNtk1, i, 0) );
+    Vec_IntForEachEntry( vId2Lit2, Class, i )
+        if ( Class == 0 )
+            Vec_IntPush( vClassC, Abc_ObjDressMakeId(pNtk2, i, 1) );
+    Vec_PtrPush( vRes, vClassC );
+    // map repr node IDs into class numbers
+    vClass2Num = Vec_IntAlloc( 0 );
+    Vec_IntFill( vClass2Num, Aig_ManObjNumMax(pMiter), -1 );
+    // keep classes having at least one element from pNtk1 and one from pNtk2
+    Vec_IntForEachEntry( vId2Lit1, Class, i )
+        if ( Class > 0 && Vec_IntEntry(vCounts0, Class) && Vec_IntEntry(vCounts1, Class) )
+            Vec_IntPush( Abc_ObjDressClass(vRes, vClass2Num, Class), Abc_ObjDressMakeId(pNtk1, i, 0) );
+    Vec_IntForEachEntry( vId2Lit2, Class, i )
+        if ( Class > 0 && Vec_IntEntry(vCounts0, Class) && Vec_IntEntry(vCounts1, Class) )
+            Vec_IntPush( Abc_ObjDressClass(vRes, vClass2Num, Class), Abc_ObjDressMakeId(pNtk2, i, 1) );
+    // package them accordingly
+    Vec_IntFree( vClass2Num );
+    Vec_IntFree( vCounts0 );
+    Vec_IntFree( vCounts1 );
+    Vec_IntFree( vId2Lit1 );
+    Vec_IntFree( vId2Lit2 );
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes equivalence classes of objects in pNtk1 and pNtk2.]
+
+  Description [Returns the array (Vec_Ptr_t) of integer arrays (Vec_Int_t).
+  Each of the integer arrays contains entries of one equivalence class.
+  Each entry contains the following information: the network number (0/1),
+  the polarity (0/1) and the object ID in the the network (0 <= num < MaxId)
+  where MaxId is the largest number of an ID of an object in that network.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDressComputeEquivs( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConflictLimit, int fVerbose )
+{
+    Dch_Pars_t Pars, * pPars = &Pars;
+    Abc_Ntk_t * pAig1, * pAig2;
+    Aig_Man_t * pMan1, * pMan2, * pMiter;
+    Vec_Ptr_t * vRes;
+    assert( !Abc_NtkIsStrash(pNtk1) );
+    assert( !Abc_NtkIsStrash(pNtk2) );
+    // convert network into AIG
+    pAig1 = Abc_NtkStrash( pNtk1, 1, 1, 0 );
+    pAig2 = Abc_NtkStrash( pNtk2, 1, 1, 0 );
+    pMan1 = Abc_NtkToDar( pAig1, 0, 0 );
+    pMan2 = Abc_NtkToDar( pAig2, 0, 0 );
+    // derive the miter
+    pMiter = Aig_ManCreateDualOutputMiter( pMan1, pMan2 );
+    // set up parameters for SAT sweeping
+    Dch_ManSetDefaultParams( pPars );
+    pPars->nBTLimit = nConflictLimit;
+    pPars->fVerbose = fVerbose;
+    // perform SAT sweeping
+    Dch_ComputeEquivalences( pMiter, pPars );
+    // now, pMiter is annotated with the equivl class info
+    // convert this info into the resulting array
+    vRes = Abc_NtkDressMapIds( pMiter, pNtk1, pNtk2 );
+    Aig_ManStop( pMiter );
+    Aig_ManStop( pMan1 );
+    Aig_ManStop( pMan2 );
+    Abc_NtkDelete( pAig1 );
+    Abc_NtkDelete( pAig2 );
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints information about node equivalences.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDressPrintEquivs( Vec_Ptr_t * vRes )
+{
+    Vec_Int_t * vClass;
+    int i, k, Entry;
+    Vec_PtrForEachEntry( Vec_Int_t *, vRes, vClass, i )
+    {
+        printf( "Class %5d : ", i );
+        printf( "Num =%5d    ", Vec_IntSize(vClass) );
+        Vec_IntForEachEntry( vClass, Entry, k )
+            printf( "%5d%c%d ", 
+                Abc_ObjEquivId2ObjId(Entry), 
+                Abc_ObjEquivId2Polar(Entry)? '-':'+', 
+                Abc_ObjEquivId2NtkId(Entry) );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints information about node equivalences.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDressPrintStats( Vec_Ptr_t * vRes, int nNodes0, int nNodes1, abctime Time )
+{
+    Vec_Int_t * vClass;
+    int i, k, Entry;
+    int NegAll[2] = {0}, PosAll[2] = {0}, PairsAll = 0, PairsOne = 0;
+    int Pos[2], Neg[2];
+    // count the number of equivalences in each class
+    Vec_PtrForEachEntry( Vec_Int_t *, vRes, vClass, i )
+    {
+        Pos[0] = Pos[1] = 0;
+        Neg[0] = Neg[1] = 0;
+        Vec_IntForEachEntry( vClass, Entry, k )
+        {
+            if ( Abc_ObjEquivId2NtkId(Entry) )
+            {
+                if ( Abc_ObjEquivId2Polar(Entry) )
+                    Neg[1]++; // negative polarity in network 1
+                else
+                    Pos[1]++; // positive polarity in network 1
+            }
+            else
+            {
+                if ( Abc_ObjEquivId2Polar(Entry) )
+                    Neg[0]++; // negative polarity in network 0
+                else
+                    Pos[0]++; // positive polarity in network 0
+            }
+        }
+        PosAll[0] += Pos[0]; // total positive polarity in network 0
+        PosAll[1] += Pos[1]; // total positive polarity in network 1
+        NegAll[0] += Neg[0]; // total negative polarity in network 0
+        NegAll[1] += Neg[1]; // total negative polarity in network 1
+
+        // assuming that the name can be transferred to only one node
+        PairsAll += Abc_MinInt(Neg[0] + Pos[0], Neg[1] + Pos[1]);
+        PairsOne += Abc_MinInt(Neg[0], Neg[1]) + Abc_MinInt(Pos[0], Pos[1]);
+    }
+    printf( "Total number of equiv classes                = %7d.\n", Vec_PtrSize(vRes) );
+    printf( "Participating nodes from both networks       = %7d.\n", NegAll[0]+PosAll[0]+NegAll[1]+PosAll[1] );
+    printf( "Participating nodes from the first network   = %7d. (%7.2f %% of nodes)\n", NegAll[0]+PosAll[0], 100.0*(NegAll[0]+PosAll[0])/(nNodes0+1) );
+    printf( "Participating nodes from the second network  = %7d. (%7.2f %% of nodes)\n", NegAll[1]+PosAll[1], 100.0*(NegAll[1]+PosAll[1])/(nNodes1+1) );
+    printf( "Node pairs (any polarity)                    = %7d. (%7.2f %% of names can be moved)\n", PairsAll, 100.0*PairsAll/(nNodes0+1) );
+    printf( "Node pairs (same polarity)                   = %7d. (%7.2f %% of names can be moved)\n", PairsOne, 100.0*PairsOne/(nNodes0+1) );
+    ABC_PRT( "Total runtime", Time );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers names from pNtk1 to pNtk2.]
+
+  Description [Internally calls new procedure for mapping node IDs of
+  both networks into the shared equivalence classes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDress2( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConflictLimit, int fVerbose )
+{
+    Vec_Ptr_t * vRes;
+    abctime clk = Abc_Clock();
+    vRes = Abc_NtkDressComputeEquivs( pNtk1, pNtk2, nConflictLimit, fVerbose );
+//    Abc_NtkDressPrintEquivs( vRes );
+    Abc_NtkDressPrintStats( vRes, Abc_NtkNodeNum(pNtk1), Abc_NtkNodeNum(pNtk1), Abc_Clock() - clk );
+    Vec_VecFree( (Vec_Vec_t *)vRes );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcDsd.c b/abc-build/src/base/abci/abcDsd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcDsd.c
@@ -0,0 +1,563 @@
+/**CFile****************************************************************
+
+  FileName    [abcDsd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Decomposes the network using disjoint-support decomposition.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/extra/extraBdd.h"
+#include "bdd/dsd/dsd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+static Abc_Ntk_t *     Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, int fVerbose, int fPrint, int fShort );
+static void            Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
+static Abc_Obj_t *     Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew, int * pCounters );
+
+static Vec_Ptr_t *     Abc_NtkCollectNodesForDsd( Abc_Ntk_t * pNtk );
+static void            Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, int fRecursive, int * pCounters );
+static int            Abc_NodeIsForDsd( Abc_Obj_t * pNode );
+static int             Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int nVars );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the DSD network.]
+
+  Description [Takes the strashed network (pNtk), derives global BDDs for
+  the combinational outputs of this network, and decomposes these BDDs using
+  disjoint support decomposition. Finally, constructs and return a new 
+  network, which is topologically equivalent to the decomposition tree.
+  Allocates and frees a new BDD manager and a new DSD manager.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, int fVerbose, int fPrint, int fShort )
+{
+    DdManager * dd;
+    Abc_Ntk_t * pNtkNew;
+    assert( Abc_NtkIsStrash(pNtk) );
+    dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose );
+    if ( dd == NULL )
+        return NULL;
+    if ( fVerbose )
+        printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+    // transform the result of mapping into a BDD network
+    pNtkNew = Abc_NtkDsdInternal( pNtk, fVerbose, fPrint, fShort );
+    Extra_StopManager( dd );
+    if ( pNtkNew == NULL )
+        return NULL;
+    // copy EXDC network
+    if ( pNtk->pExdc )
+        pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkDsdGlobal: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs the decomposed network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, int fVerbose, int fPrint, int fShort )
+{
+    char ** ppNamesCi, ** ppNamesCo;
+    Vec_Ptr_t * vFuncsGlob;
+    Dsd_Manager_t * pManDsd;
+    Abc_Ntk_t * pNtkNew;
+    DdManager * dd;
+    Abc_Obj_t * pObj;
+    int i;
+
+    // complement the global functions
+    vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Vec_PtrPush( vFuncsGlob, Cudd_NotCond(Abc_ObjGlobalBdd(pObj), Abc_ObjFaninC0(pObj)) );
+
+    // perform the decomposition
+    dd = (DdManager *)Abc_NtkGlobalBddMan(pNtk);
+    pManDsd = Dsd_ManagerStart( dd, Abc_NtkCiNum(pNtk), fVerbose );
+    if ( pManDsd == NULL )
+    {
+        Vec_PtrFree( vFuncsGlob );
+        Cudd_Quit( dd );
+        return NULL;
+    }
+    Dsd_Decompose( pManDsd, (DdNode **)vFuncsGlob->pArray, Abc_NtkCoNum(pNtk) );
+    Vec_PtrFree( vFuncsGlob );
+    Abc_NtkFreeGlobalBdds( pNtk, 0 );
+
+    // start the new network
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
+    // make sure the new manager has enough inputs
+    Cudd_bddIthVar( (DdManager *)pNtkNew->pManFunc, dd->size-1 );
+    // put the results into the new network (save new CO drivers in old CO drivers)
+    Abc_NtkDsdConstruct( pManDsd, pNtk, pNtkNew );
+    // finalize the new network
+    Abc_NtkFinalize( pNtk, pNtkNew );
+    // fix the problem with complemented and duplicated CO edges
+    Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+    if ( fPrint )
+    {
+        ppNamesCi = Abc_NtkCollectCioNames( pNtk, 0 );
+        ppNamesCo = Abc_NtkCollectCioNames( pNtk, 1 );
+        Dsd_TreePrint( stdout, pManDsd, ppNamesCi, ppNamesCo, fShort, -1 );
+        ABC_FREE( ppNamesCi );
+        ABC_FREE( ppNamesCo );
+    }
+
+    // stop the DSD manager
+    Dsd_ManagerStop( pManDsd );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs the decomposed network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
+{
+    Dsd_Node_t ** ppNodesDsd;
+    Dsd_Node_t * pNodeDsd;
+    Abc_Obj_t * pNode, * pNodeNew, * pDriver;
+    int i, nNodesDsd;
+
+    // save the CI nodes in the DSD nodes
+    Abc_AigConst1(pNtk)->pCopy = pNodeNew = Abc_NtkCreateNodeConst1(pNtkNew);
+    Dsd_NodeSetMark( Dsd_ManagerReadConst1(pManDsd), (int)(ABC_PTRINT_T)pNodeNew );
+    Abc_NtkForEachCi( pNtk, pNode, i )
+    {
+        pNodeDsd = Dsd_ManagerReadInput( pManDsd, i );
+        Dsd_NodeSetMark( pNodeDsd, (int)(ABC_PTRINT_T)pNode->pCopy );
+    }
+
+    // collect DSD nodes in DFS order (leaves and const1 are not collected)
+    ppNodesDsd = Dsd_TreeCollectNodesDfs( pManDsd, &nNodesDsd );
+    for ( i = 0; i < nNodesDsd; i++ )
+        Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNtkNew, NULL );
+    ABC_FREE( ppNodesDsd );
+
+    // set the pointers to the CO drivers
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        pDriver = Abc_ObjFanin0( pNode );
+        if ( !Abc_ObjIsNode(pDriver) )
+            continue;
+        if ( !Abc_AigNodeIsAnd(pDriver) )
+            continue;
+        pNodeDsd = Dsd_ManagerReadRoot( pManDsd, i );
+        pNodeNew = (Abc_Obj_t *)(ABC_PTRINT_T)Dsd_NodeReadMark( Dsd_Regular(pNodeDsd) );
+        assert( !Abc_ObjIsComplement(pNodeNew) );
+        pDriver->pCopy = Abc_ObjNotCond( pNodeNew, Dsd_IsComplement(pNodeDsd) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DSD using the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew, int * pCounters )
+{
+    DdManager * ddDsd = Dsd_ManagerReadDd( pManDsd );
+    DdManager * ddNew = (DdManager *)pNtkNew->pManFunc;
+    Dsd_Node_t * pFaninDsd;
+    Abc_Obj_t * pNodeNew, * pFanin;
+    DdNode * bLocal, * bTemp, * bVar;
+    Dsd_Type_t Type;
+    int i, nDecs;
+
+    // create the new node
+    pNodeNew = Abc_NtkCreateNode( pNtkNew );
+    // add the fanins
+    Type  = Dsd_NodeReadType( pNodeDsd );
+    nDecs = Dsd_NodeReadDecsNum( pNodeDsd );
+    assert( nDecs > 1 );
+    for ( i = 0; i < nDecs; i++ )
+    {
+        pFaninDsd  = Dsd_NodeReadDec( pNodeDsd, i );
+        pFanin     = (Abc_Obj_t *)(ABC_PTRINT_T)Dsd_NodeReadMark(Dsd_Regular(pFaninDsd));
+        Abc_ObjAddFanin( pNodeNew, pFanin );
+        assert( Type == DSD_NODE_OR || !Dsd_IsComplement(pFaninDsd) );
+    }
+
+    // create the local function depending on the type of the node
+    ddNew = (DdManager *)pNtkNew->pManFunc;
+    switch ( Type )
+    {
+        case DSD_NODE_CONST1:
+        {
+            bLocal = ddNew->one; Cudd_Ref( bLocal );
+            break;
+        }
+        case DSD_NODE_OR:
+        {
+            bLocal = Cudd_Not(ddNew->one); Cudd_Ref( bLocal );
+            for ( i = 0; i < nDecs; i++ )
+            {
+                pFaninDsd  = Dsd_NodeReadDec( pNodeDsd, i );
+                bVar   = Cudd_NotCond( ddNew->vars[i], Dsd_IsComplement(pFaninDsd) );
+                bLocal = Cudd_bddOr( ddNew, bTemp = bLocal, bVar );               Cudd_Ref( bLocal );
+                Cudd_RecursiveDeref( ddNew, bTemp );
+            }
+            break;
+        }
+        case DSD_NODE_EXOR:
+        {
+            bLocal = Cudd_Not(ddNew->one); Cudd_Ref( bLocal );
+            for ( i = 0; i < nDecs; i++ )
+            {
+                bLocal = Cudd_bddXor( ddNew, bTemp = bLocal, ddNew->vars[i] );    Cudd_Ref( bLocal );
+                Cudd_RecursiveDeref( ddNew, bTemp );
+            }
+            break;
+        }
+        case DSD_NODE_PRIME:
+        {
+            if ( pCounters )
+            {
+                if ( nDecs < 10 )
+                    pCounters[nDecs]++;
+                else
+                    pCounters[10]++;
+            }
+            bLocal = Dsd_TreeGetPrimeFunction( ddDsd, pNodeDsd );                Cudd_Ref( bLocal );
+            bLocal = Extra_TransferLevelByLevel( ddDsd, ddNew, bTemp = bLocal ); Cudd_Ref( bLocal );
+/*
+if ( nDecs == 3 )
+{
+Extra_bddPrint( ddDsd, bTemp );
+printf( "\n" );
+}
+*/
+            Cudd_RecursiveDeref( ddDsd, bTemp );
+            // bLocal is now in the new BDD manager
+            break;
+        }
+        default:
+        {
+            assert( 0 );
+            break;
+        }
+    }
+    pNodeNew->pData = bLocal;
+    Dsd_NodeSetMark( pNodeDsd, (int)(ABC_PTRINT_T)pNodeNew );
+    return pNodeNew;
+}
+
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively decomposes internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, int fVerbose, int fRecursive )
+{
+    Dsd_Manager_t * pManDsd;
+    DdManager * dd = (DdManager *)pNtk->pManFunc;
+    Vec_Ptr_t * vNodes;
+    int i;
+    int pCounters[11] = {0};
+
+    assert( Abc_NtkIsBddLogic(pNtk) );
+
+    // make the network minimum base
+    Abc_NtkMinimumBase( pNtk );
+
+    // start the DSD manager
+    pManDsd = Dsd_ManagerStart( dd, dd->size, 0 );
+
+    // collect nodes for decomposition
+    vNodes = Abc_NtkCollectNodesForDsd( pNtk );
+    for ( i = 0; i < vNodes->nSize; i++ )
+        Abc_NodeDecompDsdAndMux( (Abc_Obj_t *)vNodes->pArray[i], vNodes, pManDsd, fRecursive, pCounters );
+    Vec_PtrFree( vNodes );
+
+    if ( fVerbose )
+    {
+        printf( "Number of non-decomposable functions:\n" );
+        for ( i = 3; i < 10; i++ )
+            printf( "Inputs = %d.  Functions = %6d.\n", i, pCounters[i] );
+        printf( "Inputs > %d.  Functions = %6d.\n", 9, pCounters[10] );
+    }
+
+    // stop the DSD manager
+    Dsd_ManagerStop( pManDsd );
+
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pNtk ) )
+    {
+        printf( "Abc_NtkDsdRecursive: The network check has failed.\n" );
+        return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the nodes that may need decomposition.]
+
+  Description [The nodes that do not need decomposition are those
+  whose BDD has more internal nodes than the support size.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkCollectNodesForDsd( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNode;
+    int i;
+    vNodes = Vec_PtrAlloc( 100 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        if ( Abc_NodeIsForDsd(pNode) )
+            Vec_PtrPush( vNodes, pNode );
+    }
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs decomposition of one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, int fRecursive, int * pCounters )
+{
+    DdManager * dd = (DdManager *)pNode->pNtk->pManFunc;
+    Abc_Obj_t * pRoot = NULL, * pFanin, * pNode1, * pNode2, * pNodeC;
+    Dsd_Node_t ** ppNodesDsd, * pNodeDsd, * pFaninDsd;
+    int i, nNodesDsd, iVar, fCompl;
+
+    // try disjoint support decomposition
+    pNodeDsd = Dsd_DecomposeOne( pManDsd, (DdNode *)pNode->pData );
+    fCompl   = Dsd_IsComplement( pNodeDsd );
+    pNodeDsd = Dsd_Regular( pNodeDsd );
+
+    // determine what decomposition to use   
+    if ( !fRecursive || Dsd_NodeReadDecsNum(pNodeDsd) != Abc_ObjFaninNum(pNode) )
+    { // perform DSD
+
+        // set the inputs
+        Abc_ObjForEachFanin( pNode, pFanin, i )
+        {
+            pFaninDsd = Dsd_ManagerReadInput( pManDsd, i );
+            Dsd_NodeSetMark( pFaninDsd, (int)(ABC_PTRINT_T)pFanin );
+        }
+
+        // construct the intermediate nodes
+        ppNodesDsd = Dsd_TreeCollectNodesDfsOne( pManDsd, pNodeDsd, &nNodesDsd );
+        for ( i = 0; i < nNodesDsd; i++ )
+        {
+            pRoot = Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNode->pNtk, pCounters );
+            if ( Abc_NodeIsForDsd(pRoot) && fRecursive )
+                Vec_PtrPush( vNodes, pRoot );
+        }
+        ABC_FREE( ppNodesDsd );
+        assert(pRoot);
+
+        // remove the current fanins
+        Abc_ObjRemoveFanins( pNode );
+        // add fanin to the root
+        Abc_ObjAddFanin( pNode, pRoot );
+        // update the function to be that of buffer
+        Cudd_RecursiveDeref( dd, (DdNode *)pNode->pData );
+        pNode->pData = Cudd_NotCond( (DdNode *)dd->vars[0], fCompl ); Cudd_Ref( (DdNode *)pNode->pData );
+    }
+    else // perform MUX-decomposition
+    {
+        // get the cofactoring variable
+        iVar = Abc_NodeFindMuxVar( dd, (DdNode *)pNode->pData, Abc_ObjFaninNum(pNode) );
+        pNodeC = Abc_ObjFanin( pNode, iVar );
+
+        // get the negative cofactor
+        pNode1 = Abc_NtkCloneObj( pNode );
+        pNode1->pData = Cudd_Cofactor( dd, (DdNode *)pNode->pData, Cudd_Not(dd->vars[iVar]) );  Cudd_Ref( (DdNode *)pNode1->pData );
+        Abc_NodeMinimumBase( pNode1 );
+        if ( Abc_NodeIsForDsd(pNode1) )
+            Vec_PtrPush( vNodes, pNode1 );
+
+        // get the positive cofactor
+        pNode2 = Abc_NtkCloneObj( pNode );
+        pNode2->pData = Cudd_Cofactor( dd, (DdNode *)pNode->pData, dd->vars[iVar] );            Cudd_Ref( (DdNode *)pNode2->pData );
+        Abc_NodeMinimumBase( pNode2 );
+        if ( Abc_NodeIsForDsd(pNode2) )
+            Vec_PtrPush( vNodes, pNode2 );
+
+        // remove the current fanins
+        Abc_ObjRemoveFanins( pNode );
+        // add new fanins
+        Abc_ObjAddFanin( pNode, pNodeC );
+        Abc_ObjAddFanin( pNode, pNode2 );
+        Abc_ObjAddFanin( pNode, pNode1 );
+        // update the function to be that of MUX
+        Cudd_RecursiveDeref( dd, (DdNode *)pNode->pData );
+        pNode->pData = Cudd_bddIte( dd, dd->vars[0], dd->vars[1], dd->vars[2] );    Cudd_Ref( (DdNode *)pNode->pData );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the node should be decomposed by DSD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeIsForDsd( Abc_Obj_t * pNode )
+{
+//    DdManager * dd = pNode->pNtk->pManFunc;
+//    DdNode * bFunc, * bFunc0, * bFunc1;
+    assert( Abc_ObjIsNode(pNode) );
+//    if ( Cudd_DagSize(pNode->pData)-1 > Abc_ObjFaninNum(pNode) )
+//        return 1;
+//    return 0;
+
+/*
+    // this does not catch things like a(b+c), which should be decomposed
+    for ( bFunc = Cudd_Regular(pNode->pData); !cuddIsConstant(bFunc); )
+    {
+        bFunc0 = Cudd_Regular( cuddE(bFunc) );
+        bFunc1 = cuddT(bFunc);
+        if ( bFunc0 == b1 )
+            bFunc = bFunc1;
+        else if ( bFunc1 == b1 || bFunc0 == bFunc1 )
+            bFunc = bFunc0;
+        else
+            return 1;
+    }
+*/
+    if ( Abc_ObjFaninNum(pNode) > 2 )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determines a cofactoring variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int nVars )
+{
+	DdNode * bVar, * bCof0, * bCof1;
+	int SuppSumMin = 1000000;
+	int i, nSSD, nSSQ, iVar;
+
+//	printf( "\n\nCofactors:\n\n" );
+	iVar = -1;
+	for ( i = 0; i < nVars; i++ )
+	{
+		bVar = dd->vars[i];
+
+		bCof0 = Cudd_Cofactor( dd, bFunc, Cudd_Not(bVar) );  Cudd_Ref( bCof0 );
+		bCof1 = Cudd_Cofactor( dd, bFunc,          bVar  );  Cudd_Ref( bCof1 );
+
+//		nodD = Cudd_DagSize(bCof0);
+//		nodQ = Cudd_DagSize(bCof1);
+//		printf( "+%02d: D=%2d. Q=%2d.  ", i, nodD, nodQ );
+//		printf( "S=%2d. D=%2d.  ", nodD + nodQ, abs(nodD-nodQ) );
+
+		nSSD = Cudd_SupportSize( dd, bCof0 );
+		nSSQ = Cudd_SupportSize( dd, bCof1 );
+
+//		printf( "SD=%2d. SQ=%2d.  ", nSSD, nSSQ );
+//		printf( "S=%2d. D=%2d.  ", nSSD + nSSQ, abs(nSSD - nSSQ) );
+//		printf( "Cost=%3d. ", Cost(nodD,nodQ,nSSD,nSSQ) );
+//		printf( "\n" );
+
+		Cudd_RecursiveDeref( dd, bCof0 );
+		Cudd_RecursiveDeref( dd, bCof1 );
+
+		if ( SuppSumMin > nSSD + nSSQ )
+		{
+			 SuppSumMin = nSSD + nSSQ;
+			 iVar = i;
+		}
+	}
+    return iVar;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcEspresso.c b/abc-build/src/base/abci/abcEspresso.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcEspresso.c
@@ -0,0 +1,255 @@
+/**CFile****************************************************************
+
+  FileName    [abcEspresso.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Procedures to minimize SOPs using Espresso.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcEspresso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/espresso/espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void        Abc_NodeEspresso( Abc_Obj_t * pNode );
+static pset_family Abc_SopToEspresso( char * pSop );
+static char *      Abc_SopFromEspresso( Extra_MmFlex_t * pMan, pset_family Cover );
+static pset_family Abc_EspressoMinimize( pset_family pOnset, pset_family pDcset );
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Minimizes SOP representations using Espresso.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    assert( Abc_NtkIsLogic(pNtk) );
+    // convert the network to have SOPs
+    if ( Abc_NtkHasMapping(pNtk) )
+        Abc_NtkMapToSop(pNtk);
+    else if ( Abc_NtkHasBdd(pNtk) )
+    {
+        if ( !Abc_NtkBddToSop(pNtk, 0) )
+        {
+            printf( "Abc_NtkEspresso(): Converting to SOPs has failed.\n" );
+            return;
+        }
+    }
+    // minimize SOPs of all nodes
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        if ( i ) Abc_NodeEspresso( pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Minimizes SOP representation of one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeEspresso( Abc_Obj_t * pNode )
+{
+    extern void define_cube_size( int n );
+    pset_family Cover;
+    int fCompl;
+
+    assert( Abc_ObjIsNode(pNode) );
+    // define the cube for this node
+    define_cube_size( Abc_ObjFaninNum(pNode) );
+    // create the Espresso cover
+    fCompl = Abc_SopIsComplement( pNode->pData );
+    Cover = Abc_SopToEspresso( pNode->pData );
+    // perform minimization
+    Cover = Abc_EspressoMinimize( Cover, NULL ); // deletes also cover
+    // convert back onto the node's SOP representation
+    pNode->pData = Abc_SopFromEspresso( pNode->pNtk->pManFunc, Cover );
+    if ( fCompl ) Abc_SopComplement( pNode->pData );
+    sf_free(Cover);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts SOP in ABC into SOP representation in Espresso.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+pset_family Abc_SopToEspresso( char * pSop )
+{
+    char *      pCube;
+    pset_family Cover;
+    pset        set;
+    int         nCubes, nVars, Value, v;
+    
+    if ( pSop == NULL ) 
+        return NULL;
+    
+    nVars  = Abc_SopGetVarNum(pSop);
+    nCubes = Abc_SopGetCubeNum(pSop);
+    assert( cube.size == 2 * nVars );
+    
+    if ( Abc_SopIsConst0(pSop) ) 
+    {
+        Cover = sf_new(0, cube.size);
+        return Cover;
+    }
+    if ( Abc_SopIsConst1(pSop) ) 
+    {
+        Cover = sf_new(1, cube.size);
+        set = GETSET(Cover, Cover->count++);
+        set_copy( set, cube.fullset );
+        return Cover;
+    }
+
+    // create the cover
+    Cover = sf_new(nCubes, cube.size);
+    // fill in the cubes
+    Abc_SopForEachCube( pSop, nVars, pCube )
+    {
+        set = GETSET(Cover, Cover->count++);
+        set_copy( set, cube.fullset );
+        Abc_CubeForEachVar( pCube, Value, v )
+        {
+            if ( Value == '0' )
+                set_remove(set, 2*v+1);
+            else if ( Value == '1' )
+                set_remove(set, 2*v);
+        }
+    }
+    return Cover;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts SOP representation in Espresso into SOP in ABC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopFromEspresso( Extra_MmFlex_t * pMan, pset_family Cover )
+{
+    pset set;
+    char * pSop, * pCube;
+	int Lit, nVars, nCubes, i, k;
+
+	nVars  = Cover->sf_size/2;
+	nCubes = Cover->count;
+
+    pSop = Abc_SopStart( pMan, nCubes, nVars );
+
+	// go through the cubes
+    i = 0;
+    Abc_SopForEachCube( pSop, nVars, pCube )
+	{
+		set = GETSET(Cover, i++);
+		for ( k = 0; k < nVars; k++ )
+		{
+			Lit = GETINPUT(set, k);
+			if ( Lit == ZERO )
+                pCube[k] = '0';
+			else if ( Lit == ONE )
+                pCube[k] = '1';
+		}
+	}
+    return pSop;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Minimizes the cover using Espresso.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+pset_family Abc_EspressoMinimize( pset_family pOnset, pset_family pDcset )
+{
+    pset_family pOffset;
+    int fNewDcset, i;
+    int fSimple = 0;
+    int fSparse = 0;
+
+    if ( fSimple )
+    {
+        for ( i = 0; i < cube.num_vars; i++ )
+            pOnset = d1merge( pOnset, i );
+        pOnset = sf_contain( pOnset );
+        return pOnset;
+    }
+
+    // create the dcset
+    fNewDcset = (pDcset == NULL);
+    if ( pDcset == NULL )
+        pDcset = sf_new( 1, cube.size );
+    pDcset->wsize   = pOnset->wsize;
+    pDcset->sf_size = pOnset->sf_size;
+
+    // derive the offset
+    if ( pDcset->sf_size == 0 || pDcset->count == 0 )
+        pOffset = complement(cube1list(pOnset));
+    else
+        pOffset = complement(cube2list(pOnset, pDcset)); 
+
+    // perform minimization
+    skip_make_sparse = !fSparse;
+    pOnset = espresso( pOnset, pDcset, pOffset );
+
+    // free covers
+    sf_free( pOffset ); 
+    if ( fNewDcset )
+        sf_free( pDcset );
+    return pOnset;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcExtract.c b/abc-build/src/base/abci/abcExtract.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcExtract.c
@@ -0,0 +1,752 @@
+/**CFile****************************************************************
+
+  FileName    [abcShare.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Shared logic extraction.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcShare.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define SHARE_NUM 2
+
+typedef struct Abc_ShaMan_t_ Abc_ShaMan_t;
+struct Abc_ShaMan_t_ 
+{
+    int             nMultiSize;
+    int             fVerbose;
+    Abc_Ntk_t *     pNtk;
+    Vec_Ptr_t *     vBuckets;
+    Vec_Int_t *     vObj2Lit;
+    int             nStartCols;
+    int             nCountGates;
+    int             nFoundGates;
+};
+
+static inline word  Abc_NtkSharePack( int Lev, int Id )  { return (((word)Lev) << 32) | Id; }
+static inline int   Abc_NtkShareUnpackLev( word Num )    { return (Num >> 32);              }
+static inline int   Abc_NtkShareUnpackId( word Num )     { return Num & 0xFFFFFFFF;         }
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Working with the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_ShaMan_t * Abc_ShaManStart( Abc_Ntk_t * pNtk )
+{
+    Abc_ShaMan_t * p;
+    p = ABC_CALLOC( Abc_ShaMan_t, 1 );
+    p->pNtk      = pNtk;
+    p->vObj2Lit  = Vec_IntAlloc( 1000 );
+    return p;
+}
+void Abc_ShaManStop( Abc_ShaMan_t * p )
+{
+    Vec_Ptr_t * vBucket;
+    int i;
+    Vec_PtrForEachEntry( Vec_Ptr_t *, p->vBuckets, vBucket, i )
+        Vec_VecFree( (Vec_Vec_t *)vBucket );
+    Vec_PtrFreeP( &p->vBuckets );
+    Vec_IntFreeP( &p->vObj2Lit );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects one multi-input gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Wrd_t * Abc_NtkShareSuperXor( Abc_Obj_t * pObj, int * pfCompl, int * pCounter )
+{
+    Abc_Ntk_t * pNtk = Abc_ObjNtk(pObj);
+    Abc_Obj_t * pObjC, * pObj0, * pObj1, * pRoot = NULL;
+    Vec_Wrd_t * vSuper;
+    word Num, NumNext;
+    int i, k, fCompl = 0;
+    assert( !Abc_ObjIsComplement(pObj) );
+    assert( Abc_NodeIsExorType(pObj) );
+    // start iteration
+    vSuper = Vec_WrdAlloc( 10 );
+    Vec_WrdPush( vSuper, Abc_NtkSharePack(Abc_ObjLevel(pObj), Abc_ObjId(pObj)) );
+    while ( Vec_WrdSize(vSuper) > 0 )
+    {
+        // make sure there are no duplicates
+        Num = Vec_WrdEntry( vSuper, 0 );
+        Vec_WrdForEachEntryStart( vSuper, NumNext, i, 1 )
+        {
+            assert( Num < NumNext );
+            Num = NumNext;
+        }
+        // extract XOR gate decomposable on the topmost level
+        Vec_WrdForEachEntryReverse( vSuper, Num, i )
+        {
+            pRoot = Abc_NtkObj( pNtk, Abc_NtkShareUnpackId(Num) );
+            if ( Abc_NodeIsExorType(pRoot) )
+            {
+                Vec_WrdRemove( vSuper, Num );
+                break;
+            }
+        }
+        if ( i == -1 )
+            break;
+        // extract
+        pObjC = Abc_NodeRecognizeMux( pRoot, &pObj1, &pObj0 );
+        assert( pObj1 == Abc_ObjNot(pObj0) );
+        fCompl ^= Abc_ObjIsComplement(pObjC);  pObjC = Abc_ObjRegular(pObjC);
+        fCompl ^= Abc_ObjIsComplement(pObj0);  pObj0 = Abc_ObjRegular(pObj0);
+        Vec_WrdPushOrder( vSuper, Abc_NtkSharePack(Abc_ObjLevel(pObjC), Abc_ObjId(pObjC)) );
+        Vec_WrdPushOrder( vSuper, Abc_NtkSharePack(Abc_ObjLevel(pObj0), Abc_ObjId(pObj0)) );
+        (*pCounter)++;
+        // remove duplicates
+        k = 0;
+        Vec_WrdForEachEntry( vSuper, Num, i )
+        {
+            if ( i + 1 == Vec_WrdSize(vSuper) )
+            {
+                Vec_WrdWriteEntry( vSuper, k++, Num );
+                break;
+            }
+            NumNext = Vec_WrdEntry( vSuper, i+1 );
+            assert( Num <= NumNext );
+            if ( Num == NumNext )
+                i++;
+            else
+                Vec_WrdWriteEntry( vSuper, k++, Num );
+        }
+        Vec_WrdShrink( vSuper, k );
+    }
+    *pfCompl = fCompl;
+    Vec_WrdForEachEntry( vSuper, Num, i )
+        Vec_WrdWriteEntry( vSuper, i, Abc_NtkShareUnpackId(Num) );
+    return vSuper;
+}
+Vec_Wrd_t * Abc_NtkShareSuperAnd( Abc_Obj_t * pObj, int * pCounter )
+{
+    Abc_Ntk_t * pNtk = Abc_ObjNtk(pObj);
+    Abc_Obj_t * pObj0, * pObj1, * pRoot = NULL;
+    Vec_Wrd_t * vSuper;
+    word Num, NumNext;
+    int i, k;
+    assert( !Abc_ObjIsComplement(pObj) );
+    // start iteration
+    vSuper = Vec_WrdAlloc( 10 );
+    Vec_WrdPush( vSuper, Abc_NtkSharePack(Abc_ObjLevel(pObj), Abc_ObjToLit(pObj)) );
+    while ( Vec_WrdSize(vSuper) > 0 )
+    {
+        // make sure there are no duplicates
+        Num = Vec_WrdEntry( vSuper, 0 );
+        Vec_WrdForEachEntryStart( vSuper, NumNext, i, 1 )
+        {
+            assert( Num < NumNext );
+            Num = NumNext;
+        }
+        // extract AND gate decomposable on the topmost level
+        Vec_WrdForEachEntryReverse( vSuper, Num, i )
+        {
+            pRoot = Abc_ObjFromLit( pNtk, Abc_NtkShareUnpackId(Num) );
+            if ( !Abc_ObjIsComplement(pRoot) && Abc_ObjIsNode(pRoot) )
+            {
+                Vec_WrdRemove( vSuper, Num );
+                break;
+            }
+        }
+        if ( i == -1 )
+            break;
+        assert( Abc_ObjIsNode(pRoot) );
+        // extract
+        pObj0 = Abc_ObjChild0(pRoot);
+        pObj1 = Abc_ObjChild1(pRoot);
+        assert( Abc_ObjIsNode(Abc_ObjRegular(pObj0)) || Abc_ObjIsCi(Abc_ObjRegular(pObj0)) );
+        assert( Abc_ObjIsNode(Abc_ObjRegular(pObj1)) || Abc_ObjIsCi(Abc_ObjRegular(pObj1)) );
+        Vec_WrdPushOrder( vSuper, Abc_NtkSharePack(Abc_ObjLevel(Abc_ObjRegular(pObj0)), Abc_ObjToLit(pObj0)) );
+        Vec_WrdPushOrder( vSuper, Abc_NtkSharePack(Abc_ObjLevel(Abc_ObjRegular(pObj1)), Abc_ObjToLit(pObj1)) );
+        (*pCounter)++;
+        // remove duplicates
+        k = 0;
+        Vec_WrdForEachEntry( vSuper, Num, i )
+        {
+            if ( i + 1 == Vec_WrdSize(vSuper) )
+            {
+                Vec_WrdWriteEntry( vSuper, k++, Num );
+                break;
+            }
+            NumNext = Vec_WrdEntry( vSuper, i+1 );
+            assert( Num <= NumNext );
+            if ( Num + 1 == NumNext && (NumNext & 1) ) // pos_lit & neg_lit = 0
+            {
+                Vec_WrdClear( vSuper );
+                return vSuper;
+            }
+            if ( Num < NumNext )
+                Vec_WrdWriteEntry( vSuper, k++, Num );
+        }
+        Vec_WrdShrink( vSuper, k );
+    }
+    Vec_WrdForEachEntry( vSuper, Num, i )
+        Vec_WrdWriteEntry( vSuper, i, Abc_NtkShareUnpackId(Num) );
+    return vSuper;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates multi-input XOR representation for the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTraverseSupersXor_rec( Abc_ShaMan_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vInputs )
+{
+    if ( Abc_NodeIsTravIdCurrent( pObj ) )
+        return;
+    Abc_NodeSetTravIdCurrent( pObj );
+    if ( Abc_ObjIsCi(pObj) )
+        return;
+    assert( Abc_ObjIsNode(pObj) );
+    if ( Abc_NodeIsExorType(pObj) )
+    {
+        Vec_Wrd_t * vSuper;
+        int k, fCompl;
+        word Num;
+        vSuper = Abc_NtkShareSuperXor( pObj, &fCompl, &p->nFoundGates );
+        if ( Vec_WrdSize(vSuper) <= 1 || Vec_WrdSize(vSuper) >= p->nMultiSize )
+        {
+            Vec_WrdForEachEntry( vSuper, Num, k )
+            {
+                Vec_Int_t * vInput = (Vec_Int_t *)Vec_PtrEntry( vInputs, (int)Num );
+                if ( vInput == NULL )
+                {
+                    vInput = Vec_IntAlloc( 10 );
+                    Vec_IntPush( vInput, Abc_Var2Lit((int)Num, 0) );
+                    Vec_IntPush( vInput, Abc_ObjLevel(Abc_NtkObj(p->pNtk, (int)Num)) );
+                    assert( SHARE_NUM == Vec_IntSize(vInput) );
+                    Vec_PtrWriteEntry( vInputs, (int)Num, vInput );
+                }
+                Vec_IntPush( vInput, Vec_IntSize(p->vObj2Lit) );
+            }
+            Vec_IntPush( p->vObj2Lit, Abc_Var2Lit(Abc_ObjId(pObj), fCompl) );
+        }
+        // call recursively
+        Vec_WrdForEachEntry( vSuper, Num, k )
+            Abc_NtkTraverseSupersXor_rec( p, Abc_NtkObj(p->pNtk, (int)Num), vInputs );
+        Vec_WrdFree( vSuper );
+    }
+    else
+    {
+        Abc_NtkTraverseSupersXor_rec( p, Abc_ObjFanin0(pObj), vInputs );
+        Abc_NtkTraverseSupersXor_rec( p, Abc_ObjFanin1(pObj), vInputs );
+    }
+}
+void Abc_NtkTraverseSupersAnd_rec( Abc_ShaMan_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vInputs )
+{
+    Vec_Wrd_t * vSuper;
+    word Num;
+    int k;
+    if ( Abc_NodeIsTravIdCurrent( pObj ) )
+        return;
+    Abc_NodeSetTravIdCurrent( pObj );
+    if ( Abc_ObjIsCi(pObj) )
+        return;
+    assert( Abc_ObjIsNode(pObj) );
+    vSuper = Abc_NtkShareSuperAnd( pObj, &p->nFoundGates );
+    if ( Vec_WrdSize(vSuper) <= 1 || Vec_WrdSize(vSuper) >= p->nMultiSize )
+    {
+        Vec_WrdForEachEntry( vSuper, Num, k )
+        {
+            Vec_Int_t * vInput = (Vec_Int_t *)Vec_PtrEntry( vInputs, (int)Num );
+            if ( vInput == NULL )
+            {
+                vInput = Vec_IntAlloc( 10 );
+                Vec_IntPush( vInput, (int)Num );
+                Vec_IntPush( vInput, Abc_ObjLevel(Abc_NtkObj(p->pNtk, Abc_Lit2Var((int)Num))) );
+                assert( SHARE_NUM == Vec_IntSize(vInput) );
+                Vec_PtrWriteEntry( vInputs, (int)Num, vInput );
+            }
+            Vec_IntPush( vInput, Vec_IntSize(p->vObj2Lit) );
+        }
+        Vec_IntPush( p->vObj2Lit, Abc_ObjToLit(pObj) );
+    }
+    // call recursively
+    Vec_WrdForEachEntry( vSuper, Num, k )
+        Abc_NtkTraverseSupersAnd_rec( p, Abc_NtkObj(p->pNtk, Abc_Lit2Var((int)Num)), vInputs );
+    Vec_WrdFree( vSuper );
+}
+void Abc_NtkTraverseSupers( Abc_ShaMan_t * p, int fAnd )
+{
+    Vec_Ptr_t * vInputs;
+    Vec_Int_t * vInput;
+    Abc_Obj_t * pObj;
+    int i, nOnesMax;
+
+    // create mapping of nodes into their column vectors
+    vInputs = Vec_PtrStart( Abc_NtkObjNumMax(p->pNtk) * (1 + fAnd) );
+    Abc_NtkIncrementTravId( p->pNtk );
+    if ( fAnd )
+    {
+        Abc_NtkForEachCo( p->pNtk, pObj, i )
+            if ( Abc_ObjIsNode(Abc_ObjFanin0(pObj)) )
+                Abc_NtkTraverseSupersAnd_rec( p, Abc_ObjFanin0(pObj), vInputs );
+    }
+    else
+    {
+        Abc_NtkForEachCo( p->pNtk, pObj, i )
+            if ( Abc_ObjIsNode(Abc_ObjFanin0(pObj)) )
+                Abc_NtkTraverseSupersXor_rec( p, Abc_ObjFanin0(pObj), vInputs );
+    }
+    p->nStartCols = Vec_IntSize(p->vObj2Lit);
+
+    // find the largest number of 1s
+    nOnesMax = 0;
+    Vec_PtrForEachEntry( Vec_Int_t *, vInputs, vInput, i )
+        if ( vInput )
+            nOnesMax = Abc_MaxInt( nOnesMax, Vec_IntSize(vInput)-SHARE_NUM );
+
+    // create buckets
+    assert( p->vBuckets == NULL );
+    p->vBuckets = Vec_PtrAlloc( nOnesMax + 1 );
+    for ( i = 0; i <= nOnesMax; i++ )
+        Vec_PtrPush( p->vBuckets, Vec_PtrAlloc(10) );
+
+    // load vectors into buckets
+    Vec_PtrForEachEntry( Vec_Int_t *, vInputs, vInput, i )
+        if ( vInput )
+            Vec_PtrPush( (Vec_Ptr_t *)Vec_PtrEntry(p->vBuckets, Vec_IntSize(vInput)-SHARE_NUM), vInput );
+    Vec_PtrFree( vInputs );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSharePrint( Abc_ShaMan_t * p )
+{
+    Vec_Ptr_t * vBucket;
+    Vec_Int_t * vInput;
+    int i, k, j, ObjId;
+    char * pBuffer = ABC_ALLOC( char, Vec_IntSize(p->vObj2Lit) + 1 );
+    int * pCounters = ABC_CALLOC( int, Vec_IntSize(p->vObj2Lit) + 1 );
+    int nTotal = 0;
+    Vec_PtrForEachEntry( Vec_Ptr_t *, p->vBuckets, vBucket, i )
+    Vec_PtrForEachEntry( Vec_Int_t *, vBucket, vInput, j )
+    {
+        for ( k = 0; k < Vec_IntSize(p->vObj2Lit); k++ )
+            pBuffer[k] = '0';
+        pBuffer[k] = 0;
+
+        Vec_IntForEachEntryStart( vInput, ObjId, k, SHARE_NUM )
+        {
+            assert( ObjId < Vec_IntSize(p->vObj2Lit) );
+            pBuffer[ObjId] = '1';
+            pCounters[ObjId]++;
+        }
+        printf( "%4d%3d: %s\n", Vec_IntEntry(vInput, 0), Vec_IntEntry(vInput, 1), pBuffer );
+    }
+
+    for ( i = 0; i < Vec_IntSize(p->vObj2Lit); i++ )
+        if ( pCounters[i] > 0 )
+            printf( "%d=%d ", i, pCounters[i] ); 
+    printf( "\n" );
+
+    nTotal = 0;
+    for ( i = 0; i < p->nStartCols; i++ )
+        nTotal += pCounters[i] - 1;
+    printf( "Total = %d.  ", nTotal );
+    printf( "Gates = %d.\n", Vec_IntSize(p->vObj2Lit) - p->nStartCols + nTotal );
+
+    ABC_FREE( pCounters );
+    ABC_FREE( pBuffer );
+
+    printf( "Bucket contents: " );
+    Vec_PtrForEachEntry( Vec_Ptr_t *, p->vBuckets, vBucket, i )
+        printf( "%d ", Vec_PtrSize(vBucket) );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDumpBlif( Abc_Ntk_t * p )
+{
+    FILE * pFile;
+    Vec_Ptr_t * vSupp;
+    Abc_Obj_t * pObj;
+    int i, k;
+    pFile = fopen( "multi_and.blif", "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open output file.\n" );
+        return;
+    }
+    fprintf( pFile, ".model %s\n", "multi_and" );
+    fprintf( pFile, ".inputs" );
+    for ( i = 0; i < Abc_NtkCiNum(p); i++ )
+        fprintf( pFile, " i%d", i );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, ".outputs" );
+    for ( i = 0; i < Abc_NtkCoNum(p); i++ )
+        fprintf( pFile, " o%d", i );
+    fprintf( pFile, "\n" );
+    Abc_NtkForEachCi( p, pObj, i )
+        pObj->iTemp = i;
+    for ( i = 0; i < Abc_NtkCoNum(p); i++ )
+    {
+        pObj = Abc_NtkCo( p, i );
+        vSupp = Abc_NtkNodeSupport( p, &pObj, 1 );
+        fprintf( pFile, ".names" );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, k )
+            fprintf( pFile, " i%d", pObj->iTemp );
+        fprintf( pFile, " o%d\n", i );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, k )
+            fprintf( pFile, "1" );
+        fprintf( pFile, " 1\n" );
+        Vec_PtrFree( vSupp );
+    }
+    fprintf( pFile, ".end\n\n" );
+    fclose( pFile );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkShareFindBestMatch( Vec_Ptr_t * vBuckets, Vec_Int_t ** pvInput, Vec_Int_t ** pvInput2 )
+{
+    int nPoolSize = 40;
+    Vec_Ptr_t * vPool = Vec_PtrAlloc( nPoolSize );
+    Vec_Ptr_t * vBucket;
+    Vec_Int_t * vInput, * vInput2, * vInputBest = NULL, * vInputBest2 = NULL;
+    int i, k, Cost, CostBest = 0, Delay, DelayBest = 0;
+
+    Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vBuckets, vBucket, i )
+        Vec_PtrForEachEntry( Vec_Int_t *, vBucket, vInput, k )
+        {
+            Vec_PtrPush( vPool, vInput );
+            if ( Vec_PtrSize(vPool) == nPoolSize )
+                goto outside;
+        }
+outside:
+
+    Vec_PtrForEachEntryReverse( Vec_Int_t *, vPool, vInput, i )
+    Vec_PtrForEachEntryReverse( Vec_Int_t *, vPool, vInput2, k )
+    {
+        if ( i == k )
+            continue;
+
+        vInput->pArray += SHARE_NUM;
+        vInput2->pArray += SHARE_NUM;
+        vInput->nSize -= SHARE_NUM;
+        vInput2->nSize -= SHARE_NUM;
+
+        Cost = Vec_IntTwoCountCommon(vInput, vInput2);
+
+        vInput->pArray -= SHARE_NUM;
+        vInput2->pArray -= SHARE_NUM;
+        vInput->nSize += SHARE_NUM;
+        vInput2->nSize += SHARE_NUM;
+
+        if ( Cost < 2 )
+            continue;
+
+        Delay = Abc_MaxInt( Vec_IntEntry(vInput, 1), Vec_IntEntry(vInput2, 1) );
+
+        if ( CostBest < Cost || (CostBest == Cost && (DelayBest > Delay)) )
+        {
+            CostBest = Cost;
+            DelayBest = Delay;
+            vInputBest = vInput;
+            vInputBest2 = vInput2;
+        }
+    }
+    Vec_PtrFree( vPool );
+
+    *pvInput  = vInputBest;
+    *pvInput2 = vInputBest2;
+
+    if ( vInputBest == NULL )
+        return;
+
+    Vec_PtrRemove( (Vec_Ptr_t *)Vec_PtrEntry(vBuckets, Vec_IntSize(vInputBest)-SHARE_NUM),  (Vec_Int_t *)vInputBest ); 
+    Vec_PtrRemove( (Vec_Ptr_t *)Vec_PtrEntry(vBuckets, Vec_IntSize(vInputBest2)-SHARE_NUM), (Vec_Int_t *)vInputBest2 ); 
+}
+void Abc_NtkShareOptimize( Abc_ShaMan_t * p, int fAnd )
+{
+    Abc_Obj_t * pObj, * pObj0, * pObj1;
+    Vec_Int_t * vInput, * vInput2;
+    Vec_Int_t * vNew, * vOld1, * vOld2;
+    int i;
+    for ( i = 0; ; i++ )
+    {
+        Abc_NtkShareFindBestMatch( p->vBuckets, &vInput, &vInput2 );
+        if ( vInput == NULL )
+            break;
+
+        // create new node
+        pObj0 = Abc_ObjFromLit( p->pNtk, Vec_IntEntry(vInput,  0) );
+        pObj1 = Abc_ObjFromLit( p->pNtk, Vec_IntEntry(vInput2, 0) );
+        if ( fAnd )
+            pObj  = Abc_AigAnd( (Abc_Aig_t *)p->pNtk->pManFunc, pObj0, pObj1 );
+        else
+            pObj  = Abc_AigXor( (Abc_Aig_t *)p->pNtk->pManFunc, pObj0, pObj1 );
+        p->nCountGates++;
+
+        // save new node
+        vOld1 = Vec_IntAlloc( 16 );  Vec_IntPush( vOld1, Vec_IntEntry(vInput,  0) );  Vec_IntPush( vOld1, Vec_IntEntry(vInput,  1) );
+        vOld2 = Vec_IntAlloc( 16 );  Vec_IntPush( vOld2, Vec_IntEntry(vInput2, 0) );  Vec_IntPush( vOld2, Vec_IntEntry(vInput2, 1) );
+        vNew  = Vec_IntAlloc( 16 );  Vec_IntPush( vNew,  Abc_ObjToLit(pObj) );        Vec_IntPush( vNew, Abc_ObjLevel(Abc_ObjRegular(pObj)) );
+
+        // compute new arrays
+        vInput->pArray += SHARE_NUM;
+        vInput2->pArray += SHARE_NUM;
+        vInput->nSize -= SHARE_NUM;
+        vInput2->nSize -= SHARE_NUM;
+
+        Vec_IntTwoSplit( vInput, vInput2, vNew, vOld1, vOld2 );
+
+        vInput->pArray -= SHARE_NUM;
+        vInput2->pArray -= SHARE_NUM;
+        vInput->nSize += SHARE_NUM;
+        vInput2->nSize += SHARE_NUM;
+
+        // add to the old ones
+        Vec_IntPush( vOld1, Vec_IntSize(p->vObj2Lit) );
+        Vec_IntPush( vOld2, Vec_IntSize(p->vObj2Lit) );
+        Vec_IntPush( p->vObj2Lit, Abc_ObjToLit(pObj) );
+
+        Vec_PtrPush( (Vec_Ptr_t *)Vec_PtrEntry(p->vBuckets, Vec_IntSize(vOld1)-SHARE_NUM), vOld1 );
+        Vec_PtrPush( (Vec_Ptr_t *)Vec_PtrEntry(p->vBuckets, Vec_IntSize(vOld2)-SHARE_NUM), vOld2 );
+        Vec_PtrPush( (Vec_Ptr_t *)Vec_PtrEntry(p->vBuckets, Vec_IntSize(vNew)-SHARE_NUM), vNew );
+
+        Vec_IntFree( vInput );
+        Vec_IntFree( vInput2 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkUpdateNetwork( Abc_ShaMan_t * p, int fAnd )
+{
+    Abc_Ntk_t * pNtk;
+    Vec_Int_t * vInput, * vMap2Repl;
+    Vec_Ptr_t * vOrig, * vRepl, * vBucket;
+    Abc_Obj_t * pObj, * pNew;
+    int i, j, k, ObjId, iLit;
+    int iLitConst1 = Abc_ObjToLit( Abc_AigConst1(p->pNtk) );
+
+    vOrig = Vec_PtrAlloc( p->nStartCols );
+    vRepl = Vec_PtrAlloc( p->nStartCols );
+    for ( i = 0; i < p->nStartCols; i++ )
+    {
+        iLit = Vec_IntEntry( p->vObj2Lit, i );
+        assert( !fAnd || !Abc_LitIsCompl(iLit) );
+
+        pObj = Abc_NtkObj( p->pNtk, Abc_Lit2Var(iLit) );
+
+        if ( fAnd )
+            pNew = Abc_AigConst1(p->pNtk);
+        else
+            pNew = Abc_ObjNotCond( Abc_AigConst1(p->pNtk), !Abc_LitIsCompl(iLit) );
+
+        Vec_PtrPush( vOrig, pObj );
+        Vec_PtrPush( vRepl, pNew );
+
+        p->nCountGates--;
+    }
+
+    // go through the columns
+    Vec_PtrForEachEntry( Vec_Ptr_t *, p->vBuckets, vBucket, i )
+    Vec_PtrForEachEntry( Vec_Int_t *, vBucket, vInput, j )
+    {
+        Vec_IntForEachEntryStart( vInput, ObjId, k, SHARE_NUM )
+        {
+            assert( ObjId < Vec_IntSize(p->vObj2Lit) );
+            if ( ObjId >= p->nStartCols )
+                break;
+            assert( ObjId < p->nStartCols );
+            iLit = Vec_IntEntry( vInput, 0 );
+
+            pNew = (Abc_Obj_t *)Vec_PtrEntry( vRepl, ObjId );
+            if ( fAnd )
+                pNew = Abc_AigAnd( (Abc_Aig_t *)p->pNtk->pManFunc, pNew, Abc_ObjFromLit(p->pNtk, iLit) );
+            else
+                pNew = Abc_AigXor( (Abc_Aig_t *)p->pNtk->pManFunc, pNew, Abc_ObjFromLit(p->pNtk, iLit) );
+            Vec_PtrWriteEntry( vRepl, ObjId, pNew );
+            p->nCountGates++;
+        }
+    }
+
+    if ( p->fVerbose )
+        printf( "Total gates collected = %d.  Total gates constructed = %d.\n", p->nFoundGates, p->nCountGates );
+
+    // create map of originals
+    vMap2Repl = Vec_IntStartFull( Abc_NtkObjNumMax(p->pNtk) );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vOrig, pObj, i )
+    {
+//        printf( "Replacing %d by %d.\n", Abc_ObjId(pObj), Abc_ObjToLit((Abc_Obj_t *)Vec_PtrEntry(vRepl, i)) );
+        Vec_IntWriteEntry( vMap2Repl, Abc_ObjId(pObj), Abc_ObjToLit((Abc_Obj_t *)Vec_PtrEntry(vRepl, i)) );
+    }
+    Vec_PtrFree( vOrig );
+    Vec_PtrFree( vRepl );
+
+    // update fanin pointers
+    Abc_NtkForEachObj( p->pNtk, pObj, i )
+    {
+        if ( Abc_ObjIsCo(pObj) || Abc_ObjIsNode(pObj) )
+        {
+            iLit = Vec_IntEntry( vMap2Repl, Abc_ObjFaninId0(pObj) );
+            if ( iLit >= 0 )
+            {
+                if ( iLit == iLitConst1 && fAnd )
+                {
+                    pObj->fCompl0 ^= 1;
+                    Vec_IntWriteEntry( &pObj->vFanins, 0, Abc_Lit2Var(iLitConst1) );
+                }
+                else
+                {
+                    pObj->fCompl0 ^= Abc_LitIsCompl(iLit);
+                    Vec_IntWriteEntry( &pObj->vFanins, 0, Abc_Lit2Var(iLit) );
+                }
+            }
+        }
+        if ( Abc_ObjIsNode(pObj) )
+        {
+            iLit = Vec_IntEntry( vMap2Repl, Abc_ObjFaninId1(pObj) );
+            if ( iLit >= 0 )
+            {
+                if ( iLit == iLitConst1 && fAnd )
+                {
+                    pObj->fCompl1 ^= 1;
+                    Vec_IntWriteEntry( &pObj->vFanins, 1, Abc_Lit2Var(iLitConst1) );
+                }
+                else
+                {
+                    pObj->fCompl1 ^= Abc_LitIsCompl(iLit);
+                    Vec_IntWriteEntry( &pObj->vFanins, 1, Abc_Lit2Var(iLit) );
+                }
+            }
+        }
+    }
+    Vec_IntFree( vMap2Repl );
+
+//    pNtk = Abc_NtkRestrash( p->pNtk, 1 );
+    if ( fAnd )
+        pNtk = Abc_NtkBalance( p->pNtk, 0, 0, 1 );
+    else
+        pNtk = Abc_NtkBalanceExor( p->pNtk, 1, 0 );
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Extracts one multi-output XOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkShareXor( Abc_Ntk_t * pNtk, int nMultiSize, int fAnd, int fVerbose )
+{
+    Abc_Ntk_t * pNtkNew;
+    Abc_ShaMan_t * p;
+    assert( Abc_NtkIsStrash(pNtk) );
+//    Abc_NtkDumpBlif( pNtk );
+    p = Abc_ShaManStart( pNtk );
+    p->nMultiSize = nMultiSize;
+    p->fVerbose   = fVerbose;
+    Abc_NtkTraverseSupers( p, fAnd );
+    if ( p->nStartCols < 2 )
+    {
+        Abc_ShaManStop( p );
+        return Abc_NtkDup( pNtk );
+    }
+    if ( fVerbose )
+        Abc_NtkSharePrint( p );
+    Abc_NtkShareOptimize( p, fAnd );
+    if ( fVerbose )
+        Abc_NtkSharePrint( p );
+    pNtkNew = Abc_NtkUpdateNetwork( p, fAnd );
+    Abc_ShaManStop( p );
+    return pNtkNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcFlop.c b/abc-build/src/base/abci/abcFlop.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcFlop.c
@@ -0,0 +1,40 @@
+/**CFile****************************************************************
+
+  FileName    [abcFlop.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Flop dependency visualization.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcFlop.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcFpga.c b/abc-build/src/base/abci/abcFpga.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcFpga.c
@@ -0,0 +1,285 @@
+/**CFile****************************************************************
+
+  FileName    [abcFpga.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Interface with the FPGA mapping package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcFpga.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "map/fpga/fpgaInt.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fLatchPaths, int fVerbose );
+static Abc_Ntk_t *  Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk );
+static Abc_Obj_t *  Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNodeFpga );
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Interface with the FPGA mapping package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int fSwitching, int fLatchPaths, int fVerbose )
+{
+    int fShowSwitching = 1;
+    Abc_Ntk_t * pNtkNew;
+    Fpga_Man_t * pMan;
+    Vec_Int_t * vSwitching = NULL;
+    float * pSwitching = NULL;
+    int Num;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    // print a warning about choice nodes
+    if ( (Num = Abc_NtkGetChoiceNum( pNtk )) )
+        Abc_Print( 0, "Performing LUT mapping with %d choices.\n", Num );
+
+    // compute switching activity
+    fShowSwitching |= fSwitching;
+    if ( fShowSwitching )
+    {
+        extern Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns );
+        vSwitching = Sim_NtkComputeSwitching( pNtk, 4096 );
+        pSwitching = (float *)vSwitching->pArray;
+    }
+
+    // perform FPGA mapping
+    pMan = Abc_NtkToFpga( pNtk, fRecovery, pSwitching, fLatchPaths, fVerbose );    
+    if ( pSwitching ) { assert(vSwitching); Vec_IntFree( vSwitching ); }
+    if ( pMan == NULL )
+        return NULL;
+    Fpga_ManSetSwitching( pMan, fSwitching );
+    Fpga_ManSetLatchPaths( pMan, fLatchPaths );
+    Fpga_ManSetLatchNum( pMan, Abc_NtkLatchNum(pNtk) );
+    Fpga_ManSetDelayTarget( pMan, DelayTarget );
+    if ( !Fpga_Mapping( pMan ) )
+    {
+        Fpga_ManFree( pMan );
+        return NULL;
+    }
+
+    // transform the result of mapping into a BDD network
+    pNtkNew = Abc_NtkFromFpga( pMan, pNtk );
+    if ( pNtkNew == NULL )
+        return NULL;
+    Fpga_ManFree( pMan );
+
+    // make the network minimum base
+    Abc_NtkMinimumBase( pNtkNew );
+
+    if ( pNtk->pExdc )
+        pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkFpga: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Load the network into FPGA manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fLatchPaths, int fVerbose )
+{
+    Fpga_Man_t * pMan;
+    ProgressBar * pProgress;
+    Fpga_Node_t * pNodeFpga;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNode, * pFanin, * pPrev;
+    float * pfArrivals;
+    int i;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    // start the mapping manager and set its parameters
+    pMan = Fpga_ManCreate( Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), fVerbose );
+    if ( pMan == NULL )
+        return NULL;
+    Fpga_ManSetAreaRecovery( pMan, fRecovery );
+    Fpga_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) );
+    pfArrivals = Abc_NtkGetCiArrivalFloats(pNtk);
+    if ( fLatchPaths )
+    {
+        for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ )
+            pfArrivals[i] = -FPGA_FLOAT_LARGE;
+    }
+    Fpga_ManSetInputArrivals( pMan, pfArrivals );
+
+    // create PIs and remember them in the old nodes
+    Abc_NtkCleanCopy( pNtk );
+    Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Fpga_ManReadConst1(pMan);
+    Abc_NtkForEachCi( pNtk, pNode, i )
+    {
+        pNodeFpga = Fpga_ManReadInputs(pMan)[i];
+        pNode->pCopy = (Abc_Obj_t *)pNodeFpga;
+        if ( pSwitching )
+            Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] );
+    }
+
+    // load the AIG into the mapper
+    vNodes = Abc_AigDfs( pNtk, 0, 0 );
+    pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        // add the node to the mapper
+        pNodeFpga = Fpga_NodeAnd( pMan, 
+            Fpga_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ),
+            Fpga_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) );
+        assert( pNode->pCopy == NULL );
+        // remember the node
+        pNode->pCopy = (Abc_Obj_t *)pNodeFpga;
+        if ( pSwitching )
+            Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] );
+        // set up the choice node
+        if ( Abc_AigNodeIsChoice( pNode ) )
+            for ( pPrev = pNode, pFanin = (Abc_Obj_t *)pNode->pData; pFanin; pPrev = pFanin, pFanin = (Abc_Obj_t *)pFanin->pData )
+            {
+                Fpga_NodeSetNextE( (Fpga_Node_t *)pPrev->pCopy, (Fpga_Node_t *)pFanin->pCopy );
+                Fpga_NodeSetRepr( (Fpga_Node_t *)pFanin->pCopy, (Fpga_Node_t *)pNode->pCopy );
+            }
+    }
+    Extra_ProgressBarStop( pProgress );
+    Vec_PtrFree( vNodes );
+
+    // set the primary outputs without copying the phase
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        Fpga_ManReadOutputs(pMan)[i] = (Fpga_Node_t *)Abc_ObjFanin0(pNode)->pCopy;
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the mapped network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+    ProgressBar * pProgress;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pNode, * pNodeNew;
+    int i, nDupGates;
+    // create the new network
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
+    // make the mapper point to the new network
+    Fpga_CutsCleanSign( pMan );
+    Fpga_ManCleanData0( pMan );
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        Fpga_NodeSetData0( Fpga_ManReadInputs(pMan)[i], (char *)pNode->pCopy );
+    // set the constant node
+//    if ( Fpga_NodeReadRefs(Fpga_ManReadConst1(pMan)) > 0 )
+        Fpga_NodeSetData0( Fpga_ManReadConst1(pMan), (char *)Abc_NtkCreateNodeConst1(pNtkNew) );
+    // process the nodes in topological order
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        pNodeNew = Abc_NodeFromFpga_rec( pNtkNew, Fpga_ManReadOutputs(pMan)[i] );
+        assert( !Abc_ObjIsComplement(pNodeNew) );
+        Abc_ObjFanin0(pNode)->pCopy = pNodeNew;
+    }
+    Extra_ProgressBarStop( pProgress );
+    // finalize the new network
+    Abc_NtkFinalize( pNtk, pNtkNew );
+    // remove the constant node if not used
+    pNodeNew = (Abc_Obj_t *)Fpga_NodeReadData0(Fpga_ManReadConst1(pMan));
+    if ( Abc_ObjFanoutNum(pNodeNew) == 0 )
+        Abc_NtkDeleteObj( pNodeNew );
+    // decouple the PO driver nodes to reduce the number of levels
+    nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 );
+    if ( nDupGates && Fpga_ManReadVerbose(pMan) )
+        printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive one node after FPGA mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNodeFpga )
+{
+    Fpga_Cut_t * pCutBest;
+    Fpga_Node_t ** ppLeaves; 
+    Abc_Obj_t * pNodeNew;
+    int i, nLeaves;
+    assert( !Fpga_IsComplement(pNodeFpga) );
+    // return if the result if known
+    pNodeNew = (Abc_Obj_t *)Fpga_NodeReadData0( pNodeFpga );
+    if ( pNodeNew )
+        return pNodeNew;
+    assert( Fpga_NodeIsAnd(pNodeFpga) );
+    // get the parameters of the best cut
+    pCutBest = Fpga_NodeReadCutBest( pNodeFpga );
+    ppLeaves = Fpga_CutReadLeaves( pCutBest );
+    nLeaves  = Fpga_CutReadLeavesNum( pCutBest ); 
+    // create a new node 
+    pNodeNew = Abc_NtkCreateNode( pNtkNew );
+    for ( i = 0; i < nLeaves; i++ )
+        Abc_ObjAddFanin( pNodeNew, Abc_NodeFromFpga_rec(pNtkNew, ppLeaves[i]) );
+    // derive the function of this node
+    pNodeNew->pData = Fpga_TruthsCutBdd( pNtkNew->pManFunc, pCutBest );   Cudd_Ref( (DdNode *)pNodeNew->pData );
+    Fpga_NodeSetData0( pNodeFpga, (char *)pNodeNew );
+    return pNodeNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcFpgaFast.c b/abc-build/src/base/abci/abcFpgaFast.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcFpgaFast.c
@@ -0,0 +1,195 @@
+/**CFile****************************************************************
+
+  FileName    [abcFpgaFast.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Fast FPGA mapper.]
+
+  Author      [Sungmin Cho]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcFpgaFast.c,v 1.00 2006/09/02 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "aig/ivy/ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc );
+
+static Abc_Ntk_t * Ivy_ManFpgaToAbc( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan );
+static Abc_Obj_t * Ivy_ManToAbcFast_rec( Abc_Ntk_t * pNtkNew, Ivy_Man_t * pMan, Ivy_Obj_t * pObjIvy, Vec_Int_t * vNodes );
+
+static inline void        Abc_ObjSetIvy2Abc( Ivy_Man_t * p, int IvyId, Abc_Obj_t * pObjAbc ) {  assert(Vec_PtrEntry((Vec_Ptr_t *)p->pCopy, IvyId) == NULL); assert(!Abc_ObjIsComplement(pObjAbc)); Vec_PtrWriteEntry( (Vec_Ptr_t *)p->pCopy, IvyId, pObjAbc );  }
+static inline Abc_Obj_t * Abc_ObjGetIvy2Abc( Ivy_Man_t * p, int IvyId )                      {  return (Abc_Obj_t *)Vec_PtrEntry( (Vec_Ptr_t *)p->pCopy, IvyId );         }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fast FPGA mapping of the network.]
+
+  Description [Takes the AIG to be mapped, the LUT size, and verbosity
+  flag. Produces the new network by fast FPGA mapping of the current 
+  network. If the current network in ABC in not an AIG, the user should 
+  run command "strash" to make sure that the current network into an AIG 
+  before calling this procedure.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFpgaFast( Abc_Ntk_t * pNtk, int nLutSize, int fRecovery, int fVerbose )
+{
+    Ivy_Man_t * pMan;
+    Abc_Ntk_t * pNtkNew;
+    // make sure the network is an AIG
+    assert( Abc_NtkIsStrash(pNtk) );
+    // convert the network into the AIG
+    pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+    // perform fast FPGA mapping
+    Ivy_FastMapPerform( pMan, nLutSize, fRecovery, fVerbose );
+    // convert back into the ABC network
+    pNtkNew = Ivy_ManFpgaToAbc( pNtk, pMan );
+    Ivy_FastMapStop( pMan );
+    Ivy_ManStop( pMan );  
+    // make sure that the final network passes the test
+    if ( pNtkNew != NULL && !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkFastMap: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs the ABC network after mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Ivy_ManFpgaToAbc( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan )
+{
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObjAbc, * pObj;
+    Ivy_Obj_t * pObjIvy;
+    Vec_Int_t * vNodes;
+    int i;
+    // start mapping from Ivy into Abc
+    pMan->pCopy = Vec_PtrStart( Ivy_ManObjIdMax(pMan) + 1 );
+    // start the new ABC network
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG );
+    // transfer the pointers to the basic nodes
+    Abc_ObjSetIvy2Abc( pMan, Ivy_ManConst1(pMan)->Id, Abc_NtkCreateNodeConst1(pNtkNew) );
+    Abc_NtkForEachCi( pNtkNew, pObjAbc, i )
+        Abc_ObjSetIvy2Abc( pMan, Ivy_ManPi(pMan, i)->Id, pObjAbc ); 
+    // recursively construct the network
+    vNodes = Vec_IntAlloc( 100 );
+    Ivy_ManForEachPo( pMan, pObjIvy, i )
+    {
+        // get the new ABC node corresponding to the old fanin of the PO in IVY
+        pObjAbc = Ivy_ManToAbcFast_rec( pNtkNew, pMan, Ivy_ObjFanin0(pObjIvy), vNodes );
+        // consider the case of complemented fanin of the PO
+        if ( Ivy_ObjFaninC0(pObjIvy) ) // complement
+        {
+            if ( Abc_ObjIsCi(pObjAbc) )
+                pObjAbc = Abc_NtkCreateNodeInv( pNtkNew, pObjAbc );
+            else
+            {
+                // clone the node
+                pObj = Abc_NtkCloneObj( pObjAbc );
+                // set complemented functions
+                pObj->pData = Hop_Not( (Hop_Obj_t *)pObjAbc->pData );
+                // return the new node
+                pObjAbc = pObj;
+            }
+        }
+        Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjAbc );
+    }
+    Vec_IntFree( vNodes );
+    Vec_PtrFree( (Vec_Ptr_t *)pMan->pCopy ); 
+    pMan->pCopy = NULL;
+    // remove dangling nodes
+    Abc_NtkCleanup( pNtkNew, 0 );
+    // fix CIs feeding directly into COs
+    Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively construct the new node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Ivy_ManToAbcFast_rec( Abc_Ntk_t * pNtkNew, Ivy_Man_t * pMan, Ivy_Obj_t * pObjIvy, Vec_Int_t * vNodes )
+{
+    Vec_Int_t Supp, * vSupp = &Supp;
+    Abc_Obj_t * pObjAbc, * pFaninAbc;
+    Ivy_Obj_t * pNodeIvy;
+    int i, Entry;
+    // skip the node if it is a constant or already processed
+    pObjAbc = Abc_ObjGetIvy2Abc( pMan, pObjIvy->Id );
+    if ( pObjAbc )
+        return pObjAbc;
+    assert( Ivy_ObjIsAnd(pObjIvy) || Ivy_ObjIsExor(pObjIvy) );
+    // get the support of K-LUT
+    Ivy_FastMapReadSupp( pMan, pObjIvy, vSupp );
+    // create new ABC node and its fanins
+    pObjAbc = Abc_NtkCreateNode( pNtkNew );
+    Vec_IntForEachEntry( vSupp, Entry, i )
+    {
+        pFaninAbc = Ivy_ManToAbcFast_rec( pNtkNew, pMan, Ivy_ManObj(pMan, Entry), vNodes );
+        Abc_ObjAddFanin( pObjAbc, pFaninAbc );
+    }
+    // collect the nodes used in the cut
+    Ivy_ManCollectCut( pMan, pObjIvy, vSupp, vNodes );
+    // create the local function
+    Ivy_ManForEachNodeVec( pMan, vNodes, pNodeIvy, i )
+    {
+        if ( i < Vec_IntSize(vSupp) )
+            pNodeIvy->pEquiv = (Ivy_Obj_t *)Hop_IthVar( (Hop_Man_t *)pNtkNew->pManFunc, i );
+        else
+            pNodeIvy->pEquiv = (Ivy_Obj_t *)Hop_And( (Hop_Man_t *)pNtkNew->pManFunc, (Hop_Obj_t *)Ivy_ObjChild0Equiv(pNodeIvy), (Hop_Obj_t *)Ivy_ObjChild1Equiv(pNodeIvy) );
+    }
+    // set the local function
+    pObjAbc->pData = (Abc_Obj_t *)pObjIvy->pEquiv;
+    // set the node
+    Abc_ObjSetIvy2Abc( pMan, pObjIvy->Id, pObjAbc ); 
+    return pObjAbc;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcFraig.c b/abc-build/src/base/abci/abcFraig.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcFraig.c
@@ -0,0 +1,812 @@
+/**CFile****************************************************************
+
+  FileName    [abcFraig.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Procedures interfacing with the FRAIG package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcFraig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "proof/fraig/fraig.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern Abc_Ntk_t *    Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
+static Abc_Ntk_t *    Abc_NtkFromFraig2( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
+static Abc_Obj_t *    Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFraig );
+static void           Abc_NtkFromFraig2_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vNodeReprs );
+extern Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtkMain, Abc_Ntk_t * pNtkExdc );
+static void           Abc_NtkFraigRemapUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
+
+static int            Abc_NtkFraigTrustCheck( Abc_Ntk_t * pNtk );
+static void           Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
+static Abc_Obj_t *    Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode );
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Interfaces the network with the FRAIG package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc )
+{
+    Fraig_Params_t * pPars = (Fraig_Params_t *)pParams;
+    Abc_Ntk_t * pNtkNew;
+    Fraig_Man_t * pMan; 
+    // check if EXDC is present
+    if ( fExdc && pNtk->pExdc == NULL )
+        fExdc = 0, printf( "Warning: Networks has no EXDC.\n" );
+    // perform fraiging
+    pMan = (Fraig_Man_t *)Abc_NtkToFraig( pNtk, pParams, fAllNodes, fExdc ); 
+    // add algebraic choices
+//    if ( pPars->fChoicing )
+//        Fraig_ManAddChoices( pMan, 0, 6 );
+    // prove the miter if asked to
+    if ( pPars->fTryProve )
+        Fraig_ManProveMiter( pMan );
+    // reconstruct FRAIG in the new network
+    if ( fExdc ) 
+        pNtkNew = Abc_NtkFromFraig2( pMan, pNtk );
+    else
+        pNtkNew = Abc_NtkFromFraig( pMan, pNtk );
+    Fraig_ManFree( pMan );
+    if ( pNtk->pExdc )
+        pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkFraig: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the strashed network into FRAIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Abc_NtkToFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc )
+{
+    int fInternal = ((Fraig_Params_t *)pParams)->fInternal;
+    Fraig_Man_t * pMan;
+    ProgressBar * pProgress = NULL;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNode;
+    int i;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    // create the FRAIG manager
+    pMan = Fraig_ManCreate( (Fraig_Params_t *)pParams );
+
+    // map the constant node
+    Abc_NtkCleanCopy( pNtk );
+    Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Fraig_ManReadConst1(pMan);
+    // create PIs and remember them in the old nodes
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        pNode->pCopy = (Abc_Obj_t *)Fraig_ManReadIthVar(pMan, i);
+ 
+    // perform strashing
+    vNodes = Abc_AigDfs( pNtk, fAllNodes, 0 );
+    if ( !fInternal )
+        pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( Abc_ObjFaninNum(pNode) == 0 )
+            continue;
+        if ( pProgress ) 
+            Extra_ProgressBarUpdate( pProgress, i, NULL );
+        pNode->pCopy = (Abc_Obj_t *)Fraig_NodeAnd( pMan, 
+                Fraig_NotCond( Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) ),
+                Fraig_NotCond( Abc_ObjFanin1(pNode)->pCopy, (int)Abc_ObjFaninC1(pNode) ) );
+    }
+    if ( pProgress )
+        Extra_ProgressBarStop( pProgress );
+    Vec_PtrFree( vNodes );
+
+    // use EXDC to change the mapping of nodes into FRAIG nodes
+    if ( fExdc )
+        Abc_NtkFraigRemapUsingExdc( pMan, pNtk );
+
+    // set the primary outputs
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        Fraig_ManSetPo( pMan, (Fraig_Node_t *)Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ) );
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives EXDC node for the given network.]
+
+  Description [Assumes that EXDCs of all POs are the same.
+  Returns the EXDC of the first PO.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtkMain, Abc_Ntk_t * pNtkExdc )
+{
+    Abc_Ntk_t * pNtkStrash;
+    Abc_Obj_t * pObj;
+    Fraig_Node_t * gResult;
+    char ** ppNames;
+    int i, k;
+    // strash the EXDC network
+    pNtkStrash = Abc_NtkStrash( pNtkExdc, 0, 0, 0 );
+    Abc_NtkCleanCopy( pNtkStrash );
+    Abc_AigConst1(pNtkStrash)->pCopy = (Abc_Obj_t *)Fraig_ManReadConst1(pMan);
+    // set the mapping of the PI nodes
+    ppNames = Abc_NtkCollectCioNames( pNtkMain, 0 );
+    Abc_NtkForEachCi( pNtkStrash, pObj, i )
+    {
+        for ( k = 0; k < Abc_NtkCiNum(pNtkMain); k++ )
+            if ( strcmp( Abc_ObjName(pObj), ppNames[k] ) == 0 )
+            {
+                pObj->pCopy = (Abc_Obj_t *)Fraig_ManReadIthVar(pMan, k);
+                break;
+            }
+        assert( pObj->pCopy != NULL );
+    }
+    ABC_FREE( ppNames );
+    // build FRAIG for each node
+    Abc_AigForEachAnd( pNtkStrash, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)Fraig_NodeAnd( pMan, 
+                Fraig_NotCond( Abc_ObjFanin0(pObj)->pCopy, (int)Abc_ObjFaninC0(pObj) ),
+                Fraig_NotCond( Abc_ObjFanin1(pObj)->pCopy, (int)Abc_ObjFaninC1(pObj) ) );
+    // get the EXDC to be returned
+    pObj = Abc_NtkPo( pNtkStrash, 0 );
+    gResult = Fraig_NotCond( Abc_ObjFanin0(pObj)->pCopy, (int)Abc_ObjFaninC0(pObj) );
+    Abc_NtkDelete( pNtkStrash );
+    return gResult;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Changes mapping of the old nodes into FRAIG nodes using EXDC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFraigRemapUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+    Fraig_Node_t * gNodeNew, * gNodeExdc;
+    stmm_table * tTable;
+    stmm_generator * gen;
+    Abc_Obj_t * pNode, * pNodeBest;
+    Abc_Obj_t * pClass, ** ppSlot;
+    Vec_Ptr_t * vNexts;
+    int i;
+
+    // get the global don't-cares
+    assert( pNtk->pExdc );
+    gNodeExdc = Abc_NtkToFraigExdc( pMan, pNtk, pNtk->pExdc );
+
+    // save the next pointers
+    vNexts = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        Vec_PtrWriteEntry( vNexts, pNode->Id, pNode->pNext );
+
+    // find the classes of AIG nodes which have FRAIG nodes assigned
+    Abc_NtkCleanNext( pNtk );
+    tTable = stmm_init_table(stmm_ptrcmp,stmm_ptrhash);
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        if ( pNode->pCopy )
+        {
+            gNodeNew = Fraig_NodeAnd( pMan, (Fraig_Node_t *)pNode->pCopy, Fraig_Not(gNodeExdc) );
+            if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(gNodeNew), (char ***)&ppSlot ) )
+                *ppSlot = NULL;
+            pNode->pNext = *ppSlot;
+            *ppSlot = pNode;
+        }
+
+    // for reach non-trival class, find the node with minimum level, and replace other nodes by it
+    Abc_AigSetNodePhases( pNtk );
+    stmm_foreach_item( tTable, gen, (char **)&gNodeNew, (char **)&pClass )
+    {
+        if ( pClass->pNext == NULL )
+            continue;
+        // find the node with minimum level
+        pNodeBest = pClass;
+        for ( pNode = pClass->pNext; pNode; pNode = pNode->pNext )
+            if ( pNodeBest->Level > pNode->Level )
+                 pNodeBest = pNode;
+        // remap the class nodes
+        for ( pNode = pClass; pNode; pNode = pNode->pNext )
+            pNode->pCopy = Abc_ObjNotCond( pNodeBest->pCopy, pNode->fPhase ^ pNodeBest->fPhase );
+    }
+    stmm_free_table( tTable );
+
+    // restore the next pointers
+    Abc_NtkCleanNext( pNtk );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        pNode->pNext = (Abc_Obj_t *)Vec_PtrEntry( vNexts, pNode->Id );
+    Vec_PtrFree( vNexts );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms FRAIG into strashed network with choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+    ProgressBar * pProgress;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pNode, * pNodeNew;
+    int i;
+    // create the new network
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+    // make the mapper point to the new network
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        Fraig_NodeSetData1( Fraig_ManReadIthVar(pMan, i), (Fraig_Node_t *)pNode->pCopy );
+    // set the constant node
+    Fraig_NodeSetData1( Fraig_ManReadConst1(pMan), (Fraig_Node_t *)Abc_AigConst1(pNtkNew) );
+    // process the nodes in topological order
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        pNodeNew = Abc_NodeFromFraig_rec( pNtkNew, Fraig_ManReadOutputs(pMan)[i] );
+        Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+    }
+    Extra_ProgressBarStop( pProgress );
+    Abc_NtkReassignIds( pNtkNew );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms into AIG one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFraig )
+{
+    Abc_Obj_t * pRes, * pRes0, * pRes1, * pResMin, * pResCur;
+    Fraig_Node_t * pNodeTemp, * pNodeFraigR = Fraig_Regular(pNodeFraig);
+    void ** ppTail;
+    // check if the node was already considered
+    if ( (pRes = (Abc_Obj_t *)Fraig_NodeReadData1(pNodeFraigR)) )
+        return Abc_ObjNotCond( pRes, Fraig_IsComplement(pNodeFraig) );
+    // solve the children
+    pRes0 = Abc_NodeFromFraig_rec( pNtkNew, Fraig_NodeReadOne(pNodeFraigR) );
+    pRes1 = Abc_NodeFromFraig_rec( pNtkNew, Fraig_NodeReadTwo(pNodeFraigR) );
+    // derive the new node
+    pRes = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pRes0, pRes1 );
+    pRes->fPhase = Fraig_NodeReadSimInv( pNodeFraigR );
+    // if the node has an equivalence class, find its representative
+    if ( Fraig_NodeReadRepr(pNodeFraigR) == NULL && Fraig_NodeReadNextE(pNodeFraigR) != NULL )
+    {
+        // go through the FRAIG nodes belonging to this equivalence class
+        // and find the representative node (the node with the smallest level)
+        pResMin = pRes;
+        for ( pNodeTemp = Fraig_NodeReadNextE(pNodeFraigR); pNodeTemp; pNodeTemp = Fraig_NodeReadNextE(pNodeTemp) )
+        {
+            assert( Fraig_NodeReadData1(pNodeTemp) == NULL );
+            pResCur = Abc_NodeFromFraig_rec( pNtkNew, pNodeTemp );
+            if ( pResMin->Level > pResCur->Level )
+                pResMin = pResCur;
+        }
+        // link the nodes in such a way that representative goes first
+        ppTail = &pResMin->pData;
+        if ( pRes != pResMin )
+        {
+            *ppTail = pRes;
+            ppTail = &pRes->pData;
+        }
+        for ( pNodeTemp = Fraig_NodeReadNextE(pNodeFraigR); pNodeTemp; pNodeTemp = Fraig_NodeReadNextE(pNodeTemp) )
+        {
+            pResCur = (Abc_Obj_t *)Fraig_NodeReadData1(pNodeTemp);
+            assert( pResCur );
+            if ( pResMin == pResCur )
+                continue;
+            *ppTail = pResCur;
+            ppTail = &pResCur->pData;
+        }
+        assert( *ppTail == NULL );
+
+        // update the phase of the node
+        pRes = Abc_ObjNotCond( pResMin, (pRes->fPhase ^ pResMin->fPhase) );
+    }
+    Fraig_NodeSetData1( pNodeFraigR, (Fraig_Node_t *)pRes );
+    return Abc_ObjNotCond( pRes, Fraig_IsComplement(pNodeFraig) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms FRAIG into strashed network without choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromFraig2( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+    ProgressBar * pProgress;
+    stmm_table * tTable;
+    Vec_Ptr_t * vNodeReprs;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pNode, * pRepr, ** ppSlot;
+    int i;
+
+    // map the nodes into their lowest level representives
+    tTable = stmm_init_table(stmm_ptrcmp,stmm_ptrhash);
+    pNode = Abc_AigConst1(pNtk);
+    if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) )
+        *ppSlot = pNode;
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) )
+            *ppSlot = pNode;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        if ( pNode->pCopy )
+        {
+            if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) )
+                *ppSlot = pNode;
+            else if ( (*ppSlot)->Level > pNode->Level )
+                *ppSlot = pNode;
+        }
+    // save representatives for each node
+    vNodeReprs = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        if ( pNode->pCopy )
+        {           
+            if ( !stmm_lookup( tTable, (char *)Fraig_Regular(pNode->pCopy), (char **)&pRepr ) )
+                assert( 0 );
+            if ( pNode != pRepr )
+                Vec_PtrWriteEntry( vNodeReprs, pNode->Id, pRepr );
+        }
+    stmm_free_table( tTable );
+
+    // create the new network
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+
+    // perform strashing
+    Abc_AigSetNodePhases( pNtk );
+    Abc_NtkIncrementTravId( pNtk );
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin0(pNode), vNodeReprs );
+    }
+    Extra_ProgressBarStop( pProgress );
+    Vec_PtrFree( vNodeReprs );
+
+    // finalize the network
+    Abc_NtkFinalize( pNtk, pNtkNew );
+    return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms into AIG one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFromFraig2_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vNodeReprs )
+{
+    Abc_Obj_t * pRepr;
+    // skip the PIs and constants
+    if ( Abc_ObjFaninNum(pNode) < 2 )
+        return;
+    // if this node is already visited, skip
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return;
+    // mark the node as visited
+    Abc_NodeSetTravIdCurrent( pNode );
+    assert( Abc_ObjIsNode( pNode ) );
+    // get the node's representative
+    if ( (pRepr = (Abc_Obj_t *)Vec_PtrEntry(vNodeReprs, pNode->Id)) )
+    {
+        Abc_NtkFromFraig2_rec( pNtkNew, pRepr, vNodeReprs );
+        pNode->pCopy = Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pNode->fPhase );
+        return;
+    }
+    Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin0(pNode), vNodeReprs );
+    Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin1(pNode), vNodeReprs );
+    pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Interfaces the network with the FRAIG package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFraigTrust( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew;
+
+    if ( !Abc_NtkIsSopLogic(pNtk) )
+    {
+        printf( "Abc_NtkFraigTrust: Trust mode works for netlists and logic SOP networks.\n" );
+        return NULL;
+    }
+
+    if ( !Abc_NtkFraigTrustCheck(pNtk) )
+    {
+        printf( "Abc_NtkFraigTrust: The network does not look like an AIG with choice nodes.\n" );
+        return NULL;
+    }
+    
+    // perform strashing
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+    Abc_NtkFraigTrustOne( pNtk, pNtkNew );
+    Abc_NtkFinalize( pNtk, pNtkNew );
+    Abc_NtkReassignIds( pNtkNew );
+
+    // print a warning about choice nodes
+    printf( "Warning: The resulting AIG contains %d choice nodes.\n", Abc_NtkGetChoiceNum( pNtkNew ) );
+
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkFraigTrust: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks whether the node can be processed in the trust mode.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkFraigTrustCheck( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, nFanins;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        nFanins = Abc_ObjFaninNum(pNode);
+        if ( nFanins < 2 )
+            continue;
+        if ( nFanins == 2 && Abc_SopIsAndType((char *)pNode->pData) )
+            continue;
+        if ( !Abc_SopIsOrType((char *)pNode->pData) )
+            return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Interfaces the network with the FRAIG package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
+{
+    ProgressBar * pProgress;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNode, * pNodeNew, * pObj;
+    int i;
+
+    // perform strashing
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        // get the node
+        assert( Abc_ObjIsNode(pNode) );
+         // strash the node
+        pNodeNew = Abc_NodeFraigTrust( pNtkNew, pNode );
+        // get the old object
+        if ( Abc_NtkIsNetlist(pNtk) )
+            pObj = Abc_ObjFanout0( pNode ); // the fanout net 
+        else 
+            pObj = pNode; // the node itself
+        // make sure the node is not yet strashed
+        assert( pObj->pCopy == NULL );
+        // mark the old object with the new AIG node
+        pObj->pCopy = pNodeNew;
+    }
+    Vec_PtrFree( vNodes );
+    Extra_ProgressBarStop( pProgress );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms one node into a FRAIG in the trust mode.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pSum, * pFanin;
+    void ** ppTail;
+    int i, nFanins, fCompl;
+
+    assert( Abc_ObjIsNode(pNode) );
+    // get the number of node's fanins
+    nFanins = Abc_ObjFaninNum( pNode );
+    assert( nFanins == Abc_SopGetVarNum((char *)pNode->pData) );
+    // check if it is a constant
+    if ( nFanins == 0 )
+        return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Abc_SopIsConst0((char *)pNode->pData) );
+    if ( nFanins == 1 )
+        return Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_SopIsInv((char *)pNode->pData) );
+    if ( nFanins == 2 && Abc_SopIsAndType((char *)pNode->pData) )
+        return Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, 
+            Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, !Abc_SopGetIthCareLit((char *)pNode->pData,0) ),
+            Abc_ObjNotCond( Abc_ObjFanin1(pNode)->pCopy, !Abc_SopGetIthCareLit((char *)pNode->pData,1) )  );
+    assert( Abc_SopIsOrType((char *)pNode->pData) );
+    fCompl = Abc_SopGetIthCareLit((char *)pNode->pData,0);
+    // get the root of the choice node (the first fanin)
+    pSum = Abc_ObjFanin0(pNode)->pCopy;
+    // connect other fanins
+    ppTail = &pSum->pData;
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        if ( i == 0 )
+            continue;
+        *ppTail = pFanin->pCopy;
+        ppTail = &pFanin->pCopy->pData;
+        // set the complemented bit of this cut
+        if ( fCompl ^ Abc_SopGetIthCareLit((char *)pNode->pData, i) )
+            pFanin->pCopy->fPhase = 1;
+    }
+    assert( *ppTail == NULL );
+    return pSum;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Interfaces the network with the FRAIG package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkFraigStore( Abc_Ntk_t * pNtkAdd )
+{
+    Vec_Ptr_t * vStore;
+    Abc_Ntk_t * pNtk;
+    // create the network to be stored
+    pNtk = Abc_NtkStrash( pNtkAdd, 0, 0, 0 );
+    if ( pNtk == NULL )
+    {
+        printf( "Abc_NtkFraigStore: Initial strashing has failed.\n" );
+        return 0;
+    }
+    // get the network currently stored
+    vStore = Abc_FrameReadStore();
+    if ( Vec_PtrSize(vStore) > 0 )
+    {
+        // check that the networks have the same PIs
+        // reorder PIs of pNtk2 according to pNtk1
+        if ( !Abc_NtkCompareSignals( pNtk, (Abc_Ntk_t *)Vec_PtrEntry(vStore, 0), 1, 1 ) )
+        {
+            printf( "Trying to store the network with different primary inputs.\n" );
+            printf( "The previously stored networks are deleted and this one is added.\n" );
+            Abc_NtkFraigStoreClean();
+        }
+    }
+    Vec_PtrPush( vStore, pNtk );
+//    printf( "The number of AIG nodes added to storage = %5d.\n", Abc_NtkNodeNum(pNtk) );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Interfaces the network with the FRAIG package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFraigRestore()
+{
+    extern Abc_Ntk_t * Abc_NtkFraigPartitioned( Vec_Ptr_t * vStore, void * pParams );
+    Fraig_Params_t Params;
+    Vec_Ptr_t * vStore;
+    Abc_Ntk_t * pNtk, * pFraig;
+    int nWords1, nWords2, nWordsMin;
+//    abctime clk = Abc_Clock();
+
+    // get the stored network
+    vStore = Abc_FrameReadStore();
+    if ( Vec_PtrSize(vStore) == 0 )
+    {
+        printf( "There are no network currently in storage.\n" );
+        return NULL;
+    }
+//    printf( "Currently stored %d networks will be fraiged.\n", Vec_PtrSize(vStore) );
+    pNtk = (Abc_Ntk_t *)Vec_PtrEntry( vStore, 0 );
+
+    // swap the first and last network
+    // this should lead to the primary choice being "better" because of synthesis
+    if ( Vec_PtrSize(vStore) > 1 )
+    {
+        pNtk = (Abc_Ntk_t *)Vec_PtrPop( vStore );
+        Vec_PtrPush( vStore, Vec_PtrEntry(vStore,0) );
+        Vec_PtrWriteEntry( vStore, 0, pNtk );
+    }
+
+    // to determine the number of simulation patterns
+    // use the following strategy
+    // at least 64 words (32 words random and 32 words dynamic)
+    // no more than 256M for one circuit (128M + 128M)
+    nWords1 = 32;
+    nWords2 = (1<<27) / (Abc_NtkNodeNum(pNtk) + Abc_NtkCiNum(pNtk));
+    nWordsMin = Abc_MinInt( nWords1, nWords2 );
+
+    // set parameters for fraiging
+    Fraig_ParamsSetDefault( &Params );
+    Params.nPatsRand  = nWordsMin * 32;    // the number of words of random simulation info
+    Params.nPatsDyna  = nWordsMin * 32;    // the number of words of dynamic simulation info
+    Params.nBTLimit   = 1000;              // the max number of backtracks to perform
+    Params.fFuncRed   =    1;              // performs only one level hashing
+    Params.fFeedBack  =    1;              // enables solver feedback
+    Params.fDist1Pats =    1;              // enables distance-1 patterns
+    Params.fDoSparse  =    1;              // performs equiv tests for sparse functions 
+    Params.fChoicing  =    1;              // enables recording structural choices
+    Params.fTryProve  =    0;              // tries to solve the final miter
+    Params.fInternal  =    1;              // does not show progress bar
+    Params.fVerbose   =    0;              // the verbosiness flag
+
+    // perform partitioned computation of structural choices
+    pFraig = Abc_NtkFraigPartitioned( vStore, &Params );
+    Abc_NtkFraigStoreClean();
+//ABC_PRT( "Total choicing time", Abc_Clock() - clk );
+    return pFraig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Interfaces the network with the FRAIG package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFraigStoreClean()
+{
+    Vec_Ptr_t * vStore;
+    Abc_Ntk_t * pNtk;
+    int i;
+    vStore = Abc_FrameReadStore();
+    Vec_PtrForEachEntry( Abc_Ntk_t *, vStore, pNtk, i )
+        Abc_NtkDelete( pNtk );
+    Vec_PtrClear( vStore );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the correctness of stored networks.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFraigStoreCheck( Abc_Ntk_t * pFraig )
+{
+    Abc_Obj_t * pNode0, * pNode1;
+    int nPoOrig, nPoFinal, nStored; 
+    int i, k;
+    // check that the PO functions are correct
+    nPoFinal = Abc_NtkPoNum(pFraig);
+    nStored  = Abc_FrameReadStoreSize();
+    assert( nPoFinal % nStored == 0 );
+    nPoOrig  = nPoFinal / nStored;
+    for ( i = 0; i < nPoOrig; i++ )
+    {
+        pNode0 = Abc_ObjFanin0( Abc_NtkPo(pFraig, i) ); 
+        for ( k = 1; k < nStored; k++ )
+        {
+            pNode1 = Abc_ObjFanin0( Abc_NtkPo(pFraig, k*nPoOrig+i) ); 
+            if ( pNode0 != pNode1 )
+                printf( "Verification for PO #%d of network #%d has failed. The PO function is not used.\n", i+1, k+1 );
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcFx.c b/abc-build/src/base/abci/abcFx.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcFx.c
@@ -0,0 +1,1211 @@
+/**CFile****************************************************************
+
+  FileName    [abcFx.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Implementation of traditional "fast_extract" algorithm.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 26, 2013.]
+
+  Revision    [$Id: abcFx.c,v 1.00 2013/04/26 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/vec/vecWec.h"
+#include "misc/vec/vecQue.h"
+#include "misc/vec/vecHsh.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+/*
+    The code in this file implements the traditional "fast_extract" algorithm, 
+    which extracts two-cube divisors concurrently with single-cube two-literal divisors,
+    as proposed in the TCAD'92 paper by J. Rajski and J. Vasudevamurthi.
+
+    Integration notes:
+
+    It is assumed that each object (primary input or internal node) in the original network 
+    is associated with a unique integer number, called object identifier (ObjId, for short).
+
+    The user's input data given to 'fast_extract" is an array of cubes (pMan->vCubes).
+    Each cube is an array of integers, in which the first entry contains ObjId of the node, 
+    to which this cube belongs in the original network. The following entries of a cube are 
+    SOP literals of this cube.  Each literal is represtned as 2*FaninId + ComplAttr, where FaninId 
+    is ObjId of the fanin node and ComplAttr is 1 if literal is complemented, and 0 otherwise.
+
+    The user's output data produced by 'fast_extract' is also an array of cubes (pMan->vCubes).
+    If no divisors have been extracted, the output array is the same as the input array.
+    If some divisors have been extracted, the output array contains updated old cubes and new cubes 
+    representing the extracted divisors. The new divisors have their ObjId starting from the 
+    largest ObjId used in the cubes. To give the user more flexibility, which may be needed when some 
+    ObjIds are already used for primary output nodes, which do not participate in fast_extract,
+    the parameter ObjIdMax is passed to procedure Fx_FastExtract().  The new divisors will receive
+    their ObjId starting from ObjIdMax onward, as divisor extaction proceeds.
+
+    The following two requirements are imposed on the input and output array of cubes:
+    (1) The array of cubes should be sorted by the first entry in each cube (that is, cubes belonging 
+    to the same node should form a contiguous range). 
+    (2) Literals in a cube should be sorted in the increasing order of the integer numbers.
+    
+    To integrate this code into a calling application, such as ABC, the input cube array should 
+    be generated (below this is done by the procedure Abc_NtkFxRetrieve) and the output cube array
+    should be incorporated into the current network (below this is done by the procedure Abc_NtkFxInsert).
+    In essence, the latter procedure performs the following:
+    - removes the current fanins and SOPs of each node in the network
+    - adds new nodes for each new divisor introduced by "fast_extract"
+    - populates fanins and SOPs of each node, both old and new, as indicaded by the resulting cube array.
+
+    Implementation notes:
+
+    The implementation is optimized for simplicity and speed of computation.
+    (1) Main input/output data-structure (pMan->vCubes) is the array of cubes which is dynamically updated by the algorithm.
+    (2) Auxiliary data-structure (pMan->vLits) is the array of arrays. The i-th array contains IDs of cubes which have literal i.
+    It may be convenient to think about the first (second) array as rows (columns) of a sparse matrix, 
+    although the sparse matrix data-structure is not used in the proposed implementation.
+    (3) Hash table (pMan->pHash) hashes the normalized divisors (represented as integer arrays) into integer numbers.
+    (4) Array of divisor weights (pMan->vWeights), that is, the number of SOP literals to be saved by extacting each divisor.
+    (5) Priority queue (pMan->vPrio), which sorts divisor (integer numbers) by their weight
+    (6) Integer array (pMan->vVarCube), which maps each ObjId into the first cube of this object, 
+    or -1, if there is no cubes as in the case of a primary input.
+
+*/
+
+typedef struct Fx_Man_t_ Fx_Man_t;
+struct Fx_Man_t_
+{
+    // user's data
+    Vec_Wec_t *     vCubes;     // cube -> lit
+    int             LitCountMax;// max size of divisor to extract
+    // internal data
+    Vec_Wec_t *     vLits;      // lit -> cube
+    Vec_Int_t *     vCounts;    // literal counts (currently not used)
+    Hsh_VecMan_t *  pHash;      // hash table for normalized divisors
+    Vec_Flt_t *     vWeights;   // divisor weights
+    Vec_Que_t *     vPrio;      // priority queue for divisors by weight
+    Vec_Int_t *     vVarCube;   // mapping ObjId into its first cube
+    Vec_Int_t *     vLevels;    // variable levels
+    // temporary data to update the data-structure when a divisor is extracted
+    Vec_Int_t *     vCubesS;    // single cubes for the given divisor
+    Vec_Int_t *     vCubesD;    // cube pairs for the given divisor
+    Vec_Int_t *     vCompls;    // complemented attribute of each cube pair
+    Vec_Int_t *     vCubeFree;  // cube-free divisor
+    Vec_Int_t *     vDiv;       // selected divisor
+    // statistics 
+    abctime         timeStart;  // starting time
+    int             nVars;      // original problem variables
+    int             nLits;      // the number of SOP literals
+    int             nDivs;      // the number of extracted divisors
+    int             nCompls;    // the number of complements
+    int             nPairsS;    // number of lit pairs
+    int             nPairsD;    // number of cube pairs
+    int             nDivsS;     // single cube divisors
+    int             nDivMux[3]; // 0 = mux, 1 = compl mux, 2 = no mux
+};
+
+static inline int Fx_ManGetFirstVarCube( Fx_Man_t * p, Vec_Int_t * vCube ) { return Vec_IntEntry( p->vVarCube, Vec_IntEntry(vCube, 0) ); }
+
+#define Fx_ManForEachCubeVec( vVec, vCubes, vCube, i )           \
+    for ( i = 0; (i < Vec_IntSize(vVec)) && ((vCube) = Vec_WecEntry(vCubes, Vec_IntEntry(vVec, i))); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Retrieves SOP information for fast_extract.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Wec_t * Abc_NtkFxRetrieve( Abc_Ntk_t * pNtk )
+{
+    Vec_Wec_t * vCubes;
+    Vec_Int_t * vCube;
+    Abc_Obj_t * pNode;
+    char * pCube, * pSop;
+    int nVars, i, v, Lit;
+    assert( Abc_NtkIsSopLogic(pNtk) );
+    vCubes = Vec_WecAlloc( 1000 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        pSop = (char *)pNode->pData;
+        nVars = Abc_SopGetVarNum(pSop);
+        assert( nVars == Abc_ObjFaninNum(pNode) );
+//        if ( nVars < 2 ) continue;
+        Abc_SopForEachCube( pSop, nVars, pCube )
+        {
+            vCube = Vec_WecPushLevel( vCubes );
+            Vec_IntPush( vCube, Abc_ObjId(pNode) );
+            Abc_CubeForEachVar( pCube, Lit, v )
+            {
+                if ( Lit == '0' )
+                    Vec_IntPush( vCube, Abc_Var2Lit(Abc_ObjFaninId(pNode, v), 1) );
+                else if ( Lit == '1' )
+                    Vec_IntPush( vCube, Abc_Var2Lit(Abc_ObjFaninId(pNode, v), 0) );
+            }
+            Vec_IntSelectSort( Vec_IntArray(vCube) + 1, Vec_IntSize(vCube) - 1 );
+        }
+    }
+    return vCubes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts SOP information after fast_extract.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFxInsert( Abc_Ntk_t * pNtk, Vec_Wec_t * vCubes )
+{
+    Vec_Int_t * vCube, * vPres, * vFirst, * vCount;
+    Abc_Obj_t * pNode, * pFanin;
+    char * pCube, * pSop;
+    int i, k, v, Lit, iFanin, iNodeMax = 0;
+    assert( Abc_NtkIsSopLogic(pNtk) );
+    // check that cubes have no gaps and are ordered by first node
+    Lit = -1;
+    Vec_WecForEachLevel( vCubes, vCube, i )
+    {
+        assert( Vec_IntSize(vCube) > 0 );
+        assert( Lit <= Vec_IntEntry(vCube, 0) );
+        Lit = Vec_IntEntry(vCube, 0);
+    }
+    // find the largest index
+    Vec_WecForEachLevel( vCubes, vCube, i )
+        iNodeMax = Abc_MaxInt( iNodeMax, Vec_IntEntry(vCube, 0) );
+    // quit if nothing changes
+    if ( iNodeMax < Abc_NtkObjNumMax(pNtk) )
+    {
+        printf( "The network is unchanged by fast extract.\n" );
+        return;
+    }
+    // create new nodes
+    for ( i = Abc_NtkObjNumMax(pNtk); i <= iNodeMax; i++ )
+    {
+        pNode = Abc_NtkCreateNode( pNtk );
+        assert( i == (int)Abc_ObjId(pNode) );
+    }
+    // create node fanins
+    vFirst = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
+    vCount = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
+    Vec_WecForEachLevel( vCubes, vCube, i )
+    {
+        iFanin = Vec_IntEntry( vCube, 0 );
+        if ( Vec_IntEntry(vCount, iFanin) == 0 )
+            Vec_IntWriteEntry( vFirst, iFanin, i );
+        Vec_IntAddToEntry( vCount, iFanin, 1 );
+    }
+    // create node SOPs
+    vPres = Vec_IntStartFull( Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+//        if ( Vec_IntEntry(vCount, i) == 0 ) continue;
+        Abc_ObjRemoveFanins( pNode );
+        // create fanins
+        assert( Vec_IntEntry(vCount, i) > 0 );
+        for ( k = 0; k < Vec_IntEntry(vCount, i); k++ )
+        {
+            vCube = Vec_WecEntry( vCubes, Vec_IntEntry(vFirst, i) + k );
+            assert( Vec_IntEntry( vCube, 0 ) == i );
+            Vec_IntForEachEntryStart( vCube, Lit, v, 1 )
+            {
+                pFanin = Abc_NtkObj(pNtk, Abc_Lit2Var(Lit));
+                if ( Vec_IntEntry(vPres, Abc_ObjId(pFanin)) >= 0 )
+                    continue;
+                Vec_IntWriteEntry(vPres, Abc_ObjId(pFanin), Abc_ObjFaninNum(pNode));
+                Abc_ObjAddFanin( pNode, pFanin );
+            }
+        }
+        // create SOP
+        pSop = pCube = Abc_SopStart( (Mem_Flex_t *)pNtk->pManFunc, Vec_IntEntry(vCount, i), Abc_ObjFaninNum(pNode) );
+        for ( k = 0; k < Vec_IntEntry(vCount, i); k++ )
+        {
+            vCube = Vec_WecEntry( vCubes, Vec_IntEntry(vFirst, i) + k );
+            assert( Vec_IntEntry( vCube, 0 ) == i );
+            Vec_IntForEachEntryStart( vCube, Lit, v, 1 )
+            {
+                pFanin = Abc_NtkObj(pNtk, Abc_Lit2Var(Lit));
+                iFanin = Vec_IntEntry(vPres, Abc_ObjId(pFanin));
+                assert( iFanin >= 0 && iFanin < Abc_ObjFaninNum(pNode) );
+                pCube[iFanin] = Abc_LitIsCompl(Lit) ? '0' : '1';
+            }
+            pCube += Abc_ObjFaninNum(pNode) + 3;
+        }
+        // complement SOP if the original one was complemented
+        if ( pNode->pData && Abc_SopIsComplement((char *)pNode->pData) )
+            Abc_SopComplement( pSop );
+        pNode->pData = pSop;
+        // clean fanins
+        Abc_ObjForEachFanin( pNode, pFanin, v )
+            Vec_IntWriteEntry( vPres, Abc_ObjId(pFanin), -1 );
+    }
+    Vec_IntFree( vFirst );
+    Vec_IntFree( vCount );
+    Vec_IntFree( vPres );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Makes sure the nodes do not have complemented and duplicated fanins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkFxCheck( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i;
+//    Abc_NtkForEachObj( pNtk, pNode, i )
+//        Abc_ObjPrint( stdout, pNode );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        if ( !Vec_IntCheckUniqueSmall( &pNode->vFanins ) )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkFxPerform( Abc_Ntk_t * pNtk, int nNewNodesMax, int LitCountMax, int fVerbose, int fVeryVerbose )
+{
+    extern int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitCountMax, int fVerbose, int fVeryVerbose );
+    Vec_Wec_t * vCubes;
+    assert( Abc_NtkIsSopLogic(pNtk) );
+    // check unique fanins
+    if ( !Abc_NtkFxCheck(pNtk) )
+    {
+        printf( "Abc_NtkFastExtract: Nodes have duplicated fanins. FX is not performed.\n" );
+        return 0;
+    }
+    // sweep removes useless nodes
+    Abc_NtkCleanup( pNtk, 0 );
+//    Abc_NtkOrderFanins( pNtk );
+    // makes sure the SOPs are SCC-free and D1C-free
+    Abc_NtkMakeLegit( pNtk );
+    // collect information about the covers
+    vCubes = Abc_NtkFxRetrieve( pNtk );
+    // call the fast extract procedure
+    if ( Fx_FastExtract( vCubes, Abc_NtkObjNumMax(pNtk), nNewNodesMax, LitCountMax, fVerbose, fVeryVerbose ) > 0 )
+    {
+        // update the network
+        Abc_NtkFxInsert( pNtk, vCubes );
+        Vec_WecFree( vCubes );
+        if ( !Abc_NtkCheck( pNtk ) )
+            printf( "Abc_NtkFxPerform: The network check has failed.\n" );
+        return 1;
+    }
+    else
+        printf( "Warning: The network has not been changed by \"fx\".\n" );
+    Vec_WecFree( vCubes );
+    return 0;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starting the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fx_Man_t * Fx_ManStart( Vec_Wec_t * vCubes )
+{
+    Fx_Man_t * p;
+    p = ABC_CALLOC( Fx_Man_t, 1 );
+    p->vCubes   = vCubes;
+    // temporary data
+    p->vCubesS   = Vec_IntAlloc( 100 );
+    p->vCubesD   = Vec_IntAlloc( 100 );
+    p->vCompls   = Vec_IntAlloc( 100 );
+    p->vCubeFree = Vec_IntAlloc( 100 );
+    p->vDiv      = Vec_IntAlloc( 100 );
+    return p;
+}
+void Fx_ManStop( Fx_Man_t * p )
+{
+//    Vec_WecFree( p->vCubes );
+    Vec_WecFree( p->vLits );
+    Vec_IntFree( p->vCounts );
+    Hsh_VecManStop( p->pHash );
+    Vec_FltFree( p->vWeights );
+    Vec_QueFree( p->vPrio );
+    Vec_IntFree( p->vVarCube );
+    Vec_IntFree( p->vLevels );
+    // temporary data
+    Vec_IntFree( p->vCubesS );
+    Vec_IntFree( p->vCubesD );
+    Vec_IntFree( p->vCompls );
+    Vec_IntFree( p->vCubeFree );
+    Vec_IntFree( p->vDiv );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute levels of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Fx_ManComputeLevelDiv( Fx_Man_t * p, Vec_Int_t * vCubeFree )
+{
+    int i, Lit, Level = 0;
+    Vec_IntForEachEntry( vCubeFree, Lit, i )
+        Level = Abc_MaxInt( Level, Vec_IntEntry(p->vLevels, Abc_Lit2Var(Abc_Lit2Var(Lit))) );
+    return Abc_MinInt( Level, 800 );
+}
+static inline int Fx_ManComputeLevelCube( Fx_Man_t * p, Vec_Int_t * vCube )
+{
+    int k, Lit, Level = 0;
+    Vec_IntForEachEntryStart( vCube, Lit, k, 1 )
+        Level = Abc_MaxInt( Level, Vec_IntEntry(p->vLevels, Abc_Lit2Var(Lit)) );
+    return Level;
+}
+void Fx_ManComputeLevel( Fx_Man_t * p )
+{
+    Vec_Int_t * vCube;
+    int i, iVar, iFirst = 0;
+    iVar = Vec_IntEntry( Vec_WecEntry(p->vCubes,0), 0 );
+    p->vLevels = Vec_IntStart( p->nVars );
+    Vec_WecForEachLevel( p->vCubes, vCube, i )
+    {
+        if ( iVar != Vec_IntEntry(vCube, 0) )
+        {
+            // add the number of cubes
+            Vec_IntAddToEntry( p->vLevels, iVar, i - iFirst );
+            iVar = Vec_IntEntry(vCube, 0);
+            iFirst = i;
+        }
+        Vec_IntUpdateEntry( p->vLevels, iVar, Fx_ManComputeLevelCube(p, vCube) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Printing procedures.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline char Fx_PrintDivLit( int Lit ) { return (Abc_LitIsCompl(Lit) ? 'A' : 'a') + Abc_Lit2Var(Lit); }
+static inline void Fx_PrintDivOneReal( Vec_Int_t * vDiv )
+{
+    int i, Lit;
+    Vec_IntForEachEntry( vDiv, Lit, i )
+        if ( !Abc_LitIsCompl(Lit) )
+            printf( "%c", Fx_PrintDivLit(Abc_Lit2Var(Lit)) );
+    printf( " + " );
+    Vec_IntForEachEntry( vDiv, Lit, i )
+        if ( Abc_LitIsCompl(Lit) )
+            printf( "%c", Fx_PrintDivLit(Abc_Lit2Var(Lit)) );
+}
+static inline void Fx_PrintDivOne( Vec_Int_t * vDiv )
+{
+    int i, Lit;
+    Vec_IntForEachEntry( vDiv, Lit, i )
+        if ( !Abc_LitIsCompl(Lit) )
+            printf( "%c", Fx_PrintDivLit( Abc_Var2Lit(i, Abc_LitIsCompl(Lit)) ) );
+    printf( " + " );
+    Vec_IntForEachEntry( vDiv, Lit, i )
+        if ( Abc_LitIsCompl(Lit) )
+            printf( "%c", Fx_PrintDivLit( Abc_Var2Lit(i, Abc_LitIsCompl(Lit)) ) );
+}
+static inline void Fx_PrintDivArray( Vec_Int_t * vDiv )
+{
+    int i, Lit;
+    Vec_IntForEachEntry( vDiv, Lit, i )
+        if ( !Abc_LitIsCompl(Lit) )
+            printf( "%d(1) ", Abc_Lit2Var(Lit) );
+    printf( " + " );
+    Vec_IntForEachEntry( vDiv, Lit, i )
+        if ( Abc_LitIsCompl(Lit) )
+            printf( "%d(2) ", Abc_Lit2Var(Lit) );
+}
+static inline void Fx_PrintDiv( Fx_Man_t * p, int iDiv )
+{
+    int i;
+    printf( "%4d : ", p->nDivs );
+    printf( "Div %7d : ", iDiv );
+    printf( "Weight %12.5f  ", Vec_FltEntry(p->vWeights, iDiv) );
+//    printf( "Compl %4d  ", p->nCompls );
+    Fx_PrintDivOne( Hsh_VecReadEntry(p->pHash, iDiv) );
+    for ( i = Vec_IntSize(Hsh_VecReadEntry(p->pHash, iDiv)) + 3; i < 16; i++ )
+        printf( " " );
+    printf( "Lits =%7d  ", p->nLits );
+    printf( "Divs =%8d  ", Hsh_VecSize(p->pHash) );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - p->timeStart );
+}
+static void Fx_PrintDivisors( Fx_Man_t * p )
+{
+    int iDiv;
+    for ( iDiv = 0; iDiv < Vec_FltSize(p->vWeights); iDiv++ )
+        Fx_PrintDiv( p, iDiv );
+}
+static void Fx_PrintLiterals( Fx_Man_t * p )
+{
+    Vec_Int_t * vTemp;
+    int i;
+    Vec_WecForEachLevel( p->vLits, vTemp, i )
+    {
+        printf( "%c : ", Fx_PrintDivLit(i) );
+        Vec_IntPrint( vTemp );
+    }
+}
+static void Fx_PrintMatrix( Fx_Man_t * p )
+{
+    Vec_Int_t * vCube;
+    int i, v, Lit, nObjs;
+    char * pLine;
+    if ( Vec_WecSize(p->vLits)/2 > 26 )
+        return;
+    printf( "         " );
+    nObjs = Vec_WecSize(p->vLits)/2;
+    for ( i = 0; i < Abc_MinInt(nObjs, 26); i++ )
+        printf( "%c", 'a' + i );
+    printf( "\n" );
+    pLine = ABC_CALLOC( char, nObjs+1 );
+    Vec_WecForEachLevel( p->vCubes, vCube, i )
+    {
+        if ( Vec_IntSize(vCube) == 0 )
+            continue;
+        memset( pLine, '-', nObjs );
+        Vec_IntForEachEntryStart( vCube, Lit, v, 1 )
+        {
+            assert( Abc_Lit2Var(Lit) < nObjs );
+            pLine[Abc_Lit2Var(Lit)] = Abc_LitIsCompl(Lit) ? '0' : '1';
+        }
+        printf( "%6d : %s %4d\n", i, pLine, Vec_IntEntry(vCube, 0) );
+    }
+    ABC_FREE( pLine );
+    Fx_PrintLiterals( p );
+    Fx_PrintDivisors( p );
+}
+static void Fx_PrintStats( Fx_Man_t * p, abctime clk )
+{
+    printf( "Cubes =%8d  ", Vec_WecSizeUsed(p->vCubes) );
+    printf( "Lits  =%8d  ", Vec_WecSizeUsed(p->vLits) );
+    printf( "Divs  =%8d  ", Hsh_VecSize(p->pHash) );
+    printf( "Divs+ =%8d  ", Vec_QueSize(p->vPrio) );
+    printf( "Compl =%8d  ", p->nDivMux[1] );
+    printf( "Extr  =%7d  ", p->nDivs );
+//    printf( "DivsS =%6d  ", p->nDivsS );
+//    printf( "PairS =%6d  ", p->nPairsS );
+//    printf( "PairD =%6d  ", p->nPairsD );
+    Abc_PrintTime( 1, "Time", clk );
+//    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the divisor should be complemented.]
+
+  Description [Normalizes the divisor by putting, first, positive control 
+  literal first and, second, positive data1 literal. As the result, 
+  a MUX divisor is (ab + !ac) and an XOR divisor is (ab + !a!b).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Fx_ManDivNormalize( Vec_Int_t * vCubeFree ) // return 1 if complemented
+{
+    int * L = Vec_IntArray(vCubeFree);
+    int RetValue = 0, LitA0 = -1, LitB0 = -1, LitA1 = -1, LitB1 = -1;
+    assert( Vec_IntSize(vCubeFree) == 4 );
+    if ( Abc_LitIsCompl(L[0]) != Abc_LitIsCompl(L[1]) && (L[0] >> 2) == (L[1] >> 2) ) // diff cubes, same vars
+    {
+        if ( Abc_LitIsCompl(L[2]) == Abc_LitIsCompl(L[3]) )
+            return -1;
+        LitA0 = Abc_Lit2Var(L[0]), LitB0 = Abc_Lit2Var(L[1]);
+        if ( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[2]) )
+        {
+            assert( Abc_LitIsCompl(L[1]) == Abc_LitIsCompl(L[3]) );
+            LitA1 = Abc_Lit2Var(L[2]), LitB1 = Abc_Lit2Var(L[3]);
+        }
+        else
+        {
+            assert( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[3]) );
+            assert( Abc_LitIsCompl(L[1]) == Abc_LitIsCompl(L[2]) );
+            LitA1 = Abc_Lit2Var(L[3]), LitB1 = Abc_Lit2Var(L[2]);
+        }
+    }
+    else if ( Abc_LitIsCompl(L[1]) != Abc_LitIsCompl(L[2]) && (L[1] >> 2) == (L[2] >> 2) )
+    {
+        if ( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[3]) )
+            return -1;
+        LitA0 = Abc_Lit2Var(L[1]), LitB0 = Abc_Lit2Var(L[2]);
+        if ( Abc_LitIsCompl(L[1]) == Abc_LitIsCompl(L[0]) )
+            LitA1 = Abc_Lit2Var(L[0]), LitB1 = Abc_Lit2Var(L[3]);
+        else
+            LitA1 = Abc_Lit2Var(L[3]), LitB1 = Abc_Lit2Var(L[0]);
+    }
+    else if ( Abc_LitIsCompl(L[2]) != Abc_LitIsCompl(L[3]) && (L[2] >> 2) == (L[3] >> 2) )
+    {
+        if ( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[1]) )
+            return -1;
+        LitA0 = Abc_Lit2Var(L[2]), LitB0 = Abc_Lit2Var(L[3]);
+        if ( Abc_LitIsCompl(L[2]) == Abc_LitIsCompl(L[0]) )
+            LitA1 = Abc_Lit2Var(L[0]), LitB1 = Abc_Lit2Var(L[1]);
+        else
+            LitA1 = Abc_Lit2Var(L[1]), LitB1 = Abc_Lit2Var(L[0]);
+    }
+    else 
+        return -1;
+    assert( LitA0 == Abc_LitNot(LitB0) );
+    if ( Abc_LitIsCompl(LitA0) )
+    {
+        ABC_SWAP( int, LitA0, LitB0 );
+        ABC_SWAP( int, LitA1, LitB1 );
+    }
+    assert( !Abc_LitIsCompl(LitA0) );
+    if ( Abc_LitIsCompl(LitA1) )
+    {
+        LitA1 = Abc_LitNot(LitA1);
+        LitB1 = Abc_LitNot(LitB1);
+        RetValue = 1;
+    }
+    assert( !Abc_LitIsCompl(LitA1) );
+    // arrange literals in such as a way that
+    // - the first two literals are control literals from different cubes
+    // - the third literal is non-complented data input
+    // - the forth literal is possibly complemented data input
+    L[0] = Abc_Var2Lit( LitA0, 0 );
+    L[1] = Abc_Var2Lit( LitB0, 1 );
+    L[2] = Abc_Var2Lit( LitA1, 0 );
+    L[3] = Abc_Var2Lit( LitB1, 1 );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find a cube-free divisor of the two cubes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fx_ManDivFindCubeFree( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vCubeFree )
+{
+    int * pBeg1 = vArr1->pArray + 1;  // skip variable ID
+    int * pBeg2 = vArr2->pArray + 1;  // skip variable ID
+    int * pEnd1 = vArr1->pArray + vArr1->nSize;
+    int * pEnd2 = vArr2->pArray + vArr2->nSize;
+    int Counter = 0, fAttr0 = 0, fAttr1 = 1;
+    Vec_IntClear( vCubeFree );
+    while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+    {
+        if ( *pBeg1 == *pBeg2 )
+            pBeg1++, pBeg2++, Counter++;
+        else if ( *pBeg1 < *pBeg2 )
+            Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg1++, fAttr0) );
+        else  
+        {
+            if ( Vec_IntSize(vCubeFree) == 0 )
+                fAttr0 = 1, fAttr1 = 0;
+            Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg2++, fAttr1) );
+        }
+    }
+    while ( pBeg1 < pEnd1 )
+        Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg1++, fAttr0) );
+    while ( pBeg2 < pEnd2 )
+        Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg2++, fAttr1) );
+    if ( Vec_IntSize(vCubeFree) == 0 )
+        printf( "The SOP has duplicated cubes.\n" );
+    else if ( Vec_IntSize(vCubeFree) == 1 )
+        printf( "The SOP has contained cubes.\n" );
+    else if ( Vec_IntSize(vCubeFree) == 2 && Abc_Lit2Var(Abc_Lit2Var(Vec_IntEntry(vCubeFree, 0))) == Abc_Lit2Var(Abc_Lit2Var(Vec_IntEntry(vCubeFree, 1))) )
+        printf( "The SOP has distance-1 cubes or it is not a prime cover.  Please make sure the result verifies.\n" );
+    assert( !Abc_LitIsCompl(Vec_IntEntry(vCubeFree, 0)) );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedures operating on a two-cube divisor.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fx_ManDivFindPivots( Vec_Int_t * vDiv, int * pLit0, int * pLit1 )
+{
+    int i, Lit;
+    *pLit0 = -1;
+    *pLit1 = -1;
+    Vec_IntForEachEntry( vDiv, Lit, i )
+    {
+        if ( Abc_LitIsCompl(Lit) )
+        {
+            if ( *pLit1 == -1 )
+                *pLit1 = Abc_Lit2Var(Lit);
+        }
+        else
+        {
+            if ( *pLit0 == -1 )
+                *pLit0 = Abc_Lit2Var(Lit);
+        }
+        if ( *pLit0 >= 0 && *pLit1 >= 0 )
+            return;
+    }
+}
+static inline int Fx_ManDivRemoveLits( Vec_Int_t * vCube, Vec_Int_t * vDiv, int fCompl )
+{
+    int i, Lit, Count = 0;
+    assert( !fCompl || Vec_IntSize(vDiv) == 4 );
+    Vec_IntForEachEntry( vDiv, Lit, i )
+        Count += Vec_IntRemove1( vCube, Abc_Lit2Var(Lit) ^ (fCompl && i > 1) );  // the last two lits can be complemented
+    return Count;
+}
+static inline void Fx_ManDivAddLits( Vec_Int_t * vCube, Vec_Int_t * vCube2, Vec_Int_t * vDiv )
+{
+    int i, Lit, * pArray;
+//    Vec_IntClear( vCube );
+//    Vec_IntClear( vCube2 );
+    Vec_IntForEachEntry( vDiv, Lit, i )
+        if ( Abc_LitIsCompl(Lit) )
+            Vec_IntPush( vCube2, Abc_Lit2Var(Lit) );
+        else
+            Vec_IntPush( vCube, Abc_Lit2Var(Lit) );
+    if ( Vec_IntSize(vDiv) == 4 && Vec_IntSize(vCube) == 3 )
+    {
+        assert( Vec_IntSize(vCube2) == 3 );
+        pArray = Vec_IntArray(vCube);
+        if ( pArray[1] > pArray[2] )
+            ABC_SWAP( int, pArray[1], pArray[2] );
+        pArray = Vec_IntArray(vCube2);
+        if ( pArray[1] > pArray[2] )
+            ABC_SWAP( int, pArray[1], pArray[2] );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Setting up the data-structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fx_ManCreateLiterals( Fx_Man_t * p, int nVars )
+{
+    Vec_Int_t * vCube;
+    int i, k, Lit, Count;
+    // find the number of variables
+    p->nVars = p->nLits = 0;
+    Vec_WecForEachLevel( p->vCubes, vCube, i )
+    {
+        assert( Vec_IntSize(vCube) > 0 );
+        p->nVars = Abc_MaxInt( p->nVars, Vec_IntEntry(vCube, 0) );
+        p->nLits += Vec_IntSize(vCube) - 1;
+        Vec_IntForEachEntryStart( vCube, Lit, k, 1 )
+            p->nVars = Abc_MaxInt( p->nVars, Abc_Lit2Var(Lit) );
+    }
+//    p->nVars++;
+    assert( p->nVars < nVars );
+    p->nVars = nVars;
+    // count literals
+    p->vCounts = Vec_IntStart( 2*p->nVars );
+    Vec_WecForEachLevel( p->vCubes, vCube, i )
+        Vec_IntForEachEntryStart( vCube, Lit, k, 1 )
+            Vec_IntAddToEntry( p->vCounts, Lit, 1 );
+    // start literals
+    p->vLits = Vec_WecStart( 2*p->nVars );
+    Vec_IntForEachEntry( p->vCounts, Count, Lit )
+        Vec_IntGrow( Vec_WecEntry(p->vLits, Lit), Count );
+    // fill out literals
+    Vec_WecForEachLevel( p->vCubes, vCube, i )
+        Vec_IntForEachEntryStart( vCube, Lit, k, 1 )
+            Vec_WecPush( p->vLits, Lit, i );
+    // create mapping of variable into the first cube
+    p->vVarCube = Vec_IntStartFull( p->nVars );
+    Vec_WecForEachLevel( p->vCubes, vCube, i )
+        if ( Vec_IntEntry(p->vVarCube, Vec_IntEntry(vCube, 0)) == -1 )
+            Vec_IntWriteEntry( p->vVarCube, Vec_IntEntry(vCube, 0), i );
+}
+int Fx_ManCubeSingleCubeDivisors( Fx_Man_t * p, Vec_Int_t * vPivot, int fRemove, int fUpdate )
+{
+    int k, n, Lit, Lit2, iDiv;
+    if ( Vec_IntSize(vPivot) < 2 )
+        return 0;
+    Vec_IntForEachEntryStart( vPivot, Lit, k, 1 )
+    Vec_IntForEachEntryStart( vPivot, Lit2, n, k+1 )
+    {
+        assert( Lit < Lit2 );
+        Vec_IntClear( p->vCubeFree );
+        Vec_IntPush( p->vCubeFree, Abc_Var2Lit(Abc_LitNot(Lit), 0) );
+        Vec_IntPush( p->vCubeFree, Abc_Var2Lit(Abc_LitNot(Lit2), 1) );
+        iDiv = Hsh_VecManAdd( p->pHash, p->vCubeFree );
+        if ( !fRemove )
+        {
+            if ( Vec_FltSize(p->vWeights) == iDiv )
+            {
+                Vec_FltPush(p->vWeights, -2 + 0.9 - 0.001 * Fx_ManComputeLevelDiv(p, p->vCubeFree));
+                p->nDivsS++;
+            }
+            assert( iDiv < Vec_FltSize(p->vWeights) );
+            Vec_FltAddToEntry( p->vWeights, iDiv, 1 );
+            p->nPairsS++;
+        }
+        else
+        {
+            assert( iDiv < Vec_FltSize(p->vWeights) );
+            Vec_FltAddToEntry( p->vWeights, iDiv, -1 );
+            p->nPairsS--;
+        }
+        if ( fUpdate )
+        {
+            if ( Vec_QueIsMember(p->vPrio, iDiv) )
+                Vec_QueUpdate( p->vPrio, iDiv );
+            else if ( !fRemove )
+                Vec_QuePush( p->vPrio, iDiv );
+        }
+    }
+    return Vec_IntSize(vPivot) * (Vec_IntSize(vPivot) - 1) / 2;
+}
+void Fx_ManCubeDoubleCubeDivisors( Fx_Man_t * p, int iFirst, Vec_Int_t * vPivot, int fRemove, int fUpdate )
+{
+    Vec_Int_t * vCube;
+    int i, iDiv, Base;
+    Vec_WecForEachLevelStart( p->vCubes, vCube, i, iFirst )
+    {
+        if ( Vec_IntSize(vCube) == 0 || vCube == vPivot )
+            continue;
+        if ( Vec_WecIntHasMark(vCube) && Vec_WecIntHasMark(vPivot) && vCube > vPivot )
+            continue;
+        if ( Vec_IntEntry(vCube, 0) != Vec_IntEntry(vPivot, 0) )
+            break;
+        Base = Fx_ManDivFindCubeFree( vCube, vPivot, p->vCubeFree );
+        if ( Vec_IntSize(p->vCubeFree) == 4 )
+        { 
+            int Value = Fx_ManDivNormalize( p->vCubeFree );
+            if ( Value == 0 )
+                p->nDivMux[0]++;
+            else if ( Value == 1 )
+                p->nDivMux[1]++;
+            else
+                p->nDivMux[2]++;
+        }
+        if ( p->LitCountMax && p->LitCountMax < Vec_IntSize(p->vCubeFree) )
+            continue;
+        iDiv = Hsh_VecManAdd( p->pHash, p->vCubeFree );
+        if ( !fRemove )
+        {
+            if ( iDiv == Vec_FltSize(p->vWeights) )
+                Vec_FltPush(p->vWeights, -Vec_IntSize(p->vCubeFree) + 0.9 - 0.0009 * Fx_ManComputeLevelDiv(p, p->vCubeFree));
+            assert( iDiv < Vec_FltSize(p->vWeights) );
+            Vec_FltAddToEntry( p->vWeights, iDiv, Base + Vec_IntSize(p->vCubeFree) - 1 );
+            p->nPairsD++;
+        }
+        else
+        {
+            assert( iDiv < Vec_FltSize(p->vWeights) );
+            Vec_FltAddToEntry( p->vWeights, iDiv, -(Base + Vec_IntSize(p->vCubeFree) - 1) );
+            p->nPairsD--;
+        }
+        if ( fUpdate )
+        {
+            if ( Vec_QueIsMember(p->vPrio, iDiv) )
+                Vec_QueUpdate( p->vPrio, iDiv );
+            else if ( !fRemove )
+                Vec_QuePush( p->vPrio, iDiv );
+        }
+    } 
+}
+void Fx_ManCreateDivisors( Fx_Man_t * p )
+{
+    Vec_Int_t * vCube;
+    float Weight;
+    int i;
+    // alloc hash table
+    assert( p->pHash == NULL );
+    p->pHash = Hsh_VecManStart( 1000 );
+    p->vWeights = Vec_FltAlloc( 1000 );
+    // create single-cube two-literal divisors
+    Vec_WecForEachLevel( p->vCubes, vCube, i )
+        Fx_ManCubeSingleCubeDivisors( p, vCube, 0, 0 ); // add - no update
+    assert( p->nDivsS == Vec_FltSize(p->vWeights) );
+    // create two-cube divisors
+    Vec_WecForEachLevel( p->vCubes, vCube, i )
+        Fx_ManCubeDoubleCubeDivisors( p, i+1, vCube, 0, 0 ); // add - no update
+    // create queue with all divisors
+    p->vPrio = Vec_QueAlloc( Vec_FltSize(p->vWeights) );
+    Vec_QueSetPriority( p->vPrio, Vec_FltArrayP(p->vWeights) );
+    Vec_FltForEachEntry( p->vWeights, Weight, i )
+        if ( Weight > 0.0 )
+            Vec_QuePush( p->vPrio, i );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compress the cubes by removing unused ones.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fx_ManCompressCubes( Vec_Wec_t * vCubes, Vec_Int_t * vLit2Cube )
+{
+    int i, CubeId, k = 0;
+    Vec_IntForEachEntry( vLit2Cube, CubeId, i )
+        if ( Vec_IntSize(Vec_WecEntry(vCubes, CubeId)) > 0 )
+            Vec_IntWriteEntry( vLit2Cube, k++, CubeId );
+    Vec_IntShrink( vLit2Cube, k );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Find command cube pairs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Fx_ManGetCubeVar( Vec_Wec_t * vCubes, int iCube )  { return Vec_IntEntry( Vec_WecEntry(vCubes, iCube), 0 );      }
+void Fx_ManFindCommonPairs( Vec_Wec_t * vCubes, Vec_Int_t * vPart0, Vec_Int_t * vPart1, Vec_Int_t * vPairs, Vec_Int_t * vCompls, Vec_Int_t * vDiv, Vec_Int_t * vCubeFree )
+{
+    int * pBeg1 = vPart0->pArray;
+    int * pBeg2 = vPart1->pArray;
+    int * pEnd1 = vPart0->pArray + vPart0->nSize;
+    int * pEnd2 = vPart1->pArray + vPart1->nSize;
+    int i, k, i_, k_, fCompl, CubeId1, CubeId2;
+    Vec_IntClear( vPairs );
+    Vec_IntClear( vCompls );
+    while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+    {
+        CubeId1 = Fx_ManGetCubeVar(vCubes, *pBeg1);
+        CubeId2 = Fx_ManGetCubeVar(vCubes, *pBeg2);
+        if ( CubeId1 == CubeId2 )
+        {
+            for ( i = 1; pBeg1+i < pEnd1; i++ )
+                if ( CubeId1 != Fx_ManGetCubeVar(vCubes, pBeg1[i]) )
+                    break;
+            for ( k = 1; pBeg2+k < pEnd2; k++ )
+                if ( CubeId1 != Fx_ManGetCubeVar(vCubes, pBeg2[k]) )
+                    break;
+            for ( i_ = 0; i_ < i; i_++ )
+            for ( k_ = 0; k_ < k; k_++ )
+            {
+                if ( pBeg1[i_] == pBeg2[k_] )
+                    continue;
+                Fx_ManDivFindCubeFree( Vec_WecEntry(vCubes, pBeg1[i_]), Vec_WecEntry(vCubes, pBeg2[k_]), vCubeFree );
+                fCompl = (Vec_IntSize(vCubeFree) == 4 && Fx_ManDivNormalize(vCubeFree) == 1);
+                if ( !Vec_IntEqual( vDiv, vCubeFree ) )
+                    continue;
+                Vec_IntPush( vPairs, pBeg1[i_] );
+                Vec_IntPush( vPairs, pBeg2[k_] );
+                Vec_IntPush( vCompls, fCompl );
+            }
+            pBeg1 += i;
+            pBeg2 += k;
+        }
+        else if ( CubeId1 < CubeId2 )
+            pBeg1++;
+        else 
+            pBeg2++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the data-structure when one divisor is selected.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fx_ManUpdate( Fx_Man_t * p, int iDiv )
+{
+    Vec_Int_t * vCube, * vCube2, * vLitP, * vLitN;
+    Vec_Int_t * vDiv = p->vDiv;
+    int nLitsNew = p->nLits - (int)Vec_FltEntry(p->vWeights, iDiv);
+    int i, k, Lit0, Lit1, iVarNew, RetValue, Level;
+    float Diff = Vec_FltEntry(p->vWeights, iDiv) - (float)((int)Vec_FltEntry(p->vWeights, iDiv));
+    assert( Diff > 0.0 && Diff < 1.0 );
+
+    // get the divisor and select pivot variables
+    p->nDivs++;
+    Vec_IntClear( vDiv );
+    Vec_IntAppend( vDiv, Hsh_VecReadEntry(p->pHash, iDiv) );
+    Fx_ManDivFindPivots( vDiv, &Lit0, &Lit1 );
+    assert( Lit0 >= 0 && Lit1 >= 0 );
+
+    // if the input cover is not prime, it may happen that we are extracting divisor (x + !x)
+    // although it is not strictly correct, it seems to be fine to just skip such divisors
+    if ( Abc_Lit2Var(Lit0) == Abc_Lit2Var(Lit1) && Vec_IntSize(Hsh_VecReadEntry(p->pHash, iDiv)) == 2 )
+        return;
+
+    // collect single-cube-divisor cubes
+    Vec_IntClear( p->vCubesS );
+    if ( Vec_IntSize(vDiv) == 2 )
+    {
+        Fx_ManCompressCubes( p->vCubes, Vec_WecEntry(p->vLits, Abc_LitNot(Lit0)) );
+        Fx_ManCompressCubes( p->vCubes, Vec_WecEntry(p->vLits, Abc_LitNot(Lit1)) );
+        Vec_IntTwoRemoveCommon( Vec_WecEntry(p->vLits, Abc_LitNot(Lit0)), Vec_WecEntry(p->vLits, Abc_LitNot(Lit1)), p->vCubesS );
+    }
+
+    // collect double-cube-divisor cube pairs
+    Fx_ManCompressCubes( p->vCubes, Vec_WecEntry(p->vLits, Lit0) );
+    Fx_ManCompressCubes( p->vCubes, Vec_WecEntry(p->vLits, Lit1) );
+    Fx_ManFindCommonPairs( p->vCubes, Vec_WecEntry(p->vLits, Lit0), Vec_WecEntry(p->vLits, Lit1), p->vCubesD, p->vCompls, vDiv, p->vCubeFree );
+
+    // subtract cost of single-cube divisors
+    Fx_ManForEachCubeVec( p->vCubesS, p->vCubes, vCube, i )
+        Fx_ManCubeSingleCubeDivisors( p, vCube, 1, 1 );  // remove - update
+    Fx_ManForEachCubeVec( p->vCubesD, p->vCubes, vCube, i )
+        Fx_ManCubeSingleCubeDivisors( p, vCube, 1, 1 );  // remove - update
+
+    // mark the cubes to be removed
+    Vec_WecMarkLevels( p->vCubes, p->vCubesS );
+    Vec_WecMarkLevels( p->vCubes, p->vCubesD );
+
+    // subtract cost of double-cube divisors
+    Fx_ManForEachCubeVec( p->vCubesS, p->vCubes, vCube, i )
+        Fx_ManCubeDoubleCubeDivisors( p, Fx_ManGetFirstVarCube(p, vCube), vCube, 1, 1 );  // remove - update
+    Fx_ManForEachCubeVec( p->vCubesD, p->vCubes, vCube, i )
+        Fx_ManCubeDoubleCubeDivisors( p, Fx_ManGetFirstVarCube(p, vCube), vCube, 1, 1 );  // remove - update
+
+    // unmark the cubes to be removed
+    Vec_WecUnmarkLevels( p->vCubes, p->vCubesS );
+    Vec_WecUnmarkLevels( p->vCubes, p->vCubesD );
+
+    // create new divisor
+    iVarNew = Vec_WecSize( p->vLits ) / 2;
+    assert( Vec_IntSize(p->vVarCube) == iVarNew );
+    Vec_IntPush( p->vVarCube, Vec_WecSize(p->vCubes) );
+    vCube = Vec_WecPushLevel( p->vCubes );
+    Vec_IntPush( vCube, iVarNew );
+    if ( Vec_IntSize(vDiv) == 2 )
+    {
+        Vec_IntPush( vCube, Abc_LitNot(Lit0) );
+        Vec_IntPush( vCube, Abc_LitNot(Lit1) );
+        Level = 1 + Fx_ManComputeLevelCube( p, vCube );
+    }
+    else
+    {
+        vCube2 = Vec_WecPushLevel( p->vCubes );
+        vCube = Vec_WecEntry( p->vCubes, Vec_WecSize(p->vCubes) - 2 );
+        Vec_IntPush( vCube2, iVarNew );
+        Fx_ManDivAddLits( vCube, vCube2, vDiv );
+        Level = 2 + Abc_MaxInt( Fx_ManComputeLevelCube(p, vCube), Fx_ManComputeLevelCube(p, vCube2) );
+    }
+    assert( Vec_IntSize(p->vLevels) == iVarNew );
+    Vec_IntPush( p->vLevels, Level );
+    // do not add new cubes to the matrix 
+    p->nLits += Vec_IntSize( vDiv );
+    // create new literals
+    vLitP = Vec_WecPushLevel( p->vLits );
+    vLitN = Vec_WecPushLevel( p->vLits );
+    vLitP = Vec_WecEntry( p->vLits, Vec_WecSize(p->vLits) - 2 );
+    // create updated single-cube divisor cubes
+    Fx_ManForEachCubeVec( p->vCubesS, p->vCubes, vCube, i )
+    {
+        RetValue  = Vec_IntRemove1( vCube, Abc_LitNot(Lit0) );
+        RetValue += Vec_IntRemove1( vCube, Abc_LitNot(Lit1) );
+        assert( RetValue == 2 );
+        Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 0) );
+        Vec_IntPush( vLitP, Vec_WecLevelId(p->vCubes, vCube) );
+        p->nLits--;
+    }
+    // create updated double-cube divisor cube pairs
+    k = 0;
+    p->nCompls = 0;
+    assert( Vec_IntSize(p->vCubesD) % 2 == 0 );
+    assert( Vec_IntSize(p->vCubesD) == 2 * Vec_IntSize(p->vCompls) );
+    for ( i = 0; i < Vec_IntSize(p->vCubesD); i += 2 )
+    {
+        int fCompl = Vec_IntEntry(p->vCompls, i/2);
+        p->nCompls += fCompl;
+        vCube  = Vec_WecEntry( p->vCubes, Vec_IntEntry(p->vCubesD, i) );
+        vCube2 = Vec_WecEntry( p->vCubes, Vec_IntEntry(p->vCubesD, i+1) );
+        RetValue  = Fx_ManDivRemoveLits( vCube, vDiv, fCompl );  // cube 2*i
+        RetValue += Fx_ManDivRemoveLits( vCube2, vDiv, fCompl ); // cube 2*i+1
+        assert( RetValue == Vec_IntSize(vDiv) );
+        if ( Vec_IntSize(vDiv) == 2 || fCompl )
+        {
+            Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 1) );
+            Vec_IntPush( vLitN, Vec_WecLevelId(p->vCubes, vCube) );
+        }
+        else 
+        {
+            Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 0) );
+            Vec_IntPush( vLitP, Vec_WecLevelId(p->vCubes, vCube) );
+        }
+        p->nLits -= Vec_IntSize(vDiv) + Vec_IntSize(vCube2) - 2;
+        // remove second cube
+        Vec_IntWriteEntry( p->vCubesD, k++, Vec_WecLevelId(p->vCubes, vCube) );
+        Vec_IntClear( vCube2 ); 
+    }
+    assert( k == Vec_IntSize(p->vCubesD) / 2 );
+    Vec_IntShrink( p->vCubesD, k );
+    Vec_IntSort( p->vCubesD, 0 );
+
+    // add cost of single-cube divisors
+    Fx_ManForEachCubeVec( p->vCubesS, p->vCubes, vCube, i )
+        Fx_ManCubeSingleCubeDivisors( p, vCube, 0, 1 );  // add - update
+    Fx_ManForEachCubeVec( p->vCubesD, p->vCubes, vCube, i )
+        Fx_ManCubeSingleCubeDivisors( p, vCube, 0, 1 );  // add - update
+
+    // mark the cubes to be removed
+    Vec_WecMarkLevels( p->vCubes, p->vCubesS );
+    Vec_WecMarkLevels( p->vCubes, p->vCubesD );
+
+    // add cost of double-cube divisors
+    Fx_ManForEachCubeVec( p->vCubesS, p->vCubes, vCube, i )
+        Fx_ManCubeDoubleCubeDivisors( p, Fx_ManGetFirstVarCube(p, vCube), vCube, 0, 1 );  // add - update
+    Fx_ManForEachCubeVec( p->vCubesD, p->vCubes, vCube, i )
+        Fx_ManCubeDoubleCubeDivisors( p, Fx_ManGetFirstVarCube(p, vCube), vCube, 0, 1 );  // add - update
+
+    // unmark the cubes to be removed
+    Vec_WecUnmarkLevels( p->vCubes, p->vCubesS );
+    Vec_WecUnmarkLevels( p->vCubes, p->vCubesD );
+
+    // add cost of the new divisor
+    if ( Vec_IntSize(vDiv) > 2 )
+    {
+        vCube  = Vec_WecEntry( p->vCubes, Vec_WecSize(p->vCubes) - 2 );
+        vCube2 = Vec_WecEntry( p->vCubes, Vec_WecSize(p->vCubes) - 1 );
+        Fx_ManCubeSingleCubeDivisors( p, vCube,  0, 1 );  // add - update
+        Fx_ManCubeSingleCubeDivisors( p, vCube2, 0, 1 );  // add - update
+        Vec_IntForEachEntryStart( vCube, Lit0, i, 1 )
+            Vec_WecPush( p->vLits, Lit0, Vec_WecLevelId(p->vCubes, vCube) );
+        Vec_IntForEachEntryStart( vCube2, Lit0, i, 1 )
+            Vec_WecPush( p->vLits, Lit0, Vec_WecLevelId(p->vCubes, vCube2) );
+    }
+
+    // remove these cubes from the lit array of the divisor
+    Vec_IntForEachEntry( vDiv, Lit0, i )
+    {
+        Vec_IntTwoRemove( Vec_WecEntry(p->vLits, Abc_Lit2Var(Lit0)), p->vCubesD );
+        if ( p->nCompls && i > 1 ) // the last two lits are possibly complemented
+            Vec_IntTwoRemove( Vec_WecEntry(p->vLits, Abc_LitNot(Abc_Lit2Var(Lit0))), p->vCubesD );
+    }
+    
+    // check predicted improvement: (new SOP lits == old SOP lits - divisor weight)
+    assert( p->nLits == nLitsNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements the traditional fast_extract algorithm.]
+
+  Description [J. Rajski and J. Vasudevamurthi, "The testability-
+  preserving concurrent decomposition and factorization of Boolean
+  expressions", IEEE TCAD, Vol. 11, No. 6, June 1992, pp. 778-793.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitCountMax, int fVerbose, int fVeryVerbose )
+{
+    int fVeryVeryVerbose = 0;
+    int i, iDiv;
+    Fx_Man_t * p;
+    abctime clk = Abc_Clock();
+    // initialize the data-structure
+    p = Fx_ManStart( vCubes );
+    p->LitCountMax = LitCountMax;
+    Fx_ManCreateLiterals( p, ObjIdMax );
+    Fx_ManComputeLevel( p );
+    Fx_ManCreateDivisors( p );
+    if ( fVeryVerbose )
+        Fx_PrintMatrix( p );
+    if ( fVerbose )
+        Fx_PrintStats( p, Abc_Clock() - clk );
+    // perform extraction
+    p->timeStart = Abc_Clock();
+    for ( i = 0; i < nNewNodesMax && Vec_QueTopPriority(p->vPrio) > 0.0; i++ )
+    {
+        iDiv = Vec_QuePop(p->vPrio);
+        if ( fVeryVerbose )
+            Fx_PrintDiv( p, iDiv );
+        Fx_ManUpdate( p, iDiv );
+        if ( fVeryVeryVerbose )
+            Fx_PrintMatrix( p );
+    }
+    if ( fVerbose )
+        Fx_PrintStats( p, Abc_Clock() - clk );
+    Fx_ManStop( p );
+    // return the result
+    Vec_WecRemoveEmpty( vCubes );
+    return 1;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcFxu.c b/abc-build/src/base/abci/abcFxu.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcFxu.c
@@ -0,0 +1,292 @@
+/**CFile****************************************************************
+
+  FileName    [abcFxu.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Interface with the fast extract package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcFxu.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "opt/fxu/fxu.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+static int  Abc_NtkFxuCheck( Abc_Ntk_t * pNtk );
+static void Abc_NtkFxuCollectInfo( Abc_Ntk_t * pNtk, Fxu_Data_t * p );
+static void Abc_NtkFxuReconstruct( Abc_Ntk_t * pNtk, Fxu_Data_t * p );
+
+extern int  Fxu_FastExtract( Fxu_Data_t * pData );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Sets default values of the FXU parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSetDefaultFxParams( Fxu_Data_t * p )
+{
+    memset( p, 0, sizeof(Fxu_Data_t) );
+    p->nSingleMax =  20000;
+    p->nPairsMax  =  30000;
+    p->nNodesExt  =1000000;
+    p->WeightMin  =      0;
+    p->LitCountMax=      0;
+    p->fOnlyS     =      0;
+    p->fOnlyD     =      0;
+    p->fUse0      =      0;
+    p->fUseCompl  =      1;
+    p->fVerbose   =      0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fast_extract on the current network.]
+
+  Description [Takes the network and the maximum number of nodes to extract.
+  Uses the concurrent double-cube and single cube divisor extraction procedure.
+  Modifies the network in the end, after extracting all nodes. Note that 
+  Ntk_NetworkSweep() may increase the performance of this procedure because 
+  the single-literal nodes will not be created in the sparse matrix. Returns 1 
+  if the network has been changed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p )
+{
+    assert( Abc_NtkIsLogic(pNtk) );
+    // if the network is already in the SOP form, it may come from BLIF file
+    // and it may not be SCC-free, in which case FXU will not work correctly
+    if ( Abc_NtkIsSopLogic(pNtk) )
+    { // to make sure the SOPs are SCC-free
+//        Abc_NtkSopToBdd(pNtk);
+//        Abc_NtkBddToSop(pNtk);
+    }
+    // get the network in the SOP form
+    if ( !Abc_NtkToSop(pNtk, 0) )
+    {
+        printf( "Abc_NtkFastExtract(): Converting to SOPs has failed.\n" );
+        return 0;
+    }
+    // check if the network meets the requirements
+    if ( !Abc_NtkFxuCheck(pNtk) )
+    {
+        printf( "Abc_NtkFastExtract: Nodes have duplicated or complemented fanins. FXU is not performed.\n" );
+        return 0;
+    }
+    // sweep removes useless nodes
+    Abc_NtkCleanup( pNtk, 0 );
+    // collect information about the covers
+    Abc_NtkFxuCollectInfo( pNtk, p );
+    // call the fast extract procedure
+    if ( Fxu_FastExtract(p) > 0 )
+    {
+        // update the network
+        Abc_NtkFxuReconstruct( pNtk, p );
+        // make sure everything is okay
+        if ( !Abc_NtkCheck( pNtk ) )
+            printf( "Abc_NtkFastExtract: The network check has failed.\n" );
+        return 1;
+    }
+    else
+        printf( "Warning: The network has not been changed by \"fx\".\n" );
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Makes sure the nodes do not have complemented and duplicated fanins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkFxuCheck( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode, * pFanin1, * pFanin2;
+    int n, i, k;
+    Abc_NtkForEachNode( pNtk, pNode, n )
+    {
+        Abc_ObjForEachFanin( pNode, pFanin1, i )
+        {
+            if ( i < 2 && Abc_ObjFaninC(pNode, i) )
+                return 0;
+            Abc_ObjForEachFanin( pNode, pFanin2, k )
+            {
+                if ( i == k )
+                    continue;
+                if ( pFanin1 == pFanin2 )
+                    return 0;
+            }
+        }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect information about the network for fast_extract.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFxuCollectInfo( Abc_Ntk_t * pNtk, Fxu_Data_t * p )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    // add information to the manager
+    p->pManSop    = (Mem_Flex_t *)pNtk->pManFunc;
+    p->vSops      = Vec_PtrAlloc(0);
+    p->vFanins    = Vec_PtrAlloc(0);
+    p->vSopsNew   = Vec_PtrAlloc(0);
+    p->vFaninsNew = Vec_PtrAlloc(0);
+    Vec_PtrFill( p->vSops,      Abc_NtkObjNumMax(pNtk), NULL );
+    Vec_PtrFill( p->vFanins,    Abc_NtkObjNumMax(pNtk), NULL );
+    Vec_PtrFill( p->vSopsNew,   Abc_NtkObjNumMax(pNtk) + p->nNodesExt, NULL );
+    Vec_PtrFill( p->vFaninsNew, Abc_NtkObjNumMax(pNtk) + p->nNodesExt, NULL );
+    // add SOPs and fanin array
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        if ( Abc_SopGetVarNum((char *)pNode->pData) < 2 )
+            continue;
+        if ( Abc_SopGetCubeNum((char *)pNode->pData) < 1 )
+            continue;
+        p->vSops->pArray[i]   = pNode->pData;
+        p->vFanins->pArray[i] = &pNode->vFanins;
+    }
+    p->nNodesOld = Abc_NtkObjNumMax(pNtk);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFxuFreeInfo( Fxu_Data_t * p )
+{
+    int i;
+    // free the arrays of new fanins
+    if ( p->vFaninsNew )
+        for ( i = 0; i < p->vFaninsNew->nSize; i++ )
+            if ( p->vFaninsNew->pArray[i] )
+                Vec_IntFree( (Vec_Int_t *)p->vFaninsNew->pArray[i] );
+    // free the arrays
+    if ( p->vSops      ) Vec_PtrFree( p->vSops      );
+    if ( p->vSopsNew   ) Vec_PtrFree( p->vSopsNew   );
+    if ( p->vFanins    ) Vec_PtrFree( p->vFanins    );
+    if ( p->vFaninsNew ) Vec_PtrFree( p->vFaninsNew );
+//    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reconstructs the network after FX.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFxuReconstruct( Abc_Ntk_t * pNtk, Fxu_Data_t * p )
+{
+    Vec_Int_t * vFanins;
+    Abc_Obj_t * pNode, * pFanin;
+    int i, k;
+
+    assert( p->vFanins->nSize < p->vFaninsNew->nSize );
+    // create the new nodes
+    for ( i = p->vFanins->nSize; i < p->vFanins->nSize + p->nNodesNew; i++ )
+    {
+        // start the node
+        pNode = Abc_NtkCreateNode( pNtk );
+        assert( i == (int)pNode->Id );
+    }
+    // update the old nodes
+    for ( i = 0; i < p->vFanins->nSize; i++ )
+    {
+        // the new array of fanins
+        vFanins = (Vec_Int_t *)p->vFaninsNew->pArray[i];
+        if ( vFanins == NULL )
+            continue;
+        // remove old fanins
+        pNode = Abc_NtkObj( pNtk, i );
+        Abc_ObjRemoveFanins( pNode );
+        // add new fanins
+        vFanins = (Vec_Int_t *)p->vFaninsNew->pArray[i];
+        for ( k = 0; k < vFanins->nSize; k++ )
+        {
+            pFanin = Abc_NtkObj( pNtk, vFanins->pArray[k] );
+            Abc_ObjAddFanin( pNode, pFanin );
+        }
+        pNode->pData = p->vSopsNew->pArray[i];
+        assert( pNode->pData != NULL );
+    }
+    // set up the new nodes
+    for ( i = p->vFanins->nSize; i < p->vFanins->nSize + p->nNodesNew; i++ )
+    {
+        // get the new node
+        pNode = Abc_NtkObj( pNtk, i );
+        // add the fanins
+        vFanins = (Vec_Int_t *)p->vFaninsNew->pArray[i];
+        for ( k = 0; k < vFanins->nSize; k++ )
+        {
+            pFanin = Abc_NtkObj( pNtk, vFanins->pArray[k] );
+            Abc_ObjAddFanin( pNode, pFanin );
+        }
+        pNode->pData = p->vSopsNew->pArray[i];
+        assert( pNode->pData != NULL );
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcGen.c b/abc-build/src/base/abci/abcGen.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcGen.c
@@ -0,0 +1,807 @@
+/**CFile****************************************************************
+
+  FileName    [abcGen.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Procedures to generate various type of circuits.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcGen.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_WriteFullAdder( FILE * pFile )
+{
+    fprintf( pFile, ".model FA\n" );
+    fprintf( pFile, ".inputs a b cin\n" ); 
+    fprintf( pFile, ".outputs s cout\n" ); 
+    fprintf( pFile, ".names a b k\n" ); 
+    fprintf( pFile, "10 1\n" ); 
+    fprintf( pFile, "01 1\n" ); 
+    fprintf( pFile, ".names k cin s\n" ); 
+    fprintf( pFile, "10 1\n" ); 
+    fprintf( pFile, "01 1\n" ); 
+    fprintf( pFile, ".names a b cin cout\n" ); 
+    fprintf( pFile, "11- 1\n" ); 
+    fprintf( pFile, "1-1 1\n" ); 
+    fprintf( pFile, "-11 1\n" ); 
+    fprintf( pFile, ".end\n" ); 
+    fprintf( pFile, "\n" ); 
+}
+void Abc_WriteAdder( FILE * pFile, int nVars )
+{
+    int i, nDigits = Abc_Base10Log( nVars );
+
+    assert( nVars > 0 );
+    fprintf( pFile, ".model ADD%d\n", nVars );
+
+    fprintf( pFile, ".inputs" );
+    for ( i = 0; i < nVars; i++ )
+        fprintf( pFile, " a%0*d", nDigits, i );
+    for ( i = 0; i < nVars; i++ )
+        fprintf( pFile, " b%0*d", nDigits, i );
+    fprintf( pFile, "\n" );
+
+    fprintf( pFile, ".outputs" );
+    for ( i = 0; i <= nVars; i++ )
+        fprintf( pFile, " s%0*d", nDigits, i );
+    fprintf( pFile, "\n" );
+
+    fprintf( pFile, ".names c\n" );
+    if ( nVars == 1 )
+        fprintf( pFile, ".subckt FA a=a0 b=b0 cin=c s=y0 cout=s1\n" );
+    else
+    {
+        fprintf( pFile, ".subckt FA a=a%0*d b=b%0*d cin=c s=s%0*d cout=%0*d\n", nDigits, 0, nDigits, 0, nDigits, 0, nDigits, 0 );
+        for ( i = 1; i < nVars-1; i++ )
+            fprintf( pFile, ".subckt FA a=a%0*d b=b%0*d cin=%0*d s=s%0*d cout=%0*d\n", nDigits, i, nDigits, i, nDigits, i-1, nDigits, i, nDigits, i );
+        fprintf( pFile, ".subckt FA a=a%0*d b=b%0*d cin=%0*d s=s%0*d cout=s%0*d\n", nDigits, i, nDigits, i, nDigits, i-1, nDigits, i, nDigits, i+1 );
+    }
+    fprintf( pFile, ".end\n" ); 
+    fprintf( pFile, "\n" );
+    Abc_WriteFullAdder( pFile );
+}
+void Abc_GenAdder( char * pFileName, int nVars )
+{
+    FILE * pFile;
+    assert( nVars > 0 );
+    pFile = fopen( pFileName, "w" );
+    fprintf( pFile, "# %d-bit ripple-carry adder generated by ABC on %s\n", nVars, Extra_TimeStamp() );
+    Abc_WriteAdder( pFile, nVars );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_WriteMulti( FILE * pFile, int nVars )
+{
+    int i, k, nDigits = Abc_Base10Log( nVars ), nDigits2 = Abc_Base10Log( 2*nVars );
+
+    assert( nVars > 0 );
+    fprintf( pFile, ".model Multi%d\n", nVars );
+
+    fprintf( pFile, ".inputs" );
+    for ( i = 0; i < nVars; i++ )
+        fprintf( pFile, " a%0*d", nDigits, i );
+    for ( i = 0; i < nVars; i++ )
+        fprintf( pFile, " b%0*d", nDigits, i );
+    fprintf( pFile, "\n" );
+
+    fprintf( pFile, ".outputs" );
+    for ( i = 0; i < 2*nVars; i++ )
+        fprintf( pFile, " m%0*d", nDigits2, i );
+    fprintf( pFile, "\n" );
+
+    for ( i = 0; i < 2*nVars; i++ )
+        fprintf( pFile, ".names x%0*d_%0*d\n", nDigits, 0, nDigits2, i );
+    for ( k = 0; k < nVars; k++ )
+    {
+        for ( i = 0; i < 2 * nVars; i++ )
+            if ( i >= k && i < k + nVars )
+                fprintf( pFile, ".names b%0*d a%0*d y%0*d_%0*d\n11 1\n", nDigits, k, nDigits, i-k, nDigits, k, nDigits2, i );
+            else
+                fprintf( pFile, ".names y%0*d_%0*d\n", nDigits, k, nDigits2, i );
+        fprintf( pFile, ".subckt ADD%d", 2*nVars );
+        for ( i = 0; i < 2*nVars; i++ )
+            fprintf( pFile, " a%0*d=x%0*d_%0*d", nDigits2, i, nDigits, k, nDigits2, i );
+        for ( i = 0; i < 2*nVars; i++ )
+            fprintf( pFile, " b%0*d=y%0*d_%0*d", nDigits2, i, nDigits, k, nDigits2, i );
+        for ( i = 0; i <= 2*nVars; i++ )
+            fprintf( pFile, " s%0*d=x%0*d_%0*d", nDigits2, i, nDigits, k+1, nDigits2, i );
+        fprintf( pFile, "\n" );
+    }
+    for ( i = 0; i < 2 * nVars; i++ )
+        fprintf( pFile, ".names x%0*d_%0*d m%0*d\n1 1\n", nDigits, k, nDigits2, i, nDigits2, i );
+    fprintf( pFile, ".end\n" ); 
+    fprintf( pFile, "\n" );
+    Abc_WriteAdder( pFile, 2*nVars );
+}
+void Abc_GenMulti( char * pFileName, int nVars )
+{
+    FILE * pFile;
+    assert( nVars > 0 );
+    pFile = fopen( pFileName, "w" );
+    fprintf( pFile, "# %d-bit multiplier generated by ABC on %s\n", nVars, Extra_TimeStamp() );
+    Abc_WriteMulti( pFile, nVars );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_WriteComp( FILE * pFile )
+{
+    fprintf( pFile, ".model Comp\n" );
+    fprintf( pFile, ".inputs a b\n" ); 
+    fprintf( pFile, ".outputs x y\n" ); 
+    fprintf( pFile, ".names a b x\n" ); 
+    fprintf( pFile, "11 1\n" ); 
+    fprintf( pFile, ".names a b y\n" ); 
+    fprintf( pFile, "1- 1\n" ); 
+    fprintf( pFile, "-1 1\n" ); 
+    fprintf( pFile, ".end\n" ); 
+    fprintf( pFile, "\n" ); 
+}
+void Abc_WriteLayer( FILE * pFile, int nVars, int fSkip1 )
+{
+    int i;
+    fprintf( pFile, ".model Layer%d\n", fSkip1 );
+    fprintf( pFile, ".inputs" ); 
+    for ( i = 0; i < nVars; i++ )
+        fprintf( pFile, " x%02d", i ); 
+    fprintf( pFile, "\n" ); 
+    fprintf( pFile, ".outputs" ); 
+    for ( i = 0; i < nVars; i++ )
+        fprintf( pFile, " y%02d", i ); 
+    fprintf( pFile, "\n" ); 
+    if ( fSkip1 )
+    {
+        fprintf( pFile, ".names x00 y00\n" ); 
+        fprintf( pFile, "1 1\n" ); 
+        i = 1;
+    }
+    else
+        i = 0;
+    for ( ; i + 1 < nVars; i += 2 )
+        fprintf( pFile, ".subckt Comp a=x%02d b=x%02d x=y%02d y=y%02d\n", i, i+1, i, i+1 );
+    if ( i < nVars )
+    {
+        fprintf( pFile, ".names x%02d y%02d\n", i, i ); 
+        fprintf( pFile, "1 1\n" ); 
+    }
+    fprintf( pFile, ".end\n" ); 
+    fprintf( pFile, "\n" ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_GenSorter( char * pFileName, int nVars )
+{
+    FILE * pFile;
+    int i, k, Counter, nDigits;
+
+    assert( nVars > 1 );
+
+    pFile = fopen( pFileName, "w" );
+    fprintf( pFile, "# %d-bit sorter generated by ABC on %s\n", nVars, Extra_TimeStamp() );
+    fprintf( pFile, ".model Sorter%02d\n", nVars );
+
+    fprintf( pFile, ".inputs" );
+    for ( i = 0; i < nVars; i++ )
+        fprintf( pFile, " x%02d", i );
+    fprintf( pFile, "\n" );
+
+    fprintf( pFile, ".outputs" );
+    for ( i = 0; i < nVars; i++ )
+        fprintf( pFile, " y%02d", i );
+    fprintf( pFile, "\n" );
+
+    Counter = 0;
+    nDigits = Abc_Base10Log( (nVars-2)*nVars );
+    if ( nVars == 2 )
+        fprintf( pFile, ".subckt Comp a=x00 b=x01 x=y00 y=y01\n" );
+    else
+    {
+        fprintf( pFile, ".subckt Layer0" );
+        for ( k = 0; k < nVars; k++ )
+            fprintf( pFile, " x%02d=x%02d", k, k );
+        for ( k = 0; k < nVars; k++ )
+            fprintf( pFile, " y%02d=%0*d", k, nDigits, Counter++ );
+        fprintf( pFile, "\n" );
+        Counter -= nVars;
+        for ( i = 1; i < 2*nVars-2; i++ )
+        {
+            fprintf( pFile, ".subckt Layer%d", (i&1) );
+            for ( k = 0; k < nVars; k++ )
+                fprintf( pFile, " x%02d=%0*d", k, nDigits, Counter++ );
+            for ( k = 0; k < nVars; k++ )
+                fprintf( pFile, " y%02d=%0*d", k, nDigits, Counter++ );
+            fprintf( pFile, "\n" );
+            Counter -= nVars;
+        }
+        fprintf( pFile, ".subckt Layer%d", (i&1) );
+        for ( k = 0; k < nVars; k++ )
+            fprintf( pFile, " x%02d=%0*d", k, nDigits, Counter++ );
+        for ( k = 0; k < nVars; k++ )
+            fprintf( pFile, " y%02d=y%02d", k, k );
+        fprintf( pFile, "\n" );
+    }
+    fprintf( pFile, ".end\n" ); 
+    fprintf( pFile, "\n" );
+
+    Abc_WriteLayer( pFile, nVars, 0 );
+    Abc_WriteLayer( pFile, nVars, 1 );
+    Abc_WriteComp( pFile );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_WriteCell( FILE * pFile )
+{
+    fprintf( pFile, ".model cell\n" );
+    fprintf( pFile, ".inputs px1 px2 py1 py2 x y\n" ); 
+    fprintf( pFile, ".outputs fx fy\n" ); 
+    fprintf( pFile, ".names x y a\n" ); 
+    fprintf( pFile, "11 1\n" ); 
+    fprintf( pFile, ".names px1 a x nx\n" ); 
+    fprintf( pFile, "11- 1\n" ); 
+    fprintf( pFile, "0-1 1\n" ); 
+    fprintf( pFile, ".names py1 a y ny\n" ); 
+    fprintf( pFile, "11- 1\n" ); 
+    fprintf( pFile, "0-1 1\n" ); 
+    fprintf( pFile, ".names px2 nx fx\n" ); 
+    fprintf( pFile, "10 1\n" ); 
+    fprintf( pFile, "01 1\n" ); 
+    fprintf( pFile, ".names py2 ny fy\n" ); 
+    fprintf( pFile, "10 1\n" ); 
+    fprintf( pFile, "01 1\n" ); 
+    fprintf( pFile, ".end\n" ); 
+    fprintf( pFile, "\n" ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_GenMesh( char * pFileName, int nVars )
+{
+    FILE * pFile;
+    int i, k;
+
+    assert( nVars > 0 );
+
+    pFile = fopen( pFileName, "w" );
+    fprintf( pFile, "# %dx%d mesh generated by ABC on %s\n", nVars, nVars, Extra_TimeStamp() );
+    fprintf( pFile, ".model mesh%d\n", nVars );
+
+    for ( i = 0; i < nVars; i++ )
+        for ( k = 0; k < nVars; k++ )
+        {
+            fprintf( pFile, ".inputs" );
+            fprintf( pFile, " p%d%dx1", i, k );
+            fprintf( pFile, " p%d%dx2", i, k );
+            fprintf( pFile, " p%d%dy1", i, k );
+            fprintf( pFile, " p%d%dy2", i, k );
+            fprintf( pFile, "\n" );
+        }
+    fprintf( pFile, ".inputs" );
+    for ( i = 0; i < nVars; i++ )
+        fprintf( pFile, " v%02d v%02d", 2*i, 2*i+1 );
+    fprintf( pFile, "\n" );
+
+    fprintf( pFile, ".outputs" );
+    fprintf( pFile, " fx00" );
+    fprintf( pFile, "\n" );
+
+    for ( i = 0; i < nVars; i++ ) // horizontal
+        for ( k = 0; k < nVars; k++ ) // vertical
+        {
+            fprintf( pFile, ".subckt cell" );
+            fprintf( pFile, " px1=p%d%dx1", i, k );
+            fprintf( pFile, " px2=p%d%dx2", i, k );
+            fprintf( pFile, " py1=p%d%dy1", i, k );
+            fprintf( pFile, " py2=p%d%dy2", i, k );
+            if ( k == nVars - 1 )
+                fprintf( pFile, " x=v%02d", i );
+            else
+                fprintf( pFile, " x=fx%d%d", i, k+1 );
+            if ( i == nVars - 1 )
+                fprintf( pFile, " y=v%02d", nVars+k );
+            else
+                fprintf( pFile, " y=fy%d%d", i+1, k );
+            // outputs
+            fprintf( pFile, " fx=fx%d%d", i, k );
+            fprintf( pFile, " fy=fy%d%d", i, k );
+            fprintf( pFile, "\n" );
+        }
+    fprintf( pFile, ".end\n" ); 
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    Abc_WriteCell( pFile );
+    fclose( pFile );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_WriteKLut( FILE * pFile, int nLutSize )
+{
+    int i, iVar, iNext, nPars = (1 << nLutSize);
+    fprintf( pFile, "\n" ); 
+    fprintf( pFile, ".model lut%d\n", nLutSize );
+    fprintf( pFile, ".inputs" );
+    for ( i = 0; i < nPars; i++ )
+        fprintf( pFile, " p%02d", i );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, ".inputs" );
+    for ( i = 0; i < nLutSize; i++ )
+        fprintf( pFile, " i%d", i );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, ".outputs o\n" ); 
+    fprintf( pFile, ".names n01 o\n" ); 
+    fprintf( pFile, "1 1\n" ); 
+    // write internal MUXes
+    iVar = 0;
+    iNext = 2;
+    for ( i = 1; i < nPars; i++ )
+    {
+        if ( i == iNext )
+        {
+            iNext *= 2;
+            iVar++; 
+        }
+        if ( iVar == nLutSize - 1 )
+            fprintf( pFile, ".names i%d p%02d p%02d n%02d\n", iVar, 2*(i-nPars/2), 2*(i-nPars/2)+1, i ); 
+        else
+            fprintf( pFile, ".names i%d n%02d n%02d n%02d\n", iVar, 2*i, 2*i+1, i ); 
+        fprintf( pFile, "01- 1\n" ); 
+        fprintf( pFile, "1-1 1\n" ); 
+    }
+    fprintf( pFile, ".end\n" ); 
+    fprintf( pFile, "\n" ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generates structure of L K-LUTs implementing an N-var function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars )
+{
+    int fGenerateFunc = 1;
+    FILE * pFile;
+    int nVarsLut = (1 << nLutSize);                     // the number of LUT variables
+    int nVarsLog = Abc_Base2Log( nVars + nLuts - 1 ); // the number of encoding vars
+    int nVarsDeg = (1 << nVarsLog);                     // the number of LUT variables (total)
+    int nParsLut = nLuts * (1 << nLutSize);             // the number of LUT params
+    int nParsVar = nLuts * nLutSize * nVarsLog;         // the number of var params
+    int i, j, k;
+
+    assert( nVars > 0 );
+
+    pFile = fopen( pFileName, "w" );
+    fprintf( pFile, "# Structure with %d %d-LUTs for %d-var function generated by ABC on %s\n", nLuts, nLutSize, nVars, Extra_TimeStamp() );
+    fprintf( pFile, ".model struct%dx%d_%d\n", nLuts, nLutSize, nVars );
+
+    fprintf( pFile, ".inputs" );
+    for ( i = 0; i < nParsLut; i++ )
+    {
+//        if ( i % (1 << nLutSize) == 0 && i != (nLuts - 1) * (1 << nLutSize) )
+//            continue;
+        fprintf( pFile, " pl%02d", i );
+    }
+    fprintf( pFile, "\n" );
+
+    fprintf( pFile, ".inputs" );
+    for ( i = 0; i < nParsVar; i++ )
+        fprintf( pFile, " pv%02d", i );
+    fprintf( pFile, "\n" );
+
+    fprintf( pFile, ".inputs" );
+    for ( i = 0; i < nVars; i++ )
+        fprintf( pFile, " v%02d", i );
+    fprintf( pFile, "\n" );
+
+    fprintf( pFile, ".outputs" );
+//    fprintf( pFile, " v%02d", nVars + nLuts - 1 );
+    fprintf( pFile, " out" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, ".names Gnd\n" ); 
+    fprintf( pFile, " 0\n" ); 
+
+    // generate function
+    if ( fGenerateFunc )
+    {
+        fprintf( pFile, ".names v%02d func out\n", nVars + nLuts - 1 );
+        fprintf( pFile, "00 1\n11 1\n" );
+        fprintf( pFile, ".names" );
+        for ( i = 0; i < nVars; i++ )
+            fprintf( pFile, " v%02d", i );
+        fprintf( pFile, " func\n" );
+        for ( i = 0; i < nVars; i++ )
+            fprintf( pFile, "1" );
+        fprintf( pFile, " 1\n" );
+    }
+    else
+        fprintf( pFile, ".names v%02d out\n1 1\n", nVars + nLuts - 1 );
+
+    // generate LUTs
+    for ( i = 0; i < nLuts; i++ )
+    {
+        fprintf( pFile, ".subckt lut%d", nLutSize );
+        // generate config parameters
+        for ( k = 0; k < nVarsLut; k++ )
+            fprintf( pFile, " p%02d=pl%02d", k, i * nVarsLut + k );
+        // generate the inputs
+        for ( k = 0; k < nLutSize; k++ )
+            fprintf( pFile, " i%d=s%02d", k, i * nLutSize + k );
+        // generate the output
+        fprintf( pFile, " o=v%02d", nVars + i );
+        fprintf( pFile, "\n" );
+    }
+
+    // generate LUT inputs
+    for ( i = 0; i < nLuts; i++ )
+    {
+        for ( j = 0; j < nLutSize; j++ )
+        {
+            fprintf( pFile, ".subckt lut%d", nVarsLog );
+            // generate config parameters
+            for ( k = 0; k < nVarsDeg; k++ )
+            {
+                if ( k < nVars + nLuts - 1 && k < nVars + i )
+                    fprintf( pFile, " p%02d=v%02d", k, k );
+                else
+                    fprintf( pFile, " p%02d=Gnd", k );
+            }
+            // generate the inputs
+            for ( k = 0; k < nVarsLog; k++ )
+                fprintf( pFile, " i%d=pv%02d", k, (i * nLutSize + j) * nVarsLog + k );
+            // generate the output
+            fprintf( pFile, " o=s%02d", i * nLutSize + j );
+            fprintf( pFile, "\n" );
+        }
+    }
+
+    fprintf( pFile, ".end\n" ); 
+    fprintf( pFile, "\n" ); 
+
+    // generate LUTs
+    Abc_WriteKLut( pFile, nLutSize );
+    if ( nVarsLog != nLutSize )
+        Abc_WriteKLut( pFile, nVarsLog );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generates structure of L K-LUTs implementing an N-var function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_GenOneHot( char * pFileName, int nVars )
+{
+    FILE * pFile;
+    int i, k, Counter, nDigitsIn, nDigitsOut;
+    pFile = fopen( pFileName, "w" );
+    fprintf( pFile, "# One-hotness condition for %d vars generated by ABC on %s\n", nVars, Extra_TimeStamp() );
+    fprintf( pFile, ".model 1hot_%dvars\n", nVars );
+    fprintf( pFile, ".inputs" );
+    nDigitsIn = Abc_Base10Log( nVars );
+    for ( i = 0; i < nVars; i++ )
+        fprintf( pFile, " i%0*d", nDigitsIn, i );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, ".outputs" );
+    nDigitsOut = Abc_Base10Log( nVars * (nVars - 1) / 2 );
+    for ( i = 0; i < nVars * (nVars - 1) / 2; i++ )
+        fprintf( pFile, " o%0*d", nDigitsOut, i );
+    fprintf( pFile, "\n" );
+    Counter = 0;
+    for ( i = 0; i < nVars; i++ )
+        for ( k = i+1; k < nVars; k++ )
+        {
+            fprintf( pFile, ".names i%0*d i%0*d o%0*d\n", nDigitsIn, i, nDigitsIn, k, nDigitsOut, Counter ); 
+            fprintf( pFile, "11 0\n" ); 
+            Counter++;
+        }
+    fprintf( pFile, ".end\n" ); 
+    fprintf( pFile, "\n" ); 
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generates structure of L K-LUTs implementing an N-var function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_GenOneHotIntervals( char * pFileName, int nPis, int nRegs, Vec_Ptr_t * vOnehots )
+{
+    Vec_Int_t * vLine;
+    FILE * pFile;
+    int i, j, k, iReg1, iReg2, Counter, Counter2, nDigitsIn, nDigitsOut;
+    pFile = fopen( pFileName, "w" );
+    fprintf( pFile, "# One-hotness with %d vars and %d regs generated by ABC on %s\n", nPis, nRegs, Extra_TimeStamp() );
+    fprintf( pFile, "# Used %d intervals of 1-hot registers: { ", Vec_PtrSize(vOnehots) );
+    Counter = 0;
+    Vec_PtrForEachEntry( Vec_Int_t *, vOnehots, vLine, k )
+    {
+        fprintf( pFile, "%d ", Vec_IntSize(vLine) );
+        Counter += Vec_IntSize(vLine) * (Vec_IntSize(vLine) - 1) / 2;
+    }
+    fprintf( pFile, "}\n" );
+    fprintf( pFile, ".model 1hot_%dvars_%dregs\n", nPis, nRegs );
+    fprintf( pFile, ".inputs" );
+    nDigitsIn = Abc_Base10Log( nPis+nRegs );
+    for ( i = 0; i < nPis+nRegs; i++ )
+        fprintf( pFile, " i%0*d", nDigitsIn, i );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, ".outputs" );
+    nDigitsOut = Abc_Base10Log( Counter );
+    for ( i = 0; i < Counter; i++ )
+        fprintf( pFile, " o%0*d", nDigitsOut, i );
+    fprintf( pFile, "\n" );
+    Counter2 = 0;
+    Vec_PtrForEachEntry( Vec_Int_t *, vOnehots, vLine, k )
+    {
+        Vec_IntForEachEntry( vLine, iReg1, i )
+        Vec_IntForEachEntryStart( vLine, iReg2, j, i+1 )
+        {
+            fprintf( pFile, ".names i%0*d i%0*d o%0*d\n", nDigitsIn, nPis+iReg1, nDigitsIn, nPis+iReg2, nDigitsOut, Counter2 ); 
+            fprintf( pFile, "11 0\n" ); 
+            Counter2++;
+        }
+    }
+    assert( Counter == Counter2 );
+    fprintf( pFile, ".end\n" ); 
+    fprintf( pFile, "\n" ); 
+    fclose( pFile );
+}
+
+ABC_NAMESPACE_IMPL_END
+
+#include "aig/aig/aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/**Function*************************************************************
+
+  Synopsis    [Generates structure of L K-LUTs implementing an N-var function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_GenRandom( char * pFileName, int nPis )
+{
+    FILE * pFile;
+    unsigned * pTruth;
+    int i, b, w, nWords = Abc_TruthWordNum( nPis );
+    int nDigitsIn;
+    Aig_ManRandom( 1 );
+    pTruth = ABC_ALLOC( unsigned, nWords );
+    for ( w = 0; w < nWords; w++ )
+        pTruth[w] = Aig_ManRandom( 0 );
+    pFile = fopen( pFileName, "w" );
+    fprintf( pFile, "# Random function with %d inputs generated by ABC on %s\n", nPis, Extra_TimeStamp() );
+    fprintf( pFile, ".model rand%d\n", nPis );
+    fprintf( pFile, ".inputs" );
+    nDigitsIn = Abc_Base10Log( nPis );
+    for ( i = 0; i < nPis; i++ )
+        fprintf( pFile, " i%0*d", nDigitsIn, i );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, ".outputs f\n" );
+    fprintf( pFile, ".names" );
+    nDigitsIn = Abc_Base10Log( nPis );
+    for ( i = 0; i < nPis; i++ )
+        fprintf( pFile, " i%0*d", nDigitsIn, i );
+    fprintf( pFile, " f\n" );
+    for ( i = 0; i < (1<<nPis); i++ )
+        if ( Abc_InfoHasBit(pTruth, i) )
+        {
+            for ( b = nPis-1; b >= 0; b-- )
+                fprintf( pFile, "%d", (i>>b)&1 );
+            fprintf( pFile, " 1\n" );
+        }
+    fprintf( pFile, ".end\n" ); 
+    fprintf( pFile, "\n" ); 
+    fclose( pFile );
+    ABC_FREE( pTruth );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Generates structure of L K-LUTs implementing an N-var function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_GenFsmCond( Vec_Str_t * vCond, int nPis, int Prob )
+{
+    int i, Rand;
+    Vec_StrClear( vCond );
+    for ( i = 0; i < nPis; i++ )
+    {
+        Rand = Aig_ManRandom( 0 );
+        if ( Rand % 100 > Prob )
+            Vec_StrPush( vCond, '-' );
+        else if ( Rand & 1 )
+            Vec_StrPush( vCond, '1' );
+        else
+            Vec_StrPush( vCond, '0' );
+    }
+    Vec_StrPush( vCond, '\0' );
+}
+void Abc_GenFsm( char * pFileName, int nPis, int nPos, int nStates, int nLines, int ProbI, int ProbO )
+{
+    FILE * pFile;
+    Vec_Wrd_t * vStates;
+    Vec_Str_t * vCond;
+    int i, iState, iState2;
+    int nDigits = Abc_Base10Log( nStates );
+    Aig_ManRandom( 1 );
+    vStates = Vec_WrdAlloc( nLines );
+    vCond = Vec_StrAlloc( 1000 );
+    for ( i = 0; i < nStates; )
+    {
+        iState = Aig_ManRandom( 0 ) % nStates;
+        if ( iState == i )
+            continue;
+        Vec_WrdPush( vStates, ((word)i << 32) | iState );
+        i++;
+    }
+    for (      ; i < nLines; )
+    {
+        iState = Aig_ManRandom( 0 ) % nStates;
+        iState2 = Aig_ManRandom( 0 ) % nStates;
+        if ( iState2 == iState )
+            continue;
+        Vec_WrdPush( vStates, ((word)iState << 32) | iState2 );
+        i++;
+    }
+    Vec_WrdSort( vStates, 0 );
+    // write the file
+    pFile = fopen( pFileName, "w" );
+    fprintf( pFile, "# This random FSM was generated by ABC on %s\n", Extra_TimeStamp() );
+    fprintf( pFile, "# Command line was: \"genfsm -I %d -O %d -S %d -L %d -P %d -Q %d %s\"\n", nPis, nPos, nStates, nLines, ProbI, ProbO, pFileName );
+    fprintf( pFile, "# FSM has %d inputs, %d outputs, %d states, and %d products\n", nPis, nPos, nStates, nLines );
+    fprintf( pFile, ".i %d\n", nPis );
+    fprintf( pFile, ".o %d\n", nPos );
+    fprintf( pFile, ".p %d\n", nLines );
+    fprintf( pFile, ".s %d\n", nStates );
+    for ( i = 0; i < nLines; i++ )
+    {
+        Abc_GenFsmCond( vCond, nPis, ProbI );
+        fprintf( pFile, "%s ", Vec_StrArray(vCond) );
+        fprintf( pFile, "%0*d ", nDigits, (int)(Vec_WrdEntry(vStates, i) >> 32) );
+        fprintf( pFile, "%0*d ", nDigits, (int)(Vec_WrdEntry(vStates, i)) );
+        if ( nPos > 0 )
+        {
+            Abc_GenFsmCond( vCond, nPos, ProbO );
+            fprintf( pFile, "%s", Vec_StrArray(vCond) );
+        }
+        fprintf( pFile, "\n" );
+    }
+    fprintf( pFile, ".e" );
+    fprintf( pFile, "\n" );
+    fclose( pFile );
+    Vec_WrdFree( vStates );
+    Vec_StrFree( vCond );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcHaig.c b/abc-build/src/base/abci/abcHaig.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcHaig.c
@@ -0,0 +1,557 @@
+/**CFile****************************************************************
+
+  FileName    [abcHaig.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Implements history AIG for combinational rewriting.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcHaig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the nodes in the classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkHaigCollectMembers( Hop_Man_t * p )
+{
+    Vec_Ptr_t * vObjs;
+    Hop_Obj_t * pObj;
+    int i;
+    vObjs = Vec_PtrAlloc( 4098 );
+    Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
+    {
+        if ( pObj->pData == NULL )
+            continue;
+        pObj->pData = Hop_ObjRepr( pObj );
+        Vec_PtrPush( vObjs, pObj );
+    }
+    return vObjs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkHaigCreateClasses( Vec_Ptr_t * vMembers )
+{
+    Vec_Ptr_t * vClasses;
+    Hop_Obj_t * pObj, * pRepr;
+    int i;
+
+    // count classes
+    vClasses = Vec_PtrAlloc( 4098 );
+    Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i )
+    {
+        pRepr = (Hop_Obj_t *)pObj->pData;
+        assert( pRepr->pData == NULL );
+        if ( pRepr->fMarkA == 0 ) // new
+        {
+            pRepr->fMarkA = 1;
+            Vec_PtrPush( vClasses, pRepr );
+        }
+    }
+
+    // set representatives as representatives
+    Vec_PtrForEachEntry( Hop_Obj_t *, vClasses, pObj, i )
+    {
+        pObj->fMarkA = 0;
+        pObj->pData = pObj;
+    }
+
+    // go through the members and update
+    Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i )
+    {
+        pRepr = (Hop_Obj_t *)pObj->pData;
+        if ( ((Hop_Obj_t *)pRepr->pData)->Id > pObj->Id )
+            pRepr->pData = pObj;
+    }
+
+    // change representatives of the class
+    Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i )
+    {
+        pRepr = (Hop_Obj_t *)pObj->pData;
+        pObj->pData = pRepr->pData;
+        assert( ((Hop_Obj_t *)pObj->pData)->Id <= pObj->Id );
+    }
+
+    // update classes
+    Vec_PtrForEachEntry( Hop_Obj_t *, vClasses, pObj, i )
+    {
+        pRepr = (Hop_Obj_t *)pObj->pData;
+        assert( pRepr->pData == pRepr );
+//        pRepr->pData = NULL;
+        Vec_PtrWriteEntry( vClasses, i, pRepr );
+        Vec_PtrPush( vMembers, pObj );
+    }
+
+    Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i )
+        if ( pObj->pData == pObj )
+            pObj->pData = NULL;
+
+/*
+    Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i )
+    {
+        printf( "ObjId = %4d : ", pObj->Id );
+        if ( pObj->pData == NULL )
+        {
+            printf( "NULL" );
+        }
+        else
+        {
+            printf( "%4d", ((Hop_Obj_t *)pObj->pData)->Id );
+            assert( ((Hop_Obj_t *)pObj->pData)->Id <= pObj->Id );
+        }
+        printf( "\n" );
+    }
+*/
+    return vClasses;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts how many data members have non-trivial fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkHaigCountFans( Hop_Man_t * p )
+{
+    Hop_Obj_t * pObj;
+    int i, Counter = 0;
+    Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
+    {
+        if ( pObj->pData == NULL )
+            continue;
+        if ( Hop_ObjRefs(pObj) > 0 )
+            Counter++;
+    }
+    printf( "The number of class members with fanouts = %5d.\n", Counter );
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Hop_Obj_t * Hop_ObjReprHop( Hop_Obj_t * pObj )
+{
+    Hop_Obj_t * pRepr;
+    assert( pObj->pNext != NULL );
+    if ( pObj->pData == NULL )
+        return pObj->pNext;
+    pRepr = (Hop_Obj_t *)pObj->pData;
+    assert( pRepr->pData == pRepr );
+    return Hop_NotCond( pRepr->pNext, pObj->fPhase ^ pRepr->fPhase );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Hop_Obj_t * Hop_ObjChild0Hop( Hop_Obj_t * pObj ) { return Hop_NotCond( Hop_ObjReprHop(Hop_ObjFanin0(pObj)), Hop_ObjFaninC0(pObj) ); }
+static inline Hop_Obj_t * Hop_ObjChild1Hop( Hop_Obj_t * pObj ) { return Hop_NotCond( Hop_ObjReprHop(Hop_ObjFanin1(pObj)), Hop_ObjFaninC1(pObj) ); }
+
+/**Function*************************************************************
+
+  Synopsis    [Stops history AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Man_t * Abc_NtkHaigReconstruct( Hop_Man_t * p )
+{ 
+    Hop_Man_t * pNew;
+    Hop_Obj_t * pObj;
+    int i, Counter = 0;
+    Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
+        pObj->pNext = NULL;
+    // start the HOP package
+    pNew = Hop_ManStart();
+    pNew->vObjs = Vec_PtrAlloc( p->nCreated );
+    Vec_PtrPush( pNew->vObjs, Hop_ManConst1(pNew) );
+    // map the constant node
+    Hop_ManConst1(p)->pNext = Hop_ManConst1(pNew);
+    // map the CIs
+    Hop_ManForEachPi( p, pObj, i )
+        pObj->pNext = Hop_ObjCreatePi(pNew);
+    // map the internal nodes
+    Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
+    {
+        if ( !Hop_ObjIsNode(pObj) )
+            continue;
+        pObj->pNext = Hop_And( pNew, Hop_ObjChild0Hop(pObj), Hop_ObjChild1Hop(pObj) );
+//        assert( !Hop_IsComplement(pObj->pNext) );
+        if ( Hop_ManConst1(pNew) == Hop_Regular(pObj->pNext) )
+            Counter++;
+        if ( pObj->pData ) // member of the class
+            Hop_Regular(pObj->pNext)->pData = Hop_Regular(((Hop_Obj_t *)pObj->pData)->pNext);
+    }
+//    printf( " Counter = %d.\n", Counter );
+    // transfer the POs
+    Hop_ManForEachPo( p, pObj, i )
+        Hop_ObjCreatePo( pNew, Hop_ObjChild0Hop(pObj) );
+    // check the new manager
+    if ( !Hop_ManCheck(pNew) )
+    {
+        printf( "Abc_NtkHaigReconstruct: Check for History AIG has failed.\n" );
+        Hop_ManStop(pNew);
+        return NULL;
+    }
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pOld is in the TFI of pNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkHaigCheckTfi_rec( Abc_Obj_t * pNode, Abc_Obj_t * pOld )
+{
+    if ( pNode == NULL )
+        return 0;
+    if ( pNode == pOld )
+        return 1;
+    // check the trivial cases
+    if ( Abc_ObjIsCi(pNode) )
+        return 0;
+    assert( Abc_ObjIsNode(pNode) );
+    // if this node is already visited, skip
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return 0;
+    // mark the node as visited
+    Abc_NodeSetTravIdCurrent( pNode );
+    // check the children
+    if ( Abc_NtkHaigCheckTfi_rec( Abc_ObjFanin0(pNode), pOld ) )
+        return 1;
+    if ( Abc_NtkHaigCheckTfi_rec( Abc_ObjFanin1(pNode), pOld ) )
+        return 1;
+    // check equivalent nodes
+    return Abc_NtkHaigCheckTfi_rec( (Abc_Obj_t *)pNode->pData, pOld );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pOld is in the TFI of pNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkHaigCheckTfi( Abc_Ntk_t * pNtk, Abc_Obj_t * pOld, Abc_Obj_t * pNew )
+{
+    assert( !Abc_ObjIsComplement(pOld) );
+    assert( !Abc_ObjIsComplement(pNew) );
+    Abc_NtkIncrementTravId(pNtk);
+    return Abc_NtkHaigCheckTfi_rec( pNew, pOld );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Abc_Obj_t * Hop_ObjChild0Next( Hop_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Hop_ObjFanin0(pObj)->pNext, Hop_ObjFaninC0(pObj) );  }
+static inline Abc_Obj_t * Hop_ObjChild1Next( Hop_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Hop_ObjFanin1(pObj)->pNext, Hop_ObjFaninC1(pObj) );  }
+
+/**Function*************************************************************
+
+  Synopsis    [Stops history AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkHaigRecreateAig( Abc_Ntk_t * pNtk, Hop_Man_t * p )
+{
+    Abc_Ntk_t * pNtkAig;
+    Abc_Obj_t * pObjOld, * pObjAbcThis, * pObjAbcRepr;
+    Hop_Obj_t * pObj;
+    int i;
+    assert( p->nCreated == Vec_PtrSize(p->vObjs) );
+
+    // start the new network
+    pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+
+    // transfer new nodes to the PIs of HOP
+    Hop_ManConst1(p)->pNext = (Hop_Obj_t *)Abc_AigConst1( pNtkAig );
+    Hop_ManForEachPi( p, pObj, i )
+        pObj->pNext = (Hop_Obj_t *)Abc_NtkCi( pNtkAig, i );
+
+    // construct new nodes
+    Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
+    {
+        if ( !Hop_ObjIsNode(pObj) )
+            continue;
+        pObj->pNext = (Hop_Obj_t *)Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Hop_ObjChild0Next(pObj), Hop_ObjChild1Next(pObj) );
+        assert( !Hop_IsComplement(pObj->pNext) );
+    }
+
+    // set the COs
+    Abc_NtkForEachCo( pNtk, pObjOld, i )
+        Abc_ObjAddFanin( pObjOld->pCopy, Hop_ObjChild0Next(Hop_ManPo(p,i)) );
+
+    // construct choice nodes
+    Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
+    {
+        // skip the node without choices
+        if ( pObj->pData == NULL )
+            continue;
+        // skip the representative of the class
+        if ( pObj->pData == pObj )
+            continue;
+        // do not create choices for constant 1 and PIs
+        if ( !Hop_ObjIsNode((Hop_Obj_t *)pObj->pData) )
+            continue;
+        // get the corresponding new nodes
+        pObjAbcThis = (Abc_Obj_t *)pObj->pNext;
+        pObjAbcRepr = (Abc_Obj_t *)((Hop_Obj_t *)pObj->pData)->pNext;
+        // the new node cannot be already in the class
+        assert( pObjAbcThis->pData == NULL );
+        // the new node cannot have fanouts
+        assert( Abc_ObjFanoutNum(pObjAbcThis) == 0 );
+        // these should be different nodes
+        assert( pObjAbcRepr != pObjAbcThis );
+        // do not create choices if there is a path from pObjAbcThis to pObjAbcRepr
+        if ( !Abc_NtkHaigCheckTfi( pNtkAig, pObjAbcRepr, pObjAbcThis ) )
+        {
+            // find the last node in the class
+            while ( pObjAbcRepr->pData )
+                pObjAbcRepr = (Abc_Obj_t *)pObjAbcRepr->pData;
+            // add the new node at the end of the list
+            pObjAbcRepr->pData = pObjAbcThis;
+        }
+    }
+
+    // finish the new network
+//    Abc_NtkFinalize( pNtk, pNtkAig );
+//    Abc_AigCleanup( pNtkAig->pManFunc );
+    // check correctness of the network
+    if ( !Abc_NtkCheck( pNtkAig ) )
+    {
+        printf( "Abc_NtkHaigUse: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkAig );
+        return NULL;
+    }
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resets representatives.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkHaigResetReprsOld( Hop_Man_t * pMan )
+{
+    Vec_Ptr_t * vMembers, * vClasses;
+
+    // collect members of the classes and make them point to reprs
+    vMembers = Abc_NtkHaigCollectMembers( pMan );
+    printf( "Collected %6d class members.\n", Vec_PtrSize(vMembers) );
+
+    // create classes
+    vClasses = Abc_NtkHaigCreateClasses( vMembers );
+    printf( "Collected %6d classes. (Ave = %5.2f)\n", Vec_PtrSize(vClasses), 
+        (float)(Vec_PtrSize(vMembers))/Vec_PtrSize(vClasses) );
+
+    Vec_PtrFree( vMembers );
+    Vec_PtrFree( vClasses );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resets representatives.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkHaigResetReprs( Hop_Man_t * p )
+{
+    Hop_Obj_t * pObj, * pRepr;
+    int i, nClasses, nMembers, nFanouts, nNormals;
+    // clear self-classes
+    Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
+    {
+        // fix the strange situation of double-loop
+        pRepr = (Hop_Obj_t *)pObj->pData;
+        if ( pRepr && pRepr->pData == pObj )
+            pRepr->pData = pRepr;
+        // remove self-loops
+        if ( pObj->pData == pObj )
+            pObj->pData = NULL;
+    }
+    // set representatives
+    Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
+    {
+        if ( pObj->pData == NULL )
+            continue;
+        // get representative of the node
+        pRepr = Hop_ObjRepr( pObj );
+        pRepr->pData = pRepr;
+        // set the representative
+        pObj->pData = pRepr;
+    }
+    // make each class point to the smallest topological order
+    Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
+    {
+        if ( pObj->pData == NULL )
+            continue;
+        pRepr = Hop_ObjRepr( pObj );
+        if ( pRepr->Id > pObj->Id )
+        {
+            pRepr->pData = pObj;
+            pObj->pData = pObj;
+        }
+        else
+            pObj->pData = pRepr;
+    }
+    // count classes, members, and fanouts - and verify
+    nMembers = nClasses = nFanouts = nNormals = 0;
+    Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
+    {
+        if ( pObj->pData == NULL )
+            continue;
+        // count members
+        nMembers++;
+        // count the classes and fanouts
+        if ( pObj->pData == pObj )
+            nClasses++;
+        else if ( Hop_ObjRefs(pObj) > 0 )
+            nFanouts++;
+        else
+            nNormals++;
+        // compare representatives
+        pRepr = Hop_ObjRepr( pObj );
+        assert( pObj->pData == pRepr );
+        assert( pRepr->Id <= pObj->Id );
+    }
+//    printf( "Nodes = %7d.  Member = %7d.  Classes = %6d.  Fanouts = %6d.  Normals = %6d.\n", 
+//        Hop_ManNodeNum(p), nMembers, nClasses, nFanouts, nNormals );
+    return nFanouts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transform HOP manager into the one without loops.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkHopRemoveLoops( Abc_Ntk_t * pNtk, Hop_Man_t * pMan )
+{
+    Abc_Ntk_t * pNtkAig;
+    Hop_Man_t * pManTemp;
+
+    // iteratively reconstruct the HOP manager to create choice nodes
+    while ( Abc_NtkHaigResetReprs( pMan ) )
+    {
+        pMan = Abc_NtkHaigReconstruct( pManTemp = pMan );
+        Hop_ManStop( pManTemp );
+    }
+
+    // traverse in the topological order and create new AIG
+    pNtkAig = Abc_NtkHaigRecreateAig( pNtk, pMan );
+    Hop_ManStop( pMan );
+    return pNtkAig;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcIf.c b/abc-build/src/base/abci/abcIf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcIf.c
@@ -0,0 +1,793 @@
+/**CFile****************************************************************
+
+  FileName    [abcIf.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Interface with the FPGA mapping package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: abcIf.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/main.h"
+#include "map/if/if.h"
+#include "bool/kit/kit.h"
+#include "aig/aig/aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern If_Man_t *  Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
+static Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk );
+extern Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover );
+static Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj );
+static Vec_Ptr_t * Abc_NtkFindGoodOrder( Abc_Ntk_t * pNtk );
+
+extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose );
+extern void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose );
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Interface with the FPGA mapping package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManComputeSwitching( If_Man_t * pIfMan )
+{
+    abctime clk = Abc_Clock();
+    Gia_Man_t * pNew;
+    Vec_Int_t * vCopy;
+    If_Obj_t * pIfObj;
+    int i;
+    assert( pIfMan->vSwitching == NULL );
+    // create the new manager
+    pNew = Gia_ManStart( If_ManObjNum(pIfMan) );
+    vCopy = Vec_IntAlloc( If_ManObjNum(pIfMan) );
+    // constant and inputs
+    Vec_IntPush( vCopy, 1 );
+    If_ManForEachCi( pIfMan, pIfObj, i )
+        Vec_IntPush( vCopy, Gia_ManAppendCi(pNew) );
+    // internal nodes
+    If_ManForEachNode( pIfMan, pIfObj, i )
+    {
+        int iLit0 = Abc_LitNotCond( Vec_IntEntry(vCopy, If_ObjFanin0(pIfObj)->Id), If_ObjFaninC0(pIfObj) );
+        int iLit1 = Abc_LitNotCond( Vec_IntEntry(vCopy, If_ObjFanin1(pIfObj)->Id), If_ObjFaninC1(pIfObj) );
+        Vec_IntPush( vCopy, Gia_ManAppendAnd(pNew, iLit0, iLit1) );
+    }
+    // outputs
+    If_ManForEachCo( pIfMan, pIfObj, i )
+    {
+        int iLit0 = Abc_LitNotCond( Vec_IntEntry(vCopy, If_ObjFanin0(pIfObj)->Id), If_ObjFaninC0(pIfObj) );
+        Vec_IntPush( vCopy, Gia_ManAppendCo(pNew, iLit0) );
+    }
+    assert( Vec_IntSize(vCopy) == If_ManObjNum(pIfMan) );
+    Vec_IntFree( vCopy );
+    // compute switching activity
+    pIfMan->vSwitching = Gia_ManComputeSwitchProbs( pNew, 48, 16, 0 );
+    Gia_ManStop( pNew );
+    if ( pIfMan->pPars->fVerbose )
+        Abc_PrintTime( 1, "Computing switching activity", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Interface with the FPGA mapping package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )
+{
+    Abc_Ntk_t * pNtkNew, * pTemp;
+    If_Man_t * pIfMan;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    // get timing information
+    pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk);
+    pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk);
+
+    // set the latch paths
+    if ( pPars->fLatchPaths && pPars->pTimesArr )
+    {
+        int c;
+        for ( c = 0; c < Abc_NtkPiNum(pNtk); c++ )
+            pPars->pTimesArr[c] = -ABC_INFINITY;
+    }
+
+    // create FPGA mapper
+    pIfMan = Abc_NtkToIf( pNtk, pPars );    
+    if ( pIfMan == NULL )
+        return NULL;
+    if ( pPars->fPower )
+        If_ManComputeSwitching( pIfMan );
+
+    // create DSD manager
+    if ( pPars->fUseDsd )
+    {
+        If_DsdMan_t * p = (If_DsdMan_t *)Abc_FrameReadManDsd();
+        assert( pPars->nLutSize <= If_DsdManVarNum(p) );
+        assert( (pPars->pLutStruct == NULL && If_DsdManLutSize(p) == 0) || (pPars->pLutStruct && pPars->pLutStruct[0] - '0' == If_DsdManLutSize(p)) );
+        pIfMan->pIfDsdMan = (If_DsdMan_t *)Abc_FrameReadManDsd();
+        if ( pPars->fDsdBalance )
+            If_DsdManAllocIsops( pIfMan->pIfDsdMan, pPars->nLutSize );
+    }
+
+    // perform FPGA mapping
+    if ( !If_ManPerformMapping( pIfMan ) )
+    {
+        If_ManStop( pIfMan );
+        return NULL;
+    }
+
+    // transform the result of mapping into the new network
+    pNtkNew = Abc_NtkFromIf( pIfMan, pNtk );
+    if ( pNtkNew == NULL )
+        return NULL;
+    If_ManStop( pIfMan );
+    if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib )
+    {
+        pNtkNew = Abc_NtkStrash( pTemp = pNtkNew, 0, 0, 0 );
+        Abc_NtkDelete( pTemp );
+    }
+    else if ( pPars->fBidec && pPars->nLutSize <= 8 )
+        Abc_NtkBidecResyn( pNtkNew, 0 );
+
+    // duplicate EXDC
+    if ( pNtk->pExdc )
+        pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkIf: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Load the network into FPGA manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline If_Obj_t * Abc_ObjIfCopy( Abc_Obj_t * pNode ) { return (If_Obj_t *)pNode->pCopy; } 
+If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )
+{
+    ProgressBar * pProgress;
+    If_Man_t * pIfMan;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNode, * pPrev;
+    int i;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    // start the mapping manager and set its parameters
+    pIfMan = If_ManStart( pPars );
+    pIfMan->pName = Abc_UtilStrsav( Abc_NtkName(pNtk) );
+
+    // print warning about excessive memory usage
+    if ( 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30) > 1.0 )
+        printf( "Warning: The mapper will allocate %.1f GB for to represent the subject graph with %d AIG nodes.\n", 
+            1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30), Abc_NtkObjNum(pNtk) );
+
+    // create PIs and remember them in the old nodes
+    Abc_NtkCleanCopy( pNtk );
+    Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)If_ManConst1( pIfMan );
+    Abc_NtkForEachCi( pNtk, pNode, i )
+    {
+        pNode->pCopy = (Abc_Obj_t *)If_ManCreateCi( pIfMan );
+        // transfer logic level information
+        Abc_ObjIfCopy(pNode)->Level = pNode->Level;
+    }
+
+    // load the AIG into the mapper
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+    vNodes = Abc_AigDfs( pNtk, 0, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, "Initial" );
+        // add the node to the mapper
+        pNode->pCopy = (Abc_Obj_t *)If_ManCreateAnd( pIfMan, 
+            If_NotCond( Abc_ObjIfCopy(Abc_ObjFanin0(pNode)), Abc_ObjFaninC0(pNode) ), 
+            If_NotCond( Abc_ObjIfCopy(Abc_ObjFanin1(pNode)), Abc_ObjFaninC1(pNode) ) );
+        // set up the choice node
+        if ( Abc_AigNodeIsChoice( pNode ) )
+        {
+            Abc_Obj_t * pEquiv;
+//            int Counter = 0;
+            assert( If_ObjId(Abc_ObjIfCopy(pNode)) > If_ObjId(Abc_ObjIfCopy(Abc_ObjEquiv(pNode))) );
+            for ( pPrev = pNode, pEquiv = Abc_ObjEquiv(pPrev); pEquiv; pPrev = pEquiv, pEquiv = Abc_ObjEquiv(pPrev) )
+                If_ObjSetChoice( Abc_ObjIfCopy(pPrev), Abc_ObjIfCopy(pEquiv) );//, Counter++;
+//            printf( "%d ", Counter );
+            If_ManCreateChoice( pIfMan, Abc_ObjIfCopy(pNode) );
+        }
+    }
+    Extra_ProgressBarStop( pProgress );
+    Vec_PtrFree( vNodes );
+
+    // set the primary outputs without copying the phase
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        pNode->pCopy = (Abc_Obj_t *)If_ManCreateCo( pIfMan, If_NotCond( Abc_ObjIfCopy(Abc_ObjFanin0(pNode)), Abc_ObjFaninC0(pNode) ) );
+    return pIfMan;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Box mapping procedures.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_MapBoxSetPrevNext( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id )
+{
+    Abc_Obj_t * pNode;
+    pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+2);
+    Vec_IntWriteEntry( vMapIn, Abc_ObjId(Abc_ObjFanin0(pNode)), Id );
+    pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+4);
+    Vec_IntWriteEntry( vMapOut, Abc_ObjId(Abc_ObjFanin0(pNode)), Id );
+}
+static inline int Abc_MapBox2Next( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id )
+{
+    Abc_Obj_t * pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+4);
+    return Vec_IntEntry( vMapIn, Abc_ObjId(Abc_ObjFanin0(pNode)) );
+}
+static inline int Abc_MapBox2Prev( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id )
+{
+    Abc_Obj_t * pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+2);
+    return Vec_IntEntry( vMapOut, Abc_ObjId(Abc_ObjFanin0(pNode)) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the mapped network.]
+
+  Description [Assuming the copy field of the mapped nodes are NULL.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk )
+{
+    ProgressBar * pProgress;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pNode, * pNodeNew;
+    Vec_Int_t * vCover;
+    int i, nDupGates;
+    // create the new network
+    if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
+        pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
+    else if ( pIfMan->pPars->fUseSops || pIfMan->pPars->nGateSize > 0 )
+        pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+    else
+        pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG );
+    // prepare the mapping manager
+    If_ManCleanNodeCopy( pIfMan );
+    If_ManCleanCutData( pIfMan );
+    // make the mapper point to the new network
+    If_ObjSetCopy( If_ManConst1(pIfMan), Abc_NtkCreateNodeConst1(pNtkNew) );
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        If_ObjSetCopy( If_ManCi(pIfMan, i), pNode->pCopy );
+
+    // process the nodes in topological order
+    vCover = Vec_IntAlloc( 1 << 16 );
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, "Final" );
+        pNodeNew = Abc_NodeFromIf_rec( pNtkNew, pIfMan, If_ObjFanin0(If_ManCo(pIfMan, i)), vCover );
+        pNodeNew = Abc_ObjNotCond( pNodeNew, If_ObjFaninC0(If_ManCo(pIfMan, i)) );
+        Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+    }
+    Extra_ProgressBarStop( pProgress );
+    Vec_IntFree( vCover );
+
+    // remove the constant node if not used
+    pNodeNew = (Abc_Obj_t *)If_ObjCopy( If_ManConst1(pIfMan) );
+    if ( Abc_ObjFanoutNum(pNodeNew) == 0 && !Abc_ObjIsNone(pNodeNew) )
+        Abc_NtkDeleteObj( pNodeNew );
+    // minimize the node
+    if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
+        Abc_NtkSweep( pNtkNew, 0 );
+    if ( pIfMan->pPars->fUseBdds )
+        Abc_NtkBddReorder( pNtkNew, 0 );
+    // decouple the PO driver nodes to reduce the number of levels
+    nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, !pIfMan->pPars->fUseBuffs );
+    if ( nDupGates && pIfMan->pPars->fVerbose && !Abc_FrameReadFlag("silentmode") )
+    {
+        if ( pIfMan->pPars->fUseBuffs )
+            printf( "Added %d buffers/inverters to decouple the CO drivers.\n", nDupGates );
+        else
+            printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates );
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Rebuilds GIA from mini AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Abc_NodeBuildFromMiniInt( Hop_Man_t * pMan, Vec_Int_t * vAig, int nLeaves )
+{
+    assert( Vec_IntSize(vAig) > 0 );
+    assert( Vec_IntEntryLast(vAig) < 2 );
+    if ( Vec_IntSize(vAig) == 1 ) // const
+    {
+        assert( nLeaves == 0 );
+        return Hop_NotCond( Hop_ManConst0(pMan), Vec_IntEntry(vAig, 0) );
+    }
+    if ( Vec_IntSize(vAig) == 2 ) // variable
+    {
+        assert( Vec_IntEntry(vAig, 0) == 0 );
+        assert( nLeaves == 1 );
+        return Hop_NotCond( Hop_IthVar(pMan, 0), Vec_IntEntry(vAig, 1) );
+    }
+    else
+    {
+        int i, iVar0, iVar1, iLit0, iLit1;
+        Hop_Obj_t * piLit0, * piLit1, * piLit = NULL;
+        assert( Vec_IntSize(vAig) & 1 );
+        Vec_IntForEachEntryDouble( vAig, iLit0, iLit1, i )
+        {
+            iVar0 = Abc_Lit2Var( iLit0 );
+            iVar1 = Abc_Lit2Var( iLit1 );
+            piLit0 = Hop_NotCond( iVar0 < nLeaves ? Hop_IthVar(pMan, iVar0) : (Hop_Obj_t *)Vec_PtrEntry((Vec_Ptr_t *)vAig, iVar0 - nLeaves), Abc_LitIsCompl(iLit0) );
+            piLit1 = Hop_NotCond( iVar1 < nLeaves ? Hop_IthVar(pMan, iVar1) : (Hop_Obj_t *)Vec_PtrEntry((Vec_Ptr_t *)vAig, iVar1 - nLeaves), Abc_LitIsCompl(iLit1) );
+            piLit  = Hop_And( pMan, piLit0, piLit1 );
+            assert( (i & 1) == 0 );
+            Vec_PtrWriteEntry( (Vec_Ptr_t *)vAig, Abc_Lit2Var(i), piLit );  // overwriting entries
+        }
+        assert( i == Vec_IntSize(vAig) - 1 );
+        piLit = Hop_NotCond( piLit, Vec_IntEntry(vAig, i) );
+        Vec_IntClear( vAig ); // useless
+        return piLit;
+    }
+}
+Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pCut, int fUseDsd )
+{
+    int Delay;
+    if ( fUseDsd )
+        Delay = If_CutDsdBalanceEval( p, pCut, p->vArray );
+    else
+        Delay = If_CutSopBalanceEval( p, pCut, p->vArray );
+    assert( Delay >= 0 );
+    return Abc_NodeBuildFromMiniInt( pMan, p->vArray, If_CutLeaveNum(pCut) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive one node after FPGA mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover )
+{
+    Abc_Obj_t * pNodeNew;
+    If_Cut_t * pCutBest;
+    If_Obj_t * pIfLeaf;
+    int i;
+    // return if the result if known
+    pNodeNew = (Abc_Obj_t *)If_ObjCopy( pIfObj );
+    if ( pNodeNew )
+        return pNodeNew;
+    assert( pIfObj->Type == IF_AND );
+    // get the parameters of the best cut
+    // create a new node 
+    pNodeNew = Abc_NtkCreateNode( pNtkNew );
+    pCutBest = If_ObjCutBest( pIfObj );
+//    printf( "%d 0x%02X %d\n", pCutBest->nLeaves, 0xff & *If_CutTruth(pCutBest), pIfMan->pPars->pFuncCost(pCutBest) );
+//    if ( pIfMan->pPars->pLutLib && pIfMan->pPars->pLutLib->fVarPinDelays )
+    if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->fUseTtPerm && !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->nGateSize )
+        If_CutRotatePins( pIfMan, pCutBest );
+    if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
+    {
+        If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i )
+            Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) );
+    }
+    else
+    {
+        If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i )
+            Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) );
+    }
+    // set the level of the new node
+    pNodeNew->Level = Abc_ObjLevelNew( pNodeNew );
+    // derive the function of this node
+    if ( pIfMan->pPars->fTruth )
+    {
+        if ( pIfMan->pPars->fUseBdds )
+        { 
+            // transform truth table into the BDD 
+            pNodeNew->pData = Kit_TruthToBdd( (DdManager *)pNtkNew->pManFunc, If_CutTruth(pIfMan, pCutBest), If_CutLeaveNum(pCutBest), 0 );  Cudd_Ref((DdNode *)pNodeNew->pData); 
+        }
+        else if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
+        { 
+            // transform truth table into the BDD 
+            pNodeNew->pData = Kit_TruthToBdd( (DdManager *)pNtkNew->pManFunc, If_CutTruth(pIfMan, pCutBest), If_CutLeaveNum(pCutBest), 1 );  Cudd_Ref((DdNode *)pNodeNew->pData); 
+        }
+        else if ( pIfMan->pPars->fUseSops || pIfMan->pPars->nGateSize > 0 ) 
+        {
+            // transform truth table into the SOP
+            int RetValue = Kit_TruthIsop( If_CutTruth(pIfMan, pCutBest), If_CutLeaveNum(pCutBest), vCover, 1 );
+            assert( RetValue == 0 || RetValue == 1 );
+            // check the case of constant cover
+            if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) )
+            {
+                assert( RetValue == 0 );
+                pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, If_CutLeaveNum(pCutBest), NULL );
+                pNodeNew = (Vec_IntSize(vCover) == 0) ? Abc_NtkCreateNodeConst0(pNtkNew) : Abc_NtkCreateNodeConst1(pNtkNew);
+            }
+            else
+            {
+                // derive the AIG for that tree
+                pNodeNew->pData = Abc_SopCreateFromIsop( (Mem_Flex_t *)pNtkNew->pManFunc, If_CutLeaveNum(pCutBest), vCover );
+                if ( RetValue )
+                    Abc_SopComplement( (char *)pNodeNew->pData );
+            }
+        }
+        else if ( pIfMan->pPars->fDelayOpt )
+            pNodeNew->pData = Abc_NodeBuildFromMini( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, 0 );
+        else if ( pIfMan->pPars->fDsdBalance )
+            pNodeNew->pData = Abc_NodeBuildFromMini( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, 1 );
+        else if ( pIfMan->pPars->fUserRecLib )
+        {
+            extern Hop_Obj_t * Abc_RecToHop3( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj );
+            pNodeNew->pData = Abc_RecToHop3( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj ); 
+        }
+        else
+        {
+            extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory );
+            word * pTruth = If_CutTruthW(pIfMan, pCutBest);
+            if ( pIfMan->pPars->fUseTtPerm )
+                for ( i = 0; i < (int)pCutBest->nLeaves; i++ )
+                    if ( If_CutLeafBit(pCutBest, i) )
+                        Abc_TtFlip( pTruth, Abc_TtWordNum(pCutBest->nLeaves), i );
+            pNodeNew->pData = Kit_TruthToHop( (Hop_Man_t *)pNtkNew->pManFunc, (unsigned *)pTruth, If_CutLeaveNum(pCutBest), vCover );
+        }
+        // complement the node if the cut was complemented
+        if ( pCutBest->fCompl && !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDsdBalance )
+            Abc_NodeComplement( pNodeNew );
+    }
+    else
+    {
+        pNodeNew->pData = Abc_NodeIfToHop( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pIfObj );
+    }
+    If_ObjSetCopy( pIfObj, pNodeNew );
+    return pNodeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively derives the truth table for the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Abc_NodeIfToHop_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited )
+{
+    If_Cut_t * pCut;
+    Hop_Obj_t * gFunc, * gFunc0, * gFunc1;
+    // get the best cut
+    pCut = If_ObjCutBest(pIfObj);
+    // if the cut is visited, return the result
+    if ( If_CutData(pCut) )
+        return (Hop_Obj_t *)If_CutData(pCut);
+    // compute the functions of the children
+    gFunc0 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin0, vVisited );
+    gFunc1 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin1, vVisited );
+    // get the function of the cut
+    gFunc  = Hop_And( pHopMan, Hop_NotCond(gFunc0, pIfObj->fCompl0), Hop_NotCond(gFunc1, pIfObj->fCompl1) );  
+    assert( If_CutData(pCut) == NULL );
+    If_CutSetData( pCut, gFunc );
+    // add this cut to the visited list
+    Vec_PtrPush( vVisited, pCut );
+    return gFunc;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively derives the truth table for the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Abc_NodeIfToHop2_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited )
+{
+    If_Cut_t * pCut;
+    If_Obj_t * pTemp;
+    Hop_Obj_t * gFunc, * gFunc0, * gFunc1;
+    // get the best cut
+    pCut = If_ObjCutBest(pIfObj);
+    // if the cut is visited, return the result
+    if ( If_CutData(pCut) )
+        return (Hop_Obj_t *)If_CutData(pCut);
+    // mark the node as visited
+    Vec_PtrPush( vVisited, pCut );
+    // insert the worst case
+    If_CutSetData( pCut, (void *)1 );
+    // skip in case of primary input
+    if ( If_ObjIsCi(pIfObj) )
+        return (Hop_Obj_t *)If_CutData(pCut);
+    // compute the functions of the children
+    for ( pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv )
+    {
+        gFunc0 = Abc_NodeIfToHop2_rec( pHopMan, pIfMan, pTemp->pFanin0, vVisited );
+        if ( gFunc0 == (void *)1 )
+            continue;
+        gFunc1 = Abc_NodeIfToHop2_rec( pHopMan, pIfMan, pTemp->pFanin1, vVisited );
+        if ( gFunc1 == (void *)1 )
+            continue;
+        // both branches are solved
+        gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, pTemp->fCompl0), Hop_NotCond(gFunc1, pTemp->fCompl1) ); 
+        if ( pTemp->fPhase != pIfObj->fPhase )
+            gFunc = Hop_Not(gFunc);
+        If_CutSetData( pCut, gFunc );
+        break;
+    }
+    return (Hop_Obj_t *)If_CutData(pCut);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table for one cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj )
+{
+    If_Cut_t * pCut;
+    Hop_Obj_t * gFunc;
+    If_Obj_t * pLeaf;
+    int i;
+    // get the best cut
+    pCut = If_ObjCutBest(pIfObj);
+    assert( pCut->nLeaves > 1 );
+    // set the leaf variables
+    If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+        If_CutSetData( If_ObjCutBest(pLeaf), Hop_IthVar(pHopMan, i) );
+    // recursively compute the function while collecting visited cuts
+    Vec_PtrClear( pIfMan->vTemp );
+    gFunc = Abc_NodeIfToHop2_rec( pHopMan, pIfMan, pIfObj, pIfMan->vTemp ); 
+    if ( gFunc == (void *)1 )
+    {
+        printf( "Abc_NodeIfToHop(): Computing local AIG has failed.\n" );
+        return NULL;
+    }
+    // clean the cuts
+    If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+        If_CutSetData( If_ObjCutBest(pLeaf), NULL );
+    Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i )
+        If_CutSetData( pCut, NULL );
+    return gFunc;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison for two nodes with the flow.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ObjCompareFlow( Abc_Obj_t ** ppNode0, Abc_Obj_t ** ppNode1 )
+{
+    float Flow0 = Abc_Int2Float((int)(ABC_PTRINT_T)(*ppNode0)->pCopy);
+    float Flow1 = Abc_Int2Float((int)(ABC_PTRINT_T)(*ppNode1)->pCopy);
+    if ( Flow0 > Flow1 )
+        return -1;
+    if ( Flow0 < Flow1 )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Orders AIG nodes so that nodes from larger cones go first.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFindGoodOrder_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    if ( !Abc_ObjIsNode(pNode) )
+        return;
+    assert( Abc_ObjIsNode( pNode ) );
+    // if this node is already visited, skip
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return;
+    // mark the node as visited
+    Abc_NodeSetTravIdCurrent( pNode );
+    // visit the transitive fanin of the node
+    Abc_NtkFindGoodOrder_rec( Abc_ObjFanin0(pNode), vNodes );
+    Abc_NtkFindGoodOrder_rec( Abc_ObjFanin1(pNode), vNodes );
+    // add the node after the fanins have been added
+    Vec_PtrPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Orders AIG nodes so that nodes from larger cones go first.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkFindGoodOrder( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes, * vCos;
+    Abc_Obj_t * pNode, * pFanin0, * pFanin1;
+    float Flow0, Flow1;
+    int i;
+
+    // initialize the flow
+    Abc_AigConst1(pNtk)->pCopy = NULL;
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        pNode->pCopy = NULL;
+    // compute the flow
+    Abc_AigForEachAnd( pNtk, pNode, i )
+    {
+        pFanin0 = Abc_ObjFanin0(pNode);
+        pFanin1 = Abc_ObjFanin1(pNode);
+        Flow0 = Abc_Int2Float((int)(ABC_PTRINT_T)pFanin0->pCopy)/Abc_ObjFanoutNum(pFanin0);
+        Flow1 = Abc_Int2Float((int)(ABC_PTRINT_T)pFanin1->pCopy)/Abc_ObjFanoutNum(pFanin1);
+        pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Abc_Float2Int(Flow0 + Flow1+(float)1.0);
+    }
+    // find the flow of the COs
+    vCos = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        pNode->pCopy = Abc_ObjFanin0(pNode)->pCopy;
+//        pNode->pCopy = (Abc_Obj_t *)Abc_Float2Int((float)Abc_ObjFanin0(pNode)->Level);
+        Vec_PtrPush( vCos, pNode );
+    }
+
+    // sort nodes in the increasing order of the flow
+    qsort( (Abc_Obj_t **)Vec_PtrArray(vCos), Abc_NtkCoNum(pNtk), 
+        sizeof(Abc_Obj_t *), (int (*)(const void *, const void *))Abc_ObjCompareFlow );
+    // verify sorting
+    pFanin0 = (Abc_Obj_t *)Vec_PtrEntry(vCos, 0);
+    pFanin1 = (Abc_Obj_t *)Vec_PtrEntryLast(vCos);
+    assert( Abc_Int2Float((int)(ABC_PTRINT_T)pFanin0->pCopy) >= Abc_Int2Float((int)(ABC_PTRINT_T)pFanin1->pCopy) );
+
+    // collect the nodes in the topological order from the new array
+    Abc_NtkIncrementTravId( pNtk );
+    vNodes = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vCos, pNode, i )
+        Abc_NtkFindGoodOrder_rec( Abc_ObjFanin0(pNode), vNodes );
+    Vec_PtrFree( vCos );
+    return vNodes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sets PO drivers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMarkMux( Abc_Obj_t * pDriver, Abc_Obj_t ** ppNode1, Abc_Obj_t ** ppNode2 )
+{
+    Abc_Obj_t * pNodeC, * pNodeT, * pNodeE;
+    If_Obj_t * pIfObj;
+
+    *ppNode1 = NULL;
+    *ppNode2 = NULL;
+    if ( pDriver == NULL )
+        return;
+    if ( !Abc_NodeIsMuxType(pDriver) )
+        return;
+
+    pNodeC = Abc_NodeRecognizeMux( pDriver, &pNodeT, &pNodeE );
+
+    pIfObj = If_Regular( (If_Obj_t *)Abc_ObjFanin0(pDriver)->pCopy );
+    if ( If_ObjIsAnd(pIfObj) )
+        pIfObj->fSkipCut = 1;
+    pIfObj = If_Regular( (If_Obj_t *)Abc_ObjFanin1(pDriver)->pCopy );
+    if ( If_ObjIsAnd(pIfObj) )
+        pIfObj->fSkipCut = 1;
+
+    pIfObj = If_Regular( (If_Obj_t *)Abc_ObjRegular(pNodeC)->pCopy );
+    if ( If_ObjIsAnd(pIfObj) )
+        pIfObj->fSkipCut = 1;
+
+/*
+    pIfObj = If_Regular( (If_Obj_t *)Abc_ObjRegular(pNodeT)->pCopy );
+    if ( If_ObjIsAnd(pIfObj) )
+        pIfObj->fSkipCut = 1;
+    pIfObj = If_Regular( (If_Obj_t *)Abc_ObjRegular(pNodeE)->pCopy );
+    if ( If_ObjIsAnd(pIfObj) )
+        pIfObj->fSkipCut = 1;
+*/
+    *ppNode1 = Abc_ObjRegular(pNodeC);
+    *ppNode2 = Abc_ObjRegular(pNodeT);
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcIfMux.c b/abc-build/src/base/abci/abcIfMux.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcIfMux.c
@@ -0,0 +1,422 @@
+/**CFile****************************************************************
+
+  FileName    [abcIf.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Interface with the FPGA mapping package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: abcIf.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "map/if/if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_NtkFuncCof0( int t, int v )
+{
+    static int s_Truth[3] = { 0xAA, 0xCC, 0xF0 };
+    return 0xff & ((t & ~s_Truth[v]) | ((t & ~s_Truth[v]) << (1<<v)));
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_NtkFuncCof1( int t, int v )
+{
+    static int s_Truth[3] = { 0xAA, 0xCC, 0xF0 };
+    return 0xff & ((t &  s_Truth[v]) | ((t &  s_Truth[v]) >> (1<<v)));
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_NtkFuncHasVar( int t, int v )
+{
+    static int s_Truth[3] = { 0xAA, 0xCC, 0xF0 };
+    return ((t & s_Truth[v]) >> (1<<v)) != (t & ~s_Truth[v]);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_NtkFuncSuppSize( int t )
+{
+    return Abc_NtkFuncHasVar(t, 0) + Abc_NtkFuncHasVar(t, 1) + Abc_NtkFuncHasVar(t, 2);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Precomputes MUXes and functions of less than 3 inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCutCostMuxPrecompute()
+{
+    int i, Value;
+    int CounterM = 0;
+    for ( i = 0; i < 256; i++ )
+    {
+        Value = 0;
+        if ( Abc_NtkFuncSuppSize( i ) < 3 )
+            Value = 1;
+        else
+        {
+            if ( (Abc_NtkFuncSuppSize(Abc_NtkFuncCof0(i,0)) == 1 && Abc_NtkFuncSuppSize(Abc_NtkFuncCof1(i,0)) == 1) ||
+                 (Abc_NtkFuncSuppSize(Abc_NtkFuncCof0(i,1)) == 1 && Abc_NtkFuncSuppSize(Abc_NtkFuncCof1(i,1)) == 1) ||
+                 (Abc_NtkFuncSuppSize(Abc_NtkFuncCof0(i,2)) == 1 && Abc_NtkFuncSuppSize(Abc_NtkFuncCof1(i,2)) == 1) )
+            {
+                 Value = 1;
+                 CounterM++;
+            }
+        }
+        printf( "%d, // %3d  0x%02X\n", Value, i, i );
+    }
+    printf( "Total number of MUXes = %d.\n", CounterM );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure returning the cost of the cut.]
+
+  Description [The number of MUXes needed to implement the function.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCutCostMux( If_Man_t * p, If_Cut_t * pCut )
+{    
+    static char uLookup[256] = {
+        1, //   0  0x00
+        0, //   1  0x01
+        0, //   2  0x02
+        1, //   3  0x03
+        0, //   4  0x04
+        1, //   5  0x05
+        0, //   6  0x06
+        0, //   7  0x07
+        0, //   8  0x08
+        0, //   9  0x09
+        1, //  10  0x0A
+        0, //  11  0x0B
+        1, //  12  0x0C
+        0, //  13  0x0D
+        0, //  14  0x0E
+        1, //  15  0x0F
+        0, //  16  0x10
+        1, //  17  0x11
+        0, //  18  0x12
+        0, //  19  0x13
+        0, //  20  0x14
+        0, //  21  0x15
+        0, //  22  0x16
+        0, //  23  0x17
+        0, //  24  0x18
+        0, //  25  0x19
+        0, //  26  0x1A
+        1, //  27  0x1B
+        0, //  28  0x1C
+        1, //  29  0x1D
+        0, //  30  0x1E
+        0, //  31  0x1F
+        0, //  32  0x20
+        0, //  33  0x21
+        1, //  34  0x22
+        0, //  35  0x23
+        0, //  36  0x24
+        0, //  37  0x25
+        0, //  38  0x26
+        1, //  39  0x27
+        0, //  40  0x28
+        0, //  41  0x29
+        0, //  42  0x2A
+        0, //  43  0x2B
+        0, //  44  0x2C
+        0, //  45  0x2D
+        1, //  46  0x2E
+        0, //  47  0x2F
+        1, //  48  0x30
+        0, //  49  0x31
+        0, //  50  0x32
+        1, //  51  0x33
+        0, //  52  0x34
+        1, //  53  0x35
+        0, //  54  0x36
+        0, //  55  0x37
+        0, //  56  0x38
+        0, //  57  0x39
+        1, //  58  0x3A
+        0, //  59  0x3B
+        1, //  60  0x3C
+        0, //  61  0x3D
+        0, //  62  0x3E
+        1, //  63  0x3F
+        0, //  64  0x40
+        0, //  65  0x41
+        0, //  66  0x42
+        0, //  67  0x43
+        1, //  68  0x44
+        0, //  69  0x45
+        0, //  70  0x46
+        1, //  71  0x47
+        0, //  72  0x48
+        0, //  73  0x49
+        0, //  74  0x4A
+        0, //  75  0x4B
+        0, //  76  0x4C
+        0, //  77  0x4D
+        1, //  78  0x4E
+        0, //  79  0x4F
+        1, //  80  0x50
+        0, //  81  0x51
+        0, //  82  0x52
+        1, //  83  0x53
+        0, //  84  0x54
+        1, //  85  0x55
+        0, //  86  0x56
+        0, //  87  0x57
+        0, //  88  0x58
+        0, //  89  0x59
+        1, //  90  0x5A
+        0, //  91  0x5B
+        1, //  92  0x5C
+        0, //  93  0x5D
+        0, //  94  0x5E
+        1, //  95  0x5F
+        0, //  96  0x60
+        0, //  97  0x61
+        0, //  98  0x62
+        0, //  99  0x63
+        0, // 100  0x64
+        0, // 101  0x65
+        1, // 102  0x66
+        0, // 103  0x67
+        0, // 104  0x68
+        0, // 105  0x69
+        0, // 106  0x6A
+        0, // 107  0x6B
+        0, // 108  0x6C
+        0, // 109  0x6D
+        0, // 110  0x6E
+        0, // 111  0x6F
+        0, // 112  0x70
+        0, // 113  0x71
+        1, // 114  0x72
+        0, // 115  0x73
+        1, // 116  0x74
+        0, // 117  0x75
+        0, // 118  0x76
+        1, // 119  0x77
+        0, // 120  0x78
+        0, // 121  0x79
+        0, // 122  0x7A
+        0, // 123  0x7B
+        0, // 124  0x7C
+        0, // 125  0x7D
+        0, // 126  0x7E
+        0, // 127  0x7F
+        0, // 128  0x80
+        0, // 129  0x81
+        0, // 130  0x82
+        0, // 131  0x83
+        0, // 132  0x84
+        0, // 133  0x85
+        0, // 134  0x86
+        0, // 135  0x87
+        1, // 136  0x88
+        0, // 137  0x89
+        0, // 138  0x8A
+        1, // 139  0x8B
+        0, // 140  0x8C
+        1, // 141  0x8D
+        0, // 142  0x8E
+        0, // 143  0x8F
+        0, // 144  0x90
+        0, // 145  0x91
+        0, // 146  0x92
+        0, // 147  0x93
+        0, // 148  0x94
+        0, // 149  0x95
+        0, // 150  0x96
+        0, // 151  0x97
+        0, // 152  0x98
+        1, // 153  0x99
+        0, // 154  0x9A
+        0, // 155  0x9B
+        0, // 156  0x9C
+        0, // 157  0x9D
+        0, // 158  0x9E
+        0, // 159  0x9F
+        1, // 160  0xA0
+        0, // 161  0xA1
+        0, // 162  0xA2
+        1, // 163  0xA3
+        0, // 164  0xA4
+        1, // 165  0xA5
+        0, // 166  0xA6
+        0, // 167  0xA7
+        0, // 168  0xA8
+        0, // 169  0xA9
+        1, // 170  0xAA
+        0, // 171  0xAB
+        1, // 172  0xAC
+        0, // 173  0xAD
+        0, // 174  0xAE
+        1, // 175  0xAF
+        0, // 176  0xB0
+        1, // 177  0xB1
+        0, // 178  0xB2
+        0, // 179  0xB3
+        0, // 180  0xB4
+        0, // 181  0xB5
+        0, // 182  0xB6
+        0, // 183  0xB7
+        1, // 184  0xB8
+        0, // 185  0xB9
+        0, // 186  0xBA
+        1, // 187  0xBB
+        0, // 188  0xBC
+        0, // 189  0xBD
+        0, // 190  0xBE
+        0, // 191  0xBF
+        1, // 192  0xC0
+        0, // 193  0xC1
+        0, // 194  0xC2
+        1, // 195  0xC3
+        0, // 196  0xC4
+        1, // 197  0xC5
+        0, // 198  0xC6
+        0, // 199  0xC7
+        0, // 200  0xC8
+        0, // 201  0xC9
+        1, // 202  0xCA
+        0, // 203  0xCB
+        1, // 204  0xCC
+        0, // 205  0xCD
+        0, // 206  0xCE
+        1, // 207  0xCF
+        0, // 208  0xD0
+        1, // 209  0xD1
+        0, // 210  0xD2
+        0, // 211  0xD3
+        0, // 212  0xD4
+        0, // 213  0xD5
+        0, // 214  0xD6
+        0, // 215  0xD7
+        1, // 216  0xD8
+        0, // 217  0xD9
+        0, // 218  0xDA
+        0, // 219  0xDB
+        0, // 220  0xDC
+        1, // 221  0xDD
+        0, // 222  0xDE
+        0, // 223  0xDF
+        0, // 224  0xE0
+        0, // 225  0xE1
+        1, // 226  0xE2
+        0, // 227  0xE3
+        1, // 228  0xE4
+        0, // 229  0xE5
+        0, // 230  0xE6
+        0, // 231  0xE7
+        0, // 232  0xE8
+        0, // 233  0xE9
+        0, // 234  0xEA
+        0, // 235  0xEB
+        0, // 236  0xEC
+        0, // 237  0xED
+        1, // 238  0xEE
+        0, // 239  0xEF
+        1, // 240  0xF0
+        0, // 241  0xF1
+        0, // 242  0xF2
+        1, // 243  0xF3
+        0, // 244  0xF4
+        1, // 245  0xF5
+        0, // 246  0xF6
+        0, // 247  0xF7
+        0, // 248  0xF8
+        0, // 249  0xF9
+        1, // 250  0xFA
+        0, // 251  0xFB
+        1, // 252  0xFC
+        0, // 253  0xFD
+        0, // 254  0xFE
+        1  // 255  0xFF    
+    };
+    if ( pCut->nLeaves < 3 )
+        return 1;
+    if ( pCut->nLeaves == 3 && uLookup[0xff & *If_CutTruth(p, pCut)] )
+        return 1;
+    return (1 << pCut->nLeaves) - 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcIfif.c b/abc-build/src/base/abci/abcIfif.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcIfif.c
@@ -0,0 +1,349 @@
+/**CFile****************************************************************
+
+  FileName    [abcIfif.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Experiment with technology mapping.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcIfif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "map/if/if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define IFIF_MAX_LEAVES 6
+
+
+typedef struct Abc_IffObj_t_       Abc_IffObj_t;
+struct Abc_IffObj_t_ 
+{
+    float            Delay[IFIF_MAX_LEAVES+1];     // separate delay
+//    int              nLeaves;
+//    int              pLeaves[IFIF_MAX_LEAVES];
+};
+
+typedef struct Abc_IffMan_t_       Abc_IffMan_t;
+struct Abc_IffMan_t_ 
+{
+    Abc_Ntk_t *      pNtk;
+    Ifif_Par_t *     pPars;
+    // internal data
+    int              nObjs;
+    Abc_IffObj_t *   pObjs;
+};
+
+static inline Abc_IffObj_t *  Abc_IffObj( Abc_IffMan_t * p, int i )                             { assert( i >= 0 && i < p->nObjs ); return p->pObjs + i;   }
+static inline float           Abc_IffDelay( Abc_IffMan_t * p, Abc_Obj_t * pObj, int fDelay1 )   { return Abc_IffObj(p, Abc_ObjId(pObj))->Delay[fDelay1];   }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_IffMan_t * Abc_NtkIfifStart( Abc_Ntk_t * pNtk, Ifif_Par_t * pPars )
+{
+    Abc_IffMan_t * p;
+    p = ABC_CALLOC( Abc_IffMan_t, 1 );
+    p->pNtk       = pNtk;
+    p->pPars      = pPars;
+    // internal data
+    p->nObjs      = Abc_NtkObjNumMax( pNtk );
+    p->pObjs      = ABC_CALLOC( Abc_IffObj_t, p->nObjs );
+    return p;
+}
+void Abc_NtkIfifStop( Abc_IffMan_t * p )
+{
+    // internal data
+    ABC_FREE( p->pObjs );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects fanins into ppNodes in decreasing order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ObjSortByDelay( Abc_IffMan_t * p, Abc_Obj_t * pObj, int fDelay1, Abc_Obj_t ** ppNodes )
+{
+    Abc_Obj_t * pFanin;
+    int i, a, k = 0;
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+    {
+        ppNodes[k++] = pFanin;
+        if ( Abc_ObjIsCi(pFanin) )
+            continue;
+        for ( a = k-1; a > 0; a-- )
+            if ( Abc_IffDelay(p, ppNodes[a-1], fDelay1) + p->pPars->pLutDelays[a-1] < Abc_IffDelay(p, ppNodes[a], fDelay1) + p->pPars->pLutDelays[a] )
+                ABC_SWAP( Abc_Obj_t *, ppNodes[a-1], ppNodes[a] );
+    }
+/*
+    for ( a = 1; a < k; a++ )
+    {
+        float D1 = Abc_IffDelay(p, ppNodes[a-1], fDelay1);
+        float D2 = Abc_IffDelay(p, ppNodes[a], fDelay1);
+        if ( Abc_ObjIsCi(ppNodes[a-1]) || Abc_ObjIsCi(ppNodes[a]) )
+            continue;
+        assert( Abc_IffDelay(p, ppNodes[a-1], fDelay1) + p->pPars->pLutDelays[a-1] >= Abc_IffDelay(p, ppNodes[a], fDelay1) + p->pPars->pLutDelays[a] - 0.01 );
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This is the delay which object has all by itself.]
+
+  Description [This delay is stored in Delay0.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Abc_ObjDelay0( Abc_IffMan_t * p, Abc_Obj_t * pObj )
+{
+    int i;
+    float Delay0 = 0;
+    Abc_Obj_t * ppNodes[6];
+    Abc_ObjSortByDelay( p, pObj, 1, ppNodes );
+    for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ )
+        Delay0 = Abc_MaxFloat( Delay0, Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i] );
+    return Delay0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This is the delay object has in the structure.]
+
+  Description [This delay is stored in Delay1.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Abc_ObjDelay1( Abc_IffMan_t * p, Abc_Obj_t * pObj )
+{
+    int i, fVeryVerbose = 0;
+//    Abc_IffObj_t * pIfif = Abc_IffObj( p, Abc_ObjId(pObj) );
+    Abc_Obj_t * ppNodes[6];
+    float Delay1, DelayNew;
+
+    if ( Abc_ObjFaninNum(pObj) == 0 )
+        return 0;
+
+    // sort fanins by delay1+LutDelay
+    Abc_ObjSortByDelay( p, pObj, 1, ppNodes );
+
+    // print verbose results
+    if ( fVeryVerbose )
+    {
+        printf( "Object %d   Level %d\n", Abc_ObjId(pObj), Abc_ObjLevel(pObj) );
+        for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ )
+        {
+            printf( "Fanin %d : ", i );
+            printf( "D0 %3.2f  ",      Abc_IffDelay(p, ppNodes[i], 0) );
+            printf( "D0* %3.2f     ",  Abc_IffDelay(p, ppNodes[i], 0) + p->pPars->pLutDelays[i] - p->pPars->DelayWire );
+            printf( "D1 %3.2f",        Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i] );
+            printf( "\n" );
+        }
+        printf( "\n" );
+    }
+/*
+    // for the first nDegree delays, sort them by the minimum Delay1+LutDelay and Delay0-Wire+LutDelay
+    Delay1 = 0;
+    pIfif->nLeaves = 0;
+    for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ )
+    {
+        if ( Abc_ObjIsNode(ppNodes[i]) && pIfif->nLeaves < p->pPars->nDegree )
+        {
+            DelayNew = Abc_MinFloat( Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i], 
+                                     Abc_IffDelay(p, ppNodes[i], 0) + p->pPars->pLutDelays[i] - p->pPars->DelayWire );
+            pIfif->pLeaves[pIfif->nLeaves++] = Abc_ObjId(ppNodes[i]);
+        }
+        else
+            DelayNew = Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i];
+        Delay1 = Abc_MaxFloat( Delay1, DelayNew );
+    }
+*/
+    // for the first nDegree delays, sort them by the minimum Delay1+LutDelay and Delay0-Wire+LutDelay
+    Delay1 = 0;
+    for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ )
+    {
+        if ( i < p->pPars->nDegree )
+            DelayNew = Abc_MinFloat( Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i], 
+                                     Abc_IffDelay(p, ppNodes[i], 0) + p->pPars->pLutDelays[i] - p->pPars->DelayWire );
+        else
+            DelayNew = Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i];
+        Delay1 = Abc_MaxFloat( Delay1, DelayNew );
+    }
+    assert( Delay1 > 0 );
+    return Delay1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [This is the delay which object has all by itself.]
+
+  Description [This delay is stored in Delay0.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Abc_ObjDelayDegree( Abc_IffMan_t * p, Abc_Obj_t * pObj, int d )
+{
+    int i;
+    float Delay0 = 0, DelayNew;
+    Abc_Obj_t * ppNodes[6];
+    assert( d >= 0 && d <= p->pPars->nDegree );
+    Abc_ObjSortByDelay( p, pObj, p->pPars->nDegree, ppNodes );
+    for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ )
+    {
+        DelayNew = Abc_IffDelay(p, ppNodes[i], p->pPars->nDegree) + p->pPars->pLutDelays[i];
+        if ( i == 0 && d > 0 )
+            DelayNew = Abc_MinFloat(DelayNew, Abc_IffDelay(p, ppNodes[i], d-1) + p->pPars->pLutDelays[i] - p->pPars->DelayWire );
+        Delay0 = Abc_MaxFloat( Delay0, DelayNew );
+    }
+    return Delay0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPerformIfif( Abc_Ntk_t * pNtk, Ifif_Par_t * pPars )
+{
+    Abc_IffMan_t * p;
+    Abc_IffObj_t * pIffObj;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj;
+    float Delay, Delay10, DegreeFinal;
+    int i, d, Count10;
+    assert( pPars->pLutLib->LutMax >= 0 && pPars->pLutLib->LutMax <= IFIF_MAX_LEAVES );
+    assert( pPars->nLutSize >= 0 && pPars->nLutSize <= IFIF_MAX_LEAVES );
+    assert( pPars->nDegree >= 0 && pPars->nDegree <= IFIF_MAX_LEAVES );
+    // convert to AIGs
+    Abc_NtkToAig( pNtk );
+    Abc_NtkLevel( pNtk );
+
+    // print parameters
+    if ( pPars->fVerbose )
+    {
+        printf( "Running mapper into LUT structures with the following parameters:\n" );
+        printf( "Pin+Wire: {" );
+        for ( i = 0; i < pPars->pLutLib->LutMax; i++ )
+            printf( " %3.2f", pPars->pLutDelays[i] );
+        printf( " }  " );    
+        printf( "Wire %3.2f  Degree %d  Type: %s\n", 
+            pPars->DelayWire, pPars->nDegree, pPars->fCascade? "Cascade" : "Cluster" );
+    }
+
+    // start manager
+    p = Abc_NtkIfifStart( pNtk, pPars );
+//    printf( "Running experiment with LUT delay %d and degree %d (LUT size is %d).\n", DelayWire, nDegree, nLutSize );
+
+    // compute the delay
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        assert( Abc_ObjIsNode(pObj) );
+        pIffObj = Abc_IffObj( p, Abc_ObjId(pObj) );
+
+        if ( pPars->fCascade )
+        {
+            for ( d = 0; d <= pPars->nDegree; d++ )
+                pIffObj->Delay[d] = Abc_ObjDelayDegree( p, pObj, d );
+        }
+        else
+        {
+            pIffObj->Delay[0] = Abc_ObjDelay0( p, pObj );
+            pIffObj->Delay[1] = Abc_ObjDelay1( p, pObj );
+        }
+    }
+
+    // get final degree number
+    if ( pPars->fCascade )
+        DegreeFinal = pPars->nDegree;
+    else
+        DegreeFinal = 1;
+
+    if ( p->pPars->fVeryVerbose )
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        printf( "Node %3d : Lev =%3d   ",  Abc_ObjId(pObj), Abc_ObjLevel(pObj) );
+        for ( d = 0; d <= DegreeFinal; d++ )
+            printf( "Del%d =%4.2f  ", d, Abc_IffDelay(p, pObj, d) );
+        printf( "\n" );
+    }
+    Vec_PtrFree( vNodes );
+
+
+    // consider delay at the outputs
+    Delay = 0;
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Delay = Abc_MaxFloat( Delay, Abc_IffDelay(p, Abc_ObjFanin0(pObj), DegreeFinal) );
+    Delay10 = 0.9 * Delay;
+
+    // consider delay at the outputs
+    Count10 = 0;
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        if ( Abc_IffDelay(p, Abc_ObjFanin0(pObj), DegreeFinal) >= Delay10 )
+            Count10++;
+
+    printf( "Critical delay %5.2f. Critical outputs %5.2f %%\n", Delay, 100.0 * Count10 / Abc_NtkCoNum(pNtk) );
+//    printf( "%.2f %.2f\n", Delay, 100.0 * Count10 / Abc_NtkCoNum(pNtk) );
+
+    // derive a new network
+
+    // stop manager
+    Abc_NtkIfifStop( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcIvy.c b/abc-build/src/base/abci/abcIvy.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcIvy.c
@@ -0,0 +1,1144 @@
+/**CFile****************************************************************
+
+  FileName    [abcIvy.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Strashing of the current network.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcIvy.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "bool/dec/dec.h"
+#include "proof/fra/fra.h"
+#include "aig/ivy/ivy.h"
+#include "proof/fraig/fraig.h"
+#include "map/mio/mio.h"
+#include "aig/aig/aig.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+extern void   Aig_ManStop( Aig_Man_t * pMan );
+//extern int Fra_FraigSat( Aig_Man_t * pMan, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose );
+extern Ivy_Obj_t * Dec_GraphToNetworkIvy( Ivy_Man_t * pMan, Dec_Graph_t * pGraph );
+extern void Ivy_CutComputeAll( Ivy_Man_t * p, int nInputs );
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t *  Abc_NtkFromIvy( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan );
+static Abc_Ntk_t *  Abc_NtkFromIvySeq( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan, int fHaig );
+static Ivy_Man_t *  Abc_NtkToIvy( Abc_Ntk_t * pNtkOld );
+
+static void         Abc_NtkStrashPerformAig( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan );
+static Ivy_Obj_t *  Abc_NodeStrashAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode );
+static Ivy_Obj_t *  Abc_NodeStrashAigSopAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop );
+static Ivy_Obj_t *  Abc_NodeStrashAigExorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop );
+static Ivy_Obj_t *  Abc_NodeStrashAigFactorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop );
+
+typedef int   Abc_Edge_t;
+static inline Abc_Edge_t   Abc_EdgeCreate( int Id, int fCompl )                { return (Id << 1) | fCompl;             }
+static inline int          Abc_EdgeId( Abc_Edge_t Edge )                       { return Edge >> 1;                      }
+static inline int          Abc_EdgeIsComplement( Abc_Edge_t Edge )             { return Edge & 1;                       }
+static inline Abc_Edge_t   Abc_EdgeRegular( Abc_Edge_t Edge )                  { return (Edge >> 1) << 1;               }
+static inline Abc_Edge_t   Abc_EdgeNot( Abc_Edge_t Edge )                      { return Edge ^ 1;                       }
+static inline Abc_Edge_t   Abc_EdgeNotCond( Abc_Edge_t Edge, int fCond )       { return Edge ^ fCond;                   }
+static inline Abc_Edge_t   Abc_EdgeFromNode( Abc_Obj_t * pNode )               { return Abc_EdgeCreate( Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) );       }
+static inline Abc_Obj_t *  Abc_EdgeToNode( Abc_Ntk_t * p, Abc_Edge_t Edge )    { return Abc_ObjNotCond( Abc_NtkObj(p, Abc_EdgeId(Edge)), Abc_EdgeIsComplement(Edge) ); }
+
+static inline Abc_Obj_t *  Abc_ObjFanin0Ivy( Abc_Ntk_t * p, Ivy_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_EdgeToNode(p, Ivy_ObjFanin0(pObj)->TravId), Ivy_ObjFaninC0(pObj) ); }
+static inline Abc_Obj_t *  Abc_ObjFanin1Ivy( Abc_Ntk_t * p, Ivy_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_EdgeToNode(p, Ivy_ObjFanin1(pObj)->TravId), Ivy_ObjFaninC1(pObj) ); }
+
+static Vec_Int_t * Abc_NtkCollectLatchValuesIvy( Abc_Ntk_t * pNtk, int fUseDcs );
+
+extern int timeRetime;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the IVY package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc )
+{
+    Ivy_Man_t * pMan;
+//timeRetime = Abc_Clock();
+    assert( !Abc_NtkIsNetlist(pNtk) );
+    if ( Abc_NtkIsBddLogic(pNtk) )
+    {
+        if ( !Abc_NtkBddToSop(pNtk, 0) )
+        {
+            printf( "Abc_NtkIvyBefore(): Converting to SOPs has failed.\n" );
+            return NULL;
+        }
+    }
+    if ( fSeq && Abc_NtkCountSelfFeedLatches(pNtk) )
+    {
+        printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtk) );
+//        return NULL;
+    }
+    // print warning about choice nodes
+    if ( Abc_NtkGetChoiceNum( pNtk ) )
+        printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" );
+    // convert to the AIG manager
+    pMan = Abc_NtkToIvy( pNtk );
+    if ( !Ivy_ManCheck( pMan ) )
+    {
+        printf( "AIG check has failed.\n" );
+        Ivy_ManStop( pMan );
+        return NULL;
+    }
+//    Ivy_ManPrintStats( pMan );
+    if ( fSeq )
+    {
+        int nLatches = Abc_NtkLatchNum(pNtk);
+        Vec_Int_t * vInit = Abc_NtkCollectLatchValuesIvy( pNtk, fUseDc );
+        Ivy_ManMakeSeq( pMan, nLatches, vInit->pArray );
+        Vec_IntFree( vInit );
+//        Ivy_ManPrintStats( pMan );
+    }
+//timeRetime = Abc_Clock() - timeRetime;
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the IVY package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyAfter( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan, int fSeq, int fHaig )
+{
+    Abc_Ntk_t * pNtkAig;
+    int nNodes, fCleanup = 1;
+    // convert from the AIG manager
+    if ( fSeq )
+        pNtkAig = Abc_NtkFromIvySeq( pNtk, pMan, fHaig );
+    else
+        pNtkAig = Abc_NtkFromIvy( pNtk, pMan );
+    // report the cleanup results
+    if ( !fHaig && fCleanup && (nNodes = Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc)) )
+        printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes );
+    // duplicate EXDC 
+    if ( pNtk->pExdc )
+        pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pNtkAig ) )
+    {
+        printf( "Abc_NtkStrash: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkAig );
+        return NULL;
+    }
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyStrash( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkAig;
+    Ivy_Man_t * pMan;
+    pMan = Abc_NtkIvyBefore( pNtk, 1, 0 );
+    if ( pMan == NULL )
+        return NULL;
+    pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 );
+    Ivy_ManStop( pMan );
+    return pNtkAig;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyHaig( Abc_Ntk_t * pNtk, int nIters, int fUseZeroCost, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Ivy_Man_t * pMan;
+    abctime clk;
+//    int i;
+/*
+extern int nMoves;
+extern int nMovesS;
+extern int nClauses;
+extern int timeInv;
+
+nMoves = 0;
+nMovesS = 0;
+nClauses = 0;
+timeInv = 0;
+*/
+    pMan = Abc_NtkIvyBefore( pNtk, 1, 1 );
+    if ( pMan == NULL )
+        return NULL;
+//timeRetime = Abc_Clock();
+
+clk = Abc_Clock();
+    Ivy_ManHaigStart( pMan, fVerbose );
+//    Ivy_ManRewriteSeq( pMan, 0, 0 );
+//    for ( i = 0; i < nIters; i++ )
+//        Ivy_ManRewriteSeq( pMan, fUseZeroCost, 0 );
+
+//printf( "%d ", Ivy_ManNodeNum(pMan) );
+    Ivy_ManRewriteSeq( pMan, 0, 0 );
+    Ivy_ManRewriteSeq( pMan, 0, 0 );
+    Ivy_ManRewriteSeq( pMan, 1, 0 );
+//printf( "%d ", Ivy_ManNodeNum(pMan) );
+//printf( "%d ", Ivy_ManNodeNum(pMan->pHaig) );
+//ABC_PRT( " ", Abc_Clock() - clk );
+//printf( "\n" );
+/*
+    printf( "Moves = %d.  ", nMoves );
+    printf( "MovesS = %d.  ", nMovesS );
+    printf( "Clauses = %d.  ", nClauses );
+    ABC_PRT( "Time", timeInv );
+*/
+//    Ivy_ManRewriteSeq( pMan, 1, 0 );
+//printf( "Haig size = %d.\n", Ivy_ManNodeNum(pMan->pHaig) );
+//    Ivy_ManHaigPostprocess( pMan, fVerbose );
+//timeRetime = Abc_Clock() - timeRetime;
+
+    // write working AIG into the current network
+//    pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 ); 
+    // write HAIG into the current network
+    pNtkAig = Abc_NtkIvyAfter( pNtk, pMan->pHaig, 1, 1 );
+
+    Ivy_ManHaigStop( pMan );
+    Ivy_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkIvyCuts( Abc_Ntk_t * pNtk, int nInputs )
+{
+    Ivy_Man_t * pMan;
+    pMan = Abc_NtkIvyBefore( pNtk, 1, 0 );
+    if ( pMan == NULL )
+        return;
+    Ivy_CutComputeAll( pMan, nInputs );
+    Ivy_ManStop( pMan );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeroCost, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Ivy_Man_t * pMan;
+    pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+    if ( pMan == NULL )
+        return NULL;
+//timeRetime = Abc_Clock();
+    Ivy_ManRewritePre( pMan, fUpdateLevel, fUseZeroCost, fVerbose );
+//timeRetime = Abc_Clock() - timeRetime;
+    pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+    Ivy_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyRewriteSeq( Abc_Ntk_t * pNtk, int fUseZeroCost, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Ivy_Man_t * pMan;
+    pMan = Abc_NtkIvyBefore( pNtk, 1, 1 );
+    if ( pMan == NULL )
+        return NULL;
+//timeRetime = Abc_Clock();
+    Ivy_ManRewriteSeq( pMan, fUseZeroCost, fVerbose );
+//timeRetime = Abc_Clock() - timeRetime;
+//    Ivy_ManRewriteSeq( pMan, 1, 0 );
+//    Ivy_ManRewriteSeq( pMan, 1, 0 );
+    pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 );
+    Ivy_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyResyn0( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Ivy_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+    if ( pMan == NULL )
+        return NULL;
+    pMan = Ivy_ManResyn0( pTemp = pMan, fUpdateLevel, fVerbose );
+    Ivy_ManStop( pTemp );
+    pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+    Ivy_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose )
+{
+    Abc_Ntk_t * pNtkAig;
+    Ivy_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+    if ( pMan == NULL )
+        return NULL;
+    pMan = Ivy_ManResyn( pTemp = pMan, fUpdateLevel, fVerbose );
+    Ivy_ManStop( pTemp );
+    pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+    Ivy_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvySat( Abc_Ntk_t * pNtk, int nConfLimit, int fVerbose )
+{
+    Ivy_FraigParams_t Params, * pParams = &Params; 
+    Abc_Ntk_t * pNtkAig;
+    Ivy_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+    if ( pMan == NULL )
+        return NULL;
+    Ivy_FraigParamsDefault( pParams );
+    pParams->nBTLimitMiter = nConfLimit;
+    pParams->fVerbose = fVerbose;
+//    pMan = Ivy_FraigPerform( pTemp = pMan, pParams );
+    pMan = Ivy_FraigMiter( pTemp = pMan, pParams );
+    Ivy_ManStop( pTemp );
+    pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+    Ivy_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the final nodes to point to the original nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTransferPointers( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig )
+{
+    Abc_Obj_t * pObj;
+    Ivy_Obj_t * pObjIvy, * pObjFraig;
+    int i;
+    pObj = Abc_AigConst1(pNtk);
+    pObj->pCopy = Abc_AigConst1(pNtkAig);
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->pCopy = Abc_NtkCi(pNtkAig, i);
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        pObj->pCopy = Abc_NtkCo(pNtkAig, i);
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        pObj->pCopy = Abc_NtkBox(pNtkAig, i);
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        pObjIvy = (Ivy_Obj_t *)pObj->pCopy;
+        if ( pObjIvy == NULL )
+            continue;
+        pObjFraig = Ivy_ObjEquiv( pObjIvy );
+        if ( pObjFraig == NULL )
+            continue;
+        pObj->pCopy = Abc_EdgeToNode( pNtkAig, Ivy_Regular(pObjFraig)->TravId );
+        pObj->pCopy = Abc_ObjNotCond( pObj->pCopy, Ivy_IsComplement(pObjFraig) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose )
+{
+    Ivy_FraigParams_t Params, * pParams = &Params; 
+    Abc_Ntk_t * pNtkAig;
+    Ivy_Man_t * pMan, * pTemp;
+    pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+    if ( pMan == NULL )
+        return NULL;
+    Ivy_FraigParamsDefault( pParams );
+    pParams->nBTLimitNode = nConfLimit;
+    pParams->fVerbose     = fVerbose;
+    pParams->fProve       = fProve;
+    pParams->fDoSparse    = fDoSparse;
+    pMan = Ivy_FraigPerform( pTemp = pMan, pParams );
+    // transfer the pointers
+    if ( fTransfer == 1 )
+    {
+        Vec_Ptr_t * vCopies;
+        vCopies = Abc_NtkSaveCopy( pNtk );
+        pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+        Abc_NtkLoadCopy( pNtk, vCopies );
+        Vec_PtrFree( vCopies );
+        Abc_NtkTransferPointers( pNtk, pNtkAig );
+    }
+    else
+        pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+    Ivy_ManStop( pTemp );
+    Ivy_ManStop( pMan );
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars )
+{
+    Prove_Params_t * pParams = (Prove_Params_t *)pPars;
+    Abc_Ntk_t * pNtk = *ppNtk, * pNtkTemp;
+    Abc_Obj_t * pObj, * pFanin;
+    Ivy_Man_t * pMan;
+    Aig_Man_t * pMan2;
+    int RetValue;
+    assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) );
+    // experiment with various parameters settings
+//    pParams->fUseBdds = 1;
+//    pParams->fBddReorder = 1;
+//    pParams->nTotalBacktrackLimit = 10000;
+ 
+    // strash the network if it is not strashed already
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        pNtk = Abc_NtkStrash( pNtkTemp = pNtk, 0, 1, 0 );
+        Abc_NtkDelete( pNtkTemp );
+    }
+ 
+    // check the case when the 0000 simulation pattern detect the bug
+    pObj = Abc_NtkPo(pNtk,0);
+    pFanin = Abc_ObjFanin0(pObj);
+    if ( Abc_ObjFanin0(pObj)->fPhase != (unsigned)Abc_ObjFaninC0(pObj) )
+    {
+        pNtk->pModel = ABC_CALLOC( int, Abc_NtkCiNum(pNtk) );
+        return 0;
+    }
+
+    // changed in "src\sat\fraig\fraigMan.c"
+    //    pParams->nMiteringLimitStart  = 300;    // starting mitering limit
+    // to be
+    //    pParams->nMiteringLimitStart  = 5000;    // starting mitering limit
+
+    // if SAT only, solve without iteration
+//    RetValue = Abc_NtkMiterSat( pNtk, 2*(ABC_INT64_T)pParams->nMiteringLimitStart, (ABC_INT64_T)0, 0, NULL, NULL );
+    pMan2 = Abc_NtkToDar( pNtk, 0, 0 );
+    RetValue = Fra_FraigSat( pMan2, (ABC_INT64_T)pParams->nMiteringLimitStart, (ABC_INT64_T)0, 0, 0, 0, 1, 0, 0, 0 ); 
+    pNtk->pModel = (int *)pMan2->pData, pMan2->pData = NULL;
+    Aig_ManStop( pMan2 );
+//    pNtk->pModel = Aig_ManReleaseData( pMan2 );
+    if ( RetValue >= 0 )
+        return RetValue;
+
+    // apply AIG rewriting
+    if ( pParams->fUseRewriting && Abc_NtkNodeNum(pNtk) > 500 )
+    {
+//        abctime clk = Abc_Clock();
+//printf( "Before rwsat = %d. ", Abc_NtkNodeNum(pNtk) );
+        pParams->fUseRewriting = 0;
+        pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 );          
+        Abc_NtkDelete( pNtkTemp );
+        Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+        pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 );          
+        Abc_NtkDelete( pNtkTemp );
+        Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+        Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 );
+//printf( "After rwsat = %d. ", Abc_NtkNodeNum(pNtk) );
+//ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+
+    // convert ABC network into IVY network
+    pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+
+    // solve the CEC problem
+    RetValue = Ivy_FraigProve( &pMan, pParams );
+//    RetValue = -1;
+
+    // convert IVY network into ABC network    
+    pNtk = Abc_NtkIvyAfter( pNtkTemp = pNtk, pMan, 0, 0 );
+    Abc_NtkDelete( pNtkTemp );
+    // transfer model if given
+    pNtk->pModel = (int *)pMan->pData; pMan->pData = NULL;
+    Ivy_ManStop( pMan );
+
+    // try to prove it using brute force SAT with good CNF encoding
+    if ( RetValue < 0 )
+    {
+        pMan2 = Abc_NtkToDar( pNtk, 0, 0 );
+        // dump the miter before entering high-effort solving
+        if ( pParams->fVerbose )
+        {
+            char pFileName[100];
+            sprintf( pFileName, "cecmiter.aig" );
+            Ioa_WriteAiger( pMan2, pFileName, 0, 0 );
+            printf( "Intermediate reduced miter is written into file \"%s\".\n", pFileName );
+        }
+        RetValue = Fra_FraigSat( pMan2, pParams->nMiteringLimitLast, 0, 0, 0, 0, 0, 0, 0, pParams->fVerbose ); 
+        pNtk->pModel = (int *)pMan2->pData, pMan2->pData = NULL;
+        Aig_ManStop( pMan2 );
+    }
+
+    // try to prove it using brute force BDDs
+    if ( RetValue < 0 && pParams->fUseBdds )
+    {
+        if ( pParams->fVerbose )
+        {
+            printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit );
+            fflush( stdout );
+        }
+        pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 );
+        if ( pNtk )   
+        {
+            Abc_NtkDelete( pNtkTemp );
+            RetValue = ( (Abc_NtkNodeNum(pNtk) == 1) && (Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pData == Cudd_ReadLogicZero((DdManager *)pNtk->pManFunc)) );
+        }
+        else 
+            pNtk = pNtkTemp;
+    }
+
+    // return the result
+    *ppNtk = pNtk;
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gives the current ABC network to AIG manager for processing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk )
+{
+//    Abc_Ntk_t * pNtkAig;
+    Ivy_Man_t * pMan;//, * pTemp;
+//    int fCleanup = 1;
+//    int nNodes;
+//    int nLatches = Abc_NtkLatchNum(pNtk);
+    Vec_Int_t * vInit = Abc_NtkCollectLatchValuesIvy( pNtk, 0 );
+
+    assert( !Abc_NtkIsNetlist(pNtk) );
+    if ( Abc_NtkIsBddLogic(pNtk) )
+    {
+        if ( !Abc_NtkBddToSop(pNtk, 0) )
+        {
+            Vec_IntFree( vInit );
+            printf( "Abc_NtkIvy(): Converting to SOPs has failed.\n" );
+            return NULL;
+        }
+    }
+    if ( Abc_NtkCountSelfFeedLatches(pNtk) )
+    {
+        printf( "Warning: The network has %d self-feeding latches. Quitting.\n", Abc_NtkCountSelfFeedLatches(pNtk) );
+        return NULL;
+    }
+
+    // print warning about choice nodes
+    if ( Abc_NtkGetChoiceNum( pNtk ) )
+        printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" );
+
+    // convert to the AIG manager
+    pMan = Abc_NtkToIvy( pNtk );
+    if ( !Ivy_ManCheck( pMan ) )
+    {
+        Vec_IntFree( vInit );
+        printf( "AIG check has failed.\n" );
+        Ivy_ManStop( pMan );
+        return NULL;
+    }
+
+//    Ivy_MffcTest( pMan );
+//    Ivy_ManPrintStats( pMan );
+
+//    pMan = Ivy_ManBalance( pTemp = pMan, 1 );
+//    Ivy_ManStop( pTemp );
+
+//    Ivy_ManSeqRewrite( pMan, 0, 0 );
+//    Ivy_ManTestCutsAlg( pMan );
+//    Ivy_ManTestCutsBool( pMan );
+//    Ivy_ManRewriteAlg( pMan, 1, 1 );
+
+//    pMan = Ivy_ManResyn( pTemp = pMan, 1, 0 );
+//    Ivy_ManStop( pTemp );
+
+//    Ivy_ManTestCutsAll( pMan );
+//    Ivy_ManTestCutsTravAll( pMan );
+
+//    Ivy_ManPrintStats( pMan );
+
+//    Ivy_ManPrintStats( pMan );
+//    Ivy_ManRewritePre( pMan, 1, 0, 0 );
+//    Ivy_ManPrintStats( pMan );
+//    printf( "\n" );
+
+//    Ivy_ManPrintStats( pMan );
+//    Ivy_ManMakeSeq( pMan, nLatches, pInit );
+//    Ivy_ManPrintStats( pMan );
+
+//    Ivy_ManRequiredLevels( pMan );
+
+//    Ivy_FastMapPerform( pMan, 8 );
+    Ivy_ManStop( pMan );
+    return NULL;
+
+
+/*
+    // convert from the AIG manager
+    pNtkAig = Abc_NtkFromIvy( pNtk, pMan );
+//    pNtkAig = Abc_NtkFromIvySeq( pNtk, pMan );
+    Ivy_ManStop( pMan );
+
+    // report the cleanup results
+    if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) )
+        printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes );
+    // duplicate EXDC 
+    if ( pNtk->pExdc )
+        pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pNtkAig ) )
+    {
+        ABC_FREE( pInit );
+        printf( "Abc_NtkStrash: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkAig );
+        return NULL;
+    }
+
+    ABC_FREE( pInit );
+    return pNtkAig;
+*/
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from the AIG manager into ABC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromIvy( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan )
+{
+    Vec_Int_t * vNodes;
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pObj, * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1;
+    Ivy_Obj_t * pNode;
+    int i;
+    // perform strashing
+    pNtk = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
+    // transfer the pointers to the basic nodes
+    Ivy_ManConst1(pMan)->TravId = Abc_EdgeFromNode( Abc_AigConst1(pNtk) );
+    Abc_NtkForEachCi( pNtkOld, pObj, i )
+        Ivy_ManPi(pMan, i)->TravId = Abc_EdgeFromNode( pObj->pCopy );
+    // rebuild the AIG
+    vNodes = Ivy_ManDfs( pMan );
+    Ivy_ManForEachNodeVec( pMan, vNodes, pNode, i )
+    {
+        // add the first fanin
+        pFaninNew0 = Abc_ObjFanin0Ivy( pNtk, pNode );
+        if ( Ivy_ObjIsBuf(pNode) )
+        {
+            pNode->TravId = Abc_EdgeFromNode( pFaninNew0 );
+            continue;
+        }
+        // add the second fanin
+        pFaninNew1 = Abc_ObjFanin1Ivy( pNtk, pNode );
+        // create the new node
+        if ( Ivy_ObjIsExor(pNode) )
+            pObjNew = Abc_AigXor( (Abc_Aig_t *)pNtk->pManFunc, pFaninNew0, pFaninNew1 );
+        else
+            pObjNew = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pFaninNew0, pFaninNew1 );
+        pNode->TravId = Abc_EdgeFromNode( pObjNew );
+    }
+    // connect the PO nodes
+    Abc_NtkForEachCo( pNtkOld, pObj, i )
+    {
+        pFaninNew = Abc_ObjFanin0Ivy( pNtk, Ivy_ManPo(pMan, i) );
+        Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
+    }
+    Vec_IntFree( vNodes );
+    if ( !Abc_NtkCheck( pNtk ) )
+        fprintf( stdout, "Abc_NtkFromIvy(): Network check has failed.\n" );
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from the AIG manager into ABC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromIvySeq( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan, int fHaig )
+{
+    Vec_Int_t * vNodes, * vLatches;
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pObj, * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1;
+    Ivy_Obj_t * pNode, * pTemp;
+    int i;
+//    assert( Ivy_ManLatchNum(pMan) > 0 );
+    // perform strashing
+    pNtk = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
+    // transfer the pointers to the basic nodes
+    Ivy_ManConst1(pMan)->TravId = Abc_EdgeFromNode( Abc_AigConst1(pNtk) );
+    Abc_NtkForEachPi( pNtkOld, pObj, i )
+        Ivy_ManPi(pMan, i)->TravId = Abc_EdgeFromNode( pObj->pCopy );
+    // create latches of the new network
+    vNodes = Ivy_ManDfsSeq( pMan, &vLatches );
+    Ivy_ManForEachNodeVec( pMan, vLatches, pNode, i )
+    {
+        pObjNew = Abc_NtkCreateLatch( pNtk );
+        pFaninNew0 = Abc_NtkCreateBi( pNtk );
+        pFaninNew1 = Abc_NtkCreateBo( pNtk );
+        Abc_ObjAddFanin( pObjNew, pFaninNew0 );
+        Abc_ObjAddFanin( pFaninNew1, pObjNew );
+        if ( fHaig || Ivy_ObjInit(pNode) == IVY_INIT_DC )
+            Abc_LatchSetInitDc( pObjNew );
+        else if ( Ivy_ObjInit(pNode) == IVY_INIT_1 )
+            Abc_LatchSetInit1( pObjNew );
+        else if ( Ivy_ObjInit(pNode) == IVY_INIT_0 )
+            Abc_LatchSetInit0( pObjNew );
+        else assert( 0 );
+        pNode->TravId = Abc_EdgeFromNode( pFaninNew1 );
+    }
+    Abc_NtkAddDummyBoxNames( pNtk );
+    // rebuild the AIG
+    Ivy_ManForEachNodeVec( pMan, vNodes, pNode, i )
+    {
+        // add the first fanin
+        pFaninNew0 = Abc_ObjFanin0Ivy( pNtk, pNode );
+        if ( Ivy_ObjIsBuf(pNode) )
+        {
+            pNode->TravId = Abc_EdgeFromNode( pFaninNew0 );
+            continue;
+        }
+        // add the second fanin
+        pFaninNew1 = Abc_ObjFanin1Ivy( pNtk, pNode );
+        // create the new node
+        if ( Ivy_ObjIsExor(pNode) )
+            pObjNew = Abc_AigXor( (Abc_Aig_t *)pNtk->pManFunc, pFaninNew0, pFaninNew1 );
+        else
+            pObjNew = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pFaninNew0, pFaninNew1 );
+        pNode->TravId = Abc_EdgeFromNode( pObjNew );
+        // process the choice nodes
+        if ( fHaig && pNode->pEquiv && Ivy_ObjRefs(pNode) > 0 )
+        {
+            pFaninNew = Abc_EdgeToNode( pNtk, pNode->TravId );
+//            pFaninNew->fPhase = 0;
+            assert( !Ivy_IsComplement(pNode->pEquiv) );
+            for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Ivy_Regular(pTemp->pEquiv) )
+            {
+                pFaninNew1 = Abc_EdgeToNode( pNtk, pTemp->TravId );
+//                pFaninNew1->fPhase = Ivy_IsComplement( pTemp->pEquiv );
+                pFaninNew->pData = pFaninNew1;
+                pFaninNew = pFaninNew1;
+            }
+            pFaninNew->pData = NULL;
+//            printf( "Writing choice node %d.\n", pNode->Id );
+        }
+    }
+    // connect the PO nodes
+    Abc_NtkForEachPo( pNtkOld, pObj, i )
+    {
+        pFaninNew = Abc_ObjFanin0Ivy( pNtk, Ivy_ManPo(pMan, i) );
+        Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
+    }
+    // connect the latches
+    Ivy_ManForEachNodeVec( pMan, vLatches, pNode, i )
+    {
+        pFaninNew = Abc_ObjFanin0Ivy( pNtk, pNode );
+        Abc_ObjAddFanin( Abc_ObjFanin0(Abc_NtkBox(pNtk, i)), pFaninNew );
+    }
+    Vec_IntFree( vLatches );
+    Vec_IntFree( vNodes );
+    if ( !Abc_NtkCheck( pNtk ) )
+        fprintf( stdout, "Abc_NtkFromIvySeq(): Network check has failed.\n" );
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from the AIG manager into ABC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Man_t * Abc_NtkToIvy( Abc_Ntk_t * pNtkOld )
+{
+    Ivy_Man_t * pMan;
+    Abc_Obj_t * pObj;
+    Ivy_Obj_t * pFanin;
+    int i;
+    // create the manager
+    assert( Abc_NtkHasSop(pNtkOld) || Abc_NtkIsStrash(pNtkOld) );
+    pMan = Ivy_ManStart();
+    // create the PIs
+    if ( Abc_NtkIsStrash(pNtkOld) )
+        Abc_AigConst1(pNtkOld)->pCopy = (Abc_Obj_t *)Ivy_ManConst1(pMan);
+    Abc_NtkForEachCi( pNtkOld, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)Ivy_ObjCreatePi(pMan);
+    // perform the conversion of the internal nodes
+    Abc_NtkStrashPerformAig( pNtkOld, pMan );
+    // create the POs
+    Abc_NtkForEachCo( pNtkOld, pObj, i )
+    {
+        pFanin = (Ivy_Obj_t *)Abc_ObjFanin0(pObj)->pCopy;
+        pFanin = Ivy_NotCond( pFanin, Abc_ObjFaninC0(pObj) );
+        Ivy_ObjCreatePo( pMan, pFanin );
+    }
+    Ivy_ManCleanup( pMan );
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the network for strashing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkStrashPerformAig( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan )
+{
+//    ProgressBar * pProgress;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNode;
+    int i;
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+//    pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+//        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        pNode->pCopy = (Abc_Obj_t *)Abc_NodeStrashAig( pMan, pNode );
+    }
+//    Extra_ProgressBarStop( pProgress );
+    Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes one logic node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Abc_NodeStrashAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode )
+{
+    int fUseFactor = 1;
+    char * pSop;
+    Ivy_Obj_t * pFanin0, * pFanin1;
+
+    assert( Abc_ObjIsNode(pNode) );
+
+    // consider the case when the graph is an AIG
+    if ( Abc_NtkIsStrash(pNode->pNtk) )
+    {
+        if ( Abc_AigNodeIsConst(pNode) )
+            return Ivy_ManConst1(pMan);
+        pFanin0 = (Ivy_Obj_t *)Abc_ObjFanin0(pNode)->pCopy;
+        pFanin0 = Ivy_NotCond( pFanin0, Abc_ObjFaninC0(pNode) );
+        pFanin1 = (Ivy_Obj_t *)Abc_ObjFanin1(pNode)->pCopy;
+        pFanin1 = Ivy_NotCond( pFanin1, Abc_ObjFaninC1(pNode) );
+        return Ivy_And( pMan, pFanin0, pFanin1 );
+    }
+
+    // get the SOP of the node
+    if ( Abc_NtkHasMapping(pNode->pNtk) )
+        pSop = Mio_GateReadSop((Mio_Gate_t *)pNode->pData);
+    else
+        pSop = (char *)pNode->pData;
+
+    // consider the constant node
+    if ( Abc_NodeIsConst(pNode) )
+        return Ivy_NotCond( Ivy_ManConst1(pMan), Abc_SopIsConst0(pSop) );
+
+    // decide when to use factoring
+    if ( fUseFactor && Abc_ObjFaninNum(pNode) > 2 && Abc_SopGetCubeNum(pSop) > 1 && !Abc_SopIsExorType(pSop) )
+        return Abc_NodeStrashAigFactorAig( pMan, pNode, pSop );
+    return Abc_NodeStrashAigSopAig( pMan, pNode, pSop );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes one logic node using its SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Abc_NodeStrashAigSopAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop )
+{
+    Abc_Obj_t * pFanin;
+    Ivy_Obj_t * pAnd, * pSum;
+    char * pCube;
+    int i, nFanins;
+    int fExor = Abc_SopIsExorType(pSop);
+
+    // get the number of node's fanins
+    nFanins = Abc_ObjFaninNum( pNode );
+    assert( nFanins == Abc_SopGetVarNum(pSop) );
+    // go through the cubes of the node's SOP
+    pSum = Ivy_Not( Ivy_ManConst1(pMan) );
+    Abc_SopForEachCube( pSop, nFanins, pCube )
+    {
+        // create the AND of literals
+        pAnd = Ivy_ManConst1(pMan);
+        Abc_ObjForEachFanin( pNode, pFanin, i ) // pFanin can be a net
+        {
+            if ( pCube[i] == '1' )
+                pAnd = Ivy_And( pMan, pAnd, (Ivy_Obj_t *)pFanin->pCopy );
+            else if ( pCube[i] == '0' )
+                pAnd = Ivy_And( pMan, pAnd, Ivy_Not((Ivy_Obj_t *)pFanin->pCopy) );
+        }
+        // add to the sum of cubes
+        if ( fExor )
+            pSum = Ivy_Exor( pMan, pSum, pAnd );
+        else
+            pSum = Ivy_Or( pMan, pSum, pAnd );
+    }
+    // decide whether to complement the result
+    if ( Abc_SopIsComplement(pSop) )
+        pSum = Ivy_Not(pSum);
+    return pSum;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashed n-input XOR function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Abc_NodeStrashAigExorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop )
+{
+    Abc_Obj_t * pFanin;
+    Ivy_Obj_t * pSum;
+    int i, nFanins;
+    // get the number of node's fanins
+    nFanins = Abc_ObjFaninNum( pNode );
+    assert( nFanins == Abc_SopGetVarNum(pSop) );
+    // go through the cubes of the node's SOP
+    pSum = Ivy_Not( Ivy_ManConst1(pMan) );
+    for ( i = 0; i < nFanins; i++ )
+    {
+        pFanin = Abc_ObjFanin( pNode, i );
+        pSum = Ivy_Exor( pMan, pSum, (Ivy_Obj_t *)pFanin->pCopy );
+    }
+    if ( Abc_SopIsComplement(pSop) )
+        pSum = Ivy_Not(pSum);
+    return pSum;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes one logic node using its SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Abc_NodeStrashAigFactorAig( Ivy_Man_t * pMan, Abc_Obj_t * pRoot, char * pSop )
+{
+    Dec_Graph_t * pFForm;
+    Dec_Node_t * pNode;
+    Ivy_Obj_t * pAnd;
+    int i;
+
+//    extern Ivy_Obj_t * Dec_GraphToNetworkAig( Ivy_Man_t * pMan, Dec_Graph_t * pGraph );
+
+//    assert( 0 );
+
+    // perform factoring
+    pFForm = Dec_Factor( pSop );
+    // collect the fanins
+    Dec_GraphForEachLeaf( pFForm, pNode, i )
+        pNode->pFunc = Abc_ObjFanin(pRoot,i)->pCopy;
+    // perform strashing
+//    pAnd = Dec_GraphToNetworkAig( pMan, pFForm );
+    pAnd = Dec_GraphToNetworkIvy( pMan, pFForm );
+//    pAnd = NULL;
+
+    Dec_GraphFree( pFForm );
+    return pAnd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes one logic node using its SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkCollectLatchValuesIvy( Abc_Ntk_t * pNtk, int fUseDcs )
+{
+    Abc_Obj_t * pLatch;
+    Vec_Int_t * vArray;
+    int i;
+    vArray = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) );
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+        if ( fUseDcs || Abc_LatchIsInitDc(pLatch) )
+            Vec_IntPush( vArray, IVY_INIT_DC );
+        else if ( Abc_LatchIsInit1(pLatch) )
+            Vec_IntPush( vArray, IVY_INIT_1 );
+        else if ( Abc_LatchIsInit0(pLatch) )
+            Vec_IntPush( vArray, IVY_INIT_0 );
+        else assert( 0 );
+    }
+    return vArray;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcLog.c b/abc-build/src/base/abci/abcLog.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcLog.c
@@ -0,0 +1,242 @@
+/**CFile****************************************************************
+
+  FileName    [abcLog.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Log file printing.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcLog.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "aig/gia/gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+/*
+    Log file format (Jiang, Mon, 28 Sep 2009;  updated by Alan in Jan 2011)
+
+    <result> <bug_free_depth>  <engine_name> <0-based_output_num> <0-based_frame>
+    <INIT_STATE> : default is empty line.
+    <TRACE> : default is empty line
+   
+    <result> is one of the following: "snl_SAT", "snl_UNSAT", "snl_UNK", "snl_ABORT".
+    <bug_free_depth> is the number of timeframes exhaustively explored without counter-examples
+    <0-based_output_num> only need to be given if the problem is SAT.
+    <0-based_frame> only need to be given if the problem is SAT and <0-based_frame> is different from <bug_free_depth>.   
+    <INIT_STATE>  : initial state
+    <TRACE> : input vector
+
+    <INIT_STATE>and <TRACE> are strings of 0/1/- ( - means don't care). The length is equivalent to #input*#<cyc>.
+*/
+
+
+         
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkWriteLogFile( char * pFileName, Abc_Cex_t * pCex, int Status, int nFrames, char * pCommand )
+{
+    FILE * pFile;
+    int i;
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open log file for writing \"%s\".\n" , pFileName );
+        return;
+    }
+    // write <result>
+    if ( Status == 1 )
+        fprintf( pFile, "snl_UNSAT" );
+    else if ( Status == 0 )
+        fprintf( pFile, "snl_SAT" );
+    else if ( Status == -1 )
+        fprintf( pFile, "snl_UNK" );
+    else 
+        printf( "Abc_NtkWriteLogFile(): Cannot recognize solving status.\n" );
+    fprintf( pFile, " " );
+    // write <bug_free_depth>
+    fprintf( pFile, "%d", nFrames );
+    fprintf( pFile, " " );
+    // write <engine_name>
+    fprintf( pFile, "%s", pCommand ? pCommand : "unknown" );
+    if ( pCex && Status == 0 )
+        fprintf( pFile, " %d", pCex->iPo );
+    // write <cyc>
+    if ( pCex && pCex->iFrame != nFrames )
+        fprintf( pFile, " %d", pCex->iFrame );
+    fprintf( pFile, "\n" );
+    // write <INIT_STATE>
+    if ( pCex == NULL )
+        fprintf( pFile, "NULL" );
+    else
+    {
+        for ( i = 0; i < pCex->nRegs; i++ )
+            fprintf( pFile, "%d", Abc_InfoHasBit(pCex->pData,i) );
+    }
+    fprintf( pFile, "\n" );
+    // write <TRACE>
+    if ( pCex == NULL )
+        fprintf( pFile, "NULL" );
+    else
+    {
+        assert( pCex->nBits - pCex->nRegs == pCex->nPis * (pCex->iFrame + 1) );
+        for ( i = pCex->nRegs; i < pCex->nBits; i++ )
+            fprintf( pFile, "%d", Abc_InfoHasBit(pCex->pData,i) );
+    }
+    fprintf( pFile, "\n" );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkReadLogFile( char * pFileName, Abc_Cex_t ** ppCex, int * pnFrames )
+{
+    FILE * pFile;
+    Abc_Cex_t * pCex;
+    Vec_Int_t * vNums;
+    char Buffer[1000], * pToken, * RetValue;
+    int c, nRegs = -1, nFrames = -1, iPo = -1, Status = -1, nFrames2 = -1;
+    pFile = fopen( pFileName, "r" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open log file for reading \"%s\".\n" , pFileName );
+        return -1;
+    }
+    RetValue = fgets( Buffer, 1000, pFile );
+    if ( !strncmp( Buffer, "snl_UNSAT", strlen("snl_UNSAT") ) )
+    {
+        Status = 1;
+        nFrames = atoi( Buffer + strlen("snl_UNSAT") ); 
+    }
+    else if ( !strncmp( Buffer, "snl_SAT", strlen("snl_SAT") ) )
+    {
+        Status = 0;
+//        nFrames = atoi( Buffer + strlen("snl_SAT") ); 
+        pToken  = strtok( Buffer + strlen("snl_SAT"), " \t\n" );
+        nFrames = atoi( pToken ); 
+        pToken  = strtok( NULL, " \t\n" );
+        pToken  = strtok( NULL, " \t\n" );
+        if ( pToken != NULL )
+        {
+            iPo     = atoi( pToken ); 
+            pToken  = strtok( NULL, " \t\n" );
+            if ( pToken )
+                nFrames2 = atoi( pToken ); 
+        }
+//        else
+//            printf( "Warning! The current status is SAT but the current CEX is not given.\n"  );
+    }
+    else if ( !strncmp( Buffer, "snl_UNK", strlen("snl_UNK") ) )
+    {
+        Status = -1;
+        nFrames = atoi( Buffer + strlen("snl_UNK") ); 
+    }
+    else
+    {
+        printf( "Unrecognized status.\n" );
+    }
+    // found regs till the new line
+    vNums = Vec_IntAlloc( 100 );
+    while ( (c = fgetc(pFile)) != EOF )
+    {
+        if ( c == '\n' )
+            break;
+        if ( c == '0' || c == '1' )
+            Vec_IntPush( vNums, c - '0' );
+    }
+    nRegs = Vec_IntSize(vNums);
+    // skip till the new line
+    while ( (c = fgetc(pFile)) != EOF )
+    {
+        if ( c == '0' || c == '1' )
+            Vec_IntPush( vNums, c - '0' );
+    }
+    fclose( pFile );
+    if ( Vec_IntSize(vNums) )
+    {
+        int iFrameCex = (nFrames2 == -1) ? nFrames : nFrames2;
+        if ( nRegs < 0 )
+        {
+            printf( "Cannot read register number.\n" );
+            Vec_IntFree( vNums );
+            return -1;
+        }
+        if ( Vec_IntSize(vNums)-nRegs == 0 )
+        {
+            printf( "Cannot read counter example.\n" );
+            Vec_IntFree( vNums );
+            return -1;
+        }
+        if ( (Vec_IntSize(vNums)-nRegs) % (iFrameCex + 1) != 0 )
+        {
+            printf( "Incorrect number of bits.\n" );
+            Vec_IntFree( vNums );
+            return -1;
+        }
+        pCex = Abc_CexAlloc( nRegs, (Vec_IntSize(vNums)-nRegs)/(iFrameCex + 1), iFrameCex + 1 );
+        pCex->iPo    = iPo;
+        pCex->iFrame = iFrameCex;
+        assert( Vec_IntSize(vNums) == pCex->nBits );
+        for ( c = 0; c < pCex->nBits; c++ )
+            if ( Vec_IntEntry(vNums, c) )
+                Abc_InfoSetBit( pCex->pData, c );
+        Vec_IntFree( vNums );
+        if ( ppCex )
+            *ppCex = pCex;
+        else
+            ABC_FREE( pCex );
+    }
+    else
+        Vec_IntFree( vNums );
+    if ( pnFrames )
+        *pnFrames = nFrames;
+    return Status;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcLut.c b/abc-build/src/base/abci/abcLut.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcLut.c
@@ -0,0 +1,793 @@
+/**CFile****************************************************************
+
+  FileName    [abcLut.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Superchoicing for K-LUTs.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "opt/cut/cut.h"
+
+ABC_NAMESPACE_IMPL_START
+
+#define LARGE_LEVEL 1000000
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define SCL_LUT_MAX          6   // the maximum LUT size
+#define SCL_VARS_MAX        15   // the maximum number of variables
+#define SCL_NODE_MAX      1000   // the maximum number of nodes
+
+typedef struct Abc_ManScl_t_ Abc_ManScl_t;
+struct Abc_ManScl_t_
+{
+    // paramers
+    int                nLutSize;    // the LUT size
+    int                nCutSizeMax; // the max number of leaves of the cone
+    int                nNodesMax;   // the max number of divisors in the cone
+    int                nWords;      // the number of machine words in sim info
+    // structural representation of the cone
+    Vec_Ptr_t *        vLeaves;     // leaves of the cut
+    Vec_Ptr_t *        vVolume;     // volume of the cut
+    int                pBSet[SCL_VARS_MAX]; // bound set
+    // functional representation of the cone
+    unsigned *         uTruth;      // truth table of the cone
+    // representation of truth tables
+    unsigned **        uVars;       // elementary truth tables
+    unsigned **        uSims;       // truth tables of the nodes
+    unsigned **        uCofs;       // truth tables of the cofactors
+};
+
+static Vec_Ptr_t * s_pLeaves = NULL;
+
+static Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize );
+static Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax );
+static void Abc_ManSclStop( Abc_ManScl_t * p );
+static void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj );
+
+static Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * pManScl, Abc_Obj_t * pObj );
+static int Abc_NodeDecomposeStep( Abc_ManScl_t * pManScl );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs superchoicing for K-LUTs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int fVerbose )
+{
+    ProgressBar * pProgress;
+    Abc_ManCut_t * pManCut;
+    Abc_ManScl_t * pManScl;
+    Cut_Man_t * pManCuts;
+    Abc_Obj_t * pObj, * pFanin, * pObjTop;
+    int i, LevelMax, nNodes;
+    int nNodesTried, nNodesDec, nNodesExist, nNodesUsed;
+
+    assert( Abc_NtkIsSopLogic(pNtk) );
+    if ( nLutSize < 3 || nLutSize > SCL_LUT_MAX )
+    {
+        printf( "LUT size (%d) does not belong to the interval: 3 <= LUT size <= %d\n", nLutSize, SCL_LUT_MAX );
+        return 0;
+    }
+    if ( nCutSizeMax <= nLutSize || nCutSizeMax > SCL_VARS_MAX )
+    {
+        printf( "Cut size (%d) does not belong to the interval: LUT size (%d) < Cut size <= %d\n", nCutSizeMax, nLutSize, SCL_VARS_MAX );
+        return 0;
+    }
+
+    assert( nLutSize <= SCL_LUT_MAX );
+    assert( nCutSizeMax <= SCL_VARS_MAX );
+    nNodesTried = nNodesDec = nNodesExist = nNodesUsed = 0;
+
+    // set the delays of the CIs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->Level = 0;
+
+//Abc_NtkLevel( pNtk );
+ 
+    // start the managers
+    pManScl = Abc_ManSclStart( nLutSize, nCutSizeMax, 1000 );
+    pManCuts = Abc_NtkStartCutManForScl( pNtk, nLutSize );
+    pManCut = Abc_NtkManCutStart( nCutSizeMax, 100000, 100000, 100000 );
+    s_pLeaves = Abc_NtkManCutReadCutSmall( pManCut );
+    pManScl->vVolume = Abc_NtkManCutReadVisited( pManCut );
+
+    // process each internal node (assuming topological order of nodes!!!)
+    nNodes = Abc_NtkObjNumMax(pNtk);
+    pProgress = Extra_ProgressBarStart( stdout, nNodes );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+//        if ( i != nNodes-1 )
+//            continue;
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        if ( i >= nNodes )
+            break;
+        if ( Abc_ObjFaninNum(pObj) != 2 )
+            continue;
+        nNodesTried++;
+
+        // map this node using regular cuts
+//        pObj->Level = 0;
+        Abc_NodeLutMap( pManCuts, pObj );
+        // compute the cut
+        pManScl->vLeaves = Abc_NodeFindCut( pManCut, pObj, 0 );
+        if ( Vec_PtrSize(pManScl->vLeaves) <= nLutSize )
+            continue;
+        // get the volume of the cut
+        if ( Vec_PtrSize(pManScl->vVolume) > SCL_NODE_MAX )
+            continue;
+        nNodesDec++;
+
+        // decompose the cut
+        pObjTop = Abc_NodeSuperChoiceLut( pManScl, pObj );
+        if ( pObjTop == NULL )
+            continue;
+        nNodesExist++;
+
+        // if there is no delay improvement, skip; otherwise, update level
+        if ( pObjTop->Level >= pObj->Level )
+        {
+            Abc_NtkDeleteObj_rec( pObjTop, 1 );
+            continue;
+        }
+        pObj->Level = pObjTop->Level;
+        nNodesUsed++;
+    }
+    Extra_ProgressBarStop( pProgress );
+
+    // delete the managers
+    Abc_ManSclStop( pManScl );
+    Abc_NtkManCutStop( pManCut );
+    Cut_ManStop( pManCuts );
+
+    // get the largest arrival time
+    LevelMax = 0;
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        pFanin = Abc_ObjFanin0( pObj );
+        // skip inv/buf
+        if ( Abc_ObjFaninNum(pFanin) == 1 )
+            pFanin = Abc_ObjFanin0( pFanin );
+        // get the new level
+        LevelMax = Abc_MaxInt( LevelMax, (int)pFanin->Level );
+    }
+
+    if ( fVerbose )
+    printf( "Try = %d. Dec = %d. Exist = %d. Use = %d. SUPER = %d levels of %d-LUTs.\n", 
+        nNodesTried, nNodesDec, nNodesExist, nNodesUsed, LevelMax, nLutSize );
+//    if ( fVerbose )
+//    printf( "The network is superchoiced for %d levels of %d-LUTs.\n", LevelMax, nLutSize );
+
+    // clean the data field
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->pNext = NULL;
+
+    // check
+    if ( !Abc_NtkCheck( pNtk ) )
+    {
+        printf( "Abc_NtkSuperChoiceLut: The network check has failed.\n" );
+        return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs LUT mapping of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj )
+{
+    Cut_Cut_t * pCut;
+    Abc_Obj_t * pFanin;
+    int i, DelayMax;
+    pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCuts, pObj, 0, 0 );
+    assert( pCut != NULL );
+    assert( pObj->Level == 0 );
+    // go through the cuts
+    pObj->Level = LARGE_LEVEL;
+    for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext )
+    {
+        DelayMax = 0;
+        for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        {
+            pFanin = Abc_NtkObj( pObj->pNtk, pCut->pLeaves[i] );
+//            assert( Abc_ObjIsCi(pFanin) || pFanin->Level > 0 ); // should hold if node ordering is topological
+            if ( DelayMax < (int)pFanin->Level )
+                DelayMax = pFanin->Level;
+        }
+        if ( (int)pObj->Level > DelayMax )
+            pObj->Level = DelayMax;
+    }
+    assert( pObj->Level < LARGE_LEVEL );
+    pObj->Level++;
+//    printf( "%d(%d) ", pObj->Id, pObj->Level );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the cut manager for rewriting.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize )
+{
+    static Cut_Params_t Params, * pParams = &Params;
+    Cut_Man_t * pManCut;
+    Abc_Obj_t * pObj;
+    int i;
+    // start the cut manager
+    memset( pParams, 0, sizeof(Cut_Params_t) );
+    pParams->nVarsMax  = nLutSize; // the max cut size ("k" of the k-feasible cuts)
+    pParams->nKeepMax  = 500;   // the max number of cuts kept at a node
+    pParams->fTruth    = 0;     // compute truth tables
+    pParams->fFilter   = 1;     // filter dominated cuts
+    pParams->fSeq      = 0;     // compute sequential cuts
+    pParams->fDrop     = 0;     // drop cuts on the fly
+    pParams->fVerbose  = 0;     // the verbosiness flag
+    pParams->nIdsMax   = Abc_NtkObjNumMax( pNtk );
+    pManCut = Cut_ManStart( pParams );
+    if ( pParams->fDrop )
+        Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) );
+    // set cuts for PIs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        if ( Abc_ObjFanoutNum(pObj) > 0 )
+            Cut_NodeSetTriv( pManCut, pObj->Id );
+    return pManCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax )
+{
+    Abc_ManScl_t * p;
+    int i, k;
+    assert( sizeof(unsigned) == 4 );
+    p = ABC_ALLOC( Abc_ManScl_t, 1 );
+    memset( p, 0, sizeof(Abc_ManScl_t) );
+    p->nLutSize    = nLutSize;
+    p->nCutSizeMax = nCutSizeMax;
+    p->nNodesMax   = nNodesMax;
+    p->nWords      = Extra_TruthWordNum(nCutSizeMax);
+    // allocate simulation info
+    p->uVars = (unsigned **)Extra_ArrayAlloc( nCutSizeMax, p->nWords, 4 );
+    p->uSims = (unsigned **)Extra_ArrayAlloc( nNodesMax, p->nWords, 4 );
+    p->uCofs = (unsigned **)Extra_ArrayAlloc( 2 << nLutSize, p->nWords, 4 );
+    memset( p->uVars[0], 0, nCutSizeMax * p->nWords * 4 );
+    // assign elementary truth tables
+    for ( k = 0; k < p->nCutSizeMax; k++ )
+        for ( i = 0; i < p->nWords * 32; i++ )
+            if ( i & (1 << k) )
+                p->uVars[k][i>>5] |= (1 << (i&31));
+    // other data structures
+//    p->vBound = Vec_IntAlloc( nCutSizeMax );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ManSclStop( Abc_ManScl_t * p )
+{
+//    Vec_IntFree( p->vBound );
+    ABC_FREE( p->uVars );
+    ABC_FREE( p->uSims );
+    ABC_FREE( p->uCofs );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs superchoicing for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Abc_NodeSuperChoiceTruth( Abc_ManScl_t * pManScl )
+{
+    Abc_Obj_t * pObj;
+    unsigned * puData0, * puData1, * puData = NULL;
+    char * pSop;
+    int i, k;
+    // set elementary truth tables
+    Vec_PtrForEachEntry( Abc_Obj_t *, pManScl->vLeaves, pObj, i )
+        pObj->pNext = (Abc_Obj_t *)pManScl->uVars[i];
+    // compute truth tables for internal nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, pManScl->vVolume, pObj, i )
+    {
+        // set storage for the node's simulation info
+        pObj->pNext = (Abc_Obj_t *)pManScl->uSims[i];
+        // get pointer to the simulation info
+        puData  = (unsigned *)pObj->pNext;
+        puData0 = (unsigned *)Abc_ObjFanin0(pObj)->pNext;
+        puData1 = (unsigned *)Abc_ObjFanin1(pObj)->pNext;
+        // simulate
+        pSop = (char *)pObj->pData;
+        if ( pSop[0] == '0' && pSop[1] == '0' )
+            for ( k = 0; k < pManScl->nWords; k++ )
+                puData[k] = ~puData0[k] & ~puData1[k];
+        else if ( pSop[0] == '0' )
+            for ( k = 0; k < pManScl->nWords; k++ )
+                puData[k] = ~puData0[k] & puData1[k];
+        else if ( pSop[1] == '0' )
+            for ( k = 0; k < pManScl->nWords; k++ )
+                puData[k] = puData0[k] & ~puData1[k];
+        else 
+            for ( k = 0; k < pManScl->nWords; k++ )
+                puData[k] = puData0[k] & puData1[k];
+    }
+    return puData;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs superchoicing for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeSuperChoiceCollect2_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vVolume )
+{
+    if ( pObj->fMarkC )
+        return;
+    pObj->fMarkC = 1;
+    assert( Abc_ObjFaninNum(pObj) == 2 );
+    Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin0(pObj), vVolume );
+    Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin1(pObj), vVolume );
+    Vec_PtrPush( vVolume, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs superchoicing for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeSuperChoiceCollect2( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+        pObj->fMarkC = 1;
+    Vec_PtrClear( vVolume );
+    Abc_NodeSuperChoiceCollect2_rec( pRoot, vVolume );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+        pObj->fMarkC = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vVolume, pObj, i )
+        pObj->fMarkC = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs superchoicing for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeSuperChoiceCollect_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume )
+{
+    if ( pObj->fMarkB )
+    {
+        Vec_PtrPush( vLeaves, pObj );
+        pObj->fMarkB = 0;
+    }
+    if ( pObj->fMarkC )
+        return;
+    pObj->fMarkC = 1;
+    assert( Abc_ObjFaninNum(pObj) == 2 );
+    Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin0(pObj), vLeaves, vVolume );
+    Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin1(pObj), vLeaves, vVolume );
+    Vec_PtrPush( vVolume, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs superchoicing for one node.]
+
+  Description [Orders the leaves topologically.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeSuperChoiceCollect( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume )
+{
+    Abc_Obj_t * pObj;
+    int i, nLeaves;
+    nLeaves = Vec_PtrSize(vLeaves);
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+        pObj->fMarkB = pObj->fMarkC = 1;
+    Vec_PtrClear( vVolume );
+    Vec_PtrClear( vLeaves );
+    Abc_NodeSuperChoiceCollect_rec( pRoot, vLeaves, vVolume );
+    assert( Vec_PtrSize(vLeaves) == nLeaves );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+        pObj->fMarkC = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vVolume, pObj, i )
+        pObj->fMarkC = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs superchoicing for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeLeavesRemove( Vec_Ptr_t * vLeaves, unsigned uPhase, int nVars )
+{
+    int i;
+    for ( i = nVars - 1; i >= 0; i-- )
+        if ( uPhase & (1 << i) )
+            Vec_PtrRemove( vLeaves, Vec_PtrEntry(vLeaves, i) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs superchoicing for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeGetLevel( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin;
+    int i, Level;
+    Level = 0;
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        Level = Abc_MaxInt( Level, (int)pFanin->Level );
+    return Level + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs superchoicing for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin, * pObjNew;
+    int i, nVars, uSupport, nSuppVars;
+    // collect the cone using DFS (excluding leaves)
+    Abc_NodeSuperChoiceCollect2( pObj, p->vLeaves, p->vVolume );
+    assert( Vec_PtrEntryLast(p->vVolume) == pObj );  
+    // compute the truth table
+    p->uTruth = Abc_NodeSuperChoiceTruth( p );
+    // get the support of this truth table
+    nVars = Vec_PtrSize(p->vLeaves);
+    uSupport = Extra_TruthSupport(p->uTruth, nVars);
+    nSuppVars = Extra_WordCountOnes(uSupport);
+    assert( nSuppVars <= nVars );
+    if ( nSuppVars == 0 )
+    {
+        pObj->Level = 0;
+        return NULL;
+    }
+    if ( nSuppVars == 1 )
+    {
+        // find the variable
+        for ( i = 0; i < nVars; i++ )
+            if ( uSupport & (1 << i) )
+                break;
+        assert( i < nVars );
+        pFanin = (Abc_Obj_t *)Vec_PtrEntry( p->vLeaves, i );
+        pObj->Level = pFanin->Level;
+        return NULL;
+    }
+    // support-minimize the truth table
+    if ( nSuppVars != nVars )
+    {
+        Extra_TruthShrink( p->uCofs[0], p->uTruth, nSuppVars, nVars, uSupport );
+        Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars );
+        Abc_NodeLeavesRemove( p->vLeaves, ((1 << nVars) - 1) & ~uSupport, nVars );
+    }
+//    return NULL;
+    // decompose the truth table recursively
+    while ( Vec_PtrSize(p->vLeaves) > p->nLutSize )
+        if ( !Abc_NodeDecomposeStep( p ) )
+        {
+            Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pFanin, i )
+                if ( Abc_ObjIsNode(pFanin) && Abc_ObjFanoutNum(pFanin) == 0 )
+                    Abc_NtkDeleteObj_rec( pFanin, 1 );
+            return NULL;
+        }
+    // create the topmost node
+    pObjNew = Abc_NtkCreateNode( pObj->pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pFanin, i )
+        Abc_ObjAddFanin( pObjNew, pFanin );
+    // create the function
+    pObjNew->pData = Abc_SopCreateFromTruth( (Mem_Flex_t *)pObj->pNtk->pManFunc, Vec_PtrSize(p->vLeaves), p->uTruth ); // need ISOP
+    pObjNew->Level = Abc_NodeGetLevel( pObjNew );
+    return pObjNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure used for sorting the nodes in increasing order of levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCompareLevelsInc( int * pp1, int * pp2 )
+{
+    Abc_Obj_t * pNode1, * pNode2;
+    pNode1 = (Abc_Obj_t *)Vec_PtrEntry(s_pLeaves, *pp1);
+    pNode2 = (Abc_Obj_t *)Vec_PtrEntry(s_pLeaves, *pp2);
+    if ( pNode1->Level < pNode2->Level )
+        return -1;
+    if ( pNode1->Level > pNode2->Level ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Selects the earliest arriving nodes from the array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeDecomposeSort( Abc_Obj_t ** pLeaves, int nVars, int * pBSet, int nLutSize )
+{
+    Abc_Obj_t * pTemp[SCL_VARS_MAX];
+    int i, k, kBest, LevelMin;
+    assert( nLutSize < nVars );
+    assert( nVars <= SCL_VARS_MAX );
+    // copy nodes into the internal storage
+//    printf( "(" );
+    for ( i = 0; i < nVars; i++ )
+    {
+        pTemp[i] = pLeaves[i];
+//        printf( " %d", pLeaves[i]->Level );
+    }
+//    printf( " )\n" );
+    // choose one node at a time
+    for ( i = 0; i < nLutSize; i++ )
+    {
+        kBest = -1;
+        LevelMin = LARGE_LEVEL;
+        for ( k = 0; k < nVars; k++ )
+            if ( pTemp[k] && LevelMin > (int)pTemp[k]->Level )
+            {
+                LevelMin = pTemp[k]->Level;
+                kBest = k;
+            }
+        pBSet[i] = kBest;
+        pTemp[kBest] = NULL;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs superchoicing for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeDecomposeStep( Abc_ManScl_t * p )
+{
+    static char pCofClasses[1<<SCL_LUT_MAX][1<<SCL_LUT_MAX];
+    static char nCofClasses[1<<SCL_LUT_MAX];
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pObjNew, * pFanin, * pNodesNew[SCL_LUT_MAX];
+    unsigned * pTruthCof, * pTruthClass, * pTruth, uPhase;
+    int i, k, c, v, w, nVars, nVarsNew, nClasses, nCofs;
+    // set the network
+    pNtk = ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, 0))->pNtk;
+    // find the earliest nodes
+    nVars = Vec_PtrSize(p->vLeaves);
+    assert( nVars > p->nLutSize );
+/*
+    for ( v = 0; v < nVars; v++ )
+        p->pBSet[v] = v;
+    qsort( (void *)p->pBSet, nVars, sizeof(int), 
+            (int (*)(const void *, const void *)) Abc_NodeCompareLevelsInc );
+*/
+    Abc_NodeDecomposeSort( (Abc_Obj_t **)Vec_PtrArray(p->vLeaves), Vec_PtrSize(p->vLeaves), p->pBSet, p->nLutSize );
+    assert( ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[0]))->Level <=
+        ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[1]))->Level );
+    // cofactor w.r.t. the selected variables
+    Extra_TruthCopy( p->uCofs[1], p->uTruth, nVars );
+    c = 2;
+    for ( v = 0; v < p->nLutSize; v++ )
+        for ( k = 0; k < (1<<v); k++ )
+        {
+            Extra_TruthCopy( p->uCofs[c], p->uCofs[c/2], nVars );
+            Extra_TruthCopy( p->uCofs[c+1], p->uCofs[c/2], nVars );
+            Extra_TruthCofactor0( p->uCofs[c], nVars, p->pBSet[v] );
+            Extra_TruthCofactor1( p->uCofs[c+1], nVars, p->pBSet[v] );
+            c += 2;
+        }
+    assert( c == (2 << p->nLutSize) );
+    // count unique cofactors
+    nClasses = 0;
+    nCofs = (1 << p->nLutSize);
+    for ( i = 0; i < nCofs; i++ )
+    {
+        pTruthCof = p->uCofs[ nCofs + i ];
+        for ( k = 0; k < nClasses; k++ )
+        {
+            pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ];
+            if ( Extra_TruthIsEqual( pTruthCof, pTruthClass, nVars ) )
+            {
+                pCofClasses[k][(int)nCofClasses[k]++ ] = i;
+                break;
+            }
+        }
+        if ( k != nClasses )
+            continue;
+        // not found
+        pCofClasses[nClasses][0] = i;
+        nCofClasses[nClasses] = 1;
+        nClasses++;
+        if ( nClasses > nCofs/2 )
+            return 0;
+    }
+    // the number of cofactors is acceptable
+    nVarsNew = Abc_Base2Log( nClasses );
+    assert( nVarsNew < p->nLutSize );
+    // create the remainder truth table
+    // for each class of cofactors, multiply cofactor truth table by its code
+    Extra_TruthClear( p->uTruth, nVars );
+    for ( k = 0; k < nClasses; k++ )
+    {
+        pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ];
+        for ( v = 0; v < nVarsNew; v++ )
+            if ( k & (1 << v) )
+                Extra_TruthAnd( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars );
+            else
+                Extra_TruthSharp( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars );
+        Extra_TruthOr( p->uTruth, p->uTruth, pTruthClass, nVars );
+    }
+    // create nodes
+    pTruth = p->uCofs[0];
+    for ( v = 0; v < nVarsNew; v++ )
+    {
+        Extra_TruthClear( pTruth, p->nLutSize );
+        for ( k = 0; k < nClasses; k++ )
+            if ( k & (1 << v) )
+                for ( i = 0; i < nCofClasses[k]; i++ )
+                {
+                    pTruthCof = p->uCofs[1];
+                    Extra_TruthFill( pTruthCof, p->nLutSize );
+                    for ( w = 0; w < p->nLutSize; w++ )
+                        if ( pCofClasses[k][i] & (1 << (p->nLutSize-1-w)) )
+                            Extra_TruthAnd( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize );
+                        else
+                            Extra_TruthSharp( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize );
+                    Extra_TruthOr( pTruth, pTruth, pTruthCof, p->nLutSize );
+                }
+        // implement the node
+        pObjNew = Abc_NtkCreateNode( pNtk );
+        for ( i = 0; i < p->nLutSize; i++ )
+        {
+            pFanin = (Abc_Obj_t *)Vec_PtrEntry( p->vLeaves, p->pBSet[i] );
+            Abc_ObjAddFanin( pObjNew, pFanin );
+        }
+        // create the function
+        pObjNew->pData = Abc_SopCreateFromTruth( (Mem_Flex_t *)pNtk->pManFunc, p->nLutSize, pTruth ); // need ISOP
+        pObjNew->Level = Abc_NodeGetLevel( pObjNew );
+        pNodesNew[v] = pObjNew;
+    }
+    // put the new nodes back into the list
+    for ( v = 0; v < nVarsNew; v++ )
+        Vec_PtrWriteEntry( p->vLeaves, p->pBSet[v], pNodesNew[v] );
+    // compute the variables that should be removed
+    uPhase = 0;
+    for ( v = nVarsNew; v < p->nLutSize; v++ )
+        uPhase |= (1 << p->pBSet[v]);
+    // remove entries from the array
+    Abc_NodeLeavesRemove( p->vLeaves, uPhase, nVars );
+    // update truth table
+    Extra_TruthShrink( p->uCofs[0], p->uTruth, nVars - p->nLutSize + nVarsNew, nVars, ((1 << nVars) - 1) & ~uPhase );
+    Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars );
+    assert( !Extra_TruthVarInSupport( p->uTruth, nVars, nVars - p->nLutSize + nVarsNew ) );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
+
+
diff --git a/abc-build/src/base/abci/abcLutmin.c b/abc-build/src/base/abci/abcLutmin.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcLutmin.c
@@ -0,0 +1,774 @@
+/**CFile****************************************************************
+
+  FileName    [abcLutmin.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Minimization of the number of LUTs.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcLutmin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/* 
+    Implememented here is the algorithm for minimal-LUT decomposition
+    described in the paper: T. Sasao et al. "On the number of LUTs 
+    to implement logic functions", To appear in Proc. IWLS'09.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Check if a LUT can absort a fanin.]
+
+  Description [The fanins are (c, d0, d1).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ObjCheckAbsorb( Abc_Obj_t * pObj, Abc_Obj_t * pPivot, int nLutSize, Vec_Ptr_t * vFanins )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    assert( Abc_ObjIsNode(pObj) && Abc_ObjIsNode(pPivot) );
+    // add fanins of the node
+    Vec_PtrClear( vFanins );
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        if ( pFanin != pPivot )
+            Vec_PtrPush( vFanins, pFanin );
+    // add fanins of the fanin
+    Abc_ObjForEachFanin( pPivot, pFanin, i )
+    {
+        Vec_PtrPushUnique( vFanins, pFanin );
+        if ( Vec_PtrSize(vFanins) > nLutSize )
+            return 0;
+    }
+    return 1;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Check how many times a LUT can absorb a fanin.]
+
+  Description [The fanins are (c, d0, d1).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCheckAbsorb( Abc_Ntk_t * pNtk, int nLutSize )
+{
+    Vec_Int_t * vCounts;
+    Vec_Ptr_t * vFanins;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k, Counter = 0, Counter2 = 0;
+    abctime clk = Abc_Clock();
+    vCounts = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
+    vFanins = Vec_PtrAlloc( 100 );
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    Abc_ObjForEachFanin( pObj, pFanin, k )
+        if ( Abc_ObjIsNode(pFanin) && Abc_ObjCheckAbsorb( pObj, pFanin, nLutSize, vFanins ) )
+        {
+            Vec_IntAddToEntry( vCounts, Abc_ObjId(pFanin), 1 );
+            Counter++;
+        }
+    Vec_PtrFree( vFanins );
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        if ( Vec_IntEntry(vCounts, Abc_ObjId(pObj)) == Abc_ObjFanoutNum(pObj) )
+        {
+//            printf( "%d ", Abc_ObjId(pObj) );
+            Counter2++;
+        }
+    printf( "Absorted = %6d. (%6.2f %%)   Fully = %6d. (%6.2f %%)  ", 
+        Counter,  100.0 * Counter  / Abc_NtkNodeNum(pNtk), 
+        Counter2, 100.0 * Counter2 / Abc_NtkNodeNum(pNtk) );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements 2:1 MUX using one 3-LUT.]
+
+  Description [The fanins are (c, d0, d1).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkBddMux21( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] )
+{
+    DdManager * dd = (DdManager *)pNtkNew->pManFunc;
+    Abc_Obj_t * pNode;
+    DdNode * bSpin, * bCof0, * bCof1;
+    pNode = Abc_NtkCreateNode( pNtkNew );
+    Abc_ObjAddFanin( pNode, pFanins[0] );
+    Abc_ObjAddFanin( pNode, pFanins[1] );
+    Abc_ObjAddFanin( pNode, pFanins[2] );
+    bSpin = Cudd_bddIthVar(dd, 0);
+    bCof0 = Cudd_bddIthVar(dd, 1); 
+    bCof1 = Cudd_bddIthVar(dd, 2); 
+    pNode->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 );  Cudd_Ref( (DdNode *)pNode->pData ); 
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements 4:1 MUX using one 6-LUT.]
+
+  Description [The fanins are (c0, c1, d00, d01, d10, d11).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkBddMux411( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] )
+{
+    DdManager * dd = (DdManager *)pNtkNew->pManFunc;
+    Abc_Obj_t * pNode;
+    DdNode * bSpin, * bCof0, * bCof1;
+    pNode = Abc_NtkCreateNode( pNtkNew );
+    Abc_ObjAddFanin( pNode, pFanins[0] );
+    Abc_ObjAddFanin( pNode, pFanins[1] );
+    Abc_ObjAddFanin( pNode, pFanins[2] );
+    Abc_ObjAddFanin( pNode, pFanins[3] );
+    Abc_ObjAddFanin( pNode, pFanins[4] );
+    Abc_ObjAddFanin( pNode, pFanins[5] );
+    bSpin = Cudd_bddIthVar(dd, 1);
+    bCof0 = Cudd_bddIte( dd, bSpin, Cudd_bddIthVar(dd, 3), Cudd_bddIthVar(dd, 2) ); Cudd_Ref( bCof0 );
+    bCof1 = Cudd_bddIte( dd, bSpin, Cudd_bddIthVar(dd, 5), Cudd_bddIthVar(dd, 4) ); Cudd_Ref( bCof1 );
+    bSpin = Cudd_bddIthVar(dd, 0);
+    pNode->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 );  Cudd_Ref( (DdNode *)pNode->pData ); 
+    Cudd_RecursiveDeref( dd, bCof0 );
+    Cudd_RecursiveDeref( dd, bCof1 );
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implementes 4:1 MUX using two 4-LUTs.]
+
+  Description [The fanins are (c0, c1, d00, d01, d10, d11).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkBddMux412( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] )
+{
+    DdManager * dd = (DdManager *)pNtkNew->pManFunc;
+    Abc_Obj_t * pNodeBot, * pNodeTop;
+    DdNode * bSpin, * bCof0, * bCof1;
+    // bottom node
+    pNodeBot = Abc_NtkCreateNode( pNtkNew );
+    Abc_ObjAddFanin( pNodeBot, pFanins[0] );
+    Abc_ObjAddFanin( pNodeBot, pFanins[1] );
+    Abc_ObjAddFanin( pNodeBot, pFanins[2] );
+    Abc_ObjAddFanin( pNodeBot, pFanins[3] );
+    bSpin = Cudd_bddIthVar(dd, 0);
+    bCof0 = Cudd_bddIte( dd, Cudd_bddIthVar(dd, 1), Cudd_bddIthVar(dd, 3), Cudd_bddIthVar(dd, 2) ); Cudd_Ref( bCof0 );
+    bCof1 = Cudd_bddIthVar(dd, 1);
+    pNodeBot->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 );  Cudd_Ref( (DdNode *)pNodeBot->pData ); 
+    Cudd_RecursiveDeref( dd, bCof0 );
+    // top node
+    pNodeTop = Abc_NtkCreateNode( pNtkNew );
+    Abc_ObjAddFanin( pNodeTop, pFanins[0] );
+    Abc_ObjAddFanin( pNodeTop, pNodeBot   );
+    Abc_ObjAddFanin( pNodeTop, pFanins[4] );
+    Abc_ObjAddFanin( pNodeTop, pFanins[5] );
+    bSpin = Cudd_bddIthVar(dd, 0);
+    bCof0 = Cudd_bddIthVar(dd, 1);
+    bCof1 = Cudd_bddIte( dd, Cudd_bddIthVar(dd, 1), Cudd_bddIthVar(dd, 3), Cudd_bddIthVar(dd, 2) ); Cudd_Ref( bCof1 );
+    pNodeTop->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 );  Cudd_Ref( (DdNode *)pNodeTop->pData ); 
+    Cudd_RecursiveDeref( dd, bCof1 );
+    return pNodeTop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implementes 4:1 MUX using two 4-LUTs.]
+
+  Description [The fanins are (c0, c1, d00, d01, d10, d11).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkBddMux412a( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] )
+{
+    DdManager * dd = (DdManager *)pNtkNew->pManFunc;
+    Abc_Obj_t * pNodeBot, * pNodeTop;
+    DdNode * bSpin, * bCof0, * bCof1;
+    // bottom node
+    pNodeBot = Abc_NtkCreateNode( pNtkNew );
+    Abc_ObjAddFanin( pNodeBot, pFanins[1] );
+    Abc_ObjAddFanin( pNodeBot, pFanins[2] );
+    Abc_ObjAddFanin( pNodeBot, pFanins[3] );
+    bSpin = Cudd_bddIthVar(dd, 0);
+    bCof0 = Cudd_bddIthVar(dd, 1);
+    bCof1 = Cudd_bddIthVar(dd, 2);
+    pNodeBot->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 );  Cudd_Ref( (DdNode *)pNodeBot->pData ); 
+    // top node
+    pNodeTop = Abc_NtkCreateNode( pNtkNew );
+    Abc_ObjAddFanin( pNodeTop, pFanins[0] );
+    Abc_ObjAddFanin( pNodeTop, pFanins[1] );
+    Abc_ObjAddFanin( pNodeTop, pNodeBot   );
+    Abc_ObjAddFanin( pNodeTop, pFanins[4] );
+    Abc_ObjAddFanin( pNodeTop, pFanins[5] );
+    bSpin = Cudd_bddIthVar(dd, 0);
+    bCof0 = Cudd_bddIthVar(dd, 2);
+    bCof1 = Cudd_bddIte( dd, Cudd_bddIthVar(dd, 1), Cudd_bddIthVar(dd, 4), Cudd_bddIthVar(dd, 3) ); Cudd_Ref( bCof1 );
+    pNodeTop->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 );  Cudd_Ref( (DdNode *)pNodeTop->pData ); 
+    Cudd_RecursiveDeref( dd, bCof1 );
+    return pNodeTop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements 4:1 MUX using three 2:1 MUXes.]
+
+  Description [The fanins are (c0, c1, d00, d01, d10, d11).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkBddMux413( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] )
+{
+    Abc_Obj_t * pNodesBot[3], * pNodesTop[3];
+    // left bottom
+    pNodesBot[0] = pFanins[1];
+    pNodesBot[1] = pFanins[2];
+    pNodesBot[2] = pFanins[3];
+    pNodesTop[1] = Abc_NtkBddMux21( pNtkNew, pNodesBot );
+    // right bottom
+    pNodesBot[0] = pFanins[1];
+    pNodesBot[1] = pFanins[4];
+    pNodesBot[2] = pFanins[5];
+    pNodesTop[2] = Abc_NtkBddMux21( pNtkNew, pNodesBot );
+    // top node
+    pNodesTop[0] = pFanins[0];
+    return Abc_NtkBddMux21( pNtkNew, pNodesTop );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds unique cofactors of the function on the given level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NtkBddCofactors_rec( DdManager * dd, DdNode * bNode, int iCof, int iLevel, int nLevels )
+{
+    DdNode * bNode0, * bNode1;
+    if ( Cudd_IsConstant(bNode) || iLevel == nLevels )
+        return bNode;
+    if ( Cudd_ReadPerm( dd, Cudd_NodeReadIndex(bNode) ) > iLevel )
+    {
+        bNode0 = bNode;
+        bNode1 = bNode;
+    }
+    else if ( Cudd_IsComplement(bNode) )
+    {
+        bNode0 = Cudd_Not(cuddE(Cudd_Regular(bNode)));
+        bNode1 = Cudd_Not(cuddT(Cudd_Regular(bNode)));
+    }
+    else
+    {
+        bNode0 = cuddE(bNode);
+        bNode1 = cuddT(bNode);
+    }
+    if ( (iCof >> (nLevels-1-iLevel)) & 1 )
+        return Abc_NtkBddCofactors_rec( dd, bNode1, iCof, iLevel + 1, nLevels );
+    return Abc_NtkBddCofactors_rec( dd, bNode0, iCof, iLevel + 1, nLevels );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds unique cofactors of the function on the given level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkBddCofactors( DdManager * dd, DdNode * bNode, int Level )
+{
+    Vec_Ptr_t * vCofs;
+    int i, nCofs = (1<<Level);
+    assert( Level > 0 && Level < 10 );
+    vCofs = Vec_PtrAlloc( 8 );
+    for ( i = 0; i < nCofs; i++ )
+        Vec_PtrPush( vCofs, Abc_NtkBddCofactors_rec( dd, bNode, i, 0, Level ) );
+    return vCofs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two integers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Vec_PtrSortCompare( void ** pp1, void ** pp2 )
+{
+    if ( *pp1 < *pp2 )
+        return -1;
+    if ( *pp1 > *pp2 )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the node to MUXes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkCreateCofLut( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bCof, Abc_Obj_t * pNode, int Level )
+{
+    int fVerbose = 0;
+    DdNode * bFuncNew;
+    Abc_Obj_t * pNodeNew;
+    int i;
+    assert( Abc_ObjFaninNum(pNode) > Level );
+    // create a new node
+    pNodeNew = Abc_NtkCreateNode( pNtkNew );
+    // add the fanins in the order, in which they appear in the reordered manager
+    for ( i = Level; i < Abc_ObjFaninNum(pNode); i++ )
+        Abc_ObjAddFanin( pNodeNew, Abc_ObjFanin(pNode, i)->pCopy );
+if ( fVerbose )
+{
+Extra_bddPrint( dd, bCof );
+printf( "\n" );
+printf( "\n" );
+}
+    // transfer the function
+    bFuncNew = Extra_bddMove( dd, bCof, -Level );  Cudd_Ref( bFuncNew );
+if ( fVerbose )
+{
+Extra_bddPrint( dd, bFuncNew );
+printf( "\n" );
+printf( "\n" );
+}
+    pNodeNew->pData = Extra_TransferLevelByLevel( dd, (DdManager *)pNtkNew->pManFunc, bFuncNew );  Cudd_Ref( (DdNode *)pNodeNew->pData );
+//Extra_bddPrint( pNtkNew->pManFunc, pNodeNew->pData );
+//printf( "\n" );
+//printf( "\n" );
+    Cudd_RecursiveDeref( dd, bFuncNew );
+    return pNodeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one step of Ashenhurst-Curtis decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkBddCurtis( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vCofs, Vec_Ptr_t * vUniq )
+{
+    DdManager * ddOld = (DdManager *)pNode->pNtk->pManFunc;
+    DdManager * ddNew = (DdManager *)pNtkNew->pManFunc;
+    DdNode * bCof, * bUniq, * bMint, * bTemp, * bFunc, * bBits[10], ** pbCodeVars;
+    Abc_Obj_t * pNodeNew = NULL, * pNodeBS[10];
+    int nLutSize = Abc_Base2Log( Vec_PtrSize(vCofs) );
+    int nBits    = Abc_Base2Log( Vec_PtrSize(vUniq) );
+    int b, c, u, i;
+    assert( nBits + 2 <= nLutSize );
+    assert( nLutSize < Abc_ObjFaninNum(pNode) );
+    // start BDDs for the decompoosed blocks
+    for ( b = 0; b < nBits; b++ )
+        bBits[b] = Cudd_ReadLogicZero(ddNew), Cudd_Ref( bBits[b] );
+    // add each bound set minterm to one of the blccks
+    Vec_PtrForEachEntry( DdNode *, vCofs, bCof, c )
+    {
+        Vec_PtrForEachEntry( DdNode *, vUniq, bUniq, u )
+            if ( bUniq == bCof )
+                break;
+        assert( u < Vec_PtrSize(vUniq) );
+        for ( b = 0; b < nBits; b++ )
+        {
+            if ( ((u >> b) & 1) == 0 )
+                continue;
+            bMint = Extra_bddBitsToCube( ddNew, c, nLutSize, ddNew->vars, 1 );  Cudd_Ref( bMint );
+            bBits[b] = Cudd_bddOr( ddNew, bTemp = bBits[b], bMint );  Cudd_Ref( bBits[b] );
+            Cudd_RecursiveDeref( ddNew, bTemp );
+            Cudd_RecursiveDeref( ddNew, bMint );
+        }
+    }
+    // create bound set nodes
+    for ( b = 0; b < nBits; b++ )
+    {
+        pNodeBS[b] = Abc_NtkCreateNode( pNtkNew );
+        for ( i = 0; i < nLutSize; i++ )
+            Abc_ObjAddFanin( pNodeBS[b], Abc_ObjFanin(pNode, i)->pCopy );
+        pNodeBS[b]->pData = bBits[b]; // takes ref
+    }
+    // create composition node
+    pNodeNew = Abc_NtkCreateNode( pNtkNew );
+    // add free set variables first
+    for ( i = nLutSize; i < Abc_ObjFaninNum(pNode); i++ )
+        Abc_ObjAddFanin( pNodeNew, Abc_ObjFanin(pNode, i)->pCopy );
+    // add code bit variables next
+    for ( b = 0; b < nBits; b++ )
+        Abc_ObjAddFanin( pNodeNew, pNodeBS[b] );
+    // derive function of the composition node
+    bFunc = Cudd_ReadLogicZero(ddNew); Cudd_Ref( bFunc );
+    pbCodeVars = ddNew->vars + Abc_ObjFaninNum(pNode) - nLutSize;
+    Vec_PtrForEachEntry( DdNode *, vUniq, bUniq, u )
+    {
+        bUniq = Extra_bddMove( ddOld, bUniq, -nLutSize );                   Cudd_Ref( bUniq );
+        bUniq = Extra_TransferLevelByLevel( ddOld, ddNew, bTemp = bUniq );  Cudd_Ref( bUniq );
+        Cudd_RecursiveDeref( ddOld, bTemp );
+
+        bMint = Extra_bddBitsToCube( ddNew, u, nBits, pbCodeVars, 0 );  Cudd_Ref( bMint );
+        bMint = Cudd_bddAnd( ddNew, bTemp = bMint, bUniq );  Cudd_Ref( bMint );
+        Cudd_RecursiveDeref( ddNew, bTemp );
+        Cudd_RecursiveDeref( ddNew, bUniq );
+
+        bFunc = Cudd_bddOr( ddNew, bTemp = bFunc, bMint );  Cudd_Ref( bFunc );
+        Cudd_RecursiveDeref( ddNew, bTemp );
+        Cudd_RecursiveDeref( ddNew, bMint );
+    }
+    pNodeNew->pData = bFunc; // takes ref
+    return pNodeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tries to decompose using cofactoring into two LUTs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkBddFindCofactor( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int nLutSize )
+{
+    Abc_Obj_t * pNodeBot, * pNodeTop;
+    DdManager * ddOld = (DdManager *)pNode->pNtk->pManFunc;
+    DdManager * ddNew = (DdManager *)pNtkNew->pManFunc;
+    DdNode * bCof0 = NULL, * bCof1 = NULL, * bSupp, * bTemp, * bVar;
+    DdNode * bCof0n, * bCof1n;
+    int i, iCof, iFreeVar, fCof1Smaller = -1;
+    assert( Abc_ObjFaninNum(pNode) == nLutSize + 1 );
+    for ( iCof = 0; iCof < Abc_ObjFaninNum(pNode); iCof++ )
+    {
+        bVar  = Cudd_bddIthVar( ddOld, iCof );
+        bCof0 = Cudd_Cofactor( ddOld, (DdNode *)pNode->pData, Cudd_Not(bVar) );  Cudd_Ref( bCof0 );
+        bCof1 = Cudd_Cofactor( ddOld, (DdNode *)pNode->pData, bVar  );           Cudd_Ref( bCof1 );
+        if ( Cudd_SupportSize( ddOld, bCof0 ) <= nLutSize - 2 )
+        {
+            fCof1Smaller = 0;
+            break;
+        }
+        if ( Cudd_SupportSize( ddOld, bCof1 ) <= nLutSize - 2 )
+        {
+            fCof1Smaller = 1;
+            break;
+        }
+        Cudd_RecursiveDeref( ddOld, bCof0 );
+        Cudd_RecursiveDeref( ddOld, bCof1 );
+    }
+    if ( iCof == Abc_ObjFaninNum(pNode) )
+        return NULL;
+    // find unused variable
+    bSupp = Cudd_Support( ddOld, fCof1Smaller? bCof1 : bCof0 );   Cudd_Ref( bSupp );
+    iFreeVar = -1;
+    for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
+    {
+        assert( i == Cudd_ReadPerm(ddOld, i) );
+        if ( i == iCof )
+            continue;
+        for ( bTemp = bSupp; !Cudd_IsConstant(bTemp); bTemp = cuddT(bTemp) )
+            if ( i == (int)Cudd_NodeReadIndex(bTemp) )
+                break;
+        if ( Cudd_IsConstant(bTemp) )
+        {
+            iFreeVar = i;
+            break;
+        }
+    }
+    assert( iFreeVar != iCof && iFreeVar < Abc_ObjFaninNum(pNode) );
+    Cudd_RecursiveDeref( ddOld, bSupp );
+    // transfer the cofactors
+    bCof0n = Extra_TransferLevelByLevel( ddOld, ddNew, bCof0 ); Cudd_Ref( bCof0n );
+    bCof1n = Extra_TransferLevelByLevel( ddOld, ddNew, bCof1 ); Cudd_Ref( bCof1n );
+    Cudd_RecursiveDeref( ddOld, bCof0 );
+    Cudd_RecursiveDeref( ddOld, bCof1 );
+    // create bottom node
+    pNodeBot = Abc_NtkCreateNode( pNtkNew );
+    for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
+        Abc_ObjAddFanin( pNodeBot, Abc_ObjFanin(pNode, i)->pCopy );
+    pNodeBot->pData = fCof1Smaller? bCof0n : bCof1n;
+    // create top node
+    pNodeTop = Abc_NtkCreateNode( pNtkNew );
+    for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
+        if ( i == iFreeVar )           
+            Abc_ObjAddFanin( pNodeTop, pNodeBot );
+        else
+            Abc_ObjAddFanin( pNodeTop, Abc_ObjFanin(pNode, i)->pCopy );
+    // derive the new function
+    pNodeTop->pData = Cudd_bddIte( ddNew, 
+        Cudd_bddIthVar(ddNew, iCof), 
+        fCof1Smaller? bCof1n : Cudd_bddIthVar(ddNew, iFreeVar), 
+        fCof1Smaller? Cudd_bddIthVar(ddNew, iFreeVar) : bCof0n );
+    Cudd_Ref( (DdNode *)pNodeTop->pData );
+    Cudd_RecursiveDeref( ddNew, fCof1Smaller? bCof1n : bCof0n );
+    return pNodeTop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Decompose the function once.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkBddDecompose( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int nLutSize, int fVerbose )
+{
+    Vec_Ptr_t * vCofs, * vUniq;
+    DdManager * dd = (DdManager *)pNode->pNtk->pManFunc;
+    DdNode * bCof;
+    Abc_Obj_t * pNodeNew = NULL;
+    Abc_Obj_t * pCofs[20];
+    int i;
+    assert( Abc_ObjFaninNum(pNode) > nLutSize );
+    // try to decompose with two LUTs (the best case for Supp = LutSize + 1)
+    if ( Abc_ObjFaninNum(pNode) == nLutSize + 1 )
+    {
+
+        pNodeNew = Abc_NtkBddFindCofactor( pNtkNew, pNode, nLutSize );
+        if ( pNodeNew != NULL )
+        {
+            if ( fVerbose )
+            printf( "Decomposing %d-input node %d using MUX.\n",
+                Abc_ObjFaninNum(pNode), Abc_ObjId(pNode) );
+            return pNodeNew;
+        }
+
+    }
+    // cofactor w.r.t. the bound set variables
+    vCofs = Abc_NtkBddCofactors( dd, (DdNode *)pNode->pData, nLutSize );
+    vUniq = Vec_PtrDup( vCofs );
+    Vec_PtrUniqify( vUniq, (int (*)())Vec_PtrSortCompare );
+    // only perform decomposition with it is support reduring with two less vars
+    if( Vec_PtrSize(vUniq) > (1 << (nLutSize-2)) )
+    {
+        Vec_PtrFree( vCofs );
+        vCofs = Abc_NtkBddCofactors( dd, (DdNode *)pNode->pData, 2 );
+        if ( fVerbose )
+        printf( "Decomposing %d-input node %d using cofactoring with %d cofactors.\n",
+            Abc_ObjFaninNum(pNode), Abc_ObjId(pNode), Vec_PtrSize(vCofs) );
+        // implement the cofactors
+        pCofs[0] = Abc_ObjFanin(pNode, 0)->pCopy;
+        pCofs[1] = Abc_ObjFanin(pNode, 1)->pCopy;
+        Vec_PtrForEachEntry( DdNode *, vCofs, bCof, i )
+            pCofs[2+i] = Abc_NtkCreateCofLut( pNtkNew, dd, bCof, pNode, 2 );
+        if ( nLutSize == 4 )
+            pNodeNew = Abc_NtkBddMux412( pNtkNew, pCofs );
+        else if ( nLutSize == 5 )
+            pNodeNew = Abc_NtkBddMux412a( pNtkNew, pCofs );
+        else if ( nLutSize == 6 )
+            pNodeNew = Abc_NtkBddMux411( pNtkNew, pCofs );
+        else  assert( 0 );
+    }
+    // alternative decompose using MUX-decomposition
+    else
+    {
+        if ( fVerbose )
+        printf( "Decomposing %d-input node %d using Curtis with %d unique columns.\n",
+            Abc_ObjFaninNum(pNode), Abc_ObjId(pNode), Vec_PtrSize(vUniq) );
+        pNodeNew = Abc_NtkBddCurtis( pNtkNew, pNode, vCofs, vUniq );
+    }
+    Vec_PtrFree( vCofs );
+    Vec_PtrFree( vUniq );
+    return pNodeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkLutminConstruct( Abc_Ntk_t * pNtkClp, Abc_Ntk_t * pNtkDec, int nLutSize, int fVerbose )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNode, * pFanin;
+    int i, k;
+    vNodes = Abc_NtkDfs( pNtkClp, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( Abc_ObjFaninNum(pNode) <= nLutSize )
+        {
+            pNode->pCopy = Abc_NtkDupObj( pNtkDec, pNode, 0 );
+            Abc_ObjForEachFanin( pNode, pFanin, k )
+                Abc_ObjAddFanin( pNode->pCopy, pFanin->pCopy );
+        }
+        else
+            pNode->pCopy = Abc_NtkBddDecompose( pNtkDec, pNode, nLutSize, fVerbose );
+    }
+    Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkLutminInt( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose )
+{
+    extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose );
+    Abc_Ntk_t * pNtkDec;
+    // minimize BDDs
+//    Abc_NtkBddReorder( pNtk, fVerbose );
+    Abc_NtkBddReorder( pNtk, 0 );
+    // decompose one output at a time
+    pNtkDec = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
+    // make sure the new manager has enough inputs
+    Cudd_bddIthVar( (DdManager *)pNtkDec->pManFunc, Abc_NtkGetFaninMax(pNtk) );
+    // put the results into the new network (save new CO drivers in old CO drivers)
+    Abc_NtkLutminConstruct( pNtk, pNtkDec, nLutSize, fVerbose );
+    // finalize the new network
+    Abc_NtkFinalize( pNtk, pNtkDec );
+    // make the network minimum base
+    Abc_NtkMinimumBase( pNtkDec );
+    return pNtkDec;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs minimum-LUT decomposition of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtkInit, int nLutSize, int fVerbose )
+{
+    extern int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose );
+    Abc_Ntk_t * pNtkNew, * pTemp;
+    int i;
+    if ( nLutSize < 4 )
+    {
+        printf( "The LUT count (%d) should be at least 4.\n", nLutSize );
+        return NULL;
+    }
+    if ( nLutSize > 6 )
+    {
+        printf( "The LUT count (%d) should not exceed 6.\n", nLutSize );
+        return NULL;
+    }
+    // create internal representation
+    if ( Abc_NtkIsStrash(pNtkInit) )
+        pNtkNew = Abc_NtkDup( pNtkInit );
+    else
+        pNtkNew = Abc_NtkStrash( pNtkInit, 0, 1, 0 );
+    // collapse the network 
+    pNtkNew = Abc_NtkCollapse( pTemp = pNtkNew, 10000, 0, 1, 0 );
+    Abc_NtkDelete( pTemp );
+    if ( pNtkNew == NULL )
+        return NULL;
+    // convert it to BDD
+    if ( !Abc_NtkIsBddLogic(pNtkNew) )
+        Abc_NtkToBdd( pNtkNew );
+    // iterate decomposition
+    for ( i = 0; Abc_NtkGetFaninMax(pNtkNew) > nLutSize; i++ )
+    {
+        if ( fVerbose )
+            printf( "*** Iteration %d:\n", i+1 );
+        if ( fVerbose )
+            printf( "Decomposing network with %d nodes and %d max fanin count for K = %d.\n", 
+                Abc_NtkNodeNum(pNtkNew), Abc_NtkGetFaninMax(pNtkNew), nLutSize );
+        pNtkNew = Abc_NtkLutminInt( pTemp = pNtkNew, nLutSize, fVerbose );
+        Abc_NtkDelete( pTemp );
+    }
+    // fix the problem with complemented and duplicated CO edges
+    Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+    // merge functionally equivalent nodes
+    Abc_NtkFraigSweep( pNtkNew, 1, 0, 0, 0 );
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkLutmin: The network check has failed.\n" );
+        return 0;
+    }
+    return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcMap.c b/abc-build/src/base/abci/abcMap.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcMap.c
@@ -0,0 +1,966 @@
+/**CFile****************************************************************
+
+  FileName    [abcMap.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Interface with the SC mapping package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/main.h"
+#include "map/mio/mio.h"
+#include "map/mapper/mapper.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Map_Man_t *  Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, float * pSwitching, int fVerbose );
+static Abc_Ntk_t *  Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk );
+static Abc_Obj_t *  Abc_NodeFromMap_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase );
+static Abc_Obj_t *  Abc_NodeFromMapPhase_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase );
+
+static Abc_Ntk_t *  Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk );
+static void         Abc_NodeSuperChoice( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode );
+static void         Abc_NodeFromMapCutPhase( Abc_Ntk_t * pNtkNew, Map_Cut_t * pCut, int fPhase );
+static Abc_Obj_t *  Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis );
+
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Interface with the mapping package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, double AreaMulti, double DelayMulti, float LogFan, float Slew, float Gain, int nGatesMin, int fRecovery, int fSwitching, int fVerbose )
+{
+    static int fUseMulti = 0;
+    int fShowSwitching = 1;
+    Abc_Ntk_t * pNtkNew;
+    Map_Man_t * pMan;
+    Vec_Int_t * vSwitching = NULL;
+    float * pSwitching = NULL;
+    abctime clk, clkTotal = Abc_Clock();
+    Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    // derive library from SCL
+    // if the library is created here, it will be deleted when pSuperLib is deleted in Map_SuperLibFree()
+    if ( Abc_FrameReadLibScl() && Abc_SclHasDelayInfo( Abc_FrameReadLibScl() ) )
+    {
+        pLib = Abc_SclDeriveGenlib( Abc_FrameReadLibScl(), Slew, Gain, nGatesMin, fVerbose );
+        if ( Abc_FrameReadLibGen() )
+            Mio_LibraryTransferDelays( (Mio_Library_t *)Abc_FrameReadLibGen(), pLib );
+        // remove supergate library
+        Map_SuperLibFree( (Map_SuperLib_t *)Abc_FrameReadLibSuper() );
+        Abc_FrameSetLibSuper( NULL );
+    }
+    // quit if there is no library
+    if ( pLib == NULL )
+    {
+        printf( "The current library is not available.\n" );
+        return 0;
+    }
+    if ( AreaMulti != 0.0 )
+        fUseMulti = 1, printf( "The cell areas are multiplied by the factor: <num_fanins> ^ (%.2f).\n", AreaMulti );
+    if ( DelayMulti != 0.0 )
+        fUseMulti = 1, printf( "The cell delays are multiplied by the factor: <num_fanins> ^ (%.2f).\n", DelayMulti );
+
+    // penalize large gates by increasing their area
+    if ( AreaMulti != 0.0 )
+        Mio_LibraryMultiArea( pLib, AreaMulti );
+    if ( DelayMulti != 0.0 )
+        Mio_LibraryMultiDelay( pLib, DelayMulti );
+
+    // derive the supergate library
+    if ( fUseMulti || Abc_FrameReadLibSuper() == NULL )
+    {
+        if ( fVerbose )
+            printf( "Converting \"%s\" into supergate library \"%s\".\n", 
+                Mio_LibraryReadName(pLib), Extra_FileNameGenericAppend(Mio_LibraryReadName(pLib), ".super") );
+        // compute supergate library to be used for mapping
+        Map_SuperLibDeriveFromGenlib( pLib, fVerbose );
+    }
+
+    // return the library to normal
+    if ( AreaMulti != 0.0 )
+        Mio_LibraryMultiArea( (Mio_Library_t *)Abc_FrameReadLibGen(), -AreaMulti );
+    if ( DelayMulti != 0.0 )
+        Mio_LibraryMultiDelay( (Mio_Library_t *)Abc_FrameReadLibGen(), -DelayMulti );
+
+    // print a warning about choice nodes
+    if ( fVerbose && Abc_NtkGetChoiceNum( pNtk ) )
+        printf( "Performing mapping with choices.\n" );
+
+    // compute switching activity
+    fShowSwitching |= fSwitching;
+    if ( fShowSwitching )
+    {
+        extern Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns );
+        vSwitching = Sim_NtkComputeSwitching( pNtk, 4096 );
+        pSwitching = (float *)vSwitching->pArray;
+    }
+
+    // perform the mapping
+    pMan = Abc_NtkToMap( pNtk, DelayTarget, fRecovery, pSwitching, fVerbose );
+    if ( pSwitching ) Vec_IntFree( vSwitching );
+    if ( pMan == NULL )
+        return NULL;
+clk = Abc_Clock();
+    Map_ManSetSwitching( pMan, fSwitching );
+    if ( LogFan != 0 )
+        Map_ManCreateNodeDelays( pMan, LogFan );
+    if ( !Map_Mapping( pMan ) )
+    {
+        Map_ManFree( pMan );
+        return NULL;
+    }
+//    Map_ManPrintStatsToFile( pNtk->pSpec, Map_ManReadAreaFinal(pMan), Map_ManReadRequiredGlo(pMan), Abc_Clock()-clk );
+
+    // reconstruct the network after mapping
+    pNtkNew = Abc_NtkFromMap( pMan, pNtk );
+    Map_ManFree( pMan );
+    if ( pNtkNew == NULL )
+        return NULL;
+
+    if ( pNtk->pExdc )
+        pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+if ( fVerbose )
+{
+ABC_PRT( "Total runtime", Abc_Clock() - clkTotal );
+}
+
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkMap: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Load the network into manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Time_t * Abc_NtkMapCopyCiArrival( Abc_Ntk_t * pNtk, Abc_Time_t * ppTimes )
+{
+    Map_Time_t * p;
+    int i;
+    p = ABC_CALLOC( Map_Time_t, Abc_NtkCiNum(pNtk) );
+    for ( i = 0; i < Abc_NtkCiNum(pNtk); i++ )
+    {
+        p->Fall = ppTimes[i].Fall;
+        p->Rise = ppTimes[i].Rise;
+        p->Worst = Abc_MaxFloat( p->Fall, p->Rise );
+    }
+    ABC_FREE( ppTimes );
+    return p;
+}
+Map_Time_t * Abc_NtkMapCopyCoRequired( Abc_Ntk_t * pNtk, Abc_Time_t * ppTimes )
+{
+    Map_Time_t * p;
+    int i;
+    p = ABC_CALLOC( Map_Time_t, Abc_NtkCoNum(pNtk) );
+    for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ )
+    {
+        p->Fall = ppTimes[i].Fall;
+        p->Rise = ppTimes[i].Rise;
+        p->Worst = Abc_MaxFloat( p->Fall, p->Rise );
+    }
+    ABC_FREE( ppTimes );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Load the network into manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, float * pSwitching, int fVerbose )
+{
+    Map_Man_t * pMan;
+    Map_Node_t * pNodeMap;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNode, * pFanin, * pPrev;
+    int i;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    // start the mapping manager and set its parameters
+    pMan = Map_ManCreate( Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) - pNtk->nBarBufs, Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk) - pNtk->nBarBufs, fVerbose );
+    if ( pMan == NULL )
+        return NULL;
+    Map_ManSetAreaRecovery( pMan, fRecovery );
+    Map_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) );
+    Map_ManSetDelayTarget( pMan, (float)DelayTarget );
+    Map_ManSetInputArrivals( pMan, Abc_NtkMapCopyCiArrival(pNtk, Abc_NtkGetCiArrivalTimes(pNtk)) );
+    Map_ManSetOutputRequireds( pMan, Abc_NtkMapCopyCoRequired(pNtk, Abc_NtkGetCoRequiredTimes(pNtk)) );
+
+    // create PIs and remember them in the old nodes
+    Abc_NtkCleanCopy( pNtk );
+    Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Map_ManReadConst1(pMan);
+    Abc_NtkForEachCi( pNtk, pNode, i )
+    {
+        if ( i == Abc_NtkCiNum(pNtk) - pNtk->nBarBufs )
+            break;
+        pNodeMap = Map_ManReadInputs(pMan)[i];
+        pNode->pCopy = (Abc_Obj_t *)pNodeMap;
+        if ( pSwitching )
+            Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] );
+    }
+
+    // load the AIG into the mapper
+    vNodes = Abc_AigDfsMap( pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( Abc_ObjIsLatch(pNode) )
+        {
+            pFanin = Abc_ObjFanin0(pNode);
+            pNodeMap = Map_NodeBuf( pMan, Map_NotCond( Abc_ObjFanin0(pFanin)->pCopy, (int)Abc_ObjFaninC0(pFanin) ) );
+            Abc_ObjFanout0(pNode)->pCopy = (Abc_Obj_t *)pNodeMap;
+            continue;
+        }
+        assert( Abc_ObjIsNode(pNode) );
+        // add the node to the mapper
+        pNodeMap = Map_NodeAnd( pMan, 
+            Map_NotCond( Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) ),
+            Map_NotCond( Abc_ObjFanin1(pNode)->pCopy, (int)Abc_ObjFaninC1(pNode) ) );
+        assert( pNode->pCopy == NULL );
+        // remember the node
+        pNode->pCopy = (Abc_Obj_t *)pNodeMap;
+        if ( pSwitching )
+            Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] );
+        // set up the choice node
+        if ( Abc_AigNodeIsChoice( pNode ) )
+            for ( pPrev = pNode, pFanin = (Abc_Obj_t *)pNode->pData; pFanin; pPrev = pFanin, pFanin = (Abc_Obj_t *)pFanin->pData )
+            {
+                Map_NodeSetNextE( (Map_Node_t *)pPrev->pCopy, (Map_Node_t *)pFanin->pCopy );
+                Map_NodeSetRepr( (Map_Node_t *)pFanin->pCopy, (Map_Node_t *)pNode->pCopy );
+            }
+    }
+    assert( Map_ManReadBufNum(pMan) == pNtk->nBarBufs );
+    Vec_PtrFree( vNodes );
+
+    // set the primary outputs in the required phase
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        if ( i == Abc_NtkCoNum(pNtk) - pNtk->nBarBufs )
+            break;
+        Map_ManReadOutputs(pMan)[i] = Map_NotCond( (Map_Node_t *)Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) );
+    }
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the mapped network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFromMapSuper_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis )
+{
+    Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
+    Mio_Gate_t * pRoot;
+    Map_Super_t ** ppFanins;
+    Abc_Obj_t * pNodeNew, * pNodeFanin;
+    int nFanins, Number, i;
+
+    // get the parameters of the supergate
+    pRoot = Map_SuperReadRoot(pSuper);
+    if ( pRoot == NULL )
+    {
+        Number = Map_SuperReadNum(pSuper);
+        if ( Number < nNodePis )  
+        {
+            return pNodePis[Number];
+        }
+        else
+        {  
+//            assert( 0 );
+            /* It might happen that a super gate with 5 inputs is constructed that
+             * actually depends only on the first four variables; i.e the fifth is a
+             * don't care -- in that case we connect constant node for the fifth
+             * (since the cut only has 4 variables). An interesting question is what
+             * if the first variable (and not the fifth one is the redundant one;
+             * can that happen?) */
+            return Abc_NtkCreateNodeConst0(pNtkNew);
+        }
+    }
+    pRoot = Mio_LibraryReadGateByName( pLib, Mio_GateReadName(pRoot), NULL );
+
+    // get information about the fanins of the supergate
+    nFanins  = Map_SuperReadFaninNum( pSuper );
+    ppFanins = Map_SuperReadFanins( pSuper );
+    // create a new node with these fanins
+    pNodeNew = Abc_NtkCreateNode( pNtkNew );
+    for ( i = 0; i < nFanins; i++ )
+    {
+        pNodeFanin = Abc_NodeFromMapSuper_rec( pNtkNew, pNodeMap, ppFanins[i], pNodePis, nNodePis );
+        Abc_ObjAddFanin( pNodeNew, pNodeFanin );
+    }
+    pNodeNew->pData = pRoot;
+    return pNodeNew;
+}
+Abc_Obj_t * Abc_NodeFromMapPhase_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase )
+{
+    Abc_Obj_t * pNodePIs[10];
+    Abc_Obj_t * pNodeNew;
+    Map_Node_t ** ppLeaves;
+    Map_Cut_t * pCutBest;
+    Map_Super_t * pSuperBest;
+    unsigned uPhaseBest;
+    int i, fInvPin, nLeaves;
+
+    // make sure the node can be implemented in this phase
+    assert( Map_NodeReadCutBest(pNodeMap, fPhase) != NULL || Map_NodeIsConst(pNodeMap) );
+    // check if the phase is already implemented
+    pNodeNew = (Abc_Obj_t *)Map_NodeReadData( pNodeMap, fPhase );
+    if ( pNodeNew )
+        return pNodeNew;
+
+    // get the information about the best cut 
+    pCutBest   = Map_NodeReadCutBest( pNodeMap, fPhase );
+    pSuperBest = Map_CutReadSuperBest( pCutBest, fPhase );
+    uPhaseBest = Map_CutReadPhaseBest( pCutBest, fPhase );
+    nLeaves    = Map_CutReadLeavesNum( pCutBest );
+    ppLeaves   = Map_CutReadLeaves( pCutBest );
+
+    // collect the PI nodes
+    for ( i = 0; i < nLeaves; i++ )
+    {
+        fInvPin = ((uPhaseBest & (1 << i)) > 0);
+        pNodePIs[i] = Abc_NodeFromMap_rec( pNtkNew, ppLeaves[i], !fInvPin );
+        assert( pNodePIs[i] != NULL );
+    }
+
+    // implement the supergate
+    pNodeNew = Abc_NodeFromMapSuper_rec( pNtkNew, pNodeMap, pSuperBest, pNodePIs, nLeaves );
+    Map_NodeSetData( pNodeMap, fPhase, (char *)pNodeNew );
+    return pNodeNew;
+}
+Abc_Obj_t * Abc_NodeFromMap_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase )
+{
+    Abc_Obj_t * pNodeNew, * pNodeInv;
+
+    // check the case of constant node
+    if ( Map_NodeIsConst(pNodeMap) )
+    {
+        pNodeNew = fPhase? Abc_NtkCreateNodeConst1(pNtkNew) : Abc_NtkCreateNodeConst0(pNtkNew);
+        if ( pNodeNew->pData == NULL )
+            printf( "Error creating mapped network: Library does not have a constant %d gate.\n", fPhase );
+        return pNodeNew;
+    }
+
+    // check if the phase is already implemented
+    pNodeNew = (Abc_Obj_t *)Map_NodeReadData( pNodeMap, fPhase );
+    if ( pNodeNew )
+        return pNodeNew;
+
+    // implement the node if the best cut is assigned
+    if ( Map_NodeReadCutBest(pNodeMap, fPhase) != NULL )
+        return Abc_NodeFromMapPhase_rec( pNtkNew, pNodeMap, fPhase );
+
+    // if the cut is not assigned, implement the node
+    assert( Map_NodeReadCutBest(pNodeMap, !fPhase) != NULL || Map_NodeIsConst(pNodeMap) );
+    pNodeNew = Abc_NodeFromMapPhase_rec( pNtkNew, pNodeMap, !fPhase );
+
+    // add the inverter
+    pNodeInv = Abc_NtkCreateNode( pNtkNew );
+    Abc_ObjAddFanin( pNodeInv, pNodeNew );
+    pNodeInv->pData = Mio_LibraryReadInv((Mio_Library_t *)Abc_FrameReadLibGen());
+
+    // set the inverter
+    Map_NodeSetData( pNodeMap, fPhase, (char *)pNodeInv );
+    return pNodeInv;
+}
+Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew;
+    Map_Node_t * pNodeMap;
+    Abc_Obj_t * pNode, * pNodeNew;
+    int i, nDupGates;
+    assert( Map_ManReadBufNum(pMan) == pNtk->nBarBufs );
+    // create the new network
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_MAP );
+    // make the mapper point to the new network
+    Map_ManCleanData( pMan );
+    Abc_NtkForEachCi( pNtk, pNode, i )
+    {
+        if ( i >= Abc_NtkCiNum(pNtk) - pNtk->nBarBufs )
+            break;
+        Map_NodeSetData( Map_ManReadInputs(pMan)[i], 1, (char *)pNode->pCopy );
+    }
+    Abc_NtkForEachCi( pNtk, pNode, i )
+    {
+        if ( i < Abc_NtkCiNum(pNtk) - pNtk->nBarBufs )
+            continue;
+        Map_NodeSetData( Map_ManReadBufs(pMan)[i - (Abc_NtkCiNum(pNtk) - pNtk->nBarBufs)], 1, (char *)pNode->pCopy );
+    }
+    // assign the mapping of the required phase to the POs
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        if ( i < Abc_NtkCoNum(pNtk) - pNtk->nBarBufs )
+            continue;
+        pNodeMap = Map_ManReadBufDriver( pMan, i - (Abc_NtkCoNum(pNtk) - pNtk->nBarBufs) );
+        pNodeNew = Abc_NodeFromMap_rec( pNtkNew, Map_Regular(pNodeMap), !Map_IsComplement(pNodeMap) );
+        assert( !Abc_ObjIsComplement(pNodeNew) );
+        Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+    }
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        if ( i >= Abc_NtkCoNum(pNtk) - pNtk->nBarBufs )
+            break;
+        pNodeMap = Map_ManReadOutputs(pMan)[i];
+        pNodeNew = Abc_NodeFromMap_rec( pNtkNew, Map_Regular(pNodeMap), !Map_IsComplement(pNodeMap) );
+        assert( !Abc_ObjIsComplement(pNodeNew) );
+        Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+    }
+    // decouple the PO driver nodes to reduce the number of levels
+    nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 );
+//    if ( nDupGates && Map_ManReadVerbose(pMan) )
+//        printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Interface with the mapping package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew;
+
+    Map_Man_t * pMan;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    // check that the library is available
+    if ( Abc_FrameReadLibGen() == NULL )
+    {
+        printf( "The current library is not available.\n" );
+        return 0;
+    }
+
+    // derive the supergate library
+    if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() )
+    {
+//        printf( "A simple supergate library is derived from gate library \"%s\".\n", 
+//            Mio_LibraryReadName((Mio_Library_t *)Abc_FrameReadLibGen()) );
+        Map_SuperLibDeriveFromGenlib( (Mio_Library_t *)Abc_FrameReadLibGen(), 0 );
+    }
+
+    // print a warning about choice nodes
+    if ( Abc_NtkGetChoiceNum( pNtk ) )
+        printf( "Performing mapping with choices.\n" );
+
+    // perform the mapping
+    pMan = Abc_NtkToMap( pNtk, -1, 1, NULL, 0 );
+    if ( pMan == NULL )
+        return NULL;
+    if ( !Map_Mapping( pMan ) )
+    {
+        Map_ManFree( pMan );
+        return NULL;
+    }
+
+    // reconstruct the network after mapping
+    pNtkNew = Abc_NtkFromMapSuperChoice( pMan, pNtk );
+    if ( pNtkNew == NULL )
+        return NULL;
+    Map_ManFree( pMan );
+
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkMap: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the mapped network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+    extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
+    ProgressBar * pProgress;
+    Abc_Ntk_t * pNtkNew, * pNtkNew2;
+    Abc_Obj_t * pNode;
+    int i;
+
+    // save the pointer to the mapped nodes
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        pNode->pNext = pNode->pCopy;
+    Abc_NtkForEachPo( pNtk, pNode, i )
+        pNode->pNext = pNode->pCopy;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        pNode->pNext = pNode->pCopy;
+
+    // duplicate the network
+    pNtkNew2 = Abc_NtkDup( pNtk );
+    pNtkNew  = Abc_NtkMulti( pNtkNew2, 0, 20, 0, 0, 1, 0 );
+    if ( !Abc_NtkBddToSop( pNtkNew, 0 ) )
+    {
+        printf( "Abc_NtkFromMapSuperChoice(): Converting to SOPs has failed.\n" );
+        return NULL;
+    }
+
+    // set the old network to point to the new network
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        pNode->pCopy = pNode->pCopy->pCopy;
+    Abc_NtkForEachPo( pNtk, pNode, i )
+        pNode->pCopy = pNode->pCopy->pCopy;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        pNode->pCopy = pNode->pCopy->pCopy;
+    Abc_NtkDelete( pNtkNew2 );
+
+    // set the pointers from the mapper to the new nodes
+    Abc_NtkForEachCi( pNtk, pNode, i )
+    {
+        Map_NodeSetData( Map_ManReadInputs(pMan)[i], 0, (char *)Abc_NtkCreateNodeInv(pNtkNew,pNode->pCopy) );
+        Map_NodeSetData( Map_ManReadInputs(pMan)[i], 1, (char *)pNode->pCopy );
+    }
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+//        if ( Abc_NodeIsConst(pNode) )
+//            continue;
+        Map_NodeSetData( (Map_Node_t *)pNode->pNext, 0, (char *)Abc_NtkCreateNodeInv(pNtkNew,pNode->pCopy) );
+        Map_NodeSetData( (Map_Node_t *)pNode->pNext, 1, (char *)pNode->pCopy );
+    }
+
+    // assign the mapping of the required phase to the POs
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+//        if ( Abc_NodeIsConst(pNode) )
+//            continue;
+        Abc_NodeSuperChoice( pNtkNew, pNode );
+    }
+    Extra_ProgressBarStop( pProgress );
+    return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the mapped network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeSuperChoice( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode )
+{
+    Map_Node_t * pMapNode = (Map_Node_t *)pNode->pNext;
+    Map_Cut_t * pCuts, * pTemp;
+
+    pCuts = Map_NodeReadCuts(pMapNode);
+    for ( pTemp = Map_CutReadNext(pCuts); pTemp; pTemp = Map_CutReadNext(pTemp) )
+    {
+        Abc_NodeFromMapCutPhase( pNtkNew, pTemp, 0 );
+        Abc_NodeFromMapCutPhase( pNtkNew, pTemp, 1 );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs the nodes corrresponding to one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeFromMapCutPhase( Abc_Ntk_t * pNtkNew, Map_Cut_t * pCut, int fPhase )
+{
+    Abc_Obj_t * pNodePIs[10];
+    Map_Node_t ** ppLeaves;
+    Map_Super_t * pSuperBest;
+    unsigned uPhaseBest;
+    int i, fInvPin, nLeaves;
+
+    pSuperBest = Map_CutReadSuperBest( pCut, fPhase );
+    if ( pSuperBest == NULL )
+        return;
+
+    // get the information about the best cut 
+    uPhaseBest = Map_CutReadPhaseBest( pCut, fPhase );
+    nLeaves    = Map_CutReadLeavesNum( pCut );
+    ppLeaves   = Map_CutReadLeaves( pCut );
+
+    // collect the PI nodes
+    for ( i = 0; i < nLeaves; i++ )
+    {
+        fInvPin = ((uPhaseBest & (1 << i)) > 0);
+        pNodePIs[i] = (Abc_Obj_t *)Map_NodeReadData( ppLeaves[i], !fInvPin );
+        assert( pNodePIs[i] != NULL );
+    }
+
+    // implement the supergate
+    Abc_NodeFromMapSuperChoice_rec( pNtkNew, pSuperBest, pNodePIs, nLeaves );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs the nodes corrresponding to one supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis )
+{
+    Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
+    Mio_Gate_t * pRoot;
+    Map_Super_t ** ppFanins;
+    Abc_Obj_t * pNodeNew, * pNodeFanin;
+    int nFanins, Number, i;
+
+    // get the parameters of the supergate
+    pRoot = Map_SuperReadRoot(pSuper);
+    if ( pRoot == NULL )
+    {
+        Number = Map_SuperReadNum(pSuper);
+        if ( Number < nNodePis )  
+        {
+            return pNodePis[Number];
+        }
+        else
+        {  
+//            assert( 0 );
+            /* It might happen that a super gate with 5 inputs is constructed that
+             * actually depends only on the first four variables; i.e the fifth is a
+             * don't care -- in that case we connect constant node for the fifth
+             * (since the cut only has 4 variables). An interesting question is what
+             * if the first variable (and not the fifth one is the redundant one;
+             * can that happen?) */
+            return Abc_NtkCreateNodeConst0(pNtkNew);
+        }
+    }
+    pRoot = Mio_LibraryReadGateByName( pLib, Mio_GateReadName(pRoot), NULL );
+
+    // get information about the fanins of the supergate
+    nFanins  = Map_SuperReadFaninNum( pSuper );
+    ppFanins = Map_SuperReadFanins( pSuper );
+    // create a new node with these fanins
+    pNodeNew = Abc_NtkCreateNode( pNtkNew );
+    for ( i = 0; i < nFanins; i++ )
+    {
+        pNodeFanin = Abc_NodeFromMapSuperChoice_rec( pNtkNew, ppFanins[i], pNodePis, nNodePis );
+        Abc_ObjAddFanin( pNodeNew, pNodeFanin );
+    }
+    pNodeNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, Mio_GateReadSop(pRoot) );
+    return pNodeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the twin node if it exists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkFetchTwinNode( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pNode2;
+    Mio_Gate_t * pGate = (Mio_Gate_t *)pNode->pData;
+    assert( Abc_NtkHasMapping(pNode->pNtk) );
+    if ( pGate == NULL || Mio_GateReadTwin(pGate) == NULL )
+        return NULL;
+    // assuming the twin node is following next
+    if ( (int)Abc_ObjId(pNode) == Abc_NtkObjNumMax(pNode->pNtk) - 1 )
+        return NULL;
+    pNode2 = Abc_NtkObj( pNode->pNtk, Abc_ObjId(pNode) + 1 );
+    if ( pNode2 == NULL || !Abc_ObjIsNode(pNode2) || Abc_ObjFaninNum(pNode) != Abc_ObjFaninNum(pNode2) )
+        return NULL;
+    if ( Mio_GateReadTwin(pGate) != (Mio_Gate_t *)pNode2->pData )
+        return NULL;
+    return pNode2;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Dumps mapped network in the mini-mapped format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkWriteMiniMapping( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Vec_Int_t * vMapping;
+    Vec_Str_t * vGates;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k, nNodes, nFanins, nExtra, * pArray;
+    assert( Abc_NtkHasMapping(pNtk) );
+    // collect nodes in the DFS order
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    // assign unique numbers
+    nNodes = nFanins = 0;
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->iTemp = nNodes++;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        pObj->iTemp = nNodes++, nFanins += Abc_ObjFaninNum(pObj);
+    // allocate attay to store mapping (4 counters + fanins for each node + PO drivers + gate names)
+    vMapping = Vec_IntAlloc( 4 + Abc_NtkNodeNum(pNtk) + nFanins + Abc_NtkCoNum(pNtk) + 10000 );
+    // write the numbers of CI/CO/Node/FF
+    Vec_IntPush( vMapping, Abc_NtkCiNum(pNtk) );
+    Vec_IntPush( vMapping, Abc_NtkCoNum(pNtk) );
+    Vec_IntPush( vMapping, Abc_NtkNodeNum(pNtk) );
+    Vec_IntPush( vMapping, Abc_NtkLatchNum(pNtk) );
+    // write the nodes
+    vGates = Vec_StrAlloc( 10000 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        Vec_IntPush( vMapping, Abc_ObjFaninNum(pObj) );
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Vec_IntPush( vMapping, pFanin->iTemp );
+        // remember this gate (to be added to the mapping later)
+        Vec_StrPrintStr( vGates, Mio_GateReadName((Mio_Gate_t *)pObj->pData) );
+        Vec_StrPush( vGates, '\0' );
+    }
+    // write the COs literals
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Vec_IntPush( vMapping, Abc_ObjFanin0(pObj)->iTemp );
+    // finish off the array
+    nExtra = 4 - Vec_StrSize(vGates) % 4;
+    for ( i = 0; i < nExtra; i++ )
+        Vec_StrPush( vGates, '\0' );
+    // add gates to the array
+    assert( Vec_StrSize(vGates) % 4 == 0 );
+    nExtra = Vec_StrSize(vGates) / 4;
+    pArray = (int *)Vec_StrArray(vGates);
+    for ( i = 0; i < nExtra; i++ )
+        Vec_IntPush( vMapping, pArray[i] );
+    // cleanup and return
+    Vec_PtrFree( vNodes );
+    Vec_StrFree( vGates );
+    return vMapping;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints mapped network represented in mini-mapped format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintMiniMapping( int * pArray )
+{
+    int nCis, nCos, nNodes, nFlops;
+    int i, k, nLeaves, Pos = 4;
+    char * pBuffer, * pName;
+    nCis = pArray[0];
+    nCos = pArray[1];
+    nNodes = pArray[2];
+    nFlops = pArray[3];
+    printf( "Mapped network has %d CIs, %d COs, %d gates, and %d flops.\n", nCis, nCos, nNodes, nFlops );
+    printf( "The first %d object IDs (from 0 to %d) are reserved for the CIs.\n", nCis, nCis - 1 );
+    for ( i = 0; i < nNodes; i++ )
+    {
+        printf( "Node %d has fanins {", nCis + i );
+        nLeaves = pArray[Pos++];
+        for ( k = 0; k < nLeaves; k++ )
+            printf( " %d", pArray[Pos++] );
+        printf( " }\n" );
+    }
+    for ( i = 0; i < nCos; i++ )
+        printf( "CO %d is driven by node %d\n", i, pArray[Pos++] );
+    pBuffer = (char *)(pArray + Pos);
+    for ( i = 0; i < nNodes; i++ )
+    {
+        pName = pBuffer;
+        pBuffer += strlen(pName) + 1;
+        printf( "Node %d has gate \"%s\"\n", nCis + i, pName );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure outputs an array representing mini-mapped network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Abc_NtkOutputMiniMapping( void * pAbc0 )
+{
+    Abc_Frame_t * pAbc = (Abc_Frame_t *)pAbc0;
+    Abc_Ntk_t * pNtk;
+    Vec_Int_t * vMapping;
+    int * pArray;
+    if ( pAbc == NULL )
+        printf( "ABC framework is not initialized by calling Abc_Start()\n" );
+    pNtk = Abc_FrameReadNtk( pAbc );
+    if ( pNtk == NULL )
+        printf( "Current network in ABC framework is not defined.\n" );
+    if ( !Abc_NtkHasMapping(pNtk) )
+        printf( "Current network in ABC framework is not mapped.\n" );
+    // derive mini-mapping
+    vMapping = Abc_NtkWriteMiniMapping( pNtk );
+    pArray = Vec_IntArray( vMapping );
+    ABC_FREE( vMapping );
+    // print mini-mapping (optional)
+//    Abc_NtkPrintMiniMapping( pArray );
+    // return the array representation of mini-mapping
+    return pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Test for mini-mapped format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTestMiniMapping( Abc_Ntk_t * p )
+{
+    Vec_Int_t * vMapping;
+    vMapping = Abc_NtkWriteMiniMapping( p );
+    Abc_NtkPrintMiniMapping( Vec_IntArray(vMapping) );
+    printf( "Array has size %d ints.\n", Vec_IntSize(vMapping) );
+    Vec_IntFree( vMapping );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [These APIs set arriva/required times of CIs/COs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSetCiArrivalTime( void * pAbc0, int iCi, float Rise, float Fall )
+{
+    Abc_Frame_t * pAbc = (Abc_Frame_t *)pAbc0;
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pNode;
+    if ( pAbc == NULL )
+        printf( "ABC framework is not initialized by calling Abc_Start()\n" );
+    pNtk = Abc_FrameReadNtk( pAbc );
+    if ( pNtk == NULL )
+        printf( "Current network in ABC framework is not defined.\n" );
+    if ( iCi < 0 || iCi >= Abc_NtkCiNum(pNtk) )
+        printf( "CI index is not valid.\n" );
+    pNode = Abc_NtkCi( pNtk, iCi );
+    Abc_NtkTimeSetArrival( pNtk, Abc_ObjId(pNode), Rise, Fall );
+}
+void Abc_NtkSetCoRequiredTime( void * pAbc0, int iCo, float Rise, float Fall )
+{
+    Abc_Frame_t * pAbc = (Abc_Frame_t *)pAbc0;
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pNode;
+    if ( pAbc == NULL )
+        printf( "ABC framework is not initialized by calling Abc_Start()\n" );
+    pNtk = Abc_FrameReadNtk( pAbc );
+    if ( pNtk == NULL )
+        printf( "Current network in ABC framework is not defined.\n" );
+    if ( iCo < 0 || iCo >= Abc_NtkCoNum(pNtk) )
+        printf( "CO index is not valid.\n" );
+    pNode = Abc_NtkCo( pNtk, iCo );
+    Abc_NtkTimeSetRequired( pNtk, Abc_ObjId(pNode), Rise, Fall );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcMeasure.c b/abc-build/src/base/abci/abcMeasure.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcMeasure.c
@@ -0,0 +1,483 @@
+/**CFile****************************************************************
+
+  FileName    [abc_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintMeasures( unsigned * pTruth, int nVars )
+{
+    unsigned uCofs[10][32];
+    int i, k, nOnes;
+
+    // total pairs
+    nOnes =  Kit_TruthCountOnes( uCofs[0], nVars );
+    printf( "Total = %d.\n", nOnes * ((1 << nVars) - nOnes) );
+
+    // print measures for individual variables
+    for ( i = 0; i < nVars; i++ )
+    {
+        Kit_TruthUniqueNew( uCofs[0], pTruth, nVars, i );
+        nOnes = Kit_TruthCountOnes( uCofs[0], nVars );
+        printf( "%7d ", nOnes );
+    }
+    printf( "\n" );
+
+    // consider pairs
+    for ( i = 0; i < nVars; i++ )
+    for ( k = 0; k < nVars; k++ )
+    {
+        if ( i == k )
+        {
+            printf( "        " );
+            continue;
+        }
+        Kit_TruthCofactor0New( uCofs[0], pTruth, nVars, i );
+        Kit_TruthCofactor1New( uCofs[1], pTruth, nVars, i );
+
+        Kit_TruthCofactor0New( uCofs[2], uCofs[0], nVars, k ); // 00
+        Kit_TruthCofactor1New( uCofs[3], uCofs[0], nVars, k ); // 01
+        Kit_TruthCofactor0New( uCofs[4], uCofs[1], nVars, k ); // 10
+        Kit_TruthCofactor1New( uCofs[5], uCofs[1], nVars, k ); // 11
+
+        Kit_TruthAndPhase( uCofs[6], uCofs[2], uCofs[5], nVars, 0, 1 ); // 00  & 11'
+        Kit_TruthAndPhase( uCofs[7], uCofs[2], uCofs[5], nVars, 1, 0 ); // 00' & 11
+        Kit_TruthAndPhase( uCofs[8], uCofs[3], uCofs[4], nVars, 0, 1 ); // 01  & 10'
+        Kit_TruthAndPhase( uCofs[9], uCofs[3], uCofs[4], nVars, 1, 0 ); // 01' & 10
+
+        nOnes = Kit_TruthCountOnes( uCofs[6], nVars ) + 
+                Kit_TruthCountOnes( uCofs[7], nVars ) + 
+                Kit_TruthCountOnes( uCofs[8], nVars ) + 
+                Kit_TruthCountOnes( uCofs[9], nVars );
+
+        printf( "%7d ", nOnes );
+        if ( k == nVars - 1 )
+            printf( "\n" );
+    }
+    printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_Ntk4VarObjPrint_rec( Abc_Obj_t * pObj )
+{
+    if ( pObj == Abc_AigConst1(pObj->pNtk) )
+    {
+        printf( "1" );
+        return;
+    }
+    if ( Abc_ObjIsPi(pObj) )
+    {
+        printf( "%c", pObj->Id - 1 + 'a' );
+        return;
+    }
+
+    printf( "(" );
+    Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin0(pObj) );
+    if ( Abc_ObjFaninC0(pObj) )
+        printf( "\'" );
+    Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin1(pObj) );
+    if ( Abc_ObjFaninC1(pObj) )
+        printf( "\'" );
+    printf( ")" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Abc_Ntk4VarObj( Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pObj;
+    unsigned uTruth0, uTruth1;
+    int i;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        uTruth0 = (unsigned)(Abc_ObjFanin0(pObj)->pCopy);
+        uTruth1 = (unsigned)(Abc_ObjFanin1(pObj)->pCopy);
+        if ( Abc_ObjFaninC0(pObj) )
+            uTruth0 = ~uTruth0;
+        if ( Abc_ObjFaninC1(pObj) )
+            uTruth1 = ~uTruth1;
+        pObj->pCopy = (Abc_Obj_t *)(uTruth0 & uTruth1);
+    }
+    return uTruth0 & uTruth1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_Ntk4VarTable( Abc_Ntk_t * pNtk )
+{
+    static unsigned u4VarTruths[4] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00 };
+    static unsigned u4VarTts[222] = {
+        0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, 
+        0x001b, 0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, 
+        0x007f, 0x00ff, 0x0116, 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, 
+        0x012c, 0x012d, 0x012f, 0x013c, 0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016a, 
+        0x016b, 0x016e, 0x016f, 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0186, 
+        0x0187, 0x0189, 0x018b, 0x018f, 0x0196, 0x0197, 0x0198, 0x0199, 0x019a, 0x019b, 
+        0x019e, 0x019f, 0x01a8, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ad, 0x01ae, 0x01af, 
+        0x01bc, 0x01bd, 0x01be, 0x01bf, 0x01e8, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, 
+        0x01fe, 0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 
+        0x035e, 0x035f, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f, 
+        0x037c, 0x037d, 0x037e, 0x03c0, 0x03c1, 0x03c3, 0x03c5, 0x03c6, 0x03c7, 0x03cf, 
+        0x03d4, 0x03d5, 0x03d6, 0x03d7, 0x03d8, 0x03d9, 0x03db, 0x03dc, 0x03dd, 0x03de, 
+        0x03fc, 0x0660, 0x0661, 0x0662, 0x0663, 0x0666, 0x0667, 0x0669, 0x066b, 0x066f, 
+        0x0672, 0x0673, 0x0676, 0x0678, 0x0679, 0x067a, 0x067b, 0x067e, 0x0690, 0x0691, 
+        0x0693, 0x0696, 0x0697, 0x069f, 0x06b0, 0x06b1, 0x06b2, 0x06b3, 0x06b4, 0x06b5, 
+        0x06b6, 0x06b7, 0x06b9, 0x06bd, 0x06f0, 0x06f1, 0x06f2, 0x06f6, 0x06f9, 0x0776, 
+        0x0778, 0x0779, 0x077a, 0x077e, 0x07b0, 0x07b1, 0x07b4, 0x07b5, 0x07b6, 0x07bc, 
+        0x07e0, 0x07e1, 0x07e2, 0x07e3, 0x07e6, 0x07e9, 0x07f0, 0x07f1, 0x07f2, 0x07f8, 
+        0x0ff0, 0x1668, 0x1669, 0x166a, 0x166b, 0x166e, 0x167e, 0x1681, 0x1683, 0x1686, 
+        0x1687, 0x1689, 0x168b, 0x168e, 0x1696, 0x1697, 0x1698, 0x1699, 0x169a, 0x169b, 
+        0x169e, 0x16a9, 0x16ac, 0x16ad, 0x16bc, 0x16e9, 0x177e, 0x178e, 0x1796, 0x1798, 
+        0x179a, 0x17ac, 0x17e8, 0x18e7, 0x19e1, 0x19e3, 0x19e6, 0x1bd8, 0x1be4, 0x1ee1, 
+        0x3cc3, 0x6996
+    };
+    int Counters[222] = {0};
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj;
+    unsigned uTruth;
+    int i, k, Count = 0;
+
+    unsigned short * puCanons = NULL;
+    unsigned char * puMap = NULL;
+    Extra_Truth4VarNPN( &puCanons, NULL, NULL, &puMap );
+
+    // set elementary truth tables
+    assert( Abc_NtkPiNum(pNtk) == 4 );
+    Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)0xFFFFFFFF;
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)u4VarTruths[i];
+
+    // create truth tables
+    Abc_NtkForEachPo( pNtk, pObj, i )
+    {
+        vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 );
+        if ( Vec_PtrSize(vNodes) == 0 )
+            uTruth = (unsigned)Abc_ObjFanin0(pObj)->pCopy;
+        else
+            uTruth = Abc_Ntk4VarObj( vNodes );
+
+        if ( (uTruth & 0xFFFF) < (~uTruth & 0xFFFF) )
+            uTruth = uTruth & 0xFFFF;
+        else
+            uTruth = ~uTruth & 0xFFFF;
+
+        for ( k = 0; k < 222; k++ )
+            if ( u4VarTts[k] == uTruth )
+                break;
+        if ( k == 222 )
+            continue;
+/*
+//        if ( uTruth == 1725 )
+        if ( k == 96 )
+        {
+            printf( "%d : ", Vec_PtrSize(vNodes) );
+            Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin0(pObj) );
+            printf( "\n" );
+        }
+*/
+        Counters[k]++;
+
+//        Counters[ puMap[uTruth & 0xFFFF] ]++;
+        Vec_PtrFree( vNodes );
+    }
+    ABC_FREE( puCanons );
+    ABC_FREE( puMap );
+
+    Count = 0;
+    for ( k = 0; k < 222; k++ )
+    {
+        printf( "%d/%x/%d ", k, u4VarTts[k], Counters[k] );
+        Count += Counters[k];
+    }
+    printf( " Total = %d\n", Count );
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if there are no more than 2 unique cofactors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkPrintOneDecompCheckCofList( unsigned * uCofs, int nCofs )
+{
+    int i, Ind = -1;
+    assert( nCofs > 2 );
+    for ( i = 1; i < nCofs; i++ )
+    {
+        if ( uCofs[i] == uCofs[0] )
+            continue;
+        if ( Ind == -1 )
+        {
+            Ind = i;
+            continue;
+        }
+        if ( uCofs[i] == uCofs[Ind] )
+            continue;
+        return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks all cofactors with the given mask.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkPrintOneDecompCheck( unsigned * uCofs, int nCofs, unsigned uMask )
+{
+    unsigned pCofs[32][32];
+    int nCofNums[32] = {0};
+    int uMasks[32];
+    int nGroups = 0;
+    int i, k;
+    for ( i = 0; i < nCofs; i++ )
+    {
+        // find group of this cof
+        for ( k = 0; k < nGroups; k++ )
+            if ( (int)(i & uMask) == uMasks[k] )
+                break;
+        if ( k == nGroups )
+        {
+            uMasks[k] = (i & uMask);
+            nGroups++;
+        }
+        // save cof in the group
+        pCofs[k][ nCofNums[k]++ ] = uCofs[i];
+        assert( nCofNums[k] <= 32 );
+        assert( nGroups <= 32 );
+    }
+    // check the groups
+    for ( i = 0; i < nGroups; i++ )
+        if ( !Abc_NtkPrintOneDecompCheckCofList(pCofs[i], nCofNums[i]) )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintOneDecomp_rec( unsigned * uCofs, int nCofs, int nVars, unsigned uMask, int * pBestSize, unsigned * puBestMask )
+{
+    unsigned uMaskNew;
+    int v, last, Counter = 0;
+    // find the last variable in the mask
+    for ( v = 0; v < nVars; v++ )
+        if ( uMask & (1<<v) )
+        {
+            last = v;
+            Counter++;
+        }
+    if ( Counter > 3 )
+        return;
+    // try adding one variable after the last
+    for ( v = last + 1; v < nVars; v++ )
+    {
+        uMaskNew = uMask | (1 << v);
+        if ( !Abc_NtkPrintOneDecompCheck( uCofs, nCofs, uMaskNew ) )
+            continue;
+        if ( *pBestSize < Counter + 1 )
+        {
+            *pBestSize = Counter + 1;
+            *puBestMask = uMaskNew;
+        }
+        // try other masks
+        Abc_NtkPrintOneDecomp_rec( uCofs, nCofs, nVars, uMaskNew, pBestSize, puBestMask );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintOneDecomp( unsigned * pTruth, int nVars )
+{
+    int BoundSet = 6;
+    unsigned uCofs[64], uMask, uBestMask = 0;
+    int i, nCofs, nMints, nMintShift, BestSize = 1;
+
+    assert( nVars >  BoundSet );
+    assert( nVars <= BoundSet + 5 ); // at most 5 variable cofactors
+
+    // collect the cofactors
+    nCofs = (1 << BoundSet);
+    nMints = (1 << (nVars-BoundSet));
+    nMintShift = 0;
+    uMask = Kit_CubeMask( nMints );
+    for ( i = 0; i < nCofs; i++ )
+    {
+        uCofs[i] = (pTruth[nMintShift/32] >> (nMintShift % 32)) & uMask;
+        nMintShift += nMints;
+    }
+
+    // try removing variables
+    for ( i = 0; i < BoundSet; i++ )
+        Abc_NtkPrintOneDecomp_rec( uCofs, nCofs, nVars, (1 << i), &BestSize, &uBestMask );
+
+    printf( "Best size = %d  ", BestSize );
+    printf( "Best mask = " );
+    Extra_PrintBinary( stdout, &uBestMask, nVars );
+    printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintOneDec( unsigned * pTruth, int nVars )
+{
+    unsigned uCof[(1<<11)], * pOut = uCof, * pIn = pTruth, * pTemp;
+    int nDiffs[16];
+    int Order[16];
+    int i, fChange, Temp, Counter;
+
+    // find the ordering
+    for ( i = 0; i < nVars; i++ )
+    {
+        Kit_TruthUniqueNew( uCof, pTruth, nVars, i );
+        nDiffs[i] = Kit_TruthCountOnes( uCof, nVars );
+        Order[i] = i;
+    }
+
+    // permute truth table to least active variable first
+    Counter = 0;
+    do {
+        fChange = 0;
+        for ( i = 0; i < nVars-1; i++ )
+        {
+            if ( nDiffs[i] <= nDiffs[i+1] )
+                continue;
+            fChange = 1;
+            Counter++;
+
+            Temp = nDiffs[i];
+            nDiffs[i] = nDiffs[i+1];
+            nDiffs[i+1] = Temp;
+
+            Temp = Order[i];
+            Order[i] = Order[i+1];
+            Order[i+1] = Temp;
+
+            Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, i );
+            pTemp = pIn; pIn = pOut; pOut = pTemp;
+        }
+    } while ( fChange );
+
+    // swap if it was moved an even number of times
+    if ( Counter & 1 )
+        Extra_TruthCopy( pOut, pIn, nVars );
+
+    // call the decomposition
+    Abc_NtkPrintOneDecomp( pTruth, nVars );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcMerge.c b/abc-build/src/base/abci/abcMerge.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcMerge.c
@@ -0,0 +1,358 @@
+/**CFile****************************************************************
+
+  FileName    [abcMerge.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [LUT merging algorithm.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "aig/aig/aig.h"
+#include "opt/nwk/nwkMerge.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the fanins of the node with the current trav ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMarkFanins_rec( Abc_Obj_t * pLut, int nLevMin )
+{
+    Abc_Obj_t * pNext;
+    int i;
+    if ( !Abc_ObjIsNode(pLut) )
+        return;
+    if ( Abc_NodeIsTravIdCurrent( pLut ) )
+        return;
+    Abc_NodeSetTravIdCurrent( pLut );
+    if ( Abc_ObjLevel(pLut) < nLevMin )
+        return;
+    Abc_ObjForEachFanin( pLut, pNext, i )
+        Abc_NtkMarkFanins_rec( pNext, nLevMin );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the fanouts of the node with the current trav ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMarkFanouts_rec( Abc_Obj_t * pLut, int nLevMax, int nFanMax )
+{
+    Abc_Obj_t * pNext;
+    int i;
+    if ( !Abc_ObjIsNode(pLut) )
+        return;
+    if ( Abc_NodeIsTravIdCurrent( pLut ) )
+        return;
+    Abc_NodeSetTravIdCurrent( pLut );
+    if ( Abc_ObjLevel(pLut) > nLevMax )
+        return;
+    if ( Abc_ObjFanoutNum(pLut) > nFanMax )
+        return;
+    Abc_ObjForEachFanout( pLut, pNext, i )
+        Abc_NtkMarkFanouts_rec( pNext, nLevMax, nFanMax );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the circle of nodes around the given set.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax )
+{
+    Abc_Obj_t * pObj, * pNext;
+    int i, k;
+    Vec_PtrClear( vNext );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vStart, pObj, i )
+    {
+        Abc_ObjForEachFanin( pObj, pNext, k )
+        {
+            if ( !Abc_ObjIsNode(pNext) )
+                continue;
+            if ( Abc_NodeIsTravIdCurrent( pNext ) )
+                continue;
+            Abc_NodeSetTravIdCurrent( pNext );
+            Vec_PtrPush( vNext, pNext );
+        }
+        Abc_ObjForEachFanout( pObj, pNext, k )
+        {
+            if ( !Abc_ObjIsNode(pNext) )
+                continue;
+            if ( Abc_NodeIsTravIdCurrent( pNext ) )
+                continue;
+            Abc_NodeSetTravIdCurrent( pNext );
+            if ( Abc_ObjFanoutNum(pNext) > nFanMax )
+                continue;
+            Vec_PtrPush( vNext, pNext );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the circle of nodes removes from the given one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCollectNonOverlapCands( Abc_Obj_t * pLut, Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars )
+{
+    Vec_Ptr_t * vTemp;
+    Abc_Obj_t * pObj;
+    int i, k;
+    Vec_PtrClear( vCands );
+    if ( pPars->nMaxSuppSize - Abc_ObjFaninNum(pLut) <= 1 )
+        return;
+
+    // collect nodes removed by this distance
+    assert( pPars->nMaxDistance > 0 );
+    Vec_PtrClear( vStart );
+    Vec_PtrPush( vStart, pLut );
+    Abc_NtkIncrementTravId( pLut->pNtk );
+    Abc_NodeSetTravIdCurrent( pLut );
+    for ( i = 1; i <= pPars->nMaxDistance; i++ )
+    {
+        Abc_NtkCollectCircle( vStart, vNext, pPars->nMaxFanout );
+        vTemp  = vStart;
+        vStart = vNext;
+        vNext  = vTemp;
+        // collect the nodes in vStart
+        Vec_PtrForEachEntry( Abc_Obj_t *, vStart, pObj, k )
+            Vec_PtrPush( vCands, pObj );
+    }
+
+    // mark the TFI/TFO nodes
+    Abc_NtkIncrementTravId( pLut->pNtk );
+    if ( pPars->fUseTfiTfo )
+        Abc_NodeSetTravIdCurrent( pLut );
+    else
+    {
+        Abc_NodeSetTravIdPrevious( pLut );
+        Abc_NtkMarkFanins_rec( pLut, Abc_ObjLevel(pLut) - pPars->nMaxDistance );
+        Abc_NodeSetTravIdPrevious( pLut );
+        Abc_NtkMarkFanouts_rec( pLut, Abc_ObjLevel(pLut) + pPars->nMaxDistance, pPars->nMaxFanout );
+    }
+
+    // collect nodes satisfying the following conditions:
+    // - they are close enough in terms of distance
+    // - they are not in the TFI/TFO of the LUT
+    // - they have no more than the given number of fanins
+    // - they have no more than the given diff in delay
+    k = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vCands, pObj, i )
+    {
+        if ( Abc_NodeIsTravIdCurrent(pObj) )
+            continue;
+        if ( Abc_ObjFaninNum(pLut) + Abc_ObjFaninNum(pObj) > pPars->nMaxSuppSize )
+            continue;
+        if ( Abc_ObjLevel(pLut) - Abc_ObjLevel(pObj) > pPars->nMaxLevelDiff || 
+             Abc_ObjLevel(pObj) - Abc_ObjLevel(pLut) > pPars->nMaxLevelDiff )
+             continue;
+        Vec_PtrWriteEntry( vCands, k++, pObj );
+    }
+    Vec_PtrShrink( vCands, k );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Count the total number of fanins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCountTotalFanins( Abc_Obj_t * pLut, Abc_Obj_t * pCand )
+{
+    Abc_Obj_t * pFanin;
+    int i, nCounter = Abc_ObjFaninNum(pLut);
+    Abc_ObjForEachFanin( pCand, pFanin, i )
+        nCounter += !pFanin->fMarkC;
+    return nCounter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects overlapping candidates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCollectOverlapCands( Abc_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars )
+{
+    Abc_Obj_t * pFanin, * pObj;
+    int i, k;
+    // mark fanins of pLut
+    Abc_ObjForEachFanin( pLut, pFanin, i )
+        pFanin->fMarkC = 1;
+    // collect the matching fanouts of each fanin of the node
+    Vec_PtrClear( vCands );
+    Abc_NtkIncrementTravId( pLut->pNtk );
+    Abc_NodeSetTravIdCurrent( pLut );
+    Abc_ObjForEachFanin( pLut, pFanin, i )
+    {
+        if ( !Abc_ObjIsNode(pFanin) )
+            continue;
+        if ( Abc_ObjFanoutNum(pFanin) > pPars->nMaxFanout )
+            continue;
+        Abc_ObjForEachFanout( pFanin, pObj, k )
+        {
+            if ( !Abc_ObjIsNode(pObj) )
+                continue;
+            if ( Abc_NodeIsTravIdCurrent( pObj ) )
+                continue;
+            Abc_NodeSetTravIdCurrent( pObj );
+            // check the difference in delay
+            if ( Abc_ObjLevel(pLut) - Abc_ObjLevel(pObj) > pPars->nMaxLevelDiff || 
+                 Abc_ObjLevel(pObj) - Abc_ObjLevel(pLut) > pPars->nMaxLevelDiff )
+                 continue;
+            // check the total number of fanins of the node
+            if ( Abc_NtkCountTotalFanins(pLut, pObj) > pPars->nMaxSuppSize )
+                continue;
+            Vec_PtrPush( vCands, pObj );
+        }
+    }
+    // unmark fanins of pLut
+    Abc_ObjForEachFanin( pLut, pFanin, i )
+        pFanin->fMarkC = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs LUT merging with parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkLutMerge( Abc_Ntk_t * pNtk, Nwk_LMPars_t * pPars )
+{
+    Nwk_Grf_t * p;
+    Vec_Int_t * vResult;
+    Vec_Ptr_t * vStart, * vNext, * vCands1, * vCands2;
+    Abc_Obj_t * pLut, * pCand;
+    int i, k, nVertsMax, nCands;
+    abctime clk = Abc_Clock();
+    // count the number of vertices
+    nVertsMax = 0;
+    Abc_NtkForEachNode( pNtk, pLut, i )
+        nVertsMax += (int)(Abc_ObjFaninNum(pLut) <= pPars->nMaxLutSize);
+    p = Nwk_ManGraphAlloc( nVertsMax );
+    // create graph
+    vStart  = Vec_PtrAlloc( 1000 );
+    vNext   = Vec_PtrAlloc( 1000 );
+    vCands1 = Vec_PtrAlloc( 1000 );
+    vCands2 = Vec_PtrAlloc( 1000 );
+    nCands  = 0;
+    Abc_NtkForEachNode( pNtk, pLut, i )
+    {
+        if ( Abc_ObjFaninNum(pLut) > pPars->nMaxLutSize )
+            continue;
+        Abc_NtkCollectOverlapCands( pLut, vCands1, pPars );
+        if ( pPars->fUseDiffSupp )
+            Abc_NtkCollectNonOverlapCands( pLut, vStart, vNext, vCands2, pPars );
+        if ( Vec_PtrSize(vCands1) == 0 && Vec_PtrSize(vCands2) == 0 )
+            continue;
+        nCands += Vec_PtrSize(vCands1) + Vec_PtrSize(vCands2);
+        // save candidates
+        Vec_PtrForEachEntry( Abc_Obj_t *, vCands1, pCand, k )
+            Nwk_ManGraphHashEdge( p, Abc_ObjId(pLut), Abc_ObjId(pCand) );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vCands2, pCand, k )
+            Nwk_ManGraphHashEdge( p, Abc_ObjId(pLut), Abc_ObjId(pCand) );
+        // print statistics about this node
+        if ( pPars->fVeryVerbose )
+        printf( "Node %6d : Fanins = %d. Fanouts = %3d.  Cand1 = %3d. Cand2 = %3d.\n",
+            Abc_ObjId(pLut), Abc_ObjFaninNum(pLut), Abc_ObjFaninNum(pLut), 
+            Vec_PtrSize(vCands1), Vec_PtrSize(vCands2) );
+    }
+    Vec_PtrFree( vStart );
+    Vec_PtrFree( vNext );
+    Vec_PtrFree( vCands1 );
+    Vec_PtrFree( vCands2 );
+    if ( pPars->fVerbose )
+    {
+        printf( "Mergable LUTs = %6d. Total cands = %6d. ", p->nVertsMax, nCands );
+        ABC_PRT( "Deriving graph", Abc_Clock() - clk );
+    }
+    // solve the graph problem
+    clk = Abc_Clock();
+    Nwk_ManGraphSolve( p );
+    if ( pPars->fVerbose )
+    {
+        printf( "GRAPH: Nodes = %6d. Edges = %6d.  Pairs = %6d.  ", 
+            p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 );
+        ABC_PRT( "Solving", Abc_Clock() - clk );
+        Nwk_ManGraphReportMemoryUsage( p );
+    }
+    vResult = p->vPairs; p->vPairs = NULL;
+/*
+    for ( i = 0; i < vResult->nSize; i += 2 )
+        printf( "(%d,%d) ", vResult->pArray[i], vResult->pArray[i+1] );
+    printf( "\n" );
+*/
+    Nwk_ManGraphFree( p );
+    return vResult;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcMffc.c b/abc-build/src/base/abci/abcMffc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcMffc.c
@@ -0,0 +1,1252 @@
+/**CFile****************************************************************
+
+  FileName    [abcMffc.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Computing multi-output maximum fanout-free cones.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcMffc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+
+ABC_NAMESPACE_IMPL_START
+ 
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences and collects the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MffcDeref_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    if ( Abc_ObjIsCi(pNode) )
+        return;
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        assert( pFanin->vFanouts.nSize > 0 );
+        if ( --pFanin->vFanouts.nSize == 0 )
+            Abc_MffcDeref_rec( pFanin, vNodes );
+    }
+    if ( vNodes )
+        Vec_PtrPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [References the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MffcRef_rec( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    if ( Abc_ObjIsCi(pNode) )
+        return;
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        if ( pFanin->vFanouts.nSize++ == 0 )
+            Abc_MffcRef_rec( pFanin );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes belonging to the MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MffcCollectNodes( Abc_Obj_t ** pNodes, int nNodes, Vec_Ptr_t * vNodes )
+{
+    int i;
+    Vec_PtrClear( vNodes );
+    for ( i = 0; i < nNodes; i++ )
+        Abc_MffcDeref_rec( pNodes[i], vNodes );
+    for ( i = 0; i < nNodes; i++ )
+        Abc_MffcRef_rec( pNodes[i] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects leaves of the MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MffcCollectLeaves( Vec_Ptr_t * vNodes, Vec_Ptr_t * vLeaves )
+{
+    Abc_Obj_t * pNode, * pFanin;
+    int i, k;
+    assert( Vec_PtrSize(vNodes) > 0 );
+    pNode = (Abc_Obj_t *)Vec_PtrEntry( vNodes, 0 );
+    // label them
+    Abc_NtkIncrementTravId( pNode->pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        Abc_NodeSetTravIdCurrent( pNode );
+    // collect non-labeled fanins
+    Vec_PtrClear( vLeaves );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    Abc_ObjForEachFanin( pNode, pFanin, k )
+    {
+        if ( Abc_NodeIsTravIdCurrent(pFanin) )
+            continue;
+        Abc_NodeSetTravIdCurrent( pFanin );
+        Vec_PtrPush( vLeaves, pFanin );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes that are roots of MFFCs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NktMffcMarkRoots( Abc_Ntk_t * pNtk, int fSkipPis )
+{
+    Vec_Ptr_t * vRoots, * vNodes, * vLeaves;
+    Abc_Obj_t * pObj, * pLeaf;
+    int i, k;
+    Abc_NtkCleanMarkA( pNtk );
+    // mark the drivers of combinational outputs
+    vRoots  = Vec_PtrAlloc( 1000 );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        pObj = Abc_ObjFanin0( pObj );
+//        if ( Abc_ObjIsCi(pObj) || Abc_ObjFaninNum(pObj) == 0 || pObj->fMarkA )
+        if ( Abc_ObjIsCi(pObj) || pObj->fMarkA )
+            continue;
+        pObj->fMarkA = 1;
+        Vec_PtrPush( vRoots, pObj );
+    }
+    // explore starting from the drivers
+    vNodes  = Vec_PtrAlloc( 100 );
+    vLeaves = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+    {
+        if ( Abc_ObjIsCi(pObj) )
+            continue;
+        // collect internal nodes 
+        Abc_MffcCollectNodes( &pObj, 1, vNodes );
+        // collect leaves
+        Abc_MffcCollectLeaves( vNodes, vLeaves );
+        // add non-PI leaves
+        Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pLeaf, k )
+        {
+            if ( (fSkipPis && Abc_ObjIsCi(pLeaf)) || pLeaf->fMarkA )
+                continue;
+            pLeaf->fMarkA = 1;
+            Vec_PtrPush( vRoots, pLeaf );
+        }
+    }
+    Vec_PtrFree( vLeaves );
+    Vec_PtrFree( vNodes );
+    Abc_NtkCleanMarkA( pNtk );
+    return vRoots;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect fanout reachable root nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NktMffcCollectFanout_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vFanouts )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    if ( Abc_ObjIsCo(pObj) )
+        return;
+    if ( Abc_ObjFanoutNum(pObj) > 64 )
+        return;
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return;
+    Abc_NodeSetTravIdCurrent(pObj);
+    if ( pObj->fMarkA )
+    {
+        if ( pObj->vFanouts.nSize > 0 )
+            Vec_PtrPush( vFanouts, pObj );
+        return;
+    }
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        Abc_NktMffcCollectFanout_rec( pFanout, vFanouts );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect fanout reachable root nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NktMffcCollectFanout( Abc_Obj_t ** pNodes, int nNodes, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vFanouts )
+{
+    Abc_Obj_t * pFanin, * pFanout;
+    int i, k;
+    // dereference nodes
+    for ( i = 0; i < nNodes; i++ )
+        Abc_MffcDeref_rec( pNodes[i], NULL );
+    // collect fanouts
+    Vec_PtrClear( vFanouts );
+    pFanin = (Abc_Obj_t *)Vec_PtrEntry( vLeaves, 0 );
+    Abc_NtkIncrementTravId( pFanin->pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pFanin, i )
+        Abc_ObjForEachFanout( pFanin, pFanout, k )
+            Abc_NktMffcCollectFanout_rec( pFanout, vFanouts );
+    // reference nodes
+    for ( i = 0; i < nNodes; i++ )
+        Abc_MffcRef_rec( pNodes[i] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Grow one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NktMffcGrowOne( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppObjs, int nObjs, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vFanouts )
+{
+    Abc_Obj_t * pFanout, * pFanoutBest = NULL;
+    double CostBest = 0.0;
+    int i, k;
+    Abc_MffcCollectNodes( ppObjs, nObjs, vNodes );
+    Abc_MffcCollectLeaves( vNodes, vLeaves );
+    // collect fanouts of all fanins
+    Abc_NktMffcCollectFanout( ppObjs, nObjs, vLeaves, vFanouts );
+    // try different fanouts
+    Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i )
+    {
+        for ( k = 0; k < nObjs; k++ )
+            if ( pFanout == ppObjs[k] )
+                break;
+        if ( k < nObjs )
+            continue;
+        ppObjs[nObjs] = pFanout;
+        Abc_MffcCollectNodes( ppObjs, nObjs+1, vNodes );
+        Abc_MffcCollectLeaves( vNodes, vLeaves );
+        if ( pFanoutBest == NULL || CostBest < 1.0 * Vec_PtrSize(vNodes)/Vec_PtrSize(vLeaves) ) 
+        {
+            CostBest = 1.0 * Vec_PtrSize(vNodes)/Vec_PtrSize(vLeaves);
+            pFanoutBest = pFanout;
+        }
+    }
+    return pFanoutBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure to increase MFF size by pairing nodes.]
+
+  Description [For each node in the array vRoots, find a matching node, 
+  so that the ratio of nodes inside to the leaf nodes is maximized.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NktMffcGrowRoots( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots )
+{
+    Vec_Ptr_t * vRoots1, * vNodes, * vLeaves, * vFanouts;
+    Abc_Obj_t * pObj, * pRoot2, * pNodes[2];
+    int i;
+    Abc_NtkCleanMarkA( pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+        pObj->fMarkA = 1;
+    vRoots1  = Vec_PtrAlloc( 100 );
+    vNodes   = Vec_PtrAlloc( 100 );
+    vLeaves  = Vec_PtrAlloc( 100 );
+    vFanouts = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+    {
+        pNodes[0] = pObj;
+        pRoot2 = Abc_NktMffcGrowOne( pNtk, pNodes, 1, vNodes, vLeaves, vFanouts );
+        Vec_PtrPush( vRoots1, pRoot2 );
+    }
+    Vec_PtrFree( vNodes );
+    Vec_PtrFree( vLeaves );
+    Vec_PtrFree( vFanouts );
+    Abc_NtkCleanMarkA( pNtk );
+    return vRoots1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure to increase MFF size by pairing nodes.]
+
+  Description [For each node in the array vRoots, find a matching node, 
+  so that the ratio of nodes inside to the leaf nodes is maximized.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NktMffcGrowRootsAgain( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Ptr_t * vRoots1 )
+{
+    Vec_Ptr_t * vRoots2, * vNodes, * vLeaves, * vFanouts;
+    Abc_Obj_t * pObj, * pRoot2, * ppObjs[3];
+    int i;
+    Abc_NtkCleanMarkA( pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+        pObj->fMarkA = 1;
+    vRoots2  = Vec_PtrAlloc( 100 );
+    vNodes   = Vec_PtrAlloc( 100 );
+    vLeaves  = Vec_PtrAlloc( 100 );
+    vFanouts = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+    {
+        ppObjs[0] = pObj;
+        ppObjs[1] = (Abc_Obj_t *)Vec_PtrEntry( vRoots1, i );
+        if ( ppObjs[1] == NULL )
+        {
+            Vec_PtrPush( vRoots2, NULL );
+            continue;
+        }
+        pRoot2    = Abc_NktMffcGrowOne( pNtk, ppObjs, 2, vNodes, vLeaves, vFanouts );
+        Vec_PtrPush( vRoots2, pRoot2 );
+    }
+    Vec_PtrFree( vNodes );
+    Vec_PtrFree( vLeaves );
+    Vec_PtrFree( vFanouts );
+    Abc_NtkCleanMarkA( pNtk );
+    assert( Vec_PtrSize(vRoots) == Vec_PtrSize(vRoots2) );
+    return vRoots2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Testbench.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NktMffcPrint( char * pFileName, Abc_Obj_t ** pNodes, int nNodes, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLeaves )
+{
+    FILE * pFile;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k;
+    // convert the network
+    Abc_NtkToSop( pNodes[0]->pNtk, 0 );
+    // write the file
+    pFile = fopen( pFileName, "wb" );
+    fprintf( pFile, ".model %s_part\n", pNodes[0]->pNtk->pName );
+    fprintf( pFile, ".inputs" );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+        fprintf( pFile, " %s", Abc_ObjName(pObj) );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, ".outputs" );
+    for ( i = 0; i < nNodes; i++ )
+        fprintf( pFile, " %s", Abc_ObjName(pNodes[i]) );
+    fprintf( pFile, "\n" );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        fprintf( pFile, ".names" );
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            fprintf( pFile, " %s", Abc_ObjName(pFanin) );
+        fprintf( pFile, " %s", Abc_ObjName(pObj) );
+        fprintf( pFile, "\n%s", (char *)pObj->pData );
+    }
+    fprintf( pFile, ".end\n" );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Testbench.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NktMffcPrintInt( char * pFileName, Abc_Ntk_t * pNtk, Vec_Int_t * vRoots, Vec_Int_t * vNodes, Vec_Int_t * vLeaves )
+{
+    FILE * pFile;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k;
+    // convert the network
+    Abc_NtkToSop( pNtk, 0 );
+    // write the file
+    pFile = fopen( pFileName, "wb" );
+    fprintf( pFile, ".model %s_part\n", pNtk->pName );
+    fprintf( pFile, ".inputs" );
+    Abc_NtkForEachObjVec( vLeaves, pNtk, pObj, i )
+        fprintf( pFile, " %s", Abc_ObjName(pObj) );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, ".outputs" );
+    Abc_NtkForEachObjVec( vRoots, pNtk, pObj, i )
+        fprintf( pFile, " %s", Abc_ObjName(pObj) );
+    fprintf( pFile, "\n" );
+    Abc_NtkForEachObjVec( vNodes, pNtk, pObj, i )
+    {
+        fprintf( pFile, ".names" );
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            fprintf( pFile, " %s", Abc_ObjName(pFanin) );
+        fprintf( pFile, " %s", Abc_ObjName(pObj) );
+        fprintf( pFile, "\n%s", (char *)pObj->pData );
+    }
+    fprintf( pFile, ".end\n" );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Testbench.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NktMffcTest( Abc_Ntk_t * pNtk )
+{
+    char pFileName[1000];
+    Vec_Ptr_t * vRoots, * vRoots1, * vRoots2, * vNodes, * vLeaves;
+    Abc_Obj_t * pNodes[3], * pObj;
+    int i, nNodes = 0, nNodes2 = 0;
+    vRoots  = Abc_NktMffcMarkRoots( pNtk, 1 );
+    vRoots1 = Abc_NktMffcGrowRoots( pNtk, vRoots );
+    vRoots2 = Abc_NktMffcGrowRootsAgain( pNtk, vRoots, vRoots1 );
+    vNodes  = Vec_PtrAlloc( 100 );
+    vLeaves = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+    {
+        printf( "%6d : ",      i );
+
+        Abc_MffcCollectNodes( &pObj, 1, vNodes );
+        Abc_MffcCollectLeaves( vNodes, vLeaves );
+        nNodes += Vec_PtrSize(vNodes);
+        printf( "%6d  ",      Abc_ObjId(pObj) );
+        printf( "Vol =%3d  ", Vec_PtrSize(vNodes) );
+        printf( "Cut =%3d  ", Vec_PtrSize(vLeaves) );
+        if ( Vec_PtrSize(vLeaves) < 2 )
+        {
+            printf( "\n" );
+            continue;
+        }
+
+        pNodes[0] = pObj;
+        pNodes[1] = (Abc_Obj_t *)Vec_PtrEntry( vRoots1, i );
+        pNodes[2] = (Abc_Obj_t *)Vec_PtrEntry( vRoots2, i );
+        if ( pNodes[1] == NULL || pNodes[2] == NULL )
+        {
+            printf( "\n" );
+            continue;
+        }
+        Abc_MffcCollectNodes( pNodes, 3, vNodes );
+        Abc_MffcCollectLeaves( vNodes, vLeaves );
+        nNodes2 += Vec_PtrSize(vNodes);
+        printf( "%6d  ",      Abc_ObjId(pNodes[1]) );
+        printf( "%6d  ",      Abc_ObjId(pNodes[2]) );
+        printf( "Vol =%3d  ", Vec_PtrSize(vNodes) );
+        printf( "Cut =%3d  ", Vec_PtrSize(vLeaves) );
+ 
+        printf( "%4.2f  ",    1.0 * Vec_PtrSize(vNodes)/Vec_PtrSize(vLeaves)  );
+        printf( "\n" );
+
+        // generate file
+        if ( Vec_PtrSize(vNodes) < 10 )
+            continue;
+        sprintf( pFileName, "%s_mffc%04d_%02d.blif", Abc_NtkName(pNtk), Abc_ObjId(pObj), Vec_PtrSize(vNodes) );
+        Abc_NktMffcPrint( pFileName, pNodes, 3, vNodes, vLeaves );
+    }
+    printf( "Total nodes = %d.  Root nodes = %d.  Mffc nodes = %d.  Mffc nodes2 = %d.\n", 
+        Abc_NtkNodeNum(pNtk), Vec_PtrSize(vRoots), nNodes, nNodes2 );
+    Vec_PtrFree( vNodes );
+    Vec_PtrFree( vLeaves );
+    Vec_PtrFree( vRoots );
+    Vec_PtrFree( vRoots1 );
+    Vec_PtrFree( vRoots2 );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Create the network of supernodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NktMffcTestSuper( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vRoots, * vFanins, * vFanouts, * vNodes, * vLeaves;
+    Abc_Obj_t * pObj, * pFanin; 
+    Vec_Int_t * vCounts, * vNumbers, * vSizes, * vMarks;
+    Vec_Int_t * vNode1, * vNode2;
+    int i, k, Entry, nSizes;
+    abctime clk = Abc_Clock();
+    vRoots   = Abc_NktMffcMarkRoots( pNtk, 1 );
+    vFanins  = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) );
+    vFanouts = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) );
+    vCounts  = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
+    vNode1   = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
+    vNode2   = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
+    vSizes   = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
+    vMarks   = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
+
+    // create fanins/fanouts
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+    {
+        Vec_PtrWriteEntry( vFanins,  Abc_ObjId(pObj), Vec_IntAlloc(8) );
+        Vec_PtrWriteEntry( vFanouts, Abc_ObjId(pObj), Vec_IntAlloc(8) );
+    }
+    // add fanins/fanouts
+    vNodes   = Vec_PtrAlloc( 100 );
+    vLeaves  = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+    {
+        Abc_MffcCollectNodes( &pObj, 1, vNodes );
+        Abc_MffcCollectLeaves( vNodes, vLeaves );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pFanin, k )
+        {
+            if ( !Abc_ObjIsNode(pFanin) )
+                continue;
+            Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vFanins,  Abc_ObjId(pObj)),   Abc_ObjId(pFanin) );
+            Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vFanouts, Abc_ObjId(pFanin)), Abc_ObjId(pObj) );
+            // count how many times each object is a fanin
+            Vec_IntAddToEntry( vCounts, Abc_ObjId(pFanin), 1 );
+        }
+        Vec_IntWriteEntry( vSizes, Abc_ObjId(pObj), Vec_PtrSize(vNodes) );
+    }
+
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+    {
+        Abc_MffcCollectNodes( &pObj, 1, vNodes );
+        Abc_MffcCollectLeaves( vNodes, vLeaves );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pFanin, k )
+        {
+            if ( !Abc_ObjIsNode(pFanin) )
+                continue;
+            if ( Vec_IntEntry(vCounts, Abc_ObjId(pFanin)) != 2 )
+                continue;
+            if ( Vec_IntEntry(vNode1, Abc_ObjId(pFanin)) == 0 )
+                Vec_IntWriteEntry( vNode1, Abc_ObjId(pFanin), Abc_ObjId(pObj) );
+            else //if ( Vec_IntEntry(vNode2, Abc_ObjId(pFanin)) == 0 )
+                Vec_IntWriteEntry( vNode2, Abc_ObjId(pFanin), Abc_ObjId(pObj) );
+
+            Vec_IntWriteEntry( vMarks, Abc_ObjId(pFanin), 1 );
+            Vec_IntWriteEntry( vMarks, Abc_ObjId(pObj),   1 );
+        }
+    }
+
+    // count sizes
+    nSizes = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+    {
+        if ( Vec_IntEntry( vMarks, Abc_ObjId(pObj) ) )
+            nSizes += Vec_IntEntry( vSizes, Abc_ObjId(pObj) );
+    }
+    printf( "Included = %6d.  Total = %6d. (%6.2f %%)\n", 
+        nSizes, Abc_NtkNodeNum(pNtk), 100.0 * nSizes / Abc_NtkNodeNum(pNtk) );
+
+
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+    {
+        if ( Vec_IntEntry(vCounts, Abc_ObjId(pObj)) != 2 )
+            continue;
+        printf( "%d ", Vec_IntEntry( vSizes, Abc_ObjId(pObj) ) + 
+                       Vec_IntEntry( vSizes, Vec_IntEntry(vNode1, Abc_ObjId(pObj)) ) + 
+                       Vec_IntEntry( vSizes, Vec_IntEntry(vNode2, Abc_ObjId(pObj)) ) );
+    }
+    printf( "\n" );
+
+    // print how many times they appear
+    vNumbers = Vec_IntStart( 32 );
+    Vec_IntForEachEntry( vCounts, Entry, i )
+    {
+/*
+if ( Entry == 2 )
+{
+    pObj = Abc_NtkObj( pNtk, i );
+    Abc_MffcCollectNodes( &pObj, 1, vNodes );
+    Abc_MffcCollectLeaves( vNodes, vLeaves );
+    printf( "%d(%d) ", Vec_PtrSize(vNodes), Vec_PtrSize(vLeaves) );
+}
+*/
+        if ( Entry == 0 )
+            continue;
+        if ( Entry <= 10 )
+            Vec_IntAddToEntry( vNumbers, Entry, 1 );
+        else if ( Entry <= 100 )
+            Vec_IntAddToEntry( vNumbers, 10 + Entry/10, 1 );
+        else if ( Entry < 1000 )
+            Vec_IntAddToEntry( vNumbers, 20 + Entry/100, 1 );
+        else
+            Vec_IntAddToEntry( vNumbers, 30, 1 );
+    }
+    for ( i = 1; i <= 10; i++ )
+        if ( Vec_IntEntry(vNumbers,i) )
+            printf( "       n =  %4d   %6d\n", i, Vec_IntEntry(vNumbers,i) );
+    for ( i = 11; i <= 20; i++ )
+        if ( Vec_IntEntry(vNumbers,i) )
+            printf( "%4d < n <= %4d   %6d\n", 10*(i-10),  10*(i-9),  Vec_IntEntry(vNumbers,i) );
+    for ( i = 21; i < 30; i++ )
+        if ( Vec_IntEntry(vNumbers,i) )
+            printf( "%4d < n <= %4d   %6d\n", 100*(i-20), 100*(i-19), Vec_IntEntry(vNumbers,i) );
+    if ( Vec_IntEntry(vNumbers,31) )
+    printf( "       n >  1000   %6d\n", Vec_IntEntry(vNumbers,30) );
+    printf( "Total MFFCs = %d. ", Vec_PtrSize(vRoots) );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    Vec_IntFree( vNumbers );
+    Vec_PtrFree( vNodes );
+    Vec_PtrFree( vLeaves );
+
+    // delete fanins/fanouts
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+    {
+        Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vFanins,  Abc_ObjId(pObj)) );
+        Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vFanouts, Abc_ObjId(pObj)) );
+    }
+
+    Vec_IntFree( vCounts );
+    Vec_PtrFree( vFanouts );
+    Vec_PtrFree( vFanins );
+    Vec_PtrFree( vRoots );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the leaves and the roots of the window.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NktMffCollectLeafRoot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots )
+{
+    Abc_Obj_t * pObj, * pNext;
+    int i, k;
+    // mark
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        pObj->fMarkA = 1;
+    // collect leaves
+    Vec_PtrClear( vLeaves );
+    Abc_NtkIncrementTravId( pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        Abc_ObjForEachFanin( pObj, pNext, k )
+        {
+            if ( pNext->fMarkA || Abc_NodeIsTravIdCurrent(pNext) )
+                continue;
+            Abc_NodeSetTravIdCurrent(pNext);
+            Vec_PtrPush( vLeaves, pNext );
+        }
+    // collect roots
+    Vec_PtrClear( vRoots );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        Abc_ObjForEachFanout( pObj, pNext, k )
+            if ( !pNext->fMarkA )
+            {
+                Vec_PtrPush( vRoots, pObj );
+                break;
+            }
+    }
+    // unmark
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        pObj->fMarkA = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the leaves and the roots of the window.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NktMffCollectLeafRootInt( Abc_Ntk_t * pNtk, Vec_Int_t * vNodes, Vec_Int_t * vLeaves, Vec_Int_t * vRoots )
+{
+    Abc_Obj_t * pObj, * pNext;
+    int i, k;
+    // mark
+    Abc_NtkForEachObjVec( vNodes, pNtk, pObj, i )
+        pObj->fMarkA = 1;
+    // collect leaves
+    Vec_IntClear( vLeaves );
+    Abc_NtkIncrementTravId( pNtk );
+    Abc_NtkForEachObjVec( vNodes, pNtk, pObj, i )
+        Abc_ObjForEachFanin( pObj, pNext, k )
+        {
+            if ( pNext->fMarkA || Abc_NodeIsTravIdCurrent(pNext) )
+                continue;
+            Abc_NodeSetTravIdCurrent(pNext);
+            Vec_IntPush( vLeaves, Abc_ObjId(pNext) );
+        }
+    // collect roots
+    if ( vRoots )
+    {
+        Vec_IntClear( vRoots );
+        Abc_NtkForEachObjVec( vNodes, pNtk, pObj, i )
+        {
+            Abc_ObjForEachFanout( pObj, pNext, k )
+                if ( !pNext->fMarkA )
+                {
+                    Vec_IntPush( vRoots, Abc_ObjId(pObj) );
+                    break;
+                }
+        }
+    }
+    // unmark
+    Abc_NtkForEachObjVec( vNodes, pNtk, pObj, i )
+        pObj->fMarkA = 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Create the network of supernodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NktMffcTestIdeaOne( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
+{
+    Vec_Ptr_t * vNodes, * vLeaves, * vRoots, * vVolume;
+    Vec_Ptr_t * vLeaves2, * vRoots2, * vVolume2;
+    Abc_Obj_t * pNode, * pNodeBest = pObj;
+    double Cost, CostBest = 0.0;
+    int i, k;
+    vNodes   = Vec_PtrAlloc( 100 );
+    vLeaves  = Vec_PtrAlloc( 100 );
+    vRoots   = Vec_PtrAlloc( 100 );
+    vVolume  = Vec_PtrAlloc( 100 );
+    vLeaves2 = Vec_PtrAlloc( 100 );
+    vRoots2  = Vec_PtrAlloc( 100 );
+    vVolume2 = Vec_PtrAlloc( 100 );
+printf( "\n" );
+    for ( i = 1; i <= 16; i++ )
+    {
+        Vec_PtrPush( vNodes, pNodeBest );
+        Abc_NktMffCollectLeafRoot( pNtk, vNodes, vLeaves, vRoots );
+        Abc_MffcCollectNodes( (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots), vVolume );
+
+        printf( "%2d : Node =%6d (%2d%3d)  Cost =%6.2f   ", i, Abc_ObjId(pNodeBest), 
+            Abc_ObjFaninNum(pNodeBest), Abc_ObjFanoutNum(pNodeBest), CostBest );
+        printf( "Leaf =%2d  Root =%2d  Vol =%2d\n", Vec_PtrSize(vLeaves), Vec_PtrSize(vRoots), Vec_PtrSize(vVolume) );
+
+        // try including different nodes
+        pNodeBest = NULL;
+        Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, k )
+        {
+            if ( !Abc_ObjIsNode(pNode) )
+                continue;
+            Vec_PtrPush( vNodes, pNode );
+            Abc_NktMffCollectLeafRoot( pNtk, vNodes, vLeaves2, vRoots2 );
+            Abc_MffcCollectNodes( (Abc_Obj_t **)Vec_PtrArray(vRoots2), Vec_PtrSize(vRoots2), vVolume2 );
+            Cost = 1.0 * Vec_PtrSize(vVolume2) / (Vec_PtrSize(vLeaves2) + 3 * Vec_PtrSize(vRoots2));
+            if ( pNodeBest == NULL || CostBest < Cost )
+            {
+                pNodeBest = pNode;
+                CostBest  = Cost;
+            }
+            Vec_PtrPop( vNodes );
+        }
+        Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pNode, k )
+        {
+            if ( Vec_PtrFind(vNodes, pNode) >= 0 )
+                continue;
+            if ( !Abc_ObjIsNode(pNode) )
+                continue;
+            Vec_PtrPush( vNodes, pNode );
+            Abc_NktMffCollectLeafRoot( pNtk, vNodes, vLeaves2, vRoots2 );
+            Abc_MffcCollectNodes( (Abc_Obj_t **)Vec_PtrArray(vRoots2), Vec_PtrSize(vRoots2), vVolume2 );
+            Cost = 1.0 * Vec_PtrSize(vVolume2) / (Vec_PtrSize(vLeaves2) + 3 * Vec_PtrSize(vRoots2));
+            if ( pNodeBest == NULL || CostBest < Cost )
+            {
+                pNodeBest = pNode;
+                CostBest  = Cost;
+            }
+            Vec_PtrPop( vNodes );
+        }
+        if ( pNodeBest == NULL )
+            break;
+    }
+
+    Vec_PtrFree( vNodes );
+    Vec_PtrFree( vLeaves );
+    Vec_PtrFree( vRoots );
+    Vec_PtrFree( vVolume );
+    Vec_PtrFree( vLeaves2 );
+    Vec_PtrFree( vRoots2 );
+    Vec_PtrFree( vVolume2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the network of supernodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NktMffcTestIdea( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj; 
+    int i;
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        if ( Abc_ObjIsNode(pObj) && Abc_ObjId(pObj) % 100 == 0 )
+            Abc_NktMffcTestIdeaOne( pNtk, pObj );
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates MFFCs and their fanins/fanouts/volumes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NktMffcDerive( Abc_Ntk_t * pNtk, Vec_Ptr_t ** pvFanins, Vec_Ptr_t ** pvFanouts, Vec_Ptr_t ** pvVolumes )
+{
+    Vec_Ptr_t * vRoots, * vFanins, * vFanouts, * vVolumes, * vNodes, * vLeaves;
+    Abc_Obj_t * pObj, * pFanin; 
+    int i, k;
+    abctime clk = Abc_Clock();
+    // create roots
+    vRoots   = Abc_NktMffcMarkRoots( pNtk, 0 );
+    // create fanins/fanouts/volumes
+    vFanins  = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) );
+    vFanouts = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) );
+    vVolumes = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+    {
+        Vec_PtrWriteEntry( vFanins,  Abc_ObjId(pObj), Vec_IntAlloc(8) );
+        Vec_PtrWriteEntry( vFanouts, Abc_ObjId(pObj), Vec_IntAlloc(8) );
+        Vec_PtrWriteEntry( vVolumes, Abc_ObjId(pObj), Vec_IntAlloc(8) );
+    }
+    // add fanins/fanouts
+    vNodes   = Vec_PtrAlloc( 100 );
+    vLeaves  = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+    {
+        if ( Abc_ObjIsCi(pObj) )
+            continue;
+        Abc_MffcCollectNodes( &pObj, 1, vNodes );
+        Abc_MffcCollectLeaves( vNodes, vLeaves );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pFanin, k )
+        {
+            Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vFanins,  Abc_ObjId(pObj)),   Abc_ObjId(pFanin) );
+            Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vFanouts, Abc_ObjId(pFanin)), Abc_ObjId(pObj) );
+        }
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pFanin, k )
+            Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vVolumes, Abc_ObjId(pObj)),   Abc_ObjId(pFanin) );
+    }
+
+    Vec_PtrFree( vNodes );
+    Vec_PtrFree( vLeaves );
+    // sort
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+    {
+        Vec_IntSort( (Vec_Int_t *)Vec_PtrEntry(vFanins,  Abc_ObjId(pObj)), 0 );
+        Vec_IntSort( (Vec_Int_t *)Vec_PtrEntry(vFanouts, Abc_ObjId(pObj)), 0 );
+    }
+    // return
+    *pvFanins  = vFanins;
+    *pvFanouts = vFanouts;
+    *pvVolumes = vVolumes;
+    return vRoots;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees MFFCs and their fanins/fanouts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NktMffcFree( Vec_Ptr_t * vRoots, Vec_Ptr_t * vFanins, Vec_Ptr_t * vFanouts, Vec_Ptr_t * vVolumes )
+{
+    Abc_Obj_t * pObj; 
+    int i;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+    {
+        Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vFanins,  Abc_ObjId(pObj)) );
+        Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vFanouts, Abc_ObjId(pObj)) );
+        Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vVolumes, Abc_ObjId(pObj)) );
+    }
+    Vec_PtrFree( vVolumes );
+    Vec_PtrFree( vFanouts );
+    Vec_PtrFree( vFanins );
+    Vec_PtrFree( vRoots );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the cost of two supports.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+double Abc_NktMffcCostTwo( Vec_Int_t * vSupp1, Vec_Int_t * vSupp2, int Volume, int Limit )
+{
+    int nCommon = Vec_IntTwoCountCommon( vSupp1, vSupp2 );
+//printf( "s1=%2d s2=%2d c=%2d v=%2d   ", Vec_IntSize(vSupp1), Vec_IntSize(vSupp2), nCommon, Volume );
+    if ( Vec_IntSize(vSupp1) + Vec_IntSize(vSupp2) - nCommon > Limit )
+        return (double)-ABC_INFINITY;
+    return 0.6 * nCommon - 1.2 * Vec_IntSize(vSupp2) + 0.8 * Volume;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns support of the group.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NktMffcSupport( Vec_Ptr_t * vThis, Vec_Ptr_t * vFanins )
+{
+    Vec_Int_t * vIns, * vIns2, * vTemp;
+    Abc_Obj_t * pObj;
+    int i;
+    vIns = Vec_IntAlloc( 100 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vThis, pObj, i )
+    {
+        vIns2 = (Vec_Int_t *)Vec_PtrEntry( vFanins, Abc_ObjId(pObj) );
+        vIns  = Vec_IntTwoMerge( vTemp = vIns, vIns2 );
+        Vec_IntFree( vTemp );
+    }
+    return vIns;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the best merger for the cluster of given node (pPivot).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NktMffcFindBest( Abc_Ntk_t * pNtk, Vec_Int_t * vMarks, Vec_Int_t * vIns, Vec_Ptr_t * vFanins, Vec_Ptr_t * vFanouts, Vec_Ptr_t * vVolumes, int Limit )
+{
+    Vec_Int_t * vIns2, * vOuts, * vOuts2, * vTemp;
+    Abc_Obj_t * pPivot2, * pObj, * pObjBest = NULL;
+    double Cost, CostBest = (double)-ABC_INFINITY;
+    int i, Volume;
+    // collect the fanouts of the fanins
+    vOuts = Vec_IntAlloc( 100 );
+    Abc_NtkForEachObjVec( vIns, pNtk, pObj, i )
+    {
+        vOuts2 = (Vec_Int_t *)Vec_PtrEntry( vFanouts, Abc_ObjId(pObj) );
+        if ( Vec_IntSize(vOuts2) > 16 )
+            continue;
+        vOuts  = Vec_IntTwoMerge( vTemp = vOuts, vOuts2 );
+        Vec_IntFree( vTemp );
+    }
+    // check the pairs
+    Abc_NtkForEachObjVec( vOuts, pNtk, pPivot2, i )
+    {       
+        if ( Vec_IntEntry(vMarks, Abc_ObjId(pPivot2)) == 0 )
+            continue;
+        vIns2  = (Vec_Int_t *)Vec_PtrEntry( vFanins, Abc_ObjId(pPivot2) );
+        Volume = Vec_IntSize((Vec_Int_t *)Vec_PtrEntry(vVolumes, Abc_ObjId(pPivot2)));
+        Cost   = Abc_NktMffcCostTwo( vIns, vIns2, Volume, Limit );
+//printf( "%5d  %2d\n", Abc_ObjId(pPivot2), Cost  );
+        if ( Cost == (double)-ABC_INFINITY )
+            continue;
+        if ( pObjBest == NULL || CostBest < Cost )
+        {
+            pObjBest = pPivot2;
+            CostBest = Cost;
+        }
+    }    
+//printf( "Choosing %d\n", pObjBest->Id );
+    Vec_IntFree( vOuts );
+    return pObjBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Processes one cluster.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NktMffcSaveOne( Vec_Ptr_t * vThis, Vec_Ptr_t * vVolumes )
+{
+    Vec_Int_t * vVolume, * vResult;
+    Abc_Obj_t * pObj;
+    int i, k, Entry;
+    vResult = Vec_IntAlloc( 100 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vThis, pObj, i )
+    {
+        vVolume = (Vec_Int_t *)Vec_PtrEntry( vVolumes, Abc_ObjId(pObj) );
+        Vec_IntForEachEntry( vVolume, Entry, k )
+            Vec_IntPush( vResult, Entry );
+    }
+    return vResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure used for sorting the nodes in decreasing order of levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCompareVolumeDecrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 )
+{
+    int Diff = Abc_ObjRegular(*pp1)->iTemp - Abc_ObjRegular(*pp2)->iTemp;
+    if ( Diff > 0 )
+        return -1;
+    if ( Diff < 0 ) 
+        return 1;
+    Diff = Abc_ObjRegular(*pp1)->Id - Abc_ObjRegular(*pp2)->Id;
+    if ( Diff > 0 )
+        return -1;
+    if ( Diff < 0 ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the network of supernodes.]
+
+  Description [Returns array of interger arrays of IDs of nodes
+  included in a disjoint structural decomposition of the network.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NktMffcServer( Abc_Ntk_t * pNtk, int nInMax, int nOutMax )
+{
+    Vec_Ptr_t * vResult, * vThis;
+    Vec_Ptr_t * vPivots, * vFanins, * vFanouts, * vVolumes;
+    Vec_Int_t * vLeaves, * vMarks;
+    Abc_Obj_t * pObj, * pObj2;
+    int i, k;
+    assert( nOutMax >= 1 && nOutMax <= 32 );
+    vResult = Vec_PtrAlloc( 100 );
+    // create fanins/fanouts
+    vPivots = Abc_NktMffcDerive( pNtk, &vFanins, &vFanouts, &vVolumes );
+    // sort by their MFFC size
+    Vec_PtrForEachEntry( Abc_Obj_t *, vPivots, pObj, i )
+        pObj->iTemp = Vec_IntSize((Vec_Int_t *)Vec_PtrEntry(vVolumes, Abc_ObjId(pObj)));
+    Vec_PtrSort( vPivots, (int (*)(void))Abc_NodeCompareVolumeDecrease ); 
+    // create marks
+    vMarks = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vPivots, pObj, i )
+        if ( Abc_ObjIsNode(pObj) && Vec_IntSize((Vec_Int_t *)Vec_PtrEntry(vVolumes, Abc_ObjId(pObj))) > 1 )
+            Vec_IntWriteEntry( vMarks, Abc_ObjId(pObj), 1 );
+    // consider nodes in the order of the marks
+    vThis = Vec_PtrAlloc( 10 );
+//    while ( 1 )
+    Vec_PtrForEachEntry( Abc_Obj_t *, vPivots, pObj, i )
+    {
+//        pObj = Abc_NtkObj( pNtk, 589 );
+        if ( Vec_IntEntry(vMarks, Abc_ObjId(pObj)) == 0 )
+            continue;
+        // start the set
+        Vec_PtrClear( vThis );        
+        Vec_PtrPush( vThis, pObj );
+        Vec_IntWriteEntry( vMarks, Abc_ObjId(pObj), 0 );
+        // quit if exceeded the limit
+        vLeaves = (Vec_Int_t *)Vec_PtrEntry( vFanins, Abc_ObjId(pObj) );
+        if ( Vec_IntSize(vLeaves) > nInMax )
+        {
+            Vec_PtrPush( vResult, Abc_NktMffcSaveOne(vThis, vVolumes) );
+            continue;
+        }
+        // try adding one node at a time
+        for ( k = 1; k < nOutMax; k++ )
+        {
+            // quit if exceeded the limit
+            vLeaves = Abc_NktMffcSupport( vThis, vFanins );
+            assert( Vec_IntSize(vLeaves) <= nInMax );
+            pObj2 = Abc_NktMffcFindBest( pNtk, vMarks, vLeaves, vFanins, vFanouts, vVolumes, nInMax );
+            Vec_IntFree( vLeaves );
+            // quit if there is no extension
+            if ( pObj2 == NULL )
+                break;
+            Vec_PtrPush( vThis, pObj2 );
+            Vec_IntWriteEntry( vMarks, Abc_ObjId(pObj2), 0 );
+        }
+        Vec_PtrPush( vResult, Abc_NktMffcSaveOne(vThis, vVolumes) );
+//        break;
+    }
+    Vec_PtrFree( vThis );
+    Vec_IntFree( vMarks );
+    // delele fanins/outputs
+    Abc_NktMffcFree( vPivots, vFanins, vFanouts, vVolumes );
+    return vResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Testbench.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NktMffcServerTest( Abc_Ntk_t * pNtk )
+{
+    char pFileName[1000];
+    Vec_Ptr_t * vGlobs;
+    Vec_Int_t * vGlob, * vLeaves, * vRoots;
+    double Cost, CostAll = 0.0;
+    int i, k, Entry, nNodes = 0;
+    abctime clk = Abc_Clock();
+    vGlobs  = Abc_NktMffcServer( pNtk, 18, 3 );
+    vLeaves = Vec_IntAlloc( 100 );
+    vRoots  = Vec_IntAlloc( 100 );
+    Vec_PtrForEachEntry( Vec_Int_t *, vGlobs, vGlob, i )
+    {
+        nNodes += Vec_IntSize(vGlob);
+        Abc_NktMffCollectLeafRootInt( pNtk, vGlob, vLeaves, vRoots );
+        if ( Vec_IntSize(vGlob) <= Vec_IntSize(vRoots) )
+            continue;
+        Cost = 1.0 * Vec_IntSize(vGlob)/(Vec_IntSize(vLeaves) + Vec_IntSize(vRoots));
+        CostAll += Cost;
+        if ( Cost < 0.5 )
+            continue;
+
+        printf( "%6d : Root =%3d. Leaf =%3d. Node =%4d. ", 
+            i, Vec_IntSize(vRoots), Vec_IntSize(vLeaves), Vec_IntSize(vGlob) );
+        printf( "Cost =%6.2f     ", Cost );
+        Vec_IntForEachEntry( vRoots, Entry, k )
+            printf( "%d ", Entry );
+        printf( "\n" );
+
+        sprintf( pFileName, "%sc%04di%02dn%02d.blif", Abc_NtkName(pNtk), i, Vec_IntSize(vLeaves), Vec_IntSize(vGlob) );
+        Abc_NktMffcPrintInt( pFileName, pNtk, vRoots, vGlob, vLeaves );
+    }
+    Vec_IntFree( vLeaves );
+    Vec_IntFree( vRoots );
+    Vec_PtrForEachEntry( Vec_Int_t *, vGlobs, vGlob, i )
+        Vec_IntFree( vGlob );
+    Vec_PtrFree( vGlobs );
+    printf( "Total = %6d.  Nodes = %6d.  ", Abc_NtkNodeNum(pNtk), nNodes );
+    printf( "Cost = %6.2f  ", CostAll );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+
+ABC_NAMESPACE_IMPL_END
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/abc-build/src/base/abci/abcMfs.c b/abc-build/src/base/abci/abcMfs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcMfs.c
@@ -0,0 +1,483 @@
+/**CFile****************************************************************
+
+  FileName    [abcMfs.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Optimization with don't-cares.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcMfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "bool/kit/kit.h"
+#include "opt/sfm/sfm.h"
+#include "base/io/ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkAssignIDs( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj;
+    int i;
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    Abc_NtkCleanCopy( pNtk );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->iTemp = i;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        pObj->iTemp = Abc_NtkCiNum(pNtk) + i;
+//printf( "%d->%d ", pObj->Id, pObj->iTemp );
+    }
+//printf( "\n" );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        pObj->iTemp = Abc_NtkCiNum(pNtk) + Vec_PtrSize(vNodes) + i;
+    return vNodes;
+}
+Vec_Ptr_t * Abc_NtkAssignIDs2( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkCleanCopy( pNtk );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->iTemp = i;
+    vNodes = Vec_PtrAlloc( Abc_NtkNodeNum(pNtk) );
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        pObj->iTemp = Abc_NtkCiNum(pNtk) + Vec_PtrSize(vNodes);
+        Vec_PtrPush( vNodes, pObj );
+    }
+    assert( Vec_PtrSize(vNodes) == Abc_NtkNodeNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        pObj->iTemp = Abc_NtkCiNum(pNtk) + Vec_PtrSize(vNodes) + i;
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Extracts information about the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Sfm_Ntk_t * Abc_NtkExtractMfs( Abc_Ntk_t * pNtk, int nFirstFixed )
+{
+    Vec_Ptr_t * vNodes;
+    Vec_Wec_t * vFanins;
+    Vec_Str_t * vFixed;
+    Vec_Wrd_t * vTruths;
+    Vec_Int_t * vArray;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k, nObjs;
+    vNodes  = nFirstFixed ? Abc_NtkAssignIDs2(pNtk) : Abc_NtkAssignIDs(pNtk);
+    nObjs   = Abc_NtkCiNum(pNtk) + Vec_PtrSize(vNodes) + Abc_NtkCoNum(pNtk);
+    vFanins = Vec_WecStart( nObjs );
+    vFixed  = Vec_StrStart( nObjs );
+    vTruths = Vec_WrdStart( nObjs );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        word uTruth = Abc_SopToTruth((char *)pObj->pData, Abc_ObjFaninNum(pObj));
+        Vec_WrdWriteEntry( vTruths, pObj->iTemp, uTruth );
+        if ( uTruth == 0 || ~uTruth == 0 )
+            continue;
+        vArray = Vec_WecEntry( vFanins, pObj->iTemp );
+        Vec_IntGrow( vArray, Abc_ObjFaninNum(pObj) );
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Vec_IntPush( vArray, pFanin->iTemp );
+    }
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        vArray = Vec_WecEntry( vFanins, pObj->iTemp );
+        Vec_IntGrow( vArray, Abc_ObjFaninNum(pObj) );
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Vec_IntPush( vArray, pFanin->iTemp );
+    }
+    Vec_PtrFree( vNodes );
+    for ( i = Abc_NtkCiNum(pNtk); i < Abc_NtkCiNum(pNtk) + nFirstFixed; i++ )
+        Vec_StrWriteEntry( vFixed, i, (char)1 );
+    // update fixed
+    assert( nFirstFixed >= 0 && nFirstFixed < Abc_NtkNodeNum(pNtk) );
+//    for ( i = Abc_NtkCiNum(pNtk); i + Abc_NtkCoNum(pNtk) < Abc_NtkObjNum(pNtk); i++ )
+//        if ( rand() % 10 == 0 )
+//            Vec_StrWriteEntry( vFixed, i, (char)1 );
+    return Sfm_NtkConstruct( vFanins, Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), vFixed, NULL, vTruths );
+}
+Sfm_Ntk_t * Abc_NtkExtractMfs2( Abc_Ntk_t * pNtk, int iPivot )
+{
+    Vec_Ptr_t * vNodes;
+    Vec_Wec_t * vFanins;
+    Vec_Str_t * vFixed;
+    Vec_Wrd_t * vTruths;
+    Vec_Int_t * vArray;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k, nObjs;
+    vNodes  = Abc_NtkAssignIDs2(pNtk);
+    nObjs   = Abc_NtkCiNum(pNtk) + Vec_PtrSize(vNodes) + Abc_NtkCoNum(pNtk);
+    vFanins = Vec_WecStart( nObjs );
+    vFixed  = Vec_StrStart( nObjs );
+    vTruths = Vec_WrdStart( nObjs );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        word uTruth = Abc_SopToTruth((char *)pObj->pData, Abc_ObjFaninNum(pObj));
+        Vec_WrdWriteEntry( vTruths, pObj->iTemp, uTruth );
+        if ( uTruth == 0 || ~uTruth == 0 )
+            continue;
+        vArray = Vec_WecEntry( vFanins, pObj->iTemp );
+        Vec_IntGrow( vArray, Abc_ObjFaninNum(pObj) );
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Vec_IntPush( vArray, pFanin->iTemp );
+    }
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        vArray = Vec_WecEntry( vFanins, pObj->iTemp );
+        Vec_IntGrow( vArray, Abc_ObjFaninNum(pObj) );
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Vec_IntPush( vArray, pFanin->iTemp );
+    }
+    Vec_PtrFree( vNodes );
+    // set fixed attributes
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        if ( i >= iPivot )
+            Vec_StrWriteEntry( vFixed, pObj->iTemp, (char)1 );
+    return Sfm_NtkConstruct( vFanins, Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), vFixed, NULL, vTruths );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkInsertMfs( Abc_Ntk_t * pNtk, Sfm_Ntk_t * p )
+{
+    Vec_Int_t * vCover, * vMap, * vArray;
+    Abc_Obj_t * pNode;
+    word * pTruth;
+    int i, k, Fanin;
+    // map new IDs into old nodes
+    vMap = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        Vec_IntWriteEntry( vMap, pNode->iTemp, Abc_ObjId(pNode) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        if ( pNode->iTemp > 0 )
+            Vec_IntWriteEntry( vMap, pNode->iTemp, Abc_ObjId(pNode) );
+    // remove old fanins
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        if ( !Sfm_NodeReadFixed(p, pNode->iTemp) )
+            Abc_ObjRemoveFanins( pNode );
+    // create new fanins
+    vCover = Vec_IntAlloc( 1 << 16 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        if ( pNode->iTemp == 0 || Sfm_NodeReadFixed(p, pNode->iTemp) )
+            continue;
+        if ( !Sfm_NodeReadUsed(p, pNode->iTemp) )
+        {
+            Abc_NtkDeleteObj( pNode );
+            continue;
+        }
+        // update fanins
+        vArray = Sfm_NodeReadFanins( p, pNode->iTemp );
+        Vec_IntForEachEntry( vArray, Fanin, k )
+            Abc_ObjAddFanin( pNode, Abc_NtkObj(pNtk, Vec_IntEntry(vMap, Fanin)) );
+        // update function
+        pTruth = Sfm_NodeReadTruth( p, pNode->iTemp );
+        if ( pTruth[0] == 0 )
+            pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 0\n" );
+        else if ( ~pTruth[0] == 0 )
+            pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 1\n" );
+        else
+        {
+            int RetValue = Kit_TruthIsop( (unsigned *)pTruth, Vec_IntSize(vArray), vCover, 1 );
+            assert( Vec_IntSize(vArray) > 0 );
+            assert( RetValue == 0 || RetValue == 1 );
+            pNode->pData = Abc_SopCreateFromIsop( (Mem_Flex_t *)pNtk->pManFunc, Vec_IntSize(vArray), vCover );
+            if ( RetValue )
+                Abc_SopComplement( (char *)pNode->pData );
+        }
+        assert( Abc_SopGetVarNum((char *)pNode->pData) == Vec_IntSize(vArray) );
+    }
+    Vec_IntFree( vCover );
+    Vec_IntFree( vMap );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkPerformMfs( Abc_Ntk_t * pNtk, Sfm_Par_t * pPars )
+{
+    Sfm_Ntk_t * p;
+    int nFaninMax, nNodes;
+    assert( Abc_NtkIsLogic(pNtk) );
+    // count fanouts
+    nFaninMax = Abc_NtkGetFaninMax( pNtk );
+    if ( nFaninMax > 6 )
+    {
+        Abc_Print( 1, "Currently \"mfs\" cannot process the network containing nodes with more than 6 fanins.\n" );
+        return 0;
+    }
+    if ( !Abc_NtkHasSop(pNtk) )
+        Abc_NtkToSop( pNtk, 0 );
+    // collect information
+    p = Abc_NtkExtractMfs( pNtk, pPars->nFirstFixed );
+    // perform optimization
+    nNodes = Sfm_NtkPerform( p, pPars );
+    // call the fast extract procedure
+    if ( nNodes == 0 )
+    {
+//        Abc_Print( 1, "The network is not changed by \"mfs\".\n" );
+    }
+    else
+    {
+        Abc_NtkInsertMfs( pNtk, p );
+        if( pPars->fVerbose )
+            Abc_Print( 1, "The network has %d nodes changed by \"mfs\".\n", nNodes );
+    }
+    Sfm_NtkFree( p );
+    return 1;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Unrolls logic network while dropping some next-state functions.]
+
+  Description [Returns the unrolled network.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkUnrollAndDrop( Abc_Ntk_t * p, int nFrames, int nFramesAdd, Vec_Int_t * vFlops, int * piPivot )
+{
+    Abc_Ntk_t * pNtk; 
+    Abc_Obj_t * pFanin, * pNode;
+    Vec_Ptr_t * vNodes;
+    int i, k, f, Value;
+    assert( nFramesAdd >= 0 );
+    assert( Abc_NtkIsLogic(p) );
+    assert( Vec_IntSize(vFlops) == Abc_NtkLatchNum(p) );
+    *piPivot = -1;
+    // start the network
+    pNtk = Abc_NtkAlloc( p->ntkType, p->ntkFunc, 1 );
+    pNtk->pName = Extra_UtilStrsav(Abc_NtkName(p));
+    // add CIs for the new network
+    Abc_NtkForEachCi( p, pNode, i )
+        pNode->pCopy = Abc_NtkCreatePi( pNtk );
+    // iterate unrolling
+    vNodes = Abc_NtkDfs( p, 0 );
+    for ( f = 0; f <= nFrames + nFramesAdd; f++ )
+    {
+        if ( f > 0 )
+        {
+            Abc_NtkForEachPi( p, pNode, i )
+                pNode->pCopy = Abc_NtkCreatePi( pNtk );
+        }
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        {
+            Abc_NtkDupObj( pNtk, pNode, 0 );
+            Abc_ObjForEachFanin( pNode, pFanin, k )
+                Abc_ObjAddFanin( pNode->pCopy, pFanin->pCopy );
+        }
+        Abc_NtkForEachCo( p, pNode, i )
+            pNode->pCopy = Abc_ObjFanin0(pNode)->pCopy;
+        Abc_NtkForEachPo( p, pNode, i )
+            Abc_ObjAddFanin( Abc_NtkCreatePo(pNtk), pNode->pCopy );
+        // add buffers
+        if ( f == 0 )
+        {
+            *piPivot = Abc_NtkObjNum(pNtk);
+//            Abc_NtkForEachLatchInput( p, pNode, i )
+//                pNode->pCopy = Abc_NtkCreateNodeBuf( pNtk, pNode->pCopy );
+        }
+        // transfer to flop outputs
+        Abc_NtkForEachLatch( p, pNode, i )
+            Abc_ObjFanout0(pNode)->pCopy = Abc_ObjFanin0(pNode)->pCopy;
+        // add final POs
+        if ( f > nFramesAdd )
+        {
+            Vec_IntForEachEntry( vFlops, Value, i )
+            {
+                if ( Value == 0 )
+                    continue;
+                pNode = Abc_NtkCo( p, Abc_NtkPoNum(p) + i );
+                Abc_ObjAddFanin( Abc_NtkCreatePo(pNtk), pNode->pCopy );
+            }
+        }
+    }
+    Vec_PtrFree( vNodes );
+    Abc_NtkAddDummyPiNames( pNtk );
+    Abc_NtkAddDummyPoNames( pNtk );
+    // perform combinational cleanup
+    Abc_NtkCleanup( pNtk, 0 );
+    if ( !Abc_NtkCheck( pNtk ) )
+        fprintf( stdout, "Abc_NtkCreateFromNode(): Network check has failed.\n" );
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the original network to include optimized nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkReinsertNodes( Abc_Ntk_t * p, Abc_Ntk_t * pNtk, int iPivot )
+{
+    Abc_Obj_t * pNode, * pNodeNew, * pFaninNew;
+    Vec_Ptr_t * vNodes;
+    int i, k;
+    assert( Abc_NtkIsLogic(p) );
+    assert( Abc_NtkCiNum(p) <= Abc_NtkCiNum(pNtk) );
+    vNodes = Abc_NtkDfs( p, 0 );
+    // clean old network
+    Abc_NtkCleanCopy( p );
+    Abc_NtkForEachNode( p, pNode, i )
+    {
+        Abc_ObjRemoveFanins( pNode );
+        pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pManFunc, (char *)" 0\n" );
+    }
+    // map CIs
+    Abc_NtkForEachCi( p, pNode, i )
+        Abc_NtkCi(pNtk, i)->pCopy = pNode;
+    // map internal nodes
+    assert( Vec_PtrSize(vNodes) + Abc_NtkCiNum(p) + Abc_NtkPoNum(p) == iPivot );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        pNodeNew = Abc_NtkObj( pNtk, Abc_NtkCiNum(p) + i );
+        if ( pNodeNew == NULL )
+            continue;
+        pNodeNew->pCopy = pNode;
+    }
+    // connect internal nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        pNodeNew = Abc_NtkObj( pNtk, Abc_NtkCiNum(p) + i );
+        if ( pNodeNew == NULL )
+            continue;
+        assert( pNodeNew->pCopy == pNode );
+        Abc_ObjForEachFanin( pNodeNew, pFaninNew, k )
+            Abc_ObjAddFanin( pNodeNew->pCopy, pFaninNew->pCopy );
+        pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pManFunc, (char *)pNodeNew->pData );
+    }
+    Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs MFS for the unrolled network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsAfterICheck( Abc_Ntk_t * p, int nFrames, int nFramesAdd, Vec_Int_t * vFlops, Sfm_Par_t * pPars )
+{
+    Sfm_Ntk_t * pp;
+    int nFaninMax, nNodes;
+    Abc_Ntk_t * pNtk;
+    int iPivot;
+    assert( Abc_NtkIsLogic(p) );
+    // count fanouts
+    nFaninMax = Abc_NtkGetFaninMax( p );
+    if ( nFaninMax > 6 )
+    {
+        Abc_Print( 1, "Currently \"mfs\" cannot process the network containing nodes with more than 6 fanins.\n" );
+        return 0;
+    }
+    if ( !Abc_NtkHasSop(p) )
+        Abc_NtkToSop( p, 0 );
+    // derive unfolded network
+    pNtk = Abc_NtkUnrollAndDrop( p, nFrames, nFramesAdd, vFlops, &iPivot );
+    Io_WriteBlifLogic( pNtk, "unroll_dump.blif", 0 );
+    // collect information
+    pp = Abc_NtkExtractMfs2( pNtk, iPivot );
+    // perform optimization
+    nNodes = Sfm_NtkPerform( pp, pPars );
+    // call the fast extract procedure
+    if ( nNodes == 0 )
+    {
+//        Abc_Print( 1, "The network is not changed by \"mfs\".\n" );
+    }
+    else
+    {
+        Abc_NtkInsertMfs( pNtk, pp );
+        if( pPars->fVerbose )
+            Abc_Print( 1, "The network has %d nodes changed by \"mfs\".\n", nNodes );
+        Abc_NtkReinsertNodes( p, pNtk, iPivot );
+    }
+    Abc_NtkDelete( pNtk );
+    Sfm_NtkFree( pp );
+    // perform final sweep
+    Abc_NtkSweep( p, 0 );
+    if ( !Abc_NtkHasSop(p) )
+        Abc_NtkToSop( p, 0 );
+    return 1;
+
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcMini.c b/abc-build/src/base/abci/abcMini.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcMini.c
@@ -0,0 +1,227 @@
+/**CFile****************************************************************
+
+  FileName    [abcMini.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Interface to the minimalistic AIG package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcMini.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/main.h"
+#include "aig/miniaig/miniaig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from the AIG manager into ABC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFanin0Copy( Abc_Ntk_t * pNtk, Vec_Int_t * vCopies, Mini_Aig_t * p, int Id )
+{
+    int Lit = Mini_AigNodeFanin0( p, Id );
+    int AbcLit = Abc_LitNotCond( Vec_IntEntry(vCopies, Abc_Lit2Var(Lit)), Abc_LitIsCompl(Lit) );
+    return Abc_ObjFromLit( pNtk, AbcLit );
+}
+Abc_Obj_t * Abc_NodeFanin1Copy( Abc_Ntk_t * pNtk, Vec_Int_t * vCopies, Mini_Aig_t * p, int Id )
+{
+    int Lit = Mini_AigNodeFanin1( p, Id );
+    int AbcLit = Abc_LitNotCond( Vec_IntEntry(vCopies, Abc_Lit2Var(Lit)), Abc_LitIsCompl(Lit) );
+    return Abc_ObjFromLit( pNtk, AbcLit );
+}
+Abc_Ntk_t * Abc_NtkFromMiniAig( Mini_Aig_t * p )
+{
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pObj;
+    Vec_Int_t * vCopies;
+    int i, nNodes;
+    // get the number of nodes
+    nNodes = Mini_AigNodeNum(p);
+    // create ABC network
+    pNtk = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    pNtk->pName = Abc_UtilStrsav( "MiniAig" );
+    // create mapping from MiniAIG objects into ABC objects
+    vCopies = Vec_IntAlloc( nNodes );
+    Vec_IntPush( vCopies, Abc_LitNot(Abc_ObjToLit(Abc_AigConst1(pNtk))) );
+    // iterate through the objects
+    for ( i = 1; i < nNodes; i++ )
+    {
+        if ( Mini_AigNodeIsPi( p, i ) )
+            pObj = Abc_NtkCreatePi(pNtk);
+        else if ( Mini_AigNodeIsPo( p, i ) )
+            Abc_ObjAddFanin( (pObj = Abc_NtkCreatePo(pNtk)), Abc_NodeFanin0Copy(pNtk, vCopies, p, i) );
+        else if ( Mini_AigNodeIsAnd( p, i ) )
+            pObj = Abc_AigAnd((Abc_Aig_t *)pNtk->pManFunc, Abc_NodeFanin0Copy(pNtk, vCopies, p, i), Abc_NodeFanin1Copy(pNtk, vCopies, p, i));
+        else assert( 0 );
+        Vec_IntPush( vCopies, Abc_ObjToLit(pObj) );
+    }
+    assert( Vec_IntSize(vCopies) == nNodes );
+    Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc );
+    Vec_IntFree( vCopies );
+    Abc_NtkAddDummyPiNames( pNtk );
+    Abc_NtkAddDummyPoNames( pNtk );
+    if ( !Abc_NtkCheck( pNtk ) )
+        fprintf( stdout, "Abc_NtkFromMini(): Network check has failed.\n" );
+    // add latches
+    if ( Mini_AigRegNum(p) > 0 )
+    {
+        extern Abc_Ntk_t * Abc_NtkRestrashWithLatches( Abc_Ntk_t * pNtk, int nLatches );
+        Abc_Ntk_t * pTemp;
+        pNtk = Abc_NtkRestrashWithLatches( pTemp = pNtk, Mini_AigRegNum(p) );
+        Abc_NtkDelete( pTemp );
+    }
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from ABC into the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeFanin0Copy2( Abc_Obj_t * pObj )
+{
+    return Abc_LitNotCond( Abc_ObjFanin0(pObj)->iTemp, Abc_ObjFaninC0(pObj) );
+}
+int Abc_NodeFanin1Copy2( Abc_Obj_t * pObj )
+{
+    return Abc_LitNotCond( Abc_ObjFanin1(pObj)->iTemp, Abc_ObjFaninC1(pObj) );
+}
+Mini_Aig_t * Abc_NtkToMiniAig( Abc_Ntk_t * pNtk )
+{
+    Mini_Aig_t * p;
+    Abc_Obj_t * pObj;
+    int i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // create the manager
+    p = Mini_AigStart();
+    // create mapping from MiniAIG into ABC objects
+    Abc_NtkCleanCopy( pNtk );
+    Abc_AigConst1(pNtk)->iTemp = Mini_AigLitConst1();
+    // create primary inputs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->iTemp = Mini_AigCreatePi(p);
+    // create internal nodes
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        pObj->iTemp = Mini_AigAnd( p, Abc_NodeFanin0Copy2(pObj), Abc_NodeFanin1Copy2(pObj) );
+    // create primary outputs
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        pObj->iTemp = Mini_AigCreatePo( p, Abc_NodeFanin0Copy2(pObj) );
+    // set registers
+    Mini_AigSetRegNum( p, Abc_NtkLatchNum(pNtk) );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedures to update internal ABC network using AIG node array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkInputMiniAig( Abc_Frame_t * pAbc, void * p )
+{
+    Abc_Ntk_t * pNtk;
+    if ( pAbc == NULL )
+        printf( "ABC framework is not initialized by calling Abc_Start()\n" );
+    pNtk = Abc_NtkFromMiniAig( (Mini_Aig_t *)p );
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+//    Abc_NtkDelete( pNtk );
+}
+void * Abc_NtkOutputMiniAig( Abc_Frame_t * pAbc )
+{
+    Abc_Ntk_t * pNtk;
+    if ( pAbc == NULL )
+        printf( "ABC framework is not initialized by calling Abc_Start()\n" );
+    pNtk = Abc_FrameReadNtk( pAbc );
+    if ( pNtk == NULL )
+        printf( "Current network in ABC framework is not defined.\n" );
+    return Abc_NtkToMiniAig( pNtk );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Testing the above code.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMiniAigTest( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew;
+    Mini_Aig_t * p;
+    p = Abc_NtkToMiniAig( pNtk );
+    pNtkNew = Abc_NtkFromMiniAig( p );
+    Mini_AigStop( p );
+    Abc_NtkPrintStats( pNtkNew, 0, 0, 0, 0, 0, 0, 0, 0 );
+    Abc_NtkDelete( pNtkNew );
+
+    // test dumping
+    p = Abc_NtkToMiniAig( pNtk );
+    Mini_AigDump( p, "miniaig.data" );
+    Mini_AigPrintStats( p );
+    Mini_AigStop( p );
+
+    p = Mini_AigLoad( "miniaig.data" );
+    Mini_AigPrintStats( p );
+    Mini_AigStop( p );
+}
+
+/*
+    if ( pNtk )
+    {
+        extern void Abc_NtkMiniAigTest( Abc_Ntk_t * pNtk );
+        Abc_NtkMiniAigTest( pNtk );
+
+    }
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcMiter.c b/abc-build/src/base/abci/abcMiter.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcMiter.c
@@ -0,0 +1,1196 @@
+/**CFile****************************************************************
+
+  FileName    [abcMiter.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Procedures to derive the miter of two circuits.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcMiter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize, int fImplic, int fMulti );
+static void        Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize, int fMulti );
+static void        Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter );
+static void        Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize, int fImplic, int fMulti );
+static void        Abc_NtkAddFrame( Abc_Ntk_t * pNetNew, Abc_Ntk_t * pNet, int iFrame );
+
+// to be exported 
+typedef void (*AddFrameMapping)( Abc_Obj_t*, Abc_Obj_t*, int, void*);
+extern Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFrameMapping addFrameMapping, void* arg );
+static void        Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the miter of two networks.]
+
+  Description [Preprocesses the networks to make sure that they are strashed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize, int fImplic, int fMulti )
+{
+    Abc_Ntk_t * pTemp = NULL;
+    int fRemove1, fRemove2;
+    assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) );
+    assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) );
+    // check that the networks have the same PIs/POs/latches
+    if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, fImplic, fComb ) )
+        return NULL;
+    // make sure the circuits are strashed 
+    fRemove1 = (!Abc_NtkIsStrash(pNtk1) || Abc_NtkGetChoiceNum(pNtk1)) && (pNtk1 = Abc_NtkStrash(pNtk1, 0, 0, 0));
+    fRemove2 = (!Abc_NtkIsStrash(pNtk2) || Abc_NtkGetChoiceNum(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0, 0, 0));
+    if ( pNtk1 && pNtk2 )
+        pTemp = Abc_NtkMiterInt( pNtk1, pNtk2, fComb, nPartSize, fImplic, fMulti );
+    if ( fRemove1 )  Abc_NtkDelete( pNtk1 );
+    if ( fRemove2 )  Abc_NtkDelete( pNtk2 );
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the miter of two sequential networks.]
+
+  Description [Assumes that the networks are strashed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize, int fImplic, int fMulti )
+{
+    char Buffer[1000];
+    Abc_Ntk_t * pNtkMiter;
+
+    assert( Abc_NtkIsStrash(pNtk1) );
+    assert( Abc_NtkIsStrash(pNtk2) );
+
+    // start the new network
+    pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName );
+    pNtkMiter->pName = Extra_UtilStrsav(Buffer);
+
+    // perform strashing
+    Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize, fMulti );
+    Abc_NtkMiterAddOne( pNtk1, pNtkMiter );
+    Abc_NtkMiterAddOne( pNtk2, pNtkMiter );
+    Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize, fImplic, fMulti );
+    Abc_AigCleanup((Abc_Aig_t *)pNtkMiter->pManFunc);
+
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtkMiter ) )
+    {
+        printf( "Abc_NtkMiter: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkMiter );
+        return NULL;
+    }
+    return pNtkMiter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the network for mitering.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize, int fMulti )
+{
+    Abc_Obj_t * pObj, * pObjNew;
+    int i;
+    // clean the copy field in all objects
+//    Abc_NtkCleanCopy( pNtk1 );
+//    Abc_NtkCleanCopy( pNtk2 );
+    Abc_AigConst1(pNtk1)->pCopy = Abc_AigConst1(pNtkMiter);
+    Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtkMiter);
+
+    if ( fComb )
+    {
+        // create new PIs and remember them in the old PIs
+        Abc_NtkForEachCi( pNtk1, pObj, i )
+        {
+            pObjNew = Abc_NtkCreatePi( pNtkMiter );
+            // remember this PI in the old PIs
+            pObj->pCopy = pObjNew;
+            pObj = Abc_NtkCi(pNtk2, i);  
+            pObj->pCopy = pObjNew;
+            // add name
+            Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL );
+        }
+        if ( nPartSize <= 0 )
+        {
+            // create POs
+            if ( fMulti )
+            {
+                Abc_NtkForEachCo( pNtk1, pObj, i )
+                {
+                    pObjNew = Abc_NtkCreatePo( pNtkMiter );
+                    Abc_ObjAssignName( pObjNew, "miter", Abc_ObjName(pObjNew) );
+                }
+
+            }
+            else
+            {
+                pObjNew = Abc_NtkCreatePo( pNtkMiter );
+                Abc_ObjAssignName( pObjNew, "miter", NULL );
+            }
+        }
+    }
+    else
+    {
+        // create new PIs and remember them in the old PIs
+        Abc_NtkForEachPi( pNtk1, pObj, i )
+        {
+            pObjNew = Abc_NtkCreatePi( pNtkMiter );
+            // remember this PI in the old PIs
+            pObj->pCopy = pObjNew;
+            pObj = Abc_NtkPi(pNtk2, i);  
+            pObj->pCopy = pObjNew;
+            // add name
+            Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL );
+        }
+        if ( nPartSize <= 0 )
+        {
+            // create POs
+            if ( fMulti )
+            {
+                Abc_NtkForEachPo( pNtk1, pObj, i )
+                {
+                    pObjNew = Abc_NtkCreatePo( pNtkMiter );
+                    Abc_ObjAssignName( pObjNew, "miter", Abc_ObjName(pObjNew) );
+                }
+
+            }
+            else
+            {
+                pObjNew = Abc_NtkCreatePo( pNtkMiter );
+                Abc_ObjAssignName( pObjNew, "miter", NULL );
+            }
+        }
+        // create the latches
+        Abc_NtkForEachLatch( pNtk1, pObj, i )
+        {
+            pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 );
+            // add names
+            Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), "_1" );
+            Abc_ObjAssignName( Abc_ObjFanin0(pObjNew),  Abc_ObjName(Abc_ObjFanin0(pObj)), "_1" );
+            Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pObj)), "_1" );
+        }
+        Abc_NtkForEachLatch( pNtk2, pObj, i )
+        {
+            pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 );
+            // add name
+            Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), "_2" );
+            Abc_ObjAssignName( Abc_ObjFanin0(pObjNew),  Abc_ObjName(Abc_ObjFanin0(pObj)), "_2" );
+            Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pObj)), "_2" );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs mitering for one network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    assert( Abc_NtkIsDfsOrdered(pNtk) );
+    Abc_AigForEachAnd( pNtk, pNode, i )
+        pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs mitering for one network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pRoot )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNode;
+    int i;
+    // map the constant nodes
+    Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkMiter);
+    // perform strashing
+    vNodes = Abc_NtkDfsNodes( pNtk, &pRoot, 1 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        if ( Abc_AigNodeIsAnd(pNode) )
+            pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+    Vec_PtrFree( vNodes );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finalizes the miter by adding the output part.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize, int fImplic, int fMulti )
+{
+    Vec_Ptr_t * vPairs;
+    Abc_Obj_t * pMiter, * pNode;
+    int i;
+    assert( nPartSize == 0 || fMulti == 0 );
+    // collect the PO pairs from both networks
+    vPairs = Vec_PtrAlloc( 100 );
+    if ( fComb )
+    {
+        // collect the CO nodes for the miter
+        Abc_NtkForEachCo( pNtk1, pNode, i )
+        {
+            if ( fMulti )
+            {
+                pMiter = Abc_AigXor( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild0Copy(Abc_NtkCo(pNtk2, i)) );
+                Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,i), pMiter );
+            }
+            else
+            {
+                Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) );
+                pNode = Abc_NtkCo( pNtk2, i );
+                Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) );
+            }
+        }
+    }
+    else
+    {
+        // collect the PO nodes for the miter
+        Abc_NtkForEachPo( pNtk1, pNode, i )
+        {
+            if ( fMulti )
+            {
+                pMiter = Abc_AigXor( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild0Copy(Abc_NtkCo(pNtk2, i)) );
+                Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,i), pMiter );
+            }
+            else
+            {
+                Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) );
+                pNode = Abc_NtkPo( pNtk2, i );
+                Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) );
+            }
+        }
+        // connect new latches
+        Abc_NtkForEachLatch( pNtk1, pNode, i )
+            Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) );
+        Abc_NtkForEachLatch( pNtk2, pNode, i )
+            Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) );
+    }
+    // add the miter
+    if ( nPartSize <= 0 )
+    {
+        if ( !fMulti )
+        {
+            pMiter = Abc_AigMiter( (Abc_Aig_t *)pNtkMiter->pManFunc, vPairs, fImplic );
+            Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter );
+        }
+    }
+    else
+    {
+        char Buffer[1024];
+        Vec_Ptr_t * vPairsPart;
+        int nParts, i, k, iCur;
+        assert( Vec_PtrSize(vPairs) == 2 * Abc_NtkCoNum(pNtk1) );
+        // create partitions
+        nParts = Abc_NtkCoNum(pNtk1) / nPartSize + (int)((Abc_NtkCoNum(pNtk1) % nPartSize) > 0);
+        vPairsPart = Vec_PtrAlloc( nPartSize );
+        for ( i = 0; i < nParts; i++ )
+        {
+            Vec_PtrClear( vPairsPart );
+            for ( k = 0; k < nPartSize; k++ )
+            {
+                iCur = i * nPartSize + k;
+                if ( iCur >= Abc_NtkCoNum(pNtk1) )
+                    break;
+                Vec_PtrPush( vPairsPart, Vec_PtrEntry(vPairs, 2*iCur  ) );
+                Vec_PtrPush( vPairsPart, Vec_PtrEntry(vPairs, 2*iCur+1) );
+            }
+            pMiter = Abc_AigMiter( (Abc_Aig_t *)pNtkMiter->pManFunc, vPairsPart, fImplic );
+            pNode = Abc_NtkCreatePo( pNtkMiter );
+            Abc_ObjAddFanin( pNode, pMiter );
+            // assign the name to the node
+            if ( nPartSize == 1 )
+                sprintf( Buffer, "%s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) );
+            else
+                sprintf( Buffer, "%d", i );
+            Abc_ObjAssignName( pNode, "miter_", Buffer );
+        }
+        Vec_PtrFree( vPairsPart );
+    }
+    Vec_PtrFree( vPairs );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the AND of two miters.]
+
+  Description [The network should have the same names of PIs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterAnd( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOr, int fCompl2 )
+{
+    char Buffer[1000];
+    Abc_Ntk_t * pNtkMiter;
+    Abc_Obj_t * pOutput1, * pOutput2;
+    Abc_Obj_t * pRoot1, * pRoot2, * pMiter;
+
+    assert( Abc_NtkIsStrash(pNtk1) );
+    assert( Abc_NtkIsStrash(pNtk2) );
+    assert( 1 == Abc_NtkCoNum(pNtk1) );
+    assert( 1 == Abc_NtkCoNum(pNtk2) );
+    assert( 0 == Abc_NtkLatchNum(pNtk1) );
+    assert( 0 == Abc_NtkLatchNum(pNtk2) );
+    assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) );
+    assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) );
+    assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) );
+
+    // start the new network
+    pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+//    sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName );
+    sprintf( Buffer, "product" );
+    pNtkMiter->pName = Extra_UtilStrsav(Buffer);
+
+    // perform strashing
+    Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, 1, -1, 0 );
+    Abc_NtkMiterAddOne( pNtk1, pNtkMiter );
+    Abc_NtkMiterAddOne( pNtk2, pNtkMiter );
+//    Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, 1 );
+    pRoot1 = Abc_NtkPo(pNtk1,0);
+    pRoot2 = Abc_NtkPo(pNtk2,0);
+    pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot1)->pCopy, Abc_ObjFaninC0(pRoot1) );
+    pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot2)->pCopy, (int)Abc_ObjFaninC0(pRoot2) ^ fCompl2 );
+    
+    // create the miter of the two outputs
+    if ( fOr )
+        pMiter = Abc_AigOr( (Abc_Aig_t *)pNtkMiter->pManFunc, pOutput1, pOutput2 );
+    else
+        pMiter = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, pOutput1, pOutput2 );
+    Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter );
+
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtkMiter ) )
+    {
+        printf( "Abc_NtkMiterAnd: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkMiter );
+        return NULL;
+    }
+    return pNtkMiter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the cofactor of the miter w.r.t. the set of vars.]
+
+  Description [The array of variable values contains -1/0/1 for each PI.
+  -1 means this PI remains, 0/1 means this PI is set to 0/1.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues )
+{
+    char Buffer[1000];
+    Abc_Ntk_t * pNtkMiter;
+    Abc_Obj_t * pRoot, * pOutput1;
+    int Value, i;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( 1 == Abc_NtkCoNum(pNtk) );
+    assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
+
+    // start the new network
+    pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    sprintf( Buffer, "%s_miter", pNtk->pName );
+    pNtkMiter->pName = Extra_UtilStrsav(Buffer);
+
+    // get the root output
+    pRoot = Abc_NtkCo( pNtk, 0 );
+
+    // perform strashing
+    Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1, 0 );
+    // set the first cofactor
+    Vec_IntForEachEntry( vPiValues, Value, i )
+    {
+        if ( Value == -1 )
+            continue;
+        if ( Value == 0 )
+        {
+            Abc_NtkCi(pNtk, i)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) );
+            continue;
+        }
+        if ( Value == 1 )
+        {
+            Abc_NtkCi(pNtk, i)->pCopy = Abc_AigConst1(pNtkMiter);
+            continue;
+        }
+        assert( 0 );
+    }
+    // add the first cofactor
+    Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
+
+    // save the output
+    pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) );
+
+    // create the miter of the two outputs
+    Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pOutput1 );
+
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtkMiter ) )
+    {
+        printf( "Abc_NtkMiterCofactor: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkMiter );
+        return NULL;
+    }
+    return pNtkMiter;
+}
+/**Function*************************************************************
+
+  Synopsis    [Derives the miter of two cofactors of one output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 )
+{
+    char Buffer[1000];
+    Abc_Ntk_t * pNtkMiter;
+    Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( Out < Abc_NtkCoNum(pNtk) );
+    assert( In1 < Abc_NtkCiNum(pNtk) );
+    assert( In2 < Abc_NtkCiNum(pNtk) );
+    assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
+
+    // start the new network
+    pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    sprintf( Buffer, "%s_miter", Abc_ObjName(Abc_NtkCo(pNtk, Out)) );
+    pNtkMiter->pName = Extra_UtilStrsav(Buffer);
+
+    // get the root output
+    pRoot = Abc_NtkCo( pNtk, Out );
+
+    // perform strashing
+    Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1, 0 );
+    // set the first cofactor
+    Abc_NtkCi(pNtk, In1)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) );
+    if ( In2 >= 0 )
+    Abc_NtkCi(pNtk, In2)->pCopy = Abc_AigConst1(pNtkMiter);
+    // add the first cofactor
+    Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
+
+    // save the output
+    pOutput1 = Abc_ObjFanin0(pRoot)->pCopy;
+
+    // set the second cofactor
+    Abc_NtkCi(pNtk, In1)->pCopy = Abc_AigConst1(pNtkMiter);
+    if ( In2 >= 0 )
+    Abc_NtkCi(pNtk, In2)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) );
+    // add the second cofactor
+    Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
+
+    // save the output
+    pOutput2 = Abc_ObjFanin0(pRoot)->pCopy;
+
+    // create the miter of the two outputs
+    pMiter = Abc_AigXor( (Abc_Aig_t *)pNtkMiter->pManFunc, pOutput1, pOutput2 );
+    Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter );
+
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtkMiter ) )
+    {
+        printf( "Abc_NtkMiter: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkMiter );
+        return NULL;
+    }
+    return pNtkMiter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the miter of two cofactors of one output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist )
+{
+    Abc_Ntk_t * pNtkMiter;
+    Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( 1 == Abc_NtkCoNum(pNtk) );
+    assert( In < Abc_NtkCiNum(pNtk) );
+    assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
+
+    // start the new network
+    pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    pNtkMiter->pName = Extra_UtilStrsav( Abc_ObjName(Abc_NtkCo(pNtk, 0)) );
+
+    // get the root output
+    pRoot = Abc_NtkCo( pNtk, 0 );
+
+    // perform strashing
+    Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1, 0 );
+    // set the first cofactor
+    Abc_NtkCi(pNtk, In)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) );
+    // add the first cofactor
+    Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
+    // save the output
+//    pOutput1 = Abc_ObjFanin0(pRoot)->pCopy;
+    pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) );
+
+    // set the second cofactor
+    Abc_NtkCi(pNtk, In)->pCopy = Abc_AigConst1(pNtkMiter);
+    // add the second cofactor
+    Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
+    // save the output
+//    pOutput2 = Abc_ObjFanin0(pRoot)->pCopy;
+    pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) );
+
+    // create the miter of the two outputs
+    if ( fExist ) 
+        pMiter = Abc_AigOr( (Abc_Aig_t *)pNtkMiter->pManFunc, pOutput1, pOutput2 );
+    else
+        pMiter = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, pOutput1, pOutput2 );
+    Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter );
+
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtkMiter ) )
+    {
+        printf( "Abc_NtkMiter: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkMiter );
+        return NULL;
+    }
+    return pNtkMiter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Quantifies all the PIs existentially from the only PO of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterQuantifyPis( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkTemp;
+    Abc_Obj_t * pObj;
+    int i;
+    assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
+
+    Abc_NtkForEachPi( pNtk, pObj, i )
+    {
+        if ( Abc_ObjFanoutNum(pObj) == 0 )
+            continue;
+        pNtk = Abc_NtkMiterQuantify( pNtkTemp = pNtk, i, 1 );
+        Abc_NtkDelete( pNtkTemp );
+    }
+
+    return pNtk;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the status of the miter.]
+
+  Description [Return 0 if the miter is sat for at least one output.
+  Return 1 if the miter is unsat for all its outputs. Returns -1 if the
+  miter is undecided for some outputs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter )
+{
+    Abc_Obj_t * pNodePo, * pChild;
+    int i;
+    assert( Abc_NtkIsStrash(pMiter) );
+    Abc_NtkForEachPo( pMiter, pNodePo, i )
+    {
+        pChild = Abc_ObjChild0( pNodePo );
+        // check if the output is constant 1
+        if ( Abc_AigNodeIsConst(pChild) )
+        {
+            assert( Abc_ObjRegular(pChild) == Abc_AigConst1(pMiter) );
+            if ( !Abc_ObjIsComplement(pChild) )
+            {
+                // if the miter is constant 1, return immediately
+//                printf( "MITER IS CONSTANT 1!\n" );
+                return 0;
+            }
+        }
+/*
+        // check if the output is not constant 0
+        else if ( Abc_ObjRegular(pChild)->fPhase != (unsigned)Abc_ObjIsComplement(pChild) )
+        {
+            return 0;
+        }
+*/
+        // if the miter is undecided (or satisfiable), return immediately
+        else 
+            return -1;
+    }
+    // return 1, meaning all outputs are constant zero
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports the status of the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMiterReport( Abc_Ntk_t * pMiter )
+{
+    Abc_Obj_t * pChild, * pNode;
+    int i;
+    if ( Abc_NtkPoNum(pMiter) == 1 )
+    {
+        pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,0) );
+        if ( Abc_AigNodeIsConst(pChild) )
+        {
+            if ( Abc_ObjIsComplement(pChild) )
+                printf( "Unsatisfiable.\n" );
+            else
+                printf( "Satisfiable. (Constant 1).\n" );
+        }
+        else
+            printf( "Satisfiable.\n" );
+    }
+    else
+    {
+        Abc_NtkForEachPo( pMiter, pNode, i )
+        {
+            pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,i) );
+            printf( "Output #%2d : ", i );
+            if ( Abc_AigNodeIsConst(pChild) )
+            {
+                if ( Abc_ObjIsComplement(pChild) )
+                    printf( "Unsatisfiable.\n" );
+                else
+                    printf( "Satisfiable. (Constant 1).\n" );
+            }
+            else
+                printf( "Satisfiable.\n" );
+        }
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the timeframes of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial, int fVerbose )
+{
+    char Buffer[1000];
+    ProgressBar * pProgress;
+    Abc_Ntk_t * pNtkFrames;
+    Abc_Obj_t * pLatch, * pLatchOut;
+    int i, Counter;
+    assert( nFrames > 0 );
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( Abc_NtkIsDfsOrdered(pNtk) );
+    assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
+    // start the new network
+    pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames );
+    pNtkFrames->pName = Extra_UtilStrsav(Buffer);
+    // map the constant nodes
+    Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkFrames);
+    // create new latches (or their initial values) and remember them in the new latches
+    if ( !fInitial )
+    {
+        Abc_NtkForEachLatch( pNtk, pLatch, i )
+            Abc_NtkDupBox( pNtkFrames, pLatch, 1 );
+    }
+    else
+    {
+        Counter = 0;
+        Abc_NtkForEachLatch( pNtk, pLatch, i )
+        {
+            pLatchOut = Abc_ObjFanout0(pLatch);
+            if ( Abc_LatchIsInitNone(pLatch) || Abc_LatchIsInitDc(pLatch) ) // don't-care initial value - create a new PI
+            {
+                pLatchOut->pCopy = Abc_NtkCreatePi(pNtkFrames);
+                Abc_ObjAssignName( pLatchOut->pCopy, Abc_ObjName(pLatchOut), NULL );
+                Counter++;
+            }
+            else
+                pLatchOut->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames), Abc_LatchIsInit0(pLatch) );
+        }
+        if ( Counter )
+            printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter );
+    }
+    
+    // create the timeframes
+    pProgress = Extra_ProgressBarStart( stdout, nFrames );
+    for ( i = 0; i < nFrames; i++ )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        Abc_NtkAddFrame( pNtkFrames, pNtk, i );
+    }
+    Extra_ProgressBarStop( pProgress );
+    
+    // connect the new latches to the outputs of the last frame
+    if ( !fInitial )
+    {
+        // we cannot use pLatch->pCopy here because pLatch->pCopy is used for temporary storage of strashed values
+        Abc_NtkForEachLatch( pNtk, pLatch, i )
+            Abc_ObjAddFanin( Abc_ObjFanin0(pLatch)->pCopy, Abc_ObjFanout0(pLatch)->pCopy );
+    }
+
+    // remove dangling nodes
+    Abc_AigCleanup( (Abc_Aig_t *)pNtkFrames->pManFunc );
+    // reorder the latches
+    Abc_NtkOrderCisCos( pNtkFrames );
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtkFrames ) )
+    {
+        printf( "Abc_NtkFrames: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkFrames );
+        return NULL;
+    }
+    return pNtkFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one time frame to the new network.]
+
+  Description [Assumes that the latches of the old network point
+  to the outputs of the previous frame of the new network (pLatch->pCopy). 
+  In the end, updates the latches of the old network to point to the 
+  outputs of the current frame of the new network.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkAddFrame( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame )
+{
+    int fVerbose = 0;
+    int NodeBef = Abc_NtkNodeNum(pNtkFrames);
+    char Buffer[10];
+    Abc_Obj_t * pNode, * pLatch;
+    int i;
+    // create the prefix to be added to the node names
+    sprintf( Buffer, "_%02d", iFrame );
+    // add the new PI nodes
+    Abc_NtkForEachPi( pNtk, pNode, i )
+        Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer );
+    // add the internal nodes
+    Abc_AigForEachAnd( pNtk, pNode, i )
+        pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkFrames->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+    // add the new POs
+    Abc_NtkForEachPo( pNtk, pNode, i )
+    {
+        Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer );
+        Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) );
+    }
+    // transfer the implementation of the latch inputs to the latch outputs
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+        pLatch->pCopy = Abc_ObjChild0Copy(Abc_ObjFanin0(pLatch));
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+        Abc_ObjFanout0(pLatch)->pCopy = pLatch->pCopy;
+    // nodes after
+    if ( fVerbose )
+    printf( "F = %4d : Total = %6d. Nodes = %6d. Prop = %s.\n", 
+        iFrame, Abc_NtkNodeNum(pNtk), Abc_NtkNodeNum(pNtkFrames)-NodeBef, 
+        Abc_AigNodeIsConst( Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pCopy ) ? "proof" : "unknown" );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the timeframes of the network.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFrameMapping addFrameMapping, void* arg )
+{
+/*
+    char Buffer[1000];
+    ProgressBar * pProgress;
+    Abc_Ntk_t * pNtkFrames;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pLatch, * pLatchNew;
+    int i, Counter;
+    assert( nFrames > 0 );
+    assert( Abc_NtkIsStrash(pNtk) );   
+    // start the new network
+    pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames );
+    pNtkFrames->pName = Extra_UtilStrsav(Buffer);
+    // create new latches (or their initial values) and remember them in the new latches
+    if ( !fInitial )
+    {
+        Abc_NtkForEachLatch( pNtk, pLatch, i ) {
+            Abc_NtkDupObj( pNtkFrames, pLatch );
+            if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg);
+        }
+    }
+    else
+    {
+        Counter = 0;
+        Abc_NtkForEachLatch( pNtk, pLatch, i )
+        {
+            if ( Abc_LatchIsInitDc(pLatch) ) // don't-care initial value - create a new PI
+            {
+                pLatch->pCopy = Abc_NtkCreatePi(pNtkFrames);
+                Abc_ObjAssignName( pLatch->pCopy, Abc_ObjName(pLatch), NULL );
+                Counter++;
+            }
+            else {
+                pLatch->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames), Abc_LatchIsInit0(pLatch) );
+            }
+ 
+            if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg);
+        }
+        if ( Counter )
+            printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter );
+    }
+    
+    // create the timeframes
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    pProgress = Extra_ProgressBarStart( stdout, nFrames );
+    for ( i = 0; i < nFrames; i++ )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        Abc_NtkAddFrame2( pNtkFrames, pNtk, i, vNodes, addFrameMapping, arg );
+    }
+    Extra_ProgressBarStop( pProgress );
+    Vec_PtrFree( vNodes );
+    
+    // connect the new latches to the outputs of the last frame
+    if ( !fInitial )
+    {
+        Abc_NtkForEachLatch( pNtk, pLatch, i )
+        {
+            pLatchNew = Abc_NtkBox(pNtkFrames, i);
+            Abc_ObjAddFanin( pLatchNew, pLatch->pCopy );
+            Abc_ObjAssignName( pLatchNew, Abc_ObjName(pLatch), NULL );
+        }
+    }
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+        pLatch->pNext = NULL;
+
+    // remove dangling nodes
+    Abc_AigCleanup( pNtkFrames->pManFunc );
+
+    // reorder the latches
+    Abc_NtkOrderCisCos( pNtkFrames );
+    
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtkFrames ) )
+    {
+        printf( "Abc_NtkFrames: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkFrames );
+        return NULL;
+    }
+    return pNtkFrames;
+*/
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one time frame to the new network.]
+
+  Description [Assumes that the latches of the old network point
+  to the outputs of the previous frame of the new network (pLatch->pCopy). 
+  In the end, updates the latches of the old network to point to the 
+  outputs of the current frame of the new network.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg )
+{
+/*
+    char Buffer[10];
+    Abc_Obj_t * pNode, * pNodeNew, * pLatch;
+    Abc_Obj_t * pConst1, * pConst1New;
+    int i;
+    // get the constant nodes
+    pConst1    = Abc_AigConst1(pNtk);
+    pConst1New = Abc_AigConst1(pNtkFrames);
+    // create the prefix to be added to the node names
+    sprintf( Buffer, "_%02d", iFrame );
+    // add the new PI nodes
+    Abc_NtkForEachPi( pNtk, pNode, i )
+    {
+        pNodeNew = Abc_NtkDupObj( pNtkFrames, pNode );       
+        Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer );
+        if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg);
+    }
+    // add the internal nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( pNode == pConst1 )
+            pNodeNew = pConst1New;
+        else
+            pNodeNew = Abc_AigAnd( pNtkFrames->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+        pNode->pCopy = pNodeNew;
+        if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg);
+    }
+    // add the new POs
+    Abc_NtkForEachPo( pNtk, pNode, i )
+    {
+        pNodeNew = Abc_NtkDupObj( pNtkFrames, pNode );       
+        Abc_ObjAddFanin( pNodeNew, Abc_ObjChild0Copy(pNode) );
+        Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer );
+        if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg);
+    }
+    // transfer the implementation of the latch drivers to the latches
+
+    // it is important that these two steps are performed it two loops
+    // and not in the same loop
+    Abc_NtkForEachLatch( pNtk, pLatch, i ) 
+        pLatch->pNext = Abc_ObjChild0Copy(pLatch);
+    Abc_NtkForEachLatch( pNtk, pLatch, i ) 
+        pLatch->pCopy = pLatch->pNext;
+
+    Abc_NtkForEachLatch( pNtk, pLatch, i ) 
+    {
+        if (addFrameMapping) {
+            // don't give Mike complemented pointers because he doesn't like it
+            if (Abc_ObjIsComplement(pLatch->pCopy)) {            
+                pNodeNew = Abc_NtkCreateNode( pNtkFrames );
+                Abc_ObjAddFanin( pNodeNew, pLatch->pCopy );
+                assert(Abc_ObjFaninNum(pNodeNew) == 1);
+                pNodeNew->Level = 1 + Abc_ObjRegular(pLatch->pCopy)->Level;
+
+                pLatch->pNext = pNodeNew;
+                pLatch->pCopy = pNodeNew;
+            }
+            addFrameMapping(pLatch->pCopy, pLatch, iFrame+1, arg);
+        }
+    }
+*/
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Splits the miter into two logic cones combined by an EXOR]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDemiter( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNodeC, * pNodeA, * pNodeB, * pNode;
+    Abc_Obj_t * pPoNew;
+    Vec_Ptr_t * vNodes1, * vNodes2;
+    int nCommon, i;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( Abc_NtkPoNum(pNtk) == 1 );
+    if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) )
+    {
+        printf( "The root of the miter is not an EXOR gate.\n" );
+        return 0;
+    }
+    pNodeC = Abc_NodeRecognizeMux( Abc_ObjFanin0(Abc_NtkPo(pNtk,0)), &pNodeA, &pNodeB );
+    assert( Abc_ObjRegular(pNodeA) == Abc_ObjRegular(pNodeB) );
+    if ( Abc_ObjFaninC0(Abc_NtkPo(pNtk,0)) )
+    {
+        pNodeA = Abc_ObjNot(pNodeA);
+        pNodeB = Abc_ObjNot(pNodeB);
+    }
+
+    // add the PO corresponding to control input
+    pPoNew = Abc_NtkCreatePo( pNtk );
+    Abc_ObjAddFanin( pPoNew, pNodeC );
+    Abc_ObjAssignName( pPoNew, "addOut1", NULL );
+
+    // add the PO corresponding to other input
+    pPoNew = Abc_NtkCreatePo( pNtk );
+    Abc_ObjAddFanin( pPoNew, pNodeB );
+    Abc_ObjAssignName( pPoNew, "addOut2", NULL );
+
+    // mark the nodes in the first cone
+    pNodeB = Abc_ObjRegular(pNodeB);
+    vNodes1 = Abc_NtkDfsNodes( pNtk, &pNodeC, 1 );
+    vNodes2 = Abc_NtkDfsNodes( pNtk, &pNodeB, 1 );
+
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes1, pNode, i )
+        pNode->fMarkA = 1;
+    nCommon = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes2, pNode, i )
+        nCommon += pNode->fMarkA;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes1, pNode, i )
+        pNode->fMarkA = 0;
+
+    printf( "First cone = %6d.  Second cone = %6d.  Common = %6d.\n", vNodes1->nSize, vNodes2->nSize, nCommon );
+    Vec_PtrFree( vNodes1 );
+    Vec_PtrFree( vNodes2 );
+
+    // reorder the latches
+    Abc_NtkOrderCisCos( pNtk );
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtk ) )
+        printf( "Abc_NtkDemiter: The network check has failed.\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes OR or AND of the POs.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd, int fXor )
+{
+    Abc_Obj_t * pNode, * pMiter;
+    int i;
+    assert( Abc_NtkIsStrash(pNtk) );
+//    assert( Abc_NtkLatchNum(pNtk) == 0 );
+    if ( Abc_NtkPoNum(pNtk) == 1 )
+        return 1;
+    // start the result
+    if ( fAnd )
+        pMiter = Abc_AigConst1(pNtk);
+    else
+        pMiter = Abc_ObjNot( Abc_AigConst1(pNtk) );
+    // perform operations on the POs
+    Abc_NtkForEachPo( pNtk, pNode, i )
+        if ( fAnd )
+            pMiter = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) );
+        else if ( fXor )
+            pMiter = Abc_AigXor( (Abc_Aig_t *)pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) );
+        else
+            pMiter = Abc_AigOr( (Abc_Aig_t *)pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) );
+    // remove the POs and their names
+    for ( i = Abc_NtkPoNum(pNtk) - 1; i >= 0; i-- )
+        Abc_NtkDeleteObj( Abc_NtkPo(pNtk, i) );
+    assert( Abc_NtkPoNum(pNtk) == 0 );
+    // create the new PO
+    pNode = Abc_NtkCreatePo( pNtk );
+    Abc_ObjAddFanin( pNode, pMiter );
+    Abc_ObjAssignName( pNode, "miter", NULL );
+    Abc_NtkOrderCisCos( pNtk );
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtk ) )
+    {
+        printf( "Abc_NtkOrPos: The network check has failed.\n" );
+        return 0;
+    }
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcMulti.c b/abc-build/src/base/abci/abcMulti.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcMulti.c
@@ -0,0 +1,649 @@
+/**CFile****************************************************************
+
+  FileName    [abcMulti.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Procedures which transform an AIG into multi-input AND-graph.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcMulti.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void        Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
+static Abc_Obj_t * Abc_NtkMulti_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld );
+
+static DdNode *    Abc_NtkMultiDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFanins );
+static DdNode *    Abc_NtkMultiDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld );
+
+static void        Abc_NtkMultiSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax );
+static void        Abc_NtkMultiSetBoundsCnf( Abc_Ntk_t * pNtk );
+static void        Abc_NtkMultiSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh );
+static void        Abc_NtkMultiSetBoundsSimple( Abc_Ntk_t * pNtk );
+static void        Abc_NtkMultiSetBoundsFactor( Abc_Ntk_t * pNtk );
+static void        Abc_NtkMultiCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the AIG into nodes.]
+
+  Description [Threhold is the max number of nodes duplicated at a node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor )
+{
+    Abc_Ntk_t * pNtkNew;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( nThresh >= 0 );
+    assert( nFaninMax > 1 );
+
+    // print a warning about choice nodes
+    if ( Abc_NtkGetChoiceNum( pNtk ) )
+        printf( "Warning: The choice nodes in the AIG are removed by renoding.\n" );
+
+    // define the boundary
+    if ( fCnf )
+        Abc_NtkMultiSetBoundsCnf( pNtk );
+    else if ( fMulti )
+        Abc_NtkMultiSetBoundsMulti( pNtk, nThresh );
+    else if ( fSimple )
+        Abc_NtkMultiSetBoundsSimple( pNtk );
+    else if ( fFactor )
+        Abc_NtkMultiSetBoundsFactor( pNtk );
+    else
+        Abc_NtkMultiSetBounds( pNtk, nThresh, nFaninMax );
+
+    // perform renoding for this boundary
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
+    Abc_NtkMultiInt( pNtk, pNtkNew );
+    Abc_NtkFinalize( pNtk, pNtkNew );
+
+    // make the network minimum base
+    Abc_NtkMinimumBase( pNtkNew );
+
+    // fix the problem with complemented and duplicated CO edges
+    Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+
+    // report the number of CNF objects
+    if ( fCnf )
+    {
+//        int nClauses = Abc_NtkGetClauseNum(pNtkNew) + 2*Abc_NtkPoNum(pNtkNew) + 2*Abc_NtkLatchNum(pNtkNew);
+//        printf( "CNF variables = %d. CNF clauses = %d.\n",  Abc_NtkNodeNum(pNtkNew), nClauses );
+    }
+//printf( "Maximum fanin = %d.\n", Abc_NtkGetFaninMax(pNtkNew) );
+
+    if ( pNtk->pExdc )
+        pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkMulti: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the AIG into nodes.]
+
+  Description [Threhold is the max number of nodes duplicated at a node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
+{
+    ProgressBar * pProgress;
+    Abc_Obj_t * pNode, * pConst1, * pNodeNew;
+    int i;
+
+    // set the constant node
+    pConst1 = Abc_AigConst1(pNtk);
+    if ( Abc_ObjFanoutNum(pConst1) > 0 )
+    {
+        pNodeNew = Abc_NtkCreateNode( pNtkNew );  
+        pNodeNew->pData = Cudd_ReadOne( (DdManager *)pNtkNew->pManFunc );   Cudd_Ref( (DdNode *)pNodeNew->pData );
+        pConst1->pCopy = pNodeNew;
+    }
+
+    // perform renoding for POs
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        if ( Abc_ObjIsCi(Abc_ObjFanin0(pNode)) )
+            continue;
+        Abc_NtkMulti_rec( pNtkNew, Abc_ObjFanin0(pNode) );
+    }
+    Extra_ProgressBarStop( pProgress );
+
+    // clean the boundaries and data field in the old network
+    Abc_NtkForEachObj( pNtk, pNode, i )
+    {
+        pNode->fMarkA = 0;
+        pNode->pData = NULL;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the best multi-input node rooted at the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkMulti_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld )
+{
+    Vec_Ptr_t * vCone;
+    Abc_Obj_t * pNodeNew;
+    int i;
+
+    assert( !Abc_ObjIsComplement(pNodeOld) );
+    // return if the result if known
+    if ( pNodeOld->pCopy )
+        return pNodeOld->pCopy;
+    assert( Abc_ObjIsNode(pNodeOld) );
+    assert( !Abc_AigNodeIsConst(pNodeOld) );
+    assert( pNodeOld->fMarkA );
+
+//printf( "%d ", Abc_NodeMffcSizeSupp(pNodeOld) );
+
+    // collect the renoding cone
+    vCone = Vec_PtrAlloc( 10 );
+    Abc_NtkMultiCone( pNodeOld, vCone );
+
+    // create a new node 
+    pNodeNew = Abc_NtkCreateNode( pNtkNew ); 
+    for ( i = 0; i < vCone->nSize; i++ )
+        Abc_ObjAddFanin( pNodeNew, Abc_NtkMulti_rec(pNtkNew, (Abc_Obj_t *)vCone->pArray[i]) );
+
+    // derive the function of this node
+    pNodeNew->pData = Abc_NtkMultiDeriveBdd( (DdManager *)pNtkNew->pManFunc, pNodeOld, vCone );    
+    Cudd_Ref( (DdNode *)pNodeNew->pData );
+    Vec_PtrFree( vCone );
+
+    // remember the node
+    pNodeOld->pCopy = pNodeNew;
+    return pNodeOld->pCopy;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the local BDD of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NtkMultiDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld )
+{
+    Abc_Obj_t * pFaninOld;
+    DdNode * bFunc;
+    int i;
+    assert( !Abc_AigNodeIsConst(pNodeOld) );
+    assert( Abc_ObjIsNode(pNodeOld) );
+    // set the elementary BDD variables for the input nodes
+    for ( i = 0; i < vFaninsOld->nSize; i++ )
+    {
+        pFaninOld = (Abc_Obj_t *)vFaninsOld->pArray[i];
+        pFaninOld->pData = Cudd_bddIthVar( dd, i );    Cudd_Ref( (DdNode *)pFaninOld->pData );
+        pFaninOld->fMarkC = 1;
+    }
+    // call the recursive BDD computation
+    bFunc = Abc_NtkMultiDeriveBdd_rec( dd, pNodeOld, vFaninsOld );  Cudd_Ref( bFunc );
+    // dereference the intermediate nodes
+    for ( i = 0; i < vFaninsOld->nSize; i++ )
+    {
+        pFaninOld = (Abc_Obj_t *)vFaninsOld->pArray[i];
+        Cudd_RecursiveDeref( dd, (DdNode *)pFaninOld->pData );
+        pFaninOld->fMarkC = 0;
+    }
+    Cudd_Deref( bFunc );
+    return bFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the local BDD of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NtkMultiDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins )
+{
+    DdNode * bFunc, * bFunc0, * bFunc1;
+    assert( !Abc_ObjIsComplement(pNode) );
+    // if the result is available return
+    if ( pNode->fMarkC )
+    {
+        assert( pNode->pData ); // network has a cycle
+        return (DdNode *)pNode->pData;
+    }
+    // mark the node as visited
+    pNode->fMarkC = 1;
+    Vec_PtrPush( vFanins, pNode );
+    // compute the result for both branches
+    bFunc0 = Abc_NtkMultiDeriveBdd_rec( dd, Abc_ObjFanin(pNode,0), vFanins ); Cudd_Ref( bFunc0 );
+    bFunc1 = Abc_NtkMultiDeriveBdd_rec( dd, Abc_ObjFanin(pNode,1), vFanins ); Cudd_Ref( bFunc1 );
+    bFunc0 = Cudd_NotCond( bFunc0, (long)Abc_ObjFaninC0(pNode) );
+    bFunc1 = Cudd_NotCond( bFunc1, (long)Abc_ObjFaninC1(pNode) );
+    // get the final result
+    bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 );   Cudd_Ref( bFunc );
+    Cudd_RecursiveDeref( dd, bFunc0 );
+    Cudd_RecursiveDeref( dd, bFunc1 );
+    // set the result
+    pNode->pData = bFunc;
+    assert( pNode->pData );
+    return bFunc;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Limits the cones to be no more than the given size.]
+
+  Description [Returns 1 if the last cone was limited. Returns 0 if no changes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMultiLimit_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax, int fCanStop, int fFirst )
+{
+    int nNodes0, nNodes1;
+    assert( !Abc_ObjIsComplement(pNode) );
+    // check if the node should be added to the fanins
+    if ( !fFirst && (pNode->fMarkA || !Abc_ObjIsNode(pNode)) )
+    {
+        Vec_PtrPushUnique( vCone, pNode );
+        return 0;
+    }
+    // if we cannot stop in this branch, collect all nodes
+    if ( !fCanStop )
+    {
+        Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 0, 0 );
+        Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
+        return 0;
+    }
+    // if we can stop, try the left branch first, and return if we stopped
+    assert( vCone->nSize == 0 );
+    if ( Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 1, 0 ) )
+        return 1;
+    // save the number of nodes in the left branch and call for the right branch
+    nNodes0 = vCone->nSize;
+    assert( nNodes0 <= nFaninMax );
+    Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
+    // check the number of nodes
+    if ( vCone->nSize <= nFaninMax )
+        return 0;
+    // the number of nodes exceeds the limit
+
+    // get the number of nodes in the right branch
+    vCone->nSize = 0;
+    Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
+    // if this number exceeds the limit, solve the problem for this branch
+    if ( vCone->nSize > nFaninMax )
+    {
+        int RetValue;
+        vCone->nSize = 0;
+        RetValue = Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 1, 0 );
+        assert( RetValue == 1 );
+        return 1;
+    }
+
+    nNodes1 = vCone->nSize; 
+    assert( nNodes1 <= nFaninMax );
+    if ( nNodes0 >= nNodes1 )
+    { // the left branch is larger - cut it
+        assert( Abc_ObjFanin(pNode,0)->fMarkA == 0 );
+        Abc_ObjFanin(pNode,0)->fMarkA = 1;
+    }
+    else
+    { // the right branch is larger - cut it
+        assert( Abc_ObjFanin(pNode,1)->fMarkA == 0 );
+        Abc_ObjFanin(pNode,1)->fMarkA = 1;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Limits the cones to be no more than the given size.]
+
+  Description [Returns 1 if the last cone was limited. Returns 0 if no changes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMultiLimit( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax )
+{
+    vCone->nSize = 0;
+    return Abc_NtkMultiLimit_rec( pNode, vCone, nFaninMax, 1, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the expansion boundary for multi-input nodes.]
+
+  Description [The boundary includes the set of PIs and all nodes such that 
+  when expanding over the node we duplicate no more than nThresh nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMultiSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax )
+{
+    Vec_Ptr_t * vCone = Vec_PtrAlloc(10);
+    Abc_Obj_t * pNode;
+    int i, nFanouts, nConeSize;
+
+    // make sure the mark is not set
+    Abc_NtkForEachObj( pNtk, pNode, i )
+        assert( pNode->fMarkA == 0 );
+
+    // mark the nodes where expansion stops using pNode->fMarkA
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        // skip PI/PO nodes
+//        if ( Abc_NodeIsConst(pNode) )
+//            continue;
+        // mark the nodes with multiple fanouts
+        nFanouts = Abc_ObjFanoutNum(pNode);
+        nConeSize = Abc_NodeMffcSize(pNode);
+        if ( (nFanouts - 1) * nConeSize > nThresh )
+            pNode->fMarkA = 1;
+    }
+
+    // mark the PO drivers
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        Abc_ObjFanin0(pNode)->fMarkA = 1;
+
+    // make sure the fanin limit is met
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        // skip PI/PO nodes
+//        if ( Abc_NodeIsConst(pNode) )
+//            continue;
+        if ( pNode->fMarkA == 0 )
+            continue;
+        // continue cutting branches until it meets the fanin limit
+        while ( Abc_NtkMultiLimit(pNode, vCone, nFaninMax) );
+        assert( vCone->nSize <= nFaninMax );  
+    }
+    Vec_PtrFree(vCone);
+/*
+    // make sure the fanin limit is met
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        // skip PI/PO nodes
+//        if ( Abc_NodeIsConst(pNode) )
+//            continue;
+        if ( pNode->fMarkA == 0 )
+            continue;
+        Abc_NtkMultiCone( pNode, vCone );
+        assert( vCone->nSize <= nFaninMax );    
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the expansion boundary for conversion into CNF.]
+
+  Description [The boundary includes the set of PIs, the roots of MUXes,
+  the nodes with multiple fanouts and the nodes with complemented outputs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMultiSetBoundsCnf( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i, nMuxes;
+
+    // make sure the mark is not set
+    Abc_NtkForEachObj( pNtk, pNode, i )
+        assert( pNode->fMarkA == 0 );
+
+    // mark the nodes where expansion stops using pNode->fMarkA
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        // skip PI/PO nodes
+//        if ( Abc_NodeIsConst(pNode) )
+//            continue;
+        // mark the nodes with multiple fanouts
+        if ( Abc_ObjFanoutNum(pNode) > 1 )
+            pNode->fMarkA = 1;
+        // mark the nodes that are roots of MUXes
+        if ( Abc_NodeIsMuxType( pNode ) )
+        {
+            pNode->fMarkA = 1;
+            Abc_ObjFanin0( Abc_ObjFanin0(pNode) )->fMarkA = 1;
+            Abc_ObjFanin0( Abc_ObjFanin1(pNode) )->fMarkA = 1;
+            Abc_ObjFanin1( Abc_ObjFanin0(pNode) )->fMarkA = 1;
+            Abc_ObjFanin1( Abc_ObjFanin1(pNode) )->fMarkA = 1;
+        }
+        else  // mark the complemented edges
+        {
+            if ( Abc_ObjFaninC0(pNode) )
+                Abc_ObjFanin0(pNode)->fMarkA = 1;
+            if ( Abc_ObjFaninC1(pNode) )
+                Abc_ObjFanin1(pNode)->fMarkA = 1;
+        }
+    }
+
+    // mark the PO drivers
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        Abc_ObjFanin0(pNode)->fMarkA = 1;
+
+    // count the number of MUXes
+    nMuxes = 0;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        // skip PI/PO nodes
+//        if ( Abc_NodeIsConst(pNode) )
+//            continue;
+        if ( Abc_NodeIsMuxType(pNode) && 
+            Abc_ObjFanin0(pNode)->fMarkA == 0 &&
+            Abc_ObjFanin1(pNode)->fMarkA == 0 )
+            nMuxes++;
+    }
+//    printf( "The number of MUXes detected = %d (%5.2f %% of logic).\n", nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) );
+} 
+ 
+/**Function*************************************************************
+
+  Synopsis    [Sets the expansion boundary for conversion into multi-input AND graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMultiSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh )
+{
+    Abc_Obj_t * pNode;
+    int i, nFanouts, nConeSize;
+
+    // make sure the mark is not set
+    Abc_NtkForEachObj( pNtk, pNode, i )
+        assert( pNode->fMarkA == 0 );
+
+    // mark the nodes where expansion stops using pNode->fMarkA
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        // skip PI/PO nodes
+//        if ( Abc_NodeIsConst(pNode) )
+//            continue;
+        // mark the nodes with multiple fanouts
+//        if ( Abc_ObjFanoutNum(pNode) > 1 )
+//            pNode->fMarkA = 1;
+        // mark the nodes with multiple fanouts
+        nFanouts = Abc_ObjFanoutNum(pNode);
+        nConeSize = Abc_NodeMffcSizeStop(pNode);
+        if ( (nFanouts - 1) * nConeSize > nThresh )
+            pNode->fMarkA = 1;
+        // mark the children if they are pointed by the complemented edges
+        if ( Abc_ObjFaninC0(pNode) )
+            Abc_ObjFanin0(pNode)->fMarkA = 1;
+        if ( Abc_ObjFaninC1(pNode) )
+            Abc_ObjFanin1(pNode)->fMarkA = 1;
+    }
+
+    // mark the PO drivers
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        Abc_ObjFanin0(pNode)->fMarkA = 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets a simple boundary.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMultiSetBoundsSimple( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    // make sure the mark is not set
+    Abc_NtkForEachObj( pNtk, pNode, i )
+        assert( pNode->fMarkA == 0 );
+    // mark the nodes where expansion stops using pNode->fMarkA
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        pNode->fMarkA = 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets a factor-cut boundary.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMultiSetBoundsFactor( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    // make sure the mark is not set
+    Abc_NtkForEachObj( pNtk, pNode, i )
+        assert( pNode->fMarkA == 0 );
+    // mark the nodes where expansion stops using pNode->fMarkA
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        pNode->fMarkA = (pNode->vFanouts.nSize > 1 && !Abc_NodeIsMuxControlType(pNode));
+    // mark the PO drivers
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        Abc_ObjFanin0(pNode)->fMarkA = 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the fanins of a large node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMultiCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone )
+{
+    assert( !Abc_ObjIsComplement(pNode) );
+    if ( pNode->fMarkA || !Abc_ObjIsNode(pNode) )
+    {
+        Vec_PtrPushUnique( vCone, pNode );
+        return;
+    }
+    Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,0), vCone );
+    Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,1), vCone );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the fanins of a large node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMultiCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone )
+{
+    assert( !Abc_ObjIsComplement(pNode) );
+    assert( Abc_ObjIsNode(pNode) );
+    vCone->nSize = 0;
+    Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,0), vCone );
+    Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,1), vCone );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcMv.c b/abc-build/src/base/abci/abcMv.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcMv.c
@@ -0,0 +1,375 @@
+/**CFile****************************************************************
+
+  FileName    [abcMv.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Multi-valued decomposition.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Mv_Man_t_ Mv_Man_t;
+struct Mv_Man_t_
+{
+    int         nInputs;          // the number of 4-valued input variables
+    int         nFuncs;           // the number of 4-valued functions
+    DdManager * dd;               // representation of functions
+    DdNode *    bValues[15][4];   // representation of i-sets
+    DdNode *    bValueDcs[15][4]; // representation of i-sets don't-cares
+    DdNode *    bFuncs[15];       // representation of functions
+};
+
+static void     Abc_MvDecompose( Mv_Man_t * p );
+static void     Abc_MvPrintStats( Mv_Man_t * p );
+static void     Abc_MvRead( Mv_Man_t * p );
+static void     Abc_MvDeref( Mv_Man_t * p );
+static DdNode * Abc_MvReadCube( DdManager * dd, char * pLine, int nVars );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MvExperiment()
+{
+    Mv_Man_t * p;
+    // get the functions
+    p = ABC_ALLOC( Mv_Man_t, 1 );
+    memset( p, 0, sizeof(Mv_Man_t) );
+    p->dd = Cudd_Init( 32, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    p->nFuncs  = 15;
+    p->nInputs =  9;
+    Abc_MvRead( p );
+    // process the functions
+    Abc_MvPrintStats( p );
+//    Cudd_ReduceHeap( p->dd, CUDD_REORDER_SYMM_SIFT, 1 );
+//    Abc_MvPrintStats( p );
+    // try detecting support reducing bound set
+    Abc_MvDecompose( p );
+
+    // remove the manager
+    Abc_MvDeref( p );
+    Extra_StopManager( p->dd );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MvPrintStats( Mv_Man_t * p )
+{
+    int i, v;
+    for ( i = 0; i < 15; i++ )
+    {
+        printf( "%2d : ", i );
+        printf( "%3d (%2d)    ", Cudd_DagSize(p->bFuncs[i])-1, Cudd_SupportSize(p->dd, p->bFuncs[i]) );
+        for ( v = 0; v < 4; v++ )
+            printf( "%d = %3d (%2d)  ", v, Cudd_DagSize(p->bValues[i][v])-1, Cudd_SupportSize(p->dd, p->bValues[i][v]) );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_MvReadCube( DdManager * dd, char * pLine, int nVars )
+{
+    DdNode * bCube, * bVar, * bTemp;
+    int i;
+    bCube = Cudd_ReadOne(dd);  Cudd_Ref( bCube );
+    for ( i = 0; i < nVars; i++ )
+    {
+        if ( pLine[i] == '-' )
+            continue;
+        else if ( pLine[i] == '0' ) // 0
+            bVar = Cudd_Not( Cudd_bddIthVar(dd, 29-i) );
+        else if ( pLine[i] == '1' ) // 1
+            bVar = Cudd_bddIthVar(dd, 29-i);
+        else assert(0);
+        bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar );  Cudd_Ref( bCube );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    Cudd_Deref( bCube );
+    return bCube;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MvRead( Mv_Man_t * p )
+{
+    FILE * pFile;
+    char Buffer[1000], * pLine;
+    DdNode * bCube, * bTemp, * bProd, * bVar0, * bVar1, * bCubeSum;
+    int i, v;
+
+    // start the cube
+    bCubeSum = Cudd_ReadLogicZero(p->dd);  Cudd_Ref( bCubeSum );
+
+    // start the values
+    for ( i = 0; i < 15; i++ )
+    for ( v = 0; v < 4; v++ )
+    {
+        p->bValues[i][v]   = Cudd_ReadLogicZero(p->dd);  Cudd_Ref( p->bValues[i][v] );
+        p->bValueDcs[i][v] = Cudd_ReadLogicZero(p->dd);  Cudd_Ref( p->bValueDcs[i][v] );
+    }
+
+    // read the file
+    pFile = fopen( "input.pla", "r" );
+    while ( fgets( Buffer, 1000, pFile ) )
+    {
+        if ( Buffer[0] == '#' )
+            continue;
+        if ( Buffer[0] == '.' )
+        {
+            if ( Buffer[1] == 'e' )
+                break;
+            continue;
+        }
+
+        // get the cube 
+        bCube = Abc_MvReadCube( p->dd, Buffer, 18 );  Cudd_Ref( bCube );
+
+        // add it to the values of the output functions
+        pLine = Buffer + 19;
+        for ( i = 0; i < 15; i++ )
+        {
+            if ( pLine[2*i] == '-' && pLine[2*i+1] == '-' )
+            {
+                for ( v = 0; v < 4; v++ )
+                {
+                    p->bValueDcs[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValueDcs[i][v], bCube );  Cudd_Ref( p->bValueDcs[i][v] );
+                    Cudd_RecursiveDeref( p->dd, bTemp );
+                }
+                continue;
+            }
+            else if ( pLine[2*i] == '0' && pLine[2*i+1] == '0' ) // 0
+                v = 0;
+            else if ( pLine[2*i] == '1' && pLine[2*i+1] == '0' ) // 1
+                v = 1;
+            else if ( pLine[2*i] == '0' && pLine[2*i+1] == '1' ) // 2
+                v = 2;
+            else if ( pLine[2*i] == '1' && pLine[2*i+1] == '1' ) // 3
+                v = 3;
+            else assert( 0 );
+            // add the value
+            p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], bCube );  Cudd_Ref( p->bValues[i][v] );
+            Cudd_RecursiveDeref( p->dd, bTemp );
+        }
+
+        // add the cube
+        bCubeSum = Cudd_bddOr( p->dd, bTemp = bCubeSum, bCube );  Cudd_Ref( bCubeSum );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+        Cudd_RecursiveDeref( p->dd, bCube );
+    }
+
+    // add the complement of the domain to all values
+    for ( i = 0; i < 15; i++ )
+        for ( v = 0; v < 4; v++ )
+        {
+            if ( p->bValues[i][v] == Cudd_Not(Cudd_ReadOne(p->dd)) )
+                continue;
+            p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], p->bValueDcs[i][v] );  Cudd_Ref( p->bValues[i][v] );
+            Cudd_RecursiveDeref( p->dd, bTemp );
+            p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], Cudd_Not(bCubeSum) );  Cudd_Ref( p->bValues[i][v] );
+            Cudd_RecursiveDeref( p->dd, bTemp );
+        }
+    printf( "Domain = %5.2f %%.\n", 100.0*Cudd_CountMinterm(p->dd, bCubeSum, 32)/Cudd_CountMinterm(p->dd, Cudd_ReadOne(p->dd), 32) ); 
+    Cudd_RecursiveDeref( p->dd, bCubeSum );
+
+    // create each output function
+    for ( i = 0; i < 15; i++ )
+    {
+        p->bFuncs[i] = Cudd_ReadLogicZero(p->dd);  Cudd_Ref( p->bFuncs[i] );
+        for ( v = 0; v < 4; v++ )
+        {
+            bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 30), ((v & 1) == 0) );
+            bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 31), ((v & 2) == 0) );
+            bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 );             Cudd_Ref( bCube );
+            bProd = Cudd_bddAnd( p->dd, p->bValues[i][v], bCube );  Cudd_Ref( bProd );
+            Cudd_RecursiveDeref( p->dd, bCube );
+            // add the value
+            p->bFuncs[i] = Cudd_bddOr( p->dd, bTemp = p->bFuncs[i], bProd );  Cudd_Ref( p->bFuncs[i] );
+            Cudd_RecursiveDeref( p->dd, bTemp );
+            Cudd_RecursiveDeref( p->dd, bProd );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MvDeref( Mv_Man_t * p )
+{
+    int i, v;
+    for ( i = 0; i < 15; i++ )
+    for ( v = 0; v < 4; v++ )
+    {
+        Cudd_RecursiveDeref( p->dd, p->bValues[i][v] );
+        Cudd_RecursiveDeref( p->dd, p->bValueDcs[i][v] );
+    }
+    for ( i = 0; i < 15; i++ )
+        Cudd_RecursiveDeref( p->dd, p->bFuncs[i] );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MvDecompose( Mv_Man_t * p )
+{
+    DdNode * bCofs[16], * bVarCube1, * bVarCube2, * bVarCube, * bCube, * bVar0, * bVar1;//, * bRes;
+    int k, i1, i2, v1, v2;//, c1, c2, Counter;
+
+    bVar0 = Cudd_bddIthVar(p->dd, 30);
+    bVar1 = Cudd_bddIthVar(p->dd, 31);
+    bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 );  Cudd_Ref( bCube );
+
+    for ( k = 0; k < p->nFuncs; k++ )
+    {
+        printf( "FUNCTION %d\n", k );
+        for ( i1 = 0; i1 < p->nFuncs; i1++ )
+        for ( i2 = i1+1; i2 < p->nFuncs; i2++ )
+        {
+            Vec_Ptr_t * vCofs;
+
+            for ( v1 = 0; v1 < 4; v1++ )
+            {
+                bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1  ), ((v1 & 1) == 0) );
+                bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1-1), ((v1 & 2) == 0) );
+                bVarCube1 = Cudd_bddAnd( p->dd, bVar0, bVar1 );  Cudd_Ref( bVarCube1 );
+                for ( v2 = 0; v2 < 4; v2++ )
+                {
+                    bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2  ), ((v2 & 1) == 0) );
+                    bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2-1), ((v2 & 2) == 0) );
+                    bVarCube2 = Cudd_bddAnd( p->dd, bVar0, bVar1 );         Cudd_Ref( bVarCube2 );
+                    bVarCube = Cudd_bddAnd( p->dd, bVarCube1, bVarCube2 );  Cudd_Ref( bVarCube );
+                    bCofs[v1 * 4 + v2] = Cudd_Cofactor( p->dd, p->bFuncs[k], bVarCube );  Cudd_Ref( bCofs[v1 * 4 + v2] );
+                    Cudd_RecursiveDeref( p->dd, bVarCube );
+                    Cudd_RecursiveDeref( p->dd, bVarCube2 );
+                }
+                Cudd_RecursiveDeref( p->dd, bVarCube1 );
+            }
+/*
+            // check the compatibility of cofactors
+            Counter = 0;
+            for ( c1 = 0; c1 < 16; c1++ )
+            {
+                for ( c2 = 0; c2 <= c1; c2++ )
+                    printf( " " );
+                for ( c2 = c1+1; c2 < 16; c2++ )
+                {
+                    bRes = Cudd_bddAndAbstract( p->dd, bCofs[c1], bCofs[c2], bCube );  Cudd_Ref( bRes );
+                    if ( bRes == Cudd_ReadOne(p->dd) )
+                    {
+                        printf( "+" );
+                        Counter++;
+                    }
+                    else
+                    {
+                        printf( " " );
+                    }
+                    Cudd_RecursiveDeref( p->dd, bRes );
+                }
+                printf( "\n" );
+            }
+*/
+
+            vCofs = Vec_PtrAlloc( 16 );
+            for ( v1 = 0; v1 < 4; v1++ )
+            for ( v2 = 0; v2 < 4; v2++ )
+                Vec_PtrPushUnique( vCofs, bCofs[v1 * 4 + v2] );
+            printf( "%d ", Vec_PtrSize(vCofs) );
+            Vec_PtrFree( vCofs );
+
+            // free the cofactors
+            for ( v1 = 0; v1 < 4; v1++ )
+            for ( v2 = 0; v2 < 4; v2++ )
+                Cudd_RecursiveDeref( p->dd, bCofs[v1 * 4 + v2] );
+
+            printf( "\n" );
+//            printf( "%2d, %2d : %3d\n", i1, i2, Counter );
+        }
+    }
+
+    Cudd_RecursiveDeref( p->dd, bCube );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcNpn.c b/abc-build/src/base/abci/abcNpn.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcNpn.c
@@ -0,0 +1,369 @@
+/**CFile****************************************************************
+
+  FileName    [abcNpn.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Procedures for testing and comparing semi-canonical forms.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcNpn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "misc/extra/extra.h"
+#include "misc/vec/vec.h"
+
+#include "bool/kit/kit.h"
+#include "bool/lucky/lucky.h"
+#include "opt/dau/dau.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+// semi-canonical form types
+// 0 - none
+// 1 - based on counting 1s in cofactors
+// 2 - based on minimum truth table value
+// 3 - exact NPN
+
+// data-structure to store a bunch of truth tables
+typedef struct Abc_TtStore_t_  Abc_TtStore_t;
+struct Abc_TtStore_t_ 
+{
+    int                nVars;
+    int                nWords;
+    int                nFuncs;
+    word **            pFuncs;
+};
+
+extern Abc_TtStore_t * Abc_TtStoreLoad( char * pFileName, int nVarNum );
+extern void            Abc_TtStoreFree( Abc_TtStore_t * p, int nVarNum );
+extern void            Abc_TtStoreWrite( char * pFileName, Abc_TtStore_t * p, int fBinary );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of unique truth tables.]
+
+  Description []
+               
+  SideEffects [] 
+
+  SeeAlso     []
+
+***********************************************************************/
+// returns hash key of the truth table
+static inline int Abc_TruthHashKey( word * pFunc, int nWords, int nTableSize )
+{
+    static unsigned s_BigPrimes[7] = {12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457};
+    int w;
+    word Key = 0;
+    for ( w = 0; w < nWords; w++ )
+        Key += pFunc[w] * s_BigPrimes[w % 7];
+    return (int)(Key % nTableSize);
+}
+// returns 1 if the entry with this truth table exits
+static inline int Abc_TruthHashLookup( word ** pFuncs, int iThis, int nWords, int * pTable, int * pNexts, int Key )
+{
+    int iThat;
+    for ( iThat = pTable[Key]; iThat != -1; iThat = pNexts[iThat] )
+        if ( !memcmp( pFuncs[iThat], pFuncs[iThis], sizeof(word) * nWords ) )
+            return 1;
+    return 0;
+}
+// hashes truth tables and collects unique ones
+int Abc_TruthNpnCountUnique( Abc_TtStore_t * p )
+{
+    // allocate hash table
+    int nTableSize = Abc_PrimeCudd(p->nFuncs);
+    int * pTable = ABC_FALLOC( int, nTableSize );
+    int * pNexts = ABC_FALLOC( int, nTableSize );
+    // hash functions
+    int i, k, Key;
+    for ( i = 0; i < p->nFuncs; i++ )
+    {
+        Key = Abc_TruthHashKey( p->pFuncs[i], p->nWords, nTableSize );
+        if ( Abc_TruthHashLookup( p->pFuncs, i, p->nWords, pTable, pNexts, Key ) ) // found equal
+            p->pFuncs[i] = NULL;
+        else // there is no equal (the first time this one occurs so far)
+            pNexts[i] = pTable[Key], pTable[Key] = i;
+    }
+    ABC_FREE( pTable );
+    ABC_FREE( pNexts );
+    // count the number of unqiue functions
+    assert( p->pFuncs[0] != NULL );
+    for ( i = k = 1; i < p->nFuncs; i++ )
+        if ( p->pFuncs[i] != NULL )
+            p->pFuncs[k++] = p->pFuncs[i];
+    return (p->nFuncs = k);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of unique truth tables.]
+
+  Description []
+               
+  SideEffects [] 
+
+  SeeAlso     []
+
+***********************************************************************/
+int nWords = 0; // unfortunate global variable
+int Abc_TruthCompare( word ** p1, word ** p2 ) { return memcmp(*p1, *p2, sizeof(word) * nWords); }
+int Abc_TruthNpnCountUniqueSort( Abc_TtStore_t * p )
+{
+    int i, k;
+    // sort them by value
+    nWords = p->nWords;
+    assert( nWords > 0 );
+    qsort( (void *)p->pFuncs, p->nFuncs, sizeof(word *), (int(*)(const void *,const void *))Abc_TruthCompare );
+    // count the number of unqiue functions
+    for ( i = k = 1; i < p->nFuncs; i++ )
+        if ( memcmp( p->pFuncs[i-1], p->pFuncs[i], sizeof(word) * nWords ) )
+            p->pFuncs[k++] = p->pFuncs[i];
+    return (p->nFuncs = k);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints out one NPN transform.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_TruthNpnPrint( char * pCanonPermInit, unsigned uCanonPhase, int nVars )
+{
+    char pCanonPerm[16]; int i;
+    assert( nVars <= 16 );
+    for ( i = 0; i < nVars; i++ )
+        pCanonPerm[i] = pCanonPermInit ? pCanonPermInit[i] : 'a' + i;
+    printf( "   %c = ( ", Abc_InfoHasBit(&uCanonPhase, nVars) ? 'Z':'z' );
+    for ( i = 0; i < nVars; i++ )
+        printf( "%c%s", pCanonPerm[i] + ('A'-'a') * Abc_InfoHasBit(&uCanonPhase, pCanonPerm[i]-'a'), i == nVars-1 ? "":"," );
+    printf( " )  " );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Apply decomposition to the truth table.]
+
+  Description [Returns the number of AIG nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_TruthNpnPerform( Abc_TtStore_t * p, int NpnType, int fVerbose )
+{
+    unsigned pAux[2048];
+    word pAuxWord[1024], pAuxWord1[1024];
+    char pCanonPerm[16];
+    unsigned uCanonPhase=0;
+    abctime clk = Abc_Clock();
+    int i;
+
+    char * pAlgoName = NULL;
+    if ( NpnType == 0 )
+        pAlgoName = "uniqifying         ";
+    else if ( NpnType == 1 )
+        pAlgoName = "exact NPN          ";
+    else if ( NpnType == 2 )
+        pAlgoName = "counting 1s        ";
+    else if ( NpnType == 3 )
+        pAlgoName = "Jake's hybrid fast ";
+    else if ( NpnType == 4 )
+        pAlgoName = "Jake's hybrid good ";
+    else if ( NpnType == 5 )
+        pAlgoName = "new hybrid fast    ";
+    else if ( NpnType == 6 )
+        pAlgoName = "new phase flipping ";
+
+    assert( p->nVars <= 16 );
+    if ( pAlgoName )
+        printf( "Applying %-20s to %8d func%s of %2d vars...  ",  
+            pAlgoName, p->nFuncs, (p->nFuncs == 1 ? "":"s"), p->nVars );
+    if ( fVerbose )
+        printf( "\n" );
+
+    if ( NpnType == 0 )
+    {
+        for ( i = 0; i < p->nFuncs; i++ )
+        {
+            if ( fVerbose )
+                printf( "%7d : ", i );
+            if ( fVerbose )
+                Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), printf( "\n" );
+        }
+    }
+    else if ( NpnType == 1 )
+    {
+        permInfo* pi; 
+        Abc_TruthNpnCountUnique(p);
+        pi = setPermInfoPtr(p->nVars);
+        for ( i = 0; i < p->nFuncs; i++ )
+        {
+            if ( fVerbose )
+                printf( "%7d : ", i );
+            simpleMinimal(p->pFuncs[i], pAuxWord, pAuxWord1, pi, p->nVars);
+            if ( fVerbose )
+                Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), Abc_TruthNpnPrint(pCanonPerm, uCanonPhase, p->nVars), printf( "\n" );
+        }
+        freePermInfoPtr(pi);
+    }
+    else if ( NpnType == 2 )
+    {
+        for ( i = 0; i < p->nFuncs; i++ )
+        {
+            if ( fVerbose )
+                printf( "%7d : ", i );
+            resetPCanonPermArray(pCanonPerm, p->nVars);
+            uCanonPhase = Kit_TruthSemiCanonicize( (unsigned *)p->pFuncs[i], pAux, p->nVars, pCanonPerm );
+            if ( fVerbose )
+                Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), Abc_TruthNpnPrint(pCanonPerm, uCanonPhase, p->nVars), printf( "\n" );
+        }
+    }
+    else if ( NpnType == 3 )
+    {
+        for ( i = 0; i < p->nFuncs; i++ )
+        {
+            if ( fVerbose )
+                printf( "%7d : ", i );
+            resetPCanonPermArray(pCanonPerm, p->nVars);
+            uCanonPhase = luckyCanonicizer_final_fast( p->pFuncs[i], p->nVars, pCanonPerm );
+            if ( fVerbose )
+                Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), Abc_TruthNpnPrint(pCanonPerm, uCanonPhase, p->nVars), printf( "\n" );
+        }
+    }
+    else if ( NpnType == 4 )
+    {
+        for ( i = 0; i < p->nFuncs; i++ )
+        {
+            if ( fVerbose )
+                printf( "%7d : ", i );
+            resetPCanonPermArray(pCanonPerm, p->nVars);
+            uCanonPhase = luckyCanonicizer_final_fast1( p->pFuncs[i], p->nVars, pCanonPerm );
+            if ( fVerbose )
+                Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), Abc_TruthNpnPrint(pCanonPerm, uCanonPhase, p->nVars), printf( "\n" );
+        }
+    }
+    else if ( NpnType == 5 )
+    {
+        for ( i = 0; i < p->nFuncs; i++ )
+        {
+            if ( fVerbose )
+                printf( "%7d : ", i );
+            uCanonPhase = Abc_TtCanonicize( p->pFuncs[i], p->nVars, pCanonPerm );
+            if ( fVerbose )
+                Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), Abc_TruthNpnPrint(pCanonPerm, uCanonPhase, p->nVars), printf( "\n" );
+        }
+    }
+    else if ( NpnType == 6 )
+    {
+        for ( i = 0; i < p->nFuncs; i++ )
+        {
+            if ( fVerbose )
+                printf( "%7d : ", i );
+            uCanonPhase = Abc_TtCanonicizePhase( p->pFuncs[i], p->nVars );
+            if ( fVerbose )
+                Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), Abc_TruthNpnPrint(NULL, uCanonPhase, p->nVars), printf( "\n" );
+        }
+    }
+    else assert( 0 );
+    clk = Abc_Clock() - clk;
+    printf( "Classes =%9d  ", Abc_TruthNpnCountUnique(p) );
+    Abc_PrintTime( 1, "Time", clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Apply decomposition to truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_TruthNpnTest( char * pFileName, int NpnType, int nVarNum, int fDumpRes, int fBinary, int fVerbose )
+{
+    Abc_TtStore_t * p;
+    char * pFileNameOut;
+
+    // read info from file
+    p = Abc_TtStoreLoad( pFileName, nVarNum );
+    if ( p == NULL )
+        return;
+
+    // consider functions from the file
+    Abc_TruthNpnPerform( p, NpnType, fVerbose );
+
+    // write the result
+    if ( fDumpRes )
+    {
+        if ( fBinary )
+            pFileNameOut = Extra_FileNameGenericAppend( pFileName, "_out.tt" );
+        else
+            pFileNameOut = Extra_FileNameGenericAppend( pFileName, "_out.txt" );
+        Abc_TtStoreWrite( pFileNameOut, p, fBinary );
+        if ( fVerbose )
+            printf( "The resulting functions are written into file \"%s\".\n", pFileNameOut );
+    }
+
+    // delete data-structure
+    Abc_TtStoreFree( p, nVarNum );
+//    printf( "Finished computing canonical forms for functions from file \"%s\".\n", pFileName );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Testbench for decomposition algorithms.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NpnTest( char * pFileName, int NpnType, int nVarNum, int fDumpRes, int fBinary, int fVerbose )
+{
+    if ( fVerbose )
+        printf( "Using truth tables from file \"%s\"...\n", pFileName );
+    if ( NpnType >= 0 && NpnType <= 6 )
+        Abc_TruthNpnTest( pFileName, NpnType, nVarNum, fDumpRes, fBinary, fVerbose );
+    else
+        printf( "Unknown canonical form value (%d).\n", NpnType );
+    fflush( stdout );
+    return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcNpnSave.c b/abc-build/src/base/abci/abcNpnSave.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcNpnSave.c
@@ -0,0 +1,740 @@
+/**CFile****************************************************************
+
+  FileName    [abcNpnSave.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Interface with the FPGA mapping package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: abcNpnSave.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "aig/aig/aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+typedef struct Npn_Obj_t_ Npn_Obj_t;
+typedef struct Npn_Man_t_ Npn_Man_t;
+
+struct Npn_Obj_t_
+{
+    word         uTruth;      // truth table
+    int          Count;       // occurances
+    int          iNext;       // next entry
+};
+struct Npn_Man_t_
+{
+    Npn_Obj_t *  pBuffer;     // all NPN entries
+    int *        pBins;       // hash table
+    int          nBins;       // hash table size
+    int          nBufferSize; // buffer size
+    int          nEntries;    // entry count
+};
+
+static inline Npn_Obj_t * Npn_ManObj( Npn_Man_t * p, int i )                 { assert( i < p->nBufferSize ); return i ? p->pBuffer + i : NULL;  }
+static inline int         Npn_ManObjNum( Npn_Man_t * p, Npn_Obj_t * pObj )   { assert( p->pBuffer < pObj );  return pObj - p->pBuffer;          }
+
+static word Truth[8] = {
+    ABC_CONST(0xAAAAAAAAAAAAAAAA),
+    ABC_CONST(0xCCCCCCCCCCCCCCCC),
+    ABC_CONST(0xF0F0F0F0F0F0F0F0),
+    ABC_CONST(0xFF00FF00FF00FF00),
+    ABC_CONST(0xFFFF0000FFFF0000),
+    ABC_CONST(0xFFFFFFFF00000000),
+    ABC_CONST(0x0000000000000000),
+    ABC_CONST(0xFFFFFFFFFFFFFFFF)
+};
+
+static Npn_Man_t * pNpnMan = NULL;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Npn_TruthPermute_rec( char * pStr, int mid, int end )
+{
+    static int count = 0;
+    char * pTemp = Abc_UtilStrsav(pStr);
+    char e;
+    int i;
+    if ( mid == end ) 
+    {
+        printf( "%03d: %s\n", count++, pTemp );
+        return ;
+    }
+    for ( i = mid; i <= end; i++ )
+    {
+        e = pTemp[mid];
+        pTemp[mid] = pTemp[i];
+        pTemp[i] = e;
+
+        Npn_TruthPermute_rec( pTemp, mid + 1, end );
+
+        e = pTemp[mid];
+        pTemp[mid] = pTemp[i];
+        pTemp[i] = e;
+    }
+    ABC_FREE( pTemp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Npn_TruthHasVar( word t, int v )
+{
+    return ((t & Truth[v]) >> (1<<v)) != (t & ~Truth[v]);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Npn_TruthSupport( word t )
+{
+    int v, Supp = 0;
+    for ( v = 0; v < 6; v++ )
+        if ( Npn_TruthHasVar( t, v ) )
+            Supp |= (1 << v);
+    return Supp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Npn_TruthSuppSize( word t, int nVars )
+{
+    int v, nSupp = 0;
+    assert( nVars <= 6 );
+    for ( v = 0; v < nVars; v++ )
+        if ( Npn_TruthHasVar( t, v ) )
+            nSupp++;
+    return nSupp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Npn_TruthIsMinBase( word t )
+{
+    int Supp = Npn_TruthSupport(t);
+    return (Supp & (Supp+1)) == 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word Npn_TruthPadWord( word uTruth, int nVars )
+{
+    if ( nVars == 6 )
+        return uTruth;
+    if ( nVars <= 5 )
+        uTruth = ((uTruth & ABC_CONST(0x00000000FFFFFFFF)) << 32) | (uTruth & ABC_CONST(0x00000000FFFFFFFF));
+    if ( nVars <= 4 )
+        uTruth = ((uTruth & ABC_CONST(0x0000FFFF0000FFFF)) << 16) | (uTruth & ABC_CONST(0x0000FFFF0000FFFF));
+    if ( nVars <= 3 )
+        uTruth = ((uTruth & ABC_CONST(0x00FF00FF00FF00FF)) <<  8) | (uTruth & ABC_CONST(0x00FF00FF00FF00FF));
+    if ( nVars <= 2 )
+        uTruth = ((uTruth & ABC_CONST(0x0F0F0F0F0F0F0F0F)) <<  4) | (uTruth & ABC_CONST(0x0F0F0F0F0F0F0F0F));
+    if ( nVars <= 1 )
+        uTruth = ((uTruth & ABC_CONST(0x3333333333333333)) <<  2) | (uTruth & ABC_CONST(0x3333333333333333));
+    if ( nVars == 0 )
+        uTruth = ((uTruth & ABC_CONST(0x5555555555555555)) <<  1) | (uTruth & ABC_CONST(0x5555555555555555));
+    return uTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Npn_TruthCountOnes( word t )
+{
+    t =    (t & ABC_CONST(0x5555555555555555)) + ((t>> 1) & ABC_CONST(0x5555555555555555));
+    t =    (t & ABC_CONST(0x3333333333333333)) + ((t>> 2) & ABC_CONST(0x3333333333333333));
+    t =    (t & ABC_CONST(0x0F0F0F0F0F0F0F0F)) + ((t>> 4) & ABC_CONST(0x0F0F0F0F0F0F0F0F));
+    t =    (t & ABC_CONST(0x00FF00FF00FF00FF)) + ((t>> 8) & ABC_CONST(0x00FF00FF00FF00FF));
+    t =    (t & ABC_CONST(0x0000FFFF0000FFFF)) + ((t>>16) & ABC_CONST(0x0000FFFF0000FFFF));
+    return (t & ABC_CONST(0x00000000FFFFFFFF)) +  (t>>32);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Npn_TruthChangePhase( word t, int v )
+{
+    return ((t & Truth[v]) >> (1<<v)) | ((t & ~Truth[v]) << (1<<v));
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Npn_TruthSwapAdjacentVars( word t, int v )
+{
+    static word PMasks[5][3] = {
+        { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) },
+        { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) },
+        { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) },
+        { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) },
+        { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) }
+    };
+    assert( v < 6 );
+    return (t & PMasks[v][0]) | ((t & PMasks[v][1]) << (1 << v)) | ((t & PMasks[v][2]) >> (1 << v));
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Npn_TruthCanon( word t, int nVars, int * pPhase )
+{
+    int fUsePolarity    = 0;
+    int fUsePermutation = 0;
+    char Temp, pSigs[13], pCanonPerm[6];
+    int v, fChange, CanonPhase = 0;
+    assert( nVars < 7 );
+    pSigs[12] = Npn_TruthCountOnes( t );
+    if ( pSigs[12] > 32 )
+    {
+        t = ~t;
+        pSigs[12] = 64 - pSigs[12];
+        CanonPhase |= (1 << 6);
+    }
+    if ( fUsePolarity || fUsePermutation )
+    {
+        for ( v = 0; v < nVars; v++ )
+        {
+            pCanonPerm[v] = v;
+            pSigs[2*v+1] = Npn_TruthCountOnes( t & Truth[v] );
+            pSigs[2*v] = pSigs[12] - pSigs[2*v+1];
+        }
+    }
+    if ( fUsePolarity )
+    {
+        for ( v = 0; v < nVars; v++ )
+        {
+            if ( pSigs[2*v] >= pSigs[2*v+1] )
+                continue;
+            CanonPhase |= (1 << v);
+            Temp = pSigs[2*v];
+            pSigs[2*v] = pSigs[2*v+1];
+            pSigs[2*v+1] = Temp;
+            t = Npn_TruthChangePhase( t, v );
+        }
+    }
+    if ( fUsePermutation )
+    {
+        do {
+            fChange = 0;
+            for ( v = 0; v < nVars-1; v++ )
+            {
+                if ( fUsePolarity )
+                {
+                    if ( pSigs[2*v] >= pSigs[2*(v+1)] )
+                        continue;
+                }
+                else
+                {
+                    if ( Abc_MinInt(pSigs[2*v],pSigs[2*v+1]) >= Abc_MinInt(pSigs[2*(v+1)],pSigs[2*(v+1)+1]) )
+                        continue;
+                }
+                fChange = 1;
+
+                Temp = pCanonPerm[v];
+                pCanonPerm[v] = pCanonPerm[v+1];
+                pCanonPerm[v+1] = Temp;
+
+                Temp = pSigs[2*v];
+                pSigs[2*v] = pSigs[2*(v+1)];
+                pSigs[2*(v+1)] = Temp;
+
+                Temp = pSigs[2*v+1];
+                pSigs[2*v+1] = pSigs[2*(v+1)+1];
+                pSigs[2*(v+1)+1] = Temp;
+
+                t = Npn_TruthSwapAdjacentVars( t, v );
+            }
+        } while ( fChange );
+    }
+    if ( pPhase )
+    {
+        *pPhase = 0;
+        for ( v = 0; v < nVars; v++ )
+            *pPhase |= (pCanonPerm[v] << (4 * v));
+        *pPhase |= (CanonPhase << 24);
+    }
+    return t;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the hash key.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Npn_ManHash( Npn_Man_t * p, word uTruth )
+{
+    word Key = (uTruth * (word)101) ^ (uTruth * (word)733) ^ (uTruth * (word)1777);
+    return (int)(Key % (word)p->nBins);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Npn_ManResize( Npn_Man_t * p )
+{
+    Npn_Obj_t * pEntry, * pNext;
+    int * pBinsOld, * ppPlace;
+    int nBinsOld, Counter, i;
+    abctime clk;
+    assert( p->pBins != NULL );
+clk = Abc_Clock();
+    // save the old Bins
+    pBinsOld = p->pBins;
+    nBinsOld = p->nBins;
+    // get the new Bins
+    p->nBins = Abc_PrimeCudd( 3 * nBinsOld ); 
+    p->pBins = ABC_CALLOC( int, p->nBins );
+    // rehash the entries from the old table
+    Counter = 1;
+    for ( i = 0; i < nBinsOld; i++ )
+    for ( pEntry = Npn_ManObj(p, pBinsOld[i]), 
+          pNext = pEntry ? Npn_ManObj(p, pEntry->iNext) : NULL; 
+          pEntry; 
+          pEntry = pNext, 
+          pNext = pEntry ? Npn_ManObj(p, pEntry->iNext) : NULL )
+    {
+        // get the place where this entry goes 
+        ppPlace = p->pBins + Npn_ManHash( p, pEntry->uTruth );
+        // add the entry to the list
+        pEntry->iNext = *ppPlace;
+        *ppPlace = Npn_ManObjNum( p, pEntry );
+        Counter++;
+    }
+    assert( Counter == p->nEntries );
+    ABC_FREE( pBinsOld );
+//ABC_PRT( "Hash table resizing time", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one entry to the table.]
+
+  Description [Increments ref counter by 1.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Npn_Obj_t * Npn_ManAdd( Npn_Man_t * p, word uTruth )
+{
+    Npn_Obj_t * pEntry;
+    int * pPlace, Key = Npn_ManHash( p, uTruth );
+    // resize the link storage if needed
+    if ( p->nEntries == p->nBufferSize )
+    {
+        p->nBufferSize *= 2;
+        p->pBuffer = ABC_REALLOC( Npn_Obj_t, p->pBuffer, p->nBufferSize );
+    }
+    // find the entry
+    for ( pEntry = Npn_ManObj(p, p->pBins[Key]), 
+          pPlace = p->pBins + Key; 
+          pEntry; 
+          pPlace = &pEntry->iNext, 
+          pEntry = Npn_ManObj(p, pEntry->iNext) )
+        if ( pEntry->uTruth == uTruth )
+        {
+            pEntry->Count++;
+            return pEntry;
+        }
+    // create new entry
+    *pPlace = p->nEntries;
+    assert( p->nEntries < p->nBufferSize );
+    pEntry = Npn_ManObj( p, p->nEntries++ );
+    pEntry->uTruth = uTruth;
+    pEntry->Count = 1;
+    pEntry->iNext = 0;
+    // resize the table if needed
+    if ( p->nEntries > 3 * p->nBins )
+        Npn_ManResize( p );
+    return pEntry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fills table from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Npn_ManRead( Npn_Man_t * p, char * pFileName )
+{
+    char pBuffer[1000];
+    char * pToken;
+    Npn_Obj_t * pEntry;
+    unsigned Truth[2];
+    word uTruth;
+    FILE * pFile = fopen( pFileName, "r" );
+    if ( pFile == NULL )
+    {
+        Abc_Print( -1, "Cannot open NPN function file \"%s\".\n", pFileName );
+        return;
+    }
+    // read lines from the file
+    while ( fgets( pBuffer, 1000, pFile ) != NULL )
+    {
+        pToken = strtok( pBuffer, " \t\n" );
+        if ( pToken == NULL )
+            continue;
+        if ( pToken[0] == '#' )
+            continue;
+        if ( strlen(pToken) != 16 )
+        {
+            Abc_Print( 0, "Skipping token %s that does not look like a 16-digit hex number.\n" );
+            continue;
+        }
+        // extract truth table
+        Extra_ReadHexadecimal( Truth, pToken, 6 );
+        uTruth = (((word)Truth[1]) << 32) | (word)Truth[0];
+        // add truth table
+        pEntry = Npn_ManAdd( p, uTruth );
+        assert( pEntry->Count == 1 );
+        // read area
+        pToken = strtok( NULL, " \t\n" );
+        pEntry->Count = atoi(pToken);
+    }
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Npn_ManCompareEntries( Npn_Obj_t ** pp1, Npn_Obj_t ** pp2 )
+{
+    if ( (*pp1)->Count > (*pp2)->Count )
+        return -1;
+    if ( (*pp1)->Count < (*pp2)->Count ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one entry to the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Npn_ManWrite( Npn_Man_t * p, char * pFileName )
+{
+    Vec_Ptr_t * vEntries;
+    Npn_Obj_t * pEntry;
+    FILE * pFile = fopen( pFileName, "w" );
+    int i;
+    if ( pFile == NULL )
+    {
+        Abc_Print( -1, "Cannot open NPN function file \"%s\".\n", pFileName );
+        return;
+    }
+    vEntries = Vec_PtrAlloc( p->nEntries );
+    for ( i = 0; i < p->nBins; i++ )
+        for ( pEntry = Npn_ManObj(p, p->pBins[i]); pEntry; pEntry = Npn_ManObj(p, pEntry->iNext) )
+            Vec_PtrPush( vEntries, pEntry );
+    Vec_PtrSort( vEntries, (int (*)())Npn_ManCompareEntries );
+    Vec_PtrForEachEntry( Npn_Obj_t *, vEntries, pEntry, i )
+    {
+        Extra_PrintHexadecimal( pFile, (unsigned *)&pEntry->uTruth, 6 );
+        fprintf( pFile, " %d %d\n", pEntry->Count, Npn_TruthSuppSize(pEntry->uTruth, 6) );
+    }
+    fclose( pFile );
+    Vec_PtrFree( vEntries );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Npn_Man_t * Npn_ManStart( char * pFileName )
+{
+    Npn_Man_t * p;
+    p = ABC_CALLOC( Npn_Man_t, 1 );
+    if ( pFileName == NULL )
+    {
+        p->nBufferSize = 1000000;
+        p->nBufferSize = 100;
+        p->pBuffer     = ABC_ALLOC( Npn_Obj_t, p->nBufferSize );
+        p->nBins       = Abc_PrimeCudd( p->nBufferSize / 2 );
+        p->pBins       = ABC_CALLOC( int, p->nBins );
+        p->nEntries    = 1;
+    }
+    else
+    {
+        FILE * pFile = fopen( pFileName, "r" );
+        if ( pFile == NULL )
+        {
+            Abc_Print( -1, "Cannot open NPN function file \"%s\".\n", pFileName );
+            return NULL;
+        }
+        fclose( pFile );
+        p->nBufferSize = 4 * ( Extra_FileSize(pFileName) / 20 );
+        p->pBuffer     = ABC_ALLOC( Npn_Obj_t, p->nBufferSize );
+        p->nBins       = Abc_PrimeCudd( p->nBufferSize / 2 );
+        p->pBins       = ABC_CALLOC( int, p->nBins );
+        p->nEntries    = 1;
+        Npn_ManRead( p, pFileName );
+    }
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Npn_ManStop( Npn_Man_t * p )
+{
+    ABC_FREE( p->pBuffer );
+    ABC_FREE( p->pBins );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Npn_ManClean()
+{
+    if ( pNpnMan != NULL )
+    {
+        Npn_ManStop( pNpnMan );
+        pNpnMan = NULL;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Loads functions from a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Npn_ManLoad( char * pFileName )
+{
+//    Npn_TruthPermute_rec( "012345", 0, 5 );
+    if ( pNpnMan != NULL )
+    {
+        Abc_Print( 1, "Removing old table with %d entries.\n", pNpnMan->nEntries );
+        Npn_ManStop( pNpnMan );
+    }
+    pNpnMan = Npn_ManStart( pFileName );
+    Abc_Print( 1, "Created new table with %d entries from file \"%s\".\n", pNpnMan->nEntries, pFileName );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Saves functions into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Npn_ManSave( char * pFileName )
+{
+    if ( pNpnMan == NULL )
+    {
+        Abc_Print( 1, "There is no table with entries.\n" );
+        return;
+    }
+    Npn_ManWrite( pNpnMan, pFileName );
+    Abc_Print( 1, "Dumped table with %d entries from file \"%s\".\n", pNpnMan->nEntries, pFileName );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Saves one function into storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Npn_ManSaveOne( unsigned * puTruth, int nVars )
+{
+    word uTruth = (((word)puTruth[1]) << 32) | (word)puTruth[0];
+    assert( nVars >= 0 && nVars <= 6 );
+    if ( pNpnMan == NULL )
+    {
+        Abc_Print( 1, "Creating new table with 0 entries.\n" );
+        pNpnMan = Npn_ManStart( NULL );
+    }
+    // skip truth tables that do not depend on some vars
+    if ( !Npn_TruthIsMinBase( uTruth ) )
+        return;
+    // extend truth table to look like 6-input
+    uTruth = Npn_TruthPadWord( uTruth, nVars );
+    // semi(!)-NPN-canonize the truth table
+    uTruth = Npn_TruthCanon( uTruth, 6, NULL );
+    // add to storage
+    Npn_ManAdd( pNpnMan, uTruth );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcNtbdd.c b/abc-build/src/base/abci/abcNtbdd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcNtbdd.c
@@ -0,0 +1,602 @@
+/**CFile****************************************************************
+
+  FileName    [abcNtbdd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Procedures to translate between the BDD and the network.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcNtbdd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void        Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
+static Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew );
+static Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * pNtkNew, st__table * tBdd2Node );
+static DdNode *    Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs the network isomorphic to the given BDD.]
+
+  Description [Assumes that the BDD depends on the variables whose indexes
+  correspond to the names in the array (pNamesPi). Otherwise, returns NULL.
+  The resulting network comes with one node, whose functionality is
+  equal to the given BDD. To decompose this BDD into the network of
+  multiplexers use Abc_NtkBddToMuxes(). To decompose this BDD into
+  an And-Inverter Graph, use Abc_NtkStrash().]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDeriveFromBdd( void * dd0, void * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi )
+{
+    DdManager * dd = (DdManager *)dd0;
+    Abc_Ntk_t * pNtk; 
+    Vec_Ptr_t * vNamesPiFake = NULL;
+    Abc_Obj_t * pNode, * pNodePi, * pNodePo;
+    DdNode * bSupp, * bTemp;
+    char * pName;
+    int i;
+
+    // supply fake names if real names are not given
+    if ( pNamePo == NULL )
+        pNamePo = "F";
+    if ( vNamesPi == NULL )
+    {
+        vNamesPiFake = Abc_NodeGetFakeNames( dd->size );
+        vNamesPi = vNamesPiFake;
+    }
+
+    // make sure BDD depends on the variables whose index 
+    // does not exceed the size of the array with PI names
+    bSupp = Cudd_Support( dd, (DdNode *)bFunc );   Cudd_Ref( bSupp );
+    for ( bTemp = bSupp; bTemp != Cudd_ReadOne(dd); bTemp = cuddT(bTemp) )
+        if ( (int)Cudd_NodeReadIndex(bTemp) >= Vec_PtrSize(vNamesPi) )
+            break;
+    Cudd_RecursiveDeref( dd, bSupp );
+    if ( bTemp != Cudd_ReadOne(dd) )
+        return NULL;
+
+    // start the network
+    pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 );
+    pNtk->pName = Extra_UtilStrsav(pNamePo);
+    // make sure the new manager has enough inputs
+    Cudd_bddIthVar( (DdManager *)pNtk->pManFunc, Vec_PtrSize(vNamesPi) );
+    // add the PIs corresponding to the names
+    Vec_PtrForEachEntry( char *, vNamesPi, pName, i )
+        Abc_ObjAssignName( Abc_NtkCreatePi(pNtk), pName, NULL );
+    // create the node
+    pNode = Abc_NtkCreateNode( pNtk );
+    pNode->pData = (DdNode *)Cudd_bddTransfer( dd, (DdManager *)pNtk->pManFunc, (DdNode *)bFunc ); Cudd_Ref((DdNode *)pNode->pData);
+    Abc_NtkForEachPi( pNtk, pNodePi, i )
+        Abc_ObjAddFanin( pNode, pNodePi );
+    // create the only PO
+    pNodePo = Abc_NtkCreatePo( pNtk );
+    Abc_ObjAddFanin( pNodePo, pNode );
+    Abc_ObjAssignName( pNodePo, pNamePo, NULL );
+    // make the network minimum base
+    Abc_NtkMinimumBase( pNtk );
+    if ( vNamesPiFake )
+        Abc_NodeFreeNames( vNamesPiFake );
+    if ( !Abc_NtkCheck( pNtk ) )
+        fprintf( stdout, "Abc_NtkDeriveFromBdd(): Network check has failed.\n" );
+    return pNtk;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the network isomorphic to the union of local BDDs of the nodes.]
+
+  Description [The nodes of the local BDDs are converted into the network nodes 
+  with logic functions equal to the MUX.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew;
+    assert( Abc_NtkIsBddLogic(pNtk) );
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+    Abc_NtkBddToMuxesPerform( pNtk, pNtkNew );
+    Abc_NtkFinalize( pNtk, pNtkNew );
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkBddToMuxes: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network to MUXes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
+{
+    ProgressBar * pProgress;
+    Abc_Obj_t * pNode, * pNodeNew;
+    Vec_Ptr_t * vNodes;
+    int i;
+    // perform conversion in the topological order
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        // convert one node
+        assert( Abc_ObjIsNode(pNode) );
+        pNodeNew = Abc_NodeBddToMuxes( pNode, pNtkNew );
+        // mark the old node with the new one
+        assert( pNode->pCopy == NULL );
+        pNode->pCopy = pNodeNew;
+    }
+    Vec_PtrFree( vNodes );
+    Extra_ProgressBarStop( pProgress );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the node to MUXes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew )
+{
+    DdManager * dd = (DdManager *)pNodeOld->pNtk->pManFunc;
+    DdNode * bFunc = (DdNode *)pNodeOld->pData;
+    Abc_Obj_t * pFaninOld, * pNodeNew;
+    st__table * tBdd2Node;
+    int i;
+    // create the table mapping BDD nodes into the ABC nodes
+    tBdd2Node = st__init_table( st__ptrcmp, st__ptrhash );
+    // add the constant and the elementary vars
+    Abc_ObjForEachFanin( pNodeOld, pFaninOld, i )
+        st__insert( tBdd2Node, (char *)Cudd_bddIthVar(dd, i), (char *)pFaninOld->pCopy );
+    // create the new nodes recursively
+    pNodeNew = Abc_NodeBddToMuxes_rec( dd, Cudd_Regular(bFunc), pNtkNew, tBdd2Node );
+    st__free_table( tBdd2Node );
+    if ( Cudd_IsComplement(bFunc) )
+        pNodeNew = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew );
+    return pNodeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the node to MUXes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * pNtkNew, st__table * tBdd2Node )
+{
+    Abc_Obj_t * pNodeNew, * pNodeNew0, * pNodeNew1, * pNodeNewC;
+    assert( !Cudd_IsComplement(bFunc) );
+    if ( bFunc == b1 )
+        return Abc_NtkCreateNodeConst1(pNtkNew);
+    if ( st__lookup( tBdd2Node, (char *)bFunc, (char **)&pNodeNew ) )
+        return pNodeNew;
+    // solve for the children nodes
+    pNodeNew0 = Abc_NodeBddToMuxes_rec( dd, Cudd_Regular(cuddE(bFunc)), pNtkNew, tBdd2Node );
+    if ( Cudd_IsComplement(cuddE(bFunc)) )
+        pNodeNew0 = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew0 );
+    pNodeNew1 = Abc_NodeBddToMuxes_rec( dd, cuddT(bFunc), pNtkNew, tBdd2Node );
+    if ( ! st__lookup( tBdd2Node, (char *)Cudd_bddIthVar(dd, bFunc->index), (char **)&pNodeNewC ) )
+        assert( 0 );
+    // create the MUX node
+    pNodeNew = Abc_NtkCreateNodeMux( pNtkNew, pNodeNewC, pNodeNew1, pNodeNew0 );
+    st__insert( tBdd2Node, (char *)bFunc, (char *)pNodeNew );
+    return pNodeNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives global BDDs for the COs of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose )
+{
+    ProgressBar * pProgress;
+    Abc_Obj_t * pObj, * pFanin;
+    Vec_Att_t * pAttMan;
+    DdManager * dd;
+    DdNode * bFunc;
+    int i, k, Counter;
+
+    // remove dangling nodes
+    Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc );
+
+    // start the manager
+    assert( Abc_NtkGlobalBdd(pNtk) == NULL );
+    dd = Cudd_Init( Abc_NtkCiNum(pNtk), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    pAttMan = Vec_AttAlloc( Abc_NtkObjNumMax(pNtk) + 1, dd, (void (*)(void*))Extra_StopManager, NULL, (void (*)(void*,void*))Cudd_RecursiveDeref );
+    Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_GLOBAL_BDD, pAttMan );
+
+    // set reordering
+    if ( fReorder )
+        Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+
+    // assign the constant node BDD
+    pObj = Abc_AigConst1(pNtk);
+    if ( Abc_ObjFanoutNum(pObj) > 0 )
+    {
+        bFunc = dd->one;
+        Abc_ObjSetGlobalBdd( pObj, bFunc );   Cudd_Ref( bFunc );
+    }
+    // set the elementary variables
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        if ( Abc_ObjFanoutNum(pObj) > 0 )
+        {
+            bFunc = dd->vars[i];
+//            bFunc = dd->vars[Abc_NtkCiNum(pNtk) - 1 - i];
+            Abc_ObjSetGlobalBdd( pObj, bFunc );  Cudd_Ref( bFunc );
+        }
+
+    // collect the global functions of the COs
+    Counter = 0;
+    // construct the BDDs
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pObj), nBddSizeMax, fDropInternal, pProgress, &Counter, fVerbose );
+        if ( bFunc == NULL )
+        {
+            if ( fVerbose )
+            printf( "Constructing global BDDs is aborted.\n" );
+            Abc_NtkFreeGlobalBdds( pNtk, 0 );
+            Cudd_Quit( dd ); 
+
+            // reset references
+            Abc_NtkForEachObj( pNtk, pObj, i )
+                if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBi(pObj) )
+                    pObj->vFanouts.nSize = 0;
+            Abc_NtkForEachObj( pNtk, pObj, i )
+                if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) )
+                    Abc_ObjForEachFanin( pObj, pFanin, k )
+                        pFanin->vFanouts.nSize++;
+            return NULL;
+        }
+        bFunc = Cudd_NotCond( bFunc, (int)Abc_ObjFaninC0(pObj) );  Cudd_Ref( bFunc ); 
+        Abc_ObjSetGlobalBdd( pObj, bFunc );
+    }
+    Extra_ProgressBarStop( pProgress );
+
+/*
+    // derefence the intermediate BDDs
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        if ( pObj->pCopy ) 
+        {
+            Cudd_RecursiveDeref( dd, (DdNode *)pObj->pCopy );
+            pObj->pCopy = NULL;
+        }
+*/
+/*
+    // make sure all nodes are derefed
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        if ( pObj->pCopy != NULL )
+            printf( "Abc_NtkBuildGlobalBdds() error: Node %d has BDD assigned\n", pObj->Id );
+        if ( pObj->vFanouts.nSize > 0 )
+            printf( "Abc_NtkBuildGlobalBdds() error: Node %d has refs assigned\n", pObj->Id );
+    }
+*/
+    // reset references
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBi(pObj) )
+            pObj->vFanouts.nSize = 0;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) )
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                pFanin->vFanouts.nSize++;
+
+    // reorder one more time
+    if ( fReorder )
+    {
+        Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 );
+        Cudd_AutodynDisable( dd );
+    }
+//    Cudd_PrintInfo( dd, stdout );
+    return dd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the global BDD for one AIG node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose )
+{
+    DdNode * bFunc, * bFunc0, * bFunc1, * bFuncC;
+    int fDetectMuxes = 1;
+    assert( !Abc_ObjIsComplement(pNode) );
+    if ( Cudd_ReadKeys(dd)-Cudd_ReadDead(dd) > (unsigned)nBddSizeMax )
+    {
+        Extra_ProgressBarStop( pProgress );
+        if ( fVerbose )
+        printf( "The number of live nodes reached %d.\n", nBddSizeMax );
+        fflush( stdout );
+        return NULL;
+    }
+    // if the result is available return
+    if ( Abc_ObjGlobalBdd(pNode) == NULL )
+    {
+        Abc_Obj_t * pNodeC, * pNode0, * pNode1;
+        pNode0 = Abc_ObjFanin0(pNode);
+        pNode1 = Abc_ObjFanin1(pNode);
+        // check for the special case when it is MUX/EXOR
+        if ( fDetectMuxes && 
+             Abc_ObjGlobalBdd(pNode0) == NULL && Abc_ObjGlobalBdd(pNode1) == NULL &&
+             Abc_ObjIsNode(pNode0) && Abc_ObjFanoutNum(pNode0) == 1 && 
+             Abc_ObjIsNode(pNode1) && Abc_ObjFanoutNum(pNode1) == 1 && 
+             Abc_NodeIsMuxType(pNode) )
+        {
+            // deref the fanins
+            pNode0->vFanouts.nSize--;
+            pNode1->vFanouts.nSize--;
+            // recognize the MUX
+            pNodeC = Abc_NodeRecognizeMux( pNode, &pNode1, &pNode0 );
+            assert( Abc_ObjFanoutNum(pNodeC) > 1 );
+            // dereference the control once (the second time it will be derefed when BDDs are computed)
+            pNodeC->vFanouts.nSize--;
+
+            // compute the result for all branches
+            bFuncC = Abc_NodeGlobalBdds_rec( dd, pNodeC, nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); 
+            if ( bFuncC == NULL )
+                return NULL;
+            Cudd_Ref( bFuncC );
+            bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode0), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); 
+            if ( bFunc0 == NULL )
+                return NULL;
+            Cudd_Ref( bFunc0 );
+            bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode1), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); 
+            if ( bFunc1 == NULL )
+                return NULL;
+            Cudd_Ref( bFunc1 );
+
+            // complement the branch BDDs
+            bFunc0 = Cudd_NotCond( bFunc0, (int)Abc_ObjIsComplement(pNode0) );
+            bFunc1 = Cudd_NotCond( bFunc1, (int)Abc_ObjIsComplement(pNode1) );
+            // get the final result
+            bFunc = Cudd_bddIte( dd, bFuncC, bFunc1, bFunc0 );   Cudd_Ref( bFunc );
+            Cudd_RecursiveDeref( dd, bFunc0 );
+            Cudd_RecursiveDeref( dd, bFunc1 );
+            Cudd_RecursiveDeref( dd, bFuncC );
+            // add the number of used nodes
+            (*pCounter) += 3;
+        }
+        else
+        {
+            // compute the result for both branches
+            bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,0), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); 
+            if ( bFunc0 == NULL )
+                return NULL;
+            Cudd_Ref( bFunc0 );
+            bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,1), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); 
+            if ( bFunc1 == NULL )
+                return NULL;
+            Cudd_Ref( bFunc1 );
+            bFunc0 = Cudd_NotCond( bFunc0, (int)Abc_ObjFaninC0(pNode) );
+            bFunc1 = Cudd_NotCond( bFunc1, (int)Abc_ObjFaninC1(pNode) );
+            // get the final result
+            bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 );   Cudd_Ref( bFunc );
+            Cudd_RecursiveDeref( dd, bFunc0 );
+            Cudd_RecursiveDeref( dd, bFunc1 );
+            // add the number of used nodes
+            (*pCounter)++;
+        }
+        // set the result
+        assert( Abc_ObjGlobalBdd(pNode) == NULL );
+        Abc_ObjSetGlobalBdd( pNode, bFunc );
+        // increment the progress bar
+        if ( pProgress )
+            Extra_ProgressBarUpdate( pProgress, *pCounter, NULL );
+    }
+    // prepare the return value
+    bFunc = (DdNode *)Abc_ObjGlobalBdd(pNode);
+    // dereference BDD at the node
+    if ( --pNode->vFanouts.nSize == 0 && fDropInternal )
+    {
+        Cudd_Deref( bFunc );
+        Abc_ObjSetGlobalBdd( pNode, NULL );
+    }
+    return bFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the global BDDs of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan ) 
+{ 
+    return Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, fFreeMan ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the shared size of global BDDs of the COs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkSizeOfGlobalBdds( Abc_Ntk_t * pNtk ) 
+{
+    Vec_Ptr_t * vFuncsGlob;
+    Abc_Obj_t * pObj;
+    int RetValue, i;
+    // complement the global functions
+    vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) );
+    RetValue = Cudd_SharingSize( (DdNode **)Vec_PtrArray(vFuncsGlob), Vec_PtrSize(vFuncsGlob) );
+    Vec_PtrFree( vFuncsGlob );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the BDD of the logic cone of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+double Abc_NtkSpacePercentage( Abc_Obj_t * pNode )
+{
+    /*
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj, * pNodeR;
+    DdManager * dd;
+    DdNode * bFunc;
+    double Result;
+    int i;
+    pNodeR = Abc_ObjRegular(pNode);
+    assert( Abc_NtkIsStrash(pNodeR->pNtk) );
+    Abc_NtkCleanCopy( pNodeR->pNtk );
+    // get the CIs in the support of the node
+    vNodes = Abc_NtkNodeSupport( pNodeR->pNtk, &pNodeR, 1 );
+    // start the manager
+    dd = Cudd_Init( Vec_PtrSize(vNodes), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+    // assign elementary BDDs for the CIs
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)dd->vars[i];
+    // build the BDD of the cone
+    bFunc = Abc_NodeGlobalBdds_rec( dd, pNodeR, 10000000, 1, NULL, NULL, 1 );  Cudd_Ref( bFunc );
+    bFunc = Cudd_NotCond( bFunc, pNode != pNodeR );
+    // count minterms
+    Result = Cudd_CountMinterm( dd, bFunc, dd->size );
+    // get the percentagle
+    Result *= 100.0;
+    for ( i = 0; i < dd->size; i++ )
+        Result /= 2;
+    // clean up
+    Cudd_Quit( dd );
+    Vec_PtrFree( vNodes );
+    return Result;
+    */
+    return 0.0;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Experiment with BDD-based representation of implications.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkBddImplicationTest()
+{
+    DdManager * dd;
+    DdNode * bImp, * bSum, * bTemp;
+    int nVars = 200;
+    int nImps = 200;
+    int i;
+    abctime clk;
+clk = Abc_Clock();
+    dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    Cudd_AutodynEnable( dd, CUDD_REORDER_SIFT );
+    bSum = b0;   Cudd_Ref( bSum );
+    for ( i = 0; i < nImps; i++ )
+    {
+        printf( "." );
+        bImp = Cudd_bddAnd( dd, dd->vars[rand()%nVars], dd->vars[rand()%nVars] );  Cudd_Ref( bImp );
+        bSum = Cudd_bddOr( dd, bTemp = bSum, bImp );     Cudd_Ref( bSum );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bImp );
+    }
+    printf( "The BDD before = %d.\n", Cudd_DagSize(bSum) );
+    Cudd_ReduceHeap( dd, CUDD_REORDER_SIFT, 1 );
+    printf( "The BDD after  = %d.\n", Cudd_DagSize(bSum) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+    Cudd_RecursiveDeref( dd, bSum );
+    Cudd_Quit( dd );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcOdc.c b/abc-build/src/base/abci/abcOdc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcOdc.c
@@ -0,0 +1,1132 @@
+/**CFile****************************************************************
+
+  FileName    [abcOdc.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Scalable computation of observability don't-cares.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcOdc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define ABC_DC_MAX_NODES   (1<<15)
+
+typedef unsigned short Odc_Lit_t;
+
+typedef struct Odc_Obj_t_ Odc_Obj_t;     // 16 bytes
+struct Odc_Obj_t_
+{
+    Odc_Lit_t               iFan0;       // first fanin
+    Odc_Lit_t               iFan1;       // second fanin
+    Odc_Lit_t               iNext;       // next node in the hash table
+    unsigned short          TravId;      // the traversal ID
+    unsigned                uData;       // the computed data
+    unsigned                uMask;       // the variable mask 
+};
+
+struct Odc_Man_t_
+{
+    // dont'-care parameters
+    int                     nVarsMax;    // the max number of cut variables
+    int                     nLevels;     // the number of ODC levels
+    int                     fVerbose;    // the verbosiness flag
+    int                     fVeryVerbose;// the verbosiness flag to print per-node stats
+    int                     nPercCutoff; // cutoff percentage
+
+    // windowing
+    Abc_Obj_t *             pNode;       // the node for windowing
+    Vec_Ptr_t *             vLeaves;     // the number of the cut
+    Vec_Ptr_t *             vRoots;      // the roots of the cut
+    Vec_Ptr_t *             vBranches;   // additional inputs 
+
+    // internal AIG package
+    // objects
+    int                     nPis;        // number of PIs (nVarsMax + 32)
+    int                     nObjs;       // number of objects (Const1, PIs, ANDs)
+    int                     nObjsAlloc;  // number of objects allocated
+    Odc_Obj_t *             pObjs;       // objects 
+    Odc_Lit_t               iRoot;       // the root object
+    unsigned short          nTravIds;    // the number of travIDs
+    // structural hashing
+    Odc_Lit_t *             pTable;      // hash table
+    int                     nTableSize;  // hash table size
+    Vec_Int_t *             vUsedSpots;  // the used spots
+
+    // truth tables
+    int                     nBits;       // the number of bits
+    int                     nWords;      // the number of words 
+    Vec_Ptr_t *             vTruths;     // truth tables for each node
+    Vec_Ptr_t *             vTruthsElem; // elementary truth tables for the PIs
+    unsigned *              puTruth;     // the place where the resulting truth table does
+
+    // statistics
+    int                     nWins;       // the number of windows processed
+    int                     nWinsEmpty;  // the number of empty windows
+    int                     nSimsEmpty;  // the number of empty simulation infos
+    int                     nQuantsOver; // the number of quantification overflows
+    int                     nWinsFinish; // the number of windows that finished
+    int                     nTotalDcs;   // total percentage of DCs
+
+    // runtime
+    abctime                 timeClean;   // windowing
+    abctime                 timeWin;     // windowing
+    abctime                 timeMiter;   // computing the miter
+    abctime                 timeSim;     // simulation
+    abctime                 timeQuant;   // quantification
+    abctime                 timeTruth;   // truth table
+    abctime                 timeTotal;   // useful runtime
+    abctime                 timeAbort;   // aborted runtime
+};
+
+
+// quantity of different objects
+static inline int           Odc_PiNum( Odc_Man_t * p )                     { return p->nPis;                       }
+static inline int           Odc_NodeNum( Odc_Man_t * p )                   { return p->nObjs - p->nPis - 1;        }
+static inline int           Odc_ObjNum( Odc_Man_t * p )                    { return p->nObjs;                      }
+
+// complemented attributes of objects
+static inline int           Odc_IsComplement( Odc_Lit_t Lit )              { return Lit &  (Odc_Lit_t)1;           }
+static inline Odc_Lit_t     Odc_Regular( Odc_Lit_t Lit )                   { return Lit & ~(Odc_Lit_t)1;           }
+static inline Odc_Lit_t     Odc_Not( Odc_Lit_t Lit )                       { return Lit ^  (Odc_Lit_t)1;           }
+static inline Odc_Lit_t     Odc_NotCond( Odc_Lit_t Lit, int c )            { return Lit ^  (Odc_Lit_t)(c!=0);      }
+
+// specialized Literals
+static inline Odc_Lit_t     Odc_Const0()                                   { return 1;                             }
+static inline Odc_Lit_t     Odc_Const1()                                   { return 0;                             }
+static inline Odc_Lit_t     Odc_Var( Odc_Man_t * p, int i )                { assert( i >= 0 && i < p->nPis ); return (i+1) << 1;  }
+static inline int           Odc_IsConst( Odc_Lit_t Lit )                   { return Lit <  (Odc_Lit_t)2;           }
+static inline int           Odc_IsTerm( Odc_Man_t * p, Odc_Lit_t Lit )     { return (int)(Lit>>1) <= p->nPis;      }
+
+// accessing internal storage
+static inline Odc_Obj_t *   Odc_ObjNew( Odc_Man_t * p )                    { assert( p->nObjs < p->nObjsAlloc ); return p->pObjs + p->nObjs++;        }
+static inline Odc_Lit_t     Odc_Obj2Lit( Odc_Man_t * p, Odc_Obj_t * pObj ) { assert( pObj ); return (pObj - p->pObjs) << 1;                           }
+static inline Odc_Obj_t *   Odc_Lit2Obj( Odc_Man_t * p, Odc_Lit_t Lit )    { assert( !(Lit & 1) && (int)(Lit>>1) < p->nObjs ); return p->pObjs + (Lit>>1); }
+
+// fanins and their complements
+static inline Odc_Lit_t     Odc_ObjChild0( Odc_Obj_t * pObj )              { return pObj->iFan0;                   }
+static inline Odc_Lit_t     Odc_ObjChild1( Odc_Obj_t * pObj )              { return pObj->iFan1;                   }
+static inline Odc_Lit_t     Odc_ObjFanin0( Odc_Obj_t * pObj )              { return Odc_Regular(pObj->iFan0);      }
+static inline Odc_Lit_t     Odc_ObjFanin1( Odc_Obj_t * pObj )              { return Odc_Regular(pObj->iFan1);      }
+static inline int           Odc_ObjFaninC0( Odc_Obj_t * pObj )             { return Odc_IsComplement(pObj->iFan0); }
+static inline int           Odc_ObjFaninC1( Odc_Obj_t * pObj )             { return Odc_IsComplement(pObj->iFan1); }
+
+// traversal IDs
+static inline void          Odc_ManIncrementTravId( Odc_Man_t * p )                         { p->nTravIds++;                                    }
+static inline void          Odc_ObjSetTravIdCurrent( Odc_Man_t * p, Odc_Obj_t * pObj )      { pObj->TravId = p->nTravIds;                       }
+static inline int           Odc_ObjIsTravIdCurrent( Odc_Man_t * p, Odc_Obj_t * pObj )       { return (int )((int)pObj->TravId == p->nTravIds);  }
+
+// truth tables
+static inline unsigned *    Odc_ObjTruth( Odc_Man_t * p, Odc_Lit_t Lit )   { assert( !(Lit & 1) ); return (unsigned *) Vec_PtrEntry(p->vTruths, Lit >> 1);  }
+
+// iterators 
+#define Odc_ForEachPi( p, Lit, i )                                                 \
+    for ( i = 0; (i < Odc_PiNum(p)) && (((Lit) = Odc_Var(p, i)), 1); i++ )
+#define Odc_ForEachAnd( p, pObj, i )                                               \
+    for ( i = 1 + Odc_CiNum(p); (i < Odc_ObjNum(p)) && ((pObj) = (p)->pObjs + i); i++ )
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the don't-care manager.]
+
+  Description [The parameters are the max number of cut variables, 
+  the number of fanout levels used for the ODC computation, and verbosiness.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Odc_Man_t * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose )
+{
+    Odc_Man_t * p;
+    unsigned * pData;
+    int i, k;
+    p = ABC_ALLOC( Odc_Man_t, 1 );
+    memset( p, 0, sizeof(Odc_Man_t) );
+    assert( nVarsMax > 4 && nVarsMax < 16 );
+    assert( nLevels > 0 && nLevels < 10 );
+
+    srand( 0xABC );
+
+    // dont'-care parameters
+    p->nVarsMax     = nVarsMax;
+    p->nLevels      = nLevels;
+    p->fVerbose     = fVerbose;
+    p->fVeryVerbose = fVeryVerbose;
+    p->nPercCutoff  = 10;
+
+    // windowing
+    p->vRoots    = Vec_PtrAlloc( 128 );
+    p->vBranches = Vec_PtrAlloc( 128 );
+
+    // internal AIG package
+    // allocate room for objects
+    p->nObjsAlloc = ABC_DC_MAX_NODES; 
+    p->pObjs = ABC_ALLOC( Odc_Obj_t, p->nObjsAlloc * sizeof(Odc_Obj_t) );
+    p->nPis  = nVarsMax + 32;
+    p->nObjs = 1 + p->nPis;
+    memset( p->pObjs, 0, p->nObjs * sizeof(Odc_Obj_t) );
+    // set the PI masks
+    for ( i = 0; i < 32; i++ )
+        p->pObjs[1 + p->nVarsMax + i].uMask = (1 << i);
+    // allocate hash table
+    p->nTableSize = p->nObjsAlloc/3 + 1;
+    p->pTable = ABC_ALLOC( Odc_Lit_t, p->nTableSize * sizeof(Odc_Lit_t) );
+    memset( p->pTable, 0, p->nTableSize * sizeof(Odc_Lit_t) );
+    p->vUsedSpots = Vec_IntAlloc( 1000 );
+
+    // truth tables
+    p->nWords = Abc_TruthWordNum( p->nVarsMax );
+    p->nBits = p->nWords * 8 * sizeof(unsigned);
+    p->vTruths = Vec_PtrAllocSimInfo( p->nObjsAlloc, p->nWords );
+    p->vTruthsElem = Vec_PtrAllocSimInfo( p->nVarsMax, p->nWords );
+
+    // set elementary truth tables
+    Abc_InfoFill( (unsigned *)Vec_PtrEntry(p->vTruths, 0), p->nWords );
+    for ( k = 0; k < p->nVarsMax; k++ )
+    {
+//        pData = Odc_ObjTruth( p, Odc_Var(p, k) );
+        pData = (unsigned *)Vec_PtrEntry( p->vTruthsElem, k );
+        Abc_InfoClear( pData, p->nWords );
+        for ( i = 0; i < p->nBits; i++ )
+            if ( i & (1 << k) )
+                pData[i>>5] |= (1 << (i&31));
+    }
+
+    // set random truth table for the additional inputs
+    for ( k = p->nVarsMax; k < p->nPis; k++ )
+    {
+        pData = Odc_ObjTruth( p, Odc_Var(p, k) );
+        Abc_InfoRandom( pData, p->nWords );
+    }
+
+    // set the miter to the unused value
+    p->iRoot = 0xffff;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Clears the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDontCareClear( Odc_Man_t * p )
+{
+    abctime clk = Abc_Clock();
+    // clean the structural hashing table
+    if ( Vec_IntSize(p->vUsedSpots) > p->nTableSize/3 ) // more than one third
+        memset( p->pTable, 0, sizeof(Odc_Lit_t) * p->nTableSize );
+    else
+    {
+        int iSpot, i;
+        Vec_IntForEachEntry( p->vUsedSpots, iSpot, i )
+            p->pTable[iSpot] = 0;
+    }
+    Vec_IntClear( p->vUsedSpots ); 
+    // reset the number of nodes
+    p->nObjs = 1 + p->nPis;
+    // reset the root node
+    p->iRoot = 0xffff;
+
+p->timeClean += Abc_Clock() - clk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the don't-care manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDontCareFree( Odc_Man_t * p )
+{
+    if ( p->fVerbose )
+    {
+        printf( "Wins = %5d. Empty = %5d. SimsEmpty = %5d. QuantOver = %5d. WinsFinish = %5d.\n", 
+            p->nWins, p->nWinsEmpty, p->nSimsEmpty, p->nQuantsOver, p->nWinsFinish );
+        printf( "Ave DCs per window = %6.2f %%. Ave DCs per finished window = %6.2f %%.\n", 
+            1.0*p->nTotalDcs/p->nWins, 1.0*p->nTotalDcs/p->nWinsFinish );
+        printf( "Runtime stats of the ODC manager:\n" );
+        ABC_PRT( "Cleaning    ", p->timeClean );
+        ABC_PRT( "Windowing   ", p->timeWin   );
+        ABC_PRT( "Miter       ", p->timeMiter );
+        ABC_PRT( "Simulation  ", p->timeSim   );
+        ABC_PRT( "Quantifying ", p->timeQuant );
+        ABC_PRT( "Truth table ", p->timeTruth );
+        ABC_PRT( "TOTAL       ", p->timeTotal );
+        ABC_PRT( "Aborted     ", p->timeAbort );
+    }
+    Vec_PtrFree( p->vRoots );
+    Vec_PtrFree( p->vBranches );
+    Vec_PtrFree( p->vTruths );
+    Vec_PtrFree( p->vTruthsElem );
+    Vec_IntFree( p->vUsedSpots );
+    ABC_FREE( p->pObjs );
+    ABC_FREE( p->pTable );
+    ABC_FREE( p );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the TFO of the collected nodes up to the given level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDontCareWinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    if ( Abc_ObjIsCo(pObj) || (int)pObj->Level > nLevelLimit || pObj == pNode )
+        return;
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return;
+    Abc_NodeSetTravIdCurrent( pObj );
+    ////////////////////////////////////////
+    // try to reduce the runtime
+    if ( Abc_ObjFanoutNum(pObj) > 100 )
+        return;
+    ////////////////////////////////////////
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        Abc_NtkDontCareWinSweepLeafTfo_rec( pFanout, nLevelLimit, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the TFO of the collected nodes up to the given level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDontCareWinSweepLeafTfo( Odc_Man_t * p )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkIncrementTravId( p->pNode->pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, i )
+        Abc_NtkDontCareWinSweepLeafTfo_rec( pObj, p->pNode->Level + p->nLevels, p->pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively collects the roots.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDontCareWinCollectRoots_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vRoots )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    assert( Abc_ObjIsNode(pObj) );
+    assert( Abc_NodeIsTravIdCurrent(pObj) );
+    // check if the node has all fanouts marked
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        if ( !Abc_NodeIsTravIdCurrent(pFanout) )
+            break;
+    // if some of the fanouts are unmarked, add the node to the root
+    if ( i < Abc_ObjFanoutNum(pObj) ) 
+    {
+        Vec_PtrPushUnique( vRoots, pObj );
+        return;
+    }
+    // otherwise, call recursively
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        Abc_NtkDontCareWinCollectRoots_rec( pFanout, vRoots );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the roots of the window.]
+
+  Description [Roots of the window are the nodes that have at least
+  one fanout that it not in the TFO of the leaves.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDontCareWinCollectRoots( Odc_Man_t * p )
+{
+    assert( !Abc_NodeIsTravIdCurrent(p->pNode) );
+    // mark the node with the old traversal ID
+    Abc_NodeSetTravIdCurrent( p->pNode ); 
+    // collect the roots
+    Vec_PtrClear( p->vRoots );
+    Abc_NtkDontCareWinCollectRoots_rec( p->pNode, p->vRoots );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Recursively adds missing nodes and leaves.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+int Abc_NtkDontCareWinAddMissing_rec( Odc_Man_t * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    // skip the already collected leaves and branches
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return 1;
+    // if this is not an internal node - make it a new branch
+    if ( !Abc_NodeIsTravIdPrevious(pObj) || Abc_ObjIsCi(pObj) ) //|| (int)pObj->Level <= p->nLevLeaves )
+    {
+        Abc_NodeSetTravIdCurrent( pObj );
+        Vec_PtrPush( p->vBranches, pObj );
+        return Vec_PtrSize(p->vBranches) <= 32;
+    }
+    // visit the fanins of the node
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        if ( !Abc_NtkDontCareWinAddMissing_rec( p, pFanin ) )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds to the window nodes and leaves in the TFI of the roots.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDontCareWinAddMissing( Odc_Man_t * p )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    // set the leaves
+    Abc_NtkIncrementTravId( p->pNode->pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, i )
+        Abc_NodeSetTravIdCurrent( pObj );        
+    // explore from the roots
+    Vec_PtrClear( p->vBranches );
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i )
+        if ( !Abc_NtkDontCareWinAddMissing_rec( p, pObj ) )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes window for the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDontCareWindow( Odc_Man_t * p )
+{
+    // mark the TFO of the collected nodes up to the given level (p->pNode->Level + p->nWinTfoMax)
+    Abc_NtkDontCareWinSweepLeafTfo( p );
+    // find the roots of the window
+    Abc_NtkDontCareWinCollectRoots( p );
+    if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode )
+    {
+//        printf( "Empty window\n" );
+        return 0;
+    }
+    // add the nodes in the TFI of the roots that are not yet in the window
+    if ( !Abc_NtkDontCareWinAddMissing( p ) )
+    {
+//        printf( "Too many branches (%d)\n", Vec_PtrSize(p->vBranches) );
+        return 0;
+    }
+    return 1;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performing hashing of two AIG Literals.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Odc_HashKey( Odc_Lit_t iFan0, Odc_Lit_t iFan1, int TableSize ) 
+{
+    unsigned Key = 0;
+    Key ^= Odc_Regular(iFan0) * 7937;
+    Key ^= Odc_Regular(iFan1) * 2971;
+    Key ^= Odc_IsComplement(iFan0) * 911;
+    Key ^= Odc_IsComplement(iFan1) * 353;
+    return Key % TableSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the given name node already exists in the table.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Odc_Lit_t * Odc_HashLookup( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 )
+{
+    Odc_Obj_t * pObj;
+    Odc_Lit_t * pEntry;
+    unsigned uHashKey;
+    assert( iFan0 < iFan1 );
+    // get the hash key for this node
+    uHashKey = Odc_HashKey( iFan0, iFan1, p->nTableSize );
+    // remember the spot in the hash table that will be used
+    if ( p->pTable[uHashKey] == 0 )
+        Vec_IntPush( p->vUsedSpots, uHashKey );
+    // find the entry
+    for ( pEntry = p->pTable + uHashKey; *pEntry; pEntry = &pObj->iNext )
+    {
+        pObj = Odc_Lit2Obj( p, *pEntry );
+        if ( pObj->iFan0 == iFan0 && pObj->iFan1 == iFan1 )
+            return pEntry;
+    }
+    return pEntry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds node by structural hashing or creates a new node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Odc_Lit_t Odc_And( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 )
+{
+    Odc_Obj_t * pObj;
+    Odc_Lit_t * pEntry;
+    unsigned uMask0, uMask1;
+    int Temp;
+    // consider trivial cases
+    if ( iFan0 == iFan1 )
+        return iFan0;
+    if ( iFan0 == Odc_Not(iFan1) )
+        return Odc_Const0();
+    if ( Odc_Regular(iFan0) == Odc_Const1() )
+        return iFan0 == Odc_Const1() ? iFan1 : Odc_Const0();
+    if ( Odc_Regular(iFan1) == Odc_Const1() )
+        return iFan1 == Odc_Const1() ? iFan0 : Odc_Const0();
+    // canonicize the fanin order
+    if ( iFan0 > iFan1 )
+        Temp = iFan0, iFan0 = iFan1, iFan1 = Temp;
+    // check if a node with these fanins exists
+    pEntry = Odc_HashLookup( p, iFan0, iFan1 );
+    if ( *pEntry )
+        return *pEntry;
+    // create a new node
+    pObj = Odc_ObjNew( p );
+    pObj->iFan0 = iFan0;
+    pObj->iFan1 = iFan1;
+    pObj->iNext = 0;
+    pObj->TravId = 0;
+    // set the mask
+    uMask0 = Odc_Lit2Obj(p, Odc_Regular(iFan0))->uMask;
+    uMask1 = Odc_Lit2Obj(p, Odc_Regular(iFan1))->uMask;
+    pObj->uMask = uMask0 | uMask1;
+    // add to the table
+    *pEntry = Odc_Obj2Lit( p, pObj );
+    return *pEntry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Boolean OR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Odc_Lit_t Odc_Or( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 )
+{
+    return Odc_Not( Odc_And(p, Odc_Not(iFan0), Odc_Not(iFan1)) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Boolean XOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Odc_Lit_t Odc_Xor( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 )
+{
+    return Odc_Or( p, Odc_And(p, iFan0, Odc_Not(iFan1)), Odc_And(p, Odc_Not(iFan0), iFan1) );
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the window into the AIG package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Abc_NtkDontCareTransfer_rec( Odc_Man_t * p, Abc_Obj_t * pNode, Abc_Obj_t * pPivot )
+{
+    unsigned uData0, uData1;
+    Odc_Lit_t uLit0, uLit1, uRes0, uRes1;
+    assert( !Abc_ObjIsComplement(pNode) );
+    // skip visited objects
+    if ( Abc_NodeIsTravIdCurrent(pNode) )
+        return pNode->pCopy;
+    Abc_NodeSetTravIdCurrent(pNode);
+    assert( Abc_ObjIsNode(pNode) );
+    // consider the case when the node is the pivot
+    if ( pNode == pPivot )
+        return pNode->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)((Odc_Const1() << 16) | Odc_Const0());
+    // compute the cofactors
+    uData0 = (unsigned)(ABC_PTRUINT_T)Abc_NtkDontCareTransfer_rec( p, Abc_ObjFanin0(pNode), pPivot );
+    uData1 = (unsigned)(ABC_PTRUINT_T)Abc_NtkDontCareTransfer_rec( p, Abc_ObjFanin1(pNode), pPivot );
+    // find the 0-cofactor
+    uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 & 0xffff), Abc_ObjFaninC0(pNode) );
+    uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 & 0xffff), Abc_ObjFaninC1(pNode) );
+    uRes0 = Odc_And( p, uLit0, uLit1 );
+    // find the 1-cofactor
+    uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 >> 16), Abc_ObjFaninC0(pNode) );
+    uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 >> 16), Abc_ObjFaninC1(pNode) );
+    uRes1 = Odc_And( p, uLit0, uLit1 );
+    // find the result
+    return pNode->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)((uRes1 << 16) | uRes0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the window into the AIG package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDontCareTransfer( Odc_Man_t * p )
+{
+    Abc_Obj_t * pObj;
+    Odc_Lit_t uRes0, uRes1;
+    Odc_Lit_t uLit;
+    unsigned uData;
+    int i;
+    Abc_NtkIncrementTravId( p->pNode->pNtk );
+    // set elementary variables at the leaves 
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, i )
+    {
+        uLit = Odc_Var( p, i );
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)((uLit << 16) | uLit);
+        Abc_NodeSetTravIdCurrent(pObj);
+    }
+    // set elementary variables at the branched 
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vBranches, pObj, i )
+    {
+        uLit = Odc_Var( p, i+p->nVarsMax );
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)((uLit << 16) | uLit);
+        Abc_NodeSetTravIdCurrent(pObj);
+    }
+    // compute the AIG for the window
+    p->iRoot = Odc_Const0();
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i )
+    {
+        uData = (unsigned)(ABC_PTRUINT_T)Abc_NtkDontCareTransfer_rec( p, pObj, p->pNode );
+        // get the cofactors
+        uRes0 = uData & 0xffff;
+        uRes1 = uData >> 16;
+        // compute the miter
+//        assert( uRes0 != uRes1 ); // may be false if the node is redundant w.r.t. this root
+        uLit = Odc_Xor( p, uRes0, uRes1 );
+        p->iRoot = Odc_Or( p, p->iRoot, uLit );
+    }
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively computes the pair of cofactors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Abc_NtkDontCareCofactors_rec( Odc_Man_t * p, Odc_Lit_t Lit, unsigned uMask )
+{
+    Odc_Obj_t * pObj;
+    unsigned uData0, uData1;
+    Odc_Lit_t uLit0, uLit1, uRes0, uRes1;
+    assert( !Odc_IsComplement(Lit) );
+    // skip visited objects
+    pObj = Odc_Lit2Obj( p, Lit );
+    if ( Odc_ObjIsTravIdCurrent(p, pObj) )
+        return pObj->uData;
+    Odc_ObjSetTravIdCurrent(p, pObj);
+    // skip objects out of the cone
+    if ( (pObj->uMask & uMask) == 0 )
+        return pObj->uData = ((Lit << 16) | Lit);
+    // consider the case when the node is the var
+    if ( pObj->uMask == uMask && Odc_IsTerm(p, Lit) )
+        return pObj->uData = ((Odc_Const1() << 16) | Odc_Const0());
+    // compute the cofactors
+    uData0 = Abc_NtkDontCareCofactors_rec( p, Odc_ObjFanin0(pObj), uMask );
+    uData1 = Abc_NtkDontCareCofactors_rec( p, Odc_ObjFanin1(pObj), uMask );
+    // find the 0-cofactor
+    uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 & 0xffff), Odc_ObjFaninC0(pObj) );
+    uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 & 0xffff), Odc_ObjFaninC1(pObj) );
+    uRes0 = Odc_And( p, uLit0, uLit1 );
+    // find the 1-cofactor
+    uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 >> 16), Odc_ObjFaninC0(pObj) );
+    uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 >> 16), Odc_ObjFaninC1(pObj) );
+    uRes1 = Odc_And( p, uLit0, uLit1 );
+    // find the result
+    return pObj->uData = ((uRes1 << 16) | uRes0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Quantifies the branch variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDontCareQuantify( Odc_Man_t * p )
+{   
+    Odc_Lit_t uRes0, uRes1;
+    unsigned uData;
+    int i;
+    assert( p->iRoot < 0xffff );
+    assert( Vec_PtrSize(p->vBranches) <= 32 ); // the mask size
+    for ( i = 0; i < Vec_PtrSize(p->vBranches); i++ )
+    {
+        // compute the cofactors w.r.t. this variable
+        Odc_ManIncrementTravId( p );
+        uData = Abc_NtkDontCareCofactors_rec( p, Odc_Regular(p->iRoot), (1 << i) );
+        uRes0 = Odc_NotCond( (Odc_Lit_t)(uData & 0xffff), Odc_IsComplement(p->iRoot) );
+        uRes1 = Odc_NotCond( (Odc_Lit_t)(uData >> 16),    Odc_IsComplement(p->iRoot) );
+        // quantify this variable existentially
+        p->iRoot = Odc_Or( p, uRes0, uRes1 );
+        // check the limit
+        if ( Odc_ObjNum(p) > ABC_DC_MAX_NODES/2 )
+            return 0;
+    }
+    assert( p->nObjs <= p->nObjsAlloc );
+    return 1;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Set elementary truth tables for PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDontCareSimulateSetElem2( Odc_Man_t * p )
+{
+    unsigned * pData;
+    int i, k;
+    for ( k = 0; k < p->nVarsMax; k++ )
+    {
+        pData = Odc_ObjTruth( p, Odc_Var(p, k) );
+        Abc_InfoClear( pData, p->nWords );
+        for ( i = 0; i < p->nBits; i++ )
+            if ( i & (1 << k) )
+                pData[i>>5] |= (1 << (i&31));
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Set elementary truth tables for PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDontCareSimulateSetElem( Odc_Man_t * p )
+{
+    unsigned * pData, * pData2;
+    int k;
+    for ( k = 0; k < p->nVarsMax; k++ )
+    {
+        pData = Odc_ObjTruth( p, Odc_Var(p, k) );
+        pData2 = (unsigned *)Vec_PtrEntry( p->vTruthsElem, k );
+        Abc_InfoCopy( pData, pData2, p->nWords );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Set random simulation words for PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDontCareSimulateSetRand( Odc_Man_t * p )
+{
+    unsigned * pData;
+    int w, k, Number;
+    for ( w = 0; w < p->nWords; w++ )
+    {
+        Number = rand();
+        for ( k = 0; k < p->nVarsMax; k++ )
+        {
+            pData = Odc_ObjTruth( p, Odc_Var(p, k) );
+            pData[w] = (Number & (1<<k)) ? ~0 : 0;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Set random simulation words for PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDontCareCountMintsWord( Odc_Man_t * p, unsigned * puTruth )
+{
+    int w, Counter = 0;
+    for ( w = 0; w < p->nWords; w++ )
+        if ( puTruth[w] )
+            Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDontCareTruthOne( Odc_Man_t * p, Odc_Lit_t Lit )
+{
+    Odc_Obj_t * pObj;
+    unsigned * pInfo, * pInfo1, * pInfo2;
+    int k, fComp1, fComp2;
+    assert( !Odc_IsComplement( Lit ) );
+    assert( !Odc_IsTerm( p, Lit ) );
+    // get the truth tables
+    pObj   = Odc_Lit2Obj( p, Lit );
+    pInfo  = Odc_ObjTruth( p, Lit );
+    pInfo1 = Odc_ObjTruth( p, Odc_ObjFanin0(pObj) );
+    pInfo2 = Odc_ObjTruth( p, Odc_ObjFanin1(pObj) );
+    fComp1 = Odc_ObjFaninC0( pObj );
+    fComp2 = Odc_ObjFaninC1( pObj );
+    // simulate
+    if ( fComp1 && fComp2 )
+        for ( k = 0; k < p->nWords; k++ )
+            pInfo[k] = ~pInfo1[k] & ~pInfo2[k];
+    else if ( fComp1 && !fComp2 )
+        for ( k = 0; k < p->nWords; k++ )
+            pInfo[k] = ~pInfo1[k] &  pInfo2[k];
+    else if ( !fComp1 && fComp2 )
+        for ( k = 0; k < p->nWords; k++ )
+            pInfo[k] =  pInfo1[k] & ~pInfo2[k];
+    else // if ( fComp1 && fComp2 )
+        for ( k = 0; k < p->nWords; k++ )
+            pInfo[k] =  pInfo1[k] &  pInfo2[k];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDontCareSimulate_rec( Odc_Man_t * p, Odc_Lit_t Lit )
+{
+    Odc_Obj_t * pObj;
+    assert( !Odc_IsComplement(Lit) );
+    // skip terminals
+    if ( Odc_IsTerm(p, Lit) )
+        return;
+    // skip visited objects
+    pObj = Odc_Lit2Obj( p, Lit );
+    if ( Odc_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Odc_ObjSetTravIdCurrent(p, pObj);
+    // call recursively
+    Abc_NtkDontCareSimulate_rec( p, Odc_ObjFanin0(pObj) );
+    Abc_NtkDontCareSimulate_rec( p, Odc_ObjFanin1(pObj) );
+    // construct the truth table
+    Abc_NtkDontCareTruthOne( p, Lit );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the truth table of the care set.]
+
+  Description [Returns the number of ones in the simulation info.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDontCareSimulate( Odc_Man_t * p, unsigned * puTruth )
+{
+    Odc_ManIncrementTravId( p );
+    Abc_NtkDontCareSimulate_rec( p, Odc_Regular(p->iRoot) );
+    Abc_InfoCopy( puTruth, Odc_ObjTruth(p, Odc_Regular(p->iRoot)), p->nWords );
+    if ( Odc_IsComplement(p->iRoot) )
+        Abc_InfoNot( puTruth, p->nWords );
+    return Extra_TruthCountOnes( puTruth, p->nVarsMax );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the truth table of the care set.]
+
+  Description [Returns the number of ones in the simulation info.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDontCareSimulateBefore( Odc_Man_t * p, unsigned * puTruth )
+{
+    int nIters = 2;
+    int nRounds, Counter, r;
+    // decide how many rounds to simulate
+    nRounds = p->nBits / p->nWords;
+    Counter = 0;
+    for ( r = 0; r < nIters; r++ )
+    {
+        Abc_NtkDontCareSimulateSetRand( p );
+        Abc_NtkDontCareSimulate( p, puTruth );
+        Counter += Abc_NtkDontCareCountMintsWord( p, puTruth );
+    }
+    // normalize
+    Counter = Counter * nRounds / nIters;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes ODCs for the node in terms of the cut variables.]
+
+  Description [Returns the number of don't care minterms in the truth table.
+  In particular, this procedure returns 0 if there is no don't-cares.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth )
+{
+    int nMints, RetValue;
+    abctime clk, clkTotal = Abc_Clock();
+
+    p->nWins++;
+    
+    // set the parameters
+    assert( !Abc_ObjIsComplement(pNode) );
+    assert( Abc_ObjIsNode(pNode) );
+    assert( Vec_PtrSize(vLeaves) <= p->nVarsMax );
+    p->vLeaves = vLeaves;
+    p->pNode = pNode;
+
+    // compute the window
+clk = Abc_Clock();
+    RetValue = Abc_NtkDontCareWindow( p );
+p->timeWin += Abc_Clock() - clk;
+    if ( !RetValue )
+    {
+p->timeAbort += Abc_Clock() - clkTotal;
+        Abc_InfoFill( puTruth, p->nWords );
+        p->nWinsEmpty++;        
+        return 0;
+    }
+
+    if ( p->fVeryVerbose )
+    {
+        printf( " %5d : ", pNode->Id );
+        printf( "Leaf = %2d ", Vec_PtrSize(p->vLeaves) );
+        printf( "Root = %2d ", Vec_PtrSize(p->vRoots) );
+        printf( "Bran = %2d ", Vec_PtrSize(p->vBranches) );
+        printf( " |  " );
+    }
+
+    // transfer the window into the AIG package
+clk = Abc_Clock();
+    Abc_NtkDontCareTransfer( p );
+p->timeMiter += Abc_Clock() - clk;
+
+    // simulate to estimate the amount of don't-cares
+clk = Abc_Clock();
+    nMints = Abc_NtkDontCareSimulateBefore( p, puTruth );
+p->timeSim += Abc_Clock() - clk;
+    if ( p->fVeryVerbose )
+    {
+        printf( "AIG = %5d ", Odc_NodeNum(p) );
+        printf( "%6.2f %%  ", 100.0 * (p->nBits - nMints) / p->nBits );
+    }
+
+    // if there is less then the given percentage of don't-cares, skip
+    if ( 100.0 * (p->nBits - nMints) / p->nBits < 1.0 * p->nPercCutoff )
+    {
+p->timeAbort += Abc_Clock() - clkTotal;
+        if ( p->fVeryVerbose )
+            printf( "Simulation cutoff.\n" );
+        Abc_InfoFill( puTruth, p->nWords );
+        p->nSimsEmpty++;
+        return 0;
+    }
+
+    // quantify external variables
+clk = Abc_Clock();
+    RetValue = Abc_NtkDontCareQuantify( p );
+p->timeQuant += Abc_Clock() - clk;
+    if ( !RetValue )
+    {
+p->timeAbort += Abc_Clock() - clkTotal;
+        if ( p->fVeryVerbose )
+            printf( "=== Overflow! ===\n" );
+        Abc_InfoFill( puTruth, p->nWords );
+        p->nQuantsOver++;
+        return 0;
+    }
+
+    // get the truth table
+clk = Abc_Clock();
+    Abc_NtkDontCareSimulateSetElem( p );
+    nMints = Abc_NtkDontCareSimulate( p, puTruth );
+p->timeTruth += Abc_Clock() - clk;
+    if ( p->fVeryVerbose )
+    {
+        printf( "AIG = %5d ", Odc_NodeNum(p) );
+        printf( "%6.2f %%  ", 100.0 * (p->nBits - nMints) / p->nBits );
+        printf( "\n" );
+    }
+p->timeTotal += Abc_Clock() - clkTotal;
+    p->nWinsFinish++;
+    p->nTotalDcs += (int)(100.0 * (p->nBits - nMints) / p->nBits);
+    return nMints;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcOrder.c b/abc-build/src/base/abci/abcOrder.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcOrder.c
@@ -0,0 +1,136 @@
+/**CFile****************************************************************
+
+  FileName    [abcOrder.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Exploring static BDD variable orders.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcOrder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkChangeCiOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vSupp, int fReverse );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    [Changes the order of primary inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose )
+{
+    Vec_Ptr_t * vSupp;
+    vSupp = Abc_NtkSupport( pNtk );
+    Abc_NtkChangeCiOrder( pNtk, vSupp, fReverse );
+    Vec_PtrFree( vSupp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements the given variable order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose )
+{
+    char Buffer[1000];
+    FILE * pFile;
+    Vec_Ptr_t * vSupp;
+    Abc_Obj_t * pObj;
+    pFile = fopen( pFileName, "r" );
+    vSupp = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) );
+    while ( fscanf( pFile, "%s", Buffer ) == 1 )
+    {
+        pObj = Abc_NtkFindCi( pNtk, Buffer );
+        if ( pObj == NULL || !Abc_ObjIsCi(pObj) )
+        {
+            printf( "Name \"%s\" is not a PI name. Cannot use this order.\n", Buffer );
+            Vec_PtrFree( vSupp );
+            fclose( pFile );
+            return;
+        }
+        Vec_PtrPush( vSupp, pObj );
+    }
+    fclose( pFile );
+    if ( Vec_PtrSize(vSupp) != Abc_NtkCiNum(pNtk) )
+    {
+        printf( "The number of names in the order (%d) is not the same as the number of PIs (%d).\n", Vec_PtrSize(vSupp), Abc_NtkCiNum(pNtk) );
+        Vec_PtrFree( vSupp );
+        return;
+    }
+    Abc_NtkChangeCiOrder( pNtk, vSupp, fReverse );
+    Vec_PtrFree( vSupp );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Changes the order of primary inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkChangeCiOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vSupp, int fReverse )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    assert( Vec_PtrSize(vSupp) == Abc_NtkCiNum(pNtk) );
+    // order CIs using the array
+    if ( fReverse )
+        Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i )
+            Vec_PtrWriteEntry( pNtk->vCis, Vec_PtrSize(vSupp)-1-i, pObj );
+    else
+        Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i )
+            Vec_PtrWriteEntry( pNtk->vCis, i, pObj );
+    // order PIs accordingly
+    Vec_PtrClear( pNtk->vPis );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        if ( Abc_ObjIsPi(pObj) )
+            Vec_PtrPush( pNtk->vPis, pObj );
+//    Abc_NtkForEachCi( pNtk, pObj, i )
+//        printf( "%s ", Abc_ObjName(pObj) );
+//    printf( "\n" );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcPart.c b/abc-build/src/base/abci/abcPart.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcPart.c
@@ -0,0 +1,1206 @@
+/**CFile****************************************************************
+
+  FileName    [abcPart.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Output partitioning package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcPart.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/main.h"
+#include "base/cmd/cmd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Supp_Man_t_     Supp_Man_t;
+struct Supp_Man_t_
+{
+    int              nChunkSize;    // the size of one chunk of memory (~1 MB)
+    int              nStepSize;     // the step size in saving memory (~64 bytes)
+    char *           pFreeBuf;      // the pointer to free memory
+    int              nFreeSize;     // the size of remaining free memory
+    Vec_Ptr_t *      vMemory;       // the memory allocated
+    Vec_Ptr_t *      vFree;         // the vector of free pieces of memory
+};
+
+typedef struct Supp_One_t_     Supp_One_t;
+struct Supp_One_t_
+{
+    int              nRefs;         // the number of references
+    int              nOuts;         // the number of outputs
+    int              nOutsAlloc;    // the array size
+    int              pOuts[0];      // the array of outputs
+};
+
+static inline int    Supp_SizeType( int nSize, int nStepSize )     { return nSize / nStepSize + ((nSize % nStepSize) > 0); }
+static inline char * Supp_OneNext( char * pPart )                  { return *((char **)pPart);                             }
+static inline void   Supp_OneSetNext( char * pPart, char * pNext ) { *((char **)pPart) = pNext;                            }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Start the memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Supp_Man_t * Supp_ManStart( int nChunkSize, int nStepSize )
+{
+    Supp_Man_t * p;
+    p = ABC_ALLOC( Supp_Man_t, 1 );
+    memset( p, 0, sizeof(Supp_Man_t) );
+    p->nChunkSize = nChunkSize;
+    p->nStepSize  = nStepSize;
+    p->vMemory    = Vec_PtrAlloc( 1000 );
+    p->vFree      = Vec_PtrAlloc( 1000 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Supp_ManStop( Supp_Man_t * p )
+{
+    void * pMemory;
+    int i;
+    Vec_PtrForEachEntry( void *, p->vMemory, pMemory, i )
+        ABC_FREE( pMemory );
+    Vec_PtrFree( p->vMemory );
+    Vec_PtrFree( p->vFree );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fetches the memory entry of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Supp_ManFetch( Supp_Man_t * p, int nSize )
+{
+    int Type, nSizeReal;
+    char * pMemory;
+    assert( nSize > 0 );
+    Type = Supp_SizeType( nSize, p->nStepSize );
+    Vec_PtrFillExtra( p->vFree, Type + 1, NULL );
+    if ( (pMemory = (char *)Vec_PtrEntry( p->vFree, Type )) )
+    {
+        Vec_PtrWriteEntry( p->vFree, Type, Supp_OneNext(pMemory) );
+        return pMemory;
+    }
+    nSizeReal = p->nStepSize * Type;
+    if ( p->nFreeSize < nSizeReal )
+    {
+        p->pFreeBuf = ABC_ALLOC( char, p->nChunkSize );
+        p->nFreeSize = p->nChunkSize;
+        Vec_PtrPush( p->vMemory, p->pFreeBuf );
+    }
+    assert( p->nFreeSize >= nSizeReal );
+    pMemory = p->pFreeBuf;
+    p->pFreeBuf  += nSizeReal;
+    p->nFreeSize -= nSizeReal;
+    return pMemory;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the memory entry of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Supp_ManRecycle( Supp_Man_t * p, char * pMemory, int nSize )
+{
+    int Type;
+    Type = Supp_SizeType( nSize, p->nStepSize );
+    Vec_PtrFillExtra( p->vFree, Type + 1, NULL );
+    Supp_OneSetNext( pMemory, (char *)Vec_PtrEntry(p->vFree, Type) );
+    Vec_PtrWriteEntry( p->vFree, Type, pMemory );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fetches the memory entry of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Supp_One_t * Supp_ManFetchEntry( Supp_Man_t * p, int nWords, int nRefs )
+{
+    Supp_One_t * pPart;
+    pPart = (Supp_One_t *)Supp_ManFetch( p, sizeof(Supp_One_t) + sizeof(int) * nWords );
+    pPart->nRefs = nRefs;
+    pPart->nOuts = 0;
+    pPart->nOutsAlloc = nWords;
+    return pPart;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the memory entry of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Supp_ManRecycleEntry( Supp_Man_t * p, Supp_One_t * pEntry )
+{
+    assert( pEntry->nOuts <= pEntry->nOutsAlloc );
+    assert( pEntry->nOuts >= pEntry->nOutsAlloc/2 );
+    Supp_ManRecycle( p, (char *)pEntry, sizeof(Supp_One_t) + sizeof(int) * pEntry->nOutsAlloc );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Supp_One_t * Supp_ManMergeEntry( Supp_Man_t * pMan, Supp_One_t * p1, Supp_One_t * p2, int nRefs )
+{
+    Supp_One_t * p = Supp_ManFetchEntry( pMan, p1->nOuts + p2->nOuts, nRefs );
+    int * pBeg1 = p1->pOuts;
+    int * pBeg2 = p2->pOuts;
+    int * pBeg  = p->pOuts;
+    int * pEnd1 = p1->pOuts + p1->nOuts;
+    int * pEnd2 = p2->pOuts + p2->nOuts;
+    while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+    {
+        if ( *pBeg1 == *pBeg2 )
+            *pBeg++ = *pBeg1++, pBeg2++;
+        else if ( *pBeg1 < *pBeg2 )
+            *pBeg++ = *pBeg1++;
+        else 
+            *pBeg++ = *pBeg2++;
+    }
+    while ( pBeg1 < pEnd1 )
+        *pBeg++ = *pBeg1++;
+    while ( pBeg2 < pEnd2 )
+        *pBeg++ = *pBeg2++;
+    p->nOuts = pBeg - p->pOuts;
+    assert( p->nOuts <= p->nOutsAlloc );
+    assert( p->nOuts >= p1->nOuts );
+    assert( p->nOuts >= p2->nOuts );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tranfers the entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Supp_ManTransferEntry( Supp_One_t * p )
+{
+    Vec_Int_t * vSupp;
+    int i;
+    vSupp = Vec_IntAlloc( p->nOuts );
+    for ( i = 0; i < p->nOuts; i++ )
+        Vec_IntPush( vSupp, p->pOuts[i] );
+    return vSupp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes supports of the POs in the multi-output AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsNatural( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj, * pNext;
+    int i, k;
+    assert( Abc_NtkIsStrash(pNtk) );
+    vNodes = Vec_PtrAlloc( Abc_NtkObjNum(pNtk) );
+    Abc_NtkIncrementTravId( pNtk );
+    // add the constant-1 nodes
+    pObj = Abc_AigConst1(pNtk);
+    Abc_NodeSetTravIdCurrent( pObj );
+    Vec_PtrPush( vNodes, pObj );
+    // add the CIs/nodes/COs in the topological order
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        // check the fanins and add CIs
+        Abc_ObjForEachFanin( pObj, pNext, k )
+            if ( Abc_ObjIsCi(pNext) && !Abc_NodeIsTravIdCurrent(pNext) )
+            {
+                Abc_NodeSetTravIdCurrent( pNext );
+                Vec_PtrPush( vNodes, pNext );
+            }
+        // add the node
+        Vec_PtrPush( vNodes, pObj );
+        // check the fanouts and add COs
+        Abc_ObjForEachFanout( pObj, pNext, k )
+            if ( Abc_ObjIsCo(pNext) && !Abc_NodeIsTravIdCurrent(pNext) )
+            {
+                Abc_NodeSetTravIdCurrent( pNext );
+                Vec_PtrPush( vNodes, pNext );
+            }
+    }
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes supports of the POs.]
+
+  Description [Returns the ptr-vector of int-vectors.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkComputeSupportsSmart( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vSupports;
+    Vec_Ptr_t * vNodes;
+    Vec_Int_t * vSupp;
+    Supp_Man_t * p;
+    Supp_One_t * pPart0, * pPart1;
+    Abc_Obj_t * pObj;
+    int i;
+    // set the number of PIs/POs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->pNext = (Abc_Obj_t *)(ABC_PTRINT_T)i;
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        pObj->pNext = (Abc_Obj_t *)(ABC_PTRINT_T)i;
+    // start the support computation manager
+    p = Supp_ManStart( 1 << 20, 1 << 6 );
+    // consider objects in the topological order
+    vSupports = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+    Abc_NtkCleanCopy(pNtk);
+    // order the nodes so that the PIs and POs follow naturally
+    vNodes = Abc_NtkDfsNatural( pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        if ( Abc_ObjIsNode(pObj) )
+        {
+            pPart0 = (Supp_One_t *)Abc_ObjFanin0(pObj)->pCopy;
+            pPart1 = (Supp_One_t *)Abc_ObjFanin1(pObj)->pCopy;
+            pObj->pCopy = (Abc_Obj_t *)Supp_ManMergeEntry( p, pPart0, pPart1, Abc_ObjFanoutNum(pObj) );
+            assert( pPart0->nRefs > 0 );
+            if ( --pPart0->nRefs == 0 )
+                Supp_ManRecycleEntry( p, pPart0 );
+            assert( pPart1->nRefs > 0 );
+            if ( --pPart1->nRefs == 0 )
+                Supp_ManRecycleEntry( p, pPart1 );
+            continue;
+        }
+        if ( Abc_ObjIsCo(pObj) )
+        {
+            pPart0 = (Supp_One_t *)Abc_ObjFanin0(pObj)->pCopy;
+            // only save the CO if it is non-trivial
+            if ( Abc_ObjIsNode(Abc_ObjFanin0(pObj)) )
+            {
+                vSupp = Supp_ManTransferEntry(pPart0);
+                Vec_IntPush( vSupp, (int)(ABC_PTRINT_T)pObj->pNext );
+                Vec_PtrPush( vSupports, vSupp );
+            }
+            assert( pPart0->nRefs > 0 );
+            if ( --pPart0->nRefs == 0 )
+                Supp_ManRecycleEntry( p, pPart0 );
+            continue;
+        }
+        if ( Abc_ObjIsCi(pObj) )
+        {
+            if ( Abc_ObjFanoutNum(pObj) )
+            {
+                pPart0 = (Supp_One_t *)Supp_ManFetchEntry( p, 1, Abc_ObjFanoutNum(pObj) );
+                pPart0->pOuts[ pPart0->nOuts++ ] = (int)(ABC_PTRINT_T)pObj->pNext;
+                pObj->pCopy = (Abc_Obj_t *)pPart0;
+            }
+            continue;
+        }
+        if ( pObj == Abc_AigConst1(pNtk) )
+        {
+            if ( Abc_ObjFanoutNum(pObj) )
+                pObj->pCopy = (Abc_Obj_t *)Supp_ManFetchEntry( p, 0, Abc_ObjFanoutNum(pObj) );
+            continue;
+        }
+        assert( 0 );
+    }
+    Vec_PtrFree( vNodes );
+//printf( "Memory usage = %d MB.\n", Vec_PtrSize(p->vMemory) * p->nChunkSize / (1<<20) );
+    Supp_ManStop( p );
+    // sort supports by size
+    Vec_VecSort( (Vec_Vec_t *)vSupports, 1 );
+    // clear the number of PIs/POs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->pNext = NULL;
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        pObj->pNext = NULL;
+/*
+    Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vSupp, i )
+        printf( "%d ", Vec_IntSize(vSupp) );
+    printf( "\n" );
+*/
+    return vSupports;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes supports of the POs using naive method.]
+
+  Description [Returns the ptr-vector of int-vectors.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkComputeSupportsNaive( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vSupp, * vSupports;
+    Vec_Int_t * vSuppI;
+    Abc_Obj_t * pObj, * pTemp;
+    int i, k;
+    // set the PI numbers
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->pNext = (Abc_Obj_t *)(ABC_PTRINT_T)i;
+    // save the CI numbers
+    vSupports = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        if ( !Abc_ObjIsNode(Abc_ObjFanin0(pObj)) )
+            continue;
+        vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
+        vSuppI = (Vec_Int_t *)vSupp;
+        Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pTemp, k )
+            Vec_IntWriteEntry( vSuppI, k, (int)(ABC_PTRINT_T)pTemp->pNext );
+        Vec_IntSort( vSuppI, 0 );
+        // append the number of this output
+        Vec_IntPush( vSuppI, i );
+        // save the support in the vector
+        Vec_PtrPush( vSupports, vSuppI );
+    }
+    // clean the CI numbers
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->pNext = NULL;
+    // sort supports by size
+    Vec_VecSort( (Vec_Vec_t *)vSupports, 1 );
+/*
+    Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vSuppI, i )
+        printf( "%d ", Vec_IntSize(vSuppI) );
+    printf( "\n" );
+*/
+    return vSupports;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Start bitwise support representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Abc_NtkSuppCharStart( Vec_Int_t * vOne, int nPis )
+{
+    unsigned * pBuffer;
+    int i, Entry;
+    int nWords = Abc_BitWordNum(nPis);
+    pBuffer = ABC_ALLOC( unsigned, nWords );
+    memset( pBuffer, 0, sizeof(unsigned) * nWords );
+    Vec_IntForEachEntry( vOne, Entry, i )
+    {
+        assert( Entry < nPis );
+        Abc_InfoSetBit( pBuffer, Entry );
+    }
+    return pBuffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add to bitwise support representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSuppCharAdd( unsigned * pBuffer, Vec_Int_t * vOne, int nPis )
+{
+    int i, Entry;
+    Vec_IntForEachEntry( vOne, Entry, i )
+    {
+        assert( Entry < nPis );
+        Abc_InfoSetBit( pBuffer, Entry );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the common variables using bitwise support representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkSuppCharCommon( unsigned * pBuffer, Vec_Int_t * vOne )
+{
+    int i, Entry, nCommon = 0;
+    Vec_IntForEachEntry( vOne, Entry, i )
+        nCommon += Abc_InfoHasBit(pBuffer, Entry);
+    return nCommon;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the best partition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsChar, int nSuppSizeLimit, Vec_Int_t * vOne )
+{
+/*
+    Vec_Int_t * vPartSupp, * vPart;
+    double Attract, Repulse, Cost, CostBest;
+    int i, nCommon, iBest;
+    iBest = -1;
+    CostBest = 0.0;
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vPartSupp, i )
+    {
+        vPart = Vec_PtrEntry( vPartsAll, i );
+        if ( nPartSizeLimit > 0 && Vec_IntSize(vPart) >= nPartSizeLimit )
+            continue;
+        nCommon = Vec_IntTwoCountCommon( vPartSupp, vOne );
+        if ( nCommon == 0 )
+            continue;
+        if ( nCommon == Vec_IntSize(vOne) )
+            return i;
+        Attract = 1.0 * nCommon / Vec_IntSize(vOne);
+        if ( Vec_IntSize(vPartSupp) < 100 )
+            Repulse = 1.0;
+        else
+            Repulse = log10( Vec_IntSize(vPartSupp) / 10.0 );
+        Cost = pow( Attract, pow(Repulse, 5.0) );
+        if ( CostBest < Cost )
+        {
+            CostBest = Cost;
+            iBest = i;
+        }
+    }
+    if ( CostBest < 0.6 )
+        return -1;
+    return iBest;
+*/
+
+    Vec_Int_t * vPartSupp;//, * vPart;
+    int Attract, Repulse, Value, ValueBest;
+    int i, nCommon, iBest;
+//    int nCommon2;
+    iBest = -1;
+    ValueBest = 0;
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vPartSupp, i )
+    {
+        // skip partitions with too many outputs
+//        vPart = Vec_PtrEntry( vPartsAll, i );
+//        if ( nSuppSizeLimit > 0 && Vec_IntSize(vPart) >= nSuppSizeLimit )
+//            continue;
+        // find the number of common variables between this output and the partitions
+//        nCommon2 = Vec_IntTwoCountCommon( vPartSupp, vOne );
+        nCommon = Abc_NtkSuppCharCommon( (unsigned *)Vec_PtrEntry(vPartSuppsChar, i), vOne );
+//        assert( nCommon2 == nCommon );
+        // if no common variables, continue searching
+        if ( nCommon == 0 )
+            continue;
+        // if all variables are common, the best partition if found
+        if ( nCommon == Vec_IntSize(vOne) )
+            return i;
+        // skip partitions whose size exceeds the limit
+        if ( nSuppSizeLimit > 0 && Vec_IntSize(vPartSupp) >= 2 * nSuppSizeLimit )
+            continue;
+        // figure out might be the good partition for this one
+        Attract = 1000 * nCommon / Vec_IntSize(vOne);
+        if ( Vec_IntSize(vPartSupp) < 100 )
+            Repulse = 1;
+        else
+            Repulse = 1+Abc_Base2Log(Vec_IntSize(vPartSupp)-100);
+        Value = Attract/Repulse;
+        if ( ValueBest < Value )
+        {
+            ValueBest = Value;
+            iBest = i;
+        }
+    }
+    if ( ValueBest < 75 )
+        return -1;
+    return iBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform the smart partitioning.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPartitionPrint( Abc_Ntk_t * pNtk, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll )
+{
+    Vec_Int_t * vOne;
+    int i, nOutputs, Counter;
+
+    Counter = 0;
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i )
+    {
+        nOutputs = Vec_IntSize((Vec_Int_t *)Vec_PtrEntry(vPartsAll, i));
+        printf( "%d=(%d,%d) ", i, Vec_IntSize(vOne), nOutputs );
+        Counter += nOutputs;
+        if ( i == Vec_PtrSize(vPartsAll) - 1 )
+            break;
+    }
+//    assert( Counter == Abc_NtkCoNum(pNtk) );
+    printf( "\nTotal = %d. Outputs = %d.\n", Counter, Abc_NtkCoNum(pNtk) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform the smart partitioning.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, int nSuppSizeLimit )
+{
+    Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp;
+    int i, iPart;
+
+    if ( nSuppSizeLimit == 0 )
+        nSuppSizeLimit = 200;
+
+    // pack smaller partitions into larger blocks
+    iPart = 0;
+    vPart = vPartSupp = NULL;
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i )
+    {
+        if ( Vec_IntSize(vOne) < nSuppSizeLimit )
+        {
+            if ( vPartSupp == NULL )
+            {
+                assert( vPart == NULL );
+                vPartSupp = Vec_IntDup(vOne);
+                vPart = (Vec_Int_t *)Vec_PtrEntry(vPartsAll, i);
+            }
+            else
+            {
+                vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne );
+                Vec_IntFree( vTemp );
+                vPart = Vec_IntTwoMerge( vTemp = vPart, (Vec_Int_t *)Vec_PtrEntry(vPartsAll, i) );
+                Vec_IntFree( vTemp );
+                Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vPartsAll, i) );
+            }
+            if ( Vec_IntSize(vPartSupp) < nSuppSizeLimit )
+                continue;
+        }
+        else
+            vPart = (Vec_Int_t *)Vec_PtrEntry(vPartsAll, i);
+        // add the partition 
+        Vec_PtrWriteEntry( vPartsAll, iPart, vPart );  
+        vPart = NULL;
+        if ( vPartSupp ) 
+        {
+            Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vPartSuppsAll, iPart) );
+            Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp );  
+            vPartSupp = NULL;
+        }
+        iPart++;
+    }
+    // add the last one
+    if ( vPart )
+    {
+        Vec_PtrWriteEntry( vPartsAll, iPart, vPart );  
+        vPart = NULL;
+
+        assert( vPartSupp != NULL );
+        Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vPartSuppsAll, iPart) );
+        Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp );  
+        vPartSupp = NULL;
+        iPart++;
+    }
+    Vec_PtrShrink( vPartsAll, iPart );
+    Vec_PtrShrink( vPartsAll, iPart );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform the smart partitioning.]
+
+  Description [Returns the ptr-vector of int-vectors.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nSuppSizeLimit, int fVerbose )
+{
+    ProgressBar * pProgress;
+    Vec_Ptr_t * vPartSuppsChar;
+    Vec_Ptr_t * vSupps, * vPartsAll, * vPartsAll2, * vPartSuppsAll;
+    Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp;
+    int i, iPart, iOut, timeFind = 0;
+    abctime clk, clk2;
+
+    // compute the supports for all outputs
+clk = Abc_Clock();
+//    vSupps = Abc_NtkComputeSupportsNaive( pNtk );
+    vSupps = Abc_NtkComputeSupportsSmart( pNtk );
+if ( fVerbose )
+{
+ABC_PRT( "Supps", Abc_Clock() - clk );
+}
+    // start char-based support representation
+    vPartSuppsChar = Vec_PtrAlloc( 1000 );
+
+    // create partitions
+clk = Abc_Clock();
+    vPartsAll = Vec_PtrAlloc( 256 );
+    vPartSuppsAll = Vec_PtrAlloc( 256 );
+    pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vSupps) );
+    Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+//        if ( i % 1000 == 0 )
+//            printf( "CIs = %6d. COs = %6d. Processed = %6d (out of %6d). Parts = %6d.\r", 
+//                Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), i, Vec_PtrSize(vSupps), Vec_PtrSize(vPartsAll) ); 
+        // get the output number
+        iOut = Vec_IntPop(vOne);
+        // find closely matching part
+clk2 = Abc_Clock();
+        iPart = Abc_NtkPartitionSmartFindPart( vPartSuppsAll, vPartsAll, vPartSuppsChar, nSuppSizeLimit, vOne );
+timeFind += Abc_Clock() - clk2;
+        if ( iPart == -1 )
+        {
+            // create new partition
+            vPart = Vec_IntAlloc( 32 );
+            Vec_IntPush( vPart, iOut );
+            // create new partition support
+            vPartSupp = Vec_IntDup( vOne );
+            // add this partition and its support
+            Vec_PtrPush( vPartsAll, vPart );
+            Vec_PtrPush( vPartSuppsAll, vPartSupp );
+
+            Vec_PtrPush( vPartSuppsChar, Abc_NtkSuppCharStart(vOne, Abc_NtkCiNum(pNtk)) );
+        }
+        else
+        {
+            // add output to this partition
+            vPart = (Vec_Int_t *)Vec_PtrEntry( vPartsAll, iPart );
+            Vec_IntPush( vPart, iOut );
+            // merge supports
+            vPartSupp = (Vec_Int_t *)Vec_PtrEntry( vPartSuppsAll, iPart );
+            vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne );
+            Vec_IntFree( vTemp );
+            // reinsert new support
+            Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp );
+
+            Abc_NtkSuppCharAdd( (unsigned *)Vec_PtrEntry(vPartSuppsChar, iPart), vOne, Abc_NtkCiNum(pNtk) );
+        }
+    }
+    Extra_ProgressBarStop( pProgress );
+
+    // stop char-based support representation
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsChar, vTemp, i )
+        ABC_FREE( vTemp );
+    Vec_PtrFree( vPartSuppsChar );
+
+//printf( "\n" );
+if ( fVerbose )
+{
+ABC_PRT( "Parts", Abc_Clock() - clk );
+//ABC_PRT( "Find ", timeFind );
+}
+
+clk = Abc_Clock();
+    // remember number of supports
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i )
+        Vec_IntPush( vOne, i );
+    // sort the supports in the decreasing order
+    Vec_VecSort( (Vec_Vec_t *)vPartSuppsAll, 1 );
+    // reproduce partitions
+    vPartsAll2 = Vec_PtrAlloc( 256 );
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i )
+        Vec_PtrPush( vPartsAll2, Vec_PtrEntry(vPartsAll, Vec_IntPop(vOne)) );
+    Vec_PtrFree( vPartsAll );
+    vPartsAll = vPartsAll2;
+
+    // compact small partitions
+//    Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll );
+    Abc_NtkPartitionCompact( vPartsAll, vPartSuppsAll, nSuppSizeLimit );
+
+if ( fVerbose )
+{
+ABC_PRT( "Comps", Abc_Clock() - clk );
+}
+    if ( fVerbose )
+    printf( "Created %d partitions.\n", Vec_PtrSize(vPartsAll) );
+//    Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll );
+
+    // cleanup
+    Vec_VecFree( (Vec_Vec_t *)vSupps );
+    Vec_VecFree( (Vec_Vec_t *)vPartSuppsAll );
+/*
+    // converts from intergers to nodes
+    Vec_PtrForEachEntry( Vec_Int_t *, vPartsAll, vPart, iPart )
+    {
+        vPartPtr = Vec_PtrAlloc( Vec_IntSize(vPart) );
+        Vec_IntForEachEntry( vPart, iOut, i )
+            Vec_PtrPush( vPartPtr, Abc_NtkCo(pNtk, iOut) );
+        Vec_IntFree( vPart );
+        Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr );
+    }
+*/
+    return vPartsAll;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform the naive partitioning.]
+
+  Description [Returns the ptr-vector of int-vectors.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkPartitionNaive( Abc_Ntk_t * pNtk, int nPartSize )
+{
+    Vec_Ptr_t * vParts;
+    Abc_Obj_t * pObj;
+    int nParts, i;
+    nParts = (Abc_NtkCoNum(pNtk) / nPartSize) + ((Abc_NtkCoNum(pNtk) % nPartSize) > 0);
+    vParts = (Vec_Ptr_t *)Vec_VecStart( nParts );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vParts, i / nPartSize), i );
+    return vParts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts from intergers to pointers for the given network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkConvertCos( Abc_Ntk_t * pNtk, Vec_Int_t * vOuts, Vec_Ptr_t * vOutsPtr )
+{
+    int Out, i;
+    Vec_PtrClear( vOutsPtr );
+    Vec_IntForEachEntry( vOuts, Out, i )
+        Vec_PtrPush( vOutsPtr, Abc_NtkCo(pNtk, Out) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns representative of the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkPartStitchFindRepr_rec( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pRepr;
+    pRepr = (Abc_Obj_t *)Vec_PtrEntry( vEquiv, pObj->Id );
+    if ( pRepr == NULL || pRepr == pObj )
+        return pObj;
+    return Abc_NtkPartStitchFindRepr_rec( vEquiv, pRepr );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the representative of the fanin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Abc_Obj_t * Abc_NtkPartStitchCopy0( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFan = Abc_ObjFanin0( pObj );
+    Abc_Obj_t * pRepr = Abc_NtkPartStitchFindRepr_rec( vEquiv, pFan );
+    return Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pFan->fPhase ^ (int)Abc_ObjFaninC1(pObj) );
+}
+static inline Abc_Obj_t * Abc_NtkPartStitchCopy1( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFan = Abc_ObjFanin1( pObj );
+    Abc_Obj_t * pRepr = Abc_NtkPartStitchFindRepr_rec( vEquiv, pFan );
+    return Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pFan->fPhase ^ (int)Abc_ObjFaninC1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Hop_Obj_t * Hop_ObjChild0Next( Abc_Obj_t * pObj ) { return Hop_NotCond( (Hop_Obj_t *)Abc_ObjFanin0(pObj)->pNext, Abc_ObjFaninC0(pObj) ); }
+static inline Hop_Obj_t * Hop_ObjChild1Next( Abc_Obj_t * pObj ) { return Hop_NotCond( (Hop_Obj_t *)Abc_ObjFanin1(pObj)->pNext, Abc_ObjFaninC1(pObj) ); }
+
+
+/**Function*************************************************************
+
+  Synopsis    [Stitches together several networks with choice nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Man_t * Abc_NtkPartStartHop( Abc_Ntk_t * pNtk )
+{
+    Hop_Man_t * pMan;
+    Abc_Obj_t * pObj;
+    int i;
+    // start the HOP package
+    pMan = Hop_ManStart();
+    pMan->vObjs = Vec_PtrAlloc( Abc_NtkObjNumMax(pNtk) + 1  );
+    Vec_PtrPush( pMan->vObjs, Hop_ManConst1(pMan) );
+    // map constant node and PIs
+    Abc_AigConst1(pNtk)->pNext = (Abc_Obj_t *)Hop_ManConst1(pMan);
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->pNext = (Abc_Obj_t *)Hop_ObjCreatePi(pMan);
+    // map the internal nodes
+    Abc_AigForEachAnd( pNtk, pObj, i )
+    {
+        pObj->pNext = (Abc_Obj_t *)Hop_And( pMan, Hop_ObjChild0Next(pObj), Hop_ObjChild1Next(pObj) );
+        assert( !Abc_ObjIsComplement(pObj->pNext) );
+    }
+    // set the choice nodes
+    Abc_AigForEachAnd( pNtk, pObj, i )
+    {
+        if ( pObj->pCopy )
+            ((Hop_Obj_t *)pObj->pNext)->pData = pObj->pCopy->pNext;
+    }
+    // transfer the POs
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Hop_ObjCreatePo( pMan, Hop_ObjChild0Next(pObj) );
+    // check the new manager
+    if ( !Hop_ManCheck(pMan) )
+        printf( "Abc_NtkPartStartHop: HOP manager check has failed.\n" );
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stitches together several networks with choice nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts )
+{
+    extern Abc_Ntk_t * Abc_NtkHopRemoveLoops( Abc_Ntk_t * pNtk, Hop_Man_t * pMan );
+    Hop_Man_t * pMan;
+    Vec_Ptr_t * vNodes;
+    Abc_Ntk_t * pNtkNew, * pNtkTemp;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k, iNodeId;
+
+    // start a new network similar to the original one
+    assert( Abc_NtkIsStrash(pNtk) );
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+
+    // annotate parts to point to the new network
+    Vec_PtrForEachEntry( Abc_Ntk_t *, vParts, pNtkTemp, i )
+    {
+        assert( Abc_NtkIsStrash(pNtkTemp) );
+        Abc_NtkCleanCopy( pNtkTemp );
+
+        // map the CI nodes
+        Abc_AigConst1(pNtkTemp)->pCopy = Abc_AigConst1(pNtkNew);
+        Abc_NtkForEachCi( pNtkTemp, pObj, k )
+        {
+            iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO );
+            if ( iNodeId == -1 )
+            {
+                printf( "Cannot find CI node %s in the original network.\n", Abc_ObjName(pObj) );
+                return NULL;
+            }
+            pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId );
+        }
+
+        // add the internal nodes while saving representatives
+        vNodes = Abc_AigDfs( pNtkTemp, 1, 0 );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, k )
+        {
+            pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+            assert( !Abc_ObjIsComplement(pObj->pCopy) );
+            if ( Abc_AigNodeIsChoice(pObj) )
+                for ( pFanin = (Abc_Obj_t *)pObj->pData; pFanin; pFanin = (Abc_Obj_t *)pFanin->pData )
+                    pFanin->pCopy->pCopy = pObj->pCopy;
+        }
+        Vec_PtrFree( vNodes );
+
+        // map the CO nodes
+        Abc_NtkForEachCo( pNtkTemp, pObj, k )
+        {
+            iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI );
+            if ( iNodeId == -1 )
+            {
+                printf( "Cannot find CO node %s in the original network.\n", Abc_ObjName(pObj) );
+                return NULL;
+            }
+            pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId );
+            Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
+        }
+    }
+
+    // connect the remaining POs
+/*
+    Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->pCopy = Abc_NtkCi( pNtkNew, i );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        pObj->pCopy = Abc_NtkCo( pNtkNew, i );
+*/
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        if ( Abc_ObjFaninNum(pObj->pCopy) == 0 )
+            Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
+    }
+
+    // transform into the HOP manager
+    pMan = Abc_NtkPartStartHop( pNtkNew );
+    pNtkNew = Abc_NtkHopRemoveLoops( pNtkTemp = pNtkNew, pMan );
+    Abc_NtkDelete( pNtkTemp );
+
+    // check correctness of the new network
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkPartStitchChoices: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stitches together several networks with choice nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFraigPartitioned( Vec_Ptr_t * vStore, void * pParams )
+{
+    Vec_Ptr_t * vParts, * vFraigs, * vOnePtr;
+    Vec_Int_t * vOne;
+    Abc_Ntk_t * pNtk, * pNtk2, * pNtkAig, * pNtkFraig;
+    int i, k;
+
+    // perform partitioning
+    pNtk = (Abc_Ntk_t *)Vec_PtrEntry( vStore, 0 );
+    assert( Abc_NtkIsStrash(pNtk) );
+//    vParts = Abc_NtkPartitionNaive( pNtk, 20 );
+    vParts = Abc_NtkPartitionSmart( pNtk, 300, 0 );
+
+    Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" );
+
+    // fraig each partition
+    vOnePtr = Vec_PtrAlloc( 1000 );
+    vFraigs = Vec_PtrAlloc( Vec_PtrSize(vParts) );
+    Vec_PtrForEachEntry( Vec_Int_t *, vParts, vOne, i )
+    {
+        // start the partition 
+        Abc_NtkConvertCos( pNtk, vOne, vOnePtr );
+        pNtkAig = Abc_NtkCreateConeArray( pNtk, vOnePtr, 0 );
+        // add nodes to the partition
+        Vec_PtrForEachEntryStart( Abc_Ntk_t *, vStore, pNtk2, k, 1 )
+        {
+            Abc_NtkConvertCos( pNtk2, vOne, vOnePtr );
+            Abc_NtkAppendToCone( pNtkAig, pNtk2, vOnePtr );
+        }
+        printf( "Fraiging part %4d  (out of %4d)  PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", 
+            i+1, Vec_PtrSize(vParts), Abc_NtkPiNum(pNtkAig), Abc_NtkPoNum(pNtkAig), 
+            Abc_NtkNodeNum(pNtkAig), Abc_AigLevel(pNtkAig) );
+        // fraig the partition
+        pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 1, 0 );
+        Vec_PtrPush( vFraigs, pNtkFraig );
+        Abc_NtkDelete( pNtkAig );
+    }
+    printf( "                                                                                          \r" );
+    Vec_VecFree( (Vec_Vec_t *)vParts );
+
+    Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" );
+
+    // derive the final network
+    pNtkFraig = Abc_NtkPartStitchChoices( pNtk, vFraigs );
+    Vec_PtrForEachEntry( Abc_Ntk_t *, vFraigs, pNtkAig, i )
+        Abc_NtkDelete( pNtkAig );
+    Vec_PtrFree( vFraigs );
+    Vec_PtrFree( vOnePtr );
+    return pNtkFraig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stitches together several networks with choice nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams )
+{
+    Vec_Ptr_t * vParts, * vFraigs, * vOnePtr;
+    Vec_Int_t * vOne;
+    Abc_Ntk_t * pNtkAig, * pNtkFraig;
+    int i;
+    abctime clk = Abc_Clock();
+
+    // perform partitioning
+    assert( Abc_NtkIsStrash(pNtk) );
+//    vParts = Abc_NtkPartitionNaive( pNtk, 20 );
+    vParts = Abc_NtkPartitionSmart( pNtk, 300, 0 );
+
+    Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" );
+
+    // fraig each partition
+    vOnePtr = Vec_PtrAlloc( 1000 );
+    vFraigs = Vec_PtrAlloc( Vec_PtrSize(vParts) );
+    Vec_PtrForEachEntry( Vec_Int_t *, vParts, vOne, i )
+    {
+        Abc_NtkConvertCos( pNtk, vOne, vOnePtr );
+        pNtkAig = Abc_NtkCreateConeArray( pNtk, vOnePtr, 0 );
+        pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 0, 0 );
+        Vec_PtrPush( vFraigs, pNtkFraig );
+        Abc_NtkDelete( pNtkAig );
+
+        printf( "Finished part %5d (out of %5d)\r", i+1, Vec_PtrSize(vParts) );
+    }
+    Vec_VecFree( (Vec_Vec_t *)vParts );
+
+    Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" );
+
+    // derive the final network
+    Vec_PtrForEachEntry( Abc_Ntk_t *, vFraigs, pNtkAig, i )
+        Abc_NtkDelete( pNtkAig );
+    Vec_PtrFree( vFraigs );
+    Vec_PtrFree( vOnePtr );
+    ABC_PRT( "Partitioned fraiging time", Abc_Clock() - clk );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcPlace.c b/abc-build/src/base/abci/abcPlace.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcPlace.c
@@ -0,0 +1,260 @@
+/**CFile****************************************************************
+
+  FileName    [abcPlace.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Interface with a placer.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcPlace.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+
+// placement includes
+#include "phys/place/place_base.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+AbstractCell *abstractCells = NULL;
+ConcreteCell *cells = NULL;
+ConcreteNet *nets = NULL;
+int nAllocSize = 0;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new cell.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_PlaceCreateCell( Abc_Obj_t * pObj, int fAnd )
+{
+    assert( cells[pObj->Id].m_id == 0 );
+
+    cells[pObj->Id].m_id = pObj->Id;
+    cells[pObj->Id].m_label = "";
+    cells[pObj->Id].m_parent = &(abstractCells[fAnd]);
+    cells[pObj->Id].m_fixed = 0;
+    addConcreteCell(&(cells[pObj->Id]));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the net.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_PlaceUpdateNet( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    int k;
+    // free the old array of net terminals
+    if ( nets[pObj->Id].m_terms )
+        free( nets[pObj->Id].m_terms );
+    // fill in the net with the new information
+    nets[pObj->Id].m_id = pObj->Id;
+    nets[pObj->Id].m_weight = 1.0;
+    nets[pObj->Id].m_numTerms = Abc_ObjFanoutNum(pObj); //fanout
+    nets[pObj->Id].m_terms = ALLOC(ConcreteCell*, Abc_ObjFanoutNum(pObj));
+    Abc_ObjForEachFanout( pObj, pFanout, k )
+        nets[pObj->Id].m_terms[k] = &(cells[pFanout->Id]);
+    addConcreteNet(&(nets[pObj->Id]));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the placement cost of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Abc_PlaceEvaluateCut( Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins )
+{
+    Abc_Obj_t * pObj;
+//    double x, y;
+    int i;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i )
+    {
+//        pObj->Id
+    }
+    return 0.0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates placement after one step of rewriting.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_PlaceUpdate( Vec_Ptr_t * vAddedCells, Vec_Ptr_t * vUpdatedNets )
+{
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k;
+    Vec_Ptr_t * vCells, * vNets;
+
+    // start the arrays of new cells and nets
+    vCells = Vec_PtrAlloc( 16 );
+    vNets = Vec_PtrAlloc( 32 );
+
+    // go through the new nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vAddedCells, pObj, i )
+    {
+        assert( !Abc_ObjIsComplement(pObj) );
+        Abc_PlaceCreateCell( pObj, 1 );
+        Abc_PlaceUpdateNet( pObj );
+
+        // add the new cell and its fanin nets to temporary storage
+        Vec_PtrPush( vCells, &(cells[pObj->Id]) );
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Vec_PtrPushUnique( vNets, &(nets[pFanin->Id]) );
+    }
+
+    // go through the modified nets
+    Vec_PtrForEachEntry( Abc_Obj_t *, vUpdatedNets, pObj, i )
+    {
+        assert( !Abc_ObjIsComplement(pObj) );
+        if ( Abc_ObjType(pObj) == ABC_OBJ_NONE ) // dead node
+            continue;
+        Abc_PlaceUpdateNet( pObj );
+    }
+
+    // update the placement
+//    fastPlace( Vec_PtrSize(vCells), (ConcreteCell **)Vec_PtrArray(vCells), 
+//               Vec_PtrSize(vNets), (ConcreteNet **)Vec_PtrArray(vNets) );
+
+    // clean up
+    Vec_PtrFree( vCells );
+    Vec_PtrFree( vNets );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure is called before the writing start.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_PlaceBegin( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+
+    // allocate and clean internal storage
+    nAllocSize = 5 * Abc_NtkObjNumMax(pNtk);
+    cells = REALLOC(ConcreteCell, cells, nAllocSize);
+    nets  = REALLOC(ConcreteNet, nets, nAllocSize);
+    memset( cells, 0, sizeof(ConcreteCell) * nAllocSize );
+    memset( nets, 0, sizeof(ConcreteNet) * nAllocSize );
+
+    // create AbstractCells
+    //   1: pad
+    //   2: and
+    if (!abstractCells)
+        abstractCells = ALLOC(AbstractCell,2);
+
+    abstractCells[0].m_height = 1.0;
+    abstractCells[0].m_width = 1.0;
+    abstractCells[0].m_label = "pio";
+    abstractCells[0].m_pad = 1;
+
+    abstractCells[1].m_height = 1.0;
+    abstractCells[1].m_width = 1.0;
+    abstractCells[1].m_label = "and";
+    abstractCells[1].m_pad = 0;
+
+    // input pads
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        Abc_PlaceCreateCell( pObj, 0 );
+
+    // ouput pads
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Abc_PlaceCreateCell( pObj, 0 );
+
+    // AND nodes
+    Abc_AigForEachAnd( pNtk, pObj, i )
+        Abc_PlaceCreateCell( pObj, 1 );
+
+    // all nets
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        if ( !Abc_ObjIsCi(pObj) && !Abc_ObjIsNode(pObj) )
+            continue;
+        Abc_PlaceUpdateNet( pObj );
+    }
+
+    globalPreplace((float)0.8);
+    globalPlace();
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure is called after the writing completes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_PlaceEnd( Abc_Ntk_t * pNtk )
+{
+    int i;
+
+
+    // clean up
+    for ( i = 0; i < nAllocSize; i++ )
+        FREE( nets[i].m_terms );
+    FREE( abstractCells );
+    FREE( cells );
+    FREE( nets );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcPrint.c b/abc-build/src/base/abci/abcPrint.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcPrint.c
@@ -0,0 +1,1598 @@
+/**CFile****************************************************************
+
+  FileName    [abcPrint.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Printing statistics.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcPrint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <math.h>
+#include "base/abc/abc.h"
+#include "bool/dec/dec.h"
+#include "base/main/main.h"
+#include "map/mio/mio.h"
+#include "aig/aig/aig.h"
+#include "map/if/if.h"
+#include "misc/extra/extraBdd.h"
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+//extern int s_TotalNodes = 0;
+//extern int s_TotalChanges = 0;
+
+abctime s_MappingTime = 0;
+int s_MappingMem = 0;
+abctime s_ResubTime = 0;
+abctime s_ResynTime = 0;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [If the network is best, saves it in "best.blif" and returns 1.]
+
+  Description [If the networks are incomparable, saves the new network, 
+  returns its parameters in the internal parameter structure, and returns 1.
+  If the new network is not a logic network, quits without saving and returns 0.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCompareAndSaveBest( Abc_Ntk_t * pNtk )
+{
+    extern void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType );
+    static struct ParStruct {
+        char * pName;  // name of the best saved network
+        int    Depth;  // depth of the best saved network
+        int    Flops;  // flops in the best saved network 
+        int    Nodes;  // nodes in the best saved network
+        int    Edges;  // edges in the best saved network
+        int    nPis;   // the number of primary inputs
+        int    nPos;   // the number of primary outputs
+    } ParsNew, ParsBest = { 0 };
+    char * pFileNameOut;
+    // free storage for the name
+    if ( pNtk == NULL )
+    {
+        ABC_FREE( ParsBest.pName );
+        return 0;
+    }
+    // quit if not a logic network
+    if ( !Abc_NtkIsLogic(pNtk) )
+        return 0;
+    // get the parameters
+    ParsNew.Depth = Abc_NtkLevel( pNtk );
+    ParsNew.Flops = Abc_NtkLatchNum( pNtk );
+    ParsNew.Nodes = Abc_NtkNodeNum( pNtk );
+    ParsNew.Edges = Abc_NtkGetTotalFanins( pNtk );
+    ParsNew.nPis  = Abc_NtkPiNum( pNtk );
+    ParsNew.nPos  = Abc_NtkPoNum( pNtk );
+    // reset the parameters if the network has the same name
+    if (  ParsBest.pName == NULL ||
+          strcmp(ParsBest.pName, pNtk->pName) ||
+          ParsBest.Depth >  ParsNew.Depth ||
+         (ParsBest.Depth == ParsNew.Depth && ParsBest.Flops >  ParsNew.Flops) ||
+         (ParsBest.Depth == ParsNew.Depth && ParsBest.Flops == ParsNew.Flops && ParsBest.Edges >  ParsNew.Edges) )
+    {
+        ABC_FREE( ParsBest.pName );
+        ParsBest.pName = Extra_UtilStrsav( pNtk->pName );
+        ParsBest.Depth = ParsNew.Depth;
+        ParsBest.Flops = ParsNew.Flops;
+        ParsBest.Nodes = ParsNew.Nodes;
+        ParsBest.Edges = ParsNew.Edges;
+        ParsBest.nPis  = ParsNew.nPis;
+        ParsBest.nPos  = ParsNew.nPos;
+        // writ the network
+        if ( strcmp(pNtk->pSpec + strlen(pNtk->pSpec) - strlen("_best.blif"), "_best.blif") )
+            pFileNameOut = Extra_FileNameGenericAppend( pNtk->pSpec, "_best.blif" );
+        else
+            pFileNameOut = pNtk->pSpec;
+        Io_Write( pNtk, pFileNameOut, IO_FILE_BLIF );
+        return 1;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks nodes for power-optimization.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Abc_NtkMfsTotalSwitching( Abc_Ntk_t * pNtk )
+{
+    extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+    extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne );
+    Vec_Int_t * vSwitching;
+    float * pSwitching;
+    Abc_Ntk_t * pNtkStr;
+    Aig_Man_t * pAig;
+    Aig_Obj_t * pObjAig;
+    Abc_Obj_t * pObjAbc, * pObjAbc2;
+    float Result = (float)0;
+    int i;
+    // strash the network
+    pNtkStr = Abc_NtkStrash( pNtk, 0, 1, 0 );
+    Abc_NtkForEachObj( pNtk, pObjAbc, i )
+        if ( Abc_ObjRegular((Abc_Obj_t *)pObjAbc->pTemp)->Type == ABC_FUNC_NONE || (!Abc_ObjIsCi(pObjAbc) && !Abc_ObjIsNode(pObjAbc)) )
+            pObjAbc->pTemp = NULL;
+    // map network into an AIG
+    pAig = Abc_NtkToDar( pNtkStr, 0, (int)(Abc_NtkLatchNum(pNtk) > 0) );
+    vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, 0 );
+    pSwitching = (float *)vSwitching->pArray;
+    Abc_NtkForEachObj( pNtk, pObjAbc, i )
+    {
+        if ( (pObjAbc2 = Abc_ObjRegular((Abc_Obj_t *)pObjAbc->pTemp)) && (pObjAig = Aig_Regular((Aig_Obj_t *)pObjAbc2->pTemp)) )
+        {
+            Result += Abc_ObjFanoutNum(pObjAbc) * pSwitching[pObjAig->Id];
+//            Abc_ObjPrint( stdout, pObjAbc );
+//            printf( "%d = %.2f\n", i, Abc_ObjFanoutNum(pObjAbc) * pSwitching[pObjAig->Id] );
+        }
+    }
+    Vec_IntFree( vSwitching );
+    Aig_ManStop( pAig );
+    Abc_NtkDelete( pNtkStr );
+    return Result;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute area using LUT library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Abc_NtkGetArea( Abc_Ntk_t * pNtk )
+{
+    If_LibLut_t * pLutLib;
+    Abc_Obj_t * pObj;
+    float Counter = 0.0;
+    int i;
+    assert( Abc_NtkIsLogic(pNtk) );
+    // get the library
+    pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut();
+    if ( pLutLib && pLutLib->LutMax >= Abc_NtkGetFaninMax(pNtk) )
+    {
+        Abc_NtkForEachNode( pNtk, pObj, i )
+            Counter += pLutLib->pLutAreas[Abc_ObjFaninNum(pObj)];
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print the vital stats of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower, int fGlitch, int fSkipBuf )
+{
+    int nSingles = fSkipBuf ? Abc_NtkGetBufNum(pNtk) : 0;
+    if ( fPrintMuxes && Abc_NtkIsStrash(pNtk) )
+    {
+        extern int Abc_NtkCountMuxes( Abc_Ntk_t * pNtk );
+        int nXors = Abc_NtkGetExorNum(pNtk);
+        int nMuxs = Abc_NtkCountMuxes(pNtk) - nXors;
+        int nAnds = Abc_NtkNodeNum(pNtk) - (nMuxs + nXors) * 3 - nSingles;
+        Abc_Print( 1, "XMA stats:  " );
+        Abc_Print( 1,"Xor =%7d (%6.2f %%)  ", nXors, 300.0 * nXors / Abc_NtkNodeNum(pNtk) );
+        Abc_Print( 1,"Mux =%7d (%6.2f %%)  ", nMuxs, 300.0 * nMuxs / Abc_NtkNodeNum(pNtk) );
+        Abc_Print( 1,"And =%7d (%6.2f %%)",   nAnds, 100.0 * nAnds / Abc_NtkNodeNum(pNtk) );
+        Abc_Print( 1,"\n" );
+        return;
+    }
+    if ( fSaveBest )
+        Abc_NtkCompareAndSaveBest( pNtk );
+    if ( fDumpResult )
+    {
+        char Buffer[1000] = {0};
+        const char * pNameGen = pNtk->pSpec? Extra_FileNameGeneric( pNtk->pSpec ) : "nameless_";
+        sprintf( Buffer, "%s_dump.blif", pNameGen );
+        Io_Write( pNtk, Buffer, IO_FILE_BLIF );
+        if ( pNtk->pSpec ) ABC_FREE( pNameGen );
+    }
+
+//    if ( Abc_NtkIsStrash(pNtk) )
+//        Abc_AigCountNext( pNtk->pManFunc );
+
+#ifdef WIN32
+    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 15 ); // bright
+    Abc_Print( 1,"%-13s:", pNtk->pName );
+    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 );  // normal
+#else
+    Abc_Print( 1,"%s%-13s:%s", "\033[1;37m", pNtk->pName, "\033[0m" );  // bright
+#endif
+    Abc_Print( 1," i/o =%5d/%5d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) );
+    if ( Abc_NtkConstrNum(pNtk) )
+        Abc_Print( 1,"(c=%d)", Abc_NtkConstrNum(pNtk) );
+    Abc_Print( 1,"  lat =%5d", Abc_NtkLatchNum(pNtk) );
+    if ( pNtk->nBarBufs )
+        Abc_Print( 1,"(b=%d)", pNtk->nBarBufs );
+    if ( Abc_NtkIsNetlist(pNtk) )
+    {
+        Abc_Print( 1,"  net =%5d", Abc_NtkNetNum(pNtk) );
+        Abc_Print( 1,"  nd =%5d",  Abc_NtkNodeNum(pNtk) - nSingles );
+        Abc_Print( 1,"  wbox =%3d", Abc_NtkWhiteboxNum(pNtk) );
+        Abc_Print( 1,"  bbox =%3d", Abc_NtkBlackboxNum(pNtk) );
+    }
+    else if ( Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( 1,"  and =%7d", Abc_NtkNodeNum(pNtk) );
+        if ( Abc_NtkGetChoiceNum(pNtk) )
+            Abc_Print( 1," (choice = %d)", Abc_NtkGetChoiceNum(pNtk) );
+    }
+    else
+    {
+        Abc_Print( 1,"  nd =%6d", Abc_NtkNodeNum(pNtk) - nSingles );
+        Abc_Print( 1,"  edge =%7d", Abc_NtkGetTotalFanins(pNtk) - nSingles );
+    }
+
+    if ( Abc_NtkIsStrash(pNtk) || Abc_NtkIsNetlist(pNtk) )
+    {
+    }
+    else if ( Abc_NtkHasSop(pNtk) )
+    {
+
+        Abc_Print( 1,"  cube =%6d",  Abc_NtkGetCubeNum(pNtk) - nSingles );
+        if ( fFactored )
+            Abc_Print( 1,"  lit(sop) =%6d",  Abc_NtkGetLitNum(pNtk) - nSingles );
+        if ( fFactored )
+            Abc_Print( 1,"  lit(fac) =%6d",  Abc_NtkGetLitFactNum(pNtk) - nSingles );
+    }
+    else if ( Abc_NtkHasAig(pNtk) )
+        Abc_Print( 1,"  aig  =%6d",  Abc_NtkGetAigNodeNum(pNtk) - nSingles );
+    else if ( Abc_NtkHasBdd(pNtk) )
+        Abc_Print( 1,"  bdd  =%6d",  Abc_NtkGetBddNodeNum(pNtk) - nSingles );
+    else if ( Abc_NtkHasMapping(pNtk) )
+    {
+        assert( pNtk->pManFunc == Abc_FrameReadLibGen() );
+        Abc_Print( 1,"  area =%5.2f", Abc_NtkGetMappedArea(pNtk) );
+        Abc_Print( 1,"  delay =%5.2f", Abc_NtkDelayTrace(pNtk, NULL, NULL, 0) );
+        if ( pNtk->pManTime )
+            Abc_ManTimeStop( pNtk->pManTime );
+        pNtk->pManTime = NULL;
+    }
+    else if ( !Abc_NtkHasBlackbox(pNtk) )
+    {
+        assert( 0 );
+    }
+
+    if ( Abc_NtkIsStrash(pNtk) )
+    {
+        extern int Abc_NtkGetMultiRefNum( Abc_Ntk_t * pNtk );
+        Abc_Print( 1,"  lev =%3d", Abc_AigLevel(pNtk) );
+//        Abc_Print( 1,"  ff = %5d", Abc_NtkNodeNum(pNtk) + 2 * (Abc_NtkCoNum(pNtk)+Abc_NtkGetMultiRefNum(pNtk)) );
+//        Abc_Print( 1,"  var = %5d", Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk)+Abc_NtkGetMultiRefNum(pNtk) );
+    }
+    else
+        Abc_Print( 1,"  lev =%3d", Abc_NtkLevel(pNtk) );
+    if ( fUseLutLib && Abc_FrameReadLibLut() )
+        Abc_Print( 1,"  delay =%5.2f", Abc_NtkDelayTraceLut(pNtk, 1) );
+    if ( fUseLutLib && Abc_FrameReadLibLut() )
+        Abc_Print( 1,"  area =%5.2f", Abc_NtkGetArea(pNtk) );
+    if ( fPower )
+        Abc_Print( 1,"  power =%7.2f", Abc_NtkMfsTotalSwitching(pNtk) );
+    if ( fGlitch )
+    {
+        extern float Abc_NtkMfsTotalGlitching( Abc_Ntk_t * pNtk );
+        if ( Abc_NtkIsLogic(pNtk) && Abc_NtkGetFaninMax(pNtk) <= 6 )
+            Abc_Print( 1,"  glitch =%7.2f %%", Abc_NtkMfsTotalGlitching(pNtk) );
+        else
+            printf( "\nCurrently computes glitching only for K-LUT networks with K <= 6." );
+    }
+    Abc_Print( 1,"\n" );
+
+    // print the statistic into a file
+/*
+    {
+        FILE * pTable;
+        pTable = fopen( "ibm/seq_stats.txt", "a+" );
+//        fprintf( pTable, "%s ",  pNtk->pName );
+//        fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) );
+//        fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) );
+        fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) );
+        fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) );
+        fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) );
+        fprintf( pTable, "\n" );
+        fclose( pTable );
+    }
+*/
+
+/*
+    // print the statistic into a file
+    {
+        FILE * pTable;
+        pTable = fopen( "ucsb/stats.txt", "a+" );
+//        fprintf( pTable, "%s ",  pNtk->pSpec );
+        fprintf( pTable, "%d ",  Abc_NtkNodeNum(pNtk) );
+//        fprintf( pTable, "%d ",  Abc_NtkLevel(pNtk) );
+//        fprintf( pTable, "%.0f ", Abc_NtkGetMappedArea(pNtk) );
+//        fprintf( pTable, "%.2f ", Abc_NtkDelayTrace(pNtk) );
+        fprintf( pTable, "\n" );
+        fclose( pTable );
+    }
+*/
+
+/*
+    // print the statistic into a file
+    {
+        FILE * pTable;
+        pTable = fopen( "x/stats_new.txt", "a+" );
+        fprintf( pTable, "%s ",  pNtk->pName );
+//        fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) );
+//        fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) );
+//        fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) );
+//        fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) );
+//        fprintf( pTable, "%d ", Abc_NtkGetTotalFanins(pNtk) );
+//        fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) );
+//        fprintf( pTable, "%.2f ", (float)(s_MappingMem)/(float)(1<<20) );
+        fprintf( pTable, "%.2f", (float)(s_MappingTime)/(float)(CLOCKS_PER_SEC) );
+//        fprintf( pTable, "%.2f", (float)(s_ResynTime)/(float)(CLOCKS_PER_SEC) );
+        fprintf( pTable, "\n" );
+        fclose( pTable );
+
+        s_ResynTime = 0;
+    }
+*/
+
+/*
+    // print the statistic into a file
+    {
+        static int Counter = 0;
+        extern int timeRetime;
+        FILE * pTable;
+        Counter++;
+        pTable = fopen( "d/stats.txt", "a+" );
+        fprintf( pTable, "%s ", pNtk->pName );
+//        fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) );
+//        fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) );
+//        fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) );
+        fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) );
+        fprintf( pTable, "%.2f ", (float)(timeRetime)/(float)(CLOCKS_PER_SEC) );
+        fprintf( pTable, "\n" );
+        fclose( pTable );
+    }
+
+
+    s_TotalNodes += Abc_NtkNodeNum(pNtk);
+    printf( "Total nodes = %6d   %6.2f MB   Changes = %6d.\n", 
+        s_TotalNodes, s_TotalNodes * 20.0 / (1<<20), s_TotalChanges );
+*/
+
+//    if ( Abc_NtkHasSop(pNtk) )
+//        printf( "The total number of cube pairs = %d.\n", Abc_NtkGetCubePairNum(pNtk) );
+
+    fflush( stdout );
+    if ( pNtk->pExdc )
+        Abc_NtkPrintStats( pNtk->pExdc, fFactored, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints PIs/POs and LIs/LOs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintFlops )
+{
+    Abc_Obj_t * pObj;
+    int i;
+
+    fprintf( pFile, "Primary inputs (%d): ", Abc_NtkPiNum(pNtk) );
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        fprintf( pFile, " %s", Abc_ObjName(pObj) );
+//        fprintf( pFile, " %s(%d)", Abc_ObjName(pObj), Abc_ObjFanoutNum(pObj) );
+    fprintf( pFile, "\n" );
+
+    fprintf( pFile, "Primary outputs (%d):", Abc_NtkPoNum(pNtk) );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        fprintf( pFile, " %s", Abc_ObjName(pObj) );
+    fprintf( pFile, "\n" );
+
+    if ( !fPrintFlops )
+        return;
+
+    fprintf( pFile, "Latches (%d):  ", Abc_NtkLatchNum(pNtk) );
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        fprintf( pFile, " %s(%s=%s)", Abc_ObjName(pObj),
+            Abc_ObjName(Abc_ObjFanout0(pObj)), Abc_ObjName(Abc_ObjFanin0(pObj)) );
+    fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints statistics about latches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pLatch, * pFanin;
+    int i, Counter0, Counter1, Counter2;
+    int InitNums[4], Init;
+
+    assert( !Abc_NtkIsNetlist(pNtk) );
+    if ( Abc_NtkLatchNum(pNtk) == 0 )
+    {
+        fprintf( pFile, "The network is combinational.\n" );
+        return;
+    }
+
+    for ( i = 0; i < 4; i++ )
+        InitNums[i] = 0;
+    Counter0 = Counter1 = Counter2 = 0;
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+        Init = Abc_LatchInit( pLatch );
+        assert( Init < 4 );
+        InitNums[Init]++;
+
+        pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch));
+        if ( Abc_NtkIsLogic(pNtk) )
+        {
+            if ( !Abc_NodeIsConst(pFanin) )
+                continue;
+        }
+        else if ( Abc_NtkIsStrash(pNtk) )
+        {
+            if ( !Abc_AigNodeIsConst(pFanin) )
+                continue;
+        }
+        else
+            assert( 0 );
+
+        // the latch input is a constant node
+        Counter0++;
+        if ( Abc_LatchIsInitDc(pLatch) )
+        {
+            Counter1++;
+            continue;
+        }
+        // count the number of cases when the constant is equal to the initial value
+        if ( Abc_NtkIsStrash(pNtk) )
+        {
+            if ( Abc_LatchIsInit1(pLatch) == !Abc_ObjFaninC0(pLatch) )
+                Counter2++;
+        }
+        else
+        {
+            if ( Abc_LatchIsInit1(pLatch) == Abc_NodeIsConst1(Abc_ObjFanin0(Abc_ObjFanin0(pLatch))) )
+                Counter2++;
+        }
+    }
+//    fprintf( pFile, "%-15s:  ", pNtk->pName );
+    fprintf( pFile, "Total latches = %5d. Init0 = %d. Init1 = %d. InitDC = %d. Const data = %d.\n",
+        Abc_NtkLatchNum(pNtk), InitNums[1], InitNums[2], InitNums[3], Counter0 );
+//    fprintf( pFile, "Const fanin = %3d. DC init = %3d. Matching init = %3d. ", Counter0, Counter1, Counter2 );
+//    fprintf( pFile, "Self-feed latches = %2d.\n", -1 ); //Abc_NtkCountSelfFeedLatches(pNtk) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the distribution of fanins/fanouts in the network.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk, int fUsePis )
+{
+    Abc_Obj_t * pNode;
+    int i, k, nFanins, nFanouts;
+    Vec_Int_t * vFanins, * vFanouts;
+    int nOldSize, nNewSize;
+
+    vFanins  = Vec_IntAlloc( 0 );
+    vFanouts = Vec_IntAlloc( 0 );
+    Vec_IntFill( vFanins,  100, 0 );
+    Vec_IntFill( vFanouts, 100, 0 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        nFanins  = Abc_ObjFaninNum(pNode);
+        if ( Abc_NtkIsNetlist(pNtk) )
+            nFanouts = Abc_ObjFanoutNum( Abc_ObjFanout0(pNode) );
+        else
+            nFanouts = Abc_ObjFanoutNum(pNode);
+//            nFanouts = Abc_NodeMffcSize(pNode);
+        if ( nFanins > vFanins->nSize || nFanouts > vFanouts->nSize )
+        {
+            nOldSize = vFanins->nSize;
+            nNewSize = Abc_MaxInt(nFanins, nFanouts) + 10;
+            Vec_IntGrow( vFanins,  nNewSize  );
+            Vec_IntGrow( vFanouts, nNewSize );
+            for ( k = nOldSize; k < nNewSize; k++ )
+            {
+                Vec_IntPush( vFanins,  0  );
+                Vec_IntPush( vFanouts, 0 );
+            }
+        }
+        vFanins->pArray[nFanins]++;
+        vFanouts->pArray[nFanouts]++;
+    }
+    if ( fUsePis )
+    {
+        Vec_IntFill( vFanouts, Vec_IntSize(vFanouts), 0 );
+        Abc_NtkForEachCi( pNtk, pNode, i )
+        {
+            if ( Abc_NtkIsNetlist(pNtk) )
+                nFanouts = Abc_ObjFanoutNum( Abc_ObjFanout0(pNode) );
+            else
+                nFanouts = Abc_ObjFanoutNum(pNode);
+            vFanouts->pArray[nFanouts]++;
+        }
+    }
+    fprintf( pFile, "The distribution of fanins and fanouts in the network:\n" );
+    fprintf( pFile, "  Number   Nodes with fanin  Nodes with fanout\n" );
+    for ( k = 0; k < vFanins->nSize; k++ )
+    {
+        if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 )
+            continue;
+        fprintf( pFile, "%5d : ", k );
+        if ( vFanins->pArray[k] == 0 )
+            fprintf( pFile, "              " );
+        else
+            fprintf( pFile, "%12d  ", vFanins->pArray[k] );
+        fprintf( pFile, "    " );
+        if ( vFanouts->pArray[k] == 0 )
+            fprintf( pFile, "              " );
+        else
+            fprintf( pFile, "%12d  ", vFanouts->pArray[k] );
+        fprintf( pFile, "\n" );
+    }
+    Vec_IntFree( vFanins );
+    Vec_IntFree( vFanouts );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the distribution of fanins/fanouts in the network.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintFanioNew( FILE * pFile, Abc_Ntk_t * pNtk, int fMffc )
+{
+    char Buffer[100];
+    Abc_Obj_t * pNode;
+    Vec_Int_t * vFanins, * vFanouts;
+    int nFanins, nFanouts, nFaninsMax, nFanoutsMax, nFaninsAll, nFanoutsAll;
+    int i, k, nSizeMax;
+
+    // determine the largest fanin and fanout
+    nFaninsMax = nFanoutsMax = 0;
+    nFaninsAll = nFanoutsAll = 0;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        if ( fMffc && Abc_ObjFanoutNum(pNode) == 1 )
+            continue;
+        nFanins  = Abc_ObjFaninNum(pNode);
+        if ( Abc_NtkIsNetlist(pNtk) )
+            nFanouts = Abc_ObjFanoutNum( Abc_ObjFanout0(pNode) );
+        else if ( fMffc )
+            nFanouts = Abc_NodeMffcSize(pNode);
+        else
+            nFanouts = Abc_ObjFanoutNum(pNode);
+        nFaninsAll  += nFanins;
+        nFanoutsAll += nFanouts;
+        nFaninsMax   = Abc_MaxInt( nFaninsMax, nFanins );
+        nFanoutsMax  = Abc_MaxInt( nFanoutsMax, nFanouts );
+    }
+
+    // allocate storage for fanin/fanout numbers
+    nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nFaninsMax) + 1), 10 * (Abc_Base10Log(nFanoutsMax) + 1) );
+    vFanins  = Vec_IntStart( nSizeMax );
+    vFanouts = Vec_IntStart( nSizeMax );
+
+    // count the number of fanins and fanouts
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        if ( fMffc && Abc_ObjFanoutNum(pNode) == 1 )
+            continue;
+        nFanins  = Abc_ObjFaninNum(pNode);
+        if ( Abc_NtkIsNetlist(pNtk) )
+            nFanouts = Abc_ObjFanoutNum( Abc_ObjFanout0(pNode) );
+        else if ( fMffc )
+            nFanouts = Abc_NodeMffcSize(pNode);
+        else
+            nFanouts = Abc_ObjFanoutNum(pNode);
+
+        if ( nFanins < 10 )
+            Vec_IntAddToEntry( vFanins, nFanins, 1 );
+        else if ( nFanins < 100 )
+            Vec_IntAddToEntry( vFanins, 10 + nFanins/10, 1 );
+        else if ( nFanins < 1000 )
+            Vec_IntAddToEntry( vFanins, 20 + nFanins/100, 1 );
+        else if ( nFanins < 10000 )
+            Vec_IntAddToEntry( vFanins, 30 + nFanins/1000, 1 );
+        else if ( nFanins < 100000 )
+            Vec_IntAddToEntry( vFanins, 40 + nFanins/10000, 1 );
+        else if ( nFanins < 1000000 )
+            Vec_IntAddToEntry( vFanins, 50 + nFanins/100000, 1 );
+        else if ( nFanins < 10000000 )
+            Vec_IntAddToEntry( vFanins, 60 + nFanins/1000000, 1 );
+
+        if ( nFanouts < 10 )
+            Vec_IntAddToEntry( vFanouts, nFanouts, 1 );
+        else if ( nFanouts < 100 )
+            Vec_IntAddToEntry( vFanouts, 10 + nFanouts/10, 1 );
+        else if ( nFanouts < 1000 )
+            Vec_IntAddToEntry( vFanouts, 20 + nFanouts/100, 1 );
+        else if ( nFanouts < 10000 )
+            Vec_IntAddToEntry( vFanouts, 30 + nFanouts/1000, 1 );
+        else if ( nFanouts < 100000 )
+            Vec_IntAddToEntry( vFanouts, 40 + nFanouts/10000, 1 );
+        else if ( nFanouts < 1000000 )
+            Vec_IntAddToEntry( vFanouts, 50 + nFanouts/100000, 1 );
+        else if ( nFanouts < 10000000 )
+            Vec_IntAddToEntry( vFanouts, 60 + nFanouts/1000000, 1 );
+    }
+
+    fprintf( pFile, "The distribution of fanins and fanouts in the network:\n" );
+    fprintf( pFile, "         Number   Nodes with fanin  Nodes with fanout\n" );
+    for ( k = 0; k < nSizeMax; k++ )
+    {
+        if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 )
+            continue;
+        if ( k < 10 )
+            fprintf( pFile, "%15d : ", k );
+        else
+        {
+            sprintf( Buffer, "%d - %d", (int)pow((double)10, k/10) * (k%10), (int)pow((double)10, k/10) * (k%10+1) - 1 );
+            fprintf( pFile, "%15s : ", Buffer );
+        }
+        if ( vFanins->pArray[k] == 0 )
+            fprintf( pFile, "              " );
+        else
+            fprintf( pFile, "%12d  ", vFanins->pArray[k] );
+        fprintf( pFile, "    " );
+        if ( vFanouts->pArray[k] == 0 )
+            fprintf( pFile, "              " );
+        else
+            fprintf( pFile, "%12d  ", vFanouts->pArray[k] );
+        fprintf( pFile, "\n" );
+    }
+    Vec_IntFree( vFanins );
+    Vec_IntFree( vFanouts );
+
+    fprintf( pFile, "Fanins: Max = %d. Ave = %.2f.  Fanouts: Max = %d. Ave =  %.2f.\n",
+        nFaninsMax,  1.0*nFaninsAll/Abc_NtkNodeNum(pNtk),
+        nFanoutsMax, 1.0*nFanoutsAll/Abc_NtkNodeNum(pNtk)  );
+/*
+    Abc_NtkForEachCi( pNtk, pNode, i )
+    {
+        printf( "%d ", Abc_ObjFanoutNum(pNode) );
+    }
+    printf( "\n" );
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the fanins/fanouts of a node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pNode2;
+    int i;
+    if ( Abc_ObjIsPo(pNode) )
+        pNode = Abc_ObjFanin0(pNode);
+
+    fprintf( pFile, "Node %s", Abc_ObjName(pNode) );
+    fprintf( pFile, "\n" );
+
+    fprintf( pFile, "Fanins (%d): ", Abc_ObjFaninNum(pNode) );
+    Abc_ObjForEachFanin( pNode, pNode2, i )
+        fprintf( pFile, " %s", Abc_ObjName(pNode2) );
+    fprintf( pFile, "\n" );
+
+    fprintf( pFile, "Fanouts (%d): ", Abc_ObjFaninNum(pNode) );
+    Abc_ObjForEachFanout( pNode, pNode2, i )
+        fprintf( pFile, " %s", Abc_ObjName(pNode2) );
+    fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the MFFCs of the nodes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    extern void Abc_NodeMffcConeSuppPrint( Abc_Obj_t * pNode );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        if ( Abc_ObjFanoutNum(pNode) > 1 )
+            Abc_NodeMffcConeSuppPrint( pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the factored form of one node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    assert( Abc_NtkIsSopLogic(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        Abc_NodePrintFactor( pFile, pNode, fUseRealNames );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the factored form of one node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames )
+{
+    Dec_Graph_t * pGraph;
+    Vec_Ptr_t * vNamesIn;
+    if ( Abc_ObjIsCo(pNode) )
+        pNode = Abc_ObjFanin0(pNode);
+    if ( Abc_ObjIsPi(pNode) )
+    {
+        fprintf( pFile, "Skipping the PI node.\n" );
+        return;
+    }
+    if ( Abc_ObjIsLatch(pNode) )
+    {
+        fprintf( pFile, "Skipping the latch.\n" );
+        return;
+    }
+    assert( Abc_ObjIsNode(pNode) );
+    pGraph = Dec_Factor( (char *)pNode->pData );
+    if ( fUseRealNames )
+    {
+        vNamesIn = Abc_NodeGetFaninNames(pNode);
+        Dec_GraphPrint( stdout, pGraph, (char **)vNamesIn->pArray, Abc_ObjName(pNode) );
+        Abc_NodeFreeNames( vNamesIn );
+    }
+    else
+        Dec_GraphPrint( stdout, pGraph, (char **)NULL, Abc_ObjName(pNode) );
+    Dec_GraphFree( pGraph );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the level stats of the PO node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes, int fVerbose )
+{
+    Abc_Obj_t * pNode;
+    int i, k, Length;
+
+    if ( fListNodes )
+    {
+        int nLevels;
+        nLevels = Abc_NtkLevel(pNtk);
+        printf( "Nodes by level:\n" );
+        for ( i = 0; i <= nLevels; i++ )
+        {
+            printf( "%2d : ", i );
+            Abc_NtkForEachNode( pNtk, pNode, k )
+                if ( (int)pNode->Level == i )
+                    printf( " %s", Abc_ObjName(pNode) );
+            printf( "\n" );
+        }
+        return;
+    }
+
+    // print the delay profile
+    if ( fProfile && Abc_NtkHasMapping(pNtk) )
+    {
+        int nIntervals = 12;
+        float DelayMax, DelayCur, DelayDelta;
+        int * pLevelCounts;
+        int DelayInt, nOutsSum, nOutsTotal;
+
+        // get the max delay and delta
+        DelayMax   = Abc_NtkDelayTrace( pNtk, NULL, NULL, 0 );
+        DelayDelta = DelayMax/nIntervals;
+        // collect outputs by delay
+        pLevelCounts = ABC_ALLOC( int, nIntervals );
+        memset( pLevelCounts, 0, sizeof(int) * nIntervals );
+        Abc_NtkForEachCo( pNtk, pNode, i )
+        {
+            if ( Abc_ObjIsNode(Abc_ObjFanin0(pNode)) && Abc_ObjFaninNum(Abc_ObjFanin0(pNode)) == 0 )
+                DelayInt = 0;
+            else
+            {
+                DelayCur  = Abc_NodeReadArrivalWorst( Abc_ObjFanin0(pNode) );
+                DelayInt  = (int)(DelayCur / DelayDelta);
+                if ( DelayInt >= nIntervals )
+                    DelayInt = nIntervals - 1;
+            }
+            pLevelCounts[DelayInt]++;
+        }
+
+        nOutsSum   = 0;
+        nOutsTotal = Abc_NtkCoNum(pNtk);
+        for ( i = 0; i < nIntervals; i++ )
+        {
+            nOutsSum += pLevelCounts[i];
+            printf( "[%8.2f - %8.2f] :   COs = %4d.   %5.1f %%\n",
+                DelayDelta * i, DelayDelta * (i+1), pLevelCounts[i], 100.0 * nOutsSum/nOutsTotal );
+        }
+        ABC_FREE( pLevelCounts );
+        return;
+    }
+    else if ( fProfile )
+    {
+        int LevelMax, * pLevelCounts;
+        int nOutsSum, nOutsTotal;
+
+        if ( !Abc_NtkIsStrash(pNtk) )
+            Abc_NtkLevel(pNtk);
+
+        LevelMax = 0;
+        Abc_NtkForEachCo( pNtk, pNode, i )
+            if ( LevelMax < (int)Abc_ObjFanin0(pNode)->Level )
+                LevelMax = Abc_ObjFanin0(pNode)->Level;
+        pLevelCounts = ABC_ALLOC( int, LevelMax + 1 );
+        memset( pLevelCounts, 0, sizeof(int) * (LevelMax + 1) );
+        Abc_NtkForEachCo( pNtk, pNode, i )
+            pLevelCounts[Abc_ObjFanin0(pNode)->Level]++;
+
+        nOutsSum   = 0;
+        nOutsTotal = Abc_NtkCoNum(pNtk);
+        for ( i = 0; i <= LevelMax; i++ )
+            if ( pLevelCounts[i] )
+            {
+                nOutsSum += pLevelCounts[i];
+                printf( "Level = %4d.  COs = %4d.   %5.1f %%\n", i, pLevelCounts[i], 100.0 * nOutsSum/nOutsTotal );
+            }
+        ABC_FREE( pLevelCounts );
+        return;
+    }
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    if ( fVerbose )
+    {
+        // find the longest name
+        Length = 0;
+        Abc_NtkForEachCo( pNtk, pNode, i )
+            if ( Length < (int)strlen(Abc_ObjName(pNode)) )
+                Length = strlen(Abc_ObjName(pNode));
+        if ( Length < 5 )
+            Length = 5;
+        // print stats for each output
+        Abc_NtkForEachCo( pNtk, pNode, i )
+        {
+            fprintf( pFile, "CO %4d :  %*s    ", i, Length, Abc_ObjName(pNode) );
+            Abc_NodePrintLevel( pFile, pNode );
+    }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the factored form of one node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pDriver;
+    Vec_Ptr_t * vNodes;
+
+    pDriver = Abc_ObjIsCo(pNode)? Abc_ObjFanin0(pNode) : pNode;
+    if ( Abc_ObjIsPi(pDriver) )
+    {
+        fprintf( pFile, "Primary input.\n" );
+        return;
+    }
+    if ( Abc_ObjIsLatch(pDriver) )
+    {
+        fprintf( pFile, "Latch.\n" );
+        return;
+    }
+    if ( Abc_NodeIsConst(pDriver) )
+    {
+        fprintf( pFile, "Constant %d.\n", !Abc_ObjFaninC0(pNode) );
+        return;
+    }
+    // print the level
+    fprintf( pFile, "Level = %3d.  ", pDriver->Level );
+    // print the size of MFFC
+    fprintf( pFile, "Mffc = %5d.  ", Abc_NodeMffcSize(pDriver) );
+    // print the size of the shole cone
+    vNodes = Abc_NtkDfsNodes( pNode->pNtk, &pDriver, 1 );
+    fprintf( pFile, "Cone = %5d.  ", Vec_PtrSize(vNodes) );
+    Vec_PtrFree( vNodes );
+    fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the factored form of one node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodePrintKMap( Abc_Obj_t * pNode, int fUseRealNames )
+{
+    Vec_Ptr_t * vNamesIn;
+    if ( fUseRealNames )
+    {
+        vNamesIn = Abc_NodeGetFaninNames(pNode);
+        Extra_PrintKMap( stdout, (DdManager *)pNode->pNtk->pManFunc, (DdNode *)pNode->pData, Cudd_Not(pNode->pData),
+            Abc_ObjFaninNum(pNode), NULL, 0, (char **)vNamesIn->pArray );
+        Abc_NodeFreeNames( vNamesIn );
+    }
+    else
+        Extra_PrintKMap( stdout, (DdManager *)pNode->pNtk->pManFunc, (DdNode *)pNode->pData, Cudd_Not(pNode->pData),
+            Abc_ObjFaninNum(pNode), NULL, 0, NULL );
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints statistics about gates used in the network.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary )
+{
+    Abc_Obj_t * pObj;
+    int fHasBdds, i;
+    int CountConst, CountBuf, CountInv, CountAnd, CountOr, CountOther, CounterTotal;
+    char * pSop;
+
+    if ( fUseLibrary && Abc_NtkHasMapping(pNtk) )
+    {
+        Mio_Gate_t ** ppGates;
+        double Area, AreaTotal;
+        int Counter, nGates, i, nGateNameLen;
+
+        // clean value of all gates
+        nGates = Mio_LibraryReadGateNum( (Mio_Library_t *)pNtk->pManFunc );
+        ppGates = Mio_LibraryReadGateArray( (Mio_Library_t *)pNtk->pManFunc );
+        for ( i = 0; i < nGates; i++ )
+            Mio_GateSetValue( ppGates[i], 0 );
+
+        // count the gates by name
+        CounterTotal = 0;
+        Abc_NtkForEachNode( pNtk, pObj, i )
+        {
+            if ( i == 0 ) continue;
+            Mio_GateSetValue( (Mio_Gate_t *)pObj->pData, 1 + Mio_GateReadValue((Mio_Gate_t *)pObj->pData) );
+            CounterTotal++;
+            // assuming that twin gates follow each other
+            if ( Abc_NtkFetchTwinNode(pObj) )
+                i++;
+        }
+
+        // determine the longest gate name
+        nGateNameLen = 5;
+        for ( i = 0; i < nGates; i++ )
+        {
+            Counter = Mio_GateReadValue( ppGates[i] );
+            if ( Counter == 0 )
+                continue;
+            nGateNameLen = Abc_MaxInt( nGateNameLen, strlen(Mio_GateReadName(ppGates[i])) );
+        }
+
+        // print the gates
+        AreaTotal = Abc_NtkGetMappedArea(pNtk);
+        for ( i = 0; i < nGates; i++ )
+        {
+            Counter = Mio_GateReadValue( ppGates[i] );
+            if ( Counter == 0 )
+                continue;
+            Area = Counter * Mio_GateReadArea( ppGates[i] );
+            printf( "%-*s   Fanin = %2d   Instance = %8d   Area = %10.2f   %6.2f %%    %s\n",
+                nGateNameLen, Mio_GateReadName( ppGates[i] ),
+                Mio_GateReadPinNum( ppGates[i] ),
+                Counter, Area, 100.0 * Area / AreaTotal,
+                Mio_GateReadForm(ppGates[i]) );
+        }
+        printf( "%-*s                Instance = %8d   Area = %10.2f   %6.2f %%\n",
+            nGateNameLen, "TOTAL",
+            CounterTotal, AreaTotal, 100.0 );
+        return;
+    }
+
+    if ( Abc_NtkIsAigLogic(pNtk) )
+        return;
+
+    // transform logic functions from BDD to SOP
+    if ( (fHasBdds = Abc_NtkIsBddLogic(pNtk)) )
+    {
+        if ( !Abc_NtkBddToSop(pNtk, 0) )
+        {
+            printf( "Abc_NtkPrintGates(): Converting to SOPs has failed.\n" );
+            return;
+        }
+    }
+
+    // get hold of the SOP of the node
+    CountConst = CountBuf = CountInv = CountAnd = CountOr = CountOther = CounterTotal = 0;
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        if ( i == 0 ) continue;
+        if ( Abc_NtkHasMapping(pNtk) )
+            pSop = Mio_GateReadSop((Mio_Gate_t *)pObj->pData);
+        else
+            pSop = (char *)pObj->pData;
+        // collect the stats
+        if ( Abc_SopIsConst0(pSop) || Abc_SopIsConst1(pSop) )
+            CountConst++;
+        else if ( Abc_SopIsBuf(pSop) )
+            CountBuf++;
+        else if ( Abc_SopIsInv(pSop) )
+            CountInv++;
+        else if ( (!Abc_SopIsComplement(pSop) && Abc_SopIsAndType(pSop)) ||
+                  ( Abc_SopIsComplement(pSop) && Abc_SopIsOrType(pSop)) )
+            CountAnd++;
+        else if ( ( Abc_SopIsComplement(pSop) && Abc_SopIsAndType(pSop)) ||
+                  (!Abc_SopIsComplement(pSop) && Abc_SopIsOrType(pSop)) )
+            CountOr++;
+        else
+            CountOther++;
+        CounterTotal++;
+    }
+    printf( "Const        = %8d    %6.2f %%\n", CountConst  ,  100.0 * CountConst   / CounterTotal );
+    printf( "Buffer       = %8d    %6.2f %%\n", CountBuf    ,  100.0 * CountBuf     / CounterTotal );
+    printf( "Inverter     = %8d    %6.2f %%\n", CountInv    ,  100.0 * CountInv     / CounterTotal );
+    printf( "And          = %8d    %6.2f %%\n", CountAnd    ,  100.0 * CountAnd     / CounterTotal );
+    printf( "Or           = %8d    %6.2f %%\n", CountOr     ,  100.0 * CountOr      / CounterTotal );
+    printf( "Other        = %8d    %6.2f %%\n", CountOther  ,  100.0 * CountOther   / CounterTotal );
+    printf( "TOTAL        = %8d    %6.2f %%\n", CounterTotal,  100.0 * CounterTotal / CounterTotal );
+
+    // convert the network back into BDDs if this is how it was
+    if ( fHasBdds )
+        Abc_NtkSopToBdd(pNtk);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints statistics about gates used in the network.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes1, * vNodes2;
+    Abc_Obj_t * pObj1, * pObj2, * pNode1, * pNode2;
+    int i, k, m, n, Counter;
+
+    // print the template
+    printf( "Statistics about sharing of logic nodes among the CO pairs.\n" );
+    printf( "(CO1,CO2)=NumShared : " );
+    // go though the CO pairs
+    Abc_NtkForEachCo( pNtk, pObj1, i )
+    {
+        vNodes1 = Abc_NtkDfsNodes( pNtk, &pObj1, 1 );
+        // mark the nodes
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes1, pNode1, m )
+            pNode1->fMarkA = 1;
+        // go through the second COs
+        Abc_NtkForEachCo( pNtk, pObj2, k )
+        {
+            if ( i >= k )
+                continue;
+            vNodes2 = Abc_NtkDfsNodes( pNtk, &pObj2, 1 );
+            // count the number of marked
+            Counter = 0;
+            Vec_PtrForEachEntry( Abc_Obj_t *, vNodes2, pNode2, n )
+                Counter += pNode2->fMarkA;
+            // print
+            printf( "(%d,%d)=%d ", i, k, Counter );
+            Vec_PtrFree( vNodes2 );
+        }
+        // unmark the nodes
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes1, pNode1, m )
+            pNode1->fMarkA = 0;
+        Vec_PtrFree( vNodes1 );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints info for each output cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCountPis( Vec_Ptr_t * vSupp )
+{
+    Abc_Obj_t * pObj;
+    int i, Counter = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i )
+        Counter += Abc_ObjIsPi(pObj);
+    return Counter;
+}
+void Abc_NtkPrintStrSupports( Abc_Ntk_t * pNtk, int fMatrix )
+{
+    Vec_Ptr_t * vSupp, * vNodes;
+    Abc_Obj_t * pObj;
+    int i, k, nPis;
+    printf( "Structural support info:\n" );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        vSupp  = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
+        vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 );
+        nPis   = Abc_NtkCountPis( vSupp );
+        printf( "%5d  %20s :  Cone = %5d.  Supp = %5d. (PIs = %5d. FFs = %5d.)\n",
+            i, Abc_ObjName(pObj), vNodes->nSize, vSupp->nSize, nPis, vSupp->nSize - nPis );
+        Vec_PtrFree( vNodes );
+        Vec_PtrFree( vSupp );
+    }
+    if ( !fMatrix )
+        return;
+
+    Abc_NtkForEachCi( pNtk, pObj, k )
+        pObj->fMarkA = 0;
+
+    printf( "Actual support info:\n" );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        vSupp  = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, k )
+            pObj->fMarkA = 1;
+        Vec_PtrFree( vSupp );
+
+        Abc_NtkForEachCi( pNtk, pObj, k )
+            printf( "%d", pObj->fMarkA );
+        printf( "\n" );
+
+        Abc_NtkForEachCi( pNtk, pObj, k )
+            pObj->fMarkA = 0;
+    }
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints information about the object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    fprintf( pFile, "Object %5d : ", pObj->Id );
+    switch ( pObj->Type )
+    {
+        case ABC_OBJ_NONE:
+            fprintf( pFile, "NONE   " );
+            break;
+        case ABC_OBJ_CONST1:
+            fprintf( pFile, "Const1 " );
+            break;
+        case ABC_OBJ_PI:
+            fprintf( pFile, "PI     " );
+            break;
+        case ABC_OBJ_PO:
+            fprintf( pFile, "PO     " );
+            break;
+        case ABC_OBJ_BI:
+            fprintf( pFile, "BI     " );
+            break;
+        case ABC_OBJ_BO:
+            fprintf( pFile, "BO     " );
+            break;
+        case ABC_OBJ_NET:
+            fprintf( pFile, "Net    " );
+            break;
+        case ABC_OBJ_NODE:
+            fprintf( pFile, "Node   " );
+            break;
+        case ABC_OBJ_LATCH:
+            fprintf( pFile, "Latch  " );
+            break;
+        case ABC_OBJ_WHITEBOX:
+            fprintf( pFile, "Whitebox" );
+            break;
+        case ABC_OBJ_BLACKBOX:
+            fprintf( pFile, "Blackbox" );
+            break;
+        default:
+            assert(0);
+            break;
+    }
+    // print the fanins
+    fprintf( pFile, " Fanins ( " );
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        fprintf( pFile, "%d ", pFanin->Id );
+    fprintf( pFile, ") " );
+/*
+    fprintf( pFile, " Fanouts ( " );
+    Abc_ObjForEachFanout( pObj, pFanin, i )
+        fprintf( pFile, "%d(%c) ", pFanin->Id, Abc_NodeIsTravIdCurrent(pFanin)? '+' : '-' );
+    fprintf( pFile, ") " );
+*/
+    // print the logic function
+    if ( Abc_ObjIsNode(pObj) && Abc_NtkIsSopLogic(pObj->pNtk) )
+        fprintf( pFile, " %s", (char*)pObj->pData );
+    else
+        fprintf( pFile, "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the status of the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintMiter( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj, * pChild, * pConst1 = Abc_AigConst1(pNtk);
+    int i, iOut = -1;
+    abctime Time = Abc_Clock();
+    int nUnsat = 0;
+    int nSat   = 0;
+    int nUndec = 0;
+    int nPis   = 0;
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        nPis += (int)( Abc_ObjFanoutNum(pObj) > 0 );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+    {
+        pChild = Abc_ObjChild0(pObj);
+        // check if the output is constant 0
+        if ( pChild == Abc_ObjNot(pConst1) )
+            nUnsat++;
+        // check if the output is constant 1
+        else if ( pChild == pConst1 )
+        {
+            nSat++;
+            if ( iOut == -1 )
+                iOut = i;
+        }
+        // check if the output is a primary input
+        else if ( Abc_ObjIsPi(Abc_ObjRegular(pChild)) )
+        {
+            nSat++;
+            if ( iOut == -1 )
+                iOut = i;
+        }
+    // check if the output is 1 for the 0000 pattern
+        else if ( Abc_ObjRegular(pChild)->fPhase != (unsigned)Abc_ObjIsComplement(pChild) )
+        {
+            nSat++;
+            if ( iOut == -1 )
+                iOut = i;
+        }
+        else
+            nUndec++;
+    }
+    printf( "Miter:  I =%6d", nPis );
+    printf( "  N =%7d", Abc_NtkNodeNum(pNtk) );
+    printf( "  ? =%7d", nUndec );
+    printf( "  U =%6d", nUnsat );
+    printf( "  S =%6d", nSat );
+    Time = Abc_Clock() - Time;
+    printf(" %7.2f sec\n", (float)(Time)/(float)(CLOCKS_PER_SEC));
+    if ( iOut >= 0 )
+        printf( "The first satisfiable output is number %d (%s).\n", iOut, Abc_ObjName( Abc_NtkPo(pNtk, iOut) ) );
+}
+
+
+
+
+typedef struct Gli_Man_t_ Gli_Man_t;
+
+extern Gli_Man_t * Gli_ManAlloc( int nObjs, int nRegs, int nFanioPairs );
+extern void        Gli_ManStop( Gli_Man_t * p );
+extern int         Gli_ManCreateCi( Gli_Man_t * p, int nFanouts );
+extern int         Gli_ManCreateCo( Gli_Man_t * p, int iFanin );
+extern int         Gli_ManCreateNode( Gli_Man_t * p, Vec_Int_t * vFanins, int nFanouts, unsigned * puTruth );
+
+extern void        Gli_ManSwitchesAndGlitches( Gli_Man_t * p, int nPatterns, float PiTransProb, int fVerbose );
+extern int         Gli_ObjNumSwitches( Gli_Man_t * p, int iNode );
+extern int         Gli_ObjNumGlitches( Gli_Man_t * p, int iNode );
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the percentable of increased power due to glitching.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Abc_NtkMfsTotalGlitching( Abc_Ntk_t * pNtk )
+{
+    int nSwitches, nGlitches;
+    Gli_Man_t * p;
+    Vec_Ptr_t * vNodes;
+    Vec_Int_t * vFanins, * vTruth;
+    Abc_Obj_t * pObj, * pFanin;
+    unsigned * puTruth;
+    int i, k;
+    assert( Abc_NtkIsLogic(pNtk) );
+    assert( Abc_NtkGetFaninMax(pNtk) <= 6 );
+    if ( Abc_NtkGetFaninMax(pNtk) > 6 )
+    {
+        printf( "Abc_NtkMfsTotalGlitching() This procedure works only for mapped networks with LUTs size up to 6 inputs.\n" );
+        return -1.0;
+    }
+    Abc_NtkToAig( pNtk );
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    vFanins = Vec_IntAlloc( 6 );
+    vTruth = Vec_IntAlloc( 1 << 12 );
+
+    // derive network for glitch computation
+    p = Gli_ManAlloc( Vec_PtrSize(vNodes) + Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk),
+        Abc_NtkLatchNum(pNtk), Abc_NtkGetTotalFanins(pNtk) + Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->iTemp = -1;
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->iTemp = Gli_ManCreateCi( p, Abc_ObjFanoutNum(pObj) );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        Vec_IntClear( vFanins );
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Vec_IntPush( vFanins, pFanin->iTemp );
+        puTruth = Hop_ManConvertAigToTruth( (Hop_Man_t *)pNtk->pManFunc, (Hop_Obj_t *)pObj->pData, Abc_ObjFaninNum(pObj), vTruth, 0 );
+        pObj->iTemp = Gli_ManCreateNode( p, vFanins, Abc_ObjFanoutNum(pObj), puTruth );
+    }
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Gli_ManCreateCo( p, Abc_ObjFanin0(pObj)->iTemp );
+
+    // compute glitching
+    Gli_ManSwitchesAndGlitches( p, 4000, 1.0/8.0, 0 );
+
+    // compute the ratio
+    nSwitches = nGlitches = 0;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( pObj->iTemp >= 0 )
+        {
+            nSwitches += Abc_ObjFanoutNum(pObj) * Gli_ObjNumSwitches(p, pObj->iTemp);
+            nGlitches += Abc_ObjFanoutNum(pObj) * Gli_ObjNumGlitches(p, pObj->iTemp);
+        }
+
+    Gli_ManStop( p );
+    Vec_PtrFree( vNodes );
+    Vec_IntFree( vTruth );
+    Vec_IntFree( vFanins );
+    return nSwitches ? 100.0*(nGlitches-nSwitches)/nSwitches : 0.0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints K-map of 6-var function represented by truth table.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_Show6VarFunc( word F0, word F1 )
+{
+    // order of cells in the Karnaugh map
+//    int Cells[8] = { 0, 1, 3, 2, 6, 7, 5, 4 };
+    int Cells[8] = { 0, 4, 6, 2, 3, 7, 5, 1 };
+    // intermediate variables
+    int s; // symbol counter
+    int h; // horizontal coordinate;
+    int v; // vertical coordinate;
+    assert( (F0 & F1) == 0 );
+
+    // output minterms above
+    for ( s = 0; s < 4; s++ )
+        printf( " " );
+    printf( " " );
+    for ( h = 0; h < 8; h++ )
+    {
+        for ( s = 0; s < 3; s++ )
+            printf( "%d",  ((Cells[h] >> (2-s)) & 1) );
+        printf( " " );
+    }
+    printf( "\n" );
+
+    // output horizontal line above
+    for ( s = 0; s < 4; s++ )
+        printf( " " );
+    printf( "+" );
+    for ( h = 0; h < 8; h++ )
+    {
+        for ( s = 0; s < 3; s++ )
+            printf( "-" );
+        printf( "+" );
+    }
+    printf( "\n" );
+
+    // output lines with function values
+    for ( v = 0; v < 8; v++ )
+    {
+        for ( s = 0; s < 3; s++ )
+            printf( "%d",  ((Cells[v] >> (2-s)) & 1) );
+        printf( " |" );
+
+        for ( h = 0; h < 8; h++ )
+        {
+            printf( " " );
+            if ( ((F0 >> ((Cells[v]*8)+Cells[h])) & 1) )
+                printf( "0" );
+            else if ( ((F1 >> ((Cells[v]*8)+Cells[h])) & 1) )
+                printf( "1" );
+            else
+                printf( " " );
+            printf( " |" );
+        }
+        printf( "\n" );
+
+        // output horizontal line above
+        for ( s = 0; s < 4; s++ )
+            printf( " " );
+//        printf( "%c", v == 7 ? '+' : '|' );
+        printf( "+" );
+        for ( h = 0; h < 8; h++ )
+        {
+            for ( s = 0; s < 3; s++ )
+                printf( "-" );
+//            printf( "%c", v == 7 ? '+' : '|' );
+            printf( "%c", (v == 7 || h == 7) ? '+' : '|' );
+        }
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints K-map of 6-var function represented by truth table.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkShow6VarFunc( char * pF0, char * pF1 )
+{
+    word F0, F1;
+    if ( strlen(pF0) != 16 )
+    {
+        printf( "Wrong length (%d) of 6-var truth table.\n", (int)strlen(pF0) );
+        return;
+    }
+    if ( strlen(pF1) != 16 )
+    {
+        printf( "Wrong length (%d) of 6-var truth table.\n", (int)strlen(pF1) );
+        return;
+    }
+    Extra_ReadHexadecimal( (unsigned *)&F0, pF0, 6 );
+    Extra_ReadHexadecimal( (unsigned *)&F1, pF1, 6 );
+    Abc_Show6VarFunc( F0, F1 );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/base/abci/abcProve.c b/abc-build/src/base/abci/abcProve.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcProve.c
@@ -0,0 +1,349 @@
+/**CFile****************************************************************
+
+  FileName    [abcProve.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Proves the miter using AIG rewriting, FRAIGing, and SAT solving.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcProve.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <math.h>
+
+#include "base/abc/abc.h"
+#include "proof/fraig/fraig.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern int  Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose );
+extern Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
+
+static Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, ABC_INT64_T nInspLimit, int * pRetValue, int * pNumFails, ABC_INT64_T * pNumConfs, ABC_INT64_T * pNumInspects );
+static void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, abctime clk, int fVerbose );
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+  
+/**Function*************************************************************
+
+  Synopsis    [Attempts to solve the miter using a number of tricks.]
+
+  Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT. Returns
+  a simplified version of the original network (or a constant 0 network).
+  In case the network is not a constant zero and a SAT assignment is found,
+  pNtk->pModel contains a satisfying assignment.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pPars )
+{
+    Prove_Params_t * pParams = (Prove_Params_t *)pPars;
+    Abc_Ntk_t * pNtk, * pNtkTemp;
+    int RetValue = -1, nIter, nSatFails, Counter;
+    abctime clk; //, timeStart = Abc_Clock();
+    ABC_INT64_T nSatConfs, nSatInspects, nInspectLimit;
+
+    // get the starting network
+    pNtk = *ppNtk;
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( Abc_NtkPoNum(pNtk) == 1 );
+ 
+    if ( pParams->fVerbose )
+    {
+        printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n",
+            pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" );
+        printf( "Miter = %d (%3.1f).  Rwr = %d (%3.1f).  Fraig = %d (%3.1f).  Last = %d.\n", 
+            pParams->nMiteringLimitStart,  pParams->nMiteringLimitMulti, 
+            pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti,
+            pParams->nFraigingLimitStart,  pParams->nFraigingLimitMulti, pParams->nMiteringLimitLast );
+    }
+
+    // if SAT only, solve without iteration
+    if ( !pParams->fUseRewriting && !pParams->fUseFraiging )
+    {
+        clk = Abc_Clock();
+        RetValue = Abc_NtkMiterSat( pNtk, (ABC_INT64_T)pParams->nMiteringLimitLast, (ABC_INT64_T)0, 0, NULL, NULL );
+        Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose );
+        *ppNtk = pNtk;
+        return RetValue;
+    }
+
+    // check the current resource limits
+    for ( nIter = 0; nIter < pParams->nItersMax; nIter++ )
+    {
+        if ( pParams->fVerbose )
+        {
+            printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1, 
+                 (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), 
+                 (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) );
+            fflush( stdout );
+        }
+
+        // try brute-force SAT
+        clk = Abc_Clock();
+        nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0;
+        RetValue = Abc_NtkMiterSat( pNtk, (ABC_INT64_T)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), (ABC_INT64_T)nInspectLimit, 0, &nSatConfs, &nSatInspects );
+        Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose );
+        if ( RetValue >= 0 )
+            break;
+
+        // add to the number of backtracks and inspects
+        pParams->nTotalBacktracksMade += nSatConfs;
+        pParams->nTotalInspectsMade   += nSatInspects;
+        // check if global resource limit is reached
+        if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) ||
+             (pParams->nTotalInspectLimit   && pParams->nTotalInspectsMade   >= pParams->nTotalInspectLimit) )
+        {
+            printf( "Reached global limit on conflicts/inspects. Quitting.\n" );
+            *ppNtk = pNtk;
+            return -1;
+        }
+
+        // try rewriting
+        if ( pParams->fUseRewriting )
+        {
+            clk = Abc_Clock();
+            Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter));
+//            Counter = 1;
+            while ( 1 )
+            {
+/*
+                extern Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose );
+                pNtk = Abc_NtkIvyResyn( pNtkTemp = pNtk, 0, 0 );  Abc_NtkDelete( pNtkTemp );
+                if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+                    break;
+                if ( --Counter == 0 )
+                    break;
+*/
+/*
+                Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+                if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+                    break;
+                if ( --Counter == 0 )
+                    break;
+*/
+                Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+                if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+                    break;
+                if ( --Counter == 0 )
+                    break;
+                Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 );
+                if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+                    break;
+                if ( --Counter == 0 )
+                    break;
+                pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 );  Abc_NtkDelete( pNtkTemp );
+                if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+                    break;
+                if ( --Counter == 0 )
+                    break;
+            }
+            Abc_NtkMiterPrint( pNtk, "Rewriting  ", clk, pParams->fVerbose );
+        }
+ 
+        if ( pParams->fUseFraiging )
+        {
+            // try FRAIGing
+            clk = Abc_Clock();
+            nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0;
+            pNtk = Abc_NtkMiterFraig( pNtkTemp = pNtk, (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)), nInspectLimit, &RetValue, &nSatFails, &nSatConfs, &nSatInspects );  Abc_NtkDelete( pNtkTemp );
+            Abc_NtkMiterPrint( pNtk, "FRAIGing   ", clk, pParams->fVerbose );
+//            printf( "NumFails = %d\n", nSatFails );
+            if ( RetValue >= 0 )
+                break;
+
+            // add to the number of backtracks and inspects
+            pParams->nTotalBacktracksMade += nSatConfs;
+            pParams->nTotalInspectsMade += nSatInspects;
+            // check if global resource limit is reached
+            if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) ||
+                 (pParams->nTotalInspectLimit   && pParams->nTotalInspectsMade   >= pParams->nTotalInspectLimit) )
+            {
+                printf( "Reached global limit on conflicts/inspects. Quitting.\n" );
+                *ppNtk = pNtk;
+                return -1;
+            }
+        }
+
+    }    
+
+    // try to prove it using brute force SAT
+    if ( RetValue < 0 && pParams->fUseBdds )
+    {
+        if ( pParams->fVerbose )
+        {
+            printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit );
+            fflush( stdout );
+        }
+        clk = Abc_Clock();
+        pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 );
+        if ( pNtk )   
+        {
+            Abc_NtkDelete( pNtkTemp );
+            RetValue = ( (Abc_NtkNodeNum(pNtk) == 1) && (Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pData == Cudd_ReadLogicZero((DdManager *)pNtk->pManFunc)) );
+        }
+        else 
+            pNtk = pNtkTemp;
+        Abc_NtkMiterPrint( pNtk, "BDD building", clk, pParams->fVerbose );
+    }
+
+    if ( RetValue < 0 )
+    {
+        if ( pParams->fVerbose )
+        {
+            printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast );
+            fflush( stdout );
+        }
+        clk = Abc_Clock();
+        nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0;
+        RetValue = Abc_NtkMiterSat( pNtk, (ABC_INT64_T)pParams->nMiteringLimitLast, (ABC_INT64_T)nInspectLimit, 0, NULL, NULL );
+        Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose );
+    }
+
+    // assign the model if it was proved by rewriting (const 1 miter)
+    if ( RetValue == 0 && pNtk->pModel == NULL )
+    {
+        pNtk->pModel = ABC_ALLOC( int, Abc_NtkCiNum(pNtk) );
+        memset( pNtk->pModel, 0, sizeof(int) * Abc_NtkCiNum(pNtk) );
+    }
+    *ppNtk = pNtk;
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Attempts to solve the miter using a number of tricks.]
+
+  Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, ABC_INT64_T nInspLimit, int * pRetValue, int * pNumFails, ABC_INT64_T * pNumConfs, ABC_INT64_T * pNumInspects )
+{
+    Abc_Ntk_t * pNtkNew;
+    Fraig_Params_t Params, * pParams = &Params;
+    Fraig_Man_t * pMan;
+    int nWords1, nWords2, nWordsMin, RetValue;
+    int * pModel;
+
+    // to determine the number of simulation patterns
+    // use the following strategy
+    // at least 64 words (32 words random and 32 words dynamic)
+    // no more than 256M for one circuit (128M + 128M)
+    nWords1 = 32;
+    nWords2 = (1<<27) / (Abc_NtkNodeNum(pNtk) + Abc_NtkCiNum(pNtk));
+    nWordsMin = Abc_MinInt( nWords1, nWords2 );
+
+    // set the FRAIGing parameters
+    Fraig_ParamsSetDefault( pParams );
+    pParams->nPatsRand  = nWordsMin * 32; // the number of words of random simulation info
+    pParams->nPatsDyna  = nWordsMin * 32; // the number of words of dynamic simulation info
+    pParams->nBTLimit   = nBTLimit;       // the max number of backtracks
+    pParams->nSeconds   = -1;             // the runtime limit
+    pParams->fTryProve  = 0;              // do not try to prove the final miter
+    pParams->fDoSparse  = 1;              // try proving sparse functions
+    pParams->fVerbose   = 0;
+    pParams->nInspLimit = nInspLimit;
+
+    // transform the target into a fraig
+    pMan = (Fraig_Man_t *)Abc_NtkToFraig( pNtk, pParams, 0, 0 ); 
+    Fraig_ManProveMiter( pMan );
+    RetValue = Fraig_ManCheckMiter( pMan );
+
+    // create the network 
+    pNtkNew = Abc_NtkFromFraig( pMan, pNtk );
+
+    // save model
+    if ( RetValue == 0 )
+    {
+        pModel = Fraig_ManReadModel( pMan );
+        ABC_FREE( pNtkNew->pModel );
+        pNtkNew->pModel = ABC_ALLOC( int, Abc_NtkCiNum(pNtkNew) );
+        memcpy( pNtkNew->pModel, pModel, sizeof(int) * Abc_NtkCiNum(pNtkNew) );
+    }
+
+    // save the return values
+    *pRetValue = RetValue;
+    *pNumFails = Fraig_ManReadSatFails( pMan );
+    *pNumConfs = Fraig_ManReadConflicts( pMan );
+    *pNumInspects = Fraig_ManReadInspects( pMan );
+
+    // delete the fraig manager
+    Fraig_ManFree( pMan );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Attempts to solve the miter using a number of tricks.]
+
+  Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, abctime clk, int fVerbose )
+{
+    if ( !fVerbose )
+        return;
+    printf( "Nodes = %7d.  Levels = %4d.  ", Abc_NtkNodeNum(pNtk), 
+        Abc_NtkIsStrash(pNtk)? Abc_AigLevel(pNtk) : Abc_NtkLevel(pNtk) );
+    ABC_PRT( pString, Abc_Clock() - clk );
+}
+
+  
+/**Function*************************************************************
+
+  Synopsis    [Implements resynthesis for CEC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterRwsat( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkTemp;
+    Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+    pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 );  Abc_NtkDelete( pNtkTemp );
+    Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+    Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 );
+    return pNtk;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcQbf.c b/abc-build/src/base/abci/abcQbf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcQbf.c
@@ -0,0 +1,318 @@
+/**CFile****************************************************************
+
+  FileName    [abcQbf.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Implementation of a simple QBF solver.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcQbf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "sat/cnf/cnf.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+   Implementation of a simple QBF solver along the lines of
+   A. Solar-Lezama, L. Tancau, R. Bodik, V. Saraswat, and S. Seshia, 
+   "Combinatorial sketching for finite programs", 12th International 
+   Conference on Architectural Support for Programming Languages and 
+   Operating Systems (ASPLOS 2006), San Jose, CA, October 2006.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkModelToVector( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues );
+static void Abc_NtkVectorClearPars( Vec_Int_t * vPiValues, int nPars );
+static void Abc_NtkVectorClearVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars );
+static void Abc_NtkVectorPrintPars( Vec_Int_t * vPiValues, int nPars );
+static void Abc_NtkVectorPrintVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars );
+
+extern int Abc_NtkDSat( Abc_Ntk_t * pNtk, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fAlignPol, int fAndOuts, int fNewSolver, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Solve the QBF problem EpAx[M(p,x)].]
+
+  Description [Variables p go first, followed by variable x.
+  The number of parameters is nPars. The miter is in pNtk.
+  The miter expresses EQUALITY of the implementation and spec.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkQbf( Abc_Ntk_t * pNtk, int nPars, int nItersMax, int fDumpCnf, int fVerbose )
+{
+    Abc_Ntk_t * pNtkVer, * pNtkSyn, * pNtkSyn2, * pNtkTemp;
+    Vec_Int_t * vPiValues;
+    abctime clkTotal = Abc_Clock(), clkS, clkV;
+    int nIters, nInputs, RetValue, fFound = 0;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( Abc_NtkIsComb(pNtk) );
+    assert( Abc_NtkPoNum(pNtk) == 1 );
+    assert( nPars > 0 && nPars < Abc_NtkPiNum(pNtk) );
+//    assert( Abc_NtkPiNum(pNtk)-nPars < 32 );
+    nInputs = Abc_NtkPiNum(pNtk) - nPars;
+
+    if ( fDumpCnf )
+    {
+        // original problem: \exists p \forall x \exists y.  M(p,x,y)
+        // negated problem:  \forall p \exists x \exists y. !M(p,x,y)
+        extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+        Aig_Man_t * pMan = Abc_NtkToDar( pNtk, 0, 0 );
+        Cnf_Dat_t * pCnf = Cnf_Derive( pMan, 0 );
+        Vec_Int_t * vVarMap, * vForAlls, * vExists;
+        Aig_Obj_t * pObj;
+        char * pFileName;
+        int i, Entry;
+        // create var map
+        vVarMap = Vec_IntStart( pCnf->nVars );
+        Aig_ManForEachCi( pMan, pObj, i )
+            if ( i < nPars )
+                Vec_IntWriteEntry( vVarMap, pCnf->pVarNums[Aig_ObjId(pObj)], 1 );
+        // create various maps
+        vForAlls = Vec_IntAlloc( nPars );
+        vExists = Vec_IntAlloc( Abc_NtkPiNum(pNtk) - nPars );
+        Vec_IntForEachEntry( vVarMap, Entry, i )
+            if ( Entry )
+                Vec_IntPush( vForAlls, i );
+            else
+                Vec_IntPush( vExists, i );
+        // generate CNF
+        pFileName = Extra_FileNameGenericAppend( pNtk->pSpec, ".qdimacs" );
+        Cnf_DataWriteIntoFile( pCnf, pFileName, 0, vForAlls, vExists );
+        Aig_ManStop( pMan );
+        Cnf_DataFree( pCnf );
+        Vec_IntFree( vForAlls );
+        Vec_IntFree( vExists );
+        Vec_IntFree( vVarMap );
+        printf( "The 2QBF formula was written into file \"%s\".\n", pFileName );
+        return;
+    }
+
+    // initialize the synthesized network with 0000-combination
+    vPiValues = Vec_IntStart( Abc_NtkPiNum(pNtk) );
+
+    // create random init value
+    {
+    int i;
+    srand( time(NULL) );
+    for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ )
+        Vec_IntWriteEntry( vPiValues, i, rand() & 1 );
+    }
+
+    Abc_NtkVectorClearPars( vPiValues, nPars );
+    pNtkSyn = Abc_NtkMiterCofactor( pNtk, vPiValues );
+    if ( fVerbose )
+    {
+        printf( "Iter %2d : ", 0 );
+        printf( "AIG = %6d  ", Abc_NtkNodeNum(pNtkSyn) );
+        Abc_NtkVectorPrintVars( pNtk, vPiValues, nPars );
+        printf( "\n" );
+    }
+
+    // iteratively solve
+    for ( nIters = 0; nIters < nItersMax; nIters++ )
+    {
+        // solve the synthesis instance
+clkS = Abc_Clock();
+//        RetValue = Abc_NtkMiterSat( pNtkSyn, 0, 0, 0, NULL, NULL );
+        RetValue = Abc_NtkDSat( pNtkSyn, (ABC_INT64_T)0, (ABC_INT64_T)0, 0, 0, 0, 1, 0, 0, 0 );
+clkS = Abc_Clock() - clkS;
+        if ( RetValue == 0 )
+            Abc_NtkModelToVector( pNtkSyn, vPiValues );
+        if ( RetValue == 1 )
+        {
+            break;
+        }
+        if ( RetValue == -1 )
+        {
+            printf( "Synthesis timed out.\n" );
+            break;
+        }
+        // there is a counter-example
+
+        // construct the verification instance
+        Abc_NtkVectorClearVars( pNtk, vPiValues, nPars );
+        pNtkVer = Abc_NtkMiterCofactor( pNtk, vPiValues );
+        // complement the output
+        Abc_ObjXorFaninC( Abc_NtkPo(pNtkVer,0), 0 );
+
+        // solve the verification instance
+clkV = Abc_Clock();
+        RetValue = Abc_NtkMiterSat( pNtkVer, 0, 0, 0, NULL, NULL );
+clkV = Abc_Clock() - clkV;
+        if ( RetValue == 0 )
+            Abc_NtkModelToVector( pNtkVer, vPiValues );
+        Abc_NtkDelete( pNtkVer );
+        if ( RetValue == 1 )
+        {
+            fFound = 1;
+            break;
+        }
+        if ( RetValue == -1 )
+        {
+            printf( "Verification timed out.\n" );
+            break;
+        }
+        // there is a counter-example
+
+        // create a new synthesis network
+        Abc_NtkVectorClearPars( vPiValues, nPars );
+        pNtkSyn2 = Abc_NtkMiterCofactor( pNtk, vPiValues );
+        // add to the synthesis instance
+        pNtkSyn = Abc_NtkMiterAnd( pNtkTemp = pNtkSyn, pNtkSyn2, 0, 0 );
+        Abc_NtkDelete( pNtkSyn2 );
+        Abc_NtkDelete( pNtkTemp );
+
+        if ( fVerbose )
+        {
+            printf( "Iter %2d : ", nIters+1 );
+            printf( "AIG = %6d  ", Abc_NtkNodeNum(pNtkSyn) );
+            Abc_NtkVectorPrintVars( pNtk, vPiValues, nPars );
+            printf( "  " );
+            ABC_PRT( "Syn", clkS );
+//            ABC_PRT( "Ver", clkV );
+        }
+        if ( nIters+1 == nItersMax )
+            break;
+    }
+    Abc_NtkDelete( pNtkSyn );
+    // report the results
+    if ( fFound )
+    {
+        printf( "Parameters: " );
+        Abc_NtkVectorPrintPars( vPiValues, nPars );
+        printf( "\n" );
+        printf( "Solved after %d interations.  ", nIters );
+    }
+    else if ( nIters == nItersMax )
+        printf( "Unsolved after %d interations.  ", nIters );
+    else if ( nIters == nItersMax )
+        printf( "Quit after %d interatios.  ", nItersMax );
+    else
+        printf( "Implementation does not exist.  " );
+    ABC_PRT( "Total runtime", Abc_Clock() - clkTotal );
+    Vec_IntFree( vPiValues );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Translates model into the vector of values.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkModelToVector( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues )
+{
+    int * pModel, i;
+    pModel = pNtk->pModel;
+    for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ )
+        Vec_IntWriteEntry( vPiValues, i, pModel[i] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Clears parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkVectorClearPars( Vec_Int_t * vPiValues, int nPars )
+{
+    int i;
+    for ( i = 0; i < nPars; i++ )
+        Vec_IntWriteEntry( vPiValues, i, -1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Clears variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkVectorClearVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars )
+{
+    int i;
+    for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ )
+        Vec_IntWriteEntry( vPiValues, i, -1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Clears variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkVectorPrintPars( Vec_Int_t * vPiValues, int nPars )
+{
+    int i;
+    for ( i = 0; i < nPars; i++ )
+        printf( "%d", Vec_IntEntry(vPiValues,i) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Clears variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkVectorPrintVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars )
+{
+    int i;
+    for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ )
+        printf( "%d", Vec_IntEntry(vPiValues,i) );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcQuant.c b/abc-build/src/base/abci/abcQuant.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcQuant.c
@@ -0,0 +1,436 @@
+/**CFile****************************************************************
+
+  FileName    [abcQuant.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [AIG-based variable quantification.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcQuant.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fast synthesis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSynthesize( Abc_Ntk_t ** ppNtk, int fMoreEffort )
+{
+    extern Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose );
+
+    Abc_Ntk_t * pNtk, * pNtkTemp;
+
+    pNtk = *ppNtk;
+
+    Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+    Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 );
+    pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 );          
+    Abc_NtkDelete( pNtkTemp );
+
+    if ( fMoreEffort )
+    {
+        Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+        Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 );
+        pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 );          
+        Abc_NtkDelete( pNtkTemp );
+
+        pNtk = Abc_NtkIvyFraig( pNtkTemp = pNtk, 100, 1, 0, 0, 0 );
+        Abc_NtkDelete( pNtkTemp );
+    }
+
+    *ppNtk = pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Existentially quantifies one variable.]
+
+  Description []
+               
+  SideEffects [This procedure creates dangling nodes in the AIG.]
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkQuantify( Abc_Ntk_t * pNtk, int fUniv, int iVar, int fVerbose )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj, * pNext, * pFanin;
+    int i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( iVar < Abc_NtkCiNum(pNtk) );
+
+    // collect the internal nodes
+    pObj = Abc_NtkCi( pNtk, iVar );
+    vNodes = Abc_NtkDfsReverseNodes( pNtk, &pObj, 1 );
+
+    // assign the cofactors of the CI node to be constants
+    pObj->pCopy = Abc_ObjNot( Abc_AigConst1(pNtk) ); 
+    pObj->pData = Abc_AigConst1(pNtk); 
+
+    // quantify the nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        for ( pNext = pObj? pObj->pCopy : pObj; pObj; pObj = pNext, pNext = pObj? pObj->pCopy : pObj )
+        {
+            pFanin = Abc_ObjFanin0(pObj);
+            if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+            {
+                pFanin->pCopy = pFanin;
+                pFanin->pData = pFanin;
+            }
+            pFanin = Abc_ObjFanin1(pObj);
+            if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+            {
+                pFanin->pCopy = pFanin;
+                pFanin->pData = pFanin;
+            }
+            pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+            pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, Abc_ObjChild0Data(pObj), Abc_ObjChild1Data(pObj) );
+        }
+    }
+    Vec_PtrFree( vNodes );
+
+    // update the affected COs
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        if ( !Abc_NodeIsTravIdCurrent(pObj) )
+            continue;
+        pFanin = Abc_ObjFanin0(pObj);
+        // get the result of quantification
+        if ( fUniv )
+            pNext = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Data(pObj) );
+        else
+            pNext = Abc_AigOr( (Abc_Aig_t *)pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Data(pObj) );
+        pNext = Abc_ObjNotCond( pNext, Abc_ObjFaninC0(pObj) );
+        if ( Abc_ObjRegular(pNext) == pFanin )
+            continue;
+        // update the fanins of the CO
+        Abc_ObjPatchFanin( pObj, pFanin, pNext );
+//        if ( Abc_ObjFanoutNum(pFanin) == 0 )
+//            Abc_AigDeleteNode( pNtk->pManFunc, pFanin );
+    }
+
+    // make sure the node has no fanouts
+//    pObj = Abc_NtkCi( pNtk, iVar );
+//    assert( Abc_ObjFanoutNum(pObj) == 0 );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs the transition relation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkTransRel( Abc_Ntk_t * pNtk, int fInputs, int fVerbose )
+{
+    char Buffer[1000];
+    Vec_Ptr_t * vPairs;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObj, * pMiter;
+    int i, nLatches;
+    int fSynthesis = 1;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( Abc_NtkLatchNum(pNtk) );
+    nLatches = Abc_NtkLatchNum(pNtk);
+    // start the network
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    // duplicate the name and the spec
+    sprintf( Buffer, "%s_TR", pNtk->pName );
+    pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+//    pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+    Abc_NtkCleanCopy( pNtk );
+    // create current state variables
+    Abc_NtkForEachLatchOutput( pNtk, pObj, i )
+    {
+        pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+        Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+    }
+    // create next state variables
+    Abc_NtkForEachLatchInput( pNtk, pObj, i )
+        Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pObj), NULL );
+    // create PI variables
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        Abc_NtkDupObj( pNtkNew, pObj, 1 );
+    // create the PO
+    Abc_NtkCreatePo( pNtkNew );
+    // restrash the nodes (assuming a topological order of the old network)
+    Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+    // create the function of the primary output
+    assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) );
+    vPairs = Vec_PtrAlloc( 2*nLatches );
+    Abc_NtkForEachLatchInput( pNtk, pObj, i )
+    {
+        Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pObj) );
+        Vec_PtrPush( vPairs, Abc_NtkPi(pNtkNew, i+nLatches) );
+    }
+    pMiter = Abc_AigMiter( (Abc_Aig_t *)pNtkNew->pManFunc, vPairs, 0 );
+    Vec_PtrFree( vPairs );
+    // add the primary output
+    Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), Abc_ObjNot(pMiter) );
+    Abc_ObjAssignName( Abc_NtkPo(pNtkNew,0), "rel", NULL );
+
+    // quantify inputs
+    if ( fInputs )
+    {
+        assert( Abc_NtkPiNum(pNtkNew) == Abc_NtkPiNum(pNtk) + 2*nLatches );
+        for ( i = Abc_NtkPiNum(pNtkNew) - 1; i >= 2*nLatches; i-- )
+//        for ( i = 2*nLatches; i < Abc_NtkPiNum(pNtkNew); i++ )
+        {
+            Abc_NtkQuantify( pNtkNew, 0, i, fVerbose );
+//            if ( fSynthesis && (i % 3 == 2) )
+            if ( fSynthesis  )
+            {
+                Abc_NtkCleanData( pNtkNew );
+                Abc_AigCleanup( (Abc_Aig_t *)pNtkNew->pManFunc );
+                Abc_NtkSynthesize( &pNtkNew, 1 );
+            }
+//            printf( "Var = %3d. Nodes = %6d. ", Abc_NtkPiNum(pNtkNew) - 1 - i, Abc_NtkNodeNum(pNtkNew) );
+//            printf( "Var = %3d. Nodes = %6d. ", i - 2*nLatches, Abc_NtkNodeNum(pNtkNew) );
+        }
+//        printf( "\n" );
+        Abc_NtkCleanData( pNtkNew );
+        Abc_AigCleanup( (Abc_Aig_t *)pNtkNew->pManFunc );
+        for ( i = Abc_NtkPiNum(pNtkNew) - 1; i >= 2*nLatches; i-- )
+        {
+            pObj = Abc_NtkPi( pNtkNew, i );
+            assert( Abc_ObjFanoutNum(pObj) == 0 );
+            Abc_NtkDeleteObj( pObj );
+        }
+    }
+
+    // check consistency of the network
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkTransRel: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one image computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkInitialState( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pMiter;
+    int i, nVars = Abc_NtkPiNum(pNtk)/2;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // start the new network 
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+    // compute the all-zero state in terms of the CS variables
+    pMiter = Abc_AigConst1(pNtkNew);
+    for ( i = 0; i < nVars; i++ )
+        pMiter = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pMiter, Abc_ObjNot( Abc_NtkPi(pNtkNew, i) ) );
+    // add the PO
+    Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), pMiter );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Swaps current state and next state variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkSwapVariables( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pMiter, * pObj, * pObj0, * pObj1;
+    int i, nVars = Abc_NtkPiNum(pNtk)/2;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // start the new network 
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+    // update the PIs
+    for ( i = 0; i < nVars; i++ )
+    {
+        pObj0 = Abc_NtkPi( pNtk, i );
+        pObj1 = Abc_NtkPi( pNtk, i+nVars );
+        pMiter = pObj0->pCopy;
+        pObj0->pCopy = pObj1->pCopy;
+        pObj1->pCopy = pMiter;
+    }
+    // restrash
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+    // add the PO
+    pMiter = Abc_ObjChild0Copy( Abc_NtkPo(pNtk,0) );
+    Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), pMiter );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs reachability analisys.]
+
+  Description [Assumes that the input is the transition relation.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkReachability( Abc_Ntk_t * pNtkRel, int nIters, int fVerbose )
+{
+    Abc_Obj_t * pObj;
+    Abc_Ntk_t * pNtkFront, * pNtkReached, * pNtkNext, * pNtkTemp;
+    int i, v, nVars, nNodesOld, nNodesNew, nNodesPrev;
+    int fFixedPoint = 0;
+    int fSynthesis  = 1;
+    int fMoreEffort = 1;
+    abctime clk;
+
+    assert( Abc_NtkIsStrash(pNtkRel) );
+    assert( Abc_NtkLatchNum(pNtkRel) == 0 );
+    assert( Abc_NtkPiNum(pNtkRel) % 2 == 0 );
+
+    // compute the network composed of the initial states
+    pNtkFront = Abc_NtkInitialState( pNtkRel );
+    pNtkReached = Abc_NtkDup( pNtkFront );
+//Abc_NtkShow( pNtkReached, 0, 0, 0 );
+
+//    if ( fVerbose )
+//        printf( "Transition relation = %6d.\n", Abc_NtkNodeNum(pNtkRel) );
+
+    // perform iterations of reachability analysis
+    nNodesPrev = Abc_NtkNodeNum(pNtkFront);
+    nVars = Abc_NtkPiNum(pNtkRel)/2;
+    for ( i = 0; i < nIters; i++ )
+    {
+        clk = Abc_Clock();
+        // get the set of next states
+        pNtkNext = Abc_NtkMiterAnd( pNtkRel, pNtkFront, 0, 0 );
+        Abc_NtkDelete( pNtkFront );
+        // quantify the current state variables
+        for ( v = 0; v < nVars; v++ )
+        {
+            Abc_NtkQuantify( pNtkNext, 0, v, fVerbose );
+            if ( fSynthesis && (v % 3 == 2) )
+            {
+                Abc_NtkCleanData( pNtkNext );
+                Abc_AigCleanup( (Abc_Aig_t *)pNtkNext->pManFunc );
+                Abc_NtkSynthesize( &pNtkNext, fMoreEffort );
+            }
+        }
+        Abc_NtkCleanData( pNtkNext );
+        Abc_AigCleanup( (Abc_Aig_t *)pNtkNext->pManFunc );
+        if ( fSynthesis )
+            Abc_NtkSynthesize( &pNtkNext, 1 );
+        // map the next states into the current states
+        pNtkNext = Abc_NtkSwapVariables( pNtkTemp = pNtkNext );
+        Abc_NtkDelete( pNtkTemp );
+        // check the termination condition
+        if ( Abc_ObjFanin0(Abc_NtkPo(pNtkNext,0)) == Abc_AigConst1(pNtkNext) )
+        {
+            fFixedPoint = 1;
+            printf( "Fixed point is reached!\n" );
+            Abc_NtkDelete( pNtkNext );
+            break;
+        }
+        // compute new front
+        pNtkFront = Abc_NtkMiterAnd( pNtkNext, pNtkReached, 0, 1 );
+        Abc_NtkDelete( pNtkNext );
+        // add the reached states
+        pNtkReached = Abc_NtkMiterAnd( pNtkTemp = pNtkReached, pNtkFront, 1, 0 );
+        Abc_NtkDelete( pNtkTemp );
+        // compress the size of Front
+        nNodesOld = Abc_NtkNodeNum(pNtkFront);
+        if ( fSynthesis )
+        {
+            Abc_NtkSynthesize( &pNtkFront, fMoreEffort );
+            Abc_NtkSynthesize( &pNtkReached, fMoreEffort );
+        }
+        nNodesNew = Abc_NtkNodeNum(pNtkFront);
+        // print statistics
+        if ( fVerbose )
+        {
+            printf( "I = %3d : Reach = %6d  Fr = %6d  FrM = %6d  %7.2f %%   ", 
+                i + 1, Abc_NtkNodeNum(pNtkReached), nNodesOld, nNodesNew, 100.0*(nNodesNew-nNodesPrev)/nNodesPrev );
+            ABC_PRT( "T", Abc_Clock() - clk );
+        }
+        nNodesPrev = Abc_NtkNodeNum(pNtkFront);
+    }
+    if ( !fFixedPoint )
+        fprintf( stdout, "Reachability analysis stopped after %d iterations.\n", nIters );
+
+    // complement the output to represent the set of unreachable states
+    Abc_ObjXorFaninC( Abc_NtkPo(pNtkReached,0), 0 );
+
+    // remove next state variables
+    for ( i = 2*nVars - 1; i >= nVars; i-- )
+    {
+        pObj = Abc_NtkPi( pNtkReached, i );
+        assert( Abc_ObjFanoutNum(pObj) == 0 );
+        Abc_NtkDeleteObj( pObj );
+    }
+
+    // check consistency of the network
+    if ( !Abc_NtkCheck( pNtkReached ) )
+    {
+        printf( "Abc_NtkReachability: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkReached );
+        return NULL;
+    }
+    return pNtkReached;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcReach.c b/abc-build/src/base/abci/abcReach.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcReach.c
@@ -0,0 +1,321 @@
+/**CFile****************************************************************
+
+  FileName    [abcReach.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Performs reachability analysis.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcReach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the initial state and sets up the variable map.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NtkInitStateVarMap( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose )
+{
+    DdNode ** pbVarsX, ** pbVarsY;
+    DdNode * bTemp, * bProd, * bVar;
+    Abc_Obj_t * pLatch;
+    int i;
+
+    // set the variable mapping for Cudd_bddVarMap()
+    pbVarsX = ABC_ALLOC( DdNode *, dd->size );
+    pbVarsY = ABC_ALLOC( DdNode *, dd->size );
+    bProd = b1;         Cudd_Ref( bProd );
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+        pbVarsX[i] = dd->vars[ Abc_NtkPiNum(pNtk) + i ];
+        pbVarsY[i] = dd->vars[ Abc_NtkCiNum(pNtk) + i ];
+        // get the initial value of the latch
+        bVar  = Cudd_NotCond( pbVarsX[i], !Abc_LatchIsInit1(pLatch) );
+        bProd = Cudd_bddAnd( dd, bTemp = bProd, bVar );      Cudd_Ref( bProd );
+        Cudd_RecursiveDeref( dd, bTemp ); 
+    }
+    Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Abc_NtkLatchNum(pNtk) );
+    ABC_FREE( pbVarsX );
+    ABC_FREE( pbVarsY );
+
+    Cudd_Deref( bProd );
+    return bProd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode ** Abc_NtkCreatePartitions( DdManager * dd, Abc_Ntk_t * pNtk, int fReorder, int fVerbose )
+{
+    DdNode ** pbParts;
+    DdNode * bVar;
+    Abc_Obj_t * pNode;
+    int i;
+
+    // extand the BDD manager to represent NS variables
+    assert( dd->size == Abc_NtkCiNum(pNtk) );
+    Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + Abc_NtkLatchNum(pNtk) - 1 );
+
+    // enable reordering
+    if ( fReorder )
+        Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+    else
+        Cudd_AutodynDisable( dd );
+
+    // compute the transition relation
+    pbParts = ABC_ALLOC( DdNode *, Abc_NtkLatchNum(pNtk) );
+    Abc_NtkForEachLatch( pNtk, pNode, i )
+    {
+        bVar  = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i );
+        pbParts[i] = Cudd_bddXnor( dd, bVar, (DdNode *)Abc_ObjGlobalBdd(Abc_ObjFanin0(pNode)) );  Cudd_Ref( pbParts[i] );
+    }
+    // free the global BDDs
+    Abc_NtkFreeGlobalBdds( pNtk, 0 );
+
+    // reorder and disable reordering
+    if ( fReorder )
+    {
+        if ( fVerbose )
+            fprintf( stdout, "BDD nodes in the partitions before reordering %d.\n", Cudd_SharingSize(pbParts,Abc_NtkLatchNum(pNtk)) );
+        Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+        Cudd_AutodynDisable( dd );
+        if ( fVerbose )
+            fprintf( stdout, "BDD nodes in the partitions after reordering %d.\n", Cudd_SharingSize(pbParts,Abc_NtkLatchNum(pNtk)) );
+    }
+    return pbParts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the set of unreachable states.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NtkComputeReachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode ** pbParts, DdNode * bInitial, DdNode * bOutput, int nBddMax, int nIterMax, int fPartition, int fReorder, int fVerbose )
+{
+    int fInternalReorder = 0;
+    Extra_ImageTree_t * pTree = NULL;
+    Extra_ImageTree2_t * pTree2 = NULL;
+    DdNode * bReached, * bCubeCs;
+    DdNode * bCurrent, * bNext = NULL, * bTemp;
+    DdNode ** pbVarsY;
+    Abc_Obj_t * pLatch;
+    int i, nIters, nBddSize;
+    int nThreshold = 10000;
+
+    // collect the NS variables
+    // set the variable mapping for Cudd_bddVarMap()
+    pbVarsY = ABC_ALLOC( DdNode *, dd->size );
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+        pbVarsY[i] = dd->vars[ Abc_NtkCiNum(pNtk) + i ];
+
+    // start the image computation
+    bCubeCs  = Extra_bddComputeRangeCube( dd, Abc_NtkPiNum(pNtk), Abc_NtkCiNum(pNtk) );    Cudd_Ref( bCubeCs );
+    if ( fPartition )
+        pTree = Extra_bddImageStart( dd, bCubeCs, Abc_NtkLatchNum(pNtk), pbParts, Abc_NtkLatchNum(pNtk), pbVarsY, fVerbose );
+    else
+        pTree2 = Extra_bddImageStart2( dd, bCubeCs, Abc_NtkLatchNum(pNtk), pbParts, Abc_NtkLatchNum(pNtk), pbVarsY, fVerbose );
+    ABC_FREE( pbVarsY );
+    Cudd_RecursiveDeref( dd, bCubeCs );
+
+    // perform reachability analisys
+    bCurrent = bInitial;   Cudd_Ref( bCurrent );
+    bReached = bInitial;   Cudd_Ref( bReached );
+    assert( nIterMax > 1 ); // required to not deref uninitialized bNext
+    for ( nIters = 1; nIters <= nIterMax; nIters++ )
+    {
+        // compute the next states
+        if ( fPartition )
+            bNext = Extra_bddImageCompute( pTree, bCurrent );           
+        else
+            bNext = Extra_bddImageCompute2( pTree2, bCurrent );         
+        Cudd_Ref( bNext );
+        Cudd_RecursiveDeref( dd, bCurrent );
+        // remap these states into the current state vars
+        bNext = Cudd_bddVarMap( dd, bTemp = bNext );                    Cudd_Ref( bNext );
+        Cudd_RecursiveDeref( dd, bTemp );
+        // check if there are any new states
+        if ( Cudd_bddLeq( dd, bNext, bReached ) )
+            break;
+        // check the BDD size
+        nBddSize = Cudd_DagSize(bNext);
+        if ( nBddSize > nBddMax )
+            break;
+        // check the result
+        if ( !Cudd_bddLeq( dd, bNext, Cudd_Not(bOutput) ) )
+        {
+            printf( "The miter is proved REACHABLE in %d iterations.  ", nIters );
+            Cudd_RecursiveDeref( dd, bReached );
+            bReached = NULL;
+            break;
+        }
+        // get the new states
+        bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) );        Cudd_Ref( bCurrent );
+        // minimize the new states with the reached states
+//        bCurrent = Cudd_bddConstrain( dd, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent );
+//        Cudd_RecursiveDeref( dd, bTemp );
+        // add to the reached states
+        bReached = Cudd_bddOr( dd, bTemp = bReached, bNext );           Cudd_Ref( bReached );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bNext );
+        if ( fVerbose )
+            fprintf( stdout, "Iteration = %3d. BDD = %5d. ", nIters, nBddSize );
+        if ( fInternalReorder && fReorder && nBddSize > nThreshold )
+        {
+            if ( fVerbose )
+                fprintf( stdout, "Reordering... Before = %5d. ", Cudd_DagSize(bReached) );
+            Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+            Cudd_AutodynDisable( dd );
+            if ( fVerbose )
+                fprintf( stdout, "After = %5d.\r", Cudd_DagSize(bReached) );
+            nThreshold *= 2;
+        }
+        if ( fVerbose )
+            fprintf( stdout, "\r" );
+    }
+    Cudd_RecursiveDeref( dd, bNext );
+    // undo the image tree
+    if ( fPartition )
+        Extra_bddImageTreeDelete( pTree );
+    else
+        Extra_bddImageTreeDelete2( pTree2 );
+    if ( bReached == NULL )
+        return NULL;
+    // report the stats
+    if ( fVerbose )
+    {
+        double nMints = Cudd_CountMinterm(dd, bReached, Abc_NtkLatchNum(pNtk) );
+        if ( nIters > nIterMax || Cudd_DagSize(bReached) > nBddMax )
+            fprintf( stdout, "Reachability analysis is stopped after %d iterations.\n", nIters );
+        else
+            fprintf( stdout, "Reachability analysis completed in %d iterations.\n", nIters );
+        fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Abc_NtkLatchNum(pNtk)) );
+        fflush( stdout );
+    }
+//ABC_PRB( dd, bReached );
+    Cudd_Deref( bReached );
+    if ( nIters > nIterMax || Cudd_DagSize(bReached) > nBddMax )
+         printf( "Verified ONLY FOR STATES REACHED in %d iterations. \n", nIters );
+    printf( "The miter is proved unreachable in %d iteration.  ", nIters );
+    return bReached;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs reachability to see if any .]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkVerifyUsingBdds( Abc_Ntk_t * pNtk, int nBddMax, int nIterMax, int fPartition, int fReorder, int fVerbose )
+{
+    DdManager * dd;
+    DdNode ** pbParts;
+    DdNode * bOutput, * bReached, * bInitial;
+    int i;
+    abctime clk = Abc_Clock();
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( Abc_NtkPoNum(pNtk) == 1 );
+    assert( Abc_ObjFanoutNum(Abc_NtkPo(pNtk,0)) == 0 ); // PO should go first
+
+    // compute the global BDDs of the latches
+    dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, nBddMax, 1, fReorder, fVerbose );    
+    if ( dd == NULL )
+    {
+        printf( "The number of intermediate BDD nodes exceeded the limit (%d).\n", nBddMax );
+        return;
+    }
+    if ( fVerbose )
+        printf( "Shared BDD size is %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+
+    // save the output BDD
+    bOutput = (DdNode *)Abc_ObjGlobalBdd(Abc_NtkPo(pNtk,0)); Cudd_Ref( bOutput );
+
+    // create partitions
+    pbParts = Abc_NtkCreatePartitions( dd, pNtk, fReorder, fVerbose );
+
+    // create the initial state and the variable map
+    bInitial  = Abc_NtkInitStateVarMap( dd, pNtk, fVerbose );  Cudd_Ref( bInitial );
+
+    // check the result
+    if ( !Cudd_bddLeq( dd, bInitial, Cudd_Not(bOutput) ) )
+        printf( "The miter is proved REACHABLE in the initial state.  " );
+    else
+    {
+        // compute the reachable states
+        bReached = Abc_NtkComputeReachable( dd, pNtk, pbParts, bInitial, bOutput, nBddMax, nIterMax, fPartition, fReorder, fVerbose ); 
+        if ( bReached != NULL )
+        {
+            Cudd_Ref( bReached );
+            Cudd_RecursiveDeref( dd, bReached );
+        }
+    }
+
+    // cleanup
+    Cudd_RecursiveDeref( dd, bOutput );
+    Cudd_RecursiveDeref( dd, bInitial );
+    for ( i = 0; i < Abc_NtkLatchNum(pNtk); i++ )
+        Cudd_RecursiveDeref( dd, pbParts[i] );
+    ABC_FREE( pbParts );
+    Extra_StopManager( dd );
+
+    // report the runtime
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    fflush( stdout );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcRec3.c b/abc-build/src/base/abci/abcRec3.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcRec3.c
@@ -0,0 +1,1413 @@
+/**CFile****************************************************************
+
+  FileName    [abcRec2.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Record of semi-canonical AIG subgraphs.]
+
+  Author      [Allan Yang, Alan Mishchenko]
+  
+  Affiliation [Fudan University in Shanghai, UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcRec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "map/if/if.h"
+#include "bool/kit/kit.h"
+#include "aig/gia/giaAig.h"
+#include "misc/vec/vecMem.h"
+#include "opt/dau/dau.h"
+#include "misc/util/utilTruth.h"
+
+ABC_NAMESPACE_IMPL_START
+
+#define LMS_VAR_MAX    16  // LMS_VAR_MAX >= 6
+#define LMS_MAX_WORD  (1<<(LMS_VAR_MAX-6))
+//#define LMS_USE_OLD_FORM
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+/*
+    This LMS manager can be used in two modes:
+        - library constuction
+        - AIG level minimization
+    To switch from library construction to AIG level minimization
+    LSM manager should be restarted by dumping GIA (rec_dump3 <file>.aig) 
+    and starting LMS manager again (rec_start3 <file>.aig).
+*/
+
+typedef struct Lms_Man_t_ Lms_Man_t;
+struct Lms_Man_t_
+{
+    // parameters
+    int               nVars;        // the number of variables
+    int               nWords;       // the number of TT words
+    int               nCuts;        // the max number of cuts to use
+    int               fFuncOnly;    // record only functions
+    int               fLibConstr;   // this manager is used for library construction
+    // internal data for library construction
+    Gia_Man_t *       pGia;         // the record
+    Vec_Mem_t *       vTtMem;       // truth table memory and hash table
+//    Vec_Mem_t *       vTtMem2;      // truth table memory and hash table
+    Vec_Int_t *       vTruthIds;    // truth table IDs of each PO
+    // internal data for AIG level minimization (allocated the first time it is called)
+    Vec_Int_t *       vTruthPo;     // first PO where this canonicized truth table was seen
+    Vec_Wrd_t *       vDelays;      // pin-to-pin delays of each PO
+    Vec_Str_t *       vAreas;       // number of AND gates in each PO
+    Vec_Int_t *       vFreqs;       // subgraph usage frequencies
+    Vec_Int_t *       vTruthFreqs;  // truth table usage frequencies
+    // temporaries
+    Vec_Ptr_t *       vNodes;       // the temporary nodes
+    Vec_Ptr_t *       vLabelsP;     // temporary storage for HOP node labels
+    Vec_Int_t *       vLabels;      // temporary storage for AIG node labels
+    Vec_Str_t *       vSupps;       // used temporarily by TT dumping
+    word              pTemp1[LMS_MAX_WORD]; // copy of the truth table
+    word              pTemp2[LMS_MAX_WORD]; // copy of the truth table
+    // statistics 
+    int               nTried;
+    int               nFilterSize;
+    int               nFilterRedund;
+    int               nFilterVolume;
+    int               nFilterTruth;
+    int               nFilterError;
+    int               nFilterSame;
+    int               nAdded;
+    int               nAddedFuncs;
+    int               nHoleInTheWall;
+    // runtime
+    abctime           timeTruth;
+    abctime           timeCanon;
+    abctime           timeBuild;
+    abctime           timeCheck;
+    abctime           timeInsert;
+    abctime           timeOther;
+    abctime           timeTotal;
+};
+
+static Lms_Man_t * s_pMan3 = NULL;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Compute delay/area profiles of POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int  Lms_DelayGet( word D, int v )           { assert(v >= 0 && v < LMS_VAR_MAX); return (int)((D >> (v << 2)) & 0xF);                             }
+static inline void Lms_DelaySet( word * pD, int v, int d ) { assert(v >= 0 && v < LMS_VAR_MAX); assert(d >= 0 && d < LMS_VAR_MAX); *pD |= ((word)d << (v << 2)); }
+static inline word Lms_DelayInit( int v )                  { assert(v >= 0 && v < LMS_VAR_MAX); return (word)1 << (v << 2);                                      }
+static inline word Lms_DelayMax( word D1, word D2, int nVars )
+{
+    int v, Max;
+    word D = 0;
+    for ( v = 0; v < nVars; v++ )
+        if ( (Max = Abc_MaxInt(Lms_DelayGet(D1, v), Lms_DelayGet(D2, v))) )
+            Lms_DelaySet( &D, v, Abc_MinInt(Max + 1, 15) );
+    return D;
+}
+static inline word Lms_DelayDecrement( word D1, int nVars )
+{
+    int v;
+    word D = 0;
+    for ( v = 0; v < nVars; v++ )
+        if ( Lms_DelayGet(D1, v) )
+            Lms_DelaySet( &D, v, Lms_DelayGet(D1, v) - 1 );
+    return D;
+}
+static inline int Lms_DelayEqual( word D1, word D2, int nVars ) // returns 1 if D1 has the same delays than D2
+{
+    int v;
+    for ( v = 0; v < nVars; v++ )
+        if ( Lms_DelayGet(D1, v) != Lms_DelayGet(D2, v) )
+            return 0;
+    return 1;
+}
+static inline int Lms_DelayDom( word D1, word D2, int nVars ) // returns 1 if D1 has the same or smaller delays than D2
+{
+    int v;
+    for ( v = 0; v < nVars; v++ )
+        if ( Lms_DelayGet(D1, v) > Lms_DelayGet(D2, v) )
+            return 0;
+    return 1;
+}
+static inline void Lms_DelayPrint( word D, int nVars )
+{
+    int v;
+    printf( "Delay profile = {" );
+    for ( v = 0; v < nVars; v++ )
+        printf( " %d", Lms_DelayGet(D, v) );
+    printf( " }\n" );
+}
+Vec_Wrd_t * Lms_GiaDelays( Gia_Man_t * p )
+{
+    Vec_Wrd_t * vDelays, * vResult;
+    Gia_Obj_t * pObj;
+    int i;
+    // compute delay profiles of all objects
+    vDelays = Vec_WrdAlloc( Gia_ManObjNum(p) );
+    Vec_WrdPush( vDelays, 0 ); // const 0
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            Vec_WrdPush( vDelays, Lms_DelayMax( Vec_WrdEntry(vDelays, Gia_ObjFaninId0(pObj, i)), Vec_WrdEntry(vDelays, Gia_ObjFaninId1(pObj, i)), Gia_ManCiNum(p) ) );
+        else if ( Gia_ObjIsCo(pObj) )
+            Vec_WrdPush( vDelays, Lms_DelayDecrement( Vec_WrdEntry(vDelays, Gia_ObjFaninId0(pObj, i)), Gia_ManCiNum(p) ) );
+        else if ( Gia_ObjIsCi(pObj) )
+            Vec_WrdPush( vDelays, Lms_DelayInit( Gia_ObjCioId(pObj) ) );
+        else assert( 0 );
+    }
+    // collect delay profiles of COs only
+    vResult = Vec_WrdAlloc( Gia_ManCoNum(p) );
+    Gia_ManForEachCo( p, pObj, i )
+        Vec_WrdPush( vResult, Vec_WrdEntry(vDelays, Gia_ObjId(p, pObj)) );
+    Vec_WrdFree( vDelays );
+    return vResult;
+}
+void Lms_ObjAreaMark_rec( Gia_Obj_t * pObj )
+{
+    if ( pObj->fMark0 || Gia_ObjIsCi(pObj) )
+        return;
+    pObj->fMark0 = 1;
+    Lms_ObjAreaMark_rec( Gia_ObjFanin0(pObj) );
+    Lms_ObjAreaMark_rec( Gia_ObjFanin1(pObj) );
+}
+int  Lms_ObjAreaUnmark_rec( Gia_Obj_t * pObj )
+{
+    if ( !pObj->fMark0 || Gia_ObjIsCi(pObj) )
+        return 0;
+    pObj->fMark0 = 0;
+    return 1 + Lms_ObjAreaUnmark_rec( Gia_ObjFanin0(pObj) ) 
+             + Lms_ObjAreaUnmark_rec( Gia_ObjFanin1(pObj) );
+}
+int Lms_ObjArea( Gia_Obj_t * pObj )
+{
+    assert( Gia_ObjIsAnd(pObj) );
+    Lms_ObjAreaMark_rec( pObj );
+    return Lms_ObjAreaUnmark_rec( pObj );    
+}
+Vec_Str_t * Lms_GiaAreas( Gia_Man_t * p )
+{
+    Vec_Str_t * vAreas;
+    Gia_Obj_t * pObj;
+    int i;
+    vAreas = Vec_StrAlloc( Gia_ManCoNum(p) );
+    Gia_ManForEachCo( p, pObj, i )
+        Vec_StrPush( vAreas, (char)(Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) ? Lms_ObjArea(Gia_ObjFanin0(pObj)) : 0) );
+    return vAreas;
+}
+Vec_Str_t * Lms_GiaSuppSizes( Gia_Man_t * p )
+{
+    Vec_Str_t * vResult;
+    Vec_Str_t * vSupps;
+    Gia_Obj_t * pObj;
+    int i;
+    vSupps = Vec_StrAlloc( Gia_ManObjNum(p) );
+    Vec_StrPush( vSupps, 0 );
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            Vec_StrPush( vSupps, (char)Abc_MaxInt( Vec_StrEntry(vSupps, Gia_ObjFaninId0(pObj, i)), Vec_StrEntry(vSupps, Gia_ObjFaninId1(pObj, i)) ) );
+        else if ( Gia_ObjIsCo(pObj) )
+            Vec_StrPush( vSupps, Vec_StrEntry(vSupps, Gia_ObjFaninId0(pObj, i)) );
+        else if ( Gia_ObjIsCi(pObj) )
+            Vec_StrPush( vSupps, (char)(Gia_ObjCioId(pObj)+1) );
+        else assert( 0 );
+    }
+    assert( Vec_StrSize(vSupps) == Gia_ManObjNum(p) );
+    vResult = Vec_StrAlloc( Gia_ManCoNum(p) );
+    Gia_ManForEachCo( p, pObj, i )
+        Vec_StrPush( vResult, Vec_StrEntry(vSupps, Gia_ObjId(p, pObj)) );
+    Vec_StrFree( vSupps );
+    return vResult;
+}
+void Lms_GiaProfilesPrint( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Vec_Wrd_t * vDelays;
+    Vec_Str_t * vAreas;
+    vDelays = Lms_GiaDelays( p );
+    vAreas = Lms_GiaAreas( p );
+    Gia_ManForEachPo( p, pObj, i )
+    {
+        printf( "%6d : ", i );
+        printf( "A = %2d  ", Vec_StrEntry(vAreas, i) );
+        Lms_DelayPrint( Vec_WrdEntry(vDelays, i), Gia_ManPiNum(p) );
+//        Lms_GiaPrintSubgraph( p, pObj );
+//        printf( "\n" );
+    }
+    Vec_WrdFree( vDelays );
+    Vec_StrFree( vAreas );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints one GIA subgraph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lms_GiaPrintSubgraph_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( !pObj->fMark0 || Gia_ObjIsCi(pObj) )
+        return;
+    pObj->fMark0 = 0;
+    assert( Gia_ObjIsAnd(pObj) );
+    Lms_GiaPrintSubgraph_rec( p, Gia_ObjFanin0(pObj) );
+    Lms_GiaPrintSubgraph_rec( p, Gia_ObjFanin1(pObj) );
+    Gia_ObjPrint( p, pObj );
+}
+void Lms_GiaPrintSubgraph( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    assert( Gia_ObjIsCo(pObj) );
+    if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) )
+    {
+        Lms_ObjAreaMark_rec( Gia_ObjFanin0(pObj) );
+        Lms_GiaPrintSubgraph_rec( p, Gia_ObjFanin0(pObj) ); 
+    }
+    else
+        Gia_ObjPrint( p, Gia_ObjFanin0(pObj) );
+    Gia_ObjPrint( p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Lms_Man_t * Lms_ManStart( Gia_Man_t * pGia, int nVars, int nCuts, int fFuncOnly, int fVerbose )
+{
+    Lms_Man_t * p;
+    abctime clk, clk2 = Abc_Clock();
+    // if GIA is given, use the number of variables from GIA
+    nVars = pGia ? Gia_ManCiNum(pGia) : nVars;
+    assert( nVars >= 6 && nVars <= LMS_VAR_MAX );
+    // allocate manager
+    p = ABC_CALLOC( Lms_Man_t, 1 );
+    // parameters
+    p->nVars = nVars;
+    p->nCuts = nCuts;
+    p->nWords = Abc_Truth6WordNum( nVars );
+    p->fFuncOnly = fFuncOnly;
+    // internal data for library construction
+    p->vTtMem = Vec_MemAlloc( p->nWords, 12 ); // 32 KB/page for 6-var functions
+//    p->vTtMem2 = Vec_MemAlloc( p->nWords, 12 ); // 32 KB/page for 6-var functions
+    Vec_MemHashAlloc( p->vTtMem, 10000 );
+//    Vec_MemHashAlloc( p->vTtMem2, 10000 );
+    if ( fFuncOnly )
+        return p;    
+    p->vTruthIds = Vec_IntAlloc( 10000 );
+    if ( pGia == NULL )
+    {
+        int i;
+        p->pGia = Gia_ManStart( 10000 );
+        p->pGia->pName = Abc_UtilStrsav( "record" );
+        for ( i = 0; i < nVars; i++ )
+            Gia_ManAppendCi( p->pGia );
+    }
+    else
+    {
+        Gia_Obj_t * pObj;
+        word * pTruth;
+        int i, Index, Prev = -1;
+        p->pGia = pGia;
+        // populate the manager with subgraphs present in GIA
+        p->nAdded = Gia_ManCoNum( p->pGia );
+        Gia_ManForEachCo( p->pGia, pObj, i )
+        {
+            clk = Abc_Clock();
+            pTruth = Gia_ObjComputeTruthTable( p->pGia, pObj );
+            p->timeTruth += Abc_Clock() - clk;
+            clk = Abc_Clock();
+            Index = Vec_MemHashInsert( p->vTtMem, pTruth );
+            p->timeInsert += Abc_Clock() - clk;
+            assert( Index == Prev || Index == Prev + 1 ); // GIA subgraphs should be ordered
+            Vec_IntPush( p->vTruthIds, Index );
+            Prev = Index;
+        }
+    }
+    // temporaries
+    p->vNodes    = Vec_PtrAlloc( 1000 );
+    p->vLabelsP  = Vec_PtrAlloc( 1000 );
+    p->vLabels   = Vec_IntAlloc( 1000 );
+p->timeTotal += Abc_Clock() - clk2;
+    return p;    
+}
+void Lms_ManStop( Lms_Man_t * p )
+{
+    // temporaries
+    Vec_IntFreeP( &p->vLabels );
+    Vec_PtrFreeP( &p->vLabelsP );
+    Vec_PtrFreeP( &p->vNodes );
+    // internal data for AIG level minimization
+    Vec_IntFreeP( &p->vTruthPo );
+    Vec_WrdFreeP( &p->vDelays );
+    Vec_StrFreeP( &p->vAreas );
+    Vec_IntFreeP( &p->vFreqs );
+    Vec_IntFreeP( &p->vTruthFreqs );
+    // internal data for library construction
+    Vec_IntFreeP( &p->vTruthIds );
+    Vec_MemHashFree( p->vTtMem );
+//    Vec_MemHashFree( p->vTtMem2 );
+    Vec_MemFree( p->vTtMem );
+//    Vec_MemFree( p->vTtMem2 );
+    Gia_ManStopP( &p->pGia );
+    ABC_FREE( p );
+}
+void Lms_ManPrepare( Lms_Man_t * p )
+{
+    // compute the first PO for each semi-canonical form
+    int i, Entry;
+    assert( !p->fLibConstr );
+    assert( p->vTruthPo == NULL );
+    p->vTruthPo = Vec_IntStartFull( Vec_MemEntryNum(p->vTtMem)+1 );
+    assert( Vec_IntFindMin(p->vTruthIds) >= 0 );
+    assert( Vec_IntFindMax(p->vTruthIds) < Vec_MemEntryNum(p->vTtMem) );
+    Vec_IntForEachEntry( p->vTruthIds, Entry, i )
+        if ( Vec_IntEntry(p->vTruthPo, Entry) == -1 )
+            Vec_IntWriteEntry( p->vTruthPo, Entry, i );
+    Vec_IntWriteEntry( p->vTruthPo, Vec_MemEntryNum(p->vTtMem), Gia_ManCoNum(p->pGia) );
+    // compute delay/area and init frequency
+    assert( p->vDelays == NULL );
+    assert( p->vAreas == NULL );
+    assert( p->vFreqs == NULL );
+    p->vDelays = Lms_GiaDelays( p->pGia );
+    p->vAreas  = Lms_GiaAreas( p->pGia );
+    p->vFreqs  = Vec_IntStart( Gia_ManCoNum(p->pGia) );
+}
+void Lms_ManPrintFuncStats( Lms_Man_t * p )
+{
+    Vec_Str_t * vSupps;
+    int Counters[LMS_VAR_MAX+1] = {0}, CountersS[LMS_VAR_MAX+1] = {0};
+    int i, Entry, Next;
+    if ( p->pGia == NULL )
+        return;
+    if ( p->fLibConstr )
+        return;
+    if ( p->vTruthPo == NULL )
+        Lms_ManPrepare( p );
+    vSupps = Lms_GiaSuppSizes( p->pGia );
+    Vec_IntForEachEntry( p->vTruthPo, Entry, i )
+    {
+        if ( i == Vec_IntSize(p->vTruthPo) - 1 )
+            break;
+        Next = Vec_IntEntry( p->vTruthPo, i+1 );
+        Counters[(int)Vec_StrEntry(vSupps, Entry)]++;
+        CountersS[(int)Vec_StrEntry(vSupps, Entry)] += Next - Entry;
+    }
+    for ( i = 0; i <= LMS_VAR_MAX; i++ )
+        if ( Counters[i] )
+            printf( "Inputs = %2d.  Funcs = %8d.  Subgrs = %8d.  Ratio = %6.2f.\n", i, Counters[i], CountersS[i], 1.0*CountersS[i]/Counters[i] );
+    Vec_StrFree( vSupps );
+}
+void Lms_ManPrintFreqStats( Lms_Man_t * p )
+{
+    int CountDsdNpn[3]  = {0};  // full/part/none
+    int CountDsdAll[3]  = {0};  // full/part/none
+    int CountStepNpn[3] = {0};  // full/1step/complex
+    int CountStepAll[3] = {0};  // full/1step/complex
+    char pBuffer[1000];
+    int nSuppSize;
+    int nNonDecSize;
+    word * pTruth;
+    int i, Freq, Status;
+    printf( "Cuts  = %10d. ",            p->nTried );
+//    printf( "Funcs = %10d (%6.2f %%). ", Vec_MemEntryNum(p->vTtMem2), 100.0*Vec_MemEntryNum(p->vTtMem2)/p->nTried );
+    printf( "Class = %10d (%6.2f %%). ", Vec_MemEntryNum(p->vTtMem),  100.0*Vec_MemEntryNum(p->vTtMem)/p->nTried );
+    printf( "\n" );
+//    return;
+
+    Vec_IntForEachEntry( p->vTruthFreqs, Freq, i )
+    {
+        pTruth = Vec_MemReadEntry(p->vTtMem, i);
+/*
+        printf( "%6d -- %6d : ", i, Freq );
+        Kit_DsdWriteFromTruth( pBuffer, (unsigned *)pTruth, p->nVars );
+        printf( "%s\n", pBuffer );
+*/
+        nSuppSize = Abc_TtSupportSize( pTruth, p->nVars );
+        nNonDecSize = Dau_DsdDecompose( pTruth, p->nVars, 0, 0, pBuffer );
+        if ( nNonDecSize == 0 )
+        {
+            CountDsdNpn[0]++;
+            CountDsdAll[0] += Freq;
+        }
+        else if ( nNonDecSize < nSuppSize )
+        {
+            CountDsdNpn[1]++;
+            CountDsdAll[1] += Freq;
+        }
+        else // non-dec
+        {
+            CountDsdNpn[2]++;
+            CountDsdAll[2] += Freq;
+        }
+
+        if ( nNonDecSize == 0 )
+        {
+            CountStepNpn[0]++;
+            CountStepAll[0] += Freq;
+            continue;
+        }
+
+        // check the non dec core
+        Status = Dau_DsdCheck1Step( NULL, pTruth, nNonDecSize, NULL );
+        if ( Status >= 0 )
+        {
+            CountStepNpn[1]++;
+            CountStepAll[1] += Freq;
+        }
+        else
+        {
+            assert( Status == -2 );
+            CountStepNpn[2]++;
+            CountStepAll[2] += Freq;
+        }
+    }
+
+    // print the results
+    printf( "NPN: " );
+    printf( "Full = %6.2f %%  ", 100.0 * CountDsdNpn[0] / Vec_MemEntryNum(p->vTtMem) );
+    printf( "Part = %6.2f %%  ", 100.0 * CountDsdNpn[1] / Vec_MemEntryNum(p->vTtMem) );
+    printf( "None = %6.2f %%  ", 100.0 * CountDsdNpn[2] / Vec_MemEntryNum(p->vTtMem) );
+//    printf( "\n" );
+    printf( "   " );
+    // print the results
+    printf( "All: " );
+    printf( "Full = %6.2f %%  ", 100.0 * CountDsdAll[0] / p->nTried );
+    printf( "Part = %6.2f %%  ", 100.0 * CountDsdAll[1] / p->nTried );
+    printf( "None = %6.2f %%  ", 100.0 * CountDsdAll[2] / p->nTried );
+    printf( "\n" );
+
+    // print the results
+    printf( "NPN: " );
+    printf( "Full = %6.2f %%  ", 100.0 * CountStepNpn[0] / Vec_MemEntryNum(p->vTtMem) );
+    printf( "1stp = %6.2f %%  ", 100.0 * CountStepNpn[1] / Vec_MemEntryNum(p->vTtMem) );
+    printf( "Comp = %6.2f %%  ", 100.0 * CountStepNpn[2] / Vec_MemEntryNum(p->vTtMem) );
+//    printf( "\n" );
+    printf( "   " );
+    // print the results
+    printf( "All: " );
+    printf( "Full = %6.2f %%  ", 100.0 * CountStepAll[0] / p->nTried );
+    printf( "1stp = %6.2f %%  ", 100.0 * CountStepAll[1] / p->nTried );
+    printf( "Comp = %6.2f %%  ", 100.0 * CountStepAll[2] / p->nTried );
+    printf( "\n" );
+
+}
+void Lms_ManPrint( Lms_Man_t * p )
+{
+//    Gia_ManPrintStats( p->pGia, 0, 0 );
+    printf( "Library with %d vars has %d classes and %d AIG subgraphs with %d AND nodes.\n", 
+        p->nVars, Vec_MemEntryNum(p->vTtMem), p->nAdded, p->pGia ? Gia_ManAndNum(p->pGia) : 0 );
+
+//    Lms_ManPrintFreqStats( p );
+    Lms_ManPrintFuncStats( p );
+
+    p->nAddedFuncs = Vec_MemEntryNum(p->vTtMem);
+    printf( "Subgraphs tried                             = %10d. (%6.2f %%)\n", p->nTried,         !p->nTried? 0 : 100.0*p->nTried/p->nTried );
+    printf( "Subgraphs filtered by support size          = %10d. (%6.2f %%)\n", p->nFilterSize,    !p->nTried? 0 : 100.0*p->nFilterSize/p->nTried );
+    printf( "Subgraphs filtered by structural redundancy = %10d. (%6.2f %%)\n", p->nFilterRedund,  !p->nTried? 0 : 100.0*p->nFilterRedund/p->nTried );
+    printf( "Subgraphs filtered by volume                = %10d. (%6.2f %%)\n", p->nFilterVolume,  !p->nTried? 0 : 100.0*p->nFilterVolume/p->nTried );
+    printf( "Subgraphs filtered by TT redundancy         = %10d. (%6.2f %%)\n", p->nFilterTruth,   !p->nTried? 0 : 100.0*p->nFilterTruth/p->nTried );
+    printf( "Subgraphs filtered by error                 = %10d. (%6.2f %%)\n", p->nFilterError,   !p->nTried? 0 : 100.0*p->nFilterError/p->nTried );
+    printf( "Subgraphs filtered by isomorphism           = %10d. (%6.2f %%)\n", p->nFilterSame,    !p->nTried? 0 : 100.0*p->nFilterSame/p->nTried );
+    printf( "Subgraphs added                             = %10d. (%6.2f %%)\n", p->nAdded,         !p->nTried? 0 : 100.0*p->nAdded/p->nTried );
+    printf( "Functions added                             = %10d. (%6.2f %%)\n", p->nAddedFuncs,    !p->nTried? 0 : 100.0*p->nAddedFuncs/p->nTried );
+    if ( p->nHoleInTheWall )
+    printf( "Cuts whose logic structure has a hole       = %10d. (%6.2f %%)\n", p->nHoleInTheWall, !p->nTried? 0 : 100.0*p->nHoleInTheWall/p->nTried );
+
+    p->timeOther = p->timeTotal - p->timeTruth - p->timeCanon - p->timeBuild - p->timeCheck - p->timeInsert;
+    ABC_PRTP( "Runtime: Truth ", p->timeTruth,  p->timeTotal );
+    ABC_PRTP( "Runtime: Canon ", p->timeCanon,  p->timeTotal );
+    ABC_PRTP( "Runtime: Build ", p->timeBuild,  p->timeTotal );
+    ABC_PRTP( "Runtime: Check ", p->timeCheck,  p->timeTotal );
+    ABC_PRTP( "Runtime: Insert", p->timeInsert, p->timeTotal );
+    ABC_PRTP( "Runtime: Other ", p->timeOther,  p->timeTotal );
+    ABC_PRTP( "Runtime: TOTAL ", p->timeTotal,  p->timeTotal );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recanonicizes the library and add it to the current library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkRecLibMerge3( Gia_Man_t * pLib )
+{
+    int fCheck = 0;
+    Lms_Man_t * p = s_pMan3;
+    Gia_Man_t * pGia = p->pGia;
+    Vec_Str_t * vSupps;
+    char pCanonPerm[LMS_VAR_MAX];
+    unsigned uCanonPhase;
+    word * pTruth;
+    int i, k, Index, iFanin0, iFanin1, nLeaves;
+    Gia_Obj_t * pObjPo, * pDriver, * pTemp = NULL;
+    abctime clk, clk2 = Abc_Clock();
+
+    if ( Gia_ManCiNum(pLib) != Gia_ManCiNum(pGia) )
+    {
+        printf( "The number of Library inputs (%d) differs from the number of Gia inputs (%d).\n", Gia_ManCiNum(pLib), Gia_ManCiNum(pGia) );
+        return;
+    }
+    assert( Gia_ManCiNum(pLib) == Gia_ManCiNum(pGia) );
+
+    // create hash table if not available
+    if ( pGia->pHTable == NULL )
+        Gia_ManHashStart( pGia );
+
+    // add AIG subgraphs
+    vSupps = Lms_GiaSuppSizes( pLib );
+    Gia_ManForEachCo( pLib, pObjPo, k )
+    {
+        // get support size
+        nLeaves = Vec_StrEntry(vSupps, k);
+        assert( nLeaves > 1 );
+
+        // compute the truth table
+clk = Abc_Clock();
+        pTruth = Gia_ObjComputeTruthTable( pLib, Gia_ObjFanin0(pObjPo) );
+p->timeTruth += Abc_Clock() - clk;
+        // semi-canonicize
+clk = Abc_Clock();
+        memcpy( p->pTemp1, pTruth, p->nWords * sizeof(word) );
+#ifdef LMS_USE_OLD_FORM
+        uCanonPhase = Kit_TruthSemiCanonicize( (unsigned *)p->pTemp1, (unsigned *)p->pTemp2, nLeaves, pCanonPerm );
+#else
+        uCanonPhase = Abc_TtCanonicize( p->pTemp1, nLeaves, pCanonPerm );
+#endif
+        Abc_TtStretch5( (unsigned *)p->pTemp1, nLeaves, p->nVars );
+p->timeCanon += Abc_Clock() - clk;
+        // pCanonPerm and uCanonPhase show what was the variable corresponding to each var in the current truth
+        if ( nLeaves == 2 && Abc_TtSupportSize(pTruth, 2) != 2 )
+            continue;
+
+clk = Abc_Clock();
+        // map cut leaves into elementary variables of GIA
+        for ( i = 0; i < nLeaves; i++ )
+            Gia_ManCi( pLib, pCanonPerm[i] )->Value = Abc_Var2Lit( Gia_ObjId(pGia, Gia_ManPi(pGia, i)), (uCanonPhase >> i) & 1 );
+        // build internal nodes
+        assert( Vec_IntSize(pLib->vTtNodes) > 0 );
+        Gia_ManForEachObjVec( pLib->vTtNodes, pLib, pTemp, i )
+        {
+            iFanin0 = Abc_LitNotCond( Gia_ObjFanin0(pTemp)->Value, Gia_ObjFaninC0(pTemp) );
+            iFanin1 = Abc_LitNotCond( Gia_ObjFanin1(pTemp)->Value, Gia_ObjFaninC1(pTemp) );
+            pTemp->Value = Gia_ManHashAnd( pGia, iFanin0, iFanin1 );
+        }
+p->timeBuild += Abc_Clock() - clk;
+
+        // check if this node is already driving a PO
+        assert( Gia_ObjIsAnd(pTemp) );
+        pDriver = Gia_ManObj(pGia, Abc_Lit2Var(pTemp->Value));
+        if ( pDriver->fMark1 )
+        {
+            p->nFilterSame++;
+            continue;
+        }
+        pDriver->fMark1 = 1;
+        // create output
+        Gia_ManAppendCo( pGia, Abc_LitNotCond( pTemp->Value, (uCanonPhase >> nLeaves) & 1 ) );
+
+        // verify truth table
+        if ( fCheck )
+        {
+clk = Abc_Clock();
+        pTemp = Gia_ManCo(pGia, Gia_ManCoNum(pGia)-1);
+        pTruth = Gia_ObjComputeTruthTable( pGia, Gia_ManCo(pGia, Gia_ManCoNum(pGia)-1) );
+p->timeCheck += Abc_Clock() - clk;
+        if ( memcmp( p->pTemp1, pTruth, p->nWords * sizeof(word) ) != 0 )
+        {
+    
+            Kit_DsdPrintFromTruth( (unsigned *)pTruth, nLeaves ); printf( "\n" );
+            Kit_DsdPrintFromTruth( (unsigned *)p->pTemp1, nLeaves ); printf( "\n" );
+            printf( "Truth table verification has failed.\n" );
+    
+            // drive PO with constant
+            Gia_ManPatchCoDriver( pGia, Gia_ManCoNum(pGia)-1, 0 );
+            // save truth table ID
+            Vec_IntPush( p->vTruthIds, -1 );
+            p->nFilterTruth++;
+            continue;
+        }
+        }
+
+clk = Abc_Clock();
+        // add the resulting truth table to the hash table 
+        Index = Vec_MemHashInsert( p->vTtMem, p->pTemp1 );
+        // save truth table ID
+        Vec_IntPush( p->vTruthIds, Index );
+        assert( Gia_ManCoNum(pGia) == Vec_IntSize(p->vTruthIds) );
+        p->nAdded++;
+p->timeInsert += Abc_Clock() - clk;
+    }
+    Vec_StrFree( vSupps );
+p->timeTotal += Abc_Clock() - clk2;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates one cut during library construction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRecAddCut3( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut )
+{
+    Lms_Man_t * p = s_pMan3;
+    char pCanonPerm[LMS_VAR_MAX];
+    unsigned uCanonPhase;
+    int i, Index, iFanin0, iFanin1, fHole;
+    int nLeaves = If_CutLeaveNum(pCut);
+    Vec_Ptr_t * vNodes = p->vNodes;
+    Gia_Man_t * pGia = p->pGia;
+    Gia_Obj_t * pDriver;
+    If_Obj_t * pIfObj = NULL;
+    word * pTruth;
+    abctime clk;
+    p->nTried++;
+
+    // skip small cuts
+    assert( p->nVars == (int)pCut->nLimit );
+    if ( nLeaves < 2 || (nLeaves == 2 && Abc_TtSupportSize(If_CutTruthW(pIfMan, pCut), 2) != 2) )
+    {
+        p->nFilterSize++;
+        return 1;
+    }
+
+//    if ( p->vTtMem2 )
+//        Vec_MemHashInsert( p->vTtMem2, If_CutTruthW(pCut) );
+
+    // semi-canonicize truth table
+clk = Abc_Clock();
+    memcpy( p->pTemp1, If_CutTruthW(pIfMan, pCut), p->nWords * sizeof(word) );
+#ifdef LMS_USE_OLD_FORM
+    uCanonPhase = Kit_TruthSemiCanonicize( (unsigned *)p->pTemp1, (unsigned *)p->pTemp2, nLeaves, pCanonPerm );
+#else
+    uCanonPhase = Abc_TtCanonicize( p->pTemp1, nLeaves, pCanonPerm );
+#endif
+    Abc_TtStretch5( (unsigned *)p->pTemp1, nLeaves, p->nVars );
+p->timeCanon += Abc_Clock() - clk;
+    // pCanonPerm and uCanonPhase show what was the variable corresponding to each var in the current truth
+
+    if ( p->pGia == NULL )
+    {
+clk = Abc_Clock();
+        // add the resulting truth table to the hash table 
+        Index = Vec_MemHashInsert( p->vTtMem, p->pTemp1 );
+/*
+        if ( p->vTruthFreqs == NULL )
+            p->vTruthFreqs = Vec_IntAlloc( 1000 );
+        assert( Index <= Vec_IntSize(p->vTruthFreqs)  );
+        if ( Index < Vec_IntSize(p->vTruthFreqs) )
+            Vec_IntAddToEntry( p->vTruthFreqs, Index, 1 );
+        else
+            Vec_IntPush( p->vTruthFreqs, 1 );
+*/
+        p->nAdded++;
+p->timeInsert += Abc_Clock() - clk;
+        return 1;
+    }
+
+    // collect internal nodes and skip redundant cuts
+clk = Abc_Clock();
+    If_CutTraverse( pIfMan, pRoot, pCut, vNodes );
+p->timeTruth += Abc_Clock() - clk;
+    if ( Vec_PtrSize(vNodes) > 253 )
+    {
+        p->nFilterSize++;
+        return 1;
+    }
+
+clk = Abc_Clock();
+    // map cut leaves into elementary variables of GIA
+    for ( i = 0; i < nLeaves; i++ )
+        If_ManObj( pIfMan, pCut->pLeaves[(int)pCanonPerm[i]] )->iCopy = Abc_Var2Lit( Gia_ObjId(pGia, Gia_ManPi(pGia, i)), (uCanonPhase >> i) & 1 );
+    // build internal nodes
+    fHole = 0;
+    assert( Vec_PtrSize(vNodes) > 0 );
+    Vec_PtrForEachEntryStart( If_Obj_t *, vNodes, pIfObj, i, nLeaves )
+    {
+        if ( If_ObjIsCi(pIfObj) )
+        {
+            pIfObj->iCopy = 0;
+            fHole = 1;
+            continue;
+        }
+        iFanin0 = Abc_LitNotCond( If_ObjFanin0(pIfObj)->iCopy, If_ObjFaninC0(pIfObj) );
+        iFanin1 = Abc_LitNotCond( If_ObjFanin1(pIfObj)->iCopy, If_ObjFaninC1(pIfObj) );
+        pIfObj->iCopy = Gia_ManHashAnd( pGia, iFanin0, iFanin1 );
+    }
+    p->nHoleInTheWall += fHole;
+p->timeBuild += Abc_Clock() - clk;
+
+    // check if this node is already driving a PO
+    assert( If_ObjIsAnd(pIfObj) );
+    pDriver = Gia_ManObj(pGia, Abc_Lit2Var(pIfObj->iCopy));
+    if ( pDriver->fMark1 )
+    {
+        p->nFilterSame++;
+        return 1;
+    }
+    pDriver->fMark1 = 1;
+    // create output
+    Gia_ManAppendCo( pGia, Abc_LitNotCond( pIfObj->iCopy, (uCanonPhase >> nLeaves) & 1 ) );
+
+    // verify truth table
+clk = Abc_Clock();
+    pTruth = Gia_ObjComputeTruthTable( pGia, Gia_ManCo(pGia, Gia_ManCoNum(pGia)-1) );
+p->timeCheck += Abc_Clock() - clk;
+    if ( memcmp( p->pTemp1, pTruth, p->nWords * sizeof(word) ) != 0 )
+    {
+/*
+        Kit_DsdPrintFromTruth( pTruth, nLeaves ); printf( "\n" );
+        Kit_DsdPrintFromTruth( (unsigned *)p->pTemp1, nLeaves ); printf( "\n" );
+        printf( "Truth table verification has failed.\n" );
+*/
+        // drive PO with constant
+        Gia_ManPatchCoDriver( pGia, Gia_ManCoNum(pGia)-1, 0 );
+        // save truth table ID
+        Vec_IntPush( p->vTruthIds, -1 );
+        p->nFilterTruth++;
+        return 1;
+    }
+
+clk = Abc_Clock();
+    // add the resulting truth table to the hash table 
+    Index = Vec_MemHashInsert( p->vTtMem, p->pTemp1 );
+    // save truth table ID
+    Vec_IntPush( p->vTruthIds, Index );
+    assert( Gia_ManCoNum(pGia) == Vec_IntSize(p->vTruthIds) );
+    p->nAdded++;
+p->timeInsert += Abc_Clock() - clk;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Top level procedure for library construction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkRecAdd3( Abc_Ntk_t * pNtk, int fUseSOPB )
+{
+    extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
+    If_Par_t Pars, * pPars = &Pars;
+    Abc_Ntk_t * pNtkNew;
+    int clk = Abc_Clock();
+    if ( Abc_NtkGetChoiceNum( pNtk ) )
+        printf( "Performing recoding structures with choices.\n" );
+    // remember that the manager was used for library construction
+    s_pMan3->fLibConstr = 1;
+    // create hash table if not available
+    if ( s_pMan3->pGia && s_pMan3->pGia->pHTable == NULL )
+        Gia_ManHashStart( s_pMan3->pGia );
+
+    // set defaults
+    memset( pPars, 0, sizeof(If_Par_t) );
+    // user-controlable paramters
+    pPars->nLutSize    =  s_pMan3->nVars;
+    pPars->nCutsMax    =  s_pMan3->nCuts;
+    pPars->DelayTarget = -1;
+    pPars->Epsilon     =  (float)0.005;
+    pPars->fArea       =  1;
+    // internal parameters
+    if ( fUseSOPB )
+    {
+        pPars->fTruth      =  1;
+        pPars->fCutMin     =  0;
+        pPars->fUsePerm    =  1; 
+        pPars->fDelayOpt   =  1;
+    }
+    else
+    {
+        pPars->fTruth      =  1;
+        pPars->fCutMin     =  1;
+        pPars->fUsePerm    =  0; 
+        pPars->fDelayOpt   =  0;
+    }
+    pPars->fSkipCutFilter = 0;
+    pPars->pFuncCost   =  NULL;
+    pPars->pFuncUser   =  Abc_NtkRecAddCut3;
+    // perform recording
+    pNtkNew = Abc_NtkIf( pNtk, pPars );
+    Abc_NtkDelete( pNtkNew );
+s_pMan3->timeTotal += Abc_Clock() - clk;
+}
+
+ /**Function*************************************************************
+
+  Synopsis    [Returns min AIG level at the output fo the cut using the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int If_CutComputeDelay( If_Man_t * p, If_Cut_t * pCut, char * pCanonPerm, word DelayProfile )
+{
+    If_Obj_t* pLeaf;
+    int nLeaves = If_CutLeaveNum(pCut);
+    int i, delayTemp, delayMax = -ABC_INFINITY;
+    for ( i = 0; i < nLeaves; i++ )
+    {
+        pLeaf     = If_ManObj(p, (pCut)->pLeaves[(int)pCanonPerm[i]]);
+        delayTemp = If_ObjCutBest(pLeaf)->Delay + Lms_DelayGet(DelayProfile, i);
+        delayMax  = Abc_MaxInt( delayMax, delayTemp );
+    }
+    return delayMax;
+}
+static inline int If_CutFindBestStruct( If_Man_t * pIfMan, If_Cut_t * pCut, char * pCanonPerm, unsigned * puCanonPhase, int * pBestPo )
+{
+    Lms_Man_t * p = s_pMan3;
+    int i, * pTruthId, iFirstPo, iFirstPoNext, iBestPo;
+    int BestDelay = ABC_INFINITY, BestArea = ABC_INFINITY, Delay, Area;
+    int uSupport, nLeaves = If_CutLeaveNum( pCut );
+    char * pPerm = If_CutPerm( pCut );
+    word DelayProfile;
+    abctime clk;
+    pCut->fUser = 1;
+    // compute support
+    uSupport = Abc_TtSupport( If_CutTruthW(pIfMan, pCut), nLeaves );
+    if ( uSupport == 0 )
+    {
+        pCut->Cost = 1;
+        for ( i = 0; i < nLeaves; i++ )
+            pPerm[i] = IF_BIG_CHAR;
+        return 0;
+    }
+    if ( !Abc_TtSuppIsMinBase(uSupport) || uSupport == 1 )
+    {
+        assert( Abc_TtSuppOnlyOne(uSupport) );
+        pCut->Cost = 1;
+        for ( i = 0; i < nLeaves; i++ )
+            pPerm[i] = IF_BIG_CHAR;
+        pPerm[Abc_TtSuppFindFirst(uSupport)] = 0;
+        return If_ObjCutBest(If_ManObj(pIfMan, pCut->pLeaves[Abc_TtSuppFindFirst(uSupport)]))->Delay;
+    }
+    assert( Gia_WordCountOnes(uSupport) == nLeaves );
+
+    // semicanonicize the function
+clk = Abc_Clock();
+    memcpy( p->pTemp1, If_CutTruthW(pIfMan, pCut), p->nWords * sizeof(word) );
+#ifdef LMS_USE_OLD_FORM
+    *puCanonPhase = Kit_TruthSemiCanonicize( (unsigned *)p->pTemp1, (unsigned *)p->pTemp2, nLeaves, pCanonPerm );
+#else
+    *puCanonPhase = Abc_TtCanonicize( p->pTemp1, nLeaves, pCanonPerm );
+#endif
+    Abc_TtStretch5( (unsigned *)p->pTemp1, nLeaves, p->nVars );
+p->timeCanon += Abc_Clock() - clk;
+
+    // get TT ID for the given class
+    pTruthId = Vec_MemHashLookup( p->vTtMem, p->pTemp1 );
+    if ( *pTruthId == -1 )
+    {
+        pCut->Cost = IF_COST_MAX;
+        pCut->fUseless = 1;
+        return ABC_INFINITY;
+    }
+
+    // note that array p->vTruthPo contains the first PO for the given truth table
+    // other POs belonging to the same equivalence class follow immediately after this one
+    // to iterate through the POs, we need to perform the following steps
+
+    // find the first PO of this class
+    iFirstPo = Vec_IntEntry( p->vTruthPo, *pTruthId );
+    // find the first PO of the next class
+    iFirstPoNext = Vec_IntEntry( p->vTruthPo, *pTruthId+1 );
+    // iterate through the subgraphs of this class
+    iBestPo = -1;
+    for ( i = iFirstPo; i < iFirstPoNext; i++ )
+    {
+        Delay = If_CutComputeDelay( pIfMan, pCut, pCanonPerm, Vec_WrdEntry(p->vDelays, i) );
+        Area  = Vec_StrEntry(p->vAreas, i);
+        if ( iBestPo == -1 || BestDelay > Delay || (BestDelay == Delay && BestArea > Area) )
+        {
+            iBestPo = i;
+            BestDelay = Delay;
+            BestArea = Area;
+        }
+    }
+    if ( pBestPo )
+        *pBestPo = iBestPo;
+
+    // mark as user cut.
+    DelayProfile = Vec_WrdEntry(p->vDelays, iBestPo);
+    pCut->Cost = Vec_StrEntry(p->vAreas, iBestPo);
+    for ( i = 0; i < nLeaves; i++ )
+        pPerm[(int)pCanonPerm[i]] = Lms_DelayGet(DelayProfile, i);
+    return BestDelay; 
+}
+int If_CutDelayRecCost3( If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pObj )
+{
+    Lms_Man_t * p = s_pMan3;
+    char pCanonPerm[LMS_VAR_MAX];
+    unsigned uCanonPhase;
+    // make sure the cut functions match the library
+    assert( p->nVars == (int)pCut->nLimit );
+    // if this assertion fires, it means that LMS manager was used for library construction
+    // in this case, GIA has to be written out and the manager restarted as described above
+    assert( !p->fLibConstr );
+    if ( p->vTruthPo == NULL )
+        Lms_ManPrepare( p );
+    // return the delay of the best structure
+    return If_CutFindBestStruct( pIfMan, pCut, pCanonPerm, &uCanonPhase, NULL );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reexpresses the best structure of the cut in the HOP manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Abc_RecToHop3( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj )
+{
+    Lms_Man_t * p = s_pMan3;
+    char pCanonPerm[LMS_VAR_MAX];
+    unsigned uCanonPhase;
+    Hop_Obj_t * pFan0, * pFan1, * pHopObj;
+    Gia_Man_t * pGia = p->pGia;
+    Gia_Obj_t * pGiaPo, * pGiaTemp = NULL;
+    int i, uSupport, BestPo = -1, nLeaves = If_CutLeaveNum(pCut);
+    assert( pIfMan->pPars->fCutMin == 1 );
+
+    // compute support
+    uSupport = Abc_TtSupport( If_CutTruthW(pIfMan, pCut), nLeaves );
+    if ( uSupport == 0 )
+        return Hop_NotCond( Hop_ManConst0(pMan), If_CutTruthIsCompl(pCut) );
+    if ( !Abc_TtSuppIsMinBase(uSupport) || uSupport == 1 )
+    {
+        assert( Abc_TtSuppOnlyOne(uSupport) );
+        return Hop_NotCond( Hop_IthVar(pMan, Abc_TtSuppFindFirst(uSupport)), If_CutTruthIsCompl(pCut) );
+    }
+    assert( Gia_WordCountOnes(uSupport) == nLeaves );
+
+    // get the best output for this node
+    If_CutFindBestStruct( pIfMan, pCut, pCanonPerm, &uCanonPhase, &BestPo );
+    assert( BestPo >= 0 );
+    pGiaPo = Gia_ManCo( pGia, BestPo );
+    // collect internal nodes into pGia->vTtNodes
+    if ( pGia->vTtNodes == NULL )
+        pGia->vTtNodes = Vec_IntAlloc( 256 );
+    assert( Gia_ObjIsAnd( Gia_ObjFanin0(pGiaPo) ) );
+    Gia_ObjCollectInternal( pGia, Gia_ObjFanin0(pGiaPo) );
+    assert( Vec_IntSize(pGia->vTtNodes) > 0 );
+
+    // collect HOP nodes for leaves
+    Vec_PtrClear( p->vLabelsP );
+    for ( i = 0; i < nLeaves; i++ )
+        Vec_PtrPush( p->vLabelsP, Hop_NotCond(Hop_IthVar(pMan, pCanonPerm[i]), (uCanonPhase >> i) & 1) );
+
+    // compute HOP nodes for internal nodes
+    Gia_ManForEachObjVec( pGia->vTtNodes, pGia, pGiaTemp, i )
+    {
+        pGiaTemp->fMark0 = 0; // unmark node marked by Gia_ObjCollectInternal()
+        if ( Gia_ObjIsAnd(Gia_ObjFanin0(pGiaTemp)) )
+            pFan0 = (Hop_Obj_t *)Vec_PtrEntry(p->vLabelsP, Gia_ObjNum(pGia, Gia_ObjFanin0(pGiaTemp)) + nLeaves);
+        else
+            pFan0 = (Hop_Obj_t *)Vec_PtrEntry(p->vLabelsP, Gia_ObjCioId(Gia_ObjFanin0(pGiaTemp)));
+        pFan0 = Hop_NotCond(pFan0, Gia_ObjFaninC0(pGiaTemp));
+        if ( Gia_ObjIsAnd(Gia_ObjFanin1(pGiaTemp)) )
+            pFan1 = (Hop_Obj_t *)Vec_PtrEntry(p->vLabelsP, Gia_ObjNum(pGia, Gia_ObjFanin1(pGiaTemp)) + nLeaves);
+        else
+            pFan1 = (Hop_Obj_t *)Vec_PtrEntry(p->vLabelsP, Gia_ObjCioId(Gia_ObjFanin1(pGiaTemp)));
+        pFan1 = Hop_NotCond(pFan1, Gia_ObjFaninC1(pGiaTemp));
+
+        pHopObj = Hop_And(pMan, pFan0, pFan1);
+        Vec_PtrPush(p->vLabelsP, pHopObj);
+    }
+    // get the final result
+    assert( Gia_ObjIsAnd(pGiaTemp) );
+    pHopObj = (Hop_Obj_t *)Vec_PtrEntry(p->vLabelsP, Gia_ObjNum(pGia, pGiaTemp) + nLeaves);
+    // complement the result if needed
+    return Hop_NotCond( pHopObj,  Gia_ObjFaninC0(pGiaPo) ^ ((uCanonPhase >> nLeaves) & 1) );    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reexpresses the best structure of the cut in the GIA manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_RecToGia3( Gia_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, Vec_Int_t * vLeaves, int fHash )
+{
+    Lms_Man_t * p = s_pMan3;
+    char pCanonPerm[LMS_VAR_MAX];
+    unsigned uCanonPhase;
+    int iFan0, iFan1, iGiaObj;
+    Gia_Man_t * pGia = p->pGia;
+    Gia_Obj_t * pGiaPo, * pGiaTemp = NULL;
+    int i, uSupport, BestPo = -1, nLeaves = If_CutLeaveNum(pCut);
+    assert( pIfMan->pPars->fCutMin == 1 );
+    assert( nLeaves == Vec_IntSize(vLeaves) );
+
+    // compute support
+    uSupport = Abc_TtSupport( If_CutTruthW(pIfMan, pCut), nLeaves );
+    if ( uSupport == 0 )
+        return Abc_LitNotCond( 0, If_CutTruthIsCompl(pCut) );
+    if ( !Abc_TtSuppIsMinBase(uSupport) || uSupport == 1 )
+    {
+        assert( Abc_TtSuppOnlyOne(uSupport) );
+        return Abc_LitNotCond( Vec_IntEntry(vLeaves, Abc_TtSuppFindFirst(uSupport)), If_CutTruthIsCompl(pCut) );
+    }
+    assert( Gia_WordCountOnes(uSupport) == nLeaves );
+
+    // get the best output for this node
+    If_CutFindBestStruct( pIfMan, pCut, pCanonPerm, &uCanonPhase, &BestPo );
+    assert( BestPo >= 0 );
+    pGiaPo = Gia_ManCo( pGia, BestPo );
+
+    // collect internal nodes into pGia->vTtNodes
+    if ( pGia->vTtNodes == NULL )
+        pGia->vTtNodes = Vec_IntAlloc( 256 );
+    assert( Gia_ObjIsAnd( Gia_ObjFanin0(pGiaPo) ) );
+    Gia_ObjCollectInternal( pGia, Gia_ObjFanin0(pGiaPo) );
+    assert( Vec_IntSize(pGia->vTtNodes) > 0 );
+
+    // collect GIA nodes for leaves
+    Vec_IntClear( p->vLabels );
+    for (i = 0; i < nLeaves; i++)
+        Vec_IntPush( p->vLabels, Abc_LitNotCond(Vec_IntEntry(vLeaves, pCanonPerm[i]), (uCanonPhase >> i) & 1) );
+
+    // compute HOP nodes for internal nodes
+    Gia_ManForEachObjVec( pGia->vTtNodes, pGia, pGiaTemp, i )
+    {
+        pGiaTemp->fMark0 = 0; // unmark node marked by Gia_ObjCollectInternal()
+        if ( Gia_ObjIsAnd(Gia_ObjFanin0(pGiaTemp)) )
+            iFan0 = Vec_IntEntry(p->vLabels, Gia_ObjNum(pGia, Gia_ObjFanin0(pGiaTemp)) + nLeaves);
+        else
+            iFan0 = Vec_IntEntry(p->vLabels, Gia_ObjCioId(Gia_ObjFanin0(pGiaTemp)));
+        iFan0 = Abc_LitNotCond(iFan0, Gia_ObjFaninC0(pGiaTemp));
+        if ( Gia_ObjIsAnd(Gia_ObjFanin1(pGiaTemp)) )
+            iFan1 = Vec_IntEntry(p->vLabels, Gia_ObjNum(pGia, Gia_ObjFanin1(pGiaTemp)) + nLeaves);
+        else
+            iFan1 = Vec_IntEntry(p->vLabels, Gia_ObjCioId(Gia_ObjFanin1(pGiaTemp)));
+        iFan1 = Abc_LitNotCond(iFan1, Gia_ObjFaninC1(pGiaTemp));
+        if ( fHash )
+            iGiaObj = Gia_ManHashAnd(pMan, iFan0, iFan1);
+        else
+            iGiaObj = Gia_ManAppendAnd(pMan, iFan0, iFan1);
+        Vec_IntPush(p->vLabels, iGiaObj);
+    }
+    // get the final result
+    assert( Gia_ObjIsAnd(pGiaTemp) );
+    iGiaObj = Vec_IntEntry(p->vLabels, Gia_ObjNum(pGia, pGiaTemp) + nLeaves);
+    // complement the result if needed
+    return Abc_LitNotCond( iGiaObj,  Gia_ObjFaninC0(pGiaPo) ^ ((uCanonPhase >> nLeaves) & 1) ^ pCut->fCompl );    
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces GIA to contain only useful COs and internal nodes.]
+
+  Description [During library construction, redundant nodes are added.
+  Some COs are found to be useless because their TT does not match the
+  (semi-canonicized TT) of the cut, etc.  This procedure reduces GIA
+  to contains only useful (non-redundant, non-dominated) COs and the
+  corresponding internal nodes. This procedure replaces GIA by a new GIA
+  and creates new vTruthIds. The COs with the same truth table have
+  adjacent IDs. This procedure does not change the truth tables.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+// count how many times TT occurs
+Vec_Int_t * Lms_GiaCountTruths( Lms_Man_t * p )
+{
+    Vec_Int_t * vCounts = Vec_IntStart( Vec_MemEntryNum(p->vTtMem) );
+    int i, Entry;
+    Vec_IntForEachEntry( p->vTruthIds, Entry, i )
+        if ( Entry >= 0 )
+            Vec_IntAddToEntry( vCounts, Entry, 1 );
+    return vCounts;
+}
+// collect PO indexes worth visiting
+Vec_Int_t * Lms_GiaCollectUsefulCos( Lms_Man_t * p )
+{
+    Vec_Int_t * vBegins = Vec_IntAlloc( Vec_MemEntryNum(p->vTtMem) );
+    Vec_Int_t * vUseful = Vec_IntStartFull( Gia_ManCoNum(p->pGia) + Vec_MemEntryNum(p->vTtMem) );
+    Vec_Int_t * vCounts = Lms_GiaCountTruths( p );
+    int i, Entry, * pPlace, SumTotal = 0;
+    // mark up the place for POs
+    Vec_IntForEachEntry( vCounts, Entry, i )
+    {
+        assert( Entry > 0 );
+        Vec_IntPush( vBegins, SumTotal );
+        SumTotal += Entry + 1;
+//        printf( "%d ", Entry );
+    }
+    Vec_IntPush( vBegins, SumTotal );
+    // fill out POs in their places
+    Vec_IntFill( vCounts, Vec_IntSize(vCounts), 0 );
+    Vec_IntForEachEntry( p->vTruthIds, Entry, i )
+    {
+        if ( Entry < 0 )
+            continue;
+        pPlace = Vec_IntEntryP( vUseful, Vec_IntEntry(vBegins, Entry) + Vec_IntEntry(vCounts, Entry) );
+        assert( *pPlace == -1 );
+        *pPlace = i;
+        Vec_IntAddToEntry( vCounts, Entry, 1 );
+    }
+    Vec_IntFree( vBegins );
+    Vec_IntFree( vCounts );
+    return vUseful;
+}
+// collect non-dominated COs
+Vec_Int_t * Lms_GiaFindNonRedundantCos( Lms_Man_t * p )
+{
+    Vec_Int_t * vRemain;
+    Vec_Int_t * vUseful;
+    Vec_Wrd_t * vDelays;
+    int i, k, EntryI, EntryK;
+    word D1, D2;
+    vDelays = Lms_GiaDelays( p->pGia );
+    vUseful = Lms_GiaCollectUsefulCos( p );
+    Vec_IntForEachEntry( vUseful, EntryI, i )
+    {
+        if ( EntryI < 0 )
+            continue;
+        D1 = Vec_WrdEntry(vDelays, EntryI);
+        assert( D1 > 0 );
+        Vec_IntForEachEntryStart( vUseful, EntryK, k, i+1 )
+        {
+            if ( EntryK == -1 )
+                break;
+            if ( EntryK == -2 )
+                continue;
+            D2 = Vec_WrdEntry(vDelays, EntryK);
+            assert( D2 > 0 );
+            if ( Lms_DelayDom(D1, D2, Gia_ManCiNum(p->pGia)) ) // D1 dominate D2
+            {
+                Vec_IntWriteEntry( vUseful, k, -2 );
+                continue;
+            }
+            if ( Lms_DelayDom(D2, D1, Gia_ManCiNum(p->pGia)) ) // D2 dominate D1
+            {
+                Vec_IntWriteEntry( vUseful, i, -2 );
+                break;
+            }
+        }
+    }
+
+    vRemain = Vec_IntAlloc( 1000 );
+    Vec_IntForEachEntry( vUseful, EntryI, i )
+        if ( EntryI >= 0 )
+            Vec_IntPush( vRemain, EntryI );
+    Vec_IntFree( vUseful );
+    Vec_WrdFree( vDelays );
+    return vRemain;
+}
+// replace GIA and vTruthIds by filtered ones
+void Lms_GiaNormalize( Lms_Man_t * p )
+{
+    Gia_Man_t * pGiaNew;
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vRemain;
+    Vec_Int_t * vTruthIdsNew;
+    int i, Entry, Prev = -1, Next;
+    // collect non-redundant COs
+    vRemain = Lms_GiaFindNonRedundantCos( p );
+    // change these to be useful literals
+    vTruthIdsNew = Vec_IntAlloc( Vec_IntSize(vRemain) );
+    Vec_IntForEachEntry( vRemain, Entry, i )
+    {
+        pObj = Gia_ManCo(p->pGia, Entry);
+        assert( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) );
+        Vec_IntWriteEntry( vRemain, i, Gia_ObjFaninLit0p(p->pGia, pObj) );
+        // create new truth IDs
+        Next = Vec_IntEntry(p->vTruthIds, Gia_ObjCioId(pObj));
+        assert( Prev <= Next );
+        Vec_IntPush( vTruthIdsNew, Next );
+        Prev = Next;
+    }
+    // create a new GIA
+    Gia_ManForEachObj( p->pGia, pObj, i )
+        assert( pObj->fMark0 == 0 );
+    for ( i = 0; i < Gia_ManCoNum(p->pGia); i++ )
+        Gia_ManPatchCoDriver( p->pGia, i, 0 );
+    Vec_IntForEachEntry( vRemain, Entry, i )
+        Gia_ManAppendCo( p->pGia, Entry );
+//    pGiaNew = Gia_ManCleanup( p->pGia );
+    pGiaNew = Gia_ManCleanupOutputs( p->pGia, Gia_ManCoNum(p->pGia) - Vec_IntSize(vRemain) );
+    Gia_ManStop( p->pGia );
+    p->pGia = pGiaNew;
+    Vec_IntFree( vRemain );
+    // update truth IDs
+    Vec_IntFree( p->vTruthIds );
+    p->vTruthIds = vTruthIdsNew;
+//    Vec_IntPrint( vTruthIdsNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRecTruthCompare( int * p1, int * p2 ) 
+{
+    int Diff = Vec_StrEntry( s_pMan3->vSupps, *p1 ) - Vec_StrEntry( s_pMan3->vSupps, *p2 );
+    if ( Diff )
+        return Diff;
+    return memcmp( Vec_MemReadEntry(s_pMan3->vTtMem, *p1), Vec_MemReadEntry(s_pMan3->vTtMem, *p2), sizeof(word) * s_pMan3->nWords ); 
+}
+void Abc_NtkRecDumpTt3( char * pFileName, int fBinary )
+{
+    FILE * pFile;
+    char pBuffer[1000];
+    Lms_Man_t * p = s_pMan3;
+    Vec_Int_t * vEntries;
+    word * pTruth;
+    int i, Entry, nVars = p->nVars;
+    int nEntries = Vec_MemEntryNum(p->vTtMem);
+    if ( nEntries == 0 )
+    {
+        printf( "There is not truth tables.\n" );
+        return;
+    }
+    pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "The file cannot be opened.\n" );
+        return;
+    }
+    p->vSupps = Vec_StrAlloc( nEntries );
+    Vec_MemForEachEntry( p->vTtMem, pTruth, i )
+        Vec_StrPush( p->vSupps, (char)Abc_TtSupportSize(pTruth, nVars) );
+    vEntries = Vec_IntStartNatural( nEntries );
+    qsort( (void *)Vec_IntArray(vEntries), nEntries, sizeof(int), (int(*)(const void *,const void *))Abc_NtkRecTruthCompare );
+    Vec_StrFreeP( &p->vSupps );
+    // write the file
+    Vec_IntForEachEntry( vEntries, Entry, i )
+    {
+        pTruth = Vec_MemReadEntry(p->vTtMem, Entry);
+        if ( fBinary )
+        {
+            fwrite( pTruth, 1, sizeof(word) * p->nWords, pFile );
+            continue;
+        }
+        Extra_PrintHex( pFile, (unsigned *)pTruth, nVars );
+        fprintf( pFile, "  " );
+//        Kit_DsdWriteFromTruth( pBuffer, (unsigned *)pTruth, nVars );
+        Dau_DsdDecompose( pTruth, p->nVars, 0, (int)(nVars <= 10), pBuffer );
+        fprintf( pFile, "%s\n", pBuffer );
+    }
+    fclose( pFile );
+    Vec_IntFree( vEntries );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRecInputNum3()
+{
+    return Gia_ManCiNum(s_pMan3->pGia);
+}
+int Abc_NtkRecIsRunning3()
+{
+    return s_pMan3 != NULL;
+}
+Gia_Man_t * Abc_NtkRecGetGia3()
+{
+    abctime clk = Abc_Clock();
+    printf( "Before normalizing: Library has %d classes and %d AIG subgraphs with %d AND nodes.\n", 
+        Vec_MemEntryNum(s_pMan3->vTtMem), Gia_ManPoNum(s_pMan3->pGia), Gia_ManAndNum(s_pMan3->pGia) );
+    Lms_GiaNormalize( s_pMan3 );
+    printf( "After normalizing:  Library has %d classes and %d AIG subgraphs with %d AND nodes.\n", 
+        Vec_MemEntryNum(s_pMan3->vTtMem), Gia_ManPoNum(s_pMan3->pGia), Gia_ManAndNum(s_pMan3->pGia) );
+    Abc_PrintTime( 1, "Normalization runtime", Abc_Clock() - clk );
+    s_pMan3->fLibConstr = 0;
+    return s_pMan3->pGia;
+}
+void Abc_NtkRecPs3(int fPrintLib)
+{
+    Lms_ManPrint( s_pMan3 );
+}
+void Abc_NtkRecStart3( Gia_Man_t * p, int nVars, int nCuts, int fFuncOnly, int fVerbose )
+{
+    assert( s_pMan3 == NULL );
+    s_pMan3 = Lms_ManStart( p, nVars, nCuts, fFuncOnly, fVerbose );
+}
+
+void Abc_NtkRecStop3()
+{
+    assert( s_pMan3 != NULL );
+    Lms_ManStop( s_pMan3 );
+    s_pMan3 = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/base/abci/abcReconv.c b/abc-build/src/base/abci/abcReconv.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcReconv.c
@@ -0,0 +1,769 @@
+/**CFile****************************************************************
+
+  FileName    [abcReconv.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Computation of reconvergence-driven cuts.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcReconv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+struct Abc_ManCut_t_
+{
+    // user specified parameters
+    int              nNodeSizeMax;  // the limit on the size of the supernode
+    int              nConeSizeMax;  // the limit on the size of the containing cone
+    int              nNodeFanStop;  // the limit on the size of the supernode
+    int              nConeFanStop;  // the limit on the size of the containing cone
+    // internal parameters
+    Vec_Ptr_t *      vNodeLeaves;   // fanins of the collapsed node (the cut)
+    Vec_Ptr_t *      vConeLeaves;   // fanins of the containing cone
+    Vec_Ptr_t *      vVisited;      // the visited nodes
+    Vec_Vec_t *      vLevels;       // the data structure to compute TFO nodes
+    Vec_Ptr_t *      vNodesTfo;     // the nodes in the TFO of the cut
+};
+
+static int   Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit );
+static int   Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit );
+static void  Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Unmarks the TFI cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_NodesMark( Vec_Ptr_t * vVisited )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
+        pNode->fMarkA = 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Unmarks the TFI cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_NodesUnmark( Vec_Ptr_t * vVisited )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
+        pNode->fMarkA = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Unmarks the TFI cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_NodesUnmarkB( Vec_Ptr_t * vVisited )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
+        pNode->fMarkB = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluate the cost of removing the node from the set of leaves.]
+
+  Description [Returns the number of new leaves that will be brought in.
+  Returns large number if the node cannot be removed from the set of leaves.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_NodeGetLeafCostOne( Abc_Obj_t * pNode, int nFaninLimit )
+{
+    int Cost;
+    // make sure the node is in the construction zone
+    assert( pNode->fMarkB == 1 );  
+    // cannot expand over the PI node
+    if ( Abc_ObjIsCi(pNode) )
+        return 999;
+    // get the cost of the cone
+    Cost = (!Abc_ObjFanin0(pNode)->fMarkB) + (!Abc_ObjFanin1(pNode)->fMarkB);
+    // always accept if the number of leaves does not increase
+    if ( Cost < 2 )
+        return Cost;
+    // skip nodes with many fanouts
+    if ( Abc_ObjFanoutNum(pNode) > nFaninLimit )
+        return 999;
+    // return the number of nodes that will be on the leaves if this node is removed
+    return Cost;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluate the cost of removing the node from the set of leaves.]
+
+  Description [Returns the number of new leaves that will be brought in.
+  Returns large number if the node cannot be removed from the set of leaves.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_NodeGetLeafCostTwo( Abc_Obj_t * pNode, int nFaninLimit, 
+    Abc_Obj_t ** ppLeafToAdd, Abc_Obj_t ** pNodeToMark1, Abc_Obj_t ** pNodeToMark2 )
+{
+    Abc_Obj_t * pFanin0, * pFanin1, * pTemp;
+    Abc_Obj_t * pGrand, * pGrandToAdd;
+    // make sure the node is in the construction zone
+    assert( pNode->fMarkB == 1 );  
+    // cannot expand over the PI node
+    if ( Abc_ObjIsCi(pNode) )
+        return 999;
+    // skip nodes with many fanouts
+//    if ( Abc_ObjFanoutNum(pNode) > nFaninLimit )
+//        return 999;
+    // get the children
+    pFanin0 = Abc_ObjFanin0(pNode);
+    pFanin1 = Abc_ObjFanin1(pNode);
+    assert( !pFanin0->fMarkB && !pFanin1->fMarkB );
+    // count the number of unique grandchildren that will be included
+    // return infinite cost if this number if more than 1
+    if ( Abc_ObjIsCi(pFanin0) && Abc_ObjIsCi(pFanin1) )
+        return 999;
+    // consider the special case when a non-CI fanin can be dropped
+    if ( !Abc_ObjIsCi(pFanin0) && Abc_ObjFanin0(pFanin0)->fMarkB && Abc_ObjFanin1(pFanin0)->fMarkB )
+    {
+        *ppLeafToAdd  = pFanin1;
+        *pNodeToMark1 = pFanin0;
+        *pNodeToMark2 = NULL;
+        return 1;
+    }
+    if ( !Abc_ObjIsCi(pFanin1) && Abc_ObjFanin0(pFanin1)->fMarkB && Abc_ObjFanin1(pFanin1)->fMarkB )
+    {
+        *ppLeafToAdd  = pFanin0;
+        *pNodeToMark1 = pFanin1;
+        *pNodeToMark2 = NULL;
+        return 1;
+    }
+
+    // make the first node CI if any
+    if ( Abc_ObjIsCi(pFanin1) )
+        pTemp = pFanin0, pFanin0 = pFanin1, pFanin1 = pTemp;
+    // consider the first node
+    pGrandToAdd = NULL;
+    if ( Abc_ObjIsCi(pFanin0) )
+    {
+        *pNodeToMark1 = NULL;
+        pGrandToAdd = pFanin0;
+    }
+    else
+    {
+        *pNodeToMark1 = pFanin0;
+        pGrand = Abc_ObjFanin0(pFanin0);
+        if ( !pGrand->fMarkB )
+        {
+            if ( pGrandToAdd && pGrandToAdd != pGrand )
+                return 999;
+            pGrandToAdd = pGrand;
+        }
+        pGrand = Abc_ObjFanin1(pFanin0);
+        if ( !pGrand->fMarkB )
+        {
+            if ( pGrandToAdd && pGrandToAdd != pGrand )
+                return 999;
+            pGrandToAdd = pGrand;
+        }
+    }
+    // consider the second node
+    *pNodeToMark2 = pFanin1;
+    pGrand = Abc_ObjFanin0(pFanin1);
+    if ( !pGrand->fMarkB )
+    {
+        if ( pGrandToAdd && pGrandToAdd != pGrand )
+            return 999;
+        pGrandToAdd = pGrand;
+    }
+    pGrand = Abc_ObjFanin1(pFanin1);
+    if ( !pGrand->fMarkB )
+    {
+        if ( pGrandToAdd && pGrandToAdd != pGrand )
+            return 999;
+        pGrandToAdd = pGrand;
+    }
+    assert( pGrandToAdd != NULL );
+    *ppLeafToAdd = pGrandToAdd;
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds a fanin-limited, reconvergence-driven cut for the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, int fContain )
+{
+    Abc_Obj_t * pNode;
+    int i;
+
+    assert( !Abc_ObjIsComplement(pRoot) );
+    assert( Abc_ObjIsNode(pRoot) );
+
+    // start the visited nodes and mark them
+    Vec_PtrClear( p->vVisited );
+    Vec_PtrPush( p->vVisited, pRoot );
+    Vec_PtrPush( p->vVisited, Abc_ObjFanin0(pRoot) );
+    Vec_PtrPush( p->vVisited, Abc_ObjFanin1(pRoot) );
+    pRoot->fMarkB = 1;
+    Abc_ObjFanin0(pRoot)->fMarkB = 1;
+    Abc_ObjFanin1(pRoot)->fMarkB = 1;
+
+    // start the cut 
+    Vec_PtrClear( p->vNodeLeaves );
+    Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin0(pRoot) );
+    Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin1(pRoot) );
+
+    // compute the cut
+    while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vNodeLeaves, p->nNodeSizeMax, p->nNodeFanStop ) );
+    assert( Vec_PtrSize(p->vNodeLeaves) <= p->nNodeSizeMax );
+
+    // return if containing cut is not requested
+    if ( !fContain )
+    {
+        // unmark both fMarkA and fMarkB in tbe TFI
+        Abc_NodesUnmarkB( p->vVisited );
+        return p->vNodeLeaves;
+    }
+
+//printf( "\n\n\n" );
+    // compute the containing cut
+    assert( p->nNodeSizeMax < p->nConeSizeMax );
+    // copy the current boundary
+    Vec_PtrClear( p->vConeLeaves );
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodeLeaves, pNode, i )
+        Vec_PtrPush( p->vConeLeaves, pNode );
+    // compute the containing cut
+    while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vConeLeaves, p->nConeSizeMax, p->nConeFanStop ) );
+    assert( Vec_PtrSize(p->vConeLeaves) <= p->nConeSizeMax );
+    // unmark TFI using fMarkA and fMarkB
+    Abc_NodesUnmarkB( p->vVisited );
+    return p->vNodeLeaves;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Builds reconvergence-driven cut by changing one leaf at a time.]
+
+  Description [This procedure looks at the current leaves and tries to change 
+  one leaf at a time in such a way that the cut grows as little as possible.
+  In evaluating the fanins, this procedure looks only at their immediate 
+  predecessors (this is why it is called a one-level construction procedure).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit )
+{
+    Abc_Obj_t * pNode, * pFaninBest, * pNext;
+    int CostBest, CostCur, i;
+    // find the best fanin
+    CostBest   = 100;
+    pFaninBest = NULL;
+//printf( "Evaluating fanins of the cut:\n" );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i )
+    {
+        CostCur = Abc_NodeGetLeafCostOne( pNode, nFaninLimit );
+//printf( "    Fanin %s has cost %d.\n", Abc_ObjName(pNode), CostCur );
+//        if ( CostBest > CostCur ) // performance improvement: expand the variable with the smallest level
+        if ( CostBest > CostCur ||
+             (CostBest == CostCur && pNode->Level > pFaninBest->Level) )
+        {
+            CostBest   = CostCur;
+            pFaninBest = pNode;
+        }
+        if ( CostBest == 0 )
+            break;
+    }
+    if ( pFaninBest == NULL )
+        return 0;
+//        return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit );
+
+    assert( CostBest < 3 );
+    if ( vLeaves->nSize - 1 + CostBest > nSizeLimit )
+        return 0;
+//        return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit );
+
+    assert( Abc_ObjIsNode(pFaninBest) );
+    // remove the node from the array
+    Vec_PtrRemove( vLeaves, pFaninBest );
+//printf( "Removing fanin %s.\n", Abc_ObjName(pFaninBest) );
+
+    // add the left child to the fanins
+    pNext = Abc_ObjFanin0(pFaninBest);
+    if ( !pNext->fMarkB )
+    {
+//printf( "Adding fanin %s.\n", Abc_ObjName(pNext) );
+        pNext->fMarkB = 1;
+        Vec_PtrPush( vLeaves, pNext );
+        Vec_PtrPush( vVisited, pNext );
+    }
+    // add the right child to the fanins
+    pNext = Abc_ObjFanin1(pFaninBest);
+    if ( !pNext->fMarkB )
+    {
+//printf( "Adding fanin %s.\n", Abc_ObjName(pNext) );
+        pNext->fMarkB = 1;
+        Vec_PtrPush( vLeaves, pNext );
+        Vec_PtrPush( vVisited, pNext );
+    }
+    assert( vLeaves->nSize <= nSizeLimit );
+    // keep doing this
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Builds reconvergence-driven cut by changing one leaf at a time.]
+
+  Description [This procedure looks at the current leaves and tries to change 
+  one leaf at a time in such a way that the cut grows as little as possible.
+  In evaluating the fanins, this procedure looks across two levels of fanins
+  (this is why it is called a two-level construction procedure).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit )
+{
+    Abc_Obj_t * pNode = NULL, * pLeafToAdd, * pNodeToMark1, * pNodeToMark2;
+    int CostCur = 0, i;
+    // find the best fanin
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i )
+    {
+        CostCur = Abc_NodeGetLeafCostTwo( pNode, nFaninLimit, &pLeafToAdd, &pNodeToMark1, &pNodeToMark2 );
+        if ( CostCur < 2 )
+            break;
+    }
+    if ( CostCur > 2 )
+        return 0;
+    // remove the node from the array
+    Vec_PtrRemove( vLeaves, pNode );
+    // add the node to the leaves
+    if ( pLeafToAdd )
+    {
+        assert( !pLeafToAdd->fMarkB );
+        pLeafToAdd->fMarkB = 1;
+        Vec_PtrPush( vLeaves, pLeafToAdd );
+        Vec_PtrPush( vVisited, pLeafToAdd );
+    }
+    // mark the other nodes
+    if ( pNodeToMark1 )
+    {
+        assert( !pNodeToMark1->fMarkB );
+        pNodeToMark1->fMarkB = 1;
+        Vec_PtrPush( vVisited, pNodeToMark1 );
+    }
+    if ( pNodeToMark2 )
+    {
+        assert( !pNodeToMark2->fMarkB );
+        pNodeToMark2->fMarkB = 1;
+        Vec_PtrPush( vVisited, pNodeToMark2 );
+    }
+    // keep doing this
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Get the nodes contained in the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeConeCollect( Abc_Obj_t ** ppRoots, int nRoots, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited, int fIncludeFanins )
+{
+    Abc_Obj_t * pTemp;
+    int i;
+    // mark the fanins of the cone
+    Abc_NodesMark( vLeaves );
+    // collect the nodes in the DFS order
+    Vec_PtrClear( vVisited );
+    // add the fanins
+    if ( fIncludeFanins )
+        Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pTemp, i )
+            Vec_PtrPush( vVisited, pTemp );
+    // add other nodes
+    for ( i = 0; i < nRoots; i++ )
+        Abc_NodeConeMarkCollect_rec( ppRoots[i], vVisited );
+    // unmark both sets
+    Abc_NodesUnmark( vLeaves );
+    Abc_NodesUnmark( vVisited );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the TFI cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited )
+{
+    if ( pNode->fMarkA == 1 )
+        return;
+    // visit transitive fanin 
+    if ( Abc_ObjIsNode(pNode) )
+    {
+        Abc_NodeConeMarkCollect_rec( Abc_ObjFanin0(pNode), vVisited );
+        Abc_NodeConeMarkCollect_rec( Abc_ObjFanin1(pNode), vVisited );
+    }
+    assert( pNode->fMarkA == 0 );
+    pNode->fMarkA = 1;
+    Vec_PtrPush( vVisited, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns BDD representing the logic function of the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited )
+{
+    Abc_Obj_t * pNode;
+    DdNode * bFunc0, * bFunc1, * bFunc = NULL;
+    int i;
+    // get the nodes in the cut without fanins in the DFS order
+    Abc_NodeConeCollect( &pRoot, 1, vLeaves, vVisited, 0 );
+    // set the elementary BDDs
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i )
+        pNode->pCopy = (Abc_Obj_t *)pbVars[i];
+    // compute the BDDs for the collected nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
+    {
+        assert( !Abc_ObjIsPi(pNode) );
+        bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) );
+        bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, (int)Abc_ObjFaninC1(pNode) );
+        bFunc  = Cudd_bddAnd( dd, bFunc0, bFunc1 );    Cudd_Ref( bFunc );
+        pNode->pCopy = (Abc_Obj_t *)bFunc;
+    }
+    assert(bFunc);
+    Cudd_Ref( bFunc );
+    // dereference the intermediate ones
+    Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
+        Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy );
+    Cudd_Deref( bFunc );
+    return bFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns BDD representing the transition relation of the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, DdNode ** pbVarsY, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, Vec_Ptr_t * vVisited )
+{
+    DdNode * bFunc0, * bFunc1, * bFunc, * bTrans, * bTemp, * bCube, * bResult;
+    Abc_Obj_t * pNode;
+    int i;
+    // get the nodes in the cut without fanins in the DFS order
+    Abc_NodeConeCollect( (Abc_Obj_t **)vRoots->pArray, vRoots->nSize, vLeaves, vVisited, 0 );
+    // set the elementary BDDs
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i )
+        pNode->pCopy = (Abc_Obj_t *)pbVarsX[i];
+    // compute the BDDs for the collected nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
+    {
+        bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) );
+        bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, (int)Abc_ObjFaninC1(pNode) );
+        bFunc  = Cudd_bddAnd( dd, bFunc0, bFunc1 );    Cudd_Ref( bFunc );
+        pNode->pCopy = (Abc_Obj_t *)bFunc;
+    }
+    // compute the transition relation of the cone
+    bTrans = b1;    Cudd_Ref( bTrans );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pNode, i )
+    {
+        bFunc = Cudd_bddXnor( dd, (DdNode *)pNode->pCopy, pbVarsY[i] );  Cudd_Ref( bFunc );
+		bTrans = Cudd_bddAnd( dd, bTemp = bTrans, bFunc );               Cudd_Ref( bTrans );
+		Cudd_RecursiveDeref( dd, bTemp );
+		Cudd_RecursiveDeref( dd, bFunc );
+    }
+    // dereference the intermediate ones
+    Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
+        Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy );
+    // compute don't-cares
+    bCube = Extra_bddComputeRangeCube( dd, vRoots->nSize, vRoots->nSize + vLeaves->nSize );  Cudd_Ref( bCube );
+    bResult = Cudd_bddExistAbstract( dd, bTrans, bCube );                Cudd_Ref( bResult );
+    bResult = Cudd_Not( bResult );
+	Cudd_RecursiveDeref( dd, bCube );
+	Cudd_RecursiveDeref( dd, bTrans );
+    Cudd_Deref( bResult );
+    return bResult;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Starts the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop )
+{
+    Abc_ManCut_t * p;
+    p = ABC_ALLOC( Abc_ManCut_t, 1 );
+    memset( p, 0, sizeof(Abc_ManCut_t) );
+    p->vNodeLeaves  = Vec_PtrAlloc( 100 );
+    p->vConeLeaves  = Vec_PtrAlloc( 100 );
+    p->vVisited     = Vec_PtrAlloc( 100 );
+    p->vLevels      = Vec_VecAlloc( 100 );
+    p->vNodesTfo    = Vec_PtrAlloc( 100 );
+    p->nNodeSizeMax = nNodeSizeMax;
+    p->nConeSizeMax = nConeSizeMax;
+    p->nNodeFanStop = nNodeFanStop;
+    p->nConeFanStop = nConeFanStop;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkManCutStop( Abc_ManCut_t * p )
+{
+    Vec_PtrFree( p->vNodeLeaves );
+    Vec_PtrFree( p->vConeLeaves );
+    Vec_PtrFree( p->vVisited    );
+    Vec_VecFree( p->vLevels );
+    Vec_PtrFree( p->vNodesTfo );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the leaves of the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p )
+{
+    return p->vConeLeaves;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the leaves of the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkManCutReadCutSmall( Abc_ManCut_t * p )
+{
+    return p->vNodeLeaves;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the leaves of the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkManCutReadVisited( Abc_ManCut_t * p )
+{
+    return p->vVisited;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the TFO of the cut in the topological order.]
+
+  Description [TFO of the cut is defined as a set of nodes, for which the cut
+  is a cut, that is, every path from the collected nodes to the CIs goes through 
+  a node in the cut. The nodes are collected if their level does not exceed
+  the given number (LevelMax). The nodes are returned in the topological order.
+  If the root node is given, its MFFC is marked, so that the collected nodes
+  do not contain any nodes in the MFFC.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int LevelMax )
+{
+    Abc_Ntk_t * pNtk = pRoot->pNtk;
+    Vec_Ptr_t * vVec;
+    Abc_Obj_t * pNode, * pFanout;
+    int i, k, v, LevelMin;
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    // assuming that the structure is clean
+    Vec_VecForEachLevel( p->vLevels, vVec, i )
+        assert( vVec->nSize == 0 );
+
+    // put fanins into the structure while labeling them
+    Abc_NtkIncrementTravId( pNtk );
+    LevelMin = -1;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i )
+    {
+        if ( pNode->Level > (unsigned)LevelMax )
+            continue;
+        Abc_NodeSetTravIdCurrent( pNode );
+        Vec_VecPush( p->vLevels, pNode->Level, pNode );
+        if ( LevelMin < (int)pNode->Level )
+            LevelMin = pNode->Level;
+    }
+    assert( LevelMin >= 0 );
+
+    // mark MFFC 
+    if ( pRoot )
+        Abc_NodeMffcLabelAig( pRoot );
+
+    // go through the levels up
+    Vec_PtrClear( p->vNodesTfo );
+    Vec_VecForEachEntryStart( Abc_Obj_t *, p->vLevels, pNode, i, k, LevelMin )
+    {
+        if ( i > LevelMax )
+            break;
+        // if the node is not marked, it is not a fanin
+        if ( !Abc_NodeIsTravIdCurrent(pNode) )
+        {
+            // check if it belongs to the TFO
+            if ( !Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pNode)) || 
+                 !Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pNode)) )
+                 continue;
+            // save the node in the TFO and label it
+            Vec_PtrPush( p->vNodesTfo, pNode );
+            Abc_NodeSetTravIdCurrent( pNode );
+        }
+        // go through the fanouts and add them to the structure if they meet the conditions
+        Abc_ObjForEachFanout( pNode, pFanout, v )
+        {
+            // skip if fanout is a CO or its level exceeds
+            if ( Abc_ObjIsCo(pFanout) || pFanout->Level > (unsigned)LevelMax )
+                continue;
+            // skip if it is already added or if it is in MFFC
+            if ( Abc_NodeIsTravIdCurrent(pFanout) )
+                continue;
+            // add it to the structure but do not mark it (until tested later)
+            Vec_VecPushUnique( p->vLevels, pFanout->Level, pFanout );
+        }
+    }
+
+    // clear the levelized structure
+    Vec_VecForEachLevelStart( p->vLevels, vVec, i, LevelMin )
+    {
+        if ( i > LevelMax )
+            break;
+        Vec_PtrClear( vVec );
+    }
+    return p->vNodesTfo;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcRefactor.c b/abc-build/src/base/abci/abcRefactor.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcRefactor.c
@@ -0,0 +1,391 @@
+/**CFile****************************************************************
+
+  FileName    [abcRefactor.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Resynthesis based on collapsing and refactoring.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcRefactor.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "bool/dec/dec.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+typedef struct Abc_ManRef_t_   Abc_ManRef_t;
+struct Abc_ManRef_t_
+{
+    // user specified parameters
+    int              nNodeSizeMax;      // the limit on the size of the supernode
+    int              nConeSizeMax;      // the limit on the size of the containing cone
+    int              fVerbose;          // the verbosity flag
+    // internal data structures
+    DdManager *      dd;                // the BDD manager
+    Vec_Str_t *      vCube;             // temporary
+    Vec_Int_t *      vForm;             // temporary
+    Vec_Ptr_t *      vVisited;          // temporary
+    Vec_Ptr_t *      vLeaves;           // temporary
+    // node statistics
+    int              nLastGain;
+    int              nNodesConsidered;
+    int              nNodesRefactored;
+    int              nNodesGained;
+    int              nNodesBeg;
+    int              nNodesEnd;
+    // runtime statistics
+    abctime          timeCut;
+    abctime          timeBdd;
+    abctime          timeDcs;
+    abctime          timeSop;
+    abctime          timeFact;
+    abctime          timeEval;
+    abctime          timeRes;
+    abctime          timeNtk;
+    abctime          timeTotal;
+};
+ 
+static void           Abc_NtkManRefPrintStats( Abc_ManRef_t * p );
+static Abc_ManRef_t * Abc_NtkManRefStart( int nNodeSizeMax, int nConeSizeMax, int fUseDcs, int fVerbose );
+static void           Abc_NtkManRefStop( Abc_ManRef_t * p );
+static Dec_Graph_t *  Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs incremental resynthesis of the AIG.]
+
+  Description [Starting from each node, computes a reconvergence-driven cut, 
+  derives BDD of the cut function, constructs ISOP, factors the ISOP, 
+  and replaces the current implementation of the MFFC of the node by the 
+  new factored form, if the number of AIG nodes is reduced and the total
+  number of levels of the AIG network is not increated. Returns the
+  number of AIG nodes saved.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose )
+{
+    extern void           Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain );
+    ProgressBar * pProgress;
+    Abc_ManRef_t * pManRef;
+    Abc_ManCut_t * pManCut;
+    Dec_Graph_t * pFForm;
+    Vec_Ptr_t * vFanins;
+    Abc_Obj_t * pNode;
+    abctime clk, clkStart = Abc_Clock();
+    int i, nNodes;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    // cleanup the AIG
+    Abc_AigCleanup((Abc_Aig_t *)pNtk->pManFunc);
+    // start the managers
+    pManCut = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, 1000 );
+    pManRef = Abc_NtkManRefStart( nNodeSizeMax, nConeSizeMax, fUseDcs, fVerbose );
+    pManRef->vLeaves   = Abc_NtkManCutReadCutLarge( pManCut );
+    // compute the reverse levels if level update is requested
+    if ( fUpdateLevel )
+        Abc_NtkStartReverseLevels( pNtk, 0 );
+
+    // resynthesize each node once
+    pManRef->nNodesBeg = Abc_NtkNodeNum(pNtk);
+    nNodes = Abc_NtkObjNumMax(pNtk);
+    pProgress = Extra_ProgressBarStart( stdout, nNodes );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        // skip the constant node
+//        if ( Abc_NodeIsConst(pNode) )
+//            continue;
+        // skip persistant nodes
+        if ( Abc_NodeIsPersistant(pNode) )
+            continue;
+        // skip the nodes with many fanouts
+        if ( Abc_ObjFanoutNum(pNode) > 1000 )
+            continue;
+        // stop if all nodes have been tried once
+        if ( i >= nNodes )
+            break;
+        // compute a reconvergence-driven cut
+clk = Abc_Clock();
+        vFanins = Abc_NodeFindCut( pManCut, pNode, fUseDcs );
+pManRef->timeCut += Abc_Clock() - clk;
+        // evaluate this cut
+clk = Abc_Clock();
+        pFForm = Abc_NodeRefactor( pManRef, pNode, vFanins, fUpdateLevel, fUseZeros, fUseDcs, fVerbose );
+pManRef->timeRes += Abc_Clock() - clk;
+        if ( pFForm == NULL )
+            continue;
+        // acceptable replacement found, update the graph
+clk = Abc_Clock();
+        Dec_GraphUpdateNetwork( pNode, pFForm, fUpdateLevel, pManRef->nLastGain );
+pManRef->timeNtk += Abc_Clock() - clk;
+        Dec_GraphFree( pFForm );
+//    {
+//        extern int s_TotalChanges;
+//        s_TotalChanges++;
+//    }
+    }
+    Extra_ProgressBarStop( pProgress );
+pManRef->timeTotal = Abc_Clock() - clkStart;
+    pManRef->nNodesEnd = Abc_NtkNodeNum(pNtk);
+
+    // print statistics of the manager
+    if ( fVerbose )
+        Abc_NtkManRefPrintStats( pManRef );
+    // delete the managers
+    Abc_NtkManCutStop( pManCut );
+    Abc_NtkManRefStop( pManRef );
+    // put the nodes into the DFS order and reassign their IDs
+    Abc_NtkReassignIds( pNtk );
+//    Abc_AigCheckFaninOrder( pNtk->pManFunc );
+    // fix the levels
+    if ( fUpdateLevel )
+        Abc_NtkStopReverseLevels( pNtk );
+    else
+        Abc_NtkLevel( pNtk );
+    // check
+    if ( !Abc_NtkCheck( pNtk ) )
+    {
+        printf( "Abc_NtkRefactor: The network check has failed.\n" );
+        return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resynthesizes the node using refactoring.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose )
+{
+    extern DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited );
+    extern DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, DdNode ** pbVarsY, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, Vec_Ptr_t * vVisited );
+    extern char * Abc_ConvertBddToSop( Mem_Flex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, int fAllPrimes, Vec_Str_t * vCube, int fMode );
+    extern int    Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax );
+    int fVeryVerbose = 0;
+    Abc_Obj_t * pFanin;
+    Dec_Graph_t * pFForm;
+    DdNode * bNodeFunc;
+    int nNodesSaved, nNodesAdded, i;
+    abctime clk;
+    char * pSop;
+    int Required;
+
+    Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY;
+
+    p->nNodesConsidered++;
+
+    // get the function of the cut
+clk = Abc_Clock();
+    bNodeFunc = Abc_NodeConeBdd( p->dd, p->dd->vars, pNode, vFanins, p->vVisited );  Cudd_Ref( bNodeFunc );
+p->timeBdd += Abc_Clock() - clk;
+
+    // if don't-care are used, transform the function into ISOP
+    if ( fUseDcs )
+    {
+        DdNode * bNodeDc, * bNodeOn, * bNodeOnDc;
+        int nMints, nMintsDc;
+clk = Abc_Clock();
+        // get the don't-cares
+        bNodeDc = Abc_NodeConeDcs( p->dd, p->dd->vars + vFanins->nSize, p->dd->vars, p->vLeaves, vFanins, p->vVisited ); Cudd_Ref( bNodeDc );
+        nMints = (1 << vFanins->nSize);
+        nMintsDc = (int)Cudd_CountMinterm( p->dd, bNodeDc, vFanins->nSize );
+//        printf( "Percentage of minterms = %5.2f.\n", 100.0 * nMintsDc / nMints );
+        // get the ISF
+        bNodeOn   = Cudd_bddAnd( p->dd, bNodeFunc, Cudd_Not(bNodeDc) );   Cudd_Ref( bNodeOn );
+        bNodeOnDc = Cudd_bddOr ( p->dd, bNodeFunc, bNodeDc );             Cudd_Ref( bNodeOnDc );
+        Cudd_RecursiveDeref( p->dd, bNodeFunc );
+        Cudd_RecursiveDeref( p->dd, bNodeDc );
+        // get the ISOP
+        bNodeFunc = Cudd_bddIsop( p->dd, bNodeOn, bNodeOnDc );            Cudd_Ref( bNodeFunc );
+        Cudd_RecursiveDeref( p->dd, bNodeOn );
+        Cudd_RecursiveDeref( p->dd, bNodeOnDc );
+p->timeDcs += Abc_Clock() - clk;
+    }
+
+    // always accept the case of constant node
+    if ( Cudd_IsConstant(bNodeFunc) )
+    {
+        p->nLastGain = Abc_NodeMffcSize( pNode );
+        p->nNodesGained += p->nLastGain;
+        p->nNodesRefactored++;
+        Cudd_RecursiveDeref( p->dd, bNodeFunc );
+        if ( Cudd_IsComplement(bNodeFunc) )
+            return Dec_GraphCreateConst0();
+        return Dec_GraphCreateConst1();
+    }
+
+    // get the SOP of the cut
+clk = Abc_Clock();
+    pSop = Abc_ConvertBddToSop( NULL, p->dd, bNodeFunc, bNodeFunc, vFanins->nSize, 0, p->vCube, -1 );
+p->timeSop += Abc_Clock() - clk;
+
+    // get the factored form
+clk = Abc_Clock();
+    pFForm = Dec_Factor( pSop );
+    ABC_FREE( pSop );
+p->timeFact += Abc_Clock() - clk;
+
+    // mark the fanin boundary 
+    // (can mark only essential fanins, belonging to bNodeFunc!)
+    Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pFanin, i )
+        pFanin->vFanouts.nSize++;
+    // label MFFC with current traversal ID
+    Abc_NtkIncrementTravId( pNode->pNtk );
+    nNodesSaved = Abc_NodeMffcLabelAig( pNode );
+    // unmark the fanin boundary and set the fanins as leaves in the form
+    Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pFanin, i )
+    {
+        pFanin->vFanouts.nSize--;
+        Dec_GraphNode(pFForm, i)->pFunc = pFanin;
+    }
+
+    // detect how many new nodes will be added (while taking into account reused nodes)
+clk = Abc_Clock();
+    nNodesAdded = Dec_GraphToNetworkCount( pNode, pFForm, nNodesSaved, Required );
+p->timeEval += Abc_Clock() - clk;
+    // quit if there is no improvement
+    if ( nNodesAdded == -1 || (nNodesAdded == nNodesSaved && !fUseZeros) )
+    {
+        Cudd_RecursiveDeref( p->dd, bNodeFunc );
+        Dec_GraphFree( pFForm );
+        return NULL;
+    }
+
+    // compute the total gain in the number of nodes
+    p->nLastGain = nNodesSaved - nNodesAdded;
+    p->nNodesGained += p->nLastGain;
+    p->nNodesRefactored++;
+
+    // report the progress
+    if ( fVeryVerbose )
+    {
+        printf( "Node %6s : ",  Abc_ObjName(pNode) );
+        printf( "Cone = %2d. ", vFanins->nSize );
+        printf( "BDD = %2d. ",  Cudd_DagSize(bNodeFunc) );
+        printf( "FF = %2d. ",   1 + Dec_GraphNodeNum(pFForm) );
+        printf( "MFFC = %2d. ", nNodesSaved );
+        printf( "Add = %2d. ",  nNodesAdded );
+        printf( "GAIN = %2d. ", p->nLastGain );
+        printf( "\n" );
+    }
+    Cudd_RecursiveDeref( p->dd, bNodeFunc );
+    return pFForm;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_ManRef_t * Abc_NtkManRefStart( int nNodeSizeMax, int nConeSizeMax, int fUseDcs, int fVerbose )
+{
+    Abc_ManRef_t * p;
+    p = ABC_ALLOC( Abc_ManRef_t, 1 );
+    memset( p, 0, sizeof(Abc_ManRef_t) );
+    p->vCube        = Vec_StrAlloc( 100 );
+    p->vVisited     = Vec_PtrAlloc( 100 );
+    p->nNodeSizeMax = nNodeSizeMax;
+    p->nConeSizeMax = nConeSizeMax;
+    p->fVerbose     = fVerbose;
+    // start the BDD manager
+    if ( fUseDcs )
+        p->dd = Cudd_Init( p->nNodeSizeMax + p->nConeSizeMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    else
+        p->dd = Cudd_Init( p->nNodeSizeMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    Cudd_zddVarsFromBddVars( p->dd, 2 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkManRefStop( Abc_ManRef_t * p )
+{
+    Extra_StopManager( p->dd );
+    Vec_PtrFree( p->vVisited );
+    Vec_StrFree( p->vCube    );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkManRefPrintStats( Abc_ManRef_t * p )
+{
+    printf( "Refactoring statistics:\n" );
+    printf( "Nodes considered  = %8d.\n", p->nNodesConsidered );
+    printf( "Nodes refactored  = %8d.\n", p->nNodesRefactored );
+    printf( "Gain              = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg );
+    ABC_PRT( "Cuts       ", p->timeCut );
+    ABC_PRT( "Resynthesis", p->timeRes );
+    ABC_PRT( "    BDD    ", p->timeBdd );
+    ABC_PRT( "    DCs    ", p->timeDcs );
+    ABC_PRT( "    SOP    ", p->timeSop );
+    ABC_PRT( "    FF     ", p->timeFact );
+    ABC_PRT( "    Eval   ", p->timeEval );
+    ABC_PRT( "AIG update ", p->timeNtk );
+    ABC_PRT( "TOTAL      ", p->timeTotal );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcRenode.c b/abc-build/src/base/abci/abcRenode.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcRenode.c
@@ -0,0 +1,315 @@
+/**CFile****************************************************************
+
+  FileName    [abcRenode.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcRenode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "bdd/reo/reo.h"
+#include "map/if/if.h"
+#include "bool/kit/kit.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_NtkRenodeEvalAig( If_Man_t * p, If_Cut_t * pCut );
+static int Abc_NtkRenodeEvalBdd( If_Man_t * p, If_Cut_t * pCut );
+static int Abc_NtkRenodeEvalSop( If_Man_t * p, If_Cut_t * pCut );
+static int Abc_NtkRenodeEvalCnf( If_Man_t * p, If_Cut_t * pCut );
+static int Abc_NtkRenodeEvalMv( If_Man_t * p, If_Cut_t * pCut );
+
+static reo_man * s_pReo       = NULL;
+static DdManager * s_pDd      = NULL;
+static Vec_Int_t * s_vMemory  = NULL;
+static Vec_Int_t * s_vMemory2 = NULL;
+
+static int nDsdCounter = 0;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs renoding as technology mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose )
+{
+    extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
+    If_Par_t Pars, * pPars = &Pars;
+    Abc_Ntk_t * pNtkNew;
+
+    if ( Abc_NtkGetChoiceNum( pNtk ) )
+        printf( "Performing renoding with choices.\n" );
+
+    nDsdCounter = 0;
+
+    // set defaults
+    memset( pPars, 0, sizeof(If_Par_t) );
+    // user-controlable paramters
+    pPars->nLutSize    =  nFaninMax;
+    pPars->nCutsMax    =  nCubeMax;
+    pPars->nFlowIters  =  nFlowIters;
+    pPars->nAreaIters  =  nAreaIters;
+    pPars->DelayTarget = -1;
+    pPars->Epsilon     =  (float)0.005;
+    pPars->fPreprocess =  1;
+    pPars->fArea       =  fArea;
+    pPars->fFancy      =  0;
+    pPars->fExpRed     =  0; //
+    pPars->fLatchPaths =  0;
+    pPars->fVerbose    =  fVerbose;
+    // internal parameters
+    pPars->fTruth      =  1;
+    pPars->fUsePerm    =  1; 
+    pPars->nLatchesCi  =  0;
+    pPars->nLatchesCo  =  0;
+    pPars->pLutLib     =  NULL; // Abc_FrameReadLibLut();
+    pPars->pTimesArr   =  NULL; 
+    pPars->pTimesArr   =  NULL;   
+    pPars->fUseBdds    =  fUseBdds;
+    pPars->fUseSops    =  fUseSops;
+    pPars->fUseCnfs    =  fUseCnfs;
+    pPars->fUseMv      =  fUseMv;
+    if ( fUseBdds )
+        pPars->pFuncCost = Abc_NtkRenodeEvalBdd;
+    else if ( fUseSops )
+        pPars->pFuncCost = Abc_NtkRenodeEvalSop;
+    else if ( fUseCnfs )
+    {
+        pPars->fArea = 1;
+        pPars->pFuncCost = Abc_NtkRenodeEvalCnf;
+    }
+    else if ( fUseMv )
+        pPars->pFuncCost = Abc_NtkRenodeEvalMv;
+    else
+        pPars->pFuncCost = Abc_NtkRenodeEvalAig;
+
+    // start the manager
+    if ( fUseBdds )
+    {
+        assert( s_pReo == NULL );
+        s_pDd  = Cudd_Init( nFaninMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+        s_pReo = Extra_ReorderInit( nFaninMax, 100 );
+        pPars->pReoMan  = s_pReo;
+    }
+    else
+    {
+        assert( s_vMemory == NULL );
+        s_vMemory  = Vec_IntAlloc( 1 << 16 );
+        s_vMemory2 = Vec_IntAlloc( 1 << 16 );
+    }
+
+    // perform mapping/renoding
+    pNtkNew = Abc_NtkIf( pNtk, pPars );
+
+    // start the manager
+    if ( fUseBdds )
+    {
+        Extra_StopManager( s_pDd );
+        Extra_ReorderQuit( s_pReo );
+        s_pReo = NULL;
+        s_pDd  = NULL;
+    }
+    else
+    {
+        Vec_IntFree( s_vMemory );
+        Vec_IntFree( s_vMemory2 );
+        s_vMemory = NULL;
+        s_vMemory2 = NULL;
+    }
+
+//    printf( "Decomposed %d functions.\n", nDsdCounter );
+
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cost based on the factored form.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRenodeEvalAig( If_Man_t * p, If_Cut_t * pCut )
+{
+    char * pPerm = If_CutPerm( pCut );
+    Kit_Graph_t * pGraph;
+    int i, nNodes;
+    pGraph = Kit_TruthToGraph( If_CutTruth(p, pCut), If_CutLeaveNum(pCut), s_vMemory );
+    if ( pGraph == NULL )
+    {
+        for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+            pPerm[i] = 100;
+        return IF_COST_MAX;
+    }
+    nNodes = Kit_GraphNodeNum( pGraph );
+    for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+        pPerm[i] = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeLast(pGraph), Kit_GraphNode(pGraph, i) );
+    Kit_GraphFree( pGraph );
+    return nNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cost based on the BDD size after reordering.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRenodeEvalBdd( If_Man_t * p, If_Cut_t * pCut )
+{
+    char * pPerm = If_CutPerm( pCut );
+    int pOrder[IF_MAX_LUTSIZE];
+    DdNode * bFunc, * bFuncNew;
+    int i, k, nNodes;
+    for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+        pPerm[i] = pOrder[i] = -100;
+    bFunc = Kit_TruthToBdd( s_pDd, If_CutTruth(p, pCut), If_CutLeaveNum(pCut), 0 );  Cudd_Ref( bFunc );
+    bFuncNew = Extra_Reorder( s_pReo, s_pDd, bFunc, pOrder );                     Cudd_Ref( bFuncNew );
+    for ( i = k = 0; i < If_CutLeaveNum(pCut); i++ )
+        if ( pOrder[i] >= 0 )
+            pPerm[pOrder[i]] = ++k; // double-check this!
+    nNodes = -1 + Cudd_DagSize( bFuncNew );
+    Cudd_RecursiveDeref( s_pDd, bFuncNew );
+    Cudd_RecursiveDeref( s_pDd, bFunc );
+    return nNodes; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cost based on ISOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRenodeEvalSop( If_Man_t * p, If_Cut_t * pCut )
+{
+    char * pPerm = If_CutPerm( pCut );
+    int i, RetValue;
+    for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+        pPerm[i] = 1;
+    RetValue = Kit_TruthIsop( If_CutTruth(p, pCut), If_CutLeaveNum(pCut), s_vMemory, 1 );
+    if ( RetValue == -1 )
+        return IF_COST_MAX;
+    assert( RetValue == 0 || RetValue == 1 );
+    return Vec_IntSize( s_vMemory );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cost based on two ISOPs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRenodeEvalCnf( If_Man_t * p, If_Cut_t * pCut )
+{
+    char * pPerm = If_CutPerm( pCut );
+    int i, RetValue, nClauses;
+    // set internal mapper parameters
+    for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+        pPerm[i] = 1;
+    // compute ISOP for the positive phase
+    RetValue = Kit_TruthIsop( If_CutTruth(p, pCut), If_CutLeaveNum(pCut), s_vMemory, 0 );
+    if ( RetValue == -1 )
+        return IF_COST_MAX;
+    assert( RetValue == 0 || RetValue == 1 );
+    nClauses = Vec_IntSize( s_vMemory );
+    // compute ISOP for the negative phase
+    Kit_TruthNot( If_CutTruth(p, pCut), If_CutTruth(p, pCut), If_CutLeaveNum(pCut) );
+    RetValue = Kit_TruthIsop( If_CutTruth(p, pCut), If_CutLeaveNum(pCut), s_vMemory, 0 );
+    Kit_TruthNot( If_CutTruth(p, pCut), If_CutTruth(p, pCut), If_CutLeaveNum(pCut) );
+    if ( RetValue == -1 )
+        return IF_COST_MAX;
+    assert( RetValue == 0 || RetValue == 1 );
+    nClauses += Vec_IntSize( s_vMemory );
+    return nClauses;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cost of MV-SOP of the cut function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRenodeEvalMv( If_Man_t * p, If_Cut_t * pCut )
+{
+    char * pPerm = If_CutPerm( pCut );
+    int i, RetValue;
+    // set internal mapper parameters
+    for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+        pPerm[i] = 1;
+    // compute ISOP for the positive phase
+    RetValue = Kit_TruthIsop( If_CutTruth(p, pCut), If_CutLeaveNum(pCut), s_vMemory, 0 );
+    if ( RetValue == -1 )
+        return IF_COST_MAX;
+    assert( RetValue == 0 || RetValue == 1 );
+    // compute ISOP for the negative phase
+    Kit_TruthNot( If_CutTruth(p, pCut), If_CutTruth(p, pCut), If_CutLeaveNum(pCut) );
+    RetValue = Kit_TruthIsop( If_CutTruth(p, pCut), If_CutLeaveNum(pCut), s_vMemory2, 0 );
+    Kit_TruthNot( If_CutTruth(p, pCut), If_CutTruth(p, pCut), If_CutLeaveNum(pCut) );
+    if ( RetValue == -1 )
+        return IF_COST_MAX;
+    assert( RetValue == 0 || RetValue == 1 );
+    // return the cost of the cut 
+    RetValue = Abc_NodeEvalMvCost( If_CutLeaveNum(pCut), s_vMemory, s_vMemory2 );
+    if ( RetValue >= IF_COST_MAX )
+        return IF_COST_MAX;
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcReorder.c b/abc-build/src/base/abci/abcReorder.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcReorder.c
@@ -0,0 +1,106 @@
+/**CFile****************************************************************
+
+  FileName    [abcReorder.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Reordering local BDDs of the nodes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcReorder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "bdd/reo/reo.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reorders BDD of the local function of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeBddReorder( reo_man * p, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    DdNode * bFunc;
+    int * pOrder, i;
+    // create the temporary array for the variable order
+    pOrder = ABC_ALLOC( int, Abc_ObjFaninNum(pNode) );
+    for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
+        pOrder[i] = -1;
+    // reorder the BDD
+    bFunc = Extra_Reorder( p, (DdManager *)pNode->pNtk->pManFunc, (DdNode *)pNode->pData, pOrder ); Cudd_Ref( bFunc );
+    Cudd_RecursiveDeref( (DdManager *)pNode->pNtk->pManFunc, (DdNode *)pNode->pData );
+    pNode->pData = bFunc;
+    // update the fanin order
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        pOrder[i] = pNode->vFanins.pArray[ pOrder[i] ];
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        pNode->vFanins.pArray[i] = pOrder[i];
+    ABC_FREE( pOrder );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reorders BDDs of the local functions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose )
+{
+	reo_man * p;
+    Abc_Obj_t * pNode;
+    int i;
+    Abc_NtkRemoveDupFanins( pNtk );
+    Abc_NtkMinimumBase( pNtk );
+    p = Extra_ReorderInit( Abc_NtkGetFaninMax(pNtk), 100 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        if ( Abc_ObjFaninNum(pNode) < 3 )
+            continue;
+        if ( fVerbose )
+            fprintf( stdout, "%10s: ", Abc_ObjName(pNode) );
+        if ( fVerbose )
+            fprintf( stdout, "Before = %5d  BDD nodes.  ", Cudd_DagSize((DdNode *)pNode->pData) );
+        Abc_NodeBddReorder( p, pNode );
+        if ( fVerbose )
+            fprintf( stdout, "After = %5d  BDD nodes.\n", Cudd_DagSize((DdNode *)pNode->pData) );
+    }
+    Extra_ReorderQuit( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcRestruct.c b/abc-build/src/base/abci/abcRestruct.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcRestruct.c
@@ -0,0 +1,1500 @@
+/**CFile****************************************************************
+
+  FileName    [abcRestruct.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcRestruct.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "bool/dec/dec.h"
+#include "opt/cut/cut.h"
+#include "misc/extra/extraBdd.h"
+#include "bdd/dsd/dsd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+  
+#define RST_RANDOM_UNSIGNED   ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand()))
+
+typedef struct Abc_ManRst_t_   Abc_ManRst_t;
+struct Abc_ManRst_t_
+{
+    // the network
+    Abc_Ntk_t *      pNtk;              // the network for restructuring
+    // user specified parameters
+    int              nCutMax;           // the limit on the size of the supernode
+    int              fUpdateLevel;      // turns on watching the number of levels
+    int              fUseZeros;         // turns on zero-cost replacements
+    int              fVerbose;          // the verbosity flag
+    // internal data structures
+    DdManager *      dd;                // the BDD manager
+    Dsd_Manager_t *  pManDsd;           // the DSD manager
+    Vec_Ptr_t *      vVisited;          // temporary
+    Vec_Ptr_t *      vLeaves;           // temporary
+    Vec_Ptr_t *      vDecs;             // temporary
+    Vec_Ptr_t *      vTemp;             // temporary
+    Vec_Int_t *      vSims;             // temporary
+    Vec_Int_t *      vRands;            // temporary
+    Vec_Int_t *      vOnes;             // temporary
+    Vec_Int_t *      vBinate;           // temporary
+    Vec_Int_t *      vTwos;             // temporary
+    // node statistics
+    int              nLastGain;
+    int              nCutsConsidered;
+    int              nCutsExplored;
+    int              nNodesConsidered;
+    int              nNodesRestructured;
+    int              nNodesGained;
+    // runtime statistics
+    int              timeCut;
+    int              timeBdd;
+    int              timeDsd;
+    int              timeEval;
+    int              timeRes;
+    int              timeNtk;
+    int              timeTotal;
+};
+
+static Dec_Graph_t * Abc_NodeResubstitute( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList );
+
+static Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList );
+static Dec_Graph_t * Abc_NodeRestructureCut( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCut );
+static Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, Abc_Obj_t * pRoot, int Required, int nNodesSaved, int * pnNodesAdded );
+
+static Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fDag );
+static Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, int fUpdateLevel, int fUseZeros, int fVerbose );
+static void Abc_NtkManRstStop( Abc_ManRst_t * p );
+static void Abc_NtkManRstPrintStats( Abc_ManRst_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Implements AIG restructuring.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutMax, int fUpdateLevel, int fUseZeros, int fVerbose )
+{
+    extern void           Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain );
+    ProgressBar * pProgress;
+    Abc_ManRst_t * pManRst;
+    Cut_Man_t * pManCut;
+    Cut_Cut_t * pCutList;
+    Dec_Graph_t * pGraph;
+    Abc_Obj_t * pNode;
+    abctime clk, clkStart = Abc_Clock();
+    int fMulti = 1;
+    int fResub = 0;
+    int i, nNodes;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    // cleanup the AIG
+    Abc_AigCleanup((Abc_Aig_t *)pNtk->pManFunc);
+    Abc_NtkCleanCopy(pNtk);
+
+    // compute the reverse levels if level update is requested
+    if ( fUpdateLevel )
+        Abc_NtkStartReverseLevels( pNtk, 0 );
+
+    // start the restructuring manager
+    pManRst = Abc_NtkManRstStart( nCutMax, fUpdateLevel, fUseZeros, fVerbose );
+    pManRst->pNtk = pNtk;
+    // start the cut manager
+clk = Abc_Clock();
+    pManCut = Abc_NtkStartCutManForRestruct( pNtk, nCutMax, fMulti );
+pManRst->timeCut += Abc_Clock() - clk;
+//    pNtk->pManCut = pManCut;
+
+    // resynthesize each node once
+    nNodes = Abc_NtkObjNumMax(pNtk);
+    pProgress = Extra_ProgressBarStart( stdout, nNodes );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        // skip the constant node
+//        if ( Abc_NodeIsConst(pNode) )
+//            continue;
+        // skip persistant nodes
+        if ( Abc_NodeIsPersistant(pNode) )
+            continue;
+        // skip the node if it is inside the tree
+//        if ( Abc_ObjFanoutNum(pNode) < 2 )
+//            continue;
+        // skip the nodes with too many fanouts
+        if ( Abc_ObjFanoutNum(pNode) > 1000 )
+            continue;
+        // stop if all nodes have been tried once
+        if ( i >= nNodes )
+            break;
+        // get the cuts for the given node
+clk = Abc_Clock();
+        pCutList = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, fMulti, 0 ); 
+pManRst->timeCut += Abc_Clock() - clk;
+
+        // perform restructuring
+clk = Abc_Clock();
+        if ( fResub )
+            pGraph = Abc_NodeResubstitute( pManRst, pNode, pCutList );
+        else
+            pGraph = Abc_NodeRestructure( pManRst, pNode, pCutList );
+pManRst->timeRes += Abc_Clock() - clk;
+        if ( pGraph == NULL )
+            continue;
+
+        // acceptable replacement found, update the graph
+clk = Abc_Clock();
+        Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, pManRst->nLastGain );
+pManRst->timeNtk += Abc_Clock() - clk;
+        Dec_GraphFree( pGraph );
+    }
+    Extra_ProgressBarStop( pProgress );
+pManRst->timeTotal = Abc_Clock() - clkStart;
+
+    // print statistics of the manager
+//    if ( fVerbose )
+        Abc_NtkManRstPrintStats( pManRst );
+    // delete the managers
+    Cut_ManStop( pManCut );
+    Abc_NtkManRstStop( pManRst );
+    // put the nodes into the DFS order and reassign their IDs
+    Abc_NtkReassignIds( pNtk );
+//    Abc_AigCheckFaninOrder( pNtk->pManFunc );
+    // fix the levels
+    if ( fUpdateLevel )
+        Abc_NtkStopReverseLevels( pNtk );
+    else
+        Abc_NtkLevel( pNtk );
+    // check
+    if ( !Abc_NtkCheck( pNtk ) )
+    {
+        printf( "Abc_NtkRefactor: The network check has failed.\n" );
+        return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_RestructNodeDivisors( Abc_ManRst_t * p, Abc_Obj_t * pRoot, int nNodesSaved )
+{
+    Abc_Obj_t * pNode, * pFanout;//, * pFanin;
+    int i, k;
+    // start with the leaves
+    Vec_PtrClear( p->vDecs );
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pNode, i )
+    {
+        Vec_PtrPush( p->vDecs, pNode );
+        assert( pNode->fMarkC == 0 );
+        pNode->fMarkC = 1;
+    }
+    // explore the fanouts
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vDecs, pNode, i )
+    {
+        // if the fanout has both fanins in the set, add it
+        Abc_ObjForEachFanout( pNode, pFanout, k )
+        {
+            if ( pFanout->fMarkC || Abc_ObjIsPo(pFanout) )
+                continue;
+            if ( Abc_ObjFanin0(pFanout)->fMarkC && Abc_ObjFanin1(pFanout)->fMarkC )
+            {
+                Vec_PtrPush( p->vDecs, pFanout );
+                pFanout->fMarkC = 1;
+            }
+        }
+    }
+    // unmark the nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vDecs, pNode, i )
+        pNode->fMarkC = 0;
+/*
+    // print the nodes
+    Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDecs, pNode, i, Vec_PtrSize(p->vLeaves) )
+    {
+        printf( "%2d %s = ", i, Abc_NodeIsTravIdCurrent(pNode)? "*" : " " );
+        // find the first fanin
+        Vec_PtrForEachEntry( Abc_Obj_t *, p->vDecs, pFanin, k )
+            if ( Abc_ObjFanin0(pNode) == pFanin )
+                break;
+        if ( k < Vec_PtrSize(p->vLeaves) )
+            printf( "%c", 'a' + k );
+        else
+            printf( "%d", k );
+        printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" );
+        // find the second fanin
+        Vec_PtrForEachEntry( Abc_Obj_t *, p->vDecs, pFanin, k )
+            if ( Abc_ObjFanin1(pNode) == pFanin )
+                break;
+        if ( k < Vec_PtrSize(p->vLeaves) )
+            printf( "%c", 'a' + k );
+        else
+            printf( "%d", k );
+        printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" );
+        printf( "\n" );
+    }
+*/
+    printf( "%d\n", Vec_PtrSize(p->vDecs)-nNodesSaved-Vec_PtrSize(p->vLeaves) );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the cut manager for rewriting.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList )
+{
+    Dec_Graph_t * pGraph;
+    Cut_Cut_t * pCut;
+//    int nCuts;
+    p->nNodesConsidered++;
+/*
+    // count the number of cuts with four inputs or more
+    nCuts = 0;
+    for ( pCut = pCutList; pCut; pCut = pCut->pNext )
+        nCuts += (int)(pCut->nLeaves > 3);
+    printf( "-----------------------------------\n" );
+    printf( "Node %6d : Factor-cuts = %5d.\n", pNode->Id, nCuts );
+*/
+    // go through the interesting cuts
+    for ( pCut = pCutList; pCut; pCut = pCut->pNext )
+    {
+        if ( pCut->nLeaves < 4 )
+            continue;
+        if ( (pGraph = Abc_NodeRestructureCut( p, pNode, pCut )) )
+            return pGraph;
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the cut manager for rewriting.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeRestructureCut( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut )
+{
+    extern DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited );
+    Dec_Graph_t * pGraph;
+    Dsd_Node_t * pNodeDsd;
+    Abc_Obj_t * pLeaf;
+    DdNode * bFunc;
+    int nNodesSaved, nNodesAdded;
+    int Required, nMaxSize, clk, i;
+    int fVeryVerbose = 0;
+
+    p->nCutsConsidered++;
+
+    // get the required time for the node
+    Required = p->fUpdateLevel? Abc_ObjRequiredLevel(pRoot) : ABC_INFINITY;
+
+    // collect the leaves of the cut
+    Vec_PtrClear( p->vLeaves );
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+    {
+        pLeaf = Abc_NtkObj(pRoot->pNtk, pCut->pLeaves[i]);
+        if ( pLeaf == NULL )  // the so-called "bad cut phenomenon" is due to removed nodes
+            return NULL;
+        Vec_PtrPush( p->vLeaves, pLeaf );
+    }
+
+clk = Abc_Clock();
+    // collect the internal nodes of the cut
+//    Abc_NodeConeCollect( &pRoot, 1, p->vLeaves, p->vVisited, 0 );
+    // derive the BDD of the cut
+    bFunc = Abc_NodeConeBdd( p->dd, p->dd->vars, pRoot, p->vLeaves, p->vVisited );  Cudd_Ref( bFunc );
+p->timeBdd += Abc_Clock() - clk;
+
+    // consider the special case, when the function is a constant
+    if ( Cudd_IsConstant(bFunc) )
+    {
+        p->nLastGain = Abc_NodeMffcSize( pRoot );
+        p->nNodesGained += p->nLastGain;
+        p->nNodesRestructured++;
+        Cudd_RecursiveDeref( p->dd, bFunc );
+        if ( Cudd_IsComplement(bFunc) )
+            return Dec_GraphCreateConst0();
+        return Dec_GraphCreateConst1();
+    }
+
+clk = Abc_Clock();
+    // try disjoint support decomposition
+    pNodeDsd = Dsd_DecomposeOne( p->pManDsd, bFunc );
+p->timeDsd += Abc_Clock() - clk;
+
+    // skip nodes with non-decomposable blocks
+    Dsd_TreeNodeGetInfoOne( pNodeDsd, NULL, &nMaxSize );
+    if ( nMaxSize > 3 )
+    {
+        Cudd_RecursiveDeref( p->dd, bFunc );
+        return NULL;
+    }
+
+
+/*
+    // skip nodes that cannot be improved
+    if ( Vec_PtrSize(p->vVisited) <= Dsd_TreeGetAigCost(pNodeDsd) )
+    {
+        Cudd_RecursiveDeref( p->dd, bFunc );
+        return NULL;
+    }
+*/
+
+    p->nCutsExplored++;
+
+    // mark the fanin boundary 
+    // (can mark only essential fanins, belonging to bNodeFunc!)
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pLeaf, i )
+        pLeaf->vFanouts.nSize++;
+    // label MFFC with current traversal ID
+    Abc_NtkIncrementTravId( pRoot->pNtk );
+    nNodesSaved = Abc_NodeMffcLabelAig( pRoot );
+    // unmark the fanin boundary and set the fanins as leaves in the form
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pLeaf, i )
+        pLeaf->vFanouts.nSize--;
+/*
+    if ( nNodesSaved < 3 )
+    {
+        Cudd_RecursiveDeref( p->dd, bFunc );
+        return NULL;
+    }
+*/
+
+/* 
+    printf( "%5d : Cut-size = %d.  Old AIG = %2d.  New AIG = %2d.  Old MFFC = %2d.\n",
+        pRoot->Id, pCut->nLeaves, Vec_PtrSize(p->vVisited), Dsd_TreeGetAigCost(pNodeDsd), 
+        nNodesSaved );
+    Dsd_NodePrint( stdout, pNodeDsd );
+
+    Abc_RestructNodeDivisors( p, pRoot );
+
+    if ( pRoot->Id == 433 )
+    {
+        int x = 0;
+    }
+*/
+//    Abc_RestructNodeDivisors( p, pRoot, nNodesSaved );
+
+
+    // detect how many new nodes will be added (while taking into account reused nodes)
+clk = Abc_Clock();
+    if ( nMaxSize > 3 )
+        pGraph = NULL;
+    else
+        pGraph = Abc_NodeEvaluateDsd( p, pNodeDsd, pRoot, Required, nNodesSaved, &nNodesAdded );
+//    pGraph = NULL;
+p->timeEval += Abc_Clock() - clk;
+
+    // quit if there is no improvement
+    if ( pGraph == NULL || nNodesAdded == -1 || (nNodesAdded == nNodesSaved && !p->fUseZeros) )
+    {
+        Cudd_RecursiveDeref( p->dd, bFunc );
+        if ( pGraph ) Dec_GraphFree( pGraph );
+        return NULL;
+    }
+
+/*
+    // print stats
+    printf( "%5d : Cut-size = %d.  Old AIG = %2d.  New AIG = %2d.  Old MFFC = %2d.  New MFFC = %2d. Gain = %d.\n",
+        pRoot->Id, pCut->nLeaves, Vec_PtrSize(p->vVisited), Dsd_TreeGetAigCost(pNodeDsd), 
+        nNodesSaved, nNodesAdded, (nNodesAdded == -1)? 0 : nNodesSaved-nNodesAdded );
+//    Dsd_NodePrint( stdout, pNodeDsd );
+//    Dec_GraphPrint( stdout, pGraph, NULL, NULL );
+*/
+
+    // compute the total gain in the number of nodes
+    p->nLastGain = nNodesSaved - nNodesAdded;
+    p->nNodesGained += p->nLastGain;
+    p->nNodesRestructured++;
+
+    // report the progress
+    if ( fVeryVerbose )
+    {
+        printf( "Node %6s : ",  Abc_ObjName(pRoot) );
+        printf( "Cone = %2d. ", p->vLeaves->nSize );
+        printf( "BDD = %2d. ",  Cudd_DagSize(bFunc) );
+        printf( "FF = %2d. ",   1 + Dec_GraphNodeNum(pGraph) );
+        printf( "MFFC = %2d. ", nNodesSaved );
+        printf( "Add = %2d. ",  nNodesAdded );
+        printf( "GAIN = %2d. ", p->nLastGain );
+        printf( "\n" );
+    }
+    Cudd_RecursiveDeref( p->dd, bFunc );
+    return pGraph;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Moves closer to the end the node that is best for sharing.]
+
+  Description [If the flag is set, tries to find an EXOR, otherwise, tries
+  to find an OR.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeEdgeDsdPermute( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst, Vec_Int_t * vEdges, int fExor )
+{
+    Dec_Edge_t eNode1, eNode2, eNode3;
+    Abc_Obj_t * pNode1, * pNode2, * pNode3, * pTemp;
+    int LeftBound = 0, RightBound, i;
+    // get the right bound
+    RightBound = Vec_IntSize(vEdges) - 2;
+    assert( LeftBound <= RightBound );
+    if ( LeftBound == RightBound )
+        return;
+    // get the two last nodes
+    eNode1 = Dec_IntToEdge( Vec_IntEntry(vEdges, RightBound + 1) );
+    eNode2 = Dec_IntToEdge( Vec_IntEntry(vEdges, RightBound    ) );
+    pNode1 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode1.Node )->pFunc;
+    pNode2 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode2.Node )->pFunc;
+    pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl );
+    pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl );
+    // quit if the last node does not exist
+    if ( pNode1 == NULL )
+        return;
+    // find the first node that can be shared
+    for ( i = RightBound; i >= LeftBound; i-- )
+    {
+        // get the third node
+        eNode3 = Dec_IntToEdge( Vec_IntEntry(vEdges, i) );
+        pNode3 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode3.Node )->pFunc;
+        pNode3 = !pNode3? NULL : Abc_ObjNotCond( pNode3, eNode3.fCompl );
+        if ( pNode3 == NULL )
+            continue;
+        // check if the node exists
+        if ( fExor )
+        {
+            if ( pNode1 && pNode3 )
+            {
+                pTemp = Abc_AigXorLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, pNode1, pNode3, NULL );
+                if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+                    continue;
+
+                if ( pNode3 == pNode2 )
+                    return;
+                Vec_IntWriteEntry( vEdges, i,          Dec_EdgeToInt(eNode2) );
+                Vec_IntWriteEntry( vEdges, RightBound, Dec_EdgeToInt(eNode3) );
+                return;
+            }
+        }
+        else
+        {
+            if ( pNode1 && pNode3 )
+            {
+                pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode3) );
+                if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+                    continue;
+
+                if ( eNode3.Node == eNode2.Node )
+                    return;
+                Vec_IntWriteEntry( vEdges, i,          Dec_EdgeToInt(eNode2) );
+                Vec_IntWriteEntry( vEdges, RightBound, Dec_EdgeToInt(eNode3) );
+                return;
+            }
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the new edge in the given order.]
+
+  Description [Similar to Vec_IntPushOrder, except in decreasing order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeEdgeDsdPushOrdered( Dec_Graph_t * pGraph, Vec_Int_t * vEdges, int Edge )
+{
+    int i, NodeOld, NodeNew;
+    vEdges->nSize++;
+    for ( i = vEdges->nSize-2; i >= 0; i-- )
+    {
+        NodeOld = Dec_IntToEdge(vEdges->pArray[i]).Node;
+        NodeNew = Dec_IntToEdge(Edge).Node;
+        // use <= because we are trying to push the new (non-existent) nodes as far as possible
+        if ( Dec_GraphNode(pGraph, NodeOld)->Level <= Dec_GraphNode(pGraph, NodeNew)->Level )
+            vEdges->pArray[i+1] = vEdges->pArray[i];
+        else
+            break;
+    }
+    vEdges->pArray[i+1] = Edge;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluation one DSD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Edge_t Abc_NodeEvaluateDsd_rec( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, int Required, int nNodesSaved, int * pnNodesAdded )
+{
+    Dec_Edge_t eNode1, eNode2, eNode3, eResult, eQuit = { 0, 2006 };
+    Abc_Obj_t * pNode1, * pNode2, * pNode3, * pNode4, * pTemp;
+    Dsd_Node_t * pChildDsd;
+    Dsd_Type_t DecType;
+    Vec_Int_t * vEdges;
+    int Level1, Level2, Level3, Level4;
+    int i, Index, fCompl, Type;
+
+    // remove the complemented attribute
+    fCompl   = Dsd_IsComplement( pNodeDsd );
+    pNodeDsd = Dsd_Regular( pNodeDsd );
+
+    // consider the trivial case
+    DecType = Dsd_NodeReadType( pNodeDsd );
+    if ( DecType == DSD_NODE_BUF )
+    {
+        Index = Dsd_NodeReadFunc(pNodeDsd)->index;
+        assert( Index < Dec_GraphLeaveNum(pGraph) );
+        eResult = Dec_EdgeCreate( Index, fCompl );
+        return eResult;
+    }
+    assert( DecType == DSD_NODE_OR || DecType == DSD_NODE_EXOR || DecType == DSD_NODE_PRIME );
+
+    // solve the problem for the children
+    vEdges = Vec_IntAlloc( Dsd_NodeReadDecsNum(pNodeDsd) );
+    Dsd_NodeForEachChild( pNodeDsd, i, pChildDsd )
+    {
+        eResult = Abc_NodeEvaluateDsd_rec( pGraph, pManRst, pChildDsd, Required, nNodesSaved, pnNodesAdded );
+        if ( eResult.Node == eQuit.Node ) // infeasible
+        {
+            Vec_IntFree( vEdges );
+            return eQuit;
+        }
+        // order the inputs only if this is OR or EXOR
+        if ( DecType == DSD_NODE_PRIME )
+            Vec_IntPush( vEdges, Dec_EdgeToInt(eResult) );
+        else
+            Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eResult) );
+    }
+    // the edges are sorted by the level of their nodes in decreasing order
+
+
+    // consider special cases
+    if ( DecType == DSD_NODE_OR )
+    {
+        // try to balance the nodes by delay
+        assert( Vec_IntSize(vEdges) > 1 );
+        while ( Vec_IntSize(vEdges) > 1 )
+        {
+            // permute the last two entries
+            if ( Vec_IntSize(vEdges) > 2 )
+                Abc_NodeEdgeDsdPermute( pGraph, pManRst, vEdges, 0 );
+            // get the two last nodes
+            eNode1 = Dec_IntToEdge( Vec_IntPop(vEdges) );
+            eNode2 = Dec_IntToEdge( Vec_IntPop(vEdges) );
+            pNode1 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode1.Node )->pFunc;
+            pNode2 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode2.Node )->pFunc;
+            pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl );
+            pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl );
+            // check if the new node exists
+            pNode3 = NULL;
+            if ( pNode1 && pNode2 )
+            {
+                pNode3 = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); 
+                pNode3 = !pNode3? NULL : Abc_ObjNot(pNode3);
+            }
+            // create the new node
+            eNode3 = Dec_GraphAddNodeOr( pGraph, eNode1, eNode2 );
+            // set level
+            Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level;
+            Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level;
+            Dec_GraphNode( pGraph, eNode3.Node )->Level = 1 + Abc_MaxInt(Level1, Level2);
+            // get the new node if possible
+            if ( pNode3 )
+            {
+                Dec_GraphNode( pGraph, eNode3.Node )->pFunc = Abc_ObjNotCond(pNode3, eNode3.fCompl);
+                Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level;
+                assert( Required == ABC_INFINITY || Level3 == (int)Abc_ObjRegular(pNode3)->Level );
+            }
+            if ( !pNode3 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode3)) )
+            {
+                (*pnNodesAdded)++;
+                if ( *pnNodesAdded > nNodesSaved )
+                {
+                    Vec_IntFree( vEdges );
+                    return eQuit;
+                }
+            }
+            // add the resulting node to the form
+            Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eNode3) );
+        }
+        // get the last node
+        eResult = Dec_IntToEdge( Vec_IntPop(vEdges) );
+        Vec_IntFree( vEdges );
+        // complement the graph if the node was complemented
+        eResult.fCompl ^= fCompl;
+        return eResult;
+    }
+    if ( DecType == DSD_NODE_EXOR )
+    {
+        // try to balance the nodes by delay
+        assert( Vec_IntSize(vEdges) > 1 );
+        while ( Vec_IntSize(vEdges) > 1 )
+        {
+            // permute the last two entries
+            if ( Vec_IntSize(vEdges) > 2 )
+                Abc_NodeEdgeDsdPermute( pGraph, pManRst, vEdges, 1 );
+            // get the two last nodes
+            eNode1 = Dec_IntToEdge( Vec_IntPop(vEdges) );
+            eNode2 = Dec_IntToEdge( Vec_IntPop(vEdges) );
+            pNode1 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode1.Node )->pFunc;
+            pNode2 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode2.Node )->pFunc;
+            pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl );
+            pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl );
+            // check if the new node exists
+            Type = 0;
+            pNode3 = NULL;
+            if ( pNode1 && pNode2 )
+                pNode3 = Abc_AigXorLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, pNode1, pNode2, &Type ); 
+            // create the new node
+            eNode3 = Dec_GraphAddNodeXor( pGraph, eNode1, eNode2, Type ); // should have the same structure as in AIG
+            // set level
+            Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level;
+            Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level;
+            Dec_GraphNode( pGraph, eNode3.Node )->Level = 2 + Abc_MaxInt(Level1, Level2);
+            // get the new node if possible
+            if ( pNode3 )
+            {
+                Dec_GraphNode( pGraph, eNode3.Node )->pFunc = Abc_ObjNotCond(pNode3, eNode3.fCompl);
+                Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level;
+                assert( Required == ABC_INFINITY || Level3 == (int)Abc_ObjRegular(pNode3)->Level );
+            }
+            if ( !pNode3 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode3)) )
+            {
+                (*pnNodesAdded)++;
+                if ( !pNode1 || !pNode2 )
+                    (*pnNodesAdded) += 2;
+                else if ( Type == 0 )
+                {
+                    pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) );
+                    if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+                        (*pnNodesAdded)++;
+                    pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode2 );
+                    if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+                        (*pnNodesAdded)++;
+                }
+                else
+                {
+                    pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+                    if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+                        (*pnNodesAdded)++;
+                    pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, pNode1, pNode2 );
+                    if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+                        (*pnNodesAdded)++;
+                }
+                if ( *pnNodesAdded > nNodesSaved )
+                {
+                    Vec_IntFree( vEdges );
+                    return eQuit;
+                }
+            }
+            // add the resulting node to the form
+            Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eNode3) );
+        }
+        // get the last node
+        eResult = Dec_IntToEdge( Vec_IntPop(vEdges) );
+        Vec_IntFree( vEdges );
+        // complement the graph if the node is complemented
+        eResult.fCompl ^= fCompl;
+        return eResult;
+    }
+    if ( DecType == DSD_NODE_PRIME )
+    {
+        DdNode * bLocal, * bVar, * bCofT, * bCofE;
+        bLocal = Dsd_TreeGetPrimeFunction( pManRst->dd, pNodeDsd );  Cudd_Ref( bLocal );
+//Extra_bddPrint( pManRst->dd, bLocal );
+
+        bVar  = pManRst->dd->vars[0];
+        bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) );  Cudd_Ref( bCofE );
+        bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar );            Cudd_Ref( bCofT );
+        if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) )
+        {
+            Cudd_RecursiveDeref( pManRst->dd, bCofE );
+            Cudd_RecursiveDeref( pManRst->dd, bCofT );
+            bVar  = pManRst->dd->vars[1];
+            bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) );  Cudd_Ref( bCofE );
+            bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar );            Cudd_Ref( bCofT );
+            if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) )
+            {
+                Cudd_RecursiveDeref( pManRst->dd, bCofE );
+                Cudd_RecursiveDeref( pManRst->dd, bCofT );
+                bVar  = pManRst->dd->vars[2];
+                bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) );  Cudd_Ref( bCofE );
+                bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar );            Cudd_Ref( bCofT );
+                if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) )
+                {
+                    Cudd_RecursiveDeref( pManRst->dd, bCofE );
+                    Cudd_RecursiveDeref( pManRst->dd, bCofT );
+                    Cudd_RecursiveDeref( pManRst->dd, bLocal );
+                    Vec_IntFree( vEdges );
+                    return eQuit;
+                }
+            }
+        }
+        Cudd_RecursiveDeref( pManRst->dd, bLocal );
+        // we found the control variable (bVar) and the var-cofactors (bCofT, bCofE)
+
+        // find the graph nodes
+        eNode1 = Dec_IntToEdge( Vec_IntEntry(vEdges, bVar->index) );
+        eNode2 = Dec_IntToEdge( Vec_IntEntry(vEdges, Cudd_Regular(bCofT)->index) );
+        eNode3 = Dec_IntToEdge( Vec_IntEntry(vEdges, Cudd_Regular(bCofE)->index) );
+        // add the complements to the graph nodes
+        eNode2.fCompl ^= Cudd_IsComplement(bCofT);
+        eNode3.fCompl ^= Cudd_IsComplement(bCofE);
+
+        // because the cofactors are vars, we can just as well deref them here
+        Cudd_RecursiveDeref( pManRst->dd, bCofE );
+        Cudd_RecursiveDeref( pManRst->dd, bCofT );
+
+        // find the ABC nodes
+        pNode1 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode1.Node )->pFunc;
+        pNode2 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode2.Node )->pFunc;
+        pNode3 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode3.Node )->pFunc;
+        pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl );
+        pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl );
+        pNode3 = !pNode3? NULL : Abc_ObjNotCond( pNode3, eNode3.fCompl );
+
+        // check if the new node exists
+        Type = 0;
+        pNode4 = NULL;
+        if ( pNode1 && pNode2 && pNode3 )
+            pNode4 = Abc_AigMuxLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, pNode1, pNode2, pNode3, &Type ); 
+
+        // create the new node
+        eResult = Dec_GraphAddNodeMux( pGraph, eNode1, eNode2, eNode3, Type ); // should have the same structure as AIG
+
+        // set level
+        Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level;
+        Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level;
+        Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level;
+        Dec_GraphNode( pGraph, eResult.Node )->Level = 2 + Abc_MaxInt( Abc_MaxInt(Level1, Level2), Level3 );
+        // get the new node if possible
+        if ( pNode4 )
+        {
+            Dec_GraphNode( pGraph, eResult.Node )->pFunc = Abc_ObjNotCond(pNode4, eResult.fCompl);
+            Level4 = Dec_GraphNode( pGraph, eResult.Node )->Level;
+            assert( Required == ABC_INFINITY || Level4 == (int)Abc_ObjRegular(pNode4)->Level );
+        }
+        if ( !pNode4 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode4)) )
+        {
+            (*pnNodesAdded)++;
+            if ( Type == 0 ) 
+            {
+                if ( !pNode1 || !pNode2 )
+                    (*pnNodesAdded)++;
+                else
+                {
+                    pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, pNode1, pNode2 );
+                    if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+                        (*pnNodesAdded)++;
+                }
+                if ( !pNode1 || !pNode3 )
+                    (*pnNodesAdded)++;
+                else
+                {
+                    pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode3 );
+                    if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+                        (*pnNodesAdded)++;
+                }
+            }
+            else
+            {
+                if ( !pNode1 || !pNode2 )
+                    (*pnNodesAdded)++;
+                else
+                {
+                    pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) );
+                    if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+                        (*pnNodesAdded)++;
+                }
+                if ( !pNode1 || !pNode3 )
+                    (*pnNodesAdded)++;
+                else
+                {
+                    pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode3) );
+                    if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+                        (*pnNodesAdded)++;
+                }
+            }
+            if ( *pnNodesAdded > nNodesSaved )
+            {
+                Vec_IntFree( vEdges );
+                return eQuit;
+            }
+        }
+
+        Vec_IntFree( vEdges );
+        // complement the graph if the node was complemented
+        eResult.fCompl ^= fCompl;
+        return eResult;
+    }
+    Vec_IntFree( vEdges );
+    return eQuit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluation one DSD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, Abc_Obj_t * pRoot, int Required, int nNodesSaved, int * pnNodesAdded )
+{
+    Dec_Graph_t * pGraph;
+    Dec_Edge_t gEdge;
+    Abc_Obj_t * pLeaf;
+    Dec_Node_t * pNode;
+    int i;
+
+    // create the graph and set the leaves
+    pGraph = Dec_GraphCreate( Vec_PtrSize(pManRst->vLeaves) );
+    Dec_GraphForEachLeaf( pGraph, pNode, i )
+    {
+        pLeaf = (Abc_Obj_t *)Vec_PtrEntry( pManRst->vLeaves, i );
+        pNode->pFunc = pLeaf;
+        pNode->Level = pLeaf->Level;
+    }
+
+    // create the decomposition structure from the DSD
+    *pnNodesAdded = 0;
+    gEdge = Abc_NodeEvaluateDsd_rec( pGraph, pManRst, pNodeDsd, Required, nNodesSaved, pnNodesAdded );
+    if ( gEdge.Node > 1000 ) // infeasible
+    {
+        *pnNodesAdded = -1;
+        Dec_GraphFree( pGraph );
+        return NULL;
+    }
+
+    // quit if the root node is the same
+    pLeaf = (Abc_Obj_t *)Dec_GraphNode( pGraph, gEdge.Node )->pFunc;
+    if ( Abc_ObjRegular(pLeaf) == pRoot )
+    {
+        *pnNodesAdded = -1;
+        Dec_GraphFree( pGraph );
+        return NULL;
+    }
+
+    Dec_GraphSetRoot( pGraph, gEdge );
+    return pGraph;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the cut manager for rewriting.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fDag )
+{
+    static Cut_Params_t Params, * pParams = &Params;
+    Cut_Man_t * pManCut;
+    Abc_Obj_t * pObj;
+    int i;
+    // start the cut manager
+    memset( pParams, 0, sizeof(Cut_Params_t) );
+    pParams->nVarsMax  = nCutMax; // the max cut size ("k" of the k-feasible cuts)
+    pParams->nKeepMax  = 250;     // the max number of cuts kept at a node
+    pParams->fTruth    = 0;       // compute truth tables
+    pParams->fFilter   = 1;       // filter dominated cuts
+    pParams->fSeq      = 0;       // compute sequential cuts
+    pParams->fDrop     = 0;       // drop cuts on the fly
+    pParams->fDag      = fDag;    // compute DAG cuts
+    pParams->fTree     = 0;       // compute tree cuts
+    pParams->fVerbose  = 0;       // the verbosiness flag
+    pParams->nIdsMax   = Abc_NtkObjNumMax( pNtk );
+    pManCut = Cut_ManStart( pParams );
+    if ( pParams->fDrop )
+        Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) );
+    // set cuts for PIs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        if ( Abc_ObjFanoutNum(pObj) > 0 )
+            Cut_NodeSetTriv( pManCut, pObj->Id );
+    return pManCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, int fUpdateLevel, int fUseZeros, int fVerbose )
+{
+    Abc_ManRst_t * p;
+    p = ABC_ALLOC( Abc_ManRst_t, 1 );
+    memset( p, 0, sizeof(Abc_ManRst_t) );
+    // set the parameters
+    p->nCutMax      = nCutMax;
+    p->fUpdateLevel = fUpdateLevel;
+    p->fUseZeros    = fUseZeros;
+    p->fVerbose     = fVerbose;
+    // start the BDD manager
+    p->dd = Cudd_Init( p->nCutMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    Cudd_zddVarsFromBddVars( p->dd, 2 );
+    // start the DSD manager
+    p->pManDsd = Dsd_ManagerStart( p->dd, p->dd->size, 0 );
+    // other temp datastructures
+    p->vVisited     = Vec_PtrAlloc( 100 );
+    p->vLeaves      = Vec_PtrAlloc( 100 );
+    p->vDecs        = Vec_PtrAlloc( 100 );
+    p->vTemp        = Vec_PtrAlloc( 100 );
+    p->vSims        = Vec_IntAlloc( 100 );
+    p->vOnes        = Vec_IntAlloc( 100 );
+    p->vBinate      = Vec_IntAlloc( 100 );
+    p->vTwos        = Vec_IntAlloc( 100 );
+    p->vRands       = Vec_IntAlloc( 20 );
+    
+    {
+        int i;
+        for ( i = 0; i < 20; i++ )
+            Vec_IntPush( p->vRands, (int)RST_RANDOM_UNSIGNED );
+    }
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkManRstStop( Abc_ManRst_t * p )
+{
+    Dsd_ManagerStop( p->pManDsd );
+    Extra_StopManager( p->dd );
+    Vec_PtrFree( p->vDecs );
+    Vec_PtrFree( p->vLeaves );
+    Vec_PtrFree( p->vVisited );
+    Vec_PtrFree( p->vTemp );
+    Vec_IntFree( p->vSims );
+    Vec_IntFree( p->vOnes );
+    Vec_IntFree( p->vBinate );
+    Vec_IntFree( p->vTwos );
+    Vec_IntFree( p->vRands );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkManRstPrintStats( Abc_ManRst_t * p )
+{
+    printf( "Refactoring statistics:\n" );
+    printf( "Nodes considered   = %8d.\n", p->nNodesConsidered   );
+    printf( "Cuts considered    = %8d.\n", p->nCutsConsidered    );
+    printf( "Cuts explored      = %8d.\n", p->nCutsExplored      );
+    printf( "Nodes restructured = %8d.\n", p->nNodesRestructured );
+    printf( "Calculated gain    = %8d.\n", p->nNodesGained       );
+    ABC_PRT( "Cuts       ", p->timeCut );
+    ABC_PRT( "Resynthesis", p->timeRes );
+    ABC_PRT( "    BDD    ", p->timeBdd );
+    ABC_PRT( "    DSD    ", p->timeDsd );
+    ABC_PRT( "    Eval   ", p->timeEval );
+    ABC_PRT( "AIG update ", p->timeNtk );
+    ABC_PRT( "TOTAL      ", p->timeTotal );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_Abc_NodeResubCollectDivs( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut )
+{
+    Abc_Obj_t * pNode, * pFanout;
+    int i, k;
+    // collect the leaves of the cut
+    Vec_PtrClear( p->vDecs );
+    Abc_NtkIncrementTravId( pRoot->pNtk );
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+    {
+        pNode = Abc_NtkObj(pRoot->pNtk, pCut->pLeaves[i]);
+        if ( pNode == NULL )  // the so-called "bad cut phenomenon" is due to removed nodes
+            return 0;
+        Vec_PtrPush( p->vDecs, pNode );
+        Abc_NodeSetTravIdCurrent( pNode );        
+    }
+    // explore the fanouts
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vDecs, pNode, i )
+    {
+        // if the fanout has both fanins in the set, add it
+        Abc_ObjForEachFanout( pNode, pFanout, k )
+        {
+            if ( Abc_NodeIsTravIdCurrent(pFanout) || Abc_ObjIsPo(pFanout) )
+                continue;
+            if ( Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pFanout)) && Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pFanout)) )
+            {
+                Vec_PtrPush( p->vDecs, pFanout );
+                Abc_NodeSetTravIdCurrent( pFanout );     
+            }
+        }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeResubMffc_rec( Abc_Obj_t * pNode )
+{
+    if ( Abc_NodeIsTravIdCurrent(pNode) )
+        return 0;
+    Abc_NodeSetTravIdCurrent( pNode ); 
+    return 1 + Abc_NodeResubMffc_rec( Abc_ObjFanin0(pNode) ) +
+        Abc_NodeResubMffc_rec( Abc_ObjFanin1(pNode) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeResubMffc( Abc_ManRst_t * p, Vec_Ptr_t * vDecs, int nLeaves, Abc_Obj_t * pRoot )
+{
+    Abc_Obj_t * pObj;
+    int Counter, i, k;
+    // increment the traversal ID for the leaves
+    Abc_NtkIncrementTravId( pRoot->pNtk );
+    // label the leaves
+    Vec_PtrForEachEntryStop( Abc_Obj_t *, vDecs, pObj, i, nLeaves )
+        Abc_NodeSetTravIdCurrent( pObj ); 
+    // make sure the node is in the cone and is no one of the leaves
+    assert( Abc_NodeIsTravIdPrevious(pRoot) );
+    Counter = Abc_NodeResubMffc_rec( pRoot );
+    // move the labeled nodes to the end 
+    Vec_PtrClear( p->vTemp );
+    k = 0;
+    Vec_PtrForEachEntryStart( Abc_Obj_t *, vDecs, pObj, i, nLeaves )
+        if ( Abc_NodeIsTravIdCurrent(pObj) )
+            Vec_PtrPush( p->vTemp, pObj );
+        else
+            Vec_PtrWriteEntry( vDecs, k++, pObj );
+    // add the labeled nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vTemp, pObj, i )
+        Vec_PtrWriteEntry( vDecs, k++, pObj );
+    assert( k == Vec_PtrSize(p->vDecs) );
+    assert( pRoot == Vec_PtrEntryLast(p->vDecs) );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeMffcSimulate( Vec_Ptr_t * vDecs, int nLeaves, Vec_Int_t * vRands, Vec_Int_t * vSims )
+{
+    Abc_Obj_t * pObj;
+    unsigned uData0, uData1, uData;
+    int i;
+    // initialize random simulation data
+    Vec_IntClear( vSims );
+    Vec_PtrForEachEntryStop( Abc_Obj_t *, vDecs, pObj, i, nLeaves )
+    {
+        uData = (unsigned)Vec_IntEntry( vRands, i );
+        pObj->pData = (void *)(ABC_PTRUINT_T)uData;
+        Vec_IntPush( vSims, uData );
+    }
+    // simulate
+    Vec_PtrForEachEntryStart( Abc_Obj_t *, vDecs, pObj, i, nLeaves )
+    {
+        uData0 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pData;
+        uData1 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin1(pObj)->pData;
+        uData = (Abc_ObjFaninC0(pObj)? ~uData0 : uData0) & (Abc_ObjFaninC1(pObj)? ~uData1 : uData1);
+        pObj->pData = (void *)(ABC_PTRUINT_T)uData;
+        Vec_IntPush( vSims, uData );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Full equality check.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCheckFull( Abc_ManRst_t * p, Dec_Graph_t * pGraph )
+{
+    return 1;
+}
+/**Function*************************************************************
+
+  Synopsis    [Detect contants.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeMffcConstants( Abc_ManRst_t * p, Vec_Int_t * vSims )
+{
+    Dec_Graph_t * pGraph = NULL;
+    unsigned uRoot;
+    // get the root node
+    uRoot = (unsigned)Vec_IntEntryLast( vSims );
+    // get the graph if the node looks constant
+    if ( uRoot == 0 )
+        pGraph = Dec_GraphCreateConst0();
+    else if ( uRoot == ~(unsigned)0 )
+        pGraph = Dec_GraphCreateConst1();
+    // check the graph
+    assert(pGraph);
+    if ( Abc_NodeCheckFull( p, pGraph ) )
+        return pGraph;
+    Dec_GraphFree( pGraph );
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detect single non-overlaps.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeMffcSingleVar( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes )
+{
+    Dec_Graph_t * pGraph;
+    unsigned uRoot, uNode;
+    int i;
+
+    Vec_IntClear( vOnes );
+    Vec_IntClear( p->vBinate );
+    uRoot = (unsigned)Vec_IntEntryLast( vSims );
+    for ( i = 0; i < nNodes; i++ )
+    {
+        uNode = (unsigned)Vec_IntEntry( vSims, i );
+        if ( uRoot == uNode || uRoot == ~uNode )
+        {
+            pGraph = Dec_GraphCreate( 1 );
+            Dec_GraphNode( pGraph, 0 )->pFunc = Vec_PtrEntry( p->vDecs, i );
+            Dec_GraphSetRoot( pGraph, Dec_IntToEdge( (int)(uRoot == ~uNode) ) );
+            // check the graph
+            if ( Abc_NodeCheckFull( p, pGraph ) )
+                return pGraph;
+            Dec_GraphFree( pGraph );
+        }
+        if ( (uRoot & uNode) == 0 )
+            Vec_IntPush( vOnes, i << 1 );
+        else if ( (uRoot & ~uNode) == 0 )
+            Vec_IntPush( vOnes, (i << 1) + 1 );
+        else
+            Vec_IntPush( p->vBinate, i );
+    }    
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detect single non-overlaps.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeMffcSingleNode( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes )
+{
+    Dec_Graph_t * pGraph;
+    Dec_Edge_t eNode0, eNode1, eRoot;
+    unsigned uRoot;
+    int i, k;
+    uRoot = (unsigned)Vec_IntEntryLast( vSims );
+    for ( i = 0; i < vOnes->nSize; i++ )
+        for ( k = i+1; k < vOnes->nSize; k++ )
+            if ( ~uRoot == ((unsigned)vOnes->pArray[i] | (unsigned)vOnes->pArray[k]) )
+            {
+                eNode0 = Dec_IntToEdge( vOnes->pArray[i] ^ 1 );
+                eNode1 = Dec_IntToEdge( vOnes->pArray[k] ^ 1 );
+                pGraph = Dec_GraphCreate( 2 );
+                Dec_GraphNode( pGraph, 0 )->pFunc = Vec_PtrEntry( p->vDecs, eNode0.Node );
+                Dec_GraphNode( pGraph, 1 )->pFunc = Vec_PtrEntry( p->vDecs, eNode1.Node );
+                eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
+                Dec_GraphSetRoot( pGraph, eRoot );
+                if ( Abc_NodeCheckFull( p, pGraph ) )
+                    return pGraph;
+                Dec_GraphFree( pGraph );
+            }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detect single non-overlaps.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeMffcDoubleNode( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes )
+{
+//    Dec_Graph_t * pGraph;
+//    unsigned uRoot, uNode;
+//    int i;
+
+
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates resubstution of one cut.]
+
+  Description [Returns the graph to add if any.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeResubEval( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut )
+{
+    Dec_Graph_t * pGraph;
+    int nNodesSaved;
+
+    // collect the nodes in the cut
+    if ( !Abc_Abc_NodeResubCollectDivs( p, pRoot, pCut ) )
+        return NULL;
+
+    // label MFFC and count its size
+    nNodesSaved = Abc_NodeResubMffc( p, p->vDecs, pCut->nLeaves, pRoot );
+    assert( nNodesSaved > 0 );
+
+    // simulate MFFC
+    Abc_NodeMffcSimulate( p->vDecs, pCut->nLeaves, p->vRands, p->vSims );
+
+    // check for constant output
+    pGraph = Abc_NodeMffcConstants( p, p->vSims );
+    if ( pGraph )
+    {
+        p->nNodesGained += nNodesSaved;
+        p->nNodesRestructured++;
+        return pGraph;
+    }
+
+    // check for one literal (fill up the ones array)
+    pGraph = Abc_NodeMffcSingleVar( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes );
+    if ( pGraph )
+    {
+        p->nNodesGained += nNodesSaved;
+        p->nNodesRestructured++;
+        return pGraph;
+    }
+    if ( nNodesSaved == 1 )
+        return NULL;
+
+    // look for one node
+    pGraph = Abc_NodeMffcSingleNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes );
+    if ( pGraph )
+    {
+        p->nNodesGained += nNodesSaved - 1;
+        p->nNodesRestructured++;
+        return pGraph;
+    }
+    if ( nNodesSaved == 2 )
+        return NULL;
+
+    // look for two nodes
+    pGraph = Abc_NodeMffcDoubleNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes );
+    if ( pGraph )
+    {
+        p->nNodesGained += nNodesSaved - 2;
+        p->nNodesRestructured++;
+        return pGraph;
+    }
+    if ( nNodesSaved == 3 )
+        return NULL;
+/*
+    // look for MUX/EXOR
+    pGraph = Abc_NodeMffcMuxNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved );
+    if ( pGraph )
+    {
+        p->nNodesGained += nNodesSaved - 1;
+        p->nNodesRestructured++;
+        return pGraph;
+    }
+*/
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs resubstution.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeResubstitute( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList )
+{
+    Dec_Graph_t * pGraph, * pGraphBest = NULL;
+    Cut_Cut_t * pCut;
+    int nCuts;
+    p->nNodesConsidered++;
+
+    // count the number of cuts with four inputs or more
+    nCuts = 0;
+    for ( pCut = pCutList; pCut; pCut = pCut->pNext )
+        nCuts += (int)(pCut->nLeaves > 3);
+    printf( "-----------------------------------\n" );
+    printf( "Node %6d : Factor-cuts = %5d.\n", pNode->Id, nCuts );
+
+    // go through the interesting cuts
+    for ( pCut = pCutList; pCut; pCut = pCut->pNext )
+    {
+        if ( pCut->nLeaves < 4 )
+            continue;
+        pGraph = Abc_NodeResubEval( p, pNode, pCut );
+        if ( pGraph == NULL )
+            continue;
+        if ( !pGraphBest || Dec_GraphNodeNum(pGraph) < Dec_GraphNodeNum(pGraphBest) )
+        {
+            if ( pGraphBest ) 
+                Dec_GraphFree(pGraphBest);
+            pGraphBest = pGraph;
+        }
+        else
+            Dec_GraphFree(pGraph);
+    }
+    return pGraphBest;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcResub.c b/abc-build/src/base/abci/abcResub.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcResub.c
@@ -0,0 +1,1957 @@
+/**CFile****************************************************************
+
+  FileName    [abcResub.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Resubstitution manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "bool/dec/dec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+ 
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define ABC_RS_DIV1_MAX    150   // the max number of divisors to consider
+#define ABC_RS_DIV2_MAX    500   // the max number of pair-wise divisors to consider
+
+typedef struct Abc_ManRes_t_ Abc_ManRes_t;
+struct Abc_ManRes_t_
+{
+    // paramers
+    int                nLeavesMax; // the max number of leaves in the cone
+    int                nDivsMax;   // the max number of divisors in the cone
+    // representation of the cone
+    Abc_Obj_t *        pRoot;      // the root of the cone
+    int                nLeaves;    // the number of leaves
+    int                nDivs;      // the number of all divisor (including leaves)
+    int                nMffc;      // the size of MFFC
+    int                nLastGain;  // the gain the number of nodes
+    Vec_Ptr_t *        vDivs;      // the divisors
+    // representation of the simulation info
+    int                nBits;      // the number of simulation bits
+    int                nWords;     // the number of unsigneds for siminfo
+    Vec_Ptr_t        * vSims;      // simulation info
+    unsigned         * pInfo;      // pointer to simulation info
+    // observability don't-cares
+    unsigned *         pCareSet;
+    // internal divisor storage
+    Vec_Ptr_t        * vDivs1UP;   // the single-node unate divisors
+    Vec_Ptr_t        * vDivs1UN;   // the single-node unate divisors
+    Vec_Ptr_t        * vDivs1B;    // the single-node binate divisors
+    Vec_Ptr_t        * vDivs2UP0;  // the double-node unate divisors
+    Vec_Ptr_t        * vDivs2UP1;  // the double-node unate divisors
+    Vec_Ptr_t        * vDivs2UN0;  // the double-node unate divisors
+    Vec_Ptr_t        * vDivs2UN1;  // the double-node unate divisors
+    // other data
+    Vec_Ptr_t        * vTemp;      // temporary array of nodes
+    // runtime statistics
+    abctime            timeCut;
+    abctime            timeTruth;
+    abctime            timeRes;
+    abctime            timeDiv;
+    abctime            timeMffc;
+    abctime            timeSim;
+    abctime            timeRes1;
+    abctime            timeResD;
+    abctime            timeRes2;
+    abctime            timeRes3;
+    abctime            timeNtk;
+    abctime            timeTotal;
+    // improvement statistics
+    int                nUsedNodeC;
+    int                nUsedNode0;
+    int                nUsedNode1Or;
+    int                nUsedNode1And;
+    int                nUsedNode2Or;
+    int                nUsedNode2And;
+    int                nUsedNode2OrAnd;
+    int                nUsedNode2AndOr;
+    int                nUsedNode3OrAnd;
+    int                nUsedNode3AndOr;
+    int                nUsedNodeTotal;
+    int                nTotalDivs;
+    int                nTotalLeaves;
+    int                nTotalGain;
+    int                nNodesBeg;
+    int                nNodesEnd;
+};
+
+// external procedures
+static Abc_ManRes_t* Abc_ManResubStart( int nLeavesMax, int nDivsMax );
+static void          Abc_ManResubStop( Abc_ManRes_t * p );
+static Dec_Graph_t * Abc_ManResubEval( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int nSteps, int fUpdateLevel, int fVerbose );
+static void          Abc_ManResubCleanup( Abc_ManRes_t * p );
+static void          Abc_ManResubPrint( Abc_ManRes_t * p );
+
+// other procedures
+static int           Abc_ManResubCollectDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int Required );
+static void          Abc_ManResubSimulate( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords );
+static void          Abc_ManResubPrintDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves );
+
+static void          Abc_ManResubDivsS( Abc_ManRes_t * p, int Required );
+static void          Abc_ManResubDivsD( Abc_ManRes_t * p, int Required );
+static Dec_Graph_t * Abc_ManResubQuit( Abc_ManRes_t * p );
+static Dec_Graph_t * Abc_ManResubDivs0( Abc_ManRes_t * p );
+static Dec_Graph_t * Abc_ManResubDivs1( Abc_ManRes_t * p, int Required );
+static Dec_Graph_t * Abc_ManResubDivs12( Abc_ManRes_t * p, int Required );
+static Dec_Graph_t * Abc_ManResubDivs2( Abc_ManRes_t * p, int Required );
+static Dec_Graph_t * Abc_ManResubDivs3( Abc_ManRes_t * p, int Required );
+
+static Vec_Ptr_t *   Abc_CutFactorLarge( Abc_Obj_t * pNode, int nLeavesMax );
+static int           Abc_CutVolumeCheck( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves );
+
+extern abctime s_ResubTime;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs incremental resynthesis of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutMax, int nStepsMax, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose )
+{
+    extern void           Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain );
+    ProgressBar * pProgress;
+    Abc_ManRes_t * pManRes;
+    Abc_ManCut_t * pManCut;
+    Odc_Man_t * pManOdc = NULL;
+    Dec_Graph_t * pFForm;
+    Vec_Ptr_t * vLeaves;
+    Abc_Obj_t * pNode;
+    abctime clk, clkStart = Abc_Clock();
+    int i, nNodes;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    // cleanup the AIG
+    Abc_AigCleanup((Abc_Aig_t *)pNtk->pManFunc);
+    // start the managers
+    pManCut = Abc_NtkManCutStart( nCutMax, 100000, 100000, 100000 );
+    pManRes = Abc_ManResubStart( nCutMax, ABC_RS_DIV1_MAX );
+    if ( nLevelsOdc > 0 )
+    pManOdc = Abc_NtkDontCareAlloc( nCutMax, nLevelsOdc, fVerbose, fVeryVerbose );
+
+    // compute the reverse levels if level update is requested
+    if ( fUpdateLevel )
+        Abc_NtkStartReverseLevels( pNtk, 0 );
+
+    if ( Abc_NtkLatchNum(pNtk) ) {
+        Abc_NtkForEachLatch(pNtk, pNode, i)
+            pNode->pNext = (Abc_Obj_t *)pNode->pData;
+    }
+
+    // resynthesize each node once
+    pManRes->nNodesBeg = Abc_NtkNodeNum(pNtk);
+    nNodes = Abc_NtkObjNumMax(pNtk);
+    pProgress = Extra_ProgressBarStart( stdout, nNodes );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        // skip the constant node
+//        if ( Abc_NodeIsConst(pNode) )
+//            continue;
+        // skip persistant nodes
+        if ( Abc_NodeIsPersistant(pNode) )
+            continue;
+        // skip the nodes with many fanouts
+        if ( Abc_ObjFanoutNum(pNode) > 1000 )
+            continue;
+        // stop if all nodes have been tried once
+        if ( i >= nNodes )
+            break;
+
+        // compute a reconvergence-driven cut
+clk = Abc_Clock();
+        vLeaves = Abc_NodeFindCut( pManCut, pNode, 0 );
+//        vLeaves = Abc_CutFactorLarge( pNode, nCutMax );
+pManRes->timeCut += Abc_Clock() - clk;
+/*
+        if ( fVerbose && vLeaves )
+        printf( "Node %6d : Leaves = %3d. Volume = %3d.\n", pNode->Id, Vec_PtrSize(vLeaves), Abc_CutVolumeCheck(pNode, vLeaves) );
+        if ( vLeaves == NULL )
+            continue;
+*/
+        // get the don't-cares
+        if ( pManOdc )
+        {
+clk = Abc_Clock();
+            Abc_NtkDontCareClear( pManOdc );
+            Abc_NtkDontCareCompute( pManOdc, pNode, vLeaves, pManRes->pCareSet );
+pManRes->timeTruth += Abc_Clock() - clk;
+        }
+
+        // evaluate this cut
+clk = Abc_Clock();
+        pFForm = Abc_ManResubEval( pManRes, pNode, vLeaves, nStepsMax, fUpdateLevel, fVerbose );
+//        Vec_PtrFree( vLeaves );
+//        Abc_ManResubCleanup( pManRes );
+pManRes->timeRes += Abc_Clock() - clk;
+        if ( pFForm == NULL )
+            continue;
+        pManRes->nTotalGain += pManRes->nLastGain;
+/*
+        if ( pManRes->nLeaves == 4 && pManRes->nMffc == 2 && pManRes->nLastGain == 1 )
+        {
+            printf( "%6d :  L = %2d. V = %2d. Mffc = %2d. Divs = %3d.   Up = %3d. Un = %3d. B = %3d.\n", 
+                   pNode->Id, pManRes->nLeaves, Abc_CutVolumeCheck(pNode, vLeaves), pManRes->nMffc, pManRes->nDivs, 
+                   pManRes->vDivs1UP->nSize, pManRes->vDivs1UN->nSize, pManRes->vDivs1B->nSize );
+            Abc_ManResubPrintDivs( pManRes, pNode, vLeaves );
+        }
+*/
+        // acceptable replacement found, update the graph
+clk = Abc_Clock();
+        Dec_GraphUpdateNetwork( pNode, pFForm, fUpdateLevel, pManRes->nLastGain );
+pManRes->timeNtk += Abc_Clock() - clk;
+        Dec_GraphFree( pFForm );
+    }
+    Extra_ProgressBarStop( pProgress );
+pManRes->timeTotal = Abc_Clock() - clkStart;
+    pManRes->nNodesEnd = Abc_NtkNodeNum(pNtk);
+
+    // print statistics
+    if ( fVerbose )
+    Abc_ManResubPrint( pManRes );
+
+    // delete the managers
+    Abc_ManResubStop( pManRes );
+    Abc_NtkManCutStop( pManCut );
+    if ( pManOdc ) Abc_NtkDontCareFree( pManOdc );
+
+    // clean the data field
+    Abc_NtkForEachObj( pNtk, pNode, i )
+        pNode->pData = NULL;
+
+    if ( Abc_NtkLatchNum(pNtk) ) {
+        Abc_NtkForEachLatch(pNtk, pNode, i)
+            pNode->pData = pNode->pNext, pNode->pNext = NULL;
+    }
+
+    // put the nodes into the DFS order and reassign their IDs
+    Abc_NtkReassignIds( pNtk );
+//    Abc_AigCheckFaninOrder( pNtk->pManFunc );
+    // fix the levels
+    if ( fUpdateLevel )
+        Abc_NtkStopReverseLevels( pNtk );
+    else
+        Abc_NtkLevel( pNtk );
+    // check
+    if ( !Abc_NtkCheck( pNtk ) )
+    {
+        printf( "Abc_NtkRefactor: The network check has failed.\n" );
+        return 0;
+    }
+s_ResubTime = Abc_Clock() - clkStart;
+    return 1;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_ManRes_t * Abc_ManResubStart( int nLeavesMax, int nDivsMax )
+{
+    Abc_ManRes_t * p;
+    unsigned * pData;
+    int i, k;
+    assert( sizeof(unsigned) == 4 );
+    p = ABC_ALLOC( Abc_ManRes_t, 1 );
+    memset( p, 0, sizeof(Abc_ManRes_t) );
+    p->nLeavesMax = nLeavesMax;
+    p->nDivsMax   = nDivsMax;
+    p->vDivs      = Vec_PtrAlloc( p->nDivsMax );
+    // allocate simulation info
+    p->nBits      = (1 << p->nLeavesMax);
+    p->nWords     = (p->nBits <= 32)? 1 : (p->nBits / 32);
+    p->pInfo      = ABC_ALLOC( unsigned, p->nWords * (p->nDivsMax + 1) );
+    memset( p->pInfo, 0, sizeof(unsigned) * p->nWords * p->nLeavesMax );
+    p->vSims      = Vec_PtrAlloc( p->nDivsMax );
+    for ( i = 0; i < p->nDivsMax; i++ )
+        Vec_PtrPush( p->vSims, p->pInfo + i * p->nWords );
+    // assign the care set
+    p->pCareSet  = p->pInfo + p->nDivsMax * p->nWords;
+    Abc_InfoFill( p->pCareSet, p->nWords );
+    // set elementary truth tables
+    for ( k = 0; k < p->nLeavesMax; k++ )
+    {
+        pData = (unsigned *)p->vSims->pArray[k];
+        for ( i = 0; i < p->nBits; i++ )
+            if ( i & (1 << k) )
+                pData[i>>5] |= (1 << (i&31));
+    }
+    // create the remaining divisors
+    p->vDivs1UP  = Vec_PtrAlloc( p->nDivsMax );
+    p->vDivs1UN  = Vec_PtrAlloc( p->nDivsMax );
+    p->vDivs1B   = Vec_PtrAlloc( p->nDivsMax );
+    p->vDivs2UP0 = Vec_PtrAlloc( p->nDivsMax );
+    p->vDivs2UP1 = Vec_PtrAlloc( p->nDivsMax );
+    p->vDivs2UN0 = Vec_PtrAlloc( p->nDivsMax );
+    p->vDivs2UN1 = Vec_PtrAlloc( p->nDivsMax );
+    p->vTemp     = Vec_PtrAlloc( p->nDivsMax );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ManResubStop( Abc_ManRes_t * p )
+{
+    Vec_PtrFree( p->vDivs );
+    Vec_PtrFree( p->vSims );
+    Vec_PtrFree( p->vDivs1UP );
+    Vec_PtrFree( p->vDivs1UN );
+    Vec_PtrFree( p->vDivs1B );
+    Vec_PtrFree( p->vDivs2UP0 );
+    Vec_PtrFree( p->vDivs2UP1 );
+    Vec_PtrFree( p->vDivs2UN0 );
+    Vec_PtrFree( p->vDivs2UN1 );
+    Vec_PtrFree( p->vTemp );
+    ABC_FREE( p->pInfo );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ManResubPrint( Abc_ManRes_t * p )
+{
+    printf( "Used constants    = %6d.             ", p->nUsedNodeC );          ABC_PRT( "Cuts  ", p->timeCut );
+    printf( "Used replacements = %6d.             ", p->nUsedNode0 );          ABC_PRT( "Resub ", p->timeRes );
+    printf( "Used single ORs   = %6d.             ", p->nUsedNode1Or );        ABC_PRT( " Div  ", p->timeDiv );
+    printf( "Used single ANDs  = %6d.             ", p->nUsedNode1And );       ABC_PRT( " Mffc ", p->timeMffc );
+    printf( "Used double ORs   = %6d.             ", p->nUsedNode2Or );        ABC_PRT( " Sim  ", p->timeSim );
+    printf( "Used double ANDs  = %6d.             ", p->nUsedNode2And );       ABC_PRT( " 1    ", p->timeRes1 );
+    printf( "Used OR-AND       = %6d.             ", p->nUsedNode2OrAnd );     ABC_PRT( " D    ", p->timeResD );
+    printf( "Used AND-OR       = %6d.             ", p->nUsedNode2AndOr );     ABC_PRT( " 2    ", p->timeRes2 );
+    printf( "Used OR-2ANDs     = %6d.             ", p->nUsedNode3OrAnd );     ABC_PRT( "Truth ", p->timeTruth ); //ABC_PRT( " 3    ", p->timeRes3 );
+    printf( "Used AND-2ORs     = %6d.             ", p->nUsedNode3AndOr );     ABC_PRT( "AIG   ", p->timeNtk );
+    printf( "TOTAL             = %6d.             ", p->nUsedNodeC +
+                                                     p->nUsedNode0 +
+                                                     p->nUsedNode1Or +
+                                                     p->nUsedNode1And +
+                                                     p->nUsedNode2Or +
+                                                     p->nUsedNode2And +
+                                                     p->nUsedNode2OrAnd +
+                                                     p->nUsedNode2AndOr +
+                                                     p->nUsedNode3OrAnd +
+                                                     p->nUsedNode3AndOr
+                                                   );                          ABC_PRT( "TOTAL ", p->timeTotal );
+    printf( "Total leaves   = %8d.\n", p->nTotalLeaves );
+    printf( "Total divisors = %8d.\n", p->nTotalDivs );
+//    printf( "Total gain     = %8d.\n", p->nTotalGain );
+    printf( "Gain           = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ManResubCollectDivs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vInternal )
+{
+    // skip visited nodes
+    if ( Abc_NodeIsTravIdCurrent(pNode) )
+        return;
+    Abc_NodeSetTravIdCurrent(pNode);
+    // collect the fanins
+    Abc_ManResubCollectDivs_rec( Abc_ObjFanin0(pNode), vInternal );
+    Abc_ManResubCollectDivs_rec( Abc_ObjFanin1(pNode), vInternal );
+    // collect the internal node
+    if ( pNode->fMarkA == 0 ) 
+        Vec_PtrPush( vInternal, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ManResubCollectDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int Required )
+{
+    Abc_Obj_t * pNode, * pFanout;
+    int i, k, Limit, Counter;
+
+    Vec_PtrClear( p->vDivs1UP );
+    Vec_PtrClear( p->vDivs1UN );
+    Vec_PtrClear( p->vDivs1B );
+
+    // add the leaves of the cuts to the divisors
+    Vec_PtrClear( p->vDivs );
+    Abc_NtkIncrementTravId( pRoot->pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i )
+    {
+        Vec_PtrPush( p->vDivs, pNode );
+        Abc_NodeSetTravIdCurrent( pNode );        
+    }
+
+    // mark nodes in the MFFC
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vTemp, pNode, i )
+        pNode->fMarkA = 1;
+    // collect the cone (without MFFC)
+    Abc_ManResubCollectDivs_rec( pRoot, p->vDivs );
+    // unmark the current MFFC
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vTemp, pNode, i )
+        pNode->fMarkA = 0;
+
+    // check if the number of divisors is not exceeded
+    if ( Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) + Vec_PtrSize(p->vTemp) >= Vec_PtrSize(p->vSims) - p->nLeavesMax )
+        return 0;
+
+    // get the number of divisors to collect
+    Limit = Vec_PtrSize(p->vSims) - p->nLeavesMax - (Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) + Vec_PtrSize(p->vTemp));
+
+    // explore the fanouts, which are not in the MFFC
+    Counter = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs, pNode, i )
+    {
+        if ( Abc_ObjFanoutNum(pNode) > 100 )
+        {
+//            printf( "%d ", Abc_ObjFanoutNum(pNode) );
+            continue;
+        }
+        // if the fanout has both fanins in the set, add it
+        Abc_ObjForEachFanout( pNode, pFanout, k )
+        {
+            if ( Abc_NodeIsTravIdCurrent(pFanout) || Abc_ObjIsCo(pFanout) || (int)pFanout->Level > Required )
+                continue;
+            if ( Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pFanout)) && Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pFanout)) )
+            {
+                if ( Abc_ObjFanin0(pFanout) == pRoot || Abc_ObjFanin1(pFanout) == pRoot )
+                    continue;
+                Vec_PtrPush( p->vDivs, pFanout );
+                Abc_NodeSetTravIdCurrent( pFanout );
+                // quit computing divisors if there is too many of them
+                if ( ++Counter == Limit )
+                    goto Quits;
+            }
+        }
+    }
+
+Quits :
+    // get the number of divisors
+    p->nDivs = Vec_PtrSize(p->vDivs);
+
+    // add the nodes in the MFFC
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vTemp, pNode, i )
+        Vec_PtrPush( p->vDivs, pNode );
+    assert( pRoot == Vec_PtrEntryLast(p->vDivs) );
+
+    assert( Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) <= Vec_PtrSize(p->vSims) - p->nLeavesMax );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ManResubPrintDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves )
+{
+    Abc_Obj_t * pFanin, * pNode;
+    int i, k;
+    // print the nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs, pNode, i )
+    {
+        if ( i < Vec_PtrSize(vLeaves) )
+        {
+            printf( "%6d : %c\n", pNode->Id, 'a'+i );
+            continue;
+        }
+        printf( "%6d : %2d = ", pNode->Id, i );
+        // find the first fanin
+        Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs, pFanin, k )
+            if ( Abc_ObjFanin0(pNode) == pFanin )
+                break;
+        if ( k < Vec_PtrSize(vLeaves) )
+            printf( "%c", 'a' + k );
+        else
+            printf( "%d", k );
+        printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" );
+        // find the second fanin
+        Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs, pFanin, k )
+            if ( Abc_ObjFanin1(pNode) == pFanin )
+                break;
+        if ( k < Vec_PtrSize(vLeaves) )
+            printf( "%c", 'a' + k );
+        else
+            printf( "%d", k );
+        printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" );
+        if ( pNode == pRoot )
+            printf( " root" );
+        printf( "\n" );
+    }
+    printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ManResubSimulate( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords )
+{
+    Abc_Obj_t * pObj;
+    unsigned * puData0, * puData1, * puData;
+    int i, k;
+    assert( Vec_PtrSize(vDivs) - nLeaves <= Vec_PtrSize(vSims) - nLeavesMax );
+    // simulate
+    Vec_PtrForEachEntry( Abc_Obj_t *, vDivs, pObj, i )
+    {
+        if ( i < nLeaves )
+        { // initialize the leaf
+            pObj->pData = Vec_PtrEntry( vSims, i );
+            continue;
+        }
+        // set storage for the node's simulation info
+        pObj->pData = Vec_PtrEntry( vSims, i - nLeaves + nLeavesMax );
+        // get pointer to the simulation info
+        puData  = (unsigned *)pObj->pData;
+        puData0 = (unsigned *)Abc_ObjFanin0(pObj)->pData;
+        puData1 = (unsigned *)Abc_ObjFanin1(pObj)->pData;
+        // simulate
+        if ( Abc_ObjFaninC0(pObj) && Abc_ObjFaninC1(pObj) )
+            for ( k = 0; k < nWords; k++ )
+                puData[k] = ~puData0[k] & ~puData1[k];
+        else if ( Abc_ObjFaninC0(pObj) )
+            for ( k = 0; k < nWords; k++ )
+                puData[k] = ~puData0[k] & puData1[k];
+        else if ( Abc_ObjFaninC1(pObj) )
+            for ( k = 0; k < nWords; k++ )
+                puData[k] = puData0[k] & ~puData1[k];
+        else 
+            for ( k = 0; k < nWords; k++ )
+                puData[k] = puData0[k] & puData1[k];
+    }
+    // normalize
+    Vec_PtrForEachEntry( Abc_Obj_t *, vDivs, pObj, i )
+    {
+        puData = (unsigned *)pObj->pData;
+        pObj->fPhase = (puData[0] & 1);
+        if ( pObj->fPhase )
+            for ( k = 0; k < nWords; k++ )
+                puData[k] = ~puData[k];
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit0( Abc_Obj_t * pRoot, Abc_Obj_t * pObj )
+{
+    Dec_Graph_t * pGraph;
+    Dec_Edge_t eRoot;
+    pGraph = Dec_GraphCreate( 1 );
+    Dec_GraphNode( pGraph, 0 )->pFunc = pObj;
+    eRoot = Dec_EdgeCreate( 0, pObj->fPhase );
+    Dec_GraphSetRoot( pGraph, eRoot );
+    if ( pRoot->fPhase )
+        Dec_GraphComplement( pGraph );
+    return pGraph;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit1( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, int fOrGate )
+{
+    Dec_Graph_t * pGraph;
+    Dec_Edge_t eRoot, eNode0, eNode1;
+    assert( pObj0 != pObj1 );
+    assert( !Abc_ObjIsComplement(pObj0) );
+    assert( !Abc_ObjIsComplement(pObj1) );
+    pGraph = Dec_GraphCreate( 2 );
+    Dec_GraphNode( pGraph, 0 )->pFunc = pObj0;
+    Dec_GraphNode( pGraph, 1 )->pFunc = pObj1;
+    eNode0 = Dec_EdgeCreate( 0, pObj0->fPhase );
+    eNode1 = Dec_EdgeCreate( 1, pObj1->fPhase );
+    if ( fOrGate ) 
+        eRoot  = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+    else
+        eRoot  = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
+    Dec_GraphSetRoot( pGraph, eRoot );
+    if ( pRoot->fPhase )
+        Dec_GraphComplement( pGraph );
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit21( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, int fOrGate )
+{
+    Dec_Graph_t * pGraph;
+    Dec_Edge_t eRoot, eNode0, eNode1, eNode2;
+    assert( pObj0 != pObj1 );
+    assert( !Abc_ObjIsComplement(pObj0) );
+    assert( !Abc_ObjIsComplement(pObj1) );
+    assert( !Abc_ObjIsComplement(pObj2) );
+    pGraph = Dec_GraphCreate( 3 );
+    Dec_GraphNode( pGraph, 0 )->pFunc = pObj0;
+    Dec_GraphNode( pGraph, 1 )->pFunc = pObj1;
+    Dec_GraphNode( pGraph, 2 )->pFunc = pObj2;
+    eNode0 = Dec_EdgeCreate( 0, pObj0->fPhase );
+    eNode1 = Dec_EdgeCreate( 1, pObj1->fPhase );
+    eNode2 = Dec_EdgeCreate( 2, pObj2->fPhase );
+    if ( fOrGate ) 
+    {
+        eRoot  = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+        eRoot  = Dec_GraphAddNodeOr( pGraph, eNode2, eRoot );
+    }
+    else
+    {
+        eRoot  = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
+        eRoot  = Dec_GraphAddNodeAnd( pGraph, eNode2, eRoot );
+    }
+    Dec_GraphSetRoot( pGraph, eRoot );
+    if ( pRoot->fPhase )
+        Dec_GraphComplement( pGraph );
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit2( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, int fOrGate )
+{
+    Dec_Graph_t * pGraph;
+    Dec_Edge_t eRoot, ePrev, eNode0, eNode1, eNode2;
+    assert( pObj0 != pObj1 );
+    assert( pObj0 != pObj2 );
+    assert( pObj1 != pObj2 );
+    assert( !Abc_ObjIsComplement(pObj0) );
+    pGraph = Dec_GraphCreate( 3 );
+    Dec_GraphNode( pGraph, 0 )->pFunc = Abc_ObjRegular(pObj0);
+    Dec_GraphNode( pGraph, 1 )->pFunc = Abc_ObjRegular(pObj1);
+    Dec_GraphNode( pGraph, 2 )->pFunc = Abc_ObjRegular(pObj2);
+    eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase );
+    if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) )
+    {
+        eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase );
+        eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase );
+        ePrev  = Dec_GraphAddNodeOr( pGraph, eNode1, eNode2 );
+    }
+    else
+    {
+        eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ^ Abc_ObjIsComplement(pObj1) );
+        eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) );
+        ePrev  = Dec_GraphAddNodeAnd( pGraph, eNode1, eNode2 );
+    }
+    if ( fOrGate ) 
+        eRoot  = Dec_GraphAddNodeOr( pGraph, eNode0, ePrev );
+    else
+        eRoot  = Dec_GraphAddNodeAnd( pGraph, eNode0, ePrev );
+    Dec_GraphSetRoot( pGraph, eRoot );
+    if ( pRoot->fPhase )
+        Dec_GraphComplement( pGraph );
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit3( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, Abc_Obj_t * pObj3, int fOrGate )
+{
+    Dec_Graph_t * pGraph;
+    Dec_Edge_t eRoot, ePrev0, ePrev1, eNode0, eNode1, eNode2, eNode3;
+    assert( pObj0 != pObj1 );
+    assert( pObj2 != pObj3 );
+    pGraph = Dec_GraphCreate( 4 );
+    Dec_GraphNode( pGraph, 0 )->pFunc = Abc_ObjRegular(pObj0);
+    Dec_GraphNode( pGraph, 1 )->pFunc = Abc_ObjRegular(pObj1);
+    Dec_GraphNode( pGraph, 2 )->pFunc = Abc_ObjRegular(pObj2);
+    Dec_GraphNode( pGraph, 3 )->pFunc = Abc_ObjRegular(pObj3);
+    if ( Abc_ObjIsComplement(pObj0) && Abc_ObjIsComplement(pObj1) )
+    {
+        eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase );
+        eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase );
+        ePrev0 = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+        if ( Abc_ObjIsComplement(pObj2) && Abc_ObjIsComplement(pObj3) )
+        {
+            eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase );
+            eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase );
+            ePrev1 = Dec_GraphAddNodeOr( pGraph, eNode2, eNode3 );
+        }
+        else
+        {
+            eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) );
+            eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ^ Abc_ObjIsComplement(pObj3) );
+            ePrev1 = Dec_GraphAddNodeAnd( pGraph, eNode2, eNode3 );
+        }
+    }
+    else
+    {
+        eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase ^ Abc_ObjIsComplement(pObj0) );
+        eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ^ Abc_ObjIsComplement(pObj1) );
+        ePrev0 = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
+        if ( Abc_ObjIsComplement(pObj2) && Abc_ObjIsComplement(pObj3) )
+        {
+            eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase );
+            eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase );
+            ePrev1 = Dec_GraphAddNodeOr( pGraph, eNode2, eNode3 );
+        }
+        else
+        {
+            eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) );
+            eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ^ Abc_ObjIsComplement(pObj3) );
+            ePrev1 = Dec_GraphAddNodeAnd( pGraph, eNode2, eNode3 );
+        }
+    }
+    if ( fOrGate ) 
+        eRoot = Dec_GraphAddNodeOr( pGraph, ePrev0, ePrev1 );
+    else
+        eRoot = Dec_GraphAddNodeAnd( pGraph, ePrev0, ePrev1 );
+    Dec_GraphSetRoot( pGraph, eRoot );
+    if ( pRoot->fPhase )
+        Dec_GraphComplement( pGraph );
+    return pGraph;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives single-node unate/binate divisors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ManResubDivsS( Abc_ManRes_t * p, int Required )
+{
+    Abc_Obj_t * pObj;
+    unsigned * puData, * puDataR;
+    int i, w;
+    Vec_PtrClear( p->vDivs1UP );
+    Vec_PtrClear( p->vDivs1UN );
+    Vec_PtrClear( p->vDivs1B );
+    puDataR = (unsigned *)p->pRoot->pData;
+    Vec_PtrForEachEntryStop( Abc_Obj_t *, p->vDivs, pObj, i, p->nDivs )
+    {
+        if ( (int)pObj->Level > Required - 1 )
+            continue;
+
+        puData = (unsigned *)pObj->pData;
+        // check positive containment
+        for ( w = 0; w < p->nWords; w++ )
+//            if ( puData[w] & ~puDataR[w] )
+            if ( puData[w] & ~puDataR[w] & p->pCareSet[w] ) // care set
+                break;
+        if ( w == p->nWords )
+        {
+            Vec_PtrPush( p->vDivs1UP, pObj );
+            continue;
+        }
+        // check negative containment
+        for ( w = 0; w < p->nWords; w++ )
+//            if ( ~puData[w] & puDataR[w] )
+            if ( ~puData[w] & puDataR[w] & p->pCareSet[w] ) // care set
+                break;
+        if ( w == p->nWords )
+        {
+            Vec_PtrPush( p->vDivs1UN, pObj );
+            continue;
+        }
+        // add the node to binates
+        Vec_PtrPush( p->vDivs1B, pObj );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives double-node unate/binate divisors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ManResubDivsD( Abc_ManRes_t * p, int Required )
+{
+    Abc_Obj_t * pObj0, * pObj1;
+    unsigned * puData0, * puData1, * puDataR;
+    int i, k, w;
+    Vec_PtrClear( p->vDivs2UP0 );
+    Vec_PtrClear( p->vDivs2UP1 );
+    Vec_PtrClear( p->vDivs2UN0 );
+    Vec_PtrClear( p->vDivs2UN1 );
+    puDataR = (unsigned *)p->pRoot->pData;
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs1B, pObj0, i )
+    {
+        if ( (int)pObj0->Level > Required - 2 )
+            continue;
+
+        puData0 = (unsigned *)pObj0->pData;
+        Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs1B, pObj1, k, i + 1 )
+        {
+            if ( (int)pObj1->Level > Required - 2 )
+                continue;
+
+            puData1 = (unsigned *)pObj1->pData;
+
+            if ( Vec_PtrSize(p->vDivs2UP0) < ABC_RS_DIV2_MAX )
+            {
+                // get positive unate divisors
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( (puData0[w] & puData1[w]) & ~puDataR[w] )
+                    if ( (puData0[w] & puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set
+                        break;
+                if ( w == p->nWords )
+                {
+                    Vec_PtrPush( p->vDivs2UP0, pObj0 );
+                    Vec_PtrPush( p->vDivs2UP1, pObj1 );
+                }
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( (~puData0[w] & puData1[w]) & ~puDataR[w] )
+                    if ( (~puData0[w] & puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set
+                        break;
+                if ( w == p->nWords )
+                {
+                    Vec_PtrPush( p->vDivs2UP0, Abc_ObjNot(pObj0) );
+                    Vec_PtrPush( p->vDivs2UP1, pObj1 );
+                }
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( (puData0[w] & ~puData1[w]) & ~puDataR[w] )
+                    if ( (puData0[w] & ~puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set
+                        break;
+                if ( w == p->nWords )
+                {
+                    Vec_PtrPush( p->vDivs2UP0, pObj0 );
+                    Vec_PtrPush( p->vDivs2UP1, Abc_ObjNot(pObj1) );
+                }
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( (puData0[w] | puData1[w]) & ~puDataR[w] )
+                    if ( (puData0[w] | puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set
+                        break;
+                if ( w == p->nWords )
+                {
+                    Vec_PtrPush( p->vDivs2UP0, Abc_ObjNot(pObj0) );
+                    Vec_PtrPush( p->vDivs2UP1, Abc_ObjNot(pObj1) );
+                }
+            }
+
+            if ( Vec_PtrSize(p->vDivs2UN0) < ABC_RS_DIV2_MAX )
+            {
+                // get negative unate divisors
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ~(puData0[w] & puData1[w]) & puDataR[w] )
+                    if ( ~(puData0[w] & puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set
+                        break;
+                if ( w == p->nWords )
+                {
+                    Vec_PtrPush( p->vDivs2UN0, pObj0 );
+                    Vec_PtrPush( p->vDivs2UN1, pObj1 );
+                }
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ~(~puData0[w] & puData1[w]) & puDataR[w] )
+                    if ( ~(~puData0[w] & puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set
+                        break;
+                if ( w == p->nWords )
+                {
+                    Vec_PtrPush( p->vDivs2UN0, Abc_ObjNot(pObj0) );
+                    Vec_PtrPush( p->vDivs2UN1, pObj1 );
+                }
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ~(puData0[w] & ~puData1[w]) & puDataR[w] )
+                    if ( ~(puData0[w] & ~puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set
+                        break;
+                if ( w == p->nWords )
+                {
+                    Vec_PtrPush( p->vDivs2UN0, pObj0 );
+                    Vec_PtrPush( p->vDivs2UN1, Abc_ObjNot(pObj1) );
+                }
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ~(puData0[w] | puData1[w]) & puDataR[w] )
+                    if ( ~(puData0[w] | puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set
+                        break;
+                if ( w == p->nWords )
+                {
+                    Vec_PtrPush( p->vDivs2UN0, Abc_ObjNot(pObj0) );
+                    Vec_PtrPush( p->vDivs2UN1, Abc_ObjNot(pObj1) );
+                }
+            }
+        }
+    }
+//    printf( "%d %d  ", Vec_PtrSize(p->vDivs2UP0), Vec_PtrSize(p->vDivs2UN0) );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit( Abc_ManRes_t * p )
+{
+    Dec_Graph_t * pGraph;
+    unsigned * upData;
+    int w;
+    upData = (unsigned *)p->pRoot->pData;
+    for ( w = 0; w < p->nWords; w++ )
+//        if ( upData[w] )
+        if ( upData[w] & p->pCareSet[w] ) // care set
+            break;
+    if ( w != p->nWords )
+        return NULL;
+    // get constant node graph
+    if ( p->pRoot->fPhase )
+        pGraph = Dec_GraphCreateConst1();
+    else 
+        pGraph = Dec_GraphCreateConst0();
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubDivs0( Abc_ManRes_t * p )
+{
+    Abc_Obj_t * pObj;
+    unsigned * puData, * puDataR;
+    int i, w;
+    puDataR = (unsigned *)p->pRoot->pData;
+    Vec_PtrForEachEntryStop( Abc_Obj_t *, p->vDivs, pObj, i, p->nDivs )
+    {
+        puData = (unsigned *)pObj->pData;
+        for ( w = 0; w < p->nWords; w++ )
+//            if ( puData[w] != puDataR[w] )
+            if ( (puData[w] ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                break;
+        if ( w == p->nWords )
+            return Abc_ManResubQuit0( p->pRoot, pObj );
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubDivs1( Abc_ManRes_t * p, int Required )
+{
+    Abc_Obj_t * pObj0, * pObj1;
+    unsigned * puData0, * puData1, * puDataR;
+    int i, k, w;
+    puDataR = (unsigned *)p->pRoot->pData;
+    // check positive unate divisors
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs1UP, pObj0, i )
+    {
+        puData0 = (unsigned *)pObj0->pData;
+        Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs1UP, pObj1, k, i + 1 )
+        {
+            puData1 = (unsigned *)pObj1->pData;
+            for ( w = 0; w < p->nWords; w++ )
+//                if ( (puData0[w] | puData1[w]) != puDataR[w] )
+                if ( ((puData0[w] | puData1[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                    break;
+            if ( w == p->nWords )
+            {
+                p->nUsedNode1Or++;
+                return Abc_ManResubQuit1( p->pRoot, pObj0, pObj1, 1 );
+            }
+        }
+    }
+    // check negative unate divisors
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs1UN, pObj0, i )
+    {
+        puData0 = (unsigned *)pObj0->pData;
+        Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs1UN, pObj1, k, i + 1 )
+        {
+            puData1 = (unsigned *)pObj1->pData;
+            for ( w = 0; w < p->nWords; w++ )
+//                if ( (puData0[w] & puData1[w]) != puDataR[w] )
+                if ( ((puData0[w] & puData1[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                    break;
+            if ( w == p->nWords )
+            {
+                p->nUsedNode1And++;
+                return Abc_ManResubQuit1( p->pRoot, pObj0, pObj1, 0 );
+            }
+        }
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubDivs12( Abc_ManRes_t * p, int Required )
+{
+    Abc_Obj_t * pObj0, * pObj1, * pObj2, * pObjMax, * pObjMin0 = NULL, * pObjMin1 = NULL;
+    unsigned * puData0, * puData1, * puData2, * puDataR;
+    int i, k, j, w, LevelMax;
+    puDataR = (unsigned *)p->pRoot->pData;
+    // check positive unate divisors
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs1UP, pObj0, i )
+    {
+        puData0 = (unsigned *)pObj0->pData;
+        Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs1UP, pObj1, k, i + 1 )
+        {
+            puData1 = (unsigned *)pObj1->pData;
+            Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs1UP, pObj2, j, k + 1 )
+            {
+                puData2 = (unsigned *)pObj2->pData;
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( (puData0[w] | puData1[w] | puData2[w]) != puDataR[w] )
+                    if ( ((puData0[w] | puData1[w] | puData2[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+                if ( w == p->nWords )
+                {
+                    LevelMax = Abc_MaxInt( pObj0->Level, Abc_MaxInt(pObj1->Level, pObj2->Level) );
+                    assert( LevelMax <= Required - 1 );
+
+                    pObjMax = NULL;
+                    if ( (int)pObj0->Level == LevelMax )
+                        pObjMax = pObj0, pObjMin0 = pObj1, pObjMin1 = pObj2;
+                    if ( (int)pObj1->Level == LevelMax )
+                    {
+                        if ( pObjMax ) continue;
+                        pObjMax = pObj1, pObjMin0 = pObj0, pObjMin1 = pObj2;
+                    }
+                    if ( (int)pObj2->Level == LevelMax )
+                    {
+                        if ( pObjMax ) continue;
+                        pObjMax = pObj2, pObjMin0 = pObj0, pObjMin1 = pObj1;
+                    }
+
+                    p->nUsedNode2Or++;
+                    assert(pObjMin0);
+                    assert(pObjMin1);
+                    return Abc_ManResubQuit21( p->pRoot, pObjMin0, pObjMin1, pObjMax, 1 );
+                }
+            }
+        }
+    }
+    // check negative unate divisors
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs1UN, pObj0, i )
+    {
+        puData0 = (unsigned *)pObj0->pData;
+        Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs1UN, pObj1, k, i + 1 )
+        {
+            puData1 = (unsigned *)pObj1->pData;
+            Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs1UN, pObj2, j, k + 1 )
+            {
+                puData2 = (unsigned *)pObj2->pData;
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( (puData0[w] & puData1[w] & puData2[w]) != puDataR[w] )
+                    if ( ((puData0[w] & puData1[w] & puData2[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+                if ( w == p->nWords )
+                {
+                    LevelMax = Abc_MaxInt( pObj0->Level, Abc_MaxInt(pObj1->Level, pObj2->Level) );
+                    assert( LevelMax <= Required - 1 );
+
+                    pObjMax = NULL;
+                    if ( (int)pObj0->Level == LevelMax )
+                        pObjMax = pObj0, pObjMin0 = pObj1, pObjMin1 = pObj2;
+                    if ( (int)pObj1->Level == LevelMax )
+                    {
+                        if ( pObjMax ) continue;
+                        pObjMax = pObj1, pObjMin0 = pObj0, pObjMin1 = pObj2;
+                    }
+                    if ( (int)pObj2->Level == LevelMax )
+                    {
+                        if ( pObjMax ) continue;
+                        pObjMax = pObj2, pObjMin0 = pObj0, pObjMin1 = pObj1;
+                    }
+
+                    p->nUsedNode2And++;
+                    assert(pObjMin0);
+                    assert(pObjMin1);
+                    return Abc_ManResubQuit21( p->pRoot, pObjMin0, pObjMin1, pObjMax, 0 );
+                }
+            }
+        }
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubDivs2( Abc_ManRes_t * p, int Required )
+{
+    Abc_Obj_t * pObj0, * pObj1, * pObj2;
+    unsigned * puData0, * puData1, * puData2, * puDataR;
+    int i, k, w;
+    puDataR = (unsigned *)p->pRoot->pData;
+    // check positive unate divisors
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs1UP, pObj0, i )
+    {
+        puData0 = (unsigned *)pObj0->pData;
+        Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs2UP0, pObj1, k )
+        {
+            pObj2 = (Abc_Obj_t *)Vec_PtrEntry( p->vDivs2UP1, k );
+
+            puData1 = (unsigned *)Abc_ObjRegular(pObj1)->pData;
+            puData2 = (unsigned *)Abc_ObjRegular(pObj2)->pData;
+            if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) )
+            {
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( (puData0[w] | (puData1[w] | puData2[w])) != puDataR[w] )
+                    if ( ((puData0[w] | (puData1[w] | puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+            }
+            else if ( Abc_ObjIsComplement(pObj1) )
+            {
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( (puData0[w] | (~puData1[w] & puData2[w])) != puDataR[w] )
+                    if ( ((puData0[w] | (~puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+            }
+            else if ( Abc_ObjIsComplement(pObj2) )
+            {
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( (puData0[w] | (puData1[w] & ~puData2[w])) != puDataR[w] )
+                    if ( ((puData0[w] | (puData1[w] & ~puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+            }
+            else 
+            {
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( (puData0[w] | (puData1[w] & puData2[w])) != puDataR[w] )
+                    if ( ((puData0[w] | (puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+            }
+            if ( w == p->nWords )
+            {
+                p->nUsedNode2OrAnd++;
+                return Abc_ManResubQuit2( p->pRoot, pObj0, pObj1, pObj2, 1 );
+            }
+        }
+    }
+    // check negative unate divisors
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs1UN, pObj0, i )
+    {
+        puData0 = (unsigned *)pObj0->pData;
+        Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs2UN0, pObj1, k )
+        {
+            pObj2 = (Abc_Obj_t *)Vec_PtrEntry( p->vDivs2UN1, k );
+
+            puData1 = (unsigned *)Abc_ObjRegular(pObj1)->pData;
+            puData2 = (unsigned *)Abc_ObjRegular(pObj2)->pData;
+            if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) )
+            {
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( (puData0[w] & (puData1[w] | puData2[w])) != puDataR[w] )
+                    if ( ((puData0[w] & (puData1[w] | puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+            }
+            else if ( Abc_ObjIsComplement(pObj1) )
+            {
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( (puData0[w] & (~puData1[w] & puData2[w])) != puDataR[w] )
+                    if ( ((puData0[w] & (~puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+            }
+            else if ( Abc_ObjIsComplement(pObj2) )
+            {
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( (puData0[w] & (puData1[w] & ~puData2[w])) != puDataR[w] )
+                    if ( ((puData0[w] & (puData1[w] & ~puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+            }
+            else 
+            {
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( (puData0[w] & (puData1[w] & puData2[w])) != puDataR[w] )
+                    if ( ((puData0[w] & (puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+            }
+            if ( w == p->nWords )
+            {
+                p->nUsedNode2AndOr++;
+                return Abc_ManResubQuit2( p->pRoot, pObj0, pObj1, pObj2, 0 );
+            }
+        }
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubDivs3( Abc_ManRes_t * p, int Required )
+{
+    Abc_Obj_t * pObj0, * pObj1, * pObj2, * pObj3;
+    unsigned * puData0, * puData1, * puData2, * puData3, * puDataR;
+    int i, k, w = 0, Flag;
+    puDataR = (unsigned *)p->pRoot->pData;
+    // check positive unate divisors
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs2UP0, pObj0, i )
+    {
+        pObj1 = (Abc_Obj_t *)Vec_PtrEntry( p->vDivs2UP1, i );
+        puData0 = (unsigned *)Abc_ObjRegular(pObj0)->pData;
+        puData1 = (unsigned *)Abc_ObjRegular(pObj1)->pData;
+        Flag = (Abc_ObjIsComplement(pObj0) << 3) | (Abc_ObjIsComplement(pObj1) << 2);
+
+        Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs2UP0, pObj2, k, i + 1 )
+        {
+            pObj3 = (Abc_Obj_t *)Vec_PtrEntry( p->vDivs2UP1, k );
+            puData2 = (unsigned *)Abc_ObjRegular(pObj2)->pData;
+            puData3 = (unsigned *)Abc_ObjRegular(pObj3)->pData;
+
+            Flag = (Flag & 12) | ((int)Abc_ObjIsComplement(pObj2) << 1) | (int)Abc_ObjIsComplement(pObj3);
+            assert( Flag < 16 );
+            switch( Flag )
+            {
+            case 0: // 0000
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ((puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] )
+                    if ( (((puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+                break;
+            case 1: // 0001
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ((puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] )
+                    if ( (((puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+                break;
+            case 2: // 0010
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ((puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] )
+                    if ( (((puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+                break;
+            case 3: // 0011
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ((puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] )
+                    if ( (((puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+                break;
+
+            case 4: // 0100
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ((puData0[w] & ~puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] )
+                    if ( (((puData0[w] & ~puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+                break;
+            case 5: // 0101
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ((puData0[w] & ~puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] )
+                    if ( (((puData0[w] & ~puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+                break;
+            case 6: // 0110
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ((puData0[w] & ~puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] )
+                    if ( (((puData0[w] & ~puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+                break;
+            case 7: // 0111
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ((puData0[w] & ~puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] )
+                    if ( (((puData0[w] & ~puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+                break;
+
+            case 8: // 1000
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ((~puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] )
+                    if ( (((~puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+                break;
+            case 9: // 1001
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ((~puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] )
+                    if ( (((~puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+                break;
+            case 10: // 1010
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ((~puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] )
+                    if ( (((~puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+                break;
+            case 11: // 1011
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ((~puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] )
+                    if ( (((~puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+                break;
+
+            case 12: // 1100
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ((puData0[w] | puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] )
+                    if ( (((puData0[w] | puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+                        break;
+                break;
+            case 13: // 1101
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ((puData0[w] | puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] )
+                    if ( (((puData0[w] | puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] )
+                        break;
+                break;
+            case 14: // 1110
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ((puData0[w] | puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] )
+                    if ( (((puData0[w] | puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] )
+                        break;
+                break;
+            case 15: // 1111
+                for ( w = 0; w < p->nWords; w++ )
+//                    if ( ((puData0[w] | puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] )
+                    if ( (((puData0[w] | puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] )
+                        break;
+                break;
+
+            }
+            if ( w == p->nWords )
+            {
+                p->nUsedNode3OrAnd++;
+                return Abc_ManResubQuit3( p->pRoot, pObj0, pObj1, pObj2, pObj3, 1 );
+            }
+        }
+    }
+/*
+    // check negative unate divisors
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs2UN0, pObj0, i )
+    {
+        pObj1 = Vec_PtrEntry( p->vDivs2UN1, i );
+        puData0 = Abc_ObjRegular(pObj0)->pData;
+        puData1 = Abc_ObjRegular(pObj1)->pData;
+        Flag = (Abc_ObjIsComplement(pObj0) << 3) | (Abc_ObjIsComplement(pObj1) << 2);
+
+        Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs2UN0, pObj2, k, i + 1 )
+        {
+            pObj3 = Vec_PtrEntry( p->vDivs2UN1, k );
+            puData2 = Abc_ObjRegular(pObj2)->pData;
+            puData3 = Abc_ObjRegular(pObj3)->pData;
+
+            Flag = (Flag & 12) | (Abc_ObjIsComplement(pObj2) << 1) | Abc_ObjIsComplement(pObj3);
+            assert( Flag < 16 );
+            switch( Flag )
+            {
+            case 0: // 0000
+                for ( w = 0; w < p->nWords; w++ )
+                    if ( ((puData0[w] & puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] )
+                        break;
+                break;
+            case 1: // 0001
+                for ( w = 0; w < p->nWords; w++ )
+                    if ( ((puData0[w] & puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] )
+                        break;
+                break;
+            case 2: // 0010
+                for ( w = 0; w < p->nWords; w++ )
+                    if ( ((puData0[w] & puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] )
+                        break;
+                break;
+            case 3: // 0011
+                for ( w = 0; w < p->nWords; w++ )
+                    if ( ((puData0[w] & puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] )
+                        break;
+                break;
+
+            case 4: // 0100
+                for ( w = 0; w < p->nWords; w++ )
+                    if ( ((puData0[w] & ~puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] )
+                        break;
+                break;
+            case 5: // 0101
+                for ( w = 0; w < p->nWords; w++ )
+                    if ( ((puData0[w] & ~puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] )
+                        break;
+                break;
+            case 6: // 0110
+                for ( w = 0; w < p->nWords; w++ )
+                    if ( ((puData0[w] & ~puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] )
+                        break;
+                break;
+            case 7: // 0111
+                for ( w = 0; w < p->nWords; w++ )
+                    if ( ((puData0[w] & ~puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] )
+                        break;
+                break;
+
+            case 8: // 1000
+                for ( w = 0; w < p->nWords; w++ )
+                    if ( ((~puData0[w] & puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] )
+                        break;
+                break;
+            case 9: // 1001
+                for ( w = 0; w < p->nWords; w++ )
+                    if ( ((~puData0[w] & puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] )
+                        break;
+                break;
+            case 10: // 1010
+                for ( w = 0; w < p->nWords; w++ )
+                    if ( ((~puData0[w] & puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] )
+                        break;
+                break;
+            case 11: // 1011
+                for ( w = 0; w < p->nWords; w++ )
+                    if ( ((~puData0[w] & puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] )
+                        break;
+                break;
+
+            case 12: // 1100
+                for ( w = 0; w < p->nWords; w++ )
+                    if ( ((puData0[w] | puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] )
+                        break;
+                break;
+            case 13: // 1101
+                for ( w = 0; w < p->nWords; w++ )
+                    if ( ((puData0[w] | puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] )
+                        break;
+                break;
+            case 14: // 1110
+                for ( w = 0; w < p->nWords; w++ )
+                    if ( ((puData0[w] | puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] )
+                        break;
+                break;
+            case 15: // 1111
+                for ( w = 0; w < p->nWords; w++ )
+                    if ( ((puData0[w] | puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] )
+                        break;
+                break;
+
+            }
+            if ( w == p->nWords )
+            {
+                p->nUsedNode3AndOr++;
+                return Abc_ManResubQuit3( p->pRoot, pObj0, pObj1, pObj2, pObj3, 0 );
+            }
+        }
+    }
+*/
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ManResubCleanup( Abc_ManRes_t * p )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs, pObj, i )
+        pObj->pData = NULL;
+    Vec_PtrClear( p->vDivs );
+    p->pRoot = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates resubstution of one cut.]
+
+  Description [Returns the graph to add if any.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubEval( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int nSteps, int fUpdateLevel, int fVerbose )
+{
+    extern int Abc_NodeMffcInside( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vInside );
+    Dec_Graph_t * pGraph;
+    int Required;
+    abctime clk;
+
+    Required = fUpdateLevel? Abc_ObjRequiredLevel(pRoot) : ABC_INFINITY;
+
+    assert( nSteps >= 0 );
+    assert( nSteps <= 3 );
+    p->pRoot = pRoot;
+    p->nLeaves = Vec_PtrSize(vLeaves);
+    p->nLastGain = -1;
+
+    // collect the MFFC
+clk = Abc_Clock();
+    p->nMffc = Abc_NodeMffcInside( pRoot, vLeaves, p->vTemp );
+p->timeMffc += Abc_Clock() - clk;
+    assert( p->nMffc > 0 );
+
+    // collect the divisor nodes
+clk = Abc_Clock();
+    if ( !Abc_ManResubCollectDivs( p, pRoot, vLeaves, Required ) )
+        return NULL;
+    p->timeDiv += Abc_Clock() - clk;
+
+    p->nTotalDivs   += p->nDivs;
+    p->nTotalLeaves += p->nLeaves;
+
+    // simulate the nodes
+clk = Abc_Clock();
+    Abc_ManResubSimulate( p->vDivs, p->nLeaves, p->vSims, p->nLeavesMax, p->nWords );
+p->timeSim += Abc_Clock() - clk;
+
+clk = Abc_Clock();
+    // consider constants
+    if ( (pGraph = Abc_ManResubQuit( p )) )
+    {
+        p->nUsedNodeC++;
+        p->nLastGain = p->nMffc;
+        return pGraph;
+    }
+
+    // consider equal nodes
+    if ( (pGraph = Abc_ManResubDivs0( p )) )
+    {
+p->timeRes1 += Abc_Clock() - clk;
+        p->nUsedNode0++;
+        p->nLastGain = p->nMffc;
+        return pGraph;
+    }
+    if ( nSteps == 0 || p->nMffc == 1 )
+    {
+p->timeRes1 += Abc_Clock() - clk;
+        return NULL;
+    }
+
+    // get the one level divisors
+    Abc_ManResubDivsS( p, Required );
+
+    // consider one node
+    if ( (pGraph = Abc_ManResubDivs1( p, Required )) )
+    {
+p->timeRes1 += Abc_Clock() - clk;
+        p->nLastGain = p->nMffc - 1;
+        return pGraph;
+    }
+p->timeRes1 += Abc_Clock() - clk;
+    if ( nSteps == 1 || p->nMffc == 2 )
+        return NULL;
+
+clk = Abc_Clock();
+    // consider triples
+    if ( (pGraph = Abc_ManResubDivs12( p, Required )) )
+    {
+p->timeRes2 += Abc_Clock() - clk;
+        p->nLastGain = p->nMffc - 2;
+        return pGraph;
+    }
+p->timeRes2 += Abc_Clock() - clk;
+
+    // get the two level divisors
+clk = Abc_Clock();
+    Abc_ManResubDivsD( p, Required );
+p->timeResD += Abc_Clock() - clk;
+
+    // consider two nodes
+clk = Abc_Clock();
+    if ( (pGraph = Abc_ManResubDivs2( p, Required )) )
+    {
+p->timeRes2 += Abc_Clock() - clk;
+        p->nLastGain = p->nMffc - 2;
+        return pGraph;
+    }
+p->timeRes2 += Abc_Clock() - clk;
+    if ( nSteps == 2 || p->nMffc == 3 )
+        return NULL;
+
+    // consider two nodes
+clk = Abc_Clock();
+    if ( (pGraph = Abc_ManResubDivs3( p, Required )) )
+    {
+p->timeRes3 += Abc_Clock() - clk;
+        p->nLastGain = p->nMffc - 3;
+        return pGraph;
+    }
+p->timeRes3 += Abc_Clock() - clk;
+    if ( nSteps == 3 || p->nLeavesMax == 4 )
+        return NULL;
+    return NULL;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the volume and checks if the cut is feasible.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CutVolumeCheck_rec( Abc_Obj_t * pObj )
+{
+    // quit if the node is visited (or if it is a leaf)
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return 0;
+    Abc_NodeSetTravIdCurrent(pObj);
+    // report the error
+    if ( Abc_ObjIsCi(pObj) )
+        printf( "Abc_CutVolumeCheck() ERROR: The set of nodes is not a cut!\n" );
+    // count the number of nodes in the leaves
+    return 1 + Abc_CutVolumeCheck_rec( Abc_ObjFanin0(pObj) ) +
+        Abc_CutVolumeCheck_rec( Abc_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the volume and checks if the cut is feasible.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CutVolumeCheck( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    // mark the leaves
+    Abc_NtkIncrementTravId( pNode->pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+        Abc_NodeSetTravIdCurrent( pObj ); 
+    // traverse the nodes starting from the given one and count them
+    return Abc_CutVolumeCheck_rec( pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the factor cut of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_CutFactor_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves )
+{
+    if ( pObj->fMarkA )
+        return;
+    if ( Abc_ObjIsCi(pObj) || (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)) )
+    {
+        Vec_PtrPush( vLeaves, pObj );
+        pObj->fMarkA = 1;
+        return;
+    }
+    Abc_CutFactor_rec( Abc_ObjFanin0(pObj), vLeaves );
+    Abc_CutFactor_rec( Abc_ObjFanin1(pObj), vLeaves );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the factor cut of the node.]
+
+  Description [Factor-cut is the cut at a node in terms of factor-nodes.
+  Factor-nodes are roots of the node trees (MUXes/EXORs are counted as single nodes).
+  Factor-cut is unique for the given node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_CutFactor( Abc_Obj_t * pNode )
+{
+    Vec_Ptr_t * vLeaves;
+    Abc_Obj_t * pObj;
+    int i;
+    assert( !Abc_ObjIsCi(pNode) );
+    vLeaves  = Vec_PtrAlloc( 10 );
+    Abc_CutFactor_rec( Abc_ObjFanin0(pNode), vLeaves );
+    Abc_CutFactor_rec( Abc_ObjFanin1(pNode), vLeaves );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+        pObj->fMarkA = 0;
+    return vLeaves;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cut computation.]
+
+  Description [This cut computation works as follows: 
+  It starts with the factor cut at the node. If the factor-cut is large, quit.
+  It supports the set of leaves of the cut under construction and labels all nodes
+  in the cut under construction, including the leaves.
+  It computes the factor-cuts of the leaves and checks if it is easible to add any of them.
+  If it is, it randomly chooses one feasible and continues.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_CutFactorLarge( Abc_Obj_t * pNode, int nLeavesMax )
+{
+    Vec_Ptr_t * vLeaves, * vFactors, * vFact, * vNext;
+    Vec_Int_t * vFeasible;
+    Abc_Obj_t * pLeaf, * pTemp;
+    int i, k, Counter, RandLeaf;
+    int BestCut, BestShare;
+    assert( Abc_ObjIsNode(pNode) );
+    // get one factor-cut
+    vLeaves = Abc_CutFactor( pNode );
+    if ( Vec_PtrSize(vLeaves) > nLeavesMax )
+    {
+        Vec_PtrFree(vLeaves);
+        return NULL;
+    }
+    if ( Vec_PtrSize(vLeaves) == nLeavesMax )
+        return vLeaves;
+    // initialize the factor cuts for the leaves
+    vFactors = Vec_PtrAlloc( nLeavesMax );
+    Abc_NtkIncrementTravId( pNode->pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pLeaf, i )
+    {
+        Abc_NodeSetTravIdCurrent( pLeaf ); 
+        if ( Abc_ObjIsCi(pLeaf) )
+            Vec_PtrPush( vFactors, NULL );
+        else
+            Vec_PtrPush( vFactors, Abc_CutFactor(pLeaf) );
+    }
+    // construct larger factor cuts
+    vFeasible = Vec_IntAlloc( nLeavesMax );
+    while ( 1 )
+    {
+        BestCut = -1, BestShare = -1;
+        // find the next feasible cut to add
+        Vec_IntClear( vFeasible );
+        Vec_PtrForEachEntry( Vec_Ptr_t *, vFactors, vFact, i )
+        {
+            if ( vFact == NULL )
+                continue;
+            // count the number of unmarked leaves of this factor cut
+            Counter = 0;
+            Vec_PtrForEachEntry( Abc_Obj_t *, vFact, pTemp, k )
+                Counter += !Abc_NodeIsTravIdCurrent(pTemp);
+            // if the number of new leaves is smaller than the diff, it is feasible
+            if ( Counter <= nLeavesMax - Vec_PtrSize(vLeaves) + 1 )
+            {
+                Vec_IntPush( vFeasible, i );
+                if ( BestCut == -1 || BestShare < Vec_PtrSize(vFact) - Counter )
+                    BestCut = i, BestShare = Vec_PtrSize(vFact) - Counter;
+            }
+        }
+        // quit if there is no feasible factor cuts
+        if ( Vec_IntSize(vFeasible) == 0 )
+            break;
+        // randomly choose one leaf and get its factor cut
+//        RandLeaf = Vec_IntEntry( vFeasible, rand() % Vec_IntSize(vFeasible) );
+        // choose the cut that has most sharing with the other cuts
+        RandLeaf = BestCut;
+
+        pLeaf = (Abc_Obj_t *)Vec_PtrEntry( vLeaves, RandLeaf );
+        vNext = (Vec_Ptr_t *)Vec_PtrEntry( vFactors, RandLeaf );
+        // unmark this leaf
+        Abc_NodeSetTravIdPrevious( pLeaf ); 
+        // remove this cut from the leaves and factor cuts
+        for ( i = RandLeaf; i < Vec_PtrSize(vLeaves)-1; i++ )
+        {
+            Vec_PtrWriteEntry( vLeaves,  i, Vec_PtrEntry(vLeaves, i+1) );
+            Vec_PtrWriteEntry( vFactors, i, Vec_PtrEntry(vFactors,i+1) );
+        }
+        Vec_PtrShrink( vLeaves,  Vec_PtrSize(vLeaves) -1 );
+        Vec_PtrShrink( vFactors, Vec_PtrSize(vFactors)-1 );
+        // add new leaves, compute their factor cuts
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNext, pLeaf, i )
+        {
+            if ( Abc_NodeIsTravIdCurrent(pLeaf) )
+                continue;
+            Abc_NodeSetTravIdCurrent( pLeaf ); 
+            Vec_PtrPush( vLeaves, pLeaf );
+            if ( Abc_ObjIsCi(pLeaf) )
+                Vec_PtrPush( vFactors, NULL );
+            else
+                Vec_PtrPush( vFactors, Abc_CutFactor(pLeaf) );
+        }
+        Vec_PtrFree( vNext );
+        assert( Vec_PtrSize(vLeaves) <= nLeavesMax );
+        if ( Vec_PtrSize(vLeaves) == nLeavesMax )
+            break;
+    }
+
+    // remove temporary storage
+    Vec_PtrForEachEntry( Vec_Ptr_t *, vFactors, vFact, i )
+        if ( vFact ) Vec_PtrFree( vFact );
+    Vec_PtrFree( vFactors );
+    Vec_IntFree( vFeasible );
+    return vLeaves;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcRewrite.c b/abc-build/src/base/abci/abcRewrite.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcRewrite.c
@@ -0,0 +1,420 @@
+/**CFile****************************************************************
+
+  FileName    [abcRewrite.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Technology-independent resynthesis of the AIG based on DAG aware rewriting.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcRewrite.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "opt/rwr/rwr.h"
+#include "bool/dec/dec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+    The ideas realized in this package are inspired by the paper:
+    Per Bjesse, Arne Boralv, "DAG-aware circuit compression for 
+    formal verification", Proc. ICCAD 2004, pp. 42-49.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk );
+static void        Abc_NodePrintCuts( Abc_Obj_t * pNode );
+static void        Abc_ManShowCutCone( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves );
+
+extern void  Abc_PlaceBegin( Abc_Ntk_t * pNtk );
+extern void  Abc_PlaceEnd( Abc_Ntk_t * pNtk );
+extern void  Abc_PlaceUpdate( Vec_Ptr_t * vAddedCells, Vec_Ptr_t * vUpdatedNets );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs incremental rewriting of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable )
+{
+    extern void           Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain );
+    ProgressBar * pProgress;
+    Cut_Man_t * pManCut;
+    Rwr_Man_t * pManRwr;
+    Abc_Obj_t * pNode;
+//    Vec_Ptr_t * vAddedCells = NULL, * vUpdatedNets = NULL;
+    Dec_Graph_t * pGraph;
+    int i, nNodes, nGain, fCompl;
+    abctime clk, clkStart = Abc_Clock();
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    // cleanup the AIG
+    Abc_AigCleanup((Abc_Aig_t *)pNtk->pManFunc);
+/*
+    {
+        Vec_Vec_t * vParts;
+        vParts = Abc_NtkPartitionSmart( pNtk, 50, 1 );
+        Vec_VecFree( vParts );
+    }
+*/
+
+    // start placement package
+//    if ( fPlaceEnable )
+//    {
+//        Abc_PlaceBegin( pNtk );
+//        vAddedCells = Abc_AigUpdateStart( pNtk->pManFunc, &vUpdatedNets );
+//    }
+
+    // start the rewriting manager
+    pManRwr = Rwr_ManStart( 0 );
+    if ( pManRwr == NULL )
+        return 0;
+    // compute the reverse levels if level update is requested
+    if ( fUpdateLevel )
+        Abc_NtkStartReverseLevels( pNtk, 0 );
+    // start the cut manager
+clk = Abc_Clock();
+    pManCut = Abc_NtkStartCutManForRewrite( pNtk );
+Rwr_ManAddTimeCuts( pManRwr, Abc_Clock() - clk );
+    pNtk->pManCut = pManCut;
+
+    if ( fVeryVerbose )
+        Rwr_ScoresClean( pManRwr );
+
+    // resynthesize each node once
+    pManRwr->nNodesBeg = Abc_NtkNodeNum(pNtk);
+    nNodes = Abc_NtkObjNumMax(pNtk);
+    pProgress = Extra_ProgressBarStart( stdout, nNodes );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        // stop if all nodes have been tried once
+        if ( i >= nNodes )
+            break;
+        // skip persistant nodes
+        if ( Abc_NodeIsPersistant(pNode) )
+            continue;
+        // skip the nodes with many fanouts
+        if ( Abc_ObjFanoutNum(pNode) > 1000 )
+            continue;
+
+        // for each cut, try to resynthesize it
+        nGain = Rwr_NodeRewrite( pManRwr, pManCut, pNode, fUpdateLevel, fUseZeros, fPlaceEnable );
+        if ( !(nGain > 0 || (nGain == 0 && fUseZeros)) )
+            continue;
+        // if we end up here, a rewriting step is accepted
+
+        // get hold of the new subgraph to be added to the AIG
+        pGraph = (Dec_Graph_t *)Rwr_ManReadDecs(pManRwr);
+        fCompl = Rwr_ManReadCompl(pManRwr);
+
+        // reset the array of the changed nodes
+        if ( fPlaceEnable )
+            Abc_AigUpdateReset( (Abc_Aig_t *)pNtk->pManFunc );
+
+        // complement the FF if needed
+        if ( fCompl ) Dec_GraphComplement( pGraph );
+clk = Abc_Clock();
+        Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, nGain );
+Rwr_ManAddTimeUpdate( pManRwr, Abc_Clock() - clk );
+        if ( fCompl ) Dec_GraphComplement( pGraph );
+
+        // use the array of changed nodes to update placement
+//        if ( fPlaceEnable )
+//            Abc_PlaceUpdate( vAddedCells, vUpdatedNets );
+    }
+    Extra_ProgressBarStop( pProgress );
+Rwr_ManAddTimeTotal( pManRwr, Abc_Clock() - clkStart );
+    // print stats
+    pManRwr->nNodesEnd = Abc_NtkNodeNum(pNtk);
+    if ( fVerbose )
+        Rwr_ManPrintStats( pManRwr );
+//        Rwr_ManPrintStatsFile( pManRwr );
+    if ( fVeryVerbose )
+        Rwr_ScoresReport( pManRwr );
+    // delete the managers
+    Rwr_ManStop( pManRwr );
+    Cut_ManStop( pManCut );
+    pNtk->pManCut = NULL;
+
+    // start placement package
+//    if ( fPlaceEnable )
+//    {
+//        Abc_PlaceEnd( pNtk );
+//        Abc_AigUpdateStop( pNtk->pManFunc );
+//    }
+
+    // put the nodes into the DFS order and reassign their IDs
+    {
+//        abctime clk = Abc_Clock();
+    Abc_NtkReassignIds( pNtk );
+//        ABC_PRT( "time", Abc_Clock() - clk );
+    }
+//    Abc_AigCheckFaninOrder( pNtk->pManFunc );
+    // fix the levels
+    if ( fUpdateLevel )
+        Abc_NtkStopReverseLevels( pNtk );
+    else
+        Abc_NtkLevel( pNtk );
+    // check
+    if ( !Abc_NtkCheck( pNtk ) )
+    {
+        printf( "Abc_NtkRewrite: The network check has failed.\n" );
+        return 0;
+    }
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the cut manager for rewriting.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk )
+{
+    static Cut_Params_t Params, * pParams = &Params;
+    Cut_Man_t * pManCut;
+    Abc_Obj_t * pObj;
+    int i;
+    // start the cut manager
+    memset( pParams, 0, sizeof(Cut_Params_t) );
+    pParams->nVarsMax  = 4;     // the max cut size ("k" of the k-feasible cuts)
+    pParams->nKeepMax  = 250;   // the max number of cuts kept at a node
+    pParams->fTruth    = 1;     // compute truth tables
+    pParams->fFilter   = 1;     // filter dominated cuts
+    pParams->fSeq      = 0;     // compute sequential cuts
+    pParams->fDrop     = 0;     // drop cuts on the fly
+    pParams->fVerbose  = 0;     // the verbosiness flag
+    pParams->nIdsMax   = Abc_NtkObjNumMax( pNtk );
+    pManCut = Cut_ManStart( pParams );
+    if ( pParams->fDrop )
+        Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) );
+    // set cuts for PIs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        if ( Abc_ObjFanoutNum(pObj) > 0 )
+            Cut_NodeSetTriv( pManCut, pObj->Id );
+    return pManCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the cuts at the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodePrintCuts( Abc_Obj_t * pNode )
+{
+    Vec_Ptr_t * vCuts;
+    Cut_Cut_t * pCut;
+    int k;
+
+    printf( "\nNode %s\n", Abc_ObjName(pNode) );
+    vCuts = (Vec_Ptr_t *)pNode->pCopy;
+    Vec_PtrForEachEntry( Cut_Cut_t *, vCuts, pCut, k )
+    {
+        Extra_PrintBinary( stdout, (unsigned *)&pCut->uSign, 16 ); 
+        printf( "   " );
+        Cut_CutPrint( pCut, 0 );   
+        printf( "\n" );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ManRewritePrintDivs( Vec_Ptr_t * vDivs, int nLeaves )
+{
+    Abc_Obj_t * pFanin, * pNode, * pRoot;
+    int i, k;
+    pRoot = (Abc_Obj_t *)Vec_PtrEntryLast(vDivs);
+    // print the nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vDivs, pNode, i )
+    {
+        if ( i < nLeaves )
+        {
+            printf( "%6d : %c\n", pNode->Id, 'a'+i );
+            continue;
+        }
+        printf( "%6d : %2d = ", pNode->Id, i );
+        // find the first fanin
+        Vec_PtrForEachEntry( Abc_Obj_t *, vDivs, pFanin, k )
+            if ( Abc_ObjFanin0(pNode) == pFanin )
+                break;
+        if ( k < nLeaves )
+            printf( "%c", 'a' + k );
+        else
+            printf( "%d", k );
+        printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" );
+        // find the second fanin
+        Vec_PtrForEachEntry( Abc_Obj_t *, vDivs, pFanin, k )
+            if ( Abc_ObjFanin1(pNode) == pFanin )
+                break;
+        if ( k < nLeaves )
+            printf( "%c", 'a' + k );
+        else
+            printf( "%d", k );
+        printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" );
+        if ( pNode == pRoot )
+            printf( " root" );
+        printf( "\n" );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ManShowCutCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vDivs )
+{
+    if ( Abc_NodeIsTravIdCurrent(pNode) )
+        return;
+    Abc_NodeSetTravIdCurrent(pNode);
+    Abc_ManShowCutCone_rec( Abc_ObjFanin0(pNode), vDivs );
+    Abc_ManShowCutCone_rec( Abc_ObjFanin1(pNode), vDivs );
+    Vec_PtrPush( vDivs, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ManShowCutCone( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves )
+{
+    Abc_Ntk_t * pNtk = pNode->pNtk;
+    Abc_Obj_t * pObj;
+    Vec_Ptr_t * vDivs;
+    int i;
+    vDivs = Vec_PtrAlloc( 100 );
+    Abc_NtkIncrementTravId( pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+    {
+        Abc_NodeSetTravIdCurrent( Abc_ObjRegular(pObj) );
+        Vec_PtrPush( vDivs, Abc_ObjRegular(pObj) );
+    }
+    Abc_ManShowCutCone_rec( pNode, vDivs );
+    Abc_ManRewritePrintDivs( vDivs, Vec_PtrSize(vLeaves) );
+    Vec_PtrFree( vDivs );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_RwrExpWithCut_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, int fUseA )
+{
+    if ( Vec_PtrFind(vLeaves, pNode) >= 0 || Vec_PtrFind(vLeaves, Abc_ObjNot(pNode)) >= 0 )
+    {
+        if ( fUseA )
+            Abc_ObjRegular(pNode)->fMarkA = 1;
+        else
+            Abc_ObjRegular(pNode)->fMarkB = 1;
+        return;
+    }
+    assert( Abc_ObjIsNode(pNode) );
+    Abc_RwrExpWithCut_rec( Abc_ObjFanin0(pNode), vLeaves, fUseA );
+    Abc_RwrExpWithCut_rec( Abc_ObjFanin1(pNode), vLeaves, fUseA );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_RwrExpWithCut( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves )
+{
+    Abc_Obj_t * pObj;
+    int i, CountA, CountB;
+    Abc_RwrExpWithCut_rec( Abc_ObjFanin0(pNode), vLeaves, 1 );
+    Abc_RwrExpWithCut_rec( Abc_ObjFanin1(pNode), vLeaves, 0 );
+    CountA = CountB = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+    {
+        CountA += Abc_ObjRegular(pObj)->fMarkA;
+        CountB += Abc_ObjRegular(pObj)->fMarkB;
+        Abc_ObjRegular(pObj)->fMarkA = 0;
+        Abc_ObjRegular(pObj)->fMarkB = 0;
+    }
+    printf( "(%d,%d:%d) ", CountA, CountB, CountA+CountB-Vec_PtrSize(vLeaves) );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcRpo.c b/abc-build/src/base/abci/abcRpo.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcRpo.c
@@ -0,0 +1,442 @@
+/**CFile****************************************************************
+
+  FileName    [abcRpo.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Rpo package.]
+
+  Synopsis    [Procedures for executing RPO.]
+
+  Author      [Mayler G. A. Martins / Vinicius Callegaro]
+  
+  Affiliation [UFRGS]
+
+  Date        [Ver. 1.0. Started - May 08, 2013.]
+
+  Revision    [$Id: abcRpo.c,v 1.00 2013/05/08 00:00:00 mgamartins Exp $]
+
+ ***********************************************************************/
+
+#include "misc/extra/extra.h"
+
+#include "bool/rpo/rpo.h"
+#include "bool/rpo/literal.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+// data-structure to store a bunch of truth tables
+typedef struct Rpo_TtStore_t_ Rpo_TtStore_t;
+
+struct Rpo_TtStore_t_ {
+    int nVars;
+    int nWords;
+    int nFuncs;
+    word ** pFuncs;
+};
+
+
+// read/write/flip i-th bit of a bit string table:
+
+static inline int Abc_TruthGetBit(word * p, int i) {
+    return (int) (p[i >> 6] >> (i & 63)) & 1;
+}
+
+static inline void Abc_TruthSetBit(word * p, int i) {
+    p[i >> 6] |= (((word) 1) << (i & 63));
+}
+
+static inline void Abc_TruthXorBit(word * p, int i) {
+    p[i >> 6] ^= (((word) 1) << (i & 63));
+}
+
+// read/write k-th digit d of a hexadecimal number:
+
+static inline int Abc_TruthGetHex(word * p, int k) {
+    return (int) (p[k >> 4] >> ((k << 2) & 63)) & 15;
+}
+
+static inline void Abc_TruthSetHex(word * p, int k, int d) {
+    p[k >> 4] |= (((word) d) << ((k << 2) & 63));
+}
+
+static inline void Abc_TruthXorHex(word * p, int k, int d) {
+    p[k >> 4] ^= (((word) d) << ((k << 2) & 63));
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+// read one hex character
+
+static inline int Abc_TruthReadHexDigit(char HexChar) {
+    if (HexChar >= '0' && HexChar <= '9')
+        return HexChar - '0';
+    if (HexChar >= 'A' && HexChar <= 'F')
+        return HexChar - 'A' + 10;
+    if (HexChar >= 'a' && HexChar <= 'f')
+        return HexChar - 'a' + 10;
+    assert(0); // not a hexadecimal symbol
+    return -1; // return value which makes no sense
+}
+
+// write one hex character
+
+static inline void Abc_TruthWriteHexDigit(FILE * pFile, int HexDigit) {
+    assert(HexDigit >= 0 && HexDigit < 16);
+    if (HexDigit < 10)
+        fprintf(pFile, "%d", HexDigit);
+    else
+        fprintf(pFile, "%c", 'A' + HexDigit - 10);
+}
+
+// read one truth table in hexadecimal
+
+static void Abc_TruthReadHex(word * pTruth, char * pString, int nVars) {
+    int nWords = (nVars < 7) ? 1 : (1 << (nVars - 6));
+    int k, Digit, nDigits = (nWords << 4);
+    char EndSymbol;
+    // skip the first 2 symbols if they are "0x"
+    if (pString[0] == '0' && pString[1] == 'x')
+        pString += 2;
+    // get the last symbol
+    EndSymbol = pString[nDigits];
+    // the end symbol of the TT (the one immediately following hex digits)
+    // should be one of the following: space, a new-line, or a zero-terminator
+    // (note that on Windows symbols '\r' can be inserted before each '\n')
+    assert(EndSymbol == ' ' || EndSymbol == '\n' || EndSymbol == '\r' || EndSymbol == '\0');
+    // read hexadecimal digits in the reverse order
+    // (the last symbol in the string is the least significant digit)
+    for (k = 0; k < nDigits; k++) {
+        Digit = Abc_TruthReadHexDigit(pString[nDigits - 1 - k]);
+        assert(Digit >= 0 && Digit < 16);
+        Abc_TruthSetHex(pTruth, k, Digit);
+    }
+}
+
+// write one truth table in hexadecimal (do not add end-of-line!)
+
+static void Abc_TruthWriteHex(FILE * pFile, word * pTruth, int nVars) {
+    int nDigits, Digit, k;
+    nDigits = (1 << (nVars - 2));
+    for (k = 0; k < nDigits; k++) {
+        Digit = Abc_TruthGetHex(pTruth, k);
+        assert(Digit >= 0 && Digit < 16);
+        Abc_TruthWriteHexDigit(pFile, Digit);
+    }
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocate/Deallocate storage for truth tables..]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+ ***********************************************************************/
+static Rpo_TtStore_t * Abc_TruthStoreAlloc(int nVars, int nFuncs) {
+    Rpo_TtStore_t * p;
+    int i;
+    p = (Rpo_TtStore_t *) malloc(sizeof (Rpo_TtStore_t));
+    p->nVars = nVars;
+    p->nWords = (nVars < 7) ? 1 : (1 << (nVars - 6));
+    p->nFuncs = nFuncs;
+    // alloc storage for 'nFuncs' truth tables as one chunk of memory
+    p->pFuncs = (word **) malloc((sizeof (word *) + sizeof (word) * p->nWords) * p->nFuncs);
+    // assign and clean the truth table storage
+    p->pFuncs[0] = (word *) (p->pFuncs + p->nFuncs);
+    memset(p->pFuncs[0], 0, sizeof (word) * p->nWords * p->nFuncs);
+    // split it up into individual truth tables
+    for (i = 1; i < p->nFuncs; i++)
+        p->pFuncs[i] = p->pFuncs[i - 1] + p->nWords;
+    return p;
+}
+
+static Rpo_TtStore_t * Abc_TruthStoreAlloc2(int nVars, int nFuncs, word * pBuffer) {
+    Rpo_TtStore_t * p;
+    int i;
+    p = (Rpo_TtStore_t *) malloc(sizeof (Rpo_TtStore_t));
+    p->nVars = nVars;
+    p->nWords = (nVars < 7) ? 1 : (1 << (nVars - 6));
+    p->nFuncs = nFuncs;
+    // alloc storage for 'nFuncs' truth tables as one chunk of memory
+    p->pFuncs = (word **) malloc(sizeof (word *) * p->nFuncs);
+    // assign and clean the truth table storage
+    p->pFuncs[0] = pBuffer;
+    // split it up into individual truth tables
+    for (i = 1; i < p->nFuncs; i++)
+        p->pFuncs[i] = p->pFuncs[i - 1] + p->nWords;
+    return p;
+}
+
+static void Abc_TtStoreFree(Rpo_TtStore_t * p, int nVarNum) {
+    if (nVarNum >= 0)
+        ABC_FREE(p->pFuncs[0]);
+    ABC_FREE(p->pFuncs);
+    ABC_FREE(p);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read file contents.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+ ***********************************************************************/
+extern int Abc_FileSize(char * pFileName);
+
+/**Function*************************************************************
+
+  Synopsis    [Read file contents.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+ ***********************************************************************/
+extern char * Abc_FileRead(char * pFileName);
+
+/**Function*************************************************************
+
+  Synopsis    [Determine the number of variables by reading the first line.]
+
+  Description [Determine the number of functions by counting the lines.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+ ***********************************************************************/
+extern void Abc_TruthGetParams(char * pFileName, int * pnVars, int * pnTruths);
+
+
+/**Function*************************************************************
+
+  Synopsis    [Read truth tables from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+ ***********************************************************************/
+static void Abc_TruthStoreRead(char * pFileName, Rpo_TtStore_t * p) {
+    char * pContents;
+    int i, nLines;
+    pContents = Abc_FileRead(pFileName);
+    if (pContents == NULL)
+        return;
+    // here it is assumed (without checking!) that each line of the file 
+    // begins with a string of hexadecimal chars followed by space
+
+    // the file will be read till the first empty line (pContents[i] == '\n')
+    // (note that Abc_FileRead() added several empty lines at the end of the file contents)
+    for (nLines = i = 0; pContents[i] != '\n';) {
+        // read one line
+        Abc_TruthReadHex(p->pFuncs[nLines++], &pContents[i], p->nVars);
+        // skip till after the end-of-line symbol
+        // (note that end-of-line symbol is also skipped)
+        while (pContents[i++] != '\n');
+    }
+    // adjust the number of functions read 
+    // (we may have allocated more storage because some lines in the file were empty)
+    assert(p->nFuncs >= nLines);
+    p->nFuncs = nLines;
+    ABC_FREE(pContents);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write truth tables into file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+ ***********************************************************************/
+static void Abc_TtStoreWrite(char * pFileName, Rpo_TtStore_t * p, int fBinary) {
+    FILE * pFile;
+    int i, nBytes = 8 * Abc_Truth6WordNum(p->nVars);
+    pFile = fopen(pFileName, "wb");
+    if (pFile == NULL) {
+        printf("Cannot open file \"%s\" for writing.\n", pFileName);
+        return;
+    }
+    for (i = 0; i < p->nFuncs; i++) {
+        if (fBinary)
+            fwrite(p->pFuncs[i], nBytes, 1, pFile);
+        else
+            Abc_TruthWriteHex(pFile, p->pFuncs[i], p->nVars), fprintf(pFile, "\n");
+    }
+    fclose(pFile);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read truth tables from input file and write them into output file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+ ***********************************************************************/
+static Rpo_TtStore_t * Abc_TtStoreLoad(char * pFileName, int nVarNum) {
+    Rpo_TtStore_t * p;
+    if (nVarNum < 0) {
+        int nVars, nTruths;
+        // figure out how many truth table and how many variables
+        Abc_TruthGetParams(pFileName, &nVars, &nTruths);
+        if (nVars < 2 || nVars > 16 || nTruths == 0)
+            return NULL;
+        // allocate data-structure
+        p = Abc_TruthStoreAlloc(nVars, nTruths);
+        // read info from file
+        Abc_TruthStoreRead(pFileName, p);
+    } else {
+        char * pBuffer;
+        int nFileSize = Abc_FileSize(pFileName);
+        int nBytes = (1 << (nVarNum - 3)); // why mishchencko put -3? ###
+        int nTruths = nFileSize / nBytes;
+        //Abc_Print(-2,"nFileSize=%d,nTruths=%d\n",nFileSize, nTruths);
+        if (nFileSize == -1)
+            return NULL;
+        assert(nVarNum >= 6);
+        if (nFileSize % nBytes != 0)
+            Abc_Print(0, "The file size (%d) is divided by the truth table size (%d) with remainder (%d).\n",
+                nFileSize, nBytes, nFileSize % nBytes);
+        // read file contents
+        pBuffer = Abc_FileRead(pFileName);
+        // allocate data-structure
+        p = Abc_TruthStoreAlloc2(nVarNum, nTruths, (word *) pBuffer);
+    }
+    return p;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Apply decomposition to the truth table.]
+
+  Description [Returns the number of AIG nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+ ***********************************************************************/
+void Abc_TruthRpoPerform(Rpo_TtStore_t * p, int nThreshold, int fVerbose) {
+    clock_t clk = clock();
+    int i;
+    int rpoCount = 0;
+    Literal_t* lit;
+    float percent;
+    for (i = 0; i < p->nFuncs; i++) {
+//        if(i>1000) {
+//            continue;
+//        }
+////        
+//        if(i!= 2196 ) { //5886
+//            continue;
+//        }
+        if(fVerbose) {
+            Abc_Print(-2,"%d: ", i+1);
+        }
+            
+        lit = Rpo_Factorize((unsigned *) p->pFuncs[i], p->nVars, nThreshold, fVerbose);
+        if (lit != NULL) {
+            if(fVerbose) {
+                Abc_Print(-2, "Solution : %s\n", lit->expression->pArray);
+                Abc_Print(-2, "\n\n");
+            }
+            Lit_Free(lit);
+            rpoCount++;
+        } else {
+            if(fVerbose) {
+                Abc_Print(-2, "null\n");
+                Abc_Print(-2, "\n\n");
+            }
+        }
+    }
+    percent = (rpoCount * 100.0) / p->nFuncs;
+    Abc_Print(-2,"%d of %d (%.2f %%) functions are RPO.\n", rpoCount,p->nFuncs,percent);
+    Abc_PrintTime(1, "Time", clock() - clk);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Apply decomposition to truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+ ***********************************************************************/
+void Abc_TruthRpoTest(char * pFileName, int nVarNum, int nThreshold, int fVerbose) {
+    Rpo_TtStore_t * p;
+
+    // allocate data-structure
+//    if (fVerbose) {
+//        Abc_Print(-2, "Number of variables = %d\n", nVarNum);
+//    }
+    p = Abc_TtStoreLoad(pFileName, nVarNum);
+
+    if (fVerbose) {
+        Abc_Print(-2, "Number of variables = %d\n", p->nVars);
+    }
+    // consider functions from the file
+    Abc_TruthRpoPerform(p, nThreshold, fVerbose);
+
+    // delete data-structure
+    Abc_TtStoreFree(p, nVarNum);
+    //    printf( "Finished decomposing truth tables from file \"%s\".\n", pFileName );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Testbench for decomposition algorithms.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+ ***********************************************************************/
+int Abc_RpoTest(char * pFileName, int nVarNum,int nThreshold, int fVerbose) {
+    if (fVerbose) {
+        printf("Using truth tables from file \"%s\"...\n", pFileName);
+    }
+    Abc_TruthRpoTest(pFileName, nVarNum, nThreshold, fVerbose);
+    fflush(stdout);
+    return 0;
+}
+
+
+/////////////////////ert truth table to ///////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/base/abci/abcRr.c b/abc-build/src/base/abci/abcRr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcRr.c
@@ -0,0 +1,1005 @@
+/**CFile****************************************************************
+
+  FileName    [abcRr.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Redundancy removal.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcRr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "proof/fraig/fraig.h"
+#include "opt/sim/sim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Abc_RRMan_t_ Abc_RRMan_t;
+struct Abc_RRMan_t_
+{
+    // the parameters
+    Abc_Ntk_t *      pNtk;             // the network
+    int              nFaninLevels;     // the number of fanin levels
+    int              nFanoutLevels;    // the number of fanout levels
+    // the node/fanin/fanout
+    Abc_Obj_t *      pNode;            // the node
+    Abc_Obj_t *      pFanin;           // the fanin
+    Abc_Obj_t *      pFanout;          // the fanout
+    // the intermediate cones
+    Vec_Ptr_t *      vFaninLeaves;     // the leaves of the fanin cone
+    Vec_Ptr_t *      vFanoutRoots;     // the roots of the fanout cone
+    // the window
+    Vec_Ptr_t *      vLeaves;          // the leaves of the window
+    Vec_Ptr_t *      vCone;            // the internal nodes of the window
+    Vec_Ptr_t *      vRoots;           // the roots of the window
+    Abc_Ntk_t *      pWnd;             // the window derived for the edge
+    // the miter 
+    Abc_Ntk_t *      pMiter;           // the miter derived from the window
+    Prove_Params_t * pParams;          // the miter proving parameters
+    // statistical variables
+    int              nNodesOld;        // the old number of nodes
+    int              nLevelsOld;       // the old number of levels
+    int              nEdgesTried;      // the number of nodes tried
+    int              nEdgesRemoved;    // the number of nodes proved
+    abctime          timeWindow;       // the time to construct the window
+    abctime          timeMiter;        // the time to construct the miter
+    abctime          timeProve;        // the time to prove the miter
+    abctime          timeUpdate;       // the network update time
+    abctime          timeTotal;        // the total runtime
+};
+
+static Abc_RRMan_t * Abc_RRManStart();
+static void          Abc_RRManStop( Abc_RRMan_t * p );
+static void          Abc_RRManPrintStats( Abc_RRMan_t * p );
+static void          Abc_RRManClean( Abc_RRMan_t * p );
+static int           Abc_NtkRRProve( Abc_RRMan_t * p );
+static int           Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout );
+static int           Abc_NtkRRWindow( Abc_RRMan_t * p );
+
+static int           Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit );
+static int           Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout );
+static int           Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit );
+static void          Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit );
+static Abc_Ntk_t *   Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots );
+
+static void          Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk );
+static void          Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Removes stuck-at redundancies.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose )
+{
+    ProgressBar * pProgress;
+    Abc_RRMan_t * p;
+    Abc_Obj_t * pNode, * pFanin, * pFanout;
+    int i, k, m, nNodes, RetValue;
+    abctime clk, clkTotal = Abc_Clock();
+    // start the manager
+    p = Abc_RRManStart();
+    p->pNtk          = pNtk;
+    p->nFaninLevels  = nFaninLevels;
+    p->nFanoutLevels = nFanoutLevels;
+    p->nNodesOld     = Abc_NtkNodeNum(pNtk);
+    p->nLevelsOld    = Abc_AigLevel(pNtk);
+    // remember latch values
+//    Abc_NtkForEachLatch( pNtk, pNode, i )
+//        pNode->pNext = pNode->pData;
+    // go through the nodes
+    Abc_NtkCleanCopy(pNtk);
+    nNodes = Abc_NtkObjNumMax(pNtk);
+    Abc_NtkRRSimulateStart(pNtk);
+    pProgress = Extra_ProgressBarStart( stdout, nNodes );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        // stop if all nodes have been tried once
+        if ( i >= nNodes )
+            break;
+        // skip the constant node
+//        if ( Abc_NodeIsConst(pNode) )
+//            continue;
+        // skip persistant nodes
+        if ( Abc_NodeIsPersistant(pNode) )
+            continue;
+        // skip the nodes with many fanouts
+        if ( Abc_ObjFanoutNum(pNode) > 1000 )
+            continue;
+        // construct the window
+        if ( !fUseFanouts )
+        {
+            Abc_ObjForEachFanin( pNode, pFanin, k )
+            {
+                // skip the nodes with only one fanout (tree nodes)
+                if ( Abc_ObjFanoutNum(pFanin) == 1 )
+                    continue;
+/*
+                if ( pFanin->Id == 228 && pNode->Id == 2649 )
+                {
+                    int k = 0;
+                }
+*/
+                p->nEdgesTried++;
+                Abc_RRManClean( p );
+                p->pNode   = pNode;
+                p->pFanin  = pFanin;
+                p->pFanout = NULL;
+
+                clk = Abc_Clock();
+                RetValue = Abc_NtkRRWindow( p );
+                p->timeWindow += Abc_Clock() - clk;
+                if ( !RetValue )
+                    continue;
+/*
+                if ( pFanin->Id == 228 && pNode->Id == 2649 )
+                {
+                    Abc_NtkShowAig( p->pWnd, 0 );
+                }
+*/
+                clk = Abc_Clock();
+                RetValue = Abc_NtkRRProve( p );
+                p->timeMiter += Abc_Clock() - clk;
+                if ( !RetValue )
+                    continue;
+//printf( "%d -> %d (%d)\n", pFanin->Id, pNode->Id, k );
+
+                clk = Abc_Clock();
+                Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout );
+                p->timeUpdate += Abc_Clock() - clk;
+
+                p->nEdgesRemoved++;
+                break;
+            }
+            continue;
+        }
+        // use the fanouts
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+        Abc_ObjForEachFanout( pNode, pFanout, m )
+        {
+            // skip the nodes with only one fanout (tree nodes)
+//            if ( Abc_ObjFanoutNum(pFanin) == 1 && Abc_ObjFanoutNum(pNode) == 1 )
+//                continue;
+
+            p->nEdgesTried++;
+            Abc_RRManClean( p );
+            p->pNode   = pNode;
+            p->pFanin  = pFanin;
+            p->pFanout = pFanout;
+
+            clk = Abc_Clock();
+            RetValue = Abc_NtkRRWindow( p );
+            p->timeWindow += Abc_Clock() - clk;
+            if ( !RetValue )
+                continue;
+
+            clk = Abc_Clock();
+            RetValue = Abc_NtkRRProve( p );
+            p->timeMiter += Abc_Clock() - clk;
+            if ( !RetValue )
+                continue;
+
+            clk = Abc_Clock();
+            Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout );
+            p->timeUpdate += Abc_Clock() - clk;
+
+            p->nEdgesRemoved++;
+            break;
+        }
+    }
+    Abc_NtkRRSimulateStop(pNtk);
+    Extra_ProgressBarStop( pProgress );
+    p->timeTotal = Abc_Clock() - clkTotal;
+    if ( fVerbose )
+        Abc_RRManPrintStats( p );
+    Abc_RRManStop( p );
+    // restore latch values
+//    Abc_NtkForEachLatch( pNtk, pNode, i )
+//        pNode->pData = pNode->pNext, pNode->pNext = NULL;
+    // put the nodes into the DFS order and reassign their IDs
+    Abc_NtkReassignIds( pNtk );
+    Abc_NtkLevel( pNtk );
+    // check
+    if ( !Abc_NtkCheck( pNtk ) )
+    {
+        printf( "Abc_NtkRR: The network check has failed.\n" );
+        return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Start the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_RRMan_t * Abc_RRManStart()
+{
+    Abc_RRMan_t * p;
+    p = ABC_ALLOC( Abc_RRMan_t, 1 );
+    memset( p, 0, sizeof(Abc_RRMan_t) );
+    p->vFaninLeaves  = Vec_PtrAlloc( 100 );  // the leaves of the fanin cone
+    p->vFanoutRoots  = Vec_PtrAlloc( 100 );  // the roots of the fanout cone
+    p->vLeaves       = Vec_PtrAlloc( 100 );  // the leaves of the window
+    p->vCone         = Vec_PtrAlloc( 100 );  // the internal nodes of the window
+    p->vRoots        = Vec_PtrAlloc( 100 );  // the roots of the window
+    p->pParams       = ABC_ALLOC( Prove_Params_t, 1 );
+    memset( p->pParams, 0, sizeof(Prove_Params_t) );
+    Prove_ParamsSetDefault( p->pParams );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_RRManStop( Abc_RRMan_t * p )
+{
+    Abc_RRManClean( p );
+    Vec_PtrFree( p->vFaninLeaves  );  
+    Vec_PtrFree( p->vFanoutRoots  );  
+    Vec_PtrFree( p->vLeaves );  
+    Vec_PtrFree( p->vCone );  
+    Vec_PtrFree( p->vRoots );  
+    ABC_FREE( p->pParams );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_RRManPrintStats( Abc_RRMan_t * p )
+{
+    double Ratio = 100.0*(p->nNodesOld  - Abc_NtkNodeNum(p->pNtk))/p->nNodesOld;
+    printf( "Redundancy removal statistics:\n" );
+    printf( "Edges tried     = %6d.\n", p->nEdgesTried );
+    printf( "Edges removed   = %6d. (%5.2f %%)\n", p->nEdgesRemoved, 100.0*p->nEdgesRemoved/p->nEdgesTried );
+    printf( "Node gain       = %6d. (%5.2f %%)\n", p->nNodesOld  - Abc_NtkNodeNum(p->pNtk), Ratio );
+    printf( "Level gain      = %6d.\n", p->nLevelsOld - Abc_AigLevel(p->pNtk) );
+    ABC_PRT( "Windowing      ", p->timeWindow );
+    ABC_PRT( "Miter          ", p->timeMiter );
+    ABC_PRT( "    Construct  ", p->timeMiter - p->timeProve );
+    ABC_PRT( "    Prove      ", p->timeProve );
+    ABC_PRT( "Update         ", p->timeUpdate );
+    ABC_PRT( "TOTAL          ", p->timeTotal );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Clean the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_RRManClean( Abc_RRMan_t * p )
+{
+    p->pNode   = NULL; 
+    p->pFanin  = NULL; 
+    p->pFanout = NULL; 
+    Vec_PtrClear( p->vFaninLeaves  );  
+    Vec_PtrClear( p->vFanoutRoots  );  
+    Vec_PtrClear( p->vLeaves );  
+    Vec_PtrClear( p->vCone );  
+    Vec_PtrClear( p->vRoots );  
+    if ( p->pWnd )   Abc_NtkDelete( p->pWnd );
+    if ( p->pMiter ) Abc_NtkDelete( p->pMiter );
+    p->pWnd   = NULL;
+    p->pMiter = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the miter is constant 0.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRRProve( Abc_RRMan_t * p )
+{
+    Abc_Ntk_t * pWndCopy;
+    int RetValue;
+    abctime clk;
+//    Abc_NtkShowAig( p->pWnd, 0 );
+    pWndCopy = Abc_NtkDup( p->pWnd );
+    Abc_NtkRRUpdate( pWndCopy, p->pNode->pCopy->pCopy, p->pFanin->pCopy->pCopy, p->pFanout? p->pFanout->pCopy->pCopy : NULL );
+    if ( !Abc_NtkIsDfsOrdered(pWndCopy) )
+        Abc_NtkReassignIds(pWndCopy);
+    p->pMiter = Abc_NtkMiter( p->pWnd, pWndCopy, 1, 0, 0, 0 );
+    Abc_NtkDelete( pWndCopy );
+clk = Abc_Clock();
+    RetValue  = Abc_NtkMiterProve( &p->pMiter, p->pParams );
+p->timeProve += Abc_Clock() - clk;
+    if ( RetValue == 1 )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the network after redundancy removal.]
+
+  Description [This procedure assumes that non-control value of the fanin
+  was proved redundant. It is okay to concentrate on non-control values
+  because the control values can be seen as redundancy of the fanout edge.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout )
+{
+    Abc_Obj_t * pNodeNew, * pFanoutNew;
+    assert( pFanout == NULL );
+    assert( !Abc_ObjIsComplement(pNode) );
+    assert( !Abc_ObjIsComplement(pFanin) );
+    assert( !Abc_ObjIsComplement(pFanout) );
+    // find the node after redundancy removal
+    if ( pFanin == Abc_ObjFanin0(pNode) )
+        pNodeNew = Abc_ObjChild1(pNode);
+    else if ( pFanin == Abc_ObjFanin1(pNode) )
+        pNodeNew = Abc_ObjChild0(pNode);
+    else assert( 0 );
+    // replace
+    if ( pFanout == NULL )
+    {
+        Abc_AigReplace( (Abc_Aig_t *)pNtk->pManFunc, pNode, pNodeNew, 1 );
+        return 1;
+    }
+    // find the fanout after redundancy removal
+    if ( pNode == Abc_ObjFanin0(pFanout) )
+        pFanoutNew = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC0(pFanout)), Abc_ObjChild1(pFanout) );
+    else if ( pNode == Abc_ObjFanin1(pFanout) )
+        pFanoutNew = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC1(pFanout)), Abc_ObjChild0(pFanout) );
+    else assert( 0 );
+    // replace
+    Abc_AigReplace( (Abc_Aig_t *)pNtk->pManFunc, pFanout, pFanoutNew, 1 );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs window for checking RR.]
+
+  Description [If the window (p->pWnd) with the given scope (p->nFaninLevels, 
+  p->nFanoutLevels) cannot be constructed, returns 0. Otherwise, returns 1.
+  The levels are measured from the fanin node (pFanin) and the fanout node
+  (pEdgeFanout), respectively.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRRWindow( Abc_RRMan_t * p )
+{
+    Abc_Obj_t * pObj, * pEdgeFanin, * pEdgeFanout;
+    int i, LevelMin, LevelMax, RetValue;
+
+    // get the edge
+    pEdgeFanout = p->pFanout? p->pFanout : p->pNode;
+    pEdgeFanin  = p->pFanout? p->pNode : p->pFanin;
+    // get the minimum and maximum levels of the window
+    LevelMin = Abc_MaxInt( 0, ((int)p->pFanin->Level) - p->nFaninLevels );
+    LevelMax = (int)pEdgeFanout->Level + p->nFanoutLevels;
+
+    // start the TFI leaves with the fanin
+    Abc_NtkIncrementTravId( p->pNtk );
+    Abc_NodeSetTravIdCurrent( p->pFanin );
+    Vec_PtrPush( p->vFaninLeaves, p->pFanin );
+    // mark the TFI cone and collect the leaves down to the given level
+    while ( Abc_NtkRRTfi_int(p->vFaninLeaves, LevelMin) );
+
+    // mark the leaves with the new TravId
+    Abc_NtkIncrementTravId( p->pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninLeaves, pObj, i )
+        Abc_NodeSetTravIdCurrent( pObj );
+    // traverse the TFO cone of the leaves (while skipping the edge)
+    // (a) mark the nodes in the cone using the current TravId
+    // (b) collect the nodes that have external fanouts into p->vFanoutRoots
+    while ( Abc_NtkRRTfo_int(p->vFaninLeaves, p->vFanoutRoots, LevelMax, pEdgeFanin, pEdgeFanout) );
+
+    // mark the fanout roots
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanoutRoots, pObj, i )
+        pObj->fMarkA = 1;
+    // collect roots reachable from the fanout (p->vRoots)
+    RetValue = Abc_NtkRRTfo_rec( pEdgeFanout, p->vRoots, LevelMax + 1 );
+    // unmark the fanout roots
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanoutRoots, pObj, i )
+        pObj->fMarkA = 0;
+
+    // return if the window is infeasible
+    if ( RetValue == 0 )
+        return 0;
+
+    // collect the DFS-ordered new cone (p->vCone) and new leaves (p->vLeaves)
+    // using the previous marks coming from the TFO cone
+    Abc_NtkIncrementTravId( p->pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i )
+        Abc_NtkRRTfi_rec( pObj, p->vLeaves, p->vCone, LevelMin );
+
+    // create a new network
+    p->pWnd = Abc_NtkWindow( p->pNtk, p->vLeaves, p->vCone, p->vRoots );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the nodes in the TFI and collects their leaves.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit )
+{
+    Abc_Obj_t * pObj, * pNext;
+    int i, k, LevelMax, nSize;
+    assert( LevelLimit >= 0 );
+    // find the maximum level of leaves
+    LevelMax = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+        if ( LevelMax < (int)pObj->Level )
+            LevelMax = pObj->Level;
+    // if the nodes are all PIs, LevelMax == 0
+    if ( LevelMax <= LevelLimit )
+        return 0;
+    // expand the nodes with the minimum level
+    nSize = Vec_PtrSize(vLeaves);
+    Vec_PtrForEachEntryStop( Abc_Obj_t *, vLeaves, pObj, i, nSize )
+    {
+        if ( LevelMax != (int)pObj->Level )
+            continue;
+        Abc_ObjForEachFanin( pObj, pNext, k )
+        {
+            if ( Abc_NodeIsTravIdCurrent(pNext) )
+                continue;
+            Abc_NodeSetTravIdCurrent( pNext );
+            Vec_PtrPush( vLeaves, pNext );
+        }
+    }
+    // remove old nodes (cannot remove a PI)
+    k = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+    {
+        if ( LevelMax == (int)pObj->Level )
+            continue;
+        Vec_PtrWriteEntry( vLeaves, k++, pObj );
+    }
+    Vec_PtrShrink( vLeaves, k );
+    if ( Vec_PtrSize(vLeaves) > 2000 )
+        return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the nodes in the TFO and collects their roots.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout )
+{
+    Abc_Obj_t * pObj, * pNext;
+    int i, k, LevelMin, nSize, fObjIsRoot;
+    // find the minimum level of leaves
+    LevelMin = ABC_INFINITY;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+        if ( LevelMin > (int)pObj->Level )
+            LevelMin = pObj->Level;
+    // if the minimum level exceed the limit, we are done
+    if ( LevelMin > LevelLimit )
+        return 0;
+    // expand the nodes with the minimum level
+    nSize = Vec_PtrSize(vLeaves);
+    Vec_PtrForEachEntryStop( Abc_Obj_t *, vLeaves, pObj, i, nSize )
+    {
+        if ( LevelMin != (int)pObj->Level )
+            continue;
+        fObjIsRoot = 0;
+        Abc_ObjForEachFanout( pObj, pNext, k )
+        {
+            // check if the fanout is outside of the cone
+            if ( Abc_ObjIsCo(pNext) || pNext->Level > (unsigned)LevelLimit )
+            {
+                fObjIsRoot = 1;
+                continue;
+            }
+            // skip the edge under check
+            if ( pObj == pEdgeFanin && pNext == pEdgeFanout )
+                continue;
+            // skip the visited fanouts
+            if ( Abc_NodeIsTravIdCurrent(pNext) )
+                continue;
+            Abc_NodeSetTravIdCurrent( pNext );
+            Vec_PtrPush( vLeaves, pNext );
+        }
+        if ( fObjIsRoot )
+            Vec_PtrPush( vRoots, pObj );
+    }
+    // remove old nodes
+    k = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+    {
+        if ( LevelMin == (int)pObj->Level )
+            continue;
+        Vec_PtrWriteEntry( vLeaves, k++, pObj );
+    }
+    Vec_PtrShrink( vLeaves, k );
+    if ( Vec_PtrSize(vLeaves) > 2000 )
+        return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the roots in the TFO of the node.]
+
+  Description [Note that this procedure can be improved by
+  marking and skipping the visited nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    // if we encountered a node outside of the TFO cone of the fanins, quit
+    if ( Abc_ObjIsCo(pNode) || pNode->Level > (unsigned)LevelLimit )
+        return 0;
+    // if we encountered a node on the boundary, add it to the roots
+    if ( pNode->fMarkA )
+    {
+        Vec_PtrPushUnique( vRoots, pNode );
+        return 1;
+    }
+    // mark the node with the current TravId (needed to have all internal nodes marked)
+    Abc_NodeSetTravIdCurrent( pNode );
+    // traverse the fanouts
+    Abc_ObjForEachFanout( pNode, pFanout, i )
+        if ( !Abc_NtkRRTfo_rec( pFanout, vRoots, LevelLimit ) )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the leaves and cone of the roots.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    // skip visited nodes
+    if ( Abc_NodeIsTravIdCurrent(pNode) )
+        return;
+    // add node to leaves if it is not in TFI cone of the leaves (marked before) or below the limit
+    if ( !Abc_NodeIsTravIdPrevious(pNode) || (int)pNode->Level <= LevelLimit )
+    {
+        Abc_NodeSetTravIdCurrent( pNode );
+        Vec_PtrPush( vLeaves, pNode );
+        return;
+    }
+    // mark the node as visited
+    Abc_NodeSetTravIdCurrent( pNode );
+    // call for the node's fanins
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        Abc_NtkRRTfi_rec( pFanin, vLeaves, vCone, LevelLimit );
+    // add the node to the cone in topological order
+    Vec_PtrPush( vCone, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots )
+{
+    Abc_Ntk_t * pNtkNew; 
+    Abc_Obj_t * pObj;
+    int fCheck = 1;
+    int i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // start the network
+    pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+    // duplicate the name and the spec
+    pNtkNew->pName = Extra_UtilStrsav( "temp" );
+    // map the constant nodes
+    Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+    // create and map the PIs
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+        pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+    // copy the AND gates
+    Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, i )
+        pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+    // compare the number of nodes before and after
+    if ( Vec_PtrSize(vCone) != Abc_NtkNodeNum(pNtkNew) )
+        printf( "Warning: Structural hashing during windowing reduced %d nodes (this is a bug).\n",
+            Vec_PtrSize(vCone) - Abc_NtkNodeNum(pNtkNew) );
+    // create the POs
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+    {
+        assert( !Abc_ObjIsComplement(pObj->pCopy) );
+        Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pObj->pCopy );
+    }
+    // add the PI/PO names
+    Abc_NtkAddDummyPiNames( pNtkNew );
+    Abc_NtkAddDummyPoNames( pNtkNew );
+    // check
+    if ( fCheck && !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkWindow: The network check has failed.\n" );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts simulation to detect non-redundant edges.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    unsigned uData, uData0, uData1;
+    int i;
+    Abc_AigConst1(pNtk)->pData = (void *)~((unsigned)0);
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->pData = (void *)(ABC_PTRUINT_T)SIM_RANDOM_UNSIGNED;
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        if ( i == 0 ) continue;
+        uData0 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pData;
+        uData1 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin1(pObj)->pData;
+        uData  = Abc_ObjFaninC0(pObj)? ~uData0 : uData0;
+        uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1;
+        assert( pObj->pData == NULL );
+        pObj->pData = (void *)(ABC_PTRUINT_T)uData;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops simulation to detect non-redundant edges.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->pData = NULL;
+}
+
+
+
+
+
+
+
+static void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes );
+static void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField );
+static void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField );
+
+/**Function*************************************************************
+
+  Synopsis    [Simulation to detect non-redundant edges.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Abc_NtkRRSimulate( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes, * vField;
+    Vec_Str_t * vTargets;
+    Abc_Obj_t * pObj;
+    unsigned uData, uData0, uData1;
+    int PrevCi, Phase, i, k;
+
+    // start the candidates
+    vTargets = Vec_StrStart( Abc_NtkObjNumMax(pNtk) + 1 );
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        Phase = ((Abc_ObjFanoutNum(Abc_ObjFanin1(pObj)) > 1) << 1);
+        Phase |= (Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) > 1);
+        Vec_StrWriteEntry( vTargets, pObj->Id, (char)Phase );
+    }
+
+    // simulate patters and store them in copy
+    Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)~((unsigned)0);
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)SIM_RANDOM_UNSIGNED;
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        if ( i == 0 ) continue;
+        uData0 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pData;
+        uData1 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin1(pObj)->pData;
+        uData  = Abc_ObjFaninC0(pObj)? ~uData0 : uData0;
+        uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1;
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)uData;
+    }
+    // store the result in data
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        uData0 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pData;
+        if ( Abc_ObjFaninC0(pObj) )
+            pObj->pData = (void *)(ABC_PTRUINT_T)~uData0;
+        else
+            pObj->pData = (void *)(ABC_PTRUINT_T)uData0;
+    }
+
+    // refine the candidates
+    for ( PrevCi = 0; PrevCi < Abc_NtkCiNum(pNtk); PrevCi = i )
+    {
+        vNodes = Vec_PtrAlloc( 10 );
+        Abc_NtkIncrementTravId( pNtk );
+        for ( i = PrevCi; i < Abc_NtkCiNum(pNtk); i++ )
+        {
+            Sim_TraverseNodes_rec( Abc_NtkCi(pNtk, i), vTargets, vNodes );
+            if ( Vec_PtrSize(vNodes) > 128 )
+                break;
+        }
+        // collect the marked nodes in the topological order
+        vField = Vec_PtrAlloc( 10 );
+        Abc_NtkIncrementTravId( pNtk );
+        Abc_NtkForEachCo( pNtk, pObj, k )
+            Sim_CollectNodes_rec( pObj, vField );
+
+        // simulate these nodes
+        Sim_SimulateCollected( vTargets, vNodes, vField );
+        // prepare for the next loop
+        Vec_PtrFree( vNodes );
+    }
+
+    // clean
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->pData = NULL;
+    return vTargets;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes starting from the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pFanout;
+    char Entry;
+    int k;
+    if ( Abc_NodeIsTravIdCurrent(pRoot) )
+        return;
+    Abc_NodeSetTravIdCurrent( pRoot );
+    // save the reached targets
+    Entry = Vec_StrEntry(vTargets, pRoot->Id);
+    if ( Entry & 1 )
+        Vec_PtrPush( vNodes, Abc_ObjNot(pRoot) );
+    if ( Entry & 2 )
+        Vec_PtrPush( vNodes, pRoot );
+    // explore the fanouts
+    Abc_ObjForEachFanout( pRoot, pFanout, k )
+        Sim_TraverseNodes_rec( pFanout, vTargets, vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes starting from the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    if ( Abc_NodeIsTravIdCurrent(pRoot) )
+        return;
+    if ( !Abc_NodeIsTravIdPrevious(pRoot) )
+        return;
+    Abc_NodeSetTravIdCurrent( pRoot );
+    Abc_ObjForEachFanin( pRoot, pFanin, i )
+        Sim_CollectNodes_rec( pFanin, vField );
+    if ( !Abc_ObjIsCo(pRoot) )
+        pRoot->pData = (void *)(ABC_PTRUINT_T)Vec_PtrSize(vField);
+    Vec_PtrPush( vField, pRoot );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulate the given nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField )
+{
+    Abc_Obj_t * pObj, * pFanin0, * pFanin1, * pDisproved;
+    Vec_Ptr_t * vSims;
+    unsigned * pUnsigned, * pUnsignedF;
+    int i, k, Phase, fCompl;
+    // get simulation info
+    vSims = Sim_UtilInfoAlloc( Vec_PtrSize(vField), Vec_PtrSize(vNodes), 0 );
+    // simulate the nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vField, pObj, i )
+    {
+        if ( Abc_ObjIsCi(pObj) )
+        {
+            pUnsigned = (unsigned *)Vec_PtrEntry( vSims, i );
+            for ( k = 0; k < Vec_PtrSize(vNodes); k++ )
+                pUnsigned[k] = (unsigned)(ABC_PTRUINT_T)pObj->pCopy;
+            continue;
+        }
+        if ( Abc_ObjIsCo(pObj) )
+        {
+            pUnsigned  = (unsigned *)Vec_PtrEntry( vSims, i );
+            pUnsignedF = (unsigned *)Vec_PtrEntry( vSims, (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pData );
+            if ( Abc_ObjFaninC0(pObj) )
+                for ( k = 0; k < Vec_PtrSize(vNodes); k++ )
+                    pUnsigned[k] = ~pUnsignedF[k];
+            else
+                for ( k = 0; k < Vec_PtrSize(vNodes); k++ )
+                    pUnsigned[k] = pUnsignedF[k];
+            // update targets
+            for ( k = 0; k < Vec_PtrSize(vNodes); k++ )
+            {
+                if ( pUnsigned[k] == (unsigned)(ABC_PTRUINT_T)pObj->pData )
+                    continue;
+                pDisproved = (Abc_Obj_t *)Vec_PtrEntry( vNodes, k );
+                fCompl = Abc_ObjIsComplement(pDisproved);
+                pDisproved = Abc_ObjRegular(pDisproved);
+                Phase = Vec_StrEntry( vTargets, pDisproved->Id );
+                if ( fCompl )
+                    Phase = (Phase & 2);
+                else
+                    Phase = (Phase & 1);
+                Vec_StrWriteEntry( vTargets, pDisproved->Id, (char)Phase );
+            }
+            continue;
+        }
+        // simulate the node
+        pFanin0 = Abc_ObjFanin0(pObj);
+        pFanin1 = Abc_ObjFanin1(pObj);
+    }
+}
+
+
+
+/*
+                {
+                    unsigned uData;
+                    if ( pFanin == Abc_ObjFanin0(pNode) )
+                    {
+                        uData = (unsigned)Abc_ObjFanin1(pNode)->pData;
+                        uData = Abc_ObjFaninC1(pNode)? ~uData : uData;
+                    }
+                    else if ( pFanin == Abc_ObjFanin1(pNode) )
+                    {
+                        uData = (unsigned)Abc_ObjFanin0(pNode)->pData;
+                        uData = Abc_ObjFaninC0(pNode)? ~uData : uData;
+                    }
+                    uData ^= (unsigned)pNode->pData;
+//                    Extra_PrintBinary( stdout, &uData, 32 ); printf( "\n" );
+                    if ( Extra_WordCountOnes(uData) > 8 )
+                        continue;
+                }
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcSat.c b/abc-build/src/base/abci/abcSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcSat.c
@@ -0,0 +1,1012 @@
+/**CFile****************************************************************
+
+  FileName    [abcSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Procedures to solve the miter using the internal SAT sat_solver.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/main.h"
+#include "base/cmd/cmd.h"
+#include "sat/bsat/satSolver.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static sat_solver * Abc_NtkMiterSatCreateLogic( Abc_Ntk_t * pNtk, int fAllPrimes );
+extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk );
+static int nMuxes;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Attempts to solve the miter using an internal SAT sat_solver.]
+
+  Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fVerbose, ABC_INT64_T * pNumConfs, ABC_INT64_T * pNumInspects )
+{
+    sat_solver * pSat;
+    lbool   status;
+    int RetValue;
+    abctime clk;
+ 
+    if ( pNumConfs )
+        *pNumConfs = 0;
+    if ( pNumInspects )
+        *pNumInspects = 0;
+
+    assert( Abc_NtkLatchNum(pNtk) == 0 );
+
+//    if ( Abc_NtkPoNum(pNtk) > 1 )
+//        fprintf( stdout, "Warning: The miter has %d outputs. SAT will try to prove all of them.\n", Abc_NtkPoNum(pNtk) );
+
+    // load clauses into the sat_solver
+    clk = Abc_Clock();
+    pSat = (sat_solver *)Abc_NtkMiterSatCreate( pNtk, 0 );
+    if ( pSat == NULL )
+        return 1;
+//printf( "%d \n", pSat->clauses.size );
+//sat_solver_delete( pSat );
+//return 1;
+
+//    printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
+//    ABC_PRT( "Time", Abc_Clock() - clk );
+
+    // simplify the problem
+    clk = Abc_Clock();
+    status = sat_solver_simplify(pSat);
+//    printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
+//    ABC_PRT( "Time", Abc_Clock() - clk );
+    if ( status == 0 )
+    {
+        sat_solver_delete( pSat );
+//        printf( "The problem is UNSATISFIABLE after simplification.\n" );
+        return 1;
+    }
+
+    // solve the miter
+    clk = Abc_Clock();
+    if ( fVerbose )
+        pSat->verbosity = 1;
+    status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( status == l_Undef )
+    {
+//        printf( "The problem timed out.\n" );
+        RetValue = -1;
+    }
+    else if ( status == l_True )
+    {
+//        printf( "The problem is SATISFIABLE.\n" );
+        RetValue = 0;
+    }
+    else if ( status == l_False )
+    {
+//        printf( "The problem is UNSATISFIABLE.\n" );
+        RetValue = 1;
+    }
+    else
+        assert( 0 );
+//    ABC_PRT( "SAT sat_solver time", Abc_Clock() - clk );
+//    printf( "The number of conflicts = %d.\n", (int)pSat->sat_solver_stats.conflicts );
+
+    // if the problem is SAT, get the counterexample
+    if ( status == l_True )
+    {
+//        Vec_Int_t * vCiIds = Abc_NtkGetCiIds( pNtk );
+        Vec_Int_t * vCiIds = Abc_NtkGetCiSatVarNums( pNtk );
+        pNtk->pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize );
+        Vec_IntFree( vCiIds );
+    }
+    // free the sat_solver
+    if ( fVerbose )
+        Sat_SolverPrintStats( stdout, pSat );
+
+    if ( pNumConfs )
+        *pNumConfs = (int)pSat->stats.conflicts;
+    if ( pNumInspects )
+        *pNumInspects = (int)pSat->stats.inspects;
+
+sat_solver_store_write( pSat, "trace.cnf" );
+sat_solver_store_free( pSat );
+
+    sat_solver_delete( pSat );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of CI IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk )
+{
+    Vec_Int_t * vCiIds;
+    Abc_Obj_t * pObj;
+    int i;
+    vCiIds = Vec_IntAlloc( Abc_NtkCiNum(pNtk) );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        Vec_IntPush( vCiIds, (int)(ABC_PTRINT_T)pObj->pCopy );
+    return vCiIds;
+}
+
+
+ 
+/**Function*************************************************************
+
+  Synopsis    [Adds trivial clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkClauseTriv( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars )
+{
+//printf( "Adding triv %d.         %d\n", Abc_ObjRegular(pNode)->Id, (int)pSat->sat_solver_stats.clauses );
+    vVars->nSize = 0;
+    Vec_IntPush( vVars, toLitCond( (int)(ABC_PTRINT_T)Abc_ObjRegular(pNode)->pCopy, Abc_ObjIsComplement(pNode) ) );
+//    Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ) );
+    return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Adds trivial clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkClauseTop( sat_solver * pSat, Vec_Ptr_t * vNodes, Vec_Int_t * vVars )
+{
+    Abc_Obj_t * pNode;
+    int i;
+//printf( "Adding triv %d.         %d\n", Abc_ObjRegular(pNode)->Id, (int)pSat->sat_solver_stats.clauses );
+    vVars->nSize = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        Vec_IntPush( vVars, toLitCond( (int)(ABC_PTRINT_T)Abc_ObjRegular(pNode)->pCopy, Abc_ObjIsComplement(pNode) ) );
+//    Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ) );
+    return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Adds trivial clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkClauseAnd( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, Vec_Int_t * vVars )
+{
+    int fComp1, Var, Var1, i;
+//printf( "Adding AND %d.  (%d)    %d\n", pNode->Id, vSuper->nSize+1, (int)pSat->sat_solver_stats.clauses );
+
+    assert( !Abc_ObjIsComplement( pNode ) );
+    assert( Abc_ObjIsNode( pNode ) );
+
+//    nVars = sat_solver_nvars(pSat);
+    Var = (int)(ABC_PTRINT_T)pNode->pCopy;
+//    Var = pNode->Id;
+
+//    assert( Var  < nVars ); 
+    for ( i = 0; i < vSuper->nSize; i++ )
+    {
+        // get the predecessor nodes
+        // get the complemented attributes of the nodes
+        fComp1 = Abc_ObjIsComplement((Abc_Obj_t *)vSuper->pArray[i]);
+        // determine the variable numbers
+        Var1 = (int)(ABC_PTRINT_T)Abc_ObjRegular((Abc_Obj_t *)vSuper->pArray[i])->pCopy;
+//        Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->Id;
+
+        // check that the variables are in the SAT manager
+//        assert( Var1 < nVars );
+
+        // suppose the AND-gate is A * B = C
+        // add !A => !C   or   A + !C
+    //  fprintf( pFile, "%d %d 0%c", Var1, -Var, 10 );
+        vVars->nSize = 0;
+        Vec_IntPush( vVars, toLitCond(Var1, fComp1) );
+        Vec_IntPush( vVars, toLitCond(Var,  1     ) );
+        if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+            return 0;
+    }
+
+    // add A & B => C   or   !A + !B + C
+//  fprintf( pFile, "%d %d %d 0%c", -Var1, -Var2, Var, 10 );
+    vVars->nSize = 0;
+    for ( i = 0; i < vSuper->nSize; i++ )
+    {
+        // get the predecessor nodes
+        // get the complemented attributes of the nodes
+        fComp1 = Abc_ObjIsComplement((Abc_Obj_t *)vSuper->pArray[i]);
+        // determine the variable numbers
+        Var1 = (int)(ABC_PTRINT_T)Abc_ObjRegular((Abc_Obj_t *)vSuper->pArray[i])->pCopy;
+//        Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->Id;
+        // add this variable to the array
+        Vec_IntPush( vVars, toLitCond(Var1, !fComp1) );
+    }
+    Vec_IntPush( vVars, toLitCond(Var, 0) );
+    return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Adds trivial clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkClauseMux( sat_solver * pSat, Abc_Obj_t * pNode, Abc_Obj_t * pNodeC, Abc_Obj_t * pNodeT, Abc_Obj_t * pNodeE, Vec_Int_t * vVars )
+{
+    int VarF, VarI, VarT, VarE, fCompT, fCompE;
+//printf( "Adding mux %d.         %d\n", pNode->Id, (int)pSat->sat_solver_stats.clauses );
+
+    assert( !Abc_ObjIsComplement( pNode ) );
+    assert( Abc_NodeIsMuxType( pNode ) );
+    // get the variable numbers
+    VarF = (int)(ABC_PTRINT_T)pNode->pCopy;
+    VarI = (int)(ABC_PTRINT_T)pNodeC->pCopy;
+    VarT = (int)(ABC_PTRINT_T)Abc_ObjRegular(pNodeT)->pCopy;
+    VarE = (int)(ABC_PTRINT_T)Abc_ObjRegular(pNodeE)->pCopy;
+//    VarF = (int)pNode->Id;
+//    VarI = (int)pNodeC->Id;
+//    VarT = (int)Abc_ObjRegular(pNodeT)->Id;
+//    VarE = (int)Abc_ObjRegular(pNodeE)->Id;
+
+    // get the complementation flags
+    fCompT = Abc_ObjIsComplement(pNodeT);
+    fCompE = Abc_ObjIsComplement(pNodeE);
+
+    // f = ITE(i, t, e)
+    // i' + t' + f
+    // i' + t  + f'
+    // i  + e' + f
+    // i  + e  + f'
+    // create four clauses
+    vVars->nSize = 0;
+    Vec_IntPush( vVars, toLitCond(VarI,  1) );
+    Vec_IntPush( vVars, toLitCond(VarT,  1^fCompT) );
+    Vec_IntPush( vVars, toLitCond(VarF,  0) );
+    if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+        return 0;
+    vVars->nSize = 0;
+    Vec_IntPush( vVars, toLitCond(VarI,  1) );
+    Vec_IntPush( vVars, toLitCond(VarT,  0^fCompT) );
+    Vec_IntPush( vVars, toLitCond(VarF,  1) );
+    if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+        return 0;
+    vVars->nSize = 0;
+    Vec_IntPush( vVars, toLitCond(VarI,  0) );
+    Vec_IntPush( vVars, toLitCond(VarE,  1^fCompE) );
+    Vec_IntPush( vVars, toLitCond(VarF,  0) );
+    if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+        return 0;
+    vVars->nSize = 0;
+    Vec_IntPush( vVars, toLitCond(VarI,  0) );
+    Vec_IntPush( vVars, toLitCond(VarE,  0^fCompE) );
+    Vec_IntPush( vVars, toLitCond(VarF,  1) );
+    if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+        return 0;
+ 
+    if ( VarT == VarE )
+    {
+//        assert( fCompT == !fCompE );
+        return 1;
+    }
+
+    // two additional clauses
+    // t' & e' -> f'       t  + e   + f'
+    // t  & e  -> f        t' + e'  + f 
+    vVars->nSize = 0;
+    Vec_IntPush( vVars, toLitCond(VarT,  0^fCompT) );
+    Vec_IntPush( vVars, toLitCond(VarE,  0^fCompE) );
+    Vec_IntPush( vVars, toLitCond(VarF,  1) );
+    if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+        return 0;
+    vVars->nSize = 0;
+    Vec_IntPush( vVars, toLitCond(VarT,  1^fCompT) );
+    Vec_IntPush( vVars, toLitCond(VarE,  1^fCompE) );
+    Vec_IntPush( vVars, toLitCond(VarF,  0) );
+    return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCollectSupergate_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, int fFirst, int fStopAtMux )
+{
+    int RetValue1, RetValue2, i;
+    // check if the node is visited
+    if ( Abc_ObjRegular(pNode)->fMarkB )
+    {
+        // check if the node occurs in the same polarity
+        for ( i = 0; i < vSuper->nSize; i++ )
+            if ( vSuper->pArray[i] == pNode )
+                return 1;
+        // check if the node is present in the opposite polarity
+        for ( i = 0; i < vSuper->nSize; i++ )
+            if ( vSuper->pArray[i] == Abc_ObjNot(pNode) )
+                return -1;
+        assert( 0 );
+        return 0;
+    }
+    // if the new node is complemented or a PI, another gate begins
+    if ( !fFirst )
+        if ( Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || Abc_ObjFanoutNum(pNode) > 1 || (fStopAtMux && Abc_NodeIsMuxType(pNode)) )
+        {
+            Vec_PtrPush( vSuper, pNode );
+            Abc_ObjRegular(pNode)->fMarkB = 1;
+            return 0;
+        }
+    assert( !Abc_ObjIsComplement(pNode) );
+    assert( Abc_ObjIsNode(pNode) );
+    // go through the branches
+    RetValue1 = Abc_NtkCollectSupergate_rec( Abc_ObjChild0(pNode), vSuper, 0, fStopAtMux );
+    RetValue2 = Abc_NtkCollectSupergate_rec( Abc_ObjChild1(pNode), vSuper, 0, fStopAtMux );
+    if ( RetValue1 == -1 || RetValue2 == -1 )
+        return -1;
+    // return 1 if at least one branch has a duplicate
+    return RetValue1 || RetValue2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCollectSupergate( Abc_Obj_t * pNode, int fStopAtMux, Vec_Ptr_t * vNodes )
+{
+    int RetValue, i;
+    assert( !Abc_ObjIsComplement(pNode) );
+    // collect the nodes in the implication supergate
+    Vec_PtrClear( vNodes );
+    RetValue = Abc_NtkCollectSupergate_rec( pNode, vNodes, 1, fStopAtMux );
+    assert( vNodes->nSize > 1 );
+    // unmark the visited nodes
+    for ( i = 0; i < vNodes->nSize; i++ )
+        Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->fMarkB = 0;
+    // if we found the node and its complement in the same implication supergate, 
+    // return empty set of nodes (meaning that we should use constant-0 node)
+    if ( RetValue == -1 )
+        vNodes->nSize = 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the factor of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkNodeFactor( Abc_Obj_t * pObj, int nLevelMax )
+{
+//  nLevelMax = ((nLevelMax)/2)*3;
+    assert( (int)pObj->Level <= nLevelMax );
+//    return (int)(100000000.0 * pow(0.999, nLevelMax - pObj->Level));
+    return (int)(100000000.0 * (1 + 0.01 * pObj->Level));
+//    return (int)(100000000.0 / ((nLevelMax)/2)*3 - pObj->Level);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets up the SAT sat_solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMiterSatCreateInt( sat_solver * pSat, Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode, * pFanin, * pNodeC, * pNodeT, * pNodeE;
+    Vec_Ptr_t * vNodes, * vSuper;
+    Vec_Int_t * vVars;
+    int i, k, fUseMuxes = 1;
+//    int fOrderCiVarsFirst = 0;
+    int RetValue = 0;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    // clean the CI node pointers
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        pNode->pCopy = NULL;
+
+    // start the data structures
+    vNodes  = Vec_PtrAlloc( 1000 );   // the nodes corresponding to vars in the sat_solver
+    vSuper  = Vec_PtrAlloc( 100 );    // the nodes belonging to the given implication supergate
+    vVars   = Vec_IntAlloc( 100 );    // the temporary array for variables in the clause
+
+    // add the clause for the constant node
+    pNode = Abc_AigConst1(pNtk);
+    pNode->fMarkA = 1;
+    pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)vNodes->nSize;
+    Vec_PtrPush( vNodes, pNode );
+    Abc_NtkClauseTriv( pSat, pNode, vVars );
+/*
+    // add the PI variables first
+    Abc_NtkForEachCi( pNtk, pNode, i )
+    {
+        pNode->fMarkA = 1;
+        pNode->pCopy = (Abc_Obj_t *)vNodes->nSize;
+        Vec_PtrPush( vNodes, pNode );
+    }
+*/
+    // collect the nodes that need clauses and top-level assignments
+    Vec_PtrClear( vSuper );
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        // get the fanin
+        pFanin = Abc_ObjFanin0(pNode);
+        // create the node's variable
+        if ( pFanin->fMarkA == 0 )
+        {
+            pFanin->fMarkA = 1;
+            pFanin->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)vNodes->nSize;
+            Vec_PtrPush( vNodes, pFanin );
+        }
+        // add the trivial clause
+        Vec_PtrPush( vSuper, Abc_ObjChild0(pNode) );
+    }
+    if ( !Abc_NtkClauseTop( pSat, vSuper, vVars ) )
+        goto Quits;
+
+
+    // add the clauses
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        assert( !Abc_ObjIsComplement(pNode) );
+        if ( !Abc_AigNodeIsAnd(pNode) )
+            continue;
+//printf( "%d ", pNode->Id );
+
+        // add the clauses
+        if ( fUseMuxes && Abc_NodeIsMuxType(pNode) )
+        {
+            nMuxes++;
+
+            pNodeC = Abc_NodeRecognizeMux( pNode, &pNodeT, &pNodeE );
+            Vec_PtrClear( vSuper );
+            Vec_PtrPush( vSuper, pNodeC );
+            Vec_PtrPush( vSuper, pNodeT );
+            Vec_PtrPush( vSuper, pNodeE );
+            // add the fanin nodes to explore
+            Vec_PtrForEachEntry( Abc_Obj_t *, vSuper, pFanin, k )
+            {
+                pFanin = Abc_ObjRegular(pFanin);
+                if ( pFanin->fMarkA == 0 )
+                {
+                    pFanin->fMarkA = 1;
+                    pFanin->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)vNodes->nSize;
+                    Vec_PtrPush( vNodes, pFanin );
+                }
+            }
+            // add the clauses
+            if ( !Abc_NtkClauseMux( pSat, pNode, pNodeC, pNodeT, pNodeE, vVars ) )
+                goto Quits;
+        }
+        else
+        {
+            // get the supergate
+            Abc_NtkCollectSupergate( pNode, fUseMuxes, vSuper );
+            // add the fanin nodes to explore
+            Vec_PtrForEachEntry( Abc_Obj_t *, vSuper, pFanin, k )
+            {
+                pFanin = Abc_ObjRegular(pFanin);
+                if ( pFanin->fMarkA == 0 )
+                {
+                    pFanin->fMarkA = 1;
+                    pFanin->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)vNodes->nSize;
+                    Vec_PtrPush( vNodes, pFanin );
+                }
+            }
+            // add the clauses
+            if ( vSuper->nSize == 0 )
+            {
+                if ( !Abc_NtkClauseTriv( pSat, Abc_ObjNot(pNode), vVars ) )
+//                if ( !Abc_NtkClauseTriv( pSat, pNode, vVars ) )
+                    goto Quits;
+            }
+            else
+            {
+                if ( !Abc_NtkClauseAnd( pSat, pNode, vSuper, vVars ) )
+                    goto Quits;
+            }
+        }
+    }
+/*
+    // set preferred variables
+    if ( fOrderCiVarsFirst )
+    {
+        int * pPrefVars = ABC_ALLOC( int, Abc_NtkCiNum(pNtk) );
+        int nVars = 0;
+        Abc_NtkForEachCi( pNtk, pNode, i )
+        {
+            if ( pNode->fMarkA == 0 )
+                continue;
+            pPrefVars[nVars++] = (int)pNode->pCopy;
+        }
+        nVars = Abc_MinInt( nVars, 10 );
+        ASat_SolverSetPrefVars( pSat, pPrefVars, nVars );
+    }
+*/
+/*
+    Abc_NtkForEachObj( pNtk, pNode, i )
+    {
+        if ( !pNode->fMarkA )
+            continue;
+        printf( "%10s : ", Abc_ObjName(pNode) );
+        printf( "%3d\n", (int)pNode->pCopy );
+    }
+    printf( "\n" );
+*/
+    RetValue = 1;
+Quits :
+    // delete
+    Vec_IntFree( vVars );
+    Vec_PtrFree( vNodes );
+    Vec_PtrFree( vSuper );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets up the SAT sat_solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fAllPrimes )
+{
+    sat_solver * pSat;
+    Abc_Obj_t * pNode;
+    int RetValue, i; //, clk = Abc_Clock();
+
+    assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsBddLogic(pNtk) );
+    if ( Abc_NtkIsBddLogic(pNtk) )
+        return Abc_NtkMiterSatCreateLogic(pNtk, fAllPrimes);
+
+    nMuxes = 0;
+    pSat = sat_solver_new();
+//sat_solver_store_alloc( pSat );
+    RetValue = Abc_NtkMiterSatCreateInt( pSat, pNtk );
+sat_solver_store_mark_roots( pSat );
+
+    Abc_NtkForEachObj( pNtk, pNode, i )
+        pNode->fMarkA = 0;
+//    ASat_SolverWriteDimacs( pSat, "temp_sat.cnf", NULL, NULL, 1 );
+    if ( RetValue == 0 )
+    {
+        sat_solver_delete(pSat);
+        return NULL;
+    }
+//    printf( "Ands = %6d.  Muxes = %6d (%5.2f %%).  ", Abc_NtkNodeNum(pNtk), nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) );
+//    ABC_PRT( "Creating sat_solver", Abc_Clock() - clk );
+    return pSat;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Adds clauses for the internal node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeAddClauses( sat_solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t * pNode, Vec_Int_t * vVars )
+{
+    Abc_Obj_t * pFanin;
+    int i, c, nFanins;
+    int RetValue;
+    char * pCube;
+
+    nFanins = Abc_ObjFaninNum( pNode );
+    assert( nFanins == Abc_SopGetVarNum( pSop0 ) );
+
+//    if ( nFanins == 0 )
+    if ( Cudd_Regular((Abc_Obj_t *)pNode->pData) == Cudd_ReadOne((DdManager *)pNode->pNtk->pManFunc) )
+    {
+        vVars->nSize = 0;
+//        if ( Abc_SopIsConst1(pSop1) )
+        if ( !Cudd_IsComplement(pNode->pData) )
+            Vec_IntPush( vVars, toLit(pNode->Id) );
+        else
+            Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) );
+        RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+        if ( !RetValue ) 
+        {
+            printf( "The CNF is trivially UNSAT.\n" );
+            return 0;
+        }
+        return 1;
+    }
+ 
+    // add clauses for the negative phase
+    for ( c = 0; ; c++ )
+    {
+        // get the cube
+        pCube = pSop0 + c * (nFanins + 3);
+        if ( *pCube == 0 )
+            break;
+        // add the clause
+        vVars->nSize = 0;
+        Abc_ObjForEachFanin( pNode, pFanin, i )
+        {
+            if ( pCube[i] == '0' )
+                Vec_IntPush( vVars, toLit(pFanin->Id) );
+            else if ( pCube[i] == '1' )
+                Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) );
+        }
+        Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) );
+        RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+        if ( !RetValue ) 
+        {
+            printf( "The CNF is trivially UNSAT.\n" );
+            return 0;
+        }
+    }
+
+    // add clauses for the positive phase
+    for ( c = 0; ; c++ )
+    {
+        // get the cube
+        pCube = pSop1 + c * (nFanins + 3);
+        if ( *pCube == 0 )
+            break;
+        // add the clause
+        vVars->nSize = 0;
+        Abc_ObjForEachFanin( pNode, pFanin, i )
+        {
+            if ( pCube[i] == '0' )
+                Vec_IntPush( vVars, toLit(pFanin->Id) );
+            else if ( pCube[i] == '1' )
+                Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) );
+        }
+        Vec_IntPush( vVars, toLit(pNode->Id) );
+        RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+        if ( !RetValue ) 
+        {
+            printf( "The CNF is trivially UNSAT.\n" );
+            return 0;
+        }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds clauses for the PO node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeAddClausesTop( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars )
+{
+    Abc_Obj_t * pFanin;
+    int RetValue;
+
+    pFanin = Abc_ObjFanin0(pNode);
+    if ( Abc_ObjFaninC0(pNode) )
+    {
+        vVars->nSize = 0;
+        Vec_IntPush( vVars, toLit(pFanin->Id) );
+        Vec_IntPush( vVars, toLit(pNode->Id) );
+        RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+        if ( !RetValue ) 
+        {
+            printf( "The CNF is trivially UNSAT.\n" );
+            return 0;
+        }
+
+        vVars->nSize = 0;
+        Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) );
+        Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) );
+        RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+        if ( !RetValue ) 
+        {
+            printf( "The CNF is trivially UNSAT.\n" );
+            return 0;
+        }
+    }
+    else
+    {
+        vVars->nSize = 0;
+        Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) );
+        Vec_IntPush( vVars, toLit(pNode->Id) );
+        RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+        if ( !RetValue ) 
+        {
+            printf( "The CNF is trivially UNSAT.\n" );
+            return 0;
+        }
+
+        vVars->nSize = 0;
+        Vec_IntPush( vVars, toLit(pFanin->Id) );
+        Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) );
+        RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+        if ( !RetValue ) 
+        {
+            printf( "The CNF is trivially UNSAT.\n" );
+            return 0;
+        }
+    }
+
+    vVars->nSize = 0;
+    Vec_IntPush( vVars, toLit(pNode->Id) );
+    RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+    if ( !RetValue ) 
+    {
+        printf( "The CNF is trivially UNSAT.\n" );
+        return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets up the SAT sat_solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+sat_solver * Abc_NtkMiterSatCreateLogic( Abc_Ntk_t * pNtk, int fAllPrimes )
+{
+    sat_solver * pSat;
+    Mem_Flex_t * pMmFlex;
+    Abc_Obj_t * pNode;
+    Vec_Str_t * vCube;
+    Vec_Int_t * vVars;
+    char * pSop0, * pSop1;
+    int i;
+
+    assert( Abc_NtkIsBddLogic(pNtk) );
+
+    // transfer the IDs to the copy field
+    Abc_NtkForEachPi( pNtk, pNode, i )
+        pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)pNode->Id;
+
+    // start the data structures
+    pSat    = sat_solver_new();
+sat_solver_store_alloc( pSat );
+    pMmFlex = Mem_FlexStart();
+    vCube   = Vec_StrAlloc( 100 );
+    vVars   = Vec_IntAlloc( 100 );
+
+    // add clauses for each internal nodes
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        // derive SOPs for both phases of the node
+        Abc_NodeBddToCnf( pNode, pMmFlex, vCube, fAllPrimes, &pSop0, &pSop1 );
+        // add the clauses to the sat_solver
+        if ( !Abc_NodeAddClauses( pSat, pSop0, pSop1, pNode, vVars ) )
+        {
+            sat_solver_delete( pSat );
+            pSat = NULL;
+            goto finish;
+        }
+    }
+    // add clauses for each PO
+    Abc_NtkForEachPo( pNtk, pNode, i )
+    {
+        if ( !Abc_NodeAddClausesTop( pSat, pNode, vVars ) )
+        {
+            sat_solver_delete( pSat );
+            pSat = NULL;
+            goto finish;
+        }
+    }
+sat_solver_store_mark_roots( pSat );
+
+finish:
+    // delete
+    Vec_StrFree( vCube );
+    Vec_IntFree( vVars );
+    Mem_FlexStop( pMmFlex, 0 );
+    return pSat;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes CNF for the sorter with N inputs asserting Q ones.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkWriteSorterCnf( char * pFileName, int nVars, int nQueens )
+{
+    char Command[100];
+    void * pAbc;
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pObj, * ppNodes[2], * ppRoots[2];
+    Vec_Ptr_t * vNodes;
+    FILE * pFile;
+    int i, Counter;
+
+    if ( nQueens <= 0 && nQueens >= nVars )
+    {
+        printf( "The number of queens (Q = %d) should belong to the interval: 0 < Q < %d.\n", nQueens, nQueens);
+        return;
+    }
+    assert( nQueens > 0 && nQueens < nVars );
+	pAbc = Abc_FrameGetGlobalFrame();
+    // generate sorter
+    sprintf( Command, "gen -s -N %d sorter%d.blif", nVars, nVars );
+    if ( Cmd_CommandExecute( (Abc_Frame_t *)pAbc, Command ) )
+    {
+        fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+        return;
+    }
+    // read the file
+    sprintf( Command, "read sorter%d.blif; strash", nVars );
+    if ( Cmd_CommandExecute( (Abc_Frame_t *)pAbc, Command ) )
+    {
+        fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+        return;
+    }
+
+    // get the current network
+    pNtk = Abc_FrameReadNtk((Abc_Frame_t *)pAbc);
+    // collect the nodes for the given two primary outputs
+    ppNodes[0] = Abc_NtkPo( pNtk, nVars - nQueens - 1 );
+    ppNodes[1] = Abc_NtkPo( pNtk, nVars - nQueens );
+    ppRoots[0] = Abc_ObjFanin0( ppNodes[0] );
+    ppRoots[1] = Abc_ObjFanin0( ppNodes[1] );
+    vNodes = Abc_NtkDfsNodes( pNtk, ppRoots, 2 );
+
+    // assign CNF variables
+    Counter = 0;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)~0;
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Counter++;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Counter++;
+
+/*
+        OutVar   = pCnf->pVarNums[ pObj->Id ];
+        pVars[0] = pCnf->pVarNums[ Aig_ObjFanin0(pObj)->Id ];
+        pVars[1] = pCnf->pVarNums[ Aig_ObjFanin1(pObj)->Id ];
+
+        // positive phase
+        *pClas++ = pLits;
+        *pLits++ = 2 * OutVar; 
+        *pLits++ = 2 * pVars[0] + !Aig_ObjFaninC0(pObj); 
+        *pLits++ = 2 * pVars[1] + !Aig_ObjFaninC1(pObj); 
+        // negative phase
+        *pClas++ = pLits;
+        *pLits++ = 2 * OutVar + 1; 
+        *pLits++ = 2 * pVars[0] + Aig_ObjFaninC0(pObj); 
+        *pClas++ = pLits;
+        *pLits++ = 2 * OutVar + 1; 
+        *pLits++ = 2 * pVars[1] + Aig_ObjFaninC1(pObj); 
+*/
+
+    // add clauses for these nodes
+    pFile = fopen( pFileName, "w" );
+    fprintf( pFile, "c CNF for %d-bit sorter with %d bits set to 1 generated by ABC.\n", nVars, nQueens );
+    fprintf( pFile, "p cnf %d %d\n", Counter, 3 * Vec_PtrSize(vNodes) + 2 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        // positive phase
+        fprintf( pFile, "%d %s%d %s%d 0\n", 1+(int)(ABC_PTRINT_T)pObj->pCopy,
+            Abc_ObjFaninC0(pObj)? "" : "-", 1+(int)(ABC_PTRINT_T)Abc_ObjFanin0(pObj)->pCopy,
+            Abc_ObjFaninC1(pObj)? "" : "-", 1+(int)(ABC_PTRINT_T)Abc_ObjFanin1(pObj)->pCopy );
+        // negative phase
+        fprintf( pFile, "-%d %s%d 0\n",     1+(int)(ABC_PTRINT_T)pObj->pCopy,
+            Abc_ObjFaninC0(pObj)? "-" : "", 1+(int)(ABC_PTRINT_T)Abc_ObjFanin0(pObj)->pCopy );
+        fprintf( pFile, "-%d %s%d 0\n",     1+(int)(ABC_PTRINT_T)pObj->pCopy,
+            Abc_ObjFaninC1(pObj)? "-" : "", 1+(int)(ABC_PTRINT_T)Abc_ObjFanin1(pObj)->pCopy );
+    }
+    Vec_PtrFree( vNodes );
+
+/*
+    *pClas++ = pLits;
+    *pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj); 
+*/
+    // assert the first literal to zero
+    fprintf( pFile, "%s%d 0\n", 
+        Abc_ObjFaninC0(ppNodes[0])? "" : "-", 1+(int)(ABC_PTRINT_T)Abc_ObjFanin0(ppNodes[0])->pCopy );
+    // assert the second literal to one
+    fprintf( pFile, "%s%d 0\n", 
+        Abc_ObjFaninC0(ppNodes[1])? "-" : "", 1+(int)(ABC_PTRINT_T)Abc_ObjFanin0(ppNodes[1])->pCopy );
+    fclose( pFile );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcSaucy.c b/abc-build/src/base/abci/abcSaucy.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcSaucy.c
@@ -0,0 +1,3346 @@
+/**CFile****************************************************************
+
+  FileName    [abcSaucy.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Symmetry Detection Package.]
+
+  Synopsis    [Finds symmetries under permutation (but not negation) of I/Os.]
+
+  Author      [Hadi Katebi]
+  
+  Affiliation [University of Michigan]
+
+  Date        [Ver. 1.0. Started - April, 2012.]
+
+  Revision    [No revisions so far]
+
+  Comments    []                          
+
+  Debugging   [There are some part of the code that are commented out. Those parts mostly print
+               the contents of the data structures to the standard output. Un-comment them if you 
+               find them useful for debugging.]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "opt/sim/sim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/* on/off switches */
+#define REFINE_BY_SIM_1     0
+#define REFINE_BY_SIM_2     0
+#define BACKTRACK_BY_SAT    1
+#define SELECT_DYNAMICALLY  0
+
+/* number of iterations for sim1 and sim2 refinements */
+int NUM_SIM1_ITERATION;
+int NUM_SIM2_ITERATION;
+
+/* conflict analysis */
+#define CLAUSE_DECAY 0.9
+#define MAX_LEARNTS  50
+
+/*
+ * saucy.c 
+ *
+ * by Paul T. Darga <pdarga@umich.edu>
+ * and Mark Liffiton <liffiton@umich.edu>
+ * and Hadi Katebi <hadik@eecs.umich.edu>
+ * 
+ * Copyright (C) 2004, The Regents of the University of Michigan
+ * See the LICENSE file for details.
+ */
+
+struct saucy_stats {
+    double grpsize_base;
+    int grpsize_exp;
+    int levels;
+    int nodes;
+    int bads;
+    int gens;
+    int support;
+};
+
+struct saucy_graph {
+    int n;
+    int e;
+    int *adj;
+    int *edg;
+};
+
+struct coloring {
+    int *lab;        /* Labelling of objects */
+    int *unlab;      /* Inverse of lab */
+    int *cfront;     /* Pointer to front of cells */
+    int *clen;       /* Length of cells (defined for cfront's) */
+};
+
+struct sim_result {
+    int *inVec;
+    int *outVec;
+    int inVecSignature;
+    int outVecOnes; 
+    double activity;
+};
+
+struct saucy {
+    /* Graph data */
+    int n;           /* Size of domain */
+    int *adj;        /* Neighbors of k: edg[adj[k]]..edg[adj[k+1]] */
+    int *edg;        /* Actual neighbor data */
+    int *dadj;       /* Fanin neighbor indices, for digraphs */
+    int *dedg;       /* Fanin neighbor data, for digraphs */    
+
+    /* Coloring data */
+    struct coloring left, right;
+    int *nextnon;    /* Forward next-nonsingleton pointers */ 
+    int *prevnon;    /* Backward next-nonsingleton pointers */
+
+    /* Refinement: inducers */
+    char *indmark;   /* Induce marks */
+    int *ninduce;    /* Nonsingletons that might induce refinement */
+    int *sinduce;    /* Singletons that might induce refinement */
+    int nninduce;    /* Size of ninduce stack */
+    int nsinduce;    /* Size of sinduce stack */
+
+    /* Refinement: marked cells */
+    int *clist;      /* List of cells marked for refining */
+    int csize;       /* Number of cells in clist */
+
+    /* Refinement: workspace */
+    char *stuff;     /* Bit vector, but one char per bit */
+    int *ccount;     /* Number of connections to refining cell */
+    int *bucket;     /* Workspace */
+    int *count;      /* Num vertices with same adj count to ref cell */
+    int *junk;       /* More workspace */
+    int *gamma;      /* Working permutation */
+    int *conncnts;   /* Connection counts for cell fronts */
+
+    /* Search data */
+    int lev;         /* Current search tree level */
+    int anc;         /* Level of greatest common ancestor with zeta */
+    int *anctar;     /* Copy of target cell at anc */
+    int kanctar;     /* Location within anctar to iterate from */
+    int *start;      /* Location of target at each level */
+    int indmin;      /* Used for group size computation */
+    int match;       /* Have we not diverged from previous left? */
+
+    /* Search: orbit partition */
+    int *theta;      /* Running approximation of orbit partition */
+    int *thsize;     /* Size of cells in theta, defined for mcrs */
+    int *thnext;     /* Next rep in list (circular list) */
+    int *thprev;     /* Previous rep in list */
+    int *threp;      /* First rep for a given cell front */
+    int *thfront;    /* The cell front associated with this rep */
+
+    /* Search: split record */
+    int *splitvar;   /* The actual value of the splits on the left-most branch */
+    int *splitwho;   /* List of where splits occurred */
+    int *splitfrom;  /* List of cells which were split */
+    int *splitlev;   /* Where splitwho/from begins for each level */
+    int nsplits;     /* Number of splits at this point */
+
+    /* Search: differences from leftmost */
+    char *diffmark;  /* Marked for diff labels */
+    int *diffs;      /* List of diff labels */
+    int *difflev;    /* How many labels diffed at each level */
+    int ndiffs;      /* Current number of diffs */
+    int *undifflev;  /* How many diff labels fixed at each level */
+    int nundiffs;    /* Current number of diffs in singletons (fixed) */
+    int *unsupp;     /* Inverted diff array */
+    int *specmin;    /* Speculated mappings */
+    int *pairs;      /* Not-undiffed diffs that can make two-cycles */
+    int *unpairs;    /* Indices into pairs */
+    int npairs;      /* Number of such pairs */
+    int *diffnons;   /* Diffs that haven't been undiffed */
+    int *undiffnons; /* Inverse of that */
+    int ndiffnons;   /* Number of such diffs */
+
+    /* Polymorphic functions */
+    int (*split)(struct saucy *, struct coloring *, int, int);
+    int (*is_automorphism)(struct saucy *);
+    int (*ref_singleton)(struct saucy *, struct coloring *, int);
+    int (*ref_nonsingle)(struct saucy *, struct coloring *, int);
+    void (*select_decomposition)(struct saucy *, int *, int *, int *);
+
+     /* Statistics structure */
+    struct saucy_stats *stats;
+
+    /* New data structures for Boolean formulas */
+    Abc_Ntk_t * pNtk;
+    Abc_Ntk_t * pNtk_permuted;
+    int * depAdj;
+    int * depEdg;
+    Vec_Int_t ** iDep, ** oDep;
+    Vec_Int_t ** obs, ** ctrl;  
+    Vec_Ptr_t ** topOrder;
+    Vec_Ptr_t * randomVectorArray_sim1;
+    int * randomVectorSplit_sim1;
+    Vec_Ptr_t * randomVectorArray_sim2;
+    int * randomVectorSplit_sim2;
+    char * marks;
+    int * pModel;
+    Vec_Ptr_t * satCounterExamples;
+    double activityInc;
+
+    int fBooleanMatching;
+    int fPrintTree;
+    int fLookForSwaps;
+    FILE * gFile;
+    
+    int (*refineBySim1)(struct saucy *, struct coloring *);
+    int (*refineBySim2)(struct saucy *, struct coloring *);
+    int (*print_automorphism)(FILE *f, int n, const int *gamma, int nsupp, const int *support, char * marks, Abc_Ntk_t * pNtk);
+};
+
+static int  *ints(int n) { return ABC_ALLOC(int, n); }
+static int  *zeros(int n) { return ABC_CALLOC(int, n); }
+static char *bits(int n) { return ABC_CALLOC(char, n); }
+
+static char *               getVertexName(Abc_Ntk_t *pNtk, int v);
+static int *                generateProperInputVector(Abc_Ntk_t * pNtk, struct coloring *c, Vec_Int_t * randomVector);
+static int                  ifInputVectorsAreConsistent(struct saucy * s, int * leftVec, int * rightVec);
+static int                  ifOutputVectorsAreConsistent(struct saucy * s, int * leftVec, int * rightVec);
+static Vec_Ptr_t **         findTopologicalOrder(Abc_Ntk_t * pNtk);
+static void                 getDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep);
+static struct saucy_graph * buildDepGraph (Abc_Ntk_t *pNtk, Vec_Int_t ** iDep, Vec_Int_t ** oDep);
+static struct saucy_graph * buildSim1Graph(Abc_Ntk_t * pNtk, struct coloring *c, Vec_Int_t * randVec, Vec_Int_t ** iDep, Vec_Int_t ** oDep);
+static struct saucy_graph * buildSim2Graph(Abc_Ntk_t * pNtk, struct coloring *c, Vec_Int_t * randVec, Vec_Int_t ** iDep, Vec_Int_t ** oDep, Vec_Ptr_t ** topOrder, Vec_Int_t ** obs,  Vec_Int_t ** ctrl);
+static Vec_Int_t *          assignRandomBitsToCells(Abc_Ntk_t * pNtk, struct coloring *c);
+static int                  Abc_NtkCecSat_saucy(Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel);
+static struct sim_result *  analyzeConflict(Abc_Ntk_t * pNtk, int * pModel, int fVerbose);
+static void                 bumpActivity (struct saucy * s, struct sim_result * cex);
+static void                 reduceDB(struct saucy * s);
+
+
+static int
+print_automorphism_ntk(FILE *f, int n, const int *gamma, int nsupp, const int *support, char * marks, Abc_Ntk_t * pNtk)
+{
+    int i, j, k;    
+
+    /* We presume support is already sorted */
+    for (i = 0; i < nsupp; ++i) {
+        k = support[i];
+
+        /* Skip elements already seen */
+        if (marks[k]) continue;
+
+        /* Start an orbit */
+        marks[k] = 1;
+        fprintf(f, "(%s", getVertexName(pNtk, k));
+
+        /* Mark and notify elements in this orbit */
+        for (j = gamma[k]; j != k; j = gamma[j]) {
+            marks[j] = 1;
+            fprintf(f, " %s", getVertexName(pNtk, j));
+        }
+
+        /* Finish off the orbit */
+        fprintf(f, ")");
+    }
+    fprintf(f, "\n");
+
+    /* Clean up after ourselves */
+    for (i = 0; i < nsupp; ++i) {
+        marks[support[i]] = 0;
+    }
+
+    return 1;
+}
+
+static int
+print_automorphism_ntk2(FILE *f, int n, const int *gamma, int nsupp, const int *support, char * marks, Abc_Ntk_t * pNtk)
+{
+    int i, j, k;    
+
+    /* We presume support is already sorted */
+    for (i = 0; i < nsupp; ++i) {
+        k = support[i];
+
+        /* Skip elements already seen */
+        if (marks[k]) continue;
+
+        /* Start an orbit */
+        marks[k] = 1;
+        fprintf(f, "%d", k-1);
+
+        /* Mark and notify elements in this orbit */
+        for (j = gamma[k]; j != k; j = gamma[j]) {
+            marks[j] = 1;
+            fprintf(f, " %d ", j-1);
+        }
+
+        /* Finish off the orbit */      
+    }
+    fprintf(f, "-1\n");
+
+    /* Clean up after ourselves */
+    for (i = 0; i < nsupp; ++i) {
+        marks[support[i]] = 0;
+    }
+
+    return 1;
+}
+
+static int
+print_automorphism_quiet(FILE *f, int n, const int *gamma, int nsupp, const int *support, char * marks, Abc_Ntk_t * pNtk)
+{   
+    return 1;
+}
+
+static int
+array_find_min(const int *a, int n)
+{
+    const int *start = a, *end = a + n, *min = a;
+    while (++a != end) {
+        if (*a < *min) min = a;
+    }
+    return min - start;
+}
+
+static void
+swap(int *a, int x, int y)
+{
+    int tmp = a[x];
+    a[x] = a[y];
+    a[y] = tmp;
+}
+
+static void
+sift_up(int *a, int k)
+{
+    int p;
+    do {
+        p = k / 2;
+        if (a[k] <= a[p]) {
+            return;
+        }
+        else {
+            swap(a, k, p);
+            k = p;
+        }
+    } while (k > 1);
+}
+
+static void
+sift_down(int *a, int n)
+{
+    int p = 1, k = 2;
+    while (k <= n) {
+        if (k < n && a[k] < a[k+1]) ++k;
+        if (a[p] < a[k]) {
+            swap(a, p, k);
+            p = k;
+            k = 2 * p;
+        }
+        else {
+            return;
+        }
+    }
+}
+
+static void
+heap_sort(int *a, int n)
+{
+    int i;
+    for (i = 1; i < n; ++i) {
+        sift_up(a-1, i+1);
+    }
+    --i;
+    while (i > 0) {
+        swap(a, 0, i);
+        sift_down(a-1, i--);
+    }
+}
+
+static void
+insertion_sort(int *a, int n)
+{
+    int i, j, k;
+    for (i = 1; i < n; ++i) {
+        k = a[i];
+        for (j = i; j > 0 && a[j-1] > k; --j) {
+            a[j] = a[j-1];
+        }
+        a[j] = k;
+    }
+}
+
+static int
+partition(int *a, int n, int m)
+{
+    int f = 0, b = n;
+    for (;;) {
+        while (a[f] <= m) ++f;
+        do  --b; while (m <= a[b]);
+        if (f < b) {
+            swap(a, f, b);
+            ++f;
+        }
+        else break;
+    }
+    return f;
+}
+
+static int
+log_base2(int n)
+{
+    int k = 0;
+    while (n > 1) {
+        ++k;
+        n >>= 1;
+    }
+    return k;
+}
+
+static int
+median(int a, int b, int c)
+{
+    if (a <= b) {
+        if (b <= c) return b;
+        if (a <= c) return c;
+        return a;
+    }
+    else {
+        if (a <= c) return a;
+        if (b <= c) return c;
+        return b;
+    }
+}
+
+static void
+introsort_loop(int *a, int n, int lim)
+{
+    int p;
+    while (n > 16) {
+        if (lim == 0) {
+            heap_sort(a, n);
+            return;
+        }
+        --lim;
+        p = partition(a, n, median(a[0], a[n/2], a[n-1]));
+        introsort_loop(a + p, n - p, lim);
+        n = p;
+    }
+}
+
+static void
+introsort(int *a, int n)
+{
+    introsort_loop(a, n, 2 * log_base2(n));
+    insertion_sort(a, n);
+}
+
+static int
+do_find_min(struct coloring *c, int t)
+{
+    return array_find_min(c->lab + t, c->clen[t] + 1) + t;
+}
+
+static int
+find_min(struct saucy *s, int t)
+{
+    return do_find_min(&s->right, t);
+}
+
+static void
+set_label(struct coloring *c, int index, int value)
+{
+    c->lab[index] = value;
+    c->unlab[value] = index;
+}
+
+static void
+swap_labels(struct coloring *c, int a, int b)
+{
+    int tmp = c->lab[a];
+    set_label(c, a, c->lab[b]);
+    set_label(c, b, tmp);
+}
+
+static void
+move_to_back(struct saucy *s, struct coloring *c, int k)
+{
+    int cf = c->cfront[k];
+    int cb = cf + c->clen[cf];
+    int offset = s->conncnts[cf]++;
+
+    /* Move this connected label to the back of its cell */
+    swap_labels(c, cb - offset, c->unlab[k]);
+
+    /* Add it to the cell list if it's the first one swapped */
+    if (!offset) s->clist[s->csize++] = cf;
+}
+
+static void
+data_mark(struct saucy *s, struct coloring *c, int k)
+{
+    int cf = c->cfront[k];
+
+    /* Move connects to the back of nonsingletons */
+    if (c->clen[cf]) move_to_back(s, c, k);
+}
+
+static void
+data_count(struct saucy *s, struct coloring *c, int k)
+{
+    int cf = c->cfront[k];
+
+    /* Move to back and count the number of connections */
+    if (c->clen[cf] && !s->ccount[k]++) move_to_back(s, c, k);
+}
+
+static int
+check_mapping(struct saucy *s, const int *adj, const int *edg, int k)
+{
+    int i, gk, ret = 1;
+
+    /* Mark gamma of neighbors */
+    for (i = adj[k]; i != adj[k+1]; ++i) {
+        s->stuff[s->gamma[edg[i]]] = 1;
+    }
+
+    /* Check neighbors of gamma */
+    gk = s->gamma[k];
+    for (i = adj[gk]; ret && i != adj[gk+1]; ++i) {
+        ret = s->stuff[edg[i]];
+    }
+
+    /* Clear out bit vector before we leave */
+    for (i = adj[k]; i != adj[k+1]; ++i) {
+        s->stuff[s->gamma[edg[i]]] = 0;
+    }
+
+    return ret;
+}
+
+static int
+add_conterexample(struct saucy *s, struct sim_result * cex)
+{
+    int i;
+    int nins = Abc_NtkPiNum(s->pNtk);
+    struct sim_result * savedcex;
+    
+    cex->inVecSignature = 0;
+    for (i = 0; i < nins; i++) {
+        if (cex->inVec[i]) {
+            cex->inVecSignature += (cex->inVec[i] * i * i);
+            cex->inVecSignature ^= 0xABCD;
+        }
+    }
+
+    for (i = 0; i < Vec_PtrSize(s->satCounterExamples); i++) {
+        savedcex = (struct sim_result *)Vec_PtrEntry(s->satCounterExamples, i);
+        if (savedcex->inVecSignature == cex->inVecSignature) {
+            //bumpActivity(s, savedcex);
+            return 0;
+        }
+    }
+    
+    Vec_PtrPush(s->satCounterExamples, cex);
+    bumpActivity(s, cex);
+    return 1;
+}
+
+static int
+is_undirected_automorphism(struct saucy *s)
+{
+    int i, j, ret;  
+
+    for (i = 0; i < s->ndiffs; ++i) {
+        j = s->unsupp[i];
+        if (!check_mapping(s, s->adj, s->edg, j)) return 0;
+    }
+
+    ret = Abc_NtkCecSat_saucy(s->pNtk, s->pNtk_permuted, s->pModel);
+    
+    if( BACKTRACK_BY_SAT && !ret ) {
+        struct sim_result * cex;
+
+        cex = analyzeConflict( s->pNtk, s->pModel, s->fPrintTree );
+        add_conterexample(s, cex);
+
+        cex = analyzeConflict( s->pNtk_permuted, s->pModel, s->fPrintTree );
+        add_conterexample(s, cex);      
+        
+        s->activityInc *= (1 / CLAUSE_DECAY);
+        if (Vec_PtrSize(s->satCounterExamples) >= MAX_LEARNTS)
+            reduceDB(s);
+    }
+
+    return ret;
+}
+
+static int
+is_directed_automorphism(struct saucy *s)
+{
+    int i, j;
+
+    for (i = 0; i < s->ndiffs; ++i) {
+        j = s->unsupp[i];
+        if (!check_mapping(s, s->adj, s->edg, j)) return 0;
+        if (!check_mapping(s, s->dadj, s->dedg, j)) return 0;
+    }
+    return 1;
+}
+
+static void
+add_induce(struct saucy *s, struct coloring *c, int who)
+{
+    if (!c->clen[who]) {
+        s->sinduce[s->nsinduce++] = who;
+    }
+    else {
+        s->ninduce[s->nninduce++] = who;
+    }
+    s->indmark[who] = 1;
+}
+
+static void
+fix_fronts(struct coloring *c, int cf, int ff)
+{
+    int i, end = cf + c->clen[cf];
+    for (i = ff; i <= end; ++i) {
+        c->cfront[c->lab[i]] = cf;
+    }
+}
+
+static void
+array_indirect_sort(int *a, const int *b, int n)
+{
+    int h, i, j, k;
+
+    /* Shell sort, as implemented in nauty, (C) Brendan McKay */
+    j = n / 3;
+    h = 1;
+    do { h = 3 * h + 1; } while (h < j);
+
+    do {
+        for (i = h; i < n; ++i) {
+            k = a[i];
+            for (j = i; b[a[j-h]] > b[k]; ) {
+                a[j] = a[j-h];
+                if ((j -= h) < h) break;
+            }
+            a[j] = k;
+        }
+        h /= 3;
+    } while (h > 0);
+}
+
+static int
+at_terminal(struct saucy *s)
+{
+    return s->nsplits == s->n;
+}
+
+static void
+add_diffnon(struct saucy *s, int k)
+{
+    /* Only add if we're in a consistent state */
+    if (s->ndiffnons == -1) return;
+
+    s->undiffnons[k] = s->ndiffnons;
+    s->diffnons[s->ndiffnons++] = k;
+}
+
+static void
+remove_diffnon(struct saucy *s, int k)
+{
+    int j;
+
+    if (s->undiffnons[k] == -1) return;
+
+    j = s->diffnons[--s->ndiffnons];
+    s->diffnons[s->undiffnons[k]] = j;
+    s->undiffnons[j] = s->undiffnons[k];
+
+    s->undiffnons[k] = -1;
+}
+
+static void
+add_diff(struct saucy *s, int k)
+{
+    if (!s->diffmark[k]) {
+        s->diffmark[k] = 1;
+        s->diffs[s->ndiffs++] = k;
+        add_diffnon(s, k);
+    }
+}
+
+static int
+is_a_pair(struct saucy *s, int k)
+{
+    return s->unpairs[k] != -1;
+}
+
+static int
+in_cell_range(struct coloring *c, int ff, int cf)
+{
+    int cb = cf + c->clen[cf];
+    return cf <= ff && ff <= cb;
+}
+
+static void
+add_pair(struct saucy *s, int k)
+{
+    if (s->npairs != -1) {
+        s->unpairs[k] = s->npairs;
+        s->pairs[s->npairs++] = k;
+    }
+}
+
+static void
+eat_pair(struct saucy *s, int k)
+{
+    int j;
+    j = s->pairs[--s->npairs];
+    s->pairs[s->unpairs[k]] = j;
+    s->unpairs[j] = s->unpairs[k];
+    s->unpairs[k] = -1;
+}
+
+static void
+pick_all_the_pairs(struct saucy *s)
+{
+    int i;
+    for (i = 0; i < s->npairs; ++i) {
+        s->unpairs[s->pairs[i]] = -1;
+    }
+    s->npairs = 0;
+}
+
+static void
+clear_undiffnons(struct saucy *s)
+{
+    int i;
+    for (i = 0 ; i < s->ndiffnons ; ++i) {
+        s->undiffnons[s->diffnons[i]] = -1;
+    }
+}
+
+static void
+fix_diff_singleton(struct saucy *s, int cf)
+{
+    int r = s->right.lab[cf];
+    int l = s->left.lab[cf];
+    int rcfl;
+
+    if (!s->right.clen[cf] && r != l) {
+
+        /* Make sure diff is marked */
+        add_diff(s, r);
+
+        /* It is now undiffed since it is singleton */
+        ++s->nundiffs;
+        remove_diffnon(s, r);
+
+        /* Mark the other if not singleton already */
+        rcfl = s->right.cfront[l];
+        if (s->right.clen[rcfl]) {
+            add_diff(s, l);
+
+            /* Check for pairs */
+            if (in_cell_range(&s->right, s->left.unlab[r], rcfl)) {
+                add_pair(s, l);
+            }
+        }
+        /* Otherwise we might be eating a pair */
+        else if (is_a_pair(s, r)) {
+            eat_pair(s, r);
+        }
+    }
+}
+
+static void
+fix_diff_subtract(struct saucy *s, int cf, const int *a, const int *b)
+{
+    int i, k;
+    int cb = cf + s->right.clen[cf];
+
+    /* Mark the contents of the first set */
+    for (i = cf; i <= cb; ++i) {
+        s->stuff[a[i]] = 1;
+    }
+
+    /* Add elements from second set not present in the first */
+    for (i = cf; i <= cb; ++i) {
+        k = b[i];
+        if (!s->stuff[k]) add_diff(s, k);
+    }
+
+    /* Clear the marks of the first set */
+    for (i = cf; i <= cb; ++i) {
+        s->stuff[a[i]] = 0;
+    }
+}
+
+static void
+fix_diffs(struct saucy *s, int cf, int ff)
+{
+    int min;
+
+    /* Check for singleton cases in both cells */
+    fix_diff_singleton(s, cf);
+    fix_diff_singleton(s, ff);
+
+    /* If they're both nonsingleton, do subtraction on smaller */
+    if (s->right.clen[cf] && s->right.clen[ff]) {
+        min = s->right.clen[cf] < s->right.clen[ff] ? cf : ff;
+        fix_diff_subtract(s, min, s->left.lab, s->right.lab);
+        fix_diff_subtract(s, min, s->right.lab, s->left.lab);
+    }
+}
+
+static void
+split_color(struct coloring *c, int cf, int ff)
+{
+    int cb, fb;
+
+    /* Fix lengths */
+    fb = ff - 1;
+    cb = cf + c->clen[cf];
+    c->clen[cf] = fb - cf;
+    c->clen[ff] = cb - ff;
+
+    /* Fix cell front pointers */
+    fix_fronts(c, ff, ff);
+}
+
+static void
+split_common(struct saucy *s, struct coloring *c, int cf, int ff)
+{
+    split_color(c, cf, ff);
+
+    /* Add to refinement */
+    if (s->indmark[cf] || c->clen[ff] < c->clen[cf]) {
+        add_induce(s, c, ff);
+    }
+    else {
+        add_induce(s, c, cf);
+    }
+}
+
+static int
+split_left(struct saucy *s, struct coloring *c, int cf, int ff)
+{
+    /* Record the split */
+    s->splitwho[s->nsplits] = ff;
+    s->splitfrom[s->nsplits] = cf;
+    ++s->nsplits;
+
+    /* Do common splitting tasks */
+    split_common(s, c, cf, ff);
+
+    /* Always succeeds */
+    return 1;
+}
+
+static int
+split_init(struct saucy *s, struct coloring *c, int cf, int ff)
+{
+    split_left(s, c, cf, ff);
+
+    /* Maintain nonsingleton list for finding new targets */
+    if (c->clen[ff]) {
+        s->prevnon[s->nextnon[cf]] = ff;
+        s->nextnon[ff] = s->nextnon[cf];
+        s->prevnon[ff] = cf;
+        s->nextnon[cf] = ff;
+    }
+    if (!c->clen[cf]) {
+        s->nextnon[s->prevnon[cf]] = s->nextnon[cf];
+        s->prevnon[s->nextnon[cf]] = s->prevnon[cf];
+    }
+
+    /* Always succeeds */
+    return 1;
+}
+
+static int
+split_other(struct saucy *s, struct coloring *c, int cf, int ff)
+{
+    int k = s->nsplits;
+
+    /* Verify the split with init */
+    if (s->splitwho[k] != ff || s->splitfrom[k] != cf
+            || k >= s->splitlev[s->lev]) {
+        return 0;
+    }
+    ++s->nsplits;
+
+    /* Do common splitting tasks */
+    split_common(s, c, cf, ff);
+
+    /* Fix differences with init */
+    fix_diffs(s, cf, ff);
+
+    /* If we got this far we succeeded */
+    return 1;
+}
+
+static int
+print_partition(struct coloring *left, struct coloring *right, int n, Abc_Ntk_t * pNtk, int fNames)
+{
+        int i, j;        
+
+        printf("top = |");
+        for(i = 0; i < n; i += (left->clen[i]+1)) {
+            for(j = 0; j < (left->clen[i]+1); j++) {
+                if (fNames) printf("%s ", getVertexName(pNtk, left->lab[i+j]));
+                else        printf("%d ", left->lab[i+j]);
+            }
+            if((i+left->clen[i]+1) < n) printf("|");
+        }
+        printf("|\n");
+
+        /*printf("(cfront = {");
+        for (i = 0; i < n; i++)
+            printf("%d ", left->cfront[i]);
+        printf("})\n");*/
+
+        if (right == NULL) return 1;
+
+        printf("bot = |");
+        for(i = 0; i < n; i += (right->clen[i]+1)) {
+            for(j = 0; j < (right->clen[i]+1); j++) {
+                if (fNames) printf("%s ", getVertexName(pNtk, right->lab[i+j]));
+                else        printf("%d ", right->lab[i+j]);
+            }
+            if((i+right->clen[i]+1) < n) printf("|");
+        }
+        printf("|\n");
+
+        /*printf("(cfront = {");
+        for (i = 0; i < n; i++)
+            printf("%d ", right->cfront[i]);
+        printf("})\n");*/
+
+        return 1;
+}
+
+static int
+refine_cell(struct saucy *s, struct coloring *c,
+    int (*refine)(struct saucy *, struct coloring *, int))
+{
+    int i, cf, ret = 1;
+
+    /*
+     * The connected list must be consistent.  This is for
+     * detecting mappings across nodes at a given level.  However,
+     * at the root of the tree, we never have to map with another
+     * node, so we lack this consistency constraint in that case.
+     */
+    if (s->lev > 1) introsort(s->clist, s->csize);
+
+    /* Now iterate over the marked cells */
+    for (i = 0; ret && i < s->csize; ++i) {
+        cf = s->clist[i];
+        ret = refine(s, c, cf);
+    }
+
+    /* Clear the connected marks */
+    for (i = 0; i < s->csize; ++i) {
+        cf = s->clist[i];
+        s->conncnts[cf] = 0;
+    }
+    s->csize = 0;
+    return ret;
+}
+
+static int
+maybe_split(struct saucy *s, struct coloring *c, int cf, int ff)
+{
+    return cf == ff ? 1 : s->split(s, c, cf, ff);
+}
+
+static int
+ref_single_cell(struct saucy *s, struct coloring *c, int cf)
+{
+    int zcnt = c->clen[cf] + 1 - s->conncnts[cf];
+    return maybe_split(s, c, cf, cf + zcnt);
+}
+
+static int
+ref_singleton(struct saucy *s, struct coloring *c,
+    const int *adj, const int *edg, int cf)
+{
+    int i, k = c->lab[cf];
+
+    /* Find the cells we're connected to, and mark our neighbors */
+    for (i = adj[k]; i != adj[k+1]; ++i) {
+        data_mark(s, c, edg[i]);
+    }
+
+    /* Refine the cells we're connected to */
+    return refine_cell(s, c, ref_single_cell);
+}
+
+static int
+ref_singleton_directed(struct saucy *s, struct coloring *c, int cf)
+{
+    return ref_singleton(s, c, s->adj, s->edg, cf)
+        && ref_singleton(s, c, s->dadj, s->dedg, cf);
+}
+
+static int
+ref_singleton_undirected(struct saucy *s, struct coloring *c, int cf)
+{
+    return ref_singleton(s, c, s->adj, s->edg, cf);
+}
+
+static int
+ref_nonsingle_cell(struct saucy *s, struct coloring *c, int cf)
+{
+    int cnt, i, cb, nzf, ff, fb, bmin, bmax;
+
+    /* Find the front and back */
+    cb = cf + c->clen[cf];
+    nzf = cb - s->conncnts[cf] + 1;
+
+    /* Prepare the buckets */
+    ff = nzf;
+    cnt = s->ccount[c->lab[ff]];
+    s->count[ff] = bmin = bmax = cnt;
+    s->bucket[cnt] = 1;
+
+    /* Iterate through the rest of the vertices */
+    while (++ff <= cb) {
+        cnt = s->ccount[c->lab[ff]];
+
+        /* Initialize intermediate buckets */
+        while (bmin > cnt) s->bucket[--bmin] = 0;
+        while (bmax < cnt) s->bucket[++bmax] = 0;
+
+        /* Mark this count */
+        ++s->bucket[cnt];
+        s->count[ff] = cnt;
+    }
+
+    /* If they all had the same count, bail */
+    if (bmin == bmax && cf == nzf) return 1;
+    ff = fb = nzf;
+
+    /* Calculate bucket locations, sizes */
+    for (i = bmin; i <= bmax; ++i, ff = fb) {
+        if (!s->bucket[i]) continue;
+        fb = ff + s->bucket[i];
+        s->bucket[i] = fb;
+    }
+
+    /* Repair the partition nest */
+    for (i = nzf; i <= cb; ++i) {
+        s->junk[--s->bucket[s->count[i]]] = c->lab[i];
+    }
+    for (i = nzf; i <= cb; ++i) {
+        set_label(c, i, s->junk[i]);
+    }
+
+    /* Split; induce */
+    for (i = bmax; i > bmin; --i) {
+        ff = s->bucket[i];
+        if (ff && !s->split(s, c, cf, ff)) return 0;
+    }
+
+    /* If there was a zero area, then there's one more cell */
+    return maybe_split(s, c, cf, s->bucket[bmin]);
+}
+
+static int
+ref_nonsingle(struct saucy *s, struct coloring *c,
+    const int *adj, const int *edg, int cf)
+{
+    int i, j, k, ret;
+    const int cb = cf + c->clen[cf];
+    const int size = cb - cf + 1;
+
+    /* Double check for nonsingles which became singles later */
+    if (cf == cb) {
+        return ref_singleton(s, c, adj, edg, cf);
+    }
+
+    /* Establish connected list */
+    memcpy(s->junk, c->lab + cf, size * sizeof(int));
+    for (i = 0; i < size; ++i) {
+        k = s->junk[i];
+        for (j = adj[k]; j != adj[k+1]; ++j) {
+            data_count(s, c, edg[j]);
+        }
+    }
+
+    /* Refine the cells we're connected to */
+    ret = refine_cell(s, c, ref_nonsingle_cell);
+
+    /* Clear the counts; use lab because junk was overwritten */
+    for (i = cf; i <= cb; ++i) {
+        k = c->lab[i];
+        for (j = adj[k]; j != adj[k+1]; ++j) {
+            s->ccount[edg[j]] = 0;
+        }
+    }
+
+    return ret;
+}
+
+static int
+ref_nonsingle_directed(struct saucy *s, struct coloring *c, int cf)
+{
+    return ref_nonsingle(s, c, s->adj, s->edg, cf)
+        && ref_nonsingle(s, c, s->dadj, s->dedg, cf);
+}
+
+static int
+ref_nonsingle_undirected(struct saucy *s, struct coloring *c, int cf)
+{
+    return ref_nonsingle(s, c, s->adj, s->edg, cf);
+}
+
+static void
+clear_refine(struct saucy *s)
+{
+    int i;
+    for (i = 0; i < s->nninduce; ++i) {
+        s->indmark[s->ninduce[i]] = 0;
+    }
+    for (i = 0; i < s->nsinduce; ++i) {
+        s->indmark[s->sinduce[i]] = 0;
+    }
+    s->nninduce = s->nsinduce = 0;
+}
+
+static int
+refine(struct saucy *s, struct coloring *c)
+{
+    int front;
+
+    /* Keep going until refinement stops */
+    while (1) {
+
+        /* If discrete, bail */
+        if (at_terminal(s)) {
+            clear_refine(s);
+            return 1;
+        };
+
+        /* Look for something else to refine on */
+        if (s->nsinduce) {
+            front = s->sinduce[--s->nsinduce];
+            s->indmark[front] = 0;
+            if (!s->ref_singleton(s, c, front)) break;
+        }
+        else if (s->nninduce) {
+            front = s->ninduce[--s->nninduce];
+            s->indmark[front] = 0;
+            if (!s->ref_nonsingle(s, c, front)) break;
+        }
+        else {
+            return 1;
+        };
+    }
+
+    clear_refine(s);
+    return 0;
+}
+
+static int
+refineByDepGraph(struct saucy *s, struct coloring *c) 
+{
+    s->adj = s->depAdj;
+    s->edg = s->depEdg; 
+
+    return refine(s, c);
+}
+
+static int
+backtrackBysatCounterExamples(struct saucy *s, struct coloring *c)
+{
+    int i, j, res;  
+    struct sim_result * cex1, * cex2;
+    int * flag = zeros(Vec_PtrSize(s->satCounterExamples));
+
+    if (c == &s->left) return 1;
+    if (Vec_PtrSize(s->satCounterExamples) == 0) return 1;      
+
+    for (i = 0; i < Vec_PtrSize(s->satCounterExamples); i++) {  
+        cex1 = (struct sim_result *)Vec_PtrEntry(s->satCounterExamples, i);      
+
+        for (j = 0; j < Vec_PtrSize(s->satCounterExamples); j++) {
+            if (flag[j]) continue;
+        
+            cex2 = (struct sim_result *)Vec_PtrEntry(s->satCounterExamples, j);
+            res = ifInputVectorsAreConsistent(s, cex1->inVec, cex2->inVec);
+
+            if (res == -2) {
+                flag[j] = 1;
+                continue;
+            }
+            if (res == -1) break;
+            if (res == 0) continue;
+
+            if (cex1->outVecOnes != cex2->outVecOnes) {
+                bumpActivity(s, cex1);
+                bumpActivity(s, cex2);
+                ABC_FREE(flag);
+                return 0;
+            }
+
+            /* if two input vectors produce the same number of ones (look above), and
+             * pNtk's number of outputs is 1, then output vectors are definitely consistent. */
+            if (Abc_NtkPoNum(s->pNtk) == 1) continue;
+
+            if (!ifOutputVectorsAreConsistent(s, cex1->outVec, cex2->outVec)) {
+                bumpActivity(s, cex1);
+                bumpActivity(s, cex2);
+                ABC_FREE(flag);
+                return 0;
+            }
+        }
+    }
+
+    ABC_FREE(flag);
+    return 1;
+}
+
+static int
+refineBySim1_init(struct saucy *s, struct coloring *c) 
+{
+    struct saucy_graph *g;
+    Vec_Int_t * randVec;
+    int i, j;
+    int allOutputsAreDistinguished;
+    int nsplits;
+
+    if (Abc_NtkPoNum(s->pNtk) == 1) return 1;
+    
+    for (i = 0; i < NUM_SIM1_ITERATION; i++) {
+
+        /* if all outputs are distinguished, quit */
+        allOutputsAreDistinguished = 1;
+        for (j = 0; j < Abc_NtkPoNum(s->pNtk); j++) {
+            if (c->clen[j]) {
+                allOutputsAreDistinguished = 0;
+                break;
+            }
+        }
+        if (allOutputsAreDistinguished) break;
+
+        randVec = assignRandomBitsToCells(s->pNtk, c);      
+        g = buildSim1Graph(s->pNtk, c, randVec, s->iDep, s->oDep);
+        assert(g != NULL);
+
+        s->adj = g->adj;
+        s->edg = g->edg;
+
+        nsplits = s->nsplits;
+
+        for (j = 0; j < s->n; j += c->clen[j]+1)            
+                add_induce(s, c, j);
+        refine(s, c);
+
+        if (s->nsplits > nsplits) {         
+            i = 0; /* reset i */
+            /* do more refinement by dependency graph */
+            for (j = 0; j < s->n; j += c->clen[j]+1)                
+                    add_induce(s, c, j);
+            refineByDepGraph(s, c);
+        }
+        
+        Vec_IntFree(randVec);
+        ABC_FREE( g->adj );
+        ABC_FREE( g->edg );
+        ABC_FREE( g );
+    }   
+
+    return 1;
+}
+
+
+static int
+refineBySim1_left(struct saucy *s, struct coloring *c) 
+{
+    struct saucy_graph *g;
+    Vec_Int_t * randVec;
+    int i, j;
+    int allOutputsAreDistinguished;
+    int nsplits;
+
+    if (Abc_NtkPoNum(s->pNtk) == 1) return 1;
+    
+    for (i = 0; i < NUM_SIM1_ITERATION; i++) {
+
+        /* if all outputs are distinguished, quit */
+        allOutputsAreDistinguished = 1;
+        for (j = 0; j < Abc_NtkPoNum(s->pNtk); j++) {
+            if (c->clen[j]) {
+                allOutputsAreDistinguished = 0;
+                break;
+            }
+        }
+        if (allOutputsAreDistinguished) break;
+
+        randVec = assignRandomBitsToCells(s->pNtk, c);      
+        g = buildSim1Graph(s->pNtk, c, randVec, s->iDep, s->oDep);
+        assert(g != NULL);
+
+        s->adj = g->adj;
+        s->edg = g->edg;
+
+        nsplits = s->nsplits;
+
+        for (j = 0; j < s->n; j += c->clen[j]+1)            
+                add_induce(s, c, j);
+        refine(s, c);
+
+        if (s->nsplits > nsplits) {
+            /* save the random vector */
+            Vec_PtrPush(s->randomVectorArray_sim1, randVec);            
+            i = 0;  /* reset i */
+            /* do more refinement by dependency graph */
+            for (j = 0; j < s->n; j += c->clen[j]+1)                
+                    add_induce(s, c, j);
+            refineByDepGraph(s, c);
+        }
+        else
+            Vec_IntFree(randVec);
+
+        ABC_FREE( g->adj );
+        ABC_FREE( g->edg );
+        ABC_FREE( g );
+    }
+
+    s->randomVectorSplit_sim1[s->lev] = Vec_PtrSize(s->randomVectorArray_sim1); 
+
+    return 1;
+}
+
+static int
+refineBySim1_other(struct saucy *s, struct coloring *c) 
+{
+    struct saucy_graph *g;
+    Vec_Int_t * randVec;
+    int i, j;
+    int ret, nsplits;
+
+    for (i = s->randomVectorSplit_sim1[s->lev-1]; i < s->randomVectorSplit_sim1[s->lev]; i++) {
+        randVec = (Vec_Int_t *)Vec_PtrEntry(s->randomVectorArray_sim1, i);
+        g = buildSim1Graph(s->pNtk, c, randVec, s->iDep, s->oDep);
+
+        if (g == NULL) {
+            assert(c == &s->right);
+            return 0;
+        }
+
+        s->adj = g->adj;
+        s->edg = g->edg;
+
+        nsplits = s->nsplits;
+
+        for (j = 0; j < s->n; j += c->clen[j]+1)            
+                add_induce(s, c, j);
+        ret = refine(s, c);
+
+        if (s->nsplits == nsplits) {
+            assert(c == &s->right);
+            ret = 0;
+        }
+
+        if (ret) {      
+            /* do more refinement now by dependency graph */
+            for (j = 0; j < s->n; j += c->clen[j]+1)                
+                    add_induce(s, c, j);
+            ret = refineByDepGraph(s, c);
+        }
+        
+        ABC_FREE( g->adj );
+        ABC_FREE( g->edg );
+        ABC_FREE( g );
+
+        if (!ret) return 0;
+    }   
+
+    return 1;
+}
+
+static int
+refineBySim2_init(struct saucy *s, struct coloring *c) 
+{
+    struct saucy_graph *g;
+    Vec_Int_t * randVec;    
+    int i, j;
+    int nsplits;    
+    
+    for (i = 0; i < NUM_SIM2_ITERATION; i++) {
+        randVec = assignRandomBitsToCells(s->pNtk, c);      
+        g = buildSim2Graph(s->pNtk, c, randVec, s->iDep, s->oDep, s->topOrder, s->obs,  s->ctrl);
+        assert(g != NULL);
+
+        s->adj = g->adj;
+        s->edg = g->edg;
+
+        nsplits = s->nsplits;
+        
+        for (j = 0; j < s->n; j += c->clen[j]+1)            
+                add_induce(s, c, j);
+        refine(s, c);
+
+        if (s->nsplits > nsplits) {                     
+            i = 0; /* reset i */
+            /* do more refinement by dependency graph */
+            for (j = 0; j < s->n; j += c->clen[j]+1)                
+                    add_induce(s, c, j);
+            refineByDepGraph(s, c);
+        }
+        
+        Vec_IntFree(randVec);
+        
+        ABC_FREE( g->adj );
+        ABC_FREE( g->edg );
+        ABC_FREE( g );
+    }
+
+    return 1;
+}
+
+static int
+refineBySim2_left(struct saucy *s, struct coloring *c) 
+{
+    struct saucy_graph *g;
+    Vec_Int_t * randVec;    
+    int i, j;
+    int nsplits;    
+    
+    for (i = 0; i < NUM_SIM2_ITERATION; i++) {
+        randVec = assignRandomBitsToCells(s->pNtk, c);      
+        g = buildSim2Graph(s->pNtk, c, randVec, s->iDep, s->oDep, s->topOrder, s->obs,  s->ctrl);
+        assert(g != NULL);
+
+        s->adj = g->adj;
+        s->edg = g->edg;
+
+        nsplits = s->nsplits;
+        
+        for (j = 0; j < s->n; j += c->clen[j]+1)            
+                add_induce(s, c, j);
+        refine(s, c);
+
+        if (s->nsplits > nsplits) {
+            /* save the random vector */
+            Vec_PtrPush(s->randomVectorArray_sim2, randVec);            
+            i = 0; /* reset i */
+            /* do more refinement by dependency graph */
+            for (j = 0; j < s->n; j += c->clen[j]+1)                
+                    add_induce(s, c, j);
+            refineByDepGraph(s, c);
+        }
+        else
+            Vec_IntFree(randVec);
+        
+        ABC_FREE( g->adj );
+        ABC_FREE( g->edg );
+        ABC_FREE( g );
+    }
+
+    s->randomVectorSplit_sim2[s->lev] = Vec_PtrSize(s->randomVectorArray_sim2); 
+
+    return 1;
+}
+
+static int
+refineBySim2_other(struct saucy *s, struct coloring *c) 
+{
+    struct saucy_graph *g;
+    Vec_Int_t * randVec;
+    int i, j;
+    int ret, nsplits;
+
+    for (i = s->randomVectorSplit_sim2[s->lev-1]; i < s->randomVectorSplit_sim2[s->lev]; i++) {
+        randVec = (Vec_Int_t *)Vec_PtrEntry(s->randomVectorArray_sim2, i);       
+        g = buildSim2Graph(s->pNtk, c, randVec, s->iDep, s->oDep, s->topOrder, s->obs,  s->ctrl);
+
+        if (g == NULL) {
+            assert(c == &s->right);
+            return 0;
+        }
+        
+        s->adj = g->adj;
+        s->edg = g->edg;    
+
+        nsplits = s->nsplits;       
+
+        for (j = 0; j < s->n; j += c->clen[j]+1)            
+                add_induce(s, c, j);
+        ret = refine(s, c);
+
+        if (s->nsplits == nsplits) {
+            assert(c == &s->right);
+            ret = 0;
+        }
+
+        if (ret) {
+            /* do more refinement by dependency graph */
+            for (j = 0; j < s->n; j += c->clen[j]+1)                
+                    add_induce(s, c, j);
+            ret = refineByDepGraph(s, c);
+        }
+
+        ABC_FREE( g->adj );
+        ABC_FREE( g->edg );
+        ABC_FREE( g );
+
+        if (!ret) {
+            assert(c == &s->right);
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+static int
+check_OPP_only_has_swaps(struct saucy *s, struct coloring *c)
+{
+    int j, cell;
+    Vec_Int_t * left_cfront, * right_cfront;
+
+    if (c == &s->left)
+        return 1;
+
+    left_cfront = Vec_IntAlloc (1);
+    right_cfront = Vec_IntAlloc (1);
+
+    for (cell = 0; cell < s->n; cell += (s->left.clen[cell]+1)) {               
+        for (j = cell; j <= (cell+s->left.clen[cell]); j++) {
+            Vec_IntPush(left_cfront, s->left.cfront[s->right.lab[j]]);
+            Vec_IntPush(right_cfront, s->right.cfront[s->left.lab[j]]);             
+        }
+        Vec_IntSortUnsigned(left_cfront);
+        Vec_IntSortUnsigned(right_cfront);
+        for (j = 0; j < Vec_IntSize(left_cfront); j++) {
+            if (Vec_IntEntry(left_cfront, j) != Vec_IntEntry(right_cfront, j)) {
+                Vec_IntFree(left_cfront);
+                Vec_IntFree(right_cfront);
+                return 0;
+            }
+        }
+        Vec_IntClear(left_cfront);
+        Vec_IntClear(right_cfront);
+    }
+
+    Vec_IntFree(left_cfront);
+    Vec_IntFree(right_cfront);
+
+    return 1;
+}
+
+static int
+check_OPP_for_Boolean_matching(struct saucy *s, struct coloring *c)
+{
+    int j, cell;
+    int countN1Left, countN2Left;
+    int countN1Right, countN2Right;
+    char *name; 
+
+    if (c == &s->left)
+        return 1;       
+
+    for (cell = 0; cell < s->n; cell += (s->right.clen[cell]+1)) {  
+        countN1Left = countN2Left = countN1Right = countN2Right = 0;
+
+        for (j = cell; j <= (cell+s->right.clen[cell]); j++) {
+
+            name = getVertexName(s->pNtk, s->left.lab[j]);
+            assert(name[0] == 'N' && name[2] == ':');
+            if (name[1] == '1')
+                countN1Left++;
+            else {
+                assert(name[1] == '2');
+                countN2Left++;
+            }
+
+            name = getVertexName(s->pNtk, s->right.lab[j]);
+            assert(name[0] == 'N' && name[2] == ':');
+            if (name[1] == '1') 
+                countN1Right++;
+            else {
+                assert(name[1] == '2');
+                countN2Right++;
+            }
+
+        }
+
+        if (countN1Left != countN2Right || countN2Left != countN1Right)
+            return 0;
+    }   
+    
+    return 1;
+}
+
+static int
+double_check_OPP_isomorphism(struct saucy *s, struct coloring * c)
+{
+    /* This is the new enhancement in saucy 3.0 */
+    int i, j, v, sum1, sum2, xor1, xor2;
+
+    if (c == &s->left)
+        return 1;
+    
+    for (i = s->nsplits - 1; i > s->splitlev[s->lev-1]; --i) {
+        v = c->lab[s->splitwho[i]];
+        sum1 = xor1 = 0;
+        for (j = s->adj[v]; j < s->adj[v+1]; j++) {
+            sum1 += c->cfront[s->edg[j]];
+            xor1 ^= c->cfront[s->edg[j]];
+        }
+        v = s->left.lab[s->splitwho[i]];
+        sum2 = xor2 = 0;
+        for (j = s->adj[v]; j < s->adj[v+1]; j++) {
+            sum2 += s->left.cfront[s->edg[j]];
+            xor2 ^= s->left.cfront[s->edg[j]];
+        }
+        if ((sum1 != sum2) || (xor1 != xor2))
+            return 0;
+        v = c->lab[s->splitfrom[i]];
+        sum1 = xor1 = 0;
+        for (j = s->adj[v]; j < s->adj[v+1]; j++) {
+            sum1 += c->cfront[s->edg[j]];
+            xor1 ^= c->cfront[s->edg[j]];
+        }
+        v = s->left.lab[s->splitfrom[i]];
+        sum2 = xor2 = 0;
+        for (j = s->adj[v]; j < s->adj[v+1]; j++) {
+            sum2 += s->left.cfront[s->edg[j]];
+            xor2 ^= s->left.cfront[s->edg[j]];
+        }
+        if ((sum1 != sum2) || (xor1 != xor2))
+            return 0;
+    }   
+
+    return 1;
+}
+
+static int
+descend(struct saucy *s, struct coloring *c, int target, int min)
+{
+    int back = target + c->clen[target];
+
+    /* Count this node */
+    ++s->stats->nodes;
+
+    /* Move the minimum label to the back */
+    swap_labels(c, min, back);
+
+    /* Split the cell */
+    s->difflev[s->lev] = s->ndiffs;
+    s->undifflev[s->lev] = s->nundiffs;
+    ++s->lev;
+    s->split(s, c, target, back);   
+
+    /* Now go and do some work */
+    //print_partition(&s->left, NULL, s->n, s->pNtk, 1);    
+    if (!refineByDepGraph(s, c)) return 0;
+
+    /* if we are looking for a Boolean matching, check the OPP and 
+     * backtrack if the OPP maps part of one network to itself */
+    if (s->fBooleanMatching && !check_OPP_for_Boolean_matching(s, c)) return 0;
+
+    //print_partition(&s->left, NULL, s->n, s->pNtk, 1);
+    if (REFINE_BY_SIM_1 && !s->refineBySim1(s, c)) return 0;
+
+    //print_partition(&s->left, NULL, s->n, s->pNtk, 1);
+    if (REFINE_BY_SIM_2 && !s->refineBySim2(s, c)) return 0;
+
+    /* do the check once more, maybe the check fails, now that refinement is complete */
+    if (s->fBooleanMatching && !check_OPP_for_Boolean_matching(s, c)) return 0;
+
+    if (s->fLookForSwaps && !check_OPP_only_has_swaps(s, c)) return 0;
+
+    if (!double_check_OPP_isomorphism(s, c)) return 0;
+    
+    return 1;
+}
+
+static int
+select_smallest_max_connected_cell(struct saucy *s, int start, int end)
+{
+    int smallest_cell = -1, cell;
+    int smallest_cell_size = s->n;
+    int max_connections = -1;
+    int * connection_list = zeros(s->n);
+    
+    cell = start;
+    while( !s->left.clen[cell] ) cell++;
+    while( cell < end ) {       
+        if (s->left.clen[cell] <= smallest_cell_size) {
+            int i, connections = 0;;
+            for (i = s->depAdj[s->left.lab[cell]]; i < s->depAdj[s->left.lab[cell]+1]; i++) {
+                if (!connection_list[s->depEdg[i]]) {
+                    connections++;
+                    connection_list[s->depEdg[i]] = 1;
+                }
+            }
+            if ((s->left.clen[cell] < smallest_cell_size) || (connections > max_connections)) {
+                smallest_cell_size = s->left.clen[cell];
+                max_connections = connections;
+                smallest_cell = cell;
+            }
+            for (i = s->depAdj[s->left.lab[cell]]; i < s->depAdj[s->left.lab[cell]+1]; i++)
+                connection_list[s->depEdg[i]] = 0;
+        }
+        cell = s->nextnon[cell];
+    }
+    
+    ABC_FREE( connection_list );
+    return smallest_cell;
+}
+
+static int
+descend_leftmost(struct saucy *s)
+{
+    int target, min;
+
+    /* Keep going until we're discrete */
+    //print_partition(&s->left, NULL, s->n, s->pNtk, 1);
+    while (!at_terminal(s)) {
+        //target = min = s->nextnon[-1];
+        if (s->nextnon[-1] < Abc_NtkPoNum(s->pNtk))
+            target = min = select_smallest_max_connected_cell(s, s->nextnon[-1], Abc_NtkPoNum(s->pNtk));            
+        else
+            target = min = select_smallest_max_connected_cell(s, Abc_NtkPoNum(s->pNtk), s->n);
+        if (s->fPrintTree) 
+            printf("%s->%s\n", getVertexName(s->pNtk, s->left.lab[min]), getVertexName(s->pNtk, s->left.lab[min]));     
+        s->splitvar[s->lev] = s->left.lab[min];
+        s->start[s->lev] = target;
+        s->splitlev[s->lev] = s->nsplits;
+        if (!descend(s, &s->left, target, min)) return 0;       
+    }
+    s->splitlev[s->lev] = s->n;
+    return 1;
+}
+
+/*
+ * If the remaining nonsingletons in this partition match exactly
+ * those nonsingletons from the leftmost branch of the search tree,
+ * then there is no point in continuing descent.
+ */
+
+static int
+zeta_fixed(struct saucy *s)
+{
+    return s->ndiffs == s->nundiffs;
+}
+
+static void
+select_dynamically(struct saucy *s, int *target, int *lmin, int *rmin)
+{
+    /* Both clens are equal; this clarifies the code a bit */
+    const int *clen = s->left.clen;
+    int i, k;
+    //int cf;
+
+    /*
+     * If there's a pair, use it.  pairs[0] should always work,
+     * but we use a checked loop instead because I'm not 100% sure
+     * I'm "unpairing" at every point I should be.
+     */
+    for (i = 0; i < s->npairs; ++i) {
+        k = s->pairs[i];
+        *target = s->right.cfront[k];
+        *lmin = s->left.unlab[s->right.lab[s->left.unlab[k]]];
+        *rmin = s->right.unlab[k];
+
+        if (clen[*target]
+                && in_cell_range(&s->left, *lmin, *target)
+                && in_cell_range(&s->right, *rmin, *target))
+            return;
+    }
+
+    /* Diffnons is only consistent when there are no baddies */
+    /*if (s->ndiffnons != -1) {
+        *target = *lmin = *rmin = s->right.cfront[s->diffnons[0]];
+        return;
+    }*/
+
+    /* Pick any old target cell and element */
+    /*for (i = 0; i < s->ndiffs; ++i) {
+        cf = s->right.cfront[s->diffs[i]];
+        if (clen[cf]) {
+            *lmin = *rmin = *target = cf;
+            return;
+        }
+    }*/
+
+    for (i = 0; i < s->n; i += (clen[i]+1)) {
+        if (!clen[i]) continue;
+        *rmin = *lmin = *target = i;
+        if (s->right.cfront[s->left.lab[*lmin]] == *target)
+            *rmin = s->right.unlab[s->left.lab[*lmin]];
+        return;
+    }   
+    
+    /* we should never get here */
+    abort();
+}
+
+static void
+select_statically(struct saucy *s, int *target, int *lmin, int *rmin)
+{
+    int i;
+
+    *target = *rmin = s->left.cfront[s->splitvar[s->lev]];
+    *lmin = s->left.unlab[s->splitvar[s->lev]];
+    /* try to map identically! */
+    for (i = *rmin; i <= (*rmin + s->right.clen[*target]); i++)
+        if (s->right.lab[*rmin] == s->left.lab[*lmin]) {
+            *rmin = i;
+            break;
+        }
+}
+
+static int
+descend_left(struct saucy *s)
+{
+    int target, lmin, rmin;
+
+    /* Check that we ended at the right spot */
+    if (s->nsplits != s->splitlev[s->lev]) return 0;
+
+    /* Keep going until we're discrete */
+    while (!at_terminal(s) /*&& !zeta_fixed(s)*/) {
+
+        /* We can pick any old target cell and element */
+        s->select_decomposition(s, &target, &lmin, &rmin);
+
+        if (s->fPrintTree) {
+            //printf("in level %d: %d->%d\n", s->lev, s->left.lab[lmin], s->right.lab[rmin]);
+            printf("in level %d: %s->%s\n", s->lev, getVertexName(s->pNtk, s->left.lab[lmin]), getVertexName(s->pNtk, s->right.lab[rmin]));
+        }
+
+        /* Check if we need to refine on the left */
+        s->match = 0;
+        s->start[s->lev] = target;
+        s->split = split_left;
+        if (SELECT_DYNAMICALLY) {
+            s->refineBySim1 = refineBySim1_left;
+            s->refineBySim2 = refineBySim2_left;
+        }
+        descend(s, &s->left, target, lmin);
+        s->splitlev[s->lev] = s->nsplits;
+        s->split = split_other;     
+        if (SELECT_DYNAMICALLY) {
+            s->refineBySim1 = refineBySim1_other;
+            s->refineBySim2 = refineBySim2_other;
+        }
+        --s->lev;
+        s->nsplits = s->splitlev[s->lev];
+
+        /* Now refine on the right and ensure matching */
+        s->specmin[s->lev] = s->right.lab[rmin];
+        if (!descend(s, &s->right, target, rmin)) return 0;
+        if (s->nsplits != s->splitlev[s->lev]) return 0;
+    }
+    return 1;
+}
+
+static int
+find_representative(int k, int *theta)
+{
+    int rep, tmp;
+
+    /* Find the minimum cell representative */
+    for (rep = k; rep != theta[rep]; rep = theta[rep]);
+
+    /* Update all intermediaries */
+    while (theta[k] != rep) {
+        tmp = theta[k]; theta[k] = rep; k = tmp;
+    }
+    return rep;
+}
+
+static void
+update_theta(struct saucy *s)
+{
+    int i, k, x, y, tmp;
+
+    for (i = 0; i < s->ndiffs; ++i) {
+        k = s->unsupp[i];
+        x = find_representative(k, s->theta);
+        y = find_representative(s->gamma[k], s->theta);
+
+        if (x != y) {
+            if (x > y) {
+                tmp = x;
+                x = y;
+                y = tmp;
+            }
+            s->theta[y] = x;
+            s->thsize[x] += s->thsize[y];
+
+            s->thnext[s->thprev[y]] = s->thnext[y];
+            s->thprev[s->thnext[y]] = s->thprev[y];
+            s->threp[s->thfront[y]] = s->thnext[y];
+        }
+    }
+}
+
+static int
+theta_prune(struct saucy *s)
+{
+    int start = s->start[s->lev];
+    int label, rep, irep;
+
+    irep = find_representative(s->indmin, s->theta);
+    while (s->kanctar) {
+        label = s->anctar[--s->kanctar];
+        rep = find_representative(label, s->theta);
+        if (rep == label && rep != irep) {
+            return s->right.unlab[label] - start;
+        }
+    }
+    return -1;
+}
+
+static int
+orbit_prune(struct saucy *s)
+{
+    int i, label, fixed, min = -1;
+    int k = s->start[s->lev];
+    int size = s->right.clen[k] + 1;
+    int *cell = s->right.lab + k;
+
+    /* The previously fixed value */
+    fixed = cell[size-1];
+
+    /* Look for the next minimum cell representative */
+    for (i = 0; i < size-1; ++i) {
+        label = cell[i];
+
+        /* Skip things we've already considered */
+        if (label <= fixed) continue;
+
+        /* Skip things that we'll consider later */
+        if (min != -1 && label > cell[min]) continue;
+
+        /* New candidate minimum */
+        min = i;
+    }
+
+    return min;
+}
+
+static void
+note_anctar_reps(struct saucy *s)
+{
+    int i, j, k, m, f, rep, tmp;
+
+    /*
+     * Undo the previous level's splits along leftmost so that we
+     * join the appropriate lists of theta reps.
+     */
+    for (i = s->splitlev[s->anc+1]-1; i >= s->splitlev[s->anc]; --i) {
+        f = s->splitfrom[i];
+        j = s->threp[f];
+        k = s->threp[s->splitwho[i]];
+
+        s->thnext[s->thprev[j]] = k;
+        s->thnext[s->thprev[k]] = j;
+
+        tmp = s->thprev[j];
+        s->thprev[j] = s->thprev[k];
+        s->thprev[k] = tmp;
+
+        for (m = k; m != j; m = s->thnext[m]) {
+            s->thfront[m] = f;
+        }
+    }
+
+    /*
+     * Just copy over the target's reps and sort by cell size, in
+     * the hopes of trimming some otherwise redundant generators.
+     */
+    s->kanctar = 0;
+    s->anctar[s->kanctar++] = rep = s->threp[s->start[s->lev]];
+    for (k = s->thnext[rep]; k != rep; k = s->thnext[k]) {
+        s->anctar[s->kanctar++] = k;
+    }
+    array_indirect_sort(s->anctar, s->thsize, s->kanctar);
+}
+
+static void
+multiply_index(struct saucy *s, int k)
+{
+    if ((s->stats->grpsize_base *= k) > 1e10) {
+        s->stats->grpsize_base /= 1e10;
+        s->stats->grpsize_exp += 10;
+    }
+}
+
+static int
+backtrack_leftmost(struct saucy *s)
+{
+    int rep = find_representative(s->indmin, s->theta);
+    int repsize = s->thsize[rep];
+    int min = -1;
+
+    pick_all_the_pairs(s);
+    clear_undiffnons(s);
+    s->ndiffs = s->nundiffs = s->npairs = s->ndiffnons = 0;
+
+    if (repsize != s->right.clen[s->start[s->lev]]+1) {
+        min = theta_prune(s);
+    }
+
+    if (min == -1) {
+        multiply_index(s, repsize);
+    }
+
+    return min;
+}
+
+static int
+backtrack_other(struct saucy *s)
+{
+    int cf = s->start[s->lev];
+    int cb = cf + s->right.clen[cf];
+    int spec = s->specmin[s->lev];
+    int min;
+
+    /* Avoid using pairs until we get back to leftmost. */
+    pick_all_the_pairs(s);
+
+    clear_undiffnons(s);
+
+    s->npairs = s->ndiffnons = -1;
+
+    if (s->right.lab[cb] == spec) {
+        min = find_min(s, cf);
+        if (min == cb) {
+            min = orbit_prune(s);
+        }
+        else {
+            min -= cf;
+        }
+    }
+    else {
+        min = orbit_prune(s);
+        if (min != -1 && s->right.lab[min + cf] == spec) {
+            swap_labels(&s->right, min + cf, cb);
+            min = orbit_prune(s);
+        }
+    }
+    return min;
+}
+
+static void
+rewind_coloring(struct saucy *s, struct coloring *c, int lev)
+{
+    int i, cf, ff, splits = s->splitlev[lev];
+    for (i = s->nsplits - 1; i >= splits; --i) {
+        cf = s->splitfrom[i];
+        ff = s->splitwho[i];
+        c->clen[cf] += c->clen[ff] + 1;
+        fix_fronts(c, cf, ff);
+    }
+}
+
+static void
+rewind_simulation_vectors(struct saucy *s, int lev)
+{   
+    int i;
+    for (i = s->randomVectorSplit_sim1[lev]; i < Vec_PtrSize(s->randomVectorArray_sim1); i++)
+        Vec_IntFree((Vec_Int_t *)Vec_PtrEntry(s->randomVectorArray_sim1, i));
+    Vec_PtrShrink(s->randomVectorArray_sim1, s->randomVectorSplit_sim1[lev]);
+
+    for (i = s->randomVectorSplit_sim2[lev]; i < Vec_PtrSize(s->randomVectorArray_sim2); i++)                      
+        Vec_IntFree((Vec_Int_t *)Vec_PtrEntry(s->randomVectorArray_sim2, i));    
+    Vec_PtrShrink(s->randomVectorArray_sim2, s->randomVectorSplit_sim2[lev]);
+}
+
+static int
+do_backtrack(struct saucy *s)
+{
+    int i, cf, cb;
+
+    /* Undo the splits up to this level */
+    rewind_coloring(s, &s->right, s->lev);
+    s->nsplits = s->splitlev[s->lev];
+
+    /* Rewind diff information */
+    for (i = s->ndiffs - 1; i >= s->difflev[s->lev]; --i) {
+        s->diffmark[s->diffs[i]] = 0;
+    }
+    s->ndiffs = s->difflev[s->lev];
+    s->nundiffs = s->undifflev[s->lev];
+
+    /* Point to the target cell */
+    cf = s->start[s->lev];
+    cb = cf + s->right.clen[cf];
+
+    /* Update ancestor with zeta if we've rewound more */
+    if (s->anc > s->lev) {
+        s->anc = s->lev;
+        s->indmin = s->left.lab[cb];
+        s->match = 1;
+        note_anctar_reps(s);
+    }
+
+    /* Perform backtracking appropriate to our location */
+    return s->lev == s->anc
+        ? backtrack_leftmost(s)
+        : backtrack_other(s);
+}
+
+static int
+backtrack_loop(struct saucy *s)
+{
+    int min;
+
+    /* Backtrack as long as we're exhausting target cells */
+    for (--s->lev; s->lev; --s->lev) {
+        min = do_backtrack(s);
+        if (min != -1) return min + s->start[s->lev];
+    }
+    return -1;
+}
+
+static int
+backtrack(struct saucy *s)
+{
+    int min, old, tmp;
+    old = s->nsplits;
+    min = backtrack_loop(s);
+    tmp = s->nsplits;
+    s->nsplits = old;
+    rewind_coloring(s, &s->left, s->lev+1); 
+    s->nsplits = tmp;
+    if (SELECT_DYNAMICALLY)
+        rewind_simulation_vectors(s, s->lev+1);
+
+    return min;
+}
+
+static int
+backtrack_bad(struct saucy *s)
+{
+    int min, old, tmp;
+    old = s->lev;
+    min = backtrack_loop(s);
+    if (BACKTRACK_BY_SAT) {
+        int oldLev = s->lev;
+        while (!backtrackBysatCounterExamples(s, &s->right)) {                          
+            min = backtrack_loop(s);            
+            if (!s->lev) {
+                if (s->fPrintTree)
+                    printf("Backtrack by SAT from level %d to %d\n", oldLev, 0);
+                return -1;
+            }
+        }
+        if (s->fPrintTree)          
+            if (s->lev < oldLev) 
+                printf("Backtrack by SAT from level %d to %d\n", oldLev, s->lev);
+    }
+    tmp = s->nsplits;
+    s->nsplits = s->splitlev[old];
+    rewind_coloring(s, &s->left, s->lev+1); 
+    s->nsplits = tmp;
+    if (SELECT_DYNAMICALLY)
+        rewind_simulation_vectors(s, s->lev+1);
+
+    return min;
+}
+
+void
+prepare_permutation_ntk(struct saucy *s) 
+{       
+    int i;
+    Abc_Obj_t * pObj, * pObjPerm;
+    int numouts = Abc_NtkPoNum(s->pNtk);
+
+    Nm_ManFree( s->pNtk_permuted->pManName );
+    s->pNtk_permuted->pManName = Nm_ManCreate( Abc_NtkCiNum(s->pNtk) + Abc_NtkCoNum(s->pNtk) + Abc_NtkBoxNum(s->pNtk) );    
+
+    for (i = 0; i < s->n; ++i) {        
+        if (i < numouts) {
+            pObj     = (Abc_Obj_t *)Vec_PtrEntry(s->pNtk->vPos, i);
+            pObjPerm = (Abc_Obj_t *)Vec_PtrEntry(s->pNtk_permuted->vPos, s->gamma[i]);           
+        }
+        else {          
+            pObj     = (Abc_Obj_t *)Vec_PtrEntry(s->pNtk->vPis, i - numouts);
+            pObjPerm = (Abc_Obj_t *)Vec_PtrEntry(s->pNtk_permuted->vPis, s->gamma[i] - numouts);
+            
+        }
+        Abc_ObjAssignName( pObjPerm, Abc_ObjName(pObj), NULL );         
+    }
+
+    Abc_NtkOrderObjsByName( s->pNtk_permuted, 1 );
+
+    /* print the permutation */
+    /*for (i = 0; i < s->ndiffs; ++i)
+        printf(" %d->%d", s->unsupp[i], s->diffs[i]);
+    printf("\n");
+    Abc_NtkForEachCo( s->pNtk, pObj, i )
+        printf (" %d", Abc_ObjId(pObj)-1-Abc_NtkPiNum(s->pNtk));
+    Abc_NtkForEachCi( s->pNtk, pObj, i )
+        printf (" %d", Abc_ObjId(pObj)-1+Abc_NtkPoNum(s->pNtk));
+    printf("\n");
+    Abc_NtkForEachCo( s->pNtk_permuted, pObj, i )
+        printf (" %d", Abc_ObjId(pObj)-1-Abc_NtkPiNum(s->pNtk_permuted));
+    Abc_NtkForEachCi( s->pNtk_permuted, pObj, i )
+        printf (" %d", Abc_ObjId(pObj)-1+Abc_NtkPoNum(s->pNtk_permuted));   
+    printf("\n");*/
+}
+
+
+static void
+prepare_permutation(struct saucy *s)
+{
+    int i, k;
+    for (i = 0; i < s->ndiffs; ++i) {
+        k = s->right.unlab[s->diffs[i]];
+        s->unsupp[i] = s->left.lab[k];
+        s->gamma[s->left.lab[k]] = s->right.lab[k];
+    }
+    prepare_permutation_ntk(s);
+}
+
+void
+unprepare_permutation_ntk(struct saucy *s) 
+{       
+    int i;
+    Abc_Obj_t * pObj, * pObjPerm;
+    int numouts = Abc_NtkPoNum(s->pNtk);
+
+    Nm_ManFree( s->pNtk_permuted->pManName );
+    s->pNtk_permuted->pManName = Nm_ManCreate( Abc_NtkCiNum(s->pNtk) + Abc_NtkCoNum(s->pNtk) + Abc_NtkBoxNum(s->pNtk) );    
+
+    for (i = 0; i < s->n; ++i) {        
+        if (i < numouts) {
+            pObj     = (Abc_Obj_t *)Vec_PtrEntry(s->pNtk->vPos, s->gamma[i]);
+            pObjPerm = (Abc_Obj_t *)Vec_PtrEntry(s->pNtk_permuted->vPos, i);         
+        }
+        else {          
+            pObj     = (Abc_Obj_t *)Vec_PtrEntry(s->pNtk->vPis, s->gamma[i] - numouts);
+            pObjPerm = (Abc_Obj_t *)Vec_PtrEntry(s->pNtk_permuted->vPis, i - numouts);
+            
+        }
+        Abc_ObjAssignName( pObjPerm, Abc_ObjName(pObj), NULL );         
+    }
+
+    Abc_NtkOrderObjsByName( s->pNtk_permuted, 1 );
+}
+
+
+static void
+unprepare_permutation(struct saucy *s)  
+{
+    int i;
+    unprepare_permutation_ntk(s);
+    for (i = 0; i < s->ndiffs; ++i) {
+        s->gamma[s->unsupp[i]] = s->unsupp[i];
+    }   
+}
+
+static int
+do_search(struct saucy *s)
+{
+    int min;
+
+    unprepare_permutation(s);
+
+    /* Backtrack to the ancestor with zeta */
+    if (s->lev > s->anc) s->lev = s->anc + 1;
+
+    /* Perform additional backtracking */
+    min = backtrack(s);
+
+    if (s->fBooleanMatching && (s->stats->grpsize_base > 1 || s->stats->grpsize_exp > 0))
+        return 0;
+
+    if (s->fPrintTree && s->lev > 0) {
+        //printf("in level %d: %d->%d\n", s->lev, s->left.lab[s->splitwho[s->nsplits]], s->right.lab[min]);
+        printf("in level %d: %s->%s\n", s->lev, getVertexName(s->pNtk, s->left.lab[s->splitwho[s->nsplits]]), getVertexName(s->pNtk, s->right.lab[min]));
+    }   
+
+    /* Keep going while there are tree nodes to expand */
+    while (s->lev) {
+
+        /* Descend to a new leaf node */    
+        if (descend(s, &s->right, s->start[s->lev], min)
+                && descend_left(s)) {
+
+            /* Prepare permutation */
+            prepare_permutation(s);
+
+            /* If we found an automorphism, return it */
+            if (s->is_automorphism(s)) {
+                ++s->stats->gens;
+                s->stats->support += s->ndiffs;
+                update_theta(s);                
+                s->print_automorphism(s->gFile, s->n, s->gamma, s->ndiffs, s->unsupp, s->marks, s->pNtk);
+                unprepare_permutation(s);               
+                return 1;
+            }
+            else {
+                unprepare_permutation(s);
+            }
+        }
+
+        /* If we get here, something went wrong; backtrack */
+        ++s->stats->bads;
+        min = backtrack_bad(s);
+        if (s->fPrintTree) {
+            printf("BAD NODE\n");
+            if (s->lev > 0) {
+                //printf("in level %d: %d->%d\n", s->lev, s->left.lab[s->splitwho[s->nsplits]], s->right.lab[min]);     
+                printf("in level %d: %s->%s\n", s->lev, getVertexName(s->pNtk, s->left.lab[s->splitwho[s->nsplits]]), getVertexName(s->pNtk, s->right.lab[min]));                               
+            }
+        }
+    }
+
+    /* Normalize group size */
+    while (s->stats->grpsize_base >= 10.0) {
+        s->stats->grpsize_base /= 10;
+        ++s->stats->grpsize_exp;
+    }
+    return 0;
+}
+
+void
+saucy_search(
+    Abc_Ntk_t * pNtk,
+    struct saucy *s,
+    int directed,
+    const int *colors,
+    struct saucy_stats *stats)
+{
+    int i, j, max = 0;  
+    struct saucy_graph *g;
+
+    extern Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk );
+
+    /* Save network information */
+    s->pNtk = pNtk;
+    s->pNtk_permuted = Abc_NtkDup( pNtk );  
+
+    /* Builde dependency graph */
+    g = buildDepGraph(pNtk, s->iDep, s->oDep);  
+
+    /* Save graph information */
+    s->n = g->n;
+    s->depAdj = g->adj;
+    s->depEdg = g->edg;
+    /*s->dadj = g->adj + g->n + 1;
+    s->dedg = g->edg + g->e;*/
+
+    /* Save client information */
+    s->stats = stats;       
+
+    /* Polymorphism */
+    if (directed) {
+        s->is_automorphism = is_directed_automorphism;
+        s->ref_singleton = ref_singleton_directed;
+        s->ref_nonsingle = ref_nonsingle_directed;
+    }
+    else {
+        s->is_automorphism = is_undirected_automorphism;
+        s->ref_singleton = ref_singleton_undirected;
+        s->ref_nonsingle = ref_nonsingle_undirected;
+    }
+
+    /* Initialize scalars */
+    s->indmin = 0;  
+    s->lev = s->anc = 1;
+    s->ndiffs = s->nundiffs = s->ndiffnons = 0;
+    s->activityInc = 1;
+
+    /* The initial orbit partition is discrete */
+    for (i = 0; i < s->n; ++i) {
+        s->theta[i] = i;
+    }
+
+    /* The initial permutation is the identity */
+    for (i = 0; i < s->n; ++i) {
+        s->gamma[i] = i;
+    }
+
+    /* Initially every cell of theta has one element */
+    for (i = 0; i < s->n; ++i) {
+        s->thsize[i] = 1;
+    }
+
+    /* Every theta rep list is singleton */
+    for (i = 0; i < s->n; ++i) {
+        s->thprev[i] = s->thnext[i] = i;
+    }
+
+    /* We have no pairs yet */
+    s->npairs = 0;
+    for (i = 0; i < s->n; ++i) {
+        s->unpairs[i] = -1;
+    }
+
+    /* Ensure no stray pointers in undiffnons, which is checked by removed_diffnon() */
+    for (i = 0; i < s->n; ++i) {
+        s->undiffnons[i] = -1;
+    }
+
+    /* Initialize stats */
+    s->stats->grpsize_base = 1.0;
+    s->stats->grpsize_exp = 0;
+    s->stats->nodes = 1;
+    s->stats->bads = s->stats->gens = s->stats->support = 0;
+
+    /* Prepare for refinement */
+    s->nninduce = s->nsinduce = 0;
+    s->csize = 0;
+
+    /* Count cell sizes */
+    for (i = 0; i < s->n; ++i) {
+        s->ccount[colors[i]]++;
+        if (max < colors[i]) max = colors[i];
+    }
+    s->nsplits = max + 1;
+
+    /* Build cell lengths */
+    s->left.clen[0] = s->ccount[0] - 1;
+    for (i = 0; i < max; ++i) {
+        s->left.clen[s->ccount[i]] = s->ccount[i+1] - 1;
+        s->ccount[i+1] += s->ccount[i];
+    }
+
+    /* Build the label array */
+    for (i = 0; i < s->n; ++i) {
+        set_label(&s->left, --s->ccount[colors[i]], i);
+    }
+
+    /* Clear out ccount */
+    for (i = 0; i <= max; ++i) {
+        s->ccount[i] = 0;
+    }
+
+    /* Update refinement stuff based on initial partition */
+    for (i = 0; i < s->n; i += s->left.clen[i]+1) {
+        add_induce(s, &s->left, i);
+        fix_fronts(&s->left, i, i);
+    }
+
+    /* Prepare lists based on cell lengths */
+    for (i = 0, j = -1; i < s->n; i += s->left.clen[i] + 1) {
+        if (!s->left.clen[i]) continue;
+        s->prevnon[i] = j;
+        s->nextnon[j] = i;
+        j = i;
+    }
+
+    /* Fix the end */
+    s->prevnon[s->n] = j;
+    s->nextnon[j] = s->n;
+
+    /* Preprocessing after initial coloring */
+    s->split = split_init;  
+    s->refineBySim1 = refineBySim1_init;
+    s->refineBySim2 = refineBySim2_init;    
+
+    //print_partition(&s->left, NULL, s->n, s->pNtk, 1);
+    printf("Initial Refine by Dependency graph ... ");
+    refineByDepGraph(s, &s->left);
+    //print_partition(&s->left, NULL, s->n, s->pNtk, 1);
+    printf("done!\n");
+    
+    printf("Initial Refine by Simulation ... ");
+    if (REFINE_BY_SIM_1) s->refineBySim1(s, &s->left);
+    //print_partition(&s->left, NULL, s->n, s->pNtk, 1);
+    if (REFINE_BY_SIM_2) s->refineBySim2(s, &s->left);
+    //print_partition(&s->left, NULL, s->n, s->pNtk, 1);
+    printf("done!\n\t--------------------\n");
+
+    /* Descend along the leftmost branch and compute zeta */
+    s->refineBySim1 = refineBySim1_left;
+    s->refineBySim2 = refineBySim2_left;
+    descend_leftmost(s);    
+    s->split = split_other; 
+    s->refineBySim1 = refineBySim1_other;
+    s->refineBySim2 = refineBySim2_other;   
+
+    /* Our common ancestor with zeta is the current level */
+    s->stats->levels = s->anc = s->lev;
+
+    /* Copy over this data to our non-leftmost coloring */
+    memcpy(s->right.lab, s->left.lab, s->n * sizeof(int));
+    memcpy(s->right.unlab, s->left.unlab, s->n * sizeof(int));
+    memcpy(s->right.clen, s->left.clen, s->n * sizeof(int));
+    memcpy(s->right.cfront, s->left.cfront, s->n * sizeof(int));
+
+    /* The reps are just the labels at this point */
+    memcpy(s->threp, s->left.lab, s->n * sizeof(int));
+    memcpy(s->thfront, s->left.unlab, s->n * sizeof(int));
+
+    /* choose cell selection method */
+    if (SELECT_DYNAMICALLY) s->select_decomposition = select_dynamically;
+    else                    s->select_decomposition = select_statically;
+
+    /* Keep running till we're out of automorphisms */
+    while (do_search(s));
+}
+
+void
+saucy_free(struct saucy *s)
+{
+    int i;
+
+    ABC_FREE(s->undiffnons);
+    ABC_FREE(s->diffnons);
+    ABC_FREE(s->unpairs);
+    ABC_FREE(s->pairs);
+    ABC_FREE(s->thfront);
+    ABC_FREE(s->threp);
+    ABC_FREE(s->thnext);
+    ABC_FREE(s->thprev);
+    ABC_FREE(s->specmin);
+    ABC_FREE(s->anctar);
+    ABC_FREE(s->thsize);
+    ABC_FREE(s->undifflev);
+    ABC_FREE(s->difflev);
+    ABC_FREE(s->diffs);
+    ABC_FREE(s->diffmark);
+    ABC_FREE(s->conncnts);
+    ABC_FREE(s->unsupp);
+    ABC_FREE(s->splitlev);
+    ABC_FREE(s->splitfrom);
+    ABC_FREE(s->splitwho);
+    ABC_FREE(s->splitvar);
+    ABC_FREE(s->right.unlab);
+    ABC_FREE(s->right.lab);
+    ABC_FREE(s->left.unlab);
+    ABC_FREE(s->left.lab);
+    ABC_FREE(s->theta);
+    ABC_FREE(s->junk);
+    ABC_FREE(s->gamma);
+    ABC_FREE(s->start);
+    ABC_FREE(s->prevnon);
+    free(s->nextnon-1);
+    ABC_FREE(s->clist);
+    ABC_FREE(s->ccount);
+    ABC_FREE(s->count);
+    ABC_FREE(s->bucket);
+    ABC_FREE(s->stuff);
+    ABC_FREE(s->right.clen);
+    ABC_FREE(s->right.cfront);
+    ABC_FREE(s->left.clen);
+    ABC_FREE(s->left.cfront);
+    ABC_FREE(s->indmark);
+    ABC_FREE(s->sinduce);
+    ABC_FREE(s->ninduce);
+    ABC_FREE(s->depAdj);
+    ABC_FREE(s->depEdg);
+    ABC_FREE(s->marks);
+    for (i = 0; i < Abc_NtkPiNum(s->pNtk); i++) {
+        Vec_IntFree( s->iDep[i] );
+        Vec_IntFree( s->obs[i] );
+        Vec_PtrFree( s->topOrder[i] );
+    }
+    for (i = 0; i < Abc_NtkPoNum(s->pNtk); i++) {
+        Vec_IntFree( s->oDep[i] );
+        Vec_IntFree( s->ctrl[i] );
+    }
+    for (i = 0; i < Vec_PtrSize(s->randomVectorArray_sim1); i++)
+        Vec_IntFree((Vec_Int_t *)Vec_PtrEntry(s->randomVectorArray_sim1, i));
+    for (i = 0; i < Vec_PtrSize(s->randomVectorArray_sim2); i++)
+        Vec_IntFree((Vec_Int_t *)Vec_PtrEntry(s->randomVectorArray_sim2, i));
+    Vec_PtrFree( s->randomVectorArray_sim1 );
+    Vec_PtrFree( s->randomVectorArray_sim2 );
+    ABC_FREE(s->randomVectorSplit_sim1);
+    ABC_FREE(s->randomVectorSplit_sim2);
+    Abc_NtkDelete( s->pNtk_permuted );
+    for (i = 0; i < Vec_PtrSize(s->satCounterExamples); i++) {
+        struct sim_result * cex = (struct sim_result *)Vec_PtrEntry(s->satCounterExamples, i);
+        ABC_FREE( cex->inVec );
+        ABC_FREE( cex->outVec );
+        ABC_FREE( cex );
+    }
+    Vec_PtrFree(s->satCounterExamples);
+    ABC_FREE( s->pModel );
+    ABC_FREE( s->iDep );
+    ABC_FREE( s->oDep );
+    ABC_FREE( s->obs );
+    ABC_FREE( s->ctrl );
+    ABC_FREE( s->topOrder );
+    ABC_FREE(s);
+}
+
+struct saucy *
+saucy_alloc(Abc_Ntk_t * pNtk)
+{
+    int i;
+    int numouts = Abc_NtkPoNum(pNtk);
+    int numins =  Abc_NtkPiNum(pNtk);
+    int n = numins + numouts;
+    struct saucy *s = ABC_ALLOC(struct saucy, 1);
+    if (s == NULL) return NULL;
+
+    s->ninduce = ints(n);
+    s->sinduce = ints(n);
+    s->indmark = bits(n);
+    s->left.cfront = zeros(n);
+    s->left.clen = ints(n);
+    s->right.cfront = zeros(n);
+    s->right.clen = ints(n);
+    s->stuff = bits(n+1);
+    s->bucket = ints(n+2);
+    s->count = ints(n+1);
+    s->ccount = zeros(n);
+    s->clist = ints(n);
+    s->nextnon = ints(n+1) + 1;
+    s->prevnon = ints(n+1);
+    s->anctar = ints(n);
+    s->start = ints(n);
+    s->gamma = ints(n);
+    s->junk = ints(n);
+    s->theta = ints(n);
+    s->thsize = ints(n);
+    s->left.lab = ints(n);
+    s->left.unlab = ints(n);
+    s->right.lab = ints(n);
+    s->right.unlab = ints(n);
+    s->splitvar = ints(n);
+    s->splitwho = ints(n);
+    s->splitfrom = ints(n);
+    s->splitlev = ints(n+1);
+    s->unsupp = ints(n);
+    s->conncnts = zeros(n);
+    s->diffmark = bits(n);
+    s->diffs = ints(n);
+    s->difflev = ints(n);
+    s->undifflev = ints(n);
+    s->specmin = ints(n);
+    s->thnext = ints(n);
+    s->thprev = ints(n);
+    s->threp = ints(n);
+    s->thfront = ints(n);
+    s->pairs = ints(n);
+    s->unpairs = ints(n);
+    s->diffnons = ints(n);
+    s->undiffnons = ints(n);
+    s->marks = bits(n);
+
+    s->iDep = ABC_ALLOC( Vec_Int_t*,  numins );
+    s->oDep = ABC_ALLOC( Vec_Int_t*,  numouts );
+    s->obs  = ABC_ALLOC( Vec_Int_t*,  numins );
+    s->ctrl = ABC_ALLOC( Vec_Int_t*,  numouts );
+
+    for(i = 0; i < numins; i++) {       
+        s->iDep[i] = Vec_IntAlloc( 1 );
+        s->obs[i] = Vec_IntAlloc( 1 );
+    }
+    for(i = 0; i < numouts; i++) {      
+        s->oDep[i] = Vec_IntAlloc( 1 );
+        s->ctrl[i] = Vec_IntAlloc( 1 );
+    }   
+
+    s->randomVectorArray_sim1 = Vec_PtrAlloc( n );  
+    s->randomVectorSplit_sim1 = zeros( n );
+    s->randomVectorArray_sim2 = Vec_PtrAlloc( n );  
+    s->randomVectorSplit_sim2= zeros( n );
+
+    s->satCounterExamples = Vec_PtrAlloc( 1 );
+    s->pModel = ints( numins );
+
+    if (s->ninduce && s->sinduce && s->left.cfront && s->left.clen
+        && s->right.cfront && s->right.clen
+        && s->stuff && s->bucket && s->count && s->ccount
+        && s->clist && s->nextnon-1 && s->prevnon
+        && s->start && s->gamma && s->theta && s->left.unlab
+        && s->right.lab && s->right.unlab
+        && s->left.lab &&  s->splitvar && s->splitwho && s->junk
+        && s->splitfrom && s->splitlev && s->thsize
+        && s->unsupp && s->conncnts && s->anctar
+        && s->diffmark && s->diffs && s->indmark
+        && s->thnext && s->thprev && s->threp && s->thfront
+        && s->pairs && s->unpairs && s->diffnons && s->undiffnons
+        && s->difflev && s->undifflev && s->specmin)
+    {
+        return s;
+    }
+    else {
+        saucy_free(s);
+        return NULL;
+    }
+}
+
+static void
+print_stats(FILE *f, struct saucy_stats stats )
+{
+    fprintf(f, "group size = %fe%d\n",
+        stats.grpsize_base, stats.grpsize_exp);
+    fprintf(f, "levels = %d\n", stats.levels);
+    fprintf(f, "nodes = %d\n", stats.nodes);
+    fprintf(f, "generators = %d\n", stats.gens);
+    fprintf(f, "total support = %d\n", stats.support);
+    fprintf(f, "average support = %.2f\n",(double)(stats.support)/(double)(stats.gens));
+    fprintf(f, "nodes per generator = %.2f\n",(double)(stats.nodes)/(double)(stats.gens));
+    fprintf(f, "bad nodes = %d\n", stats.bads);
+}
+
+
+/* From this point up are SAUCY functions*/
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+/* From this point down are new functions */
+
+static char * 
+getVertexName(Abc_Ntk_t *pNtk, int v)
+{   
+    Abc_Obj_t * pObj;
+    int numouts =  Abc_NtkPoNum(pNtk);
+
+    if (v < numouts)    
+        pObj = (Abc_Obj_t *)Vec_PtrEntry(pNtk->vPos, v);
+    else
+        pObj = (Abc_Obj_t *)Vec_PtrEntry(pNtk->vPis, v - numouts);       
+    
+    return Abc_ObjName(pObj);
+}
+
+static Vec_Ptr_t ** 
+findTopologicalOrder( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t ** vNodes;
+    Abc_Obj_t * pObj, * pFanout;
+    int i, k;    
+    
+    extern void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes );
+    
+    /* start the array of nodes */
+    vNodes = ABC_ALLOC(Vec_Ptr_t *, Abc_NtkPiNum(pNtk));
+    for(i = 0; i < Abc_NtkPiNum(pNtk); i++)
+        vNodes[i] = Vec_PtrAlloc(50);   
+    
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        /* set the traversal ID */
+        Abc_NtkIncrementTravId( pNtk );
+        Abc_NodeSetTravIdCurrent( pObj );
+        pObj = Abc_ObjFanout0Ntk(pObj);
+        Abc_ObjForEachFanout( pObj, pFanout, k )
+            Abc_NtkDfsReverse_rec( pFanout, vNodes[i] );
+    }
+   
+    return vNodes;
+}
+
+static void 
+getDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep)
+{   
+    Vec_Ptr_t * vSuppFun;
+    int i, j;   
+    
+    vSuppFun = Sim_ComputeFunSupp(pNtk, 0);
+    for(i = 0; i < Abc_NtkPoNum(pNtk); i++) {
+        char * seg = (char *)vSuppFun->pArray[i];
+        
+        for(j = 0; j < Abc_NtkPiNum(pNtk); j+=8) {
+            if(((*seg) & 0x01) == 0x01)
+                Vec_IntPushOrder(oDep[i], j);
+            if(((*seg) & 0x02) == 0x02)
+                Vec_IntPushOrder(oDep[i], j+1);
+            if(((*seg) & 0x04) == 0x04)
+                Vec_IntPushOrder(oDep[i], j+2);
+            if(((*seg) & 0x08) == 0x08)
+                Vec_IntPushOrder(oDep[i], j+3);
+            if(((*seg) & 0x10) == 0x10)
+                Vec_IntPushOrder(oDep[i], j+4);
+            if(((*seg) & 0x20) == 0x20)
+                Vec_IntPushOrder(oDep[i], j+5);
+            if(((*seg) & 0x40) == 0x40)
+                Vec_IntPushOrder(oDep[i], j+6);
+            if(((*seg) & 0x80) == 0x80)
+                Vec_IntPushOrder(oDep[i], j+7);
+
+            seg++;
+        }
+    }
+
+    for(i = 0; i < Abc_NtkPoNum(pNtk); i++)
+        for(j = 0; j < Vec_IntSize(oDep[i]); j++)
+            Vec_IntPush(iDep[Vec_IntEntry(oDep[i], j)], i); 
+    
+
+    /*for(i = 0; i < Abc_NtkPoNum(pNtk); i++)
+    {
+        printf("Output %d: ", i);
+        for(j = 0; j < Vec_IntSize(oDep[i]); j++)
+            printf("%d ", Vec_IntEntry(oDep[i], j));
+        printf("\n");
+    }
+
+    printf("\n");
+
+    for(i = 0; i < Abc_NtkPiNum(pNtk); i++)
+    {
+        printf("Input %d: ", i);
+        for(j = 0; j < Vec_IntSize(iDep[i]); j++)
+            printf("%d ", Vec_IntEntry(iDep[i], j));
+        printf("\n");
+    }
+
+    printf("\n");   */  
+}
+
+static void 
+getDependenciesDummy(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep)
+{       
+    int i, j;   
+    
+    /* let's assume that every output is dependent on every input */
+    for(i = 0; i < Abc_NtkPoNum(pNtk); i++)
+        for(j = 0; j < Abc_NtkPiNum(pNtk); j++)
+            Vec_IntPush(oDep[i], j);
+
+    for(i = 0; i < Abc_NtkPiNum(pNtk); i++)
+        for(j = 0; j < Abc_NtkPoNum(pNtk); j++)
+            Vec_IntPush(iDep[i], j);
+}
+
+static struct saucy_graph *
+buildDepGraph(Abc_Ntk_t *pNtk, Vec_Int_t ** iDep, Vec_Int_t ** oDep)
+{       
+    int i, j, k;    
+    struct saucy_graph *g = NULL;
+    int n, e, *adj, *edg;   
+
+    n = Abc_NtkPoNum(pNtk) + Abc_NtkPiNum(pNtk);
+    for (e = 0, i = 0; i < Abc_NtkPoNum(pNtk); i++)
+        e += Vec_IntSize(oDep[i]);  
+
+    g = ABC_ALLOC(struct saucy_graph, 1);
+    adj = zeros(n+1);
+    edg = ints(2*e);    
+
+    g->n = n;
+    g->e = e;
+    g->adj = adj;
+    g->edg = edg;   
+
+    adj[0] = 0;
+    for (i = 0; i < n; i++) {
+        /* first add outputs and then inputs */
+        if ( i < Abc_NtkPoNum(pNtk)) {          
+            adj[i+1] = adj[i] + Vec_IntSize(oDep[i]);
+            for (k = 0, j = adj[i]; j < adj[i+1]; j++, k++)
+                edg[j] = Vec_IntEntry(oDep[i], k) + Abc_NtkPoNum(pNtk);
+        }
+        else {          
+            adj[i+1] = adj[i] + Vec_IntSize(iDep[i-Abc_NtkPoNum(pNtk)]);
+            for (k = 0, j = adj[i]; j < adj[i+1]; j++, k++)
+                edg[j] = Vec_IntEntry(iDep[i-Abc_NtkPoNum(pNtk)], k);
+        }
+    }
+
+    /* print graph for testing */
+    /*for (i = 0; i < n; i++) {
+        printf("%d: ", i);
+        for (j = adj[i]; j < adj[i+1]; j++)
+            printf("%d ", edg[j]);
+        printf("\n");
+    }*/
+
+    return g;
+}
+
+static Vec_Int_t * 
+assignRandomBitsToCells(Abc_Ntk_t * pNtk, struct coloring *c)
+{
+    Vec_Int_t * randVec = Vec_IntAlloc( 1 );
+    int i, bit;
+
+    for (i = 0; i < Abc_NtkPiNum(pNtk); i += (c->clen[i+Abc_NtkPoNum(pNtk)]+1)) {
+        bit = (int)(SIM_RANDOM_UNSIGNED % 2);
+        Vec_IntPush(randVec, bit);
+    }
+
+    return randVec;
+}
+
+static int * 
+generateProperInputVector( Abc_Ntk_t * pNtk, struct coloring *c, Vec_Int_t * randomVector )
+{
+    int * vPiValues;    
+    int i, j, k, bit, input;
+    int numouts =  Abc_NtkPoNum(pNtk);
+    int numins =  Abc_NtkPiNum(pNtk);
+    int n = numouts + numins;
+
+    vPiValues = ABC_ALLOC( int,  numins);   
+
+    for (i = numouts, k = 0; i < n; i += (c->clen[i]+1), k++) {
+        if (k == Vec_IntSize(randomVector)) break;
+
+        bit = Vec_IntEntry(randomVector, k);
+        for (j = i; j <= (i + c->clen[i]); j++) {
+            input = c->lab[j] - numouts;
+            vPiValues[input] = bit;
+        }
+    }
+
+    //if (k != Vec_IntSize(randomVector)) {
+    if (i < n) {
+        ABC_FREE( vPiValues );
+        return NULL;
+    }
+
+    return vPiValues;
+}
+
+static int
+ifInputVectorsAreConsistent( struct saucy * s, int * leftVec, int * rightVec )
+{
+    /* This function assumes that left and right partitions are isomorphic */
+    int i, j;
+    int lab;
+    int left_bit, right_bit;
+    int numouts =  Abc_NtkPoNum(s->pNtk);
+    int n = numouts + Abc_NtkPiNum(s->pNtk);
+
+    for (i = numouts; i < n; i += (s->right.clen[i]+1)) {       
+        lab = s->left.lab[i] - numouts;
+        left_bit = leftVec[lab];
+        for (j = i+1; j <= (i + s->right.clen[i]); j++) {
+            lab = s->left.lab[j] - numouts;         
+            if (left_bit != leftVec[lab]) return -1;
+        }       
+        
+        lab = s->right.lab[i] - numouts;
+        right_bit = rightVec[lab];
+        for (j = i+1; j <= (i + s->right.clen[i]); j++) {
+            lab = s->right.lab[j] - numouts;            
+            if (right_bit != rightVec[lab]) return 0;           
+        }
+
+        if (left_bit != right_bit) 
+             return 0;
+    }
+
+    return 1;
+}
+
+static int
+ifOutputVectorsAreConsistent( struct saucy * s, int * leftVec, int * rightVec )
+{
+    /* This function assumes that left and right partitions are isomorphic */
+    int i, j;
+    int count1, count2;
+
+    for (i = 0; i < Abc_NtkPoNum(s->pNtk); i += (s->right.clen[i]+1)) {     
+        count1 = count2 = 0;
+        for (j = i; j <= (i + s->right.clen[i]); j++) {         
+            if (leftVec[s->left.lab[j]]) count1++;
+            if (rightVec[s->right.lab[j]]) count2++;
+        }
+
+        if (count1 != count2) return 0;
+    }
+
+    return 1;
+}
+
+static struct saucy_graph *
+buildSim1Graph( Abc_Ntk_t * pNtk, struct coloring *c, Vec_Int_t * randVec, Vec_Int_t ** iDep, Vec_Int_t ** oDep )
+{
+    int i, j, k;
+    struct saucy_graph *g;
+    int n, e, *adj, *edg;
+    int * vPiValues, * output;
+    int numOneOutputs = 0;
+    int numouts =  Abc_NtkPoNum(pNtk);
+    int numins = Abc_NtkPiNum(pNtk);
+
+    vPiValues = generateProperInputVector(pNtk, c, randVec);
+    if (vPiValues == NULL) 
+        return NULL;
+
+    output = Abc_NtkVerifySimulatePattern(pNtk, vPiValues);
+
+    for (i = 0; i < numouts; i++) {
+        if (output[i])
+            numOneOutputs++;
+    }
+
+    g = ABC_ALLOC(struct saucy_graph, 1);
+    n = numouts + numins;
+    e = numins * numOneOutputs;
+    adj = ints(n+1);
+    edg = ints(2*e);        
+    g->n = n;
+    g->e = e;
+    g->adj = adj;
+    g->edg = edg;   
+
+    adj[0] = 0;
+    for (i = 0; i < numouts; i++) {
+        if (output[i]) {
+            adj[i+1] = adj[i] + Vec_IntSize(oDep[i]);
+            for (j = adj[i], k = 0; j < adj[i+1]; j++, k++)
+                edg[j] = Vec_IntEntry(oDep[i], k) + numouts;
+        } else {
+            adj[i+1] = adj[i];
+        }
+    }
+
+    for (i = 0; i < numins; i++) {
+        adj[i+numouts+1] = adj[i+numouts];
+        for (k = 0, j = adj[i+numouts]; k < Vec_IntSize(iDep[i]); k++) {
+            if (output[Vec_IntEntry(iDep[i], k)]) {
+                edg[j++] = Vec_IntEntry(iDep[i], k);
+                adj[i+numouts+1]++;
+            }
+        }
+    }
+
+    /* print graph */
+    /*for (i = 0; i < n; i++) {
+        printf("%d: ", i);
+        for (j = adj[i]; j < adj[i+1]; j++)
+            printf("%d ", edg[j]);
+        printf("\n");
+    }*/
+
+    ABC_FREE( vPiValues );  
+    ABC_FREE( output );
+    
+    return g;   
+}
+
+static struct saucy_graph *
+buildSim2Graph( Abc_Ntk_t * pNtk, struct coloring *c, Vec_Int_t * randVec, Vec_Int_t ** iDep, Vec_Int_t ** oDep, Vec_Ptr_t ** topOrder, Vec_Int_t ** obs,  Vec_Int_t ** ctrl )
+{
+    int i, j, k;
+    struct saucy_graph *g = NULL;
+    int n, e = 0, *adj, *edg;
+    int * vPiValues;
+    int * output, * output2;
+    int numouts =  Abc_NtkPoNum(pNtk);
+    int numins =  Abc_NtkPiNum(pNtk);
+
+    extern int * Abc_NtkSimulateOneNode( Abc_Ntk_t * , int * , int , Vec_Ptr_t ** );    
+    
+    vPiValues = generateProperInputVector(pNtk, c, randVec);
+    if (vPiValues == NULL) 
+        return NULL;
+
+    output = Abc_NtkVerifySimulatePattern( pNtk, vPiValues );   
+    
+    for (i = 0; i < numins; i++) {
+        if (!c->clen[c->cfront[i+numouts]]) continue;
+        if (vPiValues[i] == 0)  vPiValues[i] = 1;
+        else                    vPiValues[i] = 0;
+
+        output2 = Abc_NtkSimulateOneNode( pNtk, vPiValues, i, topOrder );
+
+        for (j = 0; j < Vec_IntSize(iDep[i]); j++) {
+            if (output[Vec_IntEntry(iDep[i], j)] != output2[Vec_IntEntry(iDep[i], j)]) {
+                Vec_IntPush(obs[i], Vec_IntEntry(iDep[i], j));
+                Vec_IntPush(ctrl[Vec_IntEntry(iDep[i], j)], i);
+                e++;
+            }
+        }
+
+        if (vPiValues[i] == 0)  vPiValues[i] = 1;
+        else                    vPiValues[i] = 0;
+
+        ABC_FREE( output2 );
+    }       
+
+    /* build the graph */
+    g = ABC_ALLOC(struct saucy_graph, 1);
+    n = numouts + numins;
+    adj = ints(n+1);
+    edg = ints(2*e);        
+    g->n = n;
+    g->e = e;
+    g->adj = adj;
+    g->edg = edg;       
+
+    adj[0] = 0;
+    for (i = 0; i < numouts; i++) {
+        adj[i+1] = adj[i] + Vec_IntSize(ctrl[i]);
+        for (k = 0, j = adj[i]; j < adj[i+1]; j++, k++)
+            edg[j] = Vec_IntEntry(ctrl[i], k) + numouts;
+    }
+    for (i = 0; i < numins; i++) {
+        adj[i+numouts+1] = adj[i+numouts] + Vec_IntSize(obs[i]);
+        for (k = 0, j = adj[i+numouts]; j < adj[i+numouts+1]; j++, k++)
+            edg[j] = Vec_IntEntry(obs[i], k);
+    }
+
+    /* print graph */
+    /*for (i = 0; i < n; i++) {
+        printf("%d: ", i);
+        for (j = adj[i]; j < adj[i+1]; j++)
+            printf("%d ", edg[j]);
+        printf("\n");
+    }*/
+
+    ABC_FREE( output );
+    ABC_FREE( vPiValues );  
+    for (j = 0; j < numins; j++)
+        Vec_IntClear(obs[j]);
+    for (j = 0; j < numouts; j++)
+        Vec_IntClear(ctrl[j]);
+
+    return g;
+}
+
+static void 
+bumpActivity( struct saucy * s, struct sim_result * cex )
+{
+    int i;
+    struct sim_result * cex2;
+
+    if ( (cex->activity += s->activityInc) > 1e20 ) {
+        /* Rescale: */
+        for (i = 0; i < Vec_PtrSize(s->satCounterExamples); i++) {
+            cex2 = (struct sim_result *)Vec_PtrEntry(s->satCounterExamples, i);
+            cex2->activity *= 1e-20;
+        }
+        s->activityInc *= 1e-20; 
+    } 
+}
+
+static void
+reduceDB( struct saucy * s )
+{   
+    int i, j;
+    double extra_lim = s->activityInc / Vec_PtrSize(s->satCounterExamples);    /* Remove any clause below this activity */
+    struct sim_result * cex;
+
+    while (Vec_PtrSize(s->satCounterExamples) > (0.7 * MAX_LEARNTS)) {
+        for (i = j = 0; i < Vec_PtrSize(s->satCounterExamples); i++) {
+            cex = (struct sim_result *)Vec_PtrEntry(s->satCounterExamples, i);
+            if (cex->activity < extra_lim) {
+                ABC_FREE(cex->inVec);
+                ABC_FREE(cex->outVec);
+                ABC_FREE(cex);                      
+            }
+            else if (j < i) {
+                Vec_PtrWriteEntry(s->satCounterExamples, j, cex);
+                j++;
+            }
+        }
+        //printf("Database size reduced from %d to %d\n", Vec_PtrSize(s->satCounterExamples), j);
+        Vec_PtrShrink(s->satCounterExamples, j);        
+        extra_lim *= 2;
+    }
+    
+    assert(Vec_PtrSize(s->satCounterExamples) <= (0.7 * MAX_LEARNTS));
+}
+
+static struct sim_result *
+analyzeConflict( Abc_Ntk_t * pNtk, int * pModel, int fVerbose )
+{   
+    Abc_Obj_t * pNode;
+    int i, count = 0;
+    int * pValues;
+    struct sim_result * cex;
+    int numouts = Abc_NtkPoNum(pNtk);
+    int numins = Abc_NtkPiNum(pNtk);
+    
+    cex = ABC_ALLOC(struct sim_result, 1);  
+    cex->inVec = ints( numins );
+    cex->outVec =  ints( numouts ); 
+
+    /* get the CO values under this model */
+    pValues = Abc_NtkVerifySimulatePattern( pNtk, pModel );    
+
+    Abc_NtkForEachCi( pNtk, pNode, i ) 
+        cex->inVec[Abc_ObjId(pNode)-1] = pModel[i];
+    Abc_NtkForEachCo( pNtk, pNode, i ) {
+        cex->outVec[Abc_ObjId(pNode)-numins-1] = pValues[i];
+        if (pValues[i]) count++;
+    }   
+    
+    cex->outVecOnes = count;
+    cex->activity = 0;  
+
+    if (fVerbose) {
+        Abc_NtkForEachCi( pNtk, pNode, i )
+            printf(" %s=%d", Abc_ObjName(pNode), pModel[i]);
+        printf("\n");
+    }
+
+    ABC_FREE( pValues );    
+
+    return cex;
+}
+
+static int
+Abc_NtkCecSat_saucy( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel )
+{
+    extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
+    Abc_Ntk_t * pMiter;
+    Abc_Ntk_t * pCnf;
+    int RetValue;
+    int nConfLimit;
+    int nInsLimit;
+    int i;
+
+    nConfLimit = 10000;
+    nInsLimit = 0;  
+
+    /* get the miter of the two networks */
+    pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0, 0, 0 );
+    if ( pMiter == NULL )
+    {
+        printf( "Miter computation has failed.\n" );
+        exit(1);
+    }
+    RetValue = Abc_NtkMiterIsConstant( pMiter );
+    if ( RetValue == 0 )
+    {
+        //printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+        /* report the error */
+        pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 );       
+        for (i = 0; i < Abc_NtkPiNum(pNtk1); i++)
+            pModel[i] = pMiter->pModel[i];  
+        ABC_FREE( pMiter->pModel );
+        Abc_NtkDelete( pMiter );
+        return 0;
+    }
+    if ( RetValue == 1 )
+    {
+        Abc_NtkDelete( pMiter );
+        //printf( "Networks are equivalent after structural hashing.\n" );
+        return 1;
+    }
+
+    /* convert the miter into a CNF */
+    pCnf = Abc_NtkMulti( pMiter, 0, 100, 1, 0, 0, 0 );
+    Abc_NtkDelete( pMiter );
+    if ( pCnf == NULL )
+    {
+        printf( "Renoding for CNF has failed.\n" );
+        exit(1);
+    }
+
+    /* solve the CNF using the SAT solver */
+    RetValue = Abc_NtkMiterSat( pCnf, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, 0, NULL, NULL );
+    if ( RetValue == -1 ) {
+        printf( "Networks are undecided (SAT solver timed out).\n" );
+        exit(1);
+    }
+    /*else if ( RetValue == 0 )
+        printf( "Networks are NOT EQUIVALENT after SAT.\n" );
+    else
+        printf( "Networks are equivalent after SAT.\n" );*/
+    if ( pCnf->pModel ) {       
+        for (i = 0; i < Abc_NtkPiNum(pNtk1); i++)
+            pModel[i] = pCnf->pModel[i];
+    }
+    ABC_FREE( pCnf->pModel );
+    Abc_NtkDelete( pCnf );
+
+    return RetValue;
+}
+
+
+void saucyGateWay( Abc_Ntk_t * pNtkOrig, Abc_Obj_t * pNodePo, FILE * gFile, int fBooleanMatching, 
+                   int fLookForSwaps, int fFixOutputs, int fFixInputs, int fQuiet, int fPrintTree )
+{
+    Abc_Ntk_t * pNtk;
+    struct saucy *s;
+    struct saucy_stats stats;
+    int *colors;
+    int i, clk = clock();   
+    
+    if (pNodePo == NULL)
+        pNtk = Abc_NtkDup( pNtkOrig );
+    else
+        pNtk = Abc_NtkCreateCone( pNtkOrig, Abc_ObjFanin0(pNodePo), Abc_ObjName(pNodePo), 0 );
+    
+    if (Abc_NtkPiNum(pNtk) == 0) {
+        Abc_Print( 0, "This output is not dependent on any input\n" );
+        Abc_NtkDelete( pNtk );
+        return;
+    }
+
+    s = saucy_alloc( pNtk );    
+
+    /******* Getting Dependencies *******/  
+    printf("Build functional dependency graph (dependency stats are below) ... ");      
+    getDependencies( pNtk, s->iDep, s->oDep );
+    printf("\t--------------------\n");
+    /************************************/
+
+    /* Finding toplogical orde */
+    s->topOrder = findTopologicalOrder( pNtk );                 
+
+    /* Setting graph colors: outputs = 0 and inputs = 1 */
+    colors = ints(Abc_NtkPoNum(pNtk) + Abc_NtkPiNum(pNtk));
+    if (fFixOutputs) {
+        for (i = 0; i < Abc_NtkPoNum(pNtk); i++)
+            colors[i] = i;
+    } else {
+        for (i = 0; i < Abc_NtkPoNum(pNtk); i++)
+            colors[i] = 0;
+    }
+    if (fFixInputs) {
+        int c = (fFixOutputs) ? Abc_NtkPoNum(pNtk) : 1;
+        for (i = 0; i < Abc_NtkPiNum(pNtk); i++)
+            colors[i+Abc_NtkPoNum(pNtk)] = c+i;     
+    } else {
+        int c = (fFixOutputs) ? Abc_NtkPoNum(pNtk) : 1;
+        for (i = 0; i < Abc_NtkPiNum(pNtk); i++)
+            colors[i+Abc_NtkPoNum(pNtk)] = c;   
+    }   
+
+    /* Are we looking for Boolean matching? */
+    s->fBooleanMatching = fBooleanMatching;
+    if (fBooleanMatching) {
+        NUM_SIM1_ITERATION = 50;
+        NUM_SIM2_ITERATION = 50;
+    } else {
+        NUM_SIM1_ITERATION = 200;
+        NUM_SIM2_ITERATION = 200;
+    }
+
+    /* Set the print automorphism routine */
+    if (!fQuiet)
+        s->print_automorphism = print_automorphism_ntk;
+    else
+        s->print_automorphism = print_automorphism_quiet;
+
+    /* Set the output file for generators */
+    if (gFile == NULL)
+        s->gFile = stdout;
+    else
+        s->gFile = gFile;
+
+    /* Set print tree option */
+    s->fPrintTree = fPrintTree;
+
+    /* Set input permutations option */
+    s->fLookForSwaps = fLookForSwaps;
+
+    saucy_search(pNtk, s, 0, colors, &stats);   
+    print_stats(stdout, stats);
+    if (fBooleanMatching) {
+        if (stats.grpsize_base > 1 || stats.grpsize_exp > 0)
+            printf("*** Networks are equivalent ***\n");
+        else
+            printf("*** Networks are NOT equivalent ***\n");
+    }
+    saucy_free(s);
+    Abc_NtkDelete(pNtk);
+
+    if (1) {
+        FILE * hadi = fopen("hadi.txt", "a");
+        fprintf(hadi, "group size = %fe%d\n",
+        stats.grpsize_base, stats.grpsize_exp); 
+        fclose(hadi);
+    }
+
+    ABC_PRT( "Runtime", clock() - clk );
+
+}ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/base/abci/abcScorr.c b/abc-build/src/base/abci/abcScorr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcScorr.c
@@ -0,0 +1,454 @@
+/**CFile****************************************************************
+
+  FileName    [abcScorr.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Signal correspondence testing procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcScorr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include "base/abc/abc.h"
+#include "base/io/ioAbc.h"
+#include "aig/saig/saig.h"
+#include "proof/ssw/ssw.h"
+#include "aig/gia/gia.h"
+#include "proof/cec/cec.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Tst_Dat_t_ Tst_Dat_t;
+struct Tst_Dat_t_
+{
+    Abc_Ntk_t * pNetlist;
+    Aig_Man_t * pAig;
+    Gia_Man_t * pGia;
+    Vec_Int_t * vId2Name;
+    char *      pFileNameOut;
+    int         fFlopOnly;
+    int         fFfNdOnly;
+    int         fDumpBmc;      
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkMapGiaIntoNameId( Abc_Ntk_t * pNetlist, Aig_Man_t * pAig, Gia_Man_t * pGia )
+{
+    Vec_Int_t * vId2Name;
+    Abc_Obj_t * pNet, * pNode, * pAnd;
+    Aig_Obj_t * pObjAig;
+    int i;
+    vId2Name = Vec_IntAlloc( 0 );
+    Vec_IntFill( vId2Name, pGia ? Gia_ManObjNum(pGia) : Aig_ManObjNumMax(pAig), ~0 );
+    // copy all names
+    Abc_NtkForEachNet( pNetlist, pNet, i )
+    {
+        pNode = Abc_ObjFanin0(pNet)->pCopy; 
+        if ( pNode && (pAnd = Abc_ObjRegular(pNode->pCopy)) && 
+            (pObjAig = (Aig_Obj_t *)Abc_ObjRegular(pAnd->pCopy)) && 
+             Aig_ObjType(pObjAig) != AIG_OBJ_NONE )
+        {
+            if ( pGia == NULL )
+                Vec_IntWriteEntry( vId2Name, Aig_ObjId(pObjAig), Abc_ObjId(pNet) );
+            else
+                Vec_IntWriteEntry( vId2Name, Abc_Lit2Var(pObjAig->iData), Abc_ObjId(pNet) );
+        }
+    }
+    // overwrite CO names
+    Abc_NtkForEachCo( pNetlist, pNode, i )
+    {
+        pNet = Abc_ObjFanin0(pNode);
+        pNode = pNode->pCopy;
+        if ( pNode && (pAnd = Abc_ObjRegular(pNode->pCopy)) && 
+            (pObjAig = (Aig_Obj_t *)Abc_ObjRegular(pAnd->pCopy)) && 
+             Aig_ObjType(pObjAig) != AIG_OBJ_NONE )
+        {
+            if ( pGia == NULL )
+                Vec_IntWriteEntry( vId2Name, Aig_ObjId(pObjAig), Abc_ObjId(pNet) );
+            else
+                Vec_IntWriteEntry( vId2Name, Abc_Lit2Var(pObjAig->iData), Abc_ObjId(pNet) );
+        }
+    }
+    // overwrite CI names
+    Abc_NtkForEachCi( pNetlist, pNode, i )
+    {
+        pNet = Abc_ObjFanout0(pNode);
+        pNode = pNode->pCopy;
+        if ( pNode && (pAnd = Abc_ObjRegular(pNode->pCopy)) && 
+            (pObjAig = (Aig_Obj_t *)Abc_ObjRegular(pAnd->pCopy)) && 
+             Aig_ObjType(pObjAig) != AIG_OBJ_NONE )
+        {
+            if ( pGia == NULL )
+                Vec_IntWriteEntry( vId2Name, Aig_ObjId(pObjAig), Abc_ObjId(pNet) );
+            else
+                Vec_IntWriteEntry( vId2Name, Abc_Lit2Var(pObjAig->iData), Abc_ObjId(pNet) );
+        }
+    }
+    return vId2Name;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_NtkTestScorrGetName( Abc_Ntk_t * pNetlist, Vec_Int_t * vId2Name, int Id )
+{
+//    Abc_Obj_t * pObj;
+//printf( "trying to get name for %d\n", Id );
+    if ( Vec_IntEntry(vId2Name, Id) == ~0 )
+        return NULL;
+//    pObj = Abc_NtkObj( pNetlist, Vec_IntEntry(vId2Name, Id) );
+//    pObj = Abc_ObjFanin0(pObj);
+//    assert( Abc_ObjIsCi(pObj) );
+    return Nm_ManFindNameById( pNetlist->pManName, Vec_IntEntry(vId2Name, Id) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkTestScorrWriteEquivPair( Abc_Ntk_t * pNetlist, Vec_Int_t * vId2Name, int Id1, int Id2, FILE * pFile, int fPol )
+{
+    char * pName1 = Abc_NtkTestScorrGetName( pNetlist, vId2Name, Id1 );
+    char * pName2 = Abc_NtkTestScorrGetName( pNetlist, vId2Name, Id2 );
+    if ( pName1 == NULL || pName2 == NULL )
+        return 0;
+    fprintf( pFile, "%s=%s%s\n", pName1, fPol? "~": "", pName2 );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkTestScorrWriteEquivConst( Abc_Ntk_t * pNetlist, Vec_Int_t * vId2Name, int Id1, FILE * pFile, int fPol )
+{
+    char * pName1 = Abc_NtkTestScorrGetName( pNetlist, vId2Name, Id1 );
+    if ( pName1 == NULL )
+        return 0;
+    fprintf( pFile, "%s=%s%s\n", pName1, fPol? "~": "", "const0" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_NtkBmcFileName( char * pName )
+{
+    static char Buffer[1000];
+    char * pNameGeneric = Extra_FileNameGeneric( pName );
+    sprintf( Buffer, "%s_bmc%s", pNameGeneric, pName + strlen(pNameGeneric) );
+    ABC_FREE( pNameGeneric );
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkTestScorrWriteEquivGia( Tst_Dat_t * pData )
+{
+    Abc_Ntk_t * pNetlist = pData->pNetlist;
+    Vec_Int_t * vId2Name = pData->vId2Name;
+    Gia_Man_t * pGia     = pData->pGia;
+    char * pFileNameOut  = pData->pFileNameOut;
+    FILE * pFile;
+    Gia_Obj_t * pObj, * pRepr;
+    int i, Counter = 0;
+    if ( pData->fDumpBmc )
+    {
+        pData->fDumpBmc = 0;
+        pFileNameOut = Abc_NtkBmcFileName( pFileNameOut );
+    }
+    pFile = fopen( pFileNameOut, "wb" );
+    Gia_ManSetPhase( pGia );
+    Gia_ManForEachObj( pGia, pObj, i )
+    {
+        if ( !Gia_ObjHasRepr(pGia, i) )
+            continue;
+        pRepr = Gia_ManObj( pGia,Gia_ObjRepr(pGia, i) );
+        if ( pData->fFlopOnly )
+        {
+            if ( !Gia_ObjIsRo(pGia, pObj) || !(Gia_ObjIsRo(pGia, pRepr)||Gia_ObjIsConst0(pRepr)) )
+                continue;
+        }
+        else if ( pData->fFfNdOnly )
+        {
+            if ( !Gia_ObjIsRo(pGia, pObj) && !(Gia_ObjIsRo(pGia, pRepr)||Gia_ObjIsConst0(pRepr)) )
+                continue;
+        }
+        if ( Gia_ObjRepr(pGia, i) == 0 )
+            Counter += Abc_NtkTestScorrWriteEquivConst( pNetlist, vId2Name, i, pFile, Gia_ObjPhase(pObj) );
+        else
+            Counter += Abc_NtkTestScorrWriteEquivPair( pNetlist, vId2Name, Gia_ObjRepr(pGia, i), i, pFile, 
+                Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) );
+    }
+    fclose( pFile );
+    printf( "%d pairs of sequentially equivalent nodes are written into file \"%s\".\n", Counter, pFileNameOut );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkTestScorrWriteEquivAig( Tst_Dat_t * pData )
+{
+    Abc_Ntk_t * pNetlist = pData->pNetlist;
+    Vec_Int_t * vId2Name = pData->vId2Name;
+    Aig_Man_t * pAig     = pData->pAig;
+    char * pFileNameOut  = pData->pFileNameOut;
+    FILE * pFile;
+    Aig_Obj_t * pObj, * pRepr;
+    int i, Counter = 0;
+    if ( pData->fDumpBmc )
+    {
+        pData->fDumpBmc = 0;
+        pFileNameOut = Abc_NtkBmcFileName( pFileNameOut );
+    }
+    pFile = fopen( pFileNameOut, "wb" );
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+        if ( (pRepr = Aig_ObjRepr(pAig, pObj)) == NULL )
+            continue;
+        if ( pData->fFlopOnly )
+        {
+            if ( !Saig_ObjIsLo(pAig, pObj) || !(Saig_ObjIsLo(pAig, pRepr)||pRepr==Aig_ManConst1(pAig)) )
+                continue;
+        }
+        else if ( pData->fFfNdOnly )
+        {
+            if ( !Saig_ObjIsLo(pAig, pObj) && !(Saig_ObjIsLo(pAig, pRepr)||pRepr==Aig_ManConst1(pAig)) )
+                continue;
+        }
+        if ( pRepr == Aig_ManConst1(pAig) )
+            Counter += Abc_NtkTestScorrWriteEquivConst( pNetlist, vId2Name, Aig_ObjId(pObj), pFile, Aig_ObjPhase(pObj) );
+        else
+            Counter += Abc_NtkTestScorrWriteEquivPair( pNetlist, vId2Name, Aig_ObjId(pRepr), Aig_ObjId(pObj), pFile, 
+                Aig_ObjPhase(pRepr) ^ Aig_ObjPhase(pObj) );
+    }
+    fclose( pFile );
+    printf( "%d pairs of sequentially equivalent nodes are written into file \"%s\".\n", Counter, pFileNameOut );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkTestScorr( char * pFileNameIn, char * pFileNameOut, int nStepsMax, int nBTLimit, int fNewAlgo, int fFlopOnly, int fFfNdOnly, int fVerbose )
+{
+    extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+    extern Abc_Ntk_t * Abc_NtkFromDarSeqSweep( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan );
+
+    FILE * pFile;
+    Tst_Dat_t Data, * pData = &Data;
+    Vec_Int_t * vId2Name;
+    Abc_Ntk_t * pNetlist, * pLogic, * pStrash, * pResult;
+    Aig_Man_t * pAig, * pTempAig;
+    Gia_Man_t * pGia, * pTempGia;
+//    int Counter = 0;
+    // check the files
+    pFile = fopen( pFileNameIn, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Input file \"%s\" cannot be opened.\n", pFileNameIn );
+        return NULL;
+    }
+    fclose( pFile );
+    // check the files
+    pFile = fopen( pFileNameOut, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Output file \"%s\" cannot be opened.\n", pFileNameOut );
+        return NULL;
+    }
+    fclose( pFile );
+    // derive AIG for signal correspondence
+    pNetlist = Io_ReadNetlist( pFileNameIn, Io_ReadFileType(pFileNameIn), 1 );
+    if ( pNetlist == NULL )
+    {
+        printf( "Reading input file \"%s\" has failed.\n", pFileNameIn );
+        return NULL;
+    }
+    pLogic = Abc_NtkToLogic( pNetlist );
+    if ( pLogic == NULL )
+    {
+        Abc_NtkDelete( pNetlist );
+        printf( "Deriving logic network from input file %s has failed.\n", pFileNameIn );
+        return NULL;
+    }
+    if ( Extra_FileIsType( pFileNameIn, ".bench", ".BENCH", NULL ) )
+    {
+        // get the init file name
+        char * pFileNameInit = Extra_FileNameGenericAppend( pLogic->pSpec, ".init" );
+        pFile = fopen( pFileNameInit, "rb" );
+        if ( pFile == NULL )
+        {
+            printf( "Init file \"%s\" cannot be opened.\n", pFileNameInit );
+            return NULL;
+        }
+        Io_ReadBenchInit( pLogic, pFileNameInit );
+        Abc_NtkConvertDcLatches( pLogic );
+        if ( fVerbose )
+            printf( "Initial state was derived from file \"%s\".\n", pFileNameInit );
+    }
+    pStrash = Abc_NtkStrash( pLogic, 0, 1, 0 );
+    if ( pStrash == NULL )
+    {
+        Abc_NtkDelete( pLogic );
+        Abc_NtkDelete( pNetlist );
+        printf( "Deriving strashed network from input file %s has failed.\n", pFileNameIn );
+        return NULL;
+    }
+    pAig = Abc_NtkToDar( pStrash, 0, 1 ); // performs "zero" internally
+    // the newer computation (&scorr)
+    if ( fNewAlgo )
+    {
+        Cec_ParCor_t CorPars, * pCorPars = &CorPars;
+        Cec_ManCorSetDefaultParams( pCorPars );
+        pCorPars->nBTLimit  = nBTLimit;
+        pCorPars->nStepsMax = nStepsMax;
+        pCorPars->fVerbose  = fVerbose;
+        pCorPars->fUseCSat  = 1;
+        pGia = Gia_ManFromAig( pAig );
+        // prepare the data-structure
+        memset( pData, 0, sizeof(Tst_Dat_t) );
+        pData->pNetlist     = pNetlist;
+        pData->pAig         = NULL;
+        pData->pGia         = pGia;
+        pData->vId2Name     = vId2Name = Abc_NtkMapGiaIntoNameId( pNetlist, pAig, pGia );
+        pData->pFileNameOut = pFileNameOut;
+        pData->fFlopOnly    = fFlopOnly;
+        pData->fFfNdOnly    = fFfNdOnly;
+        pData->fDumpBmc     = 1;
+        pCorPars->pData     = pData;
+        pCorPars->pFunc     = (void *)Abc_NtkTestScorrWriteEquivGia;
+        // call signal correspondence
+        pTempGia = Cec_ManLSCorrespondence( pGia, pCorPars );
+        pTempAig = Gia_ManToAigSimple( pTempGia );
+        Gia_ManStop( pTempGia );
+        Gia_ManStop( pGia );
+    }
+    // the older computation (scorr)
+    else
+    {
+        Ssw_Pars_t SswPars, * pSswPars = &SswPars;
+        Ssw_ManSetDefaultParams( pSswPars );
+        pSswPars->nBTLimit  = nBTLimit;
+        pSswPars->nStepsMax = nStepsMax;
+        pSswPars->fVerbose  = fVerbose;
+        // preSswPare the data-structure
+        memset( pData, 0, sizeof(Tst_Dat_t) );
+        pData->pNetlist     = pNetlist;
+        pData->pAig         = pAig;
+        pData->pGia         = NULL;
+        pData->vId2Name     = vId2Name = Abc_NtkMapGiaIntoNameId( pNetlist, pAig, NULL );
+        pData->pFileNameOut = pFileNameOut;
+        pData->fFlopOnly    = fFlopOnly;
+        pData->fFfNdOnly    = fFfNdOnly;
+        pData->fDumpBmc     = 1;
+        pSswPars->pData     = pData;
+        pSswPars->pFunc     = (void *)Abc_NtkTestScorrWriteEquivAig;
+        // call signal correspondence
+        pTempAig = Ssw_SignalCorrespondence( pAig, pSswPars );
+    }
+    // create the resulting AIG
+    pResult = Abc_NtkFromDarSeqSweep( pStrash, pTempAig );
+    // cleanup
+    Vec_IntFree( vId2Name );
+    Aig_ManStop( pAig );
+    Aig_ManStop( pTempAig );
+    Abc_NtkDelete( pStrash );
+    Abc_NtkDelete( pLogic );
+    Abc_NtkDelete( pNetlist );
+    return pResult;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcSense.c b/abc-build/src/base/abci/abcSense.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcSense.c
@@ -0,0 +1,216 @@
+/**CFile****************************************************************
+
+  FileName    [abcSense.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "proof/fraig/fraig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Copies the topmost levels of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkSensitivityMiter_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode )
+{
+    assert( !Abc_ObjIsComplement(pNode) );
+    if ( pNode->pCopy )
+        return pNode->pCopy;
+    Abc_NtkSensitivityMiter_rec( pNtkNew, Abc_ObjFanin0(pNode) );
+    Abc_NtkSensitivityMiter_rec( pNtkNew, Abc_ObjFanin1(pNode) );
+    return pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates miter for the sensitivity analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkSensitivityMiter( Abc_Ntk_t * pNtk, int iVar )
+{
+    Abc_Ntk_t * pMiter;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj, * pNext, * pFanin, * pOutput, * pObjNew;
+    int i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( iVar < Abc_NtkCiNum(pNtk) );
+
+    // duplicate the network
+    pMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    pMiter->pName = Extra_UtilStrsav(pNtk->pName);
+    pMiter->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+
+    // assign the PIs
+    Abc_NtkCleanCopy( pNtk );
+    Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pMiter);
+    Abc_AigConst1(pNtk)->pData = Abc_AigConst1(pMiter);
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        pObj->pCopy = Abc_NtkCreatePi( pMiter );
+        pObj->pData = pObj->pCopy;
+    }
+    Abc_NtkAddDummyPiNames( pMiter );
+
+    // assign the cofactors of the CI node to be constants
+    pObj = Abc_NtkCi( pNtk, iVar );
+    pObj->pCopy = Abc_ObjNot( Abc_AigConst1(pMiter) ); 
+    pObj->pData = Abc_AigConst1(pMiter); 
+
+    // collect the internal nodes
+    vNodes = Abc_NtkDfsReverseNodes( pNtk, &pObj, 1 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        for ( pNext = pObj? pObj->pCopy : pObj; pObj; pObj = pNext, pNext = pObj? pObj->pCopy : pObj )
+        {
+            pFanin = Abc_ObjFanin0(pObj);
+            if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+                pFanin->pData = Abc_NtkSensitivityMiter_rec( pMiter, pFanin );
+            pFanin = Abc_ObjFanin1(pObj);
+            if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+                pFanin->pData = Abc_NtkSensitivityMiter_rec( pMiter, pFanin );
+            pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pMiter->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+            pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pMiter->pManFunc, Abc_ObjChild0Data(pObj), Abc_ObjChild1Data(pObj) );
+        }
+    }
+    Vec_PtrFree( vNodes );
+
+    // update the affected COs
+    pOutput = Abc_ObjNot( Abc_AigConst1(pMiter) ); 
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        if ( !Abc_NodeIsTravIdCurrent(pObj) )
+            continue;
+        // get the result of quantification
+        if ( i == Abc_NtkCoNum(pNtk) - 1 )
+        {
+            pOutput = Abc_AigAnd( (Abc_Aig_t *)pMiter->pManFunc, pOutput, Abc_ObjChild0Data(pObj) );
+            pOutput = Abc_AigAnd( (Abc_Aig_t *)pMiter->pManFunc, pOutput, Abc_ObjChild0Copy(pObj) );
+        }
+        else
+        {
+            pNext   = Abc_AigXor( (Abc_Aig_t *)pMiter->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Data(pObj) );
+            pOutput = Abc_AigOr( (Abc_Aig_t *)pMiter->pManFunc, pOutput, pNext );
+        }
+    }
+    // add the PO node and name
+    pObjNew = Abc_NtkCreatePo(pMiter);
+    Abc_ObjAddFanin( pObjNew, pOutput );
+    Abc_ObjAssignName( pObjNew, "miter", NULL );
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pMiter ) )
+    {
+        printf( "Abc_NtkSensitivityMiter: The network check has failed.\n" );
+        Abc_NtkDelete( pMiter );
+        return NULL;
+    }
+    return pMiter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computing sensitivity of POs to POs under constraints.]
+
+  Description [The input network is a combinatonal AIG. The last output
+  is a constraint. The procedure returns the list of number of PIs, 
+  such that at least one PO depends on this PI, under the constraint.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkSensitivity( Abc_Ntk_t * pNtk, int nConfLim, int fVerbose )
+{
+    ProgressBar * pProgress;
+    Prove_Params_t Params, * pParams = &Params;
+    Vec_Int_t * vResult = NULL;
+    Abc_Ntk_t * pMiter;
+    Abc_Obj_t * pObj;
+    int RetValue, i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( Abc_NtkLatchNum(pNtk) == 0 );
+    // set up solving parameters
+    Prove_ParamsSetDefault( pParams );
+    pParams->nItersMax = 3;
+    pParams->nMiteringLimitLast = nConfLim;
+    // iterate through the PIs
+    vResult = Vec_IntAlloc( 100 );
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCiNum(pNtk) );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        // generate the sensitivity miter
+        pMiter = Abc_NtkSensitivityMiter( pNtk, i );
+        // solve the miter using CEC engine
+        RetValue = Abc_NtkIvyProve( &pMiter, pParams );
+        if ( RetValue == -1 ) // undecided
+            Vec_IntPush( vResult, i );
+        else if ( RetValue == 0 )
+        {
+            int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiter, pMiter->pModel );
+            if ( pSimInfo[0] != 1 )
+                printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" );
+//            else
+//                printf( "Networks are NOT EQUIVALENT.\n" );
+            ABC_FREE( pSimInfo );
+            Vec_IntPush( vResult, i );
+        }
+        Abc_NtkDelete( pMiter );
+    }
+    Extra_ProgressBarStop( pProgress );
+    if ( fVerbose )
+    {
+        printf( "The outputs are sensitive to %d (out of %d) inputs:\n", 
+            Vec_IntSize(vResult), Abc_NtkCiNum(pNtk) );
+        Vec_IntForEachEntry( vResult, RetValue, i )
+            printf( "%d ", RetValue );
+        printf( "\n" );
+    }
+    return vResult;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcSpeedup.c b/abc-build/src/base/abci/abcSpeedup.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcSpeedup.c
@@ -0,0 +1,965 @@
+/**CFile****************************************************************
+
+  FileName    [abcSpeedup.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Delay trace and speedup.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcSpeedup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/main.h"
+#include "map/if/if.h"
+#include "aig/aig/aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline float Abc_ObjArrival( Abc_Obj_t * pNode )                 { return pNode->pNtk->pLutTimes[3*pNode->Id+0]; }
+static inline float Abc_ObjRequired( Abc_Obj_t * pNode )                { return pNode->pNtk->pLutTimes[3*pNode->Id+1]; }
+static inline float Abc_ObjSlack( Abc_Obj_t * pNode )                   { return pNode->pNtk->pLutTimes[3*pNode->Id+2]; }
+
+static inline void  Abc_ObjSetArrival( Abc_Obj_t * pNode, float Time )  { pNode->pNtk->pLutTimes[3*pNode->Id+0] = Time; }
+static inline void  Abc_ObjSetRequired( Abc_Obj_t * pNode, float Time ) { pNode->pNtk->pLutTimes[3*pNode->Id+1] = Time; }
+static inline void  Abc_ObjSetSlack( Abc_Obj_t * pNode, float Time )    { pNode->pNtk->pLutTimes[3*pNode->Id+2] = Time; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts the pins in the decreasing order of delays.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDelayTraceSortPins( Abc_Obj_t * pNode, int * pPinPerm, float * pPinDelays )
+{
+    Abc_Obj_t * pFanin;
+    int i, j, best_i, temp;
+    // start the trivial permutation and collect pin delays
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        pPinPerm[i] = i;
+        pPinDelays[i] = Abc_ObjArrival(pFanin);
+    }
+    // selection sort the pins in the decreasible order of delays
+    // this order will match the increasing order of LUT input pins
+    for ( i = 0; i < Abc_ObjFaninNum(pNode)-1; i++ )
+    {
+        best_i = i;
+        for ( j = i+1; j < Abc_ObjFaninNum(pNode); j++ )
+            if ( pPinDelays[pPinPerm[j]] > pPinDelays[pPinPerm[best_i]] )
+                best_i = j;
+        if ( best_i == i )
+            continue;
+        temp = pPinPerm[i]; 
+        pPinPerm[i] = pPinPerm[best_i]; 
+        pPinPerm[best_i] = temp;
+    }
+    // verify
+    assert( Abc_ObjFaninNum(pNode) == 0 || pPinPerm[0] < Abc_ObjFaninNum(pNode) );
+    for ( i = 1; i < Abc_ObjFaninNum(pNode); i++ )
+    {
+        assert( pPinPerm[i] < Abc_ObjFaninNum(pNode) );
+        assert( pPinDelays[pPinPerm[i-1]] >= pPinDelays[pPinPerm[i]] );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Abc_NtkDelayTraceLut( Abc_Ntk_t * pNtk, int fUseLutLib )
+{
+    int fUseSorting = 1;
+    int pPinPerm[32];
+    float pPinDelays[32];
+    If_LibLut_t * pLutLib;
+    Abc_Obj_t * pNode, * pFanin;
+    Vec_Ptr_t * vNodes;
+    float tArrival, tRequired, tSlack, * pDelays;
+    int i, k;
+
+    assert( Abc_NtkIsLogic(pNtk) );
+    // get the library
+    pLutLib = fUseLutLib?  (If_LibLut_t *)Abc_FrameReadLibLut() : NULL;
+    if ( pLutLib && pLutLib->LutMax < Abc_NtkGetFaninMax(pNtk) )
+    {
+        printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", 
+            pLutLib->LutMax, Abc_NtkGetFaninMax(pNtk) );
+        return -ABC_INFINITY;
+    }
+
+    // initialize the arrival times
+    ABC_FREE( pNtk->pLutTimes );
+    pNtk->pLutTimes = ABC_ALLOC( float, 3 * Abc_NtkObjNumMax(pNtk) );
+    for ( i = 0; i < Abc_NtkObjNumMax(pNtk); i++ )
+    {
+        pNtk->pLutTimes[3*i+0] = pNtk->pLutTimes[3*i+2] = 0;
+        pNtk->pLutTimes[3*i+1] = ABC_INFINITY;
+    }
+
+    // propagate arrival times
+    vNodes = Abc_NtkDfs( pNtk, 1 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        tArrival = -ABC_INFINITY;
+        if ( pLutLib == NULL )
+        {
+            Abc_ObjForEachFanin( pNode, pFanin, k )
+                if ( tArrival < Abc_ObjArrival(pFanin) + 1.0 )
+                    tArrival = Abc_ObjArrival(pFanin) + 1.0;
+        }
+        else if ( !pLutLib->fVarPinDelays )
+        {
+            pDelays = pLutLib->pLutDelays[Abc_ObjFaninNum(pNode)];
+            Abc_ObjForEachFanin( pNode, pFanin, k )
+                if ( tArrival < Abc_ObjArrival(pFanin) + pDelays[0] )
+                    tArrival = Abc_ObjArrival(pFanin) + pDelays[0];
+        }
+        else
+        {
+            pDelays = pLutLib->pLutDelays[Abc_ObjFaninNum(pNode)];
+            if ( fUseSorting )
+            {
+                Abc_NtkDelayTraceSortPins( pNode, pPinPerm, pPinDelays );
+                Abc_ObjForEachFanin( pNode, pFanin, k ) 
+                    if ( tArrival < Abc_ObjArrival(Abc_ObjFanin(pNode,pPinPerm[k])) + pDelays[k] )
+                        tArrival = Abc_ObjArrival(Abc_ObjFanin(pNode,pPinPerm[k])) + pDelays[k];
+            }
+            else
+            {
+                Abc_ObjForEachFanin( pNode, pFanin, k )
+                    if ( tArrival < Abc_ObjArrival(pFanin) + pDelays[k] )
+                        tArrival = Abc_ObjArrival(pFanin) + pDelays[k];
+            }
+        }
+        if ( Abc_ObjFaninNum(pNode) == 0 )
+            tArrival = 0.0;
+        Abc_ObjSetArrival( pNode, tArrival );
+    }
+    Vec_PtrFree( vNodes );
+
+    // get the latest arrival times
+    tArrival = -ABC_INFINITY;
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        if ( tArrival < Abc_ObjArrival(Abc_ObjFanin0(pNode)) )
+            tArrival = Abc_ObjArrival(Abc_ObjFanin0(pNode));
+
+    // initialize the required times
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        if ( Abc_ObjRequired(Abc_ObjFanin0(pNode)) > tArrival )
+            Abc_ObjSetRequired( Abc_ObjFanin0(pNode), tArrival );
+
+    // propagate the required times
+    vNodes = Abc_NtkDfsReverse( pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( pLutLib == NULL )
+        {
+            tRequired = Abc_ObjRequired(pNode) - (float)1.0;
+            Abc_ObjForEachFanin( pNode, pFanin, k )
+                if ( Abc_ObjRequired(pFanin) > tRequired )
+                    Abc_ObjSetRequired( pFanin, tRequired );
+        }
+        else if ( !pLutLib->fVarPinDelays )
+        {
+            pDelays = pLutLib->pLutDelays[Abc_ObjFaninNum(pNode)];
+            tRequired = Abc_ObjRequired(pNode) - pDelays[0];
+            Abc_ObjForEachFanin( pNode, pFanin, k )
+                if ( Abc_ObjRequired(pFanin) > tRequired )
+                    Abc_ObjSetRequired( pFanin, tRequired );
+        }
+        else 
+        {
+            pDelays = pLutLib->pLutDelays[Abc_ObjFaninNum(pNode)];
+            if ( fUseSorting )
+            {
+                Abc_NtkDelayTraceSortPins( pNode, pPinPerm, pPinDelays );
+                Abc_ObjForEachFanin( pNode, pFanin, k )
+                {
+                    tRequired = Abc_ObjRequired(pNode) - pDelays[k];
+                    if ( Abc_ObjRequired(Abc_ObjFanin(pNode,pPinPerm[k])) > tRequired )
+                        Abc_ObjSetRequired( Abc_ObjFanin(pNode,pPinPerm[k]), tRequired );
+                }
+            }
+            else
+            {
+                Abc_ObjForEachFanin( pNode, pFanin, k )
+                {
+                    tRequired = Abc_ObjRequired(pNode) - pDelays[k];
+                    if ( Abc_ObjRequired(pFanin) > tRequired )
+                        Abc_ObjSetRequired( pFanin, tRequired );
+                }
+            }
+        }
+        // set slack for this object
+        tSlack = Abc_ObjRequired(pNode) - Abc_ObjArrival(pNode);
+        assert( tSlack + 0.001 > 0.0 );
+        Abc_ObjSetSlack( pNode, tSlack < 0.0 ? 0.0 : tSlack );
+    }
+    Vec_PtrFree( vNodes );
+    return tArrival;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Delay tracing of the LUT mapped network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDelayTracePrint( Abc_Ntk_t * pNtk, int fUseLutLib, int fVerbose )
+{
+    Abc_Obj_t * pNode;
+    If_LibLut_t * pLutLib;
+    int i, Nodes, * pCounters;
+    float tArrival, tDelta, nSteps, Num;
+    // get the library
+    pLutLib = fUseLutLib?  (If_LibLut_t *)Abc_FrameReadLibLut() : NULL;
+    if ( pLutLib && pLutLib->LutMax < Abc_NtkGetFaninMax(pNtk) )
+    {
+        printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", 
+            pLutLib->LutMax, Abc_NtkGetFaninMax(pNtk) );
+        return;
+    }
+    // decide how many steps
+    nSteps = fUseLutLib ? 20 : Abc_NtkLevel(pNtk);
+    pCounters = ABC_ALLOC( int, nSteps + 1 );
+    memset( pCounters, 0, sizeof(int)*(nSteps + 1) );
+    // perform delay trace
+    tArrival = Abc_NtkDelayTraceLut( pNtk, fUseLutLib );
+    tDelta = tArrival / nSteps;
+    // count how many nodes have slack in the corresponding intervals
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        if ( Abc_ObjFaninNum(pNode) == 0 )
+            continue;
+        Num = Abc_ObjSlack(pNode) / tDelta;
+        assert( Num >=0 && Num <= nSteps );
+        pCounters[(int)Num]++;
+    }
+    // print the results
+    printf( "Max delay = %6.2f. Delay trace using %s model:\n", tArrival, fUseLutLib? "LUT library" : "unit-delay" );
+    Nodes = 0;
+    for ( i = 0; i < nSteps; i++ )
+    {
+        Nodes += pCounters[i];
+        printf( "%3d %s : %5d  (%6.2f %%)\n", fUseLutLib? 5*(i+1) : i+1, 
+            fUseLutLib? "%":"lev", Nodes, 100.0*Nodes/Abc_NtkNodeNum(pNtk) );
+    }
+    ABC_FREE( pCounters );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pOld is in the TFI of pNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_AigCheckTfi_rec( Abc_Obj_t * pNode, Abc_Obj_t * pOld )
+{
+    // check the trivial cases
+    if ( pNode == NULL )
+        return 0;
+    if ( Abc_ObjIsCi(pNode) )
+        return 0;
+    if ( pNode == pOld )
+        return 1;
+    // skip the visited node
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return 0;
+    Abc_NodeSetTravIdCurrent( pNode );
+    // check the children
+    if ( Abc_AigCheckTfi_rec( Abc_ObjFanin0(pNode), pOld ) )
+        return 1;
+    if ( Abc_AigCheckTfi_rec( Abc_ObjFanin1(pNode), pOld ) )
+        return 1;
+    // check equivalent nodes
+    return Abc_AigCheckTfi_rec( (Abc_Obj_t *)pNode->pData, pOld );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pOld is in the TFI of pNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_AigCheckTfi( Abc_Obj_t * pNew, Abc_Obj_t * pOld )
+{
+    assert( !Abc_ObjIsComplement(pNew) );
+    assert( !Abc_ObjIsComplement(pOld) );
+    Abc_NtkIncrementTravId( pNew->pNtk );
+    return Abc_AigCheckTfi_rec( pNew, pOld );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds strashed nodes for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkSpeedupNode_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    if ( Abc_NodeIsTravIdCurrent(pNode) )
+        return 1;
+    if ( Abc_ObjIsCi(pNode) )
+        return 0;
+    assert( Abc_ObjIsNode(pNode) );
+    Abc_NodeSetTravIdCurrent( pNode );
+    if ( !Abc_NtkSpeedupNode_rec( Abc_ObjFanin0(pNode), vNodes ) )
+        return 0;
+    if ( !Abc_NtkSpeedupNode_rec( Abc_ObjFanin1(pNode), vNodes ) )
+        return 0;
+    Vec_PtrPush( vNodes, pNode );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds strashed nodes for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSpeedupNode( Abc_Ntk_t * pNtk, Abc_Ntk_t * pAig, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vTimes )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj, * pObj2, * pAnd;
+    Abc_Obj_t * ppCofs[32];
+    int nCofs, i, k, nSkip;
+
+    // quit of regulars are the same
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj2, k )
+        if ( i != k && Abc_ObjRegular(pObj->pCopy) == Abc_ObjRegular(pObj2->pCopy) )
+        {
+//            printf( "Identical after structural hashing!!!\n" );
+            return;
+        }
+
+    // collect the AIG nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    Abc_NtkIncrementTravId( pAig );
+    Abc_NodeSetTravIdCurrent( Abc_AigConst1(pAig) );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
+    {
+        pAnd = pObj->pCopy;
+        Abc_NodeSetTravIdCurrent( Abc_ObjRegular(pAnd) );
+    }
+    // traverse from the root node
+    pAnd = pNode->pCopy;
+    if ( !Abc_NtkSpeedupNode_rec( Abc_ObjRegular(pAnd), vNodes ) )
+    {
+//        printf( "Bad node!!!\n" );
+        Vec_PtrFree( vNodes );
+        return;
+    }
+
+    // derive cofactors
+    nCofs = (1 << Vec_PtrSize(vTimes));
+    for ( i = 0; i < nCofs; i++ )
+    {
+        Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, k )
+        {
+            pAnd = pObj->pCopy;
+            Abc_ObjRegular(pAnd)->pCopy = Abc_ObjRegular(pAnd);
+        }
+        Vec_PtrForEachEntry( Abc_Obj_t *, vTimes, pObj, k )
+        {
+            pAnd = pObj->pCopy;
+            Abc_ObjRegular(pAnd)->pCopy = Abc_ObjNotCond( Abc_AigConst1(pAig), ((i & (1<<k)) == 0) );
+        }
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, k )
+            pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+        // save the result
+        pAnd = pNode->pCopy;
+        ppCofs[i] = Abc_ObjNotCond( Abc_ObjRegular(pAnd)->pCopy, Abc_ObjIsComplement(pAnd) );
+    }
+    Vec_PtrFree( vNodes );
+
+//Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), ppCofs[0] );
+//Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), ppCofs[1] );
+
+    // collect the resulting tree
+    Vec_PtrForEachEntry( Abc_Obj_t *, vTimes, pObj, k )
+        for ( nSkip = (1<<k), i = 0; i < nCofs; i += 2*nSkip )
+        {
+            pAnd = pObj->pCopy;
+            ppCofs[i] = Abc_AigMux( (Abc_Aig_t *)pAig->pManFunc, Abc_ObjRegular(pAnd), ppCofs[i+nSkip], ppCofs[i] );
+        }
+//Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), ppCofs[0] );
+
+    // create choice node
+    pAnd = Abc_ObjRegular(pNode->pCopy); // repr
+    pObj = Abc_ObjRegular(ppCofs[0]);    // new
+    if ( pAnd->pData == NULL && pObj->pData == NULL && !Abc_AigNodeIsConst(pObj) && !Abc_AigCheckTfi(pObj, pAnd) )
+    {
+        pObj->pData = pAnd->pData;
+        pAnd->pData = pObj;
+    }
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determines timing-critical edges of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Abc_NtkDelayTraceTCEdges( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, float tDelta, int fUseLutLib )
+{
+    int pPinPerm[32];
+    float pPinDelays[32];
+    If_LibLut_t * pLutLib;
+    Abc_Obj_t * pFanin;
+    unsigned uResult = 0;
+    float tRequired, * pDelays;
+    int k;
+    pLutLib = fUseLutLib?  (If_LibLut_t *)Abc_FrameReadLibLut() : NULL;
+    tRequired = Abc_ObjRequired(pNode);
+    if ( pLutLib == NULL )
+    {
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+            if ( tRequired < Abc_ObjArrival(pFanin) + 1.0 + tDelta )
+                uResult |= (1 << k);
+    }
+    else if ( !pLutLib->fVarPinDelays )
+    {
+        pDelays = pLutLib->pLutDelays[Abc_ObjFaninNum(pNode)];
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+            if ( tRequired < Abc_ObjArrival(pFanin) + pDelays[0] + tDelta )
+                uResult |= (1 << k);
+    }
+    else
+    {
+        pDelays = pLutLib->pLutDelays[Abc_ObjFaninNum(pNode)];
+        Abc_NtkDelayTraceSortPins( pNode, pPinPerm, pPinDelays );
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+            if ( tRequired < Abc_ObjArrival(Abc_ObjFanin(pNode,pPinPerm[k])) + pDelays[k] + tDelta )
+                uResult |= (1 << pPinPerm[k]);
+    }
+    return uResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds choices to speed up the network by the given percentage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkSpeedup( Abc_Ntk_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose )
+{
+    Abc_Ntk_t * pNtkNew;
+    Vec_Ptr_t * vTimeCries, * vTimeFanins;
+    Abc_Obj_t * pNode, * pFanin, * pFanin2;
+    float tDelta, tArrival;
+    int i, k, k2, Counter, CounterRes, nTimeCris;
+    unsigned * puTCEdges;
+    // perform delay trace
+    tArrival = Abc_NtkDelayTraceLut( pNtk, fUseLutLib );
+    tDelta = fUseLutLib ? tArrival*Percentage/100.0 : 1.0;
+    if ( fVerbose )
+    {
+        printf( "Max delay = %.2f. Delta = %.2f. ", tArrival, tDelta );
+        printf( "Using %s model. ", fUseLutLib? "LUT library" : "unit-delay" );
+        if ( fUseLutLib )
+            printf( "Percentage = %d. ", Percentage );
+        printf( "\n" );
+    }
+    // mark the timing critical nodes and edges
+    puTCEdges = ABC_ALLOC( unsigned, Abc_NtkObjNumMax(pNtk) );
+    memset( puTCEdges, 0, sizeof(unsigned) * Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        if ( Abc_ObjSlack(pNode) >= tDelta )
+            continue;
+        puTCEdges[pNode->Id] = Abc_NtkDelayTraceTCEdges( pNtk, pNode, tDelta, fUseLutLib );
+    }
+    if ( fVerbose )
+    {
+        Counter = CounterRes = 0;
+        Abc_NtkForEachNode( pNtk, pNode, i )
+        {
+            Abc_ObjForEachFanin( pNode, pFanin, k )
+                if ( !Abc_ObjIsCi(pFanin) && Abc_ObjSlack(pFanin) < tDelta )
+                    Counter++;
+            CounterRes += Extra_WordCountOnes( puTCEdges[pNode->Id] );
+        }
+        printf( "Edges: Total = %7d. 0-slack = %7d. Critical = %7d. Ratio = %4.2f\n", 
+            Abc_NtkGetTotalFanins(pNtk), Counter, CounterRes, 1.0*CounterRes/Counter );
+    }
+    // start the resulting network
+    pNtkNew = Abc_NtkStrash( pNtk, 0, 1, 0 );
+
+    // collect nodes to be used for resynthesis
+    Counter = CounterRes = 0;
+    vTimeCries = Vec_PtrAlloc( 16 );
+    vTimeFanins = Vec_PtrAlloc( 16 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        if ( Abc_ObjSlack(pNode) >= tDelta )
+            continue;
+        // count the number of non-PI timing-critical nodes
+        nTimeCris = 0;
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+            if ( !Abc_ObjIsCi(pFanin) && (puTCEdges[pNode->Id] & (1<<k)) )
+                nTimeCris++;
+        if ( !fVeryVerbose && nTimeCris == 0 )
+            continue;
+        Counter++;
+        // count the total number of timing critical second-generation nodes
+        Vec_PtrClear( vTimeCries );
+        if ( nTimeCris )
+        {
+            Abc_ObjForEachFanin( pNode, pFanin, k )
+                if ( !Abc_ObjIsCi(pFanin) && (puTCEdges[pNode->Id] & (1<<k)) )
+                    Abc_ObjForEachFanin( pFanin, pFanin2, k2 )
+                        if ( puTCEdges[pFanin->Id] & (1<<k2) )
+                            Vec_PtrPushUnique( vTimeCries, pFanin2 );
+        }
+//        if ( !fVeryVerbose && (Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree) )
+        if ( (Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree) )
+            continue;
+        CounterRes++;
+        // collect second generation nodes
+        Vec_PtrClear( vTimeFanins );
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+        {
+            if ( Abc_ObjIsCi(pFanin) )
+                Vec_PtrPushUnique( vTimeFanins, pFanin );
+            else
+                Abc_ObjForEachFanin( pFanin, pFanin2, k2 )
+                    Vec_PtrPushUnique( vTimeFanins, pFanin2 );                    
+        }
+        // print the results
+        if ( fVeryVerbose )
+        {
+        printf( "%5d Node %5d : %d %2d %2d  ", Counter, pNode->Id, 
+            nTimeCris, Vec_PtrSize(vTimeCries), Vec_PtrSize(vTimeFanins) );
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+            printf( "%d(%.2f)%s ", pFanin->Id, Abc_ObjSlack(pFanin), (puTCEdges[pNode->Id] & (1<<k))? "*":"" );
+        printf( "\n" );
+        }
+        // add the node to choices
+        if ( Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree )
+            continue;
+        // order the fanins in the increasing order of criticalily
+        if ( Vec_PtrSize(vTimeCries) > 1 )
+        {
+            pFanin = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 0 );
+            pFanin2 = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 1 );
+            if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) )
+            {
+                Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 );
+                Vec_PtrWriteEntry( vTimeCries, 1, pFanin );
+            }
+        }
+        if ( Vec_PtrSize(vTimeCries) > 2 )
+        {
+            pFanin = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 1 );
+            pFanin2 = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 2 );
+            if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) )
+            {
+                Vec_PtrWriteEntry( vTimeCries, 1, pFanin2 );
+                Vec_PtrWriteEntry( vTimeCries, 2, pFanin );
+            }
+            pFanin = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 0 );
+            pFanin2 = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 1 );
+            if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) )
+            {
+                Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 );
+                Vec_PtrWriteEntry( vTimeCries, 1, pFanin );
+            }
+        }
+        // add choice
+        Abc_NtkSpeedupNode( pNtk, pNtkNew, pNode, vTimeFanins, vTimeCries );
+    }
+    Vec_PtrFree( vTimeCries );
+    Vec_PtrFree( vTimeFanins );
+    ABC_FREE( puTCEdges );
+    if ( fVerbose )
+        printf( "Nodes: Total = %7d. 0-slack = %7d. Workable = %7d. Ratio = %4.2f\n", 
+            Abc_NtkNodeNum(pNtk), Counter, CounterRes, 1.0*CounterRes/Counter ); 
+
+    // remove invalid choice nodes
+    Abc_AigForEachAnd( pNtkNew, pNode, i )
+        if ( pNode->pData )
+        {
+            if ( Abc_ObjFanoutNum((Abc_Obj_t *)pNode->pData) > 0 )
+                pNode->pData = NULL;
+        }
+
+    // return the result
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks nodes for power-optimization.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkPowerEstimate( Abc_Ntk_t * pNtk, int fProbOne )
+{
+    extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+    extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne );
+    Vec_Int_t * vProbs;
+    Vec_Int_t * vSwitching;
+    float * pProbability;
+    float * pSwitching;
+    Abc_Ntk_t * pNtkStr;
+    Aig_Man_t * pAig;
+    Aig_Obj_t * pObjAig;
+    Abc_Obj_t * pObjAbc, * pObjAbc2;
+    int i;
+    // start the resulting array
+    vProbs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
+    pProbability = (float *)vProbs->pArray;
+    // strash the network
+    pNtkStr = Abc_NtkStrash( pNtk, 0, 1, 0 );
+    Abc_NtkForEachObj( pNtk, pObjAbc, i )
+        if ( Abc_ObjRegular((Abc_Obj_t *)pObjAbc->pTemp)->Type == ABC_FUNC_NONE )
+            pObjAbc->pTemp = NULL;
+    // map network into an AIG
+    pAig = Abc_NtkToDar( pNtkStr, 0, (int)(Abc_NtkLatchNum(pNtk) > 0) );
+    vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, fProbOne );
+    pSwitching = (float *)vSwitching->pArray;
+    Abc_NtkForEachObj( pNtk, pObjAbc, i )
+    {
+        if ( (pObjAbc2 = Abc_ObjRegular((Abc_Obj_t *)pObjAbc->pTemp)) && (pObjAig = Aig_Regular((Aig_Obj_t *)pObjAbc2->pTemp)) )
+            pProbability[pObjAbc->Id] = pSwitching[pObjAig->Id];
+    }
+    Vec_IntFree( vSwitching );
+    Aig_ManStop( pAig );
+    Abc_NtkDelete( pNtkStr );
+    return vProbs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks nodes for power-optimization.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPowerPrint( Abc_Ntk_t * pNtk, Vec_Int_t * vProbs )
+{
+    Abc_Obj_t * pObj;
+    float * pProb, TotalProb = 0.0, ProbThis, Probs[6] = {0.0};
+    int i, nNodes = 0, nEdges = 0, Counter[6] = {0};
+    pProb = (float *)vProbs->pArray;
+    assert( Vec_IntSize(vProbs) >= Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPi(pObj) )
+            continue;
+        nNodes++;
+        nEdges += Abc_ObjFanoutNum(pObj);
+        ProbThis = pProb[i] * Abc_ObjFanoutNum(pObj);
+        TotalProb += ProbThis;
+        assert( pProb[i] >= 0.0 && pProb[i] <= 1.0 );
+        if ( pProb[i] >= 0.5 )
+        {
+            Counter[5]++;
+            Probs[5] += ProbThis;
+        }
+        else if ( pProb[i] >= 0.4 )
+        {
+            Counter[4]++;
+            Probs[4] += ProbThis;
+        }
+        else if ( pProb[i] >= 0.3 )
+        {
+            Counter[3]++;
+            Probs[3] += ProbThis;
+        }
+        else if ( pProb[i] >= 0.2 )
+        {
+            Counter[2]++;
+            Probs[2] += ProbThis;
+        }
+        else if ( pProb[i] >= 0.1 )
+        {
+            Counter[1]++;
+            Probs[1] += ProbThis;
+        }
+        else 
+        {
+            Counter[0]++;
+            Probs[0] += ProbThis;
+        }
+    }
+    printf( "Node  distribution: " );
+    for ( i = 0; i < 6; i++ )
+        printf( "n%d%d = %6.2f%%  ", i, i+1, 100.0 * Counter[i]/nNodes );
+    printf( "\n" );
+    printf( "Power distribution: " );
+    for ( i = 0; i < 6; i++ )
+        printf( "p%d%d = %6.2f%%  ", i, i+1, 100.0 * Probs[i]/TotalProb );
+    printf( "\n" );
+    printf( "Total probs = %7.2f. ", TotalProb );
+    printf( "Total edges = %d. ", nEdges );
+    printf( "Average = %7.2f. ", TotalProb / nEdges );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determines timing-critical edges of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Abc_NtkPowerCriticalEdges( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, float Limit, Vec_Int_t * vProbs )
+{
+    Abc_Obj_t * pFanin;
+    float * pProb = (float *)vProbs->pArray;
+    unsigned uResult = 0;
+    int k;
+    Abc_ObjForEachFanin( pNode, pFanin, k )
+        if ( pProb[pFanin->Id] >= Limit )
+            uResult |= (1 << k);
+    return uResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds choices to speed up the network by the given percentage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkPowerdown( Abc_Ntk_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose )
+{
+    Abc_Ntk_t * pNtkNew;
+    Vec_Int_t * vProbs;
+    Vec_Ptr_t * vTimeCries, * vTimeFanins;
+    Abc_Obj_t * pNode, * pFanin, * pFanin2;
+    float * pProb, Limit;
+    int i, k, k2, Counter, CounterRes, nTimeCris;
+    unsigned * puPCEdges;
+    // compute the limit
+    Limit = 0.5 - (1.0 * Percentage / 100);
+    // perform computation of switching probability
+    vProbs = Abc_NtkPowerEstimate( pNtk, 0 );
+    pProb = (float *)vProbs->pArray;
+    // compute percentage of wires of each type
+    if ( fVerbose )
+        Abc_NtkPowerPrint( pNtk, vProbs );
+    // mark the power critical nodes and edges
+    puPCEdges = ABC_ALLOC( unsigned, Abc_NtkObjNumMax(pNtk) );
+    memset( puPCEdges, 0, sizeof(unsigned) * Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        if ( pProb[pNode->Id] < Limit )
+            continue;
+        puPCEdges[pNode->Id] = Abc_NtkPowerCriticalEdges( pNtk, pNode, Limit, vProbs );
+    }
+/*
+    if ( fVerbose )
+    {
+        Counter = CounterRes = 0;
+        Abc_NtkForEachNode( pNtk, pNode, i )
+        {
+            Counter += Abc_ObjFaninNum(pNode);
+            CounterRes += Extra_WordCountOnes( puPCEdges[pNode->Id] );
+        }
+        printf( "Edges: Total = %7d. Critical = %7d. Ratio = %4.2f\n", 
+            Counter, CounterRes, 1.0*CounterRes/Counter );
+    }
+*/
+    // start the resulting network
+    pNtkNew = Abc_NtkStrash( pNtk, 0, 1, 0 );
+
+    // collect nodes to be used for resynthesis
+    Counter = CounterRes = 0;
+    vTimeCries = Vec_PtrAlloc( 16 );
+    vTimeFanins = Vec_PtrAlloc( 16 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+//        if ( pProb[pNode->Id] < Limit )
+//            continue;
+        // count the number of non-PI power-critical nodes
+        nTimeCris = 0;
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+            if ( !Abc_ObjIsCi(pFanin) && (puPCEdges[pNode->Id] & (1<<k)) )
+                nTimeCris++;
+        if ( !fVeryVerbose && nTimeCris == 0 )
+            continue;
+        Counter++;
+        // count the total number of power-critical second-generation nodes
+        Vec_PtrClear( vTimeCries );
+        if ( nTimeCris )
+        {
+            Abc_ObjForEachFanin( pNode, pFanin, k )
+                if ( !Abc_ObjIsCi(pFanin) && (puPCEdges[pNode->Id] & (1<<k)) )
+                    Abc_ObjForEachFanin( pFanin, pFanin2, k2 )
+                        if ( puPCEdges[pFanin->Id] & (1<<k2) )
+                            Vec_PtrPushUnique( vTimeCries, pFanin2 );
+        }
+//        if ( !fVeryVerbose && (Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree) )
+        if ( (Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree) )
+            continue;
+        CounterRes++;
+        // collect second generation nodes
+        Vec_PtrClear( vTimeFanins );
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+        {
+            if ( Abc_ObjIsCi(pFanin) )
+                Vec_PtrPushUnique( vTimeFanins, pFanin );
+            else
+                Abc_ObjForEachFanin( pFanin, pFanin2, k2 )
+                    Vec_PtrPushUnique( vTimeFanins, pFanin2 );                    
+        }
+        // print the results
+        if ( fVeryVerbose )
+        {
+        printf( "%5d Node %5d : %d %2d %2d  ", Counter, pNode->Id, 
+            nTimeCris, Vec_PtrSize(vTimeCries), Vec_PtrSize(vTimeFanins) );
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+            printf( "%d(%.2f)%s ", pFanin->Id, pProb[pFanin->Id], (puPCEdges[pNode->Id] & (1<<k))? "*":"" );
+        printf( "\n" );
+        }
+        // add the node to choices
+        if ( Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree )
+            continue;
+        // order the fanins in the increasing order of criticalily
+        if ( Vec_PtrSize(vTimeCries) > 1 )
+        {
+            pFanin = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 0 );
+            pFanin2 = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 1 );
+//            if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) )
+            if ( pProb[pFanin->Id] > pProb[pFanin2->Id] )
+            {
+                Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 );
+                Vec_PtrWriteEntry( vTimeCries, 1, pFanin );
+            }
+        }
+        if ( Vec_PtrSize(vTimeCries) > 2 )
+        {
+            pFanin = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 1 );
+            pFanin2 = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 2 );
+//            if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) )
+            if ( pProb[pFanin->Id] > pProb[pFanin2->Id] )
+            {
+                Vec_PtrWriteEntry( vTimeCries, 1, pFanin2 );
+                Vec_PtrWriteEntry( vTimeCries, 2, pFanin );
+            }
+            pFanin = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 0 );
+            pFanin2 = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 1 );
+//            if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) )
+            if ( pProb[pFanin->Id] > pProb[pFanin2->Id] )
+            {
+                Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 );
+                Vec_PtrWriteEntry( vTimeCries, 1, pFanin );
+            }
+        }
+        // add choice
+        Abc_NtkSpeedupNode( pNtk, pNtkNew, pNode, vTimeFanins, vTimeCries );
+    }
+    Vec_PtrFree( vTimeCries );
+    Vec_PtrFree( vTimeFanins );
+    ABC_FREE( puPCEdges );
+    if ( fVerbose )
+        printf( "Nodes: Total = %7d. Power-critical = %7d. Workable = %7d. Ratio = %4.2f\n", 
+            Abc_NtkNodeNum(pNtk), Counter, CounterRes, 1.0*CounterRes/Counter ); 
+
+    // remove invalid choice nodes
+    Abc_AigForEachAnd( pNtkNew, pNode, i )
+        if ( pNode->pData )
+        {
+            if ( Abc_ObjFanoutNum((Abc_Obj_t *)pNode->pData) > 0 )
+                pNode->pData = NULL;
+        }
+
+    // return the result
+    Vec_IntFree( vProbs );
+    return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcStrash.c b/abc-build/src/base/abci/abcStrash.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcStrash.c
@@ -0,0 +1,849 @@
+/**CFile****************************************************************
+
+  FileName    [abcStrash.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Strashing of the current network.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "bool/dec/dec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reapplies structural hashing to the AIG.]
+
+  Description [Because of the structural hashing, this procedure should not 
+  change the number of nodes. It is useful to detect the bugs in the original AIG.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, int fCleanup )
+{
+//    extern int timeRetime;
+    Vec_Ptr_t * vNodes;
+    Abc_Ntk_t * pNtkAig;
+    Abc_Obj_t * pObj;
+    int i, nNodes;//, RetValue;
+    assert( Abc_NtkIsStrash(pNtk) );
+//timeRetime = Abc_Clock();
+    // print warning about choice nodes
+    if ( Abc_NtkGetChoiceNum( pNtk ) )
+        printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" );
+    // start the new network (constants and CIs of the old network will point to the their counterparts in the new network)
+    pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+    // restrash the nodes (assuming a topological order of the old network)
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+    Vec_PtrFree( vNodes );
+    // finalize the network
+    Abc_NtkFinalize( pNtk, pNtkAig );
+    // print warning about self-feed latches
+//    if ( Abc_NtkCountSelfFeedLatches(pNtkAig) )
+//        printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) );
+    // perform cleanup if requested
+    if ( fCleanup && (nNodes = Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc)) ) 
+    {
+//        printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes );
+    }
+    // duplicate EXDC 
+    if ( pNtk->pExdc )
+        pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pNtkAig ) )
+    {
+        printf( "Abc_NtkStrash: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkAig );
+        return NULL;
+    }
+//timeRetime = Abc_Clock() - timeRetime;
+//    if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) )
+//        printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue );
+    return pNtkAig;
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs structural hashing by generating random number.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkRestrashRandom_rec( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
+{
+    if ( Abc_NodeIsTravIdCurrent( pObj ) )
+        return;
+    Abc_NodeSetTravIdCurrent( pObj );
+    if ( !Abc_ObjIsNode(pObj) )
+        return;
+    if ( rand() & 1 )
+    {
+        Abc_NtkRestrashRandom_rec( pNtk, Abc_ObjFanin0(pObj) );
+        Abc_NtkRestrashRandom_rec( pNtk, Abc_ObjFanin1(pObj) );
+    }
+    else
+    {
+        Abc_NtkRestrashRandom_rec( pNtk, Abc_ObjFanin1(pObj) );
+        Abc_NtkRestrashRandom_rec( pNtk, Abc_ObjFanin0(pObj) );
+    }
+    pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reapplies structural hashing to the AIG.]
+
+  Description [Because of the structural hashing, this procedure should not 
+  change the number of nodes. It is useful to detect the bugs in the original AIG.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRestrashRandom( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkAig;
+    Abc_Obj_t * pObj;
+    int i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // print warning about choice nodes
+    if ( Abc_NtkGetChoiceNum( pNtk ) )
+        printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" );
+    // start the new network (constants and CIs of the old network will point to the their counterparts in the new network)
+    pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+    // restrash the nodes (assuming a topological order of the old network)
+    Abc_NtkIncrementTravId( pNtk );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Abc_NtkRestrashRandom_rec( pNtkAig, Abc_ObjFanin0(pObj) );
+    // finalize the network
+    Abc_NtkFinalize( pNtk, pNtkAig );
+    // duplicate EXDC 
+    if ( pNtk->pExdc )
+        pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pNtkAig ) )
+    {
+        printf( "Abc_NtkStrash: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkAig );
+        return NULL;
+    }
+    return pNtkAig;
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reapplies structural hashing to the AIG.]
+
+  Description [Because of the structural hashing, this procedure should not 
+  change the number of nodes. It is useful to detect the bugs in the original AIG.]
+               
+  SideEffects []
+ 
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRestrashZero( Abc_Ntk_t * pNtk, int fCleanup )
+{
+//    extern int timeRetime;
+    Abc_Ntk_t * pNtkAig;
+    Abc_Obj_t * pObj;
+    int i, nNodes;//, RetValue;
+    int Counter = 0;
+    assert( Abc_NtkIsStrash(pNtk) );
+//timeRetime = Abc_Clock();
+    // print warning about choice nodes
+    if ( Abc_NtkGetChoiceNum( pNtk ) )
+        printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" );
+    // start the new network (constants and CIs of the old network will point to the their counterparts in the new network)
+    pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+    // complement the 1-values registers
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+    {
+        if ( Abc_LatchIsInitDc(pObj) )
+            Counter++;
+        else if ( Abc_LatchIsInit1(pObj) )
+            Abc_ObjFanout0(pObj)->pCopy = Abc_ObjNot(Abc_ObjFanout0(pObj)->pCopy);
+    }
+    if ( Counter )
+    printf( "Converting %d flops from don't-care to zero initial value.\n", Counter );
+    // restrash the nodes (assuming a topological order of the old network)
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+    // finalize the network
+    Abc_NtkFinalize( pNtk, pNtkAig );
+    // complement the 1-valued registers
+    Abc_NtkForEachLatch( pNtkAig, pObj, i )
+        if ( Abc_LatchIsInit1(pObj) )
+        {
+            Abc_ObjXorFaninC( Abc_ObjFanin0(pObj), 0 );
+            // if latch has PO as one of its fanouts change latch name
+            if ( Abc_NodeFindCoFanout( Abc_ObjFanout0(pObj) ) )
+            {
+                Nm_ManDeleteIdName( pObj->pNtk->pManName, Abc_ObjFanout0(pObj)->Id );
+                Abc_ObjAssignName( Abc_ObjFanout0(pObj), Abc_ObjName(Abc_ObjFanout0(pObj)), "_inv" );
+            }
+        }
+    // set all constant-0 values
+    Abc_NtkForEachLatch( pNtkAig, pObj, i )
+        Abc_LatchSetInit0( pObj );
+
+    // print warning about self-feed latches
+//    if ( Abc_NtkCountSelfFeedLatches(pNtkAig) )
+//        printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) );
+    // perform cleanup if requested
+    if ( fCleanup && (nNodes = Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc)) ) 
+        printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes );
+    // duplicate EXDC 
+    if ( pNtk->pExdc )
+        pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+    // transfer name IDs
+    if ( pNtk->vNameIds )
+        Abc_NtkTransferNameIds( pNtk, pNtkAig );
+    if ( pNtk->vNameIds )
+        Abc_NtkUpdateNameIds( pNtkAig );
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pNtkAig ) )
+    {
+        printf( "Abc_NtkStrash: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkAig );
+        return NULL;
+    }
+//timeRetime = Abc_Clock() - timeRetime;
+//    if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) )
+//        printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue );
+    return pNtkAig;
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms logic network into structurally hashed AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, int fAllNodes, int fCleanup, int fRecord )
+{
+    Abc_Ntk_t * pNtkAig;
+    int nNodes;
+    assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
+    // consider the special case when the network is already structurally hashed
+    if ( Abc_NtkIsStrash(pNtk) )
+        return Abc_NtkRestrash( pNtk, fCleanup );
+    // convert the node representation in the logic network to the AIG form
+    if ( !Abc_NtkToAig(pNtk) )
+    {
+        printf( "Converting to AIGs has failed.\n" );
+        return NULL;
+    }
+    // perform strashing
+//    Abc_NtkCleanCopy( pNtk );
+    pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+    Abc_NtkStrashPerform( pNtk, pNtkAig, fAllNodes, fRecord );
+    Abc_NtkFinalize( pNtk, pNtkAig );
+    // transfer name IDs
+    if ( pNtk->vNameIds )
+        Abc_NtkTransferNameIds( pNtk, pNtkAig );
+    // print warning about self-feed latches
+//    if ( Abc_NtkCountSelfFeedLatches(pNtkAig) )
+//        printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) );
+    // perform cleanup if requested
+    nNodes = fCleanup? Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc) : 0;
+//    if ( nNodes )
+//        printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes );
+    // duplicate EXDC 
+    if ( pNtk->pExdc )
+        pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pNtkAig ) )
+    {
+        printf( "Abc_NtkStrash: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkAig );
+        return NULL;
+    }
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Appends the second network to the first.]
+
+  Description [Modifies the first network by adding the logic of the second. 
+  Performs structural hashing while appending the networks. Does not change 
+  the second network. Returns 0 if the appending failed, 1 otherise.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos )
+{
+    Abc_Obj_t * pObj;
+    char * pName;
+    int i, nNewCis;
+    // the first network should be an AIG
+    assert( Abc_NtkIsStrash(pNtk1) );
+    assert( Abc_NtkIsLogic(pNtk2) || Abc_NtkIsStrash(pNtk2) ); 
+    if ( Abc_NtkIsLogic(pNtk2) && !Abc_NtkToAig(pNtk2) )
+    {
+        printf( "Converting to AIGs has failed.\n" );
+        return 0;
+    }
+    // check that the networks have the same PIs
+    // reorder PIs of pNtk2 according to pNtk1
+    if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 1, 1 ) )
+        printf( "Abc_NtkAppend(): The union of the network PIs is computed (warning).\n" );
+    // perform strashing
+    nNewCis = 0;
+    Abc_NtkCleanCopy( pNtk2 );
+    if ( Abc_NtkIsStrash(pNtk2) )
+        Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtk1);
+    Abc_NtkForEachCi( pNtk2, pObj, i )
+    {
+        pName = Abc_ObjName(pObj);
+        pObj->pCopy = Abc_NtkFindCi(pNtk1, Abc_ObjName(pObj));
+        if ( pObj->pCopy == NULL )
+        {
+            pObj->pCopy = Abc_NtkDupObj(pNtk1, pObj, 1);
+            nNewCis++;
+        }
+    }
+    if ( nNewCis )
+        printf( "Warning: Procedure Abc_NtkAppend() added %d new CIs.\n", nNewCis );
+    // add pNtk2 to pNtk1 while strashing
+    if ( Abc_NtkIsLogic(pNtk2) )
+        Abc_NtkStrashPerform( pNtk2, pNtk1, 1, 0 );
+    else
+        Abc_NtkForEachNode( pNtk2, pObj, i )
+            pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtk1->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+    // add the COs of the second network
+    if ( fAddPos )
+    {
+        Abc_NtkForEachPo( pNtk2, pObj, i )
+        {
+            Abc_NtkDupObj( pNtk1, pObj, 0 );
+            Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
+            Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+        }
+    }
+    else
+    {
+        Abc_Obj_t * pObjOld, * pDriverOld, * pDriverNew;
+        int fCompl, iNodeId;
+        // OR the choices
+        Abc_NtkForEachCo( pNtk2, pObj, i )
+        {
+            iNodeId = Nm_ManFindIdByNameTwoTypes( pNtk1->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI );
+//            if ( iNodeId < 0 )
+//                continue;
+            assert( iNodeId >= 0 );
+            pObjOld = Abc_NtkObj( pNtk1, iNodeId );
+            // derive the new driver
+            pDriverOld = Abc_ObjChild0( pObjOld );
+            pDriverNew = Abc_ObjChild0Copy( pObj );
+            pDriverNew = Abc_AigOr( (Abc_Aig_t *)pNtk1->pManFunc, pDriverOld, pDriverNew );
+            if ( Abc_ObjRegular(pDriverOld) == Abc_ObjRegular(pDriverNew) )
+                continue;
+            // replace the old driver by the new driver
+            fCompl = Abc_ObjRegular(pDriverOld)->fPhase ^ Abc_ObjRegular(pDriverNew)->fPhase;
+            Abc_ObjPatchFanin( pObjOld, Abc_ObjRegular(pDriverOld), Abc_ObjNotCond(Abc_ObjRegular(pDriverNew), fCompl) );
+        }
+    }
+    // make sure that everything is okay
+    if ( !Abc_NtkCheck( pNtk1 ) )
+    {
+        printf( "Abc_NtkAppend: The network check has failed.\n" );
+        return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the network for strashing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord )
+{
+//    ProgressBar * pProgress;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNodeOld;
+    int i; //, clk = Abc_Clock();
+    assert( Abc_NtkIsLogic(pNtkOld) );
+    assert( Abc_NtkIsStrash(pNtkNew) );
+//    vNodes = Abc_NtkDfs( pNtkOld, fAllNodes );
+    vNodes = Abc_NtkDfsIter( pNtkOld, fAllNodes );
+//printf( "Nodes = %d. ", Vec_PtrSize(vNodes) );
+//ABC_PRT( "Time", Abc_Clock() - clk );
+//    pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNodeOld, i )
+    {
+//        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        pNodeOld->pCopy = Abc_NodeStrash( pNtkNew, pNodeOld, fRecord );
+    }
+//    Extra_ProgressBarStop( pProgress );
+    Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the AIG from one manager into another.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeStrash_rec( Abc_Aig_t * pMan, Hop_Obj_t * pObj )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+        return;
+    Abc_NodeStrash_rec( pMan, Hop_ObjFanin0(pObj) ); 
+    Abc_NodeStrash_rec( pMan, Hop_ObjFanin1(pObj) );
+    pObj->pData = Abc_AigAnd( pMan, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) );
+    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjSetMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes one logic node.]
+
+  Description [Assume the network is in the AIG form]
+               
+  SideEffects []
+ 
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, int fRecord )
+{
+    Hop_Man_t * pMan;
+    Hop_Obj_t * pRoot;
+    Abc_Obj_t * pFanin;
+    int i;
+    assert( Abc_ObjIsNode(pNodeOld) );
+    assert( Abc_NtkHasAig(pNodeOld->pNtk) && !Abc_NtkIsStrash(pNodeOld->pNtk) );
+    // get the local AIG manager and the local root node
+    pMan = (Hop_Man_t *)pNodeOld->pNtk->pManFunc;
+    pRoot = (Hop_Obj_t *)pNodeOld->pData;
+    // check the constant case
+    if ( Abc_NodeIsConst(pNodeOld) || Hop_Regular(pRoot) == Hop_ManConst1(pMan) )
+        return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Hop_IsComplement(pRoot) );
+    // perform special case-strashing using the record of AIG subgraphs
+/*
+    if ( fRecord && Abc_NtkRecIsRunning() && Abc_ObjFaninNum(pNodeOld) > 2 && Abc_ObjFaninNum(pNodeOld) <= Abc_NtkRecVarNum() )
+    {
+        extern Vec_Int_t * Abc_NtkRecMemory();
+        extern int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars );
+        int nVars = Abc_NtkRecVarNum();
+        Vec_Int_t * vMemory = Abc_NtkRecMemory();
+        unsigned * pTruth = Hop_ManConvertAigToTruth( pMan, Hop_Regular(pRoot), nVars, vMemory, 0 );
+        assert( Extra_TruthSupportSize(pTruth, nVars) == Abc_ObjFaninNum(pNodeOld) ); // should be swept
+        if ( Hop_IsComplement(pRoot) )
+            Extra_TruthNot( pTruth, pTruth, nVars );
+        if ( Abc_NtkRecStrashNode( pNtkNew, pNodeOld, pTruth, nVars ) )
+            return pNodeOld->pCopy;
+    }
+*/
+    // set elementary variables
+    Abc_ObjForEachFanin( pNodeOld, pFanin, i )
+        Hop_IthVar(pMan, i)->pData = pFanin->pCopy;
+    // strash the AIG of this node
+    Abc_NodeStrash_rec( (Abc_Aig_t *)pNtkNew->pManFunc, Hop_Regular(pRoot) );
+    Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
+    // return the final node
+    return Abc_ObjNotCond( (Abc_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
+}
+
+
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Copies the topmost levels of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkTopmost_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int LevelCut )
+{
+    assert( !Abc_ObjIsComplement(pNode) );
+    if ( pNode->pCopy )
+        return pNode->pCopy;
+    if ( pNode->Level <= (unsigned)LevelCut )
+        return pNode->pCopy = Abc_NtkCreatePi( pNtkNew );
+    Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(pNode), LevelCut );
+    Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin1(pNode), LevelCut );
+    return pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Copies the topmost levels of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels )
+{
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObjNew, * pObjPo;
+    int LevelCut;
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( Abc_NtkCoNum(pNtk) == 1 );
+    // get the cutoff level
+    LevelCut = Abc_MaxInt( 0, Abc_AigLevel(pNtk) - nLevels );
+    // start the network
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+    Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+    // create PIs below the cut and nodes above the cut
+    Abc_NtkCleanCopy( pNtk );
+    pObjNew = Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(Abc_NtkPo(pNtk, 0)), LevelCut );
+    pObjNew = Abc_ObjNotCond( pObjNew, Abc_ObjFaninC0(Abc_NtkPo(pNtk, 0)) );
+    // add the PO node and name
+    pObjPo = Abc_NtkCreatePo(pNtkNew);
+    Abc_ObjAddFanin( pObjPo, pObjNew );
+    Abc_NtkAddDummyPiNames( pNtkNew );
+    Abc_ObjAssignName( pObjPo, Abc_ObjName(Abc_NtkPo(pNtk, 0)), NULL );
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkTopmost: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two integers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Vec_CompareNodeIds( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 )
+{
+    if ( Abc_ObjRegular(*pp1)->Id < Abc_ObjRegular(*pp2)->Id )
+        return -1;
+    if ( Abc_ObjRegular(*pp1)->Id > Abc_ObjRegular(*pp2)->Id ) //
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the large supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NodeGetSuper( Abc_Obj_t * pNode )
+{
+    Vec_Ptr_t * vSuper, * vFront;
+    Abc_Obj_t * pAnd, * pFanin;
+    int i;
+    assert( Abc_ObjIsNode(pNode) && !Abc_ObjIsComplement(pNode) );
+    vSuper = Vec_PtrAlloc( 100 ); 
+    // explore the frontier
+    vFront = Vec_PtrAlloc( 100 );
+    Vec_PtrPush( vFront, pNode );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vFront, pAnd, i )
+    {
+        pFanin = Abc_ObjChild0(pAnd);
+        if ( Abc_ObjIsNode(pFanin) && !Abc_ObjIsComplement(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+            Vec_PtrPush( vFront, pFanin );
+        else
+            Vec_PtrPush( vSuper, pFanin );
+
+        pFanin = Abc_ObjChild1(pAnd);
+        if ( Abc_ObjIsNode(pFanin) && !Abc_ObjIsComplement(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+            Vec_PtrPush( vFront, pFanin );
+        else
+            Vec_PtrPush( vSuper, pFanin );
+    }
+    Vec_PtrFree( vFront );
+    // reverse the array of pointers to start with lower IDs
+    vFront = Vec_PtrAlloc( Vec_PtrSize(vSuper) );
+    Vec_PtrForEachEntryReverse( Abc_Obj_t *, vSuper, pNode, i )
+        Vec_PtrPush( vFront, pNode );
+    Vec_PtrFree( vSuper );
+    vSuper = vFront;
+    // uniquify and return the frontier
+    Vec_PtrUniqify( vSuper, (int (*)())Vec_CompareNodeIds );
+    return vSuper;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Copies the topmost levels of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkTopAnd( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNodes, * vOrder;
+    Abc_Ntk_t * pNtkAig;
+    Abc_Obj_t * pObj, * pDriver, * pObjPo;
+    int i, nNodes;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // get the first PO
+    pObjPo = Abc_NtkPo(pNtk, 0);
+    vNodes = Abc_NodeGetSuper( Abc_ObjChild0(pObjPo) );
+    assert( Vec_PtrSize(vNodes) >= 2 );
+    // start the new network (constants and CIs of the old network will point to the their counterparts in the new network)
+    Abc_NtkCleanCopy( pNtk );
+    pNtkAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    pNtkAig->pName = Extra_UtilStrsav(pNtk->pName);
+    pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+    Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkAig);
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        Abc_NtkDupObj( pNtkAig, pObj, 1 );
+    // restrash the nodes reachable from the roots
+    vOrder = Abc_NtkDfsIterNodes( pNtk, vNodes );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i )
+        pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+    Vec_PtrFree( vOrder );
+    // finalize the network
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        pObjPo = Abc_NtkCreatePo(pNtkAig);
+        pDriver = Abc_ObjNotCond(Abc_ObjRegular(pObj)->pCopy, Abc_ObjIsComplement(pObj));
+        Abc_ObjAddFanin( pObjPo, pDriver );
+        Abc_ObjAssignName( pObjPo, Abc_ObjName(pObjPo), NULL );
+    }
+    Vec_PtrFree( vNodes );
+    // perform cleanup if requested
+    if ( (nNodes = Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc)) ) 
+        printf( "Abc_NtkTopAnd(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes );
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pNtkAig ) )
+    {
+        printf( "Abc_NtkStrash: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkAig );
+        return NULL;
+    }
+    return pNtkAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG into a file for parsing.]
+
+  Description [Ordering: c0, pis, ands, pos. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkWriteAig( Abc_Ntk_t * pNtk, char * pFileName )
+{
+    FILE * pFile;
+    Vec_Int_t * vId2Num;
+    Abc_Obj_t * pObj;
+    int i, iLit;
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( Abc_NtkLatchNum(pNtk) == 0 );
+    if ( pFileName == NULL )
+        pFile = stdout;
+    else
+        pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open output file.\n" );
+        return;
+    }
+    vId2Num = Vec_IntAlloc( 2*Abc_NtkObjNumMax(pNtk) );
+    Vec_IntFill( vId2Num, 2*Abc_NtkObjNumMax(pNtk), -1 );
+
+    iLit = 0;
+    Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(Abc_AigConst1(pNtk))+1, iLit++ );
+    Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(Abc_AigConst1(pNtk))+0, iLit++ );
+    Abc_NtkForEachPi( pNtk, pObj, i )
+    {
+        Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(pObj)+0, iLit++ );
+        Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(pObj)+1, iLit++ );
+    }
+    Abc_AigForEachAnd( pNtk, pObj, i )
+    {
+        Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(pObj)+0, iLit++ );
+        Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(pObj)+1, iLit++ );
+    }
+    fprintf( pFile, "{\n" );
+    fprintf( pFile, "    \"%s\", ", Abc_NtkName(pNtk) );
+    fprintf( pFile, "//  pi=%d  po=%d  and=%d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkNodeNum(pNtk) );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "    { " );
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        fprintf( pFile, "\"%s\",", Abc_ObjName(pObj) );
+    fprintf( pFile, "NULL },\n" );
+    fprintf( pFile, "    { " );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        fprintf( pFile, "\"%s\",", Abc_ObjName(pObj) );
+    fprintf( pFile, "NULL },\n" );
+    fprintf( pFile, "    { " );
+    Abc_AigForEachAnd( pNtk, pObj, i )
+        fprintf( pFile, "%d,", Vec_IntEntry(vId2Num, 2*Abc_ObjFaninId0(pObj) + Abc_ObjFaninC0(pObj)) );
+    fprintf( pFile, "0 },\n" );
+    fprintf( pFile, "    { " );
+    Abc_AigForEachAnd( pNtk, pObj, i )
+        fprintf( pFile, "%d,", Vec_IntEntry(vId2Num, 2*Abc_ObjFaninId1(pObj) + Abc_ObjFaninC1(pObj)) );
+    fprintf( pFile, "0 },\n" );
+    fprintf( pFile, "    { " );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        fprintf( pFile, "%d,", Vec_IntEntry(vId2Num, 2*Abc_ObjFaninId0(pObj) + Abc_ObjFaninC0(pObj)) );
+    fprintf( pFile, "0 },\n" );
+    fprintf( pFile, "},\n" );
+    if ( pFile != stdout )
+        fclose( pFile );
+    Vec_IntFree( vId2Num );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkPutOnTop( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtk2 )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k;
+    assert( Abc_NtkIsLogic(pNtk) );
+    assert( Abc_NtkIsLogic(pNtk2) );
+    assert( Abc_NtkPoNum(pNtk) == Abc_NtkPiNum(pNtk2) );
+    // clean the node copy fields
+    Abc_NtkCleanCopy( pNtk );
+    Abc_NtkCleanCopy( pNtk2 );
+    // duplicate the name and the spec
+    pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+    pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+    pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+    // clone CIs/CIs/boxes
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        Abc_NtkDupObj( pNtkNew, pObj, 1 );
+    // add internal nodes
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        Abc_NtkDupObj( pNtkNew, pObj, 0 );
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+    }
+    Vec_PtrFree( vNodes );
+    // transfer to the POs
+    Abc_NtkForEachPi( pNtk2, pObj, i )
+        pObj->pCopy = Abc_ObjChild0Copy( Abc_NtkPo(pNtk, i) );
+    // add internal nodes
+    vNodes = Abc_NtkDfs( pNtk2, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        Abc_NtkDupObj( pNtkNew, pObj, 0 );
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+    }
+    Vec_PtrFree( vNodes );
+    // clone CIs/CIs/boxes
+    Abc_NtkForEachPo( pNtk2, pObj, i )
+    {
+        Abc_NtkDupObj( pNtkNew, pObj, 1 );
+        Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
+    }
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkPutOnTop(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcSweep.c b/abc-build/src/base/abci/abcSweep.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcSweep.c
@@ -0,0 +1,1022 @@
+/**CFile****************************************************************
+
+  FileName    [abcDsd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Technology dependent sweep.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/main.h"
+#include "proof/fraig/fraig.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void           Abc_NtkFraigSweepUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
+static stmm_table *   Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int fVeryVerbose );
+static void           Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv, int fVerbose );
+static void           Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose );
+static void           Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose );
+static int            Abc_NodeDroppingCost( Abc_Obj_t * pNode );
+
+static int            Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes );
+static void           Abc_NodeSweep( Abc_Obj_t * pNode, int fVerbose );
+static void           Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, int fConst0 );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Sweping functionally equivalence nodes.]
+
+  Description [Removes gates with equivalent functionality. Works for 
+  both technology-independent and mapped networks. If the flag is set, 
+  allows adding inverters at the gate outputs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose )
+{
+    Fraig_Params_t Params;
+    Abc_Ntk_t * pNtkAig;
+    Fraig_Man_t * pMan;
+    stmm_table * tEquiv;
+    Abc_Obj_t * pObj;
+    int i, fUseTrick;
+
+    assert( !Abc_NtkIsStrash(pNtk) );
+
+    // save gate assignments
+    fUseTrick = 0;
+    if ( Abc_NtkIsMappedLogic(pNtk) )
+    {
+        fUseTrick = 1;
+        Abc_NtkForEachNode( pNtk, pObj, i )
+            pObj->pNext = (Abc_Obj_t *)pObj->pData;
+    }
+    // derive the AIG
+    pNtkAig = Abc_NtkStrash( pNtk, 0, 1, 0 );
+    // reconstruct gate assignments
+    if ( fUseTrick )
+    {
+//        extern void * Abc_FrameReadLibGen(); 
+        Hop_ManStop( (Hop_Man_t *)pNtk->pManFunc );
+        pNtk->pManFunc = Abc_FrameReadLibGen();
+        pNtk->ntkFunc = ABC_FUNC_MAP;
+        Abc_NtkForEachNode( pNtk, pObj, i )
+            pObj->pData = pObj->pNext, pObj->pNext = NULL;
+    }
+
+    // perform fraiging of the AIG
+    Fraig_ParamsSetDefault( &Params );
+    Params.fInternal = 1;
+    pMan = (Fraig_Man_t *)Abc_NtkToFraig( pNtkAig, &Params, 0, 0 );   
+    // cannot use EXDC with FRAIG because it can create classes of equivalent FRAIG nodes
+    // with representative nodes that do not correspond to the nodes with the current network
+
+    // update FRAIG using EXDC
+    if ( fExdc )
+    {
+        if ( pNtk->pExdc == NULL )
+            printf( "Warning: Networks has no EXDC.\n" );
+        else
+            Abc_NtkFraigSweepUsingExdc( pMan, pNtk );
+    }
+    // assign levels to the nodes of the network
+    Abc_NtkLevel( pNtk );
+
+    // collect the classes of equivalent nets
+    tEquiv = Abc_NtkFraigEquiv( pNtk, fUseInv, fVerbose, fVeryVerbose );
+
+    // transform the network into the equivalent one
+    Abc_NtkFraigTransform( pNtk, tEquiv, fUseInv, fVerbose );
+    stmm_free_table( tEquiv );
+
+    // free the manager
+    Fraig_ManFree( pMan );
+    Abc_NtkDelete( pNtkAig );
+
+    // cleanup the dangling nodes
+    if ( Abc_NtkHasMapping(pNtk) )
+        Abc_NtkCleanup( pNtk, fVerbose );
+    else
+        Abc_NtkSweep( pNtk, fVerbose );
+
+    // check
+    if ( !Abc_NtkCheck( pNtk ) )
+    {
+        printf( "Abc_NtkFraigSweep: The network check has failed.\n" );
+        return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sweep the network using EXDC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFraigSweepUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+    Fraig_Node_t * gNodeExdc, * gNode, * gNodeRes;
+    Abc_Obj_t * pNode, * pNodeAig;
+    int i;
+    extern Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkExdc );
+
+    assert( pNtk->pExdc );
+    // derive FRAIG node representing don't-cares in the EXDC network
+    gNodeExdc = Abc_NtkToFraigExdc( pMan, pNtk, pNtk->pExdc );
+    // update the node pointers
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        // skip the constant input nodes
+        if ( Abc_ObjFaninNum(pNode) == 0 )
+            continue;
+        // get the strashed node
+        pNodeAig = pNode->pCopy;
+        // skip the dangling nodes
+        if ( pNodeAig == NULL )
+            continue;
+        // get the FRAIG node
+        gNode = Fraig_NotCond( Abc_ObjRegular(pNodeAig)->pCopy, (int)Abc_ObjIsComplement(pNodeAig) );
+        // perform ANDing with EXDC
+        gNodeRes = Fraig_NodeAnd( pMan, gNode, Fraig_Not(gNodeExdc) );
+        // write the node back
+        Abc_ObjRegular(pNodeAig)->pCopy = (Abc_Obj_t *)Fraig_NotCond( gNodeRes, (int)Abc_ObjIsComplement(pNodeAig) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects equivalence classes of node in the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+stmm_table * Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int fVeryVerbose )
+{
+    Abc_Obj_t * pList, * pNode, * pNodeAig;
+    Fraig_Node_t * gNode;
+    Abc_Obj_t ** ppSlot;
+    stmm_table * tStrash2Net;
+    stmm_table * tResult;
+    stmm_generator * gen;
+    int c, Counter;
+
+    // create mapping of strashed nodes into the corresponding network nodes
+    tStrash2Net = stmm_init_table(stmm_ptrcmp,stmm_ptrhash);
+    Abc_NtkForEachNode( pNtk, pNode, c )
+    {
+        // skip the constant input nodes
+        if ( Abc_ObjFaninNum(pNode) == 0 )
+            continue;
+        // get the strashed node
+        pNodeAig = pNode->pCopy;
+        // skip the dangling nodes
+        if ( pNodeAig == NULL )
+            continue;
+        // skip the nodes that fanout into COs
+        if ( Abc_NodeFindCoFanout(pNode) )
+            continue;
+        // get the FRAIG node
+        gNode = Fraig_NotCond( Abc_ObjRegular(pNodeAig)->pCopy, (int)Abc_ObjIsComplement(pNodeAig) );
+        if ( !stmm_find_or_add( tStrash2Net, (char *)Fraig_Regular(gNode), (char ***)&ppSlot ) )
+            *ppSlot = NULL;
+        // add the node to the list
+        pNode->pNext = *ppSlot;
+        *ppSlot = pNode;
+        // mark the node if it is complemented
+        pNode->fPhase = Fraig_IsComplement(gNode);
+    }
+
+    // print the classes
+    c = 0;
+    Counter = 0;
+    tResult = stmm_init_table(stmm_ptrcmp,stmm_ptrhash);
+    stmm_foreach_item( tStrash2Net, gen, (char **)&gNode, (char **)&pList )
+    {
+        // skip the trival classes
+        if ( pList == NULL || pList->pNext == NULL )
+            continue;
+        // add the non-trival class
+        stmm_insert( tResult, (char *)pList, NULL );
+        // count nodes in the non-trival classes
+        for ( pNode = pList; pNode; pNode = pNode->pNext )
+            Counter++;
+
+        if ( fVeryVerbose )
+        {
+            printf( "Class %2d : {", c );
+            for ( pNode = pList; pNode; pNode = pNode->pNext )
+            {
+                pNode->pCopy = NULL;
+                printf( " %s", Abc_ObjName(pNode) );
+                printf( "(%c)", pNode->fPhase? '-' : '+' );
+                printf( "(%d)", pNode->Level );
+            }
+            printf( " }\n" );
+            c++;
+        }
+    }
+    if ( fVerbose || fVeryVerbose )
+    {
+        printf( "Sweeping stats for network \"%s\":\n", pNtk->pName );
+        printf( "Internal nodes = %d. Different functions (up to compl) = %d.\n", Abc_NtkNodeNum(pNtk), stmm_count(tStrash2Net) );
+        printf( "Non-trivial classes = %d. Nodes in non-trivial classes = %d.\n", stmm_count(tResult), Counter );
+    }
+    stmm_free_table( tStrash2Net );
+    return tResult;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the network using the equivalence relation on nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv, int fVerbose )
+{
+    stmm_generator * gen;
+    Abc_Obj_t * pList;
+    if ( stmm_count(tEquiv) == 0 )
+        return;
+    // merge nodes in the classes
+    if ( Abc_NtkHasMapping( pNtk ) )
+    {
+        Abc_NtkDelayTrace( pNtk, NULL, NULL, 0 );
+        stmm_foreach_item( tEquiv, gen, (char **)&pList, NULL )
+            Abc_NtkFraigMergeClassMapped( pNtk, pList, fUseInv, fVerbose );
+    }
+    else 
+    {
+        stmm_foreach_item( tEquiv, gen, (char **)&pList, NULL )
+            Abc_NtkFraigMergeClass( pNtk, pList, fUseInv, fVerbose );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the list of one-phase equivalent nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose )
+{
+    Abc_Obj_t * pListDir, * pListInv;
+    Abc_Obj_t * pNodeMin, * pNode, * pNext;
+    float Arrival1, Arrival2;
+
+    assert( pChain );
+    assert( pChain->pNext );
+
+    // divide the nodes into two parts: 
+    // those that need the invertor and those that don't need
+    pListDir = pListInv = NULL;
+    for ( pNode = pChain, pNext = pChain->pNext; 
+          pNode; 
+          pNode = pNext, pNext = pNode? pNode->pNext : NULL )
+    {
+        // check to which class the node belongs
+        if ( pNode->fPhase == 1 )
+        {
+            pNode->pNext = pListDir;
+            pListDir = pNode;
+        }
+        else
+        {
+            pNode->pNext = pListInv;
+            pListInv = pNode;
+        }
+    }
+
+    // find the node with the smallest number of logic levels
+    pNodeMin = pListDir;
+    for ( pNode = pListDir; pNode; pNode = pNode->pNext )
+    {
+        Arrival1 = Abc_NodeReadArrivalWorst(pNodeMin);
+        Arrival2 = Abc_NodeReadArrivalWorst(pNode   );
+//        assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 );
+//        assert( Abc_ObjIsCi(pNode)    || Arrival2 > 0 );
+        if (  Arrival1 > Arrival2 ||
+              (Arrival1 == Arrival2 && pNodeMin->Level >  pNode->Level) ||
+              (Arrival1 == Arrival2 && pNodeMin->Level == pNode->Level &&
+              Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode))  )
+            pNodeMin = pNode;
+    }
+
+    // move the fanouts of the direct nodes
+    for ( pNode = pListDir; pNode; pNode = pNode->pNext )
+        if ( pNode != pNodeMin )
+            Abc_ObjTransferFanout( pNode, pNodeMin );
+
+    // find the node with the smallest number of logic levels
+    pNodeMin = pListInv;
+    for ( pNode = pListInv; pNode; pNode = pNode->pNext )
+    {
+        Arrival1 = Abc_NodeReadArrivalWorst(pNodeMin);
+        Arrival2 = Abc_NodeReadArrivalWorst(pNode   );
+//        assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 );
+//        assert( Abc_ObjIsCi(pNode)    || Arrival2 > 0 );
+        if (  Arrival1 > Arrival2 ||
+              (Arrival1 == Arrival2 && pNodeMin->Level >  pNode->Level) ||
+              (Arrival1 == Arrival2 && pNodeMin->Level == pNode->Level &&
+              Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode))  )
+            pNodeMin = pNode;
+    }
+
+    // move the fanouts of the direct nodes
+    for ( pNode = pListInv; pNode; pNode = pNode->pNext )
+        if ( pNode != pNodeMin )
+            Abc_ObjTransferFanout( pNode, pNodeMin );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Process one equivalence class of nodes.]
+
+  Description [This function does not remove the nodes. It only switches 
+  around the connections.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose )
+{
+    Abc_Obj_t * pListDir, * pListInv;
+    Abc_Obj_t * pNodeMin, * pNodeMinInv;
+    Abc_Obj_t * pNode, * pNext;
+
+    assert( pChain );
+    assert( pChain->pNext );
+
+    // find the node with the smallest number of logic levels
+    pNodeMin = pChain;
+    for ( pNode = pChain->pNext; pNode; pNode = pNode->pNext )
+        if (  pNodeMin->Level >  pNode->Level || 
+            ( pNodeMin->Level == pNode->Level && 
+              Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode) ) )
+            pNodeMin = pNode;
+
+    // divide the nodes into two parts: 
+    // those that need the invertor and those that don't need
+    pListDir = pListInv = NULL;
+    for ( pNode = pChain, pNext = pChain->pNext; 
+          pNode; 
+          pNode = pNext, pNext = pNode? pNode->pNext : NULL )
+    {
+        if ( pNode == pNodeMin )
+            continue;
+        // check to which class the node belongs
+        if ( pNodeMin->fPhase == pNode->fPhase )
+        {
+            pNode->pNext = pListDir;
+            pListDir = pNode;
+        }
+        else
+        {
+            pNode->pNext = pListInv;
+            pListInv = pNode;
+        }
+    }
+
+    // move the fanouts of the direct nodes
+    for ( pNode = pListDir; pNode; pNode = pNode->pNext )
+        Abc_ObjTransferFanout( pNode, pNodeMin );
+
+    // skip if there are no inverted nodes
+    if ( pListInv == NULL )
+        return;
+
+    // add the invertor
+    pNodeMinInv = Abc_NtkCreateNodeInv( pNtk, pNodeMin );
+   
+    // move the fanouts of the inverted nodes
+    for ( pNode = pListInv; pNode; pNode = pNode->pNext )
+        Abc_ObjTransferFanout( pNode, pNodeMinInv );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of literals saved if this node becomes useless.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeDroppingCost( Abc_Obj_t * pNode )
+{ 
+    return 1;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Removes dangling nodes.]
+
+  Description [Returns the number of nodes removed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    Vec_Ptr_t * vNodes;
+    int Counter;
+    assert( Abc_NtkIsLogic(pNtk) );
+    // mark the nodes reachable from the POs
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    Counter = Abc_NtkReduceNodes( pNtk, vNodes );
+    if ( fVerbose )
+        printf( "Cleanup removed %d dangling nodes.\n", Counter );
+    Vec_PtrFree( vNodes );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes dangling nodes.]
+
+  Description [Returns the number of nodes removed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCleanupNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fVerbose )
+{
+    Vec_Ptr_t * vNodes, * vStarts;
+    Abc_Obj_t * pObj;
+    int i, Counter;
+    assert( Abc_NtkIsLogic(pNtk) );
+    // collect starting nodes into one array
+    vStarts = Vec_PtrAlloc( 1000 );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Vec_PtrPush( vStarts, pObj );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
+        if ( pObj )
+            Vec_PtrPush( vStarts, pObj );
+    // mark the nodes reachable from the POs
+    vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vStarts), Vec_PtrSize(vStarts) );
+    Vec_PtrFree( vStarts );
+    Counter = Abc_NtkReduceNodes( pNtk, vNodes );
+    if ( fVerbose )
+        printf( "Cleanup removed %d dangling nodes.\n", Counter );
+    Vec_PtrFree( vNodes );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Preserves the nodes collected in the array.]
+
+  Description [Returns the number of nodes removed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pNode;
+    int i, Counter;
+    assert( Abc_NtkIsLogic(pNtk) );
+    // mark the nodes reachable from the POs
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        pNode->fMarkA = 1;
+    // remove the non-marked nodes
+    Counter = 0;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        if ( pNode->fMarkA == 0 )
+        {
+            Abc_NtkDeleteObj( pNode );
+            Counter++;
+        }
+    // unmark the remaining nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        pNode->fMarkA = 0;
+    // check
+    if ( !Abc_NtkCheck( pNtk ) )
+        printf( "Abc_NtkCleanup: The network check has failed.\n" );
+    return Counter;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Tranditional sweep of the network.]
+
+  Description [Propagates constant and single-input node, removes dangling nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNode, * pFanout, * pDriver;
+    int i, nNodesOld;
+    assert( Abc_NtkIsLogic(pNtk) ); 
+    // convert network to BDD representation
+    if ( !Abc_NtkToBdd(pNtk) )
+    {
+        fprintf( stdout, "Converting to BDD has failed.\n" );
+        return 1;
+    }
+    // perform cleanup
+    nNodesOld = Abc_NtkNodeNum(pNtk);
+    Abc_NtkCleanup( pNtk, 0 );
+    // prepare nodes for sweeping
+    Abc_NtkRemoveDupFanins(pNtk);
+    Abc_NtkMinimumBase(pNtk);
+    // collect sweepable nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        if ( Abc_ObjFaninNum(pNode) < 2 )
+            Vec_PtrPush( vNodes, pNode );
+    // sweep the nodes
+    while ( Vec_PtrSize(vNodes) > 0 )
+    {
+        // get any sweepable node
+        pNode = (Abc_Obj_t *)Vec_PtrPop(vNodes);
+        if ( !Abc_ObjIsNode(pNode) )
+            continue;
+        // get any non-CO fanout of this node
+        pFanout = Abc_NodeFindNonCoFanout(pNode);
+        if ( pFanout == NULL )
+            continue;
+        assert( Abc_ObjIsNode(pFanout) );
+        // transform the function of the fanout
+        if ( Abc_ObjFaninNum(pNode) == 0 )
+            Abc_NodeConstantInput( pFanout, pNode, Abc_NodeIsConst0(pNode) );
+        else 
+        {
+            assert( Abc_ObjFaninNum(pNode) == 1 );
+            pDriver = Abc_ObjFanin0(pNode);
+            if ( Abc_NodeIsInv(pNode) )
+                Abc_NodeComplementInput( pFanout, pNode );
+            Abc_ObjPatchFanin( pFanout, pNode, pDriver );
+        }
+        Abc_NodeRemoveDupFanins( pFanout );
+        Abc_NodeMinimumBase( pFanout );
+        // check if the fanout should be added
+        if ( Abc_ObjFaninNum(pFanout) < 2 )
+            Vec_PtrPush( vNodes, pFanout );
+        // check if the node has other fanouts
+        if ( Abc_ObjFanoutNum(pNode) > 0 )
+            Vec_PtrPush( vNodes, pNode );
+        else
+            Abc_NtkDeleteObj_rec( pNode, 1 );
+    }
+    Vec_PtrFree( vNodes );
+    // sweep a node into its CO fanout if all of this is true:
+    // (a) this node is a single-input node
+    // (b) the driver of the node has only one fanout (this node)
+    // (c) the driver is a node
+    Abc_NtkForEachCo( pNtk, pFanout, i )
+    {
+        pNode = Abc_ObjFanin0(pFanout);
+        if ( Abc_ObjFaninNum(pNode) != 1 )
+            continue;
+        pDriver = Abc_ObjFanin0(pNode);
+        if ( !(Abc_ObjFanoutNum(pDriver) == 1 && Abc_ObjIsNode(pDriver)) )
+            continue;
+        // trasform this CO
+        if ( Abc_NodeIsInv(pNode) )
+            pDriver->pData = Cudd_Not(pDriver->pData);
+        Abc_ObjPatchFanin( pFanout, pNode, pDriver );
+    }
+    // perform cleanup
+    Abc_NtkCleanup( pNtk, 0 );
+    // report
+    if ( fVerbose )
+        printf( "Sweep removed %d nodes.\n", nNodesOld - Abc_NtkNodeNum(pNtk) );
+    return nNodesOld - Abc_NtkNodeNum(pNtk);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces the local function by its cofactor.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, int fConst0 )
+{
+    DdManager * dd = (DdManager *)pNode->pNtk->pManFunc;
+    DdNode * bVar, * bTemp;
+    int iFanin;
+    assert( Abc_NtkIsBddLogic(pNode->pNtk) ); 
+    if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 )
+    {
+        printf( "Node %s should be among", Abc_ObjName(pFanin) );
+        printf( " the fanins of node %s...\n", Abc_ObjName(pNode) );
+        return;
+    }
+    bVar = Cudd_NotCond( Cudd_bddIthVar(dd, iFanin), fConst0 );
+    pNode->pData = Cudd_Cofactor( dd, bTemp = (DdNode *)pNode->pData, bVar );   Cudd_Ref( (DdNode *)pNode->pData );
+    Cudd_RecursiveDeref( dd, bTemp );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Removes all objects whose trav ID is not current.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeRemoveNonCurrentObjects( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int Counter, i;
+    int fVerbose = 0;
+
+    // report on the nodes to be deleted
+    if ( fVerbose )
+    {
+        printf( "These nodes will be deleted: \n" );
+        Abc_NtkForEachObj( pNtk, pObj, i )
+            if ( !Abc_NodeIsTravIdCurrent( pObj ) )
+            {
+                printf( "    " );
+                Abc_ObjPrint( stdout, pObj );
+            }
+    }
+    
+    // delete the nodes    
+    Counter = 0;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( !Abc_NodeIsTravIdCurrent( pObj ) )
+        {
+            Abc_NtkDeleteObj( pObj );
+            Counter++;
+        }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check if the fanin of this latch is a constant.]
+
+  Description [Returns 0/1 if constant; -1 if not a constant.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSetTravId_rec( Abc_Obj_t * pObj )
+{
+    Abc_NodeSetTravIdCurrent(pObj);
+    if ( Abc_ObjFaninNum(pObj) == 0 )
+        return;
+    assert( Abc_ObjFaninNum(pObj) == 1 );
+    Abc_NtkSetTravId_rec( Abc_ObjFanin0(pObj) );    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check if the fanin of this latch is a constant.]
+
+  Description [Returns 0/1 if constant; -1 if not a constant.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheckConstant_rec( Abc_Obj_t * pObj )
+{
+    if ( Abc_ObjFaninNum(pObj) == 0 )
+    {
+        if ( !Abc_ObjIsNode(pObj) )
+            return -1;
+        if ( Abc_NodeIsConst0(pObj) )
+            return 0;
+        if ( Abc_NodeIsConst1(pObj) )
+            return 1;
+        assert( 0 );
+        return -1;
+    }
+    if ( Abc_ObjIsLatch(pObj) || Abc_ObjFaninNum(pObj) > 1 )
+        return -1;
+    if ( !Abc_ObjIsNode(pObj) || Abc_NodeIsBuf(pObj) )
+        return Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pObj) );
+    if ( Abc_NodeIsInv(pObj) )
+    {
+        int RetValue = Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pObj) );
+        if ( RetValue == 0 )
+            return 1;
+        if ( RetValue == 1 )
+            return 0;
+        return RetValue;
+    }
+    assert( 0 );
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes redundant latches.]
+
+  Description [The redundant latches are of two types:
+  - Latches fed by a constant which matches the init value of the latch.
+  - Latches fed by a constant which does not match the init value of the latch
+  can be all replaced by one latch.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkLatchSweep( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pFanin, * pLatch, * pLatchPivot = NULL;
+    int Counter, RetValue, i;
+    Counter = 0;
+    // go through the latches
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+        // check if the latch has constant input
+        RetValue = Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pLatch) );
+        if ( RetValue == -1 )
+            continue;
+        // found a latch with constant fanin
+        if ( (RetValue == 1 && Abc_LatchIsInit0(pLatch)) ||
+             (RetValue == 0 && Abc_LatchIsInit1(pLatch)) )
+        {
+            // fanin constant differs from the latch init value
+            if ( pLatchPivot == NULL )
+            {
+                pLatchPivot = pLatch;
+                continue;
+            }
+            if ( Abc_LatchInit(pLatch) != Abc_LatchInit(pLatchPivot) ) // add inverter
+                pFanin = Abc_NtkCreateNodeInv( pNtk, Abc_ObjFanout0(pLatchPivot) );
+            else
+                pFanin = Abc_ObjFanout0(pLatchPivot);
+        }
+        else
+            pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch));
+        // replace latch
+        Abc_ObjTransferFanout( Abc_ObjFanout0(pLatch), pFanin );
+        // delete the extra nodes
+        Abc_NtkDeleteObj_rec( Abc_ObjFanout0(pLatch), 0 );
+        Counter++;
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces autonumnous logic by free inputs.]
+
+  Description [Assumes that non-autonomous logic is marked with
+  the current ID.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkReplaceAutonomousLogic( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode, * pFanin;
+    Vec_Ptr_t * vNodes;
+    int i, k, Counter;
+    // collect the nodes that feed into the reachable logic
+    vNodes = Vec_PtrAlloc( 100 );
+    Abc_NtkForEachObj( pNtk, pNode, i )
+    {
+        // skip non-visited fanins
+        if ( !Abc_NodeIsTravIdCurrent(pNode) )
+            continue;
+        // look for non-visited fanins
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+        {
+            // skip visited fanins
+            if ( Abc_NodeIsTravIdCurrent(pFanin) )
+                continue;
+            // skip constants and latches fed by constants
+            if ( Abc_NtkCheckConstant_rec(pFanin) != -1 ||
+                 (Abc_ObjIsBo(pFanin) && Abc_NtkCheckConstant_rec(Abc_ObjFanin0(Abc_ObjFanin0(pFanin))) != -1) )
+            {
+                Abc_NtkSetTravId_rec( pFanin );
+                continue;
+            }
+            assert( !Abc_ObjIsLatch(pFanin) );
+            Vec_PtrPush( vNodes, pFanin );
+        }
+    }
+    Vec_PtrUniqify( vNodes, (int (*)(void))Abc_ObjPointerCompare );
+    // replace these nodes by the PIs
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        pFanin = Abc_NtkCreatePi(pNtk);
+        Abc_ObjAssignName( pFanin, Abc_ObjName(pFanin), NULL );
+        Abc_NodeSetTravIdCurrent( pFanin );
+        Abc_ObjTransferFanout( pNode, pFanin );
+    }
+    Counter = Vec_PtrSize(vNodes);
+    Vec_PtrFree( vNodes );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sequential cleanup.]
+
+  Description [Performs three tasks:
+  - Removes logic that does not feed into POs.
+  - Removes latches driven by constant values equal to the initial state.
+  - Replaces the autonomous components by additional PI variables.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fLatchSweep, int fAutoSweep, int fVerbose )
+{
+    Vec_Ptr_t * vNodes;
+    int Counter;
+    assert( Abc_NtkIsLogic(pNtk) );
+    // mark the nodes reachable from the POs
+    vNodes = Abc_NtkDfsSeq( pNtk );
+    Vec_PtrFree( vNodes );
+    // remove the non-marked nodes
+    Counter = Abc_NodeRemoveNonCurrentObjects( pNtk );
+    if ( fVerbose )
+        printf( "Cleanup removed %4d dangling objects.\n", Counter );
+    // check if some of the latches can be removed
+    if ( fLatchSweep )
+    {
+        Counter = Abc_NtkLatchSweep( pNtk );
+        if ( fVerbose )
+            printf( "Cleanup removed %4d redundant latches.\n", Counter );
+    }
+    // detect the autonomous components
+    if ( fAutoSweep )
+    {
+        vNodes = Abc_NtkDfsSeqReverse( pNtk );
+        Vec_PtrFree( vNodes );
+        // replace them by PIs
+        Counter = Abc_NtkReplaceAutonomousLogic( pNtk );
+        if ( fVerbose )
+            printf( "Cleanup added   %4d additional PIs.\n", Counter );
+        // remove the non-marked nodes
+        Counter = Abc_NodeRemoveNonCurrentObjects( pNtk );
+        if ( fVerbose )
+            printf( "Cleanup removed %4d autonomous objects.\n", Counter );
+    }
+    // check
+    if ( !Abc_NtkCheck( pNtk ) )
+        printf( "Abc_NtkCleanupSeq: The network check has failed.\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sweep to remove buffers and inverters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkSweepBufsInvs( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    Hop_Man_t * pMan;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k, fChanges = 1, Counter = 0;
+    assert( Abc_NtkIsLogic(pNtk) ); 
+    // convert network to BDD representation
+    if ( !Abc_NtkToAig(pNtk) )
+    {
+        fprintf( stdout, "Converting to SOP has failed.\n" );
+        return 1;
+    }
+    // get AIG manager
+    pMan = (Hop_Man_t *)pNtk->pManFunc;
+    // label selected nodes
+    Abc_NtkIncrementTravId( pNtk );
+    // iterate till no improvement
+    while ( fChanges )
+    {
+        fChanges = 0;
+        Abc_NtkForEachObj( pNtk, pObj, i )
+        {
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+            {
+                // do not eliminate marked fanins
+                if ( Abc_NodeIsTravIdCurrent(pFanin) )
+                    continue;
+                // do not eliminate constant nodes
+                if ( !Abc_ObjIsNode(pFanin) || Abc_ObjFaninNum(pFanin) != 1 )
+                    continue;
+                // do not eliminate inverters into COs
+                if ( Abc_ObjIsCo(pObj) && Abc_NodeIsInv(pFanin) )
+                    continue;
+                // do not eliminate buffers connecting PIs and POs 
+//                if ( Abc_ObjIsCo(pObj) && Abc_ObjIsCi(Abc_ObjFanin0(pFanin)) )
+//                    continue;
+                fChanges = 1;
+                Counter++;
+                // update function of the node
+                if ( Abc_NodeIsInv(pFanin) )
+                    pObj->pData = Hop_Compose( pMan, (Hop_Obj_t *)pObj->pData, Hop_Not(Hop_IthVar(pMan, k)), k );
+                // update the fanin
+                Abc_ObjPatchFanin( pObj, pFanin, Abc_ObjFanin0(pFanin) );
+                if ( Abc_ObjFanoutNum(pFanin) == 0 )
+                    Abc_NtkDeleteObj(pFanin);            
+            }
+        }
+    }
+    if ( fVerbose )
+        printf( "Removed %d single input nodes.\n", Counter );
+    return Counter;
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcSymm.c b/abc-build/src/base/abci/abcSymm.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcSymm.c
@@ -0,0 +1,236 @@
+/**CFile****************************************************************
+
+  FileName    [abcSymm.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Computation of two-variable symmetries.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcSymm.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "opt/sim/sim.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+static void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose );
+static void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose );
+static void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose );
+static void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [The top level procedure to compute symmetries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose )
+{
+    if ( fUseBdds || fNaive )
+        Abc_NtkSymmetriesUsingBdds( pNtk, fNaive, fReorder, fVerbose );
+    else
+        Abc_NtkSymmetriesUsingSandS( pNtk, fVerbose );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Symmetry computation using simulation and SAT.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose )
+{
+//    extern int Sim_ComputeTwoVarSymms( Abc_Ntk_t * pNtk, int fVerbose );
+    int nSymms = Sim_ComputeTwoVarSymms( pNtk, fVerbose );
+    printf( "The total number of symmetries is %d.\n", nSymms );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Symmetry computation using BDDs (both naive and smart).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose )
+{
+    DdManager * dd;
+    abctime clk, clkBdd, clkSym;
+    int fGarbCollect = 1;
+
+    // compute the global functions
+clk = Abc_Clock();
+    dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, fReorder, fVerbose );
+    printf( "Shared BDD size = %d nodes.\n", Abc_NtkSizeOfGlobalBdds(pNtk) ); 
+    Cudd_AutodynDisable( dd );
+    if ( !fGarbCollect )
+        Cudd_DisableGarbageCollection( dd );
+    Cudd_zddVarsFromBddVars( dd, 2 );
+clkBdd = Abc_Clock() - clk;
+    // create the collapsed network
+clk = Abc_Clock();
+    Ntk_NetworkSymmsBdd( dd, pNtk, fNaive, fVerbose );
+clkSym = Abc_Clock() - clk;
+    // undo the global functions
+    Abc_NtkFreeGlobalBdds( pNtk, 1 );
+printf( "Statistics of BDD-based symmetry detection:\n" );
+printf( "Algorithm = %s. Reordering = %s. Garbage collection = %s.\n", 
+       fNaive? "naive" : "fast", fReorder? "yes" : "no", fGarbCollect? "yes" : "no" );
+ABC_PRT( "Constructing BDDs", clkBdd );
+ABC_PRT( "Computing symms  ", clkSym );
+ABC_PRT( "TOTAL            ", clkBdd + clkSym );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Symmetry computation using BDDs (both naive and smart).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose )
+{
+    Extra_SymmInfo_t * pSymms;
+    Abc_Obj_t * pNode;
+    DdNode * bFunc;
+    int nSymms = 0;
+    int nSupps = 0;
+    int i;
+
+    // compute symmetry info for each PO
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+//      bFunc = pNtk->vFuncsGlob->pArray[i];
+        bFunc = (DdNode *)Abc_ObjGlobalBdd( pNode );
+        nSupps += Cudd_SupportSize( dd, bFunc );
+        if ( Cudd_IsConstant(bFunc) )
+            continue;
+        if ( fNaive )
+            pSymms = Extra_SymmPairsComputeNaive( dd, bFunc );
+        else
+            pSymms = Extra_SymmPairsCompute( dd, bFunc );
+        nSymms += pSymms->nSymms;
+        if ( fVerbose )
+        {
+            printf( "Output %6s (%d): ", Abc_ObjName(pNode), pSymms->nSymms );
+            Ntk_NetworkSymmsPrint( pNtk, pSymms );
+        }
+//Extra_SymmPairsPrint( pSymms );
+        Extra_SymmPairsDissolve( pSymms );
+    }
+    printf( "Total number of vars in functional supports = %8d.\n", nSupps );
+    printf( "Total number of two-variable symmetries     = %8d.\n", nSymms );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Printing symmetry groups from the symmetry data structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms )
+{
+    char ** pInputNames;
+    int * pVarTaken;
+    int i, k, nVars, nSize, fStart;
+
+    // get variable names
+    nVars = Abc_NtkCiNum(pNtk);
+    pInputNames = Abc_NtkCollectCioNames( pNtk, 0 );
+
+    // alloc the array of marks
+    pVarTaken = ABC_ALLOC( int, nVars );
+    memset( pVarTaken, 0, sizeof(int) * nVars );
+
+    // print the groups
+    fStart = 1;
+    nSize = pSymms->nVars;
+    for ( i = 0; i < nSize; i++ )
+    {
+        // skip the variable already considered
+        if ( pVarTaken[i] )
+            continue;
+        // find all the vars symmetric with this one
+        for ( k = 0; k < nSize; k++ )
+        {
+            if ( k == i )
+                continue;
+            if ( pSymms->pSymms[i][k] == 0 )
+                continue;
+            // vars i and k are symmetric
+            assert( pVarTaken[k] == 0 );
+            // there is a new symmetry pair 
+            if ( fStart == 1 )
+            {  // start a new symmetry class
+                fStart = 0;
+                printf( "  { %s", pInputNames[ pSymms->pVars[i] ] );
+                // mark the var as taken
+                pVarTaken[i] = 1;
+            }
+            printf( " %s", pInputNames[ pSymms->pVars[k] ] );
+            // mark the var as taken
+            pVarTaken[k] = 1;
+        }
+        if ( fStart == 0 )
+        {
+            printf( " }" );
+            fStart = 1; 
+        }   
+    }   
+    printf( "\n" );
+
+    ABC_FREE( pInputNames );
+    ABC_FREE( pVarTaken );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcTim.c b/abc-build/src/base/abci/abcTim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcTim.c
@@ -0,0 +1,637 @@
+/**CFile****************************************************************
+
+  FileName    [abcTim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Testing hierarchy/timing manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcTim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "aig/gia/giaAig.h"
+#include "misc/tim/tim.h"
+#include "opt/dar/dar.h"
+#include "proof/dch/dch.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define TIM_TEST_BOX_RATIO 200
+
+// assume that every TIM_TEST_BOX_RATIO'th object is a white box
+static inline int Abc_NodeIsWhiteBox( Abc_Obj_t * pObj )  { assert( Abc_ObjIsNode(pObj) ); return Abc_ObjId(pObj) % TIM_TEST_BOX_RATIO == 0 && Abc_ObjFaninNum(pObj) > 0 && Abc_ObjFaninNum(pObj) < 10; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives GIA for the output of the local function of one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTestTimNodeStrash_rec( Gia_Man_t * pGia, Hop_Obj_t * pObj )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+        return;
+    Abc_NtkTestTimNodeStrash_rec( pGia, Hop_ObjFanin0(pObj) ); 
+    Abc_NtkTestTimNodeStrash_rec( pGia, Hop_ObjFanin1(pObj) );
+    pObj->iData = Gia_ManHashAnd( pGia, Hop_ObjChild0CopyI(pObj), Hop_ObjChild1CopyI(pObj) );
+    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjSetMarkA( pObj );
+}
+int Abc_NtkTestTimNodeStrash( Gia_Man_t * pGia, Abc_Obj_t * pNode )
+{
+    Hop_Man_t * pMan;
+    Hop_Obj_t * pRoot;
+    Abc_Obj_t * pFanin;
+    int i;
+    assert( Abc_ObjIsNode(pNode) );
+    assert( Abc_NtkIsAigLogic(pNode->pNtk) );
+    // get the local AIG manager and the local root node
+    pMan = (Hop_Man_t *)pNode->pNtk->pManFunc;
+    pRoot = (Hop_Obj_t *)pNode->pData;
+    // check the constant case
+    if ( Abc_NodeIsConst(pNode) || Hop_Regular(pRoot) == Hop_ManConst1(pMan) )
+        return !Hop_IsComplement(pRoot);
+    // set elementary variables
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        Hop_IthVar(pMan, i)->iData = pFanin->iTemp;
+    // strash the AIG of this node
+    Abc_NtkTestTimNodeStrash_rec( pGia, Hop_Regular(pRoot) );
+    Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
+    // return the final node with complement if needed
+    return Abc_LitNotCond( Hop_Regular(pRoot)->iData, Hop_IsComplement(pRoot) );
+}
+
+
+#if 0 
+
+/**Function*************************************************************
+
+  Synopsis    [Derives GIA manager using special pins to denote box boundaries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Abc_NtkTestPinDeriveGia( Abc_Ntk_t * pNtk, int fWhiteBoxOnly, int fVerbose )
+{
+    Gia_Man_t * pTemp;
+    Gia_Man_t * pGia = NULL;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k, iPinLit = 0;
+    // prepare logic network
+    assert( Abc_NtkIsLogic(pNtk) );
+    Abc_NtkToAig( pNtk );
+    // construct GIA
+    Abc_NtkFillTemp( pNtk );
+    pGia = Gia_ManStart( Abc_NtkObjNumMax(pNtk) );
+    Gia_ManHashAlloc( pGia );
+    // create primary inputs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->iTemp = Gia_ManAppendCi(pGia);
+    // create internal nodes in a topologic order from white boxes
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        // input side
+        if ( !fWhiteBoxOnly || Abc_NodeIsWhiteBox(pObj) )
+        {
+            // create special pintype for this node
+            iPinLit = Gia_ManAppendPinType( pGia, 1 );
+            // create input pins
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                pFanin->iTemp = Gia_ManAppendAnd( pGia, pFanin->iTemp, iPinLit );
+        }
+        // perform GIA construction
+        pObj->iTemp = Abc_NtkTestTimNodeStrash( pGia, pObj );
+        // output side
+        if ( !fWhiteBoxOnly || Abc_NodeIsWhiteBox(pObj) )
+        {
+            // create special pintype for this node
+            iPinLit = Gia_ManAppendPinType( pGia, 1 );
+            // create output pins
+            pObj->iTemp = Gia_ManAppendAnd( pGia, pObj->iTemp, iPinLit );
+        }
+    }
+    Vec_PtrFree( vNodes );
+    // create primary outputs
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        pObj->iTemp = Gia_ManAppendCo( pGia, Abc_ObjFanin0(pObj)->iTemp );
+    // finalize GIA
+    Gia_ManHashStop( pGia );
+    Gia_ManSetRegNum( pGia, 0 );
+    // clean up GIA
+    pGia = Gia_ManCleanup( pTemp = pGia );
+    Gia_ManStop( pTemp );
+    return pGia;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTestPinGia( Abc_Ntk_t * pNtk, int fWhiteBoxOnly, int fVerbose )
+{
+    Gia_Man_t * pGia;
+    char * pFileName = "testpin.aig";
+    pGia = Abc_NtkTestPinDeriveGia( pNtk, fWhiteBoxOnly, fVerbose );
+    Gia_AigerWrite( pGia, pFileName, 0, 0 );
+    Gia_ManStop( pGia );
+    printf( "AIG with pins derived from mapped network \"%s\" was written into file \"%s\".\n", 
+        Abc_NtkName(pNtk), pFileName );
+}
+
+#endif
+
+/**Function*************************************************************
+
+  Synopsis    [Collect nodes reachable from this box.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTestTimCollectCone_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    if ( Abc_NodeIsTravIdCurrent( pObj ) )
+        return;
+    Abc_NodeSetTravIdCurrent( pObj );
+    if ( Abc_ObjIsCi(pObj) )
+        return;
+    assert( Abc_ObjIsNode( pObj ) );
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        Abc_NtkTestTimCollectCone_rec( pFanin, vNodes );
+    Vec_PtrPush( vNodes, pObj );
+}
+Vec_Ptr_t * Abc_NtkTestTimCollectCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
+{
+    Vec_Ptr_t * vCone = Vec_PtrAlloc( 1000 );
+    if ( pObj != NULL )
+    {
+        // collect for one node
+        assert( Abc_ObjIsNode(pObj) );
+        assert( !Abc_NodeIsTravIdCurrent( pObj ) );
+        Abc_NtkTestTimCollectCone_rec( pObj, vCone );
+        // remove the node because it is a white box
+        Vec_PtrPop( vCone );
+    }
+    else
+    {
+        // collect for all COs
+        Abc_Obj_t * pObj;
+        int i;
+        Abc_NtkForEachCo( pNtk, pObj, i )
+            Abc_NtkTestTimCollectCone_rec( Abc_ObjFanin0(pObj), vCone );
+    }
+    return vCone;
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create arrival times]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Flt_t * Abc_NtkTestCreateArrivals( int nInputs )
+{
+    Vec_Flt_t * p;
+    int i;
+    p = Vec_FltAlloc( nInputs );
+    for ( i = 0; i < nInputs; i++ )
+        Vec_FltPush( p, 1.0*(i % 10) );
+    return p;
+}
+Vec_Flt_t * Abc_NtkTestCreateRequired( int nOutputs )
+{
+    Vec_Flt_t * p;
+    int i;
+    p = Vec_FltAlloc( nOutputs );
+    for ( i = 0; i < nOutputs; i++ )
+        Vec_FltPush( p, 100.0 + 1.0*i );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives GIA manager together with the hierachy manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Abc_NtkTestTimDeriveGia( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    Gia_Man_t * pTemp;
+    Gia_Man_t * pGia = NULL;
+    Gia_Man_t * pHoles = NULL;
+    Tim_Man_t * pTim = NULL;
+    Vec_Int_t * vGiaCoLits, * vGiaCoLits2;
+    Vec_Flt_t * vArrTimes, * vReqTimes;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k, Entry, curPi, curPo, BoxUniqueId;
+    int nBoxFaninMax = 0;
+    assert( Abc_NtkIsTopo(pNtk) );
+    Abc_NtkFillTemp( pNtk );
+
+    // create white boxes
+    curPi = Abc_NtkCiNum(pNtk);
+    curPo = Abc_NtkCoNum(pNtk);
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        pObj->fMarkA = Abc_NodeIsWhiteBox( pObj );
+        if ( !pObj->fMarkA )
+            continue;
+        nBoxFaninMax  = Abc_MaxInt( nBoxFaninMax, Abc_ObjFaninNum(pObj) );
+        curPi++;
+        curPo += Abc_ObjFaninNum(pObj);
+        if ( fVerbose )
+            printf( "Selecting node %6d as white boxes with %d inputs and %d output.\n", i, Abc_ObjFaninNum(pObj), 1 );
+    }
+
+    // construct GIA
+    pGia = Gia_ManStart( Abc_NtkObjNumMax(pNtk) );
+    pHoles = Gia_ManStart( 1000 );
+    for ( i = 0; i < curPi; i++ )
+        Gia_ManAppendCi(pGia);
+    for ( i = 0; i < nBoxFaninMax; i++ )
+        Gia_ManAppendCi(pHoles);
+    Gia_ManHashAlloc( pGia );
+    Gia_ManHashAlloc( pHoles );
+
+    // construct the timing manager
+    pTim = Tim_ManStart( curPi, curPo );
+
+    // assign primary inputs
+    curPi = 0;
+    curPo = 0;
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->iTemp = Abc_Var2Lit( Gia_ObjId(pGia, Gia_ManCi(pGia, curPi++)), 0 );
+    // create internal nodes in a topologic order from white boxes
+    vGiaCoLits = Vec_IntAlloc( 1000 );
+    vGiaCoLits2 = Vec_IntAlloc( 1000 );
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        if ( !pObj->fMarkA ) // not a white box
+        {
+            pObj->iTemp = Abc_NtkTestTimNodeStrash( pGia, pObj );
+            continue;
+        }
+        // create box
+        BoxUniqueId = Abc_ObjFaninNum(pObj); // in this case, the node size is the ID of its delay table
+        Tim_ManCreateBox( pTim, curPo, Abc_ObjFaninNum(pObj), curPi, 1, BoxUniqueId );
+        curPo += Abc_ObjFaninNum(pObj);
+
+        // handle box inputs
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+        {
+            // save CO drivers for the AIG
+            Vec_IntPush( vGiaCoLits, pFanin->iTemp );
+            // load CI nodes for the Holes
+            pFanin->iTemp = Abc_Var2Lit( Gia_ObjId(pHoles, Gia_ManCi(pHoles, k)), 0 );
+        }
+
+        // handle logic of the box
+        pObj->iTemp = Abc_NtkTestTimNodeStrash( pHoles, pObj );
+
+        // handle box outputs
+        // save CO drivers for the Holes
+        Vec_IntPush( vGiaCoLits2, pObj->iTemp );
+//        Gia_ManAppendCo( pHoles, pObj->iTemp );
+        // load CO drivers for the AIG
+        pObj->iTemp = Abc_Var2Lit( Gia_ObjId(pGia, Gia_ManCi(pGia, curPi++)), 0 );
+    }
+    Abc_NtkCleanMarkA( pNtk );
+    // create COs of the AIG
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Gia_ManAppendCo( pGia, Abc_ObjFanin0(pObj)->iTemp );
+    Vec_IntForEachEntry( vGiaCoLits, Entry, i )
+        Gia_ManAppendCo( pGia, Entry );
+    Vec_IntFree( vGiaCoLits );
+    // second AIG
+    Vec_IntForEachEntry( vGiaCoLits2, Entry, i )
+        Gia_ManAppendCo( pHoles, Entry );
+    Vec_IntFree( vGiaCoLits2 );
+    // check parameters
+    curPo += Abc_NtkPoNum( pNtk );
+    assert( curPi == Gia_ManPiNum(pGia) );
+    assert( curPo == Gia_ManPoNum(pGia) );
+    // finalize GIA
+    Gia_ManHashStop( pGia );
+    Gia_ManSetRegNum( pGia, 0 );
+    Gia_ManHashStop( pHoles );
+    Gia_ManSetRegNum( pHoles, 0 );
+
+    // clean up GIA
+    pGia = Gia_ManCleanup( pTemp = pGia );
+    Gia_ManStop( pTemp );
+    pHoles = Gia_ManCleanup( pTemp = pHoles );
+    Gia_ManStop( pTemp );
+
+    // attach the timing manager
+    assert( pGia->pManTime == NULL );
+    pGia->pManTime = pTim;
+
+    // derive hierarchy manager from box info and input/output arrival/required info
+    vArrTimes = Abc_NtkTestCreateArrivals( Abc_NtkPiNum(pNtk) );
+    vReqTimes = Abc_NtkTestCreateRequired( Abc_NtkPoNum(pNtk) );
+
+    Tim_ManPrint( (Tim_Man_t *)pGia->pManTime );
+    Tim_ManCreate( (Tim_Man_t *)pGia->pManTime, Abc_FrameReadLibBox(), vArrTimes, vReqTimes );
+    Tim_ManPrint( (Tim_Man_t *)pGia->pManTime );
+
+    Vec_FltFree( vArrTimes );
+    Vec_FltFree( vReqTimes );
+
+Gia_AigerWrite( pHoles, "holes00.aig", 0, 0 );
+
+    // return 
+    pGia->pAigExtra = pHoles;
+    return pGia;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs synthesis with or without structural choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Abc_NtkTestTimPerformSynthesis( Gia_Man_t * p, int fChoices )
+{
+    Gia_Man_t * pGia;
+    Aig_Man_t * pNew, * pTemp;
+    Dch_Pars_t Pars, * pPars = &Pars;
+    Dch_ManSetDefaultParams( pPars );
+    pNew = Gia_ManToAig( p, 0 );
+    if ( fChoices )
+        pNew = Dar_ManChoiceNew( pNew, pPars );
+    else
+    {
+        pNew = Dar_ManCompress2( pTemp = pNew, 1, 1, 1, 0, 0 );
+        Aig_ManStop( pTemp );
+    }
+    pGia = Gia_ManFromAig( pNew );
+    Aig_ManStop( pNew );
+    return pGia;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManVerifyChoices( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, iRepr, iNode, fProb = 0;
+    assert( p->pReprs );
+
+    // mark nodes 
+    Gia_ManCleanMark0(p);
+    Gia_ManForEachClass( p, iRepr )
+        Gia_ClassForEachObj1( p, iRepr, iNode )
+        {
+            if ( Gia_ObjIsHead(p, iNode) )
+                printf( "Member %d of choice class %d is a representative.\n", iNode, iRepr ), fProb = 1;
+            if ( Gia_ManObj( p, iNode )->fMark0 == 1 )
+                printf( "Node %d participates in more than one choice node.\n", iNode ), fProb = 1;
+            Gia_ManObj( p, iNode )->fMark0 = 1;
+        }
+    Gia_ManCleanMark0(p);
+
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            if ( Gia_ObjHasRepr(p, Gia_ObjFaninId0(pObj, i)) )
+                printf( "Fanin 0 of AND node %d has a repr.\n", i ), fProb = 1;
+            if ( Gia_ObjHasRepr(p, Gia_ObjFaninId1(pObj, i)) )
+                printf( "Fanin 1 of AND node %d has a repr.\n", i ), fProb = 1;
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+        {
+            if ( Gia_ObjHasRepr(p, Gia_ObjFaninId0(pObj, i)) )
+                printf( "Fanin 0 of CO node %d has a repr.\n", i ), fProb = 1;
+        }
+    }
+//    if ( !fProb )
+//        printf( "GIA with choices is correct.\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reverse the order of nodes in equiv classes.]
+
+  Description [If the flag is 1, assumed current increasing order ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManReverseClasses( Gia_Man_t * p, int fNowIncreasing )
+{
+    Vec_Int_t * vCollected;
+    Vec_Int_t * vClass;
+    int i, k, iRepr, iNode, iPrev;
+    // collect classes
+    vCollected = Vec_IntAlloc( 100 );
+    Gia_ManForEachClass( p, iRepr )
+        Vec_IntPush( vCollected, iRepr );
+    // correct each class
+    vClass = Vec_IntAlloc( 100 );
+    Vec_IntForEachEntry( vCollected, iRepr, i )
+    {
+        Vec_IntClear( vClass );
+        Vec_IntPush( vClass, iRepr );
+        Gia_ClassForEachObj1( p, iRepr, iNode )
+        {
+            if ( fNowIncreasing )
+                assert( iRepr < iNode );
+            else
+                assert( iRepr > iNode );
+            Vec_IntPush( vClass, iNode );
+        }
+//        if ( !fNowIncreasing )
+//            Vec_IntSort( vClass, 1 );
+        // reverse the class
+        iPrev = 0;
+        iRepr = Vec_IntEntryLast( vClass );
+        Vec_IntForEachEntry( vClass, iNode, k )
+        {
+            if ( fNowIncreasing )
+                Gia_ObjSetReprRev( p, iNode, iNode == iRepr ? GIA_VOID : iRepr );
+            else
+                Gia_ObjSetRepr( p, iNode, iNode == iRepr ? GIA_VOID : iRepr );
+            Gia_ObjSetNext( p, iNode, iPrev );
+            iPrev = iNode;
+        }
+    }
+    Vec_IntFree( vCollected );
+    Vec_IntFree( vClass );
+    // verify
+    Gia_ManForEachClass( p, iRepr )
+        Gia_ClassForEachObj1( p, iRepr, iNode )
+            if ( fNowIncreasing )
+                assert( Gia_ObjRepr(p, iNode) == iRepr && iRepr > iNode );
+            else
+                assert( Gia_ObjRepr(p, iNode) == iRepr && iRepr < iNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tests the hierarchy-timing manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTestTimByWritingFile( Gia_Man_t * pGia, char * pFileName )
+{
+    Gia_Man_t * pGia2;
+
+    // normalize choices
+    if ( Gia_ManHasChoices(pGia) )
+    {
+        Gia_ManVerifyChoices( pGia );
+        Gia_ManReverseClasses( pGia, 0 );
+    }
+    // write file
+    Gia_AigerWrite( pGia, pFileName, 0, 0 );
+    // unnormalize choices
+    if ( Gia_ManHasChoices(pGia) )
+        Gia_ManReverseClasses( pGia, 1 );
+
+    // read file
+    pGia2 = Gia_AigerRead( pFileName, 1, 1 );
+
+    // normalize choices
+    if ( Gia_ManHasChoices(pGia2) )
+    {
+        Gia_ManVerifyChoices( pGia2 );
+        Gia_ManReverseClasses( pGia2, 1 );
+    }
+
+    // compare resulting managers
+    if ( Gia_ManCompare( pGia, pGia2 ) )
+        printf( "Verification suceessful.\n" );
+
+    Gia_ManStop( pGia2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tests construction and serialization.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTestTim( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    int fUseChoices = 0;
+    Gia_Man_t * pGia, * pTemp;
+
+    // this test only works for a logic network (for example, network with LUT mapping)
+    assert( Abc_NtkIsLogic(pNtk) );
+    // make sure local functions of the nodes are in the AIG form
+    Abc_NtkToAig( pNtk );
+
+    // create GIA manager (pGia) with hierarhy/timing manager attached (pGia->pManTime)
+    // while assuming that some nodes are white boxes (see Abc_NodeIsWhiteBox)
+    pGia = Abc_NtkTestTimDeriveGia( pNtk, fVerbose );
+    printf( "Created GIA manager for network with %d white boxes.\n", Tim_ManBoxNum((Tim_Man_t *)pGia->pManTime) );
+
+    // print the timing manager
+    if ( fVerbose )
+        Tim_ManPrint( (Tim_Man_t *)pGia->pManTime );
+
+    // test writing both managers into a file and reading them back
+    Abc_NtkTestTimByWritingFile( pGia, "test1.aig" );
+
+    // perform synthesis
+    pGia = Abc_NtkTestTimPerformSynthesis( pTemp = pGia, fUseChoices );
+    Gia_ManStop( pTemp );
+
+    // test writing both managers into a file and reading them back
+    Abc_NtkTestTimByWritingFile( pGia, "test2.aig" );
+
+    Gia_ManStop( pGia );
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcTiming.c b/abc-build/src/base/abci/abcTiming.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcTiming.c
@@ -0,0 +1,1321 @@
+/**CFile****************************************************************
+
+  FileName    [abcTiming.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Computation of timing info for mapped circuits.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcTiming.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/main.h"
+#include "map/mio/mio.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+struct Abc_ManTime_t_
+{
+    Abc_Time_t     tArrDef;
+    Abc_Time_t     tReqDef;
+    Vec_Ptr_t  *   vArrs;
+    Vec_Ptr_t  *   vReqs;
+    Abc_Time_t     tInDriveDef;
+    Abc_Time_t     tOutLoadDef;
+    Abc_Time_t *   tInDrive;
+    Abc_Time_t *   tOutLoad;
+};
+
+// static functions
+static Abc_ManTime_t *     Abc_ManTimeStart( Abc_Ntk_t * pNtk );
+static void                Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive );
+
+// accessing the arrival and required times of a node
+static inline Abc_Time_t * Abc_NodeArrival( Abc_Obj_t * pNode )  {  return (Abc_Time_t *)pNode->pNtk->pManTime->vArrs->pArray[pNode->Id];  }
+static inline Abc_Time_t * Abc_NodeRequired( Abc_Obj_t * pNode ) {  return (Abc_Time_t *)pNode->pNtk->pManTime->vReqs->pArray[pNode->Id];  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the arrival.required time of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Time_t * Abc_NtkReadDefaultArrival( Abc_Ntk_t * pNtk )
+{
+    assert( pNtk->pManTime );
+    return &pNtk->pManTime->tArrDef;
+}
+Abc_Time_t * Abc_NtkReadDefaultRequired( Abc_Ntk_t * pNtk )
+{
+    assert( pNtk->pManTime );
+    return &pNtk->pManTime->tReqDef;
+}
+Abc_Time_t * Abc_NodeReadArrival( Abc_Obj_t * pNode )
+{
+    assert( pNode->pNtk->pManTime );
+    return Abc_NodeArrival(pNode);
+}
+Abc_Time_t * Abc_NodeReadRequired( Abc_Obj_t * pNode )
+{
+    assert( pNode->pNtk->pManTime );
+    return Abc_NodeRequired(pNode);
+}
+float Abc_NodeReadArrivalAve( Abc_Obj_t * pNode )
+{
+    return 0.5 * Abc_NodeArrival(pNode)->Rise + 0.5 * Abc_NodeArrival(pNode)->Fall;
+}
+float Abc_NodeReadRequiredAve( Abc_Obj_t * pNode )
+{
+    return 0.5 * Abc_NodeReadRequired(pNode)->Rise + 0.5 * Abc_NodeReadRequired(pNode)->Fall;
+}
+float Abc_NodeReadArrivalWorst( Abc_Obj_t * pNode )
+{
+    return Abc_MaxFloat( Abc_NodeArrival(pNode)->Rise, Abc_NodeArrival(pNode)->Fall );
+}
+float Abc_NodeReadRequiredWorst( Abc_Obj_t * pNode )
+{
+    return Abc_MaxFloat( Abc_NodeReadRequired(pNode)->Rise, Abc_NodeReadRequired(pNode)->Fall );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the input drive / output load of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Time_t * Abc_NtkReadDefaultInputDrive( Abc_Ntk_t * pNtk )
+{
+    assert( pNtk->pManTime );
+    return &pNtk->pManTime->tInDriveDef;
+}
+Abc_Time_t * Abc_NtkReadDefaultOutputLoad( Abc_Ntk_t * pNtk )
+{
+    assert( pNtk->pManTime );
+    return &pNtk->pManTime->tOutLoadDef;
+}
+Abc_Time_t * Abc_NodeReadInputDrive( Abc_Ntk_t * pNtk, int iPi )
+{
+    assert( pNtk->pManTime );
+    return pNtk->pManTime->tInDrive ? pNtk->pManTime->tInDrive + iPi : NULL;
+}
+Abc_Time_t * Abc_NodeReadOutputLoad( Abc_Ntk_t * pNtk, int iPo )
+{
+    assert( pNtk->pManTime );
+    return pNtk->pManTime->tOutLoad ? pNtk->pManTime->tOutLoad + iPo : NULL;
+}
+float Abc_NodeReadInputDriveWorst( Abc_Ntk_t * pNtk, int iPi )
+{
+    return Abc_MaxFloat( Abc_NodeReadInputDrive(pNtk, iPi)->Rise, Abc_NodeReadInputDrive(pNtk, iPi)->Fall );
+}
+float Abc_NodeReadOutputLoadWorst( Abc_Ntk_t * pNtk, int iPo )
+{
+    return Abc_MaxFloat( Abc_NodeReadOutputLoad(pNtk, iPo)->Rise, Abc_NodeReadOutputLoad(pNtk, iPo)->Fall );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the default arrival time for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTimeSetDefaultArrival( Abc_Ntk_t * pNtk, float Rise, float Fall )
+{
+    if ( Rise == 0.0 && Fall == 0.0 )
+        return;
+    if ( pNtk->pManTime == NULL )
+        pNtk->pManTime = Abc_ManTimeStart(pNtk);
+    pNtk->pManTime->tArrDef.Rise  = Rise;
+    pNtk->pManTime->tArrDef.Fall  = Fall;
+}
+void Abc_NtkTimeSetDefaultRequired( Abc_Ntk_t * pNtk, float Rise, float Fall )
+{
+    if ( Rise == 0.0 && Fall == 0.0 )
+        return;
+    if ( pNtk->pManTime == NULL )
+        pNtk->pManTime = Abc_ManTimeStart(pNtk);
+    pNtk->pManTime->tReqDef.Rise  = Rise;
+    pNtk->pManTime->tReqDef.Fall  = Fall;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the arrival time for an object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTimeSetArrival( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall )
+{
+    Vec_Ptr_t * vTimes;
+    Abc_Time_t * pTime;
+    if ( pNtk->pManTime == NULL )
+        pNtk->pManTime = Abc_ManTimeStart(pNtk);
+    if ( pNtk->pManTime->tArrDef.Rise == Rise && pNtk->pManTime->tArrDef.Fall == Fall )
+        return;
+    Abc_ManTimeExpand( pNtk->pManTime, ObjId + 1, 1 );
+    // set the arrival time
+    vTimes = pNtk->pManTime->vArrs;
+    pTime = (Abc_Time_t *)vTimes->pArray[ObjId];
+    pTime->Rise  = Rise;
+    pTime->Fall  = Fall;
+}
+void Abc_NtkTimeSetRequired( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall )
+{
+    Vec_Ptr_t * vTimes;
+    Abc_Time_t * pTime;
+    if ( pNtk->pManTime == NULL )
+        pNtk->pManTime = Abc_ManTimeStart(pNtk);
+    if ( pNtk->pManTime->tReqDef.Rise == Rise && pNtk->pManTime->tReqDef.Fall == Fall )
+        return;
+    Abc_ManTimeExpand( pNtk->pManTime, ObjId + 1, 1 );
+    // set the required time
+    vTimes = pNtk->pManTime->vReqs;
+    pTime = (Abc_Time_t *)vTimes->pArray[ObjId];
+    pTime->Rise  = Rise;
+    pTime->Fall  = Fall;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the default arrival time for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTimeSetDefaultInputDrive( Abc_Ntk_t * pNtk, float Rise, float Fall )
+{
+    if ( Rise == 0.0 && Fall == 0.0 )
+        return;
+    if ( pNtk->pManTime == NULL )
+        pNtk->pManTime = Abc_ManTimeStart(pNtk);
+    pNtk->pManTime->tInDriveDef.Rise  = Rise;
+    pNtk->pManTime->tInDriveDef.Fall  = Fall;
+    if ( pNtk->pManTime->tInDrive != NULL )
+    {
+        int i;
+        for ( i = 0; i < Abc_NtkCiNum(pNtk); i++ )
+            if ( pNtk->pManTime->tInDrive[i].Rise == 0 && pNtk->pManTime->tInDrive[i].Fall == 0 )
+                pNtk->pManTime->tInDrive[i] = pNtk->pManTime->tInDriveDef;
+    }
+}
+void Abc_NtkTimeSetDefaultOutputLoad( Abc_Ntk_t * pNtk, float Rise, float Fall )
+{
+    if ( Rise == 0.0 && Fall == 0.0 )
+        return;
+    if ( pNtk->pManTime == NULL )
+        pNtk->pManTime = Abc_ManTimeStart(pNtk);
+    pNtk->pManTime->tOutLoadDef.Rise  = Rise;
+    pNtk->pManTime->tOutLoadDef.Fall  = Fall;
+    if ( pNtk->pManTime->tOutLoad != NULL )
+    {
+        int i;
+        for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ )
+            if ( pNtk->pManTime->tOutLoad[i].Rise == 0 && pNtk->pManTime->tOutLoad[i].Fall == 0 )
+                pNtk->pManTime->tOutLoad[i] = pNtk->pManTime->tOutLoadDef;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the arrival time for an object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTimeSetInputDrive( Abc_Ntk_t * pNtk, int PiNum, float Rise, float Fall )
+{
+    Abc_Time_t * pTime;
+    assert( PiNum >= 0 && PiNum < Abc_NtkCiNum(pNtk) );
+    if ( pNtk->pManTime == NULL )
+        pNtk->pManTime = Abc_ManTimeStart(pNtk);
+    if ( pNtk->pManTime->tInDriveDef.Rise == Rise && pNtk->pManTime->tInDriveDef.Fall == Fall )
+        return;
+    if ( pNtk->pManTime->tInDrive == NULL )
+    {
+        int i;
+        pNtk->pManTime->tInDrive = ABC_CALLOC( Abc_Time_t, Abc_NtkCiNum(pNtk) );
+        for ( i = 0; i < Abc_NtkCiNum(pNtk); i++ )
+            pNtk->pManTime->tInDrive[i] = pNtk->pManTime->tInDriveDef;
+    }
+    pTime = pNtk->pManTime->tInDrive + PiNum;
+    pTime->Rise  = Rise;
+    pTime->Fall  = Fall;
+}
+void Abc_NtkTimeSetOutputLoad( Abc_Ntk_t * pNtk, int PoNum, float Rise, float Fall )
+{
+    Abc_Time_t * pTime;
+    assert( PoNum >= 0 && PoNum < Abc_NtkCoNum(pNtk) );
+    if ( pNtk->pManTime == NULL )
+        pNtk->pManTime = Abc_ManTimeStart(pNtk);
+    if ( pNtk->pManTime->tOutLoadDef.Rise == Rise && pNtk->pManTime->tOutLoadDef.Fall == Fall )
+        return;
+    if ( pNtk->pManTime->tOutLoad == NULL )
+    {
+        int i;
+        pNtk->pManTime->tOutLoad = ABC_CALLOC( Abc_Time_t, Abc_NtkCoNum(pNtk) );
+        for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ )
+            pNtk->pManTime->tOutLoad[i] = pNtk->pManTime->tOutLoadDef;
+    }
+    pTime = pNtk->pManTime->tOutLoad + PoNum;
+    pTime->Rise  = Rise;
+    pTime->Fall  = Fall;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finalizes the timing manager after setting arr/req times.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkOld )
+{
+    Abc_Obj_t * pObj;
+    Abc_Time_t ** ppTimes, * pTime;
+    int i;
+    assert( pNtkOld == NULL || pNtkOld->pManTime != NULL );
+    assert( pNtkOld == NULL || Abc_NtkCiNum(pNtk) == Abc_NtkCiNum(pNtkOld) );
+    assert( pNtkOld == NULL || Abc_NtkCoNum(pNtk) == Abc_NtkCoNum(pNtkOld) );
+    if ( pNtk->pManTime == NULL )
+        return;
+    Abc_ManTimeExpand( pNtk->pManTime, Abc_NtkObjNumMax(pNtk), 0 );
+    // set global defaults
+    if ( pNtkOld )
+    {
+        pNtk->pManTime->tArrDef = pNtkOld->pManTime->tArrDef;
+        pNtk->pManTime->tReqDef = pNtkOld->pManTime->tReqDef;
+        pNtk->AndGateDelay = pNtkOld->AndGateDelay;
+    }
+    // set the default timing
+    ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray;
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        pTime = ppTimes[pObj->Id];
+        if ( Abc_MaxFloat(pTime->Fall, pTime->Rise) != -ABC_INFINITY )
+            continue;
+        *pTime = pNtkOld ? *Abc_NodeReadArrival(Abc_NtkCi(pNtkOld, i)) : pNtk->pManTime->tArrDef;
+    }
+    // set the default timing
+    ppTimes = (Abc_Time_t **)pNtk->pManTime->vReqs->pArray;
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        pTime = ppTimes[pObj->Id];
+        if ( Abc_MaxFloat(pTime->Fall, pTime->Rise) != ABC_INFINITY )
+            continue;
+        *pTime = pNtkOld ? *Abc_NodeReadRequired(Abc_NtkCo(pNtkOld, i)) : pNtk->pManTime->tReqDef;
+    }
+    // set the 0 arrival times for latch outputs and constant nodes
+    ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray;
+    Abc_NtkForEachLatchOutput( pNtk, pObj, i )
+    {
+        pTime = ppTimes[pObj->Id];
+        pTime->Fall = pTime->Rise = 0.0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the timing manager for delay trace.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    Abc_Time_t ** ppTimes, * pTime;
+    int i;
+    // if there is no timing manager, allocate and initialize
+    if ( pNtk->pManTime == NULL )
+    {
+        pNtk->pManTime = Abc_ManTimeStart(pNtk);
+        Abc_NtkTimeInitialize( pNtk, NULL );
+        return;
+    }
+    // if timing manager is given, expand it if necessary
+    Abc_ManTimeExpand( pNtk->pManTime, Abc_NtkObjNumMax(pNtk), 0 );
+    // clean arrivals except for PIs
+    ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray;
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        pTime = ppTimes[pObj->Id];
+        pTime->Fall = pTime->Rise = -ABC_INFINITY;
+    }
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        pTime = ppTimes[pObj->Id];
+        pTime->Fall = pTime->Rise = -ABC_INFINITY;
+    }
+    // clean required except for POs
+    ppTimes = (Abc_Time_t **)pNtk->pManTime->vReqs->pArray;
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        pTime = ppTimes[pObj->Id];
+        pTime->Fall = pTime->Rise = ABC_INFINITY;
+    }
+    Abc_NtkForEachCi( pNtk, pObj, i )
+    {
+        pTime = ppTimes[pObj->Id];
+        pTime->Fall = pTime->Rise = ABC_INFINITY;
+    }
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_ManTime_t * Abc_ManTimeStart( Abc_Ntk_t * pNtk )
+{
+    Abc_ManTime_t * p;
+    p = ABC_ALLOC( Abc_ManTime_t, 1 );
+    memset( p, 0, sizeof(Abc_ManTime_t) );
+    p->vArrs = Vec_PtrAlloc( 0 );
+    p->vReqs = Vec_PtrAlloc( 0 );
+    p->tReqDef.Rise = ABC_INFINITY;
+    p->tReqDef.Fall = ABC_INFINITY;
+    Abc_ManTimeExpand( p, Abc_NtkObjNumMax(pNtk) + 1, 0 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ManTimeStop( Abc_ManTime_t * p )
+{
+    if ( p->tInDrive )
+        ABC_FREE( p->tInDrive );
+    if ( p->tOutLoad )
+        ABC_FREE( p->tOutLoad );
+    if ( Vec_PtrSize(p->vArrs) > 0 )
+        ABC_FREE( p->vArrs->pArray[0] );
+    Vec_PtrFree( p->vArrs );
+    if ( Vec_PtrSize(p->vReqs) > 0 )
+        ABC_FREE( p->vReqs->pArray[0] );
+    Vec_PtrFree( p->vReqs );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the timing manager with the PI/PO timing info.]
+
+  Description [The PIs/POs of the new network should be allocated.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ManTimeDup( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew )
+{
+    Abc_Obj_t * pObj;
+    Abc_Time_t ** ppTimesOld, ** ppTimesNew;
+    int i;
+    if ( pNtkOld->pManTime == NULL )
+        return;
+    assert( Abc_NtkCiNum(pNtkOld) == Abc_NtkCiNum(pNtkNew) );
+    assert( Abc_NtkCoNum(pNtkOld) == Abc_NtkCoNum(pNtkNew) );
+    assert( Abc_NtkLatchNum(pNtkOld) == Abc_NtkLatchNum(pNtkNew) );
+    // create the new timing manager
+    pNtkNew->pManTime = Abc_ManTimeStart(pNtkNew);
+    Abc_ManTimeExpand( pNtkNew->pManTime, Abc_NtkObjNumMax(pNtkNew), 0 );
+    // set the default timing
+    pNtkNew->pManTime->tArrDef = pNtkOld->pManTime->tArrDef;
+    pNtkNew->pManTime->tReqDef = pNtkOld->pManTime->tReqDef;
+    // set the CI timing
+    ppTimesOld = (Abc_Time_t **)pNtkOld->pManTime->vArrs->pArray;
+    ppTimesNew = (Abc_Time_t **)pNtkNew->pManTime->vArrs->pArray;
+    Abc_NtkForEachCi( pNtkOld, pObj, i )
+        *ppTimesNew[ Abc_NtkCi(pNtkNew,i)->Id ] = *ppTimesOld[ pObj->Id ];
+    // set the CO timing
+    ppTimesOld = (Abc_Time_t **)pNtkOld->pManTime->vReqs->pArray;
+    ppTimesNew = (Abc_Time_t **)pNtkNew->pManTime->vReqs->pArray;
+    Abc_NtkForEachCo( pNtkOld, pObj, i )
+        *ppTimesNew[ Abc_NtkCo(pNtkNew,i)->Id ] = *ppTimesOld[ pObj->Id ];
+    // duplicate input drive
+    pNtkNew->pManTime->tInDriveDef = pNtkOld->pManTime->tInDriveDef; 
+    pNtkNew->pManTime->tOutLoadDef = pNtkOld->pManTime->tOutLoadDef; 
+    if ( pNtkOld->pManTime->tInDrive )
+    {
+        pNtkNew->pManTime->tInDrive = ABC_ALLOC( Abc_Time_t, Abc_NtkCiNum(pNtkOld) );
+        memcpy( pNtkNew->pManTime->tInDrive, pNtkOld->pManTime->tInDrive, sizeof(Abc_Time_t) * Abc_NtkCiNum(pNtkOld) );
+    }
+    if ( pNtkOld->pManTime->tOutLoad )
+    {
+        pNtkNew->pManTime->tOutLoad = ABC_ALLOC( Abc_Time_t, Abc_NtkCiNum(pNtkOld) );
+        memcpy( pNtkNew->pManTime->tOutLoad, pNtkOld->pManTime->tOutLoad, sizeof(Abc_Time_t) * Abc_NtkCoNum(pNtkOld) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Expends the storage for timing information.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive )
+{
+    Vec_Ptr_t * vTimes;
+    Abc_Time_t * ppTimes, * ppTimesOld, * pTime;
+    int nSizeOld, nSizeNew, i;
+
+    nSizeOld = p->vArrs->nSize;
+    if ( nSizeOld >= nSize )
+        return;
+    nSizeNew = fProgressive? 2 * nSize : nSize;
+    if ( nSizeNew < 100 )
+        nSizeNew = 100;
+
+    vTimes = p->vArrs;
+    Vec_PtrGrow( vTimes, nSizeNew );
+    vTimes->nSize = nSizeNew;
+    ppTimesOld = ( nSizeOld == 0 )? NULL : (Abc_Time_t *)vTimes->pArray[0];
+    ppTimes = ABC_REALLOC( Abc_Time_t, ppTimesOld, nSizeNew );
+    for ( i = 0; i < nSizeNew; i++ )
+        vTimes->pArray[i] = ppTimes + i;
+    for ( i = nSizeOld; i < nSizeNew; i++ )
+    {
+        pTime = (Abc_Time_t *)vTimes->pArray[i];
+        pTime->Rise  = -ABC_INFINITY;
+        pTime->Fall  = -ABC_INFINITY;
+    }
+
+    vTimes = p->vReqs;
+    Vec_PtrGrow( vTimes, nSizeNew );
+    vTimes->nSize = nSizeNew;
+    ppTimesOld = ( nSizeOld == 0 )? NULL : (Abc_Time_t *)vTimes->pArray[0];
+    ppTimes = ABC_REALLOC( Abc_Time_t, ppTimesOld, nSizeNew );
+    for ( i = 0; i < nSizeNew; i++ )
+        vTimes->pArray[i] = ppTimes + i;
+    for ( i = nSizeOld; i < nSizeNew; i++ )
+    {
+        pTime = (Abc_Time_t *)vTimes->pArray[i];
+        pTime->Rise  = ABC_INFINITY;
+        pTime->Fall  = ABC_INFINITY;
+    }
+}
+
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the CI node levels according to the arrival info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtkOld )
+{
+    Abc_Obj_t * pNodeOld, * pNodeNew;
+    float tAndDelay;
+    int i;
+    if ( pNtkOld->pManTime == NULL )
+        return;
+    if ( Abc_FrameReadLibGen() == NULL || Mio_LibraryReadNand2((Mio_Library_t *)Abc_FrameReadLibGen()) == NULL )
+        return;
+    tAndDelay = Mio_LibraryReadDelayNand2Max((Mio_Library_t *)Abc_FrameReadLibGen());
+    Abc_NtkForEachCi( pNtkOld, pNodeOld, i )
+    {
+        pNodeNew = pNodeOld->pCopy;
+        pNodeNew->Level = (int)(Abc_NodeReadArrivalWorst(pNodeOld) / tAndDelay);
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the CI node levels according to the arrival info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Time_t * Abc_NtkGetCiArrivalTimes( Abc_Ntk_t * pNtk )
+{
+    Abc_Time_t * p;
+    Abc_Obj_t * pNode;
+    int i;
+    p = ABC_CALLOC( Abc_Time_t, Abc_NtkCiNum(pNtk) );
+    if ( pNtk->pManTime == NULL )
+        return p;
+    // set the PI arrival times
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        p[i] = *Abc_NodeArrival(pNode);
+    return p;
+}
+Abc_Time_t * Abc_NtkGetCoRequiredTimes( Abc_Ntk_t * pNtk )
+{
+    Abc_Time_t * p;
+    Abc_Obj_t * pNode;
+    int i;
+    p = ABC_CALLOC( Abc_Time_t, Abc_NtkCoNum(pNtk) );
+    if ( pNtk->pManTime == NULL )
+        return p;
+    // set the PO required times
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        p[i] = *Abc_NodeRequired(pNode);
+    return p;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the CI node levels according to the arrival info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float * Abc_NtkGetCiArrivalFloats( Abc_Ntk_t * pNtk )
+{
+    float * p;
+    Abc_Obj_t * pNode;
+    int i;
+    p = ABC_CALLOC( float, Abc_NtkCiNum(pNtk) );
+    if ( pNtk->pManTime == NULL )
+        return p;
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        if ( Abc_NodeReadArrivalWorst(pNode) != 0 )
+            break;
+    if ( i == Abc_NtkCiNum(pNtk) )
+        return NULL;
+    // set the PI arrival times
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        p[i] = Abc_NodeReadArrivalWorst(pNode);
+    return p;
+}
+float * Abc_NtkGetCoRequiredFloats( Abc_Ntk_t * pNtk )
+{
+    float * p;
+    Abc_Obj_t * pNode;
+    int i;
+    if ( pNtk->pManTime == NULL )
+        return NULL;
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        if ( Abc_NodeReadRequiredWorst(pNode) != ABC_INFINITY )
+            break;
+    if ( i == Abc_NtkCoNum(pNtk) )
+        return NULL;
+    // set the PO required times
+    p = ABC_CALLOC( float, Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        p[i] = Abc_NodeReadRequiredWorst(pNode);
+    return p;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkDelayTraceSlackStart( Abc_Ntk_t * pNtk )
+{
+    Vec_Int_t * vSlacks;
+    Abc_Obj_t * pObj;
+    int i, k;
+    vSlacks = Vec_IntAlloc( Abc_NtkObjNumMax(pNtk) + Abc_NtkGetTotalFanins(pNtk) );
+    Vec_IntFill( vSlacks, Abc_NtkObjNumMax(pNtk), -1 );
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        Vec_IntWriteEntry( vSlacks, i, Vec_IntSize(vSlacks) );
+        for ( k = 0; k < Abc_ObjFaninNum(pObj); k++ )
+            Vec_IntPush( vSlacks, -1 );
+    }
+//    assert( Abc_MaxInt(16, Vec_IntSize(vSlacks)) == Vec_IntCap(vSlacks) );
+    return vSlacks;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read/write edge slacks.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline float Abc_NtkDelayTraceSlack( Vec_Int_t * vSlacks, Abc_Obj_t * pObj, int iFanin )
+{
+    return Abc_Int2Float( Vec_IntEntry( vSlacks, Vec_IntEntry(vSlacks, Abc_ObjId(pObj)) + iFanin ) );
+}
+static inline void Abc_NtkDelayTraceSetSlack( Vec_Int_t * vSlacks, Abc_Obj_t * pObj, int iFanin, float Num )
+{
+    Vec_IntWriteEntry( vSlacks, Vec_IntEntry(vSlacks, Abc_ObjId(pObj)) + iFanin, Abc_Float2Int(Num) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find most-critical path (the path with smallest slacks).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkDelayTraceCritPath_rec( Vec_Int_t * vSlacks, Abc_Obj_t * pNode, Abc_Obj_t * pLeaf, Vec_Int_t * vBest )
+{
+    Abc_Obj_t * pFanin, * pFaninBest = NULL;
+    float SlackMin = ABC_INFINITY;
+    int i;
+    // check primary inputs
+    if ( Abc_ObjIsCi(pNode) )
+        return (pLeaf == NULL || pLeaf == pNode);
+    assert( Abc_ObjIsNode(pNode) );
+    // check visited
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return Vec_IntEntry(vBest, Abc_ObjId(pNode)) >= 0;
+    Abc_NodeSetTravIdCurrent( pNode );
+    // check the node
+    assert( Abc_ObjIsNode(pNode) );
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        if ( !Abc_NtkDelayTraceCritPath_rec( vSlacks, pFanin, pLeaf, vBest ) )
+            continue;
+        if ( pFaninBest == NULL || SlackMin > Abc_NtkDelayTraceSlack(vSlacks, pNode, i) )
+        {
+            pFaninBest = pFanin;
+            SlackMin = Abc_NtkDelayTraceSlack(vSlacks, pNode, i);
+        }
+    }
+    if ( pFaninBest != NULL )
+        Vec_IntWriteEntry( vBest, Abc_ObjId(pNode), Abc_NodeFindFanin(pNode, pFaninBest) );
+    return (pFaninBest != NULL);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find most-critical path (the path with smallest slacks).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkDelayTraceCritPathCollect_rec( Vec_Int_t * vSlacks, Abc_Obj_t * pNode, Vec_Int_t * vBest, Vec_Ptr_t * vPath )
+{
+    assert( Abc_ObjIsCi(pNode) || Abc_ObjIsNode(pNode) );
+    if ( Abc_ObjIsNode(pNode) )
+    {
+        int iFanin = Vec_IntEntry( vBest, Abc_ObjId(pNode) );
+        assert( iFanin >= 0 );
+        Abc_NtkDelayTraceCritPathCollect_rec( vSlacks, Abc_ObjFanin(pNode, iFanin), vBest, vPath );
+    }
+    Vec_PtrPush( vPath, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode, Vec_Int_t * vSlacks )
+{
+    Abc_Obj_t * pFanin;
+    Abc_Time_t * pTimeIn, * pTimeOut;
+    float tDelayBlockRise, tDelayBlockFall;
+    Mio_PinPhase_t PinPhase;
+    Mio_Pin_t * pPin;
+    int i;
+
+    // start the arrival time of the node
+    pTimeOut = Abc_NodeArrival(pNode);
+    pTimeOut->Rise = pTimeOut->Fall = -ABC_INFINITY; 
+    // go through the pins of the gate
+    pPin = Mio_GateReadPins((Mio_Gate_t *)pNode->pData);
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        pTimeIn = Abc_NodeArrival(pFanin);
+        // get the interesting parameters of this pin
+        PinPhase = Mio_PinReadPhase(pPin);
+        tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin );  
+        tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin );  
+        // compute the arrival times of the positive phase
+        if ( PinPhase != MIO_PHASE_INV )  // NONINV phase is present
+        {
+            if ( pTimeOut->Rise < pTimeIn->Rise + tDelayBlockRise )
+                pTimeOut->Rise = pTimeIn->Rise + tDelayBlockRise;
+            if ( pTimeOut->Fall < pTimeIn->Fall + tDelayBlockFall )
+                pTimeOut->Fall = pTimeIn->Fall + tDelayBlockFall;
+        }
+        if ( PinPhase != MIO_PHASE_NONINV )  // INV phase is present
+        {
+            if ( pTimeOut->Rise < pTimeIn->Fall + tDelayBlockRise )
+                pTimeOut->Rise = pTimeIn->Fall + tDelayBlockRise;
+            if ( pTimeOut->Fall < pTimeIn->Rise + tDelayBlockFall )
+                pTimeOut->Fall = pTimeIn->Rise + tDelayBlockFall;
+        }
+        pPin = Mio_PinReadNext(pPin);
+    }
+
+    // compute edge slacks
+    if ( vSlacks )
+    {
+        float Slack;
+        // go through the pins of the gate
+        pPin = Mio_GateReadPins((Mio_Gate_t *)pNode->pData);
+        Abc_ObjForEachFanin( pNode, pFanin, i )
+        {
+            pTimeIn = Abc_NodeArrival(pFanin);
+            // get the interesting parameters of this pin
+            PinPhase = Mio_PinReadPhase(pPin);
+            tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin );  
+            tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin );  
+            // compute the arrival times of the positive phase
+            Slack = ABC_INFINITY;
+            if ( PinPhase != MIO_PHASE_INV )  // NONINV phase is present
+            {
+//                if ( pTimeOut->Rise < pTimeIn->Rise + tDelayBlockRise )
+//                    pTimeOut->Rise = pTimeIn->Rise + tDelayBlockRise;
+//                if ( pTimeOut->Fall < pTimeIn->Fall + tDelayBlockFall )
+//                    pTimeOut->Fall = pTimeIn->Fall + tDelayBlockFall;
+                Slack = Abc_MinFloat( Slack, Abc_AbsFloat(pTimeIn->Rise + tDelayBlockRise - pTimeOut->Rise) );
+                Slack = Abc_MinFloat( Slack, Abc_AbsFloat(pTimeIn->Fall + tDelayBlockFall - pTimeOut->Fall) );
+            }
+            if ( PinPhase != MIO_PHASE_NONINV )  // INV phase is present
+            {
+//                if ( pTimeOut->Rise < pTimeIn->Fall + tDelayBlockRise )
+//                    pTimeOut->Rise = pTimeIn->Fall + tDelayBlockRise;
+//                if ( pTimeOut->Fall < pTimeIn->Rise + tDelayBlockFall )
+//                    pTimeOut->Fall = pTimeIn->Rise + tDelayBlockFall;
+                Slack = Abc_MinFloat( Slack, Abc_AbsFloat(pTimeIn->Fall + tDelayBlockRise - pTimeOut->Rise) );
+                Slack = Abc_MinFloat( Slack, Abc_AbsFloat(pTimeIn->Rise + tDelayBlockFall - pTimeOut->Fall) );
+            }
+            pPin = Mio_PinReadNext(pPin);
+            Abc_NtkDelayTraceSetSlack( vSlacks, pNode, i, Slack );
+        }
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs delay-trace of the network. If input (pIn) or 
+  output (pOut) are given, finds the most-timing-critical path between 
+  them and prints it to the standard output. If input and/or output are 
+  not given, finds the most-critical path in the network and prints it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk, Abc_Obj_t * pOut, Abc_Obj_t * pIn, int fPrint )
+{
+    Vec_Int_t * vSlacks = NULL;
+    Abc_Obj_t * pNode, * pDriver;
+    Vec_Ptr_t * vNodes;
+    Abc_Time_t * pTime;
+    float tArrivalMax;
+    int i;
+
+    assert( Abc_NtkIsMappedLogic(pNtk) );
+    assert( pOut == NULL || Abc_ObjIsCo(pOut) );
+    assert( pIn == NULL || Abc_ObjIsCi(pIn) );
+
+    // create slacks (need slacks if printing is requested even if pIn/pOut are not given)
+    if ( pOut || pIn || fPrint )
+        vSlacks = Abc_NtkDelayTraceSlackStart( pNtk );
+
+    // compute the timing
+    Abc_NtkTimePrepare( pNtk );
+    vNodes = Abc_NtkDfs( pNtk, 1 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        Abc_NodeDelayTraceArrival( pNode, vSlacks );
+    Vec_PtrFree( vNodes );
+
+    // get the latest arrival times
+    tArrivalMax = -ABC_INFINITY;
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        pDriver = Abc_ObjFanin0(pNode);
+        pTime   = Abc_NodeArrival(pDriver);
+        if ( tArrivalMax < Abc_MaxFloat(pTime->Fall, pTime->Rise) )
+            tArrivalMax = Abc_MaxFloat(pTime->Fall, pTime->Rise);
+    }
+
+    // determine the output to print
+    if ( fPrint && pOut == NULL )
+    {
+        Abc_NtkForEachCo( pNtk, pNode, i )
+        {
+            pDriver = Abc_ObjFanin0(pNode);
+            pTime   = Abc_NodeArrival(pDriver);
+            if ( tArrivalMax == Abc_MaxFloat(pTime->Fall, pTime->Rise) )
+                pOut = pNode;
+        }
+        assert( pOut != NULL );
+    }
+
+    if ( fPrint )
+    {
+        Vec_Ptr_t * vPath = Vec_PtrAlloc( 100 );
+        Vec_Int_t * vBest = Vec_IntStartFull( Abc_NtkObjNumMax(pNtk) );
+        // traverse to determine the critical path
+        Abc_NtkIncrementTravId( pNtk );
+        if ( !Abc_NtkDelayTraceCritPath_rec( vSlacks, Abc_ObjFanin0(pOut), pIn, vBest ) )
+        {
+            if ( pIn == NULL )
+                printf( "The logic cone of PO \"%s\" has no primary inputs.\n", Abc_ObjName(pOut) );
+            else
+                printf( "There is no combinational path between PI \"%s\" and PO \"%s\".\n", Abc_ObjName(pIn), Abc_ObjName(pOut) );
+        }
+        else
+        {
+            float Slack = 0.0, SlackAdd;
+            int k, iFanin, Length = 0;
+            Abc_Obj_t * pFanin;
+            // check the additional slack
+            SlackAdd = Abc_NodeReadRequiredWorst(pOut) - Abc_NodeReadArrivalWorst(Abc_ObjFanin0(pOut));
+            // collect the critical path
+            Abc_NtkDelayTraceCritPathCollect_rec( vSlacks, Abc_ObjFanin0(pOut), vBest, vPath );
+            if ( pIn == NULL )
+                pIn = (Abc_Obj_t *)Vec_PtrEntry( vPath, 0 );
+            // find the longest gate name
+            Vec_PtrForEachEntry( Abc_Obj_t *, vPath, pNode, i )
+                if ( Abc_ObjIsNode(pNode) )
+                    Length = Abc_MaxInt( Length, strlen(Mio_GateReadName((Mio_Gate_t *)pNode->pData)) );
+            // print critical path
+            Abc_NtkLevel( pNtk );
+            printf( "Critical path from PI \"%s\" to PO \"%s\":\n", Abc_ObjName(pIn), Abc_ObjName(pOut) ); 
+            Vec_PtrForEachEntry( Abc_Obj_t *, vPath, pNode, i )
+            {
+                printf( "Level %3d : ", Abc_ObjLevel(pNode) );
+                if ( Abc_ObjIsCi(pNode) )
+                {
+                    printf( "Primary input \"%s\".   ", Abc_ObjName(pNode) );
+                    printf( "Arrival time =%6.1f. ", Abc_NodeReadArrivalWorst(pNode) );
+                    printf( "\n" );
+                    continue;
+                }
+                if ( Abc_ObjIsCo(pNode) )
+                {
+                    printf( "Primary output \"%s\".   ", Abc_ObjName(pNode) );
+                    printf( "Arrival =%6.1f. ", Abc_NodeReadArrivalWorst(pNode) );
+                }
+                else
+                {
+                    assert( Abc_ObjIsNode(pNode) );
+                    iFanin = Abc_NodeFindFanin( pNode, (Abc_Obj_t *)Vec_PtrEntry(vPath,i-1) );
+                    Slack = Abc_NtkDelayTraceSlack(vSlacks, pNode, iFanin);
+                    printf( "%10s/", Abc_ObjName(pNode) );
+                    printf( "%-4s", Mio_GateReadPinName((Mio_Gate_t *)pNode->pData, iFanin) );
+                    printf( " (%s)", Mio_GateReadName((Mio_Gate_t *)pNode->pData) );
+                    for ( k = strlen(Mio_GateReadName((Mio_Gate_t *)pNode->pData)); k < Length; k++ )
+                        printf( " " );
+                    printf( "   " );
+                    printf( "Arrival =%6.1f.   ", Abc_NodeReadArrivalWorst(pNode) );
+                    printf( "I/O times: (" );
+                    Abc_ObjForEachFanin( pNode, pFanin, k )
+                        printf( "%s%.1f", (k? ", ":""), Abc_NodeReadArrivalWorst(pFanin) );
+//                    printf( " -> %.1f)", Abc_NodeReadArrival(pNode)->Worst + Slack + SlackAdd );
+                    printf( " -> %.1f)", Abc_NodeReadArrivalWorst(pNode) );
+                }
+                printf( "\n" );
+            }
+            printf( "Level %3d : ", Abc_ObjLevel(Abc_ObjFanin0(pOut)) + 1 );
+            printf( "Primary output \"%s\".   ", Abc_ObjName(pOut) );
+            printf( "Required time = %6.1f.  ", Abc_NodeReadRequiredWorst(pOut) );
+            printf( "Path slack = %6.1f.\n", SlackAdd );
+        }
+        Vec_PtrFree( vPath );
+        Vec_IntFree( vBest );
+    }
+
+    Vec_IntFreeP( &vSlacks );
+    return tArrivalMax;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the level of the node using its fanin levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ObjLevelNew( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin;
+    int i, Level = 0;
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        Level = Abc_MaxFloat( Level, Abc_ObjLevel(pFanin) );
+    return Level + (int)(Abc_ObjFaninNum(pObj) > 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the reverse level of the node using its fanout levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ObjReverseLevelNew( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    int i, LevelCur, Level = 0;
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+    {
+        LevelCur = Abc_ObjReverseLevel( pFanout );
+        Level = Abc_MaxFloat( Level, LevelCur );
+    }
+    return Level + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns required level of the node.]
+
+  Description [Converts the reverse levels of the node into its required 
+  level as follows: ReqLevel(Node) = MaxLevels(Ntk) + 1 - LevelR(Node).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ObjRequiredLevel( Abc_Obj_t * pObj )
+{
+    Abc_Ntk_t * pNtk = pObj->pNtk;
+    assert( pNtk->vLevelsR );
+    return pNtk->LevelMax + 1 - Abc_ObjReverseLevel(pObj);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the reverse level of the node.]
+
+  Description [The reverse level is the level of the node in reverse
+  topological order, starting from the COs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ObjReverseLevel( Abc_Obj_t * pObj )
+{
+    Abc_Ntk_t * pNtk = pObj->pNtk;
+    assert( pNtk->vLevelsR );
+    Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 );
+    return Vec_IntEntry(pNtk->vLevelsR, pObj->Id);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the reverse level of the node.]
+
+  Description [The reverse level is the level of the node in reverse
+  topological order, starting from the COs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ObjSetReverseLevel( Abc_Obj_t * pObj, int LevelR )
+{
+    Abc_Ntk_t * pNtk = pObj->pNtk;
+    assert( pNtk->vLevelsR );
+    Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 );
+    Vec_IntWriteEntry( pNtk->vLevelsR, pObj->Id, LevelR );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares for the computation of required levels.]
+
+  Description [This procedure should be called before the required times
+  are used. It starts internal data structures, which records the level 
+  from the COs of the network nodes in reverse topologogical order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj;
+    int i;
+    // remember the maximum number of direct levels
+    pNtk->LevelMax = Abc_NtkLevel(pNtk) + nMaxLevelIncrease;
+    // start the reverse levels
+    pNtk->vLevelsR = Vec_IntAlloc( 0 );
+    Vec_IntFill( pNtk->vLevelsR, 1 + Abc_NtkObjNumMax(pNtk), 0 );
+    // compute levels in reverse topological order
+    vNodes = Abc_NtkDfsReverse( pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        Abc_ObjSetReverseLevel( pObj, Abc_ObjReverseLevelNew(pObj) );
+    Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the data structures used to compute required levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk )
+{
+    assert( pNtk->vLevelsR );
+    Vec_IntFree( pNtk->vLevelsR );
+    pNtk->vLevelsR = NULL;
+    pNtk->LevelMax = 0;
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Incrementally updates level of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels )
+{
+    Abc_Obj_t * pFanout, * pTemp;
+    int LevelOld, Lev, k, m;
+//    int Counter = 0, CounterMax = 0;
+    // check if level has changed
+    LevelOld = Abc_ObjLevel(pObjNew);
+    if ( LevelOld == Abc_ObjLevelNew(pObjNew) )
+        return;
+    // start the data structure for level update
+    // we cannot fail to visit a node when using this structure because the 
+    // nodes are stored by their _old_ levels, which are assumed to be correct
+    Vec_VecClear( vLevels );
+    Vec_VecPush( vLevels, LevelOld, pObjNew );
+    pObjNew->fMarkA = 1;
+    // recursively update level
+    Vec_VecForEachEntryStart( Abc_Obj_t *, vLevels, pTemp, Lev, k, LevelOld )
+    {
+//        Counter--;
+        pTemp->fMarkA = 0;
+        assert( Abc_ObjLevel(pTemp) == Lev );
+        Abc_ObjSetLevel( pTemp, Abc_ObjLevelNew(pTemp) );
+        // if the level did not change, no need to check the fanout levels
+        if ( Abc_ObjLevel(pTemp) == Lev )
+            continue;
+        // schedule fanout for level update
+        Abc_ObjForEachFanout( pTemp, pFanout, m )
+        {
+            if ( !Abc_ObjIsCo(pFanout) && !pFanout->fMarkA )
+            {
+                assert( Abc_ObjLevel(pFanout) >= Lev );
+                Vec_VecPush( vLevels, Abc_ObjLevel(pFanout), pFanout );
+//                Counter++;
+//                CounterMax = Abc_MaxFloat( CounterMax, Counter );
+                pFanout->fMarkA = 1;
+            }
+        }
+    }
+//    printf( "%d ", CounterMax );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Incrementally updates level of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels )
+{
+    Abc_Obj_t * pFanin, * pTemp;
+    int LevelOld, LevFanin, Lev, k, m;
+    // check if level has changed
+    LevelOld = Abc_ObjReverseLevel(pObjNew);
+    if ( LevelOld == Abc_ObjReverseLevelNew(pObjNew) )
+        return;
+    // start the data structure for level update
+    // we cannot fail to visit a node when using this structure because the 
+    // nodes are stored by their _old_ levels, which are assumed to be correct
+    Vec_VecClear( vLevels );
+    Vec_VecPush( vLevels, LevelOld, pObjNew );
+    pObjNew->fMarkA = 1;
+    // recursively update level
+    Vec_VecForEachEntryStart( Abc_Obj_t *, vLevels, pTemp, Lev, k, LevelOld )
+    {
+        pTemp->fMarkA = 0;
+        LevelOld = Abc_ObjReverseLevel(pTemp); 
+        assert( LevelOld == Lev );
+        Abc_ObjSetReverseLevel( pTemp, Abc_ObjReverseLevelNew(pTemp) );
+        // if the level did not change, no need to check the fanout levels
+        if ( Abc_ObjReverseLevel(pTemp) == Lev )
+            continue;
+        // schedule fanins for level update
+        Abc_ObjForEachFanin( pTemp, pFanin, m )
+        {
+            if ( !Abc_ObjIsCi(pFanin) && !pFanin->fMarkA )
+            {
+                LevFanin = Abc_ObjReverseLevel( pFanin );
+                assert( LevFanin >= Lev );
+                Vec_VecPush( vLevels, LevFanin, pFanin );
+                pFanin->fMarkA = 1;
+            }
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces the node and incrementally updates levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels )
+{
+    // replace the old node by the new node
+    pObjNew->Level = pObj->Level;
+    Abc_ObjReplace( pObj, pObjNew );
+    // update the level of the node
+    Abc_NtkUpdateLevel( pObjNew, vLevels );
+    Abc_ObjSetReverseLevel( pObjNew, 0 );
+    Abc_NtkUpdateReverseLevel( pObjNew, vLevels );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcUnate.c b/abc-build/src/base/abci/abcUnate.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcUnate.c
@@ -0,0 +1,162 @@
+/**CFile****************************************************************
+
+  FileName    [abcUnate.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcUnate.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkPrintUnateBdd( Abc_Ntk_t * pNtk, int fUseNaive, int fVerbose );
+static void Abc_NtkPrintUnateSat( Abc_Ntk_t * pNtk, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Detects unate variables of the multi-output function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintUnate( Abc_Ntk_t * pNtk, int fUseBdds, int fUseNaive, int fVerbose )
+{
+    if ( fUseBdds || fUseNaive )
+        Abc_NtkPrintUnateBdd( pNtk, fUseNaive, fVerbose );
+    else
+        Abc_NtkPrintUnateSat( pNtk, fVerbose );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detects unate variables using BDDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintUnateBdd( Abc_Ntk_t * pNtk, int fUseNaive, int fVerbose )
+{
+    Abc_Obj_t * pNode;
+    Extra_UnateInfo_t * p;
+	DdManager * dd;         // the BDD manager used to hold shared BDDs
+//	DdNode ** pbGlobal;     // temporary storage for global BDDs
+    int TotalSupps = 0;
+    int TotalUnate = 0;
+	int i;
+    abctime clk = Abc_Clock();
+    abctime clkBdd, clkUnate;
+
+    // compute the global BDDs
+    dd = (DdManager *)Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, fVerbose);
+    if ( dd == NULL )
+        return;
+clkBdd = Abc_Clock() - clk;
+
+    // get information about the network
+//    dd       = pNtk->pManGlob;
+//    dd       = (DdManager *)Abc_NtkGlobalBddMan( pNtk );
+//    pbGlobal = (DdNode **)Vec_PtrArray( pNtk->vFuncsGlob );
+
+    // print the size of the BDDs
+    printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+
+    // perform naive BDD-based computation
+    if ( fUseNaive )
+    {
+        Abc_NtkForEachCo( pNtk, pNode, i )
+        {
+//            p = Extra_UnateComputeSlow( dd, pbGlobal[i] );
+            p = Extra_UnateComputeSlow( dd, (DdNode *)Abc_ObjGlobalBdd(pNode) );
+            if ( fVerbose )
+                Extra_UnateInfoPrint( p );
+            TotalSupps += p->nVars;
+            TotalUnate += p->nUnate;
+            Extra_UnateInfoDissolve( p );
+        }
+    }
+    // perform smart BDD-based computation
+    else 
+    {
+	    // create ZDD variables in the manager
+        Cudd_zddVarsFromBddVars( dd, 2 );
+        Abc_NtkForEachCo( pNtk, pNode, i )
+        {
+//            p = Extra_UnateComputeFast( dd, pbGlobal[i] );
+            p = Extra_UnateComputeFast( dd, (DdNode *)Abc_ObjGlobalBdd(pNode) );
+            if ( fVerbose )
+                Extra_UnateInfoPrint( p );
+            TotalSupps += p->nVars;
+            TotalUnate += p->nUnate;
+            Extra_UnateInfoDissolve( p );
+        }
+    }
+clkUnate = Abc_Clock() - clk - clkBdd;
+
+    // print stats
+    printf( "Ins/Outs = %4d/%4d.  Total supp = %5d.  Total unate = %5d.\n",
+        Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), TotalSupps, TotalUnate );
+    ABC_PRT( "Glob BDDs", clkBdd );
+    ABC_PRT( "Unateness", clkUnate );
+    ABC_PRT( "Total    ", Abc_Clock() - clk );
+
+	// deref the PO functions
+//    Abc_NtkFreeGlobalBdds( pNtk );
+	// stop the global BDD manager
+//    Extra_StopManager( pNtk->pManGlob );
+//    pNtk->pManGlob = NULL;
+    Abc_NtkFreeGlobalBdds( pNtk, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detects unate variables using SAT.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintUnateSat( Abc_Ntk_t * pNtk, int fVerbose )
+{
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcUnreach.c b/abc-build/src/base/abci/abcUnreach.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcUnreach.c
@@ -0,0 +1,355 @@
+/**CFile****************************************************************
+
+  FileName    [abcUnreach.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Computes unreachable states for small benchmarks.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcUnreach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static DdNode *    Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose );
+static DdNode *    Abc_NtkInitStateAndVarMap( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose );
+static DdNode *    Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bRelation, DdNode * bInitial, int fVerbose );
+static Abc_Ntk_t * Abc_NtkConstructExdc     ( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUnreach );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Extracts sequential DCs of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    int fReorder = 1;
+    DdManager * dd;
+    DdNode * bRelation, * bInitial, * bUnreach;
+
+    // remove EXDC network if present
+    if ( pNtk->pExdc )
+    {
+        Abc_NtkDelete( pNtk->pExdc );
+        pNtk->pExdc = NULL; 
+    }
+
+    // compute the global BDDs of the latches
+    dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose );    
+    if ( dd == NULL )
+        return 0;
+    if ( fVerbose )
+        printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+
+    // create the transition relation (dereferenced global BDDs)
+    bRelation = Abc_NtkTransitionRelation( dd, pNtk, fVerbose );              Cudd_Ref( bRelation );
+    // create the initial state and the variable map
+    bInitial  = Abc_NtkInitStateAndVarMap( dd, pNtk, fVerbose );              Cudd_Ref( bInitial );
+    // compute the unreachable states
+    bUnreach  = Abc_NtkComputeUnreachable( dd, pNtk, bRelation, bInitial, fVerbose );   Cudd_Ref( bUnreach );
+    Cudd_RecursiveDeref( dd, bRelation );
+    Cudd_RecursiveDeref( dd, bInitial );
+
+    // reorder and disable reordering
+    if ( fReorder )
+    {
+        if ( fVerbose )
+            fprintf( stdout, "BDD nodes in the unreachable states before reordering %d.\n", Cudd_DagSize(bUnreach) );
+        Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 );
+        Cudd_AutodynDisable( dd );
+        if ( fVerbose )
+            fprintf( stdout, "BDD nodes in the unreachable states after reordering %d.\n", Cudd_DagSize(bUnreach) );
+    }
+
+    // allocate ZDD variables
+    Cudd_zddVarsFromBddVars( dd, 2 );
+    // create the EXDC network representing the unreachable states
+    if ( pNtk->pExdc )
+        Abc_NtkDelete( pNtk->pExdc );
+    pNtk->pExdc = Abc_NtkConstructExdc( dd, pNtk, bUnreach );
+    Cudd_RecursiveDeref( dd, bUnreach );
+    Extra_StopManager( dd );
+//    pNtk->pManGlob = NULL;
+
+    // make sure that everything is okay
+    if ( pNtk->pExdc && !Abc_NtkCheck( pNtk->pExdc ) )
+    {
+        printf( "Abc_NtkExtractSequentialDcs: The network check has failed.\n" );
+        Abc_NtkDelete( pNtk->pExdc );
+        return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the transition relation of the network.]
+
+  Description [Assumes that the global BDDs are computed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose )
+{
+    DdNode * bRel, * bTemp, * bProd, * bVar, * bInputs;
+    Abc_Obj_t * pNode;
+    int fReorder = 1;
+    int i;
+
+    // extand the BDD manager to represent NS variables
+    assert( dd->size == Abc_NtkCiNum(pNtk) );
+    Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + Abc_NtkLatchNum(pNtk) - 1 );
+
+    // enable reordering
+    if ( fReorder )
+        Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+    else
+        Cudd_AutodynDisable( dd );
+
+    // compute the transition relation
+    bRel = b1;   Cudd_Ref( bRel );
+    Abc_NtkForEachLatch( pNtk, pNode, i )
+    {
+        bVar  = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i );
+//        bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] );  Cudd_Ref( bProd );
+        bProd = Cudd_bddXnor( dd, bVar, (DdNode *)Abc_ObjGlobalBdd(Abc_ObjFanin0(pNode)) );  Cudd_Ref( bProd );
+        bRel  = Cudd_bddAnd( dd, bTemp = bRel, bProd );                 Cudd_Ref( bRel );
+        Cudd_RecursiveDeref( dd, bTemp ); 
+        Cudd_RecursiveDeref( dd, bProd ); 
+    }
+    // free the global BDDs
+//    Abc_NtkFreeGlobalBdds( pNtk );
+    Abc_NtkFreeGlobalBdds( pNtk, 0 );
+
+    // quantify the PI variables
+    bInputs = Extra_bddComputeRangeCube( dd, 0, Abc_NtkPiNum(pNtk) );    Cudd_Ref( bInputs );
+    bRel    = Cudd_bddExistAbstract( dd, bTemp = bRel, bInputs );    Cudd_Ref( bRel );
+    Cudd_RecursiveDeref( dd, bTemp ); 
+    Cudd_RecursiveDeref( dd, bInputs ); 
+
+    // reorder and disable reordering
+    if ( fReorder )
+    {
+        if ( fVerbose )
+            fprintf( stdout, "BDD nodes in the transition relation before reordering %d.\n", Cudd_DagSize(bRel) );
+        Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+        Cudd_AutodynDisable( dd );
+        if ( fVerbose )
+            fprintf( stdout, "BDD nodes in the transition relation after reordering %d.\n", Cudd_DagSize(bRel) );
+    }
+    Cudd_Deref( bRel );
+    return bRel;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the initial state and sets up the variable map.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NtkInitStateAndVarMap( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose )
+{
+    DdNode ** pbVarsX, ** pbVarsY;
+    DdNode * bTemp, * bProd, * bVar;
+    Abc_Obj_t * pLatch;
+    int i;
+
+    // set the variable mapping for Cudd_bddVarMap()
+    pbVarsX = ABC_ALLOC( DdNode *, dd->size );
+    pbVarsY = ABC_ALLOC( DdNode *, dd->size );
+    bProd = b1;         Cudd_Ref( bProd );
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+        pbVarsX[i] = dd->vars[ Abc_NtkPiNum(pNtk) + i ];
+        pbVarsY[i] = dd->vars[ Abc_NtkCiNum(pNtk) + i ];
+        // get the initial value of the latch
+        bVar  = Cudd_NotCond( pbVarsX[i], !Abc_LatchIsInit1(pLatch) );
+        bProd = Cudd_bddAnd( dd, bTemp = bProd, bVar );      Cudd_Ref( bProd );
+        Cudd_RecursiveDeref( dd, bTemp ); 
+    }
+    Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Abc_NtkLatchNum(pNtk) );
+    ABC_FREE( pbVarsX );
+    ABC_FREE( pbVarsY );
+
+    Cudd_Deref( bProd );
+    return bProd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the set of unreachable states.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bTrans, DdNode * bInitial, int fVerbose )
+{
+    DdNode * bRelation, * bReached, * bCubeCs;
+    DdNode * bCurrent, * bNext, * bTemp;
+    int nIters, nMints;
+
+    // perform reachability analisys
+    bCurrent  = bInitial;   Cudd_Ref( bCurrent );
+    bReached  = bInitial;   Cudd_Ref( bReached );
+    bRelation = bTrans;     Cudd_Ref( bRelation );
+    bCubeCs   = Extra_bddComputeRangeCube( dd, Abc_NtkPiNum(pNtk), Abc_NtkCiNum(pNtk) );    Cudd_Ref( bCubeCs );
+    for ( nIters = 1; ; nIters++ )
+    {
+        // compute the next states
+        bNext = Cudd_bddAndAbstract( dd, bRelation, bCurrent, bCubeCs );  Cudd_Ref( bNext );
+        Cudd_RecursiveDeref( dd, bCurrent );
+        // remap these states into the current state vars
+        bNext = Cudd_bddVarMap( dd, bTemp = bNext );                      Cudd_Ref( bNext );
+        Cudd_RecursiveDeref( dd, bTemp );
+        // check if there are any new states
+        if ( Cudd_bddLeq( dd, bNext, bReached ) )
+            break;
+        // get the new states
+        bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) );          Cudd_Ref( bCurrent );
+        // minimize the new states with the reached states
+//        bCurrent = Cudd_bddConstrain( dd, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent );
+//        Cudd_RecursiveDeref( dd, bTemp );
+        // add to the reached states
+        bReached = Cudd_bddOr( dd, bTemp = bReached, bNext );             Cudd_Ref( bReached );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bNext );
+        // minimize the transition relation
+//        bRelation = Cudd_bddConstrain( dd, bTemp = bRelation, Cudd_Not(bReached) ); Cudd_Ref( bRelation );
+//        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    Cudd_RecursiveDeref( dd, bRelation );
+    Cudd_RecursiveDeref( dd, bCubeCs );
+    Cudd_RecursiveDeref( dd, bNext );
+    // report the stats
+    if ( fVerbose )
+    {
+        nMints = (int)Cudd_CountMinterm(dd, bReached, Abc_NtkLatchNum(pNtk) );
+        fprintf( stdout, "Reachability analysis completed in %d iterations.\n", nIters );
+        fprintf( stdout, "The number of minterms in the reachable state set = %d. (%6.2f %%)\n", nMints, 100.0*nMints/(1<<Abc_NtkLatchNum(pNtk)) );
+    }
+//ABC_PRB( dd, bReached );
+    Cudd_Deref( bReached );
+    return Cudd_Not( bReached );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the EXDC network.]
+
+  Description [The set of unreachable states depends on CS variables.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkConstructExdc( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUnreach )
+{
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pNode, * pNodeNew;
+    int * pPermute;
+    int i;
+
+    // start the new network
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 );
+    pNtkNew->pName = Extra_UtilStrsav( "exdc" );
+    pNtkNew->pSpec = NULL;
+
+    // create PIs corresponding to LOs
+    Abc_NtkForEachLatchOutput( pNtk, pNode, i )
+        Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pNode), NULL );
+    // cannot ADD POs here because pLatch->pCopy point to the PIs
+
+    // create a new node
+    pNodeNew = Abc_NtkCreateNode(pNtkNew);
+    // add the fanins corresponding to latch outputs
+    Abc_NtkForEachLatchOutput( pNtk, pNode, i )
+        Abc_ObjAddFanin( pNodeNew, pNode->pCopy );
+
+    // create the logic function
+    pPermute = ABC_ALLOC( int, dd->size );
+    for ( i = 0; i < dd->size; i++ )
+        pPermute[i] = -1;
+    Abc_NtkForEachLatch( pNtk, pNode, i )
+        pPermute[Abc_NtkPiNum(pNtk) + i] = i;
+    // remap the functions
+    pNodeNew->pData = Extra_TransferPermute( dd, (DdManager *)pNtkNew->pManFunc, bUnreach, pPermute );   Cudd_Ref( (DdNode *)pNodeNew->pData );
+    ABC_FREE( pPermute );
+    Abc_NodeMinimumBase( pNodeNew );
+
+    // for each CO, create PO (skip POs equal to CIs because of name conflict)
+    Abc_NtkForEachPo( pNtk, pNode, i )
+        if ( !Abc_ObjIsCi(Abc_ObjFanin0(pNode)) )
+            Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePo(pNtkNew), Abc_ObjName(pNode), NULL );
+    Abc_NtkForEachLatchInput( pNtk, pNode, i )
+        Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePo(pNtkNew), Abc_ObjName(pNode), NULL );
+
+    // link to the POs of the network 
+    Abc_NtkForEachPo( pNtk, pNode, i )
+        if ( !Abc_ObjIsCi(Abc_ObjFanin0(pNode)) )
+            Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+    Abc_NtkForEachLatchInput( pNtk, pNode, i )
+        Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+
+    // remove the extra nodes
+    Abc_AigCleanup( (Abc_Aig_t *)pNtkNew->pManFunc );
+
+    // fix the problem with complemented and duplicated CO edges
+    Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+
+    // transform the network to the SOP representation
+    if ( !Abc_NtkBddToSop( pNtkNew, 0 ) )
+    {
+        printf( "Abc_NtkConstructExdc(): Converting to SOPs has failed.\n" );
+        return NULL;
+    }
+    return pNtkNew;
+//    return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcVerify.c b/abc-build/src/base/abci/abcVerify.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcVerify.c
@@ -0,0 +1,1105 @@
+/**CFile****************************************************************
+
+  FileName    [abcVerify.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Combinational and sequential verification for two networks.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcVerify.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/main.h"
+#include "base/cmd/cmd.h"
+#include "proof/fraig/fraig.h"
+#include "opt/sim/sim.h"
+#include "aig/aig/aig.h"
+#include "aig/saig/saig.h"
+#include "aig/gia/gia.h"
+#include "proof/ssw/ssw.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+static void  Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel );
+extern void  Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies combinational equivalence by brute-force SAT.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit )
+{
+    extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
+    Abc_Ntk_t * pMiter;
+    Abc_Ntk_t * pCnf;
+    int RetValue;
+
+    // get the miter of the two networks
+    pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0, 0, 0 );
+    if ( pMiter == NULL )
+    {
+        printf( "Miter computation has failed.\n" );
+        return;
+    }
+    RetValue = Abc_NtkMiterIsConstant( pMiter );
+    if ( RetValue == 0 )
+    {
+        printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+        // report the error
+        pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 );
+        Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+        ABC_FREE( pMiter->pModel );
+        Abc_NtkDelete( pMiter );
+        return;
+    }
+    if ( RetValue == 1 )
+    {
+        Abc_NtkDelete( pMiter );
+        printf( "Networks are equivalent after structural hashing.\n" );
+        return;
+    }
+
+    // convert the miter into a CNF
+    pCnf = Abc_NtkMulti( pMiter, 0, 100, 1, 0, 0, 0 );
+    Abc_NtkDelete( pMiter );
+    if ( pCnf == NULL )
+    {
+        printf( "Renoding for CNF has failed.\n" );
+        return;
+    }
+
+    // solve the CNF using the SAT solver
+    RetValue = Abc_NtkMiterSat( pCnf, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, 0, NULL, NULL );
+    if ( RetValue == -1 )
+        printf( "Networks are undecided (SAT solver timed out).\n" );
+    else if ( RetValue == 0 )
+        printf( "Networks are NOT EQUIVALENT after SAT.\n" );
+    else
+        printf( "Networks are equivalent after SAT.\n" );
+    if ( pCnf->pModel )
+        Abc_NtkVerifyReportError( pNtk1, pNtk2, pCnf->pModel );
+    ABC_FREE( pCnf->pModel );
+    Abc_NtkDelete( pCnf );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies sequential equivalence by fraiging followed by SAT.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose )
+{
+    Prove_Params_t Params, * pParams = &Params;
+//    Fraig_Params_t Params;
+//    Fraig_Man_t * pMan;
+    Abc_Ntk_t * pMiter, * pTemp;
+    Abc_Ntk_t * pExdc = NULL;
+    int RetValue;
+
+    if ( pNtk1->pExdc != NULL || pNtk2->pExdc != NULL )
+    {
+        if ( pNtk1->pExdc != NULL && pNtk2->pExdc != NULL )
+        {
+            printf( "Comparing EXDC of the two networks:\n" );
+            Abc_NtkCecFraig( pNtk1->pExdc, pNtk2->pExdc, nSeconds, fVerbose );
+            printf( "Comparing networks under EXDC of the first network.\n" );
+            pExdc = pNtk1->pExdc;
+        }
+        else if ( pNtk1->pExdc != NULL )
+        {
+            printf( "Second network has no EXDC. Comparing main networks under EXDC of the first network.\n" );
+            pExdc = pNtk1->pExdc;
+        }
+        else if ( pNtk2->pExdc != NULL ) 
+        {
+            printf( "First network has no EXDC. Comparing main networks under EXDC of the second network.\n" );
+            pExdc = pNtk2->pExdc;
+        }
+        else assert( 0 );
+    }
+
+    // get the miter of the two networks
+    pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0, 0, 0 );
+    if ( pMiter == NULL )
+    {
+        printf( "Miter computation has failed.\n" );
+        return;
+    }
+    // add EXDC to the miter
+    if ( pExdc )
+    {
+        assert( Abc_NtkPoNum(pMiter) == 1 );
+        assert( Abc_NtkPoNum(pExdc) == 1 );
+        pMiter = Abc_NtkMiter( pTemp = pMiter, pExdc, 1, 0, 1, 0 );
+        Abc_NtkDelete( pTemp );
+    }
+    // handle trivial case
+    RetValue = Abc_NtkMiterIsConstant( pMiter );
+    if ( RetValue == 0 )
+    {
+        printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+        // report the error
+        pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 );
+        Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+        ABC_FREE( pMiter->pModel );
+        Abc_NtkDelete( pMiter );
+        return;
+    }
+    if ( RetValue == 1 )
+    {
+        printf( "Networks are equivalent after structural hashing.\n" );
+        Abc_NtkDelete( pMiter );
+        return;
+    }
+/*
+    // convert the miter into a FRAIG
+    Fraig_ParamsSetDefault( &Params );
+    Params.fVerbose = fVerbose;
+    Params.nSeconds = nSeconds;
+//    Params.fFuncRed = 0;
+//    Params.nPatsRand = 0;
+//    Params.nPatsDyna = 0;
+    pMan = (Fraig_Man_t *)Abc_NtkToFraig( pMiter, &Params, 0, 0 ); 
+    Fraig_ManProveMiter( pMan );
+
+    // analyze the result
+    RetValue = Fraig_ManCheckMiter( pMan );
+    // report the result
+    if ( RetValue == -1 )
+        printf( "Networks are undecided (SAT solver timed out on the final miter).\n" );
+    else if ( RetValue == 1 )
+        printf( "Networks are equivalent after fraiging.\n" );
+    else if ( RetValue == 0 )
+    {
+        printf( "Networks are NOT EQUIVALENT after fraiging.\n" );
+        Abc_NtkVerifyReportError( pNtk1, pNtk2, Fraig_ManReadModel(pMan) );
+    }
+    else assert( 0 );
+    // delete the fraig manager
+    Fraig_ManFree( pMan );
+    // delete the miter
+    Abc_NtkDelete( pMiter );
+*/
+    // solve the CNF using the SAT solver
+    Prove_ParamsSetDefault( pParams );
+    pParams->nItersMax = 5;
+//    RetValue = Abc_NtkMiterProve( &pMiter, pParams );
+//    pParams->fVerbose = 1;
+    RetValue = Abc_NtkIvyProve( &pMiter, pParams );
+    if ( RetValue == -1 )
+        printf( "Networks are undecided (resource limits is reached).\n" );
+    else if ( RetValue == 0 )
+    {
+        int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiter, pMiter->pModel );
+        if ( pSimInfo[0] != 1 )
+            printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" );
+        else
+            printf( "Networks are NOT EQUIVALENT.\n" );
+        ABC_FREE( pSimInfo );
+    }
+    else
+        printf( "Networks are equivalent.\n" );
+    if ( pMiter->pModel )
+        Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+    Abc_NtkDelete( pMiter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies sequential equivalence by fraiging followed by SAT.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose )
+{
+    Prove_Params_t Params, * pParams = &Params;
+    Abc_Ntk_t * pMiter, * pMiterPart;
+    Abc_Obj_t * pObj;
+    int i, RetValue, Status, nOutputs;
+
+    // solve the CNF using the SAT solver
+    Prove_ParamsSetDefault( pParams );
+    pParams->nItersMax = 5;
+    //    pParams->fVerbose = 1;
+
+    assert( nPartSize > 0 );
+
+    // get the miter of the two networks
+    pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, nPartSize, 0, 0 );
+    if ( pMiter == NULL )
+    {
+        printf( "Miter computation has failed.\n" );
+        return;
+    }
+    RetValue = Abc_NtkMiterIsConstant( pMiter );
+    if ( RetValue == 0 )
+    {
+        printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+        // report the error
+        pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 );
+        Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+        ABC_FREE( pMiter->pModel );
+        Abc_NtkDelete( pMiter );
+        return;
+    }
+    if ( RetValue == 1 )
+    {
+        printf( "Networks are equivalent after structural hashing.\n" );
+        Abc_NtkDelete( pMiter );
+        return;
+    }
+
+    Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" );
+
+    // solve the problem iteratively for each output of the miter
+    Status = 1;
+    nOutputs = 0;
+    Abc_NtkForEachPo( pMiter, pObj, i )
+    {
+        if ( Abc_ObjFanin0(pObj) == Abc_AigConst1(pMiter) )
+        {
+            if ( Abc_ObjFaninC0(pObj) ) // complemented -> const 0
+                RetValue = 1;
+            else
+                RetValue = 0;
+            pMiterPart = NULL;
+        }
+        else
+        {
+            // get the cone of this output
+            pMiterPart = Abc_NtkCreateCone( pMiter, Abc_ObjFanin0(pObj), Abc_ObjName(pObj), 0 );
+            if ( Abc_ObjFaninC0(pObj) )
+                Abc_ObjXorFaninC( Abc_NtkPo(pMiterPart,0), 0 );
+            // solve the cone
+        //    RetValue = Abc_NtkMiterProve( &pMiterPart, pParams );
+            RetValue = Abc_NtkIvyProve( &pMiterPart, pParams );
+        }
+
+        if ( RetValue == -1 )
+        {
+            printf( "Networks are undecided (resource limits is reached).\r" );
+            Status = -1;
+        }
+        else if ( RetValue == 0 )
+        {
+            int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiterPart, pMiterPart->pModel );
+            if ( pSimInfo[0] != 1 )
+                printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" );
+            else
+                printf( "Networks are NOT EQUIVALENT.                 \n" );
+            ABC_FREE( pSimInfo );
+            Status = 0;
+            break;
+        }
+        else
+        {
+            printf( "Finished part %5d (out of %5d)\r", i+1, Abc_NtkPoNum(pMiter) );
+            nOutputs += nPartSize;
+        }
+//        if ( pMiter->pModel )
+//            Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+        if ( pMiterPart )
+            Abc_NtkDelete( pMiterPart );
+    }
+  
+    Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" );
+
+    if ( Status == 1 )
+        printf( "Networks are equivalent.                         \n" );
+    else if ( Status == -1 )
+        printf( "Timed out after verifying %d outputs (out of %d).\n", nOutputs, Abc_NtkCoNum(pNtk1) );
+    Abc_NtkDelete( pMiter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies sequential equivalence by fraiging followed by SAT.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose )
+{
+    extern Vec_Ptr_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nPartSizeLimit, int fVerbose );
+    extern void Abc_NtkConvertCos( Abc_Ntk_t * pNtk, Vec_Int_t * vOuts, Vec_Ptr_t * vOnePtr );
+
+    Vec_Ptr_t * vParts, * vOnePtr;
+    Vec_Int_t * vOne;
+    Prove_Params_t Params, * pParams = &Params;
+    Abc_Ntk_t * pMiter, * pMiterPart;
+    int i, RetValue, Status, nOutputs;
+
+    // solve the CNF using the SAT solver
+    Prove_ParamsSetDefault( pParams );
+    pParams->nItersMax = 5;
+    //    pParams->fVerbose = 1;
+
+    // get the miter of the two networks
+    pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 1, 0, 0 );
+    if ( pMiter == NULL )
+    {
+        printf( "Miter computation has failed.\n" );
+        return;
+    }
+    RetValue = Abc_NtkMiterIsConstant( pMiter );
+    if ( RetValue == 0 )
+    {
+        printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+        // report the error
+        pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 );
+        Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+        ABC_FREE( pMiter->pModel );
+        Abc_NtkDelete( pMiter );
+        return;
+    }
+    if ( RetValue == 1 )
+    {
+        printf( "Networks are equivalent after structural hashing.\n" );
+        Abc_NtkDelete( pMiter );
+        return;
+    }
+
+    Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" );
+
+    // partition the outputs
+    vParts = Abc_NtkPartitionSmart( pMiter, 300, 0 );
+
+    // fraig each partition
+    Status = 1;
+    nOutputs = 0;
+    vOnePtr = Vec_PtrAlloc( 1000 );
+    Vec_PtrForEachEntry( Vec_Int_t *, vParts, vOne, i )
+    {
+        // get this part of the miter
+        Abc_NtkConvertCos( pMiter, vOne, vOnePtr );
+        pMiterPart = Abc_NtkCreateConeArray( pMiter, vOnePtr, 0 );
+        Abc_NtkCombinePos( pMiterPart, 0, 0 );
+        // check the miter for being constant
+        RetValue = Abc_NtkMiterIsConstant( pMiterPart );
+        if ( RetValue == 0 )
+        {
+            printf( "Networks are NOT EQUIVALENT after partitioning.\n" );
+            Abc_NtkDelete( pMiterPart );
+            break;
+        }
+        if ( RetValue == 1 )
+        {
+            Abc_NtkDelete( pMiterPart );
+            continue;
+        }
+        printf( "Verifying part %4d  (out of %4d)  PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", 
+            i+1, Vec_PtrSize(vParts), Abc_NtkPiNum(pMiterPart), Abc_NtkPoNum(pMiterPart), 
+            Abc_NtkNodeNum(pMiterPart), Abc_AigLevel(pMiterPart) );
+        fflush( stdout );
+        // solve the problem
+        RetValue = Abc_NtkIvyProve( &pMiterPart, pParams );
+        if ( RetValue == -1 )
+        {
+            printf( "Networks are undecided (resource limits is reached).\r" );
+            Status = -1;
+        }
+        else if ( RetValue == 0 )
+        {
+            int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiterPart, pMiterPart->pModel );
+            if ( pSimInfo[0] != 1 )
+                printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" );
+            else
+                printf( "Networks are NOT EQUIVALENT.                 \n" );
+            ABC_FREE( pSimInfo );
+            Status = 0;
+            Abc_NtkDelete( pMiterPart );
+            break;
+        }
+        else
+        {
+//            printf( "Finished part %5d (out of %5d)\r", i+1, Vec_PtrSize(vParts) );
+            nOutputs += Vec_IntSize(vOne);
+        }
+        Abc_NtkDelete( pMiterPart );
+    }
+    printf( "                                                                                          \r" );
+    Vec_VecFree( (Vec_Vec_t *)vParts );
+    Vec_PtrFree( vOnePtr );
+
+    Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" );
+
+    if ( Status == 1 )
+        printf( "Networks are equivalent.                         \n" );
+    else if ( Status == -1 )
+        printf( "Timed out after verifying %d outputs (out of %d).\n", nOutputs, Abc_NtkCoNum(pNtk1) );
+    Abc_NtkDelete( pMiter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies sequential equivalence by brute-force SAT.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit, int nFrames )
+{
+    extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
+    Abc_Ntk_t * pMiter;
+    Abc_Ntk_t * pFrames;
+    Abc_Ntk_t * pCnf;
+    int RetValue;
+
+    // get the miter of the two networks
+    pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0, 0, 0 );
+    if ( pMiter == NULL )
+    {
+        printf( "Miter computation has failed.\n" );
+        return;
+    }
+    RetValue = Abc_NtkMiterIsConstant( pMiter );
+    if ( RetValue == 0 )
+    {
+        Abc_NtkDelete( pMiter );
+        printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+        return;
+    }
+    if ( RetValue == 1 )
+    {
+        Abc_NtkDelete( pMiter );
+        printf( "Networks are equivalent after structural hashing.\n" );
+        return;
+    }
+
+    // create the timeframes
+    pFrames = Abc_NtkFrames( pMiter, nFrames, 1, 0 );
+    Abc_NtkDelete( pMiter );
+    if ( pFrames == NULL )
+    {
+        printf( "Frames computation has failed.\n" );
+        return;
+    }
+    RetValue = Abc_NtkMiterIsConstant( pFrames );
+    if ( RetValue == 0 )
+    {
+        Abc_NtkDelete( pFrames );
+        printf( "Networks are NOT EQUIVALENT after framing.\n" );
+        return;
+    }
+    if ( RetValue == 1 )
+    {
+        Abc_NtkDelete( pFrames );
+        printf( "Networks are equivalent after framing.\n" );
+        return;
+    }
+
+    // convert the miter into a CNF
+    pCnf = Abc_NtkMulti( pFrames, 0, 100, 1, 0, 0, 0 );
+    Abc_NtkDelete( pFrames );
+    if ( pCnf == NULL )
+    {
+        printf( "Renoding for CNF has failed.\n" );
+        return;
+    }
+
+    // solve the CNF using the SAT solver
+    RetValue = Abc_NtkMiterSat( pCnf, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, 0, NULL, NULL );
+    if ( RetValue == -1 )
+        printf( "Networks are undecided (SAT solver timed out).\n" );
+    else if ( RetValue == 0 )
+        printf( "Networks are NOT EQUIVALENT after SAT.\n" );
+    else
+        printf( "Networks are equivalent after SAT.\n" );
+    Abc_NtkDelete( pCnf );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies combinational equivalence by fraiging followed by SAT]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose )
+{
+    Fraig_Params_t Params;
+    Fraig_Man_t * pMan;
+    Abc_Ntk_t * pMiter;
+    Abc_Ntk_t * pFrames;
+    int RetValue;
+
+    // get the miter of the two networks
+    pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0, 0, 0 );
+    if ( pMiter == NULL )
+    {
+        printf( "Miter computation has failed.\n" );
+        return 0;
+    }
+    RetValue = Abc_NtkMiterIsConstant( pMiter );
+    if ( RetValue == 0 )
+    {
+        printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+        // report the error
+        pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames );
+        Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames );
+        ABC_FREE( pMiter->pModel );
+        Abc_NtkDelete( pMiter );
+        return 0;
+    }
+    if ( RetValue == 1 )
+    {
+        Abc_NtkDelete( pMiter );
+        printf( "Networks are equivalent after structural hashing.\n" );
+        return 1;
+    }
+
+    // create the timeframes
+    pFrames = Abc_NtkFrames( pMiter, nFrames, 1, 0 );
+    Abc_NtkDelete( pMiter );
+    if ( pFrames == NULL )
+    {
+        printf( "Frames computation has failed.\n" );
+        return 0;
+    }
+    RetValue = Abc_NtkMiterIsConstant( pFrames );
+    if ( RetValue == 0 )
+    {
+        printf( "Networks are NOT EQUIVALENT after framing.\n" );
+        // report the error
+        pFrames->pModel = Abc_NtkVerifyGetCleanModel( pFrames, 1 );
+//        Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pFrames->pModel, nFrames );
+        ABC_FREE( pFrames->pModel );
+        Abc_NtkDelete( pFrames );
+        return 0;
+    }
+    if ( RetValue == 1 )
+    {
+        Abc_NtkDelete( pFrames );
+        printf( "Networks are equivalent after framing.\n" );
+        return 1;
+    }
+
+    // convert the miter into a FRAIG
+    Fraig_ParamsSetDefault( &Params );
+    Params.fVerbose = fVerbose;
+    Params.nSeconds = nSeconds;
+//    Params.fFuncRed = 0;
+//    Params.nPatsRand = 0;
+//    Params.nPatsDyna = 0;
+    pMan = (Fraig_Man_t *)Abc_NtkToFraig( pFrames, &Params, 0, 0 ); 
+    Fraig_ManProveMiter( pMan );
+
+    // analyze the result
+    RetValue = Fraig_ManCheckMiter( pMan );
+    // report the result
+    if ( RetValue == -1 )
+        printf( "Networks are undecided (SAT solver timed out on the final miter).\n" );
+    else if ( RetValue == 1 )
+        printf( "Networks are equivalent after fraiging.\n" );
+    else if ( RetValue == 0 )
+    {
+        printf( "Networks are NOT EQUIVALENT after fraiging.\n" );
+//        Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, Fraig_ManReadModel(pMan), nFrames );
+    }
+    else assert( 0 );
+    // delete the fraig manager
+    Fraig_ManFree( pMan );
+    // delete the miter
+    Abc_NtkDelete( pFrames );
+    return RetValue == 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns a dummy pattern full of zeros.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Abc_NtkVerifyGetCleanModel( Abc_Ntk_t * pNtk, int nFrames )
+{
+    int * pModel = ABC_ALLOC( int, Abc_NtkCiNum(pNtk) * nFrames );
+    memset( pModel, 0, sizeof(int) * Abc_NtkCiNum(pNtk) * nFrames );
+    return pModel;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the PO values under the given input pattern.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+int * Abc_NtkVerifySimulatePattern( Abc_Ntk_t * pNtk, int * pModel )
+{
+    Abc_Obj_t * pNode;
+    int * pValues, Value0, Value1, i;
+    int fStrashed = 0;
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        pNtk = Abc_NtkStrash(pNtk, 0, 0, 0);
+        fStrashed = 1;
+    }
+/*
+    printf( "Counter example: " );
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        printf( " %d", pModel[i] );
+    printf( "\n" );
+*/
+    // increment the trav ID
+    Abc_NtkIncrementTravId( pNtk );
+    // set the CI values
+    Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)1;
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)pModel[i];
+    // simulate in the topological order
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        Value0 = ((int)(ABC_PTRINT_T)Abc_ObjFanin0(pNode)->pCopy) ^ (int)Abc_ObjFaninC0(pNode);
+        Value1 = ((int)(ABC_PTRINT_T)Abc_ObjFanin1(pNode)->pCopy) ^ (int)Abc_ObjFaninC1(pNode);
+        pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)(Value0 & Value1);
+    }
+    // fill the output values
+    pValues = ABC_ALLOC( int, Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        pValues[i] = ((int)(ABC_PTRINT_T)Abc_ObjFanin0(pNode)->pCopy) ^ (int)Abc_ObjFaninC0(pNode);
+    if ( fStrashed )
+        Abc_NtkDelete( pNtk );
+    return pValues;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reports mismatch between the two networks.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNode;
+    int * pValues1, * pValues2;
+    int nErrors, nPrinted, i, iNode = -1;
+
+    assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) );
+    assert( Abc_NtkCoNum(pNtk1) == Abc_NtkCoNum(pNtk2) );
+    // get the CO values under this model
+    pValues1 = Abc_NtkVerifySimulatePattern( pNtk1, pModel );
+    pValues2 = Abc_NtkVerifySimulatePattern( pNtk2, pModel );
+    // count the mismatches
+    nErrors = 0;
+    for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ )
+        nErrors += (int)( pValues1[i] != pValues2[i] );
+    printf( "Verification failed for at least %d outputs: ", nErrors );
+    // print the first 3 outputs
+    nPrinted = 0;
+    for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ )
+        if ( pValues1[i] != pValues2[i] )
+        {
+            if ( iNode == -1 )
+                iNode = i;
+            printf( " %s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) );
+            if ( ++nPrinted == 3 )
+                break;
+        }
+    if ( nPrinted != nErrors )
+        printf( " ..." );
+    printf( "\n" );
+    // report mismatch for the first output
+    if ( iNode >= 0 )
+    {
+        printf( "Output %s: Value in Network1 = %d. Value in Network2 = %d.\n", 
+            Abc_ObjName(Abc_NtkCo(pNtk1,iNode)), pValues1[iNode], pValues2[iNode] );
+        printf( "Input pattern: " );
+        // collect PIs in the cone
+        pNode = Abc_NtkCo(pNtk1,iNode);
+        vNodes = Abc_NtkNodeSupport( pNtk1, &pNode, 1 );
+        // set the PI numbers
+        Abc_NtkForEachCi( pNtk1, pNode, i )
+            pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)i;
+        // print the model
+        pNode = (Abc_Obj_t *)Vec_PtrEntry( vNodes, 0 );
+        if ( Abc_ObjIsCi(pNode) )
+        {
+            Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+            {
+                assert( Abc_ObjIsCi(pNode) );
+                printf( " %s=%d", Abc_ObjName(pNode), pModel[(int)(ABC_PTRINT_T)pNode->pCopy] );
+            }
+        }
+        printf( "\n" );
+        Vec_PtrFree( vNodes );
+    }
+    ABC_FREE( pValues1 );
+    ABC_FREE( pValues2 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the COs in the support of the PO in the given frame.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkGetSeqPoSupp( Abc_Ntk_t * pNtk, int iFrame, int iNumPo )
+{
+    Abc_Ntk_t * pFrames;
+    Abc_Obj_t * pObj, * pNodePo;
+    Vec_Ptr_t * vSupp;
+    int i, k;
+    // get the timeframes of the network
+    pFrames = Abc_NtkFrames( pNtk, iFrame + 1, 0, 0 );
+//Abc_NtkShowAig( pFrames );
+
+    // get the PO of the timeframes
+    pNodePo = Abc_NtkPo( pFrames, iFrame * Abc_NtkPoNum(pNtk) + iNumPo );
+    // set the support
+    vSupp   = Abc_NtkNodeSupport( pFrames, &pNodePo, 1 );
+    // mark the support of the frames
+    Abc_NtkForEachCi( pFrames, pObj, i )
+        pObj->pCopy = NULL;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)1;
+    // mark the support of the network if the support of the timeframes is marked
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->pCopy = NULL;
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        if ( Abc_NtkBox(pFrames, i)->pCopy )
+            pObj->pCopy = (Abc_Obj_t *)1;
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        for ( k = 0; k <= iFrame; k++ )
+            if ( Abc_NtkPi(pFrames, k*Abc_NtkPiNum(pNtk) + i)->pCopy )
+                pObj->pCopy = (Abc_Obj_t *)1;
+    // free stuff
+    Vec_PtrFree( vSupp );
+    Abc_NtkDelete( pFrames );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports mismatch between the two sequential networks.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames )
+{
+    Vec_Ptr_t * vInfo1, * vInfo2;
+    Abc_Obj_t * pObj, * pObjError, * pObj1, * pObj2;
+    int ValueError1 = -1, ValueError2 = -1;
+    unsigned * pPats1, * pPats2;
+    int i, o, k, nErrors, iFrameError = -1, iNodePo = -1, nPrinted;
+    int fRemove1 = 0, fRemove2 = 0;
+
+    if ( !Abc_NtkIsStrash(pNtk1) )
+        fRemove1 = 1, pNtk1 = Abc_NtkStrash( pNtk1, 0, 0, 0 );
+    if ( !Abc_NtkIsStrash(pNtk2) )
+        fRemove2 = 1, pNtk2 = Abc_NtkStrash( pNtk2, 0, 0, 0 );
+
+    // simulate sequential circuits
+    vInfo1 = Sim_SimulateSeqModel( pNtk1, nFrames, pModel );
+    vInfo2 = Sim_SimulateSeqModel( pNtk2, nFrames, pModel );
+
+    // look for a discrepancy in the PO values
+    nErrors = 0;
+    pObjError = NULL;
+    for ( i = 0; i < nFrames; i++ )
+    {
+        if ( pObjError )
+            break;
+        Abc_NtkForEachPo( pNtk1, pObj1, o )
+        {
+            pObj2  = Abc_NtkPo( pNtk2, o );
+            pPats1 = Sim_SimInfoGet(vInfo1, pObj1);
+            pPats2 = Sim_SimInfoGet(vInfo2, pObj2);
+            if ( pPats1[i] == pPats2[i] )
+                continue;
+            nErrors++;
+            if ( pObjError == NULL )
+            {
+                pObjError   = pObj1;
+                iFrameError = i;
+                iNodePo     = o;
+                ValueError1 = (pPats1[i] > 0);
+                ValueError2 = (pPats2[i] > 0);
+            }
+        }
+    }
+
+    if ( pObjError == NULL )
+    {
+        printf( "No output mismatches detected.\n" );
+        Sim_UtilInfoFree( vInfo1 );
+        Sim_UtilInfoFree( vInfo2 );
+        if ( fRemove1 ) Abc_NtkDelete( pNtk1 );
+        if ( fRemove2 ) Abc_NtkDelete( pNtk2 );
+        return;
+    }
+
+    printf( "Verification failed for at least %d output%s of frame %d: ", nErrors, (nErrors>1? "s":""), iFrameError+1 );
+    // print the first 3 outputs
+    nPrinted = 0;
+    Abc_NtkForEachPo( pNtk1, pObj1, o )
+    {
+        pObj2 = Abc_NtkPo( pNtk2, o );
+        pPats1 = Sim_SimInfoGet(vInfo1, pObj1);
+        pPats2 = Sim_SimInfoGet(vInfo2, pObj2);
+        if ( pPats1[iFrameError] == pPats2[iFrameError] )
+            continue;
+        printf( " %s", Abc_ObjName(pObj1) );
+        if ( ++nPrinted == 3 )
+            break;
+    }
+    if ( nPrinted != nErrors )
+        printf( " ..." );
+    printf( "\n" );
+
+    // mark CIs of the networks in the cone of influence of this output
+    Abc_NtkGetSeqPoSupp( pNtk1, iFrameError, iNodePo );
+    Abc_NtkGetSeqPoSupp( pNtk2, iFrameError, iNodePo );
+
+    // report mismatch for the first output
+    printf( "Output %s: Value in Network1 = %d. Value in Network2 = %d.\n", 
+        Abc_ObjName(pObjError), ValueError1, ValueError2 );
+
+    printf( "The cone of influence of output %s in Network1:\n", Abc_ObjName(pObjError) );
+    printf( "PIs: " );
+    Abc_NtkForEachPi( pNtk1, pObj, i )
+        if ( pObj->pCopy )
+            printf( "%s ", Abc_ObjName(pObj) );
+    printf( "\n" );
+    printf( "Latches: " );
+    Abc_NtkForEachLatch( pNtk1, pObj, i )
+        if ( pObj->pCopy )
+            printf( "%s ", Abc_ObjName(pObj) );
+    printf( "\n" );
+
+    printf( "The cone of influence of output %s in Network2:\n", Abc_ObjName(pObjError) );
+    printf( "PIs: " );
+    Abc_NtkForEachPi( pNtk2, pObj, i )
+        if ( pObj->pCopy )
+            printf( "%s ", Abc_ObjName(pObj) );
+    printf( "\n" );
+    printf( "Latches: " );
+    Abc_NtkForEachLatch( pNtk2, pObj, i )
+        if ( pObj->pCopy )
+            printf( "%s ", Abc_ObjName(pObj) );
+    printf( "\n" );
+
+    // print the patterns
+    for ( i = 0; i <= iFrameError; i++ )
+    {
+        printf( "Frame %d:  ", i+1 );
+
+        printf( "PI(1):" );
+        Abc_NtkForEachPi( pNtk1, pObj, k )
+            if ( pObj->pCopy )
+                printf( "%d", Sim_SimInfoGet(vInfo1, pObj)[i] > 0 );
+        printf( " " );
+        printf( "L(1):" );
+        Abc_NtkForEachLatch( pNtk1, pObj, k )
+            if ( pObj->pCopy )
+                printf( "%d", Sim_SimInfoGet(vInfo1, pObj)[i] > 0 );
+        printf( " " );
+        printf( "%s(1):", Abc_ObjName(pObjError) );
+        printf( "%d", Sim_SimInfoGet(vInfo1, pObjError)[i] > 0 );
+
+        printf( "  " );
+
+        printf( "PI(2):" );
+        Abc_NtkForEachPi( pNtk2, pObj, k )
+            if ( pObj->pCopy )
+                printf( "%d", Sim_SimInfoGet(vInfo2, pObj)[i] > 0 );
+        printf( " " );
+        printf( "L(2):" );
+        Abc_NtkForEachLatch( pNtk2, pObj, k )
+            if ( pObj->pCopy )
+                printf( "%d", Sim_SimInfoGet(vInfo2, pObj)[i] > 0 );
+        printf( " " );
+        printf( "%s(2):", Abc_ObjName(pObjError) );
+        printf( "%d", Sim_SimInfoGet(vInfo2, pObjError)[i] > 0 );
+
+        printf( "\n" );
+    }
+    Abc_NtkForEachCi( pNtk1, pObj, i )
+        pObj->pCopy = NULL;
+    Abc_NtkForEachCi( pNtk2, pObj, i )
+        pObj->pCopy = NULL;
+
+    Sim_UtilInfoFree( vInfo1 );
+    Sim_UtilInfoFree( vInfo2 );
+    if ( fRemove1 ) Abc_NtkDelete( pNtk1 );
+    if ( fRemove2 ) Abc_NtkDelete( pNtk2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates buggy miter emailed by Mike.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSimulteBuggyMiter( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    int * pModel1, * pModel2, * pResult1, * pResult2;
+    char * vPiValues1 = "01001011100000000011010110101000000";
+    char * vPiValues2 = "11001101011101011111110100100010001";
+
+    assert( strlen(vPiValues1) == (unsigned)Abc_NtkPiNum(pNtk) );
+    assert( 1 == Abc_NtkPoNum(pNtk) );
+
+    pModel1 = ABC_ALLOC( int, Abc_NtkCiNum(pNtk) );
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        pModel1[i] = vPiValues1[i] - '0';
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        pModel1[Abc_NtkPiNum(pNtk)+i] = ((int)(ABC_PTRINT_T)pObj->pData) - 1;
+
+    pResult1 = Abc_NtkVerifySimulatePattern( pNtk, pModel1 );
+    printf( "Value = %d\n", pResult1[0] );
+
+    pModel2 = ABC_ALLOC( int, Abc_NtkCiNum(pNtk) );
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        pModel2[i] = vPiValues2[i] - '0';
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        pModel2[Abc_NtkPiNum(pNtk)+i] = pResult1[Abc_NtkPoNum(pNtk)+i];
+
+    pResult2 = Abc_NtkVerifySimulatePattern( pNtk, pModel2 );
+    printf( "Value = %d\n", pResult2[0] );
+
+    ABC_FREE( pModel1 );
+    ABC_FREE( pModel2 );
+    ABC_FREE( pResult1 );
+    ABC_FREE( pResult2 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the PO values under the given input pattern.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+int Abc_NtkIsTrueCex( Abc_Ntk_t * pNtk, Abc_Cex_t * pCex )
+{
+    extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+    Aig_Man_t * pMan;
+    int status = 0, fStrashed = 0;
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        pNtk = Abc_NtkStrash(pNtk, 0, 0, 0);
+        fStrashed = 1;
+    }
+    pMan = Abc_NtkToDar( pNtk, 0, 1 );
+    if ( pMan )
+    {
+        status = Saig_ManVerifyCex( pMan, pCex );
+        Aig_ManStop( pMan );
+    }
+    if ( fStrashed )
+        Abc_NtkDelete( pNtk );
+    return status;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the number of PIs matches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+int Abc_NtkIsValidCex( Abc_Ntk_t * pNtk, Abc_Cex_t * pCex )
+{
+    return Abc_NtkPiNum(pNtk) == pCex->nPis;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abcXsim.c b/abc-build/src/base/abci/abcXsim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abcXsim.c
@@ -0,0 +1,231 @@
+/**CFile****************************************************************
+
+  FileName    [abcXsim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Using X-valued simulation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcXsim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "aig/gia/gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define XVS0   ABC_INIT_ZERO
+#define XVS1   ABC_INIT_ONE
+#define XVSX   ABC_INIT_DC
+
+static inline void Abc_ObjSetXsim( Abc_Obj_t * pObj, int Value )  { pObj->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Value;  }
+static inline int  Abc_ObjGetXsim( Abc_Obj_t * pObj )             { return (int)(ABC_PTRINT_T)pObj->pCopy;           }
+static inline int  Abc_XsimInv( int Value )   
+{ 
+    if ( Value == XVS0 )
+        return XVS1;
+    if ( Value == XVS1 )
+        return XVS0;
+    assert( Value == XVSX );       
+    return XVSX;
+}
+static inline int  Abc_XsimAnd( int Value0, int Value1 )   
+{ 
+    if ( Value0 == XVS0 || Value1 == XVS0 )
+        return XVS0;
+    if ( Value0 == XVSX || Value1 == XVSX )
+        return XVSX;
+    assert( Value0 == XVS1 && Value1 == XVS1 );
+    return XVS1;
+}
+static inline int  Abc_XsimRand2()   
+{
+//    return (rand() & 1) ? XVS1 : XVS0;
+    return (Gia_ManRandom(0) & 1) ? XVS1 : XVS0;
+}
+static inline int  Abc_XsimRand3()   
+{
+    int RetValue;
+    do { 
+//        RetValue = rand() & 3; 
+        RetValue = Gia_ManRandom(0) & 3; 
+    } while ( RetValue == 0 );
+    return RetValue;
+}
+static inline int  Abc_ObjGetXsimFanin0( Abc_Obj_t * pObj )       
+{ 
+    int RetValue;
+    RetValue = Abc_ObjGetXsim(Abc_ObjFanin0(pObj));
+    return Abc_ObjFaninC0(pObj)? Abc_XsimInv(RetValue) : RetValue;
+}
+static inline int  Abc_ObjGetXsimFanin1( Abc_Obj_t * pObj )       
+{ 
+    int RetValue;
+    RetValue = Abc_ObjGetXsim(Abc_ObjFanin1(pObj));
+    return Abc_ObjFaninC1(pObj)? Abc_XsimInv(RetValue) : RetValue;
+}
+static inline void Abc_XsimPrint( FILE * pFile, int Value )   
+{ 
+    if ( Value == XVS0 )
+    {
+        fprintf( pFile, "0" );
+        return;
+    }
+    if ( Value == XVS1 )
+    {
+        fprintf( pFile, "1" );
+        return;
+    }
+    assert( Value == XVSX );       
+    fprintf( pFile, "x" );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs X-valued simulation of the sequential network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkXValueSimulate( Abc_Ntk_t * pNtk, int nFrames, int fXInputs, int fXState, int fVerbose )
+{
+    Abc_Obj_t * pObj;
+    int i, f;
+    assert( Abc_NtkIsStrash(pNtk) );
+//    srand( 0x12341234 );
+    Gia_ManRandom( 1 );
+    // start simulation
+    Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 );
+    if ( fXInputs )
+    {
+        Abc_NtkForEachPi( pNtk, pObj, i )
+            Abc_ObjSetXsim( pObj, XVSX );
+    }
+    else
+    {
+        Abc_NtkForEachPi( pNtk, pObj, i )
+            Abc_ObjSetXsim( pObj, Abc_XsimRand2() );
+    }
+    if ( fXState )
+    {
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+            Abc_ObjSetXsim( Abc_ObjFanout0(pObj), XVSX );
+    }
+    else
+    {
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+            Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchInit(pObj) );
+    }
+    // simulate and print the result
+    fprintf( stdout, "Frame : Inputs : Latches : Outputs\n" );
+    for ( f = 0; f < nFrames; f++ )
+    {
+        Abc_AigForEachAnd( pNtk, pObj, i )
+            Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) );
+        Abc_NtkForEachCo( pNtk, pObj, i )
+            Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) );
+        // print out
+        fprintf( stdout, "%2d : ", f );
+        Abc_NtkForEachPi( pNtk, pObj, i )
+            Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) );
+        fprintf( stdout, " : " );
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+        {
+//            if ( Abc_ObjGetXsim(Abc_ObjFanout0(pObj)) != XVSX )
+//                printf( " %s=", Abc_ObjName(pObj) );
+            Abc_XsimPrint( stdout, Abc_ObjGetXsim(Abc_ObjFanout0(pObj)) );
+        }
+        fprintf( stdout, " : " );
+        Abc_NtkForEachPo( pNtk, pObj, i )
+            Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) );
+        fprintf( stdout, "\n" );
+        // assign input values
+        if ( fXInputs )
+        {
+            Abc_NtkForEachPi( pNtk, pObj, i )
+                Abc_ObjSetXsim( pObj, XVSX );
+        }
+        else
+        {
+            Abc_NtkForEachPi( pNtk, pObj, i )
+                Abc_ObjSetXsim( pObj, Abc_XsimRand2() );
+        }
+        // transfer the latch values
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+            Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cycles the circuit to create a new initial state.]
+
+  Description [Simulates the circuit with random (or ternary) input 
+  for the given number of timeframes to get a better initial state.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCycleInitState( Abc_Ntk_t * pNtk, int nFrames, int fUseXval, int fVerbose )
+{ 
+    Abc_Obj_t * pObj;
+    int i, f;
+    assert( Abc_NtkIsStrash(pNtk) );
+//    srand( 0x12341234 );
+    Gia_ManRandom( 1 );
+    // initialize the values
+    Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 );
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchInit(pObj) );
+    // simulate for the given number of timeframes
+    for ( f = 0; f < nFrames; f++ )
+    {
+        Abc_NtkForEachPi( pNtk, pObj, i )
+            Abc_ObjSetXsim( pObj, fUseXval? ABC_INIT_DC : Abc_XsimRand2() );
+//            Abc_ObjSetXsim( pObj, ABC_INIT_ONE );
+        Abc_AigForEachAnd( pNtk, pObj, i )
+            Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) );
+        Abc_NtkForEachCo( pNtk, pObj, i )
+            Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) );
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+            Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) );
+    }
+    // set the final values
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+    {
+        pObj->pData = (void *)(ABC_PTRINT_T)Abc_ObjGetXsim(Abc_ObjFanout0(pObj));
+//        printf( "%d", Abc_LatchIsInit1(pObj) );
+    }
+//    printf( "\n" );
+}
+
+///////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/abciUnfold2.c b/abc-build/src/base/abci/abciUnfold2.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/abciUnfold2.c
@@ -0,0 +1,186 @@
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandUnfold2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int nFrames;
+    int nConfs;
+    int nProps;
+    int fStruct = 0;
+    int fOldAlgo = 0;
+    int fVerbose;
+    int c;
+    extern Abc_Ntk_t * Abc_NtkDarUnfold2( Abc_Ntk_t * pNtk, int nFrames, int nConfs, int nProps, int fStruct, int fOldAlgo, int fVerbose );
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    nFrames   =      1;
+    nConfs    =   1000;
+    nProps    =   1000;
+    fVerbose  =      0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "CPvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        /* case 'F': */
+        /*     if ( globalUtilOptind >= argc ) */
+        /*     { */
+        /*         Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); */
+        /*         goto usage; */
+        /*     } */
+        /*     nFrames = atoi(argv[globalUtilOptind]); */
+        /*     globalUtilOptind++; */
+        /*     if ( nFrames < 0 ) */
+        /*         goto usage; */
+        /*     break; */
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nConfs = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nConfs < 0 )
+                goto usage;
+            break;
+        case 'P':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nProps = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nProps < 0 )
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( Abc_NtkIsComb(pNtk) )
+    {
+        Abc_Print( -1, "The network is combinational.\n" );
+        return 0;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" );
+        return 0;
+    }
+    if ( Abc_NtkConstrNum(pNtk) > 0 )
+    {
+        Abc_Print( -1, "Constraints are already extracted.\n" );
+        return 0;
+    }
+    if ( Abc_NtkPoNum(pNtk) > 1 && !fStruct )
+    {
+        Abc_Print( -1, "Functional constraint extraction works for single-output miters (use \"orpos\").\n" );
+        return 0;
+    }
+    // modify the current network
+    pNtkRes = Abc_NtkDarUnfold2( pNtk, nFrames, nConfs, nProps, fStruct, fOldAlgo, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( 1,"Transformation has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+usage:
+    Abc_Print( -2, "usage: unfold2 [-FCP num] [-savh]\n" );
+    Abc_Print( -2, "\t         unfold hidden constraints as separate outputs\n" );
+    Abc_Print( -2, "\t-C num : the max number of conflicts in SAT solving [default = %d]\n", nConfs );
+    Abc_Print( -2, "\t-P num : the max number of constraint propagations [default = %d]\n", nProps );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
+
+
+
+int Abc_CommandFold2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk, * pNtkRes;
+    int fCompl;
+    int fVerbose;
+    int c;
+    extern Abc_Ntk_t * Abc_NtkDarFold2( Abc_Ntk_t * pNtk, int fCompl, int fVerbose , int);
+    pNtk = Abc_FrameReadNtk(pAbc);
+    // set defaults
+    fCompl    =   0;
+    fVerbose  =   0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "cvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        /* case 'c': */
+        /*     fCompl ^= 1; */
+        /*     break; */
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash(pNtk) )
+    {
+        Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" );
+        return 0;
+    }
+    if ( Abc_NtkConstrNum(pNtk) == 0 )
+    {
+        Abc_Print( 0, "The network has no constraints.\n" );
+        return 0;
+    }
+    if ( Abc_NtkIsComb(pNtk) )
+        Abc_Print( 0, "The network is combinational.\n" );
+    // modify the current network
+    pNtkRes = Abc_NtkDarFold2( pNtk, fCompl, fVerbose ,0);
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( 1,"Transformation has failed.\n" );
+        return 0;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+usage:
+    Abc_Print( -2, "usage: fold [-cvh]\n" );
+    Abc_Print( -2, "\t         folds constraints represented as separate outputs\n" );
+    //    Abc_Print( -2, "\t-c     : toggle complementing constraints while folding [default = %s]\n", fCompl? "yes": "no" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    return 1;
+}
diff --git a/abc-build/src/base/abci/fahout_cut.c b/abc-build/src/base/abci/fahout_cut.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/fahout_cut.c
@@ -0,0 +1,358 @@
+/**CFile****************************************************************
+
+  FileName    [abcMerge.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [LUT merging algorithm.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "aig/aig/aig.h"
+#include "aig/nwk/nwkMerge.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the fanins of the node with the current trav ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMarkFanins_rec( Abc_Obj_t * pLut, int nLevMin )
+{
+    Abc_Obj_t * pNext;
+    int i;
+    if ( !Abc_ObjIsNode(pLut) )
+        return;
+    if ( Abc_NodeIsTravIdCurrent( pLut ) )
+        return;
+    Abc_NodeSetTravIdCurrent( pLut );
+    if ( Abc_ObjLevel(pLut) < nLevMin )
+        return;
+    Abc_ObjForEachFanin( pLut, pNext, i )
+        Abc_NtkMarkFanins_rec( pNext, nLevMin );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the fanouts of the node with the current trav ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMarkFanouts_rec( Abc_Obj_t * pLut, int nLevMax, int nFanMax )
+{
+    Abc_Obj_t * pNext;
+    int i;
+    if ( !Abc_ObjIsNode(pLut) )
+        return;
+    if ( Abc_NodeIsTravIdCurrent( pLut ) )
+        return;
+    Abc_NodeSetTravIdCurrent( pLut );
+    if ( Abc_ObjLevel(pLut) > nLevMax )
+        return;
+    if ( Abc_ObjFanoutNum(pLut) > nFanMax )
+        return;
+    Abc_ObjForEachFanout( pLut, pNext, i )
+        Abc_NtkMarkFanouts_rec( pNext, nLevMax, nFanMax );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the circle of nodes around the given set.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax )
+{
+    Abc_Obj_t * pObj, * pNext;
+    int i, k;
+    Vec_PtrClear( vNext );
+    Vec_PtrForEachEntry( Vec_Int_t *, vStart, pObj, i )
+    {
+        Abc_ObjForEachFanin( pObj, pNext, k )
+        {
+            if ( !Abc_ObjIsNode(pNext) )
+                continue;
+            if ( Abc_NodeIsTravIdCurrent( pNext ) )
+                continue;
+            Abc_NodeSetTravIdCurrent( pNext );
+            Vec_PtrPush( vNext, pNext );
+        }
+        Abc_ObjForEachFanout( pObj, pNext, k )
+        {
+            if ( !Abc_ObjIsNode(pNext) )
+                continue;
+            if ( Abc_NodeIsTravIdCurrent( pNext ) )
+                continue;
+            Abc_NodeSetTravIdCurrent( pNext );
+            if ( Abc_ObjFanoutNum(pNext) > nFanMax )
+                continue;
+            Vec_PtrPush( vNext, pNext );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the circle of nodes removes from the given one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCollectNonOverlapCands( Abc_Obj_t * pLut, Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars )
+{
+    Vec_Ptr_t * vTemp;
+    Abc_Obj_t * pObj;
+    int i, k;
+    Vec_PtrClear( vCands );
+    if ( pPars->nMaxSuppSize - Abc_ObjFaninNum(pLut) <= 1 )
+        return;
+
+    // collect nodes removed by this distance
+    assert( pPars->nMaxDistance > 0 );
+    Vec_PtrClear( vStart );
+    Vec_PtrPush( vStart, pLut );
+    Abc_NtkIncrementTravId( pLut->pNtk );
+    Abc_NodeSetTravIdCurrent( pLut );
+    for ( i = 1; i <= pPars->nMaxDistance; i++ )
+    {
+        Abc_NtkCollectCircle( vStart, vNext, pPars->nMaxFanout );
+        vTemp  = vStart;
+        vStart = vNext;
+        vNext  = vTemp;
+        // collect the nodes in vStart
+        Vec_PtrForEachEntry( Vec_Int_t *, vStart, pObj, k )
+            Vec_PtrPush( vCands, pObj );
+    }
+
+    // mark the TFI/TFO nodes
+    Abc_NtkIncrementTravId( pLut->pNtk );
+    if ( pPars->fUseTfiTfo )
+        Abc_NodeSetTravIdCurrent( pLut );
+    else
+    {
+        Abc_NodeSetTravIdPrevious( pLut );
+        Abc_NtkMarkFanins_rec( pLut, Abc_ObjLevel(pLut) - pPars->nMaxDistance );
+        Abc_NodeSetTravIdPrevious( pLut );
+        Abc_NtkMarkFanouts_rec( pLut, Abc_ObjLevel(pLut) + pPars->nMaxDistance, pPars->nMaxFanout );
+    }
+
+    // collect nodes satisfying the following conditions:
+    // - they are close enough in terms of distance
+    // - they are not in the TFI/TFO of the LUT
+    // - they have no more than the given number of fanins
+    // - they have no more than the given diff in delay
+    k = 0;
+    Vec_PtrForEachEntry( Vec_Int_t *, vCands, pObj, i )
+    {
+        if ( Abc_NodeIsTravIdCurrent(pObj) )
+            continue;
+        if ( Abc_ObjFaninNum(pLut) + Abc_ObjFaninNum(pObj) > pPars->nMaxSuppSize )
+            continue;
+        if ( Abc_ObjLevel(pLut) - Abc_ObjLevel(pObj) > pPars->nMaxLevelDiff || 
+             Abc_ObjLevel(pObj) - Abc_ObjLevel(pLut) > pPars->nMaxLevelDiff )
+             continue;
+        Vec_PtrWriteEntry( vCands, k++, pObj );
+    }
+    Vec_PtrShrink( vCands, k );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Count the total number of fanins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCountTotalFanins( Abc_Obj_t * pLut, Abc_Obj_t * pCand )
+{
+    Abc_Obj_t * pFanin;
+    int i, nCounter = Abc_ObjFaninNum(pLut);
+    Abc_ObjForEachFanin( pCand, pFanin, i )
+        nCounter += !pFanin->fMarkC;
+    return nCounter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects overlapping candidates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCollectOverlapCands( Abc_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars )
+{
+    Abc_Obj_t * pFanin, * pObj;
+    int i, k;
+    // mark fanins of pLut
+    Abc_ObjForEachFanin( pLut, pFanin, i )
+        pFanin->fMarkC = 1;
+    // collect the matching fanouts of each fanin of the node
+    Vec_PtrClear( vCands );
+    Abc_NtkIncrementTravId( pLut->pNtk );
+    Abc_NodeSetTravIdCurrent( pLut );
+    Abc_ObjForEachFanin( pLut, pFanin, i )
+    {
+        if ( !Abc_ObjIsNode(pFanin) )
+            continue;
+        if ( Abc_ObjFanoutNum(pFanin) > pPars->nMaxFanout )
+            continue;
+        Abc_ObjForEachFanout( pFanin, pObj, k )
+        {
+            if ( !Abc_ObjIsNode(pObj) )
+                continue;
+            if ( Abc_NodeIsTravIdCurrent( pObj ) )
+                continue;
+            Abc_NodeSetTravIdCurrent( pObj );
+            // check the difference in delay
+            if ( Abc_ObjLevel(pLut) - Abc_ObjLevel(pObj) > pPars->nMaxLevelDiff || 
+                 Abc_ObjLevel(pObj) - Abc_ObjLevel(pLut) > pPars->nMaxLevelDiff )
+                 continue;
+            // check the total number of fanins of the node
+            if ( Abc_NtkCountTotalFanins(pLut, pObj) > pPars->nMaxSuppSize )
+                continue;
+            Vec_PtrPush( vCands, pObj );
+        }
+    }
+    // unmark fanins of pLut
+    Abc_ObjForEachFanin( pLut, pFanin, i )
+        pFanin->fMarkC = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs LUT merging with parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkLutMerge( Abc_Ntk_t * pNtk, Nwk_LMPars_t * pPars )
+{
+    Nwk_Grf_t * p;
+    Vec_Int_t * vResult;
+    Vec_Ptr_t * vStart, * vNext, * vCands1, * vCands2;
+    Abc_Obj_t * pLut, * pCand;
+    int i, k, nVertsMax, nCands;
+    clock_t clk = clock();
+    // count the number of vertices
+    nVertsMax = 0;
+    Abc_NtkForEachNode( pNtk, pLut, i )
+        nVertsMax += (int)(Abc_ObjFaninNum(pLut) <= pPars->nMaxLutSize);
+    p = Nwk_ManGraphAlloc( nVertsMax );
+    // create graph
+    vStart  = Vec_PtrAlloc( 1000 );
+    vNext   = Vec_PtrAlloc( 1000 );
+    vCands1 = Vec_PtrAlloc( 1000 );
+    vCands2 = Vec_PtrAlloc( 1000 );
+    nCands  = 0;
+    Abc_NtkForEachNode( pNtk, pLut, i )
+    {
+        if ( Abc_ObjFaninNum(pLut) > pPars->nMaxLutSize )
+            continue;
+        Abc_NtkCollectOverlapCands( pLut, vCands1, pPars );
+        if ( pPars->fUseDiffSupp )
+            Abc_NtkCollectNonOverlapCands( pLut, vStart, vNext, vCands2, pPars );
+        if ( Vec_PtrSize(vCands1) == 0 && Vec_PtrSize(vCands2) == 0 )
+            continue;
+        nCands += Vec_PtrSize(vCands1) + Vec_PtrSize(vCands2);
+        // save candidates
+        Vec_PtrForEachEntry( Vec_Int_t *, vCands1, pCand, k )
+            Nwk_ManGraphHashEdge( p, Abc_ObjId(pLut), Abc_ObjId(pCand) );
+        Vec_PtrForEachEntry( Vec_Int_t *, vCands2, pCand, k )
+            Nwk_ManGraphHashEdge( p, Abc_ObjId(pLut), Abc_ObjId(pCand) );
+        // print statistics about this node
+        if ( pPars->fVeryVerbose )
+        printf( "Node %6d : Fanins = %d. Fanouts = %3d.  Cand1 = %3d. Cand2 = %3d.\n",
+            Abc_ObjId(pLut), Abc_ObjFaninNum(pLut), Abc_ObjFaninNum(pLut), 
+            Vec_PtrSize(vCands1), Vec_PtrSize(vCands2) );
+    }
+    Vec_PtrFree( vStart );
+    Vec_PtrFree( vNext );
+    Vec_PtrFree( vCands1 );
+    Vec_PtrFree( vCands2 );
+    if ( pPars->fVerbose )
+    {
+        printf( "Mergable LUTs = %6d. Total cands = %6d. ", p->nVertsMax, nCands );
+        ABC_PRT( "Deriving graph", clock() - clk );
+    }
+    // solve the graph problem
+    clk = clock();
+    Nwk_ManGraphSolve( p );
+    if ( pPars->fVerbose )
+    {
+        printf( "GRAPH: Nodes = %6d. Edges = %6d.  Pairs = %6d.  ", 
+            p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 );
+        ABC_PRT( "Solving", clock() - clk );
+        Nwk_ManGraphReportMemoryUsage( p );
+    }
+    vResult = p->vPairs; p->vPairs = NULL;
+/*
+    for ( i = 0; i < vResult->nSize; i += 2 )
+        printf( "(%d,%d) ", vResult->pArray[i], vResult->pArray[i+1] );
+    printf( "\n" );
+*/
+    Nwk_ManGraphFree( p );
+    return vResult;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/abci/module.make b/abc-build/src/base/abci/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/abci/module.make
@@ -0,0 +1,71 @@
+SRC +=	src/base/abci/abc.c \
+	src/base/abci/abcAttach.c \
+	src/base/abci/abcAuto.c \
+	src/base/abci/abcBalance.c \
+	src/base/abci/abcBidec.c \
+	src/base/abci/abcBm.c \
+	src/base/abci/abcBmc.c \
+	src/base/abci/abcCas.c \
+	src/base/abci/abcCascade.c \
+	src/base/abci/abcCollapse.c \
+	src/base/abci/abcCut.c \
+	src/base/abci/abcDar.c \
+	src/base/abci/abcDebug.c \
+	src/base/abci/abcDec.c \
+	src/base/abci/abcDress.c \
+	src/base/abci/abcDress2.c \
+	src/base/abci/abcDsd.c \
+	src/base/abci/abcExtract.c \
+	src/base/abci/abcFraig.c \
+        src/base/abci/abcFx.c \
+        src/base/abci/abcFxu.c \
+        src/base/abci/abcGen.c \
+	src/base/abci/abcHaig.c \
+	src/base/abci/abcIf.c \
+	src/base/abci/abcIfif.c \
+	src/base/abci/abcIfMux.c \
+        src/base/abci/abcIvy.c \
+	src/base/abci/abcLog.c \
+	src/base/abci/abcLut.c \
+	src/base/abci/abcLutmin.c \
+	src/base/abci/abcMap.c \
+	src/base/abci/abcMerge.c \
+	src/base/abci/abcMfs.c \
+	src/base/abci/abcMini.c \
+	src/base/abci/abcMiter.c \
+	src/base/abci/abcMulti.c \
+	src/base/abci/abcNtbdd.c \
+	src/base/abci/abcNpn.c \
+	src/base/abci/abcNpnSave.c \
+	src/base/abci/abcOdc.c \
+	src/base/abci/abcOrder.c \
+	src/base/abci/abcPart.c \
+	src/base/abci/abcPrint.c \
+	src/base/abci/abcProve.c \
+	src/base/abci/abcQbf.c \
+	src/base/abci/abcQuant.c \
+	src/base/abci/abcRec3.c \
+	src/base/abci/abcReconv.c \
+	src/base/abci/abcReach.c \
+	src/base/abci/abcRefactor.c \
+	src/base/abci/abcRenode.c \
+	src/base/abci/abcReorder.c \
+	src/base/abci/abcRestruct.c \
+	src/base/abci/abcResub.c \
+	src/base/abci/abcRewrite.c \
+	src/base/abci/abcRpo.c \
+	src/base/abci/abcRr.c \
+	src/base/abci/abcSat.c \
+	src/base/abci/abcSaucy.c \
+	src/base/abci/abcScorr.c \
+	src/base/abci/abcSense.c \
+	src/base/abci/abcSpeedup.c \
+	src/base/abci/abcStrash.c \
+	src/base/abci/abcSweep.c \
+	src/base/abci/abcSymm.c \
+	src/base/abci/abcTim.c \
+	src/base/abci/abcTiming.c \
+	src/base/abci/abcUnate.c \
+	src/base/abci/abcUnreach.c \
+	src/base/abci/abcVerify.c \
+	src/base/abci/abcXsim.c 
diff --git a/abc-build/src/base/cmd/cmd.c b/abc-build/src/base/cmd/cmd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/cmd/cmd.c
@@ -0,0 +1,2282 @@
+/**CFile****************************************************************
+
+  FileName    [cmd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Command file.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cmd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifdef WIN32
+#include <process.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "base/abc/abc.h"
+#include "base/main/mainInt.h"
+#include "cmdInt.h"
+#include "misc/util/utilSignal.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int CmdCommandTime          ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandEcho          ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandQuit          ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandWhich         ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandHistory       ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandAlias         ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandUnalias       ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandHelp          ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandSource        ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandSetVariable   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandUnsetVariable ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandUndo          ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandRecall        ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandEmpty         ( Abc_Frame_t * pAbc, int argc, char ** argv );
+#if defined(WIN32) && !defined(__cplusplus)
+static int CmdCommandScanDir       ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandLs            ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandScrGen        ( Abc_Frame_t * pAbc, int argc, char ** argv );
+#endif
+static int CmdCommandVersion       ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandSis           ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandMvsis         ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandCapo          ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandStarter       ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+extern int Cmd_CommandAbcLoadPlugIn( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the command package.]
+
+  SideEffects [Commands are added to the command table.]
+
+  SeeAlso     [Cmd_End]
+
+******************************************************************************/
+void Cmd_Init( Abc_Frame_t * pAbc )
+{
+    pAbc->tCommands = st__init_table(strcmp, st__strhash);
+    pAbc->tAliases  = st__init_table(strcmp, st__strhash);
+    pAbc->tFlags    = st__init_table(strcmp, st__strhash);
+    pAbc->aHistory  = Vec_PtrAlloc( 100 );
+    Cmd_HistoryRead( pAbc );
+
+    Cmd_CommandAdd( pAbc, "Basic", "time",          CmdCommandTime,            0 );
+    Cmd_CommandAdd( pAbc, "Basic", "echo",          CmdCommandEcho,            0 );
+    Cmd_CommandAdd( pAbc, "Basic", "quit",          CmdCommandQuit,            0 );
+    Cmd_CommandAdd( pAbc, "Basic", "history",       CmdCommandHistory,         0 );
+    Cmd_CommandAdd( pAbc, "Basic", "alias",         CmdCommandAlias,           0 );
+    Cmd_CommandAdd( pAbc, "Basic", "unalias",       CmdCommandUnalias,         0 );
+    Cmd_CommandAdd( pAbc, "Basic", "help",          CmdCommandHelp,            0 );
+    Cmd_CommandAdd( pAbc, "Basic", "source",        CmdCommandSource,          0 );
+    Cmd_CommandAdd( pAbc, "Basic", "set",           CmdCommandSetVariable,     0 );
+    Cmd_CommandAdd( pAbc, "Basic", "unset",         CmdCommandUnsetVariable,   0 );
+    Cmd_CommandAdd( pAbc, "Basic", "undo",          CmdCommandUndo,            0 );
+    Cmd_CommandAdd( pAbc, "Basic", "recall",        CmdCommandRecall,          0 );
+    Cmd_CommandAdd( pAbc, "Basic", "empty",         CmdCommandEmpty,           0 );
+#if defined(WIN32) && !defined(__cplusplus)
+    Cmd_CommandAdd( pAbc, "Basic", "scandir",       CmdCommandScanDir,         0 );
+    Cmd_CommandAdd( pAbc, "Basic", "ls",            CmdCommandLs,              0 );
+    Cmd_CommandAdd( pAbc, "Basic", "scrgen",        CmdCommandScrGen,          0 );
+#endif
+    Cmd_CommandAdd( pAbc, "Basic", "version",       CmdCommandVersion,         0 );
+
+    Cmd_CommandAdd( pAbc, "Various", "sis",         CmdCommandSis,             1 );
+    Cmd_CommandAdd( pAbc, "Various", "mvsis",       CmdCommandMvsis,           1 );
+    Cmd_CommandAdd( pAbc, "Various", "capo",        CmdCommandCapo,            0 );
+    Cmd_CommandAdd( pAbc, "Various", "starter",     CmdCommandStarter,         0 );
+
+    Cmd_CommandAdd( pAbc, "Various", "load_plugin", Cmd_CommandAbcLoadPlugIn,  0 );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the command package.]
+
+  Description [Ends the command package. Tables are freed.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Cmd_End( Abc_Frame_t * pAbc )
+{
+    st__generator * gen;
+    char * pKey, * pValue;
+    Cmd_HistoryWrite( pAbc, ABC_INFINITY );
+
+//    st__free_table( pAbc->tCommands, (void (*)()) 0, CmdCommandFree );
+//    st__free_table( pAbc->tAliases,  (void (*)()) 0, CmdCommandAliasFree );
+//    st__free_table( pAbc->tFlags,    free, free );
+
+    st__foreach_item( pAbc->tCommands, gen, (const char **)&pKey, (char **)&pValue )
+        CmdCommandFree( (Abc_Command *)pValue );
+    st__free_table( pAbc->tCommands );
+
+    st__foreach_item( pAbc->tAliases, gen, (const char **)&pKey, (char **)&pValue )
+        CmdCommandAliasFree( (Abc_Alias *)pValue );
+    st__free_table( pAbc->tAliases );
+
+    st__foreach_item( pAbc->tFlags, gen, (const char **)&pKey, (char **)&pValue )
+        ABC_FREE( pKey ), ABC_FREE( pValue );
+    st__free_table( pAbc->tFlags );
+
+    Vec_PtrFreeFree( pAbc->aHistory );
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    int c;
+    int fClear;
+
+    fClear = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'c':
+            fClear ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( fClear )
+    {
+        pAbc->TimeTotal += pAbc->TimeCommand;
+        pAbc->TimeCommand = 0.0;
+        return 0;
+    }
+
+    if ( argc != globalUtilOptind )
+    {
+        goto usage;
+    }
+
+
+    pAbc->TimeTotal += pAbc->TimeCommand;
+    fprintf( pAbc->Out, "elapse: %3.2f seconds, total: %3.2f seconds\n",
+        pAbc->TimeCommand, pAbc->TimeTotal );
+/*
+    {
+        FILE * pTable;
+        pTable = fopen( "runtimes.txt", "a+" );
+        fprintf( pTable, "%4.2f\n", pAbc->TimeCommand );
+        fclose( pTable );
+    }
+*/
+    pAbc->TimeCommand = 0.0;
+    return 0;
+
+  usage:
+    fprintf( pAbc->Err, "usage: time [-ch]\n" );
+    fprintf( pAbc->Err, "      \t\tprint the runtime since the last call\n" );
+    fprintf( pAbc->Err, "   -c \t\tclears the elapsed time without printing it\n" );
+    fprintf( pAbc->Err, "   -h \t\tprint the command usage\n" );
+    return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandEcho( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    int i;
+    int c;
+    int n = 1;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "hn" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'n':
+            n = 0;
+            break;
+        case 'h':
+            goto usage;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if (pAbc->Out == stdout){
+        for ( i = globalUtilOptind; i < argc; i++ )
+            Abc_Print( 1, "%s ", argv[i] );
+        if ( n )
+            Abc_Print( 1, "\n" );
+
+    }else{
+        for ( i = globalUtilOptind; i < argc; i++ )
+            fprintf( pAbc->Out, "%s ", argv[i] );
+        if ( n )
+            fprintf( pAbc->Out, "\n" );
+
+        fflush ( pAbc->Out );
+    }
+    return 0;
+
+  usage:
+    fprintf( pAbc->Err, "usage: echo [-h] string \n" );
+    fprintf( pAbc->Err, "   -n \t\tsuppress newline at the end\n" );
+    fprintf( pAbc->Err, "   -h \t\tprint the command usage\n" );
+    return ( 1 );
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandQuit( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "hs" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+            break;
+        case 's':
+            return -2;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( argc != globalUtilOptind )
+        goto usage;
+    return -1;
+
+  usage:
+    fprintf( pAbc->Err, "usage: quit [-h] [-s]\n" );
+    fprintf( pAbc->Err, "   -h  print the command usage\n" );
+    fprintf( pAbc->Err,
+                      "   -s  frees all the memory before quitting\n" );
+    return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandWhich( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandHistory( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pName;
+    int i, c;
+    int nPrints = 20;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default :
+                goto usage;
+        }
+    }
+    if ( argc > globalUtilOptind + 1 )
+        goto usage;
+    // get the number from the command line
+    if ( argc == globalUtilOptind + 1 )
+        nPrints = atoi(argv[globalUtilOptind]);
+    // print the commands
+    Vec_PtrForEachEntryStart( char *, pAbc->aHistory, pName, i, Abc_MaxInt(0, Vec_PtrSize(pAbc->aHistory)-nPrints) )
+        fprintf( pAbc->Out, "%2d : %s\n", Vec_PtrSize(pAbc->aHistory)-i, pName );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: history [-h] <num>\n" );
+    fprintf( pAbc->Err, "\t        lists the last commands entered on the command line\n" );
+    fprintf( pAbc->Err, "\t-h    : print the command usage\n" );
+    fprintf( pAbc->Err, "\t<num> : the maximum number of entries to show [default = %d]\n", nPrints );
+    return ( 1 );
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandAlias( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    const char *key;
+    char *value;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+
+    if ( argc == 1 )
+    {
+        CmdPrintTable( pAbc->tAliases, 1 );
+        return 0;
+
+    }
+    else if ( argc == 2 )
+    {
+        if ( st__lookup( pAbc->tAliases, argv[1], &value ) )
+            CmdCommandAliasPrint( pAbc, ( Abc_Alias * ) value );
+        return 0;
+    }
+
+    // delete any existing alias
+    key = argv[1];
+    if ( st__delete( pAbc->tAliases, &key, &value ) )
+        CmdCommandAliasFree( ( Abc_Alias * ) value );
+    CmdCommandAliasAdd( pAbc, argv[1], argc - 2, argv + 2 );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: alias [-h] [command [string]]\n" );
+    fprintf( pAbc->Err, "   -h \t\tprint the command usage\n" );
+    return ( 1 );
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandUnalias( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    int i;
+    const char *key;
+    char *value;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( argc < 2 )
+    {
+        goto usage;
+    }
+
+    for ( i = 1; i < argc; i++ )
+    {
+        key = argv[i];
+        if ( st__delete( pAbc->tAliases, &key, &value ) )
+        {
+            CmdCommandAliasFree( ( Abc_Alias * ) value );
+        }
+    }
+    return 0;
+
+  usage:
+    fprintf( pAbc->Err, "usage: unalias [-h] alias_names\n" );
+    fprintf( pAbc->Err, "   -h \t\tprint the command usage\n" );
+    return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandHelp( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    int fPrintAll, fDetails;
+    int c;
+
+    fPrintAll = 0;
+    fDetails = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "adh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'a':
+            case 'v':
+                fPrintAll ^= 1;
+                break;
+            break;
+        case 'd':
+            fDetails ^= 1;
+            break;
+        case 'h':
+            goto usage;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( argc != globalUtilOptind )
+        goto usage;
+
+    CmdCommandPrint( pAbc, fPrintAll, fDetails );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: help [-a] [-d] [-h]\n" );
+    fprintf( pAbc->Err, "       prints the list of available commands by group\n" );
+    fprintf( pAbc->Err, " -a       toggle printing hidden commands [default = %s]\n", fPrintAll? "yes": "no" );
+    fprintf( pAbc->Err, " -d       print usage details to all commands [default = %s]\n", fDetails? "yes": "no" );
+    fprintf( pAbc->Err, " -h       print the command usage\n" );
+    return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandSource( Abc_Frame_t * pAbc, 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[ABC_MAX_STR], *command;
+    FILE *fp;
+
+    interactive = silent = prompt = echo = 0;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ipsxh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        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;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    /* added to avoid core-dumping when no script file is specified */
+    if ( argc == globalUtilOptind )
+    {
+        goto usage;
+    }
+
+    lp_file_index = globalUtilOptind;
+    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.
+     */
+    pAbc->fSource = 1;
+    do
+    {
+        char * pFileName, * pTemp;
+
+        // get the input file name
+        pFileName = argv[lp_file_index];
+        // fix the wrong symbol
+        for ( pTemp = pFileName; *pTemp; pTemp++ )
+            if ( *pTemp == '>' )
+                *pTemp = '\\';
+
+        lp_count++;             /* increment the loop counter */
+
+        fp = CmdFileOpen( pAbc, pFileName, "r", &real_filename, silent );
+        if ( fp == NULL )
+        {
+            pAbc->fSource = 0;
+            ABC_FREE( real_filename );
+            return !silent;     /* error return if not silent */
+        }
+
+        quit_count = 0;
+        do
+        {
+            if ( prompt )
+            {
+                prompt_string = Cmd_FlagReadByName( pAbc, "prompt" );
+                if ( prompt_string == NULL )
+                    prompt_string = "abc> ";
+
+            }
+            else
+            {
+                prompt_string = NULL;
+            }
+
+            /* clear errors -- e.g., EOF reached from stdin */
+            clearerr( fp );
+
+            /* read another command line */
+            if ( fgets( line, ABC_MAX_STR, fp ) == NULL )
+            {
+                if ( interactive )
+                {
+                    if ( quit_count++ < 5 )
+                    {
+                        fprintf( pAbc->Err, "\nUse \"quit\" to leave ABC.\n" );
+                        continue;
+                    }
+                    status = -1;    /* fake a 'quit' */
+                }
+                else
+                {
+                    status = 0; /* successful end of 'source' ; loop? */
+                }
+                break;
+            }
+            quit_count = 0;
+
+            if ( echo )
+            {
+                fprintf( pAbc->Out, "abc - > %s", line );
+            }
+            command = CmdHistorySubstitution( pAbc, line, &did_subst );
+            if ( command == NULL )
+            {
+                status = 1;
+                break;
+            }
+            if ( did_subst )
+            {
+                if ( interactive )
+                {
+                    fprintf( pAbc->Out, "%s\n", command );
+                }
+            }
+            if ( command != line )
+            {
+                strcpy( line, command );
+            }
+            if ( interactive && *line != '\0' )
+            {
+                Cmd_HistoryAddCommand( pAbc, line );
+                if ( pAbc->Hst != NULL )
+                {
+                    fprintf( pAbc->Hst, "%s\n", line );
+                    fflush( pAbc->Hst );
+                }
+            }
+
+            fflush( pAbc->Out );
+            status = Cmd_CommandExecute( pAbc, line );
+        }
+        while ( status == 0 );
+
+        if ( fp != stdin )
+        {
+            if ( status > 0 )
+            {
+                fprintf( pAbc->Err,
+                                  "** cmd error: aborting 'source %s'\n",
+                                  real_filename );
+            }
+            fclose( fp );
+        }
+        ABC_FREE( real_filename );
+
+    }
+    while ( ( status == 0 ) && ( lp_count <= 0 ) );
+    pAbc->fSource = 0;
+    return status;
+
+  usage:
+    fprintf( pAbc->Err, "usage: source [-psxh] <file_name>\n" );
+    fprintf( pAbc->Err, "\t-p     supply prompt before reading each line [default = %s]\n", prompt? "yes": "no" );
+    fprintf( pAbc->Err, "\t-s     silently ignore nonexistant file [default = %s]\n", silent? "yes": "no" );
+    fprintf( pAbc->Err, "\t-x     echo each line as it is executed [default = %s]\n", echo? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h     print the command usage\n" );
+    return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char *flag_value, *value;
+    const char* key;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( argc == 0 || argc > 3 )
+    {
+        goto usage;
+    }
+    else if ( argc == 1 )
+    {
+        CmdPrintTable( pAbc->tFlags, 0 );
+        return 0;
+    }
+    else
+    {
+        key = argv[1];
+        if ( st__delete( pAbc->tFlags, &key, &value ) )
+        {
+            ABC_FREE( key );
+            ABC_FREE( value );
+        }
+
+        flag_value = argc == 2 ? Extra_UtilStrsav( "" ) : Extra_UtilStrsav( argv[2] );
+//        flag_value = argc == 2 ? NULL : Extra_UtilStrsav(argv[2]);
+        st__insert( pAbc->tFlags, Extra_UtilStrsav(argv[1]), flag_value );
+
+        if ( strcmp( argv[1], "abcout" ) == 0 )
+        {
+            if ( pAbc->Out != stdout )
+                fclose( pAbc->Out );
+            if ( strcmp( flag_value, "" ) == 0 )
+                flag_value = "-";
+            pAbc->Out = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 );
+            if ( pAbc->Out == NULL )
+                pAbc->Out = stdout;
+#if HAVE_SETVBUF
+            setvbuf( pAbc->Out, ( char * ) NULL, _IOLBF, 0 );
+#endif
+        }
+        if ( strcmp( argv[1], "abcerr" ) == 0 )
+        {
+            if ( pAbc->Err != stderr )
+                fclose( pAbc->Err );
+            if ( strcmp( flag_value, "" ) == 0 )
+                flag_value = "-";
+            pAbc->Err = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 );
+            if ( pAbc->Err == NULL )
+                pAbc->Err = stderr;
+#if HAVE_SETVBUF
+            setvbuf( pAbc->Err, ( char * ) NULL, _IOLBF, 0 );
+#endif
+        }
+        if ( strcmp( argv[1], "history" ) == 0 )
+        {
+            if ( pAbc->Hst != NULL )
+                fclose( pAbc->Hst );
+            if ( strcmp( flag_value, "" ) == 0 )
+                pAbc->Hst = NULL;
+            else
+            {
+                pAbc->Hst = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 );
+                if ( pAbc->Hst == NULL )
+                    pAbc->Hst = NULL;
+            }
+        }
+        return 0;
+    }
+
+  usage:
+    fprintf( pAbc->Err, "usage: set [-h] <name> <value>\n" );
+    fprintf( pAbc->Err, "\t        sets the value of parameter <name>\n" );
+    fprintf( pAbc->Err, "\t-h    : print the command usage\n" );
+    return 1;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandUnsetVariable( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    int i;
+    const char *key;
+    char *value;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( argc < 2 )
+    {
+        goto usage;
+    }
+
+    for ( i = 1; i < argc; i++ )
+    {
+        key = argv[i];
+        if ( st__delete( pAbc->tFlags, &key, &value ) )
+        {
+            ABC_FREE( key );
+            ABC_FREE( value );
+        }
+    }
+    return 0;
+
+
+  usage:
+    fprintf( pAbc->Err, "usage: unset [-h] <name> \n" );
+    fprintf( pAbc->Err, "\t        removes the value of parameter <name>\n" );
+    fprintf( pAbc->Err, "\t-h    : print the command usage\n" );
+    return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandUndo( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    if ( argc == 2 && !strcmp(argv[1], "-h") )
+        goto usage;
+
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+
+    // if there are no arguments on the command line
+    // set the current network to be the network from the previous step
+    if ( argc == 1 )
+        return CmdCommandRecall( pAbc, argc, argv );
+
+usage:
+    fprintf( pAbc->Err, "usage: undo\n" );
+    fprintf( pAbc->Err, "         sets the current network to be the previously saved network\n" );
+    return 1;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandRecall( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    Abc_Ntk_t * pNtk;
+    int iStep, iStepFound;
+    int nNetsToSave, c;
+    char * pValue;
+    int iStepStart, iStepStop;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+
+    // get the number of networks to save
+    pValue = Cmd_FlagReadByName( pAbc, "savesteps" );
+    // if the value of steps to save is not set, assume 1-level undo
+    if ( pValue == NULL )
+        nNetsToSave = 1;
+    else
+        nNetsToSave = atoi(pValue);
+
+    // if there are no arguments on the command line
+    // set the current network to be the network from the previous step
+    if ( argc == 1 )
+    {
+        // get the previously saved network
+        pNtk = Abc_NtkBackup(pAbc->pNtkCur);
+        if ( pNtk == NULL )
+            fprintf( pAbc->Out, "There is no previously saved network.\n" );
+        else // set the current network to be the copy of the previous one
+            Abc_FrameSetCurrentNetwork( pAbc, Abc_NtkDup(pNtk) );
+         return 0;
+    }
+    if ( argc == 2 ) // the second argument is the number of the step to return to
+    {
+        // read the number of the step to return to
+        iStep = atoi(argv[1]);
+        // check whether it is reasonable
+        if ( iStep >= pAbc->nSteps )
+        {
+            iStepStart = pAbc->nSteps - nNetsToSave;
+            if ( iStepStart <= 0 )
+                iStepStart = 1;
+            iStepStop  = pAbc->nSteps;
+            if ( iStepStop <= 0 )
+                iStepStop = 1;
+            if ( iStepStart == iStepStop )
+                fprintf( pAbc->Out, "Can only recall step %d.\n", iStepStop );
+            else
+                fprintf( pAbc->Out, "Can only recall steps %d-%d.\n", iStepStart, iStepStop );
+        }
+        else if ( iStep < 0 )
+            fprintf( pAbc->Out, "Cannot recall step %d.\n", iStep );
+        else if ( iStep == 0 )
+            Abc_FrameDeleteAllNetworks( pAbc );
+        else
+        {
+            // scroll backward through the list of networks
+            // to determine if such a network exist
+            iStepFound = 0;
+            for ( pNtk = pAbc->pNtkCur; pNtk; pNtk = Abc_NtkBackup(pNtk) )
+                if ( (iStepFound = Abc_NtkStep(pNtk)) == iStep )
+                    break;
+            if ( pNtk == NULL )
+            {
+                iStepStart = iStepFound;
+                if ( iStepStart <= 0 )
+                    iStepStart = 1;
+                iStepStop  = pAbc->nSteps;
+                if ( iStepStop <= 0 )
+                    iStepStop = 1;
+                if ( iStepStart == iStepStop )
+                    fprintf( pAbc->Out, "Can only recall step %d.\n", iStepStop );
+                else
+                    fprintf( pAbc->Out, "Can only recall steps %d-%d.\n", iStepStart, iStepStop );
+            }
+            else
+                Abc_FrameSetCurrentNetwork( pAbc, Abc_NtkDup(pNtk) );
+        }
+        return 0;
+    }
+
+usage:
+
+    fprintf( pAbc->Err, "usage: recall -h <num>\n" );
+    fprintf( pAbc->Err, "         set the current network to be one of the previous networks\n" );
+    fprintf( pAbc->Err, "<num> :  level to return to [default = previous]\n" );
+    fprintf( pAbc->Err, "   -h :  print the command usage\n");
+    return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandEmpty( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+
+    Abc_FrameDeleteAllNetworks( pAbc );
+    Abc_FrameRestart( pAbc );
+    return 0;
+usage:
+
+    fprintf( pAbc->Err, "usage: empty [-h]\n" );
+    fprintf( pAbc->Err, "         removes all the currently stored networks\n" );
+    fprintf( pAbc->Err, "   -h :  print the command usage\n");
+    return 1;
+}
+
+
+#if 0
+
+/**Function********************************************************************
+
+  Synopsis    [Donald's version.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandUndo( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    Abc_Ntk_t * pNtkTemp;
+    int id, c;
+
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+            break;
+        default:
+            goto usage;
+        }
+    }
+    if (globalUtilOptind <= argc) {
+    pNtkTemp = pAbc->pNtk;
+    pAbc->pNtk = pAbc->pNtkSaved;
+    pAbc->pNtkSaved = pNtkTemp;
+    }
+    id = atoi(argv[globalUtilOptind]);
+    pNtkTemp = Cmd_HistoryGetSnapshot(pAbc, id);
+    if (!pNtkTemp)
+    fprintf( pAbc->Err, "Snapshot %d does not exist\n", id);
+    else
+    pAbc->pNtk = Abc_NtkDup(pNtkTemp, Abc_NtkMan(pNtkTemp));
+
+    return 0;
+usage:
+    fprintf( pAbc->Err, "usage: undo\n" );
+    fprintf( pAbc->Err, "       swaps the current network and the backup network\n" );
+    return 1;
+}
+
+#endif
+
+
+#if defined(WIN32) && !defined(__cplusplus)
+#include <direct.h>
+
+// these structures are defined in <io.h> but are for some reason invisible
+typedef unsigned long _fsize_t; // Could be 64 bits for Win32
+
+struct _finddata_t {
+    unsigned    attrib;
+    time_t      time_create;    // -1 for FAT file systems
+    time_t      time_access;    // -1 for FAT file systems
+    time_t      time_write;
+    _fsize_t    size;
+    char        name[260];
+};
+
+extern long _findfirst( char *filespec, struct _finddata_t *fileinfo );
+extern int  _findnext( long handle, struct _finddata_t *fileinfo );
+extern int  _findclose( long handle );
+
+//extern char * _getcwd( char * buffer, int maxlen );
+//extern int    _chdir( const char *dirname );
+
+
+/**Function*************************************************************
+
+  Synopsis    [Command to print the contents of the current directory (Windows).]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int CmdCommandScanDir( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    struct _finddata_t c_file;
+    char * pDirStr = NULL;
+    char*  pDirCur = NULL;
+    long   hFile;
+    char   c;
+
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "D") ) != EOF )
+    {
+        switch (c)
+        {
+            case 'D':
+                if ( globalUtilOptind >= argc )
+                {
+                    fprintf( pAbc->Err, "Command line switch \"-D\" should be followed by a string.\n" );
+                    goto usage;
+                }
+                pDirStr = argv[globalUtilOptind];
+                globalUtilOptind++;
+                break;
+            default:
+                goto usage;
+        }
+    }
+
+
+    if ( pDirStr )
+    {
+        if( (pDirCur = _getcwd( NULL, 0 )) == NULL )
+        {
+            printf( "Cannot read current directory\n" );
+            return 0;
+        }
+        if ( _chdir(pDirStr) )
+        {
+            printf( "Cannot change to directory: %s\n", pDirStr );
+            return 0;
+        }
+    }
+
+    if( (hFile = _findfirst( "*.txt", &c_file )) == -1L )
+    {
+        if ( pDirStr )
+            printf( "No .txt files in the current directory.\n" );
+        else
+            printf( "No .txt files in directory: %s\n", pDirStr );
+    }
+    else
+    {
+        do
+        {
+            FILE * pFile = fopen( c_file.name, "rb" );
+            char * pStr1 = "Property UNDECIDED.  Time =";
+            char * pStr2 = "Property proved.  Time =";
+            char * pStr3 = "Time =";
+            char * pBuffer, * pPlace, * pThis, * pThat;
+            char FileName[100];
+            float Time = 0;
+            // get the file name
+            sprintf( FileName, "%s", c_file.name );
+            pThis = strrchr( FileName, '_' );
+            pThat = strchr( FileName, '.' );
+            if ( pThis == NULL || pThat == NULL || pThis >= pThat )
+            {
+//                printf( "Something is wrong with the file name %s\n", c_file.name );
+                continue;
+            }
+            *pThat = 0;
+            pThis++;
+            // get the time
+            if ( pFile == NULL )
+            {
+                printf( "Cannot open file %s\n", c_file.name );
+                continue;
+            }
+            fclose( pFile );
+            pBuffer = Extra_FileReadContents( c_file.name );
+            pPlace = strstr( pBuffer, pStr1 );
+            if ( pPlace == NULL )
+            {
+                pPlace = strstr( pBuffer, pStr2 );
+                if ( pPlace == NULL )
+                {
+                    pPlace = strstr( pBuffer, pStr3 );
+                    if ( pPlace == NULL )
+                    {
+//                        printf( "Cannot find substrings in file %s\n", c_file.name );
+                        ABC_FREE( pBuffer );
+                        continue;
+                    }
+                    else
+                        pPlace += strlen( pStr3 );
+                }
+                else
+                    pPlace += strlen( pStr2 );
+            }
+            else
+                pPlace += strlen( pStr1 );
+            sscanf( pPlace, "%f", &Time );
+            printf( "%s %.2f\n", pThis, Time );
+            ABC_FREE( pBuffer );
+        }
+        while( _findnext( hFile, &c_file ) == 0 );
+        _findclose( hFile );
+    }
+    if ( pDirStr )
+    {
+        if ( _chdir(pDirCur) )
+        {
+            ABC_FREE( pDirCur );
+            printf( "Cannot change to directory: %s\n", pDirCur );
+            return 0;
+        }
+        ABC_FREE( pDirCur );
+    }
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: scandir [-D string]\n" );
+    fprintf( pAbc->Err, "            performs custom scanning of the files in the given directory\n" );
+    fprintf( pAbc->Err, "\t-D str  : the directory to read files from [default = current]\n" );
+    return 1;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Command to print the contents of the current directory (Windows).]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int CmdCommandLs( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    struct _finddata_t c_file;
+    long   hFile;
+    int    fLong = 0;
+    int    fOnlyBLIF = 0;
+    char   Buffer[25];
+    int    Counter = 0;
+    int    fPrintedNewLine;
+    char   c;
+
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "lb") ) != EOF )
+    {
+        switch (c)
+        {
+            case 'l':
+              fLong = 1;
+              break;
+            case 'b':
+              fOnlyBLIF = 1;
+              break;
+            default:
+              goto usage;
+        }
+    }
+
+    // find first .mv file in current directory
+    if( (hFile = _findfirst( ((fOnlyBLIF)? "*.mv": "*.*"), &c_file )) == -1L )
+    {
+        if ( fOnlyBLIF )
+            fprintf( pAbc->Out, "No *.mv files in the current directory.\n" );
+        else
+            fprintf( pAbc->Out, "No files in the current directory.\n" );
+    }
+    else
+    {
+        if ( fLong )
+        {
+            fprintf( pAbc->Out, " File              Date           Size |  File             Date           Size \n" );
+            fprintf( pAbc->Out, " ----------------------------------------------------------------------------- \n" );
+            do
+            {
+                strcpy( Buffer, ctime( &(c_file.time_write) ) );
+                Buffer[16] = 0;
+                fprintf( pAbc->Out, " %-17s %.24s%7ld", c_file.name, Buffer+4, c_file.size );
+                if ( ++Counter % 2 == 0 )
+                {
+                    fprintf( pAbc->Out, "\n" );
+                    fPrintedNewLine = 1;
+                }
+                else
+                {
+                    fprintf( pAbc->Out, " |" );
+                    fPrintedNewLine = 0;
+                }
+            }
+            while( _findnext( hFile, &c_file ) == 0 );
+        }
+        else
+        {
+            do
+            {
+                fprintf( pAbc->Out, " %-18s", c_file.name );
+                if ( ++Counter % 4 == 0 )
+                {
+                    fprintf( pAbc->Out, "\n" );
+                    fPrintedNewLine = 1;
+                }
+                else
+                {
+                    fprintf( pAbc->Out, " " );
+                    fPrintedNewLine = 0;
+                }
+            }
+            while( _findnext( hFile, &c_file ) == 0 );
+        }
+        if ( !fPrintedNewLine )
+            fprintf( pAbc->Out, "\n" );
+        _findclose( hFile );
+    }
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: ls [-l] [-b]\n" );
+    fprintf( pAbc->Err, "       print the file names in the current directory\n" );
+    fprintf( pAbc->Err, "        -l : print in the long format [default = short]\n" );
+    fprintf( pAbc->Err, "        -b : print only .mv files [default = all]\n" );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Generates the script for running ABC.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int CmdCommandScrGen( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    struct _finddata_t c_file;
+    long   hFile;
+    FILE * pFile = NULL;
+    char * pFileStr = "test.s";
+    char * pDirStr = NULL;
+    char * pComStr = "ps";
+    char * pWriteStr = NULL;
+    char   Buffer[1000], Line[2000];
+    int    nFileNameMax, nFileNameCur;
+    int    Counter = 0;
+    int    fUseCurrent;
+    char   c;
+
+    fUseCurrent = 0;
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "FDCWch") ) != EOF )
+    {
+        switch (c)
+        {
+        case 'F':
+            if ( globalUtilOptind >= argc )
+            {
+                fprintf( pAbc->Err, "Command line switch \"-F\" should be followed by a string.\n" );
+                goto usage;
+            }
+            pFileStr = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                fprintf( pAbc->Err, "Command line switch \"-D\" should be followed by a string.\n" );
+                goto usage;
+            }
+            pDirStr = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                fprintf( pAbc->Err, "Command line switch \"-C\" should be followed by a string.\n" );
+                goto usage;
+            }
+            pComStr = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                fprintf( pAbc->Err, "Command line switch \"-W\" should be followed by a string.\n" );
+                goto usage;
+            }
+            pWriteStr = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'c':
+            fUseCurrent ^= 1;
+            break;
+        default:
+            goto usage;
+        }
+    }
+
+//    printf( "File = %s.\n", pFileStr );
+//    printf( "Dir = %s.\n", pDirStr );
+//    printf( "Com = %s.\n", pComStr );
+    if ( pDirStr == NULL )
+        fUseCurrent = 1;
+
+    if ( _getcwd( Buffer, 1000 ) == NULL )
+    {
+        printf( "Cannot get the current directory.\n" );
+        return 0;
+    }
+    if ( fUseCurrent )
+        pFile = fopen( pFileStr, "w" );
+    if ( pDirStr )
+    {
+        if ( _chdir(pDirStr) )
+        {
+            printf( "Cannot change to directory: %s\n", pDirStr );
+            return 0;
+        }
+    }
+    if ( !fUseCurrent )
+        pFile = fopen( pFileStr, "w" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file %s.\n", pFileStr );
+        if ( pDirStr && _chdir(Buffer) )
+        {
+            printf( "Cannot change to the current directory: %s\n", Buffer );
+            return 0;
+        }
+        return 0;
+    }
+
+    // find the first file in the directory
+    if( (hFile = _findfirst( "*.*", &c_file )) == -1L )
+    {
+        if ( pDirStr )
+            printf( "No files in the current directory.\n" );
+        else
+            printf( "No files in directory: %s\n", pDirStr );
+        if ( pDirStr && _chdir(Buffer) )
+        {
+            printf( "Cannot change to the current directory: %s\n", Buffer );
+            return 0;
+        }
+    }
+
+    // get the longest file name
+    {
+        nFileNameMax = 0;
+        do
+        {
+            // skip script and txt files
+            nFileNameCur = strlen(c_file.name);
+            if ( c_file.name[nFileNameCur-1] == '.' )
+                continue;
+            if ( nFileNameCur > 2 &&
+                 c_file.name[nFileNameCur-1] == 's' &&
+                 c_file.name[nFileNameCur-2] == '.' )
+                 continue;
+            if ( nFileNameCur > 4 &&
+                 c_file.name[nFileNameCur-1] == 't' &&
+                 c_file.name[nFileNameCur-2] == 'x' &&
+                 c_file.name[nFileNameCur-3] == 't' &&
+                 c_file.name[nFileNameCur-4] == '.' )
+                 continue;
+            if ( nFileNameMax < nFileNameCur )
+                nFileNameMax = nFileNameCur;
+        }
+        while( _findnext( hFile, &c_file ) == 0 );
+        _findclose( hFile );
+    }
+
+    // print the script file
+    {
+        if( (hFile = _findfirst( "*.*", &c_file )) == -1L )
+        {
+            if ( pDirStr )
+                printf( "No files in the current directory.\n" );
+            else
+                printf( "No files in directory: %s\n", pDirStr );
+        }
+        fprintf( pFile, "# Script file produced by ABC on %s\n", Extra_TimeStamp() );
+        fprintf( pFile, "# Command line was: scrgen -F %s -D %s -C \"%s\"%s%s\n",
+            pFileStr, pDirStr, pComStr, pWriteStr?" -W ":"", pWriteStr?pWriteStr:"" );
+        do
+        {
+            // skip script and txt files
+            nFileNameCur = strlen(c_file.name);
+            if ( c_file.name[nFileNameCur-1] == '.' )
+                continue;
+            if ( nFileNameCur > 2 &&
+                 c_file.name[nFileNameCur-1] == 's' &&
+                 c_file.name[nFileNameCur-2] == '.' )
+                 continue;
+            if ( nFileNameCur > 4 &&
+                 c_file.name[nFileNameCur-1] == 't' &&
+                 c_file.name[nFileNameCur-2] == 'x' &&
+                 c_file.name[nFileNameCur-3] == 't' &&
+                 c_file.name[nFileNameCur-4] == '.' )
+                 continue;
+            sprintf( Line, "r %s%s%-*s ; %s", pDirStr?pDirStr:"", pDirStr?"/":"", nFileNameMax, c_file.name, pComStr );
+            for ( c = (int)strlen(Line)-1; c >= 0; c-- )
+                if ( Line[c] == '\\' )
+                    Line[c] = '/';
+            fprintf( pFile, "%s", Line );
+            if ( pWriteStr )
+            {
+                sprintf( Line, " ; w %s/%-*s", pWriteStr, nFileNameMax, c_file.name );
+                for ( c = (int)strlen(Line)-1; c >= 0; c-- )
+                    if ( Line[c] == '\\' )
+                        Line[c] = '/';
+                fprintf( pFile, "%s", Line );
+            }
+            fprintf( pFile, "\n", Line );
+        }
+        while( _findnext( hFile, &c_file ) == 0 );
+        _findclose( hFile );
+    }
+    fclose( pFile );
+    if ( pDirStr && _chdir(Buffer) )
+    {
+        printf( "Cannot change to the current directory: %s\n", Buffer );
+        return 0;
+    }
+
+    // report
+    if ( fUseCurrent )
+        printf( "Script file \"%s\" was saved in the current directory.\n", pFileStr );
+    else
+        printf( "Script file \"%s\" was saved in directory: %s\n", pFileStr, pDirStr );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: scrgen -F <str> -D <str> -C <str> -W <str> -ch\n" );
+    fprintf( pAbc->Err, "\t          generates script for running ABC\n" );
+    fprintf( pAbc->Err, "\t-F str  : the name of the script file [default = \"test.s\"]\n" );
+    fprintf( pAbc->Err, "\t-D str  : the directory to read files from [default = current]\n" );
+    fprintf( pAbc->Err, "\t-C str  : the sequence of commands to run [default = \"ps\"]\n" );
+    fprintf( pAbc->Err, "\t-W str  : the directory to write the resulting files [default = no writing]\n" );
+    fprintf( pAbc->Err, "\t-c      : toggle placing file in current/target dir [default = %s]\n", fUseCurrent? "current": "target" );
+    fprintf( pAbc->Err, "\t-h      : print the command usage\n\n");
+    fprintf( pAbc->Err, "\tExample : scrgen -F test1.s -D a/in -C \"ps; st; ps\" -W a/out\n" );
+    return 1;
+}
+#endif
+
+
+#ifdef WIN32
+#define unlink _unlink
+#endif
+
+/**Function********************************************************************
+
+  Synopsis    [Calls SIS internally.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandSis( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    FILE * pFile;
+    FILE * pOut, * pErr;
+    Abc_Ntk_t * pNtk, * pNtkNew, * pNetlist;
+    char * pNameWin = "sis.exe";
+    char * pNameUnix = "sis";
+    char Command[1000], Buffer[100];
+    char * pSisName;
+    int i;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    if ( argc == 1 )
+        goto usage;
+    if ( strcmp( argv[1], "-h" ) == 0 )
+        goto usage;
+    if ( strcmp( argv[1], "-?" ) == 0 )
+        goto usage;
+
+    if ( pNtk == NULL )
+    {
+        fprintf( pErr, "Empty network.\n" );
+        goto usage;
+    }
+
+    if ( strcmp( argv[0], "sis" ) != 0 )
+    {
+        fprintf( pErr, "Wrong command: \"%s\".\n", argv[0] );
+        goto usage;
+    }
+
+    // get the names from the resource file
+    if ( Cmd_FlagReadByName(pAbc, "siswin") )
+        pNameWin = Cmd_FlagReadByName(pAbc, "siswin");
+    if ( Cmd_FlagReadByName(pAbc, "sisunix") )
+        pNameUnix = Cmd_FlagReadByName(pAbc, "sisunix");
+
+    // check if SIS is available
+    if ( (pFile = fopen( pNameWin, "r" )) )
+        pSisName = pNameWin;
+    else if ( (pFile = fopen( pNameUnix, "r" )) )
+        pSisName = pNameUnix;
+    else if ( pFile == NULL )
+    {
+        fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pNameWin, pNameUnix );
+        goto usage;
+    }
+    fclose( pFile );
+
+    if ( Abc_NtkIsMappedLogic(pNtk) )
+    {
+        Abc_NtkMapToSop(pNtk);
+        printf( "The current network is unmapped before calling SIS.\n" );
+    }
+
+    // write out the current network
+    if ( Abc_NtkIsLogic(pNtk) )
+        Abc_NtkToSop(pNtk, 0);
+    pNetlist = Abc_NtkToNetlist(pNtk);
+    if ( pNetlist == NULL )
+    {
+        fprintf( pErr, "Cannot produce the intermediate network.\n" );
+        goto usage;
+    }
+    Io_WriteBlif( pNetlist, "_sis_in.blif", 1, 0, 0 );
+    Abc_NtkDelete( pNetlist );
+
+    // create the file for sis
+    sprintf( Command, "%s -x -c ", pSisName );
+    strcat ( Command, "\"" );
+    strcat ( Command, "read_blif _sis_in.blif" );
+    strcat ( Command, "; " );
+    for ( i = 1; i < argc; i++ )
+    {
+        sprintf( Buffer, " %s", argv[i] );
+        strcat( Command, Buffer );
+    }
+    strcat( Command, "; " );
+    strcat( Command, "write_blif _sis_out.blif" );
+    strcat( Command, "\"" );
+
+    // call SIS
+    if ( Util_SignalSystem( Command ) )
+    {
+        fprintf( pErr, "The following command has returned non-zero exit status:\n" );
+        fprintf( pErr, "\"%s\"\n", Command );
+        unlink( "_sis_in.blif" );
+        goto usage;
+    }
+
+    // read in the SIS output
+    if ( (pFile = fopen( "_sis_out.blif", "r" )) == NULL )
+    {
+        fprintf( pErr, "Cannot open SIS output file \"%s\".\n", "_sis_out.blif" );
+        unlink( "_sis_in.blif" );
+        goto usage;
+    }
+    fclose( pFile );
+
+    // set the new network
+    pNtkNew = Io_Read( "_sis_out.blif", IO_FILE_BLIF, 1, 0 );
+    // set the original spec of the new network
+    if ( pNtk->pSpec )
+    {
+        ABC_FREE( pNtkNew->pSpec );
+        pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec );
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew );
+
+    // remove temporary networks
+    unlink( "_sis_in.blif" );
+    unlink( "_sis_out.blif" );
+    return 0;
+
+usage:
+    fprintf( pErr, "Usage: sis [-h] <com>\n");
+    fprintf( pErr, "         invokes SIS command for the current ABC network\n" );
+    fprintf( pErr, "         (the executable of SIS should be in the same directory)\n" );
+    fprintf( pErr, "   -h  : print the command usage\n" );
+    fprintf( pErr, " <com> : a SIS command (or a semicolon-separated list of commands in quotes)\n" );
+    fprintf( pErr, "         Example 1: sis eliminate 0\n" );
+    fprintf( pErr, "         Example 2: sis \"ps; rd; fx; ps\"\n" );
+    fprintf( pErr, "         Example 3: sis source script.rugged\n" );
+    return 1;                   // error exit
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Calls SIS internally.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandMvsis( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    FILE * pFile;
+    FILE * pOut, * pErr;
+    Abc_Ntk_t * pNtk, * pNtkNew, * pNetlist;
+    char Command[1000], Buffer[100];
+    char * pNameWin = "mvsis.exe";
+    char * pNameUnix = "mvsis";
+    char * pMvsisName;
+    int i;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    if ( argc == 1 )
+        goto usage;
+    if ( strcmp( argv[1], "-h" ) == 0 )
+        goto usage;
+    if ( strcmp( argv[1], "-?" ) == 0 )
+        goto usage;
+
+    if ( pNtk == NULL )
+    {
+        fprintf( pErr, "Empty network.\n" );
+        goto usage;
+    }
+
+    if ( strcmp( argv[0], "mvsis" ) != 0 )
+    {
+        fprintf( pErr, "Wrong command: \"%s\".\n", argv[0] );
+        goto usage;
+    }
+
+    // get the names from the resource file
+    if ( Cmd_FlagReadByName(pAbc, "mvsiswin") )
+        pNameWin = Cmd_FlagReadByName(pAbc, "mvsiswin");
+    if ( Cmd_FlagReadByName(pAbc, "mvsisunix") )
+        pNameUnix = Cmd_FlagReadByName(pAbc, "mvsisunix");
+
+    // check if MVSIS is available
+    if ( (pFile = fopen( pNameWin, "r" )) )
+        pMvsisName = pNameWin;
+    else if ( (pFile = fopen( pNameUnix, "r" )) )
+        pMvsisName = pNameUnix;
+    else if ( pFile == NULL )
+    {
+        fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pNameWin, pNameUnix );
+        goto usage;
+    }
+    fclose( pFile );
+
+    if ( Abc_NtkIsMappedLogic(pNtk) )
+    {
+        Abc_NtkMapToSop(pNtk);
+        printf( "The current network is unmapped before calling MVSIS.\n" );
+    }
+
+    // write out the current network
+    if ( Abc_NtkIsLogic(pNtk) )
+        Abc_NtkToSop(pNtk, 0);
+    pNetlist = Abc_NtkToNetlist(pNtk);
+    if ( pNetlist == NULL )
+    {
+        fprintf( pErr, "Cannot produce the intermediate network.\n" );
+        goto usage;
+    }
+    Io_WriteBlif( pNetlist, "_mvsis_in.blif", 1, 0, 0 );
+    Abc_NtkDelete( pNetlist );
+
+    // create the file for MVSIS
+    sprintf( Command, "%s -x -c ", pMvsisName );
+    strcat ( Command, "\"" );
+    strcat ( Command, "read_blif _mvsis_in.blif" );
+    strcat ( Command, "; " );
+    for ( i = 1; i < argc; i++ )
+    {
+        sprintf( Buffer, " %s", argv[i] );
+        strcat( Command, Buffer );
+    }
+    strcat( Command, "; " );
+    strcat( Command, "write_blif _mvsis_out.blif" );
+    strcat( Command, "\"" );
+
+    // call MVSIS
+    if ( Util_SignalSystem( Command ) )
+    {
+        fprintf( pErr, "The following command has returned non-zero exit status:\n" );
+        fprintf( pErr, "\"%s\"\n", Command );
+        unlink( "_mvsis_in.blif" );
+        goto usage;
+    }
+
+    // read in the MVSIS output
+    if ( (pFile = fopen( "_mvsis_out.blif", "r" )) == NULL )
+    {
+        fprintf( pErr, "Cannot open MVSIS output file \"%s\".\n", "_mvsis_out.blif" );
+        unlink( "_mvsis_in.blif" );
+        goto usage;
+    }
+    fclose( pFile );
+
+    // set the new network
+    pNtkNew = Io_Read( "_mvsis_out.blif", IO_FILE_BLIF, 1, 0 );
+    // set the original spec of the new network
+    if ( pNtk->pSpec )
+    {
+        ABC_FREE( pNtkNew->pSpec );
+        pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec );
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew );
+
+    // remove temporary networks
+    unlink( "_mvsis_in.blif" );
+    unlink( "_mvsis_out.blif" );
+    return 0;
+
+usage:
+    fprintf( pErr, "Usage: mvsis [-h] <com>\n");
+    fprintf( pErr, "         invokes MVSIS command for the current ABC network\n" );
+    fprintf( pErr, "         (the executable of MVSIS should be in the same directory)\n" );
+    fprintf( pErr, "   -h  : print the command usage\n" );
+    fprintf( pErr, " <com> : a MVSIS command (or a semicolon-separated list of commands in quotes)\n" );
+    fprintf( pErr, "         Example 1: mvsis fraig_sweep\n" );
+    fprintf( pErr, "         Example 2: mvsis \"ps; fxu; ps\"\n" );
+    fprintf( pErr, "         Example 3: mvsis source mvsis.rugged\n" );
+    return 1;                   // error exit
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes dimentions of the graph.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManGnuplotShow( char * pPlotFileName )
+{
+    FILE * pFile;
+    void * pAbc;
+    char * pProgNameGnuplotWin  = "wgnuplot.exe";
+    char * pProgNameGnuplotUnix = "gnuplot";
+    char * pProgNameGnuplot = NULL;
+
+    // read in the Capo plotting output
+    if ( (pFile = fopen( pPlotFileName, "r" )) == NULL )
+    {
+        fprintf( stdout, "Cannot open the plot file \"%s\".\n\n", pPlotFileName );
+        return;
+    }
+    fclose( pFile );
+
+    pAbc = Abc_FrameGetGlobalFrame();
+
+    // get the names from the plotting software
+    if ( Cmd_FlagReadByName((Abc_Frame_t *)pAbc, "gnuplotwin") )
+        pProgNameGnuplotWin = Cmd_FlagReadByName((Abc_Frame_t *)pAbc, "gnuplotwin");
+    if ( Cmd_FlagReadByName((Abc_Frame_t *)pAbc, "gnuplotunix") )
+        pProgNameGnuplotUnix = Cmd_FlagReadByName((Abc_Frame_t *)pAbc, "gnuplotunix");
+
+    // check if Gnuplot is available
+    if ( (pFile = fopen( pProgNameGnuplotWin, "r" )) )
+        pProgNameGnuplot = pProgNameGnuplotWin;
+    else if ( (pFile = fopen( pProgNameGnuplotUnix, "r" )) )
+        pProgNameGnuplot = pProgNameGnuplotUnix;
+    else if ( pFile == NULL )
+    {
+        fprintf( stdout, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pProgNameGnuplotWin, pProgNameGnuplotUnix );
+        return;
+    }
+    fclose( pFile );
+
+    // spawn the viewer
+#ifdef WIN32
+    if ( _spawnl( _P_NOWAIT, pProgNameGnuplot, pProgNameGnuplot, pPlotFileName, NULL ) == -1 )
+    {
+        fprintf( stdout, "Cannot find \"%s\".\n", pProgNameGnuplot );
+        return;
+    }
+#else
+    {
+        char Command[1000];
+        sprintf( Command, "%s %s ", pProgNameGnuplot, pPlotFileName );
+        if ( system( Command ) == -1 )
+        {
+            fprintf( stdout, "Cannot execute \"%s\".\n", Command );
+            return;
+        }
+    }
+#endif
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Calls Capo internally.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandCapo( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    FILE * pFile;
+    FILE * pOut, * pErr;
+    Abc_Ntk_t * pNtk, * pNetlist;
+    char Command[1000], Buffer[100];
+    char * pProgNameCapoWin     = "capo.exe";
+    char * pProgNameCapoUnix    = "capo";
+    char * pProgNameGnuplotWin  = "wgnuplot.exe";
+    char * pProgNameGnuplotUnix = "gnuplot";
+    char * pProgNameCapo;
+    char * pProgNameGnuplot;
+    char * pPlotFileName;
+    int i;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    if ( argc > 1 )
+    {
+        if ( strcmp( argv[1], "-h" ) == 0 )
+            goto usage;
+        if ( strcmp( argv[1], "-?" ) == 0 )
+            goto usage;
+    }
+
+    if ( pNtk == NULL )
+    {
+        fprintf( pErr, "Empty network.\n" );
+        goto usage;
+    }
+
+    if ( strcmp( argv[0], "capo" ) != 0 )
+    {
+        fprintf( pErr, "Wrong command: \"%s\".\n", argv[0] );
+        goto usage;
+    }
+
+    // get the names from the resource file
+    if ( Cmd_FlagReadByName(pAbc, "capowin") )
+        pProgNameCapoWin = Cmd_FlagReadByName(pAbc, "capowin");
+    if ( Cmd_FlagReadByName(pAbc, "capounix") )
+        pProgNameCapoUnix = Cmd_FlagReadByName(pAbc, "capounix");
+
+    // check if capo is available
+    if ( (pFile = fopen( pProgNameCapoWin, "r" )) )
+        pProgNameCapo = pProgNameCapoWin;
+    else if ( (pFile = fopen( pProgNameCapoUnix, "r" )) )
+        pProgNameCapo = pProgNameCapoUnix;
+    else if ( pFile == NULL )
+    {
+        fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pProgNameCapoWin, pProgNameCapoUnix );
+        goto usage;
+    }
+    fclose( pFile );
+
+    if ( Abc_NtkIsMappedLogic(pNtk) )
+    {
+        Abc_NtkMapToSop(pNtk);
+        printf( "The current network is unmapped before calling Capo.\n" );
+    }
+
+    // write out the current network
+    if ( Abc_NtkIsLogic(pNtk) )
+        Abc_NtkToSop(pNtk, 0);
+    pNetlist = Abc_NtkToNetlist(pNtk);
+    if ( pNetlist == NULL )
+    {
+        fprintf( pErr, "Cannot produce the intermediate network.\n" );
+        goto usage;
+    }
+    Io_WriteBlif( pNetlist, "_capo_in.blif", 1, 0, 0 );
+    Abc_NtkDelete( pNetlist );
+
+    // create the file for Capo
+    sprintf( Command, "%s -f _capo_in.blif -log out.txt ", pProgNameCapo );
+    pPlotFileName = NULL;
+    for ( i = 1; i < argc; i++ )
+    {
+        sprintf( Buffer, " %s", argv[i] );
+        strcat( Command, Buffer );
+        if ( !strcmp( argv[i], "-plot" ) )
+            pPlotFileName = argv[i+1];
+    }
+
+    // call Capo
+    if ( Util_SignalSystem( Command ) )
+    {
+        fprintf( pErr, "The following command has returned non-zero exit status:\n" );
+        fprintf( pErr, "\"%s\"\n", Command );
+        unlink( "_capo_in.blif" );
+        goto usage;
+    }
+    // remove temporary networks
+    unlink( "_capo_in.blif" );
+    if ( pPlotFileName == NULL )
+        return 0;
+
+    // get the file name
+    sprintf( Buffer, "%s.plt", pPlotFileName );
+    pPlotFileName = Buffer;
+
+    // read in the Capo plotting output
+    if ( (pFile = fopen( pPlotFileName, "r" )) == NULL )
+    {
+        fprintf( pErr, "Cannot open the plot file \"%s\".\n\n", pPlotFileName );
+        goto usage;
+    }
+    fclose( pFile );
+
+    // get the names from the plotting software
+    if ( Cmd_FlagReadByName(pAbc, "gnuplotwin") )
+        pProgNameGnuplotWin = Cmd_FlagReadByName(pAbc, "gnuplotwin");
+    if ( Cmd_FlagReadByName(pAbc, "gnuplotunix") )
+        pProgNameGnuplotUnix = Cmd_FlagReadByName(pAbc, "gnuplotunix");
+
+    // check if Gnuplot is available
+    if ( (pFile = fopen( pProgNameGnuplotWin, "r" )) )
+        pProgNameGnuplot = pProgNameGnuplotWin;
+    else if ( (pFile = fopen( pProgNameGnuplotUnix, "r" )) )
+        pProgNameGnuplot = pProgNameGnuplotUnix;
+    else if ( pFile == NULL )
+    {
+        fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pProgNameGnuplotWin, pProgNameGnuplotUnix );
+        goto usage;
+    }
+    fclose( pFile );
+
+    // spawn the viewer
+#ifdef WIN32
+    if ( _spawnl( _P_NOWAIT, pProgNameGnuplot, pProgNameGnuplot, pPlotFileName, NULL ) == -1 )
+    {
+        fprintf( stdout, "Cannot find \"%s\".\n", pProgNameGnuplot );
+        goto usage;
+    }
+#else
+    {
+        sprintf( Command, "%s %s ", pProgNameGnuplot, pPlotFileName );
+        if ( Util_SignalSystem( Command ) == -1 )
+        {
+            fprintf( stdout, "Cannot execute \"%s\".\n", Command );
+            goto usage;
+        }
+    }
+#endif
+
+    // remove temporary networks
+//    unlink( pPlotFileName );
+    return 0;
+
+usage:
+    fprintf( pErr, "Usage: capo [-h] <com>\n");
+    fprintf( pErr, "         peforms placement of the current network using Capo\n" );
+    fprintf( pErr, "         a Capo binary should be present in the same directory\n" );
+    fprintf( pErr, "         (if plotting, the Gnuplot binary should also be present)\n" );
+    fprintf( pErr, "   -h  : print the command usage\n" );
+    fprintf( pErr, " <com> : a Capo command\n" );
+    fprintf( pErr, "         Example 1: capo\n" );
+    fprintf( pErr, "                    (performs placement with default options)\n" );
+    fprintf( pErr, "         Example 2: capo -AR <aspec_ratio> -WS <whitespace_percentage> -save\n" );
+    fprintf( pErr, "                    (specifies the aspect ratio [default = 1.0] and\n" );
+    fprintf( pErr, "                    the whitespace percentage [0%%; 100%%) [default = 15%%])\n" );
+    fprintf( pErr, "         Example 3: capo -plot <base_fileName>\n" );
+    fprintf( pErr, "                    (produces <base_fileName.plt> and visualize it using Gnuplot)\n" );
+    fprintf( pErr, "         Example 4: capo -help\n" );
+    fprintf( pErr, "                    (prints the default usage message of the Capo binary)\n" );
+    fprintf( pErr, "         Please refer to the Capo webpage for additional information:\n" );
+    fprintf( pErr, "         http://vlsicad.eecs.umich.edu/BK/PDtools/\n" );
+    return 1;                   // error exit
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int CmdCommandStarter( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores );
+    FILE * pFile;
+    char * pFileName;
+    char * pCommand = NULL;
+    int c, nCores    =  3;
+    int fVerbose     =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "NCvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+                goto usage;
+            }
+            nCores = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nCores < 0 ) 
+                goto usage;
+            break;
+        case 'C':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-C\" should be followed by a string (possibly in quotes).\n" );
+                goto usage;
+            }
+            pCommand = argv[globalUtilOptind];
+            globalUtilOptind++;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+    {
+        Abc_Print( -2, "The file name should be given on the command line.\n" );
+        return 1;
+    }
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    if ( (pFile = Io_FileOpen( pFileName, "open_path", "rb", 0 )) == NULL )
+//    if ( (pFile = fopen( pFileName, "rb" )) == NULL )
+    {
+        Abc_Print( -2, "Cannot open input file \"%s\". ", pFileName );
+        if (( pFileName = Extra_FileGetSimilarName( pFileName, ".c", ".s", ".scr", ".script", NULL ) ))
+            Abc_Print( -2, "Did you mean \"%s\"?", pFileName );
+        Abc_Print( -2, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+    // run commands
+    Cmd_RunStarter( pFileName, pAbc->sBinary, pCommand, nCores );
+    return 0;
+
+usage:
+    Abc_Print( -2, "usage: starter [-N num] [-C cmd] [-vh] <file>\n" );
+    Abc_Print( -2, "\t         runs command lines listed in <file> concurrently on <num> CPUs\n" );
+    Abc_Print( -2, "\t-N num : the number of concurrent jobs including the controler [default = %d]\n", nCores );
+    Abc_Print( -2, "\t-C cmd : (optional) ABC command line to execute on benchmarks in <file>\n" );
+    Abc_Print( -2, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    Abc_Print( -2, "\t-h     : print the command usage\n");
+    Abc_Print( -2, "\t<file> : file name with ABC command lines (or benchmark names, if <cmd> is given)\n");
+    return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print the version string.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandVersion( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+
+    printf("%s\n", Abc_UtilsGetVersion(pAbc));
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: version [-h]\n" );
+    fprintf( pAbc->Err, "         print the version string\n" );
+    fprintf( pAbc->Err, "   -h :  print the command usage\n");
+    return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/base/cmd/cmd.h b/abc-build/src/base/cmd/cmd.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/cmd/cmd.h
@@ -0,0 +1,80 @@
+/**CFile****************************************************************
+
+  FileName    [cmd.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [External declarations of the command package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cmd.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__base__cmd__cmd_h
+#define ABC__base__cmd__cmd_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct MvCommand    Abc_Command;  // one command
+typedef struct MvAlias      Abc_Alias;    // one alias
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== cmd.c ===========================================================*/
+extern void        Cmd_Init( Abc_Frame_t * pAbc );
+extern void        Cmd_End( Abc_Frame_t * pAbc );
+/*=== cmdApi.c ========================================================*/
+typedef int (*Cmd_CommandFuncType)(Abc_Frame_t*, int, char**);
+extern void        Cmd_CommandAdd( Abc_Frame_t * pAbc, const char * sGroup, const char * sName, Cmd_CommandFuncType pFunc, int fChanges );
+extern ABC_DLL int Cmd_CommandExecute( Abc_Frame_t * pAbc, const char * sCommand );
+/*=== cmdFlag.c ========================================================*/
+extern char *      Cmd_FlagReadByName( Abc_Frame_t * pAbc, char * flag );
+extern void        Cmd_FlagDeleteByName( Abc_Frame_t * pAbc, const char * key );
+extern void        Cmd_FlagUpdateValue( Abc_Frame_t * pAbc, const char * key, char * value );
+/*=== cmdHist.c ========================================================*/
+extern void   	   Cmd_HistoryAddCommand( Abc_Frame_t * pAbc, const char * command );
+extern void        Cmd_HistoryRead( Abc_Frame_t * p );
+extern void        Cmd_HistoryWrite( Abc_Frame_t * p, int Limit );
+extern void        Cmd_HistoryPrint( Abc_Frame_t * p, int Limit );
+/*=== cmdLoad.c ========================================================*/
+extern int         CmdCommandLoad( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/base/cmd/cmdAlias.c b/abc-build/src/base/cmd/cmdAlias.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/cmd/cmdAlias.c
@@ -0,0 +1,126 @@
+/**CFile****************************************************************
+
+  FileName    [cmdAlias.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures dealing with aliases in the command package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cmdAlias.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "cmdInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void CmdCommandAliasAdd( Abc_Frame_t * pAbc, char * sName, int argc, char ** argv )
+{
+    Abc_Alias * pAlias;
+    int fStatus, i;
+
+    pAlias = ABC_ALLOC(Abc_Alias, 1);
+    pAlias->sName = Extra_UtilStrsav(sName);
+    pAlias->argc = argc;
+    pAlias->argv = ABC_ALLOC(char *, pAlias->argc);
+    for(i = 0; i < argc; i++) 
+        pAlias->argv[i] = Extra_UtilStrsav(argv[i]);
+    fStatus = st__insert( pAbc->tAliases, pAlias->sName, (char *) pAlias );
+    assert(!fStatus);  
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void CmdCommandAliasPrint( Abc_Frame_t * pAbc, Abc_Alias * pAlias )
+{
+    int i;
+    fprintf(pAbc->Out, "%-15s", pAlias->sName);
+    for(i = 0; i < pAlias->argc; i++) 
+        fprintf( pAbc->Out, " %s", pAlias->argv[i] );
+    fprintf( pAbc->Out, "\n" );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+char * CmdCommandAliasLookup( Abc_Frame_t * pAbc, char * sCommand )
+{
+  Abc_Alias * pAlias;
+  char * value;
+  if (! st__lookup( pAbc->tAliases, sCommand, &value)) 
+    return sCommand;
+  pAlias = (Abc_Alias *) value;
+  return pAlias->argv[0];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void CmdCommandAliasFree( Abc_Alias * pAlias )
+{
+    CmdFreeArgv( pAlias->argc, pAlias->argv );
+    ABC_FREE(pAlias->sName);    
+    ABC_FREE(pAlias);
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/cmd/cmdApi.c b/abc-build/src/base/cmd/cmdApi.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/cmd/cmdApi.c
@@ -0,0 +1,111 @@
+/**CFile****************************************************************
+
+  FileName    [cmdApi.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [External procedures of the command package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cmdApi.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/mainInt.h"
+#include "cmdInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cmd_CommandAdd( Abc_Frame_t * pAbc, const char * sGroup, const char * sName, Cmd_CommandFuncType pFunc, int fChanges )
+{
+    const char * key;
+    char * value;
+    Abc_Command * pCommand;
+    int fStatus;
+
+    key = sName;
+    if ( st__delete( pAbc->tCommands, &key, &value ) ) 
+    {
+        // delete existing definition for this command 
+        fprintf( pAbc->Err, "Cmd warning: redefining '%s'\n", sName );
+        CmdCommandFree( (Abc_Command *)value );
+    }
+
+    // create the new command
+    pCommand = ABC_ALLOC( Abc_Command, 1 );
+    pCommand->sName   = Extra_UtilStrsav( sName );
+    pCommand->sGroup  = Extra_UtilStrsav( sGroup );
+    pCommand->pFunc   = pFunc;
+    pCommand->fChange = fChanges;
+    fStatus = st__insert( pAbc->tCommands, pCommand->sName, (char *)pCommand );
+    assert( !fStatus );  // the command should not be in the table
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cmd_CommandExecute( Abc_Frame_t * pAbc, const char * sCommand )
+{
+    int fStatus = 0, argc, loop;
+    const char * sCommandNext;
+    char **argv;
+
+    if ( !pAbc->fAutoexac && !pAbc->fSource ) 
+	    Cmd_HistoryAddCommand(pAbc, sCommand);
+    sCommandNext = sCommand;
+    do 
+    {
+       	sCommandNext = CmdSplitLine( pAbc, sCommandNext, &argc, &argv );
+		loop = 0;
+		fStatus = CmdApplyAlias( pAbc, &argc, &argv, &loop );
+		if ( fStatus == 0 ) 
+			fStatus = CmdCommandDispatch( pAbc, &argc, &argv );
+       	CmdFreeArgv( argc, argv );
+    } 
+    while ( fStatus == 0 && *sCommandNext != '\0' );
+    return fStatus;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/cmd/cmdFlag.c b/abc-build/src/base/cmd/cmdFlag.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/cmd/cmdFlag.c
@@ -0,0 +1,110 @@
+/**CFile****************************************************************
+
+  FileName    [cmdFlag.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures working with flags.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cmdFlag.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/mainInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**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 NULL is returned if the flag has not been set.]
+
+  SideEffects []
+
+******************************************************************************/
+char * Cmd_FlagReadByName( Abc_Frame_t * pAbc, char * flag )
+{
+    char * value;
+    if ( st__lookup(pAbc->tFlags, flag, &value) )
+        return value;
+    return NULL;
+}
+
+
+/**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( Abc_Frame_t * pAbc, const char * key, char * value )
+{
+    char * oldValue, * newValue;
+    if ( !key )
+        return;
+    if ( value )
+        newValue = Extra_UtilStrsav(value);
+    else
+        newValue = Extra_UtilStrsav("");
+//        newValue = NULL;
+    if ( st__delete(pAbc->tFlags, &key, &oldValue) )
+        ABC_FREE(oldValue);
+    st__insert( pAbc->tFlags, 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( Abc_Frame_t * pAbc, const char * key )
+{
+    char *value;
+    if ( !key )
+        return;
+    if ( st__delete( pAbc->tFlags, &key, &value ) ) 
+    {
+        ABC_FREE(key);
+        ABC_FREE(value);
+    }
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/cmd/cmdHist.c b/abc-build/src/base/cmd/cmdHist.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/cmd/cmdHist.c
@@ -0,0 +1,176 @@
+/**CFile****************************************************************
+
+  FileName    [cmdHist.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures working with history.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cmdHist.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/mainInt.h"
+#include "cmd.h"
+#include "cmdInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cmd_HistoryAddCommand(	Abc_Frame_t * p, const char * command )
+{
+    int nLastLooked =   10;  // do not add history if the same entry appears among the last entries
+    int nLastSaved  = 1000;  // when saving a file, save no more than this number of last entries
+    char Buffer[ABC_MAX_STR];
+    int Len;
+    if ( p->fBatchMode )
+        return;
+    Len = strlen(command);
+    strcpy( Buffer, command );
+    if ( Buffer[Len-1] == '\n' )
+        Buffer[Len-1] = 0;
+    if ( strlen(Buffer) > 3 &&
+         strncmp(Buffer,"set",3) && 
+         strncmp(Buffer,"time",4) && 
+         strncmp(Buffer,"quit",4) && 
+         strncmp(Buffer,"source",6) && 
+         strncmp(Buffer,"history",7) && strncmp(Buffer,"hi ", 3) && strcmp(Buffer,"hi") &&
+         Buffer[strlen(Buffer)-1] != '?' )
+    {
+        char * pStr = NULL;
+        int i, Start = Abc_MaxInt( 0, Vec_PtrSize(p->aHistory) - nLastLooked );
+        // do not enter if the same command appears among nLastLooked commands
+        Vec_PtrForEachEntryStart( char *, p->aHistory, pStr, i, Start )
+            if ( !strcmp(pStr, Buffer) )
+                break;
+        if ( i == Vec_PtrSize(p->aHistory) )
+        { // add new entry
+            Vec_PtrPush( p->aHistory, Extra_UtilStrsav(Buffer) );
+            Cmd_HistoryWrite( p, nLastSaved );
+        }
+        else
+        { // put at the end
+            Vec_PtrRemove( p->aHistory, pStr );
+            Vec_PtrPush( p->aHistory, pStr );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cmd_HistoryRead( Abc_Frame_t * p )
+{
+#if defined(WIN32) 
+    char Buffer[ABC_MAX_STR];
+    FILE * pFile;
+    assert( Vec_PtrSize(p->aHistory) == 0 );
+    pFile = fopen( "abc.history", "rb" );
+    if ( pFile == NULL )
+        return;
+    while ( fgets( Buffer, ABC_MAX_STR, pFile ) != NULL )
+    {
+        int Len = strlen(Buffer);
+        if ( Buffer[Len-1] == '\n' )
+            Buffer[Len-1] = 0;
+        Vec_PtrPush( p->aHistory, Extra_UtilStrsav(Buffer) );
+    }
+    fclose( pFile );
+#endif
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cmd_HistoryWrite( Abc_Frame_t * p, int Limit )
+{
+#if defined(WIN32) 
+    FILE * pFile;
+    char * pStr; 
+    int i;
+    pFile = fopen( "abc.history", "wb" );
+    if ( pFile == NULL )
+    {
+        Abc_Print( 0, "Cannot open file \"abc.history\" for writing.\n" );
+        return;
+    }
+    Limit = Abc_MaxInt( 0, Vec_PtrSize(p->aHistory)-Limit );
+    Vec_PtrForEachEntryStart( char *, p->aHistory, pStr, i, Limit )
+        fprintf( pFile, "%s\n", pStr );
+    fclose( pFile );
+#endif
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cmd_HistoryPrint( Abc_Frame_t * p, int Limit )
+{
+#if defined(WIN32) 
+    char * pStr; 
+    int i;
+    Limit = Abc_MaxInt( 0, Vec_PtrSize(p->aHistory)-Limit );
+    printf( "================== Command history ==================\n" );
+    Vec_PtrForEachEntryStart( char *, p->aHistory, pStr, i, Limit )
+        printf( "%s\n", pStr );
+    printf( "=====================================================\n" );
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/cmd/cmdInt.h b/abc-build/src/base/cmd/cmdInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/cmd/cmdInt.h
@@ -0,0 +1,92 @@
+/**CFile****************************************************************
+
+  FileName    [cmdInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Internal declarations of the command package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cmdInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__base__cmd__cmdInt_h
+#define ABC__base__cmd__cmdInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "base/main/mainInt.h"
+#include "cmd.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+struct MvCommand
+{
+    char *        sName;       // the command name  
+    char *        sGroup;      // the group name  
+    Cmd_CommandFuncType        pFunc;       // the function to execute the command
+    int           fChange;     // set to 1 to mark that the network is changed
+};
+
+struct MvAlias
+{
+    char *        sName;       // the alias name
+    int           argc;        // the number of alias parts
+    char **       argv;        // the alias parts
+};
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                        ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== cmdAlias.c =============-========================================*/
+extern void       CmdCommandAliasAdd( Abc_Frame_t * pAbc, char * sName, int argc, char ** argv );
+extern void       CmdCommandAliasPrint( Abc_Frame_t * pAbc, Abc_Alias * pAlias );
+extern char *     CmdCommandAliasLookup( Abc_Frame_t * pAbc, char * sCommand );
+extern void       CmdCommandAliasFree( Abc_Alias * p );
+/*=== cmdUtils.c =======================================================*/
+extern int        CmdCommandDispatch( Abc_Frame_t * pAbc, int * argc, char *** argv );
+extern const char *     CmdSplitLine( Abc_Frame_t * pAbc, const char * sCommand, int * argc, char *** argv );
+extern int        CmdApplyAlias( Abc_Frame_t * pAbc, int * argc, char *** argv, int * loop );
+extern char *     CmdHistorySubstitution( Abc_Frame_t * pAbc, char * line, int * changed );
+extern FILE *     CmdFileOpen( Abc_Frame_t * pAbc, char * sFileName, char * sMode, char ** pFileNameReal, int silent );
+extern void       CmdFreeArgv( int argc, char ** argv );
+extern char **    CmdAddToArgv( int argc, char ** argv );
+extern void       CmdCommandFree( Abc_Command * pCommand );
+extern void       CmdCommandPrint( Abc_Frame_t * pAbc, int fPrintAll, int fDetails );
+extern void       CmdPrintTable( st__table * tTable, int fAliases );
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
diff --git a/abc-build/src/base/cmd/cmdLoad.c b/abc-build/src/base/cmd/cmdLoad.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/cmd/cmdLoad.c
@@ -0,0 +1,228 @@
+/**CFile****************************************************************
+
+  FileName    [cmdApi.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [External procedures of the command package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cmdApi.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/mainInt.h"
+#include "cmd.h"
+#include "cmdInt.h"
+#include "misc/util/utilSignal.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int CmdCommandLoad( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Vec_Str_t * vCommand;
+    FILE * pFile;
+    int i;
+    vCommand = Vec_StrAlloc( 100 );
+    Vec_StrAppend( vCommand, "abccmd_" );
+    Vec_StrAppend( vCommand, argv[0] );
+    Vec_StrAppend( vCommand, ".exe" );
+    Vec_StrPush( vCommand, 0 );
+    // check if there is the binary
+    if ( (pFile = fopen( Vec_StrArray(vCommand), "r" )) == NULL )
+    {
+        Vec_StrFree( vCommand );
+        Abc_Print( -1, "Cannot run the binary \"%s\".\n\n", Vec_StrArray(vCommand) );
+        return 1;
+    }
+    fclose( pFile );
+    Vec_StrPop( vCommand );
+    // add other arguments
+    for ( i = 1; i < argc; i++ )
+    {
+        Vec_StrAppend( vCommand, " " );
+        Vec_StrAppend( vCommand, argv[i] );
+    }
+    Vec_StrPush( vCommand, 0 );
+    // run the command line
+    if ( Util_SignalSystem( Vec_StrArray(vCommand) ) )
+    {
+        Vec_StrFree( vCommand );
+        Abc_Print( -1, "The following command has returned non-zero exit status:\n" );
+        Abc_Print( -1, "\"%s\"\n", Vec_StrArray(vCommand) );
+        return 1;
+    }
+    Vec_StrFree( vCommand );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+#if defined(WIN32) && !defined(__cplusplus)
+
+#include <direct.h>
+
+
+// these structures are defined in <io.h> but are for some reason invisible
+typedef unsigned long _fsize_t; // Could be 64 bits for Win32
+
+struct _finddata_t {
+    unsigned    attrib;
+    time_t      time_create;    // -1 for FAT file systems 
+    time_t      time_access;    // -1 for FAT file systems 
+    time_t      time_write;
+    _fsize_t    size;
+    char        name[260];
+};
+
+extern long _findfirst( char *filespec, struct _finddata_t *fileinfo );
+extern int  _findnext( long handle, struct _finddata_t *fileinfo );
+extern int  _findclose( long handle );
+
+//extern char * _getcwd( char * buffer, int maxlen );
+//extern int    _chdir( const char *dirname );
+
+/**Function*************************************************************
+
+  Synopsis    [Collect file names ending with .exe]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * CmdCollectFileNames()
+{
+    Vec_Ptr_t * vFileNames;
+	struct _finddata_t c_file;
+	long   hFile;
+	if( (hFile = _findfirst( "*.exe", &c_file )) == -1L )
+	{
+//    	Abc_Print( 0, "No files with extention \"%s\" in the current directory.\n", "exe" );
+        return NULL;
+	}
+    vFileNames = Vec_PtrAlloc( 100 );
+    do {
+        Vec_PtrPush( vFileNames, Extra_UtilStrsav( c_file.name ) );
+    } while( _findnext( hFile, &c_file ) == 0 );
+	_findclose( hFile );
+    return vFileNames;
+}
+
+#else 
+
+/**Function*************************************************************
+
+  Synopsis    [Collect file names ending with .exe]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * CmdCollectFileNames()
+{
+    return NULL;
+}
+
+#endif
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Load_Init( Abc_Frame_t * pAbc )
+{
+    Vec_Ptr_t * vFileNames;
+    char * pName, * pStop;
+    int i;
+    vFileNames = CmdCollectFileNames();
+    if ( vFileNames == NULL )
+        return;
+    Vec_PtrForEachEntry( char *, vFileNames, pName, i )
+    {
+        if ( strncmp( pName, "abccmd_", 7 ) )
+            continue;
+        // get the command name
+//        pName[6] = '!';
+        pStop = strstr( pName + 7, "." );
+        if ( pStop )
+            *pStop = 0;
+        // add the command
+        Cmd_CommandAdd( pAbc, "ZZ", pName+7, CmdCommandLoad, 0 );
+//        printf( "Loaded command \"%s\"\n", pName+7 );
+    }
+    Vec_PtrFreeFree( vFileNames );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Load_End( Abc_Frame_t * pAbc )
+{
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/cmd/cmdPlugin.c b/abc-build/src/base/cmd/cmdPlugin.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/cmd/cmdPlugin.c
@@ -0,0 +1,731 @@
+/**CFile****************************************************************
+
+  FileName    [cmdPlugin.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Integrating external binary.]
+
+  Author      [Alan Mishchenko, Niklas Een]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 29, 2010.]
+
+  Revision    [$Id: cmdPlugin.c,v 1.00 2010/09/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifdef WIN32
+#include <io.h> 
+#include <process.h> 
+#else
+#include <unistd.h>
+#endif
+
+#include "base/abc/abc.h"
+#include "base/main/mainInt.h"
+#include "cmd.h"
+#include "cmdInt.h"
+#include "misc/util/utilSignal.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+/*
+
+-------- Original Message --------
+Subject: 	ABC/ZZ integration
+Date: 	Wed, 29 Sep 2010 00:34:32 -0700
+From: 	Niklas Een <niklas@een.se>
+To: 	Alan Mishchenko <alanmi@EECS.Berkeley.EDU>
+
+Hi Alan,
+
+Since the interface is file-based, it is important that we generate 
+good, unique filenames (we may run multiple instances of ABC in the 
+same directory), so I have attached some portable code for doing that 
+(tmpFile.c). You can integrate it appropriately.
+
+This is how my interface is meant to work:
+
+(1) As part of your call to Bip, give it first argument "-abc". 
+    This will alter Bip's behavior slightly.
+
+(2) To list the commands, call 'bip -list-commands'. 
+    My commands begin with a comma (so that's my prefix).
+
+(3) All commands expect an input file and an output file. 
+    The input file should be in AIGER format. 
+    The output will be a text file. 
+    Example:
+       bip -input=tmp.aig -output=tmp.out ,pdr -check -prop=5
+
+    So you just auto-generate the two temporary files (output file is 
+    closed and left empty) and stitch the ABC command line at the end. 
+    All you need to check for is if the ABC line begins with a comma.
+
+(4) The result written to the output file will contain a number 
+    of object. Each object is on a separate line of the form:
+
+    <object name>: <object data>
+
+That is: name, colon, space, data, newline. If you see a name you don't 
+recognize, just skip that line (so you will ignore future extensions by me). 
+I currently define the following objects:
+
+    result:
+    counter-example:
+    proof-invariant:
+    bug-free-depth:
+    abstraction:
+  
+"result:" is one of "proved", "failed", "undetermined" (=reached resource limit), "error" 
+(only used by the abstraction command, and only if resource limit was so tight that the 
+abstraction was still empty -- no abstraction is returned in this special case).
+
+"counter-example:" -- same format as before
+
+"proof-invariant:" contains an text-encoded single-output AIG. If you want 
+you can parse it and validate the invariant.
+
+"bug-free-depth:" the depth up to which the procedure has checked for counter-example. 
+Starts at -1 (not even the initial states have been verified).
+
+"abstraction:" -- same format as before
+
+(5) I propose that you add a command "load_plugin <path/binary>". That way Bob can put 
+Bip where ever he likes and just modify his abc_rc file.
+
+The intention is that ABC can read this file and act on it without knowing what 
+particular command was used. If there is an abstraction, you will always apply it. 
+If there is a "bug-free-depth" you will store that data somewhere so that Bob can query 
+it through the Python interface, and so on. If we need different actions for different 
+command, then we add a new object for the new action.
+
+// N.
+
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_GetBinaryName( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char * pTemp;
+    int i;
+    Vec_PtrForEachEntry( char *, pAbc->vPlugInComBinPairs, pTemp, i )
+    {
+        i++;
+        if ( strcmp( pTemp, argv[0] ) == 0 )
+            return (char *)Vec_PtrEntry( pAbc->vPlugInComBinPairs, i );
+    }
+    assert( 0 );
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read flop map.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Abc_ManReadFile( char * pFileName )
+{
+    FILE * pFile;
+    Vec_Str_t * vStr;
+    int c;
+    pFile = fopen( pFileName, "r" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\".\n", pFileName );
+        return NULL;
+    }
+    vStr = Vec_StrAlloc( 100 );
+    while ( (c = fgetc(pFile)) != EOF )
+        Vec_StrPush( vStr, (char)c );
+    Vec_StrPush( vStr, '\0' );
+    fclose( pFile );
+    return vStr;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read flop map.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_ManReadBinary( char * pFileName, char * pToken )
+{
+    Vec_Int_t * vMap = NULL;
+    Vec_Str_t * vStr;
+    char * pStr;
+    int i, Length;
+    vStr = Abc_ManReadFile( pFileName );
+    if ( vStr == NULL )
+        return NULL;
+    pStr = Vec_StrArray( vStr );
+    pStr = strstr( pStr, pToken );
+    if ( pStr != NULL )
+    {
+        pStr  += strlen( pToken );
+        vMap   = Vec_IntAlloc( 100 );
+        Length = strlen( pStr );
+        for ( i = 0; i < Length; i++ )
+        {
+            if ( pStr[i] == '0' || pStr[i] == '?' )
+                Vec_IntPush( vMap, 0 );
+            else if ( pStr[i] == '1' )
+                Vec_IntPush( vMap, 1 );
+            if ( ('a' <= pStr[i] && pStr[i] <= 'z') || 
+                 ('A' <= pStr[i] && pStr[i] <= 'Z') )
+                break;
+        }
+    }
+    Vec_StrFree( vStr );
+    return vMap;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read flop map.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ManReadInteger( char * pFileName, char * pToken )
+{
+    int Result = -1;
+    Vec_Str_t * vStr;
+    char * pStr;
+    vStr = Abc_ManReadFile( pFileName );
+    if ( vStr == NULL )
+        return -1;
+    pStr = Vec_StrArray( vStr );
+    pStr = strstr( pStr, pToken );
+    if ( pStr != NULL )
+        Result = atoi( pStr + strlen(pToken) );
+    Vec_StrFree( vStr );
+    return Result;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read flop map.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ManReadStatus( char * pFileName, char * pToken )
+{
+    int Result = -1;
+    Vec_Str_t * vStr;
+    char * pStr;
+    vStr = Abc_ManReadFile( pFileName );
+    if ( vStr == NULL )
+        return -1;
+    pStr = Vec_StrArray( vStr );
+    pStr = strstr( pStr, pToken );
+    if ( pStr != NULL )
+    {
+        if ( strncmp(pStr+8, "proved", 6) == 0 )
+            Result = 1; 
+        else if ( strncmp(pStr+8, "failed", 6) == 0 )
+            Result = 0; 
+    }
+    Vec_StrFree( vStr );
+    return Result;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Work-around to insert 0s for PIs without fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_ManExpandCex( Gia_Man_t * pGia, Vec_Int_t * vCex )
+{
+    Vec_Int_t * vCexNew;
+    Gia_Obj_t * pObj;
+    int i, k;
+
+    // start with register outputs
+    vCexNew = Vec_IntAlloc( Vec_IntSize(vCex) );
+    Gia_ManForEachRo( pGia, pObj, i )
+        Vec_IntPush( vCexNew, 0 );
+
+    ABC_FREE( pGia->pRefs );
+    Gia_ManCreateRefs( pGia );
+    k = Gia_ManRegNum( pGia );
+    while ( 1 )
+    {
+        Gia_ManForEachPi( pGia, pObj, i )
+        {
+            if ( Gia_ObjRefNum(pGia, pObj) == 0 )
+                Vec_IntPush( vCexNew, 0 );
+            else
+            {
+                if ( k == Vec_IntSize(vCex) )
+                    break;
+                Vec_IntPush( vCexNew, Vec_IntEntry(vCex, k++) );
+            }
+        }
+        if ( k == Vec_IntSize(vCex) )
+            break;
+    }
+    return vCexNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure to convert the AIG from text into binary form.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static unsigned textToBin(char* text, unsigned long text_sz)
+{
+    char*       dst = text;
+    const char* src = text;
+    unsigned sz, i;
+    sscanf(src, "%u ", &sz);
+    while(*src++ != ' ');
+    for ( i = 0; i < sz; i += 3 )
+    {
+        dst[0] = (char)( (unsigned)src[0] - '0')       | (((unsigned)src[1] - '0') << 6);
+        dst[1] = (char)(((unsigned)src[1] - '0') >> 2) | (((unsigned)src[2] - '0') << 4);
+        dst[2] = (char)(((unsigned)src[2] - '0') >> 4) | (((unsigned)src[3] - '0') << 2);
+        src += 4;
+        dst += 3;
+    }
+    return sz;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives AIG from the text string in the file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Abc_ManReadAig( char * pFileName, char * pToken )
+{
+    Gia_Man_t * pGia = NULL;
+    unsigned nBinaryPart;
+    Vec_Str_t * vStr;
+    char * pStr, * pEnd;
+    vStr = Abc_ManReadFile( pFileName );
+    if ( vStr == NULL )
+        return NULL;
+    pStr = Vec_StrArray( vStr );
+    pStr = strstr( pStr, pToken );
+    if ( pStr != NULL )
+    {
+        // skip token
+        pStr += strlen(pToken);
+        // skip spaces
+        while ( *pStr == ' ' )
+            pStr++;
+        // set the end at newline
+        for ( pEnd = pStr; *pEnd; pEnd++ )
+            if ( *pEnd == '\r' || *pEnd == '\n' )
+            {
+                *pEnd = 0;
+                break;
+            }
+        // convert into binary AIGER
+        nBinaryPart = textToBin( pStr, strlen(pStr) );
+        // dump it into file
+        if ( 0 )
+        {
+            FILE * pFile = fopen( "test.aig", "wb" );
+            fwrite( pStr, 1, nBinaryPart, pFile );
+            fclose( pFile );
+        }
+        // derive AIG
+        pGia = Gia_AigerReadFromMemory( pStr, nBinaryPart, 0, 0 ); 
+    }
+    Vec_StrFree( vStr );
+    return pGia;
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cmd_CommandAbcPlugIn( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char * pFileIn, * pFileOut;
+    char * pFileNameBinary;
+    Vec_Str_t * vCommand;
+    Vec_Int_t * vCex;
+    FILE * pFile;
+    Gia_Man_t * pGia;
+    int i, fd;
+    abctime clk;
+    int fLeaveFiles;
+/*
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Current network does not exist\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsStrash( pNtk) )
+    {
+        Abc_Print( -1, "The current network is not an AIG. Cannot continue.\n" );
+        return 1;
+    }
+*/
+
+    if ( pAbc->pGia == NULL )
+    {
+        if (argc == 2 && strcmp(argv[1], "-h") == 0)
+        {
+            // Run command to produce help string:
+            vCommand = Vec_StrAlloc( 100 );
+            pFileNameBinary = Abc_GetBinaryName( pAbc, argc, argv );
+            Vec_StrAppend( vCommand, pFileNameBinary );
+            Vec_StrAppend( vCommand, " -abc " );
+            Vec_StrAppend( vCommand, argv[0] );
+            Vec_StrAppend( vCommand, " -h" );
+            Vec_StrPush( vCommand, 0 );
+            Util_SignalSystem( Vec_StrArray(vCommand) );
+            Vec_StrFree( vCommand );
+        }
+        else
+        {
+            Abc_Print( -1, "Current AIG does not exist (try command &ps).\n" );
+        }
+        return 1;
+    }
+
+    // check if there is the binary
+    pFileNameBinary = Abc_GetBinaryName( pAbc, argc, argv );
+    if ( (pFile = fopen( pFileNameBinary, "r" )) == NULL )
+    {
+        Abc_Print( -1, "Cannot run the binary \"%s\".\n\n", pFileNameBinary );
+        return 1;
+    }
+    fclose( pFile );
+
+    // create temp file
+    fd = Util_SignalTmpFile( "__abctmp_", ".aig", &pFileIn );
+    if ( fd == -1 )
+    {
+        Abc_Print( -1, "Cannot create a temporary file.\n" );
+        return 1;
+    }
+#ifdef WIN32
+    _close( fd );
+#else
+    close( fd );
+#endif
+
+    // create temp file
+    fd = Util_SignalTmpFile( "__abctmp_", ".out", &pFileOut );
+    if ( fd == -1 )
+    {
+        ABC_FREE( pFileIn );
+        Abc_Print( -1, "Cannot create a temporary file.\n" );
+        return 1;
+    }
+#ifdef WIN32
+    _close( fd );
+#else
+    close( fd );
+#endif
+
+
+    // write current network into a file
+/*
+    {
+        extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+        Aig_Man_t * pAig;
+        pAig = Abc_NtkToDar( pNtk, 0, 1 );
+        Ioa_WriteAiger( pAig, pFileIn, 0, 0 );
+        Aig_ManStop( pAig );
+    }
+*/ 
+    // check what to do with the files
+    fLeaveFiles = 0;
+    if ( strcmp( argv[argc-1], "!" ) == 0 )
+    {
+        Abc_Print( 0, "Input file \"%s\" and output file \"%s\" are not deleted.\n", pFileIn, pFileOut );
+        fLeaveFiles = 1;
+        argc--;
+    }
+
+    // create input file
+    Gia_AigerWrite( pAbc->pGia, pFileIn, 0, 0 );
+
+    // create command line
+    vCommand = Vec_StrAlloc( 100 );
+    Vec_StrAppend( vCommand, pFileNameBinary );
+    // add input/output file
+    Vec_StrAppend( vCommand, " -abc" );
+//    Vec_StrAppend( vCommand, " -input=C:/_projects/abc/_TEST/hwmcc/139442p0.aig" );
+    Vec_StrAppend( vCommand, " -input=" );
+    Vec_StrAppend( vCommand, pFileIn );
+    Vec_StrAppend( vCommand, " -output=" );
+    Vec_StrAppend( vCommand, pFileOut );
+    // add other arguments
+    for ( i = 0; i < argc; i++ )
+    {
+        Vec_StrAppend( vCommand, " " );
+        Vec_StrAppend( vCommand, argv[i] );
+    }
+    Vec_StrPush( vCommand, 0 );
+
+    // run the command line
+//printf( "Running command line: %s\n", Vec_StrArray(vCommand) ); 
+
+    clk = Abc_Clock();
+    if ( Util_SignalSystem( Vec_StrArray(vCommand) ) )
+    {
+        Abc_Print( -1, "The following command has returned non-zero exit status:\n" );
+        Abc_Print( -1, "\"%s\"\n", Vec_StrArray(vCommand) );
+        return 1;
+    }
+    clk = Abc_Clock() - clk;
+    Vec_StrFree( vCommand );
+
+    // check if the output file exists
+    if ( (pFile = fopen( pFileOut, "r" )) == NULL )
+    {
+        Abc_Print( -1, "There is no output file \"%s\".\n", pFileOut );
+        return 1;
+    }
+    fclose( pFile );
+
+    // process the output
+    if ( Extra_FileSize(pFileOut) > 0 )
+    {
+        // get status
+        pAbc->Status  = Abc_ManReadStatus( pFileOut, "result:" );
+        // get bug-free depth
+        pAbc->nFrames = Abc_ManReadInteger( pFileOut, "bug-free-depth:" );
+        // get abstraction
+        pAbc->pGia->vFlopClasses = Abc_ManReadBinary( pFileOut, "abstraction:" );
+        // get counter-example
+        vCex = Abc_ManReadBinary( pFileOut, "counter-example:" );
+        if ( vCex ) 
+        {
+            int nFrames, nRemain;
+
+            nFrames = (Vec_IntSize(vCex) - Gia_ManRegNum(pAbc->pGia)) / Gia_ManPiNum(pAbc->pGia);
+            nRemain = (Vec_IntSize(vCex) - Gia_ManRegNum(pAbc->pGia)) % Gia_ManPiNum(pAbc->pGia);
+            if ( nRemain != 0 )
+            {   
+                Vec_Int_t * vTemp;
+                Abc_Print( 1, "Adjusting counter-example by adding zeros for PIs without fanout.\n" );
+                // expand the counter-example to include PIs without fanout
+                vCex = Abc_ManExpandCex( pAbc->pGia, vTemp = vCex );
+                Vec_IntFree( vTemp );
+            }
+
+            nFrames = (Vec_IntSize(vCex) - Gia_ManRegNum(pAbc->pGia)) / Gia_ManPiNum(pAbc->pGia);
+            nRemain = (Vec_IntSize(vCex) - Gia_ManRegNum(pAbc->pGia)) % Gia_ManPiNum(pAbc->pGia);
+            if ( nRemain != 0 )
+                Abc_Print( 1, "Counter example has a wrong length.\n" );
+            else
+            {
+                Abc_Print( 1, "Problem is satisfiable. Found counter-example in frame %d.  ", nFrames-1 );
+                Abc_PrintTime( 1, "Time", clk );
+                ABC_FREE( pAbc->pCex );
+                pAbc->pCex = Abc_CexCreate( Gia_ManRegNum(pAbc->pGia), Gia_ManPiNum(pAbc->pGia), Vec_IntArray(vCex), nFrames-1, 0, 0 );
+
+//                Abc_CexPrint( pAbc->pCex );
+
+//                if ( !Gia_ManVerifyCex( pAbc->pGia, pAbc->pCex, 0 ) )
+//                    Abc_Print( 1, "Generated counter-example is INVALID.\n" );
+
+                // remporary work-around to detect the output number - October 18, 2010
+                pAbc->pCex->iPo = Gia_ManFindFailedPoCex( pAbc->pGia, pAbc->pCex, 0 );
+                if ( pAbc->pCex->iPo == -1 )
+                {
+                    Abc_Print( 1, "Generated counter-example is INVALID.\n" );
+                    ABC_FREE( pAbc->pCex );
+                }
+                else
+                {
+                    Abc_Print( 1, "Returned counter-example successfully verified in ABC.\n" );
+                }
+            }
+            Vec_IntFreeP( &vCex );
+        }
+        // get AIG if present
+        pGia = Abc_ManReadAig( pFileOut, "aig:" );
+        if ( pGia != NULL )
+        {
+            Gia_ManStopP( &pAbc->pGia );
+            pAbc->pGia = pGia;                
+        }
+    }    
+
+    // clean up
+    Util_SignalTmpFileRemove( pFileIn, fLeaveFiles );
+    Util_SignalTmpFileRemove( pFileOut, fLeaveFiles );
+    
+    ABC_FREE( pFileIn );
+    ABC_FREE( pFileOut );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cmd_CommandAbcLoadPlugIn( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    FILE * pFile;
+    char pBuffer[1000];
+    char * pCommandLine;
+    char * pTempFile;
+    char * pStrDirBin, * pStrSection;
+    int fd, RetValue;
+
+    if ( argc != 3 )
+    {
+        Abc_Print( -1, "Wrong number of arguments.\n" );
+        goto usage;
+    }
+    // collect arguments
+    pStrDirBin  = argv[argc-2];
+    pStrSection = argv[argc-1];
+
+    // check if the file exists
+    if ( (pFile = fopen( pStrDirBin, "r" )) == NULL )
+    {
+//        Abc_Print( -1, "Cannot run the binary \"%s\".\n", pStrDirBin );
+//        goto usage;
+        return 0;
+    }
+    fclose( pFile );
+
+    // create temp file
+    fd = Util_SignalTmpFile( "__abctmp_", ".txt", &pTempFile );
+    if ( fd == -1 )
+    {
+        Abc_Print( -1, "Cannot create a temporary file.\n" );
+        goto usage;
+    }
+#ifdef WIN32
+    _close( fd );
+#else
+    close( fd );
+#endif
+
+    // get command list
+    pCommandLine = ABC_ALLOC( char, 100 + strlen(pStrDirBin) + strlen(pTempFile) );
+//    sprintf( pCommandLine, "%s -abc -list-commands > %s", pStrDirBin, pTempFile );
+    sprintf( pCommandLine, "%s -abc -list-commands > %s", pStrDirBin, pTempFile );
+    RetValue = Util_SignalSystem( pCommandLine );
+    if ( RetValue == -1 )
+    {
+        Abc_Print( -1, "Command \"%s\" did not succeed.\n", pCommandLine );
+        ABC_FREE( pCommandLine );
+        ABC_FREE( pTempFile );
+        goto usage;
+    }
+    ABC_FREE( pCommandLine );
+
+    // create commands
+    pFile = fopen( pTempFile, "r" );
+    if ( pFile == NULL )
+    {
+        Abc_Print( -1, "Cannot open file with the list of commands.\n" );
+        ABC_FREE( pTempFile );
+        goto usage;
+    }
+    while ( fgets( pBuffer, 1000, pFile ) != NULL )
+    {
+        if ( pBuffer[strlen(pBuffer)-1] == '\n' )
+            pBuffer[strlen(pBuffer)-1] = 0;
+        Cmd_CommandAdd( pAbc, pStrSection, pBuffer, Cmd_CommandAbcPlugIn, 1 );
+//        plugin_commands.push(Pair(cmd_name, binary_name));
+        Vec_PtrPush( pAbc->vPlugInComBinPairs, Extra_UtilStrsav(pBuffer) );
+        Vec_PtrPush( pAbc->vPlugInComBinPairs, Extra_UtilStrsav(pStrDirBin) );
+//        printf( "Creating command %s with binary %s\n", pBuffer, pStrDirBin );
+    }
+    fclose( pFile );
+    Util_SignalTmpFileRemove( pTempFile, 0 );
+    ABC_FREE( pTempFile );
+    return 0;
+usage:
+    Abc_Print( -2, "usage: load_plugin <plugin_dir\\binary_name> <section_name>\n" );
+    Abc_Print( -2, "\t        loads external binary as a plugin\n" );
+    Abc_Print( -2, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/cmd/cmdStarter.c b/abc-build/src/base/cmd/cmdStarter.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/cmd/cmdStarter.c
@@ -0,0 +1,259 @@
+/**CFile****************************************************************
+
+  FileName    [cmdStarter.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Command to start many instances of ABC in parallel.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cmdStarter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "misc/util/abc_global.h"
+#include "misc/extra/extra.h"
+
+#ifdef ABC_USE_PTHREADS
+
+#ifdef _WIN32
+#include "../lib/pthread.h"
+#else
+#include <pthread.h>
+#include <unistd.h>
+#endif
+
+#endif
+
+ABC_NAMESPACE_IMPL_START
+ 
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#ifndef ABC_USE_PTHREADS
+
+void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores ) {}
+
+#else // pthreads are used
+
+// the number of concurrently running threads
+static volatile int nThreadsRunning = 0;
+
+// mutex to control access to the number of threads
+pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This procedures executes one call to system().]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Abc_RunThread( void * pCommand )
+{
+    int status;
+    // perform the call
+    if ( system( (char *)pCommand ) )
+    {
+        fprintf( stderr, "The following command has returned non-zero exit status:\n" );
+        fprintf( stderr, "\"%s\"\n\n", (char *)pCommand );
+        fflush( stdout );
+    }
+    free( pCommand );
+
+    // decrement the number of threads runining 
+    status = pthread_mutex_lock(&mutex);   assert(status == 0);
+    nThreadsRunning--;
+    status = pthread_mutex_unlock(&mutex); assert(status == 0);
+
+    // quit this thread
+	//printf("...Finishing %s\n", (char *)Command);
+	pthread_exit( NULL );
+	assert(0);
+	return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Takes file with commands to be executed and the number of CPUs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores )
+{
+    FILE * pFile, * pFileTemp;
+	pthread_t * pThreadIds;
+    char * BufferCopy, * Buffer;
+    int nLines, LineMax, Line, Len;
+	int i, c, status, Counter;
+    abctime clk = Abc_Clock();
+
+    // check the number of cores
+    if ( nCores < 2 )
+    {
+        fprintf( stdout, "The number of cores (%d) should be more than 1.\n", nCores ); 
+        return; 
+    }
+
+    // open the file and make sure it is available
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    { 
+        fprintf( stdout, "Input file \"%s\" cannot be opened.\n", pFileName ); 
+        return; 
+    }
+
+    // count the number of lines and the longest line
+    nLines = LineMax = Line = 0;
+    while ( (c = fgetc(pFile)) != EOF )
+    {
+        Line++;
+        if ( c != '\n' )
+            continue;
+        nLines++;
+        LineMax = Abc_MaxInt( LineMax, Line );
+        Line = 0;       
+    }
+    nLines += 10;
+    LineMax += LineMax + 100;
+    LineMax += pBinary  ? strlen(pBinary) : 0;
+    LineMax += pCommand ? strlen(pCommand) : 0;
+
+    // allocate storage
+    Buffer = ABC_ALLOC( char, LineMax );
+    pThreadIds = ABC_ALLOC( pthread_t, nLines );
+
+    // check if all files can be opened
+    if ( pCommand != NULL )
+    {
+        // read file names
+        rewind( pFile );
+        for ( i = 0; fgets( Buffer, LineMax, pFile ) != NULL; i++ )
+        {
+            // remove trailing spaces
+            for ( Len = strlen(Buffer) - 1; Len >= 0; Len-- )
+                if ( Buffer[Len] == '\n' || Buffer[Len] == '\r' || Buffer[Len] == '\t' || Buffer[Len] == ' ' )
+                    Buffer[Len] = 0;
+                else
+                    break;
+
+            // get command from file
+            if ( Buffer[0] == 0 || Buffer[0] == '\n' || Buffer[0] == '\r' || Buffer[0] == '\t' || Buffer[0] == ' ' || Buffer[0] == '#' )
+                continue;
+
+            // try to open the file
+            pFileTemp = fopen( Buffer, "rb" );
+            if ( pFileTemp == NULL )
+            {
+                fprintf( stdout, "Starter cannot open file \"%s\".\n", Buffer );
+                fflush( stdout );
+                ABC_FREE( pThreadIds );
+                ABC_FREE( Buffer );
+                fclose( pFile );
+                return;
+            }    
+        }
+    } 
+ 
+    // read commands and execute at most <num> of them at a time
+    rewind( pFile );
+    for ( i = 0; fgets( Buffer, LineMax, pFile ) != NULL; i++ )
+    {
+        // remove trailing spaces
+        for ( Len = strlen(Buffer) - 1; Len >= 0; Len-- )
+            if ( Buffer[Len] == '\n' || Buffer[Len] == '\r' || Buffer[Len] == '\t' || Buffer[Len] == ' ' )
+                Buffer[Len] = 0;
+            else
+                break;
+
+        // get command from file
+        if ( Buffer[0] == 0 || Buffer[0] == '\n' || Buffer[0] == '\r' || Buffer[0] == '\t' || Buffer[0] == ' ' || Buffer[0] == '#' )
+            continue;
+
+        // create command
+        if ( pCommand != NULL )
+        {
+            BufferCopy = ABC_ALLOC( char, LineMax );
+            sprintf( BufferCopy, "%s -c \"%s; %s\" > %s", pBinary, Buffer, pCommand, Extra_FileNameGenericAppend(Buffer, ".txt") );
+        }
+        else
+            BufferCopy = Abc_UtilStrsav( Buffer );
+        fprintf( stdout, "Calling:  %s\n", (char *)BufferCopy );  
+        fflush( stdout );
+
+        // wait till there is an empty thread
+        while ( 1 )
+        {
+            status = pthread_mutex_lock(&mutex);   assert(status == 0);
+            Counter = nThreadsRunning;
+            status = pthread_mutex_unlock(&mutex); assert(status == 0);
+            if ( Counter < nCores - 1 )
+                break;
+//            Sleep( 100 );
+        }
+
+        // increament the number of threads running
+        status = pthread_mutex_lock(&mutex);   assert(status == 0);
+        nThreadsRunning++;
+        status = pthread_mutex_unlock(&mutex); assert(status == 0);
+
+        // create thread to execute this command
+        status = pthread_create( &pThreadIds[i], NULL, Abc_RunThread, (void *)BufferCopy );  assert(status == 0);
+        assert( i < nLines );
+    }
+    ABC_FREE( pThreadIds );
+    ABC_FREE( Buffer );
+    fclose( pFile );
+
+    // wait for all the threads to finish
+    while ( 1 )
+    {
+        status = pthread_mutex_lock(&mutex);   assert(status == 0);
+        Counter = nThreadsRunning;
+        status = pthread_mutex_unlock(&mutex); assert(status == 0);
+        if ( Counter == 0 )
+            break;
+    }
+
+    // cleanup
+//    status = pthread_mutex_destroy(&mutex);   assert(status == 0);
+//    mutex = PTHREAD_MUTEX_INITIALIZER;
+    fprintf( stdout, "Finished processing commands in file \"%s\".  ", pFileName );
+    Abc_PrintTime( 1, "Total wall time", Abc_Clock() - clk );
+    fflush( stdout );
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/cmd/cmdUtils.c b/abc-build/src/base/cmd/cmdUtils.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/cmd/cmdUtils.c
@@ -0,0 +1,748 @@
+/**CFile****************************************************************
+
+  FileName    [cmdUtils.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Various utilities of the command package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cmdUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/mainInt.h"
+#include "cmdInt.h"
+#include <ctype.h>
+
+ABC_NAMESPACE_IMPL_START
+	// proper declaration of isspace
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int CmdCommandPrintCompare( Abc_Command ** ppC1, Abc_Command ** ppC2 );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int cmdCheckShellEscape( Abc_Frame_t * pAbc, int argc, char ** argv)
+{
+    int RetValue;
+	if (argv[0][0] == '!') 
+	{
+		const int size = 4096;
+		int i;
+		char * buffer = ABC_ALLOC(char, 10000);
+		strncpy (buffer, &argv[0][1], size);
+		for (i = 1; i < argc; ++i)
+		{
+				strncat (buffer, " ", size);
+				strncat (buffer, argv[i], size);
+		}
+		if (buffer[0] == 0) 
+			strncpy (buffer, "/bin/sh", size);
+		RetValue = system (buffer);
+        ABC_FREE( buffer );
+
+		// NOTE: Since we reconstruct the cmdline by concatenating
+		// the parts, we lose information. So a command like
+		// `!ls "file name"` will be sent to the system as
+		// `ls file name` which is a BUG
+
+    	return 1;
+	}
+	else
+	{
+		return 0;
+	}
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Executes one command.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int CmdCommandDispatch( Abc_Frame_t * pAbc, int * pargc, char *** pargv )
+{
+    int argc = *pargc;
+    char ** argv = *pargv;
+    char ** argv2;
+
+    Abc_Ntk_t * pNetCopy;
+    int (*pFunc) ( Abc_Frame_t *, int, char ** );
+    Abc_Command * pCommand;
+    char * value;
+    int fError;
+    double clk;
+
+    if ( argc == 0 )
+        return 0;
+
+	if ( cmdCheckShellEscape( pAbc, argc, argv ) == 1 )
+		return 0;
+
+    // get the command
+    if ( ! st__lookup( pAbc->tCommands, argv[0], (char **)&pCommand ) )
+    {   // the command is not in the table
+        // if there is only one word with an extension, assume this is file to be read
+        if ( argc == 1 && strstr( argv[0], "." ) )
+        {
+            // add command 'read' assuming that this is the file name
+            argv2 = CmdAddToArgv( argc, argv );
+            CmdFreeArgv( argc, argv );
+            argc = argc+1;
+            argv = argv2;
+            *pargc = argc;
+            *pargv = argv;
+            if ( ! st__lookup( pAbc->tCommands, argv[0], (char **)&pCommand ) )
+                assert( 0 );
+        }
+        else
+        {
+            fprintf( pAbc->Err, "** cmd error: unknown command '%s'\n", argv[0] );
+            fprintf( pAbc->Err, "(this is likely caused by using an alias defined in \"abc.rc\"\n" );
+            fprintf( pAbc->Err, "without having this file in the current or parent directory)\n" );
+            return 1;
+        }
+    }
+
+    // get the backup network if the command is going to change the network
+    if ( pCommand->fChange ) 
+    {
+        if ( pAbc->pNtkCur && Abc_FrameIsFlagEnabled( "backup" ) )
+        {
+            pNetCopy = Abc_NtkDup( pAbc->pNtkCur );
+            Abc_FrameSetCurrentNetwork( pAbc, pNetCopy );
+            // swap the current network and the backup network 
+            // to prevent the effect of resetting the short names
+            Abc_FrameSwapCurrentAndBackup( pAbc );
+        }
+    }
+
+    // execute the command
+    clk = Extra_CpuTimeDouble();
+    pFunc = (int (*)(Abc_Frame_t *, int, char **))pCommand->pFunc;
+    fError = (*pFunc)( pAbc, argc, argv );
+    pAbc->TimeCommand += Extra_CpuTimeDouble() - clk;
+
+    // automatic execution of arbitrary command after each command 
+    // usually this is a passive command ... 
+    if ( fError == 0 && !pAbc->fAutoexac )
+    {
+        if ( st__lookup( pAbc->tFlags, "autoexec", &value ) )
+        {
+            pAbc->fAutoexac = 1;
+            fError = Cmd_CommandExecute( pAbc, value );
+            pAbc->fAutoexac = 0;
+        }
+    }
+    return fError;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Splits the command line string into individual commands.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+const char * CmdSplitLine( Abc_Frame_t * pAbc, const char *sCommand, int *argc, char ***argv )
+{
+    const char *p, *start;
+    char c;
+    int i, j;
+    char *new_arg;
+    Vec_Ptr_t * vArgs;
+    int single_quote, double_quote;
+
+    vArgs = Vec_PtrAlloc( 10 );
+
+    p = sCommand;
+    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( pAbc->Err, "** cmd warning: ignoring unbalanced quote ...\n" );
+        }
+        if ( start == p )
+            break;
+
+        new_arg = ABC_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';
+        Vec_PtrPush( vArgs, new_arg );
+    }
+
+    *argc = vArgs->nSize;
+    *argv = (char **)Vec_PtrReleaseArray( vArgs );
+    Vec_PtrFree( vArgs );
+    if ( *p == ';' )
+    {
+        p++;
+    }
+    else if ( *p == '#' )
+    {
+        for ( ; *p != 0; p++ ); // skip to end of line 
+    }
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces parts of the command line string by aliases if given.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int CmdApplyAlias( Abc_Frame_t * pAbc, int *argcp, char ***argvp, int *loop )
+{
+    int i, argc, stopit, added, offset, did_subst, subst, fError, newc, j;
+    const char *arg;
+    char **argv, **newv;
+    Abc_Alias *alias;
+
+    argc = *argcp;
+    argv = *argvp;
+    stopit = 0;
+    for ( ; *loop < 200; ( *loop )++ )
+    {
+        if ( argc == 0 )
+            return 0;
+        if ( stopit != 0 || st__lookup( pAbc->tAliases, argv[0],  (char **) &alias ) == 0 )
+        {
+            return 0;
+        }
+        if ( strcmp( argv[0], alias->argv[0] ) == 0 )
+        {
+            stopit = 1;
+        }
+        ABC_FREE( argv[0] );
+        added = alias->argc - 1;
+
+        /* shift all the arguments to the right */
+        if ( added != 0 )
+        {
+            argv = ABC_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] = NULL;
+            }
+            argc += added;
+        }
+        subst = 0;
+        for ( i = 0, offset = 0; i < alias->argc; i++, offset++ )
+        {
+            arg = CmdHistorySubstitution( pAbc, alias->argv[i], &did_subst );
+            if ( arg == NULL )
+            {
+                *argcp = argc;
+                *argvp = argv;
+                return ( 1 );
+            }
+            if ( did_subst != 0 )
+            {
+                subst = 1;
+            }
+            fError = 0;
+            do
+            {
+                arg = CmdSplitLine( pAbc, 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;
+                }
+                fError = CmdApplyAlias( pAbc, &newc, &newv, loop );
+                if ( fError == 0 )
+                {
+                   	fError = CmdCommandDispatch( pAbc, &newc, &newv );
+                }
+                CmdFreeArgv( newc, newv );
+            }
+            while ( fError == 0 );
+            if ( fError != 0 )
+            {
+                *argcp = argc;
+                *argvp = argv;
+                return ( 1 );
+            }
+            added = newc - 1;
+            if ( added != 0 )
+            {
+                argv = ABC_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];
+            }
+            ABC_FREE( newv );
+            offset += added;
+        }
+        if ( subst == 1 )
+        {
+            for ( i = offset; i < argc; i++ )
+            {
+                ABC_FREE( argv[i] );
+            }
+            argc = offset;
+        }
+        *argcp = argc;
+        *argvp = argv;
+    }
+
+    fprintf( pAbc->Err, "** cmd warning: alias loop\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs history substitution (now, disabled).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * CmdHistorySubstitution( Abc_Frame_t * pAbc, char *line, int *changed )
+{
+    // as of today, no history substitution 
+    *changed = 0;
+    return line;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Opens the file with path (now, disabled).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+FILE * CmdFileOpen( Abc_Frame_t * pAbc, char *sFileName, char *sMode, char **pFileNameReal, int silent )
+{
+    char * sRealName, * sPathUsr, * sPathLib, * sPathAll;
+    FILE * pFile;
+    
+    if (strcmp(sFileName, "-") == 0) {
+        if (strcmp(sMode, "w") == 0) {
+            sRealName = Extra_UtilStrsav( "stdout" );
+            pFile = stdout;
+        }
+        else {
+            sRealName = Extra_UtilStrsav( "stdin" );
+            pFile = stdin;
+        }
+    }
+    else {
+        sRealName = NULL;
+        if (strcmp(sMode, "r") == 0) {
+            
+            /* combine both pathes if exist */
+            sPathUsr = Cmd_FlagReadByName(pAbc,"open_path");
+            sPathLib = Cmd_FlagReadByName(pAbc,"lib_path");
+            
+            if ( sPathUsr == NULL && sPathLib == NULL ) {
+                sPathAll = NULL;
+            }
+            else if ( sPathUsr == NULL ) {
+                sPathAll = Extra_UtilStrsav( sPathLib );
+            }
+            else if ( sPathLib == NULL ) {
+                sPathAll = Extra_UtilStrsav( sPathUsr );
+            }
+            else {
+                sPathAll = ABC_ALLOC( char, strlen(sPathLib)+strlen(sPathUsr)+5 );
+                sprintf( sPathAll, "%s:%s",sPathUsr, sPathLib );
+            }
+            if ( sPathAll != NULL ) {
+                sRealName = Extra_UtilFileSearch(sFileName, sPathAll, "r");
+                ABC_FREE( sPathAll );
+            }
+        }
+        if (sRealName == NULL) {
+            sRealName = Extra_UtilTildeExpand(sFileName);
+        }
+
+        if ((pFile = fopen(sRealName, sMode)) == NULL) {
+            if (! silent) {
+//                perror(sRealName);
+                Abc_Print( 1, "Cannot open file \"%s\".\n", sRealName );
+            }
+        }
+        else
+        {
+            // print the path/name of the resource file 'abc.rc' that is being loaded
+            if ( !silent && strlen(sRealName) >= 6 && strcmp( sRealName + strlen(sRealName) - 6, "abc.rc" ) == 0 )            
+                Abc_Print( 1, "Loading resource file \"%s\".\n", sRealName );
+        }
+    }
+    if ( pFileNameReal )
+        *pFileNameReal = sRealName;
+    else
+        ABC_FREE(sRealName);
+    
+    return pFile;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the previously allocated argv array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void CmdFreeArgv( int argc, char **argv )
+{
+    int i;
+    for ( i = 0; i < argc; i++ )
+        ABC_FREE( argv[i] );
+    ABC_FREE( argv );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the previously allocated argv array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char ** CmdAddToArgv( int argc, char ** argv )
+{
+    char ** argv2;
+    int i;
+    argv2 = ABC_ALLOC( char *, argc + 1 ); 
+    argv2[0] = Extra_UtilStrsav( "read" ); 
+//    argv2[0] = Extra_UtilStrsav( "&r" ); 
+    for ( i = 0; i < argc; i++ )
+        argv2[i+1] = Extra_UtilStrsav( argv[i] ); 
+    return argv2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the previously allocated command.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void CmdCommandFree( Abc_Command * pCommand )
+{
+    ABC_FREE( pCommand->sGroup );
+    ABC_FREE( pCommand->sName );
+    ABC_FREE( pCommand );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints commands alphabetically by group.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void CmdCommandPrint( Abc_Frame_t * pAbc, int fPrintAll, int fDetails )
+{
+    const char *key;
+    char *value;
+    st__generator * gen;
+    Abc_Command ** ppCommands;
+    Abc_Command * pCommands;
+    int nCommands, iGroupStart, i, j;
+    char * sGroupCur;
+    int LenghtMax, nColumns, iCom = 0;
+    FILE *backupErr = pAbc->Err;
+
+    // put all commands into one array
+    nCommands = st__count( pAbc->tCommands );
+    ppCommands = ABC_ALLOC( Abc_Command *, nCommands );
+    i = 0;
+    st__foreach_item( pAbc->tCommands, gen, &key, &value )
+    {
+        pCommands = (Abc_Command *)value;
+        if ( fPrintAll || pCommands->sName[0] != '_' )
+            ppCommands[i++] = pCommands;
+    }
+    nCommands = i;
+
+    // sort command by group and then by name, alphabetically
+    qsort( (void *)ppCommands, nCommands, sizeof(Abc_Command *), 
+            (int (*)(const void *, const void *)) CmdCommandPrintCompare );
+    assert( CmdCommandPrintCompare( ppCommands, ppCommands + nCommands - 1 ) <= 0 );
+
+    // get the longest command name
+    LenghtMax = 0;
+    for ( i = 0; i < nCommands; i++ )
+        if ( LenghtMax < (int)strlen(ppCommands[i]->sName) )
+             LenghtMax = (int)strlen(ppCommands[i]->sName); 
+    // get the number of columns
+    nColumns = 79 / (LenghtMax + 2);
+
+    // print the starting message 
+    fprintf( pAbc->Out, "      Welcome to ABC compiled on %s %s!", __DATE__, __TIME__ );
+
+    // print the command by group
+    sGroupCur = NULL;
+    iGroupStart = 0;
+    pAbc->Err = pAbc->Out;
+    for ( i = 0; i < nCommands; i++ )
+        if ( sGroupCur && strcmp( sGroupCur, ppCommands[i]->sGroup ) == 0 )
+        { // this command belongs to the same group as the previous one
+            if ( iCom++ % nColumns == 0 )
+                fprintf( pAbc->Out, "\n" ); 
+            // print this command
+            fprintf( pAbc->Out, " %-*s", LenghtMax, ppCommands[i]->sName );
+        }
+        else
+        { // this command starts the new group of commands
+            // start the new group
+            if ( fDetails && i != iGroupStart )
+            { // print help messages for all commands in the previous groups
+                fprintf( pAbc->Out, "\n" );
+                for ( j = iGroupStart; j < i; j++ )
+                {
+                    char *tmp_cmd;
+                    fprintf( pAbc->Out, "\n" );
+                    // fprintf( pAbc->Out, "--- %s ---\n", ppCommands[j]->sName );
+                    tmp_cmd = ABC_ALLOC(char, strlen(ppCommands[j]->sName)+4);
+                    (void) sprintf(tmp_cmd, "%s -h", ppCommands[j]->sName);
+                    (void) Cmd_CommandExecute( pAbc, tmp_cmd );
+                    ABC_FREE(tmp_cmd);
+                }
+                fprintf( pAbc->Out, "\n" );
+                fprintf( pAbc->Out, "   ----------------------------------------------------------------------" );
+                iGroupStart = i;
+            }
+            fprintf( pAbc->Out, "\n" );
+            fprintf( pAbc->Out, "\n" );
+            fprintf( pAbc->Out, "%s commands:\n", ppCommands[i]->sGroup );
+            // print this command
+            fprintf( pAbc->Out, " %-*s", LenghtMax, ppCommands[i]->sName );
+            // remember current command group
+            sGroupCur = ppCommands[i]->sGroup;
+            // reset the command counter
+            iCom = 1;
+        }
+    if ( fDetails && i != iGroupStart )
+    { // print help messages for all commands in the previous groups
+        fprintf( pAbc->Out, "\n" );
+        for ( j = iGroupStart; j < i; j++ )
+        {
+            char *tmp_cmd;
+            fprintf( pAbc->Out, "\n" );
+            // fprintf( pAbc->Out, "--- %s ---\n", ppCommands[j]->sName );
+            tmp_cmd = ABC_ALLOC(char, strlen(ppCommands[j]->sName)+4);
+            (void) sprintf(tmp_cmd, "%s -h", ppCommands[j]->sName);
+            (void) Cmd_CommandExecute( pAbc, tmp_cmd );
+            ABC_FREE(tmp_cmd);
+        }
+    }
+    pAbc->Err = backupErr;
+    fprintf( pAbc->Out, "\n" );
+    ABC_FREE( ppCommands );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Comparision function used for sorting commands.]
+
+  Description []
+                
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int CmdCommandPrintCompare( Abc_Command ** ppC1, Abc_Command ** ppC2 )
+{
+    Abc_Command * pC1 = *ppC1;
+    Abc_Command * pC2 = *ppC2;
+    int RetValue;
+
+    RetValue = strcmp( pC1->sGroup, pC2->sGroup );
+    if ( RetValue < 0 )
+        return -1;
+    if ( RetValue > 0 )
+        return 1;
+    // the command belong to the same group
+
+    // put commands with "_" at the end of the list
+    if ( pC1->sName[0] != '_' && pC2->sName[0] == '_' )
+        return -1;
+    if ( pC1->sName[0] == '_' && pC2->sName[0] != '_' )
+        return 1;
+
+    RetValue = strcmp( pC1->sName, pC2->sName );
+    if ( RetValue < 0 )
+        return -1;
+    if ( RetValue > 0 )
+        return 1;
+     // should not be two indentical commands
+    assert( 0 );
+    return 0;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Comparision function used for sorting commands.]
+
+  Description []
+                
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int CmdNamePrintCompare( char ** ppC1, char ** ppC2 )
+{
+    return strcmp( *ppC1, *ppC2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparision function used for sorting commands.]
+
+  Description []
+                
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void CmdPrintTable( st__table * tTable, int fAliases )
+{
+    st__generator * gen;
+    const char ** ppNames;
+    const char * key;
+    char* value;
+    int nNames, i;
+
+    // collect keys in the array
+    ppNames = ABC_ALLOC( const char *, st__count(tTable) );
+    nNames = 0;
+    st__foreach_item( tTable, gen, &key, &value )
+        ppNames[nNames++] = key;
+
+    // sort array by name
+    qsort( (void *)ppNames, nNames, sizeof(char *), 
+        (int (*)(const void *, const void *))CmdNamePrintCompare );
+
+    // print in this order
+    for ( i = 0; i < nNames; i++ )
+    {
+        st__lookup( tTable, ppNames[i], &value );
+        if ( fAliases )
+            CmdCommandAliasPrint( Abc_FrameGetGlobalFrame(), (Abc_Alias *)value );
+        else
+            fprintf( stdout, "%-15s %-15s\n", ppNames[i], value );
+    }
+    ABC_FREE( ppNames );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/cmd/module.make b/abc-build/src/base/cmd/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/cmd/module.make
@@ -0,0 +1,9 @@
+SRC +=  src/base/cmd/cmd.c \
+	src/base/cmd/cmdAlias.c \
+	src/base/cmd/cmdApi.c \
+	src/base/cmd/cmdFlag.c \
+	src/base/cmd/cmdHist.c \
+	src/base/cmd/cmdLoad.c \
+	src/base/cmd/cmdPlugin.c \
+	src/base/cmd/cmdStarter.c \
+	src/base/cmd/cmdUtils.c
diff --git a/abc-build/src/base/io/io.c b/abc-build/src/base/io/io.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/io.c
@@ -0,0 +1,2886 @@
+/**CFile****************************************************************
+
+  FileName    [io.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Command file.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: io.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+#include "base/main/mainInt.h"
+#include "aig/saig/saig.h"
+#include "proof/abs/abs.h"
+#include "sat/bmc/bmc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int IoCommandRead        ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadAiger   ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadBaf     ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadBblif   ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadBlif    ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadBlifMv  ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadBench   ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadDsd     ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadEdif    ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadEqn     ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadInit    ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadPla     ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadTruth   ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadVerilog ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadStatus  ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadGig     ( Abc_Frame_t * pAbc, int argc, char **argv );
+
+static int IoCommandWrite       ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteHie    ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteAiger  ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteAigerCex( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteBaf    ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteBblif  ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteBlif   ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteBlifMv ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteBench  ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteBook   ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteCnf    ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteCnf2   ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteCex    ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteDot    ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteEqn    ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteGml    ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteList   ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWritePla    ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteSortCnf( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteTruth  ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteTruths ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteStatus ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteSmv    ( Abc_Frame_t * pAbc, int argc, char **argv );
+
+extern void Abc_FrameCopyLTLDataBase( Abc_Frame_t *pAbc, Abc_Ntk_t * pNtk );
+
+extern int glo_fMapped;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_Init( Abc_Frame_t * pAbc )
+{
+    Cmd_CommandAdd( pAbc, "I/O", "read",          IoCommandRead,         1 );
+    Cmd_CommandAdd( pAbc, "I/O", "read_aiger",    IoCommandReadAiger,    1 );
+    Cmd_CommandAdd( pAbc, "I/O", "read_baf",      IoCommandReadBaf,      1 );
+    Cmd_CommandAdd( pAbc, "I/O", "read_bblif",    IoCommandReadBblif,    1 );
+    Cmd_CommandAdd( pAbc, "I/O", "read_blif",     IoCommandReadBlif,     1 );
+    Cmd_CommandAdd( pAbc, "I/O", "read_blif_mv",  IoCommandReadBlifMv,   1 );
+    Cmd_CommandAdd( pAbc, "I/O", "read_bench",    IoCommandReadBench,    1 );
+    Cmd_CommandAdd( pAbc, "I/O", "read_dsd",      IoCommandReadDsd,      1 );
+//    Cmd_CommandAdd( pAbc, "I/O", "read_edif",     IoCommandReadEdif,     1 );
+    Cmd_CommandAdd( pAbc, "I/O", "read_eqn",      IoCommandReadEqn,      1 );
+    Cmd_CommandAdd( pAbc, "I/O", "read_init",     IoCommandReadInit,     1 );
+    Cmd_CommandAdd( pAbc, "I/O", "read_pla",      IoCommandReadPla,      1 );
+    Cmd_CommandAdd( pAbc, "I/O", "read_truth",    IoCommandReadTruth,    1 );
+    Cmd_CommandAdd( pAbc, "I/O", "read_verilog",  IoCommandReadVerilog,  1 );
+    Cmd_CommandAdd( pAbc, "I/O", "read_status",   IoCommandReadStatus,   0 );
+    Cmd_CommandAdd( pAbc, "I/O", "&read_gig",     IoCommandReadGig,      0 );
+
+    Cmd_CommandAdd( pAbc, "I/O", "write",         IoCommandWrite,        0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_hie",     IoCommandWriteHie,     0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_aiger",   IoCommandWriteAiger,   0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_aiger_cex",   IoCommandWriteAigerCex,   0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_baf",     IoCommandWriteBaf,     0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_bblif",   IoCommandWriteBblif,   0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_blif",    IoCommandWriteBlif,    0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_blif_mv", IoCommandWriteBlifMv,  0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_bench",   IoCommandWriteBench,   0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_book",    IoCommandWriteBook,    0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_cellnet", IoCommandWriteCellNet, 0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_cex",     IoCommandWriteCex,     0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_cnf",     IoCommandWriteCnf,     0 );
+    Cmd_CommandAdd( pAbc, "I/O", "&write_cnf",    IoCommandWriteCnf2,    0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_dot",     IoCommandWriteDot,     0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_eqn",     IoCommandWriteEqn,     0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_gml",     IoCommandWriteGml,     0 );
+//    Cmd_CommandAdd( pAbc, "I/O", "write_list",    IoCommandWriteList,    0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_pla",     IoCommandWritePla,     0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_verilog", IoCommandWriteVerilog, 0 );
+//    Cmd_CommandAdd( pAbc, "I/O", "write_verlib",  IoCommandWriteVerLib,  0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_sorter_cnf", IoCommandWriteSortCnf,  0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_truth",   IoCommandWriteTruth,   0 );
+    Cmd_CommandAdd( pAbc, "I/O", "&write_truths", IoCommandWriteTruths,  0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_status",  IoCommandWriteStatus,  0 );
+    Cmd_CommandAdd( pAbc, "I/O", "write_smv",     IoCommandWriteSmv,     0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_End( Abc_Frame_t * pAbc )
+{
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandRead( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char Command[1000];
+    Abc_Ntk_t * pNtk;
+    char * pFileName, * pTemp;
+    int c, fCheck, fBarBufs;
+
+    fCheck = 1;
+    fBarBufs = 0;
+    glo_fMapped = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "mcbh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'm':
+                glo_fMapped ^= 1;
+                break;
+            case 'c':
+                fCheck ^= 1;
+                break;
+            case 'b':
+                fBarBufs ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    // fix the wrong symbol
+    for ( pTemp = pFileName; *pTemp; pTemp++ )
+        if ( *pTemp == '>' || *pTemp == '\\' )
+            *pTemp = '/';
+    // read libraries
+    Command[0] = 0;
+    assert( strlen(pFileName) < 900 );
+    if ( !strcmp( Extra_FileNameExtension(pFileName), "genlib" )  )
+        sprintf( Command, "read_genlib %s", pFileName );
+    else if ( !strcmp( Extra_FileNameExtension(pFileName), "lib" ) )
+        sprintf( Command, "read_lib %s", pFileName );
+    else if ( !strcmp( Extra_FileNameExtension(pFileName), "scl" ) )
+        sprintf( Command, "read_scl %s", pFileName );
+    else if ( !strcmp( Extra_FileNameExtension(pFileName), "super" ) )
+        sprintf( Command, "read_super %s", pFileName );
+    else if ( !strcmp( Extra_FileNameExtension(pFileName), "constr" ) )
+        sprintf( Command, "read_constr %s", pFileName );
+    else if ( !strcmp( Extra_FileNameExtension(pFileName), "c" ) )
+        sprintf( Command, "so %s", pFileName );
+    else if ( !strcmp( Extra_FileNameExtension(pFileName), "dsd" ) )
+        sprintf( Command, "dsd_load %s", pFileName );
+    if ( Command[0] )
+    {
+        Cmd_CommandExecute( pAbc, Command );
+        return 0;
+    }
+    // check if the library is available
+    if ( glo_fMapped && Abc_FrameReadLibGen() == NULL )
+    {
+        Abc_Print( 1, "Cannot read mapped design when the library is not given.\n" );
+        return 0;
+    }
+    // read the file using the corresponding file reader
+    pNtk = Io_Read( pFileName, Io_ReadFileType(pFileName), fCheck, fBarBufs );
+    if ( pNtk == NULL )
+        return 0;
+    if ( Abc_NtkPiNum(pNtk) == 0 )
+    {
+        Abc_Print( 0, "The new network has no primary inputs. It is recommended\n" );
+        Abc_Print( 1, "to add a dummy PI to make sure all commands work correctly.\n" );
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+	Abc_FrameCopyLTLDataBase( pAbc, pNtk );
+    Abc_FrameClearVerifStatus( pAbc );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read [-mcbh] <file>\n" );
+    fprintf( pAbc->Err, "\t         replaces the current network by the network read from <file>\n" );
+    fprintf( pAbc->Err, "\t         by calling the parser that matches the extension of <file>\n" );
+    fprintf( pAbc->Err, "\t         (to read a hierarchical design, use \"read_hie\")\n" );
+    fprintf( pAbc->Err, "\t-m     : toggle reading mapped Verilog [default = %s]\n", glo_fMapped? "yes":"no" );
+    fprintf( pAbc->Err, "\t-c     : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+    fprintf( pAbc->Err, "\t-b     : toggle reading barrier buffers [default = %s]\n", fBarBufs? "yes":"no" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of a file to read\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandReadAiger( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk;
+    char * pFileName;
+    int fCheck;
+    int c;
+
+    fCheck = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'c':
+                fCheck ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    // read the file using the corresponding file reader
+    pNtk = Io_Read( pFileName, IO_FILE_AIGER, fCheck, 0 );
+    if ( pNtk == NULL )
+        return 1;
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+    Abc_FrameClearVerifStatus( pAbc );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read_aiger [-ch] <file>\n" );
+    fprintf( pAbc->Err, "\t         reads the network in the AIGER format (http://fmv.jku.at/aiger)\n" );
+    fprintf( pAbc->Err, "\t-c     : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of a file to read\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandReadBaf( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk;
+    char * pFileName;
+    int fCheck;
+    int c;
+
+    fCheck = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'c':
+                fCheck ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    // read the file using the corresponding file reader
+    pNtk = Io_Read( pFileName, IO_FILE_BAF, fCheck, 0 );
+    if ( pNtk == NULL )
+        return 1;
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+    Abc_FrameClearVerifStatus( pAbc );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read_baf [-ch] <file>\n" );
+    fprintf( pAbc->Err, "\t         reads the network in Binary Aig Format (BAF)\n" );
+    fprintf( pAbc->Err, "\t-c     : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of a file to read\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandReadBblif( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk;
+    char * pFileName;
+    int fCheck;
+    int c;
+
+    fCheck = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'c':
+                fCheck ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    // read the file using the corresponding file reader
+    pNtk = Io_Read( pFileName, IO_FILE_BBLIF, fCheck, 0 );
+    if ( pNtk == NULL )
+        return 1;
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+    Abc_FrameClearVerifStatus( pAbc );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read_bblif [-ch] <file>\n" );
+    fprintf( pAbc->Err, "\t         reads the network in a binary BLIF format\n" );
+    fprintf( pAbc->Err, "\t-c     : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of a file to read\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk;
+    char * pFileName;
+    int fReadAsAig;
+    int fCheck;
+    int fUseNewParser;
+    int fSaveNames;
+    int c;
+    extern Abc_Ntk_t * Io_ReadBlifAsAig( char * pFileName, int fCheck );
+
+    fCheck = 1;
+    fReadAsAig = 0;
+    fUseNewParser = 1;
+    fSaveNames = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "nmach" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'n':
+                fUseNewParser ^= 1;
+                break;
+            case 'm':
+                fSaveNames ^= 1;
+                break;
+            case 'a':
+                fReadAsAig ^= 1;
+                break;
+            case 'c':
+                fCheck ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    // read the file using the corresponding file reader
+    if ( fReadAsAig )
+        pNtk = Io_ReadBlifAsAig( pFileName, fCheck );
+    else if ( fUseNewParser )
+        pNtk = Io_Read( pFileName, IO_FILE_BLIF, fCheck, 0 );
+    else
+    {
+        Abc_Ntk_t * pTemp;
+        pNtk = Io_ReadBlif( pFileName, fCheck );
+        if ( pNtk == NULL )
+            return 1;
+        if ( fSaveNames )
+            Abc_NtkStartNameIds( pNtk );
+        pNtk = Abc_NtkToLogic( pTemp = pNtk );
+        if ( fSaveNames )
+            Abc_NtkTransferNameIds( pTemp, pNtk );
+        Abc_NtkDelete( pTemp );
+    }
+
+    if ( pNtk == NULL )
+        return 1;
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+    Abc_FrameClearVerifStatus( pAbc );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read_blif [-nmach] <file>\n" );
+    fprintf( pAbc->Err, "\t         reads the network in binary BLIF format\n" );
+    fprintf( pAbc->Err, "\t         (if this command does not work, try \"read\")\n" );
+    fprintf( pAbc->Err, "\t-n     : toggle using old BLIF parser without hierarchy support [default = %s]\n", !fUseNewParser? "yes":"no" );
+    fprintf( pAbc->Err, "\t-m     : toggle saving original circuit names into a file [default = %s]\n", fSaveNames? "yes":"no" );
+    fprintf( pAbc->Err, "\t-a     : toggle creating AIG while reading the file [default = %s]\n", fReadAsAig? "yes":"no" );
+    fprintf( pAbc->Err, "\t-c     : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of a file to read\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandReadBlifMv( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk;
+    char * pFileName;
+    int fCheck;
+    int c;
+
+    fCheck = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'c':
+                fCheck ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    // read the file using the corresponding file reader
+    pNtk = Io_Read( pFileName, IO_FILE_BLIFMV, fCheck, 0 );
+    if ( pNtk == NULL )
+        return 1;
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+    Abc_FrameClearVerifStatus( pAbc );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read_blif_mv [-ch] <file>\n" );
+    fprintf( pAbc->Err, "\t         reads the network in BLIF-MV format\n" );
+    fprintf( pAbc->Err, "\t         (if this command does not work, try \"read\")\n" );
+    fprintf( pAbc->Err, "\t-c     : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of a file to read\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk;
+    char * pFileName;
+    int fCheck;
+    int c;
+
+    fCheck = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'c':
+                fCheck ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    // read the file using the corresponding file reader
+    pNtk = Io_Read( pFileName, IO_FILE_BENCH, fCheck, 0 );
+    if ( pNtk == NULL )
+        return 1;
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+    Abc_FrameClearVerifStatus( pAbc );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read_bench [-ch] <file>\n" );
+    fprintf( pAbc->Err, "\t         reads the network in BENCH format\n" );
+    fprintf( pAbc->Err, "\t-c     : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of a file to read\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandReadDsd( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk;
+    char * pString;
+    int fCheck;
+    int c;
+    extern Abc_Ntk_t * Io_ReadDsd( char * pFormula );
+
+    fCheck = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'c':
+                fCheck ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pString = argv[globalUtilOptind];
+    // read the file using the corresponding file reader
+    pNtk = Io_ReadDsd( pString );
+    if ( pNtk == NULL )
+        return 1;
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+    Abc_FrameClearVerifStatus( pAbc );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read_dsd [-h] <formula>\n" );
+    fprintf( pAbc->Err, "\t          parses a formula representing DSD of a function\n" );
+    fprintf( pAbc->Err, "\t-h      : prints the command summary\n" );
+    fprintf( pAbc->Err, "\tformula : the formula representing disjoint-support decomposition (DSD)\n" );
+    fprintf( pAbc->Err, "\t          Example of a formula: !(a*(b+CA(!d,e*f,c))*79B3(g,h,i,k))\n" );
+    fprintf( pAbc->Err, "\t          where \'!\' is an INV, \'*\' is an AND, \'+\' is an XOR, \n" );
+    fprintf( pAbc->Err, "\t          CA and 79B3 are hexadecimal representations of truth tables\n" );
+    fprintf( pAbc->Err, "\t          (in this case CA=11001010 is truth table of MUX(Data0,Data1,Ctrl))\n" );
+    fprintf( pAbc->Err, "\t          The lower chars (a,b,c,etc) are reserved for elementary variables.\n" );
+    fprintf( pAbc->Err, "\t          The upper chars (A,B,C,etc) are reserved for hexadecimal digits.\n" );
+    fprintf( pAbc->Err, "\t          No spaces are allowed in formulas. In parantheses, LSB goes first.\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandReadEdif( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk;
+    char * pFileName;
+    int fCheck;
+    int c;
+
+    fCheck = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'c':
+                fCheck ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    // read the file using the corresponding file reader
+    pNtk = Io_Read( pFileName, IO_FILE_EDIF, fCheck, 0 );
+    if ( pNtk == NULL )
+        return 1;
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+    Abc_FrameClearVerifStatus( pAbc );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read_edif [-ch] <file>\n" );
+    fprintf( pAbc->Err, "\t         reads the network in EDIF (works only for ISCAS benchmarks)\n" );
+    fprintf( pAbc->Err, "\t-c     : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of a file to read\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandReadEqn( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk;
+    char * pFileName;
+    int fCheck;
+    int c;
+
+    fCheck = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'c':
+                fCheck ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    // read the file using the corresponding file reader
+    pNtk = Io_Read( pFileName, IO_FILE_EQN, fCheck, 0 );
+    if ( pNtk == NULL )
+        return 1;
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+    Abc_FrameClearVerifStatus( pAbc );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read_eqn [-ch] <file>\n" );
+    fprintf( pAbc->Err, "\t         reads the network in equation format\n" );
+    fprintf( pAbc->Err, "\t-c     : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of a file to read\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandReadInit( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    FILE * pOut, * pErr;
+    Abc_Ntk_t * pNtk;
+    char * pFileName;
+    int c;
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind && argc != globalUtilOptind + 1 )
+        goto usage;
+
+    if ( pNtk == NULL )
+    {
+        fprintf( pErr, "Empty network.\n" );
+        return 1;
+    }
+    // get the input file name
+    if ( argc == globalUtilOptind + 1 )
+        pFileName = argv[globalUtilOptind];
+    else if ( pNtk->pSpec )
+        pFileName = Extra_FileNameGenericAppend( pNtk->pSpec, ".init" );
+    else
+    {
+        printf( "File name should be given on the command line.\n" );
+        return 1;
+    }
+
+    // read the file using the corresponding file reader
+    pNtk = Abc_NtkDup( pNtk );
+    Io_ReadBenchInit( pNtk, pFileName );
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+    Abc_FrameClearVerifStatus( pAbc );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read_init [-h] <file>\n" );
+    fprintf( pAbc->Err, "\t         reads initial state of the network in BENCH format\n" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of a file to read\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk;
+    char * pFileName;
+    int fCheck;
+    int fZeros;
+    int c;
+
+    fZeros = 0;
+    fCheck = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "zch" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'z':
+                fZeros ^= 1;
+                break;
+            case 'c':
+                fCheck ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    // read the file using the corresponding file reader
+    if ( fZeros )
+    {
+        Abc_Ntk_t * pTemp;
+        pNtk = Io_ReadPla( pFileName, fZeros, fCheck );
+        if ( pNtk == NULL )
+        {
+            printf( "Reading PLA file has failed.\n" );
+            return 1;
+        }
+        pNtk = Abc_NtkToLogic( pTemp = pNtk );
+        Abc_NtkDelete( pTemp );
+    }
+    else
+        pNtk = Io_Read( pFileName, IO_FILE_PLA, fCheck, 0 );
+    if ( pNtk == NULL )
+        return 1;
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+    Abc_FrameClearVerifStatus( pAbc );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read_pla [-zch] <file>\n" );
+    fprintf( pAbc->Err, "\t         reads the network in PLA\n" );
+    fprintf( pAbc->Err, "\t-z     : toggle reading on-set and off-set [default = %s]\n", fZeros? "off-set":"on-set" );
+    fprintf( pAbc->Err, "\t-c     : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of a file to read\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandReadTruth( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk;
+    char * pSopCover;
+    int fHex;
+    int c;
+
+    fHex = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "xh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'x':
+                fHex ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+
+    if ( argc != globalUtilOptind + 1 )
+    {
+        goto usage;
+    }
+
+    // convert truth table to SOP
+    if ( fHex )
+        pSopCover = Abc_SopFromTruthHex(argv[globalUtilOptind]);
+    else
+        pSopCover = Abc_SopFromTruthBin(argv[globalUtilOptind]);
+    if ( pSopCover == NULL || pSopCover[0] == 0 )
+    {
+        ABC_FREE( pSopCover );
+        fprintf( pAbc->Err, "Reading truth table has failed.\n" );
+        return 1;
+    }
+
+    pNtk = Abc_NtkCreateWithNode( pSopCover );
+    ABC_FREE( pSopCover );
+    if ( pNtk == NULL )
+    {
+        fprintf( pAbc->Err, "Deriving the network has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+    Abc_FrameClearVerifStatus( pAbc );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read_truth [-xh] <truth>\n" );
+    fprintf( pAbc->Err, "\t         creates network with node having given truth table\n" );
+    fprintf( pAbc->Err, "\t-x     : toggles between bin and hex representation [default = %s]\n", fHex? "hex":"bin" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\ttruth  : truth table with most signficant bit first (e.g. 1000 for AND(a,b))\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandReadVerilog( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk;
+    char * pFileName;
+    int fCheck, fBarBufs;
+    int c;
+
+    fCheck = 1;
+    fBarBufs = 0;
+    glo_fMapped = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "mcbh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'm':
+                glo_fMapped ^= 1;
+                break;
+            case 'c':
+                fCheck ^= 1;
+                break;
+            case 'b':
+                fBarBufs ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    // read the file using the corresponding file reader
+    pNtk = Io_Read( pFileName, IO_FILE_VERILOG, fCheck, fBarBufs );
+    if ( pNtk == NULL )
+        return 1;
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+    Abc_FrameClearVerifStatus( pAbc );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read_verilog [-mcbh] <file>\n" );
+    fprintf( pAbc->Err, "\t         reads the network in Verilog (IWLS 2002/2005 subset)\n" );
+    fprintf( pAbc->Err, "\t-m     : toggle reading mapped Verilog [default = %s]\n", glo_fMapped? "yes":"no" );
+    fprintf( pAbc->Err, "\t-c     : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+    fprintf( pAbc->Err, "\t-b     : toggle reading barrier buffers [default = %s]\n", fBarBufs? "yes":"no" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of a file to read\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandReadStatus( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char * pFileName;
+    FILE * pFile;
+    int c;
+    extern int Abc_NtkReadLogFile( char * pFileName, Abc_Cex_t ** ppCex, int * pnFrames );
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+    {
+        goto usage;
+    }
+
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    if ( (pFile = fopen( pFileName, "r" )) == NULL )
+    {
+        fprintf( pAbc->Err, "Cannot open input file \"%s\". \n", pFileName );
+        return 1;
+    }
+    fclose( pFile );
+
+    // set the new network
+    Abc_FrameClearVerifStatus( pAbc );
+    pAbc->Status = Abc_NtkReadLogFile( pFileName, &pAbc->pCex, &pAbc->nFrames );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read_status [-ch] <file>\n" );
+    fprintf( pAbc->Err, "\t         reads verification log file\n" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of a file to read\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandReadGig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern Gia_Man_t * Gia_ManReadGig( char * pFileName );
+    Gia_Man_t * pAig;
+    char * pFileName;
+    FILE * pFile;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+    {
+        goto usage;
+    }
+
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    if ( (pFile = fopen( pFileName, "r" )) == NULL )
+    {
+        fprintf( pAbc->Err, "Cannot open input file \"%s\". \n", pFileName );
+        return 1;
+    }
+    fclose( pFile );
+
+    // set the new network
+    pAig = Gia_ManReadGig( pFileName );
+    //Abc_FrameUpdateGia( pAbc, pAig );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: &read_gig [-h] <file>\n" );
+    fprintf( pAbc->Err, "\t         reads design in GIG format\n" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of a file to read\n" );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWrite( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char Command[1000];
+    char * pFileName;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // write libraries
+    Command[0] = 0;
+    assert( strlen(pFileName) < 900 );
+    if ( !strcmp( Extra_FileNameExtension(pFileName), "genlib" )  )
+        sprintf( Command, "write_genlib %s", pFileName );
+    else if ( !strcmp( Extra_FileNameExtension(pFileName), "lib" ) )
+        sprintf( Command, "write_liberty %s", pFileName );
+    else if ( !strcmp( Extra_FileNameExtension(pFileName), "dsd" ) )
+        sprintf( Command, "dsd_save %s", pFileName );
+    if ( Command[0] )
+    {
+        Cmd_CommandExecute( pAbc, Command );
+        return 0;
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    // call the corresponding file writer
+    Io_Write( pAbc->pNtkCur, pFileName, Io_ReadFileType(pFileName) );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write [-h] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes the current network into <file> by calling\n" );
+    fprintf( pAbc->Err, "\t         the writer that matches the extension of <file>\n" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteHie( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pBaseName, * pFileName;
+    int c;
+
+    glo_fMapped = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "mh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'm':
+                glo_fMapped ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 2 )
+        goto usage;
+    // get the output file name
+    pBaseName = argv[globalUtilOptind];
+    pFileName = argv[globalUtilOptind+1];
+    // call the corresponding file writer
+//    Io_Write( pAbc->pNtkCur, pFileName, Io_ReadFileType(pFileName) );
+    Io_WriteHie( pAbc->pNtkCur, pBaseName, pFileName );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_hie [-h] <orig> <file>\n" );
+    fprintf( pAbc->Err, "\t         writes the current network into <file> by calling\n" );
+    fprintf( pAbc->Err, "\t         the hierarchical writer that matches the extension of <file>\n" );
+    fprintf( pAbc->Err, "\t-m     : toggle reading mapped Verilog for <orig> [default = %s]\n", glo_fMapped? "yes":"no" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\torig   : the name of the original file with the hierarchical design\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteAiger( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+    int fWriteSymbols;
+    int fCompact;
+    int fUnique;
+    int fVerbose;
+    int c;
+
+    fWriteSymbols = 0;
+    fCompact      = 0;
+    fUnique       = 0;
+    fVerbose      = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "scuvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 's':
+                fWriteSymbols ^= 1;
+                break;
+            case 'c':
+                fCompact ^= 1;
+                break;
+            case 'u':
+                fUnique ^= 1;
+                break;
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // call the corresponding file writer
+    if ( !Abc_NtkIsStrash(pAbc->pNtkCur) )
+    {
+        fprintf( stdout, "Writing this format is only possible for structurally hashed AIGs.\n" );
+        return 1;
+    }
+    if ( fUnique )
+    {
+        extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+        extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan );
+        Aig_Man_t * pAig = Abc_NtkToDar( pAbc->pNtkCur, 0, 1 );
+        Aig_Man_t * pCan = Saig_ManDupIsoCanonical( pAig, fVerbose );
+        Abc_Ntk_t * pTemp = Abc_NtkFromAigPhase( pCan );
+        Aig_ManStop( pCan );
+        Aig_ManStop( pAig );
+        Io_WriteAiger( pTemp, pFileName, fWriteSymbols, fCompact, fUnique );
+        Abc_NtkDelete( pTemp );
+    }
+    else
+        Io_WriteAiger( pAbc->pNtkCur, pFileName, fWriteSymbols, fCompact, fUnique );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_aiger [-scuvh] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes the network in the AIGER format (http://fmv.jku.at/aiger)\n" );
+    fprintf( pAbc->Err, "\t-s     : toggle saving I/O names [default = %s]\n", fWriteSymbols? "yes" : "no" );
+    fprintf( pAbc->Err, "\t-c     : toggle writing more compactly [default = %s]\n", fCompact? "yes" : "no" );
+    fprintf( pAbc->Err, "\t-u     : toggle writing canonical AIG structure [default = %s]\n", fUnique? "yes" : "no" );
+    fprintf( pAbc->Err, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes" : "no" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write (extension .aig)\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteAigerCex( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pCex == NULL )
+    {
+        fprintf( pAbc->Out, "There is no current CEX.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    Io_WriteAigerCex( pAbc->pCex, pAbc->pNtkCur, pAbc->pGia, pFileName );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_aiger_cex [-h] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes the current CEX in the AIGER format (http://fmv.jku.at/aiger)\n" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteBaf( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // call the corresponding file writer
+    Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BAF );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_baf [-h] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes the network into a BLIF file\n" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write (extension .baf)\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteBblif( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // call the corresponding file writer
+    Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BBLIF );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_bblif [-h] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes the network into a binary BLIF file\n" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write (extension .bblif)\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteBlif( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+    char * pLutStruct = NULL;
+    int c, fSpecial = 0;
+    int fUseHie = 0;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Sjah" ) ) != EOF )
+    {
+        switch ( c )
+        {
+		    case 'S':
+                if ( globalUtilOptind >= argc )
+                {
+                    Abc_Print( -1, "Command line switch \"-S\" should be followed by string.\n" );
+                    goto usage;
+                }
+			    pLutStruct = argv[globalUtilOptind];
+			    globalUtilOptind++;
+			    if ( strlen(pLutStruct) != 2 && strlen(pLutStruct) != 3 ) 
+                {
+                    Abc_Print( -1, "Command line switch \"-S\" should be followed by a 2- or 3-char string (e.g. \"44\" or \"555\").\n" );
+                    goto usage;
+                }
+			    break;
+            case 'j':
+                fSpecial ^= 1;
+                break;
+            case 'a':
+                fUseHie ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // call the corresponding file writer
+    if ( fSpecial || pLutStruct )
+        Io_WriteBlifSpecial( pAbc->pNtkCur, pFileName, pLutStruct, fUseHie );
+    else
+        Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BLIF );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_blif [-S str] [-jah] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes the network into a BLIF file\n" );
+    fprintf( pAbc->Err, "\t-S str : string representing the LUT structure [default = %s]\n", pLutStruct ? pLutStruct : "not used" );  
+    fprintf( pAbc->Err, "\t-j     : enables special BLIF writing [default = %s]\n", fSpecial? "yes" : "no" );;
+    fprintf( pAbc->Err, "\t-a     : enables hierarchical BLIF writing for LUT structures [default = %s]\n", fUseHie? "yes" : "no" );;
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write (extension .blif)\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteBlifMv( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // call the corresponding file writer
+    Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BLIFMV );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_blif_mv [-h] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes the network into a BLIF-MV file\n" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write (extension .mv)\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteBench( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+    int fUseLuts;
+    int c;
+
+    fUseLuts = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'l':
+                fUseLuts ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // call the corresponding file writer
+    if ( !fUseLuts )
+        Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BENCH );
+    else if ( pAbc->pNtkCur )
+    {
+        Abc_Ntk_t * pNtkTemp;
+        pNtkTemp = Abc_NtkToNetlist( pAbc->pNtkCur );
+        Abc_NtkToAig( pNtkTemp );
+        Io_WriteBenchLut( pNtkTemp, pFileName );
+        Abc_NtkDelete( pNtkTemp );
+    }
+    else
+        printf( "There is no current network.\n" );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_bench [-lh] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes the network in BENCH format\n" );
+    fprintf( pAbc->Err, "\t-l     : toggle using LUTs in the output [default = %s]\n", fUseLuts? "yes" : "no" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write (extension .bench)\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteBook( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+		int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+		// call the corresponding file writer
+    Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BOOK );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_book [-h] <file> [-options]\n" );
+    fprintf( pAbc->Err, "\t-h     : prints the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write (extension .aux, .nodes, .nets)\n" );
+    fprintf( pAbc->Err, "\t\n" );
+    fprintf( pAbc->Err, "\tThis command is developed by Myungchul Kim (University of Michigan).\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    Abc_Ntk_t * pNtk;
+    char * pFileName;
+    int c;
+    extern void Io_WriteCellNet( Abc_Ntk_t * pNtk, char * pFileName );
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    pNtk = pAbc->pNtkCur;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // call the corresponding file writer
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        fprintf( pAbc->Out, "The network should be a logic network (if it an AIG, use command \"logic\")\n" );
+        return 0;
+    }
+    Io_WriteCellNet( pNtk, pFileName );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_cellnet [-h] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes the network is the cellnet format\n" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteCnf( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+    int c;
+    int fNewAlgo;
+    int fFastAlgo;
+    int fAllPrimes;
+    int fChangePol;
+    int fVerbose;
+    extern Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName, int fFastAlgo, int fChangePol, int fVerbose );
+
+    fNewAlgo = 1;
+    fFastAlgo = 0;
+    fAllPrimes = 0;
+    fChangePol = 1;
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "nfpcvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'n':
+                fNewAlgo ^= 1;
+                break;
+            case 'f':
+                fFastAlgo ^= 1;
+                break;
+            case 'p':
+                fAllPrimes ^= 1;
+                break;
+            case 'c':
+                fChangePol ^= 1;
+                break;
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // check if the feature will be used
+    if ( Abc_NtkIsStrash(pAbc->pNtkCur) && fAllPrimes )
+    {
+        fAllPrimes = 0;
+        printf( "Warning: Selected option to write all primes has no effect when deriving CNF from AIG.\n" );
+    }
+    // call the corresponding file writer
+    if ( fFastAlgo )
+        Abc_NtkDarToCnf( pAbc->pNtkCur, pFileName, 1, fChangePol, fVerbose );
+    else if ( fNewAlgo )
+        Abc_NtkDarToCnf( pAbc->pNtkCur, pFileName, 0, fChangePol, fVerbose );
+    else if ( fAllPrimes )
+        Io_WriteCnf( pAbc->pNtkCur, pFileName, 1 );
+    else
+        Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_CNF );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_cnf [-nfpcvh] <file>\n" );
+    fprintf( pAbc->Err, "\t         generates CNF for the miter (see also \"&write_cnf\")\n" );
+    fprintf( pAbc->Err, "\t-n     : toggle using new algorithm [default = %s]\n", fNewAlgo? "yes" : "no" );
+    fprintf( pAbc->Err, "\t-f     : toggle using fast algorithm [default = %s]\n", fFastAlgo? "yes" : "no" );
+    fprintf( pAbc->Err, "\t-p     : toggle using all primes to enhance implicativity [default = %s]\n", fAllPrimes? "yes" : "no" );
+    fprintf( pAbc->Err, "\t-c     : toggle adjasting polarity of internal variables [default = %s]\n", fChangePol? "yes" : "no" );
+    fprintf( pAbc->Err, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes" : "no" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteCnf2( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    extern void Jf_ManDumpCnf( Gia_Man_t * p, char * pFileName, int fVerbose );
+    extern void Mf_ManDumpCnf( Gia_Man_t * p, char * pFileName, int nLutSize, int fVerbose );
+    FILE * pFile;
+    char * pFileName;
+    int nLutSize = 6;
+    int fNewAlgo = 1;
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Kavh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'K':
+                if ( globalUtilOptind >= argc )
+                {
+                    Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
+                    goto usage;
+                }
+                nLutSize = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                break;
+            case 'a':
+                fNewAlgo ^= 1;
+                break;
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "IoCommandWriteCnf2(): There is no AIG.\n" );
+        return 1;
+    } 
+    if ( Gia_ManRegNum(pAbc->pGia) > 0 )
+    {
+        Abc_Print( -1, "IoCommandWriteCnf2(): Works only for combinational miters.\n" );
+        return 0;
+    }
+    if ( nLutSize < 3 || nLutSize > 8 )
+    {
+        Abc_Print( -1, "IoCommandWriteCnf2(): Invalid LUT size (%d).\n", nLutSize );
+        return 0;
+    }
+    if ( !fNewAlgo && !Sdm_ManCanRead() )
+    {
+        Abc_Print( -1, "IoCommandWriteCnf2(): Cannot input precomputed DSD information.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\" for writing.\n", pFileName );
+        return 0;
+    }
+    fclose( pFile );
+    if ( fNewAlgo )
+        Mf_ManDumpCnf( pAbc->pGia, pFileName, nLutSize, fVerbose );
+    else
+        Jf_ManDumpCnf( pAbc->pGia, pFileName, fVerbose );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: &write_cnf [-Kavh] <file>\n" );
+    fprintf( pAbc->Err, "\t           writes CNF produced by a new generator\n" );
+    fprintf( pAbc->Err, "\t-K <num> : the LUT size (3 <= num <= 8) [default = %d]\n", nLutSize );
+    fprintf( pAbc->Err, "\t-a       : toggle using new algorithm [default = %s]\n", fNewAlgo? "yes" : "no" );
+    fprintf( pAbc->Err, "\t-v       : toggle printing verbose information [default = %s]\n", fVerbose? "yes" : "no" );
+    fprintf( pAbc->Err, "\t-h       : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile     : the name of the file to write\n" );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteDot( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // call the corresponding file writer
+    Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_DOT );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_dot [-h] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes the current network into a DOT file\n" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write\n" );
+    return 1;
+}
+
+ABC_NAMESPACE_IMPL_END
+
+#include "proof/fra/fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteCex( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    Abc_Ntk_t * pNtk;
+    char * pFileName;
+    int c, fNames  = 0;
+    int fMinimize  = 0;
+    int fUseOldMin = 0;
+    int fCheckCex  = 0;
+    int forceSeq   = 0;
+    int fAiger     = 0;
+    int fPrintFull = 0;
+    int fVerbose   = 0;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "snmocafvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 's':
+                forceSeq ^= 1;
+                break;
+            case 'n':
+                fNames ^= 1;
+                break;
+            case 'm':
+                fMinimize ^= 1;
+                break;
+            case 'o':
+                fUseOldMin ^= 1;
+                break;
+            case 'c':
+                fCheckCex ^= 1;
+                break;
+            case 'a':
+                fAiger ^= 1;
+                break;
+            case 'f':
+                fPrintFull ^= 1;
+                break;
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    pNtk = pAbc->pNtkCur;
+    if ( pNtk == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    if ( pNtk->pModel == NULL && pAbc->pCex == NULL )
+    {
+        fprintf( pAbc->Out, "Counter-example is not available.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+    {
+        printf( "File name is missing on the command line.\n" );
+        goto usage;
+    }
+
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    // write the counter-example into the file
+    if ( pAbc->pCex )
+    { 
+        Abc_Cex_t * pCex = pAbc->pCex;
+        Abc_Obj_t * pObj;
+        FILE * pFile;
+        int i, f;
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+            if ( !Abc_LatchIsInit0(pObj) )
+            {
+                fprintf( stdout, "IoCommandWriteCex(): The init-state should be all-0 for counter-example to work.\n" );
+                fprintf( stdout, "Run commands \"undc\" and \"zero\" and then rerun the equivalence check.\n" );
+                return 1;
+            }
+
+        pFile = fopen( pFileName, "w" );
+        if ( pFile == NULL )
+        {
+            fprintf( stdout, "IoCommandWriteCex(): Cannot open the output file \"%s\".\n", pFileName );
+            return 1;
+        }
+        if ( fPrintFull )
+        {
+            extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+            Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 );
+            Abc_Cex_t * pCexFull = Saig_ManExtendCex( pAig, pCex );
+            Aig_ManStop( pAig );
+            // output PI values (while skipping the minimized ones)
+            assert( pCexFull->nBits == Abc_NtkCiNum(pNtk) * (pCex->iFrame + 1) );
+            for ( f = 0; f <= pCex->iFrame; f++ )
+                Abc_NtkForEachCi( pNtk, pObj, i )
+                    fprintf( pFile, "%s@%d=%c ", Abc_ObjName(pObj), f, '0'+Abc_InfoHasBit(pCexFull->pData, Abc_NtkCiNum(pNtk)*f + i) );
+            Abc_CexFreeP( &pCexFull );
+        }
+        else if ( fNames )
+        {
+            Abc_Cex_t * pCare = NULL;
+            if ( fMinimize )
+            {
+                extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+                Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 );
+                if ( fUseOldMin )
+                {
+                    pCare = Saig_ManCbaFindCexCareBits( pAig, pCex, 0, fVerbose );
+                    if ( fCheckCex )
+                        Bmc_CexCareVerify( pAig, pCex, pCare, fVerbose );
+                }
+                else
+                    pCare = Bmc_CexCareMinimize( pAig, pCex, fCheckCex, fVerbose );
+                Aig_ManStop( pAig );
+            }
+            // output flop values (unaffected by the minimization)
+            Abc_NtkForEachLatch( pNtk, pObj, i )
+                fprintf( pFile, "%s@0=%c ", Abc_ObjName(Abc_ObjFanout0(pObj)), '0'+!Abc_LatchIsInit0(pObj) );
+            // output PI values (while skipping the minimized ones)
+            for ( f = 0; f <= pCex->iFrame; f++ )
+                Abc_NtkForEachPi( pNtk, pObj, i )
+                    if ( !pCare || Abc_InfoHasBit(pCare->pData, pCare->nRegs+pCare->nPis*f + i) )
+                        fprintf( pFile, "%s@%d=%c ", Abc_ObjName(pObj), f, '0'+Abc_InfoHasBit(pCex->pData, pCex->nRegs+pCex->nPis*f + i) );
+            Abc_CexFreeP( &pCare );
+        }
+        else
+        {
+            Abc_NtkForEachLatch( pNtk, pObj, i )
+                fprintf( pFile, "%c", '0'+!Abc_LatchIsInit0(pObj) );
+
+            for ( i = pCex->nRegs; i < pCex->nBits; i++ )
+            {
+                if ( fAiger && (i-pCex->nRegs)%pCex->nPis == 0)
+                    fprintf( pFile, "\n");
+                fprintf( pFile, "%c", '0'+Abc_InfoHasBit(pCex->pData, i) );
+            }
+        }
+        fprintf( pFile, "\n" );
+        fclose( pFile );
+    }
+    else
+    {
+        Abc_Obj_t * pObj;
+        FILE * pFile = fopen( pFileName, "w" );
+        int i;
+        if ( pFile == NULL )
+        {
+            fprintf( stdout, "IoCommandWriteCex(): Cannot open the output file \"%s\".\n", pFileName );
+            return 1;
+        }
+        if ( fNames )
+        {
+            const char *cycle_ctr = forceSeq?"@0":"";
+            Abc_NtkForEachPi( pNtk, pObj, i )
+//                fprintf( pFile, "%s=%c\n", Abc_ObjName(pObj), '0'+(pNtk->pModel[i]==1) );
+                fprintf( pFile, "%s%s=%c\n", Abc_ObjName(pObj), cycle_ctr, '0'+(pNtk->pModel[i]==1) );
+        }
+        else
+        {
+            Abc_NtkForEachPi( pNtk, pObj, i )
+                fprintf( pFile, "%c", '0'+(pNtk->pModel[i]==1) );
+        }
+        fprintf( pFile, "\n" );
+        fclose( pFile );
+    }
+
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_cex [-snmocfvh] <file>\n" );
+    fprintf( pAbc->Err, "\t         saves counter-example derived by \"sat\", \"iprove\", or \"dprove\"\n" );
+    fprintf( pAbc->Err, "\t         the file contains values for each PI in the natural order\n" );
+    fprintf( pAbc->Err, "\t-s     : always report a sequential ctrex (cycle 0 for comb) [default = %s]\n", forceSeq? "yes": "no" );
+    fprintf( pAbc->Err, "\t-n     : write input names into the file [default = %s]\n", fNames? "yes": "no" );
+    fprintf( pAbc->Err, "\t-m     : minimize counter-example by dropping don't-care values [default = %s]\n", fMinimize? "yes": "no" );
+    fprintf( pAbc->Err, "\t-o     : use old counter-example minimization algorithm [default = %s]\n", fUseOldMin? "yes": "no" );
+    fprintf( pAbc->Err, "\t-c     : check generated counter-example using ternary simulation [default = %s]\n", fCheckCex? "yes": "no" );
+    fprintf( pAbc->Err, "\t-a     : print cex in AIGER 1.9 format [default = %s].\n", fAiger? "yes": "no" );
+    fprintf( pAbc->Err, "\t-f     : enable printing flop values in each timeframe [default = %s].\n", fPrintFull? "yes": "no" );  
+    fprintf( pAbc->Err, "\t-v     : enable verbose output [default = %s].\n", fVerbose? "yes": "no" );  
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteEqn( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // call the corresponding file writer
+    Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_EQN );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_eqn [-h] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes the current network in the equation format\n" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteGml( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // call the corresponding file writer
+    Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_GML );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_gml [-h] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes network using graph representation formal GML\n" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteList( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+    int fUseHost;
+    int c;
+
+    printf( "This command currently does not work.\n" );
+    return 0;
+
+    fUseHost = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'n':
+                fUseHost ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+/*
+    if ( !Abc_NtkIsSeq(pAbc->pNtkCur) )
+    {
+        fprintf( stdout, "IoCommandWriteList(): Can write adjacency list for sequential AIGs only.\n" );
+        return 0;
+    }
+*/
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    // write the file
+    Io_WriteList( pAbc->pNtkCur, pFileName, fUseHost );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_list [-nh] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes network using graph representation formal GML\n" );
+    fprintf( pAbc->Err, "\t-n     : toggle writing host node [default = %s]\n", fUseHost? "yes":"no" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // call the corresponding file writer
+    Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_PLA );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_pla [-h] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes the collapsed network into a PLA file\n" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // call the corresponding file writer
+    Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_VERILOG );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_verilog [-h] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes the current network in Verilog format\n" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteSortCnf( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+    int c;
+    int nVars = 16;
+    int nQueens = 4;
+    extern void Abc_NtkWriteSorterCnf( char * pFileName, int nVars, int nQueens );
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "NQh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'N':
+                if ( globalUtilOptind >= argc )
+                {
+                    fprintf( stdout, "Command line switch \"-N\" should be followed by an integer.\n" );
+                    goto usage;
+                }
+                nVars = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( nVars <= 0 ) 
+                    goto usage;
+                break;
+            case 'Q':
+                if ( globalUtilOptind >= argc )
+                {
+                    fprintf( stdout, "Command line switch \"-Q\" should be followed by an integer.\n" );
+                    goto usage;
+                }
+                nQueens = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( nQueens <= 0 ) 
+                    goto usage;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    Abc_NtkWriteSorterCnf( pFileName, nVars, nQueens );
+    // call the corresponding file writer
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_sorter_cnf [-N <num>] [-Q <num>] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes CNF for the sorter\n" );
+    fprintf( pAbc->Err, "\t-N num : the number of sorter bits [default = %d]\n", nVars );
+    fprintf( pAbc->Err, "\t-Q num : the number of bits to be asserted to 1 [default = %d]\n", nQueens );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteTruth( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    Vec_Int_t * vTruth;
+    Abc_Ntk_t * pNtk = pAbc->pNtkCur;
+    Abc_Obj_t * pNode;
+    char * pFileName;
+    FILE * pFile;
+    unsigned * pTruth;
+    int fReverse = 0;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "rh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'r':
+                fReverse ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        printf( "Current network is not available.\n" );
+        return 0;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        printf( "Current network should not an AIG. Run \"logic\".\n" );
+        return 0;
+    }
+    if ( Abc_NtkPoNum(pNtk) != 1 )
+    {
+        printf( "Current network should have exactly one primary output.\n" );
+        return 0;
+    }
+    if ( Abc_NtkNodeNum(pNtk) != 1 )
+    {
+        printf( "Current network should have exactly one node.\n" );
+        return 0;
+    }
+    pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) );
+    if ( Abc_ObjFaninNum(pNode) == 0 )
+    { 
+        printf( "Can only write logic function with 0 inputs.\n" );
+        return 0;
+    }
+    if ( Abc_ObjFaninNum(pNode) > 16 )
+    { 
+        printf( "Can only write logic function with no more than 16 inputs.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    // convert to logic
+    Abc_NtkToAig( pNtk );
+    vTruth = Vec_IntAlloc( 0 );
+    pTruth = Hop_ManConvertAigToTruth( (Hop_Man_t *)pNtk->pManFunc, (Hop_Obj_t *)pNode->pData, Abc_ObjFaninNum(pNode), vTruth, fReverse );
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        Vec_IntFree( vTruth );
+        printf( "Cannot open file \"%s\" for writing.\n", pFileName );
+        return 0;
+    }
+    Extra_PrintBinary( pFile, pTruth, 1<<Abc_ObjFaninNum(pNode) );
+    fclose( pFile );
+    Vec_IntFree( vTruth );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_truth [-rh] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes truth table into a file\n" );
+    fprintf( pAbc->Err, "\t-r     : toggle reversing bits in the truth table [default = %s]\n", fReverse? "yes":"no" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write\n" );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteTruths( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    Gia_Obj_t * pObj;
+    char * pFileName;
+    FILE * pFile;
+    word * pTruth;
+    int nBytes;
+    int fReverse = 0;
+    int fBinary = 0;
+    int c, i;
+ 
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "rbh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'r':
+                fReverse ^= 1;
+                break;
+            case 'b':
+                fBinary ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pGia == NULL )
+    {
+        Abc_Print( -1, "IoCommandWriteTruths(): There is no AIG.\n" );
+        return 1;
+    } 
+    if ( Gia_ManPiNum(pAbc->pGia) > 16 )
+    {
+        Abc_Print( -1, "IoCommandWriteTruths(): Can write truth tables up to 16 inputs.\n" );
+        return 0;
+    }
+    if ( Gia_ManPiNum(pAbc->pGia) < 3 )
+    {
+        Abc_Print( -1, "IoCommandWriteTruths(): Can write truth tables for 3 inputs or more.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    // convert to logic
+    pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\" for writing.\n", pFileName );
+        return 0;
+    }
+    nBytes = 8 * Abc_Truth6WordNum( Gia_ManPiNum(pAbc->pGia) );
+    Gia_ManForEachCo( pAbc->pGia, pObj, i )
+    {
+        pTruth = Gia_ObjComputeTruthTable( pAbc->pGia, pObj );
+        if ( fBinary )
+            fwrite( pTruth, nBytes, 1, pFile );
+        else
+            Extra_PrintHex( pFile, (unsigned *)pTruth, Gia_ManPiNum(pAbc->pGia) ), fprintf( pFile, "\n" );
+    }
+    fclose( pFile );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: &write_truths [-rbh] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes truth tables of each PO of GIA manager into a file\n" );
+    fprintf( pAbc->Err, "\t-r     : toggle reversing bits in the truth table [default = %s]\n", fReverse? "yes":"no" );
+    fprintf( pAbc->Err, "\t-b     : toggle using binary format [default = %s]\n", fBinary? "yes":"no" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write\n" );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteStatus( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+    int c;
+    extern void Abc_NtkWriteLogFile( char * pFileName, Abc_Cex_t * pCex, int Status, int nFrames, char * pCommand );
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    Abc_NtkWriteLogFile( pFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, NULL );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_status [-h] <file>\n" );
+    fprintf( pAbc->Err, "\t         writes verification log file\n" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int IoCommandWriteSmv( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName;
+    int fUseLuts;
+    int c;
+
+    fUseLuts = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( pAbc->pNtkCur == NULL )
+    {
+        fprintf( pAbc->Out, "Empty network.\n" );
+        return 0;
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the output file name
+    pFileName = argv[globalUtilOptind];
+    // call the corresponding file writer
+    Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_SMV );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_smv [-h] <file>\n" );
+    fprintf( pAbc->Err, "\t         write the network in SMV format\n" );
+    fprintf( pAbc->Err, "\t-h     : print the help message\n" );
+    fprintf( pAbc->Err, "\tfile   : the name of the file to write (extension .smv)\n" );
+    return 1;
+}
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioAbc.h b/abc-build/src/base/io/ioAbc.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioAbc.h
@@ -0,0 +1,165 @@
+/**CFile****************************************************************
+
+  FileName    [ioAbc.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioAbc.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__base__io__ioAbc_h
+#define ABC__base__io__ioAbc_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "base/abc/abc.h"
+#include "misc/extra/extra.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// network functionality
+typedef enum { 
+    IO_FILE_NONE = 0, 
+    IO_FILE_AIGER,      
+    IO_FILE_BAF,      
+    IO_FILE_BBLIF,      
+    IO_FILE_BLIF,      
+    IO_FILE_BLIFMV,      
+    IO_FILE_BENCH,      
+    IO_FILE_BOOK,
+    IO_FILE_CNF,      
+    IO_FILE_DOT,      
+    IO_FILE_EDIF,      
+    IO_FILE_EQN,      
+    IO_FILE_GML,      
+    IO_FILE_LIST,      
+    IO_FILE_PLA,      
+    IO_FILE_SMV,      
+    IO_FILE_VERILOG,    
+    IO_FILE_UNKNOWN       
+} Io_FileType_t;
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define  IO_WRITE_LINE_LENGTH    78    // the output line length
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== abcReadAiger.c ==========================================================*/
+extern Abc_Ntk_t *        Io_ReadAiger( char * pFileName, int fCheck );
+/*=== abcReadBaf.c ============================================================*/
+extern Abc_Ntk_t *        Io_ReadBaf( char * pFileName, int fCheck );
+/*=== abcReadBblif.c ============================================================*/
+extern Abc_Ntk_t *        Io_ReadBblif( char * pFileName, int fCheck );
+/*=== abcReadBlif.c ===========================================================*/
+extern Abc_Ntk_t *        Io_ReadBlif( char * pFileName, int fCheck );
+/*=== abcReadBlifMv.c =========================================================*/
+extern Abc_Ntk_t *        Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck );
+/*=== abcReadBench.c ==========================================================*/
+extern Abc_Ntk_t *        Io_ReadBench( char * pFileName, int fCheck );
+extern void               Io_ReadBenchInit( Abc_Ntk_t * pNtk, char * pFileName );
+/*=== abcReadEdif.c ===========================================================*/
+extern Abc_Ntk_t *        Io_ReadEdif( char * pFileName, int fCheck );
+/*=== abcReadEqn.c ============================================================*/
+extern Abc_Ntk_t *        Io_ReadEqn( char * pFileName, int fCheck );
+/*=== abcReadPla.c ============================================================*/
+extern Abc_Ntk_t *        Io_ReadPla( char * pFileName, int fZeros, int fCheck );
+/*=== abcReadVerilog.c ========================================================*/
+extern Abc_Ntk_t *        Io_ReadVerilog( char * pFileName, int fCheck );
+/*=== abcWriteAiger.c =========================================================*/
+extern void               Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols, int fCompact, int fUnique );
+extern void               Io_WriteAigerCex( Abc_Cex_t * pCex, Abc_Ntk_t * pNtk, void * pG, char * pFileName );
+/*=== abcWriteBaf.c ===========================================================*/
+extern void               Io_WriteBaf( Abc_Ntk_t * pNtk, char * pFileName );
+/*=== abcWriteBblif.c ===========================================================*/
+extern void               Io_WriteBblif( Abc_Ntk_t * pNtk, char * pFileName );
+/*=== abcWriteBlif.c ==========================================================*/
+extern void               Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches );
+extern void               Io_WriteBlif( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches, int fBb2Wb, int fSeq );
+extern void               Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk );
+extern void               Io_WriteBlifSpecial( Abc_Ntk_t * pNtk, char * FileName, char * pLutStruct, int fUseHie );
+/*=== abcWriteBlifMv.c ==========================================================*/ 
+extern void               Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName );
+/*=== abcWriteBench.c =========================================================*/
+extern int                Io_WriteBench( Abc_Ntk_t * pNtk, const char * FileName );
+extern int                Io_WriteBenchLut( Abc_Ntk_t * pNtk, char * FileName );
+/*=== abcWriteBook.c =========================================================*/
+extern void               Io_WriteBook( Abc_Ntk_t * pNtk, char * FileName );
+/*=== abcWriteCnf.c ===========================================================*/
+extern int                Io_WriteCnf( Abc_Ntk_t * pNtk, char * FileName, int fAllPrimes );
+/*=== abcWriteDot.c ===========================================================*/
+extern void               Io_WriteDot( Abc_Ntk_t * pNtk, char * FileName );
+extern void               Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse );
+extern void               Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse );
+/*=== abcWriteEqn.c ===========================================================*/
+extern void               Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName );
+/*=== abcWriteGml.c ===========================================================*/
+extern void               Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName );
+/*=== abcWriteList.c ==========================================================*/
+extern void               Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost );
+/*=== abcWritePla.c ===========================================================*/
+extern int                Io_WritePla( Abc_Ntk_t * pNtk, char * FileName );
+/*=== abcWriteSmv.c ===========================================================*/
+extern int                Io_WriteSmv( Abc_Ntk_t * pNtk, char * FileName );
+/*=== abcWriteVerilog.c =======================================================*/
+extern void               Io_WriteVerilog( Abc_Ntk_t * pNtk, char * FileName );
+/*=== abcUtil.c ===============================================================*/
+extern Io_FileType_t      Io_ReadFileType( char * pFileName );
+extern Io_FileType_t      Io_ReadLibType( char * pFileName );
+extern Abc_Ntk_t *        Io_ReadNetlist( char * pFileName, Io_FileType_t FileType, int fCheck );
+extern Abc_Ntk_t *        Io_Read( char * pFileName, Io_FileType_t FileType, int fCheck, int fBarBufs );
+extern void               Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType );
+extern void               Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName );
+extern Abc_Obj_t *        Io_ReadCreatePi( Abc_Ntk_t * pNtk, char * pName );
+extern Abc_Obj_t *        Io_ReadCreatePo( Abc_Ntk_t * pNtk, char * pName );
+extern Abc_Obj_t *        Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO );
+extern Abc_Obj_t *        Io_ReadCreateResetLatch( Abc_Ntk_t * pNtk, int fBlifMv );
+extern Abc_Obj_t *        Io_ReadCreateResetMux( Abc_Ntk_t * pNtk, char * pResetLO, char * pDataLI, int fBlifMv );
+extern Abc_Obj_t *        Io_ReadCreateNode( Abc_Ntk_t * pNtk, char * pNameOut, char * pNamesIn[], int nInputs );
+extern Abc_Obj_t *        Io_ReadCreateConst( Abc_Ntk_t * pNtk, char * pName, int fConst1 );
+extern Abc_Obj_t *        Io_ReadCreateInv( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut );
+extern Abc_Obj_t *        Io_ReadCreateBuf( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut );
+extern FILE *             Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose );
+
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/base/io/ioInt.h b/abc-build/src/base/io/ioInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioInt.h
@@ -0,0 +1,57 @@
+/**CFile****************************************************************
+
+  FileName    [ioInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__base__io__ioInt_h
+#define ABC__base__io__ioInt_h
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/base/io/ioReadAiger.c b/abc-build/src/base/io/ioReadAiger.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioReadAiger.c
@@ -0,0 +1,599 @@
+/**CFile****************************************************************
+
+  FileName    [ioReadAiger.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to read binary AIGER format developed by
+  Armin Biere, Johannes Kepler University (http://fmv.jku.at/)]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - December 16, 2006.]
+
+  Revision    [$Id: ioReadAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+// The code in this file is developed in collaboration with Mark Jarvin of Toronto.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/bzlib/bzlib.h"
+#include "misc/zlib/zlib.h"
+#include "ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Extracts one unsigned AIG edge from the input buffer.]
+
+  Description [This procedure is a slightly modified version of Armin Biere's
+  procedure "unsigned decode (FILE * file)". ]
+  
+  SideEffects [Updates the current reading position.]
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Io_ReadAigerDecode( char ** ppPos )
+{
+    unsigned x = 0, i = 0;
+    unsigned char ch;
+
+//    while ((ch = getnoneofch (file)) & 0x80)
+    while ((ch = *(*ppPos)++) & 0x80)
+        x |= (ch & 0x7f) << (7 * i++);
+
+    return x | (ch << (7 * i));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Decodes the encoded array of literals.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Io_WriteDecodeLiterals( char ** ppPos, int nEntries )
+{
+    Vec_Int_t * vLits;
+    int Lit, LitPrev, Diff, i;
+    vLits = Vec_IntAlloc( nEntries );
+    LitPrev = Io_ReadAigerDecode( ppPos );
+    Vec_IntPush( vLits, LitPrev );
+    for ( i = 1; i < nEntries; i++ )
+    {
+//        Diff = Lit - LitPrev;
+//        Diff = (Lit < LitPrev)? -Diff : Diff;
+//        Diff = ((2 * Diff) << 1) | (int)(Lit < LitPrev);
+        Diff = Io_ReadAigerDecode( ppPos );
+        Diff = (Diff & 1)? -(Diff >> 1) : Diff >> 1;
+        Lit  = Diff + LitPrev;
+        Vec_IntPush( vLits, Lit );
+        LitPrev = Lit;
+    }
+    return vLits;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the file into a character buffer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+typedef struct buflist {
+  char buf[1<<20];
+  int nBuf;
+  struct buflist * next;
+} buflist;
+
+static char * Ioa_ReadLoadFileBz2Aig( char * pFileName, int * pFileSize )
+{
+    FILE    * pFile;
+    int       nFileSize = 0;
+    char    * pContents;
+    BZFILE  * b;
+    int       bzError;
+    struct buflist * pNext;
+    buflist * bufHead = NULL, * buf = NULL;
+    int RetValue;
+
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Ioa_ReadLoadFileBz2(): The file is unavailable (absent or open).\n" );
+        return NULL;
+    }
+    b = BZ2_bzReadOpen(&bzError,pFile,0,0,NULL,0);
+    if (bzError != BZ_OK) {
+        printf( "Ioa_ReadLoadFileBz2(): BZ2_bzReadOpen() failed with error %d.\n",bzError );
+        return NULL;
+    }
+    do {
+        if (!bufHead)
+            buf = bufHead = ABC_ALLOC( buflist, 1 );
+        else
+            buf = buf->next = ABC_ALLOC( buflist, 1 );
+        nFileSize += buf->nBuf = BZ2_bzRead(&bzError,b,buf->buf,1<<20);
+        buf->next = NULL;
+    } while (bzError == BZ_OK);
+    if (bzError == BZ_STREAM_END) {
+        // we're okay
+        char * p;
+        int nBytes = 0;
+        BZ2_bzReadClose(&bzError,b);
+        p = pContents = ABC_ALLOC( char, nFileSize + 10 );
+        buf = bufHead;
+        do {
+            memcpy(p+nBytes,buf->buf,buf->nBuf);
+            nBytes += buf->nBuf;
+//        } while((buf = buf->next));
+            pNext = buf->next;
+            ABC_FREE( buf );
+        } while((buf = pNext));
+    } else if (bzError == BZ_DATA_ERROR_MAGIC) {
+        // not a BZIP2 file
+        BZ2_bzReadClose(&bzError,b);
+        fseek( pFile, 0, SEEK_END );
+        nFileSize = ftell( pFile );
+        if ( nFileSize == 0 )
+        {
+            printf( "Ioa_ReadLoadFileBz2(): The file is empty.\n" );
+            return NULL;
+        }
+        pContents = ABC_ALLOC( char, nFileSize + 10 );
+        rewind( pFile );
+        RetValue = fread( pContents, nFileSize, 1, pFile );
+    } else { 
+        // Some other error.
+        printf( "Ioa_ReadLoadFileBz2(): Unable to read the compressed BLIF.\n" );
+        return NULL;
+    }
+    fclose( pFile );
+    // finish off the file with the spare .end line
+    // some benchmarks suddenly break off without this line
+//    strcpy( pContents + nFileSize, "\n.end\n" );
+    *pFileSize = nFileSize;
+    return pContents;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the file into a character buffer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static char * Ioa_ReadLoadFileGzAig( char * pFileName, int * pFileSize )
+{
+    const int READ_BLOCK_SIZE = 100000;
+    gzFile pFile;
+    char * pContents;
+    int amtRead, readBlock, nFileSize = READ_BLOCK_SIZE;
+    pFile = gzopen( pFileName, "rb" ); // if pFileName doesn't end in ".gz" then this acts as a passthrough to fopen
+    pContents = ABC_ALLOC( char, nFileSize );        
+    readBlock = 0;
+    while ((amtRead = gzread(pFile, pContents + readBlock * READ_BLOCK_SIZE, READ_BLOCK_SIZE)) == READ_BLOCK_SIZE) {
+        //printf("%d: read %d bytes\n", readBlock, amtRead);
+        nFileSize += READ_BLOCK_SIZE;
+        pContents = ABC_REALLOC(char, pContents, nFileSize);
+        ++readBlock;
+    }
+    //printf("%d: read %d bytes\n", readBlock, amtRead);
+    assert( amtRead != -1 ); // indicates a zlib error
+    nFileSize -= (READ_BLOCK_SIZE - amtRead);
+    gzclose(pFile);
+    *pFileSize = nFileSize;
+    return pContents;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the AIG in the binary AIGER format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck )
+{
+    ProgressBar * pProgress;
+    FILE * pFile;
+    Vec_Ptr_t * vNodes, * vTerms;
+    Vec_Int_t * vLits = NULL;
+    Abc_Obj_t * pObj, * pNode0, * pNode1;
+    Abc_Ntk_t * pNtkNew;
+    int nTotal, nInputs, nOutputs, nLatches, nAnds;
+    int nBad = 0, nConstr = 0, nJust = 0, nFair = 0;
+    int nFileSize = -1, iTerm, nDigits, i;
+    char * pContents, * pDrivers = NULL, * pSymbols, * pCur, * pName, * pType;
+    unsigned uLit0, uLit1, uLit;
+    int RetValue;
+
+    // read the file into the buffer
+    if ( !strncmp(pFileName+strlen(pFileName)-4,".bz2",4) )
+        pContents = Ioa_ReadLoadFileBz2Aig( pFileName, &nFileSize );
+    else if ( !strncmp(pFileName+strlen(pFileName)-3,".gz",3) )
+        pContents = Ioa_ReadLoadFileGzAig( pFileName, &nFileSize );
+    else
+    {
+//        pContents = Ioa_ReadLoadFile( pFileName );
+        nFileSize = Extra_FileSize( pFileName );
+        pFile = fopen( pFileName, "rb" );
+        pContents = ABC_ALLOC( char, nFileSize );
+        RetValue = fread( pContents, nFileSize, 1, pFile );
+        fclose( pFile );
+    }
+
+
+    // check if the input file format is correct
+    if ( strncmp(pContents, "aig", 3) != 0 || (pContents[3] != ' ' && pContents[3] != '2') )
+    {
+        fprintf( stdout, "Wrong input file format.\n" );
+        ABC_FREE( pContents );
+        return NULL;
+    }
+
+    // read the parameters (M I L O A + B C J F)
+    pCur = pContents;         while ( *pCur != ' ' ) pCur++; pCur++;
+    // read the number of objects
+    nTotal = atoi( pCur );    while ( *pCur != ' ' ) pCur++; pCur++;
+    // read the number of inputs
+    nInputs = atoi( pCur );   while ( *pCur != ' ' ) pCur++; pCur++;
+    // read the number of latches
+    nLatches = atoi( pCur );  while ( *pCur != ' ' ) pCur++; pCur++;
+    // read the number of outputs
+    nOutputs = atoi( pCur );  while ( *pCur != ' ' ) pCur++; pCur++;
+    // read the number of nodes
+    nAnds = atoi( pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
+    if ( *pCur == ' ' )
+    {
+//        assert( nOutputs == 0 );
+        // read the number of properties
+        pCur++;
+        nBad = atoi( pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
+        nOutputs += nBad;
+    }
+    if ( *pCur == ' ' )
+    {
+        // read the number of properties
+        pCur++;
+        nConstr = atoi( pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
+        nOutputs += nConstr;
+    }
+    if ( *pCur == ' ' )
+    {
+        // read the number of properties
+        pCur++;
+        nJust = atoi( pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
+        nOutputs += nJust;
+    }
+    if ( *pCur == ' ' )
+    {
+        // read the number of properties
+        pCur++;
+        nFair = atoi( pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
+        nOutputs += nFair;
+    }
+    if ( *pCur != '\n' )
+    {
+        fprintf( stdout, "The parameter line is in a wrong format.\n" );
+        ABC_FREE( pContents );
+        return NULL;
+    }
+    pCur++;
+
+    // check the parameters
+    if ( nTotal != nInputs + nLatches + nAnds )
+    {
+        fprintf( stdout, "The number of objects does not match.\n" );
+        ABC_FREE( pContents );
+        return NULL;
+    }
+    if ( nJust || nFair )
+    {
+        fprintf( stdout, "Reading AIGER files with liveness properties is currently not supported.\n" );
+        ABC_FREE( pContents );
+        return NULL;
+    }
+
+    if ( nConstr )
+    {
+        if ( nConstr == 1 )
+            fprintf( stdout, "Warning: The last output is interpreted as a constraint.\n" );
+        else
+            fprintf( stdout, "Warning: The last %d outputs are interpreted as constraints.\n", nConstr );
+    }
+
+    // allocate the empty AIG
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    pName = Extra_FileNameGeneric( pFileName );
+    pNtkNew->pName = Extra_UtilStrsav( pName );
+    pNtkNew->pSpec = Extra_UtilStrsav( pFileName );
+    ABC_FREE( pName );
+    pNtkNew->nConstrs = nConstr;
+
+    // prepare the array of nodes
+    vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds );
+    Vec_PtrPush( vNodes, Abc_ObjNot( Abc_AigConst1(pNtkNew) ) );
+
+    // create the PIs
+    for ( i = 0; i < nInputs; i++ )
+    {
+        pObj = Abc_NtkCreatePi(pNtkNew);    
+        Vec_PtrPush( vNodes, pObj );
+    }
+    // create the POs
+    for ( i = 0; i < nOutputs; i++ )
+    {
+        pObj = Abc_NtkCreatePo(pNtkNew);   
+    }
+    // create the latches
+    nDigits = Abc_Base10Log( nLatches );
+    for ( i = 0; i < nLatches; i++ )
+    {
+        pObj = Abc_NtkCreateLatch(pNtkNew);
+        Abc_LatchSetInit0( pObj );
+        pNode0 = Abc_NtkCreateBi(pNtkNew);
+        pNode1 = Abc_NtkCreateBo(pNtkNew);
+        Abc_ObjAddFanin( pObj, pNode0 );
+        Abc_ObjAddFanin( pNode1, pObj );
+        Vec_PtrPush( vNodes, pNode1 );
+        // assign names to latch and its input
+//        Abc_ObjAssignName( pObj, Abc_ObjNameDummy("_L", i, nDigits), NULL );
+//        printf( "Creating latch %s with input %d and output %d.\n", Abc_ObjName(pObj), pNode0->Id, pNode1->Id );
+    } 
+    
+
+    if ( pContents[3] == ' ' ) // standard AIGER
+    {
+        // remember the beginning of latch/PO literals
+        pDrivers = pCur;
+        // scroll to the beginning of the binary data
+        for ( i = 0; i < nLatches + nOutputs; )
+            if ( *pCur++ == '\n' )
+                i++;
+    }
+    else // modified AIGER
+    { 
+        vLits = Io_WriteDecodeLiterals( &pCur, nLatches + nOutputs );
+    }
+
+    // create the AND gates
+    pProgress = Extra_ProgressBarStart( stdout, nAnds );
+    for ( i = 0; i < nAnds; i++ )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        uLit = ((i + 1 + nInputs + nLatches) << 1);
+        uLit1 = uLit  - Io_ReadAigerDecode( &pCur );
+        uLit0 = uLit1 - Io_ReadAigerDecode( &pCur );
+//        assert( uLit1 > uLit0 );
+        pNode0 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), uLit0 & 1 );
+        pNode1 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, uLit1 >> 1), uLit1 & 1 );
+        assert( Vec_PtrSize(vNodes) == i + 1 + nInputs + nLatches );
+        Vec_PtrPush( vNodes, Abc_AigAnd((Abc_Aig_t *)pNtkNew->pManFunc, pNode0, pNode1) );
+    }
+    Extra_ProgressBarStop( pProgress );
+
+    // remember the place where symbols begin
+    pSymbols = pCur;
+
+    // read the latch driver literals
+    pCur = pDrivers;
+    if ( pContents[3] == ' ' ) // standard AIGER
+    {
+        Abc_NtkForEachLatchInput( pNtkNew, pObj, i )
+        {
+            uLit0 = atoi( pCur );  while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
+            if ( *pCur == ' ' ) // read initial value
+            {
+                int Init;
+                pCur++;
+                Init = atoi( pCur );
+                if ( Init == 0 )
+                    Abc_LatchSetInit0( Abc_NtkBox(pNtkNew, i) );
+                else if ( Init == 1 )
+                    Abc_LatchSetInit1( Abc_NtkBox(pNtkNew, i) );
+                else 
+                {
+                    assert( Init == Abc_Var2Lit(1+Abc_NtkPiNum(pNtkNew)+i, 0) ); 
+                    // unitialized value of the latch is the latch literal according to http://fmv.jku.at/hwmcc11/beyond1.pdf
+                    Abc_LatchSetInitDc( Abc_NtkBox(pNtkNew, i) );
+                }
+                while ( *pCur != ' ' && *pCur != '\n' ) pCur++;
+            }
+            if ( *pCur != '\n' )
+            {
+                fprintf( stdout, "The initial value of latch number %d is not recongnized.\n", i );
+                return NULL;
+            }
+            pCur++;
+
+            pNode0 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) );
+            Abc_ObjAddFanin( pObj, pNode0 );
+        }
+        // read the PO driver literals
+        Abc_NtkForEachPo( pNtkNew, pObj, i )
+        {
+            uLit0 = atoi( pCur );  while ( *pCur++ != '\n' );
+            pNode0 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) );
+            Abc_ObjAddFanin( pObj, pNode0 );
+        }
+    }
+    else
+    {
+        // read the latch driver literals
+        Abc_NtkForEachLatchInput( pNtkNew, pObj, i )
+        {
+            uLit0 = Vec_IntEntry( vLits, i );
+            pNode0 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );
+            Abc_ObjAddFanin( pObj, pNode0 );
+        }
+        // read the PO driver literals
+        Abc_NtkForEachPo( pNtkNew, pObj, i )
+        {
+            uLit0 = Vec_IntEntry( vLits, i+Abc_NtkLatchNum(pNtkNew) );
+            pNode0 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );
+            Abc_ObjAddFanin( pObj, pNode0 );
+        }
+        Vec_IntFree( vLits );
+    }
+ 
+    // read the names if present
+    pCur = pSymbols;
+    if ( *pCur != 'c' )
+    {
+        int Counter = 0;
+        while ( pCur < pContents + nFileSize && *pCur != 'c' )
+        {
+            // get the terminal type
+            pType = pCur;
+            if ( *pCur == 'i' )
+                vTerms = pNtkNew->vPis;
+            else if ( *pCur == 'l' )
+                vTerms = pNtkNew->vBoxes;
+            else if ( *pCur == 'o' || *pCur == 'b' || *pCur == 'c' || *pCur == 'j' || *pCur == 'f' )
+                vTerms = pNtkNew->vPos;
+            else
+            {
+//                fprintf( stdout, "Wrong terminal type.\n" );
+                return NULL;
+            }
+            // get the terminal number
+            iTerm = atoi( ++pCur );  while ( *pCur++ != ' ' );
+            // get the node
+            if ( iTerm >= Vec_PtrSize(vTerms) )
+            {
+                fprintf( stdout, "The number of terminal is out of bound.\n" );
+                return NULL;
+            }
+            pObj = (Abc_Obj_t *)Vec_PtrEntry( vTerms, iTerm );
+            if ( *pType == 'l' )
+                pObj = Abc_ObjFanout0(pObj);
+            // assign the name
+            pName = pCur;          while ( *pCur++ != '\n' );
+            // assign this name 
+            *(pCur-1) = 0;
+            Abc_ObjAssignName( pObj, pName, NULL );
+            if ( *pType == 'l' )
+            {
+                Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjName(pObj), "L" );
+                Abc_ObjAssignName( Abc_ObjFanin0(Abc_ObjFanin0(pObj)), Abc_ObjName(pObj), "_in" );
+            }
+            // mark the node as named
+            pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj);
+        } 
+
+        // assign the remaining names
+        Abc_NtkForEachPi( pNtkNew, pObj, i )
+        {
+            if ( pObj->pCopy ) continue;
+            Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL );
+            Counter++;
+        }
+        Abc_NtkForEachLatchOutput( pNtkNew, pObj, i )
+        {
+            if ( pObj->pCopy ) continue;
+            Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL );
+            Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjName(pObj), "L" );
+            Abc_ObjAssignName( Abc_ObjFanin0(Abc_ObjFanin0(pObj)), Abc_ObjName(pObj), "_in" );
+            Counter++;
+        }
+        Abc_NtkForEachPo( pNtkNew, pObj, i )
+        {
+            if ( pObj->pCopy ) continue;
+            Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL );
+            Counter++;
+        }
+//        if ( Counter )
+//            printf( "Io_ReadAiger(): Added %d default names for nameless I/O/register objects.\n", Counter );
+    }
+    else
+    {
+//        printf( "Io_ReadAiger(): I/O/register names are not given. Generating short names.\n" );
+        Abc_NtkShortNames( pNtkNew );
+    }
+
+    // read the name of the model if given
+    pCur = pSymbols;
+    if ( pCur + 1 < pContents + nFileSize && *pCur == 'c' )
+    {
+        pCur++;
+        if ( *pCur == 'n' )
+        {
+            pCur++;
+            // read model name
+            if ( strlen(pCur) > 0 )
+            {
+                ABC_FREE( pNtkNew->pName );
+                pNtkNew->pName = Extra_UtilStrsav( pCur );
+            }
+        }
+    }
+
+    // skipping the comments
+    ABC_FREE( pContents );
+    Vec_PtrFree( vNodes );
+
+    // remove the extra nodes
+    Abc_AigCleanup( (Abc_Aig_t *)pNtkNew->pManFunc );
+
+    // update polarity of the additional outputs
+    if ( nBad || nConstr || nJust || nFair )
+        Abc_NtkInvertConstraints( pNtkNew );
+
+    // check the result
+    if ( fCheck && !Abc_NtkCheckRead( pNtkNew ) )
+    {
+        printf( "Io_ReadAiger: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioReadBaf.c b/abc-build/src/base/io/ioReadBaf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioReadBaf.c
@@ -0,0 +1,177 @@
+/**CFile****************************************************************
+
+  FileName    [ioReadBaf.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to read AIG in the binary format.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioReadBaf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the AIG in the binary format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadBaf( char * pFileName, int fCheck )
+{
+    ProgressBar * pProgress;
+    FILE * pFile;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj, * pNode0, * pNode1;
+    Abc_Ntk_t * pNtkNew;
+    int nInputs, nOutputs, nLatches, nAnds, nFileSize, Num, i;
+    char * pContents, * pName, * pCur;
+    unsigned * pBufferNode;
+    int RetValue;
+
+    // read the file into the buffer
+    nFileSize = Extra_FileSize( pFileName );
+    pFile = fopen( pFileName, "rb" );
+    pContents = ABC_ALLOC( char, nFileSize );
+    RetValue = fread( pContents, nFileSize, 1, pFile );
+    fclose( pFile );
+
+    // skip the comments (comment lines begin with '#' and end with '\n')
+    for ( pCur = pContents; *pCur == '#'; )
+        while ( *pCur++ != '\n' );
+
+    // read the name
+    pName = pCur;             while ( *pCur++ );
+    // read the number of inputs
+    nInputs = atoi( pCur );   while ( *pCur++ );
+    // read the number of outputs
+    nOutputs = atoi( pCur );  while ( *pCur++ );
+    // read the number of latches
+    nLatches = atoi( pCur );  while ( *pCur++ );
+    // read the number of nodes
+    nAnds = atoi( pCur );     while ( *pCur++ );
+
+    // allocate the empty AIG
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    pNtkNew->pName = Extra_UtilStrsav( pName );
+    pNtkNew->pSpec = Extra_UtilStrsav( pFileName );
+
+    // prepare the array of nodes
+    vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds );
+    Vec_PtrPush( vNodes, Abc_AigConst1(pNtkNew) );
+
+    // create the PIs
+    for ( i = 0; i < nInputs; i++ )
+    {
+        pObj = Abc_NtkCreatePi(pNtkNew);    
+        Abc_ObjAssignName( pObj, pCur, NULL );  while ( *pCur++ );
+        Vec_PtrPush( vNodes, pObj );
+    }
+    // create the POs
+    for ( i = 0; i < nOutputs; i++ )
+    {
+        pObj = Abc_NtkCreatePo(pNtkNew);   
+        Abc_ObjAssignName( pObj, pCur, NULL );  while ( *pCur++ ); 
+    }
+    // create the latches
+    for ( i = 0; i < nLatches; i++ )
+    {
+        pObj = Abc_NtkCreateLatch(pNtkNew);
+        Abc_ObjAssignName( pObj, pCur, NULL );  while ( *pCur++ ); 
+
+        pNode0 = Abc_NtkCreateBi(pNtkNew);
+        Abc_ObjAssignName( pNode0, pCur, NULL );  while ( *pCur++ ); 
+
+        pNode1 = Abc_NtkCreateBo(pNtkNew);
+        Abc_ObjAssignName( pNode1, pCur, NULL );  while ( *pCur++ ); 
+        Vec_PtrPush( vNodes, pNode1 );
+
+        Abc_ObjAddFanin( pObj, pNode0 );
+        Abc_ObjAddFanin( pNode1, pObj );
+    }
+
+    // get the pointer to the beginning of the node array
+    pBufferNode = (unsigned *)(pContents + (nFileSize - (2 * nAnds + nOutputs + nLatches) * sizeof(int)) );
+    // make sure we are at the place where the nodes begin
+    if ( pBufferNode != (unsigned *)pCur )
+    {
+        ABC_FREE( pContents );
+        Vec_PtrFree( vNodes );
+        Abc_NtkDelete( pNtkNew );
+        printf( "Warning: Internal reader error.\n" );
+        return NULL;
+    }
+
+    // create the AND gates
+    pProgress = Extra_ProgressBarStart( stdout, nAnds );
+    for ( i = 0; i < nAnds; i++ )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        pNode0 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, pBufferNode[2*i+0] >> 1), pBufferNode[2*i+0] & 1 );
+        pNode1 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, pBufferNode[2*i+1] >> 1), pBufferNode[2*i+1] & 1 );
+        Vec_PtrPush( vNodes, Abc_AigAnd((Abc_Aig_t *)pNtkNew->pManFunc, pNode0, pNode1) );
+    }
+    Extra_ProgressBarStop( pProgress );
+
+    // read the POs
+    Abc_NtkForEachCo( pNtkNew, pObj, i )
+    {
+        Num = pBufferNode[2*nAnds+i];
+        if ( Abc_ObjFanoutNum(pObj) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) )
+        {
+            Abc_ObjSetData( Abc_ObjFanout0(pObj), (void *)(ABC_PTRINT_T)(Num & 3) );
+            Num >>= 2;
+        }
+        pNode0 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, Num >> 1), Num & 1 );
+        Abc_ObjAddFanin( pObj, pNode0 );
+    }
+    ABC_FREE( pContents );
+    Vec_PtrFree( vNodes );
+
+    // remove the extra nodes
+//    Abc_AigCleanup( (Abc_Aig_t *)pNtkNew->pManFunc );
+
+    // check the result
+    if ( fCheck && !Abc_NtkCheckRead( pNtkNew ) )
+    {
+        printf( "Io_ReadBaf: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioReadBblif.c b/abc-build/src/base/io/ioReadBblif.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioReadBblif.c
@@ -0,0 +1,348 @@
+/**CFile****************************************************************
+
+  FileName    [ioReadBblif.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to read AIG in the binary format.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioReadBblif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+#include "bool/dec/dec.h"
+#include "misc/bbl/bblif.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+// For description of Binary BLIF format, refer to "abc/src/aig/bbl/bblif.h"
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Fnction*************************************************************
+
+  Synopsis    [Constructs ABC network from the manager.]
+
+  Description [The ABC network is started, as well as the array vCopy,
+  which will map the new ID of each object in the BBLIF manager into
+  the ponter ot the corresponding object in the ABC. For each internal
+  node, determined by Bbl_ObjIsLut(), the SOP representation is created
+  by retrieving the SOP representation of the BBLIF object. Finally,
+  the objects are connected using fanin/fanout creation, and the dummy
+  names are assigned because ABC requires each CI/CO to have a name.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Bbl_ManToAbc( Bbl_Man_t * p )
+{
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pObjNew;
+    Bbl_Obj_t * pObj, * pFanin;
+    Vec_Ptr_t * vCopy;
+    // start the network
+    pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+    pNtk->pName = Extra_UtilStrsav( Bbl_ManName(p) );
+    // create objects
+    vCopy = Vec_PtrStart( 1000 );
+    Bbl_ManForEachObj( p, pObj )
+    {
+        if ( Bbl_ObjIsInput(pObj) )
+            pObjNew = Abc_NtkCreatePi( pNtk );
+        else if ( Bbl_ObjIsOutput(pObj) )
+            pObjNew = Abc_NtkCreatePo( pNtk );
+        else if ( Bbl_ObjIsLut(pObj) )
+            pObjNew = Abc_NtkCreateNode( pNtk );
+        else assert( 0 );
+        if ( Bbl_ObjIsLut(pObj) )
+            pObjNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, Bbl_ObjSop(p, pObj) );
+        Vec_PtrSetEntry( vCopy, Bbl_ObjId(pObj), pObjNew );
+    }
+    // connect objects
+    Bbl_ManForEachObj( p, pObj )
+        Bbl_ObjForEachFanin( pObj, pFanin )
+            Abc_ObjAddFanin( (Abc_Obj_t *)Vec_PtrEntry(vCopy, Bbl_ObjId(pObj)), (Abc_Obj_t *)Vec_PtrEntry(vCopy, Bbl_ObjId(pFanin)) );
+    // finalize
+    Vec_PtrFree( vCopy );
+    Abc_NtkAddDummyPiNames( pNtk );
+    Abc_NtkAddDummyPoNames( pNtk );
+    if ( !Abc_NtkCheck( pNtk ) )
+        printf( "Bbl_ManToAbc(): Network check has failed.\n" );
+    return pNtk;
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Collects internal nodes in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbl_ManDfs_rec( Bbl_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    extern void Bbl_ObjMark( Bbl_Obj_t * p );
+    extern int  Bbl_ObjIsMarked( Bbl_Obj_t * p );
+    Bbl_Obj_t * pFanin;
+    if ( Bbl_ObjIsMarked(pObj) || Bbl_ObjIsInput(pObj) )
+        return;
+    Bbl_ObjForEachFanin( pObj, pFanin )
+        Bbl_ManDfs_rec( pFanin, vNodes );
+    assert( !Bbl_ObjIsMarked(pObj) ); // checks if acyclic
+    Bbl_ObjMark( pObj );
+    Vec_PtrPush( vNodes, pObj );
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Collects internal nodes in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Bbl_ManDfs( Bbl_Man_t * p )
+{
+    Vec_Ptr_t * vNodes;
+    Bbl_Obj_t * pObj;
+    vNodes = Vec_PtrAlloc( 1000 );
+    Bbl_ManForEachObj( p, pObj )
+        if ( Bbl_ObjIsLut(pObj) )
+            Bbl_ManDfs_rec( pObj, vNodes );
+    return vNodes;
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Constructs AIG in ABC from the manager.]
+
+  Description [The ABC network is started, as well as the array vCopy,
+  which will map the new ID of each object in the BBLIF manager into
+  the ponter ot the corresponding AIG object in the ABC. For each internal
+  node in a topological oder the AIG representation is created
+  by factoring the SOP representation of the BBLIF object. Finally,
+  the CO objects are created, and the dummy names are assigned because 
+  ABC requires each CI/CO to have a name.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Bbl_ManToAig( Bbl_Man_t * p )
+{
+    extern int Bbl_ManFncSize( Bbl_Man_t * p );
+    extern int Bbl_ObjFncHandle( Bbl_Obj_t * p );
+    extern Abc_Obj_t * Dec_GraphToAig( Abc_Ntk_t * pNtk, Dec_Graph_t * pFForm, Vec_Ptr_t * vFaninAigs );
+    int fVerbose = 0;
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pObjNew;
+    Bbl_Obj_t * pObj, * pFanin;
+    Vec_Ptr_t * vCopy, * vNodes, * vFaninAigs;
+    Dec_Graph_t ** pFForms;
+    int i;
+    abctime clk;
+clk = Abc_Clock();
+    // map SOP handles into factored forms
+    pFForms = ABC_CALLOC( Dec_Graph_t *, Bbl_ManFncSize(p) );
+    Bbl_ManForEachObj( p, pObj )
+        if ( pFForms[Bbl_ObjFncHandle(pObj)] == NULL )
+            pFForms[Bbl_ObjFncHandle(pObj)] = Dec_Factor( Bbl_ObjSop(p, pObj) );
+if ( fVerbose )
+ABC_PRT( "Fct", Abc_Clock() - clk );
+    // start the network
+    pNtk = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    pNtk->pName = Extra_UtilStrsav( Bbl_ManName(p) );
+    vCopy = Vec_PtrStart( 1000 );
+    // create CIs
+    Bbl_ManForEachObj( p, pObj )
+    {
+        if ( !Bbl_ObjIsInput(pObj) )
+            continue;
+        Vec_PtrSetEntry( vCopy, Bbl_ObjId(pObj), Abc_NtkCreatePi(pNtk) );
+    }
+clk = Abc_Clock();
+    // create internal nodes
+    vNodes = Bbl_ManDfs( p );
+    vFaninAigs = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Bbl_Obj_t *, vNodes, pObj, i )
+    {
+        // collect fanin AIGs
+        Vec_PtrClear( vFaninAigs );
+        Bbl_ObjForEachFanin( pObj, pFanin )
+            Vec_PtrPush( vFaninAigs, Vec_PtrEntry( vCopy, Bbl_ObjId(pFanin) ) );
+        // create the new node
+        pObjNew = Dec_GraphToAig( pNtk, pFForms[Bbl_ObjFncHandle(pObj)], vFaninAigs );
+        Vec_PtrSetEntry( vCopy, Bbl_ObjId(pObj), pObjNew );
+    }
+    Vec_PtrFree( vFaninAigs );
+    Vec_PtrFree( vNodes );
+if ( fVerbose )
+ABC_PRT( "AIG", Abc_Clock() - clk );
+    // create COs
+    Bbl_ManForEachObj( p, pObj )
+    {
+        if ( !Bbl_ObjIsOutput(pObj) )
+            continue;
+        pObjNew = (Abc_Obj_t *)Vec_PtrEntry( vCopy, Bbl_ObjId(Bbl_ObjFaninFirst(pObj)) );
+        Abc_ObjAddFanin( Abc_NtkCreatePo(pNtk), pObjNew );
+    }
+    Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc );
+    // clear factored forms
+    for ( i = Bbl_ManFncSize(p) - 1; i >= 0; i-- )
+        if ( pFForms[i] )
+            Dec_GraphFree( pFForms[i] );
+    ABC_FREE( pFForms );
+    // finalize
+clk = Abc_Clock();
+    Vec_PtrFree( vCopy );
+    Abc_NtkAddDummyPiNames( pNtk );
+    Abc_NtkAddDummyPoNames( pNtk );
+if ( fVerbose )
+ABC_PRT( "Nam", Abc_Clock() - clk );
+//    if ( !Abc_NtkCheck( pNtk ) )
+//        printf( "Bbl_ManToAig(): Network check has failed.\n" );
+    return pNtk;
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Verifies equivalence for two combinational networks.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbl_ManVerify( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
+{
+    extern void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose );
+    Abc_Ntk_t * pAig1, * pAig2;
+    pAig1 = Abc_NtkStrash( pNtk1, 0, 1, 0 );
+    pAig2 = Abc_NtkStrash( pNtk2, 0, 1, 0 );
+    Abc_NtkShortNames( pAig1 );
+    Abc_NtkShortNames( pAig2 );
+    Abc_NtkCecFraig( pAig1, pAig2, 0, 0 );
+    Abc_NtkDelete( pAig1 );
+    Abc_NtkDelete( pAig2 );
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Performs testing of the new manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbl_ManTest( Abc_Ntk_t * pNtk )
+{
+    extern Bbl_Man_t * Bbl_ManFromAbc( Abc_Ntk_t * pNtk );
+
+    Abc_Ntk_t * pNtkNew;
+    Bbl_Man_t * p, * pNew;
+    char * pFileName = "test.bblif";
+    abctime clk, clk1, clk2, clk3, clk4, clk5;
+clk = Abc_Clock();
+    p = Bbl_ManFromAbc( pNtk );
+    Bbl_ManPrintStats( p );
+clk1 = Abc_Clock() - clk;
+//Bbl_ManDumpBlif( p, "test_bbl.blif" );
+
+    // write into file and back
+clk = Abc_Clock();
+    Bbl_ManDumpBinaryBlif( p, pFileName );
+clk2 = Abc_Clock() - clk;
+
+    // read from file
+clk = Abc_Clock();
+    pNew = Bbl_ManReadBinaryBlif( pFileName );
+    Bbl_ManStop( p ); p = pNew;
+clk3 = Abc_Clock() - clk;
+
+    // generate ABC network
+clk = Abc_Clock();
+    pNtkNew = Bbl_ManToAig( p );
+//    pNtkNew = Bbl_ManToAbc( p );
+    Bbl_ManStop( p );
+clk4 = Abc_Clock() - clk;
+
+    // equivalence check
+clk = Abc_Clock();
+//    Bbl_ManVerify( pNtk, pNtkNew );
+    Abc_NtkDelete( pNtkNew );
+clk5 = Abc_Clock() - clk;
+
+printf( "Runtime stats:\n" );
+ABC_PRT( "ABC to Man", clk1 );
+ABC_PRT( "Writing   ", clk2 );
+ABC_PRT( "Reading   ", clk3 );
+ABC_PRT( "Man to ABC", clk4 );
+ABC_PRT( "Verify    ", clk5 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the AIG in the binary format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadBblif( char * pFileName, int fCheck )
+{
+    Bbl_Man_t * p;
+    Abc_Ntk_t * pNtkNew;
+    // read the file
+    p = Bbl_ManReadBinaryBlif( pFileName );
+    pNtkNew = Bbl_ManToAig( p );
+    Bbl_ManStop( p );
+    // check the result
+    if ( fCheck && !Abc_NtkCheckRead( pNtkNew ) )
+    {
+        printf( "Io_ReadBaf: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioReadBench.c b/abc-build/src/base/io/ioReadBench.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioReadBench.c
@@ -0,0 +1,366 @@
+/**CFile****************************************************************
+
+  FileName    [ioReadBench.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to read BENCH files.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioReadBench.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the network from a BENCH file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadBench( char * pFileName, int fCheck )
+{
+    Extra_FileReader_t * p;
+    Abc_Ntk_t * pNtk;
+
+    // start the file
+    p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t,()=" );
+    if ( p == NULL )
+        return NULL;
+
+    // read the network
+    pNtk = Io_ReadBenchNetwork( p );
+    Extra_FileReaderFree( p );
+    if ( pNtk == NULL )
+        return NULL;
+
+    // make sure that everything is okay with the network structure
+    if ( fCheck && !Abc_NtkCheckRead( pNtk ) )
+    {
+        printf( "Io_ReadBench: The network check has failed.\n" );
+        Abc_NtkDelete( pNtk );
+        return NULL;
+    }
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p )
+{
+    ProgressBar * pProgress;
+    Vec_Ptr_t * vTokens;
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pNode, * pNet;
+    Vec_Str_t * vString;
+    unsigned uTruth[8];
+    char * pType, ** ppNames, * pString;
+    int iLine, nNames, nDigits, fLutsPresent = 0;
+    
+    // allocate the empty network
+    pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) );
+
+    // go through the lines of the file
+    vString = Vec_StrAlloc( 100 );
+    pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) );
+    for ( iLine = 0; (vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p)); iLine++ )
+    {
+        Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL );
+
+        if ( vTokens->nSize == 1 )
+        {
+            printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) );
+            Vec_StrFree( vString );
+            Abc_NtkDelete( pNtk );
+            return NULL;
+        }
+
+        // get the type of the line
+        if ( strncmp( (char *)vTokens->pArray[0], "INPUT", 5 ) == 0 )
+            Io_ReadCreatePi( pNtk, (char *)vTokens->pArray[1] );
+        else if ( strncmp( (char *)vTokens->pArray[0], "OUTPUT", 5 ) == 0 )
+            Io_ReadCreatePo( pNtk, (char *)vTokens->pArray[1] );
+        else 
+        {
+            // get the node name and the node type
+            pType = (char *)vTokens->pArray[1];
+            if ( strncmp(pType, "DFF", 3) == 0 ) // works for both DFF and DFFRSE
+            {
+                pNode = Io_ReadCreateLatch( pNtk, (char *)vTokens->pArray[2], (char *)vTokens->pArray[0] );
+//                Abc_LatchSetInit0( pNode );
+                if ( pType[3] == '0' )
+                    Abc_LatchSetInit0( pNode );
+                else if ( pType[3] == '1' )
+                    Abc_LatchSetInit1( pNode );
+                else
+                    Abc_LatchSetInitDc( pNode );
+            }
+            else if ( strcmp(pType, "LUT") == 0 )
+            {
+                fLutsPresent = 1;
+                ppNames = (char **)vTokens->pArray + 3;
+                nNames  = vTokens->nSize - 3;
+                // check the number of inputs
+                if ( nNames > 8 )
+                {
+                    printf( "%s: Currently cannot read truth tables with more than 8 inputs (%d).\n", Extra_FileReaderGetFileName(p), nNames );
+                    Vec_StrFree( vString );
+                    Abc_NtkDelete( pNtk );
+                    return NULL;
+                }
+                // get the hex string
+                pString = (char *)vTokens->pArray[2];
+                if ( strncmp( pString, "0x", 2 ) )
+                {
+                    printf( "%s: The LUT signature (%s) does not look like a hexadecimal beginning with \"0x\".\n", Extra_FileReaderGetFileName(p), pString );
+                    Vec_StrFree( vString );
+                    Abc_NtkDelete( pNtk );
+                    return NULL;
+                }
+                pString += 2;
+                // pad the string with zero's if needed
+                nDigits = (1 << nNames) / 4;
+                if ( nDigits == 0 )
+                    nDigits = 1;
+                if ( strlen(pString) < (unsigned)nDigits )
+                {
+                    Vec_StrFill( vString, nDigits - strlen(pString), '0' );
+                    Vec_StrPrintStr( vString, pString );
+                    Vec_StrPush( vString, 0 );
+                    pString = Vec_StrArray( vString );
+                }
+                // read the hex number from the string
+                if ( !Extra_ReadHexadecimal( uTruth, pString, nNames ) )
+                {
+                    printf( "%s: Reading hexadecimal number (%s) has failed.\n", Extra_FileReaderGetFileName(p), pString );
+                    Vec_StrFree( vString );
+                    Abc_NtkDelete( pNtk );
+                    return NULL;
+                }
+                // check if the node is a constant node
+                if ( Extra_TruthIsConst0(uTruth, nNames) )
+                {
+                    pNode = Io_ReadCreateNode( pNtk, (char *)vTokens->pArray[0], ppNames, 0 );
+                    Abc_ObjSetData( pNode, Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 0\n" ) );
+                }
+                else if ( Extra_TruthIsConst1(uTruth, nNames) )
+                {
+                    pNode = Io_ReadCreateNode( pNtk, (char *)vTokens->pArray[0], ppNames, 0 );
+                    Abc_ObjSetData( pNode, Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 1\n" ) );
+                }
+                else
+                {
+                    // create the node
+                    pNode = Io_ReadCreateNode( pNtk, (char *)vTokens->pArray[0], ppNames, nNames );
+                    assert( nNames > 0 );
+                    if ( nNames > 1 )
+                        Abc_ObjSetData( pNode, Abc_SopCreateFromTruth((Mem_Flex_t *)pNtk->pManFunc, nNames, uTruth) );
+                    else if ( pString[0] == '2' )
+                        Abc_ObjSetData( pNode, Abc_SopCreateBuf((Mem_Flex_t *)pNtk->pManFunc) );
+                    else if ( pString[0] == '1' )
+                        Abc_ObjSetData( pNode, Abc_SopCreateInv((Mem_Flex_t *)pNtk->pManFunc) );
+                    else
+                    {
+                        printf( "%s: Reading truth table (%s) of single-input node has failed.\n", Extra_FileReaderGetFileName(p), pString );
+                        Vec_StrFree( vString );
+                        Abc_NtkDelete( pNtk );
+                        return NULL;
+                    }
+                }
+            }
+            else
+            {
+                // create a new node and add it to the network
+                ppNames = (char **)vTokens->pArray + 2;
+                nNames  = vTokens->nSize - 2;
+                pNode = Io_ReadCreateNode( pNtk, (char *)vTokens->pArray[0], ppNames, nNames );
+                // assign the cover
+                if ( strcmp(pType, "AND") == 0 )
+                    Abc_ObjSetData( pNode, Abc_SopCreateAnd((Mem_Flex_t *)pNtk->pManFunc, nNames, NULL) );
+                else if ( strcmp(pType, "OR") == 0 )
+                    Abc_ObjSetData( pNode, Abc_SopCreateOr((Mem_Flex_t *)pNtk->pManFunc, nNames, NULL) );
+                else if ( strcmp(pType, "NAND") == 0 )
+                    Abc_ObjSetData( pNode, Abc_SopCreateNand((Mem_Flex_t *)pNtk->pManFunc, nNames) );
+                else if ( strcmp(pType, "NOR") == 0 )
+                    Abc_ObjSetData( pNode, Abc_SopCreateNor((Mem_Flex_t *)pNtk->pManFunc, nNames) );
+                else if ( strcmp(pType, "XOR") == 0 )
+                    Abc_ObjSetData( pNode, Abc_SopCreateXor((Mem_Flex_t *)pNtk->pManFunc, nNames) );
+                else if ( strcmp(pType, "NXOR") == 0 || strcmp(pType, "XNOR") == 0 )
+                    Abc_ObjSetData( pNode, Abc_SopCreateNxor((Mem_Flex_t *)pNtk->pManFunc, nNames) );
+                else if ( strncmp(pType, "BUF", 3) == 0 )
+                    Abc_ObjSetData( pNode, Abc_SopCreateBuf((Mem_Flex_t *)pNtk->pManFunc) );
+                else if ( strcmp(pType, "NOT") == 0 )
+                    Abc_ObjSetData( pNode, Abc_SopCreateInv((Mem_Flex_t *)pNtk->pManFunc) );
+                else if ( strncmp(pType, "MUX", 3) == 0 )
+//                    Abc_ObjSetData( pNode, Abc_SopRegister(pNtk->pManFunc, "1-0 1\n-11 1\n") );
+                    Abc_ObjSetData( pNode, Abc_SopRegister((Mem_Flex_t *)pNtk->pManFunc, "0-1 1\n11- 1\n") );
+                else if ( strncmp(pType, "gnd", 3) == 0 )
+                    Abc_ObjSetData( pNode, Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 0\n" ) );
+                else if ( strncmp(pType, "vdd", 3) == 0 )
+                    Abc_ObjSetData( pNode, Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 1\n" ) );
+                else
+                {
+                    printf( "Io_ReadBenchNetwork(): Cannot determine gate type \"%s\" in line %d.\n", pType, Extra_FileReaderGetLineNumber(p, 0) );
+                    Vec_StrFree( vString );
+                    Abc_NtkDelete( pNtk );
+                    return NULL;
+                }
+            }
+        }
+    }
+    Extra_ProgressBarStop( pProgress );
+    Vec_StrFree( vString );
+
+    // check if constant 0 is present
+    if ( (pNet = Abc_NtkFindNet( pNtk, "gnd" )) )
+    {
+        if ( Abc_ObjFaninNum(pNet) == 0 )
+            Io_ReadCreateConst( pNtk, "gnd", 0 );
+    }
+    if ( (pNet = Abc_NtkFindNet( pNtk, "1" )) )
+    {
+        if ( Abc_ObjFaninNum(pNet) == 0 )
+        {
+            printf( "Io_ReadBenchNetwork(): Adding constant 0 fanin to non-driven net \"1\".\n" );
+            Io_ReadCreateConst( pNtk, "1", 0 );
+        }
+    }
+    // check if constant 1 is present
+    if ( (pNet = Abc_NtkFindNet( pNtk, "vdd" )) )
+    {
+        if ( Abc_ObjFaninNum(pNet) == 0 )
+            Io_ReadCreateConst( pNtk, "vdd", 1 );
+    }
+    if ( (pNet = Abc_NtkFindNet( pNtk, "2" )) )
+    {
+        if ( Abc_ObjFaninNum(pNet) == 0 )
+        {
+            printf( "Io_ReadBenchNetwork(): Adding constant 1 fanin to non-driven net \"2\".\n" );
+            Io_ReadCreateConst( pNtk, "2", 1 );
+        }
+    }
+
+    Abc_NtkFinalizeRead( pNtk );
+
+    // if LUTs are present, collapse the truth tables into cubes
+    if ( fLutsPresent )
+    {
+        if ( !Abc_NtkToBdd(pNtk) )
+        {
+            printf( "Io_ReadBenchNetwork(): Converting to BDD has failed.\n" );
+            Abc_NtkDelete( pNtk );
+            return NULL;
+        }
+        if ( !Abc_NtkToSop(pNtk, 0) )
+        {
+            printf( "Io_ReadBenchNetwork(): Converting to SOP has failed.\n" );
+            Abc_NtkDelete( pNtk );
+            return NULL;
+        }
+    }
+    return pNtk;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reads initial state in BENCH format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_ReadBenchInit( Abc_Ntk_t * pNtk, char * pFileName )
+{
+    char pBuffer[1000];
+    FILE * pFile;
+    char * pToken;
+    Abc_Obj_t * pObj;
+    int Num;
+    pFile = fopen( pFileName, "r" );
+    if ( pFile == NULL )
+    {
+        printf( "Io_ReadBenchInit(): Failed to open file \"%s\".\n", pFileName );
+        return;
+    }
+    while ( fgets( pBuffer, 999, pFile ) )
+    {
+        pToken = strtok( pBuffer, " \n\t\r" );
+        // find the latch output
+        Num = Nm_ManFindIdByName( pNtk->pManName, pToken, ABC_OBJ_BO );
+        if ( Num < 0 )
+        {
+            printf( "Io_ReadBenchInit(): Cannot find register with output %s.\n", pToken );
+            continue;
+        }
+        pObj = Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) );
+        if ( !Abc_ObjIsLatch(pObj) )
+        {
+            printf( "Io_ReadBenchInit(): The signal is not a register output %s.\n", pToken );
+            continue;
+        }
+        // assign the new init state
+        pToken = strtok( NULL, " \n\t\r" );
+        if ( pToken[0] == '0' )
+            Abc_LatchSetInit0( pObj );
+        else if ( pToken[0] == '1' )
+            Abc_LatchSetInit1( pObj );
+        else if ( pToken[0] == '2' )
+            Abc_LatchSetInitDc( pObj );
+        else
+        {
+            printf( "Io_ReadBenchInit(): The signal %s has unknown initial value (%s).\n", 
+                Abc_ObjName(Abc_ObjFanout0(pObj)), pToken );
+            continue;
+        }
+    }
+    fclose( pFile );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioReadBlif.c b/abc-build/src/base/io/ioReadBlif.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioReadBlif.c
@@ -0,0 +1,1586 @@
+/**CFile****************************************************************
+
+  FileName    [ioReadBlif.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to read BLIF files.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioReadBlif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+#include "base/main/main.h"
+#include "map/mio/mio.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Io_ReadBlif_t_        Io_ReadBlif_t;   // all reading info
+struct Io_ReadBlif_t_
+{
+    // general info about file
+    char *               pFileName;    // the name of the file
+    Extra_FileReader_t * pReader;      // the input file reader
+    // current processing info
+    Abc_Ntk_t *          pNtkMaster;   // the primary network
+    Abc_Ntk_t *          pNtkCur;      // the primary network
+    int                  LineCur;      // the line currently parsed
+    // temporary storage for tokens
+    Vec_Ptr_t *          vTokens;      // the current tokens
+    Vec_Ptr_t *          vNewTokens;   // the temporary storage for the tokens
+    Vec_Str_t *          vCubes;       // the temporary storage for the tokens
+    // the error message
+    FILE *               Output;       // the output stream
+    char                 sError[1000]; // the error string generated during parsing
+    int                  fError;       // set to 1 when error occurs
+};
+
+static Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName );
+static void Io_ReadBlifFree( Io_ReadBlif_t * p );
+static void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p );
+static Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p );
+static char * Io_ReadBlifCleanName( char * pName );
+
+static Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p );
+static Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p );
+static int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
+static int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
+static int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
+static int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens );
+static int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
+static int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
+static int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
+static int Io_ReadBlifNetworkOutputRequired( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
+static int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
+static int Io_ReadBlifNetworkDefaultOutputRequired( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
+static int Io_ReadBlifNetworkInputDrive( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
+static int Io_ReadBlifNetworkOutputLoad( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
+static int Io_ReadBlifNetworkDefaultInputDrive( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
+static int Io_ReadBlifNetworkDefaultOutputLoad( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
+static int Io_ReadBlifNetworkAndGateDelay( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
+static int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the (hierarchical) network from the BLIF file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck )
+{
+    Io_ReadBlif_t * p;
+    Abc_Ntk_t * pNtk;
+
+    // start the file
+    p = Io_ReadBlifFile( pFileName );
+    if ( p == NULL )
+        return NULL;
+
+    // read the hierarchical network
+    pNtk = Io_ReadBlifNetwork( p );
+    if ( pNtk == NULL )
+    {
+        Io_ReadBlifFree( p );
+        return NULL;
+    }
+    pNtk->pSpec = Extra_UtilStrsav( pFileName );
+    Abc_NtkTimeInitialize( pNtk, NULL );
+    Io_ReadBlifFree( p );
+
+    // make sure that everything is okay with the network structure
+    if ( fCheck && !Abc_NtkCheckRead( pNtk ) )
+    {
+        printf( "Io_ReadBlif: The network check has failed.\n" );
+        Abc_NtkDelete( pNtk );
+        return NULL;
+    }
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Iteratively reads several networks in the hierarchical design.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p )
+{
+    Abc_Ntk_t * pNtk, * pNtkMaster;
+
+    // read the name of the master network
+    p->vTokens = Io_ReadBlifGetTokens(p);
+    if ( p->vTokens == NULL || strcmp( (char *)p->vTokens->pArray[0], ".model" ) )
+    {
+        p->LineCur = 0;
+        sprintf( p->sError, "Wrong input file format." );
+        Io_ReadBlifPrintErrorMessage( p );
+        return NULL;
+    }
+
+    // read networks (with EXDC) 
+    pNtkMaster = NULL;
+    while ( p->vTokens )
+    {
+        // read the network and its EXDC if present
+        pNtk = Io_ReadBlifNetworkOne( p );
+        if ( pNtk == NULL )
+            break;
+        if ( p->vTokens && strcmp((char *)p->vTokens->pArray[0], ".exdc") == 0 )
+        {
+            pNtk->pExdc = Io_ReadBlifNetworkOne( p );
+            if ( pNtk->pExdc == NULL )
+                break;
+            Abc_NtkFinalizeRead( pNtk->pExdc );
+        }
+        // add this network as part of the hierarchy
+        if ( pNtkMaster == NULL ) // no master network so far
+        {
+            p->pNtkMaster = pNtkMaster = pNtk;
+            continue;
+        }
+/*
+        // make sure hierarchy does not have the network with this name
+        if ( pNtkMaster->tName2Model && stmm_is_member( pNtkMaster->tName2Model, pNtk->pName ) )
+        {
+            p->LineCur = 0;
+            sprintf( p->sError, "Model %s is multiply defined in the file.", pNtk->pName );
+            Io_ReadBlifPrintErrorMessage( p );
+            Abc_NtkDelete( pNtk );
+            Abc_NtkDelete( pNtkMaster );
+            pNtkMaster = NULL;
+            return NULL;
+        }
+        // add the network to the hierarchy
+        if ( pNtkMaster->tName2Model == NULL )
+            pNtkMaster->tName2Model = stmm_init_table((int (*)(void))strcmp, (int (*)(void))stmm_strhash);
+        stmm_insert( pNtkMaster->tName2Model, pNtk->pName, (char *)pNtk );
+*/
+    }
+/*
+    // if there is a hierarchy, connect the boxes
+    if ( pNtkMaster && pNtkMaster->tName2Model )
+    {
+        if ( Io_ReadBlifNetworkConnectBoxes( p, pNtkMaster ) )
+        {
+            Abc_NtkDelete( pNtkMaster );
+            return NULL;
+        }
+    }
+    else 
+*/
+    if ( !p->fError )
+        Abc_NtkFinalizeRead( pNtkMaster );
+    // return the master network
+    return pNtkMaster;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads one (main or exdc) network from the BLIF file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p )
+{
+    ProgressBar * pProgress = NULL;
+    Abc_Ntk_t * pNtk;
+    char * pDirective;
+    int iLine, fTokensReady, fStatus;
+
+    // make sure the tokens are present
+    assert( p->vTokens != NULL );
+
+    // create the new network
+    p->pNtkCur = pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 );
+    // read the model name
+    if ( strcmp( (char *)p->vTokens->pArray[0], ".model" ) == 0 )
+    {
+        char * pToken, * pPivot;
+        if ( Vec_PtrSize(p->vTokens) != 2 )
+        {
+            p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+            sprintf( p->sError, "The .model line does not have exactly two entries." );
+            Io_ReadBlifPrintErrorMessage( p );
+            return NULL;
+        }
+        for ( pPivot = pToken = (char *)Vec_PtrEntry(p->vTokens, 1); *pToken; pToken++ )
+            if ( *pToken == '/' || *pToken == '\\' )
+                pPivot = pToken+1;
+        pNtk->pName = Extra_UtilStrsav( pPivot );
+    }
+    else if ( strcmp( (char *)p->vTokens->pArray[0], ".exdc" ) != 0 ) 
+    {
+        printf( "%s: File parsing skipped after line %d (\"%s\").\n", p->pFileName, 
+            Extra_FileReaderGetLineNumber(p->pReader, 0), (char*)p->vTokens->pArray[0] );
+        Abc_NtkDelete(pNtk);
+        p->pNtkCur = NULL;
+        return NULL;
+    }
+
+    // read the inputs/outputs
+    if ( p->pNtkMaster == NULL )
+        pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p->pReader) );
+    fTokensReady = fStatus = 0;
+    for ( iLine = 0; fTokensReady || (p->vTokens = Io_ReadBlifGetTokens(p)); iLine++ )
+    {
+        if ( p->pNtkMaster == NULL && iLine % 1000 == 0 )
+            Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p->pReader), NULL );
+
+        // consider different line types
+        fTokensReady = 0;
+        pDirective = (char *)p->vTokens->pArray[0];
+        if ( !strcmp( pDirective, ".names" ) )
+            { fStatus = Io_ReadBlifNetworkNames( p, &p->vTokens ); fTokensReady = 1; }
+        else if ( !strcmp( pDirective, ".gate" ) )
+            fStatus = Io_ReadBlifNetworkGate( p, p->vTokens );
+        else if ( !strcmp( pDirective, ".latch" ) )
+            fStatus = Io_ReadBlifNetworkLatch( p, p->vTokens );
+        else if ( !strcmp( pDirective, ".inputs" ) )
+            fStatus = Io_ReadBlifNetworkInputs( p, p->vTokens );
+        else if ( !strcmp( pDirective, ".outputs" ) )
+            fStatus = Io_ReadBlifNetworkOutputs( p, p->vTokens );
+        else if ( !strcmp( pDirective, ".input_arrival" ) )
+            fStatus = Io_ReadBlifNetworkInputArrival( p, p->vTokens );
+        else if ( !strcmp( pDirective, ".output_required" ) )
+            fStatus = Io_ReadBlifNetworkOutputRequired( p, p->vTokens );
+        else if ( !strcmp( pDirective, ".default_input_arrival" ) )
+            fStatus = Io_ReadBlifNetworkDefaultInputArrival( p, p->vTokens );
+        else if ( !strcmp( pDirective, ".default_output_required" ) )
+            fStatus = Io_ReadBlifNetworkDefaultOutputRequired( p, p->vTokens );
+        else if ( !strcmp( pDirective, ".input_drive" ) )
+            fStatus = Io_ReadBlifNetworkInputDrive( p, p->vTokens );
+        else if ( !strcmp( pDirective, ".output_load" ) )
+            fStatus = Io_ReadBlifNetworkOutputLoad( p, p->vTokens );
+        else if ( !strcmp( pDirective, ".default_input_drive" ) )
+            fStatus = Io_ReadBlifNetworkDefaultInputDrive( p, p->vTokens );
+        else if ( !strcmp( pDirective, ".default_output_load" ) )
+            fStatus = Io_ReadBlifNetworkDefaultOutputLoad( p, p->vTokens );
+        else if ( !strcmp( pDirective, ".and_gate_delay" ) )
+            fStatus = Io_ReadBlifNetworkAndGateDelay( p, p->vTokens );
+//        else if ( !strcmp( pDirective, ".subckt" ) )
+//            fStatus = Io_ReadBlifNetworkSubcircuit( p, p->vTokens );
+        else if ( !strcmp( pDirective, ".exdc" ) )
+            break;
+        else if ( !strcmp( pDirective, ".end" ) )
+        {
+            p->vTokens = Io_ReadBlifGetTokens(p);
+            break;
+        }
+        else if ( !strcmp( pDirective, ".blackbox" ) )
+        {
+            pNtk->ntkType = ABC_NTK_NETLIST;
+            pNtk->ntkFunc = ABC_FUNC_BLACKBOX;
+            Mem_FlexStop( (Mem_Flex_t *)pNtk->pManFunc, 0 );
+            pNtk->pManFunc = NULL;
+        }
+        else
+            printf( "%s (line %d): Skipping directive \"%s\".\n", p->pFileName, 
+                Extra_FileReaderGetLineNumber(p->pReader, 0), pDirective );
+        if ( p->vTokens == NULL ) // some files do not have ".end" in the end
+            break;
+        if ( fStatus == 1 )
+        {
+            Extra_ProgressBarStop( pProgress );
+            Abc_NtkDelete( pNtk );
+            return NULL;
+        }
+    }
+    if ( p->pNtkMaster == NULL )
+        Extra_ProgressBarStop( pProgress );
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
+{
+    int i;
+    for ( i = 1; i < vTokens->nSize; i++ )
+        Io_ReadCreatePi( p->pNtkCur, (char *)vTokens->pArray[i] );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
+{
+    int i;
+    for ( i = 1; i < vTokens->nSize; i++ )
+        Io_ReadCreatePo( p->pNtkCur, (char *)vTokens->pArray[i] );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
+{ 
+    Abc_Ntk_t * pNtk = p->pNtkCur;
+    Abc_Obj_t * pLatch;
+    int ResetValue;
+    if ( vTokens->nSize < 3 )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "The .latch line does not have enough tokens." );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    // create the latch
+    pLatch = Io_ReadCreateLatch( pNtk, (char *)vTokens->pArray[1], (char *)vTokens->pArray[2] );
+    // get the latch reset value
+    if ( vTokens->nSize == 3 )
+        Abc_LatchSetInitDc( pLatch );
+    else
+    {
+        ResetValue = atoi((char *)vTokens->pArray[vTokens->nSize-1]);
+        if ( ResetValue != 0 && ResetValue != 1 && ResetValue != 2 )
+        {
+            p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+            sprintf( p->sError, "The .latch line has an unknown reset value (%s).", (char*)vTokens->pArray[3] );
+            Io_ReadBlifPrintErrorMessage( p );
+            return 1;
+        }
+        if ( ResetValue == 0 )
+            Abc_LatchSetInit0( pLatch );
+        else if ( ResetValue == 1 )
+            Abc_LatchSetInit1( pLatch );
+        else if ( ResetValue == 2 )
+            Abc_LatchSetInitDc( pLatch );
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens )
+{
+    Vec_Ptr_t * vTokens = *pvTokens;
+    Abc_Ntk_t * pNtk = p->pNtkCur;
+    Abc_Obj_t * pNode;
+    char * pToken, Char, ** ppNames;
+    int nFanins, nNames;
+
+    // create a new node and add it to the network
+    if ( vTokens->nSize < 2 )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "The .names line has less than two tokens." );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+
+    // create the node
+    ppNames = (char **)vTokens->pArray + 1;
+    nNames  = vTokens->nSize - 2;
+    pNode   = Io_ReadCreateNode( pNtk, ppNames[nNames], ppNames, nNames );
+
+    // derive the functionality of the node
+    p->vCubes->nSize = 0;
+    nFanins = vTokens->nSize - 2;
+    if ( nFanins == 0 )
+    {
+        while ( (vTokens = Io_ReadBlifGetTokens(p)) )
+        {
+            pToken = (char *)vTokens->pArray[0];
+            if ( pToken[0] == '.' )
+                break;
+            // read the cube
+            if ( vTokens->nSize != 1 )
+            {
+                p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+                sprintf( p->sError, "The number of tokens in the constant cube is wrong." );
+                Io_ReadBlifPrintErrorMessage( p );
+                return 1;
+            }
+            // create the cube
+            Char = ((char *)vTokens->pArray[0])[0];
+            Vec_StrPush( p->vCubes, ' ' );
+            Vec_StrPush( p->vCubes, Char );
+            Vec_StrPush( p->vCubes, '\n' );
+        }
+    }
+    else
+    {
+        while ( (vTokens = Io_ReadBlifGetTokens(p)) )
+        {
+            pToken = (char *)vTokens->pArray[0];
+            if ( pToken[0] == '.' )
+                break;
+            // read the cube
+            if ( vTokens->nSize != 2 )
+            {
+                p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+                sprintf( p->sError, "The number of tokens in the cube is wrong." );
+                Io_ReadBlifPrintErrorMessage( p );
+                return 1;
+            }
+            // create the cube
+            Vec_StrPrintStr( p->vCubes, (char *)vTokens->pArray[0] );
+            // check the char 
+            Char = ((char *)vTokens->pArray[1])[0];
+            if ( Char != '0' && Char != '1' && Char != 'x' && Char != 'n' )
+            {
+                p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+                sprintf( p->sError, "The output character in the constant cube is wrong." );
+                Io_ReadBlifPrintErrorMessage( p );
+                return 1;
+            }
+            Vec_StrPush( p->vCubes, ' ' );
+            Vec_StrPush( p->vCubes, Char );
+            Vec_StrPush( p->vCubes, '\n' );
+        }
+    }
+    // if there is nothing there
+    if ( p->vCubes->nSize == 0 )
+    {
+        // create an empty cube
+        Vec_StrPush( p->vCubes, ' ' );
+        Vec_StrPush( p->vCubes, '0' );
+        Vec_StrPush( p->vCubes, '\n' );
+    }
+    Vec_StrPush( p->vCubes, 0 );
+
+    // set the pointer to the functionality of the node
+    Abc_ObjSetData( pNode, Abc_SopRegister((Mem_Flex_t *)pNtk->pManFunc, p->vCubes->pArray) );
+
+    // check the size
+    if ( Abc_ObjFaninNum(pNode) != Abc_SopGetVarNum((char *)Abc_ObjData(pNode)) )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "The number of fanins (%d) of node %s is different from SOP size (%d).", 
+            Abc_ObjFaninNum(pNode), Abc_ObjName(Abc_ObjFanout(pNode,0)), Abc_SopGetVarNum((char *)Abc_ObjData(pNode)) );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+
+    // return the last array of tokens
+    *pvTokens = vTokens;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadBlifReorderFormalNames( Vec_Ptr_t * vTokens, Mio_Gate_t * pGate, Mio_Gate_t * pTwin )
+{
+    Mio_Pin_t * pGatePin;
+    char * pName, * pNamePin;
+    int i, k, nSize, Length;
+    nSize = Vec_PtrSize(vTokens);
+    if ( pTwin == NULL )
+    {
+        if ( nSize - 3 != Mio_GateReadPinNum(pGate) )
+            return 0;
+    }
+    else
+    {
+        if ( nSize - 3 != Mio_GateReadPinNum(pGate) && nSize - 4 != Mio_GateReadPinNum(pGate) )
+            return 0;
+    }
+    // check if the names are in order
+    for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ )
+    {
+        pNamePin = Mio_PinReadName(pGatePin);
+        Length = strlen(pNamePin);
+        pName = (char *)Vec_PtrEntry(vTokens, i+2);
+        if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' )
+            continue;
+        break;
+    }
+    if ( pTwin == NULL )
+    {
+        if ( i == Mio_GateReadPinNum(pGate) )
+            return 1;
+        // reorder the pins
+        for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ )
+        {
+            pNamePin = Mio_PinReadName(pGatePin);
+            Length = strlen(pNamePin);
+            for ( k = 2; k < nSize; k++ )
+            {
+                pName = (char *)Vec_PtrEntry(vTokens, k);
+                if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' )
+                {
+                    Vec_PtrPush( vTokens, pName );
+                    break;
+                }
+            }
+        }
+        pNamePin = Mio_GateReadOutName(pGate);
+        Length = strlen(pNamePin);
+        for ( k = 2; k < nSize; k++ )
+        {
+            pName = (char *)Vec_PtrEntry(vTokens, k);
+            if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' )
+            {
+                Vec_PtrPush( vTokens, pName );
+                break;
+            }
+        }
+        if ( Vec_PtrSize(vTokens) - nSize != nSize - 2 )
+            return 0;
+        Vec_PtrForEachEntryStart( char *, vTokens, pName, k, nSize )
+            Vec_PtrWriteEntry( vTokens, k - nSize + 2, pName );
+        Vec_PtrShrink( vTokens, nSize );
+    }
+    else
+    {
+        if ( i != Mio_GateReadPinNum(pGate) ) // expect the correct order of input pins in the network with twin gates
+            return 0;
+        // check the last two entries
+        if ( nSize - 3 == Mio_GateReadPinNum(pGate) ) // only one output is available
+        {
+            pNamePin = Mio_GateReadOutName(pGate);
+            Length = strlen(pNamePin);
+            pName = (char *)Vec_PtrEntry(vTokens, nSize - 1);
+            if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) // the last entry is pGate
+            {
+                Vec_PtrPush( vTokens, NULL );
+                return 1;
+            }
+            pNamePin = Mio_GateReadOutName(pTwin);
+            Length = strlen(pNamePin);
+            pName = (char *)Vec_PtrEntry(vTokens, nSize - 1);
+            if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) // the last entry is pTwin
+            {
+                pName = (char *)Vec_PtrPop( vTokens );
+                Vec_PtrPush( vTokens, NULL );
+                Vec_PtrPush( vTokens, pName );
+                return 1;
+            }
+            return 0;
+        }
+        if ( nSize - 4 == Mio_GateReadPinNum(pGate) ) // two outputs are available
+        {
+            pNamePin = Mio_GateReadOutName(pGate);
+            Length = strlen(pNamePin);
+            pName = (char *)Vec_PtrEntry(vTokens, nSize - 2);
+            if ( !(!strncmp( pNamePin, pName, Length ) && pName[Length] == '=') )
+                return 0;
+            pNamePin = Mio_GateReadOutName(pTwin);
+            Length = strlen(pNamePin);
+            pName = (char *)Vec_PtrEntry(vTokens, nSize - 1);
+            if ( !(!strncmp( pNamePin, pName, Length ) && pName[Length] == '=') )
+                return 0;
+            return 1;
+        }
+        assert( 0 );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
+{
+    Mio_Library_t * pGenlib; 
+    Mio_Gate_t * pGate;
+    Abc_Obj_t * pNode;
+    char ** ppNames;
+    int i, nNames;
+
+    // check that the library is available
+    pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen();
+    if ( pGenlib == NULL )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "The current library is not available." );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+
+    // create a new node and add it to the network
+    if ( vTokens->nSize < 2 )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "The .gate line has less than two tokens." );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+
+    // get the gate
+    pGate = Mio_LibraryReadGateByName( pGenlib, (char *)vTokens->pArray[1], NULL );
+    if ( pGate == NULL )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Cannot find gate \"%s\" in the library.", (char*)vTokens->pArray[1] );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+
+    // if this is the first line with gate, update the network type
+    if ( Abc_NtkNodeNum(p->pNtkCur) == 0 )
+    {
+        assert( p->pNtkCur->ntkFunc == ABC_FUNC_SOP );
+        p->pNtkCur->ntkFunc = ABC_FUNC_MAP;
+        Mem_FlexStop( (Mem_Flex_t *)p->pNtkCur->pManFunc, 0 );
+        p->pNtkCur->pManFunc = pGenlib;
+    }
+
+    // reorder the formal inputs to be in the same order as in the gate
+    if ( !Io_ReadBlifReorderFormalNames( vTokens, pGate, Mio_GateReadTwin(pGate) ) )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Mismatch in the fanins of gate \"%s\".", (char*)vTokens->pArray[1] );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+
+
+    // remove the formal parameter names
+    for ( i = 2; i < vTokens->nSize; i++ )
+    {
+        vTokens->pArray[i] = Io_ReadBlifCleanName( (char *)vTokens->pArray[i] );
+        if ( vTokens->pArray[i] == NULL )
+        {
+            p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+            sprintf( p->sError, "Invalid gate input assignment." );
+            Io_ReadBlifPrintErrorMessage( p );
+            return 1;
+        }
+    }
+
+    // create the node
+    if ( Mio_GateReadTwin(pGate) == NULL )
+    {
+        nNames  = vTokens->nSize - 3;
+        ppNames = (char **)vTokens->pArray + 2;
+        pNode   = Io_ReadCreateNode( p->pNtkCur, ppNames[nNames], ppNames, nNames );
+        Abc_ObjSetData( pNode, pGate );
+    }
+    else
+    {
+        nNames  = vTokens->nSize - 4;
+        ppNames = (char **)vTokens->pArray + 2;
+        assert( ppNames[nNames] != NULL || ppNames[nNames+1] != NULL );
+        if ( ppNames[nNames] )
+        {
+            pNode   = Io_ReadCreateNode( p->pNtkCur, ppNames[nNames], ppNames, nNames );
+            Abc_ObjSetData( pNode, pGate );
+        }
+        if ( ppNames[nNames+1] )
+        {
+            pNode   = Io_ReadCreateNode( p->pNtkCur, ppNames[nNames+1], ppNames, nNames );
+            Abc_ObjSetData( pNode, Mio_GateReadTwin(pGate) );
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a multi-input multi-output box in the hierarchical design.]
+
+  Description []
+               
+  SideEffects [] 
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
+{
+    Abc_Obj_t * pBox;
+    Vec_Ptr_t * vNames;
+    char * pName;
+    int i;
+
+    // create a new node and add it to the network
+    if ( vTokens->nSize < 3 )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "The .subcircuit line has less than three tokens." );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+
+    // store the names of formal/actual inputs/outputs of the box
+    vNames = Vec_PtrAlloc( 10 );
+    Vec_PtrForEachEntryStart( char *, vTokens, pName, i, 1 )
+//        Vec_PtrPush( vNames, Abc_NtkRegisterName(p->pNtkCur, pName) );
+        Vec_PtrPush( vNames, Extra_UtilStrsav(pName) );  // memory leak!!!
+
+    // create a new box and add it to the network
+    pBox = Abc_NtkCreateBlackbox( p->pNtkCur );
+    // set the pointer to the node names
+    Abc_ObjSetData( pBox, vNames );
+    // remember the line of the file
+    pBox->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Extra_FileReaderGetLineNumber(p->pReader, 0);
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Io_ReadBlifCleanName( char * pName )
+{
+    int i, Length;
+    Length = strlen(pName);
+    for ( i = 0; i < Length; i++ )
+        if ( pName[i] == '=' )
+            return pName + i + 1;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
+{
+    Abc_Obj_t * pNet;
+    char * pFoo1, * pFoo2;
+    double TimeRise, TimeFall;
+ 
+    // make sure this is indeed the .inputs line
+    assert( strncmp( (char *)vTokens->pArray[0], ".input_arrival", 14 ) == 0 );
+    if ( vTokens->nSize != 4 )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Wrong number of arguments on .input_arrival line." );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    pNet = Abc_NtkFindNet( p->pNtkCur, (char *)vTokens->pArray[1] );
+    if ( pNet == NULL )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Cannot find object corresponding to %s on .input_arrival line.", (char*)vTokens->pArray[1] );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    TimeRise = strtod( (char *)vTokens->pArray[2], &pFoo1 );
+    TimeFall = strtod( (char *)vTokens->pArray[3], &pFoo2 );
+    if ( *pFoo1 != '\0' || *pFoo2 != '\0' )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .input_arrival line.", (char*)vTokens->pArray[2], (char*)vTokens->pArray[3] );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    // set the arrival time
+    Abc_NtkTimeSetArrival( p->pNtkCur, Abc_ObjFanin0(pNet)->Id, (float)TimeRise, (float)TimeFall );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadBlifNetworkOutputRequired( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
+{
+    Abc_Obj_t * pNet;
+    char * pFoo1, * pFoo2;
+    double TimeRise, TimeFall;
+ 
+    // make sure this is indeed the .inputs line
+    assert( strncmp( (char *)vTokens->pArray[0], ".output_required", 16 ) == 0 );
+    if ( vTokens->nSize != 4 )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Wrong number of arguments on .output_required line." );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    pNet = Abc_NtkFindNet( p->pNtkCur, (char *)vTokens->pArray[1] );
+    if ( pNet == NULL )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Cannot find object corresponding to %s on .output_required line.", (char*)vTokens->pArray[1] );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    TimeRise = strtod( (char *)vTokens->pArray[2], &pFoo1 );
+    TimeFall = strtod( (char *)vTokens->pArray[3], &pFoo2 );
+    if ( *pFoo1 != '\0' || *pFoo2 != '\0' )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .output_required line.", (char*)vTokens->pArray[2], (char*)vTokens->pArray[3] );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    // set the arrival time
+    Abc_NtkTimeSetRequired( p->pNtkCur, Abc_ObjFanout0(pNet)->Id, (float)TimeRise, (float)TimeFall );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
+{
+    char * pFoo1, * pFoo2;
+    double TimeRise, TimeFall;
+
+    // make sure this is indeed the .inputs line
+    assert( strncmp( (char *)vTokens->pArray[0], ".default_input_arrival", 23 ) == 0 );
+    if ( vTokens->nSize != 3 )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Wrong number of arguments on .default_input_arrival line." );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    TimeRise = strtod( (char *)vTokens->pArray[1], &pFoo1 );
+    TimeFall = strtod( (char *)vTokens->pArray[2], &pFoo2 );
+    if ( *pFoo1 != '\0' || *pFoo2 != '\0' )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .default_input_arrival line.", (char*)vTokens->pArray[1], (char*)vTokens->pArray[2] );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    // set the arrival time
+    Abc_NtkTimeSetDefaultArrival( p->pNtkCur, (float)TimeRise, (float)TimeFall );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadBlifNetworkDefaultOutputRequired( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
+{
+    char * pFoo1, * pFoo2;
+    double TimeRise, TimeFall;
+
+    // make sure this is indeed the .inputs line
+    assert( strncmp( (char *)vTokens->pArray[0], ".default_output_required", 25 ) == 0 );
+    if ( vTokens->nSize != 3 )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Wrong number of arguments on .default_output_required line." );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    TimeRise = strtod( (char *)vTokens->pArray[1], &pFoo1 );
+    TimeFall = strtod( (char *)vTokens->pArray[2], &pFoo2 );
+    if ( *pFoo1 != '\0' || *pFoo2 != '\0' )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .default_output_required line.", (char*)vTokens->pArray[1], (char*)vTokens->pArray[2] );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    // set the arrival time
+    Abc_NtkTimeSetDefaultRequired( p->pNtkCur, (float)TimeRise, (float)TimeFall );
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadFindCiId( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pTemp;
+    int i;
+    Abc_NtkForEachCi( pNtk, pTemp, i )
+        if ( pTemp == pObj )
+            return i;
+    return -1;
+}
+int Io_ReadBlifNetworkInputDrive( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
+{
+    Abc_Obj_t * pNet;
+    char * pFoo1, * pFoo2;
+    double TimeRise, TimeFall;
+ 
+    // make sure this is indeed the .inputs line
+    assert( strncmp( (char *)vTokens->pArray[0], ".input_drive", 12 ) == 0 );
+    if ( vTokens->nSize != 4 )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Wrong number of arguments on .input_drive line." );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    pNet = Abc_NtkFindNet( p->pNtkCur, (char *)vTokens->pArray[1] );
+    if ( pNet == NULL )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Cannot find object corresponding to %s on .input_drive line.", (char*)vTokens->pArray[1] );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    TimeRise = strtod( (char *)vTokens->pArray[2], &pFoo1 );
+    TimeFall = strtod( (char *)vTokens->pArray[3], &pFoo2 );
+    if ( *pFoo1 != '\0' || *pFoo2 != '\0' )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .input_drive line.", (char*)vTokens->pArray[2], (char*)vTokens->pArray[3] );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    // set the arrival time
+    Abc_NtkTimeSetInputDrive( p->pNtkCur, Io_ReadFindCiId(p->pNtkCur, Abc_NtkObj(p->pNtkCur, Abc_ObjFanin0(pNet)->Id)), (float)TimeRise, (float)TimeFall );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadFindCoId( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pTemp;
+    int i;
+    Abc_NtkForEachPo( pNtk, pTemp, i )
+        if ( pTemp == pObj )
+            return i;
+    return -1;
+}
+int Io_ReadBlifNetworkOutputLoad( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
+{
+    Abc_Obj_t * pNet;
+    char * pFoo1, * pFoo2;
+    double TimeRise, TimeFall;
+ 
+    // make sure this is indeed the .inputs line
+    assert( strncmp( (char *)vTokens->pArray[0], ".output_load", 12 ) == 0 );
+    if ( vTokens->nSize != 4 )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Wrong number of arguments on .output_load line." );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    pNet = Abc_NtkFindNet( p->pNtkCur, (char *)vTokens->pArray[1] );
+    if ( pNet == NULL )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Cannot find object corresponding to %s on .output_load line.", (char*)vTokens->pArray[1] );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    TimeRise = strtod( (char *)vTokens->pArray[2], &pFoo1 );
+    TimeFall = strtod( (char *)vTokens->pArray[3], &pFoo2 );
+    if ( *pFoo1 != '\0' || *pFoo2 != '\0' )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .output_load line.", (char*)vTokens->pArray[2], (char*)vTokens->pArray[3] );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    // set the arrival time
+    Abc_NtkTimeSetOutputLoad( p->pNtkCur, Io_ReadFindCoId(p->pNtkCur, Abc_NtkObj(p->pNtkCur, Abc_ObjFanout0(pNet)->Id)), (float)TimeRise, (float)TimeFall );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadBlifNetworkDefaultInputDrive( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
+{
+    char * pFoo1, * pFoo2;
+    double TimeRise, TimeFall;
+
+    // make sure this is indeed the .inputs line
+    assert( strncmp( (char *)vTokens->pArray[0], ".default_input_drive", 21 ) == 0 );
+    if ( vTokens->nSize != 3 )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Wrong number of arguments on .default_input_drive line." );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    TimeRise = strtod( (char *)vTokens->pArray[1], &pFoo1 );
+    TimeFall = strtod( (char *)vTokens->pArray[2], &pFoo2 );
+    if ( *pFoo1 != '\0' || *pFoo2 != '\0' )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .default_input_drive line.", (char*)vTokens->pArray[1], (char*)vTokens->pArray[2] );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    // set the arrival time
+    Abc_NtkTimeSetDefaultInputDrive( p->pNtkCur, (float)TimeRise, (float)TimeFall );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadBlifNetworkDefaultOutputLoad( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
+{
+    char * pFoo1, * pFoo2;
+    double TimeRise, TimeFall;
+
+    // make sure this is indeed the .inputs line
+    assert( strncmp( (char *)vTokens->pArray[0], ".default_output_load", 21 ) == 0 );
+    if ( vTokens->nSize != 3 )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Wrong number of arguments on .default_output_load line." );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    TimeRise = strtod( (char *)vTokens->pArray[1], &pFoo1 );
+    TimeFall = strtod( (char *)vTokens->pArray[2], &pFoo2 );
+    if ( *pFoo1 != '\0' || *pFoo2 != '\0' )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .default_output_load line.", (char*)vTokens->pArray[1], (char*)vTokens->pArray[2] );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    // set the arrival time
+    Abc_NtkTimeSetDefaultOutputLoad( p->pNtkCur, (float)TimeRise, (float)TimeFall );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadBlifNetworkAndGateDelay( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
+{
+    char * pFoo1;
+    double AndGateDelay;
+
+    // make sure this is indeed the .inputs line
+    assert( strncmp( (char *)vTokens->pArray[0], ".and_gate_delay", 25 ) == 0 );
+    if ( vTokens->nSize != 2 )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Wrong number of arguments (%d) on .and_gate_delay line (should be 1).", vTokens->nSize-1 );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    AndGateDelay = strtod( (char *)vTokens->pArray[1], &pFoo1 );
+    if ( *pFoo1 != '\0' )
+    {
+        p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+        sprintf( p->sError, "Bad value (%s) for AND gate delay in on .and_gate_delay line line.", (char*)vTokens->pArray[1] );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+    // set the arrival time
+    p->pNtkCur->AndGateDelay = (float)AndGateDelay;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the error message including the file name and line number.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p )
+{
+    p->fError = 1;
+    if ( p->LineCur == 0 ) // the line number is not given
+        fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError );
+    else // print the error message with the line number
+        fprintf( p->Output, "%s (line %d): %s\n", p->pFileName, p->LineCur, p->sError );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gets the tokens taking into account the line breaks.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p )
+{
+    Vec_Ptr_t * vTokens;
+    char * pLastToken;
+    int i;
+
+    // get rid of the old tokens
+    if ( p->vNewTokens->nSize > 0 )
+    {
+        for ( i = 0; i < p->vNewTokens->nSize; i++ )
+            ABC_FREE( p->vNewTokens->pArray[i] );
+        p->vNewTokens->nSize = 0;
+    }
+
+    // get the new tokens
+    vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p->pReader);
+    if ( vTokens == NULL )
+        return vTokens;
+
+    // check if there is a transfer to another line
+    pLastToken = (char *)vTokens->pArray[vTokens->nSize - 1];
+    if ( pLastToken[ strlen(pLastToken)-1 ] != '\\' )
+        return vTokens;
+
+    // remove the slash
+    pLastToken[ strlen(pLastToken)-1 ] = 0;
+    if ( pLastToken[0] == 0 )
+        vTokens->nSize--;
+    // load them into the new array
+    for ( i = 0; i < vTokens->nSize; i++ )
+        Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav((char *)vTokens->pArray[i]) );
+
+    // load as long as there is the line break
+    while ( 1 )
+    {
+        // get the new tokens
+        vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p->pReader);
+        if ( vTokens->nSize == 0 )
+            return p->vNewTokens;
+        // check if there is a transfer to another line
+        pLastToken = (char *)vTokens->pArray[vTokens->nSize - 1];
+        if ( pLastToken[ strlen(pLastToken)-1 ] == '\\' )
+        {
+            // remove the slash
+            pLastToken[ strlen(pLastToken)-1 ] = 0;
+            if ( pLastToken[0] == 0 )
+                vTokens->nSize--;
+            // load them into the new array
+            for ( i = 0; i < vTokens->nSize; i++ )
+                Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav((char *)vTokens->pArray[i]) );
+            continue;
+        }
+        // otherwise, load them and break
+        for ( i = 0; i < vTokens->nSize; i++ )
+            Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav((char *)vTokens->pArray[i]) );
+        break;
+    }
+    return p->vNewTokens;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the reading data structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName )
+{
+    Extra_FileReader_t * pReader;
+    Io_ReadBlif_t * p;
+
+    // start the reader
+    pReader = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t" );
+
+    if ( pReader == NULL )
+        return NULL;
+
+    // start the reading data structure
+    p = ABC_ALLOC( Io_ReadBlif_t, 1 );
+    memset( p, 0, sizeof(Io_ReadBlif_t) );
+    p->pFileName  = pFileName;
+    p->pReader    = pReader;
+    p->Output     = stdout;
+    p->vNewTokens = Vec_PtrAlloc( 100 );
+    p->vCubes     = Vec_StrAlloc( 100 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the data structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_ReadBlifFree( Io_ReadBlif_t * p )
+{
+    Extra_FileReaderFree( p->pReader );
+    Vec_PtrFree( p->vNewTokens );
+    Vec_StrFree( p->vCubes );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Connect one box.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadBlifNetworkConnectBoxesOneBox( Io_ReadBlif_t * p, Abc_Obj_t * pBox, stmm_table * tName2Model )
+{
+    Vec_Ptr_t * pNames;
+    Abc_Ntk_t * pNtkModel;
+    Abc_Obj_t * pObj, * pNet;
+    char * pName = NULL, * pActual;
+    int i, Length, Start = -1;
+
+    // get the model for this box
+    pNames = (Vec_Ptr_t *)pBox->pData;
+    if ( !stmm_lookup( tName2Model, (char *)Vec_PtrEntry(pNames, 0), (char **)&pNtkModel ) )
+    {
+        p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy;
+        sprintf( p->sError, "Cannot find the model for subcircuit %s.", (char*)Vec_PtrEntry(pNames, 0) );
+        Io_ReadBlifPrintErrorMessage( p );
+        return 1;
+    }
+
+    // create the fanins of the box
+    Abc_NtkForEachPi( pNtkModel, pObj, i )
+        pObj->pCopy = NULL;
+    if ( Abc_NtkPiNum(pNtkModel) == 0 )
+        Start = 1;
+    else
+    {
+        Vec_PtrForEachEntryStart( char *, pNames, pName, i, 1 )
+        {
+            pActual = Io_ReadBlifCleanName(pName);
+            if ( pActual == NULL )
+            {
+                p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy;
+                sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName );
+                Io_ReadBlifPrintErrorMessage( p );
+                return 1;
+            }
+            Length = pActual - pName - 1;
+            pName[Length] = 0;
+            // find the PI net with this name
+            pObj = Abc_NtkFindNet( pNtkModel, pName );
+            if ( pObj == NULL )
+            {
+                p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy;
+                sprintf( p->sError, "Cannot find formal input \"%s\" as an PI of model \"%s\".", pName, (char*)Vec_PtrEntry(pNames, 0) );
+                Io_ReadBlifPrintErrorMessage( p );
+                return 1;
+            }
+            // get the PI
+            pObj = Abc_ObjFanin0(pObj);
+            // quit if this is not a PI net
+            if ( !Abc_ObjIsPi(pObj) )
+            {
+                pName[Length] = '=';
+                Start = i;
+                break;
+            }
+            // remember the actual name in the net
+            if ( pObj->pCopy != NULL )
+            {
+                p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy;
+                sprintf( p->sError, "Formal input \"%s\" is used more than once.", pName );
+                Io_ReadBlifPrintErrorMessage( p );
+                return 1;
+            }
+            pObj->pCopy = (Abc_Obj_t *)pActual;
+            // quit if we processed all PIs
+            if ( i == Abc_NtkPiNum(pNtkModel) )
+            {
+                Start = i+1;
+                break;
+            }
+        }
+    }
+    // create the fanins of the box
+    Abc_NtkForEachPi( pNtkModel, pObj, i )
+    {
+        pActual = (char *)pObj->pCopy;
+        if ( pActual == NULL )
+        {
+            p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy;
+            sprintf( p->sError, "Formal input \"%s\" of model %s is not driven.", pName, (char*)Vec_PtrEntry(pNames, 0) );
+            Io_ReadBlifPrintErrorMessage( p );
+            return 1;
+        }
+        pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual );
+        Abc_ObjAddFanin( pBox, pNet );
+    }
+    Abc_NtkForEachPi( pNtkModel, pObj, i )
+        pObj->pCopy = NULL;
+
+    // create the fanouts of the box
+    Abc_NtkForEachPo( pNtkModel, pObj, i )
+        pObj->pCopy = NULL;
+    Vec_PtrForEachEntryStart( char *, pNames, pName, i, Start )
+    {
+        pActual = Io_ReadBlifCleanName(pName);
+        if ( pActual == NULL )
+        {
+            p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy;
+            sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName );
+            Io_ReadBlifPrintErrorMessage( p );
+            return 1;
+        }
+        Length = pActual - pName - 1;
+        pName[Length] = 0;
+        // find the PO net with this name
+        pObj = Abc_NtkFindNet( pNtkModel, pName );
+        if ( pObj == NULL )
+        {
+            p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy;
+            sprintf( p->sError, "Cannot find formal output \"%s\" as an PO of model \"%s\".", pName, (char*)Vec_PtrEntry(pNames, 0) );
+            Io_ReadBlifPrintErrorMessage( p );
+            return 1;
+        }
+        // get the PO
+        pObj = Abc_ObjFanout0(pObj);
+        if ( pObj->pCopy != NULL )
+        {
+            p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy;
+            sprintf( p->sError, "Formal output \"%s\" is used more than once.", pName );
+            Io_ReadBlifPrintErrorMessage( p );
+            return 1;
+        }
+        pObj->pCopy = (Abc_Obj_t *)pActual;
+    }
+    // create the fanouts of the box
+    Abc_NtkForEachPo( pNtkModel, pObj, i )
+    {
+        pActual = (char *)pObj->pCopy;
+        if ( pActual == NULL )
+        {
+            p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy;
+            sprintf( p->sError, "Formal output \"%s\" of model %s is not driven.", pName, (char*)Vec_PtrEntry(pNames, 0) );
+            Io_ReadBlifPrintErrorMessage( p );
+            return 1;
+        }
+        pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual );
+        Abc_ObjAddFanin( pNet, pBox );
+    }
+    Abc_NtkForEachPo( pNtkModel, pObj, i )
+        pObj->pCopy = NULL;
+
+    // remove the array of names, assign the pointer to the model
+    Vec_PtrForEachEntry( char *, (Vec_Ptr_t *)pBox->pData, pName, i )
+        ABC_FREE( pName );
+    Vec_PtrFree( (Vec_Ptr_t *)pBox->pData );
+    pBox->pData = pNtkModel;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Connect the boxes in the hierarchy of networks.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadBlifNetworkConnectBoxesOne( Io_ReadBlif_t * p, Abc_Ntk_t * pNtk, stmm_table * tName2Model )
+{
+    Abc_Obj_t * pBox;
+    int i;
+    // go through the boxes
+    Abc_NtkForEachBlackbox( pNtk, pBox, i )
+        if ( Io_ReadBlifNetworkConnectBoxesOneBox( p, pBox, tName2Model ) )
+            return 1;
+    Abc_NtkFinalizeRead( pNtk );
+    return 0;
+}
+
+#if 0
+
+/**Function*************************************************************
+
+  Synopsis    [Connect the boxes in the hierarchy of networks.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster )
+{
+    stmm_generator * gen;
+    Abc_Ntk_t * pNtk;
+    char * pName;
+    // connect the master network
+    if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtkMaster, pNtkMaster->tName2Model ) )
+        return 1;
+    // connect other networks
+    stmm_foreach_item( pNtkMaster->tName2Model, gen, &pName, (char **)&pNtk )
+        if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtk, pNtkMaster->tName2Model ) )
+            return 1;
+    return 0;
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioReadBlifAig.c b/abc-build/src/base/io/ioReadBlifAig.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioReadBlifAig.c
@@ -0,0 +1,1019 @@
+/**CFile****************************************************************
+
+  FileName    [ioReadBlifAig.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to read BLIF file into AIG.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - December 23, 2006.]
+
+  Revision    [$Id: ioReadBlifAig.c,v 1.00 2006/12/23 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/vec/vecPtr.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// latch initial values
+typedef enum { 
+    IO_BLIF_INIT_NONE = 0,  // 0:  unknown
+    IO_BLIF_INIT_ZERO,      // 1:  zero
+    IO_BLIF_INIT_ONE,       // 2:  one
+    IO_BLIF_INIT_DC         // 3:  don't-care
+} Io_BlifInit_t;
+
+typedef struct Io_BlifObj_t_ Io_BlifObj_t;  // parsing object
+struct Io_BlifObj_t_
+{
+    unsigned             fPi    :  1;  // the object is a primary input
+    unsigned             fPo    :  1;  // the object is a primary output
+    unsigned             fLi    :  1;  // the object is a latch input
+    unsigned             fLo    :  1;  // the object is a latch output
+    unsigned             fDef   :  1;  // the object is defined as a table (node, PO, LI)
+    unsigned             fLoop  :  1;  // flag for loop detection
+    unsigned             Init   :  2;  // the latch initial state
+    unsigned             Offset : 24;  // temporary number
+    char *               pName;        // the name of this object
+    void *               pEquiv;       // the AIG node representing this line    
+    Io_BlifObj_t *       pNext;        // the next obj in the hash table
+};
+
+typedef struct Io_BlifMan_t_ Io_BlifMan_t;  // parsing manager
+struct Io_BlifMan_t_
+{
+    // general info about file
+    char *               pFileName;    // the name of the file
+    char *               pBuffer;      // the begining of the file buffer
+    Vec_Ptr_t *          vLines;       // the line beginnings
+    // temporary objects
+    Io_BlifObj_t *       pObjects;     // the storage for objects
+    int                  nObjects;     // the number of objects allocated
+    int                  iObjNext;     // the next free object
+    // file lines
+    char *               pModel;       // .model line
+    Vec_Ptr_t *          vInputs;      // .inputs lines
+    Vec_Ptr_t *          vOutputs;     // .outputs lines
+    Vec_Ptr_t *          vLatches;     // .latches lines
+    Vec_Ptr_t *          vNames;       // .names lines
+    // network objects
+    Vec_Ptr_t *          vPis;         // the PI structures
+    Vec_Ptr_t *          vPos;         // the PO structures
+    Vec_Ptr_t *          vLis;         // the LI structures
+    Vec_Ptr_t *          vLos;         // the LO structures
+    // mapping of names into objects
+    Io_BlifObj_t **      pTable;       // the hash table
+    int                  nTableSize;   // the hash table size
+    // current processing info
+    Abc_Ntk_t *          pAig;         // the network under construction
+    Vec_Ptr_t *          vTokens;      // the current tokens
+    char                 sError[512];  // the error string generated during parsing
+    // statistics 
+    int                  nTablesRead;  // the number of processed tables
+    int                  nTablesLeft;  // the number of dangling tables
+};
+
+// static functions
+static Io_BlifMan_t *    Io_BlifAlloc();
+static void              Io_BlifFree( Io_BlifMan_t * p );
+static char *            Io_BlifLoadFile( char * pFileName );
+static void              Io_BlifReadPreparse( Io_BlifMan_t * p );
+static Abc_Ntk_t *       Io_BlifParse( Io_BlifMan_t * p );
+static int               Io_BlifParseModel( Io_BlifMan_t * p, char * pLine );
+static int               Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine );
+static int               Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine );
+static int               Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine );
+static int               Io_BlifParseNames( Io_BlifMan_t * p, char * pLine );
+static int               Io_BlifParseConstruct( Io_BlifMan_t * p );
+static int               Io_BlifCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n';  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the network from the BLIF file as an AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadBlifAsAig( char * pFileName, int fCheck )
+{
+    FILE * pFile;
+    Io_BlifMan_t * p;
+    Abc_Ntk_t * pAig;
+
+    // check that the file is available
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Io_Blif(): The file is unavailable (absent or open).\n" );
+        return 0;
+    }
+    fclose( pFile );
+
+    // start the file reader
+    p = Io_BlifAlloc();
+    p->pFileName = pFileName;
+    p->pBuffer   = Io_BlifLoadFile( pFileName );
+    if ( p->pBuffer == NULL )
+    {
+        Io_BlifFree( p );
+        return NULL;
+    }
+    // prepare the file for parsing
+    Io_BlifReadPreparse( p );
+    // construct the network
+    pAig = Io_BlifParse( p );
+    if ( p->sError[0] )
+        fprintf( stdout, "%s\n", p->sError );
+    if ( pAig == NULL )
+        return NULL;
+    Io_BlifFree( p );
+
+    // make sure that everything is okay with the network structure
+    if ( fCheck && !Abc_NtkCheckRead( pAig ) )
+    {
+        printf( "Io_Blif: The network check has failed.\n" );
+        Abc_NtkDelete( pAig );
+        return NULL;
+    }
+    return pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the BLIF parsing structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Io_BlifMan_t * Io_BlifAlloc()
+{
+    Io_BlifMan_t * p;
+    p = ABC_ALLOC( Io_BlifMan_t, 1 );
+    memset( p, 0, sizeof(Io_BlifMan_t) );
+    p->vLines   = Vec_PtrAlloc( 512 );
+    p->vInputs  = Vec_PtrAlloc( 512 );
+    p->vOutputs = Vec_PtrAlloc( 512 );
+    p->vLatches = Vec_PtrAlloc( 512 );
+    p->vNames   = Vec_PtrAlloc( 512 );
+    p->vTokens  = Vec_PtrAlloc( 512 );
+    p->vPis     = Vec_PtrAlloc( 512 );
+    p->vPos     = Vec_PtrAlloc( 512 );
+    p->vLis     = Vec_PtrAlloc( 512 );
+    p->vLos     = Vec_PtrAlloc( 512 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the BLIF parsing structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Io_BlifFree( Io_BlifMan_t * p )
+{
+    if ( p->pAig )
+        Abc_NtkDelete( p->pAig );
+    if ( p->pBuffer )  ABC_FREE( p->pBuffer );
+    if ( p->pObjects ) ABC_FREE( p->pObjects );
+    if ( p->pTable )   ABC_FREE( p->pTable );
+    Vec_PtrFree( p->vLines );
+    Vec_PtrFree( p->vInputs );
+    Vec_PtrFree( p->vOutputs );
+    Vec_PtrFree( p->vLatches );
+    Vec_PtrFree( p->vNames );
+    Vec_PtrFree( p->vTokens );
+    Vec_PtrFree( p->vPis );
+    Vec_PtrFree( p->vPos );
+    Vec_PtrFree( p->vLis );
+    Vec_PtrFree( p->vLos );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Hashing for character strings.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static unsigned Io_BlifHashString( char * pName, int TableSize ) 
+{
+    static int s_Primes[10] = { 
+        1291, 1699, 2357, 4177, 5147, 
+        5647, 6343, 7103, 7873, 8147
+    };
+    unsigned i, Key = 0;
+    for ( i = 0; pName[i] != '\0'; i++ )
+        Key ^= s_Primes[i%10]*pName[i]*pName[i];
+    return Key % TableSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the given name exists in the table.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Io_BlifObj_t ** Io_BlifHashLookup( Io_BlifMan_t * p, char * pName )
+{
+    Io_BlifObj_t ** ppEntry;
+    for ( ppEntry = p->pTable + Io_BlifHashString(pName, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext )
+        if ( !strcmp((*ppEntry)->pName, pName) )
+            return ppEntry;
+    return ppEntry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds or add the given name to the table.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Io_BlifObj_t * Io_BlifHashFindOrAdd( Io_BlifMan_t * p, char * pName )
+{
+    Io_BlifObj_t ** ppEntry;
+    ppEntry = Io_BlifHashLookup( p, pName );
+    if ( *ppEntry == NULL )
+    {
+        assert( p->iObjNext < p->nObjects ); 
+        *ppEntry = p->pObjects + p->iObjNext++;
+        (*ppEntry)->pName = pName;
+    }
+    return *ppEntry;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the already split tokens.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Io_BlifCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput )
+{
+    char * pCur;
+    Vec_PtrClear( vTokens );
+    for ( pCur = pInput; pCur < pOutput; pCur++ )
+    {
+        if ( *pCur == 0 )
+            continue;
+        Vec_PtrPush( vTokens, pCur );
+        while ( *++pCur );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Splits the line into tokens.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Io_BlifSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop )
+{
+    char * pCur;
+    // clear spaces
+    for ( pCur = pLine; *pCur != Stop; pCur++ )
+        if ( Io_BlifCharIsSpace(*pCur) )
+            *pCur = 0;
+    // collect tokens
+    Io_BlifCollectTokens( vTokens, pLine, pCur );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the 1-based number of the line in which the token occurs.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_BlifGetLine( Io_BlifMan_t * p, char * pToken )
+{
+    char * pLine;
+    int i;
+    Vec_PtrForEachEntry( char *, p->vLines, pLine, i )
+        if ( pToken < pLine )
+            return i;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Conservatively estimates the number of primary inputs.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_BlifEstimatePiNum( Io_BlifMan_t * p )
+{
+    char * pCur;
+    int i, fSpaces;
+    int Counter = 0;
+    Vec_PtrForEachEntry( char *, p->vInputs, pCur, i )
+        for ( fSpaces = 0; *pCur; pCur++ )
+        {
+            if ( Io_BlifCharIsSpace(*pCur) )
+            {
+                if ( !fSpaces )
+                    Counter++;
+                fSpaces = 1;
+            }
+            else
+                fSpaces = 0;
+        }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Conservatively estimates the number of AIG nodes.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_BlifEstimateAndNum( Io_BlifMan_t * p )
+{
+    Io_BlifObj_t * pObj;
+    char * pCur;
+    int i, CounterOne, Counter = 0;
+    for ( i = 0; i < p->iObjNext; i++ )
+    {
+        pObj = p->pObjects + i;
+        if ( !pObj->fDef )
+            continue;
+        CounterOne = 0;
+        for ( pCur = pObj->pName + strlen(pObj->pName); *pCur != '.'; pCur++ )
+            if ( *pCur == '0' || *pCur == '1' )
+                CounterOne++;
+        if ( CounterOne )
+            Counter += CounterOne - 1;
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the file into a character buffer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static char * Io_BlifLoadFile( char * pFileName )
+{
+    FILE * pFile;
+    int nFileSize;
+    char * pContents;
+    int RetValue;
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Io_BlifLoadFile(): The file is unavailable (absent or open).\n" );
+        return NULL;
+    }
+    fseek( pFile, 0, SEEK_END );  
+    nFileSize = ftell( pFile ); 
+    if ( nFileSize == 0 )
+    {
+        fclose( pFile );
+        printf( "Io_BlifLoadFile(): The file is empty.\n" );
+        return NULL;
+    }
+    pContents = ABC_ALLOC( char, nFileSize + 10 );
+    rewind( pFile );
+    RetValue = fread( pContents, nFileSize, 1, pFile );
+    fclose( pFile );
+    // finish off the file with the spare .end line
+    // some benchmarks suddenly break off without this line
+    strcpy( pContents + nFileSize, "\n.end\n" );
+    return pContents;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the parsing.]
+
+  Description [Performs several preliminary operations:
+  - Cuts the file buffer into separate lines.
+  - Removes comments and line extenders.
+  - Sorts lines by directives.
+  - Estimates the number of objects.
+  - Allocates room for the objects.
+  - Allocates room for the hash table.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Io_BlifReadPreparse( Io_BlifMan_t * p )
+{
+    char * pCur, * pPrev;
+    int i, fComment = 0;
+    // parse the buffer into lines and remove comments
+    Vec_PtrPush( p->vLines, p->pBuffer );
+    for ( pCur = p->pBuffer; *pCur; pCur++ )
+    {
+        if ( *pCur == '\n' )
+        {
+            *pCur = 0;
+            fComment = 0;
+            Vec_PtrPush( p->vLines, pCur + 1 );
+        }
+        else if ( *pCur == '#' )
+            fComment = 1;
+        // remove comments
+        if ( fComment )
+            *pCur = 0;
+    }
+
+    // unfold the line extensions and sort lines by directive
+    Vec_PtrForEachEntry( char *, p->vLines, pCur, i )
+    {
+        if ( *pCur == 0 )
+            continue;
+        // find previous non-space character
+        for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- )
+            if ( !Io_BlifCharIsSpace(*pPrev) )
+                break;
+        // if it is the line extender, overwrite it with spaces
+        if ( *pPrev == '\\' )
+        {
+            for ( ; *pPrev; pPrev++ )
+                *pPrev = ' ';
+            *pPrev = ' ';
+            continue;
+        }
+        // skip spaces at the beginning of the line
+        while ( Io_BlifCharIsSpace(*pCur++) );
+        // parse directives
+        if ( *(pCur-1) != '.' )
+            continue;
+        if ( !strncmp(pCur, "names", 5) )
+            Vec_PtrPush( p->vNames, pCur );
+        else if ( !strncmp(pCur, "latch", 5) )
+            Vec_PtrPush( p->vLatches, pCur );
+        else if ( !strncmp(pCur, "inputs", 6) )
+            Vec_PtrPush( p->vInputs, pCur );
+        else if ( !strncmp(pCur, "outputs", 7) )
+            Vec_PtrPush( p->vOutputs, pCur );
+        else if ( !strncmp(pCur, "model", 5) ) 
+            p->pModel = pCur;
+        else if ( !strncmp(pCur, "end", 3) || !strncmp(pCur, "exdc", 4) )
+            break;
+        else
+        {
+            pCur--;
+            if ( pCur[strlen(pCur)-1] == '\r' )
+                pCur[strlen(pCur)-1] = 0;
+            fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_BlifGetLine(p, pCur), pCur );
+        }
+    }
+
+    // count the number of objects
+    p->nObjects = Io_BlifEstimatePiNum(p) + Vec_PtrSize(p->vLatches) + Vec_PtrSize(p->vNames) + 512;
+
+    // allocate memory for objects
+    p->pObjects = ABC_ALLOC( Io_BlifObj_t, p->nObjects );
+    memset( p->pObjects, 0, p->nObjects * sizeof(Io_BlifObj_t) );
+
+    // allocate memory for the hash table
+    p->nTableSize = p->nObjects/2 + 1;
+    p->pTable = ABC_ALLOC( Io_BlifObj_t *, p->nTableSize );
+    memset( p->pTable, 0, p->nTableSize * sizeof(Io_BlifObj_t *) );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the AIG in the binary AIGER format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Abc_Ntk_t * Io_BlifParse( Io_BlifMan_t * p )
+{
+    Abc_Ntk_t * pAig;
+    char * pLine;
+    int i;
+    // parse the model
+    if ( !Io_BlifParseModel( p, p->pModel ) )
+        return NULL;
+    // parse the inputs
+    Vec_PtrForEachEntry( char *, p->vInputs, pLine, i )
+        if ( !Io_BlifParseInputs( p, pLine ) )
+            return NULL;
+    // parse the outputs
+    Vec_PtrForEachEntry( char *, p->vOutputs, pLine, i )
+        if ( !Io_BlifParseOutputs( p, pLine ) )
+            return NULL;
+    // parse the latches
+    Vec_PtrForEachEntry( char *, p->vLatches, pLine, i )
+        if ( !Io_BlifParseLatch( p, pLine ) )
+            return NULL;
+    // parse the nodes
+    Vec_PtrForEachEntry( char *, p->vNames, pLine, i )
+        if ( !Io_BlifParseNames( p, pLine ) )
+            return NULL;
+    // reconstruct the network from the parsed data
+    if ( !Io_BlifParseConstruct( p ) )
+        return NULL;
+    // return the network
+    pAig = p->pAig;
+    p->pAig = NULL;
+    return pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the model line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_BlifParseModel( Io_BlifMan_t * p, char * pLine )
+{
+    char * pToken;
+    Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
+    pToken = (char *)Vec_PtrEntry( p->vTokens, 0 );
+    assert( !strcmp(pToken, "model") );
+    if ( Vec_PtrSize(p->vTokens) != 2 )
+    {
+        sprintf( p->sError, "Line %d: Model line has %d entries while it should have 2.", Io_BlifGetLine(p, pToken), Vec_PtrSize(p->vTokens) );
+        return 0;
+    }
+    p->pModel = (char *)Vec_PtrEntry( p->vTokens, 1 );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the inputs line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine )
+{
+    Io_BlifObj_t * pObj;
+    char * pToken;
+    int i;
+    Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
+    pToken = (char *)Vec_PtrEntry(p->vTokens, 0);
+    assert( !strcmp(pToken, "inputs") );
+    Vec_PtrForEachEntryStart( char *, p->vTokens, pToken, i, 1 )
+    {
+        pObj = Io_BlifHashFindOrAdd( p, pToken );
+        if ( pObj->fPi )
+        {
+            sprintf( p->sError, "Line %d: Primary input (%s) is defined more than once.", Io_BlifGetLine(p, pToken), pToken );
+            return 0;
+        }
+        pObj->fPi = 1;
+        Vec_PtrPush( p->vPis, pObj );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the outputs line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine )
+{
+    Io_BlifObj_t * pObj;
+    char * pToken;
+    int i;
+    Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
+    pToken = (char *)Vec_PtrEntry(p->vTokens, 0);
+    assert( !strcmp(pToken, "outputs") );
+    Vec_PtrForEachEntryStart( char *, p->vTokens, pToken, i, 1 )
+    {
+        pObj = Io_BlifHashFindOrAdd( p, pToken );
+        if ( pObj->fPo )
+            fprintf( stdout, "Line %d: Primary output (%s) is defined more than once (warning only).\n", Io_BlifGetLine(p, pToken), pToken );
+        pObj->fPo = 1;
+        Vec_PtrPush( p->vPos, pObj );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the latches line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine )
+{
+    Io_BlifObj_t * pObj;
+    char * pToken;
+    int Init;
+    Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
+    pToken = (char *)Vec_PtrEntry(p->vTokens,0);
+    assert( !strcmp(pToken, "latch") );
+    if ( Vec_PtrSize(p->vTokens) < 3 )
+    {
+        sprintf( p->sError, "Line %d: Latch does not have input name and output name.", Io_BlifGetLine(p, pToken) );
+        return 0;
+    }
+    // get initial value
+    if ( Vec_PtrSize(p->vTokens) > 3 )
+        Init = atoi( (char *)Vec_PtrEntry(p->vTokens,3) );
+    else
+        Init = 2;
+    if ( Init < 0 || Init > 2 )
+    {
+        sprintf( p->sError, "Line %d: Initial state of the latch is incorrect (%s).", Io_BlifGetLine(p, pToken), (char*)Vec_PtrEntry(p->vTokens,3) );
+        return 0;
+    }
+    if ( Init == 0 )
+        Init = IO_BLIF_INIT_ZERO;
+    else if ( Init == 1 )
+        Init = IO_BLIF_INIT_ONE;
+    else // if ( Init == 2 )
+        Init = IO_BLIF_INIT_DC;
+    // get latch input
+    pObj = Io_BlifHashFindOrAdd( p, (char *)Vec_PtrEntry(p->vTokens,1) );
+    pObj->fLi = 1;
+    Vec_PtrPush( p->vLis, pObj );
+    pObj->Init = Init;
+    // get latch output
+    pObj = Io_BlifHashFindOrAdd( p, (char *)Vec_PtrEntry(p->vTokens,2) );
+    if ( pObj->fPi )
+    {
+        sprintf( p->sError, "Line %d: Primary input (%s) is also defined latch output.", Io_BlifGetLine(p, pToken), (char*)Vec_PtrEntry(p->vTokens,2) );
+        return 0;
+    }
+    if ( pObj->fLo )
+    {
+        sprintf( p->sError, "Line %d: Latch output (%s) is defined as the output of another latch.", Io_BlifGetLine(p, pToken), (char*)Vec_PtrEntry(p->vTokens,2) );
+        return 0;
+    }
+    pObj->fLo = 1;
+    Vec_PtrPush( p->vLos, pObj );
+    pObj->Init = Init;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the nodes line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_BlifParseNames( Io_BlifMan_t * p, char * pLine )
+{
+    Io_BlifObj_t * pObj;
+    char * pName;
+    Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
+    assert( !strcmp((char *)Vec_PtrEntry(p->vTokens,0), "names") );
+    pName = (char *)Vec_PtrEntryLast( p->vTokens );
+    pObj = Io_BlifHashFindOrAdd( p, pName );
+    if ( pObj->fPi )
+    {
+        sprintf( p->sError, "Line %d: Primary input (%s) has a table.", Io_BlifGetLine(p, pName), pName );
+        return 0;
+    }
+    if ( pObj->fLo )
+    {
+        sprintf( p->sError, "Line %d: Latch output (%s) has a table.", Io_BlifGetLine(p, pName), pName );
+        return 0;
+    }
+    if ( pObj->fDef )
+    {
+        sprintf( p->sError, "Line %d: Signal (%s) is defined more than once.", Io_BlifGetLine(p, pName), pName );
+        return 0;
+    }
+    pObj->fDef = 1;
+    // remember offset to the first fanin name
+    pObj->pName = pName;
+    pObj->Offset = pObj->pName - (char *)Vec_PtrEntry(p->vTokens,1);
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs the AIG from the file parsing info.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Abc_Obj_t * Io_BlifParseTable( Io_BlifMan_t * p, char * pTable, Vec_Ptr_t * vFanins )
+{
+    char * pProduct, * pOutput;
+    Abc_Obj_t * pRes, * pCube;
+    int i, k, Polarity = -1;
+
+    p->nTablesRead++;
+    // get the tokens
+    Io_BlifSplitIntoTokens( p->vTokens, pTable, '.' );
+    if ( Vec_PtrSize(p->vTokens) == 0 )
+        return Abc_ObjNot( Abc_AigConst1(p->pAig) );
+    if ( Vec_PtrSize(p->vTokens) == 1 )
+    {
+        pOutput = (char *)Vec_PtrEntry( p->vTokens, 0 );
+        if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] )
+        {
+            sprintf( p->sError, "Line %d: Constant table has wrong output value (%s).", Io_BlifGetLine(p, pOutput), pOutput );
+            return NULL;
+        }
+        return Abc_ObjNotCond( Abc_AigConst1(p->pAig), pOutput[0] == '0' );
+    }
+    pProduct = (char *)Vec_PtrEntry( p->vTokens, 0 );
+    if ( Vec_PtrSize(p->vTokens) % 2 == 1 )
+    {
+        sprintf( p->sError, "Line %d: Table has odd number of tokens (%d).", Io_BlifGetLine(p, pProduct), Vec_PtrSize(p->vTokens) );
+        return NULL;
+    }
+    // parse the table
+    pRes = Abc_ObjNot( Abc_AigConst1(p->pAig) );
+    for ( i = 0; i < Vec_PtrSize(p->vTokens)/2; i++ )
+    {
+        pProduct = (char *)Vec_PtrEntry( p->vTokens, 2*i + 0 );
+        pOutput  = (char *)Vec_PtrEntry( p->vTokens, 2*i + 1 );
+        if ( strlen(pProduct) != (unsigned)Vec_PtrSize(vFanins) )
+        {
+            sprintf( p->sError, "Line %d: Cube (%s) has size different from the fanin count (%d).", Io_BlifGetLine(p, pProduct), pProduct, Vec_PtrSize(vFanins) );
+            return NULL;
+        }
+        if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] )
+        {
+            sprintf( p->sError, "Line %d: Output value (%s) is incorrect.", Io_BlifGetLine(p, pProduct), pOutput );
+            return NULL;
+        }
+        if ( Polarity == -1 )
+            Polarity = pOutput[0] - '0';
+        else if ( Polarity != pOutput[0] - '0' )
+        {
+            sprintf( p->sError, "Line %d: Output value (%s) differs from the value in the first line of the table (%d).", Io_BlifGetLine(p, pProduct), pOutput, Polarity );
+            return NULL;
+        }
+        // parse one product product
+        pCube = Abc_AigConst1(p->pAig);
+        for ( k = 0; pProduct[k]; k++ )
+        {
+            if ( pProduct[k] == '0' )
+                pCube = Abc_AigAnd( (Abc_Aig_t *)p->pAig->pManFunc, pCube, Abc_ObjNot((Abc_Obj_t *)Vec_PtrEntry(vFanins,k)) );
+            else if ( pProduct[k] == '1' )
+                pCube = Abc_AigAnd( (Abc_Aig_t *)p->pAig->pManFunc, pCube, (Abc_Obj_t *)Vec_PtrEntry(vFanins,k) );
+            else if ( pProduct[k] != '-' )
+            {
+                sprintf( p->sError, "Line %d: Product term (%s) contains character (%c).", Io_BlifGetLine(p, pProduct), pProduct, pProduct[k] );
+                return NULL;
+            }
+        }
+        pRes = Abc_AigOr( (Abc_Aig_t *)p->pAig->pManFunc, pRes, pCube );
+    }
+    pRes = Abc_ObjNotCond( pRes, Polarity == 0 );
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs the AIG from the file parsing info.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Abc_Obj_t * Io_BlifParseConstruct_rec( Io_BlifMan_t * p, char * pName )
+{
+    Vec_Ptr_t * vFanins;
+    Abc_Obj_t * pFaninAbc;
+    Io_BlifObj_t * pObjIo;
+    char * pNameFanin;
+    int i;
+    // get the IO object with this name
+    pObjIo = *Io_BlifHashLookup( p, pName );
+    if ( pObjIo == NULL )
+    {
+        sprintf( p->sError, "Line %d: Signal (%s) is not defined as a table.", Io_BlifGetLine(p, pName), pName );
+        return NULL;
+    }
+    // loop detection
+    if ( pObjIo->fLoop )
+    {
+        sprintf( p->sError, "Line %d: Signal (%s) appears twice on a combinational path.", Io_BlifGetLine(p, pName), pName );
+        return NULL;
+    }
+    // check if the AIG is already constructed
+    if ( pObjIo->pEquiv )
+        return (Abc_Obj_t *)pObjIo->pEquiv;
+    // mark this node on the path
+    pObjIo->fLoop = 1;
+    // construct the AIGs for the fanins
+    vFanins = Vec_PtrAlloc( 8 );
+    Io_BlifCollectTokens( vFanins, pObjIo->pName - pObjIo->Offset, pObjIo->pName );
+    Vec_PtrForEachEntry( char *, vFanins, pNameFanin, i )
+    {
+        pFaninAbc = Io_BlifParseConstruct_rec( p, pNameFanin );
+        if ( pFaninAbc == NULL )
+        {
+            Vec_PtrFree( vFanins );
+            return NULL;
+        }
+        Vec_PtrWriteEntry( vFanins, i, pFaninAbc );
+    }
+    // construct the node
+    pObjIo->pEquiv = Io_BlifParseTable( p, pObjIo->pName + strlen(pObjIo->pName), vFanins );
+    Vec_PtrFree( vFanins );
+    // unmark this node on the path
+    pObjIo->fLoop = 0;
+    // remember the new node
+    return (Abc_Obj_t *)pObjIo->pEquiv;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs the AIG from the file parsing info.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_BlifParseConstruct( Io_BlifMan_t * p )
+{
+    Abc_Ntk_t * pAig;
+    Io_BlifObj_t * pObjIo, * pObjIoInput;
+    Abc_Obj_t * pObj, * pLatch;
+    int i;
+    // allocate the empty AIG
+    pAig = p->pAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    pAig->pName = Extra_UtilStrsav( p->pModel );
+    pAig->pSpec = Extra_UtilStrsav( p->pFileName );
+    // create PIs
+    Vec_PtrForEachEntry( Io_BlifObj_t *, p->vPis, pObjIo, i )
+    {
+        pObj = Abc_NtkCreatePi( pAig );
+        Abc_ObjAssignName( pObj, pObjIo->pName, NULL );
+        pObjIo->pEquiv = pObj;
+    }
+    // create POs
+    Vec_PtrForEachEntry( Io_BlifObj_t *, p->vPos, pObjIo, i )
+    {
+        pObj = Abc_NtkCreatePo( pAig );
+        Abc_ObjAssignName( pObj, pObjIo->pName, NULL );
+    }
+    // create latches
+    Vec_PtrForEachEntry( Io_BlifObj_t *, p->vLos, pObjIo, i )
+    {
+        // add the latch input terminal
+        pObj = Abc_NtkCreateBi( pAig );
+        pObjIoInput = (Io_BlifObj_t *)Vec_PtrEntry( p->vLis, i );
+        Abc_ObjAssignName( pObj, pObjIoInput->pName, NULL );
+        
+        // add the latch box
+        pLatch = Abc_NtkCreateLatch( pAig );
+        pLatch->pData = (void *)(ABC_PTRUINT_T)pObjIo->Init;
+        Abc_ObjAssignName( pLatch, pObjIo->pName, "L" );
+        Abc_ObjAddFanin( pLatch, pObj  );
+
+        // add the latch output terminal
+        pObj = Abc_NtkCreateBo( pAig );
+        Abc_ObjAssignName( pObj, pObjIo->pName, NULL );
+        Abc_ObjAddFanin( pObj, pLatch );
+        // set the value of the latch output
+//        pObjIo->pEquiv = Abc_ObjNotCond( pObj, pObjIo->Init );
+        pObjIo->pEquiv = pObj;
+    }
+    // traverse the nodes from the POs
+    Vec_PtrForEachEntry( Io_BlifObj_t *, p->vPos, pObjIo, i )
+    {
+        pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName );
+        if ( pObj == NULL )
+            return 0;
+        Abc_ObjAddFanin( Abc_NtkPo(p->pAig, i), pObj );
+    }
+    // traverse the nodes from the latch inputs
+    Vec_PtrForEachEntry( Io_BlifObj_t *, p->vLis, pObjIo, i )
+    {
+        pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName );
+        if ( pObj == NULL )
+            return 0;
+//        pObj = Abc_ObjNotCond( pObj, pObjIo->Init );
+        Abc_ObjAddFanin( Abc_ObjFanin0(Abc_NtkBox(p->pAig, i)), pObj );
+    }
+    p->nTablesLeft = Vec_PtrSize(p->vNames) - p->nTablesRead; 
+    if ( p->nTablesLeft ) 
+        printf( "The number of dangling tables = %d.\n", p->nTablesLeft );
+    printf( "AND nodes = %6d.  Estimate = %6d.\n", Abc_NtkNodeNum(p->pAig), Io_BlifEstimateAndNum(p) );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioReadBlifMv.c b/abc-build/src/base/io/ioReadBlifMv.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioReadBlifMv.c
@@ -0,0 +1,2237 @@
+/**CFile****************************************************************
+
+  FileName    [ioReadBlifMv.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to read BLIF-MV file.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 8, 2007.]
+
+  Revision    [$Id: ioReadBlifMv.c,v 1.00 2007/01/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/vec/vecPtr.h"
+#include "ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define IO_BLIFMV_MAXVALUES 256
+//#define IO_VERBOSE_OUTPUT
+
+typedef struct Io_MvVar_t_ Io_MvVar_t; // parsing var
+typedef struct Io_MvMod_t_ Io_MvMod_t; // parsing model
+typedef struct Io_MvMan_t_ Io_MvMan_t; // parsing manager
+
+Vec_Ptr_t *vGlobalLtlArray;
+
+struct Io_MvVar_t_
+{
+    int                  nValues;      // the number of values 
+    char **              pNames;       // the value names
+};
+
+struct Io_MvMod_t_
+{
+    // file lines
+    char *               pName;        // .model line
+    Vec_Ptr_t *          vInputs;      // .inputs lines
+    Vec_Ptr_t *          vOutputs;     // .outputs lines
+    Vec_Ptr_t *          vLatches;     // .latch lines
+    Vec_Ptr_t *          vFlops;       // .flop lines
+    Vec_Ptr_t *          vResets;      // .reset lines
+    Vec_Ptr_t *          vNames;       // .names lines
+    Vec_Ptr_t *          vSubckts;     // .subckt lines
+    Vec_Ptr_t *          vShorts;      // .short lines
+    Vec_Ptr_t *          vOnehots;     // .onehot lines
+    Vec_Ptr_t *          vMvs;         // .mv lines
+    Vec_Ptr_t *          vConstrs;     // .constraint lines
+	Vec_Ptr_t *			 vLtlProperties;
+    int                  fBlackBox;    // indicates blackbox model
+    // the resulting network
+    Abc_Ntk_t *          pNtk;   
+    Abc_Obj_t *          pResetLatch; 
+    // the parent manager
+    Io_MvMan_t *         pMan;         
+};
+
+struct Io_MvMan_t_
+{
+    // general info about file
+    int                  fBlifMv;      // the file is BLIF-MV
+    int                  fUseReset;    // the reset circuitry is added
+    char *               pFileName;    // the name of the file
+    char *               pBuffer;      // the contents of the file
+    Vec_Ptr_t *          vLines;       // the line beginnings
+    // the results of reading
+    Abc_Des_t *          pDesign;      // the design under construction
+    int                  nNDnodes;     // the counter of ND nodes
+    // intermediate storage for models
+    Vec_Ptr_t *          vModels;      // vector of models
+    Io_MvMod_t *         pLatest;      // the current model
+    // current processing info
+    Vec_Ptr_t *          vTokens;      // the current tokens
+    Vec_Ptr_t *          vTokens2;     // the current tokens
+    Vec_Str_t *          vFunc;        // the local function
+    // error reporting
+    char                 sError[512];  // the error string generated during parsing
+    // statistics 
+    int                  nTablesRead;  // the number of processed tables
+    int                  nTablesLeft;  // the number of dangling tables
+};
+
+// static functions
+static Io_MvMan_t *      Io_MvAlloc();
+static void              Io_MvFree( Io_MvMan_t * p );
+static Io_MvMod_t *      Io_MvModAlloc();
+static void              Io_MvModFree( Io_MvMod_t * p );
+static char *            Io_MvLoadFile( char * pFileName );
+static void              Io_MvReadPreparse( Io_MvMan_t * p );
+static int               Io_MvReadInterfaces( Io_MvMan_t * p );
+static Abc_Des_t *       Io_MvParse( Io_MvMan_t * p );
+static int               Io_MvParseLineModel( Io_MvMod_t * p, char * pLine );
+static int               Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine );
+static int               Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine );
+static int               Io_MvParseLineConstrs( Io_MvMod_t * p, char * pLine );
+static int               Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine );
+static int               Io_MvParseLineFlop( Io_MvMod_t * p, char * pLine );
+static int               Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine );
+static Vec_Int_t *       Io_MvParseLineOnehot( Io_MvMod_t * p, char * pLine );
+static int               Io_MvParseLineMv( Io_MvMod_t * p, char * pLine );
+static int               Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset );
+static int               Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine );
+static int               Io_MvParseLineShortBlif( Io_MvMod_t * p, char * pLine );
+static int				 Io_MvParseLineLtlProperty( Io_MvMod_t * p, char * pLine );
+static int               Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens );
+static Io_MvVar_t *      Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar );
+
+static int               Io_MvCharIsSpace( char s )  { return s == ' ' || s == '\t' || s == '\r' || s == '\n';  }
+static int               Io_MvCharIsMvSymb( char s ) { return s == '(' || s == ')' || s == '{' || s == '}' || s == '-' || s == ',' || s == '!';  }
+
+extern void              Abc_NtkStartMvVars( Abc_Ntk_t * pNtk );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the network from the BLIF or BLIF-MV file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck )
+{
+    FILE * pFile;
+    Io_MvMan_t * p;
+    Abc_Ntk_t * pNtk, * pExdc;
+    Abc_Des_t * pDesign = NULL; 
+    char * pDesignName;
+    int RetValue, i;
+	char * pLtlProp;
+
+    // check that the file is available
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Io_ReadBlifMv(): The file is unavailable (absent or open).\n" );
+        return 0;
+    }
+    fclose( pFile );
+
+    // start the file reader
+    p = Io_MvAlloc();
+    p->fBlifMv   = fBlifMv;
+    p->fUseReset = 1;
+    p->pFileName = pFileName;
+    p->pBuffer   = Io_MvLoadFile( pFileName );
+    if ( p->pBuffer == NULL )
+    {
+        Io_MvFree( p );
+        return NULL;
+    }
+    // set the design name
+    pDesignName  = Extra_FileNameGeneric( pFileName );
+    p->pDesign   = Abc_DesCreate( pDesignName );
+    ABC_FREE( pDesignName );
+    // free the HOP manager
+    Hop_ManStop( (Hop_Man_t *)p->pDesign->pManFunc );
+    p->pDesign->pManFunc = NULL;
+    // prepare the file for parsing
+    Io_MvReadPreparse( p );
+    // parse interfaces of each network and construct the network
+    if ( Io_MvReadInterfaces( p ) )
+        pDesign = Io_MvParse( p );
+    if ( p->sError[0] )
+        fprintf( stdout, "%s\n", p->sError );
+    Io_MvFree( p );
+    if ( pDesign == NULL )
+        return NULL;
+// pDesign should be linked to all models of the design
+
+    // make sure that everything is okay with the network structure
+    if ( fCheck )
+    {
+        Vec_PtrForEachEntry( Abc_Ntk_t *, pDesign->vModules, pNtk, i )
+        {
+            if ( !Abc_NtkCheckRead( pNtk ) )
+            {
+                printf( "Io_ReadBlifMv: The network check has failed for model %s.\n", pNtk->pName );
+                Abc_DesFree( pDesign, NULL );
+                return NULL;
+            }
+        }
+    }
+
+//Abc_DesPrint( pDesign );
+
+    // check if there is an EXDC network
+    if ( Vec_PtrSize(pDesign->vModules) > 1 )
+    {
+        pNtk = (Abc_Ntk_t *)Vec_PtrEntry(pDesign->vModules, 0);
+        Vec_PtrForEachEntryStart( Abc_Ntk_t *, pDesign->vModules, pExdc, i, 1 )
+            if ( !strcmp(pExdc->pName, "EXDC") )
+            {
+                assert( pNtk->pExdc == NULL );
+                pNtk->pExdc = pExdc;
+                Vec_PtrRemove(pDesign->vModules, pExdc);
+                pExdc->pDesign = NULL;
+                i--;
+            }
+            else
+                pNtk = pExdc;
+    }
+
+    // detect top-level model
+    RetValue = Abc_DesFindTopLevelModels( pDesign );
+    pNtk = (Abc_Ntk_t *)Vec_PtrEntry( pDesign->vTops, 0 );
+    if ( RetValue > 1 )
+        printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n",
+            Vec_PtrSize(pDesign->vTops), pNtk->pName );
+
+    // extract the master network
+    pNtk->pDesign = pDesign;
+    pDesign->pManFunc = NULL;
+
+    // verify the design for cyclic dependence
+    assert( Vec_PtrSize(pDesign->vModules) > 0 );
+    if ( Vec_PtrSize(pDesign->vModules) == 1 )
+    {
+//        printf( "Warning: The design is not hierarchical.\n" );
+        Abc_DesFree( pDesign, pNtk );
+        pNtk->pDesign = NULL;
+        pNtk->pSpec = Extra_UtilStrsav( pFileName );
+    }
+    else
+        Abc_NtkIsAcyclicHierarchy( pNtk );
+
+//Io_WriteBlifMv( pNtk, "_temp_.mv" );
+    if ( pNtk->pSpec == NULL )
+        pNtk->pSpec = Extra_UtilStrsav( pFileName );
+
+	vGlobalLtlArray = Vec_PtrAlloc( 100 );
+	Vec_PtrForEachEntry( char *, vGlobalLtlArray, pLtlProp, i )
+		Vec_PtrPush( pNtk->vLtlProperties, pLtlProp );
+    Vec_PtrFreeP( &vGlobalLtlArray );
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the BLIF parsing structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Io_MvMan_t * Io_MvAlloc()
+{
+    Io_MvMan_t * p;
+    p = ABC_ALLOC( Io_MvMan_t, 1 );
+    memset( p, 0, sizeof(Io_MvMan_t) );
+    p->vLines   = Vec_PtrAlloc( 512 );
+    p->vModels  = Vec_PtrAlloc( 512 );
+    p->vTokens  = Vec_PtrAlloc( 512 );
+    p->vTokens2 = Vec_PtrAlloc( 512 );
+    p->vFunc    = Vec_StrAlloc( 512 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the BLIF parsing structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Io_MvFree( Io_MvMan_t * p )
+{
+    Io_MvMod_t * pMod;
+    int i;
+    if ( p->pDesign )
+        Abc_DesFree( p->pDesign, NULL );
+    if ( p->pBuffer )  
+        ABC_FREE( p->pBuffer );
+    if ( p->vLines )
+        Vec_PtrFree( p->vLines  );
+    if ( p->vModels )
+    {
+        Vec_PtrForEachEntry( Io_MvMod_t *, p->vModels, pMod, i )
+            Io_MvModFree( pMod );
+        Vec_PtrFree( p->vModels );
+    }
+    Vec_PtrFree( p->vTokens );
+    Vec_PtrFree( p->vTokens2 );
+    Vec_StrFree( p->vFunc );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the BLIF parsing structure for one model.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Io_MvMod_t * Io_MvModAlloc()
+{
+    Io_MvMod_t * p;
+    p = ABC_ALLOC( Io_MvMod_t, 1 );
+    memset( p, 0, sizeof(Io_MvMod_t) );
+    p->vInputs  = Vec_PtrAlloc( 512 );
+    p->vOutputs = Vec_PtrAlloc( 512 );
+    p->vLatches = Vec_PtrAlloc( 512 );
+    p->vFlops   = Vec_PtrAlloc( 512 );
+    p->vResets  = Vec_PtrAlloc( 512 );
+    p->vNames   = Vec_PtrAlloc( 512 );
+    p->vSubckts = Vec_PtrAlloc( 512 );
+    p->vShorts  = Vec_PtrAlloc( 512 );
+    p->vOnehots = Vec_PtrAlloc( 512 );
+    p->vMvs     = Vec_PtrAlloc( 512 );
+    p->vConstrs = Vec_PtrAlloc( 512 );
+	p->vLtlProperties = Vec_PtrAlloc( 512 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the BLIF parsing structure for one model.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Io_MvModFree( Io_MvMod_t * p )
+{
+//    if ( p->pNtk )
+//        Abc_NtkDelete( p->pNtk );
+    Vec_PtrFree( p->vLtlProperties );
+    Vec_PtrFree( p->vInputs );
+    Vec_PtrFree( p->vOutputs );
+    Vec_PtrFree( p->vLatches );
+    Vec_PtrFree( p->vFlops );
+    Vec_PtrFree( p->vResets );
+    Vec_PtrFree( p->vNames );
+    Vec_PtrFree( p->vSubckts );
+    Vec_PtrFree( p->vShorts );
+    Vec_PtrFree( p->vOnehots );
+    Vec_PtrFree( p->vMvs );
+    Vec_PtrFree( p->vConstrs );
+    ABC_FREE( p );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of given chars.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvCountChars( char * pLine, char Char )
+{
+    char * pCur;
+    int Counter = 0;
+    for ( pCur = pLine; *pCur; pCur++ )
+        if ( *pCur == Char )
+            Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the place where the arrow is hiding.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static char * Io_MvFindArrow( char * pLine )
+{
+    char * pCur;
+    for ( pCur = pLine; *(pCur+1); pCur++ )
+        if ( *pCur == '-' && *(pCur+1) == '>' )
+        {
+            *pCur = ' ';
+            *(pCur+1) = ' ';
+            return pCur;
+        }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the already split tokens.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Io_MvCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput )
+{
+    char * pCur;
+    Vec_PtrClear( vTokens );
+    for ( pCur = pInput; pCur < pOutput; pCur++ )
+    {
+        if ( *pCur == 0 )
+            continue;
+        Vec_PtrPush( vTokens, pCur );
+        while ( *++pCur );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Splits the line into tokens.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Io_MvSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop )
+{
+    char * pCur;
+    // clear spaces
+    for ( pCur = pLine; *pCur != Stop; pCur++ )
+        if ( Io_MvCharIsSpace(*pCur) )
+            *pCur = 0;
+    // collect tokens
+    Io_MvCollectTokens( vTokens, pLine, pCur );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Splits the line into tokens when .default may be present.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Io_MvSplitIntoTokensMv( Vec_Ptr_t * vTokens, char * pLine )
+{
+    char * pCur;
+    // clear spaces
+    for ( pCur = pLine; *pCur != '.' || *(pCur+1) == 'd'; pCur++ )
+        if ( Io_MvCharIsSpace(*pCur) )
+            *pCur = 0;
+    // collect tokens
+    Io_MvCollectTokens( vTokens, pLine, pCur );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Splits the line into tokens.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Io_MvSplitIntoTokensAndClear( Vec_Ptr_t * vTokens, char * pLine, char Stop, char Char )
+{
+    char * pCur;
+    // clear spaces
+    for ( pCur = pLine; *pCur != Stop; pCur++ )
+        if ( Io_MvCharIsSpace(*pCur) || *pCur == Char )
+            *pCur = 0;
+    // collect tokens
+    Io_MvCollectTokens( vTokens, pLine, pCur );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the 1-based number of the line in which the token occurs.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvGetLine( Io_MvMan_t * p, char * pToken )
+{
+    char * pLine;
+    int i;
+    Vec_PtrForEachEntry( char *, p->vLines, pLine, i )
+        if ( pToken < pLine )
+            return i;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the file into a character buffer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static char * Io_MvLoadFile( char * pFileName )
+{
+    FILE * pFile;
+    int nFileSize;
+    char * pContents;
+    int RetValue;
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Io_MvLoadFile(): The file is unavailable (absent or open).\n" );
+        return NULL;
+    }
+    fseek( pFile, 0, SEEK_END );  
+    nFileSize = ftell( pFile ); 
+    if ( nFileSize == 0 )
+    {
+        fclose( pFile );
+        printf( "Io_MvLoadFile(): The file is empty.\n" );
+        return NULL;
+    }
+    pContents = ABC_ALLOC( char, nFileSize + 10 );
+    rewind( pFile );
+    RetValue = fread( pContents, nFileSize, 1, pFile );
+    fclose( pFile );
+    // finish off the file with the spare .end line
+    // some benchmarks suddenly break off without this line
+    strcpy( pContents + nFileSize, "\n.end\n" );
+    return pContents;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the parsing.]
+
+  Description [Performs several preliminary operations:
+  - Cuts the file buffer into separate lines.
+  - Removes comments and line extenders.
+  - Sorts lines by directives.
+  - Estimates the number of objects.
+  - Allocates room for the objects.
+  - Allocates room for the hash table.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Io_MvReadPreparse( Io_MvMan_t * p )
+{
+    char * pCur, * pPrev;
+    int i, fComment = 0;
+    // parse the buffer into lines and remove comments
+    Vec_PtrPush( p->vLines, p->pBuffer );
+    for ( pCur = p->pBuffer; *pCur; pCur++ )
+    {
+        if ( *pCur == '\n' )
+        {
+            *pCur = 0;
+//            if ( *(pCur-1) == '\r' )
+//                *(pCur-1) = 0;
+            fComment = 0;
+            Vec_PtrPush( p->vLines, pCur + 1 );
+        }
+        else if ( *pCur == '#' )
+            fComment = 1;
+        // remove comments
+        if ( fComment )
+            *pCur = 0;
+    }
+
+    // unfold the line extensions and sort lines by directive
+    Vec_PtrForEachEntry( char *, p->vLines, pCur, i )
+    {
+        if ( *pCur == 0 )
+            continue;
+        // find previous non-space character
+        for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- )
+            if ( !Io_MvCharIsSpace(*pPrev) )
+                break;
+        // if it is the line extender, overwrite it with spaces
+        if ( pPrev >= p->pBuffer && *pPrev == '\\' )
+        {
+            for ( ; *pPrev; pPrev++ )
+                *pPrev = ' ';
+            *pPrev = ' ';
+            continue;
+        }
+        // skip spaces at the beginning of the line
+        while ( Io_MvCharIsSpace(*pCur++) );
+        // parse directives
+        if ( *(pCur-1) != '.' )
+            continue;
+        if ( !strncmp(pCur, "names", 5) || !strncmp(pCur, "table", 5) || !strncmp(pCur, "gate", 4) )
+            Vec_PtrPush( p->pLatest->vNames, pCur );
+        else if ( p->fBlifMv && (!strncmp(pCur, "def ", 4) || !strncmp(pCur, "default ", 8)) )
+            continue;
+		else if ( !strncmp( pCur, "ltlformula", 10 ) )
+            Vec_PtrPush( p->pLatest->vLtlProperties, pCur );
+        else if ( !strncmp(pCur, "latch", 5) )
+            Vec_PtrPush( p->pLatest->vLatches, pCur );
+        else if ( !strncmp(pCur, "flop", 4) )
+            Vec_PtrPush( p->pLatest->vFlops, pCur );
+        else if ( !strncmp(pCur, "r ", 2) || !strncmp(pCur, "reset ", 6) )
+            Vec_PtrPush( p->pLatest->vResets, pCur );
+        else if ( !strncmp(pCur, "inputs", 6) )
+            Vec_PtrPush( p->pLatest->vInputs, pCur );
+        else if ( !strncmp(pCur, "outputs", 7) )
+            Vec_PtrPush( p->pLatest->vOutputs, pCur );
+        else if ( !strncmp(pCur, "subckt", 6) )
+            Vec_PtrPush( p->pLatest->vSubckts, pCur );
+        else if ( !strncmp(pCur, "short", 5) )
+            Vec_PtrPush( p->pLatest->vShorts, pCur );
+        else if ( !strncmp(pCur, "onehot", 6) )
+            Vec_PtrPush( p->pLatest->vOnehots, pCur );
+        else if ( p->fBlifMv && !strncmp(pCur, "mv", 2) )
+            Vec_PtrPush( p->pLatest->vMvs, pCur );
+        else if ( !strncmp(pCur, "constraint", 10) )
+            Vec_PtrPush( p->pLatest->vConstrs, pCur );
+        else if ( !strncmp(pCur, "blackbox", 8) )
+            p->pLatest->fBlackBox = 1;
+        else if ( !strncmp(pCur, "model", 5) ) 
+        {
+            p->pLatest = Io_MvModAlloc();
+            p->pLatest->pName = pCur;
+            p->pLatest->pMan = p;
+        }
+        else if ( !strncmp(pCur, "end", 3) )
+        {
+            if ( p->pLatest )
+                Vec_PtrPush( p->vModels, p->pLatest );
+            p->pLatest = NULL;
+        }
+        else if ( !strncmp(pCur, "exdc", 4) )
+        {
+//            fprintf( stdout, "Line %d: The design contains EXDC network (warning only).\n", Io_MvGetLine(p, pCur) );
+            fprintf( stdout, "Warning: The design contains EXDC network.\n" );
+            if ( p->pLatest )
+                Vec_PtrPush( p->vModels, p->pLatest );
+            p->pLatest = Io_MvModAlloc();
+            p->pLatest->pName = NULL;
+            p->pLatest->pMan = p;
+        }
+        else if ( !strncmp(pCur, "attrib", 6) )
+        {}
+        else if ( !strncmp(pCur, "delay", 5) )
+        {}
+        else if ( !strncmp(pCur, "input_", 6) )
+        {}
+        else if ( !strncmp(pCur, "output_", 7) )
+        {}
+        else if ( !strncmp(pCur, "no_merge", 8) )
+        {}
+        else if ( !strncmp(pCur, "wd", 2) )
+        {}
+//        else if ( !strncmp(pCur, "inouts", 6) )
+//        {}
+        else
+        {
+            pCur--;
+            if ( pCur[strlen(pCur)-1] == '\r' )
+                pCur[strlen(pCur)-1] = 0;
+            fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_MvGetLine(p, pCur), pCur );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses interfaces of the models.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvReadInterfaces( Io_MvMan_t * p )
+{
+    Io_MvMod_t * pMod;
+    char * pLine;
+    int i, k, nOutsOld;
+    // iterate through the models
+    Vec_PtrForEachEntry( Io_MvMod_t *, p->vModels, pMod, i )
+    {
+        // parse the model
+        if ( !Io_MvParseLineModel( pMod, pMod->pName ) )
+            return 0;
+        // add model to the design
+        if ( !Abc_DesAddModel( p->pDesign, pMod->pNtk ) )
+        {
+            sprintf( p->sError, "Line %d: Model %s is defined twice.", Io_MvGetLine(p, pMod->pName), pMod->pName );
+            return 0;
+        }
+        // parse the inputs
+        Vec_PtrForEachEntry( char *, pMod->vInputs, pLine, k )
+            if ( !Io_MvParseLineInputs( pMod, pLine ) )
+                return 0;
+        // parse the outputs
+        Vec_PtrForEachEntry( char *, pMod->vOutputs, pLine, k )
+            if ( !Io_MvParseLineOutputs( pMod, pLine ) )
+                return 0;
+        // parse the constraints
+        nOutsOld = Abc_NtkPoNum(pMod->pNtk);
+        Vec_PtrForEachEntry( char *, pMod->vConstrs, pLine, k )
+            if ( !Io_MvParseLineConstrs( pMod, pLine ) )
+                return 0;
+        pMod->pNtk->nConstrs = Abc_NtkPoNum(pMod->pNtk) - nOutsOld;
+		Vec_PtrForEachEntry( char *, pMod->vLtlProperties, pLine, k )
+			if ( !Io_MvParseLineLtlProperty( pMod, pLine ) )
+                return 0;
+        // report the results
+#ifdef IO_VERBOSE_OUTPUT
+        if ( Vec_PtrSize(p->vModels) > 1 )
+		    printf( "Parsed %-32s: PI =%6d  PO =%6d  ND =%8d  FF =%6d  B =%6d\n", 
+			    pMod->pNtk->pName, Abc_NtkPiNum(pMod->pNtk), Abc_NtkPoNum(pMod->pNtk),
+			    Vec_PtrSize(pMod->vNames), Vec_PtrSize(pMod->vLatches), Vec_PtrSize(pMod->vSubckts) );
+#endif
+    }
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Abc_Des_t * Io_MvParse( Io_MvMan_t * p )
+{
+    Abc_Des_t * pDesign;
+    Io_MvMod_t * pMod;
+    char * pLine;
+    int i, k;
+    // iterate through the models
+    Vec_PtrForEachEntry( Io_MvMod_t *, p->vModels, pMod, i )
+    { 
+#ifdef IO_VERBOSE_OUTPUT
+        if ( Vec_PtrSize(p->vModels) > 1 )
+            printf( "Parsing model %s...\n", pMod->pNtk->pName );
+#endif
+
+        // check if there any MV lines
+        if ( Vec_PtrSize(pMod->vMvs) > 0 )
+            Abc_NtkStartMvVars( pMod->pNtk );
+        // parse the mv lines
+        Vec_PtrForEachEntry( char *, pMod->vMvs, pLine, k )
+            if ( !Io_MvParseLineMv( pMod, pLine ) )
+                return NULL;
+        // if reset lines are used there should be the same number of them as latches
+        if ( Vec_PtrSize(pMod->vResets) > 0 )
+        {
+            if ( Vec_PtrSize(pMod->vLatches) != Vec_PtrSize(pMod->vResets) )
+            {
+                sprintf( p->sError, "Line %d: Model %s has different number of latches (%d) and reset nodes (%d).", 
+                    Io_MvGetLine(p, pMod->pName), Abc_NtkName(pMod->pNtk), Vec_PtrSize(pMod->vLatches), Vec_PtrSize(pMod->vResets) );
+                return NULL;
+            }
+            // create binary latch with 1-data and 0-init
+            if ( p->fUseReset ) 
+                pMod->pResetLatch = Io_ReadCreateResetLatch( pMod->pNtk, p->fBlifMv );
+        }
+        // parse the flops
+        Vec_PtrForEachEntry( char *, pMod->vFlops, pLine, k )
+            if ( !Io_MvParseLineFlop( pMod, pLine ) )
+                return NULL;
+        // parse the latches
+        Vec_PtrForEachEntry( char *, pMod->vLatches, pLine, k )
+            if ( !Io_MvParseLineLatch( pMod, pLine ) )
+                return NULL;
+        // parse the reset lines
+        if ( p->fUseReset )
+            Vec_PtrForEachEntry( char *, pMod->vResets, pLine, k )
+                if ( !Io_MvParseLineNamesMv( pMod, pLine, 1 ) )
+                    return NULL;
+        // parse the nodes
+        if ( p->fBlifMv )
+        {
+            Vec_PtrForEachEntry( char *, pMod->vNames, pLine, k )
+                if ( !Io_MvParseLineNamesMv( pMod, pLine, 0 ) )
+                    return NULL;
+        }
+        else
+        {
+            Vec_PtrForEachEntry( char *, pMod->vNames, pLine, k )
+                if ( !Io_MvParseLineNamesBlif( pMod, pLine ) )
+                    return NULL;
+            Vec_PtrForEachEntry( char *, pMod->vShorts, pLine, k )
+                if ( !Io_MvParseLineShortBlif( pMod, pLine ) )
+                    return NULL;
+        }
+        // parse the subcircuits
+        Vec_PtrForEachEntry( char *, pMod->vSubckts, pLine, k )
+            if ( !Io_MvParseLineSubckt( pMod, pLine ) )
+                return NULL;
+
+        // allow for blackboxes without .blackbox line
+        if ( Abc_NtkLatchNum(pMod->pNtk) == 0 && Abc_NtkNodeNum(pMod->pNtk) == 0 && Abc_NtkBoxNum(pMod->pNtk) == 0 )
+        {
+            if ( pMod->pNtk->ntkFunc == ABC_FUNC_SOP )
+            {
+                Mem_FlexStop( (Mem_Flex_t *)pMod->pNtk->pManFunc, 0 );
+                pMod->pNtk->pManFunc = NULL;
+                pMod->pNtk->ntkFunc = ABC_FUNC_BLACKBOX;
+            }
+        }
+
+        // finalize the network
+        Abc_NtkFinalizeRead( pMod->pNtk );
+        // read the one-hotness lines
+        if ( Vec_PtrSize(pMod->vOnehots) > 0 )
+        {
+            Vec_Int_t * vLine; 
+            Abc_Obj_t * pObj;
+            // set register numbers
+            Abc_NtkForEachLatch( pMod->pNtk, pObj, k )
+                pObj->pNext = (Abc_Obj_t *)(ABC_PTRINT_T)k;
+            // derive register
+            pMod->pNtk->vOnehots = Vec_PtrAlloc( Vec_PtrSize(pMod->vOnehots) );
+            Vec_PtrForEachEntry( char *, pMod->vOnehots, pLine, k )
+            {
+                vLine = Io_MvParseLineOnehot( pMod, pLine );
+                if ( vLine == NULL )
+                    return NULL;
+                Vec_PtrPush( pMod->pNtk->vOnehots, vLine );
+//                printf( "Parsed %d one-hot registers.\n", Vec_IntSize(vLine) );
+            }
+            // reset register numbers
+            Abc_NtkForEachLatch( pMod->pNtk, pObj, k )
+                pObj->pNext = NULL;
+            // print the result
+            printf( "Parsed %d groups of 1-hot registers: { ", Vec_PtrSize(pMod->pNtk->vOnehots) );
+            Vec_PtrForEachEntry( Vec_Int_t *, pMod->pNtk->vOnehots, vLine, k )
+                printf( "%d ", Vec_IntSize(vLine) );
+            printf( "}\n" );
+            printf( "The total number of 1-hot registers = %d. (%.2f %%)\n", 
+                Vec_VecSizeSize( (Vec_Vec_t *)pMod->pNtk->vOnehots ), 
+                100.0 * Vec_VecSizeSize( (Vec_Vec_t *)pMod->pNtk->vOnehots ) / Abc_NtkLatchNum(pMod->pNtk) );
+            {
+                extern void Abc_GenOneHotIntervals( char * pFileName, int nPis, int nRegs, Vec_Ptr_t * vOnehots );
+                char * pFileName = Extra_FileNameGenericAppend( pMod->pMan->pFileName, "_1h.blif" );
+                Abc_GenOneHotIntervals( pFileName, Abc_NtkPiNum(pMod->pNtk), Abc_NtkLatchNum(pMod->pNtk), pMod->pNtk->vOnehots );
+                printf( "One-hotness condition is written into file \"%s\".\n", pFileName );
+            }
+        }
+        if ( Vec_PtrSize(pMod->vFlops) )
+        {
+            printf( "Warning: The parser converted %d .flop lines into .latch lines\n", Vec_PtrSize(pMod->vFlops) );
+            printf( "(information about set, reset, enable of the flops may be lost).\n" );
+        }
+
+    }
+    if ( p->nNDnodes )
+//        printf( "Warning: The parser added %d PIs to replace non-deterministic nodes.\n", p->nNDnodes );
+        printf( "Warning: The parser added %d constant 0 nodes to replace non-deterministic nodes.\n", p->nNDnodes );
+    // return the network
+    pDesign = p->pDesign;
+    p->pDesign = NULL;
+    return pDesign;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the model line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvParseLineModel( Io_MvMod_t * p, char * pLine )
+{
+    Vec_Ptr_t * vTokens = p->pMan->vTokens;
+    char * pToken, * pPivot;
+    if ( pLine == NULL )
+    {
+        p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 );
+        p->pNtk->pName = Extra_UtilStrsav( "EXDC" );
+        return 1;
+    }
+    Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
+    pToken = (char *)Vec_PtrEntry( vTokens, 0 );
+    assert( !strcmp(pToken, "model") );
+    if ( Vec_PtrSize(vTokens) != 2 )
+    {
+        sprintf( p->pMan->sError, "Line %d: Model line has %d entries while it should have 2.", Io_MvGetLine(p->pMan, pToken), Vec_PtrSize(vTokens) );
+        return 0;
+    }
+    if ( p->fBlackBox )
+        p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, 1 );
+    else if ( p->pMan->fBlifMv )
+        p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLIFMV, 1 );
+    else 
+        p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 );
+//    for ( pPivot = pToken = Vec_PtrEntry(vTokens, 1); *pToken; pToken++ )
+//        if ( *pToken == '/' || *pToken == '\\' )
+//            pPivot = pToken+1;
+    pPivot = pToken = (char *)Vec_PtrEntry(vTokens, 1);
+    p->pNtk->pName = Extra_UtilStrsav( pPivot );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the inputs line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine )
+{
+    Vec_Ptr_t * vTokens = p->pMan->vTokens;
+    char * pToken;
+    int i;
+    Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
+    pToken = (char *)Vec_PtrEntry(vTokens, 0);
+    assert( !strcmp(pToken, "inputs") );
+    Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, 1 )
+        Io_ReadCreatePi( p->pNtk, pToken );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the outputs line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine )
+{
+    Vec_Ptr_t * vTokens = p->pMan->vTokens;
+    char * pToken;
+    int i;
+    Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
+    pToken = (char *)Vec_PtrEntry(vTokens, 0);
+    assert( !strcmp(pToken, "outputs") );
+    Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, 1 )
+        Io_ReadCreatePo( p->pNtk, pToken );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the outputs line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvParseLineConstrs( Io_MvMod_t * p, char * pLine )
+{
+    Vec_Ptr_t * vTokens = p->pMan->vTokens;
+    char * pToken;
+    int i;
+    Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
+    pToken = (char *)Vec_PtrEntry(vTokens, 0);
+    assert( !strcmp(pToken, "constraint") );
+    Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, 1 )
+        Io_ReadCreatePo( p->pNtk, pToken );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the LTL property line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvParseLineLtlProperty( Io_MvMod_t * p, char * pLine )
+{
+	int i, j;
+	int quoteBegin, quoteEnd;
+	char keyWordLtlFormula[11];
+	char *actualLtlFormula;
+
+	//checking if the line begins with the keyword "ltlformula" and
+	//progressing the pointer forword
+	for( i=0; i<10; i++ )
+		keyWordLtlFormula[i] = pLine[i];
+	quoteBegin = i;
+	keyWordLtlFormula[10] = '\0';
+	assert( strcmp( "ltlformula", keyWordLtlFormula ) == 0 );
+	while( pLine[i] != '"' )
+		i++;
+	quoteBegin = i;
+	i = strlen( pLine );
+	while( pLine[i] != '"' )
+		i--;
+	quoteEnd = i;
+	actualLtlFormula = (char *)malloc( sizeof(char) * (quoteEnd - quoteBegin) );
+	//printf("\nThe input ltl formula = ");
+	for( i = quoteBegin + 1, j = 0; i<quoteEnd; i++, j++ )
+		//printf("%c", pLine[i] );
+		actualLtlFormula[j] = pLine[i];
+	actualLtlFormula[j] = '\0';
+	Vec_PtrPush( vGlobalLtlArray, actualLtlFormula );
+	return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the latches line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine )
+{
+    Vec_Ptr_t * vTokens = p->pMan->vTokens;
+    Abc_Obj_t * pObj, * pNet;
+    char * pToken;
+    int Init;
+    Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
+    pToken = (char *)Vec_PtrEntry(vTokens,0);
+    assert( !strcmp(pToken, "latch") );
+    if ( Vec_PtrSize(vTokens) < 3 )
+    {
+        sprintf( p->pMan->sError, "Line %d: Latch does not have input name and output name.", Io_MvGetLine(p->pMan, pToken) );
+        return 0;
+    }
+    // create latch
+    if ( p->pResetLatch == NULL )
+    {
+        pObj = Io_ReadCreateLatch( p->pNtk, (char *)Vec_PtrEntry(vTokens,1), (char *)Vec_PtrEntry(vTokens,2) );
+        // get initial value
+        if ( p->pMan->fBlifMv )
+            Abc_LatchSetInit0( pObj );
+        else
+        {
+            if ( Vec_PtrSize(vTokens) > 6 )
+                printf( "Warning: Line %d has .latch directive with unrecognized entries (the total of %d entries).\n", 
+                    Io_MvGetLine(p->pMan, pToken), Vec_PtrSize(vTokens) ); 
+            if ( Vec_PtrSize(vTokens) > 3 )
+                Init = atoi( (char *)Vec_PtrEntryLast(vTokens) );
+            else
+                Init = 2;
+            if ( Init < 0 || Init > 3 )
+            {
+                sprintf( p->pMan->sError, "Line %d: Initial state of the latch is incorrect \"%s\".", Io_MvGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens,3) );
+                return 0;
+            }
+            if ( Init == 0 )
+                Abc_LatchSetInit0( pObj );
+            else if ( Init == 1 )
+                Abc_LatchSetInit1( pObj );
+            else // if ( Init == 2 )
+                Abc_LatchSetInitDc( pObj );
+        }
+    }
+    else
+    {
+        // get the net corresponding to the output of the latch
+        pNet = Abc_NtkFindOrCreateNet( p->pNtk, (char *)Vec_PtrEntry(vTokens,2) );
+        // get the net corresponding to the latch output (feeding into reset MUX)
+        pNet = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pNet, "_out") );
+        // create latch
+        pObj = Io_ReadCreateLatch( p->pNtk, (char *)Vec_PtrEntry(vTokens,1), Abc_ObjName(pNet) );
+//        Abc_LatchSetInit0( pObj );
+        Abc_LatchSetInit0( pObj );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the latches line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvParseLineFlop( Io_MvMod_t * p, char * pLine )
+{
+    Vec_Ptr_t * vTokens = p->pMan->vTokens;
+    Abc_Obj_t * pObj;
+    char * pToken, * pOutput, * pInput;
+    int i, Init = 2;
+    assert( !p->pMan->fBlifMv );
+    Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
+    pToken = (char *)Vec_PtrEntry(vTokens,0);
+    assert( !strcmp(pToken, "flop") );
+    // get flop output
+    Vec_PtrForEachEntry( char *, vTokens, pToken, i )
+        if ( pToken[0] == 'Q' && pToken[1] == '=' )
+            break;
+    if ( i == Vec_PtrSize(vTokens) )
+    {
+        sprintf( p->pMan->sError, "Line %d: Cannot find flop output.", Io_MvGetLine(p->pMan, (char *)Vec_PtrEntry(vTokens,0)) );
+        return 0;
+    }
+    pOutput = pToken+2;
+    // get flop input
+    Vec_PtrForEachEntry( char *, vTokens, pToken, i )
+        if ( pToken[0] == 'D' && pToken[1] == '=' )
+            break;
+    if ( i == Vec_PtrSize(vTokens) )
+    {
+        sprintf( p->pMan->sError, "Line %d: Cannot find flop input.", Io_MvGetLine(p->pMan, (char *)Vec_PtrEntry(vTokens,0)) );
+        return 0;
+    }
+    pInput = pToken+2;
+    // create latch
+    pObj = Io_ReadCreateLatch( p->pNtk, pInput, pOutput );
+    // get the init value
+    Vec_PtrForEachEntry( char *, vTokens, pToken, i )
+    {
+        if ( !strncmp( pToken, "init=", 5 ) )
+        {
+            Init = 0;
+            if ( pToken[5] == '1' )
+                Init = 1;
+            else if ( pToken[5] == '2' )
+                Init = 2;
+            else if ( pToken[5] != '0' )
+            {
+                sprintf( p->pMan->sError, "Line %d: Cannot read flop init value %s.", Io_MvGetLine(p->pMan, pToken), pToken );
+                return 0;
+            }
+            break;
+        }
+    }
+    if ( Init < 0 || Init > 2 )
+    {
+        sprintf( p->pMan->sError, "Line %d: Initial state of the flop is incorrect \"%s\".", Io_MvGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens,3) );
+        return 0;
+    }
+    if ( Init == 0 )
+        Abc_LatchSetInit0( pObj );
+    else if ( Init == 1 )
+        Abc_LatchSetInit1( pObj );
+    else // if ( Init == 2 )
+        Abc_LatchSetInitDc( pObj );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the subckt line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine )
+{
+    Vec_Ptr_t * vTokens = p->pMan->vTokens;
+    Abc_Ntk_t * pModel;
+    Abc_Obj_t * pBox, * pNet, * pTerm;
+    char * pToken, * pName, * pName2, ** ppNames;
+    int nEquals, Last, i, k;
+
+    // split the line into tokens
+    nEquals = Io_MvCountChars( pLine, '=' );
+    Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', '=' );
+    pToken = (char *)Vec_PtrEntry(vTokens,0);
+    assert( !strcmp(pToken, "subckt") );
+//printf( "%d ", nEquals );
+
+    // get the model for this box
+    pName = (char *)Vec_PtrEntry(vTokens,1);
+    // skip instance name for now
+    for ( pToken = pName; *pToken; pToken++ )
+        if ( *pToken == '|' )
+        {
+            *pToken = 0;
+            break;
+        }
+    // find the model
+    pModel = Abc_DesFindModelByName( p->pMan->pDesign, pName );
+    if ( pModel == NULL )
+    {
+        sprintf( p->pMan->sError, "Line %d: Cannot find the model for subcircuit %s.", Io_MvGetLine(p->pMan, pToken), pName );
+        return 0;
+    }
+/*
+    // check if the number of tokens is correct
+    if ( nEquals != Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) )
+    {
+        sprintf( p->pMan->sError, "Line %d: The number of ports (%d) in .subckt differs from the sum of PIs and POs of the model (%d).", 
+            Io_MvGetLine(p->pMan, pToken), nEquals, Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) );
+        return 0;
+    }
+*/
+    // get the names
+    ppNames = (char **)Vec_PtrArray(vTokens) + 2 + p->pMan->fBlifMv;
+
+    // create the box with these terminals
+    if ( Abc_NtkHasBlackbox(pModel) )
+        pBox = Abc_NtkCreateBlackbox( p->pNtk );
+    else
+        pBox = Abc_NtkCreateWhitebox( p->pNtk );
+    pBox->pData = pModel;
+    if ( p->pMan->fBlifMv )
+        Abc_ObjAssignName( pBox, (char *)Vec_PtrEntry(vTokens,2), NULL );
+    // go through formal inputs
+    Last = 0;
+    Abc_NtkForEachPi( pModel, pTerm, i )
+    { 
+        // find this terminal among the actual inputs of the subcircuit
+        pName2 = NULL;
+        pName = Abc_ObjName(Abc_ObjFanout0(pTerm));
+        for ( k = 0; k < nEquals; k++ )
+            if ( !strcmp( ppNames[2*((k+Last)%nEquals)], pName ) )
+            {
+                pName2 = ppNames[2*((k+Last)%nEquals)+1];
+                Last = k+Last+1;
+                break;
+            }
+/*
+        if ( k == nEquals )
+        {
+            sprintf( p->pMan->sError, "Line %d: Cannot find PI \"%s\" of the model \"%s\" as a formal input of the subcircuit.", 
+                Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) );
+            return 0;
+        }
+*/
+        if ( pName2 == NULL )
+        {
+            Abc_Obj_t * pNode = Abc_NtkCreateNode( p->pNtk );
+            pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pNtk->pManFunc, " 0\n" );
+            pNet = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pNode, "abc") );
+            Abc_ObjAddFanin( pNet, pNode );
+            pTerm = Abc_NtkCreateBi( p->pNtk );
+            Abc_ObjAddFanin( pBox, pTerm );
+            Abc_ObjAddFanin( pTerm, pNet );
+            continue;
+        }
+        assert( pName2 != NULL );
+  
+        // create the BI with the actual name
+        pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName2 );
+        pTerm = Abc_NtkCreateBi( p->pNtk );
+        Abc_ObjAddFanin( pBox, pTerm );
+        Abc_ObjAddFanin( pTerm, pNet );
+    }
+    // go through formal outputs
+    Last = 0;
+    Abc_NtkForEachPo( pModel, pTerm, i )
+    {
+        // find this terminal among the actual outputs of the subcircuit
+        pName2 = NULL;
+        pName = Abc_ObjName(Abc_ObjFanin0(pTerm));
+        for ( k = 0; k < nEquals; k++ )
+            if ( !strcmp( ppNames[2*((k+Last)%nEquals)], pName ) )
+            {
+                pName2 = ppNames[2*((k+Last)%nEquals)+1];
+                Last = k+Last+1;
+                break;
+            }
+/*
+        if ( k == nEquals )
+        {
+            sprintf( p->pMan->sError, "Line %d: Cannot find PO \"%s\" of the modell \"%s\" as a formal output of the subcircuit.", 
+                Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) );
+            return 0;
+        }
+*/
+
+        // create the BI with the actual name
+        pTerm = Abc_NtkCreateBo( p->pNtk );
+        pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName2 == NULL  ? Abc_ObjNameSuffix(pTerm, "abc") : pName2 );
+        Abc_ObjAddFanin( pNet, pTerm );
+        Abc_ObjAddFanin( pTerm, pBox );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the subckt line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Vec_Int_t * Io_MvParseLineOnehot( Io_MvMod_t * p, char * pLine )
+{
+    Vec_Ptr_t * vTokens = p->pMan->vTokens;
+//    Vec_Ptr_t * vResult;
+    Vec_Int_t * vResult;
+    Abc_Obj_t * pNet, * pTerm;
+    char * pToken;
+    int nEquals, i;
+
+    // split the line into tokens
+    nEquals = Io_MvCountChars( pLine, '=' );
+    Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', '=' );
+    pToken = (char *)Vec_PtrEntry(vTokens,0);
+    assert( !strcmp(pToken, "onehot") );
+
+    // iterate through the register names
+//    vResult = Vec_PtrAlloc( Vec_PtrSize(vTokens) );
+    vResult = Vec_IntAlloc( Vec_PtrSize(vTokens) );
+    Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, 1 )
+    {
+        // check if this register exists
+        pNet = Abc_NtkFindNet( p->pNtk, pToken );
+        if ( pNet == NULL )
+        {
+            sprintf( p->pMan->sError, "Line %d: Signal with name \"%s\" does not exist in the model \"%s\".", 
+                Io_MvGetLine(p->pMan, pToken), pToken, Abc_NtkName(p->pNtk) );
+            return NULL;
+        }
+        // check if this is register output net
+        pTerm = Abc_ObjFanin0( pNet );
+        if ( pTerm == NULL || Abc_ObjFanin0(pTerm) == NULL || !Abc_ObjIsLatch(Abc_ObjFanin0(pTerm)) )
+        {
+            sprintf( p->pMan->sError, "Line %d: Signal with name \"%s\" is not a register in the model \"%s\".", 
+                Io_MvGetLine(p->pMan, pToken), pToken, Abc_NtkName(p->pNtk) );
+            return NULL;
+        }
+        // save register name
+//        Vec_PtrPush( vResult, Abc_ObjName(pNet) );
+        Vec_IntPush( vResult, (int)(ABC_PTRINT_T)Abc_ObjFanin0(pTerm)->pNext );
+//        printf( "%d(%d) ", (int)Abc_ObjFanin0(pTerm)->pNext, ((int)Abc_ObjFanin0(pTerm)->pData) -1 );
+        printf( "%d", ((int)(ABC_PTRINT_T)Abc_ObjFanin0(pTerm)->pData)-1 );
+    }
+    printf( "\n" );
+    return vResult;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the mv line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine )
+{
+    Vec_Ptr_t * vTokens = p->pMan->vTokens;
+    Abc_Obj_t * pObj;
+    Io_MvVar_t * pVar = NULL;
+    Mem_Flex_t * pFlex;
+    char * pName;
+    int nCommas, nValues, i, k;
+    // count commas and get the tokens
+    nCommas = Io_MvCountChars( pLine, ',' );
+    Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', ',' );
+    pName = (char *)Vec_PtrEntry(vTokens,0);
+    assert( !strcmp(pName, "mv") );
+    // get the number of values
+    if ( Vec_PtrSize(vTokens) <= nCommas + 2 )
+    {
+        sprintf( p->pMan->sError, "Line %d: The number of values in not specified in .mv line.", Io_MvGetLine(p->pMan, pName) );
+        return 0;
+    }
+    nValues = atoi( (char *)Vec_PtrEntry(vTokens,nCommas+2) );
+    if ( nValues < 2 || nValues > IO_BLIFMV_MAXVALUES )
+    {
+        sprintf( p->pMan->sError, "Line %d: The number of values (%d) is incorrect (should be >= 2 and <= %d).", 
+            Io_MvGetLine(p->pMan, pName), nValues, IO_BLIFMV_MAXVALUES );
+        return 0;
+    }
+    // if there is no symbolic values, quit
+    if ( nValues == 2 && Vec_PtrSize(vTokens) == nCommas + 3 )
+        return 1;
+    if ( Vec_PtrSize(vTokens) > nCommas + 3 && Vec_PtrSize(vTokens) - (nCommas + 3) != nValues )
+    {
+        sprintf( p->pMan->sError, "Line %d: Wrong number (%d) of symbolic value names (should be %d).", 
+            Io_MvGetLine(p->pMan, pName), Vec_PtrSize(vTokens) - (nCommas + 3), nValues );
+        return 0;
+    }
+    // go through variables
+    pFlex = (Mem_Flex_t *)Abc_NtkMvVarMan( p->pNtk );
+    for ( i = 0; i <= nCommas; i++ )
+    {
+        pName = (char *)Vec_PtrEntry( vTokens, i+1 );
+        pObj = Abc_NtkFindOrCreateNet( p->pNtk, pName );
+        // allocate variable
+        pVar = (Io_MvVar_t *)Mem_FlexEntryFetch( pFlex, sizeof(Io_MvVar_t) );
+        pVar->nValues = nValues;
+        pVar->pNames = NULL;
+        // create names
+        if ( Vec_PtrSize(vTokens) > nCommas + 3 )
+        {
+            pVar->pNames = (char **)Mem_FlexEntryFetch( pFlex, sizeof(char *) * nValues );
+            Vec_PtrForEachEntryStart( char *, vTokens, pName, k, nCommas + 3 )
+            {
+                pVar->pNames[k-(nCommas + 3)] = (char *)Mem_FlexEntryFetch( pFlex, strlen(pName) + 1 );
+                strcpy( pVar->pNames[k-(nCommas + 3)], pName );
+            }
+        }
+        // save the variable
+        Abc_ObjSetMvVar( pObj, pVar );
+    }
+    // make sure the names are unique
+    assert(pVar);
+    if ( pVar->pNames )
+    {
+        for ( i = 0; i < nValues; i++ )
+        for ( k = i+1; k < nValues; k++ )
+            if ( !strcmp(pVar->pNames[i], pVar->pNames[k]) )
+            {
+                pName = (char *)Vec_PtrEntry(vTokens,0);
+                sprintf( p->pMan->sError, "Line %d: Symbolic value name \"%s\" is repeated in .mv line.", 
+                    Io_MvGetLine(p->pMan, pName), pVar->pNames[i] );
+                return 0;
+            }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the values into the BLIF-MV representation for the node.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvWriteValues( Abc_Obj_t * pNode, Vec_Str_t * vFunc )
+{
+    char Buffer[10];
+    Abc_Obj_t * pFanin;
+    int i;
+    // add the fanin number of values
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        sprintf( Buffer, "%d", Abc_ObjMvVarNum(pFanin) );
+        Vec_StrPrintStr( vFunc, Buffer );
+        Vec_StrPush( vFunc, ' ' );
+    }
+    // add the node number of values
+    sprintf( Buffer, "%d", Abc_ObjMvVarNum(Abc_ObjFanout0(pNode)) );
+    Vec_StrPrintStr( vFunc, Buffer );
+    Vec_StrPush( vFunc, '\n' );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Translated one literal.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvParseLiteralMv( Io_MvMod_t * p, Abc_Obj_t * pNode, char * pToken, Vec_Str_t * vFunc, int iLit )
+{
+    char Buffer[10];
+    Io_MvVar_t * pVar;
+    Abc_Obj_t * pFanin, * pNet;
+    char * pCur, * pNext;
+    int i;
+    // consider the equality literal
+    if ( pToken[0] == '=' )
+    {
+        // find the fanins
+        Abc_ObjForEachFanin( pNode, pFanin, i )
+            if ( !strcmp( Abc_ObjName(pFanin), pToken + 1 ) )
+                break;
+        if ( i == Abc_ObjFaninNum(pNode) )
+        {
+            sprintf( p->pMan->sError, "Line %d: Node name in the table \"%s\" cannot be found on .names line.", 
+                Io_MvGetLine(p->pMan, pToken), pToken + 1 );
+            return 0;
+        }
+        Vec_StrPush( vFunc, '=' );
+        sprintf( Buffer, "%d", i );
+        Vec_StrPrintStr( vFunc, Buffer );
+        Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') );
+        return 1;
+    }
+    // consider regular literal
+    assert( iLit < Abc_ObjFaninNum(pNode) );
+    pNet = iLit >= 0 ? Abc_ObjFanin(pNode, iLit) : Abc_ObjFanout0(pNode);
+    pVar = (Io_MvVar_t *)Abc_ObjMvVar( pNet );
+    // if the var is absent or has no symbolic values quit
+    if ( pVar == NULL || pVar->pNames == NULL )
+    {
+        Vec_StrPrintStr( vFunc, pToken );
+        Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') );
+        return 1;
+    }
+    // parse the literal using symbolic values
+    for ( pCur = pToken; *pCur; pCur++ )
+    {
+        if ( Io_MvCharIsMvSymb(*pCur) )
+        {
+            Vec_StrPush( vFunc, *pCur );
+            continue;
+        }
+        // find the next MvSymb char
+        for ( pNext = pCur+1; *pNext; pNext++ )
+            if ( Io_MvCharIsMvSymb(*pNext) )
+                break;
+        // look for the value name
+        for ( i = 0; i < pVar->nValues; i++ )
+            if ( !strncmp( pVar->pNames[i], pCur, pNext-pCur ) )
+                break;
+        if ( i == pVar->nValues )
+        {
+            *pNext = 0;
+            sprintf( p->pMan->sError, "Line %d: Cannot find value name \"%s\" among the value names of variable \"%s\".", 
+                Io_MvGetLine(p->pMan, pToken), pCur, Abc_ObjName(pNet) );
+            return 0;
+        }
+        // value name is found
+        sprintf( Buffer, "%d", i );
+        Vec_StrPrintStr( vFunc, Buffer );
+        // update the pointer
+        pCur = pNext - 1;
+    }
+    Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs the MV-SOP cover from the file parsing info.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static char * Io_MvParseTableMv( Io_MvMod_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut )
+{
+    Vec_Str_t * vFunc = p->pMan->vFunc;
+    char * pFirst, * pToken;
+    int iStart, i;
+    // prepare the place for the cover
+    Vec_StrClear( vFunc );
+    // write the number of values
+//    Io_MvWriteValues( pNode, vFunc );
+    // get the first token
+    pFirst = (char *)Vec_PtrEntry( vTokens2, 0 );
+    if ( pFirst[0] == '.' )
+    {
+        // write the default literal
+        Vec_StrPush( vFunc, 'd' );
+        pToken = (char *)Vec_PtrEntry(vTokens2, 1 + iOut);
+        if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) )
+            return NULL;
+        iStart = 1 + nOutputs;
+    }
+    else
+        iStart = 0;
+    // write the remaining literals
+    while ( iStart < Vec_PtrSize(vTokens2) )
+    {
+        // input literals
+        for ( i = 0; i < nInputs; i++ )
+        {
+            pToken = (char *)Vec_PtrEntry( vTokens2, iStart + i );
+            if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, i ) )
+                return NULL;
+        }
+        // output literal
+        pToken = (char *)Vec_PtrEntry( vTokens2, iStart + nInputs + iOut );
+        if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) )
+            return NULL;
+        // update the counter
+        iStart += nInputs + nOutputs;
+    }       
+    Vec_StrPush( vFunc, '\0' );
+    return Vec_StrArray( vFunc );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds reset circuitry corresponding to latch with pName.]
+
+  Description [Returns the reset node's net.]
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Abc_Obj_t * Io_MvParseAddResetCircuit( Io_MvMod_t * p, char * pName )
+{
+    char Buffer[50];
+    Abc_Obj_t * pNode, * pData0Net, * pData1Net, * pResetLONet, * pOutNet;
+    Io_MvVar_t * pVar;
+    // make sure the reset latch exists
+    assert( p->pResetLatch != NULL );
+    // get the reset net
+    pResetLONet = Abc_ObjFanout0(Abc_ObjFanout0(p->pResetLatch));
+    // get the output net
+    pOutNet = Abc_NtkFindOrCreateNet( p->pNtk, pName );
+    // get the data nets
+    pData0Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_reset") );
+    pData1Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_out") );
+    // duplicate MV variables
+    if ( Abc_NtkMvVar(p->pNtk) )
+    {
+        pVar = (Io_MvVar_t *)Abc_ObjMvVar( pOutNet );
+        Abc_ObjSetMvVar( pData0Net, Abc_NtkMvVarDup(p->pNtk, pVar) );
+        Abc_ObjSetMvVar( pData1Net, Abc_NtkMvVarDup(p->pNtk, pVar) );
+    }
+    // create the node
+    pNode = Abc_NtkCreateNode( p->pNtk );
+    // create the output net
+    Abc_ObjAddFanin( pOutNet, pNode );
+    // create the function
+    if ( p->pMan->fBlifMv )
+    {
+//        Vec_Att_t * p = Abc_NtkMvVar( pNtk );
+//        int nValues = Abc_ObjMvVarNum(pOutNet);
+//        sprintf( Buffer, "2 %d %d %d\n1 - - =1\n0 - - =2\n", nValues, nValues, nValues );
+        sprintf( Buffer, "1 - - =1\n0 - - =2\n" );
+        pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pNtk->pManFunc, Buffer );
+    }
+    else
+        pNode->pData = Abc_SopCreateMux( (Mem_Flex_t *)p->pNtk->pManFunc );
+    // add nets
+    Abc_ObjAddFanin( pNode, pResetLONet );
+    Abc_ObjAddFanin( pNode, pData1Net );
+    Abc_ObjAddFanin( pNode, pData0Net );
+    return pData0Net;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the nodes line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvParseLineNamesMvOne( Io_MvMod_t * p, Vec_Ptr_t * vTokens, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut, int fReset )
+{
+    Abc_Obj_t * pNet, * pNode;
+    char * pName;
+    // get the output name
+    pName = (char *)Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + iOut );
+    // create the node
+    if ( fReset )
+    {
+        pNet = Abc_NtkFindNet( p->pNtk, pName );
+        if ( pNet == NULL )
+        {
+            sprintf( p->pMan->sError, "Line %d: Latch with output signal \"%s\" does not exist.", Io_MvGetLine(p->pMan, pName), pName );
+            return 0;
+        }
+/*
+        if ( !Abc_ObjIsBo(Abc_ObjFanin0(pNet)) )
+        {
+            sprintf( p->pMan->sError, "Line %d: Reset line \"%s\" defines signal that is not a latch output.", Io_MvGetLine(p->pMan, pName), pName );
+            return 0;
+        }
+*/
+        // construct the reset circuit and get the reset net feeding into it
+        pNet = Io_MvParseAddResetCircuit( p, pName );
+        // create fanins
+        pNode = Io_ReadCreateNode( p->pNtk, Abc_ObjName(pNet), (char **)(vTokens->pArray + 1), nInputs );
+        assert( nInputs == Vec_PtrSize(vTokens) - 2 );
+    }
+    else
+    {
+        pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName );
+        if ( Abc_ObjFaninNum(pNet) > 0 )
+        {
+            sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName );
+            return 0;
+        }
+        pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), nInputs );
+    }
+    // create the cover
+    pNode->pData = Io_MvParseTableMv( p, pNode, vTokens2, nInputs, nOutputs, iOut );
+    if ( pNode->pData == NULL )
+        return 0;
+    pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pNtk->pManFunc, (char *)pNode->pData );
+//printf( "Finished parsing node \"%s\" with table:\n%s\n", pName, pNode->pData );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the nodes line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset )
+{
+    Vec_Ptr_t * vTokens = p->pMan->vTokens;
+    Vec_Ptr_t * vTokens2 = p->pMan->vTokens2;
+    Abc_Obj_t * pNet;
+    char * pName, * pFirst, * pArrow;
+    int nInputs, nOutputs, nLiterals, nLines, i;
+    assert( p->pMan->fBlifMv );
+    // get the arrow if it is present
+    pArrow = Io_MvFindArrow( pLine );
+    if ( !p->pMan->fBlifMv && pArrow ) 
+    {
+        sprintf( p->pMan->sError, "Line %d: Multi-output node symbol (->) in binary BLIF file.", Io_MvGetLine(p->pMan, pLine) );
+        return 0;
+    }
+    // split names line into tokens
+    Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
+    if ( fReset )
+        assert( !strcmp((char *)Vec_PtrEntry(vTokens,0), "r") || !strcmp((char *)Vec_PtrEntry(vTokens,0), "reset") );
+    else
+        assert( !strcmp((char *)Vec_PtrEntry(vTokens,0), "names") || !strcmp((char *)Vec_PtrEntry(vTokens,0), "table") );
+    // find the number of inputs and outputs
+    nInputs  = Vec_PtrSize(vTokens) - 2;
+    nOutputs = 1;
+    if ( pArrow != NULL )
+    {
+        for ( i = Vec_PtrSize(vTokens) - 2; i >= 1; i-- )
+            if ( pArrow < (char*)Vec_PtrEntry(vTokens,i) )
+            {
+                nInputs--;
+                nOutputs++;
+            }
+    }
+    // split table into tokens
+    pName = (char *)Vec_PtrEntryLast( vTokens );
+    Io_MvSplitIntoTokensMv( vTokens2, pName + strlen(pName) );
+    pFirst = (char *)Vec_PtrEntry( vTokens2, 0 );
+    if ( pFirst[0] == '.' )
+    {
+        assert( pFirst[1] == 'd' );
+        nLiterals = Vec_PtrSize(vTokens2) - 1 - nOutputs;
+    }
+    else
+        nLiterals = Vec_PtrSize(vTokens2);
+    // check the number of lines
+    if ( nLiterals % (nInputs + nOutputs) != 0 )
+    {
+        sprintf( p->pMan->sError, "Line %d: Wrong number of literals in the table of node \"%s\". (Spaces inside literals are not allowed.)", Io_MvGetLine(p->pMan, pFirst), pName );
+        return 0;
+    }
+    // check for the ND table
+    nLines = nLiterals / (nInputs + nOutputs);
+    if ( nInputs == 0 && nLines > 1 )
+    {
+        // add the outputs to the PIs
+        for ( i = 0; i < nOutputs; i++ )
+        {
+            pName = (char *)Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + i );
+            // get the net corresponding to this node
+            pNet = Abc_NtkFindOrCreateNet(p->pNtk, pName);
+            if ( fReset )
+            {
+                assert( p->pResetLatch != NULL );
+                // construct the reset circuit and get the reset net feeding into it
+                pNet = Io_MvParseAddResetCircuit( p, pName );
+            }
+            // add the new PI node
+//            Abc_ObjAddFanin( pNet, Abc_NtkCreatePi(p->pNtk) );
+//            fprintf( stdout, "Io_ReadBlifMv(): Adding PI for internal non-deterministic node \"%s\".\n", pName );
+            p->pMan->nNDnodes++;
+            Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(p->pNtk) );
+        }
+        return 1;
+    }
+    // iterate through the outputs
+    for ( i = 0; i < nOutputs; i++ )
+    {
+        if ( !Io_MvParseLineNamesMvOne( p, vTokens, vTokens2, nInputs, nOutputs, i, fReset ) )
+            return 0;
+    }
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs the SOP cover from the file parsing info.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static char * Io_MvParseTableBlif( Io_MvMod_t * p, char * pTable, int nFanins )
+{
+    Vec_Ptr_t * vTokens = p->pMan->vTokens;
+    Vec_Str_t * vFunc = p->pMan->vFunc;
+    char * pProduct, * pOutput, c;
+    int i, Polarity = -1;
+
+    p->pMan->nTablesRead++;
+    // get the tokens
+    Io_MvSplitIntoTokens( vTokens, pTable, '.' );
+    if ( Vec_PtrSize(vTokens) == 0 )
+        return Abc_SopCreateConst0( (Mem_Flex_t *)p->pNtk->pManFunc );
+    if ( Vec_PtrSize(vTokens) == 1 )
+    {
+        pOutput = (char *)Vec_PtrEntry( vTokens, 0 );
+        c = pOutput[0];
+        if ( (c!='0'&&c!='1'&&c!='x'&&c!='n') || pOutput[1] )
+        {
+            sprintf( p->pMan->sError, "Line %d: Constant table has wrong output value \"%s\".", Io_MvGetLine(p->pMan, pOutput), pOutput );
+            return NULL;
+        }
+        return pOutput[0] == '0' ? Abc_SopCreateConst0((Mem_Flex_t *)p->pNtk->pManFunc) : Abc_SopCreateConst1((Mem_Flex_t *)p->pNtk->pManFunc);
+    }
+    pProduct = (char *)Vec_PtrEntry( vTokens, 0 );
+    if ( Vec_PtrSize(vTokens) % 2 == 1 )
+    {
+        sprintf( p->pMan->sError, "Line %d: Table has odd number of tokens (%d).", Io_MvGetLine(p->pMan, pProduct), Vec_PtrSize(vTokens) );
+        return NULL;
+    }
+    // parse the table
+    Vec_StrClear( vFunc );
+    for ( i = 0; i < Vec_PtrSize(vTokens)/2; i++ )
+    {
+        pProduct = (char *)Vec_PtrEntry( vTokens, 2*i + 0 );
+        pOutput  = (char *)Vec_PtrEntry( vTokens, 2*i + 1 );
+        if ( strlen(pProduct) != (unsigned)nFanins )
+        {
+            sprintf( p->pMan->sError, "Line %d: Cube \"%s\" has size different from the fanin count (%d).", Io_MvGetLine(p->pMan, pProduct), pProduct, nFanins );
+            return NULL;
+        }
+        c = pOutput[0];
+        if ( (c!='0'&&c!='1'&&c!='x'&&c!='n') || pOutput[1] )
+        {
+            sprintf( p->pMan->sError, "Line %d: Output value \"%s\" is incorrect.", Io_MvGetLine(p->pMan, pProduct), pOutput );
+            return NULL;
+        }
+        if ( Polarity == -1 )
+            Polarity = (c=='1' || c=='x');
+        else if ( Polarity != (c=='1' || c=='x') )
+        {
+            sprintf( p->pMan->sError, "Line %d: Output value \"%s\" differs from the value in the first line of the table (%d).", Io_MvGetLine(p->pMan, pProduct), pOutput, Polarity );
+            return NULL;
+        }
+        // parse one product 
+        Vec_StrPrintStr( vFunc, pProduct );
+        Vec_StrPush( vFunc, ' ' );
+        Vec_StrPush( vFunc, pOutput[0] );
+        Vec_StrPush( vFunc, '\n' );
+    }
+    Vec_StrPush( vFunc, '\0' );
+    return Vec_StrArray( vFunc );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the nodes line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine )
+{
+    Vec_Ptr_t * vTokens = p->pMan->vTokens;
+    Abc_Obj_t * pNet, * pNode;
+    char * pName;
+    assert( !p->pMan->fBlifMv );
+    Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
+    // parse the mapped node
+    if ( !strcmp((char *)Vec_PtrEntry(vTokens,0), "gate") )
+        return Io_MvParseLineGateBlif( p, vTokens );
+    // parse the regular name line
+    assert( !strcmp((char *)Vec_PtrEntry(vTokens,0), "names") );
+    pName = (char *)Vec_PtrEntryLast( vTokens );
+    pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName );
+    if ( Abc_ObjFaninNum(pNet) > 0 )
+    {
+        sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName );
+        return 0;
+    }
+    // create fanins
+    pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), Vec_PtrSize(vTokens) - 2 );
+    // parse the table of this node
+    pNode->pData = Io_MvParseTableBlif( p, pName + strlen(pName), Abc_ObjFaninNum(pNode) );
+    if ( pNode->pData == NULL )
+        return 0;
+    pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pNtk->pManFunc, (char *)pNode->pData );
+    return 1;
+}
+
+ABC_NAMESPACE_IMPL_END
+
+#include "map/mio/mio.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the nodes line.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvParseLineShortBlif( Io_MvMod_t * p, char * pLine )
+{
+    Vec_Ptr_t * vTokens = p->pMan->vTokens;
+    Abc_Obj_t * pNet, * pNode;
+    char * pName;
+    assert( !p->pMan->fBlifMv );
+    Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
+    if ( Vec_PtrSize(vTokens) != 3 )
+    {
+        sprintf( p->pMan->sError, "Line %d: Expecting three entries in the .short line.", Io_MvGetLine(p->pMan, (char *)Vec_PtrEntry(vTokens,0)) );
+        return 0;
+    }
+    // parse the regular name line
+    assert( !strcmp((char *)Vec_PtrEntry(vTokens,0), "short") );
+    pName = (char *)Vec_PtrEntryLast( vTokens );
+    pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName );
+    if ( Abc_ObjFaninNum(pNet) > 0 )
+    {
+        sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName );
+        return 0;
+    }
+    // create fanins
+    pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), 1 );
+    // parse the table of this node
+    if ( p->pNtk->ntkFunc == ABC_FUNC_MAP )
+    {
+        Mio_Library_t * pGenlib; 
+        Mio_Gate_t * pGate;
+        // check that the library is available
+        pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen();
+        if ( pGenlib == NULL )
+        {
+            sprintf( p->pMan->sError, "Line %d: The current library is not available.", Io_MvGetLine(p->pMan, pName) );
+            return 0;
+        }
+        // get the gate
+        pGate = Mio_LibraryReadBuf( pGenlib );
+        if ( pGate == NULL )
+        {
+            sprintf( p->pMan->sError, "Line %d: Cannot find buffer gate in the library.", Io_MvGetLine(p->pMan, pName) );
+            return 0;
+        }
+        Abc_ObjSetData( pNode, pGate );
+    }
+    else
+        pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pNtk->pManFunc, "1 1\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicate the MV variable.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar )
+{
+    Mem_Flex_t * pFlex;
+    Io_MvVar_t * pVarDup;
+    int i;
+    if ( pVar == NULL )
+        return NULL;
+    pFlex = (Mem_Flex_t *)Abc_NtkMvVarMan( pNtk );
+    assert( pFlex != NULL );
+    pVarDup = (Io_MvVar_t *)Mem_FlexEntryFetch( pFlex, sizeof(Io_MvVar_t) );
+    pVarDup->nValues = pVar->nValues;
+    pVarDup->pNames = NULL;
+    if ( pVar->pNames == NULL )
+        return pVarDup;
+    pVarDup->pNames = (char **)Mem_FlexEntryFetch( pFlex, sizeof(char *) * pVar->nValues );
+    for ( i = 0; i < pVar->nValues; i++ )
+    {
+        pVarDup->pNames[i] = (char *)Mem_FlexEntryFetch( pFlex, strlen(pVar->pNames[i]) + 1 );
+        strcpy( pVarDup->pNames[i], pVar->pNames[i] );
+    }
+    return pVarDup;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static char * Io_ReadBlifCleanName( char * pName )
+{
+    int i, Length;
+    Length = strlen(pName);
+    for ( i = 0; i < Length; i++ )
+        if ( pName[i] == '=' )
+            return pName + i + 1;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens )
+{
+    extern int Io_ReadBlifReorderFormalNames( Vec_Ptr_t * vTokens, Mio_Gate_t * pGate, Mio_Gate_t * pTwin );
+    Mio_Library_t * pGenlib; 
+    Mio_Gate_t * pGate;
+    Abc_Obj_t * pNode;
+    char ** ppNames, * pName;
+    int i, nNames;
+
+    pName = (char *)vTokens->pArray[0];
+
+    // check that the library is available
+    pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen();
+    if ( pGenlib == NULL )
+    {
+        sprintf( p->pMan->sError, "Line %d: The current library is not available.", Io_MvGetLine(p->pMan, pName) );
+        return 0;
+    }
+
+    // create a new node and add it to the network
+    if ( vTokens->nSize < 2 )
+    {
+        sprintf( p->pMan->sError, "Line %d: The .gate line has less than two tokens.", Io_MvGetLine(p->pMan, pName) );
+        return 0;
+    }
+
+    // get the gate
+    pGate = Mio_LibraryReadGateByName( pGenlib, (char *)vTokens->pArray[1], NULL );
+    if ( pGate == NULL )
+    {
+        sprintf( p->pMan->sError, "Line %d: Cannot find gate \"%s\" in the library.", Io_MvGetLine(p->pMan, pName), (char*)vTokens->pArray[1] );
+        return 0;
+    }
+
+    // if this is the first line with gate, update the network type
+    if ( Abc_NtkNodeNum(p->pNtk) == 0 )
+    {
+        assert( p->pNtk->ntkFunc == ABC_FUNC_SOP );
+        p->pNtk->ntkFunc = ABC_FUNC_MAP;
+        Mem_FlexStop( (Mem_Flex_t *)p->pNtk->pManFunc, 0 );
+        p->pNtk->pManFunc = pGenlib;
+    }
+
+    // reorder the formal inputs to be in the same order as in the gate
+    if ( !Io_ReadBlifReorderFormalNames( vTokens, pGate, Mio_GateReadTwin(pGate) ) )
+    {
+        sprintf( p->pMan->sError, "Line %d: Mismatch in the fanins of gate \"%s\".", Io_MvGetLine(p->pMan, pName), (char*)vTokens->pArray[1] );
+        return 0;
+    }
+
+    // remove the formal parameter names
+    for ( i = 2; i < vTokens->nSize; i++ )
+    {
+        if ( vTokens->pArray[i] == NULL )
+            continue;
+        vTokens->pArray[i] = Io_ReadBlifCleanName( (char *)vTokens->pArray[i] );
+        if ( vTokens->pArray[i] == NULL )
+        {
+            sprintf( p->pMan->sError, "Line %d: Invalid gate input assignment.", Io_MvGetLine(p->pMan, pName) );
+            return 0;
+        }
+    }
+
+    // create the node
+    if ( Mio_GateReadTwin(pGate) == NULL )
+    {
+        nNames  = vTokens->nSize - 3;
+        ppNames = (char **)vTokens->pArray + 2;
+        pNode   = Io_ReadCreateNode( p->pNtk, ppNames[nNames], ppNames, nNames );
+        Abc_ObjSetData( pNode, pGate );
+    }
+    else
+    {
+        nNames  = vTokens->nSize - 4;
+        ppNames = (char **)vTokens->pArray + 2;
+        assert( ppNames[nNames] != NULL || ppNames[nNames+1] != NULL );
+        if ( ppNames[nNames] )
+        {
+            pNode   = Io_ReadCreateNode( p->pNtk, ppNames[nNames], ppNames, nNames );
+            Abc_ObjSetData( pNode, pGate );
+        }
+        if ( ppNames[nNames+1] )
+        {
+            pNode   = Io_ReadCreateNode( p->pNtk, ppNames[nNames+1], ppNames, nNames );
+            Abc_ObjSetData( pNode, Mio_GateReadTwin(pGate) );
+        }
+    }
+
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Box mapping procedures.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_MapBoxSetPrevNext( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id )
+{
+    Abc_Obj_t * pNode;
+    pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+2);
+    Vec_IntWriteEntry( vMapIn, Abc_ObjId(Abc_ObjFanin0(Abc_ObjFanin0(pNode))), Id );
+    pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+4);
+    Vec_IntWriteEntry( vMapOut, Abc_ObjId(Abc_ObjFanin0(Abc_ObjFanin0(pNode))), Id );
+}
+static inline int Abc_MapBox2Next( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id )
+{
+    Abc_Obj_t * pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+4);
+    return Vec_IntEntry( vMapIn, Abc_ObjId(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) );
+}
+static inline int Abc_MapBox2Prev( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id )
+{
+    Abc_Obj_t * pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+2);
+    return Vec_IntEntry( vMapOut, Abc_ObjId(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioReadDsd.c b/abc-build/src/base/io/ioReadDsd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioReadDsd.c
@@ -0,0 +1,313 @@
+/**CFile****************************************************************
+
+  FileName    [ioReadDsd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedure to read network from file.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioReadDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the end of the part.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Io_ReadDsdFindEnd( char * pCur )
+{
+    char * pEnd;
+    int nParts = 0;
+    assert( *pCur == '(' );
+    for ( pEnd = pCur; *pEnd; pEnd++ )
+    {
+        if ( *pEnd == '(' )
+            nParts++;
+        else if ( *pEnd == ')' )
+            nParts--;
+        if ( nParts == 0 )
+            return pEnd;
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Splits the formula into parts.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadDsdStrSplit( char * pCur, char * pParts[], int * pTypeXor )
+{
+    int fAnd = 0, fXor = 0, fPri = 0, nParts = 0;
+    assert( *pCur );
+    // process the parts
+    while ( 1 )
+    {
+        // save the current part
+        pParts[nParts++] = pCur;
+        // skip the complement
+        if ( *pCur == '!' )
+            pCur++;
+        // skip var
+        if ( *pCur >= 'a' && *pCur <= 'z' )
+            pCur++;
+        else
+        {
+            // skip hex truth table
+            while ( (*pCur >= '0' && *pCur <= '9') || (*pCur >= 'A' && *pCur <= 'F') )
+                pCur++;
+            // process parantheses
+            if ( *pCur != '(' )
+            {
+                printf( "Cannot find the opening paranthesis.\n" );
+                break;
+            }
+            // find the corresponding closing paranthesis
+            pCur = Io_ReadDsdFindEnd( pCur );
+            if ( pCur == NULL )
+            {
+                printf( "Cannot find the closing paranthesis.\n" );
+                break;
+            }
+            pCur++;
+        }
+        // check the end
+        if ( *pCur == 0 )
+            break;
+        // check symbol
+        if ( *pCur != '*' && *pCur != '+' && *pCur != ',' )
+        {
+            printf( "Wrong separating symbol.\n" );
+            break;
+        }
+        // remember the symbol
+        fAnd |= (*pCur == '*');
+        fXor |= (*pCur == '+');
+        fPri |= (*pCur == ',');
+        *pCur++ = 0;
+    }
+    // check separating symbols
+    if ( fAnd + fXor + fPri > 1 )
+    {
+        printf( "Different types of separating symbol ennPartsed.\n" );
+        return 0;
+    }
+    *pTypeXor = fXor;
+    return nParts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively parses the formula.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Io_ReadDsd_rec( Abc_Ntk_t * pNtk, char * pCur, char * pSop )
+{
+    Abc_Obj_t * pObj, * pFanin;
+    char * pEnd, * pParts[32];
+    int i, nParts, TypeExor;
+
+    // consider complemented formula
+    if ( *pCur == '!' )
+    {
+        pObj = Io_ReadDsd_rec( pNtk, pCur + 1, NULL );
+        return Abc_NtkCreateNodeInv( pNtk, pObj );
+    }
+    if ( *pCur == '(' )
+    {
+        assert( pCur[strlen(pCur)-1] == ')' );
+        pCur[strlen(pCur)-1] = 0;
+        nParts = Io_ReadDsdStrSplit( pCur+1, pParts, &TypeExor );
+        if ( nParts == 0 )
+        {
+            Abc_NtkDelete( pNtk );
+            return NULL;
+        }
+        pObj = Abc_NtkCreateNode( pNtk );
+        if ( pSop )
+        {
+//            for ( i = nParts - 1; i >= 0; i-- )
+            for ( i = 0; i < nParts; i++ )
+            {
+                pFanin = Io_ReadDsd_rec( pNtk, pParts[i], NULL );
+                if ( pFanin == NULL )
+                    return NULL;
+                Abc_ObjAddFanin( pObj, pFanin );
+            }
+        }
+        else
+        {
+            for ( i = 0; i < nParts; i++ )
+            {
+                pFanin = Io_ReadDsd_rec( pNtk, pParts[i], NULL );
+                if ( pFanin == NULL )
+                    return NULL;
+                Abc_ObjAddFanin( pObj, pFanin );
+            }
+        }
+        if ( pSop )
+            pObj->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, pSop );
+        else if ( TypeExor )
+            pObj->pData = Abc_SopCreateXorSpecial( (Mem_Flex_t *)pNtk->pManFunc, nParts );
+        else
+            pObj->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtk->pManFunc, nParts, NULL );
+        return pObj;
+    }
+    if ( *pCur >= 'a' && *pCur <= 'z' )
+    {
+        assert( *(pCur+1) == 0 );
+        return Abc_NtkPi( pNtk, *pCur - 'a' );
+    }
+
+    // skip hex truth table
+    pEnd = pCur;
+    while ( (*pEnd >= '0' && *pEnd <= '9') || (*pEnd >= 'A' && *pEnd <= 'F') )
+        pEnd++;
+    if ( *pEnd != '(' )
+    {
+        printf( "Cannot find the end of hexidecimal truth table.\n" );
+        return NULL;
+    }
+
+    // parse the truth table
+    *pEnd = 0;
+    pSop = Abc_SopFromTruthHex( pCur );
+    *pEnd = '(';
+    pObj = Io_ReadDsd_rec( pNtk, pEnd, pSop );
+    ABC_FREE( pSop );
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the DSD network of the formula.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadDsd( char * pForm )
+{
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pObj, * pTop;
+    Vec_Ptr_t * vNames;
+    char * pCur, * pFormCopy;
+    int i, nInputs;
+
+    // count the number of elementary variables
+    nInputs = 0;
+    for ( pCur = pForm; *pCur; pCur++ )
+        if ( *pCur >= 'a' && *pCur <= 'z' )
+            nInputs = Abc_MaxInt( nInputs, *pCur - 'a' );
+    nInputs++;
+
+    // create the network
+    pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+    pNtk->pName = Extra_UtilStrsav( "dsd" );
+
+    // create PIs
+    vNames = Abc_NodeGetFakeNames( nInputs );
+    for ( i = 0; i < nInputs; i++ )
+        Abc_ObjAssignName( Abc_NtkCreatePi(pNtk), (char *)Vec_PtrEntry(vNames, i), NULL );
+    Abc_NodeFreeNames( vNames );
+
+    // transform the formula by inserting parantheses
+    // this transforms strings like PRIME(a,b,cd) into (PRIME((a),(b),(cd)))
+    pCur = pFormCopy = ABC_ALLOC( char, 3 * strlen(pForm) + 10 );
+    *pCur++ = '(';
+    for ( ; *pForm; pForm++ )
+        if ( *pForm == '(' )
+        {
+            *pCur++ = '(';
+            *pCur++ = '(';
+        }
+        else if ( *pForm == ')' )
+        {
+            *pCur++ = ')';
+            *pCur++ = ')';
+        }
+        else if ( *pForm == ',' )
+        {
+            *pCur++ = ')';
+            *pCur++ = ',';
+            *pCur++ = '(';
+        }
+        else
+            *pCur++ = *pForm;
+    *pCur++ = ')';
+    *pCur = 0;
+
+    // parse the formula
+    pObj = Io_ReadDsd_rec( pNtk, pFormCopy, NULL );
+    ABC_FREE( pFormCopy );
+    if ( pObj == NULL )
+        return NULL;
+
+    // create output
+    pTop = Abc_NtkCreatePo(pNtk);
+    Abc_ObjAssignName( pTop, "F", NULL );
+    Abc_ObjAddFanin( pTop, pObj );
+
+    // create the only PO
+    if ( !Abc_NtkCheck( pNtk ) )
+    {
+        fprintf( stdout, "Io_ReadDsd(): Network check has failed.\n" );
+        Abc_NtkDelete( pNtk );
+        return NULL;
+    }
+    return pNtk;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioReadEdif.c b/abc-build/src/base/io/ioReadEdif.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioReadEdif.c
@@ -0,0 +1,240 @@
+/**CFile****************************************************************
+
+  FileName    [ioReadEdif.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedure to read ISCAS benchmarks in EDIF.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioReadEdif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the network from an EDIF file.]
+
+  Description [Works only for the ISCAS benchmarks.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadEdif( char * pFileName, int fCheck )
+{
+    Extra_FileReader_t * p;
+    Abc_Ntk_t * pNtk;
+
+    printf( "Currently this parser does not work!\n" );
+    return NULL;
+
+    // start the file
+    p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t()" );
+    if ( p == NULL )
+        return NULL;
+
+    // read the network
+    pNtk = Io_ReadEdifNetwork( p );
+    Extra_FileReaderFree( p );
+    if ( pNtk == NULL )
+        return NULL;
+
+    // make sure that everything is okay with the network structure
+    if ( fCheck && !Abc_NtkCheckRead( pNtk ) )
+    {
+        printf( "Io_ReadEdif: The network check has failed.\n" );
+        Abc_NtkDelete( pNtk );
+        return NULL;
+    }
+    return pNtk;
+}
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p )
+{
+    ProgressBar * pProgress;
+    Vec_Ptr_t * vTokens;
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pNet, * pObj, * pFanout;
+    char * pGateName, * pNetName;
+    int fTokensReady, iLine, i;
+
+    // read the first line
+    vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p);
+    if ( strcmp( (char *)vTokens->pArray[0], "edif" ) != 0 )
+    {
+        printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) );
+        return NULL;
+    }
+    
+    // allocate the empty network
+    pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) );
+
+    // go through the lines of the file
+    fTokensReady = 0;
+    pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) );
+    for ( iLine = 1; fTokensReady || (vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p)); iLine++ )
+    {
+        Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL );
+
+        // get the type of the line
+        fTokensReady = 0;
+        if ( strcmp( (char *)vTokens->pArray[0], "instance" ) == 0 )
+        { 
+            pNetName = (char *)vTokens->pArray[1];
+            pNet = Abc_NtkFindOrCreateNet( pNtk, pNetName );
+            vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p);
+            vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p);
+            pGateName = (char *)vTokens->pArray[1];
+            if ( strncmp( pGateName, "Flip", 4 ) == 0 )
+            {
+                pObj = Abc_NtkCreateLatch( pNtk );
+                Abc_LatchSetInit0( pObj );
+            }
+            else
+            {
+                pObj = Abc_NtkCreateNode( pNtk );
+//                pObj->pData = Abc_NtkRegisterName( pNtk, pGateName );
+                pObj->pData = Extra_UtilStrsav( pGateName ); // memory leak!!!
+            }
+            Abc_ObjAddFanin( pNet, pObj );
+        }
+        else if ( strcmp( (char *)vTokens->pArray[0], "net" ) == 0 )
+        {
+            pNetName = (char *)vTokens->pArray[1];
+            if ( strcmp( pNetName, "CK" ) == 0 || strcmp( pNetName, "RESET" ) == 0 )
+                continue;
+            if ( strcmp( pNetName + strlen(pNetName) - 4, "_out" ) == 0 )
+                pNetName[strlen(pNetName) - 4] = 0;
+            pNet = Abc_NtkFindNet( pNtk, pNetName );
+            assert( pNet );
+            vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p);
+            vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p);
+            vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p);
+            while ( strcmp( (char *)vTokens->pArray[0], "portRef" ) == 0 )
+            {
+                if ( strcmp( pNetName, (char *)vTokens->pArray[3] ) != 0 )
+                {
+                    pFanout = Abc_NtkFindNet( pNtk, (char *)vTokens->pArray[3] );
+                    Abc_ObjAddFanin( Abc_ObjFanin0(pFanout), pNet );
+                }
+                vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p);
+            }
+            fTokensReady = 1;
+        }
+        else if ( strcmp( (char *)vTokens->pArray[0], "library" ) == 0 )
+        {
+            vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p);
+            vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p);
+            vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p);
+            vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p);
+            vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p);
+            while ( strcmp( (char *)vTokens->pArray[0], "port" ) == 0 )
+            {
+                pNetName = (char *)vTokens->pArray[1];
+                if ( strcmp( pNetName, "CK" ) == 0 || strcmp( pNetName, "RESET" ) == 0 )
+                {
+                    vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p);
+                    continue;
+                }
+                if ( strcmp( pNetName + strlen(pNetName) - 3, "_PO" ) == 0 )
+                    pNetName[strlen(pNetName) - 3] = 0;
+                if ( strcmp( (char *)vTokens->pArray[3], "INPUT" ) == 0 )
+                    Io_ReadCreatePi( pNtk, (char *)vTokens->pArray[1] );
+                else if ( strcmp( (char *)vTokens->pArray[3], "OUTPUT" ) == 0 )
+                    Io_ReadCreatePo( pNtk, (char *)vTokens->pArray[1] );
+                else
+                {
+                    printf( "%s (line %d): Wrong interface specification.\n", Extra_FileReaderGetFileName(p), iLine );
+                    Abc_NtkDelete( pNtk );
+                    return NULL;
+                }
+                vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p);
+            }
+        }
+        else if ( strcmp( (char *)vTokens->pArray[0], "design" ) == 0 )
+        {
+            ABC_FREE( pNtk->pName ); 
+            pNtk->pName = (char *)Extra_UtilStrsav( (char *)vTokens->pArray[3] );
+            break;
+        }
+    }
+    Extra_ProgressBarStop( pProgress );
+
+    // assign logic functions
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        if ( strncmp( (char *)pObj->pData, "And", 3 ) == 0 )
+            Abc_ObjSetData( pObj, Abc_SopCreateAnd((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj), NULL) );
+        else if ( strncmp( (char *)pObj->pData, "Or", 2 ) == 0 )
+            Abc_ObjSetData( pObj, Abc_SopCreateOr((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj), NULL) );
+        else if ( strncmp( (char *)pObj->pData, "Nand", 4 ) == 0 )
+            Abc_ObjSetData( pObj, Abc_SopCreateNand((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj)) );
+        else if ( strncmp( (char *)pObj->pData, "Nor", 3 ) == 0 )
+            Abc_ObjSetData( pObj, Abc_SopCreateNor((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj)) );
+        else if ( strncmp( (char *)pObj->pData, "Exor", 4 ) == 0 )
+            Abc_ObjSetData( pObj, Abc_SopCreateXor((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj)) );
+        else if ( strncmp( (char *)pObj->pData, "Exnor", 5 ) == 0 )
+            Abc_ObjSetData( pObj, Abc_SopCreateNxor((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj)) );
+        else if ( strncmp( (char *)pObj->pData, "Inv", 3 ) == 0 )
+            Abc_ObjSetData( pObj, Abc_SopCreateInv((Mem_Flex_t *)pNtk->pManFunc) );
+        else if ( strncmp( (char *)pObj->pData, "Buf", 3 ) == 0 )
+            Abc_ObjSetData( pObj, Abc_SopCreateBuf((Mem_Flex_t *)pNtk->pManFunc) );
+        else
+        {
+            printf( "%s: Unknown gate type \"%s\".\n", Extra_FileReaderGetFileName(p), (char*)pObj->pData );
+            Abc_NtkDelete( pNtk );
+            return NULL;
+        }
+    }
+    // check if constants have been added
+//    if ( pNet = Abc_NtkFindNet( pNtk, "VDD" ) )
+//        Io_ReadCreateConst( pNtk, "VDD", 1 );
+//    if ( pNet = Abc_NtkFindNet( pNtk, "GND" ) )
+//        Io_ReadCreateConst( pNtk, "GND", 0 );
+
+    Abc_NtkFinalizeRead( pNtk );
+    return pNtk;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioReadEqn.c b/abc-build/src/base/io/ioReadEqn.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioReadEqn.c
@@ -0,0 +1,244 @@
+/**CFile****************************************************************
+
+  FileName    [ioReadEqn.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to read equation format files.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioReadEqn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p );
+static void        Io_ReadEqnStrCompact( char * pStr );
+static int         Io_ReadEqnStrFind( Vec_Ptr_t * vTokens, char * pName );
+static void        Io_ReadEqnStrCutAt( char * pStr, char * pStop, int fUniqueOnly, Vec_Ptr_t * vTokens );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the network from a BENCH file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadEqn( char * pFileName, int fCheck )
+{
+    Extra_FileReader_t * p;
+    Abc_Ntk_t * pNtk;
+
+    // start the file
+    p = Extra_FileReaderAlloc( pFileName, "#", ";", "=" );
+    if ( p == NULL )
+        return NULL;
+
+    // read the network
+    pNtk = Io_ReadEqnNetwork( p );
+    Extra_FileReaderFree( p );
+    if ( pNtk == NULL )
+        return NULL;
+
+    // make sure that everything is okay with the network structure
+    if ( fCheck && !Abc_NtkCheckRead( pNtk ) )
+    {
+        printf( "Io_ReadEqn: The network check has failed.\n" );
+        Abc_NtkDelete( pNtk );
+        return NULL;
+    }
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p )
+{
+    ProgressBar * pProgress;
+    Vec_Ptr_t * vTokens;
+    Vec_Ptr_t * vVars;
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pNode;
+    char * pNodeName, * pFormula, * pFormulaCopy, * pVarName;
+    int iLine, i;
+    
+    // allocate the empty network
+    pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_AIG, 1 );
+    // set the specs
+    pNtk->pName = Extra_FileNameGeneric(Extra_FileReaderGetFileName(p));
+    pNtk->pSpec = Extra_UtilStrsav(Extra_FileReaderGetFileName(p));
+
+    // go through the lines of the file
+    vVars  = Vec_PtrAlloc( 100 );
+    pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) );
+    for ( iLine = 0; (vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p)); iLine++ )
+    {
+        Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL );
+
+        // check if the first token contains anything
+        Io_ReadEqnStrCompact( (char *)vTokens->pArray[0] );
+        if ( strlen((char *)vTokens->pArray[0]) == 0 )
+            break;
+
+        // if the number of tokens is different from two, error
+        if ( vTokens->nSize != 2 )
+        {
+            printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) );
+            Abc_NtkDelete( pNtk );
+            return NULL;
+        }
+
+        // get the type of the line
+        if ( strncmp( (char *)vTokens->pArray[0], "INORDER", 7 ) == 0 )
+        {
+            Io_ReadEqnStrCutAt( (char *)vTokens->pArray[1], " \n\r\t", 0, vVars );
+            Vec_PtrForEachEntry( char *, vVars, pVarName, i )
+                Io_ReadCreatePi( pNtk, pVarName );
+        }
+        else if ( strncmp( (char *)vTokens->pArray[0], "OUTORDER", 8 ) == 0 )
+        {
+            Io_ReadEqnStrCutAt( (char *)vTokens->pArray[1], " \n\r\t", 0, vVars );
+            Vec_PtrForEachEntry( char *, vVars, pVarName, i )
+                Io_ReadCreatePo( pNtk, pVarName );
+        }
+        else 
+        {
+            extern Hop_Obj_t * Parse_FormulaParserEqn( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan );
+
+            // get hold of the node name and its formula
+            pNodeName = (char *)vTokens->pArray[0];
+            pFormula  = (char *)vTokens->pArray[1];
+            // compact the formula 
+            Io_ReadEqnStrCompact( pFormula );
+
+            // consider the case of the constant node
+            if ( pFormula[1] == 0 && (pFormula[0] == '0' || pFormula[0] == '1') )
+            {
+                pFormulaCopy = NULL;
+                Vec_PtrClear( vVars );
+            }
+            else
+            {
+                // make a copy of formula for names
+                pFormulaCopy = Extra_UtilStrsav( pFormula );
+                // find the names of the fanins of this node
+                Io_ReadEqnStrCutAt( pFormulaCopy, "!*+()", 1, vVars );
+            }
+            // create the node
+            pNode = Io_ReadCreateNode( pNtk, pNodeName, (char **)Vec_PtrArray(vVars), Vec_PtrSize(vVars) );
+            // derive the function
+            pNode->pData = Parse_FormulaParserEqn( stdout, pFormula, vVars, (Hop_Man_t *)pNtk->pManFunc );
+            // remove the cubes
+            ABC_FREE( pFormulaCopy );
+        }
+    }
+    Extra_ProgressBarStop( pProgress );
+    Vec_PtrFree( vVars );
+    Abc_NtkFinalizeRead( pNtk );
+    return pNtk;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compacts the string by throwing away space-like chars.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_ReadEqnStrCompact( char * pStr )
+{
+    char * pCur, * pNew;
+    for ( pNew = pCur = pStr; *pCur; pCur++ )
+        if ( !(*pCur == ' ' || *pCur == '\n' || *pCur == '\r' || *pCur == '\t') )
+            *pNew++ = *pCur;
+    *pNew = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determines unique variables in the string.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_ReadEqnStrFind( Vec_Ptr_t * vTokens, char * pName )
+{
+    char * pToken;
+    int i;
+    Vec_PtrForEachEntry( char *, vTokens, pToken, i )
+        if ( strcmp( pToken, pName ) == 0 )
+            return i;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cuts the string into pieces using stop chars.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_ReadEqnStrCutAt( char * pStr, char * pStop, int fUniqueOnly, Vec_Ptr_t * vTokens )
+{
+    char * pToken;
+    Vec_PtrClear( vTokens );
+    for ( pToken = strtok( pStr, pStop ); pToken; pToken = strtok( NULL, pStop ) )
+        if ( !fUniqueOnly || Io_ReadEqnStrFind( vTokens, pToken ) == -1 )
+            Vec_PtrPush( vTokens, pToken );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioReadPla.c b/abc-build/src/base/io/ioReadPla.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioReadPla.c
@@ -0,0 +1,289 @@
+/**CFile****************************************************************
+
+  FileName    [ioReadPla.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedure to read network from file.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioReadPla.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p, int fZeros );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the network from a PLA file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadPla( char * pFileName, int fZeros, int fCheck )
+{
+    Extra_FileReader_t * p;
+    Abc_Ntk_t * pNtk;
+
+    // start the file
+    p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t|" );
+//    p = Extra_FileReaderAlloc( pFileName, "", "\n\r", " \t|" );
+    if ( p == NULL )
+        return NULL;
+
+    // read the network
+    pNtk = Io_ReadPlaNetwork( p, fZeros );
+    Extra_FileReaderFree( p );
+    if ( pNtk == NULL )
+        return NULL;
+
+    // make sure that everything is okay with the network structure
+    if ( fCheck && !Abc_NtkCheckRead( pNtk ) )
+    {
+        printf( "Io_ReadPla: The network check has failed.\n" );
+        Abc_NtkDelete( pNtk );
+        return NULL;
+    }
+    return pNtk;
+}
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p, int fZeros )
+{
+    ProgressBar * pProgress;
+    Vec_Ptr_t * vTokens;
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pTermPi, * pTermPo, * pNode;
+    Vec_Str_t ** ppSops = NULL;
+    char Buffer[100];
+    int nInputs = -1, nOutputs = -1, nProducts = -1;
+    char * pCubeIn, * pCubeOut;
+    int i, k, iLine, nDigits, nCubes;
+
+    // allocate the empty network
+    pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) );
+
+    // go through the lines of the file
+    nCubes = 0;
+    pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) );
+    while ( (vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p)) )
+    {
+        Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL );
+        iLine = Extra_FileReaderGetLineNumber( p, 0 );
+
+        // if it is the end of file, quit the loop
+        if ( strncmp( (char *)vTokens->pArray[0], ".e", 2 ) == 0 )
+            break;
+
+        // if it is the model name, get the name
+        if ( strcmp( (char *)vTokens->pArray[0], ".model" ) == 0 )
+        {
+            ABC_FREE( pNtk->pName );
+            pNtk->pName = Extra_UtilStrsav( (char *)vTokens->pArray[1] );
+            continue;
+        }
+
+        if ( vTokens->nSize == 1 )
+        {
+            printf( "%s (line %d): Wrong number of token.\n", 
+                Extra_FileReaderGetFileName(p), iLine );
+            Abc_NtkDelete( pNtk );
+            Extra_ProgressBarStop( pProgress );
+            ABC_FREE( ppSops );
+            return NULL;
+        }
+
+        if ( strcmp( (char *)vTokens->pArray[0], ".i" ) == 0 )
+            nInputs = atoi((char *)vTokens->pArray[1]);
+        else if ( strcmp( (char *)vTokens->pArray[0], ".o" ) == 0 )
+            nOutputs = atoi((char *)vTokens->pArray[1]);
+        else if ( strcmp( (char *)vTokens->pArray[0], ".p" ) == 0 )
+            nProducts = atoi((char *)vTokens->pArray[1]);
+        else if ( strcmp( (char *)vTokens->pArray[0], ".ilb" ) == 0 )
+        {
+            if ( vTokens->nSize - 1 != nInputs )
+                printf( "Warning: Mismatch between the number of PIs on the .i line (%d) and the number of PIs on the .ilb line (%d).\n", nInputs, vTokens->nSize - 1 );
+            for ( i = 1; i < vTokens->nSize; i++ )
+                Io_ReadCreatePi( pNtk, (char *)vTokens->pArray[i] );
+        }
+        else if ( strcmp( (char *)vTokens->pArray[0], ".ob" ) == 0 )
+        {
+            if ( vTokens->nSize - 1 != nOutputs )
+                printf( "Warning: Mismatch between the number of POs on the .o line (%d) and the number of POs on the .ob line (%d).\n", nOutputs, vTokens->nSize - 1 );
+            for ( i = 1; i < vTokens->nSize; i++ )
+                Io_ReadCreatePo( pNtk, (char *)vTokens->pArray[i] );
+        }
+        else 
+        {
+            // check if the input/output names are given
+            if ( Abc_NtkPiNum(pNtk) == 0 )
+            {
+                if ( nInputs == -1 )
+                {
+                    printf( "%s: The number of inputs is not specified.\n", Extra_FileReaderGetFileName(p) );
+                    Abc_NtkDelete( pNtk );
+                    Extra_ProgressBarStop( pProgress );
+                    ABC_FREE( ppSops );
+                    return NULL;
+                }
+                nDigits = Abc_Base10Log( nInputs );
+                for ( i = 0; i < nInputs; i++ )
+                {
+                    sprintf( Buffer, "x%0*d", nDigits, i );
+                    Io_ReadCreatePi( pNtk, Buffer );
+                }
+            }
+            if ( Abc_NtkPoNum(pNtk) == 0 )
+            {
+                if ( nOutputs == -1 )
+                {
+                    printf( "%s: The number of outputs is not specified.\n", Extra_FileReaderGetFileName(p) );
+                    Abc_NtkDelete( pNtk );
+                    Extra_ProgressBarStop( pProgress );
+                    ABC_FREE( ppSops );
+                    return NULL;
+                }
+                nDigits = Abc_Base10Log( nOutputs );
+                for ( i = 0; i < nOutputs; i++ )
+                {
+                    sprintf( Buffer, "z%0*d", nDigits, i );
+                    Io_ReadCreatePo( pNtk, Buffer );
+                }
+            }
+            if ( Abc_NtkNodeNum(pNtk) == 0 )
+            { // first time here
+                // create the PO drivers and add them
+                // start the SOP covers
+                ppSops = ABC_ALLOC( Vec_Str_t *, nOutputs );
+                Abc_NtkForEachPo( pNtk, pTermPo, i )
+                {
+                    ppSops[i] = Vec_StrAlloc( 100 );
+                    // create the node
+                    pNode = Abc_NtkCreateNode(pNtk);
+                    // connect the node to the PO net
+                    Abc_ObjAddFanin( Abc_ObjFanin0Ntk(pTermPo), pNode );
+                    // connect the node to the PI nets
+                    Abc_NtkForEachPi( pNtk, pTermPi, k )
+                        Abc_ObjAddFanin( pNode, Abc_ObjFanout0Ntk(pTermPi) );
+                }
+            }
+            // read the cubes
+            if ( vTokens->nSize != 2 )
+            {
+                printf( "%s (line %d): Input and output cubes are not specified.\n", 
+                    Extra_FileReaderGetFileName(p), iLine );
+                Abc_NtkDelete( pNtk );
+                Extra_ProgressBarStop( pProgress );
+                ABC_FREE( ppSops );
+                return NULL;
+            }
+            pCubeIn  = (char *)vTokens->pArray[0];
+            pCubeOut = (char *)vTokens->pArray[1];
+            if ( strlen(pCubeIn) != (unsigned)nInputs )
+            {
+                printf( "%s (line %d): Input cube length (%zu) differs from the number of inputs (%d).\n",
+                    Extra_FileReaderGetFileName(p), iLine, strlen(pCubeIn), nInputs );
+                Abc_NtkDelete( pNtk );
+                return NULL;
+            }
+            if ( strlen(pCubeOut) != (unsigned)nOutputs )
+            {
+                printf( "%s (line %d): Output cube length (%zu) differs from the number of outputs (%d).\n",
+                    Extra_FileReaderGetFileName(p), iLine, strlen(pCubeOut), nOutputs );
+                Abc_NtkDelete( pNtk );
+                Extra_ProgressBarStop( pProgress );
+                ABC_FREE( ppSops );
+                return NULL;
+            }
+            if ( fZeros )
+            {
+                for ( i = 0; i < nOutputs; i++ )
+                {
+                    if ( pCubeOut[i] == '0' )
+                    {
+                        Vec_StrPrintStr( ppSops[i], pCubeIn );
+                        Vec_StrPrintStr( ppSops[i], " 1\n" );
+                    }
+                }
+            }
+            else
+            {
+                for ( i = 0; i < nOutputs; i++ )
+                {
+                    if ( pCubeOut[i] == '1' )
+                    {
+                        Vec_StrPrintStr( ppSops[i], pCubeIn );
+                        Vec_StrPrintStr( ppSops[i], " 1\n" );
+                    }
+                }
+            }
+            nCubes++;
+        }
+    }
+    Extra_ProgressBarStop( pProgress );
+    if ( nProducts != -1 && nCubes != nProducts )
+        printf( "Warning: Mismatch between the number of cubes (%d) and the number on .p line (%d).\n", 
+            nCubes, nProducts );
+
+    // add the SOP covers
+    Abc_NtkForEachPo( pNtk, pTermPo, i )
+    {
+        pNode = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pTermPo) );
+        if ( ppSops[i]->nSize == 0 )
+        {
+            Abc_ObjRemoveFanins(pNode);
+            pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 0\n" );
+            Vec_StrFree( ppSops[i] );
+            continue;
+        }
+        Vec_StrPush( ppSops[i], 0 );
+        pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, ppSops[i]->pArray );
+        Vec_StrFree( ppSops[i] );
+    }
+    ABC_FREE( ppSops );
+    Abc_NtkFinalizeRead( pNtk );
+    return pNtk;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioReadVerilog.c b/abc-build/src/base/io/ioReadVerilog.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioReadVerilog.c
@@ -0,0 +1,102 @@
+/**CFile****************************************************************
+
+  FileName    [ioReadVerilog.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedure to read network from file.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioReadVerilog.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+#include "base/ver/ver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+//extern Abc_Des_t * Ver_ParseFile( char * pFileName, Abc_Des_t * pGateLib, int fCheck, int fUseMemMan );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reads hierarchical design from the Verilog file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck )
+{
+    Abc_Ntk_t * pNtk, * pTemp;
+    Abc_Des_t * pDesign;
+    int i, RetValue;
+
+    // parse the verilog file
+    pDesign = Ver_ParseFile( pFileName, NULL, fCheck, 1 );
+    if ( pDesign == NULL )
+        return NULL;
+
+    // detect top-level model
+    RetValue = Abc_DesFindTopLevelModels( pDesign );
+    pNtk = (Abc_Ntk_t *)Vec_PtrEntry( pDesign->vTops, 0 );
+    if ( RetValue > 1 )
+    {
+        printf( "Warning: The design has %d root-level modules: ", Vec_PtrSize(pDesign->vTops) );
+        Vec_PtrForEachEntry( Abc_Ntk_t *, pDesign->vTops, pTemp, i )
+            printf( " %s", Abc_NtkName(pTemp) );
+        printf( "\n" );
+        printf( "The first one (%s) will be used.\n", pNtk->pName );
+    }
+
+    // extract the master network
+    pNtk->pDesign = pDesign;
+    pDesign->pManFunc = NULL;
+
+    // verify the design for cyclic dependence
+    assert( Vec_PtrSize(pDesign->vModules) > 0 );
+    if ( Vec_PtrSize(pDesign->vModules) == 1 )
+    {
+//        printf( "Warning: The design is not hierarchical.\n" );
+        Abc_DesFree( pDesign, pNtk );
+        pNtk->pDesign = NULL;
+        pNtk->pSpec = Extra_UtilStrsav( pFileName );
+    }
+    else
+    {
+        // check that there is no cyclic dependency
+        Abc_NtkIsAcyclicHierarchy( pNtk );
+    }
+
+//Io_WriteVerilog( pNtk, "_temp.v" );
+//    Abc_NtkPrintBoxInfo( pNtk );
+    return pNtk;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioUtil.c b/abc-build/src/base/io/ioUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioUtil.c
@@ -0,0 +1,853 @@
+/**CFile****************************************************************
+
+  FileName    [ioUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to write the network in BENCH format.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the file type.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Io_FileType_t Io_ReadFileType( char * pFileName )
+{
+    char * pExt;
+    if ( pFileName == NULL )
+        return IO_FILE_NONE;
+    pExt = Extra_FileNameExtension( pFileName );
+    if ( pExt == NULL )
+        return IO_FILE_NONE;
+    if ( !strcmp( pExt, "aig" ) )
+        return IO_FILE_AIGER;
+    if ( !strcmp( pExt, "baf" ) )
+        return IO_FILE_BAF;
+    if ( !strcmp( pExt, "bblif" ) )
+        return IO_FILE_BBLIF;
+    if ( !strcmp( pExt, "blif" ) )
+        return IO_FILE_BLIF;
+    if ( !strcmp( pExt, "bench" ) )
+        return IO_FILE_BENCH;
+    if ( !strcmp( pExt, "cnf" ) )
+        return IO_FILE_CNF;
+    if ( !strcmp( pExt, "dot" ) )
+        return IO_FILE_DOT;
+    if ( !strcmp( pExt, "edif" ) )
+        return IO_FILE_EDIF;
+    if ( !strcmp( pExt, "eqn" ) )
+        return IO_FILE_EQN;
+    if ( !strcmp( pExt, "gml" ) )
+        return IO_FILE_GML;
+    if ( !strcmp( pExt, "list" ) )
+        return IO_FILE_LIST;
+    if ( !strcmp( pExt, "mv" ) )
+        return IO_FILE_BLIFMV;
+    if ( !strcmp( pExt, "pla" ) )
+        return IO_FILE_PLA;
+    if ( !strcmp( pExt, "smv" ) )
+        return IO_FILE_SMV;
+    if ( !strcmp( pExt, "v" ) )
+        return IO_FILE_VERILOG;
+    return IO_FILE_UNKNOWN;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read the network from a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadNetlist( char * pFileName, Io_FileType_t FileType, int fCheck )
+{
+    FILE * pFile;
+    Abc_Ntk_t * pNtk;
+    if ( FileType == IO_FILE_NONE || FileType == IO_FILE_UNKNOWN )
+    {
+        fprintf( stdout, "Generic file reader requires a known file extension to open \"%s\".\n", pFileName );
+        return NULL;
+    }
+    // check if the file exists
+    pFile = fopen( pFileName, "r" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Cannot open input file \"%s\". ", pFileName );
+        if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".blif", ".bench", ".pla", ".baf", ".aig" )) )
+            fprintf( stdout, "Did you mean \"%s\"?", pFileName );
+        fprintf( stdout, "\n" );
+       return NULL;
+    }
+    fclose( pFile );
+    // read the AIG
+    if ( FileType == IO_FILE_AIGER || FileType == IO_FILE_BAF || FileType == IO_FILE_BBLIF )
+    {
+        if ( FileType == IO_FILE_AIGER )
+            pNtk = Io_ReadAiger( pFileName, fCheck );
+        else if ( FileType == IO_FILE_BAF )
+            pNtk = Io_ReadBaf( pFileName, fCheck );
+        else // if ( FileType == IO_FILE_BBLIF )
+            pNtk = Io_ReadBblif( pFileName, fCheck );
+        if ( pNtk == NULL )
+        {
+            fprintf( stdout, "Reading AIG from file has failed.\n" );
+            return NULL;
+        }
+        return pNtk;
+    }
+    // read the new netlist
+    if ( FileType == IO_FILE_BLIF )
+//        pNtk = Io_ReadBlif( pFileName, fCheck );
+        pNtk = Io_ReadBlifMv( pFileName, 0, fCheck );
+    else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV )
+        pNtk = Io_ReadBlifMv( pFileName, 1, fCheck );
+    else if ( FileType == IO_FILE_BENCH )
+        pNtk = Io_ReadBench( pFileName, fCheck );
+    else if ( FileType == IO_FILE_EDIF )
+        pNtk = Io_ReadEdif( pFileName, fCheck );
+    else if ( FileType == IO_FILE_EQN )
+        pNtk = Io_ReadEqn( pFileName, fCheck );
+    else if ( FileType == IO_FILE_PLA )
+        pNtk = Io_ReadPla( pFileName, 0, fCheck );
+    else if ( FileType == IO_FILE_VERILOG )
+        pNtk = Io_ReadVerilog( pFileName, fCheck );
+    else 
+    {
+        fprintf( stderr, "Unknown file format.\n" );
+        return NULL;
+    }
+    if ( pNtk == NULL )
+    {
+        fprintf( stdout, "Reading network from file has failed.\n" );
+        return NULL;
+    }
+    if ( Abc_NtkBlackboxNum(pNtk) || Abc_NtkWhiteboxNum(pNtk) )
+        fprintf( stdout, "Warning: The network contains hierarchy.\n" );
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t *temporaryLtlStore( Abc_Ntk_t *pNtk )
+{
+	Vec_Ptr_t *tempStore;
+	char *pFormula;
+	int i;
+
+	if( pNtk && Vec_PtrSize( pNtk->vLtlProperties ) > 0 )
+	{
+		tempStore = Vec_PtrAlloc( Vec_PtrSize( pNtk->vLtlProperties ) );
+		Vec_PtrForEachEntry( char *, pNtk->vLtlProperties, pFormula, i )
+			Vec_PtrPush( tempStore, pFormula );
+		assert( Vec_PtrSize( tempStore ) == Vec_PtrSize( pNtk->vLtlProperties ) );
+		return tempStore;
+	}
+	else
+		return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void updateLtlStoreOfNtk( Abc_Ntk_t *pNtk, Vec_Ptr_t *tempLtlStore )
+{
+	int i;
+	char *pFormula;
+
+	assert( tempLtlStore != NULL );
+	Vec_PtrForEachEntry( char *, tempLtlStore, pFormula, i )
+		Vec_PtrPush( pNtk->vLtlProperties, pFormula );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read the network from a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Io_Read( char * pFileName, Io_FileType_t FileType, int fCheck, int fBarBufs )
+{
+    Abc_Ntk_t * pNtk, * pTemp;
+	Vec_Ptr_t * vLtl;
+    // get the netlist
+    pNtk = Io_ReadNetlist( pFileName, FileType, fCheck );
+    if ( pNtk == NULL )
+        return NULL;
+	vLtl = temporaryLtlStore( pNtk );
+    if ( !Abc_NtkIsNetlist(pNtk) )
+        return pNtk;
+    // derive barbufs
+    if ( fBarBufs )
+    {
+        pNtk = Abc_NtkToBarBufs( pTemp = pNtk );
+        Abc_NtkDelete( pTemp );
+        assert( Abc_NtkIsLogic(pNtk) );
+        return pNtk;
+    }
+    // flatten logic hierarchy
+    assert( Abc_NtkIsNetlist(pNtk) );
+    if ( Abc_NtkWhiteboxNum(pNtk) > 0 )
+    {
+        pNtk = Abc_NtkFlattenLogicHierarchy( pTemp = pNtk );
+        Abc_NtkDelete( pTemp );
+        if ( pNtk == NULL )
+        {
+            fprintf( stdout, "Flattening logic hierarchy has failed.\n" );
+            return NULL;
+        }
+    }
+    // convert blackboxes
+    if ( Abc_NtkBlackboxNum(pNtk) > 0 )
+    {
+        printf( "Hierarchy reader converted %d instances of blackboxes.\n", Abc_NtkBlackboxNum(pNtk) );
+        pNtk = Abc_NtkConvertBlackboxes( pTemp = pNtk );
+        Abc_NtkDelete( pTemp );
+        if ( pNtk == NULL )
+        {
+            fprintf( stdout, "Converting blackboxes has failed.\n" );
+            return NULL;
+        }
+    }
+    // consider the case of BLIF-MV
+    if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV )
+    {
+        pNtk = Abc_NtkStrashBlifMv( pTemp = pNtk );
+        Abc_NtkDelete( pTemp );
+        if ( pNtk == NULL )
+        {
+            fprintf( stdout, "Converting BLIF-MV to AIG has failed.\n" );
+            return NULL;
+        }
+        return pNtk;
+    }
+    // convert the netlist into the logic network
+    pNtk = Abc_NtkToLogic( pTemp = pNtk );
+	if( vLtl )
+		updateLtlStoreOfNtk( pNtk, vLtl );
+    Abc_NtkDelete( pTemp );
+    if ( pNtk == NULL )
+    {
+        fprintf( stdout, "Converting netlist to logic network after reading has failed.\n" );
+        return NULL;
+    }
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the network into file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType )
+{
+    Abc_Ntk_t * pNtkTemp, * pNtkCopy;
+    // check if the current network is available
+    if ( pNtk == NULL )
+    {
+        fprintf( stdout, "Empty network.\n" );
+        return;
+    }
+    // check if the file extension if given
+    if ( FileType == IO_FILE_NONE || FileType == IO_FILE_UNKNOWN )
+    {
+        fprintf( stdout, "The generic file writer requires a known file extension.\n" );
+        return;
+    }
+    // write the AIG formats
+    if ( FileType == IO_FILE_AIGER || FileType == IO_FILE_BAF )
+    {
+        if ( !Abc_NtkIsStrash(pNtk) )
+        {
+            fprintf( stdout, "Writing this format is only possible for structurally hashed AIGs.\n" );
+            return;
+        }
+        if ( FileType == IO_FILE_AIGER )
+            Io_WriteAiger( pNtk, pFileName, 1, 0, 0 );
+        else //if ( FileType == IO_FILE_BAF )
+            Io_WriteBaf( pNtk, pFileName );
+        return;
+    }
+    // write non-netlist types
+    if ( FileType == IO_FILE_CNF )
+    {
+        Io_WriteCnf( pNtk, pFileName, 0 );
+        return;
+    }
+    if ( FileType == IO_FILE_DOT )
+    {
+        Io_WriteDot( pNtk, pFileName );
+        return;
+    }
+    if ( FileType == IO_FILE_GML )
+    {
+        Io_WriteGml( pNtk, pFileName );
+        return;
+    }
+    if ( FileType == IO_FILE_BBLIF )
+    {
+        if ( !Abc_NtkIsLogic(pNtk) )
+        {
+            fprintf( stdout, "Writing Binary BLIF is only possible for logic networks.\n" );
+            return;
+        }
+        if ( !Abc_NtkHasSop(pNtk) )
+            Abc_NtkToSop( pNtk, 0 );
+        Io_WriteBblif( pNtk, pFileName );
+        return;
+    }
+/*
+    if ( FileType == IO_FILE_BLIFMV )
+    {
+        Io_WriteBlifMv( pNtk, pFileName );
+        return;
+    }
+*/
+    // convert logic network into netlist
+    if ( FileType == IO_FILE_PLA )
+    {
+        if ( Abc_NtkLevel(pNtk) > 1 )
+        {
+            fprintf( stdout, "PLA writing is available for collapsed networks.\n" );
+            return;
+        }
+        if ( Abc_NtkIsComb(pNtk) )
+            pNtkTemp = Abc_NtkToNetlist( pNtk );
+        else
+        {
+            fprintf( stdout, "Latches are writen into the PLA file at PI/PO pairs.\n" );
+            pNtkCopy = Abc_NtkDup( pNtk );
+            Abc_NtkMakeComb( pNtkCopy, 0 );
+            pNtkTemp = Abc_NtkToNetlist( pNtk );
+            Abc_NtkDelete( pNtkCopy );
+        }
+        if ( !Abc_NtkToSop( pNtkTemp, 1 ) )
+            return;
+    }
+    else if ( FileType == IO_FILE_BENCH )
+    {
+        if ( !Abc_NtkIsStrash(pNtk) )
+        {
+            fprintf( stdout, "Writing traditional BENCH is available for AIGs only (use \"write_bench\").\n" );
+            return;
+        }
+        pNtkTemp = Abc_NtkToNetlistBench( pNtk );
+    }
+    else if ( FileType == IO_FILE_SMV )
+    {
+        if ( !Abc_NtkIsStrash(pNtk) )
+        {
+            fprintf( stdout, "Writing traditional SMV is available for AIGs only.\n" );
+            return;
+        }
+        pNtkTemp = Abc_NtkToNetlistBench( pNtk );
+    }
+    else
+        pNtkTemp = Abc_NtkToNetlist( pNtk );
+
+    if ( pNtkTemp == NULL )
+    {
+        fprintf( stdout, "Converting to netlist has failed.\n" );
+        return;
+    }
+
+    if ( FileType == IO_FILE_BLIF )
+    {
+        if ( !Abc_NtkHasSop(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) )
+            Abc_NtkToSop( pNtkTemp, 0 );
+        Io_WriteBlif( pNtkTemp, pFileName, 1, 0, 0 );
+    }
+    else if ( FileType == IO_FILE_BLIFMV )
+    {
+        if ( !Abc_NtkConvertToBlifMv( pNtkTemp ) )
+            return;
+        Io_WriteBlifMv( pNtkTemp, pFileName );
+    }
+    else if ( FileType == IO_FILE_BENCH )
+        Io_WriteBench( pNtkTemp, pFileName );
+    else if ( FileType == IO_FILE_BOOK )
+        Io_WriteBook( pNtkTemp, pFileName );
+    else if ( FileType == IO_FILE_PLA )
+        Io_WritePla( pNtkTemp, pFileName );
+    else if ( FileType == IO_FILE_EQN )
+    {
+        if ( !Abc_NtkHasAig(pNtkTemp) )
+            Abc_NtkToAig( pNtkTemp );
+        Io_WriteEqn( pNtkTemp, pFileName );
+    }
+    else if ( FileType == IO_FILE_SMV )
+        Io_WriteSmv( pNtkTemp, pFileName );
+    else if ( FileType == IO_FILE_VERILOG )
+    {
+        if ( !Abc_NtkHasAig(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) )
+            Abc_NtkToAig( pNtkTemp );
+        Io_WriteVerilog( pNtkTemp, pFileName );
+    }
+    else 
+        fprintf( stderr, "Unknown file format.\n" );
+    Abc_NtkDelete( pNtkTemp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the network into file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName )
+{
+    Abc_Ntk_t * pNtkTemp, * pNtkResult, * pNtkBase = NULL;
+    int i;
+    // check if the current network is available
+    if ( pNtk == NULL )
+    {
+        fprintf( stdout, "Empty network.\n" );
+        return;
+    }
+
+    // read the base network
+    assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) );
+    if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIF )
+        pNtkBase = Io_ReadBlifMv( pBaseName, 0, 1 );
+    else if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV )
+        pNtkBase = Io_ReadBlifMv( pBaseName, 1, 1 );
+    else if ( Io_ReadFileType(pBaseName) == IO_FILE_VERILOG )
+        pNtkBase = Io_ReadVerilog( pBaseName, 1 );
+    else 
+        fprintf( stderr, "Unknown input file format.\n" );
+    if ( pNtkBase == NULL )
+        return;
+
+    // flatten logic hierarchy if present
+    if ( Abc_NtkWhiteboxNum(pNtkBase) > 0 && pNtk->nBarBufs == 0 )
+    {
+        pNtkBase = Abc_NtkFlattenLogicHierarchy( pNtkTemp = pNtkBase );
+        Abc_NtkDelete( pNtkTemp );
+        if ( pNtkBase == NULL )
+            return;
+    }
+
+    // reintroduce the boxes into the netlist
+    if ( pNtk->nBarBufs > 0 )
+    {
+        // derive the netlist
+        pNtkResult = Abc_NtkToNetlist( pNtk );
+        pNtkResult = Abc_NtkFromBarBufs( pNtkBase, pNtkTemp = pNtkResult );
+        Abc_NtkDelete( pNtkTemp );
+        if ( pNtkResult )
+            printf( "Hierarchy writer replaced %d barbufs by hierarchy boundaries.\n", pNtk->nBarBufs );
+    }
+    else if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV ) 
+    {
+        if ( Abc_NtkBlackboxNum(pNtkBase) > 0 )
+        {
+            printf( "Hierarchy writer does not support BLIF-MV with blackboxes.\n" );
+            Abc_NtkDelete( pNtkBase );
+            return;
+        }
+        // convert the current network to BLIF-MV
+        assert( !Abc_NtkIsNetlist(pNtk) );
+        pNtkResult = Abc_NtkToNetlist( pNtk );
+        if ( !Abc_NtkConvertToBlifMv( pNtkResult ) )
+        {
+            Abc_NtkDelete( pNtkBase );
+            return;
+        }
+        // reintroduce the network
+        pNtkResult = Abc_NtkInsertBlifMv( pNtkBase, pNtkTemp = pNtkResult );
+        Abc_NtkDelete( pNtkTemp );
+    }
+    else if ( Abc_NtkBlackboxNum(pNtkBase) > 0 )
+    {
+        // derive the netlist
+        pNtkResult = Abc_NtkToNetlist( pNtk );
+        pNtkResult = Abc_NtkInsertNewLogic( pNtkBase, pNtkTemp = pNtkResult );
+        Abc_NtkDelete( pNtkTemp );
+        if ( pNtkResult )
+            printf( "Hierarchy writer reintroduced %d instances of blackboxes.\n", Abc_NtkBlackboxNum(pNtkBase) );
+    }
+    else
+    {
+        printf( "Warning: The output network does not contain blackboxes.\n" );
+        pNtkResult = Abc_NtkToNetlist( pNtk );
+    }
+    Abc_NtkDelete( pNtkBase );
+    if ( pNtkResult == NULL )
+        return;
+
+    // write the resulting network
+    if ( Io_ReadFileType(pFileName) == IO_FILE_BLIF )
+    {
+        if ( pNtkResult->pDesign )
+        {
+            Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkResult->pDesign->vModules, pNtkTemp, i )
+                if ( !Abc_NtkHasSop(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) )
+                    Abc_NtkToSop( pNtkTemp, 0 );
+        }
+        else
+        {
+            if ( !Abc_NtkHasSop(pNtkResult) && !Abc_NtkHasMapping(pNtkResult) )
+                Abc_NtkToSop( pNtkResult, 0 );
+        }
+        Io_WriteBlif( pNtkResult, pFileName, 1, 0, 0 );
+    }
+    else if ( Io_ReadFileType(pFileName) == IO_FILE_VERILOG )
+    {
+        if ( pNtkResult->pDesign )
+        {
+            Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkResult->pDesign->vModules, pNtkTemp, i )
+                if ( !Abc_NtkHasAig(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) )
+                    Abc_NtkToAig( pNtkTemp );
+        }
+        else
+        {
+            if ( !Abc_NtkHasAig(pNtkResult) && !Abc_NtkHasMapping(pNtkResult) )
+                Abc_NtkToAig( pNtkResult );
+        }
+        Io_WriteVerilog( pNtkResult, pFileName );
+    }
+    else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV )
+    {
+        Io_WriteBlifMv( pNtkResult, pFileName );
+    }
+    else 
+        fprintf( stderr, "Unknown output file format.\n" );
+
+    Abc_NtkDelete( pNtkResult );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates PI terminal and net.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Io_ReadCreatePi( Abc_Ntk_t * pNtk, char * pName )
+{
+    Abc_Obj_t * pNet, * pTerm;
+    // get the PI net
+    pNet  = Abc_NtkFindNet( pNtk, pName );
+    if ( pNet )
+        printf( "Warning: PI \"%s\" appears twice in the list.\n", pName );
+    pNet  = Abc_NtkFindOrCreateNet( pNtk, pName );
+    // add the PI node
+    pTerm = Abc_NtkCreatePi( pNtk );
+    Abc_ObjAddFanin( pNet, pTerm );
+    return pTerm;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates PO terminal and net.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Io_ReadCreatePo( Abc_Ntk_t * pNtk, char * pName )
+{
+    Abc_Obj_t * pNet, * pTerm;
+    // get the PO net
+    pNet  = Abc_NtkFindNet( pNtk, pName );
+    if ( pNet && Abc_ObjFaninNum(pNet) == 0 )
+        printf( "Warning: PO \"%s\" appears twice in the list.\n", pName );
+    pNet  = Abc_NtkFindOrCreateNet( pNtk, pName );
+    // add the PO node
+    pTerm = Abc_NtkCreatePo( pNtk );
+    Abc_ObjAddFanin( pTerm, pNet );
+    return pTerm;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create a latch with the given input/output.]
+
+  Description [By default, the latch value is unknown (ABC_INIT_NONE).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO )
+{
+    Abc_Obj_t * pLatch, * pTerm, * pNet;
+    // get the LI net
+    pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLI );
+    // add the BO terminal
+    pTerm = Abc_NtkCreateBi( pNtk );
+    Abc_ObjAddFanin( pTerm, pNet );
+    // add the latch box
+    pLatch = Abc_NtkCreateLatch( pNtk );
+    Abc_ObjAddFanin( pLatch, pTerm  );
+    // add the BI terminal
+    pTerm = Abc_NtkCreateBo( pNtk );
+    Abc_ObjAddFanin( pTerm, pLatch );
+    // get the LO net
+    pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLO );
+    Abc_ObjAddFanin( pNet, pTerm );
+    // set latch name
+    Abc_ObjAssignName( pLatch, pNetLO, "L" );
+    return pLatch;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the reset latch with data=1 and init=0.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Io_ReadCreateResetLatch( Abc_Ntk_t * pNtk, int fBlifMv )
+{
+    Abc_Obj_t * pLatch, * pNode;
+    Abc_Obj_t * pNetLI, * pNetLO;
+    // create latch with 0 init value
+//    pLatch = Io_ReadCreateLatch( pNtk, "_resetLI_", "_resetLO_" );
+    pNetLI = Abc_NtkCreateNet( pNtk );
+    pNetLO = Abc_NtkCreateNet( pNtk );
+    Abc_ObjAssignName( pNetLI, Abc_ObjName(pNetLI), NULL );
+    Abc_ObjAssignName( pNetLO, Abc_ObjName(pNetLO), NULL );
+    pLatch = Io_ReadCreateLatch( pNtk, Abc_ObjName(pNetLI), Abc_ObjName(pNetLO) );
+    // set the initial value
+    Abc_LatchSetInit0( pLatch );
+    // feed the latch with constant1- node
+//    pNode = Abc_NtkCreateNode( pNtk );   
+//    pNode->pData = Abc_SopRegister( (Extra_MmFlex_t *)pNtk->pManFunc, "2\n1\n" );
+    pNode = Abc_NtkCreateNodeConst1( pNtk );
+    Abc_ObjAddFanin( Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pNode );
+    return pLatch;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create node and the net driven by it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Io_ReadCreateNode( Abc_Ntk_t * pNtk, char * pNameOut, char * pNamesIn[], int nInputs )
+{
+    Abc_Obj_t * pNet, * pNode;
+    int i;
+    // create a new node 
+    pNode = Abc_NtkCreateNode( pNtk );
+    // add the fanin nets
+    for ( i = 0; i < nInputs; i++ )
+    {
+        pNet = Abc_NtkFindOrCreateNet( pNtk, pNamesIn[i] );
+        Abc_ObjAddFanin( pNode, pNet );
+    }
+    // add the fanout net
+    pNet = Abc_NtkFindOrCreateNet( pNtk, pNameOut );
+    Abc_ObjAddFanin( pNet, pNode );
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create a constant 0 node driving the net with this name.]
+
+  Description [Assumes that the net already exists.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Io_ReadCreateConst( Abc_Ntk_t * pNtk, char * pName, int fConst1 )
+{
+    Abc_Obj_t * pNet, * pTerm;
+    pTerm = fConst1? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk);
+    pNet  = Abc_NtkFindNet(pNtk, pName);    assert( pNet );
+    Abc_ObjAddFanin( pNet, pTerm );
+    return pTerm;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create an inverter or buffer for the given net.]
+
+  Description [Assumes that the nets already exist.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Io_ReadCreateInv( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut )
+{
+    Abc_Obj_t * pNet, * pNode;
+    pNet  = Abc_NtkFindNet(pNtk, pNameIn);     assert( pNet );
+    pNode = Abc_NtkCreateNodeInv(pNtk, pNet);
+    pNet  = Abc_NtkFindNet(pNtk, pNameOut);    assert( pNet );
+    Abc_ObjAddFanin( pNet, pNode );
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create an inverter or buffer for the given net.]
+
+  Description [Assumes that the nets already exist.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Io_ReadCreateBuf( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut )
+{
+    Abc_Obj_t * pNet, * pNode;
+    pNet  = Abc_NtkFindNet(pNtk, pNameIn);     assert( pNet );
+    pNode = Abc_NtkCreateNodeBuf(pNtk, pNet);
+    pNet  = Abc_NtkFindNet(pNtk, pNameOut);    assert( pNet );
+    Abc_ObjAddFanin( pNet, pNode );
+    return pNet;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Provide an fopen replacement with path lookup]
+
+  Description [Provide an fopen replacement where the path stored
+               in pathvar MVSIS variable is used to look up the path
+               for name. Returns NULL if file cannot be opened.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose )
+{
+    char * t = 0, * c = 0, * i;
+
+    if ( PathVar == 0 )
+    {
+        return fopen( FileName, Mode );
+    }
+    else
+    {
+        if ( (c = Abc_FrameReadFlag( (char*)PathVar )) )
+        {
+            char ActualFileName[4096];
+            FILE * fp = 0;
+            t = Extra_UtilStrsav( c );
+            for (i = strtok( t, ":" ); i != 0; i = strtok( 0, ":") )
+            {
+#ifdef WIN32
+                _snprintf ( ActualFileName, 4096, "%s/%s", i, FileName );
+#else
+                snprintf ( ActualFileName, 4096, "%s/%s", i, FileName );
+#endif
+                if ( ( fp = fopen ( ActualFileName, Mode ) ) )
+                {
+                    if ( fVerbose )
+                    fprintf ( stdout, "Using file %s\n", ActualFileName );
+                    ABC_FREE( t );
+                    return fp;
+                }
+            }
+            ABC_FREE( t );
+            return 0;
+        }
+        else
+        {
+            return fopen( FileName, Mode );
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioWriteAiger.c b/abc-build/src/base/io/ioWriteAiger.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioWriteAiger.c
@@ -0,0 +1,956 @@
+/**CFile****************************************************************
+
+  FileName    [ioWriteAiger.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to write binary AIGER format developed by
+  Armin Biere, Johannes Kepler University (http://fmv.jku.at/)]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - December 16, 2006.]
+
+  Revision    [$Id: ioWriteAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+// The code in this file is developed in collaboration with Mark Jarvin of Toronto.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/bzlib/bzlib.h"
+#include "misc/zlib/zlib.h"
+#include "ioAbc.h"
+
+
+
+ABC_NAMESPACE_IMPL_START
+
+
+#ifdef _WIN32
+#define vsnprintf _vsnprintf
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+/*
+    The following is taken from the AIGER format description, 
+    which can be found at http://fmv.jku.at/aiger
+*/
+
+
+/*
+         The AIGER And-Inverter Graph (AIG) Format Version 20061129
+         ----------------------------------------------------------
+              Armin Biere, Johannes Kepler University, 2006
+
+  This report describes the AIG file format as used by the AIGER library.
+  The purpose of this report is not only to motivate and document the
+  format, but also to allow independent implementations of writers and
+  readers by giving precise and unambiguous definitions.
+
+  ...
+
+Introduction
+
+  The name AIGER contains as one part the acronym AIG of And-Inverter
+  Graphs and also if pronounced in German sounds like the name of the
+  'Eiger', a mountain in the Swiss alps.  This choice should emphasize the
+  origin of this format. It was first openly discussed at the Alpine
+  Verification Meeting 2006 in Ascona as a way to provide a simple, compact
+  file format for a model checking competition affiliated to CAV 2007.
+
+  ...
+
+Binary Format Definition
+
+  The binary format is semantically a subset of the ASCII format with a
+  slightly different syntax.  The binary format may need to reencode
+  literals, but translating a file in binary format into ASCII format and
+  then back in to binary format will result in the same file.
+
+  The main differences of the binary format to the ASCII format are as
+  follows.  After the header the list of input literals and all the
+  current state literals of a latch can be omitted.  Furthermore the
+  definitions of the AND gates are binary encoded.  However, the symbol
+  table and the comment section are as in the ASCII format.
+
+  The header of an AIGER file in binary format has 'aig' as format
+  identifier, but otherwise is identical to the ASCII header.  The standard
+  file extension for the binary format is therefore '.aig'. 
+  
+  A header for the binary format is still in ASCII encoding:
+
+    aig M I L O A
+
+  Constants, variables and literals are handled in the same way as in the
+  ASCII format.  The first simplifying restriction is on the variable
+  indices of inputs and latches.  The variable indices of inputs come first,
+  followed by the pseudo-primary inputs of the latches and then the variable
+  indices of all LHS of AND gates:
+
+    input variable indices        1,          2,  ... ,  I
+    latch variable indices      I+1,        I+2,  ... ,  (I+L)
+    AND variable indices      I+L+1,      I+L+2,  ... ,  (I+L+A) == M
+
+  The corresponding unsigned literals are
+
+    input literals                2,          4,  ... ,  2*I
+    latch literals            2*I+2,      2*I+4,  ... ,  2*(I+L)
+    AND literals          2*(I+L)+2,  2*(I+L)+4,  ... ,  2*(I+L+A) == 2*M
+                    
+  All literals have to be defined, and therefore 'M = I + L + A'.  With this
+  restriction it becomes possible that the inputs and the current state
+  literals of the latches do not have to be listed explicitly.  Therefore,
+  after the header only the list of 'L' next state literals follows, one per
+  latch on a single line, and then the 'O' outputs, again one per line.
+
+  In the binary format we assume that the AND gates are ordered and respect
+  the child parent relation.  AND gates with smaller literals on the LHS
+  come first.  Therefore we can assume that the literals on the right-hand
+  side of a definition of an AND gate are smaller than the LHS literal.
+  Furthermore we can sort the literals on the RHS, such that the larger
+  literal comes first.  A definition thus consists of three literals
+    
+      lhs rhs0 rhs1
+
+  with 'lhs' even and 'lhs > rhs0 >= rhs1'.  Also the variable indices are
+  pairwise different to avoid combinational self loops.  Since the LHS
+  indices of the definitions are all consecutive (as even integers),
+  the binary format does not have to keep 'lhs'.  In addition, we can use
+  the order restriction and only write the differences 'delta0' and 'delta1'
+  instead of 'rhs0' and 'rhs1', with
+
+      delta0 = lhs - rhs0,  delta1 = rhs0 - rhs1
+  
+  The differences will all be strictly positive, and in practice often very
+  small.  We can take advantage of this fact by the simple little-endian
+  encoding of unsigned integers of the next section.  After the binary delta
+  encoding of the RHSs of all AND gates, the optional symbol table and
+  optional comment section start in the same format as in the ASCII case.
+
+  ...
+
+*/
+
+static unsigned Io_ObjMakeLit( int Var, int fCompl )                 { return (Var << 1) | fCompl;                   }
+static unsigned Io_ObjAigerNum( Abc_Obj_t * pObj )                   { return (unsigned)(ABC_PTRINT_T)pObj->pCopy;  }
+static void     Io_ObjSetAigerNum( Abc_Obj_t * pObj, unsigned Num )  { pObj->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Num;     }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one unsigned AIG edge to the output buffer.]
+
+  Description [This procedure is a slightly modified version of Armin Biere's
+  procedure "void encode (FILE * file, unsigned x)" ]
+  
+  SideEffects [Returns the current writing position.]
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_WriteAigerEncode( unsigned char * pBuffer, int Pos, unsigned x )
+{
+    unsigned char ch;
+    while (x & ~0x7f)
+    {
+        ch = (x & 0x7f) | 0x80;
+//        putc (ch, file);
+        pBuffer[Pos++] = ch;
+        x >>= 7;
+    }
+    ch = x;
+//    putc (ch, file);
+    pBuffer[Pos++] = ch;
+    return Pos;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the array of literals to be written.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Io_WriteAigerLiterals( Abc_Ntk_t * pNtk )
+{
+    Vec_Int_t * vLits;
+    Abc_Obj_t * pObj, * pDriver;
+    int i;
+    vLits = Vec_IntAlloc( Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachLatchInput( pNtk, pObj, i )
+    {
+        pDriver = Abc_ObjFanin0(pObj);
+        Vec_IntPush( vLits, Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) );
+    }
+    Abc_NtkForEachPo( pNtk, pObj, i )
+    {
+        pDriver = Abc_ObjFanin0(pObj);
+        Vec_IntPush( vLits, Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) );
+    }
+    return vLits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the binary encoded array of literals.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Io_WriteEncodeLiterals( Vec_Int_t * vLits )
+{
+    Vec_Str_t * vBinary;
+    int Pos = 0, Lit, LitPrev, Diff, i;
+    vBinary = Vec_StrAlloc( 2 * Vec_IntSize(vLits) );
+    LitPrev = Vec_IntEntry( vLits, 0 );
+    Pos = Io_WriteAigerEncode( (unsigned char *)Vec_StrArray(vBinary), Pos, LitPrev ); 
+    Vec_IntForEachEntryStart( vLits, Lit, i, 1 )
+    {
+        Diff = Lit - LitPrev;
+        Diff = (Lit < LitPrev)? -Diff : Diff;
+        Diff = (Diff << 1) | (int)(Lit < LitPrev);
+        Pos = Io_WriteAigerEncode( (unsigned char *)Vec_StrArray(vBinary), Pos, Diff );
+        LitPrev = Lit;
+        if ( Pos + 10 > vBinary->nCap )
+            Vec_StrGrow( vBinary, vBinary->nCap+1 );
+    }
+    vBinary->nSize = Pos;
+/*
+    // verify
+    {
+        extern Vec_Int_t * Io_WriteDecodeLiterals( char ** ppPos, int nEntries );
+        char * pPos = Vec_StrArray( vBinary );
+        Vec_Int_t * vTemp = Io_WriteDecodeLiterals( &pPos, Vec_IntSize(vLits) );
+        for ( i = 0; i < Vec_IntSize(vLits); i++ )
+        {
+            int Entry1 = Vec_IntEntry(vLits,i);
+            int Entry2 = Vec_IntEntry(vTemp,i);
+            assert( Entry1 == Entry2 );
+        }
+    }
+*/
+    return vBinary;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG in the binary AIGER format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteAiger_old( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols, int fCompact )
+{
+    ProgressBar * pProgress;
+    FILE * pFile;
+    Abc_Obj_t * pObj, * pDriver, * pLatch;
+    int i, nNodes, nBufferSize, Pos, fExtended;
+    unsigned char * pBuffer;
+    unsigned uLit0, uLit1, uLit;
+
+    fExtended = Abc_NtkConstrNum(pNtk);
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        if ( !Abc_LatchIsInit0(pObj) )
+        {
+            if ( !fCompact )
+            {
+                fExtended = 1;
+                break;
+            }
+            fprintf( stdout, "Io_WriteAiger(): Cannot write AIGER format with non-0 latch init values. Run \"zero\".\n" );
+            return;
+        }
+
+    // start the output stream
+    pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Io_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName );
+        return;
+    }
+
+    // set the node numbers to be used in the output file
+    nNodes = 0;
+    Io_ObjSetAigerNum( Abc_AigConst1(pNtk), nNodes++ );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        Io_ObjSetAigerNum( pObj, nNodes++ );
+    Abc_AigForEachAnd( pNtk, pObj, i )
+        Io_ObjSetAigerNum( pObj, nNodes++ );
+
+    // write the header "M I L O A" where M = I + L + A
+    fprintf( pFile, "aig%s %u %u %u %u %u", 
+        fCompact? "2" : "",
+        Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) + Abc_NtkNodeNum(pNtk), 
+        Abc_NtkPiNum(pNtk),
+        Abc_NtkLatchNum(pNtk),
+        fExtended ? 0 : Abc_NtkPoNum(pNtk),
+        Abc_NtkNodeNum(pNtk) );
+    // write the extended header "B C J F"
+    if ( fExtended )
+        fprintf( pFile, " %u %u", Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk), Abc_NtkConstrNum(pNtk) );
+    fprintf( pFile, "\n" );
+
+    // if the driver node is a constant, we need to complement the literal below
+    // because, in the AIGER format, literal 0/1 is represented as number 0/1
+    // while, in ABC, constant 1 node has number 0 and so literal 0/1 will be 1/0
+
+    Abc_NtkInvertConstraints( pNtk );
+    if ( !fCompact ) 
+    {
+        // write latch drivers
+        Abc_NtkForEachLatch( pNtk, pLatch, i )
+        {
+            pObj = Abc_ObjFanin0(pLatch);
+            pDriver = Abc_ObjFanin0(pObj);
+            uLit = Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) );
+            if ( Abc_LatchIsInit0(pLatch) )
+                fprintf( pFile, "%u\n", uLit );
+            else if ( Abc_LatchIsInit1(pLatch) )
+                fprintf( pFile, "%u 1\n", uLit );
+            else
+            {
+                // Both None and DC are written as 'uninitialized' e.g. a free boolean value
+                assert( Abc_LatchIsInitNone(pLatch) || Abc_LatchIsInitDc(pLatch) );
+                fprintf( pFile, "%u %u\n", uLit, Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanout0(pLatch)), 0 ) );
+            }
+        }
+        // write PO drivers
+        Abc_NtkForEachPo( pNtk, pObj, i )
+        {
+            pDriver = Abc_ObjFanin0(pObj);
+            fprintf( pFile, "%u\n", Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) );
+        }
+    }
+    else
+    {
+        Vec_Int_t * vLits = Io_WriteAigerLiterals( pNtk );
+        Vec_Str_t * vBinary = Io_WriteEncodeLiterals( vLits );
+        fwrite( Vec_StrArray(vBinary), 1, Vec_StrSize(vBinary), pFile );
+        Vec_StrFree( vBinary );
+        Vec_IntFree( vLits );
+    }
+    Abc_NtkInvertConstraints( pNtk );
+
+    // write the nodes into the buffer
+    Pos = 0;
+    nBufferSize = 6 * Abc_NtkNodeNum(pNtk) + 100; // skeptically assuming 3 chars per one AIG edge
+    pBuffer = ABC_ALLOC( unsigned char, nBufferSize );
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+    Abc_AigForEachAnd( pNtk, pObj, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        uLit  = Io_ObjMakeLit( Io_ObjAigerNum(pObj), 0 );
+        uLit0 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin0(pObj)), Abc_ObjFaninC0(pObj) );
+        uLit1 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin1(pObj)), Abc_ObjFaninC1(pObj) );
+        if ( uLit0 > uLit1 )
+        {
+            unsigned Temp = uLit0;
+            uLit0 = uLit1;
+            uLit1 = Temp;
+        }
+        assert( uLit1 < uLit );
+        Pos = Io_WriteAigerEncode( pBuffer, Pos, (unsigned)(uLit  - uLit1) );
+        Pos = Io_WriteAigerEncode( pBuffer, Pos, (unsigned)(uLit1 - uLit0) );
+        if ( Pos > nBufferSize - 10 )
+        {
+            printf( "Io_WriteAiger(): AIGER generation has failed because the allocated buffer is too small.\n" );
+	        fclose( pFile );
+            return;
+        }
+    }
+    assert( Pos < nBufferSize );
+    Extra_ProgressBarStop( pProgress );
+
+    // write the buffer
+    fwrite( pBuffer, 1, Pos, pFile );
+    ABC_FREE( pBuffer );
+
+    // write the symbol table
+    if ( fWriteSymbols )
+    {
+        // write PIs
+        Abc_NtkForEachPi( pNtk, pObj, i )
+            fprintf( pFile, "i%d %s\n", i, Abc_ObjName(pObj) );
+        // write latches
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+            fprintf( pFile, "l%d %s\n", i, Abc_ObjName(Abc_ObjFanout0(pObj)) );
+        // write POs
+        Abc_NtkForEachPo( pNtk, pObj, i )
+            if ( !fExtended )
+                fprintf( pFile, "o%d %s\n", i, Abc_ObjName(pObj) );
+            else if ( i < Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk) )
+                fprintf( pFile, "b%d %s\n", i, Abc_ObjName(pObj) );
+            else
+                fprintf( pFile, "c%d %s\n", i - (Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk)), Abc_ObjName(pObj) );
+    }
+
+    // write the comment
+    fprintf( pFile, "c\n" );
+    if ( pNtk->pName && strlen(pNtk->pName) > 0 )
+        fprintf( pFile, ".model %s\n", pNtk->pName );
+    fprintf( pFile, "This file was produced by ABC on %s\n", Extra_TimeStamp() );
+    fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" );
+	fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG in the binary AIGER format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteAigerGz( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols )
+{
+    ProgressBar * pProgress;
+    gzFile pFile;
+    Abc_Obj_t * pObj, * pDriver, * pLatch;
+    int i, nNodes, Pos, nBufferSize, fExtended;
+    unsigned char * pBuffer;
+    unsigned uLit0, uLit1, uLit;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    // start the output stream
+    pFile = gzopen( pFileName, "wb" ); // if pFileName doesn't end in ".gz" then this acts as a passthrough to fopen
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Io_WriteAigerGz(): Cannot open the output file \"%s\".\n", pFileName );
+        return;
+    }
+
+    fExtended = Abc_NtkConstrNum(pNtk);
+
+    // set the node numbers to be used in the output file
+    nNodes = 0;
+    Io_ObjSetAigerNum( Abc_AigConst1(pNtk), nNodes++ );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        Io_ObjSetAigerNum( pObj, nNodes++ );
+    Abc_AigForEachAnd( pNtk, pObj, i )
+        Io_ObjSetAigerNum( pObj, nNodes++ );
+
+    // write the header "M I L O A" where M = I + L + A
+    gzprintf( pFile, "aig %u %u %u %u %u", 
+              Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) + Abc_NtkNodeNum(pNtk), 
+              Abc_NtkPiNum(pNtk),
+              Abc_NtkLatchNum(pNtk),
+              fExtended ? 0 : Abc_NtkPoNum(pNtk),
+              Abc_NtkNodeNum(pNtk) );
+    // write the extended header "B C J F"
+    if ( fExtended )
+        gzprintf( pFile, " %u %u", Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk), Abc_NtkConstrNum(pNtk) );
+    gzprintf( pFile, "\n" ); 
+
+    // if the driver node is a constant, we need to complement the literal below
+    // because, in the AIGER format, literal 0/1 is represented as number 0/1
+    // while, in ABC, constant 1 node has number 0 and so literal 0/1 will be 1/0
+
+    // write latch drivers
+    Abc_NtkInvertConstraints( pNtk );
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+        pObj = Abc_ObjFanin0(pLatch);
+        pDriver = Abc_ObjFanin0(pObj);
+        uLit = Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) );
+        if ( Abc_LatchIsInit0(pLatch) )
+            gzprintf( pFile, "%u\n", uLit );
+        else if ( Abc_LatchIsInit1(pLatch) )
+            gzprintf( pFile, "%u 1\n", uLit );
+        else
+        {
+            // Both None and DC are written as 'uninitialized' e.g. a free boolean value
+            assert( Abc_LatchIsInitNone(pLatch) || Abc_LatchIsInitDc(pLatch) );
+            gzprintf( pFile, "%u %u\n", uLit, Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanout0(pLatch)), 0 ) );
+        }
+    }
+    // write PO drivers
+    Abc_NtkForEachPo( pNtk, pObj, i )
+    {
+        pDriver = Abc_ObjFanin0(pObj);
+        gzprintf( pFile, "%u\n", Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) );
+    }
+    Abc_NtkInvertConstraints( pNtk );
+
+    // write the nodes into the buffer
+    Pos = 0;
+    nBufferSize = 6 * Abc_NtkNodeNum(pNtk) + 100; // skeptically assuming 3 chars per one AIG edge
+    pBuffer = ABC_ALLOC( unsigned char, nBufferSize );
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+    Abc_AigForEachAnd( pNtk, pObj, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        uLit  = Io_ObjMakeLit( Io_ObjAigerNum(pObj), 0 );
+        uLit0 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin0(pObj)), Abc_ObjFaninC0(pObj) );
+        uLit1 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin1(pObj)), Abc_ObjFaninC1(pObj) );
+        if ( uLit0 > uLit1 )
+        {
+            unsigned Temp = uLit0;
+            uLit0 = uLit1;
+            uLit1 = Temp;
+        }
+        assert( uLit1 < uLit );
+        Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit  - uLit1 );
+        Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 );
+        if ( Pos > nBufferSize - 10 )
+        {
+            printf( "Io_WriteAiger(): AIGER generation has failed because the allocated buffer is too small.\n" );
+	        gzclose( pFile );
+            return;
+        }
+    }
+    assert( Pos < nBufferSize );
+    Extra_ProgressBarStop( pProgress );
+
+    // write the buffer
+    gzwrite(pFile, pBuffer, Pos);
+    ABC_FREE( pBuffer );
+
+    // write the symbol table
+    if ( fWriteSymbols )
+    {
+        // write PIs
+        Abc_NtkForEachPi( pNtk, pObj, i )
+            gzprintf( pFile, "i%d %s\n", i, Abc_ObjName(pObj) );
+        // write latches
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+            gzprintf( pFile, "l%d %s\n", i, Abc_ObjName(Abc_ObjFanout0(pObj)) );
+        // write POs
+        Abc_NtkForEachPo( pNtk, pObj, i )
+            if ( !fExtended )
+                gzprintf( pFile, "o%d %s\n", i, Abc_ObjName(pObj) );
+            else if ( i < Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk) )
+                gzprintf( pFile, "b%d %s\n", i, Abc_ObjName(pObj) );
+            else
+                gzprintf( pFile, "c%d %s\n", i - (Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk)), Abc_ObjName(pObj) );
+    }
+
+    // write the comment
+    gzprintf( pFile, "c\n" );
+    if ( pNtk->pName && strlen(pNtk->pName) > 0 )
+        gzprintf( pFile, ".model %s\n", pNtk->pName );
+    gzprintf( pFile, "This file was produced by ABC on %s\n", Extra_TimeStamp() );
+    gzprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" );
+	gzclose( pFile );
+}
+
+ 
+/**Function*************************************************************
+
+  Synopsis    [Procedure to write data into BZ2 file.]
+
+  Description [Based on the vsnprintf() man page.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+typedef struct bz2file {
+  FILE   * f;
+  BZFILE * b;
+  char   * buf;
+  int      nBytes;
+  int      nBytesMax;
+} bz2file;
+
+int fprintfBz2Aig( bz2file * b, char * fmt, ... ) {
+    if (b->b) {
+        char * newBuf;
+        int bzError;
+        va_list ap;
+        while (1) {
+            va_start(ap,fmt);
+            b->nBytes = vsnprintf(b->buf,b->nBytesMax,fmt,ap);
+            va_end(ap);
+            if (b->nBytes > -1 && b->nBytes < b->nBytesMax)
+                break;
+            if (b->nBytes > -1)
+                b->nBytesMax = b->nBytes + 1;
+            else
+                b->nBytesMax *= 2;
+            if ((newBuf = ABC_REALLOC( char,b->buf,b->nBytesMax )) == NULL)
+                return -1;
+            else
+                b->buf = newBuf;
+        }
+        BZ2_bzWrite( &bzError, b->b, b->buf, b->nBytes );
+        if (bzError == BZ_IO_ERROR) {
+            fprintf( stdout, "Ioa_WriteBlif(): I/O error writing to compressed stream.\n" );
+            return -1;
+        }
+        return b->nBytes;
+    } else {
+        int n;
+        va_list ap;
+        va_start(ap,fmt);
+        n = vfprintf( b->f, fmt, ap);
+        va_end(ap);
+        return n;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG in the binary AIGER format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols, int fCompact, int fUnique )
+{
+    ProgressBar * pProgress;
+//    FILE * pFile;
+    Abc_Obj_t * pObj, * pDriver, * pLatch;
+    int i, nNodes, nBufferSize, bzError, Pos, fExtended;
+    unsigned char * pBuffer;
+    unsigned uLit0, uLit1, uLit;
+    bz2file b;
+
+    // define unique writing
+    if ( fUnique )
+    {
+        fWriteSymbols = 0;
+        fCompact = 0;
+    }
+
+    fExtended = Abc_NtkConstrNum(pNtk);
+
+    // check that the network is valid
+    assert( Abc_NtkIsStrash(pNtk) );
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        if ( !Abc_LatchIsInit0(pObj) )
+        {
+            if ( !fCompact )
+            {
+                fExtended = 1;
+                break;
+            }
+            fprintf( stdout, "Io_WriteAiger(): Cannot write AIGER format with non-0 latch init values. Run \"zero\".\n" );
+            return;
+        }
+
+    // write the GZ file
+    if (!strncmp(pFileName+strlen(pFileName)-3,".gz",3)) 
+    {
+        Io_WriteAigerGz( pNtk, pFileName, fWriteSymbols );
+        return;
+    }
+
+    memset(&b,0,sizeof(b));
+    b.nBytesMax = (1<<12);
+    b.buf = ABC_ALLOC( char,b.nBytesMax );
+
+    // start the output stream
+    b.f = fopen( pFileName, "wb" ); 
+    if ( b.f == NULL )
+    {
+        fprintf( stdout, "Ioa_WriteBlif(): Cannot open the output file \"%s\".\n", pFileName );
+        ABC_FREE(b.buf);
+        return;
+    }
+    if (!strncmp(pFileName+strlen(pFileName)-4,".bz2",4)) {
+        b.b = BZ2_bzWriteOpen( &bzError, b.f, 9, 0, 0 );
+        if ( bzError != BZ_OK ) {
+            BZ2_bzWriteClose( &bzError, b.b, 0, NULL, NULL );
+            fprintf( stdout, "Ioa_WriteBlif(): Cannot start compressed stream.\n" );
+            fclose( b.f );
+            ABC_FREE(b.buf);
+            return;
+        }
+    }
+
+    // set the node numbers to be used in the output file
+    nNodes = 0;
+    Io_ObjSetAigerNum( Abc_AigConst1(pNtk), nNodes++ );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        Io_ObjSetAigerNum( pObj, nNodes++ );
+    Abc_AigForEachAnd( pNtk, pObj, i )
+        Io_ObjSetAigerNum( pObj, nNodes++ );
+
+    // write the header "M I L O A" where M = I + L + A
+    fprintfBz2Aig( &b, "aig%s %u %u %u %u %u", 
+        fCompact? "2" : "",
+        Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) + Abc_NtkNodeNum(pNtk), 
+        Abc_NtkPiNum(pNtk),
+        Abc_NtkLatchNum(pNtk),
+        fExtended ? 0 : Abc_NtkPoNum(pNtk),
+        Abc_NtkNodeNum(pNtk) );
+    // write the extended header "B C J F"
+    if ( fExtended )
+        fprintfBz2Aig( &b, " %u %u", Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk), Abc_NtkConstrNum(pNtk) );
+    fprintfBz2Aig( &b, "\n" );
+
+    // if the driver node is a constant, we need to complement the literal below
+    // because, in the AIGER format, literal 0/1 is represented as number 0/1
+    // while, in ABC, constant 1 node has number 0 and so literal 0/1 will be 1/0
+
+    Abc_NtkInvertConstraints( pNtk );
+    if ( !fCompact ) 
+    {
+        // write latch drivers
+        Abc_NtkForEachLatch( pNtk, pLatch, i )
+        {
+            pObj = Abc_ObjFanin0(pLatch);
+            pDriver = Abc_ObjFanin0(pObj);
+            uLit = Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) );
+            if ( Abc_LatchIsInit0(pLatch) )
+                fprintfBz2Aig( &b, "%u\n", uLit );
+            else if ( Abc_LatchIsInit1(pLatch) )
+                fprintfBz2Aig( &b, "%u 1\n", uLit );
+            else
+            {
+                // Both None and DC are written as 'uninitialized' e.g. a free boolean value
+                assert( Abc_LatchIsInitNone(pLatch) || Abc_LatchIsInitDc(pLatch) );
+                fprintfBz2Aig( &b, "%u %u\n", uLit, Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanout0(pLatch)), 0 ) );
+            }
+        }
+        // write PO drivers
+        Abc_NtkForEachPo( pNtk, pObj, i )
+        {
+            pDriver = Abc_ObjFanin0(pObj);
+            fprintfBz2Aig( &b, "%u\n", Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) );
+        }
+    }
+    else
+    {
+        Vec_Int_t * vLits = Io_WriteAigerLiterals( pNtk );
+        Vec_Str_t * vBinary = Io_WriteEncodeLiterals( vLits );
+        if ( !b.b )
+            fwrite( Vec_StrArray(vBinary), 1, Vec_StrSize(vBinary), b.f );
+        else
+        {
+            BZ2_bzWrite( &bzError, b.b, Vec_StrArray(vBinary), Vec_StrSize(vBinary) );
+            if (bzError == BZ_IO_ERROR) {
+                fprintf( stdout, "Io_WriteAiger(): I/O error writing to compressed stream.\n" );
+                fclose( b.f );
+                ABC_FREE(b.buf);
+                Vec_StrFree( vBinary );
+                return;
+            }
+        }
+        Vec_StrFree( vBinary );
+        Vec_IntFree( vLits );
+    }
+    Abc_NtkInvertConstraints( pNtk );
+
+    // write the nodes into the buffer
+    Pos = 0;
+    nBufferSize = 6 * Abc_NtkNodeNum(pNtk) + 100; // skeptically assuming 3 chars per one AIG edge
+    pBuffer = ABC_ALLOC( unsigned char, nBufferSize );
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+    Abc_AigForEachAnd( pNtk, pObj, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        uLit  = Io_ObjMakeLit( Io_ObjAigerNum(pObj), 0 );
+        uLit0 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin0(pObj)), Abc_ObjFaninC0(pObj) );
+        uLit1 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin1(pObj)), Abc_ObjFaninC1(pObj) );
+        if ( uLit0 > uLit1 )
+        {
+            unsigned Temp = uLit0;
+            uLit0 = uLit1;
+            uLit1 = Temp;
+        }
+        assert( uLit1 < uLit );
+        Pos = Io_WriteAigerEncode( pBuffer, Pos, (unsigned)(uLit  - uLit1) );
+        Pos = Io_WriteAigerEncode( pBuffer, Pos, (unsigned)(uLit1 - uLit0) );
+        if ( Pos > nBufferSize - 10 )
+        {
+            printf( "Io_WriteAiger(): AIGER generation has failed because the allocated buffer is too small.\n" );
+            fclose( b.f );
+            ABC_FREE(b.buf);
+            Extra_ProgressBarStop( pProgress );
+            return;
+        }
+    }
+    assert( Pos < nBufferSize );
+    Extra_ProgressBarStop( pProgress );
+
+    // write the buffer
+    if ( !b.b )
+        fwrite( pBuffer, 1, Pos, b.f );
+    else
+    {
+        BZ2_bzWrite( &bzError, b.b, pBuffer, Pos );
+        if (bzError == BZ_IO_ERROR) {
+            fprintf( stdout, "Io_WriteAiger(): I/O error writing to compressed stream.\n" );
+            fclose( b.f );
+            ABC_FREE(b.buf);
+            return;
+        }
+    }
+    ABC_FREE( pBuffer );
+
+    // write the symbol table
+    if ( fWriteSymbols )
+    {
+        // write PIs
+        Abc_NtkForEachPi( pNtk, pObj, i )
+            fprintfBz2Aig( &b, "i%d %s\n", i, Abc_ObjName(pObj) );
+        // write latches
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+            fprintfBz2Aig( &b, "l%d %s\n", i, Abc_ObjName(Abc_ObjFanout0(pObj)) );
+        // write POs
+        Abc_NtkForEachPo( pNtk, pObj, i )
+            if ( !fExtended )
+                fprintfBz2Aig( &b, "o%d %s\n", i, Abc_ObjName(pObj) );
+            else if ( i < Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk) )
+                fprintfBz2Aig( &b, "b%d %s\n", i, Abc_ObjName(pObj) );
+            else
+                fprintfBz2Aig( &b, "c%d %s\n", i - (Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk)), Abc_ObjName(pObj) );
+    }
+
+    // write the comment
+    fprintfBz2Aig( &b, "c" );
+    if ( !fUnique )
+    {
+        if ( pNtk->pName && strlen(pNtk->pName) > 0 )
+            fprintfBz2Aig( &b, "\n%s%c", pNtk->pName, '\0' );
+        fprintfBz2Aig( &b, "\nThis file was written by ABC on %s\n", Extra_TimeStamp() );
+        fprintfBz2Aig( &b, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" );
+    }
+
+    // close the file
+    if (b.b) {
+        BZ2_bzWriteClose( &bzError, b.b, 0, NULL, NULL );
+        if (bzError == BZ_IO_ERROR) {
+            fprintf( stdout, "Io_WriteAiger(): I/O error closing compressed stream.\n" );
+            fclose( b.f );
+            ABC_FREE(b.buf);
+            return;
+        }
+    }
+    fclose( b.f );
+    ABC_FREE(b.buf);
+}
+
+ABC_NAMESPACE_IMPL_END
+
+#include "aig/gia/giaAig.h"
+#include "aig/saig/saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG in the binary AIGER format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteAigerCex( Abc_Cex_t * pCex, Abc_Ntk_t * pNtk, void * pG, char * pFileName )
+{
+    extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+    FILE * pFile;
+    Aig_Man_t * pAig;
+    Aig_Obj_t * pObj, * pObj2;
+    Gia_Man_t * pGia = (Gia_Man_t *)pG;
+    int k, f, b;
+    assert( pCex != NULL );
+
+    // derive AIG
+    if ( pNtk != NULL && 
+         Abc_NtkPiNum(pNtk)    == pCex->nPis && 
+         Abc_NtkLatchNum(pNtk) == pCex->nRegs )
+    {
+        pAig = Abc_NtkToDar( pNtk, 0, 1 );
+    }
+    else if ( pGia != NULL && 
+         Gia_ManPiNum(pGia)  == pCex->nPis && 
+         Gia_ManRegNum(pGia) == pCex->nRegs )
+    {
+        pAig = Gia_ManToAigSimple( pGia );
+    }
+    else
+    {
+        printf( "AIG parameters do not match those of the CEX.\n" );
+        return;
+    }
+
+    // create output file
+    pFile = fopen( pFileName, "wb" );
+    fprintf( pFile, "1\n" );
+    b = pCex->nRegs;
+    for ( k = 0; k < pCex->nRegs; k++ )
+        fprintf( pFile, "0" );
+    fprintf( pFile, " " );
+    Aig_ManCleanMarkA( pAig );
+    for ( f = 0; f <= pCex->iFrame; f++ )
+    {
+        for ( k = 0; k < pCex->nPis; k++ )
+        {
+            fprintf( pFile, "%d", Abc_InfoHasBit(pCex->pData, b) );
+            Aig_ManCi( pAig, k )->fMarkA = Abc_InfoHasBit(pCex->pData, b++);
+        }
+        fprintf( pFile, " " );
+        Aig_ManForEachNode( pAig, pObj, k )
+            pObj->fMarkA = (Aig_ObjFanin0(pObj)->fMarkA ^ Aig_ObjFaninC0(pObj)) &
+                           (Aig_ObjFanin1(pObj)->fMarkA ^ Aig_ObjFaninC1(pObj));
+        Aig_ManForEachCo( pAig, pObj, k )
+            pObj->fMarkA = (Aig_ObjFanin0(pObj)->fMarkA ^ Aig_ObjFaninC0(pObj));
+        Saig_ManForEachPo( pAig, pObj, k )
+            fprintf( pFile, "%d", pObj->fMarkA );
+        fprintf( pFile, " " );
+        Saig_ManForEachLi( pAig, pObj, k )
+            fprintf( pFile, "%d", pObj->fMarkA );
+        fprintf( pFile, "\n" );
+        if ( f == pCex->iFrame )
+            break;
+        Saig_ManForEachLi( pAig, pObj, k )
+            fprintf( pFile, "%d", pObj->fMarkA );
+        fprintf( pFile, " " );
+        Saig_ManForEachLiLo( pAig, pObj, pObj2, k )
+            pObj2->fMarkA = pObj->fMarkA;
+    }  
+    assert( b == pCex->nBits );
+    fclose( pFile );
+    Aig_ManCleanMarkA( pAig );
+    Aig_ManStop( pAig );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioWriteBaf.c b/abc-build/src/base/io/ioWriteBaf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioWriteBaf.c
@@ -0,0 +1,173 @@
+/**CFile****************************************************************
+
+  FileName    [ioWriteBaf.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to write AIG in the binary format.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioWriteBaf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+/*
+    Binary Aig Format
+
+    The motivation for this format is to have
+    - compact binary representation of large AIGs (~10x more compact than BLIF)
+    - consequently, fast reading/writing of large AIGs (~10x faster than BLIF)
+    - representation for all tech-ind info related to an AIG
+    - human-readable file header
+
+    The header:
+    (1) May contain several lines of human-readable comments.
+        Each comment line begins with symbol '#' and ends with symbol '\n'.
+    (2) Always contains the following data. 
+        - benchmark name
+        - number of primary inputs
+        - number of primary outputs
+        - number of latches
+        - number of AIG nodes (excluding the constant 1 node)
+        Each entry is followed by 0-byte (character '\0'):
+    (3) Next follow the names of the PIs, POs, and latches in this order. 
+        Each name is followed by 0-byte (character '\0').
+        Inside each set of names (PIs, POs, latches) there should be no
+        identical names but the PO names may coincide with PI/latch names.
+
+    The body:
+    (1) First part of the body contains binary information about the internal AIG nodes.
+        Each internal AIG node is represented using two edges (each edge is a 4-byte integer). 
+        Each integer is the fanin ID followed by 1-bit representation of the complemented attribute.
+        (For example, complemented edge to node 10 will be represented as 2*10 + 1 = 21.)
+        The IDs of the nodes are created as follows: Constant 1 node has ID=0. 
+        CIs (PIs and latch outputs) have 1-based IDs assigned in that order.
+        Each node in the array of the internal AIG nodes has the ID assigned in that order.
+        The constant 1 node is not written into the file.
+    (2) Second part of the body contains binary information about the edges connecting 
+        the COs (POs and latch inputs) to the internal AIG nodes.
+        Each edge is a 4-byte integer the same way as a node fanin.
+        The latch initial value (2 bits) is stored in this integer.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG in the binary format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteBaf( Abc_Ntk_t * pNtk, char * pFileName )
+{
+    ProgressBar * pProgress;
+    FILE * pFile;
+    Abc_Obj_t * pObj;
+    int i, nNodes, nAnds, nBufferSize;
+    unsigned * pBufferNode;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // start the output stream
+    pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Io_WriteBaf(): Cannot open the output file \"%s\".\n", pFileName );
+        return;
+    }
+
+    // write the comment
+    fprintf( pFile, "# BAF (Binary Aig Format) for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+
+    // write the network name
+    fprintf( pFile, "%s%c", pNtk->pName, 0 );
+    // write the number of PIs
+    fprintf( pFile, "%d%c", Abc_NtkPiNum(pNtk), 0 );
+    // write the number of POs
+    fprintf( pFile, "%d%c", Abc_NtkPoNum(pNtk), 0 );
+    // write the number of latches
+    fprintf( pFile, "%d%c", Abc_NtkLatchNum(pNtk), 0 );
+    // write the number of internal nodes
+    fprintf( pFile, "%d%c", Abc_NtkNodeNum(pNtk), 0 );
+
+    // write PIs
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 );
+    // write POs
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 );
+    // write latches
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+    {
+        fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 );
+        fprintf( pFile, "%s%c", Abc_ObjName(Abc_ObjFanin0(pObj)), 0 );
+        fprintf( pFile, "%s%c", Abc_ObjName(Abc_ObjFanout0(pObj)), 0 );
+    }
+
+    // set the node numbers to be used in the output file
+    Abc_NtkCleanCopy( pNtk );
+    nNodes = 1;
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)nNodes++;
+    Abc_AigForEachAnd( pNtk, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)nNodes++;
+
+    // write the nodes into the buffer
+    nAnds = 0;
+    nBufferSize = Abc_NtkNodeNum(pNtk) * 2 + Abc_NtkCoNum(pNtk);
+    pBufferNode = ABC_ALLOC( unsigned, nBufferSize );
+    pProgress = Extra_ProgressBarStart( stdout, nBufferSize );
+    Abc_AigForEachAnd( pNtk, pObj, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, nAnds, NULL );
+        pBufferNode[nAnds++] = (((int)(ABC_PTRINT_T)Abc_ObjFanin0(pObj)->pCopy) << 1) | (int)Abc_ObjFaninC0(pObj);
+        pBufferNode[nAnds++] = (((int)(ABC_PTRINT_T)Abc_ObjFanin1(pObj)->pCopy) << 1) | (int)Abc_ObjFaninC1(pObj);
+    }
+
+    // write the COs into the buffer
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, nAnds, NULL );
+        pBufferNode[nAnds] = (((int)(ABC_PTRINT_T)Abc_ObjFanin0(pObj)->pCopy) << 1) | (int)Abc_ObjFaninC0(pObj);
+        if ( Abc_ObjFanoutNum(pObj) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) )
+            pBufferNode[nAnds] = (pBufferNode[nAnds] << 2) | ((int)(ABC_PTRINT_T)Abc_ObjData(Abc_ObjFanout0(pObj)) & 3);
+        nAnds++;
+    }
+    Extra_ProgressBarStop( pProgress );
+    assert( nBufferSize == nAnds );
+
+    // write the buffer
+    fwrite( pBufferNode, 1, sizeof(int) * nBufferSize, pFile );
+	fclose( pFile );
+    ABC_FREE( pBufferNode );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioWriteBblif.c b/abc-build/src/base/io/ioWriteBblif.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioWriteBblif.c
@@ -0,0 +1,116 @@
+/**CFile****************************************************************
+
+  FileName    [ioWriteBblif.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to write AIG in the binary format.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioWriteBblif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+#include "misc/bbl/bblif.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+// For description of Binary BLIF format, refer to "abc/src/aig/bbl/bblif.h"
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Fnction*************************************************************
+
+  Synopsis    [Construct manager from the ABC network.]
+
+  Description [In the ABC network each object has a unique integer ID.
+  This ID is used when we construct objects of the BBLIF manager 
+  corresponding to each object of the ABC network. The objects can be
+  added to the manager in any order (although below they are added in the
+  topological order), but by the time fanin/fanout connections are created, 
+  corresponding objects are already constructed. In the end the checking
+  procedure is called.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bbl_Man_t * Bbl_ManFromAbc( Abc_Ntk_t * pNtk )
+{
+    Bbl_Man_t * p;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k;
+    assert( Abc_NtkIsSopLogic(pNtk) );
+    // start the data manager
+    p = Bbl_ManStart( Abc_NtkName(pNtk) );
+    // collect internal nodes to be added
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    // create combinational inputs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        Bbl_ManCreateObject( p, BBL_OBJ_CI, Abc_ObjId(pObj), 0, NULL );
+    // create internal nodes 
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        Bbl_ManCreateObject( p, BBL_OBJ_NODE, Abc_ObjId(pObj), Abc_ObjFaninNum(pObj), (char *)pObj->pData );
+    // create combinational outputs
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Bbl_ManCreateObject( p, BBL_OBJ_CO, Abc_ObjId(pObj), 1, NULL );
+    // create fanin/fanout connections for internal nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Bbl_ManAddFanin( p, Abc_ObjId(pObj), Abc_ObjId(pFanin) );
+    // create fanin/fanout connections for combinational outputs
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Bbl_ManAddFanin( p, Abc_ObjId(pObj), Abc_ObjId(pFanin) );
+    Vec_PtrFree( vNodes );
+    // sanity check
+    Bbl_ManCheck( p );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the AIG in the binary format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteBblif( Abc_Ntk_t * pNtk, char * pFileName )
+{
+    Bbl_Man_t * p;
+    p = Bbl_ManFromAbc( pNtk );
+//Bbl_ManPrintStats( p );
+//Bbl_ManDumpBlif( p, "test_bbl.blif" );
+    Bbl_ManDumpBinaryBlif( p, pFileName );
+    Bbl_ManStop( p );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioWriteBench.c b/abc-build/src/base/io/ioWriteBench.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioWriteBench.c
@@ -0,0 +1,340 @@
+/**CFile****************************************************************
+
+  FileName    [ioWriteBench.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to write the network in BENCH format.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioWriteBench.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Io_WriteBenchCheckNames( Abc_Ntk_t * pNtk );
+
+static int Io_WriteBenchOne( FILE * pFile, Abc_Ntk_t * pNtk );
+static int Io_WriteBenchOneNode( FILE * pFile, Abc_Obj_t * pNode );
+
+static int Io_WriteBenchLutOne( FILE * pFile, Abc_Ntk_t * pNtk );
+static int Io_WriteBenchLutOneNode( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vTruth );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the network in BENCH format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_WriteBench( Abc_Ntk_t * pNtk, const char * pFileName )
+{
+    Abc_Ntk_t * pExdc;
+    FILE * pFile;
+    assert( Abc_NtkIsSopNetlist(pNtk) );
+    if ( !Io_WriteBenchCheckNames(pNtk) )
+    {
+        fprintf( stdout, "Io_WriteBench(): Signal names in this benchmark contain parantheses making them impossible to reproduce in the BENCH format. Use \"short_names\".\n" );
+        return 0;
+    }
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Io_WriteBench(): Cannot open the output file.\n" );
+        return 0;
+    }
+    fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+    // write the network
+    Io_WriteBenchOne( pFile, pNtk );
+    // write EXDC network if it exists
+    pExdc = Abc_NtkExdc( pNtk );
+    if ( pExdc )
+        printf( "Io_WriteBench: EXDC is not written (warning).\n" );
+    // finalize the file
+    fclose( pFile );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the network in BENCH format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_WriteBenchOne( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    ProgressBar * pProgress;
+    Abc_Obj_t * pNode;
+    int i;
+
+    // write the PIs/POs/latches
+    Abc_NtkForEachPi( pNtk, pNode, i )
+        fprintf( pFile, "INPUT(%s)\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+    Abc_NtkForEachPo( pNtk, pNode, i )
+        fprintf( pFile, "OUTPUT(%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) );
+    Abc_NtkForEachLatch( pNtk, pNode, i )
+        fprintf( pFile, "%-11s = DFF(%s)\n", 
+            Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode))), Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) );
+
+    // write internal nodes
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        Io_WriteBenchOneNode( pFile, pNode );
+    }
+    Extra_ProgressBarStop( pProgress );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the network in BENCH format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_WriteBenchOneNode( FILE * pFile, Abc_Obj_t * pNode )
+{
+    int nFanins;
+
+    assert( Abc_ObjIsNode(pNode) );
+    nFanins = Abc_ObjFaninNum(pNode);
+    if ( nFanins == 0 )
+    {   // write the constant 1 node
+        assert( Abc_NodeIsConst1(pNode) );
+        fprintf( pFile, "%-11s",          Abc_ObjName(Abc_ObjFanout0(pNode)) );
+        fprintf( pFile, " = vdd\n" );
+    }
+    else if ( nFanins == 1 )
+    {   // write the interver/buffer
+        if ( Abc_NodeIsBuf(pNode) )
+        {
+            fprintf( pFile, "%-11s = BUFF(",  Abc_ObjName(Abc_ObjFanout0(pNode)) );
+            fprintf( pFile, "%s)\n",          Abc_ObjName(Abc_ObjFanin0(pNode)) );
+        }
+        else
+        {
+            fprintf( pFile, "%-11s = NOT(",   Abc_ObjName(Abc_ObjFanout0(pNode)) );
+            fprintf( pFile, "%s)\n",          Abc_ObjName(Abc_ObjFanin0(pNode)) );
+        }
+    }
+    else
+    {   // write the AND gate
+        fprintf( pFile, "%-11s",       Abc_ObjName(Abc_ObjFanout0(pNode)) );
+        fprintf( pFile, " = AND(%s, ", Abc_ObjName(Abc_ObjFanin0(pNode)) );
+        fprintf( pFile, "%s)\n",       Abc_ObjName(Abc_ObjFanin1(pNode)) );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the network in BENCH format with LUTs and DFFRSE.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_WriteBenchLut( Abc_Ntk_t * pNtk, char * pFileName )
+{
+    Abc_Ntk_t * pExdc;
+    FILE * pFile;
+    assert( Abc_NtkIsAigNetlist(pNtk) );
+    if ( !Io_WriteBenchCheckNames(pNtk) )
+    {
+        fprintf( stdout, "Io_WriteBenchLut(): Signal names in this benchmark contain parantheses making them impossible to reproduce in the BENCH format. Use \"short_names\".\n" );
+        return 0;
+    }
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Io_WriteBench(): Cannot open the output file.\n" );
+        return 0;
+    }
+    fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+    // write the network
+    Io_WriteBenchLutOne( pFile, pNtk );
+    // write EXDC network if it exists
+    pExdc = Abc_NtkExdc( pNtk );
+    if ( pExdc )
+        printf( "Io_WriteBench: EXDC is not written (warning).\n" );
+    // finalize the file
+    fclose( pFile );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the network in BENCH format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_WriteBenchLutOne( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    ProgressBar * pProgress;
+    Abc_Obj_t * pNode;
+    Vec_Int_t * vMemory;
+    int i;
+
+    // write the PIs/POs/latches
+    Abc_NtkForEachPi( pNtk, pNode, i )
+        fprintf( pFile, "INPUT(%s)\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+    Abc_NtkForEachPo( pNtk, pNode, i )
+        fprintf( pFile, "OUTPUT(%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) );
+    Abc_NtkForEachLatch( pNtk, pNode, i )
+        fprintf( pFile, "%-11s = DFFRSE( %s, gnd, gnd, gnd, gnd )\n", 
+            Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode))), Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) );
+//Abc_NtkLevel(pNtk);
+    // write internal nodes
+    vMemory = Vec_IntAlloc( 10000 );
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        Io_WriteBenchLutOneNode( pFile, pNode, vMemory );
+    }
+    Extra_ProgressBarStop( pProgress );
+    Vec_IntFree( vMemory );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the network in BENCH format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_WriteBenchLutOneNode( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vTruth )
+{
+    Abc_Obj_t * pFanin;
+    unsigned * pTruth;
+    int i, nFanins;
+    assert( Abc_ObjIsNode(pNode) );
+    nFanins = Abc_ObjFaninNum(pNode);
+    assert( nFanins <= 8 );
+    // compute the truth table
+    pTruth = Hop_ManConvertAigToTruth( (Hop_Man_t *)pNode->pNtk->pManFunc, Hop_Regular((Hop_Obj_t *)pNode->pData), nFanins, vTruth, 0 );
+    if ( Hop_IsComplement((Hop_Obj_t *)pNode->pData) )
+        Extra_TruthNot( pTruth, pTruth, nFanins );
+    // consider simple cases
+    if ( Extra_TruthIsConst0(pTruth, nFanins) )
+    {
+        fprintf( pFile, "%-11s = gnd\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+        return 1;
+    }
+    if ( Extra_TruthIsConst1(pTruth, nFanins) )
+    {
+        fprintf( pFile, "%-11s = vdd\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+        return 1;
+    }
+    if ( nFanins == 1 )
+    {
+        fprintf( pFile, "%-11s = LUT 0x%d ( %s )\n",  
+            Abc_ObjName(Abc_ObjFanout0(pNode)), 
+            Abc_NodeIsBuf(pNode)? 2 : 1,
+            Abc_ObjName(Abc_ObjFanin0(pNode)) );
+        return 1;
+    }
+    // write it in the hexadecimal form
+    fprintf( pFile, "%-11s = LUT 0x",  Abc_ObjName(Abc_ObjFanout0(pNode)) );
+    Extra_PrintHexadecimal( pFile, pTruth, nFanins );
+/*
+    {
+extern void Kit_DsdTest( unsigned * pTruth, int nVars );
+Abc_ObjForEachFanin( pNode, pFanin, i )
+printf( "%c%d ", 'a'+i, Abc_ObjFanin0(pFanin)->Level );
+printf( "\n" );
+Kit_DsdTest( pTruth, nFanins );
+    }
+    if ( pNode->Id % 1000 == 0 )
+    {
+        int x = 0;
+    }
+*/
+    // write the fanins
+    fprintf( pFile, " (" );
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        fprintf( pFile, " %s%s", Abc_ObjName(pFanin), ((i==nFanins-1)? "" : ",") );
+    fprintf( pFile, " )\n" );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the names cannot be written into the bench file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_WriteBenchCheckNames( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    char * pName;
+    int i;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        for ( pName = Nm_ManFindNameById(pNtk->pManName, i); pName && *pName; pName++ )
+            if ( *pName == '(' || *pName == ')' )
+                return 0;
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioWriteBlif.c b/abc-build/src/base/io/ioWriteBlif.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioWriteBlif.c
@@ -0,0 +1,1403 @@
+/**CFile****************************************************************
+
+  FileName    [ioWriteBlif.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to write BLIF files.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioWriteBlif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+#include "base/main/main.h"
+#include "map/mio/mio.h"
+#include "bool/kit/kit.h"
+#include "map/if/if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Io_NtkWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches, int fBb2Wb, int fSeq );
+static void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches, int fBb2Wb, int fSeq );
+static void Io_NtkWritePis( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches );
+static void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches );
+static void Io_NtkWriteSubckt( FILE * pFile, Abc_Obj_t * pNode );
+static void Io_NtkWriteAsserts( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteNodeFanins( FILE * pFile, Abc_Obj_t * pNode );
+static int  Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length );
+static void Io_NtkWriteLatch( FILE * pFile, Abc_Obj_t * pLatch );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Write the network into a BLIF file with the given name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches )
+{
+    Abc_Ntk_t * pNtkTemp;
+    // derive the netlist
+    pNtkTemp = Abc_NtkToNetlist(pNtk);
+    if ( pNtkTemp == NULL )
+    {
+        fprintf( stdout, "Writing BLIF has failed.\n" );
+        return;
+    }
+    Io_WriteBlif( pNtkTemp, FileName, fWriteLatches, 0, 0 );
+    Abc_NtkDelete( pNtkTemp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the network into a BLIF file with the given name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteBlif( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches, int fBb2Wb, int fSeq )
+{
+    FILE * pFile;
+    Abc_Ntk_t * pNtkTemp;
+    int i;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    // start writing the file
+    pFile = fopen( FileName, "w" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Io_WriteBlif(): Cannot open the output file.\n" );
+        return;
+    }
+    fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+    // write the master network
+    Io_NtkWrite( pFile, pNtk, fWriteLatches, fBb2Wb, fSeq );
+    // make sure there is no logic hierarchy
+//    assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+    // write the hierarchy if present
+    if ( Abc_NtkBlackboxNum(pNtk) > 0 || Abc_NtkWhiteboxNum(pNtk) > 0 )
+    {
+        Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pNtkTemp, i )
+        {
+            if ( pNtkTemp == pNtk )
+                continue;
+            fprintf( pFile, "\n\n" );
+            Io_NtkWrite( pFile, pNtkTemp, fWriteLatches, fBb2Wb, fSeq );
+        }
+    }
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the network into a BLIF file with the given name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches, int fBb2Wb, int fSeq )
+{
+    Abc_Ntk_t * pExdc;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    // write the model name
+    fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) );
+    // write the network
+    Io_NtkWriteOne( pFile, pNtk, fWriteLatches, fBb2Wb, fSeq );
+    // write EXDC network if it exists
+    pExdc = Abc_NtkExdc( pNtk );
+    if ( pExdc )
+    {
+        fprintf( pFile, "\n" );
+        fprintf( pFile, ".exdc\n" );
+        Io_NtkWriteOne( pFile, pExdc, fWriteLatches, fBb2Wb, fSeq );
+    }
+    // finalize the file
+    fprintf( pFile, ".end\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write one network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+void Io_NtkWriteConvertedBox( FILE * pFile, Abc_Ntk_t * pNtk, int fSeq )
+{
+    Abc_Obj_t * pObj;
+    int i, v;
+    if ( fSeq )
+    {
+        fprintf( pFile, ".attrib white box seq\n" );
+    }
+    else
+    {
+        fprintf( pFile, ".attrib white box comb\n" );
+        fprintf( pFile, ".delay 1\n" );
+    }
+    Abc_NtkForEachPo( pNtk, pObj, i )
+    { 
+        // write the .names line
+        fprintf( pFile, ".names" );
+        Io_NtkWritePis( pFile, pNtk, 1 );
+        if ( fSeq )
+            fprintf( pFile, " %s_in\n", Abc_ObjName(Abc_ObjFanin0(pObj)) );
+        else
+            fprintf( pFile, " %s\n", Abc_ObjName(Abc_ObjFanin0(pObj)) );
+        for ( v = 0; v < Abc_NtkPiNum(pNtk); v++ )
+            fprintf( pFile, "1" );
+        fprintf( pFile, " 1\n" );
+        if ( fSeq )
+            fprintf( pFile, ".latch %s_in %s 1\n", Abc_ObjName(Abc_ObjFanin0(pObj)), Abc_ObjName(Abc_ObjFanin0(pObj)) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write one network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches, int fBb2Wb, int fSeq )
+{
+    ProgressBar * pProgress;
+    Abc_Obj_t * pNode, * pLatch;
+    int i, Length;
+
+    // write the PIs
+    fprintf( pFile, ".inputs" );
+    Io_NtkWritePis( pFile, pNtk, fWriteLatches );
+    fprintf( pFile, "\n" );
+
+    // write the POs
+    fprintf( pFile, ".outputs" );
+    Io_NtkWritePos( pFile, pNtk, fWriteLatches );
+    fprintf( pFile, "\n" );
+
+    // write the blackbox
+    if ( Abc_NtkHasBlackbox( pNtk ) )
+    {
+        if ( fBb2Wb )
+            Io_NtkWriteConvertedBox( pFile, pNtk, fSeq );
+        else
+            fprintf( pFile, ".blackbox\n" );
+        return;
+    }
+
+    // write the timing info
+    Io_WriteTimingInfo( pFile, pNtk );
+
+    // write the latches
+    if ( fWriteLatches && !Abc_NtkIsComb(pNtk) )
+    {
+        fprintf( pFile, "\n" );
+        Abc_NtkForEachLatch( pNtk, pLatch, i )
+            Io_NtkWriteLatch( pFile, pLatch );
+        fprintf( pFile, "\n" );
+    }
+
+    // write the subcircuits
+//    assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+    if ( Abc_NtkBlackboxNum(pNtk) > 0 || Abc_NtkWhiteboxNum(pNtk) > 0 )
+    {
+        fprintf( pFile, "\n" );
+        Abc_NtkForEachBlackbox( pNtk, pNode, i )
+            Io_NtkWriteSubckt( pFile, pNode );
+        fprintf( pFile, "\n" );
+        Abc_NtkForEachWhitebox( pNtk, pNode, i )
+            Io_NtkWriteSubckt( pFile, pNode );
+        fprintf( pFile, "\n" );
+    }
+
+    // write each internal node
+    Length = Abc_NtkHasMapping(pNtk)? Mio_LibraryReadGateNameMax((Mio_Library_t *)pNtk->pManFunc) : 0;
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        if ( Io_NtkWriteNode( pFile, pNode, Length ) ) // skip the next node
+            i++;
+    }
+    Extra_ProgressBarStop( pProgress );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the primary input list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWritePis( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches )
+{
+    Abc_Obj_t * pTerm, * pNet;
+    int LineLength;
+    int AddedLength;
+    int NameCounter;
+    int i;
+
+    LineLength  = 7;
+    NameCounter = 0;
+
+    if ( fWriteLatches )
+    {
+        Abc_NtkForEachPi( pNtk, pTerm, i )
+        {
+            pNet = Abc_ObjFanout0(pTerm);
+            // get the line length after this name is written
+            AddedLength = strlen(Abc_ObjName(pNet)) + 1;
+            if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+            { // write the line extender
+                fprintf( pFile, " \\\n" );
+                // reset the line length
+                LineLength  = 0;
+                NameCounter = 0;
+            }
+            fprintf( pFile, " %s", Abc_ObjName(pNet) );
+            LineLength += AddedLength;
+            NameCounter++;
+        }
+    }
+    else
+    {
+        Abc_NtkForEachCi( pNtk, pTerm, i )
+        {
+            pNet = Abc_ObjFanout0(pTerm);
+            // get the line length after this name is written
+            AddedLength = strlen(Abc_ObjName(pNet)) + 1;
+            if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+            { // write the line extender
+                fprintf( pFile, " \\\n" );
+                // reset the line length
+                LineLength  = 0;
+                NameCounter = 0;
+            }
+            fprintf( pFile, " %s", Abc_ObjName(pNet) );
+            LineLength += AddedLength;
+            NameCounter++;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the primary input list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches )
+{
+    Abc_Obj_t * pTerm, * pNet;
+    int LineLength;
+    int AddedLength;
+    int NameCounter;
+    int i;
+
+    LineLength  = 8;
+    NameCounter = 0;
+
+    if ( fWriteLatches )
+    {
+        Abc_NtkForEachPo( pNtk, pTerm, i )
+        {
+            pNet = Abc_ObjFanin0(pTerm);
+            // get the line length after this name is written
+            AddedLength = strlen(Abc_ObjName(pNet)) + 1;
+            if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+            { // write the line extender
+                fprintf( pFile, " \\\n" );
+                // reset the line length
+                LineLength  = 0;
+                NameCounter = 0;
+            }
+            fprintf( pFile, " %s", Abc_ObjName(pNet) );
+            LineLength += AddedLength;
+            NameCounter++;
+        }
+    }
+    else
+    {
+        Abc_NtkForEachCo( pNtk, pTerm, i )
+        {
+            pNet = Abc_ObjFanin0(pTerm);
+            // get the line length after this name is written
+            AddedLength = strlen(Abc_ObjName(pNet)) + 1;
+            if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+            { // write the line extender
+                fprintf( pFile, " \\\n" );
+                // reset the line length
+                LineLength  = 0;
+                NameCounter = 0;
+            }
+            fprintf( pFile, " %s", Abc_ObjName(pNet) );
+            LineLength += AddedLength;
+            NameCounter++;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the latch into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteSubckt( FILE * pFile, Abc_Obj_t * pNode )
+{
+    Abc_Ntk_t * pModel = (Abc_Ntk_t *)pNode->pData;
+    Abc_Obj_t * pTerm;
+    int i;
+    // write the subcircuit
+//    fprintf( pFile, ".subckt %s %s", Abc_NtkName(pModel), Abc_ObjName(pNode) );
+    fprintf( pFile, ".subckt %s", Abc_NtkName(pModel) );
+    // write pairs of the formal=actual names
+    Abc_NtkForEachPi( pModel, pTerm, i )
+    {
+        fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pTerm)) );
+        pTerm = Abc_ObjFanin( pNode, i );
+        fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanin0(pTerm)) );
+    }
+    Abc_NtkForEachPo( pModel, pTerm, i )
+    {
+        fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pTerm)) );
+        pTerm = Abc_ObjFanout( pNode, i );
+        fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanout0(pTerm)) );
+    }
+    fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the latch into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteLatch( FILE * pFile, Abc_Obj_t * pLatch )
+{
+    Abc_Obj_t * pNetLi, * pNetLo;
+    int Reset;
+    pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) );
+    pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) );
+    Reset  = (int)(ABC_PTRUINT_T)Abc_ObjData( pLatch );
+    // write the latch line
+    fprintf( pFile, ".latch" );
+    fprintf( pFile, " %10s",    Abc_ObjName(pNetLi) );
+    fprintf( pFile, " %10s",    Abc_ObjName(pNetLo) );
+    fprintf( pFile, "  %d\n",   Reset-1 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the primary input list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteNodeFanins( FILE * pFile, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pNet;
+    int LineLength;
+    int AddedLength;
+    int NameCounter;
+    char * pName;
+    int i;
+
+    LineLength  = 6;
+    NameCounter = 0;
+    Abc_ObjForEachFanin( pNode, pNet, i )
+    {
+        // get the fanin name
+        pName = Abc_ObjName(pNet);
+        // get the line length after the fanin name is written
+        AddedLength = strlen(pName) + 1;
+        if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+        { // write the line extender
+            fprintf( pFile, " \\\n" );
+            // reset the line length
+            LineLength  = 0;
+            NameCounter = 0;
+        }
+        fprintf( pFile, " %s", pName );
+        LineLength += AddedLength;
+        NameCounter++;
+    }
+
+    // get the output name
+    pName = Abc_ObjName(Abc_ObjFanout0(pNode));
+    // get the line length after the output name is written
+    AddedLength = strlen(pName) + 1;
+    if ( NameCounter && LineLength + AddedLength > 75 )
+    { // write the line extender
+        fprintf( pFile, " \\\n" );
+        // reset the line length
+        LineLength  = 0;
+        NameCounter = 0;
+    }
+    fprintf( pFile, " %s", pName );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the primary input list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteSubcktFanins( FILE * pFile, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pNet;
+    int LineLength;
+    int AddedLength;
+    int NameCounter;
+    char * pName;
+    int i;
+
+    LineLength  = 6;
+    NameCounter = 0;
+
+    // get the output name
+    pName = Abc_ObjName(Abc_ObjFanout0(pNode));
+    // get the line length after the output name is written
+    AddedLength = strlen(pName) + 1;
+    fprintf( pFile, " m%d", Abc_ObjId(pNode) );
+
+    // get the input names
+    Abc_ObjForEachFanin( pNode, pNet, i )
+    {
+        // get the fanin name
+        pName = Abc_ObjName(pNet);
+        // get the line length after the fanin name is written
+        AddedLength = strlen(pName) + 3;
+        if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+        { // write the line extender
+            fprintf( pFile, " \\\n" );
+            // reset the line length
+            LineLength  = 0;
+            NameCounter = 0;
+        }
+        fprintf( pFile, " %c=%s", 'a'+i, pName );
+        LineLength += AddedLength;
+        NameCounter++;
+    }
+
+    // get the output name
+    pName = Abc_ObjName(Abc_ObjFanout0(pNode));
+    // get the line length after the output name is written
+    AddedLength = strlen(pName) + 3;
+    if ( NameCounter && LineLength + AddedLength > 75 )
+    { // write the line extender
+        fprintf( pFile, " \\\n" );
+        // reset the line length
+        LineLength  = 0;
+        NameCounter = 0;
+    }
+    fprintf( pFile, " %c=%s", 'o', pName );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the primary input list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length )
+{
+    static int fReport = 0;
+    Mio_Gate_t * pGate = (Mio_Gate_t *)pNode->pData;
+    Mio_Pin_t * pGatePin;
+    Abc_Obj_t * pNode2;
+    int i;
+    fprintf( pFile, " %-*s ", Length, Mio_GateReadName(pGate) );
+    for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ )
+        fprintf( pFile, "%s=%s ", Mio_PinReadName(pGatePin), Abc_ObjName( Abc_ObjFanin(pNode,i) ) );
+    assert ( i == Abc_ObjFaninNum(pNode) );
+    fprintf( pFile, "%s=%s", Mio_GateReadOutName(pGate), Abc_ObjName( Abc_ObjFanout0(pNode) ) );
+    if ( Mio_GateReadTwin(pGate) == NULL )
+        return 0;
+    pNode2 = Abc_NtkFetchTwinNode( pNode );
+    if ( pNode2 == NULL )
+    {
+        if ( !fReport )
+            fReport = 1, printf( "Warning: Missing second output of gate(s) \"%s\".\n", Mio_GateReadName(pGate) );
+        return 0;
+    }
+    fprintf( pFile, " %s=%s", Mio_GateReadOutName((Mio_Gate_t *)pNode2->pData), Abc_ObjName( Abc_ObjFanout0(pNode2) ) );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the node into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length )
+{
+    int RetValue = 0;
+    if ( Abc_NtkHasMapping(pNode->pNtk) )
+    {
+        // write the .gate line
+        fprintf( pFile, ".gate" );
+        RetValue = Io_NtkWriteNodeGate( pFile, pNode, Length );
+        fprintf( pFile, "\n" );
+    }
+    else
+    {
+        // write the .names line
+        fprintf( pFile, ".names" );
+        Io_NtkWriteNodeFanins( pFile, pNode );
+        fprintf( pFile, "\n" );
+        // write the cubes
+        fprintf( pFile, "%s", (char*)Abc_ObjData(pNode) );
+    }
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the node into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_NtkWriteNodeSubckt( FILE * pFile, Abc_Obj_t * pNode, int Length )
+{
+    int RetValue = 0;
+    fprintf( pFile, ".subckt" );
+    Io_NtkWriteSubcktFanins( pFile, pNode );
+    fprintf( pFile, "\n" );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the timing info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pNode;
+    Abc_Time_t * pTime, * pTimeDef;
+    int i;
+
+    if ( pNtk->pManTime == NULL )
+        return;
+
+    fprintf( pFile, "\n" );
+
+    if ( pNtk->AndGateDelay != 0.0 )
+        fprintf( pFile, ".and_gate_delay %g\n", pNtk->AndGateDelay );
+
+    pTimeDef = Abc_NtkReadDefaultArrival( pNtk );
+    if ( pTimeDef->Rise != 0.0 || pTimeDef->Fall != 0.0 )
+        fprintf( pFile, ".default_input_arrival %g %g\n", pTimeDef->Rise, pTimeDef->Fall );
+    Abc_NtkForEachPi( pNtk, pNode, i )
+    {
+        pTime = Abc_NodeReadArrival(pNode);
+        if ( pTime->Rise == pTimeDef->Rise && pTime->Fall == pTimeDef->Fall )
+            continue;
+        fprintf( pFile, ".input_arrival %s %g %g\n", Abc_ObjName(Abc_ObjFanout0(pNode)), pTime->Rise, pTime->Fall );
+    }
+
+    pTimeDef = Abc_NtkReadDefaultRequired( pNtk );
+    if ( pTimeDef->Rise != ABC_INFINITY || pTimeDef->Fall != ABC_INFINITY )
+        fprintf( pFile, ".default_output_required %g %g\n", pTimeDef->Rise, pTimeDef->Fall );
+    Abc_NtkForEachPo( pNtk, pNode, i )
+    {
+        pTime = Abc_NodeReadRequired(pNode);
+        if ( pTime->Rise == pTimeDef->Rise && pTime->Fall == pTimeDef->Fall )
+            continue;
+        fprintf( pFile, ".output_required %s %g %g\n", Abc_ObjName(Abc_ObjFanin0(pNode)), pTime->Rise, pTime->Fall );
+    }
+
+    fprintf( pFile, "\n" );
+
+    pTimeDef = Abc_NtkReadDefaultInputDrive( pNtk );
+    if ( pTimeDef->Rise != 0.0 || pTimeDef->Fall != 0.0 )
+        fprintf( pFile, ".default_input_drive %g %g\n", pTimeDef->Rise, pTimeDef->Fall );
+    if ( Abc_NodeReadInputDrive( pNtk, 0 ) )
+        Abc_NtkForEachPi( pNtk, pNode, i )
+        {
+            pTime = Abc_NodeReadInputDrive( pNtk, i );
+            if ( pTime->Rise == pTimeDef->Rise && pTime->Fall == pTimeDef->Fall )
+                continue;
+            fprintf( pFile, ".input_drive %s %g %g\n", Abc_ObjName(Abc_ObjFanout0(pNode)), pTime->Rise, pTime->Fall );
+        }
+
+    pTimeDef = Abc_NtkReadDefaultOutputLoad( pNtk );
+    if ( pTimeDef->Rise != 0.0 || pTimeDef->Fall != 0.0 )
+        fprintf( pFile, ".default_output_load %g %g\n", pTimeDef->Rise, pTimeDef->Fall );
+    if ( Abc_NodeReadOutputLoad( pNtk, 0 ) )
+        Abc_NtkForEachPo( pNtk, pNode, i )
+        {
+            pTime = Abc_NodeReadOutputLoad( pNtk, i );
+            if ( pTime->Rise == pTimeDef->Rise && pTime->Fall == pTimeDef->Fall )
+                continue;
+            fprintf( pFile, ".output_load %s %g %g\n", Abc_ObjName(Abc_ObjFanin0(pNode)), pTime->Rise, pTime->Fall );
+        }
+
+    fprintf( pFile, "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkConvertBb2Wb( char * pFileNameIn, char * pFileNameOut, int fSeq, int fVerbose )
+{
+    FILE * pFile;
+    Abc_Ntk_t * pNetlist;
+    // check the files
+    pFile = fopen( pFileNameIn, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Input file \"%s\" cannot be opened.\n", pFileNameIn );
+        return;
+    }
+    fclose( pFile );
+    // check the files
+    pFile = fopen( pFileNameOut, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Output file \"%s\" cannot be opened.\n", pFileNameOut );
+        return;
+    }
+    fclose( pFile );
+    // derive AIG for signal correspondence
+    pNetlist = Io_ReadNetlist( pFileNameIn, Io_ReadFileType(pFileNameIn), 1 );
+    if ( pNetlist == NULL )
+    {
+        printf( "Reading input file \"%s\" has failed.\n", pFileNameIn );
+        return;
+    }
+    Io_WriteBlif( pNetlist, pFileNameOut, 1, 1, fSeq );
+    Abc_NtkDelete( pNetlist );
+}
+
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms truth table into an SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Io_NtkDeriveSop( Mem_Flex_t * pMem, word uTruth, int nVars, Vec_Int_t * vCover )
+{
+    char * pSop;
+    int RetValue = Kit_TruthIsop( (unsigned *)&uTruth, nVars, vCover, 1 );
+    assert( RetValue == 0 || RetValue == 1 );
+    // check the case of constant cover
+    if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) )
+    {
+        char * pStr0 = " 0\n", * pStr1 = " 1\n";
+        assert( RetValue == 0 );
+        return Vec_IntSize(vCover) == 0 ? pStr0 : pStr1;
+    }
+    // derive the AIG for that tree
+    pSop = Abc_SopCreateFromIsop( pMem, nVars, vCover );
+    if ( RetValue )
+        Abc_SopComplement( pSop );
+    return pSop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the node into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteNodeInt( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vCover )
+{
+    Abc_Obj_t * pNet;
+    int i, nVars = Abc_ObjFaninNum(pNode);
+    if ( nVars > 7 )
+    {
+        printf( "Node \"%s\" has more than 7 inputs. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+        return;
+    }
+
+    fprintf( pFile, "\n" );
+    if ( nVars <= 4 )
+    {
+        // write the .names line
+        fprintf( pFile, ".names" );
+        Abc_ObjForEachFanin( pNode, pNet, i )
+            fprintf( pFile, " %s", Abc_ObjName(pNet) );
+        // get the output name
+        fprintf( pFile, " %s\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+        // write the cubes
+        fprintf( pFile, "%s", (char*)Abc_ObjData(pNode) );
+    }
+    else
+    {
+        extern int  If_Dec6PickBestMux( word t, word Cofs[2] );
+        extern int  If_Dec7PickBestMux( word t[2], word c0r[2], word c1r[2] );
+        extern word If_Dec6MinimumBase( word uTruth, int * pSupp, int nVarsAll, int * pnVars );
+        extern void If_Dec7MinimumBase( word uTruth[2], int * pSupp, int nVarsAll, int * pnVars );
+        extern word If_Dec6Perform( word t, int fDerive );
+        extern word If_Dec7Perform( word t[2], int fDerive );
+
+        char * pSop;
+        word z, uTruth6 = 0, uTruth7[2], Cofs6[2], Cofs7[2][2];
+        int c, iVar, nVarsMin[2], pVars[2][10];
+
+        // collect variables
+        Abc_ObjForEachFanin( pNode, pNet, i )
+            pVars[0][i] = pVars[1][i] = i;
+
+        // derive truth table
+        if ( nVars == 7 )
+        {
+            Abc_SopToTruth7( (char*)Abc_ObjData(pNode), nVars, uTruth7 );
+            iVar = If_Dec7PickBestMux( uTruth7, Cofs7[0], Cofs7[1] );
+        }
+        else
+        {
+            uTruth6 = Abc_SopToTruth( (char*)Abc_ObjData(pNode), nVars );
+            iVar = If_Dec6PickBestMux( uTruth6, Cofs6 );
+        }
+
+        // perform MUX decomposition
+        if ( iVar >= 0 )
+        {
+            if ( nVars == 7 )
+            {
+                If_Dec7MinimumBase( Cofs7[0], pVars[0], nVars, &nVarsMin[0] );
+                If_Dec7MinimumBase( Cofs7[1], pVars[1], nVars, &nVarsMin[1] );
+            }
+            else
+            {
+                Cofs6[0] = If_Dec6MinimumBase( Cofs6[0], pVars[0], nVars, &nVarsMin[0] );
+                Cofs6[1] = If_Dec6MinimumBase( Cofs6[1], pVars[1], nVars, &nVarsMin[1] );
+            }
+            assert( nVarsMin[0] < 5 );
+            assert( nVarsMin[1] < 5 );
+            // write MUX
+            fprintf( pFile, ".names" );
+            fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,iVar)) );
+            fprintf( pFile, " %s_cascade0", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+            fprintf( pFile, " %s_cascade1", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+            fprintf( pFile, " %s\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+            fprintf( pFile, "1-1 1\n01- 1\n" );
+            // write cofactors
+            for ( c = 0; c < 2; c++ )
+            {
+                pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, 
+                    (word)(nVars == 7 ? Cofs7[c][0] : Cofs6[c]), nVarsMin[c], vCover );
+                fprintf( pFile, ".names" );
+                for ( i = 0; i < nVarsMin[c]; i++ )
+                    fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,pVars[c][i])) );
+                fprintf( pFile, " %s_cascade%d\n", Abc_ObjName(Abc_ObjFanout0(pNode)), c );
+                fprintf( pFile, "%s", pSop );
+            }
+            return;
+        }
+        assert( nVars == 6 || nVars == 7 );
+
+        // try cascade decomposition
+        if ( nVars == 7 )
+        {
+            z = If_Dec7Perform( uTruth7, 1 );
+            //If_Dec7Verify( uTruth7, z );
+        }
+        else
+        {
+            z = If_Dec6Perform( uTruth6, 1 );
+            //If_Dec6Verify( uTruth6, z );
+        }
+        if ( z == 0 )
+        {
+            printf( "Node \"%s\" is not decomposable. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+            return;
+        }
+
+        // derive nodes
+        for ( c = 1; c >= 0; c-- )
+        {
+            // collect fanins
+            uTruth7[c]  = ((c ? z >> 32 : z) & 0xffff);
+            uTruth7[c] |= (uTruth7[c] << 16);
+            uTruth7[c] |= (uTruth7[c] << 32);
+            for ( i = 0; i < 4; i++ )
+                pVars[c][i] = (z >> (c*32+16+4*i)) & 7;
+
+            // minimize truth table
+            Cofs6[c] = If_Dec6MinimumBase( uTruth7[c], pVars[c], 4, &nVarsMin[c] );
+
+            // write the nodes
+            fprintf( pFile, ".names" );
+            for ( i = 0; i < nVarsMin[c]; i++ )
+                if ( pVars[c][i] == 7 )
+                    fprintf( pFile, " %s_cascade", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+                else
+                    fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,pVars[c][i])) );
+                fprintf( pFile, " %s%s\n", Abc_ObjName(Abc_ObjFanout0(pNode)), c? "" : "_cascade" );
+
+            // write SOP
+            pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, 
+                (word)Cofs6[c], nVarsMin[c], vCover );
+            fprintf( pFile, "%s", pSop );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the node into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteNodeIntStruct( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vCover, char * pStr )
+{
+    Abc_Obj_t * pNet;
+    int nLeaves = Abc_ObjFaninNum(pNode);
+    int i, nLutLeaf, nLutLeaf2, nLutRoot, Length;
+
+    // quit if parameters are wrong
+    Length = strlen(pStr);
+    if ( Length != 2 && Length != 3 )
+    {
+        printf( "Wrong LUT struct (%s)\n", pStr );
+        return;
+    }
+    for ( i = 0; i < Length; i++ )
+        if ( pStr[i] - '0' < 3 || pStr[i] - '0' > 6 )
+        {
+            printf( "The LUT size (%d) should belong to {3,4,5,6}.\n", pStr[i] - '0' );
+            return;
+        }
+
+    nLutLeaf  =                   pStr[0] - '0';
+    nLutLeaf2 = ( Length == 3 ) ? pStr[1] - '0' : 0;
+    nLutRoot  =                   pStr[Length-1] - '0';
+    if ( nLeaves > nLutLeaf - 1 + (nLutLeaf2 ? nLutLeaf2 - 1 : 0) + nLutRoot )
+    {
+        printf( "The node size (%d) is too large for the LUT structure %s.\n", nLeaves, pStr );
+        return;
+    }
+
+    // consider easy case
+    fprintf( pFile, "\n" );
+    if ( nLeaves <= Abc_MaxInt( nLutLeaf2, Abc_MaxInt(nLutLeaf, nLutRoot) ) )
+    {
+        // write the .names line
+        fprintf( pFile, ".names" );
+        Abc_ObjForEachFanin( pNode, pNet, i )
+            fprintf( pFile, " %s", Abc_ObjName(pNet) );
+        // get the output name
+        fprintf( pFile, " %s\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+        // write the cubes
+        fprintf( pFile, "%s", (char*)Abc_ObjData(pNode) );
+        return;
+    }
+    else
+    {
+        extern int If_CluMinimumBase( word * t, int * pSupp, int nVarsAll, int * pnVars );
+
+        static word TruthStore[16][1<<10] = {{0}}, * pTruths[16];
+        word pCube[1<<10], pRes[1<<10], Func0, Func1, Func2;
+        char pLut0[32], pLut1[32], pLut2[32] = {0}, * pSop;
+//        int nVarsMin[3], pVars[3][20];
+
+        if ( TruthStore[0][0] == 0 )
+        {
+            static word Truth6[6] = {
+                ABC_CONST(0xAAAAAAAAAAAAAAAA),
+                ABC_CONST(0xCCCCCCCCCCCCCCCC),
+                ABC_CONST(0xF0F0F0F0F0F0F0F0),
+                ABC_CONST(0xFF00FF00FF00FF00),
+                ABC_CONST(0xFFFF0000FFFF0000),
+                ABC_CONST(0xFFFFFFFF00000000)
+            };
+            int nVarsMax = 16;
+            int nWordsMax = (1 << 10);
+            int i, k;
+            assert( nVarsMax <= 16 );
+            for ( i = 0; i < nVarsMax; i++ )
+                pTruths[i] = TruthStore[i];
+            for ( i = 0; i < 6; i++ )
+                for ( k = 0; k < nWordsMax; k++ )
+                    pTruths[i][k] = Truth6[i];
+            for ( i = 6; i < nVarsMax; i++ )
+                for ( k = 0; k < nWordsMax; k++ )
+                    pTruths[i][k] = ((k >> (i-6)) & 1) ? ~(word)0 : 0;
+        }
+
+        // collect variables
+//        Abc_ObjForEachFanin( pNode, pNet, i )
+//            pVars[0][i] = pVars[1][i] = pVars[2][i] = i;
+
+        // derive truth table
+        Abc_SopToTruthBig( (char*)Abc_ObjData(pNode), nLeaves, pTruths, pCube, pRes );
+        if ( Kit_TruthIsConst0((unsigned *)pRes, nLeaves) || Kit_TruthIsConst1((unsigned *)pRes, nLeaves) )
+        {
+            fprintf( pFile, ".names %s\n %d\n", Abc_ObjName(Abc_ObjFanout0(pNode)), Kit_TruthIsConst1((unsigned *)pRes, nLeaves) );
+            return;
+        }
+
+//        Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves );  printf( "    " );
+//        Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves );  printf( "\n" );
+
+        // perform decomposition
+        if ( Length == 2 )
+        {
+            if ( !If_CluCheckExt( NULL, pRes, nLeaves, nLutLeaf, nLutRoot, pLut0, pLut1, &Func0, &Func1 ) )
+            {
+                Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves );  printf( "    " );
+                Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves );  printf( "\n" );
+                printf( "Node \"%s\" is not decomposable. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+                return;
+            }
+        }
+        else
+        {
+            if ( !If_CluCheckExt3( NULL, pRes, nLeaves, nLutLeaf, nLutLeaf2, nLutRoot, pLut0, pLut1, pLut2, &Func0, &Func1, &Func2 ) )
+            {
+                Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves );  printf( "    " );
+                Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves );  printf( "\n" );
+                printf( "Node \"%s\" is not decomposable. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+                return;
+            }
+        }
+
+        // write leaf node
+        fprintf( pFile, ".names" );
+        for ( i = 0; i < pLut1[0]; i++ )
+            fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,pLut1[2+i])) );
+        fprintf( pFile, " %s_lut1\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+        // write SOP
+        pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func1, pLut1[0], vCover );
+        fprintf( pFile, "%s", pSop );
+
+        if ( Length == 3 && pLut2[0] > 0 )
+        {
+            // write leaf node
+            fprintf( pFile, ".names" );
+            for ( i = 0; i < pLut2[0]; i++ )
+                if ( pLut2[2+i] == nLeaves )
+                    fprintf( pFile, " %s_lut1", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+                else
+                    fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,pLut2[2+i])) );
+            fprintf( pFile, " %s_lut2\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+            // write SOP
+            pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func2, pLut2[0], vCover );
+            fprintf( pFile, "%s", pSop );
+        }
+
+        // write root node
+        fprintf( pFile, ".names" );
+        for ( i = 0; i < pLut0[0]; i++ )
+            if ( pLut0[2+i] == nLeaves )
+                fprintf( pFile, " %s_lut1", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+            else if ( pLut0[2+i] == nLeaves+1 )
+                fprintf( pFile, " %s_lut2", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+            else
+                fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,pLut0[2+i])) );
+        fprintf( pFile, " %s\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+        // write SOP
+        pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func0, pLut0[0], vCover );
+        fprintf( pFile, "%s", pSop );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the node into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteModelIntStruct( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vCover, char * pStr )
+{
+    Abc_Obj_t * pNet;
+    int nLeaves = Abc_ObjFaninNum(pNode);
+    int i, nLutLeaf, nLutLeaf2, nLutRoot, Length;
+
+    // write the header
+    fprintf( pFile, "\n" );
+    fprintf( pFile, ".model m%d\n", Abc_ObjId(pNode) );
+    fprintf( pFile, ".inputs" );
+    for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
+        fprintf( pFile, " %c", 'a' + i );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, ".outputs o\n" );
+
+    // quit if parameters are wrong
+    Length = strlen(pStr);
+    if ( Length != 2 && Length != 3 )
+    {
+        printf( "Wrong LUT struct (%s)\n", pStr );
+        return;
+    }
+    for ( i = 0; i < Length; i++ )
+        if ( pStr[i] - '0' < 3 || pStr[i] - '0' > 6 )
+        {
+            printf( "The LUT size (%d) should belong to {3,4,5,6}.\n", pStr[i] - '0' );
+            return;
+        }
+
+    nLutLeaf  =                   pStr[0] - '0';
+    nLutLeaf2 = ( Length == 3 ) ? pStr[1] - '0' : 0;
+    nLutRoot  =                   pStr[Length-1] - '0';
+    if ( nLeaves > nLutLeaf - 1 + (nLutLeaf2 ? nLutLeaf2 - 1 : 0) + nLutRoot )
+    {
+        printf( "The node size (%d) is too large for the LUT structure %s.\n", nLeaves, pStr );
+        return;
+    }
+
+    // consider easy case
+    if ( nLeaves <= Abc_MaxInt( nLutLeaf2, Abc_MaxInt(nLutLeaf, nLutRoot) ) )
+    {
+        // write the .names line
+        fprintf( pFile, ".names" );
+        Abc_ObjForEachFanin( pNode, pNet, i )
+            fprintf( pFile, " %c", 'a' + i );
+        // get the output name
+        fprintf( pFile, " %s\n", "o" );
+        // write the cubes
+        fprintf( pFile, "%s", (char*)Abc_ObjData(pNode) );
+        fprintf( pFile, ".end\n" );
+        return;
+    }
+    else
+    {
+        extern int If_CluMinimumBase( word * t, int * pSupp, int nVarsAll, int * pnVars );
+
+        static word TruthStore[16][1<<10] = {{0}}, * pTruths[16];
+        word pCube[1<<10], pRes[1<<10], Func0, Func1, Func2;
+        char pLut0[32], pLut1[32], pLut2[32] = {0}, * pSop;
+//        int nVarsMin[3], pVars[3][20];
+
+        if ( TruthStore[0][0] == 0 )
+        {
+            static word Truth6[6] = {
+                ABC_CONST(0xAAAAAAAAAAAAAAAA),
+                ABC_CONST(0xCCCCCCCCCCCCCCCC),
+                ABC_CONST(0xF0F0F0F0F0F0F0F0),
+                ABC_CONST(0xFF00FF00FF00FF00),
+                ABC_CONST(0xFFFF0000FFFF0000),
+                ABC_CONST(0xFFFFFFFF00000000)
+            };
+            int nVarsMax = 16;
+            int nWordsMax = (1 << 10);
+            int i, k;
+            assert( nVarsMax <= 16 );
+            for ( i = 0; i < nVarsMax; i++ )
+                pTruths[i] = TruthStore[i];
+            for ( i = 0; i < 6; i++ )
+                for ( k = 0; k < nWordsMax; k++ )
+                    pTruths[i][k] = Truth6[i];
+            for ( i = 6; i < nVarsMax; i++ )
+                for ( k = 0; k < nWordsMax; k++ )
+                    pTruths[i][k] = ((k >> (i-6)) & 1) ? ~(word)0 : 0;
+        }
+
+        // collect variables
+//        Abc_ObjForEachFanin( pNode, pNet, i )
+//            pVars[0][i] = pVars[1][i] = pVars[2][i] = i;
+
+        // derive truth table
+        Abc_SopToTruthBig( (char*)Abc_ObjData(pNode), nLeaves, pTruths, pCube, pRes );
+        if ( Kit_TruthIsConst0((unsigned *)pRes, nLeaves) || Kit_TruthIsConst1((unsigned *)pRes, nLeaves) )
+        {
+            fprintf( pFile, ".names %s\n %d\n", "o", Kit_TruthIsConst1((unsigned *)pRes, nLeaves) );
+            fprintf( pFile, ".end\n" );
+            return;
+        }
+
+//        Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves );  printf( "    " );
+//        Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves );  printf( "\n" );
+
+        // perform decomposition
+        if ( Length == 2 )
+        {
+            if ( !If_CluCheckExt( NULL, pRes, nLeaves, nLutLeaf, nLutRoot, pLut0, pLut1, &Func0, &Func1 ) )
+            {
+                Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves );  printf( "    " );
+                Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves );  printf( "\n" );
+                printf( "Node \"%s\" is not decomposable. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+                return;
+            }
+        }
+        else
+        {
+            if ( !If_CluCheckExt3( NULL, pRes, nLeaves, nLutLeaf, nLutLeaf2, nLutRoot, pLut0, pLut1, pLut2, &Func0, &Func1, &Func2 ) )
+            {
+                Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves );  printf( "    " );
+                Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves );  printf( "\n" );
+                printf( "Node \"%s\" is not decomposable. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+                return;
+            }
+        }
+
+        // write leaf node
+        fprintf( pFile, ".names" );
+        for ( i = 0; i < pLut1[0]; i++ )
+            fprintf( pFile, " %c", 'a' + pLut1[2+i] );
+        fprintf( pFile, " lut1\n" );
+        // write SOP
+        pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func1, pLut1[0], vCover );
+        fprintf( pFile, "%s", pSop );
+
+        if ( Length == 3 && pLut2[0] > 0 )
+        {
+            // write leaf node
+            fprintf( pFile, ".names" );
+            for ( i = 0; i < pLut2[0]; i++ )
+                if ( pLut2[2+i] == nLeaves )
+                    fprintf( pFile, " lut1" );
+                else
+                    fprintf( pFile, " %c", 'a' + pLut2[2+i] );
+            fprintf( pFile, " lut2\n" );
+            // write SOP
+            pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func2, pLut2[0], vCover );
+            fprintf( pFile, "%s", pSop );
+        }
+
+        // write root node
+        fprintf( pFile, ".names" );
+        for ( i = 0; i < pLut0[0]; i++ )
+            if ( pLut0[2+i] == nLeaves )
+                fprintf( pFile, " lut1" );
+            else if ( pLut0[2+i] == nLeaves+1 )
+                fprintf( pFile, " lut2" );
+            else
+                fprintf( pFile, " %c", 'a' + pLut0[2+i] );
+        fprintf( pFile, " %s\n", "o" );
+        // write SOP
+        pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func0, pLut0[0], vCover );
+        fprintf( pFile, "%s", pSop );
+        fprintf( pFile, ".end\n" );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Write the network into a BLIF file with the given name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteBlifInt( Abc_Ntk_t * pNtk, char * FileName, char * pLutStruct, int fUseHie )
+{
+    FILE * pFile;
+    Vec_Int_t * vCover;
+    Abc_Obj_t * pNode, * pLatch;
+    int i;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    // start writing the file
+    pFile = fopen( FileName, "w" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Io_WriteBlifInt(): Cannot open the output file.\n" );
+        return;
+    }
+    fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+    // write the model name
+    fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) );
+    // write the PIs
+    fprintf( pFile, ".inputs" );
+    Io_NtkWritePis( pFile, pNtk, 1 );
+    fprintf( pFile, "\n" );
+    // write the POs
+    fprintf( pFile, ".outputs" );
+    Io_NtkWritePos( pFile, pNtk, 1 );
+    fprintf( pFile, "\n" );
+    // write the latches
+    if ( Abc_NtkLatchNum(pNtk) )
+        fprintf( pFile, "\n" );
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+        Io_NtkWriteLatch( pFile, pLatch );
+    if ( Abc_NtkLatchNum(pNtk) )
+        fprintf( pFile, "\n" );
+    // write the hierarchy
+    vCover = Vec_IntAlloc( (1<<16) );
+    if ( fUseHie )
+    {
+        // write each internal node
+        fprintf( pFile, "\n" );
+        Abc_NtkForEachNode( pNtk, pNode, i )
+            Io_NtkWriteNodeSubckt( pFile, pNode, 0 );
+        fprintf( pFile, ".end\n\n" );
+        // write models
+        Abc_NtkForEachNode( pNtk, pNode, i )
+            Io_NtkWriteModelIntStruct( pFile, pNode, vCover, pLutStruct );
+        fprintf( pFile, "\n" );
+    }
+    else
+    {
+        // write each internal node
+        Abc_NtkForEachNode( pNtk, pNode, i )
+        {
+            if ( pLutStruct )
+                Io_NtkWriteNodeIntStruct( pFile, pNode, vCover, pLutStruct );
+            else
+                Io_NtkWriteNodeInt( pFile, pNode, vCover );
+        }
+        fprintf( pFile, ".end\n\n" );
+    }
+    Vec_IntFree( vCover );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the network into a BLIF file with the given name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteBlifSpecial( Abc_Ntk_t * pNtk, char * FileName, char * pLutStruct, int fUseHie )
+{
+    Abc_Ntk_t * pNtkTemp;
+    assert( Abc_NtkIsLogic(pNtk) );
+    Abc_NtkToSop( pNtk, 0 );
+    // derive the netlist
+    pNtkTemp = Abc_NtkToNetlist(pNtk);
+    if ( pNtkTemp == NULL )
+    {
+        fprintf( stdout, "Writing BLIF has failed.\n" );
+        return;
+    }
+    if ( pLutStruct && fUseHie )
+        Io_WriteBlifInt( pNtkTemp, FileName, pLutStruct, 1 );
+    else
+        Io_WriteBlifInt( pNtkTemp, FileName, pLutStruct, 0 );
+    Abc_NtkDelete( pNtkTemp );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioWriteBlifMv.c b/abc-build/src/base/io/ioWriteBlifMv.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioWriteBlifMv.c
@@ -0,0 +1,476 @@
+/**CFile****************************************************************
+
+  FileName    [ioWriteBlifMv.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to write BLIF-MV files.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioWriteBlifMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+#include "base/main/main.h"
+#include "map/mio/mio.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteBlifMvPis( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteBlifMvPos( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteBlifMvAsserts( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteBlifMvNodeFanins( FILE * pFile, Abc_Obj_t * pNode );
+static void Io_NtkWriteBlifMvNode( FILE * pFile, Abc_Obj_t * pNode );
+static void Io_NtkWriteBlifMvLatch( FILE * pFile, Abc_Obj_t * pLatch );
+static void Io_NtkWriteBlifMvSubckt( FILE * pFile, Abc_Obj_t * pNode );
+static void Io_NtkWriteBlifMvValues( FILE * pFile, Abc_Obj_t * pNode );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Write the network into a BLIF file with the given name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName )
+{
+    FILE * pFile;
+    Abc_Ntk_t * pNtkTemp;
+    int i;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_NtkHasBlifMv(pNtk) );
+    // start writing the file
+    pFile = fopen( FileName, "w" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Io_WriteBlifMv(): Cannot open the output file.\n" );
+        return;
+    }
+    fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+    // write the master network
+    Io_NtkWriteBlifMv( pFile, pNtk );
+    // write the remaining networks
+    if ( pNtk->pDesign )
+    {
+        Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pNtkTemp, i )
+        {
+            if ( pNtkTemp == pNtk )
+                continue;
+            fprintf( pFile, "\n\n" );
+            Io_NtkWriteBlifMv( pFile, pNtkTemp );
+        }
+    }
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the network into a BLIF file with the given name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    assert( Abc_NtkIsNetlist(pNtk) );
+    // write the model name
+    fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) );
+    // write the network
+    Io_NtkWriteBlifMvOne( pFile, pNtk );
+    // write EXDC network if it exists
+    if ( Abc_NtkExdc(pNtk) )
+        printf( "Io_NtkWriteBlifMv(): EXDC is not written.\n" );
+    // finalize the file
+    fprintf( pFile, ".end\n\n\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write one network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    ProgressBar * pProgress;
+    Abc_Obj_t * pNode, * pTerm, * pLatch;
+    int i;
+
+    // write the PIs
+    fprintf( pFile, ".inputs" );
+    Io_NtkWriteBlifMvPis( pFile, pNtk );
+    fprintf( pFile, "\n" );
+
+    // write the POs
+    fprintf( pFile, ".outputs" );
+    Io_NtkWriteBlifMvPos( pFile, pNtk );
+    fprintf( pFile, "\n" );
+
+    // write the MV directives
+    fprintf( pFile, "\n" );
+    Abc_NtkForEachCi( pNtk, pTerm, i )
+        if ( Abc_ObjMvVarNum(Abc_ObjFanout0(pTerm)) > 2 )
+            fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanout0(pTerm)), Abc_ObjMvVarNum(Abc_ObjFanout0(pTerm)) );
+    Abc_NtkForEachCo( pNtk, pTerm, i )
+        if ( Abc_ObjMvVarNum(Abc_ObjFanin0(pTerm)) > 2 )
+            fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanin0(pTerm)), Abc_ObjMvVarNum(Abc_ObjFanin0(pTerm)) );
+
+    // write the blackbox
+    if ( Abc_NtkHasBlackbox( pNtk ) )
+    {
+        fprintf( pFile, ".blackbox\n" );
+        return;
+    }
+
+    // write the timing info
+//    Io_WriteTimingInfo( pFile, pNtk );
+
+    // write the latches
+    if ( !Abc_NtkIsComb(pNtk) )
+    {
+        fprintf( pFile, "\n" );
+        Abc_NtkForEachLatch( pNtk, pLatch, i )
+            Io_NtkWriteBlifMvLatch( pFile, pLatch );
+        fprintf( pFile, "\n" );
+    }
+/*
+    // write the subcircuits
+    assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+    if ( Abc_NtkBlackboxNum(pNtk) > 0 )
+    {
+        fprintf( pFile, "\n" );
+        Abc_NtkForEachBlackbox( pNtk, pNode, i )
+            Io_NtkWriteBlifMvSubckt( pFile, pNode );
+        fprintf( pFile, "\n" );
+    }
+*/
+    if ( Abc_NtkBlackboxNum(pNtk) > 0 || Abc_NtkWhiteboxNum(pNtk) > 0 )
+    {
+        fprintf( pFile, "\n" );
+        Abc_NtkForEachBox( pNtk, pNode, i )
+        {
+            if ( Abc_ObjIsLatch(pNode) )
+                continue;
+            Io_NtkWriteBlifMvSubckt( pFile, pNode );
+        }
+        fprintf( pFile, "\n" );
+    }
+
+    // write each internal node
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        Io_NtkWriteBlifMvNode( pFile, pNode );
+    }
+    Extra_ProgressBarStop( pProgress );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the primary input list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteBlifMvPis( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pTerm, * pNet;
+    int LineLength;
+    int AddedLength;
+    int NameCounter;
+    int i;
+
+    LineLength  = 7;
+    NameCounter = 0;
+
+    Abc_NtkForEachPi( pNtk, pTerm, i )
+    {
+        pNet = Abc_ObjFanout0(pTerm);
+        // get the line length after this name is written
+        AddedLength = strlen(Abc_ObjName(pNet)) + 1;
+        if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+        { // write the line extender
+            fprintf( pFile, " \\\n" );
+            // reset the line length
+            LineLength  = 0;
+            NameCounter = 0;
+        }
+        fprintf( pFile, " %s", Abc_ObjName(pNet) );
+        LineLength += AddedLength;
+        NameCounter++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the primary input list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteBlifMvPos( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pTerm, * pNet;
+    int LineLength;
+    int AddedLength;
+    int NameCounter;
+    int i;
+
+    LineLength  = 8;
+    NameCounter = 0;
+
+    Abc_NtkForEachPo( pNtk, pTerm, i )
+    {
+        pNet = Abc_ObjFanin0(pTerm);
+        // get the line length after this name is written
+        AddedLength = strlen(Abc_ObjName(pNet)) + 1;
+        if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+        { // write the line extender
+            fprintf( pFile, " \\\n" );
+            // reset the line length
+            LineLength  = 0;
+            NameCounter = 0;
+        }
+        fprintf( pFile, " %s", Abc_ObjName(pNet) );
+        LineLength += AddedLength;
+        NameCounter++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the latch into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteBlifMvLatch( FILE * pFile, Abc_Obj_t * pLatch )
+{
+    Abc_Obj_t * pNetLi, * pNetLo;
+    int Reset;
+    pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) );
+    pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) );
+    Reset  = (int)(ABC_PTRUINT_T)Abc_ObjData( pLatch );
+    // write the latch line
+    fprintf( pFile, ".latch" );
+    fprintf( pFile, " %10s",    Abc_ObjName(pNetLi) );
+    fprintf( pFile, " %10s",    Abc_ObjName(pNetLo) );
+    fprintf( pFile, "\n" );
+    // write the reset node
+    fprintf( pFile, ".reset %s\n", Abc_ObjName(pNetLo) );
+    fprintf( pFile, "%d\n", Reset-1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the latch into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteBlifMvSubckt( FILE * pFile, Abc_Obj_t * pNode )
+{
+    Abc_Ntk_t * pModel = (Abc_Ntk_t *)pNode->pData;
+    Abc_Obj_t * pTerm;
+    int i;
+    // write the MV directives
+    fprintf( pFile, "\n" );
+    Abc_ObjForEachFanin( pNode, pTerm, i )
+        if ( Abc_ObjMvVarNum(pTerm) > 2 )
+            fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pTerm), Abc_ObjMvVarNum(pTerm) );
+    Abc_ObjForEachFanout( pNode, pTerm, i )
+        if ( Abc_ObjMvVarNum(pTerm) > 2 )
+            fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pTerm), Abc_ObjMvVarNum(pTerm) );
+    // write the subcircuit
+    fprintf( pFile, ".subckt %s %s", Abc_NtkName(pModel), Abc_ObjName(pNode) );
+    // write pairs of the formal=actual names
+    Abc_NtkForEachPi( pModel, pTerm, i )
+    {
+        fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pTerm)) );
+        pTerm = Abc_ObjFanin( pNode, i );
+        fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanin0(pTerm)) );
+    }
+    Abc_NtkForEachPo( pModel, pTerm, i )
+    {
+        fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pTerm)) );
+        pTerm = Abc_ObjFanout( pNode, i );
+        fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanout0(pTerm)) );
+    }
+    fprintf( pFile, "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Write the node into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteBlifMvNode( FILE * pFile, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    char * pCur;
+    int nValues, iFanin, i;
+
+    // write .mv directives for the fanins
+    fprintf( pFile, "\n" );
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+//        nValues = atoi(pCur);
+        nValues = Abc_ObjMvVarNum( pFanin );
+        if ( nValues > 2 )
+            fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pFanin), nValues );
+//        while ( *pCur++ != ' ' );
+    }
+
+    // write .mv directives for the node
+//    nValues = atoi(pCur);
+    nValues = Abc_ObjMvVarNum( Abc_ObjFanout0(pNode) );
+    if ( nValues > 2 )
+        fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanout0(pNode)), nValues );
+//    while ( *pCur++ != '\n' );
+
+    // write the .names line
+    fprintf( pFile, ".table" );
+    Io_NtkWriteBlifMvNodeFanins( pFile, pNode );
+    fprintf( pFile, "\n" );
+
+    // write the cubes
+    pCur = (char *)Abc_ObjData(pNode);
+    if ( *pCur == 'd' )
+    {
+        fprintf( pFile, ".default " );
+        pCur++;
+    }
+    // write the literals
+    for ( ; *pCur; pCur++ )
+    {
+        fprintf( pFile, "%c", *pCur );
+        if ( *pCur != '=' )
+            continue;
+        // get the number
+        iFanin = atoi( pCur+1 );
+        fprintf( pFile, "%s", Abc_ObjName(Abc_ObjFanin(pNode,iFanin)) );
+        // scroll on to the next symbol
+        while ( *pCur != ' ' && *pCur != '\n' )
+            pCur++;
+        pCur--;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the primary input list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteBlifMvNodeFanins( FILE * pFile, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pNet;
+    int LineLength;
+    int AddedLength;
+    int NameCounter;
+    char * pName;
+    int i;
+
+    LineLength  = 6;
+    NameCounter = 0;
+    Abc_ObjForEachFanin( pNode, pNet, i )
+    {
+        // get the fanin name
+        pName = Abc_ObjName(pNet);
+        // get the line length after the fanin name is written
+        AddedLength = strlen(pName) + 1;
+        if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+        { // write the line extender
+            fprintf( pFile, " \\\n" );
+            // reset the line length
+            LineLength  = 0;
+            NameCounter = 0;
+        }
+        fprintf( pFile, " %s", pName );
+        LineLength += AddedLength;
+        NameCounter++;
+    }
+
+    // get the output name
+    pName = Abc_ObjName(Abc_ObjFanout0(pNode));
+    // get the line length after the output name is written
+    AddedLength = strlen(pName) + 1;
+    if ( NameCounter && LineLength + AddedLength > 75 )
+    { // write the line extender
+        fprintf( pFile, " \\\n" );
+        // reset the line length
+        LineLength  = 0;
+        NameCounter = 0;
+    }
+    fprintf( pFile, " %s", pName );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioWriteBook.c b/abc-build/src/base/io/ioWriteBook.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioWriteBook.c
@@ -0,0 +1,998 @@
+/**CFile****************************************************************
+
+  FileName    [ioWriteBook.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to write Bookshelf files.]
+
+  Author      [Myungchul Kim]
+  
+  Affiliation [U of Michigan]
+
+  Date        [Ver. 1.0. Started - October 25, 2008.]
+
+  Revision    [$Id: ioWriteBook.c,v 1.00 2005/11/10 00:00:00 mckima Exp $]
+
+***********************************************************************/
+
+#include <math.h>
+
+#include "base/main/main.h"
+#include "map/mio/mio.h"
+#include "ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+#define	NODES	   0
+#define	PL	   1
+#define coreHeight 1
+#define termWidth  1
+#define termHeight 1
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static unsigned Io_NtkWriteNodes( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWritePiPoNodes( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteLatchNode( FILE * pFile, Abc_Obj_t * pLatch, int NodesOrPl );
+static unsigned Io_NtkWriteIntNode( FILE * pFile, Abc_Obj_t * pNode, int NodesOrPl );
+static unsigned Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode );
+static void Io_NtkWriteNets( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteIntNet( FILE * pFile, Abc_Obj_t * pNode );
+static void Io_NtkBuildLayout( FILE * pFile1, FILE *pFile2, Abc_Ntk_t * pNtk, double aspectRatio, double whiteSpace, unsigned coreCellArea );
+static void Io_NtkWriteScl( FILE * pFile, unsigned numCoreRows, double layoutWidth );
+static void Io_NtkWritePl( FILE * pFile, Abc_Ntk_t * pNtk, unsigned numTerms, double layoutHeight, double layoutWidth );
+static Vec_Ptr_t * Io_NtkOrderingPads( Abc_Ntk_t * pNtk, Vec_Ptr_t * vTerms ); 
+static Abc_Obj_t * Io_NtkBfsPads( Abc_Ntk_t * pNtk, Abc_Obj_t * pCurrEntry, unsigned numTerms, int * pOrdered );
+static int Abc_NodeIsNand2( Abc_Obj_t * pNode );
+static int Abc_NodeIsNor2( Abc_Obj_t * pNode );
+static int Abc_NodeIsAnd2( Abc_Obj_t * pNode );
+static int Abc_NodeIsOr2( Abc_Obj_t * pNode );
+static int Abc_NodeIsXor2( Abc_Obj_t * pNode );
+static int Abc_NodeIsXnor2( Abc_Obj_t * pNode );
+
+static inline double Abc_Rint( double x )   { return (double)(int)x;  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Write the network into a Bookshelf file with the given name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteBookLogic( Abc_Ntk_t * pNtk, char * FileName )
+{
+    Abc_Ntk_t * pNtkTemp;
+    // derive the netlist
+    pNtkTemp = Abc_NtkToNetlist(pNtk);
+    if ( pNtkTemp == NULL )
+    {
+        fprintf( stdout, "Writing BOOK has failed.\n" );
+        return;
+    }
+    Io_WriteBook( pNtkTemp, FileName );
+    Abc_NtkDelete( pNtkTemp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the network into a BOOK file with the given name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteBook( Abc_Ntk_t * pNtk, char * FileName )
+{
+
+    FILE * pFileNodes, * pFileNets, * pFileAux;
+    FILE * pFileScl, * pFilePl, * pFileWts;
+    char * FileExt = ABC_CALLOC( char, strlen(FileName)+7 );
+    unsigned coreCellArea=0;
+    Abc_Ntk_t * pExdc, * pNtkTemp;
+    int i;
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+    // start writing the files
+    strcpy(FileExt, FileName);
+    pFileNodes = fopen( strcat(FileExt,".nodes"), "w" );
+    strcpy(FileExt, FileName);
+    pFileNets  = fopen( strcat(FileExt,".nets"), "w" );
+    strcpy(FileExt, FileName);
+    pFileAux   = fopen( strcat(FileExt,".aux"), "w" );
+
+		// write the aux file
+    if ( (pFileNodes == NULL) || (pFileNets == NULL) || (pFileAux == NULL) )
+    {
+        fclose( pFileAux );
+        fprintf( stdout, "Io_WriteBook(): Cannot open the output files.\n" );
+        return;
+    }
+    fprintf( pFileAux, "RowBasedPlacement : %s.nodes %s.nets %s.scl %s.pl %s.wts", 
+	     FileName, FileName, FileName, FileName, FileName );
+    fclose( pFileAux );
+
+    // write the master network
+    coreCellArea+=Io_NtkWriteNodes( pFileNodes, pNtk );
+    Io_NtkWriteNets( pFileNets, pNtk );
+
+    // write EXDC network if it exists
+    pExdc = Abc_NtkExdc( pNtk );
+    if ( pExdc )
+    {
+	coreCellArea+=Io_NtkWriteNodes( pFileNodes, pNtk );
+        Io_NtkWriteNets( pFileNets, pNtk );
+    }
+
+    // make sure there is no logic hierarchy
+    assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+
+    // write the hierarchy if present
+    if ( Abc_NtkBlackboxNum(pNtk) > 0 )
+    {
+        Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pNtkTemp, i )
+        {
+            if ( pNtkTemp == pNtk )
+                continue;
+            coreCellArea+=Io_NtkWriteNodes( pFileNodes, pNtkTemp );
+            Io_NtkWriteNets( pFileNets, pNtkTemp );
+        }
+    }
+    fclose( pFileNodes );
+    fclose( pFileNets );
+
+    strcpy(FileExt, FileName);
+    pFileScl = fopen( strcat(FileExt,".scl"), "w" );
+    strcpy(FileExt, FileName);
+    pFilePl  = fopen( strcat(FileExt,".pl"), "w" );
+    strcpy(FileExt, FileName);
+    pFileWts   = fopen( strcat(FileExt,".wts"), "w" );
+    ABC_FREE(FileExt);
+
+    Io_NtkBuildLayout( pFileScl, pFilePl, pNtk, 1.0, 10, coreCellArea );
+    fclose( pFileScl );
+    fclose( pFilePl );
+    fclose( pFileWts );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the network into a BOOK file with the given name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Io_NtkWriteNodes( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    ProgressBar * pProgress;
+    Abc_Obj_t * pLatch, * pNode;
+    unsigned numTerms, numNodes, coreCellArea=0;
+    int i;
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+    // write the forehead
+    numTerms=Abc_NtkPiNum(pNtk)+Abc_NtkPoNum(pNtk);
+    numNodes=numTerms+Abc_NtkNodeNum(pNtk)+Abc_NtkLatchNum(pNtk);
+    printf("NumNodes : %d\t", numNodes );
+    printf("NumTerminals : %d\n", numTerms );
+    fprintf( pFile, "UCLA    nodes    1.0\n");
+    fprintf( pFile, "NumNodes : %d\n", numNodes );
+    fprintf( pFile, "NumTerminals : %d\n", numTerms );
+    // write the PI/POs
+    Io_NtkWritePiPoNodes( pFile, pNtk );
+    // write the latches
+    if ( !Abc_NtkIsComb(pNtk) )
+    {
+	    Abc_NtkForEachLatch( pNtk, pLatch, i )
+	    {
+	        Io_NtkWriteLatchNode( pFile, pLatch, NODES );
+	        coreCellArea+=6*coreHeight;
+	    }
+    }
+    // write each internal node
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        coreCellArea+=Io_NtkWriteIntNode( pFile, pNode, NODES );
+    }
+    Extra_ProgressBarStop( pProgress );
+    return coreCellArea;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the primary input nodes into a file]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWritePiPoNodes( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pTerm, * pNet;
+    int i;
+
+    Abc_NtkForEachPi( pNtk, pTerm, i )
+    {
+    	pNet = Abc_ObjFanout0(pTerm);
+	fprintf( pFile, "i%s_input\t", Abc_ObjName(pNet) ); 
+	fprintf( pFile, "terminal ");
+	fprintf( pFile, " %d %d\n", termWidth, termHeight );
+    }
+	
+    Abc_NtkForEachPo( pNtk, pTerm, i )
+    {
+	pNet = Abc_ObjFanin0(pTerm);
+	fprintf( pFile, "o%s_output\t", Abc_ObjName(pNet) ); 
+	fprintf( pFile, "terminal ");
+	fprintf( pFile, " %d %d\n", termWidth, termHeight );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the latch nodes into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteLatchNode( FILE * pFile, Abc_Obj_t * pLatch, int NodesOrPl )
+{
+    Abc_Obj_t * pNetLi, * pNetLo;
+    
+    pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) );
+    pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) );
+	/// write the latch line
+    fprintf( pFile, "%s_%s_latch\t", Abc_ObjName(pNetLi), Abc_ObjName(pNetLo) );
+    if (NodesOrPl == NODES)
+        fprintf( pFile, " %d %d\n", 6, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the internal node into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Io_NtkWriteIntNode( FILE * pFile, Abc_Obj_t * pNode, int NodesOrPl )
+{
+    unsigned sizex=0, sizey=coreHeight, isize=0;
+    //double nx, ny, xstep, ystep;	
+    Abc_Obj_t * pNeti, *pNeto;
+    int i;
+		
+    // write the network after mapping 
+    if ( Abc_NtkHasMapping(pNode->pNtk) )
+        sizex=Io_NtkWriteNodeGate( pFile, pNode );
+    else
+    {
+	Abc_ObjForEachFanin( pNode, pNeti, i )
+	    fprintf( pFile, "%s_", Abc_ObjName(pNeti) );
+	Abc_ObjForEachFanout( pNode, pNeto, i )
+	    fprintf( pFile, "%s_", Abc_ObjName(pNeto) );	
+	fprintf( pFile, "name\t" );
+	
+	if(NodesOrPl == NODES)
+	{
+	    isize=Abc_ObjFaninNum(pNode);
+	    if ( Abc_NodeIsConst0(pNode) || Abc_NodeIsConst1(pNode) ) 
+	        sizex=0;
+	    else if ( Abc_NodeIsInv(pNode) )
+	        sizex=1;
+	    else if ( Abc_NodeIsBuf(pNode) )
+	        sizex=2;
+	    else
+	    {
+	        assert( Abc_NtkHasSop(pNode->pNtk) );
+	        if ( Abc_NodeIsNand2(pNode) || Abc_NodeIsNor2(pNode) )
+		    sizex=2;
+		else if ( Abc_NodeIsAnd2(pNode) || Abc_NodeIsOr2(pNode) )
+		    sizex=3;
+		else if ( Abc_NodeIsXor2(pNode) || Abc_NodeIsXnor2(pNode) )
+		    sizex=5;
+		else
+		{
+		    assert( isize > 2 );
+		    sizex=isize+Abc_SopGetCubeNum((char *)pNode->pData);
+		}
+	    }
+	}
+    }
+    if(NodesOrPl == NODES)
+    {
+	fprintf( pFile, " %d %d\n", sizex, sizey );
+
+    // Equally place pins. Size pins needs /  isize+#output+1
+	isize= isize + Abc_ObjFanoutNum(pNode) + 1;
+    }
+    return sizex*sizey;
+	/*
+	xstep = sizex / isize;
+	ystep = sizey / isize;
+	nx= -0.5 * sizex;
+	ny= -0.5 * sizey;
+
+	Abc_ObjForEachFanin( pNode, pFanin, i )
+	{
+			nx+= xstep;
+			ny+= ystep;
+			if (fabs(nx) < 0.001)
+					nx= 0;
+			if (fabs(ny) < 0.001)
+					ny= 0;
+	}
+	Abc_ObjForEachFanout( pNode, pFanout, i )
+	{
+			nx+= xstep;
+			ny+= ystep;
+			if (fabs(nx) < 0.001)
+					nx= 0;
+			if (fabs(ny) < 0.001)
+					ny= 0;
+	}
+	*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the internal node after tech mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode )
+{
+    Mio_Gate_t * pGate = (Mio_Gate_t *)pNode->pData;
+    Mio_Pin_t * pGatePin;
+    int i;
+    // write the node gate
+    for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ )
+        fprintf( pFile, "%s_", Abc_ObjName( Abc_ObjFanin(pNode,i) ) );
+    assert ( i == Abc_ObjFaninNum(pNode) );
+    fprintf( pFile, "%s_%s\t", Abc_ObjName( Abc_ObjFanout0(pNode) ), Mio_GateReadName(pGate) );
+    return Mio_GateReadArea(pGate);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the nets into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteNets( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    ProgressBar * pProgress;
+    Abc_Obj_t * pNet;
+    unsigned numPin=0;
+    int i;
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+    // write the head
+    Abc_NtkForEachNet( pNtk, pNet, i )
+    numPin+=Abc_ObjFaninNum(pNet)+Abc_ObjFanoutNum(pNet);
+    printf( "NumNets  : %d\t", Abc_NtkNetNum(pNtk) );
+    printf( "NumPins      : %d\n\n", numPin );
+    fprintf( pFile, "UCLA    nets    1.0\n");
+    fprintf( pFile, "NumNets : %d\n", Abc_NtkNetNum(pNtk) );
+    fprintf( pFile, "NumPins : %d\n", numPin );
+
+    // write nets
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNetNum(pNtk) );
+    Abc_NtkForEachNet( pNtk, pNet, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        Io_NtkWriteIntNet( pFile, pNet );
+    }
+    Extra_ProgressBarStop( pProgress );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the nets into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteIntNet( FILE * pFile, Abc_Obj_t * pNet )
+{
+    Abc_Obj_t * pFanin, * pFanout;
+    Abc_Obj_t * pNeti, * pNeto;
+    Abc_Obj_t * pNetLi, * pNetLo, * pLatch;
+    int i, j;
+    int NetDegree=Abc_ObjFaninNum(pNet)+Abc_ObjFanoutNum(pNet);
+
+    fprintf( pFile, "NetDegree\t:\t\t%d\t\t%s\n", NetDegree, Abc_ObjName(Abc_ObjFanin0(pNet)) );
+
+    pFanin=Abc_ObjFanin0(pNet);
+    if ( Abc_ObjIsPi(pFanin) )
+	fprintf( pFile, "i%s_input I\n", Abc_ObjName(pNet) );
+    else 
+    {
+	if(!Abc_NtkIsComb(pNet->pNtk) && Abc_ObjFaninNum(pFanin) && Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) )
+	{
+	    pLatch=Abc_ObjFanin0(pFanin);
+	    pNetLi=Abc_ObjFanin0(Abc_ObjFanin0(pLatch));
+	    pNetLo=Abc_ObjFanout0(Abc_ObjFanout0(pLatch));
+	    fprintf( pFile, "%s_%s_latch I : ", Abc_ObjName(pNetLi), Abc_ObjName(pNetLo) );
+	}
+	else
+	{
+	    Abc_ObjForEachFanin( pFanin, pNeti, j )
+	    fprintf( pFile, "%s_", Abc_ObjName(pNeti) );
+	    Abc_ObjForEachFanout( pFanin, pNeto, j )
+	    fprintf( pFile, "%s_", Abc_ObjName(pNeto) );	
+	    if ( Abc_NtkHasMapping(pNet->pNtk) )
+		fprintf( pFile, "%s : ", Mio_GateReadName((Mio_Gate_t *)pFanin->pData) ); 
+	    else
+		fprintf( pFile, "name I : " );								
+	}
+	// offsets are simlply 0.00 0.00 at the moment
+	fprintf( pFile, "%.2f %.2f\n", .0, .0 );
+    }
+
+    Abc_ObjForEachFanout( pNet, pFanout, i )
+    {
+	if ( Abc_ObjIsPo(pFanout) )
+	    fprintf( pFile, "o%s_output O\n", Abc_ObjName(pNet) );
+	else
+	{
+	    if(!Abc_NtkIsComb(pNet->pNtk) && Abc_ObjFanoutNum(pFanout) && Abc_ObjIsLatch( Abc_ObjFanout0(pFanout) ) )
+	    {
+		pLatch=Abc_ObjFanout0(pFanout);
+		pNetLi=Abc_ObjFanin0(Abc_ObjFanin0(pLatch));
+		pNetLo=Abc_ObjFanout0(Abc_ObjFanout0(pLatch));
+		fprintf( pFile, "%s_%s_latch O : ", Abc_ObjName(pNetLi), Abc_ObjName(pNetLo) );
+	    }
+	    else
+	    {
+		Abc_ObjForEachFanin( pFanout, pNeti, j )
+		fprintf( pFile, "%s_", Abc_ObjName(pNeti) );
+		Abc_ObjForEachFanout( pFanout, pNeto, j )
+		fprintf( pFile, "%s_", Abc_ObjName(pNeto) );	
+		if ( Abc_NtkHasMapping(pNet->pNtk) )
+		    fprintf( pFile, "%s : ", Mio_GateReadName((Mio_Gate_t *)pFanout->pData) ); 
+		else
+		    fprintf( pFile, "name O : " );
+	    }
+	// offsets are simlply 0.00 0.00 at the moment
+	fprintf( pFile, "%.2f %.2f\n", .0, .0 );
+	}
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the network into a BOOK file with the given name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkBuildLayout( FILE * pFileScl, FILE * pFilePl, Abc_Ntk_t * pNtk, double aspectRatio, double whiteSpace, unsigned coreCellArea )
+{
+    unsigned numCoreCells=Abc_NtkNodeNum(pNtk)+Abc_NtkLatchNum(pNtk);
+    double targetLayoutArea = coreCellArea/(1.0-(whiteSpace/100.0));
+    unsigned numCoreRows=(aspectRatio>0.0) ? (Abc_Rint(sqrt(targetLayoutArea/aspectRatio)/coreHeight)) : 0;
+    unsigned numTerms=Abc_NtkPiNum(pNtk)+Abc_NtkPoNum(pNtk);
+    unsigned totalWidth=coreCellArea/coreHeight;
+    double layoutHeight = numCoreRows * coreHeight;
+    double layoutWidth = Abc_Rint(targetLayoutArea/layoutHeight);
+    double actualLayoutArea = layoutWidth * layoutHeight;
+
+    printf( "Core cell height(==site height) is %d\n", coreHeight );
+    printf( "Total core cell width is %d giving an ave width of %f\n", totalWidth, (double)(totalWidth/numCoreCells));
+    printf( "Target Dimensions:\n" );
+    printf( "  Area  :   %f\n", targetLayoutArea );
+    printf( "  WS%%   :   %f\n", whiteSpace );
+    printf( "  AR    :   %f\n", aspectRatio );
+    printf( "Actual Dimensions:\n" );
+    printf( "  Width :   %f\n", layoutWidth );
+    printf( "  Height:   %f (%d rows)\n", layoutHeight, numCoreRows);
+    printf( "  Area  :   %f\n", actualLayoutArea );
+    printf( "  WS%%   :   %f\n", 100*(actualLayoutArea-coreCellArea)/actualLayoutArea );
+    printf( "  AR    :   %f\n\n", layoutWidth/layoutHeight );	
+
+    Io_NtkWriteScl( pFileScl, numCoreRows, layoutWidth ); 
+    Io_NtkWritePl( pFilePl, pNtk, numTerms, layoutHeight, layoutWidth );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the network into a BOOK file with the given name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteScl( FILE * pFile, unsigned numCoreRows, double layoutWidth )
+{
+    int origin_y=0;
+    char * rowOrients[2] = {"N", "FS"};
+    char symmetry='Y';
+    double sitewidth=1.0;
+    double spacing=1.0;
+		
+    unsigned rowId;
+    // write the forehead
+    fprintf( pFile, "UCLA    scl    1.0\n\n" );
+    fprintf( pFile, "Numrows : %d\n\n", numCoreRows );
+
+    for( rowId=0 ; rowId<numCoreRows ; rowId++, origin_y += coreHeight )
+    {
+	fprintf( pFile, "CoreRow Horizontal\n" );
+	fprintf( pFile, " Coordinate   : \t%d\n", origin_y);
+	fprintf( pFile, " Height       : \t%d\n", coreHeight);
+	fprintf( pFile, " Sitewidth    : \t%d\n", (unsigned)sitewidth );
+	fprintf( pFile, " Sitespacing  : \t%d\n", (unsigned)spacing );
+	fprintf( pFile, " Siteorient   : \t%s\n", rowOrients[rowId%2] );
+	//if( coreRow[i].site.symmetry.rot90 || coreRow[i].site.symmetry.y || coreRow[i].site.symmetry.x )
+	fprintf( pFile, " Sitesymmetry : \t%c\n", symmetry );
+	//else fprintf( pFile, "Sitesymmetry			: \t\t\t1\n" );
+	fprintf( pFile, " SubrowOrigin : \t%d Numsites :	\t%d\n", 0, (unsigned)layoutWidth );
+	fprintf( pFile, "End\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the network into a BOOK file with the given name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWritePl( FILE * pFile, Abc_Ntk_t * pNtk, unsigned numTerms, double layoutWidth, double layoutHeight )
+{
+    Abc_Obj_t * pTerm, * pLatch, * pNode;
+    Vec_Ptr_t * vTerms = Vec_PtrAlloc ( numTerms ); 
+    Vec_Ptr_t * vOrderedTerms = Vec_PtrAlloc ( numTerms ); 
+    double layoutPerim = 2*layoutWidth + 2*layoutHeight;
+    double nextLoc_x, nextLoc_y;
+    double delta;
+    unsigned termsOnTop, termsOnBottom, termsOnLeft, termsOnRight;
+    unsigned t;
+	int i;
+
+    termsOnTop = termsOnBottom = (unsigned)(Abc_Rint(numTerms*(layoutWidth/layoutPerim)));
+    termsOnLeft = numTerms - (termsOnTop+termsOnBottom);
+    termsOnRight = (unsigned)(ceil(termsOnLeft/2.0));
+    termsOnLeft -= termsOnRight;
+
+    Abc_NtkForEachPi( pNtk, pTerm, i )
+	Vec_PtrPush( vTerms, pTerm );	
+    Abc_NtkForEachPo( pNtk, pTerm, i )
+	Vec_PtrPush( vTerms, pTerm );
+    // Ordering Pads
+    vOrderedTerms=Io_NtkOrderingPads( pNtk, vTerms );
+    assert( termsOnTop+termsOnBottom+termsOnLeft+termsOnRight == (unsigned)Vec_PtrSize(vOrderedTerms) );
+
+    printf( "Done constructing layout region\n" );
+    printf( "Terminals: %d\n", numTerms );
+    printf( "  Top:     %d\n", termsOnTop );
+    printf( "  Bottom:  %d\n", termsOnBottom );
+    printf( "  Left:    %d\n", termsOnLeft );
+    printf( "  Right:   %d\n", termsOnRight );
+
+    fprintf( pFile, "UCLA    pl    1.0\n\n" );
+
+    nextLoc_x = floor(.0);
+    nextLoc_y = ceil(layoutHeight + 2*coreHeight);
+    delta   = layoutWidth / termsOnTop;
+    for(t = 0; t < termsOnTop; t++)
+    {
+	pTerm = (Abc_Obj_t *)Vec_PtrEntry( vOrderedTerms, t );
+	if( Abc_ObjIsPi(pTerm) )
+	    fprintf( pFile, "i%s_input\t\t", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); 
+	else
+	    fprintf( pFile, "o%s_output\t\t", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); 
+	if( t && Abc_Rint(nextLoc_x) < Abc_Rint(nextLoc_x-delta)+termWidth )
+	    nextLoc_x++;
+	fprintf( pFile, "%d\t\t%d\t: %s /FIXED\n", (int)Abc_Rint(nextLoc_x), (int)Abc_Rint(nextLoc_y), "FS" );	
+	nextLoc_x += delta;
+    }
+
+    nextLoc_x = floor(.0);
+    nextLoc_y = floor(.0 - 2*coreHeight - termHeight);
+    delta   = layoutWidth / termsOnBottom;
+    for(;t < termsOnTop+termsOnBottom; t++)
+    {
+	pTerm = (Abc_Obj_t *)Vec_PtrEntry( vOrderedTerms, t );
+	if( Abc_ObjIsPi(pTerm) )
+	    fprintf( pFile, "i%s_input\t\t", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); 
+	else
+	    fprintf( pFile, "o%s_output\t\t", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); 
+	if( t!=termsOnTop && Abc_Rint(nextLoc_x) < Abc_Rint(nextLoc_x-delta)+termWidth )
+	    nextLoc_x++;
+	fprintf( pFile, "%d\t\t%d\t: %s /FIXED\n", (int)Abc_Rint(nextLoc_x), (int)Abc_Rint(nextLoc_y), "N" );	
+	nextLoc_x     += delta;
+    }
+
+    nextLoc_x = floor(.0-2*coreHeight-termWidth);
+    nextLoc_y = floor(.0);
+    delta   = layoutHeight / termsOnLeft;
+    for(;t < termsOnTop+termsOnBottom+termsOnLeft; t++)
+    {
+	pTerm = (Abc_Obj_t *)Vec_PtrEntry( vOrderedTerms, t );
+	if( Abc_ObjIsPi(pTerm) )
+	    fprintf( pFile, "i%s_input\t\t", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); 
+	else
+	    fprintf( pFile, "o%s_output\t\t", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); 
+	if( Abc_Rint(nextLoc_y) < Abc_Rint(nextLoc_y-delta)+termHeight )
+	    nextLoc_y++;
+	fprintf( pFile, "%d\t\t%d\t: %s /FIXED\n", (int)Abc_Rint(nextLoc_x), (int)Abc_Rint(nextLoc_y), "E" );	
+	nextLoc_y     += delta;
+    }
+
+    nextLoc_x = ceil(layoutWidth+2*coreHeight);
+    nextLoc_y = floor(.0);
+    delta   = layoutHeight / termsOnRight;
+    for(;t < termsOnTop+termsOnBottom+termsOnLeft+termsOnRight; t++)
+    {
+       	pTerm = (Abc_Obj_t *)Vec_PtrEntry( vOrderedTerms, t );
+	if( Abc_ObjIsPi(pTerm) )
+	    fprintf( pFile, "i%s_input\t\t", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); 
+	else
+	    fprintf( pFile, "o%s_output\t\t", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); 
+	if( Abc_Rint(nextLoc_y) < Abc_Rint(nextLoc_y-delta)+termHeight )
+	    nextLoc_y++;
+	fprintf( pFile, "%d\t\t%d\t: %s /FIXED\n", (int)Abc_Rint(nextLoc_x), (int)Abc_Rint(nextLoc_y), "FW" );	
+	nextLoc_y     += delta;
+    }
+
+    if( !Abc_NtkIsComb(pNtk) )
+    {
+	Abc_NtkForEachLatch( pNtk, pLatch, i )
+	{
+	    Io_NtkWriteLatchNode( pFile, pLatch, PL );
+	    fprintf( pFile, "\t%d\t\t%d\t: %s\n", 0, 0, "N" );	
+	}
+    }
+    
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+	Io_NtkWriteIntNode( pFile, pNode, PL );
+	fprintf( pFile, "\t%d\t\t%d\t: %s\n", 0, 0, "N" );	
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the closest I/O to a given I/O.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Io_NtkOrderingPads( Abc_Ntk_t * pNtk, Vec_Ptr_t * vTerms )
+{ 
+    ProgressBar * pProgress;
+    unsigned numTerms=Vec_PtrSize(vTerms); 
+    unsigned termIdx=0, termCount=0;
+    int * pOrdered = ABC_ALLOC(int, numTerms); 
+    int newNeighbor=1;
+    Vec_Ptr_t * vOrderedTerms = Vec_PtrAlloc ( numTerms );
+    Abc_Obj_t * pNeighbor = NULL, * pNextTerm;     
+    unsigned i; 
+
+    for( i=0 ; i<numTerms ; i++ )
+	pOrdered[i]=0; 
+   
+    pNextTerm = (Abc_Obj_t *)Vec_PtrEntry(vTerms, termIdx++);
+    pProgress = Extra_ProgressBarStart( stdout, numTerms );
+    while( termCount < numTerms && termIdx < numTerms )
+    {
+	if( pOrdered[Abc_ObjId(pNextTerm)] && !newNeighbor )
+	{
+	    pNextTerm = (Abc_Obj_t *)Vec_PtrEntry( vTerms, termIdx++ );
+	    continue;
+	}
+	if(!Vec_PtrPushUnique( vOrderedTerms, pNextTerm ))
+	{
+	    pOrdered[Abc_ObjId(pNextTerm)]=1;
+	    termCount++; 
+	}
+	pNeighbor=Io_NtkBfsPads( pNtk, pNextTerm, numTerms, pOrdered );
+	if( (newNeighbor=!Vec_PtrPushUnique( vOrderedTerms, pNeighbor )) )
+	{
+	   pOrdered[Abc_ObjId(pNeighbor)]=1;
+	   termCount++;
+	   pNextTerm=pNeighbor;
+	}
+	else if(termIdx < numTerms)
+	    pNextTerm = (Abc_Obj_t *)Vec_PtrEntry( vTerms, termIdx++ );
+
+	Extra_ProgressBarUpdate( pProgress, termCount, NULL );
+    }
+    Extra_ProgressBarStop( pProgress );
+    assert(termCount==numTerms);
+    return vOrderedTerms;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the closest I/O to a given I/O.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Io_NtkBfsPads( Abc_Ntk_t * pNtk, Abc_Obj_t * pTerm, unsigned numTerms, int * pOrdered )
+{
+    Vec_Ptr_t * vNeighbors = Vec_PtrAlloc ( numTerms ); 
+    Abc_Obj_t * pNet, * pNode, * pNeighbor;
+    int foundNeighbor=0;
+    int i;
+
+    assert(Abc_ObjIsPi(pTerm) || Abc_ObjIsPo(pTerm) );
+    Abc_NtkIncrementTravId ( pNtk );
+    Abc_NodeSetTravIdCurrent( pTerm );
+    if(Abc_ObjIsPi(pTerm))
+    {
+	pNet = Abc_ObjFanout0(pTerm);
+	Abc_ObjForEachFanout( pNet, pNode, i ) 
+	    Vec_PtrPush( vNeighbors, pNode );
+    }
+    else 
+    {
+	pNet = Abc_ObjFanin0(pTerm);
+	Abc_ObjForEachFanin( pNet, pNode, i ) 
+	    Vec_PtrPush( vNeighbors, pNode );   
+    }
+
+    while ( Vec_PtrSize(vNeighbors) >0 )
+    {
+	pNeighbor = (Abc_Obj_t *)Vec_PtrEntry( vNeighbors, 0 );
+	assert( Abc_ObjIsNode(pNeighbor) || Abc_ObjIsTerm(pNeighbor) );
+	Vec_PtrRemove( vNeighbors, pNeighbor );
+
+	if( Abc_NodeIsTravIdCurrent( pNeighbor ) )
+	    continue;
+	Abc_NodeSetTravIdCurrent( pNeighbor );
+
+	if( ((Abc_ObjIsPi(pNeighbor) || Abc_ObjIsPo(pNeighbor))) && !pOrdered[Abc_ObjId(pNeighbor)] )
+	{
+	    foundNeighbor=1;
+	    break;
+	}
+	if( Abc_ObjFanoutNum( pNeighbor ) )
+	{   
+	    pNet=Abc_ObjFanout0( pNeighbor );
+	    if( !Abc_NtkIsComb(pNtk) && Abc_ObjIsLatch(pNet) )
+		pNet=Abc_ObjFanout0( Abc_ObjFanout0(pNet) );
+	    Abc_ObjForEachFanout( pNet, pNode, i )
+		if( !Abc_NodeIsTravIdCurrent(pNode) ) 
+		    Vec_PtrPush( vNeighbors, pNode ); 
+	}
+	if( Abc_ObjFaninNum( pNeighbor ) )
+	{
+	    if( !Abc_NtkIsComb(pNtk) && Abc_ObjIsLatch(Abc_ObjFanin0(pNeighbor)) )
+		pNeighbor=Abc_ObjFanin0( Abc_ObjFanin0(pNeighbor) );
+	    Abc_ObjForEachFanin( pNeighbor, pNet, i )
+		if( !Abc_NodeIsTravIdCurrent(pNode=Abc_ObjFanin0(pNet)) ) 
+		    Vec_PtrPush( vNeighbors, pNode );
+	}
+    }
+    return ( foundNeighbor ) ? pNeighbor : pTerm;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Test is the node is nand2.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeIsNand2( Abc_Obj_t * pNode )
+{
+    Abc_Ntk_t * pNtk = pNode->pNtk;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_ObjIsNode(pNode) ); 
+    if ( Abc_ObjFaninNum(pNode) != 2 )
+        return 0;
+    if ( Abc_NtkHasSop(pNtk) )
+	return ( !strcmp(((char *)pNode->pData), "-0 1\n0- 1\n") || 
+		 !strcmp(((char *)pNode->pData), "0- 1\n-0 1\n") || 
+		 !strcmp(((char *)pNode->pData), "11 0\n") );
+    if ( Abc_NtkHasMapping(pNtk) )
+        return pNode->pData == (void *)Mio_LibraryReadNand2((Mio_Library_t *)Abc_FrameReadLibGen());
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Test is the node is nand2.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeIsNor2( Abc_Obj_t * pNode )
+{
+    Abc_Ntk_t * pNtk = pNode->pNtk;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_ObjIsNode(pNode) ); 
+    if ( Abc_ObjFaninNum(pNode) != 2 )
+        return 0;
+    if ( Abc_NtkHasSop(pNtk) )
+        return ( !strcmp(((char *)pNode->pData), "00 1\n") );
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Test is the node is and2.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeIsAnd2( Abc_Obj_t * pNode )
+{
+    Abc_Ntk_t * pNtk = pNode->pNtk;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_ObjIsNode(pNode) ); 
+    if ( Abc_ObjFaninNum(pNode) != 2 )
+        return 0;
+    if ( Abc_NtkHasSop(pNtk) )
+	return Abc_SopIsAndType(((char *)pNode->pData));
+    if ( Abc_NtkHasMapping(pNtk) )
+        return pNode->pData == (void *)Mio_LibraryReadAnd2((Mio_Library_t *)Abc_FrameReadLibGen());
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Test is the node is or2.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeIsOr2( Abc_Obj_t * pNode )
+{
+    Abc_Ntk_t * pNtk = pNode->pNtk;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_ObjIsNode(pNode) ); 
+    if ( Abc_ObjFaninNum(pNode) != 2 )
+        return 0;
+    if ( Abc_NtkHasSop(pNtk) )
+	return ( Abc_SopIsOrType(((char *)pNode->pData))   || 
+		 !strcmp(((char *)pNode->pData), "01 0\n") ||
+		 !strcmp(((char *)pNode->pData), "10 0\n") ||
+		 !strcmp(((char *)pNode->pData), "00 0\n") );
+		 //off-sets, too
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Test is the node is xor2.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeIsXor2( Abc_Obj_t * pNode )
+{
+    Abc_Ntk_t * pNtk = pNode->pNtk;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_ObjIsNode(pNode) ); 
+    if ( Abc_ObjFaninNum(pNode) != 2 )
+        return 0;
+    if ( Abc_NtkHasSop(pNtk) )
+	return ( !strcmp(((char *)pNode->pData), "01 1\n10 1\n") || !strcmp(((char *)pNode->pData), "10 1\n01 1\n")  );
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Test is the node is xnor2.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeIsXnor2( Abc_Obj_t * pNode )
+{
+    Abc_Ntk_t * pNtk = pNode->pNtk;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_ObjIsNode(pNode) ); 
+    if ( Abc_ObjFaninNum(pNode) != 2 )
+        return 0;
+    if ( Abc_NtkHasSop(pNtk) )
+	return ( !strcmp(((char *)pNode->pData), "11 1\n00 1\n") || !strcmp(((char *)pNode->pData), "00 1\n11 1\n") );
+    assert( 0 );
+    return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioWriteCnf.c b/abc-build/src/base/io/ioWriteCnf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioWriteCnf.c
@@ -0,0 +1,120 @@
+/**CFile****************************************************************
+
+  FileName    [ioWriteCnf.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to output CNF of the miter cone.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioWriteCnf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+#include "sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+static Abc_Ntk_t * s_pNtk = NULL;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Write the miter cone into a CNF file for the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_WriteCnf( Abc_Ntk_t * pNtk, char * pFileName, int fAllPrimes )
+{
+    sat_solver * pSat;
+    if ( Abc_NtkIsStrash(pNtk) )
+        printf( "Io_WriteCnf() warning: Generating CNF by applying heuristic AIG to CNF conversion.\n" );
+    else
+        printf( "Io_WriteCnf() warning: Generating CNF by convering logic nodes into CNF clauses.\n" );
+    if ( Abc_NtkPoNum(pNtk) != 1 )
+    {
+        fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter (the network with one PO).\n" );
+        return 0;
+    }
+    if ( Abc_NtkLatchNum(pNtk) != 0 )
+    {
+        fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter for combinational circuits.\n" );
+        return 0;
+    }
+    if ( Abc_NtkNodeNum(pNtk) == 0 )
+    {
+        fprintf( stdout, "The network has no logic nodes. No CNF file is generaled.\n" );
+        return 0;
+    }
+    // convert to logic BDD network
+    if ( Abc_NtkIsLogic(pNtk) )
+        Abc_NtkToBdd( pNtk );
+    // create solver with clauses
+    pSat = (sat_solver *)Abc_NtkMiterSatCreate( pNtk, fAllPrimes );
+    if ( pSat == NULL )
+    {
+        fprintf( stdout, "The problem is trivially UNSAT. No CNF file is generated.\n" );
+        return 1;
+    }        
+    // write the clauses
+    s_pNtk = pNtk;
+    Sat_SolverWriteDimacs( pSat, pFileName, 0, 0, 1 );
+    s_pNtk = NULL;
+    // free the solver
+    sat_solver_delete( pSat );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Output the mapping of PIs into variable numbers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteCnfOutputPiMapping( FILE * pFile, int incrementVars )
+{
+    extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk );
+    Abc_Ntk_t * pNtk = s_pNtk;
+    Vec_Int_t * vCiIds;
+    Abc_Obj_t * pObj;
+    int i;
+    vCiIds = Abc_NtkGetCiSatVarNums( pNtk );
+    fprintf( pFile, "c PI variable numbers: <PI_name> <SAT_var_number>\n" );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        fprintf( pFile, "c %s %d\n", Abc_ObjName(pObj), Vec_IntEntry(vCiIds, i) + (int)(incrementVars > 0) );
+    Vec_IntFree( vCiIds );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioWriteDot.c b/abc-build/src/base/io/ioWriteDot.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioWriteDot.c
@@ -0,0 +1,854 @@
+/**CFile****************************************************************
+
+  FileName    [ioWriteDot.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to write the graph structure of AIG in DOT.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioWriteDot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+#include "base/main/main.h"
+#include "map/mio/mio.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static char * Abc_NtkPrintSop( char * pSop );
+static int    Abc_NtkCountLogicNodes( Vec_Ptr_t * vNodes );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the graph structure of network for DOT.]
+
+  Description [Useful for graph visualization using tools such as GraphViz: 
+  http://www.graphviz.org/]
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteDot( Abc_Ntk_t * pNtk, char * FileName )
+{
+    Vec_Ptr_t * vNodes;
+    vNodes = Abc_NtkCollectObjects( pNtk );
+    Io_WriteDotNtk( pNtk, vNodes, NULL, FileName, 0, 0 );
+    Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the graph structure of network for DOT.]
+
+  Description [Useful for graph visualization using tools such as GraphViz: 
+  http://www.graphviz.org/]
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse )
+{
+    FILE * pFile;
+    Abc_Obj_t * pNode, * pFanin;
+    char * pSopString;
+    int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl, Prev;
+    int Limit = 300;
+
+    assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) );
+
+    if ( vNodes->nSize < 1 )
+    {
+        printf( "The set has no nodes. DOT file is not written.\n" );
+        return;
+    }
+
+    if ( vNodes->nSize > Limit )
+    {
+        printf( "The set has more than %d nodes. DOT file is not written.\n", Limit );
+        return;
+    }
+
+    // start the stream
+    if ( (pFile = fopen( pFileName, "w" )) == NULL )
+    {
+        fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName );
+        return;
+    }
+
+    // transform logic functions from BDD to SOP
+    if ( (fHasBdds = Abc_NtkIsBddLogic(pNtk)) )
+    {
+        if ( !Abc_NtkBddToSop(pNtk, 0) )
+        {
+            printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" );
+            return;
+        }
+    }
+
+    // mark the nodes from the set
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        pNode->fMarkC = 1;
+    if ( vNodesShow )
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodesShow, pNode, i )
+            pNode->fMarkB = 1;
+
+    // get the levels of nodes
+    LevelMax = Abc_NtkLevel( pNtk );
+    if ( fUseReverse )
+    {
+        LevelMin = Abc_NtkLevelReverse( pNtk );
+        assert( LevelMax == LevelMin );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+            if ( Abc_ObjIsNode(pNode) )
+                pNode->Level = LevelMax - pNode->Level + 1;
+    }
+
+    // find the largest and the smallest levels
+    LevelMin = 10000;
+    LevelMax = -1;
+    fHasCos  = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( Abc_ObjIsCo(pNode) )
+        {
+            fHasCos = 1;
+            continue;
+        }
+        if ( LevelMin > (int)pNode->Level )
+            LevelMin = pNode->Level;
+        if ( LevelMax < (int)pNode->Level )
+            LevelMax = pNode->Level;
+    }
+
+    // set the level of the CO nodes
+    if ( fHasCos )
+    {
+        LevelMax++;
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        {
+            if ( Abc_ObjIsCo(pNode) )
+                pNode->Level = LevelMax;
+        }
+    }
+
+    // write the DOT header
+    fprintf( pFile, "# %s\n",  "Network structure generated by ABC" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "digraph network {\n" );
+    fprintf( pFile, "size = \"7.5,10\";\n" );
+//    fprintf( pFile, "size = \"10,8.5\";\n" );
+//    fprintf( pFile, "size = \"14,11\";\n" );
+//    fprintf( pFile, "page = \"8,11\";\n" );
+//  fprintf( pFile, "ranksep = 0.5;\n" );
+//  fprintf( pFile, "nodesep = 0.5;\n" );
+    fprintf( pFile, "center = true;\n" );
+//    fprintf( pFile, "orientation = landscape;\n" );
+//  fprintf( pFile, "edge [fontsize = 10];\n" );
+//  fprintf( pFile, "edge [dir = none];\n" );
+    fprintf( pFile, "edge [dir = back];\n" );
+    fprintf( pFile, "\n" );
+
+    // labels on the left of the picture
+    fprintf( pFile, "{\n" );
+    fprintf( pFile, "  node [shape = plaintext];\n" );
+    fprintf( pFile, "  edge [style = invis];\n" );
+    fprintf( pFile, "  LevelTitle1 [label=\"\"];\n" );
+    fprintf( pFile, "  LevelTitle2 [label=\"\"];\n" );
+    // generate node names with labels
+    for ( Level = LevelMax; Level >= LevelMin; Level-- )
+    {
+        // the visible node name
+        fprintf( pFile, "  Level%d", Level );
+        fprintf( pFile, " [label = " );
+        // label name
+        fprintf( pFile, "\"" );
+        fprintf( pFile, "\"" );
+        fprintf( pFile, "];\n" );
+    }
+
+    // genetate the sequence of visible/invisible nodes to mark levels
+    fprintf( pFile, "  LevelTitle1 ->  LevelTitle2 ->" );
+    for ( Level = LevelMax; Level >= LevelMin; Level-- )
+    {
+        // the visible node name
+        fprintf( pFile, "  Level%d",  Level );
+        // the connector
+        if ( Level != LevelMin )
+            fprintf( pFile, " ->" );
+        else
+            fprintf( pFile, ";" );
+    }
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    // generate title box on top
+    fprintf( pFile, "{\n" );
+    fprintf( pFile, "  rank = same;\n" );
+    fprintf( pFile, "  LevelTitle1;\n" );
+    fprintf( pFile, "  title1 [shape=plaintext,\n" );
+    fprintf( pFile, "          fontsize=20,\n" );
+    fprintf( pFile, "          fontname = \"Times-Roman\",\n" );
+    fprintf( pFile, "          label=\"" );
+    fprintf( pFile, "%s", "Network structure visualized by ABC" );
+    fprintf( pFile, "\\n" );
+    fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName );
+    fprintf( pFile, "Time was %s. ",  Extra_TimeStamp() );
+    fprintf( pFile, "\"\n" );
+    fprintf( pFile, "         ];\n" );
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    // generate statistics box
+    fprintf( pFile, "{\n" );
+    fprintf( pFile, "  rank = same;\n" );
+    fprintf( pFile, "  LevelTitle2;\n" );
+    fprintf( pFile, "  title2 [shape=plaintext,\n" );
+    fprintf( pFile, "          fontsize=18,\n" );
+    fprintf( pFile, "          fontname = \"Times-Roman\",\n" );
+    fprintf( pFile, "          label=\"" );
+    if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) )
+        fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) );
+    else
+        fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 );
+    fprintf( pFile, "\\n" );
+    fprintf( pFile, "\"\n" );
+    fprintf( pFile, "         ];\n" );
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    // generate the POs
+    if ( fHasCos )
+    {
+        fprintf( pFile, "{\n" );
+        fprintf( pFile, "  rank = same;\n" );
+        // the labeling node of this level
+        fprintf( pFile, "  Level%d;\n",  LevelMax );
+        // generate the PO nodes
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        {
+            if ( !Abc_ObjIsCo(pNode) )
+                continue;
+            fprintf( pFile, "  Node%d [label = \"%s%s\"", 
+                pNode->Id, 
+                (Abc_ObjIsBi(pNode)? Abc_ObjName(Abc_ObjFanout0(pNode)):Abc_ObjName(pNode)), 
+                (Abc_ObjIsBi(pNode)? "_in":"") );
+            fprintf( pFile, ", shape = %s", (Abc_ObjIsBi(pNode)? "box":"invtriangle") );
+            if ( pNode->fMarkB )
+                fprintf( pFile, ", style = filled" );
+            fprintf( pFile, ", color = coral, fillcolor = coral" );
+            fprintf( pFile, "];\n" );
+        }
+        fprintf( pFile, "}" );
+        fprintf( pFile, "\n" );
+        fprintf( pFile, "\n" );
+    }
+
+    // generate nodes of each rank
+    for ( Level = LevelMax - fHasCos; Level >= LevelMin && Level > 0; Level-- )
+    {
+        fprintf( pFile, "{\n" );
+        fprintf( pFile, "  rank = same;\n" );
+        // the labeling node of this level
+        fprintf( pFile, "  Level%d;\n",  Level );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        {
+            if ( (int)pNode->Level != Level )
+                continue;
+            if ( Abc_ObjFaninNum(pNode) == 0 )
+                continue;
+
+/*
+            int SuppSize;
+            Vec_Ptr_t * vSupp;
+            if ( (int)pNode->Level != Level )
+                continue;
+            if ( Abc_ObjFaninNum(pNode) == 0 )
+                continue;
+            vSupp = Abc_NtkNodeSupport( pNtk, &pNode, 1 );
+            SuppSize = Vec_PtrSize( vSupp );
+            Vec_PtrFree( vSupp ); 
+*/
+
+//            fprintf( pFile, "  Node%d [label = \"%d\"", pNode->Id, pNode->Id );
+            if ( Abc_NtkIsStrash(pNtk) )
+                pSopString = "";
+            else if ( Abc_NtkHasMapping(pNtk) && fGateNames )
+                pSopString = Mio_GateReadName((Mio_Gate_t *)pNode->pData);
+            else if ( Abc_NtkHasMapping(pNtk) )
+                pSopString = Abc_NtkPrintSop(Mio_GateReadSop((Mio_Gate_t *)pNode->pData));
+            else
+                pSopString = Abc_NtkPrintSop((char *)pNode->pData);
+            fprintf( pFile, "  Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString );
+//            fprintf( pFile, "  Node%d [label = \"%d\\n%s\"", pNode->Id, 
+//                SuppSize, 
+//                pSopString );
+
+            fprintf( pFile, ", shape = ellipse" );
+            if ( pNode->fMarkB )
+                fprintf( pFile, ", style = filled" );
+            fprintf( pFile, "];\n" );
+        }
+        fprintf( pFile, "}" );
+        fprintf( pFile, "\n" );
+        fprintf( pFile, "\n" );
+    }
+
+    // generate the PI nodes if any
+    if ( LevelMin == 0 )
+    {
+        fprintf( pFile, "{\n" );
+        fprintf( pFile, "  rank = same;\n" );
+        // the labeling node of this level
+        fprintf( pFile, "  Level%d;\n",  LevelMin );
+        // generate the PO nodes
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        {
+            if ( !Abc_ObjIsCi(pNode) )
+            {
+                // check if the costant node is present
+                if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 )
+                {
+                    fprintf( pFile, "  Node%d [label = \"Const%d\"", pNode->Id, Abc_NtkIsStrash(pNode->pNtk) || Abc_NodeIsConst1(pNode) );
+                    fprintf( pFile, ", shape = ellipse" );
+                    if ( pNode->fMarkB )
+                        fprintf( pFile, ", style = filled" );
+                    fprintf( pFile, ", color = coral, fillcolor = coral" );
+                    fprintf( pFile, "];\n" );
+                }
+                continue;
+            }
+            fprintf( pFile, "  Node%d [label = \"%s\"", 
+                pNode->Id, 
+                (Abc_ObjIsBo(pNode)? Abc_ObjName(Abc_ObjFanin0(pNode)):Abc_ObjName(pNode)) );
+            fprintf( pFile, ", shape = %s", (Abc_ObjIsBo(pNode)? "box":"triangle") );
+            if ( pNode->fMarkB )
+                fprintf( pFile, ", style = filled" );
+            fprintf( pFile, ", color = coral, fillcolor = coral" );
+            fprintf( pFile, "];\n" );
+        }
+        fprintf( pFile, "}" );
+        fprintf( pFile, "\n" );
+        fprintf( pFile, "\n" );
+    }
+
+    // generate invisible edges from the square down
+    fprintf( pFile, "title1 -> title2 [style = invis];\n" );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( (int)pNode->Level != LevelMax )
+            continue;
+        fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id );
+    }
+    // generate invisible edges among the COs
+    Prev = -1;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( (int)pNode->Level != LevelMax )
+            continue;
+        if ( !Abc_ObjIsPo(pNode) )
+            continue;
+        if ( Prev >= 0 )
+            fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, pNode->Id );
+        Prev = pNode->Id;
+    }
+
+    // generate edges
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( Abc_ObjIsLatch(pNode) )
+            continue;
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+        {
+            if ( Abc_ObjIsLatch(pFanin) )
+                continue;
+            fCompl = 0;
+            if ( Abc_NtkIsStrash(pNtk) )
+                fCompl = Abc_ObjFaninC(pNode, k);
+            // generate the edge from this node to the next
+            fprintf( pFile, "Node%d",  pNode->Id );
+            fprintf( pFile, " -> " );
+            fprintf( pFile, "Node%d",  pFanin->Id );
+            fprintf( pFile, " [style = %s", fCompl? "dotted" : "bold" );
+//            fprintf( pFile, ", label = \"%c\"", 'a' + k );
+            fprintf( pFile, "]" );
+            fprintf( pFile, ";\n" );
+        }
+    }
+
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+    fclose( pFile );
+
+    // unmark the nodes from the set
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        pNode->fMarkC = 0;
+    if ( vNodesShow )
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodesShow, pNode, i )
+            pNode->fMarkB = 0;
+
+    // convert the network back into BDDs if this is how it was
+    if ( fHasBdds )
+        Abc_NtkSopToBdd(pNtk);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the graph structure of network for DOT.]
+
+  Description [Useful for graph visualization using tools such as GraphViz: 
+  http://www.graphviz.org/]
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse )
+{
+    FILE * pFile;
+    Abc_Obj_t * pNode, * pFanin;
+    char * pSopString;
+    int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl, Prev;
+    int Limit = 300;
+
+    assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) );
+
+    if ( vNodes->nSize < 1 )
+    {
+        printf( "The set has no nodes. DOT file is not written.\n" );
+        return;
+    }
+
+    if ( vNodes->nSize > Limit )
+    {
+        printf( "The set has more than %d nodes. DOT file is not written.\n", Limit );
+        return;
+    }
+
+    // start the stream
+    if ( (pFile = fopen( pFileName, "w" )) == NULL )
+    {
+        fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName );
+        return;
+    }
+
+    // transform logic functions from BDD to SOP
+    if ( (fHasBdds = Abc_NtkIsBddLogic(pNtk)) )
+    {
+        if ( !Abc_NtkBddToSop(pNtk, 0) )
+        {
+            printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" );
+            return;
+        }
+    }
+
+    // mark the nodes from the set
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        pNode->fMarkC = 1;
+    if ( vNodesShow )
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodesShow, pNode, i )
+            pNode->fMarkB = 1;
+
+    // get the levels of nodes
+    LevelMax = Abc_NtkLevel( pNtk );
+    if ( fUseReverse )
+    {
+        LevelMin = Abc_NtkLevelReverse( pNtk );
+        assert( LevelMax == LevelMin );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+            if ( Abc_ObjIsNode(pNode) )
+                pNode->Level = LevelMax - pNode->Level + 1;
+    }
+
+    // find the largest and the smallest levels
+    LevelMin = 10000;
+    LevelMax = -1;
+    fHasCos  = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( Abc_ObjIsCo(pNode) )
+        {
+            fHasCos = 1;
+            continue;
+        }
+        if ( LevelMin > (int)pNode->Level )
+            LevelMin = pNode->Level;
+        if ( LevelMax < (int)pNode->Level )
+            LevelMax = pNode->Level;
+    }
+
+    // set the level of the CO nodes
+    if ( fHasCos )
+    {
+        LevelMax++;
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        {
+            if ( Abc_ObjIsCo(pNode) )
+                pNode->Level = LevelMax;
+        }
+    }
+
+    // write the DOT header
+    fprintf( pFile, "# %s\n",  "Network structure generated by ABC" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "digraph network {\n" );
+    fprintf( pFile, "size = \"7.5,10\";\n" );
+//    fprintf( pFile, "size = \"10,8.5\";\n" );
+//    fprintf( pFile, "size = \"14,11\";\n" );
+//    fprintf( pFile, "page = \"8,11\";\n" );
+//  fprintf( pFile, "ranksep = 0.5;\n" );
+//  fprintf( pFile, "nodesep = 0.5;\n" );
+    fprintf( pFile, "center = true;\n" );
+//    fprintf( pFile, "orientation = landscape;\n" );
+//  fprintf( pFile, "edge [fontsize = 10];\n" );
+//  fprintf( pFile, "edge [dir = none];\n" );
+    fprintf( pFile, "edge [dir = back];\n" );
+    fprintf( pFile, "\n" );
+
+    // labels on the left of the picture
+    fprintf( pFile, "{\n" );
+    fprintf( pFile, "  node [shape = plaintext];\n" );
+    fprintf( pFile, "  edge [style = invis];\n" );
+    fprintf( pFile, "  LevelTitle1 [label=\"\"];\n" );
+    fprintf( pFile, "  LevelTitle2 [label=\"\"];\n" );
+    // generate node names with labels
+    for ( Level = LevelMax; Level >= LevelMin; Level-- )
+    {
+        // the visible node name
+        fprintf( pFile, "  Level%d", Level );
+        fprintf( pFile, " [label = " );
+        // label name
+        fprintf( pFile, "\"" );
+        fprintf( pFile, "\"" );
+        fprintf( pFile, "];\n" );
+    }
+
+    // genetate the sequence of visible/invisible nodes to mark levels
+    fprintf( pFile, "  LevelTitle1 ->  LevelTitle2 ->" );
+    for ( Level = LevelMax; Level >= LevelMin; Level-- )
+    {
+        // the visible node name
+        fprintf( pFile, "  Level%d",  Level );
+        // the connector
+        if ( Level != LevelMin )
+            fprintf( pFile, " ->" );
+        else
+            fprintf( pFile, ";" );
+    }
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    // generate title box on top
+    fprintf( pFile, "{\n" );
+    fprintf( pFile, "  rank = same;\n" );
+    fprintf( pFile, "  LevelTitle1;\n" );
+    fprintf( pFile, "  title1 [shape=plaintext,\n" );
+    fprintf( pFile, "          fontsize=20,\n" );
+    fprintf( pFile, "          fontname = \"Times-Roman\",\n" );
+    fprintf( pFile, "          label=\"" );
+    fprintf( pFile, "%s", "Network structure visualized by ABC" );
+    fprintf( pFile, "\\n" );
+    fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName );
+    fprintf( pFile, "Time was %s. ",  Extra_TimeStamp() );
+    fprintf( pFile, "\"\n" );
+    fprintf( pFile, "         ];\n" );
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    // generate statistics box
+    fprintf( pFile, "{\n" );
+    fprintf( pFile, "  rank = same;\n" );
+    fprintf( pFile, "  LevelTitle2;\n" );
+    fprintf( pFile, "  title2 [shape=plaintext,\n" );
+    fprintf( pFile, "          fontsize=18,\n" );
+    fprintf( pFile, "          fontname = \"Times-Roman\",\n" );
+    fprintf( pFile, "          label=\"" );
+    if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) )
+        fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) );
+    else
+        fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 );
+    fprintf( pFile, "\\n" );
+    fprintf( pFile, "\"\n" );
+    fprintf( pFile, "         ];\n" );
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    // generate the POs
+    if ( fHasCos )
+    {
+        fprintf( pFile, "{\n" );
+        fprintf( pFile, "  rank = same;\n" );
+        // the labeling node of this level
+        fprintf( pFile, "  Level%d;\n",  LevelMax );
+        // generate the PO nodes
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        {
+            if ( !Abc_ObjIsPo(pNode) )
+                continue;
+            fprintf( pFile, "  Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) );
+            fprintf( pFile, ", shape = %s", "invtriangle" );
+            if ( pNode->fMarkB )
+                fprintf( pFile, ", style = filled" );
+            fprintf( pFile, ", color = coral, fillcolor = coral" );
+            fprintf( pFile, "];\n" );
+        }
+        fprintf( pFile, "}" );
+        fprintf( pFile, "\n" );
+        fprintf( pFile, "\n" );
+    }
+
+    // generate nodes of each rank
+    for ( Level = LevelMax - fHasCos; Level >= LevelMin && Level > 0; Level-- )
+    {
+        fprintf( pFile, "{\n" );
+        fprintf( pFile, "  rank = same;\n" );
+        // the labeling node of this level
+        fprintf( pFile, "  Level%d;\n",  Level );
+        Abc_NtkForEachNode( pNtk, pNode, i )
+        {
+            if ( (int)pNode->Level != Level )
+                continue;
+//            fprintf( pFile, "  Node%d [label = \"%d\"", pNode->Id, pNode->Id );
+            if ( Abc_NtkIsStrash(pNtk) )
+                pSopString = "";
+            else if ( Abc_NtkHasMapping(pNtk) && fGateNames )
+                pSopString = Mio_GateReadName((Mio_Gate_t *)pNode->pData);
+            else if ( Abc_NtkHasMapping(pNtk) )
+                pSopString = Abc_NtkPrintSop(Mio_GateReadSop((Mio_Gate_t *)pNode->pData));
+            else
+                pSopString = Abc_NtkPrintSop((char *)pNode->pData);
+            fprintf( pFile, "  Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString );
+
+            fprintf( pFile, ", shape = ellipse" );
+            if ( pNode->fMarkB )
+                fprintf( pFile, ", style = filled" );
+            fprintf( pFile, "];\n" );
+        }
+        fprintf( pFile, "}" );
+        fprintf( pFile, "\n" );
+        fprintf( pFile, "\n" );
+    }
+
+    // generate the PI nodes if any
+    if ( LevelMin == 0 )
+    {
+        fprintf( pFile, "{\n" );
+        fprintf( pFile, "  rank = same;\n" );
+        // the labeling node of this level
+        fprintf( pFile, "  Level%d;\n",  LevelMin );
+        // generate the PO nodes
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        {
+            if ( pNode->Level > 0 )
+                continue;
+            if ( !Abc_ObjIsPi(pNode) )
+            {
+                // check if the costant node is present
+                if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 )
+                {
+                    fprintf( pFile, "  Node%d [label = \"Const1\"", pNode->Id );
+                    fprintf( pFile, ", shape = ellipse" );
+                    if ( pNode->fMarkB )
+                        fprintf( pFile, ", style = filled" );
+                    fprintf( pFile, ", color = coral, fillcolor = coral" );
+                    fprintf( pFile, "];\n" );
+                }
+                continue;
+            }
+            fprintf( pFile, "  Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) );
+            fprintf( pFile, ", shape = %s", "triangle" );
+            if ( pNode->fMarkB )
+                fprintf( pFile, ", style = filled" );
+            fprintf( pFile, ", color = coral, fillcolor = coral" );
+            fprintf( pFile, "];\n" );
+        }
+        fprintf( pFile, "}" );
+        fprintf( pFile, "\n" );
+        fprintf( pFile, "\n" );
+    }
+
+//    fprintf( pFile, "{\n" );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( !Abc_ObjIsLatch(pNode) )
+            continue;
+        fprintf( pFile, "Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) );
+        fprintf( pFile, ", shape = box" );
+        if ( pNode->fMarkB )
+            fprintf( pFile, ", style = filled" );
+        fprintf( pFile, ", color = coral, fillcolor = coral" );
+        fprintf( pFile, "];\n" );
+    }
+//    fprintf( pFile, "}" );
+//    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+
+    // generate invisible edges from the square down
+    fprintf( pFile, "title1 -> title2 [style = invis];\n" );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( (int)pNode->Level != LevelMax )
+            continue;
+        if ( !Abc_ObjIsPo(pNode) )
+            continue;
+        fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id );
+    }
+    // generate invisible edges among the COs
+    Prev = -1;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( (int)pNode->Level != LevelMax )
+            continue;
+        if ( !Abc_ObjIsPo(pNode) )
+            continue;
+        if ( Prev >= 0 )
+            fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, pNode->Id );
+        Prev = pNode->Id;
+    }
+
+    // generate edges
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( Abc_ObjIsBi(pNode) || Abc_ObjIsBo(pNode) )
+            continue;
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+        {
+            fCompl = 0;
+            if ( Abc_NtkIsStrash(pNtk) )
+            {
+                if ( Abc_ObjIsBi(pFanin) )
+                    fCompl = Abc_ObjFaninC(pFanin, k);
+                else
+                    fCompl = Abc_ObjFaninC(pNode, k);
+            }
+            if ( Abc_ObjIsBi(pFanin) || Abc_ObjIsBo(pFanin) )
+                pFanin = Abc_ObjFanin0(pFanin);
+            if ( Abc_ObjIsBi(pFanin) || Abc_ObjIsBo(pFanin) )
+                pFanin = Abc_ObjFanin0(pFanin);
+            if ( !pFanin->fMarkC )
+                continue;
+
+            // generate the edge from this node to the next
+            fprintf( pFile, "Node%d",  pNode->Id );
+            fprintf( pFile, " -> " );
+            fprintf( pFile, "Node%d",  pFanin->Id );
+            fprintf( pFile, " [style = %s", fCompl? "dotted" : "bold" );
+//            fprintf( pFile, ", label = \"%c\"", 'a' + k );
+            fprintf( pFile, "]" );
+            fprintf( pFile, ";\n" );
+        }
+    }
+
+    fprintf( pFile, "}" );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "\n" );
+    fclose( pFile );
+
+    // unmark the nodes from the set
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+        pNode->fMarkC = 0;
+    if ( vNodesShow )
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodesShow, pNode, i )
+            pNode->fMarkB = 0;
+
+    // convert the network back into BDDs if this is how it was
+    if ( fHasBdds )
+        Abc_NtkSopToBdd(pNtk);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the printable SOP form.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_NtkPrintSop( char * pSop ) 
+{
+    static char Buffer[1000];
+    char * pGet, * pSet;
+    pSet = Buffer;
+    for ( pGet = pSop; *pGet; pGet++ )
+    {        
+        if ( *pGet == '\n' )
+        {
+            *pSet++ = '\\';
+            *pSet++ = 'n';
+        }
+        else
+            *pSet++ = *pGet;
+    }
+    *(pSet-2) = 0;
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the printable SOP form.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCountLogicNodes( Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pObj;
+    int i, Counter = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        if ( !Abc_ObjIsNode(pObj) )
+            continue;
+        if ( Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 )
+            continue;
+        Counter ++;
+    }
+    return Counter;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioWriteEqn.c b/abc-build/src/base/io/ioWriteEqn.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioWriteEqn.c
@@ -0,0 +1,257 @@
+/**CFile****************************************************************
+
+  FileName    [ioWriteEqn.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to write equation representation of the network.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioWriteEqn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteEqnCis( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteEqnCos( FILE * pFile, Abc_Ntk_t * pNtk );
+static int Io_NtkWriteEqnCheck( Abc_Ntk_t * pNtk );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the logic network in the equation format.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName )
+{
+    FILE * pFile;
+
+    assert( Abc_NtkIsAigNetlist(pNtk) );
+    if ( Abc_NtkLatchNum(pNtk) > 0 )
+        printf( "Warning: only combinational portion is being written.\n" );
+
+    // check that the names are fine for the EQN format
+    if ( !Io_NtkWriteEqnCheck(pNtk) )
+        return;
+
+    // start the output stream
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Io_WriteEqn(): Cannot open the output file \"%s\".\n", pFileName );
+        return;
+    }
+    fprintf( pFile, "# Equations for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+
+    // write the equations for the network
+    Io_NtkWriteEqnOne( pFile, pNtk );
+	fprintf( pFile, "\n" );
+	fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write one network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    Vec_Vec_t * vLevels;
+    ProgressBar * pProgress;
+    Abc_Obj_t * pNode, * pFanin;
+    int i, k;
+
+    // write the PIs
+    fprintf( pFile, "INORDER =" );
+    Io_NtkWriteEqnCis( pFile, pNtk );
+    fprintf( pFile, ";\n" );
+
+    // write the POs
+    fprintf( pFile, "OUTORDER =" );
+    Io_NtkWriteEqnCos( pFile, pNtk );
+    fprintf( pFile, ";\n" );
+
+    // write each internal node
+    vLevels = Vec_VecAlloc( 10 );
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        fprintf( pFile, "%s = ", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+        // set the input names
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+            Hop_IthVar((Hop_Man_t *)pNtk->pManFunc, k)->pData = Abc_ObjName(pFanin);
+        // write the formula
+        Hop_ObjPrintEqn( pFile, (Hop_Obj_t *)pNode->pData, vLevels, 0 );
+        fprintf( pFile, ";\n" );
+    }
+    Extra_ProgressBarStop( pProgress );
+    Vec_VecFree( vLevels );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the primary input list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteEqnCis( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pTerm, * pNet;
+    int LineLength;
+    int AddedLength;
+    int NameCounter;
+    int i;
+
+    LineLength  = 9;
+    NameCounter = 0;
+
+    Abc_NtkForEachCi( pNtk, pTerm, i )
+    {
+        pNet = Abc_ObjFanout0(pTerm);
+        // get the line length after this name is written
+        AddedLength = strlen(Abc_ObjName(pNet)) + 1;
+        if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+        { // write the line extender
+            fprintf( pFile, " \n" );
+            // reset the line length
+            LineLength  = 0;
+            NameCounter = 0;
+        }
+        fprintf( pFile, " %s", Abc_ObjName(pNet) );
+        LineLength += AddedLength;
+        NameCounter++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the primary input list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_NtkWriteEqnCos( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pTerm, * pNet;
+    int LineLength;
+    int AddedLength;
+    int NameCounter;
+    int i;
+
+    LineLength  = 10;
+    NameCounter = 0;
+
+    Abc_NtkForEachCo( pNtk, pTerm, i )
+    {
+        pNet = Abc_ObjFanin0(pTerm);
+        // get the line length after this name is written
+        AddedLength = strlen(Abc_ObjName(pNet)) + 1;
+        if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+        { // write the line extender
+            fprintf( pFile, " \n" );
+            // reset the line length
+            LineLength  = 0;
+            NameCounter = 0;
+        }
+        fprintf( pFile, " %s", Abc_ObjName(pNet) );
+        LineLength += AddedLength;
+        NameCounter++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Make sure the network does not have offending names.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_NtkWriteEqnCheck( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    char * pName = NULL;
+    int i, k, Length;
+    int RetValue = 1;
+
+    // make sure the network does not have proper names, such as "0" or "1" or containing parantheses
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        pName = Nm_ManFindNameById(pNtk->pManName, i);
+        if ( pName == NULL )
+            continue;
+        Length = strlen(pName);
+        if ( pName[0] == '0' || pName[0] == '1' )
+        {
+            RetValue = 0;
+            break;
+        }
+        for ( k = 0; k < Length; k++ )
+            if ( pName[k] == '(' || pName[k] == ')' || pName[k] == '!' || pName[k] == '*' || pName[k] == '+' )
+            {
+                RetValue = 0;
+                break;
+            }
+        if ( k < Length )
+            break;
+    }
+    if ( RetValue == 0 )
+    {
+        printf( "The network cannot be written in the EQN format because object %d has name \"%s\".\n", i, pName );
+        printf( "Consider renaming the objects using command \"short_names\" and trying again.\n" );
+    }
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioWriteGml.c b/abc-build/src/base/io/ioWriteGml.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioWriteGml.c
@@ -0,0 +1,121 @@
+/**CFile****************************************************************
+
+  FileName    [ioWriteGml.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to write the graph structure of AIG in GML.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioWriteGml.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the graph structure of AIG in GML.]
+
+  Description [Useful for graph visualization using tools such as yEd: 
+  http://www.yworks.com/]
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName )
+{
+    FILE * pFile;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k;
+
+    assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk)  );
+
+    // start the output stream
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Io_WriteGml(): Cannot open the output file \"%s\".\n", pFileName );
+        return;
+    }
+    fprintf( pFile, "# GML for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+	fprintf( pFile, "graph [\n" );
+
+    // output the POs
+    fprintf( pFile, "\n" );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+    {
+        fprintf( pFile, "    node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) );
+        fprintf( pFile, "        graphics [ type \"triangle\" fill \"#00FFFF\" ]\n" );   // blue
+        fprintf( pFile, "    ]\n" );
+    }
+    // output the PIs
+    fprintf( pFile, "\n" );
+    Abc_NtkForEachPi( pNtk, pObj, i )
+    {
+        fprintf( pFile, "    node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) );
+        fprintf( pFile, "        graphics [ type \"triangle\" fill \"#00FF00\" ]\n" );   // green
+        fprintf( pFile, "    ]\n" );
+    }
+    // output the latches
+    fprintf( pFile, "\n" );
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+    {
+        fprintf( pFile, "    node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) );
+        fprintf( pFile, "        graphics [ type \"rectangle\" fill \"#FF0000\" ]\n" );   // red
+        fprintf( pFile, "    ]\n" );
+    }
+    // output the nodes
+    fprintf( pFile, "\n" );
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        fprintf( pFile, "    node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) );
+        fprintf( pFile, "        graphics [ type \"ellipse\" fill \"#CCCCFF\" ]\n" );     // grey
+        fprintf( pFile, "    ]\n" );
+    }
+
+    // output the edges
+    fprintf( pFile, "\n" );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+        {
+            fprintf( pFile, "    edge [ source %5d   target %5d\n", pObj->Id, pFanin->Id );
+            fprintf( pFile, "        graphics [ type \"line\" arrow \"first\" ]\n" );
+            fprintf( pFile, "    ]\n" );
+        }
+    }
+
+	fprintf( pFile, "]\n" );
+	fprintf( pFile, "\n" );
+	fclose( pFile );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioWriteList.c b/abc-build/src/base/io/ioWriteList.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioWriteList.c
@@ -0,0 +1,293 @@
+/**CFile****************************************************************
+
+  FileName    [ioWriteList.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to write the graph structure of sequential AIG.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioWriteList.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+-------- Original Message --------
+Subject: Re: abc release and retiming
+Date:    Sun, 13 Nov 2005 20:31:18 -0500 (EST)
+From:    Luca Carloni <luca@cs.columbia.edu>
+To:      Alan Mishchenko <alanmi@eecs.berkeley.edu>
+
+Alan,
+
+My graph-representation file format is based on an adjacency list
+representation and is indeed quite simple, in fact maybe too simple... I
+used it in order to reason on relatively small weighed direct graphs. I
+simply list all vertices, one per line and for each vertex "V_source" I
+list all vertices that are "sinks" with respect to it, i.e. such that
+there is a distinct arc between "V_source" and each of them (in
+paranthesis I list the name of the edge and its weight (number of latency
+on that path). For instance, if you look at the following graph, you have
+that vertex "v_5" is connected to vertex "v_6" through a directed arc
+called "v_5_to_v_6" whose latency is equal to 3, i.e. there are three
+flip-flops on this arc. Still, notice that I sometime interpret the graph
+also as the representation of a  LIS where each node corresponds to a
+shell encapsulating a sequential core module (i.e. a module which does not
+contain any combinational path between its inputs and its outputs). With
+this representation an arc of latency 3 is interpreted as a wire where two
+relay stations have been inserted in addition to the flip-flop terminating
+the output of the core module.
+
+Finally, notice that the name of the arc does not necessarily have to be
+"v_5_to_v_6", but it could have been something like "arc_222" or "xyz" as
+long as it is a unique name in the graph.
+
+Thanks,
+Luca
+
+Example of graph representation
+-----------------------------------------------------------------------------
+v_5	>	v_6 ([v_5_to_v_6] = 3), v_12 ([v_5_to_v_12] = 2).
+v_2	>	v_4 ([v_2_to_v_4] = 1), v_10_s0 ([v_2_to_v_10_s0] = 6), v_12 ([v_2_to_v_12] = 3).
+v_9	>	v_10_s0 ([v_9_to_v_10_s0] = 5), v_12 ([v_9_to_v_12] = 2).
+v_12	>	v_13 ([v_12_to_v_13] = 5).
+v_13	>	v_14 ([v_13_to_v_14] = 1).
+v_6	>	v_7 ([v_6_to_v_7] = 2).
+v_4	>	v_5 ([v_4_to_v_5] = 2).
+v_1	>	v_2 ([v_1_to_v_2] = 1).
+v_7	>	v_8 ([v_7_to_v_8] = 2).
+t	>	.
+v_14	>	t ([v_14_to_t] = 1), v_5 ([v_14_to_v_5] = 1).
+v_8	>	v_9 ([v_8_to_v_9] = 2).
+s	>	v_1 ([s_to_v_1] = 1).
+v_10_s0	>	v_10_s1 ([v_10_s0_to_v_10_s1] = 1).
+v_10_s1	>	v_4 ([v_10_s1__v_4] = 1), v_8 ([v_10_s1__v_8] = 1).
+-----------------------------------------------------------------------------
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Io_WriteListEdge( FILE * pFile, Abc_Obj_t * pObj );
+static void Io_WriteListHost( FILE * pFile, Abc_Ntk_t * pNtk );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the adjacency list for a sequential AIG.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost )
+{
+    FILE * pFile;
+    Abc_Obj_t * pObj;
+    int i;
+
+//    assert( Abc_NtkIsSeq(pNtk)  );
+
+    // start the output stream
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Io_WriteList(): Cannot open the output file \"%s\".\n", pFileName );
+        return;
+    }
+
+    fprintf( pFile, "# Adjacency list for sequential AIG \"%s\"\n", pNtk->pName );
+    fprintf( pFile, "# written by ABC on %s\n", Extra_TimeStamp() );
+
+    // write the constant node
+    if ( Abc_ObjFanoutNum( Abc_AigConst1(pNtk) ) > 0 )
+        Io_WriteListEdge( pFile, Abc_AigConst1(pNtk) );
+
+    // write the PI edges
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        Io_WriteListEdge( pFile, pObj );
+
+    // write the internal nodes
+    Abc_AigForEachAnd( pNtk, pObj, i )
+        Io_WriteListEdge( pFile, pObj );
+
+    // write the host node
+    if ( fUseHost )
+        Io_WriteListHost( pFile, pNtk );
+    else
+        Abc_NtkForEachPo( pNtk, pObj, i )
+            Io_WriteListEdge( pFile, pObj );
+
+	fprintf( pFile, "\n" );
+	fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the adjacency list for one edge in a sequential AIG.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteListEdge( FILE * pFile, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    fprintf( pFile, "%-10s >    ", Abc_ObjName(pObj) );
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+    {
+        fprintf( pFile, " %s", Abc_ObjName(pFanout) );
+        fprintf( pFile, " ([%s_to_", Abc_ObjName(pObj) );
+//        fprintf( pFile, "%s] = %d)", Abc_ObjName(pFanout), Seq_ObjFanoutL(pObj, pFanout) );
+        fprintf( pFile, "%s] = %d)", Abc_ObjName(pFanout), 0 );
+        if ( i != Abc_ObjFanoutNum(pObj) - 1 )
+            fprintf( pFile, "," );
+    }
+    fprintf( pFile, "." );
+    fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the adjacency list for one edge in a sequential AIG.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteListHost( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+
+    Abc_NtkForEachPo( pNtk, pObj, i )
+    {
+        fprintf( pFile, "%-10s >    ", Abc_ObjName(pObj) );
+        fprintf( pFile, " %s ([%s_to_%s] = %d)", "HOST", Abc_ObjName(pObj), "HOST", 0 );
+        fprintf( pFile, "." );
+        fprintf( pFile, "\n" );
+    }
+
+    fprintf( pFile, "%-10s >    ", "HOST" );
+    Abc_NtkForEachPi( pNtk, pObj, i )
+    {
+        fprintf( pFile, " %s", Abc_ObjName(pObj) );
+        fprintf( pFile, " ([%s_to_%s] = %d)", "HOST", Abc_ObjName(pObj), 0 );
+        if ( i != Abc_NtkPiNum(pNtk) - 1 )
+            fprintf( pFile, "," );
+    }
+    fprintf( pFile, "." );
+    fprintf( pFile, "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the adjacency list for a sequential AIG.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteCellNet( Abc_Ntk_t * pNtk, char * pFileName )
+{
+    FILE * pFile;
+    Abc_Obj_t * pObj, * pFanout;
+    int i, k;
+
+    assert( Abc_NtkIsLogic(pNtk)  );
+
+    // start the output stream
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Io_WriteCellNet(): Cannot open the output file \"%s\".\n", pFileName );
+        return;
+    }
+
+    fprintf( pFile, "# CellNet file for network \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+
+    // the only tricky part with writing is handling latches:
+    // each latch comes with (a) single-input latch-input node, (b) latch proper, (c) single-input latch-output node
+    // we arbitrarily decide to use the interger ID of the latch-input node to represent the latch in the file
+    // (this ID is used for both the cell and the net driven by that cell)
+
+    // write the PIs
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        fprintf( pFile, "cell %d is 0\n", pObj->Id );
+    // write the POs
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        fprintf( pFile, "cell %d is 1\n", pObj->Id );
+    // write the latches (use the ID of latch input)
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        fprintf( pFile, "cell %d is 2\n", Abc_ObjFanin0(pObj)->Id );
+    // write the logic nodes
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        fprintf( pFile, "cell %d is %d\n", pObj->Id, 3+Abc_ObjFaninNum(pObj) );
+
+    // write the nets driven by PIs
+    Abc_NtkForEachPi( pNtk, pObj, i )
+    {
+        fprintf( pFile, "net %d  %d 0", pObj->Id, pObj->Id );
+        Abc_ObjForEachFanout( pObj, pFanout, k )
+            fprintf( pFile, "  %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) );
+	    fprintf( pFile, "\n" );
+    }
+    // write the nets driven by latches
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+    {
+        fprintf( pFile, "net %d  %d 0", Abc_ObjFanin0(pObj)->Id, Abc_ObjFanin0(pObj)->Id );
+        pObj = Abc_ObjFanout0(pObj);
+        Abc_ObjForEachFanout( pObj, pFanout, k )
+            fprintf( pFile, "  %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) );
+	    fprintf( pFile, "\n" );
+    }
+    // write the nets driven by nodes
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        fprintf( pFile, "net %d  %d 0", pObj->Id, pObj->Id );
+        Abc_ObjForEachFanout( pObj, pFanout, k )
+            fprintf( pFile, "  %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) );
+	    fprintf( pFile, "\n" );
+    }
+
+	fprintf( pFile, "\n" );
+	fclose( pFile );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioWritePla.c b/abc-build/src/base/io/ioWritePla.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioWritePla.c
@@ -0,0 +1,202 @@
+/**CFile****************************************************************
+
+  FileName    [ioWritePla.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to write the network in BENCH format.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioWritePla.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int    Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the network in PLA format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_WritePla( Abc_Ntk_t * pNtk, char * pFileName )
+{
+    Abc_Ntk_t * pExdc;
+    FILE * pFile;
+
+    assert( Abc_NtkIsSopNetlist(pNtk) );
+    assert( Abc_NtkLevel(pNtk) == 1 );
+
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Io_WritePla(): Cannot open the output file.\n" );
+        return 0;
+    }
+    fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+    // write the network
+    Io_WritePlaOne( pFile, pNtk );
+    // write EXDC network if it exists
+    pExdc = Abc_NtkExdc( pNtk );
+    if ( pExdc )
+        printf( "Io_WritePla: EXDC is not written (warning).\n" );
+    // finalize the file
+    fclose( pFile );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the network in PLA format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    ProgressBar * pProgress;
+    Abc_Obj_t * pNode, * pFanin, * pDriver;
+    char * pCubeIn, * pCubeOut, * pCube;
+    int i, k, nProducts, nInputs, nOutputs, nFanins;
+
+    nProducts = 0;
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) );
+        if ( !Abc_ObjIsNode(pDriver) )
+        {
+            nProducts++;
+            continue;
+        }
+        if ( Abc_NodeIsConst(pDriver) )
+        {
+            if ( Abc_NodeIsConst1(pDriver) )
+                nProducts++;
+            continue;
+        }
+        nProducts += Abc_SopGetCubeNum((char *)pDriver->pData);
+    }
+
+    // collect the parameters
+    nInputs  = Abc_NtkCiNum(pNtk);
+    nOutputs = Abc_NtkCoNum(pNtk);
+    pCubeIn  = ABC_ALLOC( char, nInputs + 1 );
+    pCubeOut = ABC_ALLOC( char, nOutputs + 1 );
+    memset( pCubeIn,  '-', nInputs );     pCubeIn[nInputs]   = 0;
+    memset( pCubeOut, '0', nOutputs );    pCubeOut[nOutputs] = 0;
+
+    // write the header
+    fprintf( pFile, ".i %d\n", nInputs );
+    fprintf( pFile, ".o %d\n", nOutputs );
+    fprintf( pFile, ".ilb" );
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, ".ob" );
+    Abc_NtkForEachCo( pNtk, pNode, i )
+        fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pNode)) );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, ".p %d\n", nProducts );
+
+    // mark the CI nodes
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        pNode->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)i;
+
+    // write the cubes
+    pProgress = Extra_ProgressBarStart( stdout, nOutputs );
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        // prepare the output cube
+        if ( i - 1 >= 0 )
+            pCubeOut[i-1] = '0';
+        pCubeOut[i] = '1';
+
+        // consider special cases of nodes
+        pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) );
+        if ( !Abc_ObjIsNode(pDriver) )
+        {
+            assert( Abc_ObjIsCi(pDriver) );
+            pCubeIn[(int)(ABC_PTRUINT_T)pDriver->pCopy] = '1' - Abc_ObjFaninC0(pNode);
+            fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut );
+            pCubeIn[(int)(ABC_PTRUINT_T)pDriver->pCopy] = '-';
+            continue;
+        }
+        if ( Abc_NodeIsConst(pDriver) )
+        {
+            if ( Abc_NodeIsConst1(pDriver) )
+                fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut );
+            continue;
+        }
+
+        // make sure the cover is not complemented
+        assert( !Abc_SopIsComplement( (char *)pDriver->pData ) );
+
+        // write the cubes
+        nFanins = Abc_ObjFaninNum(pDriver);
+        Abc_SopForEachCube( (char *)pDriver->pData, nFanins, pCube )
+        {
+            Abc_ObjForEachFanin( pDriver, pFanin, k )
+            {
+                pFanin = Abc_ObjFanin0Ntk(pFanin);
+                assert( (int)(ABC_PTRUINT_T)pFanin->pCopy < nInputs );
+                pCubeIn[(int)(ABC_PTRUINT_T)pFanin->pCopy] = pCube[k];
+            }
+            fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut );
+        }
+        // clean the cube for future writing
+        Abc_ObjForEachFanin( pDriver, pFanin, k )
+        {
+            pFanin = Abc_ObjFanin0Ntk(pFanin);
+            assert( Abc_ObjIsCi(pFanin) );
+            pCubeIn[(int)(ABC_PTRUINT_T)pFanin->pCopy] = '-';
+        }
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+    }
+    Extra_ProgressBarStop( pProgress );
+    fprintf( pFile, ".e\n" );
+
+    // clean the CI nodes
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        pNode->pCopy = NULL;
+    ABC_FREE( pCubeIn );
+    ABC_FREE( pCubeOut );
+    return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioWriteSmv.c b/abc-build/src/base/io/ioWriteSmv.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioWriteSmv.c
@@ -0,0 +1,265 @@
+/**CFile****************************************************************
+
+  FileName    [ioWriteSmv.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to write the network in SMV format.]
+
+  Author      [Satrajit Chatterjee]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioWriteSmv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Io_WriteSmvCheckNames( Abc_Ntk_t * pNtk );
+
+static int Io_WriteSmvOne( FILE * pFile, Abc_Ntk_t * pNtk );
+static int Io_WriteSmvOneNode( FILE * pFile, Abc_Obj_t * pNode );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+// This returns a pointer to a static area, so be careful in using results
+// of this function i.e. don't call this twice in the same printf call.
+//
+// This function replaces '|' with '_' I think abc introduces '|' when
+// flattening hierarchy. The '|' is interpreted as a or function by nusmv
+// which is unfortunate. This probably should be fixed elsewhere.
+static char *cleanUNSAFE( const char *s )
+{
+    char *t;
+    static char buffer[1024];
+    assert (strlen(s) < 1024);
+    strcpy(buffer, s);
+    for (t = buffer; *t != 0; ++t) *t = (*t == '|') ? '_' : *t;
+    return buffer;
+}
+
+static int hasPrefix(const char *needle, const char *haystack)
+{
+    return (strncmp(haystack, needle, strlen(needle)) == 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the network in SMV format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_WriteSmv( Abc_Ntk_t * pNtk, char * pFileName )
+{
+    Abc_Ntk_t * pExdc;
+    FILE * pFile;
+    assert( Abc_NtkIsSopNetlist(pNtk) );
+    if ( !Io_WriteSmvCheckNames(pNtk) )
+    {
+        fprintf( stdout, "Io_WriteSmv(): Signal names in this benchmark contain parantheses making them impossible to reproduce in the SMV format. Use \"short_names\".\n" );
+        return 0;
+    }
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Io_WriteSmv(): Cannot open the output file.\n" );
+        return 0;
+    }
+    fprintf( pFile, "-- benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+    // write the network
+    Io_WriteSmvOne( pFile, pNtk );
+    // write EXDC network if it exists
+    pExdc = Abc_NtkExdc( pNtk );
+    if ( pExdc )
+        printf( "Io_WriteSmv: EXDC is not written (warning).\n" );
+    // finalize the file
+    fclose( pFile );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the network in SMV format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_WriteSmvOne( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    ProgressBar * pProgress;
+    Abc_Obj_t * pNode;
+    int i;
+
+    // write the PIs/POs/latches
+    fprintf( pFile, "MODULE main\n");   // nusmv needs top module to be main
+    fprintf ( pFile, "\n" );
+
+    fprintf( pFile, "VAR  -- inputs\n");
+    Abc_NtkForEachPi( pNtk, pNode, i )
+        fprintf( pFile, "    %s : boolean;\n", 
+                cleanUNSAFE(Abc_ObjName(Abc_ObjFanout0(pNode))) );
+    fprintf ( pFile, "\n" );
+
+    fprintf( pFile, "VAR  -- state variables\n");
+    Abc_NtkForEachLatch( pNtk, pNode, i )
+        fprintf( pFile, "    %s : boolean;\n", 
+                cleanUNSAFE(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode)))) ); 
+    fprintf ( pFile, "\n" );
+
+    // No outputs needed for NuSMV: 
+    // TODO: Add sepcs by recognizing assume_.* and assert_.*
+    //
+    // Abc_NtkForEachPo( pNtk, pNode, i )
+    //    fprintf( pFile, "OUTPUT(%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) );
+    
+    // write internal nodes
+    fprintf( pFile, "DEFINE\n");
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        Io_WriteSmvOneNode( pFile, pNode );
+    }
+    Extra_ProgressBarStop( pProgress );
+    fprintf ( pFile, "\n" );
+
+    fprintf( pFile, "ASSIGN\n");
+    Abc_NtkForEachLatch( pNtk, pNode, i )
+    {
+        int Reset = (int)(ABC_PTRUINT_T)Abc_ObjData( pNode );
+        assert (Reset >= 1);
+        assert (Reset <= 3);
+
+        if (Reset != 3)
+        {
+            fprintf( pFile, "    init(%s) := %d;\n", 
+                cleanUNSAFE(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode)))),
+                Reset - 1); 
+        }
+        fprintf( pFile, "    next(%s) := ", 
+                cleanUNSAFE(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode)))) ); 
+        fprintf( pFile, "%s;\n", 
+                cleanUNSAFE(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pNode)))) );
+    }
+      
+    fprintf ( pFile, "\n" );
+    Abc_NtkForEachPo( pNtk, pNode, i )
+    {
+        const char *n = cleanUNSAFE(Abc_ObjName(Abc_ObjFanin0(pNode)));
+        // fprintf( pFile, "-- output %s;\n", n );
+        if (hasPrefix("assume_fair_", n))
+        {
+            fprintf( pFile, "FAIRNESS %s;\n", n );
+        }
+        else if (hasPrefix("Assert_", n) || 
+                hasPrefix("assert_safety_", n))
+        {
+            fprintf( pFile, "INVARSPEC %s;\n", n );
+        }
+        else if (hasPrefix("assert_fair_", n))
+        {
+            fprintf( pFile, "LTLSPEC G F %s;\n", n );
+        }
+    }
+
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the network in SMV format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_WriteSmvOneNode( FILE * pFile, Abc_Obj_t * pNode )
+{
+    int nFanins;
+
+    assert( Abc_ObjIsNode(pNode) );
+    nFanins = Abc_ObjFaninNum(pNode);
+    if ( nFanins == 0 )
+    {   // write the constant 1 node
+        assert( Abc_NodeIsConst1(pNode) );
+        fprintf( pFile, "    %s", cleanUNSAFE(Abc_ObjName(Abc_ObjFanout0(pNode)) ) );
+        fprintf( pFile, " := 1;\n" );
+    }
+    else if ( nFanins == 1 )
+    {   // write the interver/buffer
+        if ( Abc_NodeIsBuf(pNode) )
+        {
+            fprintf( pFile, "    %s := ", cleanUNSAFE(Abc_ObjName(Abc_ObjFanout0(pNode))) );
+            fprintf( pFile, "%s;\n",      cleanUNSAFE(Abc_ObjName(Abc_ObjFanin0(pNode))) );
+        }
+        else
+        {
+            fprintf( pFile, "    %s := !",  cleanUNSAFE(Abc_ObjName(Abc_ObjFanout0(pNode))) );
+            fprintf( pFile, "%s;\n",       cleanUNSAFE(Abc_ObjName(Abc_ObjFanin0(pNode))) );
+        }
+    }
+    else
+    {   // write the AND gate
+        fprintf( pFile, "    %s", cleanUNSAFE(Abc_ObjName(Abc_ObjFanout0(pNode))) );
+        fprintf( pFile, " := %s & ", cleanUNSAFE(Abc_ObjName(Abc_ObjFanin0(pNode))) );
+        fprintf( pFile, "%s;\n", cleanUNSAFE(Abc_ObjName(Abc_ObjFanin1(pNode))) );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the names cannot be written into the bench file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_WriteSmvCheckNames( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    char * pName;
+    int i;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        for ( pName = Nm_ManFindNameById(pNtk->pManName, i); pName && *pName; pName++ )
+            if ( *pName == '(' || *pName == ')' )
+                return 0;
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/ioWriteVerilog.c b/abc-build/src/base/io/ioWriteVerilog.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/ioWriteVerilog.c
@@ -0,0 +1,649 @@
+/**CFile****************************************************************
+
+  FileName    [ioWriteVerilog.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Command processing package.]
+
+  Synopsis    [Procedures to output a special subset of Verilog.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ioWriteVerilog.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+#include "base/main/main.h"
+#include "map/mio/mio.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start );
+static void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start );
+static void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start );
+static void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start );
+static void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk );
+static int  Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk );
+static char * Io_WriteVerilogGetName( char * pName );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Write verilog.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * pFileName )
+{
+    Abc_Ntk_t * pNetlist;
+    FILE * pFile;
+    int i;
+    // can only write nodes represented using local AIGs
+    if ( !Abc_NtkIsAigNetlist(pNtk) && !Abc_NtkIsMappedNetlist(pNtk) )
+    {
+        printf( "Io_WriteVerilog(): Can produce Verilog for mapped or AIG netlists only.\n" );
+        return;
+    }
+    // start the output stream
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        fprintf( stdout, "Io_WriteVerilog(): Cannot open the output file \"%s\".\n", pFileName );
+        return;
+    }
+
+    // write the equations for the network
+    fprintf( pFile, "// Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+	fprintf( pFile, "\n" );
+
+    // write modules
+    if ( pNtk->pDesign )
+    {
+        // write the network first
+        Io_WriteVerilogInt( pFile, pNtk );
+        // write other things
+        Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pNetlist, i )
+        {
+            assert( Abc_NtkIsNetlist(pNetlist) );
+            if ( pNetlist == pNtk )
+                continue;
+	        fprintf( pFile, "\n" );
+            Io_WriteVerilogInt( pFile, pNetlist );
+        }
+    }
+    else
+    {
+        Io_WriteVerilogInt( pFile, pNtk );
+    }
+
+	fprintf( pFile, "\n" );
+	fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes verilog.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    // write inputs and outputs
+//    fprintf( pFile, "module %s ( gclk,\n   ", Abc_NtkName(pNtk) );
+    fprintf( pFile, "module %s ( ", Io_WriteVerilogGetName(Abc_NtkName(pNtk)) );
+    // add the clock signal if it does not exist
+    if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 )
+        fprintf( pFile, "clock, " );
+    // write other primary inputs
+    fprintf( pFile, "\n   " );
+    if ( Abc_NtkPiNum(pNtk) > 0  )
+    {
+        Io_WriteVerilogPis( pFile, pNtk, 3 );
+        fprintf( pFile, ",\n   " );
+    }
+    if ( Abc_NtkPoNum(pNtk) > 0  )
+        Io_WriteVerilogPos( pFile, pNtk, 3 );
+    fprintf( pFile, "  );\n" );
+    // add the clock signal if it does not exist
+    if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 )
+        fprintf( pFile, "  input  clock;\n" );
+    // write inputs, outputs, registers, and wires
+    if ( Abc_NtkPiNum(pNtk) > 0  )
+    {
+//        fprintf( pFile, "  input gclk," );
+        fprintf( pFile, "  input " );
+        Io_WriteVerilogPis( pFile, pNtk, 10 );
+        fprintf( pFile, ";\n" );
+    }
+    if ( Abc_NtkPoNum(pNtk) > 0  )
+    {
+        fprintf( pFile, "  output" );
+        Io_WriteVerilogPos( pFile, pNtk, 5 );
+        fprintf( pFile, ";\n" );
+    }
+    // if this is not a blackbox, write internal signals
+    if ( !Abc_NtkHasBlackbox(pNtk) )
+    {
+        if ( Abc_NtkLatchNum(pNtk) > 0 )
+        {
+            fprintf( pFile, "  reg" );
+            Io_WriteVerilogRegs( pFile, pNtk, 4 );
+            fprintf( pFile, ";\n" );
+        }
+        if ( Io_WriteVerilogWiresCount(pNtk) > 0 )
+        {
+            fprintf( pFile, "  wire" );
+            Io_WriteVerilogWires( pFile, pNtk, 4 );
+            fprintf( pFile, ";\n" );
+        }
+        // write nodes
+        Io_WriteVerilogObjects( pFile, pNtk );        
+        // write registers
+        if ( Abc_NtkLatchNum(pNtk) > 0 )
+            Io_WriteVerilogLatches( pFile, pNtk );
+    }
+    // finalize the file
+    fprintf( pFile, "endmodule\n\n" );
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the primary inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start )
+{
+    Abc_Obj_t * pTerm, * pNet;
+    int LineLength;
+    int AddedLength;
+    int NameCounter;
+    int i;
+
+    LineLength  = Start;
+    NameCounter = 0;
+    Abc_NtkForEachPi( pNtk, pTerm, i )
+    {
+        pNet = Abc_ObjFanout0(pTerm);
+        // get the line length after this name is written
+        AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
+        if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+        { // write the line extender
+            fprintf( pFile, "\n   " );
+            // reset the line length
+            LineLength  = 3;
+            NameCounter = 0;
+        }
+        fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (i==Abc_NtkPiNum(pNtk)-1)? "" : "," );
+        LineLength += AddedLength;
+        NameCounter++;
+    }
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the primary outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start )
+{
+    Abc_Obj_t * pTerm, * pNet, * pSkip;
+    int LineLength;
+    int AddedLength;
+    int NameCounter;
+    int i;
+    int nskip;
+
+    pSkip = 0;
+    nskip = 0;
+
+    LineLength  = Start;
+    NameCounter = 0;
+    Abc_NtkForEachPo( pNtk, pTerm, i )
+    {
+        pNet = Abc_ObjFanin0(pTerm);
+        
+        if ( Abc_ObjIsPi(Abc_ObjFanin0(pNet)) )
+        {
+            // Skip this output since it is a feedthrough -- the same
+            // name will appear as an input and an output which other
+            // tools reading verilog do not like.
+            
+            nskip++;
+            pSkip = pNet;   // save an example of skipped net
+            continue;
+        }
+        
+        // get the line length after this name is written
+        AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
+        if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+        { // write the line extender
+            fprintf( pFile, "\n   " );
+            // reset the line length
+            LineLength  = 3;
+            NameCounter = 0;
+        }
+        fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (i==Abc_NtkPoNum(pNtk)-1)? "" : "," );
+        LineLength += AddedLength;
+        NameCounter++;
+    }
+
+    if (nskip != 0)
+    {
+        assert (pSkip);
+        printf( "Io_WriteVerilogPos(): Omitted %d feedthrough nets from output list of module (e.g. %s).\n", nskip, Abc_ObjName(pSkip) );
+        return;
+    }
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the wires.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start )
+{
+    Abc_Obj_t * pObj, * pNet, * pBox, * pTerm;
+    int LineLength;
+    int AddedLength;
+    int NameCounter;
+    int i, k, Counter, nNodes;
+
+    // count the number of wires
+    nNodes = Io_WriteVerilogWiresCount( pNtk );
+
+    // write the wires
+    Counter = 0;
+    LineLength  = Start;
+    NameCounter = 0;
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        if ( i == 0 ) 
+            continue;
+        pNet = Abc_ObjFanout0(pObj);
+        if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) )
+            continue;
+        Counter++;
+        // get the line length after this name is written
+        AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
+        if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+        { // write the line extender
+            fprintf( pFile, "\n   " );
+            // reset the line length
+            LineLength  = 3;
+            NameCounter = 0;
+        }
+        fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," );
+        LineLength += AddedLength;
+        NameCounter++;
+    }
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+    {
+        pNet = Abc_ObjFanin0(Abc_ObjFanin0(pObj));
+        Counter++;
+        // get the line length after this name is written
+        AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
+        if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+        { // write the line extender
+            fprintf( pFile, "\n   " );
+            // reset the line length
+            LineLength  = 3;
+            NameCounter = 0;
+        }
+        fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," );
+        LineLength += AddedLength;
+        NameCounter++;
+    }
+    Abc_NtkForEachBox( pNtk, pBox, i )
+    {
+        if ( Abc_ObjIsLatch(pBox) )
+            continue;
+        Abc_ObjForEachFanin( pBox, pTerm, k )
+        {
+            pNet = Abc_ObjFanin0(pTerm);
+            Counter++;
+            // get the line length after this name is written
+            AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
+            if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+            { // write the line extender
+                fprintf( pFile, "\n   " );
+                // reset the line length
+                LineLength  = 3;
+                NameCounter = 0;
+            }
+            fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," );
+            LineLength += AddedLength;
+            NameCounter++;
+        }
+        Abc_ObjForEachFanout( pBox, pTerm, k )
+        {
+            pNet = Abc_ObjFanout0(pTerm);
+            if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) )
+                continue;
+            Counter++;
+            // get the line length after this name is written
+            AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
+            if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+            { // write the line extender
+                fprintf( pFile, "\n   " );
+                // reset the line length
+                LineLength  = 3;
+                NameCounter = 0;
+            }
+            fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," );
+            LineLength += AddedLength;
+            NameCounter++;
+        }
+    }
+    assert( Counter == nNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the regs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start )
+{
+    Abc_Obj_t * pLatch, * pNet;
+    int LineLength;
+    int AddedLength;
+    int NameCounter;
+    int i, Counter, nNodes;
+
+    // count the number of latches
+    nNodes = Abc_NtkLatchNum(pNtk);
+
+    // write the wires
+    Counter = 0;
+    LineLength  = Start;
+    NameCounter = 0;
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+        pNet = Abc_ObjFanout0(Abc_ObjFanout0(pLatch));
+        Counter++;
+        // get the line length after this name is written
+        AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
+        if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+        { // write the line extender
+            fprintf( pFile, "\n   " );
+            // reset the line length
+            LineLength  = 3;
+            NameCounter = 0;
+        }
+        fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," );
+        LineLength += AddedLength;
+        NameCounter++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the latches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pLatch;
+    int i;
+    if ( Abc_NtkLatchNum(pNtk) == 0 )
+        return;
+    // write the latches
+//    fprintf( pFile, "  always @(posedge %s) begin\n", Io_WriteVerilogGetName(Abc_ObjFanout0(Abc_NtkPi(pNtk,0))) );
+//    fprintf( pFile, "  always begin\n" );
+    fprintf( pFile, "  always @ (posedge clock) begin\n" );
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+        fprintf( pFile, "    %s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) );
+        fprintf( pFile, " <= %s;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pLatch)))) );
+    }
+    fprintf( pFile, "  end\n" );
+    // check if there are initial values
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+        if ( Abc_LatchInit(pLatch) == ABC_INIT_ZERO || Abc_LatchInit(pLatch) == ABC_INIT_ONE )
+            break;
+    if ( i == Abc_NtkLatchNum(pNtk) )
+        return;
+    // write the initial values
+    fprintf( pFile, "  initial begin\n" );
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+        if ( Abc_LatchInit(pLatch) == ABC_INIT_ZERO )
+            fprintf( pFile, "    %s <= 1\'b0;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) );
+        else if ( Abc_LatchInit(pLatch) == ABC_INIT_ONE )
+            fprintf( pFile, "    %s <= 1\'b1;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) );
+    }
+    fprintf( pFile, "  end\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the nodes and boxes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+    Vec_Vec_t * vLevels;
+    Abc_Ntk_t * pNtkBox;
+    Abc_Obj_t * pObj, * pTerm, * pFanin;
+    Hop_Obj_t * pFunc;
+    int i, k, Counter, nDigits, Length;
+
+    // write boxes
+    nDigits = Abc_Base10Log( Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) );
+    Counter = 0;
+    Abc_NtkForEachBox( pNtk, pObj, i )
+    {
+        if ( Abc_ObjIsLatch(pObj) )
+            continue;
+        pNtkBox = (Abc_Ntk_t *)pObj->pData;
+        fprintf( pFile, "  %s box%0*d", pNtkBox->pName, nDigits, Counter++ );
+        fprintf( pFile, "(" );
+        Abc_NtkForEachPi( pNtkBox, pTerm, k )
+        {
+            fprintf( pFile, ".%s",   Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pTerm))) );
+            fprintf( pFile, "(%s), ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin(pObj,k)))) );
+        }
+        Abc_NtkForEachPo( pNtkBox, pTerm, k )
+        {
+            fprintf( pFile, ".%s",   Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(pTerm))) );
+            fprintf( pFile, "(%s)%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout(pObj,k)))), k==Abc_NtkPoNum(pNtkBox)-1? "":", " );
+        }
+        fprintf( pFile, ");\n" );
+    }
+    // write nodes
+    if ( Abc_NtkHasMapping(pNtk) )
+    {
+        Length  = Mio_LibraryReadGateNameMax((Mio_Library_t *)pNtk->pManFunc);
+        nDigits = Abc_Base10Log( Abc_NtkNodeNum(pNtk) );
+        Counter = 0;
+        Abc_NtkForEachNode( pNtk, pObj, k )
+        {
+            Mio_Gate_t * pGate = (Mio_Gate_t *)pObj->pData;
+            Mio_Pin_t * pGatePin;
+            if ( Abc_ObjFaninNum(pObj) == 0 && (!strcmp(Mio_GateReadName(pGate), "_const0_") || !strcmp(Mio_GateReadName(pGate), "_const1_")) )
+            {
+                fprintf( pFile, "  %-*s %s = 1\'b%d;\n", Length, "assign", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanout0(pObj) )), !strcmp(Mio_GateReadName(pGate), "_const1_") );
+                continue;
+            }
+            // write the node
+            fprintf( pFile, "  %-*s g%0*d", Length, Mio_GateReadName(pGate), nDigits, Counter++ );
+            fprintf( pFile, "(" );
+            for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ )
+            {
+                fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_PinReadName(pGatePin)) );
+                fprintf( pFile, "(%s), ", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanin(pObj,i) )) );
+            }
+            assert ( i == Abc_ObjFaninNum(pObj) );
+            fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_GateReadOutName(pGate)) );
+            fprintf( pFile, "(%s)", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanout0(pObj) )) );
+            fprintf( pFile, ");\n" );
+        }
+    }
+    else
+    {
+        vLevels = Vec_VecAlloc( 10 );
+        Abc_NtkForEachNode( pNtk, pObj, i )
+        {
+            pFunc = (Hop_Obj_t *)pObj->pData;
+            fprintf( pFile, "  assign %s = ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) );
+            // set the input names
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                Hop_IthVar((Hop_Man_t *)pNtk->pManFunc, k)->pData = Extra_UtilStrsav(Io_WriteVerilogGetName(Abc_ObjName(pFanin)));
+            // write the formula
+            Hop_ObjPrintVerilog( pFile, pFunc, vLevels, 0 );
+            fprintf( pFile, ";\n" );
+            // clear the input names
+            Abc_ObjForEachFanin( pObj, pFanin, k )
+                ABC_FREE( Hop_IthVar((Hop_Man_t *)pNtk->pManFunc, k)->pData );
+        }
+        Vec_VecFree( vLevels );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of wires.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj, * pNet, * pBox;
+    int i, k, nWires;
+    nWires = Abc_NtkLatchNum(pNtk);
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        if ( i == 0 ) 
+            continue;
+        pNet = Abc_ObjFanout0(pObj);
+        if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) )
+            continue;
+        nWires++;
+    }
+    Abc_NtkForEachBox( pNtk, pBox, i )
+    {
+        if ( Abc_ObjIsLatch(pBox) )
+            continue;
+        nWires += Abc_ObjFaninNum(pBox);
+        Abc_ObjForEachFanout( pBox, pObj, k )
+        {
+            pNet = Abc_ObjFanout0(pObj);
+            if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) )
+                continue;
+            nWires++;
+        }
+    }
+    return nWires;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the name for writing the Verilog file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Io_WriteVerilogGetName( char * pName )
+{
+    static char Buffer[500];
+    int Length, i;
+    Length = strlen(pName);
+    // consider the case of a signal having name "0" or "1"
+    if ( !(Length == 1 && (pName[0] == '0' || pName[0] == '1')) )
+    {
+        for ( i = 0; i < Length; i++ )
+            if ( !((pName[i] >= 'a' && pName[i] <= 'z') || 
+                 (pName[i] >= 'A' && pName[i] <= 'Z') || 
+                 (pName[i] >= '0' && pName[i] <= '9') || pName[i] == '_') )
+                 break;
+        if ( i == Length )
+            return pName;
+    }
+    // create Verilog style name
+    Buffer[0] = '\\';
+    for ( i = 0; i < Length; i++ )
+        Buffer[i+1] = pName[i];
+    Buffer[Length+1] = ' ';
+    Buffer[Length+2] = 0;
+    return Buffer;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/io/module.make b/abc-build/src/base/io/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/io/module.make
@@ -0,0 +1,29 @@
+SRC +=  src/base/io/io.c \
+	src/base/io/ioReadAiger.c \
+	src/base/io/ioReadBaf.c \
+	src/base/io/ioReadBblif.c \
+	src/base/io/ioReadBench.c \
+	src/base/io/ioReadBlif.c \
+	src/base/io/ioReadBlifAig.c \
+	src/base/io/ioReadBlifMv.c \
+	src/base/io/ioReadDsd.c \
+	src/base/io/ioReadEdif.c \
+	src/base/io/ioReadEqn.c \
+	src/base/io/ioReadPla.c \
+	src/base/io/ioReadVerilog.c \
+	src/base/io/ioUtil.c \
+	src/base/io/ioWriteAiger.c \
+	src/base/io/ioWriteBaf.c \
+	src/base/io/ioWriteBblif.c \
+	src/base/io/ioWriteBench.c \
+	src/base/io/ioWriteBlif.c \
+	src/base/io/ioWriteBlifMv.c \
+	src/base/io/ioWriteBook.c \
+	src/base/io/ioWriteCnf.c \
+	src/base/io/ioWriteDot.c \
+	src/base/io/ioWriteEqn.c \
+	src/base/io/ioWriteGml.c \
+	src/base/io/ioWriteList.c \
+	src/base/io/ioWritePla.c \
+	src/base/io/ioWriteVerilog.c \
+	src/base/io/ioWriteSmv.c
diff --git a/abc-build/src/base/main/libSupport.c b/abc-build/src/base/main/libSupport.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/main/libSupport.c
@@ -0,0 +1,211 @@
+/**CFile****************************************************************
+
+  FileName    [libSupport.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The main package.]
+
+  Synopsis    [Support for external libaries.]
+
+  Author      [Mike Case]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: libSupport.c,v 1.1 2005/09/06 19:59:51 casem Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include "base/abc/abc.h"
+#include "mainInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+#if defined(ABC_NO_DYNAMIC_LINKING)
+#define WIN32
+#endif
+
+#ifndef WIN32
+# include <sys/types.h>
+# include <dirent.h>
+# include <dlfcn.h>
+#endif
+
+// fix by Paddy O'Brien  on Sep 22, 2009
+#ifdef __CYGWIN__
+#ifndef RTLD_LOCAL
+#define RTLD_LOCAL 0
+#endif
+#endif 
+
+
+#define MAX_LIBS 256
+static void* libHandles[MAX_LIBS+1]; // will be null terminated
+
+typedef void (*lib_init_end_func) (Abc_Frame_t * pAbc);
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// This will find all the ABC library extensions in the current directory and load them all.
+////////////////////////////////////////////////////////////////////////////////////////////////////
+void open_libs() {
+    int curr_lib = 0;
+
+#ifdef WIN32
+//    printf("Warning: open_libs WIN32 not implemented.\n");
+#else
+    DIR* dirp;
+    struct dirent* dp;
+    char *env, *init_p, *p;
+    int done;
+
+    env = getenv ("ABC_LIB_PATH");
+    if (env == NULL) {
+//    printf("Warning: ABC_LIB_PATH not defined. Looking into the current directory.\n");
+      init_p = ABC_ALLOC( char, (2*sizeof(char)) );
+      init_p[0]='.'; init_p[1] = 0;
+    } else {
+      init_p = ABC_ALLOC( char, ((strlen(env)+1)*sizeof(char)) );
+      strcpy (init_p, env);
+    }
+
+    // Extract directories and read libraries
+    done = 0;
+    p = init_p;
+    while (!done) {
+      char *endp = strchr (p,':');
+      if (endp == NULL) done = 1; // last directory in the list
+      else *endp = 0; // end of string
+
+      dirp = opendir(p);
+      if (dirp == NULL) {
+//      printf("Warning: directory in ABC_LIB_PATH does not exist (%s).\n", p);
+        continue;
+      }
+
+      while ((dp = readdir(dirp)) != NULL) {
+        if ((strncmp("libabc_", dp->d_name, 7) == 0) &&
+            (strcmp(".so", dp->d_name + strlen(dp->d_name) - 3) == 0)) {
+
+          // make sure we don't overflow the handle array
+          if (curr_lib >= MAX_LIBS) {
+            printf("Warning: maximum number of ABC libraries (%d) exceeded.  Not loading %s.\n",
+                   MAX_LIBS,
+                   dp->d_name);
+          }
+          
+          // attempt to load it
+          else {
+            char* szPrefixed = ABC_ALLOC( char, ((strlen(dp->d_name) + strlen(p) + 2) * 
+                                      sizeof(char)) );
+            sprintf(szPrefixed, "%s/", p);
+            strcat(szPrefixed, dp->d_name);
+            libHandles[curr_lib] = dlopen(szPrefixed, RTLD_NOW | RTLD_LOCAL);
+            
+            // did the load succeed?
+            if (libHandles[curr_lib] != 0) {
+              printf("Loaded ABC library: %s (Abc library extension #%d)\n", szPrefixed, curr_lib);
+              curr_lib++;
+            } else {
+              printf("Warning: failed to load ABC library %s:\n\t%s\n", szPrefixed, dlerror());
+            }
+            
+            ABC_FREE(szPrefixed);
+          }
+        }
+      }
+      closedir(dirp);
+      p = endp+1;
+    }
+
+    ABC_FREE(init_p);
+#endif
+    
+    // null terminate the list of handles
+    libHandles[curr_lib] = 0;    
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// This will close all open ABC library extensions
+////////////////////////////////////////////////////////////////////////////////////////////////////
+void close_libs() {
+#ifdef WIN32
+    printf("Warning: close_libs WIN32 not implemented.\n");
+#else
+    int i;
+    for (i = 0; libHandles[i] != 0; i++) {
+        if (dlclose(libHandles[i]) != 0) {
+            printf("Warning: failed to close library %d\n", i);
+        }
+        libHandles[i] = 0;
+    }
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// This will get a pointer to a function inside of an open library
+////////////////////////////////////////////////////////////////////////////////////////////////////
+void* get_fnct_ptr(int lib_num, char* sym_name) {
+#ifdef WIN32
+    printf("Warning: get_fnct_ptr WIN32 not implemented.\n");
+    return 0;
+#else
+    return dlsym(libHandles[lib_num], sym_name);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// This will call an initialization function in every open library.
+////////////////////////////////////////////////////////////////////////////////////////////////////
+void call_inits(Abc_Frame_t* pAbc) {
+    int i;
+    lib_init_end_func init_func;
+    for (i = 0; libHandles[i] != 0; i++) {
+        init_func = (lib_init_end_func) get_fnct_ptr(i, "abc_init");
+        if (init_func == 0) {
+            printf("Warning: Failed to initialize library %d.\n", i);
+        } else {
+            (*init_func)(pAbc);
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// This will call a shutdown function in every open library.
+////////////////////////////////////////////////////////////////////////////////////////////////////
+void call_ends(Abc_Frame_t* pAbc) {
+    int i;
+    lib_init_end_func end_func;
+    for (i = 0; libHandles[i] != 0; i++) {
+        end_func = (lib_init_end_func) get_fnct_ptr(i, "abc_end");
+        if (end_func == 0) {
+            printf("Warning: Failed to end library %d.\n", i);
+        } else {
+            (*end_func)(pAbc);
+        }
+    }
+}
+
+void Libs_Init(Abc_Frame_t * pAbc)
+{
+    open_libs();
+    call_inits(pAbc);
+}
+
+void Libs_End(Abc_Frame_t * pAbc)
+{
+    call_ends(pAbc);
+
+    // It's good practice to close our libraries at this point, but this can mess up any backtrace printed by Valgind.
+    //    close_libs();
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/main/main.c b/abc-build/src/base/main/main.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/main/main.c
@@ -0,0 +1,384 @@
+/*////////////////////////////////////////////////////////////////////////////
+
+ABC: System for Sequential Synthesis and Verification
+
+http://www.eecs.berkeley.edu/~alanmi/abc/
+
+Copyright (c) The Regents of the University 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.
+
+////////////////////////////////////////////////////////////////////////////*/
+
+/**CFile****************************************************************
+
+  FileName    [main.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The main package.]
+
+  Synopsis    [Here everything starts.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: main.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+
+#ifdef ABC_PYTHON_EMBED
+#include <Python.h>
+#endif /* ABC_PYTHON_EMBED */
+
+#include "base/abc/abc.h"
+#include "mainInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+// this line should be included in the library project
+//#define ABC_LIB
+
+//#define ABC_USE_BINARY 1
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int TypeCheck( Abc_Frame_t * pAbc, const char * s);
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+#ifndef ABC_LIB
+
+/**Function*************************************************************
+
+  Synopsis    [The main() procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_RealMain( int argc, char * argv[] )
+{
+    Abc_Frame_t * pAbc;
+    char sCommandUsr[ABC_MAX_STR] = {0}, sCommandTmp[ABC_MAX_STR], sReadCmd[1000], sWriteCmd[1000];
+    const char * sOutFile, * sInFile;
+    char * sCommand;
+    int  fStatus = 0;
+    int c, fInitSource, fInitRead, fFinalWrite;
+
+    enum {
+        INTERACTIVE, // interactive mode
+        BATCH, // batch mode, run a command and quit
+        BATCH_THEN_INTERACTIVE, // run a command, then back to interactive mode
+        BATCH_QUIET // as in batch mode, but don't echo the command
+    } fBatch;
+
+    // added to detect memory leaks
+    // watch for {,,msvcrtd.dll}*__p__crtBreakAlloc()
+    // (http://support.microsoft.com/kb/151585)
+#if defined(_DEBUG) && defined(_MSC_VER)
+    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
+#endif
+
+    // get global frame (singleton pattern)
+    // will be initialized on first call
+    pAbc = Abc_FrameGetGlobalFrame();
+    pAbc->sBinary = argv[0];
+
+#ifdef ABC_PYTHON_EMBED
+    {
+        PyObject* pModule;
+        void init_pyabc(void);
+
+        Py_SetProgramName(argv[0]);
+        Py_NoSiteFlag = 1;
+        Py_Initialize();
+
+        init_pyabc();
+
+        pModule = PyImport_ImportModule("pyabc");
+        if (pModule)
+        {
+            Py_DECREF(pModule);
+        }
+        else
+        {
+            fprintf( pAbc->Err, "error: pyabc.py not found. PYTHONPATH may not be set properly.\n");
+        }
+    }
+#endif /* ABC_PYTHON_EMBED */
+
+    // default options
+    fBatch      = INTERACTIVE;
+    fInitSource = 1;
+    fInitRead   = 0;
+    fFinalWrite = 0;
+    sInFile = sOutFile = NULL;
+    sprintf( sReadCmd,  "read"  );
+    sprintf( sWriteCmd, "write" );
+
+    Extra_UtilGetoptReset();
+    while ((c = Extra_UtilGetopt(argc, argv, "c:q:C:hf:F:o:st:T:xb")) != EOF) {
+        switch(c) {
+            case 'c':
+                strcpy( sCommandUsr, globalUtilOptarg );
+                fBatch = BATCH;
+                break;
+
+            case 'q':
+                strcpy( sCommandUsr, globalUtilOptarg );
+                fBatch = BATCH_QUIET;
+                break;
+
+            case 'C':
+                strcpy( sCommandUsr, globalUtilOptarg );
+                fBatch = BATCH_THEN_INTERACTIVE;
+                break;
+
+            case 'f':
+                sprintf(sCommandUsr, "source %s", globalUtilOptarg);
+                fBatch = BATCH;
+                break;
+
+            case 'F':
+                sprintf(sCommandUsr, "source -x %s", globalUtilOptarg);
+                fBatch = BATCH;
+                break;
+
+            case 'h':
+                goto usage;
+                break;
+
+            case 'o':
+                sOutFile = globalUtilOptarg;
+                fFinalWrite = 1;
+                break;
+
+            case 's':
+                fInitSource = 0;
+                break;
+
+            case 't':
+                if ( TypeCheck( pAbc, globalUtilOptarg ) )
+                {
+                    if ( !strcmp(globalUtilOptarg, "none") == 0 )
+                    {
+                        fInitRead = 1;
+                        sprintf( sReadCmd, "read_%s", globalUtilOptarg );
+                    }
+                }
+                else {
+                    goto usage;
+                }
+                fBatch = BATCH;
+                break;
+
+            case 'T':
+                if ( TypeCheck( pAbc, globalUtilOptarg ) )
+                {
+                    if (!strcmp(globalUtilOptarg, "none") == 0)
+                    {
+                        fFinalWrite = 1;
+                        sprintf( sWriteCmd, "write_%s", globalUtilOptarg);
+                    }
+                }
+                else {
+                    goto usage;
+                }
+                fBatch = BATCH;
+                break;
+
+            case 'x':
+                fFinalWrite = 0;
+                fInitRead   = 0;
+                fBatch = BATCH;
+                break;
+
+            case 'b':
+                Abc_FrameSetBridgeMode();
+                break;
+
+            default:
+                goto usage;
+        }
+    }
+
+    if ( Abc_FrameIsBridgeMode() )
+    {
+        extern Gia_Man_t * Gia_ManFromBridge( FILE * pFile, Vec_Int_t ** pvInit );
+        pAbc->pGia = Gia_ManFromBridge( stdin, NULL );
+    }
+    else if ( fBatch!=INTERACTIVE && fBatch!=BATCH_QUIET && sCommandUsr[0] )
+        Abc_Print( 1, "ABC command line: \"%s\".\n\n", sCommandUsr );
+
+    if ( fBatch!=INTERACTIVE )
+    {
+        pAbc->fBatchMode = 1;
+
+
+        if (argc - globalUtilOptind == 0)
+        {
+            sInFile = NULL;
+        }
+        else if (argc - globalUtilOptind == 1)
+        {
+            fInitRead = 1;
+            sInFile = argv[globalUtilOptind];
+        }
+        else
+        {
+            Abc_UtilsPrintUsage( pAbc, argv[0] );
+        }
+
+        // source the resource file
+        if ( fInitSource )
+        {
+            Abc_UtilsSource( pAbc );
+        }
+
+        fStatus = 0;
+        if ( fInitRead && sInFile )
+        {
+            sprintf( sCommandTmp, "%s %s", sReadCmd, sInFile );
+            fStatus = Cmd_CommandExecute( pAbc, sCommandTmp );
+        }
+
+        if ( fStatus == 0 )
+        {
+            /* cmd line contains `source <file>' */
+            fStatus = Cmd_CommandExecute( pAbc, sCommandUsr );
+            if ( (fStatus == 0 || fStatus == -1) && fFinalWrite && sOutFile )
+            {
+                sprintf( sCommandTmp, "%s %s", sWriteCmd, sOutFile );
+                fStatus = Cmd_CommandExecute( pAbc, sCommandTmp );
+            }
+        }
+
+        if (fBatch == BATCH_THEN_INTERACTIVE){
+            fBatch = INTERACTIVE;
+            pAbc->fBatchMode = 0;
+        }
+
+    }
+
+    if ( fBatch==INTERACTIVE )
+    {
+        // start interactive mode
+
+        // print the hello line
+        Abc_UtilsPrintHello( pAbc );
+        // print history of the recent commands
+        Cmd_HistoryPrint( pAbc, 10 );
+
+        // source the resource file
+        if ( fInitSource )
+        {
+            Abc_UtilsSource( pAbc );
+        }
+
+        // execute commands given by the user
+        while ( !feof(stdin) )
+        {
+            // print command line prompt and
+            // get the command from the user
+            sCommand = Abc_UtilsGetUsersInput( pAbc );
+
+            // execute the user's command
+            fStatus = Cmd_CommandExecute( pAbc, sCommand );
+
+            // stop if the user quitted or an error occurred
+            if ( fStatus == -1 || fStatus == -2 )
+                break;
+        }
+    }
+
+#ifdef ABC_PYTHON_EMBED
+    {
+        Py_Finalize();
+    }
+#endif /* ABC_PYTHON_EMBED */
+
+    // if the memory should be freed, quit packages
+//    if ( fStatus < 0 ) 
+    {
+        Abc_Stop();
+    }
+    return 0;
+
+usage:
+    Abc_UtilsPrintHello( pAbc );
+    Abc_UtilsPrintUsage( pAbc, argv[0] );
+    return 1;
+}
+
+#endif
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if s is a file type recognized, else returns 0.]
+
+  Description [Returns 1 if s is a file type recognized by ABC, else returns 0. 
+  Recognized types are "blif", "bench", "pla", and "none".]
+
+  SideEffects []
+
+******************************************************************************/
+static int TypeCheck( Abc_Frame_t * pAbc, const char * s )
+{
+    if (strcmp(s, "blif") == 0)
+        return 1;
+    else if (strcmp(s, "bench") == 0)
+        return 1;
+    else if (strcmp(s, "pla") == 0)
+        return 1;
+    else if (strcmp(s, "none") == 0)
+        return 1;
+    else {
+        fprintf( pAbc->Err, "unknown type %s\n", s );
+        return 0;
+    }
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
+#if defined(ABC_USE_BINARY)
+int main_( int argc, char * argv[] )
+#else
+int main( int argc, char * argv[] )
+#endif
+{
+  return ABC_NAMESPACE_PREFIX Abc_RealMain(argc, argv);
+}
diff --git a/abc-build/src/base/main/main.h b/abc-build/src/base/main/main.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/main/main.h
@@ -0,0 +1,162 @@
+/**CFile****************************************************************
+
+  FileName    [main.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The main package.]
+
+  Synopsis    [External declarations of the main package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: main.h,v 1.1 2008/05/14 22:13:13 wudenni Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__base__main__main_h
+#define ABC__base__main__main_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+// core packages
+#include "base/abc/abc.h"
+#include "aig/gia/gia.h"
+
+// data structure packages
+#include "misc/vec/vec.h"
+#include "misc/st/st.h"
+
+ABC_NAMESPACE_HEADER_START
+// the framework containing all data
+typedef struct Abc_Frame_t_      Abc_Frame_t;
+ABC_NAMESPACE_HEADER_END
+
+#include "base/cmd/cmd.h"
+#include "base/io/ioAbc.h"
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         TYPEDEFS                                 ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== main.c ===========================================================*/
+extern ABC_DLL void            Abc_Start();
+extern ABC_DLL void            Abc_Stop();
+
+/*=== mainFrame.c ===========================================================*/
+extern ABC_DLL Abc_Ntk_t *     Abc_FrameReadNtk( Abc_Frame_t * p );
+extern ABC_DLL Gia_Man_t *     Abc_FrameReadGia( Abc_Frame_t * p );
+extern ABC_DLL FILE *          Abc_FrameReadOut( Abc_Frame_t * p );
+extern ABC_DLL FILE *          Abc_FrameReadErr( Abc_Frame_t * p );
+extern ABC_DLL int             Abc_FrameReadMode( Abc_Frame_t * p );
+extern ABC_DLL int             Abc_FrameSetMode( Abc_Frame_t * p, int fNameMode );
+extern ABC_DLL void            Abc_FrameRestart( Abc_Frame_t * p );
+extern ABC_DLL int             Abc_FrameShowProgress( Abc_Frame_t * p );
+extern ABC_DLL void            Abc_FrameClearVerifStatus( Abc_Frame_t * p );
+extern ABC_DLL void            Abc_FrameUpdateGia( Abc_Frame_t * p, Gia_Man_t * pNew );
+extern ABC_DLL Gia_Man_t *     Abc_FrameGetGia( Abc_Frame_t * p );
+
+extern ABC_DLL void            Abc_FrameSetCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNet );
+extern ABC_DLL void            Abc_FrameSwapCurrentAndBackup( Abc_Frame_t * p );
+extern ABC_DLL void            Abc_FrameReplaceCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNet );
+extern ABC_DLL void            Abc_FrameUnmapAllNetworks( Abc_Frame_t * p );
+extern ABC_DLL void            Abc_FrameDeleteAllNetworks( Abc_Frame_t * p );
+
+extern ABC_DLL void			   Abc_FrameSetGlobalFrame( Abc_Frame_t * p );
+extern ABC_DLL Abc_Frame_t *   Abc_FrameGetGlobalFrame();
+extern ABC_DLL Abc_Frame_t *   Abc_FrameReadGlobalFrame();
+
+extern ABC_DLL Vec_Ptr_t *     Abc_FrameReadStore();                  
+extern ABC_DLL int             Abc_FrameReadStoreSize();              
+extern ABC_DLL void *          Abc_FrameReadLibLut();                    
+extern ABC_DLL void *          Abc_FrameReadLibBox();                    
+extern ABC_DLL void *          Abc_FrameReadLibGen();                    
+extern ABC_DLL void *          Abc_FrameReadLibGen2();                    
+extern ABC_DLL void *          Abc_FrameReadLibSuper();                  
+extern ABC_DLL void *          Abc_FrameReadLibScl();                  
+extern ABC_DLL void *          Abc_FrameReadManDd();                     
+extern ABC_DLL void *          Abc_FrameReadManDec();                    
+extern ABC_DLL void *          Abc_FrameReadManDsd();           
+         
+extern ABC_DLL char *          Abc_FrameReadFlag( char * pFlag ); 
+extern ABC_DLL int             Abc_FrameIsFlagEnabled( char * pFlag );
+extern ABC_DLL int             Abc_FrameIsBatchMode();
+extern ABC_DLL int             Abc_FrameIsBridgeMode();
+extern ABC_DLL void            Abc_FrameSetBridgeMode();
+
+extern ABC_DLL int             Abc_FrameReadBmcFrames( Abc_Frame_t * p );              
+extern ABC_DLL int             Abc_FrameReadProbStatus( Abc_Frame_t * p );              
+extern ABC_DLL Abc_Cex_t *     Abc_FrameReadCex( Abc_Frame_t * p );              
+extern ABC_DLL Vec_Ptr_t *     Abc_FrameReadCexVec( Abc_Frame_t * p );  
+extern ABC_DLL Vec_Int_t *     Abc_FrameReadStatusVec( Abc_Frame_t * p );  
+extern ABC_DLL Vec_Ptr_t *     Abc_FrameReadPoEquivs( Abc_Frame_t * p );  
+extern ABC_DLL Vec_Int_t *     Abc_FrameReadPoStatuses( Abc_Frame_t * p );  
+extern ABC_DLL Vec_Int_t *     Abc_FrameReadObjIds( Abc_Frame_t * p );
+
+extern ABC_DLL int             Abc_FrameReadCexPiNum( Abc_Frame_t * p );              
+extern ABC_DLL int             Abc_FrameReadCexRegNum( Abc_Frame_t * p );              
+extern ABC_DLL int             Abc_FrameReadCexPo( Abc_Frame_t * p );              
+extern ABC_DLL int             Abc_FrameReadCexFrame( Abc_Frame_t * p );              
+
+extern ABC_DLL void            Abc_FrameSetNtkStore( Abc_Ntk_t * pNtk ); 
+extern ABC_DLL void            Abc_FrameSetNtkStoreSize( int nStored );  
+extern ABC_DLL void            Abc_FrameSetLibLut( void * pLib );        
+extern ABC_DLL void            Abc_FrameSetLibBox( void * pLib );        
+extern ABC_DLL void            Abc_FrameSetLibGen( void * pLib );        
+extern ABC_DLL void            Abc_FrameSetLibGen2( void * pLib );        
+extern ABC_DLL void            Abc_FrameSetLibSuper( void * pLib );      
+extern ABC_DLL void            Abc_FrameSetLibVer( void * pLib );      
+extern ABC_DLL void            Abc_FrameSetFlag( char * pFlag, char * pValue );
+extern ABC_DLL void            Abc_FrameSetCex( Abc_Cex_t * pCex );
+extern ABC_DLL void            Abc_FrameSetNFrames( int nFrames );
+extern ABC_DLL void            Abc_FrameSetStatus( int Status );
+extern ABC_DLL void            Abc_FrameSetManDsd( void * pMan );
+
+extern ABC_DLL int             Abc_FrameCheckPoConst( Abc_Frame_t * p, int iPoNum );
+
+extern ABC_DLL void            Abc_FrameReplaceCex( Abc_Frame_t * pAbc, Abc_Cex_t ** ppCex );
+extern ABC_DLL void            Abc_FrameReplaceCexVec( Abc_Frame_t * pAbc, Vec_Ptr_t ** pvCexVec );
+extern ABC_DLL void            Abc_FrameReplacePoEquivs( Abc_Frame_t * pAbc, Vec_Ptr_t ** pvPoEquivs );
+extern ABC_DLL void            Abc_FrameReplacePoStatuses( Abc_Frame_t * pAbc, Vec_Int_t ** pvStatuses );
+
+extern ABC_DLL char *          Abc_FrameReadDrivingCell();              
+extern ABC_DLL float           Abc_FrameReadMaxLoad();
+extern ABC_DLL void            Abc_FrameSetDrivingCell( char * pName );
+extern ABC_DLL void            Abc_FrameSetMaxLoad( float Load );
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/base/main/mainFrame.c b/abc-build/src/base/main/mainFrame.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/main/mainFrame.c
@@ -0,0 +1,709 @@
+/**CFile****************************************************************
+
+  FileName    [mainFrame.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The main package.]
+
+  Synopsis    [The global framework resides in this file.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mainFrame.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "mainInt.h"
+#include "bool/dec/dec.h"
+#include "misc/extra/extraBdd.h"
+#include "map/if/if.h"
+
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Frame_t * s_GlobalFrame = NULL;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [APIs to access parameters in the flobal frame.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_FrameReadStore()                             { return s_GlobalFrame->vStore;       } 
+int         Abc_FrameReadStoreSize()                         { return Vec_PtrSize(s_GlobalFrame->vStore); }
+void *      Abc_FrameReadLibLut()                            { return s_GlobalFrame->pLibLut;      } 
+void *      Abc_FrameReadLibBox()                            { return s_GlobalFrame->pLibBox;      } 
+void *      Abc_FrameReadLibGen()                            { return s_GlobalFrame->pLibGen;      } 
+void *      Abc_FrameReadLibGen2()                           { return s_GlobalFrame->pLibGen2;     } 
+void *      Abc_FrameReadLibSuper()                          { return s_GlobalFrame->pLibSuper;    } 
+void *      Abc_FrameReadLibScl()                            { return s_GlobalFrame->pLibScl;      } 
+void *      Abc_FrameReadManDd()                             { if ( s_GlobalFrame->dd == NULL )      s_GlobalFrame->dd = Cudd_Init( 0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );  return s_GlobalFrame->dd;      } 
+void *      Abc_FrameReadManDec()                            { if ( s_GlobalFrame->pManDec == NULL ) s_GlobalFrame->pManDec = Dec_ManStart();                                        return s_GlobalFrame->pManDec; } 
+void *      Abc_FrameReadManDsd()                            { return s_GlobalFrame->pManDsd;      } 
+char *      Abc_FrameReadFlag( char * pFlag )                { return Cmd_FlagReadByName( s_GlobalFrame, pFlag );   } 
+
+int         Abc_FrameReadBmcFrames( Abc_Frame_t * p )        { return s_GlobalFrame->nFrames;      }               
+int         Abc_FrameReadProbStatus( Abc_Frame_t * p )       { return s_GlobalFrame->Status;       }               
+Abc_Cex_t * Abc_FrameReadCex( Abc_Frame_t * p )              { return s_GlobalFrame->pCex;         }        
+Vec_Ptr_t * Abc_FrameReadCexVec( Abc_Frame_t * p )           { return s_GlobalFrame->vCexVec;      }        
+Vec_Int_t * Abc_FrameReadStatusVec( Abc_Frame_t * p )        { return s_GlobalFrame->vStatuses;    }        
+Vec_Ptr_t * Abc_FrameReadPoEquivs( Abc_Frame_t * p )         { return s_GlobalFrame->vPoEquivs;    }        
+Vec_Int_t * Abc_FrameReadPoStatuses( Abc_Frame_t * p )       { return s_GlobalFrame->vStatuses;    }        
+Vec_Int_t * Abc_FrameReadObjIds( Abc_Frame_t * p )           { return s_GlobalFrame->vAbcObjIds;   }        
+       
+int         Abc_FrameReadCexPiNum( Abc_Frame_t * p )         { return s_GlobalFrame->pCex->nPis;   }               
+int         Abc_FrameReadCexRegNum( Abc_Frame_t * p )        { return s_GlobalFrame->pCex->nRegs;  }               
+int         Abc_FrameReadCexPo( Abc_Frame_t * p )            { return s_GlobalFrame->pCex->iPo;    }               
+int         Abc_FrameReadCexFrame( Abc_Frame_t * p )         { return s_GlobalFrame->pCex->iFrame; }               
+
+void        Abc_FrameSetLibLut( void * pLib )                { s_GlobalFrame->pLibLut   = pLib;    } 
+void        Abc_FrameSetLibBox( void * pLib )                { s_GlobalFrame->pLibBox   = pLib;    } 
+void        Abc_FrameSetLibGen( void * pLib )                { s_GlobalFrame->pLibGen   = pLib;    } 
+void        Abc_FrameSetLibGen2( void * pLib )               { s_GlobalFrame->pLibGen2  = pLib;    } 
+void        Abc_FrameSetLibSuper( void * pLib )              { s_GlobalFrame->pLibSuper = pLib;    } 
+void        Abc_FrameSetFlag( char * pFlag, char * pValue )  { Cmd_FlagUpdateValue( s_GlobalFrame, pFlag, pValue );               } 
+void        Abc_FrameSetCex( Abc_Cex_t * pCex )              { ABC_FREE( s_GlobalFrame->pCex ); s_GlobalFrame->pCex = pCex;       }
+void        Abc_FrameSetNFrames( int nFrames )               { ABC_FREE( s_GlobalFrame->pCex ); s_GlobalFrame->nFrames = nFrames; }
+void        Abc_FrameSetStatus( int Status )                 { ABC_FREE( s_GlobalFrame->pCex ); s_GlobalFrame->Status = Status;   }
+void        Abc_FrameSetManDsd( void * pMan )                { if (s_GlobalFrame->pManDsd && s_GlobalFrame->pManDsd != pMan) If_DsdManFree((If_DsdMan_t *)s_GlobalFrame->pManDsd, 0); s_GlobalFrame->pManDsd = pMan; }
+
+int         Abc_FrameIsBatchMode()                           { return s_GlobalFrame ? s_GlobalFrame->fBatchMode : 0;              } 
+
+int         Abc_FrameIsBridgeMode()                          { return s_GlobalFrame ? s_GlobalFrame->fBridgeMode : 0;             } 
+void        Abc_FrameSetBridgeMode()                         { if ( s_GlobalFrame ) s_GlobalFrame->fBridgeMode = 1;               } 
+
+char *      Abc_FrameReadDrivingCell()                       { return s_GlobalFrame->pDrivingCell;    }              
+float       Abc_FrameReadMaxLoad()                           { return s_GlobalFrame->MaxLoad;         }      
+void        Abc_FrameSetDrivingCell( char * pName )          { ABC_FREE(s_GlobalFrame->pDrivingCell); s_GlobalFrame->pDrivingCell   = pName; }      
+void        Abc_FrameSetMaxLoad( float Load )                { s_GlobalFrame->MaxLoad        = Load;  }      
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the flag is enabled without value or with value 1.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_FrameIsFlagEnabled( char * pFlag )
+{
+    char * pValue;
+    // if flag is not defined, it is not enabled
+    pValue = Abc_FrameReadFlag( pFlag );
+    if ( pValue == NULL )
+        return 0;
+    // if flag is defined but value is not empty (no parameter) or "1", it is not enabled
+    if ( strcmp(pValue, "") && strcmp(pValue, "1") )
+        return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Frame_t * Abc_FrameAllocate()
+{
+    Abc_Frame_t * p;
+    extern void define_cube_size( int n );
+    extern void set_espresso_flags();
+    // allocate and clean
+    p = ABC_CALLOC( Abc_Frame_t, 1 );
+    // get version
+    p->sVersion = Abc_UtilsGetVersion( p );
+    // set streams
+    p->Err = stderr;
+    p->Out = stdout;
+    p->Hst = NULL;
+    p->Status     = -1;
+    p->nFrames    = -1;
+    // set the starting step
+    p->nSteps     =  1;
+	p->fBatchMode =  0;
+    // networks to be used by choice
+    p->vStore = Vec_PtrAlloc( 16 );
+    p->vAbcObjIds = Vec_IntAlloc( 0 );
+    // initialize decomposition manager
+//    define_cube_size(20);
+//    set_espresso_flags();
+    // initialize the trace manager
+//    Abc_HManStart();
+    p->vPlugInComBinPairs = Vec_PtrAlloc( 100 );
+    return p;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameDeallocate( Abc_Frame_t * p )
+{
+    extern void Rwt_ManGlobalStop();
+    extern void undefine_cube_size();
+//    extern void Ivy_TruthManStop();
+//    Abc_HManStop();
+//    undefine_cube_size();
+    Rwt_ManGlobalStop();
+//    Ivy_TruthManStop();
+    if ( p->vAbcObjIds)  Vec_IntFree( p->vAbcObjIds );
+    if ( p->vCexVec   )  Vec_PtrFreeFree( p->vCexVec );
+    if ( p->vPoEquivs )  Vec_VecFree( (Vec_Vec_t *)p->vPoEquivs );
+    if ( p->vStatuses )  Vec_IntFree( p->vStatuses );
+    if ( p->pManDec   )  Dec_ManStop( (Dec_Man_t *)p->pManDec );
+    if ( p->dd        )  Extra_StopManager( p->dd );
+    if ( p->vStore    )  Vec_PtrFree( p->vStore );
+    if ( p->pSave1    )  Aig_ManStop( (Aig_Man_t *)p->pSave1 );
+    if ( p->pSave2    )  Aig_ManStop( (Aig_Man_t *)p->pSave2 );
+    if ( p->pSave3    )  Aig_ManStop( (Aig_Man_t *)p->pSave3 );
+    if ( p->pSave4    )  Aig_ManStop( (Aig_Man_t *)p->pSave4 );
+    if ( p->pManDsd   )  If_DsdManFree( (If_DsdMan_t *)p->pManDsd, 0 );
+    if ( p->vPlugInComBinPairs ) 
+    {
+        char * pTemp;
+        int i;
+        Vec_PtrForEachEntry( char *, p->vPlugInComBinPairs, pTemp, i )
+            ABC_FREE( pTemp );
+        Vec_PtrFree( p->vPlugInComBinPairs );
+    }
+    Vec_IntFreeP( &p->vIndFlops );
+    Vec_PtrFreeP( &p->vLTLProperties_global );
+    Abc_FrameDeleteAllNetworks( p );
+    ABC_FREE( p->pDrivingCell );
+    ABC_FREE( p->pCex2 );
+    ABC_FREE( p->pCex );
+    ABC_FREE( p );
+    s_GlobalFrame = NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameRestart( Abc_Frame_t * p )
+{
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameClearVerifStatus( Abc_Frame_t * p )
+{
+    p->nFrames = -1;
+    p->Status  = -1;
+    ABC_FREE( p->pCex );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_FrameShowProgress( Abc_Frame_t * p )
+{
+    return Abc_FrameIsFlagEnabled( "progressbar" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_FrameReadNtk( Abc_Frame_t * p )
+{
+    return p->pNtkCur;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Abc_FrameReadGia( Abc_Frame_t * p )
+{
+    return p->pGia;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+FILE * Abc_FrameReadOut( Abc_Frame_t * p )
+{
+    return p->Out;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+FILE * Abc_FrameReadErr( Abc_Frame_t * p )
+{
+    return p->Err;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_FrameReadMode( Abc_Frame_t * p )
+{
+    int fShortNames;
+    char * pValue;
+    pValue = Cmd_FlagReadByName( p, "namemode" );
+    if ( pValue == NULL )
+        fShortNames = 0;
+    else 
+        fShortNames = atoi(pValue);
+    return fShortNames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_FrameSetMode( Abc_Frame_t * p, int fNameMode )
+{
+    char Buffer[2];
+    int fNameModeOld;
+    fNameModeOld = Abc_FrameReadMode( p );
+    Buffer[0] = '0' + fNameMode;
+    Buffer[1] = 0;
+    Cmd_FlagUpdateValue( p, "namemode", (char *)Buffer );
+    return fNameModeOld;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the given network to be the current one.]
+
+  Description [Takes the network and makes it the current network.
+  The previous current network is attached to the given network as 
+  a backup copy. In the stack of backup networks contains too many
+  networks (defined by the paramater "savesteps"), the bottom
+  most network is deleted.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameSetCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNtkNew )
+{
+    Abc_Ntk_t * pNtk, * pNtk2, * pNtk3;
+    int nNetsPresent;
+    int nNetsToSave;
+    char * pValue;
+
+    if ( p->pNtkCur == pNtkNew )
+        return;
+
+    // link it to the previous network
+    Abc_NtkSetBackup( pNtkNew, p->pNtkCur );
+    // set the step of this network
+    Abc_NtkSetStep( pNtkNew, ++p->nSteps );
+    // set this network to be the current network
+    p->pNtkCur = pNtkNew;
+
+    // remove any extra network that may happen to be in the stack
+    pValue = Cmd_FlagReadByName( p, "savesteps" );
+    // if the value of steps to save is not set, assume 1-level undo
+    if ( pValue == NULL )
+        nNetsToSave = 1;
+    else 
+        nNetsToSave = atoi(pValue);
+    
+    // count the network, remember the last one, and the one before the last one
+    nNetsPresent = 0;
+    pNtk2 = pNtk3 = NULL;
+    for ( pNtk = p->pNtkCur; pNtk; pNtk = Abc_NtkBackup(pNtk2) )
+    {
+        nNetsPresent++;
+        pNtk3 = pNtk2;
+        pNtk2 = pNtk;
+    }
+
+    // remove the earliest backup network if it is more steps away than we store
+    if ( nNetsPresent - 1 > nNetsToSave )
+    { // delete the last network
+        Abc_NtkDelete( pNtk2 );
+        // clean the pointer of the network before the last one
+        Abc_NtkSetBackup( pNtk3, NULL );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure swaps the current and the backup network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameSwapCurrentAndBackup( Abc_Frame_t * p )
+{
+    Abc_Ntk_t * pNtkCur, * pNtkBack, * pNtkBack2;
+    int iStepCur, iStepBack;
+
+    pNtkCur  = p->pNtkCur;
+    pNtkBack = Abc_NtkBackup( pNtkCur );
+    iStepCur = Abc_NtkStep  ( pNtkCur );
+
+    // if there is no backup nothing to reset
+    if ( pNtkBack == NULL )
+        return;
+
+    // remember the backup of the backup
+    pNtkBack2 = Abc_NtkBackup( pNtkBack );
+    iStepBack = Abc_NtkStep  ( pNtkBack );
+
+    // set pNtkCur to be the next after the backup's backup
+    Abc_NtkSetBackup( pNtkCur, pNtkBack2 );
+    Abc_NtkSetStep  ( pNtkCur, iStepBack );
+
+    // set pNtkCur to be the next after the backup
+    Abc_NtkSetBackup( pNtkBack, pNtkCur );
+    Abc_NtkSetStep  ( pNtkBack, iStepCur );
+
+    // set the current network
+    p->pNtkCur = pNtkBack;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces the current network by the given one.]
+
+  Description [This procedure does not modify the stack of saved
+  networks.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameReplaceCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNtk )
+{
+    if ( pNtk == NULL )
+        return;
+
+    if ( Abc_NtkPoNum(pNtk) == 0 )
+        Abc_Print( 0, "The current network has no primary outputs. Some commands may not work correctly.\n" );
+
+    // transfer the parameters to the new network
+    if ( p->pNtkCur && Abc_FrameIsFlagEnabled( "backup" ) )
+    {
+        Abc_NtkSetBackup( pNtk, Abc_NtkBackup(p->pNtkCur) );
+        Abc_NtkSetStep( pNtk, Abc_NtkStep(p->pNtkCur) );
+        // delete the current network
+        Abc_NtkDelete( p->pNtkCur );
+    }
+    else
+    {
+        Abc_NtkSetBackup( pNtk, NULL );
+        Abc_NtkSetStep( pNtk, ++p->nSteps );
+        // delete the current network if present but backup is disabled
+        if ( p->pNtkCur )
+            Abc_NtkDelete( p->pNtkCur );
+    }
+    // set the new current network
+    p->pNtkCur = pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes library binding of all currently stored networks.]
+
+  Description [This procedure is called when the library is freed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameUnmapAllNetworks( Abc_Frame_t * p )
+{
+    Abc_Ntk_t * pNtk;
+    for ( pNtk = p->pNtkCur; pNtk; pNtk = Abc_NtkBackup(pNtk) )
+        if ( Abc_NtkHasMapping(pNtk) )
+            Abc_NtkMapToSop( pNtk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameDeleteAllNetworks( Abc_Frame_t * p )
+{
+    Abc_Ntk_t * pNtk, * pNtk2;
+    // delete all the currently saved networks
+    for ( pNtk  = p->pNtkCur, 
+          pNtk2 = pNtk? Abc_NtkBackup(pNtk): NULL; 
+          pNtk; 
+          pNtk  = pNtk2, 
+          pNtk2 = pNtk? Abc_NtkBackup(pNtk): NULL )
+        Abc_NtkDelete( pNtk );
+    // set the current network empty
+    p->pNtkCur = NULL;
+//    fprintf( p->Out, "All networks have been deleted.\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameSetGlobalFrame( Abc_Frame_t * p )
+{
+	s_GlobalFrame = p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Frame_t * Abc_FrameGetGlobalFrame()
+{
+	if ( s_GlobalFrame == 0 )
+	{
+		// start the framework
+		s_GlobalFrame = Abc_FrameAllocate();
+		// perform initializations
+		Abc_FrameInit( s_GlobalFrame );
+	}
+	return s_GlobalFrame;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Frame_t * Abc_FrameReadGlobalFrame()
+{
+	return s_GlobalFrame;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameSetSave1( void * pAig )
+{
+    Abc_Frame_t * pFrame = Abc_FrameGetGlobalFrame();
+    if ( pFrame->pSave1 )
+        Aig_ManStop( (Aig_Man_t *)pFrame->pSave1 );
+    pFrame->pSave1 = pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameSetSave2( void * pAig )
+{
+    Abc_Frame_t * pFrame = Abc_FrameGetGlobalFrame();
+    if ( pFrame->pSave2 )
+        Aig_ManStop( (Aig_Man_t *)pFrame->pSave2 );
+    pFrame->pSave2 = pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Abc_FrameReadSave1()  { void * pAig = Abc_FrameGetGlobalFrame()->pSave1; Abc_FrameGetGlobalFrame()->pSave1 = NULL; return pAig; }
+void * Abc_FrameReadSave2()  { void * pAig = Abc_FrameGetGlobalFrame()->pSave2; Abc_FrameGetGlobalFrame()->pSave2 = NULL; return pAig; }
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 0/1 if pNtkCur is an AIG and PO is 0/1; -1 otherwise.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_FrameCheckPoConst( Abc_Frame_t * p, int iPoNum )
+{
+    Abc_Obj_t * pObj;
+    if ( p->pNtkCur == NULL )
+        return -1;
+    if ( !Abc_NtkIsStrash(p->pNtkCur) )
+        return -1;
+    if ( iPoNum < 0 || iPoNum >= Abc_NtkPoNum(p->pNtkCur) )
+        return -1;
+    pObj = Abc_NtkPo( p->pNtkCur, iPoNum );
+    if ( !Abc_AigNodeIsConst(Abc_ObjFanin0(pObj)) )
+        return -1;
+    return !Abc_ObjFaninC0(pObj);
+}
+void Abc_FrameCheckPoConstTest( Abc_Frame_t * p )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachPo( p->pNtkCur, pObj, i )
+        printf( "%d = %d\n", i, Abc_FrameCheckPoConst(p, i) );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/main/mainInit.c b/abc-build/src/base/main/mainInit.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/main/mainInit.c
@@ -0,0 +1,139 @@
+/**CFile****************************************************************
+
+  FileName    [mainInit.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The main package.]
+
+  Synopsis    [Initialization procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mainInit.c,v 1.3 2005/09/14 22:53:37 casem Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "mainInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+//#define USE_ABC2
+//#define USE_ABC85
+ 
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern void Abc_Init( Abc_Frame_t * pAbc );
+extern void Abc_End ( Abc_Frame_t * pAbc );
+extern void Io_Init( Abc_Frame_t * pAbc );
+extern void Io_End ( Abc_Frame_t * pAbc );
+extern void Cmd_Init( Abc_Frame_t * pAbc );
+extern void Cmd_End ( Abc_Frame_t * pAbc );
+extern void If_Init( Abc_Frame_t * pAbc );
+extern void If_End ( Abc_Frame_t * pAbc );
+extern void Map_Init( Abc_Frame_t * pAbc );
+extern void Map_End ( Abc_Frame_t * pAbc );
+extern void Mio_Init( Abc_Frame_t * pAbc );
+extern void Mio_End ( Abc_Frame_t * pAbc );
+extern void Super_Init( Abc_Frame_t * pAbc );
+extern void Super_End ( Abc_Frame_t * pAbc );
+extern void Libs_Init( Abc_Frame_t * pAbc );
+extern void Libs_End( Abc_Frame_t * pAbc );
+extern void Load_Init( Abc_Frame_t * pAbc );
+extern void Load_End( Abc_Frame_t * pAbc );
+extern void Scl_Init( Abc_Frame_t * pAbc );
+extern void Scl_End( Abc_Frame_t * pAbc );
+extern void Test_Init( Abc_Frame_t * pAbc );
+extern void Test_End( Abc_Frame_t * pAbc );
+extern void Abc2_Init( Abc_Frame_t * pAbc );
+extern void Abc2_End ( Abc_Frame_t * pAbc );
+extern void Abc85_Init( Abc_Frame_t * pAbc );
+extern void Abc85_End( Abc_Frame_t * pAbc );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts all the packages.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameInit( Abc_Frame_t * pAbc )
+{
+    Cmd_Init( pAbc );
+    Cmd_CommandExecute( pAbc, "set checkread" ); 
+    Io_Init( pAbc );
+    Abc_Init( pAbc );
+    If_Init( pAbc );
+    Map_Init( pAbc );
+    Mio_Init( pAbc );
+    Super_Init( pAbc );
+    Libs_Init( pAbc );
+    Load_Init( pAbc );
+    Scl_Init( pAbc );
+    Test_Init( pAbc );
+#ifdef USE_ABC2
+    Abc2_Init( pAbc );
+#endif
+#ifdef USE_ABC85
+    Abc85_Init( pAbc );
+#endif
+    EXT_ABC_INIT(pAbc) // plugin for external functionality
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Stops all the packages.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_FrameEnd( Abc_Frame_t * pAbc )
+{
+    Abc_End( pAbc );
+    Io_End( pAbc );
+    Cmd_End( pAbc );
+    If_End( pAbc );
+    Map_End( pAbc );
+    Mio_End( pAbc );
+    Super_End( pAbc );
+    Libs_End( pAbc );
+    Load_End( pAbc );
+    Scl_End( pAbc );
+    Test_End( pAbc );
+#ifdef USE_ABC2
+    Abc2_End( pAbc );
+#endif
+#ifdef USE_ABC85
+    Abc85_End( pAbc );
+#endif
+    EXT_ABC_END(pAbc) // plugin for external functionality
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/main/mainInt.h b/abc-build/src/base/main/mainInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/main/mainInt.h
@@ -0,0 +1,164 @@
+/**CFile****************************************************************
+
+  FileName    [mainInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The main package.]
+
+  Synopsis    [Internal declarations of the main package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mainInt.h,v 1.1 2008/05/14 22:13:13 wudenni Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__base__main__mainInt_h
+#define ABC__base__main__mainInt_h
+
+ 
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "main.h"
+#include "misc/tim/tim.h"
+#include "map/if/if.h"
+#include "aig/aig/aig.h"
+#include "aig/gia/gia.h"
+#include "proof/ssw/ssw.h"
+#include "proof/fra/fra.h"
+//#include "aig/nwk/nwkMerge.h"
+//#include "aig/ntl/ntlnwk.h"
+#include "misc/ext/ext.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+// the current version
+#define ABC_VERSION "UC Berkeley, ABC 1.01"
+
+// the maximum length of an input line 
+#define ABC_MAX_STR     (1<<15)
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+struct Abc_Frame_t_
+{
+    // general info
+    char *          sVersion;      // the name of the current version
+    char *          sBinary;       // the name of the binary running
+    // commands, aliases, etc
+    st__table *      tCommands;     // the command table
+    st__table *      tAliases;      // the alias table
+    st__table *      tFlags;        // the flag table
+    Vec_Ptr_t *     aHistory;      // the command history
+    // the functionality
+    Abc_Ntk_t *     pNtkCur;       // the current network
+    Abc_Ntk_t *     pNtkBestDelay; // the current network
+    Abc_Ntk_t *     pNtkBestArea;  // the current network
+    int             nSteps;        // the counter of different network processed
+    int             fSource;       // marks the source mode
+    int             fAutoexac;     // marks the autoexec mode
+	int				fBatchMode;	   // batch mode flag
+    int             fBridgeMode;   // bridge mode flag
+    // output streams
+    FILE *          Out;
+    FILE *          Err;
+    FILE *          Hst;
+    // used for runtime measurement
+    double          TimeCommand;   // the runtime of the last command
+    double          TimeTotal;     // the total runtime of all commands
+    // temporary storage for structural choices
+    Vec_Ptr_t *     vStore;        // networks to be used by choice
+    // decomposition package    
+    void *          pManDec;       // decomposition manager
+    void *          pManDsd;       // decomposition manager
+    DdManager *     dd;            // temporary BDD package
+    // libraries for mapping
+    void *          pLibLut;       // the current LUT library
+    void *          pLibBox;       // the current box library
+    void *          pLibGen;       // the current genlib
+    void *          pLibGen2;      // the current genlib
+    void *          pLibSuper;     // the current supergate library
+    void *          pLibScl;       // the current Liberty library
+    // timing constraints
+    char *          pDrivingCell;  // name of the driving cell
+    float           MaxLoad;       // maximum output load
+    // inductive don't-cares
+    Vec_Int_t *     vIndFlops;
+    int             nIndFrames;
+
+    // new code
+    Gia_Man_t *     pGia;          // alternative current network as a light-weight AIG
+    Gia_Man_t *     pGia2;         // copy of the above
+    Abc_Cex_t *     pCex;          // a counter-example to fail the current network
+    Abc_Cex_t *     pCex2;         // copy of the above
+    Vec_Ptr_t *     vCexVec;       // a vector of counter-examples if more than one PO fails
+    Vec_Ptr_t *     vPoEquivs;     // equivalence classes of isomorphic primary outputs
+    Vec_Int_t *     vStatuses;     // problem status for each output
+    Vec_Int_t *     vAbcObjIds;    // object IDs
+    int             Status;                // the status of verification problem (proved=1, disproved=0, undecided=-1)
+    int             nFrames;               // the number of time frames completed by BMC
+    Vec_Ptr_t *     vPlugInComBinPairs;    // pairs of command and its binary name
+	Vec_Ptr_t *     vLTLProperties_global; // related to LTL
+    void *          pSave1; 
+    void *          pSave2; 
+    void *          pSave3; 
+    void *          pSave4; 
+    void *          pAbc85Ntl;
+    void *          pAbc85Ntl2;
+    void *          pAbc85Best;
+    void *          pAbc85Delay;
+
+    EXT_ABC_FRAME   // plugin for external functionality
+};
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== mvMain.c ===========================================================*/
+extern ABC_DLL int             main( int argc, char * argv[] );
+/*=== mvInit.c ===================================================*/
+extern ABC_DLL void            Abc_FrameInit( Abc_Frame_t * pAbc );
+extern ABC_DLL void            Abc_FrameEnd( Abc_Frame_t * pAbc );
+/*=== mvFrame.c =====================================================*/
+extern ABC_DLL Abc_Frame_t *   Abc_FrameAllocate();
+extern ABC_DLL void            Abc_FrameDeallocate( Abc_Frame_t * p );
+/*=== mvUtils.c =====================================================*/
+extern ABC_DLL char *          Abc_UtilsGetVersion( Abc_Frame_t * pAbc );
+extern ABC_DLL char *          Abc_UtilsGetUsersInput( Abc_Frame_t * pAbc );
+extern ABC_DLL void            Abc_UtilsPrintHello( Abc_Frame_t * pAbc );
+extern ABC_DLL void            Abc_UtilsPrintUsage( Abc_Frame_t * pAbc, char * ProgName );
+extern ABC_DLL void            Abc_UtilsSource( Abc_Frame_t * pAbc );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/base/main/mainLib.c b/abc-build/src/base/main/mainLib.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/main/mainLib.c
@@ -0,0 +1,93 @@
+/**CFile****************************************************************
+
+  FileName    [main.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The main package.]
+
+  Synopsis    [Here everything starts.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: main.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "mainInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Initialization procedure for the library project.]
+
+  Description [Note that when Abc_Start() is run in a static library
+  project, it does not load the resource file by default. As a result, 
+  ABC is not set up the same way, as when it is run on a command line. 
+  For example, some error messages while parsing files will not be 
+  produced, and intermediate networks will not be checked for consistancy. 
+  One possibility is to load the resource file after Abc_Start() as follows:
+  Abc_UtilsSource(  Abc_FrameGetGlobalFrame() );]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_Start()
+{
+    Abc_Frame_t * pAbc;
+    // added to detect memory leaks:
+#if defined(_DEBUG) && defined(_MSC_VER) 
+    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
+#endif
+    // start the glocal frame
+    pAbc = Abc_FrameGetGlobalFrame();
+    // source the resource file
+//    Abc_UtilsSource( pAbc );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocation procedure for the library project.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_Stop()
+{
+    Abc_Frame_t * pAbc;
+    pAbc = Abc_FrameGetGlobalFrame();
+    // perform uninitializations
+    Abc_FrameEnd( pAbc );
+    // stop the framework
+    Abc_FrameDeallocate( pAbc );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/main/mainMC.c b/abc-build/src/base/main/mainMC.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/main/mainMC.c
@@ -0,0 +1,203 @@
+/**CFile****************************************************************
+
+  FileName    [mainMC.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The main package.]
+
+  Synopsis    [The main file for the model checker.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: main.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mainInt.h"
+#include "aig/aig/aig.h"
+#include "aig/saig/saig.h"
+#include "aig/fra/fra.h"
+#include "aig/ioa/ioa.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [The main() procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int main( int argc, char * argv[] )
+{
+    int fEnableBmcOnly = 0;  // enable to make it BMC-only
+
+    int fEnableCounter = 1;  // should be 1 in the final version
+    int fEnableComment = 0;  // should be 0 in the final version
+
+    Fra_Sec_t SecPar, * pSecPar = &SecPar;
+    FILE * pFile;
+    Aig_Man_t * pAig;
+    int RetValue = -1;
+    int Depth    = -1;
+    // BMC parameters
+    int nFrames  = 50;
+    int nSizeMax = 500000;
+    int nBTLimit = 10000;
+    int fRewrite = 0;
+    int fNewAlgo = 1;
+    int fVerbose = 0;
+    clock_t clkTotal = clock();
+
+    if ( argc != 2 )
+    {
+        printf( "  Expecting one command-line argument (an input file in AIGER format).\n" );
+        printf( "  usage: %s <file.aig>\n", argv[0] );
+        return 0;
+    }
+    pFile = fopen( argv[1], "r" );
+    if ( pFile == NULL )
+    {
+        printf( "  Cannot open input AIGER file \"%s\".\n", argv[1] );
+        printf( "  usage: %s <file.aig>\n", argv[0] );
+        return 0;
+    }
+    fclose( pFile );
+    pAig = Ioa_ReadAiger( argv[1], 1 );
+    if ( pAig == NULL )
+    {
+        printf( "  Parsing the AIGER file \"%s\" has failed.\n", argv[1] );
+        printf( "  usage: %s <file.aig>\n", argv[0] );
+        return 0;
+    }
+
+    Aig_ManSetRegNum( pAig, pAig->nRegs );
+    if ( !fEnableBmcOnly )
+    {
+        // perform BMC
+        if ( pAig->nRegs != 0 )
+            RetValue = Saig_ManBmcSimple( pAig, nFrames, nSizeMax, nBTLimit, fRewrite, fVerbose, NULL, 0 );
+
+        // perform full-blown SEC
+        if ( RetValue != 0 )
+        {
+            extern void Dar_LibStart();
+            extern void Dar_LibStop();
+            extern void Cnf_ManFree();
+
+            Fra_SecSetDefaultParams( pSecPar );
+            pSecPar->TimeLimit       = 600;
+            pSecPar->nFramesMax      =   4;  // the max number of frames used for induction
+            pSecPar->fPhaseAbstract  =   0;  // disable phase-abstraction
+            pSecPar->fSilent         =   1;  // disable phase-abstraction
+
+            Dar_LibStart();
+            RetValue = Fra_FraigSec( pAig, pSecPar, NULL );
+            Dar_LibStop();
+            Cnf_ManFree();
+        }
+    }
+
+    // perform BMC again
+    if ( RetValue == -1 && pAig->nRegs != 0 )
+    {
+        int nFrames  = 200;
+        int nSizeMax = 500000;
+        int nBTLimit = 10000000;
+        int fRewrite = 0;
+        RetValue = Saig_ManBmcSimple( pAig, nFrames, nSizeMax, nBTLimit, fRewrite, fVerbose, &Depth, 0 );
+        if ( RetValue != 0 )
+            RetValue = -1;
+    }
+
+    // decide how to report the output
+    pFile = stdout;
+
+    // report the result
+    if ( RetValue == 0 ) 
+    {
+//        fprintf(stdout, "s SATIFIABLE\n");
+        fprintf( pFile, "1" );
+        if ( fEnableCounter  )
+        {
+        printf( "\n" );
+        if ( pAig->pSeqModel )
+        Fra_SmlWriteCounterExample( pFile, pAig, pAig->pSeqModel );
+        }
+
+        if ( fEnableComment )
+        {
+        printf( "  # File %10s.  ", argv[1] );
+        PRT( "Time", clock() - clkTotal );
+        }
+
+        if ( pFile != stdout )
+            fclose(pFile);
+        Aig_ManStop( pAig );
+        exit(10);
+    } 
+    else if ( RetValue == 1 ) 
+    {
+//    fprintf(stdout, "s UNSATISFIABLE\n");
+        fprintf( pFile, "0" );
+
+        if ( fEnableComment )
+        {
+        printf( "  # File %10s.  ", argv[1] );
+        PRT( "Time", clock() - clkTotal );
+        }
+        printf( "\n" );
+
+        if ( pFile != stdout )
+            fclose(pFile);
+        Aig_ManStop( pAig );
+        exit(20);
+    } 
+    else // if ( RetValue == -1 ) 
+    {
+//    fprintf(stdout, "s UNKNOWN\n");
+        fprintf( pFile, "2" );
+
+        if ( fEnableComment )
+        {
+        printf( "  # File %10s.  ", argv[1] );
+        PRT( "Time", clock() - clkTotal );
+        }
+        printf( "\n" );
+
+        if ( pFile != stdout )
+            fclose(pFile);
+        Aig_ManStop( pAig );
+        exit(0);
+    }
+    return 0;
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/main/mainUtils.c b/abc-build/src/base/main/mainUtils.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/main/mainUtils.c
@@ -0,0 +1,311 @@
+/**CFile****************************************************************
+
+  FileName    [mainUtils.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+ 
+  PackageName [The main package.]
+
+  Synopsis    [Miscellaneous utilities.]
+ 
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mainUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "mainInt.h"
+
+#ifdef ABC_USE_READLINE
+#include <readline/readline.h>
+#include <readline/history.h>
+#endif
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static char * DateReadFromDateString( char * datestr );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_UtilsGetVersion( Abc_Frame_t * pAbc )
+{
+    static char Version[1000];
+    sprintf(Version, "%s (compiled %s %s)", ABC_VERSION, __DATE__, __TIME__);
+    return Version;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_UtilsGetUsersInput( Abc_Frame_t * pAbc )
+{
+    static char Prompt[5000];
+    sprintf( Prompt, "abc %02d> ", pAbc->nSteps );
+#ifdef ABC_USE_READLINE
+    {
+    static char * line = NULL;
+    if (line != NULL) ABC_FREE(line);
+    line = readline(Prompt);  
+    if (line == NULL){ printf("***EOF***\n"); exit(0); }
+    add_history(line);
+    return line;
+    }
+#else
+    {
+    char * pRetValue;
+    fprintf( pAbc->Out, "%s", Prompt );
+    pRetValue = fgets( Prompt, 5000, stdin );
+    return Prompt;
+    }
+#endif
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_UtilsPrintHello( Abc_Frame_t * pAbc )
+{
+    fprintf( pAbc->Out, "%s\n", pAbc->sVersion );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_UtilsPrintUsage( Abc_Frame_t * pAbc, char * ProgName )
+{
+    fprintf( pAbc->Err, "\n" );
+    fprintf( pAbc->Err,
+             "usage: %s [-c cmd] [-f script] [-h] [-o file] [-s] [-t type] [-T type] [-x] [-b] [file]\n", 
+             ProgName);
+    fprintf( pAbc->Err, "    -c cmd\texecute commands `cmd'\n");
+    fprintf( pAbc->Err, "    -q cmd\texecute commands `cmd' quietly\n");
+    fprintf( pAbc->Err, "    -C cmd\texecute commands `cmd', then continue in interactive mode\n");
+    fprintf( pAbc->Err, "    -F script\texecute commands from a script file and echo commands\n");
+    fprintf( pAbc->Err, "    -f script\texecute commands from a script file\n");
+    fprintf( pAbc->Err, "    -h\t\tprint the command usage\n");
+    fprintf( pAbc->Err, "    -o file\tspecify output filename to store the result\n");
+    fprintf( pAbc->Err, "    -s\t\tdo not read any initialization file\n");
+    fprintf( pAbc->Err, "    -t type\tspecify input type (blif_mv (default), blif_mvs, blif, or none)\n");
+    fprintf( pAbc->Err, "    -T type\tspecify output type (blif_mv (default), blif_mvs, blif, or none)\n");
+    fprintf( pAbc->Err, "    -x\t\tequivalent to '-t none -T none'\n");
+    fprintf( pAbc->Err, "    -b\t\trunning in bridge mode\n");
+    fprintf( pAbc->Err, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_UtilsSource( Abc_Frame_t * pAbc )
+{  
+#ifdef WIN32
+    if ( Cmd_CommandExecute(pAbc, "source abc.rc") )
+    {
+        if ( Cmd_CommandExecute(pAbc, "source ..\\abc.rc") == 0 )
+            printf( "Loaded \"abc.rc\" from the parent directory.\n" );
+        else if ( Cmd_CommandExecute(pAbc, "source ..\\..\\abc.rc") == 0 )
+            printf( "Loaded \"abc.rc\" from the grandparent directory.\n" );
+    }
+#else
+
+#if 0
+    {
+        char * sPath1, * sPath2;
+
+         // If .rc is present in both the home and current directories, then read
+         // it from the home directory.  Otherwise, read it from wherever it's located.
+        sPath1 = Extra_UtilFileSearch(".rc", "~/", "r");
+        sPath2 = Extra_UtilFileSearch(".rc", ".",  "r");
+  
+        if ( sPath1 && sPath2 ) {
+            /* ~/.rc == .rc : Source the file only once */
+            (void) Cmd_CommandExecute(pAbc, "source -s ~/.rc");
+        }
+        else {
+            if (sPath1) {
+                (void) Cmd_CommandExecute(pAbc, "source -s ~/.rc");
+            }
+            if (sPath2) {
+                (void) Cmd_CommandExecute(pAbc, "source -s .rc");
+            }
+        }
+        if ( sPath1 ) ABC_FREE(sPath1);
+        if ( sPath2 ) ABC_FREE(sPath2);
+    
+        /* execute the abc script which can be open with the "open_path" */
+        Cmd_CommandExecute( pAbc, "source -s abc.rc" );
+    }
+#endif
+
+#ifdef ABC_PYTHON_EMBED
+    if ( getenv("ABC_PYTHON_ABC_RC") )
+    {
+        /* read script file from $ABC_PYTHON_ABC_RC */
+
+        char * sPath = getenv("ABC_PYTHON_ABC_RC");
+        
+        if (sPath){
+            char * sCmd = ABC_ALLOC(char, strlen(sPath) + 50);
+            (void) sprintf(sCmd, "source -s %s", sPath);
+            (void) Cmd_CommandExecute(pAbc, sCmd);
+            ABC_FREE(sCmd);
+        }
+    }
+    else
+#endif /* #ifdef ABC_PYTHON_EMBED */
+
+    {
+        char * sPath1, * sPath2;
+        char * home;
+
+         // If .rc is present in both the home and current directories, then read
+         // it from the home directory.  Otherwise, read it from wherever it's located.
+        home = getenv("HOME");
+        if (home){
+            char * sPath3 = ABC_ALLOC(char, strlen(home) + 2);
+            (void) sprintf(sPath3, "%s/", home);
+            sPath1 = Extra_UtilFileSearch(".abc.rc", sPath3, "r");
+            ABC_FREE(sPath3);
+        }else
+            sPath1 = NULL;
+
+        sPath2 = Extra_UtilFileSearch(".abc.rc", ".",  "r");
+
+        if ( sPath1 && sPath2 ) {
+            /* ~/.rc == .rc : Source the file only once */
+            char *tmp_cmd = ABC_ALLOC(char, strlen(sPath1)+12);
+            (void) sprintf(tmp_cmd, "source -s %s", sPath1);
+            // (void) Cmd_CommandExecute(pAbc, "source -s ~/.abc.rc");
+            (void) Cmd_CommandExecute(pAbc, tmp_cmd);
+            ABC_FREE(tmp_cmd);
+        }
+        else {
+            if (sPath1) {
+                char *tmp_cmd = ABC_ALLOC(char, strlen(sPath1)+12);
+                (void) sprintf(tmp_cmd, "source -s %s", sPath1);
+                // (void) Cmd_CommandExecute(pAbc, "source -s ~/.abc.rc");
+                (void) Cmd_CommandExecute(pAbc, tmp_cmd);
+                ABC_FREE(tmp_cmd);
+            }
+            if (sPath2) {
+                char *tmp_cmd = ABC_ALLOC(char, strlen(sPath2)+12);
+                (void) sprintf(tmp_cmd, "source -s %s", sPath2);
+                // (void) Cmd_CommandExecute(pAbc, "source -s .abc.rc");
+                (void) Cmd_CommandExecute(pAbc, tmp_cmd);
+                ABC_FREE(tmp_cmd);
+            }
+        }
+        if ( sPath1 ) ABC_FREE(sPath1);
+        if ( sPath2 ) ABC_FREE(sPath2);
+
+        /* execute the abc script which can be open with the "open_path" */
+        Cmd_CommandExecute( pAbc, "source -s abc.rc" );
+    }
+    
+#endif //WIN32
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the date in a brief format assuming its coming from
+  the program `date'.]
+
+  Description [optional]
+
+  SideEffects []
+
+******************************************************************************/
+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;
+  }
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/main/module.make b/abc-build/src/base/main/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/main/module.make
@@ -0,0 +1,5 @@
+SRC +=  src/base/main/mainFrame.c \
+	src/base/main/mainInit.c \
+	src/base/main/mainLib.c \
+	src/base/main/libSupport.c \
+	src/base/main/mainUtils.c
diff --git a/abc-build/src/base/test/module.make b/abc-build/src/base/test/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/test/module.make
@@ -0,0 +1,1 @@
+SRC +=	src/base/test/test.c
diff --git a/abc-build/src/base/test/test.c b/abc-build/src/base/test/test.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/test/test.c
@@ -0,0 +1,70 @@
+/**CFile****************************************************************
+
+  FileName    [test.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Template package.]
+
+  Synopsis    []
+
+  Author      []
+  
+  Affiliation []
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: test.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Test_Init( Abc_Frame_t * pAbc )
+{
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Test_End( Abc_Frame_t * pAbc )
+{
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/ver/module.make b/abc-build/src/base/ver/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/ver/module.make
@@ -0,0 +1,4 @@
+SRC +=	src/base/ver/verCore.c \
+	src/base/ver/verFormula.c \
+	src/base/ver/verParse.c \
+	src/base/ver/verStream.c 
diff --git a/abc-build/src/base/ver/ver.h b/abc-build/src/base/ver/ver.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/ver/ver.h
@@ -0,0 +1,122 @@
+/**CFile****************************************************************
+
+  FileName    [ver.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Verilog parser.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 19, 2006.]
+
+  Revision    [$Id: ver.h,v 1.00 2006/08/19 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__base__ver__ver_h
+#define ABC__base__ver__ver_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "base/abc/abc.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ver_Man_t_       Ver_Man_t;
+typedef struct Ver_Stream_t_    Ver_Stream_t;
+
+struct Ver_Man_t_
+{
+    // internal parameters
+    int             fMapped;       // mapped verilog
+    int             fUseMemMan;    // allocate memory manager in the networks
+    int             fCheck;        // checks network for currectness
+    // input file stream
+    char *          pFileName;
+    Ver_Stream_t *  pReader;
+    int             fNameLast;
+    ProgressBar *   pProgress;
+    // current design
+    Abc_Des_t *     pDesign;
+    st__table *      tName2Suffix;
+    // error handling
+    FILE *          Output;
+    int             fTopLevel;
+    int             fError;
+    char            sError[2000];
+    // intermediate structures
+    Vec_Ptr_t *     vNames;  
+    Vec_Ptr_t *     vStackFn;
+    Vec_Int_t *     vStackOp;
+    Vec_Int_t *     vPerm;
+};
+
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                             ITERATORS                            ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== verCore.c ========================================================*/
+extern Abc_Des_t *    Ver_ParseFile( char * pFileName, Abc_Des_t * pGateLib, int fCheck, int fUseMemMan );
+extern void           Ver_ParsePrintErrorMessage( Ver_Man_t * p );
+/*=== verFormula.c ========================================================*/
+extern void *         Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage );
+extern void *         Ver_FormulaReduction( char * pFormula, void * pMan, Vec_Ptr_t * vNames, char * pErrorMessage );
+/*=== verParse.c ========================================================*/
+extern int            Ver_ParseSkipComments( Ver_Man_t * p );
+extern char *         Ver_ParseGetName( Ver_Man_t * p );
+/*=== verStream.c ========================================================*/
+extern Ver_Stream_t * Ver_StreamAlloc( char * pFileName );
+extern void           Ver_StreamFree( Ver_Stream_t * p );
+extern char *         Ver_StreamGetFileName( Ver_Stream_t * p );
+extern int            Ver_StreamGetFileSize( Ver_Stream_t * p );
+extern int            Ver_StreamGetCurPosition( Ver_Stream_t * p );
+extern int            Ver_StreamGetLineNumber( Ver_Stream_t * p );
+
+extern int            Ver_StreamIsOkey( Ver_Stream_t * p );
+extern char           Ver_StreamScanChar( Ver_Stream_t * p );
+extern char           Ver_StreamPopChar( Ver_Stream_t * p );
+extern void           Ver_StreamSkipChars( Ver_Stream_t * p, char * pCharsToSkip );
+extern void           Ver_StreamSkipToChars( Ver_Stream_t * p, char * pCharsToStop );
+extern char *         Ver_StreamGetWord( Ver_Stream_t * p, char * pCharsToStop );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/base/ver/verCore.c b/abc-build/src/base/ver/verCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/ver/verCore.c
@@ -0,0 +1,3015 @@
+/**CFile****************************************************************
+
+  FileName    [verCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Verilog parser.]
+
+  Synopsis    [Parses several flavors of structural Verilog.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 19, 2006.]
+
+  Revision    [$Id: verCore.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ver.h"
+#include "map/mio/mio.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// types of verilog signals
+typedef enum { 
+    VER_SIG_NONE = 0,
+    VER_SIG_INPUT,
+    VER_SIG_OUTPUT,
+    VER_SIG_INOUT,
+    VER_SIG_REG,
+    VER_SIG_WIRE
+} Ver_SignalType_t;
+
+// types of verilog gates
+typedef enum { 
+    VER_GATE_AND = 0,
+    VER_GATE_OR,
+    VER_GATE_XOR,
+    VER_GATE_BUF,
+    VER_GATE_NAND,
+    VER_GATE_NOR,
+    VER_GATE_XNOR,
+    VER_GATE_NOT
+} Ver_GateType_t;
+
+static Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Des_t * pGateLib );
+static void Ver_ParseStop( Ver_Man_t * p );
+static void Ver_ParseFreeData( Ver_Man_t * p );
+static void Ver_ParseInternal( Ver_Man_t * p );
+static int  Ver_ParseModule( Ver_Man_t * p );
+static int  Ver_ParseSignal( Ver_Man_t * p, Abc_Ntk_t * pNtk, Ver_SignalType_t SigType );
+static int  Ver_ParseAlways( Ver_Man_t * p, Abc_Ntk_t * pNtk );
+static int  Ver_ParseInitial( Ver_Man_t * p, Abc_Ntk_t * pNtk );
+static int  Ver_ParseAssign( Ver_Man_t * p, Abc_Ntk_t * pNtk );
+static int  Ver_ParseGateStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_GateType_t GateType );
+static int  Ver_ParseFlopStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk );
+static int  Ver_ParseGate( Ver_Man_t * p, Abc_Ntk_t * pNtk, Mio_Gate_t * pGate );
+static int  Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox );
+static int  Ver_ParseConnectBox( Ver_Man_t * pMan, Abc_Obj_t * pBox );
+static int  Ver_ParseAttachBoxes( Ver_Man_t * pMan );
+
+static Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName );
+static Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName );
+static Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pNetLI, Abc_Obj_t * pNetLO );
+static Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet );
+
+static void Ver_ParseRemoveSuffixTable( Ver_Man_t * pMan );
+
+static inline int Ver_NtkIsDefined( Abc_Ntk_t * pNtkBox )  { assert( pNtkBox->pName );     return Abc_NtkPiNum(pNtkBox) || Abc_NtkPoNum(pNtkBox);  }
+static inline int Ver_ObjIsConnected( Abc_Obj_t * pObj )   { assert( Abc_ObjIsBox(pObj) ); return Abc_ObjFaninNum(pObj) || Abc_ObjFanoutNum(pObj); }
+
+int glo_fMapped = 0; // this is bad!
+
+typedef struct Ver_Bundle_t_    Ver_Bundle_t;
+struct Ver_Bundle_t_
+{
+    char *          pNameFormal;   // the name of the formal net
+    Vec_Ptr_t *     vNetsActual;   // the vector of actual nets (MSB to LSB)
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Start parser.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Des_t * pGateLib )
+{
+    Ver_Man_t * p;
+    p = ABC_ALLOC( Ver_Man_t, 1 );
+    memset( p, 0, sizeof(Ver_Man_t) );
+    p->pFileName = pFileName;
+    p->pReader   = Ver_StreamAlloc( pFileName );
+    if ( p->pReader == NULL )
+    {
+        ABC_FREE( p );
+        return NULL;
+    }
+    p->Output    = stdout;
+    p->vNames    = Vec_PtrAlloc( 100 );
+    p->vStackFn  = Vec_PtrAlloc( 100 );
+    p->vStackOp  = Vec_IntAlloc( 100 );
+    p->vPerm     = Vec_IntAlloc( 100 );
+    // create the design library and assign the technology library
+    p->pDesign   = Abc_DesCreate( pFileName );
+    p->pDesign->pLibrary = pGateLib;
+    // derive library from SCL
+//    if ( Abc_FrameReadLibScl() )
+//        Abc_SclInstallGenlib( Abc_FrameReadLibScl(), 0, 0, 0 );
+    p->pDesign->pGenlib = Abc_FrameReadLibGen();
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop parser.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ver_ParseStop( Ver_Man_t * p )
+{
+    if ( p->pProgress )
+        Extra_ProgressBarStop( p->pProgress );
+    Ver_StreamFree( p->pReader );
+    Vec_PtrFree( p->vNames   );
+    Vec_PtrFree( p->vStackFn );
+    Vec_IntFree( p->vStackOp );
+    Vec_IntFree( p->vPerm );
+    ABC_FREE( p );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [File parser.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Des_t * Ver_ParseFile( char * pFileName, Abc_Des_t * pGateLib, int fCheck, int fUseMemMan )
+{
+    Ver_Man_t * p;
+    Abc_Des_t * pDesign;
+    // start the parser
+    p = Ver_ParseStart( pFileName, pGateLib );
+    p->fMapped    = glo_fMapped;
+    p->fCheck     = fCheck;
+    p->fUseMemMan = fUseMemMan;
+    if ( glo_fMapped )
+    {
+        Hop_ManStop((Hop_Man_t *)p->pDesign->pManFunc);
+        p->pDesign->pManFunc = NULL;
+    }
+    // parse the file
+    Ver_ParseInternal( p );
+    // save the result
+    pDesign = p->pDesign;
+    p->pDesign = NULL;
+    // stop the parser
+    Ver_ParseStop( p );
+    return pDesign;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [File parser.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ver_ParseInternal( Ver_Man_t * pMan )
+{
+    Abc_Ntk_t * pNtk;
+    char * pToken;
+    int i;
+
+    // preparse the modeles
+    pMan->pProgress = Extra_ProgressBarStart( stdout, Ver_StreamGetFileSize(pMan->pReader) );
+    while ( 1 )
+    {
+        // get the next token
+        pToken = Ver_ParseGetName( pMan );
+        if ( pToken == NULL )
+            break;
+        if ( strcmp( pToken, "module" ) )
+        {
+            sprintf( pMan->sError, "Cannot read \"module\" directive." );
+            Ver_ParsePrintErrorMessage( pMan );
+            return;
+        }
+        // parse the module
+        if ( !Ver_ParseModule(pMan) )
+            return;
+    }
+    Extra_ProgressBarStop( pMan->pProgress );
+    pMan->pProgress = NULL;
+
+    // process defined and undefined boxes
+    if ( !Ver_ParseAttachBoxes( pMan ) )
+        return;
+
+    // connect the boxes and check
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i )
+    {
+        // fix the dangling nets
+        Abc_NtkFinalizeRead( pNtk );
+        // check the network for correctness
+        if ( pMan->fCheck && !Abc_NtkCheckRead( pNtk ) )
+        {
+            pMan->fTopLevel = 1;
+            sprintf( pMan->sError, "The network check has failed for network %s.", pNtk->pName );
+            Ver_ParsePrintErrorMessage( pMan );
+            return;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [File parser.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ver_ParseFreeData( Ver_Man_t * p )
+{
+    if ( p->pDesign )
+    {
+        Abc_DesFree( p->pDesign, NULL );
+        p->pDesign = NULL;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the error message including the file name and line number.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ver_ParsePrintErrorMessage( Ver_Man_t * p )
+{
+    p->fError = 1;
+    if ( p->fTopLevel ) // the line number is not given
+        fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError );
+    else // print the error message with the line number
+        fprintf( p->Output, "%s (line %d): %s\n", 
+            p->pFileName, Ver_StreamGetLineNumber(p->pReader), p->sError );
+    // free the data
+    Ver_ParseFreeData( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the network by name or create a new blackbox network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Ver_ParseFindOrCreateNetwork( Ver_Man_t * pMan, char * pName )
+{
+    Abc_Ntk_t * pNtkNew;
+    // check if the network exists
+    if ( (pNtkNew = Abc_DesFindModelByName( pMan->pDesign, pName )) )
+        return pNtkNew;
+//printf( "Creating network %s.\n", pName );
+    // create new network
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, pMan->fUseMemMan );
+    pNtkNew->pName = Extra_UtilStrsav( pName );
+    pNtkNew->pSpec = NULL;
+    // add module to the design
+    Abc_DesAddModel( pMan->pDesign, pNtkNew );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the network by name or create a new blackbox network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Ver_ParseFindNet( Abc_Ntk_t * pNtk, char * pName )
+{
+    Abc_Obj_t * pObj;
+    if ( (pObj = Abc_NtkFindNet(pNtk, pName)) )
+        return pObj;
+    if ( !strcmp( pName, "1\'b0" ) || !strcmp( pName, "1\'bx" ) )
+        return Abc_NtkFindOrCreateNet( pNtk, "1\'b0" );
+    if ( !strcmp( pName, "1\'b1" ) )
+        return Abc_NtkFindOrCreateNet( pNtk, "1\'b1" );
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from the blackbox type into a different one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseConvertNetwork( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, int fMapped )
+{
+    if ( fMapped )
+    {
+        // convert from the blackbox into the network with local functions representated by AIGs
+        if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX )
+        {
+            // change network type
+            assert( pNtk->pManFunc == NULL );
+            pNtk->ntkFunc = ABC_FUNC_MAP;
+            pNtk->pManFunc = pMan->pDesign->pGenlib;
+        }
+        else if ( pNtk->ntkFunc != ABC_FUNC_MAP )
+        {
+            sprintf( pMan->sError, "The network %s appears to have both gates and assign statements. Currently such network are not allowed. One way to fix this problem might be to replace assigns by buffers from the library.", pNtk->pName );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+    }
+    else
+    {
+        // convert from the blackbox into the network with local functions representated by AIGs
+        if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX )
+        {
+            // change network type
+            assert( pNtk->pManFunc == NULL );
+            pNtk->ntkFunc = ABC_FUNC_AIG;
+            pNtk->pManFunc = pMan->pDesign->pManFunc;
+        }
+        else if ( pNtk->ntkFunc != ABC_FUNC_AIG )
+        {
+            sprintf( pMan->sError, "The network %s appears to have both gates and assign statements. Currently such network are not allowed. One way to fix this problem might be to replace assigns by buffers from the library.", pNtk->pName );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses one Verilog module.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseModule( Ver_Man_t * pMan )
+{
+    Mio_Gate_t * pGate;
+    Ver_Stream_t * p = pMan->pReader;
+    Abc_Ntk_t * pNtk, * pNtkTemp;
+    char * pWord, Symbol;
+    int RetValue;
+
+    // get the network name
+    pWord = Ver_ParseGetName( pMan );
+
+    // get the network with this name
+    pNtk = Ver_ParseFindOrCreateNetwork( pMan, pWord );
+
+    // make sure we stopped at the opening paranthesis
+    if ( Ver_StreamPopChar(p) != '(' )
+    {
+        sprintf( pMan->sError, "Cannot find \"(\" after \"module\" in network %s.", pNtk->pName );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+
+    // skip to the end of parantheses
+    do {
+        if ( Ver_ParseGetName( pMan ) == NULL )
+            return 0;
+        Symbol = Ver_StreamPopChar(p);
+    } while ( Symbol == ',' );
+    assert( Symbol == ')' );
+    if ( !Ver_ParseSkipComments( pMan ) )
+        return 0;
+    Symbol = Ver_StreamPopChar(p);
+    if ( Symbol != ';' )
+    {
+        sprintf( pMan->sError, "Expected closing paranthesis after \"module\"." );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+
+    // parse the inputs/outputs/registers/wires/inouts
+    while ( 1 )
+    {
+        Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL );
+        pWord = Ver_ParseGetName( pMan );
+        if ( pWord == NULL )
+            return 0;
+        if ( !strcmp( pWord, "input" ) )
+            RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_INPUT );
+        else if ( !strcmp( pWord, "output" ) )
+            RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_OUTPUT );
+        else if ( !strcmp( pWord, "reg" ) )
+            RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_REG );
+        else if ( !strcmp( pWord, "wire" ) )
+            RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_WIRE );
+        else if ( !strcmp( pWord, "inout" ) )
+            RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_INOUT );
+        else 
+            break;
+        if ( RetValue == 0 )
+            return 0;
+    }
+
+    // parse the remaining statements
+    while ( 1 )
+    {
+        Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL );
+
+        if ( !strcmp( pWord, "and" ) )
+            RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_AND );
+        else if ( !strcmp( pWord, "or" ) )
+            RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_OR );
+        else if ( !strcmp( pWord, "xor" ) )
+            RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_XOR );
+        else if ( !strcmp( pWord, "buf" ) )
+            RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_BUF );
+        else if ( !strcmp( pWord, "nand" ) )
+            RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NAND );
+        else if ( !strcmp( pWord, "nor" ) )
+            RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NOR );
+        else if ( !strcmp( pWord, "xnor" ) )
+            RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_XNOR );
+        else if ( !strcmp( pWord, "not" ) )
+            RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NOT );
+
+        else if ( !strcmp( pWord, "dff" ) )
+            RetValue = Ver_ParseFlopStandard( pMan, pNtk );
+
+        else if ( !strcmp( pWord, "assign" ) )
+            RetValue = Ver_ParseAssign( pMan, pNtk );
+        else if ( !strcmp( pWord, "always" ) )
+            RetValue = Ver_ParseAlways( pMan, pNtk );
+        else if ( !strcmp( pWord, "initial" ) )
+            RetValue = Ver_ParseInitial( pMan, pNtk );
+        else if ( !strcmp( pWord, "endmodule" ) )
+            break;
+        else if ( pMan->pDesign->pGenlib && (pGate = Mio_LibraryReadGateByName((Mio_Library_t *)pMan->pDesign->pGenlib, pWord, NULL)) ) // current design
+            RetValue = Ver_ParseGate( pMan, pNtk, pGate );
+//        else if ( pMan->pDesign->pLibrary && st__lookup(pMan->pDesign->pLibrary->tModules, pWord, (char**)&pNtkTemp) ) // gate library
+//            RetValue = Ver_ParseGate( pMan, pNtkTemp );
+        else // assume this is the box used in the current design
+        {
+            pNtkTemp = Ver_ParseFindOrCreateNetwork( pMan, pWord );
+            RetValue = Ver_ParseBox( pMan, pNtk, pNtkTemp );
+        }
+        if ( RetValue == 0 )
+            return 0;
+        // skip the comments
+        if ( !Ver_ParseSkipComments( pMan ) )
+            return 0;
+        // get new word
+        pWord = Ver_ParseGetName( pMan );
+        if ( pWord == NULL )
+            return 0;
+    }
+
+    // convert from the blackbox into the network with local functions representated by AIGs
+    if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX )
+    {
+        if ( Abc_NtkNodeNum(pNtk) > 0 || Abc_NtkBoxNum(pNtk) > 0 )
+        {
+            if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) )
+                return 0;
+        }
+        else
+        {
+            Abc_Obj_t * pObj, * pBox, * pTerm;
+            int i; 
+            pBox = Abc_NtkCreateBlackbox(pNtk);
+            Abc_NtkForEachPi( pNtk, pObj, i )
+            {
+                pTerm = Abc_NtkCreateBi(pNtk);
+                Abc_ObjAddFanin( pTerm, Abc_ObjFanout0(pObj) );
+                Abc_ObjAddFanin( pBox, pTerm );
+            }
+            Abc_NtkForEachPo( pNtk, pObj, i )
+            {
+                pTerm = Abc_NtkCreateBo(pNtk);
+                Abc_ObjAddFanin( pTerm, pBox );
+                Abc_ObjAddFanin( Abc_ObjFanin0(pObj), pTerm );
+            }
+        }
+    }
+
+    // remove the table if needed
+    Ver_ParseRemoveSuffixTable( pMan );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Lookups the suffix of the signal of the form [m:n].]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseLookupSuffix( Ver_Man_t * pMan, char * pWord, int * pnMsb, int * pnLsb )
+{
+    unsigned Value;
+    *pnMsb = *pnLsb = -1;
+    if ( pMan->tName2Suffix == NULL )
+        return 1;
+    if ( ! st__lookup( pMan->tName2Suffix, (char *)pWord, (char **)&Value ) )
+        return 1;
+    *pnMsb = (Value >> 8) & 0xff;
+    *pnLsb = Value & 0xff;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Lookups the suffix of the signal of the form [m:n].]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseInsertsSuffix( Ver_Man_t * pMan, char * pWord, int nMsb, int nLsb )
+{
+    unsigned Value;
+    if ( pMan->tName2Suffix == NULL )
+        pMan->tName2Suffix = st__init_table( strcmp, st__strhash );
+    if ( st__is_member( pMan->tName2Suffix, pWord ) )
+        return 1;
+    assert( nMsb >= 0 && nMsb < 128 );
+    assert( nLsb >= 0 && nLsb < 128 );
+    Value = (nMsb << 8) | nLsb;
+    st__insert( pMan->tName2Suffix, Extra_UtilStrsav(pWord), (char *)(ABC_PTRUINT_T)Value );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Lookups the suffic of the signal of the form [m:n].]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ver_ParseRemoveSuffixTable( Ver_Man_t * pMan )
+{
+    st__generator * gen;
+    char * pKey, * pValue;
+    if ( pMan->tName2Suffix == NULL )
+        return;
+    st__foreach_item( pMan->tName2Suffix, gen, (const char **)&pKey, (char **)&pValue )
+        ABC_FREE( pKey );
+    st__free_table( pMan->tName2Suffix );
+    pMan->tName2Suffix = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determine signal prefix of the form [Beg:End].]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseSignalPrefix( Ver_Man_t * pMan, char ** ppWord, int * pnMsb, int * pnLsb )
+{
+    char * pWord = *ppWord, * pTemp;
+    int nMsb, nLsb;
+    assert( pWord[0] == '[' );
+    // get the beginning
+    nMsb = atoi( pWord + 1 );
+    // find the splitter
+    while ( *pWord && *pWord != ':' && *pWord != ']' )
+        pWord++;
+    if ( *pWord == 0 )
+    {
+        sprintf( pMan->sError, "Cannot find closing bracket in this line." );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    if ( *pWord == ']' )
+        nLsb = nMsb;
+    else
+    {
+        assert( *pWord == ':' );
+        nLsb = atoi( pWord + 1 );
+        // find the closing paranthesis
+        while ( *pWord && *pWord != ']' )
+            pWord++;
+        if ( *pWord == 0 )
+        {
+            sprintf( pMan->sError, "Cannot find closing bracket in this line." );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+        assert( *pWord == ']' );
+        pWord++;
+
+        // fix the case when \<name> follows after [] without space
+        if ( *pWord == '\\' )
+        {
+            pWord++;
+            pTemp = pWord;
+            while ( *pTemp && *pTemp != ' ' )
+                pTemp++;
+            if ( *pTemp == ' ' )
+                *pTemp = 0;
+        }
+    }
+    assert( nMsb >= 0 && nLsb >= 0 );
+    // return
+    *ppWord = pWord;
+    *pnMsb = nMsb;
+    *pnLsb = nLsb;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determine signal suffix of the form [m:n].]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseSignalSuffix( Ver_Man_t * pMan, char * pWord, int * pnMsb, int * pnLsb )
+{
+    char * pCur;
+    int Length;
+    Length = strlen(pWord);
+    assert( pWord[Length-1] == ']' );
+    // walk backward
+    for ( pCur = pWord + Length - 2; pCur != pWord; pCur-- )
+        if ( *pCur == ':' || *pCur == '[' )
+            break;
+    if ( pCur == pWord )
+    {
+        sprintf( pMan->sError, "Cannot find opening bracket in signal name %s.", pWord );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    if ( *pCur == '[' )
+    {
+        *pnMsb = *pnLsb = atoi(pCur+1);
+        *pCur = 0;
+        return 1;
+    }
+    assert( *pCur == ':' );
+    // get the end of the interval
+    *pnLsb = atoi(pCur+1);
+    // find the beginning
+    for ( pCur = pWord + Length - 2; pCur != pWord; pCur-- )
+        if ( *pCur == '[' )
+            break;
+    if ( pCur == pWord )
+    {
+        sprintf( pMan->sError, "Cannot find opening bracket in signal name %s.", pWord );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    assert( *pCur == '[' );
+    // get the beginning of the interval
+    *pnMsb = atoi(pCur+1);
+    // cut the word
+    *pCur = 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the values of constant bits.]
+
+  Description [The resulting bits are in MSB to LSB order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseConstant( Ver_Man_t * pMan, char * pWord )
+{
+    int nBits, i;
+    assert( pWord[0] >= '1' && pWord[1] <= '9' );
+    nBits = atoi(pWord);
+    // find the next symbol \'
+    while ( *pWord && *pWord != '\'' )
+        pWord++;
+    if ( *pWord == 0 )
+    {
+        sprintf( pMan->sError, "Cannot find symbol \' in the constant." );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    assert( *pWord == '\'' );
+    pWord++;
+    if ( *pWord != 'b' )
+    {
+        sprintf( pMan->sError, "Currently can only handle binary constants." );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    pWord++;
+    // scan the bits
+    Vec_PtrClear( pMan->vNames );
+    for ( i = 0; i < nBits; i++ )
+    {
+      if ( pWord[i] != '0' && pWord[i] != '1' && pWord[i] != 'x' )
+      {
+         sprintf( pMan->sError, "Having problem parsing the binary constant." );
+         Ver_ParsePrintErrorMessage( pMan );
+         return 0;
+      }
+      if ( pWord[i] == 'x' ) 
+          Vec_PtrPush( pMan->vNames, (void *)0 );
+      else 
+          Vec_PtrPush( pMan->vNames, (void *)(ABC_PTRUINT_T)(pWord[i]-'0') );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses one directive.]
+
+  Description [The signals are added in the order from LSB to MSB.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseSignal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_SignalType_t SigType )
+{
+    Ver_Stream_t * p = pMan->pReader;
+    char Buffer[1000], Symbol, * pWord;
+    int nMsb, nLsb, Bit, Limit, i;
+    nMsb = nLsb = -1;
+    while ( 1 )
+    {
+        // get the next word
+        pWord = Ver_ParseGetName( pMan );
+        if ( pWord == NULL )
+            return 0;
+
+        // check if the range is specified
+        if ( pWord[0] == '[' && !pMan->fNameLast )
+        {
+            assert( nMsb == -1 && nLsb == -1 );
+            Ver_ParseSignalPrefix( pMan, &pWord, &nMsb, &nLsb );
+            // check the case when there is space between bracket and the next word
+            if ( *pWord == 0 )
+            {
+                // get the signal name
+                pWord = Ver_ParseGetName( pMan );
+                if ( pWord == NULL )
+                    return 0;
+            }
+        }
+
+        // create signals
+        if ( nMsb == -1 && nLsb == -1 )
+        {
+            if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT )
+                Ver_ParseCreatePi( pNtk, pWord );
+            if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT )
+                Ver_ParseCreatePo( pNtk, pWord );
+            if ( SigType == VER_SIG_WIRE || SigType == VER_SIG_REG )
+                Abc_NtkFindOrCreateNet( pNtk, pWord );
+        }
+        else
+        {
+            assert( nMsb >= 0 && nLsb >= 0 );
+            // add to the hash table
+            Ver_ParseInsertsSuffix( pMan, pWord, nMsb, nLsb );
+            // add signals from Lsb to Msb
+            Limit = nMsb > nLsb? nMsb - nLsb + 1: nLsb - nMsb + 1;
+            for ( i = 0, Bit = nLsb; i < Limit; i++, Bit = nMsb > nLsb ? Bit + 1: Bit - 1  )
+            {
+                sprintf( Buffer, "%s[%d]", pWord, Bit );
+                if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT )
+                    Ver_ParseCreatePi( pNtk, Buffer );
+                if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT )
+                    Ver_ParseCreatePo( pNtk, Buffer );
+                if ( SigType == VER_SIG_WIRE || SigType == VER_SIG_REG )
+                    Abc_NtkFindOrCreateNet( pNtk, Buffer );
+            }
+        }
+
+        Symbol = Ver_StreamPopChar(p);
+        if ( Symbol == ',' )
+            continue;
+        if ( Symbol == ';' )
+            return 1;
+        break;
+    }
+    sprintf( pMan->sError, "Cannot parse signal line (expected , or ;)." );
+    Ver_ParsePrintErrorMessage( pMan );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses one directive.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseAlways( Ver_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+    Ver_Stream_t * p = pMan->pReader;
+    Abc_Obj_t * pNet, * pNet2;
+    int fStopAfterOne;
+    char * pWord, * pWord2;
+    char Symbol;
+    // parse the directive 
+    pWord = Ver_ParseGetName( pMan );
+    if ( pWord == NULL )
+        return 0;
+    if ( pWord[0] == '@' )
+    {
+        Ver_StreamSkipToChars( p, ")" );
+        Ver_StreamPopChar(p);
+        // parse the directive 
+        pWord = Ver_ParseGetName( pMan );
+        if ( pWord == NULL )
+            return 0;
+    }
+    // decide how many statements to parse
+    fStopAfterOne = 0;
+    if ( strcmp( pWord, "begin" ) )
+        fStopAfterOne = 1;
+    // iterate over the initial states
+    while ( 1 )
+    {
+        if ( !fStopAfterOne )
+        {
+            // get the name of the output signal
+            pWord = Ver_ParseGetName( pMan );
+            if ( pWord == NULL )
+                return 0;
+            // look for the end of directive
+            if ( !strcmp( pWord, "end" ) )
+                break;
+        }
+        // get the fanout net
+        pNet = Ver_ParseFindNet( pNtk, pWord );
+        if ( pNet == NULL )
+        {
+            sprintf( pMan->sError, "Cannot read the always statement for %s (output wire is not defined).", pWord );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+        // get the equality sign
+        Symbol = Ver_StreamPopChar(p);
+        if ( Symbol != '<' && Symbol != '=' )
+        {
+            sprintf( pMan->sError, "Cannot read the assign statement for %s (expected <= or =).", pWord );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+        if ( Symbol == '<' )
+            Ver_StreamPopChar(p);
+        // skip the comments
+        if ( !Ver_ParseSkipComments( pMan ) )
+            return 0;
+        // get the second name
+        pWord2 = Ver_ParseGetName( pMan );
+        if ( pWord2 == NULL )
+            return 0;
+        // check if the name is complemented
+        if ( pWord2[0] == '~' )
+        {
+            pNet2 = Ver_ParseFindNet( pNtk, pWord2+1 );
+            pNet2 = Ver_ParseCreateInv( pNtk, pNet2 );
+        }
+        else
+            pNet2 = Ver_ParseFindNet( pNtk, pWord2 );
+        if ( pNet2 == NULL )
+        {
+            sprintf( pMan->sError, "Cannot read the always statement for %s (input wire is not defined).", pWord2 );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+        // create the latch
+        Ver_ParseCreateLatch( pNtk, pNet2, pNet );
+        // remove the last symbol
+        Symbol = Ver_StreamPopChar(p);
+        assert( Symbol == ';' );
+        // quit if only one directive
+        if ( fStopAfterOne )
+            break;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses one directive.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseInitial( Ver_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+    Ver_Stream_t * p = pMan->pReader;
+    Abc_Obj_t * pNode, * pNet;
+    int fStopAfterOne;
+    char * pWord, * pEquation;
+    char Symbol;
+    // parse the directive 
+    pWord = Ver_ParseGetName( pMan );
+    if ( pWord == NULL )
+        return 0;
+    // decide how many statements to parse
+    fStopAfterOne = 0;
+    if ( strcmp( pWord, "begin" ) )
+        fStopAfterOne = 1;
+    // iterate over the initial states
+    while ( 1 )
+    {
+        if ( !fStopAfterOne )
+        {
+            // get the name of the output signal
+            pWord = Ver_ParseGetName( pMan );
+            if ( pWord == NULL )
+                return 0;
+            // look for the end of directive
+            if ( !strcmp( pWord, "end" ) )
+                break;
+        }
+        // get the fanout net
+        pNet = Ver_ParseFindNet( pNtk, pWord );
+        if ( pNet == NULL )
+        {
+            sprintf( pMan->sError, "Cannot read the initial statement for %s (output wire is not defined).", pWord );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+        // get the equality sign
+        Symbol = Ver_StreamPopChar(p);
+        if ( Symbol != '<' && Symbol != '=' )
+        {
+            sprintf( pMan->sError, "Cannot read the assign statement for %s (expected <= or =).", pWord );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+        if ( Symbol == '<' )
+            Ver_StreamPopChar(p);
+        // skip the comments
+        if ( !Ver_ParseSkipComments( pMan ) )
+            return 0;
+        // get the second name
+        pEquation = Ver_StreamGetWord( p, ";" );
+        if ( pEquation == NULL )
+            return 0;
+        // find the corresponding latch
+        if ( Abc_ObjFaninNum(pNet) == 0 )
+        {
+            sprintf( pMan->sError, "Cannot find the latch to assign the initial value." );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+        pNode = Abc_ObjFanin0(Abc_ObjFanin0(pNet));
+        assert( Abc_ObjIsLatch(pNode) );
+        // set the initial state
+        if ( !strcmp(pEquation, "0") || !strcmp(pEquation, "1\'b0") )
+            Abc_LatchSetInit0( pNode );
+        else if ( !strcmp(pEquation, "1") || !strcmp(pEquation, "1\'b1") )
+            Abc_LatchSetInit1( pNode );
+//        else if ( !strcmp(pEquation, "2") )
+//            Abc_LatchSetInitDc( pNode );
+        else 
+        {
+            sprintf( pMan->sError, "Incorrect initial value of the latch %s.", Abc_ObjName(pNet) );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+        // remove the last symbol
+        Symbol = Ver_StreamPopChar(p);
+        assert( Symbol == ';' );
+        // quit if only one directive
+        if ( fStopAfterOne )
+            break;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses one directive.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseAssign( Ver_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+    char Buffer[1000], Buffer2[1000];
+    Ver_Stream_t * p = pMan->pReader;
+    Abc_Obj_t * pNode, * pNet;
+    char * pWord, * pName, * pEquation;
+    Hop_Obj_t * pFunc;
+    char Symbol;
+    int i, Bit, Limit, Length, fReduction;
+    int nMsb, nLsb;
+
+//    if ( Ver_StreamGetLineNumber(p) == 2756 )
+//    {
+//        int x = 0;
+//    }
+
+    // convert from the blackbox into the network with local functions representated by AIGs
+    if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) )
+        return 0;
+
+    while ( 1 )
+    {
+        // get the name of the output signal
+        pWord = Ver_ParseGetName( pMan );
+        if ( pWord == NULL )
+            return 0;
+        if ( strcmp(pWord, "#1") == 0 )
+            continue;
+        // check for vector-inputs
+        if ( !Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb ) )
+            return 0;
+        // handle special case of constant assignment
+        if ( nMsb >= 0 && nLsb >= 0 )
+        {
+            // save the fanout name
+            strcpy( Buffer, pWord );
+            // get the equality sign
+            if ( Ver_StreamPopChar(p) != '=' )
+            {
+                sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+            // get the constant
+            pWord = Ver_ParseGetName( pMan );
+            if ( pWord == NULL )
+                return 0;
+            // check if it is indeed a constant
+            if ( !(pWord[0] >= '0' && pWord[0] <= '9') )
+            {
+                sprintf( pMan->sError, "Currently can only assign vector-signal \"%s\" to be a constant.", Buffer );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+
+            // get individual bits of the constant
+            if ( !Ver_ParseConstant( pMan, pWord ) )
+                return 0;
+            // check that the constant has the same size
+            Limit = nMsb > nLsb? nMsb - nLsb + 1: nLsb - nMsb + 1;
+            if ( Limit != Vec_PtrSize(pMan->vNames) )
+            {
+                sprintf( pMan->sError, "The constant size (%d) is different from the signal\"%s\" size (%d).", 
+                    Vec_PtrSize(pMan->vNames), Buffer, Limit );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+            // iterate through the bits
+            for ( i = 0, Bit = nLsb; i < Limit; i++, Bit = nMsb > nLsb ? Bit + 1: Bit - 1  )
+            {
+                // get the fanin net
+                if ( Vec_PtrEntry( pMan->vNames, Limit-1-i ) )
+                    pNet = Ver_ParseFindNet( pNtk, "1\'b1" );
+                else
+                    pNet = Ver_ParseFindNet( pNtk, "1\'b0" );
+                assert( pNet != NULL );
+
+                // create the buffer
+                pNode = Abc_NtkCreateNodeBuf( pNtk, pNet );
+
+                // get the fanout net
+                sprintf( Buffer2, "%s[%d]", Buffer, Bit );
+                pNet = Ver_ParseFindNet( pNtk, Buffer2 );
+                if ( pNet == NULL )
+                {
+                    sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord );
+                    Ver_ParsePrintErrorMessage( pMan );
+                    return 0;
+                }
+                Abc_ObjAddFanin( pNet, pNode );
+            }
+            // go to the end of the line
+            Ver_ParseSkipComments( pMan );
+        }
+        else
+        {
+            // consider the case of reduction operations
+            fReduction = 0;
+            if ( pWord[0] == '{' && !pMan->fNameLast )
+                fReduction = 1;
+            if ( fReduction )
+            {
+                pWord++;
+                pWord[strlen(pWord)-1] = 0;
+                assert( pWord[0] != '\\' );
+            }
+            // get the fanout net
+            pNet = Ver_ParseFindNet( pNtk, pWord );
+            if ( pNet == NULL )
+            {
+                sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+            // get the equality sign
+            if ( Ver_StreamPopChar(p) != '=' )
+            {
+                sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+            // skip the comments
+            if ( !Ver_ParseSkipComments( pMan ) )
+                return 0;
+            // get the second name
+            if ( fReduction )
+                pEquation = Ver_StreamGetWord( p, ";" );
+            else
+                pEquation = Ver_StreamGetWord( p, ",;" );
+            if ( pEquation == NULL )
+            {
+                sprintf( pMan->sError, "Cannot read the equation for %s.", Abc_ObjName(pNet) );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+
+            // consider the case of mapped network
+            Vec_PtrClear( pMan->vNames );
+            if ( pMan->fMapped )
+            {
+                if ( !strcmp( pEquation, "1\'b0" ) )
+                    pFunc = (Hop_Obj_t *)Mio_LibraryReadConst0((Mio_Library_t *)Abc_FrameReadLibGen());
+                else if ( !strcmp( pEquation, "1\'b1" ) )
+                    pFunc = (Hop_Obj_t *)Mio_LibraryReadConst1((Mio_Library_t *)Abc_FrameReadLibGen());
+                else
+                {
+                    // "assign foo = \bar ;"
+                    if ( *pEquation == '\\' )
+                    {
+                        pEquation++;
+                        pEquation[strlen(pEquation) - 1] = 0;
+                    }
+                    if ( Ver_ParseFindNet(pNtk, pEquation) == NULL )
+                    {
+                        sprintf( pMan->sError, "Cannot read Verilog with non-trivial assignments in the mapped netlist." );
+                        Ver_ParsePrintErrorMessage( pMan );
+                        return 0;
+                    }
+                    Vec_PtrPush( pMan->vNames, (void *)(ABC_PTRUINT_T)strlen(pEquation) );
+                    Vec_PtrPush( pMan->vNames, pEquation );
+                    // get the buffer
+                    pFunc = (Hop_Obj_t *)Mio_LibraryReadBuf((Mio_Library_t *)Abc_FrameReadLibGen());
+                    if ( pFunc == NULL )
+                    {
+                        sprintf( pMan->sError, "Reading assign statement for node %s has failed because the genlib library has no buffer.", Abc_ObjName(pNet) );
+                        Ver_ParsePrintErrorMessage( pMan );
+                        return 0;
+                    }
+                }
+            }
+            else
+            {
+                if ( !strcmp(pEquation, "0") || !strcmp(pEquation, "1\'b0") || !strcmp(pEquation, "1\'bx") )
+                    pFunc = Hop_ManConst0((Hop_Man_t *)pNtk->pManFunc);
+                else if ( !strcmp(pEquation, "1") || !strcmp(pEquation, "1\'b1") )
+                    pFunc = Hop_ManConst1((Hop_Man_t *)pNtk->pManFunc);
+                else if ( fReduction )
+                    pFunc = (Hop_Obj_t *)Ver_FormulaReduction( pEquation, pNtk->pManFunc, pMan->vNames, pMan->sError );  
+                else
+                    pFunc = (Hop_Obj_t *)Ver_FormulaParser( pEquation, pNtk->pManFunc, pMan->vNames, pMan->vStackFn, pMan->vStackOp, pMan->sError );  
+                if ( pFunc == NULL )
+                {
+                    Ver_ParsePrintErrorMessage( pMan );
+                    return 0;
+                }
+            }
+
+            // create the node with the given inputs
+            pNode = Abc_NtkCreateNode( pNtk );
+            pNode->pData = pFunc;
+            Abc_ObjAddFanin( pNet, pNode );
+            // connect to fanin nets
+            for ( i = 0; i < Vec_PtrSize(pMan->vNames)/2; i++ )
+            {
+                // get the name of this signal
+                Length = (int)(ABC_PTRUINT_T)Vec_PtrEntry( pMan->vNames, 2*i );
+                pName  = (char *)Vec_PtrEntry( pMan->vNames, 2*i + 1 );
+                pName[Length] = 0;
+                // find the corresponding net
+                pNet = Ver_ParseFindNet( pNtk, pName );
+                if ( pNet == NULL )
+                {
+                    sprintf( pMan->sError, "Cannot read the assign statement for %s (input wire %s is not defined).", pWord, pName );
+                    Ver_ParsePrintErrorMessage( pMan );
+                    return 0;
+                }
+                Abc_ObjAddFanin( pNode, pNet );
+            }
+        }
+
+        Symbol = Ver_StreamPopChar(p);
+        if ( Symbol == ',' )
+            continue;
+        if ( Symbol == ';' )
+            return 1;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses one directive.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseGateStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_GateType_t GateType )
+{
+    Ver_Stream_t * p = pMan->pReader;
+    Abc_Obj_t * pNet, * pNode;
+    char * pWord, Symbol;
+
+    // convert from the blackbox into the network with local functions representated by AIGs
+    if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) )
+        return 0;
+
+    // this is gate name - throw it away
+    if ( Ver_StreamPopChar(p) != '(' )
+    {
+        sprintf( pMan->sError, "Cannot parse a standard gate (expected opening paranthesis)." );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    Ver_ParseSkipComments( pMan );
+
+    // create the node
+    pNode = Abc_NtkCreateNode( pNtk );
+
+    // parse pairs of formal/actural inputs
+    while ( 1 )
+    {
+        // parse the output name
+        pWord = Ver_ParseGetName( pMan );
+        if ( pWord == NULL )
+            return 0;
+        // get the net corresponding to this output
+        pNet = Ver_ParseFindNet( pNtk, pWord );
+        if ( pNet == NULL )
+        {
+            sprintf( pMan->sError, "Net is missing in gate %s.", pWord );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+        // if this is the first net, add it as an output
+        if ( Abc_ObjFanoutNum(pNode) == 0 )
+            Abc_ObjAddFanin( pNet, pNode );
+        else
+            Abc_ObjAddFanin( pNode, pNet );
+        // check if it is the end of gate
+        Ver_ParseSkipComments( pMan );
+        Symbol = Ver_StreamPopChar(p);
+        if ( Symbol == ')' )
+            break;
+        // skip comma
+        if ( Symbol != ',' )
+        {
+            sprintf( pMan->sError, "Cannot parse a standard gate %s (expected closing paranthesis).", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+        Ver_ParseSkipComments( pMan );
+    }
+    if ( (GateType == VER_GATE_BUF || GateType == VER_GATE_NOT) && Abc_ObjFaninNum(pNode) != 1 )
+    {
+        sprintf( pMan->sError, "Buffer or interver with multiple fanouts %s (currently not supported).", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+
+    // check if it is the end of gate
+    Ver_ParseSkipComments( pMan );
+    if ( Ver_StreamPopChar(p) != ';' )
+    {
+        sprintf( pMan->sError, "Cannot read standard gate %s (expected closing semicolumn).", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    // add logic function
+    if ( GateType == VER_GATE_AND || GateType == VER_GATE_NAND )
+        pNode->pData = Hop_CreateAnd( (Hop_Man_t *)pNtk->pManFunc, Abc_ObjFaninNum(pNode) );
+    else if ( GateType == VER_GATE_OR || GateType == VER_GATE_NOR )
+        pNode->pData = Hop_CreateOr( (Hop_Man_t *)pNtk->pManFunc, Abc_ObjFaninNum(pNode) );
+    else if ( GateType == VER_GATE_XOR || GateType == VER_GATE_XNOR )
+        pNode->pData = Hop_CreateExor( (Hop_Man_t *)pNtk->pManFunc, Abc_ObjFaninNum(pNode) );
+    else if ( GateType == VER_GATE_BUF || GateType == VER_GATE_NOT )
+        pNode->pData = Hop_CreateAnd( (Hop_Man_t *)pNtk->pManFunc, Abc_ObjFaninNum(pNode) );
+    if ( GateType == VER_GATE_NAND || GateType == VER_GATE_NOR || GateType == VER_GATE_XNOR || GateType == VER_GATE_NOT )
+        pNode->pData = Hop_Not( (Hop_Obj_t *)pNode->pData );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses one directive.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseFlopStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+    Ver_Stream_t * p = pMan->pReader;
+    Abc_Obj_t * pNetLi, * pNetLo, * pLatch;
+    char * pWord, Symbol;
+
+    // convert from the blackbox into the network with local functions representated by AIGs
+    if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) )
+        return 0;
+
+    // this is gate name - throw it away
+    if ( Ver_StreamPopChar(p) != '(' )
+    {
+        sprintf( pMan->sError, "Cannot parse a standard gate (expected opening paranthesis)." );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    Ver_ParseSkipComments( pMan );
+
+    // parse the output name
+    pWord = Ver_ParseGetName( pMan );
+    if ( pWord == NULL )
+        return 0;
+    // get the net corresponding to this output
+    pNetLo = Ver_ParseFindNet( pNtk, pWord );
+    if ( pNetLo == NULL )
+    {
+        sprintf( pMan->sError, "Net is missing in gate %s.", pWord );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+
+    // check if it is the end of gate
+    Ver_ParseSkipComments( pMan );
+    Symbol = Ver_StreamPopChar(p);
+    if ( Symbol == ')' )
+    {
+        sprintf( pMan->sError, "Cannot parse the flop." );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    // skip comma
+    if ( Symbol != ',' )
+    {
+        sprintf( pMan->sError, "Cannot parse the flop." );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    Ver_ParseSkipComments( pMan );
+
+    // parse the output name
+    pWord = Ver_ParseGetName( pMan );
+    if ( pWord == NULL )
+        return 0;
+    // get the net corresponding to this output
+    pNetLi = Ver_ParseFindNet( pNtk, pWord );
+    if ( pNetLi == NULL )
+    {
+        sprintf( pMan->sError, "Net is missing in gate %s.", pWord );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+
+    // check if it is the end of gate
+    Ver_ParseSkipComments( pMan );
+    Symbol = Ver_StreamPopChar(p);
+    if ( Symbol != ')' )
+    {
+        sprintf( pMan->sError, "Cannot parse the flop." );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+
+    // check if it is the end of gate
+    Ver_ParseSkipComments( pMan );
+    if ( Ver_StreamPopChar(p) != ';' )
+    {
+        sprintf( pMan->sError, "Cannot parse the flop." );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+
+    // create the latch
+    pLatch = Ver_ParseCreateLatch( pNtk, pNetLi, pNetLo );
+    Abc_LatchSetInit0( pLatch );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the index of the given pin the gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_FindGateInput( Mio_Gate_t * pGate, char * pName )
+{
+    Mio_Pin_t * pGatePin;
+    int i;
+    for ( i = 0, pGatePin = Mio_GateReadPins(pGate); pGatePin != NULL; pGatePin = Mio_PinReadNext(pGatePin), i++ )
+        if ( strcmp(pName, Mio_PinReadName(pGatePin)) == 0 )
+            return i;
+    if ( strcmp(pName, Mio_GateReadOutName(pGate)) == 0 )
+        return i;
+    if ( Mio_GateReadTwin(pGate) && strcmp(pName, Mio_GateReadOutName(Mio_GateReadTwin(pGate))) == 0 )
+        return i+1;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses one directive.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseGate( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Mio_Gate_t * pGate )
+{
+    Ver_Stream_t * p = pMan->pReader;
+    Abc_Obj_t * pNetActual, * pNode, * pNode2 = NULL;
+    char * pWord, Symbol;
+    int Input, i, nFanins = Mio_GateReadPinNum(pGate);
+
+    // convert from the blackbox into the network with local functions representated by gates
+    if ( 1 != pMan->fMapped )
+    {
+        sprintf( pMan->sError, "The network appears to be mapped. Use \"r -m\" to read mapped Verilog." );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+
+    // update the network type if needed
+    if ( !Ver_ParseConvertNetwork( pMan, pNtk, 1 ) )
+        return 0;
+
+    // parse the directive and set the pointers to the PIs/POs of the gate
+    pWord = Ver_ParseGetName( pMan );
+    if ( pWord == NULL )
+        return 0;
+    // this is gate name - throw it away
+    if ( Ver_StreamPopChar(p) != '(' )
+    {
+        sprintf( pMan->sError, "Cannot parse gate %s (expected opening paranthesis).", Mio_GateReadName(pGate) );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    Ver_ParseSkipComments( pMan );
+
+    // start the node
+    pNode = Abc_NtkCreateNode( pNtk );
+    pNode->pData = pGate;
+    if ( Mio_GateReadTwin(pGate) )
+    {
+        pNode2 = Abc_NtkCreateNode( pNtk );
+        pNode2->pData = Mio_GateReadTwin(pGate);
+    }
+    // parse pairs of formal/actural inputs
+    Vec_IntClear( pMan->vPerm );
+    while ( 1 )
+    {
+        // process one pair of formal/actual parameters
+        if ( Ver_StreamPopChar(p) != '.' )
+        {
+            sprintf( pMan->sError, "Cannot parse gate %s (expected .).", Mio_GateReadName(pGate) );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+
+        // parse the formal name
+        pWord = Ver_ParseGetName( pMan );
+        if ( pWord == NULL )
+            return 0;
+
+        // find the corresponding pin of the gate
+        Input = Ver_FindGateInput( pGate, pWord );
+        if ( Input == -1 )
+        {
+            sprintf( pMan->sError, "Formal input name %s cannot be found in the gate %s.", pWord, Mio_GateReadOutName(pGate) );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+
+        // open the paranthesis
+        if ( Ver_StreamPopChar(p) != '(' )
+        {
+            sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected opening paranthesis).", pWord, Mio_GateReadName(pGate) );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+
+        // parse the actual name
+        pWord = Ver_ParseGetName( pMan );
+        if ( pWord == NULL )
+            return 0;
+        // check if the name is complemented
+        assert( pWord[0] != '~' );
+/*
+        fCompl = (pWord[0] == '~');
+        if ( fCompl )
+        {
+            fComplUsed = 1;
+            pWord++;
+            if ( pNtk->pData == NULL )
+                pNtk->pData = Extra_MmFlexStart();
+        }
+*/
+        // get the actual net
+        pNetActual = Ver_ParseFindNet( pNtk, pWord );
+        if ( pNetActual == NULL )
+        {
+            sprintf( pMan->sError, "Actual net %s is missing.", pWord );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+
+        // close the paranthesis
+        if ( Ver_StreamPopChar(p) != ')' )
+        {
+            sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, Mio_GateReadName(pGate) );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+
+        // add the fanin
+        if ( Input < nFanins )
+        {
+            Vec_IntPush( pMan->vPerm, Input );
+            Abc_ObjAddFanin( pNode, pNetActual ); // fanin
+            if ( pNode2 )
+                Abc_ObjAddFanin( pNode2, pNetActual ); // fanin
+        }
+        else if ( Input == nFanins )
+            Abc_ObjAddFanin( pNetActual, pNode ); // fanout
+        else if ( Input == nFanins + 1 )
+            Abc_ObjAddFanin( pNetActual, pNode2 ); // fanout
+        else
+            assert( 0 );
+
+        // check if it is the end of gate
+        Ver_ParseSkipComments( pMan );
+        Symbol = Ver_StreamPopChar(p);
+        if ( Symbol == ')' )
+            break;
+
+        // skip comma
+        if ( Symbol != ',' )
+        {
+            sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, Mio_GateReadName(pGate) );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+        Ver_ParseSkipComments( pMan );
+    }
+
+    // check that the gate as the same number of input
+    if ( !(Abc_ObjFaninNum(pNode) == nFanins && Abc_ObjFanoutNum(pNode) == 1) )
+    {
+        sprintf( pMan->sError, "Parsing of gate %s has failed.", Mio_GateReadName(pGate) );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+
+    // check if it is the end of gate
+    Ver_ParseSkipComments( pMan );
+    if ( Ver_StreamPopChar(p) != ';' )
+    {
+        sprintf( pMan->sError, "Cannot read gate %s (expected closing semicolumn).", Mio_GateReadName(pGate) );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    
+    // check if we need to permute the inputs
+    Vec_IntForEachEntry( pMan->vPerm, Input, i )
+        if ( Input != i )
+            break;
+    if ( i < Vec_IntSize(pMan->vPerm) )
+    {
+        // add the fanin numnbers to the end of the permuation array
+        for ( i = 0; i < nFanins; i++ )
+            Vec_IntPush( pMan->vPerm, Abc_ObjFaninId(pNode, i) );
+        // write the fanin numbers into their corresponding places (according to the gate) 
+        for ( i = 0; i < nFanins; i++ )
+            Vec_IntWriteEntry( &pNode->vFanins, Vec_IntEntry(pMan->vPerm, i), Vec_IntEntry(pMan->vPerm, i+nFanins) );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses one directive.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox )
+{
+    char Buffer[1000];
+    Ver_Stream_t * p = pMan->pReader;
+    Ver_Bundle_t * pBundle;
+    Vec_Ptr_t * vBundles;
+    Abc_Obj_t * pNetActual; 
+    Abc_Obj_t * pNode;
+    char * pWord, Symbol;
+    int fCompl, fFormalIsGiven;
+    int i, k, Bit, Limit, nMsb, nLsb, fQuit, flag;
+
+    // gate the name of the box
+    pWord = Ver_ParseGetName( pMan );
+    if ( pWord == NULL )
+        return 0;
+
+    // create a box with this name
+    pNode = Abc_NtkCreateBlackbox( pNtk );
+    pNode->pData = pNtkBox;
+    Abc_ObjAssignName( pNode, pWord, NULL );
+
+    // continue parsing the box
+    if ( Ver_StreamPopChar(p) != '(' )
+    {
+        sprintf( pMan->sError, "Cannot parse box %s (expected opening paranthesis).", Abc_ObjName(pNode) );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    Ver_ParseSkipComments( pMan );
+ 
+    // parse pairs of formal/actual inputs
+    vBundles = Vec_PtrAlloc( 16 );
+    pNode->pCopy = (Abc_Obj_t *)vBundles;
+    while ( 1 )
+    {
+        // allocate the bundle (formal name + array of actual nets)
+        pBundle = ABC_ALLOC( Ver_Bundle_t, 1 );
+        pBundle->pNameFormal = NULL;
+        pBundle->vNetsActual = Vec_PtrAlloc( 4 );
+        Vec_PtrPush( vBundles, pBundle );
+
+        // process one pair of formal/actual parameters
+        fFormalIsGiven = 0;
+        if ( Ver_StreamScanChar(p) == '.' )
+        {
+            fFormalIsGiven = 1;
+            if ( Ver_StreamPopChar(p) != '.' )
+            {
+                sprintf( pMan->sError, "Cannot parse box %s (expected .).", Abc_ObjName(pNode) );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+
+            // parse the formal name
+            pWord = Ver_ParseGetName( pMan );
+            if ( pWord == NULL )
+                return 0;
+
+            // save the name
+            pBundle->pNameFormal = Extra_UtilStrsav( pWord );
+
+            // open the paranthesis
+            if ( Ver_StreamPopChar(p) != '(' )
+            {
+                sprintf( pMan->sError, "Cannot formal parameter %s of box %s (expected opening paranthesis).", pWord, Abc_ObjName(pNode));
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+            Ver_ParseSkipComments( pMan );
+        }
+
+        // check if this is the beginning of {} expression
+        Symbol = Ver_StreamScanChar(p);
+
+        // consider the case of vector-inputs
+        if ( Symbol == '{' )
+        {
+            // skip this char
+            Ver_StreamPopChar(p);
+
+            // read actual names
+            i = 0;
+            fQuit = 0;
+            while ( 1 )
+            {
+                // parse the formal name
+                Ver_ParseSkipComments( pMan );
+                pWord = Ver_ParseGetName( pMan );
+                if ( pWord == NULL )
+                    return 0;
+
+                // check if the last char is a closing brace
+                if ( pWord[strlen(pWord)-1] == '}' )
+                {
+                    pWord[strlen(pWord)-1] = 0;
+                    fQuit = 1;
+                }
+                if ( pWord[0] == 0 )
+                    break;
+
+                // check for constant
+                if ( pWord[0] >= '1' && pWord[0] <= '9' )
+                {
+                    if ( !Ver_ParseConstant( pMan, pWord ) )
+                        return 0;
+                    // add constant MSB to LSB
+                    for ( k = 0; k < Vec_PtrSize(pMan->vNames); k++, i++ )
+                    {
+                        // get the actual net
+                        sprintf( Buffer, "1\'b%d", (int)(Vec_PtrEntry(pMan->vNames,k) != NULL) );
+                        pNetActual = Ver_ParseFindNet( pNtk, Buffer );
+                        if ( pNetActual == NULL )
+                        {
+                            sprintf( pMan->sError, "Actual net \"%s\" is missing in gate \"%s\".", Buffer, Abc_ObjName(pNode) );
+                            Ver_ParsePrintErrorMessage( pMan );
+                            return 0;
+                        }
+                        Vec_PtrPush( pBundle->vNetsActual, pNetActual );
+                    }
+                }
+                else
+                {
+                    // get the suffix of the form [m:n]
+                    if ( pWord[strlen(pWord)-1] == ']' && !pMan->fNameLast )
+                        Ver_ParseSignalSuffix( pMan, pWord, &nMsb, &nLsb );
+                    else
+                        Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb );
+
+                    // generate signals
+                    if ( nMsb == -1 && nLsb == -1 )
+                    {
+                        // get the actual net
+                        pNetActual = Ver_ParseFindNet( pNtk, pWord );
+                        if ( pNetActual == NULL )
+                        {
+                            if ( !strncmp(pWord, "Open_", 5) ||
+                                !strncmp(pWord, "dct_unconnected", 15) ) 
+                                pNetActual = Abc_NtkCreateNet( pNtk );
+                            else
+                            {
+                                sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) );
+                                Ver_ParsePrintErrorMessage( pMan );
+                                return 0;
+                            }
+                        }
+                        Vec_PtrPush( pBundle->vNetsActual, pNetActual );
+                        i++;
+                    }
+                    else
+                    {
+                        // go from MSB to LSB
+                        assert( nMsb >= 0 && nLsb >= 0 );
+                        Limit = (nMsb > nLsb) ? nMsb - nLsb + 1: nLsb - nMsb + 1;  
+                        for ( Bit = nMsb, k = Limit - 1; k >= 0; Bit = (nMsb > nLsb ? Bit - 1: Bit + 1), k--, i++ )
+                        {
+                            // get the actual net
+                            sprintf( Buffer, "%s[%d]", pWord, Bit );
+                            pNetActual = Ver_ParseFindNet( pNtk, Buffer );
+                            if ( pNetActual == NULL )
+                            {
+                                if ( !strncmp(pWord, "Open_", 5) ||
+                                    !strncmp(pWord, "dct_unconnected", 15) ) 
+                                    pNetActual = Abc_NtkCreateNet( pNtk );
+                                else
+                                {
+                                    sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) );
+                                    Ver_ParsePrintErrorMessage( pMan );
+                                    return 0;
+                                }
+                            }
+                            Vec_PtrPush( pBundle->vNetsActual, pNetActual );
+                        }
+                    }
+                }
+
+                if ( fQuit )
+                    break;
+
+                // skip comma
+                Ver_ParseSkipComments( pMan );
+                Symbol = Ver_StreamPopChar(p);
+                if ( Symbol == '}' )
+                    break;
+                if ( Symbol != ',' )
+                {
+                    sprintf( pMan->sError, "Cannot parse formal parameter %s of gate %s (expected comma).", pWord, Abc_ObjName(pNode) );
+                    Ver_ParsePrintErrorMessage( pMan );
+                    return 0;
+                }
+            }
+        }
+        else
+        {
+            // get the next word
+            pWord = Ver_ParseGetName( pMan );
+            if ( pWord == NULL )
+                return 0;
+            // consider the case of empty name
+            fCompl = 0;
+            if ( pWord[0] == 0 )
+            {
+                pNetActual = Abc_NtkCreateNet( pNtk );
+		        Vec_PtrPush( pBundle->vNetsActual, Abc_ObjNotCond( pNetActual, fCompl ) );
+            }
+            else
+            {
+                // get the actual net
+                flag=0;
+                pNetActual = Ver_ParseFindNet( pNtk, pWord );
+                if ( pNetActual == NULL ) 
+                {
+                    Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb );
+                    if ( nMsb == -1 && nLsb == -1 ) 
+                    {
+                        Ver_ParseSignalSuffix( pMan, pWord, &nMsb, &nLsb );
+                        if ( nMsb == -1 && nLsb == -1 ) 
+                        {
+                            if ( !strncmp(pWord, "Open_", 5) ||
+                                !strncmp(pWord, "dct_unconnected", 15) ) 
+                            {
+                                pNetActual = Abc_NtkCreateNet( pNtk );
+                                Vec_PtrPush( pBundle->vNetsActual, pNetActual );
+                            } 
+                            else 
+                            {
+                                sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) );
+                                Ver_ParsePrintErrorMessage( pMan );
+                                return 0;
+                            }
+                        } 
+                        else 
+                        {
+                            flag=1;
+                        }
+                    } 
+                    else 
+                    {
+                        flag=1;
+                    }
+                    if (flag) 
+                    {
+                        Limit = (nMsb > nLsb) ? nMsb - nLsb + 1: nLsb - nMsb + 1;  
+                        for ( Bit = nMsb, k = Limit - 1; k >= 0; Bit = (nMsb > nLsb ? Bit - 1: Bit + 1), k--)
+                        {
+                            // get the actual net
+                            sprintf( Buffer, "%s[%d]", pWord, Bit );
+                            pNetActual = Ver_ParseFindNet( pNtk, Buffer );
+                            if ( pNetActual == NULL )
+                            {
+                                if ( !strncmp(pWord, "Open_", 5) ||
+                                    !strncmp(pWord, "dct_unconnected", 15)) 
+                                    pNetActual = Abc_NtkCreateNet( pNtk );
+                                else
+                                {
+                                    sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) );
+                                    Ver_ParsePrintErrorMessage( pMan );
+                                    return 0;
+                                }
+                            }
+                            Vec_PtrPush( pBundle->vNetsActual, pNetActual );
+                        }
+                    }
+                } 
+                else 
+                {
+                    Vec_PtrPush( pBundle->vNetsActual, Abc_ObjNotCond( pNetActual, fCompl ) );
+                }
+            }
+        }
+
+        if ( fFormalIsGiven )
+        {
+            // close the paranthesis
+            Ver_ParseSkipComments( pMan );
+            if ( Ver_StreamPopChar(p) != ')' )
+            {
+                sprintf( pMan->sError, "Cannot parse formal parameter %s of box %s (expected closing paranthesis).", pWord, Abc_ObjName(pNode) );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+            Ver_ParseSkipComments( pMan );
+        }
+
+        // check if it is the end of gate
+        Symbol = Ver_StreamPopChar(p);
+        if ( Symbol == ')' )
+            break;
+        // skip comma
+        if ( Symbol != ',' )
+        {
+            sprintf( pMan->sError, "Cannot parse formal parameter %s of box %s (expected comma).", pWord, Abc_ObjName(pNode) );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+        Ver_ParseSkipComments( pMan );
+    }
+
+    // check if it is the end of gate
+    Ver_ParseSkipComments( pMan );
+    if ( Ver_StreamPopChar(p) != ';' )
+    {
+        sprintf( pMan->sError, "Cannot read box %s (expected closing semicolumn).", Abc_ObjName(pNode) );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Connects one box to the network]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ver_ParseFreeBundle( Ver_Bundle_t * pBundle )
+{
+    ABC_FREE( pBundle->pNameFormal );
+    Vec_PtrFree( pBundle->vNetsActual );
+    ABC_FREE( pBundle );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Connects one box to the network]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseConnectBox( Ver_Man_t * pMan, Abc_Obj_t * pBox )
+{
+    Vec_Ptr_t * vBundles = (Vec_Ptr_t *)pBox->pCopy;
+    Abc_Ntk_t * pNtk = pBox->pNtk;
+    Abc_Ntk_t * pNtkBox = (Abc_Ntk_t *)pBox->pData;
+    Abc_Obj_t * pTerm, * pTermNew, * pNetAct;
+    Ver_Bundle_t * pBundle;
+    char * pNameFormal;
+    int i, k, j, iBundle, Length;
+
+    assert( !Ver_ObjIsConnected(pBox) );
+    assert( Ver_NtkIsDefined(pNtkBox) );
+    assert( !Abc_NtkHasBlackbox(pNtkBox) || Abc_NtkBoxNum(pNtkBox) == 1 );
+
+/*
+    // clean the PI/PO nets
+    Abc_NtkForEachPi( pNtkBox, pTerm, i )
+        Abc_ObjFanout0(pTerm)->pCopy = NULL;
+    Abc_NtkForEachPo( pNtkBox, pTerm, i )
+        Abc_ObjFanin0(pTerm)->pCopy = NULL;
+*/
+
+    // check the number of actual nets is the same as the number of formal nets
+    if ( Vec_PtrSize(vBundles) > Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) )
+    {
+        sprintf( pMan->sError, "The number of actual IOs (%d) is bigger than the number of formal IOs (%d) when instantiating network %s in box %s.", 
+            Vec_PtrSize(vBundles), Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox), pNtkBox->pName, Abc_ObjName(pBox) );
+        // free the bundling
+        Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, k )
+            Ver_ParseFreeBundle( pBundle );
+        Vec_PtrFree( vBundles );
+        pBox->pCopy = NULL;
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+
+    // check if some of them do not have formal names
+    Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, k )
+        if ( pBundle->pNameFormal == NULL )
+            break;
+    if ( k < Vec_PtrSize(vBundles) )
+    {
+        printf( "Warning: The instance %s of network %s will be connected without using formal names.\n", pNtkBox->pName, Abc_ObjName(pBox) );
+        // add all actual nets in the bundles
+        iBundle = 0;
+        Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, j )
+            iBundle += Vec_PtrSize(pBundle->vNetsActual);
+
+        // check the number of actual nets is the same as the number of formal nets
+        if ( iBundle != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) )
+        {
+            sprintf( pMan->sError, "The number of actual IOs (%d) is different from the number of formal IOs (%d) when instantiating network %s in box %s.", 
+                Vec_PtrSize(vBundles), Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox), pNtkBox->pName, Abc_ObjName(pBox) );
+            // free the bundling
+            Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, k )
+                Ver_ParseFreeBundle( pBundle );
+            Vec_PtrFree( vBundles );
+            pBox->pCopy = NULL;
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+        // connect bundles in the natural order
+        iBundle = 0;
+        Abc_NtkForEachPi( pNtkBox, pTerm, i )
+        {
+            pBundle = (Ver_Bundle_t *)Vec_PtrEntry( vBundles, iBundle++ );
+            // the bundle is found - add the connections - using order LSB to MSB
+            Vec_PtrForEachEntryReverse( Abc_Obj_t *, pBundle->vNetsActual, pNetAct, k )
+            {
+                pTermNew = Abc_NtkCreateBi( pNtk );
+                Abc_ObjAddFanin( pBox, pTermNew );
+                Abc_ObjAddFanin( pTermNew, pNetAct );
+                i++;
+            }
+            i--;
+        }
+        // create fanins of the box
+        Abc_NtkForEachPo( pNtkBox, pTerm, i )
+        {
+            pBundle = (Ver_Bundle_t *)Vec_PtrEntry( vBundles, iBundle++ );
+            // the bundle is found - add the connections - using order LSB to MSB
+            Vec_PtrForEachEntryReverse( Abc_Obj_t *, pBundle->vNetsActual, pNetAct, k )
+            {
+                pTermNew = Abc_NtkCreateBo( pNtk );
+                Abc_ObjAddFanin( pTermNew, pBox );
+                Abc_ObjAddFanin( pNetAct, pTermNew );
+                i++;
+            }
+            i--;
+        }
+
+        // free the bundling
+        Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, k )
+            Ver_ParseFreeBundle( pBundle );
+        Vec_PtrFree( vBundles );
+        pBox->pCopy = NULL;
+        return 1;
+    }
+
+    // bundles arrive in any order - but inside each bundle the order is MSB to LSB
+    // make sure every formal PI has a corresponding net
+    Abc_NtkForEachPi( pNtkBox, pTerm, i )
+    {
+        // get the name of this formal net
+        pNameFormal = Abc_ObjName( Abc_ObjFanout0(pTerm) );
+        // try to find the bundle with this formal net
+        pBundle = NULL;
+        Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, k )
+            if ( !strcmp(pBundle->pNameFormal, pNameFormal) )
+                break;
+        assert( pBundle != NULL );
+        // if the bundle is not found, try without parantheses
+        if ( k == Vec_PtrSize(vBundles) )
+        {
+            pBundle = NULL;
+            Length = strlen(pNameFormal);
+            if ( pNameFormal[Length-1] == ']' )
+            {
+                // find the opening brace
+                for ( Length--; Length >= 0; Length-- )
+                    if ( pNameFormal[Length] == '[' )
+                        break;
+                // compare names before brace
+                if ( Length > 0 )
+                {
+                    Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, j )
+                        if ( !strncmp(pBundle->pNameFormal, pNameFormal, Length) && (int)strlen(pBundle->pNameFormal) == Length )
+                            break;
+                    if ( j == Vec_PtrSize(vBundles) )
+                        pBundle = NULL;
+                }
+            }
+            if ( pBundle == NULL )
+            {
+                sprintf( pMan->sError, "Cannot find an actual net for the formal net %s when instantiating network %s in box %s.", 
+                    pNameFormal, pNtkBox->pName, Abc_ObjName(pBox) );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+        }
+        // the bundle is found - add the connections - using order LSB to MSB
+        Vec_PtrForEachEntryReverse( Abc_Obj_t *, pBundle->vNetsActual, pNetAct, k )
+        {
+            pTermNew = Abc_NtkCreateBi( pNtk );
+            Abc_ObjAddFanin( pBox, pTermNew );
+            Abc_ObjAddFanin( pTermNew, pNetAct );
+            i++;
+        }
+        i--;
+    }
+
+    // connect those formal POs that do have nets
+    Abc_NtkForEachPo( pNtkBox, pTerm, i )
+    {
+        // get the name of this PI
+        pNameFormal = Abc_ObjName( Abc_ObjFanin0(pTerm) );
+        // try to find this formal net in the bundle
+        pBundle = NULL;
+        Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, k )
+            if ( !strcmp(pBundle->pNameFormal, pNameFormal) )
+                break;
+        assert( pBundle != NULL );
+        // if the name is not found, try without parantheses
+        if ( k == Vec_PtrSize(vBundles) )
+        {
+            pBundle = NULL;
+            Length = strlen(pNameFormal);
+            if ( pNameFormal[Length-1] == ']' )
+            {
+                // find the opening brace
+                for ( Length--; Length >= 0; Length-- )
+                    if ( pNameFormal[Length] == '[' )
+                        break;
+                // compare names before brace
+                if ( Length > 0 )
+                {
+                    Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, j )
+                        if ( !strncmp(pBundle->pNameFormal, pNameFormal, Length) && (int)strlen(pBundle->pNameFormal) == Length ) 
+                            break;
+                    if ( j == Vec_PtrSize(vBundles) )
+                        pBundle = NULL;
+                }
+            }
+            if ( pBundle == NULL )
+            {
+                char Buffer[1000];
+//                printf( "Warning: The formal output %s is not driven when instantiating network %s in box %s.", 
+//                    pNameFormal, pNtkBox->pName, Abc_ObjName(pBox) );
+                pTermNew = Abc_NtkCreateBo( pNtk );
+                sprintf( Buffer, "_temp_net%d", Abc_ObjId(pTermNew) );
+                pNetAct = Abc_NtkFindOrCreateNet( pNtk, Buffer );
+                Abc_ObjAddFanin( pTermNew, pBox );
+                Abc_ObjAddFanin( pNetAct, pTermNew );
+                continue;
+            }
+        }
+        // the bundle is found - add the connections
+        Vec_PtrForEachEntryReverse( Abc_Obj_t *, pBundle->vNetsActual, pNetAct, k )
+        {
+            if ( !strcmp(Abc_ObjName(pNetAct), "1\'b0") || !strcmp(Abc_ObjName(pNetAct), "1\'b1") )
+            {
+                sprintf( pMan->sError, "It looks like formal output %s is driving a constant net (%s) when instantiating network %s in box %s.", 
+                    pBundle->pNameFormal, Abc_ObjName(pNetAct), pNtkBox->pName, Abc_ObjName(pBox) );
+                // free the bundling
+                Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, k )
+                    Ver_ParseFreeBundle( pBundle );
+                Vec_PtrFree( vBundles );
+                pBox->pCopy = NULL;
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+            pTermNew = Abc_NtkCreateBo( pNtk );
+            Abc_ObjAddFanin( pTermNew, pBox );
+            Abc_ObjAddFanin( pNetAct, pTermNew );
+            i++;
+        }
+        i--;
+    }
+
+    // free the bundling
+    Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, k )
+        Ver_ParseFreeBundle( pBundle );
+    Vec_PtrFree( vBundles );
+    pBox->pCopy = NULL;
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Connects the defined boxes.]
+
+  Description [Returns 2 if there are any undef boxes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseConnectDefBoxes( Ver_Man_t * pMan )
+{
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pBox;
+    int i, k, RetValue = 1;
+    // go through all the modules
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i )
+    {
+        // go through all the boxes of this module
+        Abc_NtkForEachBox( pNtk, pBox, k )
+        {
+            if ( Abc_ObjIsLatch(pBox) )
+                continue;
+            // skip internal boxes of the blackboxes
+            if ( pBox->pData == NULL )
+                continue;
+            // if the network is undefined, it will be connected later
+            if ( !Ver_NtkIsDefined((Abc_Ntk_t *)pBox->pData) )
+            {
+                RetValue = 2;
+                continue;
+            }
+            // connect the box
+            if ( !Ver_ParseConnectBox( pMan, pBox ) )
+                return 0;
+            // if the network is a true blackbox, skip
+            if ( Abc_NtkHasBlackbox((Abc_Ntk_t *)pBox->pData) )
+                continue;
+            // convert the box to the whitebox
+            Abc_ObjBlackboxToWhitebox( pBox );
+        }
+    }
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the undef boxes and maps them into their instances.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Ver_ParseCollectUndefBoxes( Ver_Man_t * pMan )
+{
+    Vec_Ptr_t * vUndefs;
+    Abc_Ntk_t * pNtk, * pNtkBox;
+    Abc_Obj_t * pBox;
+    int i, k;
+    // clear the module structures
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i )
+        pNtk->pData = NULL;
+    // go through all the blackboxes
+    vUndefs = Vec_PtrAlloc( 16 );
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i )
+    {
+        Abc_NtkForEachBlackbox( pNtk, pBox, k )
+        {
+            pNtkBox = (Abc_Ntk_t *)pBox->pData;
+            if ( pNtkBox == NULL )
+                continue;
+            if ( Ver_NtkIsDefined(pNtkBox) )
+                continue;
+            if ( pNtkBox->pData == NULL )
+            {
+                // save the box
+                Vec_PtrPush( vUndefs, pNtkBox );
+                pNtkBox->pData = Vec_PtrAlloc( 16 );
+            }
+            // save the instance
+            Vec_PtrPush( (Vec_Ptr_t *)pNtkBox->pData, pBox );
+        }
+    }
+    return vUndefs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports how many times each type of undefined box occurs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ver_ParseReportUndefBoxes( Ver_Man_t * pMan )
+{
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pBox;
+    int i, k, nBoxes;
+    // clean 
+    nBoxes = 0;
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i )
+    {
+        pNtk->fHiePath = 0;
+        if ( !Ver_NtkIsDefined(pNtk) )
+            nBoxes++;
+    }
+    // count
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i )
+        Abc_NtkForEachBlackbox( pNtk, pBox, k )
+            if ( pBox->pData && !Ver_NtkIsDefined((Abc_Ntk_t *)pBox->pData) )
+                ((Abc_Ntk_t *)pBox->pData)->fHiePath++;
+    // print the stats
+    printf( "Warning: The design contains %d undefined object types interpreted as blackboxes:\n", nBoxes );
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i )
+        if ( !Ver_NtkIsDefined(pNtk) )
+            printf( "%s (%d)  ", Abc_NtkName(pNtk), pNtk->fHiePath );
+    printf( "\n" );
+    // clean 
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i )
+        pNtk->fHiePath = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if there are non-driven nets.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseCheckNondrivenNets( Vec_Ptr_t * vUndefs )
+{
+    Abc_Ntk_t * pNtk;
+    Ver_Bundle_t * pBundle;
+    Abc_Obj_t * pBox, * pNet;
+    int i, k, j, m;
+    // go through undef box types
+    Vec_PtrForEachEntry( Abc_Ntk_t *, vUndefs, pNtk, i )
+        // go through instances of this type
+        Vec_PtrForEachEntry( Abc_Obj_t *, (Vec_Ptr_t *)pNtk->pData, pBox, k )
+            // go through the bundles of this instance
+            Vec_PtrForEachEntryReverse( Ver_Bundle_t *, (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
+                // go through the actual nets of this bundle
+                if ( pBundle )
+                Vec_PtrForEachEntry( Abc_Obj_t *, pBundle->vNetsActual, pNet, m )
+                {
+                    if ( Abc_ObjFaninNum(pNet) == 0 ) // non-driven
+                        if ( strcmp(Abc_ObjName(pNet), "1\'b0") && strcmp(Abc_ObjName(pNet), "1\'b1") ) // diff from a const
+                            return 1;
+                }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if formal nets with the given name are driven in any of the instances of undef boxes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseFormalNetsAreDriven( Abc_Ntk_t * pNtk, char * pNameFormal )
+{
+    Ver_Bundle_t * pBundle = NULL;
+    Abc_Obj_t * pBox, * pNet;
+    int k, j, m;
+    // go through instances of this type
+    Vec_PtrForEachEntry( Abc_Obj_t *, (Vec_Ptr_t *)pNtk->pData, pBox, k )
+    {
+        // find a bundle with the given name in this instance
+        Vec_PtrForEachEntryReverse( Ver_Bundle_t *, (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
+            if ( pBundle && !strcmp( pBundle->pNameFormal, pNameFormal ) )
+                break;
+        // skip non-driven bundles
+        if ( j == Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) )
+            continue;
+        // check if all nets are driven in this bundle
+        assert(pBundle); // Verify that pBundle was assigned to.
+        Vec_PtrForEachEntry( Abc_Obj_t *, pBundle->vNetsActual, pNet, m )
+            if ( Abc_ObjFaninNum(pNet) > 0 )
+                return 1;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the non-driven bundle that is given distance from the end.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ver_Bundle_t * Ver_ParseGetNondrivenBundle( Abc_Ntk_t * pNtk, int Counter )
+{
+    Ver_Bundle_t * pBundle;
+    Abc_Obj_t * pBox, * pNet;
+    int k, m;
+    // go through instances of this type
+    Vec_PtrForEachEntry( Abc_Obj_t *, (Vec_Ptr_t *)pNtk->pData, pBox, k )
+    {
+        if ( Counter >= Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) )
+            continue;
+        // get the bundle given distance away
+        pBundle = (Ver_Bundle_t *)Vec_PtrEntry( (Vec_Ptr_t *)pBox->pCopy, Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) - 1 - Counter );
+        if ( pBundle == NULL )
+            continue;
+        // go through the actual nets of this bundle
+        Vec_PtrForEachEntry( Abc_Obj_t *, pBundle->vNetsActual, pNet, m )
+            if ( !Abc_ObjFaninNum(pNet) && !Ver_ParseFormalNetsAreDriven(pNtk, pBundle->pNameFormal) ) // non-driven
+                return pBundle;
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Drives the bundle in the given undef box.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseDriveFormal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_Bundle_t * pBundle0 )
+{
+    char Buffer[200];
+    char * pName;
+    Ver_Bundle_t * pBundle = NULL;
+    Abc_Obj_t * pBox, * pTerm, * pTermNew, * pNetAct, * pNetFormal;
+    int k, j, m;
+
+    // drive this net in the undef box
+    Vec_PtrForEachEntry( Abc_Obj_t *, pBundle0->vNetsActual, pNetAct, m )
+    {
+        // create the formal net
+        if ( Vec_PtrSize(pBundle0->vNetsActual) == 1 )
+            sprintf( Buffer, "%s", pBundle0->pNameFormal );
+        else
+            sprintf( Buffer, "%s[%d]", pBundle0->pNameFormal, m );
+        assert( Abc_NtkFindNet( pNtk, Buffer ) == NULL );
+        pNetFormal = Abc_NtkFindOrCreateNet( pNtk, Buffer );
+        // connect it to the box
+        pTerm = Abc_NtkCreateBo( pNtk );
+        assert( Abc_NtkBoxNum(pNtk) <= 1 );
+        pBox = Abc_NtkBoxNum(pNtk)? Abc_NtkBox(pNtk,0) : Abc_NtkCreateBlackbox(pNtk);
+        Abc_ObjAddFanin( Abc_NtkCreatePo(pNtk), pNetFormal );
+        Abc_ObjAddFanin( pNetFormal, pTerm );
+        Abc_ObjAddFanin( pTerm, pBox );
+    }
+
+    // go through instances of this type
+    pName = Extra_UtilStrsav(pBundle0->pNameFormal);
+    Vec_PtrForEachEntry( Abc_Obj_t *, (Vec_Ptr_t *)pNtk->pData, pBox, k )
+    {
+        // find a bundle with the given name in this instance
+        Vec_PtrForEachEntryReverse( Ver_Bundle_t *, (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
+            if ( pBundle && !strcmp( pBundle->pNameFormal, pName ) )
+                break;
+        // skip non-driven bundles
+        if ( j == Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) )
+            continue;
+        // check if any nets are driven in this bundle
+        assert(pBundle); // Verify pBundle was assigned to.
+        Vec_PtrForEachEntry( Abc_Obj_t *, pBundle->vNetsActual, pNetAct, m )
+            if ( Abc_ObjFaninNum(pNetAct) > 0 )
+            {
+                sprintf( pMan->sError, "Missing specification of the I/Os of undefined box \"%s\".", Abc_NtkName(pNtk) );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+        // drive the nets by the undef box
+        Vec_PtrForEachEntryReverse( Abc_Obj_t *, pBundle->vNetsActual, pNetAct, m )
+        {
+            pTermNew = Abc_NtkCreateBo( pNetAct->pNtk );
+            Abc_ObjAddFanin( pTermNew, pBox );
+            Abc_ObjAddFanin( pNetAct, pTermNew );
+        }
+        // remove the bundle
+        Ver_ParseFreeBundle( pBundle ); pBundle = NULL;
+        Vec_PtrWriteEntry( (Vec_Ptr_t *)pBox->pCopy, j, NULL );
+    }
+    ABC_FREE( pName );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Drives the bundle in the given undef box.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseDriveInputs( Ver_Man_t * pMan, Vec_Ptr_t * vUndefs )
+{
+    char Buffer[200];
+    Ver_Bundle_t * pBundle;
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pBox, * pBox2, * pTerm, * pTermNew, * pNetFormal, * pNetAct;
+    int i, k, j, m, CountCur, CountTotal = -1;
+    // iterate through the undef boxes
+    Vec_PtrForEachEntry( Abc_Ntk_t *, vUndefs, pNtk, i )
+    {
+        // count the number of unconnected bundles for instances of this type of box
+        CountTotal = -1;
+        Vec_PtrForEachEntry( Abc_Obj_t *, (Vec_Ptr_t *)pNtk->pData, pBox, k )
+        {
+            CountCur = 0;
+            Vec_PtrForEachEntry( Ver_Bundle_t *, (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
+                CountCur += (pBundle != NULL);
+            if ( CountTotal == -1 )
+                CountTotal = CountCur;
+            else if ( CountTotal != CountCur )
+            {
+                sprintf( pMan->sError, "The number of formal inputs (%d) is different from the expected one (%d) when instantiating network %s in box %s.", 
+                    CountCur, CountTotal, pNtk->pName, Abc_ObjName(pBox) );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+        }
+
+        // create formals
+        pBox = (Abc_Obj_t *)Vec_PtrEntry( (Vec_Ptr_t *)pNtk->pData, 0 );
+        Vec_PtrForEachEntry( Ver_Bundle_t *, (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
+        {
+            if ( pBundle == NULL )
+                continue;
+            Vec_PtrForEachEntry( Abc_Obj_t *, pBundle->vNetsActual, pNetAct, m )
+            {
+                // find create the formal net
+                if ( Vec_PtrSize(pBundle->vNetsActual) == 1 )
+                    sprintf( Buffer, "%s", pBundle->pNameFormal );
+                else
+                    sprintf( Buffer, "%s[%d]", pBundle->pNameFormal, m );
+                assert( Abc_NtkFindNet( pNtk, Buffer ) == NULL );
+                pNetFormal = Abc_NtkFindOrCreateNet( pNtk, Buffer );
+                // connect
+                pTerm = Abc_NtkCreateBi( pNtk );
+                assert( Abc_NtkBoxNum(pNtk) <= 1 );
+                pBox2 = Abc_NtkBoxNum(pNtk)? Abc_NtkBox(pNtk,0) : Abc_NtkCreateBlackbox(pNtk);
+                Abc_ObjAddFanin( pNetFormal, Abc_NtkCreatePi(pNtk) );
+                Abc_ObjAddFanin( pTerm, pNetFormal );
+                Abc_ObjAddFanin( pBox2, pTerm );
+            }
+        }
+
+        // go through all the boxes
+        Vec_PtrForEachEntry( Abc_Obj_t *, (Vec_Ptr_t *)pNtk->pData, pBox, k )
+        {
+            // go through all the bundles
+            Vec_PtrForEachEntry( Ver_Bundle_t *, (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
+            {
+                if ( pBundle == NULL )
+                    continue;
+                // drive the nets by the undef box
+                Vec_PtrForEachEntryReverse( Abc_Obj_t *, pBundle->vNetsActual, pNetAct, m )
+                {
+                    pTermNew = Abc_NtkCreateBi( pNetAct->pNtk );
+                    Abc_ObjAddFanin( pBox, pTermNew );
+                    Abc_ObjAddFanin( pTermNew, pNetAct );
+                }
+                // remove the bundle
+                Ver_ParseFreeBundle( pBundle );
+                Vec_PtrWriteEntry( (Vec_Ptr_t *)pBox->pCopy, j, NULL );
+            }
+
+            // free the bundles
+            Vec_PtrFree( (Vec_Ptr_t *)pBox->pCopy );
+            pBox->pCopy = NULL;
+        }
+    }
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the max size of any undef box.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseMaxBoxSize( Vec_Ptr_t * vUndefs )
+{
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pBox;
+    int i, k, nMaxSize = 0;
+    // go through undef box types
+    Vec_PtrForEachEntry( Abc_Ntk_t *, vUndefs, pNtk, i )
+        // go through instances of this type
+        Vec_PtrForEachEntry( Abc_Obj_t *, (Vec_Ptr_t *)pNtk->pData, pBox, k )
+            // check the number of bundles of this instance
+            if ( nMaxSize < Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) )
+                nMaxSize = Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy);
+    return nMaxSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the comprehensive report into a log file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ver_ParsePrintLog( Ver_Man_t * pMan )
+{
+    Abc_Ntk_t * pNtk, * pNtkBox;
+    Abc_Obj_t * pBox;
+    FILE * pFile;
+    char * pNameGeneric;
+    char Buffer[1000];
+    int i, k, Count1 = 0;
+
+    // open the log file
+    pNameGeneric = Extra_FileNameGeneric( pMan->pFileName );
+    sprintf( Buffer, "%s.log", pNameGeneric );
+    ABC_FREE( pNameGeneric );
+    pFile = fopen( Buffer, "w" );
+
+    // count the total number of instances and how many times they occur
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i )
+        pNtk->fHieVisited = 0;
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i )
+        Abc_NtkForEachBox( pNtk, pBox, k )
+        {
+            if ( Abc_ObjIsLatch(pBox) )
+                continue;
+            pNtkBox = (Abc_Ntk_t *)pBox->pData;
+            if ( pNtkBox == NULL )
+                continue;
+            pNtkBox->fHieVisited++;
+        }
+    // print each box and its stats
+    fprintf( pFile, "The hierarhical design %s contains %d modules:\n", pMan->pFileName, Vec_PtrSize(pMan->pDesign->vModules) );
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i )
+    {
+        fprintf( pFile, "%-50s : ", Abc_NtkName(pNtk) );
+        if ( !Ver_NtkIsDefined(pNtk) )
+            fprintf( pFile, "undefbox" );
+        else if ( Abc_NtkHasBlackbox(pNtk) )
+            fprintf( pFile, "blackbox" );
+        else
+            fprintf( pFile, "logicbox" );
+        fprintf( pFile, " instantiated %6d times ", pNtk->fHieVisited );
+//        fprintf( pFile, "\n   " );
+        fprintf( pFile, " pi = %4d", Abc_NtkPiNum(pNtk) );
+        fprintf( pFile, " po = %4d", Abc_NtkPoNum(pNtk) );
+        fprintf( pFile, " nd = %8d",  Abc_NtkNodeNum(pNtk) );
+        fprintf( pFile, " lat = %6d",  Abc_NtkLatchNum(pNtk) );
+        fprintf( pFile, " box = %6d", Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) );
+        fprintf( pFile, "\n" );
+        Count1 += (Abc_NtkPoNum(pNtk) == 1);
+    }
+    Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i )
+        pNtk->fHieVisited = 0;
+    fprintf( pFile, "The number of modules with one output = %d (%.2f %%).\n", Count1, 100.0 * Count1/Vec_PtrSize(pMan->pDesign->vModules) ); 
+
+    // report instances with dangling outputs
+    if ( Vec_PtrSize(pMan->pDesign->vModules) > 1 )
+    {
+        Vec_Ptr_t * vBundles;
+        Ver_Bundle_t * pBundle;
+        int j, nActNets, Counter = 0;
+        // count the number of instances with dangling outputs
+        Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i )
+        {
+            Abc_NtkForEachBox( pNtk, pBox, k )
+            {
+                if ( Abc_ObjIsLatch(pBox) )
+                    continue;
+                vBundles = (Vec_Ptr_t *)pBox->pCopy;
+                pNtkBox = (Abc_Ntk_t *)pBox->pData;
+                if ( pNtkBox == NULL )
+                    continue;
+                if ( !Ver_NtkIsDefined(pNtkBox) )
+                    continue;
+                // count the number of actual nets
+                nActNets = 0;
+                Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, j )
+                    nActNets += Vec_PtrSize(pBundle->vNetsActual);
+                // the box is defined and will be connected
+                if ( nActNets != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) )
+                    Counter++;
+            }
+        }
+        if ( Counter == 0 )
+            fprintf( pFile, "The outputs of all box instances are connected.\n" );
+        else
+        {
+            fprintf( pFile, "\n" );
+            fprintf( pFile, "The outputs of %d box instances are not connected:\n", Counter );
+            // enumerate through the boxes
+            Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i )
+            {
+                Abc_NtkForEachBox( pNtk, pBox, k )
+                {
+                    if ( Abc_ObjIsLatch(pBox) )
+                        continue;
+                    vBundles = (Vec_Ptr_t *)pBox->pCopy;
+                    pNtkBox = (Abc_Ntk_t *)pBox->pData;
+                    if ( pNtkBox == NULL )
+                        continue;
+                    if ( !Ver_NtkIsDefined(pNtkBox) )
+                        continue;
+                    // count the number of actual nets
+                    nActNets = 0;
+                    Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, j )
+                        nActNets += Vec_PtrSize(pBundle->vNetsActual);
+                    // the box is defined and will be connected
+                    if ( nActNets != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) )
+                        fprintf( pFile, "In module \"%s\" instance \"%s\" of box \"%s\" has different numbers of actual/formal nets (%d/%d).\n",
+                            Abc_NtkName(pNtk), Abc_ObjName(pBox), Abc_NtkName(pNtkBox), nActNets, Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) );
+                }
+            }
+        }
+    }
+    fclose( pFile );
+    printf( "Hierarchy statistics can be found in log file \"%s\".\n", Buffer );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Attaches the boxes to the network.]
+
+  Description [This procedure is called after the design is parsed. 
+  At that point, all the defined models have their PIs present. 
+  They are connected first. Next undef boxes are processed (if present).
+  Iteratively, one bundle is selected to be driven by the undef boxes in such 
+  a way that there is no conflict (if it is driven by an instance of the box,
+  no other net will be driven twice by the same formal net of some other instance 
+  of the same box). In the end, all the remaining nets that cannot be driven 
+  by the undef boxes are connected to the undef boxes as inputs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseAttachBoxes( Ver_Man_t * pMan )
+{
+    int fPrintLog = 1;
+    Abc_Ntk_t * pNtk = NULL;
+    Ver_Bundle_t * pBundle;
+    Vec_Ptr_t * vUndefs;
+    int i, RetValue, Counter, nMaxBoxSize;
+
+    // print the log file
+    if ( fPrintLog && pMan->pDesign->vModules && Vec_PtrSize(pMan->pDesign->vModules) > 1 )
+        Ver_ParsePrintLog( pMan );
+
+    // connect defined boxes
+    RetValue = Ver_ParseConnectDefBoxes( pMan );
+    if ( RetValue < 2 )
+        return RetValue;
+
+    // report the boxes
+    Ver_ParseReportUndefBoxes( pMan );
+
+    // collect undef box types and their actual instances
+    vUndefs = Ver_ParseCollectUndefBoxes( pMan );
+    assert( Vec_PtrSize( vUndefs ) > 0 );
+
+    // go through all undef box types
+    Counter = 0;
+    nMaxBoxSize = Ver_ParseMaxBoxSize( vUndefs );
+    while ( Ver_ParseCheckNondrivenNets(vUndefs) && Counter < nMaxBoxSize )
+    {
+        // go through undef box types
+        pBundle = NULL;
+        Vec_PtrForEachEntry( Abc_Ntk_t *, vUndefs, pNtk, i )
+            if ( (pBundle = Ver_ParseGetNondrivenBundle( pNtk, Counter )) )
+                break;
+        if ( pBundle == NULL )
+        {
+            Counter++;
+            continue;
+        }
+        // drive this bundle by this box
+        if ( !Ver_ParseDriveFormal( pMan, pNtk, pBundle ) )
+            return 0;
+    }
+
+    // make all the remaining bundles the drivers of undefs
+    if ( !Ver_ParseDriveInputs( pMan, vUndefs ) )
+        return 0;
+
+    // cleanup
+    Vec_PtrForEachEntry( Abc_Ntk_t *, vUndefs, pNtk, i )
+    {
+        Vec_PtrFree( (Vec_Ptr_t *)pNtk->pData );
+        pNtk->pData = NULL;
+    }
+    Vec_PtrFree( vUndefs ); 
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates PI terminal and net.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName )
+{
+    Abc_Obj_t * pNet, * pTerm;
+    // get the PI net
+//    pNet  = Ver_ParseFindNet( pNtk, pName );
+//    if ( pNet )
+//        printf( "Warning: PI \"%s\" appears twice in the list.\n", pName );
+    pNet  = Abc_NtkFindOrCreateNet( pNtk, pName );
+    // add the PI node
+    pTerm = Abc_NtkCreatePi( pNtk );
+    Abc_ObjAddFanin( pNet, pTerm );
+    return pTerm;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates PO terminal and net.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName )
+{
+    Abc_Obj_t * pNet, * pTerm;
+    // get the PO net
+//    pNet  = Ver_ParseFindNet( pNtk, pName );
+//    if ( pNet && Abc_ObjFaninNum(pNet) == 0 )
+//        printf( "Warning: PO \"%s\" appears twice in the list.\n", pName );
+    pNet  = Abc_NtkFindOrCreateNet( pNtk, pName );
+    // add the PO node
+    pTerm = Abc_NtkCreatePo( pNtk );
+    Abc_ObjAddFanin( pTerm, pNet );
+    return pTerm;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create a latch with the given input/output.]
+
+  Description [By default, the latch value is a don't-care.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pNetLI, Abc_Obj_t * pNetLO )
+{
+    Abc_Obj_t * pLatch, * pTerm;
+    // add the BO terminal
+    pTerm = Abc_NtkCreateBi( pNtk );
+    Abc_ObjAddFanin( pTerm, pNetLI );
+    // add the latch box
+    pLatch = Abc_NtkCreateLatch( pNtk );
+    Abc_ObjAddFanin( pLatch, pTerm  );
+    // add the BI terminal
+    pTerm = Abc_NtkCreateBo( pNtk );
+    Abc_ObjAddFanin( pTerm, pLatch );
+    // get the LO net
+    Abc_ObjAddFanin( pNetLO, pTerm );
+    // set latch name
+    Abc_ObjAssignName( pLatch, Abc_ObjName(pNetLO), "L" );
+    Abc_LatchSetInitDc( pLatch );
+    return pLatch;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates inverter and returns its net.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet )
+{
+    Abc_Obj_t * pObj;
+    pObj = Abc_NtkCreateNodeInv( pNtk, pNet );
+    pNet = Abc_NtkCreateNet( pNtk );
+    Abc_ObjAddFanin( pNet, pObj );
+    return pNet;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/ver/verFormula.c b/abc-build/src/base/ver/verFormula.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/ver/verFormula.c
@@ -0,0 +1,479 @@
+/**CFile****************************************************************
+
+  FileName    [verFormula.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Verilog parser.]
+
+  Synopsis    [Formula parser to read Verilog assign statements.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 19, 2006.]
+
+  Revision    [$Id: verFormula.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// the list of operation symbols to be used in expressions
+#define VER_PARSE_SYM_OPEN    '('   // opening paranthesis
+#define VER_PARSE_SYM_CLOSE   ')'   // closing paranthesis
+#define VER_PARSE_SYM_CONST0  '0'   // constant 0
+#define VER_PARSE_SYM_CONST1  '1'   // constant 1
+#define VER_PARSE_SYM_NEGBEF1 '!'   // negation before the variable
+#define VER_PARSE_SYM_NEGBEF2 '~'   // negation before the variable
+#define VER_PARSE_SYM_AND     '&'   // logic AND
+#define VER_PARSE_SYM_OR      '|'   // logic OR
+#define VER_PARSE_SYM_XOR     '^'   // logic XOR
+#define VER_PARSE_SYM_MUX1    '?'   // first symbol of MUX
+#define VER_PARSE_SYM_MUX2    ':'   // second symbol of MUX
+
+// the list of opcodes (also specifying operation precedence)
+#define VER_PARSE_OPER_NEG     7    // negation (highest precedence)
+#define VER_PARSE_OPER_AND     6    // logic AND
+#define VER_PARSE_OPER_XOR     5    // logic EXOR   (a'b | ab')   
+#define VER_PARSE_OPER_OR      4    // logic OR
+#define VER_PARSE_OPER_EQU     3    // equvalence   (a'b'| ab )
+#define VER_PARSE_OPER_MUX     2    // MUX(a,b,c)   (ab | a'c )
+#define VER_PARSE_OPER_MARK    1    // OpStack token standing for an opening paranthesis
+
+// these are values of the internal Flag
+#define VER_PARSE_FLAG_START   1    // after the opening parenthesis 
+#define VER_PARSE_FLAG_VAR     2    // after operation is received
+#define VER_PARSE_FLAG_OPER    3    // after operation symbol is received
+#define VER_PARSE_FLAG_ERROR   4    // when error is detected
+
+static Hop_Obj_t * Ver_FormulaParserTopOper( Hop_Man_t * pMan, Vec_Ptr_t * vStackFn, int Oper );
+static int         Ver_FormulaParserFindVar( char * pString, Vec_Ptr_t * vNames );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Parser of the formula encountered in assign statements.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage )
+{
+    char * pTemp;
+    Hop_Obj_t * bFunc, * bTemp;
+    int nParans, Flag;
+	int Oper, Oper1, Oper2;
+    int v;
+
+    // clear the stacks and the names
+    Vec_PtrClear( vNames );
+    Vec_PtrClear( vStackFn );
+    Vec_IntClear( vStackOp );
+
+    if ( !strcmp(pFormula, "0") || !strcmp(pFormula, "1\'b0") )
+        return Hop_ManConst0((Hop_Man_t *)pMan);
+    if ( !strcmp(pFormula, "1") || !strcmp(pFormula, "1\'b1") )
+        return Hop_ManConst1((Hop_Man_t *)pMan);
+
+    // make sure that the number of opening and closing parantheses is the same
+    nParans = 0;
+    for ( pTemp = pFormula; *pTemp; pTemp++ )
+        if ( *pTemp == '(' )
+            nParans++;
+        else if ( *pTemp == ')' )
+            nParans--;
+    if ( nParans != 0 )
+    {
+        sprintf( pErrorMessage, "Parse_FormulaParser(): Different number of opening and closing parantheses ()." );
+        return NULL;
+    }
+ 
+    // add parantheses
+    pTemp = pFormula + strlen(pFormula) + 2;
+    *pTemp-- = 0; *pTemp = ')';
+    while ( --pTemp != pFormula )
+        *pTemp = *(pTemp - 1);
+    *pTemp = '(';
+
+    // perform parsing
+    Flag = VER_PARSE_FLAG_START;
+    for ( pTemp = pFormula; *pTemp; pTemp++ )
+	{
+		switch ( *pTemp )
+	    {
+		// skip all spaces, tabs, and end-of-lines
+        case ' ':
+        case '\t':
+        case '\r':
+        case '\n':
+			continue;
+/*
+		// treat Constant 0 as a variable
+		case VER_PARSE_SYM_CONST0:
+		    Vec_PtrPush( vStackFn, Hop_ManConst0(pMan) );  // Cudd_Ref( Hop_ManConst0(pMan) );
+			if ( Flag == VER_PARSE_FLAG_VAR )
+			{
+				sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 0." );
+				Flag = VER_PARSE_FLAG_ERROR; 
+                break;
+			}
+            Flag = VER_PARSE_FLAG_VAR; 
+            break;
+
+		// the same for Constant 1
+		case VER_PARSE_SYM_CONST1:
+		    Vec_PtrPush( vStackFn, Hop_ManConst1(pMan) );  //  Cudd_Ref( Hop_ManConst1(pMan) );
+			if ( Flag == VER_PARSE_FLAG_VAR )
+			{
+				sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 1." );
+				Flag = VER_PARSE_FLAG_ERROR; 
+                break;
+			}
+            Flag = VER_PARSE_FLAG_VAR; 
+            break;
+*/
+		case VER_PARSE_SYM_NEGBEF1:
+		case VER_PARSE_SYM_NEGBEF2:
+			if ( Flag == VER_PARSE_FLAG_VAR )
+			{// if NEGBEF follows a variable, AND is assumed
+				sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before negation." );
+				Flag = VER_PARSE_FLAG_ERROR; 
+                break;
+			}
+    		Vec_IntPush( vStackOp, VER_PARSE_OPER_NEG );
+			break;
+
+        case VER_PARSE_SYM_AND:
+        case VER_PARSE_SYM_OR:
+        case VER_PARSE_SYM_XOR:
+        case VER_PARSE_SYM_MUX1:
+        case VER_PARSE_SYM_MUX2:
+			if ( Flag != VER_PARSE_FLAG_VAR )
+			{
+				sprintf( pErrorMessage, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR." );
+				Flag = VER_PARSE_FLAG_ERROR; 
+                break;
+			}
+			if ( *pTemp == VER_PARSE_SYM_AND )
+				Vec_IntPush( vStackOp, VER_PARSE_OPER_AND );
+			else if ( *pTemp == VER_PARSE_SYM_OR )
+				Vec_IntPush( vStackOp, VER_PARSE_OPER_OR );
+			else if ( *pTemp == VER_PARSE_SYM_XOR )
+				Vec_IntPush( vStackOp, VER_PARSE_OPER_XOR );
+			else if ( *pTemp == VER_PARSE_SYM_MUX1 )
+				Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX );
+//			else if ( *pTemp == VER_PARSE_SYM_MUX2 )
+//				Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX );
+			Flag = VER_PARSE_FLAG_OPER; 
+            break;
+
+        case VER_PARSE_SYM_OPEN:
+			if ( Flag == VER_PARSE_FLAG_VAR )
+			{
+				sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before a paranthesis." );
+				Flag = VER_PARSE_FLAG_ERROR; 
+                break;
+			}
+			Vec_IntPush( vStackOp, VER_PARSE_OPER_MARK );
+			// after an opening bracket, it feels like starting over again
+			Flag = VER_PARSE_FLAG_START; 
+            break;
+
+		case VER_PARSE_SYM_CLOSE:
+			if ( Vec_IntSize( vStackOp ) )
+            {
+				while ( 1 )
+			    {
+				    if ( !Vec_IntSize( vStackOp ) )
+					{
+						sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" );
+						Flag = VER_PARSE_FLAG_ERROR; 
+                        break;
+					}
+					Oper = Vec_IntPop( vStackOp );
+					if ( Oper == VER_PARSE_OPER_MARK )
+						break;
+                    // skip the second MUX operation
+//                    if ( Oper == VER_PARSE_OPER_MUX2 )
+//                    {
+//					    Oper = Vec_IntPop( vStackOp );
+//                        assert( Oper == VER_PARSE_OPER_MUX1 );
+//                    }
+
+                    // perform the given operation
+                    if ( Ver_FormulaParserTopOper( (Hop_Man_t *)pMan, vStackFn, Oper ) == NULL )
+	                {
+		                sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" );
+		                return NULL;
+	                }
+			    }
+            }
+		    else
+			{
+				sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" );
+				Flag = VER_PARSE_FLAG_ERROR; 
+                break;
+			}
+			if ( Flag != VER_PARSE_FLAG_ERROR )
+			    Flag = VER_PARSE_FLAG_VAR; 
+			break;
+
+
+		default:
+            // scan the next name
+            v = Ver_FormulaParserFindVar( pTemp, vNames );
+            if ( *pTemp == '\\' )
+                pTemp++;
+            pTemp += (int)(ABC_PTRUINT_T)Vec_PtrEntry( vNames, 2*v ) - 1;
+
+			// assume operation AND, if vars follow one another
+			if ( Flag == VER_PARSE_FLAG_VAR )
+            {
+		        sprintf( pErrorMessage, "Parse_FormulaParser(): Incorrect state." );
+                return NULL;
+            }
+            bTemp = Hop_IthVar( (Hop_Man_t *)pMan, v );
+			Vec_PtrPush( vStackFn, bTemp ); //  Cudd_Ref( bTemp );
+            Flag = VER_PARSE_FLAG_VAR; 
+            break;
+	    }
+
+		if ( Flag == VER_PARSE_FLAG_ERROR )
+			break;      // error exit
+		else if ( Flag == VER_PARSE_FLAG_START )
+			continue;  //  go on parsing
+		else if ( Flag == VER_PARSE_FLAG_VAR )
+			while ( 1 )
+			{  // check if there are negations in the OpStack     
+				if ( !Vec_IntSize(vStackOp) )
+					break;
+                Oper = Vec_IntPop( vStackOp );
+				if ( Oper != VER_PARSE_OPER_NEG )
+                {
+					Vec_IntPush( vStackOp, Oper );
+					break;
+                }
+				else
+				{
+//      				Vec_PtrPush( vStackFn, Cudd_Not(Vec_PtrPop(vStackFn)) );
+      				Vec_PtrPush( vStackFn, Hop_Not((Hop_Obj_t *)Vec_PtrPop(vStackFn)) );
+				}
+			}
+		else // if ( Flag == VER_PARSE_FLAG_OPER )
+			while ( 1 )
+			{  // execute all the operations in the OpStack
+			   // with precedence higher or equal than the last one
+				Oper1 = Vec_IntPop( vStackOp ); // the last operation
+				if ( !Vec_IntSize(vStackOp) ) 
+				{  // if it is the only operation, push it back
+					Vec_IntPush( vStackOp, Oper1 );
+					break;
+				}
+				Oper2 = Vec_IntPop( vStackOp ); // the operation before the last one
+				if ( Oper2 >= Oper1 && !(Oper1 == Oper2 && Oper1 == VER_PARSE_OPER_MUX) )  
+				{  // if Oper2 precedence is higher or equal, execute it
+                    if ( Ver_FormulaParserTopOper( (Hop_Man_t *)pMan, vStackFn, Oper2 ) == NULL )
+	                {
+		                sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" );
+		                return NULL;
+	                }
+					Vec_IntPush( vStackOp,  Oper1 );     // push the last operation back
+				}
+				else
+				{  // if Oper2 precedence is lower, push them back and done
+					Vec_IntPush( vStackOp, Oper2 );
+					Vec_IntPush( vStackOp, Oper1 );
+					break;
+				}
+			}
+    }
+
+	if ( Flag != VER_PARSE_FLAG_ERROR )
+    {
+		if ( Vec_PtrSize(vStackFn) )
+	    {	
+			bFunc = (Hop_Obj_t *)Vec_PtrPop(vStackFn);
+			if ( !Vec_PtrSize(vStackFn) )
+				if ( !Vec_IntSize(vStackOp) )
+                {
+//                    Cudd_Deref( bFunc );
+					return bFunc;
+                }
+				else
+					sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the operation stack\n" );
+			else
+				sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the function stack\n" );
+	    }
+	    else
+			sprintf( pErrorMessage, "Parse_FormulaParser(): The input string is empty\n" );
+    }
+//    Cudd_Ref( bFunc );
+//    Cudd_RecursiveDeref( dd, bFunc );
+	return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs the operation on the top entries in the stack.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Ver_FormulaParserTopOper( Hop_Man_t * pMan, Vec_Ptr_t * vStackFn, int Oper )
+{
+    Hop_Obj_t * bArg0, * bArg1, * bArg2, * bFunc;
+    // perform the given operation
+    bArg2 = (Hop_Obj_t *)Vec_PtrPop( vStackFn );
+    bArg1 = (Hop_Obj_t *)Vec_PtrPop( vStackFn );
+	if ( Oper == VER_PARSE_OPER_AND )
+		bFunc = Hop_And( pMan, bArg1, bArg2 );
+	else if ( Oper == VER_PARSE_OPER_XOR )
+		bFunc = Hop_Exor( pMan, bArg1, bArg2 );
+	else if ( Oper == VER_PARSE_OPER_OR )
+		bFunc = Hop_Or( pMan, bArg1, bArg2 );
+	else if ( Oper == VER_PARSE_OPER_EQU )
+		bFunc = Hop_Not( Hop_Exor( pMan, bArg1, bArg2 ) );
+	else if ( Oper == VER_PARSE_OPER_MUX )
+    {
+        bArg0 = (Hop_Obj_t *)Vec_PtrPop( vStackFn );
+//		bFunc = Cudd_bddIte( dd, bArg0, bArg1, bArg2 );  Cudd_Ref( bFunc );
+		bFunc = Hop_Mux( pMan, bArg0, bArg1, bArg2 ); 
+//        Cudd_RecursiveDeref( dd, bArg0 );
+//        Cudd_Deref( bFunc );
+    }
+	else
+		return NULL;
+//    Cudd_Ref( bFunc );
+//    Cudd_RecursiveDeref( dd, bArg1 );
+//    Cudd_RecursiveDeref( dd, bArg2 );
+	Vec_PtrPush( vStackFn,  bFunc );
+    return bFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the index of the new variable found.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_FormulaParserFindVar( char * pString, Vec_Ptr_t * vNames )
+{
+    char * pTemp, * pTemp2;
+    int nLength, nLength2, i;
+    // start the string
+    pTemp = pString;
+    // find the end of the string delimited by other characters
+    if ( *pTemp == '\\' )
+    {
+        pString++;
+        while ( *pTemp && *pTemp != ' ' )
+            pTemp++;
+    }
+    else
+    {
+        while ( *pTemp && *pTemp != ' ' && *pTemp != '\t' && *pTemp != '\r' && *pTemp != '\n' && *pTemp != ',' && *pTemp != '}' && 
+                *pTemp != VER_PARSE_SYM_OPEN && *pTemp != VER_PARSE_SYM_CLOSE && 
+                *pTemp != VER_PARSE_SYM_NEGBEF1 && *pTemp != VER_PARSE_SYM_NEGBEF2 && 
+                *pTemp != VER_PARSE_SYM_AND && *pTemp != VER_PARSE_SYM_OR && *pTemp != VER_PARSE_SYM_XOR && 
+                *pTemp != VER_PARSE_SYM_MUX1 && *pTemp != VER_PARSE_SYM_MUX2 )
+                pTemp++;
+    }
+    // look for this string in the array
+    nLength = pTemp - pString;
+    for ( i = 0; i < Vec_PtrSize(vNames)/2; i++ )
+    {
+        nLength2 = (int)(ABC_PTRUINT_T)Vec_PtrEntry( vNames, 2*i + 0 );
+        if ( nLength2 != nLength )
+            continue;
+        pTemp2   = (char *)Vec_PtrEntry( vNames, 2*i + 1 );
+        if ( strncmp( pString, pTemp2, nLength ) )
+            continue;
+        return i;
+    }
+    // could not find - add and return the number
+    Vec_PtrPush( vNames, (void *)(ABC_PTRUINT_T)nLength );
+    Vec_PtrPush( vNames, pString );
+    return i;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the AIG representation of the reduction formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Ver_FormulaReduction( char * pFormula, void * pMan, Vec_Ptr_t * vNames, char * pErrorMessage )
+{
+    Hop_Obj_t * pRes = NULL;
+    int v, fCompl;
+    char Symbol;
+
+    // get the operation
+    Symbol = *pFormula++;
+    fCompl = ( Symbol == '~' );
+    if ( fCompl )
+        Symbol = *pFormula++;
+    // check the operation
+    if ( Symbol != '&' && Symbol != '|' && Symbol != '^' )
+    {
+		sprintf( pErrorMessage, "Ver_FormulaReduction(): Unknown operation (%c)\n", Symbol );
+		return NULL;
+    }
+    // skip the brace
+    while ( *pFormula++ != '{' );
+    // parse the names
+    Vec_PtrClear( vNames );
+    while ( *pFormula != '}' )
+    {
+        v = Ver_FormulaParserFindVar( pFormula, vNames );
+        pFormula += (int)(ABC_PTRUINT_T)Vec_PtrEntry( vNames, 2*v );
+        while ( *pFormula == ' ' || *pFormula == ',' )
+            pFormula++;
+    }
+    // compute the function
+    if ( Symbol == '&' )
+        pRes = Hop_CreateAnd( (Hop_Man_t *)pMan, Vec_PtrSize(vNames)/2 );
+    else if ( Symbol == '|' )
+        pRes = Hop_CreateOr( (Hop_Man_t *)pMan, Vec_PtrSize(vNames)/2 );
+    else if ( Symbol == '^' )
+        pRes = Hop_CreateExor( (Hop_Man_t *)pMan, Vec_PtrSize(vNames)/2 );
+    return Hop_NotCond( pRes, fCompl );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/ver/verParse.c b/abc-build/src/base/ver/verParse.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/ver/verParse.c
@@ -0,0 +1,131 @@
+/**CFile****************************************************************
+
+  FileName    [verParse.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Verilog parser.]
+
+  Synopsis    [Performs some Verilog parsing tasks.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 19, 2006.]
+
+  Revision    [$Id: verParse.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Skips the comments of they are present.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseSkipComments( Ver_Man_t * pMan )
+{
+    Ver_Stream_t * p = pMan->pReader;
+    char Symbol;
+    // skip spaces
+    Ver_StreamSkipChars( p, " \t\n\r" );
+    if ( !Ver_StreamIsOkey(pMan->pReader) )
+        return 1;
+    // read the first symbol
+    Symbol = Ver_StreamScanChar( p );
+    if ( Symbol != '/' )
+        return 1;
+    Ver_StreamPopChar( p );
+    // read the second symbol
+    Symbol = Ver_StreamScanChar( p );
+    if ( Symbol == '/' )
+    { // skip till the end of line
+        Ver_StreamSkipToChars( p, "\n" );
+        return Ver_ParseSkipComments( pMan );
+    }
+    if ( Symbol == '*' )
+    { // skip till the next occurance of */
+        Ver_StreamPopChar( p );
+        do {
+            Ver_StreamSkipToChars( p, "*" );
+            Ver_StreamPopChar( p );
+        } while ( Ver_StreamScanChar( p ) != '/' );
+        Ver_StreamPopChar( p );
+        return Ver_ParseSkipComments( pMan );
+    }
+    sprintf( pMan->sError, "Cannot parse after symbol \"/\"." );
+    Ver_ParsePrintErrorMessage( pMan );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses a Verilog name that can be being with a slash.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Ver_ParseGetName( Ver_Man_t * pMan )
+{
+    Ver_Stream_t * p = pMan->pReader;
+    char Symbol;
+    char * pWord;
+    pMan->fNameLast = 0;
+    if ( !Ver_StreamIsOkey(p) )
+        return NULL;
+    if ( !Ver_ParseSkipComments( pMan ) )
+        return NULL;
+    Symbol = Ver_StreamScanChar( p );
+    if ( Symbol == '\\' )
+    {
+        pMan->fNameLast = 1;
+        Ver_StreamPopChar( p );
+        pWord = Ver_StreamGetWord( p, " \r\n" );
+        Ver_StreamSkipChars( p, " \r\n" );
+        if ( Ver_StreamScanChar(p) == '[' )
+        {
+            char This, * pEnd = pWord + strlen( pWord );
+            while ( (This = Ver_StreamPopChar(p)) != ']' )
+                *pEnd++ = This;
+            *pEnd++ = This;
+            *pEnd = 0;
+        }
+    }
+    else
+        pWord = Ver_StreamGetWord( p, " \t\n\r(),;" );
+    if ( Ver_StreamIsOkey(p) && !Ver_ParseSkipComments( pMan ) )
+        return NULL;
+    return pWord;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/ver/verStream.c b/abc-build/src/base/ver/verStream.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/ver/verStream.c
@@ -0,0 +1,450 @@
+/**CFile****************************************************************
+
+  FileName    [verStream.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Verilog parser.]
+
+  Synopsis    [Input file stream, which knows nothing about Verilog.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 19, 2006.]
+
+  Revision    [$Id: verStream.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define VER_BUFFER_SIZE        1048576    // 1M  - size of the data chunk stored in memory
+#define VER_OFFSET_SIZE          65536    // 64K - load new data when less than this is left
+#define VER_WORD_SIZE            65536    // 64K - the largest token that can be returned
+
+#define VER_MINIMUM(a,b)       (((a) < (b))? (a) : (b))
+
+struct Ver_Stream_t_
+{
+    // the input file
+    char *           pFileName;     // the input file name
+    FILE *           pFile;         // the input file pointer
+    iword            nFileSize;     // the total number of bytes in the file
+    iword            nFileRead;     // the number of bytes currently read from file
+    iword            nLineCounter;  // the counter of lines processed
+    // temporary storage for data 
+    iword            nBufferSize;   // the size of the buffer
+    char *           pBuffer;       // the buffer
+    char *           pBufferCur;    // the current reading position
+    char *           pBufferEnd;    // the first position not used by currently loaded data
+    char *           pBufferStop;   // the position where loading new data will be done
+    // tokens given to the user
+    char             pChars[VER_WORD_SIZE+5]; // temporary storage for a word (plus end-of-string and two parantheses)
+    int              nChars;        // the total number of characters in the word
+    // status of the parser
+    int              fStop;         // this flag goes high when the end of file is reached
+};
+
+static void Ver_StreamReload( Ver_Stream_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the file reader for the given file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ver_Stream_t * Ver_StreamAlloc( char * pFileName )
+{
+    Ver_Stream_t * p;
+    FILE * pFile;
+    int nCharsToRead;
+    int RetValue;
+    // check if the file can be opened
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Ver_StreamAlloc(): Cannot open input file \"%s\".\n", pFileName );
+        return NULL;
+    }
+    // start the file reader    
+    p = ABC_ALLOC( Ver_Stream_t, 1 );
+    memset( p, 0, sizeof(Ver_Stream_t) );
+    p->pFileName   = pFileName;
+    p->pFile       = pFile;
+    // get the file size, in bytes
+    fseek( pFile, 0, SEEK_END );  
+    p->nFileSize = ftell( pFile );  
+    rewind( pFile ); 
+    // allocate the buffer
+    p->pBuffer = ABC_ALLOC( char, VER_BUFFER_SIZE+1 );
+    p->nBufferSize = VER_BUFFER_SIZE;
+    p->pBufferCur  = p->pBuffer;
+    // determine how many chars to read
+    nCharsToRead = VER_MINIMUM(p->nFileSize, VER_BUFFER_SIZE);
+    // load the first part into the buffer
+    RetValue = fread( p->pBuffer, nCharsToRead, 1, p->pFile );
+    p->nFileRead = nCharsToRead;
+    // set the ponters to the end and the stopping point
+    p->pBufferEnd  = p->pBuffer + nCharsToRead;
+    p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + VER_BUFFER_SIZE - VER_OFFSET_SIZE;
+    // start the arrays
+    p->nLineCounter = 1; // 1-based line counting
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Loads new data into the file reader.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ver_StreamReload( Ver_Stream_t * p )
+{
+    int nCharsUsed, nCharsToRead;
+    int RetValue;
+    assert( !p->fStop );
+    assert( p->pBufferCur > p->pBufferStop );
+    assert( p->pBufferCur < p->pBufferEnd );
+    // figure out how many chars are still not processed
+    nCharsUsed = p->pBufferEnd - p->pBufferCur;
+    // move the remaining data to the beginning of the buffer
+    memmove( p->pBuffer, p->pBufferCur, nCharsUsed );
+    p->pBufferCur = p->pBuffer;
+    // determine how many chars we will read
+    nCharsToRead = VER_MINIMUM( p->nBufferSize - nCharsUsed, p->nFileSize - p->nFileRead );
+    // read the chars
+    RetValue = fread( p->pBuffer + nCharsUsed, nCharsToRead, 1, p->pFile );
+    p->nFileRead += nCharsToRead;
+    // set the ponters to the end and the stopping point
+    p->pBufferEnd  = p->pBuffer + nCharsUsed + nCharsToRead;
+    p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + VER_BUFFER_SIZE - VER_OFFSET_SIZE;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the file reader.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ver_StreamFree( Ver_Stream_t * p )
+{
+    if ( p->pFile )
+        fclose( p->pFile );
+    ABC_FREE( p->pBuffer );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the file size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Ver_StreamGetFileName( Ver_Stream_t * p )
+{
+    return p->pFileName;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the file size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_StreamGetFileSize( Ver_Stream_t * p )
+{
+    return p->nFileSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the current reading position.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_StreamGetCurPosition( Ver_Stream_t * p )
+{
+    return p->nFileRead - (p->pBufferEnd - p->pBufferCur);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the line number for the given token.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_StreamGetLineNumber( Ver_Stream_t * p )
+{
+    return p->nLineCounter;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns current symbol.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_StreamIsOkey( Ver_Stream_t * p )
+{
+    return !p->fStop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns current symbol.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char Ver_StreamScanChar( Ver_Stream_t * p )
+{
+    assert( !p->fStop );
+    return *p->pBufferCur;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns current symbol and moves to the next.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char Ver_StreamPopChar( Ver_Stream_t * p )
+{
+    assert( !p->fStop );
+    // check if the new data should to be loaded
+    if ( p->pBufferCur > p->pBufferStop )
+        Ver_StreamReload( p );
+    // check if there are symbols left
+    if ( p->pBufferCur == p->pBufferEnd ) // end of file
+    {
+        p->fStop = 1;
+        return -1;
+    }
+    // count the lines
+    if ( *p->pBufferCur == '\n' )
+        p->nLineCounter++;
+    return *p->pBufferCur++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Skips the current symbol and all symbols from the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ver_StreamSkipChars( Ver_Stream_t * p, char * pCharsToSkip )
+{
+    char * pChar, * pTemp;
+    assert( !p->fStop );
+    assert( pCharsToSkip != NULL );
+    // check if the new data should to be loaded
+    if ( p->pBufferCur > p->pBufferStop )
+        Ver_StreamReload( p );
+    // skip the symbols
+    for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ )
+    {
+        // skip symbols as long as they are in the list
+        for ( pTemp = pCharsToSkip; *pTemp; pTemp++ )
+            if ( *pChar == *pTemp )
+                break;
+        if ( *pTemp == 0 ) // pChar is not found in the list
+        {
+            p->pBufferCur = pChar;
+            return;
+        }
+        // count the lines
+        if ( *pChar == '\n' )
+            p->nLineCounter++;
+    }
+    // the file is finished or the last part continued 
+    // through VER_OFFSET_SIZE chars till the end of the buffer
+    if ( p->pBufferStop == p->pBufferEnd ) // end of file
+    {
+        p->fStop = 1;
+        return;
+    }
+    printf( "Ver_StreamSkipSymbol() failed to parse the file \"%s\".\n", p->pFileName );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Skips all symbols until encountering one from the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ver_StreamSkipToChars( Ver_Stream_t * p, char * pCharsToStop )
+{
+    char * pChar, * pTemp;
+    assert( !p->fStop );
+    assert( pCharsToStop != NULL );
+    // check if the new data should to be loaded
+    if ( p->pBufferCur > p->pBufferStop )
+        Ver_StreamReload( p );
+    // skip the symbols
+    for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ )
+    {
+        // skip symbols as long as they are NOT in the list
+        for ( pTemp = pCharsToStop; *pTemp; pTemp++ )
+            if ( *pChar == *pTemp )
+                break;
+        if ( *pTemp == 0 ) // pChar is not found in the list
+        {
+            // count the lines
+            if ( *pChar == '\n' )
+                p->nLineCounter++;
+            continue;
+        }
+        // the symbol is found - move position and return
+        p->pBufferCur = pChar;
+        return;
+    }
+    // the file is finished or the last part continued 
+    // through VER_OFFSET_SIZE chars till the end of the buffer
+    if ( p->pBufferStop == p->pBufferEnd ) // end of file
+    {
+        p->fStop = 1;
+        return;
+    }
+    printf( "Ver_StreamSkipToSymbol() failed to parse the file \"%s\".\n", p->pFileName );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns current word delimited by the set of symbols.]
+
+  Description [Modifies the stream by inserting 0 at the first encounter
+  of one of the symbols in the list.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Ver_StreamGetWord( Ver_Stream_t * p, char * pCharsToStop )
+{
+    char * pChar, * pTemp;
+    if ( p->fStop )
+        return NULL;
+    assert( pCharsToStop != NULL );
+    // check if the new data should to be loaded
+    if ( p->pBufferCur > p->pBufferStop )
+        Ver_StreamReload( p );
+    // skip the symbols
+    p->nChars = 0;
+    for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ )
+    {
+        // skip symbols as long as they are NOT in the list
+        for ( pTemp = pCharsToStop; *pTemp; pTemp++ )
+            if ( *pChar == *pTemp )
+                break;
+        if ( *pTemp == 0 ) // pChar is not found in the list
+        {
+            p->pChars[p->nChars++] = *pChar;
+            if ( p->nChars == VER_WORD_SIZE )
+            {
+                printf( "Ver_StreamGetWord(): The buffer size is exceeded.\n" );
+                return NULL;
+            }
+            // count the lines
+            if ( *pChar == '\n' )
+                p->nLineCounter++;
+            continue;
+        }
+        // the symbol is found - move the position, set the word end, return the word
+        p->pBufferCur = pChar;
+        p->pChars[p->nChars] = 0;
+        return p->pChars;
+    }
+    // the file is finished or the last part continued 
+    // through VER_OFFSET_SIZE chars till the end of the buffer
+    if ( p->pBufferStop == p->pBufferEnd ) // end of file
+    {
+        p->fStop = 1;
+        p->pChars[p->nChars] = 0;
+        return p->pChars;
+    }
+    printf( "Ver_StreamGetWord() failed to parse the file \"%s\".\n", p->pFileName );
+    return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/ver/verWords.c b/abc-build/src/base/ver/verWords.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/ver/verWords.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+  FileName    [verWords.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Verilog parser.]
+
+  Synopsis    [Handles keywords that are currently supported.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 19, 2006.]
+
+  Revision    [$Id: verWords.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/base/ver/ver_.c b/abc-build/src/base/ver/ver_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/base/ver/ver_.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+  FileName    [ver_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Verilog parser.]
+
+  Synopsis    [Parses several flavors of structural Verilog.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 19, 2006.]
+
+  Revision    [$Id: ver_.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cas/cas.h b/abc-build/src/bdd/cas/cas.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cas/cas.h
@@ -0,0 +1,66 @@
+/**CFile****************************************************************
+
+  FileName    [cas.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cas.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__bdd__cas__cas_h
+#define ABC__bdd__cas__cas_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+#define MAXINPUTS   1024
+#define MAXOUTPUTS  1024
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== zzz.c ==========================================================*/
+ 
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/bdd/cas/casCore.c b/abc-build/src/bdd/cas/casCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cas/casCore.c
@@ -0,0 +1,1265 @@
+/**CFile****************************************************************
+
+  FileName    [casCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.]
+
+  Synopsis    [Entrance into the implementation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Spring 2002.]
+
+  Revision    [$Id: casCore.c,v 1.0 2002/01/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "base/main/main.h"
+#include "base/cmd/cmd.h"
+#include "misc/extra/extraBdd.h"
+#include "cas.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                      static functions                            ///
+////////////////////////////////////////////////////////////////////////
+
+DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc, int fVerbose );
+DdNode * GetSingleOutputFunctionRemapped( DdManager * dd, DdNode ** pOutputs, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc );
+DdNode * GetSingleOutputFunctionRemappedNewDD( DdManager * dd, DdNode ** pOutputs, int nOuts, DdManager ** DdNew );
+
+extern int CreateDecomposedNetwork( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName, int nLutSize, int fCheck, int fVerbose );
+
+void WriteSingleOutputFunctionBlif( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName );
+
+DdNode * Cudd_bddTransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute );
+
+////////////////////////////////////////////////////////////////////////
+///                      static varibles                             ///
+////////////////////////////////////////////////////////////////////////
+
+//static FILE * pTable = NULL;
+//static long s_RemappingTime = 0;
+
+////////////////////////////////////////////////////////////////////////
+///                      debugging macros                            ///
+////////////////////////////////////////////////////////////////////////
+
+#define PRD(p)       printf( "\nDECOMPOSITION TREE:\n\n" ); PrintDecEntry( (p), 0 ) 
+#define PRB_(f)       printf( #f " = " ); Cudd_bddPrint(dd,f); printf( "\n" )
+#define PRK(f,n)     Cudd_PrintKMap(stdout,dd,(f),Cudd_Not(f),(n),NULL,0); printf( "K-map for function" #f "\n\n" )
+#define PRK2(f,g,n)  Cudd_PrintKMap(stdout,dd,(f),(g),(n),NULL,0); printf( "K-map for function <" #f ", " #g ">\n\n" ) 
+
+
+////////////////////////////////////////////////////////////////////////
+///                     EXTERNAL FUNCTIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CascadeExperiment( char * pFileGeneric, DdManager * dd, DdNode ** pOutputs, int nInputs, int nOutputs, int nLutSize, int fCheck, int fVerbose )
+{
+    int i;
+    int nVars = nInputs;
+    int nOuts = nOutputs;
+    abctime clk1;
+
+    int      nVarsEnc;              // the number of additional variables to encode outputs
+    DdNode * pbVarsEnc[MAXOUTPUTS]; // the BDDs of the encoding vars
+
+    int      nNames;               // the total number of all inputs
+    char *   pNames[MAXINPUTS];     // the temporary storage for the input (and output encoding) names
+
+    DdNode * aFunc;                 // the encoded 0-1 BDD containing all the outputs
+
+    char FileNameIni[100];
+    char FileNameFin[100];
+    char Buffer[100];
+
+    
+//pTable = fopen( "stats.txt", "a+" );
+//fprintf( pTable, "%s ", pFileGeneric );
+//fprintf( pTable, "%d ", nVars );
+//fprintf( pTable, "%d ", nOuts );
+
+
+    // assign the file names
+    strcpy( FileNameIni, pFileGeneric );
+    strcat( FileNameIni, "_ENC.blif" );
+
+    strcpy( FileNameFin, pFileGeneric );
+    strcat( FileNameFin, "_LUT.blif" );
+
+
+    // create the variables to encode the outputs
+    nVarsEnc = Abc_Base2Log( nOuts );
+    for ( i = 0; i < nVarsEnc; i++ )
+        pbVarsEnc[i] = Cudd_bddNewVarAtLevel( dd, i );
+
+
+    // store the input names
+    nNames  = nVars + nVarsEnc;
+    for ( i = 0; i < nVars; i++ )
+    {
+//      pNames[i] = Extra_UtilStrsav( pFunc->pInputNames[i] );
+        sprintf( Buffer, "pi%03d", i );
+        pNames[i] = Extra_UtilStrsav( Buffer );
+    }
+    // set the encoding variable name
+    for ( ; i < nNames; i++ )
+    {       
+        sprintf( Buffer, "OutEnc_%02d", i-nVars );
+        pNames[i] = Extra_UtilStrsav( Buffer );
+    }
+
+
+    // print the variable order
+//  printf( "\n" );
+//  printf( "Variable order is: " );
+//  for ( i = 0; i < dd->size; i++ )
+//      printf( " %d", dd->invperm[i] );
+//  printf( "\n" );
+
+    // derive the single-output function
+    clk1 = Abc_Clock();
+    aFunc = GetSingleOutputFunction( dd, pOutputs, nOuts, pbVarsEnc, nVarsEnc, fVerbose );  Cudd_Ref( aFunc );
+//  aFunc = GetSingleOutputFunctionRemapped( dd, pOutputs, nOuts, pbVarsEnc, nVarsEnc );  Cudd_Ref( aFunc );
+//  if ( fVerbose )
+//  printf( "Single-output function computation time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+ 
+//fprintf( pTable, "%d ", Cudd_SharingSize( pOutputs, nOutputs ) );
+//fprintf( pTable, "%d ", Extra_ProfileWidthSharingMax(dd, pOutputs, nOutputs) );
+
+    // dispose of the multiple-output function
+//  Extra_Dissolve( pFunc );
+ 
+    // reorder the single output function
+//    if ( fVerbose )
+//  printf( "Reordering variables...\n");
+    clk1 = Abc_Clock();
+//  if ( fVerbose )
+//  printf( "Node count before = %6d\n", Cudd_DagSize( aFunc ) );
+//  Cudd_ReduceHeap(dd, CUDD_REORDER_SIFT,1);
+    Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1);
+    Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1);
+//  Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1);
+//  Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1);
+//  Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1);
+//  Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1);
+    if ( fVerbose )
+    printf( "MTBDD reordered = %6d nodes\n", Cudd_DagSize( aFunc ) );
+    if ( fVerbose )
+    printf( "Variable reordering time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+//  printf( "\n" );
+//  printf( "Variable order is: " );
+//  for ( i = 0; i < dd->size; i++ )
+//      printf( " %d", dd->invperm[i] );
+//  printf( "\n" );
+//fprintf( pTable, "%d ", Cudd_DagSize( aFunc ) );
+//fprintf( pTable, "%d ", Extra_ProfileWidthMax(dd, aFunc) );
+
+    // write the single-output function into BLIF for verification
+    clk1 = Abc_Clock();
+    if ( fCheck )
+    WriteSingleOutputFunctionBlif( dd, aFunc, pNames, nNames, FileNameIni );
+//    if ( fVerbose )
+//  printf( "Single-output function writing time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+
+/*
+    ///////////////////////////////////////////////////////////////////
+    // verification of single output function
+    clk1 = Abc_Clock();
+    {
+        BFunc g_Func;
+        DdNode * aRes;
+
+        g_Func.dd = dd;
+        g_Func.FileInput = Extra_UtilStrsav(FileNameIni);
+
+        if ( Extra_ReadFile( &g_Func ) == 0 )
+        {
+            printf( "\nSomething did not work out while reading the input file for verification\n");
+            Extra_Dissolve( &g_Func );
+            return;
+        } 
+
+        aRes = Cudd_BddToAdd( dd, g_Func.pOutputs[0] );  Cudd_Ref( aRes );
+
+        if ( aRes != aFunc )
+            printf( "\nVerification FAILED!\n");
+        else
+            printf( "\nVerification okay!\n");
+        
+        Cudd_RecursiveDeref( dd, aRes );
+
+        // delocate
+        Extra_Dissolve( &g_Func );
+    }
+    printf( "Preliminary verification time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+    ///////////////////////////////////////////////////////////////////
+*/
+
+    if ( !CreateDecomposedNetwork( dd, aFunc, pNames, nNames, FileNameFin, nLutSize, fCheck, fVerbose ) )
+        return 0;
+
+/*
+    ///////////////////////////////////////////////////////////////////
+    // verification of the decomposed LUT network
+    clk1 = Abc_Clock();
+    {
+        BFunc g_Func;
+        DdNode * aRes;
+
+        g_Func.dd = dd;
+        g_Func.FileInput = Extra_UtilStrsav(FileNameFin);
+
+        if ( Extra_ReadFile( &g_Func ) == 0 )
+        {
+            printf( "\nSomething did not work out while reading the input file for verification\n");
+            Extra_Dissolve( &g_Func );
+            return;
+        } 
+
+        aRes = Cudd_BddToAdd( dd, g_Func.pOutputs[0] );  Cudd_Ref( aRes );
+
+        if ( aRes != aFunc )
+            printf( "\nFinal verification FAILED!\n");
+        else
+            printf( "\nFinal verification okay!\n");
+        
+        Cudd_RecursiveDeref( dd, aRes );
+ 
+        // delocate 
+        Extra_Dissolve( &g_Func );
+    }
+    printf( "Final verification time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+    ///////////////////////////////////////////////////////////////////
+*/
+ 
+    // verify the results
+    if ( fCheck )
+    {
+        char Command[200];
+        sprintf( Command, "cec %s %s", FileNameIni, FileNameFin );
+        Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command );
+    }
+
+    Cudd_RecursiveDeref( dd, aFunc );
+
+    // release the names
+    for ( i = 0; i < nNames; i++ )
+        ABC_FREE( pNames[i] );
+
+
+//fprintf( pTable, "\n" );
+//fclose( pTable );
+
+    return 1;
+}
+
+#if 0
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Experiment2( BFunc * pFunc )
+{
+    int i, x, RetValue;
+    int nVars = pFunc->nInputs;
+    int nOuts = pFunc->nOutputs;
+    DdManager * dd = pFunc->dd;
+    long clk1;
+
+//  int      nVarsEnc;              // the number of additional variables to encode outputs
+//  DdNode * pbVarsEnc[MAXOUTPUTS]; // the BDDs of the encoding vars
+
+    int      nNames;               // the total number of all inputs
+    char *   pNames[MAXINPUTS];     // the temporary storage for the input (and output encoding) names
+
+    DdNode * aFunc;                 // the encoded 0-1 BDD containing all the outputs
+
+    char FileNameIni[100];
+    char FileNameFin[100];
+    char Buffer[100];
+
+    DdManager * DdNew;
+
+//pTable = fopen( "stats.txt", "a+" );
+//fprintf( pTable, "%s ", pFunc->FileGeneric );
+//fprintf( pTable, "%d ", nVars );
+//fprintf( pTable, "%d ", nOuts );
+
+
+    // assign the file names
+    strcpy( FileNameIni, pFunc->FileGeneric );
+    strcat( FileNameIni, "_ENC.blif" );
+
+    strcpy( FileNameFin, pFunc->FileGeneric );
+    strcat( FileNameFin, "_LUT.blif" );
+
+    // derive the single-output function IN THE NEW MANAGER
+    clk1 = Abc_Clock();
+//  aFunc = GetSingleOutputFunction( dd, pFunc->pOutputs, nOuts, pbVarsEnc, nVarsEnc );  Cudd_Ref( aFunc );
+    aFunc = GetSingleOutputFunctionRemappedNewDD( dd, pFunc->pOutputs, nOuts, &DdNew );  Cudd_Ref( aFunc );
+    printf( "Single-output function derivation time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+//  s_RemappingTime = Abc_Clock() - clk1;
+
+    // dispose of the multiple-output function
+    Extra_Dissolve( pFunc );
+
+    // reorder the single output function
+    printf( "\nReordering variables in the new manager...\n");
+    clk1 = Abc_Clock();
+    printf( "Node count before = %d\n", Cudd_DagSize( aFunc ) );
+//  Cudd_ReduceHeap(DdNew, CUDD_REORDER_SIFT,1);
+    Cudd_ReduceHeap(DdNew, CUDD_REORDER_SYMM_SIFT,1);
+//  Cudd_ReduceHeap(DdNew, CUDD_REORDER_SYMM_SIFT,1);
+    printf( "Node count after  = %d\n", Cudd_DagSize( aFunc ) );
+    printf( "Variable reordering time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+    printf( "\n" );
+
+//fprintf( pTable, "%d ", Cudd_DagSize( aFunc ) );
+//fprintf( pTable, "%d ", Extra_ProfileWidthMax(DdNew, aFunc) );
+
+
+    // create the names to be used with the new manager
+    nNames = DdNew->size;
+    for ( x = 0; x < nNames; x++ )
+    {
+        sprintf( Buffer, "v%02d", x );
+        pNames[x] = Extra_UtilStrsav( Buffer );
+    }
+
+
+
+    // write the single-output function into BLIF for verification
+    clk1 = Abc_Clock();
+    WriteSingleOutputFunctionBlif( DdNew, aFunc, pNames, nNames, FileNameIni );
+    printf( "Single-output function writing time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+
+
+    ///////////////////////////////////////////////////////////////////
+    // verification of single output function
+    clk1 = Abc_Clock();
+    {
+        BFunc g_Func;
+        DdNode * aRes;
+
+        g_Func.dd = DdNew;
+        g_Func.FileInput = Extra_UtilStrsav(FileNameIni);
+
+        if ( Extra_ReadFile( &g_Func ) == 0 )
+        {
+            printf( "\nSomething did not work out while reading the input file for verification\n");
+            Extra_Dissolve( &g_Func );
+            return;
+        } 
+
+        aRes = Cudd_BddToAdd( DdNew, g_Func.pOutputs[0] );  Cudd_Ref( aRes );
+
+        if ( aRes != aFunc )
+            printf( "\nVerification FAILED!\n");
+        else
+            printf( "\nVerification okay!\n");
+        
+        Cudd_RecursiveDeref( DdNew, aRes );
+
+        // delocate
+        Extra_Dissolve( &g_Func );
+    }
+    printf( "Preliminary verification time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+    ///////////////////////////////////////////////////////////////////
+
+
+    CreateDecomposedNetwork( DdNew, aFunc, pNames, nNames, FileNameFin, nLutSize, 0 );
+
+/*
+    ///////////////////////////////////////////////////////////////////
+    // verification of the decomposed LUT network
+    clk1 = Abc_Clock();
+    {
+        BFunc g_Func;
+        DdNode * aRes;
+
+        g_Func.dd = DdNew;
+        g_Func.FileInput = Extra_UtilStrsav(FileNameFin);
+
+        if ( Extra_ReadFile( &g_Func ) == 0 )
+        {
+            printf( "\nSomething did not work out while reading the input file for verification\n");
+            Extra_Dissolve( &g_Func );
+            return;
+        } 
+
+        aRes = Cudd_BddToAdd( DdNew, g_Func.pOutputs[0] );  Cudd_Ref( aRes );
+
+        if ( aRes != aFunc )
+            printf( "\nFinal verification FAILED!\n");
+        else
+            printf( "\nFinal verification okay!\n");
+        
+        Cudd_RecursiveDeref( DdNew, aRes );
+
+        // delocate
+        Extra_Dissolve( &g_Func );
+    }
+    printf( "Final verification time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+    ///////////////////////////////////////////////////////////////////
+*/
+
+
+    Cudd_RecursiveDeref( DdNew, aFunc );
+
+    // release the names
+    for ( i = 0; i < nNames; i++ )
+        ABC_FREE( pNames[i] );
+
+
+    
+    /////////////////////////////////////////////////////////////////////
+    // check for remaining references in the package
+    RetValue = Cudd_CheckZeroRef( DdNew );
+    printf( "\nThe number of referenced nodes in the new manager = %d\n", RetValue );
+    Cudd_Quit( DdNew );
+
+//fprintf( pTable, "\n" );
+//fclose( pTable );
+
+} 
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       SINGLE OUTPUT FUNCTION                     ///
+////////////////////////////////////////////////////////////////////////
+
+// the bit count for the first 256 integer numbers
+//static unsigned char BitCount8[256] = {
+//    0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+//    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+//    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+//    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+//    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+//    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+//    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+//    3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+//};
+
+/////////////////////////////////////////////////////////////
+static int s_SuppSize[MAXOUTPUTS];
+int CompareSupports( int *ptrX, int *ptrY )
+{
+    return ( s_SuppSize[*ptrY] - s_SuppSize[*ptrX] );
+}
+/////////////////////////////////////////////////////////////
+
+ 
+/////////////////////////////////////////////////////////////
+static int s_MintOnes[MAXOUTPUTS];
+int CompareMinterms( int *ptrX, int *ptrY )
+{
+    return ( s_MintOnes[*ptrY] - s_MintOnes[*ptrX] );
+}
+/////////////////////////////////////////////////////////////
+
+int GrayCode ( int BinCode )
+{ 
+  return BinCode ^ ( BinCode >> 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc, int fVerbose )
+{
+    int i;
+    DdNode * bResult, * aResult;
+    DdNode * bCube, * bTemp, * bProd;
+
+    int Order[MAXOUTPUTS];
+//  int OrderMint[MAXOUTPUTS];
+ 
+    // sort the output according to their support size
+    for ( i = 0; i < nOuts; i++ )
+    {
+        s_SuppSize[i] = Cudd_SupportSize( dd, pbOuts[i] );
+//      s_MintOnes[i] = BitCount8[i];
+        Order[i]      = i;
+//      OrderMint[i]  = i;
+    }
+    
+    // order the outputs
+    qsort( (void*)Order,     nOuts, sizeof(int), (int(*)(const void*, const void*)) CompareSupports );
+    // order the outputs
+//  qsort( (void*)OrderMint, nOuts, sizeof(int), (int(*)(const void*, const void*)) CompareMinterms );
+
+
+    bResult = b0;   Cudd_Ref( bResult );
+    for ( i = 0; i < nOuts; i++ )
+    {
+//      bCube   = Cudd_bddBitsToCube( dd, OrderMint[i], nVarsEnc, pbVarsEnc );   Cudd_Ref( bCube );
+//      bProd   = Cudd_bddAnd( dd, bCube, pbOuts[Order[nOuts-1-i]] );         Cudd_Ref( bProd );
+        bCube   = Extra_bddBitsToCube( dd, i, nVarsEnc, pbVarsEnc, 1 );   Cudd_Ref( bCube );
+        bProd   = Cudd_bddAnd( dd, bCube, pbOuts[Order[i]] );         Cudd_Ref( bProd );
+        Cudd_RecursiveDeref( dd, bCube );
+
+        bResult = Cudd_bddOr( dd, bProd, bTemp = bResult );           Cudd_Ref( bResult );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bProd );
+    }
+
+    // convert to the ADD
+if ( fVerbose )
+printf( "Single BDD size = %6d nodes\n", Cudd_DagSize(bResult) );
+    aResult = Cudd_BddToAdd( dd, bResult );  Cudd_Ref( aResult );
+    Cudd_RecursiveDeref( dd, bResult );
+if ( fVerbose )
+printf( "MTBDD           = %6d nodes\n", Cudd_DagSize(aResult) );
+    Cudd_Deref( aResult );
+    return aResult;
+}
+/*
+DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc )
+{
+    int i;
+    DdNode * bResult, * aResult;
+    DdNode * bCube, * bTemp, * bProd;
+
+    bResult = b0;   Cudd_Ref( bResult );
+    for ( i = 0; i < nOuts; i++ )
+    {
+//      bCube   = Extra_bddBitsToCube( dd, i, nVarsEnc, pbVarsEnc );   Cudd_Ref( bCube );
+        bCube   = Extra_bddBitsToCube( dd, nOuts-1-i, nVarsEnc, pbVarsEnc );   Cudd_Ref( bCube );
+        bProd   = Cudd_bddAnd( dd, bCube, pbOuts[i] );                Cudd_Ref( bProd );
+        Cudd_RecursiveDeref( dd, bCube );
+
+        bResult = Cudd_bddOr( dd, bProd, bTemp = bResult );           Cudd_Ref( bResult );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bProd );
+    }
+
+    // conver to the ADD
+    aResult = Cudd_BddToAdd( dd, bResult );  Cudd_Ref( aResult );
+    Cudd_RecursiveDeref( dd, bResult );
+
+    Cudd_Deref( aResult );
+    return aResult;
+}
+*/
+
+
+////////////////////////////////////////////////////////////////////////
+///                        INPUT REMAPPING                           ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * GetSingleOutputFunctionRemapped( DdManager * dd, DdNode ** pOutputs, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc )
+// returns the ADD of the remapped function
+{
+    static int Permute[MAXINPUTS];
+    static DdNode * pRemapped[MAXOUTPUTS];
+
+    DdNode * bSupp, * bTemp;
+    int i, Counter;
+    DdNode * bFunc;
+    DdNode * aFunc;
+
+    Cudd_AutodynDisable(dd);
+
+    // perform the remapping
+    for ( i = 0; i < nOuts; i++ )
+    {
+        // get support
+        bSupp = Cudd_Support( dd, pOutputs[i] );    Cudd_Ref( bSupp );
+
+        // create the variable map
+        Counter = 0;
+        for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) )
+            Permute[bTemp->index] = Counter++;
+
+        // transfer the BDD and remap it
+        pRemapped[i] = Cudd_bddPermute( dd, pOutputs[i], Permute );  Cudd_Ref( pRemapped[i] );
+
+        // remove support
+        Cudd_RecursiveDeref( dd, bSupp );
+    }
+    
+    // perform the encoding
+    bFunc = Extra_bddEncodingBinary( dd, pRemapped, nOuts, pbVarsEnc, nVarsEnc );   Cudd_Ref( bFunc );
+
+    // convert to ADD
+    aFunc = Cudd_BddToAdd( dd, bFunc );  Cudd_Ref( aFunc );
+    Cudd_RecursiveDeref( dd, bFunc );
+
+    // deref the intermediate results
+    for ( i = 0; i < nOuts; i++ )
+        Cudd_RecursiveDeref( dd, pRemapped[i] );
+
+    Cudd_Deref( aFunc );
+    return aFunc;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * GetSingleOutputFunctionRemappedNewDD( DdManager * dd, DdNode ** pOutputs, int nOuts, DdManager ** DdNew )
+// returns the ADD of the remapped function
+{
+    static int Permute[MAXINPUTS];
+    static DdNode * pRemapped[MAXOUTPUTS];
+
+    static DdNode * pbVarsEnc[MAXINPUTS];
+    int nVarsEnc;
+
+    DdManager * ddnew;
+
+    DdNode * bSupp, * bTemp;
+    int i, v, Counter;
+    DdNode * bFunc;
+
+    // these are in the new manager
+    DdNode * bFuncNew;
+    DdNode * aFuncNew;
+
+    int nVarsMax = 0;
+
+    // perform the remapping and write the DDs into the new manager
+    for ( i = 0; i < nOuts; i++ )
+    {
+        // get support
+        bSupp = Cudd_Support( dd, pOutputs[i] );    Cudd_Ref( bSupp );
+
+        // create the variable map
+        // to remap the DD into the upper part of the manager
+        Counter = 0;
+        for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) )
+            Permute[bTemp->index] = dd->invperm[Counter++];
+
+        // transfer the BDD and remap it
+        pRemapped[i] = Cudd_bddPermute( dd, pOutputs[i], Permute );  Cudd_Ref( pRemapped[i] );
+
+        // remove support
+        Cudd_RecursiveDeref( dd, bSupp );
+
+
+        // determine the largest support size
+        if ( nVarsMax < Counter )
+            nVarsMax = Counter;
+    }
+    
+    // select the encoding variables to follow immediately after the original variables
+    nVarsEnc = Abc_Base2Log(nOuts);
+/*
+    for ( v = 0; v < nVarsEnc; v++ )
+        if ( nVarsMax + v < dd->size )
+            pbVarsEnc[v] = dd->var[ dd->invperm[nVarsMax+v] ];
+        else
+            pbVarsEnc[v] = Cudd_bddNewVar( dd );
+*/
+    // create the new variables on top of the manager
+    for ( v = 0; v < nVarsEnc; v++ )
+        pbVarsEnc[v] = Cudd_bddNewVarAtLevel( dd, v );
+
+//fprintf( pTable, "%d ", Cudd_SharingSize( pRemapped, nOuts ) );
+//fprintf( pTable, "%d ", Extra_ProfileWidthSharingMax(dd, pRemapped, nOuts) );
+
+
+    // perform the encoding
+    bFunc = Extra_bddEncodingBinary( dd, pRemapped, nOuts, pbVarsEnc, nVarsEnc );   Cudd_Ref( bFunc );
+
+
+    // find the cross-manager permutation
+    // the variable from the level v in the old manager 
+    // should become a variable number v in the new manager
+    for ( v = 0; v < nVarsMax + nVarsEnc; v++ )
+        Permute[dd->invperm[v]] = v;
+
+
+    ///////////////////////////////////////////////////////////////////////////////
+    // start the new manager
+    ddnew = Cudd_Init( nVarsMax + nVarsEnc, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0);
+//  Cudd_AutodynDisable(ddnew);
+    Cudd_AutodynEnable(dd, CUDD_REORDER_SYMM_SIFT);
+
+    // transfer it to the new manager
+    bFuncNew = Cudd_bddTransferPermute( dd, ddnew, bFunc, Permute );      Cudd_Ref( bFuncNew );
+    ///////////////////////////////////////////////////////////////////////////////
+
+
+    // deref the intermediate results in the old manager
+    Cudd_RecursiveDeref( dd, bFunc );
+    for ( i = 0; i < nOuts; i++ )
+        Cudd_RecursiveDeref( dd, pRemapped[i] );
+
+
+    ///////////////////////////////////////////////////////////////////////////////
+    // convert to ADD in the new manager
+    aFuncNew = Cudd_BddToAdd( ddnew, bFuncNew );  Cudd_Ref( aFuncNew );
+    Cudd_RecursiveDeref( ddnew, bFuncNew );
+
+    // return the manager
+    *DdNew = ddnew;
+    ///////////////////////////////////////////////////////////////////////////////
+
+    Cudd_Deref( aFuncNew );
+    return aFuncNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                        BLIF WRITING FUNCTIONS                    ///
+////////////////////////////////////////////////////////////////////////
+
+void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames );
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void WriteSingleOutputFunctionBlif( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName )
+{
+    int i;
+    FILE * pFile;
+
+    // start the file
+    pFile = fopen( FileName, "w" );
+    fprintf( pFile, ".model %s\n", FileName );
+
+    fprintf( pFile, ".inputs" );
+    for ( i = 0; i < nNames; i++ )
+        fprintf( pFile, " %s", pNames[i] );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, ".outputs F" );
+    fprintf( pFile, "\n" );
+
+    // write the DD into the file
+    WriteDDintoBLIFfile( pFile, aFunc, "F", "", pNames );
+
+    fprintf( pFile, ".end\n" );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames )
+// writes the main part of the BLIF file 
+// Func is a BDD or a 0-1 ADD to be written
+// OutputName is the name of the output
+// Prefix is attached to each intermendiate signal to make it unique
+// InputNames are the names of the input signals
+// (some part of the code is borrowed from Cudd_DumpDot())
+{
+    int i;
+    st__table * visited;
+    st__generator * gen = NULL;
+    long refAddr, diff, mask;
+    DdNode * Node, * Else, * ElseR, * Then;
+
+    /* Initialize symbol table for visited nodes. */
+    visited = st__init_table( st__ptrcmp, st__ptrhash );
+
+    /* Collect all the nodes of this DD in the symbol table. */
+    cuddCollectNodes( Cudd_Regular(Func), visited );
+
+    /* Find how many most significant hex digits are identical
+       ** in the addresses of all the nodes. Build a mask based
+       ** on this knowledge, so that digits that carry no information
+       ** will not be printed. This is done in two steps.
+       **  1. We scan the symbol table to find the bits that differ
+       **     in at least 2 addresses.
+       **  2. We choose one of the possible masks. There are 8 possible
+       **     masks for 32-bit integer, and 16 possible masks for 64-bit
+       **     integers.
+     */
+
+    /* Find the bits that are different. */
+    refAddr = ( long )Cudd_Regular(Func);
+    diff = 0;
+    gen = st__init_gen( visited );
+    while ( st__gen( gen, ( const char ** ) &Node, NULL ) )
+    {
+        diff |= refAddr ^ ( long ) Node;
+    }
+    st__free_gen( gen );
+    gen = NULL;
+
+    /* Choose the mask. */
+    for ( i = 0; ( unsigned ) i < 8 * sizeof( long ); i += 4 )
+    {
+        mask = ( 1 << i ) - 1;
+        if ( diff <= mask )
+            break;
+    }
+
+
+    // write the buffer for the output
+    fprintf( pFile, ".names %s%lx %s\n", Prefix, ( mask & (long)Cudd_Regular(Func) ) / sizeof(DdNode), OutputName ); 
+    fprintf( pFile, "%s 1\n", (Cudd_IsComplement(Func))? "0": "1" );
+
+
+    gen = st__init_gen( visited );
+    while ( st__gen( gen, ( const char ** ) &Node, NULL ) )
+    {
+        if ( Node->index == CUDD_MAXINDEX )
+        {
+            // write the terminal node
+            fprintf( pFile, ".names %s%lx\n", Prefix, ( mask & (long)Node ) / sizeof(DdNode) );
+            fprintf( pFile, " %s\n", (cuddV(Node) == 0.0)? "0": "1" );
+            continue;
+        }
+
+        Else  = cuddE(Node);
+        ElseR = Cudd_Regular(Else);
+        Then  = cuddT(Node);
+
+        assert( InputNames[Node->index] );
+        if ( Else == ElseR )
+        { // no inverter
+            fprintf( pFile, ".names %s %s%lx %s%lx %s%lx\n", InputNames[Node->index],                           
+                              Prefix, ( mask & (long)ElseR ) / sizeof(DdNode),
+                              Prefix, ( mask & (long)Then  ) / sizeof(DdNode),
+                              Prefix, ( mask & (long)Node  ) / sizeof(DdNode)   );
+            fprintf( pFile, "01- 1\n" );
+            fprintf( pFile, "1-1 1\n" );
+        }
+        else
+        { // inverter
+            int * pSlot;
+            fprintf( pFile, ".names %s %s%lx_i %s%lx %s%lx\n", InputNames[Node->index],                         
+                              Prefix, ( mask & (long)ElseR ) / sizeof(DdNode),
+                              Prefix, ( mask & (long)Then  ) / sizeof(DdNode),
+                              Prefix, ( mask & (long)Node  ) / sizeof(DdNode)   );
+            fprintf( pFile, "01- 1\n" );
+            fprintf( pFile, "1-1 1\n" );
+
+            // if the inverter is written, skip
+            if ( ! st__find( visited, (char *)ElseR, (char ***)&pSlot ) )
+                assert( 0 );
+            if ( *pSlot )
+                continue;
+            *pSlot = 1;
+
+            fprintf( pFile, ".names %s%lx %s%lx_i\n",  
+                              Prefix, ( mask & (long)ElseR  ) / sizeof(DdNode),
+                              Prefix, ( mask & (long)ElseR  ) / sizeof(DdNode)   );
+            fprintf( pFile, "0 1\n" );
+        }
+    }
+    st__free_gen( gen );
+    gen = NULL;
+    st__free_table( visited );
+}
+
+
+
+
+static DdManager * s_ddmin;
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void WriteDDintoBLIFfileReorder( DdManager * dd, FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames )
+// writes the main part of the BLIF file 
+// Func is a BDD or a 0-1 ADD to be written
+// OutputName is the name of the output
+// Prefix is attached to each intermendiate signal to make it unique
+// InputNames are the names of the input signals
+// (some part of the code is borrowed from Cudd_DumpDot())
+{
+    int i;
+    st__table * visited;
+    st__generator * gen = NULL;
+    long refAddr, diff, mask;
+    DdNode * Node, * Else, * ElseR, * Then;
+
+
+    ///////////////////////////////////////////////////////////////
+    DdNode * bFmin;
+    abctime clk1;
+
+    if ( s_ddmin == NULL )
+        s_ddmin = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0);
+
+    clk1 = Abc_Clock();
+    bFmin = Cudd_bddTransfer( dd, s_ddmin, Func );  Cudd_Ref( bFmin );
+
+    // reorder
+    printf( "Nodes before = %d.   ", Cudd_DagSize(bFmin) ); 
+    Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT,1);
+//  Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT_CONV,1);
+    printf( "Nodes after  = %d.  \n", Cudd_DagSize(bFmin) ); 
+    ///////////////////////////////////////////////////////////////
+
+
+
+    /* Initialize symbol table for visited nodes. */
+    visited = st__init_table( st__ptrcmp, st__ptrhash );
+
+    /* Collect all the nodes of this DD in the symbol table. */
+    cuddCollectNodes( Cudd_Regular(bFmin), visited );
+
+    /* Find how many most significant hex digits are identical
+       ** in the addresses of all the nodes. Build a mask based
+       ** on this knowledge, so that digits that carry no information
+       ** will not be printed. This is done in two steps.
+       **  1. We scan the symbol table to find the bits that differ
+       **     in at least 2 addresses.
+       **  2. We choose one of the possible masks. There are 8 possible
+       **     masks for 32-bit integer, and 16 possible masks for 64-bit
+       **     integers.
+     */
+
+    /* Find the bits that are different. */
+    refAddr = ( long )Cudd_Regular(bFmin);
+    diff = 0;
+    gen = st__init_gen( visited );
+    while ( st__gen( gen, ( const char ** ) &Node, NULL ) )
+    {
+        diff |= refAddr ^ ( long ) Node;
+    }
+    st__free_gen( gen );
+    gen = NULL;
+
+    /* Choose the mask. */
+    for ( i = 0; ( unsigned ) i < 8 * sizeof( long ); i += 4 )
+    {
+        mask = ( 1 << i ) - 1;
+        if ( diff <= mask )
+            break;
+    }
+
+
+    // write the buffer for the output
+    fprintf( pFile, ".names %s%lx %s\n", Prefix, ( mask & (long)Cudd_Regular(bFmin) ) / sizeof(DdNode), OutputName ); 
+    fprintf( pFile, "%s 1\n", (Cudd_IsComplement(bFmin))? "0": "1" );
+
+
+    gen = st__init_gen( visited );
+    while ( st__gen( gen, ( const char ** ) &Node, NULL ) )
+    {
+        if ( Node->index == CUDD_MAXINDEX )
+        {
+            // write the terminal node
+            fprintf( pFile, ".names %s%lx\n", Prefix, ( mask & (long)Node ) / sizeof(DdNode) );
+            fprintf( pFile, " %s\n", (cuddV(Node) == 0.0)? "0": "1" );
+            continue;
+        }
+
+        Else  = cuddE(Node);
+        ElseR = Cudd_Regular(Else);
+        Then  = cuddT(Node);
+
+        assert( InputNames[Node->index] );
+        if ( Else == ElseR )
+        { // no inverter
+            fprintf( pFile, ".names %s %s%lx %s%lx %s%lx\n", InputNames[Node->index],                           
+                              Prefix, ( mask & (long)ElseR ) / sizeof(DdNode),
+                              Prefix, ( mask & (long)Then  ) / sizeof(DdNode),
+                              Prefix, ( mask & (long)Node  ) / sizeof(DdNode)   );
+            fprintf( pFile, "01- 1\n" );
+            fprintf( pFile, "1-1 1\n" );
+        }
+        else
+        { // inverter
+            fprintf( pFile, ".names %s %s%lx_i %s%lx %s%lx\n", InputNames[Node->index],                         
+                              Prefix, ( mask & (long)ElseR ) / sizeof(DdNode),
+                              Prefix, ( mask & (long)Then  ) / sizeof(DdNode),
+                              Prefix, ( mask & (long)Node  ) / sizeof(DdNode)   );
+            fprintf( pFile, "01- 1\n" );
+            fprintf( pFile, "1-1 1\n" );
+
+            fprintf( pFile, ".names %s%lx %s%lx_i\n",  
+                              Prefix, ( mask & (long)ElseR  ) / sizeof(DdNode),
+                              Prefix, ( mask & (long)ElseR  ) / sizeof(DdNode)   );
+            fprintf( pFile, "0 1\n" );
+        }
+    }
+    st__free_gen( gen );
+    gen = NULL;
+    st__free_table( visited );
+
+
+    //////////////////////////////////////////////////
+    Cudd_RecursiveDeref( s_ddmin, bFmin );
+    //////////////////////////////////////////////////
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                    TRANSFER WITH MAPPING                         ///
+////////////////////////////////////////////////////////////////////////
+static DdNode * cuddBddTransferPermuteRecur
+ARGS((DdManager * ddS, DdManager * ddD, DdNode * f, st__table * table, int * Permute ));
+
+static DdNode * cuddBddTransferPermute
+ARGS((DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute));
+
+/**Function********************************************************************
+
+  Synopsis    [Convert a BDD from a manager to another one.]
+
+  Description [Convert a BDD from a manager to another one. The orders of the
+  variables in the two managers may be different. Returns a
+  pointer to the BDD in the destination manager if successful; NULL
+  otherwise. The i-th entry in the array Permute tells what is the index
+  of the i-th variable from the old manager in the new manager.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_bddTransferPermute( DdManager * ddSource,
+                  DdManager * ddDestination, DdNode * f, int * Permute )
+{
+    DdNode *res;
+    do
+    {
+        ddDestination->reordered = 0;
+        res = cuddBddTransferPermute( ddSource, ddDestination, f, Permute );
+    }
+    while ( ddDestination->reordered == 1 );
+    return ( res );
+
+}                               /* end of Cudd_bddTransferPermute */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Convert a BDD from a manager to another one.]
+
+  Description [Convert a BDD from a manager to another one. Returns a
+  pointer to the BDD in the destination manager if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddTransferPermute]
+
+******************************************************************************/
+DdNode *
+cuddBddTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute )
+{
+    DdNode *res;
+    st__table *table = NULL;
+    st__generator *gen = NULL;
+    DdNode *key, *value;
+
+    table = st__init_table( st__ptrcmp, st__ptrhash );
+    if ( table == NULL )
+        goto failure;
+    res = cuddBddTransferPermuteRecur( ddS, ddD, f, table, Permute );
+    if ( res != NULL )
+        cuddRef( res );
+
+    /* Dereference all elements in the table and dispose of the table.
+       ** This must be done also if res is NULL to avoid leaks in case of
+       ** reordering. */
+    gen = st__init_gen( table );
+    if ( gen == NULL )
+        goto failure;
+    while ( st__gen( gen, ( const char ** ) &key, ( char ** ) &value ) )
+    {
+        Cudd_RecursiveDeref( ddD, value );
+    }
+    st__free_gen( gen );
+    gen = NULL;
+    st__free_table( table );
+    table = NULL;
+
+    if ( res != NULL )
+        cuddDeref( res );
+    return ( res );
+
+  failure:
+    if ( table != NULL )
+        st__free_table( table );
+    if ( gen != NULL )
+        st__free_gen( gen );
+    return ( NULL );
+
+}                               /* end of cuddBddTransferPermute */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddTransferPermute.]
+
+  Description [Performs the recursive step of Cudd_bddTransferPermute.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddBddTransferPermute]
+
+******************************************************************************/
+static DdNode *
+cuddBddTransferPermuteRecur( DdManager * ddS,
+                      DdManager * ddD, DdNode * f, st__table * table, int * Permute )
+{
+    DdNode *ft, *fe, *t, *e, *var, *res;
+    DdNode *one, *zero;
+    int index;
+    int comple = 0;
+
+    statLine( ddD );
+    one = DD_ONE( ddD );
+    comple = Cudd_IsComplement( f );
+
+    /* Trivial cases. */
+    if ( Cudd_IsConstant( f ) )
+        return ( Cudd_NotCond( one, comple ) );
+
+    /* Make canonical to increase the utilization of the cache. */
+    f = Cudd_NotCond( f, comple );
+    /* Now f is a regular pointer to a non-constant node. */
+
+    /* Check the cache. */
+    if ( st__lookup( table, ( char * ) f, ( char ** ) &res ) )
+        return ( Cudd_NotCond( res, comple ) );
+
+    /* Recursive step. */
+    index = Permute[f->index];
+    ft = cuddT( f );
+    fe = cuddE( f );
+
+    t = cuddBddTransferPermuteRecur( ddS, ddD, ft, table, Permute );
+    if ( t == NULL )
+    {
+        return ( NULL );
+    }
+    cuddRef( t );
+
+    e = cuddBddTransferPermuteRecur( ddS, ddD, fe, table, Permute );
+    if ( e == NULL )
+    {
+        Cudd_RecursiveDeref( ddD, t );
+        return ( NULL );
+    }
+    cuddRef( e );
+
+    zero = Cudd_Not( one );
+    var = cuddUniqueInter( ddD, index, one, zero );
+    if ( var == NULL )
+    {
+        Cudd_RecursiveDeref( ddD, t );
+        Cudd_RecursiveDeref( ddD, e );
+        return ( NULL );
+    }
+    res = cuddBddIteRecur( ddD, var, t, e );
+    if ( res == NULL )
+    {
+        Cudd_RecursiveDeref( ddD, t );
+        Cudd_RecursiveDeref( ddD, e );
+        return ( NULL );
+    }
+    cuddRef( res );
+    Cudd_RecursiveDeref( ddD, t );
+    Cudd_RecursiveDeref( ddD, e );
+
+    if ( st__add_direct( table, ( char * ) f, ( char * ) res ) ==
+         st__OUT_OF_MEM )
+    {
+        Cudd_RecursiveDeref( ddD, res );
+        return ( NULL );
+    }
+    return ( Cudd_NotCond( res, comple ) );
+
+}                               /* end of cuddBddTransferPermuteRecur */
+
+////////////////////////////////////////////////////////////////////////
+///                           END OF FILE                            ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cas/casDec.c b/abc-build/src/bdd/cas/casDec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cas/casDec.c
@@ -0,0 +1,512 @@
+/**CFile****************************************************************
+
+  FileName    [casDec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.]
+
+  Synopsis    [BDD-based decomposition with encoding.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Spring 2002.]
+
+  Revision    [$Id: casDec.c,v 1.0 2002/01/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "misc/extra/extraBdd.h"
+#include "cas.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                      type definitions                            ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct
+{
+    int nIns;                // the number of LUT variables
+    int nInsP;               // the number of inputs coming from the previous LUT
+    int nCols;               // the number of columns in this LUT
+    int nMulti;              // the column multiplicity, [log2(nCols)]
+    int nSimple;             // the number of outputs implemented as direct connections to inputs of the previous block
+    int Level;               // the starting level in the ADD in this LUT
+
+//  DdNode ** pbVarsIn[32];  // the BDDs of the elementary input variables
+//  DdNode ** pbVarsOut[32]; // the BDDs of the elementary output variables 
+
+//  char * pNamesIn[32];     // the names of input variables
+//  char * pNamesOut[32];    // the names of output variables
+
+    DdNode ** pbCols;        // the array of columns represented by BDDs
+    DdNode ** pbCodes;       // the array of codes (in terms of pbVarsOut)
+    DdNode ** paNodes;       // the array of starting ADD nodes on the next level (also referenced)
+
+    DdNode * bRelation;      // the relation after encoding
+
+    // the relation depends on the three groups of variables:
+    // (1) variables on top represent the outputs of the previous cascade
+    // (2) variables in the middle represent the primary inputs
+    // (3) variables below (CVars) represent the codes
+    //
+    // the replacement is done after computing the relation
+} LUT;
+
+
+////////////////////////////////////////////////////////////////////////
+///                      static functions                            ///
+////////////////////////////////////////////////////////////////////////
+
+// the LUT-2-BLIF writing function
+void WriteLUTSintoBLIFfile( FILE * pFile, DdManager * dd, LUT ** pLuts, int nLuts, DdNode ** bCVars, char ** pNames, int nNames, char * FileName );
+
+// the function to write a DD (BDD or ADD) as a network of MUXES
+extern void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames );
+extern void WriteDDintoBLIFfileReorder( DdManager * dd, FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames );
+
+////////////////////////////////////////////////////////////////////////
+///                      static varibles                             ///
+////////////////////////////////////////////////////////////////////////
+
+static int s_LutSize = 15;
+static int s_nFuncVars; 
+
+long s_EncodingTime;
+
+long s_EncSearchTime;
+long s_EncComputeTime;
+
+////////////////////////////////////
+// temporary output variables
+//FILE * pTable;
+//long s_ReadingTime;
+//long s_RemappingTime;
+////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      debugging macros                            ///
+////////////////////////////////////////////////////////////////////////
+
+#define PRB_(f)       printf( #f " = " ); Cudd_bddPrint(dd,f); printf( "\n" )
+#define PRK(f,n)     Cudd_PrintKMap(stdout,dd,(f),Cudd_Not(f),(n),NULL,0); printf( "K-map for function" #f "\n\n" )
+#define PRK2(f,g,n)  Cudd_PrintKMap(stdout,dd,(f),(g),(n),NULL,0); printf( "K-map for function <" #f ", " #g ">\n\n" ) 
+
+
+////////////////////////////////////////////////////////////////////////
+///                     EXTERNAL FUNCTIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+int CreateDecomposedNetwork( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName, int nLutSize, int fCheck, int fVerbose )
+// aFunc is a 0-1 ADD for the given function
+// pNames (nNames) are the input variable names
+// FileName is the name of the output file for the LUT network
+// dynamic variable reordering should be disabled when this function is running
+{
+    static LUT * pLuts[MAXINPUTS];   // the LUT cascade
+    static int Profile[MAXINPUTS];   // the profile filled in with the info about the BDD width
+    static int Permute[MAXINPUTS];   // the array to store a temporary permutation of variables
+
+    LUT * p;               // the current LUT
+    int i, v;
+
+    DdNode * bCVars[32];   // these are variables for the codes
+
+    int nVarsRem;          // the number of remaining variables
+    int PrevMulti;         // column multiplicity on the previous level
+    int fLastLut;          // flag to signal the last LUT
+    int nLuts;
+    int nLutsTotal = 0;
+    int nLutOutputs = 0;
+    int nLutOutputsOrig = 0;
+
+    abctime clk1;
+
+    s_LutSize = nLutSize;
+
+    s_nFuncVars = nNames;
+
+    // get the profile
+    clk1 = Abc_Clock();
+    Extra_ProfileWidth( dd, aFunc, Profile, -1 );
+
+
+//  for ( v = 0; v < nNames; v++ )
+//      printf( "Level = %2d, Width = %2d\n", v+1, Profile[v] );
+
+
+//printf( "\n" );
+
+    // mark-up the LUTs
+    // assuming that the manager has exactly nNames vars (new vars have not been introduced yet)
+    nVarsRem  = nNames;     // the number of remaining variables
+    PrevMulti = 0;          // column multiplicity on the previous level
+    fLastLut  = 0;
+    nLuts     = 0;
+    do
+    {
+        p = (LUT*) ABC_ALLOC( char, sizeof(LUT) );
+        memset( p, 0, sizeof(LUT) );
+
+        if ( nVarsRem + PrevMulti <= s_LutSize ) // this is the last LUT
+        {
+            p->nIns   = nVarsRem + PrevMulti;
+            p->nInsP  = PrevMulti;
+            p->nCols  = 2;
+            p->nMulti = 1;
+            p->Level  = nNames-nVarsRem;
+
+            nVarsRem  = 0;
+            PrevMulti = 1;
+
+            fLastLut  = 1;
+        }
+        else // this is not the last LUT
+        {
+            p->nIns   = s_LutSize;
+            p->nInsP  = PrevMulti;
+            p->nCols  = Profile[nNames-(nVarsRem-(s_LutSize-PrevMulti))];
+            p->nMulti = Abc_Base2Log(p->nCols);
+            p->Level  = nNames-nVarsRem;
+
+            nVarsRem  = nVarsRem-(s_LutSize-PrevMulti);
+            PrevMulti = p->nMulti;
+        }
+        
+        if ( p->nMulti >= s_LutSize )
+        {
+            printf( "The LUT size is too small\n" );
+            return 0;
+        }
+
+        nLutOutputsOrig += p->nMulti;
+
+
+//if ( fVerbose )
+//printf( "Stage %2d: In = %3d, InP = %3d, Cols = %5d, Multi = %2d, Level = %2d\n", 
+//       nLuts+1, p->nIns, p->nInsP, p->nCols, p->nMulti, p->Level );
+
+
+        // there should be as many columns, codes, and nodes, as there are columns on this level
+        p->pbCols  = (DdNode **) ABC_ALLOC( char, p->nCols * sizeof(DdNode *) );
+        p->pbCodes = (DdNode **) ABC_ALLOC( char, p->nCols * sizeof(DdNode *) );
+        p->paNodes = (DdNode **) ABC_ALLOC( char, p->nCols * sizeof(DdNode *) );
+
+        pLuts[nLuts] = p;
+        nLuts++;
+    }
+    while ( !fLastLut );
+
+
+//if ( fVerbose )
+//printf( "The number of cascades = %d\n", nLuts );
+
+
+//fprintf( pTable, "%d ", nLuts );
+
+
+    // add the new variables at the bottom
+    for ( i = 0; i < s_LutSize; i++ )
+        bCVars[i] = Cudd_bddNewVar(dd);
+
+    // for each LUT - assign the LUT and encode the columns
+    s_EncodingTime = 0;
+    for ( i = 0; i < nLuts; i++ )
+    {
+        int RetValue;
+        DdNode * bVars[32];    
+        int nVars;
+        DdNode * bVarsInCube;
+        DdNode * bVarsCCube;
+        DdNode * bVarsCube;
+        int CutLevel;
+
+        p = pLuts[i];
+
+        // compute the columns of this LUT starting from the given set of nodes with the given codes
+        // (these codes have been remapped to depend on the topmost variables in the manager)
+        // for the first LUT, start with the constant 1 BDD
+        CutLevel = p->Level + p->nIns - p->nInsP;
+        if ( i == 0 )
+            RetValue = Extra_bddNodePathsUnderCutArray( 
+                            dd, &aFunc, &(b1), 1, 
+                            p->paNodes, p->pbCols, CutLevel );
+        else
+            RetValue = Extra_bddNodePathsUnderCutArray( 
+                            dd, pLuts[i-1]->paNodes, pLuts[i-1]->pbCodes, pLuts[i-1]->nCols, 
+                            p->paNodes, p->pbCols, CutLevel );
+        assert( RetValue == p->nCols );
+        // at this point, we have filled out p->paNodes[] and p->pbCols[] of this LUT
+        // pLuts[i-1]->paNodes depended on normal vars
+        // pLuts[i-1]->pbCodes depended on the topmost variables 
+        // the resulting p->paNodes depend on normal ADD nodes
+        // the resulting p->pbCols depend on normal vars and topmost variables in the manager
+
+        // perform the encoding
+
+        // create the cube of these variables
+        // collect the topmost variables of the manager
+        nVars = p->nInsP;
+        for ( v = 0; v < nVars; v++ )
+            bVars[v] = dd->vars[ dd->invperm[v] ];
+        bVarsCCube  = Extra_bddBitsToCube( dd, (1<<nVars)-1, nVars, bVars, 1 );    Cudd_Ref( bVarsCCube );
+
+        // collect the primary input variables involved in this LUT
+        nVars = p->nIns - p->nInsP;
+        for ( v = 0; v < nVars; v++ )
+            bVars[v] = dd->vars[ dd->invperm[p->Level+v] ];
+        bVarsInCube = Extra_bddBitsToCube( dd, (1<<nVars)-1, nVars, bVars, 1 );    Cudd_Ref( bVarsInCube );
+
+        // get the cube
+        bVarsCube   = Cudd_bddAnd( dd, bVarsInCube, bVarsCCube );              Cudd_Ref( bVarsCube );
+        Cudd_RecursiveDeref( dd, bVarsInCube );
+        Cudd_RecursiveDeref( dd, bVarsCCube );
+
+        // get the encoding relation
+        if ( i == nLuts -1 )
+        {
+            DdNode * bVar;
+            assert( p->nMulti == 1 );
+            assert( p->nCols == 2 );
+            assert( Cudd_IsConstant( p->paNodes[0] ) );
+            assert( Cudd_IsConstant( p->paNodes[1] ) );
+
+            bVar = ( p->paNodes[0] == a1 )? bCVars[0]: Cudd_Not( bCVars[0] );
+            p->bRelation = Cudd_bddIte( dd, bVar, p->pbCols[0], p->pbCols[1] );  Cudd_Ref( p->bRelation );
+        }
+        else
+        {
+            abctime clk2 = Abc_Clock();
+//          p->bRelation = PerformTheEncoding( dd, p->pbCols, p->nCols, bVarsCube, bCVars, p->nMulti, &p->nSimple );  Cudd_Ref( p->bRelation );
+            p->bRelation = Extra_bddEncodingNonStrict( dd, p->pbCols, p->nCols, bVarsCube, bCVars, p->nMulti, &p->nSimple );  Cudd_Ref( p->bRelation );
+            s_EncodingTime += Abc_Clock() - clk2;
+        }
+
+        // update the number of LUT outputs
+        nLutOutputs += (p->nMulti - p->nSimple);
+        nLutsTotal += p->nMulti;
+
+//if ( fVerbose )
+//printf( "Stage %2d: Simple = %d\n", i+1, p->nSimple );
+
+if ( fVerbose )
+printf( "Stage %3d: In = %3d  InP = %3d  Cols = %5d  Multi = %2d  Simple = %2d  Level = %3d\n", 
+       i+1, p->nIns, p->nInsP, p->nCols, p->nMulti, p->nSimple, p->Level );
+
+        // get the codes from the relation (these are not necessarily cubes)
+        {
+            int c;
+            for ( c = 0; c < p->nCols; c++ )
+            {
+                p->pbCodes[c] = Cudd_bddAndAbstract( dd, p->bRelation, p->pbCols[c], bVarsCube ); Cudd_Ref( p->pbCodes[c] );
+            }
+        }
+
+        Cudd_RecursiveDeref( dd, bVarsCube );
+
+        // remap the codes to depend on the topmost varibles of the manager
+        // useful as a preparation for the next step
+        {
+            DdNode ** pbTemp;
+            int k, v;
+
+            pbTemp = (DdNode **) ABC_ALLOC( char, p->nCols * sizeof(DdNode *) );
+
+            // create the identical permutation
+            for ( v = 0; v < dd->size; v++ )
+                Permute[v] = v;
+
+            // use the topmost variables of the manager 
+            // to represent the previous level codes
+            for ( v = 0; v < p->nMulti; v++ )
+                Permute[bCVars[v]->index] = dd->invperm[v];
+
+            Extra_bddPermuteArray( dd, p->pbCodes, pbTemp, p->nCols, Permute );
+            // the array pbTemp comes already referenced
+
+            // deref the old codes and assign the new ones
+            for ( k = 0; k < p->nCols; k++ )
+            {
+                Cudd_RecursiveDeref( dd, p->pbCodes[k] );
+                p->pbCodes[k] = pbTemp[k];
+            }
+            ABC_FREE( pbTemp );
+        }
+    } 
+    if ( fVerbose )
+    printf( "LUTs: Total = %5d. Final = %5d. Simple = %5d. (%6.2f %%)  ", 
+        nLutsTotal, nLutOutputs, nLutsTotal-nLutOutputs, 100.0*(nLutsTotal-nLutOutputs)/nLutsTotal );
+    if ( fVerbose )
+    printf( "Memory = %6.2f MB\n", 1.0*nLutOutputs*(1<<nLutSize)/(1<<20) );
+//  printf( "\n" );
+
+//fprintf( pTable, "%d ", nLutOutputsOrig );
+//fprintf( pTable, "%d ", nLutOutputs );
+
+    if ( fVerbose )
+    {
+    printf( "Pure decomposition time   = %.2f sec\n", (float)(Abc_Clock() - clk1 - s_EncodingTime)/(float)(CLOCKS_PER_SEC) );
+    printf( "Encoding time             = %.2f sec\n", (float)(s_EncodingTime)/(float)(CLOCKS_PER_SEC) );
+//  printf( "Encoding search time      = %.2f sec\n", (float)(s_EncSearchTime)/(float)(CLOCKS_PER_SEC) );
+//  printf( "Encoding compute time     = %.2f sec\n", (float)(s_EncComputeTime)/(float)(CLOCKS_PER_SEC) );
+    }
+
+
+//fprintf( pTable, "%.2f ", (float)(s_ReadingTime)/(float)(CLOCKS_PER_SEC) );
+//fprintf( pTable, "%.2f ", (float)(Abc_Clock() - clk1 - s_EncodingTime)/(float)(CLOCKS_PER_SEC) );
+//fprintf( pTable, "%.2f ", (float)(s_EncodingTime)/(float)(CLOCKS_PER_SEC) );
+//fprintf( pTable, "%.2f ", (float)(s_RemappingTime)/(float)(CLOCKS_PER_SEC) );
+
+
+    // write LUTs into the BLIF file
+    clk1 = Abc_Clock();
+    if ( fCheck )
+    {
+        FILE * pFile;
+        // start the file
+        pFile = fopen( FileName, "w" );
+        fprintf( pFile, ".model %s\n", FileName );
+
+        fprintf( pFile, ".inputs" );
+        for ( i = 0; i < nNames; i++ )
+            fprintf( pFile, " %s", pNames[i] );
+        fprintf( pFile, "\n" );
+        fprintf( pFile, ".outputs F" );
+        fprintf( pFile, "\n" );
+
+        // write the DD into the file
+        WriteLUTSintoBLIFfile( pFile, dd, pLuts, nLuts, bCVars, pNames, nNames, FileName );
+
+        fprintf( pFile, ".end\n" );
+        fclose( pFile );
+        if ( fVerbose )
+        printf( "Output file writing time  = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+    }
+
+
+    // updo the LUT cascade
+    for ( i = 0; i < nLuts; i++ )
+    {
+        p = pLuts[i];
+        for ( v = 0; v < p->nCols; v++ )
+        {
+            Cudd_RecursiveDeref( dd, p->pbCols[v] );
+            Cudd_RecursiveDeref( dd, p->pbCodes[v] );
+            Cudd_RecursiveDeref( dd, p->paNodes[v] );
+        }
+        Cudd_RecursiveDeref( dd, p->bRelation );
+
+        ABC_FREE( p->pbCols );
+        ABC_FREE( p->pbCodes );
+        ABC_FREE( p->paNodes );
+        ABC_FREE( p );
+    }
+
+    return 1;
+}
+ 
+void WriteLUTSintoBLIFfile( FILE * pFile, DdManager * dd, LUT ** pLuts, int nLuts, DdNode ** bCVars, char ** pNames, int nNames, char * FileName )
+{
+    int i, v, o;
+    static char * pNamesLocalIn[MAXINPUTS];
+    static char * pNamesLocalOut[MAXINPUTS];
+    static char Buffer[100];
+    DdNode * bCube, * bCof, * bFunc;
+    LUT * p;
+
+    // go through all the LUTs
+    for ( i = 0; i < nLuts; i++ )
+    {
+        // get the pointer to the LUT
+        p = pLuts[i];
+
+        if ( i == nLuts -1 )
+        {
+            assert( p->nMulti == 1 );
+        }
+
+
+        fprintf( pFile, "#----------------- LUT #%d ----------------------\n", i );
+
+
+        // fill in the names for the current LUT
+
+        // write the outputs of the previous LUT
+        if ( i != 0 )
+        for ( v = 0; v < p->nInsP; v++ )
+        {
+            sprintf( Buffer, "LUT%02d_%02d", i-1, v );
+            pNamesLocalIn[dd->invperm[v]] = Extra_UtilStrsav( Buffer );
+        }
+        // write the primary inputs of the current LUT
+        for ( v = 0; v < p->nIns - p->nInsP; v++ )
+            pNamesLocalIn[dd->invperm[p->Level+v]] = Extra_UtilStrsav( pNames[dd->invperm[p->Level+v]] );
+        // write the outputs of the current LUT
+        for ( v = 0; v < p->nMulti; v++ )
+        {
+            sprintf( Buffer, "LUT%02d_%02d", i, v );
+            if ( i != nLuts - 1 )
+                pNamesLocalOut[v] = Extra_UtilStrsav( Buffer );
+            else 
+                pNamesLocalOut[v] = Extra_UtilStrsav( "F" );
+        }
+
+
+        // write LUT outputs
+
+        // get the prefix
+        sprintf( Buffer, "L%02d_", i );
+
+        // get the cube of encoding variables
+        bCube = Extra_bddBitsToCube( dd, (1<<p->nMulti)-1, p->nMulti, bCVars, 1 );   Cudd_Ref( bCube );
+
+        // write each output of the LUT
+        for ( o = 0; o < p->nMulti; o++ )
+        {
+            // get the cofactor of this output
+            bCof = Cudd_Cofactor( dd, p->bRelation, bCVars[o] );  Cudd_Ref( bCof );
+            // quantify the remaining variables to get the function
+            bFunc = Cudd_bddExistAbstract( dd, bCof, bCube );     Cudd_Ref( bFunc );
+            Cudd_RecursiveDeref( dd, bCof );
+            
+            // write BLIF
+            sprintf( Buffer, "L%02d_%02d_", i, o );
+
+//          WriteDDintoBLIFfileReorder( dd, pFile, bFunc, pNamesLocalOut[o], Buffer, pNamesLocalIn );
+            // does not work well; the advantage is marginal (30%), the run time is huge...
+
+            WriteDDintoBLIFfile( pFile, bFunc, pNamesLocalOut[o], Buffer, pNamesLocalIn );
+            Cudd_RecursiveDeref( dd, bFunc );
+        }
+        Cudd_RecursiveDeref( dd, bCube );
+
+        // clean up the previous local names
+        for ( v = 0; v < dd->size; v++ )
+        {
+            if ( pNamesLocalIn[v] )
+                ABC_FREE( pNamesLocalIn[v] );
+            pNamesLocalIn[v] = NULL;
+        }
+        for ( v = 0; v < p->nMulti; v++ )
+            ABC_FREE( pNamesLocalOut[v] );
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                           END OF FILE                            ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cas/module.make b/abc-build/src/bdd/cas/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cas/module.make
@@ -0,0 +1,3 @@
+SRC +=	src/bdd/cas/casCore.c \
+	src/bdd/cas/casDec.c
+
diff --git a/abc-build/src/bdd/cudd/Makefile b/abc-build/src/bdd/cudd/Makefile
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/Makefile
@@ -0,0 +1,124 @@
+# $Id$
+#
+#    Cudd - DD package
+#---------------------------
+.SUFFIXES: .o .c .u
+
+CC	= gcc
+RANLIB	= ranlib
+PURE	=
+# Define EXE as .exe for MS-DOS and derivatives.
+EXE	=
+#EXE	= .exe
+
+MFLAG	=
+ICFLAGS	= -g
+XCFLAGS	= -DDD_STATS
+CFLAGS	= $(ICFLAGS) $(MFLAG) $(XCFLAGS)
+#DDDEBUG	= -DDD_DEBUG -DDD_CACHE_PROFILE -DDD_VERBOSE -DDD_UNIQUE_PROFILE
+DDDEBUG	=
+
+LINTFLAGS = -u -n -DDD_STATS -DDD_CACHE_PROFILE -DDD_VERBOSE -DDD_DEBUG -DDD_UNIQUE_PROFILE
+
+# this is to create the lint library
+LINTSWITCH = -o
+
+WHERE	= ..
+
+INCLUDE = $(WHERE)/include
+
+LIBS	= ./libcudd.a $(WHERE)/mtr/libmtr.a \
+	$(WHERE)/st/libst.a $(WHERE)/util/libutil.a $(WHERE)/epd/libepd.a
+
+MNEMLIB =
+
+BLIBS	= -kL. -klcudd -kL$(WHERE)/mtr -klmtr \
+	-kL$(WHERE)/st -klst -kL$(WHERE)/util -klutil -kL$(WHERE)/epd -klepd
+
+LINTLIBS = ./llib-lcudd.ln $(WHERE)/mtr/llib-lmtr.ln \
+	$(WHERE)/st/llib-lst.ln $(WHERE)/util/llib-lutil.ln \
+	$(WHERE)/epd/llib-lepd.ln
+
+LDFLAGS	=
+
+# files for the package
+P	= cudd
+PSRC	= cuddAPI.c cuddAddAbs.c cuddAddApply.c cuddAddFind.c cuddAddIte.c \
+	  cuddAddInv.c cuddAddNeg.c cuddAddWalsh.c cuddAndAbs.c \
+	  cuddAnneal.c cuddApa.c cuddApprox.c cuddBddAbs.c cuddBddCorr.c \
+	  cuddBddIte.c cuddBridge.c cuddCache.c cuddCheck.c cuddClip.c \
+	  cuddCof.c cuddCompose.c cuddDecomp.c cuddEssent.c \
+	  cuddExact.c cuddExport.c cuddGenCof.c cuddGenetic.c \
+	  cuddGroup.c cuddHarwell.c cuddInit.c cuddInteract.c \
+	  cuddLCache.c cuddLevelQ.c \
+	  cuddLinear.c cuddLiteral.c cuddMatMult.c cuddPriority.c \
+	  cuddRead.c cuddRef.c cuddReorder.c cuddSat.c cuddSign.c \
+	  cuddSolve.c cuddSplit.c cuddSubsetHB.c cuddSubsetSP.c cuddSymmetry.c \
+	  cuddTable.c cuddUtil.c cuddWindow.c cuddZddCount.c cuddZddFuncs.c \
+	  cuddZddGroup.c cuddZddIsop.c cuddZddLin.c cuddZddMisc.c \
+	  cuddZddPort.c cuddZddReord.c cuddZddSetop.c cuddZddSymm.c \
+	  cuddZddUtil.c
+PHDR    = cudd.h cuddInt.h
+POBJ	= $(PSRC:.c=.o)
+PUBJ	= $(PSRC:.c=.u)
+TARGET	= test$(P)$(EXE)
+TARGETu = test$(P)-u
+
+# files for the test program
+SRC	= test$(P).c
+OBJ	= $(SRC:.c=.o)
+UBJ	= $(SRC:.c=.u)
+
+#------------------------------------------------------
+
+lib$(P).a: $(POBJ)
+	ar rv $@ $?
+	$(RANLIB) $@
+
+.c.o: $(PSRC) $(PHDR)
+	$(CC) -c  $< -I$(INCLUDE) $(CFLAGS) $(DDDEBUG) 
+
+optimize_dec: lib$(P).b
+
+lib$(P).b: $(PUBJ)
+	ar rv $@ $?
+	$(RANLIB) $@
+
+.c.u: $(PSRC) $(PHDR)
+	cc -j $< -I$(INCLUDE) $(XCFLAGS)
+
+# if the header files change, recompile
+$(POBJ): $(PHDR)
+$(PUBJ): $(PHDR)
+$(OBJ): $(PHDR)
+$(UBJ): $(PHDR)
+
+$(TARGET): $(SRC) $(OBJ) $(HDR) $(LIBS) $(MNEMLIB)
+	$(PURE) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(MNEMLIB) -lm
+
+# optimize (DECstations and Alphas only: uses u-code)
+$(TARGETu): $(SRC) $(UBJ) $(HDR) $(LIBS:.a=.b)
+	$(CC) -O3 -Olimit 1000 $(XCFLAGS) $(LDFLAGS) -o $@ $(UBJ) $(BLIBS) -lm
+
+lint: llib-l$(P).ln
+
+llib-l$(P).ln: $(PSRC) $(PHDR)
+	lint $(LINTFLAGS) $(LINTSWITCH)$(P) -I$(INCLUDE) $(PSRC)
+
+lintpgm: lint
+	lint $(LINTFLAGS) -I$(INCLUDE) $(SRC) $(LINTLIBS)
+
+tags: $(PSRC) $(PHDR)
+	ctags $(PSRC) $(PHDR)
+
+all: lib$(P).a lib$(P).b llib-l$(P).ln tags
+
+programs: $(TARGET) $(TARGETu) lintpgm
+
+clean:
+	rm -f *.o *.u mon.out gmon.out *.pixie *.Addrs *.Counts mnem.* \
+	.pure core *.warnings
+
+distclean: clean
+	rm -f $(TARGET) $(TARGETu) lib*.a lib$(P).b llib-l$(P).ln \
+	*.bak *~ tags .gdb_history *.qv *.qx
diff --git a/abc-build/src/bdd/cudd/cuBdd.make b/abc-build/src/bdd/cudd/cuBdd.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuBdd.make
@@ -0,0 +1,41 @@
+CSRC_cu += cuddAPI.c cuddAddAbs.c cuddAddApply.c cuddAddFind.c cuddAddIte.c \
+        cuddAddInv.c cuddAddNeg.c cuddAddWalsh.c cuddAndAbs.c \
+        cuddAnneal.c cuddApa.c cuddApprox.c cuddBddAbs.c cuddBddCorr.c \
+	cuddBddIte.c cuddBridge.c cuddCache.c cuddCheck.c cuddClip.c \
+	cuddCof.c cuddCompose.c cuddDecomp.c cuddEssent.c cuddExact.c \
+	cuddExport.c cuddGenCof.c cuddGenetic.c \
+        cuddGroup.c cuddHarwell.c cuddInit.c cuddInteract.c \
+	cuddLCache.c cuddLevelQ.c \
+        cuddLinear.c cuddLiteral.c cuddMatMult.c cuddPriority.c \
+        cuddRead.c cuddRef.c cuddReorder.c cuddSat.c cuddSign.c \
+        cuddSolve.c cuddSplit.c cuddSubsetHB.c cuddSubsetSP.c cuddSymmetry.c \
+	cuddTable.c cuddUtil.c cuddWindow.c cuddZddCount.c cuddZddFuncs.c \
+	cuddZddGroup.c cuddZddIsop.c cuddZddLin.c cuddZddMisc.c cuddZddPort.c \
+	cuddZddReord.c cuddZddSetop.c cuddZddSymm.c cuddZddUtil.c 
+HEADERS_cu += cudd.h cuddInt.h
+MISC += testcudd.c r7x8.1.mat doc/cudd.ps doc/cuddAllAbs.html doc/cuddAllDet.html \
+	doc/cuddExtAbs.html doc/cuddExtDet.html doc/cuddIntro.css \
+	doc/cuddIntro.html doc/footnode.html doc/img1.gif doc/img2.gif \
+	doc/img3.gif doc/img4.gif doc/img5.gif doc/index.html \
+	doc/node1.html doc/node2.html doc/node3.html doc/node4.html \
+	doc/node5.html doc/node6.html doc/node7.html doc/node8.html \
+	doc/icons/change_begin.gif \
+	doc/icons/change_delete.gif \
+	doc/icons/change_end.gif \
+	doc/icons/contents_motif.gif \
+	doc/icons/cross_ref_motif.gif \
+	doc/icons/foot_motif.gif \
+	doc/icons/image.gif \
+	doc/icons/index_motif.gif \
+	doc/icons/next_group_motif.gif \
+	doc/icons/next_group_motif_gr.gif \
+	doc/icons/next_motif.gif \
+	doc/icons/next_motif_gr.gif \
+	doc/icons/previous_group_motif.gif \
+	doc/icons/previous_group_motif_gr.gif \
+	doc/icons/previous_motif.gif \
+	doc/icons/previous_motif_gr.gif \
+	doc/icons/up_motif.gif \
+	doc/icons/up_motif_gr.gif
+
+DEPENDENCYFILES = $(CSRC_cu)
diff --git a/abc-build/src/bdd/cudd/cudd.h b/abc-build/src/bdd/cudd/cudd.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cudd.h
@@ -0,0 +1,1054 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [cudd.h]
+
+  PackageName [cudd]
+
+  Synopsis    [The University of Colorado decision diagram package.]
+
+  Description [External functions and data strucures of the CUDD package.
+                <ul>
+                <li> To turn on the gathering of statistics, define DD_STATS.
+                <li> To link with mis, define DD_MIS.
+                </ul>
+               Modified by Abelardo Pardo to interface it to VIS.
+  ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+  Revision    [$Id: cudd.h,v 1.174 2009/02/21 05:55:18 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef ABC__bdd__cudd__cudd_h
+#define ABC__bdd__cudd__cudd_h
+
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+#include "bdd/mtr/mtr.h"
+#include "bdd/epd/epd.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define CUDD_VERSION "2.4.2"
+
+#ifndef SIZEOF_VOID_P
+#define SIZEOF_VOID_P 4
+#endif
+#ifndef SIZEOF_INT
+#define SIZEOF_INT 4
+#endif
+#ifndef SIZEOF_LONG
+#define SIZEOF_LONG 4
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define CUDD_VALUE_TYPE         double
+#define CUDD_OUT_OF_MEM         -1
+/* The sizes of the subtables and the cache must be powers of two. */
+#define CUDD_UNIQUE_SLOTS       256     /* initial size of subtables */
+#define CUDD_CACHE_SLOTS        262144  /* default size of the cache */
+
+/* Constants for residue functions. */
+#define CUDD_RESIDUE_DEFAULT    0
+#define CUDD_RESIDUE_MSB        1
+#define CUDD_RESIDUE_TC         2
+
+/* CUDD_MAXINDEX is defined in such a way that on 32-bit and 64-bit
+** machines one can cast an index to (int) without generating a negative
+** number.
+*/
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define CUDD_MAXINDEX           (((DdHalfWord) ~0) >> 1)
+#else
+#define CUDD_MAXINDEX           ((DdHalfWord) ~0)
+#endif
+
+/* CUDD_CONST_INDEX is the index of constant nodes.  Currently this
+** is a synonim for CUDD_MAXINDEX. */
+#define CUDD_CONST_INDEX        CUDD_MAXINDEX
+
+/* These constants define the digits used in the representation of
+** arbitrary precision integers.  The configurations tested use 8, 16,
+** and 32 bits for each digit.  The typedefs should be in agreement
+** with these definitions.
+*/
+#if SIZEOF_LONG == 8
+#define DD_APA_BITS     32
+#define DD_APA_BASE     (1L << DD_APA_BITS)
+#define DD_APA_HEXPRINT "%08x"
+#else
+#define DD_APA_BITS     16
+#define DD_APA_BASE     (1 << DD_APA_BITS)
+#define DD_APA_HEXPRINT "%04x"
+#endif
+#define DD_APA_MASK     (DD_APA_BASE - 1)
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/**Enum************************************************************************
+
+  Synopsis    [Type of reordering algorithm.]
+
+  Description [Type of reordering algorithm.]
+
+******************************************************************************/
+typedef enum {
+    CUDD_REORDER_SAME,
+    CUDD_REORDER_NONE,
+    CUDD_REORDER_RANDOM,
+    CUDD_REORDER_RANDOM_PIVOT,
+    CUDD_REORDER_SIFT,
+    CUDD_REORDER_SIFT_CONVERGE,
+    CUDD_REORDER_SYMM_SIFT,
+    CUDD_REORDER_SYMM_SIFT_CONV,
+    CUDD_REORDER_WINDOW2,
+    CUDD_REORDER_WINDOW3,
+    CUDD_REORDER_WINDOW4,
+    CUDD_REORDER_WINDOW2_CONV,
+    CUDD_REORDER_WINDOW3_CONV,
+    CUDD_REORDER_WINDOW4_CONV,
+    CUDD_REORDER_GROUP_SIFT,
+    CUDD_REORDER_GROUP_SIFT_CONV,
+    CUDD_REORDER_ANNEALING,
+    CUDD_REORDER_GENETIC,
+    CUDD_REORDER_LINEAR,
+    CUDD_REORDER_LINEAR_CONVERGE,
+    CUDD_REORDER_LAZY_SIFT,
+    CUDD_REORDER_EXACT
+} Cudd_ReorderingType;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Type of aggregation methods.]
+
+  Description [Type of aggregation methods.]
+
+******************************************************************************/
+typedef enum {
+    CUDD_NO_CHECK,
+    CUDD_GROUP_CHECK,
+    CUDD_GROUP_CHECK2,
+    CUDD_GROUP_CHECK3,
+    CUDD_GROUP_CHECK4,
+    CUDD_GROUP_CHECK5,
+    CUDD_GROUP_CHECK6,
+    CUDD_GROUP_CHECK7,
+    CUDD_GROUP_CHECK8,
+    CUDD_GROUP_CHECK9
+} Cudd_AggregationType;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Type of hooks.]
+
+  Description [Type of hooks.]
+
+******************************************************************************/
+typedef enum {
+    CUDD_PRE_GC_HOOK,
+    CUDD_POST_GC_HOOK,
+    CUDD_PRE_REORDERING_HOOK,
+    CUDD_POST_REORDERING_HOOK
+} Cudd_HookType;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Type of error codes.]
+
+  Description [Type of  error codes.]
+
+******************************************************************************/
+typedef enum {
+    CUDD_NO_ERROR,
+    CUDD_MEMORY_OUT,
+    CUDD_TOO_MANY_NODES,
+    CUDD_MAX_MEM_EXCEEDED,
+    CUDD_INVALID_ARG,
+    CUDD_INTERNAL_ERROR
+} Cudd_ErrorType;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Group type for lazy sifting.]
+
+  Description [Group type for lazy sifting.]
+
+******************************************************************************/
+typedef enum {
+    CUDD_LAZY_NONE,
+    CUDD_LAZY_SOFT_GROUP,
+    CUDD_LAZY_HARD_GROUP,
+    CUDD_LAZY_UNGROUP
+} Cudd_LazyGroupType;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Variable type.]
+
+  Description [Variable type. Currently used only in lazy sifting.]
+
+******************************************************************************/
+typedef enum {
+    CUDD_VAR_PRIMARY_INPUT,
+    CUDD_VAR_PRESENT_STATE,
+    CUDD_VAR_NEXT_STATE
+} Cudd_VariableType;
+
+
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+typedef unsigned int   DdHalfWord;
+#else
+typedef unsigned short DdHalfWord;
+#endif
+
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+
+typedef struct DdNode DdNode;
+
+typedef struct DdChildren {
+    struct DdNode *T;
+    struct DdNode *E;
+} DdChildren;
+
+/* The DdNode structure is the only one exported out of the package */
+struct DdNode {
+    DdHalfWord index;
+    DdHalfWord ref;             /* reference count */
+    DdNode *next;               /* next pointer for unique table */
+    union {
+        CUDD_VALUE_TYPE value;  /* for constant nodes */
+        DdChildren kids;        /* for internal nodes */
+    } type;
+    ABC_INT64_T Id;
+};
+
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+
+typedef struct DdManager DdManager;
+
+typedef struct DdGen DdGen;
+
+/* These typedefs for arbitrary precision arithmetic should agree with
+** the corresponding constant definitions above. */
+#if SIZEOF_LONG == 8
+typedef unsigned int DdApaDigit;
+typedef unsigned long int DdApaDoubleDigit;
+#else
+typedef unsigned short int DdApaDigit;
+typedef unsigned int DdApaDoubleDigit;
+#endif
+typedef DdApaDigit * DdApaNumber;
+
+/* Return type for function computing two-literal clauses. */
+typedef struct DdTlcInfo DdTlcInfo;
+
+/* Type of hook function. */
+typedef int (*DD_HFP)(DdManager *, const char *, void *);
+/* Type of priority function */
+typedef DdNode * (*DD_PRFP)(DdManager * , int, DdNode **, DdNode **,
+                            DdNode **);
+/* Type of apply operator. */
+typedef DdNode * (*DD_AOP)(DdManager *, DdNode **, DdNode **);
+/* Type of monadic apply operator. */
+typedef DdNode * (*DD_MAOP)(DdManager *, DdNode *);
+/* Types of cache tag functions. */
+typedef DdNode * (*DD_CTFP)(DdManager *, DdNode *, DdNode *);
+typedef DdNode * (*DD_CTFP1)(DdManager *, DdNode *);
+/* Type of memory-out function. */
+typedef void (*DD_OOMFP)(long);
+/* Type of comparison function for qsort. */
+typedef int (*DD_QSFP)(const void *, const void *);
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns 1 if the node is a constant node.]
+
+  Description  [Returns 1 if the node is a constant node (rather than an
+  internal node). All constant nodes have the same index
+  (CUDD_CONST_INDEX). The pointer passed to Cudd_IsConstant may be either
+  regular or complemented.]
+
+  SideEffects  [none]
+
+  SeeAlso      []
+
+******************************************************************************/
+#define Cudd_IsConstant(node) ((Cudd_Regular(node))->index == CUDD_CONST_INDEX)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Complements a DD.]
+
+  Description  [Complements a DD by flipping the complement attribute of
+  the pointer (the least significant bit).]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_NotCond]
+
+******************************************************************************/
+#define Cudd_Not(node) ((DdNode *)((ptrint)(node) ^ 01))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Complements a DD if a condition is true.]
+
+  Description  [Complements a DD if condition c is true; c should be
+  either 0 or 1, because it is used directly (for efficiency). If in
+  doubt on the values c may take, use "(c) ? Cudd_Not(node) : node".]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_Not]
+
+******************************************************************************/
+#define Cudd_NotCond(node,c) ((DdNode *)((ptrint)(node) ^ (c)))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the regular version of a pointer.]
+
+  Description  []
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_Complement Cudd_IsComplement]
+
+******************************************************************************/
+#define Cudd_Regular(node) ((DdNode *)((ptruint)(node) & ~01))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the complemented version of a pointer.]
+
+  Description  []
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_Regular Cudd_IsComplement]
+
+******************************************************************************/
+#define Cudd_Complement(node) ((DdNode *)((ptruint)(node) | 01))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns 1 if a pointer is complemented.]
+
+  Description  []
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_Regular Cudd_Complement]
+
+******************************************************************************/
+#define Cudd_IsComplement(node) ((int) ((ptrint) (node) & 01))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the then child of an internal node.]
+
+  Description  [Returns the then child of an internal node. If
+  <code>node</code> is a constant node, the result is unpredictable.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_E Cudd_V]
+
+******************************************************************************/
+#define Cudd_T(node) ((Cudd_Regular(node))->type.kids.T)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the else child of an internal node.]
+
+  Description  [Returns the else child of an internal node. If
+  <code>node</code> is a constant node, the result is unpredictable.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_T Cudd_V]
+
+******************************************************************************/
+#define Cudd_E(node) ((Cudd_Regular(node))->type.kids.E)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the value of a constant node.]
+
+  Description  [Returns the value of a constant node. If
+  <code>node</code> is an internal node, the result is unpredictable.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_T Cudd_E]
+
+******************************************************************************/
+#define Cudd_V(node) ((Cudd_Regular(node))->type.value)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the current position in the order of variable
+  index.]
+
+  Description [Returns the current position in the order of variable
+  index. This macro is obsolete and is kept for compatibility. New
+  applications should use Cudd_ReadPerm instead.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_ReadPerm]
+
+******************************************************************************/
+#define Cudd_ReadIndex(dd,index) (Cudd_ReadPerm(dd,index))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the cubes of a decision diagram.]
+
+  Description  [Iterates over the cubes of a decision diagram f.
+  <ul>
+  <li> DdManager *manager;
+  <li> DdNode *f;
+  <li> DdGen *gen;
+  <li> int *cube;
+  <li> CUDD_VALUE_TYPE value;
+  </ul>
+  Cudd_ForeachCube allocates and frees the generator. Therefore the
+  application should not try to do that. Also, the cube is freed at the
+  end of Cudd_ForeachCube and hence is not available outside of the loop.<p>
+  CAUTION: It is assumed that dynamic reordering will not occur while
+  there are open generators. It is the user's responsibility to make sure
+  that dynamic reordering does not occur. As long as new nodes are not created
+  during generation, and dynamic reordering is not called explicitly,
+  dynamic reordering will not occur. Alternatively, it is sufficient to
+  disable dynamic reordering. It is a mistake to dispose of a diagram
+  on which generation is ongoing.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube Cudd_GenFree
+  Cudd_IsGenEmpty Cudd_AutodynDisable]
+
+******************************************************************************/
+#define Cudd_ForeachCube(manager, f, gen, cube, value)\
+    for((gen) = Cudd_FirstCube(manager, f, &cube, &value);\
+        Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\
+        (void) Cudd_NextCube(gen, &cube, &value))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the primes of a Boolean function.]
+
+  Description  [Iterates over the primes of a Boolean function producing
+  a prime and irredundant cover.
+  <ul>
+  <li> DdManager *manager;
+  <li> DdNode *l;
+  <li> DdNode *u;
+  <li> DdGen *gen;
+  <li> int *cube;
+  </ul>
+  The Boolean function is described by an upper bound and a lower bound.  If
+  the function is completely specified, the two bounds coincide.
+  Cudd_ForeachPrime allocates and frees the generator.  Therefore the
+  application should not try to do that.  Also, the cube is freed at the
+  end of Cudd_ForeachPrime and hence is not available outside of the loop.<p>
+  CAUTION: It is a mistake to change a diagram on which generation is ongoing.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_ForeachCube Cudd_FirstPrime Cudd_NextPrime Cudd_GenFree
+  Cudd_IsGenEmpty]
+
+******************************************************************************/
+#define Cudd_ForeachPrime(manager, l, u, gen, cube)\
+    for((gen) = Cudd_FirstPrime(manager, l, u, &cube);\
+        Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\
+        (void) Cudd_NextPrime(gen, &cube))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the nodes of a decision diagram.]
+
+  Description  [Iterates over the nodes of a decision diagram f.
+  <ul>
+  <li> DdManager *manager;
+  <li> DdNode *f;
+  <li> DdGen *gen;
+  <li> DdNode *node;
+  </ul>
+  The nodes are returned in a seemingly random order.
+  Cudd_ForeachNode allocates and frees the generator. Therefore the
+  application should not try to do that.<p>
+  CAUTION: It is assumed that dynamic reordering will not occur while
+  there are open generators. It is the user's responsibility to make sure
+  that dynamic reordering does not occur. As long as new nodes are not created
+  during generation, and dynamic reordering is not called explicitly,
+  dynamic reordering will not occur. Alternatively, it is sufficient to
+  disable dynamic reordering. It is a mistake to dispose of a diagram
+  on which generation is ongoing.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_ForeachCube Cudd_FirstNode Cudd_NextNode Cudd_GenFree
+  Cudd_IsGenEmpty Cudd_AutodynDisable]
+
+******************************************************************************/
+#define Cudd_ForeachNode(manager, f, gen, node)\
+    for((gen) = Cudd_FirstNode(manager, f, &node);\
+        Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\
+        (void) Cudd_NextNode(gen, &node))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the paths of a ZDD.]
+
+  Description  [Iterates over the paths of a ZDD f.
+  <ul>
+  <li> DdManager *manager;
+  <li> DdNode *f;
+  <li> DdGen *gen;
+  <li> int *path;
+  </ul>
+  Cudd_zddForeachPath allocates and frees the generator. Therefore the
+  application should not try to do that. Also, the path is freed at the
+  end of Cudd_zddForeachPath and hence is not available outside of the loop.<p>
+  CAUTION: It is assumed that dynamic reordering will not occur while
+  there are open generators.  It is the user's responsibility to make sure
+  that dynamic reordering does not occur.  As long as new nodes are not created
+  during generation, and dynamic reordering is not called explicitly,
+  dynamic reordering will not occur.  Alternatively, it is sufficient to
+  disable dynamic reordering.  It is a mistake to dispose of a diagram
+  on which generation is ongoing.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_zddFirstPath Cudd_zddNextPath Cudd_GenFree
+  Cudd_IsGenEmpty Cudd_AutodynDisable]
+
+******************************************************************************/
+#define Cudd_zddForeachPath(manager, f, gen, path)\
+    for((gen) = Cudd_zddFirstPath(manager, f, &path);\
+        Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\
+        (void) Cudd_zddNextPath(gen, &path))
+
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+extern DdNode *        Cudd_addNewVar( DdManager * dd );
+extern DdNode *        Cudd_addNewVarAtLevel( DdManager * dd, int level );
+extern DdNode *        Cudd_bddNewVar( DdManager * dd );
+extern DdNode *        Cudd_bddNewVarAtLevel( DdManager * dd, int level );
+extern DdNode *        Cudd_addIthVar( DdManager * dd, int i );
+extern DdNode *        Cudd_bddIthVar( DdManager * dd, int i );
+extern DdNode *        Cudd_zddIthVar( DdManager * dd, int i );
+extern int             Cudd_zddVarsFromBddVars( DdManager * dd, int multiplicity );
+extern DdNode *        Cudd_addConst( DdManager * dd, CUDD_VALUE_TYPE c );
+extern int             Cudd_IsNonConstant( DdNode * f );
+extern void            Cudd_AutodynEnable( DdManager * unique, Cudd_ReorderingType method );
+extern void            Cudd_AutodynDisable( DdManager * unique );
+extern int             Cudd_ReorderingStatus( DdManager * unique, Cudd_ReorderingType * method );
+extern void            Cudd_AutodynEnableZdd( DdManager * unique, Cudd_ReorderingType method );
+extern void            Cudd_AutodynDisableZdd( DdManager * unique );
+extern int             Cudd_ReorderingStatusZdd( DdManager * unique, Cudd_ReorderingType * method );
+extern int             Cudd_zddRealignmentEnabled( DdManager * unique );
+extern void            Cudd_zddRealignEnable( DdManager * unique );
+extern void            Cudd_zddRealignDisable( DdManager * unique );
+extern int             Cudd_bddRealignmentEnabled( DdManager * unique );
+extern void            Cudd_bddRealignEnable( DdManager * unique );
+extern void            Cudd_bddRealignDisable( DdManager * unique );
+extern DdNode *        Cudd_ReadOne( DdManager * dd );
+extern DdNode *        Cudd_ReadZddOne( DdManager * dd, int i );
+extern DdNode *        Cudd_ReadZero( DdManager * dd );
+extern DdNode *        Cudd_ReadLogicZero( DdManager * dd );
+extern DdNode *        Cudd_ReadPlusInfinity( DdManager * dd );
+extern DdNode *        Cudd_ReadMinusInfinity( DdManager * dd );
+extern DdNode *        Cudd_ReadBackground( DdManager * dd );
+extern void            Cudd_SetBackground( DdManager * dd, DdNode * bck );
+extern unsigned int    Cudd_ReadCacheSlots( DdManager * dd );
+extern double          Cudd_ReadCacheUsedSlots( DdManager * dd );
+extern double          Cudd_ReadCacheLookUps( DdManager * dd );
+extern double          Cudd_ReadCacheHits( DdManager * dd );
+extern double          Cudd_ReadRecursiveCalls( DdManager * dd );
+extern unsigned int    Cudd_ReadMinHit( DdManager * dd );
+extern void            Cudd_SetMinHit( DdManager * dd, unsigned int hr );
+extern unsigned int    Cudd_ReadLooseUpTo( DdManager * dd );
+extern void            Cudd_SetLooseUpTo( DdManager * dd, unsigned int lut );
+extern unsigned int    Cudd_ReadMaxCache( DdManager * dd );
+extern unsigned int    Cudd_ReadMaxCacheHard( DdManager * dd );
+extern void            Cudd_SetMaxCacheHard( DdManager * dd, unsigned int mc );
+extern int             Cudd_ReadSize( DdManager * dd );
+extern int             Cudd_ReadZddSize( DdManager * dd );
+extern unsigned int    Cudd_ReadSlots( DdManager * dd );
+extern double          Cudd_ReadUsedSlots( DdManager * dd );
+extern double          Cudd_ExpectedUsedSlots( DdManager * dd );
+extern unsigned int    Cudd_ReadKeys( DdManager * dd );
+extern unsigned int    Cudd_ReadDead( DdManager * dd );
+extern unsigned int    Cudd_ReadMinDead( DdManager * dd );
+extern int             Cudd_ReadReorderings( DdManager * dd );
+extern long            Cudd_ReadReorderingTime( DdManager * dd );
+extern int             Cudd_ReadGarbageCollections( DdManager * dd );
+extern long            Cudd_ReadGarbageCollectionTime( DdManager * dd );
+extern double          Cudd_ReadNodesFreed( DdManager * dd );
+extern double          Cudd_ReadNodesDropped( DdManager * dd );
+extern double          Cudd_ReadUniqueLookUps( DdManager * dd );
+extern double          Cudd_ReadUniqueLinks( DdManager * dd );
+extern int             Cudd_ReadSiftMaxVar( DdManager * dd );
+extern void            Cudd_SetSiftMaxVar( DdManager * dd, int smv );
+extern int             Cudd_ReadSiftMaxSwap( DdManager * dd );
+extern void            Cudd_SetSiftMaxSwap( DdManager * dd, int sms );
+extern double          Cudd_ReadMaxGrowth( DdManager * dd );
+extern void            Cudd_SetMaxGrowth( DdManager * dd, double mg );
+extern double          Cudd_ReadMaxGrowthAlternate( DdManager * dd );
+extern void            Cudd_SetMaxGrowthAlternate( DdManager * dd, double mg );
+extern int             Cudd_ReadReorderingCycle( DdManager * dd );
+extern void            Cudd_SetReorderingCycle( DdManager * dd, int cycle );
+extern MtrNode *       Cudd_ReadTree( DdManager * dd );
+extern void            Cudd_SetTree( DdManager * dd, MtrNode * tree );
+extern void            Cudd_FreeTree( DdManager * dd );
+extern MtrNode *       Cudd_ReadZddTree( DdManager * dd );
+extern void            Cudd_SetZddTree( DdManager * dd, MtrNode * tree );
+extern void            Cudd_FreeZddTree( DdManager * dd );
+extern unsigned int    Cudd_NodeReadIndex( DdNode * node );
+extern int             Cudd_ReadPerm( DdManager * dd, int i );
+extern int             Cudd_ReadPermZdd( DdManager * dd, int i );
+extern int             Cudd_ReadInvPerm( DdManager * dd, int i );
+extern int             Cudd_ReadInvPermZdd( DdManager * dd, int i );
+extern DdNode *        Cudd_ReadVars( DdManager * dd, int i );
+extern CUDD_VALUE_TYPE Cudd_ReadEpsilon( DdManager * dd );
+extern void            Cudd_SetEpsilon( DdManager * dd, CUDD_VALUE_TYPE ep );
+extern Cudd_AggregationType Cudd_ReadGroupcheck( DdManager * dd );
+extern void            Cudd_SetGroupcheck( DdManager * dd, Cudd_AggregationType gc );
+extern int             Cudd_GarbageCollectionEnabled( DdManager * dd );
+extern void            Cudd_EnableGarbageCollection( DdManager * dd );
+extern void            Cudd_DisableGarbageCollection( DdManager * dd );
+extern int             Cudd_DeadAreCounted( DdManager * dd );
+extern void            Cudd_TurnOnCountDead( DdManager * dd );
+extern void            Cudd_TurnOffCountDead( DdManager * dd );
+extern int             Cudd_ReadRecomb( DdManager * dd );
+extern void            Cudd_SetRecomb( DdManager * dd, int recomb );
+extern int             Cudd_ReadSymmviolation( DdManager * dd );
+extern void            Cudd_SetSymmviolation( DdManager * dd, int symmviolation );
+extern int             Cudd_ReadArcviolation( DdManager * dd );
+extern void            Cudd_SetArcviolation( DdManager * dd, int arcviolation );
+extern int             Cudd_ReadPopulationSize( DdManager * dd );
+extern void            Cudd_SetPopulationSize( DdManager * dd, int populationSize );
+extern int             Cudd_ReadNumberXovers( DdManager * dd );
+extern void            Cudd_SetNumberXovers( DdManager * dd, int numberXovers );
+extern unsigned long   Cudd_ReadMemoryInUse( DdManager * dd );
+extern int             Cudd_PrintInfo( DdManager * dd, FILE * fp );
+extern long            Cudd_ReadPeakNodeCount( DdManager * dd );
+extern int             Cudd_ReadPeakLiveNodeCount( DdManager * dd );
+extern long            Cudd_ReadNodeCount( DdManager * dd );
+extern long            Cudd_zddReadNodeCount( DdManager * dd );
+extern int             Cudd_AddHook( DdManager * dd, DD_HFP f, Cudd_HookType where );
+extern int             Cudd_RemoveHook( DdManager * dd, DD_HFP f, Cudd_HookType where );
+extern int             Cudd_IsInHook( DdManager * dd, DD_HFP f, Cudd_HookType where );
+extern int             Cudd_StdPreReordHook( DdManager * dd, const char * str, void * data );
+extern int             Cudd_StdPostReordHook( DdManager * dd, const char * str, void * data );
+extern int             Cudd_EnableReorderingReporting( DdManager * dd );
+extern int             Cudd_DisableReorderingReporting( DdManager * dd );
+extern int             Cudd_ReorderingReporting( DdManager * dd );
+extern Cudd_ErrorType  Cudd_ReadErrorCode( DdManager * dd );
+extern void            Cudd_ClearErrorCode( DdManager * dd );
+extern FILE *          Cudd_ReadStdout( DdManager * dd );
+extern void            Cudd_SetStdout( DdManager * dd, FILE * fp );
+extern FILE *          Cudd_ReadStderr( DdManager * dd );
+extern void            Cudd_SetStderr( DdManager * dd, FILE * fp );
+extern unsigned int    Cudd_ReadNextReordering( DdManager * dd );
+extern void            Cudd_SetNextReordering( DdManager * dd, unsigned int next );
+extern double          Cudd_ReadSwapSteps( DdManager * dd );
+extern unsigned int    Cudd_ReadMaxLive( DdManager * dd );
+extern void            Cudd_SetMaxLive( DdManager * dd, unsigned int maxLive );
+extern unsigned long   Cudd_ReadMaxMemory( DdManager * dd );
+extern void            Cudd_SetMaxMemory( DdManager * dd, unsigned long maxMemory );
+extern int             Cudd_bddBindVar( DdManager * dd, int index );
+extern int             Cudd_bddUnbindVar( DdManager * dd, int index );
+extern int             Cudd_bddVarIsBound( DdManager * dd, int index );
+extern DdNode *        Cudd_addExistAbstract( DdManager * manager, DdNode * f, DdNode * cube );
+extern DdNode *        Cudd_addUnivAbstract( DdManager * manager, DdNode * f, DdNode * cube );
+extern DdNode *        Cudd_addOrAbstract( DdManager * manager, DdNode * f, DdNode * cube );
+extern DdNode *        Cudd_addApply( DdManager * dd, DdNode * ( * )(DdManager * , DdNode ** , DdNode ** ), DdNode * f, DdNode * g );
+extern DdNode *        Cudd_addPlus( DdManager * dd, DdNode ** f, DdNode ** g );
+extern DdNode *        Cudd_addTimes( DdManager * dd, DdNode ** f, DdNode ** g );
+extern DdNode *        Cudd_addThreshold( DdManager * dd, DdNode ** f, DdNode ** g );
+extern DdNode *        Cudd_addSetNZ( DdManager * dd, DdNode ** f, DdNode ** g );
+extern DdNode *        Cudd_addDivide( DdManager * dd, DdNode ** f, DdNode ** g );
+extern DdNode *        Cudd_addMinus( DdManager * dd, DdNode ** f, DdNode ** g );
+extern DdNode *        Cudd_addMinimum( DdManager * dd, DdNode ** f, DdNode ** g );
+extern DdNode *        Cudd_addMaximum( DdManager * dd, DdNode ** f, DdNode ** g );
+extern DdNode *        Cudd_addOneZeroMaximum( DdManager * dd, DdNode ** f, DdNode ** g );
+extern DdNode *        Cudd_addDiff( DdManager * dd, DdNode ** f, DdNode ** g );
+extern DdNode *        Cudd_addAgreement( DdManager * dd, DdNode ** f, DdNode ** g );
+extern DdNode *        Cudd_addOr( DdManager * dd, DdNode ** f, DdNode ** g );
+extern DdNode *        Cudd_addNand( DdManager * dd, DdNode ** f, DdNode ** g );
+extern DdNode *        Cudd_addNor( DdManager * dd, DdNode ** f, DdNode ** g );
+extern DdNode *        Cudd_addXor( DdManager * dd, DdNode ** f, DdNode ** g );
+extern DdNode *        Cudd_addXnor( DdManager * dd, DdNode ** f, DdNode ** g );
+extern DdNode *        Cudd_addMonadicApply( DdManager * dd, DdNode * ( * op)(DdManager * , DdNode * ), DdNode * f );
+extern DdNode *        Cudd_addLog( DdManager * dd, DdNode * f );
+extern DdNode *        Cudd_addFindMax( DdManager * dd, DdNode * f );
+extern DdNode *        Cudd_addFindMin( DdManager * dd, DdNode * f );
+extern DdNode *        Cudd_addIthBit( DdManager * dd, DdNode * f, int bit );
+extern DdNode *        Cudd_addScalarInverse( DdManager * dd, DdNode * f, DdNode * epsilon );
+extern DdNode *        Cudd_addIte( DdManager * dd, DdNode * f, DdNode * g, DdNode * h );
+extern DdNode *        Cudd_addIteConstant( DdManager * dd, DdNode * f, DdNode * g, DdNode * h );
+extern DdNode *        Cudd_addEvalConst( DdManager * dd, DdNode * f, DdNode * g );
+extern int             Cudd_addLeq( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        Cudd_addCmpl( DdManager * dd, DdNode * f );
+extern DdNode *        Cudd_addNegate( DdManager * dd, DdNode * f );
+extern DdNode *        Cudd_addRoundOff( DdManager * dd, DdNode * f, int N );
+extern DdNode *        Cudd_addWalsh( DdManager * dd, DdNode ** x, DdNode ** y, int n );
+extern DdNode *        Cudd_addResidue( DdManager * dd, int n, int m, int options, int top );
+extern DdNode *        Cudd_bddAndAbstract( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube );
+extern DdNode *        Cudd_bddAndAbstractLimit( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube, unsigned int limit );
+extern int             Cudd_ApaNumberOfDigits( int binaryDigits );
+extern DdApaNumber     Cudd_NewApaNumber( int digits );
+extern void            Cudd_ApaCopy( int digits, DdApaNumber source, DdApaNumber dest );
+extern DdApaDigit      Cudd_ApaAdd( int digits, DdApaNumber a, DdApaNumber b, DdApaNumber sum );
+extern DdApaDigit      Cudd_ApaSubtract( int digits, DdApaNumber a, DdApaNumber b, DdApaNumber diff );
+extern DdApaDigit      Cudd_ApaShortDivision( int digits, DdApaNumber dividend, DdApaDigit divisor, DdApaNumber quotient );
+extern unsigned int    Cudd_ApaIntDivision( int digits, DdApaNumber dividend, unsigned int divisor, DdApaNumber quotient );
+extern void            Cudd_ApaShiftRight( int digits, DdApaDigit in, DdApaNumber a, DdApaNumber b );
+extern void            Cudd_ApaSetToLiteral( int digits, DdApaNumber number, DdApaDigit literal );
+extern void            Cudd_ApaPowerOfTwo( int digits, DdApaNumber number, int power );
+extern int             Cudd_ApaCompare( int digitsFirst, DdApaNumber first, int digitsSecond, DdApaNumber second );
+extern int             Cudd_ApaCompareRatios( int digitsFirst, DdApaNumber firstNum, unsigned int firstDen, int digitsSecond, DdApaNumber secondNum, unsigned int secondDen );
+extern int             Cudd_ApaPrintHex( FILE * fp, int digits, DdApaNumber number );
+extern int             Cudd_ApaPrintDecimal( FILE * fp, int digits, DdApaNumber number );
+extern int             Cudd_ApaPrintExponential( FILE * fp, int digits, DdApaNumber number, int precision );
+extern DdApaNumber     Cudd_ApaCountMinterm( DdManager * manager, DdNode * node, int nvars, int * digits );
+extern int             Cudd_ApaPrintMinterm( FILE * fp, DdManager * dd, DdNode * node, int nvars );
+extern int             Cudd_ApaPrintMintermExp( FILE * fp, DdManager * dd, DdNode * node, int nvars, int precision );
+extern int             Cudd_ApaPrintDensity( FILE * fp, DdManager * dd, DdNode * node, int nvars );
+extern DdNode *        Cudd_UnderApprox( DdManager * dd, DdNode * f, int numVars, int threshold, int safe, double quality );
+extern DdNode *        Cudd_OverApprox( DdManager * dd, DdNode * f, int numVars, int threshold, int safe, double quality );
+extern DdNode *        Cudd_RemapUnderApprox( DdManager * dd, DdNode * f, int numVars, int threshold, double quality );
+extern DdNode *        Cudd_RemapOverApprox( DdManager * dd, DdNode * f, int numVars, int threshold, double quality );
+extern DdNode *        Cudd_BiasedUnderApprox( DdManager * dd, DdNode * f, DdNode * b, int numVars, int threshold, double quality1, double quality0 );
+extern DdNode *        Cudd_BiasedOverApprox( DdManager * dd, DdNode * f, DdNode * b, int numVars, int threshold, double quality1, double quality0 );
+extern DdNode *        Cudd_bddExistAbstract( DdManager * manager, DdNode * f, DdNode * cube );
+extern DdNode *        Cudd_bddXorExistAbstract( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube );
+extern DdNode *        Cudd_bddUnivAbstract( DdManager * manager, DdNode * f, DdNode * cube );
+extern DdNode *        Cudd_bddBooleanDiff( DdManager * manager, DdNode * f, int x );
+extern int             Cudd_bddVarIsDependent( DdManager * dd, DdNode * f, DdNode * var );
+extern double          Cudd_bddCorrelation( DdManager * manager, DdNode * f, DdNode * g );
+extern double          Cudd_bddCorrelationWeights( DdManager * manager, DdNode * f, DdNode * g, double * prob );
+extern DdNode *        Cudd_bddIte( DdManager * dd, DdNode * f, DdNode * g, DdNode * h );
+extern DdNode *        Cudd_bddIteConstant( DdManager * dd, DdNode * f, DdNode * g, DdNode * h );
+extern DdNode *        Cudd_bddIntersect( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        Cudd_bddAnd( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        Cudd_bddAndLimit( DdManager * dd, DdNode * f, DdNode * g, unsigned int limit );
+extern DdNode *        Cudd_bddOr( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        Cudd_bddNand( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        Cudd_bddNor( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        Cudd_bddXor( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        Cudd_bddXnor( DdManager * dd, DdNode * f, DdNode * g );
+extern int             Cudd_bddLeq( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        Cudd_addBddThreshold( DdManager * dd, DdNode * f, CUDD_VALUE_TYPE value );
+extern DdNode *        Cudd_addBddStrictThreshold( DdManager * dd, DdNode * f, CUDD_VALUE_TYPE value );
+extern DdNode *        Cudd_addBddInterval( DdManager * dd, DdNode * f, CUDD_VALUE_TYPE lower, CUDD_VALUE_TYPE upper );
+extern DdNode *        Cudd_addBddIthBit( DdManager * dd, DdNode * f, int bit );
+extern DdNode *        Cudd_BddToAdd( DdManager * dd, DdNode * B );
+extern DdNode *        Cudd_addBddPattern( DdManager * dd, DdNode * f );
+extern DdNode *        Cudd_bddTransfer( DdManager * ddSource, DdManager * ddDestination, DdNode * f );
+extern int             Cudd_DebugCheck( DdManager * table );
+extern int             Cudd_CheckKeys( DdManager * table );
+extern DdNode *        Cudd_bddClippingAnd( DdManager * dd, DdNode * f, DdNode * g, int maxDepth, int direction );
+extern DdNode *        Cudd_bddClippingAndAbstract( DdManager * dd, DdNode * f, DdNode * g, DdNode * cube, int maxDepth, int direction );
+extern DdNode *        Cudd_Cofactor( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        Cudd_bddCompose( DdManager * dd, DdNode * f, DdNode * g, int v );
+extern DdNode *        Cudd_addCompose( DdManager * dd, DdNode * f, DdNode * g, int v );
+extern DdNode *        Cudd_addPermute( DdManager * manager, DdNode * node, int * permut );
+extern DdNode *        Cudd_addSwapVariables( DdManager * dd, DdNode * f, DdNode ** x, DdNode ** y, int n );
+extern DdNode *        Cudd_bddPermute( DdManager * manager, DdNode * node, int * permut );
+extern DdNode *        Cudd_bddVarMap( DdManager * manager, DdNode * f );
+extern int             Cudd_SetVarMap( DdManager * manager, DdNode ** x, DdNode ** y, int n );
+extern DdNode *        Cudd_bddSwapVariables( DdManager * dd, DdNode * f, DdNode ** x, DdNode ** y, int n );
+extern DdNode *        Cudd_bddAdjPermuteX( DdManager * dd, DdNode * B, DdNode ** x, int n );
+extern DdNode *        Cudd_addVectorCompose( DdManager * dd, DdNode * f, DdNode ** vector );
+extern DdNode *        Cudd_addGeneralVectorCompose( DdManager * dd, DdNode * f, DdNode ** vectorOn, DdNode ** vectorOff );
+extern DdNode *        Cudd_addNonSimCompose( DdManager * dd, DdNode * f, DdNode ** vector );
+extern DdNode *        Cudd_bddVectorCompose( DdManager * dd, DdNode * f, DdNode ** vector );
+extern int             Cudd_bddApproxConjDecomp( DdManager * dd, DdNode * f, DdNode ** * conjuncts );
+extern int             Cudd_bddApproxDisjDecomp( DdManager * dd, DdNode * f, DdNode ** * disjuncts );
+extern int             Cudd_bddIterConjDecomp( DdManager * dd, DdNode * f, DdNode ** * conjuncts );
+extern int             Cudd_bddIterDisjDecomp( DdManager * dd, DdNode * f, DdNode ** * disjuncts );
+extern int             Cudd_bddGenConjDecomp( DdManager * dd, DdNode * f, DdNode ** * conjuncts );
+extern int             Cudd_bddGenDisjDecomp( DdManager * dd, DdNode * f, DdNode ** * disjuncts );
+extern int             Cudd_bddVarConjDecomp( DdManager * dd, DdNode * f, DdNode ** * conjuncts );
+extern int             Cudd_bddVarDisjDecomp( DdManager * dd, DdNode * f, DdNode ** * disjuncts );
+extern DdNode *        Cudd_FindEssential( DdManager * dd, DdNode * f );
+extern int             Cudd_bddIsVarEssential( DdManager * manager, DdNode * f, int id, int phase );
+extern DdTlcInfo *     Cudd_FindTwoLiteralClauses( DdManager * dd, DdNode * f );
+extern int             Cudd_PrintTwoLiteralClauses( DdManager * dd, DdNode * f, char ** names, FILE * fp );
+extern int             Cudd_ReadIthClause( DdTlcInfo * tlc, int i, DdHalfWord * var1, DdHalfWord * var2, int * phase1, int * phase2 );
+extern void            Cudd_tlcInfoFree( DdTlcInfo * t );
+extern int             Cudd_DumpBlif( DdManager * dd, int n, DdNode ** f, char ** inames, char ** onames, char * mname, FILE * fp, int mv );
+extern int             Cudd_DumpBlifBody( DdManager * dd, int n, DdNode ** f, char ** inames, char ** onames, FILE * fp, int mv );
+extern int             Cudd_DumpDot( DdManager * dd, int n, DdNode ** f, char ** inames, char ** onames, FILE * fp );
+extern int             Cudd_DumpDaVinci( DdManager * dd, int n, DdNode ** f, char ** inames, char ** onames, FILE * fp );
+extern int             Cudd_DumpDDcal( DdManager * dd, int n, DdNode ** f, char ** inames, char ** onames, FILE * fp );
+extern int             Cudd_DumpFactoredForm( DdManager * dd, int n, DdNode ** f, char ** inames, char ** onames, FILE * fp );
+extern DdNode *        Cudd_bddConstrain( DdManager * dd, DdNode * f, DdNode * c );
+extern DdNode *        Cudd_bddRestrict( DdManager * dd, DdNode * f, DdNode * c );
+extern DdNode *        Cudd_bddNPAnd( DdManager * dd, DdNode * f, DdNode * c );
+extern DdNode *        Cudd_addConstrain( DdManager * dd, DdNode * f, DdNode * c );
+extern DdNode **       Cudd_bddConstrainDecomp( DdManager * dd, DdNode * f );
+extern DdNode *        Cudd_addRestrict( DdManager * dd, DdNode * f, DdNode * c );
+extern DdNode **       Cudd_bddCharToVect( DdManager * dd, DdNode * f );
+extern DdNode *        Cudd_bddLICompaction( DdManager * dd, DdNode * f, DdNode * c );
+extern DdNode *        Cudd_bddSqueeze( DdManager * dd, DdNode * l, DdNode * u );
+extern DdNode *        Cudd_bddMinimize( DdManager * dd, DdNode * f, DdNode * c );
+extern DdNode *        Cudd_SubsetCompress( DdManager * dd, DdNode * f, int nvars, int threshold );
+extern DdNode *        Cudd_SupersetCompress( DdManager * dd, DdNode * f, int nvars, int threshold );
+extern MtrNode *       Cudd_MakeTreeNode( DdManager * dd, unsigned int low, unsigned int size, unsigned int type );
+extern int             Cudd_addHarwell( FILE * fp, DdManager * dd, DdNode ** E, DdNode ** * x, DdNode ** * y, DdNode ** * xn, DdNode ** * yn_, int * nx, int * ny, int * m, int * n, int bx, int sx, int by, int sy, int pr );
+extern DdManager *     Cudd_Init( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory );
+extern void            Cudd_Quit( DdManager * unique );
+extern int             Cudd_PrintLinear( DdManager * table );
+extern int             Cudd_ReadLinear( DdManager * table, int x, int y );
+extern DdNode *        Cudd_bddLiteralSetIntersection( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        Cudd_addMatrixMultiply( DdManager * dd, DdNode * A, DdNode * B, DdNode ** z, int nz );
+extern DdNode *        Cudd_addTimesPlus( DdManager * dd, DdNode * A, DdNode * B, DdNode ** z, int nz );
+extern DdNode *        Cudd_addTriangle( DdManager * dd, DdNode * f, DdNode * g, DdNode ** z, int nz );
+extern DdNode *        Cudd_addOuterSum( DdManager * dd, DdNode * M, DdNode * r, DdNode * c );
+extern DdNode *        Cudd_PrioritySelect( DdManager * dd, DdNode * R, DdNode ** x, DdNode ** y, DdNode ** z, DdNode * Pi, int n, DdNode * ( * )(DdManager * , int, DdNode ** , DdNode ** , DdNode ** ) );
+extern DdNode *        Cudd_Xgty( DdManager * dd, int N, DdNode ** z, DdNode ** x, DdNode ** y );
+extern DdNode *        Cudd_Xeqy( DdManager * dd, int N, DdNode ** x, DdNode ** y );
+extern DdNode *        Cudd_addXeqy( DdManager * dd, int N, DdNode ** x, DdNode ** y );
+extern DdNode *        Cudd_Dxygtdxz( DdManager * dd, int N, DdNode ** x, DdNode ** y, DdNode ** z );
+extern DdNode *        Cudd_Dxygtdyz( DdManager * dd, int N, DdNode ** x, DdNode ** y, DdNode ** z );
+extern DdNode *        Cudd_Inequality( DdManager * dd, int N, int c, DdNode ** x, DdNode ** y );
+extern DdNode *        Cudd_Disequality( DdManager * dd, int N, int c, DdNode ** x, DdNode ** y );
+extern DdNode *        Cudd_bddInterval( DdManager * dd, int N, DdNode ** x, unsigned int lowerB, unsigned int upperB );
+extern DdNode *        Cudd_CProjection( DdManager * dd, DdNode * R, DdNode * Y );
+extern DdNode *        Cudd_addHamming( DdManager * dd, DdNode ** xVars, DdNode ** yVars, int nVars );
+extern int             Cudd_MinHammingDist( DdManager * dd, DdNode * f, int * minterm, int upperBound );
+extern DdNode *        Cudd_bddClosestCube( DdManager * dd, DdNode * f, DdNode * g, int * distance );
+extern int             Cudd_addRead( FILE * fp, DdManager * dd, DdNode ** E, DdNode ** * x, DdNode ** * y, DdNode ** * xn, DdNode ** * yn_, int * nx, int * ny, int * m, int * n, int bx, int sx, int by, int sy );
+extern int             Cudd_bddRead( FILE * fp, DdManager * dd, DdNode ** E, DdNode ** * x, DdNode ** * y, int * nx, int * ny, int * m, int * n, int bx, int sx, int by, int sy );
+extern void            Cudd_Ref( DdNode * n );
+extern void            Cudd_RecursiveDeref( DdManager * table, DdNode * n );
+extern void            Cudd_IterDerefBdd( DdManager * table, DdNode * n );
+extern void            Cudd_DelayedDerefBdd( DdManager * table, DdNode * n );
+extern void            Cudd_RecursiveDerefZdd( DdManager * table, DdNode * n );
+extern void            Cudd_Deref( DdNode * node );
+extern int             Cudd_CheckZeroRef( DdManager * manager );
+extern int             Cudd_ReduceHeap( DdManager * table, Cudd_ReorderingType heuristic, int minsize );
+extern int             Cudd_ShuffleHeap( DdManager * table, int * permutation );
+extern DdNode *        Cudd_Eval( DdManager * dd, DdNode * f, int * inputs );
+extern DdNode *        Cudd_ShortestPath( DdManager * manager, DdNode * f, int * weight, int * support, int * length );
+extern DdNode *        Cudd_LargestCube( DdManager * manager, DdNode * f, int * length );
+extern int             Cudd_ShortestLength( DdManager * manager, DdNode * f, int * weight );
+extern DdNode *        Cudd_Decreasing( DdManager * dd, DdNode * f, int i );
+extern DdNode *        Cudd_Increasing( DdManager * dd, DdNode * f, int i );
+extern int             Cudd_EquivDC( DdManager * dd, DdNode * F, DdNode * G, DdNode * D );
+extern int             Cudd_bddLeqUnless( DdManager * dd, DdNode * f, DdNode * g, DdNode * D );
+extern int             Cudd_EqualSupNorm( DdManager * dd, DdNode * f, DdNode * g, CUDD_VALUE_TYPE tolerance, int pr );
+extern DdNode *        Cudd_bddMakePrime( DdManager * dd, DdNode * cube, DdNode * f );
+extern double *        Cudd_CofMinterm( DdManager * dd, DdNode * node );
+extern DdNode *        Cudd_SolveEqn( DdManager * bdd, DdNode * F, DdNode * Y, DdNode ** G, int ** yIndex, int n );
+extern DdNode *        Cudd_VerifySol( DdManager * bdd, DdNode * F, DdNode ** G, int * yIndex, int n );
+extern DdNode *        Cudd_SplitSet( DdManager * manager, DdNode * S, DdNode ** xVars, int n, double m );
+extern DdNode *        Cudd_SubsetHeavyBranch( DdManager * dd, DdNode * f, int numVars, int threshold );
+extern DdNode *        Cudd_SupersetHeavyBranch( DdManager * dd, DdNode * f, int numVars, int threshold );
+extern DdNode *        Cudd_SubsetShortPaths( DdManager * dd, DdNode * f, int numVars, int threshold, int hardlimit );
+extern DdNode *        Cudd_SupersetShortPaths( DdManager * dd, DdNode * f, int numVars, int threshold, int hardlimit );
+extern void            Cudd_SymmProfile( DdManager * table, int lower, int upper );
+extern unsigned int    Cudd_Prime( unsigned int p );
+extern int             Cudd_PrintMinterm( DdManager * manager, DdNode * node );
+extern int             Cudd_bddPrintCover( DdManager * dd, DdNode * l, DdNode * u );
+extern int             Cudd_PrintDebug( DdManager * dd, DdNode * f, int n, int pr );
+extern int             Cudd_DagSize( DdNode * node );
+extern int             Cudd_EstimateCofactor( DdManager * dd, DdNode * node, int i, int phase );
+extern int             Cudd_EstimateCofactorSimple( DdNode * node, int i );
+extern int             Cudd_SharingSize( DdNode ** nodeArray, int n );
+extern double          Cudd_CountMinterm( DdManager * manager, DdNode * node, int nvars );
+extern int             Cudd_EpdCountMinterm( DdManager * manager, DdNode * node, int nvars, EpDouble * epd );
+extern double          Cudd_CountPath( DdNode * node );
+extern double          Cudd_CountPathsToNonZero( DdNode * node );
+extern DdNode *        Cudd_Support( DdManager * dd, DdNode * f );
+extern int *           Cudd_SupportIndex( DdManager * dd, DdNode * f );
+extern int             Cudd_SupportSize( DdManager * dd, DdNode * f );
+extern DdNode *        Cudd_VectorSupport( DdManager * dd, DdNode ** F, int n );
+extern int *           Cudd_VectorSupportIndex( DdManager * dd, DdNode ** F, int n );
+extern int             Cudd_VectorSupportSize( DdManager * dd, DdNode ** F, int n );
+extern int             Cudd_ClassifySupport( DdManager * dd, DdNode * f, DdNode * g, DdNode ** common, DdNode ** onlyF, DdNode ** onlyG );
+extern int             Cudd_CountLeaves( DdNode * node );
+extern int             Cudd_bddPickOneCube( DdManager * ddm, DdNode * node, char * string );
+extern DdNode *        Cudd_bddPickOneMinterm( DdManager * dd, DdNode * f, DdNode ** vars, int n );
+extern DdNode **       Cudd_bddPickArbitraryMinterms( DdManager * dd, DdNode * f, DdNode ** vars, int n, int k );
+extern DdNode *        Cudd_SubsetWithMaskVars( DdManager * dd, DdNode * f, DdNode ** vars, int nvars, DdNode ** maskVars, int mvars );
+extern DdGen *         Cudd_FirstCube( DdManager * dd, DdNode * f, int ** cube, CUDD_VALUE_TYPE * value );
+extern int             Cudd_NextCube( DdGen * gen, int ** cube, CUDD_VALUE_TYPE * value );
+extern DdGen *         Cudd_FirstPrime(DdManager * dd, DdNode * l, DdNode * u, int ** cube );
+extern int             Cudd_NextPrime(DdGen * gen, int ** cube );
+extern DdNode *        Cudd_bddComputeCube( DdManager * dd, DdNode ** vars, int * phase, int n );
+extern DdNode *        Cudd_addComputeCube( DdManager * dd, DdNode ** vars, int * phase, int n );
+extern DdNode *        Cudd_CubeArrayToBdd( DdManager * dd, int * array );
+extern int             Cudd_BddToCubeArray( DdManager * dd, DdNode * cube, int * array );
+extern DdGen *         Cudd_FirstNode( DdManager * dd, DdNode * f, DdNode ** node );
+extern int             Cudd_NextNode( DdGen * gen, DdNode ** node );
+extern int             Cudd_GenFree( DdGen * gen );
+extern int             Cudd_IsGenEmpty( DdGen * gen );
+extern DdNode *        Cudd_IndicesToCube( DdManager * dd, int * array, int n );
+extern void            Cudd_PrintVersion( FILE * fp );
+extern double          Cudd_AverageDistance( DdManager * dd );
+extern long            Cudd_Random( void );
+extern void            Cudd_Srandom( long seed );
+extern double          Cudd_Density( DdManager * dd, DdNode * f, int nvars );
+extern void            Cudd_OutOfMem( long size );
+extern int             Cudd_zddCount( DdManager * zdd, DdNode * P );
+extern double          Cudd_zddCountDouble( DdManager * zdd, DdNode * P );
+extern DdNode *        Cudd_zddProduct( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        Cudd_zddUnateProduct( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        Cudd_zddWeakDiv( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        Cudd_zddDivide( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        Cudd_zddWeakDivF( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        Cudd_zddDivideF( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        Cudd_zddComplement( DdManager * dd, DdNode * node );
+extern MtrNode *       Cudd_MakeZddTreeNode( DdManager * dd, unsigned int low, unsigned int size, unsigned int type );
+extern DdNode *        Cudd_zddIsop( DdManager * dd, DdNode * L, DdNode * U, DdNode ** zdd_I );
+extern DdNode *        Cudd_bddIsop( DdManager * dd, DdNode * L, DdNode * U );
+extern DdNode *        Cudd_MakeBddFromZddCover( DdManager * dd, DdNode * node );
+extern int             Cudd_zddDagSize( DdNode * p_node );
+extern double          Cudd_zddCountMinterm( DdManager * zdd, DdNode * node, int path );
+extern void            Cudd_zddPrintSubtable( DdManager * table );
+extern DdNode *        Cudd_zddPortFromBdd( DdManager * dd, DdNode * B );
+extern DdNode *        Cudd_zddPortToBdd( DdManager * dd, DdNode * f );
+extern int             Cudd_zddReduceHeap( DdManager * table, Cudd_ReorderingType heuristic, int minsize );
+extern int             Cudd_zddShuffleHeap( DdManager * table, int * permutation );
+extern DdNode *        Cudd_zddIte( DdManager * dd, DdNode * f, DdNode * g, DdNode * h );
+extern DdNode *        Cudd_zddUnion( DdManager * dd, DdNode * P, DdNode * Q );
+extern DdNode *        Cudd_zddIntersect( DdManager * dd, DdNode * P, DdNode * Q );
+extern DdNode *        Cudd_zddDiff( DdManager * dd, DdNode * P, DdNode * Q );
+extern DdNode *        Cudd_zddDiffConst( DdManager * zdd, DdNode * P, DdNode * Q );
+extern DdNode *        Cudd_zddSubset1( DdManager * dd, DdNode * P, int var );
+extern DdNode *        Cudd_zddSubset0( DdManager * dd, DdNode * P, int var );
+extern DdNode *        Cudd_zddChange( DdManager * dd, DdNode * P, int var );
+extern void            Cudd_zddSymmProfile( DdManager * table, int lower, int upper );
+extern int             Cudd_zddPrintMinterm( DdManager * zdd, DdNode * node );
+extern int             Cudd_zddPrintCover( DdManager * zdd, DdNode * node );
+extern int             Cudd_zddPrintDebug( DdManager * zdd, DdNode * f, int n, int pr );
+extern DdGen *         Cudd_zddFirstPath( DdManager * zdd, DdNode * f, int ** path );
+extern int             Cudd_zddNextPath( DdGen * gen, int ** path );
+extern char *          Cudd_zddCoverPathToString( DdManager * zdd, int * path, char * str );
+extern int             Cudd_zddDumpDot( DdManager * dd, int n, DdNode ** f, char ** inames, char ** onames, FILE * fp );
+extern int             Cudd_bddSetPiVar( DdManager * dd, int index );
+extern int             Cudd_bddSetPsVar( DdManager * dd, int index );
+extern int             Cudd_bddSetNsVar( DdManager * dd, int index );
+extern int             Cudd_bddIsPiVar( DdManager * dd, int index );
+extern int             Cudd_bddIsPsVar( DdManager * dd, int index );
+extern int             Cudd_bddIsNsVar( DdManager * dd, int index );
+extern int             Cudd_bddSetPairIndex( DdManager * dd, int index, int pairIndex );
+extern int             Cudd_bddReadPairIndex( DdManager * dd, int index );
+extern int             Cudd_bddSetVarToBeGrouped( DdManager * dd, int index );
+extern int             Cudd_bddSetVarHardGroup( DdManager * dd, int index );
+extern int             Cudd_bddResetVarToBeGrouped( DdManager * dd, int index );
+extern int             Cudd_bddIsVarToBeGrouped( DdManager * dd, int index );
+extern int             Cudd_bddSetVarToBeUngrouped( DdManager * dd, int index );
+extern int             Cudd_bddIsVarToBeUngrouped( DdManager * dd, int index );
+extern int             Cudd_bddIsVarHardGroup( DdManager * dd, int index );
+
+/**AutomaticEnd***************************************************************/
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif /* _CUDD */
diff --git a/abc-build/src/bdd/cudd/cudd.make b/abc-build/src/bdd/cudd/cudd.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cudd.make
@@ -0,0 +1,42 @@
+CSRC += cuddAPI.c cuddAddAbs.c cuddAddApply.c cuddAddFind.c cuddAddIte.c \
+	cuddAddInv.c cuddAddNeg.c cuddAddWalsh.c cuddAndAbs.c \
+	cuddAnneal.c cuddApa.c cuddApprox.c cuddBddAbs.c cuddBddCorr.c\
+	cuddBddIte.c cuddBridge.c cuddCache.c cuddCheck.c cuddClip.c \
+	cuddCof.c cuddCompose.c cuddDecomp.c cuddEssent.c cuddExact.c \
+	cuddExport.c cuddGenCof.c cuddGenetic.c \
+	cuddGroup.c cuddHarwell.c cuddInit.c cuddInteract.c \
+	cuddLCache.c cuddLevelQ.c \
+	cuddLinear.c cuddLiteral.c cuddMatMult.c cuddPriority.c \
+	cuddRead.c cuddRef.c cuddReorder.c cuddSat.c cuddSign.c \
+	cuddSolve.c cuddSplit.c cuddSubsetHB.c cuddSubsetSP.c cuddSymmetry.c \
+	cuddTable.c cuddUtil.c cuddWindow.c cuddZddCount.c cuddZddFuncs.c \
+	cuddZddGroup.c cuddZddIsop.c cuddZddLin.c cuddZddMisc.c cuddZddPort.c \
+	cuddZddReord.c cuddZddSetop.c cuddZddSymm.c cuddZddUtil.c 
+
+HEADERS += cudd.h cuddInt.h
+MISC += testcudd.c r7x8.1.mat doc/cudd.ps doc/cuddAllAbs.html doc/cuddAllDet.html \
+	doc/cuddExtAbs.html doc/cuddExtDet.html doc/cuddIntro.css \
+	doc/cuddIntro.html doc/footnode.html doc/img1.gif doc/img2.gif \
+	doc/img3.gif doc/img4.gif doc/img5.gif doc/index.html \
+	doc/node1.html doc/node2.html doc/node3.html doc/node4.html \
+	doc/node5.html doc/node6.html doc/node7.html doc/node8.html \
+	doc/icons/change_begin.gif \
+	doc/icons/change_delete.gif \
+	doc/icons/change_end.gif \
+	doc/icons/contents_motif.gif \
+	doc/icons/cross_ref_motif.gif \
+	doc/icons/foot_motif.gif \
+	doc/icons/image.gif \
+	doc/icons/index_motif.gif \
+	doc/icons/next_group_motif.gif \
+	doc/icons/next_group_motif_gr.gif \
+	doc/icons/next_motif.gif \
+	doc/icons/next_motif_gr.gif \
+	doc/icons/previous_group_motif.gif \
+	doc/icons/previous_group_motif_gr.gif \
+	doc/icons/previous_motif.gif \
+	doc/icons/previous_motif_gr.gif \
+	doc/icons/up_motif.gif \
+	doc/icons/up_motif_gr.gif
+
+DEPENDENCYFILES = $(CSRC)
diff --git a/abc-build/src/bdd/cudd/cuddAPI.c b/abc-build/src/bdd/cudd/cuddAPI.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddAPI.c
@@ -0,0 +1,4444 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAPI.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Application interface functions.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_addNewVar()
+                <li> Cudd_addNewVarAtLevel()
+                <li> Cudd_bddNewVar()
+                <li> Cudd_bddNewVarAtLevel()
+                <li> Cudd_addIthVar()
+                <li> Cudd_bddIthVar()
+                <li> Cudd_zddIthVar()
+                <li> Cudd_zddVarsFromBddVars()
+                <li> Cudd_addConst()
+                <li> Cudd_IsNonConstant()
+                <li> Cudd_AutodynEnable()
+                <li> Cudd_AutodynDisable()
+                <li> Cudd_ReorderingStatus()
+                <li> Cudd_AutodynEnableZdd()
+                <li> Cudd_AutodynDisableZdd()
+                <li> Cudd_ReorderingStatusZdd()
+                <li> Cudd_zddRealignmentEnabled()
+                <li> Cudd_zddRealignEnable()
+                <li> Cudd_zddRealignDisable()
+                <li> Cudd_bddRealignmentEnabled()
+                <li> Cudd_bddRealignEnable()
+                <li> Cudd_bddRealignDisable()
+                <li> Cudd_ReadOne()
+                <li> Cudd_ReadZddOne()
+                <li> Cudd_ReadZero()
+                <li> Cudd_ReadLogicZero()
+                <li> Cudd_ReadPlusInfinity()
+                <li> Cudd_ReadMinusInfinity()
+                <li> Cudd_ReadBackground()
+                <li> Cudd_SetBackground()
+                <li> Cudd_ReadCacheSlots()
+                <li> Cudd_ReadCacheUsedSlots()
+                <li> Cudd_ReadCacheLookUps()
+                <li> Cudd_ReadCacheHits()
+                <li> Cudd_ReadMinHit()
+                <li> Cudd_SetMinHit()
+                <li> Cudd_ReadLooseUpTo()
+                <li> Cudd_SetLooseUpTo()
+                <li> Cudd_ReadMaxCache()
+                <li> Cudd_ReadMaxCacheHard()
+                <li> Cudd_SetMaxCacheHard()
+                <li> Cudd_ReadSize()
+                <li> Cudd_ReadSlots()
+                <li> Cudd_ReadUsedSlots()
+                <li> Cudd_ExpectedUsedSlots()
+                <li> Cudd_ReadKeys()
+                <li> Cudd_ReadDead()
+                <li> Cudd_ReadMinDead()
+                <li> Cudd_ReadReorderings()
+                <li> Cudd_ReadReorderingTime()
+                <li> Cudd_ReadGarbageCollections()
+                <li> Cudd_ReadGarbageCollectionTime()
+                <li> Cudd_ReadNodesFreed()
+                <li> Cudd_ReadNodesDropped()
+                <li> Cudd_ReadUniqueLookUps()
+                <li> Cudd_ReadUniqueLinks()
+                <li> Cudd_ReadSiftMaxVar()
+                <li> Cudd_SetSiftMaxVar()
+                <li> Cudd_ReadMaxGrowth()
+                <li> Cudd_SetMaxGrowth()
+                <li> Cudd_ReadMaxGrowthAlternate()
+                <li> Cudd_SetMaxGrowthAlternate()
+                <li> Cudd_ReadReorderingCycle()
+                <li> Cudd_SetReorderingCycle()
+                <li> Cudd_ReadTree()
+                <li> Cudd_SetTree()
+                <li> Cudd_FreeTree()
+                <li> Cudd_ReadZddTree()
+                <li> Cudd_SetZddTree()
+                <li> Cudd_FreeZddTree()
+                <li> Cudd_NodeReadIndex()
+                <li> Cudd_ReadPerm()
+                <li> Cudd_ReadInvPerm()
+                <li> Cudd_ReadVars()
+                <li> Cudd_ReadEpsilon()
+                <li> Cudd_SetEpsilon()
+                <li> Cudd_ReadGroupCheck()
+                <li> Cudd_SetGroupcheck()
+                <li> Cudd_GarbageCollectionEnabled()
+                <li> Cudd_EnableGarbageCollection()
+                <li> Cudd_DisableGarbageCollection()
+                <li> Cudd_DeadAreCounted()
+                <li> Cudd_TurnOnCountDead()
+                <li> Cudd_TurnOffCountDead()
+                <li> Cudd_ReadRecomb()
+                <li> Cudd_SetRecomb()
+                <li> Cudd_ReadSymmviolation()
+                <li> Cudd_SetSymmviolation()
+                <li> Cudd_ReadArcviolation()
+                <li> Cudd_SetArcviolation()
+                <li> Cudd_ReadPopulationSize()
+                <li> Cudd_SetPopulationSize()
+                <li> Cudd_ReadNumberXovers()
+                <li> Cudd_SetNumberXovers()
+                <li> Cudd_ReadMemoryInUse()
+                <li> Cudd_PrintInfo()
+                <li> Cudd_ReadPeakNodeCount()
+                <li> Cudd_ReadPeakLiveNodeCount()
+                <li> Cudd_ReadNodeCount()
+                <li> Cudd_zddReadNodeCount()
+                <li> Cudd_AddHook()
+                <li> Cudd_RemoveHook()
+                <li> Cudd_IsInHook()
+                <li> Cudd_StdPreReordHook()
+                <li> Cudd_StdPostReordHook()
+                <li> Cudd_EnableReorderingReporting()
+                <li> Cudd_DisableReorderingReporting()
+                <li> Cudd_ReorderingReporting()
+                <li> Cudd_ReadErrorCode()
+                <li> Cudd_ClearErrorCode()
+                <li> Cudd_ReadStdout()
+                <li> Cudd_SetStdout()
+                <li> Cudd_ReadStderr()
+                <li> Cudd_SetStderr()
+                <li> Cudd_ReadNextReordering()
+                <li> Cudd_SetNextReordering()
+                <li> Cudd_ReadSwapSteps()
+                <li> Cudd_ReadMaxLive()
+                <li> Cudd_SetMaxLive()
+                <li> Cudd_ReadMaxMemory()
+                <li> Cudd_SetMaxMemory()
+                <li> Cudd_bddBindVar()
+                <li> Cudd_bddUnbindVar()
+                <li> Cudd_bddVarIsBound()
+                <li> Cudd_bddSetPiVar()
+                <li> Cudd_bddSetPsVar()
+                <li> Cudd_bddSetNsVar()
+                <li> Cudd_bddIsPiVar()
+                <li> Cudd_bddIsPsVar()
+                <li> Cudd_bddIsNsVar()
+                <li> Cudd_bddSetPairIndex()
+                <li> Cudd_bddReadPairIndex()
+                <li> Cudd_bddSetVarToBeGrouped()
+                <li> Cudd_bddSetVarHardGroup()
+                <li> Cudd_bddResetVarToBeGrouped()
+                <li> Cudd_bddIsVarToBeGrouped()
+                <li> Cudd_bddSetVarToBeUngrouped()
+                <li> Cudd_bddIsVarToBeUngrouped()
+                <li> Cudd_bddIsVarHardGroup()
+                </ul>
+              Static procedures included in this module:
+                <ul>
+                <li> fixVarTree()
+                </ul>]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAPI.c,v 1.59 2009/02/19 16:14:14 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void fixVarTree (MtrNode *treenode, int *perm, int size);
+static int addMultiplicityGroups (DdManager *dd, MtrNode *treenode, int multiplicity, char *vmask, char *lmask);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a new ADD variable.]
+
+  Description [Creates a new ADD variable.  The new variable has an
+  index equal to the largest previous index plus 1.  Returns a
+  pointer to the new variable if successful; NULL otherwise.
+  An ADD variable differs from a BDD variable because it points to the
+  arithmetic zero, instead of having a complement pointer to 1. ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddNewVar Cudd_addIthVar Cudd_addConst
+  Cudd_addNewVarAtLevel]
+
+******************************************************************************/
+DdNode *
+Cudd_addNewVar(
+  DdManager * dd)
+{
+    DdNode *res;
+
+    if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL);
+    do {
+        dd->reordered = 0;
+        res = cuddUniqueInter(dd,dd->size,DD_ONE(dd),DD_ZERO(dd));
+    } while (dd->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_addNewVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a new ADD variable at a specified level.]
+
+  Description [Creates a new ADD variable.  The new variable has an
+  index equal to the largest previous index plus 1 and is positioned at
+  the specified level in the order.  Returns a pointer to the new
+  variable if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addNewVar Cudd_addIthVar Cudd_bddNewVarAtLevel]
+
+******************************************************************************/
+DdNode *
+Cudd_addNewVarAtLevel(
+  DdManager * dd,
+  int  level)
+{
+    DdNode *res;
+
+    if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL);
+    if (level >= dd->size) return(Cudd_addIthVar(dd,level));
+    if (!cuddInsertSubtables(dd,1,level)) return(NULL);
+    do {
+        dd->reordered = 0;
+        res = cuddUniqueInter(dd,dd->size - 1,DD_ONE(dd),DD_ZERO(dd));
+    } while (dd->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_addNewVarAtLevel */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a new BDD variable.]
+
+  Description [Creates a new BDD variable.  The new variable has an
+  index equal to the largest previous index plus 1.  Returns a
+  pointer to the new variable if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addNewVar Cudd_bddIthVar Cudd_bddNewVarAtLevel]
+
+******************************************************************************/
+DdNode *
+Cudd_bddNewVar(
+  DdManager * dd)
+{
+    DdNode *res;
+
+    if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL);
+    res = cuddUniqueInter(dd,dd->size,dd->one,Cudd_Not(dd->one));
+
+    return(res);
+
+} /* end of Cudd_bddNewVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a new BDD variable at a specified level.]
+
+  Description [Creates a new BDD variable.  The new variable has an
+  index equal to the largest previous index plus 1 and is positioned at
+  the specified level in the order.  Returns a pointer to the new
+  variable if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddNewVar Cudd_bddIthVar Cudd_addNewVarAtLevel]
+
+******************************************************************************/
+DdNode *
+Cudd_bddNewVarAtLevel(
+  DdManager * dd,
+  int  level)
+{
+    DdNode *res;
+
+    if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL);
+    if (level >= dd->size) return(Cudd_bddIthVar(dd,level));
+    if (!cuddInsertSubtables(dd,1,level)) return(NULL);
+    res = dd->vars[dd->size - 1];
+
+    return(res);
+
+} /* end of Cudd_bddNewVarAtLevel */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the ADD variable with index i.]
+
+  Description [Retrieves the ADD variable with index i if it already
+  exists, or creates a new ADD variable.  Returns a pointer to the
+  variable if successful; NULL otherwise.  An ADD variable differs from
+  a BDD variable because it points to the arithmetic zero, instead of
+  having a complement pointer to 1. ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addNewVar Cudd_bddIthVar Cudd_addConst
+  Cudd_addNewVarAtLevel]
+
+******************************************************************************/
+DdNode *
+Cudd_addIthVar(
+  DdManager * dd,
+  int  i)
+{
+    DdNode *res;
+
+    if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL);
+    do {
+        dd->reordered = 0;
+        res = cuddUniqueInter(dd,i,DD_ONE(dd),DD_ZERO(dd));
+    } while (dd->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_addIthVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD variable with index i.]
+
+  Description [Retrieves the BDD variable with index i if it already
+  exists, or creates a new BDD variable.  Returns a pointer to the
+  variable if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddNewVar Cudd_addIthVar Cudd_bddNewVarAtLevel
+  Cudd_ReadVars]
+
+******************************************************************************/
+DdNode *
+Cudd_bddIthVar(
+  DdManager * dd,
+  int  i)
+{
+    DdNode *res;
+
+    if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL);
+    if (i < dd->size) {
+        res = dd->vars[i];
+    } else {
+        res = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
+    }
+
+    return(res);
+
+} /* end of Cudd_bddIthVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the ZDD variable with index i.]
+
+  Description [Retrieves the ZDD variable with index i if it already
+  exists, or creates a new ZDD variable.  Returns a pointer to the
+  variable if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIthVar Cudd_addIthVar]
+
+******************************************************************************/
+DdNode *
+Cudd_zddIthVar(
+  DdManager * dd,
+  int  i)
+{
+    DdNode *res;
+    DdNode *zvar;
+    DdNode *lower;
+    int j;
+
+    if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL);
+
+    /* The i-th variable function has the following structure:
+    ** at the level corresponding to index i there is a node whose "then"
+    ** child points to the universe, and whose "else" child points to zero.
+    ** Above that level there are nodes with identical children.
+    */
+
+    /* First we build the node at the level of index i. */
+    lower = (i < dd->sizeZ - 1) ? dd->univ[dd->permZ[i]+1] : DD_ONE(dd);
+    do {
+        dd->reordered = 0;
+        zvar = cuddUniqueInterZdd(dd, i, lower, DD_ZERO(dd));
+    } while (dd->reordered == 1);
+
+    if (zvar == NULL)
+        return(NULL);
+    cuddRef(zvar);
+
+    /* Now we add the "filler" nodes above the level of index i. */
+    for (j = dd->permZ[i] - 1; j >= 0; j--) {
+        do {
+            dd->reordered = 0;
+            res = cuddUniqueInterZdd(dd, dd->invpermZ[j], zvar, zvar);
+        } while (dd->reordered == 1);
+        if (res == NULL) {
+            Cudd_RecursiveDerefZdd(dd,zvar);
+            return(NULL);
+        }
+        cuddRef(res);
+        Cudd_RecursiveDerefZdd(dd,zvar);
+        zvar = res;
+    }
+    cuddDeref(zvar);
+    return(zvar);
+
+} /* end of Cudd_zddIthVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates one or more ZDD variables for each BDD variable.]
+
+  Description [Creates one or more ZDD variables for each BDD
+  variable.  If some ZDD variables already exist, only the missing
+  variables are created.  Parameter multiplicity allows the caller to
+  control how many variables are created for each BDD variable in
+  existence. For instance, if ZDDs are used to represent covers, two
+  ZDD variables are required for each BDD variable.  The order of the
+  BDD variables is transferred to the ZDD variables. If a variable
+  group tree exists for the BDD variables, a corresponding ZDD
+  variable group tree is created by expanding the BDD variable
+  tree. In any case, the ZDD variables derived from the same BDD
+  variable are merged in a ZDD variable group. If a ZDD variable group
+  tree exists, it is freed. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddNewVar Cudd_bddIthVar Cudd_bddNewVarAtLevel]
+
+******************************************************************************/
+int
+Cudd_zddVarsFromBddVars(
+  DdManager * dd /* DD manager */,
+  int multiplicity /* how many ZDD variables are created for each BDD variable */)
+{
+    int res;
+    int i, j;
+    int allnew;
+    int *permutation;
+
+    if (multiplicity < 1) return(0);
+    allnew = dd->sizeZ == 0;
+    if (dd->size * multiplicity > dd->sizeZ) {
+        res = cuddResizeTableZdd(dd,dd->size * multiplicity - 1);
+        if (res == 0) return(0);
+    }
+    /* Impose the order of the BDD variables to the ZDD variables. */
+    if (allnew) {
+        for (i = 0; i < dd->size; i++) {
+            for (j = 0; j < multiplicity; j++) {
+                dd->permZ[i * multiplicity + j] =
+                    dd->perm[i] * multiplicity + j;
+                dd->invpermZ[dd->permZ[i * multiplicity + j]] =
+                    i * multiplicity + j;
+            }
+        }
+        for (i = 0; i < dd->sizeZ; i++) {
+            dd->univ[i]->index = dd->invpermZ[i];
+        }
+    } else {
+        permutation = ABC_ALLOC(int,dd->sizeZ);
+        if (permutation == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        for (i = 0; i < dd->size; i++) {
+            for (j = 0; j < multiplicity; j++) {
+                permutation[i * multiplicity + j] =
+                    dd->invperm[i] * multiplicity + j;
+            }
+        }
+        for (i = dd->size * multiplicity; i < dd->sizeZ; i++) {
+            permutation[i] = i;
+        }
+        res = Cudd_zddShuffleHeap(dd, permutation);
+        ABC_FREE(permutation);
+        if (res == 0) return(0);
+    }
+    /* Copy and expand the variable group tree if it exists. */
+    if (dd->treeZ != NULL) {
+        Cudd_FreeZddTree(dd);
+    }
+    if (dd->tree != NULL) {
+        dd->treeZ = Mtr_CopyTree(dd->tree, multiplicity);
+        if (dd->treeZ == NULL) return(0);
+    } else if (multiplicity > 1) {
+        dd->treeZ = Mtr_InitGroupTree(0, dd->sizeZ);
+        if (dd->treeZ == NULL) return(0);
+        dd->treeZ->index = dd->invpermZ[0];
+    }
+    /* Create groups for the ZDD variables derived from the same BDD variable.
+    */
+    if (multiplicity > 1) {
+        char *vmask, *lmask;
+
+        vmask = ABC_ALLOC(char, dd->size);
+        if (vmask == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        lmask =  ABC_ALLOC(char, dd->size);
+        if (lmask == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        for (i = 0; i < dd->size; i++) {
+            vmask[i] = lmask[i] = 0;
+        }
+        res = addMultiplicityGroups(dd,dd->treeZ,multiplicity,vmask,lmask);
+        ABC_FREE(vmask);
+        ABC_FREE(lmask);
+        if (res == 0) return(0);
+    }
+    return(1);
+
+} /* end of Cudd_zddVarsFromBddVars */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the ADD for constant c.]
+
+  Description [Retrieves the ADD for constant c if it already
+  exists, or creates a new ADD.  Returns a pointer to the
+  ADD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addNewVar Cudd_addIthVar]
+
+******************************************************************************/
+DdNode *
+Cudd_addConst(
+  DdManager * dd,
+  CUDD_VALUE_TYPE  c)
+{
+    return(cuddUniqueConst(dd,c));
+
+} /* end of Cudd_addConst */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if a DD node is not constant.]
+
+  Description [Returns 1 if a DD node is not constant. This function is
+  useful to test the results of Cudd_bddIteConstant, Cudd_addIteConstant,
+  Cudd_addEvalConst. These results may be a special value signifying
+  non-constant. In the other cases the macro Cudd_IsConstant can be used.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_IsConstant Cudd_bddIteConstant Cudd_addIteConstant
+  Cudd_addEvalConst]
+
+******************************************************************************/
+int
+Cudd_IsNonConstant(
+  DdNode *f)
+{
+    return(f == DD_NON_CONSTANT || !Cudd_IsConstant(f));
+
+} /* end of Cudd_IsNonConstant */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Enables automatic dynamic reordering of BDDs and ADDs.]
+
+  Description [Enables automatic dynamic reordering of BDDs and
+  ADDs. Parameter method is used to determine the method used for
+  reordering. If CUDD_REORDER_SAME is passed, the method is
+  unchanged.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_AutodynDisable Cudd_ReorderingStatus
+  Cudd_AutodynEnableZdd]
+
+******************************************************************************/
+void
+Cudd_AutodynEnable(
+  DdManager * unique,
+  Cudd_ReorderingType  method)
+{
+    unique->autoDyn = 1;
+    if (method != CUDD_REORDER_SAME) {
+        unique->autoMethod = method;
+    }
+#ifndef DD_NO_DEATH_ROW
+    /* If reordering is enabled, using the death row causes too many
+    ** invocations. Hence, we shrink the death row to just one entry.
+    */
+    cuddClearDeathRow(unique);
+    unique->deathRowDepth = 1;
+    unique->deadMask = unique->deathRowDepth - 1;
+    if ((unsigned) unique->nextDead > unique->deadMask) {
+        unique->nextDead = 0;
+    }
+    unique->deathRow = ABC_REALLOC(DdNodePtr, unique->deathRow,
+        unique->deathRowDepth);
+#endif
+    return;
+
+} /* end of Cudd_AutodynEnable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disables automatic dynamic reordering.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_AutodynEnable Cudd_ReorderingStatus
+  Cudd_AutodynDisableZdd]
+
+******************************************************************************/
+void
+Cudd_AutodynDisable(
+  DdManager * unique)
+{
+    unique->autoDyn = 0;
+    return;
+
+} /* end of Cudd_AutodynDisable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reports the status of automatic dynamic reordering of BDDs
+  and ADDs.]
+
+  Description [Reports the status of automatic dynamic reordering of
+  BDDs and ADDs. Parameter method is set to the reordering method
+  currently selected. Returns 1 if automatic reordering is enabled; 0
+  otherwise.]
+
+  SideEffects [Parameter method is set to the reordering method currently
+  selected.]
+
+  SeeAlso     [Cudd_AutodynEnable Cudd_AutodynDisable
+  Cudd_ReorderingStatusZdd]
+
+******************************************************************************/
+int
+Cudd_ReorderingStatus(
+  DdManager * unique,
+  Cudd_ReorderingType * method)
+{
+    *method = unique->autoMethod;
+    return(unique->autoDyn);
+
+} /* end of Cudd_ReorderingStatus */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Enables automatic dynamic reordering of ZDDs.]
+
+  Description [Enables automatic dynamic reordering of ZDDs. Parameter
+  method is used to determine the method used for reordering ZDDs. If
+  CUDD_REORDER_SAME is passed, the method is unchanged.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_AutodynDisableZdd Cudd_ReorderingStatusZdd
+  Cudd_AutodynEnable]
+
+******************************************************************************/
+void
+Cudd_AutodynEnableZdd(
+  DdManager * unique,
+  Cudd_ReorderingType method)
+{
+    unique->autoDynZ = 1;
+    if (method != CUDD_REORDER_SAME) {
+        unique->autoMethodZ = method;
+    }
+    return;
+
+} /* end of Cudd_AutodynEnableZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disables automatic dynamic reordering of ZDDs.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_AutodynEnableZdd Cudd_ReorderingStatusZdd
+  Cudd_AutodynDisable]
+
+******************************************************************************/
+void
+Cudd_AutodynDisableZdd(
+  DdManager * unique)
+{
+    unique->autoDynZ = 0;
+    return;
+
+} /* end of Cudd_AutodynDisableZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reports the status of automatic dynamic reordering of ZDDs.]
+
+  Description [Reports the status of automatic dynamic reordering of
+  ZDDs. Parameter method is set to the ZDD reordering method currently
+  selected. Returns 1 if automatic reordering is enabled; 0
+  otherwise.]
+
+  SideEffects [Parameter method is set to the ZDD reordering method currently
+  selected.]
+
+  SeeAlso     [Cudd_AutodynEnableZdd Cudd_AutodynDisableZdd
+  Cudd_ReorderingStatus]
+
+******************************************************************************/
+int
+Cudd_ReorderingStatusZdd(
+  DdManager * unique,
+  Cudd_ReorderingType * method)
+{
+    *method = unique->autoMethodZ;
+    return(unique->autoDynZ);
+
+} /* end of Cudd_ReorderingStatusZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tells whether the realignment of ZDD order to BDD order is
+  enabled.]
+
+  Description [Returns 1 if the realignment of ZDD order to BDD order is
+  enabled; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddRealignEnable Cudd_zddRealignDisable
+  Cudd_bddRealignEnable Cudd_bddRealignDisable]
+
+******************************************************************************/
+int
+Cudd_zddRealignmentEnabled(
+  DdManager * unique)
+{
+    return(unique->realign);
+
+} /* end of Cudd_zddRealignmentEnabled */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Enables realignment of ZDD order to BDD order.]
+
+  Description [Enables realignment of the ZDD variable order to the
+  BDD variable order after the BDDs and ADDs have been reordered.  The
+  number of ZDD variables must be a multiple of the number of BDD
+  variables for realignment to make sense. If this condition is not met,
+  Cudd_ReduceHeap will return 0. Let <code>M</code> be the
+  ratio of the two numbers. For the purpose of realignment, the ZDD
+  variables from <code>M*i</code> to <code>(M+1)*i-1</code> are
+  reagarded as corresponding to BDD variable <code>i</code>. Realignment
+  is initially disabled.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReduceHeap Cudd_zddRealignDisable
+  Cudd_zddRealignmentEnabled Cudd_bddRealignDisable
+  Cudd_bddRealignmentEnabled]
+
+******************************************************************************/
+void
+Cudd_zddRealignEnable(
+  DdManager * unique)
+{
+    unique->realign = 1;
+    return;
+
+} /* end of Cudd_zddRealignEnable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disables realignment of ZDD order to BDD order.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddRealignEnable Cudd_zddRealignmentEnabled
+  Cudd_bddRealignEnable Cudd_bddRealignmentEnabled]
+
+******************************************************************************/
+void
+Cudd_zddRealignDisable(
+  DdManager * unique)
+{
+    unique->realign = 0;
+    return;
+
+} /* end of Cudd_zddRealignDisable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tells whether the realignment of BDD order to ZDD order is
+  enabled.]
+
+  Description [Returns 1 if the realignment of BDD order to ZDD order is
+  enabled; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddRealignEnable Cudd_bddRealignDisable
+  Cudd_zddRealignEnable Cudd_zddRealignDisable]
+
+******************************************************************************/
+int
+Cudd_bddRealignmentEnabled(
+  DdManager * unique)
+{
+    return(unique->realignZ);
+
+} /* end of Cudd_bddRealignmentEnabled */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Enables realignment of BDD order to ZDD order.]
+
+  Description [Enables realignment of the BDD variable order to the
+  ZDD variable order after the ZDDs have been reordered.  The
+  number of ZDD variables must be a multiple of the number of BDD
+  variables for realignment to make sense. If this condition is not met,
+  Cudd_zddReduceHeap will return 0. Let <code>M</code> be the
+  ratio of the two numbers. For the purpose of realignment, the ZDD
+  variables from <code>M*i</code> to <code>(M+1)*i-1</code> are
+  reagarded as corresponding to BDD variable <code>i</code>. Realignment
+  is initially disabled.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddReduceHeap Cudd_bddRealignDisable
+  Cudd_bddRealignmentEnabled Cudd_zddRealignDisable
+  Cudd_zddRealignmentEnabled]
+
+******************************************************************************/
+void
+Cudd_bddRealignEnable(
+  DdManager * unique)
+{
+    unique->realignZ = 1;
+    return;
+
+} /* end of Cudd_bddRealignEnable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disables realignment of ZDD order to BDD order.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddRealignEnable Cudd_bddRealignmentEnabled
+  Cudd_zddRealignEnable Cudd_zddRealignmentEnabled]
+
+******************************************************************************/
+void
+Cudd_bddRealignDisable(
+  DdManager * unique)
+{
+    unique->realignZ = 0;
+    return;
+
+} /* end of Cudd_bddRealignDisable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the one constant of the manager.]
+
+  Description [Returns the one constant of the manager. The one
+  constant is common to ADDs and BDDs.]
+
+  SideEffects [None]
+
+  SeeAlso [Cudd_ReadZero Cudd_ReadLogicZero Cudd_ReadZddOne]
+
+******************************************************************************/
+DdNode *
+Cudd_ReadOne(
+  DdManager * dd)
+{
+    return(dd->one);
+
+} /* end of Cudd_ReadOne */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the ZDD for the constant 1 function.]
+
+  Description [Returns the ZDD for the constant 1 function.
+  The representation of the constant 1 function as a ZDD depends on
+  how many variables it (nominally) depends on. The index of the
+  topmost variable in the support is given as argument <code>i</code>.]
+
+  SideEffects [None]
+
+  SeeAlso [Cudd_ReadOne]
+
+******************************************************************************/
+DdNode *
+Cudd_ReadZddOne(
+  DdManager * dd,
+  int  i)
+{
+    if (i < 0)
+        return(NULL);
+    return(i < dd->sizeZ ? dd->univ[i] : DD_ONE(dd));
+
+} /* end of Cudd_ReadZddOne */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the zero constant of the manager.]
+
+  Description [Returns the zero constant of the manager. The zero
+  constant is the arithmetic zero, rather than the logic zero. The
+  latter is the complement of the one constant.]
+
+  SideEffects [None]
+
+  SeeAlso [Cudd_ReadOne Cudd_ReadLogicZero]
+
+******************************************************************************/
+DdNode *
+Cudd_ReadZero(
+  DdManager * dd)
+{
+    return(DD_ZERO(dd));
+
+} /* end of Cudd_ReadZero */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the logic zero constant of the manager.]
+
+  Description [Returns the zero constant of the manager. The logic zero
+  constant is the complement of the one constant, and is distinct from
+  the arithmetic zero.]
+
+  SideEffects [None]
+
+  SeeAlso [Cudd_ReadOne Cudd_ReadZero]
+
+******************************************************************************/
+DdNode *
+Cudd_ReadLogicZero(
+  DdManager * dd)
+{
+    return(Cudd_Not(DD_ONE(dd)));
+
+} /* end of Cudd_ReadLogicZero */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the plus-infinity constant from the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+Cudd_ReadPlusInfinity(
+  DdManager * dd)
+{
+    return(dd->plusinfinity);
+
+} /* end of Cudd_ReadPlusInfinity */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the minus-infinity constant from the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+Cudd_ReadMinusInfinity(
+  DdManager * dd)
+{
+    return(dd->minusinfinity);
+
+} /* end of Cudd_ReadMinusInfinity */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the background constant of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+Cudd_ReadBackground(
+  DdManager * dd)
+{
+    return(dd->background);
+
+} /* end of Cudd_ReadBackground */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the background constant of the manager.]
+
+  Description [Sets the background constant of the manager. It assumes
+  that the DdNode pointer bck is already referenced.]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+Cudd_SetBackground(
+  DdManager * dd,
+  DdNode * bck)
+{
+    dd->background = bck;
+
+} /* end of Cudd_SetBackground */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the number of slots in the cache.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadCacheUsedSlots]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadCacheSlots(
+  DdManager * dd)
+{
+    return(dd->cacheSlots);
+
+} /* end of Cudd_ReadCacheSlots */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the fraction of used slots in the cache.]
+
+  Description [Reads the fraction of used slots in the cache. The unused
+  slots are those in which no valid data is stored. Garbage collection,
+  variable reordering, and cache resizing may cause used slots to become
+  unused.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadCacheSlots]
+
+******************************************************************************/
+double
+Cudd_ReadCacheUsedSlots(
+  DdManager * dd)
+{
+    unsigned long used = 0;
+    int slots = dd->cacheSlots;
+    DdCache *cache = dd->cache;
+    int i;
+
+    for (i = 0; i < slots; i++) {
+        used += cache[i].h != 0;
+    }
+
+    return((double)used / (double) dd->cacheSlots);
+
+} /* end of Cudd_ReadCacheUsedSlots */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of cache look-ups.]
+
+  Description [Returns the number of cache look-ups.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadCacheHits]
+
+******************************************************************************/
+double
+Cudd_ReadCacheLookUps(
+  DdManager * dd)
+{
+    return(dd->cacheHits + dd->cacheMisses +
+           dd->totCachehits + dd->totCacheMisses);
+
+} /* end of Cudd_ReadCacheLookUps */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of cache hits.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadCacheLookUps]
+
+******************************************************************************/
+double
+Cudd_ReadCacheHits(
+  DdManager * dd)
+{
+    return(dd->cacheHits + dd->totCachehits);
+
+} /* end of Cudd_ReadCacheHits */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of recursive calls.]
+
+  Description [Returns the number of recursive calls if the package is
+  compiled with DD_COUNT defined.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+double
+Cudd_ReadRecursiveCalls(
+  DdManager * dd)
+{
+#ifdef DD_COUNT
+    return(dd->recursiveCalls);
+#else
+    return(-1.0);
+#endif
+
+} /* end of Cudd_ReadRecursiveCalls */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the hit rate that causes resizinig of the computed
+  table.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetMinHit]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadMinHit(
+  DdManager * dd)
+{
+    /* Internally, the package manipulates the ratio of hits to
+    ** misses instead of the ratio of hits to accesses. */
+    return((unsigned int) (0.5 + 100 * dd->minHit / (1 + dd->minHit)));
+
+} /* end of Cudd_ReadMinHit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the hit rate that causes resizinig of the computed
+  table.]
+
+  Description [Sets the minHit parameter of the manager. This
+  parameter controls the resizing of the computed table. If the hit
+  rate is larger than the specified value, and the cache is not
+  already too large, then its size is doubled.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadMinHit]
+
+******************************************************************************/
+void
+Cudd_SetMinHit(
+  DdManager * dd,
+  unsigned int hr)
+{
+    /* Internally, the package manipulates the ratio of hits to
+    ** misses instead of the ratio of hits to accesses. */
+    dd->minHit = (double) hr / (100.0 - (double) hr);
+
+} /* end of Cudd_SetMinHit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the looseUpTo parameter of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetLooseUpTo Cudd_ReadMinHit Cudd_ReadMinDead]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadLooseUpTo(
+  DdManager * dd)
+{
+    return(dd->looseUpTo);
+
+} /* end of Cudd_ReadLooseUpTo */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the looseUpTo parameter of the manager.]
+
+  Description [Sets the looseUpTo parameter of the manager. This
+  parameter of the manager controls the threshold beyond which no fast
+  growth of the unique table is allowed. The threshold is given as a
+  number of slots. If the value passed to this function is 0, the
+  function determines a suitable value based on the available memory.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadLooseUpTo Cudd_SetMinHit]
+
+******************************************************************************/
+void
+Cudd_SetLooseUpTo(
+  DdManager * dd,
+  unsigned int lut)
+{
+    if (lut == 0) {
+        unsigned long datalimit = getSoftDataLimit();
+        lut = (unsigned int) (datalimit / (sizeof(DdNode) *
+                                           DD_MAX_LOOSE_FRACTION));
+    }
+    dd->looseUpTo = lut;
+
+} /* end of Cudd_SetLooseUpTo */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the soft limit for the cache size.]
+
+  Description [Returns the soft limit for the cache size. The soft limit]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadMaxCache]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadMaxCache(
+  DdManager * dd)
+{
+    return(2 * dd->cacheSlots + dd->cacheSlack);
+
+} /* end of Cudd_ReadMaxCache */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the maxCacheHard parameter of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetMaxCacheHard Cudd_ReadMaxCache]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadMaxCacheHard(
+  DdManager * dd)
+{
+    return(dd->maxCacheHard);
+
+} /* end of Cudd_ReadMaxCache */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the maxCacheHard parameter of the manager.]
+
+  Description [Sets the maxCacheHard parameter of the manager. The
+  cache cannot grow larger than maxCacheHard entries. This parameter
+  allows an application to control the trade-off of memory versus
+  speed. If the value passed to this function is 0, the function
+  determines a suitable maximum cache size based on the available memory.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadMaxCacheHard Cudd_SetMaxCache]
+
+******************************************************************************/
+void
+Cudd_SetMaxCacheHard(
+  DdManager * dd,
+  unsigned int mc)
+{
+    if (mc == 0) {
+        unsigned long datalimit = getSoftDataLimit();
+        mc = (unsigned int) (datalimit / (sizeof(DdCache) *
+                                          DD_MAX_CACHE_FRACTION));
+    }
+    dd->maxCacheHard = mc;
+
+} /* end of Cudd_SetMaxCacheHard */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of BDD variables in existance.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadZddSize]
+
+******************************************************************************/
+int
+Cudd_ReadSize(
+  DdManager * dd)
+{
+    return(dd->size);
+
+} /* end of Cudd_ReadSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of ZDD variables in existance.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadSize]
+
+******************************************************************************/
+int
+Cudd_ReadZddSize(
+  DdManager * dd)
+{
+    return(dd->sizeZ);
+
+} /* end of Cudd_ReadZddSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the total number of slots of the unique table.]
+
+  Description [Returns the total number of slots of the unique table.
+  This number ismainly for diagnostic purposes.]
+
+  SideEffects [None]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadSlots(
+  DdManager * dd)
+{
+    return(dd->slots);
+
+} /* end of Cudd_ReadSlots */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the fraction of used slots in the unique table.]
+
+  Description [Reads the fraction of used slots in the unique
+  table. The unused slots are those in which no valid data is
+  stored. Garbage collection, variable reordering, and subtable
+  resizing may cause used slots to become unused.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadSlots]
+
+******************************************************************************/
+double
+Cudd_ReadUsedSlots(
+  DdManager * dd)
+{
+    unsigned long used = 0;
+    int i, j;
+    int size = dd->size;
+    DdNodePtr *nodelist;
+    DdSubtable *subtable;
+    DdNode *node;
+    DdNode *sentinel = &(dd->sentinel);
+
+    /* Scan each BDD/ADD subtable. */
+    for (i = 0; i < size; i++) {
+        subtable = &(dd->subtables[i]);
+        nodelist = subtable->nodelist;
+        for (j = 0; (unsigned) j < subtable->slots; j++) {
+            node = nodelist[j];
+            if (node != sentinel) {
+                used++;
+            }
+        }
+    }
+
+    /* Scan the ZDD subtables. */
+    size = dd->sizeZ;
+
+    for (i = 0; i < size; i++) {
+        subtable = &(dd->subtableZ[i]);
+        nodelist = subtable->nodelist;
+        for (j = 0; (unsigned) j < subtable->slots; j++) {
+            node = nodelist[j];
+            if (node != NULL) {
+                used++;
+            }
+        }
+    }
+
+    /* Constant table. */
+    subtable = &(dd->constants);
+    nodelist = subtable->nodelist;
+    for (j = 0; (unsigned) j < subtable->slots; j++) {
+        node = nodelist[j];
+        if (node != NULL) {
+            used++;
+        }
+    }
+
+    return((double)used / (double) dd->slots);
+
+} /* end of Cudd_ReadUsedSlots */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the expected fraction of used slots in the unique
+  table.]
+
+  Description [Computes the fraction of slots in the unique table that
+  should be in use. This expected value is based on the assumption
+  that the hash function distributes the keys randomly; it can be
+  compared with the result of Cudd_ReadUsedSlots to monitor the
+  performance of the unique table hash function.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadSlots Cudd_ReadUsedSlots]
+
+******************************************************************************/
+double
+Cudd_ExpectedUsedSlots(
+  DdManager * dd)
+{
+    int i;
+    int size = dd->size;
+    DdSubtable *subtable;
+    double empty = 0.0;
+
+    /* To each subtable we apply the corollary to Theorem 8.5 (occupancy
+    ** distribution) from Sedgewick and Flajolet's Analysis of Algorithms.
+    ** The corollary says that for a table with M buckets and a load ratio
+    ** of r, the expected number of empty buckets is asymptotically given
+    ** by M * exp(-r).
+    */
+
+    /* Scan each BDD/ADD subtable. */
+    for (i = 0; i < size; i++) {
+        subtable = &(dd->subtables[i]);
+        empty += (double) subtable->slots *
+            exp(-(double) subtable->keys / (double) subtable->slots);
+    }
+
+    /* Scan the ZDD subtables. */
+    size = dd->sizeZ;
+
+    for (i = 0; i < size; i++) {
+        subtable = &(dd->subtableZ[i]);
+        empty += (double) subtable->slots *
+            exp(-(double) subtable->keys / (double) subtable->slots);
+    }
+
+    /* Constant table. */
+    subtable = &(dd->constants);
+    empty += (double) subtable->slots *
+        exp(-(double) subtable->keys / (double) subtable->slots);
+
+    return(1.0 - empty / (double) dd->slots);
+
+} /* end of Cudd_ExpectedUsedSlots */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of nodes in the unique table.]
+
+  Description [Returns the total number of nodes currently in the unique
+  table, including the dead nodes.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadDead]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadKeys(
+  DdManager * dd)
+{
+    return(dd->keys);
+
+} /* end of Cudd_ReadKeys */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of dead nodes in the unique table.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadKeys]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadDead(
+  DdManager * dd)
+{
+    return(dd->dead);
+
+} /* end of Cudd_ReadDead */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the minDead parameter of the manager.]
+
+  Description [Reads the minDead parameter of the manager. The minDead
+  parameter is used by the package to decide whether to collect garbage
+  or resize a subtable of the unique table when the subtable becomes
+  too full. The application can indirectly control the value of minDead
+  by setting the looseUpTo parameter.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadDead Cudd_ReadLooseUpTo Cudd_SetLooseUpTo]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadMinDead(
+  DdManager * dd)
+{
+    return(dd->minDead);
+
+} /* end of Cudd_ReadMinDead */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of times reordering has occurred.]
+
+  Description [Returns the number of times reordering has occurred in the
+  manager. The number includes both the calls to Cudd_ReduceHeap from
+  the application program and those automatically performed by the
+  package. However, calls that do not even initiate reordering are not
+  counted. A call may not initiate reordering if there are fewer than
+  minsize live nodes in the manager, or if CUDD_REORDER_NONE is specified
+  as reordering method. The calls to Cudd_ShuffleHeap are not counted.]
+
+  SideEffects [None]
+
+  SeeAlso [Cudd_ReduceHeap Cudd_ReadReorderingTime]
+
+******************************************************************************/
+int
+Cudd_ReadReorderings(
+  DdManager * dd)
+{
+    return(dd->reorderings);
+
+} /* end of Cudd_ReadReorderings */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the time spent in reordering.]
+
+  Description [Returns the number of milliseconds spent reordering
+  variables since the manager was initialized. The time spent in collecting
+  garbage before reordering is included.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadReorderings]
+
+******************************************************************************/
+long
+Cudd_ReadReorderingTime(
+  DdManager * dd)
+{
+    return(dd->reordTime);
+
+} /* end of Cudd_ReadReorderingTime */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of times garbage collection has occurred.]
+
+  Description [Returns the number of times garbage collection has
+  occurred in the manager. The number includes both the calls from
+  reordering procedures and those caused by requests to create new
+  nodes.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadGarbageCollectionTime]
+
+******************************************************************************/
+int
+Cudd_ReadGarbageCollections(
+  DdManager * dd)
+{
+    return(dd->garbageCollections);
+
+} /* end of Cudd_ReadGarbageCollections */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the time spent in garbage collection.]
+
+  Description [Returns the number of milliseconds spent doing garbage
+  collection since the manager was initialized.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadGarbageCollections]
+
+******************************************************************************/
+long
+Cudd_ReadGarbageCollectionTime(
+  DdManager * dd)
+{
+    return(dd->GCTime);
+
+} /* end of Cudd_ReadGarbageCollectionTime */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of nodes freed.]
+
+  Description [Returns the number of nodes returned to the free list if the
+  keeping of this statistic is enabled; -1 otherwise. This statistic is
+  enabled only if the package is compiled with DD_STATS defined.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadNodesDropped]
+
+******************************************************************************/
+double
+Cudd_ReadNodesFreed(
+  DdManager * dd)
+{
+#ifdef DD_STATS
+    return(dd->nodesFreed);
+#else
+    return(-1.0);
+#endif
+
+} /* end of Cudd_ReadNodesFreed */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of nodes dropped.]
+
+  Description [Returns the number of nodes killed by dereferencing if the
+  keeping of this statistic is enabled; -1 otherwise. This statistic is
+  enabled only if the package is compiled with DD_STATS defined.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadNodesFreed]
+
+******************************************************************************/
+double
+Cudd_ReadNodesDropped(
+  DdManager * dd)
+{
+#ifdef DD_STATS
+    return(dd->nodesDropped);
+#else
+    return(-1.0);
+#endif
+
+} /* end of Cudd_ReadNodesDropped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of look-ups in the unique table.]
+
+  Description [Returns the number of look-ups in the unique table if the
+  keeping of this statistic is enabled; -1 otherwise. This statistic is
+  enabled only if the package is compiled with DD_UNIQUE_PROFILE defined.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadUniqueLinks]
+
+******************************************************************************/
+double
+Cudd_ReadUniqueLookUps(
+  DdManager * dd)
+{
+#ifdef DD_UNIQUE_PROFILE
+    return(dd->uniqueLookUps);
+#else
+    return(-1.0);
+#endif
+
+} /* end of Cudd_ReadUniqueLookUps */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of links followed in the unique table.]
+
+  Description [Returns the number of links followed during look-ups in the
+  unique table if the keeping of this statistic is enabled; -1 otherwise.
+  If an item is found in the first position of its collision list, the
+  number of links followed is taken to be 0. If it is in second position,
+  the number of links is 1, and so on. This statistic is enabled only if
+  the package is compiled with DD_UNIQUE_PROFILE defined.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadUniqueLookUps]
+
+******************************************************************************/
+double
+Cudd_ReadUniqueLinks(
+  DdManager * dd)
+{
+#ifdef DD_UNIQUE_PROFILE
+    return(dd->uniqueLinks);
+#else
+    return(-1.0);
+#endif
+
+} /* end of Cudd_ReadUniqueLinks */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the siftMaxVar parameter of the manager.]
+
+  Description [Reads the siftMaxVar parameter of the manager. This
+  parameter gives the maximum number of variables that will be sifted
+  for each invocation of sifting.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadSiftMaxSwap Cudd_SetSiftMaxVar]
+
+******************************************************************************/
+int
+Cudd_ReadSiftMaxVar(
+  DdManager * dd)
+{
+    return(dd->siftMaxVar);
+
+} /* end of Cudd_ReadSiftMaxVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the siftMaxVar parameter of the manager.]
+
+  Description [Sets the siftMaxVar parameter of the manager. This
+  parameter gives the maximum number of variables that will be sifted
+  for each invocation of sifting.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetSiftMaxSwap Cudd_ReadSiftMaxVar]
+
+******************************************************************************/
+void
+Cudd_SetSiftMaxVar(
+  DdManager * dd,
+  int  smv)
+{
+    dd->siftMaxVar = smv;
+
+} /* end of Cudd_SetSiftMaxVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the siftMaxSwap parameter of the manager.]
+
+  Description [Reads the siftMaxSwap parameter of the manager. This
+  parameter gives the maximum number of swaps that will be attempted
+  for each invocation of sifting. The real number of swaps may exceed
+  the set limit because the package will always complete the sifting
+  of the variable that causes the limit to be reached.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadSiftMaxVar Cudd_SetSiftMaxSwap]
+
+******************************************************************************/
+int
+Cudd_ReadSiftMaxSwap(
+  DdManager * dd)
+{
+    return(dd->siftMaxSwap);
+
+} /* end of Cudd_ReadSiftMaxSwap */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the siftMaxSwap parameter of the manager.]
+
+  Description [Sets the siftMaxSwap parameter of the manager. This
+  parameter gives the maximum number of swaps that will be attempted
+  for each invocation of sifting. The real number of swaps may exceed
+  the set limit because the package will always complete the sifting
+  of the variable that causes the limit to be reached.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetSiftMaxVar Cudd_ReadSiftMaxSwap]
+
+******************************************************************************/
+void
+Cudd_SetSiftMaxSwap(
+  DdManager * dd,
+  int  sms)
+{
+    dd->siftMaxSwap = sms;
+
+} /* end of Cudd_SetSiftMaxSwap */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the maxGrowth parameter of the manager.]
+
+  Description [Reads the maxGrowth parameter of the manager.  This
+  parameter determines how much the number of nodes can grow during
+  sifting of a variable.  Overall, sifting never increases the size of
+  the decision diagrams.  This parameter only refers to intermediate
+  results.  A lower value will speed up sifting, possibly at the
+  expense of quality.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetMaxGrowth Cudd_ReadMaxGrowthAlternate]
+
+******************************************************************************/
+double
+Cudd_ReadMaxGrowth(
+  DdManager * dd)
+{
+    return(dd->maxGrowth);
+
+} /* end of Cudd_ReadMaxGrowth */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the maxGrowth parameter of the manager.]
+
+  Description [Sets the maxGrowth parameter of the manager.  This
+  parameter determines how much the number of nodes can grow during
+  sifting of a variable.  Overall, sifting never increases the size of
+  the decision diagrams.  This parameter only refers to intermediate
+  results.  A lower value will speed up sifting, possibly at the
+  expense of quality.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadMaxGrowth Cudd_SetMaxGrowthAlternate]
+
+******************************************************************************/
+void
+Cudd_SetMaxGrowth(
+  DdManager * dd,
+  double mg)
+{
+    dd->maxGrowth = mg;
+
+} /* end of Cudd_SetMaxGrowth */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the maxGrowthAlt parameter of the manager.]
+
+  Description [Reads the maxGrowthAlt parameter of the manager.  This
+  parameter is analogous to the maxGrowth paramter, and is used every
+  given number of reorderings instead of maxGrowth.  The number of
+  reorderings is set with Cudd_SetReorderingCycle.  If the number of
+  reorderings is 0 (default) maxGrowthAlt is never used.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadMaxGrowth Cudd_SetMaxGrowthAlternate
+  Cudd_SetReorderingCycle Cudd_ReadReorderingCycle]
+
+******************************************************************************/
+double
+Cudd_ReadMaxGrowthAlternate(
+  DdManager * dd)
+{
+    return(dd->maxGrowthAlt);
+
+} /* end of Cudd_ReadMaxGrowthAlternate */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the maxGrowthAlt parameter of the manager.]
+
+  Description [Sets the maxGrowthAlt parameter of the manager.  This
+  parameter is analogous to the maxGrowth paramter, and is used every
+  given number of reorderings instead of maxGrowth.  The number of
+  reorderings is set with Cudd_SetReorderingCycle.  If the number of
+  reorderings is 0 (default) maxGrowthAlt is never used.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowth
+  Cudd_SetReorderingCycle Cudd_ReadReorderingCycle]
+
+******************************************************************************/
+void
+Cudd_SetMaxGrowthAlternate(
+  DdManager * dd,
+  double mg)
+{
+    dd->maxGrowthAlt = mg;
+
+} /* end of Cudd_SetMaxGrowthAlternate */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the reordCycle parameter of the manager.]
+
+  Description [Reads the reordCycle parameter of the manager.  This
+  parameter determines how often the alternate threshold on maximum
+  growth is used in reordering.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowthAlternate
+  Cudd_SetReorderingCycle]
+
+******************************************************************************/
+int
+Cudd_ReadReorderingCycle(
+  DdManager * dd)
+{
+    return(dd->reordCycle);
+
+} /* end of Cudd_ReadReorderingCycle */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the reordCycle parameter of the manager.]
+
+  Description [Sets the reordCycle parameter of the manager.  This
+  parameter determines how often the alternate threshold on maximum
+  growth is used in reordering.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowthAlternate
+  Cudd_ReadReorderingCycle]
+
+******************************************************************************/
+void
+Cudd_SetReorderingCycle(
+  DdManager * dd,
+  int cycle)
+{
+    dd->reordCycle = cycle;
+
+} /* end of Cudd_SetReorderingCycle */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the variable group tree of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetTree Cudd_FreeTree Cudd_ReadZddTree]
+
+******************************************************************************/
+MtrNode *
+Cudd_ReadTree(
+  DdManager * dd)
+{
+    return(dd->tree);
+
+} /* end of Cudd_ReadTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the variable group tree of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_FreeTree Cudd_ReadTree Cudd_SetZddTree]
+
+******************************************************************************/
+void
+Cudd_SetTree(
+  DdManager * dd,
+  MtrNode * tree)
+{
+    if (dd->tree != NULL) {
+        Mtr_FreeTree(dd->tree);
+    }
+    dd->tree = tree;
+    if (tree == NULL) return;
+
+    fixVarTree(tree, dd->perm, dd->size);
+    return;
+
+} /* end of Cudd_SetTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the variable group tree of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetTree Cudd_ReadTree Cudd_FreeZddTree]
+
+******************************************************************************/
+void
+Cudd_FreeTree(
+  DdManager * dd)
+{
+    if (dd->tree != NULL) {
+        Mtr_FreeTree(dd->tree);
+        dd->tree = NULL;
+    }
+    return;
+
+} /* end of Cudd_FreeTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the variable group tree of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetZddTree Cudd_FreeZddTree Cudd_ReadTree]
+
+******************************************************************************/
+MtrNode *
+Cudd_ReadZddTree(
+  DdManager * dd)
+{
+    return(dd->treeZ);
+
+} /* end of Cudd_ReadZddTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the ZDD variable group tree of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_FreeZddTree Cudd_ReadZddTree Cudd_SetTree]
+
+******************************************************************************/
+void
+Cudd_SetZddTree(
+  DdManager * dd,
+  MtrNode * tree)
+{
+    if (dd->treeZ != NULL) {
+        Mtr_FreeTree(dd->treeZ);
+    }
+    dd->treeZ = tree;
+    if (tree == NULL) return;
+
+    fixVarTree(tree, dd->permZ, dd->sizeZ);
+    return;
+
+} /* end of Cudd_SetZddTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the variable group tree of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetZddTree Cudd_ReadZddTree Cudd_FreeTree]
+
+******************************************************************************/
+void
+Cudd_FreeZddTree(
+  DdManager * dd)
+{
+    if (dd->treeZ != NULL) {
+        Mtr_FreeTree(dd->treeZ);
+        dd->treeZ = NULL;
+    }
+    return;
+
+} /* end of Cudd_FreeZddTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of the node.]
+
+  Description [Returns the index of the node. The node pointer can be
+  either regular or complemented.]
+
+  SideEffects [None]
+
+  SeeAlso [Cudd_ReadIndex]
+
+******************************************************************************/
+unsigned int
+Cudd_NodeReadIndex(
+  DdNode * node)
+{
+    return((unsigned int) Cudd_Regular(node)->index);
+
+} /* end of Cudd_NodeReadIndex */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the current position of the i-th variable in the
+  order.]
+
+  Description [Returns the current position of the i-th variable in
+  the order. If the index is CUDD_CONST_INDEX, returns
+  CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns
+  -1.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadInvPerm Cudd_ReadPermZdd]
+
+******************************************************************************/
+int
+Cudd_ReadPerm(
+  DdManager * dd,
+  int  i)
+{
+    if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX);
+    if (i < 0 || i >= dd->size) return(-1);
+    return(dd->perm[i]);
+
+} /* end of Cudd_ReadPerm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the current position of the i-th ZDD variable in the
+  order.]
+
+  Description [Returns the current position of the i-th ZDD variable
+  in the order. If the index is CUDD_CONST_INDEX, returns
+  CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns
+  -1.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadInvPermZdd Cudd_ReadPerm]
+
+******************************************************************************/
+int
+Cudd_ReadPermZdd(
+  DdManager * dd,
+  int  i)
+{
+    if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX);
+    if (i < 0 || i >= dd->sizeZ) return(-1);
+    return(dd->permZ[i]);
+
+} /* end of Cudd_ReadPermZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of the variable currently in the i-th
+  position of the order.]
+
+  Description [Returns the index of the variable currently in the i-th
+  position of the order. If the index is CUDD_CONST_INDEX, returns
+  CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadPerm Cudd_ReadInvPermZdd]
+
+******************************************************************************/
+int
+Cudd_ReadInvPerm(
+  DdManager * dd,
+  int  i)
+{
+    if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX);
+    if (i < 0 || i >= dd->size) return(-1);
+    return(dd->invperm[i]);
+
+} /* end of Cudd_ReadInvPerm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of the ZDD variable currently in the i-th
+  position of the order.]
+
+  Description [Returns the index of the ZDD variable currently in the
+  i-th position of the order. If the index is CUDD_CONST_INDEX, returns
+  CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadPerm Cudd_ReadInvPermZdd]
+
+******************************************************************************/
+int
+Cudd_ReadInvPermZdd(
+  DdManager * dd,
+  int  i)
+{
+    if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX);
+    if (i < 0 || i >= dd->sizeZ) return(-1);
+    return(dd->invpermZ[i]);
+
+} /* end of Cudd_ReadInvPermZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the i-th element of the vars array.]
+
+  Description [Returns the i-th element of the vars array if it falls
+  within the array bounds; NULL otherwise. If i is the index of an
+  existing variable, this function produces the same result as
+  Cudd_bddIthVar. However, if the i-th var does not exist yet,
+  Cudd_bddIthVar will create it, whereas Cudd_ReadVars will not.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIthVar]
+
+******************************************************************************/
+DdNode *
+Cudd_ReadVars(
+  DdManager * dd,
+  int  i)
+{
+    if (i < 0 || i > dd->size) return(NULL);
+    return(dd->vars[i]);
+
+} /* end of Cudd_ReadVars */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the epsilon parameter of the manager.]
+
+  Description [Reads the epsilon parameter of the manager. The epsilon
+  parameter control the comparison between floating point numbers.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetEpsilon]
+
+******************************************************************************/
+CUDD_VALUE_TYPE
+Cudd_ReadEpsilon(
+  DdManager * dd)
+{
+    return(dd->epsilon);
+
+} /* end of Cudd_ReadEpsilon */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the epsilon parameter of the manager to ep.]
+
+  Description [Sets the epsilon parameter of the manager to ep. The epsilon
+  parameter control the comparison between floating point numbers.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadEpsilon]
+
+******************************************************************************/
+void
+Cudd_SetEpsilon(
+  DdManager * dd,
+  CUDD_VALUE_TYPE  ep)
+{
+    dd->epsilon = ep;
+
+} /* end of Cudd_SetEpsilon */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the groupcheck parameter of the manager.]
+
+  Description [Reads the groupcheck parameter of the manager. The
+  groupcheck parameter determines the aggregation criterion in group
+  sifting.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetGroupcheck]
+
+******************************************************************************/
+Cudd_AggregationType
+Cudd_ReadGroupcheck(
+  DdManager * dd)
+{
+    return(dd->groupcheck);
+
+} /* end of Cudd_ReadGroupCheck */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the parameter groupcheck of the manager to gc.]
+
+  Description [Sets the parameter groupcheck of the manager to gc. The
+  groupcheck parameter determines the aggregation criterion in group
+  sifting.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadGroupCheck]
+
+******************************************************************************/
+void
+Cudd_SetGroupcheck(
+  DdManager * dd,
+  Cudd_AggregationType gc)
+{
+    dd->groupcheck = gc;
+
+} /* end of Cudd_SetGroupcheck */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tells whether garbage collection is enabled.]
+
+  Description [Returns 1 if garbage collection is enabled; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_EnableGarbageCollection Cudd_DisableGarbageCollection]
+
+******************************************************************************/
+int
+Cudd_GarbageCollectionEnabled(
+  DdManager * dd)
+{
+    return(dd->gcEnabled);
+
+} /* end of Cudd_GarbageCollectionEnabled */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Enables garbage collection.]
+
+  Description [Enables garbage collection. Garbage collection is
+  initially enabled. Therefore it is necessary to call this function
+  only if garbage collection has been explicitly disabled.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DisableGarbageCollection Cudd_GarbageCollectionEnabled]
+
+******************************************************************************/
+void
+Cudd_EnableGarbageCollection(
+  DdManager * dd)
+{
+    dd->gcEnabled = 1;
+
+} /* end of Cudd_EnableGarbageCollection */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disables garbage collection.]
+
+  Description [Disables garbage collection. Garbage collection is
+  initially enabled. This function may be called to disable it.
+  However, garbage collection will still occur when a new node must be
+  created and no memory is left, or when garbage collection is required
+  for correctness. (E.g., before reordering.)]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_EnableGarbageCollection Cudd_GarbageCollectionEnabled]
+
+******************************************************************************/
+void
+Cudd_DisableGarbageCollection(
+  DdManager * dd)
+{
+    dd->gcEnabled = 0;
+
+} /* end of Cudd_DisableGarbageCollection */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tells whether dead nodes are counted towards triggering
+  reordering.]
+
+  Description [Tells whether dead nodes are counted towards triggering
+  reordering. Returns 1 if dead nodes are counted; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_TurnOnCountDead Cudd_TurnOffCountDead]
+
+******************************************************************************/
+int
+Cudd_DeadAreCounted(
+  DdManager * dd)
+{
+    return(dd->countDead == 0 ? 1 : 0);
+
+} /* end of Cudd_DeadAreCounted */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Causes the dead nodes to be counted towards triggering
+  reordering.]
+
+  Description [Causes the dead nodes to be counted towards triggering
+  reordering. This causes more frequent reorderings. By default dead
+  nodes are not counted.]
+
+  SideEffects [Changes the manager.]
+
+  SeeAlso     [Cudd_TurnOffCountDead Cudd_DeadAreCounted]
+
+******************************************************************************/
+void
+Cudd_TurnOnCountDead(
+  DdManager * dd)
+{
+    dd->countDead = 0;
+
+} /* end of Cudd_TurnOnCountDead */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Causes the dead nodes not to be counted towards triggering
+  reordering.]
+
+  Description [Causes the dead nodes not to be counted towards
+  triggering reordering. This causes less frequent reorderings. By
+  default dead nodes are not counted. Therefore there is no need to
+  call this function unless Cudd_TurnOnCountDead has been previously
+  called.]
+
+  SideEffects [Changes the manager.]
+
+  SeeAlso     [Cudd_TurnOnCountDead Cudd_DeadAreCounted]
+
+******************************************************************************/
+void
+Cudd_TurnOffCountDead(
+  DdManager * dd)
+{
+    dd->countDead = ~0;
+
+} /* end of Cudd_TurnOffCountDead */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the current value of the recombination parameter used
+  in group sifting.]
+
+  Description [Returns the current value of the recombination
+  parameter used in group sifting. A larger (positive) value makes the
+  aggregation of variables due to the second difference criterion more
+  likely. A smaller (negative) value makes aggregation less likely.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetRecomb]
+
+******************************************************************************/
+int
+Cudd_ReadRecomb(
+  DdManager * dd)
+{
+    return(dd->recomb);
+
+} /* end of Cudd_ReadRecomb */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the value of the recombination parameter used in group
+  sifting.]
+
+  Description [Sets the value of the recombination parameter used in
+  group sifting. A larger (positive) value makes the aggregation of
+  variables due to the second difference criterion more likely. A
+  smaller (negative) value makes aggregation less likely. The default
+  value is 0.]
+
+  SideEffects [Changes the manager.]
+
+  SeeAlso     [Cudd_ReadRecomb]
+
+******************************************************************************/
+void
+Cudd_SetRecomb(
+  DdManager * dd,
+  int  recomb)
+{
+    dd->recomb = recomb;
+
+} /* end of Cudd_SetRecomb */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the current value of the symmviolation parameter used
+  in group sifting.]
+
+  Description [Returns the current value of the symmviolation
+  parameter. This parameter is used in group sifting to decide how
+  many violations to the symmetry conditions <code>f10 = f01</code> or
+  <code>f11 = f00</code> are tolerable when checking for aggregation
+  due to extended symmetry. The value should be between 0 and 100. A
+  small value causes fewer variables to be aggregated. The default
+  value is 0.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetSymmviolation]
+
+******************************************************************************/
+int
+Cudd_ReadSymmviolation(
+  DdManager * dd)
+{
+    return(dd->symmviolation);
+
+} /* end of Cudd_ReadSymmviolation */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the value of the symmviolation parameter used
+  in group sifting.]
+
+  Description [Sets the value of the symmviolation
+  parameter. This parameter is used in group sifting to decide how
+  many violations to the symmetry conditions <code>f10 = f01</code> or
+  <code>f11 = f00</code> are tolerable when checking for aggregation
+  due to extended symmetry. The value should be between 0 and 100. A
+  small value causes fewer variables to be aggregated. The default
+  value is 0.]
+
+  SideEffects [Changes the manager.]
+
+  SeeAlso     [Cudd_ReadSymmviolation]
+
+******************************************************************************/
+void
+Cudd_SetSymmviolation(
+  DdManager * dd,
+  int  symmviolation)
+{
+    dd->symmviolation = symmviolation;
+
+} /* end of Cudd_SetSymmviolation */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the current value of the arcviolation parameter used
+  in group sifting.]
+
+  Description [Returns the current value of the arcviolation
+  parameter. This parameter is used in group sifting to decide how
+  many arcs into <code>y</code> not coming from <code>x</code> are
+  tolerable when checking for aggregation due to extended
+  symmetry. The value should be between 0 and 100. A small value
+  causes fewer variables to be aggregated. The default value is 0.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetArcviolation]
+
+******************************************************************************/
+int
+Cudd_ReadArcviolation(
+  DdManager * dd)
+{
+    return(dd->arcviolation);
+
+} /* end of Cudd_ReadArcviolation */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the value of the arcviolation parameter used
+  in group sifting.]
+
+  Description [Sets the value of the arcviolation
+  parameter. This parameter is used in group sifting to decide how
+  many arcs into <code>y</code> not coming from <code>x</code> are
+  tolerable when checking for aggregation due to extended
+  symmetry. The value should be between 0 and 100. A small value
+  causes fewer variables to be aggregated. The default value is 0.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadArcviolation]
+
+******************************************************************************/
+void
+Cudd_SetArcviolation(
+  DdManager * dd,
+  int  arcviolation)
+{
+    dd->arcviolation = arcviolation;
+
+} /* end of Cudd_SetArcviolation */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the current size of the population used by the
+  genetic algorithm for reordering.]
+
+  Description [Reads the current size of the population used by the
+  genetic algorithm for variable reordering. A larger population size will
+  cause the genetic algorithm to take more time, but will generally
+  produce better results. The default value is 0, in which case the
+  package uses three times the number of variables as population size,
+  with a maximum of 120.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetPopulationSize]
+
+******************************************************************************/
+int
+Cudd_ReadPopulationSize(
+  DdManager * dd)
+{
+    return(dd->populationSize);
+
+} /* end of Cudd_ReadPopulationSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the size of the population used by the
+  genetic algorithm for reordering.]
+
+  Description [Sets the size of the population used by the
+  genetic algorithm for variable reordering. A larger population size will
+  cause the genetic algorithm to take more time, but will generally
+  produce better results. The default value is 0, in which case the
+  package uses three times the number of variables as population size,
+  with a maximum of 120.]
+
+  SideEffects [Changes the manager.]
+
+  SeeAlso     [Cudd_ReadPopulationSize]
+
+******************************************************************************/
+void
+Cudd_SetPopulationSize(
+  DdManager * dd,
+  int  populationSize)
+{
+    dd->populationSize = populationSize;
+
+} /* end of Cudd_SetPopulationSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the current number of crossovers used by the
+  genetic algorithm for reordering.]
+
+  Description [Reads the current number of crossovers used by the
+  genetic algorithm for variable reordering. A larger number of crossovers will
+  cause the genetic algorithm to take more time, but will generally
+  produce better results. The default value is 0, in which case the
+  package uses three times the number of variables as number of crossovers,
+  with a maximum of 60.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetNumberXovers]
+
+******************************************************************************/
+int
+Cudd_ReadNumberXovers(
+  DdManager * dd)
+{
+    return(dd->numberXovers);
+
+} /* end of Cudd_ReadNumberXovers */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the number of crossovers used by the
+  genetic algorithm for reordering.]
+
+  Description [Sets the number of crossovers used by the genetic
+  algorithm for variable reordering. A larger number of crossovers
+  will cause the genetic algorithm to take more time, but will
+  generally produce better results. The default value is 0, in which
+  case the package uses three times the number of variables as number
+  of crossovers, with a maximum of 60.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadNumberXovers]
+
+******************************************************************************/
+void
+Cudd_SetNumberXovers(
+  DdManager * dd,
+  int  numberXovers)
+{
+    dd->numberXovers = numberXovers;
+
+} /* end of Cudd_SetNumberXovers */
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the memory in use by the manager measured in bytes.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+unsigned long
+Cudd_ReadMemoryInUse(
+  DdManager * dd)
+{
+    return(dd->memused);
+
+} /* end of Cudd_ReadMemoryInUse */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints out statistics and settings for a CUDD manager.]
+
+  Description [Prints out statistics and settings for a CUDD manager.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_PrintInfo(
+  DdManager * dd,
+  FILE * fp)
+{
+    int retval;
+    Cudd_ReorderingType autoMethod, autoMethodZ;
+
+    /* Modifiable parameters. */
+    retval = fprintf(fp,"**** CUDD modifiable parameters ****\n");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Hard limit for cache size: %u\n",
+                     Cudd_ReadMaxCacheHard(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Cache hit threshold for resizing: %u%%\n",
+                     Cudd_ReadMinHit(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Garbage collection enabled: %s\n",
+                     Cudd_GarbageCollectionEnabled(dd) ? "yes" : "no");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Limit for fast unique table growth: %u\n",
+                     Cudd_ReadLooseUpTo(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,
+                     "Maximum number of variables sifted per reordering: %d\n",
+                     Cudd_ReadSiftMaxVar(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,
+                     "Maximum number of variable swaps per reordering: %d\n",
+                     Cudd_ReadSiftMaxSwap(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Maximum growth while sifting a variable: %g\n",
+                     Cudd_ReadMaxGrowth(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Dynamic reordering of BDDs enabled: %s\n",
+                     Cudd_ReorderingStatus(dd,&autoMethod) ? "yes" : "no");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Default BDD reordering method: %d\n",
+                     (int) autoMethod);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Dynamic reordering of ZDDs enabled: %s\n",
+                     Cudd_ReorderingStatusZdd(dd,&autoMethodZ) ? "yes" : "no");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Default ZDD reordering method: %d\n",
+                     (int) autoMethodZ);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Realignment of ZDDs to BDDs enabled: %s\n",
+                     Cudd_zddRealignmentEnabled(dd) ? "yes" : "no");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Realignment of BDDs to ZDDs enabled: %s\n",
+                     Cudd_bddRealignmentEnabled(dd) ? "yes" : "no");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Dead nodes counted in triggering reordering: %s\n",
+                     Cudd_DeadAreCounted(dd) ? "yes" : "no");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Group checking criterion: %d\n",
+                     (int) Cudd_ReadGroupcheck(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Recombination threshold: %d\n", Cudd_ReadRecomb(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Symmetry violation threshold: %d\n",
+                     Cudd_ReadSymmviolation(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Arc violation threshold: %d\n",
+                     Cudd_ReadArcviolation(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"GA population size: %d\n",
+                     Cudd_ReadPopulationSize(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of crossovers for GA: %d\n",
+                     Cudd_ReadNumberXovers(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Next reordering threshold: %u\n",
+                     Cudd_ReadNextReordering(dd));
+    if (retval == EOF) return(0);
+
+    /* Non-modifiable parameters. */
+    retval = fprintf(fp,"**** CUDD non-modifiable parameters ****\n");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Memory in use: %lu\n", Cudd_ReadMemoryInUse(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Peak number of nodes: %ld\n",
+                     Cudd_ReadPeakNodeCount(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Peak number of live nodes: %d\n",
+                     Cudd_ReadPeakLiveNodeCount(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of BDD variables: %d\n", dd->size);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of ZDD variables: %d\n", dd->sizeZ);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of cache entries: %u\n", dd->cacheSlots);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of cache look-ups: %.0f\n",
+                     Cudd_ReadCacheLookUps(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of cache hits: %.0f\n",
+                     Cudd_ReadCacheHits(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of cache insertions: %.0f\n",
+                     dd->cacheinserts);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of cache collisions: %.0f\n",
+                     dd->cachecollisions);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of cache deletions: %.0f\n",
+                     dd->cachedeletions);
+    if (retval == EOF) return(0);
+    retval = cuddCacheProfile(dd,fp);
+    if (retval == 0) return(0);
+    retval = fprintf(fp,"Soft limit for cache size: %u\n",
+                     Cudd_ReadMaxCache(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of buckets in unique table: %u\n", dd->slots);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Used buckets in unique table: %.2f%% (expected %.2f%%)\n",
+                     100.0 * Cudd_ReadUsedSlots(dd),
+                     100.0 * Cudd_ExpectedUsedSlots(dd));
+    if (retval == EOF) return(0);
+#ifdef DD_UNIQUE_PROFILE
+    retval = fprintf(fp,"Unique lookups: %.0f\n", dd->uniqueLookUps);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Unique links: %.0f (%g per lookup)\n",
+            dd->uniqueLinks, dd->uniqueLinks / dd->uniqueLookUps);
+    if (retval == EOF) return(0);
+#endif
+    retval = fprintf(fp,"Number of BDD and ADD nodes: %u\n", dd->keys);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of ZDD nodes: %u\n", dd->keysZ);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of dead BDD and ADD nodes: %u\n", dd->dead);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of dead ZDD nodes: %u\n", dd->deadZ);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Total number of nodes allocated: %d\n", (int)dd->allocated);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Total number of nodes reclaimed: %.0f\n",
+                     dd->reclaimed);
+    if (retval == EOF) return(0);
+#ifdef DD_STATS
+    retval = fprintf(fp,"Nodes freed: %.0f\n", dd->nodesFreed);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Nodes dropped: %.0f\n", dd->nodesDropped);
+    if (retval == EOF) return(0);
+#endif
+#ifdef DD_COUNT
+    retval = fprintf(fp,"Number of recursive calls: %.0f\n",
+                     Cudd_ReadRecursiveCalls(dd));
+    if (retval == EOF) return(0);
+#endif
+    retval = fprintf(fp,"Garbage collections so far: %d\n",
+                     Cudd_ReadGarbageCollections(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Time for garbage collection: %.2f sec\n",
+                     ((double)Cudd_ReadGarbageCollectionTime(dd)/1000.0));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Reorderings so far: %d\n", dd->reorderings);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Time for reordering: %.2f sec\n",
+                     ((double)Cudd_ReadReorderingTime(dd)/1000.0));
+    if (retval == EOF) return(0);
+#ifdef DD_COUNT
+    retval = fprintf(fp,"Node swaps in reordering: %.0f\n",
+        Cudd_ReadSwapSteps(dd));
+    if (retval == EOF) return(0);
+#endif
+
+    return(1);
+
+} /* end of Cudd_PrintInfo */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reports the peak number of nodes.]
+
+  Description [Reports the peak number of nodes. This number includes
+  node on the free list. At the peak, the number of nodes on the free
+  list is guaranteed to be less than DD_MEM_CHUNK.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadNodeCount Cudd_PrintInfo]
+
+******************************************************************************/
+long
+Cudd_ReadPeakNodeCount(
+  DdManager * dd)
+{
+    long count = 0;
+    DdNodePtr *scan = dd->memoryList;
+
+    while (scan != NULL) {
+        count += DD_MEM_CHUNK;
+        scan = (DdNodePtr *) *scan;
+    }
+    return(count);
+
+} /* end of Cudd_ReadPeakNodeCount */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reports the peak number of live nodes.]
+
+  Description [Reports the peak number of live nodes. This count is kept
+  only if CUDD is compiled with DD_STATS defined. If DD_STATS is not
+  defined, this function returns -1.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadNodeCount Cudd_PrintInfo Cudd_ReadPeakNodeCount]
+
+******************************************************************************/
+int
+Cudd_ReadPeakLiveNodeCount(
+  DdManager * dd)
+{
+    unsigned int live = dd->keys - dd->dead;
+
+    if (live > dd->peakLiveNodes) {
+        dd->peakLiveNodes = live;
+    }
+    return((int)dd->peakLiveNodes);
+
+} /* end of Cudd_ReadPeakLiveNodeCount */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reports the number of nodes in BDDs and ADDs.]
+
+  Description [Reports the number of live nodes in BDDs and ADDs. This
+  number does not include the isolated projection functions and the
+  unused constants. These nodes that are not counted are not part of
+  the DDs manipulated by the application.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadPeakNodeCount Cudd_zddReadNodeCount]
+
+******************************************************************************/
+long
+Cudd_ReadNodeCount(
+  DdManager * dd)
+{
+    long count;
+    int i;
+
+#ifndef DD_NO_DEATH_ROW
+    cuddClearDeathRow(dd);
+#endif
+
+    count = (long) (dd->keys - dd->dead);
+
+    /* Count isolated projection functions. Their number is subtracted
+    ** from the node count because they are not part of the BDDs.
+    */
+    for (i=0; i < dd->size; i++) {
+        if (dd->vars[i]->ref == 1) count--;
+    }
+    /* Subtract from the count the unused constants. */
+    if (DD_ZERO(dd)->ref == 1) count--;
+    if (DD_PLUS_INFINITY(dd)->ref == 1) count--;
+    if (DD_MINUS_INFINITY(dd)->ref == 1) count--;
+
+    return(count);
+
+} /* end of Cudd_ReadNodeCount */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reports the number of nodes in ZDDs.]
+
+  Description [Reports the number of nodes in ZDDs. This
+  number always includes the two constants 1 and 0.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadPeakNodeCount Cudd_ReadNodeCount]
+
+******************************************************************************/
+long
+Cudd_zddReadNodeCount(
+  DdManager * dd)
+{
+    return((long)(dd->keysZ - dd->deadZ + 2));
+
+} /* end of Cudd_zddReadNodeCount */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a function to a hook.]
+
+  Description [Adds a function to a hook. A hook is a list of
+  application-provided functions called on certain occasions by the
+  package. Returns 1 if the function is successfully added; 2 if the
+  function was already in the list; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_RemoveHook]
+
+******************************************************************************/
+int
+Cudd_AddHook(
+  DdManager * dd,
+  DD_HFP f,
+  Cudd_HookType where)
+{
+    DdHook **hook, *nextHook, *newHook;
+
+    switch (where) {
+    case CUDD_PRE_GC_HOOK:
+        hook = &(dd->preGCHook);
+        break;
+    case CUDD_POST_GC_HOOK:
+        hook = &(dd->postGCHook);
+        break;
+    case CUDD_PRE_REORDERING_HOOK:
+        hook = &(dd->preReorderingHook);
+        break;
+    case CUDD_POST_REORDERING_HOOK:
+        hook = &(dd->postReorderingHook);
+        break;
+    default:
+        return(0);
+    }
+    /* Scan the list and find whether the function is already there.
+    ** If so, just return. */
+    nextHook = *hook;
+    while (nextHook != NULL) {
+        if (nextHook->f == f) {
+            return(2);
+        }
+        hook = &(nextHook->next);
+        nextHook = nextHook->next;
+    }
+    /* The function was not in the list. Create a new item and append it
+    ** to the end of the list. */
+    newHook = ABC_ALLOC(DdHook,1);
+    if (newHook == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    newHook->next = NULL;
+    newHook->f = f;
+    *hook = newHook;
+    return(1);
+
+} /* end of Cudd_AddHook */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Removes a function from a hook.]
+
+  Description [Removes a function from a hook. A hook is a list of
+  application-provided functions called on certain occasions by the
+  package. Returns 1 if successful; 0 the function was not in the list.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_AddHook]
+
+******************************************************************************/
+int
+Cudd_RemoveHook(
+  DdManager * dd,
+  DD_HFP f,
+  Cudd_HookType where)
+{
+    DdHook **hook, *nextHook;
+
+    switch (where) {
+    case CUDD_PRE_GC_HOOK:
+        hook = &(dd->preGCHook);
+        break;
+    case CUDD_POST_GC_HOOK:
+        hook = &(dd->postGCHook);
+        break;
+    case CUDD_PRE_REORDERING_HOOK:
+        hook = &(dd->preReorderingHook);
+        break;
+    case CUDD_POST_REORDERING_HOOK:
+        hook = &(dd->postReorderingHook);
+        break;
+    default:
+        return(0);
+    }
+    nextHook = *hook;
+    while (nextHook != NULL) {
+        if (nextHook->f == f) {
+            *hook = nextHook->next;
+            ABC_FREE(nextHook);
+            return(1);
+        }
+        hook = &(nextHook->next);
+        nextHook = nextHook->next;
+    }
+
+    return(0);
+
+} /* end of Cudd_RemoveHook */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a function is in a hook.]
+
+  Description [Checks whether a function is in a hook. A hook is a list of
+  application-provided functions called on certain occasions by the
+  package. Returns 1 if the function is found; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_AddHook Cudd_RemoveHook]
+
+******************************************************************************/
+int
+Cudd_IsInHook(
+  DdManager * dd,
+  DD_HFP f,
+  Cudd_HookType where)
+{
+    DdHook *hook;
+
+    switch (where) {
+    case CUDD_PRE_GC_HOOK:
+        hook = dd->preGCHook;
+        break;
+    case CUDD_POST_GC_HOOK:
+        hook = dd->postGCHook;
+        break;
+    case CUDD_PRE_REORDERING_HOOK:
+        hook = dd->preReorderingHook;
+        break;
+    case CUDD_POST_REORDERING_HOOK:
+        hook = dd->postReorderingHook;
+        break;
+    default:
+        return(0);
+    }
+    /* Scan the list and find whether the function is already there. */
+    while (hook != NULL) {
+        if (hook->f == f) {
+            return(1);
+        }
+        hook = hook->next;
+    }
+    return(0);
+
+} /* end of Cudd_IsInHook */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sample hook function to call before reordering.]
+
+  Description [Sample hook function to call before reordering.
+  Prints on the manager's stdout reordering method and initial size.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_StdPostReordHook]
+
+******************************************************************************/
+int
+Cudd_StdPreReordHook(
+  DdManager *dd,
+  const char *str,
+  void *data)
+{
+    Cudd_ReorderingType method = (Cudd_ReorderingType) (ptruint) data;
+    int retval;
+
+    retval = fprintf(dd->out,"%s reordering with ", str);
+    if (retval == EOF) return(0);
+    switch (method) {
+    case CUDD_REORDER_SIFT_CONVERGE:
+    case CUDD_REORDER_SYMM_SIFT_CONV:
+    case CUDD_REORDER_GROUP_SIFT_CONV:
+    case CUDD_REORDER_WINDOW2_CONV:
+    case CUDD_REORDER_WINDOW3_CONV:
+    case CUDD_REORDER_WINDOW4_CONV:
+    case CUDD_REORDER_LINEAR_CONVERGE:
+        retval = fprintf(dd->out,"converging ");
+        if (retval == EOF) return(0);
+        break;
+    default:
+        break;
+    }
+    switch (method) {
+    case CUDD_REORDER_RANDOM:
+    case CUDD_REORDER_RANDOM_PIVOT:
+        retval = fprintf(dd->out,"random");
+        break;
+    case CUDD_REORDER_SIFT:
+    case CUDD_REORDER_SIFT_CONVERGE:
+        retval = fprintf(dd->out,"sifting");
+        break;
+    case CUDD_REORDER_SYMM_SIFT:
+    case CUDD_REORDER_SYMM_SIFT_CONV:
+        retval = fprintf(dd->out,"symmetric sifting");
+        break;
+    case CUDD_REORDER_LAZY_SIFT:
+        retval = fprintf(dd->out,"lazy sifting");
+        break;
+    case CUDD_REORDER_GROUP_SIFT:
+    case CUDD_REORDER_GROUP_SIFT_CONV:
+        retval = fprintf(dd->out,"group sifting");
+        break;
+    case CUDD_REORDER_WINDOW2:
+    case CUDD_REORDER_WINDOW3:
+    case CUDD_REORDER_WINDOW4:
+    case CUDD_REORDER_WINDOW2_CONV:
+    case CUDD_REORDER_WINDOW3_CONV:
+    case CUDD_REORDER_WINDOW4_CONV:
+        retval = fprintf(dd->out,"window");
+        break;
+    case CUDD_REORDER_ANNEALING:
+        retval = fprintf(dd->out,"annealing");
+        break;
+    case CUDD_REORDER_GENETIC:
+        retval = fprintf(dd->out,"genetic");
+        break;
+    case CUDD_REORDER_LINEAR:
+    case CUDD_REORDER_LINEAR_CONVERGE:
+        retval = fprintf(dd->out,"linear sifting");
+        break;
+    case CUDD_REORDER_EXACT:
+        retval = fprintf(dd->out,"exact");
+        break;
+    default:
+        return(0);
+    }
+    if (retval == EOF) return(0);
+
+    retval = fprintf(dd->out,": from %ld to ... ", strcmp(str, "BDD") == 0 ?
+                     Cudd_ReadNodeCount(dd) : Cudd_zddReadNodeCount(dd));
+    if (retval == EOF) return(0);
+    fflush(dd->out);
+    return(1);
+
+} /* end of Cudd_StdPreReordHook */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sample hook function to call after reordering.]
+
+  Description [Sample hook function to call after reordering.
+  Prints on the manager's stdout final size and reordering time.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_StdPreReordHook]
+
+******************************************************************************/
+int
+Cudd_StdPostReordHook(
+  DdManager *dd,
+  const char *str,
+  void *data)
+{
+    long initialTime = (long) data;
+    int retval;
+    long finalTime = util_cpu_time();
+    double totalTimeSec = (double)(finalTime - initialTime) / 1000.0;
+
+    retval = fprintf(dd->out,"%ld nodes in %g sec\n", strcmp(str, "BDD") == 0 ?
+                     Cudd_ReadNodeCount(dd) : Cudd_zddReadNodeCount(dd),
+                     totalTimeSec);
+    if (retval == EOF) return(0);
+    retval = fflush(dd->out);
+    if (retval == EOF) return(0);
+    return(1);
+
+} /* end of Cudd_StdPostReordHook */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Enables reporting of reordering stats.]
+
+  Description [Enables reporting of reordering stats.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [Installs functions in the pre-reordering and post-reordering
+  hooks.]
+
+  SeeAlso     [Cudd_DisableReorderingReporting Cudd_ReorderingReporting]
+
+******************************************************************************/
+int
+Cudd_EnableReorderingReporting(
+  DdManager *dd)
+{
+    if (!Cudd_AddHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)) {
+        return(0);
+    }
+    if (!Cudd_AddHook(dd, Cudd_StdPostReordHook, CUDD_POST_REORDERING_HOOK)) {
+        return(0);
+    }
+    return(1);
+
+} /* end of Cudd_EnableReorderingReporting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disables reporting of reordering stats.]
+
+  Description [Disables reporting of reordering stats.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [Removes functions from the pre-reordering and post-reordering
+  hooks.]
+
+  SeeAlso     [Cudd_EnableReorderingReporting Cudd_ReorderingReporting]
+
+******************************************************************************/
+int
+Cudd_DisableReorderingReporting(
+  DdManager *dd)
+{
+    if (!Cudd_RemoveHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)) {
+        return(0);
+    }
+    if (!Cudd_RemoveHook(dd, Cudd_StdPostReordHook, CUDD_POST_REORDERING_HOOK)) {
+        return(0);
+    }
+    return(1);
+
+} /* end of Cudd_DisableReorderingReporting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if reporting of reordering stats is enabled.]
+
+  Description [Returns 1 if reporting of reordering stats is enabled;
+  0 otherwise.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_EnableReorderingReporting Cudd_DisableReorderingReporting]
+
+******************************************************************************/
+int
+Cudd_ReorderingReporting(
+  DdManager *dd)
+{
+    return(Cudd_IsInHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK));
+
+} /* end of Cudd_ReorderingReporting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the code of the last error.]
+
+  Description [Returns the code of the last error. The error codes are
+  defined in cudd.h.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ClearErrorCode]
+
+******************************************************************************/
+Cudd_ErrorType
+Cudd_ReadErrorCode(
+  DdManager *dd)
+{
+    return(dd->errorCode);
+
+} /* end of Cudd_ReadErrorCode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Clear the error code of a manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadErrorCode]
+
+******************************************************************************/
+void
+Cudd_ClearErrorCode(
+  DdManager *dd)
+{
+    dd->errorCode = CUDD_NO_ERROR;
+
+} /* end of Cudd_ClearErrorCode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the stdout of a manager.]
+
+  Description [Reads the stdout of a manager. This is the file pointer to
+  which messages normally going to stdout are written. It is initialized
+  to stdout. Cudd_SetStdout allows the application to redirect it.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetStdout Cudd_ReadStderr]
+
+******************************************************************************/
+FILE *
+Cudd_ReadStdout(
+  DdManager *dd)
+{
+    return(dd->out);
+
+} /* end of Cudd_ReadStdout */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the stdout of a manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadStdout Cudd_SetStderr]
+
+******************************************************************************/
+void
+Cudd_SetStdout(
+  DdManager *dd,
+  FILE *fp)
+{
+    dd->out = fp;
+
+} /* end of Cudd_SetStdout */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the stderr of a manager.]
+
+  Description [Reads the stderr of a manager. This is the file pointer to
+  which messages normally going to stderr are written. It is initialized
+  to stderr. Cudd_SetStderr allows the application to redirect it.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetStderr Cudd_ReadStdout]
+
+******************************************************************************/
+FILE *
+Cudd_ReadStderr(
+  DdManager *dd)
+{
+    return(dd->err);
+
+} /* end of Cudd_ReadStderr */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the stderr of a manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadStderr Cudd_SetStdout]
+
+******************************************************************************/
+void
+Cudd_SetStderr(
+  DdManager *dd,
+  FILE *fp)
+{
+    dd->err = fp;
+
+} /* end of Cudd_SetStderr */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the threshold for the next dynamic reordering.]
+
+  Description [Returns the threshold for the next dynamic reordering.
+  The threshold is in terms of number of nodes and is in effect only
+  if reordering is enabled. The count does not include the dead nodes,
+  unless the countDead parameter of the manager has been changed from
+  its default setting.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetNextReordering]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadNextReordering(
+  DdManager *dd)
+{
+    return(dd->nextDyn);
+
+} /* end of Cudd_ReadNextReordering */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the threshold for the next dynamic reordering.]
+
+  Description [Sets the threshold for the next dynamic reordering.
+  The threshold is in terms of number of nodes and is in effect only
+  if reordering is enabled. The count does not include the dead nodes,
+  unless the countDead parameter of the manager has been changed from
+  its default setting.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadNextReordering]
+
+******************************************************************************/
+void
+Cudd_SetNextReordering(
+  DdManager *dd,
+  unsigned int next)
+{
+    dd->nextDyn = next;
+
+} /* end of Cudd_SetNextReordering */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the number of elementary reordering steps.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+double
+Cudd_ReadSwapSteps(
+  DdManager *dd)
+{
+#ifdef DD_COUNT
+    return(dd->swapSteps);
+#else
+    return(-1);
+#endif
+
+} /* end of Cudd_ReadSwapSteps */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the maximum allowed number of live nodes.]
+
+  Description [Reads the maximum allowed number of live nodes. When this
+  number is exceeded, the package returns NULL.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_SetMaxLive]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadMaxLive(
+  DdManager *dd)
+{
+    return(dd->maxLive);
+
+} /* end of Cudd_ReadMaxLive */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the maximum allowed number of live nodes.]
+
+  Description [Sets the maximum allowed number of live nodes. When this
+  number is exceeded, the package returns NULL.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_ReadMaxLive]
+
+******************************************************************************/
+void
+Cudd_SetMaxLive(
+  DdManager *dd,
+  unsigned int maxLive)
+{
+    dd->maxLive = maxLive;
+
+} /* end of Cudd_SetMaxLive */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the maximum allowed memory.]
+
+  Description [Reads the maximum allowed memory. When this
+  number is exceeded, the package returns NULL.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_SetMaxMemory]
+
+******************************************************************************/
+unsigned long
+Cudd_ReadMaxMemory(
+  DdManager *dd)
+{
+    return(dd->maxmemhard);
+
+} /* end of Cudd_ReadMaxMemory */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the maximum allowed memory.]
+
+  Description [Sets the maximum allowed memory. When this
+  number is exceeded, the package returns NULL.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_ReadMaxMemory]
+
+******************************************************************************/
+void
+Cudd_SetMaxMemory(
+  DdManager *dd,
+  unsigned long maxMemory)
+{
+    dd->maxmemhard = maxMemory;
+
+} /* end of Cudd_SetMaxMemory */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prevents sifting of a variable.]
+
+  Description [This function sets a flag to prevent sifting of a
+  variable.  Returns 1 if successful; 0 otherwise (i.e., invalid
+  variable index).]
+
+  SideEffects [Changes the "bindVar" flag in DdSubtable.]
+
+  SeeAlso     [Cudd_bddUnbindVar]
+
+******************************************************************************/
+int
+Cudd_bddBindVar(
+  DdManager *dd /* manager */,
+  int index /* variable index */)
+{
+    if (index >= dd->size || index < 0) return(0);
+    dd->subtables[dd->perm[index]].bindVar = 1;
+    return(1);
+
+} /* end of Cudd_bddBindVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allows the sifting of a variable.]
+
+  Description [This function resets the flag that prevents the sifting
+  of a variable. In successive variable reorderings, the variable will
+  NOT be skipped, that is, sifted.  Initially all variables can be
+  sifted. It is necessary to call this function only to re-enable
+  sifting after a call to Cudd_bddBindVar. Returns 1 if successful; 0
+  otherwise (i.e., invalid variable index).]
+
+  SideEffects [Changes the "bindVar" flag in DdSubtable.]
+
+  SeeAlso     [Cudd_bddBindVar]
+
+******************************************************************************/
+int
+Cudd_bddUnbindVar(
+  DdManager *dd /* manager */,
+  int index /* variable index */)
+{
+    if (index >= dd->size || index < 0) return(0);
+    dd->subtables[dd->perm[index]].bindVar = 0;
+    return(1);
+
+} /* end of Cudd_bddUnbindVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tells whether a variable can be sifted.]
+
+  Description [This function returns 1 if a variable is enabled for
+  sifting.  Initially all variables can be sifted. This function returns
+  0 only if there has been a previous call to Cudd_bddBindVar for that
+  variable not followed by a call to Cudd_bddUnbindVar. The function returns
+  0 also in the case in which the index of the variable is out of bounds.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_bddBindVar Cudd_bddUnbindVar]
+
+******************************************************************************/
+int
+Cudd_bddVarIsBound(
+  DdManager *dd /* manager */,
+  int index /* variable index */)
+{
+    if (index >= dd->size || index < 0) return(0);
+    return(dd->subtables[dd->perm[index]].bindVar);
+
+} /* end of Cudd_bddVarIsBound */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable type to primary input.]
+
+  Description [Sets a variable type to primary input.  The variable type is
+  used by lazy sifting.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddSetPsVar Cudd_bddSetNsVar Cudd_bddIsPiVar]
+
+******************************************************************************/
+int
+Cudd_bddSetPiVar(
+  DdManager *dd /* manager */,
+  int index /* variable index */)
+{
+    if (index >= dd->size || index < 0) return (0);
+    dd->subtables[dd->perm[index]].varType = CUDD_VAR_PRIMARY_INPUT;
+    return(1);
+
+} /* end of Cudd_bddSetPiVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable type to present state.]
+
+  Description [Sets a variable type to present state.  The variable type is
+  used by lazy sifting.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddSetPiVar Cudd_bddSetNsVar Cudd_bddIsPsVar]
+
+******************************************************************************/
+int
+Cudd_bddSetPsVar(
+  DdManager *dd /* manager */,
+  int index /* variable index */)
+{
+    if (index >= dd->size || index < 0) return (0);
+    dd->subtables[dd->perm[index]].varType = CUDD_VAR_PRESENT_STATE;
+    return(1);
+
+} /* end of Cudd_bddSetPsVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable type to next state.]
+
+  Description [Sets a variable type to next state.  The variable type is
+  used by lazy sifting.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddSetPiVar Cudd_bddSetPsVar Cudd_bddIsNsVar]
+
+******************************************************************************/
+int
+Cudd_bddSetNsVar(
+  DdManager *dd /* manager */,
+  int index /* variable index */)
+{
+    if (index >= dd->size || index < 0) return (0);
+    dd->subtables[dd->perm[index]].varType = CUDD_VAR_NEXT_STATE;
+    return(1);
+
+} /* end of Cudd_bddSetNsVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is primary input.]
+
+  Description [Checks whether a variable is primary input.  Returns 1 if
+  the variable's type is primary input; 0 if the variable exists but is
+  not a primary input; -1 if the variable does not exist.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_bddSetPiVar Cudd_bddIsPsVar Cudd_bddIsNsVar]
+
+******************************************************************************/
+int
+Cudd_bddIsPiVar(
+  DdManager *dd /* manager */,
+  int index /* variable index */)
+{
+    if (index >= dd->size || index < 0) return -1;
+    return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_PRIMARY_INPUT);
+
+} /* end of Cudd_bddIsPiVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is present state.]
+
+  Description [Checks whether a variable is present state.  Returns 1 if
+  the variable's type is present state; 0 if the variable exists but is
+  not a present state; -1 if the variable does not exist.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_bddSetPsVar Cudd_bddIsPiVar Cudd_bddIsNsVar]
+
+******************************************************************************/
+int
+Cudd_bddIsPsVar(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return -1;
+    return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_PRESENT_STATE);
+
+} /* end of Cudd_bddIsPsVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is next state.]
+
+  Description [Checks whether a variable is next state.  Returns 1 if
+  the variable's type is present state; 0 if the variable exists but is
+  not a present state; -1 if the variable does not exist.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_bddSetNsVar Cudd_bddIsPiVar Cudd_bddIsPsVar]
+
+******************************************************************************/
+int
+Cudd_bddIsNsVar(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return -1;
+    return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_NEXT_STATE);
+
+} /* end of Cudd_bddIsNsVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a corresponding pair index for a given index.]
+
+  Description [Sets a corresponding pair index for a given index.
+  These pair indices are present and next state variable.  Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddReadPairIndex]
+
+******************************************************************************/
+int
+Cudd_bddSetPairIndex(
+  DdManager *dd /* manager */,
+  int index /* variable index */,
+  int pairIndex /* corresponding variable index */)
+{
+    if (index >= dd->size || index < 0) return(0);
+    dd->subtables[dd->perm[index]].pairIndex = pairIndex;
+    return(1);
+
+} /* end of Cudd_bddSetPairIndex */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads a corresponding pair index for a given index.]
+
+  Description [Reads a corresponding pair index for a given index.
+  These pair indices are present and next state variable.  Returns the
+  corresponding variable index if the variable exists; -1 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddSetPairIndex]
+
+******************************************************************************/
+int
+Cudd_bddReadPairIndex(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return -1;
+    return dd->subtables[dd->perm[index]].pairIndex;
+
+} /* end of Cudd_bddReadPairIndex */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable to be grouped.]
+
+  Description [Sets a variable to be grouped. This function is used for
+  lazy sifting.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddSetVarHardGroup Cudd_bddResetVarToBeGrouped]
+
+******************************************************************************/
+int
+Cudd_bddSetVarToBeGrouped(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(0);
+    if (dd->subtables[dd->perm[index]].varToBeGrouped <= CUDD_LAZY_SOFT_GROUP) {
+        dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_SOFT_GROUP;
+    }
+    return(1);
+
+} /* end of Cudd_bddSetVarToBeGrouped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable to be a hard group.]
+
+  Description [Sets a variable to be a hard group.  This function is used
+  for lazy sifting.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddSetVarToBeGrouped Cudd_bddResetVarToBeGrouped
+  Cudd_bddIsVarHardGroup]
+
+******************************************************************************/
+int
+Cudd_bddSetVarHardGroup(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(0);
+    dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_HARD_GROUP;
+    return(1);
+
+} /* end of Cudd_bddSetVarHardGrouped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resets a variable not to be grouped.]
+
+  Description [Resets a variable not to be grouped.  This function is
+  used for lazy sifting.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddSetVarToBeGrouped Cudd_bddSetVarHardGroup]
+
+******************************************************************************/
+int
+Cudd_bddResetVarToBeGrouped(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(0);
+    if (dd->subtables[dd->perm[index]].varToBeGrouped <=
+        CUDD_LAZY_SOFT_GROUP) {
+        dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_NONE;
+    }
+    return(1);
+
+} /* end of Cudd_bddResetVarToBeGrouped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is set to be grouped.]
+
+  Description [Checks whether a variable is set to be grouped. This
+  function is used for lazy sifting.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_bddIsVarToBeGrouped(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(-1);
+    if (dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_UNGROUP)
+        return(0);
+    else
+        return(dd->subtables[dd->perm[index]].varToBeGrouped);
+
+} /* end of Cudd_bddIsVarToBeGrouped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable to be ungrouped.]
+
+  Description [Sets a variable to be ungrouped. This function is used
+  for lazy sifting.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddIsVarToBeUngrouped]
+
+******************************************************************************/
+int
+Cudd_bddSetVarToBeUngrouped(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(0);
+    dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_UNGROUP;
+    return(1);
+
+} /* end of Cudd_bddSetVarToBeGrouped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is set to be ungrouped.]
+
+  Description [Checks whether a variable is set to be ungrouped. This
+  function is used for lazy sifting.  Returns 1 if the variable is marked
+  to be ungrouped; 0 if the variable exists, but it is not marked to be
+  ungrouped; -1 if the variable does not exist.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_bddSetVarToBeUngrouped]
+
+******************************************************************************/
+int
+Cudd_bddIsVarToBeUngrouped(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(-1);
+    return dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_UNGROUP;
+
+} /* end of Cudd_bddIsVarToBeGrouped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is set to be in a hard group.]
+
+  Description [Checks whether a variable is set to be in a hard group.  This
+  function is used for lazy sifting.  Returns 1 if the variable is marked
+  to be in a hard group; 0 if the variable exists, but it is not marked to be
+  in a hard group; -1 if the variable does not exist.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_bddSetVarHardGroup]
+
+******************************************************************************/
+int
+Cudd_bddIsVarHardGroup(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(-1);
+    if (dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_HARD_GROUP)
+        return(1);
+    return(0);
+
+} /* end of Cudd_bddIsVarToBeGrouped */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Fixes a variable group tree.]
+
+  Description []
+
+  SideEffects [Changes the variable group tree.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+fixVarTree(
+  MtrNode * treenode,
+  int * perm,
+  int  size)
+{
+    treenode->index = treenode->low;
+    treenode->low = ((int) treenode->index < size) ?
+        perm[treenode->index] : treenode->index;
+    if (treenode->child != NULL)
+        fixVarTree(treenode->child, perm, size);
+    if (treenode->younger != NULL)
+        fixVarTree(treenode->younger, perm, size);
+    return;
+
+} /* end of fixVarTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds multiplicity groups to a ZDD variable group tree.]
+
+  Description [Adds multiplicity groups to a ZDD variable group tree.
+  Returns 1 if successful; 0 otherwise. This function creates the groups
+  for set of ZDD variables (whose cardinality is given by parameter
+  multiplicity) that are created for each BDD variable in
+  Cudd_zddVarsFromBddVars. The crux of the matter is to determine the index
+  each new group. (The index of the first variable in the group.)
+  We first build all the groups for the children of a node, and then deal
+  with the ZDD variables that are directly attached to the node. The problem
+  for these is that the tree itself does not provide information on their
+  position inside the group. While we deal with the children of the node,
+  therefore, we keep track of all the positions they occupy. The remaining
+  positions in the tree can be freely used. Also, we keep track of all the
+  variables placed in the children. All the remaining variables are directly
+  attached to the group. We can then place any pair of variables not yet
+  grouped in any pair of available positions in the node.]
+
+  SideEffects [Changes the variable group tree.]
+
+  SeeAlso     [Cudd_zddVarsFromBddVars]
+
+******************************************************************************/
+static int
+addMultiplicityGroups(
+  DdManager *dd /* manager */,
+  MtrNode *treenode /* current tree node */,
+  int multiplicity /* how many ZDD vars per BDD var */,
+  char *vmask /* variable pairs for which a group has been already built */,
+  char *lmask /* levels for which a group has already been built*/)
+{
+    int startV, stopV, startL;
+    int i, j;
+    MtrNode *auxnode = treenode;
+
+    while (auxnode != NULL) {
+        if (auxnode->child != NULL) {
+            addMultiplicityGroups(dd,auxnode->child,multiplicity,vmask,lmask);
+        }
+        /* Build remaining groups. */
+        startV = dd->permZ[auxnode->index] / multiplicity;
+        startL = auxnode->low / multiplicity;
+        stopV = startV + auxnode->size / multiplicity;
+        /* Walk down vmask starting at startV and build missing groups. */
+        for (i = startV, j = startL; i < stopV; i++) {
+            if (vmask[i] == 0) {
+                MtrNode *node;
+                while (lmask[j] == 1) j++;
+                node = Mtr_MakeGroup(auxnode, j * multiplicity, multiplicity,
+                                     MTR_FIXED);
+                if (node == NULL) {
+                    return(0);
+                }
+                node->index = dd->invpermZ[i * multiplicity];
+                vmask[i] = 1;
+                lmask[j] = 1;
+            }
+        }
+        auxnode = auxnode->younger;
+    }
+    return(1);
+
+} /* end of addMultiplicityGroups */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddAddAbs.c b/abc-build/src/bdd/cudd/cuddAddAbs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddAddAbs.c
@@ -0,0 +1,588 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAddAbs.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Quantification functions for ADDs.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_addExistAbstract()
+                <li> Cudd_addUnivAbstract()
+                <li> Cudd_addOrAbstract()
+                </ul>
+        Internal procedures included in this module:
+                <ul>
+                <li> cuddAddExistAbstractRecur()
+                <li> cuddAddUnivAbstractRecur()
+                <li> cuddAddOrAbstractRecur()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> addCheckPositiveCube()
+                </ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAddAbs.c,v 1.15 2004/08/13 18:04:45 fabio Exp $";
+#endif
+
+static  DdNode  *two;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int addCheckPositiveCube (DdManager *manager, DdNode *cube);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Existentially Abstracts all the variables in cube from f.]
+
+  Description [Abstracts all the variables in cube from f by summing
+  over all possible values taken by the variables. Returns the
+  abstracted ADD.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addUnivAbstract Cudd_bddExistAbstract
+  Cudd_addOrAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_addExistAbstract(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode *res;
+
+    two = cuddUniqueConst(manager,(CUDD_VALUE_TYPE) 2);
+    if (two == NULL) return(NULL);
+    cuddRef(two);
+
+    if (addCheckPositiveCube(manager, cube) == 0) {
+        (void) fprintf(manager->err,"Error: Can only abstract cubes");
+        return(NULL);
+    }
+
+    do {
+        manager->reordered = 0;
+        res = cuddAddExistAbstractRecur(manager, f, cube);
+    } while (manager->reordered == 1);
+
+    if (res == NULL) {
+        Cudd_RecursiveDeref(manager,two);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(manager,two);
+    cuddDeref(res);
+
+    return(res);
+
+} /* end of Cudd_addExistAbstract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Universally Abstracts all the variables in cube from f.]
+
+  Description [Abstracts all the variables in cube from f by taking
+  the product over all possible values taken by the variable. Returns
+  the abstracted ADD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addExistAbstract Cudd_bddUnivAbstract
+  Cudd_addOrAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_addUnivAbstract(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode              *res;
+
+    if (addCheckPositiveCube(manager, cube) == 0) {
+        (void) fprintf(manager->err,"Error:  Can only abstract cubes");
+        return(NULL);
+    }
+
+    do {
+        manager->reordered = 0;
+        res = cuddAddUnivAbstractRecur(manager, f, cube);
+    } while (manager->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_addUnivAbstract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disjunctively abstracts all the variables in cube from the
+  0-1 ADD f.]
+
+  Description [Abstracts all the variables in cube from the 0-1 ADD f
+  by taking the disjunction over all possible values taken by the
+  variables.  Returns the abstracted ADD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addUnivAbstract Cudd_addExistAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_addOrAbstract(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode *res;
+
+    if (addCheckPositiveCube(manager, cube) == 0) {
+        (void) fprintf(manager->err,"Error: Can only abstract cubes");
+        return(NULL);
+    }
+
+    do {
+        manager->reordered = 0;
+        res = cuddAddOrAbstractRecur(manager, f, cube);
+    } while (manager->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addOrAbstract */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addExistAbstract.]
+
+  Description [Performs the recursive step of Cudd_addExistAbstract.
+  Returns the ADD obtained by abstracting the variables of cube from f,
+  if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddAddExistAbstractRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode      *T, *E, *res, *res1, *res2, *zero;
+
+    statLine(manager);
+    zero = DD_ZERO(manager);
+
+    /* Cube is guaranteed to be a cube at this point. */        
+    if (f == zero || cuddIsConstant(cube)) {  
+        return(f);
+    }
+
+    /* Abstract a variable that does not appear in f => multiply by 2. */
+    if (cuddI(manager,f->index) > cuddI(manager,cube->index)) {
+        res1 = cuddAddExistAbstractRecur(manager, f, cuddT(cube));
+        if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+        /* Use the "internal" procedure to be alerted in case of
+        ** dynamic reordering. If dynamic reordering occurs, we
+        ** have to abort the entire abstraction.
+        */
+        res = cuddAddApplyRecur(manager,Cudd_addTimes,res1,two);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            return(NULL);
+        }
+        cuddRef(res);
+        Cudd_RecursiveDeref(manager,res1);
+        cuddDeref(res);
+        return(res);
+    }
+
+    if ((res = cuddCacheLookup2(manager, Cudd_addExistAbstract, f, cube)) != NULL) {
+        return(res);
+    }
+
+    T = cuddT(f);
+    E = cuddE(f);
+
+    /* If the two indices are the same, so are their levels. */
+    if (f->index == cube->index) {
+        res1 = cuddAddExistAbstractRecur(manager, T, cuddT(cube));
+        if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+        res2 = cuddAddExistAbstractRecur(manager, E, cuddT(cube));
+        if (res2 == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            return(NULL);
+        }
+        cuddRef(res2);
+        res = cuddAddApplyRecur(manager, Cudd_addPlus, res1, res2);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            Cudd_RecursiveDeref(manager,res2);
+            return(NULL);
+        }
+        cuddRef(res);
+        Cudd_RecursiveDeref(manager,res1);
+        Cudd_RecursiveDeref(manager,res2);
+        cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res);
+        cuddDeref(res);
+        return(res);
+    } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
+        res1 = cuddAddExistAbstractRecur(manager, T, cube);
+        if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+        res2 = cuddAddExistAbstractRecur(manager, E, cube);
+        if (res2 == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            return(NULL);
+        }
+        cuddRef(res2);
+        res = (res1 == res2) ? res1 :
+            cuddUniqueInter(manager, (int) f->index, res1, res2);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            Cudd_RecursiveDeref(manager,res2);
+            return(NULL);
+        }
+        cuddDeref(res1);
+        cuddDeref(res2);
+        cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res);
+        return(res);
+    }       
+
+} /* end of cuddAddExistAbstractRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addUnivAbstract.]
+
+  Description [Performs the recursive step of Cudd_addUnivAbstract.
+  Returns the ADD obtained by abstracting the variables of cube from f,
+  if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddAddUnivAbstractRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode      *T, *E, *res, *res1, *res2, *one, *zero;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+    zero = DD_ZERO(manager);
+
+    /* Cube is guaranteed to be a cube at this point.
+    ** zero and one are the only constatnts c such that c*c=c.
+    */
+    if (f == zero || f == one || cube == one) {  
+        return(f);
+    }
+
+    /* Abstract a variable that does not appear in f. */
+    if (cuddI(manager,f->index) > cuddI(manager,cube->index)) {
+        res1 = cuddAddUnivAbstractRecur(manager, f, cuddT(cube));
+        if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+        /* Use the "internal" procedure to be alerted in case of
+        ** dynamic reordering. If dynamic reordering occurs, we
+        ** have to abort the entire abstraction.
+        */
+        res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res1);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            return(NULL);
+        }
+        cuddRef(res);
+        Cudd_RecursiveDeref(manager,res1);
+        cuddDeref(res);
+        return(res);
+    }
+
+    if ((res = cuddCacheLookup2(manager, Cudd_addUnivAbstract, f, cube)) != NULL) {
+        return(res);
+    }
+
+    T = cuddT(f);
+    E = cuddE(f);
+
+    /* If the two indices are the same, so are their levels. */
+    if (f->index == cube->index) {
+        res1 = cuddAddUnivAbstractRecur(manager, T, cuddT(cube));
+        if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+        res2 = cuddAddUnivAbstractRecur(manager, E, cuddT(cube));
+        if (res2 == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            return(NULL);
+        }
+        cuddRef(res2);
+        res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res2);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            Cudd_RecursiveDeref(manager,res2);
+            return(NULL);
+        }
+        cuddRef(res);
+        Cudd_RecursiveDeref(manager,res1);
+        Cudd_RecursiveDeref(manager,res2);
+        cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res);
+        cuddDeref(res);
+        return(res);
+    } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
+        res1 = cuddAddUnivAbstractRecur(manager, T, cube);
+        if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+        res2 = cuddAddUnivAbstractRecur(manager, E, cube);
+        if (res2 == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            return(NULL);
+        }
+        cuddRef(res2);
+        res = (res1 == res2) ? res1 :
+            cuddUniqueInter(manager, (int) f->index, res1, res2);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            Cudd_RecursiveDeref(manager,res2);
+            return(NULL);
+        }
+        cuddDeref(res1);
+        cuddDeref(res2);
+        cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res);
+        return(res);
+    }
+
+} /* end of cuddAddUnivAbstractRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addOrAbstract.]
+
+  Description [Performs the recursive step of Cudd_addOrAbstract.
+  Returns the ADD obtained by abstracting the variables of cube from f,
+  if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddAddOrAbstractRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode      *T, *E, *res, *res1, *res2, *one;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+
+    /* Cube is guaranteed to be a cube at this point. */
+    if (cuddIsConstant(f) || cube == one) {  
+        return(f);
+    }
+
+    /* Abstract a variable that does not appear in f. */
+    if (cuddI(manager,f->index) > cuddI(manager,cube->index)) {
+        res = cuddAddOrAbstractRecur(manager, f, cuddT(cube));
+        return(res);
+    }
+
+    if ((res = cuddCacheLookup2(manager, Cudd_addOrAbstract, f, cube)) != NULL) {
+        return(res);
+    }
+
+    T = cuddT(f);
+    E = cuddE(f);
+
+    /* If the two indices are the same, so are their levels. */
+    if (f->index == cube->index) {
+        res1 = cuddAddOrAbstractRecur(manager, T, cuddT(cube));
+        if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+        if (res1 != one) {
+            res2 = cuddAddOrAbstractRecur(manager, E, cuddT(cube));
+            if (res2 == NULL) {
+                Cudd_RecursiveDeref(manager,res1);
+                return(NULL);
+            }
+            cuddRef(res2);
+            res = cuddAddApplyRecur(manager, Cudd_addOr, res1, res2);
+            if (res == NULL) {
+                Cudd_RecursiveDeref(manager,res1);
+                Cudd_RecursiveDeref(manager,res2);
+                return(NULL);
+            }
+            cuddRef(res);
+            Cudd_RecursiveDeref(manager,res1);
+            Cudd_RecursiveDeref(manager,res2);
+        } else {
+            res = res1;
+        }
+        cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res);
+        cuddDeref(res);
+        return(res);
+    } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
+        res1 = cuddAddOrAbstractRecur(manager, T, cube);
+        if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+        res2 = cuddAddOrAbstractRecur(manager, E, cube);
+        if (res2 == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            return(NULL);
+        }
+        cuddRef(res2);
+        res = (res1 == res2) ? res1 :
+            cuddUniqueInter(manager, (int) f->index, res1, res2);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(manager,res1);
+            Cudd_RecursiveDeref(manager,res2);
+            return(NULL);
+        }
+        cuddDeref(res1);
+        cuddDeref(res2);
+        cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res);
+        return(res);
+    }
+
+} /* end of cuddAddOrAbstractRecur */
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether cube is an ADD representing the product
+  of positive literals.]
+
+  Description [Checks whether cube is an ADD representing the product of
+  positive literals. Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+addCheckPositiveCube(
+  DdManager * manager,
+  DdNode * cube)
+{
+    if (Cudd_IsComplement(cube)) return(0);
+    if (cube == DD_ONE(manager)) return(1);
+    if (cuddIsConstant(cube)) return(0);
+    if (cuddE(cube) == DD_ZERO(manager)) {
+        return(addCheckPositiveCube(manager, cuddT(cube)));
+    }
+    return(0);
+
+} /* end of addCheckPositiveCube */
+
+
+ABC_NAMESPACE_IMPL_END
+
+
+
diff --git a/abc-build/src/bdd/cudd/cuddAddApply.c b/abc-build/src/bdd/cudd/cuddAddApply.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddAddApply.c
@@ -0,0 +1,949 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAddApply.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Apply functions for ADDs and their operators.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_addApply()
+                <li> Cudd_addMonadicApply()
+                <li> Cudd_addPlus()
+                <li> Cudd_addTimes()
+                <li> Cudd_addThreshold()
+                <li> Cudd_addSetNZ()
+                <li> Cudd_addDivide()
+                <li> Cudd_addMinus()
+                <li> Cudd_addMinimum()
+                <li> Cudd_addMaximum()
+                <li> Cudd_addOneZeroMaximum()
+                <li> Cudd_addDiff()
+                <li> Cudd_addAgreement()
+                <li> Cudd_addOr()
+                <li> Cudd_addNand()
+                <li> Cudd_addNor()
+                <li> Cudd_addXor()
+                <li> Cudd_addXnor()
+                </ul>
+            Internal procedures included in this module:
+                <ul>
+                <li> cuddAddApplyRecur()
+                <li> cuddAddMonadicApplyRecur()
+                </ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAddApply.c,v 1.18 2009/02/19 16:15:26 fabio Exp $";
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Applies op to the corresponding discriminants of f and g.]
+
+  Description [Applies op to the corresponding discriminants of f and g.
+  Returns a pointer to the result if succssful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addMonadicApply Cudd_addPlus Cudd_addTimes
+  Cudd_addThreshold Cudd_addSetNZ Cudd_addDivide Cudd_addMinus Cudd_addMinimum
+  Cudd_addMaximum Cudd_addOneZeroMaximum Cudd_addDiff Cudd_addAgreement
+  Cudd_addOr Cudd_addNand Cudd_addNor Cudd_addXor Cudd_addXnor]
+
+******************************************************************************/
+DdNode *
+Cudd_addApply(
+  DdManager * dd,
+  DD_AOP op,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddAddApplyRecur(dd,op,f,g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addApply */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Integer and floating point addition.]
+
+  Description [Integer and floating point addition. Returns NULL if not
+  a terminal case; f+g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addPlus(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *res;
+    DdNode *F, *G;
+    CUDD_VALUE_TYPE value;
+
+    F = *f; G = *g;
+    if (F == DD_ZERO(dd)) return(G);
+    if (G == DD_ZERO(dd)) return(F);
+    if (cuddIsConstant(F) && cuddIsConstant(G)) {
+        value = cuddV(F)+cuddV(G);
+        res = cuddUniqueConst(dd,value);
+        return(res);
+    }
+    if (F > G) { /* swap f and g */
+        *f = G;
+        *g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addPlus */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Integer and floating point multiplication.]
+
+  Description [Integer and floating point multiplication. Returns NULL
+  if not a terminal case; f * g otherwise.  This function can be used also
+  to take the AND of two 0-1 ADDs.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addTimes(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *res;
+    DdNode *F, *G;
+    CUDD_VALUE_TYPE value;
+
+    F = *f; G = *g;
+    if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ZERO(dd));
+    if (F == DD_ONE(dd)) return(G);
+    if (G == DD_ONE(dd)) return(F);
+    if (cuddIsConstant(F) && cuddIsConstant(G)) {
+        value = cuddV(F)*cuddV(G);
+        res = cuddUniqueConst(dd,value);
+        return(res);
+    }
+    if (F > G) { /* swap f and g */
+        *f = G;
+        *g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addTimes */
+
+
+/**Function********************************************************************
+
+  Synopsis    [f if f&gt;=g; 0 if f&lt;g.]
+
+  Description [Threshold operator for Apply (f if f &gt;=g; 0 if f&lt;g).
+  Returns NULL if not a terminal case; f op g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addThreshold(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == G || F == DD_PLUS_INFINITY(dd)) return(F);
+    if (cuddIsConstant(F) && cuddIsConstant(G)) {
+        if (cuddV(F) >= cuddV(G)) {
+            return(F);
+        } else {
+            return(DD_ZERO(dd));
+        }
+    }
+    return(NULL);
+
+} /* end of Cudd_addThreshold */
+
+
+/**Function********************************************************************
+
+  Synopsis    [This operator sets f to the value of g wherever g != 0.]
+
+  Description [This operator sets f to the value of g wherever g != 0.
+  Returns NULL if not a terminal case; f op g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addSetNZ(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == G) return(F);
+    if (F == DD_ZERO(dd)) return(G);
+    if (G == DD_ZERO(dd)) return(F);
+    if (cuddIsConstant(G)) return(G);
+    return(NULL);
+
+} /* end of Cudd_addSetNZ */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Integer and floating point division.]
+
+  Description [Integer and floating point division. Returns NULL if not
+  a terminal case; f / g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addDivide(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *res;
+    DdNode *F, *G;
+    CUDD_VALUE_TYPE value;
+
+    F = *f; G = *g;
+    /* We would like to use F == G -> F/G == 1, but F and G may
+    ** contain zeroes. */
+    if (F == DD_ZERO(dd)) return(DD_ZERO(dd));
+    if (G == DD_ONE(dd)) return(F);
+    if (cuddIsConstant(F) && cuddIsConstant(G)) {
+        value = cuddV(F)/cuddV(G);
+        res = cuddUniqueConst(dd,value);
+        return(res);
+    }
+    return(NULL);
+
+} /* end of Cudd_addDivide */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Integer and floating point subtraction.]
+
+  Description [Integer and floating point subtraction. Returns NULL if
+  not a terminal case; f - g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addMinus(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *res;
+    DdNode *F, *G;
+    CUDD_VALUE_TYPE value;
+
+    F = *f; G = *g;
+    if (F == G) return(DD_ZERO(dd));
+    if (F == DD_ZERO(dd)) return(cuddAddNegateRecur(dd,G));
+    if (G == DD_ZERO(dd)) return(F);
+    if (cuddIsConstant(F) && cuddIsConstant(G)) {
+        value = cuddV(F)-cuddV(G);
+        res = cuddUniqueConst(dd,value);
+        return(res);
+    }
+    return(NULL);
+
+} /* end of Cudd_addMinus */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Integer and floating point min.]
+
+  Description [Integer and floating point min for Cudd_addApply.
+  Returns NULL if not a terminal case; min(f,g) otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addMinimum(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == DD_PLUS_INFINITY(dd)) return(G);
+    if (G == DD_PLUS_INFINITY(dd)) return(F);
+    if (F == G) return(F);
+#if 0
+    /* These special cases probably do not pay off. */
+    if (F == DD_MINUS_INFINITY(dd)) return(F);
+    if (G == DD_MINUS_INFINITY(dd)) return(G);
+#endif
+    if (cuddIsConstant(F) && cuddIsConstant(G)) {
+        if (cuddV(F) <= cuddV(G)) {
+            return(F);
+        } else {
+            return(G);
+        }
+    }
+    if (F > G) { /* swap f and g */
+        *f = G;
+        *g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addMinimum */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Integer and floating point max.]
+
+  Description [Integer and floating point max for Cudd_addApply.
+  Returns NULL if not a terminal case; max(f,g) otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addMaximum(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == G) return(F);
+    if (F == DD_MINUS_INFINITY(dd)) return(G);
+    if (G == DD_MINUS_INFINITY(dd)) return(F);
+#if 0
+    /* These special cases probably do not pay off. */
+    if (F == DD_PLUS_INFINITY(dd)) return(F);
+    if (G == DD_PLUS_INFINITY(dd)) return(G);
+#endif
+    if (cuddIsConstant(F) && cuddIsConstant(G)) {
+        if (cuddV(F) >= cuddV(G)) {
+            return(F);
+        } else {
+            return(G);
+        }
+    }
+    if (F > G) { /* swap f and g */
+        *f = G;
+        *g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addMaximum */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if f &gt; g and 0 otherwise.]
+
+  Description [Returns 1 if f &gt; g and 0 otherwise. Used in
+  conjunction with Cudd_addApply. Returns NULL if not a terminal
+  case.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addOneZeroMaximum(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+
+    if (*f == *g) return(DD_ZERO(dd));
+    if (*g == DD_PLUS_INFINITY(dd))
+        return DD_ZERO(dd);
+    if (cuddIsConstant(*f) && cuddIsConstant(*g)) {
+        if (cuddV(*f) > cuddV(*g)) {
+            return(DD_ONE(dd));
+        } else {
+            return(DD_ZERO(dd));
+        }
+    }
+
+    return(NULL);
+
+} /* end of Cudd_addOneZeroMaximum */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns plusinfinity if f=g; returns min(f,g) if f!=g.]
+
+  Description [Returns NULL if not a terminal case; f op g otherwise,
+  where f op g is plusinfinity if f=g; min(f,g) if f!=g.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addDiff(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == G) return(DD_PLUS_INFINITY(dd));
+    if (F == DD_PLUS_INFINITY(dd)) return(G);
+    if (G == DD_PLUS_INFINITY(dd)) return(F);
+    if (cuddIsConstant(F) && cuddIsConstant(G)) {
+        if (cuddV(F) != cuddV(G)) {
+            if (cuddV(F) < cuddV(G)) {
+                return(F);
+            } else {
+                return(G);
+            }
+        } else {
+            return(DD_PLUS_INFINITY(dd));
+        }
+    }
+    return(NULL);
+
+} /* end of Cudd_addDiff */
+
+
+/**Function********************************************************************
+
+  Synopsis    [f if f==g; background if f!=g.]
+
+  Description [Returns NULL if not a terminal case; f op g otherwise,
+  where f op g is f if f==g; background if f!=g.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addAgreement(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == G) return(F);
+    if (F == dd->background) return(F);
+    if (G == dd->background) return(G);
+    if (cuddIsConstant(F) && cuddIsConstant(G)) return(dd->background);
+    return(NULL);
+
+} /* end of Cudd_addAgreement */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disjunction of two 0-1 ADDs.]
+
+  Description [Disjunction of two 0-1 ADDs. Returns NULL
+  if not a terminal case; f OR g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addOr(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ONE(dd));
+    if (cuddIsConstant(F)) return(G);
+    if (cuddIsConstant(G)) return(F);
+    if (F == G) return(F);
+    if (F > G) { /* swap f and g */
+        *f = G;
+        *g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addOr */
+
+
+/**Function********************************************************************
+
+  Synopsis    [NAND of two 0-1 ADDs.]
+
+  Description [NAND of two 0-1 ADDs. Returns NULL
+  if not a terminal case; f NAND g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addNand(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ONE(dd));
+    if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
+    if (F > G) { /* swap f and g */
+        *f = G;
+        *g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addNand */
+
+
+/**Function********************************************************************
+
+  Synopsis    [NOR of two 0-1 ADDs.]
+
+  Description [NOR of two 0-1 ADDs. Returns NULL
+  if not a terminal case; f NOR g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addNor(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ZERO(dd));
+    if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ONE(dd));
+    if (F > G) { /* swap f and g */
+        *f = G;
+        *g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addNor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [XOR of two 0-1 ADDs.]
+
+  Description [XOR of two 0-1 ADDs. Returns NULL
+  if not a terminal case; f XOR g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addXor(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == G) return(DD_ZERO(dd));
+    if (F == DD_ONE(dd) && G == DD_ZERO(dd)) return(DD_ONE(dd));
+    if (G == DD_ONE(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd));
+    if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
+    if (F > G) { /* swap f and g */
+        *f = G;
+        *g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addXor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [XNOR of two 0-1 ADDs.]
+
+  Description [XNOR of two 0-1 ADDs. Returns NULL
+  if not a terminal case; f XNOR g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addXnor(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == G) return(DD_ONE(dd));
+    if (F == DD_ONE(dd) && G == DD_ONE(dd)) return(DD_ONE(dd));
+    if (G == DD_ZERO(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd));
+    if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
+    if (F > G) { /* swap f and g */
+        *f = G;
+        *g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addXnor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Applies op to the discriminants of f.]
+
+  Description [Applies op to the discriminants of f.
+  Returns a pointer to the result if succssful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply Cudd_addLog]
+
+******************************************************************************/
+DdNode *
+Cudd_addMonadicApply(
+  DdManager * dd,
+  DD_MAOP op,
+  DdNode * f)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddAddMonadicApplyRecur(dd,op,f);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addMonadicApply */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Natural logarithm of an ADD.]
+
+  Description [Natural logarithm of an ADDs. Returns NULL
+  if not a terminal case; log(f) otherwise.  The discriminants of f must
+  be positive double's.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addMonadicApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addLog(
+  DdManager * dd,
+  DdNode * f)
+{
+    if (cuddIsConstant(f)) {
+        CUDD_VALUE_TYPE value = log(cuddV(f));
+        DdNode *res = cuddUniqueConst(dd,value);
+        return(res);
+    }
+    return(NULL);
+
+} /* end of Cudd_addLog */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addApply.]
+
+  Description [Performs the recursive step of Cudd_addApply. Returns a
+  pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddAddMonadicApplyRecur]
+
+******************************************************************************/
+DdNode *
+cuddAddApplyRecur(
+  DdManager * dd,
+  DD_AOP op,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res,
+           *fv, *fvn, *gv, *gvn,
+           *T, *E;
+    unsigned int ford, gord;
+    unsigned int index;
+    DD_CTFP cacheOp;
+
+    /* Check terminal cases. Op may swap f and g to increase the
+     * cache hit rate.
+     */
+    statLine(dd);
+    res = (*op)(dd,&f,&g);
+    if (res != NULL) return(res);
+
+    /* Check cache. */
+    cacheOp = (DD_CTFP) op;
+    res = cuddCacheLookup2(dd,cacheOp,f,g);
+    if (res != NULL) return(res);
+
+    /* Recursive step. */
+    ford = cuddI(dd,f->index);
+    gord = cuddI(dd,g->index);
+    if (ford <= gord) {
+        index = f->index;
+        fv = cuddT(f);
+        fvn = cuddE(f);
+    } else {
+        index = g->index;
+        fv = fvn = f;
+    }
+    if (gord <= ford) {
+        gv = cuddT(g);
+        gvn = cuddE(g);
+    } else {
+        gv = gvn = g;
+    }
+
+    T = cuddAddApplyRecur(dd,op,fv,gv);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = cuddAddApplyRecur(dd,op,fvn,gvn);
+    if (E == NULL) {
+        Cudd_RecursiveDeref(dd,T);
+        return(NULL);
+    }
+    cuddRef(E);
+
+    res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E);
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd, T);
+        Cudd_RecursiveDeref(dd, E);
+        return(NULL);
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert2(dd,cacheOp,f,g,res);
+
+    return(res);
+
+} /* end of cuddAddApplyRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addMonadicApply.]
+
+  Description [Performs the recursive step of Cudd_addMonadicApply. Returns a
+  pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddAddApplyRecur]
+
+******************************************************************************/
+DdNode *
+cuddAddMonadicApplyRecur(
+  DdManager * dd,
+  DD_MAOP op,
+  DdNode * f)
+{
+    DdNode *res, *ft, *fe, *T, *E;
+    unsigned int index;
+
+    /* Check terminal cases. */
+    statLine(dd);
+    res = (*op)(dd,f);
+    if (res != NULL) return(res);
+
+    /* Check cache. */
+    res = cuddCacheLookup1(dd,op,f);
+    if (res != NULL) return(res);
+
+    /* Recursive step. */
+    index = f->index;
+    ft = cuddT(f);
+    fe = cuddE(f);
+
+    T = cuddAddMonadicApplyRecur(dd,op,ft);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = cuddAddMonadicApplyRecur(dd,op,fe);
+    if (E == NULL) {
+        Cudd_RecursiveDeref(dd,T);
+        return(NULL);
+    }
+    cuddRef(E);
+
+    res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E);
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd, T);
+        Cudd_RecursiveDeref(dd, E);
+        return(NULL);
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert1(dd,op,f,res);
+
+    return(res);
+
+} /* end of cuddAddMonadicApplyRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddAddFind.c b/abc-build/src/bdd/cudd/cuddAddFind.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddAddFind.c
@@ -0,0 +1,324 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAddFind.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions to find maximum and minimum in an ADD and to
+  extract the i-th bit.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_addFindMax()
+                <li> Cudd_addFindMin()
+                <li> Cudd_addIthBit()
+                </ul>
+               Static functions included in this module:
+                <ul>
+                <li> addDoIthBit()
+                </ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAddFind.c,v 1.8 2004/08/13 18:04:45 fabio Exp $";
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * addDoIthBit (DdManager *dd, DdNode *f, DdNode *index);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the maximum discriminant of f.]
+
+  Description [Returns a pointer to a constant ADD.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+Cudd_addFindMax(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *t, *e, *res;
+
+    statLine(dd);
+    if (cuddIsConstant(f)) {
+        return(f);
+    }
+
+    res = cuddCacheLookup1(dd,Cudd_addFindMax,f);
+    if (res != NULL) {
+        return(res);
+    }
+
+    t  = Cudd_addFindMax(dd,cuddT(f));
+    if (t == DD_PLUS_INFINITY(dd)) return(t);
+
+    e  = Cudd_addFindMax(dd,cuddE(f));
+
+    res = (cuddV(t) >= cuddV(e)) ? t : e;
+
+    cuddCacheInsert1(dd,Cudd_addFindMax,f,res);
+
+    return(res);
+
+} /* end of Cudd_addFindMax */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the minimum discriminant of f.]
+
+  Description [Returns a pointer to a constant ADD.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+Cudd_addFindMin(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *t, *e, *res;
+
+    statLine(dd);
+    if (cuddIsConstant(f)) {
+        return(f);
+    }
+
+    res = cuddCacheLookup1(dd,Cudd_addFindMin,f);
+    if (res != NULL) {
+        return(res);
+    }
+
+    t  = Cudd_addFindMin(dd,cuddT(f));
+    if (t == DD_MINUS_INFINITY(dd)) return(t);
+
+    e  = Cudd_addFindMin(dd,cuddE(f));
+
+    res = (cuddV(t) <= cuddV(e)) ? t : e;
+
+    cuddCacheInsert1(dd,Cudd_addFindMin,f,res);
+
+    return(res);
+
+} /* end of Cudd_addFindMin */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts the i-th bit from an ADD.]
+
+  Description [Produces an ADD from another ADD by replacing all
+  discriminants whose i-th bit is equal to 1 with 1, and all other
+  discriminants with 0. The i-th bit refers to the integer
+  representation of the leaf value. If the value is has a fractional
+  part, it is ignored. Repeated calls to this procedure allow one to
+  transform an integer-valued ADD into an array of ADDs, one for each
+  bit of the leaf values. Returns a pointer to the resulting ADD if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addBddIthBit]
+
+******************************************************************************/
+DdNode *
+Cudd_addIthBit(
+  DdManager * dd,
+  DdNode * f,
+  int  bit)
+{
+    DdNode *res;
+    DdNode *index;
+    
+    /* Use a constant node to remember the bit, so that we can use the
+    ** global cache.
+    */
+    index = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) bit);
+    if (index == NULL) return(NULL);
+    cuddRef(index);
+
+    do {
+        dd->reordered = 0;
+        res = addDoIthBit(dd, f, index);
+    } while (dd->reordered == 1);
+
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd, index);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd, index);
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addIthBit */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step for Cudd_addIthBit.]
+
+  Description [Performs the recursive step for Cudd_addIthBit.
+  Returns a pointer to the BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+addDoIthBit(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * index)
+{
+    DdNode *res, *T, *E;
+    DdNode *fv, *fvn;
+    int mask, value;
+    int v;
+
+    statLine(dd);
+    /* Check terminal case. */
+    if (cuddIsConstant(f)) {
+        mask = 1 << ((int) cuddV(index));
+        value = (int) cuddV(f);
+        return((value & mask) == 0 ? DD_ZERO(dd) : DD_ONE(dd));
+    }
+
+    /* Check cache. */
+    res = cuddCacheLookup2(dd,addDoIthBit,f,index);
+    if (res != NULL) return(res);
+
+    /* Recursive step. */
+    v = f->index;
+    fv = cuddT(f); fvn = cuddE(f);
+
+    T = addDoIthBit(dd,fv,index);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = addDoIthBit(dd,fvn,index);
+    if (E == NULL) {
+        Cudd_RecursiveDeref(dd, T);
+        return(NULL);
+    }
+    cuddRef(E);
+
+    res = (T == E) ? T : cuddUniqueInter(dd,v,T,E);
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd, T);
+        Cudd_RecursiveDeref(dd, E);
+        return(NULL);
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert2(dd,addDoIthBit,f,index,res);
+
+    return(res);
+
+} /* end of addDoIthBit */
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddAddInv.c b/abc-build/src/bdd/cudd/cuddAddInv.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddAddInv.c
@@ -0,0 +1,209 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAddInv.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Function to compute the scalar inverse of an ADD.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_addScalarInverse()
+                </ul>
+            Internal procedures included in this module:
+                <ul>
+                <li> cuddAddScalarInverseRecur()
+                </ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAddInv.c,v 1.9 2004/08/13 18:04:45 fabio Exp $";
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the scalar inverse of an ADD.]
+  
+  Description [Computes an n ADD where the discriminants are the
+  multiplicative inverses of the corresponding discriminants of the
+  argument ADD.  Returns a pointer to the resulting ADD in case of
+  success. Returns NULL if any discriminants smaller than epsilon is
+  encountered.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+Cudd_addScalarInverse(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * epsilon)
+{
+    DdNode *res;
+
+    if (!cuddIsConstant(epsilon)) {
+        (void) fprintf(dd->err,"Invalid epsilon\n");
+        return(NULL);
+    }
+    do {
+        dd->reordered = 0;
+        res  = cuddAddScalarInverseRecur(dd,f,epsilon);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addScalarInverse */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of addScalarInverse.]
+
+  Description [Returns a pointer to the resulting ADD in case of
+  success. Returns NULL if any discriminants smaller than epsilon is
+  encountered.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+cuddAddScalarInverseRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * epsilon)
+{
+    DdNode *t, *e, *res;
+    CUDD_VALUE_TYPE value;
+
+    statLine(dd);
+    if (cuddIsConstant(f)) {
+        if (ddAbs(cuddV(f)) < cuddV(epsilon)) return(NULL);
+        value = 1.0 / cuddV(f);
+        res = cuddUniqueConst(dd,value);
+        return(res);
+    }
+
+    res = cuddCacheLookup2(dd,Cudd_addScalarInverse,f,epsilon);
+    if (res != NULL) return(res);
+
+    t = cuddAddScalarInverseRecur(dd,cuddT(f),epsilon);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+
+    e = cuddAddScalarInverseRecur(dd,cuddE(f),epsilon);
+    if (e == NULL) {
+        Cudd_RecursiveDeref(dd, t);
+        return(NULL);
+    }
+    cuddRef(e);
+
+    res = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e);
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd, t);
+        Cudd_RecursiveDeref(dd, e);
+        return(NULL);
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    cuddCacheInsert2(dd,Cudd_addScalarInverse,f,epsilon,res);
+
+    return(res);
+
+} /* end of cuddAddScalarInverseRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddAddIte.c b/abc-build/src/bdd/cudd/cuddAddIte.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddAddIte.c
@@ -0,0 +1,647 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAddIte.c]
+
+  PackageName [cudd]
+
+  Synopsis    [ADD ITE function and satellites.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_addIte()
+                <li> Cudd_addIteConstant()
+                <li> Cudd_addEvalConst()
+                <li> Cudd_addCmpl()
+                <li> Cudd_addLeq()
+                </ul>
+        Internal procedures included in this module:
+                <ul>
+                <li> cuddAddIteRecur()
+                <li> cuddAddCmplRecur()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> addVarToConst()
+                </ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAddIte.c,v 1.15 2004/08/13 18:04:45 fabio Exp $";
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void addVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *one, DdNode *zero);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements ITE(f,g,h).]
+
+  Description [Implements ITE(f,g,h). This procedure assumes that f is
+  a 0-1 ADD.  Returns a pointer to the resulting ADD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIte Cudd_addIteConstant Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addIte(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddAddIteRecur(dd,f,g,h);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addIte */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements ITEconstant for ADDs.]
+
+  Description [Implements ITEconstant for ADDs.  f must be a 0-1 ADD.
+  Returns a pointer to the resulting ADD (which may or may not be
+  constant) or DD_NON_CONSTANT. No new nodes are created. This function
+  can be used, for instance, to check that g has a constant value
+  (specified by h) whenever f is 1. If the constant value is unknown,
+  then one should use Cudd_addEvalConst.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addIte Cudd_addEvalConst Cudd_bddIteConstant]
+
+******************************************************************************/
+DdNode *
+Cudd_addIteConstant(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode *one,*zero;
+    DdNode *Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*r,*t,*e;
+    unsigned int topf,topg,toph,v;
+
+    statLine(dd);
+    /* Trivial cases. */
+    if (f == (one = DD_ONE(dd))) {      /* ITE(1,G,H) = G */
+        return(g);
+    }
+    if (f == (zero = DD_ZERO(dd))) {    /* ITE(0,G,H) = H */
+        return(h);
+    }
+
+    /* From now on, f is known not to be a constant. */
+    addVarToConst(f,&g,&h,one,zero);
+
+    /* Check remaining one variable cases. */
+    if (g == h) {                       /* ITE(F,G,G) = G */
+        return(g);
+    }
+    if (cuddIsConstant(g) && cuddIsConstant(h)) {
+        return(DD_NON_CONSTANT);
+    }
+
+    topf = cuddI(dd,f->index);
+    topg = cuddI(dd,g->index);
+    toph = cuddI(dd,h->index);
+    v = ddMin(topg,toph);
+
+    /* ITE(F,G,H) = (x,G,H) (non constant) if F = (x,1,0), x < top(G,H). */
+    if (topf < v && cuddIsConstant(cuddT(f)) && cuddIsConstant(cuddE(f))) {
+        return(DD_NON_CONSTANT);
+    }
+
+    /* Check cache. */
+    r = cuddConstantLookup(dd,DD_ADD_ITE_CONSTANT_TAG,f,g,h);
+    if (r != NULL) {
+        return(r);
+    }
+
+    /* Compute cofactors. */
+    if (topf <= v) {
+        v = ddMin(topf,v);      /* v = top_var(F,G,H) */
+        Fv = cuddT(f); Fnv = cuddE(f);
+    } else {
+        Fv = Fnv = f;
+    }
+    if (topg == v) {
+        Gv = cuddT(g); Gnv = cuddE(g);
+    } else {
+        Gv = Gnv = g;
+    }
+    if (toph == v) {
+        Hv = cuddT(h); Hnv = cuddE(h);
+    } else {
+        Hv = Hnv = h;
+    }
+    
+    /* Recursive step. */
+    t = Cudd_addIteConstant(dd,Fv,Gv,Hv);
+    if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) {
+        cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT);
+        return(DD_NON_CONSTANT);
+    }
+    e = Cudd_addIteConstant(dd,Fnv,Gnv,Hnv);
+    if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) {
+        cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT);
+        return(DD_NON_CONSTANT);
+    }
+    cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, t);
+    return(t);
+
+} /* end of Cudd_addIteConstant */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether ADD g is constant whenever ADD f is 1.]
+
+  Description [Checks whether ADD g is constant whenever ADD f is 1.  f
+  must be a 0-1 ADD.  Returns a pointer to the resulting ADD (which may
+  or may not be constant) or DD_NON_CONSTANT. If f is identically 0,
+  the check is assumed to be successful, and the background value is
+  returned. No new nodes are created.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addIteConstant Cudd_addLeq]
+
+******************************************************************************/
+DdNode *
+Cudd_addEvalConst(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *zero;
+    DdNode *Fv,*Fnv,*Gv,*Gnv,*r,*t,*e;
+    unsigned int topf,topg;
+
+#ifdef DD_DEBUG
+    assert(!Cudd_IsComplement(f));
+#endif
+
+    statLine(dd);
+    /* Terminal cases. */
+    if (f == DD_ONE(dd) || cuddIsConstant(g)) {
+        return(g);
+    }
+    if (f == (zero = DD_ZERO(dd))) {
+        return(dd->background);
+    }
+
+#ifdef DD_DEBUG
+    assert(!cuddIsConstant(f));
+#endif
+    /* From now on, f and g are known not to be constants. */
+
+    topf = cuddI(dd,f->index);
+    topg = cuddI(dd,g->index);
+
+    /* Check cache. */
+    r = cuddConstantLookup(dd,DD_ADD_EVAL_CONST_TAG,f,g,g);
+    if (r != NULL) {
+        return(r);
+    }
+
+    /* Compute cofactors. */
+    if (topf <= topg) {
+        Fv = cuddT(f); Fnv = cuddE(f);
+    } else {
+        Fv = Fnv = f;
+    }
+    if (topg <= topf) {
+        Gv = cuddT(g); Gnv = cuddE(g);
+    } else {
+        Gv = Gnv = g;
+    }
+    
+    /* Recursive step. */
+    if (Fv != zero) {
+        t = Cudd_addEvalConst(dd,Fv,Gv);
+        if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) {
+            cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, DD_NON_CONSTANT);
+            return(DD_NON_CONSTANT);
+        }
+        if (Fnv != zero) {
+            e = Cudd_addEvalConst(dd,Fnv,Gnv);
+            if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) {
+                cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, DD_NON_CONSTANT);
+                return(DD_NON_CONSTANT);
+            }
+        }
+        cuddCacheInsert2(dd,Cudd_addEvalConst,f,g,t);
+        return(t);
+    } else { /* Fnv must be != zero */
+        e = Cudd_addEvalConst(dd,Fnv,Gnv);
+        cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, e);
+        return(e);
+    }
+
+} /* end of Cudd_addEvalConst */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the complement of an ADD a la C language.]
+
+  Description [Computes the complement of an ADD a la C language: The
+  complement of 0 is 1 and the complement of everything else is 0.
+  Returns a pointer to the resulting ADD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addNegate]
+
+******************************************************************************/
+DdNode *
+Cudd_addCmpl(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddAddCmplRecur(dd,f);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addCmpl */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Determines whether f is less than or equal to g.]
+
+  Description [Returns 1 if f is less than or equal to g; 0 otherwise.
+  No new nodes are created. This procedure works for arbitrary ADDs.
+  For 0-1 ADDs Cudd_addEvalConst is more efficient.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addIteConstant Cudd_addEvalConst Cudd_bddLeq]
+
+******************************************************************************/
+int
+Cudd_addLeq(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *tmp, *fv, *fvn, *gv, *gvn;
+    unsigned int topf, topg, res;
+
+    /* Terminal cases. */
+    if (f == g) return(1);
+
+    statLine(dd);
+    if (cuddIsConstant(f)) {
+        if (cuddIsConstant(g)) return(cuddV(f) <= cuddV(g));
+        if (f == DD_MINUS_INFINITY(dd)) return(1);
+        if (f == DD_PLUS_INFINITY(dd)) return(0); /* since f != g */
+    }
+    if (g == DD_PLUS_INFINITY(dd)) return(1);
+    if (g == DD_MINUS_INFINITY(dd)) return(0); /* since f != g */
+
+    /* Check cache. */
+    tmp = cuddCacheLookup2(dd,(DD_CTFP)Cudd_addLeq,f,g);
+    if (tmp != NULL) {
+        return(tmp == DD_ONE(dd));
+    }
+
+    /* Compute cofactors. One of f and g is not constant. */
+    topf = cuddI(dd,f->index);
+    topg = cuddI(dd,g->index);
+    if (topf <= topg) {
+        fv = cuddT(f); fvn = cuddE(f);
+    } else {
+        fv = fvn = f;
+    }
+    if (topg <= topf) {
+        gv = cuddT(g); gvn = cuddE(g);
+    } else {
+        gv = gvn = g;
+    }
+
+    res = Cudd_addLeq(dd,fvn,gvn) && Cudd_addLeq(dd,fv,gv);
+
+    /* Store result in cache and return. */
+    cuddCacheInsert2(dd,(DD_CTFP) Cudd_addLeq,f,g,
+                     Cudd_NotCond(DD_ONE(dd),res==0));
+    return(res);
+
+} /* end of Cudd_addLeq */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_addIte(f,g,h).]
+
+  Description [Implements the recursive step of Cudd_addIte(f,g,h).
+  Returns a pointer to the resulting ADD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addIte]
+
+******************************************************************************/
+DdNode *
+cuddAddIteRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode *one,*zero;
+    DdNode *r,*Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*t,*e;
+    unsigned int topf,topg,toph,v;
+    int index = -1;
+
+    statLine(dd);
+    /* Trivial cases. */
+
+    /* One variable cases. */
+    if (f == (one = DD_ONE(dd))) {      /* ITE(1,G,H) = G */
+        return(g);
+    }
+    if (f == (zero = DD_ZERO(dd))) {    /* ITE(0,G,H) = H */
+        return(h);
+    }
+
+    /* From now on, f is known to not be a constant. */
+    addVarToConst(f,&g,&h,one,zero);
+
+    /* Check remaining one variable cases. */
+    if (g == h) {                       /* ITE(F,G,G) = G */
+        return(g);
+    }
+
+    if (g == one) {                     /* ITE(F,1,0) = F */
+        if (h == zero) return(f);
+    }
+
+    topf = cuddI(dd,f->index);
+    topg = cuddI(dd,g->index);
+    toph = cuddI(dd,h->index);
+    v = ddMin(topg,toph);
+
+    /* A shortcut: ITE(F,G,H) = (x,G,H) if F=(x,1,0), x < top(G,H). */
+    if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
+        r = cuddUniqueInter(dd,(int)f->index,g,h);
+        return(r);
+    }
+    if (topf < v && cuddT(f) == zero && cuddE(f) == one) {
+        r = cuddUniqueInter(dd,(int)f->index,h,g);
+        return(r);
+    }
+
+    /* Check cache. */
+    r = cuddCacheLookup(dd,DD_ADD_ITE_TAG,f,g,h);
+    if (r != NULL) {
+        return(r);
+    }
+
+    /* Compute cofactors. */
+    if (topf <= v) {
+        v = ddMin(topf,v);      /* v = top_var(F,G,H) */
+        index = f->index;
+        Fv = cuddT(f); Fnv = cuddE(f);
+    } else {
+        Fv = Fnv = f;
+    }
+    if (topg == v) {
+        index = g->index;
+        Gv = cuddT(g); Gnv = cuddE(g);
+    } else {
+        Gv = Gnv = g;
+    }
+    if (toph == v) {
+        index = h->index;
+        Hv = cuddT(h); Hnv = cuddE(h);
+    } else {
+        Hv = Hnv = h;
+    }
+    
+    /* Recursive step. */
+    t = cuddAddIteRecur(dd,Fv,Gv,Hv);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+
+    e = cuddAddIteRecur(dd,Fnv,Gnv,Hnv);
+    if (e == NULL) {
+        Cudd_RecursiveDeref(dd,t);
+        return(NULL);
+    }
+    cuddRef(e);
+
+    r = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
+    if (r == NULL) {
+        Cudd_RecursiveDeref(dd,t);
+        Cudd_RecursiveDeref(dd,e);
+        return(NULL);
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    cuddCacheInsert(dd,DD_ADD_ITE_TAG,f,g,h,r);
+
+    return(r);
+
+} /* end of cuddAddIteRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addCmpl.]
+
+  Description [Performs the recursive step of Cudd_addCmpl. Returns a
+  pointer to the resulting ADD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addCmpl]
+
+******************************************************************************/
+DdNode *
+cuddAddCmplRecur(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *one,*zero;
+    DdNode *r,*Fv,*Fnv,*t,*e;
+
+    statLine(dd);
+    one = DD_ONE(dd);
+    zero = DD_ZERO(dd); 
+
+    if (cuddIsConstant(f)) {
+        if (f == zero) {
+            return(one);
+        } else {
+            return(zero);
+        }
+    }
+    r = cuddCacheLookup1(dd,Cudd_addCmpl,f);
+    if (r != NULL) {
+        return(r);
+    }
+    Fv = cuddT(f);
+    Fnv = cuddE(f);
+    t = cuddAddCmplRecur(dd,Fv);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+    e = cuddAddCmplRecur(dd,Fnv);
+    if (e == NULL) {
+        Cudd_RecursiveDeref(dd,t);
+        return(NULL);
+    }
+    cuddRef(e);
+    r = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e);
+    if (r == NULL) {
+        Cudd_RecursiveDeref(dd, t);
+        Cudd_RecursiveDeref(dd, e);
+        return(NULL);
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+    cuddCacheInsert1(dd,Cudd_addCmpl,f,r);
+    return(r);
+
+} /* end of cuddAddCmplRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Replaces variables with constants if possible (part of
+  canonical form).]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+addVarToConst(
+  DdNode * f,
+  DdNode ** gp,
+  DdNode ** hp,
+  DdNode * one,
+  DdNode * zero)
+{
+    DdNode *g = *gp;
+    DdNode *h = *hp;
+
+    if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */
+        *gp = one;
+    }
+
+    if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */
+        *hp = zero;
+    }
+
+} /* end of addVarToConst */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddAddNeg.c b/abc-build/src/bdd/cudd/cuddAddNeg.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddAddNeg.c
@@ -0,0 +1,296 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAddNeg.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Function to compute the negation of an ADD.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_addNegate()
+                <li> Cudd_addRoundOff()
+                </ul>
+        Internal procedures included in this module:
+                <ul>
+                <li> cuddAddNegateRecur()
+                <li> cuddAddRoundOffRecur()
+                </ul> ]
+
+  Author      [Fabio Somenzi, Balakrishna Kumthekar]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAddNeg.c,v 1.12 2009/02/20 02:14:58 fabio Exp $";
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the additive inverse of an ADD.]
+
+  Description [Computes the additive inverse of an ADD. Returns a pointer
+  to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addCmpl]
+
+******************************************************************************/
+DdNode *
+Cudd_addNegate(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *res;
+
+    do {
+        res = cuddAddNegateRecur(dd,f);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addNegate */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Rounds off the discriminants of an ADD.]
+
+  Description [Rounds off the discriminants of an ADD. The discriminants are
+  rounded off to N digits after the decimal. Returns a pointer to the result
+  ADD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_addRoundOff(
+  DdManager * dd,
+  DdNode * f,
+  int  N)
+{
+    DdNode *res;
+    double trunc = pow(10.0,(double)N);
+
+    do {
+        res = cuddAddRoundOffRecur(dd,f,trunc);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addRoundOff */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_addNegate.]
+
+  Description [Implements the recursive step of Cudd_addNegate.
+  Returns a pointer to the result.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+cuddAddNegateRecur(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *res,
+            *fv, *fvn,
+            *T, *E;
+
+    statLine(dd);
+    /* Check terminal cases. */
+    if (cuddIsConstant(f)) {
+        res = cuddUniqueConst(dd,-cuddV(f));
+        return(res);
+    }
+
+    /* Check cache */
+    res = cuddCacheLookup1(dd,Cudd_addNegate,f);
+    if (res != NULL) return(res);
+
+    /* Recursive Step */
+    fv = cuddT(f);
+    fvn = cuddE(f);
+    T = cuddAddNegateRecur(dd,fv);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = cuddAddNegateRecur(dd,fvn);
+    if (E == NULL) {
+        Cudd_RecursiveDeref(dd,T);
+        return(NULL);
+    }
+    cuddRef(E);
+    res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E);
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd, T);
+        Cudd_RecursiveDeref(dd, E);
+        return(NULL);
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert1(dd,Cudd_addNegate,f,res);
+
+    return(res);
+
+} /* end of cuddAddNegateRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_addRoundOff.]
+
+  Description [Implements the recursive step of Cudd_addRoundOff.
+  Returns a pointer to the result.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+cuddAddRoundOffRecur(
+  DdManager * dd,
+  DdNode * f,
+  double  trunc)
+{
+
+    DdNode *res, *fv, *fvn, *T, *E;
+    double n;
+    DD_CTFP1 cacheOp;
+
+    statLine(dd);
+    if (cuddIsConstant(f)) {
+        n = ceil(cuddV(f)*trunc)/trunc;
+        res = cuddUniqueConst(dd,n);
+        return(res);
+    }
+    cacheOp = (DD_CTFP1) Cudd_addRoundOff;
+    res = cuddCacheLookup1(dd,cacheOp,f);
+    if (res != NULL) {
+        return(res);
+    }
+    /* Recursive Step */
+    fv = cuddT(f);
+    fvn = cuddE(f);
+    T = cuddAddRoundOffRecur(dd,fv,trunc);
+    if (T == NULL) {
+       return(NULL);
+    }
+    cuddRef(T);
+    E = cuddAddRoundOffRecur(dd,fvn,trunc);
+    if (E == NULL) {
+        Cudd_RecursiveDeref(dd,T);
+        return(NULL);
+    }
+    cuddRef(E);
+    res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E);
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd,T);
+        Cudd_RecursiveDeref(dd,E);
+        return(NULL);
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert1(dd,cacheOp,f,res);
+    return(res);
+
+} /* end of cuddAddRoundOffRecur */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddAddWalsh.c b/abc-build/src/bdd/cudd/cuddAddWalsh.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddAddWalsh.c
@@ -0,0 +1,399 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAddWalsh.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions that generate Walsh matrices and residue
+  functions in ADD form.]
+
+  Description [External procedures included in this module:
+            <ul>
+            <li> Cudd_addWalsh()
+            <li> Cudd_addResidue()
+            </ul>
+        Static procedures included in this module:
+            <ul>
+            <li> addWalshInt()
+            </ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAddWalsh.c,v 1.10 2008/04/17 21:17:11 fabio Exp $";
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * addWalshInt (DdManager *dd, DdNode **x, DdNode **y, int n);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a Walsh matrix in ADD form.]
+
+  Description [Generates a Walsh matrix in ADD form. Returns a pointer
+  to the matrixi if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+Cudd_addWalsh(
+  DdManager * dd,
+  DdNode ** x,
+  DdNode ** y,
+  int  n)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = addWalshInt(dd, x, y, n);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addWalsh */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds an ADD for the residue modulo m of an n-bit
+  number.]
+
+  Description [Builds an ADD for the residue modulo m of an n-bit
+  number. The modulus must be at least 2, and the number of bits at
+  least 1. Parameter options specifies whether the MSB should be on top
+  or the LSB; and whther the number whose residue is computed is in
+  two's complement notation or not. The macro CUDD_RESIDUE_DEFAULT
+  specifies LSB on top and unsigned number. The macro CUDD_RESIDUE_MSB
+  specifies MSB on top, and the macro CUDD_RESIDUE_TC specifies two's
+  complement residue. To request MSB on top and two's complement residue
+  simultaneously, one can OR the two macros:
+  CUDD_RESIDUE_MSB | CUDD_RESIDUE_TC.
+  Cudd_addResidue returns a pointer to the resulting ADD if successful;
+  NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_addResidue(
+  DdManager * dd /* manager */,
+  int  n /* number of bits */,
+  int  m /* modulus */,
+  int  options /* options */,
+  int  top /* index of top variable */)
+{
+    int msbLsb; /* MSB on top (1) or LSB on top (0) */
+    int tc;     /* two's complement (1) or unsigned (0) */
+    int i, j, k, t, residue, thisOne, previous, index;
+    DdNode **array[2], *var, *tmp, *res;
+
+    /* Sanity check. */
+    if (n < 1 && m < 2) return(NULL);
+
+    msbLsb = options & CUDD_RESIDUE_MSB;
+    tc = options & CUDD_RESIDUE_TC;
+
+    /* Allocate and initialize working arrays. */
+    array[0] = ABC_ALLOC(DdNode *,m);
+    if (array[0] == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    array[1] = ABC_ALLOC(DdNode *,m);
+    if (array[1] == NULL) {
+        ABC_FREE(array[0]);
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    for (i = 0; i < m; i++) {
+        array[0][i] = array[1][i] = NULL;
+    }
+
+    /* Initialize residues. */
+    for (i = 0; i < m; i++) {
+        tmp = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) i);
+        if (tmp == NULL) {
+            for (j = 0; j < i; j++) {
+                Cudd_RecursiveDeref(dd,array[1][j]);
+            }
+            ABC_FREE(array[0]);
+            ABC_FREE(array[1]);
+            return(NULL);
+        }
+        cuddRef(tmp);
+        array[1][i] = tmp;
+    }
+
+    /* Main iteration. */
+    residue = 1;        /* residue of 2**0 */
+    for (k = 0; k < n; k++) {
+        /* Choose current and previous arrays. */
+        thisOne = k & 1;
+        previous = thisOne ^ 1;
+        /* Build an ADD projection function. */
+        if (msbLsb) {
+            index = top+n-k-1;
+        } else {
+            index = top+k;
+        }
+        var = cuddUniqueInter(dd,index,DD_ONE(dd),DD_ZERO(dd));
+        if (var == NULL) {
+            for (j = 0; j < m; j++) {
+                Cudd_RecursiveDeref(dd,array[previous][j]);
+            }
+            ABC_FREE(array[0]);
+            ABC_FREE(array[1]);
+            return(NULL);
+        }
+        cuddRef(var);
+        for (i = 0; i < m; i ++) {
+            t = (i + residue) % m;
+            tmp = Cudd_addIte(dd,var,array[previous][t],array[previous][i]);
+            if (tmp == NULL) {
+                for (j = 0; j < i; j++) {
+                    Cudd_RecursiveDeref(dd,array[thisOne][j]);
+                }
+                for (j = 0; j < m; j++) {
+                    Cudd_RecursiveDeref(dd,array[previous][j]);
+                }
+                ABC_FREE(array[0]);
+                ABC_FREE(array[1]);
+                return(NULL);
+            }
+            cuddRef(tmp);
+            array[thisOne][i] = tmp;
+        }
+        /* One layer completed. Free the other array for the next iteration. */
+        for (i = 0; i < m; i++) {
+            Cudd_RecursiveDeref(dd,array[previous][i]);
+        }
+        Cudd_RecursiveDeref(dd,var);
+        /* Update residue of 2**k. */
+        residue = (2 * residue) % m;
+        /* Adjust residue for MSB, if this is a two's complement number. */
+        if (tc && (k == n - 1)) {
+            residue = (m - residue) % m;
+        }
+    }
+
+    /* We are only interested in the 0-residue node of the top layer. */
+    for (i = 1; i < m; i++) {
+        Cudd_RecursiveDeref(dd,array[(n - 1) & 1][i]);
+    }
+    res = array[(n - 1) & 1][0];
+
+    ABC_FREE(array[0]);
+    ABC_FREE(array[1]);
+
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addResidue */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_addWalsh.]
+
+  Description [Generates a Walsh matrix in ADD form. Returns a pointer
+  to the matrixi if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static DdNode *
+addWalshInt(
+  DdManager * dd,
+  DdNode ** x,
+  DdNode ** y,
+  int  n)
+{
+    DdNode *one, *minusone;
+    DdNode *t = NULL, *u = NULL, *t1, *u1, *v, *w;
+    int     i;
+
+    one = DD_ONE(dd);
+    if (n == 0) return(one);
+
+    /* Build bottom part of ADD outside loop */
+    minusone = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) -1);
+    if (minusone == NULL) return(NULL);
+    cuddRef(minusone);
+    v = Cudd_addIte(dd, y[n-1], minusone, one);
+    if (v == NULL) {
+        Cudd_RecursiveDeref(dd, minusone);
+        return(NULL);
+    }
+    cuddRef(v);
+    u = Cudd_addIte(dd, x[n-1], v, one);
+    if (u == NULL) {
+        Cudd_RecursiveDeref(dd, minusone);
+        Cudd_RecursiveDeref(dd, v);
+        return(NULL);
+    }
+    cuddRef(u);
+    Cudd_RecursiveDeref(dd, v);
+    if (n>1) {
+        w = Cudd_addIte(dd, y[n-1], one, minusone);
+        if (w == NULL) {
+            Cudd_RecursiveDeref(dd, minusone);
+            Cudd_RecursiveDeref(dd, u);
+            return(NULL);
+        }
+        cuddRef(w);
+        t = Cudd_addIte(dd, x[n-1], w, minusone);
+        if (t == NULL) {
+            Cudd_RecursiveDeref(dd, minusone);
+            Cudd_RecursiveDeref(dd, u);
+            Cudd_RecursiveDeref(dd, w);
+            return(NULL);
+        }
+        cuddRef(t);
+        Cudd_RecursiveDeref(dd, w);
+    }
+    cuddDeref(minusone); /* minusone is in the result; it won't die */
+
+    /* Loop to build the rest of the ADD */
+    for (i=n-2; i>=0; i--) {
+        t1 = t; u1 = u;
+        v = Cudd_addIte(dd, y[i], t1, u1);
+        if (v == NULL) {
+            Cudd_RecursiveDeref(dd, u1);
+            Cudd_RecursiveDeref(dd, t1);
+            return(NULL);
+        }
+        cuddRef(v);
+        u = Cudd_addIte(dd, x[i], v, u1);
+        if (u == NULL) {
+            Cudd_RecursiveDeref(dd, u1);
+            Cudd_RecursiveDeref(dd, t1);
+            Cudd_RecursiveDeref(dd, v);
+            return(NULL);
+        }
+        cuddRef(u);
+        Cudd_RecursiveDeref(dd, v);
+        if (i>0) {
+            w = Cudd_addIte(dd, y[i], u1, t1);
+            if (w == NULL) {
+                Cudd_RecursiveDeref(dd, u1);
+                Cudd_RecursiveDeref(dd, t1);
+                Cudd_RecursiveDeref(dd, u);
+                return(NULL);
+            }
+            cuddRef(w);
+            t = Cudd_addIte(dd, x[i], w, t1);
+            if (u == NULL) {
+                Cudd_RecursiveDeref(dd, u1);
+                Cudd_RecursiveDeref(dd, t1);
+                Cudd_RecursiveDeref(dd, u);
+                Cudd_RecursiveDeref(dd, w);
+                return(NULL);
+            }
+            cuddRef(t);
+            Cudd_RecursiveDeref(dd, w);
+        }
+        Cudd_RecursiveDeref(dd, u1);
+        Cudd_RecursiveDeref(dd, t1);
+    }
+
+    cuddDeref(u);
+    return(u);
+
+} /* end of addWalshInt */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddAndAbs.c b/abc-build/src/bdd/cudd/cuddAndAbs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddAndAbs.c
@@ -0,0 +1,384 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAndAbs.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Combined AND and existential abstraction for BDDs]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_bddAndAbstract()
+                <li> Cudd_bddAndAbstractLimit()
+                </ul>
+            Internal procedures included in this module:
+                <ul>
+                <li> cuddBddAndAbstractRecur()
+                </ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAndAbs.c,v 1.19 2004/08/13 18:04:46 fabio Exp $";
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
+  variables in cube.]
+
+  Description [Takes the AND of two BDDs and simultaneously abstracts
+  the variables in cube. The variables are existentially abstracted.
+  Returns a pointer to the result is successful; NULL otherwise.
+  Cudd_bddAndAbstract implements the semiring matrix multiplication
+  algorithm for the boolean semiring.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addMatrixMultiply Cudd_addTriangle Cudd_bddAnd]
+
+******************************************************************************/
+DdNode *
+Cudd_bddAndAbstract(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  DdNode * cube)
+{
+    DdNode *res;
+
+    do {
+        manager->reordered = 0;
+        res = cuddBddAndAbstractRecur(manager, f, g, cube);
+    } while (manager->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddAndAbstract */
+
+
+/**Function********************************************************************
+
+  Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
+  variables in cube.  Returns NULL if too many nodes are required.]
+
+  Description [Takes the AND of two BDDs and simultaneously abstracts
+  the variables in cube. The variables are existentially abstracted.
+  Returns a pointer to the result is successful; NULL otherwise.
+  In particular, if the number of new nodes created exceeds
+  <code>limit</code>, this function returns NULL.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddAndAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_bddAndAbstractLimit(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  DdNode * cube,
+  unsigned int limit)
+{
+    DdNode *res;
+    unsigned int saveLimit = manager->maxLive;
+
+    manager->maxLive = (manager->keys - manager->dead) +
+      (manager->keysZ - manager->deadZ) + limit;
+    do {
+        manager->reordered = 0;
+        res = cuddBddAndAbstractRecur(manager, f, g, cube);
+    } while (manager->reordered == 1);
+    manager->maxLive = saveLimit;
+    return(res);
+
+} /* end of Cudd_bddAndAbstractLimit */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
+  variables in cube.]
+
+  Description [Takes the AND of two BDDs and simultaneously abstracts
+  the variables in cube. The variables are existentially abstracted.
+  Returns a pointer to the result is successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddAndAbstract]
+
+******************************************************************************/
+DdNode *
+cuddBddAndAbstractRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  DdNode * cube)
+{
+    DdNode *F, *ft, *fe, *G, *gt, *ge;
+    DdNode *one, *zero, *r, *t, *e;
+    unsigned int topf, topg, topcube, top, index;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    /* Terminal cases. */
+    if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
+    if (f == one && g == one)   return(one);
+
+    if (cube == one) {
+        return(cuddBddAndRecur(manager, f, g));
+    }
+    if (f == one || f == g) {
+        return(cuddBddExistAbstractRecur(manager, g, cube));
+    }
+    if (g == one) {
+        return(cuddBddExistAbstractRecur(manager, f, cube));
+    }
+    /* At this point f, g, and cube are not constant. */
+
+    if (f > g) { /* Try to increase cache efficiency. */
+        DdNode *tmp = f;
+        f = g;
+        g = tmp;
+    }
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    topf = manager->perm[F->index];
+    topg = manager->perm[G->index];
+    top = ddMin(topf, topg);
+    topcube = manager->perm[cube->index];
+
+    while (topcube < top) {
+        cube = cuddT(cube);
+        if (cube == one) {
+            return(cuddBddAndRecur(manager, f, g));
+        }
+        topcube = manager->perm[cube->index];
+    }
+    /* Now, topcube >= top. */
+
+    /* Check cache. */
+    if (F->ref != 1 || G->ref != 1) {
+        r = cuddCacheLookup(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube);
+        if (r != NULL) {
+            return(r);
+        }
+    }
+
+    if ( manager->TimeStop && Abc_Clock() > manager->TimeStop )
+        return NULL;
+
+    if (topf == top) {
+        index = F->index;
+        ft = cuddT(F);
+        fe = cuddE(F);
+        if (Cudd_IsComplement(f)) {
+            ft = Cudd_Not(ft);
+            fe = Cudd_Not(fe);
+        }
+    } else {
+        index = G->index;
+        ft = fe = f;
+    }
+
+    if (topg == top) {
+        gt = cuddT(G);
+        ge = cuddE(G);
+        if (Cudd_IsComplement(g)) {
+            gt = Cudd_Not(gt);
+            ge = Cudd_Not(ge);
+        }
+    } else {
+        gt = ge = g;
+    }
+
+    if (topcube == top) {       /* quantify */
+        DdNode *Cube = cuddT(cube);
+        t = cuddBddAndAbstractRecur(manager, ft, gt, Cube);
+        if (t == NULL) return(NULL);
+        /* Special case: 1 OR anything = 1. Hence, no need to compute
+        ** the else branch if t is 1. Likewise t + t * anything == t.
+        ** Notice that t == fe implies that fe does not depend on the
+        ** variables in Cube. Likewise for t == ge.
+        */
+        if (t == one || t == fe || t == ge) {
+            if (F->ref != 1 || G->ref != 1)
+                cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG,
+                                f, g, cube, t);
+            return(t);
+        }
+        cuddRef(t);
+        /* Special case: t + !t * anything == t + anything. */
+        if (t == Cudd_Not(fe)) {
+            e = cuddBddExistAbstractRecur(manager, ge, Cube);
+        } else if (t == Cudd_Not(ge)) {
+            e = cuddBddExistAbstractRecur(manager, fe, Cube);
+        } else {
+            e = cuddBddAndAbstractRecur(manager, fe, ge, Cube);
+        }
+        if (e == NULL) {
+            Cudd_IterDerefBdd(manager, t);
+            return(NULL);
+        }
+        if (t == e) {
+            r = t;
+            cuddDeref(t);
+        } else {
+            cuddRef(e);
+            r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e));
+            if (r == NULL) {
+                Cudd_IterDerefBdd(manager, t);
+                Cudd_IterDerefBdd(manager, e);
+                return(NULL);
+            }
+            r = Cudd_Not(r);
+            cuddRef(r);
+            Cudd_DelayedDerefBdd(manager, t);
+            Cudd_DelayedDerefBdd(manager, e);
+            cuddDeref(r);
+        }
+    } else {
+        t = cuddBddAndAbstractRecur(manager, ft, gt, cube);
+        if (t == NULL) return(NULL);
+        cuddRef(t);
+        e = cuddBddAndAbstractRecur(manager, fe, ge, cube);
+        if (e == NULL) {
+            Cudd_IterDerefBdd(manager, t);
+            return(NULL);
+        }
+        if (t == e) {
+            r = t;
+            cuddDeref(t);
+        } else {
+            cuddRef(e);
+            if (Cudd_IsComplement(t)) {
+                r = cuddUniqueInter(manager, (int) index,
+                                    Cudd_Not(t), Cudd_Not(e));
+                if (r == NULL) {
+                    Cudd_IterDerefBdd(manager, t);
+                    Cudd_IterDerefBdd(manager, e);
+                    return(NULL);
+                }
+                r = Cudd_Not(r);
+            } else {
+                r = cuddUniqueInter(manager,(int)index,t,e);
+                if (r == NULL) {
+                    Cudd_IterDerefBdd(manager, t);
+                    Cudd_IterDerefBdd(manager, e);
+                    return(NULL);
+                }
+            }
+            cuddDeref(e);
+            cuddDeref(t);
+        }
+    }
+
+    if (F->ref != 1 || G->ref != 1)
+        cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, r);
+    return (r);
+
+} /* end of cuddBddAndAbstractRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddAnneal.c b/abc-build/src/bdd/cudd/cuddAnneal.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddAnneal.c
@@ -0,0 +1,822 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAnneal.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Reordering of DDs based on simulated annealing]
+
+  Description [Internal procedures included in this file:
+                <ul>
+                <li> cuddAnnealing()
+                </ul>
+               Static procedures included in this file:
+                <ul>
+                <li> stopping_criterion()
+                <li> random_generator()
+                <li> ddExchange()
+                <li> ddJumpingAux()
+                <li> ddJumpingUp()
+                <li> ddJumpingDown()
+                <li> siftBackwardProb()
+                <li> copyOrder()
+                <li> restoreOrder()
+                </ul>
+                ]
+
+  SeeAlso     []
+
+  Author      [Jae-Young Jang, Jorgen Sivesind]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* Annealing parameters */
+#define BETA 0.6 
+#define ALPHA 0.90
+#define EXC_PROB 0.4 
+#define JUMP_UP_PROB 0.36
+#define MAXGEN_RATIO 15.0
+#define STOP_TEMP 1.0
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAnneal.c,v 1.14 2004/08/13 18:04:46 fabio Exp $";
+#endif
+
+#ifdef DD_STATS
+extern  int     ddTotalNumberSwapping;
+extern  int     ddTotalNISwaps;
+static  int     tosses;
+static  int     acceptances;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int stopping_criterion (int c1, int c2, int c3, int c4, double temp);
+static double random_generator (void);
+static int ddExchange (DdManager *table, int x, int y, double temp);
+static int ddJumpingAux (DdManager *table, int x, int x_low, int x_high, double temp);
+static Move * ddJumpingUp (DdManager *table, int x, int x_low, int initial_size);
+static Move * ddJumpingDown (DdManager *table, int x, int x_high, int initial_size);
+static int siftBackwardProb (DdManager *table, Move *moves, int size, double temp);
+static void copyOrder (DdManager *table, int *array, int lower, int upper);
+static int restoreOrder (DdManager *table, int *array, int lower, int upper);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Get new variable-order by simulated annealing algorithm.]
+
+  Description [Get x, y by random selection. Choose either
+  exchange or jump randomly. In case of jump, choose between jump_up
+  and jump_down randomly. Do exchange or jump and get optimal case.
+  Loop until there is no improvement or temperature reaches
+  minimum. Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddAnnealing(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int         nvars;
+    int         size;
+    int         x,y;
+    int         result;
+    int         c1, c2, c3, c4;
+    int         BestCost;
+    int         *BestOrder;
+    double      NewTemp, temp;
+    double      rand1;
+    int         innerloop, maxGen;
+    int         ecount, ucount, dcount;
+   
+    nvars = upper - lower + 1;
+
+    result = cuddSifting(table,lower,upper);
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n");
+#endif
+    if (result == 0) return(0);
+
+    size = table->keys - table->isolated;
+
+    /* Keep track of the best order. */
+    BestCost = size;
+    BestOrder = ABC_ALLOC(int,nvars);
+    if (BestOrder == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    copyOrder(table,BestOrder,lower,upper);
+
+    temp = BETA * size;
+    maxGen = (int) (MAXGEN_RATIO * nvars);
+
+    c1 = size + 10;
+    c2 = c1 + 10;
+    c3 = size;
+    c4 = c2 + 10;
+    ecount = ucount = dcount = 0;
+ 
+    while (!stopping_criterion(c1, c2, c3, c4, temp)) {
+#ifdef DD_STATS
+        (void) fprintf(table->out,"temp=%f\tsize=%d\tgen=%d\t",
+                       temp,size,maxGen);
+        tosses = acceptances = 0;
+#endif
+        for (innerloop = 0; innerloop < maxGen; innerloop++) {
+            /* Choose x, y  randomly. */
+            x = (int) Cudd_Random() % nvars;
+            do {
+                y = (int) Cudd_Random() % nvars;
+            } while (x == y);
+            x += lower;
+            y += lower;
+            if (x > y) {
+                int tmp = x;
+                x = y;
+                y = tmp;
+            }
+
+            /* Choose move with roulette wheel. */
+            rand1 = random_generator();
+            if (rand1 < EXC_PROB) {
+                result = ddExchange(table,x,y,temp);       /* exchange */
+                ecount++;
+#if 0
+                (void) fprintf(table->out,
+                               "Exchange of %d and %d: size = %d\n",
+                               x,y,table->keys - table->isolated);
+#endif
+            } else if (rand1 < EXC_PROB + JUMP_UP_PROB) {
+                result = ddJumpingAux(table,y,x,y,temp); /* jumping_up */
+                ucount++;
+#if 0
+                (void) fprintf(table->out,
+                               "Jump up of %d to %d: size = %d\n",
+                               y,x,table->keys - table->isolated);
+#endif
+            } else {
+                result = ddJumpingAux(table,x,x,y,temp); /* jumping_down */
+                dcount++;
+#if 0
+                (void) fprintf(table->out,
+                               "Jump down of %d to %d: size = %d\n",
+                               x,y,table->keys - table->isolated);
+#endif
+            }
+
+            if (!result) {
+                ABC_FREE(BestOrder);
+                return(0);
+            }
+
+            size = table->keys - table->isolated;       /* keep current size */
+            if (size < BestCost) {                      /* update best order */
+                BestCost = size;
+                copyOrder(table,BestOrder,lower,upper);
+            }
+        }
+        c1 = c2;
+        c2 = c3;
+        c3 = c4;
+        c4 = size;
+        NewTemp = ALPHA * temp;
+        if (NewTemp >= 1.0) {
+            maxGen = (int)(log(NewTemp) / log(temp) * maxGen);
+        }
+        temp = NewTemp;                 /* control variable */
+#ifdef DD_STATS
+        (void) fprintf(table->out,"uphill = %d\taccepted = %d\n",
+                       tosses,acceptances);
+        fflush(table->out);
+#endif
+    }
+
+    result = restoreOrder(table,BestOrder,lower,upper);
+    ABC_FREE(BestOrder);
+    if (!result) return(0);
+#ifdef DD_STATS
+    fprintf(table->out,"#:N_EXCHANGE %8d : total exchanges\n",ecount);
+    fprintf(table->out,"#:N_JUMPUP   %8d : total jumps up\n",ucount);
+    fprintf(table->out,"#:N_JUMPDOWN %8d : total jumps down",dcount);
+#endif
+    return(1);
+
+} /* end of cuddAnnealing */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Checks termination condition.]
+
+  Description [If temperature is STOP_TEMP or there is no improvement
+  then terminates. Returns 1 if the termination criterion is met; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+stopping_criterion(
+  int  c1,
+  int  c2,
+  int  c3,
+  int  c4,
+  double  temp)
+{
+    if (STOP_TEMP < temp) {
+        return(0);
+    } else if ((c1 == c2) && (c1 == c3) && (c1 == c4)) {
+        return(1);
+    } else {
+        return(0);
+    }
+
+} /* end of stopping_criterion */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Random number generator.]
+
+  Description [Returns a double precision value between 0.0 and 1.0.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static double
+random_generator(void)
+{
+    return((double)(Cudd_Random() / 2147483561.0));
+
+} /* end of random_generator */
+
+
+/**Function********************************************************************
+
+  Synopsis    [This function is for exchanging two variables, x and y.]
+
+  Description [This is the same funcion as ddSwapping except for
+  comparison expression.  Use probability function, exp(-size_change/temp).]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddExchange(
+  DdManager * table,
+  int  x,
+  int  y,
+  double  temp)
+{
+    Move       *move,*moves;
+    int        tmp;
+    int        x_ref,y_ref;
+    int        x_next,y_next;
+    int        size, result;
+    int        initial_size, limit_size;
+
+    x_ref = x;
+    y_ref = y;
+
+    x_next = cuddNextHigh(table,x);
+    y_next = cuddNextLow(table,y);
+    moves = NULL;
+    initial_size = limit_size = table->keys - table->isolated;
+
+    for (;;) {
+        if (x_next == y_next) {
+            size = cuddSwapInPlace(table,x,x_next);
+            if (size == 0) goto ddExchangeOutOfMem;
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddExchangeOutOfMem;
+            move->x = x;
+            move->y = x_next;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+            size = cuddSwapInPlace(table,y_next,y);
+            if (size == 0) goto ddExchangeOutOfMem;
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddExchangeOutOfMem;
+            move->x = y_next;
+            move->y = y;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+            size = cuddSwapInPlace(table,x,x_next);
+            if (size == 0) goto ddExchangeOutOfMem;
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddExchangeOutOfMem;
+            move->x = x;
+            move->y = x_next;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+
+            tmp = x;
+            x = y;
+            y = tmp;
+        } else if (x == y_next) {
+            size = cuddSwapInPlace(table,x,x_next);
+            if (size == 0) goto ddExchangeOutOfMem;
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddExchangeOutOfMem;
+            move->x = x;
+            move->y = x_next;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+            tmp = x;
+            x = y;
+            y = tmp;
+        } else {
+            size = cuddSwapInPlace(table,x,x_next);
+            if (size == 0) goto ddExchangeOutOfMem;
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddExchangeOutOfMem;
+            move->x = x;
+            move->y = x_next;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+            size = cuddSwapInPlace(table,y_next,y);
+            if (size == 0) goto ddExchangeOutOfMem;
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddExchangeOutOfMem;
+            move->x = y_next;
+            move->y = y;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+            x = x_next;
+            y = y_next;
+        }
+
+        x_next = cuddNextHigh(table,x);
+        y_next = cuddNextLow(table,y);
+        if (x_next > y_ref) break;
+
+        if ((double) size > DD_MAX_REORDER_GROWTH * (double) limit_size) {
+            break;
+        } else if (size < limit_size) {
+            limit_size = size;
+        }
+    }
+
+    if (y_next>=x_ref) {
+        size = cuddSwapInPlace(table,y_next,y);
+        if (size == 0) goto ddExchangeOutOfMem;
+        move = (Move *)cuddDynamicAllocNode(table);
+        if (move == NULL) goto ddExchangeOutOfMem;
+        move->x = y_next;
+        move->y = y;
+        move->size = size;
+        move->next = moves;
+        moves = move;
+    }
+
+    /* move backward and stop at best position or accept uphill move */
+    result = siftBackwardProb(table,moves,initial_size,temp);
+    if (!result) goto ddExchangeOutOfMem;
+
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return(1);
+
+ddExchangeOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return(0);
+
+} /* end of ddExchange */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves a variable to a specified position.]
+
+  Description [If x==x_low, it executes jumping_down. If x==x_high, it
+  executes jumping_up. This funcion is similar to ddSiftingAux. Returns
+  1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddJumpingAux(
+  DdManager * table,
+  int  x,
+  int  x_low,
+  int  x_high,
+  double  temp)
+{
+    Move       *move;
+    Move       *moves;        /* list of moves */
+    int        initial_size;
+    int        result;
+
+    initial_size = table->keys - table->isolated;
+
+#ifdef DD_DEBUG
+    assert(table->subtables[x].keys > 0);
+#endif
+
+    moves = NULL;
+
+    if (cuddNextLow(table,x) < x_low) {
+        if (cuddNextHigh(table,x) > x_high) return(1);
+        moves = ddJumpingDown(table,x,x_high,initial_size);
+        /* after that point x --> x_high unless early termination */
+        if (moves == NULL) goto ddJumpingAuxOutOfMem;
+        /* move backward and stop at best position or accept uphill move */
+        result = siftBackwardProb(table,moves,initial_size,temp);
+        if (!result) goto ddJumpingAuxOutOfMem;
+    } else if (cuddNextHigh(table,x) > x_high) {
+        moves = ddJumpingUp(table,x,x_low,initial_size);
+        /* after that point x --> x_low unless early termination */
+        if (moves == NULL) goto ddJumpingAuxOutOfMem;
+        /* move backward and stop at best position or accept uphill move */
+        result = siftBackwardProb(table,moves,initial_size,temp);
+        if (!result) goto ddJumpingAuxOutOfMem;
+    } else {
+        (void) fprintf(table->err,"Unexpected condition in ddJumping\n");
+        goto ddJumpingAuxOutOfMem;
+    }
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return(1);
+
+ddJumpingAuxOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return(0);
+
+} /* end of ddJumpingAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [This function is for jumping up.]
+
+  Description [This is a simplified version of ddSiftingUp. It does not
+  use lower bounding. Returns the set of moves in case of success; NULL
+  if memory is full.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+ddJumpingUp(
+  DdManager * table,
+  int  x,
+  int  x_low,
+  int  initial_size)
+{
+    Move       *moves;
+    Move       *move;
+    int        y;
+    int        size;
+    int        limit_size = initial_size;
+
+    moves = NULL;
+    y = cuddNextLow(table,x);
+    while (y >= x_low) {
+        size = cuddSwapInPlace(table,y,x);
+        if (size == 0) goto ddJumpingUpOutOfMem;
+        move = (Move *)cuddDynamicAllocNode(table);
+        if (move == NULL) goto ddJumpingUpOutOfMem;
+        move->x = y;
+        move->y = x;
+        move->size = size;
+        move->next = moves;
+        moves = move;
+        if ((double) size > table->maxGrowth * (double) limit_size) {
+            break;
+        } else if (size < limit_size) {
+            limit_size = size;
+        }
+        x = y;
+        y = cuddNextLow(table,x);
+    }
+    return(moves);
+
+ddJumpingUpOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return(NULL);
+
+} /* end of ddJumpingUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [This function is for jumping down.]
+
+  Description [This is a simplified version of ddSiftingDown. It does not
+  use lower bounding. Returns the set of moves in case of success; NULL
+  if memory is full.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+ddJumpingDown(
+  DdManager * table,
+  int  x,
+  int  x_high,
+  int  initial_size)
+{
+    Move       *moves;
+    Move       *move;
+    int        y;
+    int        size;
+    int        limit_size = initial_size;
+
+    moves = NULL;
+    y = cuddNextHigh(table,x);
+    while (y <= x_high) {
+        size = cuddSwapInPlace(table,x,y);
+        if (size == 0) goto ddJumpingDownOutOfMem;
+        move = (Move *)cuddDynamicAllocNode(table);
+        if (move == NULL) goto ddJumpingDownOutOfMem;
+        move->x = x;
+        move->y = y;
+        move->size = size;
+        move->next = moves;
+        moves = move;
+        if ((double) size > table->maxGrowth * (double) limit_size) {
+            break;
+        } else if (size < limit_size) {
+            limit_size = size;
+        }
+        x = y;
+        y = cuddNextHigh(table,x);
+    }
+    return(moves);
+
+ddJumpingDownOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return(NULL);
+
+} /* end of ddJumpingDown */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the DD to the best position encountered during
+  sifting if there was improvement.]
+
+  Description [Otherwise, "tosses a coin" to decide whether to keep
+  the current configuration or return the DD to the original
+  one. Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+siftBackwardProb(
+  DdManager * table,
+  Move * moves,
+  int  size,
+  double  temp)
+{
+    Move   *move;
+    int    res;
+    int    best_size = size;
+    double coin, threshold;
+
+    /* Look for best size during the last sifting */
+    for (move = moves; move != NULL; move = move->next) {
+        if (move->size < best_size) {
+            best_size = move->size;
+        }
+    }
+    
+    /* If best_size equals size, the last sifting did not produce any
+    ** improvement. We now toss a coin to decide whether to retain
+    ** this change or not.
+    */
+    if (best_size == size) {
+        coin = random_generator();
+#ifdef DD_STATS
+        tosses++;
+#endif
+        threshold = exp(-((double)(table->keys - table->isolated - size))/temp);
+        if (coin < threshold) {
+#ifdef DD_STATS
+            acceptances++;
+#endif
+            return(1);
+        }
+    }
+
+    /* Either there was improvement, or we have decided not to
+    ** accept the uphill move. Go to best position.
+    */
+    res = table->keys - table->isolated;
+    for (move = moves; move != NULL; move = move->next) {
+        if (res == best_size) return(1);
+        res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
+        if (!res) return(0);
+    }
+
+    return(1);
+
+} /* end of sift_backward_prob */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Copies the current variable order to array.]
+
+  Description [Copies the current variable order to array.
+  At the same time inverts the permutation.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+copyOrder(
+  DdManager * table,
+  int * array,
+  int  lower,
+  int  upper)
+{
+    int i;
+    int nvars;
+
+    nvars = upper - lower + 1;
+    for (i = 0; i < nvars; i++) {
+        array[i] = table->invperm[i+lower];
+    }
+
+} /* end of copyOrder */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Restores the variable order in array by a series of sifts up.]
+
+  Description [Restores the variable order in array by a series of sifts up.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+restoreOrder(
+  DdManager * table,
+  int * array,
+  int  lower,
+  int  upper)
+{
+    int i, x, y, size;
+    int nvars = upper - lower + 1;
+
+    for (i = 0; i < nvars; i++) {
+        x = table->perm[array[i]];
+#ifdef DD_DEBUG
+    assert(x >= lower && x <= upper);
+#endif
+        y = cuddNextLow(table,x);
+        while (y >= i + lower) {
+            size = cuddSwapInPlace(table,y,x);
+            if (size == 0) return(0);
+            x = y;
+            y = cuddNextLow(table,x);
+        }
+    }
+
+    return(1);
+
+} /* end of restoreOrder */
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddApa.c b/abc-build/src/bdd/cudd/cuddApa.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddApa.c
@@ -0,0 +1,987 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddApa.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Arbitrary precision arithmetic functions.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_ApaNumberOfDigits()
+                <li> Cudd_NewApaNumber()
+                <li> Cudd_ApaCopy()
+                <li> Cudd_ApaAdd()
+                <li> Cudd_ApaSubtract()
+                <li> Cudd_ApaShortDivision()
+                <li> Cudd_ApaIntDivision()
+                <li> Cudd_ApaShiftRight()
+                <li> Cudd_ApaSetToLiteral()
+                <li> Cudd_ApaPowerOfTwo()
+                <li> Cudd_ApaCompare()
+                <li> Cudd_ApaCompareRatios()
+                <li> Cudd_ApaPrintHex()
+                <li> Cudd_ApaPrintDecimal()
+                <li> Cudd_ApaPrintExponential()
+                <li> Cudd_ApaCountMinterm()
+                <li> Cudd_ApaPrintMinterm()
+                <li> Cudd_ApaPrintMintermExp()
+                <li> Cudd_ApaPrintDensity()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> cuddApaCountMintermAux()
+                <li> cuddApaStCountfree()
+                </ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddApa.c,v 1.19 2009/03/08 01:27:50 fabio Exp $";
+#endif
+
+static  DdNode  *background, *zero;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdApaNumber cuddApaCountMintermAux (DdNode * node, int digits, DdApaNumber max, DdApaNumber min, st__table * table);
+static enum st__retval cuddApaStCountfree (char * key, char * value, char * arg);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the number of digits for an arbitrary precision
+  integer.]
+
+  Description [Finds the number of digits for an arbitrary precision
+  integer given the maximum number of binary digits.  The number of
+  binary digits should be positive. Returns the number of digits if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_ApaNumberOfDigits(
+  int  binaryDigits)
+{
+    int digits;
+
+    digits = binaryDigits / DD_APA_BITS;
+    if ((digits * DD_APA_BITS) != binaryDigits)
+        digits++;
+    return(digits);
+
+} /* end of Cudd_ApaNumberOfDigits */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates memory for an arbitrary precision integer.]
+
+  Description [Allocates memory for an arbitrary precision
+  integer. Returns a pointer to the allocated memory if successful;
+  NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdApaNumber
+Cudd_NewApaNumber(
+  int  digits)
+{
+    return(ABC_ALLOC(DdApaDigit, digits));
+
+} /* end of Cudd_NewApaNumber */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes a copy of an arbitrary precision integer.]
+
+  Description [Makes a copy of an arbitrary precision integer.]
+
+  SideEffects [Changes parameter <code>dest</code>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_ApaCopy(
+  int  digits,
+  DdApaNumber  source,
+  DdApaNumber  dest)
+{
+    int i;
+
+    for (i = 0; i < digits; i++) {
+        dest[i] = source[i];
+    }
+
+} /* end of Cudd_ApaCopy */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds two arbitrary precision integers.]
+
+  Description [Adds two arbitrary precision integers.  Returns the
+  carry out of the most significant digit.]
+
+  SideEffects [The result of the sum is stored in parameter <code>sum</code>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdApaDigit
+Cudd_ApaAdd(
+  int  digits,
+  DdApaNumber  a,
+  DdApaNumber  b,
+  DdApaNumber  sum)
+{
+    int i;
+    DdApaDoubleDigit partial = 0;
+
+    for (i = digits - 1; i >= 0; i--) {
+        partial = a[i] + b[i] + DD_MSDIGIT(partial);
+        sum[i] = (DdApaDigit) DD_LSDIGIT(partial);
+    }
+    return((DdApaDigit) DD_MSDIGIT(partial));
+
+} /* end of Cudd_ApaAdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Subtracts two arbitrary precision integers.]
+
+  Description [Subtracts two arbitrary precision integers.  Returns the
+  borrow out of the most significant digit.]
+
+  SideEffects [The result of the subtraction is stored in parameter
+  <code>diff</code>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdApaDigit
+Cudd_ApaSubtract(
+  int  digits,
+  DdApaNumber  a,
+  DdApaNumber  b,
+  DdApaNumber  diff)
+{
+    int i;
+    DdApaDoubleDigit partial = DD_APA_BASE;
+
+    for (i = digits - 1; i >= 0; i--) {
+        partial = DD_MSDIGIT(partial) + DD_APA_MASK + a[i] - b[i];
+        diff[i] = (DdApaDigit) DD_LSDIGIT(partial);
+    }
+    return((DdApaDigit) DD_MSDIGIT(partial) - 1);
+
+} /* end of Cudd_ApaSubtract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Divides an arbitrary precision integer by a digit.]
+
+  Description [Divides an arbitrary precision integer by a digit.]
+
+  SideEffects [The quotient is returned in parameter <code>quotient</code>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdApaDigit
+Cudd_ApaShortDivision(
+  int  digits,
+  DdApaNumber  dividend,
+  DdApaDigit  divisor,
+  DdApaNumber  quotient)
+{
+    int i;
+    DdApaDigit remainder;
+    DdApaDoubleDigit partial;
+
+    remainder = 0;
+    for (i = 0; i < digits; i++) {
+        partial = remainder * DD_APA_BASE + dividend[i];
+        quotient[i] = (DdApaDigit) (partial/(DdApaDoubleDigit)divisor);
+        remainder = (DdApaDigit) (partial % divisor);
+    }
+
+    return(remainder);
+
+} /* end of Cudd_ApaShortDivision */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Divides an arbitrary precision integer by an integer.]
+
+  Description [Divides an arbitrary precision integer by a 32-bit
+  unsigned integer. Returns the remainder of the division. This
+  procedure relies on the assumption that the number of bits of a
+  DdApaDigit plus the number of bits of an unsigned int is less the
+  number of bits of the mantissa of a double. This guarantees that the
+  product of a DdApaDigit and an unsigned int can be represented
+  without loss of precision by a double. On machines where this
+  assumption is not satisfied, this procedure will malfunction.]
+
+  SideEffects [The quotient is returned in parameter <code>quotient</code>.]
+
+  SeeAlso     [Cudd_ApaShortDivision]
+
+******************************************************************************/
+unsigned int
+Cudd_ApaIntDivision(
+  int  digits,
+  DdApaNumber dividend,
+  unsigned int divisor,
+  DdApaNumber quotient)
+{
+    int i;
+    double partial;
+    unsigned int remainder = 0;
+    double ddiv = (double) divisor;
+
+    for (i = 0; i < digits; i++) {
+        partial = (double) remainder * DD_APA_BASE + dividend[i];
+        quotient[i] = (DdApaDigit) (partial / ddiv);
+        remainder = (unsigned int) (partial - ((double)quotient[i] * ddiv));
+    }
+
+    return(remainder);
+
+} /* end of Cudd_ApaIntDivision */
+
+
+/**Function********************************************************************
+
+  Synopsis [Shifts right an arbitrary precision integer by one binary
+  place.]
+
+  Description [Shifts right an arbitrary precision integer by one
+  binary place. The most significant binary digit of the result is
+  taken from parameter <code>in</code>.]
+
+  SideEffects [The result is returned in parameter <code>b</code>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_ApaShiftRight(
+  int  digits,
+  DdApaDigit  in,
+  DdApaNumber  a,
+  DdApaNumber  b)
+{
+    int i;
+
+    for (i = digits - 1; i > 0; i--) {
+        b[i] = (a[i] >> 1) | ((a[i-1] & 1) << (DD_APA_BITS - 1));
+    }
+    b[0] = (a[0] >> 1) | (in << (DD_APA_BITS - 1));
+
+} /* end of Cudd_ApaShiftRight */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets an arbitrary precision integer to a one-digit literal.]
+
+  Description [Sets an arbitrary precision integer to a one-digit literal.]
+
+  SideEffects [The result is returned in parameter <code>number</code>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_ApaSetToLiteral(
+  int  digits,
+  DdApaNumber  number,
+  DdApaDigit  literal)
+{
+    int i;
+
+    for (i = 0; i < digits - 1; i++)
+        number[i] = 0;
+    number[digits - 1] = literal;
+
+} /* end of Cudd_ApaSetToLiteral */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets an arbitrary precision integer to a power of two.]
+
+  Description [Sets an arbitrary precision integer to a power of
+  two. If the power of two is too large to be represented, the number
+  is set to 0.]
+
+  SideEffects [The result is returned in parameter <code>number</code>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_ApaPowerOfTwo(
+  int  digits,
+  DdApaNumber  number,
+  int  power)
+{
+    int i;
+    int index;
+
+    for (i = 0; i < digits; i++)
+        number[i] = 0;
+    i = digits - 1 - power / DD_APA_BITS;
+    if (i < 0) return;
+    index = power & (DD_APA_BITS - 1);
+    number[i] = 1 << index;
+
+} /* end of Cudd_ApaPowerOfTwo */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two arbitrary precision integers.]
+
+  Description [Compares two arbitrary precision integers. Returns 1 if
+  the first number is larger; 0 if they are equal; -1 if the second
+  number is larger.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_ApaCompare(
+  int digitsFirst,
+  DdApaNumber  first,
+  int digitsSecond,
+  DdApaNumber  second)
+{
+    int i;
+    int firstNZ, secondNZ;
+
+    /* Find first non-zero in both numbers. */
+    for (firstNZ = 0; firstNZ < digitsFirst; firstNZ++)
+        if (first[firstNZ] != 0) break;
+    for (secondNZ = 0; secondNZ < digitsSecond; secondNZ++)
+        if (second[secondNZ] != 0) break;
+    if (digitsFirst - firstNZ > digitsSecond - secondNZ) return(1);
+    else if (digitsFirst - firstNZ < digitsSecond - secondNZ) return(-1);
+    for (i = 0; i < digitsFirst - firstNZ; i++) {
+        if (first[firstNZ + i] > second[secondNZ + i]) return(1);
+        else if (first[firstNZ + i] < second[secondNZ + i]) return(-1);
+    }
+    return(0);
+
+} /* end of Cudd_ApaCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares the ratios of two arbitrary precision integers to two
+  unsigned ints.]
+
+  Description [Compares the ratios of two arbitrary precision integers
+  to two unsigned ints. Returns 1 if the first number is larger; 0 if
+  they are equal; -1 if the second number is larger.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_ApaCompareRatios(
+  int digitsFirst,
+  DdApaNumber firstNum,
+  unsigned int firstDen,
+  int digitsSecond,
+  DdApaNumber secondNum,
+  unsigned int secondDen)
+{
+    int result;
+    DdApaNumber first, second;
+    unsigned int firstRem, secondRem;
+
+    first = Cudd_NewApaNumber(digitsFirst);
+    firstRem = Cudd_ApaIntDivision(digitsFirst,firstNum,firstDen,first);
+    second = Cudd_NewApaNumber(digitsSecond);
+    secondRem = Cudd_ApaIntDivision(digitsSecond,secondNum,secondDen,second);
+    result = Cudd_ApaCompare(digitsFirst,first,digitsSecond,second);
+    ABC_FREE(first);
+    ABC_FREE(second);
+    if (result == 0) {
+        if ((double)firstRem/firstDen > (double)secondRem/secondDen)
+            return(1);
+        else if ((double)firstRem/firstDen < (double)secondRem/secondDen)
+            return(-1);
+    }
+    return(result);
+
+} /* end of Cudd_ApaCompareRatios */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints an arbitrary precision integer in hexadecimal format.]
+
+  Description [Prints an arbitrary precision integer in hexadecimal format.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ApaPrintDecimal Cudd_ApaPrintExponential]
+
+******************************************************************************/
+int
+Cudd_ApaPrintHex(
+  FILE * fp,
+  int  digits,
+  DdApaNumber  number)
+{
+    int i, result;
+
+    for (i = 0; i < digits; i++) {
+        result = fprintf(fp,DD_APA_HEXPRINT,number[i]);
+        if (result == EOF)
+            return(0);
+    }
+    return(1);
+
+} /* end of Cudd_ApaPrintHex */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints an arbitrary precision integer in decimal format.]
+
+  Description [Prints an arbitrary precision integer in decimal format.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ApaPrintHex Cudd_ApaPrintExponential]
+
+******************************************************************************/
+int
+Cudd_ApaPrintDecimal(
+  FILE * fp,
+  int  digits,
+  DdApaNumber  number)
+{
+    int i, result;
+    DdApaDigit remainder;
+    DdApaNumber work;
+    unsigned char *decimal;
+    int leadingzero;
+    int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1;
+
+    work = Cudd_NewApaNumber(digits);
+    if (work == NULL)
+        return(0);
+    decimal = ABC_ALLOC(unsigned char, decimalDigits);
+    if (decimal == NULL) {
+        ABC_FREE(work);
+        return(0);
+    }
+    Cudd_ApaCopy(digits,number,work);
+    for (i = decimalDigits - 1; i >= 0; i--) {
+        remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work);
+        decimal[i] = (unsigned char) remainder;
+    }
+    ABC_FREE(work);
+
+    leadingzero = 1;
+    for (i = 0; i < decimalDigits; i++) {
+        leadingzero = leadingzero && (decimal[i] == 0);
+        if ((!leadingzero) || (i == (decimalDigits - 1))) {
+            result = fprintf(fp,"%1d",decimal[i]);
+            if (result == EOF) {
+                ABC_FREE(decimal);
+                return(0);
+            }
+        }
+    }
+    ABC_FREE(decimal);
+    return(1);
+
+} /* end of Cudd_ApaPrintDecimal */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints an arbitrary precision integer in exponential format.]
+
+  Description [Prints an arbitrary precision integer in exponential format.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ApaPrintHex Cudd_ApaPrintDecimal]
+
+******************************************************************************/
+int
+Cudd_ApaPrintExponential(
+  FILE * fp,
+  int  digits,
+  DdApaNumber  number,
+  int precision)
+{
+    int i, first, last, result;
+    DdApaDigit remainder;
+    DdApaNumber work;
+    unsigned char *decimal;
+    int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1;
+
+    work = Cudd_NewApaNumber(digits);
+    if (work == NULL)
+        return(0);
+    decimal = ABC_ALLOC(unsigned char, decimalDigits);
+    if (decimal == NULL) {
+        ABC_FREE(work);
+        return(0);
+    }
+    Cudd_ApaCopy(digits,number,work);
+    first = decimalDigits - 1;
+    for (i = decimalDigits - 1; i >= 0; i--) {
+        remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work);
+        decimal[i] = (unsigned char) remainder;
+        if (remainder != 0) first = i; /* keep track of MS non-zero */
+    }
+    ABC_FREE(work);
+    last = ddMin(first + precision, decimalDigits);
+
+    for (i = first; i < last; i++) {
+        result = fprintf(fp,"%s%1d",i == first+1 ? "." : "", decimal[i]);
+        if (result == EOF) {
+            ABC_FREE(decimal);
+            return(0);
+        }
+    }
+    ABC_FREE(decimal);
+    result = fprintf(fp,"e+%d",decimalDigits - first - 1);
+    if (result == EOF) {
+        return(0);
+    }
+    return(1);
+
+} /* end of Cudd_ApaPrintExponential */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of minterms of a DD.]
+
+  Description [Counts the number of minterms of a DD. The function is
+  assumed to depend on nvars variables. The minterm count is
+  represented as an arbitrary precision unsigned integer, to allow for
+  any number of variables CUDD supports.  Returns a pointer to the
+  array representing the number of minterms of the function rooted at
+  node if successful; NULL otherwise.]
+
+  SideEffects [The number of digits of the result is returned in
+  parameter <code>digits</code>.]
+
+  SeeAlso     [Cudd_CountMinterm]
+
+******************************************************************************/
+DdApaNumber
+Cudd_ApaCountMinterm(
+  DdManager * manager,
+  DdNode * node,
+  int  nvars,
+  int * digits)
+{
+    DdApaNumber max, min;
+    st__table    *table;
+    DdApaNumber i,count;
+
+    background = manager->background;
+    zero = Cudd_Not(manager->one);
+
+    *digits = Cudd_ApaNumberOfDigits(nvars+1);
+    max = Cudd_NewApaNumber(*digits);
+    if (max == NULL) {
+        return(NULL);
+    }
+    Cudd_ApaPowerOfTwo(*digits,max,nvars);
+    min = Cudd_NewApaNumber(*digits);
+    if (min == NULL) {
+        ABC_FREE(max);
+        return(NULL);
+    }
+    Cudd_ApaSetToLiteral(*digits,min,0);
+    table = st__init_table( st__ptrcmp, st__ptrhash);
+    if (table == NULL) {
+        ABC_FREE(max);
+        ABC_FREE(min);
+        return(NULL);
+    }
+    i = cuddApaCountMintermAux(Cudd_Regular(node),*digits,max,min,table);
+    if (i == NULL) {
+        ABC_FREE(max);
+        ABC_FREE(min);
+        st__foreach(table, cuddApaStCountfree, NULL);
+        st__free_table(table);
+        return(NULL);
+    }
+    count = Cudd_NewApaNumber(*digits);
+    if (count == NULL) {
+        ABC_FREE(max);
+        ABC_FREE(min);
+        st__foreach(table, cuddApaStCountfree, NULL);
+        st__free_table(table);
+        if (Cudd_Regular(node)->ref == 1) ABC_FREE(i);
+        return(NULL);
+    }
+    if (Cudd_IsComplement(node)) {
+        (void) Cudd_ApaSubtract(*digits,max,i,count);
+    } else {
+        Cudd_ApaCopy(*digits,i,count);
+    }
+    ABC_FREE(max);
+    ABC_FREE(min);
+    st__foreach(table, cuddApaStCountfree, NULL);
+    st__free_table(table);
+    if (Cudd_Regular(node)->ref == 1) ABC_FREE(i);
+    return(count);
+
+} /* end of Cudd_ApaCountMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the number of minterms of a BDD or ADD using
+  arbitrary precision arithmetic.]
+
+  Description [Prints the number of minterms of a BDD or ADD using
+  arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ApaPrintMintermExp]
+
+******************************************************************************/
+int
+Cudd_ApaPrintMinterm(
+  FILE * fp,
+  DdManager * dd,
+  DdNode * node,
+  int  nvars)
+{
+    int digits;
+    int result;
+    DdApaNumber count;
+
+    count = Cudd_ApaCountMinterm(dd,node,nvars,&digits);
+    if (count == NULL)
+        return(0);
+    result = Cudd_ApaPrintDecimal(fp,digits,count);
+    ABC_FREE(count);
+    if (fprintf(fp,"\n") == EOF) {
+        return(0);
+    }
+    return(result);
+
+} /* end of Cudd_ApaPrintMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the number of minterms of a BDD or ADD in exponential
+  format using arbitrary precision arithmetic.]
+
+  Description [Prints the number of minterms of a BDD or ADD in
+  exponential format using arbitrary precision arithmetic. Parameter
+  precision controls the number of signficant digits printed. Returns
+  1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ApaPrintMinterm]
+
+******************************************************************************/
+int
+Cudd_ApaPrintMintermExp(
+  FILE * fp,
+  DdManager * dd,
+  DdNode * node,
+  int  nvars,
+  int precision)
+{
+    int digits;
+    int result;
+    DdApaNumber count;
+
+    count = Cudd_ApaCountMinterm(dd,node,nvars,&digits);
+    if (count == NULL)
+        return(0);
+    result = Cudd_ApaPrintExponential(fp,digits,count,precision);
+    ABC_FREE(count);
+    if (fprintf(fp,"\n") == EOF) {
+        return(0);
+    }
+    return(result);
+
+} /* end of Cudd_ApaPrintMintermExp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the density of a BDD or ADD using
+  arbitrary precision arithmetic.]
+
+  Description [Prints the density of a BDD or ADD using
+  arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_ApaPrintDensity(
+  FILE * fp,
+  DdManager * dd,
+  DdNode * node,
+  int  nvars)
+{
+    int digits;
+    int result;
+    DdApaNumber count,density;
+    unsigned int size, remainder, fractional;
+
+    count = Cudd_ApaCountMinterm(dd,node,nvars,&digits);
+    if (count == NULL)
+        return(0);
+    size = Cudd_DagSize(node);
+    density = Cudd_NewApaNumber(digits);
+    remainder = Cudd_ApaIntDivision(digits,count,size,density);
+    result = Cudd_ApaPrintDecimal(fp,digits,density);
+    ABC_FREE(count);
+    ABC_FREE(density);
+    fractional = (unsigned int)((double)remainder / size * 1000000);
+    if (fprintf(fp,".%u\n", fractional) == EOF) {
+        return(0);
+    }
+    return(result);
+
+} /* end of Cudd_ApaPrintDensity */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_ApaCountMinterm.]
+
+  Description [Performs the recursive step of Cudd_ApaCountMinterm.
+  It is based on the following identity. Let |f| be the
+  number of minterms of f. Then:
+  <xmp>
+    |f| = (|f0|+|f1|)/2
+  </xmp>
+  where f0 and f1 are the two cofactors of f.
+  Uses the identity <code>|f'| = max - |f|</code>.
+  The procedure expects the argument "node" to be a regular pointer, and
+  guarantees this condition is met in the recursive calls.
+  For efficiency, the result of a call is cached only if the node has
+  a reference count greater than 1.
+  Returns the number of minterms of the function rooted at node.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static DdApaNumber
+cuddApaCountMintermAux(
+  DdNode * node,
+  int  digits,
+  DdApaNumber  max,
+  DdApaNumber  min,
+  st__table * table)
+{
+    DdNode      *Nt, *Ne;
+    DdApaNumber mint, mint1, mint2;
+    DdApaDigit  carryout;
+
+    if (cuddIsConstant(node)) {
+        if (node == background || node == zero) {
+            return(min);
+        } else {
+            return(max);
+        }
+    }
+    if (node->ref > 1 && st__lookup(table, (const char *)node, (char **)&mint)) {
+        return(mint);
+    }
+
+    Nt = cuddT(node); Ne = cuddE(node);
+
+    mint1 = cuddApaCountMintermAux(Nt,  digits, max, min, table);
+    if (mint1 == NULL) return(NULL);
+    mint2 = cuddApaCountMintermAux(Cudd_Regular(Ne), digits, max, min, table);
+    if (mint2 == NULL) {
+        if (Nt->ref == 1) ABC_FREE(mint1);
+        return(NULL);
+    }
+    mint = Cudd_NewApaNumber(digits);
+    if (mint == NULL) {
+        if (Nt->ref == 1) ABC_FREE(mint1);
+        if (Cudd_Regular(Ne)->ref == 1) ABC_FREE(mint2);
+        return(NULL);
+    }
+    if (Cudd_IsComplement(Ne)) {
+        (void) Cudd_ApaSubtract(digits,max,mint2,mint);
+        carryout = Cudd_ApaAdd(digits,mint1,mint,mint);
+    } else {
+        carryout = Cudd_ApaAdd(digits,mint1,mint2,mint);
+    }
+    Cudd_ApaShiftRight(digits,carryout,mint,mint);
+    /* If the refernce count of a child is 1, its minterm count
+    ** hasn't been stored in table.  Therefore, it must be explicitly
+    ** freed here. */
+    if (Nt->ref == 1) ABC_FREE(mint1);
+    if (Cudd_Regular(Ne)->ref == 1) ABC_FREE(mint2);
+
+    if (node->ref > 1) {
+        if ( st__insert(table, (char *)node, (char *)mint) == st__OUT_OF_MEM) {
+            ABC_FREE(mint);
+            return(NULL);
+        }
+    }
+    return(mint);
+
+} /* end of cuddApaCountMintermAux */
+
+
+/**Function********************************************************************
+
+  Synopsis [Frees the memory used to store the minterm counts recorded
+  in the visited table.]
+
+  Description [Frees the memory used to store the minterm counts
+  recorded in the visited table. Returns st__CONTINUE.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static enum st__retval
+cuddApaStCountfree(
+  char * key,
+  char * value,
+  char * arg)
+{
+    DdApaNumber d;
+
+    d = (DdApaNumber) value;
+    ABC_FREE(d);
+    return( st__CONTINUE);
+
+} /* end of cuddApaStCountfree */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddApprox.c b/abc-build/src/bdd/cudd/cuddApprox.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddApprox.c
@@ -0,0 +1,2213 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddApprox.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Procedures to approximate a given BDD.]
+
+  Description [External procedures provided by this module:
+                <ul>
+                <li> Cudd_UnderApprox()
+                <li> Cudd_OverApprox()
+                <li> Cudd_RemapUnderApprox()
+                <li> Cudd_RemapOverApprox()
+                <li> Cudd_BiasedUnderApprox()
+                <li> Cudd_BiasedOverApprox()
+                </ul>
+               Internal procedures included in this module:
+                <ul>
+                <li> cuddUnderApprox()
+                <li> cuddRemapUnderApprox()
+                <li> cuddBiasedUnderApprox()
+                </ul>
+               Static procedures included in this module:
+                <ul>
+                <li> gatherInfoAux()
+                <li> gatherInfo()
+                <li> computeSavings()
+                <li> UAmarkNodes()
+                <li> UAbuildSubset()
+                <li> updateRefs()
+                <li> RAmarkNodes()
+                <li> BAmarkNodes()
+                <li> RAbuildSubset()
+                </ul>
+                ]
+
+  SeeAlso     [cuddSubsetHB.c cuddSubsetSP.c cuddGenCof.c]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#ifdef __STDC__
+#include <float.h>
+#else
+#define DBL_MAX_EXP 1024
+#endif
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define NOTHING         0
+#define REPLACE_T       1
+#define REPLACE_E       2
+#define REPLACE_N       3
+#define REPLACE_TT      4
+#define REPLACE_TE      5
+
+#define DONT_CARE       0
+#define CARE            1
+#define TOTAL_CARE      2
+#define CARE_ERROR      3
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/* Data structure to store the information on each node. It keeps the
+** number of minterms of the function rooted at this node in terms of
+** the number of variables specified by the user; the number of
+** minterms of the complement; the impact of the number of minterms of
+** this function on the number of minterms of the root function; the
+** reference count of the node from within the root function; the
+** reference count of the node from an internal node; and the flag
+** that says whether the node should be replaced and how. */
+typedef struct NodeData {
+    double mintermsP;           /* minterms for the regular node */
+    double mintermsN;           /* minterms for the complemented node */
+    int functionRef;            /* references from within this function */
+    char care;                  /* node intersects care set */
+    char replace;               /* replacement decision */
+    short int parity;           /* 1: even; 2: odd; 3: both */
+    DdNode *resultP;            /* result for even parity */
+    DdNode *resultN;            /* result for odd parity */
+} NodeData;
+
+typedef struct ApproxInfo {
+    DdNode *one;                /* one constant */
+    DdNode *zero;               /* BDD zero constant */
+    NodeData *page;             /* per-node information */
+    st__table *table;            /* hash table to access the per-node info */
+    int index;                  /* index of the current node */
+    double max;                 /* max number of minterms */
+    int size;                   /* how many nodes are left */
+    double minterms;            /* how many minterms are left */
+} ApproxInfo;
+
+/* Item of the queue used in the levelized traversal of the BDD. */
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+typedef struct GlobalQueueItem {
+    struct GlobalQueueItem *next;
+    struct GlobalQueueItem *cnext;
+    DdNode *node;
+    double impactP;
+    double impactN;
+} GlobalQueueItem;
+ 
+typedef struct LocalQueueItem {
+    struct LocalQueueItem *next;
+    struct LocalQueueItem *cnext;
+    DdNode *node;
+    int localRef;
+} LocalQueueItem;
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+
+    
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddApprox.c,v 1.27 2009/02/19 16:16:51 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void updateParity (DdNode *node, ApproxInfo *info, int newparity);
+static NodeData * gatherInfoAux (DdNode *node, ApproxInfo *info, int parity);
+static ApproxInfo * gatherInfo (DdManager *dd, DdNode *node, int numVars, int parity);
+static int computeSavings (DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue);
+static int updateRefs (DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue);
+static int UAmarkNodes (DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, int safe, double quality);
+static DdNode * UAbuildSubset (DdManager *dd, DdNode *node, ApproxInfo *info);
+static int RAmarkNodes (DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality);
+static int BAmarkNodes (DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality1, double quality0);
+static DdNode * RAbuildSubset (DdManager *dd, DdNode *node, ApproxInfo *info);
+static int BAapplyBias (DdManager *dd, DdNode *f, DdNode *b, ApproxInfo *info, DdHashTable *cache);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Extracts a dense subset from a BDD with Shiple's
+  underapproximation method.]
+
+  Description [Extracts a dense subset from a BDD. This procedure uses
+  a variant of Tom Shiple's underapproximation method. The main
+  difference from the original method is that density is used as cost
+  function.  Returns a pointer to the BDD of the subset if
+  successful. NULL if the procedure runs out of memory. The parameter
+  numVars is the maximum number of variables to be used in minterm
+  calculation.  The optimal number should be as close as possible to
+  the size of the support of f.  However, it is safe to pass the value
+  returned by Cudd_ReadSize for numVars when the number of variables
+  is under 1023.  If numVars is larger than 1023, it will cause
+  overflow. If a 0 parameter is passed then the procedure will compute
+  a value which will avoid overflow but will cause underflow with 2046
+  variables or more.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_UnderApprox(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be subset */,
+  int  numVars /* number of variables in the support of f */,
+  int  threshold /* when to stop approximation */,
+  int  safe /* enforce safe approximation */,
+  double  quality /* minimum improvement for accepted changes */)
+{
+    DdNode *subset;
+
+    do {
+        dd->reordered = 0;
+        subset = cuddUnderApprox(dd, f, numVars, threshold, safe, quality);
+    } while (dd->reordered == 1);
+
+    return(subset);
+
+} /* end of Cudd_UnderApprox */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts a dense superset from a BDD with Shiple's
+  underapproximation method.]
+
+  Description [Extracts a dense superset from a BDD. The procedure is
+  identical to the underapproximation procedure except for the fact that it
+  works on the complement of the given function. Extracting the subset
+  of the complement function is equivalent to extracting the superset
+  of the function.
+  Returns a pointer to the BDD of the superset if successful. NULL if
+  intermediate result causes the procedure to run out of memory. The
+  parameter numVars is the maximum number of variables to be used in
+  minterm calculation.  The optimal number
+  should be as close as possible to the size of the support of f.
+  However, it is safe to pass the value returned by Cudd_ReadSize for
+  numVars when the number of variables is under 1023.  If numVars is
+  larger than 1023, it will overflow. If a 0 parameter is passed then
+  the procedure will compute a value which will avoid overflow but
+  will cause underflow with 2046 variables or more.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_OverApprox(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be superset */,
+  int  numVars /* number of variables in the support of f */,
+  int  threshold /* when to stop approximation */,
+  int  safe /* enforce safe approximation */,
+  double  quality /* minimum improvement for accepted changes */)
+{
+    DdNode *subset, *g;
+
+    g = Cudd_Not(f);    
+    do {
+        dd->reordered = 0;
+        subset = cuddUnderApprox(dd, g, numVars, threshold, safe, quality);
+    } while (dd->reordered == 1);
+    
+    return(Cudd_NotCond(subset, (subset != NULL)));
+    
+} /* end of Cudd_OverApprox */
+
+
+/**Function********************************************************************
+
+  Synopsis [Extracts a dense subset from a BDD with the remapping
+  underapproximation method.]
+
+  Description [Extracts a dense subset from a BDD. This procedure uses
+  a remapping technique and density as the cost function.
+  Returns a pointer to the BDD of the subset if
+  successful. NULL if the procedure runs out of memory. The parameter
+  numVars is the maximum number of variables to be used in minterm
+  calculation.  The optimal number should be as close as possible to
+  the size of the support of f.  However, it is safe to pass the value
+  returned by Cudd_ReadSize for numVars when the number of variables
+  is under 1023.  If numVars is larger than 1023, it will cause
+  overflow. If a 0 parameter is passed then the procedure will compute
+  a value which will avoid overflow but will cause underflow with 2046
+  variables or more.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_UnderApprox Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_RemapUnderApprox(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be subset */,
+  int  numVars /* number of variables in the support of f */,
+  int  threshold /* when to stop approximation */,
+  double  quality /* minimum improvement for accepted changes */)
+{
+    DdNode *subset;
+
+    do {
+        dd->reordered = 0;
+        subset = cuddRemapUnderApprox(dd, f, numVars, threshold, quality);
+    } while (dd->reordered == 1);
+
+    return(subset);
+
+} /* end of Cudd_RemapUnderApprox */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts a dense superset from a BDD with the remapping
+  underapproximation method.]
+
+  Description [Extracts a dense superset from a BDD. The procedure is
+  identical to the underapproximation procedure except for the fact that it
+  works on the complement of the given function. Extracting the subset
+  of the complement function is equivalent to extracting the superset
+  of the function.
+  Returns a pointer to the BDD of the superset if successful. NULL if
+  intermediate result causes the procedure to run out of memory. The
+  parameter numVars is the maximum number of variables to be used in
+  minterm calculation.  The optimal number
+  should be as close as possible to the size of the support of f.
+  However, it is safe to pass the value returned by Cudd_ReadSize for
+  numVars when the number of variables is under 1023.  If numVars is
+  larger than 1023, it will overflow. If a 0 parameter is passed then
+  the procedure will compute a value which will avoid overflow but
+  will cause underflow with 2046 variables or more.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_RemapOverApprox(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be superset */,
+  int  numVars /* number of variables in the support of f */,
+  int  threshold /* when to stop approximation */,
+  double  quality /* minimum improvement for accepted changes */)
+{
+    DdNode *subset, *g;
+
+    g = Cudd_Not(f);    
+    do {
+        dd->reordered = 0;
+        subset = cuddRemapUnderApprox(dd, g, numVars, threshold, quality);
+    } while (dd->reordered == 1);
+    
+    return(Cudd_NotCond(subset, (subset != NULL)));
+    
+} /* end of Cudd_RemapOverApprox */
+
+
+/**Function********************************************************************
+
+  Synopsis [Extracts a dense subset from a BDD with the biased
+  underapproximation method.]
+
+  Description [Extracts a dense subset from a BDD. This procedure uses
+  a biased remapping technique and density as the cost function. The bias
+  is a function. This procedure tries to approximate where the bias is 0
+  and preserve the given function where the bias is 1.
+  Returns a pointer to the BDD of the subset if
+  successful. NULL if the procedure runs out of memory. The parameter
+  numVars is the maximum number of variables to be used in minterm
+  calculation.  The optimal number should be as close as possible to
+  the size of the support of f.  However, it is safe to pass the value
+  returned by Cudd_ReadSize for numVars when the number of variables
+  is under 1023.  If numVars is larger than 1023, it will cause
+  overflow. If a 0 parameter is passed then the procedure will compute
+  a value which will avoid overflow but will cause underflow with 2046
+  variables or more.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_UnderApprox
+  Cudd_RemapUnderApprox Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_BiasedUnderApprox(
+  DdManager *dd /* manager */,
+  DdNode *f /* function to be subset */,
+  DdNode *b /* bias function */,
+  int numVars /* number of variables in the support of f */,
+  int threshold /* when to stop approximation */,
+  double quality1 /* minimum improvement for accepted changes when b=1 */,
+  double quality0 /* minimum improvement for accepted changes when b=0 */)
+{
+    DdNode *subset;
+
+    do {
+        dd->reordered = 0;
+        subset = cuddBiasedUnderApprox(dd, f, b, numVars, threshold, quality1,
+                                       quality0);
+    } while (dd->reordered == 1);
+
+    return(subset);
+
+} /* end of Cudd_BiasedUnderApprox */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts a dense superset from a BDD with the biased
+  underapproximation method.]
+
+  Description [Extracts a dense superset from a BDD. The procedure is
+  identical to the underapproximation procedure except for the fact that it
+  works on the complement of the given function. Extracting the subset
+  of the complement function is equivalent to extracting the superset
+  of the function.
+  Returns a pointer to the BDD of the superset if successful. NULL if
+  intermediate result causes the procedure to run out of memory. The
+  parameter numVars is the maximum number of variables to be used in
+  minterm calculation.  The optimal number
+  should be as close as possible to the size of the support of f.
+  However, it is safe to pass the value returned by Cudd_ReadSize for
+  numVars when the number of variables is under 1023.  If numVars is
+  larger than 1023, it will overflow. If a 0 parameter is passed then
+  the procedure will compute a value which will avoid overflow but
+  will cause underflow with 2046 variables or more.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths
+  Cudd_RemapOverApprox Cudd_BiasedUnderApprox Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_BiasedOverApprox(
+  DdManager *dd /* manager */,
+  DdNode *f /* function to be superset */,
+  DdNode *b /* bias function */,
+  int numVars /* number of variables in the support of f */,
+  int threshold /* when to stop approximation */,
+  double quality1 /* minimum improvement for accepted changes when b=1*/,
+  double quality0 /* minimum improvement for accepted changes when b=0 */)
+{
+    DdNode *subset, *g;
+
+    g = Cudd_Not(f);    
+    do {
+        dd->reordered = 0;
+        subset = cuddBiasedUnderApprox(dd, g, b, numVars, threshold, quality1,
+                                      quality0);
+    } while (dd->reordered == 1);
+    
+    return(Cudd_NotCond(subset, (subset != NULL)));
+    
+} /* end of Cudd_BiasedOverApprox */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Applies Tom Shiple's underappoximation algorithm.]
+
+  Description [Applies Tom Shiple's underappoximation algorithm. Proceeds
+  in three phases:
+  <ul>
+  <li> collect information on each node in the BDD; this is done via DFS.
+  <li> traverse the BDD in top-down fashion and compute for each node
+  whether its elimination increases density.
+  <li> traverse the BDD via DFS and actually perform the elimination.
+  </ul>
+  Returns the approximated BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_UnderApprox]
+
+******************************************************************************/
+DdNode *
+cuddUnderApprox(
+  DdManager * dd /* DD manager */,
+  DdNode * f /* current DD */,
+  int  numVars /* maximum number of variables */,
+  int  threshold /* threshold under which approximation stops */,
+  int  safe /* enforce safe approximation */,
+  double  quality /* minimum improvement for accepted changes */)
+{
+    ApproxInfo *info;
+    DdNode *subset;
+    int result;
+
+    if (f == NULL) {
+        fprintf(dd->err, "Cannot subset, nil object\n");
+        return(NULL);
+    }
+
+    if (Cudd_IsConstant(f)) {
+        return(f);
+    }
+
+    /* Create table where node data are accessible via a hash table. */
+    info = gatherInfo(dd, f, numVars, safe);
+    if (info == NULL) {
+        (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+
+    /* Mark nodes that should be replaced by zero. */
+    result = UAmarkNodes(dd, f, info, threshold, safe, quality);
+    if (result == 0) {
+        (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+        ABC_FREE(info->page);
+        st__free_table(info->table);
+        ABC_FREE(info);
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+
+    /* Build the result. */
+    subset = UAbuildSubset(dd, f, info);
+#if 1
+    if (subset && info->size < Cudd_DagSize(subset))
+        (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
+                       info->size, Cudd_DagSize(subset));
+#endif
+    ABC_FREE(info->page);
+    st__free_table(info->table);
+    ABC_FREE(info);
+
+#ifdef DD_DEBUG
+    if (subset != NULL) {
+        cuddRef(subset);
+#if 0
+        (void) Cudd_DebugCheck(dd);
+        (void) Cudd_CheckKeys(dd);
+#endif
+        if (!Cudd_bddLeq(dd, subset, f)) {
+            (void) fprintf(dd->err, "Wrong subset\n");
+            dd->errorCode = CUDD_INTERNAL_ERROR;
+        }
+        cuddDeref(subset);
+    }
+#endif
+    return(subset);
+
+} /* end of cuddUnderApprox */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Applies the remapping underappoximation algorithm.]
+
+  Description [Applies the remapping underappoximation algorithm.
+  Proceeds in three phases:
+  <ul>
+  <li> collect information on each node in the BDD; this is done via DFS.
+  <li> traverse the BDD in top-down fashion and compute for each node
+  whether remapping increases density.
+  <li> traverse the BDD via DFS and actually perform the elimination.
+  </ul>
+  Returns the approximated BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_RemapUnderApprox]
+
+******************************************************************************/
+DdNode *
+cuddRemapUnderApprox(
+  DdManager * dd /* DD manager */,
+  DdNode * f /* current DD */,
+  int  numVars /* maximum number of variables */,
+  int  threshold /* threshold under which approximation stops */,
+  double  quality /* minimum improvement for accepted changes */)
+{
+    ApproxInfo *info;
+    DdNode *subset;
+    int result;
+
+    if (f == NULL) {
+        fprintf(dd->err, "Cannot subset, nil object\n");
+        dd->errorCode = CUDD_INVALID_ARG;
+        return(NULL);
+    }
+
+    if (Cudd_IsConstant(f)) {
+        return(f);
+    }
+
+    /* Create table where node data are accessible via a hash table. */
+    info = gatherInfo(dd, f, numVars, TRUE);
+    if (info == NULL) {
+        (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+
+    /* Mark nodes that should be replaced by zero. */
+    result = RAmarkNodes(dd, f, info, threshold, quality);
+    if (result == 0) {
+        (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+        ABC_FREE(info->page);
+        st__free_table(info->table);
+        ABC_FREE(info);
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+
+    /* Build the result. */
+    subset = RAbuildSubset(dd, f, info);
+#if 1
+    if (subset && info->size < Cudd_DagSize(subset))
+        (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
+                       info->size, Cudd_DagSize(subset));
+#endif
+    ABC_FREE(info->page);
+    st__free_table(info->table);
+    ABC_FREE(info);
+
+#ifdef DD_DEBUG
+    if (subset != NULL) {
+        cuddRef(subset);
+#if 0
+        (void) Cudd_DebugCheck(dd);
+        (void) Cudd_CheckKeys(dd);
+#endif
+        if (!Cudd_bddLeq(dd, subset, f)) {
+            (void) fprintf(dd->err, "Wrong subset\n");
+        }
+        cuddDeref(subset);
+        dd->errorCode = CUDD_INTERNAL_ERROR;
+    }
+#endif
+    return(subset);
+
+} /* end of cuddRemapUnderApprox */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Applies the biased remapping underappoximation algorithm.]
+
+  Description [Applies the biased remapping underappoximation algorithm.
+  Proceeds in three phases:
+  <ul>
+  <li> collect information on each node in the BDD; this is done via DFS.
+  <li> traverse the BDD in top-down fashion and compute for each node
+  whether remapping increases density.
+  <li> traverse the BDD via DFS and actually perform the elimination.
+  </ul>
+  Returns the approximated BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_BiasedUnderApprox]
+
+******************************************************************************/
+DdNode *
+cuddBiasedUnderApprox(
+  DdManager *dd /* DD manager */,
+  DdNode *f /* current DD */,
+  DdNode *b /* bias function */,
+  int numVars /* maximum number of variables */,
+  int threshold /* threshold under which approximation stops */,
+  double quality1 /* minimum improvement for accepted changes when b=1 */,
+  double quality0 /* minimum improvement for accepted changes when b=0 */)
+{
+    ApproxInfo *info;
+    DdNode *subset;
+    int result;
+    DdHashTable *cache;
+
+    if (f == NULL) {
+        fprintf(dd->err, "Cannot subset, nil object\n");
+        dd->errorCode = CUDD_INVALID_ARG;
+        return(NULL);
+    }
+
+    if (Cudd_IsConstant(f)) {
+        return(f);
+    }
+
+    /* Create table where node data are accessible via a hash table. */
+    info = gatherInfo(dd, f, numVars, TRUE);
+    if (info == NULL) {
+        (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+
+    cache = cuddHashTableInit(dd,2,2);
+    result = BAapplyBias(dd, Cudd_Regular(f), b, info, cache);
+    if (result == CARE_ERROR) {
+        (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+        cuddHashTableQuit(cache);
+        ABC_FREE(info->page);
+        st__free_table(info->table);
+        ABC_FREE(info);
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    cuddHashTableQuit(cache);
+
+    /* Mark nodes that should be replaced by zero. */
+    result = BAmarkNodes(dd, f, info, threshold, quality1, quality0);
+    if (result == 0) {
+        (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+        ABC_FREE(info->page);
+        st__free_table(info->table);
+        ABC_FREE(info);
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+
+    /* Build the result. */
+    subset = RAbuildSubset(dd, f, info);
+#if 1
+    if (subset && info->size < Cudd_DagSize(subset))
+        (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
+                       info->size, Cudd_DagSize(subset));
+#endif
+    ABC_FREE(info->page);
+    st__free_table(info->table);
+    ABC_FREE(info);
+
+#ifdef DD_DEBUG
+    if (subset != NULL) {
+        cuddRef(subset);
+#if 0
+        (void) Cudd_DebugCheck(dd);
+        (void) Cudd_CheckKeys(dd);
+#endif
+        if (!Cudd_bddLeq(dd, subset, f)) {
+            (void) fprintf(dd->err, "Wrong subset\n");
+        }
+        cuddDeref(subset);
+        dd->errorCode = CUDD_INTERNAL_ERROR;
+    }
+#endif
+    return(subset);
+
+} /* end of cuddBiasedUnderApprox */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively update the parity of the paths reaching a node.]
+
+  Description [Recursively update the parity of the paths reaching a node.
+  Assumes that node is regular and propagates the invariant.]
+
+  SideEffects [None]
+
+  SeeAlso     [gatherInfoAux]
+
+******************************************************************************/
+static void
+updateParity(
+  DdNode * node /* function to analyze */,
+  ApproxInfo * info /* info on BDD */,
+  int  newparity /* new parity for node */)
+{
+    NodeData *infoN;
+    DdNode *E;
+
+    if (! st__lookup(info->table, (const char *)node, (char **)&infoN)) return;
+    if ((infoN->parity & newparity) != 0) return;
+    infoN->parity |= (short) newparity;
+    if (Cudd_IsConstant(node)) return;
+    updateParity(cuddT(node),info,newparity);
+    E = cuddE(node);
+    if (Cudd_IsComplement(E)) {
+        updateParity(Cudd_Not(E),info,3-newparity);
+    } else {
+        updateParity(E,info,newparity);
+    }
+    return;
+
+} /* end of updateParity */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively counts minterms and computes reference counts
+  of each node in the BDD.]
+
+  Description [Recursively counts minterms and computes reference
+  counts of each node in the BDD.  Similar to the cuddCountMintermAux
+  which recursively counts the number of minterms for the dag rooted
+  at each node in terms of the total number of variables (max). It assumes
+  that the node pointer passed to it is regular and it maintains the
+  invariant.]
+
+  SideEffects [None]
+
+  SeeAlso     [gatherInfo]
+
+******************************************************************************/
+static NodeData *
+gatherInfoAux(
+  DdNode * node /* function to analyze */,
+  ApproxInfo * info /* info on BDD */,
+  int  parity /* gather parity information */)
+{
+    DdNode      *N, *Nt, *Ne;
+    NodeData    *infoN, *infoT, *infoE;
+
+    N = Cudd_Regular(node);
+
+    /* Check whether entry for this node exists. */
+    if ( st__lookup(info->table, (const char *)N, (char **)&infoN)) {
+        if (parity) {
+            /* Update parity and propagate. */
+            updateParity(N, info, 1 +  (int) Cudd_IsComplement(node));
+        }
+        return(infoN);
+    }
+
+    /* Compute the cofactors. */
+    Nt = Cudd_NotCond(cuddT(N), N != node);
+    Ne = Cudd_NotCond(cuddE(N), N != node);
+
+    infoT = gatherInfoAux(Nt, info, parity);
+    if (infoT == NULL) return(NULL);
+    infoE = gatherInfoAux(Ne, info, parity);
+    if (infoE == NULL) return(NULL);
+
+    infoT->functionRef++;
+    infoE->functionRef++;
+
+    /* Point to the correct location in the page. */
+    infoN = &(info->page[info->index++]);
+    infoN->parity |= (short) (1 + Cudd_IsComplement(node));
+
+    infoN->mintermsP = infoT->mintermsP/2;
+    infoN->mintermsN = infoT->mintermsN/2;
+    if (Cudd_IsComplement(Ne) ^ Cudd_IsComplement(node)) {
+        infoN->mintermsP += infoE->mintermsN/2;
+        infoN->mintermsN += infoE->mintermsP/2;
+    } else {
+        infoN->mintermsP += infoE->mintermsP/2;
+        infoN->mintermsN += infoE->mintermsN/2;
+    }
+
+    /* Insert entry for the node in the table. */
+    if ( st__insert(info->table,(char *)N, (char *)infoN) == st__OUT_OF_MEM) {
+        return(NULL);
+    }
+    return(infoN);
+
+} /* end of gatherInfoAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gathers information about each node.]
+
+  Description [Counts minterms and computes reference counts of each
+  node in the BDD . The minterm count is separately computed for the
+  node and its complement. This is to avoid cancellation
+  errors. Returns a pointer to the data structure holding the
+  information gathered if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUnderApprox gatherInfoAux]
+
+******************************************************************************/
+static ApproxInfo *
+gatherInfo(
+  DdManager * dd /* manager */,
+  DdNode * node /* function to be analyzed */,
+  int  numVars /* number of variables node depends on */,
+  int  parity /* gather parity information */)
+{
+    ApproxInfo  *info;
+    NodeData *infoTop;
+
+    /* If user did not give numVars value, set it to the maximum
+    ** exponent that the pow function can take. The -1 is due to the
+    ** discrepancy in the value that pow takes and the value that
+    ** log gives.
+    */
+    if (numVars == 0) {
+        numVars = DBL_MAX_EXP - 1;
+    }
+
+    info = ABC_ALLOC(ApproxInfo,1);
+    if (info == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    info->max = pow(2.0,(double) numVars);
+    info->one = DD_ONE(dd);
+    info->zero = Cudd_Not(info->one);
+    info->size = Cudd_DagSize(node);
+    /* All the information gathered will be stored in a contiguous
+    ** piece of memory, which is allocated here. This can be done
+    ** efficiently because we have counted the number of nodes of the
+    ** BDD. info->index points to the next available entry in the array
+    ** that stores the per-node information. */
+    info->page = ABC_ALLOC(NodeData,info->size);
+    if (info->page == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        ABC_FREE(info);
+        return(NULL);
+    }
+    memset(info->page, 0, info->size * sizeof(NodeData)); /* clear all page */
+    info->table = st__init_table( st__ptrcmp, st__ptrhash);
+    if (info->table == NULL) {
+        ABC_FREE(info->page);
+        ABC_FREE(info);
+        return(NULL);
+    }
+    /* We visit the DAG in post-order DFS. Hence, the constant node is
+    ** in first position, and the root of the DAG is in last position. */
+
+    /* Info for the constant node: Initialize only fields different from 0. */
+    if ( st__insert(info->table, (char *)info->one, (char *)info->page) == st__OUT_OF_MEM) {
+        ABC_FREE(info->page);
+        ABC_FREE(info);
+        st__free_table(info->table);
+        return(NULL);
+    }
+    info->page[0].mintermsP = info->max;
+    info->index = 1;
+
+    infoTop = gatherInfoAux(node,info,parity);
+    if (infoTop == NULL) {
+        ABC_FREE(info->page);
+        st__free_table(info->table);
+        ABC_FREE(info);
+        return(NULL);
+    }
+    if (Cudd_IsComplement(node)) {
+        info->minterms = infoTop->mintermsN;
+    } else {
+        info->minterms = infoTop->mintermsP;
+    }
+
+    infoTop->functionRef = 1;
+    return(info);
+
+} /* end of gatherInfo */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the nodes that would be eliminated if a given node
+  were replaced by zero.]
+
+  Description [Counts the nodes that would be eliminated if a given
+  node were replaced by zero. This procedure uses a queue passed by
+  the caller for efficiency: since the queue is left empty at the
+  endof the search, it can be reused as is by the next search. Returns
+  the count (always striclty positive) if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUnderApprox]
+
+******************************************************************************/
+static int
+computeSavings(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * skip,
+  ApproxInfo * info,
+  DdLevelQueue * queue)
+{
+    NodeData *infoN;
+    LocalQueueItem *item;
+    DdNode *node;
+    int savings = 0;
+
+    node = Cudd_Regular(f);
+    skip = Cudd_Regular(skip);
+    /* Insert the given node in the level queue. Its local reference
+    ** count is set equal to the function reference count so that the
+    ** search will continue from it when it is retrieved. */
+    item = (LocalQueueItem *)
+        cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
+    if (item == NULL)
+        return(0);
+    (void) st__lookup(info->table, (const char *)node, (char **)&infoN);
+    item->localRef = infoN->functionRef;
+
+    /* Process the queue. */
+    while (queue->first != NULL) {
+        item = (LocalQueueItem *) queue->first;
+        node = item->node;
+        cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
+        if (node == skip) continue;
+        (void) st__lookup(info->table, (const char *)node, (char **)&infoN);
+        if (item->localRef != infoN->functionRef) {
+            /* This node is shared. */
+            continue;
+        }
+        savings++;
+        if (!cuddIsConstant(cuddT(node))) {
+            item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
+                                         cuddI(dd,cuddT(node)->index));
+            if (item == NULL) return(0);
+            item->localRef++;
+        }
+        if (!Cudd_IsConstant(cuddE(node))) {
+            item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
+                                         cuddI(dd,Cudd_Regular(cuddE(node))->index));
+            if (item == NULL) return(0);
+            item->localRef++;
+        }
+    }
+
+#ifdef DD_DEBUG
+    /* At the end of a local search the queue should be empty. */
+    assert(queue->size == 0);
+#endif
+    return(savings);
+
+} /* end of computeSavings */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Update function reference counts.]
+
+  Description [Update function reference counts to account for replacement.
+  Returns the number of nodes saved if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [UAmarkNodes RAmarkNodes]
+
+******************************************************************************/
+static int
+updateRefs(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * skip,
+  ApproxInfo * info,
+  DdLevelQueue * queue)
+{
+    NodeData *infoN;
+    LocalQueueItem *item;
+    DdNode *node;
+    int savings = 0;
+
+    node = Cudd_Regular(f);
+    /* Insert the given node in the level queue. Its function reference
+    ** count is set equal to 0 so that the search will continue from it
+    ** when it is retrieved. */
+    item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
+    if (item == NULL)
+        return(0);
+    (void) st__lookup(info->table, (const char *)node, (char **)&infoN);
+    infoN->functionRef = 0;
+
+    if (skip != NULL) {
+        /* Increase the function reference count of the node to be skipped
+        ** by 1 to account for the node pointing to it that will be created. */
+        skip = Cudd_Regular(skip);
+        (void) st__lookup(info->table, (const char *)skip, (char **)&infoN);
+        infoN->functionRef++;
+    }
+
+    /* Process the queue. */
+    while (queue->first != NULL) {
+        item = (LocalQueueItem *) queue->first;
+        node = item->node;
+        cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
+        (void) st__lookup(info->table, (const char *)node, (char **)&infoN);
+        if (infoN->functionRef != 0) {
+            /* This node is shared or must be skipped. */
+            continue;
+        }
+        savings++;
+        if (!cuddIsConstant(cuddT(node))) {
+            item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
+                                         cuddI(dd,cuddT(node)->index));
+            if (item == NULL) return(0);
+            (void) st__lookup(info->table, (const char *)cuddT(node), (char **)&infoN);
+            infoN->functionRef--;
+        }
+        if (!Cudd_IsConstant(cuddE(node))) {
+            item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
+                                         cuddI(dd,Cudd_Regular(cuddE(node))->index));
+            if (item == NULL) return(0);
+            (void) st__lookup(info->table, (const char *)Cudd_Regular(cuddE(node)), (char **)&infoN);
+            infoN->functionRef--;
+        }
+    }
+
+#ifdef DD_DEBUG
+    /* At the end of a local search the queue should be empty. */
+    assert(queue->size == 0);
+#endif
+    return(savings);
+
+} /* end of updateRefs */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Marks nodes for replacement by zero.]
+
+  Description [Marks nodes for replacement by zero. Returns 1 if successful;
+  0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUnderApprox]
+
+******************************************************************************/
+static int
+UAmarkNodes(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be analyzed */,
+  ApproxInfo * info /* info on BDD */,
+  int  threshold /* when to stop approximating */,
+  int  safe /* enforce safe approximation */,
+  double  quality /* minimum improvement for accepted changes */)
+{
+    DdLevelQueue *queue;
+    DdLevelQueue *localQueue;
+    NodeData *infoN;
+    GlobalQueueItem *item;
+    DdNode *node;
+    double numOnset;
+    double impactP, impactN;
+    int savings;
+
+#if 0
+    (void) printf("initial size = %d initial minterms = %g\n",
+                  info->size, info->minterms);
+#endif
+    queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size);
+    if (queue == NULL) {
+        return(0);
+    }
+    localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem),
+                                    dd->initSlots);
+    if (localQueue == NULL) {
+        cuddLevelQueueQuit(queue);
+        return(0);
+    }
+    node = Cudd_Regular(f);
+    item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
+    if (item == NULL) {
+        cuddLevelQueueQuit(queue);
+        cuddLevelQueueQuit(localQueue);
+        return(0);
+    }
+    if (Cudd_IsComplement(f)) {
+        item->impactP = 0.0;
+        item->impactN = 1.0;
+    } else {
+        item->impactP = 1.0;
+        item->impactN = 0.0;
+    }
+    while (queue->first != NULL) {
+        /* If the size of the subset is below the threshold, quit. */
+        if (info->size <= threshold)
+            break;
+        item = (GlobalQueueItem *) queue->first;
+        node = item->node;
+        node = Cudd_Regular(node);
+        (void) st__lookup(info->table, (const char *)node, (char **)&infoN);
+        if (safe && infoN->parity == 3) {
+            cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
+            continue;
+        }
+        impactP = item->impactP;
+        impactN = item->impactN;
+        numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN;
+        savings = computeSavings(dd,node,NULL,info,localQueue);
+        if (savings == 0) {
+            cuddLevelQueueQuit(queue);
+            cuddLevelQueueQuit(localQueue);
+            return(0);
+        }
+        cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
+#if 0
+        (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n",
+                      node, impactP, impactN, numOnset, savings);
+#endif
+        if ((1 - numOnset / info->minterms) >
+            quality * (1 - (double) savings / info->size)) {
+            infoN->replace = TRUE;
+            info->size -= savings;
+            info->minterms -=numOnset;
+#if 0
+            (void) printf("replace: new size = %d new minterms = %g\n",
+                          info->size, info->minterms);
+#endif
+            savings -= updateRefs(dd,node,NULL,info,localQueue);
+            assert(savings == 0);
+            continue;
+        }
+        if (!cuddIsConstant(cuddT(node))) {
+            item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
+                                         cuddI(dd,cuddT(node)->index));
+            item->impactP += impactP/2.0;
+            item->impactN += impactN/2.0;
+        }
+        if (!Cudd_IsConstant(cuddE(node))) {
+            item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
+                                         cuddI(dd,Cudd_Regular(cuddE(node))->index));
+            if (Cudd_IsComplement(cuddE(node))) {
+                item->impactP += impactN/2.0;
+                item->impactN += impactP/2.0;
+            } else {
+                item->impactP += impactP/2.0;
+                item->impactN += impactN/2.0;
+            }
+        }
+    }
+
+    cuddLevelQueueQuit(queue);
+    cuddLevelQueueQuit(localQueue);
+    return(1);
+
+} /* end of UAmarkNodes */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the subset BDD.] 
+
+  Description [Builds the subset BDD. Based on the info table,
+  replaces selected nodes by zero. Returns a pointer to the result if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUnderApprox]
+
+******************************************************************************/
+static DdNode *
+UAbuildSubset(
+  DdManager * dd /* DD manager */,
+  DdNode * node /* current node */,
+  ApproxInfo * info /* node info */)
+{
+
+    DdNode *Nt, *Ne, *N, *t, *e, *r;
+    NodeData *infoN;
+
+    if (Cudd_IsConstant(node))
+        return(node);
+
+    N = Cudd_Regular(node);
+
+    if ( st__lookup(info->table, (const char *)N, (char **)&infoN)) {
+        if (infoN->replace == TRUE) {
+            return(info->zero);
+        }
+        if (N == node ) {
+            if (infoN->resultP != NULL) {
+                return(infoN->resultP);
+            }
+        } else {
+            if (infoN->resultN != NULL) {
+                return(infoN->resultN);
+            }
+        }
+    } else {
+        (void) fprintf(dd->err,
+                       "Something is wrong, ought to be in info table\n");
+        dd->errorCode = CUDD_INTERNAL_ERROR;
+        return(NULL);
+    }
+
+    Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node));
+    Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node));
+
+    t = UAbuildSubset(dd, Nt, info);
+    if (t == NULL) {
+        return(NULL);
+    }
+    cuddRef(t);
+
+    e = UAbuildSubset(dd, Ne, info);
+    if (e == NULL) {
+        Cudd_RecursiveDeref(dd,t);
+        return(NULL);
+    }
+    cuddRef(e);
+
+    if (Cudd_IsComplement(t)) {
+        t = Cudd_Not(t);
+        e = Cudd_Not(e);
+        r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
+        if (r == NULL) {
+            Cudd_RecursiveDeref(dd, e);
+            Cudd_RecursiveDeref(dd, t);
+            return(NULL);
+        }
+        r = Cudd_Not(r);
+    } else {
+        r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
+        if (r == NULL) {
+            Cudd_RecursiveDeref(dd, e);
+            Cudd_RecursiveDeref(dd, t);
+            return(NULL);
+        }
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    if (N == node) {
+        infoN->resultP = r;
+    } else {
+        infoN->resultN = r;
+    }
+
+    return(r);
+
+} /* end of UAbuildSubset */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Marks nodes for remapping.]
+
+  Description [Marks nodes for remapping. Returns 1 if successful; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddRemapUnderApprox]
+
+******************************************************************************/
+static int
+RAmarkNodes(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be analyzed */,
+  ApproxInfo * info /* info on BDD */,
+  int  threshold /* when to stop approximating */,
+  double  quality /* minimum improvement for accepted changes */)
+{
+    DdLevelQueue *queue;
+    DdLevelQueue *localQueue;
+    NodeData *infoN, *infoT, *infoE;
+    GlobalQueueItem *item;
+    DdNode *node, *T, *E;
+    DdNode *shared; /* grandchild shared by the two children of node */
+    double numOnset;
+    double impact, impactP, impactN;
+    double minterms;
+    int savings;
+    int replace;
+
+#if 0
+    (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n",
+                  info->size, info->minterms);
+#endif
+    queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size);
+    if (queue == NULL) {
+        return(0);
+    }
+    localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem),
+                                    dd->initSlots);
+    if (localQueue == NULL) {
+        cuddLevelQueueQuit(queue);
+        return(0);
+    }
+    /* Enqueue regular pointer to root and initialize impact. */
+    node = Cudd_Regular(f);
+    item = (GlobalQueueItem *)
+        cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
+    if (item == NULL) {
+        cuddLevelQueueQuit(queue);
+        cuddLevelQueueQuit(localQueue);
+        return(0);
+    }
+    if (Cudd_IsComplement(f)) {
+        item->impactP = 0.0;
+        item->impactN = 1.0;
+    } else {
+        item->impactP = 1.0;
+        item->impactN = 0.0;
+    }
+    /* The nodes retrieved here are guaranteed to be non-terminal.
+    ** The initial node is not terminal because constant nodes are
+    ** dealt with in the calling procedure. Subsequent nodes are inserted
+    ** only if they are not terminal. */
+    while (queue->first != NULL) {
+        /* If the size of the subset is below the threshold, quit. */
+        if (info->size <= threshold)
+            break;
+        item = (GlobalQueueItem *) queue->first;
+        node = item->node;
+#ifdef DD_DEBUG
+        assert(item->impactP >= 0 && item->impactP <= 1.0);
+        assert(item->impactN >= 0 && item->impactN <= 1.0);
+        assert(!Cudd_IsComplement(node));
+        assert(!Cudd_IsConstant(node));
+#endif
+        if (! st__lookup(info->table, (const char *)node, (char **)&infoN)) {
+            cuddLevelQueueQuit(queue);
+            cuddLevelQueueQuit(localQueue);
+            return(0);
+        }
+#ifdef DD_DEBUG
+        assert(infoN->parity >= 1 && infoN->parity <= 3);
+#endif
+        if (infoN->parity == 3) {
+            /* This node can be reached through paths of different parity.
+            ** It is not safe to replace it, because remapping will give
+            ** an incorrect result, while replacement by 0 may cause node
+            ** splitting. */
+            cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
+            continue;
+        }
+        T = cuddT(node);
+        E = cuddE(node);
+        shared = NULL;
+        impactP = item->impactP;
+        impactN = item->impactN;
+        if (Cudd_bddLeq(dd,T,E)) {
+            /* Here we know that E is regular. */
+#ifdef DD_DEBUG
+            assert(!Cudd_IsComplement(E));
+#endif
+            (void) st__lookup(info->table, (const char *)T, (char **)&infoT);
+            (void) st__lookup(info->table, (const char *)E, (char **)&infoE);
+            if (infoN->parity == 1) {
+                impact = impactP;
+                minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0;
+                if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
+                    savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
+                    if (savings == 1) {
+                        cuddLevelQueueQuit(queue);
+                        cuddLevelQueueQuit(localQueue);
+                        return(0);
+                    }
+                } else {
+                    savings = 1;
+                }
+                replace = REPLACE_E;
+            } else {
+#ifdef DD_DEBUG
+                assert(infoN->parity == 2);
+#endif
+                impact = impactN;
+                minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0;
+                if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
+                    savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
+                    if (savings == 1) {
+                        cuddLevelQueueQuit(queue);
+                        cuddLevelQueueQuit(localQueue);
+                        return(0);
+                    }
+                } else {
+                    savings = 1;
+                }
+                replace = REPLACE_T;
+            }
+            numOnset = impact * minterms;
+        } else if (Cudd_bddLeq(dd,E,T)) {
+            /* Here E may be complemented. */
+            DdNode *Ereg = Cudd_Regular(E);
+            (void) st__lookup(info->table, (const char *)T, (char **)&infoT);
+            (void) st__lookup(info->table, (const char *)Ereg, (char **)&infoE);
+            if (infoN->parity == 1) {
+                impact = impactP;
+                minterms = infoT->mintermsP/2.0 -
+                    ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0;
+                if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
+                    savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
+                    if (savings == 1) {
+                        cuddLevelQueueQuit(queue);
+                        cuddLevelQueueQuit(localQueue);
+                        return(0);
+                    }
+                } else {
+                    savings = 1;
+                }
+                replace = REPLACE_T;
+            } else {
+#ifdef DD_DEBUG
+                assert(infoN->parity == 2);
+#endif
+                impact = impactN;
+                minterms = ((E == Ereg) ? infoE->mintermsN :
+                            infoE->mintermsP)/2.0 - infoT->mintermsN/2.0;
+                if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
+                    savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
+                    if (savings == 1) {
+                        cuddLevelQueueQuit(queue);
+                        cuddLevelQueueQuit(localQueue);
+                        return(0);
+                    }
+                } else {
+                    savings = 1;
+                }
+                replace = REPLACE_E;
+            }
+            numOnset = impact * minterms;
+        } else {
+            DdNode *Ereg = Cudd_Regular(E);
+            DdNode *TT = cuddT(T);
+            DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E));
+            if (T->index == Ereg->index && TT == ET) {
+                shared = TT;
+                replace = REPLACE_TT;
+            } else {
+                DdNode *TE = cuddE(T);
+                DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E));
+                if (T->index == Ereg->index && TE == EE) {
+                    shared = TE;
+                    replace = REPLACE_TE;
+                } else {
+                    replace = REPLACE_N;
+                }
+            }
+            numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN;
+            savings = computeSavings(dd,node,shared,info,localQueue);
+            if (shared != NULL) {
+                NodeData *infoS;
+                (void) st__lookup(info->table, (const char *)Cudd_Regular(shared), (char **)&infoS);
+                if (Cudd_IsComplement(shared)) {
+                    numOnset -= (infoS->mintermsN * impactP +
+                        infoS->mintermsP * impactN)/2.0;
+                } else {
+                    numOnset -= (infoS->mintermsP * impactP +
+                        infoS->mintermsN * impactN)/2.0;
+                }
+                savings--;
+            }
+        }
+
+        cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
+#if 0
+        if (replace == REPLACE_T || replace == REPLACE_E)
+            (void) printf("node %p: impact = %g numOnset = %g savings %d\n",
+                          node, impact, numOnset, savings);
+        else
+            (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n",
+                          node, impactP, impactN, numOnset, savings);
+#endif
+        if ((1 - numOnset / info->minterms) >
+            quality * (1 - (double) savings / info->size)) {
+            infoN->replace = (char) replace;
+            info->size -= savings;
+            info->minterms -=numOnset;
+#if 0
+            (void) printf("remap(%d): new size = %d new minterms = %g\n",
+                          replace, info->size, info->minterms);
+#endif
+            if (replace == REPLACE_N) {
+                savings -= updateRefs(dd,node,NULL,info,localQueue);
+            } else if (replace == REPLACE_T) {
+                savings -= updateRefs(dd,node,E,info,localQueue);
+            } else if (replace == REPLACE_E) {
+                savings -= updateRefs(dd,node,T,info,localQueue);
+            } else {
+#ifdef DD_DEBUG
+                assert(replace == REPLACE_TT || replace == REPLACE_TE);
+#endif
+                savings -= updateRefs(dd,node,shared,info,localQueue) - 1;
+            }
+            assert(savings == 0);
+        } else {
+            replace = NOTHING;
+        }
+        if (replace == REPLACE_N) continue;
+        if ((replace == REPLACE_E || replace == NOTHING) &&
+            !cuddIsConstant(cuddT(node))) {
+            item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
+                                         cuddI(dd,cuddT(node)->index));
+            if (replace == REPLACE_E) {
+                item->impactP += impactP;
+                item->impactN += impactN;
+            } else {
+                item->impactP += impactP/2.0;
+                item->impactN += impactN/2.0;
+            }
+        }
+        if ((replace == REPLACE_T || replace == NOTHING) &&
+            !Cudd_IsConstant(cuddE(node))) {
+            item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
+                                         cuddI(dd,Cudd_Regular(cuddE(node))->index));
+            if (Cudd_IsComplement(cuddE(node))) {
+                if (replace == REPLACE_T) {
+                    item->impactP += impactN;
+                    item->impactN += impactP;
+                } else {
+                    item->impactP += impactN/2.0;
+                    item->impactN += impactP/2.0;
+                }
+            } else {
+                if (replace == REPLACE_T) {
+                    item->impactP += impactP;
+                    item->impactN += impactN;
+                } else {
+                    item->impactP += impactP/2.0;
+                    item->impactN += impactN/2.0;
+                }
+            }
+        }
+        if ((replace == REPLACE_TT || replace == REPLACE_TE) &&
+            !Cudd_IsConstant(shared)) {
+            item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared),
+                                         cuddI(dd,Cudd_Regular(shared)->index));
+            if (Cudd_IsComplement(shared)) {
+                item->impactP += impactN;
+                item->impactN += impactP;
+            } else {
+                item->impactP += impactP;
+                item->impactN += impactN;
+            }
+        }
+    }
+
+    cuddLevelQueueQuit(queue);
+    cuddLevelQueueQuit(localQueue);
+    return(1);
+
+} /* end of RAmarkNodes */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Marks nodes for remapping.]
+
+  Description [Marks nodes for remapping. Returns 1 if successful; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddRemapUnderApprox]
+
+******************************************************************************/
+static int
+BAmarkNodes(
+  DdManager *dd /* manager */,
+  DdNode *f /* function to be analyzed */,
+  ApproxInfo *info /* info on BDD */,
+  int threshold /* when to stop approximating */,
+  double quality1 /* minimum improvement for accepted changes when b=1 */,
+  double quality0 /* minimum improvement for accepted changes when b=0 */)
+{
+    DdLevelQueue *queue;
+    DdLevelQueue *localQueue;
+    NodeData *infoN, *infoT, *infoE;
+    GlobalQueueItem *item;
+    DdNode *node, *T, *E;
+    DdNode *shared; /* grandchild shared by the two children of node */
+    double numOnset;
+    double impact, impactP, impactN;
+    double minterms;
+    double quality;
+    int savings;
+    int replace;
+
+#if 0
+    (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n",
+                  info->size, info->minterms);
+#endif
+    queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size);
+    if (queue == NULL) {
+        return(0);
+    }
+    localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem),
+                                    dd->initSlots);
+    if (localQueue == NULL) {
+        cuddLevelQueueQuit(queue);
+        return(0);
+    }
+    /* Enqueue regular pointer to root and initialize impact. */
+    node = Cudd_Regular(f);
+    item = (GlobalQueueItem *)
+        cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
+    if (item == NULL) {
+        cuddLevelQueueQuit(queue);
+        cuddLevelQueueQuit(localQueue);
+        return(0);
+    }
+    if (Cudd_IsComplement(f)) {
+        item->impactP = 0.0;
+        item->impactN = 1.0;
+    } else {
+        item->impactP = 1.0;
+        item->impactN = 0.0;
+    }
+    /* The nodes retrieved here are guaranteed to be non-terminal.
+    ** The initial node is not terminal because constant nodes are
+    ** dealt with in the calling procedure. Subsequent nodes are inserted
+    ** only if they are not terminal. */
+    while (queue->first != NULL) {
+        /* If the size of the subset is below the threshold, quit. */
+        if (info->size <= threshold)
+            break;
+        item = (GlobalQueueItem *) queue->first;
+        node = item->node;
+#ifdef DD_DEBUG
+        assert(item->impactP >= 0 && item->impactP <= 1.0);
+        assert(item->impactN >= 0 && item->impactN <= 1.0);
+        assert(!Cudd_IsComplement(node));
+        assert(!Cudd_IsConstant(node));
+#endif
+        if (! st__lookup(info->table, (const char *)node, (char **)&infoN)) {
+            cuddLevelQueueQuit(queue);
+            cuddLevelQueueQuit(localQueue);
+            return(0);
+        }
+        quality = infoN->care ? quality1 : quality0;
+#ifdef DD_DEBUG
+        assert(infoN->parity >= 1 && infoN->parity <= 3);
+#endif
+        if (infoN->parity == 3) {
+            /* This node can be reached through paths of different parity.
+            ** It is not safe to replace it, because remapping will give
+            ** an incorrect result, while replacement by 0 may cause node
+            ** splitting. */
+            cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
+            continue;
+        }
+        T = cuddT(node);
+        E = cuddE(node);
+        shared = NULL;
+        impactP = item->impactP;
+        impactN = item->impactN;
+        if (Cudd_bddLeq(dd,T,E)) {
+            /* Here we know that E is regular. */
+#ifdef DD_DEBUG
+            assert(!Cudd_IsComplement(E));
+#endif
+            (void) st__lookup(info->table, (const char *)T, (char **)&infoT);
+            (void) st__lookup(info->table, (const char *)E, (char **)&infoE);
+            if (infoN->parity == 1) {
+                impact = impactP;
+                minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0;
+                if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
+                    savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
+                    if (savings == 1) {
+                        cuddLevelQueueQuit(queue);
+                        cuddLevelQueueQuit(localQueue);
+                        return(0);
+                    }
+                } else {
+                    savings = 1;
+                }
+                replace = REPLACE_E;
+            } else {
+#ifdef DD_DEBUG
+                assert(infoN->parity == 2);
+#endif
+                impact = impactN;
+                minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0;
+                if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
+                    savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
+                    if (savings == 1) {
+                        cuddLevelQueueQuit(queue);
+                        cuddLevelQueueQuit(localQueue);
+                        return(0);
+                    }
+                } else {
+                    savings = 1;
+                }
+                replace = REPLACE_T;
+            }
+            numOnset = impact * minterms;
+        } else if (Cudd_bddLeq(dd,E,T)) {
+            /* Here E may be complemented. */
+            DdNode *Ereg = Cudd_Regular(E);
+            (void) st__lookup(info->table, (const char *)T, (char **)&infoT);
+            (void) st__lookup(info->table, (const char *)Ereg, (char **)&infoE);
+            if (infoN->parity == 1) {
+                impact = impactP;
+                minterms = infoT->mintermsP/2.0 -
+                    ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0;
+                if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
+                    savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
+                    if (savings == 1) {
+                        cuddLevelQueueQuit(queue);
+                        cuddLevelQueueQuit(localQueue);
+                        return(0);
+                    }
+                } else {
+                    savings = 1;
+                }
+                replace = REPLACE_T;
+            } else {
+#ifdef DD_DEBUG
+                assert(infoN->parity == 2);
+#endif
+                impact = impactN;
+                minterms = ((E == Ereg) ? infoE->mintermsN :
+                            infoE->mintermsP)/2.0 - infoT->mintermsN/2.0;
+                if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
+                    savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
+                    if (savings == 1) {
+                        cuddLevelQueueQuit(queue);
+                        cuddLevelQueueQuit(localQueue);
+                        return(0);
+                    }
+                } else {
+                    savings = 1;
+                }
+                replace = REPLACE_E;
+            }
+            numOnset = impact * minterms;
+        } else {
+            DdNode *Ereg = Cudd_Regular(E);
+            DdNode *TT = cuddT(T);
+            DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E));
+            if (T->index == Ereg->index && TT == ET) {
+                shared = TT;
+                replace = REPLACE_TT;
+            } else {
+                DdNode *TE = cuddE(T);
+                DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E));
+                if (T->index == Ereg->index && TE == EE) {
+                    shared = TE;
+                    replace = REPLACE_TE;
+                } else {
+                    replace = REPLACE_N;
+                }
+            }
+            numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN;
+            savings = computeSavings(dd,node,shared,info,localQueue);
+            if (shared != NULL) {
+                NodeData *infoS;
+                (void) st__lookup(info->table, (const char *)Cudd_Regular(shared), (char **)&infoS);
+                if (Cudd_IsComplement(shared)) {
+                    numOnset -= (infoS->mintermsN * impactP +
+                        infoS->mintermsP * impactN)/2.0;
+                } else {
+                    numOnset -= (infoS->mintermsP * impactP +
+                        infoS->mintermsN * impactN)/2.0;
+                }
+                savings--;
+            }
+        }
+
+        cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
+#if 0
+        if (replace == REPLACE_T || replace == REPLACE_E)
+            (void) printf("node %p: impact = %g numOnset = %g savings %d\n",
+                          node, impact, numOnset, savings);
+        else
+            (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n",
+                          node, impactP, impactN, numOnset, savings);
+#endif
+        if ((1 - numOnset / info->minterms) >
+            quality * (1 - (double) savings / info->size)) {
+            infoN->replace = (char) replace;
+            info->size -= savings;
+            info->minterms -=numOnset;
+#if 0
+            (void) printf("remap(%d): new size = %d new minterms = %g\n",
+                          replace, info->size, info->minterms);
+#endif
+            if (replace == REPLACE_N) {
+                savings -= updateRefs(dd,node,NULL,info,localQueue);
+            } else if (replace == REPLACE_T) {
+                savings -= updateRefs(dd,node,E,info,localQueue);
+            } else if (replace == REPLACE_E) {
+                savings -= updateRefs(dd,node,T,info,localQueue);
+            } else {
+#ifdef DD_DEBUG
+                assert(replace == REPLACE_TT || replace == REPLACE_TE);
+#endif
+                savings -= updateRefs(dd,node,shared,info,localQueue) - 1;
+            }
+            assert(savings == 0);
+        } else {
+            replace = NOTHING;
+        }
+        if (replace == REPLACE_N) continue;
+        if ((replace == REPLACE_E || replace == NOTHING) &&
+            !cuddIsConstant(cuddT(node))) {
+            item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
+                                         cuddI(dd,cuddT(node)->index));
+            if (replace == REPLACE_E) {
+                item->impactP += impactP;
+                item->impactN += impactN;
+            } else {
+                item->impactP += impactP/2.0;
+                item->impactN += impactN/2.0;
+            }
+        }
+        if ((replace == REPLACE_T || replace == NOTHING) &&
+            !Cudd_IsConstant(cuddE(node))) {
+            item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
+                                         cuddI(dd,Cudd_Regular(cuddE(node))->index));
+            if (Cudd_IsComplement(cuddE(node))) {
+                if (replace == REPLACE_T) {
+                    item->impactP += impactN;
+                    item->impactN += impactP;
+                } else {
+                    item->impactP += impactN/2.0;
+                    item->impactN += impactP/2.0;
+                }
+            } else {
+                if (replace == REPLACE_T) {
+                    item->impactP += impactP;
+                    item->impactN += impactN;
+                } else {
+                    item->impactP += impactP/2.0;
+                    item->impactN += impactN/2.0;
+                }
+            }
+        }
+        if ((replace == REPLACE_TT || replace == REPLACE_TE) &&
+            !Cudd_IsConstant(shared)) {
+            item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared),
+                                         cuddI(dd,Cudd_Regular(shared)->index));
+            if (Cudd_IsComplement(shared)) {
+                if (replace == REPLACE_T) {
+                    item->impactP += impactN;
+                    item->impactN += impactP;
+                } else {
+                    item->impactP += impactN/2.0;
+                    item->impactN += impactP/2.0;
+                }
+            } else {
+                if (replace == REPLACE_T) {
+                    item->impactP += impactP;
+                    item->impactN += impactN;
+                } else {
+                    item->impactP += impactP/2.0;
+                    item->impactN += impactN/2.0;
+                }
+            }
+        }
+    }
+
+    cuddLevelQueueQuit(queue);
+    cuddLevelQueueQuit(localQueue);
+    return(1);
+
+} /* end of BAmarkNodes */
+
+
+/**Function********************************************************************
+
+  Synopsis [Builds the subset BDD for cuddRemapUnderApprox.]
+
+  Description [Builds the subset BDDfor cuddRemapUnderApprox.  Based
+  on the info table, performs remapping or replacement at selected
+  nodes. Returns a pointer to the result if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddRemapUnderApprox]
+
+******************************************************************************/
+static DdNode *
+RAbuildSubset(
+  DdManager * dd /* DD manager */,
+  DdNode * node /* current node */,
+  ApproxInfo * info /* node info */)
+{
+    DdNode *Nt, *Ne, *N, *t, *e, *r;
+    NodeData *infoN;
+
+    if (Cudd_IsConstant(node))
+        return(node);
+
+    N = Cudd_Regular(node);
+
+    Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node));
+    Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node));
+
+    if ( st__lookup(info->table, (const char *)N, (char **)&infoN)) {
+        if (N == node ) {
+            if (infoN->resultP != NULL) {
+                return(infoN->resultP);
+            }
+        } else {
+            if (infoN->resultN != NULL) {
+                return(infoN->resultN);
+            }
+        }
+        if (infoN->replace == REPLACE_T) {
+            r = RAbuildSubset(dd, Ne, info);
+            return(r);
+        } else if (infoN->replace == REPLACE_E) {
+            r = RAbuildSubset(dd, Nt, info);
+            return(r);
+        } else if (infoN->replace == REPLACE_N) {
+            return(info->zero);
+        } else if (infoN->replace == REPLACE_TT) {
+            DdNode *Ntt = Cudd_NotCond(cuddT(cuddT(N)),
+                                       Cudd_IsComplement(node));
+            int index = cuddT(N)->index;
+            e = info->zero;
+            t = RAbuildSubset(dd, Ntt, info);
+            if (t == NULL) {
+                return(NULL);
+            }
+            cuddRef(t);
+            if (Cudd_IsComplement(t)) {
+                t = Cudd_Not(t);
+                e = Cudd_Not(e);
+                r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+                if (r == NULL) {
+                    Cudd_RecursiveDeref(dd, t);
+                    return(NULL);
+                }
+                r = Cudd_Not(r);
+            } else {
+                r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+                if (r == NULL) {
+                    Cudd_RecursiveDeref(dd, t);
+                    return(NULL);
+                }
+            }
+            cuddDeref(t);
+            return(r);
+        } else if (infoN->replace == REPLACE_TE) {
+            DdNode *Nte = Cudd_NotCond(cuddE(cuddT(N)),
+                                       Cudd_IsComplement(node));
+            int index = cuddT(N)->index;
+            t = info->one;
+            e = RAbuildSubset(dd, Nte, info);
+            if (e == NULL) {
+                return(NULL);
+            }
+            cuddRef(e);
+            e = Cudd_Not(e);
+            r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+            if (r == NULL) {
+                Cudd_RecursiveDeref(dd, e);
+                return(NULL);
+            }
+            r =Cudd_Not(r);
+            cuddDeref(e);
+            return(r);
+        }
+    } else {
+        (void) fprintf(dd->err,
+                       "Something is wrong, ought to be in info table\n");
+        dd->errorCode = CUDD_INTERNAL_ERROR;
+        return(NULL);
+    }
+
+    t = RAbuildSubset(dd, Nt, info);
+    if (t == NULL) {
+        return(NULL);
+    }
+    cuddRef(t);
+
+    e = RAbuildSubset(dd, Ne, info);
+    if (e == NULL) {
+        Cudd_RecursiveDeref(dd,t);
+        return(NULL);
+    }
+    cuddRef(e);
+
+    if (Cudd_IsComplement(t)) {
+        t = Cudd_Not(t);
+        e = Cudd_Not(e);
+        r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
+        if (r == NULL) {
+            Cudd_RecursiveDeref(dd, e);
+            Cudd_RecursiveDeref(dd, t);
+            return(NULL);
+        }
+        r = Cudd_Not(r);
+    } else {
+        r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
+        if (r == NULL) {
+            Cudd_RecursiveDeref(dd, e);
+            Cudd_RecursiveDeref(dd, t);
+            return(NULL);
+        }
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    if (N == node) {
+        infoN->resultP = r;
+    } else {
+        infoN->resultN = r;
+    }
+
+    return(r);
+
+} /* end of RAbuildSubset */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds don't care nodes.]
+
+  Description [Finds don't care nodes by traversing f and b in parallel.
+  Returns the care status of the visited f node if successful; CARE_ERROR
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddBiasedUnderApprox]
+
+******************************************************************************/
+static int
+BAapplyBias(
+  DdManager *dd,
+  DdNode *f,
+  DdNode *b,
+  ApproxInfo *info,
+  DdHashTable *cache)
+{
+    DdNode *one, *zero, *res;
+    DdNode *Ft, *Fe, *B, *Bt, *Be;
+    unsigned int topf, topb;
+    NodeData *infoF;
+    int careT, careE;
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    if (! st__lookup(info->table, (const char *)f, (char **)&infoF))
+        return(CARE_ERROR);
+    if (f == one) return(TOTAL_CARE);
+    if (b == zero) return(infoF->care);
+    if (infoF->care == TOTAL_CARE) return(TOTAL_CARE);
+
+    if ((f->ref != 1 || Cudd_Regular(b)->ref != 1) &&
+        (res = cuddHashTableLookup2(cache,f,b)) != NULL) {
+        if (res->ref == 0) {
+            cache->manager->dead++;
+            cache->manager->constants.dead++;
+        }
+        return(infoF->care);
+    }
+
+    topf = dd->perm[f->index];
+    B = Cudd_Regular(b);
+    topb = cuddI(dd,B->index);
+    if (topf <= topb) {
+        Ft = cuddT(f); Fe = cuddE(f);
+    } else {
+        Ft = Fe = f;
+    }
+    if (topb <= topf) {
+        /* We know that b is not constant because f is not. */
+        Bt = cuddT(B); Be = cuddE(B);
+        if (Cudd_IsComplement(b)) {
+            Bt = Cudd_Not(Bt);
+            Be = Cudd_Not(Be);
+        }
+    } else {
+        Bt = Be = b;
+    }
+
+    careT = BAapplyBias(dd, Ft, Bt, info, cache);
+    if (careT == CARE_ERROR)
+        return(CARE_ERROR);
+    careE = BAapplyBias(dd, Cudd_Regular(Fe), Be, info, cache);
+    if (careE == CARE_ERROR)
+        return(CARE_ERROR);
+    if (careT == TOTAL_CARE && careE == TOTAL_CARE) {
+        infoF->care = TOTAL_CARE;
+    } else {
+        infoF->care = CARE;
+    }
+
+    if (f->ref != 1 || Cudd_Regular(b)->ref != 1) {
+        ptrint fanout = (ptrint) f->ref * Cudd_Regular(b)->ref;
+        cuddSatDec(fanout);
+        if (!cuddHashTableInsert2(cache,f,b,one,fanout)) {
+            return(CARE_ERROR);
+        }
+    }
+    return(infoF->care);
+
+} /* end of BAapplyBias */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddBddAbs.c b/abc-build/src/bdd/cudd/cuddBddAbs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddBddAbs.c
@@ -0,0 +1,725 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddBddAbs.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Quantification functions for BDDs.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_bddExistAbstract()
+                <li> Cudd_bddXorExistAbstract()
+                <li> Cudd_bddUnivAbstract()
+                <li> Cudd_bddBooleanDiff()
+                <li> Cudd_bddVarIsDependent()
+                </ul>
+        Internal procedures included in this module:
+                <ul>
+                <li> cuddBddExistAbstractRecur()
+                <li> cuddBddXorExistAbstractRecur()
+                <li> cuddBddBooleanDiffRecur()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> bddCheckPositiveCube()
+                </ul>
+                ]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddBddAbs.c,v 1.26 2004/08/13 18:04:46 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int bddCheckPositiveCube (DdManager *manager, DdNode *cube);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Existentially abstracts all the variables in cube from f.]
+
+  Description [Existentially abstracts all the variables in cube from f.
+  Returns the abstracted BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddUnivAbstract Cudd_addExistAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_bddExistAbstract(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode *res;
+
+    if (bddCheckPositiveCube(manager, cube) == 0) {
+        (void) fprintf(manager->err,
+                       "Error: Can only abstract positive cubes\n");
+        manager->errorCode = CUDD_INVALID_ARG;
+        return(NULL);
+    }
+
+    do {
+        manager->reordered = 0;
+        res = cuddBddExistAbstractRecur(manager, f, cube);
+    } while (manager->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_bddExistAbstract */
+
+
+/**Function********************************************************************
+
+  Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the
+  variables in cube.]
+
+  Description [Takes the exclusive OR of two BDDs and simultaneously abstracts
+  the variables in cube. The variables are existentially abstracted.  Returns a
+  pointer to the result is successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddUnivAbstract Cudd_bddExistAbstract Cudd_bddAndAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_bddXorExistAbstract(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  DdNode * cube)
+{
+    DdNode *res;
+
+    if (bddCheckPositiveCube(manager, cube) == 0) {
+        (void) fprintf(manager->err,
+                       "Error: Can only abstract positive cubes\n");
+        manager->errorCode = CUDD_INVALID_ARG;
+        return(NULL);
+    }
+
+    do {
+        manager->reordered = 0;
+        res = cuddBddXorExistAbstractRecur(manager, f, g, cube);
+    } while (manager->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_bddXorExistAbstract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Universally abstracts all the variables in cube from f.]
+
+  Description [Universally abstracts all the variables in cube from f.
+  Returns the abstracted BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddExistAbstract Cudd_addUnivAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_bddUnivAbstract(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode      *res;
+
+    if (bddCheckPositiveCube(manager, cube) == 0) {
+        (void) fprintf(manager->err,
+                       "Error: Can only abstract positive cubes\n");
+        manager->errorCode = CUDD_INVALID_ARG;
+        return(NULL);
+    }
+
+    do {
+        manager->reordered = 0;
+        res = cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube);
+    } while (manager->reordered == 1);
+    if (res != NULL) res = Cudd_Not(res);
+
+    return(res);
+
+} /* end of Cudd_bddUnivAbstract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the boolean difference of f with respect to x.]
+
+  Description [Computes the boolean difference of f with respect to the
+  variable with index x.  Returns the BDD of the boolean difference if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_bddBooleanDiff(
+  DdManager * manager,
+  DdNode * f,
+  int  x)
+{
+    DdNode *res, *var;
+
+    /* If the variable is not currently in the manager, f cannot
+    ** depend on it.
+    */
+    if (x >= manager->size) return(Cudd_Not(DD_ONE(manager)));
+    var = manager->vars[x];
+
+    do {
+        manager->reordered = 0;
+        res = cuddBddBooleanDiffRecur(manager, Cudd_Regular(f), var);
+    } while (manager->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_bddBooleanDiff */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is dependent on others in a
+  function.]
+
+  Description [Checks whether a variable is dependent on others in a
+  function.  Returns 1 if the variable is dependent; 0 otherwise. No
+  new nodes are created.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_bddVarIsDependent(
+  DdManager *dd,                /* manager */
+  DdNode *f,                    /* function */
+  DdNode *var                   /* variable */)
+{
+    DdNode *F, *res, *zero, *ft, *fe;
+    unsigned topf, level;
+    DD_CTFP cacheOp;
+    int retval;
+
+    zero = Cudd_Not(DD_ONE(dd));
+    if (Cudd_IsConstant(f)) return(f == zero);
+
+    /* From now on f is not constant. */
+    F = Cudd_Regular(f);
+    topf = (unsigned) dd->perm[F->index];
+    level = (unsigned) dd->perm[var->index];
+
+    /* Check terminal case. If topf > index of var, f does not depend on var.
+    ** Therefore, var is not dependent in f. */
+    if (topf > level) {
+        return(0);
+    }
+
+    cacheOp = (DD_CTFP) Cudd_bddVarIsDependent;
+    res = cuddCacheLookup2(dd,cacheOp,f,var);
+    if (res != NULL) {
+        return(res != zero);
+    }
+
+    /* Compute cofactors. */
+    ft = Cudd_NotCond(cuddT(F), f != F);
+    fe = Cudd_NotCond(cuddE(F), f != F);
+
+    if (topf == level) {
+        retval = Cudd_bddLeq(dd,ft,Cudd_Not(fe));
+    } else {
+        retval = Cudd_bddVarIsDependent(dd,ft,var) &&
+            Cudd_bddVarIsDependent(dd,fe,var);
+    }
+
+    cuddCacheInsert2(dd,cacheOp,f,var,Cudd_NotCond(zero,retval));
+
+    return(retval);
+
+} /* Cudd_bddVarIsDependent */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive steps of Cudd_bddExistAbstract.]
+
+  Description [Performs the recursive steps of Cudd_bddExistAbstract.
+  Returns the BDD obtained by abstracting the variables
+  of cube from f if successful; NULL otherwise. It is also used by
+  Cudd_bddUnivAbstract.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddExistAbstract Cudd_bddUnivAbstract]
+
+******************************************************************************/
+DdNode *
+cuddBddExistAbstractRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode      *F, *T, *E, *res, *res1, *res2, *one;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+    F = Cudd_Regular(f);
+
+    /* Cube is guaranteed to be a cube at this point. */        
+    if (cube == one || F == one) {  
+        return(f);
+    }
+    /* From now on, f and cube are non-constant. */
+
+    /* Abstract a variable that does not appear in f. */
+    while (manager->perm[F->index] > manager->perm[cube->index]) {
+        cube = cuddT(cube);
+        if (cube == one) return(f);
+    }
+
+    /* Check the cache. */
+    if (F->ref != 1 && (res = cuddCacheLookup2(manager, Cudd_bddExistAbstract, f, cube)) != NULL) {
+        return(res);
+    }
+
+    /* Compute the cofactors of f. */
+    T = cuddT(F); E = cuddE(F);
+    if (f != F) {
+        T = Cudd_Not(T); E = Cudd_Not(E);
+    }
+
+    /* If the two indices are the same, so are their levels. */
+    if (F->index == cube->index) {
+        if (T == one || E == one || T == Cudd_Not(E)) {
+            return(one);
+        }
+        res1 = cuddBddExistAbstractRecur(manager, T, cuddT(cube));
+        if (res1 == NULL) return(NULL);
+        if (res1 == one) {
+            if (F->ref != 1)
+                cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, one);
+            return(one);
+        }
+        cuddRef(res1);
+        res2 = cuddBddExistAbstractRecur(manager, E, cuddT(cube));
+        if (res2 == NULL) {
+            Cudd_IterDerefBdd(manager,res1);
+            return(NULL);
+        }
+        cuddRef(res2);
+        res = cuddBddAndRecur(manager, Cudd_Not(res1), Cudd_Not(res2));
+        if (res == NULL) {
+            Cudd_IterDerefBdd(manager, res1);
+            Cudd_IterDerefBdd(manager, res2);
+            return(NULL);
+        }
+        res = Cudd_Not(res);
+        cuddRef(res);
+        Cudd_IterDerefBdd(manager, res1);
+        Cudd_IterDerefBdd(manager, res2);
+        if (F->ref != 1)
+            cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res);
+        cuddDeref(res);
+        return(res);
+    } else { /* if (cuddI(manager,F->index) < cuddI(manager,cube->index)) */
+        res1 = cuddBddExistAbstractRecur(manager, T, cube);
+        if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+        res2 = cuddBddExistAbstractRecur(manager, E, cube);
+        if (res2 == NULL) {
+            Cudd_IterDerefBdd(manager, res1);
+            return(NULL);
+        }
+        cuddRef(res2);
+        /* ITE takes care of possible complementation of res1 and of the
+        ** case in which res1 == res2. */
+        res = cuddBddIteRecur(manager, manager->vars[F->index], res1, res2);
+        if (res == NULL) {
+            Cudd_IterDerefBdd(manager, res1);
+            Cudd_IterDerefBdd(manager, res2);
+            return(NULL);
+        }
+        cuddRef(res); //Added
+        Cudd_IterDerefBdd(manager, res1); //cuddDeref(res1);
+        Cudd_IterDerefBdd(manager, res2); //cuddDeref(res2);
+        cuddDeref(res); //Added
+        if (F->ref != 1)
+            cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res);
+        return(res);
+    }       
+
+} /* end of cuddBddExistAbstractRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the
+  variables in cube.]
+
+  Description [Takes the exclusive OR of two BDDs and simultaneously abstracts
+  the variables in cube. The variables are existentially abstracted.  Returns a
+  pointer to the result is successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddAndAbstract]
+
+******************************************************************************/
+DdNode *
+cuddBddXorExistAbstractRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  DdNode * cube)
+{
+    DdNode *F, *fv, *fnv, *G, *gv, *gnv;
+    DdNode *one, *zero, *r, *t, *e, *Cube;
+    unsigned int topf, topg, topcube, top, index;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    /* Terminal cases. */
+    if (f == g) {
+        return(zero);
+    }
+    if (f == Cudd_Not(g)) {
+        return(one);
+    }
+    if (cube == one) {
+        return(cuddBddXorRecur(manager, f, g));
+    }
+    if (f == one) {
+        return(cuddBddExistAbstractRecur(manager, Cudd_Not(g), cube));
+    }
+    if (g == one) {
+        return(cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube));
+    }
+    if (f == zero) {
+        return(cuddBddExistAbstractRecur(manager, g, cube));
+    }
+    if (g == zero) {
+        return(cuddBddExistAbstractRecur(manager, f, cube));
+    }
+
+    /* At this point f, g, and cube are not constant. */
+
+    if (cuddF2L(f) > cuddF2L(g)) { /* Try to increase cache efficiency. */
+        DdNode *tmp = f;
+        f = g;
+        g = tmp;
+    }
+
+    /* Check cache. */
+    r = cuddCacheLookup(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube);
+    if (r != NULL) {
+        return(r);
+    }
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    F = Cudd_Regular(f);
+    topf = manager->perm[F->index];
+    G = Cudd_Regular(g);
+    topg = manager->perm[G->index];
+    top = ddMin(topf, topg);
+    topcube = manager->perm[cube->index];
+
+    if (topcube < top) {
+        return(cuddBddXorExistAbstractRecur(manager, f, g, cuddT(cube)));
+    }
+    /* Now, topcube >= top. */
+
+    if (topf == top) {
+        index = F->index;
+        fv = cuddT(F);
+        fnv = cuddE(F);
+        if (Cudd_IsComplement(f)) {
+            fv = Cudd_Not(fv);
+            fnv = Cudd_Not(fnv);
+        }
+    } else {
+        index = G->index;
+        fv = fnv = f;
+    }
+
+    if (topg == top) {
+        gv = cuddT(G);
+        gnv = cuddE(G);
+        if (Cudd_IsComplement(g)) {
+            gv = Cudd_Not(gv);
+            gnv = Cudd_Not(gnv);
+        }
+    } else {
+        gv = gnv = g;
+    }
+
+    if (topcube == top) {
+        Cube = cuddT(cube);
+    } else {
+        Cube = cube;
+    }
+
+    t = cuddBddXorExistAbstractRecur(manager, fv, gv, Cube);
+    if (t == NULL) return(NULL);
+
+    /* Special case: 1 OR anything = 1. Hence, no need to compute
+    ** the else branch if t is 1.
+    */
+    if (t == one && topcube == top) {
+        cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, one);
+        return(one);
+    }
+    cuddRef(t);
+
+    e = cuddBddXorExistAbstractRecur(manager, fnv, gnv, Cube);
+    if (e == NULL) {
+        Cudd_IterDerefBdd(manager, t);
+        return(NULL);
+    }
+    cuddRef(e);
+
+    if (topcube == top) {       /* abstract */
+        r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e));
+        if (r == NULL) {
+            Cudd_IterDerefBdd(manager, t);
+            Cudd_IterDerefBdd(manager, e);
+            return(NULL);
+        }
+        r = Cudd_Not(r);
+        cuddRef(r);
+        Cudd_IterDerefBdd(manager, t);
+        Cudd_IterDerefBdd(manager, e);
+        cuddDeref(r);
+    } else if (t == e) {
+        r = t;
+        cuddDeref(t);
+        cuddDeref(e);
+    } else {
+        if (Cudd_IsComplement(t)) {
+            r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
+            if (r == NULL) {
+                Cudd_IterDerefBdd(manager, t);
+                Cudd_IterDerefBdd(manager, e);
+                return(NULL);
+            }
+            r = Cudd_Not(r);
+        } else {
+            r = cuddUniqueInter(manager,(int)index,t,e);
+            if (r == NULL) {
+                Cudd_IterDerefBdd(manager, t);
+                Cudd_IterDerefBdd(manager, e);
+                return(NULL);
+            }
+        }
+        cuddDeref(e);
+        cuddDeref(t);
+    }
+    cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, r);
+    return (r);
+
+} /* end of cuddBddXorExistAbstractRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive steps of Cudd_bddBoleanDiff.]
+
+  Description [Performs the recursive steps of Cudd_bddBoleanDiff.
+  Returns the BDD obtained by XORing the cofactors of f with respect to
+  var if successful; NULL otherwise. Exploits the fact that dF/dx =
+  dF'/dx.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddBddBooleanDiffRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * var)
+{
+    DdNode *T, *E, *res, *res1, *res2;
+
+    statLine(manager);
+    if (cuddI(manager,f->index) > manager->perm[var->index]) {
+        /* f does not depend on var. */
+        return(Cudd_Not(DD_ONE(manager)));
+    }
+
+    /* From now on, f is non-constant. */
+
+    /* If the two indices are the same, so are their levels. */
+    if (f->index == var->index) {
+        res = cuddBddXorRecur(manager, cuddT(f), cuddE(f));
+        return(res);
+    }
+
+    /* From now on, cuddI(manager,f->index) < cuddI(manager,cube->index). */
+
+    /* Check the cache. */
+    res = cuddCacheLookup2(manager, cuddBddBooleanDiffRecur, f, var);
+    if (res != NULL) {
+        return(res);
+    }
+
+    /* Compute the cofactors of f. */
+    T = cuddT(f); E = cuddE(f);
+
+    res1 = cuddBddBooleanDiffRecur(manager, T, var);
+    if (res1 == NULL) return(NULL);
+    cuddRef(res1);
+    res2 = cuddBddBooleanDiffRecur(manager, Cudd_Regular(E), var);
+    if (res2 == NULL) {
+        Cudd_IterDerefBdd(manager, res1);
+        return(NULL);
+    }
+    cuddRef(res2);
+    /* ITE takes care of possible complementation of res1 and of the
+    ** case in which res1 == res2. */
+    res = cuddBddIteRecur(manager, manager->vars[f->index], res1, res2);
+    if (res == NULL) {
+        Cudd_IterDerefBdd(manager, res1);
+        Cudd_IterDerefBdd(manager, res2);
+        return(NULL);
+    }
+    cuddDeref(res1);
+    cuddDeref(res2);
+    cuddCacheInsert2(manager, cuddBddBooleanDiffRecur, f, var, res);
+    return(res);
+
+} /* end of cuddBddBooleanDiffRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Checks whether cube is an BDD representing the product of
+  positive literals.]
+
+  Description [Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+bddCheckPositiveCube(
+  DdManager * manager,
+  DdNode * cube)
+{
+    if (Cudd_IsComplement(cube)) return(0);
+    if (cube == DD_ONE(manager)) return(1);
+    if (cuddIsConstant(cube)) return(0);
+    if (cuddE(cube) == Cudd_Not(DD_ONE(manager))) {
+        return(bddCheckPositiveCube(manager, cuddT(cube)));
+    }
+    return(0);
+
+} /* end of bddCheckPositiveCube */
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddBddCorr.c b/abc-build/src/bdd/cudd/cuddBddCorr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddBddCorr.c
@@ -0,0 +1,523 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddBddCorr.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Correlation between BDDs.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_bddCorrelation()
+                <li> Cudd_bddCorrelationWeights()
+                </ul>
+            Static procedures included in this module:
+                <ul>
+                <li> bddCorrelationAux()
+                <li> bddCorrelationWeightsAux()
+                <li> CorrelCompare()
+                <li> CorrelHash()
+                <li> CorrelCleanUp()
+                </ul>
+                ]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct hashEntry {
+    DdNode *f;
+    DdNode *g;
+} HashEntry;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddBddCorr.c,v 1.14 2004/08/13 18:04:46 fabio Exp $";
+#endif
+
+#ifdef CORREL_STATS
+static  int     num_calls;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static double bddCorrelationAux (DdManager *dd, DdNode *f, DdNode *g, st__table *table);
+static double bddCorrelationWeightsAux (DdManager *dd, DdNode *f, DdNode *g, double *prob, st__table *table);
+static int CorrelCompare (const char *key1, const char *key2);
+static int CorrelHash (const char *key, int modulus);
+static enum st__retval CorrelCleanUp (char *key, char *value, char *arg);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the correlation of f and g.]
+
+  Description [Computes the correlation of f and g. If f == g, their
+  correlation is 1. If f == g', their correlation is 0.  Returns the
+  fraction of minterms in the ON-set of the EXNOR of f and g.  If it
+  runs out of memory, returns (double)CUDD_OUT_OF_MEM.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddCorrelationWeights]
+
+******************************************************************************/
+double
+Cudd_bddCorrelation(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g)
+{
+
+    st__table    *table;
+    double      correlation;
+
+#ifdef CORREL_STATS
+    num_calls = 0;
+#endif
+
+    table = st__init_table(CorrelCompare,CorrelHash);
+    if (table == NULL) return((double)CUDD_OUT_OF_MEM);
+    correlation = bddCorrelationAux(manager,f,g,table);
+    st__foreach(table, CorrelCleanUp, NIL(char));
+    st__free_table(table);
+    return(correlation);
+
+} /* end of Cudd_bddCorrelation */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the correlation of f and g for given input
+  probabilities.]
+
+  Description [Computes the correlation of f and g for given input
+  probabilities. On input, prob\[i\] is supposed to contain the
+  probability of the i-th input variable to be 1.
+  If f == g, their correlation is 1. If f == g', their
+  correlation is 0.  Returns the probability that f and g have the same
+  value. If it runs out of memory, returns (double)CUDD_OUT_OF_MEM. The
+  correlation of f and the constant one gives the probability of f.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddCorrelation]
+
+******************************************************************************/
+double
+Cudd_bddCorrelationWeights(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  double * prob)
+{
+
+    st__table    *table;
+    double      correlation;
+
+#ifdef CORREL_STATS
+    num_calls = 0;
+#endif
+
+    table = st__init_table(CorrelCompare,CorrelHash);
+    if (table == NULL) return((double)CUDD_OUT_OF_MEM);
+    correlation = bddCorrelationWeightsAux(manager,f,g,prob,table);
+    st__foreach(table, CorrelCleanUp, NIL(char));
+    st__free_table(table);
+    return(correlation);
+
+} /* end of Cudd_bddCorrelationWeights */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddCorrelation.]
+
+  Description [Performs the recursive step of Cudd_bddCorrelation.
+  Returns the fraction of minterms in the ON-set of the EXNOR of f and
+  g.]
+
+  SideEffects [None]
+
+  SeeAlso     [bddCorrelationWeightsAux]
+
+******************************************************************************/
+static double
+bddCorrelationAux(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  st__table * table)
+{
+    DdNode      *Fv, *Fnv, *G, *Gv, *Gnv;
+    double      min, *pmin, min1, min2, *dummy;
+    HashEntry   *entry;
+    unsigned int topF, topG;
+
+    statLine(dd);
+#ifdef CORREL_STATS
+    num_calls++;
+#endif
+
+    /* Terminal cases: only work for BDDs. */
+    if (f == g) return(1.0);
+    if (f == Cudd_Not(g)) return(0.0);
+
+    /* Standardize call using the following properties:
+    **     (f EXNOR g)   = (g EXNOR f)
+    **     (f' EXNOR g') = (f EXNOR g).
+    */
+    if (cuddF2L(f) > cuddF2L(g)) {
+        DdNode *tmp = f;
+        f = g; g = tmp;
+    }
+    if (Cudd_IsComplement(f)) {
+        f = Cudd_Not(f);
+        g = Cudd_Not(g);
+    }
+    /* From now on, f is regular. */
+    
+    entry = ABC_ALLOC(HashEntry,1);
+    if (entry == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(CUDD_OUT_OF_MEM);
+    }
+    entry->f = f; entry->g = g;
+
+    /* We do not use the fact that
+    ** correlation(f,g') = 1 - correlation(f,g)
+    ** to minimize the risk of cancellation.
+    */
+    if ( st__lookup(table, (const char *)entry, (char **)&dummy)) {
+        min = *dummy;
+        ABC_FREE(entry);
+        return(min);
+    }
+
+    G = Cudd_Regular(g);
+    topF = cuddI(dd,f->index); topG = cuddI(dd,G->index);
+    if (topF <= topG) { Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; }
+    if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; }
+
+    if (g != G) {
+        Gv = Cudd_Not(Gv);
+        Gnv = Cudd_Not(Gnv);
+    }
+
+    min1 = bddCorrelationAux(dd, Fv, Gv, table) / 2.0;
+    if (min1 == (double)CUDD_OUT_OF_MEM) {
+        ABC_FREE(entry);
+        return(CUDD_OUT_OF_MEM);
+    }
+    min2 = bddCorrelationAux(dd, Fnv, Gnv, table) / 2.0; 
+    if (min2 == (double)CUDD_OUT_OF_MEM) {
+        ABC_FREE(entry);
+        return(CUDD_OUT_OF_MEM);
+    }
+    min = (min1+min2);
+    
+    pmin = ABC_ALLOC(double,1);
+    if (pmin == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return((double)CUDD_OUT_OF_MEM);
+    }
+    *pmin = min;
+
+    if ( st__insert(table,(char *)entry, (char *)pmin) == st__OUT_OF_MEM) {
+        ABC_FREE(entry);
+        ABC_FREE(pmin);
+        return((double)CUDD_OUT_OF_MEM);
+    }
+    return(min);
+
+} /* end of bddCorrelationAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddCorrelationWeigths.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [bddCorrelationAux]
+
+******************************************************************************/
+static double
+bddCorrelationWeightsAux(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  double * prob,
+  st__table * table)
+{
+    DdNode      *Fv, *Fnv, *G, *Gv, *Gnv;
+    double      min, *pmin, min1, min2, *dummy;
+    HashEntry   *entry;
+    int         topF, topG, index;
+
+    statLine(dd);
+#ifdef CORREL_STATS
+    num_calls++;
+#endif
+
+    /* Terminal cases: only work for BDDs. */
+    if (f == g) return(1.0);
+    if (f == Cudd_Not(g)) return(0.0);
+
+    /* Standardize call using the following properties:
+    **     (f EXNOR g)   = (g EXNOR f)
+    **     (f' EXNOR g') = (f EXNOR g).
+    */
+    if (cuddF2L(f) > cuddF2L(g)) {
+        DdNode *tmp = f;
+        f = g; g = tmp;
+    }
+    if (Cudd_IsComplement(f)) {
+        f = Cudd_Not(f);
+        g = Cudd_Not(g);
+    }
+    /* From now on, f is regular. */
+    
+    entry = ABC_ALLOC(HashEntry,1);
+    if (entry == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return((double)CUDD_OUT_OF_MEM);
+    }
+    entry->f = f; entry->g = g;
+
+    /* We do not use the fact that
+    ** correlation(f,g') = 1 - correlation(f,g)
+    ** to minimize the risk of cancellation.
+    */
+    if ( st__lookup(table, (const char *)entry, (char **)&dummy)) {
+        min = *dummy;
+        ABC_FREE(entry);
+        return(min);
+    }
+
+    G = Cudd_Regular(g);
+    topF = cuddI(dd,f->index); topG = cuddI(dd,G->index);
+    if (topF <= topG) {
+        Fv = cuddT(f); Fnv = cuddE(f);
+        index = f->index;
+    } else {
+        Fv = Fnv = f;
+        index = G->index;
+    }
+    if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; }
+
+    if (g != G) {
+        Gv = Cudd_Not(Gv);
+        Gnv = Cudd_Not(Gnv);
+    }
+
+    min1 = bddCorrelationWeightsAux(dd, Fv, Gv, prob, table) * prob[index];
+    if (min1 == (double)CUDD_OUT_OF_MEM) {
+        ABC_FREE(entry);
+        return((double)CUDD_OUT_OF_MEM);
+    }
+    min2 = bddCorrelationWeightsAux(dd, Fnv, Gnv, prob, table) * (1.0 - prob[index]); 
+    if (min2 == (double)CUDD_OUT_OF_MEM) {
+        ABC_FREE(entry);
+        return((double)CUDD_OUT_OF_MEM);
+    }
+    min = (min1+min2);
+    
+    pmin = ABC_ALLOC(double,1);
+    if (pmin == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return((double)CUDD_OUT_OF_MEM);
+    }
+    *pmin = min;
+
+    if ( st__insert(table,(char *)entry, (char *)pmin) == st__OUT_OF_MEM) {
+        ABC_FREE(entry);
+        ABC_FREE(pmin);
+        return((double)CUDD_OUT_OF_MEM);
+    }
+    return(min);
+
+} /* end of bddCorrelationWeightsAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two hash table entries.]
+
+  Description [Compares two hash table entries. Returns 0 if they are
+  identical; 1 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+CorrelCompare(
+  const char * key1,
+  const char * key2)
+{
+    HashEntry *entry1;
+    HashEntry *entry2;
+
+    entry1 = (HashEntry *) key1;
+    entry2 = (HashEntry *) key2;
+    if (entry1->f != entry2->f || entry1->g != entry2->g) return(1);
+
+    return(0);
+
+} /* end of CorrelCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Hashes a hash table entry.]
+
+  Description [Hashes a hash table entry. It is patterned after
+  st__strhash. Returns a value between 0 and modulus.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+CorrelHash(
+  const char * key,
+  int  modulus)
+{
+    HashEntry *entry;
+    int val = 0;
+
+    entry = (HashEntry *) key;
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+    val = ((int) ((long)entry->f))*997 + ((int) ((long)entry->g));
+#else
+    val = ((int) entry->f)*997 + ((int) entry->g);
+#endif
+
+    return ((val < 0) ? -val : val) % modulus;
+
+} /* end of CorrelHash */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees memory associated with hash table.]
+
+  Description [Frees memory associated with hash table. Returns
+  st__CONTINUE.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static enum st__retval
+CorrelCleanUp(
+  char * key,
+  char * value,
+  char * arg)
+{
+    double      *d;
+    HashEntry *entry;
+
+    entry = (HashEntry *) key;
+    ABC_FREE(entry);
+    d = (double *)value;
+    ABC_FREE(d);
+    return st__CONTINUE;
+
+} /* end of CorrelCleanUp */
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddBddIte.c b/abc-build/src/bdd/cudd/cuddBddIte.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddBddIte.c
@@ -0,0 +1,1328 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddBddIte.c]
+
+  PackageName [cudd]
+
+  Synopsis    [BDD ITE function and satellites.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_bddIte()
+                <li> Cudd_bddIteConstant()
+                <li> Cudd_bddIntersect()
+                <li> Cudd_bddAnd()
+                <li> Cudd_bddAndLimit()
+                <li> Cudd_bddOr()
+                <li> Cudd_bddNand()
+                <li> Cudd_bddNor()
+                <li> Cudd_bddXor()
+                <li> Cudd_bddXnor()
+                <li> Cudd_bddLeq()
+                </ul>
+       Internal procedures included in this module:
+                <ul>
+                <li> cuddBddIteRecur()
+                <li> cuddBddIntersectRecur()
+                <li> cuddBddAndRecur()
+                <li> cuddBddXorRecur()
+                </ul>
+       Static procedures included in this module:
+                <ul>
+                <li> bddVarToConst()
+                <li> bddVarToCanonical()
+                <li> bddVarToCanonicalSimple()
+                </ul>]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddBddIte.c,v 1.24 2004/08/13 18:04:46 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void bddVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *one);
+static int bddVarToCanonical (DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp);
+static int bddVarToCanonicalSimple (DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements ITE(f,g,h).]
+
+  Description [Implements ITE(f,g,h). Returns a pointer to the
+  resulting BDD if successful; NULL if the intermediate result blows
+  up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addIte Cudd_bddIteConstant Cudd_bddIntersect]
+
+******************************************************************************/
+DdNode *
+Cudd_bddIte(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddIteRecur(dd,f,g,h);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddIte */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements ITEconstant(f,g,h).]
+
+  Description [Implements ITEconstant(f,g,h). Returns a pointer to the
+  resulting BDD (which may or may not be constant) or DD_NON_CONSTANT.
+  No new nodes are created.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIte Cudd_bddIntersect Cudd_bddLeq Cudd_addIteConstant]
+
+******************************************************************************/
+DdNode *
+Cudd_bddIteConstant(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode       *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e;
+    DdNode       *one = DD_ONE(dd);
+    DdNode       *zero = Cudd_Not(one);
+    int          comple;
+    unsigned int topf, topg, toph, v;
+
+    statLine(dd);
+    /* Trivial cases. */
+    if (f == one)                       /* ITE(1,G,H) => G */
+        return(g);
+    
+    if (f == zero)                      /* ITE(0,G,H) => H */
+        return(h);
+    
+    /* f now not a constant. */
+    bddVarToConst(f, &g, &h, one);      /* possibly convert g or h */
+                                        /* to constants */
+
+    if (g == h)                         /* ITE(F,G,G) => G */
+        return(g);
+
+    if (Cudd_IsConstant(g) && Cudd_IsConstant(h)) 
+        return(DD_NON_CONSTANT);        /* ITE(F,1,0) or ITE(F,0,1) */
+                                        /* => DD_NON_CONSTANT */
+    
+    if (g == Cudd_Not(h))
+        return(DD_NON_CONSTANT);        /* ITE(F,G,G') => DD_NON_CONSTANT */
+                                        /* if F != G and F != G' */
+    
+    comple = bddVarToCanonical(dd, &f, &g, &h, &topf, &topg, &toph);
+
+    /* Cache lookup. */
+    r = cuddConstantLookup(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h);
+    if (r != NULL) {
+        return(Cudd_NotCond(r,comple && r != DD_NON_CONSTANT));
+    }
+
+    v = ddMin(topg, toph);
+
+    /* ITE(F,G,H) = (v,G,H) (non constant) if F = (v,1,0), v < top(G,H). */
+    if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
+        return(DD_NON_CONSTANT);
+    }
+
+    /* Compute cofactors. */
+    if (topf <= v) {
+        v = ddMin(topf, v);             /* v = top_var(F,G,H) */
+        Fv = cuddT(f); Fnv = cuddE(f);
+    } else {
+        Fv = Fnv = f;
+    }
+
+    if (topg == v) {
+        Gv = cuddT(g); Gnv = cuddE(g);
+    } else {
+        Gv = Gnv = g;
+    }
+
+    if (toph == v) {
+        H = Cudd_Regular(h);
+        Hv = cuddT(H); Hnv = cuddE(H);
+        if (Cudd_IsComplement(h)) {
+            Hv = Cudd_Not(Hv);
+            Hnv = Cudd_Not(Hnv);
+        }
+    } else {
+        Hv = Hnv = h;
+    }
+
+    /* Recursion. */
+    t = Cudd_bddIteConstant(dd, Fv, Gv, Hv);
+    if (t == DD_NON_CONSTANT || !Cudd_IsConstant(t)) {
+        cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT);
+        return(DD_NON_CONSTANT);
+    }
+    e = Cudd_bddIteConstant(dd, Fnv, Gnv, Hnv);
+    if (e == DD_NON_CONSTANT || !Cudd_IsConstant(e) || t != e) {
+        cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT);
+        return(DD_NON_CONSTANT);
+    }
+    cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, t);
+    return(Cudd_NotCond(t,comple));
+
+} /* end of Cudd_bddIteConstant */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a function included in the intersection of f and g.]
+
+  Description [Computes a function included in the intersection of f and
+  g. (That is, a witness that the intersection is not empty.)
+  Cudd_bddIntersect tries to build as few new nodes as possible. If the
+  only result of interest is whether f and g intersect,
+  Cudd_bddLeq should be used instead.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLeq Cudd_bddIteConstant]
+
+******************************************************************************/
+DdNode *
+Cudd_bddIntersect(
+  DdManager * dd /* manager */,
+  DdNode * f /* first operand */,
+  DdNode * g /* second operand */)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddIntersectRecur(dd,f,g);
+    } while (dd->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_bddIntersect */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the conjunction of two BDDs f and g.]
+
+  Description [Computes the conjunction of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAndAbstract Cudd_bddIntersect
+  Cudd_bddOr Cudd_bddNand Cudd_bddNor Cudd_bddXor Cudd_bddXnor]
+
+******************************************************************************/
+DdNode *
+Cudd_bddAnd(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddAndRecur(dd,f,g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddAnd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the conjunction of two BDDs f and g.  Returns
+  NULL if too many nodes are required.]
+
+  Description [Computes the conjunction of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up or more new nodes than <code>limit</code> are
+  required.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddAnd]
+
+******************************************************************************/
+DdNode *
+Cudd_bddAndLimit(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  unsigned int limit)
+{
+    DdNode *res;
+    unsigned int saveLimit = dd->maxLive;
+
+    dd->maxLive = (dd->keys - dd->dead) + (dd->keysZ - dd->deadZ) + limit;
+    do {
+        dd->reordered = 0;
+        res = cuddBddAndRecur(dd,f,g);
+    } while (dd->reordered == 1);
+    dd->maxLive = saveLimit;
+    return(res);
+
+} /* end of Cudd_bddAndLimit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the disjunction of two BDDs f and g.]
+
+  Description [Computes the disjunction of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddNand Cudd_bddNor
+  Cudd_bddXor Cudd_bddXnor]
+
+******************************************************************************/
+DdNode *
+Cudd_bddOr(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g));
+    } while (dd->reordered == 1);
+    res = Cudd_NotCond(res,res != NULL);
+    return(res);
+
+} /* end of Cudd_bddOr */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the NAND of two BDDs f and g.]
+
+  Description [Computes the NAND of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNor
+  Cudd_bddXor Cudd_bddXnor]
+
+******************************************************************************/
+DdNode *
+Cudd_bddNand(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddAndRecur(dd,f,g);
+    } while (dd->reordered == 1);
+    res = Cudd_NotCond(res,res != NULL);
+    return(res);
+
+} /* end of Cudd_bddNand */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the NOR of two BDDs f and g.]
+
+  Description [Computes the NOR of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNand
+  Cudd_bddXor Cudd_bddXnor]
+
+******************************************************************************/
+DdNode *
+Cudd_bddNor(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g));
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddNor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the exclusive OR of two BDDs f and g.]
+
+  Description [Computes the exclusive OR of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr
+  Cudd_bddNand Cudd_bddNor Cudd_bddXnor]
+
+******************************************************************************/
+DdNode *
+Cudd_bddXor(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddXorRecur(dd,f,g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddXor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the exclusive NOR of two BDDs f and g.]
+
+  Description [Computes the exclusive NOR of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr
+  Cudd_bddNand Cudd_bddNor Cudd_bddXor]
+
+******************************************************************************/
+DdNode *
+Cudd_bddXnor(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddXorRecur(dd,f,Cudd_Not(g));
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddXnor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Determines whether f is less than or equal to g.]
+
+  Description [Returns 1 if f is less than or equal to g; 0 otherwise.
+  No new nodes are created.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIteConstant Cudd_addEvalConst]
+
+******************************************************************************/
+int
+Cudd_bddLeq(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *one, *zero, *tmp, *F, *fv, *fvn, *gv, *gvn;
+    unsigned int topf, topg, res;
+
+    statLine(dd);
+    /* Terminal cases and normalization. */
+    if (f == g) return(1);
+
+    if (Cudd_IsComplement(g)) {
+        /* Special case: if f is regular and g is complemented,
+        ** f(1,...,1) = 1 > 0 = g(1,...,1).
+        */
+        if (!Cudd_IsComplement(f)) return(0);
+        /* Both are complemented: Swap and complement because
+        ** f <= g <=> g' <= f' and we want the second argument to be regular.
+        */
+        tmp = g;
+        g = Cudd_Not(f);
+        f = Cudd_Not(tmp);
+    } else if (Cudd_IsComplement(f) && cuddF2L(g) < cuddF2L(f)) {
+        tmp = g;
+        g = Cudd_Not(f);
+        f = Cudd_Not(tmp);
+    }
+
+    /* Now g is regular and, if f is not regular, f < g. */
+    one = DD_ONE(dd);
+    if (g == one) return(1);    /* no need to test against zero */
+    if (f == one) return(0);    /* since at this point g != one */
+    if (Cudd_Not(f) == g) return(0); /* because neither is constant */
+    zero = Cudd_Not(one);
+    if (f == zero) return(1);
+
+    /* Here neither f nor g is constant. */
+
+    /* Check cache. */
+    tmp = cuddCacheLookup2(dd,(DD_CTFP)Cudd_bddLeq,f,g);
+    if (tmp != NULL) {
+        return(tmp == one);
+    }
+
+    /* Compute cofactors. */
+    F = Cudd_Regular(f);
+    topf = dd->perm[F->index];
+    topg = dd->perm[g->index];
+    if (topf <= topg) {
+        fv = cuddT(F); fvn = cuddE(F);
+        if (f != F) {
+            fv = Cudd_Not(fv);
+            fvn = Cudd_Not(fvn);
+        }
+    } else {
+        fv = fvn = f;
+    }
+    if (topg <= topf) {
+        gv = cuddT(g); gvn = cuddE(g);
+    } else {
+        gv = gvn = g;
+    }
+
+    /* Recursive calls. Since we want to maximize the probability of
+    ** the special case f(1,...,1) > g(1,...,1), we consider the negative
+    ** cofactors first. Indeed, the complementation parity of the positive
+    ** cofactors is the same as the one of the parent functions.
+    */
+    res = Cudd_bddLeq(dd,fvn,gvn) && Cudd_bddLeq(dd,fv,gv);
+
+    /* Store result in cache and return. */
+    cuddCacheInsert2(dd,(DD_CTFP)Cudd_bddLeq,f,g,(res ? one : zero));
+    return(res);
+
+} /* end of Cudd_bddLeq */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_bddIte.]
+
+  Description [Implements the recursive step of Cudd_bddIte. Returns a
+  pointer to the resulting BDD. NULL if the intermediate result blows
+  up or if reordering occurs.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddBddIteRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode       *one, *zero, *res;
+    DdNode       *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e;
+    unsigned int topf, topg, toph, v;
+    int          index = -1;
+    int          comple;
+
+    statLine(dd);
+    /* Terminal cases. */
+
+    /* One variable cases. */
+    if (f == (one = DD_ONE(dd)))        /* ITE(1,G,H) = G */
+        return(g);
+    
+    if (f == (zero = Cudd_Not(one)))    /* ITE(0,G,H) = H */
+        return(h);
+    
+    /* From now on, f is known not to be a constant. */
+    if (g == one || f == g) {   /* ITE(F,F,H) = ITE(F,1,H) = F + H */
+        if (h == zero) {        /* ITE(F,1,0) = F */
+            return(f);
+        } else {
+            res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(h));
+            return(Cudd_NotCond(res,res != NULL));
+        }
+    } else if (g == zero || f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */
+        if (h == one) {         /* ITE(F,0,1) = !F */
+            return(Cudd_Not(f));
+        } else {
+            res = cuddBddAndRecur(dd,Cudd_Not(f),h);
+            return(res);
+        }
+    }
+    if (h == zero || f == h) {    /* ITE(F,G,F) = ITE(F,G,0) = F * G */
+        res = cuddBddAndRecur(dd,f,g);
+        return(res);
+    } else if (h == one || f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */
+        res = cuddBddAndRecur(dd,f,Cudd_Not(g));
+        return(Cudd_NotCond(res,res != NULL));
+    }
+
+    /* Check remaining one variable case. */
+    if (g == h) {               /* ITE(F,G,G) = G */
+        return(g);
+    } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = F <-> G */
+        res = cuddBddXorRecur(dd,f,h);
+        return(res);
+    }
+    
+    /* From here, there are no constants. */
+    comple = bddVarToCanonicalSimple(dd, &f, &g, &h, &topf, &topg, &toph);
+
+    /* f & g are now regular pointers */
+
+    v = ddMin(topg, toph);
+
+    /* A shortcut: ITE(F,G,H) = (v,G,H) if F = (v,1,0), v < top(G,H). */
+    if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
+        r = cuddUniqueInter(dd, (int) f->index, g, h);
+        return(Cudd_NotCond(r,comple && r != NULL));
+    }
+
+    /* Check cache. */
+    r = cuddCacheLookup(dd, DD_BDD_ITE_TAG, f, g, h);
+    if (r != NULL) {
+        return(Cudd_NotCond(r,comple));
+    }
+
+    /* Compute cofactors. */
+    if (topf <= v) {
+        v = ddMin(topf, v);     /* v = top_var(F,G,H) */
+        index = f->index;
+        Fv = cuddT(f); Fnv = cuddE(f);
+    } else {
+        Fv = Fnv = f;
+    }
+    if (topg == v) {
+        index = g->index;
+        Gv = cuddT(g); Gnv = cuddE(g);
+    } else {
+        Gv = Gnv = g;
+    }
+    if (toph == v) {
+        H = Cudd_Regular(h);
+        index = H->index;
+        Hv = cuddT(H); Hnv = cuddE(H);
+        if (Cudd_IsComplement(h)) {
+            Hv = Cudd_Not(Hv);
+            Hnv = Cudd_Not(Hnv);
+        }
+    } else {
+        Hv = Hnv = h;
+    }
+
+    /* Recursive step. */
+    t = cuddBddIteRecur(dd,Fv,Gv,Hv);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+
+    e = cuddBddIteRecur(dd,Fnv,Gnv,Hnv);
+    if (e == NULL) {
+        Cudd_IterDerefBdd(dd,t);
+        return(NULL);
+    }
+    cuddRef(e);
+
+    r = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
+    if (r == NULL) {
+        Cudd_IterDerefBdd(dd,t);
+        Cudd_IterDerefBdd(dd,e);
+        return(NULL);
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    cuddCacheInsert(dd, DD_BDD_ITE_TAG, f, g, h, r);
+    return(Cudd_NotCond(r,comple));
+
+} /* end of cuddBddIteRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_bddIntersect.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIntersect]
+
+******************************************************************************/
+DdNode *
+cuddBddIntersectRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+    DdNode *F, *G, *t, *e;
+    DdNode *fv, *fnv, *gv, *gnv;
+    DdNode *one, *zero;
+    unsigned int index, topf, topg;
+
+    statLine(dd);
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    /* Terminal cases. */
+    if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
+    if (f == g || g == one) return(f);
+    if (f == one) return(g);
+
+    /* At this point f and g are not constant. */
+    if (cuddF2L(f) > cuddF2L(g)) { DdNode *tmp = f; f = g; g = tmp; }
+    res = cuddCacheLookup2(dd,Cudd_bddIntersect,f,g);
+    if (res != NULL) return(res);
+
+    /* Find splitting variable. Here we can skip the use of cuddI,
+    ** because the operands are known to be non-constant.
+    */
+    F = Cudd_Regular(f);
+    topf = dd->perm[F->index];
+    G = Cudd_Regular(g);
+    topg = dd->perm[G->index];
+
+    /* Compute cofactors. */
+    if (topf <= topg) {
+        index = F->index;
+        fv = cuddT(F);
+        fnv = cuddE(F);
+        if (Cudd_IsComplement(f)) {
+            fv = Cudd_Not(fv);
+            fnv = Cudd_Not(fnv);
+        }
+    } else {
+        index = G->index;
+        fv = fnv = f;
+    }
+
+    if (topg <= topf) {
+        gv = cuddT(G);
+        gnv = cuddE(G);
+        if (Cudd_IsComplement(g)) {
+            gv = Cudd_Not(gv);
+            gnv = Cudd_Not(gnv);
+        }
+    } else {
+        gv = gnv = g;
+    }
+
+    /* Compute partial results. */
+    t = cuddBddIntersectRecur(dd,fv,gv);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+    if (t != zero) {
+        e = zero;
+    } else {
+        e = cuddBddIntersectRecur(dd,fnv,gnv);
+        if (e == NULL) {
+            Cudd_IterDerefBdd(dd, t);
+            return(NULL);
+        }
+    }
+    cuddRef(e);
+
+    if (t == e) { /* both equal zero */
+        res = t;
+    } else if (Cudd_IsComplement(t)) {
+        res = cuddUniqueInter(dd,(int)index,Cudd_Not(t),Cudd_Not(e));
+        if (res == NULL) {
+            Cudd_IterDerefBdd(dd, t);
+            Cudd_IterDerefBdd(dd, e);
+            return(NULL);
+        }
+        res = Cudd_Not(res);
+    } else {
+        res = cuddUniqueInter(dd,(int)index,t,e);
+        if (res == NULL) {
+            Cudd_IterDerefBdd(dd, t);
+            Cudd_IterDerefBdd(dd, e);
+            return(NULL);
+        }
+    }
+    cuddDeref(e);
+    cuddDeref(t);
+
+    cuddCacheInsert2(dd,Cudd_bddIntersect,f,g,res);
+
+    return(res);
+
+} /* end of cuddBddIntersectRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis [Implements the recursive step of Cudd_bddAnd.]
+
+  Description [Implements the recursive step of Cudd_bddAnd by taking
+  the conjunction of two BDDs.  Returns a pointer to the result is
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddAnd]
+
+******************************************************************************/
+DdNode *
+cuddBddAndRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *F, *fv, *fnv, *G, *gv, *gnv;
+    DdNode *one, *r, *t, *e;
+    unsigned int topf, topg, index;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+
+    /* Terminal cases. */
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    if (F == G) {
+        if (f == g) return(f);
+        else return(Cudd_Not(one));
+    }
+    if (F == one) {
+        if (f == one) return(g);
+        else return(f);
+    }
+    if (G == one) {
+        if (g == one) return(f);
+        else return(g);
+    }
+
+    /* At this point f and g are not constant. */
+    if (cuddF2L(f) > cuddF2L(g)) { /* Try to increase cache efficiency. */
+        DdNode *tmp = f;
+        f = g;
+        g = tmp;
+        F = Cudd_Regular(f);
+        G = Cudd_Regular(g);
+    }
+
+    /* Check cache. */
+    if (F->ref != 1 || G->ref != 1) {
+        r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g);
+        if (r != NULL) return(r);
+    }
+
+    if ( manager->TimeStop && Abc_Clock() > manager->TimeStop )
+        return NULL;
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    topf = manager->perm[F->index];
+    topg = manager->perm[G->index];
+
+    /* Compute cofactors. */
+    if (topf <= topg) {
+        index = F->index;
+        fv = cuddT(F);
+        fnv = cuddE(F);
+        if (Cudd_IsComplement(f)) {
+            fv = Cudd_Not(fv);
+            fnv = Cudd_Not(fnv);
+        }
+    } else {
+        index = G->index;
+        fv = fnv = f;
+    }
+
+    if (topg <= topf) {
+        gv = cuddT(G);
+        gnv = cuddE(G);
+        if (Cudd_IsComplement(g)) {
+            gv = Cudd_Not(gv);
+            gnv = Cudd_Not(gnv);
+        }
+    } else {
+        gv = gnv = g;
+    }
+
+    t = cuddBddAndRecur(manager, fv, gv);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+
+    e = cuddBddAndRecur(manager, fnv, gnv);
+    if (e == NULL) {
+        Cudd_IterDerefBdd(manager, t);
+        return(NULL);
+    }
+    cuddRef(e);
+
+    if (t == e) {
+        r = t;
+    } else {
+        if (Cudd_IsComplement(t)) {
+            r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
+            if (r == NULL) {
+                Cudd_IterDerefBdd(manager, t);
+                Cudd_IterDerefBdd(manager, e);
+                return(NULL);
+            }
+            r = Cudd_Not(r);
+        } else {
+            r = cuddUniqueInter(manager,(int)index,t,e);
+            if (r == NULL) {
+                Cudd_IterDerefBdd(manager, t);
+                Cudd_IterDerefBdd(manager, e);
+                return(NULL);
+            }
+        }
+    }
+    cuddDeref(e);
+    cuddDeref(t);
+    if (F->ref != 1 || G->ref != 1)
+        cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r);
+    return(r);
+
+} /* end of cuddBddAndRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis [Implements the recursive step of Cudd_bddXor.]
+
+  Description [Implements the recursive step of Cudd_bddXor by taking
+  the exclusive OR of two BDDs.  Returns a pointer to the result is
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddXor]
+
+******************************************************************************/
+DdNode *
+cuddBddXorRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *fv, *fnv, *G, *gv, *gnv;
+    DdNode *one, *zero, *r, *t, *e;
+    unsigned int topf, topg, index;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    /* Terminal cases. */
+    if (f == g) return(zero);
+    if (f == Cudd_Not(g)) return(one);
+    if (cuddF2L(f) > cuddF2L(g)) { /* Try to increase cache efficiency and simplify tests. */
+        DdNode *tmp = f;
+        f = g;
+        g = tmp;
+    }
+    if (g == zero) return(f);
+    if (g == one) return(Cudd_Not(f));
+    if (Cudd_IsComplement(f)) {
+        f = Cudd_Not(f);
+        g = Cudd_Not(g);
+    }
+    /* Now the first argument is regular. */
+    if (f == one) return(Cudd_Not(g));
+
+    /* At this point f and g are not constant. */
+
+    /* Check cache. */
+    r = cuddCacheLookup2(manager, Cudd_bddXor, f, g);
+    if (r != NULL) return(r);
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    topf = manager->perm[f->index];
+    G = Cudd_Regular(g);
+    topg = manager->perm[G->index];
+
+    /* Compute cofactors. */
+    if (topf <= topg) {
+        index = f->index;
+        fv = cuddT(f);
+        fnv = cuddE(f);
+    } else {
+        index = G->index;
+        fv = fnv = f;
+    }
+
+    if (topg <= topf) {
+        gv = cuddT(G);
+        gnv = cuddE(G);
+        if (Cudd_IsComplement(g)) {
+            gv = Cudd_Not(gv);
+            gnv = Cudd_Not(gnv);
+        }
+    } else {
+        gv = gnv = g;
+    }
+
+    t = cuddBddXorRecur(manager, fv, gv);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+
+    e = cuddBddXorRecur(manager, fnv, gnv);
+    if (e == NULL) {
+        Cudd_IterDerefBdd(manager, t);
+        return(NULL);
+    }
+    cuddRef(e);
+
+    if (t == e) {
+        r = t;
+    } else {
+        if (Cudd_IsComplement(t)) {
+            r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
+            if (r == NULL) {
+                Cudd_IterDerefBdd(manager, t);
+                Cudd_IterDerefBdd(manager, e);
+                return(NULL);
+            }
+            r = Cudd_Not(r);
+        } else {
+            r = cuddUniqueInter(manager,(int)index,t,e);
+            if (r == NULL) {
+                Cudd_IterDerefBdd(manager, t);
+                Cudd_IterDerefBdd(manager, e);
+                return(NULL);
+            }
+        }
+    }
+    cuddDeref(e);
+    cuddDeref(t);
+    cuddCacheInsert2(manager, Cudd_bddXor, f, g, r);
+    return(r);
+
+} /* end of cuddBddXorRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Replaces variables with constants if possible.]
+
+  Description [This function performs part of the transformation to
+  standard form by replacing variables with constants if possible.]
+
+  SideEffects [None]
+
+  SeeAlso     [bddVarToCanonical bddVarToCanonicalSimple]
+
+******************************************************************************/
+static void
+bddVarToConst(
+  DdNode * f,
+  DdNode ** gp,
+  DdNode ** hp,
+  DdNode * one)
+{
+    DdNode *g = *gp;
+    DdNode *h = *hp;
+
+    if (f == g) {    /* ITE(F,F,H) = ITE(F,1,H) = F + H */
+        *gp = one;
+    } else if (f == Cudd_Not(g)) {    /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */
+        *gp = Cudd_Not(one);
+    }
+    if (f == h) {    /* ITE(F,G,F) = ITE(F,G,0) = F * G */
+        *hp = Cudd_Not(one);
+    } else if (f == Cudd_Not(h)) {    /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */
+        *hp = one;
+    }
+
+} /* end of bddVarToConst */
+
+
+/**Function********************************************************************
+
+  Synopsis [Picks unique member from equiv expressions.]
+
+  Description [Reduces 2 variable expressions to canonical form.]
+
+  SideEffects [None]
+
+  SeeAlso     [bddVarToConst bddVarToCanonicalSimple]
+
+******************************************************************************/
+static int
+bddVarToCanonical(
+  DdManager * dd,
+  DdNode ** fp,
+  DdNode ** gp,
+  DdNode ** hp,
+  unsigned int * topfp,
+  unsigned int * topgp,
+  unsigned int * tophp)
+{
+    register DdNode             *F, *G, *H, *r, *f, *g, *h;
+    register unsigned int       topf, topg, toph;
+    DdNode                      *one = dd->one;
+    int                         comple, change;
+
+    f = *fp;
+    g = *gp;
+    h = *hp;
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    H = Cudd_Regular(h);
+    topf = cuddI(dd,F->index);
+    topg = cuddI(dd,G->index);
+    toph = cuddI(dd,H->index);
+
+    change = 0;
+
+    if (G == one) {                     /* ITE(F,c,H) */
+        if ((topf > toph) || (topf == toph && cuddF2L(f) > cuddF2L(h))) {
+            r = h;
+            h = f;
+            f = r;                      /* ITE(F,1,H) = ITE(H,1,F) */
+            if (g != one) {     /* g == zero */
+                f = Cudd_Not(f);                /* ITE(F,0,H) = ITE(!H,0,!F) */
+                h = Cudd_Not(h);
+            }
+            change = 1;
+        }
+    } else if (H == one) {              /* ITE(F,G,c) */
+        if ((topf > topg) || (topf == topg && cuddF2L(f) > cuddF2L(g))) {
+            r = g;
+            g = f;
+            f = r;                      /* ITE(F,G,0) = ITE(G,F,0) */
+            if (h == one) {
+                f = Cudd_Not(f);                /* ITE(F,G,1) = ITE(!G,!F,1) */
+                g = Cudd_Not(g);
+            }
+            change = 1;
+        }
+    } else if (g == Cudd_Not(h)) {      /* ITE(F,G,!G) = ITE(G,F,!F) */
+        if ((topf > topg) || (topf == topg && cuddF2L(f) > cuddF2L(g))) {
+            r = f;
+            f = g;
+            g = r;
+            h = Cudd_Not(r);
+            change = 1;
+        }
+    }
+    /* adjust pointers so that the first 2 arguments to ITE are regular */
+    if (Cudd_IsComplement(f) != 0) {    /* ITE(!F,G,H) = ITE(F,H,G) */
+        f = Cudd_Not(f);
+        r = g;
+        g = h;
+        h = r;
+        change = 1;
+    }
+    comple = 0;
+    if (Cudd_IsComplement(g) != 0) {    /* ITE(F,!G,H) = !ITE(F,G,!H) */
+        g = Cudd_Not(g);
+        h = Cudd_Not(h);
+        change = 1;
+        comple = 1;
+    }
+    if (change != 0) {
+        *fp = f;
+        *gp = g;
+        *hp = h;
+    }
+    *topfp = cuddI(dd,f->index);
+    *topgp = cuddI(dd,g->index);
+    *tophp = cuddI(dd,Cudd_Regular(h)->index);
+
+    return(comple);
+
+} /* end of bddVarToCanonical */
+
+
+/**Function********************************************************************
+
+  Synopsis [Picks unique member from equiv expressions.]
+
+  Description [Makes sure the first two pointers are regular.  This
+  mat require the complementation of the result, which is signaled by
+  returning 1 instead of 0.  This function is simpler than the general
+  case because it assumes that no two arguments are the same or
+  complementary, and no argument is constant.]
+
+  SideEffects [None]
+
+  SeeAlso     [bddVarToConst bddVarToCanonical]
+
+******************************************************************************/
+static int
+bddVarToCanonicalSimple(
+  DdManager * dd,
+  DdNode ** fp,
+  DdNode ** gp,
+  DdNode ** hp,
+  unsigned int * topfp,
+  unsigned int * topgp,
+  unsigned int * tophp)
+{
+    register DdNode             *r, *f, *g, *h;
+    int                         comple, change;
+
+    f = *fp;
+    g = *gp;
+    h = *hp;
+
+    change = 0;
+
+    /* adjust pointers so that the first 2 arguments to ITE are regular */
+    if (Cudd_IsComplement(f)) { /* ITE(!F,G,H) = ITE(F,H,G) */
+        f = Cudd_Not(f);
+        r = g;
+        g = h;
+        h = r;
+        change = 1;
+    }
+    comple = 0;
+    if (Cudd_IsComplement(g)) { /* ITE(F,!G,H) = !ITE(F,G,!H) */
+        g = Cudd_Not(g);
+        h = Cudd_Not(h);
+        change = 1;
+        comple = 1;
+    }
+    if (change) {
+        *fp = f;
+        *gp = g;
+        *hp = h;
+    }
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    *topfp = dd->perm[f->index];
+    *topgp = dd->perm[g->index];
+    *tophp = dd->perm[Cudd_Regular(h)->index];
+
+    return(comple);
+
+} /* end of bddVarToCanonicalSimple */
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddBridge.c b/abc-build/src/bdd/cudd/cuddBridge.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddBridge.c
@@ -0,0 +1,1029 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddBridge.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Translation from BDD to ADD and vice versa and transfer between
+  different managers.]
+
+  Description [External procedures included in this file:
+            <ul>
+            <li> Cudd_addBddThreshold()
+            <li> Cudd_addBddStrictThreshold()
+            <li> Cudd_addBddInterval()
+            <li> Cudd_addBddIthBit()
+            <li> Cudd_BddToAdd()
+            <li> Cudd_addBddPattern()
+            <li> Cudd_bddTransfer()
+            </ul>
+        Internal procedures included in this file:
+            <ul>
+            <li> cuddBddTransfer()
+            <li> cuddAddBddDoPattern()
+            </ul>
+        Static procedures included in this file:
+            <ul>
+            <li> addBddDoThreshold()
+            <li> addBddDoStrictThreshold()
+            <li> addBddDoInterval()
+            <li> addBddDoIthBit()
+            <li> ddBddToAddRecur()
+            <li> cuddBddTransferRecur()
+            </ul>
+            ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddBridge.c,v 1.19 2008/04/25 06:42:55 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * addBddDoThreshold (DdManager *dd, DdNode *f, DdNode *val);
+static DdNode * addBddDoStrictThreshold (DdManager *dd, DdNode *f, DdNode *val);
+static DdNode * addBddDoInterval (DdManager *dd, DdNode *f, DdNode *l, DdNode *u);
+static DdNode * addBddDoIthBit (DdManager *dd, DdNode *f, DdNode *index);
+static DdNode * ddBddToAddRecur (DdManager *dd, DdNode *B);
+static DdNode * cuddBddTransferRecur (DdManager *ddS, DdManager *ddD, DdNode *f, st__table *table);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts an ADD to a BDD.]
+
+  Description [Converts an ADD to a BDD by replacing all
+  discriminants greater than or equal to value with 1, and all other
+  discriminants with 0. Returns a pointer to the resulting BDD if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd
+  Cudd_addBddStrictThreshold]
+
+******************************************************************************/
+DdNode *
+Cudd_addBddThreshold(
+  DdManager * dd,
+  DdNode * f,
+  CUDD_VALUE_TYPE  value)
+{
+    DdNode *res;
+    DdNode *val;
+    
+    val = cuddUniqueConst(dd,value);
+    if (val == NULL) return(NULL);
+    cuddRef(val);
+
+    do {
+        dd->reordered = 0;
+        res = addBddDoThreshold(dd, f, val);
+    } while (dd->reordered == 1);
+
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd, val);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd, val);
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addBddThreshold */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts an ADD to a BDD.]
+
+  Description [Converts an ADD to a BDD by replacing all
+  discriminants STRICTLY greater than value with 1, and all other
+  discriminants with 0. Returns a pointer to the resulting BDD if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd 
+  Cudd_addBddThreshold]
+
+******************************************************************************/
+DdNode *
+Cudd_addBddStrictThreshold(
+  DdManager * dd,
+  DdNode * f,
+  CUDD_VALUE_TYPE  value)
+{
+    DdNode *res;
+    DdNode *val;
+    
+    val = cuddUniqueConst(dd,value);
+    if (val == NULL) return(NULL);
+    cuddRef(val);
+
+    do {
+        dd->reordered = 0;
+        res = addBddDoStrictThreshold(dd, f, val);
+    } while (dd->reordered == 1);
+
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd, val);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd, val);
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addBddStrictThreshold */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts an ADD to a BDD.]
+
+  Description [Converts an ADD to a BDD by replacing all
+  discriminants greater than or equal to lower and less than or equal to
+  upper with 1, and all other discriminants with 0. Returns a pointer to
+  the resulting BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addBddThreshold Cudd_addBddStrictThreshold 
+  Cudd_addBddPattern Cudd_BddToAdd]
+
+******************************************************************************/
+DdNode *
+Cudd_addBddInterval(
+  DdManager * dd,
+  DdNode * f,
+  CUDD_VALUE_TYPE  lower,
+  CUDD_VALUE_TYPE  upper)
+{
+    DdNode *res;
+    DdNode *l;
+    DdNode *u;
+    
+    /* Create constant nodes for the interval bounds, so that we can use
+    ** the global cache.
+    */
+    l = cuddUniqueConst(dd,lower);
+    if (l == NULL) return(NULL);
+    cuddRef(l);
+    u = cuddUniqueConst(dd,upper);
+    if (u == NULL) {
+        Cudd_RecursiveDeref(dd,l);
+        return(NULL);
+    }
+    cuddRef(u);
+
+    do {
+        dd->reordered = 0;
+        res = addBddDoInterval(dd, f, l, u);
+    } while (dd->reordered == 1);
+
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd, l);
+        Cudd_RecursiveDeref(dd, u);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd, l);
+    Cudd_RecursiveDeref(dd, u);
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addBddInterval */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts an ADD to a BDD by extracting the i-th bit from
+  the leaves.]
+
+  Description [Converts an ADD to a BDD by replacing all
+  discriminants whose i-th bit is equal to 1 with 1, and all other
+  discriminants with 0. The i-th bit refers to the integer
+  representation of the leaf value. If the value is has a fractional
+  part, it is ignored. Repeated calls to this procedure allow one to
+  transform an integer-valued ADD into an array of BDDs, one for each
+  bit of the leaf values. Returns a pointer to the resulting BDD if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd]
+
+******************************************************************************/
+DdNode *
+Cudd_addBddIthBit(
+  DdManager * dd,
+  DdNode * f,
+  int  bit)
+{
+    DdNode *res;
+    DdNode *index;
+    
+    index = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) bit);
+    if (index == NULL) return(NULL);
+    cuddRef(index);
+
+    do {
+        dd->reordered = 0;
+        res = addBddDoIthBit(dd, f, index);
+    } while (dd->reordered == 1);
+
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd, index);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd, index);
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addBddIthBit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a BDD to a 0-1 ADD.]
+
+  Description [Converts a BDD to a 0-1 ADD. Returns a pointer to the
+  resulting ADD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addBddPattern Cudd_addBddThreshold Cudd_addBddInterval
+  Cudd_addBddStrictThreshold]
+
+******************************************************************************/
+DdNode *
+Cudd_BddToAdd(
+  DdManager * dd,
+  DdNode * B)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = ddBddToAddRecur(dd, B);
+    } while (dd->reordered ==1);
+    return(res);
+
+} /* end of Cudd_BddToAdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts an ADD to a BDD.]
+
+  Description [Converts an ADD to a BDD by replacing all
+  discriminants different from 0 with 1. Returns a pointer to the
+  resulting BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_BddToAdd Cudd_addBddThreshold Cudd_addBddInterval
+  Cudd_addBddStrictThreshold]
+
+******************************************************************************/
+DdNode *
+Cudd_addBddPattern(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *res;
+    
+    do {
+        dd->reordered = 0;
+        res = cuddAddBddDoPattern(dd, f);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addBddPattern */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Convert a BDD from a manager to another one.]
+
+  Description [Convert a BDD from a manager to another one. The orders of the
+  variables in the two managers may be different. Returns a
+  pointer to the BDD in the destination manager if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_bddTransfer(
+  DdManager * ddSource,
+  DdManager * ddDestination,
+  DdNode * f)
+{
+    DdNode *res;
+    do {
+        ddDestination->reordered = 0;
+        res = cuddBddTransfer(ddSource, ddDestination, f);
+    } while (ddDestination->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddTransfer */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Convert a BDD from a manager to another one.]
+
+  Description [Convert a BDD from a manager to another one. Returns a
+  pointer to the BDD in the destination manager if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddTransfer]
+
+******************************************************************************/
+DdNode *
+cuddBddTransfer(
+  DdManager * ddS,
+  DdManager * ddD,
+  DdNode * f)
+{
+    DdNode *res;
+    st__table *table = NULL;
+    st__generator *gen = NULL;
+    DdNode *key, *value;
+
+    table = st__init_table( st__ptrcmp, st__ptrhash);
+    if (table == NULL) goto failure;
+    res = cuddBddTransferRecur(ddS, ddD, f, table);
+    if (res != NULL) cuddRef(res);
+
+    /* Dereference all elements in the table and dispose of the table.
+    ** This must be done also if res is NULL to avoid leaks in case of
+    ** reordering. */
+    gen = st__init_gen(table);
+    if (gen == NULL) goto failure;
+    while ( st__gen(gen, (const char **)&key, (char **)&value)) {
+        Cudd_RecursiveDeref(ddD, value);
+    }
+    st__free_gen(gen); gen = NULL;
+    st__free_table(table); table = NULL;
+
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+failure:
+    /* No need to free gen because it is always NULL here. */
+    if (table != NULL) st__free_table(table);
+    return(NULL);
+
+} /* end of cuddBddTransfer */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step for Cudd_addBddPattern.]
+
+  Description [Performs the recursive step for Cudd_addBddPattern. Returns a
+  pointer to the resulting BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddAddBddDoPattern(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *res, *T, *E;
+    DdNode *fv, *fvn;
+    int v;
+
+    statLine(dd);
+    /* Check terminal case. */
+    if (cuddIsConstant(f)) {
+        return(Cudd_NotCond(DD_ONE(dd),f == DD_ZERO(dd)));
+    }
+
+    /* Check cache. */
+    res = cuddCacheLookup1(dd,Cudd_addBddPattern,f);
+    if (res != NULL) return(res);
+
+    /* Recursive step. */
+    v = f->index;
+    fv = cuddT(f); fvn = cuddE(f);
+
+    T = cuddAddBddDoPattern(dd,fv);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = cuddAddBddDoPattern(dd,fvn);
+    if (E == NULL) {
+        Cudd_RecursiveDeref(dd, T);
+        return(NULL);
+    }
+    cuddRef(E);
+    if (Cudd_IsComplement(T)) {
+        res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E));
+        if (res == NULL) {
+            Cudd_RecursiveDeref(dd, T);
+            Cudd_RecursiveDeref(dd, E);
+            return(NULL);
+        }
+        res = Cudd_Not(res);
+    } else {
+        res = (T == E) ? T : cuddUniqueInter(dd,v,T,E);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(dd, T);
+            Cudd_RecursiveDeref(dd, E);
+            return(NULL);
+        }
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert1(dd,Cudd_addBddPattern,f,res);
+
+    return(res);
+
+} /* end of cuddAddBddDoPattern */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step for Cudd_addBddThreshold.]
+
+  Description [Performs the recursive step for Cudd_addBddThreshold.
+  Returns a pointer to the BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [addBddDoStrictThreshold]
+
+******************************************************************************/
+static DdNode *
+addBddDoThreshold(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * val)
+{
+    DdNode *res, *T, *E;
+    DdNode *fv, *fvn;
+    int v;
+
+    statLine(dd);
+    /* Check terminal case. */
+    if (cuddIsConstant(f)) {
+        return(Cudd_NotCond(DD_ONE(dd),cuddV(f) < cuddV(val)));
+    }
+
+    /* Check cache. */
+    res = cuddCacheLookup2(dd,addBddDoThreshold,f,val);
+    if (res != NULL) return(res);
+
+    /* Recursive step. */
+    v = f->index;
+    fv = cuddT(f); fvn = cuddE(f);
+
+    T = addBddDoThreshold(dd,fv,val);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = addBddDoThreshold(dd,fvn,val);
+    if (E == NULL) {
+        Cudd_RecursiveDeref(dd, T);
+        return(NULL);
+    }
+    cuddRef(E);
+    if (Cudd_IsComplement(T)) {
+        res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E));
+        if (res == NULL) {
+            Cudd_RecursiveDeref(dd, T);
+            Cudd_RecursiveDeref(dd, E);
+            return(NULL);
+        }
+        res = Cudd_Not(res);
+    } else {
+        res = (T == E) ? T : cuddUniqueInter(dd,v,T,E);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(dd, T);
+            Cudd_RecursiveDeref(dd, E);
+            return(NULL);
+        }
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert2(dd,addBddDoThreshold,f,val,res);
+
+    return(res);
+
+} /* end of addBddDoThreshold */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step for Cudd_addBddStrictThreshold.]
+
+  Description [Performs the recursive step for Cudd_addBddStrictThreshold.
+  Returns a pointer to the BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [addBddDoThreshold]
+
+******************************************************************************/
+static DdNode *
+addBddDoStrictThreshold(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * val)
+{
+    DdNode *res, *T, *E;
+    DdNode *fv, *fvn;
+    int v;
+
+    statLine(dd);
+    /* Check terminal case. */
+    if (cuddIsConstant(f)) {
+        return(Cudd_NotCond(DD_ONE(dd),cuddV(f) <= cuddV(val)));
+    }
+
+    /* Check cache. */
+    res = cuddCacheLookup2(dd,addBddDoStrictThreshold,f,val);
+    if (res != NULL) return(res);
+
+    /* Recursive step. */
+    v = f->index;
+    fv = cuddT(f); fvn = cuddE(f);
+
+    T = addBddDoStrictThreshold(dd,fv,val);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = addBddDoStrictThreshold(dd,fvn,val);
+    if (E == NULL) {
+        Cudd_RecursiveDeref(dd, T);
+        return(NULL);
+    }
+    cuddRef(E);
+    if (Cudd_IsComplement(T)) {
+        res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E));
+        if (res == NULL) {
+            Cudd_RecursiveDeref(dd, T);
+            Cudd_RecursiveDeref(dd, E);
+            return(NULL);
+        }
+        res = Cudd_Not(res);
+    } else {
+        res = (T == E) ? T : cuddUniqueInter(dd,v,T,E);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(dd, T);
+            Cudd_RecursiveDeref(dd, E);
+            return(NULL);
+        }
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert2(dd,addBddDoStrictThreshold,f,val,res);
+
+    return(res);
+
+} /* end of addBddDoStrictThreshold */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step for Cudd_addBddInterval.]
+
+  Description [Performs the recursive step for Cudd_addBddInterval.
+  Returns a pointer to the BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [addBddDoThreshold addBddDoStrictThreshold]
+
+******************************************************************************/
+static DdNode *
+addBddDoInterval(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * l,
+  DdNode * u)
+{
+    DdNode *res, *T, *E;
+    DdNode *fv, *fvn;
+    int v;
+
+    statLine(dd);
+    /* Check terminal case. */
+    if (cuddIsConstant(f)) {
+        return(Cudd_NotCond(DD_ONE(dd),cuddV(f) < cuddV(l) || cuddV(f) > cuddV(u)));
+    }
+
+    /* Check cache. */
+    res = cuddCacheLookup(dd,DD_ADD_BDD_DO_INTERVAL_TAG,f,l,u);
+    if (res != NULL) return(res);
+
+    /* Recursive step. */
+    v = f->index;
+    fv = cuddT(f); fvn = cuddE(f);
+
+    T = addBddDoInterval(dd,fv,l,u);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = addBddDoInterval(dd,fvn,l,u);
+    if (E == NULL) {
+        Cudd_RecursiveDeref(dd, T);
+        return(NULL);
+    }
+    cuddRef(E);
+    if (Cudd_IsComplement(T)) {
+        res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E));
+        if (res == NULL) {
+            Cudd_RecursiveDeref(dd, T);
+            Cudd_RecursiveDeref(dd, E);
+            return(NULL);
+        }
+        res = Cudd_Not(res);
+    } else {
+        res = (T == E) ? T : cuddUniqueInter(dd,v,T,E);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(dd, T);
+            Cudd_RecursiveDeref(dd, E);
+            return(NULL);
+        }
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert(dd,DD_ADD_BDD_DO_INTERVAL_TAG,f,l,u,res);
+
+    return(res);
+
+} /* end of addBddDoInterval */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step for Cudd_addBddIthBit.]
+
+  Description [Performs the recursive step for Cudd_addBddIthBit.
+  Returns a pointer to the BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+addBddDoIthBit(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * index)
+{
+    DdNode *res, *T, *E;
+    DdNode *fv, *fvn;
+    int mask, value;
+    int v;
+
+    statLine(dd);
+    /* Check terminal case. */
+    if (cuddIsConstant(f)) {
+        mask = 1 << ((int) cuddV(index));
+        value = (int) cuddV(f);
+        return(Cudd_NotCond(DD_ONE(dd),(value & mask) == 0));
+    }
+
+    /* Check cache. */
+    res = cuddCacheLookup2(dd,addBddDoIthBit,f,index);
+    if (res != NULL) return(res);
+
+    /* Recursive step. */
+    v = f->index;
+    fv = cuddT(f); fvn = cuddE(f);
+
+    T = addBddDoIthBit(dd,fv,index);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = addBddDoIthBit(dd,fvn,index);
+    if (E == NULL) {
+        Cudd_RecursiveDeref(dd, T);
+        return(NULL);
+    }
+    cuddRef(E);
+    if (Cudd_IsComplement(T)) {
+        res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E));
+        if (res == NULL) {
+            Cudd_RecursiveDeref(dd, T);
+            Cudd_RecursiveDeref(dd, E);
+            return(NULL);
+        }
+        res = Cudd_Not(res);
+    } else {
+        res = (T == E) ? T : cuddUniqueInter(dd,v,T,E);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(dd, T);
+            Cudd_RecursiveDeref(dd, E);
+            return(NULL);
+        }
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert2(dd,addBddDoIthBit,f,index,res);
+
+    return(res);
+
+} /* end of addBddDoIthBit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step for Cudd_BddToAdd.]
+
+  Description [Performs the recursive step for Cudd_BddToAdd. Returns a
+  pointer to the resulting ADD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+ddBddToAddRecur(
+  DdManager * dd,
+  DdNode * B)
+{
+    DdNode *one;
+    DdNode *res, *res1, *T, *E, *Bt, *Be;
+    int complement = 0;
+
+    statLine(dd);
+    one = DD_ONE(dd);
+
+    if (Cudd_IsConstant(B)) {
+        if (B == one) {
+            res = one;
+        } else {
+            res = DD_ZERO(dd);
+        }
+        return(res);
+    }
+    /* Check visited table */
+    res = cuddCacheLookup1(dd,ddBddToAddRecur,B);
+    if (res != NULL) return(res);
+
+    if (Cudd_IsComplement(B)) {
+        complement = 1;
+        Bt = cuddT(Cudd_Regular(B));
+        Be = cuddE(Cudd_Regular(B));
+    } else {
+        Bt = cuddT(B);
+        Be = cuddE(B);
+    }
+
+    T = ddBddToAddRecur(dd, Bt);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = ddBddToAddRecur(dd, Be);
+    if (E == NULL) {
+        Cudd_RecursiveDeref(dd, T);
+        return(NULL);
+    }
+    cuddRef(E);
+
+    /* No need to check for T == E, because it is guaranteed not to happen. */
+    res = cuddUniqueInter(dd, (int) Cudd_Regular(B)->index, T, E);
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd ,T);
+        Cudd_RecursiveDeref(dd ,E);
+        return(NULL);
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    if (complement) {
+        cuddRef(res);
+        res1 = cuddAddCmplRecur(dd, res);
+        if (res1 == NULL) {
+            Cudd_RecursiveDeref(dd, res);
+            return(NULL);
+        }
+        cuddRef(res1);
+        Cudd_RecursiveDeref(dd, res);
+        res = res1;
+        cuddDeref(res);
+    }
+
+    /* Store result. */
+    cuddCacheInsert1(dd,ddBddToAddRecur,B,res);
+
+    return(res);
+
+} /* end of ddBddToAddRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddTransfer.]
+
+  Description [Performs the recursive step of Cudd_bddTransfer.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddBddTransfer]
+
+******************************************************************************/
+static DdNode *
+cuddBddTransferRecur(
+  DdManager * ddS,
+  DdManager * ddD,
+  DdNode * f,
+  st__table * table)
+{
+    DdNode *ft, *fe, *t, *e, *var, *res;
+    DdNode *one, *zero;
+    int    index;
+    int    comple = 0;
+
+    statLine(ddD);
+    one = DD_ONE(ddD);
+    comple = Cudd_IsComplement(f);
+
+    /* Trivial cases. */
+    if (Cudd_IsConstant(f)) return(Cudd_NotCond(one, comple));
+
+    /* Make canonical to increase the utilization of the cache. */
+    f = Cudd_NotCond(f,comple);
+    /* Now f is a regular pointer to a non-constant node. */
+
+    /* Check the cache. */
+    if ( st__lookup(table, (const char *)f, (char **)&res))
+        return(Cudd_NotCond(res,comple));
+
+    if ( ddS->TimeStop && Abc_Clock() > ddS->TimeStop )
+        return NULL;
+    if ( ddD->TimeStop && Abc_Clock() > ddD->TimeStop )
+        return NULL;
+    
+    /* Recursive step. */
+    index = f->index;
+    ft = cuddT(f); fe = cuddE(f);
+
+    t = cuddBddTransferRecur(ddS, ddD, ft, table);
+    if (t == NULL) {
+        return(NULL);
+    }
+    cuddRef(t);
+
+    e = cuddBddTransferRecur(ddS, ddD, fe, table);
+    if (e == NULL) {
+        Cudd_RecursiveDeref(ddD, t);
+        return(NULL);
+    }
+    cuddRef(e);
+
+    zero = Cudd_Not(one);
+    var = cuddUniqueInter(ddD,index,one,zero);
+    if (var == NULL) {
+        Cudd_RecursiveDeref(ddD, t);
+        Cudd_RecursiveDeref(ddD, e);
+        return(NULL);
+    }
+    res = cuddBddIteRecur(ddD,var,t,e);
+    if (res == NULL) {
+        Cudd_RecursiveDeref(ddD, t);
+        Cudd_RecursiveDeref(ddD, e);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(ddD, t);
+    Cudd_RecursiveDeref(ddD, e);
+
+    if ( st__add_direct(table, (char *) f, (char *) res) == st__OUT_OF_MEM) {
+        Cudd_RecursiveDeref(ddD, res);
+        return(NULL);
+    }
+    return(Cudd_NotCond(res,comple));
+
+} /* end of cuddBddTransferRecur */
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddCache.c b/abc-build/src/bdd/cudd/cuddCache.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddCache.c
@@ -0,0 +1,1100 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddCache.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for cache insertion and lookup.]
+
+  Description [Internal procedures included in this module:
+                <ul>
+                <li> cuddInitCache()
+                <li> cuddCacheInsert()
+                <li> cuddCacheInsert2()
+                <li> cuddCacheLookup()
+                <li> cuddCacheLookupZdd()
+                <li> cuddCacheLookup2()
+                <li> cuddCacheLookup2Zdd()
+                <li> cuddConstantLookup()
+                <li> cuddCacheProfile()
+                <li> cuddCacheResize()
+                <li> cuddCacheFlush()
+                <li> cuddComputeFloorLog2()
+                </ul>
+            Static procedures included in this module:
+                <ul>
+                </ul> ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifdef DD_CACHE_PROFILE
+#define DD_HYSTO_BINS 8
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddCache.c,v 1.34 2009/02/19 16:17:50 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the computed table.]
+
+  Description [Initializes the computed table. It is called by
+  Cudd_Init. Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Init]
+
+******************************************************************************/
+int
+cuddInitCache(
+  DdManager * unique /* unique table */,
+  unsigned int cacheSize /* initial size of the cache */,
+  unsigned int maxCacheSize /* cache size beyond which no resizing occurs */)
+{
+    int i;
+    unsigned int logSize;
+#ifndef DD_CACHE_PROFILE
+    DdNodePtr *mem;
+    ptruint offset;
+#endif
+
+    /* Round cacheSize to largest power of 2 not greater than the requested
+    ** initial cache size. */
+    logSize = cuddComputeFloorLog2(ddMax(cacheSize,unique->slots/2));
+    cacheSize = 1 << logSize;
+//    unique->acache = ABC_ALLOC(DdCache,cacheSize+1);
+    unique->acache = ABC_ALLOC(DdCache,cacheSize+2);
+    if (unique->acache == NULL) {
+        unique->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    /* If the size of the cache entry is a power of 2, we want to
+    ** enforce alignment to that power of two. This happens when
+    ** DD_CACHE_PROFILE is not defined. */
+#ifdef DD_CACHE_PROFILE
+    unique->cache = unique->acache;
+    unique->memused += (cacheSize) * sizeof(DdCache);
+#else
+    mem = (DdNodePtr *) unique->acache;
+//    offset = (ptruint) mem & (sizeof(DdCache) - 1);
+//    mem += (sizeof(DdCache) - offset) / sizeof(DdNodePtr);
+    offset = (ptruint) mem & (32 - 1);
+    mem += (32 - offset) / sizeof(DdNodePtr);
+    unique->cache = (DdCache *) mem;
+//    assert(((ptruint) unique->cache & (sizeof(DdCache) - 1)) == 0);
+    assert(((ptruint) unique->cache & (32 - 1)) == 0);
+    unique->memused += (cacheSize+1) * sizeof(DdCache);
+#endif
+    unique->cacheSlots = cacheSize;
+    unique->cacheShift = sizeof(int) * 8 - logSize;
+    unique->maxCacheHard = maxCacheSize;
+    /* If cacheSlack is non-negative, we can resize. */
+    unique->cacheSlack = (int) ddMin(maxCacheSize,
+        DD_MAX_CACHE_TO_SLOTS_RATIO*unique->slots) -
+        2 * (int) cacheSize;
+    Cudd_SetMinHit(unique,DD_MIN_HIT);
+    /* Initialize to avoid division by 0 and immediate resizing. */
+    unique->cacheMisses = (double) (int) (cacheSize * unique->minHit + 1);
+    unique->cacheHits = 0;
+    unique->totCachehits = 0;
+    /* The sum of cacheMisses and totCacheMisses is always correct,
+    ** even though cacheMisses is larger than it should for the reasons
+    ** explained above. */
+    unique->totCacheMisses = -unique->cacheMisses;
+    unique->cachecollisions = 0;
+    unique->cacheinserts = 0;
+    unique->cacheLastInserts = 0;
+    unique->cachedeletions = 0;
+
+    /* Initialize the cache */
+    for (i = 0; (unsigned) i < cacheSize; i++) {
+        unique->cache[i].h = 0; /* unused slots */
+        unique->cache[i].data = NULL; /* invalid entry */
+#ifdef DD_CACHE_PROFILE
+        unique->cache[i].count = 0;
+#endif
+    }
+
+    return(1);
+
+} /* end of cuddInitCache */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts a result in the cache.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheInsert2 cuddCacheInsert1]
+
+******************************************************************************/
+void
+cuddCacheInsert(
+  DdManager * table,
+  ptruint op,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h,
+  DdNode * data)
+{
+    int posn;
+    unsigned hash;
+    register DdCache *entry;
+    ptruint uf, ug, uh;
+    ptruint ufc, ugc, uhc;
+
+    uf = (ptruint) f | (op & 0xe);
+    ug = (ptruint) g | (op >> 4);
+    uh = (ptruint) h;
+
+    ufc = (ptruint) cuddF2L(f) | (op & 0xe);
+    ugc = (ptruint) cuddF2L(g) | (op >> 4);
+    uhc = (ptruint) cuddF2L(h);
+
+    hash = ddCHash2_(uhc,ufc,ugc);
+//    posn = ddCHash2(uhc,ufc,ugc,table->cacheShift);
+    posn = hash >> table->cacheShift;
+    entry = &table->cache[posn];
+
+    table->cachecollisions += entry->data != NULL;
+    table->cacheinserts++;
+
+    entry->f    = (DdNode *) uf;
+    entry->g    = (DdNode *) ug;
+    entry->h    = uh;
+    entry->data = data;
+#ifdef DD_CACHE_PROFILE
+    entry->count++;
+#endif
+    entry->hash = hash;
+
+} /* end of cuddCacheInsert */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts a result in the cache for a function with two
+  operands.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheInsert cuddCacheInsert1]
+
+******************************************************************************/
+void
+cuddCacheInsert2(
+  DdManager * table,
+  DD_CTFP op,
+  DdNode * f,
+  DdNode * g,
+  DdNode * data)
+{
+    int posn;
+    unsigned hash;
+    register DdCache *entry;
+
+    hash = ddCHash2_(op,cuddF2L(f),cuddF2L(g));
+//    posn = ddCHash2(op,cuddF2L(f),cuddF2L(g),table->cacheShift);
+    posn = hash >> table->cacheShift;
+    entry = &table->cache[posn];
+
+    if (entry->data != NULL) {
+        table->cachecollisions++;
+    }
+    table->cacheinserts++;
+
+    entry->f = f;
+    entry->g = g;
+    entry->h = (ptruint) op;
+    entry->data = data;
+#ifdef DD_CACHE_PROFILE
+    entry->count++;
+#endif
+    entry->hash = hash;
+
+} /* end of cuddCacheInsert2 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts a result in the cache for a function with two
+  operands.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheInsert cuddCacheInsert2]
+
+******************************************************************************/
+void
+cuddCacheInsert1(
+  DdManager * table,
+  DD_CTFP1 op,
+  DdNode * f,
+  DdNode * data)
+{
+    int posn;
+    unsigned hash;
+    register DdCache *entry;
+
+    hash = ddCHash2_(op,cuddF2L(f),cuddF2L(f));
+//    posn = ddCHash2(op,cuddF2L(f),cuddF2L(f),table->cacheShift);
+    posn = hash >> table->cacheShift;
+    entry = &table->cache[posn];
+
+    if (entry->data != NULL) {
+        table->cachecollisions++;
+    }
+    table->cacheinserts++;
+
+    entry->f = f;
+    entry->g = f;
+    entry->h = (ptruint) op;
+    entry->data = data;
+#ifdef DD_CACHE_PROFILE
+    entry->count++;
+#endif
+    entry->hash = hash;
+
+} /* end of cuddCacheInsert1 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Looks up in the cache for the result of op applied to f,
+  g, and h.]
+
+  Description [Returns the result if found; it returns NULL if no
+  result is found.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheLookup2 cuddCacheLookup1]
+
+******************************************************************************/
+DdNode *
+cuddCacheLookup(
+  DdManager * table,
+  ptruint op,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    int posn;
+    DdCache *en,*cache;
+    DdNode *data;
+    ptruint uf, ug, uh;
+    ptruint ufc, ugc, uhc;
+
+    uf = (ptruint) f | (op & 0xe);
+    ug = (ptruint) g | (op >> 4);
+    uh = (ptruint) h;
+
+    ufc = (ptruint) cuddF2L(f) | (op & 0xe);
+    ugc = (ptruint) cuddF2L(g) | (op >> 4);
+    uhc = (ptruint) cuddF2L(h);
+
+    cache = table->cache;
+#ifdef DD_DEBUG
+    if (cache == NULL) {
+        return(NULL);
+    }
+#endif
+
+    posn = ddCHash2(uhc,ufc,ugc,table->cacheShift);
+    en = &cache[posn];
+    if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug && en->h==uh) {
+        data = Cudd_Regular(en->data);
+        table->cacheHits++;
+        if (data->ref == 0) {
+            cuddReclaim(table,data);
+        }
+        return(en->data);
+    }
+
+    /* Cache miss: decide whether to resize. */
+    table->cacheMisses++;
+
+    if (table->cacheSlack >= 0 &&
+        table->cacheHits > table->cacheMisses * table->minHit) {
+        cuddCacheResize(table);
+    }
+
+    return(NULL);
+
+} /* end of cuddCacheLookup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Looks up in the cache for the result of op applied to f,
+  g, and h.]
+
+  Description [Returns the result if found; it returns NULL if no
+  result is found.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheLookup2Zdd cuddCacheLookup1Zdd]
+
+******************************************************************************/
+DdNode *
+cuddCacheLookupZdd(
+  DdManager * table,
+  ptruint op,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    int posn;
+    DdCache *en,*cache;
+    DdNode *data;
+    ptruint uf, ug, uh;
+    ptruint ufc, ugc, uhc;
+
+    uf = (ptruint) f | (op & 0xe);
+    ug = (ptruint) g | (op >> 4);
+    uh = (ptruint) h;
+
+    ufc = (ptruint) cuddF2L(f) | (op & 0xe);
+    ugc = (ptruint) cuddF2L(g) | (op >> 4);
+    uhc = (ptruint) cuddF2L(h);
+
+    cache = table->cache;
+#ifdef DD_DEBUG
+    if (cache == NULL) {
+        return(NULL);
+    }
+#endif
+
+    posn = ddCHash2(uhc,ufc,ugc,table->cacheShift);
+    en = &cache[posn];
+    if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug &&
+        en->h==uh) {
+        data = Cudd_Regular(en->data);
+        table->cacheHits++;
+        if (data->ref == 0) {
+            cuddReclaimZdd(table,data);
+        }
+        return(en->data);
+    }
+
+    /* Cache miss: decide whether to resize. */
+    table->cacheMisses++;
+
+    if (table->cacheSlack >= 0 &&
+        table->cacheHits > table->cacheMisses * table->minHit) {
+        cuddCacheResize(table);
+    }
+
+    return(NULL);
+
+} /* end of cuddCacheLookupZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Looks up in the cache for the result of op applied to f
+  and g.]
+
+  Description [Returns the result if found; it returns NULL if no
+  result is found.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheLookup cuddCacheLookup1]
+
+******************************************************************************/
+DdNode *
+cuddCacheLookup2(
+  DdManager * table,
+  DD_CTFP op,
+  DdNode * f,
+  DdNode * g)
+{
+    int posn;
+    DdCache *en,*cache;
+    DdNode *data;
+
+    cache = table->cache;
+#ifdef DD_DEBUG
+    if (cache == NULL) {
+        return(NULL);
+    }
+#endif
+
+    posn = ddCHash2(op,cuddF2L(f),cuddF2L(g),table->cacheShift);
+    en = &cache[posn];
+    if (en->data != NULL && en->f==f && en->g==g && en->h==(ptruint)op) {
+        data = Cudd_Regular(en->data);
+        table->cacheHits++;
+        if (data->ref == 0) {
+            cuddReclaim(table,data);
+        }
+        return(en->data);
+    }
+
+    /* Cache miss: decide whether to resize. */
+    table->cacheMisses++;
+
+    if (table->cacheSlack >= 0 &&
+        table->cacheHits > table->cacheMisses * table->minHit) {
+        cuddCacheResize(table);
+    }
+
+    return(NULL);
+
+} /* end of cuddCacheLookup2 */
+
+
+/**Function********************************************************************
+
+  Synopsis [Looks up in the cache for the result of op applied to f.]
+
+  Description [Returns the result if found; it returns NULL if no
+  result is found.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheLookup cuddCacheLookup2]
+
+******************************************************************************/
+DdNode *
+cuddCacheLookup1(
+  DdManager * table,
+  DD_CTFP1 op,
+  DdNode * f)
+{
+    int posn;
+    DdCache *en,*cache;
+    DdNode *data;
+
+    cache = table->cache;
+#ifdef DD_DEBUG
+    if (cache == NULL) {
+        return(NULL);
+    }
+#endif
+
+    posn = ddCHash2(op,cuddF2L(f),cuddF2L(f),table->cacheShift);
+    en = &cache[posn];
+    if (en->data != NULL && en->f==f && en->h==(ptruint)op) {
+        data = Cudd_Regular(en->data);
+        table->cacheHits++;
+        if (data->ref == 0) {
+            cuddReclaim(table,data);
+        }
+        return(en->data);
+    }
+
+    /* Cache miss: decide whether to resize. */
+    table->cacheMisses++;
+
+    if (table->cacheSlack >= 0 &&
+        table->cacheHits > table->cacheMisses * table->minHit) {
+        cuddCacheResize(table);
+    }
+
+    return(NULL);
+
+} /* end of cuddCacheLookup1 */
+
+
+/**Function********************************************************************
+
+  Synopsis [Looks up in the cache for the result of op applied to f
+  and g.]
+
+  Description [Returns the result if found; it returns NULL if no
+  result is found.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheLookupZdd cuddCacheLookup1Zdd]
+
+******************************************************************************/
+DdNode *
+cuddCacheLookup2Zdd(
+  DdManager * table,
+  DD_CTFP op,
+  DdNode * f,
+  DdNode * g)
+{
+    int posn;
+    DdCache *en,*cache;
+    DdNode *data;
+
+    cache = table->cache;
+#ifdef DD_DEBUG
+    if (cache == NULL) {
+        return(NULL);
+    }
+#endif
+
+    posn = ddCHash2(op,cuddF2L(f),cuddF2L(g),table->cacheShift);
+    en = &cache[posn];
+    if (en->data != NULL && en->f==f && en->g==g && en->h==(ptruint)op) {
+        data = Cudd_Regular(en->data);
+        table->cacheHits++;
+        if (data->ref == 0) {
+            cuddReclaimZdd(table,data);
+        }
+        return(en->data);
+    }
+
+    /* Cache miss: decide whether to resize. */
+    table->cacheMisses++;
+
+    if (table->cacheSlack >= 0 &&
+        table->cacheHits > table->cacheMisses * table->minHit) {
+        cuddCacheResize(table);
+    }
+
+    return(NULL);
+
+} /* end of cuddCacheLookup2Zdd */
+
+
+/**Function********************************************************************
+
+  Synopsis [Looks up in the cache for the result of op applied to f.]
+
+  Description [Returns the result if found; it returns NULL if no
+  result is found.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheLookupZdd cuddCacheLookup2Zdd]
+
+******************************************************************************/
+DdNode *
+cuddCacheLookup1Zdd(
+  DdManager * table,
+  DD_CTFP1 op,
+  DdNode * f)
+{
+    int posn;
+    DdCache *en,*cache;
+    DdNode *data;
+
+    cache = table->cache;
+#ifdef DD_DEBUG
+    if (cache == NULL) {
+        return(NULL);
+    }
+#endif
+
+    posn = ddCHash2(op,cuddF2L(f),cuddF2L(f),table->cacheShift);
+    en = &cache[posn];
+    if (en->data != NULL && en->f==f && en->h==(ptruint)op) {
+        data = Cudd_Regular(en->data);
+        table->cacheHits++;
+        if (data->ref == 0) {
+            cuddReclaimZdd(table,data);
+        }
+        return(en->data);
+    }
+
+    /* Cache miss: decide whether to resize. */
+    table->cacheMisses++;
+
+    if (table->cacheSlack >= 0  &&
+        table->cacheHits > table->cacheMisses * table->minHit) {
+        cuddCacheResize(table);
+    }
+
+    return(NULL);
+
+} /* end of cuddCacheLookup1Zdd */
+
+
+/**Function********************************************************************
+
+  Synopsis [Looks up in the cache for the result of op applied to f,
+  g, and h.]
+
+  Description [Looks up in the cache for the result of op applied to f,
+  g, and h. Assumes that the calling procedure (e.g.,
+  Cudd_bddIteConstant) is only interested in whether the result is
+  constant or not. Returns the result if found (possibly
+  DD_NON_CONSTANT); otherwise it returns NULL.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheLookup]
+
+******************************************************************************/
+DdNode *
+cuddConstantLookup(
+  DdManager * table,
+  ptruint op,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    int posn;
+    DdCache *en,*cache;
+    ptruint uf, ug, uh;
+    ptruint ufc, ugc, uhc;
+
+    uf = (ptruint) f | (op & 0xe);
+    ug = (ptruint) g | (op >> 4);
+    uh = (ptruint) h;
+
+    ufc = (ptruint) cuddF2L(f) | (op & 0xe);
+    ugc = (ptruint) cuddF2L(g) | (op >> 4);
+    uhc = (ptruint) cuddF2L(h);
+
+    cache = table->cache;
+#ifdef DD_DEBUG
+    if (cache == NULL) {
+        return(NULL);
+    }
+#endif
+    posn = ddCHash2(uhc,ufc,ugc,table->cacheShift);
+    en = &cache[posn];
+
+    /* We do not reclaim here because the result should not be
+     * referenced, but only tested for being a constant.
+     */
+    if (en->data != NULL &&
+        en->f == (DdNodePtr)uf && en->g == (DdNodePtr)ug && en->h == uh) {
+        table->cacheHits++;
+        return(en->data);
+    }
+
+    /* Cache miss: decide whether to resize. */
+    table->cacheMisses++;
+
+    if (table->cacheSlack >= 0 &&
+        table->cacheHits > table->cacheMisses * table->minHit) {
+        cuddCacheResize(table);
+    }
+
+    return(NULL);
+
+} /* end of cuddConstantLookup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes and prints a profile of the cache usage.]
+
+  Description [Computes and prints a profile of the cache usage.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddCacheProfile(
+  DdManager * table,
+  FILE * fp)
+{
+    DdCache *cache = table->cache;
+    int slots = table->cacheSlots;
+    int nzeroes = 0;
+    int i, retval;
+    double exUsed;
+
+#ifdef DD_CACHE_PROFILE
+    double count, mean, meansq, stddev, expected;
+    long max, min;
+    int imax, imin;
+    double *hystogramQ, *hystogramR; /* histograms by quotient and remainder */
+    int nbins = DD_HYSTO_BINS;
+    int bin;
+    long thiscount;
+    double totalcount, exStddev;
+
+    meansq = mean = expected = 0.0;
+    max = min = (long) cache[0].count;
+    imax = imin = 0;
+    totalcount = 0.0;
+
+    hystogramQ = ABC_ALLOC(double, nbins);
+    if (hystogramQ == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    hystogramR = ABC_ALLOC(double, nbins);
+    if (hystogramR == NULL) {
+        ABC_FREE(hystogramQ);
+        table->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    for (i = 0; i < nbins; i++) {
+        hystogramQ[i] = 0;
+        hystogramR[i] = 0;
+    }
+
+    for (i = 0; i < slots; i++) {
+        thiscount = (long) cache[i].count;
+        if (thiscount > max) {
+            max = thiscount;
+            imax = i;
+        }
+        if (thiscount < min) {
+            min = thiscount;
+            imin = i;
+        }
+        if (thiscount == 0) {
+            nzeroes++;
+        }
+        count = (double) thiscount;
+        mean += count;
+        meansq += count * count;
+        totalcount += count;
+        expected += count * (double) i;
+        bin = (i * nbins) / slots;
+        hystogramQ[bin] += (double) thiscount;
+        bin = i % nbins;
+        hystogramR[bin] += (double) thiscount;
+    }
+    mean /= (double) slots;
+    meansq /= (double) slots;
+
+    /* Compute the standard deviation from both the data and the
+    ** theoretical model for a random distribution. */
+    stddev = sqrt(meansq - mean*mean);
+    exStddev = sqrt((1 - 1/(double) slots) * totalcount / (double) slots);
+
+    retval = fprintf(fp,"Cache average accesses = %g\n",  mean);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Cache access standard deviation = %g ", stddev);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"(expected = %g)\n", exStddev);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin);
+    if (retval == EOF) return(0);
+    exUsed = 100.0 * (1.0 - exp(-totalcount / (double) slots));
+    retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n",
+                     100.0 - (double) nzeroes * 100.0 / (double) slots,
+                     exUsed);
+    if (retval == EOF) return(0);
+
+    if (totalcount > 0) {
+        expected /= totalcount;
+        retval = fprintf(fp,"Cache access hystogram for %d bins", nbins);
+        if (retval == EOF) return(0);
+        retval = fprintf(fp," (expected bin value = %g)\nBy quotient:",
+                         expected);
+        if (retval == EOF) return(0);
+        for (i = nbins - 1; i>=0; i--) {
+            retval = fprintf(fp," %.0f", hystogramQ[i]);
+            if (retval == EOF) return(0);
+        }
+        retval = fprintf(fp,"\nBy residue: ");
+        if (retval == EOF) return(0);
+        for (i = nbins - 1; i>=0; i--) {
+            retval = fprintf(fp," %.0f", hystogramR[i]);
+            if (retval == EOF) return(0);
+        }
+        retval = fprintf(fp,"\n");
+        if (retval == EOF) return(0);
+    }
+
+    ABC_FREE(hystogramQ);
+    ABC_FREE(hystogramR);
+#else
+    for (i = 0; i < slots; i++) {
+        nzeroes += cache[i].h == 0;
+    }
+    exUsed = 100.0 *
+        (1.0 - exp(-(table->cacheinserts - table->cacheLastInserts) /
+                   (double) slots));
+    retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n",
+                     100.0 - (double) nzeroes * 100.0 / (double) slots,
+                     exUsed);
+    if (retval == EOF) return(0);
+#endif
+    return(1);
+
+} /* end of cuddCacheProfile */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resizes the cache.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddCacheResize(
+  DdManager * table)
+{
+    DdCache *cache, *oldcache, *oldacache, *entry, *old;
+    int i;
+    int posn, shift;
+    unsigned int slots, oldslots;
+    double offset;
+    int moved = 0;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+#ifndef DD_CACHE_PROFILE
+    ptruint misalignment;
+    DdNodePtr *mem;
+#endif
+
+    oldcache = table->cache;
+    oldacache = table->acache;
+    oldslots = table->cacheSlots;
+    slots = table->cacheSlots = oldslots << 1;
+
+#ifdef DD_VERBOSE
+    (void) fprintf(table->err,"Resizing the cache from %d to %d entries\n",
+                   oldslots, slots);
+    (void) fprintf(table->err,
+                   "\thits = %g\tmisses = %g\thit ratio = %5.3f\n",
+                   table->cacheHits, table->cacheMisses,
+                   table->cacheHits / (table->cacheHits + table->cacheMisses));
+#endif
+
+    saveHandler = MMoutOfMemory;
+    MMoutOfMemory = Cudd_OutOfMem;
+//    table->acache = cache = ABC_ALLOC(DdCache,slots+1);
+    table->acache = cache = ABC_ALLOC(DdCache,slots+2);
+    MMoutOfMemory = saveHandler;
+    /* If we fail to allocate the new table we just give up. */
+    if (cache == NULL) {
+#ifdef DD_VERBOSE
+        (void) fprintf(table->err,"Resizing failed. Giving up.\n");
+#endif
+        table->cacheSlots = oldslots;
+        table->acache = oldacache;
+        /* Do not try to resize again. */
+        table->maxCacheHard = oldslots - 1;
+        table->cacheSlack = - (int) (oldslots + 1);
+        return;
+    }
+    /* If the size of the cache entry is a power of 2, we want to
+    ** enforce alignment to that power of two. This happens when
+    ** DD_CACHE_PROFILE is not defined. */
+#ifdef DD_CACHE_PROFILE
+    table->cache = cache;
+#else
+    mem = (DdNodePtr *) cache;
+//    misalignment = (ptruint) mem & (sizeof(DdCache) - 1);
+//    mem += (sizeof(DdCache) - misalignment) / sizeof(DdNodePtr);
+//    table->cache = cache = (DdCache *) mem;
+//    assert(((ptruint) table->cache & (sizeof(DdCache) - 1)) == 0);
+    misalignment = (ptruint) mem & (32 - 1);
+    mem += (32 - misalignment) / sizeof(DdNodePtr);
+    table->cache = cache = (DdCache *) mem;
+    assert(((ptruint) table->cache & (32 - 1)) == 0);
+#endif
+    shift = --(table->cacheShift);
+    table->memused += (slots - oldslots) * sizeof(DdCache);
+    table->cacheSlack -= slots; /* need these many slots to double again */
+
+    /* Clear new cache. */
+    for (i = 0; (unsigned) i < slots; i++) {
+        cache[i].data = NULL;
+        cache[i].h = 0;
+#ifdef DD_CACHE_PROFILE
+        cache[i].count = 0;
+#endif
+    }
+
+    /* Copy from old cache to new one. */
+    for (i = 0; (unsigned) i < oldslots; i++) {
+        old = &oldcache[i];
+        if (old->data != NULL) {
+//            posn = ddCHash2(old->h,old->f,old->g,shift);
+            posn = old->hash >> shift;
+            entry = &cache[posn];
+            entry->f = old->f;
+            entry->g = old->g;
+            entry->h = old->h;
+            entry->data = old->data;
+#ifdef DD_CACHE_PROFILE
+            entry->count = 1;
+#endif
+            entry->hash = old->hash;
+            moved++;
+        }
+    }
+
+    ABC_FREE(oldacache);
+
+    /* Reinitialize measurements so as to avoid division by 0 and
+    ** immediate resizing.
+    */
+    offset = (double) (int) (slots * table->minHit + 1);
+    table->totCacheMisses += table->cacheMisses - offset;
+    table->cacheMisses = offset;
+    table->totCachehits += table->cacheHits;
+    table->cacheHits = 0;
+    table->cacheLastInserts = table->cacheinserts - (double) moved;
+
+} /* end of cuddCacheResize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Flushes the cache.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddCacheFlush(
+  DdManager * table)
+{
+    int i, slots;
+    DdCache *cache;
+
+    slots = table->cacheSlots;
+    cache = table->cache;
+    for (i = 0; i < slots; i++) {
+        table->cachedeletions += cache[i].data != NULL;
+        cache[i].data = NULL;
+    }
+    table->cacheLastInserts = table->cacheinserts;
+
+    return;
+
+} /* end of cuddCacheFlush */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the floor of the logarithm to the base 2.]
+
+  Description [Returns the floor of the logarithm to the base 2.
+  The input value is assumed to be greater than 0.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddComputeFloorLog2(
+  unsigned int value)
+{
+    int floorLog = 0;
+#ifdef DD_DEBUG
+    assert(value > 0);
+#endif
+    while (value > 1) {
+        floorLog++;
+        value >>= 1;
+    }
+    return(floorLog);
+
+} /* end of cuddComputeFloorLog2 */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddCheck.c b/abc-build/src/bdd/cudd/cuddCheck.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddCheck.c
@@ -0,0 +1,887 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddCheck.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions to check consistency of data structures.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_DebugCheck()
+                <li> Cudd_CheckKeys()
+                </ul>
+               Internal procedures included in this module:
+                <ul>
+                <li> cuddHeapProfile()
+                <li> cuddPrintNode()
+                <li> cuddPrintVarGroups()
+                </ul>
+               Static procedures included in this module:
+                <ul>
+                <li> debugFindParent()
+                </ul>
+                ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddCheck.c,v 1.35 2009/03/08 02:49:01 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void debugFindParent (DdManager *table, DdNode *node);
+#if 0
+static void debugCheckParent (DdManager *table, DdNode *node);
+#endif
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks for inconsistencies in the DD heap.]
+
+  Description [Checks for inconsistencies in the DD heap:
+  <ul>
+  <li> node has illegal index
+  <li> live node has dead children
+  <li> node has illegal Then or Else pointers
+  <li> BDD/ADD node has identical children
+  <li> ZDD node has zero then child
+  <li> wrong number of total nodes
+  <li> wrong number of dead nodes
+  <li> ref count error at node
+  </ul>
+  Returns 0 if no inconsistencies are found; DD_OUT_OF_MEM if there is
+  not enough memory; 1 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_CheckKeys]
+
+******************************************************************************/
+int
+Cudd_DebugCheck(
+  DdManager * table)
+{
+    unsigned int i;
+    int         j,count;
+    int         slots;
+    DdNodePtr   *nodelist;
+    DdNode      *f;
+    DdNode      *sentinel = &(table->sentinel);
+    st__table    *edgeTable;     /* stores internal ref count for each node */
+    st__generator        *gen;
+    int         flag = 0;
+    int         totalNode;
+    int         deadNode;
+    int         index;
+
+
+    edgeTable = st__init_table( st__ptrcmp, st__ptrhash);
+    if (edgeTable == NULL) return(CUDD_OUT_OF_MEM);
+
+    /* Check the BDD/ADD subtables. */
+    for (i = 0; i < (unsigned) table->size; i++) {
+        index = table->invperm[i];
+        if (i != (unsigned) table->perm[index]) {
+            (void) fprintf(table->err,
+                           "Permutation corrupted: invperm[%u] = %d\t perm[%d] = %d\n",
+                           i, index, index, table->perm[index]);
+        }
+        nodelist = table->subtables[i].nodelist;
+        slots = table->subtables[i].slots;
+
+        totalNode = 0;
+        deadNode = 0;
+        for (j = 0; j < slots; j++) {   /* for each subtable slot */
+            f = nodelist[j];
+            while (f != sentinel) {
+                totalNode++;
+                if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) {
+                    if ((int) f->index != index) {
+                        (void) fprintf(table->err,
+                                       "Error: node has illegal index\n");
+                        cuddPrintNode(f,table->err);
+                        flag = 1;
+                    }
+                    if ((unsigned) cuddI(table,cuddT(f)->index) <= i ||
+                        (unsigned) cuddI(table,Cudd_Regular(cuddE(f))->index)
+                        <= i) {
+                        (void) fprintf(table->err,
+                                       "Error: node has illegal children\n");
+                        cuddPrintNode(f,table->err);
+                        flag = 1;
+                    }
+                    if (Cudd_Regular(cuddT(f)) != cuddT(f)) {
+                        (void) fprintf(table->err,
+                                       "Error: node has illegal form\n");
+                        cuddPrintNode(f,table->err);
+                        flag = 1;
+                    }
+                    if (cuddT(f) == cuddE(f)) {
+                        (void) fprintf(table->err,
+                                       "Error: node has identical children\n");
+                        cuddPrintNode(f,table->err);
+                        flag = 1;
+                    }
+                    if (cuddT(f)->ref == 0 || Cudd_Regular(cuddE(f))->ref == 0) {
+                        (void) fprintf(table->err,
+                                       "Error: live node has dead children\n");
+                        cuddPrintNode(f,table->err);
+                        flag =1;
+                    }
+                    /* Increment the internal reference count for the
+                    ** then child of the current node.
+                    */
+                    if ( st__lookup_int(edgeTable,(char *)cuddT(f),&count)) {
+                        count++;
+                    } else {
+                        count = 1;
+                    }
+                    if ( st__insert(edgeTable,(char *)cuddT(f),
+                    (char *)(long)count) == st__OUT_OF_MEM) {
+                        st__free_table(edgeTable);
+                        return(CUDD_OUT_OF_MEM);
+                    }
+
+                    /* Increment the internal reference count for the
+                    ** else child of the current node.
+                    */
+                    if ( st__lookup_int(edgeTable,(char *)Cudd_Regular(cuddE(f)),
+                                      &count)) {
+                        count++;
+                    } else {
+                        count = 1;
+                    }
+                    if ( st__insert(edgeTable,(char *)Cudd_Regular(cuddE(f)),
+                    (char *)(long)count) == st__OUT_OF_MEM) {
+                        st__free_table(edgeTable);
+                        return(CUDD_OUT_OF_MEM);
+                    }
+                } else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) {
+                    deadNode++;
+#if 0
+                    debugCheckParent(table,f);
+#endif
+                } else {
+                    fprintf(table->err,
+                            "Error: node has illegal Then or Else pointers\n");
+                    cuddPrintNode(f,table->err);
+                    flag = 1;
+                }
+
+                f = f->next;
+            }   /* for each element of the collision list */
+        }       /* for each subtable slot */
+
+        if ((unsigned) totalNode != table->subtables[i].keys) {
+            fprintf(table->err,"Error: wrong number of total nodes\n");
+            flag = 1;
+        }
+        if ((unsigned) deadNode != table->subtables[i].dead) {
+            fprintf(table->err,"Error: wrong number of dead nodes\n");
+            flag = 1;
+        }
+    }   /* for each BDD/ADD subtable */
+
+    /* Check the ZDD subtables. */
+    for (i = 0; i < (unsigned) table->sizeZ; i++) {
+        index = table->invpermZ[i];
+        if (i != (unsigned) table->permZ[index]) {
+            (void) fprintf(table->err,
+                           "Permutation corrupted: invpermZ[%u] = %d\t permZ[%d] = %d in ZDD\n",
+                           i, index, index, table->permZ[index]);
+        }
+        nodelist = table->subtableZ[i].nodelist;
+        slots = table->subtableZ[i].slots;
+
+        totalNode = 0;
+        deadNode = 0;
+        for (j = 0; j < slots; j++) {   /* for each subtable slot */
+            f = nodelist[j];
+            while (f != NULL) {
+                totalNode++;
+                if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) {
+                    if ((int) f->index != index) {
+                        (void) fprintf(table->err,
+                                       "Error: ZDD node has illegal index\n");
+                        cuddPrintNode(f,table->err);
+                        flag = 1;
+                    }
+                    if (Cudd_IsComplement(cuddT(f)) ||
+                        Cudd_IsComplement(cuddE(f))) {
+                        (void) fprintf(table->err,
+                                       "Error: ZDD node has complemented children\n");
+                        cuddPrintNode(f,table->err);
+                        flag = 1;
+                    }
+                    if ((unsigned) cuddIZ(table,cuddT(f)->index) <= i ||
+                    (unsigned) cuddIZ(table,cuddE(f)->index) <= i) {
+                        (void) fprintf(table->err,
+                                       "Error: ZDD node has illegal children\n");
+                        cuddPrintNode(f,table->err);
+                        cuddPrintNode(cuddT(f),table->err);
+                        cuddPrintNode(cuddE(f),table->err);
+                        flag = 1;
+                    }
+                    if (cuddT(f) == DD_ZERO(table)) {
+                        (void) fprintf(table->err,
+                                       "Error: ZDD node has zero then child\n");
+                        cuddPrintNode(f,table->err);
+                        flag = 1;
+                    }
+                    if (cuddT(f)->ref == 0 || cuddE(f)->ref == 0) {
+                        (void) fprintf(table->err,
+                                       "Error: ZDD live node has dead children\n");
+                        cuddPrintNode(f,table->err);
+                        flag =1;
+                    }
+                    /* Increment the internal reference count for the
+                    ** then child of the current node.
+                    */
+                    if ( st__lookup_int(edgeTable,(char *)cuddT(f),&count)) {
+                        count++;
+                    } else {
+                        count = 1;
+                    }
+                    if ( st__insert(edgeTable,(char *)cuddT(f),
+                    (char *)(long)count) == st__OUT_OF_MEM) {
+                        st__free_table(edgeTable);
+                        return(CUDD_OUT_OF_MEM);
+                    }
+
+                    /* Increment the internal reference count for the
+                    ** else child of the current node.
+                    */
+                    if ( st__lookup_int(edgeTable,(char *)cuddE(f),&count)) {
+                        count++;
+                    } else {
+                        count = 1;
+                    }
+                    if ( st__insert(edgeTable,(char *)cuddE(f),
+                    (char *)(long)count) == st__OUT_OF_MEM) {
+                        st__free_table(edgeTable);
+                        table->errorCode = CUDD_MEMORY_OUT;
+                        return(CUDD_OUT_OF_MEM);
+                    }
+                } else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) {
+                    deadNode++;
+#if 0
+                    debugCheckParent(table,f);
+#endif
+                } else {
+                    fprintf(table->err,
+                            "Error: ZDD node has illegal Then or Else pointers\n");
+                    cuddPrintNode(f,table->err);
+                    flag = 1;
+                }
+
+                f = f->next;
+            }   /* for each element of the collision list */
+        }       /* for each subtable slot */
+
+        if ((unsigned) totalNode != table->subtableZ[i].keys) {
+            fprintf(table->err,
+                    "Error: wrong number of total nodes in ZDD\n");
+            flag = 1;
+        }
+        if ((unsigned) deadNode != table->subtableZ[i].dead) {
+            fprintf(table->err,
+                    "Error: wrong number of dead nodes in ZDD\n");
+            flag = 1;
+        }
+    }   /* for each ZDD subtable */
+
+    /* Check the constant table. */
+    nodelist = table->constants.nodelist;
+    slots = table->constants.slots;
+
+    totalNode = 0;
+    deadNode = 0;
+    for (j = 0; j < slots; j++) {
+        f = nodelist[j];
+        while (f != NULL) {
+            totalNode++;
+            if (f->ref != 0) {
+                if (f->index != CUDD_CONST_INDEX) {
+                    fprintf(table->err,"Error: node has illegal index\n");
+#if SIZEOF_VOID_P == 8
+                    fprintf(table->err,
+                            "       node 0x%lx, id = %u, ref = %u, value = %g\n",
+                            (ptruint)f,f->index,f->ref,cuddV(f));
+#else
+                    fprintf(table->err,
+                            "       node 0x%x, id = %hu, ref = %hu, value = %g\n",
+                            (ptruint)f,f->index,f->ref,cuddV(f));
+#endif
+                    flag = 1;
+                }
+            } else {
+                deadNode++;
+            }
+            f = f->next;
+        }
+    }
+    if ((unsigned) totalNode != table->constants.keys) {
+        (void) fprintf(table->err,
+                       "Error: wrong number of total nodes in constants\n");
+        flag = 1;
+    }
+    if ((unsigned) deadNode != table->constants.dead) {
+        (void) fprintf(table->err,
+                       "Error: wrong number of dead nodes in constants\n");
+        flag = 1;
+    }
+    gen = st__init_gen(edgeTable);
+    while ( st__gen(gen, (const char **)&f, (char **)&count)) {
+        if (count > (int)(f->ref) && f->ref != DD_MAXREF) {
+#if SIZEOF_VOID_P == 8
+            fprintf(table->err,"ref count error at node 0x%lx, count = %d, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",(ptruint)f,count,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
+#else
+            fprintf(table->err,"ref count error at node 0x%x, count = %d, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",(ptruint)f,count,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
+#endif
+            debugFindParent(table,f);
+            flag = 1;
+        }
+    }
+    st__free_gen(gen);
+    st__free_table(edgeTable);
+
+    return (flag);
+
+} /* end of Cudd_DebugCheck */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks for several conditions that should not occur.]
+
+  Description [Checks for the following conditions:
+  <ul>
+  <li>Wrong sizes of subtables.
+  <li>Wrong number of keys found in unique subtable.
+  <li>Wrong number of dead found in unique subtable.
+  <li>Wrong number of keys found in the constant table
+  <li>Wrong number of dead found in the constant table
+  <li>Wrong number of total slots found
+  <li>Wrong number of maximum keys found
+  <li>Wrong number of total dead found
+  </ul>
+  Reports the average length of non-empty lists. Returns the number of
+  subtables for which the number of keys is wrong.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DebugCheck]
+
+******************************************************************************/
+int
+Cudd_CheckKeys(
+  DdManager * table)
+{
+    int size;
+    int i,j;
+    DdNodePtr *nodelist;
+    DdNode *node;
+    DdNode *sentinel = &(table->sentinel);
+    DdSubtable *subtable;
+    int keys;
+    int dead;
+    int count = 0;
+    int totalKeys = 0;
+    int totalSlots = 0;
+    int totalDead = 0;
+    int nonEmpty = 0;
+    unsigned int slots;
+    int logSlots;
+    int shift;
+
+    size = table->size;
+
+    for (i = 0; i < size; i++) {
+        subtable = &(table->subtables[i]);
+        nodelist = subtable->nodelist;
+        keys = subtable->keys;
+        dead = subtable->dead;
+        totalKeys += keys;
+        slots = subtable->slots;
+        shift = subtable->shift;
+        logSlots = sizeof(int) * 8 - shift;
+        if (((slots >> logSlots) << logSlots) != slots) {
+            (void) fprintf(table->err,
+                           "Unique table %d is not the right power of 2\n", i);
+            (void) fprintf(table->err,
+                           "    slots = %u shift = %d\n", slots, shift);
+        }
+        totalSlots += slots;
+        totalDead += dead;
+        for (j = 0; (unsigned) j < slots; j++) {
+            node = nodelist[j];
+            if (node != sentinel) {
+                nonEmpty++;
+            }
+            while (node != sentinel) {
+                keys--;
+                if (node->ref == 0) {
+                    dead--;
+                }
+                node = node->next;
+            }
+        }
+        if (keys != 0) {
+            (void) fprintf(table->err, "Wrong number of keys found \
+in unique table %d (difference=%d)\n", i, keys);
+            count++;
+        }
+        if (dead != 0) {
+            (void) fprintf(table->err, "Wrong number of dead found \
+in unique table no. %d (difference=%d)\n", i, dead);
+        }
+    }   /* for each BDD/ADD subtable */
+
+    /* Check the ZDD subtables. */
+    size = table->sizeZ;
+
+    for (i = 0; i < size; i++) {
+        subtable = &(table->subtableZ[i]);
+        nodelist = subtable->nodelist;
+        keys = subtable->keys;
+        dead = subtable->dead;
+        totalKeys += keys;
+        totalSlots += subtable->slots;
+        totalDead += dead;
+        for (j = 0; (unsigned) j < subtable->slots; j++) {
+            node = nodelist[j];
+            if (node != NULL) {
+                nonEmpty++;
+            }
+            while (node != NULL) {
+                keys--;
+                if (node->ref == 0) {
+                    dead--;
+                }
+                node = node->next;
+            }
+        }
+        if (keys != 0) {
+            (void) fprintf(table->err, "Wrong number of keys found \
+in ZDD unique table no. %d (difference=%d)\n", i, keys);
+            count++;
+        }
+        if (dead != 0) {
+            (void) fprintf(table->err, "Wrong number of dead found \
+in ZDD unique table no. %d (difference=%d)\n", i, dead);
+        }
+    }   /* for each ZDD subtable */
+
+    /* Check the constant table. */
+    subtable = &(table->constants);
+    nodelist = subtable->nodelist;
+    keys = subtable->keys;
+    dead = subtable->dead;
+    totalKeys += keys;
+    totalSlots += subtable->slots;
+    totalDead += dead;
+    for (j = 0; (unsigned) j < subtable->slots; j++) {
+        node = nodelist[j];
+        if (node != NULL) {
+            nonEmpty++;
+        }
+        while (node != NULL) {
+            keys--;
+            if (node->ref == 0) {
+                dead--;
+            }
+            node = node->next;
+        }
+    }
+    if (keys != 0) {
+        (void) fprintf(table->err, "Wrong number of keys found \
+in the constant table (difference=%d)\n", keys);
+        count++;
+    }
+    if (dead != 0) {
+        (void) fprintf(table->err, "Wrong number of dead found \
+in the constant table (difference=%d)\n", dead);
+    }
+    if ((unsigned) totalKeys != table->keys + table->keysZ) {
+        (void) fprintf(table->err, "Wrong number of total keys found \
+(difference=%d)\n", (int) (totalKeys-table->keys));
+    }
+    if ((unsigned) totalSlots != table->slots) {
+        (void) fprintf(table->err, "Wrong number of total slots found \
+(difference=%d)\n", (int) (totalSlots-table->slots));
+    }
+    if (table->minDead != (unsigned) (table->gcFrac * table->slots)) {
+        (void) fprintf(table->err, "Wrong number of minimum dead found \
+(%u vs. %u)\n", table->minDead,
+        (unsigned) (table->gcFrac * (double) table->slots));
+    }
+    if ((unsigned) totalDead != table->dead + table->deadZ) {
+        (void) fprintf(table->err, "Wrong number of total dead found \
+(difference=%d)\n", (int) (totalDead-table->dead));
+    }
+    (void)printf("Average length of non-empty lists = %g\n",
+    (double) table->keys / (double) nonEmpty);
+
+    return(count);
+
+} /* end of Cudd_CheckKeys */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints information about the heap.]
+
+  Description [Prints to the manager's stdout the number of live nodes for each
+  level of the DD heap that contains at least one live node.  It also
+  prints a summary containing:
+  <ul>
+  <li> total number of tables;
+  <li> number of tables with live nodes;
+  <li> table with the largest number of live nodes;
+  <li> number of nodes in that table.
+  </ul>
+  If more than one table contains the maximum number of live nodes,
+  only the one of lowest index is reported. Returns 1 in case of success
+  and 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddHeapProfile(
+  DdManager * dd)
+{
+    int ntables = dd->size;
+    DdSubtable *subtables = dd->subtables;
+    int i,              /* loop index */
+        nodes,          /* live nodes in i-th layer */
+        retval,         /* return value of fprintf */
+        largest = -1,   /* index of the table with most live nodes */
+        maxnodes = -1,  /* maximum number of live nodes in a table */
+        nonempty = 0;   /* number of tables with live nodes */
+
+    /* Print header. */
+#if SIZEOF_VOID_P == 8
+    retval = fprintf(dd->out,"*** DD heap profile for 0x%lx ***\n",
+                     (ptruint) dd);
+#else
+    retval = fprintf(dd->out,"*** DD heap profile for 0x%x ***\n",
+                     (ptruint) dd);
+#endif
+    if (retval == EOF) return 0;
+
+    /* Print number of live nodes for each nonempty table. */
+    for (i=0; i<ntables; i++) {
+        nodes = subtables[i].keys - subtables[i].dead;
+        if (nodes) {
+            nonempty++;
+            retval = fprintf(dd->out,"%5d: %5d nodes\n", i, nodes);
+            if (retval == EOF) return 0;
+            if (nodes > maxnodes) {
+                maxnodes = nodes;
+                largest = i;
+            }
+        }
+    }
+
+    nodes = dd->constants.keys - dd->constants.dead;
+    if (nodes) {
+        nonempty++;
+        retval = fprintf(dd->out,"const: %5d nodes\n", nodes);
+        if (retval == EOF) return 0;
+        if (nodes > maxnodes) {
+            maxnodes = nodes;
+            largest = CUDD_CONST_INDEX;
+        }
+    }
+
+    /* Print summary. */
+    retval = fprintf(dd->out,"Summary: %d tables, %d non-empty, largest: %d ",
+          ntables+1, nonempty, largest);
+    if (retval == EOF) return 0;
+    retval = fprintf(dd->out,"(with %d nodes)\n", maxnodes);
+    if (retval == EOF) return 0;
+
+    return(1);
+
+} /* end of cuddHeapProfile */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints out information on a node.]
+
+  Description [Prints out information on a node.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddPrintNode(
+  DdNode * f,
+  FILE *fp)
+{
+    f = Cudd_Regular(f);
+#if SIZEOF_VOID_P == 8
+    (void) fprintf(fp,"       node 0x%lx, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",(ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
+#else
+    (void) fprintf(fp,"       node 0x%x, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",(ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
+#endif
+
+} /* end of cuddPrintNode */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the variable groups as a parenthesized list.]
+
+  Description [Prints the variable groups as a parenthesized list.
+  For each group the level range that it represents is printed. After
+  each group, the group's flags are printed, preceded by a `|'.  For
+  each flag (except MTR_TERMINAL) a character is printed.
+  <ul>
+  <li>F: MTR_FIXED
+  <li>N: MTR_NEWNODE
+  <li>S: MTR_SOFT
+  </ul>
+  The second argument, silent, if different from 0, causes
+  Cudd_PrintVarGroups to only check the syntax of the group tree.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddPrintVarGroups(
+  DdManager * dd /* manager */,
+  MtrNode * root /* root of the group tree */,
+  int zdd /* 0: BDD; 1: ZDD */,
+  int silent /* flag to check tree syntax only */)
+{
+    MtrNode *node;
+    int level;
+
+    assert(root != NULL);
+    assert(root->younger == NULL || root->younger->elder == root);
+    assert(root->elder == NULL || root->elder->younger == root);
+    if (zdd) {
+        level = dd->permZ[root->index];
+    } else {
+        level = dd->perm[root->index];
+    }
+    if (!silent) (void) printf("(%d",level);
+    if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) {
+        if (!silent) (void) printf(",");
+    } else {
+        node = root->child;
+        while (node != NULL) {
+            assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size));
+            assert(node->parent == root);
+            cuddPrintVarGroups(dd,node,zdd,silent);
+            node = node->younger;
+        }
+    }
+    if (!silent) {
+        (void) printf("%d", (int) (level + root->size - 1));
+        if (root->flags != MTR_DEFAULT) {
+            (void) printf("|");
+            if (MTR_TEST(root,MTR_FIXED)) (void) printf("F");
+            if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N");
+            if (MTR_TEST(root,MTR_SOFT)) (void) printf("S");
+        }
+        (void) printf(")");
+        if (root->parent == NULL) (void) printf("\n");
+    }
+    assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0);
+    return;
+
+} /* end of cuddPrintVarGroups */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Searches the subtables above node for its parents.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+debugFindParent(
+  DdManager * table,
+  DdNode * node)
+{
+    int         i,j;
+    int         slots;
+    DdNodePtr   *nodelist;
+    DdNode      *f;
+
+    for (i = 0; i < cuddI(table,node->index); i++) {
+        nodelist = table->subtables[i].nodelist;
+        slots = table->subtables[i].slots;
+
+        for (j=0;j<slots;j++) {
+            f = nodelist[j];
+            while (f != NULL) {
+                if (cuddT(f) == node || Cudd_Regular(cuddE(f)) == node) {
+#if SIZEOF_VOID_P == 8
+                    (void) fprintf(table->out,"parent is at 0x%lx, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",
+                        (ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
+#else
+                    (void) fprintf(table->out,"parent is at 0x%x, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",
+                        (ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
+#endif
+                }
+                f = f->next;
+            }
+        }
+    }
+
+} /* end of debugFindParent */
+
+
+#if 0
+/**Function********************************************************************
+
+  Synopsis    [Reports an error if a (dead) node has a non-dead parent.]
+
+  Description [Searches all the subtables above node. Very expensive.
+  The same check is now implemented more efficiently in ddDebugCheck.]
+
+  SideEffects [None]
+
+  SeeAlso     [debugFindParent]
+
+******************************************************************************/
+static void
+debugCheckParent(
+  DdManager * table,
+  DdNode * node)
+{
+    int         i,j;
+    int         slots;
+    DdNode      **nodelist,*f;
+
+    for (i = 0; i < cuddI(table,node->index); i++) {
+        nodelist = table->subtables[i].nodelist;
+        slots = table->subtables[i].slots;
+
+        for (j=0;j<slots;j++) {
+            f = nodelist[j];
+            while (f != NULL) {
+                if ((Cudd_Regular(cuddE(f)) == node || cuddT(f) == node) && f->ref != 0) {
+                    (void) fprintf(table->err,
+                                   "error with zero ref count\n");
+                    (void) fprintf(table->err,"parent is 0x%x, id = %u, ref = %u, then = 0x%x, else = 0x%x\n",f,f->index,f->ref,cuddT(f),cuddE(f));
+                    (void) fprintf(table->err,"child  is 0x%x, id = %u, ref = %u, then = 0x%x, else = 0x%x\n",node,node->index,node->ref,cuddT(node),cuddE(node));
+                }
+                f = f->next;
+            }
+        }
+    }
+}
+#endif
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddClip.c b/abc-build/src/bdd/cudd/cuddClip.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddClip.c
@@ -0,0 +1,566 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddClip.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Clipping functions.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_bddClippingAnd()
+                <li> Cudd_bddClippingAndAbstract()
+                </ul>
+       Internal procedures included in this module:
+                <ul>
+                <li> cuddBddClippingAnd()
+                <li> cuddBddClippingAndAbstract()
+                </ul>
+       Static procedures included in this module:
+                <ul>
+                <li> cuddBddClippingAndRecur()
+                <li> cuddBddClipAndAbsRecur()
+                </ul>
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddClip.c,v 1.8 2004/08/13 18:04:47 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * cuddBddClippingAndRecur (DdManager *manager, DdNode *f, DdNode *g, int distance, int direction);
+static DdNode * cuddBddClipAndAbsRecur (DdManager *manager, DdNode *f, DdNode *g, DdNode *cube, int distance, int direction);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Approximates the conjunction of two BDDs f and g.]
+
+  Description [Approximates the conjunction of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddAnd]
+
+******************************************************************************/
+DdNode *
+Cudd_bddClippingAnd(
+  DdManager * dd /* manager */,
+  DdNode * f /* first conjunct */,
+  DdNode * g /* second conjunct */,
+  int  maxDepth /* maximum recursion depth */,
+  int  direction /* under (0) or over (1) approximation */)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddClippingAnd(dd,f,g,maxDepth,direction);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddClippingAnd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Approximates the conjunction of two BDDs f and g and
+  simultaneously abstracts the variables in cube.]
+
+  Description [Approximates the conjunction of two BDDs f and g and
+  simultaneously abstracts the variables in cube. The variables are
+  existentially abstracted. Returns a pointer to the resulting BDD if
+  successful; NULL if the intermediate result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddAndAbstract Cudd_bddClippingAnd]
+
+******************************************************************************/
+DdNode *
+Cudd_bddClippingAndAbstract(
+  DdManager * dd /* manager */,
+  DdNode * f /* first conjunct */,
+  DdNode * g /* second conjunct */,
+  DdNode * cube /* cube of variables to be abstracted */,
+  int  maxDepth /* maximum recursion depth */,
+  int  direction /* under (0) or over (1) approximation */)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddClippingAndAbstract(dd,f,g,cube,maxDepth,direction);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddClippingAndAbstract */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Approximates the conjunction of two BDDs f and g.]
+
+  Description [Approximates the conjunction of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddClippingAnd]
+
+******************************************************************************/
+DdNode *
+cuddBddClippingAnd(
+  DdManager * dd /* manager */,
+  DdNode * f /* first conjunct */,
+  DdNode * g /* second conjunct */,
+  int  maxDepth /* maximum recursion depth */,
+  int  direction /* under (0) or over (1) approximation */)
+{
+    DdNode *res;
+
+    res = cuddBddClippingAndRecur(dd,f,g,maxDepth,direction);
+
+    return(res);
+
+} /* end of cuddBddClippingAnd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Approximates the conjunction of two BDDs f and g and
+  simultaneously abstracts the variables in cube.]
+
+  Description [Approximates the conjunction of two BDDs f and g and
+  simultaneously abstracts the variables in cube. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddClippingAndAbstract]
+
+******************************************************************************/
+DdNode *
+cuddBddClippingAndAbstract(
+  DdManager * dd /* manager */,
+  DdNode * f /* first conjunct */,
+  DdNode * g /* second conjunct */,
+  DdNode * cube /* cube of variables to be abstracted */,
+  int  maxDepth /* maximum recursion depth */,
+  int  direction /* under (0) or over (1) approximation */)
+{
+    DdNode *res;
+
+    res = cuddBddClipAndAbsRecur(dd,f,g,cube,maxDepth,direction);
+
+    return(res);
+
+} /* end of cuddBddClippingAndAbstract */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Implements the recursive step of Cudd_bddClippingAnd.]
+
+  Description [Implements the recursive step of Cudd_bddClippingAnd by taking
+  the conjunction of two BDDs.  Returns a pointer to the result is
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddBddClippingAnd]
+
+******************************************************************************/
+static DdNode *
+cuddBddClippingAndRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  int  distance,
+  int  direction)
+{
+    DdNode *F, *ft, *fe, *G, *gt, *ge;
+    DdNode *one, *zero, *r, *t, *e;
+    unsigned int topf, topg, index;
+    DD_CTFP cacheOp;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    /* Terminal cases. */
+    if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
+    if (f == g || g == one) return(f);
+    if (f == one) return(g);
+    if (distance == 0) {
+        /* One last attempt at returning the right result. We sort of
+        ** cheat by calling Cudd_bddLeq. */
+        if (Cudd_bddLeq(manager,f,g)) return(f);
+        if (Cudd_bddLeq(manager,g,f)) return(g);
+        if (direction == 1) {
+            if (Cudd_bddLeq(manager,f,Cudd_Not(g)) ||
+                Cudd_bddLeq(manager,g,Cudd_Not(f))) return(zero);
+        }
+        return(Cudd_NotCond(one,(direction == 0)));
+    }
+
+    /* At this point f and g are not constant. */
+    distance--;
+
+    /* Check cache. Try to increase cache efficiency by sorting the
+    ** pointers. */
+    if (f > g) {
+        DdNode *tmp = f;
+        f = g; g = tmp;
+    }
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    cacheOp = (DD_CTFP)
+        (direction ? Cudd_bddClippingAnd : cuddBddClippingAnd);
+    if (F->ref != 1 || G->ref != 1) {
+        r = cuddCacheLookup2(manager, cacheOp, f, g);
+        if (r != NULL) return(r);
+    }
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    topf = manager->perm[F->index];
+    topg = manager->perm[G->index];
+
+    /* Compute cofactors. */
+    if (topf <= topg) {
+        index = F->index;
+        ft = cuddT(F);
+        fe = cuddE(F);
+        if (Cudd_IsComplement(f)) {
+            ft = Cudd_Not(ft);
+            fe = Cudd_Not(fe);
+        }
+    } else {
+        index = G->index;
+        ft = fe = f;
+    }
+
+    if (topg <= topf) {
+        gt = cuddT(G);
+        ge = cuddE(G);
+        if (Cudd_IsComplement(g)) {
+            gt = Cudd_Not(gt);
+            ge = Cudd_Not(ge);
+        }
+    } else {
+        gt = ge = g;
+    }
+
+    t = cuddBddClippingAndRecur(manager, ft, gt, distance, direction);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+    e = cuddBddClippingAndRecur(manager, fe, ge, distance, direction);
+    if (e == NULL) {
+        Cudd_RecursiveDeref(manager, t);
+        return(NULL);
+    }
+    cuddRef(e);
+
+    if (t == e) {
+        r = t;
+    } else {
+        if (Cudd_IsComplement(t)) {
+            r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
+            if (r == NULL) {
+                Cudd_RecursiveDeref(manager, t);
+                Cudd_RecursiveDeref(manager, e);
+                return(NULL);
+            }
+            r = Cudd_Not(r);
+        } else {
+            r = cuddUniqueInter(manager,(int)index,t,e);
+            if (r == NULL) {
+                Cudd_RecursiveDeref(manager, t);
+                Cudd_RecursiveDeref(manager, e);
+                return(NULL);
+            }
+        }
+    }
+    cuddDeref(e);
+    cuddDeref(t);
+    if (F->ref != 1 || G->ref != 1)
+        cuddCacheInsert2(manager, cacheOp, f, g, r);
+    return(r);
+
+} /* end of cuddBddClippingAndRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis [Approximates the AND of two BDDs and simultaneously abstracts the
+  variables in cube.]
+
+  Description [Approximates the AND of two BDDs and simultaneously
+  abstracts the variables in cube. The variables are existentially
+  abstracted.  Returns a pointer to the result is successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddClippingAndAbstract]
+
+******************************************************************************/
+static DdNode *
+cuddBddClipAndAbsRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  DdNode * cube,
+  int  distance,
+  int  direction)
+{
+    DdNode *F, *ft, *fe, *G, *gt, *ge;
+    DdNode *one, *zero, *r, *t, *e, *Cube;
+    unsigned int topf, topg, topcube, top, index;
+    ptruint cacheTag;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    /* Terminal cases. */
+    if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
+    if (f == one && g == one)   return(one);
+    if (cube == one) {
+        return(cuddBddClippingAndRecur(manager, f, g, distance, direction));
+    }
+    if (f == one || f == g) {
+        return (cuddBddExistAbstractRecur(manager, g, cube));
+    }
+    if (g == one) {
+        return (cuddBddExistAbstractRecur(manager, f, cube));
+    }
+    if (distance == 0) return(Cudd_NotCond(one,(direction == 0)));
+
+    /* At this point f, g, and cube are not constant. */
+    distance--;
+
+    /* Check cache. */
+    if (f > g) { /* Try to increase cache efficiency. */
+        DdNode *tmp = f;
+        f = g; g = tmp;
+    }
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    cacheTag = direction ? DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG :
+        DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG;
+    if (F->ref != 1 || G->ref != 1) {
+        r = cuddCacheLookup(manager, cacheTag,
+                            f, g, cube);
+        if (r != NULL) {
+            return(r);
+        }
+    }
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    topf = manager->perm[F->index];
+    topg = manager->perm[G->index];
+    top = ddMin(topf, topg);
+    topcube = manager->perm[cube->index];
+
+    if (topcube < top) {
+        return(cuddBddClipAndAbsRecur(manager, f, g, cuddT(cube),
+                                      distance, direction));
+    }
+    /* Now, topcube >= top. */
+
+    if (topf == top) {
+        index = F->index;
+        ft = cuddT(F);
+        fe = cuddE(F);
+        if (Cudd_IsComplement(f)) {
+            ft = Cudd_Not(ft);
+            fe = Cudd_Not(fe);
+        }
+    } else {
+        index = G->index;
+        ft = fe = f;
+    }
+
+    if (topg == top) {
+        gt = cuddT(G);
+        ge = cuddE(G);
+        if (Cudd_IsComplement(g)) {
+            gt = Cudd_Not(gt);
+            ge = Cudd_Not(ge);
+        }
+    } else {
+        gt = ge = g;
+    }
+
+    if (topcube == top) {
+        Cube = cuddT(cube);
+    } else {
+        Cube = cube;
+    }
+
+    t = cuddBddClipAndAbsRecur(manager, ft, gt, Cube, distance, direction);
+    if (t == NULL) return(NULL);
+
+    /* Special case: 1 OR anything = 1. Hence, no need to compute
+    ** the else branch if t is 1.
+    */
+    if (t == one && topcube == top) {
+        if (F->ref != 1 || G->ref != 1)
+            cuddCacheInsert(manager, cacheTag, f, g, cube, one);
+        return(one);
+    }
+    cuddRef(t);
+
+    e = cuddBddClipAndAbsRecur(manager, fe, ge, Cube, distance, direction);
+    if (e == NULL) {
+        Cudd_RecursiveDeref(manager, t);
+        return(NULL);
+    }
+    cuddRef(e);
+
+    if (topcube == top) {       /* abstract */
+        r = cuddBddClippingAndRecur(manager, Cudd_Not(t), Cudd_Not(e),
+                                    distance, (direction == 0));
+        if (r == NULL) {
+            Cudd_RecursiveDeref(manager, t);
+            Cudd_RecursiveDeref(manager, e);
+            return(NULL);
+        }
+        r = Cudd_Not(r);
+        cuddRef(r);
+        Cudd_RecursiveDeref(manager, t);
+        Cudd_RecursiveDeref(manager, e);
+        cuddDeref(r);
+    } else if (t == e) {
+        r = t;
+        cuddDeref(t);
+        cuddDeref(e);
+    } else {
+        if (Cudd_IsComplement(t)) {
+            r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
+            if (r == NULL) {
+                Cudd_RecursiveDeref(manager, t);
+                Cudd_RecursiveDeref(manager, e);
+                return(NULL);
+            }
+            r = Cudd_Not(r);
+        } else {
+            r = cuddUniqueInter(manager,(int)index,t,e);
+            if (r == NULL) {
+                Cudd_RecursiveDeref(manager, t);
+                Cudd_RecursiveDeref(manager, e);
+                return(NULL);
+            }
+        }
+        cuddDeref(e);
+        cuddDeref(t);
+    }
+    if (F->ref != 1 || G->ref != 1)
+        cuddCacheInsert(manager, cacheTag, f, g, cube, r);
+    return (r);
+
+} /* end of cuddBddClipAndAbsRecur */
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddCof.c b/abc-build/src/bdd/cudd/cuddCof.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddCof.c
@@ -0,0 +1,335 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddCof.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Cofactoring functions.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_Cofactor()
+                </ul>
+               Internal procedures included in this module:
+                <ul>
+                <li> cuddGetBranches()
+                <li> cuddCheckCube()
+                <li> cuddCofactorRecur()
+                </ul>
+              ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddCof.c,v 1.9 2004/08/13 18:04:47 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the cofactor of f with respect to g.]
+
+  Description [Computes the cofactor of f with respect to g; g must be
+  the BDD or the ADD of a cube. Returns a pointer to the cofactor if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddConstrain Cudd_bddRestrict]
+
+******************************************************************************/
+DdNode *
+Cudd_Cofactor(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res,*zero;
+
+    zero = Cudd_Not(DD_ONE(dd));
+    if (g == zero || g == DD_ZERO(dd)) {
+        (void) fprintf(dd->err,"Cudd_Cofactor: Invalid restriction 1\n");
+        dd->errorCode = CUDD_INVALID_ARG;
+        return(NULL);
+    }
+    do {
+        dd->reordered = 0;
+        res = cuddCofactorRecur(dd,f,g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_Cofactor */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the children of g.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddGetBranches(
+  DdNode * g,
+  DdNode ** g1,
+  DdNode ** g0)
+{
+    DdNode      *G = Cudd_Regular(g);
+
+    *g1 = cuddT(G);
+    *g0 = cuddE(G);
+    if (Cudd_IsComplement(g)) {
+        *g1 = Cudd_Not(*g1);
+        *g0 = Cudd_Not(*g0);
+    }
+
+} /* end of cuddGetBranches */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether g is the BDD of a cube.]
+
+  Description [Checks whether g is the BDD of a cube. Returns 1 in case
+  of success; 0 otherwise. The constant 1 is a valid cube, but all other
+  constant functions cause cuddCheckCube to return 0.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddCheckCube(
+  DdManager * dd,
+  DdNode * g)
+{
+    DdNode *g1,*g0,*one,*zero;
+    
+    one = DD_ONE(dd);
+    if (g == one) return(1);
+    if (Cudd_IsConstant(g)) return(0);
+
+    zero = Cudd_Not(one);
+    cuddGetBranches(g,&g1,&g0);
+
+    if (g0 == zero) {
+        return(cuddCheckCube(dd, g1));
+    }
+    if (g1 == zero) {
+        return(cuddCheckCube(dd, g0));
+    }
+    return(0);
+
+} /* end of cuddCheckCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_Cofactor.]
+
+  Description [Performs the recursive step of Cudd_Cofactor. Returns a
+  pointer to the cofactor if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Cofactor]
+
+******************************************************************************/
+DdNode *
+cuddCofactorRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *one,*zero,*F,*G,*g1,*g0,*f1,*f0,*t,*e,*r;
+    unsigned int topf,topg;
+    int comple;
+
+    statLine(dd);
+    F = Cudd_Regular(f);
+    if (cuddIsConstant(F)) return(f);
+
+    one = DD_ONE(dd);
+
+    /* The invariant g != 0 is true on entry to this procedure and is
+    ** recursively maintained by it. Therefore it suffices to test g
+    ** against one to make sure it is not constant.
+    */
+    if (g == one) return(f);
+    /* From now on, f and g are known not to be constants. */
+
+    comple = f != F;
+    r = cuddCacheLookup2(dd,Cudd_Cofactor,F,g);
+    if (r != NULL) {
+        return(Cudd_NotCond(r,comple));
+    }
+
+    topf = dd->perm[F->index];
+    G = Cudd_Regular(g);
+    topg = dd->perm[G->index];
+
+    /* We take the cofactors of F because we are going to rely on
+    ** the fact that the cofactors of the complement are the complements
+    ** of the cofactors to better utilize the cache. Variable comple
+    ** remembers whether we have to complement the result or not.
+    */
+    if (topf <= topg) {
+        f1 = cuddT(F); f0 = cuddE(F);
+    } else {
+        f1 = f0 = F;
+    }
+    if (topg <= topf) {
+        g1 = cuddT(G); g0 = cuddE(G);
+        if (g != G) { g1 = Cudd_Not(g1); g0 = Cudd_Not(g0); }
+    } else {
+        g1 = g0 = g;
+    }
+
+    zero = Cudd_Not(one);
+    if (topf >= topg) {
+        if (g0 == zero || g0 == DD_ZERO(dd)) {
+            r = cuddCofactorRecur(dd, f1, g1);
+        } else if (g1 == zero || g1 == DD_ZERO(dd)) {
+            r = cuddCofactorRecur(dd, f0, g0);
+        } else {
+            (void) fprintf(dd->out,
+                           "Cudd_Cofactor: Invalid restriction 2\n");
+            dd->errorCode = CUDD_INVALID_ARG;
+            return(NULL);
+        }
+        if (r == NULL) return(NULL);
+    } else /* if (topf < topg) */ {
+        t = cuddCofactorRecur(dd, f1, g);
+        if (t == NULL) return(NULL);
+        cuddRef(t);
+        e = cuddCofactorRecur(dd, f0, g);
+        if (e == NULL) {
+            Cudd_RecursiveDeref(dd, t);
+            return(NULL);
+        }
+        cuddRef(e);
+
+        if (t == e) {
+            r = t;
+        } else if (Cudd_IsComplement(t)) {
+            r = cuddUniqueInter(dd,(int)F->index,Cudd_Not(t),Cudd_Not(e));
+            if (r != NULL)
+                r = Cudd_Not(r);
+        } else {
+            r = cuddUniqueInter(dd,(int)F->index,t,e);
+        }
+        if (r == NULL) {
+            Cudd_RecursiveDeref(dd ,e);
+            Cudd_RecursiveDeref(dd ,t);
+            return(NULL);
+        }
+        cuddDeref(t);
+        cuddDeref(e);
+    }
+
+    cuddCacheInsert2(dd,Cudd_Cofactor,F,g,r);
+
+    return(Cudd_NotCond(r,comple));
+
+} /* end of cuddCofactorRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddCompose.c b/abc-build/src/bdd/cudd/cuddCompose.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddCompose.c
@@ -0,0 +1,1760 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddCompose.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functional composition and variable permutation of DDs.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_bddCompose()
+                <li> Cudd_addCompose()
+                <li> Cudd_addPermute()
+                <li> Cudd_addSwapVariables()
+                <li> Cudd_bddPermute()
+                <li> Cudd_bddVarMap()
+                <li> Cudd_SetVarMap()
+                <li> Cudd_bddSwapVariables()
+                <li> Cudd_bddAdjPermuteX()
+                <li> Cudd_addVectorCompose()
+                <li> Cudd_addGeneralVectorCompose()
+                <li> Cudd_addNonSimCompose()
+                <li> Cudd_bddVectorCompose()
+                </ul>
+               Internal procedures included in this module:
+                <ul>
+                <li> cuddBddComposeRecur()
+                <li> cuddAddComposeRecur()
+                </ul>
+               Static procedures included in this module:
+                <ul>
+                <li> cuddAddPermuteRecur()
+                <li> cuddBddPermuteRecur()
+                <li> cuddBddVarMapRecur()
+                <li> cuddAddVectorComposeRecur()
+                <li> cuddAddGeneralVectorComposeRecur()
+                <li> cuddAddNonSimComposeRecur()
+                <li> cuddBddVectorComposeRecur()
+                <li> ddIsIthAddVar()
+                <li> ddIsIthAddVarPair()
+               </ul>
+  The permutation functions use a local cache because the results to
+  be remembered depend on the permutation being applied.  Since the
+  permutation is just an array, it cannot be stored in the global
+  cache. There are different procedured for BDDs and ADDs. This is
+  because bddPermuteRecur uses cuddBddIteRecur. If this were changed,
+  the procedures could be merged.]
+
+  Author      [Fabio Somenzi and Kavita Ravi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddCompose.c,v 1.45 2004/08/13 18:04:47 fabio Exp $";
+#endif
+
+#ifdef DD_DEBUG
+static int addPermuteRecurHits;
+static int bddPermuteRecurHits;
+static int bddVectorComposeHits;
+static int addVectorComposeHits;
+
+static int addGeneralVectorComposeHits;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * cuddAddPermuteRecur (DdManager *manager, DdHashTable *table, DdNode *node, int *permut);
+static DdNode * cuddBddPermuteRecur (DdManager *manager, DdHashTable *table, DdNode *node, int *permut);
+static DdNode * cuddBddVarMapRecur (DdManager *manager, DdNode *f);
+static DdNode * cuddAddVectorComposeRecur (DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vector, int deepest);
+static DdNode * cuddAddNonSimComposeRecur (DdManager *dd, DdNode *f, DdNode **vector, DdNode *key, DdNode *cube, int lastsub);
+static DdNode * cuddBddVectorComposeRecur (DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vector, int deepest);
+DD_INLINE static int ddIsIthAddVar (DdManager *dd, DdNode *f, unsigned int i);
+
+static DdNode * cuddAddGeneralVectorComposeRecur (DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vectorOn, DdNode **vectorOff, int deepest);
+DD_INLINE static int ddIsIthAddVarPair (DdManager *dd, DdNode *f, DdNode *g, unsigned int i);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Substitutes g for x_v in the BDD for f.]
+
+  Description [Substitutes g for x_v in the BDD for f. v is the index of the
+  variable to be substituted. Cudd_bddCompose passes the corresponding
+  projection function to the recursive procedure, so that the cache may
+  be used.  Returns the composed BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addCompose]
+
+******************************************************************************/
+DdNode *
+Cudd_bddCompose(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  int  v)
+{
+    DdNode *proj, *res;
+
+    /* Sanity check. */
+    if (v < 0 || v >= dd->size) return(NULL);
+
+    proj =  dd->vars[v];
+    do {
+        dd->reordered = 0;
+        res = cuddBddComposeRecur(dd,f,g,proj);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddCompose */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Substitutes g for x_v in the ADD for f.]
+
+  Description [Substitutes g for x_v in the ADD for f. v is the index of the
+  variable to be substituted. g must be a 0-1 ADD. Cudd_bddCompose passes
+  the corresponding projection function to the recursive procedure, so
+  that the cache may be used.  Returns the composed ADD if successful;
+  NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddCompose]
+
+******************************************************************************/
+DdNode *
+Cudd_addCompose(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  int  v)
+{
+    DdNode *proj, *res;
+
+    /* Sanity check. */
+    if (v < 0 || v >= dd->size) return(NULL);
+
+    proj =  dd->vars[v];
+    do {
+        dd->reordered = 0;
+        res = cuddAddComposeRecur(dd,f,g,proj);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addCompose */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Permutes the variables of an ADD.]
+
+  Description [Given a permutation in array permut, creates a new ADD
+  with permuted variables. There should be an entry in array permut
+  for each variable in the manager. The i-th entry of permut holds the
+  index of the variable that is to substitute the i-th
+  variable. Returns a pointer to the resulting ADD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPermute Cudd_addSwapVariables]
+
+******************************************************************************/
+DdNode *
+Cudd_addPermute(
+  DdManager * manager,
+  DdNode * node,
+  int * permut)
+{
+    DdHashTable         *table;
+    DdNode              *res;
+
+    do {
+        manager->reordered = 0;
+        table = cuddHashTableInit(manager,1,2);
+        if (table == NULL) return(NULL);
+        /* Recursively solve the problem. */
+        res = cuddAddPermuteRecur(manager,table,node,permut);
+        if (res != NULL) cuddRef(res);
+        /* Dispose of local cache. */
+        cuddHashTableQuit(table);
+    } while (manager->reordered == 1);
+
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addPermute */
+
+
+/**Function********************************************************************
+
+  Synopsis [Swaps two sets of variables of the same size (x and y) in
+  the ADD f.]
+
+  Description [Swaps two sets of variables of the same size (x and y) in
+  the ADD f.  The size is given by n. The two sets of variables are
+  assumed to be disjoint. Returns a pointer to the resulting ADD if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addPermute Cudd_bddSwapVariables]
+
+******************************************************************************/
+DdNode *
+Cudd_addSwapVariables(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** x,
+  DdNode ** y,
+  int  n)
+{
+    DdNode *swapped;
+    int  i, j, k;
+    int  *permut;
+
+    permut = ABC_ALLOC(int,dd->size);
+    if (permut == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    for (i = 0; i < dd->size; i++) permut[i] = i;
+    for (i = 0; i < n; i++) {
+        j = x[i]->index;
+        k = y[i]->index;
+        permut[j] = k;
+        permut[k] = j;
+    }
+
+    swapped = Cudd_addPermute(dd,f,permut);
+    ABC_FREE(permut);
+
+    return(swapped);
+
+} /* end of Cudd_addSwapVariables */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Permutes the variables of a BDD.]
+
+  Description [Given a permutation in array permut, creates a new BDD
+  with permuted variables. There should be an entry in array permut
+  for each variable in the manager. The i-th entry of permut holds the
+  index of the variable that is to substitute the i-th variable.
+  Returns a pointer to the resulting BDD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addPermute Cudd_bddSwapVariables]
+
+******************************************************************************/
+DdNode *
+Cudd_bddPermute(
+  DdManager * manager,
+  DdNode * node,
+  int * permut)
+{
+    DdHashTable         *table;
+    DdNode              *res;
+
+    do {
+        manager->reordered = 0;
+        table = cuddHashTableInit(manager,1,2);
+        if (table == NULL) return(NULL);
+        res = cuddBddPermuteRecur(manager,table,node,permut);
+        if (res != NULL) cuddRef(res);
+        /* Dispose of local cache. */
+        cuddHashTableQuit(table);
+
+    } while (manager->reordered == 1);
+
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_bddPermute */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Remaps the variables of a BDD using the default variable map.]
+
+  Description [Remaps the variables of a BDD using the default
+  variable map.  A typical use of this function is to swap two sets of
+  variables.  The variable map must be registered with Cudd_SetVarMap.
+  Returns a pointer to the resulting BDD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPermute Cudd_bddSwapVariables Cudd_SetVarMap]
+
+******************************************************************************/
+DdNode *
+Cudd_bddVarMap(
+  DdManager * manager /* DD manager */,
+  DdNode * f /* function in which to remap variables */)
+{
+    DdNode *res;
+
+    if (manager->map == NULL) return(NULL);
+    do {
+        manager->reordered = 0;
+        res = cuddBddVarMapRecur(manager, f);
+    } while (manager->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_bddVarMap */
+
+
+/**Function********************************************************************
+
+  Synopsis [Registers a variable mapping with the manager.]
+
+  Description [Registers with the manager a variable mapping described
+  by two sets of variables.  This variable mapping is then used by
+  functions like Cudd_bddVarMap.  This function is convenient for
+  those applications that perform the same mapping several times.
+  However, if several different permutations are used, it may be more
+  efficient not to rely on the registered mapping, because changing
+  mapping causes the cache to be cleared.  (The initial setting,
+  however, does not clear the cache.) The two sets of variables (x and
+  y) must have the same size (x and y).  The size is given by n. The
+  two sets of variables are normally disjoint, but this restriction is
+  not imposeded by the function. When new variables are created, the
+  map is automatically extended (each new variable maps to
+  itself). The typical use, however, is to wait until all variables
+  are created, and then create the map.  Returns 1 if the mapping is
+  successfully registered with the manager; 0 otherwise.]
+
+  SideEffects [Modifies the manager. May clear the cache.]
+
+  SeeAlso     [Cudd_bddVarMap Cudd_bddPermute Cudd_bddSwapVariables]
+
+******************************************************************************/
+int
+Cudd_SetVarMap (
+  DdManager *manager /* DD manager */,
+  DdNode **x /* first array of variables */,
+  DdNode **y /* second array of variables */,
+  int n /* length of both arrays */)
+{
+    int i;
+
+    if (manager->map != NULL) {
+        cuddCacheFlush(manager);
+    } else {
+        manager->map = ABC_ALLOC(int,manager->maxSize);
+        if (manager->map == NULL) {
+            manager->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        manager->memused += sizeof(int) * manager->maxSize;
+    }
+    /* Initialize the map to the identity. */
+    for (i = 0; i < manager->size; i++) {
+        manager->map[i] = i;
+    }
+    /* Create the map. */
+    for (i = 0; i < n; i++) {
+        manager->map[x[i]->index] = y[i]->index;
+        manager->map[y[i]->index] = x[i]->index;
+    }
+    return(1);
+
+} /* end of Cudd_SetVarMap */
+
+
+/**Function********************************************************************
+
+  Synopsis [Swaps two sets of variables of the same size (x and y) in
+  the BDD f.]
+
+  Description [Swaps two sets of variables of the same size (x and y)
+  in the BDD f. The size is given by n. The two sets of variables are
+  assumed to be disjoint.  Returns a pointer to the resulting BDD if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPermute Cudd_addSwapVariables]
+
+******************************************************************************/
+DdNode *
+Cudd_bddSwapVariables(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** x,
+  DdNode ** y,
+  int  n)
+{
+    DdNode *swapped;
+    int  i, j, k;
+    int  *permut;
+
+    permut = ABC_ALLOC(int,dd->size);
+    if (permut == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    for (i = 0; i < dd->size; i++) permut[i] = i;
+    for (i = 0; i < n; i++) {
+        j = x[i]->index;
+        k = y[i]->index;
+        permut[j] = k;
+        permut[k] = j;
+    }
+
+    swapped = Cudd_bddPermute(dd,f,permut);
+    ABC_FREE(permut);
+
+    return(swapped);
+
+} /* end of Cudd_bddSwapVariables */
+
+
+/**Function********************************************************************
+
+  Synopsis [Rearranges a set of variables in the BDD B.]
+
+  Description [Rearranges a set of variables in the BDD B. The size of
+  the set is given by n. This procedure is intended for the
+  `randomization' of the priority functions. Returns a pointer to the
+  BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPermute Cudd_bddSwapVariables
+  Cudd_Dxygtdxz Cudd_Dxygtdyz Cudd_PrioritySelect]
+
+******************************************************************************/
+DdNode *
+Cudd_bddAdjPermuteX(
+  DdManager * dd,
+  DdNode * B,
+  DdNode ** x,
+  int  n)
+{
+    DdNode *swapped;
+    int  i, j, k;
+    int  *permut;
+
+    permut = ABC_ALLOC(int,dd->size);
+    if (permut == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    for (i = 0; i < dd->size; i++) permut[i] = i;
+    for (i = 0; i < n-2; i += 3) {
+        j = x[i]->index;
+        k = x[i+1]->index;
+        permut[j] = k;
+        permut[k] = j;
+    }
+
+    swapped = Cudd_bddPermute(dd,B,permut);
+    ABC_FREE(permut);
+
+    return(swapped);
+
+} /* end of Cudd_bddAdjPermuteX */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Composes an ADD with a vector of 0-1 ADDs.]
+
+  Description [Given a vector of 0-1 ADDs, creates a new ADD by
+  substituting the 0-1 ADDs for the variables of the ADD f.  There
+  should be an entry in vector for each variable in the manager.
+  If no substitution is sought for a given variable, the corresponding
+  projection function should be specified in the vector.
+  This function implements simultaneous composition.
+  Returns a pointer to the resulting ADD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addNonSimCompose Cudd_addPermute Cudd_addCompose
+  Cudd_bddVectorCompose]
+
+******************************************************************************/
+DdNode *
+Cudd_addVectorCompose(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** vector)
+{
+    DdHashTable         *table;
+    DdNode              *res;
+    int                 deepest;
+    int                 i;
+
+    do {
+        dd->reordered = 0;
+        /* Initialize local cache. */
+        table = cuddHashTableInit(dd,1,2);
+        if (table == NULL) return(NULL);
+
+        /* Find deepest real substitution. */
+        for (deepest = dd->size - 1; deepest >= 0; deepest--) {
+            i = dd->invperm[deepest];
+            if (!ddIsIthAddVar(dd,vector[i],i)) {
+                break;
+            }
+        }
+
+        /* Recursively solve the problem. */
+        res = cuddAddVectorComposeRecur(dd,table,f,vector,deepest);
+        if (res != NULL) cuddRef(res);
+
+        /* Dispose of local cache. */
+        cuddHashTableQuit(table);
+    } while (dd->reordered == 1);
+
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addVectorCompose */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Composes an ADD with a vector of ADDs.]
+
+  Description [Given a vector of ADDs, creates a new ADD by substituting the
+  ADDs for the variables of the ADD f. vectorOn contains ADDs to be substituted
+  for the x_v and vectorOff the ADDs to be substituted for x_v'. There should
+  be an entry in vector for each variable in the manager.  If no substitution
+  is sought for a given variable, the corresponding projection function should
+  be specified in the vector.  This function implements simultaneous
+  composition.  Returns a pointer to the resulting ADD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso [Cudd_addVectorCompose Cudd_addNonSimCompose Cudd_addPermute
+  Cudd_addCompose Cudd_bddVectorCompose]
+
+******************************************************************************/
+DdNode *
+Cudd_addGeneralVectorCompose(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** vectorOn,
+  DdNode ** vectorOff)
+{
+    DdHashTable         *table;
+    DdNode              *res;
+    int                 deepest;
+    int                 i;
+
+    do {
+        dd->reordered = 0;
+        /* Initialize local cache. */
+        table = cuddHashTableInit(dd,1,2);
+        if (table == NULL) return(NULL);
+
+        /* Find deepest real substitution. */
+        for (deepest = dd->size - 1; deepest >= 0; deepest--) {
+            i = dd->invperm[deepest];
+            if (!ddIsIthAddVarPair(dd,vectorOn[i],vectorOff[i],i)) {
+                break;
+            }
+        }
+
+        /* Recursively solve the problem. */
+        res = cuddAddGeneralVectorComposeRecur(dd,table,f,vectorOn,
+                                               vectorOff,deepest);
+        if (res != NULL) cuddRef(res);
+
+        /* Dispose of local cache. */
+        cuddHashTableQuit(table);
+    } while (dd->reordered == 1);
+
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addGeneralVectorCompose */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Composes an ADD with a vector of 0-1 ADDs.]
+
+  Description [Given a vector of 0-1 ADDs, creates a new ADD by
+  substituting the 0-1 ADDs for the variables of the ADD f.  There
+  should be an entry in vector for each variable in the manager.
+  This function implements non-simultaneous composition. If any of the
+  functions being composed depends on any of the variables being
+  substituted, then the result depends on the order of composition,
+  which in turn depends on the variable order: The variables farther from
+  the roots in the order are substituted first.
+  Returns a pointer to the resulting ADD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addVectorCompose Cudd_addPermute Cudd_addCompose]
+
+******************************************************************************/
+DdNode *
+Cudd_addNonSimCompose(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** vector)
+{
+    DdNode              *cube, *key, *var, *tmp, *piece;
+    DdNode              *res;
+    int                 i, lastsub;
+
+    /* The cache entry for this function is composed of three parts:
+    ** f itself, the replacement relation, and the cube of the
+    ** variables being substituted.
+    ** The replacement relation is the product of the terms (yi EXNOR gi).
+    ** This apporach allows us to use the global cache for this function,
+    ** with great savings in memory with respect to using arrays for the
+    ** cache entries.
+    ** First we build replacement relation and cube of substituted
+    ** variables from the vector specifying the desired composition.
+    */
+    key = DD_ONE(dd);
+    cuddRef(key);
+    cube = DD_ONE(dd);
+    cuddRef(cube);
+    for (i = (int) dd->size - 1; i >= 0; i--) {
+        if (ddIsIthAddVar(dd,vector[i],(unsigned int)i)) {
+            continue;
+        }
+        var = Cudd_addIthVar(dd,i);
+        if (var == NULL) {
+            Cudd_RecursiveDeref(dd,key);
+            Cudd_RecursiveDeref(dd,cube);
+            return(NULL);
+        }
+        cuddRef(var);
+        /* Update cube. */
+        tmp = Cudd_addApply(dd,Cudd_addTimes,var,cube);
+        if (tmp == NULL) {
+            Cudd_RecursiveDeref(dd,key);
+            Cudd_RecursiveDeref(dd,cube);
+            Cudd_RecursiveDeref(dd,var);
+            return(NULL);
+        }
+        cuddRef(tmp);
+        Cudd_RecursiveDeref(dd,cube);
+        cube = tmp;
+        /* Update replacement relation. */
+        piece = Cudd_addApply(dd,Cudd_addXnor,var,vector[i]);
+        if (piece == NULL) {
+            Cudd_RecursiveDeref(dd,key);
+            Cudd_RecursiveDeref(dd,var);
+            return(NULL);
+        }
+        cuddRef(piece);
+        Cudd_RecursiveDeref(dd,var);
+        tmp = Cudd_addApply(dd,Cudd_addTimes,key,piece);
+        if (tmp == NULL) {
+            Cudd_RecursiveDeref(dd,key);
+            Cudd_RecursiveDeref(dd,piece);
+            return(NULL);
+        }
+        cuddRef(tmp);
+        Cudd_RecursiveDeref(dd,key);
+        Cudd_RecursiveDeref(dd,piece);
+        key = tmp;
+    }
+
+    /* Now try composition, until no reordering occurs. */
+    do {
+        /* Find real substitution with largest index. */
+        for (lastsub = dd->size - 1; lastsub >= 0; lastsub--) {
+            if (!ddIsIthAddVar(dd,vector[lastsub],(unsigned int)lastsub)) {
+                break;
+            }
+        }
+
+        /* Recursively solve the problem. */
+        dd->reordered = 0;
+        res = cuddAddNonSimComposeRecur(dd,f,vector,key,cube,lastsub+1);
+        if (res != NULL) cuddRef(res);
+
+    } while (dd->reordered == 1);
+
+    Cudd_RecursiveDeref(dd,key);
+    Cudd_RecursiveDeref(dd,cube);
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addNonSimCompose */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Composes a BDD with a vector of BDDs.]
+
+  Description [Given a vector of BDDs, creates a new BDD by
+  substituting the BDDs for the variables of the BDD f.  There
+  should be an entry in vector for each variable in the manager.
+  If no substitution is sought for a given variable, the corresponding
+  projection function should be specified in the vector.
+  This function implements simultaneous composition.
+  Returns a pointer to the resulting BDD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPermute Cudd_bddCompose Cudd_addVectorCompose]
+
+******************************************************************************/
+DdNode *
+Cudd_bddVectorCompose(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** vector)
+{
+    DdHashTable         *table;
+    DdNode              *res;
+    int                 deepest;
+    int                 i;
+
+    do {
+        dd->reordered = 0;
+        /* Initialize local cache. */
+        table = cuddHashTableInit(dd,1,2);
+        if (table == NULL) return(NULL);
+
+        /* Find deepest real substitution. */
+        for (deepest = dd->size - 1; deepest >= 0; deepest--) {
+            i = dd->invperm[deepest];
+            if (vector[i] != dd->vars[i]) {
+                break;
+            }
+        }
+
+        /* Recursively solve the problem. */
+        res = cuddBddVectorComposeRecur(dd,table,f,vector, deepest);
+        if (res != NULL) cuddRef(res);
+
+        /* Dispose of local cache. */
+        cuddHashTableQuit(table);
+    } while (dd->reordered == 1);
+
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_bddVectorCompose */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddCompose.]
+
+  Description [Performs the recursive step of Cudd_bddCompose.
+  Exploits the fact that the composition of f' with g
+  produces the complement of the composition of f with g to better
+  utilize the cache.  Returns the composed BDD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddCompose]
+
+******************************************************************************/
+DdNode *
+cuddBddComposeRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * proj)
+{
+    DdNode      *F, *G, *f1, *f0, *g1, *g0, *r, *t, *e;
+    unsigned int v, topf, topg, topindex;
+    int         comple;
+
+    statLine(dd);
+    v = dd->perm[proj->index];
+    F = Cudd_Regular(f);
+    topf = cuddI(dd,F->index);
+
+    /* Terminal case. Subsumes the test for constant f. */
+    if (topf > v) return(f);
+
+    /* We solve the problem for a regular pointer, and then complement
+    ** the result if the pointer was originally complemented.
+    */
+    comple = Cudd_IsComplement(f);
+
+    /* Check cache. */
+    r = cuddCacheLookup(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj);
+    if (r != NULL) {
+        return(Cudd_NotCond(r,comple));
+    }
+
+    if (topf == v) {
+        /* Compose. */
+        f1 = cuddT(F);
+        f0 = cuddE(F);
+        r = cuddBddIteRecur(dd, g, f1, f0);
+        if (r == NULL) return(NULL);
+    } else {
+        /* Compute cofactors of f and g. Remember the index of the top
+        ** variable.
+        */
+        G = Cudd_Regular(g);
+        topg = cuddI(dd,G->index);
+        if (topf > topg) {
+            topindex = G->index;
+            f1 = f0 = F;
+        } else {
+            topindex = F->index;
+            f1 = cuddT(F);
+            f0 = cuddE(F);
+        }
+        if (topg > topf) {
+            g1 = g0 = g;
+        } else {
+            g1 = cuddT(G);
+            g0 = cuddE(G);
+            if (g != G) {
+                g1 = Cudd_Not(g1);
+                g0 = Cudd_Not(g0);
+            }
+        }
+        /* Recursive step. */
+        t = cuddBddComposeRecur(dd, f1, g1, proj);
+        if (t == NULL) return(NULL);
+        cuddRef(t);
+        e = cuddBddComposeRecur(dd, f0, g0, proj);
+        if (e == NULL) {
+            Cudd_IterDerefBdd(dd, t);
+            return(NULL);
+        }
+        cuddRef(e);
+
+        r = cuddBddIteRecur(dd, dd->vars[topindex], t, e);
+        if (r == NULL) {
+            Cudd_IterDerefBdd(dd, t);
+            Cudd_IterDerefBdd(dd, e);
+            return(NULL);
+        }
+        cuddRef(r);
+        Cudd_IterDerefBdd(dd, t); /* t & e not necessarily part of r */
+        Cudd_IterDerefBdd(dd, e);
+        cuddDeref(r);
+    }
+
+    cuddCacheInsert(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj,r);
+
+    return(Cudd_NotCond(r,comple));
+
+} /* end of cuddBddComposeRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addCompose.]
+
+  Description [Performs the recursive step of Cudd_addCompose.
+  Returns the composed BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addCompose]
+
+******************************************************************************/
+DdNode *
+cuddAddComposeRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * proj)
+{
+    DdNode *f1, *f0, *g1, *g0, *r, *t, *e;
+    unsigned int v, topf, topg, topindex;
+
+    statLine(dd);
+    v = dd->perm[proj->index];
+    topf = cuddI(dd,f->index);
+
+    /* Terminal case. Subsumes the test for constant f. */
+    if (topf > v) return(f);
+
+    /* Check cache. */
+    r = cuddCacheLookup(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj);
+    if (r != NULL) {
+        return(r);
+    }
+
+    if (topf == v) {
+        /* Compose. */
+        f1 = cuddT(f);
+        f0 = cuddE(f);
+        r = cuddAddIteRecur(dd, g, f1, f0);
+        if (r == NULL) return(NULL);
+    } else {
+        /* Compute cofactors of f and g. Remember the index of the top
+        ** variable.
+        */
+        topg = cuddI(dd,g->index);
+        if (topf > topg) {
+            topindex = g->index;
+            f1 = f0 = f;
+        } else {
+            topindex = f->index;
+            f1 = cuddT(f);
+            f0 = cuddE(f);
+        }
+        if (topg > topf) {
+            g1 = g0 = g;
+        } else {
+            g1 = cuddT(g);
+            g0 = cuddE(g);
+        }
+        /* Recursive step. */
+        t = cuddAddComposeRecur(dd, f1, g1, proj);
+        if (t == NULL) return(NULL);
+        cuddRef(t);
+        e = cuddAddComposeRecur(dd, f0, g0, proj);
+        if (e == NULL) {
+            Cudd_RecursiveDeref(dd, t);
+            return(NULL);
+        }
+        cuddRef(e);
+
+        if (t == e) {
+            r = t;
+        } else {
+            r = cuddUniqueInter(dd, (int) topindex, t, e);
+            if (r == NULL) {
+                Cudd_RecursiveDeref(dd, t);
+                Cudd_RecursiveDeref(dd, e);
+                return(NULL);
+            }
+        }
+        cuddDeref(t);
+        cuddDeref(e);
+    }
+
+    cuddCacheInsert(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj,r);
+
+    return(r);
+
+} /* end of cuddAddComposeRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_addPermute.]
+
+  Description [ Recursively puts the ADD in the order given in the
+  array permut. Checks for trivial cases to terminate recursion, then
+  splits on the children of this node.  Once the solutions for the
+  children are obtained, it puts into the current position the node
+  from the rest of the ADD that should be here. Then returns this ADD.
+  The key here is that the node being visited is NOT put in its proper
+  place by this instance, but rather is switched when its proper
+  position is reached in the recursion tree.<p>
+  The DdNode * that is returned is the same ADD as passed in as node,
+  but in the new order.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addPermute cuddBddPermuteRecur]
+
+******************************************************************************/
+static DdNode *
+cuddAddPermuteRecur(
+  DdManager * manager /* DD manager */,
+  DdHashTable * table /* computed table */,
+  DdNode * node /* ADD to be reordered */,
+  int * permut /* permutation array */)
+{
+    DdNode      *T,*E;
+    DdNode      *res,*var;
+    int         index;
+    
+    statLine(manager);
+    /* Check for terminal case of constant node. */
+    if (cuddIsConstant(node)) {
+        return(node);
+    }
+
+    /* If problem already solved, look up answer and return. */
+    if (node->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) {
+#ifdef DD_DEBUG
+        addPermuteRecurHits++;
+#endif
+        return(res);
+    }
+
+    /* Split and recur on children of this node. */
+    T = cuddAddPermuteRecur(manager,table,cuddT(node),permut);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+    E = cuddAddPermuteRecur(manager,table,cuddE(node),permut);
+    if (E == NULL) {
+        Cudd_RecursiveDeref(manager, T);
+        return(NULL);
+    }
+    cuddRef(E);
+
+    /* Move variable that should be in this position to this position
+    ** by creating a single var ADD for that variable, and calling
+    ** cuddAddIteRecur with the T and E we just created.
+    */
+    index = permut[node->index];
+    var = cuddUniqueInter(manager,index,DD_ONE(manager),DD_ZERO(manager));
+    if (var == NULL) return(NULL);
+    cuddRef(var);
+    res = cuddAddIteRecur(manager,var,T,E);
+    if (res == NULL) {
+        Cudd_RecursiveDeref(manager,var);
+        Cudd_RecursiveDeref(manager, T);
+        Cudd_RecursiveDeref(manager, E);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(manager,var);
+    Cudd_RecursiveDeref(manager, T);
+    Cudd_RecursiveDeref(manager, E);
+
+    /* Do not keep the result if the reference count is only 1, since
+    ** it will not be visited again.
+    */
+    if (node->ref != 1) {
+        ptrint fanout = (ptrint) node->ref;
+        cuddSatDec(fanout);
+        if (!cuddHashTableInsert1(table,node,res,fanout)) {
+            Cudd_RecursiveDeref(manager, res);
+            return(NULL);
+        }
+    }
+    cuddDeref(res);
+    return(res);
+
+} /* end of cuddAddPermuteRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_bddPermute.]
+
+  Description [ Recursively puts the BDD in the order given in the array permut.
+  Checks for trivial cases to terminate recursion, then splits on the
+  children of this node.  Once the solutions for the children are
+  obtained, it puts into the current position the node from the rest of
+  the BDD that should be here. Then returns this BDD.
+  The key here is that the node being visited is NOT put in its proper
+  place by this instance, but rather is switched when its proper position
+  is reached in the recursion tree.<p>
+  The DdNode * that is returned is the same BDD as passed in as node,
+  but in the new order.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPermute cuddAddPermuteRecur]
+
+******************************************************************************/
+static DdNode *
+cuddBddPermuteRecur(
+  DdManager * manager /* DD manager */,
+  DdHashTable * table /* computed table */,
+  DdNode * node /* BDD to be reordered */,
+  int * permut /* permutation array */)
+{
+    DdNode      *N,*T,*E;
+    DdNode      *res;
+    int         index;
+
+    statLine(manager);
+    N = Cudd_Regular(node);
+
+    /* Check for terminal case of constant node. */
+    if (cuddIsConstant(N)) {
+        return(node);
+    }
+
+    /* If problem already solved, look up answer and return. */
+    if (N->ref != 1 && (res = cuddHashTableLookup1(table,N)) != NULL) {
+#ifdef DD_DEBUG
+        bddPermuteRecurHits++;
+#endif
+        return(Cudd_NotCond(res,N != node));
+    }
+
+    /* Split and recur on children of this node. */
+    T = cuddBddPermuteRecur(manager,table,cuddT(N),permut);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+    E = cuddBddPermuteRecur(manager,table,cuddE(N),permut);
+    if (E == NULL) {
+        Cudd_IterDerefBdd(manager, T);
+        return(NULL);
+    }
+    cuddRef(E);
+
+    /* Move variable that should be in this position to this position
+    ** by retrieving the single var BDD for that variable, and calling
+    ** cuddBddIteRecur with the T and E we just created.
+    */
+    index = permut[N->index];
+    res = cuddBddIteRecur(manager,manager->vars[index],T,E);
+    if (res == NULL) {
+        Cudd_IterDerefBdd(manager, T);
+        Cudd_IterDerefBdd(manager, E);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_IterDerefBdd(manager, T);
+    Cudd_IterDerefBdd(manager, E);
+
+    /* Do not keep the result if the reference count is only 1, since
+    ** it will not be visited again.
+    */
+    if (N->ref != 1) {
+        ptrint fanout = (ptrint) N->ref;
+        cuddSatDec(fanout);
+        if (!cuddHashTableInsert1(table,N,res,fanout)) {
+            Cudd_IterDerefBdd(manager, res);
+            return(NULL);
+        }
+    }
+    cuddDeref(res);
+    return(Cudd_NotCond(res,N != node));
+
+} /* end of cuddBddPermuteRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_bddVarMap.]
+
+  Description [Implements the recursive step of Cudd_bddVarMap.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddVarMap]
+
+******************************************************************************/
+static DdNode *
+cuddBddVarMapRecur(
+  DdManager *manager /* DD manager */,
+  DdNode *f /* BDD to be remapped */)
+{
+    DdNode      *F, *T, *E;
+    DdNode      *res;
+    int         index;
+
+    statLine(manager);
+    F = Cudd_Regular(f);
+
+    /* Check for terminal case of constant node. */
+    if (cuddIsConstant(F)) {
+        return(f);
+    }
+
+    /* If problem already solved, look up answer and return. */
+    if (F->ref != 1 &&
+        (res = cuddCacheLookup1(manager,Cudd_bddVarMap,F)) != NULL) {
+        return(Cudd_NotCond(res,F != f));
+    }
+
+    if ( manager->TimeStop && Abc_Clock() > manager->TimeStop )
+        return NULL;
+
+    /* Split and recur on children of this node. */
+    T = cuddBddVarMapRecur(manager,cuddT(F));
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+    E = cuddBddVarMapRecur(manager,cuddE(F));
+    if (E == NULL) {
+        Cudd_IterDerefBdd(manager, T);
+        return(NULL);
+    }
+    cuddRef(E);
+
+    /* Move variable that should be in this position to this position
+    ** by retrieving the single var BDD for that variable, and calling
+    ** cuddBddIteRecur with the T and E we just created.
+    */
+    index = manager->map[F->index];
+    res = cuddBddIteRecur(manager,manager->vars[index],T,E);
+    if (res == NULL) {
+        Cudd_IterDerefBdd(manager, T);
+        Cudd_IterDerefBdd(manager, E);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_IterDerefBdd(manager, T);
+    Cudd_IterDerefBdd(manager, E);
+
+    /* Do not keep the result if the reference count is only 1, since
+    ** it will not be visited again.
+    */
+    if (F->ref != 1) {
+        cuddCacheInsert1(manager,Cudd_bddVarMap,F,res);
+    }
+    cuddDeref(res);
+    return(Cudd_NotCond(res,F != f));
+
+} /* end of cuddBddVarMapRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addVectorCompose.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+cuddAddVectorComposeRecur(
+  DdManager * dd /* DD manager */,
+  DdHashTable * table /* computed table */,
+  DdNode * f /* ADD in which to compose */,
+  DdNode ** vector /* functions to substitute */,
+  int  deepest /* depth of deepest substitution */)
+{
+    DdNode      *T,*E;
+    DdNode      *res;
+
+    statLine(dd);
+    /* If we are past the deepest substitution, return f. */
+    if (cuddI(dd,f->index) > deepest) {
+        return(f);
+    }
+
+    if ((res = cuddHashTableLookup1(table,f)) != NULL) {
+#ifdef DD_DEBUG
+        addVectorComposeHits++;
+#endif
+        return(res);
+    }
+
+    /* Split and recur on children of this node. */
+    T = cuddAddVectorComposeRecur(dd,table,cuddT(f),vector,deepest);
+    if (T == NULL)  return(NULL);
+    cuddRef(T);
+    E = cuddAddVectorComposeRecur(dd,table,cuddE(f),vector,deepest);
+    if (E == NULL) {
+        Cudd_RecursiveDeref(dd, T);
+        return(NULL);
+    }
+    cuddRef(E);
+
+    /* Retrieve the 0-1 ADD for the current top variable and call
+    ** cuddAddIteRecur with the T and E we just created.
+    */
+    res = cuddAddIteRecur(dd,vector[f->index],T,E);
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd, T);
+        Cudd_RecursiveDeref(dd, E);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd, T);
+    Cudd_RecursiveDeref(dd, E);
+
+    /* Do not keep the result if the reference count is only 1, since
+    ** it will not be visited again
+    */
+    if (f->ref != 1) {
+        ptrint fanout = (ptrint) f->ref;
+        cuddSatDec(fanout);
+        if (!cuddHashTableInsert1(table,f,res,fanout)) {
+            Cudd_RecursiveDeref(dd, res);
+            return(NULL);
+        }
+    }
+    cuddDeref(res);
+    return(res);
+
+} /* end of cuddAddVectorComposeRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addGeneralVectorCompose.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+cuddAddGeneralVectorComposeRecur(
+  DdManager * dd /* DD manager */,
+  DdHashTable * table /* computed table */,
+  DdNode * f /* ADD in which to compose */,
+  DdNode ** vectorOn /* functions to substitute for x_i */,
+  DdNode ** vectorOff /* functions to substitute for x_i' */,
+  int  deepest /* depth of deepest substitution */)
+{
+    DdNode      *T,*E,*t,*e;
+    DdNode      *res;
+
+    /* If we are past the deepest substitution, return f. */
+    if (cuddI(dd,f->index) > deepest) {
+        return(f);
+    }
+
+    if ((res = cuddHashTableLookup1(table,f)) != NULL) {
+#ifdef DD_DEBUG
+        addGeneralVectorComposeHits++;
+#endif
+        return(res);
+    }
+
+    /* Split and recur on children of this node. */
+    T = cuddAddGeneralVectorComposeRecur(dd,table,cuddT(f),
+                                         vectorOn,vectorOff,deepest);
+    if (T == NULL)  return(NULL);
+    cuddRef(T);
+    E = cuddAddGeneralVectorComposeRecur(dd,table,cuddE(f),
+                                         vectorOn,vectorOff,deepest);
+    if (E == NULL) {
+        Cudd_RecursiveDeref(dd, T);
+        return(NULL);
+    }
+    cuddRef(E);
+
+    /* Retrieve the compose ADDs for the current top variable and call
+    ** cuddAddApplyRecur with the T and E we just created.
+    */
+    t = cuddAddApplyRecur(dd,Cudd_addTimes,vectorOn[f->index],T);
+    if (t == NULL) {
+      Cudd_RecursiveDeref(dd,T);
+      Cudd_RecursiveDeref(dd,E);
+      return(NULL);
+    }
+    cuddRef(t);
+    e = cuddAddApplyRecur(dd,Cudd_addTimes,vectorOff[f->index],E);
+    if (e == NULL) {
+      Cudd_RecursiveDeref(dd,T);
+      Cudd_RecursiveDeref(dd,E);
+      Cudd_RecursiveDeref(dd,t);
+      return(NULL);
+    }
+    cuddRef(e);
+    res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e);
+    if (res == NULL) {
+      Cudd_RecursiveDeref(dd,T);
+      Cudd_RecursiveDeref(dd,E);
+      Cudd_RecursiveDeref(dd,t);
+      Cudd_RecursiveDeref(dd,e);
+      return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd,T);
+    Cudd_RecursiveDeref(dd,E);
+    Cudd_RecursiveDeref(dd,t);
+    Cudd_RecursiveDeref(dd,e);
+
+    /* Do not keep the result if the reference count is only 1, since
+    ** it will not be visited again
+    */
+    if (f->ref != 1) {
+        ptrint fanout = (ptrint) f->ref;
+        cuddSatDec(fanout);
+        if (!cuddHashTableInsert1(table,f,res,fanout)) {
+            Cudd_RecursiveDeref(dd, res);
+            return(NULL);
+        }
+    }
+    cuddDeref(res);
+    return(res);
+
+} /* end of cuddAddGeneralVectorComposeRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addNonSimCompose.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+cuddAddNonSimComposeRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** vector,
+  DdNode * key,
+  DdNode * cube,
+  int  lastsub)
+{
+    DdNode *f1, *f0, *key1, *key0, *cube1, *var;
+    DdNode *T,*E;
+    DdNode *r;
+    unsigned int top, topf, topk, topc;
+    unsigned int index;
+    int i;
+    DdNode **vect1;
+    DdNode **vect0;
+
+    statLine(dd);
+    /* If we are past the deepest substitution, return f. */
+    if (cube == DD_ONE(dd) || cuddIsConstant(f)) {
+        return(f);
+    }
+
+    /* If problem already solved, look up answer and return. */
+    r = cuddCacheLookup(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube);
+    if (r != NULL) {
+        return(r);
+    }
+
+    /* Find top variable. we just need to look at f, key, and cube,
+    ** because all the varibles in the gi are in key.
+    */
+    topf = cuddI(dd,f->index);
+    topk = cuddI(dd,key->index);
+    top = ddMin(topf,topk);
+    topc = cuddI(dd,cube->index);
+    top = ddMin(top,topc);
+    index = dd->invperm[top];
+
+    /* Compute the cofactors. */
+    if (topf == top) {
+        f1 = cuddT(f);
+        f0 = cuddE(f);
+    } else {
+        f1 = f0 = f;
+    }
+    if (topc == top) {
+        cube1 = cuddT(cube);
+        /* We want to eliminate vector[index] from key. Otherwise
+        ** cache performance is severely affected. Hence we
+        ** existentially quantify the variable with index "index" from key.
+        */
+        var = Cudd_addIthVar(dd, (int) index);
+        if (var == NULL) {
+            return(NULL);
+        }
+        cuddRef(var);
+        key1 = cuddAddExistAbstractRecur(dd, key, var);
+        if (key1 == NULL) {
+            Cudd_RecursiveDeref(dd,var);
+            return(NULL);
+        }
+        cuddRef(key1);
+        Cudd_RecursiveDeref(dd,var);
+        key0 = key1;
+    } else {
+        cube1 = cube;
+        if (topk == top) {
+            key1 = cuddT(key);
+            key0 = cuddE(key);
+        } else {
+            key1 = key0 = key;
+        }
+        cuddRef(key1);
+    }
+
+    /* Allocate two new vectors for the cofactors of vector. */
+    vect1 = ABC_ALLOC(DdNode *,lastsub);
+    if (vect1 == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        Cudd_RecursiveDeref(dd,key1);
+        return(NULL);
+    }
+    vect0 = ABC_ALLOC(DdNode *,lastsub);
+    if (vect0 == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        Cudd_RecursiveDeref(dd,key1);
+        ABC_FREE(vect1);
+        return(NULL);
+    }
+
+    /* Cofactor the gi. Eliminate vect1[index] and vect0[index], because
+    ** we do not need them.
+    */
+    for (i = 0; i < lastsub; i++) {
+        DdNode *gi = vector[i];
+        if (gi == NULL) {
+            vect1[i] = vect0[i] = NULL;
+        } else if (gi->index == index) {
+            vect1[i] = cuddT(gi);
+            vect0[i] = cuddE(gi);
+        } else {
+            vect1[i] = vect0[i] = gi;
+        }
+    }
+    vect1[index] = vect0[index] = NULL;
+
+    /* Recur on children. */
+    T = cuddAddNonSimComposeRecur(dd,f1,vect1,key1,cube1,lastsub);
+    ABC_FREE(vect1);
+    if (T == NULL) {
+        Cudd_RecursiveDeref(dd,key1);
+        ABC_FREE(vect0);
+        return(NULL);
+    }
+    cuddRef(T);
+    E = cuddAddNonSimComposeRecur(dd,f0,vect0,key0,cube1,lastsub);
+    ABC_FREE(vect0);
+    if (E == NULL) {
+        Cudd_RecursiveDeref(dd,key1);
+        Cudd_RecursiveDeref(dd,T);
+        return(NULL);
+    }
+    cuddRef(E);
+    Cudd_RecursiveDeref(dd,key1);
+
+    /* Retrieve the 0-1 ADD for the current top variable from vector,
+    ** and call cuddAddIteRecur with the T and E we just created.
+    */
+    r = cuddAddIteRecur(dd,vector[index],T,E);
+    if (r == NULL) {
+        Cudd_RecursiveDeref(dd,T);
+        Cudd_RecursiveDeref(dd,E);
+        return(NULL);
+    }
+    cuddRef(r);
+    Cudd_RecursiveDeref(dd,T);
+    Cudd_RecursiveDeref(dd,E);
+    cuddDeref(r);
+
+    /* Store answer to trim recursion. */
+    cuddCacheInsert(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube,r);
+
+    return(r);
+
+} /* end of cuddAddNonSimComposeRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddVectorCompose.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+cuddBddVectorComposeRecur(
+  DdManager * dd /* DD manager */,
+  DdHashTable * table /* computed table */,
+  DdNode * f /* BDD in which to compose */,
+  DdNode ** vector /* functions to be composed */,
+  int deepest /* depth of the deepest substitution */)
+{
+    DdNode      *F,*T,*E;
+    DdNode      *res;
+
+    statLine(dd);
+    F = Cudd_Regular(f);
+
+    /* If we are past the deepest substitution, return f. */
+    if (cuddI(dd,F->index) > deepest) {
+        return(f);
+    }
+
+    /* If problem already solved, look up answer and return. */
+    if ((res = cuddHashTableLookup1(table,F)) != NULL) {
+#ifdef DD_DEBUG
+        bddVectorComposeHits++;
+#endif
+        return(Cudd_NotCond(res,F != f));
+    }
+
+    /* Split and recur on children of this node. */
+    T = cuddBddVectorComposeRecur(dd,table,cuddT(F),vector, deepest);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+    E = cuddBddVectorComposeRecur(dd,table,cuddE(F),vector, deepest);
+    if (E == NULL) {
+        Cudd_IterDerefBdd(dd, T);
+        return(NULL);
+    }
+    cuddRef(E);
+
+    /* Call cuddBddIteRecur with the BDD that replaces the current top
+    ** variable and the T and E we just created.
+    */
+    res = cuddBddIteRecur(dd,vector[F->index],T,E);
+    if (res == NULL) {
+        Cudd_IterDerefBdd(dd, T);
+        Cudd_IterDerefBdd(dd, E);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_IterDerefBdd(dd, T);
+    Cudd_IterDerefBdd(dd, E);   
+
+    /* Do not keep the result if the reference count is only 1, since
+    ** it will not be visited again.
+    */
+    if (F->ref != 1) {
+        ptrint fanout = (ptrint) F->ref;
+        cuddSatDec(fanout);
+        if (!cuddHashTableInsert1(table,F,res,fanout)) {
+            Cudd_IterDerefBdd(dd, res);
+            return(NULL);
+        }
+    }
+    cuddDeref(res);
+    return(Cudd_NotCond(res,F != f));
+
+} /* end of cuddBddVectorComposeRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison of a function to the i-th ADD variable.]
+
+  Description [Comparison of a function to the i-th ADD variable. Returns 1 if
+  the function is the i-th ADD variable; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DD_INLINE
+static int
+ddIsIthAddVar(
+  DdManager * dd,
+  DdNode * f,
+  unsigned int  i)
+{
+    return(f->index == i && cuddT(f) == DD_ONE(dd) && cuddE(f) == DD_ZERO(dd));
+
+} /* end of ddIsIthAddVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison of a pair of functions to the i-th ADD variable.]
+
+  Description [Comparison of a pair of functions to the i-th ADD
+  variable. Returns 1 if the functions are the i-th ADD variable and its
+  complement; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DD_INLINE
+static int
+ddIsIthAddVarPair(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  unsigned int  i)
+{
+    return(f->index == i && g->index == i && 
+           cuddT(f) == DD_ONE(dd) && cuddE(f) == DD_ZERO(dd) &&
+           cuddT(g) == DD_ZERO(dd) && cuddE(g) == DD_ONE(dd));
+
+} /* end of ddIsIthAddVarPair */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddDecomp.c b/abc-build/src/bdd/cudd/cuddDecomp.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddDecomp.c
@@ -0,0 +1,2185 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddDecomp.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for BDD decomposition.]
+
+  Description [External procedures included in this file:
+                <ul>
+                <li> Cudd_bddApproxConjDecomp()
+                <li> Cudd_bddApproxDisjDecomp()
+                <li> Cudd_bddIterConjDecomp()
+                <li> Cudd_bddIterDisjDecomp()
+                <li> Cudd_bddGenConjDecomp()
+                <li> Cudd_bddGenDisjDecomp()
+                <li> Cudd_bddVarConjDecomp()
+                <li> Cudd_bddVarDisjDecomp()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> cuddConjunctsAux()
+                <li> CreateBotDist()
+                <li> BuildConjuncts()
+                <li> ConjunctsFree()
+                </ul>]
+
+  Author      [Kavita Ravi, Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define DEPTH 5
+#define THRESHOLD 10
+#define NONE 0
+#define PAIR_ST 1
+#define PAIR_CR 2
+#define G_ST 3
+#define G_CR 4
+#define H_ST 5
+#define H_CR 6
+#define BOTH_G 7
+#define BOTH_H 8
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct Conjuncts {
+    DdNode *g;
+    DdNode *h;
+} Conjuncts;
+
+typedef struct  NodeStat {
+    int distance;
+    int localRef;
+} NodeStat;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddDecomp.c,v 1.44 2004/08/13 18:04:47 fabio Exp $";
+#endif
+
+static  DdNode  *one, *zero;
+long lastTimeG;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+#define FactorsNotStored(factors)  ((int)((long)(factors) & 01))
+
+#define FactorsComplement(factors) ((Conjuncts *)((long)(factors) | 01))
+
+#define FactorsUncomplement(factors) ((Conjuncts *)((long)(factors) ^ 01))
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static NodeStat * CreateBotDist (DdNode * node, st__table * distanceTable);
+static double CountMinterms (DdNode * node, double max, st__table * mintermTable, FILE *fp);
+static void ConjunctsFree (DdManager * dd, Conjuncts * factors);
+static int PairInTables (DdNode * g, DdNode * h, st__table * ghTable);
+static Conjuncts * CheckTablesCacheAndReturn (DdNode * node, DdNode * g, DdNode * h, st__table * ghTable, st__table * cacheTable);
+static Conjuncts * PickOnePair (DdNode * node, DdNode * g1, DdNode * h1, DdNode * g2, DdNode * h2, st__table * ghTable, st__table * cacheTable);
+static Conjuncts * CheckInTables (DdNode * node, DdNode * g1, DdNode * h1, DdNode * g2, DdNode * h2, st__table * ghTable, st__table * cacheTable, int * outOfMem);
+static Conjuncts * ZeroCase (DdManager * dd, DdNode * node, Conjuncts * factorsNv, st__table * ghTable, st__table * cacheTable, int switched);
+static Conjuncts * BuildConjuncts (DdManager * dd, DdNode * node, st__table * distanceTable, st__table * cacheTable, int approxDistance, int maxLocalRef, st__table * ghTable, st__table * mintermTable);
+static int cuddConjunctsAux (DdManager * dd, DdNode * f, DdNode ** c1, DdNode ** c2);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs two-way conjunctive decomposition of a BDD.]
+
+  Description [Performs two-way conjunctive decomposition of a
+  BDD. This procedure owes its name to the use of supersetting to
+  obtain an initial factor of the given function. Returns the number
+  of conjuncts produced, that is, 2 if successful; 1 if no meaningful
+  decomposition was found; 0 otherwise. The conjuncts produced by this
+  procedure tend to be imbalanced.]
+
+  SideEffects [The factors are returned in an array as side effects.
+  The array is allocated by this function. It is the caller's responsibility
+  to free it. On successful completion, the conjuncts are already
+  referenced. If the function returns 0, the array for the conjuncts is
+  not allocated. If the function returns 1, the only factor equals the
+  function to be decomposed.]
+
+  SeeAlso     [Cudd_bddApproxDisjDecomp Cudd_bddIterConjDecomp
+  Cudd_bddGenConjDecomp Cudd_bddVarConjDecomp Cudd_RemapOverApprox
+  Cudd_bddSqueeze Cudd_bddLICompaction]
+
+******************************************************************************/
+int
+Cudd_bddApproxConjDecomp(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be decomposed */,
+  DdNode *** conjuncts /* address of the first factor */)
+{
+    DdNode *superset1, *superset2, *glocal, *hlocal;
+    int nvars = Cudd_SupportSize(dd,f);
+
+    /* Find a tentative first factor by overapproximation and minimization. */
+    superset1 = Cudd_RemapOverApprox(dd,f,nvars,0,1.0);
+    if (superset1 == NULL) return(0);
+    cuddRef(superset1);
+    superset2 = Cudd_bddSqueeze(dd,f,superset1);
+    if (superset2 == NULL) {
+        Cudd_RecursiveDeref(dd,superset1);
+        return(0);
+    }
+    cuddRef(superset2);
+    Cudd_RecursiveDeref(dd,superset1);
+
+    /* Compute the second factor by minimization. */
+    hlocal = Cudd_bddLICompaction(dd,f,superset2);
+    if (hlocal == NULL) {
+        Cudd_RecursiveDeref(dd,superset2);
+        return(0);
+    }
+    cuddRef(hlocal);
+
+    /* Refine the first factor by minimization. If h turns out to be f, this
+    ** step guarantees that g will be 1. */
+    glocal = Cudd_bddLICompaction(dd,superset2,hlocal);
+    if (glocal == NULL) {
+        Cudd_RecursiveDeref(dd,superset2);
+        Cudd_RecursiveDeref(dd,hlocal);
+        return(0);
+    }
+    cuddRef(glocal);
+    Cudd_RecursiveDeref(dd,superset2);
+
+    if (glocal != DD_ONE(dd)) {
+        if (hlocal != DD_ONE(dd)) {
+            *conjuncts = ABC_ALLOC(DdNode *,2);
+            if (*conjuncts == NULL) {
+                Cudd_RecursiveDeref(dd,glocal);
+                Cudd_RecursiveDeref(dd,hlocal);
+                dd->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            (*conjuncts)[0] = glocal;
+            (*conjuncts)[1] = hlocal;
+            return(2);
+        } else {
+            Cudd_RecursiveDeref(dd,hlocal);
+            *conjuncts = ABC_ALLOC(DdNode *,1);
+            if (*conjuncts == NULL) {
+                Cudd_RecursiveDeref(dd,glocal);
+                dd->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            (*conjuncts)[0] = glocal;
+            return(1);
+        }
+    } else {
+        Cudd_RecursiveDeref(dd,glocal);
+        *conjuncts = ABC_ALLOC(DdNode *,1);
+        if (*conjuncts == NULL) {
+            Cudd_RecursiveDeref(dd,hlocal);
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        (*conjuncts)[0] = hlocal;
+        return(1);
+    }
+
+} /* end of Cudd_bddApproxConjDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs two-way disjunctive decomposition of a BDD.]
+
+  Description [Performs two-way disjunctive decomposition of a BDD.
+  Returns the number of disjuncts produced, that is, 2 if successful;
+  1 if no meaningful decomposition was found; 0 otherwise. The
+  disjuncts produced by this procedure tend to be imbalanced.]
+
+  SideEffects [The two disjuncts are returned in an array as side effects.
+  The array is allocated by this function. It is the caller's responsibility
+  to free it. On successful completion, the disjuncts are already
+  referenced. If the function returns 0, the array for the disjuncts is
+  not allocated. If the function returns 1, the only factor equals the
+  function to be decomposed.]
+
+  SeeAlso     [Cudd_bddApproxConjDecomp Cudd_bddIterDisjDecomp
+  Cudd_bddGenDisjDecomp Cudd_bddVarDisjDecomp]
+
+******************************************************************************/
+int
+Cudd_bddApproxDisjDecomp(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be decomposed */,
+  DdNode *** disjuncts /* address of the array of the disjuncts */)
+{
+    int result, i;
+
+    result = Cudd_bddApproxConjDecomp(dd,Cudd_Not(f),disjuncts);
+    for (i = 0; i < result; i++) {
+        (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]);
+    }
+    return(result);
+
+} /* end of Cudd_bddApproxDisjDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs two-way conjunctive decomposition of a BDD.]
+
+  Description [Performs two-way conjunctive decomposition of a
+  BDD. This procedure owes its name to the iterated use of
+  supersetting to obtain a factor of the given function. Returns the
+  number of conjuncts produced, that is, 2 if successful; 1 if no
+  meaningful decomposition was found; 0 otherwise. The conjuncts
+  produced by this procedure tend to be imbalanced.]
+
+  SideEffects [The factors are returned in an array as side effects.
+  The array is allocated by this function. It is the caller's responsibility
+  to free it. On successful completion, the conjuncts are already
+  referenced. If the function returns 0, the array for the conjuncts is
+  not allocated. If the function returns 1, the only factor equals the
+  function to be decomposed.]
+
+  SeeAlso     [Cudd_bddIterDisjDecomp Cudd_bddApproxConjDecomp
+  Cudd_bddGenConjDecomp Cudd_bddVarConjDecomp Cudd_RemapOverApprox
+  Cudd_bddSqueeze Cudd_bddLICompaction]
+
+******************************************************************************/
+int
+Cudd_bddIterConjDecomp(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be decomposed */,
+  DdNode *** conjuncts /* address of the array of conjuncts */)
+{
+    DdNode *superset1, *superset2, *old[2], *res[2];
+    int sizeOld, sizeNew;
+    int nvars = Cudd_SupportSize(dd,f);
+
+    old[0] = DD_ONE(dd);
+    cuddRef(old[0]);
+    old[1] = f;
+    cuddRef(old[1]);
+    sizeOld = Cudd_SharingSize(old,2);
+
+    do {
+        /* Find a tentative first factor by overapproximation and
+        ** minimization. */
+        superset1 = Cudd_RemapOverApprox(dd,old[1],nvars,0,1.0);
+        if (superset1 == NULL) {
+            Cudd_RecursiveDeref(dd,old[0]);
+            Cudd_RecursiveDeref(dd,old[1]);
+            return(0);
+        }
+        cuddRef(superset1);
+        superset2 = Cudd_bddSqueeze(dd,old[1],superset1);
+        if (superset2 == NULL) {
+            Cudd_RecursiveDeref(dd,old[0]);
+            Cudd_RecursiveDeref(dd,old[1]);
+            Cudd_RecursiveDeref(dd,superset1);
+            return(0);
+        }
+        cuddRef(superset2);
+        Cudd_RecursiveDeref(dd,superset1);
+        res[0] = Cudd_bddAnd(dd,old[0],superset2);
+        if (res[0] == NULL) {
+            Cudd_RecursiveDeref(dd,superset2);
+            Cudd_RecursiveDeref(dd,old[0]);
+            Cudd_RecursiveDeref(dd,old[1]);
+            return(0);
+        }
+        cuddRef(res[0]);
+        Cudd_RecursiveDeref(dd,superset2);
+        if (res[0] == old[0]) {
+            Cudd_RecursiveDeref(dd,res[0]);
+            break;      /* avoid infinite loop */
+        }
+
+        /* Compute the second factor by minimization. */
+        res[1] = Cudd_bddLICompaction(dd,old[1],res[0]);
+        if (res[1] == NULL) {
+            Cudd_RecursiveDeref(dd,old[0]);
+            Cudd_RecursiveDeref(dd,old[1]);
+            return(0);
+        }
+        cuddRef(res[1]);
+
+        sizeNew = Cudd_SharingSize(res,2);
+        if (sizeNew <= sizeOld) {
+            Cudd_RecursiveDeref(dd,old[0]);
+            old[0] = res[0];
+            Cudd_RecursiveDeref(dd,old[1]);
+            old[1] = res[1];
+            sizeOld = sizeNew;
+        } else {
+            Cudd_RecursiveDeref(dd,res[0]);
+            Cudd_RecursiveDeref(dd,res[1]);
+            break;
+        }
+
+    } while (1);
+
+    /* Refine the first factor by minimization. If h turns out to
+    ** be f, this step guarantees that g will be 1. */
+    superset1 = Cudd_bddLICompaction(dd,old[0],old[1]);
+    if (superset1 == NULL) {
+        Cudd_RecursiveDeref(dd,old[0]);
+        Cudd_RecursiveDeref(dd,old[1]);
+        return(0);
+    }
+    cuddRef(superset1);
+    Cudd_RecursiveDeref(dd,old[0]);
+    old[0] = superset1;
+
+    if (old[0] != DD_ONE(dd)) {
+        if (old[1] != DD_ONE(dd)) {
+            *conjuncts = ABC_ALLOC(DdNode *,2);
+            if (*conjuncts == NULL) {
+                Cudd_RecursiveDeref(dd,old[0]);
+                Cudd_RecursiveDeref(dd,old[1]);
+                dd->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            (*conjuncts)[0] = old[0];
+            (*conjuncts)[1] = old[1];
+            return(2);
+        } else {
+            Cudd_RecursiveDeref(dd,old[1]);
+            *conjuncts = ABC_ALLOC(DdNode *,1);
+            if (*conjuncts == NULL) {
+                Cudd_RecursiveDeref(dd,old[0]);
+                dd->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            (*conjuncts)[0] = old[0];
+            return(1);
+        }
+    } else {
+        Cudd_RecursiveDeref(dd,old[0]);
+        *conjuncts = ABC_ALLOC(DdNode *,1);
+        if (*conjuncts == NULL) {
+            Cudd_RecursiveDeref(dd,old[1]);
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        (*conjuncts)[0] = old[1];
+        return(1);
+    }
+
+} /* end of Cudd_bddIterConjDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs two-way disjunctive decomposition of a BDD.]
+
+  Description [Performs two-way disjunctive decomposition of a BDD.
+  Returns the number of disjuncts produced, that is, 2 if successful;
+  1 if no meaningful decomposition was found; 0 otherwise. The
+  disjuncts produced by this procedure tend to be imbalanced.]
+
+  SideEffects [The two disjuncts are returned in an array as side effects.
+  The array is allocated by this function. It is the caller's responsibility
+  to free it. On successful completion, the disjuncts are already
+  referenced. If the function returns 0, the array for the disjuncts is
+  not allocated. If the function returns 1, the only factor equals the
+  function to be decomposed.]
+
+  SeeAlso     [Cudd_bddIterConjDecomp Cudd_bddApproxDisjDecomp
+  Cudd_bddGenDisjDecomp Cudd_bddVarDisjDecomp]
+
+******************************************************************************/
+int
+Cudd_bddIterDisjDecomp(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be decomposed */,
+  DdNode *** disjuncts /* address of the array of the disjuncts */)
+{
+    int result, i;
+
+    result = Cudd_bddIterConjDecomp(dd,Cudd_Not(f),disjuncts);
+    for (i = 0; i < result; i++) {
+        (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]);
+    }
+    return(result);
+
+} /* end of Cudd_bddIterDisjDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs two-way conjunctive decomposition of a BDD.]
+
+  Description [Performs two-way conjunctive decomposition of a
+  BDD. This procedure owes its name to the fact tht it generalizes the
+  decomposition based on the cofactors with respect to one
+  variable. Returns the number of conjuncts produced, that is, 2 if
+  successful; 1 if no meaningful decomposition was found; 0
+  otherwise. The conjuncts produced by this procedure tend to be
+  balanced.]
+
+  SideEffects [The two factors are returned in an array as side effects.
+  The array is allocated by this function. It is the caller's responsibility
+  to free it. On successful completion, the conjuncts are already
+  referenced. If the function returns 0, the array for the conjuncts is
+  not allocated. If the function returns 1, the only factor equals the
+  function to be decomposed.]
+
+  SeeAlso     [Cudd_bddGenDisjDecomp Cudd_bddApproxConjDecomp
+  Cudd_bddIterConjDecomp Cudd_bddVarConjDecomp]
+
+******************************************************************************/
+int
+Cudd_bddGenConjDecomp(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be decomposed */,
+  DdNode *** conjuncts /* address of the array of conjuncts */)
+{
+    int result;
+    DdNode *glocal, *hlocal;
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+    
+    do {
+        dd->reordered = 0;
+        result = cuddConjunctsAux(dd, f, &glocal, &hlocal);
+    } while (dd->reordered == 1);
+
+    if (result == 0) {
+        return(0);
+    }
+
+    if (glocal != one) {
+        if (hlocal != one) {
+            *conjuncts = ABC_ALLOC(DdNode *,2);
+            if (*conjuncts == NULL) {
+                Cudd_RecursiveDeref(dd,glocal);
+                Cudd_RecursiveDeref(dd,hlocal);
+                dd->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            (*conjuncts)[0] = glocal;
+            (*conjuncts)[1] = hlocal;
+            return(2);
+        } else {
+            Cudd_RecursiveDeref(dd,hlocal);
+            *conjuncts = ABC_ALLOC(DdNode *,1);
+            if (*conjuncts == NULL) {
+                Cudd_RecursiveDeref(dd,glocal);
+                dd->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            (*conjuncts)[0] = glocal;
+            return(1);
+        }
+    } else {
+        Cudd_RecursiveDeref(dd,glocal);
+        *conjuncts = ABC_ALLOC(DdNode *,1);
+        if (*conjuncts == NULL) {
+            Cudd_RecursiveDeref(dd,hlocal);
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        (*conjuncts)[0] = hlocal;
+        return(1);
+    }
+
+} /* end of Cudd_bddGenConjDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs two-way disjunctive decomposition of a BDD.]
+
+  Description [Performs two-way disjunctive decomposition of a BDD.
+  Returns the number of disjuncts produced, that is, 2 if successful;
+  1 if no meaningful decomposition was found; 0 otherwise. The
+  disjuncts produced by this procedure tend to be balanced.]
+
+  SideEffects [The two disjuncts are returned in an array as side effects.
+  The array is allocated by this function. It is the caller's responsibility
+  to free it. On successful completion, the disjuncts are already
+  referenced. If the function returns 0, the array for the disjuncts is
+  not allocated. If the function returns 1, the only factor equals the
+  function to be decomposed.]
+
+  SeeAlso     [Cudd_bddGenConjDecomp Cudd_bddApproxDisjDecomp
+  Cudd_bddIterDisjDecomp Cudd_bddVarDisjDecomp]
+
+******************************************************************************/
+int
+Cudd_bddGenDisjDecomp(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be decomposed */,
+  DdNode *** disjuncts /* address of the array of the disjuncts */)
+{
+    int result, i;
+
+    result = Cudd_bddGenConjDecomp(dd,Cudd_Not(f),disjuncts);
+    for (i = 0; i < result; i++) {
+        (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]);
+    }
+    return(result);
+
+} /* end of Cudd_bddGenDisjDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs two-way conjunctive decomposition of a BDD.]
+
+  Description [Conjunctively decomposes one BDD according to a
+  variable.  If <code>f</code> is the function of the BDD and
+  <code>x</code> is the variable, the decomposition is
+  <code>(f+x)(f+x')</code>.  The variable is chosen so as to balance
+  the sizes of the two conjuncts and to keep them small.  Returns the
+  number of conjuncts produced, that is, 2 if successful; 1 if no
+  meaningful decomposition was found; 0 otherwise.]
+
+  SideEffects [The two factors are returned in an array as side effects.
+  The array is allocated by this function. It is the caller's responsibility
+  to free it. On successful completion, the conjuncts are already
+  referenced. If the function returns 0, the array for the conjuncts is
+  not allocated. If the function returns 1, the only factor equals the
+  function to be decomposed.]
+
+  SeeAlso     [Cudd_bddVarDisjDecomp Cudd_bddGenConjDecomp
+  Cudd_bddApproxConjDecomp Cudd_bddIterConjDecomp]
+
+*****************************************************************************/
+int
+Cudd_bddVarConjDecomp(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be decomposed */,
+  DdNode *** conjuncts /* address of the array of conjuncts */)
+{
+    int best;
+    int min;
+    DdNode *support, *scan, *var, *glocal, *hlocal;
+
+    /* Find best cofactoring variable. */
+    support = Cudd_Support(dd,f);
+    if (support == NULL) return(0);
+    if (Cudd_IsConstant(support)) {
+        *conjuncts = ABC_ALLOC(DdNode *,1);
+        if (*conjuncts == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        (*conjuncts)[0] = f;
+        cuddRef((*conjuncts)[0]);
+        return(1);
+    }
+    cuddRef(support);
+    min = 1000000000;
+    best = -1;
+    scan = support;
+    while (!Cudd_IsConstant(scan)) {
+        int i = scan->index;
+        int est1 = Cudd_EstimateCofactor(dd,f,i,1);
+        int est0 = Cudd_EstimateCofactor(dd,f,i,0);
+        /* Minimize the size of the larger of the two cofactors. */
+        int est = (est1 > est0) ? est1 : est0;
+        if (est < min) {
+            min = est;
+            best = i;
+        }
+        scan = cuddT(scan);
+    }
+#ifdef DD_DEBUG
+    assert(best >= 0 && best < dd->size);
+#endif
+    Cudd_RecursiveDeref(dd,support);
+
+    var = Cudd_bddIthVar(dd,best);
+    glocal = Cudd_bddOr(dd,f,var);
+    if (glocal == NULL) {
+        return(0);
+    }
+    cuddRef(glocal);
+    hlocal = Cudd_bddOr(dd,f,Cudd_Not(var));
+    if (hlocal == NULL) {
+        Cudd_RecursiveDeref(dd,glocal);
+        return(0);
+    }
+    cuddRef(hlocal);
+
+    if (glocal != DD_ONE(dd)) {
+        if (hlocal != DD_ONE(dd)) {
+            *conjuncts = ABC_ALLOC(DdNode *,2);
+            if (*conjuncts == NULL) {
+                Cudd_RecursiveDeref(dd,glocal);
+                Cudd_RecursiveDeref(dd,hlocal);
+                dd->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            (*conjuncts)[0] = glocal;
+            (*conjuncts)[1] = hlocal;
+            return(2);
+        } else {
+            Cudd_RecursiveDeref(dd,hlocal);
+            *conjuncts = ABC_ALLOC(DdNode *,1);
+            if (*conjuncts == NULL) {
+                Cudd_RecursiveDeref(dd,glocal);
+                dd->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            (*conjuncts)[0] = glocal;
+            return(1);
+        }
+    } else {
+        Cudd_RecursiveDeref(dd,glocal);
+        *conjuncts = ABC_ALLOC(DdNode *,1);
+        if (*conjuncts == NULL) {
+            Cudd_RecursiveDeref(dd,hlocal);
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        (*conjuncts)[0] = hlocal;
+        return(1);
+    }
+
+} /* end of Cudd_bddVarConjDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs two-way disjunctive decomposition of a BDD.]
+
+  Description [Performs two-way disjunctive decomposition of a BDD
+  according to a variable. If <code>f</code> is the function of the
+  BDD and <code>x</code> is the variable, the decomposition is
+  <code>f*x + f*x'</code>.  The variable is chosen so as to balance
+  the sizes of the two disjuncts and to keep them small.  Returns the
+  number of disjuncts produced, that is, 2 if successful; 1 if no
+  meaningful decomposition was found; 0 otherwise.]
+
+  SideEffects [The two disjuncts are returned in an array as side effects.
+  The array is allocated by this function. It is the caller's responsibility
+  to free it. On successful completion, the disjuncts are already
+  referenced. If the function returns 0, the array for the disjuncts is
+  not allocated. If the function returns 1, the only factor equals the
+  function to be decomposed.]
+
+  SeeAlso     [Cudd_bddVarConjDecomp Cudd_bddApproxDisjDecomp
+  Cudd_bddIterDisjDecomp Cudd_bddGenDisjDecomp]
+
+******************************************************************************/
+int
+Cudd_bddVarDisjDecomp(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be decomposed */,
+  DdNode *** disjuncts /* address of the array of the disjuncts */)
+{
+    int result, i;
+
+    result = Cudd_bddVarConjDecomp(dd,Cudd_Not(f),disjuncts);
+    for (i = 0; i < result; i++) {
+        (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]);
+    }
+    return(result);
+
+} /* end of Cudd_bddVarDisjDecomp */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Get longest distance of node from constant.]
+
+  Description [Get longest distance of node from constant. Returns the
+  distance of the root from the constant if successful; CUDD_OUT_OF_MEM
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static NodeStat *
+CreateBotDist(
+  DdNode * node,
+  st__table * distanceTable)
+{
+    DdNode *N, *Nv, *Nnv;
+    int distance, distanceNv, distanceNnv;
+    NodeStat *nodeStat, *nodeStatNv, *nodeStatNnv;
+
+#if 0
+    if (Cudd_IsConstant(node)) {
+        return(0);
+    }
+#endif
+    
+    /* Return the entry in the table if found. */
+    N = Cudd_Regular(node);
+    if ( st__lookup(distanceTable, (const char *)N, (char **)&nodeStat)) {
+        nodeStat->localRef++;
+        return(nodeStat);
+    }
+
+    Nv = cuddT(N);
+    Nnv = cuddE(N);
+    Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
+    Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
+
+    /* Recur on the children. */
+    nodeStatNv = CreateBotDist(Nv, distanceTable);
+    if (nodeStatNv == NULL) return(NULL);
+    distanceNv = nodeStatNv->distance;
+
+    nodeStatNnv = CreateBotDist(Nnv, distanceTable);
+    if (nodeStatNnv == NULL) return(NULL);
+    distanceNnv = nodeStatNnv->distance;
+    /* Store max distance from constant; note sometimes this distance
+    ** may be to 0.
+    */
+    distance = (distanceNv > distanceNnv) ? (distanceNv+1) : (distanceNnv + 1);
+
+    nodeStat = ABC_ALLOC(NodeStat, 1);
+    if (nodeStat == NULL) {
+        return(0);
+    }
+    nodeStat->distance = distance;
+    nodeStat->localRef = 1;
+    
+    if ( st__insert(distanceTable, (char *)N, (char *)nodeStat) ==
+        st__OUT_OF_MEM) {
+        return(0);
+
+    }
+    return(nodeStat);
+
+} /* end of CreateBotDist */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Count the number of minterms of each node ina a BDD and
+  store it in a hash table.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static double
+CountMinterms(
+  DdNode * node,
+  double  max,
+  st__table * mintermTable,
+  FILE *fp)
+{
+    DdNode *N, *Nv, *Nnv;
+    double min, minNv, minNnv;
+    double *dummy;
+
+    N = Cudd_Regular(node);
+
+    if (cuddIsConstant(N)) {
+        if (node == zero) {
+            return(0);
+        } else {
+            return(max);
+        }
+    }
+
+    /* Return the entry in the table if found. */
+    if ( st__lookup(mintermTable, (const char *)node, (char **)&dummy)) {
+        min = *dummy;
+        return(min);
+    }
+
+    Nv = cuddT(N);
+    Nnv = cuddE(N);
+    Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
+    Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
+
+    /* Recur on the children. */
+    minNv = CountMinterms(Nv, max, mintermTable, fp);
+    if (minNv == -1.0) return(-1.0);
+    minNnv = CountMinterms(Nnv, max, mintermTable, fp);
+    if (minNnv == -1.0) return(-1.0);
+    min = minNv / 2.0 + minNnv / 2.0;
+    /* store 
+     */
+
+    dummy = ABC_ALLOC(double, 1);
+    if (dummy == NULL) return(-1.0);
+    *dummy = min;
+    if ( st__insert(mintermTable, (char *)node, (char *)dummy) == st__OUT_OF_MEM) {
+        (void) fprintf(fp, "st table insert failed\n");
+    }
+    return(min);
+
+} /* end of CountMinterms */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Free factors structure]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ConjunctsFree(
+  DdManager * dd,
+  Conjuncts * factors)
+{
+    Cudd_RecursiveDeref(dd, factors->g);
+    Cudd_RecursiveDeref(dd, factors->h);
+    ABC_FREE(factors);
+    return;
+
+} /* end of ConjunctsFree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Check whether the given pair is in the tables.]
+
+  Description [.Check whether the given pair is in the tables.  gTable
+  and hTable are combined.
+  absence in both is indicated by 0,
+  presence in gTable is indicated by 1,
+  presence in hTable by 2 and
+  presence in both by 3.
+  The values returned by this function are PAIR_ST,
+  PAIR_CR, G_ST, G_CR, H_ST, H_CR, BOTH_G, BOTH_H, NONE.
+  PAIR_ST implies g in gTable and h in hTable
+  PAIR_CR implies g in hTable and h in gTable
+  G_ST implies g in gTable and h not in any table
+  G_CR implies g in hTable and h not in any table
+  H_ST implies h in hTable and g not in any table
+  H_CR implies h in gTable and g not in any table
+  BOTH_G implies both in gTable
+  BOTH_H implies both in hTable
+  NONE implies none in table; ]
+
+  SideEffects []
+
+  SeeAlso     [CheckTablesCacheAndReturn CheckInTables]
+
+******************************************************************************/
+static int
+PairInTables(
+  DdNode * g,
+  DdNode * h,
+  st__table * ghTable)
+{
+    int valueG, valueH, gPresent, hPresent;
+
+    valueG = valueH = gPresent = hPresent = 0;
+    
+    gPresent = st__lookup_int(ghTable, (char *)Cudd_Regular(g), &valueG);
+    hPresent = st__lookup_int(ghTable, (char *)Cudd_Regular(h), &valueH);
+
+    if (!gPresent && !hPresent) return(NONE);
+
+    if (!hPresent) {
+        if (valueG & 1) return(G_ST);
+        if (valueG & 2) return(G_CR);
+    }
+    if (!gPresent) {
+        if (valueH & 1) return(H_CR);
+        if (valueH & 2) return(H_ST);
+    }
+    /* both in tables */
+    if ((valueG & 1) && (valueH & 2)) return(PAIR_ST);
+    if ((valueG & 2) && (valueH & 1)) return(PAIR_CR);
+    
+    if (valueG & 1) {
+        return(BOTH_G);
+    } else {
+        return(BOTH_H);
+    }
+    
+} /* end of PairInTables */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Check the tables for the existence of pair and return one
+  combination, cache the result.]
+
+  Description [Check the tables for the existence of pair and return
+  one combination, cache the result. The assumption is that one of the
+  conjuncts is already in the tables.]
+
+  SideEffects [g and h referenced for the cache]
+
+  SeeAlso     [ZeroCase]
+
+******************************************************************************/
+static Conjuncts *
+CheckTablesCacheAndReturn(
+  DdNode * node,
+  DdNode * g,
+  DdNode * h,
+  st__table * ghTable,
+  st__table * cacheTable)
+{
+    int pairValue;
+    int value;
+    Conjuncts *factors;
+    
+    value = 0;
+    /* check tables */
+    pairValue = PairInTables(g, h, ghTable);
+    assert(pairValue != NONE);
+    /* if both dont exist in table, we know one exists(either g or h).
+     * Therefore store the other and proceed
+     */
+    factors = ABC_ALLOC(Conjuncts, 1);
+    if (factors == NULL) return(NULL);
+    if ((pairValue == BOTH_H) || (pairValue == H_ST)) {
+        if (g != one) {
+            value = 0;
+            if ( st__lookup_int(ghTable, (char *)Cudd_Regular(g), &value)) {
+                value |= 1;
+            } else {
+                value = 1;
+            }
+            if ( st__insert(ghTable, (char *)Cudd_Regular(g),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                return(NULL);
+            }
+        }
+        factors->g = g;
+        factors->h = h;
+    } else  if ((pairValue == BOTH_G) || (pairValue == G_ST)) {
+        if (h != one) {
+            value = 0;
+            if ( st__lookup_int(ghTable, (char *)Cudd_Regular(h), &value)) {
+                value |= 2;
+            } else {
+                value = 2;
+            }
+            if ( st__insert(ghTable, (char *)Cudd_Regular(h),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                return(NULL);
+            }
+        }
+        factors->g = g;
+        factors->h = h;
+    } else if (pairValue == H_CR) {
+        if (g != one) {
+            value = 2;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(g),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                return(NULL);
+            }
+        }
+        factors->g = h;
+        factors->h = g;
+    } else if (pairValue == G_CR) {
+        if (h != one) {
+            value = 1;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(h),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                return(NULL);
+            }
+        }
+        factors->g = h;
+        factors->h = g;
+    } else if (pairValue == PAIR_CR) {
+    /* pair exists in table */
+        factors->g = h;
+        factors->h = g;
+    } else if (pairValue == PAIR_ST) {
+        factors->g = g;
+        factors->h = h;
+    }
+            
+    /* cache the result for this node */
+    if ( st__insert(cacheTable, (char *)node, (char *)factors) == st__OUT_OF_MEM) {
+        ABC_FREE(factors);
+        return(NULL);
+    }
+
+    return(factors);
+
+} /* end of CheckTablesCacheAndReturn */
+        
+/**Function********************************************************************
+
+  Synopsis    [Check the tables for the existence of pair and return one
+  combination, store in cache.]
+
+  Description [Check the tables for the existence of pair and return
+  one combination, store in cache. The pair that has more pointers to
+  it is picked. An approximation of the number of local pointers is
+  made by taking the reference count of the pairs sent. ]
+
+  SideEffects []
+
+  SeeAlso     [ZeroCase BuildConjuncts]
+
+******************************************************************************/
+static Conjuncts *
+PickOnePair(
+  DdNode * node,
+  DdNode * g1,
+  DdNode * h1,
+  DdNode * g2,
+  DdNode * h2,
+  st__table * ghTable,
+  st__table * cacheTable)
+{
+    int value;
+    Conjuncts *factors;
+    int oneRef, twoRef;
+    
+    factors = ABC_ALLOC(Conjuncts, 1);
+    if (factors == NULL) return(NULL);
+
+    /* count the number of pointers to pair 2 */
+    if (h2 == one) {
+        twoRef = (Cudd_Regular(g2))->ref;
+    } else if (g2 == one) {
+        twoRef = (Cudd_Regular(h2))->ref;
+    } else {
+        twoRef = ((Cudd_Regular(g2))->ref + (Cudd_Regular(h2))->ref)/2;
+    }
+
+    /* count the number of pointers to pair 1 */
+    if (h1 == one) {
+        oneRef  = (Cudd_Regular(g1))->ref;
+    } else if (g1 == one) {
+        oneRef  = (Cudd_Regular(h1))->ref;
+    } else {
+        oneRef = ((Cudd_Regular(g1))->ref + (Cudd_Regular(h1))->ref)/2;
+    }
+
+    /* pick the pair with higher reference count */
+    if (oneRef >= twoRef) {
+        factors->g = g1;
+        factors->h = h1;
+    } else {
+        factors->g = g2;
+        factors->h = h2;
+    }
+    
+    /*
+     * Store computed factors in respective tables to encourage
+     * recombination.
+     */
+    if (factors->g != one) {
+        /* insert g in htable */
+        value = 0;
+        if ( st__lookup_int(ghTable, (char *)Cudd_Regular(factors->g), &value)) {
+            if (value == 2) {
+                value |= 1;
+                if ( st__insert(ghTable, (char *)Cudd_Regular(factors->g),
+                              (char *)(long)value) == st__OUT_OF_MEM) {
+                    ABC_FREE(factors);
+                    return(NULL);
+                }
+            }
+        } else {
+            value = 1;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(factors->g),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                ABC_FREE(factors);
+                return(NULL);
+            }
+        }
+    }
+
+    if (factors->h != one) {
+        /* insert h in htable */
+        value = 0;
+        if ( st__lookup_int(ghTable, (char *)Cudd_Regular(factors->h), &value)) {
+            if (value == 1) {
+                value |= 2;
+                if ( st__insert(ghTable, (char *)Cudd_Regular(factors->h),
+                              (char *)(long)value) == st__OUT_OF_MEM) {
+                    ABC_FREE(factors);
+                    return(NULL);
+                }
+            }       
+        } else {
+            value = 2;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(factors->h),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                ABC_FREE(factors);
+                return(NULL);
+            }
+        }
+    }
+    
+    /* Store factors in cache table for later use. */
+    if ( st__insert(cacheTable, (char *)node, (char *)factors) ==
+            st__OUT_OF_MEM) {
+        ABC_FREE(factors);
+        return(NULL);
+    }
+
+    return(factors);
+
+} /* end of PickOnePair */
+
+
+/**Function********************************************************************
+
+  Synopsis [Check if the two pairs exist in the table, If any of the
+  conjuncts do exist, store in the cache and return the corresponding pair.]
+
+  Description [Check if the two pairs exist in the table. If any of
+  the conjuncts do exist, store in the cache and return the
+  corresponding pair.]
+
+  SideEffects []
+
+  SeeAlso     [ZeroCase BuildConjuncts]
+
+******************************************************************************/
+static Conjuncts *
+CheckInTables(
+  DdNode * node,
+  DdNode * g1,
+  DdNode * h1,
+  DdNode * g2,
+  DdNode * h2,
+  st__table * ghTable,
+  st__table * cacheTable,
+  int * outOfMem)
+{
+    int pairValue1,  pairValue2;
+    Conjuncts *factors;
+    int value;
+    
+    *outOfMem = 0;
+
+    /* check existence of pair in table */
+    pairValue1 = PairInTables(g1, h1, ghTable);
+    pairValue2 = PairInTables(g2, h2, ghTable);
+
+    /* if none of the 4 exist in the gh tables, return NULL */
+    if ((pairValue1 == NONE) && (pairValue2 == NONE)) {
+        return NULL;
+    }
+    
+    factors = ABC_ALLOC(Conjuncts, 1);
+    if (factors == NULL) {
+        *outOfMem = 1;
+        return NULL;
+    }
+
+    /* pairs that already exist in the table get preference. */
+    if (pairValue1 == PAIR_ST) {
+        factors->g = g1;
+        factors->h = h1;
+    } else if (pairValue2 == PAIR_ST) {
+        factors->g = g2;
+        factors->h = h2;
+    } else if (pairValue1 == PAIR_CR) {
+        factors->g = h1;
+        factors->h = g1;
+    } else if (pairValue2 == PAIR_CR) {
+        factors->g = h2;
+        factors->h = g2;
+    } else if (pairValue1 == G_ST) {
+        /* g exists in the table, h is not found in either table */
+        factors->g = g1;
+        factors->h = h1;
+        if (h1 != one) {
+            value = 2;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(h1),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                *outOfMem = 1;
+                ABC_FREE(factors);
+                return(NULL);
+            }
+        }
+    } else if (pairValue1 == BOTH_G) {
+        /* g and h are  found in the g table */
+        factors->g = g1;
+        factors->h = h1;
+        if (h1 != one) {
+            value = 3;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(h1),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                *outOfMem = 1;
+                ABC_FREE(factors);
+                return(NULL);
+            }
+        }
+    } else if (pairValue1 == H_ST) {
+        /* h exists in the table, g is not found in either table */
+        factors->g = g1;
+        factors->h = h1;
+        if (g1 != one) {
+            value = 1;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(g1),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                *outOfMem = 1;
+                ABC_FREE(factors);
+                return(NULL);
+            }
+        }
+    } else if (pairValue1 == BOTH_H) {
+        /* g and h are  found in the h table */
+        factors->g = g1;
+        factors->h = h1;
+        if (g1 != one) {
+            value = 3;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(g1),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                *outOfMem = 1;
+                ABC_FREE(factors);
+                return(NULL);
+            }
+        }
+    } else if (pairValue2 == G_ST) {
+        /* g exists in the table, h is not found in either table */
+        factors->g = g2;
+        factors->h = h2;
+        if (h2 != one) {
+            value = 2;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(h2),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                *outOfMem = 1;
+                ABC_FREE(factors);
+                return(NULL);
+            }
+        }
+    } else if  (pairValue2 == BOTH_G) {
+        /* g and h are  found in the g table */
+        factors->g = g2;
+        factors->h = h2;
+        if (h2 != one) {
+            value = 3;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(h2),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                *outOfMem = 1;
+                ABC_FREE(factors);
+                return(NULL);
+            }
+        }
+    } else if (pairValue2 == H_ST) { 
+        /* h exists in the table, g is not found in either table */
+        factors->g = g2;
+        factors->h = h2;
+        if (g2 != one) {
+            value = 1;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(g2),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                *outOfMem = 1;
+                ABC_FREE(factors);
+                return(NULL);
+            }
+        }
+    } else if (pairValue2 == BOTH_H) {
+        /* g and h are  found in the h table */
+        factors->g = g2;
+        factors->h = h2;
+        if (g2 != one) {
+            value = 3;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(g2),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                *outOfMem = 1;
+                ABC_FREE(factors);
+                return(NULL);
+            }
+        }
+    } else if (pairValue1 == G_CR) {
+        /* g found in h table and h in none */
+        factors->g = h1;
+        factors->h = g1;
+        if (h1 != one) {
+            value = 1;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(h1),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                *outOfMem = 1;
+                ABC_FREE(factors);
+                return(NULL);
+            }
+        }
+    } else if (pairValue1 == H_CR) {
+        /* h found in g table and g in none */
+        factors->g = h1;
+        factors->h = g1;
+        if (g1 != one) {
+            value = 2;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(g1),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                *outOfMem = 1;
+                ABC_FREE(factors);
+                return(NULL);
+            }
+        }
+    } else if (pairValue2 == G_CR) {
+        /* g found in h table and h in none */
+        factors->g = h2;
+        factors->h = g2;
+        if (h2 != one) {
+            value = 1;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(h2),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                *outOfMem = 1;
+                ABC_FREE(factors);
+                return(NULL);
+            }
+        }
+    } else if (pairValue2 == H_CR) {
+        /* h found in g table and g in none */
+        factors->g = h2;
+        factors->h = g2;
+        if (g2 != one) {
+            value = 2;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(g2),
+                          (char *)(long)value) == st__OUT_OF_MEM) {
+                *outOfMem = 1;
+                ABC_FREE(factors);
+                return(NULL);
+            }
+        }
+    }
+    
+    /* Store factors in cache table for later use. */
+    if ( st__insert(cacheTable, (char *)node, (char *)factors) ==
+            st__OUT_OF_MEM) {
+        *outOfMem = 1;
+        ABC_FREE(factors);
+        return(NULL);
+    }
+    return factors;
+} /* end of CheckInTables */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [If one child is zero, do explicitly what Restrict does or better]
+
+  Description [If one child is zero, do explicitly what Restrict does or better.
+  First separate a variable and its child in the base case. In case of a cube
+  times a function, separate the cube and function. As a last resort, look in
+  tables.]
+
+  SideEffects [Frees the BDDs in factorsNv. factorsNv itself is not freed
+  because it is freed above.]
+
+  SeeAlso     [BuildConjuncts]
+
+******************************************************************************/
+static Conjuncts *
+ZeroCase(
+  DdManager * dd,
+  DdNode * node,
+  Conjuncts * factorsNv,
+  st__table * ghTable,
+  st__table * cacheTable,
+  int switched)
+{
+    int topid;
+    DdNode *g, *h, *g1, *g2, *h1, *h2, *x, *N, *G, *H, *Gv, *Gnv;
+    DdNode *Hv, *Hnv;
+    int value;
+    int outOfMem;
+    Conjuncts *factors;
+    
+    /* get var at this node */
+    N = Cudd_Regular(node);
+    topid = N->index;
+    x = dd->vars[topid];
+    x = (switched) ? Cudd_Not(x): x;
+    cuddRef(x);
+
+    /* Seprate variable and child */
+    if (factorsNv->g == one) {
+        Cudd_RecursiveDeref(dd, factorsNv->g);
+        factors = ABC_ALLOC(Conjuncts, 1);
+        if (factors == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            Cudd_RecursiveDeref(dd, factorsNv->h);
+            Cudd_RecursiveDeref(dd, x);
+            return(NULL);
+        }
+        factors->g = x;
+        factors->h = factorsNv->h;
+        /* cache the result*/
+        if ( st__insert(cacheTable, (char *)node, (char *)factors) == st__OUT_OF_MEM) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            Cudd_RecursiveDeref(dd, factorsNv->h); 
+            Cudd_RecursiveDeref(dd, x);
+            ABC_FREE(factors);
+            return NULL;
+        }
+        
+        /* store  x in g table, the other node is already in the table */
+        if ( st__lookup_int(ghTable, (char *)Cudd_Regular(x), &value)) {
+            value |= 1;
+        } else {
+            value = 1;
+        }
+        if ( st__insert(ghTable, (char *)Cudd_Regular(x), (char *)(long)value) == st__OUT_OF_MEM) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return NULL;
+        }
+        return(factors);
+    }
+    
+    /* Seprate variable and child */
+    if (factorsNv->h == one) {
+        Cudd_RecursiveDeref(dd, factorsNv->h);
+        factors = ABC_ALLOC(Conjuncts, 1);
+        if (factors == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            Cudd_RecursiveDeref(dd, factorsNv->g);
+            Cudd_RecursiveDeref(dd, x);
+            return(NULL);
+        }
+        factors->g = factorsNv->g;
+        factors->h = x;
+        /* cache the result. */
+        if ( st__insert(cacheTable, (char *)node, (char *)factors) == st__OUT_OF_MEM) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            Cudd_RecursiveDeref(dd, factorsNv->g);
+            Cudd_RecursiveDeref(dd, x);
+            ABC_FREE(factors);
+            return(NULL);
+        }
+        /* store x in h table,  the other node is already in the table */
+        if ( st__lookup_int(ghTable, (char *)Cudd_Regular(x), &value)) {
+            value |= 2;
+        } else {
+            value = 2;
+        }
+        if ( st__insert(ghTable, (char *)Cudd_Regular(x), (char *)(long)value) == st__OUT_OF_MEM) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return NULL;
+        }
+        return(factors);
+    }
+
+    G = Cudd_Regular(factorsNv->g);
+    Gv = cuddT(G);
+    Gnv = cuddE(G);
+    Gv = Cudd_NotCond(Gv, Cudd_IsComplement(node));
+    Gnv = Cudd_NotCond(Gnv, Cudd_IsComplement(node));
+    /* if the child below is a variable */
+    if ((Gv == zero) || (Gnv == zero)) {
+        h = factorsNv->h;
+        g = cuddBddAndRecur(dd, x, factorsNv->g);
+        if (g != NULL)  cuddRef(g);
+        Cudd_RecursiveDeref(dd, factorsNv->g); 
+        Cudd_RecursiveDeref(dd, x);
+        if (g == NULL) {
+            Cudd_RecursiveDeref(dd, factorsNv->h); 
+            return NULL;
+        }
+        /* CheckTablesCacheAndReturn responsible for allocating
+         * factors structure., g,h referenced for cache store  the
+         */
+        factors = CheckTablesCacheAndReturn(node,
+                                            g,
+                                            h,
+                                            ghTable,
+                                            cacheTable);
+        if (factors == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            Cudd_RecursiveDeref(dd, g);
+            Cudd_RecursiveDeref(dd, h);
+        }
+        return(factors); 
+    }
+
+    H = Cudd_Regular(factorsNv->h);
+    Hv = cuddT(H);
+    Hnv = cuddE(H);
+    Hv = Cudd_NotCond(Hv, Cudd_IsComplement(node));
+    Hnv = Cudd_NotCond(Hnv, Cudd_IsComplement(node));
+    /* if the child below is a variable */
+    if ((Hv == zero) || (Hnv == zero)) {
+        g = factorsNv->g;
+        h = cuddBddAndRecur(dd, x, factorsNv->h);
+        if (h!= NULL) cuddRef(h);
+        Cudd_RecursiveDeref(dd, factorsNv->h);
+        Cudd_RecursiveDeref(dd, x);
+        if (h == NULL) {
+            Cudd_RecursiveDeref(dd, factorsNv->g);
+            return NULL;
+        }
+        /* CheckTablesCacheAndReturn responsible for allocating
+         * factors structure.g,h referenced for table store 
+         */
+        factors = CheckTablesCacheAndReturn(node,
+                                            g,
+                                            h,
+                                            ghTable,
+                                            cacheTable);
+        if (factors == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            Cudd_RecursiveDeref(dd, g);
+            Cudd_RecursiveDeref(dd, h);
+        }
+        return(factors); 
+    }
+
+    /* build g1 = x*g; h1 = h */
+    /* build g2 = g; h2 = x*h */
+    Cudd_RecursiveDeref(dd, x);
+    h1 = factorsNv->h;
+    g1 = cuddBddAndRecur(dd, x, factorsNv->g);
+    if (g1 != NULL) cuddRef(g1);
+    if (g1 == NULL) {
+        Cudd_RecursiveDeref(dd, factorsNv->g); 
+        Cudd_RecursiveDeref(dd, factorsNv->h);
+        return NULL;
+    }
+    
+    g2 = factorsNv->g;
+    h2 = cuddBddAndRecur(dd, x, factorsNv->h);
+    if (h2 != NULL) cuddRef(h2);
+    if (h2 == NULL) {
+        Cudd_RecursiveDeref(dd, factorsNv->h);
+        Cudd_RecursiveDeref(dd, factorsNv->g);
+        return NULL;
+    }
+
+    /* check whether any pair is in tables */
+    factors = CheckInTables(node, g1, h1, g2, h2, ghTable, cacheTable, &outOfMem);
+    if (outOfMem) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        Cudd_RecursiveDeref(dd, g1);
+        Cudd_RecursiveDeref(dd, h1);
+        Cudd_RecursiveDeref(dd, g2);
+        Cudd_RecursiveDeref(dd, h2);
+        return NULL;
+    }
+    if (factors != NULL) {
+        if ((factors->g == g1) || (factors->g == h1)) {
+            Cudd_RecursiveDeref(dd, g2);
+            Cudd_RecursiveDeref(dd, h2);
+        } else {
+            Cudd_RecursiveDeref(dd, g1);
+            Cudd_RecursiveDeref(dd, h1);
+        }
+        return factors;
+    }
+
+    /* check for each pair in tables and choose one */
+    factors = PickOnePair(node,g1, h1, g2, h2, ghTable, cacheTable);
+    if (factors == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        Cudd_RecursiveDeref(dd, g1);
+        Cudd_RecursiveDeref(dd, h1);
+        Cudd_RecursiveDeref(dd, g2);
+        Cudd_RecursiveDeref(dd, h2);
+    } else {
+        /* now free what was created and not used */
+        if ((factors->g == g1) || (factors->g == h1)) {
+            Cudd_RecursiveDeref(dd, g2);
+            Cudd_RecursiveDeref(dd, h2);
+        } else {
+            Cudd_RecursiveDeref(dd, g1);
+            Cudd_RecursiveDeref(dd, h1);
+        }
+    }
+        
+    return(factors);
+} /* end of ZeroCase */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the conjuncts recursively, bottom up.]
+
+  Description [Builds the conjuncts recursively, bottom up. Constants
+  are returned as (f, f). The cache is checked for previously computed
+  result. The decomposition points are determined by the local
+  reference count of this node and the longest distance from the
+  constant. At the decomposition point, the factors returned are (f,
+  1). Recur on the two children. The order is determined by the
+  heavier branch. Combine the factors of the two children and pick the
+  one that already occurs in the gh table. Occurence in g is indicated
+  by value 1, occurence in h by 2, occurence in both 3.]
+
+  SideEffects []
+
+  SeeAlso     [cuddConjunctsAux]
+
+******************************************************************************/
+static Conjuncts *
+BuildConjuncts(
+  DdManager * dd,
+  DdNode * node,
+  st__table * distanceTable,
+  st__table * cacheTable,
+  int approxDistance,
+  int maxLocalRef,
+  st__table * ghTable,
+  st__table * mintermTable)
+{
+    int topid, distance;
+    Conjuncts *factorsNv = NULL, *factorsNnv = NULL, *factors;
+    Conjuncts *dummy;
+    DdNode *N, *Nv, *Nnv, *temp, *g1, *g2, *h1, *h2, *topv;
+    double minNv = 0.0, minNnv = 0.0;
+    double *doubleDummy;
+    int switched =0;
+    int outOfMem;
+    int freeNv = 0, freeNnv = 0, freeTemp;
+    NodeStat *nodeStat;
+    int value;
+
+    /* if f is constant, return (f,f) */
+    if (Cudd_IsConstant(node)) {
+        factors = ABC_ALLOC(Conjuncts, 1);
+        if (factors == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(NULL);
+        }
+        factors->g = node;
+        factors->h = node;
+        return(FactorsComplement(factors));
+    }
+
+    /* If result (a pair of conjuncts) in cache, return the factors. */
+    if ( st__lookup(cacheTable, (const char *)node, (char **)&dummy)) {
+        factors = dummy;
+        return(factors);
+    }
+    
+    /* check distance and local reference count of this node */
+    N = Cudd_Regular(node);
+    if (! st__lookup(distanceTable, (const char *)N, (char **)&nodeStat)) {
+        (void) fprintf(dd->err, "Not in table, Something wrong\n");
+        dd->errorCode = CUDD_INTERNAL_ERROR;
+        return(NULL);
+    }
+    distance = nodeStat->distance;
+
+    /* at or below decomposition point, return (f, 1) */
+    if (((nodeStat->localRef > maxLocalRef*2/3) &&
+         (distance < approxDistance*2/3)) ||
+            (distance <= approxDistance/4)) {
+        factors = ABC_ALLOC(Conjuncts, 1);
+        if (factors == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(NULL);
+        }
+        /* alternate assigning (f,1) */
+        value = 0;
+        if ( st__lookup_int(ghTable, (char *)Cudd_Regular(node), &value)) {
+            if (value == 3) {
+                if (!lastTimeG) {
+                    factors->g = node;
+                    factors->h = one;
+                    lastTimeG = 1;
+                } else {
+                    factors->g = one;
+                    factors->h = node;
+                    lastTimeG = 0; 
+                }
+            } else if (value == 1) {
+                factors->g = node;
+                factors->h = one;
+            } else {
+                factors->g = one;
+                factors->h = node;
+            }
+        } else if (!lastTimeG) {
+            factors->g = node;
+            factors->h = one;
+            lastTimeG = 1;
+            value = 1;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(node), (char *)(long)value) == st__OUT_OF_MEM) {
+                dd->errorCode = CUDD_MEMORY_OUT;
+                ABC_FREE(factors);
+                return NULL;
+            }
+        } else {
+            factors->g = one;
+            factors->h = node;
+            lastTimeG = 0;
+            value = 2;
+            if ( st__insert(ghTable, (char *)Cudd_Regular(node), (char *)(long)value) == st__OUT_OF_MEM) {
+                dd->errorCode = CUDD_MEMORY_OUT;
+                ABC_FREE(factors);
+                return NULL;
+            }
+        }
+        return(FactorsComplement(factors));
+    }
+    
+    /* get the children and recur */
+    Nv = cuddT(N);
+    Nnv = cuddE(N);
+    Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
+    Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
+
+    /* Choose which subproblem to solve first based on the number of
+     * minterms. We go first where there are more minterms.
+     */
+    if (!Cudd_IsConstant(Nv)) {
+        if (! st__lookup(mintermTable, (const char *)Nv, (char **)&doubleDummy)) {
+            (void) fprintf(dd->err, "Not in table: Something wrong\n");
+            dd->errorCode = CUDD_INTERNAL_ERROR;
+            return(NULL);
+        }
+        minNv = *doubleDummy;
+    }
+    
+    if (!Cudd_IsConstant(Nnv)) {
+        if (! st__lookup(mintermTable, (const char *)Nnv, (char **)&doubleDummy)) {
+            (void) fprintf(dd->err, "Not in table: Something wrong\n");
+            dd->errorCode = CUDD_INTERNAL_ERROR;
+            return(NULL);
+        }
+        minNnv = *doubleDummy;
+    }
+    
+    if (minNv < minNnv) {
+        temp = Nv;
+        Nv = Nnv;
+        Nnv = temp;
+        switched = 1;
+    }
+
+    /* build gt, ht recursively */
+    if (Nv != zero) {
+        factorsNv = BuildConjuncts(dd, Nv, distanceTable,
+                                   cacheTable, approxDistance, maxLocalRef, 
+                                   ghTable, mintermTable);
+        if (factorsNv == NULL) return(NULL);
+        freeNv = FactorsNotStored(factorsNv);
+        factorsNv = (freeNv) ? FactorsUncomplement(factorsNv) : factorsNv;
+        cuddRef(factorsNv->g);
+        cuddRef(factorsNv->h);
+        
+        /* Deal with the zero case */
+        if (Nnv == zero) {
+            /* is responsible for freeing factorsNv */
+            factors = ZeroCase(dd, node, factorsNv, ghTable,
+                               cacheTable, switched);
+            if (freeNv) ABC_FREE(factorsNv);
+            return(factors);
+        }
+    }
+
+    /* build ge, he recursively */
+    if (Nnv != zero) {
+        factorsNnv = BuildConjuncts(dd, Nnv, distanceTable,
+                                    cacheTable, approxDistance, maxLocalRef,
+                                    ghTable, mintermTable);
+        if (factorsNnv == NULL) {
+            Cudd_RecursiveDeref(dd, factorsNv->g);
+            Cudd_RecursiveDeref(dd, factorsNv->h);
+            if (freeNv) ABC_FREE(factorsNv);
+            return(NULL);
+        }
+        freeNnv = FactorsNotStored(factorsNnv);
+        factorsNnv = (freeNnv) ? FactorsUncomplement(factorsNnv) : factorsNnv;
+        cuddRef(factorsNnv->g);
+        cuddRef(factorsNnv->h);
+        
+        /* Deal with the zero case */
+        if (Nv == zero) {
+            /* is responsible for freeing factorsNv */
+            factors = ZeroCase(dd, node, factorsNnv, ghTable,
+                               cacheTable, switched);
+            if (freeNnv) ABC_FREE(factorsNnv);
+            return(factors);
+        }
+    }
+
+    /* construct the 2 pairs */
+    /* g1 = x*gt + x'*ge; h1 = x*ht + x'*he; */
+    /* g2 = x*gt + x'*he; h2 = x*ht + x'*ge */
+    if (switched) {
+        factors = factorsNnv;
+        factorsNnv = factorsNv;
+        factorsNv = factors;
+        freeTemp = freeNv;
+        freeNv = freeNnv;
+        freeNnv = freeTemp;
+    }
+
+    /* Build the factors for this node. */
+    topid = N->index;
+    topv = dd->vars[topid];
+    
+    g1 = cuddBddIteRecur(dd, topv, factorsNv->g, factorsNnv->g);
+    if (g1 == NULL) {
+        Cudd_RecursiveDeref(dd, factorsNv->g);
+        Cudd_RecursiveDeref(dd, factorsNv->h);
+        Cudd_RecursiveDeref(dd, factorsNnv->g);
+        Cudd_RecursiveDeref(dd, factorsNnv->h);
+        if (freeNv) ABC_FREE(factorsNv);
+        if (freeNnv) ABC_FREE(factorsNnv);
+        return(NULL);
+    }
+
+    cuddRef(g1);
+
+    h1 = cuddBddIteRecur(dd, topv, factorsNv->h, factorsNnv->h);
+    if (h1 == NULL) {
+        Cudd_RecursiveDeref(dd, factorsNv->g);
+        Cudd_RecursiveDeref(dd, factorsNv->h);
+        Cudd_RecursiveDeref(dd, factorsNnv->g);
+        Cudd_RecursiveDeref(dd, factorsNnv->h);
+        Cudd_RecursiveDeref(dd, g1);
+        if (freeNv) ABC_FREE(factorsNv);
+        if (freeNnv) ABC_FREE(factorsNnv);
+        return(NULL);
+    }
+
+    cuddRef(h1);
+
+    g2 = cuddBddIteRecur(dd, topv, factorsNv->g, factorsNnv->h);
+    if (g2 == NULL) {
+        Cudd_RecursiveDeref(dd, factorsNv->h);
+        Cudd_RecursiveDeref(dd, factorsNv->g);
+        Cudd_RecursiveDeref(dd, factorsNnv->g);
+        Cudd_RecursiveDeref(dd, factorsNnv->h);
+        Cudd_RecursiveDeref(dd, g1);
+        Cudd_RecursiveDeref(dd, h1);
+        if (freeNv) ABC_FREE(factorsNv);
+        if (freeNnv) ABC_FREE(factorsNnv);
+        return(NULL);
+    }
+    cuddRef(g2);
+    Cudd_RecursiveDeref(dd, factorsNv->g);
+    Cudd_RecursiveDeref(dd, factorsNnv->h);
+
+    h2 = cuddBddIteRecur(dd, topv, factorsNv->h, factorsNnv->g);
+    if (h2 == NULL) {
+        Cudd_RecursiveDeref(dd, factorsNv->g);
+        Cudd_RecursiveDeref(dd, factorsNv->h);
+        Cudd_RecursiveDeref(dd, factorsNnv->g);
+        Cudd_RecursiveDeref(dd, factorsNnv->h);
+        Cudd_RecursiveDeref(dd, g1);
+        Cudd_RecursiveDeref(dd, h1);
+        Cudd_RecursiveDeref(dd, g2);
+        if (freeNv) ABC_FREE(factorsNv);
+        if (freeNnv) ABC_FREE(factorsNnv);
+        return(NULL);
+    }
+    cuddRef(h2);
+    Cudd_RecursiveDeref(dd, factorsNv->h);
+    Cudd_RecursiveDeref(dd, factorsNnv->g);
+    if (freeNv) ABC_FREE(factorsNv);
+    if (freeNnv) ABC_FREE(factorsNnv);
+
+    /* check for each pair in tables and choose one */
+    factors = CheckInTables(node, g1, h1, g2, h2, ghTable, cacheTable, &outOfMem);
+    if (outOfMem) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        Cudd_RecursiveDeref(dd, g1);
+        Cudd_RecursiveDeref(dd, h1);
+        Cudd_RecursiveDeref(dd, g2);
+        Cudd_RecursiveDeref(dd, h2);
+        return(NULL);
+    }
+    if (factors != NULL) {
+        if ((factors->g == g1) || (factors->g == h1)) {
+            Cudd_RecursiveDeref(dd, g2);
+            Cudd_RecursiveDeref(dd, h2);
+        } else {
+            Cudd_RecursiveDeref(dd, g1);
+            Cudd_RecursiveDeref(dd, h1);
+        }
+        return(factors);
+    }
+
+    /* if not in tables, pick one pair */
+    factors = PickOnePair(node,g1, h1, g2, h2, ghTable, cacheTable);
+    if (factors == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        Cudd_RecursiveDeref(dd, g1);
+        Cudd_RecursiveDeref(dd, h1);
+        Cudd_RecursiveDeref(dd, g2);
+        Cudd_RecursiveDeref(dd, h2);
+    } else {
+        /* now free what was created and not used */
+        if ((factors->g == g1) || (factors->g == h1)) {
+            Cudd_RecursiveDeref(dd, g2);
+            Cudd_RecursiveDeref(dd, h2);
+        } else {
+            Cudd_RecursiveDeref(dd, g1);
+            Cudd_RecursiveDeref(dd, h1);
+        }
+    }
+        
+    return(factors);
+    
+} /* end of BuildConjuncts */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Procedure to compute two conjunctive factors of f and place in *c1 and *c2.]
+
+  Description [Procedure to compute two conjunctive factors of f and
+  place in *c1 and *c2. Sets up the required data - table of distances
+  from the constant and local reference count. Also minterm table. ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddConjunctsAux(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** c1,
+  DdNode ** c2)
+{
+    st__table *distanceTable = NULL;
+    st__table *cacheTable = NULL;
+    st__table *mintermTable = NULL;
+    st__table *ghTable = NULL;
+    st__generator *stGen;
+    char *key, *value;
+    Conjuncts *factors;
+    int distance, approxDistance;
+    double max, minterms;
+    int freeFactors;
+    NodeStat *nodeStat;
+    int maxLocalRef;
+    
+    /* initialize */
+    *c1 = NULL;
+    *c2 = NULL;
+
+    /* initialize distances table */
+    distanceTable = st__init_table( st__ptrcmp, st__ptrhash);
+    if (distanceTable == NULL) goto outOfMem;
+    
+    /* make the entry for the constant */
+    nodeStat = ABC_ALLOC(NodeStat, 1);
+    if (nodeStat == NULL) goto outOfMem;
+    nodeStat->distance = 0;
+    nodeStat->localRef = 1;
+    if ( st__insert(distanceTable, (char *)one, (char *)nodeStat) == st__OUT_OF_MEM) {
+        goto outOfMem;
+    }
+
+    /* Count node distances from constant. */
+    nodeStat = CreateBotDist(f, distanceTable);
+    if (nodeStat == NULL) goto outOfMem;
+
+    /* set the distance for the decomposition points */
+    approxDistance = (DEPTH < nodeStat->distance) ? nodeStat->distance : DEPTH;
+    distance = nodeStat->distance;
+
+    if (distance < approxDistance) {
+        /* Too small to bother. */
+        *c1 = f;
+        *c2 = DD_ONE(dd);
+        cuddRef(*c1); cuddRef(*c2);
+        stGen = st__init_gen(distanceTable);
+        if (stGen == NULL) goto outOfMem;
+        while( st__gen(stGen, (const char **)&key, (char **)&value)) {
+            ABC_FREE(value);
+        }
+        st__free_gen(stGen); stGen = NULL;
+        st__free_table(distanceTable);
+        return(1);
+    }
+
+    /* record the maximum local reference count */
+    maxLocalRef = 0;
+    stGen = st__init_gen(distanceTable);
+    if (stGen == NULL) goto outOfMem;
+    while( st__gen(stGen, (const char **)&key, (char **)&value)) {
+        nodeStat = (NodeStat *)value;
+        maxLocalRef = (nodeStat->localRef > maxLocalRef) ?
+            nodeStat->localRef : maxLocalRef;
+    }
+    st__free_gen(stGen); stGen = NULL;
+
+            
+    /* Count minterms for each node. */
+    max = pow(2.0, (double)Cudd_SupportSize(dd,f)); /* potential overflow */
+    mintermTable = st__init_table( st__ptrcmp, st__ptrhash);
+    if (mintermTable == NULL) goto outOfMem;
+    minterms = CountMinterms(f, max, mintermTable, dd->err);
+    if (minterms == -1.0) goto outOfMem;
+    
+    lastTimeG = Cudd_Random() & 1;
+    cacheTable = st__init_table( st__ptrcmp, st__ptrhash);
+    if (cacheTable == NULL) goto outOfMem;
+    ghTable = st__init_table( st__ptrcmp, st__ptrhash);
+    if (ghTable == NULL) goto outOfMem;
+
+    /* Build conjuncts. */
+    factors = BuildConjuncts(dd, f, distanceTable, cacheTable,
+                             approxDistance, maxLocalRef, ghTable, mintermTable);
+    if (factors == NULL) goto outOfMem;
+
+    /* free up tables */
+    stGen = st__init_gen(distanceTable);
+    if (stGen == NULL) goto outOfMem;
+    while( st__gen(stGen, (const char **)&key, (char **)&value)) {
+        ABC_FREE(value);
+    }
+    st__free_gen(stGen); stGen = NULL;
+    st__free_table(distanceTable); distanceTable = NULL;
+    st__free_table(ghTable); ghTable = NULL;
+    
+    stGen = st__init_gen(mintermTable);
+    if (stGen == NULL) goto outOfMem;
+    while( st__gen(stGen, (const char **)&key, (char **)&value)) {
+        ABC_FREE(value);
+    }
+    st__free_gen(stGen); stGen = NULL;
+    st__free_table(mintermTable); mintermTable = NULL;
+
+    freeFactors = FactorsNotStored(factors);
+    factors = (freeFactors) ? FactorsUncomplement(factors) : factors;
+    if (factors != NULL) {
+        *c1 = factors->g;
+        *c2 = factors->h;
+        cuddRef(*c1);
+        cuddRef(*c2);
+        if (freeFactors) ABC_FREE(factors);
+        
+#if 0    
+        if ((*c1 == f) && (!Cudd_IsConstant(f))) {
+            assert(*c2 == one);
+        }
+        if ((*c2 == f) && (!Cudd_IsConstant(f))) {
+            assert(*c1 == one);
+        }
+        
+        if ((*c1 != one) && (!Cudd_IsConstant(f))) {
+            assert(!Cudd_bddLeq(dd, *c2, *c1));
+        }
+        if ((*c2 != one) && (!Cudd_IsConstant(f))) {
+            assert(!Cudd_bddLeq(dd, *c1, *c2));
+        }
+#endif
+    }
+
+    stGen = st__init_gen(cacheTable);
+    if (stGen == NULL) goto outOfMem;
+    while( st__gen(stGen, (const char **)&key, (char **)&value)) {
+        ConjunctsFree(dd, (Conjuncts *)value);
+    }
+    st__free_gen(stGen); stGen = NULL;
+
+    st__free_table(cacheTable); cacheTable = NULL;
+
+    return(1);
+
+outOfMem:
+    if (distanceTable != NULL) {
+        stGen = st__init_gen(distanceTable);
+        if (stGen == NULL) goto outOfMem;
+        while( st__gen(stGen, (const char **)&key, (char **)&value)) {
+            ABC_FREE(value);
+        }
+        st__free_gen(stGen); stGen = NULL;
+        st__free_table(distanceTable); distanceTable = NULL;
+    }
+    if (mintermTable != NULL) {
+        stGen = st__init_gen(mintermTable);
+        if (stGen == NULL) goto outOfMem;
+        while( st__gen(stGen, (const char **)&key, (char **)&value)) {
+            ABC_FREE(value);
+        }
+        st__free_gen(stGen); stGen = NULL;
+        st__free_table(mintermTable); mintermTable = NULL;
+    }
+    if (ghTable != NULL) st__free_table(ghTable);
+    if (cacheTable != NULL) {
+        stGen = st__init_gen(cacheTable);
+        if (stGen == NULL) goto outOfMem;
+        while( st__gen(stGen, (const char **)&key, (char **)&value)) {
+            ConjunctsFree(dd, (Conjuncts *)value);
+        }
+        st__free_gen(stGen); stGen = NULL;
+        st__free_table(cacheTable); cacheTable = NULL;
+    }
+    dd->errorCode = CUDD_MEMORY_OUT;
+    return(0);
+
+} /* end of cuddConjunctsAux */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddEssent.c b/abc-build/src/bdd/cudd/cuddEssent.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddEssent.c
@@ -0,0 +1,1475 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddEssent.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for the detection of essential variables.]
+
+  Description [External procedures included in this file:
+                <ul>
+                <li> Cudd_FindEssential()
+                <li> Cudd_bddIsVarEssential()
+                <li> Cudd_FindTwoLiteralClauses()
+                <li> Cudd_ReadIthClause()
+                <li> Cudd_PrintTwoLiteralClauses()
+                <li> Cudd_tlcInfoFree()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> ddFindEssentialRecur()
+                <li> ddFindTwoLiteralClausesRecur()
+                <li> computeClauses()
+                <li> computeClausesWithUniverse()
+                <li> emptyClauseSet()
+                <li> sentinelp()
+                <li> equalp()
+                <li> beforep()
+                <li> oneliteralp()
+                <li> impliedp()
+                <li> bitVectorAlloc()
+                <li> bitVectorClear()
+                <li> bitVectorFree()
+                <li> bitVectorRead()
+                <li> bitVectorSet()
+                <li> tlcInfoAlloc()
+                </ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* These definitions are for the bit vectors. */
+#if SIZEOF_LONG == 8
+#define BPL 64
+#define LOGBPL 6
+#else
+#define BPL 32
+#define LOGBPL 5
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* This structure holds the set of clauses for a node.  Each clause consists
+** of two literals.  For one-literal clauses, the second lietral is FALSE.
+** Each literal is composed of a variable and a phase.  A variable is a node
+** index, and requires sizeof(DdHalfWord) bytes.  The constant literals use
+** CUDD_MAXINDEX as variable indicator.  Each phase is a bit: 0 for positive
+** phase, and 1 for negative phase.
+** Variables and phases are stored separately for the sake of compactness.
+** The variables are stored in an array of DdHalfWord's terminated by a
+** sentinel (a pair of zeroes).  The phases are stored in a bit vector.
+** The cnt field holds, at the end, the number of clauses.
+** The clauses of the set are kept sorted.  For each clause, the first literal
+** is the one of least index.  So, the clause with literals +2 and -4 is stored
+** as (+2,-4).  A one-literal clause with literal +3 is stored as
+** (+3,-CUDD_MAXINDEX).  Clauses are sorted in decreasing order as follows:
+**      (+5,-7)
+**      (+5,+6)
+**      (-5,+7)
+**      (-4,FALSE)
+**      (-4,+8)
+**      ...
+** That is, one first looks at the variable of the first literal, then at the
+** phase of the first litral, then at the variable of the second literal,
+** and finally at the phase of the second literal.
+*/
+struct DdTlcInfo {
+    DdHalfWord *vars;
+    long *phases;
+    DdHalfWord cnt;
+};
+
+/* This structure is for temporary representation of sets of clauses.  It is
+** meant to be used in link lists, when the number of clauses is not yet
+** known. The encoding of a clause is the same as in DdTlcInfo, though
+** the phase information is not stored in a bit array. */
+struct TlClause {
+    DdHalfWord v1, v2;
+    short p1, p2;
+    struct TlClause *next;
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef long BitVector;
+typedef struct TlClause TlClause;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddEssent.c,v 1.24 2009/02/21 18:24:10 fabio Exp $";
+#endif
+
+static BitVector *Tolv;
+static BitVector *Tolp;
+static BitVector *Eolv;
+static BitVector *Eolp;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * ddFindEssentialRecur (DdManager *dd, DdNode *f);
+static DdTlcInfo * ddFindTwoLiteralClausesRecur (DdManager * dd, DdNode * f, st__table *table);
+static DdTlcInfo * computeClauses (DdTlcInfo *Tres, DdTlcInfo *Eres, DdHalfWord label, int size);
+static DdTlcInfo * computeClausesWithUniverse (DdTlcInfo *Cres, DdHalfWord label, short phase);
+static DdTlcInfo * emptyClauseSet (void);
+static int sentinelp (DdHalfWord var1, DdHalfWord var2);
+static int equalp (DdHalfWord var1a, short phase1a, DdHalfWord var1b, short phase1b, DdHalfWord var2a, short phase2a, DdHalfWord var2b, short phase2b);
+static int beforep (DdHalfWord var1a, short phase1a, DdHalfWord var1b, short phase1b, DdHalfWord var2a, short phase2a, DdHalfWord var2b, short phase2b);
+static int oneliteralp (DdHalfWord var);
+static int impliedp (DdHalfWord var1, short phase1, DdHalfWord var2, short phase2, BitVector *olv, BitVector *olp);
+static BitVector * bitVectorAlloc (int size);
+DD_INLINE static void bitVectorClear (BitVector *vector, int size);
+static void bitVectorFree (BitVector *vector);
+DD_INLINE static short bitVectorRead (BitVector *vector, int i);
+DD_INLINE static void bitVectorSet (BitVector * vector, int i, short val);
+static DdTlcInfo * tlcInfoAlloc (void);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the essential variables of a DD.]
+
+  Description [Returns the cube of the essential variables. A positive
+  literal means that the variable must be set to 1 for the function to be
+  1. A negative literal means that the variable must be set to 0 for the
+  function to be 1. Returns a pointer to the cube BDD if successful;
+  NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIsVarEssential]
+
+******************************************************************************/
+DdNode *
+Cudd_FindEssential(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = ddFindEssentialRecur(dd,f);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_FindEssential */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Determines whether a given variable is essential with a
+  given phase in a BDD.]
+
+  Description [Determines whether a given variable is essential with a
+  given phase in a BDD. Uses Cudd_bddIteConstant. Returns 1 if phase == 1
+  and f-->x_id, or if phase == 0 and f-->x_id'.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_FindEssential]
+
+******************************************************************************/
+int
+Cudd_bddIsVarEssential(
+  DdManager * manager,
+  DdNode * f,
+  int  id,
+  int  phase)
+{
+    DdNode      *var;
+    int         res;
+
+    var = Cudd_bddIthVar(manager, id);
+
+    var = Cudd_NotCond(var,phase == 0);
+
+    res = Cudd_bddLeq(manager, f, var);
+
+    return(res);
+
+} /* end of Cudd_bddIsVarEssential */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the two literal clauses of a DD.]
+
+  Description [Returns the one- and two-literal clauses of a DD.
+  Returns a pointer to the structure holding the clauses if
+  successful; NULL otherwise.  For a constant DD, the empty set of clauses
+  is returned.  This is obviously correct for a non-zero constant.  For the
+  constant zero, it is based on the assumption that only those clauses
+  containing variables in the support of the function are considered.  Since
+  the support of a constant function is empty, no clauses are returned.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_FindEssential]
+
+******************************************************************************/
+DdTlcInfo *
+Cudd_FindTwoLiteralClauses(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdTlcInfo *res;
+    st__table *table;
+    st__generator *gen;
+    DdTlcInfo *tlc;
+    DdNode *node;
+    int size = dd->size;
+
+    if (Cudd_IsConstant(f)) {
+        res = emptyClauseSet();
+        return(res);
+    }
+    table = st__init_table( st__ptrcmp, st__ptrhash);
+    if (table == NULL) return(NULL);
+    Tolv = bitVectorAlloc(size);
+    if (Tolv == NULL) {
+        st__free_table(table);
+        return(NULL);
+    }
+    Tolp = bitVectorAlloc(size);
+    if (Tolp == NULL) {
+        st__free_table(table);
+        bitVectorFree(Tolv);
+        return(NULL);
+    }
+    Eolv = bitVectorAlloc(size);
+    if (Eolv == NULL) {
+        st__free_table(table);
+        bitVectorFree(Tolv);
+        bitVectorFree(Tolp);
+        return(NULL);
+    }
+    Eolp = bitVectorAlloc(size);
+    if (Eolp == NULL) {
+        st__free_table(table);
+        bitVectorFree(Tolv);
+        bitVectorFree(Tolp);
+        bitVectorFree(Eolv);
+        return(NULL);
+    }
+
+    res = ddFindTwoLiteralClausesRecur(dd,f,table);
+    /* Dispose of table contents and free table. */
+    st__foreach_item(table, gen, (const char **)&node, (char **)&tlc) {
+        if (node != f) {
+            Cudd_tlcInfoFree(tlc);
+        }
+    }
+    st__free_table(table);
+    bitVectorFree(Tolv);
+    bitVectorFree(Tolp);
+    bitVectorFree(Eolv);
+    bitVectorFree(Eolp);
+
+    if (res != NULL) {
+        int i;
+        for (i = 0; !sentinelp(res->vars[i], res->vars[i+1]); i += 2);
+        res->cnt = i >> 1;
+    }
+
+    return(res);
+
+} /* end of Cudd_FindTwoLiteralClauses */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Accesses the i-th clause of a DD.]
+
+  Description [Accesses the i-th clause of a DD given the clause set which
+  must be already computed.  Returns 1 if successful; 0 if i is out of range,
+  or in case of error.]
+
+  SideEffects [the four components of a clause are returned as side effects.]
+
+  SeeAlso     [Cudd_FindTwoLiteralClauses]
+
+******************************************************************************/
+int
+Cudd_ReadIthClause(
+  DdTlcInfo * tlc,
+  int i,
+  DdHalfWord *var1,
+  DdHalfWord *var2,
+  int *phase1,
+  int *phase2)
+{
+    if (tlc == NULL) return(0);
+    if (tlc->vars == NULL || tlc->phases == NULL) return(0);
+    if (i < 0 || (unsigned) i >= tlc->cnt) return(0);
+    *var1 = tlc->vars[2*i];
+    *var2 = tlc->vars[2*i+1];
+    *phase1 = (int) bitVectorRead(tlc->phases, 2*i);
+    *phase2 = (int) bitVectorRead(tlc->phases, 2*i+1);
+    return(1);
+
+} /* end of Cudd_ReadIthClause */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the two literal clauses of a DD.]
+
+  Description [Prints the one- and two-literal clauses. Returns 1 if
+  successful; 0 otherwise.  The argument "names" can be NULL, in which case
+  the variable indices are printed.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_FindTwoLiteralClauses]
+
+******************************************************************************/
+int
+Cudd_PrintTwoLiteralClauses(
+  DdManager * dd,
+  DdNode * f,
+  char **names,
+  FILE *fp)
+{
+    DdHalfWord *vars;
+    BitVector *phases;
+    int i;
+    DdTlcInfo *res = Cudd_FindTwoLiteralClauses(dd, f);
+    FILE *ifp = fp == NULL ? dd->out : fp;
+
+    if (res == NULL) return(0);
+    vars = res->vars;
+    phases = res->phases;
+    for (i = 0; !sentinelp(vars[i], vars[i+1]); i += 2) {
+        if (names != NULL) {
+            if (vars[i+1] == CUDD_MAXINDEX) {
+                (void) fprintf(ifp, "%s%s\n",
+                               bitVectorRead(phases, i) ? "~" : " ",
+                               names[vars[i]]);
+            } else {
+                (void) fprintf(ifp, "%s%s | %s%s\n",
+                               bitVectorRead(phases, i) ? "~" : " ",
+                               names[vars[i]],
+                               bitVectorRead(phases, i+1) ? "~" : " ",
+                               names[vars[i+1]]);
+            }
+        } else {
+            if (vars[i+1] == CUDD_MAXINDEX) {
+                (void) fprintf(ifp, "%s%d\n",
+                               bitVectorRead(phases, i) ? "~" : " ",
+                               (int) vars[i]);
+            } else {
+                (void) fprintf(ifp, "%s%d | %s%d\n",
+                               bitVectorRead(phases, i) ? "~" : " ",
+                               (int) vars[i],
+                               bitVectorRead(phases, i+1) ? "~" : " ",
+                               (int) vars[i+1]);
+            }
+        }
+    }
+    Cudd_tlcInfoFree(res);
+
+    return(1);
+
+} /* end of Cudd_PrintTwoLiteralClauses */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a DdTlcInfo Structure.]
+
+  Description [Frees a DdTlcInfo Structure as well as the memory pointed
+  by it.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_tlcInfoFree(
+  DdTlcInfo * t)
+{
+    if (t->vars != NULL) ABC_FREE(t->vars);
+    if (t->phases != NULL) ABC_FREE(t->phases);
+    ABC_FREE(t);
+
+} /* end of Cudd_tlcInfoFree */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_FindEssential.]
+
+  Description [Implements the recursive step of Cudd_FindEssential.
+  Returns a pointer to the cube BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static DdNode *
+ddFindEssentialRecur(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode      *T, *E, *F;
+    DdNode      *essT, *essE, *res;
+    int         index;
+    DdNode      *one, *lzero, *azero;
+
+    one = DD_ONE(dd);
+    F = Cudd_Regular(f);
+    /* If f is constant the set of essential variables is empty. */
+    if (cuddIsConstant(F)) return(one);
+
+    res = cuddCacheLookup1(dd,Cudd_FindEssential,f);
+    if (res != NULL) {
+        return(res);
+    }
+
+    lzero = Cudd_Not(one);
+    azero = DD_ZERO(dd);
+    /* Find cofactors: here f is non-constant. */
+    T = cuddT(F);
+    E = cuddE(F);
+    if (Cudd_IsComplement(f)) {
+        T = Cudd_Not(T); E = Cudd_Not(E);
+    }
+
+    index = F->index;
+    if (Cudd_IsConstant(T) && T != lzero && T != azero) {
+        /* if E is zero, index is essential, otherwise there are no
+        ** essentials, because index is not essential and no other variable
+        ** can be, since setting index = 1 makes the function constant and
+        ** different from 0.
+        */
+        if (E == lzero || E == azero) {
+            res = dd->vars[index];
+        } else {
+            res = one;
+        }
+    } else if (T == lzero || T == azero) {
+        if (Cudd_IsConstant(E)) { /* E cannot be zero here */
+            res = Cudd_Not(dd->vars[index]);
+        } else { /* E == non-constant */
+            /* find essentials in the else branch */
+            essE = ddFindEssentialRecur(dd,E);
+            if (essE == NULL) {
+                return(NULL);
+            }
+            cuddRef(essE);
+
+            /* add index to the set with negative phase */
+            res = cuddUniqueInter(dd,index,one,Cudd_Not(essE));
+            if (res == NULL) {
+                Cudd_RecursiveDeref(dd,essE);
+                return(NULL);
+            }
+            res = Cudd_Not(res);
+            cuddDeref(essE);
+        }
+    } else { /* T == non-const */
+        if (E == lzero || E == azero) {
+            /* find essentials in the then branch */
+            essT = ddFindEssentialRecur(dd,T);
+            if (essT == NULL) {
+                return(NULL);
+            }
+            cuddRef(essT);
+
+            /* add index to the set with positive phase */
+            /* use And because essT may be complemented */
+            res = cuddBddAndRecur(dd,dd->vars[index],essT);
+            if (res == NULL) {
+                Cudd_RecursiveDeref(dd,essT);
+                return(NULL);
+            }
+            cuddDeref(essT);
+        } else if (!Cudd_IsConstant(E)) {
+            /* if E is a non-zero constant there are no essentials
+            ** because T is non-constant.
+            */
+            essT = ddFindEssentialRecur(dd,T);
+            if (essT == NULL) {
+                return(NULL);
+            }
+            if (essT == one) {
+                res = one;
+            } else {
+                cuddRef(essT);
+                essE = ddFindEssentialRecur(dd,E);
+                if (essE == NULL) {
+                    Cudd_RecursiveDeref(dd,essT);
+                    return(NULL);
+                }
+                cuddRef(essE);
+
+                /* res = intersection(essT, essE) */
+                res = cuddBddLiteralSetIntersectionRecur(dd,essT,essE);
+                if (res == NULL) {
+                    Cudd_RecursiveDeref(dd,essT);
+                    Cudd_RecursiveDeref(dd,essE);
+                    return(NULL);
+                }
+                cuddRef(res);
+                Cudd_RecursiveDeref(dd,essT);
+                Cudd_RecursiveDeref(dd,essE);
+                cuddDeref(res);
+            }
+        } else {        /* E is a non-zero constant */
+            res = one;
+        }
+    }
+
+    cuddCacheInsert1(dd,Cudd_FindEssential, f, res);
+    return(res);
+
+} /* end of ddFindEssentialRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_FindTwoLiteralClauses.]
+
+  Description [Implements the recursive step of
+  Cudd_FindTwoLiteralClauses.  The DD node is assumed to be not
+  constant.  Returns a pointer to a set of clauses if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_FindTwoLiteralClauses]
+
+******************************************************************************/
+static DdTlcInfo *
+ddFindTwoLiteralClausesRecur(
+  DdManager * dd,
+  DdNode * f,
+  st__table *table)
+{
+    DdNode *T, *E, *F;
+    DdNode *one, *lzero, *azero;
+    DdTlcInfo *res, *Tres, *Eres;
+    DdHalfWord index;
+
+    F = Cudd_Regular(f);
+
+    assert(!cuddIsConstant(F));
+
+    /* Check computed table.  Separate entries are necessary for
+    ** a node and its complement.  We should update the counter here. */
+    if ( st__lookup(table, (const char *)f, (char **)&res)) {
+        return(res);
+    }
+
+    /* Easy access to the constants for BDDs and ADDs. */
+    one = DD_ONE(dd);
+    lzero = Cudd_Not(one);
+    azero = DD_ZERO(dd);
+
+    /* Find cofactors and variable labeling the top node. */
+    T = cuddT(F); E = cuddE(F);
+    if (Cudd_IsComplement(f)) {
+        T = Cudd_Not(T); E = Cudd_Not(E);
+    }
+    index = F->index;
+
+    if (Cudd_IsConstant(T) && T != lzero && T != azero) {
+        /* T is a non-zero constant.  If E is zero, then this node's index
+        ** is a one-literal clause.  Otherwise, if E is a non-zero
+        ** constant, there are no clauses for this node.  Finally,
+        ** if E is not constant, we recursively compute its clauses, and then
+        ** merge using the empty set for T. */
+        if (E == lzero || E == azero) {
+            /* Create the clause (index + 0). */
+            res = tlcInfoAlloc();
+            if (res == NULL) return(NULL);
+            res->vars = ABC_ALLOC(DdHalfWord,4);
+            if (res->vars == NULL) {
+                ABC_FREE(res);
+                return(NULL);
+            }
+            res->phases = bitVectorAlloc(2);
+            if (res->phases == NULL) {
+                ABC_FREE(res->vars);
+                ABC_FREE(res);
+                return(NULL);
+            }
+            res->vars[0] = index;
+            res->vars[1] = CUDD_MAXINDEX;
+            res->vars[2] = 0;
+            res->vars[3] = 0;
+            bitVectorSet(res->phases, 0, 0); /* positive phase */
+            bitVectorSet(res->phases, 1, 1); /* negative phase */
+        } else if (Cudd_IsConstant(E)) {
+            /* If E is a non-zero constant, no clauses. */
+            res = emptyClauseSet();
+        } else {
+            /* E is non-constant */
+            Tres = emptyClauseSet();
+            if (Tres == NULL) return(NULL);
+            Eres = ddFindTwoLiteralClausesRecur(dd, E, table);
+            if (Eres == NULL) {
+                Cudd_tlcInfoFree(Tres);
+                return(NULL);
+            }
+            res = computeClauses(Tres, Eres, index, dd->size);
+            Cudd_tlcInfoFree(Tres);
+        }
+    } else if (T == lzero || T == azero) {
+        /* T is zero.  If E is a non-zero constant, then the
+        ** complement of this node's index is a one-literal clause.
+        ** Otherwise, if E is not constant, we recursively compute its
+        ** clauses, and then merge using the universal set for T. */
+        if (Cudd_IsConstant(E)) { /* E cannot be zero here */
+            /* Create the clause (!index + 0). */
+            res = tlcInfoAlloc();
+            if (res == NULL) return(NULL);
+            res->vars = ABC_ALLOC(DdHalfWord,4);
+            if (res->vars == NULL) {
+                ABC_FREE(res);
+                return(NULL);
+            }
+            res->phases = bitVectorAlloc(2);
+            if (res->phases == NULL) {
+                ABC_FREE(res->vars);
+                ABC_FREE(res);
+                return(NULL);
+            }
+            res->vars[0] = index;
+            res->vars[1] = CUDD_MAXINDEX;
+            res->vars[2] = 0;
+            res->vars[3] = 0;
+            bitVectorSet(res->phases, 0, 1); /* negative phase */
+            bitVectorSet(res->phases, 1, 1); /* negative phase */
+        } else { /* E == non-constant */
+            Eres = ddFindTwoLiteralClausesRecur(dd, E, table);
+            if (Eres == NULL) return(NULL);
+            res = computeClausesWithUniverse(Eres, index, 1);
+        }
+    } else { /* T == non-const */
+        Tres = ddFindTwoLiteralClausesRecur(dd, T, table);
+        if (Tres == NULL) return(NULL);
+        if (Cudd_IsConstant(E)) {
+            if (E == lzero || E == azero) {
+                res = computeClausesWithUniverse(Tres, index, 0);
+            } else {
+                Eres = emptyClauseSet();
+                if (Eres == NULL) return(NULL);
+                res = computeClauses(Tres, Eres, index, dd->size);
+                Cudd_tlcInfoFree(Eres);
+            }
+        } else {
+            Eres = ddFindTwoLiteralClausesRecur(dd, E, table);
+            if (Eres == NULL) return(NULL);
+            res = computeClauses(Tres, Eres, index, dd->size);
+        }
+    }
+
+    /* Cache results. */
+    if ( st__add_direct(table, (char *)f, (char *)res) == st__OUT_OF_MEM) {
+        ABC_FREE(res);
+        return(NULL);
+    }
+    return(res);
+
+} /* end of ddFindTwoLiteralClausesRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the two-literal clauses for a node.]
+
+  Description [Computes the two-literal clauses for a node given the
+  clauses for its children and the label of the node.  Returns a
+  pointer to a TclInfo structure if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [computeClausesWithUniverse]
+
+******************************************************************************/
+static DdTlcInfo *
+computeClauses(
+  DdTlcInfo *Tres /* list of clauses for T child */,
+  DdTlcInfo *Eres /* list of clauses for E child */,
+  DdHalfWord label /* variable labeling the current node */,
+  int size /* number of variables in the manager */)
+{
+    DdHalfWord *Tcv = Tres->vars; /* variables of clauses for the T child */
+    BitVector *Tcp = Tres->phases; /* phases of clauses for the T child */
+    DdHalfWord *Ecv = Eres->vars; /* variables of clauses for the E child */
+    BitVector *Ecp = Eres->phases; /* phases of clauses for the E child */
+    DdHalfWord *Vcv = NULL; /* pointer to variables of the clauses for v */
+    BitVector *Vcp = NULL; /* pointer to phases of the clauses for v */
+    DdTlcInfo *res = NULL; /* the set of clauses to be returned */
+    int pt = 0; /* index in the list of clauses of T */
+    int pe = 0; /* index in the list of clauses of E */
+    int cv = 0; /* counter of the clauses for this node */
+    TlClause *iclauses = NULL; /* list of inherited clauses */
+    TlClause *tclauses = NULL; /* list of 1-literal clauses of T */
+    TlClause *eclauses = NULL; /* list of 1-literal clauses of E */
+    TlClause *nclauses = NULL; /* list of new (non-inherited) clauses */
+    TlClause *lnclause = NULL; /* pointer to last new clause */
+    TlClause *newclause; /* temporary pointer to new clauses */
+
+    /* Initialize sets of one-literal clauses.  The one-literal clauses
+    ** are stored redundantly.  These sets allow constant-time lookup, which
+    ** we need when we check for implication of a two-literal clause by a
+    ** one-literal clause.  The linked lists allow fast sequential
+    ** processing. */
+    bitVectorClear(Tolv, size);
+    bitVectorClear(Tolp, size);
+    bitVectorClear(Eolv, size);
+    bitVectorClear(Eolp, size);
+
+    /* Initialize result structure. */
+    res = tlcInfoAlloc();
+    if (res == NULL) goto cleanup;
+
+    /* Scan the two input list.  Extract inherited two-literal clauses
+    ** and set aside one-literal clauses from each list.  The incoming lists
+    ** are sorted in the order defined by beforep.  The three linked list
+    ** produced by this loop are sorted in the reverse order because we
+    ** always append to the front of the lists.
+    ** The inherited clauses are those clauses (both one- and two-literal)
+    ** that are common to both children; and the two-literal clauses of
+    ** one child that are implied by a one-literal clause of the other
+    ** child. */
+    while (!sentinelp(Tcv[pt], Tcv[pt+1]) || !sentinelp(Ecv[pe], Ecv[pe+1])) {
+        if (equalp(Tcv[pt], bitVectorRead(Tcp, pt),
+                   Tcv[pt+1], bitVectorRead(Tcp, pt+1),
+                   Ecv[pe], bitVectorRead(Ecp, pe),
+                   Ecv[pe+1], bitVectorRead(Ecp, pe+1))) {
+            /* Add clause to inherited list. */
+            newclause = ABC_ALLOC(TlClause,1);
+            if (newclause == NULL) goto cleanup;
+            newclause->v1 = Tcv[pt];
+            newclause->v2 = Tcv[pt+1];
+            newclause->p1 = bitVectorRead(Tcp, pt);
+            newclause->p2 = bitVectorRead(Tcp, pt+1);
+            newclause->next = iclauses;
+            iclauses = newclause;
+            pt += 2; pe += 2; cv++;
+        } else if (beforep(Tcv[pt], bitVectorRead(Tcp, pt),
+                   Tcv[pt+1], bitVectorRead(Tcp, pt+1),
+                   Ecv[pe], bitVectorRead(Ecp, pe),
+                   Ecv[pe+1], bitVectorRead(Ecp, pe+1))) {
+            if (oneliteralp(Tcv[pt+1])) {
+                /* Add this one-literal clause to the T set. */
+                newclause = ABC_ALLOC(TlClause,1);
+                if (newclause == NULL) goto cleanup;
+                newclause->v1 = Tcv[pt];
+                newclause->v2 = CUDD_MAXINDEX;
+                newclause->p1 = bitVectorRead(Tcp, pt);
+                newclause->p2 = 1;
+                newclause->next = tclauses;
+                tclauses = newclause;
+                bitVectorSet(Tolv, Tcv[pt], 1);
+                bitVectorSet(Tolp, Tcv[pt], bitVectorRead(Tcp, pt));
+            } else {
+                if (impliedp(Tcv[pt], bitVectorRead(Tcp, pt),
+                             Tcv[pt+1], bitVectorRead(Tcp, pt+1),
+                             Eolv, Eolp)) {
+                    /* Add clause to inherited list. */
+                    newclause = ABC_ALLOC(TlClause,1);
+                    if (newclause == NULL) goto cleanup;
+                    newclause->v1 = Tcv[pt];
+                    newclause->v2 = Tcv[pt+1];
+                    newclause->p1 = bitVectorRead(Tcp, pt);
+                    newclause->p2 = bitVectorRead(Tcp, pt+1);
+                    newclause->next = iclauses;
+                    iclauses = newclause;
+                    cv++;
+                }
+            }
+            pt += 2;
+        } else { /* !beforep() */
+            if (oneliteralp(Ecv[pe+1])) {
+                /* Add this one-literal clause to the E set. */
+                newclause = ABC_ALLOC(TlClause,1);
+                if (newclause == NULL) goto cleanup;
+                newclause->v1 = Ecv[pe];
+                newclause->v2 = CUDD_MAXINDEX;
+                newclause->p1 = bitVectorRead(Ecp, pe);
+                newclause->p2 = 1;
+                newclause->next = eclauses;
+                eclauses = newclause;
+                bitVectorSet(Eolv, Ecv[pe], 1);
+                bitVectorSet(Eolp, Ecv[pe], bitVectorRead(Ecp, pe));
+            } else {
+                if (impliedp(Ecv[pe], bitVectorRead(Ecp, pe),
+                             Ecv[pe+1], bitVectorRead(Ecp, pe+1),
+                             Tolv, Tolp)) {
+                    /* Add clause to inherited list. */
+                    newclause = ABC_ALLOC(TlClause,1);
+                    if (newclause == NULL) goto cleanup;
+                    newclause->v1 = Ecv[pe];
+                    newclause->v2 = Ecv[pe+1];
+                    newclause->p1 = bitVectorRead(Ecp, pe);
+                    newclause->p2 = bitVectorRead(Ecp, pe+1);
+                    newclause->next = iclauses;
+                    iclauses = newclause;
+                    cv++;
+                }
+            }
+            pe += 2;
+        }
+    }
+
+    /* Add one-literal clauses for the label variable to the front of
+    ** the two lists. */
+    newclause = ABC_ALLOC(TlClause,1);
+    if (newclause == NULL) goto cleanup;
+    newclause->v1 = label;
+    newclause->v2 = CUDD_MAXINDEX;
+    newclause->p1 = 0;
+    newclause->p2 = 1;
+    newclause->next = tclauses;
+    tclauses = newclause;
+    newclause = ABC_ALLOC(TlClause,1);
+    if (newclause == NULL) goto cleanup;
+    newclause->v1 = label;
+    newclause->v2 = CUDD_MAXINDEX;
+    newclause->p1 = 1;
+    newclause->p2 = 1;
+    newclause->next = eclauses;
+    eclauses = newclause;
+
+    /* Produce the non-inherited clauses.  We preserve the "reverse"
+    ** order of the two input lists by appending to the end of the
+    ** list.  In this way, iclauses and nclauses are consistent. */
+    while (tclauses != NULL && eclauses != NULL) {
+        if (beforep(eclauses->v1, eclauses->p1, eclauses->v2, eclauses->p2,
+                    tclauses->v1, tclauses->p1, tclauses->v2, tclauses->p2)) {
+            TlClause *nextclause = tclauses->next;
+            TlClause *otherclauses = eclauses;
+            while (otherclauses != NULL) {
+                if (tclauses->v1 != otherclauses->v1) {
+                    newclause = ABC_ALLOC(TlClause,1);
+                    if (newclause == NULL) goto cleanup;
+                    newclause->v1 = tclauses->v1;
+                    newclause->v2 = otherclauses->v1;
+                    newclause->p1 = tclauses->p1;
+                    newclause->p2 = otherclauses->p1;
+                    newclause->next = NULL;
+                    if (nclauses == NULL) {
+                        nclauses = newclause;
+                        lnclause = newclause;
+                    } else {
+                        lnclause->next = newclause;
+                        lnclause = newclause;
+                    }
+                    cv++;
+                }
+                otherclauses = otherclauses->next;
+            }
+            ABC_FREE(tclauses);
+            tclauses = nextclause;
+        } else {
+            TlClause *nextclause = eclauses->next;
+            TlClause *otherclauses = tclauses;
+            while (otherclauses != NULL) {
+                if (eclauses->v1 != otherclauses->v1) {
+                    newclause = ABC_ALLOC(TlClause,1);
+                    if (newclause == NULL) goto cleanup;
+                    newclause->v1 = eclauses->v1;
+                    newclause->v2 = otherclauses->v1;
+                    newclause->p1 = eclauses->p1;
+                    newclause->p2 = otherclauses->p1;
+                    newclause->next = NULL;
+                    if (nclauses == NULL) {
+                        nclauses = newclause;
+                        lnclause = newclause;
+                    } else {
+                        lnclause->next = newclause;
+                        lnclause = newclause;
+                    }
+                    cv++;
+                }
+                otherclauses = otherclauses->next;
+            }
+            ABC_FREE(eclauses);
+            eclauses = nextclause;
+        }
+    }
+    while (tclauses != NULL) {
+        TlClause *nextclause = tclauses->next;
+        ABC_FREE(tclauses);
+        tclauses = nextclause;
+    }
+    while (eclauses != NULL) {
+        TlClause *nextclause = eclauses->next;
+        ABC_FREE(eclauses);
+        eclauses = nextclause;
+    }
+
+    /* Merge inherited and non-inherited clauses.  Now that we know the
+    ** total number, we allocate the arrays, and we fill them bottom-up
+    ** to restore the proper ordering. */
+    Vcv = ABC_ALLOC(DdHalfWord, 2*(cv+1));
+    if (Vcv == NULL) goto cleanup;
+    if (cv > 0) {
+        Vcp = bitVectorAlloc(2*cv);
+        if (Vcp == NULL) goto cleanup;
+    } else {
+        Vcp = NULL;
+    }
+    res->vars = Vcv;
+    res->phases = Vcp;
+    /* Add sentinel. */
+    Vcv[2*cv] = 0;
+    Vcv[2*cv+1] = 0;
+    while (iclauses != NULL || nclauses != NULL) {
+        TlClause *nextclause;
+        cv--;
+        if (nclauses == NULL || (iclauses != NULL &&
+            beforep(nclauses->v1, nclauses->p1, nclauses->v2, nclauses->p2,
+                    iclauses->v1, iclauses->p1, iclauses->v2, iclauses->p2))) {
+            Vcv[2*cv] = iclauses->v1;
+            Vcv[2*cv+1] = iclauses->v2;
+            bitVectorSet(Vcp, 2*cv, iclauses->p1);
+            bitVectorSet(Vcp, 2*cv+1, iclauses->p2);
+            nextclause = iclauses->next;
+            ABC_FREE(iclauses);
+            iclauses = nextclause;
+        } else {
+            Vcv[2*cv] = nclauses->v1;
+            Vcv[2*cv+1] = nclauses->v2;
+            bitVectorSet(Vcp, 2*cv, nclauses->p1);
+            bitVectorSet(Vcp, 2*cv+1, nclauses->p2);
+            nextclause = nclauses->next;
+            ABC_FREE(nclauses);
+            nclauses = nextclause;
+        }
+    }
+    assert(cv == 0);
+
+    return(res);
+
+ cleanup:
+    if (res != NULL) Cudd_tlcInfoFree(res);
+    while (iclauses != NULL) {
+        TlClause *nextclause = iclauses->next;
+        ABC_FREE(iclauses);
+        iclauses = nextclause;
+    }
+    while (nclauses != NULL) {
+        TlClause *nextclause = nclauses->next;
+        ABC_FREE(nclauses);
+        nclauses = nextclause;
+    }
+    while (tclauses != NULL) {
+        TlClause *nextclause = tclauses->next;
+        ABC_FREE(tclauses);
+        tclauses = nextclause;
+    }
+    while (eclauses != NULL) {
+        TlClause *nextclause = eclauses->next;
+        ABC_FREE(eclauses);
+        eclauses = nextclause;
+    }
+
+    return(NULL);
+
+} /* end of computeClauses */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the two-literal clauses for a node.]
+
+  Description [Computes the two-literal clauses for a node with a zero
+  child, given the clauses for its other child and the label of the
+  node.  Returns a pointer to a TclInfo structure if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [computeClauses]
+
+******************************************************************************/
+static DdTlcInfo *
+computeClausesWithUniverse(
+  DdTlcInfo *Cres /* list of clauses for child */,
+  DdHalfWord label /* variable labeling the current node */,
+  short phase /* 0 if E child is zero; 1 if T child is zero */)
+{
+    DdHalfWord *Ccv = Cres->vars; /* variables of clauses for child */
+    BitVector *Ccp = Cres->phases; /* phases of clauses for child */
+    DdHalfWord *Vcv = NULL; /* pointer to the variables of the clauses for v */
+    BitVector *Vcp = NULL; /* pointer to the phases of the clauses for v */
+    DdTlcInfo *res = NULL; /* the set of clauses to be returned */
+    int i;
+
+    /* Initialize result. */
+    res = tlcInfoAlloc();
+    if (res == NULL) goto cleanup;
+    /* Count entries for new list and allocate accordingly. */
+    for (i = 0; !sentinelp(Ccv[i], Ccv[i+1]); i += 2);
+    /* At this point, i is twice the number of clauses in the child's
+    ** list.  We need four more entries for this node: 2 for the one-literal
+    ** clause for the label, and 2 for the sentinel. */
+    Vcv = ABC_ALLOC(DdHalfWord,i+4);
+    if (Vcv == NULL) goto cleanup;
+    Vcp = bitVectorAlloc(i+4);
+    if (Vcp == NULL) goto cleanup;
+    res->vars = Vcv;
+    res->phases = Vcp;
+    /* Copy old list into new. */
+    for (i = 0; !sentinelp(Ccv[i], Ccv[i+1]); i += 2) {
+        Vcv[i] = Ccv[i];
+        Vcv[i+1] = Ccv[i+1];
+        bitVectorSet(Vcp, i, bitVectorRead(Ccp, i));
+        bitVectorSet(Vcp, i+1, bitVectorRead(Ccp, i+1));
+    }
+    /* Add clause corresponding to label. */
+    Vcv[i] = label;
+    bitVectorSet(Vcp, i, phase);
+    i++;
+    Vcv[i] = CUDD_MAXINDEX;
+    bitVectorSet(Vcp, i, 1);
+    i++;
+    /* Add sentinel. */
+    Vcv[i] = 0;
+    Vcv[i+1] = 0;
+    bitVectorSet(Vcp, i, 0);
+    bitVectorSet(Vcp, i+1, 0);
+
+    return(res);
+
+ cleanup:
+    /* Vcp is guaranteed to be NULL here.  Hence, we do not try to free it. */
+    if (Vcv != NULL) ABC_FREE(Vcv);
+    if (res != NULL) Cudd_tlcInfoFree(res);
+
+    return(NULL);
+
+} /* end of computeClausesWithUniverse */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns an enpty set of clauses.]
+
+  Description [Returns a pointer to an empty set of clauses if
+  successful; NULL otherwise.  No bit vector for the phases is
+  allocated.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdTlcInfo *
+emptyClauseSet(void)
+{
+    DdTlcInfo *eset;
+
+    eset = ABC_ALLOC(DdTlcInfo,1);
+    if (eset == NULL) return(NULL);
+    eset->vars = ABC_ALLOC(DdHalfWord,2);
+    if (eset->vars == NULL) {
+        ABC_FREE(eset);
+        return(NULL);
+    }
+    /* Sentinel */
+    eset->vars[0] = 0;
+    eset->vars[1] = 0;
+    eset->phases = NULL; /* does not matter */
+    eset->cnt = 0;
+    return(eset);
+
+} /* end of emptyClauseSet */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns true iff the argument is the sentinel clause.]
+
+  Description [Returns true iff the argument is the sentinel clause.
+  A sentinel clause has both variables equal to 0.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+sentinelp(
+  DdHalfWord var1,
+  DdHalfWord var2)
+{
+    return(var1 == 0 && var2 == 0);
+
+} /* end of sentinelp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns true iff the two arguments are identical clauses.]
+
+  Description [Returns true iff the two arguments are identical
+  clauses.  Since literals are sorted, we only need to compare
+  literals in the same position.]
+
+  SideEffects [None]
+
+  SeeAlso     [beforep]
+
+******************************************************************************/
+static int
+equalp(
+  DdHalfWord var1a,
+  short phase1a,
+  DdHalfWord var1b,
+  short phase1b,
+  DdHalfWord var2a,
+  short phase2a,
+  DdHalfWord var2b,
+  short phase2b)
+{
+    return(var1a == var2a && phase1a == phase2a &&
+           var1b == var2b && phase1b == phase2b);
+
+} /* end of equalp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns true iff the first argument precedes the second in
+  the clause order.]
+
+  Description [Returns true iff the first argument precedes the second
+  in the clause order.  A clause precedes another if its first lieral
+  precedes the first literal of the other, or if the first literals
+  are the same, and its second literal precedes the second literal of
+  the other clause.  A literal precedes another if it has a higher
+  index, of if it has the same index, but it has lower phase.  Phase 0
+  is the positive phase, and it is lower than Phase 1 (negative
+  phase).]
+
+  SideEffects [None]
+
+  SeeAlso     [equalp]
+
+******************************************************************************/
+static int
+beforep(
+  DdHalfWord var1a,
+  short phase1a,
+  DdHalfWord var1b,
+  short phase1b,
+  DdHalfWord var2a,
+  short phase2a,
+  DdHalfWord var2b,
+  short phase2b)
+{
+    return(var1a > var2a || (var1a == var2a &&
+           (phase1a < phase2a || (phase1a == phase2a &&
+            (var1b > var2b || (var1b == var2b && phase1b < phase2b))))));
+
+} /* end of beforep */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns true iff the argument is a one-literal clause.]
+
+  Description [Returns true iff the argument is a one-literal clause.
+  A one-litaral clause has the constant FALSE as second literal.
+  Since the constant TRUE is never used, it is sufficient to test for
+  a constant.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+oneliteralp(
+  DdHalfWord var)
+{
+    return(var == CUDD_MAXINDEX);
+
+} /* end of oneliteralp */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns true iff either literal of a clause is in a set of
+  literals.]
+
+  Description [Returns true iff either literal of a clause is in a set
+  of literals.  The first four arguments specify the clause.  The
+  remaining two arguments specify the literal set.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+impliedp(
+  DdHalfWord var1,
+  short phase1,
+  DdHalfWord var2,
+  short phase2,
+  BitVector *olv,
+  BitVector *olp)
+{
+    return((bitVectorRead(olv, var1) &&
+            bitVectorRead(olp, var1) == phase1) ||
+           (bitVectorRead(olv, var2) &&
+            bitVectorRead(olp, var2) == phase2));
+
+} /* end of impliedp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a bit vector.]
+
+  Description [Allocates a bit vector.  The parameter size gives the
+  number of bits.  This procedure allocates enough long's to hold the
+  specified number of bits.  Returns a pointer to the allocated vector
+  if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [bitVectorClear bitVectorFree]
+
+******************************************************************************/
+static BitVector *
+bitVectorAlloc(
+  int size)
+{
+    int allocSize;
+    BitVector *vector;
+
+    /* Find out how many long's we need.
+    ** There are sizeof(long) * 8 bits in a long.
+    ** The ceiling of the ratio of two integers m and n is given
+    ** by ((n-1)/m)+1.  Putting all this together, we get... */
+    allocSize = ((size - 1) / (sizeof(BitVector) * 8)) + 1;
+    vector = ABC_ALLOC(BitVector, allocSize);
+    if (vector == NULL) return(NULL);
+    /* Clear the whole array. */
+    (void) memset(vector, 0, allocSize * sizeof(BitVector));
+    return(vector);
+
+} /* end of bitVectorAlloc */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Clears a bit vector.]
+
+  Description [Clears a bit vector.  The parameter size gives the
+  number of bits.]
+
+  SideEffects [None]
+
+  SeeAlso     [bitVectorAlloc]
+
+******************************************************************************/
+DD_INLINE
+static void
+bitVectorClear(
+  BitVector *vector,
+  int size)
+{
+    int allocSize;
+
+    /* Find out how many long's we need.
+    ** There are sizeof(long) * 8 bits in a long.
+    ** The ceiling of the ratio of two integers m and n is given
+    ** by ((n-1)/m)+1.  Putting all this together, we get... */
+    allocSize = ((size - 1) / (sizeof(BitVector) * 8)) + 1;
+    /* Clear the whole array. */
+    (void) memset(vector, 0, allocSize * sizeof(BitVector));
+    return;
+
+} /* end of bitVectorClear */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a bit vector.]
+
+  Description [Frees a bit vector.]
+
+  SideEffects [None]
+
+  SeeAlso     [bitVectorAlloc]
+
+******************************************************************************/
+static void
+bitVectorFree(
+  BitVector *vector)
+{
+    ABC_FREE(vector);
+
+} /* end of bitVectorFree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the i-th entry of a bit vector.]
+
+  Description [Returns the i-th entry of a bit vector.]
+
+  SideEffects [None]
+
+  SeeAlso     [bitVectorSet]
+
+******************************************************************************/
+DD_INLINE
+static short
+bitVectorRead(
+  BitVector *vector,
+  int i)
+{
+    int word, bit;
+    short result;
+
+    if (vector == NULL) return((short) 0);
+
+    word = i >> LOGBPL;
+    bit = i & (BPL - 1);
+    result = (short) ((vector[word] >> bit) & 1L);
+    return(result);
+
+} /* end of bitVectorRead */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the i-th entry of a bit vector to a value.]
+
+  Description [Sets the i-th entry of a bit vector to a value.]
+
+  SideEffects [None]
+
+  SeeAlso     [bitVectorRead]
+
+******************************************************************************/
+DD_INLINE
+static void
+bitVectorSet(
+  BitVector * vector,
+  int i,
+  short val)
+{
+    int word, bit;
+
+    word = i >> LOGBPL;
+    bit = i & (BPL - 1);
+    vector[word] &= ~(1L << bit);
+    vector[word] |= (((long) val) << bit);
+
+} /* end of bitVectorSet */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a DdTlcInfo Structure.]
+
+  Description [Returns a pointer to a DdTlcInfo Structure if successful;
+  NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_tlcInfoFree]
+
+******************************************************************************/
+static DdTlcInfo *
+tlcInfoAlloc(void)
+{
+    DdTlcInfo *res = ABC_ALLOC(DdTlcInfo,1);
+    if (res == NULL) return(NULL);
+    res->vars = NULL;
+    res->phases = NULL;
+    res->cnt = 0;
+    return(res);
+
+} /* end of tlcInfoAlloc */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddExact.c b/abc-build/src/bdd/cudd/cuddExact.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddExact.c
@@ -0,0 +1,1028 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddExact.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for exact variable reordering.]
+
+  Description [External procedures included in this file:
+                <ul>
+                </ul>
+        Internal procedures included in this module:
+                <ul>
+                <li> cuddExact()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> getMaxBinomial()
+                <li> gcd()
+                <li> getMatrix()
+                <li> freeMatrix()
+                <li> getLevelKeys()
+                <li> ddShuffle()
+                <li> ddSiftUp()
+                <li> updateUB()
+                <li> ddCountRoots()
+                <li> ddClearGlobal()
+                <li> computeLB()
+                <li> updateEntry()
+                <li> pushDown()
+                <li> initSymmInfo()
+                </ul>]
+
+  Author      [Cheng Hua, Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddExact.c,v 1.28 2009/02/19 16:19:19 fabio Exp $";
+#endif
+
+#ifdef DD_STATS
+static int ddTotalShuffles;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int getMaxBinomial (int n);
+static DdHalfWord ** getMatrix (int rows, int cols);
+static void freeMatrix (DdHalfWord **matrix);
+static int getLevelKeys (DdManager *table, int l);
+static int ddShuffle (DdManager *table, DdHalfWord *permutation, int lower, int upper);
+static int ddSiftUp (DdManager *table, int x, int xLow);
+static int updateUB (DdManager *table, int oldBound, DdHalfWord *bestOrder, int lower, int upper);
+static int ddCountRoots (DdManager *table, int lower, int upper);
+static void ddClearGlobal (DdManager *table, int lower, int maxlevel);
+static int computeLB (DdManager *table, DdHalfWord *order, int roots, int cost, int lower, int upper, int level);
+static int updateEntry (DdManager *table, DdHalfWord *order, int level, int cost, DdHalfWord **orders, int *costs, int subsets, char *mask, int lower, int upper);
+static void pushDown (DdHalfWord *order, int j, int level);
+static DdHalfWord * initSymmInfo (DdManager *table, int lower, int upper);
+static int checkSymmInfo (DdManager *table, DdHalfWord *symmInfo, int index, int level);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Exact variable ordering algorithm.]
+
+  Description [Exact variable ordering algorithm. Finds an optimum
+  order for the variables between lower and upper.  Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddExact(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int k, i, j;
+    int maxBinomial, oldSubsets, newSubsets;
+    int subsetCost;
+    int size;                   /* number of variables to be reordered */
+    int unused, nvars, level, result;
+    int upperBound, lowerBound, cost;
+    int roots;
+    char *mask = NULL;
+    DdHalfWord  *symmInfo = NULL;
+    DdHalfWord **newOrder = NULL;
+    DdHalfWord **oldOrder = NULL;
+    int *newCost = NULL;
+    int *oldCost = NULL;
+    DdHalfWord **tmpOrder;
+    int *tmpCost;
+    DdHalfWord *bestOrder = NULL;
+    DdHalfWord *order;
+#ifdef DD_STATS
+    int  ddTotalSubsets;
+#endif
+
+    /* Restrict the range to be reordered by excluding unused variables
+    ** at the two ends. */
+    while (table->subtables[lower].keys == 1 &&
+           table->vars[table->invperm[lower]]->ref == 1 &&
+           lower < upper)
+        lower++;
+    while (table->subtables[upper].keys == 1 &&
+           table->vars[table->invperm[upper]]->ref == 1 &&
+           lower < upper)
+        upper--;
+    if (lower == upper) return(1); /* trivial problem */
+
+    /* Apply symmetric sifting to get a good upper bound and to extract
+    ** symmetry information. */
+    result = cuddSymmSiftingConv(table,lower,upper);
+    if (result == 0) goto cuddExactOutOfMem;
+
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n");
+    ddTotalShuffles = 0;
+    ddTotalSubsets = 0;
+#endif
+
+    /* Initialization. */
+    nvars = table->size;
+    size = upper - lower + 1;
+    /* Count unused variable among those to be reordered.  This is only
+    ** used to compute maxBinomial. */
+    unused = 0;
+    for (i = lower + 1; i < upper; i++) {
+        if (table->subtables[i].keys == 1 &&
+            table->vars[table->invperm[i]]->ref == 1)
+            unused++;
+    }
+
+    /* Find the maximum number of subsets we may have to store. */
+    maxBinomial = getMaxBinomial(size - unused);
+    if (maxBinomial == -1) goto cuddExactOutOfMem;
+
+    newOrder = getMatrix(maxBinomial, size);
+    if (newOrder == NULL) goto cuddExactOutOfMem;
+
+    newCost = ABC_ALLOC(int, maxBinomial);
+    if (newCost == NULL) goto cuddExactOutOfMem;
+
+    oldOrder = getMatrix(maxBinomial, size);
+    if (oldOrder == NULL) goto cuddExactOutOfMem;
+
+    oldCost = ABC_ALLOC(int, maxBinomial);
+    if (oldCost == NULL) goto cuddExactOutOfMem;
+
+    bestOrder = ABC_ALLOC(DdHalfWord, size);
+    if (bestOrder == NULL) goto cuddExactOutOfMem;
+
+    mask = ABC_ALLOC(char, nvars);
+    if (mask == NULL) goto cuddExactOutOfMem;
+
+    symmInfo = initSymmInfo(table, lower, upper);
+    if (symmInfo == NULL) goto cuddExactOutOfMem;
+
+    roots = ddCountRoots(table, lower, upper);
+
+    /* Initialize the old order matrix for the empty subset and the best
+    ** order to the current order. The cost for the empty subset includes
+    ** the cost of the levels between upper and the constants. These levels
+    ** are not going to change. Hence, we count them only once.
+    */
+    oldSubsets = 1;
+    for (i = 0; i < size; i++) {
+        oldOrder[0][i] = bestOrder[i] = (DdHalfWord) table->invperm[i+lower];
+    }
+    subsetCost = table->constants.keys;
+    for (i = upper + 1; i < nvars; i++)
+        subsetCost += getLevelKeys(table,i);
+    oldCost[0] = subsetCost;
+    /* The upper bound is initialized to the current size of the BDDs. */
+    upperBound = table->keys - table->isolated;
+
+    /* Now consider subsets of increasing size. */
+    for (k = 1; k <= size; k++) {
+#ifdef DD_STATS
+        (void) fprintf(table->out,"Processing subsets of size %d\n", k);
+        fflush(table->out);
+#endif
+        newSubsets = 0;
+        level = size - k;               /* offset of first bottom variable */
+
+        for (i = 0; i < oldSubsets; i++) { /* for each subset of size k-1 */
+            order = oldOrder[i];
+            cost = oldCost[i];
+            lowerBound = computeLB(table, order, roots, cost, lower, upper,
+                                   level);
+            if (lowerBound >= upperBound)
+                continue;
+            /* Impose new order. */
+            result = ddShuffle(table, order, lower, upper);
+            if (result == 0) goto cuddExactOutOfMem;
+            upperBound = updateUB(table,upperBound,bestOrder,lower,upper);
+            /* For each top bottom variable. */
+            for (j = level; j >= 0; j--) {
+                /* Skip unused variables. */
+                if (table->subtables[j+lower-1].keys == 1 &&
+                    table->vars[table->invperm[j+lower-1]]->ref == 1) continue;
+                /* Find cost under this order. */
+                subsetCost = cost + getLevelKeys(table, lower + level);
+                newSubsets = updateEntry(table, order, level, subsetCost,
+                                         newOrder, newCost, newSubsets, mask,
+                                         lower, upper);
+                if (j == 0)
+                    break;
+                if (checkSymmInfo(table, symmInfo, order[j-1], level) == 0)
+                    continue;
+                pushDown(order,j-1,level);
+                /* Impose new order. */
+                result = ddShuffle(table, order, lower, upper);
+                if (result == 0) goto cuddExactOutOfMem;
+                upperBound = updateUB(table,upperBound,bestOrder,lower,upper);
+            } /* for each bottom variable */
+        } /* for each subset of size k */
+
+        /* New orders become old orders in preparation for next iteration. */
+        tmpOrder = oldOrder; tmpCost = oldCost;
+        oldOrder = newOrder; oldCost = newCost;
+        newOrder = tmpOrder; newCost = tmpCost;
+#ifdef DD_STATS
+        ddTotalSubsets += newSubsets;
+#endif
+        oldSubsets = newSubsets;
+    }
+    result = ddShuffle(table, bestOrder, lower, upper);
+    if (result == 0) goto cuddExactOutOfMem;
+#ifdef DD_STATS
+#ifdef DD_VERBOSE
+    (void) fprintf(table->out,"\n");
+#endif
+    (void) fprintf(table->out,"#:S_EXACT   %8d: total subsets\n",
+                   ddTotalSubsets);
+    (void) fprintf(table->out,"#:H_EXACT   %8d: total shuffles",
+                   ddTotalShuffles);
+#endif
+
+    freeMatrix(newOrder);
+    freeMatrix(oldOrder);
+    ABC_FREE(bestOrder);
+    ABC_FREE(oldCost);
+    ABC_FREE(newCost);
+    ABC_FREE(symmInfo);
+    ABC_FREE(mask);
+    return(1);
+
+cuddExactOutOfMem:
+
+    if (newOrder != NULL) freeMatrix(newOrder);
+    if (oldOrder != NULL) freeMatrix(oldOrder);
+    if (bestOrder != NULL) ABC_FREE(bestOrder);
+    if (oldCost != NULL) ABC_FREE(oldCost);
+    if (newCost != NULL) ABC_FREE(newCost);
+    if (symmInfo != NULL) ABC_FREE(symmInfo);
+    if (mask != NULL) ABC_FREE(mask);
+    table->errorCode = CUDD_MEMORY_OUT;
+    return(0);
+
+} /* end of cuddExact */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the maximum value of (n choose k) for a given n.]
+
+  Description [Computes the maximum value of (n choose k) for a given
+  n.  The maximum value occurs for k = n/2 when n is even, or k =
+  (n-1)/2 when n is odd.  The algorithm used in this procedure avoids
+  intermediate overflow problems.  It is based on the identity
+  <pre>
+    binomial(n,k) = n/k * binomial(n-1,k-1).
+  </pre>
+  Returns the computed value if successful; -1 if out of range.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+getMaxBinomial(
+  int n)
+{
+    double i, j, result;
+
+    if (n < 0 || n > 33) return(-1); /* error */
+    if (n < 2) return(1);
+
+    for (result = (double)((n+3)/2), i = result+1, j=2; i <= n; i++, j++) {
+        result *= i;
+        result /= j;
+    }
+
+    return((int)result);
+
+} /* end of getMaxBinomial */
+
+
+#if 0
+/**Function********************************************************************
+
+  Synopsis    [Returns the gcd of two integers.]
+
+  Description [Returns the gcd of two integers. Uses the binary GCD
+  algorithm described in Cormen, Leiserson, and Rivest.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+gcd(
+  int  x,
+  int  y)
+{
+    int a;
+    int b;
+    int lsbMask;
+
+    /* GCD(n,0) = n. */
+    if (x == 0) return(y);
+    if (y == 0) return(x);
+
+    a = x; b = y; lsbMask = 1;
+
+    /* Here both a and b are != 0. The iteration maintains this invariant.
+    ** Hence, we only need to check for when they become equal.
+    */
+    while (a != b) {
+        if (a & lsbMask) {
+            if (b & lsbMask) {  /* both odd */
+                if (a < b) {
+                    b = (b - a) >> 1;
+                } else {
+                    a = (a - b) >> 1;
+                }
+            } else {            /* a odd, b even */
+                b >>= 1;
+            }
+        } else {
+            if (b & lsbMask) {  /* a even, b odd */
+                a >>= 1;
+            } else {            /* both even */
+                lsbMask <<= 1;
+            }
+        }
+    }
+
+    return(a);
+
+} /* end of gcd */
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a two-dimensional matrix of ints.]
+
+  Description [Allocates a two-dimensional matrix of ints.
+  Returns the pointer to the matrix if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [freeMatrix]
+
+******************************************************************************/
+static DdHalfWord **
+getMatrix(
+  int  rows /* number of rows */,
+  int  cols /* number of columns */)
+{
+    DdHalfWord **matrix;
+    int i;
+
+    if (cols*rows == 0) return(NULL);
+    matrix = ABC_ALLOC(DdHalfWord *, rows);
+    if (matrix == NULL) return(NULL);
+    matrix[0] = ABC_ALLOC(DdHalfWord, cols*rows);
+    if (matrix[0] == NULL) {
+        ABC_FREE(matrix);
+        return(NULL);
+    }
+    for (i = 1; i < rows; i++) {
+        matrix[i] = matrix[i-1] + cols;
+    }
+    return(matrix);
+
+} /* end of getMatrix */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a two-dimensional matrix allocated by getMatrix.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [getMatrix]
+
+******************************************************************************/
+static void
+freeMatrix(
+  DdHalfWord ** matrix)
+{
+    ABC_FREE(matrix[0]);
+    ABC_FREE(matrix);
+    return;
+
+} /* end of freeMatrix */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of nodes at one level of a unique table.]
+
+  Description [Returns the number of nodes at one level of a unique table.
+  The projection function, if isolated, is not counted.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static int
+getLevelKeys(
+  DdManager * table,
+  int  l)
+{
+    int isolated;
+    int x;        /* x is an index */
+
+    x = table->invperm[l];
+    isolated = table->vars[x]->ref == 1;
+
+    return(table->subtables[l].keys - isolated);
+
+} /* end of getLevelKeys */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders variables according to a given permutation.]
+
+  Description [Reorders variables according to a given permutation.
+  The i-th permutation array contains the index of the variable that
+  should be brought to the i-th level. ddShuffle assumes that no
+  dead nodes are present and that the interaction matrix is properly
+  initialized.  The reordering is achieved by a series of upward sifts.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static int
+ddShuffle(
+  DdManager * table,
+  DdHalfWord * permutation,
+  int  lower,
+  int  upper)
+{
+    DdHalfWord  index;
+    int         level;
+    int         position;
+#if 0
+    int         numvars;
+#endif
+    int         result;
+#ifdef DD_STATS
+    long        localTime;
+    int         initialSize;
+#ifdef DD_VERBOSE
+    int         finalSize;
+#endif
+    int         previousSize;
+#endif
+
+#ifdef DD_STATS
+    localTime = util_cpu_time();
+    initialSize = table->keys - table->isolated;
+#endif
+
+#if 0
+    numvars = table->size;
+
+    (void) fprintf(table->out,"%d:", ddTotalShuffles);
+    for (level = 0; level < numvars; level++) {
+        (void) fprintf(table->out," %d", table->invperm[level]);
+    }
+    (void) fprintf(table->out,"\n");
+#endif
+
+    for (level = 0; level <= upper - lower; level++) {
+        index = permutation[level];
+        position = table->perm[index];
+#ifdef DD_STATS
+        previousSize = table->keys - table->isolated;
+#endif
+        result = ddSiftUp(table,position,level+lower);
+        if (!result) return(0);
+    }
+
+#ifdef DD_STATS
+    ddTotalShuffles++;
+#ifdef DD_VERBOSE
+    finalSize = table->keys - table->isolated;
+    if (finalSize < initialSize) {
+        (void) fprintf(table->out,"-");
+    } else if (finalSize > initialSize) {
+        (void) fprintf(table->out,"+");
+    } else {
+        (void) fprintf(table->out,"=");
+    }
+    if ((ddTotalShuffles & 63) == 0) (void) fprintf(table->out,"\n");
+    fflush(table->out);
+#endif
+#endif
+
+    return(1);
+
+} /* end of ddShuffle */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves one variable up.]
+
+  Description [Takes a variable from position x and sifts it up to
+  position xLow;  xLow should be less than or equal to x.
+  Returns 1 if successful; 0 otherwise]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddSiftUp(
+  DdManager * table,
+  int  x,
+  int  xLow)
+{
+    int        y;
+    int        size;
+
+    y = cuddNextLow(table,x);
+    while (y >= xLow) {
+        size = cuddSwapInPlace(table,y,x);
+        if (size == 0) {
+            return(0);
+        }
+        x = y;
+        y = cuddNextLow(table,x);
+    }
+    return(1);
+
+} /* end of ddSiftUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Updates the upper bound and saves the best order seen so far.]
+
+  Description [Updates the upper bound and saves the best order seen so far.
+  Returns the current value of the upper bound.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+updateUB(
+  DdManager * table,
+  int  oldBound,
+  DdHalfWord * bestOrder,
+  int  lower,
+  int  upper)
+{
+    int i;
+    int newBound = table->keys - table->isolated;
+
+    if (newBound < oldBound) {
+#ifdef DD_STATS
+        (void) fprintf(table->out,"New upper bound = %d\n", newBound);
+        fflush(table->out);
+#endif
+        for (i = lower; i <= upper; i++)
+            bestOrder[i-lower] = (DdHalfWord) table->invperm[i];
+        return(newBound);
+    } else {
+        return(oldBound);
+    }
+
+} /* end of updateUB */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of roots.]
+
+  Description [Counts the number of roots at the levels between lower and
+  upper.  The computation is based on breadth-first search.
+  A node is a root if it is not reachable from any previously visited node.
+  (All the nodes at level lower are therefore considered roots.)
+  The visited flag uses the LSB of the next pointer.  Returns the root
+  count. The roots that are constant nodes are always ignored.]
+
+  SideEffects [None]
+
+  SeeAlso     [ddClearGlobal]
+
+******************************************************************************/
+static int
+ddCountRoots(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int i,j;
+    DdNode *f;
+    DdNodePtr *nodelist;
+    DdNode *sentinel = &(table->sentinel);
+    int slots;
+    int roots = 0;
+    int maxlevel = lower;
+
+    for (i = lower; i <= upper; i++) {
+        nodelist = table->subtables[i].nodelist;
+        slots = table->subtables[i].slots;
+        for (j = 0; j < slots; j++) {
+            f = nodelist[j];
+            while (f != sentinel) {
+                /* A node is a root of the DAG if it cannot be
+                ** reached by nodes above it. If a node was never
+                ** reached during the previous depth-first searches,
+                ** then it is a root, and we start a new depth-first
+                ** search from it.
+                */
+                if (!Cudd_IsComplement(f->next)) {
+                    if (f != table->vars[f->index]) {
+                        roots++;
+                    }
+                }
+                if (!Cudd_IsConstant(cuddT(f))) {
+                    cuddT(f)->next = Cudd_Complement(cuddT(f)->next);
+                    if (table->perm[cuddT(f)->index] > maxlevel)
+                        maxlevel = table->perm[cuddT(f)->index];
+                }
+                if (!Cudd_IsConstant(cuddE(f))) {
+                    Cudd_Regular(cuddE(f))->next =
+                        Cudd_Complement(Cudd_Regular(cuddE(f))->next);
+                    if (table->perm[Cudd_Regular(cuddE(f))->index] > maxlevel)
+                        maxlevel = table->perm[Cudd_Regular(cuddE(f))->index];
+                }
+                f = Cudd_Regular(f->next);
+            }
+        }
+    }
+    ddClearGlobal(table, lower, maxlevel);
+
+    return(roots);
+
+} /* end of ddCountRoots */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Scans the DD and clears the LSB of the next pointers.]
+
+  Description [Scans the DD and clears the LSB of the next pointers.
+  The LSB of the next pointers are used as markers to tell whether a
+  node was reached. Once the roots are counted, these flags are
+  reset.]
+
+  SideEffects [None]
+
+  SeeAlso     [ddCountRoots]
+
+******************************************************************************/
+static void
+ddClearGlobal(
+  DdManager * table,
+  int  lower,
+  int  maxlevel)
+{
+    int i,j;
+    DdNode *f;
+    DdNodePtr *nodelist;
+    DdNode *sentinel = &(table->sentinel);
+    int slots;
+
+    for (i = lower; i <= maxlevel; i++) {
+        nodelist = table->subtables[i].nodelist;
+        slots = table->subtables[i].slots;
+        for (j = 0; j < slots; j++) {
+            f = nodelist[j];
+            while (f != sentinel) {
+                f->next = Cudd_Regular(f->next);
+                f = f->next;
+            }
+        }
+    }
+
+} /* end of ddClearGlobal */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a lower bound on the size of a BDD.]
+
+  Description [Computes a lower bound on the size of a BDD from the
+  following factors:
+  <ul>
+  <li> size of the lower part of it;
+  <li> size of the part of the upper part not subjected to reordering;
+  <li> number of roots in the part of the BDD subjected to reordering;
+  <li> variable in the support of the roots in the upper part of the
+       BDD subjected to reordering.
+  <ul/>]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+computeLB(
+  DdManager * table             /* manager */,
+  DdHalfWord * order            /* optimal order for the subset */,
+  int  roots                    /* roots between lower and upper */,
+  int  cost                     /* minimum cost for the subset */,
+  int  lower                    /* lower level to be reordered */,
+  int  upper                    /* upper level to be reordered */,
+  int  level                    /* offset for the current top bottom var */
+  )
+{
+    int i;
+    int lb = cost;
+    int lb1 = 0;
+    int lb2;
+    int support;
+    DdHalfWord ref;
+
+    /* The levels not involved in reordering are not going to change.
+    ** Add their sizes to the lower bound.
+    */
+    for (i = 0; i < lower; i++) {
+        lb += getLevelKeys(table,i);
+    }
+    /* If a variable is in the support, then there is going
+    ** to be at least one node labeled by that variable.
+    */
+    for (i = lower; i <= lower+level; i++) {
+        support = table->subtables[i].keys > 1 ||
+            table->vars[order[i-lower]]->ref > 1;
+        lb1 += support;
+    }
+
+    /* Estimate the number of nodes required to connect the roots to
+    ** the nodes in the bottom part. */
+    if (lower+level+1 < table->size) {
+        if (lower+level < upper)
+            ref = table->vars[order[level+1]]->ref;
+        else
+            ref = table->vars[table->invperm[upper+1]]->ref;
+        lb2 = table->subtables[lower+level+1].keys -
+            (ref > (DdHalfWord) 1) - roots;
+    } else {
+        lb2 = 0;
+    }
+
+    lb += lb1 > lb2 ? lb1 : lb2;
+
+    return(lb);
+
+} /* end of computeLB */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Updates entry for a subset.]
+
+  Description [Updates entry for a subset. Finds the subset, if it exists.
+  If the new order for the subset has lower cost, or if the subset did not
+  exist, it stores the new order and cost. Returns the number of subsets
+  currently in the table.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+updateEntry(
+  DdManager * table,
+  DdHalfWord * order,
+  int  level,
+  int  cost,
+  DdHalfWord ** orders,
+  int * costs,
+  int  subsets,
+  char * mask,
+  int  lower,
+  int  upper)
+{
+    int i, j;
+    int size = upper - lower + 1;
+
+    /* Build a mask that says what variables are in this subset. */
+    for (i = lower; i <= upper; i++)
+        mask[table->invperm[i]] = 0;
+    for (i = level; i < size; i++)
+        mask[order[i]] = 1;
+
+    /* Check each subset until a match is found or all subsets are examined. */
+    for (i = 0; i < subsets; i++) {
+        DdHalfWord *subset = orders[i];
+        for (j = level; j < size; j++) {
+            if (mask[subset[j]] == 0)
+                break;
+        }
+        if (j == size)          /* no mismatches: success */
+            break;
+    }
+    if (i == subsets || cost < costs[i]) {              /* add or replace */
+        for (j = 0; j < size; j++)
+            orders[i][j] = order[j];
+        costs[i] = cost;
+        subsets += (i == subsets);
+    }
+    return(subsets);
+
+} /* end of updateEntry */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Pushes a variable in the order down to position "level."]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+pushDown(
+  DdHalfWord * order,
+  int  j,
+  int  level)
+{
+    int i;
+    DdHalfWord tmp;
+
+    tmp = order[j];
+    for (i = j; i < level; i++) {
+        order[i] = order[i+1];
+    }
+    order[level] = tmp;
+    return;
+
+} /* end of pushDown */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gathers symmetry information.]
+
+  Description [Translates the symmetry information stored in the next
+  field of each subtable from level to indices. This procedure is called
+  immediately after symmetric sifting, so that the next fields are correct.
+  By translating this informaton in terms of indices, we make it independent
+  of subsequent reorderings. The format used is that of the next fields:
+  a circular list where each variable points to the next variable in the
+  same symmetry group. Only the entries between lower and upper are
+  considered.  The procedure returns a pointer to an array
+  holding the symmetry information if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [checkSymmInfo]
+
+******************************************************************************/
+static DdHalfWord *
+initSymmInfo(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int level, index, next, nextindex;
+    DdHalfWord *symmInfo;
+
+    symmInfo =  ABC_ALLOC(DdHalfWord, table->size);
+    if (symmInfo == NULL) return(NULL);
+
+    for (level = lower; level <= upper; level++) {
+        index = table->invperm[level];
+        next =  table->subtables[level].next;
+        nextindex = table->invperm[next];
+        symmInfo[index] = nextindex;
+    }
+    return(symmInfo);
+
+} /* end of initSymmInfo */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Check symmetry condition.]
+
+  Description [Returns 1 if a variable is the one with the highest index
+  among those belonging to a symmetry group that are in the top part of
+  the BDD.  The top part is given by level.]
+
+  SideEffects [None]
+
+  SeeAlso     [initSymmInfo]
+
+******************************************************************************/
+static int
+checkSymmInfo(
+  DdManager * table,
+  DdHalfWord * symmInfo,
+  int  index,
+  int  level)
+{
+    int i;
+
+    i = symmInfo[index];
+    while (i != index) {
+        if (index < i && table->perm[i] <= level)
+            return(0);
+        i = symmInfo[i];
+    }
+    return(1);
+
+} /* end of checkSymmInfo */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddExport.c b/abc-build/src/bdd/cudd/cuddExport.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddExport.c
@@ -0,0 +1,1384 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddExport.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Export functions.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_DumpBlif()
+                <li> Cudd_DumpBlifBody()
+                <li> Cudd_DumpDot()
+                <li> Cudd_DumpDaVinci()
+                <li> Cudd_DumpDDcal()
+                <li> Cudd_DumpFactoredForm()
+                </ul>
+        Internal procedures included in this module:
+                <ul>
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> ddDoDumpBlif()
+                <li> ddDoDumpDaVinci()
+                <li> ddDoDumpDDcal()
+                <li> ddDoDumpFactoredForm()
+                </ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddExport.c,v 1.22 2009/03/08 02:49:02 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int ddDoDumpBlif (DdManager *dd, DdNode *f, FILE *fp, st__table *visited, char **names, int mv);
+static int ddDoDumpDaVinci (DdManager *dd, DdNode *f, FILE *fp, st__table *visited, char **names, ptruint mask);
+static int ddDoDumpDDcal (DdManager *dd, DdNode *f, FILE *fp, st__table *visited, char **names, ptruint mask);
+static int ddDoDumpFactoredForm (DdManager *dd, DdNode *f, FILE *fp, char **names);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a blif file representing the argument BDDs.]
+
+  Description [Writes a blif file representing the argument BDDs as a
+  network of multiplexers. One multiplexer is written for each BDD
+  node. It returns 1 in case of success; 0 otherwise (e.g.,
+  out-of-memory, file system full, or an ADD with constants different
+  from 0 and 1).  Cudd_DumpBlif does not close the file: This is the
+  caller responsibility. Cudd_DumpBlif uses a minimal unique subset of
+  the hexadecimal address of a node as name for it.  If the argument
+  inames is non-null, it is assumed to hold the pointers to the names
+  of the inputs. Similarly for onames.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DumpBlifBody Cudd_DumpDot Cudd_PrintDebug Cudd_DumpDDcal
+  Cudd_DumpDaVinci Cudd_DumpFactoredForm]
+
+******************************************************************************/
+int
+Cudd_DumpBlif(
+  DdManager * dd /* manager */,
+  int  n /* number of output nodes to be dumped */,
+  DdNode ** f /* array of output nodes to be dumped */,
+  char ** inames /* array of input names (or NULL) */,
+  char ** onames /* array of output names (or NULL) */,
+  char * mname /* model name (or NULL) */,
+  FILE * fp /* pointer to the dump file */,
+  int mv /* 0: blif, 1: blif-MV */)
+{
+    DdNode      *support = NULL;
+    DdNode      *scan;
+    int         *sorted = NULL;
+    int         nvars = dd->size;
+    int         retval;
+    int         i;
+
+    /* Build a bit array with the support of f. */
+    sorted = ABC_ALLOC(int,nvars);
+    if (sorted == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        goto failure;
+    }
+    for (i = 0; i < nvars; i++) sorted[i] = 0;
+
+    /* Take the union of the supports of each output function. */
+    support = Cudd_VectorSupport(dd,f,n);
+    if (support == NULL) goto failure;
+    cuddRef(support);
+    scan = support;
+    while (!cuddIsConstant(scan)) {
+        sorted[scan->index] = 1;
+        scan = cuddT(scan);
+    }
+    Cudd_RecursiveDeref(dd,support);
+    support = NULL; /* so that we do not try to free it in case of failure */
+
+    /* Write the header (.model .inputs .outputs). */
+    if (mname == NULL) {
+        retval = fprintf(fp,".model DD\n.inputs");
+    } else {
+        retval = fprintf(fp,".model %s\n.inputs",mname);
+    }
+    if (retval == EOF) {
+        ABC_FREE(sorted);
+        return(0);
+    }
+
+    /* Write the input list by scanning the support array. */
+    for (i = 0; i < nvars; i++) {
+        if (sorted[i]) {
+            if (inames == NULL) {
+                retval = fprintf(fp," %d", i);
+            } else {
+                retval = fprintf(fp," %s", inames[i]);
+            }
+            if (retval == EOF) goto failure;
+        }
+    }
+    ABC_FREE(sorted);
+    sorted = NULL;
+
+    /* Write the .output line. */
+    retval = fprintf(fp,"\n.outputs");
+    if (retval == EOF) goto failure;
+    for (i = 0; i < n; i++) {
+        if (onames == NULL) {
+            retval = fprintf(fp," f%d", i);
+        } else {
+            retval = fprintf(fp," %s", onames[i]);
+        }
+        if (retval == EOF) goto failure;
+    }
+    retval = fprintf(fp,"\n");
+    if (retval == EOF) goto failure;
+
+    retval = Cudd_DumpBlifBody(dd, n, f, inames, onames, fp, mv);
+    if (retval == 0) goto failure;
+
+    /* Write trailer and return. */
+    retval = fprintf(fp,".end\n");
+    if (retval == EOF) goto failure;
+
+    return(1);
+
+failure:
+    if (sorted != NULL) ABC_FREE(sorted);
+    if (support != NULL) Cudd_RecursiveDeref(dd,support);
+    return(0);
+
+} /* end of Cudd_DumpBlif */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a blif body representing the argument BDDs.]
+
+  Description [Writes a blif body representing the argument BDDs as a
+  network of multiplexers.  No header (.model, .inputs, and .outputs) and
+  footer (.end) are produced by this function.  One multiplexer is written
+  for each BDD node. It returns 1 in case of success; 0 otherwise (e.g.,
+  out-of-memory, file system full, or an ADD with constants different
+  from 0 and 1).  Cudd_DumpBlifBody does not close the file: This is the
+  caller responsibility. Cudd_DumpBlifBody uses a minimal unique subset of
+  the hexadecimal address of a node as name for it.  If the argument
+  inames is non-null, it is assumed to hold the pointers to the names
+  of the inputs. Similarly for onames. This function prints out only
+  .names part.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DumpBlif Cudd_DumpDot Cudd_PrintDebug Cudd_DumpDDcal
+  Cudd_DumpDaVinci Cudd_DumpFactoredForm]
+
+******************************************************************************/
+int
+Cudd_DumpBlifBody(
+  DdManager * dd /* manager */,
+  int  n /* number of output nodes to be dumped */,
+  DdNode ** f /* array of output nodes to be dumped */,
+  char ** inames /* array of input names (or NULL) */,
+  char ** onames /* array of output names (or NULL) */,
+  FILE * fp /* pointer to the dump file */,
+  int mv /* 0: blif, 1: blif-MV */)
+{
+    st__table    *visited = NULL;
+    int         retval;
+    int         i;
+
+    /* Initialize symbol table for visited nodes. */
+    visited = st__init_table( st__ptrcmp, st__ptrhash);
+    if (visited == NULL) goto failure;
+
+    /* Call the function that really gets the job done. */
+    for (i = 0; i < n; i++) {
+        retval = ddDoDumpBlif(dd,Cudd_Regular(f[i]),fp,visited,inames,mv);
+        if (retval == 0) goto failure;
+    }
+
+    /* To account for the possible complement on the root,
+    ** we put either a buffer or an inverter at the output of
+    ** the multiplexer representing the top node.
+    */
+    for (i = 0; i < n; i++) {
+        if (onames == NULL) {
+            retval = fprintf(fp,
+#if SIZEOF_VOID_P == 8
+                ".names %lx f%d\n", (ptruint) f[i] / (ptruint) sizeof(DdNode), i);
+#else
+                ".names %x f%d\n", (ptruint) f[i] / (ptruint) sizeof(DdNode), i);
+#endif
+        } else {
+            retval = fprintf(fp,
+#if SIZEOF_VOID_P == 8
+                ".names %lx %s\n", (ptruint) f[i] / (ptruint) sizeof(DdNode), onames[i]);
+#else
+                ".names %x %s\n", (ptruint) f[i] / (ptruint) sizeof(DdNode), onames[i]);
+#endif
+        }
+        if (retval == EOF) goto failure;
+        if (Cudd_IsComplement(f[i])) {
+            retval = fprintf(fp,"%s0 1\n", mv ? ".def 0\n" : "");
+        } else {
+            retval = fprintf(fp,"%s1 1\n", mv ? ".def 0\n" : "");
+        }
+        if (retval == EOF) goto failure;
+    }
+
+    st__free_table(visited);
+    return(1);
+
+failure:
+    if (visited != NULL) st__free_table(visited);
+    return(0);
+
+} /* end of Cudd_DumpBlifBody */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a dot file representing the argument DDs.]
+
+  Description [Writes a file representing the argument DDs in a format
+  suitable for the graph drawing program dot.
+  It returns 1 in case of success; 0 otherwise (e.g., out-of-memory,
+  file system full).
+  Cudd_DumpDot does not close the file: This is the caller
+  responsibility. Cudd_DumpDot uses a minimal unique subset of the
+  hexadecimal address of a node as name for it.
+  If the argument inames is non-null, it is assumed to hold the pointers
+  to the names of the inputs. Similarly for onames.
+  Cudd_DumpDot uses the following convention to draw arcs:
+    <ul>
+    <li> solid line: THEN arcs;
+    <li> dotted line: complement arcs;
+    <li> dashed line: regular ELSE arcs.
+    </ul>
+  The dot options are chosen so that the drawing fits on a letter-size
+  sheet.
+  ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DumpBlif Cudd_PrintDebug Cudd_DumpDDcal
+  Cudd_DumpDaVinci Cudd_DumpFactoredForm]
+
+******************************************************************************/
+int
+Cudd_DumpDot(
+  DdManager * dd /* manager */,
+  int  n /* number of output nodes to be dumped */,
+  DdNode ** f /* array of output nodes to be dumped */,
+  char ** inames /* array of input names (or NULL) */,
+  char ** onames /* array of output names (or NULL) */,
+  FILE * fp /* pointer to the dump file */)
+{
+    DdNode      *support = NULL;
+    DdNode      *scan;
+    int         *sorted = NULL;
+    int         nvars = dd->size;
+    st__table    *visited = NULL;
+    st__generator *gen = NULL;
+    int         retval;
+    int         i, j;
+    int         slots;
+    DdNodePtr   *nodelist;
+    long        refAddr, diff, mask;
+
+    /* Build a bit array with the support of f. */
+    sorted = ABC_ALLOC(int,nvars);
+    if (sorted == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        goto failure;
+    }
+    for (i = 0; i < nvars; i++) sorted[i] = 0;
+
+    /* Take the union of the supports of each output function. */
+    support = Cudd_VectorSupport(dd,f,n);
+    if (support == NULL) goto failure;
+    cuddRef(support);
+    scan = support;
+    while (!cuddIsConstant(scan)) {
+        sorted[scan->index] = 1;
+        scan = cuddT(scan);
+    }
+    Cudd_RecursiveDeref(dd,support);
+    support = NULL; /* so that we do not try to free it in case of failure */
+
+    /* Initialize symbol table for visited nodes. */
+    visited = st__init_table( st__ptrcmp, st__ptrhash);
+    if (visited == NULL) goto failure;
+
+    /* Collect all the nodes of this DD in the symbol table. */
+    for (i = 0; i < n; i++) {
+        retval = cuddCollectNodes(Cudd_Regular(f[i]),visited);
+        if (retval == 0) goto failure;
+    }
+
+    /* Find how many most significant hex digits are identical
+    ** in the addresses of all the nodes. Build a mask based
+    ** on this knowledge, so that digits that carry no information
+    ** will not be printed. This is done in two steps.
+    **  1. We scan the symbol table to find the bits that differ
+    **     in at least 2 addresses.
+    **  2. We choose one of the possible masks. There are 8 possible
+    **     masks for 32-bit integer, and 16 possible masks for 64-bit
+    **     integers.
+    */
+
+    /* Find the bits that are different. */
+    refAddr = (long) Cudd_Regular(f[0]);
+    diff = 0;
+    gen = st__init_gen(visited);
+    if (gen == NULL) goto failure;
+    while ( st__gen(gen, (const char **)&scan, NULL)) {
+        diff |= refAddr ^ (long) scan;
+    }
+    st__free_gen(gen); gen = NULL;
+
+    /* Choose the mask. */
+    for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) {
+        mask = (1 << i) - 1;
+        if (diff <= mask) break;
+    }
+
+    /* Write the header and the global attributes. */
+    retval = fprintf(fp,"digraph \"DD\" {\n");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,
+        "size = \"7.5,10\"\ncenter = true;\nedge [dir = none];\n");
+    if (retval == EOF) return(0);
+
+    /* Write the input name subgraph by scanning the support array. */
+    retval = fprintf(fp,"{ node [shape = plaintext];\n");
+    if (retval == EOF) goto failure;
+    retval = fprintf(fp,"  edge [style = invis];\n");
+    if (retval == EOF) goto failure;
+    /* We use a name ("CONST NODES") with an embedded blank, because
+    ** it is unlikely to appear as an input name.
+    */
+    retval = fprintf(fp,"  \"CONST NODES\" [style = invis];\n");
+    if (retval == EOF) goto failure;
+    for (i = 0; i < nvars; i++) {
+        if (sorted[dd->invperm[i]]) {
+            if (inames == NULL || inames[dd->invperm[i]] == NULL) {
+                retval = fprintf(fp,"\" %d \" -> ", dd->invperm[i]);
+            } else {
+                retval = fprintf(fp,"\" %s \" -> ", inames[dd->invperm[i]]);
+            }
+            if (retval == EOF) goto failure;
+        }
+    }
+    retval = fprintf(fp,"\"CONST NODES\"; \n}\n");
+    if (retval == EOF) goto failure;
+
+    /* Write the output node subgraph. */
+    retval = fprintf(fp,"{ rank = same; node [shape = box]; edge [style = invis];\n");
+    if (retval == EOF) goto failure;
+    for (i = 0; i < n; i++) {
+        if (onames == NULL) {
+            retval = fprintf(fp,"\"F%d\"", i);
+        } else {
+            retval = fprintf(fp,"\"  %s  \"", onames[i]);
+        }
+        if (retval == EOF) goto failure;
+        if (i == n - 1) {
+            retval = fprintf(fp,"; }\n");
+        } else {
+            retval = fprintf(fp," -> ");
+        }
+        if (retval == EOF) goto failure;
+    }
+
+    /* Write rank info: All nodes with the same index have the same rank. */
+    for (i = 0; i < nvars; i++) {
+        if (sorted[dd->invperm[i]]) {
+            retval = fprintf(fp,"{ rank = same; ");
+            if (retval == EOF) goto failure;
+            if (inames == NULL || inames[dd->invperm[i]] == NULL) {
+                retval = fprintf(fp,"\" %d \";\n", dd->invperm[i]);
+            } else {
+                retval = fprintf(fp,"\" %s \";\n", inames[dd->invperm[i]]);
+            }
+            if (retval == EOF) goto failure;
+            nodelist = dd->subtables[i].nodelist;
+            slots = dd->subtables[i].slots;
+            for (j = 0; j < slots; j++) {
+                scan = nodelist[j];
+                while (scan != NULL) {
+                    if ( st__is_member(visited,(char *) scan)) {
+                        retval = fprintf(fp,"\"%lx\";\n", ((mask & (ptrint) scan) / sizeof(DdNode)));
+                        if (retval == EOF) goto failure;
+                    }
+                    scan = scan->next;
+                }
+            }
+            retval = fprintf(fp,"}\n");
+            if (retval == EOF) goto failure;
+        }
+    }
+
+    /* All constants have the same rank. */
+    retval = fprintf(fp,
+        "{ rank = same; \"CONST NODES\";\n{ node [shape = box]; ");
+    if (retval == EOF) goto failure;
+    nodelist = dd->constants.nodelist;
+    slots = dd->constants.slots;
+    for (j = 0; j < slots; j++) {
+        scan = nodelist[j];
+        while (scan != NULL) {
+            if ( st__is_member(visited,(char *) scan)) {
+                retval = fprintf(fp,"\"%lx\";\n", ((mask & (ptrint) scan) / sizeof(DdNode)));
+                if (retval == EOF) goto failure;
+            }
+            scan = scan->next;
+        }
+    }
+    retval = fprintf(fp,"}\n}\n");
+    if (retval == EOF) goto failure;
+
+    /* Write edge info. */
+    /* Edges from the output nodes. */
+    for (i = 0; i < n; i++) {
+        if (onames == NULL) {
+            retval = fprintf(fp,"\"F%d\"", i);
+        } else {
+            retval = fprintf(fp,"\"  %s  \"", onames[i]);
+        }
+        if (retval == EOF) goto failure;
+        /* Account for the possible complement on the root. */
+        if (Cudd_IsComplement(f[i])) {
+            retval = fprintf(fp," -> \"%lx\" [style = dotted];\n", ((mask & (ptrint) f[i]) / sizeof(DdNode)));
+        } else {
+            retval = fprintf(fp," -> \"%lx\" [style = solid];\n", ((mask & (ptrint) f[i]) / sizeof(DdNode)));
+        }
+        if (retval == EOF) goto failure;
+    }
+
+    /* Edges from internal nodes. */
+    for (i = 0; i < nvars; i++) {
+        if (sorted[dd->invperm[i]]) {
+            nodelist = dd->subtables[i].nodelist;
+            slots = dd->subtables[i].slots;
+            for (j = 0; j < slots; j++) {
+                scan = nodelist[j];
+                while (scan != NULL) {
+                    if ( st__is_member(visited,(char *) scan)) {
+                        retval = fprintf(fp, "\"%lx\" -> \"%lx\";\n", 
+                            ((mask & (ptrint) scan) / sizeof(DdNode)),
+                            ((mask & (ptrint) cuddT(scan)) / sizeof(DdNode)));
+                        if (retval == EOF) goto failure;
+                        if (Cudd_IsComplement(cuddE(scan))) {
+                            retval = fprintf(fp,"\"%lx\" -> \"%lx\" [style = dotted];\n", 
+                                ((mask & (ptrint) scan) / sizeof(DdNode)),
+                                ((mask & (ptrint) cuddE(scan)) / sizeof(DdNode)));
+                        } else {
+                            retval = fprintf(fp, "\"%lx\" -> \"%lx\" [style = dashed];\n", 
+                                ((mask & (ptrint) scan) / sizeof(DdNode)),
+                                ((mask & (ptrint) cuddE(scan)) / sizeof(DdNode)));
+                        }
+                        if (retval == EOF) goto failure;
+                    }
+                    scan = scan->next;
+                }
+            }
+        }
+    }
+
+    /* Write constant labels. */
+    nodelist = dd->constants.nodelist;
+    slots = dd->constants.slots;
+    for (j = 0; j < slots; j++) {
+        scan = nodelist[j];
+        while (scan != NULL) {
+            if ( st__is_member(visited,(char *) scan)) {
+                retval = fprintf(fp,"\"%lx\" [label = \"%g\"];\n", 
+                    ((mask & (ptrint) scan) / sizeof(DdNode)), cuddV(scan));
+                if (retval == EOF) goto failure;
+            }
+            scan = scan->next;
+        }
+    }
+
+    /* Write trailer and return. */
+    retval = fprintf(fp,"}\n");
+    if (retval == EOF) goto failure;
+
+    st__free_table(visited);
+    ABC_FREE(sorted);
+    return(1);
+
+failure:
+    if (sorted != NULL) ABC_FREE(sorted);
+    if (support != NULL) Cudd_RecursiveDeref(dd,support);
+    if (visited != NULL) st__free_table(visited);
+    return(0);
+
+} /* end of Cudd_DumpDot */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a daVinci file representing the argument BDDs.]
+
+  Description [Writes a daVinci file representing the argument BDDs.
+  It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or
+  file system full).  Cudd_DumpDaVinci does not close the file: This
+  is the caller responsibility. Cudd_DumpDaVinci uses a minimal unique
+  subset of the hexadecimal address of a node as name for it.  If the
+  argument inames is non-null, it is assumed to hold the pointers to
+  the names of the inputs. Similarly for onames.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDDcal
+  Cudd_DumpFactoredForm]
+
+******************************************************************************/
+int
+Cudd_DumpDaVinci(
+  DdManager * dd /* manager */,
+  int  n /* number of output nodes to be dumped */,
+  DdNode ** f /* array of output nodes to be dumped */,
+  char ** inames /* array of input names (or NULL) */,
+  char ** onames /* array of output names (or NULL) */,
+  FILE * fp /* pointer to the dump file */)
+{
+    DdNode        *support = NULL;
+    DdNode        *scan;
+    st__table      *visited = NULL;
+    int           retval;
+    int           i;
+    st__generator  *gen;
+    ptruint       refAddr, diff, mask;
+
+    /* Initialize symbol table for visited nodes. */
+    visited = st__init_table( st__ptrcmp, st__ptrhash);
+    if (visited == NULL) goto failure;
+
+    /* Collect all the nodes of this DD in the symbol table. */
+    for (i = 0; i < n; i++) {
+        retval = cuddCollectNodes(Cudd_Regular(f[i]),visited);
+        if (retval == 0) goto failure;
+    }
+
+    /* Find how many most significant hex digits are identical
+    ** in the addresses of all the nodes. Build a mask based
+    ** on this knowledge, so that digits that carry no information
+    ** will not be printed. This is done in two steps.
+    **  1. We scan the symbol table to find the bits that differ
+    **     in at least 2 addresses.
+    **  2. We choose one of the possible masks. There are 8 possible
+    **     masks for 32-bit integer, and 16 possible masks for 64-bit
+    **     integers.
+    */
+
+    /* Find the bits that are different. */
+    refAddr = (ptruint) Cudd_Regular(f[0]);
+    diff = 0;
+    gen = st__init_gen(visited);
+    while ( st__gen(gen, (const char **)&scan, NULL)) {
+        diff |= refAddr ^ (ptruint) scan;
+    }
+    st__free_gen(gen);
+
+    /* Choose the mask. */
+    for (i = 0; (unsigned) i < 8 * sizeof(ptruint); i += 4) {
+        mask = (1 << i) - 1;
+        if (diff <= mask) break;
+    }
+    st__free_table(visited);
+
+    /* Initialize symbol table for visited nodes. */
+    visited = st__init_table( st__ptrcmp, st__ptrhash);
+    if (visited == NULL) goto failure;
+
+    retval = fprintf(fp, "[");
+    if (retval == EOF) goto failure;
+    /* Call the function that really gets the job done. */
+    for (i = 0; i < n; i++) {
+        if (onames == NULL) {
+            retval = fprintf(fp,
+                             "l(\"f%d\",n(\"root\",[a(\"OBJECT\",\"f%d\")],",
+                             i,i);
+        } else {
+            retval = fprintf(fp,
+                             "l(\"%s\",n(\"root\",[a(\"OBJECT\",\"%s\")],",
+                             onames[i], onames[i]);
+        }
+        if (retval == EOF) goto failure;
+        retval = fprintf(fp, "[e(\"edge\",[a(\"EDGECOLOR\",\"%s\"),a(\"_DIR\",\"none\")],",
+                         Cudd_IsComplement(f[i]) ? "red" : "blue");
+        if (retval == EOF) goto failure;
+        retval = ddDoDumpDaVinci(dd,Cudd_Regular(f[i]),fp,visited,inames,mask);
+        if (retval == 0) goto failure;
+        retval = fprintf(fp, ")]))%s", i == n-1 ? "" : ",");
+        if (retval == EOF) goto failure;
+    }
+
+    /* Write trailer and return. */
+    retval = fprintf(fp, "]\n");
+    if (retval == EOF) goto failure;
+
+    st__free_table(visited);
+    return(1);
+
+failure:
+    if (support != NULL) Cudd_RecursiveDeref(dd,support);
+    if (visited != NULL) st__free_table(visited);
+    return(0);
+
+} /* end of Cudd_DumpDaVinci */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a DDcal file representing the argument BDDs.]
+
+  Description [Writes a DDcal file representing the argument BDDs.
+  It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or
+  file system full).  Cudd_DumpDDcal does not close the file: This
+  is the caller responsibility. Cudd_DumpDDcal uses a minimal unique
+  subset of the hexadecimal address of a node as name for it.  If the
+  argument inames is non-null, it is assumed to hold the pointers to
+  the names of the inputs. Similarly for onames.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDaVinci
+  Cudd_DumpFactoredForm]
+
+******************************************************************************/
+int
+Cudd_DumpDDcal(
+  DdManager * dd /* manager */,
+  int  n /* number of output nodes to be dumped */,
+  DdNode ** f /* array of output nodes to be dumped */,
+  char ** inames /* array of input names (or NULL) */,
+  char ** onames /* array of output names (or NULL) */,
+  FILE * fp /* pointer to the dump file */)
+{
+    DdNode        *support = NULL;
+    DdNode        *scan;
+    int           *sorted = NULL;
+    int           nvars = dd->size;
+    st__table      *visited = NULL;
+    int           retval;
+    int           i;
+    st__generator  *gen;
+    ptruint       refAddr, diff, mask;
+
+    /* Initialize symbol table for visited nodes. */
+    visited = st__init_table( st__ptrcmp, st__ptrhash);
+    if (visited == NULL) goto failure;
+
+    /* Collect all the nodes of this DD in the symbol table. */
+    for (i = 0; i < n; i++) {
+        retval = cuddCollectNodes(Cudd_Regular(f[i]),visited);
+        if (retval == 0) goto failure;
+    }
+
+    /* Find how many most significant hex digits are identical
+    ** in the addresses of all the nodes. Build a mask based
+    ** on this knowledge, so that digits that carry no information
+    ** will not be printed. This is done in two steps.
+    **  1. We scan the symbol table to find the bits that differ
+    **     in at least 2 addresses.
+    **  2. We choose one of the possible masks. There are 8 possible
+    **     masks for 32-bit integer, and 16 possible masks for 64-bit
+    **     integers.
+    */
+
+    /* Find the bits that are different. */
+    refAddr = (ptruint) Cudd_Regular(f[0]);
+    diff = 0;
+    gen = st__init_gen(visited);
+    while ( st__gen(gen, (const char **)&scan, NULL)) {
+        diff |= refAddr ^ (ptruint) scan;
+    }
+    st__free_gen(gen);
+
+    /* Choose the mask. */
+    for (i = 0; (unsigned) i < 8 * sizeof(ptruint); i += 4) {
+        mask = (1 << i) - 1;
+        if (diff <= mask) break;
+    }
+    st__free_table(visited);
+    visited = NULL;
+
+    /* Build a bit array with the support of f. */
+    sorted = ABC_ALLOC(int,nvars);
+    if (sorted == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        goto failure;
+    }
+    for (i = 0; i < nvars; i++) sorted[i] = 0;
+
+    /* Take the union of the supports of each output function. */
+    support = Cudd_VectorSupport(dd,f,n);
+    if (support == NULL) goto failure;
+    cuddRef(support);
+    scan = support;
+    while (!cuddIsConstant(scan)) {
+        sorted[scan->index] = 1;
+        scan = cuddT(scan);
+    }
+    Cudd_RecursiveDeref(dd,support);
+    support = NULL; /* so that we do not try to free it in case of failure */
+    for (i = 0; i < nvars; i++) {
+        if (sorted[dd->invperm[i]]) {
+            if (inames == NULL || inames[dd->invperm[i]] == NULL) {
+                retval = fprintf(fp,"v%d", dd->invperm[i]);
+            } else {
+                retval = fprintf(fp,"%s", inames[dd->invperm[i]]);
+            }
+            if (retval == EOF) goto failure;
+        }
+        retval = fprintf(fp,"%s", i == nvars - 1 ? "\n" : " * ");
+        if (retval == EOF) goto failure;
+    }
+    ABC_FREE(sorted);
+    sorted = NULL;
+
+    /* Initialize symbol table for visited nodes. */
+    visited = st__init_table( st__ptrcmp, st__ptrhash);
+    if (visited == NULL) goto failure;
+
+    /* Call the function that really gets the job done. */
+    for (i = 0; i < n; i++) {
+        retval = ddDoDumpDDcal(dd,Cudd_Regular(f[i]),fp,visited,inames,mask);
+        if (retval == 0) goto failure;
+        if (onames == NULL) {
+            retval = fprintf(fp, "f%d = ", i);
+        } else {
+            retval = fprintf(fp, "%s = ", onames[i]);
+        }
+        if (retval == EOF) goto failure;
+        retval = fprintf(fp, "n%p%s\n",
+                         (void *) (((ptruint) f[i] & mask) /
+                         (ptruint) sizeof(DdNode)),
+                         Cudd_IsComplement(f[i]) ? "'" : "");
+        if (retval == EOF) goto failure;
+    }
+
+    /* Write trailer and return. */
+    retval = fprintf(fp, "[");
+    if (retval == EOF) goto failure;
+    for (i = 0; i < n; i++) {
+        if (onames == NULL) {
+            retval = fprintf(fp, "f%d", i);
+        } else {
+            retval = fprintf(fp, "%s", onames[i]);
+        }
+        retval = fprintf(fp, "%s", i == n-1 ? "" : " ");
+        if (retval == EOF) goto failure;
+    }
+    retval = fprintf(fp, "]\n");
+    if (retval == EOF) goto failure;
+
+    if ( visited )
+        st__free_table(visited);
+    return(1);
+
+failure:
+    if (sorted != NULL) ABC_FREE(sorted);
+    if (support != NULL) Cudd_RecursiveDeref(dd,support);
+    if (visited != NULL) st__free_table(visited);
+    return(0);
+
+} /* end of Cudd_DumpDDcal */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes factored forms representing the argument BDDs.]
+
+  Description [Writes factored forms representing the argument BDDs.
+  The format of the factored form is the one used in the genlib files
+  for technology mapping in sis.  It returns 1 in case of success; 0
+  otherwise (e.g., file system full).  Cudd_DumpFactoredForm does not
+  close the file: This is the caller responsibility. Caution must be
+  exercised because a factored form may be exponentially larger than
+  the argument BDD.  If the argument inames is non-null, it is assumed
+  to hold the pointers to the names of the inputs. Similarly for
+  onames.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDaVinci
+  Cudd_DumpDDcal]
+
+******************************************************************************/
+int
+Cudd_DumpFactoredForm(
+  DdManager * dd /* manager */,
+  int  n /* number of output nodes to be dumped */,
+  DdNode ** f /* array of output nodes to be dumped */,
+  char ** inames /* array of input names (or NULL) */,
+  char ** onames /* array of output names (or NULL) */,
+  FILE * fp /* pointer to the dump file */)
+{
+    int         retval;
+    int         i;
+
+    /* Call the function that really gets the job done. */
+    for (i = 0; i < n; i++) {
+        if (onames == NULL) {
+            retval = fprintf(fp, "f%d = ", i);
+        } else {
+            retval = fprintf(fp, "%s = ", onames[i]);
+        }
+        if (retval == EOF) return(0);
+        if (f[i] == DD_ONE(dd)) {
+            retval = fprintf(fp, "CONST1");
+            if (retval == EOF) return(0);
+        } else if (f[i] == Cudd_Not(DD_ONE(dd)) || f[i] == DD_ZERO(dd)) {
+            retval = fprintf(fp, "CONST0");
+            if (retval == EOF) return(0);
+        } else {
+            retval = fprintf(fp, "%s", Cudd_IsComplement(f[i]) ? "!(" : "");
+            if (retval == EOF) return(0);
+            retval = ddDoDumpFactoredForm(dd,Cudd_Regular(f[i]),fp,inames);
+            if (retval == 0) return(0);
+            retval = fprintf(fp, "%s", Cudd_IsComplement(f[i]) ? ")" : "");
+            if (retval == EOF) return(0);
+        }
+        retval = fprintf(fp, "%s", i == n-1 ? "" : "\n");
+        if (retval == EOF) return(0);
+    }
+
+    return(1);
+
+} /* end of Cudd_DumpFactoredForm */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_DumpBlif.]
+
+  Description [Performs the recursive step of Cudd_DumpBlif. Traverses
+  the BDD f and writes a multiplexer-network description to the file
+  pointed by fp in blif format. f is assumed to be a regular pointer
+  and ddDoDumpBlif guarantees this assumption in the recursive calls.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddDoDumpBlif(
+  DdManager * dd,
+  DdNode * f,
+  FILE * fp,
+  st__table * visited,
+  char ** names,
+  int mv)
+{
+    DdNode      *T, *E;
+    int         retval;
+
+#ifdef DD_DEBUG
+    assert(!Cudd_IsComplement(f));
+#endif
+
+    /* If already visited, nothing to do. */
+    if ( st__is_member(visited, (char *) f) == 1)
+        return(1);
+
+    /* Check for abnormal condition that should never happen. */
+    if (f == NULL)
+        return(0);
+
+    /* Mark node as visited. */
+    if ( st__insert(visited, (char *) f, NULL) == st__OUT_OF_MEM)
+        return(0);
+
+    /* Check for special case: If constant node, generate constant 1. */
+    if (f == DD_ONE(dd)) {
+#if SIZEOF_VOID_P == 8
+        retval = fprintf(fp, ".names %lx\n1\n",(ptruint) f / (ptruint) sizeof(DdNode));
+#else
+        retval = fprintf(fp, ".names %x\n1\n",(ptruint) f / (ptruint) sizeof(DdNode));
+#endif
+        if (retval == EOF) {
+            return(0);
+        } else {
+            return(1);
+        }
+    }
+
+    /* Check whether this is an ADD. We deal with 0-1 ADDs, but not
+    ** with the general case.
+    */
+    if (f == DD_ZERO(dd)) {
+#if SIZEOF_VOID_P == 8
+        retval = fprintf(fp, ".names %lx\n%s",
+                         (ptruint) f / (ptruint) sizeof(DdNode),
+                         mv ? "0\n" : "");
+#else
+        retval = fprintf(fp, ".names %x\n%s",
+                         (ptruint) f / (ptruint) sizeof(DdNode),
+                         mv ? "0\n" : "");
+#endif
+        if (retval == EOF) {
+            return(0);
+        } else {
+            return(1);
+        }
+    }
+    if (cuddIsConstant(f))
+        return(0);
+
+    /* Recursive calls. */
+    T = cuddT(f);
+    retval = ddDoDumpBlif(dd,T,fp,visited,names,mv);
+    if (retval != 1) return(retval);
+    E = Cudd_Regular(cuddE(f));
+    retval = ddDoDumpBlif(dd,E,fp,visited,names,mv);
+    if (retval != 1) return(retval);
+
+    /* Write multiplexer taking complement arc into account. */
+    if (names != NULL) {
+        retval = fprintf(fp,".names %s", names[f->index]);
+    } else {
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+        retval = fprintf(fp,".names %u", f->index);
+#else
+        retval = fprintf(fp,".names %hu", f->index);
+#endif
+    }
+    if (retval == EOF)
+        return(0);
+
+#if SIZEOF_VOID_P == 8
+    if (mv) {
+        if (Cudd_IsComplement(cuddE(f))) {
+            retval = fprintf(fp," %lx %lx %lx\n.def 0\n1 1 - 1\n0 - 0 1\n",
+                (ptruint) T / (ptruint) sizeof(DdNode),
+                (ptruint) E / (ptruint) sizeof(DdNode),
+                (ptruint) f / (ptruint) sizeof(DdNode));
+        } else {
+            retval = fprintf(fp," %lx %lx %lx\n.def 0\n1 1 - 1\n0 - 1 1\n",
+                (ptruint) T / (ptruint) sizeof(DdNode),
+                (ptruint) E / (ptruint) sizeof(DdNode),
+                (ptruint) f / (ptruint) sizeof(DdNode));
+        }
+    } else {
+        if (Cudd_IsComplement(cuddE(f))) {
+            retval = fprintf(fp," %lx %lx %lx\n11- 1\n0-0 1\n",
+                (ptruint) T / (ptruint) sizeof(DdNode),
+                (ptruint) E / (ptruint) sizeof(DdNode),
+                (ptruint) f / (ptruint) sizeof(DdNode));
+        } else {
+            retval = fprintf(fp," %lx %lx %lx\n11- 1\n0-1 1\n",
+                (ptruint) T / (ptruint) sizeof(DdNode),
+                (ptruint) E / (ptruint) sizeof(DdNode),
+                (ptruint) f / (ptruint) sizeof(DdNode));
+        }
+    }
+#else
+    if (mv) {
+        if (Cudd_IsComplement(cuddE(f))) {
+            retval = fprintf(fp," %x %x %x\n.def 0\n1 1 - 1\n0 - 0 1\n",
+                (ptruint) T / (ptruint) sizeof(DdNode),
+                (ptruint) E / (ptruint) sizeof(DdNode),
+                (ptruint) f / (ptruint) sizeof(DdNode));
+        } else {
+            retval = fprintf(fp," %x %x %x\n.def 0\n1 1 - 1\n0 - 1 1\n",
+                (ptruint) T / (ptruint) sizeof(DdNode),
+                (ptruint) E / (ptruint) sizeof(DdNode),
+                (ptruint) f / (ptruint) sizeof(DdNode));
+        }
+    } else {
+        if (Cudd_IsComplement(cuddE(f))) {
+            retval = fprintf(fp," %x %x %x\n11- 1\n0-0 1\n",
+                (ptruint) T / (ptruint) sizeof(DdNode),
+                (ptruint) E / (ptruint) sizeof(DdNode),
+                (ptruint) f / (ptruint) sizeof(DdNode));
+        } else {
+            retval = fprintf(fp," %x %x %x\n11- 1\n0-1 1\n",
+                (ptruint) T / (ptruint) sizeof(DdNode),
+                (ptruint) E / (ptruint) sizeof(DdNode),
+                (ptruint) f / (ptruint) sizeof(DdNode));
+        }
+    }
+#endif
+    if (retval == EOF) {
+        return(0);
+    } else {
+        return(1);
+    }
+
+} /* end of ddDoDumpBlif */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_DumpDaVinci.]
+
+  Description [Performs the recursive step of Cudd_DumpDaVinci. Traverses
+  the BDD f and writes a term expression to the file
+  pointed by fp in daVinci format. f is assumed to be a regular pointer
+  and ddDoDumpDaVinci guarantees this assumption in the recursive calls.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddDoDumpDaVinci(
+  DdManager * dd,
+  DdNode * f,
+  FILE * fp,
+  st__table * visited,
+  char ** names,
+  ptruint mask)
+{
+    DdNode  *T, *E;
+    int     retval;
+    ptruint id;
+
+#ifdef DD_DEBUG
+    assert(!Cudd_IsComplement(f));
+#endif
+
+    id = ((ptruint) f & mask) / sizeof(DdNode);
+
+    /* If already visited, insert a reference. */
+    if ( st__is_member(visited, (char *) f) == 1) {
+        retval = fprintf(fp,"r(\"%p\")", (void *) id);
+        if (retval == EOF) {
+            return(0);
+        } else {
+            return(1);
+        }
+    }
+
+    /* Check for abnormal condition that should never happen. */
+    if (f == NULL)
+        return(0);
+
+    /* Mark node as visited. */
+    if ( st__insert(visited, (char *) f, NULL) == st__OUT_OF_MEM)
+        return(0);
+
+    /* Check for special case: If constant node, generate constant 1. */
+    if (Cudd_IsConstant(f)) {
+        retval = fprintf(fp,
+                         "l(\"%p\",n(\"constant\",[a(\"OBJECT\",\"%g\")],[]))",
+                         (void *) id, cuddV(f));
+        if (retval == EOF) {
+            return(0);
+        } else {
+            return(1);
+        }
+    }
+
+    /* Recursive calls. */
+    if (names != NULL) {
+        retval = fprintf(fp,
+                         "l(\"%p\",n(\"internal\",[a(\"OBJECT\",\"%s\"),",
+                         (void *) id, names[f->index]);
+    } else {
+        retval = fprintf(fp,
+#if SIZEOF_VOID_P == 8
+                         "l(\"%p\",n(\"internal\",[a(\"OBJECT\",\"%u\"),",
+#else
+                         "l(\"%p\",n(\"internal\",[a(\"OBJECT\",\"%hu\"),",
+#endif
+                         (void *) id, f->index);
+    }
+    retval = fprintf(fp, "a(\"_GO\",\"ellipse\")],[e(\"then\",[a(\"EDGECOLOR\",\"blue\"),a(\"_DIR\",\"none\")],");
+    if (retval == EOF) return(0);
+    T = cuddT(f);
+    retval = ddDoDumpDaVinci(dd,T,fp,visited,names,mask);
+    if (retval != 1) return(retval);
+    retval = fprintf(fp, "),e(\"else\",[a(\"EDGECOLOR\",\"%s\"),a(\"_DIR\",\"none\")],",
+                     Cudd_IsComplement(cuddE(f)) ? "red" : "green");
+    if (retval == EOF) return(0);
+    E = Cudd_Regular(cuddE(f));
+    retval = ddDoDumpDaVinci(dd,E,fp,visited,names,mask);
+    if (retval != 1) return(retval);
+
+    retval = fprintf(fp,")]))");
+    if (retval == EOF) {
+        return(0);
+    } else {
+        return(1);
+    }
+
+} /* end of ddDoDumpDaVinci */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_DumpDDcal.]
+
+  Description [Performs the recursive step of Cudd_DumpDDcal. Traverses
+  the BDD f and writes a line for each node to the file
+  pointed by fp in DDcal format. f is assumed to be a regular pointer
+  and ddDoDumpDDcal guarantees this assumption in the recursive calls.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddDoDumpDDcal(
+  DdManager * dd,
+  DdNode * f,
+  FILE * fp,
+  st__table * visited,
+  char ** names,
+  ptruint mask)
+{
+    DdNode  *T, *E;
+    int     retval;
+    ptruint id, idT, idE;
+
+#ifdef DD_DEBUG
+    assert(!Cudd_IsComplement(f));
+#endif
+
+    id = ((ptruint) f & mask) / sizeof(DdNode);
+
+    /* If already visited, do nothing. */
+    if ( st__is_member(visited, (char *) f) == 1) {
+        return(1);
+    }
+
+    /* Check for abnormal condition that should never happen. */
+    if (f == NULL)
+        return(0);
+
+    /* Mark node as visited. */
+    if ( st__insert(visited, (char *) f, NULL) == st__OUT_OF_MEM)
+        return(0);
+
+    /* Check for special case: If constant node, assign constant. */
+    if (Cudd_IsConstant(f)) {
+        if (f != DD_ONE(dd) && f != DD_ZERO(dd))
+            return(0);
+        retval = fprintf(fp, "n%p = %g\n", (void *) id, cuddV(f));
+        if (retval == EOF) {
+            return(0);
+        } else {
+            return(1);
+        }
+    }
+
+    /* Recursive calls. */
+    T = cuddT(f);
+    retval = ddDoDumpDDcal(dd,T,fp,visited,names,mask);
+    if (retval != 1) return(retval);
+    E = Cudd_Regular(cuddE(f));
+    retval = ddDoDumpDDcal(dd,E,fp,visited,names,mask);
+    if (retval != 1) return(retval);
+    idT = ((ptruint) T & mask) / sizeof(DdNode);
+    idE = ((ptruint) E & mask) / sizeof(DdNode);
+    if (names != NULL) {
+        retval = fprintf(fp, "n%p = %s * n%p + %s' * n%p%s\n",
+                         (void *) id, names[f->index],
+                         (void *) idT, names[f->index],
+                         (void *) idE, Cudd_IsComplement(cuddE(f)) ? "'" : "");
+    } else {
+#if SIZEOF_VOID_P == 8
+        retval = fprintf(fp, "n%p = v%u * n%p + v%u' * n%p%s\n",
+#else
+        retval = fprintf(fp, "n%p = v%hu * n%p + v%hu' * n%p%s\n",
+#endif
+                         (void *) id, f->index,
+                         (void *) idT, f->index,
+                         (void *) idE, Cudd_IsComplement(cuddE(f)) ? "'" : "");
+    }
+    if (retval == EOF) {
+        return(0);
+    } else {
+        return(1);
+    }
+
+} /* end of ddDoDumpDDcal */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_DumpFactoredForm.]
+
+  Description [Performs the recursive step of
+  Cudd_DumpFactoredForm. Traverses the BDD f and writes a factored
+  form for each node to the file pointed by fp in terms of the
+  factored forms of the children. Constants are propagated, and
+  absorption is applied.  f is assumed to be a regular pointer and
+  ddDoDumpFActoredForm guarantees this assumption in the recursive
+  calls.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DumpFactoredForm]
+
+******************************************************************************/
+static int
+ddDoDumpFactoredForm(
+  DdManager * dd,
+  DdNode * f,
+  FILE * fp,
+  char ** names)
+{
+    DdNode      *T, *E;
+    int         retval;
+
+#ifdef DD_DEBUG
+    assert(!Cudd_IsComplement(f));
+    assert(!Cudd_IsConstant(f));
+#endif
+
+    /* Check for abnormal condition that should never happen. */
+    if (f == NULL)
+        return(0);
+
+    /* Recursive calls. */
+    T = cuddT(f);
+    E = cuddE(f);
+    if (T != DD_ZERO(dd)) {
+        if (E != DD_ONE(dd)) {
+            if (names != NULL) {
+                retval = fprintf(fp, "%s", names[f->index]);
+            } else {
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+                retval = fprintf(fp, "x%u", f->index);
+#else
+                retval = fprintf(fp, "x%hu", f->index);
+#endif
+            }
+            if (retval == EOF) return(0);
+        }
+        if (T != DD_ONE(dd)) {
+            retval = fprintf(fp, "%s(", E != DD_ONE(dd) ? " * " : "");
+            if (retval == EOF) return(0);
+            retval = ddDoDumpFactoredForm(dd,T,fp,names);
+            if (retval != 1) return(retval);
+            retval = fprintf(fp, ")");
+            if (retval == EOF) return(0);
+        }
+        if (E == Cudd_Not(DD_ONE(dd)) || E == DD_ZERO(dd)) return(1);
+        retval = fprintf(fp, " + ");
+        if (retval == EOF) return(0);
+    }
+    E = Cudd_Regular(E);
+    if (T != DD_ONE(dd)) {
+        if (names != NULL) {
+            retval = fprintf(fp, "!%s", names[f->index]);
+        } else {
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+            retval = fprintf(fp, "!x%u", f->index);
+#else
+            retval = fprintf(fp, "!x%hu", f->index);
+#endif
+        }
+        if (retval == EOF) return(0);
+    }
+    if (E != DD_ONE(dd)) {
+        retval = fprintf(fp, "%s%s(", T != DD_ONE(dd) ? " * " : "",
+                         E != cuddE(f) ? "!" : "");
+        if (retval == EOF) return(0);
+        retval = ddDoDumpFactoredForm(dd,E,fp,names);
+        if (retval != 1) return(retval);
+        retval = fprintf(fp, ")");
+        if (retval == EOF) return(0);
+    }
+    return(1);
+
+} /* end of ddDoDumpFactoredForm */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddGenCof.c b/abc-build/src/bdd/cudd/cuddGenCof.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddGenCof.c
@@ -0,0 +1,2183 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddGenCof.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Generalized cofactors for BDDs and ADDs.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_bddConstrain()
+                <li> Cudd_bddRestrict()
+                <li> Cudd_bddNPAnd()
+                <li> Cudd_addConstrain()
+                <li> Cudd_bddConstrainDecomp()
+                <li> Cudd_addRestrict()
+                <li> Cudd_bddCharToVect()
+                <li> Cudd_bddLICompaction()
+                <li> Cudd_bddSqueeze()
+                <li> Cudd_SubsetCompress()
+                <li> Cudd_SupersetCompress()
+                </ul>
+            Internal procedures included in this module:
+                <ul>
+                <li> cuddBddConstrainRecur()
+                <li> cuddBddRestrictRecur()
+                <li> cuddBddNPAndRecur()
+                <li> cuddAddConstrainRecur()
+                <li> cuddAddRestrictRecur()
+                <li> cuddBddLICompaction()
+                </ul>
+            Static procedures included in this module:
+                <ul>
+                <li> cuddBddConstrainDecomp()
+                <li> cuddBddCharToVect()
+                <li> cuddBddLICMarkEdges()
+                <li> cuddBddLICBuildResult()
+                <li> cuddBddSqueeze()
+                </ul>
+                ]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* Codes for edge markings in Cudd_bddLICompaction.  The codes are defined
+** so that they can be bitwise ORed to implement the code priority scheme.
+*/
+#define DD_LIC_DC 0
+#define DD_LIC_1  1
+#define DD_LIC_0  2
+#define DD_LIC_NL 3
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/* Key for the cache used in the edge marking phase. */
+typedef struct MarkCacheKey {
+    DdNode *f;
+    DdNode *c;
+} MarkCacheKey;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddGenCof.c,v 1.38 2005/05/14 17:27:11 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int cuddBddConstrainDecomp (DdManager *dd, DdNode *f, DdNode **decomp);
+static DdNode * cuddBddCharToVect (DdManager *dd, DdNode *f, DdNode *x);
+static int cuddBddLICMarkEdges (DdManager *dd, DdNode *f, DdNode *c, st__table *table, st__table *cache);
+static DdNode * cuddBddLICBuildResult (DdManager *dd, DdNode *f, st__table *cache, st__table *table);
+static int MarkCacheHash (const char *ptr, int modulus);
+static int MarkCacheCompare (const char *ptr1, const char *ptr2);
+static enum st__retval MarkCacheCleanUp (char *key, char *value, char *arg);
+static DdNode * cuddBddSqueeze (DdManager *dd, DdNode *l, DdNode *u);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes f constrain c.]
+
+  Description [Computes f constrain c (f @ c).
+  Uses a canonical form: (f' @ c) = ( f @ c)'.  (Note: this is not true
+  for c.)  List of special cases:
+    <ul>
+    <li> f @ 0 = 0
+    <li> f @ 1 = f
+    <li> 0 @ c = 0
+    <li> 1 @ c = 1
+    <li> f @ f = 1
+    <li> f @ f'= 0
+    </ul>
+  Returns a pointer to the result if successful; NULL otherwise. Note that if
+  F=(f1,...,fn) and reordering takes place while computing F @ c, then the
+  image restriction property (Img(F,c) = Img(F @ c)) is lost.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddRestrict Cudd_addConstrain]
+
+******************************************************************************/
+DdNode *
+Cudd_bddConstrain(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddConstrainRecur(dd,f,c);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddConstrain */
+
+
+/**Function********************************************************************
+
+  Synopsis [BDD restrict according to Coudert and Madre's algorithm
+  (ICCAD90).]
+
+  Description [BDD restrict according to Coudert and Madre's algorithm
+  (ICCAD90). Returns the restricted BDD if successful; otherwise NULL.
+  If application of restrict results in a BDD larger than the input
+  BDD, the input BDD is returned.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddConstrain Cudd_addRestrict]
+
+******************************************************************************/
+DdNode *
+Cudd_bddRestrict(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode *suppF, *suppC, *commonSupport;
+    DdNode *cplus, *res;
+    int retval;
+    int sizeF, sizeRes;
+
+    /* Check terminal cases here to avoid computing supports in trivial cases.
+    ** This also allows us notto check later for the case c == 0, in which
+    ** there is no common support. */
+    if (c == Cudd_Not(DD_ONE(dd))) return(Cudd_Not(DD_ONE(dd)));
+    if (Cudd_IsConstant(f)) return(f);
+    if (f == c) return(DD_ONE(dd));
+    if (f == Cudd_Not(c)) return(Cudd_Not(DD_ONE(dd)));
+
+    /* Check if supports intersect. */
+    retval = Cudd_ClassifySupport(dd,f,c,&commonSupport,&suppF,&suppC);
+    if (retval == 0) {
+        return(NULL);
+    }
+    cuddRef(commonSupport); cuddRef(suppF); cuddRef(suppC);
+    Cudd_IterDerefBdd(dd,suppF);
+
+    if (commonSupport == DD_ONE(dd)) {
+        Cudd_IterDerefBdd(dd,commonSupport);
+        Cudd_IterDerefBdd(dd,suppC);
+        return(f);
+    }
+    Cudd_IterDerefBdd(dd,commonSupport);
+
+    /* Abstract from c the variables that do not appear in f. */
+    cplus = Cudd_bddExistAbstract(dd, c, suppC);
+    if (cplus == NULL) {
+        Cudd_IterDerefBdd(dd,suppC);
+        return(NULL);
+    }
+    cuddRef(cplus);
+    Cudd_IterDerefBdd(dd,suppC);
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddRestrictRecur(dd, f, cplus);
+    } while (dd->reordered == 1);
+    if (res == NULL) {
+        Cudd_IterDerefBdd(dd,cplus);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_IterDerefBdd(dd,cplus);
+    /* Make restric safe by returning the smaller of the input and the
+    ** result. */
+    sizeF = Cudd_DagSize(f);
+    sizeRes = Cudd_DagSize(res);
+    if (sizeF <= sizeRes) {
+        Cudd_IterDerefBdd(dd, res);
+        return(f);
+    } else {
+        cuddDeref(res);
+        return(res);
+    }
+
+} /* end of Cudd_bddRestrict */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes f non-polluting-and g.]
+
+  Description [Computes f non-polluting-and g.  The non-polluting AND
+  of f and g is a hybrid of AND and Restrict.  From Restrict, this
+  operation takes the idea of existentially quantifying the top
+  variable of the second operand if it does not appear in the first.
+  Therefore, the variables that appear in the result also appear in f.
+  For the rest, the function behaves like AND.  Since the two operands
+  play different roles, non-polluting AND is not commutative.
+
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddConstrain Cudd_bddRestrict]
+
+******************************************************************************/
+DdNode *
+Cudd_bddNPAnd(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddNPAndRecur(dd,f,g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddNPAnd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes f constrain c for ADDs.]
+
+  Description [Computes f constrain c (f @ c), for f an ADD and c a 0-1
+  ADD.  List of special cases:
+    <ul>
+    <li> F @ 0 = 0
+    <li> F @ 1 = F
+    <li> 0 @ c = 0
+    <li> 1 @ c = 1
+    <li> F @ F = 1
+    </ul>
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddConstrain]
+
+******************************************************************************/
+DdNode *
+Cudd_addConstrain(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddAddConstrainRecur(dd,f,c);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addConstrain */
+
+
+/**Function********************************************************************
+
+  Synopsis [BDD conjunctive decomposition as in McMillan's CAV96 paper.]
+
+  Description [BDD conjunctive decomposition as in McMillan's CAV96
+  paper.  The decomposition is canonical only for a given variable
+  order. If canonicity is required, variable ordering must be disabled
+  after the decomposition has been computed. Returns an array with one
+  entry for each BDD variable in the manager if successful; otherwise
+  NULL. The components of the solution have their reference counts
+  already incremented (unlike the results of most other functions in
+  the package.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddConstrain Cudd_bddExistAbstract]
+
+******************************************************************************/
+DdNode **
+Cudd_bddConstrainDecomp(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode **decomp;
+    int res;
+    int i;
+
+    /* Create an initialize decomposition array. */
+    decomp = ABC_ALLOC(DdNode *,dd->size);
+    if (decomp == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    for (i = 0; i < dd->size; i++) {
+        decomp[i] = NULL;
+    }
+    do {
+        dd->reordered = 0;
+        /* Clean up the decomposition array in case reordering took place. */
+        for (i = 0; i < dd->size; i++) {
+            if (decomp[i] != NULL) {
+                Cudd_IterDerefBdd(dd, decomp[i]);
+                decomp[i] = NULL;
+            }
+        }
+        res = cuddBddConstrainDecomp(dd,f,decomp);
+    } while (dd->reordered == 1);
+    if (res == 0) {
+        ABC_FREE(decomp);
+        return(NULL);
+    }
+    /* Missing components are constant ones. */
+    for (i = 0; i < dd->size; i++) {
+        if (decomp[i] == NULL) {
+            decomp[i] = DD_ONE(dd);
+            cuddRef(decomp[i]);
+        }
+    }
+    return(decomp);
+
+} /* end of Cudd_bddConstrainDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis [ADD restrict according to Coudert and Madre's algorithm
+  (ICCAD90).]
+
+  Description [ADD restrict according to Coudert and Madre's algorithm
+  (ICCAD90). Returns the restricted ADD if successful; otherwise NULL.
+  If application of restrict results in an ADD larger than the input
+  ADD, the input ADD is returned.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addConstrain Cudd_bddRestrict]
+
+******************************************************************************/
+DdNode *
+Cudd_addRestrict(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode *supp_f, *supp_c;
+    DdNode *res, *commonSupport;
+    int intersection;
+    int sizeF, sizeRes;
+
+    /* Check if supports intersect. */
+    supp_f = Cudd_Support(dd, f);
+    if (supp_f == NULL) {
+        return(NULL);
+    }
+    cuddRef(supp_f);
+    supp_c = Cudd_Support(dd, c);
+    if (supp_c == NULL) {
+        Cudd_RecursiveDeref(dd,supp_f);
+        return(NULL);
+    }
+    cuddRef(supp_c);
+    commonSupport = Cudd_bddLiteralSetIntersection(dd, supp_f, supp_c);
+    if (commonSupport == NULL) {
+        Cudd_RecursiveDeref(dd,supp_f);
+        Cudd_RecursiveDeref(dd,supp_c);
+        return(NULL);
+    }
+    cuddRef(commonSupport);
+    Cudd_RecursiveDeref(dd,supp_f);
+    Cudd_RecursiveDeref(dd,supp_c);
+    intersection = commonSupport != DD_ONE(dd);
+    Cudd_RecursiveDeref(dd,commonSupport);
+
+    if (intersection) {
+        do {
+            dd->reordered = 0;
+            res = cuddAddRestrictRecur(dd, f, c);
+        } while (dd->reordered == 1);
+        sizeF = Cudd_DagSize(f);
+        sizeRes = Cudd_DagSize(res);
+        if (sizeF <= sizeRes) {
+            cuddRef(res);
+            Cudd_RecursiveDeref(dd, res);
+            return(f);
+        } else {
+            return(res);
+        }
+    } else {
+        return(f);
+    }
+
+} /* end of Cudd_addRestrict */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a vector whose image equals a non-zero function.]
+
+  Description [Computes a vector of BDDs whose image equals a non-zero
+  function.
+  The result depends on the variable order. The i-th component of the vector
+  depends only on the first i variables in the order.  Each BDD in the vector
+  is not larger than the BDD of the given characteristic function.  This
+  function is based on the description of char-to-vect in "Verification of
+  Sequential Machines Using Boolean Functional Vectors" by O. Coudert, C.
+  Berthet and J. C. Madre.
+  Returns a pointer to an array containing the result if successful; NULL
+  otherwise. The size of the array equals the number of variables in the
+  manager. The components of the solution have their reference counts 
+  already incremented (unlike the results of most other functions in 
+  the package).]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddConstrain]
+
+******************************************************************************/
+DdNode **
+Cudd_bddCharToVect(
+  DdManager * dd,
+  DdNode * f)
+{
+    int i, j;
+    DdNode **vect;
+    DdNode *res = NULL;
+
+    if (f == Cudd_Not(DD_ONE(dd))) return(NULL);
+
+    vect = ABC_ALLOC(DdNode *, dd->size);
+    if (vect == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+
+    do {
+        dd->reordered = 0;
+        for (i = 0; i < dd->size; i++) {
+            res = cuddBddCharToVect(dd,f,dd->vars[dd->invperm[i]]);
+            if (res == NULL) {
+                /* Clean up the vector array in case reordering took place. */
+                for (j = 0; j < i; j++) {
+                    Cudd_IterDerefBdd(dd, vect[dd->invperm[j]]);
+                }
+                break;
+            }
+            cuddRef(res);
+            vect[dd->invperm[i]] = res;
+        }
+    } while (dd->reordered == 1);
+    if (res == NULL) {
+        ABC_FREE(vect);
+        return(NULL);
+    }
+    return(vect);
+
+} /* end of Cudd_bddCharToVect */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs safe minimization of a BDD.]
+
+  Description [Performs safe minimization of a BDD. Given the BDD
+  <code>f</code> of a function to be minimized and a BDD
+  <code>c</code> representing the care set, Cudd_bddLICompaction
+  produces the BDD of a function that agrees with <code>f</code>
+  wherever <code>c</code> is 1.  Safe minimization means that the size
+  of the result is guaranteed not to exceed the size of
+  <code>f</code>. This function is based on the DAC97 paper by Hong et
+  al..  Returns a pointer to the result if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddRestrict]
+
+******************************************************************************/
+DdNode *
+Cudd_bddLICompaction(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be minimized */,
+  DdNode * c /* constraint (care set) */)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddLICompaction(dd,f,c);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddLICompaction */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a small BDD in a function interval.]
+
+  Description [Finds a small BDD in a function interval. Given BDDs
+  <code>l</code> and <code>u</code>, representing the lower bound and
+  upper bound of a function interval, Cudd_bddSqueeze produces the BDD
+  of a function within the interval with a small BDD.  Returns a
+  pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddRestrict Cudd_bddLICompaction]
+
+******************************************************************************/
+DdNode *
+Cudd_bddSqueeze(
+  DdManager * dd /* manager */,
+  DdNode * l /* lower bound */,
+  DdNode * u /* upper bound */)
+{
+    DdNode *res;
+    int sizeRes, sizeL, sizeU;
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddSqueeze(dd,l,u);
+    } while (dd->reordered == 1);
+    if (res == NULL) return(NULL);
+    /* We now compare the result with the bounds and return the smallest.
+    ** We first compare to u, so that in case l == 0 and u == 1, we return
+    ** 0 as in other minimization algorithms. */
+    sizeRes = Cudd_DagSize(res);
+    sizeU = Cudd_DagSize(u);
+    if (sizeU <= sizeRes) {
+        cuddRef(res);
+        Cudd_IterDerefBdd(dd,res);
+        res = u;
+        sizeRes = sizeU;
+    }
+    sizeL = Cudd_DagSize(l);
+    if (sizeL <= sizeRes) {
+        cuddRef(res);
+        Cudd_IterDerefBdd(dd,res);
+        res = l;
+        sizeRes = sizeL;
+    }
+    return(res);
+
+} /* end of Cudd_bddSqueeze */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a small BDD that agrees with <code>f</code> over
+  <code>c</code>.]
+
+  Description [Finds a small BDD that agrees with <code>f</code> over
+  <code>c</code>.  Returns a pointer to the result if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddRestrict Cudd_bddLICompaction Cudd_bddSqueeze]
+
+******************************************************************************/
+DdNode *
+Cudd_bddMinimize(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode *cplus, *res;
+
+    if (c == Cudd_Not(DD_ONE(dd))) return(c);
+    if (Cudd_IsConstant(f)) return(f);
+    if (f == c) return(DD_ONE(dd));
+    if (f == Cudd_Not(c)) return(Cudd_Not(DD_ONE(dd)));
+
+    cplus = Cudd_RemapOverApprox(dd,c,0,0,1.0);
+    if (cplus == NULL) return(NULL);
+    cuddRef(cplus);
+    res = Cudd_bddLICompaction(dd,f,cplus);
+    if (res == NULL) {
+        Cudd_IterDerefBdd(dd,cplus);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_IterDerefBdd(dd,cplus);
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_bddMinimize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find a dense subset of BDD <code>f</code>.]
+
+  Description [Finds a dense subset of BDD <code>f</code>. Density is
+  the ratio of number of minterms to number of nodes.  Uses several
+  techniques in series. It is more expensive than other subsetting
+  procedures, but often produces better results. See
+  Cudd_SubsetShortPaths for a description of the threshold and nvars
+  parameters.  Returns a pointer to the result if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetRemap Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch
+  Cudd_bddSqueeze]
+
+******************************************************************************/
+DdNode *
+Cudd_SubsetCompress(
+  DdManager * dd /* manager */,
+  DdNode * f /* BDD whose subset is sought */,
+  int  nvars /* number of variables in the support of f */,
+  int  threshold /* maximum number of nodes in the subset */)
+{
+    DdNode *res, *tmp1, *tmp2;
+
+    tmp1 = Cudd_SubsetShortPaths(dd, f, nvars, threshold, 0);
+    if (tmp1 == NULL) return(NULL);
+    cuddRef(tmp1);
+    tmp2 = Cudd_RemapUnderApprox(dd,tmp1,nvars,0,1.0);
+    if (tmp2 == NULL) {
+        Cudd_IterDerefBdd(dd,tmp1);
+        return(NULL);
+    }
+    cuddRef(tmp2);
+    Cudd_IterDerefBdd(dd,tmp1);
+    res = Cudd_bddSqueeze(dd,tmp2,f);
+    if (res == NULL) {
+        Cudd_IterDerefBdd(dd,tmp2);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_IterDerefBdd(dd,tmp2);
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_SubsetCompress */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find a dense superset of BDD <code>f</code>.]
+
+  Description [Finds a dense superset of BDD <code>f</code>. Density is
+  the ratio of number of minterms to number of nodes.  Uses several
+  techniques in series. It is more expensive than other supersetting
+  procedures, but often produces better results. See
+  Cudd_SupersetShortPaths for a description of the threshold and nvars
+  parameters.  Returns a pointer to the result if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetCompress Cudd_SupersetRemap Cudd_SupersetShortPaths
+  Cudd_SupersetHeavyBranch Cudd_bddSqueeze]
+
+******************************************************************************/
+DdNode *
+Cudd_SupersetCompress(
+  DdManager * dd /* manager */,
+  DdNode * f /* BDD whose superset is sought */,
+  int  nvars /* number of variables in the support of f */,
+  int  threshold /* maximum number of nodes in the superset */)
+{
+    DdNode *subset;
+
+    subset = Cudd_SubsetCompress(dd, Cudd_Not(f),nvars,threshold);
+
+    return(Cudd_NotCond(subset, (subset != NULL)));
+
+} /* end of Cudd_SupersetCompress */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddConstrain.]
+
+  Description [Performs the recursive step of Cudd_bddConstrain.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddConstrain]
+
+******************************************************************************/
+DdNode *
+cuddBddConstrainRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode       *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r;
+    DdNode       *one, *zero;
+    unsigned int topf, topc;
+    int          index;
+    int          comple = 0;
+
+    statLine(dd);
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    /* Trivial cases. */
+    if (c == one)               return(f);
+    if (c == zero)              return(zero);
+    if (Cudd_IsConstant(f))     return(f);
+    if (f == c)                 return(one);
+    if (f == Cudd_Not(c))       return(zero);
+
+    /* Make canonical to increase the utilization of the cache. */
+    if (Cudd_IsComplement(f)) {
+        f = Cudd_Not(f);
+        comple = 1;
+    }
+    /* Now f is a regular pointer to a non-constant node; c is also
+    ** non-constant, but may be complemented.
+    */
+
+    /* Check the cache. */
+    r = cuddCacheLookup2(dd, Cudd_bddConstrain, f, c);
+    if (r != NULL) {
+        return(Cudd_NotCond(r,comple));
+    }
+    
+    /* Recursive step. */
+    topf = dd->perm[f->index];
+    topc = dd->perm[Cudd_Regular(c)->index];
+    if (topf <= topc) {
+        index = f->index;
+        Fv = cuddT(f); Fnv = cuddE(f);
+    } else {
+        index = Cudd_Regular(c)->index;
+        Fv = Fnv = f;
+    }
+    if (topc <= topf) {
+        Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c));
+        if (Cudd_IsComplement(c)) {
+            Cv = Cudd_Not(Cv);
+            Cnv = Cudd_Not(Cnv);
+        }
+    } else {
+        Cv = Cnv = c;
+    }
+
+    if (!Cudd_IsConstant(Cv)) {
+        t = cuddBddConstrainRecur(dd, Fv, Cv);
+        if (t == NULL)
+            return(NULL);
+    } else if (Cv == one) {
+        t = Fv;
+    } else {            /* Cv == zero: return Fnv @ Cnv */
+        if (Cnv == one) {
+            r = Fnv;
+        } else {
+            r = cuddBddConstrainRecur(dd, Fnv, Cnv);
+            if (r == NULL)
+                return(NULL);
+        }
+        return(Cudd_NotCond(r,comple));
+    }
+    cuddRef(t);
+
+    if (!Cudd_IsConstant(Cnv)) {
+        e = cuddBddConstrainRecur(dd, Fnv, Cnv);
+        if (e == NULL) {
+            Cudd_IterDerefBdd(dd, t);
+            return(NULL);
+        }
+    } else if (Cnv == one) {
+        e = Fnv;
+    } else {            /* Cnv == zero: return Fv @ Cv previously computed */
+        cuddDeref(t);
+        return(Cudd_NotCond(t,comple));
+    }
+    cuddRef(e);
+
+    if (Cudd_IsComplement(t)) {
+        t = Cudd_Not(t);
+        e = Cudd_Not(e);
+        r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+        if (r == NULL) {
+            Cudd_IterDerefBdd(dd, e);
+            Cudd_IterDerefBdd(dd, t);
+            return(NULL);
+        }
+        r = Cudd_Not(r);
+    } else {
+        r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+        if (r == NULL) {
+            Cudd_IterDerefBdd(dd, e);
+            Cudd_IterDerefBdd(dd, t);
+            return(NULL);
+        }
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    cuddCacheInsert2(dd, Cudd_bddConstrain, f, c, r);
+    return(Cudd_NotCond(r,comple));
+
+} /* end of cuddBddConstrainRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddRestrict.]
+
+  Description [Performs the recursive step of Cudd_bddRestrict.
+  Returns the restricted BDD if successful; otherwise NULL.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddRestrict]
+
+******************************************************************************/
+DdNode *
+cuddBddRestrictRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode       *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero;
+    unsigned int topf, topc;
+    int          index;
+    int          comple = 0;
+
+    statLine(dd);
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    /* Trivial cases */
+    if (c == one)               return(f);
+    if (c == zero)              return(zero);
+    if (Cudd_IsConstant(f))     return(f);
+    if (f == c)                 return(one);
+    if (f == Cudd_Not(c))       return(zero);
+
+    /* Make canonical to increase the utilization of the cache. */
+    if (Cudd_IsComplement(f)) {
+        f = Cudd_Not(f);
+        comple = 1;
+    }
+    /* Now f is a regular pointer to a non-constant node; c is also
+    ** non-constant, but may be complemented.
+    */
+
+    /* Check the cache. */
+    r = cuddCacheLookup2(dd, Cudd_bddRestrict, f, c);
+    if (r != NULL) {
+        return(Cudd_NotCond(r,comple));
+    }
+
+    topf = dd->perm[f->index];
+    topc = dd->perm[Cudd_Regular(c)->index];
+
+    if (topc < topf) {  /* abstract top variable from c */
+        DdNode *d, *s1, *s2;
+
+        /* Find complements of cofactors of c. */
+        if (Cudd_IsComplement(c)) {
+            s1 = cuddT(Cudd_Regular(c));
+            s2 = cuddE(Cudd_Regular(c));
+        } else {
+            s1 = Cudd_Not(cuddT(c));
+            s2 = Cudd_Not(cuddE(c));
+        }
+        /* Take the OR by applying DeMorgan. */
+        d = cuddBddAndRecur(dd, s1, s2);
+        if (d == NULL) return(NULL);
+        d = Cudd_Not(d);
+        cuddRef(d);
+        r = cuddBddRestrictRecur(dd, f, d);
+        if (r == NULL) {
+            Cudd_IterDerefBdd(dd, d);
+            return(NULL);
+        }
+        cuddRef(r);
+        Cudd_IterDerefBdd(dd, d);
+        cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r);
+        cuddDeref(r);
+        return(Cudd_NotCond(r,comple));
+    }
+
+    /* Recursive step. Here topf <= topc. */
+    index = f->index;
+    Fv = cuddT(f); Fnv = cuddE(f);
+    if (topc == topf) {
+        Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c));
+        if (Cudd_IsComplement(c)) {
+            Cv = Cudd_Not(Cv);
+            Cnv = Cudd_Not(Cnv);
+        }
+    } else {
+        Cv = Cnv = c;
+    }
+
+    if (!Cudd_IsConstant(Cv)) {
+        t = cuddBddRestrictRecur(dd, Fv, Cv);
+        if (t == NULL) return(NULL);
+    } else if (Cv == one) {
+        t = Fv;
+    } else {            /* Cv == zero: return(Fnv @ Cnv) */
+        if (Cnv == one) {
+            r = Fnv;
+        } else {
+            r = cuddBddRestrictRecur(dd, Fnv, Cnv);
+            if (r == NULL) return(NULL);
+        }
+        return(Cudd_NotCond(r,comple));
+    }
+    cuddRef(t);
+
+    if (!Cudd_IsConstant(Cnv)) {
+        e = cuddBddRestrictRecur(dd, Fnv, Cnv);
+        if (e == NULL) {
+            Cudd_IterDerefBdd(dd, t);
+            return(NULL);
+        }
+    } else if (Cnv == one) {
+        e = Fnv;
+    } else {            /* Cnv == zero: return (Fv @ Cv) previously computed */
+        cuddDeref(t);
+        return(Cudd_NotCond(t,comple));
+    }
+    cuddRef(e);
+
+    if (Cudd_IsComplement(t)) {
+        t = Cudd_Not(t);
+        e = Cudd_Not(e);
+        r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+        if (r == NULL) {
+            Cudd_IterDerefBdd(dd, e);
+            Cudd_IterDerefBdd(dd, t);
+            return(NULL);
+        }
+        r = Cudd_Not(r);
+    } else {
+        r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+        if (r == NULL) {
+            Cudd_IterDerefBdd(dd, e);
+            Cudd_IterDerefBdd(dd, t);
+            return(NULL);
+        }
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r);
+    return(Cudd_NotCond(r,comple));
+
+} /* end of cuddBddRestrictRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis [Implements the recursive step of Cudd_bddAnd.]
+
+  Description [Implements the recursive step of Cudd_bddNPAnd.
+  Returns a pointer to the result is successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddNPAnd]
+
+******************************************************************************/
+DdNode *
+cuddBddNPAndRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *F, *ft, *fe, *G, *gt, *ge;
+    DdNode *one, *r, *t, *e;
+    unsigned int topf, topg, index;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+
+    /* Terminal cases. */
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    if (F == G) {
+        if (f == g) return(one);
+        else return(Cudd_Not(one));
+    }
+    if (G == one) {
+        if (g == one) return(f);
+        else return(g);
+    }
+    if (F == one) {
+        return(f);
+    }
+
+    /* At this point f and g are not constant. */
+    /* Check cache. */
+    if (F->ref != 1 || G->ref != 1) {
+        r = cuddCacheLookup2(manager, Cudd_bddNPAnd, f, g);
+        if (r != NULL) return(r);
+    }
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    topf = manager->perm[F->index];
+    topg = manager->perm[G->index];
+
+    if (topg < topf) {  /* abstract top variable from g */
+        DdNode *d;
+
+        /* Find complements of cofactors of g. */
+        if (Cudd_IsComplement(g)) {
+            gt = cuddT(G);
+            ge = cuddE(G);
+        } else {
+            gt = Cudd_Not(cuddT(g));
+            ge = Cudd_Not(cuddE(g));
+        }
+        /* Take the OR by applying DeMorgan. */
+        d = cuddBddAndRecur(manager, gt, ge);
+        if (d == NULL) return(NULL);
+        d = Cudd_Not(d);
+        cuddRef(d);
+        r = cuddBddNPAndRecur(manager, f, d);
+        if (r == NULL) {
+            Cudd_IterDerefBdd(manager, d);
+            return(NULL);
+        }
+        cuddRef(r);
+        Cudd_IterDerefBdd(manager, d);
+        cuddCacheInsert2(manager, Cudd_bddNPAnd, f, g, r);
+        cuddDeref(r);
+        return(r);
+    }
+
+    /* Compute cofactors. */
+    index = F->index;
+    ft = cuddT(F);
+    fe = cuddE(F);
+    if (Cudd_IsComplement(f)) {
+      ft = Cudd_Not(ft);
+      fe = Cudd_Not(fe);
+    }
+
+    if (topg == topf) {
+        gt = cuddT(G);
+        ge = cuddE(G);
+        if (Cudd_IsComplement(g)) {
+            gt = Cudd_Not(gt);
+            ge = Cudd_Not(ge);
+        }
+    } else {
+        gt = ge = g;
+    }
+
+    t = cuddBddAndRecur(manager, ft, gt);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+
+    e = cuddBddAndRecur(manager, fe, ge);
+    if (e == NULL) {
+        Cudd_IterDerefBdd(manager, t);
+        return(NULL);
+    }
+    cuddRef(e);
+
+    if (t == e) {
+        r = t;
+    } else {
+        if (Cudd_IsComplement(t)) {
+            r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
+            if (r == NULL) {
+                Cudd_IterDerefBdd(manager, t);
+                Cudd_IterDerefBdd(manager, e);
+                return(NULL);
+            }
+            r = Cudd_Not(r);
+        } else {
+            r = cuddUniqueInter(manager,(int)index,t,e);
+            if (r == NULL) {
+                Cudd_IterDerefBdd(manager, t);
+                Cudd_IterDerefBdd(manager, e);
+                return(NULL);
+            }
+        }
+    }
+    cuddDeref(e);
+    cuddDeref(t);
+    if (F->ref != 1 || G->ref != 1)
+        cuddCacheInsert2(manager, Cudd_bddNPAnd, f, g, r);
+    return(r);
+
+} /* end of cuddBddNPAndRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addConstrain.]
+
+  Description [Performs the recursive step of Cudd_addConstrain.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addConstrain]
+
+******************************************************************************/
+DdNode *
+cuddAddConstrainRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode       *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r;
+    DdNode       *one, *zero;
+    unsigned int topf, topc;
+    int          index;
+
+    statLine(dd);
+    one = DD_ONE(dd);
+    zero = DD_ZERO(dd);
+
+    /* Trivial cases. */
+    if (c == one)               return(f);
+    if (c == zero)              return(zero);
+    if (Cudd_IsConstant(f))     return(f);
+    if (f == c)                 return(one);
+
+    /* Now f and c are non-constant. */
+
+    /* Check the cache. */
+    r = cuddCacheLookup2(dd, Cudd_addConstrain, f, c);
+    if (r != NULL) {
+        return(r);
+    }
+    
+    /* Recursive step. */
+    topf = dd->perm[f->index];
+    topc = dd->perm[c->index];
+    if (topf <= topc) {
+        index = f->index;
+        Fv = cuddT(f); Fnv = cuddE(f);
+    } else {
+        index = c->index;
+        Fv = Fnv = f;
+    }
+    if (topc <= topf) {
+        Cv = cuddT(c); Cnv = cuddE(c);
+    } else {
+        Cv = Cnv = c;
+    }
+
+    if (!Cudd_IsConstant(Cv)) {
+        t = cuddAddConstrainRecur(dd, Fv, Cv);
+        if (t == NULL)
+            return(NULL);
+    } else if (Cv == one) {
+        t = Fv;
+    } else {            /* Cv == zero: return Fnv @ Cnv */
+        if (Cnv == one) {
+            r = Fnv;
+        } else {
+            r = cuddAddConstrainRecur(dd, Fnv, Cnv);
+            if (r == NULL)
+                return(NULL);
+        }
+        return(r);
+    }
+    cuddRef(t);
+
+    if (!Cudd_IsConstant(Cnv)) {
+        e = cuddAddConstrainRecur(dd, Fnv, Cnv);
+        if (e == NULL) {
+            Cudd_RecursiveDeref(dd, t);
+            return(NULL);
+        }
+    } else if (Cnv == one) {
+        e = Fnv;
+    } else {            /* Cnv == zero: return Fv @ Cv previously computed */
+        cuddDeref(t);
+        return(t);
+    }
+    cuddRef(e);
+
+    r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+    if (r == NULL) {
+        Cudd_RecursiveDeref(dd, e);
+        Cudd_RecursiveDeref(dd, t);
+        return(NULL);
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    cuddCacheInsert2(dd, Cudd_addConstrain, f, c, r);
+    return(r);
+
+} /* end of cuddAddConstrainRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addRestrict.]
+
+  Description [Performs the recursive step of Cudd_addRestrict.
+  Returns the restricted ADD if successful; otherwise NULL.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addRestrict]
+
+******************************************************************************/
+DdNode *
+cuddAddRestrictRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode       *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero;
+    unsigned int topf, topc;
+    int          index;
+
+    statLine(dd);
+    one = DD_ONE(dd);
+    zero = DD_ZERO(dd);
+
+    /* Trivial cases */
+    if (c == one)               return(f);
+    if (c == zero)              return(zero);
+    if (Cudd_IsConstant(f))     return(f);
+    if (f == c)                 return(one);
+
+    /* Now f and c are non-constant. */
+
+    /* Check the cache. */
+    r = cuddCacheLookup2(dd, Cudd_addRestrict, f, c);
+    if (r != NULL) {
+        return(r);
+    }
+
+    topf = dd->perm[f->index];
+    topc = dd->perm[c->index];
+
+    if (topc < topf) {  /* abstract top variable from c */
+        DdNode *d, *s1, *s2;
+
+        /* Find cofactors of c. */
+        s1 = cuddT(c);
+        s2 = cuddE(c);
+        /* Take the OR by applying DeMorgan. */
+        d = cuddAddApplyRecur(dd, Cudd_addOr, s1, s2);
+        if (d == NULL) return(NULL);
+        cuddRef(d);
+        r = cuddAddRestrictRecur(dd, f, d);
+        if (r == NULL) {
+            Cudd_RecursiveDeref(dd, d);
+            return(NULL);
+        }
+        cuddRef(r);
+        Cudd_RecursiveDeref(dd, d);
+        cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r);
+        cuddDeref(r);
+        return(r);
+    }
+
+    /* Recursive step. Here topf <= topc. */
+    index = f->index;
+    Fv = cuddT(f); Fnv = cuddE(f);
+    if (topc == topf) {
+        Cv = cuddT(c); Cnv = cuddE(c);
+    } else {
+        Cv = Cnv = c;
+    }
+
+    if (!Cudd_IsConstant(Cv)) {
+        t = cuddAddRestrictRecur(dd, Fv, Cv);
+        if (t == NULL) return(NULL);
+    } else if (Cv == one) {
+        t = Fv;
+    } else {            /* Cv == zero: return(Fnv @ Cnv) */
+        if (Cnv == one) {
+            r = Fnv;
+        } else {
+            r = cuddAddRestrictRecur(dd, Fnv, Cnv);
+            if (r == NULL) return(NULL);
+        }
+        return(r);
+    }
+    cuddRef(t);
+
+    if (!Cudd_IsConstant(Cnv)) {
+        e = cuddAddRestrictRecur(dd, Fnv, Cnv);
+        if (e == NULL) {
+            Cudd_RecursiveDeref(dd, t);
+            return(NULL);
+        }
+    } else if (Cnv == one) {
+        e = Fnv;
+    } else {            /* Cnv == zero: return (Fv @ Cv) previously computed */
+        cuddDeref(t);
+        return(t);
+    }
+    cuddRef(e);
+
+    r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+    if (r == NULL) {
+        Cudd_RecursiveDeref(dd, e);
+        Cudd_RecursiveDeref(dd, t);
+        return(NULL);
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r);
+    return(r);
+
+} /* end of cuddAddRestrictRecur */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs safe minimization of a BDD.]
+
+  Description [Performs safe minimization of a BDD. Given the BDD
+  <code>f</code> of a function to be minimized and a BDD
+  <code>c</code> representing the care set, Cudd_bddLICompaction
+  produces the BDD of a function that agrees with <code>f</code>
+  wherever <code>c</code> is 1.  Safe minimization means that the size
+  of the result is guaranteed not to exceed the size of
+  <code>f</code>. This function is based on the DAC97 paper by Hong et
+  al..  Returns a pointer to the result if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLICompaction]
+
+******************************************************************************/
+DdNode *
+cuddBddLICompaction(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be minimized */,
+  DdNode * c /* constraint (care set) */)
+{
+    st__table *marktable, *markcache, *buildcache;
+    DdNode *res, *zero;
+
+    zero = Cudd_Not(DD_ONE(dd));
+    if (c == zero) return(zero);
+
+    /* We need to use local caches for both steps of this operation.
+    ** The results of the edge marking step are only valid as long as the
+    ** edge markings themselves are available. However, the edge markings
+    ** are lost at the end of one invocation of Cudd_bddLICompaction.
+    ** Hence, the cache entries for the edge marking step must be
+    ** invalidated at the end of this function.
+    ** For the result of the building step we argue as follows. The result
+    ** for a node and a given constrain depends on the BDD in which the node
+    ** appears. Hence, the same node and constrain may give different results
+    ** in successive invocations.
+    */
+    marktable = st__init_table( st__ptrcmp, st__ptrhash);
+    if (marktable == NULL) {
+        return(NULL);
+    }
+    markcache = st__init_table(MarkCacheCompare,MarkCacheHash);
+    if (markcache == NULL) {
+        st__free_table(marktable);
+        return(NULL);
+    }
+    if (cuddBddLICMarkEdges(dd,f,c,marktable,markcache) == CUDD_OUT_OF_MEM) {
+        st__foreach(markcache, MarkCacheCleanUp, NULL);
+        st__free_table(marktable);
+        st__free_table(markcache);
+        return(NULL);
+    }
+    st__foreach(markcache, MarkCacheCleanUp, NULL);
+    st__free_table(markcache);
+    buildcache = st__init_table( st__ptrcmp, st__ptrhash);
+    if (buildcache == NULL) {
+        st__free_table(marktable);
+        return(NULL);
+    }
+    res = cuddBddLICBuildResult(dd,f,buildcache,marktable);
+    st__free_table(buildcache);
+    st__free_table(marktable);
+    return(res);
+
+} /* end of cuddBddLICompaction */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddConstrainDecomp.]
+
+  Description [Performs the recursive step of Cudd_bddConstrainDecomp.
+  Returns f super (i) if successful; otherwise NULL.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddConstrainDecomp]
+
+******************************************************************************/
+static int
+cuddBddConstrainDecomp(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** decomp)
+{
+    DdNode *F, *fv, *fvn;
+    DdNode *fAbs;
+    DdNode *result;
+    int ok;
+
+    if (Cudd_IsConstant(f)) return(1);
+    /* Compute complements of cofactors. */
+    F = Cudd_Regular(f);
+    fv = cuddT(F);
+    fvn = cuddE(F);
+    if (F == f) {
+        fv = Cudd_Not(fv);
+        fvn = Cudd_Not(fvn);
+    }
+    /* Compute abstraction of top variable. */
+    fAbs = cuddBddAndRecur(dd, fv, fvn);
+    if (fAbs == NULL) {
+        return(0);
+    }
+    cuddRef(fAbs);
+    fAbs = Cudd_Not(fAbs);
+    /* Recursively find the next abstraction and the components of the
+    ** decomposition. */
+    ok = cuddBddConstrainDecomp(dd, fAbs, decomp);
+    if (ok == 0) {
+        Cudd_IterDerefBdd(dd,fAbs);
+        return(0);
+    }
+    /* Compute the component of the decomposition corresponding to the
+    ** top variable and store it in the decomposition array. */
+    result = cuddBddConstrainRecur(dd, f, fAbs);
+    if (result == NULL) {
+        Cudd_IterDerefBdd(dd,fAbs);
+        return(0);
+    }
+    cuddRef(result);
+    decomp[F->index] = result;
+    Cudd_IterDerefBdd(dd, fAbs);
+    return(1);
+
+} /* end of cuddBddConstrainDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddCharToVect.]
+
+  Description [Performs the recursive step of Cudd_bddCharToVect.
+  This function maintains the invariant that f is non-zero.
+  Returns the i-th component of the vector if successful; otherwise NULL.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddCharToVect]
+
+******************************************************************************/
+static DdNode *
+cuddBddCharToVect(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * x)
+{
+    unsigned int topf;
+    unsigned int level;
+    int comple;
+
+    DdNode *one, *zero, *res, *F, *fT, *fE, *T, *E;
+
+    statLine(dd);
+    /* Check the cache. */
+    res = cuddCacheLookup2(dd, cuddBddCharToVect, f, x);
+    if (res != NULL) {
+        return(res);
+    }
+
+    F = Cudd_Regular(f);
+
+    topf = cuddI(dd,F->index);
+    level = dd->perm[x->index];
+
+    if (topf > level) return(x);
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    comple = F != f;
+    fT = Cudd_NotCond(cuddT(F),comple);
+    fE = Cudd_NotCond(cuddE(F),comple);
+
+    if (topf == level) {
+        if (fT == zero) return(zero);
+        if (fE == zero) return(one);
+        return(x);
+    }
+
+    /* Here topf < level. */
+    if (fT == zero) return(cuddBddCharToVect(dd, fE, x));
+    if (fE == zero) return(cuddBddCharToVect(dd, fT, x));
+
+    T = cuddBddCharToVect(dd, fT, x);
+    if (T == NULL) {
+        return(NULL);
+    }
+    cuddRef(T);
+    E = cuddBddCharToVect(dd, fE, x);
+    if (E == NULL) {
+        Cudd_IterDerefBdd(dd,T);
+        return(NULL);
+    }
+    cuddRef(E);
+    res = cuddBddIteRecur(dd, dd->vars[F->index], T, E);
+    if (res == NULL) {
+        Cudd_IterDerefBdd(dd,T);
+        Cudd_IterDerefBdd(dd,E);
+        return(NULL);
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+    cuddCacheInsert2(dd, cuddBddCharToVect, f, x, res);
+    return(res);
+
+} /* end of cuddBddCharToVect */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the edge marking step of Cudd_bddLICompaction.]
+
+  Description [Performs the edge marking step of Cudd_bddLICompaction.
+  Returns the LUB of the markings of the two outgoing edges of <code>f</code>
+  if successful; otherwise CUDD_OUT_OF_MEM.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLICompaction cuddBddLICBuildResult]
+
+******************************************************************************/
+static int
+cuddBddLICMarkEdges(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c,
+  st__table * table,
+  st__table * cache)
+{
+    DdNode *Fv, *Fnv, *Cv, *Cnv;
+    DdNode *one, *zero;
+    unsigned int topf, topc;
+    int comple;
+    int resT, resE, res, retval;
+    char **slot;
+    MarkCacheKey *key;
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    /* Terminal cases. */
+    if (c == zero) return(DD_LIC_DC);
+    if (f == one)  return(DD_LIC_1);
+    if (f == zero) return(DD_LIC_0);
+
+    /* Make canonical to increase the utilization of the cache. */
+    comple = Cudd_IsComplement(f);
+    f = Cudd_Regular(f);
+    /* Now f is a regular pointer to a non-constant node; c may be
+    ** constant, or it may be complemented.
+    */
+
+    /* Check the cache. */
+    key = ABC_ALLOC(MarkCacheKey, 1);
+    if (key == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(CUDD_OUT_OF_MEM);
+    }
+    key->f = f; key->c = c;
+    if ( st__lookup_int(cache, (char *)key, &res)) {
+        ABC_FREE(key);
+        if (comple) {
+            if (res == DD_LIC_0) res = DD_LIC_1;
+            else if (res == DD_LIC_1) res = DD_LIC_0;
+        }
+        return(res);
+    }
+
+    /* Recursive step. */
+    topf = dd->perm[f->index];
+    topc = cuddI(dd,Cudd_Regular(c)->index);
+    if (topf <= topc) {
+        Fv = cuddT(f); Fnv = cuddE(f);
+    } else {
+        Fv = Fnv = f;
+    }
+    if (topc <= topf) {
+        /* We know that c is not constant because f is not. */
+        Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c));
+        if (Cudd_IsComplement(c)) {
+            Cv = Cudd_Not(Cv);
+            Cnv = Cudd_Not(Cnv);
+        }
+    } else {
+        Cv = Cnv = c;
+    }
+
+    resT = cuddBddLICMarkEdges(dd, Fv, Cv, table, cache);
+    if (resT == CUDD_OUT_OF_MEM) {
+        ABC_FREE(key);
+        return(CUDD_OUT_OF_MEM);
+    }
+    resE = cuddBddLICMarkEdges(dd, Fnv, Cnv, table, cache);
+    if (resE == CUDD_OUT_OF_MEM) {
+        ABC_FREE(key);
+        return(CUDD_OUT_OF_MEM);
+    }
+
+    /* Update edge markings. */
+    if (topf <= topc) {
+        retval = st__find_or_add(table, (char *)f, (char ***)&slot);
+        if (retval == 0) {
+            *slot = (char *) (ptrint)((resT << 2) | resE);
+        } else if (retval == 1) {
+            *slot = (char *) (ptrint)((int)((ptrint) *slot) | (resT << 2) | resE);
+        } else {
+            ABC_FREE(key);
+            return(CUDD_OUT_OF_MEM);
+        }
+    }
+
+    /* Cache result. */
+    res = resT | resE;
+    if ( st__insert(cache, (char *)key, (char *)(ptrint)res) == st__OUT_OF_MEM) {
+        ABC_FREE(key);
+        return(CUDD_OUT_OF_MEM);
+    }
+
+    /* Take into account possible complementation. */
+    if (comple) {
+        if (res == DD_LIC_0) res = DD_LIC_1;
+        else if (res == DD_LIC_1) res = DD_LIC_0;
+    }
+    return(res);
+
+} /* end of cuddBddLICMarkEdges */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the result of Cudd_bddLICompaction.]
+
+  Description [Builds the results of Cudd_bddLICompaction.
+  Returns a pointer to the minimized BDD if successful; otherwise NULL.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLICompaction cuddBddLICMarkEdges]
+
+******************************************************************************/
+static DdNode *
+cuddBddLICBuildResult(
+  DdManager * dd,
+  DdNode * f,
+  st__table * cache,
+  st__table * table)
+{
+    DdNode *Fv, *Fnv, *r, *t, *e;
+    DdNode *one, *zero;
+    int index;
+    int comple;
+    int markT, markE, markings;
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    if (Cudd_IsConstant(f)) return(f);
+    /* Make canonical to increase the utilization of the cache. */
+    comple = Cudd_IsComplement(f);
+    f = Cudd_Regular(f);
+
+    /* Check the cache. */
+    if ( st__lookup(cache, (const char *)f, (char **)&r)) {
+        return(Cudd_NotCond(r,comple));
+    }
+
+    /* Retrieve the edge markings. */
+    if ( st__lookup_int(table, (char *)f, &markings) == 0)
+        return(NULL);
+    markT = markings >> 2;
+    markE = markings & 3;
+
+    index = f->index;
+    Fv = cuddT(f); Fnv = cuddE(f);
+
+    if (markT == DD_LIC_NL) {
+        t = cuddBddLICBuildResult(dd,Fv,cache,table);
+        if (t == NULL) {
+            return(NULL);
+        }
+    } else if (markT == DD_LIC_1) {
+        t = one;
+    } else {
+        t = zero;
+    }
+    cuddRef(t);
+    if (markE == DD_LIC_NL) {
+        e = cuddBddLICBuildResult(dd,Fnv,cache,table);
+        if (e == NULL) {
+            Cudd_IterDerefBdd(dd,t);
+            return(NULL);
+        }
+    } else if (markE == DD_LIC_1) {
+        e = one;
+    } else {
+        e = zero;
+    }
+    cuddRef(e);
+
+    if (markT == DD_LIC_DC && markE != DD_LIC_DC) {
+        r = e;
+    } else if (markT != DD_LIC_DC && markE == DD_LIC_DC) {
+        r = t;
+    } else {
+        if (Cudd_IsComplement(t)) {
+            t = Cudd_Not(t);
+            e = Cudd_Not(e);
+            r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+            if (r == NULL) {
+                Cudd_IterDerefBdd(dd, e);
+                Cudd_IterDerefBdd(dd, t);
+                return(NULL);
+            }
+            r = Cudd_Not(r);
+        } else {
+            r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+            if (r == NULL) {
+                Cudd_IterDerefBdd(dd, e);
+                Cudd_IterDerefBdd(dd, t);
+                return(NULL);
+            }
+        }
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    if ( st__insert(cache, (char *)f, (char *)r) == st__OUT_OF_MEM) {
+        cuddRef(r);
+        Cudd_IterDerefBdd(dd,r);
+        return(NULL);
+    }
+
+    return(Cudd_NotCond(r,comple));
+
+} /* end of cuddBddLICBuildResult */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Hash function for the computed table of cuddBddLICMarkEdges.]
+
+  Description [Hash function for the computed table of
+  cuddBddLICMarkEdges.  Returns the bucket number.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLICompaction]
+
+******************************************************************************/
+static int
+MarkCacheHash(
+  const char * ptr,
+  int  modulus)
+{
+    int val = 0;
+    MarkCacheKey *entry;
+
+    entry = (MarkCacheKey *) ptr;
+
+    val = (int) (ptrint) entry->f;
+    val = val * 997 + (int) (ptrint) entry->c;
+
+    return ((val < 0) ? -val : val) % modulus;
+
+} /* end of MarkCacheHash */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison function for the computed table of
+  cuddBddLICMarkEdges.]
+
+  Description [Comparison function for the computed table of
+  cuddBddLICMarkEdges. Returns 0 if the two nodes of the key are equal; 1
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLICompaction]
+
+******************************************************************************/
+static int
+MarkCacheCompare(
+  const char * ptr1,
+  const char * ptr2)
+{
+    MarkCacheKey *entry1, *entry2;
+
+    entry1 = (MarkCacheKey *) ptr1;
+    entry2 = (MarkCacheKey *) ptr2;
+    
+    return((entry1->f != entry2->f) || (entry1->c != entry2->c));
+
+} /* end of MarkCacheCompare */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees memory associated with computed table of
+  cuddBddLICMarkEdges.]
+
+  Description [Frees memory associated with computed table of
+  cuddBddLICMarkEdges. Returns st__CONTINUE.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLICompaction]
+
+******************************************************************************/
+static enum st__retval
+MarkCacheCleanUp(
+  char * key,
+  char * value,
+  char * arg)
+{
+    MarkCacheKey *entry;
+
+    entry = (MarkCacheKey *) key;
+    ABC_FREE(entry);
+    return st__CONTINUE;
+
+} /* end of MarkCacheCleanUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddSqueeze.]
+
+  Description [Performs the recursive step of Cudd_bddSqueeze.  This
+  procedure exploits the fact that if we complement and swap the
+  bounds of the interval we obtain a valid solution by taking the
+  complement of the solution to the original problem. Therefore, we
+  can enforce the condition that the upper bound is always regular.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddSqueeze]
+
+******************************************************************************/
+static DdNode *
+cuddBddSqueeze(
+  DdManager * dd,
+  DdNode * l,
+  DdNode * u)
+{
+    DdNode *one, *zero, *r, *lt, *le, *ut, *ue, *t, *e;
+#if 0
+    DdNode *ar;
+#endif
+    int comple = 0;
+    unsigned int topu, topl;
+    int index;
+
+    statLine(dd);
+    if (l == u) {
+        return(l);
+    }
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+    /* The only case when l == zero && u == one is at the top level,
+    ** where returning either one or zero is OK. In all other cases
+    ** the procedure will detect such a case and will perform
+    ** remapping. Therefore the order in which we test l and u at this
+    ** point is immaterial. */
+    if (l == zero) return(l);
+    if (u == one)  return(u);
+
+    /* Make canonical to increase the utilization of the cache. */
+    if (Cudd_IsComplement(u)) {
+        DdNode *temp;
+        temp = Cudd_Not(l);
+        l = Cudd_Not(u);
+        u = temp;
+        comple = 1;
+    }
+    /* At this point u is regular and non-constant; l is non-constant, but
+    ** may be complemented. */
+
+    /* Here we could check the relative sizes. */
+
+    /* Check the cache. */
+    r = cuddCacheLookup2(dd, Cudd_bddSqueeze, l, u);
+    if (r != NULL) {
+        return(Cudd_NotCond(r,comple));
+    }
+
+    /* Recursive step. */
+    topu = dd->perm[u->index];
+    topl = dd->perm[Cudd_Regular(l)->index];
+    if (topu <= topl) {
+        index = u->index;
+        ut = cuddT(u); ue = cuddE(u);
+    } else {
+        index = Cudd_Regular(l)->index;
+        ut = ue = u;
+    }
+    if (topl <= topu) {
+        lt = cuddT(Cudd_Regular(l)); le = cuddE(Cudd_Regular(l));
+        if (Cudd_IsComplement(l)) {
+            lt = Cudd_Not(lt);
+            le = Cudd_Not(le);
+        }
+    } else {
+        lt = le = l;
+    }
+
+    /* If one interval is contained in the other, use the smaller
+    ** interval. This corresponds to one-sided matching. */
+    if ((lt == zero || Cudd_bddLeq(dd,lt,le)) &&
+        (ut == one  || Cudd_bddLeq(dd,ue,ut))) { /* remap */
+        r = cuddBddSqueeze(dd, le, ue);
+        if (r == NULL)
+            return(NULL);
+        return(Cudd_NotCond(r,comple));
+    } else if ((le == zero || Cudd_bddLeq(dd,le,lt)) &&
+               (ue == one  || Cudd_bddLeq(dd,ut,ue))) { /* remap */
+        r = cuddBddSqueeze(dd, lt, ut);
+        if (r == NULL)
+            return(NULL);
+        return(Cudd_NotCond(r,comple));
+    } else if ((le == zero || Cudd_bddLeq(dd,le,Cudd_Not(ut))) &&
+               (ue == one  || Cudd_bddLeq(dd,Cudd_Not(lt),ue))) { /* c-remap */
+        t = cuddBddSqueeze(dd, lt, ut);
+        cuddRef(t);
+        if (Cudd_IsComplement(t)) {
+            r = cuddUniqueInter(dd, index, Cudd_Not(t), t);
+            if (r == NULL) {
+                Cudd_IterDerefBdd(dd, t);
+                return(NULL);
+            }
+            r = Cudd_Not(r);
+        } else {
+            r = cuddUniqueInter(dd, index, t, Cudd_Not(t));
+            if (r == NULL) {
+                Cudd_IterDerefBdd(dd, t);
+                return(NULL);
+            }
+        }
+        cuddDeref(t);
+        if (r == NULL)
+            return(NULL);
+        cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r);
+        return(Cudd_NotCond(r,comple));
+    } else if ((lt == zero || Cudd_bddLeq(dd,lt,Cudd_Not(ue))) &&
+               (ut == one  || Cudd_bddLeq(dd,Cudd_Not(le),ut))) { /* c-remap */
+        e = cuddBddSqueeze(dd, le, ue);
+        cuddRef(e);
+        if (Cudd_IsComplement(e)) {
+            r = cuddUniqueInter(dd, index, Cudd_Not(e), e);
+            if (r == NULL) {
+                Cudd_IterDerefBdd(dd, e);
+                return(NULL);
+            }
+        } else {
+            r = cuddUniqueInter(dd, index, e, Cudd_Not(e));
+            if (r == NULL) {
+                Cudd_IterDerefBdd(dd, e);
+                return(NULL);
+            }
+            r = Cudd_Not(r);
+        }
+        cuddDeref(e);
+        if (r == NULL)
+            return(NULL);
+        cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r);
+        return(Cudd_NotCond(r,comple));
+    }
+
+#if 0
+    /* If the two intervals intersect, take a solution from
+    ** the intersection of the intervals. This guarantees that the
+    ** splitting variable will not appear in the result.
+    ** This approach corresponds to two-sided matching, and is very
+    ** expensive. */
+    if (Cudd_bddLeq(dd,lt,ue) && Cudd_bddLeq(dd,le,ut)) {
+        DdNode *au, *al;
+        au = cuddBddAndRecur(dd,ut,ue);
+        if (au == NULL)
+            return(NULL);
+        cuddRef(au);
+        al = cuddBddAndRecur(dd,Cudd_Not(lt),Cudd_Not(le));
+        if (al == NULL) {
+            Cudd_IterDerefBdd(dd,au);
+            return(NULL);
+        }
+        cuddRef(al);
+        al = Cudd_Not(al);
+        ar = cuddBddSqueeze(dd, al, au);
+        if (ar == NULL) {
+            Cudd_IterDerefBdd(dd,au);
+            Cudd_IterDerefBdd(dd,al);
+            return(NULL);
+        }
+        cuddRef(ar);
+        Cudd_IterDerefBdd(dd,au);
+        Cudd_IterDerefBdd(dd,al);
+    } else {
+        ar = NULL;
+    }
+#endif
+
+    t = cuddBddSqueeze(dd, lt, ut);
+    if (t == NULL) {
+        return(NULL);
+    }
+    cuddRef(t);
+    e = cuddBddSqueeze(dd, le, ue);
+    if (e == NULL) {
+        Cudd_IterDerefBdd(dd,t);
+        return(NULL);
+    }
+    cuddRef(e);
+
+    if (Cudd_IsComplement(t)) {
+        t = Cudd_Not(t);
+        e = Cudd_Not(e);
+        r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+        if (r == NULL) {
+            Cudd_IterDerefBdd(dd, e);
+            Cudd_IterDerefBdd(dd, t);
+            return(NULL);
+        }
+        r = Cudd_Not(r);
+    } else {
+        r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+        if (r == NULL) {
+            Cudd_IterDerefBdd(dd, e);
+            Cudd_IterDerefBdd(dd, t);
+            return(NULL);
+        }
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+#if 0
+    /* Check whether there is a result obtained by abstraction and whether
+    ** it is better than the one obtained by recursion. */
+    cuddRef(r);
+    if (ar != NULL) {
+        if (Cudd_DagSize(ar) <= Cudd_DagSize(r)) {
+            Cudd_IterDerefBdd(dd, r);
+            r = ar;
+        } else {
+            Cudd_IterDerefBdd(dd, ar);
+        }
+    }
+    cuddDeref(r);
+#endif
+
+    cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r);
+    return(Cudd_NotCond(r,comple));
+
+} /* end of cuddBddSqueeze */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddGenetic.c b/abc-build/src/bdd/cudd/cuddGenetic.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddGenetic.c
@@ -0,0 +1,965 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddGenetic.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Genetic algorithm for variable reordering.]
+
+  Description [Internal procedures included in this file:
+                <ul>
+                <li> cuddGa()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> make_random()
+                <li> sift_up()
+                <li> build_dd()
+                <li> largest()
+                <li> rand_int()
+                <li> array_hash()
+                <li> array_compare()
+                <li> find_best()
+                <li> find_average_fitness()
+                <li> PMX()
+                <li> roulette()
+                </ul>
+
+  The genetic algorithm implemented here is as follows.  We start with
+  the current DD order.  We sift this order and use this as the
+  reference DD.  We only keep 1 DD around for the entire process and
+  simply rearrange the order of this DD, storing the various orders
+  and their corresponding DD sizes.  We generate more random orders to
+  build an initial population. This initial population is 3 times the
+  number of variables, with a maximum of 120. Each random order is
+  built (from the reference DD) and its size stored.  Each random
+  order is also sifted to keep the DD sizes fairly small.  Then a
+  crossover is performed between two orders (picked randomly) and the
+  two resulting DDs are built and sifted.  For each new order, if its
+  size is smaller than any DD in the population, it is inserted into
+  the population and the DD with the largest number of nodes is thrown
+  out. The crossover process happens up to 50 times, and at this point
+  the DD in the population with the smallest size is chosen as the
+  result.  This DD must then be built from the reference DD.]
+
+  SeeAlso     []
+
+  Author      [Curt Musfeldt, Alan Shuler, Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddGenetic.c,v 1.28 2004/08/13 18:04:48 fabio Exp $";
+#endif
+
+static int popsize;             /* the size of the population */
+static int numvars;             /* the number of input variables in the ckt. */
+/* storedd stores the population orders and sizes. This table has two
+** extra rows and one extras column. The two extra rows are used for the
+** offspring produced by a crossover. Each row stores one order and its
+** size. The order is stored by storing the indices of variables in the
+** order in which they appear in the order. The table is in reality a
+** one-dimensional array which is accessed via a macro to give the illusion
+** it is a two-dimensional structure.
+*/
+static int *storedd;
+static st__table *computed;      /* hash table to identify existing orders */
+static int *repeat;             /* how many times an order is present */
+static int large;               /* stores the index of the population with
+                                ** the largest number of nodes in the DD */
+static int result;
+static int cross;               /* the number of crossovers to perform */
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/* macro used to access the population table as if it were a
+** two-dimensional structure.
+*/
+#define STOREDD(i,j)    storedd[(i)*(numvars+1)+(j)]
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int make_random (DdManager *table, int lower);
+static int sift_up (DdManager *table, int x, int x_low);
+static int build_dd (DdManager *table, int num, int lower, int upper);
+static int largest (void);
+static int rand_int (int a);
+static int array_hash (const char *array, int modulus);
+static int array_compare (const char *array1, const char *array2);
+static int find_best (void);
+#ifdef DD_STATS
+static double find_average_fitness (void);
+#endif
+static int PMX (int maxvar);
+static int roulette (int *p1, int *p2);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Genetic algorithm for DD reordering.]
+
+  Description [Genetic algorithm for DD reordering.
+  The two children of a crossover will be stored in
+  storedd[popsize] and storedd[popsize+1] --- the last two slots in the
+  storedd array.  (This will make comparisons and replacement easy.)
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddGa(
+  DdManager * table /* manager */,
+  int  lower /* lowest level to be reordered */,
+  int  upper /* highest level to be reorderded */)
+{
+    int         i,n,m;          /* dummy/loop vars */
+    int         index;
+#ifdef DD_STATS
+    double      average_fitness;
+#endif
+    int         small;          /* index of smallest DD in population */
+
+    /* Do an initial sifting to produce at least one reasonable individual. */
+    if (!cuddSifting(table,lower,upper)) return(0);
+
+    /* Get the initial values. */
+    numvars = upper - lower + 1; /* number of variables to be reordered */
+    if (table->populationSize == 0) {
+        popsize = 3 * numvars;  /* population size is 3 times # of vars */
+        if (popsize > 120) {
+            popsize = 120;      /* Maximum population size is 120 */
+        }
+    } else {
+        popsize = table->populationSize;  /* user specified value */
+    }
+    if (popsize < 4) popsize = 4;       /* enforce minimum population size */
+
+    /* Allocate population table. */
+    storedd = ABC_ALLOC(int,(popsize+2)*(numvars+1));
+    if (storedd == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+
+    /* Initialize the computed table. This table is made up of two data
+    ** structures: A hash table with the key given by the order, which says
+    ** if a given order is present in the population; and the repeat
+    ** vector, which says how many copies of a given order are stored in
+    ** the population table. If there are multiple copies of an order, only
+    ** one has a repeat count greater than 1. This copy is the one pointed
+    ** by the computed table.
+    */
+    repeat = ABC_ALLOC(int,popsize);
+    if (repeat == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        ABC_FREE(storedd);
+        return(0);
+    }
+    for (i = 0; i < popsize; i++) {
+        repeat[i] = 0;
+    }
+    computed = st__init_table(array_compare,array_hash);
+    if (computed == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        ABC_FREE(storedd);
+        ABC_FREE(repeat);
+        return(0);
+    }
+
+    /* Copy the current DD and its size to the population table. */
+    for (i = 0; i < numvars; i++) {
+        STOREDD(0,i) = table->invperm[i+lower]; /* order of initial DD */
+    }
+    STOREDD(0,numvars) = table->keys - table->isolated; /* size of initial DD */
+
+    /* Store the initial order in the computed table. */
+    if ( st__insert(computed,(char *)storedd,(char *) 0) == st__OUT_OF_MEM) {
+        ABC_FREE(storedd);
+        ABC_FREE(repeat);
+        st__free_table(computed);
+        return(0);
+    }
+    repeat[0]++;
+
+    /* Insert the reverse order as second element of the population. */
+    for (i = 0; i < numvars; i++) {
+        STOREDD(1,numvars-1-i) = table->invperm[i+lower]; /* reverse order */
+    }
+
+    /* Now create the random orders. make_random fills the population
+    ** table with random permutations. The successive loop builds and sifts
+    ** the DDs for the reverse order and each random permutation, and stores
+    ** the results in the computed table.
+    */
+    if (!make_random(table,lower)) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        ABC_FREE(storedd);
+        ABC_FREE(repeat);
+        st__free_table(computed);
+        return(0);
+    }
+    for (i = 1; i < popsize; i++) {
+        result = build_dd(table,i,lower,upper); /* build and sift order */
+        if (!result) {
+            ABC_FREE(storedd);
+            ABC_FREE(repeat);
+            st__free_table(computed);
+            return(0);
+        }
+        if ( st__lookup_int(computed,(char *)&STOREDD(i,0),&index)) {
+            repeat[index]++;
+        } else {
+            if ( st__insert(computed,(char *)&STOREDD(i,0),(char *)(long)i) ==
+            st__OUT_OF_MEM) {
+                ABC_FREE(storedd);
+                ABC_FREE(repeat);
+                st__free_table(computed);
+                return(0);
+            }
+            repeat[i]++;
+        }
+    }
+
+#if 0
+#ifdef DD_STATS
+    /* Print the initial population. */
+    (void) fprintf(table->out,"Initial population after sifting\n");
+    for (m = 0; m < popsize; m++) {
+        for (i = 0; i < numvars; i++) {
+            (void) fprintf(table->out," %2d",STOREDD(m,i));
+        }
+        (void) fprintf(table->out," : %3d (%d)\n",
+                       STOREDD(m,numvars),repeat[m]);
+    }
+#endif
+#endif
+
+    small = find_best();
+#ifdef DD_STATS
+    average_fitness = find_average_fitness();
+    (void) fprintf(table->out,"\nInitial population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness);
+#endif
+
+    /* Decide how many crossovers should be tried. */
+    if (table->numberXovers == 0) {
+        cross = 3*numvars;
+        if (cross > 60) {       /* do a maximum of 50 crossovers */
+            cross = 60;
+        }
+    } else {
+        cross = table->numberXovers;      /* use user specified value */
+    }
+
+    /* Perform the crossovers to get the best order. */
+    for (m = 0; m < cross; m++) {
+        if (!PMX(table->size)) {        /* perform one crossover */
+            table->errorCode = CUDD_MEMORY_OUT;
+            ABC_FREE(storedd);
+            ABC_FREE(repeat);
+            st__free_table(computed);
+            return(0);
+        }
+        /* The offsprings are left in the last two entries of the
+        ** population table. These are now considered in turn.
+        */
+        for (i = popsize; i <= popsize+1; i++) {
+            result = build_dd(table,i,lower,upper); /* build and sift child */
+            if (!result) {
+                ABC_FREE(storedd);
+                ABC_FREE(repeat);
+                st__free_table(computed);
+                return(0);
+            }
+            large = largest();  /* find the largest DD in population */
+
+            /* If the new child is smaller than the largest DD in the current
+            ** population, enter it into the population in place of the
+            ** largest DD.
+            */
+            if (STOREDD(i,numvars) < STOREDD(large,numvars)) {
+                /* Look up the largest DD in the computed table.
+                ** Decrease its repetition count. If the repetition count
+                ** goes to 0, remove the largest DD from the computed table.
+                */
+                result = st__lookup_int(computed,(char *)&STOREDD(large,0),
+                                       &index);
+                if (!result) {
+                    ABC_FREE(storedd);
+                    ABC_FREE(repeat);
+                    st__free_table(computed);
+                    return(0);
+                }
+                repeat[index]--;
+                if (repeat[index] == 0) {
+                    int *pointer = &STOREDD(index,0);
+                    result = st__delete(computed, (const char **)&pointer, NULL);
+                    if (!result) {
+                        ABC_FREE(storedd);
+                        ABC_FREE(repeat);
+                        st__free_table(computed);
+                        return(0);
+                    }
+                }
+                /* Copy the new individual to the entry of the
+                ** population table just made available and update the
+                ** computed table.
+                */
+                for (n = 0; n <= numvars; n++) {
+                    STOREDD(large,n) = STOREDD(i,n);
+                }
+                if ( st__lookup_int(computed,(char *)&STOREDD(large,0),
+                                  &index)) {
+                    repeat[index]++;
+                } else {
+                    if ( st__insert(computed,(char *)&STOREDD(large,0),
+                    (char *)(long)large) == st__OUT_OF_MEM) {
+                        ABC_FREE(storedd);
+                        ABC_FREE(repeat);
+                        st__free_table(computed);
+                        return(0);
+                    }
+                    repeat[large]++;
+                }
+            }
+        }
+    }
+
+    /* Find the smallest DD in the population and build it;
+    ** that will be the result.
+    */
+    small = find_best();
+
+    /* Print stats on the final population. */
+#ifdef DD_STATS
+    average_fitness = find_average_fitness();
+    (void) fprintf(table->out,"\nFinal population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness);
+#endif
+
+    /* Clean up, build the result DD, and return. */
+    st__free_table(computed);
+    computed = NULL;
+    result = build_dd(table,small,lower,upper);
+    ABC_FREE(storedd);
+    ABC_FREE(repeat);
+    return(result);
+
+} /* end of cuddGa */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Generates the random sequences for the initial population.]
+
+  Description [Generates the random sequences for the initial population.
+  The sequences are permutations of the indices between lower and
+  upper in the current order.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+make_random(
+  DdManager * table,
+  int  lower)
+{
+    int i,j;            /* loop variables */
+    int *used;          /* is a number already in a permutation */
+    int next;           /* next random number without repetitions */
+
+    used = ABC_ALLOC(int,numvars);
+    if (used == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+#if 0
+#ifdef DD_STATS
+    (void) fprintf(table->out,"Initial population before sifting\n");
+    for (i = 0; i < 2; i++) {
+        for (j = 0; j < numvars; j++) {
+            (void) fprintf(table->out," %2d",STOREDD(i,j));
+        }
+        (void) fprintf(table->out,"\n");
+    }
+#endif
+#endif
+    for (i = 2; i < popsize; i++) {
+        for (j = 0; j < numvars; j++) {
+            used[j] = 0;
+        }
+        /* Generate a permutation of {0...numvars-1} and use it to
+        ** permute the variables in the layesr from lower to upper.
+        */
+        for (j = 0; j < numvars; j++) {
+            do {
+                next = rand_int(numvars-1);
+            } while (used[next] != 0);
+            used[next] = 1;
+            STOREDD(i,j) = table->invperm[next+lower];
+        }
+#if 0
+#ifdef DD_STATS
+        /* Print the order just generated. */
+        for (j = 0; j < numvars; j++) {
+            (void) fprintf(table->out," %2d",STOREDD(i,j));
+        }
+        (void) fprintf(table->out,"\n");
+#endif
+#endif
+    }
+    ABC_FREE(used);
+    return(1);
+
+} /* end of make_random */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves one variable up.]
+
+  Description [Takes a variable from position x and sifts it up to
+  position x_low;  x_low should be less than x. Returns 1 if successful;
+  0 otherwise]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+sift_up(
+  DdManager * table,
+  int  x,
+  int  x_low)
+{
+    int        y;
+    int        size;
+
+    y = cuddNextLow(table,x);
+    while (y >= x_low) {
+        size = cuddSwapInPlace(table,y,x);
+        if (size == 0) {
+            return(0);
+        }
+        x = y;
+        y = cuddNextLow(table,x);
+    }
+    return(1);
+
+} /* end of sift_up */
+
+
+/**Function********************************************************************
+
+  Synopsis [Builds a DD from a given order.]
+
+  Description [Builds a DD from a given order.  This procedure also
+  sifts the final order and inserts into the array the size in nodes
+  of the result. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+build_dd(
+  DdManager * table,
+  int  num /* the index of the individual to be built */,
+  int  lower,
+  int  upper)
+{
+    int         i,j;            /* loop vars */
+    int         position;
+    int         index;
+    int         limit;          /* how large the DD for this order can grow */
+    int         size;
+
+    /* Check the computed table. If the order already exists, it
+    ** suffices to copy the size from the existing entry.
+    */
+    if (computed && st__lookup_int(computed,(char *)&STOREDD(num,0),&index)) {
+        STOREDD(num,numvars) = STOREDD(index,numvars);
+#ifdef DD_STATS
+        (void) fprintf(table->out,"\nCache hit for index %d", index);
+#endif
+        return(1);
+    }
+
+    /* Stop if the DD grows 20 times larges than the reference size. */
+    limit = 20 * STOREDD(0,numvars);
+
+    /* Sift up the variables so as to build the desired permutation.
+    ** First the variable that has to be on top is sifted to the top.
+    ** Then the variable that has to occupy the secon position is sifted
+    ** up to the second position, and so on.
+    */
+    for (j = 0; j < numvars; j++) {
+        i = STOREDD(num,j);
+        position = table->perm[i];
+        result = sift_up(table,position,j+lower);
+        if (!result) return(0);
+        size = table->keys - table->isolated;
+        if (size > limit) break;
+    }
+
+    /* Sift the DD just built. */
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n");
+#endif
+    result = cuddSifting(table,lower,upper);
+    if (!result) return(0);
+
+    /* Copy order and size to table. */
+    for (j = 0; j < numvars; j++) {
+        STOREDD(num,j) = table->invperm[lower+j];
+    }
+    STOREDD(num,numvars) = table->keys - table->isolated; /* size of new DD */
+    return(1);
+
+} /* end of build_dd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the largest DD in the population.]
+
+  Description [Finds the largest DD in the population. If an order is
+  repeated, it avoids choosing the copy that is in the computed table
+  (it has repeat[i] > 1).]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+largest(void)
+{
+    int i;      /* loop var */
+    int big;    /* temporary holder to return result */
+
+    big = 0;
+    while (repeat[big] > 1) big++;
+    for (i = big + 1; i < popsize; i++) {
+        if (STOREDD(i,numvars) >= STOREDD(big,numvars) && repeat[i] <= 1) {
+            big = i;
+        }
+    }
+    return(big);
+
+} /* end of largest */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a random number between 0 and the integer a.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+rand_int(
+  int  a)
+{
+    return(Cudd_Random() % (a+1));
+
+} /* end of rand_int */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Hash function for the computed table.]
+
+  Description [Hash function for the computed table. Returns the bucket
+  number.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+array_hash(
+  const char * array,
+  int  modulus)
+{
+    int val = 0;
+    int i;
+    int *intarray;
+
+    intarray = (int *) array;
+
+    for (i = 0; i < numvars; i++) {
+        val = val * 997 + intarray[i];
+    }
+
+    return ((val < 0) ? -val : val) % modulus;
+
+} /* end of array_hash */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison function for the computed table.]
+
+  Description [Comparison function for the computed table. Returns 0 if
+  the two arrays are equal; 1 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+array_compare(
+  const char * array1,
+  const char * array2)
+{
+    int i;
+    int *intarray1, *intarray2;
+
+    intarray1 = (int *) array1;
+    intarray2 = (int *) array2;
+
+    for (i = 0; i < numvars; i++) {
+        if (intarray1[i] != intarray2[i]) return(1);
+    }
+    return(0);
+
+} /* end of array_compare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of the fittest individual.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+find_best(void)
+{
+    int i,small;
+
+    small = 0;
+    for (i = 1; i < popsize; i++) {
+        if (STOREDD(i,numvars) < STOREDD(small,numvars)) {
+            small = i;
+        }
+    }
+    return(small);
+
+} /* end of find_best */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the average fitness of the population.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+#ifdef DD_STATS
+static double
+find_average_fitness(void)
+{
+    int i;
+    int total_fitness = 0;
+    double average_fitness;
+
+    for (i = 0; i < popsize; i++) {
+        total_fitness += STOREDD(i,numvars);
+    }
+    average_fitness = (double) total_fitness / (double) popsize;
+    return(average_fitness);
+
+} /* end of find_average_fitness */
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the crossover between two parents.]
+
+  Description [Performs the crossover between two randomly chosen
+  parents, and creates two children, x1 and x2. Uses the Partially
+  Matched Crossover operator.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+PMX(
+  int  maxvar)
+{
+    int         cut1,cut2;      /* the two cut positions (random) */
+    int         mom,dad;        /* the two randomly chosen parents */
+    int         *inv1;          /* inverse permutations for repair algo */
+    int         *inv2;
+    int         i;              /* loop vars */
+    int         u,v;            /* aux vars */
+
+    inv1 = ABC_ALLOC(int,maxvar);
+    if (inv1 == NULL) {
+        return(0);
+    }
+    inv2 = ABC_ALLOC(int,maxvar);
+    if (inv2 == NULL) {
+        ABC_FREE(inv1);
+        return(0);
+    }
+
+    /* Choose two orders from the population using roulette wheel. */
+    if (!roulette(&mom,&dad)) {
+        ABC_FREE(inv1);
+        ABC_FREE(inv2);
+        return(0);
+    }
+
+    /* Choose two random cut positions. A cut in position i means that
+    ** the cut immediately precedes position i.  If cut1 < cut2, we
+    ** exchange the middle of the two orderings; otherwise, we
+    ** exchange the beginnings and the ends.
+    */
+    cut1 = rand_int(numvars-1);
+    do {
+        cut2 = rand_int(numvars-1);
+    } while (cut1 == cut2);
+
+#if 0
+    /* Print out the parents. */
+    (void) fprintf(table->out,
+                   "Crossover of %d (mom) and %d (dad) between %d and %d\n",
+                   mom,dad,cut1,cut2);
+    for (i = 0; i < numvars; i++) {
+        if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
+        (void) fprintf(table->out,"%2d ",STOREDD(mom,i));
+    }
+    (void) fprintf(table->out,"\n");
+    for (i = 0; i < numvars; i++) {
+        if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
+        (void) fprintf(table->out,"%2d ",STOREDD(dad,i));
+    }
+    (void) fprintf(table->out,"\n");
+#endif
+
+    /* Initialize the inverse permutations: -1 means yet undetermined. */
+    for (i = 0; i < maxvar; i++) {
+        inv1[i] = -1;
+        inv2[i] = -1;
+    }
+
+    /* Copy the portions whithin the cuts. */
+    for (i = cut1; i != cut2; i = (i == numvars-1) ? 0 : i+1) {
+        STOREDD(popsize,i) = STOREDD(dad,i);
+        inv1[STOREDD(popsize,i)] = i;
+        STOREDD(popsize+1,i) = STOREDD(mom,i);
+        inv2[STOREDD(popsize+1,i)] = i;
+    }
+
+    /* Now apply the repair algorithm outside the cuts. */
+    for (i = cut2; i != cut1; i = (i == numvars-1 ) ? 0 : i+1) {
+        v = i;
+        do {
+            u = STOREDD(mom,v);
+            v = inv1[u];
+        } while (v != -1);
+        STOREDD(popsize,i) = u;
+        inv1[u] = i;
+        v = i;
+        do {
+            u = STOREDD(dad,v);
+            v = inv2[u];
+        } while (v != -1);
+        STOREDD(popsize+1,i) = u;
+        inv2[u] = i;
+    }
+
+#if 0
+    /* Print the results of crossover. */
+    for (i = 0; i < numvars; i++) {
+        if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
+        (void) fprintf(table->out,"%2d ",STOREDD(popsize,i));
+    }
+    (void) fprintf(table->out,"\n");
+    for (i = 0; i < numvars; i++) {
+        if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
+        (void) fprintf(table->out,"%2d ",STOREDD(popsize+1,i));
+    }
+    (void) fprintf(table->out,"\n");
+#endif
+
+    ABC_FREE(inv1);
+    ABC_FREE(inv2);
+    return(1);
+
+} /* end of PMX */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Selects two parents with the roulette wheel method.]
+
+  Description [Selects two distinct parents with the roulette wheel method.]
+
+  SideEffects [The indices of the selected parents are returned as side
+  effects.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+roulette(
+  int * p1,
+  int * p2)
+{
+    double *wheel;
+    double spin;
+    int i;
+
+    wheel = ABC_ALLOC(double,popsize);
+    if (wheel == NULL) {
+        return(0);
+    }
+
+    /* The fitness of an individual is the reciprocal of its size. */
+    wheel[0] = 1.0 / (double) STOREDD(0,numvars);
+
+    for (i = 1; i < popsize; i++) {
+        wheel[i] = wheel[i-1] + 1.0 / (double) STOREDD(i,numvars);
+    }
+
+    /* Get a random number between 0 and wheel[popsize-1] (that is,
+    ** the sum of all fitness values. 2147483561 is the largest number
+    ** returned by Cudd_Random.
+    */
+    spin = wheel[numvars-1] * (double) Cudd_Random() / 2147483561.0;
+
+    /* Find the lucky element by scanning the wheel. */
+    for (i = 0; i < popsize; i++) {
+        if (spin <= wheel[i]) break;
+    }
+    *p1 = i;
+
+    /* Repeat the process for the second parent, making sure it is
+    ** distinct from the first.
+    */
+    do {
+        spin = wheel[popsize-1] * (double) Cudd_Random() / 2147483561.0;
+        for (i = 0; i < popsize; i++) {
+            if (spin <= wheel[i]) break;
+        }
+    } while (i == *p1);
+    *p2 = i;
+
+    ABC_FREE(wheel);
+    return(1);
+
+} /* end of roulette */
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddGroup.c b/abc-build/src/bdd/cudd/cuddGroup.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddGroup.c
@@ -0,0 +1,2187 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddGroup.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for group sifting.]
+
+  Description [External procedures included in this file:
+                <ul>
+                <li> Cudd_MakeTreeNode()
+                </ul>
+        Internal procedures included in this file:
+                <ul>
+                <li> cuddTreeSifting()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> ddTreeSiftingAux()
+                <li> ddCountInternalMtrNodes()
+                <li> ddReorderChildren()
+                <li> ddFindNodeHiLo()
+                <li> ddUniqueCompareGroup()
+                <li> ddGroupSifting()
+                <li> ddCreateGroup()
+                <li> ddGroupSiftingAux()
+                <li> ddGroupSiftingUp()
+                <li> ddGroupSiftingDown()
+                <li> ddGroupMove()
+                <li> ddGroupMoveBackward()
+                <li> ddGroupSiftingBackward()
+                <li> ddMergeGroups()
+                <li> ddDissolveGroup()
+                <li> ddNoCheck()
+                <li> ddSecDiffCheck()
+                <li> ddExtSymmCheck()
+                <li> ddVarGroupCheck()
+                <li> ddSetVarHandled()
+                <li> ddResetVarHandled()
+                <li> ddIsVarHandled()
+                </ul>]
+
+  Author      [Shipra Panda, Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* Constants for lazy sifting */
+#define DD_NORMAL_SIFT  0
+#define DD_LAZY_SIFT    1
+
+/* Constants for sifting up and down */
+#define DD_SIFT_DOWN    0
+#define DD_SIFT_UP      1
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+    typedef int (*DD_CHKFP)(DdManager *, int, int);
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddGroup.c,v 1.44 2009/02/21 18:24:10 fabio Exp $";
+#endif
+
+static  int     *entry;
+extern  int     ddTotalNumberSwapping;
+#ifdef DD_STATS
+extern  int     ddTotalNISwaps;
+static  int     extsymmcalls;
+static  int     extsymm;
+static  int     secdiffcalls;
+static  int     secdiff;
+static  int     secdiffmisfire;
+#endif
+#ifdef DD_DEBUG
+static  int     pr = 0; /* flag to enable printing while debugging */
+                        /* by depositing a 1 into it */
+#endif
+static unsigned int originalSize;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int ddTreeSiftingAux (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
+#ifdef DD_STATS
+static int ddCountInternalMtrNodes (DdManager *table, MtrNode *treenode);
+#endif
+static int ddReorderChildren (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
+static void ddFindNodeHiLo (DdManager *table, MtrNode *treenode, int *lower, int *upper);
+static int ddUniqueCompareGroup (int *ptrX, int *ptrY);
+static int ddGroupSifting (DdManager *table, int lower, int upper, DD_CHKFP checkFunction, int lazyFlag);
+static void ddCreateGroup (DdManager *table, int x, int y);
+static int ddGroupSiftingAux (DdManager *table, int x, int xLow, int xHigh, DD_CHKFP checkFunction, int lazyFlag);
+static int ddGroupSiftingUp (DdManager *table, int y, int xLow, DD_CHKFP checkFunction, Move **moves);
+static int ddGroupSiftingDown (DdManager *table, int x, int xHigh, DD_CHKFP checkFunction, Move **moves);
+static int ddGroupMove (DdManager *table, int x, int y, Move **moves);
+static int ddGroupMoveBackward (DdManager *table, int x, int y);
+static int ddGroupSiftingBackward (DdManager *table, Move *moves, int size, int upFlag, int lazyFlag);
+static void ddMergeGroups (DdManager *table, MtrNode *treenode, int low, int high);
+static void ddDissolveGroup (DdManager *table, int x, int y);
+static int ddNoCheck (DdManager *table, int x, int y);
+static int ddSecDiffCheck (DdManager *table, int x, int y);
+static int ddExtSymmCheck (DdManager *table, int x, int y);
+static int ddVarGroupCheck (DdManager * table, int x, int y);
+static int ddSetVarHandled (DdManager *dd, int index);
+static int ddResetVarHandled (DdManager *dd, int index);
+static int ddIsVarHandled (DdManager *dd, int index);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a new variable group.]
+
+  Description [Creates a new variable group. The group starts at
+  variable and contains size variables. The parameter low is the index
+  of the first variable. If the variable already exists, its current
+  position in the order is known to the manager. If the variable does
+  not exist yet, the position is assumed to be the same as the index.
+  The group tree is created if it does not exist yet.
+  Returns a pointer to the group if successful; NULL otherwise.]
+
+  SideEffects [The variable tree is changed.]
+
+  SeeAlso     [Cudd_MakeZddTreeNode]
+
+******************************************************************************/
+MtrNode *
+Cudd_MakeTreeNode(
+  DdManager * dd /* manager */,
+  unsigned int  low /* index of the first group variable */,
+  unsigned int  size /* number of variables in the group */,
+  unsigned int  type /* MTR_DEFAULT or MTR_FIXED */)
+{
+    MtrNode *group;
+    MtrNode *tree;
+    unsigned int level;
+
+    /* If the variable does not exist yet, the position is assumed to be
+    ** the same as the index. Therefore, applications that rely on
+    ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new
+    ** variables have to create the variables before they group them.
+    */
+    level = (low < (unsigned int) dd->size) ? dd->perm[low] : low;
+
+    if (level + size - 1> (int) MTR_MAXHIGH)
+        return(NULL);
+
+    /* If the tree does not exist yet, create it. */
+    tree = dd->tree;
+    if (tree == NULL) {
+        dd->tree = tree = Mtr_InitGroupTree(0, dd->size);
+        if (tree == NULL)
+            return(NULL);
+        tree->index = dd->invperm[0];
+    }
+
+    /* Extend the upper bound of the tree if necessary. This allows the
+    ** application to create groups even before the variables are created.
+    */
+    tree->size = ddMax(tree->size, ddMax(level + size, (unsigned) dd->size));
+
+    /* Create the group. */
+    group = Mtr_MakeGroup(tree, level, size, type);
+    if (group == NULL)
+        return(NULL);
+
+    /* Initialize the index field to the index of the variable currently
+    ** in position low. This field will be updated by the reordering
+    ** procedure to provide a handle to the group once it has been moved.
+    */
+    group->index = (MtrHalfWord) low;
+
+    return(group);
+
+} /* end of Cudd_MakeTreeNode */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tree sifting algorithm.]
+
+  Description [Tree sifting algorithm. Assumes that a tree representing
+  a group hierarchy is passed as a parameter. It then reorders each
+  group in postorder fashion by calling ddTreeSiftingAux.  Assumes that
+  no dead nodes are present.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+cuddTreeSifting(
+  DdManager * table /* DD table */,
+  Cudd_ReorderingType method /* reordering method for the groups of leaves */)
+{
+    int i;
+    int nvars;
+    int result;
+    int tempTree;
+
+    /* If no tree is provided we create a temporary one in which all
+    ** variables are in a single group. After reordering this tree is
+    ** destroyed.
+    */
+    tempTree = table->tree == NULL;
+    if (tempTree) {
+        table->tree = Mtr_InitGroupTree(0,table->size);
+        table->tree->index = table->invperm[0];
+    }
+    nvars = table->size;
+
+#ifdef DD_DEBUG
+    if (pr > 0 && !tempTree) (void) fprintf(table->out,"cuddTreeSifting:");
+    Mtr_PrintGroups(table->tree,pr <= 0);
+#endif
+
+#ifdef DD_STATS
+    extsymmcalls = 0;
+    extsymm = 0;
+    secdiffcalls = 0;
+    secdiff = 0;
+    secdiffmisfire = 0;
+
+    (void) fprintf(table->out,"\n");
+    if (!tempTree)
+        (void) fprintf(table->out,"#:IM_NODES  %8d: group tree nodes\n",
+                       ddCountInternalMtrNodes(table,table->tree));
+#endif
+
+    /* Initialize the group of each subtable to itself. Initially
+    ** there are no groups. Groups are created according to the tree
+    ** structure in postorder fashion.
+    */
+    for (i = 0; i < nvars; i++)
+        table->subtables[i].next = i;
+
+
+    /* Reorder. */
+    result = ddTreeSiftingAux(table, table->tree, method);
+
+#ifdef DD_STATS         /* print stats */
+    if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
+        (table->groupcheck == CUDD_GROUP_CHECK7 ||
+         table->groupcheck == CUDD_GROUP_CHECK5)) {
+        (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls);
+        (void) fprintf(table->out,"extsymm = %d",extsymm);
+    }
+    if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
+        table->groupcheck == CUDD_GROUP_CHECK7) {
+        (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls);
+        (void) fprintf(table->out,"secdiff = %d\n",secdiff);
+        (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire);
+    }
+#endif
+
+    if (tempTree)
+        Cudd_FreeTree(table);
+    return(result);
+
+} /* end of cuddTreeSifting */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Visits the group tree and reorders each group.]
+
+  Description [Recursively visits the group tree and reorders each
+  group in postorder fashion.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddTreeSiftingAux(
+  DdManager * table,
+  MtrNode * treenode,
+  Cudd_ReorderingType method)
+{
+    MtrNode  *auxnode;
+    int res;
+    Cudd_AggregationType saveCheck;
+
+#ifdef DD_DEBUG
+    Mtr_PrintGroups(treenode,1);
+#endif
+
+    auxnode = treenode;
+    while (auxnode != NULL) {
+        if (auxnode->child != NULL) {
+            if (!ddTreeSiftingAux(table, auxnode->child, method))
+                return(0);
+            saveCheck = table->groupcheck;
+            table->groupcheck = CUDD_NO_CHECK;
+            if (method != CUDD_REORDER_LAZY_SIFT)
+              res = ddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT);
+            else
+              res = ddReorderChildren(table, auxnode, CUDD_REORDER_LAZY_SIFT);
+            table->groupcheck = saveCheck;
+
+            if (res == 0)
+                return(0);
+        } else if (auxnode->size > 1) {
+            if (!ddReorderChildren(table, auxnode, method))
+                return(0);
+        }
+        auxnode = auxnode->younger;
+    }
+
+    return(1);
+
+} /* end of ddTreeSiftingAux */
+
+
+#ifdef DD_STATS
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of internal nodes of the group tree.]
+
+  Description [Counts the number of internal nodes of the group tree.
+  Returns the count.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddCountInternalMtrNodes(
+  DdManager * table,
+  MtrNode * treenode)
+{
+    MtrNode *auxnode;
+    int     count,nodeCount;
+
+
+    nodeCount = 0;
+    auxnode = treenode;
+    while (auxnode != NULL) {
+        if (!(MTR_TEST(auxnode,MTR_TERMINAL))) {
+            nodeCount++;
+            count = ddCountInternalMtrNodes(table,auxnode->child);
+            nodeCount += count;
+        }
+        auxnode = auxnode->younger;
+    }
+
+    return(nodeCount);
+
+} /* end of ddCountInternalMtrNodes */
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders the children of a group tree node according to
+  the options.]
+
+  Description [Reorders the children of a group tree node according to
+  the options. After reordering puts all the variables in the group
+  and/or its descendents in a single group. This allows hierarchical
+  reordering.  If the variables in the group do not exist yet, simply
+  does nothing. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddReorderChildren(
+  DdManager * table,
+  MtrNode * treenode,
+  Cudd_ReorderingType method)
+{
+    int lower;
+    int upper = -1;
+    int result;
+    unsigned int initialSize;
+
+    ddFindNodeHiLo(table,treenode,&lower,&upper);
+    /* If upper == -1 these variables do not exist yet. */
+    if (upper == -1)
+        return(1);
+
+    if (treenode->flags == MTR_FIXED) {
+        result = 1;
+    } else {
+#ifdef DD_STATS
+        (void) fprintf(table->out," ");
+#endif
+        switch (method) {
+        case CUDD_REORDER_RANDOM:
+        case CUDD_REORDER_RANDOM_PIVOT:
+            result = cuddSwapping(table,lower,upper,method);
+            break;
+        case CUDD_REORDER_SIFT:
+            result = cuddSifting(table,lower,upper);
+            break;
+        case CUDD_REORDER_SIFT_CONVERGE:
+            do {
+                initialSize = table->keys - table->isolated;
+                result = cuddSifting(table,lower,upper);
+                if (initialSize <= table->keys - table->isolated)
+                    break;
+#ifdef DD_STATS
+                else
+                    (void) fprintf(table->out,"\n");
+#endif
+            } while (result != 0);
+            break;
+        case CUDD_REORDER_SYMM_SIFT:
+            result = cuddSymmSifting(table,lower,upper);
+            break;
+        case CUDD_REORDER_SYMM_SIFT_CONV:
+            result = cuddSymmSiftingConv(table,lower,upper);
+            break;
+        case CUDD_REORDER_GROUP_SIFT:
+            if (table->groupcheck == CUDD_NO_CHECK) {
+                result = ddGroupSifting(table,lower,upper,ddNoCheck,
+                                        DD_NORMAL_SIFT);
+            } else if (table->groupcheck == CUDD_GROUP_CHECK5) {
+                result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
+                                        DD_NORMAL_SIFT);
+            } else if (table->groupcheck == CUDD_GROUP_CHECK7) {
+                result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
+                                        DD_NORMAL_SIFT);
+            } else {
+                (void) fprintf(table->err,
+                               "Unknown group ckecking method\n");
+                result = 0;
+            }
+            break;
+        case CUDD_REORDER_GROUP_SIFT_CONV:
+            do {
+                initialSize = table->keys - table->isolated;
+                if (table->groupcheck == CUDD_NO_CHECK) {
+                    result = ddGroupSifting(table,lower,upper,ddNoCheck,
+                                            DD_NORMAL_SIFT);
+                } else if (table->groupcheck == CUDD_GROUP_CHECK5) {
+                    result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
+                                            DD_NORMAL_SIFT);
+                } else if (table->groupcheck == CUDD_GROUP_CHECK7) {
+                    result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
+                                            DD_NORMAL_SIFT);
+                } else {
+                    (void) fprintf(table->err,
+                                   "Unknown group ckecking method\n");
+                    result = 0;
+                }
+#ifdef DD_STATS
+                (void) fprintf(table->out,"\n");
+#endif
+                result = cuddWindowReorder(table,lower,upper,
+                                           CUDD_REORDER_WINDOW4);
+                if (initialSize <= table->keys - table->isolated)
+                    break;
+#ifdef DD_STATS
+                else
+                    (void) fprintf(table->out,"\n");
+#endif
+            } while (result != 0);
+            break;
+        case CUDD_REORDER_WINDOW2:
+        case CUDD_REORDER_WINDOW3:
+        case CUDD_REORDER_WINDOW4:
+        case CUDD_REORDER_WINDOW2_CONV:
+        case CUDD_REORDER_WINDOW3_CONV:
+        case CUDD_REORDER_WINDOW4_CONV:
+            result = cuddWindowReorder(table,lower,upper,method);
+            break;
+        case CUDD_REORDER_ANNEALING:
+            result = cuddAnnealing(table,lower,upper);
+            break;
+        case CUDD_REORDER_GENETIC:
+            result = cuddGa(table,lower,upper);
+            break;
+        case CUDD_REORDER_LINEAR:
+            result = cuddLinearAndSifting(table,lower,upper);
+            break;
+        case CUDD_REORDER_LINEAR_CONVERGE:
+            do {
+                initialSize = table->keys - table->isolated;
+                result = cuddLinearAndSifting(table,lower,upper);
+                if (initialSize <= table->keys - table->isolated)
+                    break;
+#ifdef DD_STATS
+                else
+                    (void) fprintf(table->out,"\n");
+#endif
+            } while (result != 0);
+            break;
+        case CUDD_REORDER_EXACT:
+            result = cuddExact(table,lower,upper);
+            break;
+        case CUDD_REORDER_LAZY_SIFT:
+            result = ddGroupSifting(table,lower,upper,ddVarGroupCheck,
+                                    DD_LAZY_SIFT);
+            break;
+        default:
+            return(0);
+        }
+    }
+
+    /* Create a single group for all the variables that were sifted,
+    ** so that they will be treated as a single block by successive
+    ** invocations of ddGroupSifting.
+    */
+    ddMergeGroups(table,treenode,lower,upper);
+
+#ifdef DD_DEBUG
+    if (pr > 0) (void) fprintf(table->out,"ddReorderChildren:");
+#endif
+
+    return(result);
+
+} /* end of ddReorderChildren */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the lower and upper bounds of the group represented
+  by treenode.]
+
+  Description [Finds the lower and upper bounds of the group
+  represented by treenode.  From the index and size fields we need to
+  derive the current positions, and find maximum and minimum.]
+
+  SideEffects [The bounds are returned as side effects.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ddFindNodeHiLo(
+  DdManager * table,
+  MtrNode * treenode,
+  int * lower,
+  int * upper)
+{
+    int low;
+    int high;
+
+    /* Check whether no variables in this group already exist.
+    ** If so, return immediately. The calling procedure will know from
+    ** the values of upper that no reordering is needed.
+    */
+    if ((int) treenode->low >= table->size) {
+        *lower = table->size;
+        *upper = -1;
+        return;
+    }
+
+    *lower = low = (unsigned int) table->perm[treenode->index];
+    high = (int) (low + treenode->size - 1);
+
+    if (high >= table->size) {
+        /* This is the case of a partially existing group. The aim is to
+        ** reorder as many variables as safely possible.  If the tree
+        ** node is terminal, we just reorder the subset of the group
+        ** that is currently in existence.  If the group has
+        ** subgroups, then we only reorder those subgroups that are
+        ** fully instantiated.  This way we avoid breaking up a group.
+        */
+        MtrNode *auxnode = treenode->child;
+        if (auxnode == NULL) {
+            *upper = (unsigned int) table->size - 1;
+        } else {
+            /* Search the subgroup that strands the table->size line.
+            ** If the first group starts at 0 and goes past table->size
+            ** upper will get -1, thus correctly signaling that no reordering
+            ** should take place.
+            */
+            while (auxnode != NULL) {
+                int thisLower = table->perm[auxnode->low];
+                int thisUpper = thisLower + auxnode->size - 1;
+                if (thisUpper >= table->size && thisLower < table->size)
+                    *upper = (unsigned int) thisLower - 1;
+                auxnode = auxnode->younger;
+            }
+        }
+    } else {
+        /* Normal case: All the variables of the group exist. */
+        *upper = (unsigned int) high;
+    }
+
+#ifdef DD_DEBUG
+    /* Make sure that all variables in group are contiguous. */
+    assert(treenode->size >= *upper - *lower + 1);
+#endif
+
+    return;
+
+} /* end of ddFindNodeHiLo */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison function used by qsort.]
+
+  Description [Comparison function used by qsort to order the variables
+  according to the number of keys in the subtables.  Returns the
+  difference in number of keys between the two variables being
+  compared.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddUniqueCompareGroup(
+  int * ptrX,
+  int * ptrY)
+{
+#if 0
+    if (entry[*ptrY] == entry[*ptrX]) {
+        return((*ptrX) - (*ptrY));
+    }
+#endif
+    return(entry[*ptrY] - entry[*ptrX]);
+
+} /* end of ddUniqueCompareGroup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts from treenode->low to treenode->high.]
+
+  Description [Sifts from treenode->low to treenode->high. If
+  croupcheck == CUDD_GROUP_CHECK7, it checks for group creation at the
+  end of the initial sifting. If a group is created, it is then sifted
+  again. After sifting one variable, the group that contains it is
+  dissolved.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddGroupSifting(
+  DdManager * table,
+  int  lower,
+  int  upper,
+  DD_CHKFP checkFunction,
+  int lazyFlag)
+{
+    int         *var;
+    int         i,j,x,xInit;
+    int         nvars;
+    int         classes;
+    int         result;
+    int         *sifted;
+    int         merged;
+    int         dissolve;
+#ifdef DD_STATS
+    unsigned    previousSize;
+#endif
+    int         xindex;
+
+    nvars = table->size;
+
+    /* Order variables to sift. */
+    entry = NULL;
+    sifted = NULL;
+    var = ABC_ALLOC(int,nvars);
+    if (var == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto ddGroupSiftingOutOfMem;
+    }
+    entry = ABC_ALLOC(int,nvars);
+    if (entry == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto ddGroupSiftingOutOfMem;
+    }
+    sifted = ABC_ALLOC(int,nvars);
+    if (sifted == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto ddGroupSiftingOutOfMem;
+    }
+
+    /* Here we consider only one representative for each group. */
+    for (i = 0, classes = 0; i < nvars; i++) {
+        sifted[i] = 0;
+        x = table->perm[i];
+        if ((unsigned) x >= table->subtables[x].next) {
+            entry[i] = table->subtables[x].keys;
+            var[classes] = i;
+            classes++;
+        }
+    }
+
+    qsort((void *)var,classes,sizeof(int),
+          (DD_QSFP) ddUniqueCompareGroup);
+
+    if (lazyFlag) {
+        for (i = 0; i < nvars; i ++) {
+            ddResetVarHandled(table, i);
+        }
+    }
+
+    /* Now sift. */
+    for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
+        if (ddTotalNumberSwapping >= table->siftMaxSwap)
+            break;
+        xindex = var[i];
+        if (sifted[xindex] == 1) /* variable already sifted as part of group */
+            continue;
+        x = table->perm[xindex]; /* find current level of this variable */
+
+        if (x < lower || x > upper || table->subtables[x].bindVar == 1)
+            continue;
+#ifdef DD_STATS
+        previousSize = table->keys - table->isolated;
+#endif
+#ifdef DD_DEBUG
+        /* x is bottom of group */
+        assert((unsigned) x >= table->subtables[x].next);
+#endif
+        if ((unsigned) x == table->subtables[x].next) {
+            dissolve = 1;
+            result = ddGroupSiftingAux(table,x,lower,upper,checkFunction,
+                                        lazyFlag);
+        } else {
+            dissolve = 0;
+            result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag);
+        }
+        if (!result) goto ddGroupSiftingOutOfMem;
+
+        /* check for aggregation */
+        merged = 0;
+        if (lazyFlag == 0 && table->groupcheck == CUDD_GROUP_CHECK7) {
+            x = table->perm[xindex]; /* find current level */
+            if ((unsigned) x == table->subtables[x].next) { /* not part of a group */
+                if (x != upper && sifted[table->invperm[x+1]] == 0 &&
+                (unsigned) x+1 == table->subtables[x+1].next) {
+                    if (ddSecDiffCheck(table,x,x+1)) {
+                        merged =1;
+                        ddCreateGroup(table,x,x+1);
+                    }
+                }
+                if (x != lower && sifted[table->invperm[x-1]] == 0 &&
+                (unsigned) x-1 == table->subtables[x-1].next) {
+                    if (ddSecDiffCheck(table,x-1,x)) {
+                        merged =1;
+                        ddCreateGroup(table,x-1,x);
+                    }
+                }
+            }
+        }
+
+        if (merged) { /* a group was created */
+            /* move x to bottom of group */
+            while ((unsigned) x < table->subtables[x].next)
+                x = table->subtables[x].next;
+            /* sift */
+            result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag);
+            if (!result) goto ddGroupSiftingOutOfMem;
+#ifdef DD_STATS
+            if (table->keys < previousSize + table->isolated) {
+                (void) fprintf(table->out,"_");
+            } else if (table->keys > previousSize + table->isolated) {
+                (void) fprintf(table->out,"^");
+            } else {
+                (void) fprintf(table->out,"*");
+            }
+            fflush(table->out);
+        } else {
+            if (table->keys < previousSize + table->isolated) {
+                (void) fprintf(table->out,"-");
+            } else if (table->keys > previousSize + table->isolated) {
+                (void) fprintf(table->out,"+");
+            } else {
+                (void) fprintf(table->out,"=");
+            }
+            fflush(table->out);
+#endif
+        }
+
+        /* Mark variables in the group just sifted. */
+        x = table->perm[xindex];
+        if ((unsigned) x != table->subtables[x].next) {
+            xInit = x;
+            do {
+                j = table->invperm[x];
+                sifted[j] = 1;
+                x = table->subtables[x].next;
+            } while (x != xInit);
+
+            /* Dissolve the group if it was created. */
+            if (lazyFlag == 0 && dissolve) {
+                do {
+                    j = table->subtables[x].next;
+                    table->subtables[x].next = x;
+                    x = j;
+                } while (x != xInit);
+            }
+        }
+
+#ifdef DD_DEBUG
+        if (pr > 0) (void) fprintf(table->out,"ddGroupSifting:");
+#endif
+
+      if (lazyFlag) ddSetVarHandled(table, xindex);
+    } /* for */
+
+    ABC_FREE(sifted);
+    ABC_FREE(var);
+    ABC_FREE(entry);
+
+    return(1);
+
+ddGroupSiftingOutOfMem:
+    if (entry != NULL)  ABC_FREE(entry);
+    if (var != NULL)    ABC_FREE(var);
+    if (sifted != NULL) ABC_FREE(sifted);
+
+    return(0);
+
+} /* end of ddGroupSifting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a group encompassing variables from x to y in the
+  DD table.]
+
+  Description [Creates a group encompassing variables from x to y in the
+  DD table. In the current implementation it must be y == x+1.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+ddCreateGroup(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int  gybot;
+
+#ifdef DD_DEBUG
+    assert(y == x+1);
+#endif
+
+    /* Find bottom of second group. */
+    gybot = y;
+    while ((unsigned) gybot < table->subtables[gybot].next)
+        gybot = table->subtables[gybot].next;
+
+    /* Link groups. */
+    table->subtables[x].next = y;
+    table->subtables[gybot].next = x;
+
+    return;
+
+} /* ddCreateGroup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts one variable up and down until it has taken all
+  positions. Checks for aggregation.]
+
+  Description [Sifts one variable up and down until it has taken all
+  positions. Checks for aggregation. There may be at most two sweeps,
+  even if the group grows.  Assumes that x is either an isolated
+  variable, or it is the bottom of a group. All groups may not have
+  been found. The variable being moved is returned to the best position
+  seen during sifting.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddGroupSiftingAux(
+  DdManager * table,
+  int  x,
+  int  xLow,
+  int  xHigh,
+  DD_CHKFP checkFunction,
+  int lazyFlag)
+{
+    Move *move;
+    Move *moves;        /* list of moves */
+    int  initialSize;
+    int  result;
+    int  y;
+    int  topbot;
+
+#ifdef DD_DEBUG
+    if (pr > 0) (void) fprintf(table->out,
+                               "ddGroupSiftingAux from %d to %d\n",xLow,xHigh);
+    assert((unsigned) x >= table->subtables[x].next); /* x is bottom of group */
+#endif
+
+    initialSize = table->keys - table->isolated;
+    moves = NULL;
+
+    originalSize = initialSize;         /* for lazy sifting */
+
+    /* If we have a singleton, we check for aggregation in both
+    ** directions before we sift.
+    */
+    if ((unsigned) x == table->subtables[x].next) {
+        /* Will go down first, unless x == xHigh:
+        ** Look for aggregation above x.
+        */
+        for (y = x; y > xLow; y--) {
+            if (!checkFunction(table,y-1,y))
+                break;
+            topbot = table->subtables[y-1].next; /* find top of y-1's group */
+            table->subtables[y-1].next = y;
+            table->subtables[x].next = topbot; /* x is bottom of group so its */
+                                               /* next is top of y-1's group */
+            y = topbot + 1; /* add 1 for y--; new y is top of group */
+        }
+        /* Will go up first unless x == xlow:
+        ** Look for aggregation below x.
+        */
+        for (y = x; y < xHigh; y++) {
+            if (!checkFunction(table,y,y+1))
+                break;
+            /* find bottom of y+1's group */
+            topbot = y + 1;
+            while ((unsigned) topbot < table->subtables[topbot].next) {
+                topbot = table->subtables[topbot].next;
+            }
+            table->subtables[topbot].next = table->subtables[y].next;
+            table->subtables[y].next = y + 1;
+            y = topbot - 1; /* subtract 1 for y++; new y is bottom of group */
+        }
+    }
+
+    /* Now x may be in the middle of a group.
+    ** Find bottom of x's group.
+    */
+    while ((unsigned) x < table->subtables[x].next)
+        x = table->subtables[x].next;
+
+    if (x == xLow) { /* Sift down */
+#ifdef DD_DEBUG
+        /* x must be a singleton */
+        assert((unsigned) x == table->subtables[x].next);
+#endif
+        if (x == xHigh) return(1);      /* just one variable */
+
+        if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
+            goto ddGroupSiftingAuxOutOfMem;
+        /* at this point x == xHigh, unless early term */
+
+        /* move backward and stop at best position */
+        result = ddGroupSiftingBackward(table,moves,initialSize,
+                                        DD_SIFT_DOWN,lazyFlag);
+#ifdef DD_DEBUG
+        assert(table->keys - table->isolated <= (unsigned) initialSize);
+#endif
+        if (!result) goto ddGroupSiftingAuxOutOfMem;
+
+    } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
+#ifdef DD_DEBUG
+        /* x is bottom of group */
+        assert((unsigned) x >= table->subtables[x].next);
+#endif
+        /* Find top of x's group */
+        x = table->subtables[x].next;
+
+        if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
+            goto ddGroupSiftingAuxOutOfMem;
+        /* at this point x == xLow, unless early term */
+
+        /* move backward and stop at best position */
+        result = ddGroupSiftingBackward(table,moves,initialSize,
+                                        DD_SIFT_UP,lazyFlag);
+#ifdef DD_DEBUG
+        assert(table->keys - table->isolated <= (unsigned) initialSize);
+#endif
+        if (!result) goto ddGroupSiftingAuxOutOfMem;
+
+    } else if (x - xLow > xHigh - x) { /* must go down first: shorter */
+        if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
+            goto ddGroupSiftingAuxOutOfMem;
+        /* at this point x == xHigh, unless early term */
+
+        /* Find top of group */
+        if (moves) {
+            x = moves->y;
+        }
+        while ((unsigned) x < table->subtables[x].next)
+            x = table->subtables[x].next;
+        x = table->subtables[x].next;
+#ifdef DD_DEBUG
+        /* x should be the top of a group */
+        assert((unsigned) x <= table->subtables[x].next);
+#endif
+
+        if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
+            goto ddGroupSiftingAuxOutOfMem;
+
+        /* move backward and stop at best position */
+        result = ddGroupSiftingBackward(table,moves,initialSize,
+                                        DD_SIFT_UP,lazyFlag);
+#ifdef DD_DEBUG
+        assert(table->keys - table->isolated <= (unsigned) initialSize);
+#endif
+        if (!result) goto ddGroupSiftingAuxOutOfMem;
+
+    } else { /* moving up first: shorter */
+        /* Find top of x's group */
+        x = table->subtables[x].next;
+
+        if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
+            goto ddGroupSiftingAuxOutOfMem;
+        /* at this point x == xHigh, unless early term */
+
+        if (moves) {
+            x = moves->x;
+        }
+        while ((unsigned) x < table->subtables[x].next)
+            x = table->subtables[x].next;
+#ifdef DD_DEBUG
+        /* x is bottom of a group */
+        assert((unsigned) x >= table->subtables[x].next);
+#endif
+
+        if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
+            goto ddGroupSiftingAuxOutOfMem;
+
+        /* move backward and stop at best position */
+        result = ddGroupSiftingBackward(table,moves,initialSize,
+                                        DD_SIFT_DOWN,lazyFlag);
+#ifdef DD_DEBUG
+        assert(table->keys - table->isolated <= (unsigned) initialSize);
+#endif
+        if (!result) goto ddGroupSiftingAuxOutOfMem;
+    }
+
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+
+    return(1);
+
+ddGroupSiftingAuxOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+
+    return(0);
+
+} /* end of ddGroupSiftingAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts up a variable until either it reaches position xLow
+  or the size of the DD heap increases too much.]
+
+  Description [Sifts up a variable until either it reaches position
+  xLow or the size of the DD heap increases too much. Assumes that y is
+  the top of a group (or a singleton).  Checks y for aggregation to the
+  adjacent variables. Records all the moves that are appended to the
+  list of moves received as input and returned as a side effect.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddGroupSiftingUp(
+  DdManager * table,
+  int  y,
+  int  xLow,
+  DD_CHKFP checkFunction,
+  Move ** moves)
+{
+    Move *move;
+    int  x;
+    int  size;
+    int  i;
+    int  gxtop,gybot;
+    int  limitSize;
+    int  xindex, yindex;
+    int  zindex;
+    int  z;
+    int  isolated;
+    int  L;     /* lower bound on DD size */
+#ifdef DD_DEBUG
+    int  checkL;
+#endif
+
+    yindex = table->invperm[y];
+
+    /* Initialize the lower bound.
+    ** The part of the DD below the bottom of y's group will not change.
+    ** The part of the DD above y that does not interact with any
+    ** variable of y's group will not change.
+    ** The rest may vanish in the best case, except for
+    ** the nodes at level xLow, which will not vanish, regardless.
+    ** What we use here is not really a lower bound, because we ignore
+    ** the interactions with all variables except y.
+    */
+    limitSize = L = table->keys - table->isolated;
+    gybot = y;
+    while ((unsigned) gybot < table->subtables[gybot].next)
+        gybot = table->subtables[gybot].next;
+    for (z = xLow + 1; z <= gybot; z++) {
+        zindex = table->invperm[z];
+        if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
+            isolated = table->vars[zindex]->ref == 1;
+            L -= table->subtables[z].keys - isolated;
+        }
+    }
+
+    x = cuddNextLow(table,y);
+    while (x >= xLow && L <= limitSize) {
+#ifdef DD_DEBUG
+        gybot = y;
+        while ((unsigned) gybot < table->subtables[gybot].next)
+            gybot = table->subtables[gybot].next;
+        checkL = table->keys - table->isolated;
+        for (z = xLow + 1; z <= gybot; z++) {
+            zindex = table->invperm[z];
+            if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
+                isolated = table->vars[zindex]->ref == 1;
+                checkL -= table->subtables[z].keys - isolated;
+            }
+        }
+        if (pr > 0 && L != checkL) {
+            (void) fprintf(table->out,
+                           "Inaccurate lower bound: L = %d checkL = %d\n",
+                           L, checkL);
+        }
+#endif
+        gxtop = table->subtables[x].next;
+        if (checkFunction(table,x,y)) {
+            /* Group found, attach groups */
+            table->subtables[x].next = y;
+            i = table->subtables[y].next;
+            while (table->subtables[i].next != (unsigned) y)
+                i = table->subtables[i].next;
+            table->subtables[i].next = gxtop;
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddGroupSiftingUpOutOfMem;
+            move->x = x;
+            move->y = y;
+            move->flags = MTR_NEWNODE;
+            move->size = table->keys - table->isolated;
+            move->next = *moves;
+            *moves = move;
+        } else if (table->subtables[x].next == (unsigned) x &&
+                   table->subtables[y].next == (unsigned) y) {
+            /* x and y are self groups */
+            xindex = table->invperm[x];
+            size = cuddSwapInPlace(table,x,y);
+#ifdef DD_DEBUG
+            assert(table->subtables[x].next == (unsigned) x);
+            assert(table->subtables[y].next == (unsigned) y);
+#endif
+            if (size == 0) goto ddGroupSiftingUpOutOfMem;
+            /* Update the lower bound. */
+            if (cuddTestInteract(table,xindex,yindex)) {
+                isolated = table->vars[xindex]->ref == 1;
+                L += table->subtables[y].keys - isolated;
+            }
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddGroupSiftingUpOutOfMem;
+            move->x = x;
+            move->y = y;
+            move->flags = MTR_DEFAULT;
+            move->size = size;
+            move->next = *moves;
+            *moves = move;
+
+#ifdef DD_DEBUG
+            if (pr > 0) (void) fprintf(table->out,
+                                       "ddGroupSiftingUp (2 single groups):\n");
+#endif
+            if ((double) size > (double) limitSize * table->maxGrowth)
+                return(1);
+            if (size < limitSize) limitSize = size;
+        } else { /* Group move */
+            size = ddGroupMove(table,x,y,moves);
+            if (size == 0) goto ddGroupSiftingUpOutOfMem;
+            /* Update the lower bound. */
+            z = (*moves)->y;
+            do {
+                zindex = table->invperm[z];
+                if (cuddTestInteract(table,zindex,yindex)) {
+                    isolated = table->vars[zindex]->ref == 1;
+                    L += table->subtables[z].keys - isolated;
+                }
+                z = table->subtables[z].next;
+            } while (z != (int) (*moves)->y);
+            if ((double) size > (double) limitSize * table->maxGrowth)
+                return(1);
+            if (size < limitSize) limitSize = size;
+        }
+        y = gxtop;
+        x = cuddNextLow(table,y);
+    }
+
+    return(1);
+
+ddGroupSiftingUpOutOfMem:
+    while (*moves != NULL) {
+        move = (*moves)->next;
+        cuddDeallocMove(table, *moves);
+        *moves = move;
+    }
+    return(0);
+
+} /* end of ddGroupSiftingUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts down a variable until it reaches position xHigh.]
+
+  Description [Sifts down a variable until it reaches position xHigh.
+  Assumes that x is the bottom of a group (or a singleton).  Records
+  all the moves.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddGroupSiftingDown(
+  DdManager * table,
+  int  x,
+  int  xHigh,
+  DD_CHKFP checkFunction,
+  Move ** moves)
+{
+    Move *move;
+    int  y;
+    int  size;
+    int  limitSize;
+    int  gxtop,gybot;
+    int  R;     /* upper bound on node decrease */
+    int  xindex, yindex;
+    int  isolated, allVars;
+    int  z;
+    int  zindex;
+#ifdef DD_DEBUG
+    int  checkR;
+#endif
+
+    /* If the group consists of simple variables, there is no point in
+    ** sifting it down. This check is redundant if the projection functions
+    ** do not have external references, because the computation of the
+    ** lower bound takes care of the problem.  It is necessary otherwise to
+    ** prevent the sifting down of simple variables. */
+    y = x;
+    allVars = 1;
+    do {
+        if (table->subtables[y].keys != 1) {
+            allVars = 0;
+            break;
+        }
+        y = table->subtables[y].next;
+    } while (table->subtables[y].next != (unsigned) x);
+    if (allVars)
+        return(1);
+
+    /* Initialize R. */
+    xindex = table->invperm[x];
+    gxtop = table->subtables[x].next;
+    limitSize = size = table->keys - table->isolated;
+    R = 0;
+    for (z = xHigh; z > gxtop; z--) {
+        zindex = table->invperm[z];
+        if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
+            isolated = table->vars[zindex]->ref == 1;
+            R += table->subtables[z].keys - isolated;
+        }
+    }
+
+    y = cuddNextHigh(table,x);
+    while (y <= xHigh && size - R < limitSize) {
+#ifdef DD_DEBUG
+        gxtop = table->subtables[x].next;
+        checkR = 0;
+        for (z = xHigh; z > gxtop; z--) {
+            zindex = table->invperm[z];
+            if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
+                isolated = table->vars[zindex]->ref == 1;
+                checkR += table->subtables[z].keys - isolated;
+            }
+        }
+        assert(R >= checkR);
+#endif
+        /* Find bottom of y group. */
+        gybot = table->subtables[y].next;
+        while (table->subtables[gybot].next != (unsigned) y)
+            gybot = table->subtables[gybot].next;
+
+        if (checkFunction(table,x,y)) {
+            /* Group found: attach groups and record move. */
+            gxtop = table->subtables[x].next;
+            table->subtables[x].next = y;
+            table->subtables[gybot].next = gxtop;
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddGroupSiftingDownOutOfMem;
+            move->x = x;
+            move->y = y;
+            move->flags = MTR_NEWNODE;
+            move->size = table->keys - table->isolated;
+            move->next = *moves;
+            *moves = move;
+        } else if (table->subtables[x].next == (unsigned) x &&
+                   table->subtables[y].next == (unsigned) y) {
+            /* x and y are self groups */
+            /* Update upper bound on node decrease. */
+            yindex = table->invperm[y];
+            if (cuddTestInteract(table,xindex,yindex)) {
+                isolated = table->vars[yindex]->ref == 1;
+                R -= table->subtables[y].keys - isolated;
+            }
+            size = cuddSwapInPlace(table,x,y);
+#ifdef DD_DEBUG
+            assert(table->subtables[x].next == (unsigned) x);
+            assert(table->subtables[y].next == (unsigned) y);
+#endif
+            if (size == 0) goto ddGroupSiftingDownOutOfMem;
+
+            /* Record move. */
+            move = (Move *) cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddGroupSiftingDownOutOfMem;
+            move->x = x;
+            move->y = y;
+            move->flags = MTR_DEFAULT;
+            move->size = size;
+            move->next = *moves;
+            *moves = move;
+
+#ifdef DD_DEBUG
+            if (pr > 0) (void) fprintf(table->out,
+                                       "ddGroupSiftingDown (2 single groups):\n");
+#endif
+            if ((double) size > (double) limitSize * table->maxGrowth)
+                return(1);
+            if (size < limitSize) limitSize = size;
+
+            x = y;
+            y = cuddNextHigh(table,x);
+        } else { /* Group move */
+            /* Update upper bound on node decrease: first phase. */
+            gxtop = table->subtables[x].next;
+            z = gxtop + 1;
+            do {
+                zindex = table->invperm[z];
+                if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
+                    isolated = table->vars[zindex]->ref == 1;
+                    R -= table->subtables[z].keys - isolated;
+                }
+                z++;
+            } while (z <= gybot);
+            size = ddGroupMove(table,x,y,moves);
+            if (size == 0) goto ddGroupSiftingDownOutOfMem;
+            if ((double) size > (double) limitSize * table->maxGrowth)
+                return(1);
+            if (size < limitSize) limitSize = size;
+
+            /* Update upper bound on node decrease: second phase. */
+            gxtop = table->subtables[gybot].next;
+            for (z = gxtop + 1; z <= gybot; z++) {
+                zindex = table->invperm[z];
+                if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
+                    isolated = table->vars[zindex]->ref == 1;
+                    R += table->subtables[z].keys - isolated;
+                }
+            }
+        }
+        x = gybot;
+        y = cuddNextHigh(table,x);
+    }
+
+    return(1);
+
+ddGroupSiftingDownOutOfMem:
+    while (*moves != NULL) {
+        move = (*moves)->next;
+        cuddDeallocMove(table, *moves);
+        *moves = move;
+    }
+
+    return(0);
+
+} /* end of ddGroupSiftingDown */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Swaps two groups and records the move.]
+
+  Description [Swaps two groups and records the move. Returns the
+  number of keys in the DD table in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddGroupMove(
+  DdManager * table,
+  int  x,
+  int  y,
+  Move ** moves)
+{
+    Move *move;
+    int  size;
+    int  i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
+    int  swapx = -1,swapy = -1;
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    int  initialSize,bestSize;
+#endif
+
+#ifdef DD_DEBUG
+    /* We assume that x < y */
+    assert(x < y);
+#endif
+    /* Find top, bottom, and size for the two groups. */
+    xbot = x;
+    xtop = table->subtables[x].next;
+    xsize = xbot - xtop + 1;
+    ybot = y;
+    while ((unsigned) ybot < table->subtables[ybot].next)
+        ybot = table->subtables[ybot].next;
+    ytop = y;
+    ysize = ybot - ytop + 1;
+
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    initialSize = bestSize = table->keys - table->isolated;
+#endif
+    /* Sift the variables of the second group up through the first group */
+    for (i = 1; i <= ysize; i++) {
+        for (j = 1; j <= xsize; j++) {
+            size = cuddSwapInPlace(table,x,y);
+            if (size == 0) goto ddGroupMoveOutOfMem;
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+            if (size < bestSize)
+                bestSize = size;
+#endif
+            swapx = x; swapy = y;
+            y = x;
+            x = cuddNextLow(table,y);
+        }
+        y = ytop + i;
+        x = cuddNextLow(table,y);
+    }
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    if ((bestSize < initialSize) && (bestSize < size))
+        (void) fprintf(table->out,"Missed local minimum: initialSize:%d  bestSize:%d  finalSize:%d\n",initialSize,bestSize,size);
+#endif
+
+    /* fix groups */
+    y = xtop; /* ytop is now where xtop used to be */
+    for (i = 0; i < ysize - 1; i++) {
+        table->subtables[y].next = cuddNextHigh(table,y);
+        y = cuddNextHigh(table,y);
+    }
+    table->subtables[y].next = xtop; /* y is bottom of its group, join */
+                                    /* it to top of its group */
+    x = cuddNextHigh(table,y);
+    newxtop = x;
+    for (i = 0; i < xsize - 1; i++) {
+        table->subtables[x].next = cuddNextHigh(table,x);
+        x = cuddNextHigh(table,x);
+    }
+    table->subtables[x].next = newxtop; /* x is bottom of its group, join */
+                                    /* it to top of its group */
+#ifdef DD_DEBUG
+    if (pr > 0) (void) fprintf(table->out,"ddGroupMove:\n");
+#endif
+
+    /* Store group move */
+    move = (Move *) cuddDynamicAllocNode(table);
+    if (move == NULL) goto ddGroupMoveOutOfMem;
+    move->x = swapx;
+    move->y = swapy;
+    move->flags = MTR_DEFAULT;
+    move->size = table->keys - table->isolated;
+    move->next = *moves;
+    *moves = move;
+
+    return(table->keys - table->isolated);
+
+ddGroupMoveOutOfMem:
+    while (*moves != NULL) {
+        move = (*moves)->next;
+        cuddDeallocMove(table, *moves);
+        *moves = move;
+    }
+    return(0);
+
+} /* end of ddGroupMove */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Undoes the swap two groups.]
+
+  Description [Undoes the swap two groups.  Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddGroupMoveBackward(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int size;
+    int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
+
+
+#ifdef DD_DEBUG
+    /* We assume that x < y */
+    assert(x < y);
+#endif
+
+    /* Find top, bottom, and size for the two groups. */
+    xbot = x;
+    xtop = table->subtables[x].next;
+    xsize = xbot - xtop + 1;
+    ybot = y;
+    while ((unsigned) ybot < table->subtables[ybot].next)
+        ybot = table->subtables[ybot].next;
+    ytop = y;
+    ysize = ybot - ytop + 1;
+
+    /* Sift the variables of the second group up through the first group */
+    for (i = 1; i <= ysize; i++) {
+        for (j = 1; j <= xsize; j++) {
+            size = cuddSwapInPlace(table,x,y);
+            if (size == 0)
+                return(0);
+            y = x;
+            x = cuddNextLow(table,y);
+        }
+        y = ytop + i;
+        x = cuddNextLow(table,y);
+    }
+
+    /* fix groups */
+    y = xtop;
+    for (i = 0; i < ysize - 1; i++) {
+        table->subtables[y].next = cuddNextHigh(table,y);
+        y = cuddNextHigh(table,y);
+    }
+    table->subtables[y].next = xtop; /* y is bottom of its group, join */
+                                    /* to its top */
+    x = cuddNextHigh(table,y);
+    newxtop = x;
+    for (i = 0; i < xsize - 1; i++) {
+        table->subtables[x].next = cuddNextHigh(table,x);
+        x = cuddNextHigh(table,x);
+    }
+    table->subtables[x].next = newxtop; /* x is bottom of its group, join */
+                                    /* to its top */
+#ifdef DD_DEBUG
+    if (pr > 0) (void) fprintf(table->out,"ddGroupMoveBackward:\n");
+#endif
+
+    return(1);
+
+} /* end of ddGroupMoveBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Determines the best position for a variables and returns
+  it there.]
+
+  Description [Determines the best position for a variables and returns
+  it there.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddGroupSiftingBackward(
+  DdManager * table,
+  Move * moves,
+  int  size,
+  int  upFlag,
+  int  lazyFlag)
+{
+    Move *move;
+    int  res;
+    Move *end_move = NULL;
+    int diff, tmp_diff;
+    int index;
+    unsigned int pairlev;
+
+    if (lazyFlag) {
+        end_move = NULL;
+
+        /* Find the minimum size, and the earliest position at which it
+        ** was achieved. */
+        for (move = moves; move != NULL; move = move->next) {
+            if (move->size < size) {
+                size = move->size;
+                end_move = move;
+            } else if (move->size == size) {
+                if (end_move == NULL) end_move = move;
+            }
+        }
+
+        /* Find among the moves that give minimum size the one that
+        ** minimizes the distance from the corresponding variable. */
+        if (moves != NULL) {
+            diff = Cudd_ReadSize(table) + 1;
+            index = (upFlag == 1) ?
+                    table->invperm[moves->x] : table->invperm[moves->y];
+            pairlev =
+                (unsigned) table->perm[Cudd_bddReadPairIndex(table, index)];
+
+            for (move = moves; move != NULL; move = move->next) {
+                if (move->size == size) {
+                    if (upFlag == 1) {
+                        tmp_diff = (move->x > pairlev) ?
+                                    move->x - pairlev : pairlev - move->x;
+                    } else {
+                        tmp_diff = (move->y > pairlev) ?
+                                    move->y - pairlev : pairlev - move->y;
+                    }
+                    if (tmp_diff < diff) {
+                        diff = tmp_diff;
+                        end_move = move;
+                    }
+                }
+            }
+        }
+    } else {
+        /* Find the minimum size. */
+        for (move = moves; move != NULL; move = move->next) {
+            if (move->size < size) {
+                size = move->size;
+            }
+        }
+    }
+
+    /* In case of lazy sifting, end_move identifies the position at
+    ** which we want to stop.  Otherwise, we stop as soon as we meet
+    ** the minimum size. */
+    for (move = moves; move != NULL; move = move->next) {
+        if (lazyFlag) {
+            if (move == end_move) return(1);
+        } else {
+            if (move->size == size) return(1);
+        }
+        if ((table->subtables[move->x].next == move->x) &&
+        (table->subtables[move->y].next == move->y)) {
+            res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
+            if (!res) return(0);
+#ifdef DD_DEBUG
+            if (pr > 0) (void) fprintf(table->out,"ddGroupSiftingBackward:\n");
+            assert(table->subtables[move->x].next == move->x);
+            assert(table->subtables[move->y].next == move->y);
+#endif
+        } else { /* Group move necessary */
+            if (move->flags == MTR_NEWNODE) {
+                ddDissolveGroup(table,(int)move->x,(int)move->y);
+            } else {
+                res = ddGroupMoveBackward(table,(int)move->x,(int)move->y);
+                if (!res) return(0);
+            }
+        }
+
+    }
+
+    return(1);
+
+} /* end of ddGroupSiftingBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Merges groups in the DD table.]
+
+  Description [Creates a single group from low to high and adjusts the
+  index field of the tree node.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+ddMergeGroups(
+  DdManager * table,
+  MtrNode * treenode,
+  int  low,
+  int  high)
+{
+    int i;
+    MtrNode *auxnode;
+    int saveindex;
+    int newindex;
+
+    /* Merge all variables from low to high in one group, unless
+    ** this is the topmost group. In such a case we do not merge lest
+    ** we lose the symmetry information. */
+    if (treenode != table->tree) {
+        for (i = low; i < high; i++)
+            table->subtables[i].next = i+1;
+        table->subtables[high].next = low;
+    }
+
+    /* Adjust the index fields of the tree nodes. If a node is the
+    ** first child of its parent, then the parent may also need adjustment. */
+    saveindex = treenode->index;
+    newindex = table->invperm[low];
+    auxnode = treenode;
+    do {
+        auxnode->index = newindex;
+        if (auxnode->parent == NULL ||
+                (int) auxnode->parent->index != saveindex)
+            break;
+        auxnode = auxnode->parent;
+    } while (1);
+    return;
+
+} /* end of ddMergeGroups */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Dissolves a group in the DD table.]
+
+  Description [x and y are variables in a group to be cut in two. The cut
+  is to pass between x and y.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+ddDissolveGroup(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int topx;
+    int boty;
+
+    /* find top and bottom of the two groups */
+    boty = y;
+    while ((unsigned) boty < table->subtables[boty].next)
+        boty = table->subtables[boty].next;
+
+    topx = table->subtables[boty].next;
+
+    table->subtables[boty].next = y;
+    table->subtables[x].next = topx;
+
+    return;
+
+} /* end of ddDissolveGroup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Pretends to check two variables for aggregation.]
+
+  Description [Pretends to check two variables for aggregation. Always
+  returns 0.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddNoCheck(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    return(0);
+
+} /* end of ddNoCheck */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks two variables for aggregation.]
+
+  Description [Checks two variables for aggregation. The check is based
+  on the second difference of the number of nodes as a function of the
+  layer. If the second difference is lower than a given threshold
+  (typically negative) then the two variables should be aggregated.
+  Returns 1 if the two variables pass the test; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSecDiffCheck(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    double Nx,Nx_1;
+    double Sx;
+    double threshold;
+    int    xindex,yindex;
+
+    if (x==0) return(0);
+
+#ifdef DD_STATS
+    secdiffcalls++;
+#endif
+    Nx = (double) table->subtables[x].keys;
+    Nx_1 = (double) table->subtables[x-1].keys;
+    Sx = (table->subtables[y].keys/Nx) - (Nx/Nx_1);
+
+    threshold = table->recomb / 100.0;
+    if (Sx < threshold) {
+        xindex = table->invperm[x];
+        yindex = table->invperm[y];
+        if (cuddTestInteract(table,xindex,yindex)) {
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+            (void) fprintf(table->out,
+                           "Second difference for %d = %g Pos(%d)\n",
+                           table->invperm[x],Sx,x);
+#endif
+#ifdef DD_STATS
+            secdiff++;
+#endif
+            return(1);
+        } else {
+#ifdef DD_STATS
+            secdiffmisfire++;
+#endif
+            return(0);
+        }
+
+    }
+    return(0);
+
+} /* end of ddSecDiffCheck */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks for extended symmetry of x and y.]
+
+  Description [Checks for extended symmetry of x and y. Returns 1 in
+  case of extended symmetry; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddExtSymmCheck(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10;
+    DdNode *one;
+    unsigned comple;    /* f0 is complemented */
+    int notproj;        /* f is not a projection function */
+    int arccount;       /* number of arcs from layer x to layer y */
+    int TotalRefCount;  /* total reference count of layer y minus 1 */
+    int counter;        /* number of nodes of layer x that are allowed */
+                        /* to violate extended symmetry conditions */
+    int arccounter;     /* number of arcs into layer y that are allowed */
+                        /* to come from layers other than x */
+    int i;
+    int xindex;
+    int yindex;
+    int res;
+    int slots;
+    DdNodePtr *list;
+    DdNode *sentinel = &(table->sentinel);
+
+    xindex = table->invperm[x];
+    yindex = table->invperm[y];
+
+    /* If the two variables do not interact, we do not want to merge them. */
+    if (!cuddTestInteract(table,xindex,yindex))
+        return(0);
+
+#ifdef DD_DEBUG
+    /* Checks that x and y do not contain just the projection functions.
+    ** With the test on interaction, these test become redundant,
+    ** because an isolated projection function does not interact with
+    ** any other variable.
+    */
+    if (table->subtables[x].keys == 1) {
+        assert(table->vars[xindex]->ref != 1);
+    }
+    if (table->subtables[y].keys == 1) {
+        assert(table->vars[yindex]->ref != 1);
+    }
+#endif
+
+#ifdef DD_STATS
+    extsymmcalls++;
+#endif
+
+    arccount = 0;
+    counter = (int) (table->subtables[x].keys *
+              (table->symmviolation/100.0) + 0.5);
+    one = DD_ONE(table);
+
+    slots = table->subtables[x].slots;
+    list = table->subtables[x].nodelist;
+    for (i = 0; i < slots; i++) {
+        f = list[i];
+        while (f != sentinel) {
+            /* Find f1, f0, f11, f10, f01, f00. */
+            f1 = cuddT(f);
+            f0 = Cudd_Regular(cuddE(f));
+            comple = Cudd_IsComplement(cuddE(f));
+            notproj = f1 != one || f0 != one || f->ref != (DdHalfWord) 1;
+            if (f1->index == (unsigned) yindex) {
+                arccount++;
+                f11 = cuddT(f1); f10 = cuddE(f1);
+            } else {
+                if ((int) f0->index != yindex) {
+                    /* If f is an isolated projection function it is
+                    ** allowed to bypass layer y.
+                    */
+                    if (notproj) {
+                        if (counter == 0)
+                            return(0);
+                        counter--; /* f bypasses layer y */
+                    }
+                }
+                f11 = f10 = f1;
+            }
+            if ((int) f0->index == yindex) {
+                arccount++;
+                f01 = cuddT(f0); f00 = cuddE(f0);
+            } else {
+                f01 = f00 = f0;
+            }
+            if (comple) {
+                f01 = Cudd_Not(f01);
+                f00 = Cudd_Not(f00);
+            }
+
+            /* Unless we are looking at a projection function
+            ** without external references except the one from the
+            ** table, we insist that f01 == f10 or f11 == f00
+            */
+            if (notproj) {
+                if (f01 != f10 && f11 != f00) {
+                    if (counter == 0)
+                        return(0);
+                    counter--;
+                }
+            }
+
+            f = f->next;
+        } /* while */
+    } /* for */
+
+    /* Calculate the total reference counts of y */
+    TotalRefCount = -1; /* -1 for projection function */
+    slots = table->subtables[y].slots;
+    list = table->subtables[y].nodelist;
+    for (i = 0; i < slots; i++) {
+        f = list[i];
+        while (f != sentinel) {
+            TotalRefCount += f->ref;
+            f = f->next;
+        }
+    }
+
+    arccounter = (int) (table->subtables[y].keys *
+                 (table->arcviolation/100.0) + 0.5);
+    res = arccount >= TotalRefCount - arccounter;
+
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    if (res) {
+        (void) fprintf(table->out,
+                       "Found extended symmetry! x = %d\ty = %d\tPos(%d,%d)\n",
+                       xindex,yindex,x,y);
+    }
+#endif
+
+#ifdef DD_STATS
+    if (res)
+        extsymm++;
+#endif
+    return(res);
+
+} /* end ddExtSymmCheck */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks for grouping of x and y.]
+
+  Description [Checks for grouping of x and y. Returns 1 in
+  case of grouping; 0 otherwise. This function is used for lazy sifting.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddVarGroupCheck(
+  DdManager * table,
+  int x,
+  int y)
+{
+    int xindex = table->invperm[x];
+    int yindex = table->invperm[y];
+
+    if (Cudd_bddIsVarToBeUngrouped(table, xindex)) return(0);
+
+    if (Cudd_bddReadPairIndex(table, xindex) == yindex) {
+        if (ddIsVarHandled(table, xindex) ||
+            ddIsVarHandled(table, yindex)) {
+            if (Cudd_bddIsVarToBeGrouped(table, xindex) ||
+                Cudd_bddIsVarToBeGrouped(table, yindex) ) {
+                if (table->keys - table->isolated <= originalSize) {
+                    return(1);
+                }
+            }
+        }
+    }
+
+    return(0);
+
+} /* end of ddVarGroupCheck */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable to already handled.]
+
+  Description [Sets a variable to already handled. This function is used
+  for lazy sifting.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddSetVarHandled(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(0);
+    dd->subtables[dd->perm[index]].varHandled = 1;
+    return(1);
+
+} /* end of ddSetVarHandled */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resets a variable to be processed.]
+
+  Description [Resets a variable to be processed. This function is used
+  for lazy sifting.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddResetVarHandled(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(0);
+    dd->subtables[dd->perm[index]].varHandled = 0;
+    return(1);
+
+} /* end of ddResetVarHandled */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variables is already handled.]
+
+  Description [Checks whether a variables is already handled. This
+  function is used for lazy sifting.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddIsVarHandled(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(-1);
+    return dd->subtables[dd->perm[index]].varHandled;
+
+} /* end of ddIsVarHandled */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddHarwell.c b/abc-build/src/bdd/cudd/cuddHarwell.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddHarwell.c
@@ -0,0 +1,576 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddHarwell.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Function to read a matrix in Harwell format.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_addHarwell()
+                </ul>
+        ]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddHarwell.c,v 1.9 2004/08/13 18:04:49 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Reads in a matrix in the format of the Harwell-Boeing
+  benchmark suite.]
+
+  Description [Reads in a matrix in the format of the Harwell-Boeing
+  benchmark suite. The variables are ordered as follows:
+  <blockquote>
+  x\[0\] y\[0\] x\[1\] y\[1\] ...
+  </blockquote>
+  0 is the most significant bit.  On input, nx and ny hold the numbers
+  of row and column variables already in existence. On output, they
+  hold the numbers of row and column variables actually used by the
+  matrix.  m and n are set to the numbers of rows and columns of the
+  matrix.  Their values on input are immaterial.  Returns 1 on
+  success; 0 otherwise. The ADD for the sparse matrix is returned in
+  E, and its reference count is > 0.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addRead Cudd_bddRead]
+
+******************************************************************************/
+int
+Cudd_addHarwell(
+  FILE * fp /* pointer to the input file */,
+  DdManager * dd /* DD manager */,
+  DdNode ** E /* characteristic function of the graph */,
+  DdNode *** x /* array of row variables */,
+  DdNode *** y /* array of column variables */,
+  DdNode *** xn /* array of complemented row variables */,
+  DdNode *** yn_ /* array of complemented column variables */,
+  int * nx /* number or row variables */,
+  int * ny /* number or column variables */,
+  int * m /* number of rows */,
+  int * n /* number of columns */,
+  int  bx /* first index of row variables */,
+  int  sx /* step of row variables */,
+  int  by /* first index of column variables */,
+  int  sy /* step of column variables */,
+  int  pr /* verbosity level */)
+{
+    DdNode *one, *zero;
+    DdNode *w;
+    DdNode *cubex, *cubey, *minterm1;
+    int u, v, err, i, j, nv;
+    double val;
+    DdNode **lx = NULL, **ly = NULL, **lxn = NULL, **lyn = NULL;    /* local copies of x, y, xn, yn_ */
+    int lnx, lny;                       /* local copies of nx and ny */
+    char title[73], key[9], mxtype[4], rhstyp[4];
+    int totcrd, ptrcrd, indcrd, valcrd, rhscrd,
+        nrow, ncol, nnzero, neltvl,
+        nrhs, nrhsix;
+    int *colptr, *rowind;
+#if 0
+    int nguess, nexact;
+    int *rhsptr, *rhsind;
+#endif
+
+    if (*nx < 0 || *ny < 0) return(0);
+
+    one = DD_ONE(dd);
+    zero = DD_ZERO(dd);
+
+    /* Read the header */
+    err = fscanf(fp, "%72c %8c", title, key);
+    if (err == EOF) {
+        return(0);
+    } else if (err != 2) {
+        return(0);
+    }
+    title[72] = (char) 0;
+    key[8] = (char) 0;
+
+    err = fscanf(fp, "%d %d %d %d %d", &totcrd, &ptrcrd, &indcrd,
+    &valcrd, &rhscrd);
+    if (err == EOF) {
+        return(0);
+    } else if (err != 5) {
+        return(0);
+    }
+
+    err = fscanf(fp, "%3s %d %d %d %d", mxtype, &nrow, &ncol,
+    &nnzero, &neltvl);
+    if (err == EOF) {
+        return(0);
+    } else if (err != 5) {
+        return(0);
+    }
+
+    /* Skip FORTRAN formats */
+    if (rhscrd == 0) {
+        err = fscanf(fp, "%*s %*s %*s \n");
+    } else {
+        err = fscanf(fp, "%*s %*s %*s %*s \n");
+    }
+    if (err == EOF) {
+        return(0);
+    } else if (err != 0) {
+        return(0);
+    }
+
+    /* Print out some stuff if requested to be verbose */
+    if (pr>0) {
+        (void) fprintf(dd->out,"%s: type %s, %d rows, %d columns, %d entries\n", key,
+        mxtype, nrow, ncol, nnzero);
+        if (pr>1) (void) fprintf(dd->out,"%s\n", title);
+    }
+
+    /* Check matrix type */
+    if (mxtype[0] != 'R' || mxtype[1] != 'U' || mxtype[2] != 'A') {
+        (void) fprintf(dd->err,"%s: Illegal matrix type: %s\n",
+                       key, mxtype);
+        return(0);
+    }
+    if (neltvl != 0) return(0);
+
+    /* Read optional 5-th line */
+    if (rhscrd != 0) {
+        err = fscanf(fp, "%3c %d %d", rhstyp, &nrhs, &nrhsix);
+        if (err == EOF) {
+            return(0);
+        } else if (err != 3) {
+            return(0);
+        }
+        rhstyp[3] = (char) 0;
+        if (rhstyp[0] != 'F') {
+            (void) fprintf(dd->err,
+            "%s: Sparse right-hand side not yet supported\n", key);
+            return(0);
+        }
+        if (pr>0) (void) fprintf(dd->out,"%d right-hand side(s)\n", nrhs);
+    } else {
+        nrhs = 0;
+    }
+
+    /* Compute the number of variables */
+
+    /* row and column numbers start from 0 */
+    u = nrow - 1;
+    for (i=0; u > 0; i++) {
+        u >>= 1;
+    }
+    lnx = i;
+    if (nrhs == 0) {
+        v = ncol - 1;
+    } else {
+        v = 2* (ddMax(ncol, nrhs) - 1);
+    }
+    for (i=0; v > 0; i++) {
+        v >>= 1;
+    }
+    lny = i;
+
+    /* Allocate or reallocate arrays for variables as needed */
+    if (*nx == 0) {
+        if (lnx > 0) {
+            *x = lx = ABC_ALLOC(DdNode *,lnx);
+            if (lx == NULL) {
+                dd->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            *xn = lxn =  ABC_ALLOC(DdNode *,lnx);
+            if (lxn == NULL) {
+                dd->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+        } else {
+            *x = *xn = NULL;
+        }
+    } else if (lnx > *nx) {
+        *x = lx = ABC_REALLOC(DdNode *, *x, lnx);
+        if (lx == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        *xn = lxn =  ABC_REALLOC(DdNode *, *xn, lnx);
+        if (lxn == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+    } else {
+        lx = *x;
+        lxn = *xn;
+    }
+    if (*ny == 0) {
+        if (lny >0) {
+            *y = ly = ABC_ALLOC(DdNode *,lny);
+            if (ly == NULL) {
+                dd->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            *yn_ = lyn = ABC_ALLOC(DdNode *,lny);
+            if (lyn == NULL) {
+                dd->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+        } else {
+            *y = *yn_ = NULL;
+        }
+    } else if (lny > *ny) {
+        *y = ly = ABC_REALLOC(DdNode *, *y, lny);
+        if (ly == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        *yn_ = lyn = ABC_REALLOC(DdNode *, *yn_, lny);
+        if (lyn == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+    } else {
+        ly = *y;
+        lyn = *yn_;
+    }
+
+    /* Create new variables as needed */
+    for (i= *nx,nv=bx+(*nx)*sx; i < lnx; i++,nv+=sx) {
+        do {
+            dd->reordered = 0;
+            lx[i] = cuddUniqueInter(dd, nv, one, zero);
+        } while (dd->reordered == 1);
+        if (lx[i] == NULL) return(0);
+        cuddRef(lx[i]);
+        do {
+            dd->reordered = 0;
+            lxn[i] = cuddUniqueInter(dd, nv, zero, one);
+        } while (dd->reordered == 1);
+        if (lxn[i] == NULL) return(0);
+        cuddRef(lxn[i]);
+    }
+    for (i= *ny,nv=by+(*ny)*sy; i < lny; i++,nv+=sy) {
+        do {
+            dd->reordered = 0;
+            ly[i] = cuddUniqueInter(dd, nv, one, zero);
+        } while (dd->reordered == 1);
+        if (ly[i] == NULL) return(0);
+        cuddRef(ly[i]);
+        do {
+            dd->reordered = 0;
+            lyn[i] = cuddUniqueInter(dd, nv, zero, one);
+        } while (dd->reordered == 1);
+        if (lyn[i] == NULL) return(0);
+        cuddRef(lyn[i]);
+    }
+
+    /* Update matrix parameters */
+    *nx = lnx;
+    *ny = lny;
+    *m = nrow;
+    if (nrhs == 0) {
+        *n = ncol;
+    } else {
+        *n = (1 << (lny - 1)) + nrhs;
+    }
+    
+    /* Read structure data */
+    colptr = ABC_ALLOC(int, ncol+1);
+    if (colptr == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    rowind = ABC_ALLOC(int, nnzero);
+    if (rowind == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+
+    for (i=0; i<ncol+1; i++) {
+        err = fscanf(fp, " %d ", &u);
+        if (err == EOF){ 
+            ABC_FREE(colptr);
+            ABC_FREE(rowind);
+            return(0);
+        } else if (err != 1) {
+            ABC_FREE(colptr);
+            ABC_FREE(rowind);
+            return(0);
+        }
+        colptr[i] = u - 1;
+    }
+    if (colptr[0] != 0) {
+        (void) fprintf(dd->err,"%s: Unexpected colptr[0] (%d)\n",
+                       key,colptr[0]);
+        ABC_FREE(colptr);
+        ABC_FREE(rowind);
+        return(0);
+    }
+    for (i=0; i<nnzero; i++) {
+        err = fscanf(fp, " %d ", &u);
+        if (err == EOF){ 
+            ABC_FREE(colptr);
+            ABC_FREE(rowind);
+            return(0);
+        } else if (err != 1) {
+            ABC_FREE(colptr);
+            ABC_FREE(rowind);
+            return(0);
+        }
+        rowind[i] = u - 1;
+    }
+
+    *E = zero; cuddRef(*E);
+
+    for (j=0; j<ncol; j++) {
+        v = j;
+        cubey = one; cuddRef(cubey);
+        for (nv = lny - 1; nv>=0; nv--) {
+            if (v & 1) {
+                w = Cudd_addApply(dd, Cudd_addTimes, cubey, ly[nv]);
+            } else {
+                w = Cudd_addApply(dd, Cudd_addTimes, cubey, lyn[nv]);
+            }
+            if (w == NULL) {
+                Cudd_RecursiveDeref(dd, cubey);
+                ABC_FREE(colptr);
+                ABC_FREE(rowind);
+                return(0);
+            }
+            cuddRef(w);
+            Cudd_RecursiveDeref(dd, cubey);
+            cubey = w;
+            v >>= 1;
+        }
+        for (i=colptr[j]; i<colptr[j+1]; i++) {
+            u = rowind[i];
+            err = fscanf(fp, " %lf ", &val);
+            if (err == EOF || err != 1){ 
+                Cudd_RecursiveDeref(dd, cubey);
+                ABC_FREE(colptr);
+                ABC_FREE(rowind);
+                return(0);
+            }
+            /* Create new Constant node if necessary */
+            cubex = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) val);
+            if (cubex == NULL) {
+                Cudd_RecursiveDeref(dd, cubey);
+                ABC_FREE(colptr);
+                ABC_FREE(rowind);
+                return(0);
+            }
+            cuddRef(cubex);
+
+            for (nv = lnx - 1; nv>=0; nv--) {
+                if (u & 1) {
+                    w = Cudd_addApply(dd, Cudd_addTimes, cubex, lx[nv]);
+                } else { 
+                    w = Cudd_addApply(dd, Cudd_addTimes, cubex, lxn[nv]);
+                }
+                if (w == NULL) {
+                    Cudd_RecursiveDeref(dd, cubey);
+                    Cudd_RecursiveDeref(dd, cubex);
+                    ABC_FREE(colptr);
+                    ABC_FREE(rowind);
+                    return(0);
+                }
+                cuddRef(w);
+                Cudd_RecursiveDeref(dd, cubex);
+                cubex = w;
+                u >>= 1;
+            }
+            minterm1 = Cudd_addApply(dd, Cudd_addTimes, cubey, cubex);
+            if (minterm1 == NULL) {
+                Cudd_RecursiveDeref(dd, cubey);
+                Cudd_RecursiveDeref(dd, cubex);
+                ABC_FREE(colptr);
+                ABC_FREE(rowind);
+                return(0);
+            }
+            cuddRef(minterm1);
+            Cudd_RecursiveDeref(dd, cubex);
+            w = Cudd_addApply(dd, Cudd_addPlus, *E, minterm1);
+            if (w == NULL) {
+                Cudd_RecursiveDeref(dd, cubey);
+                ABC_FREE(colptr);
+                ABC_FREE(rowind);
+                return(0);
+            }
+            cuddRef(w);
+            Cudd_RecursiveDeref(dd, minterm1);
+            Cudd_RecursiveDeref(dd, *E);
+            *E = w;
+        }
+        Cudd_RecursiveDeref(dd, cubey);
+    }
+    ABC_FREE(colptr);
+    ABC_FREE(rowind);
+
+    /* Read right-hand sides */
+    for (j=0; j<nrhs; j++) {
+        v = j + (1<< (lny-1));
+        cubey = one; cuddRef(cubey);
+        for (nv = lny - 1; nv>=0; nv--) {
+            if (v & 1) {
+                w = Cudd_addApply(dd, Cudd_addTimes, cubey, ly[nv]);
+            } else {
+                w = Cudd_addApply(dd, Cudd_addTimes, cubey, lyn[nv]);
+            }
+            if (w == NULL) {
+                Cudd_RecursiveDeref(dd, cubey);
+                return(0);
+            }
+            cuddRef(w);
+            Cudd_RecursiveDeref(dd, cubey);
+            cubey = w;
+            v >>= 1;
+        }
+        for (i=0; i<nrow; i++) {
+            u = i;
+            err = fscanf(fp, " %lf ", &val);
+            if (err == EOF || err != 1){ 
+                Cudd_RecursiveDeref(dd, cubey);
+                return(0);
+            }
+            /* Create new Constant node if necessary */
+            if (val == (double) 0.0) continue;
+            cubex = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) val);
+            if (cubex == NULL) {
+                Cudd_RecursiveDeref(dd, cubey);
+                return(0);
+            }
+            cuddRef(cubex);
+
+            for (nv = lnx - 1; nv>=0; nv--) {
+                if (u & 1) {
+                   w = Cudd_addApply(dd, Cudd_addTimes, cubex, lx[nv]);
+                } else { 
+                    w = Cudd_addApply(dd, Cudd_addTimes, cubex, lxn[nv]);
+                }
+                if (w == NULL) {
+                    Cudd_RecursiveDeref(dd, cubey);
+                    Cudd_RecursiveDeref(dd, cubex);
+                    return(0);
+                }
+                cuddRef(w);
+                Cudd_RecursiveDeref(dd, cubex);
+                cubex = w;
+                u >>= 1;
+            }
+            minterm1 = Cudd_addApply(dd, Cudd_addTimes, cubey, cubex);
+            if (minterm1 == NULL) {
+                Cudd_RecursiveDeref(dd, cubey);
+                Cudd_RecursiveDeref(dd, cubex);
+                return(0);
+            }
+            cuddRef(minterm1);
+            Cudd_RecursiveDeref(dd, cubex);
+            w = Cudd_addApply(dd, Cudd_addPlus, *E, minterm1);
+            if (w == NULL) {
+                Cudd_RecursiveDeref(dd, cubey);
+                return(0);
+            }
+            cuddRef(w);
+            Cudd_RecursiveDeref(dd, minterm1);
+            Cudd_RecursiveDeref(dd, *E);
+            *E = w;
+        }
+        Cudd_RecursiveDeref(dd, cubey);
+    }
+
+    return(1);
+
+} /* end of Cudd_addHarwell */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddInit.c b/abc-build/src/bdd/cudd/cuddInit.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddInit.c
@@ -0,0 +1,319 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddInit.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions to initialize and shut down the DD manager.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_Init()
+                <li> Cudd_Quit()
+                </ul>
+               Internal procedures included in this module:
+                <ul>
+                <li> cuddZddInitUniv()
+                <li> cuddZddFreeUniv()
+                </ul>
+              ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddInit.c,v 1.33 2007/07/01 05:10:50 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a new DD manager.]
+
+  Description [Creates a new DD manager, initializes the table, the
+  basic constants and the projection functions. If maxMemory is 0,
+  Cudd_Init decides suitable values for the maximum size of the cache
+  and for the limit for fast unique table growth based on the available
+  memory. Returns a pointer to the manager if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Quit]
+
+******************************************************************************/
+DdManager *
+Cudd_Init(
+  unsigned int numVars /* initial number of BDD variables (i.e., subtables) */,
+  unsigned int numVarsZ /* initial number of ZDD variables (i.e., subtables) */,
+  unsigned int numSlots /* initial size of the unique tables */,
+  unsigned int cacheSize /* initial size of the cache */,
+  unsigned long maxMemory /* target maximum memory occupation */)
+{
+    DdManager *unique;
+    int i,result;
+    DdNode *one, *zero;
+    unsigned int maxCacheSize;
+    unsigned int looseUpTo;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    if (maxMemory == 0) {
+        maxMemory = getSoftDataLimit();
+    }
+    looseUpTo = (unsigned int) ((maxMemory / sizeof(DdNode)) /
+                                DD_MAX_LOOSE_FRACTION);
+    unique = cuddInitTable(numVars,numVarsZ,numSlots,looseUpTo);
+    if (unique == NULL) return(NULL);
+    unique->maxmem = (unsigned long) maxMemory / 10 * 9;
+    maxCacheSize = (unsigned int) ((maxMemory / sizeof(DdCache)) /
+                                   DD_MAX_CACHE_FRACTION);
+    result = cuddInitCache(unique,cacheSize,maxCacheSize);
+    if (result == 0) return(NULL);
+
+    saveHandler = MMoutOfMemory;
+    MMoutOfMemory = Cudd_OutOfMem;
+    unique->stash = ABC_ALLOC(char,(maxMemory / DD_STASH_FRACTION) + 4);
+    MMoutOfMemory = saveHandler;
+    if (unique->stash == NULL) {
+        (void) fprintf(unique->err,"Unable to set aside memory\n");
+    }
+
+    /* Initialize constants. */
+    unique->one = cuddUniqueConst(unique,1.0);
+    if (unique->one == NULL) return(0);
+    cuddRef(unique->one);
+    unique->zero = cuddUniqueConst(unique,0.0);
+    if (unique->zero == NULL) return(0);
+    cuddRef(unique->zero);
+#ifdef HAVE_IEEE_754
+    if (DD_PLUS_INF_VAL != DD_PLUS_INF_VAL * 3 ||
+        DD_PLUS_INF_VAL != DD_PLUS_INF_VAL / 3) {
+        (void) fprintf(unique->err,"Warning: Crippled infinite values\n");
+        (void) fprintf(unique->err,"Recompile without -DHAVE_IEEE_754\n");
+    }
+#endif
+    unique->plusinfinity = cuddUniqueConst(unique,DD_PLUS_INF_VAL);
+    if (unique->plusinfinity == NULL) return(0);
+    cuddRef(unique->plusinfinity);
+    unique->minusinfinity = cuddUniqueConst(unique,DD_MINUS_INF_VAL);
+    if (unique->minusinfinity == NULL) return(0);
+    cuddRef(unique->minusinfinity);
+    unique->background = unique->zero;
+
+    /* The logical zero is different from the CUDD_VALUE_TYPE zero! */
+    one = unique->one;
+    zero = Cudd_Not(one);
+    /* Create the projection functions. */
+    unique->vars = ABC_ALLOC(DdNodePtr,unique->maxSize);
+    if (unique->vars == NULL) {
+        unique->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    for (i = 0; i < unique->size; i++) {
+        unique->vars[i] = cuddUniqueInter(unique,i,one,zero);
+        if (unique->vars[i] == NULL) return(0);
+        cuddRef(unique->vars[i]);
+    }
+
+    if (unique->sizeZ)
+        cuddZddInitUniv(unique);
+
+    unique->memused += sizeof(DdNode *) * unique->maxSize;
+
+    unique->bFunc = NULL;
+    unique->bFunc2 = NULL;
+    unique->TimeStop = 0;
+    return(unique);
+
+} /* end of Cudd_Init */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Deletes resources associated with a DD manager.]
+
+  Description [Deletes resources associated with a DD manager and
+  resets the global statistical counters. (Otherwise, another manaqger
+  subsequently created would inherit the stats of this one.)]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Init]
+
+******************************************************************************/
+void
+Cudd_Quit(
+  DdManager * unique)
+{
+    if (unique->stash != NULL) ABC_FREE(unique->stash);
+    cuddFreeTable(unique);
+
+} /* end of Cudd_Quit */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the ZDD universe.]
+
+  Description [Initializes the ZDD universe. Returns 1 if successful; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddZddFreeUniv]
+
+******************************************************************************/
+int
+cuddZddInitUniv(
+  DdManager * zdd)
+{
+    DdNode      *p, *res;
+    int         i;
+
+    zdd->univ = ABC_ALLOC(DdNodePtr, zdd->sizeZ);
+    if (zdd->univ == NULL) {
+        zdd->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+
+    res = DD_ONE(zdd);
+    cuddRef(res);
+    for (i = zdd->sizeZ - 1; i >= 0; i--) {
+        unsigned int index = zdd->invpermZ[i];
+        p = res;
+        res = cuddUniqueInterZdd(zdd, index, p, p);
+        if (res == NULL) {
+            Cudd_RecursiveDerefZdd(zdd,p);
+            ABC_FREE(zdd->univ);
+            return(0);
+        }
+        cuddRef(res);
+        cuddDeref(p);
+        zdd->univ[i] = res;
+    }
+
+#ifdef DD_VERBOSE
+    cuddZddP(zdd, zdd->univ[0]);
+#endif
+
+    return(1);
+
+} /* end of cuddZddInitUniv */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the ZDD universe.]
+
+  Description [Frees the ZDD universe.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddZddInitUniv]
+
+******************************************************************************/
+void
+cuddZddFreeUniv(
+  DdManager * zdd)
+{
+    if (zdd->univ) {
+        Cudd_RecursiveDerefZdd(zdd, zdd->univ[0]);
+        ABC_FREE(zdd->univ);
+    }
+
+} /* end of cuddZddFreeUniv */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddInt.h b/abc-build/src/bdd/cudd/cuddInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddInt.h
@@ -0,0 +1,1232 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [cuddInt.h]
+
+  PackageName [cudd]
+
+  Synopsis    [Internal data structures of the CUDD package.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+  Revision    [$Id: cuddInt.h,v 1.139 2009/03/08 02:49:02 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef ABC__bdd__cudd__cuddInt_h
+#define ABC__bdd__cudd__cuddInt_h
+
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+#ifdef DD_MIS
+#include "array.h"
+#include "list.h"
+#include "misc/st/st.h"
+#include "misc/espresso/espresso.h"
+#include "node.h"
+#ifdef SIS
+#include "graph.h"
+#include "astg.h"
+#endif
+#include "network.h"
+#endif
+
+#include <math.h>
+#include "cudd.h"
+#include "misc/st/st.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+#if defined(__GNUC__)
+# define DD_INLINE __inline__
+# if (__GNUC__ >2 || __GNUC_MINOR__ >=7)
+#   define DD_UNUSED __attribute__ ((__unused__))
+# else
+#   define DD_UNUSED
+# endif
+#else
+# if defined(__cplusplus)
+#   define DD_INLINE inline
+# else
+#   define DD_INLINE
+# endif
+# define DD_UNUSED
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DD_MAXREF               ((DdHalfWord) ~0)
+
+#define DD_DEFAULT_RESIZE       10      /* how many extra variables */
+                                        /* should be added when resizing */
+#define DD_MEM_CHUNK            1022
+
+/* These definitions work for CUDD_VALUE_TYPE == double */
+#define DD_ONE_VAL              (1.0)
+#define DD_ZERO_VAL             (0.0)
+#define DD_EPSILON              (1.0e-12)
+
+/* The definitions of +/- infinity in terms of HUGE_VAL work on
+** the DECstations and on many other combinations of OS/compiler.
+*/
+#ifdef HAVE_IEEE_754
+#  define DD_PLUS_INF_VAL       (HUGE_VAL)
+#else
+#  define DD_PLUS_INF_VAL       (10e301)
+#  define DD_CRI_HI_MARK        (10e150)
+#  define DD_CRI_LO_MARK        (-(DD_CRI_HI_MARK))
+#endif
+#define DD_MINUS_INF_VAL        (-(DD_PLUS_INF_VAL))
+
+#define DD_NON_CONSTANT         ((DdNode *) 1)  /* for Cudd_bddIteConstant */
+
+/* Unique table and cache management constants. */
+#define DD_MAX_SUBTABLE_DENSITY 4       /* tells when to resize a subtable */
+/* gc when this percent are dead (measured w.r.t. slots, not keys)
+** The first limit (LO) applies normally. The second limit applies when
+** the package believes more space for the unique table (i.e., more dead
+** nodes) would improve performance, and the unique table is not already
+** too large. The third limit applies when memory is low.
+*/
+#define DD_GC_FRAC_LO           DD_MAX_SUBTABLE_DENSITY * 0.25
+#define DD_GC_FRAC_HI           DD_MAX_SUBTABLE_DENSITY * 1.0
+#define DD_GC_FRAC_MIN          0.2
+#define DD_MIN_HIT              30      /* resize cache when hit ratio
+                                           above this percentage (default) */
+#define DD_MAX_LOOSE_FRACTION   5 /* 1 / (max fraction of memory used for
+                                     unique table in fast growth mode) */
+#define DD_MAX_CACHE_FRACTION   3 /* 1 / (max fraction of memory used for
+                                     computed table if resizing enabled) */
+#define DD_STASH_FRACTION       64 /* 1 / (fraction of memory set
+                                      aside for emergencies) */
+#define DD_MAX_CACHE_TO_SLOTS_RATIO 4 /* used to limit the cache size */
+
+/* Variable ordering default parameter values. */
+#define DD_SIFT_MAX_VAR         1000
+#define DD_SIFT_MAX_SWAPS       2000000
+#define DD_DEFAULT_RECOMB       0
+#define DD_MAX_REORDER_GROWTH   1.1
+#define DD_FIRST_REORDER        4004    /* 4 for the constants */
+#define DD_DYN_RATIO            2       /* when to dynamically reorder */
+
+/* Primes for cache hash functions. */
+#define DD_P1                   12582917
+#define DD_P2                   4256249
+#define DD_P3                   741457
+#define DD_P4                   1618033999
+
+/* Cache tags for 3-operand operators.  These tags are stored in the
+** least significant bits of the cache operand pointers according to
+** the following scheme.  The tag consists of two hex digits.  Both digits
+** must be even, so that they do not interfere with complementation bits.
+** The least significant one is stored in Bits 3:1 of the f operand in the
+** cache entry.  Bit 1 is always 1, so that we can differentiate
+** three-operand operations from one- and two-operand operations.
+** Therefore, the least significant digit is one of {2,6,a,e}.  The most
+** significant digit occupies Bits 3:1 of the g operand in the cache
+** entry.  It can by any even digit between 0 and e.  This gives a total
+** of 5 bits for the tag proper, which means a maximum of 32 three-operand
+** operations. */
+#define DD_ADD_ITE_TAG                          0x02
+#define DD_BDD_AND_ABSTRACT_TAG                 0x06
+#define DD_BDD_XOR_EXIST_ABSTRACT_TAG           0x0a
+#define DD_BDD_ITE_TAG                          0x0e
+#define DD_ADD_BDD_DO_INTERVAL_TAG              0x22
+#define DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG     0x26
+#define DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG   0x2a
+#define DD_BDD_COMPOSE_RECUR_TAG                0x2e
+#define DD_ADD_COMPOSE_RECUR_TAG                0x42
+#define DD_ADD_NON_SIM_COMPOSE_TAG              0x46
+#define DD_EQUIV_DC_TAG                         0x4a
+#define DD_ZDD_ITE_TAG                          0x4e
+#define DD_ADD_ITE_CONSTANT_TAG                 0x62
+#define DD_ADD_EVAL_CONST_TAG                   0x66
+#define DD_BDD_ITE_CONSTANT_TAG                 0x6a
+#define DD_ADD_OUT_SUM_TAG                      0x6e
+#define DD_BDD_LEQ_UNLESS_TAG                   0x82
+#define DD_ADD_TRIANGLE_TAG                     0x86
+
+/* Generator constants. */
+#define CUDD_GEN_CUBES 0
+#define CUDD_GEN_PRIMES 1
+#define CUDD_GEN_NODES 2
+#define CUDD_GEN_ZDD_PATHS 3
+#define CUDD_GEN_EMPTY 0
+#define CUDD_GEN_NONEMPTY 1
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+struct DdGen {
+    DdManager   *manager;
+    int         type;
+    int         status;
+    union {
+        struct {
+            int                 *cube;
+            CUDD_VALUE_TYPE     value;
+        } cubes;
+        struct {
+            int                 *cube;
+            DdNode              *ub;
+        } primes;
+        struct {
+            int                 size;
+        } nodes;
+    } gen;
+    struct {
+        int     sp;
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+        DdNode  **stack;
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    } stack;
+    DdNode      *node;
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/* Hooks in CUDD are functions that the application registers with the
+** manager so that they are called at appropriate times. The functions
+** are passed the manager as argument; they should return 1 if
+** successful and 0 otherwise.
+*/
+typedef struct DdHook {         /* hook list element */
+    DD_HFP f; /* function to be called */
+    struct DdHook *next;        /* next element in the list */
+} DdHook;
+
+/*
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+typedef long ptrint;
+typedef unsigned long ptruint;
+#else
+typedef int ptrint;
+typedef unsigned int ptruint;
+#endif
+*/
+
+typedef ABC_PTRINT_T ptrint;
+typedef ABC_PTRUINT_T ptruint;
+
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+
+typedef DdNode *DdNodePtr;
+
+/* Generic local cache item. */
+typedef struct DdLocalCacheItem {
+    DdNode *value;
+#ifdef DD_CACHE_PROFILE
+    ptrint count;
+#endif
+    DdNode *key[1];
+} DdLocalCacheItem;
+
+/* Local cache. */
+typedef struct DdLocalCache {
+    DdLocalCacheItem *item;
+    unsigned int itemsize;
+    unsigned int keysize;
+    unsigned int slots;
+    int shift;
+    double lookUps;
+    double minHit;
+    double hits;
+    unsigned int maxslots;
+    DdManager *manager;
+    struct DdLocalCache *next;
+} DdLocalCache;
+
+/* Generic hash item. */
+typedef struct DdHashItem {
+    struct DdHashItem *next;
+    ptrint count;
+    DdNode *value;
+    DdNode *key[1];
+} DdHashItem;
+
+/* Local hash table */
+typedef struct DdHashTable {
+    unsigned int keysize;
+    unsigned int itemsize;
+    DdHashItem **bucket;
+    DdHashItem *nextFree;
+    DdHashItem **memoryList;
+    unsigned int numBuckets;
+    int shift;
+    unsigned int size;
+    unsigned int maxsize;
+    DdManager *manager;
+} DdHashTable;
+
+typedef struct DdCache {
+    DdNode *f,*g;               /* DDs */
+    ptruint h;                  /* either operator or DD */
+    DdNode *data;               /* already constructed DD */
+#ifdef DD_CACHE_PROFILE
+    ptrint count;
+#endif
+    unsigned hash;
+} DdCache;
+
+typedef struct DdSubtable {     /* subtable for one index */
+    DdNode **nodelist;          /* hash table */
+    int shift;                  /* shift for hash function */
+    unsigned int slots;         /* size of the hash table */
+    unsigned int keys;          /* number of nodes stored in this table */
+    unsigned int maxKeys;       /* slots * DD_MAX_SUBTABLE_DENSITY */
+    unsigned int dead;          /* number of dead nodes in this table */
+    unsigned int next;          /* index of next variable in group */
+    int bindVar;                /* flag to bind this variable to its level */
+    /* Fields for lazy sifting. */
+    Cudd_VariableType varType;  /* variable type (ps, ns, pi) */
+    int pairIndex;              /* corresponding variable index (ps <-> ns) */
+    int varHandled;             /* flag: 1 means variable is already handled */
+    Cudd_LazyGroupType varToBeGrouped; /* tells what grouping to apply */
+} DdSubtable;
+
+struct DdManager {      /* specialized DD symbol table */
+    /* Constants */
+    DdNode sentinel;            /* for collision lists */
+    DdNode *one;                /* constant 1 */
+    DdNode *zero;               /* constant 0 */
+    DdNode *plusinfinity;       /* plus infinity */
+    DdNode *minusinfinity;      /* minus infinity */
+    DdNode *background;         /* background value */
+    /* Computed Table */
+    DdCache *acache;            /* address of allocated memory for cache */
+    DdCache *cache;             /* the cache-based computed table */
+    unsigned int cacheSlots;    /* total number of cache entries */
+    int cacheShift;             /* shift value for cache hash function */
+    double cacheMisses;         /* number of cache misses (since resizing) */
+    double cacheHits;           /* number of cache hits (since resizing) */
+    double minHit;              /* hit percentage above which to resize */
+    int cacheSlack;             /* slots still available for resizing */
+    unsigned int maxCacheHard;  /* hard limit for cache size */
+    /* Unique Table */
+    int size;                   /* number of unique subtables */
+    int sizeZ;                  /* for ZDD */
+    int maxSize;                /* max number of subtables before resizing */
+    int maxSizeZ;               /* for ZDD */
+    DdSubtable *subtables;      /* array of unique subtables */
+    DdSubtable *subtableZ;      /* for ZDD */
+    DdSubtable constants;       /* unique subtable for the constants */
+    unsigned int slots;         /* total number of hash buckets */
+    unsigned int keys;          /* total number of BDD and ADD nodes */
+    unsigned int keysZ;         /* total number of ZDD nodes */
+    unsigned int dead;          /* total number of dead BDD and ADD nodes */
+    unsigned int deadZ;         /* total number of dead ZDD nodes */
+    unsigned int maxLive;       /* maximum number of live nodes */
+    unsigned int minDead;       /* do not GC if fewer than these dead */
+    double gcFrac;              /* gc when this fraction is dead */
+    int gcEnabled;              /* gc is enabled */
+    unsigned int looseUpTo;     /* slow growth beyond this limit */
+                                /* (measured w.r.t. slots, not keys) */
+    unsigned int initSlots;     /* initial size of a subtable */
+    DdNode **stack;             /* stack for iterative procedures */
+//    double allocated;           /* number of nodes allocated */
+    ABC_INT64_T allocated;      /* number of nodes allocated */
+                                /* (not during reordering) */
+    double reclaimed;           /* number of nodes brought back from the dead */
+    int isolated;               /* isolated projection functions */
+    int *perm;                  /* current variable perm. (index to level) */
+    int *permZ;                 /* for ZDD */
+    int *invperm;               /* current inv. var. perm. (level to index) */
+    int *invpermZ;              /* for ZDD */
+    DdNode **vars;              /* projection functions */
+    int *map;                   /* variable map for fast swap */
+    DdNode **univ;              /* ZDD 1 for each variable */
+    int linearSize;             /* number of rows and columns of linear */
+    long *interact;             /* interacting variable matrix */
+    long *linear;               /* linear transform matrix */
+    /* Memory Management */
+    DdNode **memoryList;        /* memory manager for symbol table */
+    DdNode *nextFree;           /* list of free nodes */
+    char *stash;                /* memory reserve */
+#ifndef DD_NO_DEATH_ROW
+    DdNode **deathRow;          /* queue for dereferencing */
+    int deathRowDepth;          /* number of slots in the queue */
+    int nextDead;               /* index in the queue */
+    unsigned deadMask;          /* mask for circular index update */
+#endif
+    /* General Parameters */
+    CUDD_VALUE_TYPE epsilon;    /* tolerance on comparisons */
+    /* Dynamic Reordering Parameters */
+    int reordered;              /* flag set at the end of reordering */
+    int reorderings;            /* number of calls to Cudd_ReduceHeap */
+    int siftMaxVar;             /* maximum number of vars sifted */
+    int siftMaxSwap;            /* maximum number of swaps per sifting */
+    double maxGrowth;           /* maximum growth during reordering */
+    double maxGrowthAlt;        /* alternate maximum growth for reordering */
+    int reordCycle;             /* how often to apply alternate threshold */
+    int autoDyn;                /* automatic dynamic reordering flag (BDD) */
+    int autoDynZ;               /* automatic dynamic reordering flag (ZDD) */
+    Cudd_ReorderingType autoMethod;  /* default reordering method */
+    Cudd_ReorderingType autoMethodZ; /* default reordering method (ZDD) */
+    int realign;                /* realign ZDD order after BDD reordering */
+    int realignZ;               /* realign BDD order after ZDD reordering */
+    unsigned int nextDyn;       /* reorder if this size is reached */
+    unsigned int countDead;     /* if 0, count deads to trigger reordering */
+    MtrNode *tree;              /* Variable group tree (BDD) */
+    MtrNode *treeZ;             /* Variable group tree (ZDD) */
+    Cudd_AggregationType groupcheck; /* Used during group sifting */
+    int recomb;                 /* Used during group sifting */
+    int symmviolation;          /* Used during group sifting */
+    int arcviolation;           /* Used during group sifting */
+    int populationSize;         /* population size for GA */
+    int numberXovers;           /* number of crossovers for GA */
+    DdLocalCache *localCaches;  /* local caches currently in existence */
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    char *hooks;                /* application-specific field (used by vis) */
+    DdHook *preGCHook;          /* hooks to be called before GC */
+    DdHook *postGCHook;         /* hooks to be called after GC */
+    DdHook *preReorderingHook;  /* hooks to be called before reordering */
+    DdHook *postReorderingHook; /* hooks to be called after reordering */
+    FILE *out;                  /* stdout for this manager */
+    FILE *err;                  /* stderr for this manager */
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    Cudd_ErrorType errorCode;   /* info on last error */
+    /* Statistical counters. */
+    unsigned long memused;      /* total memory allocated for the manager */
+    unsigned long maxmem;       /* target maximum memory */
+    unsigned long maxmemhard;   /* hard limit for maximum memory */
+    int garbageCollections;     /* number of garbage collections */
+    long GCTime;                /* total time spent in garbage collection */
+    long reordTime;             /* total time spent in reordering */
+    double totCachehits;        /* total number of cache hits */
+    double totCacheMisses;      /* total number of cache misses */
+    double cachecollisions;     /* number of cache collisions */
+    double cacheinserts;        /* number of cache insertions */
+    double cacheLastInserts;    /* insertions at the last cache resizing */
+    double cachedeletions;      /* number of deletions during garbage coll. */
+#ifdef DD_STATS
+    double nodesFreed;          /* number of nodes returned to the free list */
+    double nodesDropped;        /* number of nodes killed by dereferencing */
+#endif
+    unsigned int peakLiveNodes; /* maximum number of live nodes */
+#ifdef DD_UNIQUE_PROFILE
+    double uniqueLookUps;       /* number of unique table lookups */
+    double uniqueLinks;         /* total distance traveled in coll. chains */
+#endif
+#ifdef DD_COUNT
+    double recursiveCalls;      /* number of recursive calls */
+#ifdef DD_STATS
+    double nextSample;          /* when to write next line of stats */
+#endif
+    double swapSteps;           /* number of elementary reordering steps */
+#endif
+#ifdef DD_MIS
+    /* mis/verif compatibility fields */
+    array_t *iton;              /* maps ids in ddNode to node_t */
+    array_t *order;             /* copy of order_list */
+    lsHandle handle;            /* where it is in network BDD list */
+    network_t *network;
+    st__table *local_order;      /* for local BDDs */
+    int nvars;                  /* variables used so far */
+    int threshold;              /* for pseudo var threshold value*/
+#endif
+    DdNode * bFunc;
+    DdNode * bFunc2;
+    abctime TimeStop;           /* timeout for reordering */
+};
+
+typedef struct Move {
+    DdHalfWord x;
+    DdHalfWord y;
+    unsigned int flags;
+    int size;
+    struct Move *next;
+} Move;
+
+/* Generic level queue item. */
+typedef struct DdQueueItem {
+    struct DdQueueItem *next;
+    struct DdQueueItem *cnext;
+    void *key;
+} DdQueueItem;
+
+/* Level queue. */
+typedef struct DdLevelQueue {
+    void *first;
+    DdQueueItem **last;
+    DdQueueItem *freelist;
+    DdQueueItem **buckets;
+    int levels;
+    int itemsize;
+    int size;
+    int maxsize;
+    int numBuckets;
+    int shift;
+} DdLevelQueue;
+
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis    [Adds node to the head of the free list.]
+
+  Description [Adds node to the head of the free list.  Does not
+  deallocate memory chunks that become free.  This function is also
+  used by the dynamic reordering functions.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddAllocNode cuddDynamicAllocNode cuddDeallocMove]
+
+******************************************************************************/
+#define cuddDeallocNode(unique,node) \
+    (node)->next = (unique)->nextFree; \
+    (unique)->nextFree = node;
+
+/**Macro***********************************************************************
+
+  Synopsis    [Adds node to the head of the free list.]
+
+  Description [Adds node to the head of the free list.  Does not
+  deallocate memory chunks that become free.  This function is also
+  used by the dynamic reordering functions.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddDeallocNode cuddDynamicAllocNode]
+
+******************************************************************************/
+#define cuddDeallocMove(unique,node) \
+    ((DdNode *)(node))->ref = 0; \
+    ((DdNode *)(node))->next = (unique)->nextFree; \
+    (unique)->nextFree = (DdNode *)(node);
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Increases the reference count of a node, if it is not
+  saturated.]
+
+  Description  [Increases the reference count of a node, if it is not
+  saturated. This being a macro, it is faster than Cudd_Ref, but it
+  cannot be used in constructs like cuddRef(a = b()).]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_Ref]
+
+******************************************************************************/
+#define cuddRef(n) cuddSatInc(Cudd_Regular(n)->ref)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Decreases the reference count of a node, if it is not
+  saturated.]
+
+  Description  [Decreases the reference count of node. It is primarily
+  used in recursive procedures to decrease the ref count of a result
+  node before returning it. This accomplishes the goal of removing the
+  protection applied by a previous cuddRef. This being a macro, it is
+  faster than Cudd_Deref, but it cannot be used in constructs like
+  cuddDeref(a = b()).]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_Deref]
+
+******************************************************************************/
+#define cuddDeref(n) cuddSatDec(Cudd_Regular(n)->ref)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns 1 if the node is a constant node.]
+
+  Description  [Returns 1 if the node is a constant node (rather than an
+  internal node). All constant nodes have the same index
+  (CUDD_CONST_INDEX). The pointer passed to cuddIsConstant must be regular.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_IsConstant]
+
+******************************************************************************/
+#define cuddIsConstant(node) ((node)->index == CUDD_CONST_INDEX)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the then child of an internal node.]
+
+  Description  [Returns the then child of an internal node. If
+  <code>node</code> is a constant node, the result is unpredictable.
+  The pointer passed to cuddT must be regular.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_T]
+
+******************************************************************************/
+#define cuddT(node) ((node)->type.kids.T)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the else child of an internal node.]
+
+  Description  [Returns the else child of an internal node. If
+  <code>node</code> is a constant node, the result is unpredictable.
+  The pointer passed to cuddE must be regular.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_E]
+
+******************************************************************************/
+#define cuddE(node) ((node)->type.kids.E)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the value of a constant node.]
+
+  Description  [Returns the value of a constant node. If
+  <code>node</code> is an internal node, the result is unpredictable.
+  The pointer passed to cuddV must be regular.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_V]
+
+******************************************************************************/
+#define cuddV(node) ((node)->type.value)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Finds the current position of variable index in the
+  order.]
+
+  Description [Finds the current position of variable index in the
+  order.  This macro duplicates the functionality of Cudd_ReadPerm,
+  but it does not check for out-of-bounds indices and it is more
+  efficient.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_ReadPerm]
+
+******************************************************************************/
+#define cuddI(dd,index) (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->perm[(index)])
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Finds the current position of ZDD variable index in the
+  order.]
+
+  Description [Finds the current position of ZDD variable index in the
+  order.  This macro duplicates the functionality of Cudd_ReadPermZdd,
+  but it does not check for out-of-bounds indices and it is more
+  efficient.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_ReadPermZdd]
+
+******************************************************************************/
+#define cuddIZ(dd,index) (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->permZ[(index)])
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Converts pointer into a literal.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+#define cuddF2L(f) ((Cudd_Regular(f)->Id << 1) | Cudd_IsComplement(f))
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Hash function for the unique table.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [ddCHash ddCHash2]
+
+******************************************************************************/
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define ddHash(f,g,s) \
+((((unsigned)(ptruint)(f) * DD_P1 + \
+   (unsigned)(ptruint)(g)) * DD_P2) >> (s))
+#else
+#define ddHash(f,g,s) \
+((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s))
+#endif
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Hash function for the cache.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [ddHash ddCHash2]
+
+******************************************************************************/
+/*
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define ddCHash(o,f,g,h,s) \
+((((((unsigned)(ptruint)(f) + (unsigned)(ptruint)(o)) * DD_P1 + \
+    (unsigned)(ptruint)(g)) * DD_P2 + \
+   (unsigned)(ptruint)(h)) * DD_P3) >> (s))
+#else
+#define ddCHash(o,f,g,h,s) \
+((((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2 + \
+   (unsigned)(h)) * DD_P3) >> (s))
+#endif
+*/
+
+/**Macro***********************************************************************
+
+  Synopsis    [Hash function for the cache for functions with two
+  operands.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [ddHash ddCHash]
+
+******************************************************************************/
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define ddCHash2(o,f,g,s) \
+(((((unsigned)(ptruint)(f) + (unsigned)(ptruint)(o)) * DD_P1 + \
+   (unsigned)(ptruint)(g)) * DD_P2) >> (s))
+#define ddCHash2_(o,f,g) \
+(((((unsigned)(ptruint)(f) + (unsigned)(ptruint)(o)) * DD_P1 + \
+   (unsigned)(ptruint)(g)) * DD_P2))
+#else
+#define ddCHash2(o,f,g,s) \
+(((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s))
+#define ddCHash2_(o,f,g) \
+(((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2))
+#endif
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Clears the 4 least significant bits of a pointer.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define cuddClean(p) ((DdNode *)((ptruint)(p) & ~0xf))
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Computes the minimum of two numbers.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [ddMax]
+
+******************************************************************************/
+#define ddMin(x,y) (((y) < (x)) ? (y) : (x))
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Computes the maximum of two numbers.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [ddMin]
+
+******************************************************************************/
+#define ddMax(x,y) (((y) > (x)) ? (y) : (x))
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Computes the absolute value of a number.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define ddAbs(x) (((x)<0) ? -(x) : (x))
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Returns 1 if the absolute value of the difference of the two
+  arguments x and y is less than e.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define ddEqualVal(x,y,e) (ddAbs((x)-(y))<(e))
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Saturating increment operator.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [cuddSatDec]
+
+******************************************************************************/
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define cuddSatInc(x) ((x)++)
+#else
+#define cuddSatInc(x) ((x) += (x) != (DdHalfWord)DD_MAXREF)
+#endif
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Saturating decrement operator.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [cuddSatInc]
+
+******************************************************************************/
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define cuddSatDec(x) ((x)--)
+#else
+#define cuddSatDec(x) ((x) -= (x) != (DdHalfWord)DD_MAXREF)
+#endif
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Returns the constant 1 node.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [DD_ZERO DD_PLUS_INFINITY DD_MINUS_INFINITY]
+
+******************************************************************************/
+#define DD_ONE(dd)              ((dd)->one)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Returns the arithmetic 0 constant node.]
+
+  Description [Returns the arithmetic 0 constant node. This is different
+  from the logical zero. The latter is obtained by
+  Cudd_Not(DD_ONE(dd)).]
+
+  SideEffects [none]
+
+  SeeAlso     [DD_ONE Cudd_Not DD_PLUS_INFINITY DD_MINUS_INFINITY]
+
+******************************************************************************/
+#define DD_ZERO(dd) ((dd)->zero)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Returns the plus infinity constant node.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [DD_ONE DD_ZERO DD_MINUS_INFINITY]
+
+******************************************************************************/
+#define DD_PLUS_INFINITY(dd) ((dd)->plusinfinity)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Returns the minus infinity constant node.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [DD_ONE DD_ZERO DD_PLUS_INFINITY]
+
+******************************************************************************/
+#define DD_MINUS_INFINITY(dd) ((dd)->minusinfinity)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL.]
+
+  Description [Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL.
+  Furthermore, if x <= DD_MINUS_INF_VAL/2, x is set to
+  DD_MINUS_INF_VAL. Similarly, if DD_PLUS_INF_VAL/2 <= x, x is set to
+  DD_PLUS_INF_VAL.  Normally this macro is a NOOP. However, if
+  HAVE_IEEE_754 is not defined, it makes sure that a value does not
+  get larger than infinity in absolute value, and once it gets to
+  infinity, stays there.  If the value overflows before this macro is
+  applied, no recovery is possible.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#ifdef HAVE_IEEE_754
+#define cuddAdjust(x)
+#else
+#define cuddAdjust(x)           ((x) = ((x) >= DD_CRI_HI_MARK) ? DD_PLUS_INF_VAL : (((x) <= DD_CRI_LO_MARK) ? DD_MINUS_INF_VAL : (x)))
+#endif
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Extract the least significant digit of a double digit.]
+
+  Description [Extract the least significant digit of a double digit. Used
+  in the manipulation of arbitrary precision integers.]
+
+  SideEffects [None]
+
+  SeeAlso     [DD_MSDIGIT]
+
+******************************************************************************/
+#define DD_LSDIGIT(x)   ((x) & DD_APA_MASK)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Extract the most significant digit of a double digit.]
+
+  Description [Extract the most significant digit of a double digit. Used
+  in the manipulation of arbitrary precision integers.]
+
+  SideEffects [None]
+
+  SeeAlso     [DD_LSDIGIT]
+
+******************************************************************************/
+#define DD_MSDIGIT(x)   ((x) >> DD_APA_BITS)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Outputs a line of stats.]
+
+  Description [Outputs a line of stats if DD_COUNT and DD_STATS are
+  defined. Increments the number of recursive calls if DD_COUNT is
+  defined.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+#ifdef DD_COUNT
+#ifdef DD_STATS
+#define statLine(dd) dd->recursiveCalls++; \
+if (dd->recursiveCalls == dd->nextSample) {(void) fprintf(dd->err, \
+"@%.0f: %u nodes %u live %.0f dropped %.0f reclaimed\n", dd->recursiveCalls, \
+dd->keys, dd->keys - dd->dead, dd->nodesDropped, dd->reclaimed); \
+dd->nextSample += 250000;}
+#else
+#define statLine(dd) dd->recursiveCalls++;
+#endif
+#else
+#define statLine(dd)
+#endif
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+extern DdNode *        cuddAddExistAbstractRecur( DdManager * manager, DdNode * f, DdNode * cube );
+extern DdNode *        cuddAddUnivAbstractRecur( DdManager * manager, DdNode * f, DdNode * cube );
+extern DdNode *        cuddAddOrAbstractRecur( DdManager * manager, DdNode * f, DdNode * cube );
+extern DdNode *        cuddAddApplyRecur( DdManager * dd, DdNode * (*)(DdManager * , DdNode ** , DdNode **), DdNode * f, DdNode * g );
+extern DdNode *        cuddAddMonadicApplyRecur( DdManager *  dd, DdNode * (*)(DdManager * , DdNode *), DdNode *  f );
+extern DdNode *        cuddAddScalarInverseRecur( DdManager * dd, DdNode * f, DdNode * epsilon );
+extern DdNode *        cuddAddIteRecur( DdManager * dd, DdNode * f, DdNode * g, DdNode * h );
+extern DdNode *        cuddAddCmplRecur( DdManager * dd, DdNode * f );
+extern DdNode *        cuddAddNegateRecur( DdManager * dd, DdNode * f );
+extern DdNode *        cuddAddRoundOffRecur( DdManager * dd, DdNode * f, double trunc );
+extern DdNode *        cuddUnderApprox( DdManager * dd, DdNode * f, int numVars, int threshold, int safe, double quality );
+extern DdNode *        cuddRemapUnderApprox( DdManager * dd, DdNode * f, int numVars, int threshold, double quality );
+extern DdNode *        cuddBiasedUnderApprox( DdManager * dd, DdNode * f, DdNode * b, int numVars, int threshold, double quality1, double quality0 );
+extern DdNode *        cuddBddAndAbstractRecur( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube );
+extern int             cuddAnnealing( DdManager * table, int lower, int upper );
+extern DdNode *        cuddBddExistAbstractRecur( DdManager * manager, DdNode * f, DdNode * cube );
+extern DdNode *        cuddBddXorExistAbstractRecur( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube );
+extern DdNode *        cuddBddBooleanDiffRecur( DdManager * manager, DdNode * f, DdNode * var );
+extern DdNode *        cuddBddIteRecur( DdManager * dd, DdNode * f, DdNode * g, DdNode * h );
+extern DdNode *        cuddBddIntersectRecur( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        cuddBddAndRecur( DdManager * manager, DdNode * f, DdNode * g );
+extern DdNode *        cuddBddXorRecur( DdManager * manager, DdNode * f, DdNode * g );
+extern DdNode *        cuddBddTransfer( DdManager * ddS, DdManager * ddD, DdNode * f );
+extern DdNode *        cuddAddBddDoPattern( DdManager * dd, DdNode * f );
+extern int             cuddInitCache( DdManager * unique, unsigned int cacheSize, unsigned int maxCacheSize );
+extern void            cuddCacheInsert( DdManager * table, ptruint op, DdNode * f, DdNode * g, DdNode * h, DdNode * data );
+extern void            cuddCacheInsert2( DdManager * table, DdNode * (*)(DdManager * , DdNode * , DdNode *), DdNode * f, DdNode * g, DdNode * data );
+extern void            cuddCacheInsert1( DdManager * table, DdNode * (*)(DdManager * , DdNode *), DdNode * f, DdNode * data );
+extern DdNode *        cuddCacheLookup( DdManager * table, ptruint op, DdNode * f, DdNode * g, DdNode * h );
+extern DdNode *        cuddCacheLookupZdd( DdManager * table, ptruint op, DdNode * f, DdNode * g, DdNode * h );
+extern DdNode *        cuddCacheLookup2( DdManager * table, DdNode * (*)(DdManager * , DdNode * , DdNode *), DdNode * f, DdNode * g );
+extern DdNode *        cuddCacheLookup1( DdManager * table, DdNode * (*)(DdManager * , DdNode *), DdNode * f );
+extern DdNode *        cuddCacheLookup2Zdd( DdManager * table, DdNode * (*)(DdManager * , DdNode * , DdNode *), DdNode * f, DdNode * g );
+extern DdNode *        cuddCacheLookup1Zdd( DdManager * table, DdNode * (*)(DdManager * , DdNode *), DdNode * f );
+extern DdNode *        cuddConstantLookup( DdManager * table, ptruint op, DdNode * f, DdNode * g, DdNode * h );
+extern int             cuddCacheProfile( DdManager * table, FILE * fp );
+extern void            cuddCacheResize( DdManager * table );
+extern void            cuddCacheFlush( DdManager * table );
+extern int             cuddComputeFloorLog2( unsigned int value );
+extern int             cuddHeapProfile( DdManager * dd );
+extern void            cuddPrintNode( DdNode * f, FILE * fp );
+extern void            cuddPrintVarGroups( DdManager *  dd, MtrNode *  root, int zdd, int silent );
+extern DdNode *        cuddBddClippingAnd( DdManager * dd, DdNode * f, DdNode * g, int maxDepth, int direction );
+extern DdNode *        cuddBddClippingAndAbstract( DdManager * dd, DdNode * f, DdNode * g, DdNode * cube, int maxDepth, int direction );
+extern void            cuddGetBranches( DdNode * g, DdNode ** g1, DdNode ** g0 );
+extern int             cuddCheckCube( DdManager * dd, DdNode * g );
+extern DdNode *        cuddCofactorRecur( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        cuddBddComposeRecur( DdManager * dd, DdNode * f, DdNode * g, DdNode * proj );
+extern DdNode *        cuddAddComposeRecur( DdManager * dd, DdNode * f, DdNode * g, DdNode * proj );
+extern int             cuddExact( DdManager * table, int lower, int upper );
+extern DdNode *        cuddBddConstrainRecur( DdManager * dd, DdNode * f, DdNode * c );
+extern DdNode *        cuddBddRestrictRecur( DdManager * dd, DdNode * f, DdNode * c );
+extern DdNode *        cuddBddNPAndRecur( DdManager * dd, DdNode * f, DdNode * c );
+extern DdNode *        cuddAddConstrainRecur( DdManager * dd, DdNode * f, DdNode * c );
+extern DdNode *        cuddAddRestrictRecur( DdManager * dd, DdNode * f, DdNode * c );
+extern DdNode *        cuddBddLICompaction( DdManager * dd, DdNode * f, DdNode * c );
+extern int             cuddGa( DdManager * table, int lower, int upper );
+extern int             cuddTreeSifting( DdManager * table, Cudd_ReorderingType method );
+extern int             cuddZddInitUniv( DdManager * zdd );
+extern void            cuddZddFreeUniv( DdManager * zdd );
+extern void            cuddSetInteract( DdManager * table, int x, int y );
+extern int             cuddTestInteract( DdManager * table, int x, int y );
+extern int             cuddInitInteract( DdManager * table );
+extern DdLocalCache *  cuddLocalCacheInit( DdManager * manager, unsigned int keySize, unsigned int cacheSize, unsigned int maxCacheSize );
+extern void            cuddLocalCacheQuit( DdLocalCache * cache );
+extern void            cuddLocalCacheInsert( DdLocalCache * cache, DdNodePtr * key, DdNode * value );
+extern DdNode *        cuddLocalCacheLookup( DdLocalCache * cache, DdNodePtr * key );
+extern void            cuddLocalCacheClearDead( DdManager * manager );
+extern int             cuddIsInDeathRow( DdManager * dd, DdNode * f );
+extern int             cuddTimesInDeathRow( DdManager * dd, DdNode * f );
+extern void            cuddLocalCacheClearAll( DdManager * manager );
+#ifdef DD_CACHE_PROFILE
+extern int             cuddLocalCacheProfile( DdLocalCache * cache );
+#endif
+extern DdHashTable *   cuddHashTableInit( DdManager * manager, unsigned int keySize, unsigned int initSize );
+extern void            cuddHashTableQuit( DdHashTable * hash );
+extern int             cuddHashTableInsert( DdHashTable * hash, DdNodePtr * key, DdNode * value, ptrint count );
+extern DdNode *        cuddHashTableLookup( DdHashTable * hash, DdNodePtr * key );
+extern int             cuddHashTableInsert1( DdHashTable * hash, DdNode * f, DdNode * value, ptrint count );
+extern DdNode *        cuddHashTableLookup1( DdHashTable * hash, DdNode * f );
+extern int             cuddHashTableInsert2( DdHashTable * hash, DdNode * f, DdNode * g, DdNode * value, ptrint count );
+extern DdNode *        cuddHashTableLookup2( DdHashTable * hash, DdNode * f, DdNode * g );
+extern int             cuddHashTableInsert3( DdHashTable * hash, DdNode * f, DdNode * g, DdNode * h, DdNode * value, ptrint count );
+extern DdNode *        cuddHashTableLookup3( DdHashTable * hash, DdNode * f, DdNode * g, DdNode * h );
+extern DdLevelQueue *  cuddLevelQueueInit( int levels, int itemSize, int numBuckets );
+extern void            cuddLevelQueueQuit( DdLevelQueue * queue );
+extern void *          cuddLevelQueueEnqueue( DdLevelQueue * queue, void * key, int level );
+extern void            cuddLevelQueueDequeue( DdLevelQueue * queue, int level );
+extern int             cuddLinearAndSifting( DdManager * table, int lower, int upper );
+extern int             cuddLinearInPlace( DdManager *  table, int  x, int  y );
+extern void            cuddUpdateInteractionMatrix( DdManager *  table, int  xindex, int  yindex );
+extern int             cuddInitLinear( DdManager * table );
+extern int             cuddResizeLinear( DdManager * table );
+extern DdNode *        cuddBddLiteralSetIntersectionRecur( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        cuddCProjectionRecur( DdManager * dd, DdNode * R, DdNode * Y, DdNode * Ysupp );
+extern DdNode *        cuddBddClosestCube( DdManager * dd, DdNode * f, DdNode * g, CUDD_VALUE_TYPE bound );
+extern void            cuddReclaim( DdManager * table, DdNode * n );
+extern void            cuddReclaimZdd( DdManager * table, DdNode * n );
+extern void            cuddClearDeathRow( DdManager * table );
+extern void            cuddShrinkDeathRow( DdManager * table );
+extern DdNode *        cuddDynamicAllocNode( DdManager * table );
+extern int             cuddSifting( DdManager * table, int lower, int upper );
+extern int             cuddSwapping( DdManager * table, int lower, int upper, Cudd_ReorderingType heuristic );
+extern int             cuddNextHigh( DdManager * table, int x );
+extern int             cuddNextLow( DdManager * table, int x );
+extern int             cuddSwapInPlace( DdManager * table, int x, int y );
+extern int             cuddBddAlignToZdd( DdManager * table );
+extern DdNode *        cuddBddMakePrime( DdManager * dd, DdNode * cube, DdNode * f );
+extern DdNode *        cuddSolveEqnRecur( DdManager * bdd, DdNode * F, DdNode * Y, DdNode ** G, int n, int * yIndex, int i );
+extern DdNode *        cuddVerifySol( DdManager * bdd, DdNode * F, DdNode ** G, int * yIndex, int n );
+#ifdef st__INCLUDED
+extern DdNode *        cuddSplitSetRecur( DdManager * manager, st__table * mtable, int * varSeen, DdNode * p, double n, double max, int index );
+#endif
+extern DdNode *        cuddSubsetHeavyBranch( DdManager * dd, DdNode * f, int numVars, int threshold );
+extern DdNode *        cuddSubsetShortPaths( DdManager * dd, DdNode * f, int numVars, int threshold, int hardlimit );
+extern int             cuddSymmCheck( DdManager * table, int x, int y );
+extern int             cuddSymmSifting( DdManager * table, int lower, int upper );
+extern int             cuddSymmSiftingConv( DdManager * table, int lower, int upper );
+extern DdNode *        cuddAllocNode( DdManager * unique );
+extern DdManager *     cuddInitTable( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int looseUpTo );
+extern void            cuddFreeTable( DdManager * unique );
+extern int             cuddGarbageCollect( DdManager * unique, int clearCache );
+extern DdNode *        cuddZddGetNode( DdManager * zdd, int id, DdNode * T, DdNode * E );
+extern DdNode *        cuddZddGetNodeIVO( DdManager * dd, int index, DdNode * g, DdNode * h );
+extern DdNode *        cuddUniqueInter( DdManager * unique, int index, DdNode * T, DdNode * E );
+extern DdNode *        cuddUniqueInterIVO( DdManager * unique, int index, DdNode * T, DdNode * E );
+extern DdNode *        cuddUniqueInterZdd( DdManager * unique, int index, DdNode * T, DdNode * E );
+extern DdNode *        cuddUniqueConst( DdManager * unique, CUDD_VALUE_TYPE value );
+extern void            cuddRehash( DdManager * unique, int i );
+extern void            cuddShrinkSubtable( DdManager * unique, int i );
+extern int             cuddInsertSubtables( DdManager * unique, int n, int level );
+extern int             cuddDestroySubtables( DdManager * unique, int n );
+extern int             cuddResizeTableZdd( DdManager * unique, int index );
+extern void            cuddSlowTableGrowth( DdManager * unique );
+extern int             cuddP( DdManager * dd, DdNode * f );
+#ifdef st__INCLUDED
+extern enum st__retval  cuddStCountfree( char * key, char * value, char * arg );
+extern int             cuddCollectNodes( DdNode * f, st__table * visited );
+#endif
+extern DdNodePtr *     cuddNodeArray( DdNode * f, int * n );
+extern int             cuddWindowReorder( DdManager * table, int low, int high, Cudd_ReorderingType submethod );
+extern DdNode *        cuddZddProduct( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        cuddZddUnateProduct( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        cuddZddWeakDiv( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        cuddZddWeakDivF( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        cuddZddDivide( DdManager * dd, DdNode * f, DdNode * g );
+extern DdNode *        cuddZddDivideF( DdManager * dd, DdNode * f, DdNode * g );
+extern int             cuddZddGetCofactors3( DdManager * dd, DdNode * f, int v, DdNode ** f1, DdNode ** f0, DdNode ** fd );
+extern int             cuddZddGetCofactors2( DdManager * dd, DdNode * f, int v, DdNode ** f1, DdNode ** f0 );
+extern DdNode *        cuddZddComplement( DdManager * dd, DdNode * node );
+extern int             cuddZddGetPosVarIndex(DdManager *  dd, int index );
+extern int             cuddZddGetNegVarIndex(DdManager *  dd, int index );
+extern int             cuddZddGetPosVarLevel(DdManager *  dd, int index );
+extern int             cuddZddGetNegVarLevel(DdManager *  dd, int index );
+extern int             cuddZddTreeSifting( DdManager * table, Cudd_ReorderingType method );
+extern DdNode *        cuddZddIsop( DdManager * dd, DdNode * L, DdNode * U, DdNode ** zdd_I );
+extern DdNode *        cuddBddIsop( DdManager * dd, DdNode * L, DdNode * U );
+extern DdNode *        cuddMakeBddFromZddCover( DdManager * dd, DdNode * node );
+extern int             cuddZddLinearSifting( DdManager * table, int lower, int upper );
+extern int             cuddZddAlignToBdd( DdManager * table );
+extern int             cuddZddNextHigh( DdManager * table, int x );
+extern int             cuddZddNextLow( DdManager * table, int x );
+extern int             cuddZddUniqueCompare( int * ptr_x, int * ptr_y );
+extern int             cuddZddSwapInPlace( DdManager * table, int x, int y );
+extern int             cuddZddSwapping( DdManager * table, int lower, int upper, Cudd_ReorderingType heuristic );
+extern int             cuddZddSifting( DdManager * table, int lower, int upper );
+extern DdNode *        cuddZddIte( DdManager * dd, DdNode * f, DdNode * g, DdNode * h );
+extern DdNode *        cuddZddUnion( DdManager * zdd, DdNode * P, DdNode * Q );
+extern DdNode *        cuddZddIntersect( DdManager * zdd, DdNode * P, DdNode * Q );
+extern DdNode *        cuddZddDiff( DdManager * zdd, DdNode * P, DdNode * Q );
+extern DdNode *        cuddZddChangeAux( DdManager * zdd, DdNode * P, DdNode * zvar );
+extern DdNode *        cuddZddSubset1( DdManager * dd, DdNode * P, int var );
+extern DdNode *        cuddZddSubset0( DdManager * dd, DdNode * P, int var );
+extern DdNode *        cuddZddChange( DdManager * dd, DdNode * P, int var );
+extern int             cuddZddSymmCheck( DdManager * table, int x, int y );
+extern int             cuddZddSymmSifting( DdManager * table, int lower, int upper );
+extern int             cuddZddSymmSiftingConv( DdManager * table, int lower, int upper );
+extern int             cuddZddP( DdManager * zdd, DdNode * f );
+
+/**AutomaticEnd***************************************************************/
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif /* _CUDDINT */
diff --git a/abc-build/src/bdd/cudd/cuddInteract.c b/abc-build/src/bdd/cudd/cuddInteract.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddInteract.c
@@ -0,0 +1,437 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddInteract.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions to manipulate the variable interaction matrix.]
+
+  Description [Internal procedures included in this file:
+        <ul>
+        <li> cuddSetInteract()
+        <li> cuddTestInteract()
+        <li> cuddInitInteract()
+        </ul>
+  Static procedures included in this file:
+        <ul>
+        <li> ddSuppInteract()
+        <li> ddClearLocal()
+        <li> ddUpdateInteract()
+        <li> ddClearGlobal()
+        </ul>
+  The interaction matrix tells whether two variables are
+  both in the support of some function of the DD. The main use of the
+  interaction matrix is in the in-place swapping. Indeed, if two
+  variables do not interact, there is no arc connecting the two layers;
+  therefore, the swap can be performed in constant time, without
+  scanning the subtables. Another use of the interaction matrix is in
+  the computation of the lower bounds for sifting. Finally, the
+  interaction matrix can be used to speed up aggregation checks in
+  symmetric and group sifting.<p>
+  The computation of the interaction matrix is done with a series of
+  depth-first searches. The searches start from those nodes that have
+  only external references. The matrix is stored as a packed array of bits;
+  since it is symmetric, only the upper triangle is kept in memory.
+  As a final remark, we note that there may be variables that do
+  intercat, but that for a given variable order have no arc connecting
+  their layers when they are adjacent.]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#if SIZEOF_LONG == 8
+#define BPL 64
+#define LOGBPL 6
+#else
+#define BPL 32
+#define LOGBPL 5
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddInteract.c,v 1.12 2004/08/13 18:04:49 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void ddSuppInteract (DdNode *f, int *support);
+static void ddClearLocal (DdNode *f);
+static void ddUpdateInteract (DdManager *table, int *support);
+static void ddClearGlobal (DdManager *table);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Set interaction matrix entries.]
+
+  Description [Given a pair of variables 0 <= x < y < table->size,
+  sets the corresponding bit of the interaction matrix to 1.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddSetInteract(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int posn, word, bit;
+
+#ifdef DD_DEBUG
+    assert(x < y);
+    assert(y < table->size);
+    assert(x >= 0);
+#endif
+
+    posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1;
+    word = posn >> LOGBPL;
+    bit = posn & (BPL-1);
+    table->interact[word] |= 1L << bit;
+
+} /* end of cuddSetInteract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Test interaction matrix entries.]
+
+  Description [Given a pair of variables 0 <= x < y < table->size,
+  tests whether the corresponding bit of the interaction matrix is 1.
+  Returns the value of the bit.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddTestInteract(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int posn, word, bit, result;
+
+    if (x > y) {
+        int tmp = x;
+        x = y;
+        y = tmp;
+    }
+#ifdef DD_DEBUG
+    assert(x < y);
+    assert(y < table->size);
+    assert(x >= 0);
+#endif
+
+    posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1;
+    word = posn >> LOGBPL;
+    bit = posn & (BPL-1);
+    result = (table->interact[word] >> bit) & 1L;
+    return(result);
+
+} /* end of cuddTestInteract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the interaction matrix.]
+
+  Description [Initializes the interaction matrix. The interaction
+  matrix is implemented as a bit vector storing the upper triangle of
+  the symmetric interaction matrix. The bit vector is kept in an array
+  of long integers. The computation is based on a series of depth-first
+  searches, one for each root of the DAG. Two flags are needed: The
+  local visited flag uses the LSB of the then pointer. The global
+  visited flag uses the LSB of the next pointer.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddInitInteract(
+  DdManager * table)
+{
+    int i,j,k;
+    ABC_UINT64_T words;
+    long *interact;
+    int *support;
+    DdNode *f;
+    DdNode *sentinel = &(table->sentinel);
+    DdNodePtr *nodelist;
+    int slots;
+    int n = table->size;
+
+    words = ((n * (n-1)) >> (1 + LOGBPL)) + 1;
+    table->interact = interact = ABC_ALLOC(long,(unsigned)words);
+    if (interact == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    for (i = 0; i < words; i++) {
+        interact[i] = 0;
+    }
+
+    support = ABC_ALLOC(int,n);
+    if (support == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        ABC_FREE(interact);
+        return(0);
+    }
+
+    for (i = 0; i < n; i++) {
+        nodelist = table->subtables[i].nodelist;
+        slots = table->subtables[i].slots;
+        for (j = 0; j < slots; j++) {
+            f = nodelist[j];
+            while (f != sentinel) {
+                /* A node is a root of the DAG if it cannot be
+                ** reached by nodes above it. If a node was never
+                ** reached during the previous depth-first searches,
+                ** then it is a root, and we start a new depth-first
+                ** search from it.
+                */
+                if (!Cudd_IsComplement(f->next)) {
+                    for (k = 0; k < n; k++) {
+                        support[k] = 0;
+                    }
+                    ddSuppInteract(f,support);
+                    ddClearLocal(f);
+                    ddUpdateInteract(table,support);
+                }
+                f = Cudd_Regular(f->next);
+            }
+        }
+    }
+    ddClearGlobal(table);
+
+    ABC_FREE(support);
+    return(1);
+
+} /* end of cuddInitInteract */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find the support of f.]
+
+  Description [Performs a DFS from f. Uses the LSB of the then pointer
+  as visited flag.]
+
+  SideEffects [Accumulates in support the variables on which f depends.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ddSuppInteract(
+  DdNode * f,
+  int * support)
+{
+    if (cuddIsConstant(f) || Cudd_IsComplement(cuddT(f))) {
+        return;
+    }
+
+    support[f->index] = 1;
+    ddSuppInteract(cuddT(f),support);
+    ddSuppInteract(Cudd_Regular(cuddE(f)),support);
+    /* mark as visited */
+    cuddT(f) = Cudd_Complement(cuddT(f));
+    f->next = Cudd_Complement(f->next);
+    return;
+
+} /* end of ddSuppInteract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs a DFS from f, clearing the LSB of the then pointers.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ddClearLocal(
+  DdNode * f)
+{
+    if (cuddIsConstant(f) || !Cudd_IsComplement(cuddT(f))) {
+        return;
+    }
+    /* clear visited flag */
+    cuddT(f) = Cudd_Regular(cuddT(f));
+    ddClearLocal(cuddT(f));
+    ddClearLocal(Cudd_Regular(cuddE(f)));
+    return;
+
+} /* end of ddClearLocal */
+
+
+/**Function********************************************************************
+
+  Synopsis [Marks as interacting all pairs of variables that appear in
+  support.]
+
+  Description [If support[i] == support[j] == 1, sets the (i,j) entry
+  of the interaction matrix to 1.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ddUpdateInteract(
+  DdManager * table,
+  int * support)
+{
+    int i,j;
+    int n = table->size;
+
+    for (i = 0; i < n-1; i++) {
+        if (support[i] == 1) {
+            for (j = i+1; j < n; j++) {
+                if (support[j] == 1) {
+                    cuddSetInteract(table,i,j);
+                }
+            }
+        }
+    }
+
+} /* end of ddUpdateInteract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Scans the DD and clears the LSB of the next pointers.]
+
+  Description [The LSB of the next pointers are used as markers to tell
+  whether a node was reached by at least one DFS. Once the interaction
+  matrix is built, these flags are reset.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ddClearGlobal(
+  DdManager * table)
+{
+    int i,j;
+    DdNode *f;
+    DdNode *sentinel = &(table->sentinel);
+    DdNodePtr *nodelist;
+    int slots;
+
+    for (i = 0; i < table->size; i++) {
+        nodelist = table->subtables[i].nodelist;
+        slots = table->subtables[i].slots;
+        for (j = 0; j < slots; j++) {
+            f = nodelist[j];
+            while (f != sentinel) {
+                f->next = Cudd_Regular(f->next);
+                f = f->next;
+            }
+        }
+    }
+
+} /* end of ddClearGlobal */
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddLCache.c b/abc-build/src/bdd/cudd/cuddLCache.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddLCache.c
@@ -0,0 +1,1465 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddLCache.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for local caches.]
+
+  Description [Internal procedures included in this module:
+                <ul>
+                <li> cuddLocalCacheInit()
+                <li> cuddLocalCacheQuit()
+                <li> cuddLocalCacheInsert()
+                <li> cuddLocalCacheLookup()
+                <li> cuddLocalCacheClearDead()
+                <li> cuddLocalCacheClearAll()
+                <li> cuddLocalCacheProfile()
+                <li> cuddHashTableInit()
+                <li> cuddHashTableQuit()
+                <li> cuddHashTableInsert()
+                <li> cuddHashTableLookup()
+                <li> cuddHashTableInsert2()
+                <li> cuddHashTableLookup2()
+                <li> cuddHashTableInsert3()
+                <li> cuddHashTableLookup3()
+                </ul>
+            Static procedures included in this module:
+                <ul>
+                <li> cuddLocalCacheResize()
+                <li> ddLCHash()
+                <li> cuddLocalCacheAddToList()
+                <li> cuddLocalCacheRemoveFromList()
+                <li> cuddHashTableResize()
+                <li> cuddHashTableAlloc()
+                </ul> ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DD_MAX_HASHTABLE_DENSITY 2      /* tells when to resize a table */
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddLCache.c,v 1.24 2009/03/08 02:49:02 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis    [Computes hash function for keys of two operands.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [ddLCHash3 ddLCHash]
+
+******************************************************************************/
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define ddLCHash2(f,g,shift) \
+((((unsigned)(ptruint)(f) * DD_P1 + \
+   (unsigned)(ptruint)(g)) * DD_P2) >> (shift))
+#else
+#define ddLCHash2(f,g,shift) \
+((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (shift))
+#endif
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Computes hash function for keys of three operands.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [ddLCHash2 ddLCHash]
+
+******************************************************************************/
+#define ddLCHash3(f,g,h,shift)  ddCHash2(f,g,h,shift)
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void cuddLocalCacheResize (DdLocalCache *cache);
+DD_INLINE static unsigned int ddLCHash (DdNodePtr *key, unsigned int keysize, int shift);
+static void cuddLocalCacheAddToList (DdLocalCache *cache);
+static void cuddLocalCacheRemoveFromList (DdLocalCache *cache);
+static int cuddHashTableResize (DdHashTable *hash);
+DD_INLINE static DdHashItem * cuddHashTableAlloc (DdHashTable *hash);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes a local computed table.]
+
+  Description [Initializes a computed table.  Returns a pointer the
+  the new local cache in case of success; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddInitCache]
+
+******************************************************************************/
+DdLocalCache *
+cuddLocalCacheInit(
+  DdManager * manager /* manager */,
+  unsigned int  keySize /* size of the key (number of operands) */,
+  unsigned int  cacheSize /* Initial size of the cache */,
+  unsigned int  maxCacheSize /* Size of the cache beyond which no resizing occurs */)
+{
+    DdLocalCache *cache;
+    int logSize;
+
+    cache = ABC_ALLOC(DdLocalCache,1);
+    if (cache == NULL) {
+        manager->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    cache->manager = manager;
+    cache->keysize = keySize;
+    cache->itemsize = (keySize + 1) * sizeof(DdNode *);
+#ifdef DD_CACHE_PROFILE
+    cache->itemsize += sizeof(ptrint);
+#endif
+    logSize = cuddComputeFloorLog2(ddMax(cacheSize,manager->slots/2));
+    cacheSize = 1 << logSize;
+    cache->item = (DdLocalCacheItem *)
+        ABC_ALLOC(char, cacheSize * cache->itemsize);
+    if (cache->item == NULL) {
+        manager->errorCode = CUDD_MEMORY_OUT;
+        ABC_FREE(cache);
+        return(NULL);
+    }
+    cache->slots = cacheSize;
+    cache->shift = sizeof(int) * 8 - logSize;
+    cache->maxslots = ddMin(maxCacheSize,manager->slots);
+    cache->minHit = manager->minHit;
+    /* Initialize to avoid division by 0 and immediate resizing. */
+    cache->lookUps = (double) (int) (cacheSize * cache->minHit + 1);
+    cache->hits = 0;
+    manager->memused += cacheSize * cache->itemsize + sizeof(DdLocalCache);
+
+    /* Initialize the cache. */
+    memset(cache->item, 0, cacheSize * cache->itemsize);
+
+    /* Add to manager's list of local caches for GC. */
+    cuddLocalCacheAddToList(cache);
+
+    return(cache);
+
+} /* end of cuddLocalCacheInit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Shuts down a local computed table.]
+
+  Description [Initializes the computed table. It is called by
+  Cudd_Init. Returns a pointer the the new local cache in case of
+  success; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddLocalCacheInit]
+
+******************************************************************************/
+void
+cuddLocalCacheQuit(
+  DdLocalCache * cache /* cache to be shut down */)
+{
+    cache->manager->memused -=
+        cache->slots * cache->itemsize + sizeof(DdLocalCache);
+    cuddLocalCacheRemoveFromList(cache);
+    ABC_FREE(cache->item);
+    ABC_FREE(cache);
+
+    return;
+
+} /* end of cuddLocalCacheQuit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts a result in a local cache.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddLocalCacheInsert(
+  DdLocalCache * cache,
+  DdNodePtr * key,
+  DdNode * value)
+{
+    unsigned int posn;
+    DdLocalCacheItem *entry;
+
+    posn = ddLCHash(key,cache->keysize,cache->shift);
+    entry = (DdLocalCacheItem *) ((char *) cache->item +
+                                  posn * cache->itemsize);
+    memcpy(entry->key,key,cache->keysize * sizeof(DdNode *));
+    entry->value = value;
+#ifdef DD_CACHE_PROFILE
+    entry->count++;
+#endif
+
+} /* end of cuddLocalCacheInsert */
+
+
+/**Function********************************************************************
+
+  Synopsis [Looks up in a local cache.]
+
+  Description [Looks up in a local cache. Returns the result if found;
+  it returns NULL if no result is found.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddLocalCacheLookup(
+  DdLocalCache * cache,
+  DdNodePtr * key)
+{
+    unsigned int posn;
+    DdLocalCacheItem *entry;
+    DdNode *value;
+
+    cache->lookUps++;
+    posn = ddLCHash(key,cache->keysize,cache->shift);
+    entry = (DdLocalCacheItem *) ((char *) cache->item +
+                                  posn * cache->itemsize);
+    if (entry->value != NULL &&
+        memcmp(key,entry->key,cache->keysize*sizeof(DdNode *)) == 0) {
+        cache->hits++;
+        value = Cudd_Regular(entry->value);
+        if (value->ref == 0) {
+            cuddReclaim(cache->manager,value);
+        }
+        return(entry->value);
+    }
+
+    /* Cache miss: decide whether to resize */
+
+    if (cache->slots < cache->maxslots &&
+        cache->hits > cache->lookUps * cache->minHit) {
+        cuddLocalCacheResize(cache);
+    }
+
+    return(NULL);
+
+} /* end of cuddLocalCacheLookup */
+
+
+/**Function********************************************************************
+
+  Synopsis [Clears the dead entries of the local caches of a manager.]
+
+  Description [Clears the dead entries of the local caches of a manager.
+  Used during garbage collection.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddLocalCacheClearDead(
+  DdManager * manager)
+{
+    DdLocalCache *cache = manager->localCaches;
+    unsigned int keysize;
+    unsigned int itemsize;
+    unsigned int slots;
+    DdLocalCacheItem *item;
+    DdNodePtr *key;
+    unsigned int i, j;
+
+    while (cache != NULL) {
+        keysize = cache->keysize;
+        itemsize = cache->itemsize;
+        slots = cache->slots;
+        item = cache->item;
+        for (i = 0; i < slots; i++) {
+            if (item->value != NULL) {
+                if (Cudd_Regular(item->value)->ref == 0) {
+                    item->value = NULL;
+                } else {
+                    key = item->key;
+                    for (j = 0; j < keysize; j++) {
+                        if (Cudd_Regular(key[j])->ref == 0) {
+                            item->value = NULL;
+                            break;
+                        }
+                    }
+                }
+            }
+            item = (DdLocalCacheItem *) ((char *) item + itemsize);
+        }
+        cache = cache->next;
+    }
+    return;
+
+} /* end of cuddLocalCacheClearDead */
+
+
+/**Function********************************************************************
+
+  Synopsis [Clears the local caches of a manager.]
+
+  Description [Clears the local caches of a manager.
+  Used before reordering.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddLocalCacheClearAll(
+  DdManager * manager)
+{
+    DdLocalCache *cache = manager->localCaches;
+
+    while (cache != NULL) {
+        memset(cache->item, 0, cache->slots * cache->itemsize);
+        cache = cache->next;
+    }
+    return;
+
+} /* end of cuddLocalCacheClearAll */
+
+
+#ifdef DD_CACHE_PROFILE
+
+#define DD_HYSTO_BINS 8
+
+/**Function********************************************************************
+
+  Synopsis    [Computes and prints a profile of a local cache usage.]
+
+  Description [Computes and prints a profile of a local cache usage.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddLocalCacheProfile(
+  DdLocalCache * cache)
+{
+    double count, mean, meansq, stddev, expected;
+    long max, min;
+    int imax, imin;
+    int i, retval, slots;
+    long *hystogram;
+    int nbins = DD_HYSTO_BINS;
+    int bin;
+    long thiscount;
+    double totalcount;
+    int nzeroes;
+    DdLocalCacheItem *entry;
+    FILE *fp = cache->manager->out;
+
+    slots = cache->slots;
+
+    meansq = mean = expected = 0.0;
+    max = min = (long) cache->item[0].count;
+    imax = imin = nzeroes = 0;
+    totalcount = 0.0;
+
+    hystogram = ABC_ALLOC(long, nbins);
+    if (hystogram == NULL) {
+        return(0);
+    }
+    for (i = 0; i < nbins; i++) {
+        hystogram[i] = 0;
+    }
+
+    for (i = 0; i < slots; i++) {
+        entry = (DdLocalCacheItem *) ((char *) cache->item +
+                                      i * cache->itemsize);
+        thiscount = (long) entry->count;
+        if (thiscount > max) {
+            max = thiscount;
+            imax = i;
+        }
+        if (thiscount < min) {
+            min = thiscount;
+            imin = i;
+        }
+        if (thiscount == 0) {
+            nzeroes++;
+        }
+        count = (double) thiscount;
+        mean += count;
+        meansq += count * count;
+        totalcount += count;
+        expected += count * (double) i;
+        bin = (i * nbins) / slots;
+        hystogram[bin] += thiscount;
+    }
+    mean /= (double) slots;
+    meansq /= (double) slots;
+    stddev = sqrt(meansq - mean*mean);
+
+    retval = fprintf(fp,"Cache stats: slots = %d average = %g ", slots, mean);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"standard deviation = %g\n", stddev);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Cache unused slots = %d\n", nzeroes);
+    if (retval == EOF) return(0);
+
+    if (totalcount) {
+        expected /= totalcount;
+        retval = fprintf(fp,"Cache access hystogram for %d bins", nbins);
+        if (retval == EOF) return(0);
+        retval = fprintf(fp," (expected bin value = %g)\n# ", expected);
+        if (retval == EOF) return(0);
+        for (i = nbins - 1; i>=0; i--) {
+            retval = fprintf(fp,"%ld ", hystogram[i]);
+            if (retval == EOF) return(0);
+        }
+        retval = fprintf(fp,"\n");
+        if (retval == EOF) return(0);
+    }
+
+    ABC_FREE(hystogram);
+    return(1);
+
+} /* end of cuddLocalCacheProfile */
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes a hash table.]
+
+  Description [Initializes a hash table. Returns a pointer to the new
+  table if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableQuit]
+
+******************************************************************************/
+DdHashTable *
+cuddHashTableInit(
+  DdManager * manager,
+  unsigned int  keySize,
+  unsigned int  initSize)
+{
+    DdHashTable *hash;
+    int logSize;
+
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    hash = ABC_ALLOC(DdHashTable, 1);
+    if (hash == NULL) {
+        manager->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    hash->keysize = keySize;
+    hash->manager = manager;
+    hash->memoryList = NULL;
+    hash->nextFree = NULL;
+    hash->itemsize = (keySize + 1) * sizeof(DdNode *) +
+        sizeof(ptrint) + sizeof(DdHashItem *);
+    /* We have to guarantee that the shift be < 32. */
+    if (initSize < 2) initSize = 2;
+    logSize = cuddComputeFloorLog2(initSize);
+    hash->numBuckets = 1 << logSize;
+    hash->shift = sizeof(int) * 8 - logSize;
+    hash->bucket = ABC_ALLOC(DdHashItem *, hash->numBuckets);
+    if (hash->bucket == NULL) {
+        manager->errorCode = CUDD_MEMORY_OUT;
+        ABC_FREE(hash);
+        return(NULL);
+    }
+    memset(hash->bucket, 0, hash->numBuckets * sizeof(DdHashItem *));
+    hash->size = 0;
+    hash->maxsize = hash->numBuckets * DD_MAX_HASHTABLE_DENSITY;
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    return(hash);
+
+} /* end of cuddHashTableInit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Shuts down a hash table.]
+
+  Description [Shuts down a hash table, dereferencing all the values.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableInit]
+
+******************************************************************************/
+void
+cuddHashTableQuit(
+  DdHashTable * hash)
+{
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    unsigned int i;
+    DdManager *dd = hash->manager;
+    DdHashItem *bucket;
+    DdHashItem **memlist, **nextmem;
+    unsigned int numBuckets = hash->numBuckets;
+
+    for (i = 0; i < numBuckets; i++) {
+        bucket = hash->bucket[i];
+        while (bucket != NULL) {
+            Cudd_RecursiveDeref(dd, bucket->value);
+            bucket = bucket->next;
+        }
+    }
+
+    memlist = hash->memoryList;
+    while (memlist != NULL) {
+        nextmem = (DdHashItem **) memlist[0];
+        ABC_FREE(memlist);
+        memlist = nextmem;
+    }
+
+    ABC_FREE(hash->bucket);
+    ABC_FREE(hash);
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+
+    return;
+
+} /* end of cuddHashTableQuit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts an item in a hash table.]
+
+  Description [Inserts an item in a hash table when the key has more than
+  three pointers.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [[cuddHashTableInsert1 cuddHashTableInsert2 cuddHashTableInsert3
+  cuddHashTableLookup]
+
+******************************************************************************/
+int
+cuddHashTableInsert(
+  DdHashTable * hash,
+  DdNodePtr * key,
+  DdNode * value,
+  ptrint count)
+{
+    int result;
+    unsigned int posn;
+    DdHashItem *item;
+    unsigned int i;
+
+#ifdef DD_DEBUG
+    assert(hash->keysize > 3);
+#endif
+
+    if (hash->size > hash->maxsize) {
+        result = cuddHashTableResize(hash);
+        if (result == 0) return(0);
+    }
+    item = cuddHashTableAlloc(hash);
+    if (item == NULL) return(0);
+    hash->size++;
+    item->value = value;
+    cuddRef(value);
+    item->count = count;
+    for (i = 0; i < hash->keysize; i++) {
+        item->key[i] = key[i];
+    }
+    posn = ddLCHash(key,hash->keysize,hash->shift);
+    item->next = hash->bucket[posn];
+    hash->bucket[posn] = item;
+
+    return(1);
+
+} /* end of cuddHashTableInsert */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Looks up a key in a hash table.]
+
+  Description [Looks up a key consisting of more than three pointers
+  in a hash table.  Returns the value associated to the key if there
+  is an entry for the given key in the table; NULL otherwise. If the
+  entry is present, its reference counter is decremented if not
+  saturated. If the counter reaches 0, the value of the entry is
+  dereferenced, and the entry is returned to the free list.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableLookup1 cuddHashTableLookup2 cuddHashTableLookup3
+  cuddHashTableInsert]
+
+******************************************************************************/
+DdNode *
+cuddHashTableLookup(
+  DdHashTable * hash,
+  DdNodePtr * key)
+{
+    unsigned int posn;
+    DdHashItem *item, *prev;
+    unsigned int i, keysize;
+
+#ifdef DD_DEBUG
+    assert(hash->keysize > 3);
+#endif
+
+    posn = ddLCHash(key,hash->keysize,hash->shift);
+    item = hash->bucket[posn];
+    prev = NULL;
+
+    keysize = hash->keysize;
+    while (item != NULL) {
+        DdNodePtr *key2 = item->key;
+        int equal = 1;
+        for (i = 0; i < keysize; i++) {
+            if (key[i] != key2[i]) {
+                equal = 0;
+                break;
+            }
+        }
+        if (equal) {
+            DdNode *value = item->value;
+            cuddSatDec(item->count);
+            if (item->count == 0) {
+                cuddDeref(value);
+                if (prev == NULL) {
+                    hash->bucket[posn] = item->next;
+                } else {
+                    prev->next = item->next;
+                }
+                item->next = hash->nextFree;
+                hash->nextFree = item;
+                hash->size--;
+            }
+            return(value);
+        }
+        prev = item;
+        item = item->next;
+    }
+    return(NULL);
+
+} /* end of cuddHashTableLookup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts an item in a hash table.]
+
+  Description [Inserts an item in a hash table when the key is one pointer.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableInsert cuddHashTableInsert2 cuddHashTableInsert3
+  cuddHashTableLookup1]
+
+******************************************************************************/
+int
+cuddHashTableInsert1(
+  DdHashTable * hash,
+  DdNode * f,
+  DdNode * value,
+  ptrint count)
+{
+    int result;
+    unsigned int posn;
+    DdHashItem *item;
+
+#ifdef DD_DEBUG
+    assert(hash->keysize == 1);
+#endif
+
+    if (hash->size > hash->maxsize) {
+        result = cuddHashTableResize(hash);
+        if (result == 0) return(0);
+    }
+    item = cuddHashTableAlloc(hash);
+    if (item == NULL) return(0);
+    hash->size++;
+    item->value = value;
+    cuddRef(value);
+    item->count = count;
+    item->key[0] = f;
+    posn = ddLCHash2(cuddF2L(f),cuddF2L(f),hash->shift);
+    item->next = hash->bucket[posn];
+    hash->bucket[posn] = item;
+
+    return(1);
+
+} /* end of cuddHashTableInsert1 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Looks up a key consisting of one pointer in a hash table.]
+
+  Description [Looks up a key consisting of one pointer in a hash table.
+  Returns the value associated to the key if there is an entry for the given
+  key in the table; NULL otherwise. If the entry is present, its reference
+  counter is decremented if not saturated. If the counter reaches 0, the
+  value of the entry is dereferenced, and the entry is returned to the free
+  list.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableLookup cuddHashTableLookup2 cuddHashTableLookup3
+  cuddHashTableInsert1]
+
+******************************************************************************/
+DdNode *
+cuddHashTableLookup1(
+  DdHashTable * hash,
+  DdNode * f)
+{
+    unsigned int posn;
+    DdHashItem *item, *prev;
+
+#ifdef DD_DEBUG
+    assert(hash->keysize == 1);
+#endif
+
+    posn = ddLCHash2(cuddF2L(f),cuddF2L(f),hash->shift);
+    item = hash->bucket[posn];
+    prev = NULL;
+
+    while (item != NULL) {
+        DdNodePtr *key = item->key;
+        if (f == key[0]) {
+            DdNode *value = item->value;
+            cuddSatDec(item->count);
+            if (item->count == 0) {
+                cuddDeref(value);
+                if (prev == NULL) {
+                    hash->bucket[posn] = item->next;
+                } else {
+                    prev->next = item->next;
+                }
+                item->next = hash->nextFree;
+                hash->nextFree = item;
+                hash->size--;
+            }
+            return(value);
+        }
+        prev = item;
+        item = item->next;
+    }
+    return(NULL);
+
+} /* end of cuddHashTableLookup1 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts an item in a hash table.]
+
+  Description [Inserts an item in a hash table when the key is
+  composed of two pointers. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert3
+  cuddHashTableLookup2]
+
+******************************************************************************/
+int
+cuddHashTableInsert2(
+  DdHashTable * hash,
+  DdNode * f,
+  DdNode * g,
+  DdNode * value,
+  ptrint count)
+{
+    int result;
+    unsigned int posn;
+    DdHashItem *item;
+
+#ifdef DD_DEBUG
+    assert(hash->keysize == 2);
+#endif
+
+    if (hash->size > hash->maxsize) {
+        result = cuddHashTableResize(hash);
+        if (result == 0) return(0);
+    }
+    item = cuddHashTableAlloc(hash);
+    if (item == NULL) return(0);
+    hash->size++;
+    item->value = value;
+    cuddRef(value);
+    item->count = count;
+    item->key[0] = f;
+    item->key[1] = g;
+    posn = ddLCHash2(cuddF2L(f),cuddF2L(g),hash->shift);
+    item->next = hash->bucket[posn];
+    hash->bucket[posn] = item;
+
+    return(1);
+
+} /* end of cuddHashTableInsert2 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Looks up a key consisting of two pointers in a hash table.]
+
+  Description [Looks up a key consisting of two pointer in a hash table.
+  Returns the value associated to the key if there is an entry for the given
+  key in the table; NULL otherwise. If the entry is present, its reference
+  counter is decremented if not saturated. If the counter reaches 0, the
+  value of the entry is dereferenced, and the entry is returned to the free
+  list.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup3
+  cuddHashTableInsert2]
+
+******************************************************************************/
+DdNode *
+cuddHashTableLookup2(
+  DdHashTable * hash,
+  DdNode * f,
+  DdNode * g)
+{
+    unsigned int posn;
+    DdHashItem *item, *prev;
+
+#ifdef DD_DEBUG
+    assert(hash->keysize == 2);
+#endif
+
+    posn = ddLCHash2(cuddF2L(f),cuddF2L(g),hash->shift);
+    item = hash->bucket[posn];
+    prev = NULL;
+
+    while (item != NULL) {
+        DdNodePtr *key = item->key;
+        if ((f == key[0]) && (g == key[1])) {
+            DdNode *value = item->value;
+            cuddSatDec(item->count);
+            if (item->count == 0) {
+                cuddDeref(value);
+                if (prev == NULL) {
+                    hash->bucket[posn] = item->next;
+                } else {
+                    prev->next = item->next;
+                }
+                item->next = hash->nextFree;
+                hash->nextFree = item;
+                hash->size--;
+            }
+            return(value);
+        }
+        prev = item;
+        item = item->next;
+    }
+    return(NULL);
+
+} /* end of cuddHashTableLookup2 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts an item in a hash table.]
+
+  Description [Inserts an item in a hash table when the key is
+  composed of three pointers. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert2
+  cuddHashTableLookup3]
+
+******************************************************************************/
+int
+cuddHashTableInsert3(
+  DdHashTable * hash,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h,
+  DdNode * value,
+  ptrint count)
+{
+    int result;
+    unsigned int posn;
+    DdHashItem *item;
+
+#ifdef DD_DEBUG
+    assert(hash->keysize == 3);
+#endif
+
+    if (hash->size > hash->maxsize) {
+        result = cuddHashTableResize(hash);
+        if (result == 0) return(0);
+    }
+    item = cuddHashTableAlloc(hash);
+    if (item == NULL) return(0);
+    hash->size++;
+    item->value = value;
+    cuddRef(value);
+    item->count = count;
+    item->key[0] = f;
+    item->key[1] = g;
+    item->key[2] = h;
+    posn = ddLCHash3(cuddF2L(f),cuddF2L(g),cuddF2L(h),hash->shift);
+    item->next = hash->bucket[posn];
+    hash->bucket[posn] = item;
+
+    return(1);
+
+} /* end of cuddHashTableInsert3 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Looks up a key consisting of three pointers in a hash table.]
+
+  Description [Looks up a key consisting of three pointers in a hash table.
+  Returns the value associated to the key if there is an entry for the given
+  key in the table; NULL otherwise. If the entry is present, its reference
+  counter is decremented if not saturated. If the counter reaches 0, the
+  value of the entry is dereferenced, and the entry is returned to the free
+  list.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup2
+  cuddHashTableInsert3]
+
+******************************************************************************/
+DdNode *
+cuddHashTableLookup3(
+  DdHashTable * hash,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    unsigned int posn;
+    DdHashItem *item, *prev;
+
+#ifdef DD_DEBUG
+    assert(hash->keysize == 3);
+#endif
+
+    posn = ddLCHash3(cuddF2L(f),cuddF2L(g),cuddF2L(h),hash->shift);
+    item = hash->bucket[posn];
+    prev = NULL;
+
+    while (item != NULL) {
+        DdNodePtr *key = item->key;
+        if ((f == key[0]) && (g == key[1]) && (h == key[2])) {
+            DdNode *value = item->value;
+            cuddSatDec(item->count);
+            if (item->count == 0) {
+                cuddDeref(value);
+                if (prev == NULL) {
+                    hash->bucket[posn] = item->next;
+                } else {
+                    prev->next = item->next;
+                }
+                item->next = hash->nextFree;
+                hash->nextFree = item;
+                hash->size--;
+            }
+            return(value);
+        }
+        prev = item;
+        item = item->next;
+    }
+    return(NULL);
+
+} /* end of cuddHashTableLookup3 */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resizes a local cache.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+cuddLocalCacheResize(
+  DdLocalCache * cache)
+{
+    DdLocalCacheItem *item, *olditem, *entry, *old;
+    int i, shift;
+    unsigned int posn;
+    unsigned int slots, oldslots;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    olditem = cache->item;
+    oldslots = cache->slots;
+    slots = cache->slots = oldslots << 1;
+
+#ifdef DD_VERBOSE
+    (void) fprintf(cache->manager->err,
+                   "Resizing local cache from %d to %d entries\n",
+                   oldslots, slots);
+    (void) fprintf(cache->manager->err,
+                   "\thits = %.0f\tlookups = %.0f\thit ratio = %5.3f\n",
+                   cache->hits, cache->lookUps, cache->hits / cache->lookUps);
+#endif
+
+    saveHandler = MMoutOfMemory;
+    MMoutOfMemory = Cudd_OutOfMem;
+    cache->item = item =
+        (DdLocalCacheItem *) ABC_ALLOC(char, slots * cache->itemsize);
+    MMoutOfMemory = saveHandler;
+    /* If we fail to allocate the new table we just give up. */
+    if (item == NULL) {
+#ifdef DD_VERBOSE
+        (void) fprintf(cache->manager->err,"Resizing failed. Giving up.\n");
+#endif
+        cache->slots = oldslots;
+        cache->item = olditem;
+        /* Do not try to resize again. */
+        cache->maxslots = oldslots - 1;
+        return;
+    }
+    shift = --(cache->shift);
+    cache->manager->memused += (slots - oldslots) * cache->itemsize;
+
+    /* Clear new cache. */
+    memset(item, 0, slots * cache->itemsize);
+
+    /* Copy from old cache to new one. */
+    for (i = 0; (unsigned) i < oldslots; i++) {
+        old = (DdLocalCacheItem *) ((char *) olditem + i * cache->itemsize);
+        if (old->value != NULL) {
+            posn = ddLCHash(old->key,cache->keysize,shift);
+            entry = (DdLocalCacheItem *) ((char *) item +
+                                          posn * cache->itemsize);
+            memcpy(entry->key,old->key,cache->keysize*sizeof(DdNode *));
+            entry->value = old->value;
+        }
+    }
+
+    ABC_FREE(olditem);
+
+    /* Reinitialize measurements so as to avoid division by 0 and
+    ** immediate resizing.
+    */
+    cache->lookUps = (double) (int) (slots * cache->minHit + 1);
+    cache->hits = 0;
+
+} /* end of cuddLocalCacheResize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the hash value for a local cache.]
+
+  Description [Computes the hash value for a local cache. Returns the
+  bucket index.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DD_INLINE
+static unsigned int
+ddLCHash(
+  DdNodePtr * key,
+  unsigned int keysize,
+  int shift)
+{
+    unsigned int val = (unsigned int) (ptrint) key[0] * DD_P2;
+    unsigned int i;
+
+    for (i = 1; i < keysize; i++) {
+        val = val * DD_P1 + (int) (ptrint) key[i];
+    }
+
+    return(val >> shift);
+
+} /* end of ddLCHash */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts a local cache in the manager list.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+cuddLocalCacheAddToList(
+  DdLocalCache * cache)
+{
+    DdManager *manager = cache->manager;
+
+    cache->next = manager->localCaches;
+    manager->localCaches = cache;
+    return;
+
+} /* end of cuddLocalCacheAddToList */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Removes a local cache from the manager list.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+cuddLocalCacheRemoveFromList(
+  DdLocalCache * cache)
+{
+    DdManager *manager = cache->manager;
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    DdLocalCache **prevCache, *nextCache;
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+
+    prevCache = &(manager->localCaches);
+    nextCache = manager->localCaches;
+
+    while (nextCache != NULL) {
+        if (nextCache == cache) {
+            *prevCache = nextCache->next;
+            return;
+        }
+        prevCache = &(nextCache->next);
+        nextCache = nextCache->next;
+    }
+    return;                     /* should never get here */
+
+} /* end of cuddLocalCacheRemoveFromList */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resizes a hash table.]
+
+  Description [Resizes a hash table. Returns 1 if successful; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableInsert]
+
+******************************************************************************/
+static int
+cuddHashTableResize(
+  DdHashTable * hash)
+{
+    int j;
+    unsigned int posn;
+    DdHashItem *item;
+    DdHashItem *next;
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    DdNode **key;
+    int numBuckets;
+    DdHashItem **buckets;
+    DdHashItem **oldBuckets = hash->bucket;
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    int shift;
+    int oldNumBuckets = hash->numBuckets;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    /* Compute the new size of the table. */
+    numBuckets = oldNumBuckets << 1;
+    saveHandler = MMoutOfMemory;
+    MMoutOfMemory = Cudd_OutOfMem;
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    buckets = ABC_ALLOC(DdHashItem *, numBuckets);
+    MMoutOfMemory = saveHandler;
+    if (buckets == NULL) {
+        hash->maxsize <<= 1;
+        return(1);
+    }
+
+    hash->bucket = buckets;
+    hash->numBuckets = numBuckets;
+    shift = --(hash->shift);
+    hash->maxsize <<= 1;
+    memset(buckets, 0, numBuckets * sizeof(DdHashItem *));
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    if (hash->keysize == 1) {
+        for (j = 0; j < oldNumBuckets; j++) {
+            item = oldBuckets[j];
+            while (item != NULL) {
+                next = item->next;
+                key = item->key;
+                posn = ddLCHash2(cuddF2L(key[0]), cuddF2L(key[0]), shift);
+                item->next = buckets[posn];
+                buckets[posn] = item;
+                item = next;
+            }
+        }
+    } else if (hash->keysize == 2) {
+        for (j = 0; j < oldNumBuckets; j++) {
+            item = oldBuckets[j];
+            while (item != NULL) {
+                next = item->next;
+                key = item->key;
+                posn = ddLCHash2(cuddF2L(key[0]), cuddF2L(key[1]), shift);
+                item->next = buckets[posn];
+                buckets[posn] = item;
+                item = next;
+            }
+        }
+    } else if (hash->keysize == 3) {
+        for (j = 0; j < oldNumBuckets; j++) {
+            item = oldBuckets[j];
+            while (item != NULL) {
+                next = item->next;
+                key = item->key;
+                posn = ddLCHash3(cuddF2L(key[0]), cuddF2L(key[1]), cuddF2L(key[2]), shift);
+                item->next = buckets[posn];
+                buckets[posn] = item;
+                item = next;
+            }
+        }
+    } else {
+        for (j = 0; j < oldNumBuckets; j++) {
+            item = oldBuckets[j];
+            while (item != NULL) {
+                next = item->next;
+                posn = ddLCHash(item->key, hash->keysize, shift);
+                item->next = buckets[posn];
+                buckets[posn] = item;
+                item = next;
+            }
+        }
+    }
+    ABC_FREE(oldBuckets);
+    return(1);
+
+} /* end of cuddHashTableResize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Fast storage allocation for items in a hash table.]
+
+  Description [Fast storage allocation for items in a hash table. The
+  first 4 bytes of a chunk contain a pointer to the next block; the
+  rest contains DD_MEM_CHUNK spaces for hash items.  Returns a pointer to
+  a new item if successful; NULL is memory is full.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddAllocNode cuddDynamicAllocNode]
+
+******************************************************************************/
+DD_INLINE
+static DdHashItem *
+cuddHashTableAlloc(
+  DdHashTable * hash)
+{
+    int i;
+    unsigned int itemsize = hash->itemsize;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    DdHashItem **mem, *thisOne, *next, *item;
+
+    if (hash->nextFree == NULL) {
+        saveHandler = MMoutOfMemory;
+        MMoutOfMemory = Cudd_OutOfMem;
+        mem = (DdHashItem **) ABC_ALLOC(char,(DD_MEM_CHUNK+1) * itemsize);
+        MMoutOfMemory = saveHandler;
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+        if (mem == NULL) {
+            if (hash->manager->stash != NULL) {
+                ABC_FREE(hash->manager->stash);
+                hash->manager->stash = NULL;
+                /* Inhibit resizing of tables. */
+                hash->manager->maxCacheHard = hash->manager->cacheSlots - 1;
+                hash->manager->cacheSlack = - (int) (hash->manager->cacheSlots + 1);
+                for (i = 0; i < hash->manager->size; i++) {
+                    hash->manager->subtables[i].maxKeys <<= 2;
+                }
+                hash->manager->gcFrac = 0.2;
+                hash->manager->minDead =
+                    (unsigned) (0.2 * (double) hash->manager->slots);
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+                mem = (DdHashItem **) ABC_ALLOC(char,(DD_MEM_CHUNK+1) * itemsize);
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+            }
+            if (mem == NULL) {
+                (*MMoutOfMemory)((long)((DD_MEM_CHUNK + 1) * itemsize));
+                hash->manager->errorCode = CUDD_MEMORY_OUT;
+                return(NULL);
+            }
+        }
+
+        mem[0] = (DdHashItem *) hash->memoryList;
+        hash->memoryList = mem;
+
+        thisOne = (DdHashItem *) ((char *) mem + itemsize);
+        hash->nextFree = thisOne;
+        for (i = 1; i < DD_MEM_CHUNK; i++) {
+            next = (DdHashItem *) ((char *) thisOne + itemsize);
+            thisOne->next = next;
+            thisOne = next;
+        }
+
+        thisOne->next = NULL;
+
+    }
+    item = hash->nextFree;
+    hash->nextFree = item->next;
+    return(item);
+
+} /* end of cuddHashTableAlloc */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddLevelQ.c b/abc-build/src/bdd/cudd/cuddLevelQ.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddLevelQ.c
@@ -0,0 +1,569 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddLevelQ.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Procedure to manage level queues.]
+
+  Description [The functions in this file allow an application to
+  easily manipulate a queue where nodes are prioritized by level. The
+  emphasis is on efficiency. Therefore, the queue items can have
+  variable size.  If the application does not need to attach
+  information to the nodes, it can declare the queue items to be of
+  type DdQueueItem. Otherwise, it can declare them to be of a
+  structure type such that the first three fields are data
+  pointers. The third pointer points to the node.  The first two
+  pointers are used by the level queue functions. The remaining fields
+  are initialized to 0 when a new item is created, and are then left
+  to the exclusive use of the application. On the DEC Alphas the three
+  pointers must be 32-bit pointers when CUDD is compiled with 32-bit
+  pointers.  The level queue functions make sure that each node
+  appears at most once in the queue. They do so by keeping a hash
+  table where the node is used as key.  Queue items are recycled via a
+  free list for efficiency.
+  
+  Internal procedures provided by this module:
+                <ul>
+                <li> cuddLevelQueueInit()
+                <li> cuddLevelQueueQuit()
+                <li> cuddLevelQueueEnqueue()
+                <li> cuddLevelQueueDequeue()
+                </ul>
+  Static procedures included in this module:
+                <ul>
+                <li> hashLookup()
+                <li> hashInsert()
+                <li> hashDelete()
+                <li> hashResize()
+                </ul>
+                ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddLevelQ.c,v 1.13 2009/03/08 02:49:02 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Hash function for the table of a level queue.]
+
+  Description [Hash function for the table of a level queue.]
+
+  SideEffects [None]
+
+  SeeAlso     [hashInsert hashLookup hashDelete]
+
+******************************************************************************/
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define lqHash(key,shift) \
+(((unsigned)(ptruint)(key) * DD_P1) >> (shift))
+#else
+#define lqHash(key,shift) \
+(((unsigned)(key) * DD_P1) >> (shift))
+#endif
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdQueueItem * hashLookup (DdLevelQueue *queue, void *key);
+static int hashInsert (DdLevelQueue *queue, DdQueueItem *item);
+static void hashDelete (DdLevelQueue *queue, DdQueueItem *item);
+static int hashResize (DdLevelQueue *queue);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes a level queue.]
+
+  Description [Initializes a level queue. A level queue is a queue
+  where inserts are based on the levels of the nodes. Within each
+  level the policy is FIFO. Level queues are useful in traversing a
+  BDD top-down. Queue items are kept in a free list when dequeued for
+  efficiency. Returns a pointer to the new queue if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddLevelQueueQuit cuddLevelQueueEnqueue cuddLevelQueueDequeue]
+
+******************************************************************************/
+DdLevelQueue *
+cuddLevelQueueInit(
+  int  levels /* number of levels */,
+  int  itemSize /* size of the item */,
+  int  numBuckets /* initial number of hash buckets */)
+{
+    DdLevelQueue *queue;
+    int logSize;
+
+    queue = ABC_ALLOC(DdLevelQueue,1);
+    if (queue == NULL)
+        return(NULL);
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    /* Keep pointers to the insertion points for all levels. */
+    queue->last = ABC_ALLOC(DdQueueItem *, levels);
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    if (queue->last == NULL) {
+        ABC_FREE(queue);
+        return(NULL);
+    }
+    /* Use a hash table to test for uniqueness. */
+    if (numBuckets < 2) numBuckets = 2;
+    logSize = cuddComputeFloorLog2(numBuckets);
+    queue->numBuckets = 1 << logSize;
+    queue->shift = sizeof(int) * 8 - logSize;
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    queue->buckets = ABC_ALLOC(DdQueueItem *, queue->numBuckets);
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    if (queue->buckets == NULL) {
+        ABC_FREE(queue->last);
+        ABC_FREE(queue);
+        return(NULL);
+    }
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    memset(queue->last, 0, levels * sizeof(DdQueueItem *));
+    memset(queue->buckets, 0, queue->numBuckets * sizeof(DdQueueItem *));
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    queue->first = NULL;
+    queue->freelist = NULL;
+    queue->levels = levels;
+    queue->itemsize = itemSize;
+    queue->size = 0;
+    queue->maxsize = queue->numBuckets * DD_MAX_SUBTABLE_DENSITY;
+    return(queue);
+
+} /* end of cuddLevelQueueInit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Shuts down a level queue.]
+
+  Description [Shuts down a level queue and releases all the
+  associated memory.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddLevelQueueInit]
+
+******************************************************************************/
+void
+cuddLevelQueueQuit(
+  DdLevelQueue * queue)
+{
+    DdQueueItem *item;
+
+    while (queue->freelist != NULL) {
+        item = queue->freelist;
+        queue->freelist = item->next;
+        ABC_FREE(item);
+    }
+    while (queue->first != NULL) {
+        item = (DdQueueItem *) queue->first;
+        queue->first = item->next;
+        ABC_FREE(item);
+    }
+    ABC_FREE(queue->buckets);
+    ABC_FREE(queue->last);
+    ABC_FREE(queue);
+    return;
+
+} /* end of cuddLevelQueueQuit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts a new key in a level queue.]
+
+  Description [Inserts a new key in a level queue. A new entry is
+  created in the queue only if the node is not already
+  enqueued. Returns a pointer to the queue item if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddLevelQueueInit cuddLevelQueueDequeue]
+
+******************************************************************************/
+void *
+cuddLevelQueueEnqueue(
+  DdLevelQueue * queue /* level queue */,
+  void * key /* key to be enqueued */,
+  int  level /* level at which to insert */)
+{
+    int plevel;
+    DdQueueItem *item;
+
+#ifdef DD_DEBUG
+    assert(level < queue->levels);
+#endif
+    /* Check whether entry for this node exists. */
+    item = hashLookup(queue,key);
+    if (item != NULL) return(item);
+
+    /* Get a free item from either the free list or the memory manager. */
+    if (queue->freelist == NULL) {
+        item = (DdQueueItem *) ABC_ALLOC(char, queue->itemsize);
+        if (item == NULL)
+            return(NULL);
+    } else {
+        item = queue->freelist;
+        queue->freelist = item->next;
+    }
+    /* Initialize. */
+    memset(item, 0, queue->itemsize);
+    item->key = key;
+    /* Update stats. */
+    queue->size++;
+
+    if (queue->last[level]) {
+        /* There are already items for this level in the queue. */
+        item->next = queue->last[level]->next;
+        queue->last[level]->next = item;
+    } else {
+        /* There are no items at the current level.  Look for the first
+        ** non-empty level preceeding this one. */
+        plevel = level;
+        while (plevel != 0 && queue->last[plevel] == NULL)
+            plevel--;
+        if (queue->last[plevel] == NULL) {
+            /* No element precedes this one in the queue. */
+            item->next = (DdQueueItem *) queue->first;
+            queue->first = item;
+        } else {
+            item->next = queue->last[plevel]->next;
+            queue->last[plevel]->next = item;
+        }
+    }
+    queue->last[level] = item;
+
+    /* Insert entry for the key in the hash table. */
+    if (hashInsert(queue,item) == 0) {
+        return(NULL);
+    }
+    return(item);
+
+} /* end of cuddLevelQueueEnqueue */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Remove an item from the front of a level queue.]
+
+  Description [Remove an item from the front of a level queue.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddLevelQueueEnqueue]
+
+******************************************************************************/
+void
+cuddLevelQueueDequeue(
+  DdLevelQueue * queue,
+  int  level)
+{
+    DdQueueItem *item = (DdQueueItem *) queue->first;
+
+    /* Delete from the hash table. */
+    hashDelete(queue,item);
+
+    /* Since we delete from the front, if this is the last item for
+    ** its level, there are no other items for the same level. */
+    if (queue->last[level] == item)
+        queue->last[level] = NULL;
+
+    queue->first = item->next;
+    /* Put item on the free list. */
+    item->next = queue->freelist;
+    queue->freelist = item;
+    /* Update stats. */
+    queue->size--;
+    return;
+
+} /* end of cuddLevelQueueDequeue */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Looks up a key in the hash table of a level queue.]
+
+  Description [Looks up a key in the hash table of a level queue. Returns
+  a pointer to the item with the given key if the key is found; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddLevelQueueEnqueue hashInsert]
+
+******************************************************************************/
+static DdQueueItem *
+hashLookup(
+  DdLevelQueue * queue,
+  void * key)
+{
+    int posn;
+    DdQueueItem *item;
+
+    posn = lqHash(key,queue->shift);
+    item = queue->buckets[posn];
+
+    while (item != NULL) {
+        if (item->key == key) {
+            return(item);
+        }
+        item = item->cnext;
+    }
+    return(NULL);
+
+} /* end of hashLookup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts an item in the hash table of a level queue.]
+
+  Description [Inserts an item in the hash table of a level queue. Returns
+  1 if successful; 0 otherwise. No check is performed to see if an item with
+  the same key is already in the hash table.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddLevelQueueEnqueue]
+
+******************************************************************************/
+static int
+hashInsert(
+  DdLevelQueue * queue,
+  DdQueueItem * item)
+{
+    int result;
+    int posn;
+
+    if (queue->size > queue->maxsize) {
+        result = hashResize(queue);
+        if (result == 0) return(0);
+    }
+
+    posn = lqHash(item->key,queue->shift);
+    item->cnext = queue->buckets[posn];
+    queue->buckets[posn] = item;
+
+    return(1);
+    
+} /* end of hashInsert */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Removes an item from the hash table of a level queue.]
+
+  Description [Removes an item from the hash table of a level queue.
+  Nothing is done if the item is not in the table.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddLevelQueueDequeue hashInsert]
+
+******************************************************************************/
+static void
+hashDelete(
+  DdLevelQueue * queue,
+  DdQueueItem * item)
+{
+    int posn;
+    DdQueueItem *prevItem;
+
+    posn = lqHash(item->key,queue->shift);
+    prevItem = queue->buckets[posn];
+
+    if (prevItem == NULL) return;
+    if (prevItem == item) {
+        queue->buckets[posn] = prevItem->cnext;
+        return;
+    }
+
+    while (prevItem->cnext != NULL) {
+        if (prevItem->cnext == item) {
+            prevItem->cnext = item->cnext;
+            return;
+        }
+        prevItem = prevItem->cnext;
+    }
+    return;
+
+} /* end of hashDelete */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resizes the hash table of a level queue.]
+
+  Description [Resizes the hash table of a level queue. Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [hashInsert]
+
+******************************************************************************/
+static int
+hashResize(
+  DdLevelQueue * queue)
+{
+    int j;
+    int posn;
+    DdQueueItem *item;
+    DdQueueItem *next;
+    int numBuckets;
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    DdQueueItem **buckets;
+    DdQueueItem **oldBuckets = queue->buckets;
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    int shift;
+    int oldNumBuckets = queue->numBuckets;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    /* Compute the new size of the subtable. */
+    numBuckets = oldNumBuckets << 1;
+    saveHandler = MMoutOfMemory;
+    MMoutOfMemory = Cudd_OutOfMem;
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    buckets = queue->buckets = ABC_ALLOC(DdQueueItem *, numBuckets);
+    MMoutOfMemory = saveHandler;
+    if (buckets == NULL) {
+        queue->maxsize <<= 1;
+        return(1);
+    }
+
+    queue->numBuckets = numBuckets;
+    shift = --(queue->shift);
+    queue->maxsize <<= 1;
+    memset(buckets, 0, numBuckets * sizeof(DdQueueItem *));
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    for (j = 0; j < oldNumBuckets; j++) {
+        item = oldBuckets[j];
+        while (item != NULL) {
+            next = item->cnext;
+            posn = lqHash(item->key, shift);
+            item->cnext = buckets[posn];
+            buckets[posn] = item;
+            item = next;
+        }
+    }
+    ABC_FREE(oldBuckets);
+    return(1);
+
+} /* end of hashResize */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddLinear.c b/abc-build/src/bdd/cudd/cuddLinear.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddLinear.c
@@ -0,0 +1,1373 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddLinear.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for DD reduction by linear transformations.]
+
+  Description [ Internal procedures included in this module:
+                <ul>
+                <li> cuddLinearAndSifting()
+                <li> cuddLinearInPlace()
+                <li> cuddUpdateInteractionMatrix()
+                <li> cuddInitLinear()
+                <li> cuddResizeLinear()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> ddLinearUniqueCompare()
+                <li> ddLinearAndSiftingAux()
+                <li> ddLinearAndSiftingUp()
+                <li> ddLinearAndSiftingDown()
+                <li> ddLinearAndSiftingBackward()
+                <li> ddUndoMoves()
+                <li> cuddXorLinear()
+                </ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define CUDD_SWAP_MOVE 0
+#define CUDD_LINEAR_TRANSFORM_MOVE 1
+#define CUDD_INVERSE_TRANSFORM_MOVE 2
+#if SIZEOF_LONG == 8
+#define BPL 64
+#define LOGBPL 6
+#else
+#define BPL 32
+#define LOGBPL 5
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddLinear.c,v 1.28 2009/02/19 16:21:03 fabio Exp $";
+#endif
+
+static  int     *entry;
+
+#ifdef DD_STATS
+extern  int     ddTotalNumberSwapping;
+extern  int     ddTotalNISwaps;
+static  int     ddTotalNumberLinearTr;
+#endif
+
+#ifdef DD_DEBUG
+static  int     zero = 0;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int ddLinearUniqueCompare (int *ptrX, int *ptrY);
+static int ddLinearAndSiftingAux (DdManager *table, int x, int xLow, int xHigh);
+static Move * ddLinearAndSiftingUp (DdManager *table, int y, int xLow, Move *prevMoves);
+static Move * ddLinearAndSiftingDown (DdManager *table, int x, int xHigh, Move *prevMoves);
+static int ddLinearAndSiftingBackward (DdManager *table, int size, Move *moves);
+static Move* ddUndoMoves (DdManager *table, Move *moves);
+static void cuddXorLinear (DdManager *table, int x, int y);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the linear transform matrix.]
+
+  Description [Prints the linear transform matrix. Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_PrintLinear(
+  DdManager * table)
+{
+    int i,j,k;
+    int retval;
+    int nvars = table->linearSize;
+    int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
+    long word;
+
+    for (i = 0; i < nvars; i++) {
+        for (j = 0; j < wordsPerRow; j++) {
+            word = table->linear[i*wordsPerRow + j];
+            for (k = 0; k < BPL; k++) {
+                retval = fprintf(table->out,"%ld",word & 1);
+                if (retval == 0) return(0);
+                word >>= 1;
+            }
+        }
+        retval = fprintf(table->out,"\n");
+        if (retval == 0) return(0);
+    }
+    return(1);
+
+} /* end of Cudd_PrintLinear */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads an entry of the linear transform matrix.]
+
+  Description [Reads an entry of the linear transform matrix.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_ReadLinear(
+  DdManager * table /* CUDD manager */,
+  int  x /* row index */,
+  int  y /* column index */)
+{
+    int nvars = table->size;
+    int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
+    long word;
+    int bit;
+    int result;
+
+    assert(table->size == table->linearSize);
+
+    word = wordsPerRow * x + (y >> LOGBPL);
+    bit  = y & (BPL-1);
+    result = (int) ((table->linear[word] >> bit) & 1);
+    return(result);
+
+} /* end of Cudd_ReadLinear */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [BDD reduction based on combination of sifting and linear
+  transformations.]
+
+  Description [BDD reduction based on combination of sifting and linear
+  transformations.  Assumes that no dead nodes are present.
+    <ol>
+    <li> Order all the variables according to the number of entries
+    in each unique table.
+    <li> Sift the variable up and down, remembering each time the
+    total size of the DD heap. At each position, linear transformation
+    of the two adjacent variables is tried and is accepted if it reduces
+    the size of the DD.
+    <li> Select the best permutation.
+    <li> Repeat 3 and 4 for all variables.
+    </ol>
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+cuddLinearAndSifting(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int         i;
+    int         *var;
+    int         size;
+    int         x;
+    int         result;
+#ifdef DD_STATS
+    int         previousSize;
+#endif
+
+#ifdef DD_STATS
+    ddTotalNumberLinearTr = 0;
+#endif
+
+    size = table->size;
+
+    var = NULL;
+    entry = NULL;
+    if (table->linear == NULL) {
+        result = cuddInitLinear(table);
+        if (result == 0) goto cuddLinearAndSiftingOutOfMem;
+#if 0
+        (void) fprintf(table->out,"\n");
+        result = Cudd_PrintLinear(table);
+        if (result == 0) goto cuddLinearAndSiftingOutOfMem;
+#endif
+    } else if (table->size != table->linearSize) {
+        result = cuddResizeLinear(table);
+        if (result == 0) goto cuddLinearAndSiftingOutOfMem;
+#if 0
+        (void) fprintf(table->out,"\n");
+        result = Cudd_PrintLinear(table);
+        if (result == 0) goto cuddLinearAndSiftingOutOfMem;
+#endif
+    }
+
+    /* Find order in which to sift variables. */
+    entry = ABC_ALLOC(int,size);
+    if (entry == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto cuddLinearAndSiftingOutOfMem;
+    }
+    var = ABC_ALLOC(int,size);
+    if (var == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto cuddLinearAndSiftingOutOfMem;
+    }
+
+    for (i = 0; i < size; i++) {
+        x = table->perm[i];
+        entry[i] = table->subtables[x].keys;
+        var[i] = i;
+    }
+
+    qsort((void *)var,size,sizeof(int),(DD_QSFP)ddLinearUniqueCompare);
+
+    /* Now sift. */
+    for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
+        x = table->perm[var[i]];
+        if (x < lower || x > upper) continue;
+#ifdef DD_STATS
+        previousSize = table->keys - table->isolated;
+#endif
+        result = ddLinearAndSiftingAux(table,x,lower,upper);
+        if (!result) goto cuddLinearAndSiftingOutOfMem;
+#ifdef DD_STATS
+        if (table->keys < (unsigned) previousSize + table->isolated) {
+            (void) fprintf(table->out,"-");
+        } else if (table->keys > (unsigned) previousSize + table->isolated) {
+            (void) fprintf(table->out,"+");     /* should never happen */
+            (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
+        } else {
+            (void) fprintf(table->out,"=");
+        }
+        fflush(table->out);
+#endif
+#ifdef DD_DEBUG
+        (void) Cudd_DebugCheck(table);
+#endif
+    }
+
+    ABC_FREE(var);
+    ABC_FREE(entry);
+
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.",
+                   ddTotalNumberLinearTr);
+#endif
+
+    return(1);
+
+cuddLinearAndSiftingOutOfMem:
+
+    if (entry != NULL) ABC_FREE(entry);
+    if (var != NULL) ABC_FREE(var);
+
+    return(0);
+
+} /* end of cuddLinearAndSifting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Linearly combines two adjacent variables.]
+
+  Description [Linearly combines two adjacent variables. Specifically,
+  replaces the top variable with the exclusive nor of the two variables.
+  It assumes that no dead nodes are present on entry to this
+  procedure.  The procedure then guarantees that no dead nodes will be
+  present when it terminates.  cuddLinearInPlace assumes that x &lt;
+  y.  Returns the number of keys in the table if successful; 0
+  otherwise.]
+
+  SideEffects [The two subtables corrresponding to variables x and y are
+  modified. The global counters of the unique table are also affected.]
+
+  SeeAlso     [cuddSwapInPlace]
+
+******************************************************************************/
+int
+cuddLinearInPlace(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    DdNodePtr *xlist, *ylist;
+    int    xindex, yindex;
+    int    xslots, yslots;
+    int    xshift, yshift;
+    int    oldxkeys, oldykeys;
+    int    newxkeys, newykeys;
+    int    comple, newcomplement;
+    int    i;
+    int    posn;
+    int    isolated;
+    DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
+    DdNode *g,*next,*last=NULL;
+    DdNodePtr *previousP;
+    DdNode *tmp;
+    DdNode *sentinel = &(table->sentinel);
+#ifdef DD_DEBUG
+    int    count, idcheck;
+#endif
+
+#ifdef DD_DEBUG
+    assert(x < y);
+    assert(cuddNextHigh(table,x) == y);
+    assert(table->subtables[x].keys != 0);
+    assert(table->subtables[y].keys != 0);
+    assert(table->subtables[x].dead == 0);
+    assert(table->subtables[y].dead == 0);
+#endif
+
+    xindex = table->invperm[x];
+    yindex = table->invperm[y];
+
+    if (cuddTestInteract(table,xindex,yindex)) {
+#ifdef DD_STATS
+        ddTotalNumberLinearTr++;
+#endif
+        /* Get parameters of x subtable. */
+        xlist = table->subtables[x].nodelist;
+        oldxkeys = table->subtables[x].keys;
+        xslots = table->subtables[x].slots;
+        xshift = table->subtables[x].shift;
+
+        /* Get parameters of y subtable. */
+        ylist = table->subtables[y].nodelist;
+        oldykeys = table->subtables[y].keys;
+        yslots = table->subtables[y].slots;
+        yshift = table->subtables[y].shift;
+
+        newxkeys = 0;
+        newykeys = oldykeys;
+
+        /* Check whether the two projection functions involved in this
+        ** swap are isolated. At the end, we'll be able to tell how many
+        ** isolated projection functions are there by checking only these
+        ** two functions again. This is done to eliminate the isolated
+        ** projection functions from the node count.
+        */
+        isolated = - ((table->vars[xindex]->ref == 1) +
+                     (table->vars[yindex]->ref == 1));
+
+        /* The nodes in the x layer are put in a chain.
+        ** The chain is handled as a FIFO; g points to the beginning and
+        ** last points to the end.
+        */
+        g = NULL;
+#ifdef DD_DEBUG
+        last = NULL;
+#endif
+        for (i = 0; i < xslots; i++) {
+            f = xlist[i];
+            if (f == sentinel) continue;
+            xlist[i] = sentinel;
+            if (g == NULL) {
+                g = f;
+            } else {
+                last->next = f;
+            }
+            while ((next = f->next) != sentinel) {
+                f = next;
+            } /* while there are elements in the collision chain */
+            last = f;
+        } /* for each slot of the x subtable */
+#ifdef DD_DEBUG
+        /* last is always assigned in the for loop because there is at
+        ** least one key */
+        assert(last != NULL);
+#endif
+        last->next = NULL;
+
+#ifdef DD_COUNT
+        table->swapSteps += oldxkeys;
+#endif
+        /* Take care of the x nodes that must be re-expressed.
+        ** They form a linked list pointed by g.
+        */
+        f = g;
+        while (f != NULL) {
+            next = f->next;
+            /* Find f1, f0, f11, f10, f01, f00. */
+            f1 = cuddT(f);
+#ifdef DD_DEBUG
+            assert(!(Cudd_IsComplement(f1)));
+#endif
+            if ((int) f1->index == yindex) {
+                f11 = cuddT(f1); f10 = cuddE(f1);
+            } else {
+                f11 = f10 = f1;
+            }
+#ifdef DD_DEBUG
+            assert(!(Cudd_IsComplement(f11)));
+#endif
+            f0 = cuddE(f);
+            comple = Cudd_IsComplement(f0);
+            f0 = Cudd_Regular(f0);
+            if ((int) f0->index == yindex) {
+                f01 = cuddT(f0); f00 = cuddE(f0);
+            } else {
+                f01 = f00 = f0;
+            }
+            if (comple) {
+                f01 = Cudd_Not(f01);
+                f00 = Cudd_Not(f00);
+            }
+            /* Decrease ref count of f1. */
+            cuddSatDec(f1->ref);
+            /* Create the new T child. */
+            if (f11 == f00) {
+                newf1 = f11;
+                cuddSatInc(newf1->ref);
+            } else {
+                /* Check ylist for triple (yindex,f11,f00). */
+                posn = ddHash(cuddF2L(f11), cuddF2L(f00), yshift);
+                /* For each element newf1 in collision list ylist[posn]. */
+                previousP = &(ylist[posn]);
+                newf1 = *previousP;
+                while (f11 < cuddT(newf1)) {
+                    previousP = &(newf1->next);
+                    newf1 = *previousP;
+                }
+                while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) {
+                    previousP = &(newf1->next);
+                    newf1 = *previousP;
+                }
+                if (cuddT(newf1) == f11 && cuddE(newf1) == f00) {
+                    cuddSatInc(newf1->ref);
+                } else { /* no match */
+                    newf1 = cuddDynamicAllocNode(table);
+                    if (newf1 == NULL)
+                        goto cuddLinearOutOfMem;
+                    newf1->index = yindex; newf1->ref = 1;
+                    cuddT(newf1) = f11;
+                    cuddE(newf1) = f00;
+                    /* Insert newf1 in the collision list ylist[posn];
+                    ** increase the ref counts of f11 and f00.
+                    */
+                    newykeys++;
+                    newf1->next = *previousP;
+                    *previousP = newf1;
+                    cuddSatInc(f11->ref);
+                    tmp = Cudd_Regular(f00);
+                    cuddSatInc(tmp->ref);
+                }
+            }
+            cuddT(f) = newf1;
+#ifdef DD_DEBUG
+            assert(!(Cudd_IsComplement(newf1)));
+#endif
+
+            /* Do the same for f0, keeping complement dots into account. */
+            /* decrease ref count of f0 */
+            tmp = Cudd_Regular(f0);
+            cuddSatDec(tmp->ref);
+            /* create the new E child */
+            if (f01 == f10) {
+                newf0 = f01;
+                tmp = Cudd_Regular(newf0);
+                cuddSatInc(tmp->ref);
+            } else {
+                /* make sure f01 is regular */
+                newcomplement = Cudd_IsComplement(f01);
+                if (newcomplement) {
+                    f01 = Cudd_Not(f01);
+                    f10 = Cudd_Not(f10);
+                }
+                /* Check ylist for triple (yindex,f01,f10). */
+                posn = ddHash(cuddF2L(f01), cuddF2L(f10), yshift);
+                /* For each element newf0 in collision list ylist[posn]. */
+                previousP = &(ylist[posn]);
+                newf0 = *previousP;
+                while (f01 < cuddT(newf0)) {
+                    previousP = &(newf0->next);
+                    newf0 = *previousP;
+                }
+                while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) {
+                    previousP = &(newf0->next);
+                    newf0 = *previousP;
+                }
+                if (cuddT(newf0) == f01 && cuddE(newf0) == f10) {
+                    cuddSatInc(newf0->ref);
+                } else { /* no match */
+                    newf0 = cuddDynamicAllocNode(table);
+                    if (newf0 == NULL)
+                        goto cuddLinearOutOfMem;
+                    newf0->index = yindex; newf0->ref = 1;
+                    cuddT(newf0) = f01;
+                    cuddE(newf0) = f10;
+                    /* Insert newf0 in the collision list ylist[posn];
+                    ** increase the ref counts of f01 and f10.
+                    */
+                    newykeys++;
+                    newf0->next = *previousP;
+                    *previousP = newf0;
+                    cuddSatInc(f01->ref);
+                    tmp = Cudd_Regular(f10);
+                    cuddSatInc(tmp->ref);
+                }
+                if (newcomplement) {
+                    newf0 = Cudd_Not(newf0);
+                }
+            }
+            cuddE(f) = newf0;
+
+            /* Re-insert the modified f in xlist.
+            ** The modified f does not already exists in xlist.
+            ** (Because of the uniqueness of the cofactors.)
+            */
+            posn = ddHash(cuddF2L(newf1), cuddF2L(newf0), xshift);
+            newxkeys++;
+            previousP = &(xlist[posn]);
+            tmp = *previousP;
+            while (newf1 < cuddT(tmp)) {
+                previousP = &(tmp->next);
+                tmp = *previousP;
+            }
+            while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
+                previousP = &(tmp->next);
+                tmp = *previousP;
+            }
+            f->next = *previousP;
+            *previousP = f;
+            f = next;
+        } /* while f != NULL */
+
+        /* GC the y layer. */
+
+        /* For each node f in ylist. */
+        for (i = 0; i < yslots; i++) {
+            previousP = &(ylist[i]);
+            f = *previousP;
+            while (f != sentinel) {
+                next = f->next;
+                if (f->ref == 0) {
+                    tmp = cuddT(f);
+                    cuddSatDec(tmp->ref);
+                    tmp = Cudd_Regular(cuddE(f));
+                    cuddSatDec(tmp->ref);
+                    cuddDeallocNode(table,f);
+                    newykeys--;
+                } else {
+                    *previousP = f;
+                    previousP = &(f->next);
+                }
+                f = next;
+            } /* while f */
+            *previousP = sentinel;
+        } /* for every collision list */
+
+#ifdef DD_DEBUG
+#if 0
+        (void) fprintf(table->out,"Linearly combining %d and %d\n",x,y);
+#endif
+        count = 0;
+        idcheck = 0;
+        for (i = 0; i < yslots; i++) {
+            f = ylist[i];
+            while (f != sentinel) {
+                count++;
+                if (f->index != (DdHalfWord) yindex)
+                    idcheck++;
+                f = f->next;
+            }
+        }
+        if (count != newykeys) {
+            fprintf(table->err,"Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",oldykeys,newykeys,count);
+        }
+        if (idcheck != 0)
+            fprintf(table->err,"Error in id's of ylist\twrong id's = %d\n",idcheck);
+        count = 0;
+        idcheck = 0;
+        for (i = 0; i < xslots; i++) {
+            f = xlist[i];
+            while (f != sentinel) {
+                count++;
+                if (f->index != (DdHalfWord) xindex)
+                    idcheck++;
+                f = f->next;
+            }
+        }
+        if (count != newxkeys || newxkeys != oldxkeys) {
+            fprintf(table->err,"Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",oldxkeys,newxkeys,count);
+        }
+        if (idcheck != 0)
+            fprintf(table->err,"Error in id's of xlist\twrong id's = %d\n",idcheck);
+#endif
+
+        isolated += (table->vars[xindex]->ref == 1) +
+                    (table->vars[yindex]->ref == 1);
+        table->isolated += isolated;
+
+        /* Set the appropriate fields in table. */
+        table->subtables[y].keys = newykeys;
+
+        /* Here we should update the linear combination table
+        ** to record that x <- x EXNOR y. This is done by complementing
+        ** the (x,y) entry of the table.
+        */
+
+        table->keys += newykeys - oldykeys;
+
+        cuddXorLinear(table,xindex,yindex);
+    }
+
+#ifdef DD_DEBUG
+    if (zero) {
+        (void) Cudd_DebugCheck(table);
+    }
+#endif
+
+    return(table->keys - table->isolated);
+
+cuddLinearOutOfMem:
+    (void) fprintf(table->err,"Error: cuddLinearInPlace out of memory\n");
+
+    return (0);
+
+} /* end of cuddLinearInPlace */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Updates the interaction matrix.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddUpdateInteractionMatrix(
+  DdManager * table,
+  int  xindex,
+  int  yindex)
+{
+    int i;
+    for (i = 0; i < yindex; i++) {
+        if (i != xindex && cuddTestInteract(table,i,yindex)) {
+            if (i < xindex) {
+                cuddSetInteract(table,i,xindex);
+            } else {
+                cuddSetInteract(table,xindex,i);
+            }
+        }
+    }
+    for (i = yindex+1; i < table->size; i++) {
+        if (i != xindex && cuddTestInteract(table,yindex,i)) {
+            if (i < xindex) {
+                cuddSetInteract(table,i,xindex);
+            } else {
+                cuddSetInteract(table,xindex,i);
+            }
+        }
+    }
+
+} /* end of cuddUpdateInteractionMatrix */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the linear transform matrix.]
+
+  Description [Initializes the linear transform matrix.  Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddInitLinear(
+  DdManager * table)
+{
+    int words;
+    int wordsPerRow;
+    int nvars;
+    int word;
+    int bit;
+    int i;
+    long *linear;
+
+    nvars = table->size;
+    wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
+    words = wordsPerRow * nvars;
+    table->linear = linear = ABC_ALLOC(long,words);
+    if (linear == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    table->memused += words * sizeof(long);
+    table->linearSize = nvars;
+    for (i = 0; i < words; i++) linear[i] = 0;
+    for (i = 0; i < nvars; i++) {
+        word = wordsPerRow * i + (i >> LOGBPL);
+        bit  = i & (BPL-1);
+        linear[word] = 1 << bit;
+    }
+    return(1);
+
+} /* end of cuddInitLinear */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resizes the linear transform matrix.]
+
+  Description [Resizes the linear transform matrix.  Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddResizeLinear(
+  DdManager * table)
+{
+    int words,oldWords;
+    int wordsPerRow,oldWordsPerRow;
+    int nvars,oldNvars;
+    int word,oldWord;
+    int bit;
+    int i,j;
+    long *linear,*oldLinear;
+
+    oldNvars = table->linearSize;
+    oldWordsPerRow = ((oldNvars - 1) >> LOGBPL) + 1;
+    oldWords = oldWordsPerRow * oldNvars;
+    oldLinear = table->linear;
+
+    nvars = table->size;
+    wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
+    words = wordsPerRow * nvars;
+    table->linear = linear = ABC_ALLOC(long,words);
+    if (linear == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    table->memused += (words - oldWords) * sizeof(long);
+    for (i = 0; i < words; i++) linear[i] = 0;
+
+    /* Copy old matrix. */
+    for (i = 0; i < oldNvars; i++) {
+        for (j = 0; j < oldWordsPerRow; j++) {
+            oldWord = oldWordsPerRow * i + j;
+            word = wordsPerRow * i + j;
+            linear[word] = oldLinear[oldWord];
+        }
+    }
+    ABC_FREE(oldLinear);
+
+    /* Add elements to the diagonal. */
+    for (i = oldNvars; i < nvars; i++) {
+        word = wordsPerRow * i + (i >> LOGBPL);
+        bit  = i & (BPL-1);
+        linear[word] = 1 << bit;
+    }
+    table->linearSize = nvars;
+
+    return(1);
+
+} /* end of cuddResizeLinear */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison function used by qsort.]
+
+  Description [Comparison function used by qsort to order the
+  variables according to the number of keys in the subtables.
+  Returns the difference in number of keys between the two
+  variables being compared.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddLinearUniqueCompare(
+  int * ptrX,
+  int * ptrY)
+{
+#if 0
+    if (entry[*ptrY] == entry[*ptrX]) {
+        return((*ptrX) - (*ptrY));
+    }
+#endif
+    return(entry[*ptrY] - entry[*ptrX]);
+
+} /* end of ddLinearUniqueCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries.]
+
+  Description [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries. At each step a linear transformation is tried, and, if it
+  decreases the size of the DD, it is accepted. Finds the best position
+  and does the required changes.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddLinearAndSiftingAux(
+  DdManager * table,
+  int  x,
+  int  xLow,
+  int  xHigh)
+{
+
+    Move        *move;
+    Move        *moveUp;                /* list of up moves */
+    Move        *moveDown;              /* list of down moves */
+    int         initialSize;
+    int         result;
+
+    initialSize = table->keys - table->isolated;
+
+    moveDown = NULL;
+    moveUp = NULL;
+
+    if (x == xLow) {
+        moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
+        /* At this point x --> xHigh unless bounding occurred. */
+        if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
+        /* Move backward and stop at best position. */
+        result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
+        if (!result) goto ddLinearAndSiftingAuxOutOfMem;
+
+    } else if (x == xHigh) {
+        moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
+        /* At this point x --> xLow unless bounding occurred. */
+        if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
+        /* Move backward and stop at best position. */
+        result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
+        if (!result) goto ddLinearAndSiftingAuxOutOfMem;
+
+    } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
+        moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
+        /* At this point x --> xHigh unless bounding occurred. */
+        if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
+        moveUp = ddUndoMoves(table,moveDown);
+#ifdef DD_DEBUG
+        assert(moveUp == NULL || moveUp->x == x);
+#endif
+        moveUp = ddLinearAndSiftingUp(table,x,xLow,moveUp);
+        if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
+        /* Move backward and stop at best position. */
+        result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
+        if (!result) goto ddLinearAndSiftingAuxOutOfMem;
+
+    } else { /* must go up first: shorter */
+        moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
+        /* At this point x --> xLow unless bounding occurred. */
+        if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
+        moveDown = ddUndoMoves(table,moveUp);
+#ifdef DD_DEBUG
+        assert(moveDown == NULL || moveDown->y == x);
+#endif
+        moveDown = ddLinearAndSiftingDown(table,x,xHigh,moveDown);
+        if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
+        /* Move backward and stop at best position. */
+        result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
+        if (!result) goto ddLinearAndSiftingAuxOutOfMem;
+    }
+
+    while (moveDown != NULL) {
+        move = moveDown->next;
+        cuddDeallocMove(table, moveDown);
+        moveDown = move;
+    }
+    while (moveUp != NULL) {
+        move = moveUp->next;
+        cuddDeallocMove(table, moveUp);
+        moveUp = move;
+    }
+
+    return(1);
+
+ddLinearAndSiftingAuxOutOfMem:
+    while (moveDown != NULL) {
+        move = moveDown->next;
+        cuddDeallocMove(table, moveDown);
+        moveDown = move;
+    }
+    while (moveUp != NULL) {
+        move = moveUp->next;
+        cuddDeallocMove(table, moveUp);
+        moveUp = move;
+    }
+
+    return(0);
+
+} /* end of ddLinearAndSiftingAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts a variable up and applies linear transformations.]
+
+  Description [Sifts a variable up and applies linear transformations.
+  Moves y up until either it reaches the bound (xLow) or the size of
+  the DD heap increases too much.  Returns the set of moves in case of
+  success; NULL if memory is full.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move *
+ddLinearAndSiftingUp(
+  DdManager * table,
+  int  y,
+  int  xLow,
+  Move * prevMoves)
+{
+    Move        *moves;
+    Move        *move;
+    int         x;
+    int         size, newsize;
+    int         limitSize;
+    int         xindex, yindex;
+    int         isolated;
+    int         L;      /* lower bound on DD size */
+#ifdef DD_DEBUG
+    int checkL;
+    int z;
+    int zindex;
+#endif
+
+    moves = prevMoves;
+    yindex = table->invperm[y];
+
+    /* Initialize the lower bound.
+    ** The part of the DD below y will not change.
+    ** The part of the DD above y that does not interact with y will not
+    ** change. The rest may vanish in the best case, except for
+    ** the nodes at level xLow, which will not vanish, regardless.
+    */
+    limitSize = L = table->keys - table->isolated;
+    for (x = xLow + 1; x < y; x++) {
+        xindex = table->invperm[x];
+        if (cuddTestInteract(table,xindex,yindex)) {
+            isolated = table->vars[xindex]->ref == 1;
+            L -= table->subtables[x].keys - isolated;
+        }
+    }
+    isolated = table->vars[yindex]->ref == 1;
+    L -= table->subtables[y].keys - isolated;
+
+    x = cuddNextLow(table,y);
+    while (x >= xLow && L <= limitSize) {
+        xindex = table->invperm[x];
+#ifdef DD_DEBUG
+        checkL = table->keys - table->isolated;
+        for (z = xLow + 1; z < y; z++) {
+            zindex = table->invperm[z];
+            if (cuddTestInteract(table,zindex,yindex)) {
+                isolated = table->vars[zindex]->ref == 1;
+                checkL -= table->subtables[z].keys - isolated;
+            }
+        }
+        isolated = table->vars[yindex]->ref == 1;
+        checkL -= table->subtables[y].keys - isolated;
+        if (L != checkL) {
+            (void) fprintf(table->out, "checkL(%d) != L(%d)\n",checkL,L);
+        }
+#endif
+        size = cuddSwapInPlace(table,x,y);
+        if (size == 0) goto ddLinearAndSiftingUpOutOfMem;
+        newsize = cuddLinearInPlace(table,x,y);
+        if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
+        move = (Move *) cuddDynamicAllocNode(table);
+        if (move == NULL) goto ddLinearAndSiftingUpOutOfMem;
+        move->x = x;
+        move->y = y;
+        move->next = moves;
+        moves = move;
+        move->flags = CUDD_SWAP_MOVE;
+        if (newsize >= size) {
+            /* Undo transformation. The transformation we apply is
+            ** its own inverse. Hence, we just apply the transformation
+            ** again.
+            */
+            newsize = cuddLinearInPlace(table,x,y);
+            if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
+#ifdef DD_DEBUG
+            if (newsize != size) {
+                (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
+            }
+#endif
+        } else if (cuddTestInteract(table,xindex,yindex)) {
+            size = newsize;
+            move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
+            cuddUpdateInteractionMatrix(table,xindex,yindex);
+        }
+        move->size = size;
+        /* Update the lower bound. */
+        if (cuddTestInteract(table,xindex,yindex)) {
+            isolated = table->vars[xindex]->ref == 1;
+            L += table->subtables[y].keys - isolated;
+        }
+        if ((double) size > (double) limitSize * table->maxGrowth) break;
+        if (size < limitSize) limitSize = size;
+        y = x;
+        x = cuddNextLow(table,y);
+    }
+    return(moves);
+
+ddLinearAndSiftingUpOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return((Move *) CUDD_OUT_OF_MEM);
+
+} /* end of ddLinearAndSiftingUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts a variable down and applies linear transformations.]
+
+  Description [Sifts a variable down and applies linear
+  transformations. Moves x down until either it reaches the bound
+  (xHigh) or the size of the DD heap increases too much. Returns the
+  set of moves in case of success; NULL if memory is full.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move *
+ddLinearAndSiftingDown(
+  DdManager * table,
+  int  x,
+  int  xHigh,
+  Move * prevMoves)
+{
+    Move        *moves;
+    Move        *move;
+    int         y;
+    int         size, newsize;
+    int         R;      /* upper bound on node decrease */
+    int         limitSize;
+    int         xindex, yindex;
+    int         isolated;
+#ifdef DD_DEBUG
+    int         checkR;
+    int         z;
+    int         zindex;
+#endif
+
+    moves = prevMoves;
+    /* Initialize R */
+    xindex = table->invperm[x];
+    limitSize = size = table->keys - table->isolated;
+    R = 0;
+    for (y = xHigh; y > x; y--) {
+        yindex = table->invperm[y];
+        if (cuddTestInteract(table,xindex,yindex)) {
+            isolated = table->vars[yindex]->ref == 1;
+            R += table->subtables[y].keys - isolated;
+        }
+    }
+
+    y = cuddNextHigh(table,x);
+    while (y <= xHigh && size - R < limitSize) {
+#ifdef DD_DEBUG
+        checkR = 0;
+        for (z = xHigh; z > x; z--) {
+            zindex = table->invperm[z];
+            if (cuddTestInteract(table,xindex,zindex)) {
+                isolated = table->vars[zindex]->ref == 1;
+                checkR += table->subtables[z].keys - isolated;
+            }
+        }
+        if (R != checkR) {
+            (void) fprintf(table->out, "checkR(%d) != R(%d)\n",checkR,R);
+        }
+#endif
+        /* Update upper bound on node decrease. */
+        yindex = table->invperm[y];
+        if (cuddTestInteract(table,xindex,yindex)) {
+            isolated = table->vars[yindex]->ref == 1;
+            R -= table->subtables[y].keys - isolated;
+        }
+        size = cuddSwapInPlace(table,x,y);
+        if (size == 0) goto ddLinearAndSiftingDownOutOfMem;
+        newsize = cuddLinearInPlace(table,x,y);
+        if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
+        move = (Move *) cuddDynamicAllocNode(table);
+        if (move == NULL) goto ddLinearAndSiftingDownOutOfMem;
+        move->x = x;
+        move->y = y;
+        move->next = moves;
+        moves = move;
+        move->flags = CUDD_SWAP_MOVE;
+        if (newsize >= size) {
+            /* Undo transformation. The transformation we apply is
+            ** its own inverse. Hence, we just apply the transformation
+            ** again.
+            */
+            newsize = cuddLinearInPlace(table,x,y);
+            if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
+            if (newsize != size) {
+                (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
+            }
+        } else if (cuddTestInteract(table,xindex,yindex)) {
+            size = newsize;
+            move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
+            cuddUpdateInteractionMatrix(table,xindex,yindex);
+        }
+        move->size = size;
+        if ((double) size > (double) limitSize * table->maxGrowth) break;
+        if (size < limitSize) limitSize = size;
+        x = y;
+        y = cuddNextHigh(table,x);
+    }
+    return(moves);
+
+ddLinearAndSiftingDownOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return((Move *) CUDD_OUT_OF_MEM);
+
+} /* end of ddLinearAndSiftingDown */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given a set of moves, returns the DD heap to the order
+  giving the minimum size.]
+
+  Description [Given a set of moves, returns the DD heap to the
+  position giving the minimum size. In case of ties, returns to the
+  closest position giving the minimum size. Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddLinearAndSiftingBackward(
+  DdManager * table,
+  int  size,
+  Move * moves)
+{
+    Move *move;
+    int res;
+
+    for (move = moves; move != NULL; move = move->next) {
+        if (move->size < size) {
+            size = move->size;
+        }
+    }
+
+    for (move = moves; move != NULL; move = move->next) {
+        if (move->size == size) return(1);
+        if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
+            res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
+            if (!res) return(0);
+        }
+        res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
+        if (!res) return(0);
+        if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) {
+            res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
+            if (!res) return(0);
+        }
+    }
+
+    return(1);
+
+} /* end of ddLinearAndSiftingBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given a set of moves, returns the DD heap to the order
+  in effect before the moves.]
+
+  Description [Given a set of moves, returns the DD heap to the
+  order in effect before the moves.  Returns 1 in case of success;
+  0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move*
+ddUndoMoves(
+  DdManager * table,
+  Move * moves)
+{
+    Move *invmoves = NULL;
+    Move *move;
+    Move *invmove;
+    int size;
+
+    for (move = moves; move != NULL; move = move->next) {
+        invmove = (Move *) cuddDynamicAllocNode(table);
+        if (invmove == NULL) goto ddUndoMovesOutOfMem;
+        invmove->x = move->x;
+        invmove->y = move->y;
+        invmove->next = invmoves;
+        invmoves = invmove;
+        if (move->flags == CUDD_SWAP_MOVE) {
+            invmove->flags = CUDD_SWAP_MOVE;
+            size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
+            if (!size) goto ddUndoMovesOutOfMem;
+        } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
+            invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE;
+            size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
+            if (!size) goto ddUndoMovesOutOfMem;
+            size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
+            if (!size) goto ddUndoMovesOutOfMem;
+        } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */
+#ifdef DD_DEBUG
+            (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n");
+#endif
+            invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE;
+            size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
+            if (!size) goto ddUndoMovesOutOfMem;
+            size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
+            if (!size) goto ddUndoMovesOutOfMem;
+        }
+        invmove->size = size;
+    }
+
+    return(invmoves);
+
+ddUndoMovesOutOfMem:
+    while (invmoves != NULL) {
+        move = invmoves->next;
+        cuddDeallocMove(table, invmoves);
+        invmoves = move;
+    }
+    return((Move *) CUDD_OUT_OF_MEM);
+
+} /* end of ddUndoMoves */
+
+
+/**Function********************************************************************
+
+  Synopsis    [XORs two rows of the linear transform matrix.]
+
+  Description [XORs two rows of the linear transform matrix and replaces
+  the first row with the result.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+cuddXorLinear(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int i;
+    int nvars = table->size;
+    int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
+    int xstart = wordsPerRow * x;
+    int ystart = wordsPerRow * y;
+    long *linear = table->linear;
+
+    for (i = 0; i < wordsPerRow; i++) {
+        linear[xstart+i] ^= linear[ystart+i];
+    }
+
+} /* end of cuddXorLinear */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddLiteral.c b/abc-build/src/bdd/cudd/cuddLiteral.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddLiteral.c
@@ -0,0 +1,272 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddLiteral.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for manipulation of literal sets represented by
+  BDDs.]
+
+  Description [External procedures included in this file:
+                <ul>
+                <li> Cudd_bddLiteralSetIntersection()
+                </ul>
+            Internal procedures included in this file:
+                <ul>
+                <li> cuddBddLiteralSetIntersectionRecur()
+                </ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddLiteral.c,v 1.8 2004/08/13 18:04:50 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the intesection of two sets of literals
+  represented as BDDs.]
+
+  Description [Computes the intesection of two sets of literals
+  represented as BDDs. Each set is represented as a cube of the
+  literals in the set. The empty set is represented by the constant 1.
+  No variable can be simultaneously present in both phases in a set.
+  Returns a pointer to the BDD representing the intersected sets, if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+Cudd_bddLiteralSetIntersection(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddLiteralSetIntersectionRecur(dd,f,g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddLiteralSetIntersection */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of
+  Cudd_bddLiteralSetIntersection.]
+
+  Description [Performs the recursive step of
+  Cudd_bddLiteralSetIntersection. Scans the cubes for common variables,
+  and checks whether they agree in phase.  Returns a pointer to the
+  resulting cube if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+cuddBddLiteralSetIntersectionRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res, *tmp;
+    DdNode *F, *G;
+    DdNode *fc, *gc;
+    DdNode *one;
+    DdNode *zero;
+    unsigned int topf, topg, comple;
+    int phasef, phaseg;
+
+    statLine(dd);
+    if (f == g) return(f);
+
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    one = DD_ONE(dd);
+
+    /* Here f != g. If F == G, then f and g are complementary.
+    ** Since they are two cubes, this case only occurs when f == v,
+    ** g == v', and v is a variable or its complement.
+    */
+    if (F == G) return(one);
+
+    zero = Cudd_Not(one);
+    topf = cuddI(dd,F->index);
+    topg = cuddI(dd,G->index);
+    /* Look for a variable common to both cubes. If there are none, this
+    ** loop will stop when the constant node is reached in both cubes.
+    */
+    while (topf != topg) {
+        if (topf < topg) {      /* move down on f */
+            comple = f != F;
+            f = cuddT(F);
+            if (comple) f = Cudd_Not(f);
+            if (f == zero) {
+                f = cuddE(F);
+                if (comple) f = Cudd_Not(f);
+            }
+            F = Cudd_Regular(f);
+            topf = cuddI(dd,F->index);
+        } else if (topg < topf) {
+            comple = g != G;
+            g = cuddT(G);
+            if (comple) g = Cudd_Not(g);
+            if (g == zero) {
+                g = cuddE(G);
+                if (comple) g = Cudd_Not(g);
+            }
+            G = Cudd_Regular(g);
+            topg = cuddI(dd,G->index);
+        }
+    }
+
+    /* At this point, f == one <=> g == 1. It suffices to test one of them. */
+    if (f == one) return(one);
+
+    res = cuddCacheLookup2(dd,Cudd_bddLiteralSetIntersection,f,g);
+    if (res != NULL) {
+        return(res);
+    }
+
+    /* Here f and g are both non constant and have the same top variable. */
+    comple = f != F;
+    fc = cuddT(F);
+    phasef = 1;
+    if (comple) fc = Cudd_Not(fc);
+    if (fc == zero) {
+        fc = cuddE(F);
+        phasef = 0;
+        if (comple) fc = Cudd_Not(fc);
+    }
+    comple = g != G;
+    gc = cuddT(G);
+    phaseg = 1;
+    if (comple) gc = Cudd_Not(gc);
+    if (gc == zero) {
+        gc = cuddE(G);
+        phaseg = 0;
+        if (comple) gc = Cudd_Not(gc);
+    }
+
+    tmp = cuddBddLiteralSetIntersectionRecur(dd,fc,gc);
+    if (tmp == NULL) {
+        return(NULL);
+    }
+
+    if (phasef != phaseg) {
+        res = tmp;
+    } else {
+        cuddRef(tmp);
+        if (phasef == 0) {
+            res = cuddBddAndRecur(dd,Cudd_Not(dd->vars[F->index]),tmp);
+        } else {
+            res = cuddBddAndRecur(dd,dd->vars[F->index],tmp);
+        }
+        if (res == NULL) {
+            Cudd_RecursiveDeref(dd,tmp);
+            return(NULL);
+        }
+        cuddDeref(tmp); /* Just cuddDeref, because it is included in result */
+    }
+
+    cuddCacheInsert2(dd,Cudd_bddLiteralSetIntersection,f,g,res);
+
+    return(res);
+
+} /* end of cuddBddLiteralSetIntersectionRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddMatMult.c b/abc-build/src/bdd/cudd/cuddMatMult.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddMatMult.c
@@ -0,0 +1,715 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddMatMult.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Matrix multiplication functions.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_addMatrixMultiply()
+                <li> Cudd_addTimesPlus()
+                <li> Cudd_addTriangle()
+                <li> Cudd_addOuterSum()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> addMMRecur()
+                <li> addTriangleRecur()
+                <li> cuddAddOuterSumRecur()
+                </ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddMatMult.c,v 1.17 2004/08/13 18:04:50 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * addMMRecur (DdManager *dd, DdNode *A, DdNode *B, int topP, int *vars);
+static DdNode * addTriangleRecur (DdManager *dd, DdNode *f, DdNode *g, int *vars, DdNode *cube);
+static DdNode * cuddAddOuterSumRecur (DdManager *dd, DdNode *M, DdNode *r, DdNode *c);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Calculates the product of two matrices represented as
+  ADDs.]
+
+  Description [Calculates the product of two matrices, A and B,
+  represented as ADDs. This procedure implements the quasiring multiplication
+  algorithm.  A is assumed to depend on variables x (rows) and z
+  (columns).  B is assumed to depend on variables z (rows) and y
+  (columns).  The product of A and B then depends on x (rows) and y
+  (columns).  Only the z variables have to be explicitly identified;
+  they are the "summation" variables.  Returns a pointer to the
+  result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addTimesPlus Cudd_addTriangle Cudd_bddAndAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_addMatrixMultiply(
+  DdManager * dd,
+  DdNode * A,
+  DdNode * B,
+  DdNode ** z,
+  int  nz)
+{
+    int i, nvars, *vars;
+    DdNode *res; 
+
+    /* Array vars says what variables are "summation" variables. */
+    nvars = dd->size;
+    vars = ABC_ALLOC(int,nvars);
+    if (vars == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    for (i = 0; i < nvars; i++) {
+        vars[i] = 0;
+    }
+    for (i = 0; i < nz; i++) {
+        vars[z[i]->index] = 1;
+    }
+
+    do {
+        dd->reordered = 0;
+        res = addMMRecur(dd,A,B,-1,vars);
+    } while (dd->reordered == 1);
+    ABC_FREE(vars);
+    return(res);
+
+} /* end of Cudd_addMatrixMultiply */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Calculates the product of two matrices represented as
+  ADDs.]
+
+  Description [Calculates the product of two matrices, A and B,
+  represented as ADDs, using the CMU matrix by matrix multiplication
+  procedure by Clarke et al..  Matrix A has x's as row variables and z's
+  as column variables, while matrix B has z's as row variables and y's
+  as column variables. Returns the pointer to the result if successful;
+  NULL otherwise. The resulting matrix has x's as row variables and y's
+  as column variables.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addMatrixMultiply]
+
+******************************************************************************/
+DdNode *
+Cudd_addTimesPlus(
+  DdManager * dd,
+  DdNode * A,
+  DdNode * B,
+  DdNode ** z,
+  int  nz)
+{
+    DdNode *w, *cube, *tmp, *res; 
+    int i;
+    tmp = Cudd_addApply(dd,Cudd_addTimes,A,B);
+    if (tmp == NULL) return(NULL);
+    Cudd_Ref(tmp);
+    Cudd_Ref(cube = DD_ONE(dd));
+    for (i = nz-1; i >= 0; i--) {
+         w = Cudd_addIte(dd,z[i],cube,DD_ZERO(dd));
+         if (w == NULL) {
+            Cudd_RecursiveDeref(dd,tmp);
+            return(NULL);
+         }
+         Cudd_Ref(w);
+         Cudd_RecursiveDeref(dd,cube);
+         cube = w;
+    }
+    res = Cudd_addExistAbstract(dd,tmp,cube);
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd,tmp);
+        Cudd_RecursiveDeref(dd,cube);
+        return(NULL);
+    }
+    Cudd_Ref(res);
+    Cudd_RecursiveDeref(dd,cube);
+    Cudd_RecursiveDeref(dd,tmp);
+    Cudd_Deref(res);
+    return(res);
+
+} /* end of Cudd_addTimesPlus */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the triangulation step for the shortest path
+  computation.]
+
+  Description [Implements the semiring multiplication algorithm used in
+  the triangulation step for the shortest path computation.  f
+  is assumed to depend on variables x (rows) and z (columns).  g is
+  assumed to depend on variables z (rows) and y (columns).  The product
+  of f and g then depends on x (rows) and y (columns).  Only the z
+  variables have to be explicitly identified; they are the
+  "abstraction" variables.  Returns a pointer to the result if
+  successful; NULL otherwise. ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addMatrixMultiply Cudd_bddAndAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_addTriangle(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode ** z,
+  int  nz)
+{
+    int    i, nvars, *vars;
+    DdNode *res, *cube;
+
+    nvars = dd->size;
+    vars = ABC_ALLOC(int, nvars);
+    if (vars == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    for (i = 0; i < nvars; i++) vars[i] = -1;
+    for (i = 0; i < nz; i++) vars[z[i]->index] = i;
+    cube = Cudd_addComputeCube(dd, z, NULL, nz);
+    if (cube == NULL) {
+        ABC_FREE(vars);
+        return(NULL);
+    }
+    cuddRef(cube);
+
+    do {
+        dd->reordered = 0;
+        res = addTriangleRecur(dd, f, g, vars, cube);
+    } while (dd->reordered == 1);
+    if (res != NULL) cuddRef(res);
+    Cudd_RecursiveDeref(dd,cube);
+    if (res != NULL) cuddDeref(res);
+    ABC_FREE(vars);
+    return(res);
+
+} /* end of Cudd_addTriangle */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Takes the minimum of a matrix and the outer sum of two vectors.]
+
+  Description [Takes the pointwise minimum of a matrix and the outer
+  sum of two vectors.  This procedure is used in the Floyd-Warshall
+  all-pair shortest path algorithm.  Returns a pointer to the result if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_addOuterSum(
+  DdManager *dd,
+  DdNode *M,
+  DdNode *r,
+  DdNode *c)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddAddOuterSumRecur(dd, M, r, c);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addOuterSum */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addMatrixMultiply.]
+
+  Description [Performs the recursive step of Cudd_addMatrixMultiply.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static DdNode *
+addMMRecur(
+  DdManager * dd,
+  DdNode * A,
+  DdNode * B,
+  int  topP,
+  int * vars)
+{
+    DdNode *zero,
+           *At,         /* positive cofactor of first operand */
+           *Ae,         /* negative cofactor of first operand */
+           *Bt,         /* positive cofactor of second operand */
+           *Be,         /* negative cofactor of second operand */
+           *t,          /* positive cofactor of result */
+           *e,          /* negative cofactor of result */
+           *scaled,     /* scaled result */
+           *add_scale,  /* ADD representing the scaling factor */
+           *res;
+    int i;              /* loop index */
+    double scale;       /* scaling factor */
+    int index;          /* index of the top variable */
+    CUDD_VALUE_TYPE value;
+    unsigned int topA, topB, topV;
+    DD_CTFP cacheOp;
+
+    statLine(dd);
+    zero = DD_ZERO(dd);
+
+    if (A == zero || B == zero) {
+        return(zero);
+    }
+
+    if (cuddIsConstant(A) && cuddIsConstant(B)) {
+        /* Compute the scaling factor. It is 2^k, where k is the
+        ** number of summation variables below the current variable.
+        ** Indeed, these constants represent blocks of 2^k identical
+        ** constant values in both A and B.
+        */
+        value = cuddV(A) * cuddV(B);
+        for (i = 0; i < dd->size; i++) {
+            if (vars[i]) {
+                if (dd->perm[i] > topP) {
+                    value *= (CUDD_VALUE_TYPE) 2;
+                }
+            }
+        }
+        res = cuddUniqueConst(dd, value);
+        return(res);
+    }
+
+    /* Standardize to increase cache efficiency. Clearly, A*B != B*A
+    ** in matrix multiplication. However, which matrix is which is
+    ** determined by the variables appearing in the ADDs and not by
+    ** which one is passed as first argument.
+    */
+    if (A > B) {
+        DdNode *tmp = A;
+        A = B;
+        B = tmp;
+    }
+
+    topA = cuddI(dd,A->index); topB = cuddI(dd,B->index);
+    topV = ddMin(topA,topB);
+
+    cacheOp = (DD_CTFP) addMMRecur;
+    res = cuddCacheLookup2(dd,cacheOp,A,B);
+    if (res != NULL) {
+        /* If the result is 0, there is no need to normalize.
+        ** Otherwise we count the number of z variables between
+        ** the current depth and the top of the ADDs. These are
+        ** the missing variables that determine the size of the
+        ** constant blocks.
+        */
+        if (res == zero) return(res);
+        scale = 1.0;
+        for (i = 0; i < dd->size; i++) {
+            if (vars[i]) {
+                if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) {
+                    scale *= 2;
+                }
+            }
+        }
+        if (scale > 1.0) {
+            cuddRef(res);
+            add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale);
+            if (add_scale == NULL) {
+                Cudd_RecursiveDeref(dd, res);
+                return(NULL);
+            }
+            cuddRef(add_scale);
+            scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale);
+            if (scaled == NULL) {
+                Cudd_RecursiveDeref(dd, add_scale);
+                Cudd_RecursiveDeref(dd, res);
+                return(NULL);
+            }
+            cuddRef(scaled);
+            Cudd_RecursiveDeref(dd, add_scale);
+            Cudd_RecursiveDeref(dd, res);
+            res = scaled;
+            cuddDeref(res);
+        }
+        return(res);
+    }
+
+    /* compute the cofactors */
+    if (topV == topA) {
+        At = cuddT(A);
+        Ae = cuddE(A);
+    } else {
+        At = Ae = A;
+    }
+    if (topV == topB) {
+        Bt = cuddT(B);
+        Be = cuddE(B);
+    } else {
+        Bt = Be = B;
+    }
+
+    t = addMMRecur(dd, At, Bt, (int)topV, vars);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+    e = addMMRecur(dd, Ae, Be, (int)topV, vars);
+    if (e == NULL) {
+        Cudd_RecursiveDeref(dd, t);
+        return(NULL);
+    }
+    cuddRef(e);
+
+    index = dd->invperm[topV];
+    if (vars[index] == 0) {
+        /* We have split on either the rows of A or the columns
+        ** of B. We just need to connect the two subresults,
+        ** which correspond to two submatrices of the result.
+        */
+        res = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(dd, t);
+            Cudd_RecursiveDeref(dd, e);
+            return(NULL);
+        }
+        cuddRef(res);
+        cuddDeref(t);
+        cuddDeref(e);
+    } else {
+        /* we have simultaneously split on the columns of A and
+        ** the rows of B. The two subresults must be added.
+        */
+        res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(dd, t);
+            Cudd_RecursiveDeref(dd, e);
+            return(NULL);
+        }
+        cuddRef(res);
+        Cudd_RecursiveDeref(dd, t);
+        Cudd_RecursiveDeref(dd, e);
+    }
+
+    cuddCacheInsert2(dd,cacheOp,A,B,res);
+
+    /* We have computed (and stored in the computed table) a minimal
+    ** result; that is, a result that assumes no summation variables
+    ** between the current depth of the recursion and its top
+    ** variable. We now take into account the z variables by properly
+    ** scaling the result.
+    */
+    if (res != zero) {
+        scale = 1.0;
+        for (i = 0; i < dd->size; i++) {
+            if (vars[i]) {
+                if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) {
+                    scale *= 2;
+                }
+            }
+        }
+        if (scale > 1.0) {
+            add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale);
+            if (add_scale == NULL) {
+                Cudd_RecursiveDeref(dd, res);
+                return(NULL);
+            }
+            cuddRef(add_scale);
+            scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale);
+            if (scaled == NULL) {
+                Cudd_RecursiveDeref(dd, res);
+                Cudd_RecursiveDeref(dd, add_scale);
+                return(NULL);
+            }
+            cuddRef(scaled);
+            Cudd_RecursiveDeref(dd, add_scale);
+            Cudd_RecursiveDeref(dd, res);
+            res = scaled;
+        }
+    }
+    cuddDeref(res);
+    return(res);
+
+} /* end of addMMRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addTriangle.]
+
+  Description [Performs the recursive step of Cudd_addTriangle. Returns
+  a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static DdNode *
+addTriangleRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  int * vars,
+  DdNode *cube)
+{
+    DdNode *fv, *fvn, *gv, *gvn, *t, *e, *res;
+    CUDD_VALUE_TYPE value;
+    int top, topf, topg, index;
+
+    statLine(dd);
+    if (f == DD_PLUS_INFINITY(dd) || g == DD_PLUS_INFINITY(dd)) {
+        return(DD_PLUS_INFINITY(dd));
+    }
+
+    if (cuddIsConstant(f) && cuddIsConstant(g)) {
+        value = cuddV(f) + cuddV(g);
+        res = cuddUniqueConst(dd, value);
+        return(res);
+    }
+    if (f < g) {
+        DdNode *tmp = f;
+        f = g;
+        g = tmp;
+    }
+
+    if (f->ref != 1 || g->ref != 1) {
+        res = cuddCacheLookup(dd, DD_ADD_TRIANGLE_TAG, f, g, cube);
+        if (res != NULL) {
+            return(res);
+        }
+    }
+
+    topf = cuddI(dd,f->index); topg = cuddI(dd,g->index);
+    top = ddMin(topf,topg);
+
+    if (top == topf) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;}
+    if (top == topg) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;}
+
+    t = addTriangleRecur(dd, fv, gv, vars, cube);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+    e = addTriangleRecur(dd, fvn, gvn, vars, cube);
+    if (e == NULL) {
+        Cudd_RecursiveDeref(dd, t);
+        return(NULL);
+    }
+    cuddRef(e);
+
+    index = dd->invperm[top];
+    if (vars[index] < 0) {
+        res = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(dd, t);
+            Cudd_RecursiveDeref(dd, e);
+            return(NULL);
+        }
+        cuddDeref(t);
+        cuddDeref(e);
+    } else {
+        res = cuddAddApplyRecur(dd,Cudd_addMinimum,t,e);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(dd, t);
+            Cudd_RecursiveDeref(dd, e);
+            return(NULL);
+        }
+        cuddRef(res);
+        Cudd_RecursiveDeref(dd, t);
+        Cudd_RecursiveDeref(dd, e);
+        cuddDeref(res);
+    }
+
+    if (f->ref != 1 || g->ref != 1) {
+        cuddCacheInsert(dd, DD_ADD_TRIANGLE_TAG, f, g, cube, res);
+    }
+
+    return(res);
+
+} /* end of addTriangleRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addOuterSum.]
+
+  Description [Performs the recursive step of Cudd_addOuterSum.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+cuddAddOuterSumRecur(
+  DdManager *dd,
+  DdNode *M,
+  DdNode *r,
+  DdNode *c)
+{
+    DdNode *P, *R, *Mt, *Me, *rt, *re, *ct, *ce, *Rt, *Re;
+    int topM, topc, topr;
+    int v, index;
+
+    statLine(dd);
+    /* Check special cases. */
+    if (r == DD_PLUS_INFINITY(dd) || c == DD_PLUS_INFINITY(dd)) return(M); 
+
+    if (cuddIsConstant(c) && cuddIsConstant(r)) {
+        R = cuddUniqueConst(dd,Cudd_V(c)+Cudd_V(r));
+        cuddRef(R);
+        if (cuddIsConstant(M)) {
+            if (cuddV(R) <= cuddV(M)) {
+                cuddDeref(R);
+                return(R);
+            } else {
+                Cudd_RecursiveDeref(dd,R);       
+                return(M);
+            }
+        } else {
+            P = Cudd_addApply(dd,Cudd_addMinimum,R,M);
+            cuddRef(P);
+            Cudd_RecursiveDeref(dd,R);
+            cuddDeref(P);
+            return(P);
+        }
+    }
+
+    /* Check the cache. */
+    R = cuddCacheLookup(dd,DD_ADD_OUT_SUM_TAG,M,r,c);
+    if (R != NULL) return(R);
+
+    topM = cuddI(dd,M->index); topr = cuddI(dd,r->index);
+    topc = cuddI(dd,c->index);
+    v = ddMin(topM,ddMin(topr,topc));
+
+    /* Compute cofactors. */
+    if (topM == v) { Mt = cuddT(M); Me = cuddE(M); } else { Mt = Me = M; }
+    if (topr == v) { rt = cuddT(r); re = cuddE(r); } else { rt = re = r; }
+    if (topc == v) { ct = cuddT(c); ce = cuddE(c); } else { ct = ce = c; }
+
+    /* Recursively solve. */
+    Rt = cuddAddOuterSumRecur(dd,Mt,rt,ct);
+    if (Rt == NULL) return(NULL);
+    cuddRef(Rt);
+    Re = cuddAddOuterSumRecur(dd,Me,re,ce);
+    if (Re == NULL) {
+        Cudd_RecursiveDeref(dd, Rt);
+        return(NULL);
+    }
+    cuddRef(Re);
+    index = dd->invperm[v];
+    R = (Rt == Re) ? Rt : cuddUniqueInter(dd,index,Rt,Re);
+    if (R == NULL) {
+        Cudd_RecursiveDeref(dd, Rt);
+        Cudd_RecursiveDeref(dd, Re);
+        return(NULL);
+    }
+    cuddDeref(Rt);
+    cuddDeref(Re);
+
+    /* Store the result in the cache. */
+    cuddCacheInsert(dd,DD_ADD_OUT_SUM_TAG,M,r,c,R);
+
+    return(R);
+
+} /* end of cuddAddOuterSumRecur */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddPriority.c b/abc-build/src/bdd/cudd/cuddPriority.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddPriority.c
@@ -0,0 +1,2035 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddPriority.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Priority functions.]
+
+  Description [External procedures included in this file:
+            <ul>
+            <li> Cudd_PrioritySelect()
+            <li> Cudd_Xgty()
+            <li> Cudd_Xeqy()
+            <li> Cudd_addXeqy()
+            <li> Cudd_Dxygtdxz()
+            <li> Cudd_Dxygtdyz()
+            <li> Cudd_Inequality()
+            <li> Cudd_Disequality()
+            <li> Cudd_bddInterval()
+            <li> Cudd_CProjection()
+            <li> Cudd_addHamming()
+            <li> Cudd_MinHammingDist()
+            <li> Cudd_bddClosestCube()
+            </ul>
+        Internal procedures included in this module:
+            <ul>
+            <li> cuddCProjectionRecur()
+            <li> cuddBddClosestCube()
+            </ul>
+        Static procedures included in this module:
+            <ul>
+            <li> cuddMinHammingDistRecur()
+            <li> separateCube()
+            <li> createResult()
+            </ul>
+            ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DD_DEBUG 1
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddPriority.c,v 1.33 2009/02/20 02:14:58 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+static int cuddMinHammingDistRecur (DdNode * f, int *minterm, DdHashTable * table, int upperBound);
+static DdNode * separateCube (DdManager *dd, DdNode *f, CUDD_VALUE_TYPE *distance);
+static DdNode * createResult (DdManager *dd, unsigned int index, unsigned int phase, DdNode *cube, CUDD_VALUE_TYPE distance);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Selects pairs from R using a priority function.]
+
+  Description [Selects pairs from a relation R(x,y) (given as a BDD)
+  in such a way that a given x appears in one pair only. Uses a
+  priority function to determine which y should be paired to a given x.
+  Cudd_PrioritySelect returns a pointer to
+  the selected function if successful; NULL otherwise.
+  Three of the arguments--x, y, and z--are vectors of BDD variables.
+  The first two are the variables on which R depends. The third vectore
+  is a vector of auxiliary variables, used during the computation. This
+  vector is optional. If a NULL value is passed instead,
+  Cudd_PrioritySelect will create the working variables on the fly.
+  The sizes of x and y (and z if it is not NULL) should equal n.
+  The priority function Pi can be passed as a BDD, or can be built by
+  Cudd_PrioritySelect. If NULL is passed instead of a DdNode *,
+  parameter Pifunc is used by Cudd_PrioritySelect to build a BDD for the
+  priority function. (Pifunc is a pointer to a C function.) If Pi is not
+  NULL, then Pifunc is ignored. Pifunc should have the same interface as
+  the standard priority functions (e.g., Cudd_Dxygtdxz).
+  Cudd_PrioritySelect and Cudd_CProjection can sometimes be used
+  interchangeably. Specifically, calling Cudd_PrioritySelect with
+  Cudd_Xgty as Pifunc produces the same result as calling
+  Cudd_CProjection with the all-zero minterm as reference minterm.
+  However, depending on the application, one or the other may be
+  preferable:
+  <ul>
+  <li> When extracting representatives from an equivalence relation,
+  Cudd_CProjection has the advantage of nor requiring the auxiliary
+  variables.
+  <li> When computing matchings in general bipartite graphs,
+  Cudd_PrioritySelect normally obtains better results because it can use
+  more powerful matching schemes (e.g., Cudd_Dxygtdxz).
+  </ul>
+  ]
+
+  SideEffects [If called with z == NULL, will create new variables in
+  the manager.]
+
+  SeeAlso     [Cudd_Dxygtdxz Cudd_Dxygtdyz Cudd_Xgty
+  Cudd_bddAdjPermuteX Cudd_CProjection]
+
+******************************************************************************/
+DdNode *
+Cudd_PrioritySelect(
+  DdManager * dd /* manager */,
+  DdNode * R /* BDD of the relation */,
+  DdNode ** x /* array of x variables */,
+  DdNode ** y /* array of y variables */,
+  DdNode ** z /* array of z variables (optional: may be NULL) */,
+  DdNode * Pi /* BDD of the priority function (optional: may be NULL) */,
+  int  n /* size of x, y, and z */,
+  DD_PRFP Pifunc /* function used to build Pi if it is NULL */)
+{
+    DdNode *res = NULL;
+    DdNode *zcube = NULL;
+    DdNode *Rxz, *Q;
+    int createdZ = 0;
+    int createdPi = 0;
+    int i;
+
+    /* Create z variables if needed. */
+    if (z == NULL) {
+        if (Pi != NULL) return(NULL);
+        z = ABC_ALLOC(DdNode *,n);
+        if (z == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(NULL);
+        }
+        createdZ = 1;
+        for (i = 0; i < n; i++) {
+            if (dd->size >= (int) CUDD_MAXINDEX - 1) goto endgame;
+            z[i] = cuddUniqueInter(dd,dd->size,dd->one,Cudd_Not(dd->one));
+            if (z[i] == NULL) goto endgame;
+        }
+    }
+
+    /* Create priority function BDD if needed. */
+    if (Pi == NULL) {
+        Pi = Pifunc(dd,n,x,y,z);
+        if (Pi == NULL) goto endgame;
+        createdPi = 1;
+        cuddRef(Pi);
+    }
+
+    /* Initialize abstraction cube. */
+    zcube = DD_ONE(dd);
+    cuddRef(zcube);
+    for (i = n - 1; i >= 0; i--) {
+        DdNode *tmpp;
+        tmpp = Cudd_bddAnd(dd,z[i],zcube);
+        if (tmpp == NULL) goto endgame;
+        cuddRef(tmpp);
+        Cudd_RecursiveDeref(dd,zcube);
+        zcube = tmpp;
+    }
+
+    /* Compute subset of (x,y) pairs. */
+    Rxz = Cudd_bddSwapVariables(dd,R,y,z,n);
+    if (Rxz == NULL) goto endgame;
+    cuddRef(Rxz);
+    Q = Cudd_bddAndAbstract(dd,Rxz,Pi,zcube);
+    if (Q == NULL) {
+        Cudd_RecursiveDeref(dd,Rxz);
+        goto endgame;
+    }
+    cuddRef(Q);
+    Cudd_RecursiveDeref(dd,Rxz);
+    res = Cudd_bddAnd(dd,R,Cudd_Not(Q));
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd,Q);
+        goto endgame;
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd,Q);
+
+endgame:
+    if (zcube != NULL) Cudd_RecursiveDeref(dd,zcube);
+    if (createdZ) {
+        ABC_FREE(z);
+    }
+    if (createdPi) {
+        Cudd_RecursiveDeref(dd,Pi);
+    }
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+} /* Cudd_PrioritySelect */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a BDD for the function x &gt; y.]
+
+  Description [This function generates a BDD for the function x &gt; y.
+  Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and
+  y\[0\] y\[1\] ...  y\[N-1\], with 0 the most significant bit.
+  The BDD is built bottom-up.
+  It has 3*N-1 internal nodes, if the variables are ordered as follows:
+  x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\].
+  Argument z is not used by Cudd_Xgty: it is included to make it
+  call-compatible to Cudd_Dxygtdxz and Cudd_Dxygtdyz.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrioritySelect Cudd_Dxygtdxz Cudd_Dxygtdyz]
+
+******************************************************************************/
+DdNode *
+Cudd_Xgty(
+  DdManager * dd /* DD manager */,
+  int  N /* number of x and y variables */,
+  DdNode ** z /* array of z variables: unused */,
+  DdNode ** x /* array of x variables */,
+  DdNode ** y /* array of y variables */)
+{
+    DdNode *u, *v, *w;
+    int     i;
+
+    /* Build bottom part of BDD outside loop. */
+    u = Cudd_bddAnd(dd, x[N-1], Cudd_Not(y[N-1]));
+    if (u == NULL) return(NULL);
+    cuddRef(u);
+
+    /* Loop to build the rest of the BDD. */
+    for (i = N-2; i >= 0; i--) {
+        v = Cudd_bddAnd(dd, y[i], Cudd_Not(u));
+        if (v == NULL) {
+            Cudd_RecursiveDeref(dd, u);
+            return(NULL);
+        }
+        cuddRef(v);
+        w = Cudd_bddAnd(dd, Cudd_Not(y[i]), u);
+        if (w == NULL) {
+            Cudd_RecursiveDeref(dd, u);
+            Cudd_RecursiveDeref(dd, v);
+            return(NULL);
+        }
+        cuddRef(w);
+        Cudd_RecursiveDeref(dd, u);
+        u = Cudd_bddIte(dd, x[i], Cudd_Not(v), w);
+        if (u == NULL) {
+            Cudd_RecursiveDeref(dd, v);
+            Cudd_RecursiveDeref(dd, w);
+            return(NULL);
+        }
+        cuddRef(u);
+        Cudd_RecursiveDeref(dd, v);
+        Cudd_RecursiveDeref(dd, w);
+
+    }
+    cuddDeref(u);
+    return(u);
+
+} /* end of Cudd_Xgty */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a BDD for the function x==y.]
+
+  Description [This function generates a BDD for the function x==y.
+  Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and
+  y\[0\] y\[1\] ...  y\[N-1\], with 0 the most significant bit.
+  The BDD is built bottom-up.
+  It has 3*N-1 internal nodes, if the variables are ordered as follows:
+  x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addXeqy]
+
+******************************************************************************/
+DdNode *
+Cudd_Xeqy(
+  DdManager * dd /* DD manager */,
+  int  N /* number of x and y variables */,
+  DdNode ** x /* array of x variables */,
+  DdNode ** y /* array of y variables */)
+{
+    DdNode *u, *v, *w;
+    int     i;
+
+    /* Build bottom part of BDD outside loop. */
+    u = Cudd_bddIte(dd, x[N-1], y[N-1], Cudd_Not(y[N-1]));
+    if (u == NULL) return(NULL);
+    cuddRef(u);
+
+    /* Loop to build the rest of the BDD. */
+    for (i = N-2; i >= 0; i--) {
+        v = Cudd_bddAnd(dd, y[i], u);
+        if (v == NULL) {
+            Cudd_RecursiveDeref(dd, u);
+            return(NULL);
+        }
+        cuddRef(v);
+        w = Cudd_bddAnd(dd, Cudd_Not(y[i]), u);
+        if (w == NULL) {
+            Cudd_RecursiveDeref(dd, u);
+            Cudd_RecursiveDeref(dd, v);
+            return(NULL);
+        }
+        cuddRef(w);
+        Cudd_RecursiveDeref(dd, u);
+        u = Cudd_bddIte(dd, x[i], v, w);
+        if (u == NULL) {
+            Cudd_RecursiveDeref(dd, v);
+            Cudd_RecursiveDeref(dd, w);
+            return(NULL);
+        }
+        cuddRef(u);
+        Cudd_RecursiveDeref(dd, v);
+        Cudd_RecursiveDeref(dd, w);
+    }
+    cuddDeref(u);
+    return(u);
+
+} /* end of Cudd_Xeqy */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates an ADD for the function x==y.]
+
+  Description [This function generates an ADD for the function x==y.
+  Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and
+  y\[0\] y\[1\] ...  y\[N-1\], with 0 the most significant bit.
+  The ADD is built bottom-up.
+  It has 3*N-1 internal nodes, if the variables are ordered as follows:
+  x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Xeqy]
+
+******************************************************************************/
+DdNode *
+Cudd_addXeqy(
+  DdManager * dd /* DD manager */,
+  int  N /* number of x and y variables */,
+  DdNode ** x /* array of x variables */,
+  DdNode ** y /* array of y variables */)
+{
+    DdNode *one, *zero;
+    DdNode *u, *v, *w;
+    int     i;
+
+    one = DD_ONE(dd);
+    zero = DD_ZERO(dd);
+
+    /* Build bottom part of ADD outside loop. */
+    v = Cudd_addIte(dd, y[N-1], one, zero);
+    if (v == NULL) return(NULL);
+    cuddRef(v);
+    w = Cudd_addIte(dd, y[N-1], zero, one);
+    if (w == NULL) {
+        Cudd_RecursiveDeref(dd, v);
+        return(NULL);
+    }
+    cuddRef(w);
+    u = Cudd_addIte(dd, x[N-1], v, w);
+    if (u == NULL) {
+        Cudd_RecursiveDeref(dd, v);
+        Cudd_RecursiveDeref(dd, w);
+        return(NULL);
+    }
+    cuddRef(u);
+    Cudd_RecursiveDeref(dd, v);
+    Cudd_RecursiveDeref(dd, w);
+
+    /* Loop to build the rest of the ADD. */
+    for (i = N-2; i >= 0; i--) {
+        v = Cudd_addIte(dd, y[i], u, zero);
+        if (v == NULL) {
+            Cudd_RecursiveDeref(dd, u);
+            return(NULL);
+        }
+        cuddRef(v);
+        w = Cudd_addIte(dd, y[i], zero, u);
+        if (w == NULL) {
+            Cudd_RecursiveDeref(dd, u);
+            Cudd_RecursiveDeref(dd, v);
+            return(NULL);
+        }
+        cuddRef(w);
+        Cudd_RecursiveDeref(dd, u);
+        u = Cudd_addIte(dd, x[i], v, w);
+        if (w == NULL) {
+            Cudd_RecursiveDeref(dd, v);
+            Cudd_RecursiveDeref(dd, w);
+            return(NULL);
+        }
+        cuddRef(u);
+        Cudd_RecursiveDeref(dd, v);
+        Cudd_RecursiveDeref(dd, w);
+    }
+    cuddDeref(u);
+    return(u);
+
+} /* end of Cudd_addXeqy */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a BDD for the function d(x,y) &gt; d(x,z).]
+
+  Description [This function generates a BDD for the function d(x,y)
+  &gt; d(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\],
+  with 0 the most significant bit.
+  The distance d(x,y) is defined as:
+        \sum_{i=0}^{N-1}(|x_i - y_i| \cdot 2^{N-i-1}).
+  The BDD is built bottom-up.
+  It has 7*N-3 internal nodes, if the variables are ordered as follows:
+  x\[0\] y\[0\] z\[0\] x\[1\] y\[1\] z\[1\] ... x\[N-1\] y\[N-1\] z\[N-1\]. ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrioritySelect Cudd_Dxygtdyz Cudd_Xgty Cudd_bddAdjPermuteX]
+
+******************************************************************************/
+DdNode *
+Cudd_Dxygtdxz(
+  DdManager * dd /* DD manager */,
+  int  N /* number of x, y, and z variables */,
+  DdNode ** x /* array of x variables */,
+  DdNode ** y /* array of y variables */,
+  DdNode ** z /* array of z variables */)
+{
+    DdNode *one, *zero;
+    DdNode *z1, *z2, *z3, *z4, *y1_, *y2, *x1;
+    int     i;
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    /* Build bottom part of BDD outside loop. */
+    y1_ = Cudd_bddIte(dd, y[N-1], one, Cudd_Not(z[N-1]));
+    if (y1_ == NULL) return(NULL);
+    cuddRef(y1_);
+    y2 = Cudd_bddIte(dd, y[N-1], z[N-1], one);
+    if (y2 == NULL) {
+        Cudd_RecursiveDeref(dd, y1_);
+        return(NULL);
+    }
+    cuddRef(y2);
+    x1 = Cudd_bddIte(dd, x[N-1], y1_, y2);
+    if (x1 == NULL) {
+        Cudd_RecursiveDeref(dd, y1_);
+        Cudd_RecursiveDeref(dd, y2);
+        return(NULL);
+    }
+    cuddRef(x1);
+    Cudd_RecursiveDeref(dd, y1_);
+    Cudd_RecursiveDeref(dd, y2);
+
+    /* Loop to build the rest of the BDD. */
+    for (i = N-2; i >= 0; i--) {
+        z1 = Cudd_bddIte(dd, z[i], one, Cudd_Not(x1));
+        if (z1 == NULL) {
+            Cudd_RecursiveDeref(dd, x1);
+            return(NULL);
+        }
+        cuddRef(z1);
+        z2 = Cudd_bddIte(dd, z[i], x1, one);
+        if (z2 == NULL) {
+            Cudd_RecursiveDeref(dd, x1);
+            Cudd_RecursiveDeref(dd, z1);
+            return(NULL);
+        }
+        cuddRef(z2);
+        z3 = Cudd_bddIte(dd, z[i], one, x1);
+        if (z3 == NULL) {
+            Cudd_RecursiveDeref(dd, x1);
+            Cudd_RecursiveDeref(dd, z1);
+            Cudd_RecursiveDeref(dd, z2);
+            return(NULL);
+        }
+        cuddRef(z3);
+        z4 = Cudd_bddIte(dd, z[i], x1, zero);
+        if (z4 == NULL) {
+            Cudd_RecursiveDeref(dd, x1);
+            Cudd_RecursiveDeref(dd, z1);
+            Cudd_RecursiveDeref(dd, z2);
+            Cudd_RecursiveDeref(dd, z3);
+            return(NULL);
+        }
+        cuddRef(z4);
+        Cudd_RecursiveDeref(dd, x1);
+        y1_ = Cudd_bddIte(dd, y[i], z2, Cudd_Not(z1));
+        if (y1_ == NULL) {
+            Cudd_RecursiveDeref(dd, z1);
+            Cudd_RecursiveDeref(dd, z2);
+            Cudd_RecursiveDeref(dd, z3);
+            Cudd_RecursiveDeref(dd, z4);
+            return(NULL);
+        }
+        cuddRef(y1_);
+        y2 = Cudd_bddIte(dd, y[i], z4, z3);
+        if (y2 == NULL) {
+            Cudd_RecursiveDeref(dd, z1);
+            Cudd_RecursiveDeref(dd, z2);
+            Cudd_RecursiveDeref(dd, z3);
+            Cudd_RecursiveDeref(dd, z4);
+            Cudd_RecursiveDeref(dd, y1_);
+            return(NULL);
+        }
+        cuddRef(y2);
+        Cudd_RecursiveDeref(dd, z1);
+        Cudd_RecursiveDeref(dd, z2);
+        Cudd_RecursiveDeref(dd, z3);
+        Cudd_RecursiveDeref(dd, z4);
+        x1 = Cudd_bddIte(dd, x[i], y1_, y2);
+        if (x1 == NULL) {
+            Cudd_RecursiveDeref(dd, y1_);
+            Cudd_RecursiveDeref(dd, y2);
+            return(NULL);
+        }
+        cuddRef(x1);
+        Cudd_RecursiveDeref(dd, y1_);
+        Cudd_RecursiveDeref(dd, y2);
+    }
+    cuddDeref(x1);
+    return(Cudd_Not(x1));
+
+} /* end of Cudd_Dxygtdxz */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a BDD for the function d(x,y) &gt; d(y,z).]
+
+  Description [This function generates a BDD for the function d(x,y)
+  &gt; d(y,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\],
+  with 0 the most significant bit.
+  The distance d(x,y) is defined as:
+        \sum_{i=0}^{N-1}(|x_i - y_i| \cdot 2^{N-i-1}).
+  The BDD is built bottom-up.
+  It has 7*N-3 internal nodes, if the variables are ordered as follows:
+  x\[0\] y\[0\] z\[0\] x\[1\] y\[1\] z\[1\] ... x\[N-1\] y\[N-1\] z\[N-1\]. ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrioritySelect Cudd_Dxygtdxz Cudd_Xgty Cudd_bddAdjPermuteX]
+
+******************************************************************************/
+DdNode *
+Cudd_Dxygtdyz(
+  DdManager * dd /* DD manager */,
+  int  N /* number of x, y, and z variables */,
+  DdNode ** x /* array of x variables */,
+  DdNode ** y /* array of y variables */,
+  DdNode ** z /* array of z variables */)
+{
+    DdNode *one, *zero;
+    DdNode *z1, *z2, *z3, *z4, *y1_, *y2, *x1;
+    int     i;
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    /* Build bottom part of BDD outside loop. */
+    y1_ = Cudd_bddIte(dd, y[N-1], one, z[N-1]);
+    if (y1_ == NULL) return(NULL);
+    cuddRef(y1_);
+    y2 = Cudd_bddIte(dd, y[N-1], z[N-1], zero);
+    if (y2 == NULL) {
+        Cudd_RecursiveDeref(dd, y1_);
+        return(NULL);
+    }
+    cuddRef(y2);
+    x1 = Cudd_bddIte(dd, x[N-1], y1_, Cudd_Not(y2));
+    if (x1 == NULL) {
+        Cudd_RecursiveDeref(dd, y1_);
+        Cudd_RecursiveDeref(dd, y2);
+        return(NULL);
+    }
+    cuddRef(x1);
+    Cudd_RecursiveDeref(dd, y1_);
+    Cudd_RecursiveDeref(dd, y2);
+
+    /* Loop to build the rest of the BDD. */
+    for (i = N-2; i >= 0; i--) {
+        z1 = Cudd_bddIte(dd, z[i], x1, zero);
+        if (z1 == NULL) {
+            Cudd_RecursiveDeref(dd, x1);
+            return(NULL);
+        }
+        cuddRef(z1);
+        z2 = Cudd_bddIte(dd, z[i], x1, one);
+        if (z2 == NULL) {
+            Cudd_RecursiveDeref(dd, x1);
+            Cudd_RecursiveDeref(dd, z1);
+            return(NULL);
+        }
+        cuddRef(z2);
+        z3 = Cudd_bddIte(dd, z[i], one, x1);
+        if (z3 == NULL) {
+            Cudd_RecursiveDeref(dd, x1);
+            Cudd_RecursiveDeref(dd, z1);
+            Cudd_RecursiveDeref(dd, z2);
+            return(NULL);
+        }
+        cuddRef(z3);
+        z4 = Cudd_bddIte(dd, z[i], one, Cudd_Not(x1));
+        if (z4 == NULL) {
+            Cudd_RecursiveDeref(dd, x1);
+            Cudd_RecursiveDeref(dd, z1);
+            Cudd_RecursiveDeref(dd, z2);
+            Cudd_RecursiveDeref(dd, z3);
+            return(NULL);
+        }
+        cuddRef(z4);
+        Cudd_RecursiveDeref(dd, x1);
+        y1_ = Cudd_bddIte(dd, y[i], z2, z1);
+        if (y1_ == NULL) {
+            Cudd_RecursiveDeref(dd, z1);
+            Cudd_RecursiveDeref(dd, z2);
+            Cudd_RecursiveDeref(dd, z3);
+            Cudd_RecursiveDeref(dd, z4);
+            return(NULL);
+        }
+        cuddRef(y1_);
+        y2 = Cudd_bddIte(dd, y[i], z4, Cudd_Not(z3));
+        if (y2 == NULL) {
+            Cudd_RecursiveDeref(dd, z1);
+            Cudd_RecursiveDeref(dd, z2);
+            Cudd_RecursiveDeref(dd, z3);
+            Cudd_RecursiveDeref(dd, z4);
+            Cudd_RecursiveDeref(dd, y1_);
+            return(NULL);
+        }
+        cuddRef(y2);
+        Cudd_RecursiveDeref(dd, z1);
+        Cudd_RecursiveDeref(dd, z2);
+        Cudd_RecursiveDeref(dd, z3);
+        Cudd_RecursiveDeref(dd, z4);
+        x1 = Cudd_bddIte(dd, x[i], y1_, Cudd_Not(y2));
+        if (x1 == NULL) {
+            Cudd_RecursiveDeref(dd, y1_);
+            Cudd_RecursiveDeref(dd, y2);
+            return(NULL);
+        }
+        cuddRef(x1);
+        Cudd_RecursiveDeref(dd, y1_);
+        Cudd_RecursiveDeref(dd, y2);
+    }
+    cuddDeref(x1);
+    return(Cudd_Not(x1));
+
+} /* end of Cudd_Dxygtdyz */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a BDD for the function x - y &ge; c.]
+
+  Description [This function generates a BDD for the function x -y &ge; c.
+  Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and
+  y\[0\] y\[1\] ...  y\[N-1\], with 0 the most significant bit.
+  The BDD is built bottom-up.
+  It has a linear number of nodes if the variables are ordered as follows:
+  x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\].]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Xgty]
+
+******************************************************************************/
+DdNode *
+Cudd_Inequality(
+  DdManager * dd /* DD manager */,
+  int  N /* number of x and y variables */,
+  int c /* right-hand side constant */,
+  DdNode ** x /* array of x variables */,
+  DdNode ** y /* array of y variables */)
+{
+    /* The nodes at level i represent values of the difference that are
+    ** multiples of 2^i.  We use variables with names starting with k
+    ** to denote the multipliers of 2^i in such multiples. */
+    int kTrue = c;
+    int kFalse = c - 1;
+    /* Mask used to compute the ceiling function.  Since we divide by 2^i,
+    ** we want to know whether the dividend is a multiple of 2^i.  If it is,
+    ** then ceiling and floor coincide; otherwise, they differ by one. */
+    int mask = 1;
+    int i;
+
+    DdNode *f = NULL;           /* the eventual result */
+    DdNode *one = DD_ONE(dd);
+    DdNode *zero = Cudd_Not(one);
+
+    /* Two x-labeled nodes are created at most at each iteration.  They are
+    ** stored, along with their k values, in these variables.  At each level,
+    ** the old nodes are freed and the new nodes are copied into the old map.
+    */
+    DdNode *map[2] = {0};
+    int invalidIndex = 1 << (N-1);
+    int index[2] = {invalidIndex, invalidIndex};
+
+    /* This should never happen. */
+    if (N < 0) return(NULL);
+
+    /* If there are no bits, both operands are 0.  The result depends on c. */
+    if (N == 0) {
+        if (c >= 0) return(one);
+        else return(zero);
+    }
+
+    /* The maximum or the minimum difference comparing to c can generate the terminal case */
+    if ((1 << N) - 1 < c) return(zero);
+    else if ((-(1 << N) + 1) >= c) return(one);
+
+    /* Build the result bottom up. */
+    for (i = 1; i <= N; i++) {
+        int kTrueLower, kFalseLower;
+        int leftChild, middleChild, rightChild;
+        DdNode *g0, *g1, *fplus, *fequal, *fminus;
+        int j;
+        DdNode *newMap[2] = {NULL};
+        int newIndex[2];
+
+        kTrueLower = kTrue;
+        kFalseLower = kFalse;
+        /* kTrue = ceiling((c-1)/2^i) + 1 */
+        kTrue = ((c-1) >> i) + ((c & mask) != 1) + 1;
+        mask = (mask << 1) | 1;
+        /* kFalse = floor(c/2^i) - 1 */
+        kFalse = (c >> i) - 1;
+        newIndex[0] = invalidIndex;
+        newIndex[1] = invalidIndex;
+
+        for (j = kFalse + 1; j < kTrue; j++) {
+            /* Skip if node is not reachable from top of BDD. */
+            if ((j >= (1 << (N - i))) || (j <= -(1 << (N -i)))) continue;
+
+            /* Find f- */
+            leftChild = (j << 1) - 1;
+            if (leftChild >= kTrueLower) {
+                fminus = one;
+            } else if (leftChild <= kFalseLower) {
+                fminus = zero;
+            } else {
+                assert(leftChild == index[0] || leftChild == index[1]);
+                if (leftChild == index[0]) {
+                    fminus = map[0];
+                } else {
+                    fminus = map[1];
+                }
+            }
+
+            /* Find f= */
+            middleChild = j << 1;
+            if (middleChild >= kTrueLower) {
+                fequal = one;
+            } else if (middleChild <= kFalseLower) {
+                fequal = zero;
+            } else {
+                assert(middleChild == index[0] || middleChild == index[1]);
+                if (middleChild == index[0]) {
+                    fequal = map[0];
+                } else {
+                    fequal = map[1];
+                }
+            }
+
+            /* Find f+ */
+            rightChild = (j << 1) + 1;
+            if (rightChild >= kTrueLower) {
+                fplus = one;
+            } else if (rightChild <= kFalseLower) {
+                fplus = zero;
+            } else {
+                assert(rightChild == index[0] || rightChild == index[1]);
+                if (rightChild == index[0]) {
+                    fplus = map[0];
+                } else {
+                    fplus = map[1];
+                }
+            }
+
+            /* Build new nodes. */
+            g1 = Cudd_bddIte(dd, y[N - i], fequal, fplus);
+            if (g1 == NULL) {
+                if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]);
+                if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]);
+                if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]);
+                if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]);
+                return(NULL);
+            }
+            cuddRef(g1);
+            g0 = Cudd_bddIte(dd, y[N - i], fminus, fequal);
+            if (g0 == NULL) {
+                Cudd_IterDerefBdd(dd, g1);
+                if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]);
+                if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]);
+                if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]);
+                if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]);
+                return(NULL);
+            }
+            cuddRef(g0);
+            f = Cudd_bddIte(dd, x[N - i], g1, g0);
+            if (f == NULL) {
+                Cudd_IterDerefBdd(dd, g1);
+                Cudd_IterDerefBdd(dd, g0);
+                if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]);
+                if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]);
+                if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]);
+                if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]);
+                return(NULL);
+            }
+            cuddRef(f);
+            Cudd_IterDerefBdd(dd, g1);
+            Cudd_IterDerefBdd(dd, g0);
+
+            /* Save newly computed node in map. */
+            assert(newIndex[0] == invalidIndex || newIndex[1] == invalidIndex);
+            if (newIndex[0] == invalidIndex) {
+                newIndex[0] = j;
+                newMap[0] = f;
+            } else {
+                newIndex[1] = j;
+                newMap[1] = f;
+            }
+        }
+
+        /* Copy new map to map. */
+        if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]);
+        if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]);
+        map[0] = newMap[0];
+        map[1] = newMap[1];
+        index[0] = newIndex[0];
+        index[1] = newIndex[1];
+    }
+
+    cuddDeref(f);
+    return(f);
+
+} /* end of Cudd_Inequality */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a BDD for the function x - y != c.]
+
+  Description [This function generates a BDD for the function x -y != c.
+  Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and
+  y\[0\] y\[1\] ...  y\[N-1\], with 0 the most significant bit.
+  The BDD is built bottom-up.
+  It has a linear number of nodes if the variables are ordered as follows:
+  x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\].]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Xgty]
+
+******************************************************************************/
+DdNode *
+Cudd_Disequality(
+  DdManager * dd /* DD manager */,
+  int  N /* number of x and y variables */,
+  int c /* right-hand side constant */,
+  DdNode ** x /* array of x variables */,
+  DdNode ** y /* array of y variables */)
+{
+    /* The nodes at level i represent values of the difference that are
+    ** multiples of 2^i.  We use variables with names starting with k
+    ** to denote the multipliers of 2^i in such multiples. */
+    int kTrueLb = c + 1;
+    int kTrueUb = c - 1;
+    int kFalse = c;
+    /* Mask used to compute the ceiling function.  Since we divide by 2^i,
+    ** we want to know whether the dividend is a multiple of 2^i.  If it is,
+    ** then ceiling and floor coincide; otherwise, they differ by one. */
+    int mask = 1;
+    int i;
+
+    DdNode *f = NULL;           /* the eventual result */
+    DdNode *one = DD_ONE(dd);
+    DdNode *zero = Cudd_Not(one);
+
+    /* Two x-labeled nodes are created at most at each iteration.  They are
+    ** stored, along with their k values, in these variables.  At each level,
+    ** the old nodes are freed and the new nodes are copied into the old map.
+    */
+    DdNode *map[2] = {0};
+    int invalidIndex = 1 << (N-1);
+    int index[2] = {invalidIndex, invalidIndex};
+
+    /* This should never happen. */
+    if (N < 0) return(NULL);
+
+    /* If there are no bits, both operands are 0.  The result depends on c. */
+    if (N == 0) {
+        if (c != 0) return(one);
+        else return(zero);
+    }
+
+    /* The maximum or the minimum difference comparing to c can generate the terminal case */
+    if ((1 << N) - 1 < c || (-(1 << N) + 1) > c) return(one);
+
+    /* Build the result bottom up. */
+    for (i = 1; i <= N; i++) {
+        int kTrueLbLower, kTrueUbLower;
+        int leftChild, middleChild, rightChild;
+        DdNode *g0, *g1, *fplus, *fequal, *fminus;
+        int j;
+        DdNode *newMap[2] = {NULL};
+        int newIndex[2];
+
+        kTrueLbLower = kTrueLb;
+        kTrueUbLower = kTrueUb;
+        /* kTrueLb = floor((c-1)/2^i) + 2 */
+        kTrueLb = ((c-1) >> i) + 2;
+        /* kTrueUb = ceiling((c+1)/2^i) - 2 */
+        kTrueUb = ((c+1) >> i) + (((c+2) & mask) != 1) - 2;
+        mask = (mask << 1) | 1;
+        newIndex[0] = invalidIndex;
+        newIndex[1] = invalidIndex;
+
+        for (j = kTrueUb + 1; j < kTrueLb; j++) {
+            /* Skip if node is not reachable from top of BDD. */
+            if ((j >= (1 << (N - i))) || (j <= -(1 << (N -i)))) continue;
+
+            /* Find f- */
+            leftChild = (j << 1) - 1;
+            if (leftChild >= kTrueLbLower || leftChild <= kTrueUbLower) {
+                fminus = one;
+            } else if (i == 1 && leftChild == kFalse) {
+                fminus = zero;
+            } else {
+                assert(leftChild == index[0] || leftChild == index[1]);
+                if (leftChild == index[0]) {
+                    fminus = map[0];
+                } else {
+                    fminus = map[1];
+                }
+            }
+
+            /* Find f= */
+            middleChild = j << 1;
+            if (middleChild >= kTrueLbLower || middleChild <= kTrueUbLower) {
+                fequal = one;
+            } else if (i == 1 && middleChild == kFalse) {
+                fequal = zero;
+            } else {
+                assert(middleChild == index[0] || middleChild == index[1]);
+                if (middleChild == index[0]) {
+                    fequal = map[0];
+                } else {
+                    fequal = map[1];
+                }
+            }
+
+            /* Find f+ */
+            rightChild = (j << 1) + 1;
+            if (rightChild >= kTrueLbLower || rightChild <= kTrueUbLower) {
+                fplus = one;
+            } else if (i == 1 && rightChild == kFalse) {
+                fplus = zero;
+            } else {
+                assert(rightChild == index[0] || rightChild == index[1]);
+                if (rightChild == index[0]) {
+                    fplus = map[0];
+                } else {
+                    fplus = map[1];
+                }
+            }
+
+            /* Build new nodes. */
+            g1 = Cudd_bddIte(dd, y[N - i], fequal, fplus);
+            if (g1 == NULL) {
+                if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]);
+                if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]);
+                if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]);
+                if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]);
+                return(NULL);
+            }
+            cuddRef(g1);
+            g0 = Cudd_bddIte(dd, y[N - i], fminus, fequal);
+            if (g0 == NULL) {
+                Cudd_IterDerefBdd(dd, g1);
+                if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]);
+                if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]);
+                if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]);
+                if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]);
+                return(NULL);
+            }
+            cuddRef(g0);
+            f = Cudd_bddIte(dd, x[N - i], g1, g0);
+            if (f == NULL) {
+                Cudd_IterDerefBdd(dd, g1);
+                Cudd_IterDerefBdd(dd, g0);
+                if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]);
+                if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]);
+                if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]);
+                if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]);
+                return(NULL);
+            }
+            cuddRef(f);
+            Cudd_IterDerefBdd(dd, g1);
+            Cudd_IterDerefBdd(dd, g0);
+
+            /* Save newly computed node in map. */
+            assert(newIndex[0] == invalidIndex || newIndex[1] == invalidIndex);
+            if (newIndex[0] == invalidIndex) {
+                newIndex[0] = j;
+                newMap[0] = f;
+            } else {
+                newIndex[1] = j;
+                newMap[1] = f;
+            }
+        }
+
+        /* Copy new map to map. */
+        if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]);
+        if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]);
+        map[0] = newMap[0];
+        map[1] = newMap[1];
+        index[0] = newIndex[0];
+        index[1] = newIndex[1];
+    }
+
+    cuddDeref(f);
+    return(f);
+
+} /* end of Cudd_Disequality */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a BDD for the function lowerB &le; x &le; upperB.]
+
+  Description [This function generates a BDD for the function
+  lowerB &le; x &le; upperB, where x is an N-bit number,
+  x\[0\] x\[1\] ... x\[N-1\], with 0 the most significant bit (important!).
+  The number of variables N should be sufficient to represent the bounds;
+  otherwise, the bounds are truncated to their N least significant bits.
+  Two BDDs are built bottom-up for lowerB &le; x and x &le; upperB, and they
+  are finally conjoined.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Xgty]
+
+******************************************************************************/
+DdNode *
+Cudd_bddInterval(
+  DdManager * dd /* DD manager */,
+  int  N /* number of x variables */,
+  DdNode ** x /* array of x variables */,
+  unsigned int lowerB /* lower bound */,
+  unsigned int upperB /* upper bound */)
+{
+    DdNode *one, *zero;
+    DdNode *r, *rl, *ru;
+    int     i;
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    rl = one;
+    cuddRef(rl);
+    ru = one;
+    cuddRef(ru);
+
+    /* Loop to build the rest of the BDDs. */
+    for (i = N-1; i >= 0; i--) {
+        DdNode *vl, *vu;
+        vl = Cudd_bddIte(dd, x[i],
+                         lowerB&1 ? rl : one,
+                         lowerB&1 ? zero : rl);
+        if (vl == NULL) {
+            Cudd_IterDerefBdd(dd, rl);
+            Cudd_IterDerefBdd(dd, ru);
+            return(NULL);
+        }
+        cuddRef(vl);
+        Cudd_IterDerefBdd(dd, rl);
+        rl = vl;
+        lowerB >>= 1;
+        vu = Cudd_bddIte(dd, x[i],
+                         upperB&1 ? ru : zero,
+                         upperB&1 ? one : ru);
+        if (vu == NULL) {
+            Cudd_IterDerefBdd(dd, rl);
+            Cudd_IterDerefBdd(dd, ru);
+            return(NULL);
+        }
+        cuddRef(vu);
+        Cudd_IterDerefBdd(dd, ru);
+        ru = vu;
+        upperB >>= 1;
+    }
+
+    /* Conjoin the two bounds. */
+    r = Cudd_bddAnd(dd, rl, ru);
+    if (r == NULL) {
+        Cudd_IterDerefBdd(dd, rl);
+        Cudd_IterDerefBdd(dd, ru);
+        return(NULL);
+    }
+    cuddRef(r);
+    Cudd_IterDerefBdd(dd, rl);
+    Cudd_IterDerefBdd(dd, ru);
+    cuddDeref(r);
+    return(r);
+
+} /* end of Cudd_bddInterval */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the compatible projection of R w.r.t. cube Y.]
+
+  Description [Computes the compatible projection of relation R with
+  respect to cube Y. Returns a pointer to the c-projection if
+  successful; NULL otherwise. For a comparison between Cudd_CProjection
+  and Cudd_PrioritySelect, see the documentation of the latter.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrioritySelect]
+
+******************************************************************************/
+DdNode *
+Cudd_CProjection(
+  DdManager * dd,
+  DdNode * R,
+  DdNode * Y)
+{
+    DdNode *res;
+    DdNode *support;
+
+    if (cuddCheckCube(dd,Y) == 0) {
+        (void) fprintf(dd->err,
+        "Error: The third argument of Cudd_CProjection should be a cube\n");
+        dd->errorCode = CUDD_INVALID_ARG;
+        return(NULL);
+    }
+
+    /* Compute the support of Y, which is used by the abstraction step
+    ** in cuddCProjectionRecur.
+    */
+    support = Cudd_Support(dd,Y);
+    if (support == NULL) return(NULL);
+    cuddRef(support);
+
+    do {
+        dd->reordered = 0;
+        res = cuddCProjectionRecur(dd,R,Y,support);
+    } while (dd->reordered == 1);
+
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd,support);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd,support);
+    cuddDeref(res);
+
+    return(res);
+
+} /* end of Cudd_CProjection */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the Hamming distance ADD.]
+
+  Description [Computes the Hamming distance ADD. Returns an ADD that
+  gives the Hamming distance between its two arguments if successful;
+  NULL otherwise. The two vectors xVars and yVars identify the variables
+  that form the two arguments.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_addHamming(
+  DdManager * dd,
+  DdNode ** xVars,
+  DdNode ** yVars,
+  int  nVars)
+{
+    DdNode  *result,*tempBdd;
+    DdNode  *tempAdd,*temp;
+    int     i;
+
+    result = DD_ZERO(dd);
+    cuddRef(result);
+
+    for (i = 0; i < nVars; i++) {
+        tempBdd = Cudd_bddIte(dd,xVars[i],Cudd_Not(yVars[i]),yVars[i]);
+        if (tempBdd == NULL) {
+            Cudd_RecursiveDeref(dd,result);
+            return(NULL);
+        }
+        cuddRef(tempBdd);
+        tempAdd = Cudd_BddToAdd(dd,tempBdd);
+        if (tempAdd == NULL) {
+            Cudd_RecursiveDeref(dd,tempBdd);
+            Cudd_RecursiveDeref(dd,result);
+            return(NULL);
+        }
+        cuddRef(tempAdd);
+        Cudd_RecursiveDeref(dd,tempBdd);
+        temp = Cudd_addApply(dd,Cudd_addPlus,tempAdd,result);
+        if (temp == NULL) {
+            Cudd_RecursiveDeref(dd,tempAdd);
+            Cudd_RecursiveDeref(dd,result);
+            return(NULL);
+        }
+        cuddRef(temp);
+        Cudd_RecursiveDeref(dd,tempAdd);
+        Cudd_RecursiveDeref(dd,result);
+        result = temp;
+    }
+
+    cuddDeref(result);
+    return(result);
+
+} /* end of Cudd_addHamming */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the minimum Hamming distance between f and minterm.]
+
+  Description [Returns the minimum Hamming distance between the
+  minterms of a function f and a reference minterm. The function is
+  given as a BDD; the minterm is given as an array of integers, one
+  for each variable in the manager.  Returns the minimum distance if
+  it is less than the upper bound; the upper bound if the minimum
+  distance is at least as large; CUDD_OUT_OF_MEM in case of failure.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addHamming Cudd_bddClosestCube]
+
+******************************************************************************/
+int
+Cudd_MinHammingDist(
+  DdManager *dd /* DD manager */,
+  DdNode *f /* function to examine */,
+  int *minterm /* reference minterm */,
+  int upperBound /* distance above which an approximate answer is OK */)
+{
+    DdHashTable *table;
+    CUDD_VALUE_TYPE epsilon;
+    int res;
+
+    table = cuddHashTableInit(dd,1,2);
+    if (table == NULL) {
+        return(CUDD_OUT_OF_MEM);
+    }
+    epsilon = Cudd_ReadEpsilon(dd);
+    Cudd_SetEpsilon(dd,(CUDD_VALUE_TYPE)0.0);
+    res = cuddMinHammingDistRecur(f,minterm,table,upperBound);
+    cuddHashTableQuit(table);
+    Cudd_SetEpsilon(dd,epsilon);
+
+    return(res);
+
+} /* end of Cudd_MinHammingDist */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a cube of f at minimum Hamming distance from g.]
+
+  Description [Finds a cube of f at minimum Hamming distance from the
+  minterms of g.  All the minterms of the cube are at the minimum
+  distance.  If the distance is 0, the cube belongs to the
+  intersection of f and g.  Returns the cube if successful; NULL
+  otherwise.]
+
+  SideEffects [The distance is returned as a side effect.]
+
+  SeeAlso     [Cudd_MinHammingDist]
+
+******************************************************************************/
+DdNode *
+Cudd_bddClosestCube(
+  DdManager *dd,
+  DdNode * f,
+  DdNode *g,
+  int *distance)
+{
+    DdNode *res, *acube;
+    CUDD_VALUE_TYPE rdist;
+
+    /* Compute the cube and distance as a single ADD. */
+    do {
+        dd->reordered = 0;
+        res = cuddBddClosestCube(dd,f,g,CUDD_CONST_INDEX + 1.0);
+    } while (dd->reordered == 1);
+    if (res == NULL) return(NULL);
+    cuddRef(res);
+
+    /* Unpack distance and cube. */
+    do {
+        dd->reordered = 0;
+        acube = separateCube(dd, res, &rdist);
+    } while (dd->reordered == 1);
+    if (acube == NULL) {
+        Cudd_RecursiveDeref(dd, res);
+        return(NULL);
+    }
+    cuddRef(acube);
+    Cudd_RecursiveDeref(dd, res);
+
+    /* Convert cube from ADD to BDD. */
+    do {
+        dd->reordered = 0;
+        res = cuddAddBddDoPattern(dd, acube);
+    } while (dd->reordered == 1);
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd, acube);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd, acube);
+
+    *distance = (int) rdist;
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_bddClosestCube */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_CProjection.]
+
+  Description [Performs the recursive step of Cudd_CProjection. Returns
+  the projection if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_CProjection]
+
+******************************************************************************/
+DdNode *
+cuddCProjectionRecur(
+  DdManager * dd,
+  DdNode * R,
+  DdNode * Y,
+  DdNode * Ysupp)
+{
+    DdNode *res, *res1, *res2, *resA;
+    DdNode *r, *y, *RT, *RE, *YT, *YE, *Yrest, *Ra, *Ran, *Gamma, *Alpha;
+    unsigned int topR, topY, top, index = 0;
+    DdNode *one = DD_ONE(dd);
+
+    statLine(dd);
+    if (Y == one) return(R);
+
+#ifdef DD_DEBUG
+    assert(!Cudd_IsConstant(Y));
+#endif
+
+    if (R == Cudd_Not(one)) return(R);
+
+    res = cuddCacheLookup2(dd, Cudd_CProjection, R, Y);
+    if (res != NULL) return(res);
+
+    r = Cudd_Regular(R);
+    topR = cuddI(dd,r->index);
+    y = Cudd_Regular(Y);
+    topY = cuddI(dd,y->index);
+
+    top = ddMin(topR, topY);
+
+    /* Compute the cofactors of R */
+    if (topR == top) {
+        index = r->index;
+        RT = cuddT(r);
+        RE = cuddE(r);
+        if (r != R) {
+            RT = Cudd_Not(RT); RE = Cudd_Not(RE);
+        }
+    } else {
+        RT = RE = R;
+    }
+
+    if (topY > top) {
+        /* Y does not depend on the current top variable.
+        ** We just need to compute the results on the two cofactors of R
+        ** and make them the children of a node labeled r->index.
+        */
+        res1 = cuddCProjectionRecur(dd,RT,Y,Ysupp);
+        if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+        res2 = cuddCProjectionRecur(dd,RE,Y,Ysupp);
+        if (res2 == NULL) {
+            Cudd_RecursiveDeref(dd,res1);
+            return(NULL);
+        }
+        cuddRef(res2);
+        res = cuddBddIteRecur(dd, dd->vars[index], res1, res2);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(dd,res1);
+            Cudd_RecursiveDeref(dd,res2);
+            return(NULL);
+        }
+        /* If we have reached this point, res1 and res2 are now
+        ** incorporated in res. cuddDeref is therefore sufficient.
+        */
+        cuddDeref(res1);
+        cuddDeref(res2);
+    } else {
+        /* Compute the cofactors of Y */
+        index = y->index;
+        YT = cuddT(y);
+        YE = cuddE(y);
+        if (y != Y) {
+            YT = Cudd_Not(YT); YE = Cudd_Not(YE);
+        }
+        if (YT == Cudd_Not(one)) {
+            Alpha  = Cudd_Not(dd->vars[index]);
+            Yrest = YE;
+            Ra = RE;
+            Ran = RT;
+        } else {
+            Alpha = dd->vars[index];
+            Yrest = YT;
+            Ra = RT;
+            Ran = RE;
+        }
+        Gamma = cuddBddExistAbstractRecur(dd,Ra,cuddT(Ysupp));
+        if (Gamma == NULL) return(NULL);
+        if (Gamma == one) {
+            res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp));
+            if (res1 == NULL) return(NULL);
+            cuddRef(res1);
+            res = cuddBddAndRecur(dd, Alpha, res1);
+            if (res == NULL) {
+                Cudd_RecursiveDeref(dd,res1);
+                return(NULL);
+            }
+            cuddDeref(res1);
+        } else if (Gamma == Cudd_Not(one)) {
+            res1 = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp));
+            if (res1 == NULL) return(NULL);
+            cuddRef(res1);
+            res = cuddBddAndRecur(dd, Cudd_Not(Alpha), res1);
+            if (res == NULL) {
+                Cudd_RecursiveDeref(dd,res1);
+                return(NULL);
+            }
+            cuddDeref(res1);
+        } else {
+            cuddRef(Gamma);
+            resA = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp));
+            if (resA == NULL) {
+                Cudd_RecursiveDeref(dd,Gamma);
+                return(NULL);
+            }
+            cuddRef(resA);
+            res2 = cuddBddAndRecur(dd, Cudd_Not(Gamma), resA);
+            if (res2 == NULL) {
+                Cudd_RecursiveDeref(dd,Gamma);
+                Cudd_RecursiveDeref(dd,resA);
+                return(NULL);
+            }
+            cuddRef(res2);
+            Cudd_RecursiveDeref(dd,Gamma);
+            Cudd_RecursiveDeref(dd,resA);
+            res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp));
+            if (res1 == NULL) {
+                Cudd_RecursiveDeref(dd,res2);
+                return(NULL);
+            }
+            cuddRef(res1);
+            res = cuddBddIteRecur(dd, Alpha, res1, res2);
+            if (res == NULL) {
+                Cudd_RecursiveDeref(dd,res1);
+                Cudd_RecursiveDeref(dd,res2);
+                return(NULL);
+            }
+            cuddDeref(res1);
+            cuddDeref(res2);
+        }
+    }
+
+    cuddCacheInsert2(dd,Cudd_CProjection,R,Y,res);
+
+    return(res);
+
+} /* end of cuddCProjectionRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddClosestCube.]
+
+  Description [Performs the recursive step of Cudd_bddClosestCube.
+  Returns the cube if succesful; NULL otherwise.  The procedure uses a
+  four-way recursion to examine all four combinations of cofactors of
+  <code>f</code> and <code>g</code> according to the following formula.
+  <pre>
+    H(f,g) = min(H(ft,gt), H(fe,ge), H(ft,ge)+1, H(fe,gt)+1)
+  </pre>
+  Bounding is based on the following observations.
+  <ul>
+  <li> If we already found two points at distance 0, there is no point in
+       continuing.  Furthermore,
+  <li> If F == not(G) then the best we can hope for is a minimum distance
+       of 1.  If we have already found two points at distance 1, there is
+       no point in continuing.  (Indeed, H(F,G) == 1 in this case.  We
+       have to continue, though, to find the cube.)
+  </ul>
+  The variable <code>bound</code> is set at the largest value of the distance
+  that we are still interested in.  Therefore, we desist when
+  <pre>
+    (bound == -1) and (F != not(G)) or (bound == 0) and (F == not(G)).
+  </pre>
+  If we were maximally aggressive in using the bound, we would always
+  set the bound to the minimum distance seen thus far minus one.  That
+  is, we would maintain the invariant
+  <pre>
+    bound < minD,
+  </pre>
+  except at the very beginning, when we have no value for
+  <code>minD</code>.<p>
+
+  However, we do not use <code>bound < minD</code> when examining the
+  two negative cofactors, because we try to find a large cube at
+  minimum distance.  To do so, we try to find a cube in the negative
+  cofactors at the same or smaller distance from the cube found in the
+  positive cofactors.<p>
+
+  When we compute <code>H(ft,ge)</code> and <code>H(fe,gt)</code> we
+  know that we are going to add 1 to the result of the recursive call
+  to account for the difference in the splitting variable.  Therefore,
+  we decrease the bound correspondingly.<p>
+
+  Another important observation concerns the need of examining all
+  four pairs of cofators only when both <code>f</code> and
+  <code>g</code> depend on the top variable.<p>
+
+  Suppose <code>gt == ge == g</code>.  (That is, <code>g</code> does
+  not depend on the top variable.)  Then
+  <pre>
+    H(f,g) = min(H(ft,g), H(fe,g), H(ft,g)+1, H(fe,g)+1)
+           = min(H(ft,g), H(fe,g)) .
+  </pre>
+  Therefore, under these circumstances, we skip the two "cross" cases.<p>
+
+  An interesting feature of this function is the scheme used for
+  caching the results in the global computed table.  Since we have a
+  cube and a distance, we combine them to form an ADD.  The
+  combination replaces the zero child of the top node of the cube with
+  the negative of the distance.  (The use of the negative is to avoid
+  ambiguity with 1.)  The degenerate cases (zero and one) are treated
+  specially because the distance is known (0 for one, and infinity for
+  zero).]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddClosestCube]
+
+******************************************************************************/
+DdNode *
+cuddBddClosestCube(
+  DdManager *dd,
+  DdNode *f,
+  DdNode *g,
+  CUDD_VALUE_TYPE bound)
+{
+    DdNode *res, *F, *G, *ft, *fe, *gt, *ge, *tt, *ee;
+    DdNode *ctt, *cee, *cte, *cet;
+    CUDD_VALUE_TYPE minD, dtt, dee, dte, det;
+    DdNode *one = DD_ONE(dd);
+    DdNode *lzero = Cudd_Not(one);
+    DdNode *azero = DD_ZERO(dd);
+    unsigned int topf, topg, index;
+
+    statLine(dd);
+    if (bound < (int)(f == Cudd_Not(g))) return(azero);
+    /* Terminal cases. */
+    if (g == lzero || f == lzero) return(azero);
+    if (f == one && g == one) return(one);
+
+    /* Check cache. */
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    if (F->ref != 1 || G->ref != 1) {
+        res = cuddCacheLookup2(dd,(DD_CTFP) Cudd_bddClosestCube, f, g);
+        if (res != NULL) return(res);
+    }
+
+    topf = cuddI(dd,F->index);
+    topg = cuddI(dd,G->index);
+
+    /* Compute cofactors. */
+    if (topf <= topg) {
+        index = F->index;
+        ft = cuddT(F);
+        fe = cuddE(F);
+        if (Cudd_IsComplement(f)) {
+            ft = Cudd_Not(ft);
+            fe = Cudd_Not(fe);
+        }
+    } else {
+        index = G->index;
+        ft = fe = f;
+    }
+
+    if (topg <= topf) {
+        gt = cuddT(G);
+        ge = cuddE(G);
+        if (Cudd_IsComplement(g)) {
+            gt = Cudd_Not(gt);
+            ge = Cudd_Not(ge);
+        }
+    } else {
+        gt = ge = g;
+    }
+
+    tt = cuddBddClosestCube(dd,ft,gt,bound);
+    if (tt == NULL) return(NULL);
+    cuddRef(tt);
+    ctt = separateCube(dd,tt,&dtt);
+    if (ctt == NULL) {
+        Cudd_RecursiveDeref(dd, tt);
+        return(NULL);
+    }
+    cuddRef(ctt);
+    Cudd_RecursiveDeref(dd, tt);
+    minD = dtt;
+    bound = ddMin(bound,minD);
+
+    ee = cuddBddClosestCube(dd,fe,ge,bound);
+    if (ee == NULL) {
+        Cudd_RecursiveDeref(dd, ctt);
+        return(NULL);
+    }
+    cuddRef(ee);
+    cee = separateCube(dd,ee,&dee);
+    if (cee == NULL) {
+        Cudd_RecursiveDeref(dd, ctt);
+        Cudd_RecursiveDeref(dd, ee);
+        return(NULL);
+    }
+    cuddRef(cee);
+    Cudd_RecursiveDeref(dd, ee);
+    minD = ddMin(dtt, dee);
+    if (minD <= CUDD_CONST_INDEX) bound = ddMin(bound,minD-1);
+
+    if (minD > 0 && topf == topg) {
+        DdNode *te = cuddBddClosestCube(dd,ft,ge,bound-1);
+        if (te == NULL) {
+            Cudd_RecursiveDeref(dd, ctt);
+            Cudd_RecursiveDeref(dd, cee);
+            return(NULL);
+        }
+        cuddRef(te);
+        cte = separateCube(dd,te,&dte);
+        if (cte == NULL) {
+            Cudd_RecursiveDeref(dd, ctt);
+            Cudd_RecursiveDeref(dd, cee);
+            Cudd_RecursiveDeref(dd, te);
+            return(NULL);
+        }
+        cuddRef(cte);
+        Cudd_RecursiveDeref(dd, te);
+        dte += 1.0;
+        minD = ddMin(minD, dte);
+    } else {
+        cte = azero;
+        cuddRef(cte);
+        dte = CUDD_CONST_INDEX + 1.0;
+    }
+    if (minD <= CUDD_CONST_INDEX) bound = ddMin(bound,minD-1);
+
+    if (minD > 0 && topf == topg) {
+        DdNode *et = cuddBddClosestCube(dd,fe,gt,bound-1);
+        if (et == NULL) {
+            Cudd_RecursiveDeref(dd, ctt);
+            Cudd_RecursiveDeref(dd, cee);
+            Cudd_RecursiveDeref(dd, cte);
+            return(NULL);
+        }
+        cuddRef(et);
+        cet = separateCube(dd,et,&det);
+        if (cet == NULL) {
+            Cudd_RecursiveDeref(dd, ctt);
+            Cudd_RecursiveDeref(dd, cee);
+            Cudd_RecursiveDeref(dd, cte);
+            Cudd_RecursiveDeref(dd, et);
+            return(NULL);
+        }
+        cuddRef(cet);
+        Cudd_RecursiveDeref(dd, et);
+        det += 1.0;
+        minD = ddMin(minD, det);
+    } else {
+        cet = azero;
+        cuddRef(cet);
+        det = CUDD_CONST_INDEX + 1.0;
+    }
+
+    if (minD == dtt) {
+        if (dtt == dee && ctt == cee) {
+            res = createResult(dd,CUDD_CONST_INDEX,1,ctt,dtt);
+        } else {
+            res = createResult(dd,index,1,ctt,dtt);
+        }
+    } else if (minD == dee) {
+        res = createResult(dd,index,0,cee,dee);
+    } else if (minD == dte) {
+#ifdef DD_DEBUG
+        assert(topf == topg);
+#endif
+        res = createResult(dd,index,1,cte,dte);
+    } else {
+#ifdef DD_DEBUG
+        assert(topf == topg);
+#endif
+        res = createResult(dd,index,0,cet,det);
+    }
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd, ctt);
+        Cudd_RecursiveDeref(dd, cee);
+        Cudd_RecursiveDeref(dd, cte);
+        Cudd_RecursiveDeref(dd, cet);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd, ctt);
+    Cudd_RecursiveDeref(dd, cee);
+    Cudd_RecursiveDeref(dd, cte);
+    Cudd_RecursiveDeref(dd, cet);
+
+    /* Only cache results that are different from azero to avoid
+    ** storing results that depend on the value of the bound. */
+    if ((F->ref != 1 || G->ref != 1) && res != azero)
+        cuddCacheInsert2(dd,(DD_CTFP) Cudd_bddClosestCube, f, g, res);
+
+    cuddDeref(res);
+    return(res);
+
+} /* end of cuddBddClosestCube */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_MinHammingDist.]
+
+  Description [Performs the recursive step of Cudd_MinHammingDist.
+  It is based on the following identity. Let H(f) be the
+  minimum Hamming distance of the minterms of f from the reference
+  minterm. Then:
+  <xmp>
+    H(f) = min(H(f0)+h0,H(f1)+h1)
+  </xmp>
+  where f0 and f1 are the two cofactors of f with respect to its top
+  variable; h0 is 1 if the minterm assigns 1 to the top variable of f;
+  h1 is 1 if the minterm assigns 0 to the top variable of f.
+  The upper bound on the distance is used to bound the depth of the
+  recursion.
+  Returns the minimum distance unless it exceeds the upper bound or
+  computation fails.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_MinHammingDist]
+
+******************************************************************************/
+static int
+cuddMinHammingDistRecur(
+  DdNode * f,
+  int *minterm,
+  DdHashTable * table,
+  int upperBound)
+{
+    DdNode      *F, *Ft, *Fe;
+    double      h, hT, hE;
+    DdNode      *zero, *res;
+    DdManager   *dd = table->manager;
+
+    statLine(dd);
+    if (upperBound == 0) return(0);
+
+    F = Cudd_Regular(f);
+
+    if (cuddIsConstant(F)) {
+        zero = Cudd_Not(DD_ONE(dd));
+        if (f == dd->background || f == zero) {
+            return(upperBound);
+        } else {
+            return(0);
+        }
+    }
+    if ((res = cuddHashTableLookup1(table,f)) != NULL) {
+        h = cuddV(res);
+        if (res->ref == 0) {
+            dd->dead++;
+            dd->constants.dead++;
+        }
+        return((int) h);
+    }
+
+    Ft = cuddT(F); Fe = cuddE(F);
+    if (Cudd_IsComplement(f)) {
+        Ft = Cudd_Not(Ft); Fe = Cudd_Not(Fe);
+    }
+    if (minterm[F->index] == 0) {
+        DdNode *temp = Ft;
+        Ft = Fe; Fe = temp;
+    }
+
+    hT = cuddMinHammingDistRecur(Ft,minterm,table,upperBound);
+    if (hT == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
+    if (hT == 0) {
+        hE = upperBound;
+    } else {
+        hE = cuddMinHammingDistRecur(Fe,minterm,table,upperBound - 1);
+        if (hE == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
+    }
+    h = ddMin(hT, hE + 1);
+
+    if (F->ref != 1) {
+        ptrint fanout = (ptrint) F->ref;
+        cuddSatDec(fanout);
+        res = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) h);
+        if (!cuddHashTableInsert1(table,f,res,fanout)) {
+            cuddRef(res); Cudd_RecursiveDeref(dd, res);
+            return(CUDD_OUT_OF_MEM);
+        }
+    }
+
+    return((int) h);
+
+} /* end of cuddMinHammingDistRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Separates cube from distance.]
+
+  Description [Separates cube from distance.  Returns the cube if
+  successful; NULL otherwise.]
+
+  SideEffects [The distance is returned as a side effect.]
+
+  SeeAlso     [cuddBddClosestCube createResult]
+
+******************************************************************************/
+static DdNode *
+separateCube(
+  DdManager *dd,
+  DdNode *f,
+  CUDD_VALUE_TYPE *distance)
+{
+    DdNode *cube, *t;
+
+    /* One and zero are special cases because the distance is implied. */
+    if (Cudd_IsConstant(f)) {
+        *distance = (f == DD_ONE(dd)) ? 0.0 :
+            (1.0 + (CUDD_VALUE_TYPE) CUDD_CONST_INDEX);
+        return(f);
+    }
+
+    /* Find out which branch points to the distance and replace the top
+    ** node with one pointing to zero instead. */
+    t = cuddT(f);
+    if (Cudd_IsConstant(t) && cuddV(t) <= 0) {
+#ifdef DD_DEBUG
+        assert(!Cudd_IsConstant(cuddE(f)) || cuddE(f) == DD_ONE(dd));
+#endif
+        *distance = -cuddV(t);
+        cube = cuddUniqueInter(dd, f->index, DD_ZERO(dd), cuddE(f));
+    } else {
+#ifdef DD_DEBUG
+        assert(!Cudd_IsConstant(t) || t == DD_ONE(dd));
+#endif
+        *distance = -cuddV(cuddE(f));
+        cube = cuddUniqueInter(dd, f->index, t, DD_ZERO(dd));
+    }
+
+    return(cube);
+
+} /* end of separateCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds a result for cache storage.]
+
+  Description [Builds a result for cache storage.  Returns a pointer
+  to the resulting ADD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddBddClosestCube separateCube]
+
+******************************************************************************/
+static DdNode *
+createResult(
+  DdManager *dd,
+  unsigned int index,
+  unsigned int phase,
+  DdNode *cube,
+  CUDD_VALUE_TYPE distance)
+{
+    DdNode *res, *constant;
+
+    /* Special case.  The cube is either one or zero, and we do not
+    ** add any variables.  Hence, the result is also one or zero,
+    ** and the distance remains implied by the value of the constant. */
+    if (index == CUDD_CONST_INDEX && Cudd_IsConstant(cube)) return(cube);
+
+    constant = cuddUniqueConst(dd,-distance);
+    if (constant == NULL) return(NULL);
+    cuddRef(constant);
+
+    if (index == CUDD_CONST_INDEX) {
+        /* Replace the top node. */
+        if (cuddT(cube) == DD_ZERO(dd)) {
+            res = cuddUniqueInter(dd,cube->index,constant,cuddE(cube));
+        } else {
+            res = cuddUniqueInter(dd,cube->index,cuddT(cube),constant);
+        }
+    } else {
+        /* Add a new top node. */
+#ifdef DD_DEBUG
+        assert(cuddI(dd,index) < cuddI(dd,cube->index));
+#endif
+        if (phase) {
+            res = cuddUniqueInter(dd,index,cube,constant);
+        } else {
+            res = cuddUniqueInter(dd,index,constant,cube);
+        }
+    }
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd, constant);
+        return(NULL);
+    }
+    cuddDeref(constant); /* safe because constant is part of res */
+
+    return(res);
+
+} /* end of createResult */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddRead.c b/abc-build/src/bdd/cudd/cuddRead.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddRead.c
@@ -0,0 +1,525 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddRead.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions to read in a matrix]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_addRead()
+                <li> Cudd_bddRead()
+                </ul>]
+
+  SeeAlso     [cudd_addHarwell.c]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddRead.c,v 1.6 2004/08/13 18:04:50 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads in a sparse matrix.]
+
+  Description [Reads in a sparse matrix specified in a simple format.
+  The first line of the input contains the numbers of rows and columns.
+  The remaining lines contain the elements of the matrix, one per line.
+  Given a background value
+  (specified by the background field of the manager), only the values
+  different from it are explicitly listed.  Each foreground element is
+  described by two integers, i.e., the row and column number, and a
+  real number, i.e., the value.<p>
+  Cudd_addRead produces an ADD that depends on two sets of variables: x
+  and y.  The x variables (x\[0\] ... x\[nx-1\]) encode the row index and
+  the y variables (y\[0\] ... y\[ny-1\]) encode the column index.
+  x\[0\] and y\[0\] are the most significant bits in the indices.
+  The variables may already exist or may be created by the function.
+  The index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.<p>
+  On input, nx and ny hold the numbers
+  of row and column variables already in existence. On output, they
+  hold the numbers of row and column variables actually used by the
+  matrix. When Cudd_addRead creates the variable arrays,
+  the index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.
+  When some variables already exist Cudd_addRead expects the indices
+  of the existing x variables to be bx+i*sx, and the indices of the
+  existing y variables to be by+i*sy.<p>
+  m and n are set to the numbers of rows and columns of the
+  matrix.  Their values on input are immaterial.
+  The ADD for the
+  sparse matrix is returned in E, and its reference count is > 0.
+  Cudd_addRead returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [nx and ny are set to the numbers of row and column
+  variables. m and n are set to the numbers of rows and columns. x and y
+  are possibly extended to represent the array of row and column
+  variables. Similarly for xn and yn_, which hold on return from
+  Cudd_addRead the complements of the row and column variables.]
+
+  SeeAlso     [Cudd_addHarwell Cudd_bddRead]
+
+******************************************************************************/
+int
+Cudd_addRead(
+  FILE * fp /* input file pointer */,
+  DdManager * dd /* DD manager */,
+  DdNode ** E /* characteristic function of the graph */,
+  DdNode *** x /* array of row variables */,
+  DdNode *** y /* array of column variables */,
+  DdNode *** xn /* array of complemented row variables */,
+  DdNode *** yn_ /* array of complemented column variables */,
+  int * nx /* number or row variables */,
+  int * ny /* number or column variables */,
+  int * m /* number of rows */,
+  int * n /* number of columns */,
+  int  bx /* first index of row variables */,
+  int  sx /* step of row variables */,
+  int  by /* first index of column variables */,
+  int  sy /* step of column variables */)
+{
+    DdNode *one, *zero;
+    DdNode *w, *neW;
+    DdNode *minterm1;
+    int u, v, err, i, nv;
+    int lnx, lny;
+    CUDD_VALUE_TYPE val;
+    DdNode **lx, **ly, **lxn, **lyn;
+
+    one = DD_ONE(dd);
+    zero = DD_ZERO(dd);
+
+    err = fscanf(fp, "%d %d", &u, &v);
+    if (err == EOF) {
+        return(0);
+    } else if (err != 2) {
+        return(0);
+    }
+
+    *m = u;
+    /* Compute the number of x variables. */
+    lx = *x; lxn = *xn;
+    u--;        /* row and column numbers start from 0 */
+    for (lnx=0; u > 0; lnx++) {
+        u >>= 1;
+    }
+    /* Here we rely on the fact that REALLOC of a null pointer is
+    ** translates to an ALLOC.
+    */
+    if (lnx > *nx) {
+        *x = lx = ABC_REALLOC(DdNode *, *x, lnx);
+        if (lx == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        *xn = lxn =  ABC_REALLOC(DdNode *, *xn, lnx);
+        if (lxn == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+    }
+
+    *n = v;
+    /* Compute the number of y variables. */
+    ly = *y; lyn = *yn_;
+    v--;        /* row and column numbers start from 0 */
+    for (lny=0; v > 0; lny++) {
+        v >>= 1;
+    }
+    /* Here we rely on the fact that REALLOC of a null pointer is
+    ** translates to an ALLOC.
+    */
+    if (lny > *ny) {
+        *y = ly = ABC_REALLOC(DdNode *, *y, lny);
+        if (ly == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        *yn_ = lyn =  ABC_REALLOC(DdNode *, *yn_, lny);
+        if (lyn == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+    }
+
+    /* Create all new variables. */
+    for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) {
+        do {
+            dd->reordered = 0;
+            lx[i] = cuddUniqueInter(dd, nv, one, zero);
+        } while (dd->reordered == 1);
+        if (lx[i] == NULL) return(0);
+        cuddRef(lx[i]);
+        do {
+            dd->reordered = 0;
+            lxn[i] = cuddUniqueInter(dd, nv, zero, one);
+        } while (dd->reordered == 1);
+        if (lxn[i] == NULL) return(0);
+        cuddRef(lxn[i]);
+    }
+    for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) {
+        do {
+            dd->reordered = 0;
+            ly[i] = cuddUniqueInter(dd, nv, one, zero);
+        } while (dd->reordered == 1);
+        if (ly[i] == NULL) return(0);
+        cuddRef(ly[i]);
+        do {
+            dd->reordered = 0;
+            lyn[i] = cuddUniqueInter(dd, nv, zero, one);
+        } while (dd->reordered == 1);
+        if (lyn[i] == NULL) return(0);
+        cuddRef(lyn[i]);
+    }
+    *nx = lnx;
+    *ny = lny;
+
+    *E = dd->background; /* this call will never cause reordering */
+    cuddRef(*E);
+
+    while (! feof(fp)) {
+        err = fscanf(fp, "%d %d %lf", &u, &v, &val);
+        if (err == EOF) {
+            break;
+        } else if (err != 3) {
+            return(0);
+        } else if (u >= *m || v >= *n || u < 0 || v < 0) {
+            return(0);
+        }
+ 
+        minterm1 = one; cuddRef(minterm1);
+
+        /* Build minterm1 corresponding to this arc */
+        for (i = lnx - 1; i>=0; i--) {
+            if (u & 1) {
+                w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lx[i]);
+            } else {
+                w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lxn[i]);
+            }
+            if (w == NULL) {
+                Cudd_RecursiveDeref(dd, minterm1);
+                return(0);
+            }
+            cuddRef(w);
+            Cudd_RecursiveDeref(dd, minterm1);
+            minterm1 = w;
+            u >>= 1;
+        }
+        for (i = lny - 1; i>=0; i--) {
+            if (v & 1) {
+                w = Cudd_addApply(dd, Cudd_addTimes, minterm1, ly[i]);
+            } else {
+                w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lyn[i]);
+            }
+            if (w == NULL) {
+                Cudd_RecursiveDeref(dd, minterm1);
+                return(0);
+            }
+            cuddRef(w);
+            Cudd_RecursiveDeref(dd, minterm1);
+            minterm1 = w;
+            v >>= 1;
+        }
+        /* Create new constant node if necessary.
+        ** This call will never cause reordering.
+        */
+        neW = cuddUniqueConst(dd, val);
+        if (neW == NULL) {
+            Cudd_RecursiveDeref(dd, minterm1);
+            return(0);
+        }
+        cuddRef(neW);
+
+        w = Cudd_addIte(dd, minterm1, neW, *E);
+        if (w == NULL) {
+            Cudd_RecursiveDeref(dd, minterm1);
+            Cudd_RecursiveDeref(dd, neW);
+            return(0);
+        }
+        cuddRef(w);
+        Cudd_RecursiveDeref(dd, minterm1);
+        Cudd_RecursiveDeref(dd, neW);
+        Cudd_RecursiveDeref(dd, *E);
+        *E = w;
+    }
+    return(1);
+
+} /* end of Cudd_addRead */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads in a graph (without labels) given as a list of arcs.]
+
+  Description [Reads in a graph (without labels) given as an adjacency
+  matrix.  The first line of the input contains the numbers of rows and
+  columns of the adjacency matrix. The remaining lines contain the arcs
+  of the graph, one per line. Each arc is described by two integers,
+  i.e., the row and column number, or the indices of the two endpoints.
+  Cudd_bddRead produces a BDD that depends on two sets of variables: x
+  and y.  The x variables (x\[0\] ... x\[nx-1\]) encode
+  the row index and the y variables (y\[0\] ... y\[ny-1\]) encode the
+  column index. x\[0\] and y\[0\] are the most significant bits in the
+  indices.
+  The variables may already exist or may be created by the function.
+  The index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.<p>
+  On input, nx and ny hold the numbers of row and column variables already
+  in existence. On output, they hold the numbers of row and column
+  variables actually used by the matrix. When Cudd_bddRead creates the
+  variable arrays, the index of x\[i\] is bx+i*sx, and the index of
+  y\[i\] is by+i*sy. When some variables already exist, Cudd_bddRead
+  expects the indices of the existing x variables to be bx+i*sx, and the
+  indices of the existing y variables to be by+i*sy.<p>
+  m and n are set to the numbers of rows and columns of the
+  matrix.  Their values on input are immaterial.  The BDD for the graph
+  is returned in E, and its reference count is > 0. Cudd_bddRead returns
+  1 in case of success; 0 otherwise.]
+
+  SideEffects [nx and ny are set to the numbers of row and column
+  variables. m and n are set to the numbers of rows and columns. x and y
+  are possibly extended to represent the array of row and column
+  variables.]
+
+  SeeAlso     [Cudd_addHarwell Cudd_addRead]
+
+******************************************************************************/
+int
+Cudd_bddRead(
+  FILE * fp /* input file pointer */,
+  DdManager * dd /* DD manager */,
+  DdNode ** E /* characteristic function of the graph */,
+  DdNode *** x /* array of row variables */,
+  DdNode *** y /* array of column variables */,
+  int * nx /* number or row variables */,
+  int * ny /* number or column variables */,
+  int * m /* number of rows */,
+  int * n /* number of columns */,
+  int  bx /* first index of row variables */,
+  int  sx /* step of row variables */,
+  int  by /* first index of column variables */,
+  int  sy /* step of column variables */)
+{
+    DdNode *one, *zero;
+    DdNode *w;
+    DdNode *minterm1;
+    int u, v, err, i, nv;
+    int lnx, lny;
+    DdNode **lx, **ly;
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    err = fscanf(fp, "%d %d", &u, &v);
+    if (err == EOF) {
+        return(0);
+    } else if (err != 2) {
+        return(0);
+    }
+
+    *m = u;
+    /* Compute the number of x variables. */
+    lx = *x;
+    u--;        /* row and column numbers start from 0 */
+    for (lnx=0; u > 0; lnx++) {
+        u >>= 1;
+    }
+    if (lnx > *nx) {
+        *x = lx = ABC_REALLOC(DdNode *, *x, lnx);
+        if (lx == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+    }
+
+    *n = v;
+    /* Compute the number of y variables. */
+    ly = *y;
+    v--;        /* row and column numbers start from 0 */
+    for (lny=0; v > 0; lny++) {
+        v >>= 1;
+    }
+    if (lny > *ny) {
+        *y = ly = ABC_REALLOC(DdNode *, *y, lny);
+        if (ly == NULL) {
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+    }
+
+    /* Create all new variables. */
+    for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) {
+        do {
+            dd->reordered = 0;
+            lx[i] = cuddUniqueInter(dd, nv, one, zero);
+        } while (dd->reordered == 1);
+        if (lx[i] == NULL) return(0);
+        cuddRef(lx[i]);
+    }
+    for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) {
+        do {
+            dd->reordered = 0;
+            ly[i] = cuddUniqueInter(dd, nv, one, zero);
+        } while (dd->reordered == 1);
+        if (ly[i] == NULL) return(0);
+        cuddRef(ly[i]);
+    }
+    *nx = lnx;
+    *ny = lny;
+
+    *E = zero; /* this call will never cause reordering */
+    cuddRef(*E);
+
+    while (! feof(fp)) {
+        err = fscanf(fp, "%d %d", &u, &v);
+        if (err == EOF) {
+            break;
+        } else if (err != 2) {
+            return(0);
+        } else if (u >= *m || v >= *n || u < 0 || v < 0) {
+            return(0);
+        }
+ 
+        minterm1 = one; cuddRef(minterm1);
+
+        /* Build minterm1 corresponding to this arc. */
+        for (i = lnx - 1; i>=0; i--) {
+            if (u & 1) {
+                w = Cudd_bddAnd(dd, minterm1, lx[i]);
+            } else {
+                w = Cudd_bddAnd(dd, minterm1, Cudd_Not(lx[i]));
+            }
+            if (w == NULL) {
+                Cudd_RecursiveDeref(dd, minterm1);
+                return(0);
+            }
+            cuddRef(w);
+            Cudd_RecursiveDeref(dd,minterm1);
+            minterm1 = w;
+            u >>= 1;
+        }
+        for (i = lny - 1; i>=0; i--) {
+            if (v & 1) {
+                w = Cudd_bddAnd(dd, minterm1, ly[i]);
+            } else {
+                w = Cudd_bddAnd(dd, minterm1, Cudd_Not(ly[i]));
+            }
+            if (w == NULL) {
+                Cudd_RecursiveDeref(dd, minterm1);
+                return(0);
+            }
+            cuddRef(w);
+            Cudd_RecursiveDeref(dd, minterm1);
+            minterm1 = w;
+            v >>= 1;
+        }
+
+        w = Cudd_bddAnd(dd, Cudd_Not(minterm1), Cudd_Not(*E));
+        if (w == NULL) {
+            Cudd_RecursiveDeref(dd, minterm1);
+            return(0);
+        }
+        w = Cudd_Not(w);
+        cuddRef(w);
+        Cudd_RecursiveDeref(dd, minterm1);
+        Cudd_RecursiveDeref(dd, *E);
+        *E = w;
+    }
+    return(1);
+
+} /* end of Cudd_bddRead */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddRef.c b/abc-build/src/bdd/cudd/cuddRef.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddRef.c
@@ -0,0 +1,816 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddRef.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions that manipulate the reference counts.]
+
+  Description [External procedures included in this module:
+                    <ul>
+                    <li> Cudd_Ref()
+                    <li> Cudd_RecursiveDeref()
+                    <li> Cudd_IterDerefBdd()
+                    <li> Cudd_DelayedDerefBdd()
+                    <li> Cudd_RecursiveDerefZdd()
+                    <li> Cudd_Deref()
+                    <li> Cudd_CheckZeroRef()
+                    </ul>
+               Internal procedures included in this module:
+                    <ul>
+                    <li> cuddReclaim()
+                    <li> cuddReclaimZdd()
+                    <li> cuddClearDeathRow()
+                    <li> cuddShrinkDeathRow()
+                    <li> cuddIsInDeathRow()
+                    <li> cuddTimesInDeathRow()
+                    </ul>
+              ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddRef.c,v 1.28 2004/08/13 18:04:50 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Increases the reference count of a node, if it is not
+  saturated.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_RecursiveDeref Cudd_Deref]
+
+******************************************************************************/
+void
+Cudd_Ref(
+  DdNode * n)
+{
+
+    n = Cudd_Regular(n);
+
+    cuddSatInc(n->ref);
+
+} /* end of Cudd_Ref */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Decreases the reference count of node n.]
+
+  Description [Decreases the reference count of node n. If n dies,
+  recursively decreases the reference counts of its children.  It is
+  used to dispose of a DD that is no longer needed.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Deref Cudd_Ref Cudd_RecursiveDerefZdd]
+
+******************************************************************************/
+void
+Cudd_RecursiveDeref(
+  DdManager * table,
+  DdNode * n)
+{
+    DdNode *N;
+    int ord;
+    DdNodePtr *stack = table->stack;
+    int SP = 1;
+
+    unsigned int live = table->keys - table->dead;
+    if (live > table->peakLiveNodes) {
+        table->peakLiveNodes = live;
+    }
+
+    N = Cudd_Regular(n);
+
+    do {
+#ifdef DD_DEBUG
+        assert(N->ref != 0);
+#endif
+
+        if (N->ref == 1) {
+            N->ref = 0;
+            table->dead++;
+#ifdef DD_STATS
+            table->nodesDropped++;
+#endif
+            if (cuddIsConstant(N)) {
+                table->constants.dead++;
+                N = stack[--SP];
+            } else {
+                ord = table->perm[N->index];
+                stack[SP++] = Cudd_Regular(cuddE(N));
+                table->subtables[ord].dead++;
+                N = cuddT(N);
+            }
+        } else {
+            cuddSatDec(N->ref);
+            N = stack[--SP];
+        }
+    } while (SP != 0);
+
+} /* end of Cudd_RecursiveDeref */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Decreases the reference count of BDD node n.]
+
+  Description [Decreases the reference count of node n. If n dies,
+  recursively decreases the reference counts of its children.  It is
+  used to dispose of a BDD that is no longer needed. It is more
+  efficient than Cudd_RecursiveDeref, but it cannot be used on
+  ADDs. The greater efficiency comes from being able to assume that no
+  constant node will ever die as a result of a call to this
+  procedure.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_RecursiveDeref Cudd_DelayedDerefBdd]
+
+******************************************************************************/
+void
+Cudd_IterDerefBdd(
+  DdManager * table,
+  DdNode * n)
+{
+    DdNode *N;
+    int ord;
+    DdNodePtr *stack = table->stack;
+    int SP = 1;
+
+    unsigned int live = table->keys - table->dead;
+    if (live > table->peakLiveNodes) {
+        table->peakLiveNodes = live;
+    }
+
+    N = Cudd_Regular(n);
+
+    do {
+#ifdef DD_DEBUG
+        assert(N->ref != 0);
+#endif
+
+        if (N->ref == 1) {
+            N->ref = 0;
+            table->dead++;
+#ifdef DD_STATS
+            table->nodesDropped++;
+#endif
+            ord = table->perm[N->index];
+            stack[SP++] = Cudd_Regular(cuddE(N));
+            table->subtables[ord].dead++;
+            N = cuddT(N);
+        } else {
+            cuddSatDec(N->ref);
+            N = stack[--SP];
+        }
+    } while (SP != 0);
+
+} /* end of Cudd_IterDerefBdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Decreases the reference count of BDD node n.]
+
+  Description [Enqueues node n for later dereferencing. If the queue
+  is full decreases the reference count of the oldest node N to make
+  room for n. If N dies, recursively decreases the reference counts of
+  its children.  It is used to dispose of a BDD that is currently not
+  needed, but may be useful again in the near future. The dereferencing
+  proper is done as in Cudd_IterDerefBdd.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_RecursiveDeref Cudd_IterDerefBdd]
+
+******************************************************************************/
+void
+Cudd_DelayedDerefBdd(
+  DdManager * table,
+  DdNode * n)
+{
+    DdNode *N;
+    int ord;
+    DdNodePtr *stack;
+    int SP;
+
+    unsigned int live = table->keys - table->dead;
+    if (live > table->peakLiveNodes) {
+        table->peakLiveNodes = live;
+    }
+
+    n = Cudd_Regular(n);
+#ifdef DD_DEBUG
+    assert(n->ref != 0);
+#endif
+
+#ifdef DD_NO_DEATH_ROW
+    N = n;
+#else
+    if (cuddIsConstant(n) || n->ref > 1) {
+#ifdef DD_DEBUG
+        assert(n->ref != 1 && (!cuddIsConstant(n) || n == DD_ONE(table)));
+#endif
+        cuddSatDec(n->ref);
+        return;
+    }
+
+    N = table->deathRow[table->nextDead];
+
+    if (N != NULL) {
+#endif
+#ifdef DD_DEBUG
+        assert(!Cudd_IsComplement(N));
+#endif
+        stack = table->stack;
+        SP = 1;
+        do {
+#ifdef DD_DEBUG
+            assert(N->ref != 0);
+#endif
+            if (N->ref == 1) {
+                N->ref = 0;
+                table->dead++;
+#ifdef DD_STATS
+                table->nodesDropped++;
+#endif
+                ord = table->perm[N->index];
+                stack[SP++] = Cudd_Regular(cuddE(N));
+                table->subtables[ord].dead++;
+                N = cuddT(N);
+            } else {
+                cuddSatDec(N->ref);
+                N = stack[--SP];
+            }
+        } while (SP != 0);
+#ifndef DD_NO_DEATH_ROW
+    }
+    table->deathRow[table->nextDead] = n;
+
+    /* Udate insertion point. */
+    table->nextDead++;
+    table->nextDead &= table->deadMask;
+#if 0
+    if (table->nextDead == table->deathRowDepth) {
+        if (table->deathRowDepth < table->looseUpTo / 2) {
+            extern void (*MMoutOfMemory)(long);
+            void (*saveHandler)(long) = MMoutOfMemory;
+            DdNodePtr *newRow;
+            MMoutOfMemory = Cudd_OutOfMem;
+            newRow = ABC_REALLOC(DdNodePtr,table->deathRow,2*table->deathRowDepth);
+            MMoutOfMemory = saveHandler;
+            if (newRow == NULL) {
+                table->nextDead = 0;
+            } else {
+                int i;
+                table->memused += table->deathRowDepth;
+                i = table->deathRowDepth;
+                table->deathRowDepth <<= 1;
+                for (; i < table->deathRowDepth; i++) {
+                    newRow[i] = NULL;
+                }
+                table->deadMask = table->deathRowDepth - 1;
+                table->deathRow = newRow;
+            }
+        } else {
+            table->nextDead = 0;
+        }
+    }
+#endif
+#endif
+
+} /* end of Cudd_DelayedDerefBdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Decreases the reference count of ZDD node n.]
+
+  Description [Decreases the reference count of ZDD node n. If n dies,
+  recursively decreases the reference counts of its children.  It is
+  used to dispose of a ZDD that is no longer needed.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Deref Cudd_Ref Cudd_RecursiveDeref]
+
+******************************************************************************/
+void
+Cudd_RecursiveDerefZdd(
+  DdManager * table,
+  DdNode * n)
+{
+    DdNode *N;
+    int ord;
+    DdNodePtr *stack = table->stack;
+    int SP = 1;
+
+    N = n;
+
+    do {
+#ifdef DD_DEBUG
+        assert(N->ref != 0);
+#endif
+
+        cuddSatDec(N->ref);
+    
+        if (N->ref == 0) {
+            table->deadZ++;
+#ifdef DD_STATS
+            table->nodesDropped++;
+#endif
+#ifdef DD_DEBUG
+            assert(!cuddIsConstant(N));
+#endif
+            ord = table->permZ[N->index];
+            stack[SP++] = cuddE(N);
+            table->subtableZ[ord].dead++;
+            N = cuddT(N);
+        } else {
+            N = stack[--SP];
+        }
+    } while (SP != 0);
+
+} /* end of Cudd_RecursiveDerefZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Decreases the reference count of node.]
+
+  Description [Decreases the reference count of node. It is primarily
+  used in recursive procedures to decrease the ref count of a result
+  node before returning it. This accomplishes the goal of removing the
+  protection applied by a previous Cudd_Ref.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_RecursiveDeref Cudd_RecursiveDerefZdd Cudd_Ref]
+
+******************************************************************************/
+void
+Cudd_Deref(
+  DdNode * node)
+{
+    node = Cudd_Regular(node);
+    cuddSatDec(node->ref);
+
+} /* end of Cudd_Deref */
+
+
+/**Function********************************************************************
+
+  Synopsis [Checks the unique table for nodes with non-zero reference
+  counts.]
+
+  Description [Checks the unique table for nodes with non-zero
+  reference counts. It is normally called before Cudd_Quit to make sure
+  that there are no memory leaks due to missing Cudd_RecursiveDeref's.
+  Takes into account that reference counts may saturate and that the
+  basic constants and the projection functions are referenced by the
+  manager.  Returns the number of nodes with non-zero reference count.
+  (Except for the cases mentioned above.)]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_CheckZeroRef(
+  DdManager * manager)
+{
+    int size;
+    int i, j;
+    int remain; /* the expected number of remaining references to one */
+    DdNodePtr *nodelist;
+    DdNode *node;
+    DdNode *sentinel = &(manager->sentinel);
+    DdSubtable *subtable;
+    int count = 0;
+    int index;
+
+#ifndef DD_NO_DEATH_ROW
+    cuddClearDeathRow(manager);
+#endif
+
+    /* First look at the BDD/ADD subtables. */
+    remain = 1; /* reference from the manager */
+    size = manager->size;
+    remain += 2 * size; /* reference from the BDD projection functions */
+
+    for (i = 0; i < size; i++) {
+        subtable = &(manager->subtables[i]);
+        nodelist = subtable->nodelist;
+        for (j = 0; (unsigned) j < subtable->slots; j++) {
+            node = nodelist[j];
+            while (node != sentinel) {
+                if (node->ref != 0 && node->ref != DD_MAXREF) {
+                    index = (int) node->index;
+                    if (node != manager->vars[index]) {
+                        count++;
+                    } else {
+                        if (node->ref != 1) {
+                            count++;
+                        }
+                    }
+                }
+                node = node->next;
+            }
+        }
+    }
+
+    /* Then look at the ZDD subtables. */
+    size = manager->sizeZ;
+    if (size) /* references from ZDD universe */
+        remain += 2;
+
+    for (i = 0; i < size; i++) {
+        subtable = &(manager->subtableZ[i]);
+        nodelist = subtable->nodelist;
+        for (j = 0; (unsigned) j < subtable->slots; j++) {
+            node = nodelist[j];
+            while (node != NULL) {
+                if (node->ref != 0 && node->ref != DD_MAXREF) {
+                    index = (int) node->index;
+                    if (node == manager->univ[manager->permZ[index]]) {
+                        if (node->ref > 2) {
+                            count++;
+                        }
+                    } else {
+                        count++;
+                    }
+                }
+                node = node->next;
+            }
+        }
+    }
+
+    /* Now examine the constant table. Plusinfinity, minusinfinity, and
+    ** zero are referenced by the manager. One is referenced by the
+    ** manager, by the ZDD universe, and by all projection functions.
+    ** All other nodes should have no references.
+    */
+    nodelist = manager->constants.nodelist;
+    for (j = 0; (unsigned) j < manager->constants.slots; j++) {
+        node = nodelist[j];
+        while (node != NULL) {
+            if (node->ref != 0 && node->ref != DD_MAXREF) {
+                if (node == manager->one) {
+                    if ((int) node->ref != remain) {
+                        count++;
+                    }
+                } else if (node == manager->zero ||
+                node == manager->plusinfinity ||
+                node == manager->minusinfinity) {
+                    if (node->ref != 1) {
+                        count++;
+                    }
+                } else {
+                    count++;
+                }
+            }
+            node = node->next;
+        }
+    }
+    return(count);
+
+} /* end of Cudd_CheckZeroRef */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Brings children of a dead node back.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddReclaimZdd]
+
+******************************************************************************/
+void
+cuddReclaim(
+  DdManager * table,
+  DdNode * n)
+{
+    DdNode *N;
+    int ord;
+    DdNodePtr *stack = table->stack;
+    int SP = 1;
+    double initialDead = table->dead;
+
+    N = Cudd_Regular(n);
+
+#ifdef DD_DEBUG
+    assert(N->ref == 0);
+#endif
+
+    do {
+        if (N->ref == 0) {
+            N->ref = 1;
+            table->dead--;
+            if (cuddIsConstant(N)) {
+                table->constants.dead--;
+                N = stack[--SP];
+            } else {
+                ord = table->perm[N->index];
+                stack[SP++] = Cudd_Regular(cuddE(N));
+                table->subtables[ord].dead--;
+                N = cuddT(N);
+            }
+        } else {
+            cuddSatInc(N->ref);
+            N = stack[--SP];
+        }
+    } while (SP != 0);
+
+    N = Cudd_Regular(n);
+    cuddSatDec(N->ref);
+    table->reclaimed += initialDead - table->dead;
+
+} /* end of cuddReclaim */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Brings children of a dead ZDD node back.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddReclaim]
+
+******************************************************************************/
+void
+cuddReclaimZdd(
+  DdManager * table,
+  DdNode * n)
+{
+    DdNode *N;
+    int ord;
+    DdNodePtr *stack = table->stack;
+    int SP = 1;
+
+    N = n;
+
+#ifdef DD_DEBUG
+    assert(N->ref == 0);
+#endif
+
+    do {
+        cuddSatInc(N->ref);
+
+        if (N->ref == 1) {
+            table->deadZ--;
+            table->reclaimed++;
+#ifdef DD_DEBUG
+            assert(!cuddIsConstant(N));
+#endif
+            ord = table->permZ[N->index];
+            stack[SP++] = cuddE(N);
+            table->subtableZ[ord].dead--;
+            N = cuddT(N);
+        } else {
+            N = stack[--SP];
+        }
+    } while (SP != 0);
+
+    cuddSatDec(n->ref);
+
+} /* end of cuddReclaimZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Shrinks the death row.]
+
+  Description [Shrinks the death row by a factor of four.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddClearDeathRow]
+
+******************************************************************************/
+void
+cuddShrinkDeathRow(
+  DdManager *table)
+{
+#ifndef DD_NO_DEATH_ROW
+    int i;
+
+    if (table->deathRowDepth > 3) {
+        for (i = table->deathRowDepth/4; i < table->deathRowDepth; i++) {
+            if (table->deathRow[i] == NULL) break;
+            Cudd_IterDerefBdd(table,table->deathRow[i]);
+            table->deathRow[i] = NULL;
+        }
+        table->deathRowDepth /= 4;
+        table->deadMask = table->deathRowDepth - 1;
+        if ((unsigned) table->nextDead > table->deadMask) {
+            table->nextDead = 0;
+        }
+        table->deathRow = ABC_REALLOC(DdNodePtr, table->deathRow,
+                                   table->deathRowDepth);
+    }
+#endif
+
+} /* end of cuddShrinkDeathRow */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Clears the death row.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DelayedDerefBdd Cudd_IterDerefBdd Cudd_CheckZeroRef
+  cuddGarbageCollect]
+
+******************************************************************************/
+void
+cuddClearDeathRow(
+  DdManager *table)
+{
+#ifndef DD_NO_DEATH_ROW
+    int i;
+
+    for (i = 0; i < table->deathRowDepth; i++) {
+        if (table->deathRow[i] == NULL) break;
+        Cudd_IterDerefBdd(table,table->deathRow[i]);
+        table->deathRow[i] = NULL;
+    }
+#ifdef DD_DEBUG
+    for (; i < table->deathRowDepth; i++) {
+        assert(table->deathRow[i] == NULL);
+    }
+#endif
+    table->nextDead = 0;
+#endif
+
+} /* end of cuddClearDeathRow */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a node is in the death row.]
+
+  Description [Checks whether a node is in the death row. Returns the
+  position of the first occurrence if the node is present; -1
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DelayedDerefBdd cuddClearDeathRow]
+
+******************************************************************************/
+int
+cuddIsInDeathRow(
+  DdManager *dd,
+  DdNode *f)
+{
+#ifndef DD_NO_DEATH_ROW
+    int i;
+
+    for (i = 0; i < dd->deathRowDepth; i++) {
+        if (f == dd->deathRow[i]) {
+            return(i);
+        }
+    }
+#endif
+
+    return(-1);
+
+} /* end of cuddIsInDeathRow */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts how many times a node is in the death row.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DelayedDerefBdd cuddClearDeathRow cuddIsInDeathRow]
+
+******************************************************************************/
+int
+cuddTimesInDeathRow(
+  DdManager *dd,
+  DdNode *f)
+{
+    int count = 0;
+#ifndef DD_NO_DEATH_ROW
+    int i;
+
+    for (i = 0; i < dd->deathRowDepth; i++) {
+        count += f == dd->deathRow[i];
+    }
+#endif
+
+    return(count);
+
+} /* end of cuddTimesInDeathRow */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddReorder.c b/abc-build/src/bdd/cudd/cuddReorder.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddReorder.c
@@ -0,0 +1,2142 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddReorder.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for dynamic variable reordering.]
+
+  Description [External procedures included in this file:
+                <ul>
+                <li> Cudd_ReduceHeap()
+                <li> Cudd_ShuffleHeap()
+                </ul>
+        Internal procedures included in this module:
+                <ul>
+                <li> cuddDynamicAllocNode()
+                <li> cuddSifting()
+                <li> cuddSwapping()
+                <li> cuddNextHigh()
+                <li> cuddNextLow()
+                <li> cuddSwapInPlace()
+                <li> cuddBddAlignToZdd()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> ddUniqueCompare()
+                <li> ddSwapAny()
+                <li> ddSiftingAux()
+                <li> ddSiftingUp()
+                <li> ddSiftingDown()
+                <li> ddSiftingBackward()
+                <li> ddReorderPreprocess()
+                <li> ddReorderPostprocess()
+                <li> ddShuffle()
+                <li> ddSiftUp()
+                <li> bddFixTree()
+                </ul>]
+
+  Author      [Shipra Panda, Bernard Plessier, Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DD_MAX_SUBTABLE_SPARSITY 8
+#define DD_SHRINK_FACTOR 2
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddReorder.c,v 1.69 2009/02/21 18:24:10 fabio Exp $";
+#endif
+
+static  int     *entry;
+
+int     ddTotalNumberSwapping;
+#ifdef DD_STATS
+int     ddTotalNISwaps;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int ddUniqueCompare (int *ptrX, int *ptrY);
+static Move * ddSwapAny (DdManager *table, int x, int y);
+static int ddSiftingAux (DdManager *table, int x, int xLow, int xHigh);
+static Move * ddSiftingUp (DdManager *table, int y, int xLow);
+static Move * ddSiftingDown (DdManager *table, int x, int xHigh);
+static int ddSiftingBackward (DdManager *table, int size, Move *moves);
+static int ddReorderPreprocess (DdManager *table);
+static int ddReorderPostprocess (DdManager *table);
+static int ddShuffle (DdManager *table, int *permutation);
+static int ddSiftUp (DdManager *table, int x, int xLow);
+static void bddFixTree (DdManager *table, MtrNode *treenode);
+static int ddUpdateMtrTree (DdManager *table, MtrNode *treenode, int *perm, int *invperm);
+static int ddCheckPermuation (DdManager *table, MtrNode *treenode, int *perm, int *invperm);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Main dynamic reordering routine.]
+
+  Description [Main dynamic reordering routine.
+  Calls one of the possible reordering procedures:
+  <ul>
+  <li>Swapping
+  <li>Sifting
+  <li>Symmetric Sifting
+  <li>Group Sifting
+  <li>Window Permutation
+  <li>Simulated Annealing
+  <li>Genetic Algorithm
+  <li>Dynamic Programming (exact)
+  </ul>
+
+  For sifting, symmetric sifting, group sifting, and window
+  permutation it is possible to request reordering to convergence.<p>
+
+  The core of all methods is the reordering procedure
+  cuddSwapInPlace() which swaps two adjacent variables and is based
+  on Rudell's paper.
+  Returns 1 in case of success; 0 otherwise. In the case of symmetric
+  sifting (with and without convergence) returns 1 plus the number of
+  symmetric variables, in case of success.]
+
+  SideEffects [Changes the variable order for all diagrams and clears
+  the cache.]
+
+******************************************************************************/
+int
+Cudd_ReduceHeap(
+  DdManager * table /* DD manager */,
+  Cudd_ReorderingType heuristic /* method used for reordering */,
+  int  minsize /* bound below which no reordering occurs */)
+{
+    DdHook *hook;
+    int result;
+    unsigned int nextDyn;
+#ifdef DD_STATS
+    unsigned int initialSize;
+    unsigned int finalSize;
+#endif
+    long localTime;
+
+    /* Don't reorder if there are too many dead nodes. */
+    if (table->keys - table->dead < (unsigned) minsize)
+        return(1);
+
+    if (heuristic == CUDD_REORDER_SAME) {
+        heuristic = table->autoMethod;
+    }
+    if (heuristic == CUDD_REORDER_NONE) {
+        return(1);
+    }
+
+    /* This call to Cudd_ReduceHeap does initiate reordering. Therefore
+    ** we count it.
+    */
+    table->reorderings++;
+
+    localTime = util_cpu_time();
+
+    /* Run the hook functions. */
+    hook = table->preReorderingHook;
+    while (hook != NULL) {
+        int res = (hook->f)(table, "BDD", (void *)heuristic);
+        if (res == 0) return(0);
+        hook = hook->next;
+    }
+
+    if (!ddReorderPreprocess(table)) return(0);
+    ddTotalNumberSwapping = 0;
+
+    if (table->keys > table->peakLiveNodes) {
+        table->peakLiveNodes = table->keys;
+    }
+#ifdef DD_STATS
+    initialSize = table->keys - table->isolated;
+    ddTotalNISwaps = 0;
+
+    switch(heuristic) {
+    case CUDD_REORDER_RANDOM:
+    case CUDD_REORDER_RANDOM_PIVOT:
+        (void) fprintf(table->out,"#:I_RANDOM  ");
+        break;
+    case CUDD_REORDER_SIFT:
+    case CUDD_REORDER_SIFT_CONVERGE:
+    case CUDD_REORDER_SYMM_SIFT:
+    case CUDD_REORDER_SYMM_SIFT_CONV:
+    case CUDD_REORDER_GROUP_SIFT:
+    case CUDD_REORDER_GROUP_SIFT_CONV:
+        (void) fprintf(table->out,"#:I_SIFTING ");
+        break;
+    case CUDD_REORDER_WINDOW2:
+    case CUDD_REORDER_WINDOW3:
+    case CUDD_REORDER_WINDOW4:
+    case CUDD_REORDER_WINDOW2_CONV:
+    case CUDD_REORDER_WINDOW3_CONV:
+    case CUDD_REORDER_WINDOW4_CONV:
+        (void) fprintf(table->out,"#:I_WINDOW  ");
+        break;
+    case CUDD_REORDER_ANNEALING:
+        (void) fprintf(table->out,"#:I_ANNEAL  ");
+        break;
+    case CUDD_REORDER_GENETIC:
+        (void) fprintf(table->out,"#:I_GENETIC ");
+        break;
+    case CUDD_REORDER_LINEAR:
+    case CUDD_REORDER_LINEAR_CONVERGE:
+        (void) fprintf(table->out,"#:I_LINSIFT ");
+        break;
+    case CUDD_REORDER_EXACT:
+        (void) fprintf(table->out,"#:I_EXACT   ");
+        break;
+    default:
+        return(0);
+    }
+    (void) fprintf(table->out,"%8d: initial size",initialSize);
+#endif
+
+    /* See if we should use alternate threshold for maximum growth. */
+    if (table->reordCycle && table->reorderings % table->reordCycle == 0) {
+        double saveGrowth = table->maxGrowth;
+        table->maxGrowth = table->maxGrowthAlt;
+        result = cuddTreeSifting(table,heuristic);
+        table->maxGrowth = saveGrowth;
+    } else {
+        result = cuddTreeSifting(table,heuristic);
+    }
+
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n");
+    finalSize = table->keys - table->isolated;
+    (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize);
+    (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n",
+                   ((double)(util_cpu_time() - localTime)/1000.0));
+    (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n",
+                   ddTotalNumberSwapping);
+    (void) fprintf(table->out,"#:M_REORDER %8d: NI swaps\n",ddTotalNISwaps);
+#endif
+
+    if (result == 0)
+        return(0);
+
+    if (!ddReorderPostprocess(table))
+        return(0);
+
+    if (table->realign) {
+        if (!cuddZddAlignToBdd(table))
+            return(0);
+    }
+
+    nextDyn = (table->keys - table->constants.keys + 1) *
+              DD_DYN_RATIO + table->constants.keys;
+    if (table->reorderings < 20 || nextDyn > table->nextDyn)
+        table->nextDyn = nextDyn;
+    else
+        table->nextDyn += 20;
+    table->reordered = 1;
+
+    /* Run hook functions. */
+    hook = table->postReorderingHook;
+    while (hook != NULL) {
+        int res = (hook->f)(table, "BDD", (void *)localTime);
+        if (res == 0) return(0);
+        hook = hook->next;
+    }
+    /* Update cumulative reordering time. */
+    table->reordTime += util_cpu_time() - localTime;
+
+    return(result);
+
+} /* end of Cudd_ReduceHeap */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders variables according to given permutation.]
+
+  Description [Reorders variables according to given permutation.
+  The i-th entry of the permutation array contains the index of the variable
+  that should be brought to the i-th level.  The size of the array should be
+  equal or greater to the number of variables currently in use.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [Changes the variable order for all diagrams and clears
+  the cache.]
+
+  SeeAlso [Cudd_ReduceHeap]
+
+******************************************************************************/
+int
+Cudd_ShuffleHeap(
+  DdManager * table /* DD manager */,
+  int * permutation /* required variable permutation */)
+{
+
+    int result;
+    int i;
+    int identity = 1;
+    int *perm;
+
+    /* Don't waste time in case of identity permutation. */
+    for (i = 0; i < table->size; i++) {
+        if (permutation[i] != table->invperm[i]) {
+            identity = 0;
+            break;
+        }
+    }
+    if (identity == 1) {
+        return(1);
+    }
+    if (!ddReorderPreprocess(table)) return(0);
+    if (table->keys > table->peakLiveNodes) {
+        table->peakLiveNodes = table->keys;
+    }
+
+    perm = ABC_ALLOC(int, table->size);
+    for (i = 0; i < table->size; i++)
+        perm[permutation[i]] = i;
+    if (!ddCheckPermuation(table,table->tree,perm,permutation)) {
+        ABC_FREE(perm);
+        return(0);
+    }
+    if (!ddUpdateMtrTree(table,table->tree,perm,permutation)) {
+        ABC_FREE(perm);
+        return(0);
+    }
+    ABC_FREE(perm);
+
+    result = ddShuffle(table,permutation);
+
+    if (!ddReorderPostprocess(table)) return(0);
+
+    return(result);
+
+} /* end of Cudd_ShuffleHeap */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Dynamically allocates a Node.]
+
+  Description [Dynamically allocates a Node. This procedure is similar
+  to cuddAllocNode in Cudd_Table.c, but it does not attempt garbage
+  collection, because during reordering there are no dead nodes.
+  Returns a pointer to a new node if successful; NULL is memory is
+  full.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddAllocNode]
+
+******************************************************************************/
+DdNode *
+cuddDynamicAllocNode(
+  DdManager * table)
+{
+    int     i;
+    DdNodePtr *mem;
+    DdNode *list, *node;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    if (table->nextFree == NULL) {        /* free list is empty */
+        /* Try to allocate a new block. */
+        saveHandler = MMoutOfMemory;
+        MMoutOfMemory = Cudd_OutOfMem;
+//        mem = (DdNodePtr *) ABC_ALLOC(DdNode, DD_MEM_CHUNK + 1);
+        mem = (DdNodePtr *) ABC_ALLOC(DdNode, DD_MEM_CHUNK + 2);
+        MMoutOfMemory = saveHandler;
+        if (mem == NULL && table->stash != NULL) {
+            ABC_FREE(table->stash);
+            table->stash = NULL;
+            /* Inhibit resizing of tables. */
+            table->maxCacheHard = table->cacheSlots - 1;
+            table->cacheSlack = - (int) (table->cacheSlots + 1);
+            for (i = 0; i < table->size; i++) {
+                table->subtables[i].maxKeys <<= 2;
+            }
+//            mem = (DdNodePtr *) ABC_ALLOC(DdNode,DD_MEM_CHUNK + 1);
+            mem = (DdNodePtr *) ABC_ALLOC(DdNode,DD_MEM_CHUNK + 2);
+        }
+        if (mem == NULL) {
+            /* Out of luck. Call the default handler to do
+            ** whatever it specifies for a failed malloc.  If this
+            ** handler returns, then set error code, print
+            ** warning, and return. */
+            (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1));
+            table->errorCode = CUDD_MEMORY_OUT;
+#ifdef DD_VERBOSE
+            (void) fprintf(table->err,
+                           "cuddDynamicAllocNode: out of memory");
+            (void) fprintf(table->err,"Memory in use = %lu\n",
+                           table->memused);
+#endif
+            return(NULL);
+        } else {        /* successful allocation; slice memory */
+            unsigned long offset;
+            table->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode);
+            mem[0] = (DdNode *) table->memoryList;
+            table->memoryList = mem;
+
+            /* Here we rely on the fact that the size of a DdNode is a
+            ** power of 2 and a multiple of the size of a pointer.
+            ** If we align one node, all the others will be aligned
+            ** as well. */
+//            offset = (unsigned long) mem & (sizeof(DdNode) - 1);
+//            mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
+            offset = (unsigned long) mem & (32 - 1);
+            mem += (32 - offset) / sizeof(DdNodePtr);
+#ifdef DD_DEBUG
+//            assert(((unsigned long) mem & (sizeof(DdNode) - 1)) == 0);
+            assert(((unsigned long) mem & (32 - 1)) == 0);
+#endif
+            list = (DdNode *) mem;
+
+            i = 1;
+            do {
+                list[i - 1].ref = 0;
+                list[i - 1].next = &list[i];
+            } while (++i < DD_MEM_CHUNK);
+
+            list[DD_MEM_CHUNK-1].ref = 0;
+            list[DD_MEM_CHUNK - 1].next = NULL;
+
+            table->nextFree = &list[0];
+        }
+    } /* if free list empty */
+
+    node = table->nextFree;
+    table->nextFree = node->next;
+    return (node);
+
+} /* end of cuddDynamicAllocNode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implementation of Rudell's sifting algorithm.]
+
+  Description [Implementation of Rudell's sifting algorithm.
+  Assumes that no dead nodes are present.
+    <ol>
+    <li> Order all the variables according to the number of entries
+    in each unique table.
+    <li> Sift the variable up and down, remembering each time the
+    total size of the DD heap.
+    <li> Select the best permutation.
+    <li> Repeat 3 and 4 for all variables.
+    </ol>
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+cuddSifting(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int i;
+    int *var;
+    int size;
+    int x;
+    int result;
+#ifdef DD_STATS
+    int previousSize;
+#endif
+
+    size = table->size;
+
+    /* Find order in which to sift variables. */
+    var = NULL;
+    entry = ABC_ALLOC(int,size);
+    if (entry == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto cuddSiftingOutOfMem;
+    }
+    var = ABC_ALLOC(int,size);
+    if (var == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto cuddSiftingOutOfMem;
+    }
+
+    for (i = 0; i < size; i++) {
+        x = table->perm[i];
+        entry[i] = table->subtables[x].keys;
+        var[i] = i;
+    }
+
+    qsort((void *)var,size,sizeof(int),(DD_QSFP)ddUniqueCompare);
+
+    /* Now sift. */
+    for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
+        if (ddTotalNumberSwapping >= table->siftMaxSwap)
+            break;
+        x = table->perm[var[i]];
+
+        if (x < lower || x > upper || table->subtables[x].bindVar == 1)
+            continue;
+#ifdef DD_STATS
+        previousSize = table->keys - table->isolated;
+#endif
+        result = ddSiftingAux(table, x, lower, upper);
+        if (!result) goto cuddSiftingOutOfMem;
+#ifdef DD_STATS
+        if (table->keys < (unsigned) previousSize + table->isolated) {
+            (void) fprintf(table->out,"-");
+        } else if (table->keys > (unsigned) previousSize + table->isolated) {
+            (void) fprintf(table->out,"+");     /* should never happen */
+            (void) fprintf(table->err,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
+        } else {
+            (void) fprintf(table->out,"=");
+        }
+        fflush(table->out);
+#endif
+    }
+
+    ABC_FREE(var);
+    ABC_FREE(entry);
+
+    return(1);
+
+cuddSiftingOutOfMem:
+
+    if (entry != NULL) ABC_FREE(entry);
+    if (var != NULL) ABC_FREE(var);
+
+    return(0);
+
+} /* end of cuddSifting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders variables by a sequence of (non-adjacent) swaps.]
+
+  Description [Implementation of Plessier's algorithm that reorders
+  variables by a sequence of (non-adjacent) swaps.
+    <ol>
+    <li> Select two variables (RANDOM or HEURISTIC).
+    <li> Permute these variables.
+    <li> If the nodes have decreased accept the permutation.
+    <li> Otherwise reconstruct the original heap.
+    <li> Loop.
+    </ol>
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+cuddSwapping(
+  DdManager * table,
+  int lower,
+  int upper,
+  Cudd_ReorderingType heuristic)
+{
+    int i, j;
+    int max, keys;
+    int nvars;
+    int x, y;
+    int iterate;
+    int previousSize;
+    Move *moves, *move;
+    int pivot = -1;
+    int modulo;
+    int result;
+
+#ifdef DD_DEBUG
+    /* Sanity check */
+    assert(lower >= 0 && upper < table->size && lower <= upper);
+#endif
+
+    nvars = upper - lower + 1;
+    iterate = nvars;
+
+    for (i = 0; i < iterate; i++) {
+        if (ddTotalNumberSwapping >= table->siftMaxSwap)
+            break;
+        if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
+            max = -1;
+            for (j = lower; j <= upper; j++) {
+                if ((keys = table->subtables[j].keys) > max) {
+                    max = keys;
+                    pivot = j;
+                }
+            }
+
+            modulo = upper - pivot;
+            if (modulo == 0) {
+                y = pivot;
+            } else{
+                y = pivot + 1 + ((int) Cudd_Random() % modulo);
+            }
+
+            modulo = pivot - lower - 1;
+            if (modulo < 1) {
+                x = lower;
+            } else{
+                do {
+                    x = (int) Cudd_Random() % modulo;
+                } while (x == y);
+            }
+        } else {
+            x = ((int) Cudd_Random() % nvars) + lower;
+            do {
+                y = ((int) Cudd_Random() % nvars) + lower;
+            } while (x == y);
+        }
+        previousSize = table->keys - table->isolated;
+        moves = ddSwapAny(table,x,y);
+        if (moves == NULL) goto cuddSwappingOutOfMem;
+        result = ddSiftingBackward(table,previousSize,moves);
+        if (!result) goto cuddSwappingOutOfMem;
+        while (moves != NULL) {
+            move = moves->next;
+            cuddDeallocMove(table, moves);
+            moves = move;
+        }
+#ifdef DD_STATS
+        if (table->keys < (unsigned) previousSize + table->isolated) {
+            (void) fprintf(table->out,"-");
+        } else if (table->keys > (unsigned) previousSize + table->isolated) {
+            (void) fprintf(table->out,"+");     /* should never happen */
+        } else {
+            (void) fprintf(table->out,"=");
+        }
+        fflush(table->out);
+#endif
+#if 0
+        (void) fprintf(table->out,"#:t_SWAPPING %8d: tmp size\n",
+                       table->keys - table->isolated);
+#endif
+    }
+
+    return(1);
+
+cuddSwappingOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+
+    return(0);
+
+} /* end of cuddSwapping */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the next subtable with a larger index.]
+
+  Description [Finds the next subtable with a larger index. Returns the
+  index.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddNextLow]
+
+******************************************************************************/
+int
+cuddNextHigh(
+  DdManager * table,
+  int  x)
+{
+    return(x+1);
+
+} /* end of cuddNextHigh */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the next subtable with a smaller index.]
+
+  Description [Finds the next subtable with a smaller index. Returns the
+  index.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddNextHigh]
+
+******************************************************************************/
+int
+cuddNextLow(
+  DdManager * table,
+  int  x)
+{
+    return(x-1);
+
+} /* end of cuddNextLow */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Swaps two adjacent variables.]
+
+  Description [Swaps two adjacent variables. It assumes that no dead
+  nodes are present on entry to this procedure.  The procedure then
+  guarantees that no dead nodes will be present when it terminates.
+  cuddSwapInPlace assumes that x &lt; y.  Returns the number of keys in
+  the table if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+cuddSwapInPlace(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    DdNodePtr *xlist, *ylist;
+    int    xindex, yindex;
+    int    xslots, yslots;
+    int    xshift, yshift;
+    int    oldxkeys, oldykeys;
+    int    newxkeys, newykeys;
+    int    comple, newcomplement;
+    int    i;
+    Cudd_VariableType varType;
+    Cudd_LazyGroupType groupType;
+    int    posn;
+    int    isolated;
+    DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
+    DdNode *g,*next;
+    DdNodePtr *previousP;
+    DdNode *tmp;
+    DdNode *sentinel = &(table->sentinel);
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+#ifdef DD_DEBUG
+    int    count,idcheck;
+#endif
+
+#ifdef DD_DEBUG
+    assert(x < y);
+    assert(cuddNextHigh(table,x) == y);
+    assert(table->subtables[x].keys != 0);
+    assert(table->subtables[y].keys != 0);
+    assert(table->subtables[x].dead == 0);
+    assert(table->subtables[y].dead == 0);
+#endif
+
+    ddTotalNumberSwapping++;
+
+    /* Get parameters of x subtable. */
+    xindex = table->invperm[x];
+    xlist = table->subtables[x].nodelist;
+    oldxkeys = table->subtables[x].keys;
+    xslots = table->subtables[x].slots;
+    xshift = table->subtables[x].shift;
+
+    /* Get parameters of y subtable. */
+    yindex = table->invperm[y];
+    ylist = table->subtables[y].nodelist;
+    oldykeys = table->subtables[y].keys;
+    yslots = table->subtables[y].slots;
+    yshift = table->subtables[y].shift;
+
+    if (!cuddTestInteract(table,xindex,yindex)) {
+#ifdef DD_STATS
+        ddTotalNISwaps++;
+#endif
+        newxkeys = oldxkeys;
+        newykeys = oldykeys;
+    } else {
+        newxkeys = 0;
+        newykeys = oldykeys;
+
+        /* Check whether the two projection functions involved in this
+        ** swap are isolated. At the end, we'll be able to tell how many
+        ** isolated projection functions are there by checking only these
+        ** two functions again. This is done to eliminate the isolated
+        ** projection functions from the node count.
+        */
+        isolated = - ((table->vars[xindex]->ref == 1) +
+                     (table->vars[yindex]->ref == 1));
+
+        /* The nodes in the x layer that do not depend on
+        ** y will stay there; the others are put in a chain.
+        ** The chain is handled as a LIFO; g points to the beginning.
+        */
+        g = NULL;
+        if ((oldxkeys >= xslots || (unsigned) xslots == table->initSlots) &&
+            oldxkeys <= DD_MAX_SUBTABLE_DENSITY * xslots) {
+            for (i = 0; i < xslots; i++) {
+                previousP = &(xlist[i]);
+                f = *previousP;
+                while (f != sentinel) {
+                    next = f->next;
+                    f1 = cuddT(f); f0 = cuddE(f);
+                    if (f1->index != (DdHalfWord) yindex &&
+                        Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
+                        /* stays */
+                        newxkeys++;
+                        *previousP = f;
+                        previousP = &(f->next);
+                    } else {
+                        f->index = yindex;
+                        f->next = g;
+                        g = f;
+                    }
+                    f = next;
+                } /* while there are elements in the collision chain */
+                *previousP = sentinel;
+            } /* for each slot of the x subtable */
+        } else {                /* resize xlist */
+            DdNode *h = NULL;
+            DdNodePtr *newxlist;
+            unsigned int newxslots;
+            int newxshift;
+            /* Empty current xlist. Nodes that stay go to list h;
+            ** nodes that move go to list g. */
+            for (i = 0; i < xslots; i++) {
+                f = xlist[i];
+                while (f != sentinel) {
+                    next = f->next;
+                    f1 = cuddT(f); f0 = cuddE(f);
+                    if (f1->index != (DdHalfWord) yindex &&
+                        Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
+                        /* stays */
+                        f->next = h;
+                        h = f;
+                        newxkeys++;
+                    } else {
+                        f->index = yindex;
+                        f->next = g;
+                        g = f;
+                    }
+                    f = next;
+                } /* while there are elements in the collision chain */
+            } /* for each slot of the x subtable */
+            /* Decide size of new subtable. */
+            newxshift = xshift;
+            newxslots = xslots;
+            while ((unsigned) oldxkeys > DD_MAX_SUBTABLE_DENSITY * newxslots) {
+                newxshift--;
+                newxslots <<= 1;
+            }
+            while ((unsigned) oldxkeys < newxslots &&
+                   newxslots > table->initSlots) {
+                newxshift++;
+                newxslots >>= 1;
+            }
+            /* Try to allocate new table. Be ready to back off. */
+            saveHandler = MMoutOfMemory;
+            MMoutOfMemory = Cudd_OutOfMem;
+            newxlist = ABC_ALLOC(DdNodePtr, newxslots);
+            MMoutOfMemory = saveHandler;
+            if (newxlist == NULL) {
+                (void) fprintf(table->err, "Unable to resize subtable %d for lack of memory\n", i);
+                newxlist = xlist;
+                newxslots = xslots;
+                newxshift = xshift;
+            } else {
+                table->slots += ((int) newxslots - xslots);
+                table->minDead = (unsigned)
+                    (table->gcFrac * (double) table->slots);
+                table->cacheSlack = (int)
+                    ddMin(table->maxCacheHard, DD_MAX_CACHE_TO_SLOTS_RATIO
+                          * table->slots) - 2 * (int) table->cacheSlots;
+                table->memused +=
+                    ((int) newxslots - xslots) * sizeof(DdNodePtr);
+                ABC_FREE(xlist);
+                xslots =  newxslots;
+                xshift = newxshift;
+                xlist = newxlist;
+            }
+            /* Initialize new subtable. */
+            for (i = 0; i < xslots; i++) {
+                xlist[i] = sentinel;
+            }
+            /* Move nodes that were parked in list h to their new home. */
+            f = h;
+            while (f != NULL) {
+                next = f->next;
+                f1 = cuddT(f);
+                f0 = cuddE(f);
+                /* Check xlist for pair (f11,f01). */
+                posn = ddHash(cuddF2L(f1), cuddF2L(f0), xshift);
+                /* For each element tmp in collision list xlist[posn]. */
+                previousP = &(xlist[posn]);
+                tmp = *previousP;
+                while (f1 < cuddT(tmp)) {
+                    previousP = &(tmp->next);
+                    tmp = *previousP;
+                }
+                while (f1 == cuddT(tmp) && f0 < cuddE(tmp)) {
+                    previousP = &(tmp->next);
+                    tmp = *previousP;
+                }
+                f->next = *previousP;
+                *previousP = f;
+                f = next;
+            }
+        }
+
+#ifdef DD_COUNT
+        table->swapSteps += oldxkeys - newxkeys;
+#endif
+        /* Take care of the x nodes that must be re-expressed.
+        ** They form a linked list pointed by g. Their index has been
+        ** already changed to yindex.
+        */
+        f = g;
+        while (f != NULL) {
+            next = f->next;
+            /* Find f1, f0, f11, f10, f01, f00. */
+            f1 = cuddT(f);
+#ifdef DD_DEBUG
+            assert(!(Cudd_IsComplement(f1)));
+#endif
+            if ((int) f1->index == yindex) {
+                f11 = cuddT(f1); f10 = cuddE(f1);
+            } else {
+                f11 = f10 = f1;
+            }
+#ifdef DD_DEBUG
+            assert(!(Cudd_IsComplement(f11)));
+#endif
+            f0 = cuddE(f);
+            comple = Cudd_IsComplement(f0);
+            f0 = Cudd_Regular(f0);
+            if ((int) f0->index == yindex) {
+                f01 = cuddT(f0); f00 = cuddE(f0);
+            } else {
+                f01 = f00 = f0;
+            }
+            if (comple) {
+                f01 = Cudd_Not(f01);
+                f00 = Cudd_Not(f00);
+            }
+            /* Decrease ref count of f1. */
+            cuddSatDec(f1->ref);
+            /* Create the new T child. */
+            if (f11 == f01) {
+                newf1 = f11;
+                cuddSatInc(newf1->ref);
+            } else {
+                /* Check xlist for triple (xindex,f11,f01). */
+                posn = ddHash(cuddF2L(f11), cuddF2L(f01), xshift);
+                /* For each element newf1 in collision list xlist[posn]. */
+                previousP = &(xlist[posn]);
+                newf1 = *previousP;
+                while (f11 < cuddT(newf1)) {
+                    previousP = &(newf1->next);
+                    newf1 = *previousP;
+                }
+                while (f11 == cuddT(newf1) && f01 < cuddE(newf1)) {
+                    previousP = &(newf1->next);
+                    newf1 = *previousP;
+                }
+                if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
+                    cuddSatInc(newf1->ref);
+                } else { /* no match */
+                    newf1 = cuddDynamicAllocNode(table);
+                    if (newf1 == NULL)
+                        goto cuddSwapOutOfMem;
+                    newf1->index = xindex; newf1->ref = 1;
+                    cuddT(newf1) = f11;
+                    cuddE(newf1) = f01;
+                    /* Insert newf1 in the collision list xlist[posn];
+                    ** increase the ref counts of f11 and f01.
+                    */
+                    newxkeys++;
+                    newf1->next = *previousP;
+                    *previousP = newf1;
+                    cuddSatInc(f11->ref);
+                    tmp = Cudd_Regular(f01);
+                    cuddSatInc(tmp->ref);
+                }
+            }
+            cuddT(f) = newf1;
+#ifdef DD_DEBUG
+            assert(!(Cudd_IsComplement(newf1)));
+#endif
+
+            /* Do the same for f0, keeping complement dots into account. */
+            /* Decrease ref count of f0. */
+            tmp = Cudd_Regular(f0);
+            cuddSatDec(tmp->ref);
+            /* Create the new E child. */
+            if (f10 == f00) {
+                newf0 = f00;
+                tmp = Cudd_Regular(newf0);
+                cuddSatInc(tmp->ref);
+            } else {
+                /* make sure f10 is regular */
+                newcomplement = Cudd_IsComplement(f10);
+                if (newcomplement) {
+                    f10 = Cudd_Not(f10);
+                    f00 = Cudd_Not(f00);
+                }
+                /* Check xlist for triple (xindex,f10,f00). */
+                posn = ddHash(cuddF2L(f10), cuddF2L(f00), xshift);
+                /* For each element newf0 in collision list xlist[posn]. */
+                previousP = &(xlist[posn]);
+                newf0 = *previousP;
+                while (f10 < cuddT(newf0)) {
+                    previousP = &(newf0->next);
+                    newf0 = *previousP;
+                }
+                while (f10 == cuddT(newf0) && f00 < cuddE(newf0)) {
+                    previousP = &(newf0->next);
+                    newf0 = *previousP;
+                }
+                if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
+                    cuddSatInc(newf0->ref);
+                } else { /* no match */
+                    newf0 = cuddDynamicAllocNode(table);
+                    if (newf0 == NULL)
+                        goto cuddSwapOutOfMem;
+                    newf0->index = xindex; newf0->ref = 1;
+                    cuddT(newf0) = f10;
+                    cuddE(newf0) = f00;
+                    /* Insert newf0 in the collision list xlist[posn];
+                    ** increase the ref counts of f10 and f00.
+                    */
+                    newxkeys++;
+                    newf0->next = *previousP;
+                    *previousP = newf0;
+                    cuddSatInc(f10->ref);
+                    tmp = Cudd_Regular(f00);
+                    cuddSatInc(tmp->ref);
+                }
+                if (newcomplement) {
+                    newf0 = Cudd_Not(newf0);
+                }
+            }
+            cuddE(f) = newf0;
+
+            /* Insert the modified f in ylist.
+            ** The modified f does not already exists in ylist.
+            ** (Because of the uniqueness of the cofactors.)
+            */
+            posn = ddHash(cuddF2L(newf1), cuddF2L(newf0), yshift);
+            newykeys++;
+            previousP = &(ylist[posn]);
+            tmp = *previousP;
+            while (newf1 < cuddT(tmp)) {
+                previousP = &(tmp->next);
+                tmp = *previousP;
+            }
+            while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
+                previousP = &(tmp->next);
+                tmp = *previousP;
+            }
+            f->next = *previousP;
+            *previousP = f;
+            f = next;
+        } /* while f != NULL */
+
+        /* GC the y layer. */
+
+        /* For each node f in ylist. */
+        for (i = 0; i < yslots; i++) {
+            previousP = &(ylist[i]);
+            f = *previousP;
+            while (f != sentinel) {
+                next = f->next;
+                if (f->ref == 0) {
+                    tmp = cuddT(f);
+                    cuddSatDec(tmp->ref);
+                    tmp = Cudd_Regular(cuddE(f));
+                    cuddSatDec(tmp->ref);
+                    cuddDeallocNode(table,f);
+                    newykeys--;
+                } else {
+                    *previousP = f;
+                    previousP = &(f->next);
+                }
+                f = next;
+            } /* while f */
+            *previousP = sentinel;
+        } /* for i */
+
+#ifdef DD_DEBUG
+#if 0
+        (void) fprintf(table->out,"Swapping %d and %d\n",x,y);
+#endif
+        count = 0;
+        idcheck = 0;
+        for (i = 0; i < yslots; i++) {
+            f = ylist[i];
+            while (f != sentinel) {
+                count++;
+                if (f->index != (DdHalfWord) yindex)
+                    idcheck++;
+                f = f->next;
+            }
+        }
+        if (count != newykeys) {
+            (void) fprintf(table->out,
+                           "Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",
+                           oldykeys,newykeys,count);
+        }
+        if (idcheck != 0)
+            (void) fprintf(table->out,
+                           "Error in id's of ylist\twrong id's = %d\n",
+                           idcheck);
+        count = 0;
+        idcheck = 0;
+        for (i = 0; i < xslots; i++) {
+            f = xlist[i];
+            while (f != sentinel) {
+                count++;
+                if (f->index != (DdHalfWord) xindex)
+                    idcheck++;
+                f = f->next;
+            }
+        }
+        if (count != newxkeys) {
+            (void) fprintf(table->out,
+                           "Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",
+                           oldxkeys,newxkeys,count);
+        }
+        if (idcheck != 0)
+            (void) fprintf(table->out,
+                           "Error in id's of xlist\twrong id's = %d\n",
+                           idcheck);
+#endif
+
+        isolated += (table->vars[xindex]->ref == 1) +
+                    (table->vars[yindex]->ref == 1);
+        table->isolated += isolated;
+    }
+
+    /* Set the appropriate fields in table. */
+    table->subtables[x].nodelist = ylist;
+    table->subtables[x].slots = yslots;
+    table->subtables[x].shift = yshift;
+    table->subtables[x].keys = newykeys;
+    table->subtables[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY;
+    i = table->subtables[x].bindVar;
+    table->subtables[x].bindVar = table->subtables[y].bindVar;
+    table->subtables[y].bindVar = i;
+    /* Adjust filds for lazy sifting. */
+    varType = table->subtables[x].varType;
+    table->subtables[x].varType = table->subtables[y].varType;
+    table->subtables[y].varType = varType;
+    i = table->subtables[x].pairIndex;
+    table->subtables[x].pairIndex = table->subtables[y].pairIndex;
+    table->subtables[y].pairIndex = i;
+    i = table->subtables[x].varHandled;
+    table->subtables[x].varHandled = table->subtables[y].varHandled;
+    table->subtables[y].varHandled = i;
+    groupType = table->subtables[x].varToBeGrouped;
+    table->subtables[x].varToBeGrouped = table->subtables[y].varToBeGrouped;
+    table->subtables[y].varToBeGrouped = groupType;
+
+    table->subtables[y].nodelist = xlist;
+    table->subtables[y].slots = xslots;
+    table->subtables[y].shift = xshift;
+    table->subtables[y].keys = newxkeys;
+    table->subtables[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY;
+
+    table->perm[xindex] = y; table->perm[yindex] = x;
+    table->invperm[x] = yindex; table->invperm[y] = xindex;
+
+    table->keys += newxkeys + newykeys - oldxkeys - oldykeys;
+
+    return(table->keys - table->isolated);
+
+cuddSwapOutOfMem:
+    (void) fprintf(table->err,"Error: cuddSwapInPlace out of memory\n");
+
+    return (0);
+
+} /* end of cuddSwapInPlace */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders BDD variables according to the order of the ZDD
+  variables.]
+
+  Description [Reorders BDD variables according to the order of the
+  ZDD variables. This function can be called at the end of ZDD
+  reordering to insure that the order of the BDD variables is
+  consistent with the order of the ZDD variables. The number of ZDD
+  variables must be a multiple of the number of BDD variables. Let
+  <code>M</code> be the ratio of the two numbers. cuddBddAlignToZdd
+  then considers the ZDD variables from <code>M*i</code> to
+  <code>(M+1)*i-1</code> as corresponding to BDD variable
+  <code>i</code>.  This function should be normally called from
+  Cudd_zddReduceHeap, which clears the cache.  Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [Changes the BDD variable order for all diagrams and performs
+  garbage collection of the BDD unique table.]
+
+  SeeAlso [Cudd_ShuffleHeap Cudd_zddReduceHeap]
+
+******************************************************************************/
+int
+cuddBddAlignToZdd(
+  DdManager * table /* DD manager */)
+{
+    int *invperm;               /* permutation array */
+    int M;                      /* ratio of ZDD variables to BDD variables */
+    int i;                      /* loop index */
+    int result;                 /* return value */
+
+    /* We assume that a ratio of 0 is OK. */
+    if (table->size == 0)
+        return(1);
+
+    M = table->sizeZ / table->size;
+    /* Check whether the number of ZDD variables is a multiple of the
+    ** number of BDD variables.
+    */
+    if (M * table->size != table->sizeZ)
+        return(0);
+    /* Create and initialize the inverse permutation array. */
+    invperm = ABC_ALLOC(int,table->size);
+    if (invperm == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    for (i = 0; i < table->sizeZ; i += M) {
+        int indexZ = table->invpermZ[i];
+        int index  = indexZ / M;
+        invperm[i / M] = index;
+    }
+    /* Eliminate dead nodes. Do not scan the cache again, because we
+    ** assume that Cudd_zddReduceHeap has already cleared it.
+    */
+    cuddGarbageCollect(table,0);
+
+    /* Initialize number of isolated projection functions. */
+    table->isolated = 0;
+    for (i = 0; i < table->size; i++) {
+        if (table->vars[i]->ref == 1) table->isolated++;
+    }
+
+    /* Initialize the interaction matrix. */
+    result = cuddInitInteract(table);
+    if (result == 0) return(0);
+
+    result = ddShuffle(table, invperm);
+    ABC_FREE(invperm);
+    /* Free interaction matrix. */
+    ABC_FREE(table->interact);
+    /* Fix the BDD variable group tree. */
+    bddFixTree(table,table->tree);
+    return(result);
+
+} /* end of cuddBddAlignToZdd */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison function used by qsort.]
+
+  Description [Comparison function used by qsort to order the
+  variables according to the number of keys in the subtables.
+  Returns the difference in number of keys between the two
+  variables being compared.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddUniqueCompare(
+  int * ptrX,
+  int * ptrY)
+{
+#if 0
+    if (entry[*ptrY] == entry[*ptrX]) {
+        return((*ptrX) - (*ptrY));
+    }
+#endif
+    return(entry[*ptrY] - entry[*ptrX]);
+
+} /* end of ddUniqueCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Swaps any two variables.]
+
+  Description [Swaps any two variables. Returns the set of moves.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move *
+ddSwapAny(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    Move        *move, *moves;
+    int         xRef,yRef;
+    int         xNext,yNext;
+    int         size;
+    int         limitSize;
+    int         tmp;
+
+    if (x >y) {
+        tmp = x; x = y; y = tmp;
+    }
+
+    xRef = x; yRef = y;
+
+    xNext = cuddNextHigh(table,x);
+    yNext = cuddNextLow(table,y);
+    moves = NULL;
+    limitSize = table->keys - table->isolated;
+
+    for (;;) {
+        if ( xNext == yNext) {
+            size = cuddSwapInPlace(table,x,xNext);
+            if (size == 0) goto ddSwapAnyOutOfMem;
+            move = (Move *) cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddSwapAnyOutOfMem;
+            move->x = x;
+            move->y = xNext;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+
+            size = cuddSwapInPlace(table,yNext,y);
+            if (size == 0) goto ddSwapAnyOutOfMem;
+            move = (Move *) cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddSwapAnyOutOfMem;
+            move->x = yNext;
+            move->y = y;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+
+            size = cuddSwapInPlace(table,x,xNext);
+            if (size == 0) goto ddSwapAnyOutOfMem;
+            move = (Move *) cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddSwapAnyOutOfMem;
+            move->x = x;
+            move->y = xNext;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+
+            tmp = x; x = y; y = tmp;
+
+        } else if (x == yNext) {
+
+            size = cuddSwapInPlace(table,x,xNext);
+            if (size == 0) goto ddSwapAnyOutOfMem;
+            move = (Move *) cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddSwapAnyOutOfMem;
+            move->x = x;
+            move->y = xNext;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+
+            tmp = x; x = y; y = tmp;
+
+        } else {
+            size = cuddSwapInPlace(table,x,xNext);
+            if (size == 0) goto ddSwapAnyOutOfMem;
+            move = (Move *) cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddSwapAnyOutOfMem;
+            move->x = x;
+            move->y = xNext;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+
+            size = cuddSwapInPlace(table,yNext,y);
+            if (size == 0) goto ddSwapAnyOutOfMem;
+            move = (Move *) cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddSwapAnyOutOfMem;
+            move->x = yNext;
+            move->y = y;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+
+            x = xNext;
+            y = yNext;
+        }
+
+        xNext = cuddNextHigh(table,x);
+        yNext = cuddNextLow(table,y);
+        if (xNext > yRef) break;
+
+        if ((double) size > table->maxGrowth * (double) limitSize) break;
+        if (size < limitSize) limitSize = size;
+    }
+    if (yNext>=xRef) {
+        size = cuddSwapInPlace(table,yNext,y);
+        if (size == 0) goto ddSwapAnyOutOfMem;
+        move = (Move *) cuddDynamicAllocNode(table);
+        if (move == NULL) goto ddSwapAnyOutOfMem;
+        move->x = yNext;
+        move->y = y;
+        move->size = size;
+        move->next = moves;
+        moves = move;
+    }
+
+    return(moves);
+
+ddSwapAnyOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return(NULL);
+
+} /* end of ddSwapAny */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries.]
+
+  Description [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries. Finds the best position and does the required changes.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSiftingAux(
+  DdManager * table,
+  int  x,
+  int  xLow,
+  int  xHigh)
+{
+
+    Move        *move;
+    Move        *moveUp;                /* list of up moves */
+    Move        *moveDown;              /* list of down moves */
+    int         initialSize;
+    int         result;
+
+    initialSize = table->keys - table->isolated;
+
+    moveDown = NULL;
+    moveUp = NULL;
+
+    if (x == xLow) {
+        moveDown = ddSiftingDown(table,x,xHigh);
+        /* At this point x --> xHigh unless bounding occurred. */
+        if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
+        /* Move backward and stop at best position. */
+        result = ddSiftingBackward(table,initialSize,moveDown);
+        if (!result) goto ddSiftingAuxOutOfMem;
+
+    } else if (x == xHigh) {
+        moveUp = ddSiftingUp(table,x,xLow);
+        /* At this point x --> xLow unless bounding occurred. */
+        if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
+        /* Move backward and stop at best position. */
+        result = ddSiftingBackward(table,initialSize,moveUp);
+        if (!result) goto ddSiftingAuxOutOfMem;
+
+    } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
+        moveDown = ddSiftingDown(table,x,xHigh);
+        /* At this point x --> xHigh unless bounding occurred. */
+        if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
+        if (moveDown != NULL) {
+            x = moveDown->y;
+        }
+        moveUp = ddSiftingUp(table,x,xLow);
+        if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
+        /* Move backward and stop at best position */
+        result = ddSiftingBackward(table,initialSize,moveUp);
+        if (!result) goto ddSiftingAuxOutOfMem;
+
+    } else { /* must go up first: shorter */
+        moveUp = ddSiftingUp(table,x,xLow);
+        /* At this point x --> xLow unless bounding occurred. */
+        if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
+        if (moveUp != NULL) {
+            x = moveUp->x;
+        }
+        moveDown = ddSiftingDown(table,x,xHigh);
+        if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
+        /* Move backward and stop at best position. */
+        result = ddSiftingBackward(table,initialSize,moveDown);
+        if (!result) goto ddSiftingAuxOutOfMem;
+    }
+
+    while (moveDown != NULL) {
+        move = moveDown->next;
+        cuddDeallocMove(table, moveDown);
+        moveDown = move;
+    }
+    while (moveUp != NULL) {
+        move = moveUp->next;
+        cuddDeallocMove(table, moveUp);
+        moveUp = move;
+    }
+
+    return(1);
+
+ddSiftingAuxOutOfMem:
+    if (moveDown != (Move *) CUDD_OUT_OF_MEM) {
+        while (moveDown != NULL) {
+            move = moveDown->next;
+            cuddDeallocMove(table, moveDown);
+            moveDown = move;
+        }
+    }
+    if (moveUp != (Move *) CUDD_OUT_OF_MEM) {
+        while (moveUp != NULL) {
+            move = moveUp->next;
+            cuddDeallocMove(table, moveUp);
+            moveUp = move;
+        }
+    }
+
+    return(0);
+
+} /* end of ddSiftingAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts a variable up.]
+
+  Description [Sifts a variable up. Moves y up until either it reaches
+  the bound (xLow) or the size of the DD heap increases too much.
+  Returns the set of moves in case of success; NULL if memory is full.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move *
+ddSiftingUp(
+  DdManager * table,
+  int  y,
+  int  xLow)
+{
+    Move        *moves;
+    Move        *move;
+    int         x;
+    int         size;
+    int         limitSize;
+    int         xindex, yindex;
+    int         isolated;
+    int         L;      /* lower bound on DD size */
+#ifdef DD_DEBUG
+    int checkL;
+    int z;
+    int zindex;
+#endif
+
+    moves = NULL;
+    yindex = table->invperm[y];
+
+    /* Initialize the lower bound.
+    ** The part of the DD below y will not change.
+    ** The part of the DD above y that does not interact with y will not
+    ** change. The rest may vanish in the best case, except for
+    ** the nodes at level xLow, which will not vanish, regardless.
+    */
+    limitSize = L = table->keys - table->isolated;
+    for (x = xLow + 1; x < y; x++) {
+        xindex = table->invperm[x];
+        if (cuddTestInteract(table,xindex,yindex)) {
+            isolated = table->vars[xindex]->ref == 1;
+            L -= table->subtables[x].keys - isolated;
+        }
+    }
+    isolated = table->vars[yindex]->ref == 1;
+    L -= table->subtables[y].keys - isolated;
+
+    x = cuddNextLow(table,y);
+    while (x >= xLow && L <= limitSize) {
+        xindex = table->invperm[x];
+#ifdef DD_DEBUG
+        checkL = table->keys - table->isolated;
+        for (z = xLow + 1; z < y; z++) {
+            zindex = table->invperm[z];
+            if (cuddTestInteract(table,zindex,yindex)) {
+                isolated = table->vars[zindex]->ref == 1;
+                checkL -= table->subtables[z].keys - isolated;
+            }
+        }
+        isolated = table->vars[yindex]->ref == 1;
+        checkL -= table->subtables[y].keys - isolated;
+        assert(L == checkL);
+#endif
+        size = cuddSwapInPlace(table,x,y);
+        if (size == 0) goto ddSiftingUpOutOfMem;
+        /* Update the lower bound. */
+        if (cuddTestInteract(table,xindex,yindex)) {
+            isolated = table->vars[xindex]->ref == 1;
+            L += table->subtables[y].keys - isolated;
+        }
+        move = (Move *) cuddDynamicAllocNode(table);
+        if (move == NULL) goto ddSiftingUpOutOfMem;
+        move->x = x;
+        move->y = y;
+        move->size = size;
+        move->next = moves;
+        moves = move;
+        if ((double) size > (double) limitSize * table->maxGrowth) break;
+        if (size < limitSize) limitSize = size;
+        y = x;
+        x = cuddNextLow(table,y);
+    }
+    return(moves);
+
+ddSiftingUpOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return((Move *) CUDD_OUT_OF_MEM);
+
+} /* end of ddSiftingUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts a variable down.]
+
+  Description [Sifts a variable down. Moves x down until either it
+  reaches the bound (xHigh) or the size of the DD heap increases too
+  much. Returns the set of moves in case of success; NULL if memory is
+  full.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move *
+ddSiftingDown(
+  DdManager * table,
+  int  x,
+  int  xHigh)
+{
+    Move        *moves;
+    Move        *move;
+    int         y;
+    int         size;
+    int         R;      /* upper bound on node decrease */
+    int         limitSize;
+    int         xindex, yindex;
+    int         isolated;
+#ifdef DD_DEBUG
+    int         checkR;
+    int         z;
+    int         zindex;
+#endif
+
+    moves = NULL;
+    /* Initialize R */
+    xindex = table->invperm[x];
+    limitSize = size = table->keys - table->isolated;
+    R = 0;
+    for (y = xHigh; y > x; y--) {
+        yindex = table->invperm[y];
+        if (cuddTestInteract(table,xindex,yindex)) {
+            isolated = table->vars[yindex]->ref == 1;
+            R += table->subtables[y].keys - isolated;
+        }
+    }
+
+    y = cuddNextHigh(table,x);
+    while (y <= xHigh && size - R < limitSize) {
+#ifdef DD_DEBUG
+        checkR = 0;
+        for (z = xHigh; z > x; z--) {
+            zindex = table->invperm[z];
+            if (cuddTestInteract(table,xindex,zindex)) {
+                isolated = table->vars[zindex]->ref == 1;
+                checkR += table->subtables[z].keys - isolated;
+            }
+        }
+        assert(R == checkR);
+#endif
+        /* Update upper bound on node decrease. */
+        yindex = table->invperm[y];
+        if (cuddTestInteract(table,xindex,yindex)) {
+            isolated = table->vars[yindex]->ref == 1;
+            R -= table->subtables[y].keys - isolated;
+        }
+        size = cuddSwapInPlace(table,x,y);
+        if (size == 0) goto ddSiftingDownOutOfMem;
+        move = (Move *) cuddDynamicAllocNode(table);
+        if (move == NULL) goto ddSiftingDownOutOfMem;
+        move->x = x;
+        move->y = y;
+        move->size = size;
+        move->next = moves;
+        moves = move;
+        if ((double) size > (double) limitSize * table->maxGrowth) break;
+        if (size < limitSize) limitSize = size;
+        x = y;
+        y = cuddNextHigh(table,x);
+    }
+    return(moves);
+
+ddSiftingDownOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return((Move *) CUDD_OUT_OF_MEM);
+
+} /* end of ddSiftingDown */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given a set of moves, returns the DD heap to the position
+  giving the minimum size.]
+
+  Description [Given a set of moves, returns the DD heap to the
+  position giving the minimum size. In case of ties, returns to the
+  closest position giving the minimum size. Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSiftingBackward(
+  DdManager * table,
+  int  size,
+  Move * moves)
+{
+    Move *move;
+    int res;
+
+    for (move = moves; move != NULL; move = move->next) {
+        if (move->size < size) {
+            size = move->size;
+        }
+    }
+
+    for (move = moves; move != NULL; move = move->next) {
+        if (move->size == size) return(1);
+        res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
+        if (!res) return(0);
+    }
+
+    return(1);
+
+} /* end of ddSiftingBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prepares the DD heap for dynamic reordering.]
+
+  Description [Prepares the DD heap for dynamic reordering. Does
+  garbage collection, to guarantee that there are no dead nodes;
+  clears the cache, which is invalidated by dynamic reordering; initializes
+  the number of isolated projection functions; and initializes the
+  interaction matrix.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddReorderPreprocess(
+  DdManager * table)
+{
+    int i;
+    int res;
+
+    /* Clear the cache. */
+    cuddCacheFlush(table);
+    cuddLocalCacheClearAll(table);
+
+    /* Eliminate dead nodes. Do not scan the cache again. */
+    cuddGarbageCollect(table,0);
+
+    /* Initialize number of isolated projection functions. */
+    table->isolated = 0;
+    for (i = 0; i < table->size; i++) {
+        if (table->vars[i]->ref == 1) table->isolated++;
+    }
+
+    /* Initialize the interaction matrix. */
+    res = cuddInitInteract(table);
+    if (res == 0) return(0);
+
+    return(1);
+
+} /* end of ddReorderPreprocess */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Cleans up at the end of reordering.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddReorderPostprocess(
+  DdManager * table)
+{
+
+#ifdef DD_VERBOSE
+    (void) fflush(table->out);
+#endif
+
+    /* Free interaction matrix. */
+    ABC_FREE(table->interact);
+
+    return(1);
+
+} /* end of ddReorderPostprocess */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders variables according to a given permutation.]
+
+  Description [Reorders variables according to a given permutation.
+  The i-th permutation array contains the index of the variable that
+  should be brought to the i-th level. ddShuffle assumes that no
+  dead nodes are present and that the interaction matrix is properly
+  initialized.  The reordering is achieved by a series of upward sifts.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static int
+ddShuffle(
+  DdManager * table,
+  int * permutation)
+{
+    int         index;
+    int         level;
+    int         position;
+    int         numvars;
+    int         result;
+#ifdef DD_STATS
+    long        localTime;
+    int         initialSize;
+    int         finalSize;
+    int         previousSize;
+#endif
+
+    ddTotalNumberSwapping = 0;
+#ifdef DD_STATS
+    localTime = util_cpu_time();
+    initialSize = table->keys - table->isolated;
+    (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n",
+                   initialSize);
+    ddTotalNISwaps = 0;
+#endif
+
+    numvars = table->size;
+
+    for (level = 0; level < numvars; level++) {
+        index = permutation[level];
+        position = table->perm[index];
+#ifdef DD_STATS
+        previousSize = table->keys - table->isolated;
+#endif
+        result = ddSiftUp(table,position,level);
+        if (!result) return(0);
+#ifdef DD_STATS
+        if (table->keys < (unsigned) previousSize + table->isolated) {
+            (void) fprintf(table->out,"-");
+        } else if (table->keys > (unsigned) previousSize + table->isolated) {
+            (void) fprintf(table->out,"+");     /* should never happen */
+        } else {
+            (void) fprintf(table->out,"=");
+        }
+        fflush(table->out);
+#endif
+    }
+
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n");
+    finalSize = table->keys - table->isolated;
+    (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize);
+    (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n",
+        ((double)(util_cpu_time() - localTime)/1000.0));
+    (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n",
+                   ddTotalNumberSwapping);
+    (void) fprintf(table->out,"#:M_SHUFFLE %8d: NI swaps\n",ddTotalNISwaps);
+#endif
+
+    return(1);
+
+} /* end of ddShuffle */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves one variable up.]
+
+  Description [Takes a variable from position x and sifts it up to
+  position xLow;  xLow should be less than or equal to x.
+  Returns 1 if successful; 0 otherwise]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddSiftUp(
+  DdManager * table,
+  int  x,
+  int  xLow)
+{
+    int        y;
+    int        size;
+
+    y = cuddNextLow(table,x);
+    while (y >= xLow) {
+        size = cuddSwapInPlace(table,y,x);
+        if (size == 0) {
+            return(0);
+        }
+        x = y;
+        y = cuddNextLow(table,x);
+    }
+    return(1);
+
+} /* end of ddSiftUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Fixes the BDD variable group tree after a shuffle.]
+
+  Description [Fixes the BDD variable group tree after a
+  shuffle. Assumes that the order of the variables in a terminal node
+  has not been changed.]
+
+  SideEffects [Changes the BDD variable group tree.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+bddFixTree(
+  DdManager * table,
+  MtrNode * treenode)
+{
+    if (treenode == NULL) return;
+    treenode->low = ((int) treenode->index < table->size) ?
+        table->perm[treenode->index] : treenode->index;
+    if (treenode->child != NULL) {
+        bddFixTree(table, treenode->child);
+    }
+    if (treenode->younger != NULL)
+        bddFixTree(table, treenode->younger);
+    if (treenode->parent != NULL && treenode->low < treenode->parent->low) {
+        treenode->parent->low = treenode->low;
+        treenode->parent->index = treenode->index;
+    }
+    return;
+
+} /* end of bddFixTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Updates the BDD variable group tree before a shuffle.]
+
+  Description [Updates the BDD variable group tree before a shuffle.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [Changes the BDD variable group tree.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddUpdateMtrTree(
+  DdManager * table,
+  MtrNode * treenode,
+  int * perm,
+  int * invperm)
+{
+    int i, size;
+    int index, level, minLevel, maxLevel, minIndex;
+
+    if (treenode == NULL) return(1);
+
+    minLevel = CUDD_MAXINDEX;
+    maxLevel = 0;
+    minIndex = -1;
+    /* i : level */
+    for (i = treenode->low; i < treenode->low + treenode->size; i++) {
+        index = table->invperm[i];
+        level = perm[index];
+        if (level < minLevel) {
+            minLevel = level;
+            minIndex = index;
+        }
+        if (level > maxLevel)
+            maxLevel = level;
+    }
+    size = maxLevel - minLevel + 1;
+    if (minIndex == -1) return(0);
+    if (size == treenode->size) {
+        treenode->low = minLevel;
+        treenode->index = minIndex;
+    } else {
+        return(0);
+    }
+
+    if (treenode->child != NULL) {
+        if (!ddUpdateMtrTree(table, treenode->child, perm, invperm))
+            return(0);
+    }
+    if (treenode->younger != NULL) {
+        if (!ddUpdateMtrTree(table, treenode->younger, perm, invperm))
+            return(0);
+    }
+    return(1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the BDD variable group tree before a shuffle.]
+
+  Description [Checks the BDD variable group tree before a shuffle.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [Changes the BDD variable group tree.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddCheckPermuation(
+  DdManager * table,
+  MtrNode * treenode,
+  int * perm,
+  int * invperm)
+{
+    int i, size;
+    int index, level, minLevel, maxLevel;
+
+    if (treenode == NULL) return(1);
+
+    minLevel = table->size;
+    maxLevel = 0;
+    /* i : level */
+    for (i = treenode->low; i < treenode->low + treenode->size; i++) {
+        index = table->invperm[i];
+        level = perm[index];
+        if (level < minLevel)
+            minLevel = level;
+        if (level > maxLevel)
+            maxLevel = level;
+    }
+    size = maxLevel - minLevel + 1;
+    if (size != treenode->size)
+        return(0);
+
+    if (treenode->child != NULL) {
+        if (!ddCheckPermuation(table, treenode->child, perm, invperm))
+            return(0);
+    }
+    if (treenode->younger != NULL) {
+        if (!ddCheckPermuation(table, treenode->younger, perm, invperm))
+            return(0);
+    }
+    return(1);
+}
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddSat.c b/abc-build/src/bdd/cudd/cuddSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddSat.c
@@ -0,0 +1,1346 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddSat.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for the solution of satisfiability related
+  problems.]
+
+  Description [External procedures included in this file:
+                <ul>
+                <li> Cudd_Eval()
+                <li> Cudd_ShortestPath()
+                <li> Cudd_LargestCube()
+                <li> Cudd_ShortestLength()
+                <li> Cudd_Decreasing()
+                <li> Cudd_Increasing()
+                <li> Cudd_EquivDC()
+                <li> Cudd_bddLeqUnless()
+                <li> Cudd_EqualSupNorm()
+                <li> Cudd_bddMakePrime()
+                </ul>
+        Internal procedures included in this module:
+                <ul>
+                <li> cuddBddMakePrime()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> freePathPair()
+                <li> getShortest()
+                <li> getPath()
+                <li> getLargest()
+                <li> getCube()
+                </ul>]
+
+  Author      [Seh-Woong Jeong, Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DD_BIGGY        1000000
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct cuddPathPair {
+    int pos;
+    int neg;
+} cuddPathPair;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddSat.c,v 1.36 2009/03/08 02:49:02 fabio Exp $";
+#endif
+
+static  DdNode  *one, *zero;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#define WEIGHT(weight, col)     ((weight) == NULL ? 1 : weight[col])
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static enum st__retval freePathPair (char *key, char *value, char *arg);
+static cuddPathPair getShortest (DdNode *root, int *cost, int *support, st__table *visited);
+static DdNode * getPath (DdManager *manager, st__table *visited, DdNode *f, int *weight, int cost);
+static cuddPathPair getLargest (DdNode *root, st__table *visited);
+static DdNode * getCube (DdManager *manager, st__table *visited, DdNode *f, int cost);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the value of a DD for a given variable assignment.]
+
+  Description [Finds the value of a DD for a given variable
+  assignment. The variable assignment is passed in an array of int's,
+  that should specify a zero or a one for each variable in the support
+  of the function. Returns a pointer to a constant node. No new nodes
+  are produced.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLeq Cudd_addEvalConst]
+
+******************************************************************************/
+DdNode *
+Cudd_Eval(
+  DdManager * dd,
+  DdNode * f,
+  int * inputs)
+{
+    int comple;
+    DdNode *ptr;
+
+    comple = Cudd_IsComplement(f);
+    ptr = Cudd_Regular(f);
+
+    while (!cuddIsConstant(ptr)) {
+        if (inputs[ptr->index] == 1) {
+            ptr = cuddT(ptr);
+        } else {
+            comple ^= Cudd_IsComplement(cuddE(ptr));
+            ptr = Cudd_Regular(cuddE(ptr));
+        }
+    }
+    return(Cudd_NotCond(ptr,comple));
+
+} /* end of Cudd_Eval */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a shortest path in a DD.]
+
+  Description [Finds a shortest path in a DD. f is the DD we want to
+  get the shortest path for; weight\[i\] is the weight of the THEN arc
+  coming from the node whose index is i. If weight is NULL, then unit
+  weights are assumed for all THEN arcs. All ELSE arcs have 0 weight.
+  If non-NULL, both weight and support should point to arrays with at
+  least as many entries as there are variables in the manager.
+  Returns the shortest path as the BDD of a cube.]
+
+  SideEffects [support contains on return the true support of f.
+  If support is NULL on entry, then Cudd_ShortestPath does not compute
+  the true support info. length contains the length of the path.]
+
+  SeeAlso     [Cudd_ShortestLength Cudd_LargestCube]
+
+******************************************************************************/
+DdNode *
+Cudd_ShortestPath(
+  DdManager * manager,
+  DdNode * f,
+  int * weight,
+  int * support,
+  int * length)
+{
+    DdNode      *F;
+    st__table    *visited;
+    DdNode      *sol;
+    cuddPathPair *rootPair;
+    int         complement, cost;
+    int         i;
+
+    one = DD_ONE(manager);
+    zero = DD_ZERO(manager);
+
+    /* Initialize support. Support does not depend on variable order.
+    ** Hence, it does not need to be reinitialized if reordering occurs.
+    */
+    if (support) {
+      for (i = 0; i < manager->size; i++) {
+        support[i] = 0;
+      }
+    }
+
+    if (f == Cudd_Not(one) || f == zero) {
+      *length = DD_BIGGY;
+      return(Cudd_Not(one));
+    }
+    /* From this point on, a path exists. */
+
+    do {
+        manager->reordered = 0;
+
+        /* Initialize visited table. */
+        visited = st__init_table( st__ptrcmp, st__ptrhash);
+
+        /* Now get the length of the shortest path(s) from f to 1. */
+        (void) getShortest(f, weight, support, visited);
+
+        complement = Cudd_IsComplement(f);
+
+        F = Cudd_Regular(f);
+
+        if (! st__lookup(visited, (const char *)F, (char **)&rootPair)) return(NULL);
+
+        if (complement) {
+          cost = rootPair->neg;
+        } else {
+          cost = rootPair->pos;
+        }
+
+        /* Recover an actual shortest path. */
+        sol = getPath(manager,visited,f,weight,cost);
+
+        st__foreach(visited, freePathPair, NULL);
+        st__free_table(visited);
+
+    } while (manager->reordered == 1);
+
+    *length = cost;
+    return(sol);
+
+} /* end of Cudd_ShortestPath */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a largest cube in a DD.]
+
+  Description [Finds a largest cube in a DD. f is the DD we want to
+  get the largest cube for. The problem is translated into the one of
+  finding a shortest path in f, when both THEN and ELSE arcs are assumed to
+  have unit length. This yields a largest cube in the disjoint cover
+  corresponding to the DD. Therefore, it is not necessarily the largest
+  implicant of f.  Returns the largest cube as a BDD.]
+
+  SideEffects [The number of literals of the cube is returned in length.]
+
+  SeeAlso     [Cudd_ShortestPath]
+
+******************************************************************************/
+DdNode *
+Cudd_LargestCube(
+  DdManager * manager,
+  DdNode * f,
+  int * length)
+{
+    register    DdNode  *F;
+    st__table    *visited;
+    DdNode      *sol;
+    cuddPathPair *rootPair;
+    int         complement, cost;
+
+    one = DD_ONE(manager);
+    zero = DD_ZERO(manager);
+
+    if (f == Cudd_Not(one) || f == zero) {
+        *length = DD_BIGGY;
+        return(Cudd_Not(one));
+    }
+    /* From this point on, a path exists. */
+
+    do {
+        manager->reordered = 0;
+
+        /* Initialize visited table. */
+        visited = st__init_table( st__ptrcmp, st__ptrhash);
+
+        /* Now get the length of the shortest path(s) from f to 1. */
+        (void) getLargest(f, visited);
+
+        complement = Cudd_IsComplement(f);
+
+        F = Cudd_Regular(f);
+
+        if (! st__lookup(visited, (const char *)F, (char **)&rootPair)) return(NULL);
+
+        if (complement) {
+          cost = rootPair->neg;
+        } else {
+          cost = rootPair->pos;
+        }
+
+        /* Recover an actual shortest path. */
+        sol = getCube(manager,visited,f,cost);
+
+        st__foreach(visited, freePathPair, NULL);
+        st__free_table(visited);
+
+    } while (manager->reordered == 1);
+
+    *length = cost;
+    return(sol);
+
+} /* end of Cudd_LargestCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find the length of the shortest path(s) in a DD.]
+
+  Description [Find the length of the shortest path(s) in a DD. f is
+  the DD we want to get the shortest path for; weight\[i\] is the
+  weight of the THEN edge coming from the node whose index is i. All
+  ELSE edges have 0 weight. Returns the length of the shortest
+  path(s) if such a path is found; a large number if the function is
+  identically 0, and CUDD_OUT_OF_MEM in case of failure.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ShortestPath]
+
+******************************************************************************/
+int
+Cudd_ShortestLength(
+  DdManager * manager,
+  DdNode * f,
+  int * weight)
+{
+    register    DdNode  *F;
+    st__table    *visited;
+    cuddPathPair *my_pair;
+    int         complement, cost;
+
+    one = DD_ONE(manager);
+    zero = DD_ZERO(manager);
+
+    if (f == Cudd_Not(one) || f == zero) {
+        return(DD_BIGGY);
+    }
+
+    /* From this point on, a path exists. */
+    /* Initialize visited table and support. */
+    visited = st__init_table( st__ptrcmp, st__ptrhash);
+
+    /* Now get the length of the shortest path(s) from f to 1. */
+    (void) getShortest(f, weight, NULL, visited);
+
+    complement = Cudd_IsComplement(f);
+
+    F = Cudd_Regular(f);
+
+    if (! st__lookup(visited, (const char *)F, (char **)&my_pair)) return(CUDD_OUT_OF_MEM);
+    
+    if (complement) {
+        cost = my_pair->neg;
+    } else {
+        cost = my_pair->pos;
+    }
+
+    st__foreach(visited, freePathPair, NULL);
+    st__free_table(visited);
+
+    return(cost);
+
+} /* end of Cudd_ShortestLength */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Determines whether a BDD is negative unate in a
+  variable.]
+
+  Description [Determines whether the function represented by BDD f is
+  negative unate (monotonic decreasing) in variable i. Returns the
+  constant one is f is unate and the (logical) constant zero if it is not.
+  This function does not generate any new nodes.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Increasing]
+
+******************************************************************************/
+DdNode *
+Cudd_Decreasing(
+  DdManager * dd,
+  DdNode * f,
+  int  i)
+{
+    unsigned int topf, level;
+    DdNode *F, *fv, *fvn, *res;
+    DD_CTFP cacheOp;
+
+    statLine(dd);
+#ifdef DD_DEBUG
+    assert(0 <= i && i < dd->size);
+#endif
+
+    F = Cudd_Regular(f);
+    topf = cuddI(dd,F->index);
+
+    /* Check terminal case. If topf > i, f does not depend on var.
+    ** Therefore, f is unate in i.
+    */
+    level = (unsigned) dd->perm[i];
+    if (topf > level) {
+        return(DD_ONE(dd));
+    }
+
+    /* From now on, f is not constant. */
+
+    /* Check cache. */
+    cacheOp = (DD_CTFP) Cudd_Decreasing;
+    res = cuddCacheLookup2(dd,cacheOp,f,dd->vars[i]);
+    if (res != NULL) {
+        return(res);
+    }
+
+    /* Compute cofactors. */
+    fv = cuddT(F); fvn = cuddE(F);
+    if (F != f) {
+        fv = Cudd_Not(fv);
+        fvn = Cudd_Not(fvn);
+    }
+
+    if (topf == (unsigned) level) {
+        /* Special case: if fv is regular, fv(1,...,1) = 1;
+        ** If in addition fvn is complemented, fvn(1,...,1) = 0.
+        ** But then f(1,1,...,1) > f(0,1,...,1). Hence f is not
+        ** monotonic decreasing in i.
+        */
+        if (!Cudd_IsComplement(fv) && Cudd_IsComplement(fvn)) {
+            return(Cudd_Not(DD_ONE(dd)));
+        }
+        res = Cudd_bddLeq(dd,fv,fvn) ? DD_ONE(dd) : Cudd_Not(DD_ONE(dd));
+    } else {
+        res = Cudd_Decreasing(dd,fv,i);
+        if (res == DD_ONE(dd)) {
+            res = Cudd_Decreasing(dd,fvn,i);
+        }
+    }
+
+    cuddCacheInsert2(dd,cacheOp,f,dd->vars[i],res);
+    return(res);
+
+} /* end of Cudd_Decreasing */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Determines whether a BDD is positive unate in a
+  variable.]
+
+  Description [Determines whether the function represented by BDD f is
+  positive unate (monotonic increasing) in variable i. It is based on
+  Cudd_Decreasing and the fact that f is monotonic increasing in i if
+  and only if its complement is monotonic decreasing in i.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Decreasing]
+
+******************************************************************************/
+DdNode *
+Cudd_Increasing(
+  DdManager * dd,
+  DdNode * f,
+  int  i)
+{
+    return(Cudd_Decreasing(dd,Cudd_Not(f),i));
+
+} /* end of Cudd_Increasing */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tells whether F and G are identical wherever D is 0.]
+
+  Description [Tells whether F and G are identical wherever D is 0.  F
+  and G are either two ADDs or two BDDs.  D is either a 0-1 ADD or a
+  BDD.  The function returns 1 if F and G are equivalent, and 0
+  otherwise.  No new nodes are created.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLeqUnless]
+
+******************************************************************************/
+int
+Cudd_EquivDC(
+  DdManager * dd,
+  DdNode * F,
+  DdNode * G,
+  DdNode * D)
+{
+    DdNode *tmp, *One, *Gr, *Dr;
+    DdNode *Fv, *Fvn, *Gv, *Gvn, *Dv, *Dvn;
+    int res;
+    unsigned int flevel, glevel, dlevel, top;
+
+    One = DD_ONE(dd);
+
+    statLine(dd);
+    /* Check terminal cases. */
+    if (D == One || F == G) return(1);
+    if (D == Cudd_Not(One) || D == DD_ZERO(dd) || F == Cudd_Not(G)) return(0);
+
+    /* From now on, D is non-constant. */
+
+    /* Normalize call to increase cache efficiency. */
+    if (F > G) {
+        tmp = F;
+        F = G;
+        G = tmp;
+    }
+    if (Cudd_IsComplement(F)) {
+        F = Cudd_Not(F);
+        G = Cudd_Not(G);
+    }
+
+    /* From now on, F is regular. */
+
+    /* Check cache. */
+    tmp = cuddCacheLookup(dd,DD_EQUIV_DC_TAG,F,G,D);
+    if (tmp != NULL) return(tmp == One);
+
+    /* Find splitting variable. */
+    flevel = cuddI(dd,F->index);
+    Gr = Cudd_Regular(G);
+    glevel = cuddI(dd,Gr->index);
+    top = ddMin(flevel,glevel);
+    Dr = Cudd_Regular(D);
+    dlevel = dd->perm[Dr->index];
+    top = ddMin(top,dlevel);
+
+    /* Compute cofactors. */
+    if (top == flevel) {
+        Fv = cuddT(F);
+        Fvn = cuddE(F);
+    } else {
+        Fv = Fvn = F;
+    }
+    if (top == glevel) {
+        Gv = cuddT(Gr);
+        Gvn = cuddE(Gr);
+        if (G != Gr) {
+            Gv = Cudd_Not(Gv);
+            Gvn = Cudd_Not(Gvn);
+        }
+    } else {
+        Gv = Gvn = G;
+    }
+    if (top == dlevel) {
+        Dv = cuddT(Dr);
+        Dvn = cuddE(Dr);
+        if (D != Dr) {
+            Dv = Cudd_Not(Dv);
+            Dvn = Cudd_Not(Dvn);
+        }
+    } else {
+        Dv = Dvn = D;
+    }
+
+    /* Solve recursively. */
+    res = Cudd_EquivDC(dd,Fv,Gv,Dv);
+    if (res != 0) {
+        res = Cudd_EquivDC(dd,Fvn,Gvn,Dvn);
+    }
+    cuddCacheInsert(dd,DD_EQUIV_DC_TAG,F,G,D,(res) ? One : Cudd_Not(One));
+
+    return(res);
+
+} /* end of Cudd_EquivDC */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tells whether f is less than of equal to G unless D is 1.]
+
+  Description [Tells whether f is less than of equal to G unless D is
+  1.  f, g, and D are BDDs.  The function returns 1 if f is less than
+  of equal to G, and 0 otherwise.  No new nodes are created.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_EquivDC Cudd_bddLeq Cudd_bddIteConstant]
+
+******************************************************************************/
+int
+Cudd_bddLeqUnless(
+  DdManager *dd,
+  DdNode *f,
+  DdNode *g,
+  DdNode *D)
+{
+    DdNode *tmp, *One, *F, *G;
+    DdNode *Ft, *Fe, *Gt, *Ge, *Dt, *De;
+    int res;
+    unsigned int flevel, glevel, dlevel, top;
+
+    statLine(dd);
+
+    One = DD_ONE(dd);
+
+    /* Check terminal cases. */
+    if (f == g || g == One || f == Cudd_Not(One) || D == One ||
+        D == f || D == Cudd_Not(g)) return(1);
+    /* Check for two-operand cases. */
+    if (D == Cudd_Not(One) || D == g || D == Cudd_Not(f))
+        return(Cudd_bddLeq(dd,f,g));
+    if (g == Cudd_Not(One) || g == Cudd_Not(f)) return(Cudd_bddLeq(dd,f,D));
+    if (f == One) return(Cudd_bddLeq(dd,Cudd_Not(g),D));
+
+    /* From now on, f, g, and D are non-constant, distinct, and
+    ** non-complementary. */
+
+    /* Normalize call to increase cache efficiency.  We rely on the
+    ** fact that f <= g unless D is equivalent to not(g) <= not(f)
+    ** unless D and to f <= D unless g.  We make sure that D is
+    ** regular, and that at most one of f and g is complemented.  We also
+    ** ensure that when two operands can be swapped, the one with the
+    ** lowest address comes first. */
+
+    if (Cudd_IsComplement(D)) {
+        if (Cudd_IsComplement(g)) {
+            /* Special case: if f is regular and g is complemented,
+            ** f(1,...,1) = 1 > 0 = g(1,...,1).  If D(1,...,1) = 0, return 0.
+            */
+            if (!Cudd_IsComplement(f)) return(0);
+            /* !g <= D unless !f  or  !D <= g unless !f */
+            tmp = D;
+            D = Cudd_Not(f);
+            if (g < tmp) {
+                f = Cudd_Not(g);
+                g = tmp;
+            } else {
+                f = Cudd_Not(tmp);
+            }
+        } else {
+            if (Cudd_IsComplement(f)) {
+                /* !D <= !f unless g  or  !D <= g unless !f */
+                tmp = f;
+                f = Cudd_Not(D);
+                if (tmp < g) {
+                    D = g;
+                    g = Cudd_Not(tmp);
+                } else {
+                    D = Cudd_Not(tmp);
+                }
+            } else {
+                /* f <= D unless g  or  !D <= !f unless g */
+                tmp = D;
+                D = g;
+                if (tmp < f) {
+                    g = Cudd_Not(f);
+                    f = Cudd_Not(tmp);
+                } else {
+                    g = tmp;
+                }
+            }
+        }
+    } else {
+        if (Cudd_IsComplement(g)) {
+            if (Cudd_IsComplement(f)) {
+                /* !g <= !f unless D  or  !g <= D unless !f */
+                tmp = f;
+                f = Cudd_Not(g);
+                if (D < tmp) {
+                    g = D;
+                    D = Cudd_Not(tmp);
+                } else {
+                    g = Cudd_Not(tmp);
+                }
+            } else {
+                /* f <= g unless D  or  !g <= !f unless D */
+                if (g < f) {
+                    tmp = g;
+                    g = Cudd_Not(f);
+                    f = Cudd_Not(tmp);
+                }
+            }
+        } else {
+            /* f <= g unless D  or  f <= D unless g */
+            if (D < g) {
+                tmp = D;
+                D = g;
+                g = tmp;
+            }
+        }
+    }
+
+    /* From now on, D is regular. */
+
+    /* Check cache. */
+    tmp = cuddCacheLookup(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D);
+    if (tmp != NULL) return(tmp == One);
+
+    /* Find splitting variable. */
+    F = Cudd_Regular(f);
+    flevel = dd->perm[F->index];
+    G = Cudd_Regular(g);
+    glevel = dd->perm[G->index];
+    top = ddMin(flevel,glevel);
+    dlevel = dd->perm[D->index];
+    top = ddMin(top,dlevel);
+
+    /* Compute cofactors. */
+    if (top == flevel) {
+        Ft = cuddT(F);
+        Fe = cuddE(F);
+        if (F != f) {
+            Ft = Cudd_Not(Ft);
+            Fe = Cudd_Not(Fe);
+        }
+    } else {
+        Ft = Fe = f;
+    }
+    if (top == glevel) {
+        Gt = cuddT(G);
+        Ge = cuddE(G);
+        if (G != g) {
+            Gt = Cudd_Not(Gt);
+            Ge = Cudd_Not(Ge);
+        }
+    } else {
+        Gt = Ge = g;
+    }
+    if (top == dlevel) {
+        Dt = cuddT(D);
+        De = cuddE(D);
+    } else {
+        Dt = De = D;
+    }
+
+    /* Solve recursively. */
+    res = Cudd_bddLeqUnless(dd,Ft,Gt,Dt);
+    if (res != 0) {
+        res = Cudd_bddLeqUnless(dd,Fe,Ge,De);
+    }
+    cuddCacheInsert(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D,Cudd_NotCond(One,!res));
+
+    return(res);
+
+} /* end of Cudd_bddLeqUnless */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two ADDs for equality within tolerance.]
+
+  Description [Compares two ADDs for equality within tolerance. Two
+  ADDs are reported to be equal if the maximum difference between them
+  (the sup norm of their difference) is less than or equal to the
+  tolerance parameter. Returns 1 if the two ADDs are equal (within
+  tolerance); 0 otherwise. If parameter <code>pr</code> is positive
+  the first failure is reported to the standard output.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_EqualSupNorm(
+  DdManager * dd /* manager */,
+  DdNode * f /* first ADD */,
+  DdNode * g /* second ADD */,
+  CUDD_VALUE_TYPE  tolerance /* maximum allowed difference */,
+  int  pr /* verbosity level */)
+{
+    DdNode *fv, *fvn, *gv, *gvn, *r;
+    unsigned int topf, topg;
+
+    statLine(dd);
+    /* Check terminal cases. */
+    if (f == g) return(1);
+    if (Cudd_IsConstant(f) && Cudd_IsConstant(g)) {
+        if (ddEqualVal(cuddV(f),cuddV(g),tolerance)) {
+            return(1);
+        } else {
+            if (pr>0) {
+                (void) fprintf(dd->out,"Offending nodes:\n");
+                (void) fprintf(dd->out,
+                               "f: address = %p\t value = %40.30f\n",
+                               (void *) f, cuddV(f));
+                (void) fprintf(dd->out,
+                               "g: address = %p\t value = %40.30f\n",
+                               (void *) g, cuddV(g));
+            }
+            return(0);
+        }
+    }
+
+    /* We only insert the result in the cache if the comparison is
+    ** successful. Therefore, if we hit we return 1. */
+    r = cuddCacheLookup2(dd,(DD_CTFP)Cudd_EqualSupNorm,f,g);
+    if (r != NULL) {
+        return(1);
+    }
+
+    /* Compute the cofactors and solve the recursive subproblems. */
+    topf = cuddI(dd,f->index);
+    topg = cuddI(dd,g->index);
+
+    if (topf <= topg) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;}
+    if (topg <= topf) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;}
+
+    if (!Cudd_EqualSupNorm(dd,fv,gv,tolerance,pr)) return(0);
+    if (!Cudd_EqualSupNorm(dd,fvn,gvn,tolerance,pr)) return(0);
+
+    cuddCacheInsert2(dd,(DD_CTFP)Cudd_EqualSupNorm,f,g,DD_ONE(dd));
+
+    return(1);
+
+} /* end of Cudd_EqualSupNorm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Expands cube to a prime implicant of f.]
+
+  Description [Expands cube to a prime implicant of f. Returns the prime
+  if successful; NULL otherwise.  In particular, NULL is returned if cube
+  is not a real cube or is not an implicant of f.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_bddMakePrime(
+  DdManager *dd /* manager */,
+  DdNode *cube /* cube to be expanded */,
+  DdNode *f /* function of which the cube is to be made a prime */)
+{
+    DdNode *res;
+
+    if (!Cudd_bddLeq(dd,cube,f)) return(NULL);
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddMakePrime(dd,cube,f);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddMakePrime */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddMakePrime.]
+
+  Description [Performs the recursive step of Cudd_bddMakePrime.
+  Returns the prime if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddBddMakePrime(
+  DdManager *dd /* manager */,
+  DdNode *cube /* cube to be expanded */,
+  DdNode *f /* function of which the cube is to be made a prime */)
+{
+    DdNode *scan;
+    DdNode *t, *e;
+    DdNode *res = cube;
+    DdNode *zero = Cudd_Not(DD_ONE(dd));
+
+    Cudd_Ref(res);
+    scan = cube;
+    while (!Cudd_IsConstant(scan)) {
+        DdNode *reg = Cudd_Regular(scan);
+        DdNode *var = dd->vars[reg->index];
+        DdNode *expanded = Cudd_bddExistAbstract(dd,res,var);
+        if (expanded == NULL) {
+            return(NULL);
+        }
+        Cudd_Ref(expanded);
+        if (Cudd_bddLeq(dd,expanded,f)) {
+            Cudd_RecursiveDeref(dd,res);
+            res = expanded;
+        } else {
+            Cudd_RecursiveDeref(dd,expanded);
+        }
+        cuddGetBranches(scan,&t,&e);
+        if (t == zero) {
+            scan = e;
+        } else if (e == zero) {
+            scan = t;
+        } else {
+            Cudd_RecursiveDeref(dd,res);
+            return(NULL);       /* cube is not a cube */
+        }
+    }
+
+    if (scan == DD_ONE(dd)) {
+        Cudd_Deref(res);
+        return(res);
+    } else {
+        Cudd_RecursiveDeref(dd,res);
+        return(NULL);
+    }
+
+} /* end of cuddBddMakePrime */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the entries of the visited symbol table.]
+
+  Description [Frees the entries of the visited symbol table. Returns
+  st__CONTINUE.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static enum st__retval
+freePathPair(
+  char * key,
+  char * value,
+  char * arg)
+{
+    cuddPathPair *pair;
+
+    pair = (cuddPathPair *) value;
+        ABC_FREE(pair);
+    return( st__CONTINUE);
+
+} /* end of freePathPair */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the length of the shortest path(s) in a DD.]
+
+  Description [Finds the length of the shortest path(s) in a DD.
+  Uses a local symbol table to store the lengths for each
+  node. Only the lengths for the regular nodes are entered in the table,
+  because those for the complement nodes are simply obtained by swapping
+  the two lenghts.
+  Returns a pair of lengths: the length of the shortest path to 1;
+  and the length of the shortest path to 0. This is done so as to take
+  complement arcs into account.]
+
+  SideEffects [Accumulates the support of the DD in support.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static cuddPathPair
+getShortest(
+  DdNode * root,
+  int * cost,
+  int * support,
+  st__table * visited)
+{
+    cuddPathPair *my_pair, res_pair, pair_T, pair_E;
+    DdNode      *my_root, *T, *E;
+    int         weight;
+
+    my_root = Cudd_Regular(root);
+
+    if ( st__lookup(visited, (const char *)my_root, (char **)&my_pair)) {
+        if (Cudd_IsComplement(root)) {
+            res_pair.pos = my_pair->neg;
+            res_pair.neg = my_pair->pos;
+        } else {
+            res_pair.pos = my_pair->pos;
+            res_pair.neg = my_pair->neg;
+        }
+        return(res_pair);
+    }
+
+    /* In the case of a BDD the following test is equivalent to
+    ** testing whether the BDD is the constant 1. This formulation,
+    ** however, works for ADDs as well, by assuming the usual
+    ** dichotomy of 0 and != 0.
+    */
+    if (cuddIsConstant(my_root)) {
+        if (my_root != zero) {
+            res_pair.pos = 0;
+            res_pair.neg = DD_BIGGY;
+        } else {
+            res_pair.pos = DD_BIGGY;
+            res_pair.neg = 0;
+        }
+    } else {
+        T = cuddT(my_root);
+        E = cuddE(my_root);
+
+        pair_T = getShortest(T, cost, support, visited);
+        pair_E = getShortest(E, cost, support, visited);
+        weight = WEIGHT(cost, my_root->index);
+        res_pair.pos = ddMin(pair_T.pos+weight, pair_E.pos);
+        res_pair.neg = ddMin(pair_T.neg+weight, pair_E.neg);
+
+        /* Update support. */
+        if (support != NULL) {
+            support[my_root->index] = 1;
+        }
+    }
+
+    my_pair = ABC_ALLOC(cuddPathPair, 1);
+    if (my_pair == NULL) {
+        if (Cudd_IsComplement(root)) {
+            int tmp = res_pair.pos;
+            res_pair.pos = res_pair.neg;
+            res_pair.neg = tmp;
+        }
+        return(res_pair);
+    }
+    my_pair->pos = res_pair.pos;
+    my_pair->neg = res_pair.neg;
+
+    st__insert(visited, (char *)my_root, (char *)my_pair);
+    if (Cudd_IsComplement(root)) {
+        res_pair.pos = my_pair->neg;
+        res_pair.neg = my_pair->pos;
+    } else {
+        res_pair.pos = my_pair->pos;
+        res_pair.neg = my_pair->neg;
+    }
+    return(res_pair);
+
+} /* end of getShortest */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Build a BDD for a shortest path of f.]
+
+  Description [Build a BDD for a shortest path of f.
+  Given the minimum length from the root, and the minimum
+  lengths for each node (in visited), apply triangulation at each node.
+  Of the two children of each node on a shortest path, at least one is
+  on a shortest path. In case of ties the procedure chooses the THEN
+  children.
+  Returns a pointer to the cube BDD representing the path if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+getPath(
+  DdManager * manager,
+  st__table * visited,
+  DdNode * f,
+  int * weight,
+  int  cost)
+{
+    DdNode      *sol, *tmp;
+    DdNode      *my_dd, *T, *E;
+    cuddPathPair *T_pair, *E_pair;
+    int         Tcost, Ecost;
+    int         complement;
+
+    my_dd = Cudd_Regular(f);
+    complement = Cudd_IsComplement(f);
+
+    sol = one;
+    cuddRef(sol);
+
+    while (!cuddIsConstant(my_dd)) {
+        Tcost = cost - WEIGHT(weight, my_dd->index);
+        Ecost = cost;
+
+        T = cuddT(my_dd);
+        E = cuddE(my_dd);
+
+        if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);}
+
+        st__lookup(visited, (const char *)Cudd_Regular(T), (char **)&T_pair);
+        if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) ||
+        (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) {
+            tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol);
+            if (tmp == NULL) {
+                Cudd_RecursiveDeref(manager,sol);
+                return(NULL);
+            }
+            cuddRef(tmp);
+            Cudd_RecursiveDeref(manager,sol);
+            sol = tmp;
+
+            complement =  Cudd_IsComplement(T);
+            my_dd = Cudd_Regular(T);
+            cost = Tcost;
+            continue;
+        }
+        st__lookup(visited, (const char *)Cudd_Regular(E), (char **)&E_pair);
+        if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) ||
+        (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) {
+            tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol);
+            if (tmp == NULL) {
+                Cudd_RecursiveDeref(manager,sol);
+                return(NULL);
+            }
+            cuddRef(tmp);
+            Cudd_RecursiveDeref(manager,sol);
+            sol = tmp;
+            complement = Cudd_IsComplement(E);
+            my_dd = Cudd_Regular(E);
+            cost = Ecost;
+            continue;
+        }
+        (void) fprintf(manager->err,"We shouldn't be here!!\n");
+        manager->errorCode = CUDD_INTERNAL_ERROR;
+        return(NULL);
+    }
+
+    cuddDeref(sol);
+    return(sol);
+
+} /* end of getPath */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the size of the largest cube(s) in a DD.]
+
+  Description [Finds the size of the largest cube(s) in a DD.
+  This problem is translated into finding the shortest paths from a node
+  when both THEN and ELSE arcs have unit lengths.
+  Uses a local symbol table to store the lengths for each
+  node. Only the lengths for the regular nodes are entered in the table,
+  because those for the complement nodes are simply obtained by swapping
+  the two lenghts.
+  Returns a pair of lengths: the length of the shortest path to 1;
+  and the length of the shortest path to 0. This is done so as to take
+  complement arcs into account.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+static cuddPathPair
+getLargest(
+  DdNode * root,
+  st__table * visited)
+{
+    cuddPathPair *my_pair, res_pair, pair_T, pair_E;
+    DdNode      *my_root, *T, *E;
+
+    my_root = Cudd_Regular(root);
+
+    if ( st__lookup(visited, (const char *)my_root, (char **)&my_pair)) {
+        if (Cudd_IsComplement(root)) {
+            res_pair.pos = my_pair->neg;
+            res_pair.neg = my_pair->pos;
+        } else {
+            res_pair.pos = my_pair->pos;
+            res_pair.neg = my_pair->neg;
+        }
+        return(res_pair);
+    }
+
+    /* In the case of a BDD the following test is equivalent to
+    ** testing whether the BDD is the constant 1. This formulation,
+    ** however, works for ADDs as well, by assuming the usual
+    ** dichotomy of 0 and != 0.
+    */
+    if (cuddIsConstant(my_root)) {
+        if (my_root != zero) {
+            res_pair.pos = 0;
+            res_pair.neg = DD_BIGGY;
+        } else {
+            res_pair.pos = DD_BIGGY;
+            res_pair.neg = 0;
+        }
+    } else {
+        T = cuddT(my_root);
+        E = cuddE(my_root);
+
+        pair_T = getLargest(T, visited);
+        pair_E = getLargest(E, visited);
+        res_pair.pos = ddMin(pair_T.pos, pair_E.pos) + 1;
+        res_pair.neg = ddMin(pair_T.neg, pair_E.neg) + 1;
+    }
+
+    my_pair = ABC_ALLOC(cuddPathPair, 1);
+    if (my_pair == NULL) {      /* simply do not cache this result */
+        if (Cudd_IsComplement(root)) {
+            int tmp = res_pair.pos;
+            res_pair.pos = res_pair.neg;
+            res_pair.neg = tmp;
+        }
+        return(res_pair);
+    }
+    my_pair->pos = res_pair.pos;
+    my_pair->neg = res_pair.neg;
+
+    /* Caching may fail without affecting correctness. */
+    st__insert(visited, (char *)my_root, (char *)my_pair);
+    if (Cudd_IsComplement(root)) {
+        res_pair.pos = my_pair->neg;
+        res_pair.neg = my_pair->pos;
+    } else {
+        res_pair.pos = my_pair->pos;
+        res_pair.neg = my_pair->neg;
+    }
+    return(res_pair);
+
+} /* end of getLargest */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Build a BDD for a largest cube of f.]
+
+  Description [Build a BDD for a largest cube of f.
+  Given the minimum length from the root, and the minimum
+  lengths for each node (in visited), apply triangulation at each node.
+  Of the two children of each node on a shortest path, at least one is
+  on a shortest path. In case of ties the procedure chooses the THEN
+  children.
+  Returns a pointer to the cube BDD representing the path if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+getCube(
+  DdManager * manager,
+  st__table * visited,
+  DdNode * f,
+  int  cost)
+{
+    DdNode      *sol, *tmp;
+    DdNode      *my_dd, *T, *E;
+    cuddPathPair *T_pair, *E_pair;
+    int         Tcost, Ecost;
+    int         complement;
+
+    my_dd = Cudd_Regular(f);
+    complement = Cudd_IsComplement(f);
+
+    sol = one;
+    cuddRef(sol);
+
+    while (!cuddIsConstant(my_dd)) {
+        Tcost = cost - 1;
+        Ecost = cost - 1;
+
+        T = cuddT(my_dd);
+        E = cuddE(my_dd);
+
+        if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);}
+
+        if (! st__lookup(visited, (const char *)Cudd_Regular(T), (char **)&T_pair)) return(NULL);
+        if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) ||
+        (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) {
+            tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol);
+            if (tmp == NULL) {
+                Cudd_RecursiveDeref(manager,sol);
+                return(NULL);
+            }
+            cuddRef(tmp);
+            Cudd_RecursiveDeref(manager,sol);
+            sol = tmp;
+
+            complement =  Cudd_IsComplement(T);
+            my_dd = Cudd_Regular(T);
+            cost = Tcost;
+            continue;
+        }
+        if (! st__lookup(visited, (const char *)Cudd_Regular(E), (char **)&E_pair)) return(NULL);
+        if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) ||
+        (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) {
+            tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol);
+            if (tmp == NULL) {
+                Cudd_RecursiveDeref(manager,sol);
+                return(NULL);
+            }
+            cuddRef(tmp);
+            Cudd_RecursiveDeref(manager,sol);
+            sol = tmp;
+            complement = Cudd_IsComplement(E);
+            my_dd = Cudd_Regular(E);
+            cost = Ecost;
+            continue;
+        }
+        (void) fprintf(manager->err,"We shouldn't be here!\n");
+        manager->errorCode = CUDD_INTERNAL_ERROR;
+        return(NULL);
+    }
+
+    cuddDeref(sol);
+    return(sol);
+
+} /* end of getCube */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddSign.c b/abc-build/src/bdd/cudd/cuddSign.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddSign.c
@@ -0,0 +1,326 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddSign.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Computation of signatures.]
+
+  Description [External procedures included in this module:
+                    <ul>
+                    <li> Cudd_CofMinterm();
+                    </ul>
+                Static procedures included in this module:
+                    <ul>
+                    <li> ddCofMintermAux()
+                    </ul>
+                    ]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddSign.c,v 1.22 2009/02/20 02:14:58 fabio Exp $";
+#endif
+
+static int    size;
+
+#ifdef DD_STATS
+static int num_calls;   /* should equal 2n-1 (n is the # of nodes) */
+static int table_mem;
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static double * ddCofMintermAux (DdManager *dd, DdNode *node, st__table *table);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Computes the fraction of minterms in the on-set of all the
+  positive cofactors of a BDD or ADD.]
+
+  Description [Computes the fraction of minterms in the on-set of all
+  the positive cofactors of DD. Returns the pointer to an array of
+  doubles if successful; NULL otherwise. The array has as many
+  positions as there are BDD variables in the manager plus one. The
+  last position of the array contains the fraction of the minterms in
+  the ON-set of the function represented by the BDD or ADD. The other
+  positions of the array hold the variable signatures.]
+
+  SideEffects [None]
+
+******************************************************************************/
+double *
+Cudd_CofMinterm(
+  DdManager * dd,
+  DdNode * node)
+{
+    st__table    *table;
+    double      *values;
+    double      *result = NULL;
+    int         i, firstLevel;
+
+#ifdef DD_STATS
+    long startTime;
+    startTime = util_cpu_time();
+    num_calls = 0;
+    table_mem = sizeof( st__table);
+#endif
+
+    table = st__init_table( st__ptrcmp, st__ptrhash);
+    if (table == NULL) {
+        (void) fprintf(dd->err,
+                       "out-of-memory, couldn't measure DD cofactors.\n");
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    size = dd->size;
+    values = ddCofMintermAux(dd, node, table);
+    if (values != NULL) {
+        result = ABC_ALLOC(double,size + 1);
+        if (result != NULL) {
+#ifdef DD_STATS
+            table_mem += (size + 1) * sizeof(double);
+#endif
+            if (Cudd_IsConstant(node))
+                firstLevel = 1;
+            else
+                firstLevel = cuddI(dd,Cudd_Regular(node)->index);
+            for (i = 0; i < size; i++) {
+                if (i >= cuddI(dd,Cudd_Regular(node)->index)) {
+                    result[dd->invperm[i]] = values[i - firstLevel];
+                } else {
+                    result[dd->invperm[i]] = values[size - firstLevel];
+                }
+            }
+            result[size] = values[size - firstLevel];
+        } else {
+            dd->errorCode = CUDD_MEMORY_OUT;
+        }
+    }
+
+#ifdef DD_STATS
+    table_mem += table->num_bins * sizeof( st__table_entry *);
+#endif
+    if (Cudd_Regular(node)->ref == 1) ABC_FREE(values);
+    st__foreach(table, cuddStCountfree, NULL);
+    st__free_table(table);
+#ifdef DD_STATS
+    (void) fprintf(dd->out,"Number of calls: %d\tTable memory: %d bytes\n",
+                  num_calls, table_mem);
+    (void) fprintf(dd->out,"Time to compute measures: %s\n",
+                  util_print_time(util_cpu_time() - startTime));
+#endif
+    if (result == NULL) {
+        (void) fprintf(dd->out,
+                       "out-of-memory, couldn't measure DD cofactors.\n");
+        dd->errorCode = CUDD_MEMORY_OUT;
+    }
+    return(result);
+
+} /* end of Cudd_CofMinterm */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursive Step for Cudd_CofMinterm function.]
+
+  Description [Traverses the DD node and computes the fraction of
+  minterms in the on-set of all positive cofactors simultaneously.
+  It allocates an array with two more entries than there are
+  variables below the one labeling the node.  One extra entry (the
+  first in the array) is for the variable labeling the node. The other
+  entry (the last one in the array) holds the fraction of minterms of
+  the function rooted at node.  Each other entry holds the value for
+  one cofactor. The array is put in a symbol table, to avoid repeated
+  computation, and its address is returned by the procedure, for use
+  by the caller.  Returns a pointer to the array of cofactor measures.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static double *
+ddCofMintermAux(
+  DdManager * dd,
+  DdNode * node,
+  st__table * table)
+{
+    DdNode      *N;             /* regular version of node */
+    DdNode      *Nv, *Nnv;
+    double      *values;
+    double      *valuesT, *valuesE;
+    int         i;
+    int         localSize, localSizeT, localSizeE;
+    double      vT, vE;
+
+    statLine(dd);
+#ifdef DD_STATS
+    num_calls++;
+#endif
+
+    if ( st__lookup(table, (const char *)node, (char **)&values)) {
+        return(values);
+    }
+
+    N = Cudd_Regular(node);
+    if (cuddIsConstant(N)) {
+        localSize = 1;
+    } else {
+        localSize = size - cuddI(dd,N->index) + 1;
+    }
+    values = ABC_ALLOC(double, localSize);
+    if (values == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+
+    if (cuddIsConstant(N)) {
+        if (node == DD_ZERO(dd) || node == Cudd_Not(DD_ONE(dd))) {
+            values[0] = 0.0;
+        } else {
+            values[0] = 1.0;
+        }
+    } else {
+        Nv = Cudd_NotCond(cuddT(N),N!=node);
+        Nnv = Cudd_NotCond(cuddE(N),N!=node);
+
+        valuesT = ddCofMintermAux(dd, Nv, table);
+        if (valuesT == NULL) return(NULL);
+        valuesE = ddCofMintermAux(dd, Nnv, table);
+        if (valuesE == NULL) return(NULL);
+
+        if (Cudd_IsConstant(Nv)) {
+            localSizeT = 1;
+        } else {
+            localSizeT = size - cuddI(dd,Cudd_Regular(Nv)->index) + 1;
+        }
+        if (Cudd_IsConstant(Nnv)) {
+            localSizeE = 1;
+        } else {
+            localSizeE = size - cuddI(dd,Cudd_Regular(Nnv)->index) + 1;
+        }
+        values[0] = valuesT[localSizeT - 1];
+        for (i = 1; i < localSize; i++) {
+            if (i >= cuddI(dd,Cudd_Regular(Nv)->index) - cuddI(dd,N->index)) {
+                vT = valuesT[i - cuddI(dd,Cudd_Regular(Nv)->index) +
+                            cuddI(dd,N->index)];
+            } else {
+                vT = valuesT[localSizeT - 1];
+            }
+            if (i >= cuddI(dd,Cudd_Regular(Nnv)->index) - cuddI(dd,N->index)) {
+                vE = valuesE[i - cuddI(dd,Cudd_Regular(Nnv)->index) +
+                            cuddI(dd,N->index)];
+            } else {
+                vE = valuesE[localSizeE - 1];
+            }
+            values[i] = (vT + vE) / 2.0;
+        }
+        if (Cudd_Regular(Nv)->ref == 1) ABC_FREE(valuesT);
+        if (Cudd_Regular(Nnv)->ref == 1) ABC_FREE(valuesE);
+    }
+
+    if (N->ref > 1) {
+        if ( st__add_direct(table, (char *) node, (char *) values) == st__OUT_OF_MEM) {
+            ABC_FREE(values);
+            return(NULL);
+        }
+#ifdef DD_STATS
+        table_mem += localSize * sizeof(double) + sizeof( st__table_entry);
+#endif
+    }
+    return(values);
+
+} /* end of ddCofMintermAux */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddSolve.c b/abc-build/src/bdd/cudd/cuddSolve.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddSolve.c
@@ -0,0 +1,374 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddSolve.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Boolean equation solver and related functions.]
+
+  Description [External functions included in this modoule:
+                <ul>
+                <li> Cudd_SolveEqn()
+                <li> Cudd_VerifySol()
+                </ul>
+        Internal functions included in this module:
+                <ul>
+                <li> cuddSolveEqnRecur()
+                <li> cuddVerifySol()
+                </ul> ]
+
+  SeeAlso     []
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddSolve.c,v 1.12 2004/08/13 18:04:51 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the solution of F(x,y) = 0.]
+
+  Description [Implements the solution for F(x,y) = 0. The return
+  value is the consistency condition. The y variables are the unknowns
+  and the remaining variables are the parameters.  Returns the
+  consistency condition if successful; NULL otherwise. Cudd_SolveEqn
+  allocates an array and fills it with the indices of the
+  unknowns. This array is used by Cudd_VerifySol.]
+
+  SideEffects [The solution is returned in G; the indices of the y
+  variables are returned in yIndex.]
+
+  SeeAlso     [Cudd_VerifySol]
+
+******************************************************************************/
+DdNode *
+Cudd_SolveEqn(
+  DdManager *  bdd,
+  DdNode * F /* the left-hand side of the equation */,
+  DdNode * Y /* the cube of the y variables */,
+  DdNode ** G /* the array of solutions (return parameter) */,
+  int ** yIndex /* index of y variables */,
+  int  n /* numbers of unknowns */)
+{
+    DdNode *res;
+    int *temp;
+
+    *yIndex = temp = ABC_ALLOC(int, n);
+    if (temp == NULL) {
+        bdd->errorCode = CUDD_MEMORY_OUT;
+        (void) fprintf(bdd->out,
+                       "Cudd_SolveEqn: Out of memory for yIndex\n");
+        return(NULL);
+    }
+
+    do {
+        bdd->reordered = 0;
+        res = cuddSolveEqnRecur(bdd, F, Y, G, n, temp, 0);
+    } while (bdd->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_SolveEqn */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the solution of F(x,y) = 0.]
+
+  Description [Checks the solution of F(x,y) = 0. This procedure 
+  substitutes the solution components for the unknowns of F and returns 
+  the resulting BDD for F.] 
+
+  SideEffects [Frees the memory pointed by yIndex.]
+
+  SeeAlso     [Cudd_SolveEqn]
+
+******************************************************************************/
+DdNode *
+Cudd_VerifySol(
+  DdManager *  bdd,
+  DdNode * F /* the left-hand side of the equation */,
+  DdNode ** G /* the array of solutions */,
+  int * yIndex /* index of y variables */,
+  int  n /* numbers of unknowns */)
+{
+    DdNode *res;
+
+    do {
+        bdd->reordered = 0;
+        res = cuddVerifySol(bdd, F, G, yIndex, n);
+    } while (bdd->reordered == 1);
+
+    ABC_FREE(yIndex);
+
+    return(res);
+
+} /* end of Cudd_VerifySol */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_SolveEqn.]
+
+  Description [Implements the recursive step of Cudd_SolveEqn. 
+  Returns NULL if the intermediate solution blows up
+  or reordering occurs. The parametric solutions are
+  stored in the array G.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_SolveEqn, Cudd_VerifySol]
+
+******************************************************************************/
+DdNode *
+cuddSolveEqnRecur(
+  DdManager * bdd,
+  DdNode * F /* the left-hand side of the equation */,
+  DdNode * Y /* the cube of remaining y variables */,
+  DdNode ** G /* the array of solutions */,
+  int  n /* number of unknowns */,
+  int * yIndex /* array holding the y variable indices */,
+  int  i /* level of recursion */)
+{
+    DdNode *Fn, *Fm1, *Fv, *Fvbar, *T, *w, *nextY, *one;
+    DdNodePtr *variables;
+
+    int j;
+
+    statLine(bdd);
+    variables = bdd->vars;
+    one = DD_ONE(bdd);
+
+    /* Base condition. */
+    if (Y == one) {
+        return F;
+    }
+
+    /* Cofactor of Y. */
+    yIndex[i] = Y->index;
+    nextY = Cudd_T(Y);
+
+    /* Universal abstraction of F with respect to the top variable index. */
+    Fm1 = cuddBddExistAbstractRecur(bdd, Cudd_Not(F), variables[yIndex[i]]);
+    if (Fm1) {
+        Fm1 = Cudd_Not(Fm1);
+        cuddRef(Fm1);
+    } else {
+        return(NULL);
+    }
+
+    Fn = cuddSolveEqnRecur(bdd, Fm1, nextY, G, n, yIndex, i+1);
+    if (Fn) {
+        cuddRef(Fn);
+    } else {
+        Cudd_RecursiveDeref(bdd, Fm1);
+        return(NULL);
+    }
+
+    Fv = cuddCofactorRecur(bdd, F, variables[yIndex[i]]);
+    if (Fv) {
+        cuddRef(Fv);
+    } else {
+        Cudd_RecursiveDeref(bdd, Fm1);
+        Cudd_RecursiveDeref(bdd, Fn);
+        return(NULL);
+    }
+
+    Fvbar = cuddCofactorRecur(bdd, F, Cudd_Not(variables[yIndex[i]]));
+    if (Fvbar) {
+        cuddRef(Fvbar);
+    } else {
+        Cudd_RecursiveDeref(bdd, Fm1);
+        Cudd_RecursiveDeref(bdd, Fn);
+        Cudd_RecursiveDeref(bdd, Fv);
+        return(NULL);
+    }
+
+    /* Build i-th component of the solution. */
+    w = cuddBddIteRecur(bdd, variables[yIndex[i]], Cudd_Not(Fv), Fvbar);
+    if (w) {
+        cuddRef(w);
+    } else {
+        Cudd_RecursiveDeref(bdd, Fm1);
+        Cudd_RecursiveDeref(bdd, Fn);
+        Cudd_RecursiveDeref(bdd, Fv);
+        Cudd_RecursiveDeref(bdd, Fvbar);
+        return(NULL);
+    }
+
+    T = cuddBddRestrictRecur(bdd, w, Cudd_Not(Fm1));
+    if(T) {
+        cuddRef(T);
+    } else {
+        Cudd_RecursiveDeref(bdd, Fm1);
+        Cudd_RecursiveDeref(bdd, Fn);
+        Cudd_RecursiveDeref(bdd, Fv);
+        Cudd_RecursiveDeref(bdd, Fvbar);
+        Cudd_RecursiveDeref(bdd, w);
+        return(NULL);
+    }
+
+    Cudd_RecursiveDeref(bdd,Fm1);
+    Cudd_RecursiveDeref(bdd,w);
+    Cudd_RecursiveDeref(bdd,Fv);
+    Cudd_RecursiveDeref(bdd,Fvbar);
+
+    /* Substitute components of solution already found into solution. */
+    for (j = n-1; j > i; j--) {
+        w = cuddBddComposeRecur(bdd,T, G[j], variables[yIndex[j]]);
+        if(w) {
+            cuddRef(w);
+        } else {
+            Cudd_RecursiveDeref(bdd, Fn);
+            Cudd_RecursiveDeref(bdd, T);
+            return(NULL);
+        }
+        Cudd_RecursiveDeref(bdd,T);
+        T = w;
+    }
+    G[i] = T;
+
+    Cudd_Deref(Fn);
+
+    return(Fn);
+
+} /* end of cuddSolveEqnRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_VerifySol. ]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_VerifySol]
+
+******************************************************************************/
+DdNode *
+cuddVerifySol(
+  DdManager * bdd,
+  DdNode * F /* the left-hand side of the equation */,
+  DdNode ** G /* the array of solutions */,
+  int * yIndex /* array holding the y variable indices */,
+  int  n /* number of unknowns */)
+{
+    DdNode *w, *R;
+
+    int j;
+
+    R = F;
+    cuddRef(R);
+    for(j = n - 1; j >= 0; j--) {
+         w = Cudd_bddCompose(bdd, R, G[j], yIndex[j]);
+        if (w) {
+            cuddRef(w);
+        } else {
+            return(NULL); 
+        }
+        Cudd_RecursiveDeref(bdd,R);
+        R = w;
+    }
+
+    cuddDeref(R);
+
+    return(R);
+
+} /* end of cuddVerifySol */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddSplit.c b/abc-build/src/bdd/cudd/cuddSplit.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddSplit.c
@@ -0,0 +1,694 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddSplit.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Returns a subset of minterms from a boolean function.]
+
+  Description [External functions included in this modoule:
+                <ul>
+                <li> Cudd_SplitSet()
+                </ul>
+        Internal functions included in this module:
+                <ul>
+                <li> cuddSplitSetRecur()
+                </u>
+        Static functions included in this module:
+                <ul>
+                <li> selectMintermsFromUniverse()
+                <li> mintermsFromUniverse()
+                <li> bddAnnotateMintermCount()
+                </ul> ]
+
+  SeeAlso     []
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * selectMintermsFromUniverse (DdManager *manager, int *varSeen, double n);
+static DdNode * mintermsFromUniverse (DdManager *manager, DdNode **vars, int numVars, double n, int index);
+static double bddAnnotateMintermCount (DdManager *manager, DdNode *node, double max, st__table *table);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns m minterms from a BDD.]
+
+  Description [Returns <code>m</code> minterms from a BDD whose
+  support has <code>n</code> variables at most.  The procedure tries
+  to create as few extra nodes as possible. The function represented
+  by <code>S</code> depends on at most <code>n</code> of the variables
+  in <code>xVars</code>. Returns a BDD with <code>m</code> minterms
+  of the on-set of S if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_SplitSet(
+  DdManager * manager,
+  DdNode * S,
+  DdNode ** xVars,
+  int  n,
+  double  m)
+{
+    DdNode *result;
+    DdNode *zero, *one;
+    double  max, num;
+    st__table *mtable;
+    int *varSeen;
+    int i,index, size;
+
+    size = manager->size;
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    /* Trivial cases. */
+    if (m == 0.0) {
+        return(zero);
+    }
+    if (S == zero) {
+        return(NULL);
+    }
+
+    max = pow(2.0,(double)n);
+    if (m > max)
+        return(NULL);
+
+    do {
+        manager->reordered = 0;
+        /* varSeen is used to mark the variables that are encountered
+        ** while traversing the BDD S.
+        */
+        varSeen = ABC_ALLOC(int, size);
+        if (varSeen == NULL) {
+            manager->errorCode = CUDD_MEMORY_OUT;
+            return(NULL);
+        }
+        for (i = 0; i < size; i++) {
+            varSeen[i] = -1;
+        }
+        for (i = 0; i < n; i++) {
+            index = (xVars[i])->index;
+            varSeen[manager->invperm[index]] = 0;
+        }
+
+        if (S == one) {
+            if (m == max) {
+                ABC_FREE(varSeen);
+                return(S);
+            }
+            result = selectMintermsFromUniverse(manager,varSeen,m);
+            if (result)
+                cuddRef(result);
+            ABC_FREE(varSeen);
+        } else {
+            mtable = st__init_table( st__ptrcmp, st__ptrhash);
+            if (mtable == NULL) {
+                (void) fprintf(manager->out,
+                               "Cudd_SplitSet: out-of-memory.\n");
+                ABC_FREE(varSeen);
+                manager->errorCode = CUDD_MEMORY_OUT;
+                return(NULL);
+            }
+            /* The nodes of BDD S are annotated by the number of minterms
+            ** in their onset. The node and the number of minterms in its
+            ** onset are stored in mtable.
+            */
+            num = bddAnnotateMintermCount(manager,S,max,mtable);
+            if (m == num) {
+                st__foreach(mtable,cuddStCountfree,NIL(char));
+                st__free_table(mtable);
+                ABC_FREE(varSeen);
+                return(S);
+            }
+            
+            result = cuddSplitSetRecur(manager,mtable,varSeen,S,m,max,0);
+            if (result)
+                cuddRef(result);
+            st__foreach(mtable,cuddStCountfree,NULL);
+            st__free_table(mtable);
+            ABC_FREE(varSeen);
+        }
+    } while (manager->reordered == 1);
+
+    cuddDeref(result);
+    return(result);
+
+} /* end of Cudd_SplitSet */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_SplitSet.]
+
+  Description [Implements the recursive step of Cudd_SplitSet. The
+  procedure recursively traverses the BDD and checks to see if any
+  node satisfies the minterm requirements as specified by 'n'. At any
+  node X, n is compared to the number of minterms in the onset of X's
+  children. If either of the child nodes have exactly n minterms, then
+  that node is returned; else, if n is greater than the onset of one
+  of the child nodes, that node is retained and the difference in the
+  number of minterms is extracted from the other child. In case n
+  minterms can be extracted from constant 1, the algorithm returns the
+  result with at most log(n) nodes.]
+
+  SideEffects [The array 'varSeen' is updated at every recursive call
+  to set the variables traversed by the procedure.]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode*
+cuddSplitSetRecur(
+  DdManager * manager,
+  st__table * mtable,
+  int * varSeen,
+  DdNode * p,
+  double  n,
+  double  max,
+  int  index)
+{
+    DdNode *one, *zero, *N, *Nv;
+    DdNode *Nnv, *q, *r, *v;
+    DdNode *result;
+    double *dummy, numT, numE;
+    int variable, positive;
+  
+    statLine(manager);
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    /* If p is constant, extract n minterms from constant 1.  The procedure by
+    ** construction guarantees that minterms will not be extracted from
+    ** constant 0.
+    */
+    if (Cudd_IsConstant(p)) {
+        q = selectMintermsFromUniverse(manager,varSeen,n);
+        return(q);
+    }
+
+    N = Cudd_Regular(p);
+
+    /* Set variable as seen. */
+    variable = N->index;
+    varSeen[manager->invperm[variable]] = -1;
+
+    Nv = cuddT(N);
+    Nnv = cuddE(N);
+    if (Cudd_IsComplement(p)) {
+        Nv = Cudd_Not(Nv);
+        Nnv = Cudd_Not(Nnv);
+    }
+
+    /* If both the children of 'p' are constants, extract n minterms from a
+    ** constant node.
+    */
+    if (Cudd_IsConstant(Nv) && Cudd_IsConstant(Nnv)) {
+        q = selectMintermsFromUniverse(manager,varSeen,n);
+        if (q == NULL) {
+            return(NULL);
+        }
+        cuddRef(q);
+        r = cuddBddAndRecur(manager,p,q);
+        if (r == NULL) {
+            Cudd_RecursiveDeref(manager,q);
+            return(NULL);
+        }
+        cuddRef(r);
+        Cudd_RecursiveDeref(manager,q);
+        cuddDeref(r);
+        return(r);
+    }
+  
+    /* Lookup the # of minterms in the onset of the node from the table. */
+    if (!Cudd_IsConstant(Nv)) {
+        if (! st__lookup(mtable, (const char *)Nv, (char **)&dummy)) return(NULL);
+        numT = *dummy/(2*(1<<index));
+    } else if (Nv == one) {
+        numT = max/(2*(1<<index));
+    } else {
+        numT = 0;
+    }
+  
+    if (!Cudd_IsConstant(Nnv)) {
+        if (! st__lookup(mtable, (const char *)Nnv, (char **)&dummy)) return(NULL);
+        numE = *dummy/(2*(1<<index));
+    } else if (Nnv == one) {
+        numE = max/(2*(1<<index));
+    } else {
+        numE = 0;
+    }
+
+    v = cuddUniqueInter(manager,variable,one,zero);
+    cuddRef(v);
+
+    /* If perfect match. */
+    if (numT == n) {
+        q = cuddBddAndRecur(manager,v,Nv);
+        if (q == NULL) {
+            Cudd_RecursiveDeref(manager,v);
+            return(NULL);
+        }
+        cuddRef(q);
+        Cudd_RecursiveDeref(manager,v);
+        cuddDeref(q);
+        return(q);
+    }
+    if (numE == n) {
+        q = cuddBddAndRecur(manager,Cudd_Not(v),Nnv);
+        if (q == NULL) {
+            Cudd_RecursiveDeref(manager,v);
+            return(NULL);
+        }
+        cuddRef(q);
+        Cudd_RecursiveDeref(manager,v);
+        cuddDeref(q);
+        return(q);
+    }
+    /* If n is greater than numT, extract the difference from the ELSE child
+    ** and retain the function represented by the THEN branch.
+    */
+    if (numT < n) {
+        q = cuddSplitSetRecur(manager,mtable,varSeen,
+                              Nnv,(n-numT),max,index+1);
+        if (q == NULL) {
+            Cudd_RecursiveDeref(manager,v);
+            return(NULL);
+        }
+        cuddRef(q);
+        r = cuddBddIteRecur(manager,v,Nv,q);
+        if (r == NULL) {
+            Cudd_RecursiveDeref(manager,q);
+            Cudd_RecursiveDeref(manager,v);
+            return(NULL);
+        }
+        cuddRef(r);
+        Cudd_RecursiveDeref(manager,q);
+        Cudd_RecursiveDeref(manager,v);
+        cuddDeref(r);
+        return(r);
+    }
+    /* If n is greater than numE, extract the difference from the THEN child
+    ** and retain the function represented by the ELSE branch.
+    */
+    if (numE < n) {
+        q = cuddSplitSetRecur(manager,mtable,varSeen,
+                              Nv, (n-numE),max,index+1);
+        if (q == NULL) {
+            Cudd_RecursiveDeref(manager,v);
+            return(NULL);
+        }
+        cuddRef(q);
+        r = cuddBddIteRecur(manager,v,q,Nnv);
+        if (r == NULL) {
+            Cudd_RecursiveDeref(manager,q);
+            Cudd_RecursiveDeref(manager,v);
+            return(NULL);
+        }
+        cuddRef(r);
+        Cudd_RecursiveDeref(manager,q);
+        Cudd_RecursiveDeref(manager,v);
+        cuddDeref(r);    
+        return(r);
+    }
+
+    /* None of the above cases; (n < numT and n < numE) and either of
+    ** the Nv, Nnv or both are not constants. If possible extract the
+    ** required minterms the constant branch.
+    */
+    if (Cudd_IsConstant(Nv) && !Cudd_IsConstant(Nnv)) {
+        q = selectMintermsFromUniverse(manager,varSeen,n);
+        if (q == NULL) {
+            Cudd_RecursiveDeref(manager,v);
+            return(NULL);
+        }
+        cuddRef(q);
+        result = cuddBddAndRecur(manager,v,q);
+        if (result == NULL) {
+            Cudd_RecursiveDeref(manager,q);
+            Cudd_RecursiveDeref(manager,v);
+            return(NULL);
+        }
+        cuddRef(result);
+        Cudd_RecursiveDeref(manager,q);
+        Cudd_RecursiveDeref(manager,v);
+        cuddDeref(result);
+        return(result);
+    } else if (!Cudd_IsConstant(Nv) && Cudd_IsConstant(Nnv)) {
+        q = selectMintermsFromUniverse(manager,varSeen,n);
+        if (q == NULL) {
+            Cudd_RecursiveDeref(manager,v);
+            return(NULL);
+        }
+        cuddRef(q);
+        result = cuddBddAndRecur(manager,Cudd_Not(v),q);
+        if (result == NULL) {
+            Cudd_RecursiveDeref(manager,q);
+            Cudd_RecursiveDeref(manager,v);
+            return(NULL);
+        }
+        cuddRef(result);
+        Cudd_RecursiveDeref(manager,q);
+        Cudd_RecursiveDeref(manager,v);
+        cuddDeref(result);
+        return(result);
+    }
+
+    /* Both Nv and Nnv are not constants. So choose the one which
+    ** has fewer minterms in its onset.
+    */
+    positive = 0;
+    if (numT < numE) {
+        q = cuddSplitSetRecur(manager,mtable,varSeen,
+                              Nv,n,max,index+1);
+        positive = 1;
+    } else {
+        q = cuddSplitSetRecur(manager,mtable,varSeen,
+                              Nnv,n,max,index+1);
+    }
+
+    if (q == NULL) {
+        Cudd_RecursiveDeref(manager,v);
+        return(NULL);
+    }
+    cuddRef(q);
+
+    if (positive) {
+        result = cuddBddAndRecur(manager,v,q);
+    } else {
+        result = cuddBddAndRecur(manager,Cudd_Not(v),q);
+    }
+    if (result == NULL) {
+        Cudd_RecursiveDeref(manager,q);
+        Cudd_RecursiveDeref(manager,v);
+        return(NULL);
+    }
+    cuddRef(result);
+    Cudd_RecursiveDeref(manager,q);
+    Cudd_RecursiveDeref(manager,v);
+    cuddDeref(result);
+
+    return(result);
+
+} /* end of cuddSplitSetRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [This function prepares an array of variables which have not been
+  encountered so far when traversing the procedure cuddSplitSetRecur.]
+
+  Description [This function prepares an array of variables which have not been
+  encountered so far when traversing the procedure cuddSplitSetRecur. This
+  array is then used to extract the required number of minterms from a constant
+  1. The algorithm guarantees that the size of BDD will be utmost \log(n).]
+
+  SideEffects [None]
+
+******************************************************************************/
+static DdNode *
+selectMintermsFromUniverse(
+  DdManager * manager,
+  int * varSeen,
+  double  n)
+{
+    int numVars;
+    int i, size, j;
+     DdNode *one, *zero, *result;
+    DdNode **vars;
+
+    numVars = 0;
+    size = manager->size;
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    /* Count the number of variables not encountered so far in procedure
+    ** cuddSplitSetRecur.
+    */
+    for (i = size-1; i >= 0; i--) {
+        if(varSeen[i] == 0)
+            numVars++;
+    }
+    vars = ABC_ALLOC(DdNode *, numVars);
+    if (!vars) {
+        manager->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+
+    j = 0;
+    for (i = size-1; i >= 0; i--) {
+        if(varSeen[i] == 0) {
+            vars[j] = cuddUniqueInter(manager,manager->perm[i],one,zero);
+            cuddRef(vars[j]);
+            j++;
+        }
+    }
+
+    /* Compute a function which has n minterms and depends on at most
+    ** numVars variables.
+    */
+    result = mintermsFromUniverse(manager,vars,numVars,n, 0);
+    if (result) 
+        cuddRef(result);
+
+    for (i = 0; i < numVars; i++)
+        Cudd_RecursiveDeref(manager,vars[i]);
+    ABC_FREE(vars);
+
+    return(result);
+
+} /* end of selectMintermsFromUniverse */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursive procedure to extract n mintems from constant 1.]
+
+  Description [Recursive procedure to extract n mintems from constant 1.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static DdNode *
+mintermsFromUniverse(
+  DdManager * manager,
+  DdNode ** vars,
+  int  numVars,
+  double  n,
+  int  index)
+{
+    DdNode *one, *zero;
+    DdNode *q, *result;
+    double max, max2;
+    
+    statLine(manager);
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    max = pow(2.0, (double)numVars);
+    max2 = max / 2.0;
+
+    if (n == max)
+        return(one);
+    if (n == 0.0)
+        return(zero);
+    /* if n == 2^(numVars-1), return a single variable */
+    if (n == max2)
+        return vars[index];
+    else if (n > max2) {
+        /* When n > 2^(numVars-1), a single variable vars[index]
+        ** contains 2^(numVars-1) minterms. The rest are extracted
+        ** from a constant with 1 less variable.
+        */
+        q = mintermsFromUniverse(manager,vars,numVars-1,(n-max2),index+1);
+        if (q == NULL)
+            return(NULL);
+        cuddRef(q);
+        result = cuddBddIteRecur(manager,vars[index],one,q);
+    } else {
+        /* When n < 2^(numVars-1), a literal of variable vars[index]
+        ** is selected. The required n minterms are extracted from a
+        ** constant with 1 less variable.
+        */
+        q = mintermsFromUniverse(manager,vars,numVars-1,n,index+1);
+        if (q == NULL)
+            return(NULL);
+        cuddRef(q);
+        result = cuddBddAndRecur(manager,vars[index],q);
+    }
+    
+    if (result == NULL) {
+        Cudd_RecursiveDeref(manager,q);
+        return(NULL);
+    }
+    cuddRef(result);
+    Cudd_RecursiveDeref(manager,q);
+    cuddDeref(result);
+    return(result);
+
+} /* end of mintermsFromUniverse */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Annotates every node in the BDD node with its minterm count.]
+
+  Description [Annotates every node in the BDD node with its minterm count.
+  In this function, every node and the minterm count represented by it are
+  stored in a hash table.]
+
+  SideEffects [Fills up 'table' with the pair <node,minterm_count>.]
+
+******************************************************************************/
+static double
+bddAnnotateMintermCount(
+  DdManager * manager,
+  DdNode * node,
+  double  max,
+  st__table * table)
+{
+
+    DdNode *N,*Nv,*Nnv;
+    register double min_v,min_nv;
+    register double min_N;
+    double *pmin;
+    double *dummy;
+
+    statLine(manager);
+    N = Cudd_Regular(node);
+    if (cuddIsConstant(N)) {
+        if (node == DD_ONE(manager)) {
+            return(max);
+        } else {
+            return(0.0);
+        }
+    }
+
+    if ( st__lookup(table, (const char *)node, (char **)&dummy)) {
+        return(*dummy);
+    }   
+  
+    Nv = cuddT(N);
+    Nnv = cuddE(N);
+    if (N != node) {
+        Nv = Cudd_Not(Nv);
+        Nnv = Cudd_Not(Nnv);
+    }
+
+    /* Recur on the two branches. */
+    min_v  = bddAnnotateMintermCount(manager,Nv,max,table) / 2.0;
+    if (min_v == (double)CUDD_OUT_OF_MEM)
+        return ((double)CUDD_OUT_OF_MEM);
+    min_nv = bddAnnotateMintermCount(manager,Nnv,max,table) / 2.0;
+    if (min_nv == (double)CUDD_OUT_OF_MEM)
+        return ((double)CUDD_OUT_OF_MEM);
+    min_N  = min_v + min_nv;
+
+    pmin = ABC_ALLOC(double,1);
+    if (pmin == NULL) {
+        manager->errorCode = CUDD_MEMORY_OUT;
+        return((double)CUDD_OUT_OF_MEM);
+    }
+    *pmin = min_N;
+
+    if ( st__insert(table,(char *)node, (char *)pmin) == st__OUT_OF_MEM) {
+        ABC_FREE(pmin);
+        return((double)CUDD_OUT_OF_MEM);
+    }
+    
+    return(min_N);
+
+} /* end of bddAnnotateMintermCount */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddSubsetHB.c b/abc-build/src/bdd/cudd/cuddSubsetHB.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddSubsetHB.c
@@ -0,0 +1,1337 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddSubsetHB.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Procedure to subset the given BDD by choosing the heavier
+               branches.]
+
+
+  Description [External procedures provided by this module:
+                <ul>
+                <li> Cudd_SubsetHeavyBranch()
+                <li> Cudd_SupersetHeavyBranch()
+                </ul>
+               Internal procedures included in this module:
+                <ul>
+                <li> cuddSubsetHeavyBranch()
+                </ul>
+               Static procedures included in this module:
+                <ul>
+                <li> ResizeCountMintermPages();
+                <li> ResizeNodeDataPages()
+                <li> ResizeCountNodePages()
+                <li> SubsetCountMintermAux()
+                <li> SubsetCountMinterm()
+                <li> SubsetCountNodesAux()
+                <li> SubsetCountNodes()
+                <li> BuildSubsetBdd()
+                </ul>
+                ]
+
+  SeeAlso     [cuddSubsetSP.c]
+
+  Author      [Kavita Ravi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#ifdef __STDC__
+#include <float.h>
+#else
+#define DBL_MAX_EXP 1024
+#endif
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DEFAULT_PAGE_SIZE 2048
+#define DEFAULT_NODE_DATA_PAGE_SIZE 1024
+#define INITIAL_PAGES 128
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* data structure to store the information on each node. It keeps
+ * the number of minterms represented by the DAG rooted at this node
+ * in terms of the number of variables specified by the user, number
+ * of nodes in this DAG and the number of nodes of its child with
+ * lesser number of minterms that are not shared by the child with
+ * more minterms
+ */
+struct NodeData {
+    double *mintermPointer;
+    int *nodesPointer;
+    int *lightChildNodesPointer;
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct NodeData NodeData_t;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddSubsetHB.c,v 1.37 2009/02/20 02:14:58 fabio Exp $";
+#endif
+
+static int memOut;
+#ifdef DEBUG
+static  int             num_calls;
+#endif
+
+static  DdNode          *zero, *one; /* constant functions */
+static  double          **mintermPages; /* pointers to the pages */
+static  int             **nodePages; /* pointers to the pages */
+static  int             **lightNodePages; /* pointers to the pages */
+static  double          *currentMintermPage; /* pointer to the current
+                                                   page */
+static  double          max; /* to store the 2^n value of the number
+                              * of variables */
+
+static  int             *currentNodePage; /* pointer to the current
+                                                   page */
+static  int             *currentLightNodePage; /* pointer to the
+                                                *  current page */
+static  int             pageIndex; /* index to next element */
+static  int             page; /* index to current page */
+static  int             pageSize = DEFAULT_PAGE_SIZE; /* page size */
+static  int             maxPages; /* number of page pointers */
+
+static  NodeData_t      *currentNodeDataPage; /* pointer to the current
+                                                 page */
+static  int             nodeDataPage; /* index to next element */
+static  int             nodeDataPageIndex; /* index to next element */
+static  NodeData_t      **nodeDataPages; /* index to current page */
+static  int             nodeDataPageSize = DEFAULT_NODE_DATA_PAGE_SIZE;
+                                                     /* page size */
+static  int             maxNodeDataPages; /* number of page pointers */
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void ResizeNodeDataPages (void);
+static void ResizeCountMintermPages (void);
+static void ResizeCountNodePages (void);
+static double SubsetCountMintermAux (DdNode *node, double max, st__table *table);
+static st__table * SubsetCountMinterm (DdNode *node, int nvars);
+static int SubsetCountNodesAux (DdNode *node, st__table *table, double max);
+static int SubsetCountNodes (DdNode *node, st__table *table, int nvars);
+static void StoreNodes ( st__table *storeTable, DdManager *dd, DdNode *node);
+static DdNode * BuildSubsetBdd (DdManager *dd, DdNode *node, int *size, st__table *visitedTable, int threshold, st__table *storeTable, st__table *approxTable);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts a dense subset from a BDD with the heavy branch
+  heuristic.]
+
+  Description [Extracts a dense subset from a BDD. This procedure
+  builds a subset by throwing away one of the children of each node,
+  starting from the root, until the result is small enough. The child
+  that is eliminated from the result is the one that contributes the
+  fewer minterms.  Returns a pointer to the BDD of the subset if
+  successful. NULL if the procedure runs out of memory. The parameter
+  numVars is the maximum number of variables to be used in minterm
+  calculation and node count calculation.  The optimal number should
+  be as close as possible to the size of the support of f.  However,
+  it is safe to pass the value returned by Cudd_ReadSize for numVars
+  when the number of variables is under 1023.  If numVars is larger
+  than 1023, it will overflow. If a 0 parameter is passed then the
+  procedure will compute a value which will avoid overflow but will
+  cause underflow with 2046 variables or more.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetShortPaths Cudd_SupersetHeavyBranch Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_SubsetHeavyBranch(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be subset */,
+  int  numVars /* number of variables in the support of f */,
+  int  threshold /* maximum number of nodes in the subset */)
+{
+    DdNode *subset;
+
+    memOut = 0;
+    do {
+        dd->reordered = 0;
+        subset = cuddSubsetHeavyBranch(dd, f, numVars, threshold);
+    } while ((dd->reordered == 1) && (!memOut));
+
+    return(subset);
+
+} /* end of Cudd_SubsetHeavyBranch */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts a dense superset from a BDD with the heavy branch
+  heuristic.]
+
+  Description [Extracts a dense superset from a BDD. The procedure is
+  identical to the subset procedure except for the fact that it
+  receives the complement of the given function. Extracting the subset
+  of the complement function is equivalent to extracting the superset
+  of the function. This procedure builds a superset by throwing away
+  one of the children of each node starting from the root of the
+  complement function, until the result is small enough. The child
+  that is eliminated from the result is the one that contributes the
+  fewer minterms.
+  Returns a pointer to the BDD of the superset if successful. NULL if
+  intermediate result causes the procedure to run out of memory. The
+  parameter numVars is the maximum number of variables to be used in
+  minterm calculation and node count calculation.  The optimal number
+  should be as close as possible to the size of the support of f.
+  However, it is safe to pass the value returned by Cudd_ReadSize for
+  numVars when the number of variables is under 1023.  If numVars is
+  larger than 1023, it will overflow. If a 0 parameter is passed then
+  the procedure will compute a value which will avoid overflow but
+  will cause underflow with 2046 variables or more.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_SupersetHeavyBranch(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be superset */,
+  int  numVars /* number of variables in the support of f */,
+  int  threshold /* maximum number of nodes in the superset */)
+{
+    DdNode *subset, *g;
+
+    g = Cudd_Not(f);
+    memOut = 0;
+    do {
+        dd->reordered = 0;
+        subset = cuddSubsetHeavyBranch(dd, g, numVars, threshold);
+    } while ((dd->reordered == 1) && (!memOut));
+
+    return(Cudd_NotCond(subset, (subset != NULL)));
+
+} /* end of Cudd_SupersetHeavyBranch */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [The main procedure that returns a subset by choosing the heavier
+  branch in the BDD.]
+
+  Description [Here a subset BDD is built by throwing away one of the
+  children. Starting at root, annotate each node with the number of
+  minterms (in terms of the total number of variables specified -
+  numVars), number of nodes taken by the DAG rooted at this node and
+  number of additional nodes taken by the child that has the lesser
+  minterms. The child with the lower number of minterms is thrown away
+  and a dyanmic count of the nodes of the subset is kept. Once the
+  threshold is reached the subset is returned to the calling
+  procedure.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetHeavyBranch]
+
+******************************************************************************/
+DdNode *
+cuddSubsetHeavyBranch(
+  DdManager * dd /* DD manager */,
+  DdNode * f /* current DD */,
+  int  numVars /* maximum number of variables */,
+  int  threshold /* threshold size for the subset */)
+{
+
+    int i, *size;
+    st__table *visitedTable;
+    int numNodes;
+    NodeData_t *currNodeQual;
+    DdNode *subset;
+    st__table *storeTable, *approxTable;
+    char *key, *value;
+    st__generator *stGen;
+
+    if (f == NULL) {
+        fprintf(dd->err, "Cannot subset, nil object\n");
+        dd->errorCode = CUDD_INVALID_ARG;
+        return(NULL);
+    }
+
+    one  = Cudd_ReadOne(dd);
+    zero = Cudd_Not(one);
+
+    /* If user does not know numVars value, set it to the maximum
+     * exponent that the pow function can take. The -1 is due to the
+     * discrepancy in the value that pow takes and the value that
+     * log gives.
+     */
+    if (numVars == 0) {
+        /* set default value */
+        numVars = DBL_MAX_EXP - 1;
+    }
+
+    if (Cudd_IsConstant(f)) {
+        return(f);
+    }
+
+    max = pow(2.0, (double)numVars);
+
+    /* Create visited table where structures for node data are allocated and
+       stored in a st__table */
+    visitedTable = SubsetCountMinterm(f, numVars);
+    if ((visitedTable == NULL) || memOut) {
+        (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    numNodes = SubsetCountNodes(f, visitedTable, numVars);
+    if (memOut) {
+        (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+
+    if ( st__lookup(visitedTable, (const char *)f, (char **)&currNodeQual) == 0) {
+        fprintf(dd->err,
+                "Something is wrong, ought to be node quality table\n");
+        dd->errorCode = CUDD_INTERNAL_ERROR;
+    }
+
+    size = ABC_ALLOC(int, 1);
+    if (size == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    *size = numNodes;
+
+#ifdef DEBUG
+    num_calls = 0;
+#endif
+    /* table to store nodes being created. */
+    storeTable = st__init_table( st__ptrcmp, st__ptrhash);
+    /* insert the constant */
+    cuddRef(one);
+    if ( st__insert(storeTable, (char *)Cudd_ReadOne(dd), NIL(char)) ==
+        st__OUT_OF_MEM) {
+        fprintf(dd->out, "Something wrong, st__table insert failed\n");
+    }
+    /* table to store approximations of nodes */
+    approxTable = st__init_table( st__ptrcmp, st__ptrhash);
+    subset = (DdNode *)BuildSubsetBdd(dd, f, size, visitedTable, threshold,
+                                      storeTable, approxTable);
+    if (subset != NULL) {
+        cuddRef(subset);
+    }
+
+    stGen = st__init_gen(approxTable);
+    if (stGen == NULL) {
+        st__free_table(approxTable);
+        return(NULL);
+    }
+    while( st__gen(stGen, (const char **)&key, (char **)&value)) {
+        Cudd_RecursiveDeref(dd, (DdNode *)value);
+    }
+    st__free_gen(stGen); stGen = NULL;
+    st__free_table(approxTable);
+
+    stGen = st__init_gen(storeTable);
+    if (stGen == NULL) {
+        st__free_table(storeTable);
+        return(NULL);
+    }
+    while( st__gen(stGen, (const char **)&key, (char **)&value)) {
+        Cudd_RecursiveDeref(dd, (DdNode *)key);
+    }
+    st__free_gen(stGen); stGen = NULL;
+    st__free_table(storeTable);
+
+    for (i = 0; i <= page; i++) {
+        ABC_FREE(mintermPages[i]);
+    }
+    ABC_FREE(mintermPages);
+    for (i = 0; i <= page; i++) {
+        ABC_FREE(nodePages[i]);
+    }
+    ABC_FREE(nodePages);
+    for (i = 0; i <= page; i++) {
+        ABC_FREE(lightNodePages[i]);
+    }
+    ABC_FREE(lightNodePages);
+    for (i = 0; i <= nodeDataPage; i++) {
+        ABC_FREE(nodeDataPages[i]);
+    }
+    ABC_FREE(nodeDataPages);
+    st__free_table(visitedTable);
+    ABC_FREE(size);
+#if 0
+    (void) Cudd_DebugCheck(dd);
+    (void) Cudd_CheckKeys(dd);
+#endif
+
+    if (subset != NULL) {
+#ifdef DD_DEBUG
+      if (!Cudd_bddLeq(dd, subset, f)) {
+            fprintf(dd->err, "Wrong subset\n");
+            dd->errorCode = CUDD_INTERNAL_ERROR;
+            return(NULL);
+      }
+#endif
+        cuddDeref(subset);
+        return(subset);
+    } else {
+        return(NULL);
+    }
+} /* end of cuddSubsetHeavyBranch */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resize the number of pages allocated to store the node data.]
+
+  Description [Resize the number of pages allocated to store the node data
+  The procedure  moves the counter to the next page when the end of
+  the page is reached and allocates new pages when necessary.]
+
+  SideEffects [Changes the size of pages, page, page index, maximum
+  number of pages freeing stuff in case of memory out. ]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ResizeNodeDataPages(void)
+{
+    int i;
+    NodeData_t **newNodeDataPages;
+
+    nodeDataPage++;
+    /* If the current page index is larger than the number of pages
+     * allocated, allocate a new page array. Page numbers are incremented by
+     * INITIAL_PAGES
+     */
+    if (nodeDataPage == maxNodeDataPages) {
+        newNodeDataPages = ABC_ALLOC(NodeData_t *,maxNodeDataPages + INITIAL_PAGES);
+        if (newNodeDataPages == NULL) {
+            for (i = 0; i < nodeDataPage; i++) ABC_FREE(nodeDataPages[i]);
+            ABC_FREE(nodeDataPages);
+            memOut = 1;
+            return;
+        } else {
+            for (i = 0; i < maxNodeDataPages; i++) {
+                newNodeDataPages[i] = nodeDataPages[i];
+            }
+            /* Increase total page count */
+            maxNodeDataPages += INITIAL_PAGES;
+            ABC_FREE(nodeDataPages);
+            nodeDataPages = newNodeDataPages;
+        }
+    }
+    /* Allocate a new page */
+    currentNodeDataPage = nodeDataPages[nodeDataPage] =
+        ABC_ALLOC(NodeData_t ,nodeDataPageSize);
+    if (currentNodeDataPage == NULL) {
+        for (i = 0; i < nodeDataPage; i++) ABC_FREE(nodeDataPages[i]);
+        ABC_FREE(nodeDataPages);
+        memOut = 1;
+        return;
+    }
+    /* reset page index */
+    nodeDataPageIndex = 0;
+    return;
+
+} /* end of ResizeNodeDataPages */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resize the number of pages allocated to store the minterm
+  counts. ]
+
+  Description [Resize the number of pages allocated to store the minterm
+  counts.  The procedure  moves the counter to the next page when the
+  end of the page is reached and allocates new pages when necessary.]
+
+  SideEffects [Changes the size of minterm pages, page, page index, maximum
+  number of pages freeing stuff in case of memory out. ]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ResizeCountMintermPages(void)
+{
+    int i;
+    double **newMintermPages;
+
+    page++;
+    /* If the current page index is larger than the number of pages
+     * allocated, allocate a new page array. Page numbers are incremented by
+     * INITIAL_PAGES
+     */
+    if (page == maxPages) {
+        newMintermPages = ABC_ALLOC(double *,maxPages + INITIAL_PAGES);
+        if (newMintermPages == NULL) {
+            for (i = 0; i < page; i++) ABC_FREE(mintermPages[i]);
+            ABC_FREE(mintermPages);
+            memOut = 1;
+            return;
+        } else {
+            for (i = 0; i < maxPages; i++) {
+                newMintermPages[i] = mintermPages[i];
+            }
+            /* Increase total page count */
+            maxPages += INITIAL_PAGES;
+            ABC_FREE(mintermPages);
+            mintermPages = newMintermPages;
+        }
+    }
+    /* Allocate a new page */
+    currentMintermPage = mintermPages[page] = ABC_ALLOC(double,pageSize);
+    if (currentMintermPage == NULL) {
+        for (i = 0; i < page; i++) ABC_FREE(mintermPages[i]);
+        ABC_FREE(mintermPages);
+        memOut = 1;
+        return;
+    }
+    /* reset page index */
+    pageIndex = 0;
+    return;
+
+} /* end of ResizeCountMintermPages */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resize the number of pages allocated to store the node counts.]
+
+  Description [Resize the number of pages allocated to store the node counts.
+  The procedure  moves the counter to the next page when the end of
+  the page is reached and allocates new pages when necessary.]
+
+  SideEffects [Changes the size of pages, page, page index, maximum
+  number of pages freeing stuff in case of memory out.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ResizeCountNodePages(void)
+{
+    int i;
+    int **newNodePages;
+
+    page++;
+
+    /* If the current page index is larger than the number of pages
+     * allocated, allocate a new page array. The number of pages is incremented
+     * by INITIAL_PAGES.
+     */
+    if (page == maxPages) {
+        newNodePages = ABC_ALLOC(int *,maxPages + INITIAL_PAGES);
+        if (newNodePages == NULL) {
+            for (i = 0; i < page; i++) ABC_FREE(nodePages[i]);
+            ABC_FREE(nodePages);
+            for (i = 0; i < page; i++) ABC_FREE(lightNodePages[i]);
+            ABC_FREE(lightNodePages);
+            memOut = 1;
+            return;
+        } else {
+            for (i = 0; i < maxPages; i++) {
+                newNodePages[i] = nodePages[i];
+            }
+            ABC_FREE(nodePages);
+            nodePages = newNodePages;
+        }
+
+        newNodePages = ABC_ALLOC(int *,maxPages + INITIAL_PAGES);
+        if (newNodePages == NULL) {
+            for (i = 0; i < page; i++) ABC_FREE(nodePages[i]);
+            ABC_FREE(nodePages);
+            for (i = 0; i < page; i++) ABC_FREE(lightNodePages[i]);
+            ABC_FREE(lightNodePages);
+            memOut = 1;
+            return;
+        } else {
+            for (i = 0; i < maxPages; i++) {
+                newNodePages[i] = lightNodePages[i];
+            }
+            ABC_FREE(lightNodePages);
+            lightNodePages = newNodePages;
+        }
+        /* Increase total page count */
+        maxPages += INITIAL_PAGES;
+    }
+    /* Allocate a new page */
+    currentNodePage = nodePages[page] = ABC_ALLOC(int,pageSize);
+    if (currentNodePage == NULL) {
+        for (i = 0; i < page; i++) ABC_FREE(nodePages[i]);
+        ABC_FREE(nodePages);
+        for (i = 0; i < page; i++) ABC_FREE(lightNodePages[i]);
+        ABC_FREE(lightNodePages);
+        memOut = 1;
+        return;
+    }
+    /* Allocate a new page */
+    currentLightNodePage = lightNodePages[page] = ABC_ALLOC(int,pageSize);
+    if (currentLightNodePage == NULL) {
+        for (i = 0; i <= page; i++) ABC_FREE(nodePages[i]);
+        ABC_FREE(nodePages);
+        for (i = 0; i < page; i++) ABC_FREE(lightNodePages[i]);
+        ABC_FREE(lightNodePages);
+        memOut = 1;
+        return;
+    }
+    /* reset page index */
+    pageIndex = 0;
+    return;
+
+} /* end of ResizeCountNodePages */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively counts minterms of each node in the DAG.]
+
+  Description [Recursively counts minterms of each node in the DAG.
+  Similar to the cuddCountMintermAux which recursively counts the
+  number of minterms for the dag rooted at each node in terms of the
+  total number of variables (max). This procedure creates the node
+  data structure and stores the minterm count as part of the node
+  data structure. ]
+
+  SideEffects [Creates structures of type node quality and fills the st__table]
+
+  SeeAlso     [SubsetCountMinterm]
+
+******************************************************************************/
+static double
+SubsetCountMintermAux(
+  DdNode * node /* function to analyze */,
+  double  max /* number of minterms of constant 1 */,
+  st__table * table /* visitedTable table */)
+{
+
+    DdNode      *N,*Nv,*Nnv; /* nodes to store cofactors  */
+    double      min,*pmin; /* minterm count */
+    double      min1, min2; /* minterm count */
+    NodeData_t *dummy;
+    NodeData_t *newEntry;
+    int i;
+
+#ifdef DEBUG
+    num_calls++;
+#endif
+
+    /* Constant case */
+    if (Cudd_IsConstant(node)) {
+        if (node == zero) {
+            return(0.0);
+        } else {
+            return(max);
+        }
+    } else {
+
+        /* check if entry for this node exists */
+        if ( st__lookup(table, (const char *)node, (char **)&dummy)) {
+            min = *(dummy->mintermPointer);
+            return(min);
+        }
+
+        /* Make the node regular to extract cofactors */
+        N = Cudd_Regular(node);
+
+        /* store the cofactors */
+        Nv = Cudd_T(N);
+        Nnv = Cudd_E(N);
+
+        Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
+        Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
+
+        min1 =  SubsetCountMintermAux(Nv, max,table)/2.0;
+        if (memOut) return(0.0);
+        min2 =  SubsetCountMintermAux(Nnv,max,table)/2.0;
+        if (memOut) return(0.0);
+        min = (min1+min2);
+
+        /* if page index is at the bottom, then create a new page */
+        if (pageIndex == pageSize) ResizeCountMintermPages();
+        if (memOut) {
+            for (i = 0; i <= nodeDataPage; i++) ABC_FREE(nodeDataPages[i]);
+            ABC_FREE(nodeDataPages);
+            st__free_table(table);
+            return(0.0);
+        }
+
+        /* point to the correct location in the page */
+        pmin = currentMintermPage+pageIndex;
+        pageIndex++;
+
+        /* store the minterm count of this node in the page */
+        *pmin = min;
+
+        /* Note I allocate the struct here. Freeing taken care of later */
+        if (nodeDataPageIndex == nodeDataPageSize) ResizeNodeDataPages();
+        if (memOut) {
+            for (i = 0; i <= page; i++) ABC_FREE(mintermPages[i]);
+            ABC_FREE(mintermPages);
+            st__free_table(table);
+            return(0.0);
+        }
+
+        newEntry = currentNodeDataPage + nodeDataPageIndex;
+        nodeDataPageIndex++;
+
+        /* points to the correct location in the page */
+        newEntry->mintermPointer = pmin;
+        /* initialize this field of the Node Quality structure */
+        newEntry->nodesPointer = NULL;
+
+        /* insert entry for the node in the table */
+        if ( st__insert(table,(char *)node, (char *)newEntry) == st__OUT_OF_MEM) {
+            memOut = 1;
+            for (i = 0; i <= page; i++) ABC_FREE(mintermPages[i]);
+            ABC_FREE(mintermPages);
+            for (i = 0; i <= nodeDataPage; i++) ABC_FREE(nodeDataPages[i]);
+            ABC_FREE(nodeDataPages);
+            st__free_table(table);
+            return(0.0);
+        }
+        return(min);
+    }
+
+} /* end of SubsetCountMintermAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts minterms of each node in the DAG]
+
+  Description [Counts minterms of each node in the DAG. Similar to the
+  Cudd_CountMinterm procedure except this returns the minterm count for
+  all the nodes in the bdd in an st__table.]
+
+  SideEffects [none]
+
+  SeeAlso     [SubsetCountMintermAux]
+
+******************************************************************************/
+static st__table *
+SubsetCountMinterm(
+  DdNode * node /* function to be analyzed */,
+  int nvars /* number of variables node depends on */)
+{
+    st__table    *table;
+    int i;
+
+
+#ifdef DEBUG
+    num_calls = 0;
+#endif
+
+    max = pow(2.0,(double) nvars);
+    table = st__init_table( st__ptrcmp, st__ptrhash);
+    if (table == NULL) goto OUT_OF_MEM;
+    maxPages = INITIAL_PAGES;
+    mintermPages = ABC_ALLOC(double *,maxPages);
+    if (mintermPages == NULL) {
+        st__free_table(table);
+        goto OUT_OF_MEM;
+    }
+    page = 0;
+    currentMintermPage = ABC_ALLOC(double,pageSize);
+    mintermPages[page] = currentMintermPage;
+    if (currentMintermPage == NULL) {
+        ABC_FREE(mintermPages);
+        st__free_table(table);
+        goto OUT_OF_MEM;
+    }
+    pageIndex = 0;
+    maxNodeDataPages = INITIAL_PAGES;
+    nodeDataPages = ABC_ALLOC(NodeData_t *, maxNodeDataPages);
+    if (nodeDataPages == NULL) {
+        for (i = 0; i <= page ; i++) ABC_FREE(mintermPages[i]);
+        ABC_FREE(mintermPages);
+        st__free_table(table);
+        goto OUT_OF_MEM;
+    }
+    nodeDataPage = 0;
+    currentNodeDataPage = ABC_ALLOC(NodeData_t ,nodeDataPageSize);
+    nodeDataPages[nodeDataPage] = currentNodeDataPage;
+    if (currentNodeDataPage == NULL) {
+        for (i = 0; i <= page ; i++) ABC_FREE(mintermPages[i]);
+        ABC_FREE(mintermPages);
+        ABC_FREE(nodeDataPages);
+        st__free_table(table);
+        goto OUT_OF_MEM;
+    }
+    nodeDataPageIndex = 0;
+
+    (void) SubsetCountMintermAux(node,max,table);
+    if (memOut) goto OUT_OF_MEM;
+    return(table);
+
+OUT_OF_MEM:
+    memOut = 1;
+    return(NULL);
+
+} /* end of SubsetCountMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively counts the number of nodes under the dag.
+  Also counts the number of nodes under the lighter child of
+  this node.]
+
+  Description [Recursively counts the number of nodes under the dag.
+  Also counts the number of nodes under the lighter child of
+  this node. . Note that the same dag may be the lighter child of two
+  different nodes and have different counts. As with the minterm counts,
+  the node counts are stored in pages to be space efficient and the
+  address for these node counts are stored in an st__table associated
+  to each node. ]
+
+  SideEffects [Updates the node data table with node counts]
+
+  SeeAlso     [SubsetCountNodes]
+
+******************************************************************************/
+static int
+SubsetCountNodesAux(
+  DdNode * node /* current node */,
+  st__table * table /* table to update node count, also serves as visited table. */,
+  double  max /* maximum number of variables */)
+{
+    int tval, eval, i;
+    DdNode *N, *Nv, *Nnv;
+    double minNv, minNnv;
+    NodeData_t *dummyN, *dummyNv, *dummyNnv, *dummyNBar;
+    int *pmin, *pminBar, *val;
+
+    if ((node == NULL) || Cudd_IsConstant(node))
+        return(0);
+
+    /* if this node has been processed do nothing */
+    if ( st__lookup(table, (const char *)node, (char **)&dummyN) == 1) {
+        val = dummyN->nodesPointer;
+        if (val != NULL)
+            return(0);
+    } else {
+        return(0);
+    }
+
+    N  = Cudd_Regular(node);
+    Nv = Cudd_T(N);
+    Nnv = Cudd_E(N);
+
+    Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
+    Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
+
+    /* find the minterm counts for the THEN and ELSE branches */
+    if (Cudd_IsConstant(Nv)) {
+        if (Nv == zero) {
+            minNv = 0.0;
+        } else {
+            minNv = max;
+        }
+    } else {
+        if ( st__lookup(table, (const char *)Nv, (char **)&dummyNv) == 1)
+            minNv = *(dummyNv->mintermPointer);
+        else {
+            return(0);
+        }
+    }
+    if (Cudd_IsConstant(Nnv)) {
+        if (Nnv == zero) {
+            minNnv = 0.0;
+        } else {
+            minNnv = max;
+        }
+    } else {
+        if ( st__lookup(table, (const char *)Nnv, (char **)&dummyNnv) == 1) {
+            minNnv = *(dummyNnv->mintermPointer);
+        }
+        else {
+            return(0);
+        }
+    }
+
+
+    /* recur based on which has larger minterm, */
+    if (minNv >= minNnv) {
+        tval = SubsetCountNodesAux(Nv, table, max);
+        if (memOut) return(0);
+        eval = SubsetCountNodesAux(Nnv, table, max);
+        if (memOut) return(0);
+
+        /* store the node count of the lighter child. */
+        if (pageIndex == pageSize) ResizeCountNodePages();
+        if (memOut) {
+            for (i = 0; i <= page; i++) ABC_FREE(mintermPages[i]);
+            ABC_FREE(mintermPages);
+            for (i = 0; i <= nodeDataPage; i++) ABC_FREE(nodeDataPages[i]);
+            ABC_FREE(nodeDataPages);
+            st__free_table(table);
+            return(0);
+        }
+        pmin = currentLightNodePage + pageIndex;
+        *pmin = eval; /* Here the ELSE child is lighter */
+        dummyN->lightChildNodesPointer = pmin;
+
+    } else {
+        eval = SubsetCountNodesAux(Nnv, table, max);
+        if (memOut) return(0);
+        tval = SubsetCountNodesAux(Nv, table, max);
+        if (memOut) return(0);
+
+        /* store the node count of the lighter child. */
+        if (pageIndex == pageSize) ResizeCountNodePages();
+        if (memOut) {
+            for (i = 0; i <= page; i++) ABC_FREE(mintermPages[i]);
+            ABC_FREE(mintermPages);
+            for (i = 0; i <= nodeDataPage; i++) ABC_FREE(nodeDataPages[i]);
+            ABC_FREE(nodeDataPages);
+            st__free_table(table);
+            return(0);
+        }
+        pmin = currentLightNodePage + pageIndex;
+        *pmin = tval; /* Here the THEN child is lighter */
+        dummyN->lightChildNodesPointer = pmin;
+
+    }
+    /* updating the page index for node count storage. */
+    pmin = currentNodePage + pageIndex;
+    *pmin = tval + eval + 1;
+    dummyN->nodesPointer = pmin;
+
+    /* pageIndex is parallel page index for count_nodes and count_lightNodes */
+    pageIndex++;
+
+    /* if this node has been reached first, it belongs to a heavier
+       branch. Its complement will be reached later on a lighter branch.
+       Hence the complement has zero node count. */
+
+    if ( st__lookup(table, (const char *)Cudd_Not(node), (char **)&dummyNBar) == 1)  {
+        if (pageIndex == pageSize) ResizeCountNodePages();
+        if (memOut) {
+            for (i = 0; i < page; i++) ABC_FREE(mintermPages[i]);
+            ABC_FREE(mintermPages);
+            for (i = 0; i < nodeDataPage; i++) ABC_FREE(nodeDataPages[i]);
+            ABC_FREE(nodeDataPages);
+            st__free_table(table);
+            return(0);
+        }
+        pminBar = currentLightNodePage + pageIndex;
+        *pminBar = 0;
+        dummyNBar->lightChildNodesPointer = pminBar;
+        /* The lighter child has less nodes than the parent.
+         * So if parent 0 then lighter child zero
+         */
+        if (pageIndex == pageSize) ResizeCountNodePages();
+        if (memOut) {
+            for (i = 0; i < page; i++) ABC_FREE(mintermPages[i]);
+            ABC_FREE(mintermPages);
+            for (i = 0; i < nodeDataPage; i++) ABC_FREE(nodeDataPages[i]);
+            ABC_FREE(nodeDataPages);
+            st__free_table(table);
+            return(0);
+        }
+        pminBar = currentNodePage + pageIndex;
+        *pminBar = 0;
+        dummyNBar->nodesPointer = pminBar ; /* maybe should point to zero */
+
+        pageIndex++;
+    }
+    return(*pmin);
+} /*end of SubsetCountNodesAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the nodes under the current node and its lighter child]
+
+  Description [Counts the nodes under the current node and its lighter
+  child. Calls a recursive procedure to count the number of nodes of
+  a DAG rooted at a particular node and the number of nodes taken by its
+  lighter child.]
+
+  SideEffects [None]
+
+  SeeAlso     [SubsetCountNodesAux]
+
+******************************************************************************/
+static int
+SubsetCountNodes(
+  DdNode * node /* function to be analyzed */,
+  st__table * table /* node quality table */,
+  int  nvars /* number of variables node depends on */)
+{
+    int num;
+    int i;
+
+#ifdef DEBUG
+    num_calls = 0;
+#endif
+
+    max = pow(2.0,(double) nvars);
+    maxPages = INITIAL_PAGES;
+    nodePages = ABC_ALLOC(int *,maxPages);
+    if (nodePages == NULL)  {
+        goto OUT_OF_MEM;
+    }
+
+    lightNodePages = ABC_ALLOC(int *,maxPages);
+    if (lightNodePages == NULL) {
+        for (i = 0; i <= page; i++) ABC_FREE(mintermPages[i]);
+        ABC_FREE(mintermPages);
+        for (i = 0; i <= nodeDataPage; i++) ABC_FREE(nodeDataPages[i]);
+        ABC_FREE(nodeDataPages);
+        ABC_FREE(nodePages);
+        goto OUT_OF_MEM;
+    }
+
+    page = 0;
+    currentNodePage = nodePages[page] = ABC_ALLOC(int,pageSize);
+    if (currentNodePage == NULL) {
+        for (i = 0; i <= page; i++) ABC_FREE(mintermPages[i]);
+        ABC_FREE(mintermPages);
+        for (i = 0; i <= nodeDataPage; i++) ABC_FREE(nodeDataPages[i]);
+        ABC_FREE(nodeDataPages);
+        ABC_FREE(lightNodePages);
+        ABC_FREE(nodePages);
+        goto OUT_OF_MEM;
+    }
+
+    currentLightNodePage = lightNodePages[page] = ABC_ALLOC(int,pageSize);
+    if (currentLightNodePage == NULL) {
+        for (i = 0; i <= page; i++) ABC_FREE(mintermPages[i]);
+        ABC_FREE(mintermPages);
+        for (i = 0; i <= nodeDataPage; i++) ABC_FREE(nodeDataPages[i]);
+        ABC_FREE(nodeDataPages);
+        ABC_FREE(currentNodePage);
+        ABC_FREE(lightNodePages);
+        ABC_FREE(nodePages);
+        goto OUT_OF_MEM;
+    }
+
+    pageIndex = 0;
+    num = SubsetCountNodesAux(node,table,max);
+    if (memOut) goto OUT_OF_MEM;
+    return(num);
+
+OUT_OF_MEM:
+    memOut = 1;
+    return(0);
+
+} /* end of SubsetCountNodes */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Procedure to recursively store nodes that are retained in the subset.]
+
+  Description [rocedure to recursively store nodes that are retained in the subset.]
+
+  SideEffects [None]
+
+  SeeAlso     [StoreNodes]
+
+******************************************************************************/
+static void
+StoreNodes(
+  st__table * storeTable,
+  DdManager * dd,
+  DdNode * node)
+{
+    DdNode *N, *Nt, *Ne;
+    if (Cudd_IsConstant(dd)) {
+        return;
+    }
+    N = Cudd_Regular(node);
+    if ( st__lookup(storeTable, (char *)N, NIL(char *))) {
+        return;
+    }
+    cuddRef(N);
+    if ( st__insert(storeTable, (char *)N, NIL(char)) == st__OUT_OF_MEM) {
+        fprintf(dd->err,"Something wrong, st__table insert failed\n");
+    }
+
+    Nt = Cudd_T(N);
+    Ne = Cudd_E(N);
+
+    StoreNodes(storeTable, dd, Nt);
+    StoreNodes(storeTable, dd, Ne);
+    return;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the subset BDD using the heavy branch method.]
+
+  Description [The procedure carries out the building of the subset BDD
+  starting at the root. Using the three different counts labelling each node,
+  the procedure chooses the heavier branch starting from the root and keeps
+  track of the number of nodes it discards at each step, thus keeping count
+  of the size of the subset BDD dynamically. Once the threshold is satisfied,
+  the procedure then calls ITE to build the BDD.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+BuildSubsetBdd(
+  DdManager * dd /* DD manager */,
+  DdNode * node /* current node */,
+  int * size /* current size of the subset */,
+  st__table * visitedTable /* visited table storing all node data */,
+  int  threshold,
+  st__table * storeTable,
+  st__table * approxTable)
+{
+
+    DdNode *Nv, *Nnv, *N, *topv, *neW;
+    double minNv, minNnv;
+    NodeData_t *currNodeQual;
+    NodeData_t *currNodeQualT;
+    NodeData_t *currNodeQualE;
+    DdNode *ThenBranch, *ElseBranch;
+    unsigned int topid;
+    char *dummy;
+
+#ifdef DEBUG
+    num_calls++;
+#endif
+    /*If the size of the subset is below the threshold, dont do
+      anything. */
+    if ((*size) <= threshold) {
+      /* store nodes below this, so we can recombine if possible */
+      StoreNodes(storeTable, dd, node);
+      return(node);
+    }
+
+    if (Cudd_IsConstant(node))
+        return(node);
+
+    /* Look up minterm count for this node. */
+    if (! st__lookup(visitedTable, (const char *)node, (char **)&currNodeQual)) {
+        fprintf(dd->err,
+                "Something is wrong, ought to be in node quality table\n");
+    }
+
+    /* Get children. */
+    N = Cudd_Regular(node);
+    Nv = Cudd_T(N);
+    Nnv = Cudd_E(N);
+
+    /* complement if necessary */
+    Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
+    Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
+
+    if (!Cudd_IsConstant(Nv)) {
+        /* find out minterms and nodes contributed by then child */
+        if (! st__lookup(visitedTable, (const char *)Nv, (char **)&currNodeQualT)) {
+                fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n");
+                dd->errorCode = CUDD_INTERNAL_ERROR;
+                return(NULL);
+            }
+        else {
+            minNv = *(((NodeData_t *)currNodeQualT)->mintermPointer);
+        }
+    } else {
+        if (Nv == zero) {
+            minNv = 0;
+        } else  {
+            minNv = max;
+        }
+    }
+    if (!Cudd_IsConstant(Nnv)) {
+        /* find out minterms and nodes contributed by else child */
+        if (! st__lookup(visitedTable, (const char *)Nnv, (char **)&currNodeQualE)) {
+            fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n");
+            dd->errorCode = CUDD_INTERNAL_ERROR;
+            return(NULL);
+        } else {
+            minNnv = *(((NodeData_t *)currNodeQualE)->mintermPointer);
+        }
+    } else {
+        if (Nnv == zero) {
+            minNnv = 0;
+        } else {
+            minNnv = max;
+        }
+    }
+
+    /* keep track of size of subset by subtracting the number of
+     * differential nodes contributed by lighter child
+     */
+    *size = (*(size)) - (int)*(currNodeQual->lightChildNodesPointer);
+    if (minNv >= minNnv) { /*SubsetCountNodesAux procedure takes
+                             the Then branch in case of a tie */
+
+        /* recur with the Then branch */
+        ThenBranch = (DdNode *)BuildSubsetBdd(dd, Nv, size,
+              visitedTable, threshold, storeTable, approxTable);
+        if (ThenBranch == NULL) {
+            return(NULL);
+        }
+        cuddRef(ThenBranch);
+        /* The Else branch is either a node that already exists in the
+         * subset, or one whose approximation has been computed, or
+         * Zero.
+         */
+        if ( st__lookup(storeTable, (char *)Cudd_Regular(Nnv), &dummy)) {
+          ElseBranch = Nnv;
+          cuddRef(ElseBranch);
+        } else {
+          if ( st__lookup(approxTable, (char *)Nnv, &dummy)) {
+            ElseBranch = (DdNode *)dummy;
+            cuddRef(ElseBranch);
+          } else {
+            ElseBranch = zero;
+            cuddRef(ElseBranch);
+          }
+        }
+
+    }
+    else {
+        /* recur with the Else branch */
+        ElseBranch = (DdNode *)BuildSubsetBdd(dd, Nnv, size,
+                      visitedTable, threshold, storeTable, approxTable);
+        if (ElseBranch == NULL) {
+            return(NULL);
+        }
+        cuddRef(ElseBranch);
+        /* The Then branch is either a node that already exists in the
+         * subset, or one whose approximation has been computed, or
+         * Zero.
+         */
+        if ( st__lookup(storeTable, (char *)Cudd_Regular(Nv), &dummy)) {
+          ThenBranch = Nv;
+          cuddRef(ThenBranch);
+        } else {
+          if ( st__lookup(approxTable, (char *)Nv, &dummy)) {
+            ThenBranch = (DdNode *)dummy;
+            cuddRef(ThenBranch);
+          } else {
+            ThenBranch = zero;
+            cuddRef(ThenBranch);
+          }
+        }
+    }
+
+    /* construct the Bdd with the top variable and the two children */
+    topid = Cudd_NodeReadIndex(N);
+    topv = Cudd_ReadVars(dd, topid);
+    cuddRef(topv);
+    neW =  cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch);
+    if (neW != NULL) {
+      cuddRef(neW);
+    }
+    Cudd_RecursiveDeref(dd, topv);
+    Cudd_RecursiveDeref(dd, ThenBranch);
+    Cudd_RecursiveDeref(dd, ElseBranch);
+
+
+    if (neW == NULL)
+        return(NULL);
+    else {
+        /* store this node in the store table */
+        if (! st__lookup(storeTable, (char *)Cudd_Regular(neW), &dummy)) {
+          cuddRef(neW);
+          if (! st__insert(storeTable, (char *)Cudd_Regular(neW), NIL(char)))
+              return (NULL);
+        }
+        /* store the approximation for this node */
+        if (N !=  Cudd_Regular(neW)) {
+            if ( st__lookup(approxTable, (char *)node, &dummy)) {
+                fprintf(dd->err, "This node should not be in the approximated table\n");
+            } else {
+                cuddRef(neW);
+                if (! st__insert(approxTable, (char *)node, (char *)neW))
+                    return(NULL);
+            }
+        }
+        cuddDeref(neW);
+        return(neW);
+    }
+} /* end of BuildSubsetBdd */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddSubsetSP.c b/abc-build/src/bdd/cudd/cuddSubsetSP.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddSubsetSP.c
@@ -0,0 +1,1665 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddSubsetSP.c]
+
+  PackageName [cudd]
+
+  Synopsis [Procedure to subset the given BDD choosing the shortest paths
+            (largest cubes) in the BDD.]
+
+
+  Description  [External procedures included in this module:
+                <ul>
+                <li> Cudd_SubsetShortPaths()
+                <li> Cudd_SupersetShortPaths()
+                </ul>
+                Internal procedures included in this module:
+                <ul>
+                <li> cuddSubsetShortPaths()
+                </ul>
+                Static procedures included in this module:
+                <ul>
+                <li> BuildSubsetBdd()
+                <li> CreatePathTable()
+                <li> AssessPathLength()
+                <li> CreateTopDist()
+                <li> CreateBotDist()
+                <li> ResizeNodeDistPages()
+                <li> ResizeQueuePages()
+                <li> stPathTableDdFree()
+                </ul>
+                ]
+
+  SeeAlso     [cuddSubsetHB.c]
+
+  Author      [Kavita Ravi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DEFAULT_PAGE_SIZE 2048 /* page size to store the BFS queue element type */
+#define DEFAULT_NODE_DIST_PAGE_SIZE 2048 /*  page sizesto store NodeDist_t type */
+#define MAXSHORTINT     ((DdHalfWord) ~0) /* constant defined to store
+                                           * maximum distance of a node
+                                           * from the root or the
+                                           * constant
+                                           */
+#define INITIAL_PAGES 128 /* number of initial pages for the
+                           * queue/NodeDist_t type */
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* structure created to store subset results for each node and distances with
+ * odd and even parity of the node from the root and sink. Main data structure
+ * in this procedure.
+ */
+struct NodeDist{
+    DdHalfWord oddTopDist;
+    DdHalfWord evenTopDist;
+    DdHalfWord oddBotDist;
+    DdHalfWord evenBotDist;
+    DdNode *regResult;
+    DdNode *compResult;
+};
+
+/* assorted information needed by the BuildSubsetBdd procedure. */
+struct AssortedInfo {
+    unsigned int maxpath;
+    int findShortestPath;
+    int thresholdReached;
+    st__table *maxpathTable;
+    int threshold;
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct NodeDist NodeDist_t;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddSubsetSP.c,v 1.34 2009/02/19 16:23:19 fabio Exp $";
+#endif
+
+#ifdef DD_DEBUG
+static int numCalls;
+static int hits;
+static int thishit;
+#endif
+
+
+static  int             memOut; /* flag to indicate out of memory */
+static  DdNode          *zero, *one; /* constant functions */
+
+static  NodeDist_t      **nodeDistPages; /* pointers to the pages */
+static  int             nodeDistPageIndex; /* index to next element */
+static  int             nodeDistPage; /* index to current page */
+static  int             nodeDistPageSize = DEFAULT_NODE_DIST_PAGE_SIZE; /* page size */
+static  int             maxNodeDistPages; /* number of page pointers */
+static  NodeDist_t      *currentNodeDistPage; /* current page */
+
+static  DdNode          ***queuePages; /* pointers to the pages */
+static  int             queuePageIndex; /* index to next element */
+static  int             queuePage; /* index to current page */
+static  int             queuePageSize = DEFAULT_PAGE_SIZE; /* page size */
+static  int             maxQueuePages; /* number of page pointers */
+static  DdNode          **currentQueuePage; /* current page */
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void ResizeNodeDistPages (void);
+static void ResizeQueuePages (void);
+static void CreateTopDist ( st__table *pathTable, int parentPage, int parentQueueIndex, int topLen, DdNode **childPage, int childQueueIndex, int numParents, FILE *fp);
+static int CreateBotDist (DdNode *node, st__table *pathTable, unsigned int *pathLengthArray, FILE *fp);
+static st__table * CreatePathTable (DdNode *node, unsigned int *pathLengthArray, FILE *fp);
+static unsigned int AssessPathLength (unsigned int *pathLengthArray, int threshold, int numVars, unsigned int *excess, FILE *fp);
+static DdNode * BuildSubsetBdd (DdManager *dd, st__table *pathTable, DdNode *node, struct AssortedInfo *info, st__table *subsetNodeTable);
+static enum st__retval stPathTableDdFree (char *key, char *value, char *arg);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of Exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts a dense subset from a BDD with the shortest paths
+  heuristic.]
+
+  Description [Extracts a dense subset from a BDD.  This procedure
+  tries to preserve the shortest paths of the input BDD, because they
+  give many minterms and contribute few nodes.  This procedure may
+  increase the number of nodes in trying to create the subset or
+  reduce the number of nodes due to recombination as compared to the
+  original BDD. Hence the threshold may not be strictly adhered to. In
+  practice, recombination overshadows the increase in the number of
+  nodes and results in small BDDs as compared to the threshold. The
+  hardlimit specifies whether threshold needs to be strictly adhered
+  to. If it is set to 1, the procedure ensures that result is never
+  larger than the specified limit but may be considerably less than
+  the threshold.  Returns a pointer to the BDD for the subset if
+  successful; NULL otherwise.  The value for numVars should be as
+  close as possible to the size of the support of f for better
+  efficiency. However, it is safe to pass the value returned by
+  Cudd_ReadSize for numVars. If 0 is passed, then the value returned
+  by Cudd_ReadSize is used.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SupersetShortPaths Cudd_SubsetHeavyBranch Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_SubsetShortPaths(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be subset */,
+  int  numVars /* number of variables in the support of f */,
+  int  threshold /* maximum number of nodes in the subset */,
+  int  hardlimit /* flag: 1 if threshold is a hard limit */)
+{
+    DdNode *subset;
+
+    memOut = 0;
+    do {
+        dd->reordered = 0;
+        subset = cuddSubsetShortPaths(dd, f, numVars, threshold, hardlimit);
+    } while((dd->reordered ==1) && (!memOut));
+
+    return(subset);
+
+} /* end of Cudd_SubsetShortPaths */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts a dense superset from a BDD with the shortest paths
+  heuristic.]
+
+  Description [Extracts a dense superset from a BDD.  The procedure is
+  identical to the subset procedure except for the fact that it
+  receives the complement of the given function. Extracting the subset
+  of the complement function is equivalent to extracting the superset
+  of the function.  This procedure tries to preserve the shortest
+  paths of the complement BDD, because they give many minterms and
+  contribute few nodes.  This procedure may increase the number of
+  nodes in trying to create the superset or reduce the number of nodes
+  due to recombination as compared to the original BDD. Hence the
+  threshold may not be strictly adhered to. In practice, recombination
+  overshadows the increase in the number of nodes and results in small
+  BDDs as compared to the threshold.  The hardlimit specifies whether
+  threshold needs to be strictly adhered to. If it is set to 1, the
+  procedure ensures that result is never larger than the specified
+  limit but may be considerably less than the threshold. Returns a
+  pointer to the BDD for the superset if successful; NULL
+  otherwise. The value for numVars should be as close as possible to
+  the size of the support of f for better efficiency.  However, it is
+  safe to pass the value returned by Cudd_ReadSize for numVar.  If 0
+  is passed, then the value returned by Cudd_ReadSize is used.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetShortPaths Cudd_SupersetHeavyBranch Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_SupersetShortPaths(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be superset */,
+  int  numVars /* number of variables in the support of f */,
+  int  threshold /* maximum number of nodes in the subset */,
+  int  hardlimit /* flag: 1 if threshold is a hard limit */)
+{
+    DdNode *subset, *g;
+
+    g = Cudd_Not(f);
+    memOut = 0;
+    do {
+        dd->reordered = 0;
+        subset = cuddSubsetShortPaths(dd, g, numVars, threshold, hardlimit);
+    } while((dd->reordered ==1) && (!memOut));
+
+    return(Cudd_NotCond(subset, (subset != NULL)));
+
+} /* end of Cudd_SupersetShortPaths */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [The outermost procedure to return a subset of the given BDD
+  with the shortest path lengths.]
+
+  Description [The outermost procedure to return a subset of the given
+  BDD with the largest cubes. The path lengths are calculated, the maximum
+  allowable path length is determined and the number of nodes of this
+  path length that can be used to build a subset. If the threshold is
+  larger than the size of the original BDD, the original BDD is
+  returned. ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetShortPaths]
+
+******************************************************************************/
+DdNode *
+cuddSubsetShortPaths(
+  DdManager * dd /* DD manager */,
+  DdNode * f /* function to be subset */,
+  int  numVars /* total number of variables in consideration */,
+  int  threshold /* maximum number of nodes allowed in the subset */,
+  int  hardlimit /* flag determining whether thershold should be respected strictly */)
+{
+    st__table *pathTable;
+    DdNode *N, *subset;
+
+    unsigned int  *pathLengthArray;
+    unsigned int maxpath, oddLen, evenLen, pathLength, *excess;
+    int i;
+    NodeDist_t  *nodeStat;
+    struct AssortedInfo *info;
+    st__table *subsetNodeTable;
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    if (numVars == 0) {
+      /* set default value */
+      numVars = Cudd_ReadSize(dd);
+    }
+
+    if (threshold > numVars) {
+        threshold = threshold - numVars;
+    }
+    if (f == NULL) {
+        fprintf(dd->err, "Cannot partition, nil object\n");
+        dd->errorCode = CUDD_INVALID_ARG;
+        return(NULL);
+    }
+    if (Cudd_IsConstant(f))
+        return (f);
+
+    pathLengthArray = ABC_ALLOC(unsigned int, numVars+1);
+    for (i = 0; i < numVars+1; i++) pathLengthArray[i] = 0;
+
+
+#ifdef DD_DEBUG
+    numCalls = 0;
+#endif
+
+    pathTable = CreatePathTable(f, pathLengthArray, dd->err);
+
+    if ((pathTable == NULL) || (memOut)) {
+        if (pathTable != NULL)
+            st__free_table(pathTable);
+        ABC_FREE(pathLengthArray);
+        return (NIL(DdNode));
+    }
+
+    excess = ABC_ALLOC(unsigned int, 1);
+    *excess = 0;
+    maxpath = AssessPathLength(pathLengthArray, threshold, numVars, excess,
+                               dd->err);
+
+    if (maxpath != (unsigned) (numVars + 1)) {
+
+        info = ABC_ALLOC(struct AssortedInfo, 1);
+        info->maxpath = maxpath;
+        info->findShortestPath = 0;
+        info->thresholdReached = *excess;
+        info->maxpathTable = st__init_table( st__ptrcmp, st__ptrhash);
+        info->threshold = threshold;
+
+#ifdef DD_DEBUG
+        (void) fprintf(dd->out, "Path length array\n");
+        for (i = 0; i < (numVars+1); i++) {
+            if (pathLengthArray[i])
+                (void) fprintf(dd->out, "%d ",i);
+        }
+        (void) fprintf(dd->out, "\n");
+        for (i = 0; i < (numVars+1); i++) {
+            if (pathLengthArray[i])
+                (void) fprintf(dd->out, "%d ",pathLengthArray[i]);
+        }
+        (void) fprintf(dd->out, "\n");
+        (void) fprintf(dd->out, "Maxpath  = %d, Thresholdreached = %d\n",
+                       maxpath, info->thresholdReached);
+#endif
+
+        N = Cudd_Regular(f);
+        if (! st__lookup(pathTable, (const char *)N, (char **)&nodeStat)) {
+            fprintf(dd->err, "Something wrong, root node must be in table\n");
+            dd->errorCode = CUDD_INTERNAL_ERROR;
+            ABC_FREE(excess);
+            ABC_FREE(info);
+            return(NULL);
+        } else {
+            if ((nodeStat->oddTopDist != MAXSHORTINT) &&
+                (nodeStat->oddBotDist != MAXSHORTINT))
+                oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist);
+            else
+                oddLen = MAXSHORTINT;
+
+            if ((nodeStat->evenTopDist != MAXSHORTINT) &&
+                (nodeStat->evenBotDist != MAXSHORTINT))
+                evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist);
+            else
+                evenLen = MAXSHORTINT;
+
+            pathLength = (oddLen <= evenLen) ? oddLen : evenLen;
+            if (pathLength > maxpath) {
+                (void) fprintf(dd->err, "All computations are bogus, since root has path length greater than max path length within threshold %u, %u\n", maxpath, pathLength);
+                dd->errorCode = CUDD_INTERNAL_ERROR;
+                return(NULL);
+            }
+        }
+
+#ifdef DD_DEBUG
+        numCalls = 0;
+        hits = 0;
+        thishit = 0;
+#endif
+        /* initialize a table to store computed nodes */
+        if (hardlimit) {
+            subsetNodeTable = st__init_table( st__ptrcmp, st__ptrhash);
+        } else {
+            subsetNodeTable = NIL( st__table);
+        }
+        subset = BuildSubsetBdd(dd, pathTable, f, info, subsetNodeTable);
+        if (subset != NULL) {
+            cuddRef(subset);
+        }
+        /* record the number of times a computed result for a node is hit */
+
+#ifdef DD_DEBUG
+        (void) fprintf(dd->out, "Hits = %d, New==Node = %d, NumCalls = %d\n",
+                hits, thishit, numCalls);
+#endif
+
+        if (subsetNodeTable != NIL( st__table)) {
+            st__free_table(subsetNodeTable);
+        }
+        st__free_table(info->maxpathTable);
+        st__foreach(pathTable, stPathTableDdFree, (char *)dd);
+
+        ABC_FREE(info);
+
+    } else {/* if threshold larger than size of dd */
+        subset = f;
+        cuddRef(subset);
+    }
+    ABC_FREE(excess);
+    st__free_table(pathTable);
+    ABC_FREE(pathLengthArray);
+    for (i = 0; i <= nodeDistPage; i++) ABC_FREE(nodeDistPages[i]);
+    ABC_FREE(nodeDistPages);
+
+#ifdef DD_DEBUG
+    /* check containment of subset in f */
+    if (subset != NULL) {
+        DdNode *check;
+        check = Cudd_bddIteConstant(dd, subset, f, one);
+        if (check != one) {
+            (void) fprintf(dd->err, "Wrong partition\n");
+            dd->errorCode = CUDD_INTERNAL_ERROR;
+            return(NULL);
+        }
+    }
+#endif
+
+    if (subset != NULL) {
+        cuddDeref(subset);
+        return(subset);
+    } else {
+        return(NULL);
+    }
+
+} /* end of cuddSubsetShortPaths */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resize the number of pages allocated to store the distances
+  related to each node.]
+
+  Description [Resize the number of pages allocated to store the distances
+  related to each node. The procedure  moves the counter to the
+  next page when the end of the page is reached and allocates new
+  pages when necessary. ]
+
+  SideEffects [Changes the size of  pages, page, page index, maximum
+  number of pages freeing stuff in case of memory out. ]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ResizeNodeDistPages(void)
+{
+    int i;
+    NodeDist_t **newNodeDistPages;
+
+    /* move to next page */
+    nodeDistPage++;
+
+    /* If the current page index is larger than the number of pages
+     * allocated, allocate a new page array. Page numbers are incremented by
+     * INITIAL_PAGES
+     */
+    if (nodeDistPage == maxNodeDistPages) {
+        newNodeDistPages = ABC_ALLOC(NodeDist_t *,maxNodeDistPages + INITIAL_PAGES);
+        if (newNodeDistPages == NULL) {
+            for (i = 0; i < nodeDistPage; i++) ABC_FREE(nodeDistPages[i]);
+            ABC_FREE(nodeDistPages);
+            memOut = 1;
+            return;
+        } else {
+            for (i = 0; i < maxNodeDistPages; i++) {
+                newNodeDistPages[i] = nodeDistPages[i];
+            }
+            /* Increase total page count */
+            maxNodeDistPages += INITIAL_PAGES;
+            ABC_FREE(nodeDistPages);
+            nodeDistPages = newNodeDistPages;
+        }
+    }
+    /* Allocate a new page */
+    currentNodeDistPage = nodeDistPages[nodeDistPage] = ABC_ALLOC(NodeDist_t,
+                                                              nodeDistPageSize);
+    if (currentNodeDistPage == NULL) {
+        for (i = 0; i < nodeDistPage; i++) ABC_FREE(nodeDistPages[i]);
+        ABC_FREE(nodeDistPages);
+        memOut = 1;
+        return;
+    }
+    /* reset page index */
+    nodeDistPageIndex = 0;
+    return;
+
+} /* end of ResizeNodeDistPages */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resize the number of pages allocated to store nodes in the BFS
+  traversal of the Bdd  .]
+
+  Description [Resize the number of pages allocated to store nodes in the BFS
+  traversal of the Bdd. The procedure  moves the counter to the
+  next page when the end of the page is reached and allocates new
+  pages when necessary.]
+
+  SideEffects [Changes the size of pages, page, page index, maximum
+  number of pages freeing stuff in case of memory out. ]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ResizeQueuePages(void)
+{
+    int i;
+    DdNode ***newQueuePages;
+
+    queuePage++;
+    /* If the current page index is larger than the number of pages
+     * allocated, allocate a new page array. Page numbers are incremented by
+     * INITIAL_PAGES
+     */
+    if (queuePage == maxQueuePages) {
+        newQueuePages = ABC_ALLOC(DdNode **,maxQueuePages + INITIAL_PAGES);
+        if (newQueuePages == NULL) {
+            for (i = 0; i < queuePage; i++) ABC_FREE(queuePages[i]);
+            ABC_FREE(queuePages);
+            memOut = 1;
+            return;
+        } else {
+            for (i = 0; i < maxQueuePages; i++) {
+                newQueuePages[i] = queuePages[i];
+            }
+            /* Increase total page count */
+            maxQueuePages += INITIAL_PAGES;
+            ABC_FREE(queuePages);
+            queuePages = newQueuePages;
+        }
+    }
+    /* Allocate a new page */
+    currentQueuePage = queuePages[queuePage] = ABC_ALLOC(DdNode *,queuePageSize);
+    if (currentQueuePage == NULL) {
+        for (i = 0; i < queuePage; i++) ABC_FREE(queuePages[i]);
+        ABC_FREE(queuePages);
+        memOut = 1;
+        return;
+    }
+    /* reset page index */
+    queuePageIndex = 0;
+    return;
+
+} /* end of ResizeQueuePages */
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Labels each node with its shortest distance from the root]
+
+  Description [ Labels each node with its shortest distance from the root.
+  This is done in a BFS search of the BDD. The nodes are processed
+  in a queue implemented as pages(array) to reduce memory fragmentation.
+  An entry is created for each node visited. The distance from the root
+  to the node with the corresponding  parity is updated. The procedure
+  is called recursively each recusion level handling nodes at a given
+  level from the root.]
+
+
+  SideEffects [Creates entries in the pathTable]
+
+  SeeAlso     [CreatePathTable CreateBotDist]
+
+******************************************************************************/
+static void
+CreateTopDist(
+  st__table * pathTable /* hast table to store path lengths */,
+  int  parentPage /* the pointer to the page on which the first parent in the queue is to be found. */,
+  int  parentQueueIndex /* pointer to the first parent on the page */,
+  int  topLen /* current distance from the root */,
+  DdNode ** childPage /* pointer to the page on which the first child is to be added. */,
+  int  childQueueIndex /* pointer to the first child */,
+  int  numParents /* number of parents to process in this recursive call */,
+  FILE *fp /* where to write messages */)
+{
+    NodeDist_t *nodeStat;
+    DdNode *N, *Nv, *Nnv, *node, *child, *regChild;
+    int  i;
+    int processingDone, childrenCount;
+
+#ifdef DD_DEBUG
+    numCalls++;
+
+    /* assume this procedure comes in with only the root node*/
+    /* set queue index to the next available entry for addition */
+    /* set queue page to page of addition */
+    if ((queuePages[parentPage] == childPage) && (parentQueueIndex ==
+                                                  childQueueIndex)) {
+        fprintf(fp, "Should not happen that they are equal\n");
+    }
+    assert(queuePageIndex == childQueueIndex);
+    assert(currentQueuePage == childPage);
+#endif
+    /* number children added to queue is initialized , needed for
+     * numParents in the next call
+     */
+    childrenCount = 0;
+    /* process all the nodes in this level */
+    while (numParents) {
+        numParents--;
+        if (parentQueueIndex == queuePageSize) {
+            parentPage++;
+            parentQueueIndex = 0;
+        }
+        /* a parent to process */
+        node = *(queuePages[parentPage] + parentQueueIndex);
+        parentQueueIndex++;
+        /* get its children */
+        N = Cudd_Regular(node);
+        Nv = Cudd_T(N);
+        Nnv = Cudd_E(N);
+
+        Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
+        Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
+
+        processingDone = 2;
+        while (processingDone) {
+            /* processing the THEN and the ELSE children, the THEN
+             * child first
+             */
+            if (processingDone == 2) {
+                child = Nv;
+            } else {
+                child = Nnv;
+            }
+
+            regChild = Cudd_Regular(child);
+            /* dont process if the child is a constant */
+            if (!Cudd_IsConstant(child)) {
+                /* check is already visited, if not add a new entry in
+                 * the path Table
+                 */
+                if (! st__lookup(pathTable, (const char *)regChild, (char **)&nodeStat)) {
+                    /* if not in table, has never been visited */
+                    /* create entry for table */
+                    if (nodeDistPageIndex == nodeDistPageSize)
+                        ResizeNodeDistPages();
+                    if (memOut) {
+                        for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]);
+                        ABC_FREE(queuePages);
+                        st__free_table(pathTable);
+                        return;
+                    }
+                    /* New entry for child in path Table is created here */
+                    nodeStat = currentNodeDistPage + nodeDistPageIndex;
+                    nodeDistPageIndex++;
+
+                    /* Initialize fields of the node data */
+                    nodeStat->oddTopDist = MAXSHORTINT;
+                    nodeStat->evenTopDist = MAXSHORTINT;
+                    nodeStat->evenBotDist = MAXSHORTINT;
+                    nodeStat->oddBotDist = MAXSHORTINT;
+                    nodeStat->regResult = NULL;
+                    nodeStat->compResult = NULL;
+                    /* update the table entry element, the distance keeps
+                     * track of the parity of the path from the root
+                     */
+                    if (Cudd_IsComplement(child)) {
+                        nodeStat->oddTopDist = (DdHalfWord) topLen + 1;
+                    } else {
+                        nodeStat->evenTopDist = (DdHalfWord) topLen + 1;
+                    }
+
+                    /* insert entry element for  child in the table */
+                    if ( st__insert(pathTable, (char *)regChild,
+                                  (char *)nodeStat) == st__OUT_OF_MEM) {
+                        memOut = 1;
+                        for (i = 0; i <= nodeDistPage; i++)
+                            ABC_FREE(nodeDistPages[i]);
+                        ABC_FREE(nodeDistPages);
+                        for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]);
+                        ABC_FREE(queuePages);
+                        st__free_table(pathTable);
+                        return;
+                    }
+
+                    /* Create list element for this child to process its children.
+                     * If this node has been processed already, then it appears
+                     * in the path table and hence is never added to the list
+                     * again.
+                     */
+
+                    if (queuePageIndex == queuePageSize) ResizeQueuePages();
+                    if (memOut) {
+                        for (i = 0; i <= nodeDistPage; i++)
+                            ABC_FREE(nodeDistPages[i]);
+                        ABC_FREE(nodeDistPages);
+                        st__free_table(pathTable);
+                        return;
+                    }
+                    *(currentQueuePage + queuePageIndex) = child;
+                    queuePageIndex++;
+
+                    childrenCount++;
+                } else {
+                    /* if not been met in a path with this parity before */
+                    /* put in list */
+                    if (((Cudd_IsComplement(child)) && (nodeStat->oddTopDist ==
+                          MAXSHORTINT)) || ((!Cudd_IsComplement(child)) &&
+                                  (nodeStat->evenTopDist == MAXSHORTINT))) {
+
+                        if (queuePageIndex == queuePageSize) ResizeQueuePages();
+                        if (memOut) {
+                            for (i = 0; i <= nodeDistPage; i++)
+                                ABC_FREE(nodeDistPages[i]);
+                            ABC_FREE(nodeDistPages);
+                            st__free_table(pathTable);
+                            return;
+
+                        }
+                        *(currentQueuePage + queuePageIndex) = child;
+                        queuePageIndex++;
+
+                        /* update the distance with the appropriate parity */
+                        if (Cudd_IsComplement(child)) {
+                            nodeStat->oddTopDist = (DdHalfWord) topLen + 1;
+                        } else {
+                            nodeStat->evenTopDist = (DdHalfWord) topLen + 1;
+                        }
+                        childrenCount++;
+                    }
+
+                } /* end of else (not found in st__table) */
+            } /*end of if Not constant child */
+            processingDone--;
+        } /*end of while processing Nv, Nnv */
+    }  /*end of while numParents */
+
+#ifdef DD_DEBUG
+    assert(queuePages[parentPage] == childPage);
+    assert(parentQueueIndex == childQueueIndex);
+#endif
+
+    if (childrenCount != 0) {
+        topLen++;
+        childPage = currentQueuePage;
+        childQueueIndex = queuePageIndex;
+        CreateTopDist(pathTable, parentPage, parentQueueIndex, topLen,
+                      childPage, childQueueIndex, childrenCount, fp);
+    }
+
+    return;
+
+} /* end of CreateTopDist */
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Labels each node with the shortest distance from the constant.]
+
+  Description [Labels each node with the shortest distance from the constant.
+  This is done in a DFS search of the BDD. Each node has an odd
+  and even parity distance from the sink (since there exists paths to both
+  zero and one) which is less than MAXSHORTINT. At each node these distances
+  are updated using the minimum distance of its children from the constant.
+  SInce now both the length from the root and child is known, the minimum path
+  length(length of the shortest path between the root and the constant that
+  this node lies on) of this node can be calculated and used to update the
+  pathLengthArray]
+
+  SideEffects [Updates Path Table and path length array]
+
+  SeeAlso     [CreatePathTable CreateTopDist AssessPathLength]
+
+******************************************************************************/
+static int
+CreateBotDist(
+  DdNode * node /* current node */,
+  st__table * pathTable /* path table with path lengths */,
+  unsigned int * pathLengthArray /* array that stores number of nodes belonging to a particular path length. */,
+  FILE *fp /* where to write messages */)
+{
+    DdNode *N, *Nv, *Nnv;
+    DdNode *realChild;
+    DdNode *child, *regChild;
+    NodeDist_t *nodeStat, *nodeStatChild;
+    unsigned int  oddLen, evenLen, pathLength;
+    DdHalfWord botDist;
+    int processingDone;
+
+    if (Cudd_IsConstant(node))
+        return(1);
+    N = Cudd_Regular(node);
+    /* each node has one table entry */
+    /* update as you go down the min dist of each node from
+       the root in each (odd and even) parity */
+    if (! st__lookup(pathTable, (const char *)N, (char **)&nodeStat)) {
+        fprintf(fp, "Something wrong, the entry doesn't exist\n");
+        return(0);
+    }
+
+    /* compute length of odd parity distances */
+    if ((nodeStat->oddTopDist != MAXSHORTINT) &&
+        (nodeStat->oddBotDist != MAXSHORTINT))
+        oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist);
+    else
+        oddLen = MAXSHORTINT;
+
+    /* compute length of even parity distances */
+    if (!((nodeStat->evenTopDist == MAXSHORTINT) ||
+          (nodeStat->evenBotDist == MAXSHORTINT)))
+        evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist);
+    else
+        evenLen = MAXSHORTINT;
+
+    /* assign pathlength to minimum of the two */
+    pathLength = (oddLen <= evenLen) ? oddLen : evenLen;
+
+    Nv = Cudd_T(N);
+    Nnv = Cudd_E(N);
+
+    /* process each child */
+    processingDone = 0;
+    while (processingDone != 2) {
+        if (!processingDone) {
+            child = Nv;
+        } else {
+            child = Nnv;
+        }
+
+        realChild = Cudd_NotCond(child, Cudd_IsComplement(node));
+        regChild = Cudd_Regular(child);
+        if (Cudd_IsConstant(realChild)) {
+            /* Found a minterm; count parity and shortest distance
+            ** from the constant.
+            */
+            if (Cudd_IsComplement(child))
+                nodeStat->oddBotDist = 1;
+            else
+                nodeStat->evenBotDist = 1;
+        } else {
+            /* If node not in table, recur. */
+            if (! st__lookup(pathTable, (const char *)regChild, (char **)&nodeStatChild)) {
+                fprintf(fp, "Something wrong, node in table should have been created in top dist proc.\n");
+                return(0);
+            }
+
+            if (nodeStatChild->oddBotDist == MAXSHORTINT) {
+                if (nodeStatChild->evenBotDist == MAXSHORTINT) {
+                    if (!CreateBotDist(realChild, pathTable, pathLengthArray, fp))
+                        return(0);
+                } else {
+                    fprintf(fp, "Something wrong, both bot nodeStats should be there\n");
+                    return(0);
+                }
+            }
+
+            /* Update shortest distance from the constant depending on
+            **  parity. */
+
+            if (Cudd_IsComplement(child)) {
+                /* If parity on the edge then add 1 to even distance
+                ** of child to get odd parity distance and add 1 to
+                ** odd distance of child to get even parity
+                ** distance. Change distance of current node only if
+                ** the calculated distance is less than existing
+                ** distance. */
+                if (nodeStatChild->oddBotDist != MAXSHORTINT)
+                    botDist = nodeStatChild->oddBotDist + 1;
+                else
+                    botDist = MAXSHORTINT;
+                if (nodeStat->evenBotDist > botDist )
+                    nodeStat->evenBotDist = botDist;
+
+                if (nodeStatChild->evenBotDist != MAXSHORTINT)
+                    botDist = nodeStatChild->evenBotDist + 1;
+                else
+                    botDist = MAXSHORTINT;
+                if (nodeStat->oddBotDist > botDist)
+                    nodeStat->oddBotDist = botDist;
+
+            } else {
+                /* If parity on the edge then add 1 to even distance
+                ** of child to get even parity distance and add 1 to
+                ** odd distance of child to get odd parity distance.
+                ** Change distance of current node only if the
+                ** calculated distance is lesser than existing
+                ** distance. */
+                if (nodeStatChild->evenBotDist != MAXSHORTINT)
+                    botDist = nodeStatChild->evenBotDist + 1;
+                else
+                    botDist = MAXSHORTINT;
+                if (nodeStat->evenBotDist > botDist)
+                    nodeStat->evenBotDist = botDist;
+
+                if (nodeStatChild->oddBotDist != MAXSHORTINT)
+                    botDist = nodeStatChild->oddBotDist + 1;
+                else
+                    botDist = MAXSHORTINT;
+                if (nodeStat->oddBotDist > botDist)
+                    nodeStat->oddBotDist = botDist;
+            }
+        } /* end of else (if not constant child ) */
+        processingDone++;
+    } /* end of while processing Nv, Nnv */
+
+    /* Compute shortest path length on the fly. */
+    if ((nodeStat->oddTopDist != MAXSHORTINT) &&
+        (nodeStat->oddBotDist != MAXSHORTINT))
+        oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist);
+    else
+        oddLen = MAXSHORTINT;
+
+    if ((nodeStat->evenTopDist != MAXSHORTINT) &&
+        (nodeStat->evenBotDist != MAXSHORTINT))
+        evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist);
+    else
+        evenLen = MAXSHORTINT;
+
+    /* Update path length array that has number of nodes of a particular
+    ** path length. */
+    if (oddLen < pathLength ) {
+        if (pathLength != MAXSHORTINT)
+            pathLengthArray[pathLength]--;
+        if (oddLen != MAXSHORTINT)
+            pathLengthArray[oddLen]++;
+        pathLength = oddLen;
+    }
+    if (evenLen < pathLength ) {
+        if (pathLength != MAXSHORTINT)
+            pathLengthArray[pathLength]--;
+        if (evenLen != MAXSHORTINT)
+            pathLengthArray[evenLen]++;
+    }
+
+    return(1);
+
+} /*end of CreateBotDist */
+
+
+/**Function********************************************************************
+
+  Synopsis    [ The outer procedure to label each node with its shortest
+  distance from the root and constant]
+
+  Description [ The outer procedure to label each node with its shortest
+  distance from the root and constant. Calls CreateTopDist and CreateBotDist.
+  The basis for computing the distance between root and constant is that
+  the distance may be the sum of even distances from the node to the root
+  and constant or the sum of odd distances from the node to the root and
+  constant.  Both CreateTopDist and CreateBotDist create the odd and
+  even parity distances from the root and constant respectively.]
+
+  SideEffects [None]
+
+  SeeAlso     [CreateTopDist CreateBotDist]
+
+******************************************************************************/
+static st__table *
+CreatePathTable(
+  DdNode * node /* root of function */,
+  unsigned int * pathLengthArray /* array of path lengths to store nodes labeled with the various path lengths */,
+  FILE *fp /* where to write messages */)
+{
+
+    st__table *pathTable;
+    NodeDist_t *nodeStat;
+    DdHalfWord topLen;
+    DdNode *N;
+    int i, numParents;
+    int insertValue;
+    DdNode **childPage;
+    int parentPage;
+    int childQueueIndex, parentQueueIndex;
+
+    /* Creating path Table for storing data about nodes */
+    pathTable = st__init_table( st__ptrcmp, st__ptrhash);
+
+    /* initializing pages for info about each node */
+    maxNodeDistPages = INITIAL_PAGES;
+    nodeDistPages = ABC_ALLOC(NodeDist_t *, maxNodeDistPages);
+    if (nodeDistPages == NULL) {
+        goto OUT_OF_MEM;
+    }
+    nodeDistPage = 0;
+    currentNodeDistPage = nodeDistPages[nodeDistPage] =
+        ABC_ALLOC(NodeDist_t, nodeDistPageSize);
+    if (currentNodeDistPage == NULL) {
+        for (i = 0; i <= nodeDistPage; i++) ABC_FREE(nodeDistPages[i]);
+        ABC_FREE(nodeDistPages);
+        goto OUT_OF_MEM;
+    }
+    nodeDistPageIndex = 0;
+
+    /* Initializing pages for the BFS search queue, implemented as an array. */
+    maxQueuePages = INITIAL_PAGES;
+    queuePages = ABC_ALLOC(DdNode **, maxQueuePages);
+    if (queuePages == NULL) {
+        goto OUT_OF_MEM;
+    }
+    queuePage = 0;
+    currentQueuePage  = queuePages[queuePage] = ABC_ALLOC(DdNode *, queuePageSize);
+    if (currentQueuePage == NULL) {
+        for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]);
+        ABC_FREE(queuePages);
+        goto OUT_OF_MEM;
+    }
+    queuePageIndex = 0;
+
+    /* Enter the root node into the queue to start with. */
+    parentPage = queuePage;
+    parentQueueIndex = queuePageIndex;
+    topLen = 0;
+    *(currentQueuePage + queuePageIndex) = node;
+    queuePageIndex++;
+    childPage = currentQueuePage;
+    childQueueIndex = queuePageIndex;
+
+    N = Cudd_Regular(node);
+
+    if (nodeDistPageIndex == nodeDistPageSize) ResizeNodeDistPages();
+    if (memOut) {
+        for (i = 0; i <= nodeDistPage; i++) ABC_FREE(nodeDistPages[i]);
+        ABC_FREE(nodeDistPages);
+        for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]);
+        ABC_FREE(queuePages);
+        st__free_table(pathTable);
+        goto OUT_OF_MEM;
+    }
+
+    nodeStat = currentNodeDistPage + nodeDistPageIndex;
+    nodeDistPageIndex++;
+
+    nodeStat->oddTopDist = MAXSHORTINT;
+    nodeStat->evenTopDist = MAXSHORTINT;
+    nodeStat->evenBotDist = MAXSHORTINT;
+    nodeStat->oddBotDist = MAXSHORTINT;
+    nodeStat->regResult = NULL;
+    nodeStat->compResult = NULL;
+
+    insertValue = st__insert(pathTable, (char *)N, (char *)nodeStat);
+    if (insertValue == st__OUT_OF_MEM) {
+        memOut = 1;
+        for (i = 0; i <= nodeDistPage; i++) ABC_FREE(nodeDistPages[i]);
+        ABC_FREE(nodeDistPages);
+        for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]);
+        ABC_FREE(queuePages);
+        st__free_table(pathTable);
+        goto OUT_OF_MEM;
+    } else if (insertValue == 1) {
+        fprintf(fp, "Something wrong, the entry exists but didnt show up in st__lookup\n");
+        return(NULL);
+    }
+
+    if (Cudd_IsComplement(node)) {
+        nodeStat->oddTopDist = 0;
+    } else {
+        nodeStat->evenTopDist = 0;
+    }
+    numParents = 1;
+    /* call the function that counts the distance of each node from the
+     * root
+     */
+#ifdef DD_DEBUG
+    numCalls = 0;
+#endif
+    CreateTopDist(pathTable, parentPage, parentQueueIndex, (int) topLen,
+                  childPage, childQueueIndex, numParents, fp);
+    if (memOut) {
+        fprintf(fp, "Out of Memory and cant count path lengths\n");
+        goto OUT_OF_MEM;
+    }
+
+#ifdef DD_DEBUG
+    numCalls = 0;
+#endif
+    /* call the function that counts the distance of each node from the
+     * constant
+     */
+    if (!CreateBotDist(node, pathTable, pathLengthArray, fp)) return(NULL);
+
+    /* free BFS queue pages as no longer required */
+    for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]);
+    ABC_FREE(queuePages);
+    return(pathTable);
+
+OUT_OF_MEM:
+    (void) fprintf(fp, "Out of Memory, cannot allocate pages\n");
+    memOut = 1;
+    return(NULL);
+
+} /*end of CreatePathTable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Chooses the maximum allowable path length of nodes under the
+  threshold.]
+
+  Description [Chooses the maximum allowable path length under each node.
+  The corner cases are when the threshold is larger than the number
+  of nodes in the BDD iself, in which case 'numVars + 1' is returned.
+  If all nodes of a particular path length are needed, then the
+  maxpath returned is the next one with excess nodes = 0;]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static unsigned int
+AssessPathLength(
+  unsigned int * pathLengthArray /* array determining number of nodes belonging to the different path lengths */,
+  int  threshold /* threshold to determine maximum allowable nodes in the subset */,
+  int  numVars /* maximum number of variables */,
+  unsigned int * excess /* number of nodes labeled maxpath required in the subset */,
+  FILE *fp /* where to write messages */)
+{
+    unsigned int i, maxpath;
+    int temp;
+
+    temp = threshold;
+    i = 0;
+    maxpath = 0;
+    /* quit loop if i reaches max number of variables or if temp reaches
+     * below zero
+     */
+    while ((i < (unsigned) numVars+1) && (temp > 0)) {
+        if (pathLengthArray[i] > 0) {
+            maxpath = i;
+            temp = temp - pathLengthArray[i];
+        }
+        i++;
+    }
+    /* if all nodes of max path are needed */
+    if (temp >= 0) {
+        maxpath++; /* now maxpath  becomes the next maxppath or max number
+                      of variables */
+        *excess = 0;
+    } else { /* normal case when subset required is less than size of
+                original BDD */
+        *excess = temp + pathLengthArray[maxpath];
+    }
+
+    if (maxpath == 0) {
+        fprintf(fp, "Path Length array seems to be all zeroes, check\n");
+    }
+    return(maxpath);
+
+} /* end of AssessPathLength */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the BDD with nodes labeled with path length less than or equal to maxpath]
+
+  Description [Builds the BDD with nodes labeled with path length
+  under maxpath and as many nodes labeled maxpath as determined by the
+  threshold. The procedure uses the path table to determine which nodes
+  in the original bdd need to be retained. This procedure picks a
+  shortest path (tie break decided by taking the child with the shortest
+  distance to the constant) and recurs down the path till it reaches the
+  constant. the procedure then starts building the subset upward from
+  the constant. All nodes labeled by path lengths less than the given
+  maxpath are used to build the subset.  However, in the case of nodes
+  that have label equal to maxpath, as many are chosen as required by
+  the threshold. This number is stored in the info structure in the
+  field thresholdReached. This field is decremented whenever a node
+  labeled maxpath is encountered and the nodes labeled maxpath are
+  aggregated in a maxpath table. As soon as the thresholdReached count
+  goes to 0, the shortest path from this node to the constant is found.
+  The extraction of nodes with the above labeling is based on the fact
+  that each node, labeled with a path length, P, has at least one child
+  labeled P or less. So extracting all nodes labeled a given path length
+  P ensures complete paths between the root and the constant. Extraction
+  of a partial number of nodes with a given path length may result in
+  incomplete paths and hence the additional number of nodes are grabbed
+  to complete the path. Since the Bdd is built bottom-up, other nodes
+  labeled maxpath do lie on complete paths.  The procedure may cause the
+  subset to have a larger or smaller number of nodes than the specified
+  threshold. The increase in the number of nodes is caused by the
+  building of a subset and the reduction by recombination. However in
+  most cases, the recombination overshadows the increase and the
+  procedure returns a result with lower number of nodes than specified.
+  The subsetNodeTable is NIL when there is no hard limit on the number
+  of nodes. Further efforts towards keeping the subset closer to the
+  threshold number were abandoned in favour of keeping the procedure
+  simple and fast.]
+
+  SideEffects [SubsetNodeTable is changed if it is not NIL.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+BuildSubsetBdd(
+  DdManager * dd /* DD manager */,
+  st__table * pathTable /* path table with path lengths and computed results */,
+  DdNode * node /* current node */,
+  struct AssortedInfo * info /* assorted information structure */,
+  st__table * subsetNodeTable /* table storing computed results */)
+{
+    DdNode *N, *Nv, *Nnv;
+    DdNode *ThenBranch, *ElseBranch, *childBranch;
+    DdNode *child, *regChild, *regNnv = NULL, *regNv = NULL;
+    NodeDist_t *nodeStatNv, *nodeStat, *nodeStatNnv;
+    DdNode *neW, *topv, *regNew;
+    char *entry;
+    unsigned int topid;
+    unsigned int childPathLength, oddLen, evenLen, NnvPathLength = 0, NvPathLength = 0;
+    unsigned int NvBotDist, NnvBotDist;
+    int tiebreakChild;
+    int  processingDone, thenDone, elseDone;
+
+
+#ifdef DD_DEBUG
+    numCalls++;
+#endif
+    if (Cudd_IsConstant(node))
+        return(node);
+
+    N = Cudd_Regular(node);
+    /* Find node in table. */
+    if (! st__lookup(pathTable, (const char *)N, (char **)&nodeStat)) {
+        (void) fprintf(dd->err, "Something wrong, node must be in table \n");
+        dd->errorCode = CUDD_INTERNAL_ERROR;
+        return(NULL);
+    }
+    /* If the node in the table has been visited, then return the corresponding
+    ** Dd. Since a node can become a subset of itself, its
+    ** complement (that is te same node reached by a different parity) will
+    ** become a superset of the original node and result in some minterms
+    ** that were not in the original set. Hence two different results are
+    ** maintained, corresponding to the odd and even parities.
+    */
+
+    /* If this node is reached with an odd parity, get odd parity results. */
+    if (Cudd_IsComplement(node)) {
+        if  (nodeStat->compResult != NULL) {
+#ifdef DD_DEBUG
+            hits++;
+#endif
+            return(nodeStat->compResult);
+        }
+    } else {
+        /* if this node is reached with an even parity, get even parity
+         * results
+         */
+        if (nodeStat->regResult != NULL) {
+#ifdef DD_DEBUG
+            hits++;
+#endif
+            return(nodeStat->regResult);
+        }
+    }
+
+
+    /* get children */
+    Nv = Cudd_T(N);
+    Nnv = Cudd_E(N);
+
+    Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
+    Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
+
+    /* no child processed */
+    processingDone = 0;
+    /* then child not processed */
+    thenDone = 0;
+    ThenBranch = NULL;
+    /* else child not processed */
+    elseDone = 0;
+    ElseBranch = NULL;
+    /* if then child constant, branch is the child */
+    if (Cudd_IsConstant(Nv)) {
+        /*shortest path found */
+        if ((Nv == DD_ONE(dd)) && (info->findShortestPath)) {
+            info->findShortestPath = 0;
+        }
+
+        ThenBranch = Nv;
+        cuddRef(ThenBranch);
+        if (ThenBranch == NULL) {
+            return(NULL);
+        }
+
+        thenDone++;
+        processingDone++;
+        NvBotDist = MAXSHORTINT;
+    } else {
+        /* Derive regular child for table lookup. */
+        regNv = Cudd_Regular(Nv);
+        /* Get node data for shortest path length. */
+        if (! st__lookup(pathTable, (const char *)regNv, (char **)&nodeStatNv) ) {
+            (void) fprintf(dd->err, "Something wrong, node must be in table\n");
+            dd->errorCode = CUDD_INTERNAL_ERROR;
+            return(NULL);
+        }
+        /* Derive shortest path length for child. */
+        if ((nodeStatNv->oddTopDist != MAXSHORTINT) &&
+            (nodeStatNv->oddBotDist != MAXSHORTINT)) {
+            oddLen = (nodeStatNv->oddTopDist + nodeStatNv->oddBotDist);
+        } else {
+            oddLen = MAXSHORTINT;
+        }
+
+        if ((nodeStatNv->evenTopDist != MAXSHORTINT) &&
+            (nodeStatNv->evenBotDist != MAXSHORTINT)) {
+            evenLen = (nodeStatNv->evenTopDist +nodeStatNv->evenBotDist);
+        } else {
+            evenLen = MAXSHORTINT;
+        }
+
+        NvPathLength = (oddLen <= evenLen) ? oddLen : evenLen;
+        NvBotDist = (oddLen <= evenLen) ? nodeStatNv->oddBotDist:
+                                                   nodeStatNv->evenBotDist;
+    }
+    /* if else child constant, branch is the child */
+    if (Cudd_IsConstant(Nnv)) {
+        /*shortest path found */
+        if ((Nnv == DD_ONE(dd)) && (info->findShortestPath)) {
+            info->findShortestPath = 0;
+        }
+
+        ElseBranch = Nnv;
+        cuddRef(ElseBranch);
+        if (ElseBranch == NULL) {
+            return(NULL);
+        }
+
+        elseDone++;
+        processingDone++;
+        NnvBotDist = MAXSHORTINT;
+    } else {
+        /* Derive regular child for table lookup. */
+        regNnv = Cudd_Regular(Nnv);
+        /* Get node data for shortest path length. */
+        if (! st__lookup(pathTable, (const char *)regNnv, (char **)&nodeStatNnv) ) {
+            (void) fprintf(dd->err, "Something wrong, node must be in table\n");
+            dd->errorCode = CUDD_INTERNAL_ERROR;
+            return(NULL);
+        }
+        /* Derive shortest path length for child. */
+        if ((nodeStatNnv->oddTopDist != MAXSHORTINT) &&
+            (nodeStatNnv->oddBotDist != MAXSHORTINT)) {
+            oddLen = (nodeStatNnv->oddTopDist + nodeStatNnv->oddBotDist);
+        } else {
+            oddLen = MAXSHORTINT;
+        }
+
+        if ((nodeStatNnv->evenTopDist != MAXSHORTINT) &&
+            (nodeStatNnv->evenBotDist != MAXSHORTINT)) {
+            evenLen = (nodeStatNnv->evenTopDist +nodeStatNnv->evenBotDist);
+        } else {
+            evenLen = MAXSHORTINT;
+        }
+
+        NnvPathLength = (oddLen <= evenLen) ? oddLen : evenLen;
+        NnvBotDist = (oddLen <= evenLen) ? nodeStatNnv->oddBotDist :
+                                                   nodeStatNnv->evenBotDist;
+    }
+
+    tiebreakChild = (NvBotDist <= NnvBotDist) ? 1 : 0;
+    /* while both children not processed */
+    while (processingDone != 2) {
+        if (!processingDone) {
+            /* if no child processed */
+            /* pick the child with shortest path length and record which one
+             * picked
+             */
+            if ((NvPathLength < NnvPathLength) ||
+                ((NvPathLength == NnvPathLength) && (tiebreakChild == 1))) {
+                child = Nv;
+                regChild = regNv;
+                thenDone = 1;
+                childPathLength = NvPathLength;
+            } else {
+                child = Nnv;
+                regChild = regNnv;
+                elseDone = 1;
+                childPathLength = NnvPathLength;
+            } /* then path length less than else path length */
+        } else {
+            /* if one child processed, process the other */
+            if (thenDone) {
+                child = Nnv;
+                regChild = regNnv;
+                elseDone = 1;
+                childPathLength = NnvPathLength;
+            } else {
+                child = Nv;
+                regChild = regNv;
+                thenDone = 1;
+                childPathLength = NvPathLength;
+            } /* end of else pick the Then child if ELSE child processed */
+        } /* end of else one child has been processed */
+
+        /* ignore (replace with constant 0) all nodes which lie on paths larger
+         * than the maximum length of the path required
+         */
+        if (childPathLength > info->maxpath) {
+            /* record nodes visited */
+            childBranch = zero;
+        } else {
+            if (childPathLength < info->maxpath) {
+                if (info->findShortestPath) {
+                    info->findShortestPath = 0;
+                }
+                childBranch = BuildSubsetBdd(dd, pathTable, child, info,
+                                             subsetNodeTable);
+
+            } else { /* Case: path length of node = maxpath */
+                /* If the node labeled with maxpath is found in the
+                ** maxpathTable, use it to build the subset BDD.  */
+                if ( st__lookup(info->maxpathTable, (char *)regChild,
+                              (char **)&entry)) {
+                    /* When a node that is already been chosen is hit,
+                    ** the quest for a complete path is over.  */
+                    if (info->findShortestPath) {
+                        info->findShortestPath = 0;
+                    }
+                    childBranch = BuildSubsetBdd(dd, pathTable, child, info,
+                                                 subsetNodeTable);
+                } else {
+                    /* If node is not found in the maxpathTable and
+                    ** the threshold has been reached, then if the
+                    ** path needs to be completed, continue. Else
+                    ** replace the node with a zero.  */
+                    if (info->thresholdReached <= 0) {
+                        if (info->findShortestPath) {
+                            if ( st__insert(info->maxpathTable, (char *)regChild,
+                                          (char *)NIL(char)) == st__OUT_OF_MEM) {
+                                memOut = 1;
+                                (void) fprintf(dd->err, "OUT of memory\n");
+                                info->thresholdReached = 0;
+                                childBranch = zero;
+                            } else {
+                                info->thresholdReached--;
+                                childBranch = BuildSubsetBdd(dd, pathTable,
+                                                    child, info,subsetNodeTable);
+                            }
+                        } else { /* not find shortest path, we dont need this
+                                    node */
+                            childBranch = zero;
+                        }
+                    } else { /* Threshold hasn't been reached,
+                             ** need the node. */
+                        if ( st__insert(info->maxpathTable, (char *)regChild,
+                                      (char *)NIL(char)) == st__OUT_OF_MEM) {
+                            memOut = 1;
+                            (void) fprintf(dd->err, "OUT of memory\n");
+                            info->thresholdReached = 0;
+                            childBranch = zero;
+                        } else {
+                            info->thresholdReached--;
+                            if (info->thresholdReached <= 0) {
+                                info->findShortestPath = 1;
+                            }
+                            childBranch = BuildSubsetBdd(dd, pathTable,
+                                                 child, info, subsetNodeTable);
+
+                        } /* end of st__insert successful */
+                    } /* end of threshold hasnt been reached yet */
+                } /* end of else node not found in maxpath table */
+            } /* end of if (path length of node = maxpath) */
+        } /* end if !(childPathLength > maxpath) */
+        if (childBranch == NULL) {
+            /* deref other stuff incase reordering has taken place */
+            if (ThenBranch != NULL) {
+                Cudd_RecursiveDeref(dd, ThenBranch);
+                ThenBranch = NULL;
+            }
+            if (ElseBranch != NULL) {
+                Cudd_RecursiveDeref(dd, ElseBranch);
+                ElseBranch = NULL;
+            }
+            return(NULL);
+        }
+
+        cuddRef(childBranch);
+
+        if (child == Nv) {
+            ThenBranch = childBranch;
+        } else {
+            ElseBranch = childBranch;
+        }
+        processingDone++;
+
+    } /*end of while processing Nv, Nnv */
+
+    info->findShortestPath = 0;
+    topid = Cudd_NodeReadIndex(N);
+    topv = Cudd_ReadVars(dd, topid);
+    cuddRef(topv);
+    neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch);
+    if (neW != NULL) {
+        cuddRef(neW);
+    }
+    Cudd_RecursiveDeref(dd, topv);
+    Cudd_RecursiveDeref(dd, ThenBranch);
+    Cudd_RecursiveDeref(dd, ElseBranch);
+
+
+    /* Hard Limit of threshold has been imposed */
+    if (subsetNodeTable != NIL( st__table)) {
+        /* check if a new node is created */
+        regNew = Cudd_Regular(neW);
+        /* subset node table keeps all new nodes that have been created to keep
+         * a running count of how many nodes have been built in the subset.
+         */
+        if (! st__lookup(subsetNodeTable, (char *)regNew, (char **)&entry)) {
+            if (!Cudd_IsConstant(regNew)) {
+                if ( st__insert(subsetNodeTable, (char *)regNew,
+                              (char *)NULL) == st__OUT_OF_MEM) {
+                    (void) fprintf(dd->err, "Out of memory\n");
+                    return (NULL);
+                }
+                if ( st__count(subsetNodeTable) > info->threshold) {
+                    info->thresholdReached = 0;
+                }
+            }
+        }
+    }
+
+
+    if (neW == NULL) {
+        return(NULL);
+    } else {
+        /*store computed result in regular form*/
+        if (Cudd_IsComplement(node)) {
+            nodeStat->compResult = neW;
+            cuddRef(nodeStat->compResult);
+            /* if the new node is the same as the corresponding node in the
+             * original bdd then its complement need not be computed as it
+             * cannot be larger than the node itself
+             */
+            if (neW == node) {
+#ifdef DD_DEBUG
+                thishit++;
+#endif
+                /* if a result for the node has already been computed, then
+                 * it can only be smaller than teh node itself. hence store
+                 * the node result in order not to break recombination
+                 */
+                if (nodeStat->regResult != NULL) {
+                    Cudd_RecursiveDeref(dd, nodeStat->regResult);
+                }
+                nodeStat->regResult = Cudd_Not(neW);
+                cuddRef(nodeStat->regResult);
+            }
+
+        } else {
+            nodeStat->regResult = neW;
+            cuddRef(nodeStat->regResult);
+            if (neW == node) {
+#ifdef DD_DEBUG
+                thishit++;
+#endif
+                if (nodeStat->compResult != NULL) {
+                    Cudd_RecursiveDeref(dd, nodeStat->compResult);
+                }
+                nodeStat->compResult = Cudd_Not(neW);
+                cuddRef(nodeStat->compResult);
+            }
+        }
+
+        cuddDeref(neW);
+        return(neW);
+    } /* end of else i.e. Subset != NULL */
+} /* end of BuildSubsetBdd */
+
+
+/**Function********************************************************************
+
+  Synopsis     [Procedure to free te result dds stored in the NodeDist pages.]
+
+  Description [None]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static enum st__retval
+stPathTableDdFree(
+  char * key,
+  char * value,
+  char * arg)
+{
+    NodeDist_t *nodeStat;
+    DdManager *dd;
+
+    nodeStat = (NodeDist_t *)value;
+    dd = (DdManager *)arg;
+    if (nodeStat->regResult != NULL) {
+        Cudd_RecursiveDeref(dd, nodeStat->regResult);
+    }
+    if (nodeStat->compResult != NULL) {
+        Cudd_RecursiveDeref(dd, nodeStat->compResult);
+    }
+    return( st__CONTINUE);
+
+} /* end of stPathTableFree */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddSymmetry.c b/abc-build/src/bdd/cudd/cuddSymmetry.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddSymmetry.c
@@ -0,0 +1,1706 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddSymmetry.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for symmetry-based variable reordering.]
+
+  Description [External procedures included in this file:
+                <ul>
+                <li> Cudd_SymmProfile()
+                </ul>
+        Internal procedures included in this module:
+                <ul>
+                <li> cuddSymmCheck()
+                <li> cuddSymmSifting()
+                <li> cuddSymmSiftingConv()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> ddSymmUniqueCompare()
+                <li> ddSymmSiftingAux()
+                <li> ddSymmSiftingConvAux()
+                <li> ddSymmSiftingUp()
+                <li> ddSymmSiftingDown()
+                <li> ddSymmGroupMove()
+                <li> ddSymmGroupMoveBackward()
+                <li> ddSymmSiftingBackward()
+                <li> ddSymmSummary()
+                </ul>]
+
+  Author      [Shipra Panda, Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define MV_OOM (Move *)1
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddSymmetry.c,v 1.26 2009/02/19 16:23:54 fabio Exp $";
+#endif
+
+static  int     *entry;
+
+extern  int     ddTotalNumberSwapping;
+#ifdef DD_STATS
+extern  int     ddTotalNISwaps;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int ddSymmUniqueCompare (int *ptrX, int *ptrY);
+static int ddSymmSiftingAux (DdManager *table, int x, int xLow, int xHigh);
+static int ddSymmSiftingConvAux (DdManager *table, int x, int xLow, int xHigh);
+static Move * ddSymmSiftingUp (DdManager *table, int y, int xLow);
+static Move * ddSymmSiftingDown (DdManager *table, int x, int xHigh);
+static int ddSymmGroupMove (DdManager *table, int x, int y, Move **moves);
+static int ddSymmGroupMoveBackward (DdManager *table, int x, int y);
+static int ddSymmSiftingBackward (DdManager *table, Move *moves, int size);
+static void ddSymmSummary (DdManager *table, int lower, int upper, int *symvars, int *symgroups);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints statistics on symmetric variables.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+Cudd_SymmProfile(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int i,x,gbot;
+    int TotalSymm = 0;
+    int TotalSymmGroups = 0;
+
+    for (i = lower; i <= upper; i++) {
+        if (table->subtables[i].next != (unsigned) i) {
+            x = i;
+            (void) fprintf(table->out,"Group:");
+            do {
+                (void) fprintf(table->out,"  %d",table->invperm[x]);
+                TotalSymm++;
+                gbot = x;
+                x = table->subtables[x].next;
+            } while (x != i);
+            TotalSymmGroups++;
+#ifdef DD_DEBUG
+            assert(table->subtables[gbot].next == (unsigned) i);
+#endif
+            i = gbot;
+            (void) fprintf(table->out,"\n");
+        }
+    }
+    (void) fprintf(table->out,"Total Symmetric = %d\n",TotalSymm);
+    (void) fprintf(table->out,"Total Groups = %d\n",TotalSymmGroups);
+
+} /* end of Cudd_SymmProfile */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks for symmetry of x and y.]
+
+  Description [Checks for symmetry of x and y. Ignores projection
+  functions, unless they are isolated. Returns 1 in case of symmetry; 0
+  otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+cuddSymmCheck(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10;
+    int comple;         /* f0 is complemented */
+    int xsymmy;         /* x and y may be positively symmetric */
+    int xsymmyp;        /* x and y may be negatively symmetric */
+    int arccount;       /* number of arcs from layer x to layer y */
+    int TotalRefCount;  /* total reference count of layer y minus 1 */
+    int yindex;
+    int i;
+    DdNodePtr *list;
+    int slots;
+    DdNode *sentinel = &(table->sentinel);
+#ifdef DD_DEBUG
+    int xindex;
+#endif
+
+    /* Checks that x and y are not the projection functions.
+    ** For x it is sufficient to check whether there is only one
+    ** node; indeed, if there is one node, it is the projection function
+    ** and it cannot point to y. Hence, if y isn't just the projection
+    ** function, it has one arc coming from a layer different from x.
+    */
+    if (table->subtables[x].keys == 1) {
+        return(0);
+    }
+    yindex = table->invperm[y];
+    if (table->subtables[y].keys == 1) {
+        if (table->vars[yindex]->ref == 1)
+            return(0);
+    }
+
+    xsymmy = xsymmyp = 1;
+    arccount = 0;
+    slots = table->subtables[x].slots;
+    list = table->subtables[x].nodelist;
+    for (i = 0; i < slots; i++) {
+        f = list[i];
+        while (f != sentinel) {
+            /* Find f1, f0, f11, f10, f01, f00. */
+            f1 = cuddT(f);
+            f0 = Cudd_Regular(cuddE(f));
+            comple = Cudd_IsComplement(cuddE(f));
+            if ((int) f1->index == yindex) {
+                arccount++;
+                f11 = cuddT(f1); f10 = cuddE(f1);
+            } else {
+                if ((int) f0->index != yindex) {
+                    /* If f is an isolated projection function it is
+                    ** allowed to bypass layer y.
+                    */
+                    if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1)
+                        return(0); /* f bypasses layer y */
+                }
+                f11 = f10 = f1;
+            }
+            if ((int) f0->index == yindex) {
+                arccount++;
+                f01 = cuddT(f0); f00 = cuddE(f0);
+            } else {
+                f01 = f00 = f0;
+            }
+            if (comple) {
+                f01 = Cudd_Not(f01);
+                f00 = Cudd_Not(f00);
+            }
+
+            if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) {
+                xsymmy &= f01 == f10;
+                xsymmyp &= f11 == f00;
+                if ((xsymmy == 0) && (xsymmyp == 0))
+                    return(0);
+            }
+
+            f = f->next;
+        } /* while */
+    } /* for */
+
+    /* Calculate the total reference counts of y */
+    TotalRefCount = -1; /* -1 for projection function */
+    slots = table->subtables[y].slots;
+    list = table->subtables[y].nodelist;
+    for (i = 0; i < slots; i++) {
+        f = list[i];
+        while (f != sentinel) {
+            TotalRefCount += f->ref;
+            f = f->next;
+        }
+    }
+
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    if (arccount == TotalRefCount) {
+        xindex = table->invperm[x];
+        (void) fprintf(table->out,
+                       "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
+                       xindex,yindex,x,y);
+    }
+#endif
+
+    return(arccount == TotalRefCount);
+
+} /* end of cuddSymmCheck */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Symmetric sifting algorithm.]
+
+  Description [Symmetric sifting algorithm.
+  Assumes that no dead nodes are present.
+    <ol>
+    <li> Order all the variables according to the number of entries in
+    each unique subtable.
+    <li> Sift the variable up and down, remembering each time the total
+    size of the DD heap and grouping variables that are symmetric.
+    <li> Select the best permutation.
+    <li> Repeat 3 and 4 for all variables.
+    </ol>
+  Returns 1 plus the number of symmetric variables if successful; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddSymmSiftingConv]
+
+******************************************************************************/
+int
+cuddSymmSifting(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int         i;
+    int         *var;
+    int         size;
+    int         x;
+    int         result;
+    int         symvars;
+    int         symgroups;
+#ifdef DD_STATS
+    int         previousSize;
+#endif
+
+    size = table->size;
+
+    /* Find order in which to sift variables. */
+    var = NULL;
+    entry = ABC_ALLOC(int,size);
+    if (entry == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto ddSymmSiftingOutOfMem;
+    }
+    var = ABC_ALLOC(int,size);
+    if (var == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto ddSymmSiftingOutOfMem;
+    }
+
+    for (i = 0; i < size; i++) {
+        x = table->perm[i];
+        entry[i] = table->subtables[x].keys;
+        var[i] = i;
+    }
+
+    qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
+
+    /* Initialize the symmetry of each subtable to itself. */
+    for (i = lower; i <= upper; i++) {
+        table->subtables[i].next = i;
+    }
+
+    for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
+        if (ddTotalNumberSwapping >= table->siftMaxSwap)
+            break;
+        // enable timeout during variable reodering - alanmi 2/13/11
+        if ( table->TimeStop && Abc_Clock() > table->TimeStop )
+            break;
+        x = table->perm[var[i]];
+#ifdef DD_STATS
+        previousSize = table->keys - table->isolated;
+#endif
+        if (x < lower || x > upper) continue;
+        if (table->subtables[x].next == (unsigned) x) {
+            result = ddSymmSiftingAux(table,x,lower,upper);
+            if (!result) goto ddSymmSiftingOutOfMem;
+#ifdef DD_STATS
+            if (table->keys < (unsigned) previousSize + table->isolated) {
+                (void) fprintf(table->out,"-");
+            } else if (table->keys > (unsigned) previousSize +
+                       table->isolated) {
+                (void) fprintf(table->out,"+"); /* should never happen */
+            } else {
+                (void) fprintf(table->out,"=");
+            }
+            fflush(table->out);
+#endif
+        }
+    }
+
+    ABC_FREE(var);
+    ABC_FREE(entry);
+
+    ddSymmSummary(table, lower, upper, &symvars, &symgroups);
+
+#ifdef DD_STATS
+    (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
+                   symvars);
+    (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
+                   symgroups);
+#endif
+
+    return(1+symvars);
+
+ddSymmSiftingOutOfMem:
+
+    if (entry != NULL) ABC_FREE(entry);
+    if (var != NULL) ABC_FREE(var);
+
+    return(0);
+
+} /* end of cuddSymmSifting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Symmetric sifting to convergence algorithm.]
+
+  Description [Symmetric sifting to convergence algorithm.
+  Assumes that no dead nodes are present.
+    <ol>
+    <li> Order all the variables according to the number of entries in
+    each unique subtable.
+    <li> Sift the variable up and down, remembering each time the total
+    size of the DD heap and grouping variables that are symmetric.
+    <li> Select the best permutation.
+    <li> Repeat 3 and 4 for all variables.
+    <li> Repeat 1-4 until no further improvement.
+    </ol>
+  Returns 1 plus the number of symmetric variables if successful; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddSymmSifting]
+
+******************************************************************************/
+int
+cuddSymmSiftingConv(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int         i;
+    int         *var;
+    int         size;
+    int         x;
+    int         result;
+    int         symvars;
+    int         symgroups;
+    int         classes;
+    int         initialSize;
+#ifdef DD_STATS
+    int         previousSize;
+#endif
+
+    initialSize = table->keys - table->isolated;
+
+    size = table->size;
+
+    /* Find order in which to sift variables. */
+    var = NULL;
+    entry = ABC_ALLOC(int,size);
+    if (entry == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto ddSymmSiftingConvOutOfMem;
+    }
+    var = ABC_ALLOC(int,size);
+    if (var == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto ddSymmSiftingConvOutOfMem;
+    }
+
+    for (i = 0; i < size; i++) {
+        x = table->perm[i];
+        entry[i] = table->subtables[x].keys;
+        var[i] = i;
+    }
+
+    qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
+
+    /* Initialize the symmetry of each subtable to itself
+    ** for first pass of converging symmetric sifting.
+    */
+    for (i = lower; i <= upper; i++) {
+        table->subtables[i].next = i;
+    }
+
+    for (i = 0; i < ddMin(table->siftMaxVar, table->size); i++) {
+        if (ddTotalNumberSwapping >= table->siftMaxSwap)
+            break;
+        x = table->perm[var[i]];
+        if (x < lower || x > upper) continue;
+        /* Only sift if not in symmetry group already. */
+        if (table->subtables[x].next == (unsigned) x) {
+#ifdef DD_STATS
+            previousSize = table->keys - table->isolated;
+#endif
+            result = ddSymmSiftingAux(table,x,lower,upper);
+            if (!result) goto ddSymmSiftingConvOutOfMem;
+#ifdef DD_STATS
+            if (table->keys < (unsigned) previousSize + table->isolated) {
+                (void) fprintf(table->out,"-");
+            } else if (table->keys > (unsigned) previousSize +
+                       table->isolated) {
+                (void) fprintf(table->out,"+");
+            } else {
+                (void) fprintf(table->out,"=");
+            }
+            fflush(table->out);
+#endif
+        }
+    }
+
+    /* Sifting now until convergence. */
+    while ((unsigned) initialSize > table->keys - table->isolated) {
+        initialSize = table->keys - table->isolated;
+#ifdef DD_STATS
+        (void) fprintf(table->out,"\n");
+#endif
+        /* Here we consider only one representative for each symmetry class. */
+        for (x = lower, classes = 0; x <= upper; x++, classes++) {
+            while ((unsigned) x < table->subtables[x].next) {
+                x = table->subtables[x].next;
+            }
+            /* Here x is the largest index in a group.
+            ** Groups consist of adjacent variables.
+            ** Hence, the next increment of x will move it to a new group.
+            */
+            i = table->invperm[x];
+            entry[i] = table->subtables[x].keys;
+            var[classes] = i;
+        }
+
+        qsort((void *)var,classes,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
+
+        /* Now sift. */
+        for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
+            if (ddTotalNumberSwapping >= table->siftMaxSwap)
+                break;
+            x = table->perm[var[i]];
+            if ((unsigned) x >= table->subtables[x].next) {
+#ifdef DD_STATS
+                previousSize = table->keys - table->isolated;
+#endif
+                result = ddSymmSiftingConvAux(table,x,lower,upper);
+                if (!result ) goto ddSymmSiftingConvOutOfMem;
+#ifdef DD_STATS
+                if (table->keys < (unsigned) previousSize + table->isolated) {
+                    (void) fprintf(table->out,"-");
+                } else if (table->keys > (unsigned) previousSize +
+                           table->isolated) {
+                    (void) fprintf(table->out,"+");
+                } else {
+                    (void) fprintf(table->out,"=");
+                }
+                fflush(table->out);
+#endif
+            }
+        } /* for */
+    }
+
+    ddSymmSummary(table, lower, upper, &symvars, &symgroups);
+
+#ifdef DD_STATS
+    (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
+                   symvars);
+    (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
+                   symgroups);
+#endif
+
+    ABC_FREE(var);
+    ABC_FREE(entry);
+
+    return(1+symvars);
+
+ddSymmSiftingConvOutOfMem:
+
+    if (entry != NULL) ABC_FREE(entry);
+    if (var != NULL) ABC_FREE(var);
+
+    return(0);
+
+} /* end of cuddSymmSiftingConv */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison function used by qsort.]
+
+  Description [Comparison function used by qsort to order the variables
+  according to the number of keys in the subtables.
+  Returns the difference in number of keys between the two
+  variables being compared.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSymmUniqueCompare(
+  int * ptrX,
+  int * ptrY)
+{
+#if 0
+    if (entry[*ptrY] == entry[*ptrX]) {
+        return((*ptrX) - (*ptrY));
+    }
+#endif
+    return(entry[*ptrY] - entry[*ptrX]);
+
+} /* end of ddSymmUniqueCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries.]
+
+  Description [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries. Finds the best position and does the required changes.
+  Assumes that x is not part of a symmetry group. Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSymmSiftingAux(
+  DdManager * table,
+  int  x,
+  int  xLow,
+  int  xHigh)
+{
+    Move *move;
+    Move *moveUp;       /* list of up moves */
+    Move *moveDown;     /* list of down moves */
+    int  initialSize;
+    int  result;
+    int  i;
+    int  topbot;        /* index to either top or bottom of symmetry group */
+    int  initGroupSize, finalGroupSize;
+
+
+#ifdef DD_DEBUG
+    /* check for previously detected symmetry */
+    assert(table->subtables[x].next == (unsigned) x);
+#endif
+
+    initialSize = table->keys - table->isolated;
+
+    moveDown = NULL;
+    moveUp = NULL;
+
+    if ((x - xLow) > (xHigh - x)) {
+        /* Will go down first, unless x == xHigh:
+        ** Look for consecutive symmetries above x.
+        */
+        for (i = x; i > xLow; i--) {
+            if (!cuddSymmCheck(table,i-1,i))
+                break;
+            topbot = table->subtables[i-1].next; /* find top of i-1's group */
+            table->subtables[i-1].next = i;
+            table->subtables[x].next = topbot; /* x is bottom of group so its */
+                                               /* next is top of i-1's group */
+            i = topbot + 1; /* add 1 for i--; new i is top of symm group */
+        }
+    } else {
+        /* Will go up first unless x == xlow:
+        ** Look for consecutive symmetries below x.
+        */
+        for (i = x; i < xHigh; i++) {
+            if (!cuddSymmCheck(table,i,i+1))
+                break;
+            /* find bottom of i+1's symm group */
+            topbot = i + 1;
+            while ((unsigned) topbot < table->subtables[topbot].next) {
+                topbot = table->subtables[topbot].next;
+            }
+            table->subtables[topbot].next = table->subtables[i].next;
+            table->subtables[i].next = i + 1;
+            i = topbot - 1; /* subtract 1 for i++; new i is bottom of group */
+        }
+    }
+
+    /* Now x may be in the middle of a symmetry group.
+    ** Find bottom of x's symm group.
+    */
+    while ((unsigned) x < table->subtables[x].next)
+        x = table->subtables[x].next;
+
+    if (x == xLow) { /* Sift down */
+
+#ifdef DD_DEBUG
+        /* x must be a singleton */
+        assert((unsigned) x == table->subtables[x].next);
+#endif
+        if (x == xHigh) return(1);      /* just one variable */
+
+        initGroupSize = 1;
+
+        moveDown = ddSymmSiftingDown(table,x,xHigh);
+            /* after this point x --> xHigh, unless early term */
+        if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
+        if (moveDown == NULL) return(1);
+
+        x = moveDown->y;
+        /* Find bottom of x's group */
+        i = x;
+        while ((unsigned) i < table->subtables[i].next) {
+            i = table->subtables[i].next;
+        }
+#ifdef DD_DEBUG
+        /* x should be the top of the symmetry group and i the bottom */
+        assert((unsigned) i >= table->subtables[i].next);
+        assert((unsigned) x == table->subtables[i].next);
+#endif
+        finalGroupSize = i - x + 1;
+
+        if (initGroupSize == finalGroupSize) {
+            /* No new symmetry groups detected, return to best position */
+            result = ddSymmSiftingBackward(table,moveDown,initialSize);
+        } else {
+            initialSize = table->keys - table->isolated;
+            moveUp = ddSymmSiftingUp(table,x,xLow);
+            result = ddSymmSiftingBackward(table,moveUp,initialSize);
+        }
+        if (!result) goto ddSymmSiftingAuxOutOfMem;
+
+    } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
+        /* Find top of x's symm group */
+        i = x;                          /* bottom */
+        x = table->subtables[x].next;   /* top */
+
+        if (x == xLow) return(1); /* just one big group */
+
+        initGroupSize = i - x + 1;
+
+        moveUp = ddSymmSiftingUp(table,x,xLow);
+            /* after this point x --> xLow, unless early term */
+        if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
+        if (moveUp == NULL) return(1);
+
+        x = moveUp->x;
+        /* Find top of x's group */
+        i = table->subtables[x].next;
+#ifdef DD_DEBUG
+        /* x should be the bottom of the symmetry group and i the top */
+        assert((unsigned) x >= table->subtables[x].next);
+        assert((unsigned) i == table->subtables[x].next);
+#endif
+        finalGroupSize = x - i + 1;
+
+        if (initGroupSize == finalGroupSize) {
+            /* No new symmetry groups detected, return to best position */
+            result = ddSymmSiftingBackward(table,moveUp,initialSize);
+        } else {
+            initialSize = table->keys - table->isolated;
+            moveDown = ddSymmSiftingDown(table,x,xHigh);
+            result = ddSymmSiftingBackward(table,moveDown,initialSize);
+        }
+        if (!result) goto ddSymmSiftingAuxOutOfMem;
+
+    } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
+
+        moveDown = ddSymmSiftingDown(table,x,xHigh);
+        /* at this point x == xHigh, unless early term */
+        if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
+
+        if (moveDown != NULL) {
+            x = moveDown->y;    /* x is top here */
+            i = x;
+            while ((unsigned) i < table->subtables[i].next) {
+                i = table->subtables[i].next;
+            }
+        } else {
+            i = x;
+            while ((unsigned) i < table->subtables[i].next) {
+                i = table->subtables[i].next;
+            }
+            x = table->subtables[i].next;
+        }
+#ifdef DD_DEBUG
+        /* x should be the top of the symmetry group and i the bottom */
+        assert((unsigned) i >= table->subtables[i].next);
+        assert((unsigned) x == table->subtables[i].next);
+#endif
+        initGroupSize = i - x + 1;
+
+        moveUp = ddSymmSiftingUp(table,x,xLow);
+        if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
+
+        if (moveUp != NULL) {
+            x = moveUp->x;
+            i = table->subtables[x].next;
+        } else {
+            i = x;
+            while ((unsigned) x < table->subtables[x].next)
+                x = table->subtables[x].next;
+        }
+#ifdef DD_DEBUG
+        /* x should be the bottom of the symmetry group and i the top */
+        assert((unsigned) x >= table->subtables[x].next);
+        assert((unsigned) i == table->subtables[x].next);
+#endif
+        finalGroupSize = x - i + 1;
+
+        if (initGroupSize == finalGroupSize) {
+            /* No new symmetry groups detected, return to best position */
+            result = ddSymmSiftingBackward(table,moveUp,initialSize);
+        } else {
+            while (moveDown != NULL) {
+                move = moveDown->next;
+                cuddDeallocMove(table, moveDown);
+                moveDown = move;
+            }
+            initialSize = table->keys - table->isolated;
+            moveDown = ddSymmSiftingDown(table,x,xHigh);
+            result = ddSymmSiftingBackward(table,moveDown,initialSize);
+        }
+        if (!result) goto ddSymmSiftingAuxOutOfMem;
+
+    } else { /* moving up first: shorter */
+        /* Find top of x's symmetry group */
+        x = table->subtables[x].next;
+
+        moveUp = ddSymmSiftingUp(table,x,xLow);
+        /* at this point x == xHigh, unless early term */
+        if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
+
+        if (moveUp != NULL) {
+            x = moveUp->x;
+            i = table->subtables[x].next;
+        } else {
+            while ((unsigned) x < table->subtables[x].next)
+                x = table->subtables[x].next;
+            i = table->subtables[x].next;
+        }
+#ifdef DD_DEBUG
+        /* x is bottom of the symmetry group and i is top */
+        assert((unsigned) x >= table->subtables[x].next);
+        assert((unsigned) i == table->subtables[x].next);
+#endif
+        initGroupSize = x - i + 1;
+
+        moveDown = ddSymmSiftingDown(table,x,xHigh);
+        if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
+
+        if (moveDown != NULL) {
+            x = moveDown->y;
+            i = x;
+            while ((unsigned) i < table->subtables[i].next) {
+                i = table->subtables[i].next;
+            }
+        } else {
+            i = x;
+            x = table->subtables[x].next;
+        }
+#ifdef DD_DEBUG
+        /* x should be the top of the symmetry group and i the bottom */
+        assert((unsigned) i >= table->subtables[i].next);
+        assert((unsigned) x == table->subtables[i].next);
+#endif
+        finalGroupSize = i - x + 1;
+
+        if (initGroupSize == finalGroupSize) {
+            /* No new symmetries detected, go back to best position */
+            result = ddSymmSiftingBackward(table,moveDown,initialSize);
+        } else {
+            while (moveUp != NULL) {
+                move = moveUp->next;
+                cuddDeallocMove(table, moveUp);
+                moveUp = move;
+            }
+            initialSize = table->keys - table->isolated;
+            moveUp = ddSymmSiftingUp(table,x,xLow);
+            result = ddSymmSiftingBackward(table,moveUp,initialSize);
+        }
+        if (!result) goto ddSymmSiftingAuxOutOfMem;
+    }
+
+    while (moveDown != NULL) {
+        move = moveDown->next;
+        cuddDeallocMove(table, moveDown);
+        moveDown = move;
+    }
+    while (moveUp != NULL) {
+        move = moveUp->next;
+        cuddDeallocMove(table, moveUp);
+        moveUp = move;
+    }
+
+    return(1);
+
+ddSymmSiftingAuxOutOfMem:
+    if (moveDown != MV_OOM) {
+        while (moveDown != NULL) {
+            move = moveDown->next;
+            cuddDeallocMove(table, moveDown);
+            moveDown = move;
+        }
+    }
+    if (moveUp != MV_OOM) {
+        while (moveUp != NULL) {
+            move = moveUp->next;
+            cuddDeallocMove(table, moveUp);
+            moveUp = move;
+        }
+    }
+
+    return(0);
+
+} /* end of ddSymmSiftingAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries.]
+
+  Description [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries. Finds the best position and does the required changes.
+  Assumes that x is either an isolated variable, or it is the bottom of
+  a symmetry group. All symmetries may not have been found, because of
+  exceeded growth limit. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSymmSiftingConvAux(
+  DdManager * table,
+  int  x,
+  int  xLow,
+  int  xHigh)
+{
+    Move *move;
+    Move *moveUp;       /* list of up moves */
+    Move *moveDown;     /* list of down moves */
+    int  initialSize;
+    int  result;
+    int  i;
+    int  initGroupSize, finalGroupSize;
+
+
+    initialSize = table->keys - table->isolated;
+
+    moveDown = NULL;
+    moveUp = NULL;
+
+    if (x == xLow) { /* Sift down */
+#ifdef DD_DEBUG
+        /* x is bottom of symmetry group */
+        assert((unsigned) x >= table->subtables[x].next);
+#endif
+        i = table->subtables[x].next;
+        initGroupSize = x - i + 1;
+
+        moveDown = ddSymmSiftingDown(table,x,xHigh);
+        /* at this point x == xHigh, unless early term */
+        if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
+        if (moveDown == NULL) return(1);
+
+        x = moveDown->y;
+        i = x;
+        while ((unsigned) i < table->subtables[i].next) {
+            i = table->subtables[i].next;
+        }
+#ifdef DD_DEBUG
+        /* x should be the top of the symmetric group and i the bottom */
+        assert((unsigned) i >= table->subtables[i].next);
+        assert((unsigned) x == table->subtables[i].next);
+#endif
+        finalGroupSize = i - x + 1;
+
+        if (initGroupSize == finalGroupSize) {
+            /* No new symmetries detected, go back to best position */
+            result = ddSymmSiftingBackward(table,moveDown,initialSize);
+        } else {
+            initialSize = table->keys - table->isolated;
+            moveUp = ddSymmSiftingUp(table,x,xLow);
+            result = ddSymmSiftingBackward(table,moveUp,initialSize);
+        }
+        if (!result) goto ddSymmSiftingConvAuxOutOfMem;
+
+    } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
+        /* Find top of x's symm group */
+        while ((unsigned) x < table->subtables[x].next)
+            x = table->subtables[x].next;
+        i = x;                          /* bottom */
+        x = table->subtables[x].next;   /* top */
+
+        if (x == xLow) return(1);
+
+        initGroupSize = i - x + 1;
+
+        moveUp = ddSymmSiftingUp(table,x,xLow);
+            /* at this point x == xLow, unless early term */
+        if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
+        if (moveUp == NULL) return(1);
+
+        x = moveUp->x;
+        i = table->subtables[x].next;
+#ifdef DD_DEBUG
+        /* x should be the bottom of the symmetry group and i the top */
+        assert((unsigned) x >= table->subtables[x].next);
+        assert((unsigned) i == table->subtables[x].next);
+#endif
+        finalGroupSize = x - i + 1;
+
+        if (initGroupSize == finalGroupSize) {
+            /* No new symmetry groups detected, return to best position */
+            result = ddSymmSiftingBackward(table,moveUp,initialSize);
+        } else {
+            initialSize = table->keys - table->isolated;
+            moveDown = ddSymmSiftingDown(table,x,xHigh);
+            result = ddSymmSiftingBackward(table,moveDown,initialSize);
+        }
+        if (!result)
+            goto ddSymmSiftingConvAuxOutOfMem;
+
+    } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
+        moveDown = ddSymmSiftingDown(table,x,xHigh);
+            /* at this point x == xHigh, unless early term */
+        if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
+
+        if (moveDown != NULL) {
+            x = moveDown->y;
+            i = x;
+            while ((unsigned) i < table->subtables[i].next) {
+                i = table->subtables[i].next;
+            }
+        } else {
+            while ((unsigned) x < table->subtables[x].next)
+                x = table->subtables[x].next;
+            i = x;
+            x = table->subtables[x].next;
+        }
+#ifdef DD_DEBUG
+        /* x should be the top of the symmetry group and i the bottom */
+        assert((unsigned) i >= table->subtables[i].next);
+        assert((unsigned) x == table->subtables[i].next);
+#endif
+        initGroupSize = i - x + 1;
+
+        moveUp = ddSymmSiftingUp(table,x,xLow);
+        if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
+
+        if (moveUp != NULL) {
+            x = moveUp->x;
+            i = table->subtables[x].next;
+        } else {
+            i = x;
+            while ((unsigned) x < table->subtables[x].next)
+                x = table->subtables[x].next;
+        }
+#ifdef DD_DEBUG
+        /* x should be the bottom of the symmetry group and i the top */
+        assert((unsigned) x >= table->subtables[x].next);
+        assert((unsigned) i == table->subtables[x].next);
+#endif
+        finalGroupSize = x - i + 1;
+
+        if (initGroupSize == finalGroupSize) {
+            /* No new symmetry groups detected, return to best position */
+            result = ddSymmSiftingBackward(table,moveUp,initialSize);
+        } else {
+            while (moveDown != NULL) {
+                move = moveDown->next;
+                cuddDeallocMove(table, moveDown);
+                moveDown = move;
+            }
+            initialSize = table->keys - table->isolated;
+            moveDown = ddSymmSiftingDown(table,x,xHigh);
+            result = ddSymmSiftingBackward(table,moveDown,initialSize);
+        }
+        if (!result) goto ddSymmSiftingConvAuxOutOfMem;
+
+    } else { /* moving up first: shorter */
+        /* Find top of x's symmetry group */
+        x = table->subtables[x].next;
+
+        moveUp = ddSymmSiftingUp(table,x,xLow);
+        /* at this point x == xHigh, unless early term */
+        if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
+
+        if (moveUp != NULL) {
+            x = moveUp->x;
+            i = table->subtables[x].next;
+        } else {
+            i = x;
+            while ((unsigned) x < table->subtables[x].next)
+                x = table->subtables[x].next;
+        }
+#ifdef DD_DEBUG
+        /* x is bottom of the symmetry group and i is top */
+        assert((unsigned) x >= table->subtables[x].next);
+        assert((unsigned) i == table->subtables[x].next);
+#endif
+        initGroupSize = x - i + 1;
+
+        moveDown = ddSymmSiftingDown(table,x,xHigh);
+        if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
+
+        if (moveDown != NULL) {
+            x = moveDown->y;
+            i = x;
+            while ((unsigned) i < table->subtables[i].next) {
+                i = table->subtables[i].next;
+            }
+        } else {
+            i = x;
+            x = table->subtables[x].next;
+        }
+#ifdef DD_DEBUG
+        /* x should be the top of the symmetry group and i the bottom */
+        assert((unsigned) i >= table->subtables[i].next);
+        assert((unsigned) x == table->subtables[i].next);
+#endif
+        finalGroupSize = i - x + 1;
+
+        if (initGroupSize == finalGroupSize) {
+            /* No new symmetries detected, go back to best position */
+            result = ddSymmSiftingBackward(table,moveDown,initialSize);
+        } else {
+            while (moveUp != NULL) {
+                move = moveUp->next;
+                cuddDeallocMove(table, moveUp);
+                moveUp = move;
+            }
+            initialSize = table->keys - table->isolated;
+            moveUp = ddSymmSiftingUp(table,x,xLow);
+            result = ddSymmSiftingBackward(table,moveUp,initialSize);
+        }
+        if (!result) goto ddSymmSiftingConvAuxOutOfMem;
+    }
+
+    while (moveDown != NULL) {
+        move = moveDown->next;
+        cuddDeallocMove(table, moveDown);
+        moveDown = move;
+    }
+    while (moveUp != NULL) {
+        move = moveUp->next;
+        cuddDeallocMove(table, moveUp);
+        moveUp = move;
+    }
+
+    return(1);
+
+ddSymmSiftingConvAuxOutOfMem:
+    if (moveDown != MV_OOM) {
+        while (moveDown != NULL) {
+            move = moveDown->next;
+            cuddDeallocMove(table, moveDown);
+            moveDown = move;
+        }
+    }
+    if (moveUp != MV_OOM) {
+        while (moveUp != NULL) {
+            move = moveUp->next;
+            cuddDeallocMove(table, moveUp);
+            moveUp = move;
+        }
+    }
+
+    return(0);
+
+} /* end of ddSymmSiftingConvAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves x up until either it reaches the bound (xLow) or
+  the size of the DD heap increases too much.]
+
+  Description [Moves x up until either it reaches the bound (xLow) or
+  the size of the DD heap increases too much. Assumes that x is the top
+  of a symmetry group.  Checks x for symmetry to the adjacent
+  variables. If symmetry is found, the symmetry group of x is merged
+  with the symmetry group of the other variable. Returns the set of
+  moves in case of success; MV_OOM if memory is full.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move *
+ddSymmSiftingUp(
+  DdManager * table,
+  int  y,
+  int  xLow)
+{
+    Move *moves;
+    Move *move;
+    int  x;
+    int  size;
+    int  i;
+    int  gxtop,gybot;
+    int  limitSize;
+    int  xindex, yindex;
+    int  zindex;
+    int  z;
+    int  isolated;
+    int  L;     /* lower bound on DD size */
+#ifdef DD_DEBUG
+    int  checkL;
+#endif
+
+
+    moves = NULL;
+    yindex = table->invperm[y];
+
+    /* Initialize the lower bound.
+    ** The part of the DD below the bottom of y' group will not change.
+    ** The part of the DD above y that does not interact with y will not
+    ** change. The rest may vanish in the best case, except for
+    ** the nodes at level xLow, which will not vanish, regardless.
+    */
+    limitSize = L = table->keys - table->isolated;
+    gybot = y;
+    while ((unsigned) gybot < table->subtables[gybot].next)
+        gybot = table->subtables[gybot].next;
+    for (z = xLow + 1; z <= gybot; z++) {
+        zindex = table->invperm[z];
+        if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
+            isolated = table->vars[zindex]->ref == 1;
+            L -= table->subtables[z].keys - isolated;
+        }
+    }
+
+    x = cuddNextLow(table,y);
+    while (x >= xLow && L <= limitSize) {
+#ifdef DD_DEBUG
+        gybot = y;
+        while ((unsigned) gybot < table->subtables[gybot].next)
+            gybot = table->subtables[gybot].next;
+        checkL = table->keys - table->isolated;
+        for (z = xLow + 1; z <= gybot; z++) {
+            zindex = table->invperm[z];
+            if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
+                isolated = table->vars[zindex]->ref == 1;
+                checkL -= table->subtables[z].keys - isolated;
+            }
+        }
+        assert(L == checkL);
+#endif
+        gxtop = table->subtables[x].next;
+        if (cuddSymmCheck(table,x,y)) {
+            /* Symmetry found, attach symm groups */
+            table->subtables[x].next = y;
+            i = table->subtables[y].next;
+            while (table->subtables[i].next != (unsigned) y)
+                i = table->subtables[i].next;
+            table->subtables[i].next = gxtop;
+        } else if (table->subtables[x].next == (unsigned) x &&
+                   table->subtables[y].next == (unsigned) y) {
+            /* x and y have self symmetry */
+            xindex = table->invperm[x];
+            size = cuddSwapInPlace(table,x,y);
+#ifdef DD_DEBUG
+            assert(table->subtables[x].next == (unsigned) x);
+            assert(table->subtables[y].next == (unsigned) y);
+#endif
+            if (size == 0) goto ddSymmSiftingUpOutOfMem;
+            /* Update the lower bound. */
+            if (cuddTestInteract(table,xindex,yindex)) {
+                isolated = table->vars[xindex]->ref == 1;
+                L += table->subtables[y].keys - isolated;
+            }
+            move = (Move *) cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddSymmSiftingUpOutOfMem;
+            move->x = x;
+            move->y = y;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+            if ((double) size > (double) limitSize * table->maxGrowth)
+                return(moves);
+            if (size < limitSize) limitSize = size;
+        } else { /* Group move */
+            size = ddSymmGroupMove(table,x,y,&moves);
+            if (size == 0) goto ddSymmSiftingUpOutOfMem;
+            /* Update the lower bound. */
+            z = moves->y;
+            do {
+                zindex = table->invperm[z];
+                if (cuddTestInteract(table,zindex,yindex)) {
+                    isolated = table->vars[zindex]->ref == 1;
+                    L += table->subtables[z].keys - isolated;
+                }
+                z = table->subtables[z].next;
+            } while (z != (int) moves->y);
+            if ((double) size > (double) limitSize * table->maxGrowth)
+                return(moves);
+            if (size < limitSize) limitSize = size;
+        }
+        y = gxtop;
+        x = cuddNextLow(table,y);
+    }
+
+    return(moves);
+
+ddSymmSiftingUpOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return(MV_OOM);
+
+} /* end of ddSymmSiftingUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves x down until either it reaches the bound (xHigh) or
+  the size of the DD heap increases too much.]
+
+  Description [Moves x down until either it reaches the bound (xHigh)
+  or the size of the DD heap increases too much. Assumes that x is the
+  bottom of a symmetry group. Checks x for symmetry to the adjacent
+  variables. If symmetry is found, the symmetry group of x is merged
+  with the symmetry group of the other variable. Returns the set of
+  moves in case of success; MV_OOM if memory is full.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move *
+ddSymmSiftingDown(
+  DdManager * table,
+  int  x,
+  int  xHigh)
+{
+    Move *moves;
+    Move *move;
+    int  y;
+    int  size;
+    int  limitSize;
+    int  gxtop,gybot;
+    int  R;     /* upper bound on node decrease */
+    int  xindex, yindex;
+    int  isolated;
+    int  z;
+    int  zindex;
+#ifdef DD_DEBUG
+    int  checkR;
+#endif
+
+    moves = NULL;
+    /* Initialize R */
+    xindex = table->invperm[x];
+    gxtop = table->subtables[x].next;
+    limitSize = size = table->keys - table->isolated;
+    R = 0;
+    for (z = xHigh; z > gxtop; z--) {
+        zindex = table->invperm[z];
+        if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
+            isolated = table->vars[zindex]->ref == 1;
+            R += table->subtables[z].keys - isolated;
+        }
+    }
+
+    y = cuddNextHigh(table,x);
+    while (y <= xHigh && size - R < limitSize) {
+#ifdef DD_DEBUG
+        gxtop = table->subtables[x].next;
+        checkR = 0;
+        for (z = xHigh; z > gxtop; z--) {
+            zindex = table->invperm[z];
+            if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
+                isolated = table->vars[zindex]->ref == 1;
+                checkR += table->subtables[z].keys - isolated;
+            }
+        }
+        assert(R == checkR);
+#endif
+        gybot = table->subtables[y].next;
+        while (table->subtables[gybot].next != (unsigned) y)
+            gybot = table->subtables[gybot].next;
+        if (cuddSymmCheck(table,x,y)) {
+            /* Symmetry found, attach symm groups */
+            gxtop = table->subtables[x].next;
+            table->subtables[x].next = y;
+            table->subtables[gybot].next = gxtop;
+        } else if (table->subtables[x].next == (unsigned) x &&
+                   table->subtables[y].next == (unsigned) y) {
+            /* x and y have self symmetry */
+            /* Update upper bound on node decrease. */
+            yindex = table->invperm[y];
+            if (cuddTestInteract(table,xindex,yindex)) {
+                isolated = table->vars[yindex]->ref == 1;
+                R -= table->subtables[y].keys - isolated;
+            }
+            size = cuddSwapInPlace(table,x,y);
+#ifdef DD_DEBUG
+            assert(table->subtables[x].next == (unsigned) x);
+            assert(table->subtables[y].next == (unsigned) y);
+#endif
+            if (size == 0) goto ddSymmSiftingDownOutOfMem;
+            move = (Move *) cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddSymmSiftingDownOutOfMem;
+            move->x = x;
+            move->y = y;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+            if ((double) size > (double) limitSize * table->maxGrowth)
+                return(moves);
+            if (size < limitSize) limitSize = size;
+        } else { /* Group move */
+            /* Update upper bound on node decrease: first phase. */
+            gxtop = table->subtables[x].next;
+            z = gxtop + 1;
+            do {
+                zindex = table->invperm[z];
+                if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
+                    isolated = table->vars[zindex]->ref == 1;
+                    R -= table->subtables[z].keys - isolated;
+                }
+                z++;
+            } while (z <= gybot);
+            size = ddSymmGroupMove(table,x,y,&moves);
+            if (size == 0) goto ddSymmSiftingDownOutOfMem;
+            if ((double) size > (double) limitSize * table->maxGrowth)
+                return(moves);
+            if (size < limitSize) limitSize = size;
+            /* Update upper bound on node decrease: second phase. */
+            gxtop = table->subtables[gybot].next;
+            for (z = gxtop + 1; z <= gybot; z++) {
+                zindex = table->invperm[z];
+                if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
+                    isolated = table->vars[zindex]->ref == 1;
+                    R += table->subtables[z].keys - isolated;
+                }
+            }
+        }
+        x = gybot;
+        y = cuddNextHigh(table,x);
+    }
+
+    return(moves);
+
+ddSymmSiftingDownOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return(MV_OOM);
+
+} /* end of ddSymmSiftingDown */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Swaps two groups.]
+
+  Description [Swaps two groups. x is assumed to be the bottom variable
+  of the first group. y is assumed to be the top variable of the second
+  group.  Updates the list of moves. Returns the number of keys in the
+  table if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSymmGroupMove(
+  DdManager * table,
+  int  x,
+  int  y,
+  Move ** moves)
+{
+    Move *move;
+    int  size = -1;
+    int  i,j;
+    int  xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
+    int  swapx = -1,swapy = -1;
+
+#ifdef DD_DEBUG
+    assert(x < y);      /* we assume that x < y */
+#endif
+    /* Find top, bottom, and size for the two groups. */
+    xbot = x;
+    xtop = table->subtables[x].next;
+    xsize = xbot - xtop + 1;
+    ybot = y;
+    while ((unsigned) ybot < table->subtables[ybot].next)
+        ybot = table->subtables[ybot].next;
+    ytop = y;
+    ysize = ybot - ytop + 1;
+
+    /* Sift the variables of the second group up through the first group. */
+    for (i = 1; i <= ysize; i++) {
+        for (j = 1; j <= xsize; j++) {
+            size = cuddSwapInPlace(table,x,y);
+            if (size == 0) return(0);
+            swapx = x; swapy = y;
+            y = x;
+            x = y - 1;
+        }
+        y = ytop + i;
+        x = y - 1;
+    }
+
+    /* fix symmetries */
+    y = xtop; /* ytop is now where xtop used to be */
+    for (i = 0; i < ysize-1 ; i++) {
+        table->subtables[y].next = y + 1;
+        y = y + 1;
+    }
+    table->subtables[y].next = xtop; /* y is bottom of its group, join */
+                                     /* its symmetry to top of its group */
+    x = y + 1;
+    newxtop = x;
+    for (i = 0; i < xsize - 1 ; i++) {
+        table->subtables[x].next = x + 1;
+        x = x + 1;
+    }
+    table->subtables[x].next = newxtop; /* x is bottom of its group, join */
+                                        /* its symmetry to top of its group */
+    /* Store group move */
+    move = (Move *) cuddDynamicAllocNode(table);
+    if (move == NULL) return(0);
+    move->x = swapx;
+    move->y = swapy;
+    move->size = size;
+    move->next = *moves;
+    *moves = move;
+
+    return(size);
+
+} /* end of ddSymmGroupMove */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Undoes the swap of two groups.]
+
+  Description [Undoes the swap of two groups. x is assumed to be the
+  bottom variable of the first group. y is assumed to be the top
+  variable of the second group.  Returns the number of keys in the table
+  if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSymmGroupMoveBackward(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int size = -1;
+    int i,j;
+    int xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
+
+#ifdef DD_DEBUG
+    assert(x < y); /* We assume that x < y */
+#endif
+
+    /* Find top, bottom, and size for the two groups. */
+    xbot = x;
+    xtop = table->subtables[x].next;
+    xsize = xbot - xtop + 1;
+    ybot = y;
+    while ((unsigned) ybot < table->subtables[ybot].next)
+        ybot = table->subtables[ybot].next;
+    ytop = y;
+    ysize = ybot - ytop + 1;
+
+    /* Sift the variables of the second group up through the first group. */
+    for (i = 1; i <= ysize; i++) {
+        for (j = 1; j <= xsize; j++) {
+            size = cuddSwapInPlace(table,x,y);
+            if (size == 0) return(0);
+            y = x;
+            x = cuddNextLow(table,y);
+        }
+        y = ytop + i;
+        x = y - 1;
+    }
+
+    /* Fix symmetries. */
+    y = xtop;
+    for (i = 0; i < ysize-1 ; i++) {
+        table->subtables[y].next = y + 1;
+        y = y + 1;
+    }
+    table->subtables[y].next = xtop; /* y is bottom of its group, join */
+                                     /* its symmetry to top of its group */
+    x = y + 1;
+    newxtop = x;
+    for (i = 0; i < xsize-1 ; i++) {
+        table->subtables[x].next = x + 1;
+        x = x + 1;
+    }
+    table->subtables[x].next = newxtop; /* x is bottom of its group, join */
+                                        /* its symmetry to top of its group */
+
+    return(size);
+
+} /* end of ddSymmGroupMoveBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given a set of moves, returns the DD heap to the position
+  giving the minimum size.]
+
+  Description [Given a set of moves, returns the DD heap to the
+  position giving the minimum size. In case of ties, returns to the
+  closest position giving the minimum size. Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSymmSiftingBackward(
+  DdManager * table,
+  Move * moves,
+  int  size)
+{
+    Move *move;
+    int  res = -1;
+
+    for (move = moves; move != NULL; move = move->next) {
+        if (move->size < size) {
+            size = move->size;
+        }
+    }
+
+    for (move = moves; move != NULL; move = move->next) {
+        if (move->size == size) return(1);
+        if (table->subtables[move->x].next == move->x && table->subtables[move->y].next == move->y) {
+            res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
+#ifdef DD_DEBUG
+            assert(table->subtables[move->x].next == move->x);
+            assert(table->subtables[move->y].next == move->y);
+#endif
+        } else { /* Group move necessary */
+            res = ddSymmGroupMoveBackward(table,(int)move->x,(int)move->y);
+        }
+        if (!res) return(0);
+    }
+
+    return(1);
+
+} /* end of ddSymmSiftingBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts numbers of symmetric variables and symmetry
+  groups.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+ddSymmSummary(
+  DdManager * table,
+  int  lower,
+  int  upper,
+  int * symvars,
+  int * symgroups)
+{
+    int i,x,gbot;
+    int TotalSymm = 0;
+    int TotalSymmGroups = 0;
+
+    for (i = lower; i <= upper; i++) {
+        if (table->subtables[i].next != (unsigned) i) {
+            TotalSymmGroups++;
+            x = i;
+            do {
+                TotalSymm++;
+                gbot = x;
+                x = table->subtables[x].next;
+            } while (x != i);
+#ifdef DD_DEBUG
+            assert(table->subtables[gbot].next == (unsigned) i);
+#endif
+            i = gbot;
+        }
+    }
+    *symvars = TotalSymm;
+    *symgroups = TotalSymmGroups;
+
+    return;
+
+} /* end of ddSymmSummary */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddTable.c b/abc-build/src/bdd/cudd/cuddTable.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddTable.c
@@ -0,0 +1,3179 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddTable.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Unique table management functions.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_Prime()
+                </ul>
+        Internal procedures included in this module:
+                <ul>
+                <li> cuddAllocNode()
+                <li> cuddInitTable()
+                <li> cuddFreeTable()
+                <li> cuddGarbageCollect()
+                <li> cuddZddGetNode()
+                <li> cuddZddGetNodeIVO()
+                <li> cuddUniqueInter()
+                <li> cuddUniqueInterIVO()
+                <li> cuddUniqueInterZdd()
+                <li> cuddUniqueConst()
+                <li> cuddRehash()
+                <li> cuddShrinkSubtable()
+                <li> cuddInsertSubtables()
+                <li> cuddDestroySubtables()
+                <li> cuddResizeTableZdd()
+                <li> cuddSlowTableGrowth()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> ddRehashZdd()
+                <li> ddResizeTable()
+                <li> cuddFindParent()
+                <li> cuddOrderedInsert()
+                <li> cuddOrderedThread()
+                <li> cuddRotateLeft()
+                <li> cuddRotateRight()
+                <li> cuddDoRebalance()
+                <li> cuddCheckCollisionOrdering()
+                </ul>]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+/* Constants for red/black trees. */
+#define DD_STACK_SIZE 128
+#define DD_RED   0
+#define DD_BLACK 1
+#define DD_PAGE_SIZE 8192
+#define DD_PAGE_MASK ~(DD_PAGE_SIZE - 1)
+#endif
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* This is a hack for when CUDD_VALUE_TYPE is double */
+typedef union hack {
+    CUDD_VALUE_TYPE value;
+    unsigned int bits[2];
+} hack;
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddTable.c,v 1.122 2009/02/19 16:24:28 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+/* Macros for red/black trees. */
+#define DD_INSERT_COMPARE(x,y) \
+        (((ptruint) (x) & DD_PAGE_MASK) - ((ptruint) (y) & DD_PAGE_MASK))
+#define DD_COLOR(p)  ((p)->index)
+#define DD_IS_BLACK(p) ((p)->index == DD_BLACK)
+#define DD_IS_RED(p) ((p)->index == DD_RED)
+#define DD_LEFT(p) cuddT(p)
+#define DD_RIGHT(p) cuddE(p)
+#define DD_NEXT(p) ((p)->next)
+#endif
+#endif
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void ddRehashZdd (DdManager *unique, int i);
+static int ddResizeTable (DdManager *unique, int index);
+static int cuddFindParent (DdManager *table, DdNode *node);
+DD_INLINE static void ddFixLimits (DdManager *unique);
+#ifdef DD_RED_BLACK_FREE_LIST
+static void cuddOrderedInsert (DdNodePtr *root, DdNodePtr node);
+static DdNode * cuddOrderedThread (DdNode *root, DdNode *list);
+static void cuddRotateLeft (DdNodePtr *nodeP);
+static void cuddRotateRight (DdNodePtr *nodeP);
+static void cuddDoRebalance (DdNodePtr **stack, int stackN);
+#endif
+static void ddPatchTree (DdManager *dd, MtrNode *treenode);
+#ifdef DD_DEBUG
+static int cuddCheckCollisionOrdering (DdManager *unique, int i, int j);
+#endif
+static void ddReportRefMess (DdManager *unique, int i, const char *caller);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the next prime &gt;= p.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+unsigned int
+Cudd_Prime(
+  unsigned int  p)
+{
+    int i,pn;
+
+    p--;
+    do {
+        p++;
+        if (p&1) {
+            pn = 1;
+            i = 3;
+            while ((unsigned) (i * i) <= p) {
+                if (p % i == 0) {
+                    pn = 0;
+                    break;
+                }
+                i += 2;
+            }
+        } else {
+            pn = 0;
+        }
+    } while (!pn);
+    return(p);
+
+} /* end of Cudd_Prime */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Fast storage allocation for DdNodes in the table.]
+
+  Description [Fast storage allocation for DdNodes in the table. The
+  first 4 bytes of a chunk contain a pointer to the next block; the
+  rest contains DD_MEM_CHUNK spaces for DdNodes.  Returns a pointer to
+  a new node if successful; NULL is memory is full.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddDynamicAllocNode]
+
+******************************************************************************/
+DdNode *
+cuddAllocNode(
+  DdManager * unique)
+{
+    int i;
+    DdNodePtr *mem;
+    DdNode *list, *node;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    if (unique->nextFree == NULL) {     /* free list is empty */
+        /* Check for exceeded limits. */
+        if ((unique->keys - unique->dead) + (unique->keysZ - unique->deadZ) >
+            unique->maxLive) {
+            unique->errorCode = CUDD_TOO_MANY_NODES;
+            return(NULL);
+        }
+        if (unique->stash == NULL || unique->memused > unique->maxmemhard) {
+            (void) cuddGarbageCollect(unique,1);
+            mem = NULL;
+        }
+        if (unique->nextFree == NULL) {
+            if (unique->memused > unique->maxmemhard) {
+                unique->errorCode = CUDD_MAX_MEM_EXCEEDED;
+                return(NULL);
+            }
+            /* Try to allocate a new block. */
+            saveHandler = MMoutOfMemory;
+            MMoutOfMemory = Cudd_OutOfMem;
+//            mem = (DdNodePtr *) ABC_ALLOC(DdNode,DD_MEM_CHUNK + 1);
+            mem = (DdNodePtr *) ABC_ALLOC(DdNode,DD_MEM_CHUNK + 2);
+            MMoutOfMemory = saveHandler;
+            if (mem == NULL) {
+                /* No more memory: Try collecting garbage. If this succeeds,
+                ** we end up with mem still NULL, but unique->nextFree !=
+                ** NULL. */
+                if (cuddGarbageCollect(unique,1) == 0) {
+                    /* Last resort: Free the memory stashed away, if there
+                    ** any. If this succeeeds, mem != NULL and
+                    ** unique->nextFree still NULL. */
+                    if (unique->stash != NULL) {
+                        ABC_FREE(unique->stash);
+                        unique->stash = NULL;
+                        /* Inhibit resizing of tables. */
+                        cuddSlowTableGrowth(unique);
+                        /* Now try again. */
+//                        mem = (DdNodePtr *) ABC_ALLOC(DdNode,DD_MEM_CHUNK + 1);
+                        mem = (DdNodePtr *) ABC_ALLOC(DdNode,DD_MEM_CHUNK + 2);
+                    }
+                    if (mem == NULL) {
+                        /* Out of luck. Call the default handler to do
+                        ** whatever it specifies for a failed malloc.
+                        ** If this handler returns, then set error code,
+                        ** print warning, and return. */
+                        (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1));
+                        unique->errorCode = CUDD_MEMORY_OUT;
+#ifdef DD_VERBOSE
+                        (void) fprintf(unique->err,
+                                       "cuddAllocNode: out of memory");
+                        (void) fprintf(unique->err, "Memory in use = %lu\n",
+                                       unique->memused);
+#endif
+                        return(NULL);
+                    }
+                }
+            }
+            if (mem != NULL) {  /* successful allocation; slice memory */
+                ptruint offset;
+                unique->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode);
+                mem[0] = (DdNodePtr) unique->memoryList;
+                unique->memoryList = mem;
+
+                /* Here we rely on the fact that a DdNode is as large as 4 pointers.  */
+//                offset = (ptruint) mem & (sizeof(DdNode) - 1);
+//                mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
+//                assert(((ptruint) mem & (sizeof(DdNode) - 1)) == 0);
+//                list = (DdNode *) mem;
+                offset = (ptruint) mem & (32 - 1);
+                mem += (32 - offset) / sizeof(DdNodePtr);
+                assert(((ptruint) mem & (32 - 1)) == 0);
+                list = (DdNode *) mem;
+
+                i = 1;
+                do {
+                    list[i - 1].ref = 0;
+                    list[i - 1].next = &list[i];
+                } while (++i < DD_MEM_CHUNK);
+
+                list[DD_MEM_CHUNK-1].ref = 0;
+                list[DD_MEM_CHUNK-1].next = NULL;
+
+                unique->nextFree = &list[0];
+            }
+        }
+    }
+    unique->allocated++;
+    node = unique->nextFree;
+    unique->nextFree = node->next;
+    node->Id = (unique->allocated<<4);
+    return(node);
+
+} /* end of cuddAllocNode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates and initializes the unique table.]
+
+  Description [Creates and initializes the unique table. Returns a pointer
+  to the table if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Init cuddFreeTable]
+
+******************************************************************************/
+DdManager *
+cuddInitTable(
+  unsigned int numVars  /* Initial number of BDD variables (and subtables) */,
+  unsigned int numVarsZ /* Initial number of ZDD variables (and subtables) */,
+  unsigned int numSlots /* Initial size of the BDD subtables */,
+  unsigned int looseUpTo /* Limit for fast table growth */)
+{
+    DdManager   *unique = ABC_ALLOC(DdManager,1);
+    int         i, j;
+    DdNodePtr   *nodelist;
+    DdNode      *sentinel;
+    unsigned int slots;
+    int shift;
+
+    if (unique == NULL) {
+        return(NULL);
+    }
+    sentinel = &(unique->sentinel);
+    sentinel->ref = 0;
+    sentinel->index = 0;
+    cuddT(sentinel) = NULL;
+    cuddE(sentinel) = NULL;
+    sentinel->next = NULL;
+    unique->epsilon = DD_EPSILON;
+    unique->maxGrowth = DD_MAX_REORDER_GROWTH;
+    unique->maxGrowthAlt = 2.0 * DD_MAX_REORDER_GROWTH;
+    unique->reordCycle = 0;     /* do not use alternate threshold */
+    unique->size = numVars;
+    unique->sizeZ = numVarsZ;
+    unique->maxSize = ddMax(DD_DEFAULT_RESIZE, numVars);
+    unique->maxSizeZ = ddMax(DD_DEFAULT_RESIZE, numVarsZ);
+
+    /* Adjust the requested number of slots to a power of 2. */
+    slots = 8;
+    while (slots < numSlots) {
+        slots <<= 1;
+    }
+    unique->initSlots = slots;
+    shift = sizeof(int) * 8 - cuddComputeFloorLog2(slots);
+
+    unique->slots = (numVars + numVarsZ + 1) * slots;
+    unique->keys = 0;
+    unique->maxLive = ~0;       /* very large number */
+    unique->keysZ = 0;
+    unique->dead = 0;
+    unique->deadZ = 0;
+    unique->gcFrac = DD_GC_FRAC_HI;
+    unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots);
+    unique->looseUpTo = looseUpTo;
+    unique->gcEnabled = 1;
+    unique->allocated = 0;
+    unique->reclaimed = 0;
+    unique->subtables = ABC_ALLOC(DdSubtable,unique->maxSize);
+    if (unique->subtables == NULL) {
+        ABC_FREE(unique);
+        return(NULL);
+    }
+    unique->subtableZ = ABC_ALLOC(DdSubtable,unique->maxSizeZ);
+    if (unique->subtableZ == NULL) {
+        ABC_FREE(unique->subtables);
+        ABC_FREE(unique);
+        return(NULL);
+    }
+    unique->perm = ABC_ALLOC(int,unique->maxSize);
+    if (unique->perm == NULL) {
+        ABC_FREE(unique->subtables);
+        ABC_FREE(unique->subtableZ);
+        ABC_FREE(unique);
+        return(NULL);
+    }
+    unique->invperm = ABC_ALLOC(int,unique->maxSize);
+    if (unique->invperm == NULL) {
+        ABC_FREE(unique->subtables);
+        ABC_FREE(unique->subtableZ);
+        ABC_FREE(unique->perm);
+        ABC_FREE(unique);
+        return(NULL);
+    }
+    unique->permZ = ABC_ALLOC(int,unique->maxSizeZ);
+    if (unique->permZ == NULL) {
+        ABC_FREE(unique->subtables);
+        ABC_FREE(unique->subtableZ);
+        ABC_FREE(unique->perm);
+        ABC_FREE(unique->invperm);
+        ABC_FREE(unique);
+        return(NULL);
+    }
+    unique->invpermZ = ABC_ALLOC(int,unique->maxSizeZ);
+    if (unique->invpermZ == NULL) {
+        ABC_FREE(unique->subtables);
+        ABC_FREE(unique->subtableZ);
+        ABC_FREE(unique->perm);
+        ABC_FREE(unique->invperm);
+        ABC_FREE(unique->permZ);
+        ABC_FREE(unique);
+        return(NULL);
+    }
+    unique->map = NULL;
+    unique->stack = ABC_ALLOC(DdNodePtr,ddMax(unique->maxSize,unique->maxSizeZ)+1);
+    if (unique->stack == NULL) {
+        ABC_FREE(unique->subtables);
+        ABC_FREE(unique->subtableZ);
+        ABC_FREE(unique->perm);
+        ABC_FREE(unique->invperm);
+        ABC_FREE(unique->permZ);
+        ABC_FREE(unique->invpermZ);
+        ABC_FREE(unique);
+        return(NULL);
+    }
+    unique->stack[0] = NULL; /* to suppress harmless UMR */
+
+#ifndef DD_NO_DEATH_ROW
+    unique->deathRowDepth = 1 << cuddComputeFloorLog2(unique->looseUpTo >> 2);
+    unique->deathRow = ABC_ALLOC(DdNodePtr,unique->deathRowDepth);
+    if (unique->deathRow == NULL) {
+        ABC_FREE(unique->subtables);
+        ABC_FREE(unique->subtableZ);
+        ABC_FREE(unique->perm);
+        ABC_FREE(unique->invperm);
+        ABC_FREE(unique->permZ);
+        ABC_FREE(unique->invpermZ);
+        ABC_FREE(unique->stack);
+        ABC_FREE(unique);
+        return(NULL);
+    }
+    for (i = 0; i < unique->deathRowDepth; i++) {
+        unique->deathRow[i] = NULL;
+    }
+    unique->nextDead = 0;
+    unique->deadMask = unique->deathRowDepth - 1;
+#endif
+
+    for (i = 0; (unsigned) i < numVars; i++) {
+        unique->subtables[i].slots = slots;
+        unique->subtables[i].shift = shift;
+        unique->subtables[i].keys = 0;
+        unique->subtables[i].dead = 0;
+        unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
+        unique->subtables[i].bindVar = 0;
+        unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT;
+        unique->subtables[i].pairIndex = 0;
+        unique->subtables[i].varHandled = 0;
+        unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE;
+
+        nodelist = unique->subtables[i].nodelist = ABC_ALLOC(DdNodePtr,slots);
+        if (nodelist == NULL) {
+            for (j = 0; j < i; j++) {
+                ABC_FREE(unique->subtables[j].nodelist);
+            }
+            ABC_FREE(unique->subtables);
+            ABC_FREE(unique->subtableZ);
+            ABC_FREE(unique->perm);
+            ABC_FREE(unique->invperm);
+            ABC_FREE(unique->permZ);
+            ABC_FREE(unique->invpermZ);
+            ABC_FREE(unique->stack);
+            ABC_FREE(unique);
+            return(NULL);
+        }
+        for (j = 0; (unsigned) j < slots; j++) {
+            nodelist[j] = sentinel;
+        }
+        unique->perm[i] = i;
+        unique->invperm[i] = i;
+    }
+    for (i = 0; (unsigned) i < numVarsZ; i++) {
+        unique->subtableZ[i].slots = slots;
+        unique->subtableZ[i].shift = shift;
+        unique->subtableZ[i].keys = 0;
+        unique->subtableZ[i].dead = 0;
+        unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
+        nodelist = unique->subtableZ[i].nodelist = ABC_ALLOC(DdNodePtr,slots);
+        if (nodelist == NULL) {
+            for (j = 0; (unsigned) j < numVars; j++) {
+                ABC_FREE(unique->subtables[j].nodelist);
+            }
+            ABC_FREE(unique->subtables);
+            for (j = 0; j < i; j++) {
+                ABC_FREE(unique->subtableZ[j].nodelist);
+            }
+            ABC_FREE(unique->subtableZ);
+            ABC_FREE(unique->perm);
+            ABC_FREE(unique->invperm);
+            ABC_FREE(unique->permZ);
+            ABC_FREE(unique->invpermZ);
+            ABC_FREE(unique->stack);
+            ABC_FREE(unique);
+            return(NULL);
+        }
+        for (j = 0; (unsigned) j < slots; j++) {
+            nodelist[j] = NULL;
+        }
+        unique->permZ[i] = i;
+        unique->invpermZ[i] = i;
+    }
+    unique->constants.slots = slots;
+    unique->constants.shift = shift;
+    unique->constants.keys = 0;
+    unique->constants.dead = 0;
+    unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
+    nodelist = unique->constants.nodelist = ABC_ALLOC(DdNodePtr,slots);
+    if (nodelist == NULL) {
+        for (j = 0; (unsigned) j < numVars; j++) {
+            ABC_FREE(unique->subtables[j].nodelist);
+        }
+        ABC_FREE(unique->subtables);
+        for (j = 0; (unsigned) j < numVarsZ; j++) {
+            ABC_FREE(unique->subtableZ[j].nodelist);
+        }
+        ABC_FREE(unique->subtableZ);
+        ABC_FREE(unique->perm);
+        ABC_FREE(unique->invperm);
+        ABC_FREE(unique->permZ);
+        ABC_FREE(unique->invpermZ);
+        ABC_FREE(unique->stack);
+        ABC_FREE(unique);
+        return(NULL);
+    }
+    for (j = 0; (unsigned) j < slots; j++) {
+        nodelist[j] = NULL;
+    }
+
+    unique->memoryList = NULL;
+    unique->nextFree = NULL;
+
+    unique->memused = sizeof(DdManager) + (unique->maxSize + unique->maxSizeZ)
+        * (sizeof(DdSubtable) + 2 * sizeof(int)) + (numVars + 1) *
+        slots * sizeof(DdNodePtr) +
+        (ddMax(unique->maxSize,unique->maxSizeZ) + 1) * sizeof(DdNodePtr);
+#ifndef DD_NO_DEATH_ROW
+    unique->memused += unique->deathRowDepth * sizeof(DdNodePtr);
+#endif
+
+    /* Initialize fields concerned with automatic dynamic reordering */
+    unique->reorderings = 0;
+    unique->autoDyn = 0;        /* initially disabled */
+    unique->autoDynZ = 0;       /* initially disabled */
+    unique->realign = 0;        /* initially disabled */
+    unique->realignZ = 0;       /* initially disabled */
+    unique->reordered = 0;
+    unique->autoMethod = CUDD_REORDER_SIFT;
+    unique->autoMethodZ = CUDD_REORDER_SIFT;
+    unique->nextDyn = DD_FIRST_REORDER;
+    unique->countDead = ~0;
+    unique->siftMaxVar = DD_SIFT_MAX_VAR;
+    unique->siftMaxSwap = DD_SIFT_MAX_SWAPS;
+    unique->tree = NULL;
+    unique->treeZ = NULL;
+    unique->groupcheck = CUDD_GROUP_CHECK7;
+    unique->recomb = DD_DEFAULT_RECOMB;
+    unique->symmviolation = 0;
+    unique->arcviolation = 0;
+    unique->populationSize = 0;
+    unique->numberXovers = 0;
+    unique->linear = NULL;
+    unique->linearSize = 0;
+
+    /* Initialize ZDD universe. */
+    unique->univ = (DdNodePtr *)NULL;
+
+    /* Initialize auxiliary fields. */
+    unique->localCaches = NULL;
+    unique->preGCHook = NULL;
+    unique->postGCHook = NULL;
+    unique->preReorderingHook = NULL;
+    unique->postReorderingHook = NULL;
+    unique->out = stdout;
+    unique->err = stderr;
+    unique->errorCode = CUDD_NO_ERROR;
+
+    /* Initialize statistical counters. */
+    unique->maxmemhard = ~ 0UL;
+    unique->garbageCollections = 0;
+    unique->GCTime = 0;
+    unique->reordTime = 0;
+#ifdef DD_STATS
+    unique->nodesDropped = 0;
+    unique->nodesFreed = 0;
+#endif
+    unique->peakLiveNodes = 0;
+#ifdef DD_UNIQUE_PROFILE
+    unique->uniqueLookUps = 0;
+    unique->uniqueLinks = 0;
+#endif
+#ifdef DD_COUNT
+    unique->recursiveCalls = 0;
+    unique->swapSteps = 0;
+#ifdef DD_STATS
+    unique->nextSample = 250000;
+#endif
+#endif
+
+    return(unique);
+
+} /* end of cuddInitTable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the resources associated to a unique table.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddInitTable]
+
+******************************************************************************/
+void
+cuddFreeTable(
+  DdManager * unique)
+{
+    DdNodePtr *next;
+    DdNodePtr *memlist = unique->memoryList;
+    int i;
+
+    if (unique->univ != NULL) cuddZddFreeUniv(unique);
+    while (memlist != NULL) {
+        next = (DdNodePtr *) memlist[0];        /* link to next block */
+        ABC_FREE(memlist);
+        memlist = next;
+    }
+    unique->nextFree = NULL;
+    unique->memoryList = NULL;
+
+    for (i = 0; i < unique->size; i++) {
+        ABC_FREE(unique->subtables[i].nodelist);
+    }
+    for (i = 0; i < unique->sizeZ; i++) {
+        ABC_FREE(unique->subtableZ[i].nodelist);
+    }
+    ABC_FREE(unique->constants.nodelist);
+    ABC_FREE(unique->subtables);
+    ABC_FREE(unique->subtableZ);
+    ABC_FREE(unique->acache);
+    ABC_FREE(unique->perm);
+    ABC_FREE(unique->permZ);
+    ABC_FREE(unique->invperm);
+    ABC_FREE(unique->invpermZ);
+    ABC_FREE(unique->vars);
+    if (unique->map != NULL) ABC_FREE(unique->map);
+    ABC_FREE(unique->stack);
+#ifndef DD_NO_DEATH_ROW
+    ABC_FREE(unique->deathRow);
+#endif
+    if (unique->tree != NULL) Mtr_FreeTree(unique->tree);
+    if (unique->treeZ != NULL) Mtr_FreeTree(unique->treeZ);
+    if (unique->linear != NULL) ABC_FREE(unique->linear);
+    while (unique->preGCHook != NULL)
+        Cudd_RemoveHook(unique,unique->preGCHook->f,CUDD_PRE_GC_HOOK);
+    while (unique->postGCHook != NULL)
+        Cudd_RemoveHook(unique,unique->postGCHook->f,CUDD_POST_GC_HOOK);
+    while (unique->preReorderingHook != NULL)
+        Cudd_RemoveHook(unique,unique->preReorderingHook->f,
+                        CUDD_PRE_REORDERING_HOOK);
+    while (unique->postReorderingHook != NULL)
+        Cudd_RemoveHook(unique,unique->postReorderingHook->f,
+                        CUDD_POST_REORDERING_HOOK);
+    ABC_FREE(unique);
+
+} /* end of cuddFreeTable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs garbage collection on the unique tables.]
+
+  Description [Performs garbage collection on the BDD and ZDD unique tables.
+  If clearCache is 0, the cache is not cleared. This should only be
+  specified if the cache has been cleared right before calling
+  cuddGarbageCollect. (As in the case of dynamic reordering.)
+  Returns the total number of deleted nodes.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddGarbageCollect(
+  DdManager * unique,
+  int  clearCache)
+{
+    DdHook      *hook;
+    DdCache     *cache = unique->cache;
+    DdNode      *sentinel = &(unique->sentinel);
+    DdNodePtr   *nodelist;
+    int         i, j, deleted, totalDeleted, totalDeletedZ;
+    DdCache     *c;
+    DdNode      *node,*next;
+    DdNodePtr   *lastP;
+    int         slots;
+    long        localTime;
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+    DdNodePtr   tree;
+#else
+    DdNodePtr *memListTrav, *nxtNode;
+    DdNode *downTrav, *sentry;
+    int k;
+#endif
+#endif
+
+#ifndef DD_NO_DEATH_ROW
+    cuddClearDeathRow(unique);
+#endif
+
+    hook = unique->preGCHook;
+    while (hook != NULL) {
+        int res = (hook->f)(unique,"DD",NULL);
+        if (res == 0) return(0);
+        hook = hook->next;
+    }
+
+    if (unique->dead + unique->deadZ == 0) {
+        hook = unique->postGCHook;
+        while (hook != NULL) {
+            int res = (hook->f)(unique,"DD",NULL);
+            if (res == 0) return(0);
+            hook = hook->next;
+        }
+        return(0);
+    }
+
+    /* If many nodes are being reclaimed, we want to resize the tables
+    ** more aggressively, to reduce the frequency of garbage collection.
+    */
+    if (clearCache && unique->gcFrac == DD_GC_FRAC_LO &&
+        unique->slots <= unique->looseUpTo && unique->stash != NULL) {
+        unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots);
+#ifdef DD_VERBOSE
+        (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_HI);
+        (void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
+#endif
+        unique->gcFrac = DD_GC_FRAC_HI;
+        return(0);
+    }
+
+    localTime = util_cpu_time();
+
+    unique->garbageCollections++;
+#ifdef DD_VERBOSE
+    (void) fprintf(unique->err,
+                   "garbage collecting (%d dead BDD nodes out of %d, min %d)...",
+                   unique->dead, unique->keys, unique->minDead);
+    (void) fprintf(unique->err,
+                   "                   (%d dead ZDD nodes out of %d)...",
+                   unique->deadZ, unique->keysZ);
+#endif
+
+    /* Remove references to garbage collected nodes from the cache. */
+    if (clearCache) {
+        slots = unique->cacheSlots;
+        for (i = 0; i < slots; i++) {
+            c = &cache[i];
+            if (c->data != NULL) {
+                if (cuddClean(c->f)->ref == 0 ||
+                cuddClean(c->g)->ref == 0 ||
+                (((ptruint)c->f & 0x2) && Cudd_Regular(c->h)->ref == 0) ||
+                (c->data != DD_NON_CONSTANT &&
+                Cudd_Regular(c->data)->ref == 0)) {
+                    c->data = NULL;
+                    unique->cachedeletions++;
+                }
+            }
+        }
+        cuddLocalCacheClearDead(unique);
+    }
+
+    /* Now return dead nodes to free list. Count them for sanity check. */
+    totalDeleted = 0;
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+    tree = NULL;
+#endif
+#endif
+
+    for (i = 0; i < unique->size; i++) {
+        if (unique->subtables[i].dead == 0) continue;
+        nodelist = unique->subtables[i].nodelist;
+
+        deleted = 0;
+        slots = unique->subtables[i].slots;
+        for (j = 0; j < slots; j++) {
+            lastP = &(nodelist[j]);
+            node = *lastP;
+            while (node != sentinel) {
+                next = node->next;
+                if (node->ref == 0) {
+                    deleted++;
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+                    cuddOrderedInsert(&tree,node);
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+#endif
+#else
+                    cuddDeallocNode(unique,node);
+#endif
+                } else {
+                    *lastP = node;
+                    lastP = &(node->next);
+                }
+                node = next;
+            }
+            *lastP = sentinel;
+        }
+        if ((unsigned) deleted != unique->subtables[i].dead) {
+            ddReportRefMess(unique, i, "cuddGarbageCollect");
+        }
+        totalDeleted += deleted;
+        unique->subtables[i].keys -= deleted;
+        unique->subtables[i].dead = 0;
+    }
+    if (unique->constants.dead != 0) {
+        nodelist = unique->constants.nodelist;
+        deleted = 0;
+        slots = unique->constants.slots;
+        for (j = 0; j < slots; j++) {
+            lastP = &(nodelist[j]);
+            node = *lastP;
+            while (node != NULL) {
+                next = node->next;
+                if (node->ref == 0) {
+                    deleted++;
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+                    cuddOrderedInsert(&tree,node);
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+#endif
+#else
+                    cuddDeallocNode(unique,node);
+#endif
+                } else {
+                    *lastP = node;
+                    lastP = &(node->next);
+                }
+                node = next;
+            }
+            *lastP = NULL;
+        }
+        if ((unsigned) deleted != unique->constants.dead) {
+            ddReportRefMess(unique, CUDD_CONST_INDEX, "cuddGarbageCollect");
+        }
+        totalDeleted += deleted;
+        unique->constants.keys -= deleted;
+        unique->constants.dead = 0;
+    }
+    if ((unsigned) totalDeleted != unique->dead) {
+        ddReportRefMess(unique, -1, "cuddGarbageCollect");
+    }
+    unique->keys -= totalDeleted;
+    unique->dead = 0;
+#ifdef DD_STATS
+    unique->nodesFreed += (double) totalDeleted;
+#endif
+
+    totalDeletedZ = 0;
+
+    for (i = 0; i < unique->sizeZ; i++) {
+        if (unique->subtableZ[i].dead == 0) continue;
+        nodelist = unique->subtableZ[i].nodelist;
+
+        deleted = 0;
+        slots = unique->subtableZ[i].slots;
+        for (j = 0; j < slots; j++) {
+            lastP = &(nodelist[j]);
+            node = *lastP;
+            while (node != NULL) {
+                next = node->next;
+                if (node->ref == 0) {
+                    deleted++;
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+                    cuddOrderedInsert(&tree,node);
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+#endif
+#else
+                    cuddDeallocNode(unique,node);
+#endif
+                } else {
+                    *lastP = node;
+                    lastP = &(node->next);
+                }
+                node = next;
+            }
+            *lastP = NULL;
+        }
+        if ((unsigned) deleted != unique->subtableZ[i].dead) {
+            ddReportRefMess(unique, i, "cuddGarbageCollect");
+        }
+        totalDeletedZ += deleted;
+        unique->subtableZ[i].keys -= deleted;
+        unique->subtableZ[i].dead = 0;
+    }
+
+    /* No need to examine the constant table for ZDDs.
+    ** If we did we should be careful not to count whatever dead
+    ** nodes we found there among the dead ZDD nodes. */
+    if ((unsigned) totalDeletedZ != unique->deadZ) {
+        ddReportRefMess(unique, -1, "cuddGarbageCollect");
+    }
+    unique->keysZ -= totalDeletedZ;
+    unique->deadZ = 0;
+#ifdef DD_STATS
+    unique->nodesFreed += (double) totalDeletedZ;
+#endif
+
+
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+    unique->nextFree = cuddOrderedThread(tree,unique->nextFree);
+#else
+    memListTrav = unique->memoryList;
+    sentry = NULL;
+    while (memListTrav != NULL) {
+        ptruint offset;
+        nxtNode = (DdNodePtr *)memListTrav[0];
+//        offset = (ptruint) memListTrav & (sizeof(DdNode) - 1);
+//        memListTrav += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
+        offset = (ptruint) memListTrav & (32 - 1);
+        memListTrav += (32 - offset) / sizeof(DdNodePtr);
+
+        downTrav = (DdNode *)memListTrav;
+        k = 0;
+        do {
+            if (downTrav[k].ref == 0) {
+                if (sentry == NULL) {
+                    unique->nextFree = sentry = &downTrav[k];
+                } else {
+                    /* First hook sentry->next to the dead node and then
+                    ** reassign sentry to the dead node. */
+                    sentry = (sentry->next = &downTrav[k]);
+                }
+            }
+        } while (++k < DD_MEM_CHUNK);
+        memListTrav = nxtNode;
+    }
+    sentry->next = NULL;
+#endif
+#endif
+
+    unique->GCTime += util_cpu_time() - localTime;
+
+    hook = unique->postGCHook;
+    while (hook != NULL) {
+        int res = (hook->f)(unique,"DD",NULL);
+        if (res == 0) return(0);
+        hook = hook->next;
+    }
+
+#ifdef DD_VERBOSE
+    (void) fprintf(unique->err," done\n");
+#endif
+
+    return(totalDeleted+totalDeletedZ);
+
+} /* end of cuddGarbageCollect */
+
+
+/**Function********************************************************************
+
+  Synopsis [Wrapper for cuddUniqueInterZdd.]
+
+  Description [Wrapper for cuddUniqueInterZdd, which applies the ZDD
+  reduction rule. Returns a pointer to the result node under normal
+  conditions; NULL if reordering occurred or memory was exhausted.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUniqueInterZdd]
+
+******************************************************************************/
+DdNode *
+cuddZddGetNode(
+  DdManager * zdd,
+  int  id,
+  DdNode * T,
+  DdNode * E)
+{
+    DdNode      *node;
+
+    if (T == DD_ZERO(zdd))
+        return(E);
+    node = cuddUniqueInterZdd(zdd, id, T, E);
+    return(node);
+
+} /* end of cuddZddGetNode */
+
+
+/**Function********************************************************************
+
+  Synopsis [Wrapper for cuddUniqueInterZdd that is independent of variable
+  ordering.]
+
+  Description [Wrapper for cuddUniqueInterZdd that is independent of
+  variable ordering (IVO). This function does not require parameter
+  index to precede the indices of the top nodes of g and h in the
+  variable order.  Returns a pointer to the result node under normal
+  conditions; NULL if reordering occurred or memory was exhausted.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddZddGetNode cuddZddIsop]
+
+******************************************************************************/
+DdNode *
+cuddZddGetNodeIVO(
+  DdManager * dd,
+  int  index,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode      *f, *r, *t;
+    DdNode      *zdd_one = DD_ONE(dd);
+    DdNode      *zdd_zero = DD_ZERO(dd);
+
+    f = cuddUniqueInterZdd(dd, index, zdd_one, zdd_zero);
+    if (f == NULL) {
+        return(NULL);
+    }
+    cuddRef(f);
+    t = cuddZddProduct(dd, f, g);
+    if (t == NULL) {
+        Cudd_RecursiveDerefZdd(dd, f);
+        return(NULL);
+    }
+    cuddRef(t);
+    Cudd_RecursiveDerefZdd(dd, f);
+    r = cuddZddUnion(dd, t, h);
+    if (r == NULL) {
+        Cudd_RecursiveDerefZdd(dd, t);
+        return(NULL);
+    }
+    cuddRef(r);
+    Cudd_RecursiveDerefZdd(dd, t);
+
+    cuddDeref(r);
+    return(r);
+
+} /* end of cuddZddGetNodeIVO */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the unique table for the existence of an internal node.]
+
+  Description [Checks the unique table for the existence of an internal
+  node. If it does not exist, it creates a new one.  Does not
+  modify the reference count of whatever is returned.  A newly created
+  internal node comes back with a reference count 0.  For a newly
+  created node, increments the reference counts of what T and E point
+  to.  Returns a pointer to the new node if successful; NULL if memory
+  is exhausted or if reordering took place.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUniqueInterZdd]
+
+******************************************************************************/
+DdNode *
+cuddUniqueInter(
+  DdManager * unique,
+  int  index,
+  DdNode * T,
+  DdNode * E)
+{
+    int pos;
+    unsigned int level;
+    int retval;
+    DdNodePtr *nodelist;
+    DdNode *looking;
+    DdNodePtr *previousP;
+    DdSubtable *subtable;
+    int gcNumber;
+
+#ifdef DD_UNIQUE_PROFILE
+    unique->uniqueLookUps++;
+#endif
+
+    if (index >= unique->size) {
+        if (!ddResizeTable(unique,index)) return(NULL);
+    }
+
+    level = unique->perm[index];
+    subtable = &(unique->subtables[level]);
+
+#ifdef DD_DEBUG
+    assert(level < (unsigned) cuddI(unique,T->index));
+    assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index));
+#endif
+
+    pos = ddHash(cuddF2L(T), cuddF2L(E), subtable->shift);
+    nodelist = subtable->nodelist;
+    previousP = &(nodelist[pos]);
+    looking = *previousP;
+
+    while (T < cuddT(looking)) {
+        previousP = &(looking->next);
+        looking = *previousP;
+#ifdef DD_UNIQUE_PROFILE
+        unique->uniqueLinks++;
+#endif
+    }
+    while (T == cuddT(looking) && E < cuddE(looking)) {
+        previousP = &(looking->next);
+        looking = *previousP;
+#ifdef DD_UNIQUE_PROFILE
+        unique->uniqueLinks++;
+#endif
+    }
+    if (T == cuddT(looking) && E == cuddE(looking)) {
+        if (looking->ref == 0) {
+            cuddReclaim(unique,looking);
+        }
+        return(looking);
+    }
+
+    /* countDead is 0 if deads should be counted and ~0 if they should not. */
+    if (unique->autoDyn &&
+    unique->keys - (unique->dead & unique->countDead) >= unique->nextDyn) {
+#ifdef DD_DEBUG
+        retval = Cudd_DebugCheck(unique);
+        if (retval != 0) return(NULL);
+        retval = Cudd_CheckKeys(unique);
+        if (retval != 0) return(NULL);
+#endif
+        retval = Cudd_ReduceHeap(unique,unique->autoMethod,10); /* 10 = whatever */
+        if (retval == 0) unique->reordered = 2;
+#ifdef DD_DEBUG
+        retval = Cudd_DebugCheck(unique);
+        if (retval != 0) unique->reordered = 2;
+        retval = Cudd_CheckKeys(unique);
+        if (retval != 0) unique->reordered = 2;
+#endif
+        return(NULL);
+    }
+
+    if (subtable->keys > subtable->maxKeys) {
+        if (unique->gcEnabled &&
+            ((unique->dead > unique->minDead) ||
+            ((unique->dead > unique->minDead / 2) &&
+            (subtable->dead > subtable->keys * 0.95)))) { /* too many dead */
+            (void) cuddGarbageCollect(unique,1);
+        } else {
+            cuddRehash(unique,(int)level);
+        }
+        /* Update pointer to insertion point. In the case of rehashing,
+        ** the slot may have changed. In the case of garbage collection,
+        ** the predecessor may have been dead. */
+        pos = ddHash(cuddF2L(T), cuddF2L(E), subtable->shift);
+        nodelist = subtable->nodelist;
+        previousP = &(nodelist[pos]);
+        looking = *previousP;
+
+        while (T < cuddT(looking)) {
+            previousP = &(looking->next);
+            looking = *previousP;
+#ifdef DD_UNIQUE_PROFILE
+            unique->uniqueLinks++;
+#endif
+        }
+        while (T == cuddT(looking) && E < cuddE(looking)) {
+            previousP = &(looking->next);
+            looking = *previousP;
+#ifdef DD_UNIQUE_PROFILE
+            unique->uniqueLinks++;
+#endif
+        }
+    }
+
+    gcNumber = unique->garbageCollections;
+    looking = cuddAllocNode(unique);
+    if (looking == NULL) {
+        return(NULL);
+    }
+    unique->keys++;
+    subtable->keys++;
+
+    if (gcNumber != unique->garbageCollections) {
+        DdNode *looking2;
+        pos = ddHash(cuddF2L(T), cuddF2L(E), subtable->shift);
+        nodelist = subtable->nodelist;
+        previousP = &(nodelist[pos]);
+        looking2 = *previousP;
+
+        while (T < cuddT(looking2)) {
+            previousP = &(looking2->next);
+            looking2 = *previousP;
+#ifdef DD_UNIQUE_PROFILE
+            unique->uniqueLinks++;
+#endif
+        }
+        while (T == cuddT(looking2) && E < cuddE(looking2)) {
+            previousP = &(looking2->next);
+            looking2 = *previousP;
+#ifdef DD_UNIQUE_PROFILE
+            unique->uniqueLinks++;
+#endif
+        }
+    }
+    looking->index = index;
+    cuddT(looking) = T;
+    cuddE(looking) = E;
+    looking->next = *previousP;
+    *previousP = looking;
+    cuddSatInc(T->ref);         /* we know T is a regular pointer */
+    cuddRef(E);
+
+#ifdef DD_DEBUG
+    cuddCheckCollisionOrdering(unique,level,pos);
+#endif
+
+//    assert( Cudd_Regular(T)->Id < 100000000 );
+//    assert( Cudd_Regular(E)->Id < 100000000 );
+    return(looking);
+
+} /* end of cuddUniqueInter */
+
+
+/**Function********************************************************************
+
+  Synopsis [Wrapper for cuddUniqueInter that is independent of variable
+  ordering.]
+
+  Description [Wrapper for cuddUniqueInter that is independent of
+  variable ordering (IVO). This function does not require parameter
+  index to precede the indices of the top nodes of T and E in the
+  variable order.  Returns a pointer to the result node under normal
+  conditions; NULL if reordering occurred or memory was exhausted.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUniqueInter Cudd_MakeBddFromZddCover]
+
+******************************************************************************/
+DdNode *
+cuddUniqueInterIVO(
+  DdManager * unique,
+  int  index,
+  DdNode * T,
+  DdNode * E)
+{
+    DdNode *result;
+    DdNode *v;
+
+    v = cuddUniqueInter(unique, index, DD_ONE(unique),
+                        Cudd_Not(DD_ONE(unique)));
+    if (v == NULL)
+        return(NULL);
+    cuddRef(v);
+    result = cuddBddIteRecur(unique, v, T, E);
+    Cudd_RecursiveDeref(unique, v);
+    return(result);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the unique table for the existence of an internal
+  ZDD node.]
+
+  Description [Checks the unique table for the existence of an internal
+  ZDD node. If it does not exist, it creates a new one.  Does not
+  modify the reference count of whatever is returned.  A newly created
+  internal node comes back with a reference count 0.  For a newly
+  created node, increments the reference counts of what T and E point
+  to.  Returns a pointer to the new node if successful; NULL if memory
+  is exhausted or if reordering took place.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUniqueInter]
+
+******************************************************************************/
+DdNode *
+cuddUniqueInterZdd(
+  DdManager * unique,
+  int  index,
+  DdNode * T,
+  DdNode * E)
+{
+    int pos;
+    unsigned int level;
+    int retval;
+    DdNodePtr *nodelist;
+    DdNode *looking;
+    DdSubtable *subtable;
+
+#ifdef DD_UNIQUE_PROFILE
+    unique->uniqueLookUps++;
+#endif
+
+    if (index >= unique->sizeZ) {
+        if (!cuddResizeTableZdd(unique,index)) return(NULL);
+    }
+
+    level = unique->permZ[index];
+    subtable = &(unique->subtableZ[level]);
+
+#ifdef DD_DEBUG
+    assert(level < (unsigned) cuddIZ(unique,T->index));
+    assert(level < (unsigned) cuddIZ(unique,Cudd_Regular(E)->index));
+#endif
+
+    if (subtable->keys > subtable->maxKeys) {
+        if (unique->gcEnabled && ((unique->deadZ > unique->minDead) ||
+        (10 * subtable->dead > 9 * subtable->keys))) {  /* too many dead */
+            (void) cuddGarbageCollect(unique,1);
+        } else {
+            ddRehashZdd(unique,(int)level);
+        }
+    }
+
+    pos = ddHash(cuddF2L(T), cuddF2L(E), subtable->shift);
+    nodelist = subtable->nodelist;
+    looking = nodelist[pos];
+
+    while (looking != NULL) {
+        if (cuddT(looking) == T && cuddE(looking) == E) {
+            if (looking->ref == 0) {
+                cuddReclaimZdd(unique,looking);
+            }
+            return(looking);
+        }
+        looking = looking->next;
+#ifdef DD_UNIQUE_PROFILE
+        unique->uniqueLinks++;
+#endif
+    }
+
+    /* countDead is 0 if deads should be counted and ~0 if they should not. */
+    if (unique->autoDynZ &&
+    unique->keysZ - (unique->deadZ & unique->countDead) >= unique->nextDyn) {
+#ifdef DD_DEBUG
+        retval = Cudd_DebugCheck(unique);
+        if (retval != 0) return(NULL);
+        retval = Cudd_CheckKeys(unique);
+        if (retval != 0) return(NULL);
+#endif
+        retval = Cudd_zddReduceHeap(unique,unique->autoMethodZ,10); /* 10 = whatever */
+        if (retval == 0) unique->reordered = 2;
+#ifdef DD_DEBUG
+        retval = Cudd_DebugCheck(unique);
+        if (retval != 0) unique->reordered = 2;
+        retval = Cudd_CheckKeys(unique);
+        if (retval != 0) unique->reordered = 2;
+#endif
+        return(NULL);
+    }
+
+    unique->keysZ++;
+    subtable->keys++;
+
+    looking = cuddAllocNode(unique);
+    if (looking == NULL) return(NULL);
+    looking->index = index;
+    cuddT(looking) = T;
+    cuddE(looking) = E;
+    looking->next = nodelist[pos];
+    nodelist[pos] = looking;
+    cuddRef(T);
+    cuddRef(E);
+
+    return(looking);
+
+} /* end of cuddUniqueInterZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the unique table for the existence of a constant node.]
+
+  Description [Checks the unique table for the existence of a constant node.
+  If it does not exist, it creates a new one.  Does not
+  modify the reference count of whatever is returned.  A newly created
+  internal node comes back with a reference count 0.  Returns a
+  pointer to the new node.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+cuddUniqueConst(
+  DdManager * unique,
+  CUDD_VALUE_TYPE  value)
+{
+    int pos;
+    DdNodePtr *nodelist;
+    DdNode *looking;
+    hack split;
+
+#ifdef DD_UNIQUE_PROFILE
+    unique->uniqueLookUps++;
+#endif
+
+    if (unique->constants.keys > unique->constants.maxKeys) {
+        if (unique->gcEnabled && ((unique->dead > unique->minDead) ||
+        (10 * unique->constants.dead > 9 * unique->constants.keys))) {  /* too many dead */
+            (void) cuddGarbageCollect(unique,1);
+        } else {
+            cuddRehash(unique,CUDD_CONST_INDEX);
+        }
+    }
+
+    cuddAdjust(value); /* for the case of crippled infinities */
+
+    if (ddAbs(value) < unique->epsilon) {
+        value = 0.0;
+    }
+    split.value = value;
+
+    pos = ddHash(split.bits[0], split.bits[1], unique->constants.shift);
+    nodelist = unique->constants.nodelist;
+    looking = nodelist[pos];
+
+    /* Here we compare values both for equality and for difference less
+     * than epsilon. The first comparison is required when values are
+     * infinite, since Infinity - Infinity is NaN and NaN < X is 0 for
+     * every X.
+     */
+    while (looking != NULL) {
+        if (looking->type.value == value ||
+        ddEqualVal(looking->type.value,value,unique->epsilon)) {
+            if (looking->ref == 0) {
+                cuddReclaim(unique,looking);
+            }
+            return(looking);
+        }
+        looking = looking->next;
+#ifdef DD_UNIQUE_PROFILE
+        unique->uniqueLinks++;
+#endif
+    }
+
+    unique->keys++;
+    unique->constants.keys++;
+
+    looking = cuddAllocNode(unique);
+    if (looking == NULL) return(NULL);
+    looking->index = CUDD_CONST_INDEX;
+    looking->type.value = value;
+    looking->next = nodelist[pos];
+    nodelist[pos] = looking;
+
+    return(looking);
+
+} /* end of cuddUniqueConst */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Rehashes a unique subtable.]
+
+  Description [Doubles the size of a unique subtable and rehashes its
+  contents.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddRehash(
+  DdManager * unique,
+  int i)
+{
+    unsigned int slots, oldslots;
+    int shift, oldshift;
+    int j, pos;
+    DdNodePtr *nodelist, *oldnodelist;
+    DdNode *node, *next;
+    DdNode *sentinel = &(unique->sentinel);
+    hack split;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    if (unique->gcFrac == DD_GC_FRAC_HI && unique->slots > unique->looseUpTo) {
+        unique->gcFrac = DD_GC_FRAC_LO;
+        unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots);
+#ifdef DD_VERBOSE
+        (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_LO);
+        (void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
+#endif
+    }
+
+    if (unique->gcFrac != DD_GC_FRAC_MIN && unique->memused > unique->maxmem) {
+        unique->gcFrac = DD_GC_FRAC_MIN;
+        unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots);
+#ifdef DD_VERBOSE
+        (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_MIN);
+        (void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
+#endif
+        cuddShrinkDeathRow(unique);
+        if (cuddGarbageCollect(unique,1) > 0) return;
+    }
+
+    if (i != CUDD_CONST_INDEX) {
+        oldslots = unique->subtables[i].slots;
+        oldshift = unique->subtables[i].shift;
+        oldnodelist = unique->subtables[i].nodelist;
+
+        /* Compute the new size of the subtable. */
+        slots = oldslots << 1;
+        shift = oldshift - 1;
+
+        saveHandler = MMoutOfMemory;
+        MMoutOfMemory = Cudd_OutOfMem;
+        nodelist = ABC_ALLOC(DdNodePtr, slots);
+        MMoutOfMemory = saveHandler;
+        if (nodelist == NULL) {
+            (void) fprintf(unique->err,
+                           "Unable to resize subtable %d for lack of memory\n",
+                           i);
+            /* Prevent frequent resizing attempts. */
+            (void) cuddGarbageCollect(unique,1);
+            if (unique->stash != NULL) {
+                ABC_FREE(unique->stash);
+                unique->stash = NULL;
+                /* Inhibit resizing of tables. */
+                cuddSlowTableGrowth(unique);
+            }
+            return;
+        }
+        unique->subtables[i].nodelist = nodelist;
+        unique->subtables[i].slots = slots;
+        unique->subtables[i].shift = shift;
+        unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
+
+        /* Move the nodes from the old table to the new table.
+        ** This code depends on the type of hash function.
+        ** It assumes that the effect of doubling the size of the table
+        ** is to retain one more bit of the 32-bit hash value.
+        ** The additional bit is the LSB. */
+        for (j = 0; (unsigned) j < oldslots; j++) {
+            DdNodePtr *evenP, *oddP;
+            node = oldnodelist[j];
+            evenP = &(nodelist[j<<1]);
+            oddP = &(nodelist[(j<<1)+1]);
+            while (node != sentinel) {
+                next = node->next;
+                pos = ddHash(cuddF2L(cuddT(node)), cuddF2L(cuddE(node)), shift);
+                if (pos & 1) {
+                    *oddP = node;
+                    oddP = &(node->next);
+                } else {
+                    *evenP = node;
+                    evenP = &(node->next);
+                }
+                node = next;
+            }
+            *evenP = *oddP = sentinel;
+        }
+        ABC_FREE(oldnodelist);
+
+#ifdef DD_VERBOSE
+        (void) fprintf(unique->err,
+                       "rehashing layer %d: keys %d dead %d new size %d\n",
+                       i, unique->subtables[i].keys,
+                       unique->subtables[i].dead, slots);
+#endif
+    } else {
+        oldslots = unique->constants.slots;
+        oldshift = unique->constants.shift;
+        oldnodelist = unique->constants.nodelist;
+
+        /* The constant subtable is never subjected to reordering.
+        ** Therefore, when it is resized, it is because it has just
+        ** reached the maximum load. We can safely just double the size,
+        ** with no need for the loop we use for the other tables.
+        */
+        slots = oldslots << 1;
+        shift = oldshift - 1;
+        saveHandler = MMoutOfMemory;
+        MMoutOfMemory = Cudd_OutOfMem;
+        nodelist = ABC_ALLOC(DdNodePtr, slots);
+        MMoutOfMemory = saveHandler;
+        if (nodelist == NULL) {
+            (void) fprintf(unique->err,
+                           "Unable to resize constant subtable for lack of memory\n");
+            (void) cuddGarbageCollect(unique,1);
+            for (j = 0; j < unique->size; j++) {
+                unique->subtables[j].maxKeys <<= 1;
+            }
+            unique->constants.maxKeys <<= 1;
+            return;
+        }
+        unique->constants.slots = slots;
+        unique->constants.shift = shift;
+        unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
+        unique->constants.nodelist = nodelist;
+        for (j = 0; (unsigned) j < slots; j++) {
+            nodelist[j] = NULL;
+        }
+        for (j = 0; (unsigned) j < oldslots; j++) {
+            node = oldnodelist[j];
+            while (node != NULL) {
+                next = node->next;
+                split.value = cuddV(node);
+                pos = ddHash(split.bits[0], split.bits[1], shift);
+                node->next = nodelist[pos];
+                nodelist[pos] = node;
+                node = next;
+            }
+        }
+        ABC_FREE(oldnodelist);
+
+#ifdef DD_VERBOSE
+        (void) fprintf(unique->err,
+                       "rehashing constants: keys %d dead %d new size %d\n",
+                       unique->constants.keys,unique->constants.dead,slots);
+#endif
+    }
+
+    /* Update global data */
+
+    unique->memused += (slots - oldslots) * sizeof(DdNodePtr);
+    unique->slots += (slots - oldslots);
+    ddFixLimits(unique);
+
+} /* end of cuddRehash */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Shrinks a subtable.]
+
+  Description [Shrinks a subtable.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddRehash]
+
+******************************************************************************/
+void
+cuddShrinkSubtable(
+  DdManager *unique,
+  int i)
+{
+    int j;
+    int shift, posn;
+    DdNodePtr *nodelist, *oldnodelist;
+    DdNode *node, *next;
+    DdNode *sentinel = &(unique->sentinel);
+    unsigned int slots, oldslots;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    oldnodelist = unique->subtables[i].nodelist;
+    oldslots = unique->subtables[i].slots;
+    slots = oldslots >> 1;
+    saveHandler = MMoutOfMemory;
+    MMoutOfMemory = Cudd_OutOfMem;
+    nodelist = ABC_ALLOC(DdNodePtr, slots);
+    MMoutOfMemory = saveHandler;
+    if (nodelist == NULL) {
+        return;
+    }
+    unique->subtables[i].nodelist = nodelist;
+    unique->subtables[i].slots = slots;
+    unique->subtables[i].shift++;
+    unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
+#ifdef DD_VERBOSE
+    (void) fprintf(unique->err,
+                   "shrunk layer %d (%d keys) from %d to %d slots\n",
+                   i, unique->subtables[i].keys, oldslots, slots);
+#endif
+
+    for (j = 0; (unsigned) j < slots; j++) {
+        nodelist[j] = sentinel;
+    }
+    shift = unique->subtables[i].shift;
+    for (j = 0; (unsigned) j < oldslots; j++) {
+        node = oldnodelist[j];
+        while (node != sentinel) {
+            DdNode *looking, *T, *E;
+            DdNodePtr *previousP;
+            next = node->next;
+            posn = ddHash(cuddF2L(cuddT(node)), cuddF2L(cuddE(node)), shift);
+            previousP = &(nodelist[posn]);
+            looking = *previousP;
+            T = cuddT(node);
+            E = cuddE(node);
+            while (T < cuddT(looking)) {
+                previousP = &(looking->next);
+                looking = *previousP;
+#ifdef DD_UNIQUE_PROFILE
+                unique->uniqueLinks++;
+#endif
+            }
+            while (T == cuddT(looking) && E < cuddE(looking)) {
+                previousP = &(looking->next);
+                looking = *previousP;
+#ifdef DD_UNIQUE_PROFILE
+                unique->uniqueLinks++;
+#endif
+            }
+            node->next = *previousP;
+            *previousP = node;
+            node = next;
+        }
+    }
+    ABC_FREE(oldnodelist);
+
+    unique->memused += ((long) slots - (long) oldslots) * sizeof(DdNode *);
+    unique->slots += slots - oldslots;
+    unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots);
+    unique->cacheSlack = (int)
+        ddMin(unique->maxCacheHard,DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots)
+        - 2 * (int) unique->cacheSlots;
+
+} /* end of cuddShrinkSubtable */
+
+
+/**Function********************************************************************
+
+  Synopsis [Inserts n new subtables in a unique table at level.]
+
+  Description [Inserts n new subtables in a unique table at level.
+  The number n should be positive, and level should be an existing level.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddDestroySubtables]
+
+******************************************************************************/
+int
+cuddInsertSubtables(
+  DdManager * unique,
+  int  n,
+  int  level)
+{
+    DdSubtable *newsubtables;
+    DdNodePtr *newnodelist;
+    DdNodePtr *newvars;
+    DdNode *sentinel = &(unique->sentinel);
+    int oldsize,newsize;
+    int i,j,index,reorderSave;
+    unsigned int numSlots = unique->initSlots;
+    int *newperm, *newinvperm, *newmap=NULL;
+    DdNode *one, *zero;
+
+#ifdef DD_DEBUG
+    assert(n > 0 && level < unique->size);
+#endif
+
+    oldsize = unique->size;
+    /* Easy case: there is still room in the current table. */
+    if (oldsize + n <= unique->maxSize) {
+        /* Shift the tables at and below level. */
+        for (i = oldsize - 1; i >= level; i--) {
+            unique->subtables[i+n].slots    = unique->subtables[i].slots;
+            unique->subtables[i+n].shift    = unique->subtables[i].shift;
+            unique->subtables[i+n].keys     = unique->subtables[i].keys;
+            unique->subtables[i+n].maxKeys  = unique->subtables[i].maxKeys;
+            unique->subtables[i+n].dead     = unique->subtables[i].dead;
+            unique->subtables[i+n].nodelist = unique->subtables[i].nodelist;
+            unique->subtables[i+n].bindVar  = unique->subtables[i].bindVar;
+            unique->subtables[i+n].varType  = unique->subtables[i].varType;
+            unique->subtables[i+n].pairIndex  = unique->subtables[i].pairIndex;
+            unique->subtables[i+n].varHandled = unique->subtables[i].varHandled;
+            unique->subtables[i+n].varToBeGrouped =
+                unique->subtables[i].varToBeGrouped;
+
+            index                           = unique->invperm[i];
+            unique->invperm[i+n]            = index;
+            unique->perm[index]            += n;
+        }
+        /* Create new subtables. */
+        for (i = 0; i < n; i++) {
+            unique->subtables[level+i].slots = numSlots;
+            unique->subtables[level+i].shift = sizeof(int) * 8 -
+                cuddComputeFloorLog2(numSlots);
+            unique->subtables[level+i].keys = 0;
+            unique->subtables[level+i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
+            unique->subtables[level+i].dead = 0;
+            unique->subtables[level+i].bindVar = 0;
+            unique->subtables[level+i].varType = CUDD_VAR_PRIMARY_INPUT;
+            unique->subtables[level+i].pairIndex = 0;
+            unique->subtables[level+i].varHandled = 0;
+            unique->subtables[level+i].varToBeGrouped = CUDD_LAZY_NONE;
+
+            unique->perm[oldsize+i] = level + i;
+            unique->invperm[level+i] = oldsize + i;
+            newnodelist = unique->subtables[level+i].nodelist =
+                ABC_ALLOC(DdNodePtr, numSlots);
+            if (newnodelist == NULL) {
+                unique->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            for (j = 0; (unsigned) j < numSlots; j++) {
+                newnodelist[j] = sentinel;
+            }
+        }
+        if (unique->map != NULL) {
+            for (i = 0; i < n; i++) {
+                unique->map[oldsize+i] = oldsize + i;
+            }
+        }
+    } else {
+        /* The current table is too small: we need to allocate a new,
+        ** larger one; move all old subtables, and initialize the new
+        ** subtables.
+        */
+        newsize = oldsize + n + DD_DEFAULT_RESIZE;
+#ifdef DD_VERBOSE
+        (void) fprintf(unique->err,
+                       "Increasing the table size from %d to %d\n",
+            unique->maxSize, newsize);
+#endif
+        /* Allocate memory for new arrays (except nodelists). */
+        newsubtables = ABC_ALLOC(DdSubtable,newsize);
+        if (newsubtables == NULL) {
+            unique->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        newvars = ABC_ALLOC(DdNodePtr,newsize);
+        if (newvars == NULL) {
+            unique->errorCode = CUDD_MEMORY_OUT;
+            ABC_FREE(newsubtables);
+            return(0);
+        }
+        newperm = ABC_ALLOC(int,newsize);
+        if (newperm == NULL) {
+            unique->errorCode = CUDD_MEMORY_OUT;
+            ABC_FREE(newsubtables);
+            ABC_FREE(newvars);
+            return(0);
+        }
+        newinvperm = ABC_ALLOC(int,newsize);
+        if (newinvperm == NULL) {
+            unique->errorCode = CUDD_MEMORY_OUT;
+            ABC_FREE(newsubtables);
+            ABC_FREE(newvars);
+            ABC_FREE(newperm);
+            return(0);
+        }
+        if (unique->map != NULL) {
+            newmap = ABC_ALLOC(int,newsize);
+            if (newmap == NULL) {
+                unique->errorCode = CUDD_MEMORY_OUT;
+                ABC_FREE(newsubtables);
+                ABC_FREE(newvars);
+                ABC_FREE(newperm);
+                ABC_FREE(newinvperm);
+                return(0);
+            }
+            unique->memused += (newsize - unique->maxSize) * sizeof(int);
+        }
+        unique->memused += (newsize - unique->maxSize) * ((numSlots+1) *
+            sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable));
+        /* Copy levels before insertion points from old tables. */
+        for (i = 0; i < level; i++) {
+            newsubtables[i].slots = unique->subtables[i].slots;
+            newsubtables[i].shift = unique->subtables[i].shift;
+            newsubtables[i].keys = unique->subtables[i].keys;
+            newsubtables[i].maxKeys = unique->subtables[i].maxKeys;
+            newsubtables[i].dead = unique->subtables[i].dead;
+            newsubtables[i].nodelist = unique->subtables[i].nodelist;
+            newsubtables[i].bindVar = unique->subtables[i].bindVar;
+            newsubtables[i].varType = unique->subtables[i].varType;
+            newsubtables[i].pairIndex = unique->subtables[i].pairIndex;
+            newsubtables[i].varHandled = unique->subtables[i].varHandled;
+            newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped;
+
+            newvars[i] = unique->vars[i];
+            newperm[i] = unique->perm[i];
+            newinvperm[i] = unique->invperm[i];
+        }
+        /* Finish initializing permutation for new table to old one. */
+        for (i = level; i < oldsize; i++) {
+            newperm[i] = unique->perm[i];
+        }
+        /* Initialize new levels. */
+        for (i = level; i < level + n; i++) {
+            newsubtables[i].slots = numSlots;
+            newsubtables[i].shift = sizeof(int) * 8 -
+                cuddComputeFloorLog2(numSlots);
+            newsubtables[i].keys = 0;
+            newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
+            newsubtables[i].dead = 0;
+            newsubtables[i].bindVar = 0;
+            newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT;
+            newsubtables[i].pairIndex = 0;
+            newsubtables[i].varHandled = 0;
+            newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE;
+
+            newperm[oldsize + i - level] = i;
+            newinvperm[i] = oldsize + i - level;
+            newnodelist = newsubtables[i].nodelist = ABC_ALLOC(DdNodePtr, numSlots);
+            if (newnodelist == NULL) {
+                /* We are going to leak some memory.  We should clean up. */
+                unique->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            for (j = 0; (unsigned) j < numSlots; j++) {
+                newnodelist[j] = sentinel;
+            }
+        }
+        /* Copy the old tables for levels past the insertion point. */
+        for (i = level; i < oldsize; i++) {
+            newsubtables[i+n].slots    = unique->subtables[i].slots;
+            newsubtables[i+n].shift    = unique->subtables[i].shift;
+            newsubtables[i+n].keys     = unique->subtables[i].keys;
+            newsubtables[i+n].maxKeys  = unique->subtables[i].maxKeys;
+            newsubtables[i+n].dead     = unique->subtables[i].dead;
+            newsubtables[i+n].nodelist = unique->subtables[i].nodelist;
+            newsubtables[i+n].bindVar  = unique->subtables[i].bindVar;
+            newsubtables[i+n].varType  = unique->subtables[i].varType;
+            newsubtables[i+n].pairIndex  = unique->subtables[i].pairIndex;
+            newsubtables[i+n].varHandled  = unique->subtables[i].varHandled;
+            newsubtables[i+n].varToBeGrouped  =
+                unique->subtables[i].varToBeGrouped;
+
+            newvars[i]                 = unique->vars[i];
+            index                      = unique->invperm[i];
+            newinvperm[i+n]            = index;
+            newperm[index]            += n;
+        }
+        /* Update the map. */
+        if (unique->map != NULL) {
+            for (i = 0; i < oldsize; i++) {
+                newmap[i] = unique->map[i];
+            }
+            for (i = oldsize; i < oldsize + n; i++) {
+                newmap[i] = i;
+            }
+            ABC_FREE(unique->map);
+            unique->map = newmap;
+        }
+        /* Install the new tables and free the old ones. */
+        ABC_FREE(unique->subtables);
+        unique->subtables = newsubtables;
+        unique->maxSize = newsize;
+        ABC_FREE(unique->vars);
+        unique->vars = newvars;
+        ABC_FREE(unique->perm);
+        unique->perm = newperm;
+        ABC_FREE(unique->invperm);
+        unique->invperm = newinvperm;
+        /* Update the stack for iterative procedures. */
+        if (newsize > unique->maxSizeZ) {
+            ABC_FREE(unique->stack);
+            unique->stack = ABC_ALLOC(DdNodePtr,newsize + 1);
+            if (unique->stack == NULL) {
+                unique->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            unique->stack[0] = NULL; /* to suppress harmless UMR */
+            unique->memused +=
+                (newsize - ddMax(unique->maxSize,unique->maxSizeZ))
+                * sizeof(DdNode *);
+        }
+    }
+    /* Update manager parameters to account for the new subtables. */
+    unique->slots += n * numSlots;
+    ddFixLimits(unique);
+    unique->size += n;
+
+    /* Now that the table is in a coherent state, create the new
+    ** projection functions. We need to temporarily disable reordering,
+    ** because we cannot reorder without projection functions in place.
+    **/
+    one = unique->one;
+    zero = Cudd_Not(one);
+
+    reorderSave = unique->autoDyn;
+    unique->autoDyn = 0;
+    for (i = oldsize; i < oldsize + n; i++) {
+        unique->vars[i] = cuddUniqueInter(unique,i,one,zero);
+        if (unique->vars[i] == NULL) {
+            unique->autoDyn = reorderSave;
+            /* Shift everything back so table remains coherent. */
+            for (j = oldsize; j < i; j++) {
+                Cudd_IterDerefBdd(unique,unique->vars[j]);
+                cuddDeallocNode(unique,unique->vars[j]);
+                unique->vars[j] = NULL;
+            }
+            for (j = level; j < oldsize; j++) {
+                unique->subtables[j].slots    = unique->subtables[j+n].slots;
+                unique->subtables[j].slots    = unique->subtables[j+n].slots;
+                unique->subtables[j].shift    = unique->subtables[j+n].shift;
+                unique->subtables[j].keys     = unique->subtables[j+n].keys;
+                unique->subtables[j].maxKeys  =
+                    unique->subtables[j+n].maxKeys;
+                unique->subtables[j].dead     = unique->subtables[j+n].dead;
+                ABC_FREE(unique->subtables[j].nodelist);
+                unique->subtables[j].nodelist =
+                    unique->subtables[j+n].nodelist;
+                unique->subtables[j+n].nodelist = NULL;
+                unique->subtables[j].bindVar  =
+                    unique->subtables[j+n].bindVar;
+                unique->subtables[j].varType  =
+                    unique->subtables[j+n].varType;
+                unique->subtables[j].pairIndex =
+                    unique->subtables[j+n].pairIndex;
+                unique->subtables[j].varHandled =
+                    unique->subtables[j+n].varHandled;
+                unique->subtables[j].varToBeGrouped =
+                    unique->subtables[j+n].varToBeGrouped;
+                index                         = unique->invperm[j+n];
+                unique->invperm[j]            = index;
+                unique->perm[index]          -= n;
+            }
+            unique->size = oldsize;
+            unique->slots -= n * numSlots;
+            ddFixLimits(unique);
+            (void) Cudd_DebugCheck(unique);
+            return(0);
+        }
+        cuddRef(unique->vars[i]);
+    }
+    if (unique->tree != NULL) {
+        unique->tree->size += n;
+        unique->tree->index = unique->invperm[0];
+        ddPatchTree(unique,unique->tree);
+    }
+    unique->autoDyn = reorderSave;
+
+    return(1);
+
+} /* end of cuddInsertSubtables */
+
+
+/**Function********************************************************************
+
+  Synopsis [Destroys the n most recently created subtables in a unique table.]
+
+  Description [Destroys the n most recently created subtables in a unique
+  table.  n should be positive. The subtables should not contain any live
+  nodes, except the (isolated) projection function. The projection
+  functions are freed.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [The variable map used for fast variable substitution is
+  destroyed if it exists. In this case the cache is also cleared.]
+
+  SeeAlso     [cuddInsertSubtables Cudd_SetVarMap]
+
+******************************************************************************/
+int
+cuddDestroySubtables(
+  DdManager * unique,
+  int  n)
+{
+    DdSubtable *subtables;
+    DdNodePtr *nodelist;
+    DdNodePtr *vars;
+    int firstIndex, lastIndex;
+    int index, level, newlevel;
+    int lowestLevel;
+    int shift;
+    int found;
+
+    /* Sanity check and set up. */
+    if (n <= 0) return(0);
+    if (n > unique->size) n = unique->size;
+
+    subtables = unique->subtables;
+    vars = unique->vars;
+    firstIndex = unique->size - n;
+    lastIndex  = unique->size;
+
+    /* Check for nodes labeled by the variables being destroyed
+    ** that may still be in use.  It is allowed to destroy a variable
+    ** only if there are no such nodes. Also, find the lowest level
+    ** among the variables being destroyed. This will make further
+    ** processing more efficient.
+    */
+    lowestLevel = unique->size;
+    for (index = firstIndex; index < lastIndex; index++) {
+        level = unique->perm[index];
+        if (level < lowestLevel) lowestLevel = level;
+        nodelist = subtables[level].nodelist;
+        if (subtables[level].keys - subtables[level].dead != 1) return(0);
+        /* The projection function should be isolated. If the ref count
+        ** is 1, everything is OK. If the ref count is saturated, then
+        ** we need to make sure that there are no nodes pointing to it.
+        ** As for the external references, we assume the application is
+        ** responsible for them.
+        */
+        if (vars[index]->ref != 1) {
+            if (vars[index]->ref != DD_MAXREF) return(0);
+            found = cuddFindParent(unique,vars[index]);
+            if (found) {
+                return(0);
+            } else {
+                vars[index]->ref = 1;
+            }
+        }
+        Cudd_RecursiveDeref(unique,vars[index]);
+    }
+
+    /* Collect garbage, because we cannot afford having dead nodes pointing
+    ** to the dead nodes in the subtables being destroyed.
+    */
+    (void) cuddGarbageCollect(unique,1);
+
+    /* Here we know we can destroy our subtables. */
+    for (index = firstIndex; index < lastIndex; index++) {
+        level = unique->perm[index];
+        nodelist = subtables[level].nodelist;
+#ifdef DD_DEBUG
+        assert(subtables[level].keys == 0);
+#endif
+        ABC_FREE(nodelist);
+        unique->memused -= sizeof(DdNodePtr) * subtables[level].slots;
+        unique->slots -= subtables[level].slots;
+        unique->dead -= subtables[level].dead;
+    }
+
+    /* Here all subtables to be destroyed have their keys field == 0 and
+    ** their hash tables have been freed.
+    ** We now scan the subtables from level lowestLevel + 1 to level size - 1,
+    ** shifting the subtables as required. We keep a running count of
+    ** how many subtables have been moved, so that we know by how many
+    ** positions each subtable should be shifted.
+    */
+    shift = 1;
+    for (level = lowestLevel + 1; level < unique->size; level++) {
+        if (subtables[level].keys == 0) {
+            shift++;
+            continue;
+        }
+        newlevel = level - shift;
+        subtables[newlevel].slots = subtables[level].slots;
+        subtables[newlevel].shift = subtables[level].shift;
+        subtables[newlevel].keys = subtables[level].keys;
+        subtables[newlevel].maxKeys = subtables[level].maxKeys;
+        subtables[newlevel].dead = subtables[level].dead;
+        subtables[newlevel].nodelist = subtables[level].nodelist;
+        index = unique->invperm[level];
+        unique->perm[index] = newlevel;
+        unique->invperm[newlevel]  = index;
+        subtables[newlevel].bindVar = subtables[level].bindVar;
+        subtables[newlevel].varType = subtables[level].varType;
+        subtables[newlevel].pairIndex = subtables[level].pairIndex;
+        subtables[newlevel].varHandled = subtables[level].varHandled;
+        subtables[newlevel].varToBeGrouped = subtables[level].varToBeGrouped;
+    }
+    /* Destroy the map. If a surviving variable is
+    ** mapped to a dying variable, and the map were used again,
+    ** an out-of-bounds access to unique->vars would result. */
+    if (unique->map != NULL) {
+        cuddCacheFlush(unique);
+        ABC_FREE(unique->map);
+        unique->map = NULL;
+    }
+
+    unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots);
+    unique->size -= n;
+
+    return(1);
+
+} /* end of cuddDestroySubtables */
+
+
+/**Function********************************************************************
+
+  Synopsis [Increases the number of ZDD subtables in a unique table so
+  that it meets or exceeds index.]
+
+  Description [Increases the number of ZDD subtables in a unique table so
+  that it meets or exceeds index.  When new ZDD variables are created, it
+  is possible to preserve the functions unchanged, or it is possible to
+  preserve the covers unchanged, but not both. cuddResizeTableZdd preserves
+  the covers.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [ddResizeTable]
+
+******************************************************************************/
+int
+cuddResizeTableZdd(
+  DdManager * unique,
+  int  index)
+{
+    DdSubtable *newsubtables;
+    DdNodePtr *newnodelist;
+    int oldsize,newsize;
+    int i,j,reorderSave;
+    unsigned int numSlots = unique->initSlots;
+    int *newperm, *newinvperm;
+
+    oldsize = unique->sizeZ;
+    /* Easy case: there is still room in the current table. */
+    if (index < unique->maxSizeZ) {
+        for (i = oldsize; i <= index; i++) {
+            unique->subtableZ[i].slots = numSlots;
+            unique->subtableZ[i].shift = sizeof(int) * 8 -
+                cuddComputeFloorLog2(numSlots);
+            unique->subtableZ[i].keys = 0;
+            unique->subtableZ[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
+            unique->subtableZ[i].dead = 0;
+            unique->permZ[i] = i;
+            unique->invpermZ[i] = i;
+            newnodelist = unique->subtableZ[i].nodelist =
+                ABC_ALLOC(DdNodePtr, numSlots);
+            if (newnodelist == NULL) {
+                unique->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            for (j = 0; (unsigned) j < numSlots; j++) {
+                newnodelist[j] = NULL;
+            }
+        }
+    } else {
+        /* The current table is too small: we need to allocate a new,
+        ** larger one; move all old subtables, and initialize the new
+        ** subtables up to index included.
+        */
+        newsize = index + DD_DEFAULT_RESIZE;
+#ifdef DD_VERBOSE
+        (void) fprintf(unique->err,
+                       "Increasing the ZDD table size from %d to %d\n",
+            unique->maxSizeZ, newsize);
+#endif
+        newsubtables = ABC_ALLOC(DdSubtable,newsize);
+        if (newsubtables == NULL) {
+            unique->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        newperm = ABC_ALLOC(int,newsize);
+        if (newperm == NULL) {
+            unique->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        newinvperm = ABC_ALLOC(int,newsize);
+        if (newinvperm == NULL) {
+            unique->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        unique->memused += (newsize - unique->maxSizeZ) * ((numSlots+1) *
+            sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable));
+        if (newsize > unique->maxSize) {
+            ABC_FREE(unique->stack);
+            unique->stack = ABC_ALLOC(DdNodePtr,newsize + 1);
+            if (unique->stack == NULL) {
+                unique->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            unique->stack[0] = NULL; /* to suppress harmless UMR */
+            unique->memused +=
+                (newsize - ddMax(unique->maxSize,unique->maxSizeZ))
+                * sizeof(DdNode *);
+        }
+        for (i = 0; i < oldsize; i++) {
+            newsubtables[i].slots = unique->subtableZ[i].slots;
+            newsubtables[i].shift = unique->subtableZ[i].shift;
+            newsubtables[i].keys = unique->subtableZ[i].keys;
+            newsubtables[i].maxKeys = unique->subtableZ[i].maxKeys;
+            newsubtables[i].dead = unique->subtableZ[i].dead;
+            newsubtables[i].nodelist = unique->subtableZ[i].nodelist;
+            newperm[i] = unique->permZ[i];
+            newinvperm[i] = unique->invpermZ[i];
+        }
+        for (i = oldsize; i <= index; i++) {
+            newsubtables[i].slots = numSlots;
+            newsubtables[i].shift = sizeof(int) * 8 -
+                cuddComputeFloorLog2(numSlots);
+            newsubtables[i].keys = 0;
+            newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
+            newsubtables[i].dead = 0;
+            newperm[i] = i;
+            newinvperm[i] = i;
+            newnodelist = newsubtables[i].nodelist = ABC_ALLOC(DdNodePtr, numSlots);
+            if (newnodelist == NULL) {
+                unique->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            for (j = 0; (unsigned) j < numSlots; j++) {
+                newnodelist[j] = NULL;
+            }
+        }
+        ABC_FREE(unique->subtableZ);
+        unique->subtableZ = newsubtables;
+        unique->maxSizeZ = newsize;
+        ABC_FREE(unique->permZ);
+        unique->permZ = newperm;
+        ABC_FREE(unique->invpermZ);
+        unique->invpermZ = newinvperm;
+    }
+    unique->slots += (index + 1 - unique->sizeZ) * numSlots;
+    ddFixLimits(unique);
+    unique->sizeZ = index + 1;
+
+    /* Now that the table is in a coherent state, update the ZDD
+    ** universe. We need to temporarily disable reordering,
+    ** because we cannot reorder without universe in place.
+    */
+
+    reorderSave = unique->autoDynZ;
+    unique->autoDynZ = 0;
+    cuddZddFreeUniv(unique);
+    if (!cuddZddInitUniv(unique)) {
+        unique->autoDynZ = reorderSave;
+        return(0);
+    }
+    unique->autoDynZ = reorderSave;
+
+    return(1);
+
+} /* end of cuddResizeTableZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adjusts parameters of a table to slow down its growth.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddSlowTableGrowth(
+  DdManager *unique)
+{
+    int i;
+
+    unique->maxCacheHard = unique->cacheSlots - 1;
+    unique->cacheSlack = - (int) (unique->cacheSlots + 1);
+    for (i = 0; i < unique->size; i++) {
+        unique->subtables[i].maxKeys <<= 2;
+    }
+    unique->gcFrac = DD_GC_FRAC_MIN;
+    unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots);
+    cuddShrinkDeathRow(unique);
+    (void) fprintf(unique->err,"Slowing down table growth: ");
+    (void) fprintf(unique->err,"GC fraction = %.2f\t", unique->gcFrac);
+    (void) fprintf(unique->err,"minDead = %u\n", unique->minDead);
+
+} /* end of cuddSlowTableGrowth */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Rehashes a ZDD unique subtable.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddRehash]
+
+******************************************************************************/
+static void
+ddRehashZdd(
+  DdManager * unique,
+  int  i)
+{
+    unsigned int slots, oldslots;
+    int shift, oldshift;
+    int j, pos;
+    DdNodePtr *nodelist, *oldnodelist;
+    DdNode *node, *next;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    if (unique->slots > unique->looseUpTo) {
+        unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots);
+#ifdef DD_VERBOSE
+        if (unique->gcFrac == DD_GC_FRAC_HI) {
+            (void) fprintf(unique->err,"GC fraction = %.2f\t",
+                           DD_GC_FRAC_LO);
+            (void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
+        }
+#endif
+        unique->gcFrac = DD_GC_FRAC_LO;
+    }
+
+    assert(i != CUDD_MAXINDEX);
+    oldslots = unique->subtableZ[i].slots;
+    oldshift = unique->subtableZ[i].shift;
+    oldnodelist = unique->subtableZ[i].nodelist;
+
+    /* Compute the new size of the subtable. Normally, we just
+    ** double.  However, after reordering, a table may be severely
+    ** overloaded. Therefore, we iterate. */
+    slots = oldslots;
+    shift = oldshift;
+    do {
+        slots <<= 1;
+        shift--;
+    } while (slots * DD_MAX_SUBTABLE_DENSITY < unique->subtableZ[i].keys);
+
+    saveHandler = MMoutOfMemory;
+    MMoutOfMemory = Cudd_OutOfMem;
+    nodelist = ABC_ALLOC(DdNodePtr, slots);
+    MMoutOfMemory = saveHandler;
+    if (nodelist == NULL) {
+        (void) fprintf(unique->err,
+                       "Unable to resize ZDD subtable %d for lack of memory.\n",
+                       i);
+        (void) cuddGarbageCollect(unique,1);
+        for (j = 0; j < unique->sizeZ; j++) {
+            unique->subtableZ[j].maxKeys <<= 1;
+        }
+        return;
+    }
+    unique->subtableZ[i].nodelist = nodelist;
+    unique->subtableZ[i].slots = slots;
+    unique->subtableZ[i].shift = shift;
+    unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
+    for (j = 0; (unsigned) j < slots; j++) {
+        nodelist[j] = NULL;
+    }
+    for (j = 0; (unsigned) j < oldslots; j++) {
+        node = oldnodelist[j];
+        while (node != NULL) {
+            next = node->next;
+            pos = ddHash(cuddF2L(cuddT(node)), cuddF2L(cuddE(node)), shift);
+            node->next = nodelist[pos];
+            nodelist[pos] = node;
+            node = next;
+        }
+    }
+    ABC_FREE(oldnodelist);
+
+#ifdef DD_VERBOSE
+    (void) fprintf(unique->err,
+                   "rehashing layer %d: keys %d dead %d new size %d\n",
+                   i, unique->subtableZ[i].keys,
+                   unique->subtableZ[i].dead, slots);
+#endif
+
+    /* Update global data. */
+    unique->memused += (slots - oldslots) * sizeof(DdNode *);
+    unique->slots += (slots - oldslots);
+    ddFixLimits(unique);
+
+} /* end of ddRehashZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis [Increases the number of subtables in a unique table so
+  that it meets or exceeds index.]
+
+  Description [Increases the number of subtables in a unique table so
+  that it meets or exceeds index. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddResizeTableZdd]
+
+******************************************************************************/
+static int
+ddResizeTable(
+  DdManager * unique,
+  int index)
+{
+    DdSubtable *newsubtables;
+    DdNodePtr *newnodelist;
+    DdNodePtr *newvars;
+    DdNode *sentinel = &(unique->sentinel);
+    int oldsize,newsize;
+    int i,j,reorderSave;
+    int numSlots = unique->initSlots;
+    int *newperm, *newinvperm, *newmap = NULL;
+    DdNode *one, *zero;
+
+    oldsize = unique->size;
+    /* Easy case: there is still room in the current table. */
+    if (index < unique->maxSize) {
+        for (i = oldsize; i <= index; i++) {
+            unique->subtables[i].slots = numSlots;
+            unique->subtables[i].shift = sizeof(int) * 8 -
+                cuddComputeFloorLog2(numSlots);
+            unique->subtables[i].keys = 0;
+            unique->subtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
+            unique->subtables[i].dead = 0;
+            unique->subtables[i].bindVar = 0;
+            unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT;
+            unique->subtables[i].pairIndex = 0;
+            unique->subtables[i].varHandled = 0;
+            unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE;
+
+            unique->perm[i] = i;
+            unique->invperm[i] = i;
+            newnodelist = unique->subtables[i].nodelist =
+                ABC_ALLOC(DdNodePtr, numSlots);
+            if (newnodelist == NULL) {
+                for (j = oldsize; j < i; j++) {
+                    ABC_FREE(unique->subtables[j].nodelist);
+                }
+                unique->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            for (j = 0; j < numSlots; j++) {
+                newnodelist[j] = sentinel;
+            }
+        }
+        if (unique->map != NULL) {
+            for (i = oldsize; i <= index; i++) {
+                unique->map[i] = i;
+            }
+        }
+    } else {
+        /* The current table is too small: we need to allocate a new,
+        ** larger one; move all old subtables, and initialize the new
+        ** subtables up to index included.
+        */
+        newsize = index + DD_DEFAULT_RESIZE;
+#ifdef DD_VERBOSE
+        (void) fprintf(unique->err,
+                       "Increasing the table size from %d to %d\n",
+                       unique->maxSize, newsize);
+#endif
+        newsubtables = ABC_ALLOC(DdSubtable,newsize);
+        if (newsubtables == NULL) {
+            unique->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        newvars = ABC_ALLOC(DdNodePtr,newsize);
+        if (newvars == NULL) {
+            ABC_FREE(newsubtables);
+            unique->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        newperm = ABC_ALLOC(int,newsize);
+        if (newperm == NULL) {
+            ABC_FREE(newsubtables);
+            ABC_FREE(newvars);
+            unique->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        newinvperm = ABC_ALLOC(int,newsize);
+        if (newinvperm == NULL) {
+            ABC_FREE(newsubtables);
+            ABC_FREE(newvars);
+            ABC_FREE(newperm);
+            unique->errorCode = CUDD_MEMORY_OUT;
+            return(0);
+        }
+        if (unique->map != NULL) {
+            newmap = ABC_ALLOC(int,newsize);
+            if (newmap == NULL) {
+                ABC_FREE(newsubtables);
+                ABC_FREE(newvars);
+                ABC_FREE(newperm);
+                ABC_FREE(newinvperm);
+                unique->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            unique->memused += (newsize - unique->maxSize) * sizeof(int);
+        }
+        unique->memused += (newsize - unique->maxSize) * ((numSlots+1) *
+            sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable));
+        if (newsize > unique->maxSizeZ) {
+            ABC_FREE(unique->stack);
+            unique->stack = ABC_ALLOC(DdNodePtr,newsize + 1);
+            if (unique->stack == NULL) {
+                ABC_FREE(newsubtables);
+                ABC_FREE(newvars);
+                ABC_FREE(newperm);
+                ABC_FREE(newinvperm);
+                if (unique->map != NULL) {
+                    ABC_FREE(newmap);
+                }
+                unique->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            unique->stack[0] = NULL; /* to suppress harmless UMR */
+            unique->memused +=
+                (newsize - ddMax(unique->maxSize,unique->maxSizeZ))
+                * sizeof(DdNode *);
+        }
+        for (i = 0; i < oldsize; i++) {
+            newsubtables[i].slots = unique->subtables[i].slots;
+            newsubtables[i].shift = unique->subtables[i].shift;
+            newsubtables[i].keys = unique->subtables[i].keys;
+            newsubtables[i].maxKeys = unique->subtables[i].maxKeys;
+            newsubtables[i].dead = unique->subtables[i].dead;
+            newsubtables[i].nodelist = unique->subtables[i].nodelist;
+            newsubtables[i].bindVar = unique->subtables[i].bindVar;
+            newsubtables[i].varType = unique->subtables[i].varType;
+            newsubtables[i].pairIndex = unique->subtables[i].pairIndex;
+            newsubtables[i].varHandled = unique->subtables[i].varHandled;
+            newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped;
+
+            newvars[i] = unique->vars[i];
+            newperm[i] = unique->perm[i];
+            newinvperm[i] = unique->invperm[i];
+        }
+        for (i = oldsize; i <= index; i++) {
+            newsubtables[i].slots = numSlots;
+            newsubtables[i].shift = sizeof(int) * 8 -
+                cuddComputeFloorLog2(numSlots);
+            newsubtables[i].keys = 0;
+            newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
+            newsubtables[i].dead = 0;
+            newsubtables[i].bindVar = 0;
+            newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT;
+            newsubtables[i].pairIndex = 0;
+            newsubtables[i].varHandled = 0;
+            newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE;
+
+            newperm[i] = i;
+            newinvperm[i] = i;
+            newnodelist = newsubtables[i].nodelist = ABC_ALLOC(DdNodePtr, numSlots);
+            if (newnodelist == NULL) {
+                unique->errorCode = CUDD_MEMORY_OUT;
+                return(0);
+            }
+            for (j = 0; j < numSlots; j++) {
+                newnodelist[j] = sentinel;
+            }
+        }
+        if (unique->map != NULL) {
+            for (i = 0; i < oldsize; i++) {
+                newmap[i] = unique->map[i];
+            }
+            for (i = oldsize; i <= index; i++) {
+                newmap[i] = i;
+            }
+            ABC_FREE(unique->map);
+            unique->map = newmap;
+        }
+        ABC_FREE(unique->subtables);
+        unique->subtables = newsubtables;
+        unique->maxSize = newsize;
+        ABC_FREE(unique->vars);
+        unique->vars = newvars;
+        ABC_FREE(unique->perm);
+        unique->perm = newperm;
+        ABC_FREE(unique->invperm);
+        unique->invperm = newinvperm;
+    }
+
+    /* Now that the table is in a coherent state, create the new
+    ** projection functions. We need to temporarily disable reordering,
+    ** because we cannot reorder without projection functions in place.
+    **/
+    one = unique->one;
+    zero = Cudd_Not(one);
+
+    unique->size = index + 1;
+    unique->slots += (index + 1 - oldsize) * numSlots;
+    ddFixLimits(unique);
+
+    reorderSave = unique->autoDyn;
+    unique->autoDyn = 0;
+    for (i = oldsize; i <= index; i++) {
+        unique->vars[i] = cuddUniqueInter(unique,i,one,zero);
+        if (unique->vars[i] == NULL) {
+            unique->autoDyn = reorderSave;
+            for (j = oldsize; j < i; j++) {
+                Cudd_IterDerefBdd(unique,unique->vars[j]);
+                cuddDeallocNode(unique,unique->vars[j]);
+                unique->vars[j] = NULL;
+            }
+            for (j = oldsize; j <= index; j++) {
+                ABC_FREE(unique->subtables[j].nodelist);
+                unique->subtables[j].nodelist = NULL;
+            }
+            unique->size = oldsize;
+            unique->slots -= (index + 1 - oldsize) * numSlots;
+            ddFixLimits(unique);
+            return(0);
+        }
+        cuddRef(unique->vars[i]);
+    }
+    unique->autoDyn = reorderSave;
+
+    return(1);
+
+} /* end of ddResizeTable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Searches the subtables above node for a parent.]
+
+  Description [Searches the subtables above node for a parent. Returns 1
+  as soon as one parent is found. Returns 0 is the search is fruitless.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddFindParent(
+  DdManager * table,
+  DdNode * node)
+{
+    int         i,j;
+    int         slots;
+    DdNodePtr   *nodelist;
+    DdNode      *f;
+
+    for (i = cuddI(table,node->index) - 1; i >= 0; i--) {
+        nodelist = table->subtables[i].nodelist;
+        slots = table->subtables[i].slots;
+
+        for (j = 0; j < slots; j++) {
+            f = nodelist[j];
+            while (cuddT(f) > node) {
+                f = f->next;
+            }
+            while (cuddT(f) == node && Cudd_Regular(cuddE(f)) > node) {
+                f = f->next;
+            }
+            if (cuddT(f) == node && Cudd_Regular(cuddE(f)) == node) {
+                return(1);
+            }
+        }
+    }
+
+    return(0);
+
+} /* end of cuddFindParent */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adjusts the values of table limits.]
+
+  Description [Adjusts the values of table fields controlling the.
+  sizes of subtables and computed table. If the computed table is too small
+  according to the new values, it is resized.]
+
+  SideEffects [Modifies manager fields. May resize computed table.]
+
+  SeeAlso     []
+
+******************************************************************************/
+DD_INLINE
+static void
+ddFixLimits(
+  DdManager *unique)
+{
+    unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots);
+    unique->cacheSlack = (int) ddMin(unique->maxCacheHard,
+        DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots) -
+        2 * (int) unique->cacheSlots;
+    if (unique->cacheSlots < unique->slots/2 && unique->cacheSlack >= 0)
+        cuddCacheResize(unique);
+    return;
+
+} /* end of ddFixLimits */
+
+
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+/**Function********************************************************************
+
+  Synopsis    [Inserts a DdNode in a red/black search tree.]
+
+  Description [Inserts a DdNode in a red/black search tree. Nodes from
+  the same "page" (defined by DD_PAGE_MASK) are linked in a LIFO list.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddOrderedThread]
+
+******************************************************************************/
+static void
+cuddOrderedInsert(
+  DdNodePtr * root,
+  DdNodePtr node)
+{
+    DdNode *scan;
+    DdNodePtr *scanP;
+    DdNodePtr *stack[DD_STACK_SIZE];
+    int stackN = 0;
+
+    scanP = root;
+    while ((scan = *scanP) != NULL) {
+        stack[stackN++] = scanP;
+        if (DD_INSERT_COMPARE(node, scan) == 0) { /* add to page list */
+            DD_NEXT(node) = DD_NEXT(scan);
+            DD_NEXT(scan) = node;
+            return;
+        }
+        scanP = (node < scan) ? &DD_LEFT(scan) : &DD_RIGHT(scan);
+    }
+    DD_RIGHT(node) = DD_LEFT(node) = DD_NEXT(node) = NULL;
+    DD_COLOR(node) = DD_RED;
+    *scanP = node;
+    stack[stackN] = &node;
+    cuddDoRebalance(stack,stackN);
+
+} /* end of cuddOrderedInsert */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Threads all the nodes of a search tree into a linear list.]
+
+  Description [Threads all the nodes of a search tree into a linear
+  list. For each node of the search tree, the "left" child, if non-null, has
+  a lower address than its parent, and the "right" child, if non-null, has a
+  higher address than its parent.
+  The list is sorted in order of increasing addresses. The search
+  tree is destroyed as a result of this operation. The last element of
+  the linear list is made to point to the address passed in list. Each
+  node if the search tree is a linearly-linked list of nodes from the
+  same memory page (as defined in DD_PAGE_MASK). When a node is added to
+  the linear list, all the elements of the linked list are added.]
+
+  SideEffects [The search tree is destroyed as a result of this operation.]
+
+  SeeAlso     [cuddOrderedInsert]
+
+******************************************************************************/
+static DdNode *
+cuddOrderedThread(
+  DdNode * root,
+  DdNode * list)
+{
+    DdNode *current, *next, *prev, *end;
+
+    current = root;
+    /* The first word in the node is used to implement a stack that holds
+    ** the nodes from the root of the tree to the current node. Here we
+    ** put the root of the tree at the bottom of the stack.
+    */
+    *((DdNodePtr *) current) = NULL;
+
+    while (current != NULL) {
+        if (DD_RIGHT(current) != NULL) {
+            /* If possible, we follow the "right" link. Eventually we'll
+            ** find the node with the largest address in the current tree.
+            ** In this phase we use the first word of a node to implemen
+            ** a stack of the nodes on the path from the root to "current".
+            ** Also, we disconnect the "right" pointers to indicate that
+            ** we have already followed them.
+            */
+            next = DD_RIGHT(current);
+            DD_RIGHT(current) = NULL;
+            *((DdNodePtr *)next) = current;
+            current = next;
+        } else {
+            /* We can't proceed along the "right" links any further.
+            ** Hence "current" is the largest element in the current tree.
+            ** We make this node the new head of "list". (Repeating this
+            ** operation until the tree is empty yields the desired linear
+            ** threading of all nodes.)
+            */
+            prev = *((DdNodePtr *) current); /* save prev node on stack in prev */
+            /* Traverse the linked list of current until the end. */
+            for (end = current; DD_NEXT(end) != NULL; end = DD_NEXT(end));
+            DD_NEXT(end) = list; /* attach "list" at end and make */
+            list = current;   /* "current" the new head of "list" */
+            /* Now, if current has a "left" child, we push it on the stack.
+            ** Otherwise, we just continue with the parent of "current".
+            */
+            if (DD_LEFT(current) != NULL) {
+                next = DD_LEFT(current);
+                *((DdNodePtr *) next) = prev;
+                current = next;
+            } else {
+                current = prev;
+            }
+        }
+    }
+
+    return(list);
+
+} /* end of cuddOrderedThread */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the left rotation for red/black trees.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddRotateRight]
+
+******************************************************************************/
+DD_INLINE
+static void
+cuddRotateLeft(
+  DdNodePtr * nodeP)
+{
+    DdNode *newRoot;
+    DdNode *oldRoot = *nodeP;
+
+    *nodeP = newRoot = DD_RIGHT(oldRoot);
+    DD_RIGHT(oldRoot) = DD_LEFT(newRoot);
+    DD_LEFT(newRoot) = oldRoot;
+
+} /* end of cuddRotateLeft */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the right rotation for red/black trees.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddRotateLeft]
+
+******************************************************************************/
+DD_INLINE
+static void
+cuddRotateRight(
+  DdNodePtr * nodeP)
+{
+    DdNode *newRoot;
+    DdNode *oldRoot = *nodeP;
+
+    *nodeP = newRoot = DD_LEFT(oldRoot);
+    DD_LEFT(oldRoot) = DD_RIGHT(newRoot);
+    DD_RIGHT(newRoot) = oldRoot;
+
+} /* end of cuddRotateRight */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Rebalances a red/black tree.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+cuddDoRebalance(
+  DdNodePtr ** stack,
+  int  stackN)
+{
+    DdNodePtr *xP, *parentP, *grandpaP;
+    DdNode *x, *y, *parent, *grandpa;
+
+    xP = stack[stackN];
+    x = *xP;
+    /* Work our way back up, re-balancing the tree. */
+    while (--stackN >= 0) {
+        parentP = stack[stackN];
+        parent = *parentP;
+        if (DD_IS_BLACK(parent)) break;
+        /* Since the root is black, here a non-null grandparent exists. */
+        grandpaP = stack[stackN-1];
+        grandpa = *grandpaP;
+        if (parent == DD_LEFT(grandpa)) {
+            y = DD_RIGHT(grandpa);
+            if (y != NULL && DD_IS_RED(y)) {
+                DD_COLOR(parent) = DD_BLACK;
+                DD_COLOR(y) = DD_BLACK;
+                DD_COLOR(grandpa) = DD_RED;
+                x = grandpa;
+                stackN--;
+            } else {
+                if (x == DD_RIGHT(parent)) {
+                    cuddRotateLeft(parentP);
+                    DD_COLOR(x) = DD_BLACK;
+                } else {
+                    DD_COLOR(parent) = DD_BLACK;
+                }
+                DD_COLOR(grandpa) = DD_RED;
+                cuddRotateRight(grandpaP);
+                break;
+            }
+        } else {
+            y = DD_LEFT(grandpa);
+            if (y != NULL && DD_IS_RED(y)) {
+                DD_COLOR(parent) = DD_BLACK;
+                DD_COLOR(y) = DD_BLACK;
+                DD_COLOR(grandpa) = DD_RED;
+                x = grandpa;
+                stackN--;
+            } else {
+                if (x == DD_LEFT(parent)) {
+                    cuddRotateRight(parentP);
+                    DD_COLOR(x) = DD_BLACK;
+                } else {
+                    DD_COLOR(parent) = DD_BLACK;
+                }
+                DD_COLOR(grandpa) = DD_RED;
+                cuddRotateLeft(grandpaP);
+            }
+        }
+    }
+    DD_COLOR(*(stack[0])) = DD_BLACK;
+
+} /* end of cuddDoRebalance */
+#endif
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis    [Fixes a variable tree after the insertion of new subtables.]
+
+  Description [Fixes a variable tree after the insertion of new subtables.
+  After such an insertion, the low fields of the tree below the insertion
+  point are inconsistent.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ddPatchTree(
+  DdManager *dd,
+  MtrNode *treenode)
+{
+    MtrNode *auxnode = treenode;
+
+    while (auxnode != NULL) {
+        auxnode->low = dd->perm[auxnode->index];
+        if (auxnode->child != NULL) {
+            ddPatchTree(dd, auxnode->child);
+        }
+        auxnode = auxnode->younger;
+    }
+
+    return;
+
+} /* end of ddPatchTree */
+
+
+#ifdef DD_DEBUG
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a collision list is ordered.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddCheckCollisionOrdering(
+  DdManager *unique,
+  int i,
+  int j)
+{
+    int slots;
+    DdNode *node, *next;
+    DdNodePtr *nodelist;
+    DdNode *sentinel = &(unique->sentinel);
+
+    nodelist = unique->subtables[i].nodelist;
+    slots = unique->subtables[i].slots;
+    node = nodelist[j];
+    if (node == sentinel) return(1);
+    next = node->next;
+    while (next != sentinel) {
+        if (cuddT(node) < cuddT(next) ||
+            (cuddT(node) == cuddT(next) && cuddE(node) < cuddE(next))) {
+            (void) fprintf(unique->err,
+                           "Unordered list: index %u, position %d\n", i, j);
+            return(0);
+        }
+        node = next;
+        next = node->next;
+    }
+    return(1);
+
+} /* end of cuddCheckCollisionOrdering */
+#endif
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reports problem in garbage collection.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddGarbageCollect cuddGarbageCollectZdd]
+
+******************************************************************************/
+static void
+ddReportRefMess(
+  DdManager *unique /* manager */,
+  int i /* table in which the problem occurred */,
+  const char *caller /* procedure that detected the problem */)
+{
+    if (i == CUDD_CONST_INDEX) {
+        (void) fprintf(unique->err,
+                           "%s: problem in constants\n", caller);
+    } else if (i != -1) {
+        (void) fprintf(unique->err,
+                           "%s: problem in table %d\n", caller, i);
+    }
+    (void) fprintf(unique->err, "  dead count != deleted\n");
+    (void) fprintf(unique->err, "  This problem is often due to a missing \
+call to Cudd_Ref\n  or to an extra call to Cudd_RecursiveDeref.\n  \
+See the CUDD Programmer's Guide for additional details.");
+    abort();
+
+} /* end of ddReportRefMess */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddUtil.c b/abc-build/src/bdd/cudd/cuddUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddUtil.c
@@ -0,0 +1,3937 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddUtil.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Utility functions.]
+
+  Description [External procedures included in this module:
+                <ul>
+                <li> Cudd_PrintMinterm()
+                <li> Cudd_bddPrintCover()
+                <li> Cudd_PrintDebug()
+                <li> Cudd_DagSize()
+                <li> Cudd_EstimateCofactor()
+                <li> Cudd_EstimateCofactorSimple()
+                <li> Cudd_SharingSize()
+                <li> Cudd_CountMinterm()
+                <li> Cudd_EpdCountMinterm()
+                <li> Cudd_CountPath()
+                <li> Cudd_CountPathsToNonZero()
+                <li> Cudd_Support()
+                <li> Cudd_SupportIndex()
+                <li> Cudd_SupportSize()
+                <li> Cudd_VectorSupport()
+                <li> Cudd_VectorSupportIndex()
+                <li> Cudd_VectorSupportSize()
+                <li> Cudd_ClassifySupport()
+                <li> Cudd_CountLeaves()
+                <li> Cudd_bddPickOneCube()
+                <li> Cudd_bddPickOneMinterm()
+                <li> Cudd_bddPickArbitraryMinterms()
+                <li> Cudd_SubsetWithMaskVars()
+                <li> Cudd_FirstCube()
+                <li> Cudd_NextCube()
+                <li> Cudd_bddComputeCube()
+                <li> Cudd_addComputeCube()
+                <li> Cudd_FirstNode()
+                <li> Cudd_NextNode()
+                <li> Cudd_GenFree()
+                <li> Cudd_IsGenEmpty()
+                <li> Cudd_IndicesToCube()
+                <li> Cudd_PrintVersion()
+                <li> Cudd_AverageDistance()
+                <li> Cudd_Random()
+                <li> Cudd_Srandom()
+                <li> Cudd_Density()
+                </ul>
+        Internal procedures included in this module:
+                <ul>
+                <li> cuddP()
+                <li> cuddStCountfree()
+                <li> cuddCollectNodes()
+                <li> cuddNodeArray()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> dp2()
+                <li> ddPrintMintermAux()
+                <li> ddDagInt()
+                <li> ddCountMintermAux()
+                <li> ddEpdCountMintermAux()
+                <li> ddCountPathAux()
+                <li> ddSupportStep()
+                <li> ddClearFlag()
+                <li> ddLeavesInt()
+                <li> ddPickArbitraryMinterms()
+                <li> ddPickRepresentativeCube()
+                <li> ddEpdFree()
+                </ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* Random generator constants. */
+#define MODULUS1 2147483563
+#define LEQA1 40014
+#define LEQQ1 53668
+#define LEQR1 12211
+#define MODULUS2 2147483399
+#define LEQA2 40692
+#define LEQQ2 52774
+#define LEQR2 3791
+#define STAB_SIZE 64
+#define STAB_DIV (1 + (MODULUS1 - 1) / STAB_SIZE)
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddUtil.c,v 1.81 2009/03/08 02:49:02 fabio Exp $";
+#endif
+
+static  DdNode  *background, *zero;
+
+static  long cuddRand = 0;
+static  long cuddRand2;
+static  long shuffleSelect;
+static  long shuffleTable[STAB_SIZE];
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#define bang(f) ((Cudd_IsComplement(f)) ? '!' : ' ')
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int dp2 (DdManager *dd, DdNode *f, st__table *t);
+static void ddPrintMintermAux (DdManager *dd, DdNode *node, int *list);
+static int ddDagInt (DdNode *n);
+static int cuddNodeArrayRecur (DdNode *f, DdNodePtr *table, int index);
+static int cuddEstimateCofactor (DdManager *dd, st__table *table, DdNode * node, int i, int phase, DdNode ** ptr);
+static DdNode * cuddUniqueLookup (DdManager * unique, int  index, DdNode * T, DdNode * E);
+static int cuddEstimateCofactorSimple (DdNode * node, int i);
+static double ddCountMintermAux (DdNode *node, double max, DdHashTable *table);
+static int ddEpdCountMintermAux (DdNode *node, EpDouble *max, EpDouble *epd, st__table *table);
+static double ddCountPathAux (DdNode *node, st__table *table);
+static double ddCountPathsToNonZero (DdNode * N, st__table * table);
+static void ddSupportStep (DdNode *f, int *support);
+static void ddClearFlag (DdNode *f);
+static int ddLeavesInt (DdNode *n);
+static int ddPickArbitraryMinterms (DdManager *dd, DdNode *node, int nvars, int nminterms, char **string);
+static int ddPickRepresentativeCube (DdManager *dd, DdNode *node, double *weight, char *string);
+static enum st__retval ddEpdFree (char * key, char * value, char * arg);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a disjoint sum of products.]
+
+  Description [Prints a disjoint sum of product cover for the function
+  rooted at node. Each product corresponds to a path from node to a
+  leaf node different from the logical zero, and different from the
+  background value. Uses the package default output file.  Returns 1
+  if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrintDebug Cudd_bddPrintCover]
+
+******************************************************************************/
+int
+Cudd_PrintMinterm(
+  DdManager * manager,
+  DdNode * node)
+{
+    int         i, *list;
+
+    background = manager->background;
+    zero = Cudd_Not(manager->one);
+    list = ABC_ALLOC(int,manager->size);
+    if (list == NULL) {
+        manager->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    for (i = 0; i < manager->size; i++) list[i] = 2;
+    ddPrintMintermAux(manager,node,list);
+    ABC_FREE(list);
+    return(1);
+
+} /* end of Cudd_PrintMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a sum of prime implicants of a BDD.]
+
+  Description [Prints a sum of product cover for an incompletely
+  specified function given by a lower bound and an upper bound.  Each
+  product is a prime implicant obtained by expanding the product
+  corresponding to a path from node to the constant one.  Uses the
+  package default output file.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrintMinterm]
+
+******************************************************************************/
+int
+Cudd_bddPrintCover(
+  DdManager *dd,
+  DdNode *l,
+  DdNode *u)
+{
+    int *array;
+    int q, result;
+    DdNode *lb;
+#ifdef DD_DEBUG
+    DdNode *cover;
+#endif
+
+    array = ABC_ALLOC(int, Cudd_ReadSize(dd));
+    if (array == NULL) return(0);
+    lb = l;
+    cuddRef(lb);
+#ifdef DD_DEBUG
+    cover = Cudd_ReadLogicZero(dd);
+    cuddRef(cover);
+#endif
+    while (lb != Cudd_ReadLogicZero(dd)) {
+        DdNode *implicant, *prime, *tmp;
+        int length;
+        implicant = Cudd_LargestCube(dd,lb,&length);
+        if (implicant == NULL) {
+            Cudd_RecursiveDeref(dd,lb);
+            ABC_FREE(array);
+            return(0);
+        }
+        cuddRef(implicant);
+        prime = Cudd_bddMakePrime(dd,implicant,u);
+        if (prime == NULL) {
+            Cudd_RecursiveDeref(dd,lb);
+            Cudd_RecursiveDeref(dd,implicant);
+            ABC_FREE(array);
+            return(0);
+        }
+        cuddRef(prime);
+        Cudd_RecursiveDeref(dd,implicant);
+        tmp = Cudd_bddAnd(dd,lb,Cudd_Not(prime));
+        if (tmp == NULL) {
+            Cudd_RecursiveDeref(dd,lb);
+            Cudd_RecursiveDeref(dd,prime);
+            ABC_FREE(array);
+            return(0);
+        }
+        cuddRef(tmp);
+        Cudd_RecursiveDeref(dd,lb);
+        lb = tmp;
+        result = Cudd_BddToCubeArray(dd,prime,array);
+        if (result == 0) {
+            Cudd_RecursiveDeref(dd,lb);
+            Cudd_RecursiveDeref(dd,prime);
+            ABC_FREE(array);
+            return(0);
+        }
+        for (q = 0; q < dd->size; q++) {
+            switch (array[q]) {
+            case 0:
+                (void) fprintf(dd->out, "0");
+                break;
+            case 1:
+                (void) fprintf(dd->out, "1");
+                break;
+            case 2:
+                (void) fprintf(dd->out, "-");
+                break;
+            default:
+                (void) fprintf(dd->out, "?");
+            }
+        }
+        (void) fprintf(dd->out, " 1\n");
+#ifdef DD_DEBUG
+        tmp = Cudd_bddOr(dd,prime,cover);
+        if (tmp == NULL) {
+            Cudd_RecursiveDeref(dd,cover);
+            Cudd_RecursiveDeref(dd,lb);
+            Cudd_RecursiveDeref(dd,prime);
+            ABC_FREE(array);
+            return(0);
+        }
+        cuddRef(tmp);
+        Cudd_RecursiveDeref(dd,cover);
+        cover = tmp;
+#endif
+        Cudd_RecursiveDeref(dd,prime);
+    }
+    (void) fprintf(dd->out, "\n");
+    Cudd_RecursiveDeref(dd,lb);
+    ABC_FREE(array);
+#ifdef DD_DEBUG
+    if (!Cudd_bddLeq(dd,cover,u) || !Cudd_bddLeq(dd,l,cover)) {
+        Cudd_RecursiveDeref(dd,cover);
+        return(0);
+    }
+    Cudd_RecursiveDeref(dd,cover);
+#endif
+    return(1);
+
+} /* end of Cudd_bddPrintCover */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints to the standard output a DD and its statistics.]
+
+  Description [Prints to the standard output a DD and its statistics.
+  The statistics include the number of nodes, the number of leaves, and
+  the number of minterms. (The number of minterms is the number of
+  assignments to the variables that cause the function to be different
+  from the logical zero (for BDDs) and from the background value (for
+  ADDs.) The statistics are printed if pr &gt; 0. Specifically:
+  <ul>
+  <li> pr = 0 : prints nothing
+  <li> pr = 1 : prints counts of nodes and minterms
+  <li> pr = 2 : prints counts + disjoint sum of product
+  <li> pr = 3 : prints counts + list of nodes
+  <li> pr &gt; 3 : prints counts + disjoint sum of product + list of nodes
+  </ul>
+  For the purpose of counting the number of minterms, the function is
+  supposed to depend on n variables. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DagSize Cudd_CountLeaves Cudd_CountMinterm
+  Cudd_PrintMinterm]
+
+******************************************************************************/
+int
+Cudd_PrintDebug(
+  DdManager * dd,
+  DdNode * f,
+  int  n,
+  int  pr)
+{
+    DdNode *azero, *bzero;
+    int    nodes;
+    int    leaves;
+    double minterms;
+    int    retval = 1;
+
+    if (f == NULL) {
+        (void) fprintf(dd->out,": is the NULL DD\n");
+        (void) fflush(dd->out);
+        return(0);
+    }
+    azero = DD_ZERO(dd);
+    bzero = Cudd_Not(DD_ONE(dd));
+    if ((f == azero || f == bzero) && pr > 0){
+       (void) fprintf(dd->out,": is the zero DD\n");
+       (void) fflush(dd->out);
+       return(1);
+    }
+    if (pr > 0) {
+        nodes = Cudd_DagSize(f);
+        if (nodes == CUDD_OUT_OF_MEM) retval = 0;
+        leaves = Cudd_CountLeaves(f);
+        if (leaves == CUDD_OUT_OF_MEM) retval = 0;
+        minterms = Cudd_CountMinterm(dd, f, n);
+        if (minterms == (double)CUDD_OUT_OF_MEM) retval = 0;
+        (void) fprintf(dd->out,": %d nodes %d leaves %g minterms\n",
+                       nodes, leaves, minterms);
+        if (pr > 2) {
+            if (!cuddP(dd, f)) retval = 0;
+        }
+        if (pr == 2 || pr > 3) {
+            if (!Cudd_PrintMinterm(dd,f)) retval = 0;
+            (void) fprintf(dd->out,"\n");
+        }
+        (void) fflush(dd->out);
+    }
+    return(retval);
+
+} /* end of Cudd_PrintDebug */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of nodes in a DD.]
+
+  Description [Counts the number of nodes in a DD. Returns the number
+  of nodes in the graph rooted at node.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SharingSize Cudd_PrintDebug]
+
+******************************************************************************/
+int
+Cudd_DagSize(
+  DdNode * node)
+{
+    int i;
+
+    i = ddDagInt(Cudd_Regular(node));
+    ddClearFlag(Cudd_Regular(node));
+
+    return(i);
+
+} /* end of Cudd_DagSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Estimates the number of nodes in a cofactor of a DD.]
+
+  Description [Estimates the number of nodes in a cofactor of a DD.
+  Returns an estimate of the number of nodes in a cofactor of
+  the graph rooted at node with respect to the variable whose index is i.
+  In case of failure, returns CUDD_OUT_OF_MEM.
+  This function uses a refinement of the algorithm of Cabodi et al.
+  (ICCAD96). The refinement allows the procedure to account for part
+  of the recombination that may occur in the part of the cofactor above
+  the cofactoring variable. This procedure does no create any new node.
+  It does keep a small table of results; therefore it may run out of memory.
+  If this is a concern, one should use Cudd_EstimateCofactorSimple, which
+  is faster, does not allocate any memory, but is less accurate.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DagSize Cudd_EstimateCofactorSimple]
+
+******************************************************************************/
+int
+Cudd_EstimateCofactor(
+  DdManager *dd /* manager */,
+  DdNode * f    /* function */,
+  int i         /* index of variable */,
+  int phase     /* 1: positive; 0: negative */
+  )
+{
+    int val;
+    DdNode *ptr;
+    st__table *table;
+
+    table = st__init_table( st__ptrcmp, st__ptrhash);
+    if (table == NULL) return(CUDD_OUT_OF_MEM);
+    val = cuddEstimateCofactor(dd,table,Cudd_Regular(f),i,phase,&ptr);
+    ddClearFlag(Cudd_Regular(f));
+    st__free_table(table);
+
+    return(val);
+
+} /* end of Cudd_EstimateCofactor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Estimates the number of nodes in a cofactor of a DD.]
+
+  Description [Estimates the number of nodes in a cofactor of a DD.
+  Returns an estimate of the number of nodes in the positive cofactor of
+  the graph rooted at node with respect to the variable whose index is i.
+  This procedure implements with minor changes the algorithm of Cabodi et al.
+  (ICCAD96). It does not allocate any memory, it does not change the
+  state of the manager, and it is fast. However, it has been observed to
+  overestimate the size of the cofactor by as much as a factor of 2.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DagSize]
+
+******************************************************************************/
+int
+Cudd_EstimateCofactorSimple(
+  DdNode * node,
+  int i)
+{
+    int val;
+
+    val = cuddEstimateCofactorSimple(Cudd_Regular(node),i);
+    ddClearFlag(Cudd_Regular(node));
+
+    return(val);
+
+} /* end of Cudd_EstimateCofactorSimple */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of nodes in an array of DDs.]
+
+  Description [Counts the number of nodes in an array of DDs. Shared
+  nodes are counted only once.  Returns the total number of nodes.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DagSize]
+
+******************************************************************************/
+int
+Cudd_SharingSize(
+  DdNode ** nodeArray,
+  int  n)
+{
+    int i,j;
+
+    i = 0;
+    for (j = 0; j < n; j++) {
+        i += ddDagInt(Cudd_Regular(nodeArray[j]));
+    }
+    for (j = 0; j < n; j++) {
+        ddClearFlag(Cudd_Regular(nodeArray[j]));
+    }
+    return(i);
+
+} /* end of Cudd_SharingSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of minterms of a DD.]
+
+  Description [Counts the number of minterms of a DD. The function is
+  assumed to depend on nvars variables. The minterm count is
+  represented as a double, to allow for a larger number of variables.
+  Returns the number of minterms of the function rooted at node if
+  successful; (double) CUDD_OUT_OF_MEM otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrintDebug Cudd_CountPath]
+
+******************************************************************************/
+double
+Cudd_CountMinterm(
+  DdManager * manager,
+  DdNode * node,
+  int  nvars)
+{
+    double      max;
+    DdHashTable *table;
+    double      res;
+    CUDD_VALUE_TYPE epsilon;
+
+    background = manager->background;
+    zero = Cudd_Not(manager->one);
+
+    max = pow(2.0,(double)nvars);
+    table = cuddHashTableInit(manager,1,2);
+    if (table == NULL) {
+        return((double)CUDD_OUT_OF_MEM);
+    }
+    epsilon = Cudd_ReadEpsilon(manager);
+    Cudd_SetEpsilon(manager,(CUDD_VALUE_TYPE)0.0);
+    res = ddCountMintermAux(node,max,table);
+    cuddHashTableQuit(table);
+    Cudd_SetEpsilon(manager,epsilon);
+
+    return(res);
+
+} /* end of Cudd_CountMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of paths of a DD.]
+
+  Description [Counts the number of paths of a DD.  Paths to all
+  terminal nodes are counted. The path count is represented as a
+  double, to allow for a larger number of variables.  Returns the
+  number of paths of the function rooted at node if successful;
+  (double) CUDD_OUT_OF_MEM otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_CountMinterm]
+
+******************************************************************************/
+double
+Cudd_CountPath(
+  DdNode * node)
+{
+
+    st__table    *table;
+    double      i;
+
+    table = st__init_table( st__ptrcmp, st__ptrhash);
+    if (table == NULL) {
+        return((double)CUDD_OUT_OF_MEM);
+    }
+    i = ddCountPathAux(Cudd_Regular(node),table);
+    st__foreach(table, cuddStCountfree, NULL);
+    st__free_table(table);
+    return(i);
+
+} /* end of Cudd_CountPath */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of minterms of a DD with extended precision.]
+
+  Description [Counts the number of minterms of a DD with extended precision.
+  The function is assumed to depend on nvars variables. The minterm count is
+  represented as an EpDouble, to allow any number of variables.
+  Returns 0 if successful; CUDD_OUT_OF_MEM otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrintDebug Cudd_CountPath]
+
+******************************************************************************/
+int
+Cudd_EpdCountMinterm(
+  DdManager * manager,
+  DdNode * node,
+  int  nvars,
+  EpDouble * epd)
+{
+    EpDouble    max, tmp;
+    st__table    *table;
+    int         status;
+
+    background = manager->background;
+    zero = Cudd_Not(manager->one);
+
+    EpdPow2(nvars, &max);
+    table = st__init_table(EpdCmp, st__ptrhash);
+    if (table == NULL) {
+        EpdMakeZero(epd, 0);
+        return(CUDD_OUT_OF_MEM);
+    }
+    status = ddEpdCountMintermAux(Cudd_Regular(node),&max,epd,table);
+    st__foreach(table, ddEpdFree, NULL);
+    st__free_table(table);
+    if (status == CUDD_OUT_OF_MEM) {
+        EpdMakeZero(epd, 0);
+        return(CUDD_OUT_OF_MEM);
+    }
+    if (Cudd_IsComplement(node)) {
+        EpdSubtract3(&max, epd, &tmp);
+        EpdCopy(&tmp, epd);
+    }
+    return(0);
+
+} /* end of Cudd_EpdCountMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of paths to a non-zero terminal of a DD.]
+
+  Description [Counts the number of paths to a non-zero terminal of a
+  DD.  The path count is
+  represented as a double, to allow for a larger number of variables.
+  Returns the number of paths of the function rooted at node.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_CountMinterm Cudd_CountPath]
+
+******************************************************************************/
+double
+Cudd_CountPathsToNonZero(
+  DdNode * node)
+{
+
+    st__table    *table;
+    double      i;
+
+    table = st__init_table( st__ptrcmp, st__ptrhash);
+    if (table == NULL) {
+        return((double)CUDD_OUT_OF_MEM);
+    }
+    i = ddCountPathsToNonZero(node,table);
+    st__foreach(table, cuddStCountfree, NULL);
+    st__free_table(table);
+    return(i);
+
+} /* end of Cudd_CountPathsToNonZero */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the variables on which a DD depends.]
+
+  Description [Finds the variables on which a DD depends.
+  Returns a BDD consisting of the product of the variables if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_VectorSupport Cudd_ClassifySupport]
+
+******************************************************************************/
+DdNode *
+Cudd_Support(
+  DdManager * dd /* manager */,
+  DdNode * f /* DD whose support is sought */)
+{
+    int *support;
+    DdNode *res, *tmp, *var;
+    int i,j;
+    int size;
+
+    /* Allocate and initialize support array for ddSupportStep. */
+    size = ddMax(dd->size, dd->sizeZ);
+    support = ABC_ALLOC(int,size);
+    if (support == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    for (i = 0; i < size; i++) {
+        support[i] = 0;
+    }
+
+    /* Compute support and clean up markers. */
+    ddSupportStep(Cudd_Regular(f),support);
+    ddClearFlag(Cudd_Regular(f));
+
+    /* Transform support from array to cube. */
+    do {
+        dd->reordered = 0;
+        res = DD_ONE(dd);
+        cuddRef(res);
+        for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */
+            i = (j >= dd->size) ? j : dd->invperm[j];
+            if (support[i] == 1) {
+                /* The following call to cuddUniqueInter is guaranteed
+                ** not to trigger reordering because the node we look up
+                ** already exists. */
+                var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
+                cuddRef(var);
+                tmp = cuddBddAndRecur(dd,res,var);
+                if (tmp == NULL) {
+                    Cudd_RecursiveDeref(dd,res);
+                    Cudd_RecursiveDeref(dd,var);
+                    res = NULL;
+                    break;
+                }
+                cuddRef(tmp);
+                Cudd_RecursiveDeref(dd,res);
+                Cudd_RecursiveDeref(dd,var);
+                res = tmp;
+            }
+        }
+    } while (dd->reordered == 1);
+
+    ABC_FREE(support);
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_Support */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the variables on which a DD depends.]
+
+  Description [Finds the variables on which a DD depends.  Returns an
+  index array of the variables if successful; NULL otherwise.  The
+  size of the array equals the number of variables in the manager.
+  Each entry of the array is 1 if the corresponding variable is in the
+  support of the DD and 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Support Cudd_VectorSupport Cudd_ClassifySupport]
+
+******************************************************************************/
+int *
+Cudd_SupportIndex(
+  DdManager * dd /* manager */,
+  DdNode * f /* DD whose support is sought */)
+{
+    int *support;
+    int i;
+    int size;
+
+    /* Allocate and initialize support array for ddSupportStep. */
+    size = ddMax(dd->size, dd->sizeZ);
+    support = ABC_ALLOC(int,size);
+    if (support == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    for (i = 0; i < size; i++) {
+        support[i] = 0;
+    }
+
+    /* Compute support and clean up markers. */
+    ddSupportStep(Cudd_Regular(f),support);
+    ddClearFlag(Cudd_Regular(f));
+
+    return(support);
+
+} /* end of Cudd_SupportIndex */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the variables on which a DD depends.]
+
+  Description [Counts the variables on which a DD depends.
+  Returns the number of the variables if successful; CUDD_OUT_OF_MEM
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Support]
+
+******************************************************************************/
+int
+Cudd_SupportSize(
+  DdManager * dd /* manager */,
+  DdNode * f /* DD whose support size is sought */)
+{
+    int *support;
+    int i;
+    int size;
+    int count;
+
+    /* Allocate and initialize support array for ddSupportStep. */
+    size = ddMax(dd->size, dd->sizeZ);
+    support = ABC_ALLOC(int,size);
+    if (support == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(CUDD_OUT_OF_MEM);
+    }
+    for (i = 0; i < size; i++) {
+        support[i] = 0;
+    }
+
+    /* Compute support and clean up markers. */
+    ddSupportStep(Cudd_Regular(f),support);
+    ddClearFlag(Cudd_Regular(f));
+
+    /* Count support variables. */
+    count = 0;
+    for (i = 0; i < size; i++) {
+        if (support[i] == 1) count++;
+    }
+
+    ABC_FREE(support);
+    return(count);
+
+} /* end of Cudd_SupportSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the variables on which a set of DDs depends.]
+
+  Description [Finds the variables on which a set of DDs depends.
+  The set must contain either BDDs and ADDs, or ZDDs.
+  Returns a BDD consisting of the product of the variables if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Support Cudd_ClassifySupport]
+
+******************************************************************************/
+DdNode *
+Cudd_VectorSupport(
+  DdManager * dd /* manager */,
+  DdNode ** F /* array of DDs whose support is sought */,
+  int  n /* size of the array */)
+{
+    int *support;
+    DdNode *res, *tmp, *var;
+    int i,j;
+    int size;
+
+    /* Allocate and initialize support array for ddSupportStep. */
+    size = ddMax(dd->size, dd->sizeZ);
+    support = ABC_ALLOC(int,size);
+    if (support == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    for (i = 0; i < size; i++) {
+        support[i] = 0;
+    }
+
+    /* Compute support and clean up markers. */
+    for (i = 0; i < n; i++) {
+        ddSupportStep(Cudd_Regular(F[i]),support);
+    }
+    for (i = 0; i < n; i++) {
+        ddClearFlag(Cudd_Regular(F[i]));
+    }
+
+    /* Transform support from array to cube. */
+    res = DD_ONE(dd);
+    cuddRef(res);
+    for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */
+        i = (j >= dd->size) ? j : dd->invperm[j];
+        if (support[i] == 1) {
+            var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
+            cuddRef(var);
+            tmp = Cudd_bddAnd(dd,res,var);
+            if (tmp == NULL) {
+                Cudd_RecursiveDeref(dd,res);
+                Cudd_RecursiveDeref(dd,var);
+                ABC_FREE(support);
+                return(NULL);
+            }
+            cuddRef(tmp);
+            Cudd_RecursiveDeref(dd,res);
+            Cudd_RecursiveDeref(dd,var);
+            res = tmp;
+        }
+    }
+
+    ABC_FREE(support);
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_VectorSupport */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the variables on which a set of DDs depends.]
+
+  Description [Finds the variables on which a set of DDs depends.
+  The set must contain either BDDs and ADDs, or ZDDs.
+  Returns an index array of the variables if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SupportIndex Cudd_VectorSupport Cudd_ClassifySupport]
+
+******************************************************************************/
+int *
+Cudd_VectorSupportIndex(
+  DdManager * dd /* manager */,
+  DdNode ** F /* array of DDs whose support is sought */,
+  int  n /* size of the array */)
+{
+    int *support;
+    int i;
+    int size;
+
+    /* Allocate and initialize support array for ddSupportStep. */
+    size = ddMax(dd->size, dd->sizeZ);
+    support = ABC_ALLOC(int,size);
+    if (support == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    for (i = 0; i < size; i++) {
+        support[i] = 0;
+    }
+
+    /* Compute support and clean up markers. */
+    for (i = 0; i < n; i++) {
+        ddSupportStep(Cudd_Regular(F[i]),support);
+    }
+    for (i = 0; i < n; i++) {
+        ddClearFlag(Cudd_Regular(F[i]));
+    }
+
+    return(support);
+
+} /* end of Cudd_VectorSupportIndex */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the variables on which a set of DDs depends.]
+
+  Description [Counts the variables on which a set of DDs depends.
+  The set must contain either BDDs and ADDs, or ZDDs.
+  Returns the number of the variables if successful; CUDD_OUT_OF_MEM
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_VectorSupport Cudd_SupportSize]
+
+******************************************************************************/
+int
+Cudd_VectorSupportSize(
+  DdManager * dd /* manager */,
+  DdNode ** F /* array of DDs whose support is sought */,
+  int  n /* size of the array */)
+{
+    int *support;
+    int i;
+    int size;
+    int count;
+
+    /* Allocate and initialize support array for ddSupportStep. */
+    size = ddMax(dd->size, dd->sizeZ);
+    support = ABC_ALLOC(int,size);
+    if (support == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(CUDD_OUT_OF_MEM);
+    }
+    for (i = 0; i < size; i++) {
+        support[i] = 0;
+    }
+
+    /* Compute support and clean up markers. */
+    for (i = 0; i < n; i++) {
+        ddSupportStep(Cudd_Regular(F[i]),support);
+    }
+    for (i = 0; i < n; i++) {
+        ddClearFlag(Cudd_Regular(F[i]));
+    }
+
+    /* Count vriables in support. */
+    count = 0;
+    for (i = 0; i < size; i++) {
+        if (support[i] == 1) count++;
+    }
+
+    ABC_FREE(support);
+    return(count);
+
+} /* end of Cudd_VectorSupportSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Classifies the variables in the support of two DDs.]
+
+  Description [Classifies the variables in the support of two DDs
+  <code>f</code> and <code>g</code>, depending on whther they appear
+  in both DDs, only in <code>f</code>, or only in <code>g</code>.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [The cubes of the three classes of variables are
+  returned as side effects.]
+
+  SeeAlso     [Cudd_Support Cudd_VectorSupport]
+
+******************************************************************************/
+int
+Cudd_ClassifySupport(
+  DdManager * dd /* manager */,
+  DdNode * f /* first DD */,
+  DdNode * g /* second DD */,
+  DdNode ** common /* cube of shared variables */,
+  DdNode ** onlyF /* cube of variables only in f */,
+  DdNode ** onlyG /* cube of variables only in g */)
+{
+    int *supportF, *supportG;
+    DdNode *tmp, *var;
+    int i,j;
+    int size;
+
+    /* Allocate and initialize support arrays for ddSupportStep. */
+    size = ddMax(dd->size, dd->sizeZ);
+    supportF = ABC_ALLOC(int,size);
+    if (supportF == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    supportG = ABC_ALLOC(int,size);
+    if (supportG == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        ABC_FREE(supportF);
+        return(0);
+    }
+    for (i = 0; i < size; i++) {
+        supportF[i] = 0;
+        supportG[i] = 0;
+    }
+
+    /* Compute supports and clean up markers. */
+    ddSupportStep(Cudd_Regular(f),supportF);
+    ddClearFlag(Cudd_Regular(f));
+    ddSupportStep(Cudd_Regular(g),supportG);
+    ddClearFlag(Cudd_Regular(g));
+
+    /* Classify variables and create cubes. */
+    *common = *onlyF = *onlyG = DD_ONE(dd);
+    cuddRef(*common); cuddRef(*onlyF); cuddRef(*onlyG);
+    for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */
+        i = (j >= dd->size) ? j : dd->invperm[j];
+        if (supportF[i] == 0 && supportG[i] == 0) continue;
+        var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
+        cuddRef(var);
+        if (supportG[i] == 0) {
+            tmp = Cudd_bddAnd(dd,*onlyF,var);
+            if (tmp == NULL) {
+                Cudd_RecursiveDeref(dd,*common);
+                Cudd_RecursiveDeref(dd,*onlyF);
+                Cudd_RecursiveDeref(dd,*onlyG);
+                Cudd_RecursiveDeref(dd,var);
+                ABC_FREE(supportF); ABC_FREE(supportG);
+                return(0);
+            }
+            cuddRef(tmp);
+            Cudd_RecursiveDeref(dd,*onlyF);
+            *onlyF = tmp;
+        } else if (supportF[i] == 0) {
+            tmp = Cudd_bddAnd(dd,*onlyG,var);
+            if (tmp == NULL) {
+                Cudd_RecursiveDeref(dd,*common);
+                Cudd_RecursiveDeref(dd,*onlyF);
+                Cudd_RecursiveDeref(dd,*onlyG);
+                Cudd_RecursiveDeref(dd,var);
+                ABC_FREE(supportF); ABC_FREE(supportG);
+                return(0);
+            }
+            cuddRef(tmp);
+            Cudd_RecursiveDeref(dd,*onlyG);
+            *onlyG = tmp;
+        } else {
+            tmp = Cudd_bddAnd(dd,*common,var);
+            if (tmp == NULL) {
+                Cudd_RecursiveDeref(dd,*common);
+                Cudd_RecursiveDeref(dd,*onlyF);
+                Cudd_RecursiveDeref(dd,*onlyG);
+                Cudd_RecursiveDeref(dd,var);
+                ABC_FREE(supportF); ABC_FREE(supportG);
+                return(0);
+            }
+            cuddRef(tmp);
+            Cudd_RecursiveDeref(dd,*common);
+            *common = tmp;
+        }
+        Cudd_RecursiveDeref(dd,var);
+    }
+
+    ABC_FREE(supportF); ABC_FREE(supportG);
+    cuddDeref(*common); cuddDeref(*onlyF); cuddDeref(*onlyG);
+    return(1);
+
+} /* end of Cudd_ClassifySupport */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of leaves in a DD.]
+
+  Description [Counts the number of leaves in a DD. Returns the number
+  of leaves in the DD rooted at node if successful; CUDD_OUT_OF_MEM
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrintDebug]
+
+******************************************************************************/
+int
+Cudd_CountLeaves(
+  DdNode * node)
+{
+    int i;
+
+    i = ddLeavesInt(Cudd_Regular(node));
+    ddClearFlag(Cudd_Regular(node));
+    return(i);
+
+} /* end of Cudd_CountLeaves */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Picks one on-set cube randomly from the given DD.]
+
+  Description [Picks one on-set cube randomly from the given DD. The
+  cube is written into an array of characters.  The array must have at
+  least as many entries as there are variables. Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPickOneMinterm]
+
+******************************************************************************/
+int
+Cudd_bddPickOneCube(
+  DdManager * ddm,
+  DdNode * node,
+  char * string)
+{
+    DdNode *N, *T, *E;
+    DdNode *one, *bzero;
+    char   dir;
+    int    i;
+
+    if (string == NULL || node == NULL) return(0);
+
+    /* The constant 0 function has no on-set cubes. */
+    one = DD_ONE(ddm);
+    bzero = Cudd_Not(one);
+    if (node == bzero) return(0);
+
+    for (i = 0; i < ddm->size; i++) string[i] = 2;
+
+    for (;;) {
+
+        if (node == one) break;
+
+        N = Cudd_Regular(node);
+
+        T = cuddT(N); E = cuddE(N);
+        if (Cudd_IsComplement(node)) {
+            T = Cudd_Not(T); E = Cudd_Not(E);
+        }
+        if (T == bzero) {
+            string[N->index] = 0;
+            node = E;
+        } else if (E == bzero) {
+            string[N->index] = 1;
+            node = T;
+        } else {
+            dir = (char) ((Cudd_Random() & 0x2000) >> 13);
+            string[N->index] = dir;
+            node = dir ? T : E;
+        }
+    }
+    return(1);
+
+} /* end of Cudd_bddPickOneCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Picks one on-set minterm randomly from the given DD.]
+
+  Description [Picks one on-set minterm randomly from the given
+  DD. The minterm is in terms of <code>vars</code>. The array
+  <code>vars</code> should contain at least all variables in the
+  support of <code>f</code>; if this condition is not met the minterm
+  built by this procedure may not be contained in
+  <code>f</code>. Builds a BDD for the minterm and returns a pointer
+  to it if successful; NULL otherwise. There are three reasons why the
+  procedure may fail:
+  <ul>
+  <li> It may run out of memory;
+  <li> the function <code>f</code> may be the constant 0;
+  <li> the minterm may not be contained in <code>f</code>.
+  </ul>]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPickOneCube]
+
+******************************************************************************/
+DdNode *
+Cudd_bddPickOneMinterm(
+  DdManager * dd /* manager */,
+  DdNode * f /* function from which to pick one minterm */,
+  DdNode ** vars /* array of variables */,
+  int  n /* size of <code>vars</code> */)
+{
+    char *string;
+    int i, size;
+    int *indices;
+    int result;
+    DdNode *old, *neW;
+
+    size = dd->size;
+    string = ABC_ALLOC(char, size);
+    if (string == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    indices = ABC_ALLOC(int,n);
+    if (indices == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        ABC_FREE(string);
+        return(NULL);
+    }
+
+    for (i = 0; i < n; i++) {
+        indices[i] = vars[i]->index;
+    }
+
+    result = Cudd_bddPickOneCube(dd,f,string);
+    if (result == 0) {
+        ABC_FREE(string);
+        ABC_FREE(indices);
+        return(NULL);
+    }
+
+    /* Randomize choice for don't cares. */
+    for (i = 0; i < n; i++) {
+        if (string[indices[i]] == 2)
+            string[indices[i]] = (char) ((Cudd_Random() & 0x20) >> 5);
+    }
+
+    /* Build result BDD. */
+    old = Cudd_ReadOne(dd);
+    cuddRef(old);
+
+    for (i = n-1; i >= 0; i--) {
+        neW = Cudd_bddAnd(dd,old,Cudd_NotCond(vars[i],string[indices[i]]==0));
+        if (neW == NULL) {
+            ABC_FREE(string);
+            ABC_FREE(indices);
+            Cudd_RecursiveDeref(dd,old);
+            return(NULL);
+        }
+        cuddRef(neW);
+        Cudd_RecursiveDeref(dd,old);
+        old = neW;
+    }
+
+#ifdef DD_DEBUG
+    /* Test. */
+    if (Cudd_bddLeq(dd,old,f)) {
+        cuddDeref(old);
+    } else {
+        Cudd_RecursiveDeref(dd,old);
+        old = NULL;
+    }
+#else
+    cuddDeref(old);
+#endif
+
+    ABC_FREE(string);
+    ABC_FREE(indices);
+    return(old);
+
+}  /* end of Cudd_bddPickOneMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Picks k on-set minterms evenly distributed from given DD.]
+
+  Description [Picks k on-set minterms evenly distributed from given DD.
+  The minterms are in terms of <code>vars</code>. The array
+  <code>vars</code> should contain at least all variables in the
+  support of <code>f</code>; if this condition is not met the minterms
+  built by this procedure may not be contained in
+  <code>f</code>. Builds an array of BDDs for the minterms and returns a
+  pointer to it if successful; NULL otherwise. There are three reasons
+  why the procedure may fail:
+  <ul>
+  <li> It may run out of memory;
+  <li> the function <code>f</code> may be the constant 0;
+  <li> the minterms may not be contained in <code>f</code>.
+  </ul>]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPickOneMinterm Cudd_bddPickOneCube]
+
+******************************************************************************/
+DdNode **
+Cudd_bddPickArbitraryMinterms(
+  DdManager * dd /* manager */,
+  DdNode * f /* function from which to pick k minterms */,
+  DdNode ** vars /* array of variables */,
+  int  n /* size of <code>vars</code> */,
+  int  k /* number of minterms to find */)
+{
+    char **string;
+    int i, j, l, size;
+    int *indices;
+    int result;
+    DdNode **old, *neW;
+    double minterms;
+    char *saveString;
+    int saveFlag, savePoint = -1, isSame;
+
+    minterms = Cudd_CountMinterm(dd,f,n);
+    if ((double)k > minterms) {
+        return(NULL);
+    }
+
+    size = dd->size;
+    string = ABC_ALLOC(char *, k);
+    if (string == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    for (i = 0; i < k; i++) {
+        string[i] = ABC_ALLOC(char, size + 1);
+        if (string[i] == NULL) {
+            for (j = 0; j < i; j++)
+                ABC_FREE(string[i]);
+            ABC_FREE(string);
+            dd->errorCode = CUDD_MEMORY_OUT;
+            return(NULL);
+        }
+        for (j = 0; j < size; j++) string[i][j] = '2';
+        string[i][size] = '\0';
+    }
+    indices = ABC_ALLOC(int,n);
+    if (indices == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        for (i = 0; i < k; i++)
+            ABC_FREE(string[i]);
+        ABC_FREE(string);
+        return(NULL);
+    }
+
+    for (i = 0; i < n; i++) {
+        indices[i] = vars[i]->index;
+    }
+
+    result = ddPickArbitraryMinterms(dd,f,n,k,string);
+    if (result == 0) {
+        for (i = 0; i < k; i++)
+            ABC_FREE(string[i]);
+        ABC_FREE(string);
+        ABC_FREE(indices);
+        return(NULL);
+    }
+
+    old = ABC_ALLOC(DdNode *, k);
+    if (old == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        for (i = 0; i < k; i++)
+            ABC_FREE(string[i]);
+        ABC_FREE(string);
+        ABC_FREE(indices);
+        return(NULL);
+    }
+    saveString = ABC_ALLOC(char, size + 1);
+    if (saveString == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        for (i = 0; i < k; i++)
+            ABC_FREE(string[i]);
+        ABC_FREE(string);
+        ABC_FREE(indices);
+        ABC_FREE(old);
+        return(NULL);
+    }
+    saveFlag = 0;
+
+    /* Build result BDD array. */
+    for (i = 0; i < k; i++) {
+        isSame = 0;
+        if (!saveFlag) {
+            for (j = i + 1; j < k; j++) {
+                if (strcmp(string[i], string[j]) == 0) {
+                    savePoint = i;
+                    strcpy(saveString, string[i]);
+                    saveFlag = 1;
+                    break;
+                }
+            }
+        } else {
+            if (strcmp(string[i], saveString) == 0) {
+                isSame = 1;
+            } else {
+                saveFlag = 0;
+                for (j = i + 1; j < k; j++) {
+                    if (strcmp(string[i], string[j]) == 0) {
+                        savePoint = i;
+                        strcpy(saveString, string[i]);
+                        saveFlag = 1;
+                        break;
+                    }
+                }
+            }
+        }
+        /* Randomize choice for don't cares. */
+        for (j = 0; j < n; j++) {
+            if (string[i][indices[j]] == '2')
+                string[i][indices[j]] =
+                  (char) ((Cudd_Random() & 0x20) ? '1' : '0');
+        }
+
+        while (isSame) {
+            isSame = 0;
+            for (j = savePoint; j < i; j++) {
+                if (strcmp(string[i], string[j]) == 0) {
+                    isSame = 1;
+                    break;
+                }
+            }
+            if (isSame) {
+                strcpy(string[i], saveString);
+                /* Randomize choice for don't cares. */
+                for (j = 0; j < n; j++) {
+                    if (string[i][indices[j]] == '2')
+                        string[i][indices[j]] =
+                          (char) ((Cudd_Random() & 0x20) ? '1' : '0');
+                }
+            }
+        }
+
+        old[i] = Cudd_ReadOne(dd);
+        cuddRef(old[i]);
+
+        for (j = 0; j < n; j++) {
+            if (string[i][indices[j]] == '0') {
+                neW = Cudd_bddAnd(dd,old[i],Cudd_Not(vars[j]));
+            } else {
+                neW = Cudd_bddAnd(dd,old[i],vars[j]);
+            }
+            if (neW == NULL) {
+                ABC_FREE(saveString);
+                for (l = 0; l < k; l++)
+                    ABC_FREE(string[l]);
+                ABC_FREE(string);
+                ABC_FREE(indices);
+                for (l = 0; l <= i; l++)
+                    Cudd_RecursiveDeref(dd,old[l]);
+                ABC_FREE(old);
+                return(NULL);
+            }
+            cuddRef(neW);
+            Cudd_RecursiveDeref(dd,old[i]);
+            old[i] = neW;
+        }
+
+        /* Test. */
+        if (!Cudd_bddLeq(dd,old[i],f)) {
+            ABC_FREE(saveString);
+            for (l = 0; l < k; l++)
+                ABC_FREE(string[l]);
+            ABC_FREE(string);
+            ABC_FREE(indices);
+            for (l = 0; l <= i; l++)
+                Cudd_RecursiveDeref(dd,old[l]);
+            ABC_FREE(old);
+            return(NULL);
+        }
+    }
+
+    ABC_FREE(saveString);
+    for (i = 0; i < k; i++) {
+        cuddDeref(old[i]);
+        ABC_FREE(string[i]);
+    }
+    ABC_FREE(string);
+    ABC_FREE(indices);
+    return(old);
+
+}  /* end of Cudd_bddPickArbitraryMinterms */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts a subset from a BDD.]
+
+  Description [Extracts a subset from a BDD in the following procedure.
+  1. Compute the weight for each mask variable by counting the number of
+     minterms for both positive and negative cofactors of the BDD with
+     respect to each mask variable. (weight = #positive - #negative)
+  2. Find a representative cube of the BDD by using the weight. From the
+     top variable of the BDD, for each variable, if the weight is greater
+     than 0.0, choose THEN branch, othereise ELSE branch, until meeting
+     the constant 1.
+  3. Quantify out the variables not in maskVars from the representative
+     cube and if a variable in maskVars is don't care, replace the
+     variable with a constant(1 or 0) depending on the weight.
+  4. Make a subset of the BDD by multiplying with the modified cube.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_SubsetWithMaskVars(
+  DdManager * dd /* manager */,
+  DdNode * f /* function from which to pick a cube */,
+  DdNode ** vars /* array of variables */,
+  int  nvars /* size of <code>vars</code> */,
+  DdNode ** maskVars /* array of variables */,
+  int  mvars /* size of <code>maskVars</code> */)
+{
+    double      *weight;
+    char        *string;
+    int         i, size;
+    int         *indices, *mask;
+    int         result;
+    DdNode      *zero, *cube, *newCube, *subset;
+    DdNode      *cof;
+
+    DdNode      *support;
+    support = Cudd_Support(dd,f);
+    cuddRef(support);
+    Cudd_RecursiveDeref(dd,support);
+
+    zero = Cudd_Not(dd->one);
+    size = dd->size;
+
+    weight = ABC_ALLOC(double,size);
+    if (weight == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    for (i = 0; i < size; i++) {
+        weight[i] = 0.0;
+    }
+    for (i = 0; i < mvars; i++) {
+        cof = Cudd_Cofactor(dd, f, maskVars[i]);
+        cuddRef(cof);
+        weight[i] = Cudd_CountMinterm(dd, cof, nvars);
+        Cudd_RecursiveDeref(dd,cof);
+
+        cof = Cudd_Cofactor(dd, f, Cudd_Not(maskVars[i]));
+        cuddRef(cof);
+        weight[i] -= Cudd_CountMinterm(dd, cof, nvars);
+        Cudd_RecursiveDeref(dd,cof);
+    }
+
+    string = ABC_ALLOC(char, size + 1);
+    if (string == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        ABC_FREE(weight);
+        return(NULL);
+    }
+    mask = ABC_ALLOC(int, size);
+    if (mask == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        ABC_FREE(weight);
+        ABC_FREE(string);
+        return(NULL);
+    }
+    for (i = 0; i < size; i++) {
+        string[i] = '2';
+        mask[i] = 0;
+    }
+    string[size] = '\0';
+    indices = ABC_ALLOC(int,nvars);
+    if (indices == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        ABC_FREE(weight);
+        ABC_FREE(string);
+        ABC_FREE(mask);
+        return(NULL);
+    }
+    for (i = 0; i < nvars; i++) {
+        indices[i] = vars[i]->index;
+    }
+
+    result = ddPickRepresentativeCube(dd,f,weight,string);
+    if (result == 0) {
+        ABC_FREE(weight);
+        ABC_FREE(string);
+        ABC_FREE(mask);
+        ABC_FREE(indices);
+        return(NULL);
+    }
+
+    cube = Cudd_ReadOne(dd);
+    cuddRef(cube);
+    zero = Cudd_Not(Cudd_ReadOne(dd));
+    for (i = 0; i < nvars; i++) {
+        if (string[indices[i]] == '0') {
+            newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero);
+        } else if (string[indices[i]] == '1') {
+            newCube = Cudd_bddIte(dd,cube,vars[i],zero);
+        } else
+            continue;
+        if (newCube == NULL) {
+            ABC_FREE(weight);
+            ABC_FREE(string);
+            ABC_FREE(mask);
+            ABC_FREE(indices);
+            Cudd_RecursiveDeref(dd,cube);
+            return(NULL);
+        }
+        cuddRef(newCube);
+        Cudd_RecursiveDeref(dd,cube);
+        cube = newCube;
+    }
+    Cudd_RecursiveDeref(dd,cube);
+
+    for (i = 0; i < mvars; i++) {
+        mask[maskVars[i]->index] = 1;
+    }
+    for (i = 0; i < nvars; i++) {
+        if (mask[indices[i]]) {
+            if (string[indices[i]] == '2') {
+                if (weight[indices[i]] >= 0.0)
+                    string[indices[i]] = '1';
+                else
+                    string[indices[i]] = '0';
+            }
+        } else {
+            string[indices[i]] = '2';
+        }
+    }
+
+    cube = Cudd_ReadOne(dd);
+    cuddRef(cube);
+    zero = Cudd_Not(Cudd_ReadOne(dd));
+
+    /* Build result BDD. */
+    for (i = 0; i < nvars; i++) {
+        if (string[indices[i]] == '0') {
+            newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero);
+        } else if (string[indices[i]] == '1') {
+            newCube = Cudd_bddIte(dd,cube,vars[i],zero);
+        } else
+            continue;
+        if (newCube == NULL) {
+            ABC_FREE(weight);
+            ABC_FREE(string);
+            ABC_FREE(mask);
+            ABC_FREE(indices);
+            Cudd_RecursiveDeref(dd,cube);
+            return(NULL);
+        }
+        cuddRef(newCube);
+        Cudd_RecursiveDeref(dd,cube);
+        cube = newCube;
+    }
+
+    subset = Cudd_bddAnd(dd,f,cube);
+    cuddRef(subset);
+    Cudd_RecursiveDeref(dd,cube);
+
+    /* Test. */
+    if (Cudd_bddLeq(dd,subset,f)) {
+        cuddDeref(subset);
+    } else {
+        Cudd_RecursiveDeref(dd,subset);
+        subset = NULL;
+    }
+
+    ABC_FREE(weight);
+    ABC_FREE(string);
+    ABC_FREE(mask);
+    ABC_FREE(indices);
+    return(subset);
+
+} /* end of Cudd_SubsetWithMaskVars */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the first cube of a decision diagram.]
+
+  Description [Defines an iterator on the onset of a decision diagram
+  and finds its first cube. Returns a generator that contains the
+  information necessary to continue the enumeration if successful; NULL
+  otherwise.<p>
+  A cube is represented as an array of literals, which are integers in
+  {0, 1, 2}; 0 represents a complemented literal, 1 represents an
+  uncomplemented literal, and 2 stands for don't care. The enumeration
+  produces a disjoint cover of the function associated with the diagram.
+  The size of the array equals the number of variables in the manager at
+  the time Cudd_FirstCube is called.<p>
+  For each cube, a value is also returned. This value is always 1 for a
+  BDD, while it may be different from 1 for an ADD.
+  For BDDs, the offset is the set of cubes whose value is the logical zero.
+  For ADDs, the offset is the set of cubes whose value is the
+  background value. The cubes of the offset are not enumerated.]
+
+  SideEffects [The first cube and its value are returned as side effects.]
+
+  SeeAlso     [Cudd_ForeachCube Cudd_NextCube Cudd_GenFree Cudd_IsGenEmpty
+  Cudd_FirstNode]
+
+******************************************************************************/
+DdGen *
+Cudd_FirstCube(
+  DdManager * dd,
+  DdNode * f,
+  int ** cube,
+  CUDD_VALUE_TYPE * value)
+{
+    DdGen *gen;
+    DdNode *top, *treg, *next, *nreg, *prev, *preg;
+    int i;
+    int nvars;
+
+    /* Sanity Check. */
+    if (dd == NULL || f == NULL) return(NULL);
+
+    /* Allocate generator an initialize it. */
+    gen = ABC_ALLOC(DdGen,1);
+    if (gen == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+
+    gen->manager = dd;
+    gen->type = CUDD_GEN_CUBES;
+    gen->status = CUDD_GEN_EMPTY;
+    gen->gen.cubes.cube = NULL;
+    gen->gen.cubes.value = DD_ZERO_VAL;
+    gen->stack.sp = 0;
+    gen->stack.stack = NULL;
+    gen->node = NULL;
+
+    nvars = dd->size;
+    gen->gen.cubes.cube = ABC_ALLOC(int,nvars);
+    if (gen->gen.cubes.cube == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        ABC_FREE(gen);
+        return(NULL);
+    }
+    for (i = 0; i < nvars; i++) gen->gen.cubes.cube[i] = 2;
+
+    /* The maximum stack depth is one plus the number of variables.
+    ** because a path may have nodes at all levels, including the
+    ** constant level.
+    */
+    gen->stack.stack = ABC_ALLOC(DdNodePtr, nvars+1);
+    if (gen->stack.stack == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        ABC_FREE(gen->gen.cubes.cube);
+        ABC_FREE(gen);
+        return(NULL);
+    }
+    for (i = 0; i <= nvars; i++) gen->stack.stack[i] = NULL;
+
+    /* Find the first cube of the onset. */
+    gen->stack.stack[gen->stack.sp] = f; gen->stack.sp++;
+
+    while (1) {
+        top = gen->stack.stack[gen->stack.sp-1];
+        treg = Cudd_Regular(top);
+        if (!cuddIsConstant(treg)) {
+            /* Take the else branch first. */
+            gen->gen.cubes.cube[treg->index] = 0;
+            next = cuddE(treg);
+            if (top != treg) next = Cudd_Not(next);
+            gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++;
+        } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) {
+            /* Backtrack */
+            while (1) {
+                if (gen->stack.sp == 1) {
+                    /* The current node has no predecessor. */
+                    gen->status = CUDD_GEN_EMPTY;
+                    gen->stack.sp--;
+                    goto done;
+                }
+                prev = gen->stack.stack[gen->stack.sp-2];
+                preg = Cudd_Regular(prev);
+                nreg = cuddT(preg);
+                if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
+                if (next != top) { /* follow the then branch next */
+                    gen->gen.cubes.cube[preg->index] = 1;
+                    gen->stack.stack[gen->stack.sp-1] = next;
+                    break;
+                }
+                /* Pop the stack and try again. */
+                gen->gen.cubes.cube[preg->index] = 2;
+                gen->stack.sp--;
+                top = gen->stack.stack[gen->stack.sp-1];
+                treg = Cudd_Regular(top);
+            }
+        } else {
+            gen->status = CUDD_GEN_NONEMPTY;
+            gen->gen.cubes.value = cuddV(top);
+            goto done;
+        }
+    }
+
+done:
+    *cube = gen->gen.cubes.cube;
+    *value = gen->gen.cubes.value;
+    return(gen);
+
+} /* end of Cudd_FirstCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates the next cube of a decision diagram onset.]
+
+  Description [Generates the next cube of a decision diagram onset,
+  using generator gen. Returns 0 if the enumeration is completed; 1
+  otherwise.]
+
+  SideEffects [The cube and its value are returned as side effects. The
+  generator is modified.]
+
+  SeeAlso     [Cudd_ForeachCube Cudd_FirstCube Cudd_GenFree Cudd_IsGenEmpty
+  Cudd_NextNode]
+
+******************************************************************************/
+int
+Cudd_NextCube(
+  DdGen * gen,
+  int ** cube,
+  CUDD_VALUE_TYPE * value)
+{
+    DdNode *top, *treg, *next, *nreg, *prev, *preg;
+    DdManager *dd = gen->manager;
+
+    /* Backtrack from previously reached terminal node. */
+    while (1) {
+        if (gen->stack.sp == 1) {
+            /* The current node has no predecessor. */
+            gen->status = CUDD_GEN_EMPTY;
+            gen->stack.sp--;
+            goto done;
+        }
+        top = gen->stack.stack[gen->stack.sp-1];
+        treg = Cudd_Regular(top);
+        prev = gen->stack.stack[gen->stack.sp-2];
+        preg = Cudd_Regular(prev);
+        nreg = cuddT(preg);
+        if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
+        if (next != top) { /* follow the then branch next */
+            gen->gen.cubes.cube[preg->index] = 1;
+            gen->stack.stack[gen->stack.sp-1] = next;
+            break;
+        }
+        /* Pop the stack and try again. */
+        gen->gen.cubes.cube[preg->index] = 2;
+        gen->stack.sp--;
+    }
+
+    while (1) {
+        top = gen->stack.stack[gen->stack.sp-1];
+        treg = Cudd_Regular(top);
+        if (!cuddIsConstant(treg)) {
+            /* Take the else branch first. */
+            gen->gen.cubes.cube[treg->index] = 0;
+            next = cuddE(treg);
+            if (top != treg) next = Cudd_Not(next);
+            gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++;
+        } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) {
+            /* Backtrack */
+            while (1) {
+                if (gen->stack.sp == 1) {
+                    /* The current node has no predecessor. */
+                    gen->status = CUDD_GEN_EMPTY;
+                    gen->stack.sp--;
+                    goto done;
+                }
+                prev = gen->stack.stack[gen->stack.sp-2];
+                preg = Cudd_Regular(prev);
+                nreg = cuddT(preg);
+                if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
+                if (next != top) { /* follow the then branch next */
+                    gen->gen.cubes.cube[preg->index] = 1;
+                    gen->stack.stack[gen->stack.sp-1] = next;
+                    break;
+                }
+                /* Pop the stack and try again. */
+                gen->gen.cubes.cube[preg->index] = 2;
+                gen->stack.sp--;
+                top = gen->stack.stack[gen->stack.sp-1];
+                treg = Cudd_Regular(top);
+            }
+        } else {
+            gen->status = CUDD_GEN_NONEMPTY;
+            gen->gen.cubes.value = cuddV(top);
+            goto done;
+        }
+    }
+
+done:
+    if (gen->status == CUDD_GEN_EMPTY) return(0);
+    *cube = gen->gen.cubes.cube;
+    *value = gen->gen.cubes.value;
+    return(1);
+
+} /* end of Cudd_NextCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the first prime of a Boolean function.]
+
+  Description [Defines an iterator on a pair of BDDs describing a
+  (possibly incompletely specified) Boolean functions and finds the
+  first cube of a cover of the function.  Returns a generator
+  that contains the information necessary to continue the enumeration
+  if successful; NULL otherwise.<p>
+
+  The two argument BDDs are the lower and upper bounds of an interval.
+  It is a mistake to call this function with a lower bound that is not
+  less than or equal to the upper bound.<p>
+
+  A cube is represented as an array of literals, which are integers in
+  {0, 1, 2}; 0 represents a complemented literal, 1 represents an
+  uncomplemented literal, and 2 stands for don't care. The enumeration
+  produces a prime and irredundant cover of the function associated
+  with the two BDDs.  The size of the array equals the number of
+  variables in the manager at the time Cudd_FirstCube is called.<p>
+
+  This iterator can only be used on BDDs.]
+
+  SideEffects [The first cube is returned as side effect.]
+
+  SeeAlso     [Cudd_ForeachPrime Cudd_NextPrime Cudd_GenFree Cudd_IsGenEmpty
+  Cudd_FirstCube Cudd_FirstNode]
+
+******************************************************************************/
+DdGen *
+Cudd_FirstPrime(
+  DdManager *dd,
+  DdNode *l,
+  DdNode *u,
+  int **cube)
+{
+    DdGen *gen;
+    DdNode *implicant, *prime, *tmp;
+    int length, result;
+
+    /* Sanity Check. */
+    if (dd == NULL || l == NULL || u == NULL) return(NULL);
+
+    /* Allocate generator an initialize it. */
+    gen = ABC_ALLOC(DdGen,1);
+    if (gen == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+
+    gen->manager = dd;
+    gen->type = CUDD_GEN_PRIMES;
+    gen->status = CUDD_GEN_EMPTY;
+    gen->gen.primes.cube = NULL;
+    gen->gen.primes.ub = u;
+    gen->stack.sp = 0;
+    gen->stack.stack = NULL;
+    gen->node = l;
+    cuddRef(l);
+
+    gen->gen.primes.cube = ABC_ALLOC(int,dd->size);
+    if (gen->gen.primes.cube == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        ABC_FREE(gen);
+        return(NULL);
+    }
+
+    if (gen->node == Cudd_ReadLogicZero(dd)) {
+        gen->status = CUDD_GEN_EMPTY;
+    } else {
+        implicant = Cudd_LargestCube(dd,gen->node,&length);
+        if (implicant == NULL) {
+            Cudd_RecursiveDeref(dd,gen->node);
+            ABC_FREE(gen->gen.primes.cube);
+            ABC_FREE(gen);
+            return(NULL);
+        }
+        cuddRef(implicant);
+        prime = Cudd_bddMakePrime(dd,implicant,gen->gen.primes.ub);
+        if (prime == NULL) {
+            Cudd_RecursiveDeref(dd,gen->node);
+            Cudd_RecursiveDeref(dd,implicant);
+            ABC_FREE(gen->gen.primes.cube);
+            ABC_FREE(gen);
+            return(NULL);
+        }
+        cuddRef(prime);
+        Cudd_RecursiveDeref(dd,implicant);
+        tmp = Cudd_bddAnd(dd,gen->node,Cudd_Not(prime));
+        if (tmp == NULL) {
+            Cudd_RecursiveDeref(dd,gen->node);
+            Cudd_RecursiveDeref(dd,prime);
+            ABC_FREE(gen->gen.primes.cube);
+            ABC_FREE(gen);
+            return(NULL);
+        }
+        cuddRef(tmp);
+        Cudd_RecursiveDeref(dd,gen->node);
+        gen->node = tmp;
+        result = Cudd_BddToCubeArray(dd,prime,gen->gen.primes.cube);
+        if (result == 0) {
+            Cudd_RecursiveDeref(dd,gen->node);
+            Cudd_RecursiveDeref(dd,prime);
+            ABC_FREE(gen->gen.primes.cube);
+            ABC_FREE(gen);
+            return(NULL);
+        }
+        Cudd_RecursiveDeref(dd,prime);
+        gen->status = CUDD_GEN_NONEMPTY;
+    }
+    *cube = gen->gen.primes.cube;
+    return(gen);
+
+} /* end of Cudd_FirstPrime */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates the next prime of a Boolean function.]
+
+  Description [Generates the next cube of a Boolean function,
+  using generator gen. Returns 0 if the enumeration is completed; 1
+  otherwise.]
+
+  SideEffects [The cube and is returned as side effects. The
+  generator is modified.]
+
+  SeeAlso     [Cudd_ForeachPrime Cudd_FirstPrime Cudd_GenFree Cudd_IsGenEmpty
+  Cudd_NextCube Cudd_NextNode]
+
+******************************************************************************/
+int
+Cudd_NextPrime(
+  DdGen *gen,
+  int **cube)
+{
+    DdNode *implicant, *prime, *tmp;
+    DdManager *dd = gen->manager;
+    int length, result;
+
+    if (gen->node == Cudd_ReadLogicZero(dd)) {
+        gen->status = CUDD_GEN_EMPTY;
+    } else {
+        implicant = Cudd_LargestCube(dd,gen->node,&length);
+        if (implicant == NULL) {
+            gen->status = CUDD_GEN_EMPTY;
+            return(0);
+        }
+        cuddRef(implicant);
+        prime = Cudd_bddMakePrime(dd,implicant,gen->gen.primes.ub);
+        if (prime == NULL) {
+            Cudd_RecursiveDeref(dd,implicant);
+            gen->status = CUDD_GEN_EMPTY;
+            return(0);
+        }
+        cuddRef(prime);
+        Cudd_RecursiveDeref(dd,implicant);
+        tmp = Cudd_bddAnd(dd,gen->node,Cudd_Not(prime));
+        if (tmp == NULL) {
+            Cudd_RecursiveDeref(dd,prime);
+            gen->status = CUDD_GEN_EMPTY;
+            return(0);
+        }
+        cuddRef(tmp);
+        Cudd_RecursiveDeref(dd,gen->node);
+        gen->node = tmp;
+        result = Cudd_BddToCubeArray(dd,prime,gen->gen.primes.cube);
+        if (result == 0) {
+            Cudd_RecursiveDeref(dd,prime);
+            gen->status = CUDD_GEN_EMPTY;
+            return(0);
+        }
+        Cudd_RecursiveDeref(dd,prime);
+        gen->status = CUDD_GEN_NONEMPTY;
+    }
+    if (gen->status == CUDD_GEN_EMPTY) return(0);
+    *cube = gen->gen.primes.cube;
+    return(1);
+
+} /* end of Cudd_NextPrime */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the cube of an array of BDD variables.]
+
+  Description [Computes the cube of an array of BDD variables. If
+  non-null, the phase argument indicates which literal of each
+  variable should appear in the cube. If phase\[i\] is nonzero, then the
+  positive literal is used. If phase is NULL, the cube is positive unate.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addComputeCube Cudd_IndicesToCube Cudd_CubeArrayToBdd]
+
+******************************************************************************/
+DdNode *
+Cudd_bddComputeCube(
+  DdManager * dd,
+  DdNode ** vars,
+  int * phase,
+  int  n)
+{
+    DdNode      *cube;
+    DdNode      *fn;
+    int         i;
+
+    cube = DD_ONE(dd);
+    cuddRef(cube);
+
+    for (i = n - 1; i >= 0; i--) {
+        if (phase == NULL || phase[i] != 0) {
+            fn = Cudd_bddAnd(dd,vars[i],cube);
+        } else {
+            fn = Cudd_bddAnd(dd,Cudd_Not(vars[i]),cube);
+        }
+        if (fn == NULL) {
+            Cudd_RecursiveDeref(dd,cube);
+            return(NULL);
+        }
+        cuddRef(fn);
+        Cudd_RecursiveDeref(dd,cube);
+        cube = fn;
+    }
+    cuddDeref(cube);
+
+    return(cube);
+
+}  /* end of Cudd_bddComputeCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the cube of an array of ADD variables.]
+
+  Description [Computes the cube of an array of ADD variables.  If
+  non-null, the phase argument indicates which literal of each
+  variable should appear in the cube. If phase\[i\] is nonzero, then the
+  positive literal is used. If phase is NULL, the cube is positive unate.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_bddComputeCube]
+
+******************************************************************************/
+DdNode *
+Cudd_addComputeCube(
+  DdManager * dd,
+  DdNode ** vars,
+  int * phase,
+  int  n)
+{
+    DdNode      *cube, *zero;
+    DdNode      *fn;
+    int         i;
+
+    cube = DD_ONE(dd);
+    cuddRef(cube);
+    zero = DD_ZERO(dd);
+
+    for (i = n - 1; i >= 0; i--) {
+        if (phase == NULL || phase[i] != 0) {
+            fn = Cudd_addIte(dd,vars[i],cube,zero);
+        } else {
+            fn = Cudd_addIte(dd,vars[i],zero,cube);
+        }
+        if (fn == NULL) {
+            Cudd_RecursiveDeref(dd,cube);
+            return(NULL);
+        }
+        cuddRef(fn);
+        Cudd_RecursiveDeref(dd,cube);
+        cube = fn;
+    }
+    cuddDeref(cube);
+
+    return(cube);
+
+} /* end of Cudd_addComputeCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the BDD of a cube from a positional array.]
+
+  Description [Builds a cube from a positional array.  The array must
+  have one integer entry for each BDD variable.  If the i-th entry is
+  1, the variable of index i appears in true form in the cube; If the
+  i-th entry is 0, the variable of index i appears complemented in the
+  cube; otherwise the variable does not appear in the cube.  Returns a
+  pointer to the BDD for the cube if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddComputeCube Cudd_IndicesToCube Cudd_BddToCubeArray]
+
+******************************************************************************/
+DdNode *
+Cudd_CubeArrayToBdd(
+  DdManager *dd,
+  int *array)
+{
+    DdNode *cube, *var, *tmp;
+    int i;
+    int size = Cudd_ReadSize(dd);
+
+    cube = DD_ONE(dd);
+    cuddRef(cube);
+    for (i = size - 1; i >= 0; i--) {
+        if ((array[i] & ~1) == 0) {
+            var = Cudd_bddIthVar(dd,i);
+            tmp = Cudd_bddAnd(dd,cube,Cudd_NotCond(var,array[i]==0));
+            if (tmp == NULL) {
+                Cudd_RecursiveDeref(dd,cube);
+                return(NULL);
+            }
+            cuddRef(tmp);
+            Cudd_RecursiveDeref(dd,cube);
+            cube = tmp;
+        }
+    }
+    cuddDeref(cube);
+    return(cube);
+
+} /* end of Cudd_CubeArrayToBdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds a positional array from the BDD of a cube.]
+
+  Description [Builds a positional array from the BDD of a cube.
+  Array must have one entry for each BDD variable.  The positional
+  array has 1 in i-th position if the variable of index i appears in
+  true form in the cube; it has 0 in i-th position if the variable of
+  index i appears in complemented form in the cube; finally, it has 2
+  in i-th position if the variable of index i does not appear in the
+  cube.  Returns 1 if successful (the BDD is indeed a cube); 0
+  otherwise.]
+
+  SideEffects [The result is in the array passed by reference.]
+
+  SeeAlso     [Cudd_CubeArrayToBdd]
+
+******************************************************************************/
+int
+Cudd_BddToCubeArray(
+  DdManager *dd,
+  DdNode *cube,
+  int *array)
+{
+    DdNode *scan, *t, *e;
+    int i;
+    int size = Cudd_ReadSize(dd);
+    DdNode *zero = Cudd_Not(DD_ONE(dd));
+
+    for (i = size-1; i >= 0; i--) {
+        array[i] = 2;
+    }
+    scan = cube;
+    while (!Cudd_IsConstant(scan)) {
+        int index = Cudd_Regular(scan)->index;
+        cuddGetBranches(scan,&t,&e);
+        if (t == zero) {
+            array[index] = 0;
+            scan = e;
+        } else if (e == zero) {
+            array[index] = 1;
+            scan = t;
+        } else {
+            return(0);  /* cube is not a cube */
+        }
+    }
+    if (scan == zero) {
+        return(0);
+    } else {
+        return(1);
+    }
+
+} /* end of Cudd_BddToCubeArray */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the first node of a decision diagram.]
+
+  Description [Defines an iterator on the nodes of a decision diagram
+  and finds its first node. Returns a generator that contains the
+  information necessary to continue the enumeration if successful;
+  NULL otherwise.  The nodes are enumerated in a reverse topological
+  order, so that a node is always preceded in the enumeration by its
+  descendants.]
+
+  SideEffects [The first node is returned as a side effect.]
+
+  SeeAlso     [Cudd_ForeachNode Cudd_NextNode Cudd_GenFree Cudd_IsGenEmpty
+  Cudd_FirstCube]
+
+******************************************************************************/
+DdGen *
+Cudd_FirstNode(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** node)
+{
+    DdGen *gen;
+    int size;
+
+    /* Sanity Check. */
+    if (dd == NULL || f == NULL) return(NULL);
+
+    /* Allocate generator an initialize it. */
+    gen = ABC_ALLOC(DdGen,1);
+    if (gen == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+
+    gen->manager = dd;
+    gen->type = CUDD_GEN_NODES;
+    gen->status = CUDD_GEN_EMPTY;
+    gen->stack.sp = 0;
+    gen->node = NULL;
+
+    /* Collect all the nodes on the generator stack for later perusal. */
+    gen->stack.stack = cuddNodeArray(Cudd_Regular(f), &size);
+    if (gen->stack.stack == NULL) {
+        ABC_FREE(gen);
+        dd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+    gen->gen.nodes.size = size;
+
+    /* Find the first node. */
+    if (gen->stack.sp < gen->gen.nodes.size) {
+        gen->status = CUDD_GEN_NONEMPTY;
+        gen->node = gen->stack.stack[gen->stack.sp];
+        *node = gen->node;
+    }
+
+    return(gen);
+
+} /* end of Cudd_FirstNode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the next node of a decision diagram.]
+
+  Description [Finds the node of a decision diagram, using generator
+  gen. Returns 0 if the enumeration is completed; 1 otherwise.]
+
+  SideEffects [The next node is returned as a side effect.]
+
+  SeeAlso     [Cudd_ForeachNode Cudd_FirstNode Cudd_GenFree Cudd_IsGenEmpty
+  Cudd_NextCube]
+
+******************************************************************************/
+int
+Cudd_NextNode(
+  DdGen * gen,
+  DdNode ** node)
+{
+    /* Find the next node. */
+    gen->stack.sp++;
+    if (gen->stack.sp < gen->gen.nodes.size) {
+        gen->node = gen->stack.stack[gen->stack.sp];
+        *node = gen->node;
+        return(1);
+    } else {
+        gen->status = CUDD_GEN_EMPTY;
+        return(0);
+    }
+
+} /* end of Cudd_NextNode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a CUDD generator.]
+
+  Description [Frees a CUDD generator. Always returns 0, so that it can
+  be used in mis-like foreach constructs.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube
+  Cudd_FirstNode Cudd_NextNode Cudd_IsGenEmpty]
+
+******************************************************************************/
+int
+Cudd_GenFree(
+  DdGen * gen)
+{
+    if (gen == NULL) return(0);
+    switch (gen->type) {
+    case CUDD_GEN_CUBES:
+    case CUDD_GEN_ZDD_PATHS:
+        ABC_FREE(gen->gen.cubes.cube);
+        ABC_FREE(gen->stack.stack);
+        break;
+    case CUDD_GEN_PRIMES:
+        ABC_FREE(gen->gen.primes.cube);
+        Cudd_RecursiveDeref(gen->manager,gen->node);
+        break;
+    case CUDD_GEN_NODES:
+        ABC_FREE(gen->stack.stack);
+        break;
+    default:
+        return(0);
+    }
+    ABC_FREE(gen);
+    return(0);
+
+} /* end of Cudd_GenFree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Queries the status of a generator.]
+
+  Description [Queries the status of a generator. Returns 1 if the
+  generator is empty or NULL; 0 otherswise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube
+  Cudd_FirstNode Cudd_NextNode Cudd_GenFree]
+
+******************************************************************************/
+int
+Cudd_IsGenEmpty(
+  DdGen * gen)
+{
+    if (gen == NULL) return(1);
+    return(gen->status == CUDD_GEN_EMPTY);
+
+} /* end of Cudd_IsGenEmpty */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds a cube of BDD variables from an array of indices.]
+
+  Description [Builds a cube of BDD variables from an array of indices.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddComputeCube Cudd_CubeArrayToBdd]
+
+******************************************************************************/
+DdNode *
+Cudd_IndicesToCube(
+  DdManager * dd,
+  int * array,
+  int  n)
+{
+    DdNode *cube, *tmp;
+    int i;
+
+    cube = DD_ONE(dd);
+    cuddRef(cube);
+    for (i = n - 1; i >= 0; i--) {
+        tmp = Cudd_bddAnd(dd,Cudd_bddIthVar(dd,array[i]),cube);
+        if (tmp == NULL) {
+            Cudd_RecursiveDeref(dd,cube);
+            return(NULL);
+        }
+        cuddRef(tmp);
+        Cudd_RecursiveDeref(dd,cube);
+        cube = tmp;
+    }
+
+    cuddDeref(cube);
+    return(cube);
+
+} /* end of Cudd_IndicesToCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the package version number.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_PrintVersion(
+  FILE * fp)
+{
+    (void) fprintf(fp, "%s\n", CUDD_VERSION);
+
+} /* end of Cudd_PrintVersion */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the average distance between adjacent nodes.]
+
+  Description [Computes the average distance between adjacent nodes in
+  the manager. Adjacent nodes are node pairs such that the second node
+  is the then child, else child, or next node in the collision list.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+double
+Cudd_AverageDistance(
+  DdManager * dd)
+{
+    double tetotal, nexttotal;
+    double tesubtotal, nextsubtotal;
+    double temeasured, nextmeasured;
+    int i, j;
+    int slots, nvars;
+    long diff;
+    DdNode *scan;
+    DdNodePtr *nodelist;
+    DdNode *sentinel = &(dd->sentinel);
+
+    nvars = dd->size;
+    if (nvars == 0) return(0.0);
+
+    /* Initialize totals. */
+    tetotal = 0.0;
+    nexttotal = 0.0;
+    temeasured = 0.0;
+    nextmeasured = 0.0;
+
+    /* Scan the variable subtables. */
+    for (i = 0; i < nvars; i++) {
+        nodelist = dd->subtables[i].nodelist;
+        tesubtotal = 0.0;
+        nextsubtotal = 0.0;
+        slots = dd->subtables[i].slots;
+        for (j = 0; j < slots; j++) {
+            scan = nodelist[j];
+            while (scan != sentinel) {
+                diff = (long) scan - (long) cuddT(scan);
+                tesubtotal += (double) ddAbs(diff);
+                diff = (long) scan - (long) Cudd_Regular(cuddE(scan));
+                tesubtotal += (double) ddAbs(diff);
+                temeasured += 2.0;
+                if (scan->next != sentinel) {
+                    diff = (long) scan - (long) scan->next;
+                    nextsubtotal += (double) ddAbs(diff);
+                    nextmeasured += 1.0;
+                }
+                scan = scan->next;
+            }
+        }
+        tetotal += tesubtotal;
+        nexttotal += nextsubtotal;
+    }
+
+    /* Scan the constant table. */
+    nodelist = dd->constants.nodelist;
+    nextsubtotal = 0.0;
+    slots = dd->constants.slots;
+    for (j = 0; j < slots; j++) {
+        scan = nodelist[j];
+        while (scan != NULL) {
+            if (scan->next != NULL) {
+                diff = (long) scan - (long) scan->next;
+                nextsubtotal += (double) ddAbs(diff);
+                nextmeasured += 1.0;
+            }
+            scan = scan->next;
+        }
+    }
+    nexttotal += nextsubtotal;
+
+    return((tetotal + nexttotal) / (temeasured + nextmeasured));
+
+} /* end of Cudd_AverageDistance */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Portable random number generator.]
+
+  Description [Portable number generator based on ran2 from "Numerical
+  Recipes in C." It is a long period (> 2 * 10^18) random number generator
+  of L'Ecuyer with Bays-Durham shuffle. Returns a long integer uniformly
+  distributed between 0 and 2147483561 (inclusive of the endpoint values).
+  The random generator can be explicitly initialized by calling
+  Cudd_Srandom. If no explicit initialization is performed, then the
+  seed 1 is assumed.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Srandom]
+
+******************************************************************************/
+long
+Cudd_Random(void)
+{
+    int i;      /* index in the shuffle table */
+    long int w; /* work variable */
+
+    /* cuddRand == 0 if the geneartor has not been initialized yet. */
+    if (cuddRand == 0) Cudd_Srandom(1);
+
+    /* Compute cuddRand = (cuddRand * LEQA1) % MODULUS1 avoiding
+    ** overflows by Schrage's method.
+    */
+    w          = cuddRand / LEQQ1;
+    cuddRand   = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1;
+    cuddRand  += (cuddRand < 0) * MODULUS1;
+
+    /* Compute cuddRand2 = (cuddRand2 * LEQA2) % MODULUS2 avoiding
+    ** overflows by Schrage's method.
+    */
+    w          = cuddRand2 / LEQQ2;
+    cuddRand2  = LEQA2 * (cuddRand2 - w * LEQQ2) - w * LEQR2;
+    cuddRand2 += (cuddRand2 < 0) * MODULUS2;
+
+    /* cuddRand is shuffled with the Bays-Durham algorithm.
+    ** shuffleSelect and cuddRand2 are combined to generate the output.
+    */
+
+    /* Pick one element from the shuffle table; "i" will be in the range
+    ** from 0 to STAB_SIZE-1.
+    */
+    i = (int) (shuffleSelect / STAB_DIV);
+    /* Mix the element of the shuffle table with the current iterate of
+    ** the second sub-generator, and replace the chosen element of the
+    ** shuffle table with the current iterate of the first sub-generator.
+    */
+    shuffleSelect   = shuffleTable[i] - cuddRand2;
+    shuffleTable[i] = cuddRand;
+    shuffleSelect  += (shuffleSelect < 1) * (MODULUS1 - 1);
+    /* Since shuffleSelect != 0, and we want to be able to return 0,
+    ** here we subtract 1 before returning.
+    */
+    return(shuffleSelect - 1);
+
+} /* end of Cudd_Random */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializer for the portable random number generator.]
+
+  Description [Initializer for the portable number generator based on
+  ran2 in "Numerical Recipes in C." The input is the seed for the
+  generator. If it is negative, its absolute value is taken as seed.
+  If it is 0, then 1 is taken as seed. The initialized sets up the two
+  recurrences used to generate a long-period stream, and sets up the
+  shuffle table.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Random]
+
+******************************************************************************/
+void
+Cudd_Srandom(
+  long  seed)
+{
+    int i;
+
+    if (seed < 0)       cuddRand = -seed;
+    else if (seed == 0) cuddRand = 1;
+    else                cuddRand = seed;
+    cuddRand2 = cuddRand;
+    /* Load the shuffle table (after 11 warm-ups). */
+    for (i = 0; i < STAB_SIZE + 11; i++) {
+        long int w;
+        w = cuddRand / LEQQ1;
+        cuddRand = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1;
+        cuddRand += (cuddRand < 0) * MODULUS1;
+        shuffleTable[i % STAB_SIZE] = cuddRand;
+    }
+    shuffleSelect = shuffleTable[1 % STAB_SIZE];
+
+} /* end of Cudd_Srandom */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the density of a BDD or ADD.]
+
+  Description [Computes the density of a BDD or ADD. The density is
+  the ratio of the number of minterms to the number of nodes. If 0 is
+  passed as number of variables, the number of variables existing in
+  the manager is used. Returns the density if successful; (double)
+  CUDD_OUT_OF_MEM otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_CountMinterm Cudd_DagSize]
+
+******************************************************************************/
+double
+Cudd_Density(
+  DdManager * dd /* manager */,
+  DdNode * f /* function whose density is sought */,
+  int  nvars /* size of the support of f */)
+{
+    double minterms;
+    int nodes;
+    double density;
+
+    if (nvars == 0) nvars = dd->size;
+    minterms = Cudd_CountMinterm(dd,f,nvars);
+    if (minterms == (double) CUDD_OUT_OF_MEM) return(minterms);
+    nodes = Cudd_DagSize(f);
+    density = minterms / (double) nodes;
+    return(density);
+
+} /* end of Cudd_Density */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Warns that a memory allocation failed.]
+
+  Description [Warns that a memory allocation failed.
+  This function can be used as replacement of MMout_of_memory to prevent
+  the safe_mem functions of the util package from exiting when malloc
+  returns NULL. One possible use is in case of discretionary allocations;
+  for instance, the allocation of memory to enlarge the computed table.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_OutOfMem(
+  long size /* size of the allocation that failed */)
+{
+    (void) fflush(stdout);
+    (void) fprintf(stderr, "\nunable to allocate %ld bytes\n", size);
+    return;
+
+} /* end of Cudd_OutOfMem */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a DD to the standard output. One line per node is
+  printed.]
+
+  Description [Prints a DD to the standard output. One line per node is
+  printed. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrintDebug]
+
+******************************************************************************/
+int
+cuddP(
+  DdManager * dd,
+  DdNode * f)
+{
+    int retval;
+    st__table *table = st__init_table( st__ptrcmp, st__ptrhash);
+
+    if (table == NULL) return(0);
+
+    retval = dp2(dd,f,table);
+    st__free_table(table);
+    (void) fputc('\n',dd->out);
+    return(retval);
+
+} /* end of cuddP */
+
+
+/**Function********************************************************************
+
+  Synopsis [Frees the memory used to store the minterm counts recorded
+  in the visited table.]
+
+  Description [Frees the memory used to store the minterm counts
+  recorded in the visited table. Returns st__CONTINUE.]
+
+  SideEffects [None]
+
+******************************************************************************/
+enum st__retval
+cuddStCountfree(
+  char * key,
+  char * value,
+  char * arg)
+{
+    double      *d;
+
+    d = (double *)value;
+    ABC_FREE(d);
+    return( st__CONTINUE);
+
+} /* end of cuddStCountfree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively collects all the nodes of a DD in a symbol
+  table.]
+
+  Description [Traverses the DD f and collects all its nodes in a
+  symbol table.  f is assumed to be a regular pointer and
+  cuddCollectNodes guarantees this assumption in the recursive calls.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddCollectNodes(
+  DdNode * f,
+  st__table * visited)
+{
+    DdNode      *T, *E;
+    int         retval;
+
+#ifdef DD_DEBUG
+    assert(!Cudd_IsComplement(f));
+#endif
+
+    /* If already visited, nothing to do. */
+    if ( st__is_member(visited, (char *) f) == 1)
+        return(1);
+
+    /* Check for abnormal condition that should never happen. */
+    if (f == NULL)
+        return(0);
+
+    /* Mark node as visited. */
+    if ( st__add_direct(visited, (char *) f, NULL) == st__OUT_OF_MEM)
+        return(0);
+
+    /* Check terminal case. */
+    if (cuddIsConstant(f))
+        return(1);
+
+    /* Recursive calls. */
+    T = cuddT(f);
+    retval = cuddCollectNodes(T,visited);
+    if (retval != 1) return(retval);
+    E = Cudd_Regular(cuddE(f));
+    retval = cuddCollectNodes(E,visited);
+    return(retval);
+
+} /* end of cuddCollectNodes */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively collects all the nodes of a DD in an array.]
+
+  Description [Traverses the DD f and collects all its nodes in an array.
+  The caller should free the array returned by cuddNodeArray.
+  Returns a pointer to the array of nodes in case of success; NULL
+  otherwise.  The nodes are collected in reverse topological order, so
+  that a node is always preceded in the array by all its descendants.]
+
+  SideEffects [The number of nodes is returned as a side effect.]
+
+  SeeAlso     [Cudd_FirstNode]
+
+******************************************************************************/
+DdNodePtr *
+cuddNodeArray(
+  DdNode *f,
+  int *n)
+{
+    DdNodePtr *table;
+    int size, retval;
+
+    size = ddDagInt(Cudd_Regular(f));
+    table = ABC_ALLOC(DdNodePtr, size);
+    if (table == NULL) {
+        ddClearFlag(Cudd_Regular(f));
+        return(NULL);
+    }
+
+    retval = cuddNodeArrayRecur(f, table, 0);
+    assert(retval == size);
+
+    *n = size;
+    return(table);
+
+} /* cuddNodeArray */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of cuddP.]
+
+  Description [Performs the recursive step of cuddP. Returns 1 in case
+  of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+dp2(
+  DdManager *dd,
+  DdNode * f,
+  st__table * t)
+{
+    DdNode *g, *n, *N;
+    int T,E;
+
+    if (f == NULL) {
+        return(0);
+    }
+    g = Cudd_Regular(f);
+    if (cuddIsConstant(g)) {
+#if SIZEOF_VOID_P == 8
+        (void) fprintf(dd->out,"ID = %c0x%lx\tvalue = %-9g\n", bang(f),
+                (ptruint) g / (ptruint) sizeof(DdNode),cuddV(g));
+#else
+        (void) fprintf(dd->out,"ID = %c0x%x\tvalue = %-9g\n", bang(f),
+                (ptruint) g / (ptruint) sizeof(DdNode),cuddV(g));
+#endif
+        return(1);
+    }
+    if ( st__is_member(t,(char *) g) == 1) {
+        return(1);
+    }
+    if ( st__add_direct(t,(char *) g,NULL) == st__OUT_OF_MEM)
+        return(0);
+#ifdef DD_STATS
+#if SIZEOF_VOID_P == 8
+    (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %d\tr = %d\t", bang(f),
+                (ptruint) g / (ptruint) sizeof(DdNode), g->index, g->ref);
+#else
+    (void) fprintf(dd->out,"ID = %c0x%x\tindex = %d\tr = %d\t", bang(f),
+                (ptruint) g / (ptruint) sizeof(DdNode),g->index,g->ref);
+#endif
+#else
+#if SIZEOF_VOID_P == 8
+    (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %u\t", bang(f),
+                (ptruint) g / (ptruint) sizeof(DdNode),g->index);
+#else
+    (void) fprintf(dd->out,"ID = %c0x%x\tindex = %hu\t", bang(f),
+                (ptruint) g / (ptruint) sizeof(DdNode),g->index);
+#endif
+#endif
+    n = cuddT(g);
+    if (cuddIsConstant(n)) {
+        (void) fprintf(dd->out,"T = %-9g\t",cuddV(n));
+        T = 1;
+    } else {
+#if SIZEOF_VOID_P == 8
+        (void) fprintf(dd->out,"T = 0x%lx\t",(ptruint) n / (ptruint) sizeof(DdNode));
+#else
+        (void) fprintf(dd->out,"T = 0x%x\t",(ptruint) n / (ptruint) sizeof(DdNode));
+#endif
+        T = 0;
+    }
+
+    n = cuddE(g);
+    N = Cudd_Regular(n);
+    if (cuddIsConstant(N)) {
+        (void) fprintf(dd->out,"E = %c%-9g\n",bang(n),cuddV(N));
+        E = 1;
+    } else {
+#if SIZEOF_VOID_P == 8
+        (void) fprintf(dd->out,"E = %c0x%lx\n", bang(n), (ptruint) N/(ptruint) sizeof(DdNode));
+#else
+        (void) fprintf(dd->out,"E = %c0x%x\n", bang(n), (ptruint) N/(ptruint) sizeof(DdNode));
+#endif
+        E = 0;
+    }
+    if (E == 0) {
+        if (dp2(dd,N,t) == 0)
+            return(0);
+    }
+    if (T == 0) {
+        if (dp2(dd,cuddT(g),t) == 0)
+            return(0);
+    }
+    return(1);
+
+} /* end of dp2 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_PrintMinterm.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+ddPrintMintermAux(
+  DdManager * dd /* manager */,
+  DdNode * node /* current node */,
+  int * list /* current recursion path */)
+{
+    DdNode      *N,*Nv,*Nnv;
+    int         i,v,index;
+
+    N = Cudd_Regular(node);
+
+    if (cuddIsConstant(N)) {
+        /* Terminal case: Print one cube based on the current recursion
+        ** path, unless we have reached the background value (ADDs) or
+        ** the logical zero (BDDs).
+        */
+        if (node != background && node != zero) {
+            for (i = 0; i < dd->size; i++) {
+                v = list[i];
+                if (v == 0) (void) fprintf(dd->out,"0");
+                else if (v == 1) (void) fprintf(dd->out,"1");
+                else (void) fprintf(dd->out,"-");
+            }
+            (void) fprintf(dd->out," % g\n", cuddV(node));
+        }
+    } else {
+        Nv  = cuddT(N);
+        Nnv = cuddE(N);
+        if (Cudd_IsComplement(node)) {
+            Nv  = Cudd_Not(Nv);
+            Nnv = Cudd_Not(Nnv);
+        }
+        index = N->index;
+        list[index] = 0;
+        ddPrintMintermAux(dd,Nnv,list);
+        list[index] = 1;
+        ddPrintMintermAux(dd,Nv,list);
+        list[index] = 2;
+    }
+    return;
+
+} /* end of ddPrintMintermAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_DagSize.]
+
+  Description [Performs the recursive step of Cudd_DagSize. Returns the
+  number of nodes in the graph rooted at n.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddDagInt(
+  DdNode * n)
+{
+    int tval, eval;
+
+    if (Cudd_IsComplement(n->next)) {
+        return(0);
+    }
+    n->next = Cudd_Not(n->next);
+    if (cuddIsConstant(n)) {
+        return(1);
+    }
+    tval = ddDagInt(cuddT(n));
+    eval = ddDagInt(Cudd_Regular(cuddE(n)));
+    return(1 + tval + eval);
+
+} /* end of ddDagInt */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of cuddNodeArray.]
+
+  Description [Performs the recursive step of cuddNodeArray.  Returns
+  an the number of nodes in the DD.  Clear the least significant bit
+  of the next field that was used as visited flag by
+  cuddNodeArrayRecur when counting the nodes.  node is supposed to be
+  regular; the invariant is maintained by this procedure.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddNodeArrayRecur(
+  DdNode *f,
+  DdNodePtr *table,
+  int index)
+{
+    int tindex, eindex;
+
+    if (!Cudd_IsComplement(f->next)) {
+        return(index);
+    }
+    /* Clear visited flag. */
+    f->next = Cudd_Regular(f->next);
+    if (cuddIsConstant(f)) {
+        table[index] = f;
+        return(index + 1);
+    }
+    tindex = cuddNodeArrayRecur(cuddT(f), table, index);
+    eindex = cuddNodeArrayRecur(Cudd_Regular(cuddE(f)), table, tindex);
+    table[eindex] = f;
+    return(eindex + 1);
+
+} /* end of cuddNodeArrayRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_CofactorEstimate.]
+
+  Description [Performs the recursive step of Cudd_CofactorEstimate.
+  Returns an estimate of the number of nodes in the DD of a
+  cofactor of node. Uses the least significant bit of the next field as
+  visited flag. node is supposed to be regular; the invariant is maintained
+  by this procedure.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddEstimateCofactor(
+  DdManager *dd,
+  st__table *table,
+  DdNode * node,
+  int i,
+  int phase,
+  DdNode ** ptr)
+{
+    int tval, eval, val;
+    DdNode *ptrT, *ptrE;
+
+    if (Cudd_IsComplement(node->next)) {
+        if (! st__lookup(table,(char *)node,(char **)ptr)) {
+            if ( st__add_direct(table,(char *)node,(char *)node) ==
+                st__OUT_OF_MEM)
+                return(CUDD_OUT_OF_MEM);
+            *ptr = node;
+        }
+        return(0);
+    }
+    node->next = Cudd_Not(node->next);
+    if (cuddIsConstant(node)) {
+        *ptr = node;
+        if ( st__add_direct(table,(char *)node,(char *)node) == st__OUT_OF_MEM)
+            return(CUDD_OUT_OF_MEM);
+        return(1);
+    }
+    if ((int) node->index == i) {
+        if (phase == 1) {
+            *ptr = cuddT(node);
+            val = ddDagInt(cuddT(node));
+        } else {
+            *ptr = cuddE(node);
+            val = ddDagInt(Cudd_Regular(cuddE(node)));
+        }
+        if (node->ref > 1) {
+            if ( st__add_direct(table,(char *)node,(char *)*ptr) ==
+                st__OUT_OF_MEM)
+                return(CUDD_OUT_OF_MEM);
+        }
+        return(val);
+    }
+    if (dd->perm[node->index] > dd->perm[i]) {
+        *ptr = node;
+        tval = ddDagInt(cuddT(node));
+        eval = ddDagInt(Cudd_Regular(cuddE(node)));
+        if (node->ref > 1) {
+            if ( st__add_direct(table,(char *)node,(char *)node) ==
+                st__OUT_OF_MEM)
+                return(CUDD_OUT_OF_MEM);
+        }
+        val = 1 + tval + eval;
+        return(val);
+    }
+    tval = cuddEstimateCofactor(dd,table,cuddT(node),i,phase,&ptrT);
+    eval = cuddEstimateCofactor(dd,table,Cudd_Regular(cuddE(node)),i,
+                                phase,&ptrE);
+    ptrE = Cudd_NotCond(ptrE,Cudd_IsComplement(cuddE(node)));
+    if (ptrT == ptrE) {         /* recombination */
+        *ptr = ptrT;
+        val = tval;
+        if (node->ref > 1) {
+            if ( st__add_direct(table,(char *)node,(char *)*ptr) ==
+                    st__OUT_OF_MEM)
+                return(CUDD_OUT_OF_MEM);
+        }
+    } else if ((ptrT != cuddT(node) || ptrE != cuddE(node)) &&
+               (*ptr = cuddUniqueLookup(dd,node->index,ptrT,ptrE)) != NULL) {
+        if (Cudd_IsComplement((*ptr)->next)) {
+            val = 0;
+        } else {
+            val = 1 + tval + eval;
+        }
+        if (node->ref > 1) {
+            if ( st__add_direct(table,(char *)node,(char *)*ptr) ==
+                    st__OUT_OF_MEM)
+                return(CUDD_OUT_OF_MEM);
+        }
+    } else {
+        *ptr = node;
+        val = 1 + tval + eval;
+    }
+    return(val);
+
+} /* end of cuddEstimateCofactor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the unique table for the existence of an internal node.]
+
+  Description [Checks the unique table for the existence of an internal
+  node. Returns a pointer to the node if it is in the table; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUniqueInter]
+
+******************************************************************************/
+static DdNode *
+cuddUniqueLookup(
+  DdManager * unique,
+  int  index,
+  DdNode * T,
+  DdNode * E)
+{
+    int posn;
+    unsigned int level;
+    DdNodePtr *nodelist;
+    DdNode *looking;
+    DdSubtable *subtable;
+
+    if (index >= unique->size) {
+        return(NULL);
+    }
+
+    level = unique->perm[index];
+    subtable = &(unique->subtables[level]);
+
+#ifdef DD_DEBUG
+    assert(level < (unsigned) cuddI(unique,T->index));
+    assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index));
+#endif
+
+    posn = ddHash(cuddF2L(T), cuddF2L(E), subtable->shift);
+    nodelist = subtable->nodelist;
+    looking = nodelist[posn];
+
+    while (T < cuddT(looking)) {
+        looking = Cudd_Regular(looking->next);
+    }
+    while (T == cuddT(looking) && E < cuddE(looking)) {
+        looking = Cudd_Regular(looking->next);
+    }
+    if (cuddT(looking) == T && cuddE(looking) == E) {
+        return(looking);
+    }
+
+    return(NULL);
+
+} /* end of cuddUniqueLookup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_CofactorEstimateSimple.]
+
+  Description [Performs the recursive step of Cudd_CofactorEstimateSimple.
+  Returns an estimate of the number of nodes in the DD of the positive
+  cofactor of node. Uses the least significant bit of the next field as
+  visited flag. node is supposed to be regular; the invariant is maintained
+  by this procedure.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddEstimateCofactorSimple(
+  DdNode * node,
+  int i)
+{
+    int tval, eval;
+
+    if (Cudd_IsComplement(node->next)) {
+        return(0);
+    }
+    node->next = Cudd_Not(node->next);
+    if (cuddIsConstant(node)) {
+        return(1);
+    }
+    tval = cuddEstimateCofactorSimple(cuddT(node),i);
+    if ((int) node->index == i) return(tval);
+    eval = cuddEstimateCofactorSimple(Cudd_Regular(cuddE(node)),i);
+    return(1 + tval + eval);
+
+} /* end of cuddEstimateCofactorSimple */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_CountMinterm.]
+
+  Description [Performs the recursive step of Cudd_CountMinterm.
+  It is based on the following identity. Let |f| be the
+  number of minterms of f. Then:
+  <xmp>
+    |f| = (|f0|+|f1|)/2
+  </xmp>
+  where f0 and f1 are the two cofactors of f.  Does not use the
+  identity |f'| = max - |f|, to minimize loss of accuracy due to
+  roundoff.  Returns the number of minterms of the function rooted at
+  node.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static double
+ddCountMintermAux(
+  DdNode * node,
+  double  max,
+  DdHashTable * table)
+{
+    DdNode      *N, *Nt, *Ne;
+    double      min, minT, minE;
+    DdNode      *res;
+
+    N = Cudd_Regular(node);
+
+    if (cuddIsConstant(N)) {
+        if (node == background || node == zero) {
+            return(0.0);
+        } else {
+            return(max);
+        }
+    }
+    if (N->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) {
+        min = cuddV(res);
+        if (res->ref == 0) {
+            table->manager->dead++;
+            table->manager->constants.dead++;
+        }
+        return(min);
+    }
+
+    Nt = cuddT(N); Ne = cuddE(N);
+    if (Cudd_IsComplement(node)) {
+        Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne);
+    }
+
+    minT = ddCountMintermAux(Nt,max,table);
+    if (minT == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
+    minT *= 0.5;
+    minE = ddCountMintermAux(Ne,max,table);
+    if (minE == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
+    minE *= 0.5;
+    min = minT + minE;
+
+    if (N->ref != 1) {
+        ptrint fanout = (ptrint) N->ref;
+        cuddSatDec(fanout);
+        res = cuddUniqueConst(table->manager,min);
+        if (!cuddHashTableInsert1(table,node,res,fanout)) {
+            cuddRef(res); Cudd_RecursiveDeref(table->manager, res);
+            return((double)CUDD_OUT_OF_MEM);
+        }
+    }
+
+    return(min);
+
+} /* end of ddCountMintermAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_CountPath.]
+
+  Description [Performs the recursive step of Cudd_CountPath.
+  It is based on the following identity. Let |f| be the
+  number of paths of f. Then:
+  <xmp>
+    |f| = |f0|+|f1|
+  </xmp>
+  where f0 and f1 are the two cofactors of f.  Uses the
+  identity |f'| = |f|, to improve the utilization of the (local) cache.
+  Returns the number of paths of the function rooted at node.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static double
+ddCountPathAux(
+  DdNode * node,
+  st__table * table)
+{
+
+    DdNode      *Nv, *Nnv;
+    double      paths, *ppaths, paths1, paths2;
+    double      *dummy;
+
+
+    if (cuddIsConstant(node)) {
+        return(1.0);
+    }
+    if ( st__lookup(table, (const char *)node, (char **)&dummy)) {
+        paths = *dummy;
+        return(paths);
+    }
+
+    Nv = cuddT(node); Nnv = cuddE(node);
+
+    paths1 = ddCountPathAux(Nv,table);
+    if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
+    paths2 = ddCountPathAux(Cudd_Regular(Nnv),table);
+    if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
+    paths = paths1 + paths2;
+
+    ppaths = ABC_ALLOC(double,1);
+    if (ppaths == NULL) {
+        return((double)CUDD_OUT_OF_MEM);
+    }
+
+    *ppaths = paths;
+
+    if ( st__add_direct(table,(char *)node, (char *)ppaths) == st__OUT_OF_MEM) {
+        ABC_FREE(ppaths);
+        return((double)CUDD_OUT_OF_MEM);
+    }
+    return(paths);
+
+} /* end of ddCountPathAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_EpdCountMinterm.]
+
+  Description [Performs the recursive step of Cudd_EpdCountMinterm.
+  It is based on the following identity. Let |f| be the
+  number of minterms of f. Then:
+  <xmp>
+    |f| = (|f0|+|f1|)/2
+  </xmp>
+  where f0 and f1 are the two cofactors of f.  Does not use the
+  identity |f'| = max - |f|, to minimize loss of accuracy due to
+  roundoff.  Returns the number of minterms of the function rooted at
+  node.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddEpdCountMintermAux(
+  DdNode * node,
+  EpDouble * max,
+  EpDouble * epd,
+  st__table * table)
+{
+    DdNode      *Nt, *Ne;
+    EpDouble    *min, minT, minE;
+    EpDouble    *res;
+    int         status;
+
+    /* node is assumed to be regular */
+    if (cuddIsConstant(node)) {
+        if (node == background || node == zero) {
+            EpdMakeZero(epd, 0);
+        } else {
+            EpdCopy(max, epd);
+        }
+        return(0);
+    }
+    if (node->ref != 1 && st__lookup(table, (const char *)node, (char **)&res)) {
+        EpdCopy(res, epd);
+        return(0);
+    }
+
+    Nt = cuddT(node); Ne = cuddE(node);
+
+    status = ddEpdCountMintermAux(Nt,max,&minT,table);
+    if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
+    EpdMultiply(&minT, (double)0.5);
+    status = ddEpdCountMintermAux(Cudd_Regular(Ne),max,&minE,table);
+    if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
+    if (Cudd_IsComplement(Ne)) {
+        EpdSubtract3(max, &minE, epd);
+        EpdCopy(epd, &minE);
+    }
+    EpdMultiply(&minE, (double)0.5);
+    EpdAdd3(&minT, &minE, epd);
+
+    if (node->ref > 1) {
+        min = EpdAlloc();
+        if (!min)
+            return(CUDD_OUT_OF_MEM);
+        EpdCopy(epd, min);
+        if ( st__insert(table, (char *)node, (char *)min) == st__OUT_OF_MEM) {
+            EpdFree(min);
+            return(CUDD_OUT_OF_MEM);
+        }
+    }
+
+    return(0);
+
+} /* end of ddEpdCountMintermAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_CountPathsToNonZero.]
+
+  Description [Performs the recursive step of Cudd_CountPathsToNonZero.
+  It is based on the following identity. Let |f| be the
+  number of paths of f. Then:
+  <xmp>
+    |f| = |f0|+|f1|
+  </xmp>
+  where f0 and f1 are the two cofactors of f.  Returns the number of
+  paths of the function rooted at node.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static double
+ddCountPathsToNonZero(
+  DdNode * N,
+  st__table * table)
+{
+
+    DdNode      *node, *Nt, *Ne;
+    double      paths, *ppaths, paths1, paths2;
+    double      *dummy;
+
+    node = Cudd_Regular(N);
+    if (cuddIsConstant(node)) {
+        return((double) !(Cudd_IsComplement(N) || cuddV(node)==DD_ZERO_VAL));
+    }
+    if ( st__lookup(table, (const char *)N, (char **)&dummy)) {
+        paths = *dummy;
+        return(paths);
+    }
+
+    Nt = cuddT(node); Ne = cuddE(node);
+    if (node != N) {
+        Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne);
+    }
+
+    paths1 = ddCountPathsToNonZero(Nt,table);
+    if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
+    paths2 = ddCountPathsToNonZero(Ne,table);
+    if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
+    paths = paths1 + paths2;
+
+    ppaths = ABC_ALLOC(double,1);
+    if (ppaths == NULL) {
+        return((double)CUDD_OUT_OF_MEM);
+    }
+
+    *ppaths = paths;
+
+    if ( st__add_direct(table,(char *)N, (char *)ppaths) == st__OUT_OF_MEM) {
+        ABC_FREE(ppaths);
+        return((double)CUDD_OUT_OF_MEM);
+    }
+    return(paths);
+
+} /* end of ddCountPathsToNonZero */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_Support.]
+
+  Description [Performs the recursive step of Cudd_Support. Performs a
+  DFS from f. The support is accumulated in supp as a side effect. Uses
+  the LSB of the then pointer as visited flag.]
+
+  SideEffects [None]
+
+  SeeAlso     [ddClearFlag]
+
+******************************************************************************/
+static void
+ddSupportStep(
+  DdNode * f,
+  int * support)
+{
+    if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) {
+        return;
+    }
+
+    support[f->index] = 1;
+    ddSupportStep(cuddT(f),support);
+    ddSupportStep(Cudd_Regular(cuddE(f)),support);
+    /* Mark as visited. */
+    f->next = Cudd_Not(f->next);
+    return;
+
+} /* end of ddSupportStep */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs a DFS from f, clearing the LSB of the next
+  pointers.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [ddSupportStep ddDagInt]
+
+******************************************************************************/
+static void
+ddClearFlag(
+  DdNode * f)
+{
+    if (!Cudd_IsComplement(f->next)) {
+        return;
+    }
+    /* Clear visited flag. */
+    f->next = Cudd_Regular(f->next);
+    if (cuddIsConstant(f)) {
+        return;
+    }
+    ddClearFlag(cuddT(f));
+    ddClearFlag(Cudd_Regular(cuddE(f)));
+    return;
+
+} /* end of ddClearFlag */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_CountLeaves.]
+
+  Description [Performs the recursive step of Cudd_CountLeaves. Returns
+  the number of leaves in the DD rooted at n.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_CountLeaves]
+
+******************************************************************************/
+static int
+ddLeavesInt(
+  DdNode * n)
+{
+    int tval, eval;
+
+    if (Cudd_IsComplement(n->next)) {
+        return(0);
+    }
+    n->next = Cudd_Not(n->next);
+    if (cuddIsConstant(n)) {
+        return(1);
+    }
+    tval = ddLeavesInt(cuddT(n));
+    eval = ddLeavesInt(Cudd_Regular(cuddE(n)));
+    return(tval + eval);
+
+} /* end of ddLeavesInt */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddPickArbitraryMinterms.]
+
+  Description [Performs the recursive step of Cudd_bddPickArbitraryMinterms.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [none]
+
+  SeeAlso [Cudd_bddPickArbitraryMinterms]
+
+******************************************************************************/
+static int
+ddPickArbitraryMinterms(
+  DdManager *dd,
+  DdNode *node,
+  int nvars,
+  int nminterms,
+  char **string)
+{
+    DdNode *N, *T, *E;
+    DdNode *one, *bzero;
+    int    i, t, result;
+    double min1, min2;
+
+    if (string == NULL || node == NULL) return(0);
+
+    /* The constant 0 function has no on-set cubes. */
+    one = DD_ONE(dd);
+    bzero = Cudd_Not(one);
+    if (nminterms == 0 || node == bzero) return(1);
+    if (node == one) {
+        return(1);
+    }
+
+    N = Cudd_Regular(node);
+    T = cuddT(N); E = cuddE(N);
+    if (Cudd_IsComplement(node)) {
+        T = Cudd_Not(T); E = Cudd_Not(E);
+    }
+
+    min1 = Cudd_CountMinterm(dd, T, nvars) / 2.0;
+    if (min1 == (double)CUDD_OUT_OF_MEM) return(0);
+    min2 = Cudd_CountMinterm(dd, E, nvars) / 2.0;
+    if (min2 == (double)CUDD_OUT_OF_MEM) return(0);
+
+    t = (int)((double)nminterms * min1 / (min1 + min2) + 0.5);
+    for (i = 0; i < t; i++)
+        string[i][N->index] = '1';
+    for (i = t; i < nminterms; i++)
+        string[i][N->index] = '0';
+
+    result = ddPickArbitraryMinterms(dd,T,nvars,t,&string[0]);
+    if (result == 0)
+        return(0);
+    result = ddPickArbitraryMinterms(dd,E,nvars,nminterms-t,&string[t]);
+    return(result);
+
+} /* end of ddPickArbitraryMinterms */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a representative cube of a BDD.]
+
+  Description [Finds a representative cube of a BDD with the weight of
+  each variable. From the top variable, if the weight is greater than or
+  equal to 0.0, choose THEN branch unless the child is the constant 0.
+  Otherwise, choose ELSE branch unless the child is the constant 0.]
+
+  SideEffects [Cudd_SubsetWithMaskVars Cudd_bddPickOneCube]
+
+******************************************************************************/
+static int
+ddPickRepresentativeCube(
+  DdManager *dd,
+  DdNode *node,
+  double *weight,
+  char *string)
+{
+    DdNode *N, *T, *E;
+    DdNode *one, *bzero;
+
+    if (string == NULL || node == NULL) return(0);
+
+    /* The constant 0 function has no on-set cubes. */
+    one = DD_ONE(dd);
+    bzero = Cudd_Not(one);
+    if (node == bzero) return(0);
+
+    if (node == DD_ONE(dd)) return(1);
+
+    for (;;) {
+        N = Cudd_Regular(node);
+        if (N == one)
+            break;
+        T = cuddT(N);
+        E = cuddE(N);
+        if (Cudd_IsComplement(node)) {
+            T = Cudd_Not(T);
+            E = Cudd_Not(E);
+        }
+        if (weight[N->index] >= 0.0) {
+            if (T == bzero) {
+                node = E;
+                string[N->index] = '0';
+            } else {
+                node = T;
+                string[N->index] = '1';
+            }
+        } else {
+            if (E == bzero) {
+                node = T;
+                string[N->index] = '1';
+            } else {
+                node = E;
+                string[N->index] = '0';
+            }
+        }
+    }
+    return(1);
+
+} /* end of ddPickRepresentativeCube */
+
+
+/**Function********************************************************************
+
+  Synopsis [Frees the memory used to store the minterm counts recorded
+  in the visited table.]
+
+  Description [Frees the memory used to store the minterm counts
+  recorded in the visited table. Returns st__CONTINUE.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static enum st__retval
+ddEpdFree(
+  char * key,
+  char * value,
+  char * arg)
+{
+    EpDouble    *epd;
+
+    epd = (EpDouble *) value;
+    EpdFree(epd);
+    return( st__CONTINUE);
+
+} /* end of ddEpdFree */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddWindow.c b/abc-build/src/bdd/cudd/cuddWindow.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddWindow.c
@@ -0,0 +1,1031 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddWindow.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for variable reordering by window permutation.]
+
+  Description [Internal procedures included in this module:
+                <ul>
+                <li> cuddWindowReorder()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> ddWindow2()
+                <li> ddWindowConv2()
+                <li> ddPermuteWindow3()
+                <li> ddWindow3()
+                <li> ddWindowConv3()
+                <li> ddPermuteWindow4()
+                <li> ddWindow4()
+                <li> ddWindowConv4()
+                </ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddWindow.c,v 1.14 2009/02/20 02:14:58 fabio Exp $";
+#endif
+
+#ifdef DD_STATS
+extern  int     ddTotalNumberSwapping;
+extern  int     ddTotalNISwaps;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int ddWindow2 (DdManager *table, int low, int high);
+static int ddWindowConv2 (DdManager *table, int low, int high);
+static int ddPermuteWindow3 (DdManager *table, int x);
+static int ddWindow3 (DdManager *table, int low, int high);
+static int ddWindowConv3 (DdManager *table, int low, int high);
+static int ddPermuteWindow4 (DdManager *table, int w);
+static int ddWindow4 (DdManager *table, int low, int high);
+static int ddWindowConv4 (DdManager *table, int low, int high);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders by applying the method of the sliding window.]
+
+  Description [Reorders by applying the method of the sliding window.
+  Tries all possible permutations to the variables in a window that
+  slides from low to high. The size of the window is determined by
+  submethod.  Assumes that no dead nodes are present.  Returns 1 in
+  case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+cuddWindowReorder(
+  DdManager * table /* DD table */,
+  int low /* lowest index to reorder */,
+  int high /* highest index to reorder */,
+  Cudd_ReorderingType submethod /* window reordering option */)
+{
+
+    int res;
+#ifdef DD_DEBUG
+    int supposedOpt;
+#endif
+
+    switch (submethod) {
+    case CUDD_REORDER_WINDOW2:
+        res = ddWindow2(table,low,high);
+        break;
+    case CUDD_REORDER_WINDOW3:
+        res = ddWindow3(table,low,high);
+        break;
+    case CUDD_REORDER_WINDOW4:
+        res = ddWindow4(table,low,high);
+        break;
+    case CUDD_REORDER_WINDOW2_CONV:
+        res = ddWindowConv2(table,low,high);
+        break;
+    case CUDD_REORDER_WINDOW3_CONV:
+        res = ddWindowConv3(table,low,high);
+#ifdef DD_DEBUG
+        supposedOpt = table->keys - table->isolated;
+        res = ddWindow3(table,low,high);
+        if (table->keys - table->isolated != (unsigned) supposedOpt) {
+            (void) fprintf(table->err, "Convergence failed! (%d != %d)\n",
+                           table->keys - table->isolated, supposedOpt);
+        }
+#endif
+        break;
+    case CUDD_REORDER_WINDOW4_CONV:
+        res = ddWindowConv4(table,low,high);
+#ifdef DD_DEBUG
+        supposedOpt = table->keys - table->isolated;
+        res = ddWindow4(table,low,high);
+        if (table->keys - table->isolated != (unsigned) supposedOpt) {
+            (void) fprintf(table->err,"Convergence failed! (%d != %d)\n",
+                           table->keys - table->isolated, supposedOpt);
+        }
+#endif
+        break;
+    default: return(0);
+    }
+
+    return(res);
+
+} /* end of cuddWindowReorder */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders by applying a sliding window of width 2.]
+
+  Description [Reorders by applying a sliding window of width 2.
+  Tries both permutations of the variables in a window
+  that slides from low to high.  Assumes that no dead nodes are
+  present.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddWindow2(
+  DdManager * table,
+  int  low,
+  int  high)
+{
+
+    int x;
+    int res;
+    int size;
+
+#ifdef DD_DEBUG
+    assert(low >= 0 && high < table->size);
+#endif
+
+    if (high-low < 1) return(0);
+
+    res = table->keys - table->isolated;
+    for (x = low; x < high; x++) {
+        size = res;
+        res = cuddSwapInPlace(table,x,x+1);
+        if (res == 0) return(0);
+        if (res >= size) { /* no improvement: undo permutation */
+            res = cuddSwapInPlace(table,x,x+1);
+            if (res == 0) return(0);
+        }
+#ifdef DD_STATS
+        if (res < size) {
+            (void) fprintf(table->out,"-");
+        } else {
+            (void) fprintf(table->out,"=");
+        }
+        fflush(table->out);
+#endif
+    }
+
+    return(1);
+
+} /* end of ddWindow2 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders by repeatedly applying a sliding window of width 2.]
+
+  Description [Reorders by repeatedly applying a sliding window of width
+  2. Tries both permutations of the variables in a window
+  that slides from low to high.  Assumes that no dead nodes are
+  present.  Uses an event-driven approach to determine convergence.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddWindowConv2(
+  DdManager * table,
+  int  low,
+  int  high)
+{
+    int x;
+    int res;
+    int nwin;
+    int newevent;
+    int *events;
+    int size;
+
+#ifdef DD_DEBUG
+    assert(low >= 0 && high < table->size);
+#endif
+
+    if (high-low < 1) return(ddWindowConv2(table,low,high));
+
+    nwin = high-low;
+    events = ABC_ALLOC(int,nwin);
+    if (events == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    for (x=0; x<nwin; x++) {
+        events[x] = 1;
+    }
+
+    res = table->keys - table->isolated;
+    do {
+        newevent = 0;
+        for (x=0; x<nwin; x++) {
+            if (events[x]) {
+                size = res;
+                res = cuddSwapInPlace(table,x+low,x+low+1);
+                if (res == 0) {
+                    ABC_FREE(events);
+                    return(0);
+                }
+                if (res >= size) { /* no improvement: undo permutation */
+                    res = cuddSwapInPlace(table,x+low,x+low+1);
+                    if (res == 0) {
+                        ABC_FREE(events);
+                        return(0);
+                    }
+                }
+                if (res < size) {
+                    if (x < nwin-1)     events[x+1] = 1;
+                    if (x > 0)          events[x-1] = 1;
+                    newevent = 1;
+                }
+                events[x] = 0;
+#ifdef DD_STATS
+                if (res < size) {
+                    (void) fprintf(table->out,"-");
+                } else {
+                    (void) fprintf(table->out,"=");
+                }
+                fflush(table->out);
+#endif
+            }
+        }
+#ifdef DD_STATS
+        if (newevent) {
+            (void) fprintf(table->out,"|");
+            fflush(table->out);
+        }
+#endif
+    } while (newevent);
+
+    ABC_FREE(events);
+
+    return(1);
+
+} /* end of ddWindowConv3 */
+
+
+/**Function********************************************************************
+
+  Synopsis [Tries all the permutations of the three variables between
+  x and x+2 and retains the best.]
+
+  Description [Tries all the permutations of the three variables between
+  x and x+2 and retains the best. Assumes that no dead nodes are
+  present.  Returns the index of the best permutation (1-6) in case of
+  success; 0 otherwise.Assumes that no dead nodes are present.  Returns
+  the index of the best permutation (1-6) in case of success; 0
+  otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddPermuteWindow3(
+  DdManager * table,
+  int  x)
+{
+    int y,z;
+    int size,sizeNew;
+    int best;
+
+#ifdef DD_DEBUG
+    assert(table->dead == 0);
+    assert(x+2 < table->size);
+#endif
+
+    size = table->keys - table->isolated;
+    y = x+1; z = y+1;
+
+    /* The permutation pattern is:
+    ** (x,y)(y,z)
+    ** repeated three times to get all 3! = 6 permutations.
+    */
+#define ABC 1
+    best = ABC;
+
+#define BAC 2
+    sizeNew = cuddSwapInPlace(table,x,y);
+    if (sizeNew < size) {
+        if (sizeNew == 0) return(0);
+        best = BAC;
+        size = sizeNew;
+    }
+#define BCA 3
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size) {
+        if (sizeNew == 0) return(0);
+        best = BCA;
+        size = sizeNew;
+    }
+#define CBA 4
+    sizeNew = cuddSwapInPlace(table,x,y);
+    if (sizeNew < size) {
+        if (sizeNew == 0) return(0);
+        best = CBA;
+        size = sizeNew;
+    }
+#define CAB 5
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size) {
+        if (sizeNew == 0) return(0);
+        best = CAB;
+        size = sizeNew;
+    }
+#define ACB 6
+    sizeNew = cuddSwapInPlace(table,x,y);
+    if (sizeNew < size) {
+        if (sizeNew == 0) return(0);
+        best = ACB;
+        size = sizeNew;
+    }
+
+    /* Now take the shortest route to the best permuytation.
+    ** The initial permutation is ACB.
+    */
+    switch(best) {
+    case BCA: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case CBA: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case ABC: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case ACB: break;
+    case BAC: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case CAB: if (!cuddSwapInPlace(table,x,y)) return(0);
+               break;
+    default: return(0);
+    }
+
+#ifdef DD_DEBUG
+    assert(table->keys - table->isolated == (unsigned) size);
+#endif
+
+    return(best);
+
+} /* end of ddPermuteWindow3 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders by applying a sliding window of width 3.]
+
+  Description [Reorders by applying a sliding window of width 3.
+  Tries all possible permutations to the variables in a
+  window that slides from low to high.  Assumes that no dead nodes are
+  present.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddWindow3(
+  DdManager * table,
+  int  low,
+  int  high)
+{
+
+    int x;
+    int res;
+
+#ifdef DD_DEBUG
+    assert(low >= 0 && high < table->size);
+#endif
+
+    if (high-low < 2) return(ddWindow2(table,low,high));
+
+    for (x = low; x+1 < high; x++) {
+        res = ddPermuteWindow3(table,x);
+        if (res == 0) return(0);
+#ifdef DD_STATS
+        if (res == ABC) {
+            (void) fprintf(table->out,"=");
+        } else {
+            (void) fprintf(table->out,"-");
+        }
+        fflush(table->out);
+#endif
+    }
+
+    return(1);
+
+} /* end of ddWindow3 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders by repeatedly applying a sliding window of width 3.]
+
+  Description [Reorders by repeatedly applying a sliding window of width
+  3. Tries all possible permutations to the variables in a
+  window that slides from low to high.  Assumes that no dead nodes are
+  present.  Uses an event-driven approach to determine convergence.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddWindowConv3(
+  DdManager * table,
+  int  low,
+  int  high)
+{
+    int x;
+    int res;
+    int nwin;
+    int newevent;
+    int *events;
+
+#ifdef DD_DEBUG
+    assert(low >= 0 && high < table->size);
+#endif
+
+    if (high-low < 2) return(ddWindowConv2(table,low,high));
+
+    nwin = high-low-1;
+    events = ABC_ALLOC(int,nwin);
+    if (events == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    for (x=0; x<nwin; x++) {
+        events[x] = 1;
+    }
+
+    do {
+        newevent = 0;
+        for (x=0; x<nwin; x++) {
+            if (events[x]) {
+                res = ddPermuteWindow3(table,x+low);
+                switch (res) {
+                case ABC:
+                    break;
+                case BAC:
+                    if (x < nwin-1)     events[x+1] = 1;
+                    if (x > 1)          events[x-2] = 1;
+                    newevent = 1;
+                    break;
+                case BCA:
+                case CBA:
+                case CAB:
+                    if (x < nwin-2)     events[x+2] = 1;
+                    if (x < nwin-1)     events[x+1] = 1;
+                    if (x > 0)          events[x-1] = 1;
+                    if (x > 1)          events[x-2] = 1;
+                    newevent = 1;
+                    break;
+                case ACB:
+                    if (x < nwin-2)     events[x+2] = 1;
+                    if (x > 0)          events[x-1] = 1;
+                    newevent = 1;
+                    break;
+                default:
+                    ABC_FREE(events);
+                    return(0);
+                }
+                events[x] = 0;
+#ifdef DD_STATS
+                if (res == ABC) {
+                    (void) fprintf(table->out,"=");
+                } else {
+                    (void) fprintf(table->out,"-");
+                }
+                fflush(table->out);
+#endif
+            }
+        }
+#ifdef DD_STATS
+        if (newevent) {
+            (void) fprintf(table->out,"|");
+            fflush(table->out);
+        }
+#endif
+    } while (newevent);
+
+    ABC_FREE(events);
+
+    return(1);
+
+} /* end of ddWindowConv3 */
+
+
+/**Function********************************************************************
+
+  Synopsis [Tries all the permutations of the four variables between w
+  and w+3 and retains the best.]
+
+  Description [Tries all the permutations of the four variables between
+  w and w+3 and retains the best. Assumes that no dead nodes are
+  present.  Returns the index of the best permutation (1-24) in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddPermuteWindow4(
+  DdManager * table,
+  int  w)
+{
+    int x,y,z;
+    int size,sizeNew;
+    int best;
+
+#ifdef DD_DEBUG
+    assert(table->dead == 0);
+    assert(w+3 < table->size);
+#endif
+
+    size = table->keys - table->isolated;
+    x = w+1; y = x+1; z = y+1;
+
+    /* The permutation pattern is:
+     * (w,x)(y,z)(w,x)(x,y)
+     * (y,z)(w,x)(y,z)(x,y)
+     * repeated three times to get all 4! = 24 permutations.
+     * This gives a hamiltonian circuit of Cayley's graph.
+     * The codes to the permutation are assigned in topological order.
+     * The permutations at lower distance from the final permutation are
+     * assigned lower codes. This way we can choose, between
+     * permutations that give the same size, one that requires the minimum
+     * number of swaps from the final permutation of the hamiltonian circuit.
+     * There is an exception to this rule: ABCD is given Code 1, to
+     * avoid oscillation when convergence is sought.
+     */
+#define ABCD 1
+    best = ABCD;
+
+#define BACD 7
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size) {
+        if (sizeNew == 0) return(0);
+        best = BACD;
+        size = sizeNew;
+    }
+#define BADC 13
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size) {
+        if (sizeNew == 0) return(0);
+        best = BADC;
+        size = sizeNew;
+    }
+#define ABDC 8
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size || (sizeNew == size && ABDC < best)) {
+        if (sizeNew == 0) return(0);
+        best = ABDC;
+        size = sizeNew;
+    }
+#define ADBC 14
+    sizeNew = cuddSwapInPlace(table,x,y);
+    if (sizeNew < size) {
+        if (sizeNew == 0) return(0);
+        best = ADBC;
+        size = sizeNew;
+    }
+#define ADCB 9
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size || (sizeNew == size && ADCB < best)) {
+        if (sizeNew == 0) return(0);
+        best = ADCB;
+        size = sizeNew;
+    }
+#define DACB 15
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size) {
+        if (sizeNew == 0) return(0);
+        best = DACB;
+        size = sizeNew;
+    }
+#define DABC 20
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size) {
+        if (sizeNew == 0) return(0);
+        best = DABC;
+        size = sizeNew;
+    }
+#define DBAC 23
+    sizeNew = cuddSwapInPlace(table,x,y);
+    if (sizeNew < size) {
+        if (sizeNew == 0) return(0);
+        best = DBAC;
+        size = sizeNew;
+    }
+#define BDAC 19
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size || (sizeNew == size && BDAC < best)) {
+        if (sizeNew == 0) return(0);
+        best = BDAC;
+        size = sizeNew;
+    }
+#define BDCA 21
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size || (sizeNew == size && BDCA < best)) {
+        if (sizeNew == 0) return(0);
+        best = BDCA;
+        size = sizeNew;
+    }
+#define DBCA 24
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size) {
+        if (sizeNew == 0) return(0);
+        best = DBCA;
+        size = sizeNew;
+    }
+#define DCBA 22
+    sizeNew = cuddSwapInPlace(table,x,y);
+    if (sizeNew < size || (sizeNew == size && DCBA < best)) {
+        if (sizeNew == 0) return(0);
+        best = DCBA;
+        size = sizeNew;
+    }
+#define DCAB 18
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size || (sizeNew == size && DCAB < best)) {
+        if (sizeNew == 0) return(0);
+        best = DCAB;
+        size = sizeNew;
+    }
+#define CDAB 12
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size || (sizeNew == size && CDAB < best)) {
+        if (sizeNew == 0) return(0);
+        best = CDAB;
+        size = sizeNew;
+    }
+#define CDBA 17
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size || (sizeNew == size && CDBA < best)) {
+        if (sizeNew == 0) return(0);
+        best = CDBA;
+        size = sizeNew;
+    }
+#define CBDA 11
+    sizeNew = cuddSwapInPlace(table,x,y);
+    if (sizeNew < size || (sizeNew == size && CBDA < best)) {
+        if (sizeNew == 0) return(0);
+        best = CBDA;
+        size = sizeNew;
+    }
+#define BCDA 16
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size || (sizeNew == size && BCDA < best)) {
+        if (sizeNew == 0) return(0);
+        best = BCDA;
+        size = sizeNew;
+    }
+#define BCAD 10
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size || (sizeNew == size && BCAD < best)) {
+        if (sizeNew == 0) return(0);
+        best = BCAD;
+        size = sizeNew;
+    }
+#define CBAD 5
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size || (sizeNew == size && CBAD < best)) {
+        if (sizeNew == 0) return(0);
+        best = CBAD;
+        size = sizeNew;
+    }
+#define CABD 3
+    sizeNew = cuddSwapInPlace(table,x,y);
+    if (sizeNew < size || (sizeNew == size && CABD < best)) {
+        if (sizeNew == 0) return(0);
+        best = CABD;
+        size = sizeNew;
+    }
+#define CADB 6
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size || (sizeNew == size && CADB < best)) {
+        if (sizeNew == 0) return(0);
+        best = CADB;
+        size = sizeNew;
+    }
+#define ACDB 4
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size || (sizeNew == size && ACDB < best)) {
+        if (sizeNew == 0) return(0);
+        best = ACDB;
+        size = sizeNew;
+    }
+#define ACBD 2
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size || (sizeNew == size && ACBD < best)) {
+        if (sizeNew == 0) return(0);
+        best = ACBD;
+        size = sizeNew;
+    }
+
+    /* Now take the shortest route to the best permutation.
+    ** The initial permutation is ACBD.
+    */
+    switch(best) {
+    case DBCA: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case BDCA: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case CDBA: if (!cuddSwapInPlace(table,w,x)) return(0);
+    case ADBC: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case ABDC: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case ACDB: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case ACBD: break;
+    case DCBA: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case BCDA: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case CBDA: if (!cuddSwapInPlace(table,w,x)) return(0);
+               if (!cuddSwapInPlace(table,x,y)) return(0);
+               if (!cuddSwapInPlace(table,y,z)) return(0);
+               break;
+    case DBAC: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case DCAB: if (!cuddSwapInPlace(table,w,x)) return(0);
+    case DACB: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case BACD: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case CABD: if (!cuddSwapInPlace(table,w,x)) return(0);
+               break;
+    case DABC: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case BADC: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case CADB: if (!cuddSwapInPlace(table,w,x)) return(0);
+               if (!cuddSwapInPlace(table,y,z)) return(0);
+               break;
+    case BDAC: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case CDAB: if (!cuddSwapInPlace(table,w,x)) return(0);
+    case ADCB: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case ABCD: if (!cuddSwapInPlace(table,x,y)) return(0);
+               break;
+    case BCAD: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case CBAD: if (!cuddSwapInPlace(table,w,x)) return(0);
+               if (!cuddSwapInPlace(table,x,y)) return(0);
+               break;
+    default: return(0);
+    }
+
+#ifdef DD_DEBUG
+    assert(table->keys - table->isolated == (unsigned) size);
+#endif
+
+    return(best);
+
+} /* end of ddPermuteWindow4 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders by applying a sliding window of width 4.]
+
+  Description [Reorders by applying a sliding window of width 4.
+  Tries all possible permutations to the variables in a
+  window that slides from low to high.  Assumes that no dead nodes are
+  present.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddWindow4(
+  DdManager * table,
+  int  low,
+  int  high)
+{
+
+    int w;
+    int res;
+
+#ifdef DD_DEBUG
+    assert(low >= 0 && high < table->size);
+#endif
+
+    if (high-low < 3) return(ddWindow3(table,low,high));
+
+    for (w = low; w+2 < high; w++) {
+        res = ddPermuteWindow4(table,w);
+        if (res == 0) return(0);
+#ifdef DD_STATS
+        if (res == ABCD) {
+            (void) fprintf(table->out,"=");
+        } else {
+            (void) fprintf(table->out,"-");
+        }
+        fflush(table->out);
+#endif
+    }
+
+    return(1);
+
+} /* end of ddWindow4 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders by repeatedly applying a sliding window of width 4.]
+
+  Description [Reorders by repeatedly applying a sliding window of width
+  4. Tries all possible permutations to the variables in a
+  window that slides from low to high.  Assumes that no dead nodes are
+  present.  Uses an event-driven approach to determine convergence.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddWindowConv4(
+  DdManager * table,
+  int  low,
+  int  high)
+{
+    int x;
+    int res;
+    int nwin;
+    int newevent;
+    int *events;
+
+#ifdef DD_DEBUG
+    assert(low >= 0 && high < table->size);
+#endif
+
+    if (high-low < 3) return(ddWindowConv3(table,low,high));
+
+    nwin = high-low-2;
+    events = ABC_ALLOC(int,nwin);
+    if (events == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    for (x=0; x<nwin; x++) {
+        events[x] = 1;
+    }
+
+    do {
+        newevent = 0;
+        for (x=0; x<nwin; x++) {
+            if (events[x]) {
+                res = ddPermuteWindow4(table,x+low);
+                switch (res) {
+                case ABCD:
+                    break;
+                case BACD:
+                    if (x < nwin-1)     events[x+1] = 1;
+                    if (x > 2)          events[x-3] = 1;
+                    newevent = 1;
+                    break;
+                case BADC:
+                    if (x < nwin-3)     events[x+3] = 1;
+                    if (x < nwin-1)     events[x+1] = 1;
+                    if (x > 0)          events[x-1] = 1;
+                    if (x > 2)          events[x-3] = 1;
+                    newevent = 1;
+                    break;
+                case ABDC:
+                    if (x < nwin-3)     events[x+3] = 1;
+                    if (x > 0)          events[x-1] = 1;
+                    newevent = 1;
+                    break;
+                case ADBC:
+                case ADCB:
+                case ACDB:
+                    if (x < nwin-3)     events[x+3] = 1;
+                    if (x < nwin-2)     events[x+2] = 1;
+                    if (x > 0)          events[x-1] = 1;
+                    if (x > 1)          events[x-2] = 1;
+                    newevent = 1;
+                    break;
+                case DACB:
+                case DABC:
+                case DBAC:
+                case BDAC:
+                case BDCA:
+                case DBCA:
+                case DCBA:
+                case DCAB:
+                case CDAB:
+                case CDBA:
+                case CBDA:
+                case BCDA:
+                case CADB:
+                    if (x < nwin-3)     events[x+3] = 1;
+                    if (x < nwin-2)     events[x+2] = 1;
+                    if (x < nwin-1)     events[x+1] = 1;
+                    if (x > 0)          events[x-1] = 1;
+                    if (x > 1)          events[x-2] = 1;
+                    if (x > 2)          events[x-3] = 1;
+                    newevent = 1;
+                    break;
+                case BCAD:
+                case CBAD:
+                case CABD:
+                    if (x < nwin-2)     events[x+2] = 1;
+                    if (x < nwin-1)     events[x+1] = 1;
+                    if (x > 1)          events[x-2] = 1;
+                    if (x > 2)          events[x-3] = 1;
+                    newevent = 1;
+                    break;
+                case ACBD:
+                    if (x < nwin-2)     events[x+2] = 1;
+                    if (x > 1)          events[x-2] = 1;
+                    newevent = 1;
+                    break;
+                default:
+                    ABC_FREE(events);
+                    return(0);
+                }
+                events[x] = 0;
+#ifdef DD_STATS
+                if (res == ABCD) {
+                    (void) fprintf(table->out,"=");
+                } else {
+                    (void) fprintf(table->out,"-");
+                }
+                fflush(table->out);
+#endif
+            }
+        }
+#ifdef DD_STATS
+        if (newevent) {
+            (void) fprintf(table->out,"|");
+            fflush(table->out);
+        }
+#endif
+    } while (newevent);
+
+    ABC_FREE(events);
+
+    return(1);
+
+} /* end of ddWindowConv4 */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddZddCount.c b/abc-build/src/bdd/cudd/cuddZddCount.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddZddCount.c
@@ -0,0 +1,365 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddCount.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Procedures to count the number of minterms of a ZDD.]
+
+  Description [External procedures included in this module:
+                    <ul>
+                    <li> Cudd_zddCount();
+                    <li> Cudd_zddCountDouble();
+                    </ul>
+               Internal procedures included in this module:
+                    <ul>
+                    </ul>
+               Static procedures included in this module:
+                    <ul>
+                    <li> cuddZddCountStep();
+                    <li> cuddZddCountDoubleStep();
+                    <li> st__zdd_count_dbl_free()
+                    <li> st__zdd_countfree()
+                    </ul>
+              ]
+
+  SeeAlso     []
+
+  Author      [Hyong-Kyoon Shin, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddCount.c,v 1.14 2004/08/13 18:04:53 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int cuddZddCountStep (DdNode *P, st__table *table, DdNode *base, DdNode *empty);
+static double cuddZddCountDoubleStep (DdNode *P, st__table *table, DdNode *base, DdNode *empty);
+static enum st__retval st__zdd_countfree (char *key, char *value, char *arg);
+static enum st__retval st__zdd_count_dbl_free (char *key, char *value, char *arg);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Counts the number of minterms in a ZDD.]
+
+  Description [Returns an integer representing the number of minterms
+  in a ZDD.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddCountDouble]
+
+******************************************************************************/
+int
+Cudd_zddCount(
+  DdManager * zdd,
+  DdNode * P)
+{
+    st__table    *table;
+    int         res;
+    DdNode      *base, *empty;
+
+    base  = DD_ONE(zdd);
+    empty = DD_ZERO(zdd);
+    table = st__init_table( st__ptrcmp, st__ptrhash);
+    if (table == NULL) return(CUDD_OUT_OF_MEM);
+    res = cuddZddCountStep(P, table, base, empty);
+    if (res == CUDD_OUT_OF_MEM) {
+        zdd->errorCode = CUDD_MEMORY_OUT;
+    }
+    st__foreach(table, st__zdd_countfree, NIL(char));
+    st__free_table(table);
+
+    return(res);
+
+} /* end of Cudd_zddCount */
+
+
+/**Function********************************************************************
+
+  Synopsis [Counts the number of minterms of a ZDD.]
+
+  Description [Counts the number of minterms of a ZDD. The result is
+  returned as a double. If the procedure runs out of memory, it
+  returns (double) CUDD_OUT_OF_MEM. This procedure is used in
+  Cudd_zddCountMinterm.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddCountMinterm Cudd_zddCount]
+
+******************************************************************************/
+double
+Cudd_zddCountDouble(
+  DdManager * zdd,
+  DdNode * P)
+{
+    st__table    *table;
+    double      res;
+    DdNode      *base, *empty;
+
+    base  = DD_ONE(zdd);
+    empty = DD_ZERO(zdd);
+    table = st__init_table( st__ptrcmp, st__ptrhash);
+    if (table == NULL) return((double)CUDD_OUT_OF_MEM);
+    res = cuddZddCountDoubleStep(P, table, base, empty);
+    if (res == (double)CUDD_OUT_OF_MEM) {
+        zdd->errorCode = CUDD_MEMORY_OUT;
+    }
+    st__foreach(table, st__zdd_count_dbl_free, NIL(char));
+    st__free_table(table);
+
+    return(res);
+
+} /* end of Cudd_zddCountDouble */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddCount.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddCountStep(
+  DdNode * P,
+  st__table * table,
+  DdNode * base,
+  DdNode * empty)
+{
+    int         res;
+    int         *dummy;
+
+    if (P == empty)
+        return(0);
+    if (P == base)
+        return(1);
+
+    /* Check cache. */
+    if ( st__lookup(table, (const char *)P, (char **)&dummy)) {
+        res = *dummy;
+        return(res);
+    }
+
+    res = cuddZddCountStep(cuddE(P), table, base, empty) +
+        cuddZddCountStep(cuddT(P), table, base, empty);
+
+    dummy = ABC_ALLOC(int, 1);
+    if (dummy == NULL) {
+        return(CUDD_OUT_OF_MEM);
+    }
+    *dummy = res;
+    if ( st__insert(table, (char *)P, (char *)dummy) == st__OUT_OF_MEM) {
+        ABC_FREE(dummy);
+        return(CUDD_OUT_OF_MEM);
+    }
+
+    return(res);
+
+} /* end of cuddZddCountStep */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddCountDouble.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static double
+cuddZddCountDoubleStep(
+  DdNode * P,
+  st__table * table,
+  DdNode * base,
+  DdNode * empty)
+{
+    double      res;
+    double      *dummy;
+
+    if (P == empty)
+        return((double)0.0);
+    if (P == base)
+        return((double)1.0);
+
+    /* Check cache */
+    if ( st__lookup(table, (const char *)P, (char **)&dummy)) {
+        res = *dummy;
+        return(res);
+    }
+
+    res = cuddZddCountDoubleStep(cuddE(P), table, base, empty) +
+        cuddZddCountDoubleStep(cuddT(P), table, base, empty);
+
+    dummy = ABC_ALLOC(double, 1);
+    if (dummy == NULL) {
+        return((double)CUDD_OUT_OF_MEM);
+    }
+    *dummy = res;
+    if ( st__insert(table, (char *)P, (char *)dummy) == st__OUT_OF_MEM) {
+        ABC_FREE(dummy);
+        return((double)CUDD_OUT_OF_MEM);
+    }
+
+    return(res);
+
+} /* end of cuddZddCountDoubleStep */
+
+
+/**Function********************************************************************
+
+  Synopsis [Frees the memory associated with the computed table of
+  Cudd_zddCount.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static enum st__retval
+ st__zdd_countfree(
+  char * key,
+  char * value,
+  char * arg)
+{
+    int *d;
+
+    d = (int *)value;
+    ABC_FREE(d);
+    return( st__CONTINUE);
+
+} /* end of st__zdd_countfree */
+
+
+/**Function********************************************************************
+
+  Synopsis [Frees the memory associated with the computed table of
+  Cudd_zddCountDouble.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static enum st__retval
+ st__zdd_count_dbl_free(
+  char * key,
+  char * value,
+  char * arg)
+{
+    double      *d;
+
+    d = (double *)value;
+    ABC_FREE(d);
+    return( st__CONTINUE);
+
+} /* end of st__zdd_count_dbl_free */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddZddFuncs.c b/abc-build/src/bdd/cudd/cuddZddFuncs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddZddFuncs.c
@@ -0,0 +1,1638 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddFuncs.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions to manipulate covers represented as ZDDs.]
+
+  Description [External procedures included in this module:
+                    <ul>
+                    <li> Cudd_zddProduct();
+                    <li> Cudd_zddUnateProduct();
+                    <li> Cudd_zddWeakDiv();
+                    <li> Cudd_zddWeakDivF();
+                    <li> Cudd_zddDivide();
+                    <li> Cudd_zddDivideF();
+                    <li> Cudd_zddComplement();
+                    </ul>
+               Internal procedures included in this module:
+                    <ul>
+                    <li> cuddZddProduct();
+                    <li> cuddZddUnateProduct();
+                    <li> cuddZddWeakDiv();
+                    <li> cuddZddWeakDivF();
+                    <li> cuddZddDivide();
+                    <li> cuddZddDivideF();
+                    <li> cuddZddGetCofactors3()
+                    <li> cuddZddGetCofactors2()
+                    <li> cuddZddComplement();
+                    <li> cuddZddGetPosVarIndex();
+                    <li> cuddZddGetNegVarIndex();
+                    <li> cuddZddGetPosVarLevel();
+                    <li> cuddZddGetNegVarLevel();
+                    </ul>
+               Static procedures included in this module:
+                    <ul>
+                    </ul>
+              ]
+
+  SeeAlso     []
+
+  Author      [In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddFuncs.c,v 1.16 2008/04/25 07:39:33 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the product of two covers represented by ZDDs.]
+
+  Description [Computes the product of two covers represented by
+  ZDDs. The result is also a ZDD. Returns a pointer to the result if
+  successful; NULL otherwise.  The covers on which Cudd_zddProduct
+  operates use two ZDD variables for each function variable (one ZDD
+  variable for each literal of the variable). Those two ZDD variables
+  should be adjacent in the order.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddUnateProduct]
+
+******************************************************************************/
+DdNode  *
+Cudd_zddProduct(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode      *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddZddProduct(dd, f, g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddProduct */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the product of two unate covers.]
+
+  Description [Computes the product of two unate covers represented as
+  ZDDs. Unate covers use one ZDD variable for each BDD
+  variable. Returns a pointer to the result if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddProduct]
+
+******************************************************************************/
+DdNode  *
+Cudd_zddUnateProduct(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode      *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddZddUnateProduct(dd, f, g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddUnateProduct */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Applies weak division to two covers.]
+
+  Description [Applies weak division to two ZDDs representing two
+  covers. Returns a pointer to the ZDD representing the result if
+  successful; NULL otherwise. The result of weak division depends on
+  the variable order. The covers on which Cudd_zddWeakDiv operates use
+  two ZDD variables for each function variable (one ZDD variable for
+  each literal of the variable). Those two ZDD variables should be
+  adjacent in the order.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddDivide]
+
+******************************************************************************/
+DdNode  *
+Cudd_zddWeakDiv(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode      *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddZddWeakDiv(dd, f, g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddWeakDiv */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the quotient of two unate covers.]
+
+  Description [Computes the quotient of two unate covers represented
+  by ZDDs.  Unate covers use one ZDD variable for each BDD
+  variable. Returns a pointer to the resulting ZDD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddWeakDiv]
+
+******************************************************************************/
+DdNode  *
+Cudd_zddDivide(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode      *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddZddDivide(dd, f, g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddDivide */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Modified version of Cudd_zddWeakDiv.]
+
+  Description [Modified version of Cudd_zddWeakDiv. This function may
+  disappear in future releases.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddWeakDiv]
+
+******************************************************************************/
+DdNode  *
+Cudd_zddWeakDivF(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode      *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddZddWeakDivF(dd, f, g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddWeakDivF */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Modified version of Cudd_zddDivide.]
+
+  Description [Modified version of Cudd_zddDivide. This function may
+  disappear in future releases.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode  *
+Cudd_zddDivideF(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode      *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddZddDivideF(dd, f, g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddDivideF */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a complement cover for a ZDD node.]
+
+  Description [Computes a complement cover for a ZDD node. For lack of a
+  better method, we first extract the function BDD from the ZDD cover,
+  then make the complement of the ZDD cover from the complement of the
+  BDD node by using ISOP. Returns a pointer to the resulting cover if
+  successful; NULL otherwise. The result depends on current variable
+  order.]
+
+  SideEffects [The result depends on current variable order.]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode  *
+Cudd_zddComplement(
+  DdManager *dd,
+  DdNode *node)
+{
+    DdNode      *b, *isop, *zdd_I;
+
+    /* Check cache */
+    zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node);
+    if (zdd_I)
+        return(zdd_I);
+
+    b = Cudd_MakeBddFromZddCover(dd, node);
+    if (!b)
+        return(NULL);
+    Cudd_Ref(b);
+    isop = Cudd_zddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I);
+    if (!isop) {
+        Cudd_RecursiveDeref(dd, b);
+        return(NULL);
+    }
+    Cudd_Ref(isop);
+    Cudd_Ref(zdd_I);
+    Cudd_RecursiveDeref(dd, b);
+    Cudd_RecursiveDeref(dd, isop);
+
+    cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I);
+    Cudd_Deref(zdd_I);
+    return(zdd_I);
+} /* end of Cudd_zddComplement */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddProduct.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddProduct]
+
+******************************************************************************/
+DdNode  *
+cuddZddProduct(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    int         v, top_f, top_g;
+    DdNode      *tmp, *term1, *term2, *term3;
+    DdNode      *f0, *f1, *fd, *g0, *g1, *gd;
+    DdNode      *R0, *R1, *Rd, *N0, *N1;
+    DdNode      *r;
+    DdNode      *one = DD_ONE(dd);
+    DdNode      *zero = DD_ZERO(dd);
+    int         flag;
+    int         pv, nv;
+
+    statLine(dd);
+    if (f == zero || g == zero)
+        return(zero);
+    if (f == one)
+        return(g);
+    if (g == one)
+        return(f);
+
+    top_f = dd->permZ[f->index];
+    top_g = dd->permZ[g->index];
+
+    if (top_f > top_g)
+        return(cuddZddProduct(dd, g, f));
+
+    /* Check cache */
+    r = cuddCacheLookup2Zdd(dd, cuddZddProduct, f, g);
+    if (r)
+        return(r);
+
+    v = f->index;       /* either yi or zi */
+    flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
+    if (flag == 1)
+        return(NULL);
+    Cudd_Ref(f1);
+    Cudd_Ref(f0);
+    Cudd_Ref(fd);
+    flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
+    if (flag == 1) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        return(NULL);
+    }
+    Cudd_Ref(g1);
+    Cudd_Ref(g0);
+    Cudd_Ref(gd);
+    pv = cuddZddGetPosVarIndex(dd, v);
+    nv = cuddZddGetNegVarIndex(dd, v);
+
+    Rd = cuddZddProduct(dd, fd, gd);
+    if (Rd == NULL) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, g0);
+        Cudd_RecursiveDerefZdd(dd, gd);
+        return(NULL);
+    }
+    Cudd_Ref(Rd);
+
+    term1 = cuddZddProduct(dd, f0, g0);
+    if (term1 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, g0);
+        Cudd_RecursiveDerefZdd(dd, gd);
+        Cudd_RecursiveDerefZdd(dd, Rd);
+        return(NULL);
+    }
+    Cudd_Ref(term1);
+    term2 = cuddZddProduct(dd, f0, gd);
+    if (term2 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, g0);
+        Cudd_RecursiveDerefZdd(dd, gd);
+        Cudd_RecursiveDerefZdd(dd, Rd);
+        Cudd_RecursiveDerefZdd(dd, term1);
+        return(NULL);
+    }
+    Cudd_Ref(term2);
+    term3 = cuddZddProduct(dd, fd, g0);
+    if (term3 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, g0);
+        Cudd_RecursiveDerefZdd(dd, gd);
+        Cudd_RecursiveDerefZdd(dd, Rd);
+        Cudd_RecursiveDerefZdd(dd, term1);
+        Cudd_RecursiveDerefZdd(dd, term2);
+        return(NULL);
+    }
+    Cudd_Ref(term3);
+    Cudd_RecursiveDerefZdd(dd, f0);
+    Cudd_RecursiveDerefZdd(dd, g0);
+    tmp = cuddZddUnion(dd, term1, term2);
+    if (tmp == NULL) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, gd);
+        Cudd_RecursiveDerefZdd(dd, Rd);
+        Cudd_RecursiveDerefZdd(dd, term1);
+        Cudd_RecursiveDerefZdd(dd, term2);
+        Cudd_RecursiveDerefZdd(dd, term3);
+        return(NULL);
+    }
+    Cudd_Ref(tmp);
+    Cudd_RecursiveDerefZdd(dd, term1);
+    Cudd_RecursiveDerefZdd(dd, term2);
+    R0 = cuddZddUnion(dd, tmp, term3);
+    if (R0 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, gd);
+        Cudd_RecursiveDerefZdd(dd, Rd);
+        Cudd_RecursiveDerefZdd(dd, term3);
+        Cudd_RecursiveDerefZdd(dd, tmp);
+        return(NULL);
+    }
+    Cudd_Ref(R0);
+    Cudd_RecursiveDerefZdd(dd, tmp);
+    Cudd_RecursiveDerefZdd(dd, term3);
+    N0 = cuddZddGetNode(dd, nv, R0, Rd); /* nv = zi */
+    if (N0 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, gd);
+        Cudd_RecursiveDerefZdd(dd, Rd);
+        Cudd_RecursiveDerefZdd(dd, R0);
+        return(NULL);
+    }
+    Cudd_Ref(N0);
+    Cudd_RecursiveDerefZdd(dd, R0);
+    Cudd_RecursiveDerefZdd(dd, Rd);
+
+    term1 = cuddZddProduct(dd, f1, g1);
+    if (term1 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, gd);
+        Cudd_RecursiveDerefZdd(dd, N0);
+        return(NULL);
+    }
+    Cudd_Ref(term1);
+    term2 = cuddZddProduct(dd, f1, gd);
+    if (term2 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, gd);
+        Cudd_RecursiveDerefZdd(dd, N0);
+        Cudd_RecursiveDerefZdd(dd, term1);
+        return(NULL);
+    }
+    Cudd_Ref(term2);
+    term3 = cuddZddProduct(dd, fd, g1);
+    if (term3 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, gd);
+        Cudd_RecursiveDerefZdd(dd, N0);
+        Cudd_RecursiveDerefZdd(dd, term1);
+        Cudd_RecursiveDerefZdd(dd, term2);
+        return(NULL);
+    }
+    Cudd_Ref(term3);
+    Cudd_RecursiveDerefZdd(dd, f1);
+    Cudd_RecursiveDerefZdd(dd, g1);
+    Cudd_RecursiveDerefZdd(dd, fd);
+    Cudd_RecursiveDerefZdd(dd, gd);
+    tmp = cuddZddUnion(dd, term1, term2);
+    if (tmp == NULL) {
+        Cudd_RecursiveDerefZdd(dd, N0);
+        Cudd_RecursiveDerefZdd(dd, term1);
+        Cudd_RecursiveDerefZdd(dd, term2);
+        Cudd_RecursiveDerefZdd(dd, term3);
+        return(NULL);
+    }
+    Cudd_Ref(tmp);
+    Cudd_RecursiveDerefZdd(dd, term1);
+    Cudd_RecursiveDerefZdd(dd, term2);
+    R1 = cuddZddUnion(dd, tmp, term3);
+    if (R1 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, N0);
+        Cudd_RecursiveDerefZdd(dd, term3);
+        Cudd_RecursiveDerefZdd(dd, tmp);
+        return(NULL);
+    }
+    Cudd_Ref(R1);
+    Cudd_RecursiveDerefZdd(dd, tmp);
+    Cudd_RecursiveDerefZdd(dd, term3);
+    N1 = cuddZddGetNode(dd, pv, R1, N0); /* pv = yi */
+    if (N1 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, N0);
+        Cudd_RecursiveDerefZdd(dd, R1);
+        return(NULL);
+    }
+    Cudd_Ref(N1);
+    Cudd_RecursiveDerefZdd(dd, R1);
+    Cudd_RecursiveDerefZdd(dd, N0);
+
+    cuddCacheInsert2(dd, cuddZddProduct, f, g, N1);
+    Cudd_Deref(N1);
+    return(N1);
+
+} /* end of cuddZddProduct */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddUnateProduct.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddUnateProduct]
+
+******************************************************************************/
+DdNode  *
+cuddZddUnateProduct(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    int         v, top_f, top_g;
+    DdNode      *term1, *term2, *term3, *term4;
+    DdNode      *sum1, *sum2;
+    DdNode      *f0, *f1, *g0, *g1;
+    DdNode      *r;
+    DdNode      *one = DD_ONE(dd);
+    DdNode      *zero = DD_ZERO(dd);
+    int         flag;
+
+    statLine(dd);
+    if (f == zero || g == zero)
+        return(zero);
+    if (f == one)
+        return(g);
+    if (g == one)
+        return(f);
+
+    top_f = dd->permZ[f->index];
+    top_g = dd->permZ[g->index];
+
+    if (top_f > top_g)
+        return(cuddZddUnateProduct(dd, g, f));
+
+    /* Check cache */
+    r = cuddCacheLookup2Zdd(dd, cuddZddUnateProduct, f, g);
+    if (r)
+        return(r);
+
+    v = f->index;       /* either yi or zi */
+    flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0);
+    if (flag == 1)
+        return(NULL);
+    Cudd_Ref(f1);
+    Cudd_Ref(f0);
+    flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0);
+    if (flag == 1) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        return(NULL);
+    }
+    Cudd_Ref(g1);
+    Cudd_Ref(g0);
+
+    term1 = cuddZddUnateProduct(dd, f1, g1);
+    if (term1 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, g0);
+        return(NULL);
+    }
+    Cudd_Ref(term1);
+    term2 = cuddZddUnateProduct(dd, f1, g0);
+    if (term2 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, g0);
+        Cudd_RecursiveDerefZdd(dd, term1);
+        return(NULL);
+    }
+    Cudd_Ref(term2);
+    term3 = cuddZddUnateProduct(dd, f0, g1);
+    if (term3 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, g0);
+        Cudd_RecursiveDerefZdd(dd, term1);
+        Cudd_RecursiveDerefZdd(dd, term2);
+        return(NULL);
+    }
+    Cudd_Ref(term3);
+    term4 = cuddZddUnateProduct(dd, f0, g0);
+    if (term4 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, g0);
+        Cudd_RecursiveDerefZdd(dd, term1);
+        Cudd_RecursiveDerefZdd(dd, term2);
+        Cudd_RecursiveDerefZdd(dd, term3);
+        return(NULL);
+    }
+    Cudd_Ref(term4);
+    Cudd_RecursiveDerefZdd(dd, f1);
+    Cudd_RecursiveDerefZdd(dd, f0);
+    Cudd_RecursiveDerefZdd(dd, g1);
+    Cudd_RecursiveDerefZdd(dd, g0);
+    sum1 = cuddZddUnion(dd, term1, term2);
+    if (sum1 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, term1);
+        Cudd_RecursiveDerefZdd(dd, term2);
+        Cudd_RecursiveDerefZdd(dd, term3);
+        Cudd_RecursiveDerefZdd(dd, term4);
+        return(NULL);
+    }
+    Cudd_Ref(sum1);
+    Cudd_RecursiveDerefZdd(dd, term1);
+    Cudd_RecursiveDerefZdd(dd, term2);
+    sum2 = cuddZddUnion(dd, sum1, term3);
+    if (sum2 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, term3);
+        Cudd_RecursiveDerefZdd(dd, term4);
+        Cudd_RecursiveDerefZdd(dd, sum1);
+        return(NULL);
+    }
+    Cudd_Ref(sum2);
+    Cudd_RecursiveDerefZdd(dd, sum1);
+    Cudd_RecursiveDerefZdd(dd, term3);
+    r = cuddZddGetNode(dd, v, sum2, term4);
+    if (r == NULL) {
+        Cudd_RecursiveDerefZdd(dd, term4);
+        Cudd_RecursiveDerefZdd(dd, sum2);
+        return(NULL);
+    }
+    Cudd_Ref(r);
+    Cudd_RecursiveDerefZdd(dd, sum2);
+    Cudd_RecursiveDerefZdd(dd, term4);
+
+    cuddCacheInsert2(dd, cuddZddUnateProduct, f, g, r);
+    Cudd_Deref(r);
+    return(r);
+
+} /* end of cuddZddUnateProduct */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddWeakDiv.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddWeakDiv]
+
+******************************************************************************/
+DdNode  *
+cuddZddWeakDiv(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    int         v;
+    DdNode      *one = DD_ONE(dd);
+    DdNode      *zero = DD_ZERO(dd);
+    DdNode      *f0, *f1, *fd, *g0, *g1, *gd;
+    DdNode      *q, *tmp;
+    DdNode      *r;
+    int         flag;
+
+    statLine(dd);
+    if (g == one)
+        return(f);
+    if (f == zero || f == one)
+        return(zero);
+    if (f == g)
+        return(one);
+
+    /* Check cache. */
+    r = cuddCacheLookup2Zdd(dd, cuddZddWeakDiv, f, g);
+    if (r)
+        return(r);
+
+    v = g->index;
+
+    flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
+    if (flag == 1)
+        return(NULL);
+    Cudd_Ref(f1);
+    Cudd_Ref(f0);
+    Cudd_Ref(fd);
+    flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
+    if (flag == 1) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        return(NULL);
+    }
+    Cudd_Ref(g1);
+    Cudd_Ref(g0);
+    Cudd_Ref(gd);
+
+    q = g;
+
+    if (g0 != zero) {
+        q = cuddZddWeakDiv(dd, f0, g0);
+        if (q == NULL) {
+            Cudd_RecursiveDerefZdd(dd, f1);
+            Cudd_RecursiveDerefZdd(dd, f0);
+            Cudd_RecursiveDerefZdd(dd, fd);
+            Cudd_RecursiveDerefZdd(dd, g1);
+            Cudd_RecursiveDerefZdd(dd, g0);
+            Cudd_RecursiveDerefZdd(dd, gd);
+            return(NULL);
+        }
+        Cudd_Ref(q);
+    }
+    else
+        Cudd_Ref(q);
+    Cudd_RecursiveDerefZdd(dd, f0);
+    Cudd_RecursiveDerefZdd(dd, g0);
+
+    if (q == zero) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, gd);
+        cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero);
+        Cudd_Deref(q);
+        return(zero);
+    }
+
+    if (g1 != zero) {
+        Cudd_RecursiveDerefZdd(dd, q);
+        tmp = cuddZddWeakDiv(dd, f1, g1);
+        if (tmp == NULL) {
+            Cudd_RecursiveDerefZdd(dd, f1);
+            Cudd_RecursiveDerefZdd(dd, g1);
+            Cudd_RecursiveDerefZdd(dd, fd);
+            Cudd_RecursiveDerefZdd(dd, gd);
+            return(NULL);
+        }
+        Cudd_Ref(tmp);
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        if (q == g)
+            q = tmp;
+        else {
+            q = cuddZddIntersect(dd, q, tmp);
+            if (q == NULL) {
+                Cudd_RecursiveDerefZdd(dd, fd);
+                Cudd_RecursiveDerefZdd(dd, gd);
+                return(NULL);
+            }
+            Cudd_Ref(q);
+            Cudd_RecursiveDerefZdd(dd, tmp);
+        }
+    }
+    else {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, g1);
+    }
+
+    if (q == zero) {
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, gd);
+        cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero);
+        Cudd_Deref(q);
+        return(zero);
+    }
+
+    if (gd != zero) {
+        Cudd_RecursiveDerefZdd(dd, q);
+        tmp = cuddZddWeakDiv(dd, fd, gd);
+        if (tmp == NULL) {
+            Cudd_RecursiveDerefZdd(dd, fd);
+            Cudd_RecursiveDerefZdd(dd, gd);
+            return(NULL);
+        }
+        Cudd_Ref(tmp);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, gd);
+        if (q == g)
+            q = tmp;
+        else {
+            q = cuddZddIntersect(dd, q, tmp);
+            if (q == NULL) {
+                Cudd_RecursiveDerefZdd(dd, tmp);
+                return(NULL);
+            }
+            Cudd_Ref(q);
+            Cudd_RecursiveDerefZdd(dd, tmp);
+        }
+    }
+    else {
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, gd);
+    }
+
+    cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, q);
+    Cudd_Deref(q);
+    return(q);
+
+} /* end of cuddZddWeakDiv */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddWeakDivF.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddWeakDivF]
+
+******************************************************************************/
+DdNode  *
+cuddZddWeakDivF(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    int         v, top_f, top_g, vf, vg;
+    DdNode      *one = DD_ONE(dd);
+    DdNode      *zero = DD_ZERO(dd);
+    DdNode      *f0, *f1, *fd, *g0, *g1, *gd;
+    DdNode      *q, *tmp;
+    DdNode      *r;
+    DdNode      *term1, *term0, *termd;
+    int         flag;
+    int         pv, nv;
+
+    statLine(dd);
+    if (g == one)
+        return(f);
+    if (f == zero || f == one)
+        return(zero);
+    if (f == g)
+        return(one);
+
+    /* Check cache. */
+    r = cuddCacheLookup2Zdd(dd, cuddZddWeakDivF, f, g);
+    if (r)
+        return(r);
+
+    top_f = dd->permZ[f->index];
+    top_g = dd->permZ[g->index];
+    vf = top_f >> 1;
+    vg = top_g >> 1;
+    v = ddMin(top_f, top_g);
+
+    if (v == top_f && vf < vg) {
+        v = f->index;
+        flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
+        if (flag == 1)
+            return(NULL);
+        Cudd_Ref(f1);
+        Cudd_Ref(f0);
+        Cudd_Ref(fd);
+
+        pv = cuddZddGetPosVarIndex(dd, v);
+        nv = cuddZddGetNegVarIndex(dd, v);
+
+        term1 = cuddZddWeakDivF(dd, f1, g);
+        if (term1 == NULL) {
+            Cudd_RecursiveDerefZdd(dd, f1);
+            Cudd_RecursiveDerefZdd(dd, f0);
+            Cudd_RecursiveDerefZdd(dd, fd);
+            return(NULL);
+        }
+        Cudd_Ref(term1);
+        Cudd_RecursiveDerefZdd(dd, f1);
+        term0 = cuddZddWeakDivF(dd, f0, g);
+        if (term0 == NULL) {
+            Cudd_RecursiveDerefZdd(dd, f0);
+            Cudd_RecursiveDerefZdd(dd, fd);
+            Cudd_RecursiveDerefZdd(dd, term1);
+            return(NULL);
+        }
+        Cudd_Ref(term0);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        termd = cuddZddWeakDivF(dd, fd, g);
+        if (termd == NULL) {
+            Cudd_RecursiveDerefZdd(dd, fd);
+            Cudd_RecursiveDerefZdd(dd, term1);
+            Cudd_RecursiveDerefZdd(dd, term0);
+            return(NULL);
+        }
+        Cudd_Ref(termd);
+        Cudd_RecursiveDerefZdd(dd, fd);
+
+        tmp = cuddZddGetNode(dd, nv, term0, termd); /* nv = zi */
+        if (tmp == NULL) {
+            Cudd_RecursiveDerefZdd(dd, term1);
+            Cudd_RecursiveDerefZdd(dd, term0);
+            Cudd_RecursiveDerefZdd(dd, termd);
+            return(NULL);
+        }
+        Cudd_Ref(tmp);
+        Cudd_RecursiveDerefZdd(dd, term0);
+        Cudd_RecursiveDerefZdd(dd, termd);
+        q = cuddZddGetNode(dd, pv, term1, tmp); /* pv = yi */
+        if (q == NULL) {
+            Cudd_RecursiveDerefZdd(dd, term1);
+            Cudd_RecursiveDerefZdd(dd, tmp);
+            return(NULL);
+        }
+        Cudd_Ref(q);
+        Cudd_RecursiveDerefZdd(dd, term1);
+        Cudd_RecursiveDerefZdd(dd, tmp);
+
+        cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q);
+        Cudd_Deref(q);
+        return(q);
+    }
+
+    if (v == top_f)
+        v = f->index;
+    else
+        v = g->index;
+
+    flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
+    if (flag == 1)
+        return(NULL);
+    Cudd_Ref(f1);
+    Cudd_Ref(f0);
+    Cudd_Ref(fd);
+    flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
+    if (flag == 1) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        return(NULL);
+    }
+    Cudd_Ref(g1);
+    Cudd_Ref(g0);
+    Cudd_Ref(gd);
+
+    q = g;
+
+    if (g0 != zero) {
+        q = cuddZddWeakDivF(dd, f0, g0);
+        if (q == NULL) {
+            Cudd_RecursiveDerefZdd(dd, f1);
+            Cudd_RecursiveDerefZdd(dd, f0);
+            Cudd_RecursiveDerefZdd(dd, fd);
+            Cudd_RecursiveDerefZdd(dd, g1);
+            Cudd_RecursiveDerefZdd(dd, g0);
+            Cudd_RecursiveDerefZdd(dd, gd);
+            return(NULL);
+        }
+        Cudd_Ref(q);
+    }
+    else
+        Cudd_Ref(q);
+    Cudd_RecursiveDerefZdd(dd, f0);
+    Cudd_RecursiveDerefZdd(dd, g0);
+
+    if (q == zero) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, gd);
+        cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero);
+        Cudd_Deref(q);
+        return(zero);
+    }
+
+    if (g1 != zero) {
+        Cudd_RecursiveDerefZdd(dd, q);
+        tmp = cuddZddWeakDivF(dd, f1, g1);
+        if (tmp == NULL) {
+            Cudd_RecursiveDerefZdd(dd, f1);
+            Cudd_RecursiveDerefZdd(dd, g1);
+            Cudd_RecursiveDerefZdd(dd, fd);
+            Cudd_RecursiveDerefZdd(dd, gd);
+            return(NULL);
+        }
+        Cudd_Ref(tmp);
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        if (q == g)
+            q = tmp;
+        else {
+            q = cuddZddIntersect(dd, q, tmp);
+            if (q == NULL) {
+                Cudd_RecursiveDerefZdd(dd, fd);
+                Cudd_RecursiveDerefZdd(dd, gd);
+                return(NULL);
+            }
+            Cudd_Ref(q);
+            Cudd_RecursiveDerefZdd(dd, tmp);
+        }
+    }
+    else {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, g1);
+    }
+
+    if (q == zero) {
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, gd);
+        cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero);
+        Cudd_Deref(q);
+        return(zero);
+    }
+
+    if (gd != zero) {
+        Cudd_RecursiveDerefZdd(dd, q);
+        tmp = cuddZddWeakDivF(dd, fd, gd);
+        if (tmp == NULL) {
+            Cudd_RecursiveDerefZdd(dd, fd);
+            Cudd_RecursiveDerefZdd(dd, gd);
+            return(NULL);
+        }
+        Cudd_Ref(tmp);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, gd);
+        if (q == g)
+            q = tmp;
+        else {
+            q = cuddZddIntersect(dd, q, tmp);
+            if (q == NULL) {
+                Cudd_RecursiveDerefZdd(dd, tmp);
+                return(NULL);
+            }
+            Cudd_Ref(q);
+            Cudd_RecursiveDerefZdd(dd, tmp);
+        }
+    }
+    else {
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDerefZdd(dd, gd);
+    }
+
+    cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q);
+    Cudd_Deref(q);
+    return(q);
+
+} /* end of cuddZddWeakDivF */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddDivide.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddDivide]
+
+******************************************************************************/
+DdNode  *
+cuddZddDivide(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    int         v;
+    DdNode      *one = DD_ONE(dd);
+    DdNode      *zero = DD_ZERO(dd);
+    DdNode      *f0, *f1, *g0, *g1;
+    DdNode      *q, *r, *tmp;
+    int         flag;
+
+    statLine(dd);
+    if (g == one)
+        return(f);
+    if (f == zero || f == one)
+        return(zero);
+    if (f == g)
+        return(one);
+
+    /* Check cache. */
+    r = cuddCacheLookup2Zdd(dd, cuddZddDivide, f, g);
+    if (r)
+        return(r);
+
+    v = g->index;
+
+    flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0);
+    if (flag == 1)
+        return(NULL);
+    Cudd_Ref(f1);
+    Cudd_Ref(f0);
+    flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0);    /* g1 != zero */
+    if (flag == 1) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        return(NULL);
+    }
+    Cudd_Ref(g1);
+    Cudd_Ref(g0);
+
+    r = cuddZddDivide(dd, f1, g1);
+    if (r == NULL) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, g0);
+        return(NULL);
+    }
+    Cudd_Ref(r);
+
+    if (r != zero && g0 != zero) {
+        tmp = r;
+        q = cuddZddDivide(dd, f0, g0);
+        if (q == NULL) {
+            Cudd_RecursiveDerefZdd(dd, f1);
+            Cudd_RecursiveDerefZdd(dd, f0);
+            Cudd_RecursiveDerefZdd(dd, g1);
+            Cudd_RecursiveDerefZdd(dd, g0);
+            return(NULL);
+        }
+        Cudd_Ref(q);
+        r = cuddZddIntersect(dd, r, q);
+        if (r == NULL) {
+            Cudd_RecursiveDerefZdd(dd, f1);
+            Cudd_RecursiveDerefZdd(dd, f0);
+            Cudd_RecursiveDerefZdd(dd, g1);
+            Cudd_RecursiveDerefZdd(dd, g0);
+            Cudd_RecursiveDerefZdd(dd, q);
+            return(NULL);
+        }
+        Cudd_Ref(r);
+        Cudd_RecursiveDerefZdd(dd, q);
+        Cudd_RecursiveDerefZdd(dd, tmp);
+    }
+
+    Cudd_RecursiveDerefZdd(dd, f1);
+    Cudd_RecursiveDerefZdd(dd, f0);
+    Cudd_RecursiveDerefZdd(dd, g1);
+    Cudd_RecursiveDerefZdd(dd, g0);
+    
+    cuddCacheInsert2(dd, cuddZddDivide, f, g, r);
+    Cudd_Deref(r);
+    return(r);
+
+} /* end of cuddZddDivide */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddDivideF.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddDivideF]
+
+******************************************************************************/
+DdNode  *
+cuddZddDivideF(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    int         v;
+    DdNode      *one = DD_ONE(dd);
+    DdNode      *zero = DD_ZERO(dd);
+    DdNode      *f0, *f1, *g0, *g1;
+    DdNode      *q, *r, *tmp;
+    int         flag;
+
+    statLine(dd);
+    if (g == one)
+        return(f);
+    if (f == zero || f == one)
+        return(zero);
+    if (f == g)
+        return(one);
+
+    /* Check cache. */
+    r = cuddCacheLookup2Zdd(dd, cuddZddDivideF, f, g);
+    if (r)
+        return(r);
+
+    v = g->index;
+
+    flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0);
+    if (flag == 1)
+        return(NULL);
+    Cudd_Ref(f1);
+    Cudd_Ref(f0);
+    flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0);    /* g1 != zero */
+    if (flag == 1) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        return(NULL);
+    }
+    Cudd_Ref(g1);
+    Cudd_Ref(g0);
+
+    r = cuddZddDivideF(dd, f1, g1);
+    if (r == NULL) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        Cudd_RecursiveDerefZdd(dd, g1);
+        Cudd_RecursiveDerefZdd(dd, g0);
+        return(NULL);
+    }
+    Cudd_Ref(r);
+
+    if (r != zero && g0 != zero) {
+        tmp = r;
+        q = cuddZddDivideF(dd, f0, g0);
+        if (q == NULL) {
+            Cudd_RecursiveDerefZdd(dd, f1);
+            Cudd_RecursiveDerefZdd(dd, f0);
+            Cudd_RecursiveDerefZdd(dd, g1);
+            Cudd_RecursiveDerefZdd(dd, g0);
+            return(NULL);
+        }
+        Cudd_Ref(q);
+        r = cuddZddIntersect(dd, r, q);
+        if (r == NULL) {
+            Cudd_RecursiveDerefZdd(dd, f1);
+            Cudd_RecursiveDerefZdd(dd, f0);
+            Cudd_RecursiveDerefZdd(dd, g1);
+            Cudd_RecursiveDerefZdd(dd, g0);
+            Cudd_RecursiveDerefZdd(dd, q);
+            return(NULL);
+        }
+        Cudd_Ref(r);
+        Cudd_RecursiveDerefZdd(dd, q);
+        Cudd_RecursiveDerefZdd(dd, tmp);
+    }
+
+    Cudd_RecursiveDerefZdd(dd, f1);
+    Cudd_RecursiveDerefZdd(dd, f0);
+    Cudd_RecursiveDerefZdd(dd, g1);
+    Cudd_RecursiveDerefZdd(dd, g0);
+    
+    cuddCacheInsert2(dd, cuddZddDivideF, f, g, r);
+    Cudd_Deref(r);
+    return(r);
+
+} /* end of cuddZddDivideF */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the three-way decomposition of f w.r.t. v.]
+
+  Description [Computes the three-way decomposition of function f (represented
+  by a ZDD) wit respect to variable v.  Returns 0 if successful; 1 otherwise.]
+
+  SideEffects [The results are returned in f1, f0, and fd.]
+
+  SeeAlso     [cuddZddGetCofactors2]
+
+******************************************************************************/
+int
+cuddZddGetCofactors3(
+  DdManager * dd,
+  DdNode * f,
+  int  v,
+  DdNode ** f1,
+  DdNode ** f0,
+  DdNode ** fd)
+{
+    DdNode      *pc, *nc;
+    DdNode      *zero = DD_ZERO(dd);
+    int         top, hv, ht, pv, nv;
+    int         level;
+
+    top = dd->permZ[f->index];
+    level = dd->permZ[v];
+    hv = level >> 1;
+    ht = top >> 1;
+
+    if (hv < ht) {
+        *f1 = zero;
+        *f0 = zero;
+        *fd = f;
+    }
+    else {
+        pv = cuddZddGetPosVarIndex(dd, v);
+        nv = cuddZddGetNegVarIndex(dd, v);
+
+        /* not to create intermediate ZDD node */
+        if (cuddZddGetPosVarLevel(dd, v) < cuddZddGetNegVarLevel(dd, v)) {
+            pc = cuddZddSubset1(dd, f, pv);
+            if (pc == NULL)
+                return(1);
+            Cudd_Ref(pc);
+            nc = cuddZddSubset0(dd, f, pv);
+            if (nc == NULL) {
+                Cudd_RecursiveDerefZdd(dd, pc);
+                return(1);
+            }
+            Cudd_Ref(nc);
+
+            *f1 = cuddZddSubset0(dd, pc, nv);
+            if (*f1 == NULL) {
+                Cudd_RecursiveDerefZdd(dd, pc);
+                Cudd_RecursiveDerefZdd(dd, nc);
+                return(1);
+            }
+            Cudd_Ref(*f1);
+            *f0 = cuddZddSubset1(dd, nc, nv);
+            if (*f0 == NULL) {
+                Cudd_RecursiveDerefZdd(dd, pc);
+                Cudd_RecursiveDerefZdd(dd, nc);
+                Cudd_RecursiveDerefZdd(dd, *f1);
+                return(1);
+            }
+            Cudd_Ref(*f0);
+
+            *fd = cuddZddSubset0(dd, nc, nv);
+            if (*fd == NULL) {
+                Cudd_RecursiveDerefZdd(dd, pc);
+                Cudd_RecursiveDerefZdd(dd, nc);
+                Cudd_RecursiveDerefZdd(dd, *f1);
+                Cudd_RecursiveDerefZdd(dd, *f0);
+                return(1);
+            }
+            Cudd_Ref(*fd);
+        } else {
+            pc = cuddZddSubset1(dd, f, nv);
+            if (pc == NULL)
+                return(1);
+            Cudd_Ref(pc);
+            nc = cuddZddSubset0(dd, f, nv);
+            if (nc == NULL) {
+                Cudd_RecursiveDerefZdd(dd, pc);
+                return(1);
+            }
+            Cudd_Ref(nc);
+
+            *f0 = cuddZddSubset0(dd, pc, pv);
+            if (*f0 == NULL) {
+                Cudd_RecursiveDerefZdd(dd, pc);
+                Cudd_RecursiveDerefZdd(dd, nc);
+                return(1);
+            }
+            Cudd_Ref(*f0);
+            *f1 = cuddZddSubset1(dd, nc, pv);
+            if (*f1 == NULL) {
+                Cudd_RecursiveDerefZdd(dd, pc);
+                Cudd_RecursiveDerefZdd(dd, nc);
+                Cudd_RecursiveDerefZdd(dd, *f0);
+                return(1);
+            }
+            Cudd_Ref(*f1);
+
+            *fd = cuddZddSubset0(dd, nc, pv);
+            if (*fd == NULL) {
+                Cudd_RecursiveDerefZdd(dd, pc);
+                Cudd_RecursiveDerefZdd(dd, nc);
+                Cudd_RecursiveDerefZdd(dd, *f1);
+                Cudd_RecursiveDerefZdd(dd, *f0);
+                return(1);
+            }
+            Cudd_Ref(*fd);
+        }
+
+        Cudd_RecursiveDerefZdd(dd, pc);
+        Cudd_RecursiveDerefZdd(dd, nc);
+        Cudd_Deref(*f1);
+        Cudd_Deref(*f0);
+        Cudd_Deref(*fd);
+    }
+    return(0);
+
+} /* end of cuddZddGetCofactors3 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the two-way decomposition of f w.r.t. v.]
+
+  Description []
+
+  SideEffects [The results are returned in f1 and f0.]
+
+  SeeAlso     [cuddZddGetCofactors3]
+
+******************************************************************************/
+int
+cuddZddGetCofactors2(
+  DdManager * dd,
+  DdNode * f,
+  int  v,
+  DdNode ** f1,
+  DdNode ** f0)
+{
+    *f1 = cuddZddSubset1(dd, f, v);
+    if (*f1 == NULL)
+        return(1);
+    *f0 = cuddZddSubset0(dd, f, v);
+    if (*f0 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, *f1);
+        return(1);
+    }
+    return(0);
+
+} /* end of cuddZddGetCofactors2 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a complement of a ZDD node.]
+
+  Description [Computes the complement of a ZDD node. So far, since we
+  couldn't find a direct way to get the complement of a ZDD cover, we first
+  convert a ZDD cover to a BDD, then make the complement of the ZDD cover
+  from the complement of the BDD node by using ISOP.]
+
+  SideEffects [The result depends on current variable order.]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode  *
+cuddZddComplement(
+  DdManager * dd,
+  DdNode *node)
+{
+    DdNode      *b, *isop, *zdd_I;
+
+    /* Check cache */
+    zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node);
+    if (zdd_I)
+        return(zdd_I);
+
+    b = cuddMakeBddFromZddCover(dd, node);
+    if (!b)
+        return(NULL);
+    cuddRef(b);
+    isop = cuddZddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I);
+    if (!isop) {
+        Cudd_RecursiveDeref(dd, b);
+        return(NULL);
+    }
+    cuddRef(isop);
+    cuddRef(zdd_I);
+    Cudd_RecursiveDeref(dd, b);
+    Cudd_RecursiveDeref(dd, isop);
+
+    cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I);
+    cuddDeref(zdd_I);
+    return(zdd_I);
+} /* end of cuddZddComplement */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of positive ZDD variable.]
+
+  Description [Returns the index of positive ZDD variable.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddGetPosVarIndex(
+  DdManager * dd,
+  int index)
+{
+    int pv = (index >> 1) << 1;
+    return(pv);
+} /* end of cuddZddGetPosVarIndex */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of negative ZDD variable.]
+
+  Description [Returns the index of negative ZDD variable.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddGetNegVarIndex(
+  DdManager * dd,
+  int index)
+{
+    int nv = index | 0x1;
+    return(nv);
+} /* end of cuddZddGetPosVarIndex */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the level of positive ZDD variable.]
+
+  Description [Returns the level of positive ZDD variable.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddGetPosVarLevel(
+  DdManager * dd,
+  int index)
+{
+    int pv = cuddZddGetPosVarIndex(dd, index);
+    return(dd->permZ[pv]);
+} /* end of cuddZddGetPosVarLevel */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the level of negative ZDD variable.]
+
+  Description [Returns the level of negative ZDD variable.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddGetNegVarLevel(
+  DdManager * dd,
+  int index)
+{
+    int nv = cuddZddGetNegVarIndex(dd, index);
+    return(dd->permZ[nv]);
+} /* end of cuddZddGetNegVarLevel */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddZddGroup.c b/abc-build/src/bdd/cudd/cuddZddGroup.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddZddGroup.c
@@ -0,0 +1,1344 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddGroup.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for ZDD group sifting.]
+
+  Description [External procedures included in this file:
+                <ul>
+                <li> Cudd_MakeZddTreeNode()
+                </ul>
+        Internal procedures included in this file:
+                <ul>
+                <li> cuddZddTreeSifting()
+                </ul>
+        Static procedures included in this module:
+                <ul>
+                <li> zddTreeSiftingAux()
+                <li> zddCountInternalMtrNodes()
+                <li> zddReorderChildren()
+                <li> zddFindNodeHiLo()
+                <li> zddUniqueCompareGroup()
+                <li> zddGroupSifting()
+                <li> zddGroupSiftingAux()
+                <li> zddGroupSiftingUp()
+                <li> zddGroupSiftingDown()
+                <li> zddGroupMove()
+                <li> zddGroupMoveBackward()
+                <li> zddGroupSiftingBackward()
+                <li> zddMergeGroups()
+                </ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddGroup.c,v 1.20 2009/02/19 16:25:36 fabio Exp $";
+#endif
+
+static  int     *entry;
+extern  int     zddTotalNumberSwapping;
+#ifdef DD_STATS
+static  int     extsymmcalls;
+static  int     extsymm;
+static  int     secdiffcalls;
+static  int     secdiff;
+static  int     secdiffmisfire;
+#endif
+#ifdef DD_DEBUG
+static  int     pr = 0; /* flag to enable printing while debugging */
+                        /* by depositing a 1 into it */
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int zddTreeSiftingAux (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
+#ifdef DD_STATS
+static int zddCountInternalMtrNodes (DdManager *table, MtrNode *treenode);
+#endif
+static int zddReorderChildren (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
+static void zddFindNodeHiLo (DdManager *table, MtrNode *treenode, int *lower, int *upper);
+static int zddUniqueCompareGroup (int *ptrX, int *ptrY);
+static int zddGroupSifting (DdManager *table, int lower, int upper);
+static int zddGroupSiftingAux (DdManager *table, int x, int xLow, int xHigh);
+static int zddGroupSiftingUp (DdManager *table, int y, int xLow, Move **moves);
+static int zddGroupSiftingDown (DdManager *table, int x, int xHigh, Move **moves);
+static int zddGroupMove (DdManager *table, int x, int y, Move **moves);
+static int zddGroupMoveBackward (DdManager *table, int x, int y);
+static int zddGroupSiftingBackward (DdManager *table, Move *moves, int size);
+static void zddMergeGroups (DdManager *table, MtrNode *treenode, int low, int high);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a new ZDD variable group.]
+
+  Description [Creates a new ZDD variable group. The group starts at
+  variable and contains size variables. The parameter low is the index
+  of the first variable. If the variable already exists, its current
+  position in the order is known to the manager. If the variable does
+  not exist yet, the position is assumed to be the same as the index.
+  The group tree is created if it does not exist yet.
+  Returns a pointer to the group if successful; NULL otherwise.]
+
+  SideEffects [The ZDD variable tree is changed.]
+
+  SeeAlso     [Cudd_MakeTreeNode]
+
+******************************************************************************/
+MtrNode *
+Cudd_MakeZddTreeNode(
+  DdManager * dd /* manager */,
+  unsigned int  low /* index of the first group variable */,
+  unsigned int  size /* number of variables in the group */,
+  unsigned int  type /* MTR_DEFAULT or MTR_FIXED */)
+{
+    MtrNode *group;
+    MtrNode *tree;
+    unsigned int level;
+
+    /* If the variable does not exist yet, the position is assumed to be
+    ** the same as the index. Therefore, applications that rely on
+    ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new
+    ** variables have to create the variables before they group them.
+    */
+    level = (low < (unsigned int) dd->sizeZ) ? dd->permZ[low] : low;
+
+    if (level + size - 1> (int) MTR_MAXHIGH)
+        return(NULL);
+
+    /* If the tree does not exist yet, create it. */
+    tree = dd->treeZ;
+    if (tree == NULL) {
+        dd->treeZ = tree = Mtr_InitGroupTree(0, dd->sizeZ);
+        if (tree == NULL)
+            return(NULL);
+        tree->index = dd->invpermZ[0];
+    }
+
+    /* Extend the upper bound of the tree if necessary. This allows the
+    ** application to create groups even before the variables are created.
+    */
+    tree->size = ddMax(tree->size, level + size);
+
+    /* Create the group. */
+    group = Mtr_MakeGroup(tree, level, size, type);
+    if (group == NULL)
+        return(NULL);
+
+    /* Initialize the index field to the index of the variable currently
+    ** in position low. This field will be updated by the reordering
+    ** procedure to provide a handle to the group once it has been moved.
+    */
+    group->index = (MtrHalfWord) low;
+
+    return(group);
+
+} /* end of Cudd_MakeZddTreeNode */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tree sifting algorithm for ZDDs.]
+
+  Description [Tree sifting algorithm for ZDDs. Assumes that a tree
+  representing a group hierarchy is passed as a parameter. It then
+  reorders each group in postorder fashion by calling
+  zddTreeSiftingAux.  Assumes that no dead nodes are present.  Returns
+  1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+cuddZddTreeSifting(
+  DdManager * table /* DD table */,
+  Cudd_ReorderingType method /* reordering method for the groups of leaves */)
+{
+    int i;
+    int nvars;
+    int result;
+    int tempTree;
+
+    /* If no tree is provided we create a temporary one in which all
+    ** variables are in a single group. After reordering this tree is
+    ** destroyed.
+    */
+    tempTree = table->treeZ == NULL;
+    if (tempTree) {
+        table->treeZ = Mtr_InitGroupTree(0,table->sizeZ);
+        table->treeZ->index = table->invpermZ[0];
+    }
+    nvars = table->sizeZ;
+
+#ifdef DD_DEBUG
+    if (pr > 0 && !tempTree)
+        (void) fprintf(table->out,"cuddZddTreeSifting:");
+    Mtr_PrintGroups(table->treeZ,pr <= 0);
+#endif
+#if 0
+    /* Debugging code. */
+    if (table->tree && table->treeZ) {
+        (void) fprintf(table->out,"\n");
+        Mtr_PrintGroups(table->tree, 0);
+        cuddPrintVarGroups(table,table->tree,0,0);
+        for (i = 0; i < table->size; i++) {
+            (void) fprintf(table->out,"%s%d",
+                           (i == 0) ? "" : ",", table->invperm[i]);
+        }
+        (void) fprintf(table->out,"\n");
+        for (i = 0; i < table->size; i++) {
+            (void) fprintf(table->out,"%s%d",
+                           (i == 0) ? "" : ",", table->perm[i]);
+        }
+        (void) fprintf(table->out,"\n\n");
+        Mtr_PrintGroups(table->treeZ,0);
+        cuddPrintVarGroups(table,table->treeZ,1,0);
+        for (i = 0; i < table->sizeZ; i++) {
+            (void) fprintf(table->out,"%s%d",
+                           (i == 0) ? "" : ",", table->invpermZ[i]);
+        }
+        (void) fprintf(table->out,"\n");
+        for (i = 0; i < table->sizeZ; i++) {
+            (void) fprintf(table->out,"%s%d",
+                           (i == 0) ? "" : ",", table->permZ[i]);
+        }
+        (void) fprintf(table->out,"\n");
+    }
+    /* End of debugging code. */
+#endif
+#ifdef DD_STATS
+    extsymmcalls = 0;
+    extsymm = 0;
+    secdiffcalls = 0;
+    secdiff = 0;
+    secdiffmisfire = 0;
+
+    (void) fprintf(table->out,"\n");
+    if (!tempTree)
+        (void) fprintf(table->out,"#:IM_NODES  %8d: group tree nodes\n",
+                       zddCountInternalMtrNodes(table,table->treeZ));
+#endif
+
+    /* Initialize the group of each subtable to itself. Initially
+    ** there are no groups. Groups are created according to the tree
+    ** structure in postorder fashion.
+    */
+    for (i = 0; i < nvars; i++)
+        table->subtableZ[i].next = i;
+
+    /* Reorder. */
+    result = zddTreeSiftingAux(table, table->treeZ, method);
+
+#ifdef DD_STATS         /* print stats */
+    if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
+        (table->groupcheck == CUDD_GROUP_CHECK7 ||
+         table->groupcheck == CUDD_GROUP_CHECK5)) {
+        (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls);
+        (void) fprintf(table->out,"extsymm = %d",extsymm);
+    }
+    if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
+        table->groupcheck == CUDD_GROUP_CHECK7) {
+        (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls);
+        (void) fprintf(table->out,"secdiff = %d\n",secdiff);
+        (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire);
+    }
+#endif
+
+    if (tempTree)
+        Cudd_FreeZddTree(table);
+    return(result);
+
+} /* end of cuddZddTreeSifting */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Visits the group tree and reorders each group.]
+
+  Description [Recursively visits the group tree and reorders each
+  group in postorder fashion.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddTreeSiftingAux(
+  DdManager * table,
+  MtrNode * treenode,
+  Cudd_ReorderingType method)
+{
+    MtrNode  *auxnode;
+    int res;
+
+#ifdef DD_DEBUG
+    Mtr_PrintGroups(treenode,1);
+#endif
+
+    auxnode = treenode;
+    while (auxnode != NULL) {
+        if (auxnode->child != NULL) {
+            if (!zddTreeSiftingAux(table, auxnode->child, method))
+                return(0);
+            res = zddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT);
+            if (res == 0)
+                return(0);
+        } else if (auxnode->size > 1) {
+            if (!zddReorderChildren(table, auxnode, method))
+                return(0);
+        }
+        auxnode = auxnode->younger;
+    }
+
+    return(1);
+
+} /* end of zddTreeSiftingAux */
+
+
+#ifdef DD_STATS
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of internal nodes of the group tree.]
+
+  Description [Counts the number of internal nodes of the group tree.
+  Returns the count.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddCountInternalMtrNodes(
+  DdManager * table,
+  MtrNode * treenode)
+{
+    MtrNode *auxnode;
+    int     count,nodeCount;
+
+
+    nodeCount = 0;
+    auxnode = treenode;
+    while (auxnode != NULL) {
+        if (!(MTR_TEST(auxnode,MTR_TERMINAL))) {
+            nodeCount++;
+            count = zddCountInternalMtrNodes(table,auxnode->child);
+            nodeCount += count;
+        }
+        auxnode = auxnode->younger;
+    }
+
+    return(nodeCount);
+
+} /* end of zddCountInternalMtrNodes */
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders the children of a group tree node according to
+  the options.]
+
+  Description [Reorders the children of a group tree node according to
+  the options. After reordering puts all the variables in the group
+  and/or its descendents in a single group. This allows hierarchical
+  reordering.  If the variables in the group do not exist yet, simply
+  does nothing. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddReorderChildren(
+  DdManager * table,
+  MtrNode * treenode,
+  Cudd_ReorderingType method)
+{
+    int lower;
+    int upper = -1;
+    int result;
+    unsigned int initialSize;
+
+    zddFindNodeHiLo(table,treenode,&lower,&upper);
+    /* If upper == -1 these variables do not exist yet. */
+    if (upper == -1)
+        return(1);
+
+    if (treenode->flags == MTR_FIXED) {
+        result = 1;
+    } else {
+#ifdef DD_STATS
+        (void) fprintf(table->out," ");
+#endif
+        switch (method) {
+        case CUDD_REORDER_RANDOM:
+        case CUDD_REORDER_RANDOM_PIVOT:
+            result = cuddZddSwapping(table,lower,upper,method);
+            break;
+        case CUDD_REORDER_SIFT:
+            result = cuddZddSifting(table,lower,upper);
+            break;
+        case CUDD_REORDER_SIFT_CONVERGE:
+            do {
+                initialSize = table->keysZ;
+                result = cuddZddSifting(table,lower,upper);
+                if (initialSize <= table->keysZ)
+                    break;
+#ifdef DD_STATS
+                else
+                    (void) fprintf(table->out,"\n");
+#endif
+            } while (result != 0);
+            break;
+        case CUDD_REORDER_SYMM_SIFT:
+            result = cuddZddSymmSifting(table,lower,upper);
+            break;
+        case CUDD_REORDER_SYMM_SIFT_CONV:
+            result = cuddZddSymmSiftingConv(table,lower,upper);
+            break;
+        case CUDD_REORDER_GROUP_SIFT:
+            result = zddGroupSifting(table,lower,upper);
+            break;
+        case CUDD_REORDER_LINEAR:
+            result = cuddZddLinearSifting(table,lower,upper);
+            break;
+        case CUDD_REORDER_LINEAR_CONVERGE:
+            do {
+                initialSize = table->keysZ;
+                result = cuddZddLinearSifting(table,lower,upper);
+                if (initialSize <= table->keysZ)
+                    break;
+#ifdef DD_STATS
+                else
+                    (void) fprintf(table->out,"\n");
+#endif
+            } while (result != 0);
+            break;
+        default:
+            return(0);
+        }
+    }
+
+    /* Create a single group for all the variables that were sifted,
+    ** so that they will be treated as a single block by successive
+    ** invocations of zddGroupSifting.
+    */
+    zddMergeGroups(table,treenode,lower,upper);
+
+#ifdef DD_DEBUG
+    if (pr > 0) (void) fprintf(table->out,"zddReorderChildren:");
+#endif
+
+    return(result);
+
+} /* end of zddReorderChildren */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the lower and upper bounds of the group represented
+  by treenode.]
+
+  Description [Finds the lower and upper bounds of the group represented
+  by treenode.  The high and low fields of treenode are indices.  From
+  those we need to derive the current positions, and find maximum and
+  minimum.]
+
+  SideEffects [The bounds are returned as side effects.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+zddFindNodeHiLo(
+  DdManager * table,
+  MtrNode * treenode,
+  int * lower,
+  int * upper)
+{
+    int low;
+    int high;
+
+    /* Check whether no variables in this group already exist.
+    ** If so, return immediately. The calling procedure will know from
+    ** the values of upper that no reordering is needed.
+    */
+    if ((int) treenode->low >= table->sizeZ) {
+        *lower = table->sizeZ;
+        *upper = -1;
+        return;
+    }
+
+    *lower = low = (unsigned int) table->permZ[treenode->index];
+    high = (int) (low + treenode->size - 1);
+
+    if (high >= table->sizeZ) {
+        /* This is the case of a partially existing group. The aim is to
+        ** reorder as many variables as safely possible.  If the tree
+        ** node is terminal, we just reorder the subset of the group
+        ** that is currently in existence.  If the group has
+        ** subgroups, then we only reorder those subgroups that are
+        ** fully instantiated.  This way we avoid breaking up a group.
+        */
+        MtrNode *auxnode = treenode->child;
+        if (auxnode == NULL) {
+            *upper = (unsigned int) table->sizeZ - 1;
+        } else {
+            /* Search the subgroup that strands the table->sizeZ line.
+            ** If the first group starts at 0 and goes past table->sizeZ
+            ** upper will get -1, thus correctly signaling that no reordering
+            ** should take place.
+            */
+            while (auxnode != NULL) {
+                int thisLower = table->permZ[auxnode->low];
+                int thisUpper = thisLower + auxnode->size - 1;
+                if (thisUpper >= table->sizeZ && thisLower < table->sizeZ)
+                    *upper = (unsigned int) thisLower - 1;
+                auxnode = auxnode->younger;
+            }
+        }
+    } else {
+        /* Normal case: All the variables of the group exist. */
+        *upper = (unsigned int) high;
+    }
+
+#ifdef DD_DEBUG
+    /* Make sure that all variables in group are contiguous. */
+    assert(treenode->size >= *upper - *lower + 1);
+#endif
+
+    return;
+
+} /* end of zddFindNodeHiLo */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison function used by qsort.]
+
+  Description [Comparison function used by qsort to order the variables
+  according to the number of keys in the subtables.  Returns the
+  difference in number of keys between the two variables being
+  compared.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddUniqueCompareGroup(
+  int * ptrX,
+  int * ptrY)
+{
+#if 0
+    if (entry[*ptrY] == entry[*ptrX]) {
+        return((*ptrX) - (*ptrY));
+    }
+#endif
+    return(entry[*ptrY] - entry[*ptrX]);
+
+} /* end of zddUniqueCompareGroup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts from treenode->low to treenode->high.]
+
+  Description [Sifts from treenode->low to treenode->high. If
+  croupcheck == CUDD_GROUP_CHECK7, it checks for group creation at the
+  end of the initial sifting. If a group is created, it is then sifted
+  again. After sifting one variable, the group that contains it is
+  dissolved.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddGroupSifting(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int         *var;
+    int         i,j,x,xInit;
+    int         nvars;
+    int         classes;
+    int         result;
+    int         *sifted;
+#ifdef DD_STATS
+    unsigned    previousSize;
+#endif
+    int         xindex;
+
+    nvars = table->sizeZ;
+
+    /* Order variables to sift. */
+    entry = NULL;
+    sifted = NULL;
+    var = ABC_ALLOC(int,nvars);
+    if (var == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto zddGroupSiftingOutOfMem;
+    }
+    entry = ABC_ALLOC(int,nvars);
+    if (entry == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto zddGroupSiftingOutOfMem;
+    }
+    sifted = ABC_ALLOC(int,nvars);
+    if (sifted == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto zddGroupSiftingOutOfMem;
+    }
+
+    /* Here we consider only one representative for each group. */
+    for (i = 0, classes = 0; i < nvars; i++) {
+        sifted[i] = 0;
+        x = table->permZ[i];
+        if ((unsigned) x >= table->subtableZ[x].next) {
+            entry[i] = table->subtableZ[x].keys;
+            var[classes] = i;
+            classes++;
+        }
+    }
+
+    qsort((void *)var,classes,sizeof(int),(DD_QSFP)zddUniqueCompareGroup);
+
+    /* Now sift. */
+    for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
+        if (zddTotalNumberSwapping >= table->siftMaxSwap)
+            break;
+        xindex = var[i];
+        if (sifted[xindex] == 1) /* variable already sifted as part of group */
+            continue;
+        x = table->permZ[xindex]; /* find current level of this variable */
+        if (x < lower || x > upper)
+            continue;
+#ifdef DD_STATS
+        previousSize = table->keysZ;
+#endif
+#ifdef DD_DEBUG
+        /* x is bottom of group */
+        assert((unsigned) x >= table->subtableZ[x].next);
+#endif
+        result = zddGroupSiftingAux(table,x,lower,upper);
+        if (!result) goto zddGroupSiftingOutOfMem;
+
+#ifdef DD_STATS
+        if (table->keysZ < previousSize) {
+            (void) fprintf(table->out,"-");
+        } else if (table->keysZ > previousSize) {
+            (void) fprintf(table->out,"+");
+        } else {
+            (void) fprintf(table->out,"=");
+        }
+        fflush(table->out);
+#endif
+
+        /* Mark variables in the group just sifted. */
+        x = table->permZ[xindex];
+        if ((unsigned) x != table->subtableZ[x].next) {
+            xInit = x;
+            do {
+                j = table->invpermZ[x];
+                sifted[j] = 1;
+                x = table->subtableZ[x].next;
+            } while (x != xInit);
+        }
+
+#ifdef DD_DEBUG
+        if (pr > 0) (void) fprintf(table->out,"zddGroupSifting:");
+#endif
+    } /* for */
+
+    ABC_FREE(sifted);
+    ABC_FREE(var);
+    ABC_FREE(entry);
+
+    return(1);
+
+zddGroupSiftingOutOfMem:
+    if (entry != NULL)  ABC_FREE(entry);
+    if (var != NULL)    ABC_FREE(var);
+    if (sifted != NULL) ABC_FREE(sifted);
+
+    return(0);
+
+} /* end of zddGroupSifting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts one variable up and down until it has taken all
+  positions. Checks for aggregation.]
+
+  Description [Sifts one variable up and down until it has taken all
+  positions. Checks for aggregation. There may be at most two sweeps,
+  even if the group grows.  Assumes that x is either an isolated
+  variable, or it is the bottom of a group. All groups may not have
+  been found. The variable being moved is returned to the best position
+  seen during sifting.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddGroupSiftingAux(
+  DdManager * table,
+  int  x,
+  int  xLow,
+  int  xHigh)
+{
+    Move *move;
+    Move *moves;        /* list of moves */
+    int  initialSize;
+    int  result;
+
+
+#ifdef DD_DEBUG
+    if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingAux from %d to %d\n",xLow,xHigh);
+    assert((unsigned) x >= table->subtableZ[x].next); /* x is bottom of group */
+#endif
+
+    initialSize = table->keysZ;
+    moves = NULL;
+
+    if (x == xLow) { /* Sift down */
+#ifdef DD_DEBUG
+        /* x must be a singleton */
+        assert((unsigned) x == table->subtableZ[x].next);
+#endif
+        if (x == xHigh) return(1);      /* just one variable */
+
+        if (!zddGroupSiftingDown(table,x,xHigh,&moves))
+            goto zddGroupSiftingAuxOutOfMem;
+        /* at this point x == xHigh, unless early term */
+
+        /* move backward and stop at best position */
+        result = zddGroupSiftingBackward(table,moves,initialSize);
+#ifdef DD_DEBUG
+        assert(table->keysZ <= (unsigned) initialSize);
+#endif
+        if (!result) goto zddGroupSiftingAuxOutOfMem;
+
+    } else if (cuddZddNextHigh(table,x) > xHigh) { /* Sift up */
+#ifdef DD_DEBUG
+        /* x is bottom of group */
+        assert((unsigned) x >= table->subtableZ[x].next);
+#endif
+        /* Find top of x's group */
+        x = table->subtableZ[x].next;
+
+        if (!zddGroupSiftingUp(table,x,xLow,&moves))
+            goto zddGroupSiftingAuxOutOfMem;
+        /* at this point x == xLow, unless early term */
+
+        /* move backward and stop at best position */
+        result = zddGroupSiftingBackward(table,moves,initialSize);
+#ifdef DD_DEBUG
+        assert(table->keysZ <= (unsigned) initialSize);
+#endif
+        if (!result) goto zddGroupSiftingAuxOutOfMem;
+
+    } else if (x - xLow > xHigh - x) { /* must go down first: shorter */
+        if (!zddGroupSiftingDown(table,x,xHigh,&moves))
+            goto zddGroupSiftingAuxOutOfMem;
+        /* at this point x == xHigh, unless early term */
+
+        /* Find top of group */
+        if (moves) {
+            x = moves->y;
+        }
+        while ((unsigned) x < table->subtableZ[x].next)
+            x = table->subtableZ[x].next;
+        x = table->subtableZ[x].next;
+#ifdef DD_DEBUG
+        /* x should be the top of a group */
+        assert((unsigned) x <= table->subtableZ[x].next);
+#endif
+
+        if (!zddGroupSiftingUp(table,x,xLow,&moves))
+            goto zddGroupSiftingAuxOutOfMem;
+
+        /* move backward and stop at best position */
+        result = zddGroupSiftingBackward(table,moves,initialSize);
+#ifdef DD_DEBUG
+        assert(table->keysZ <= (unsigned) initialSize);
+#endif
+        if (!result) goto zddGroupSiftingAuxOutOfMem;
+
+    } else { /* moving up first: shorter */
+        /* Find top of x's group */
+        x = table->subtableZ[x].next;
+
+        if (!zddGroupSiftingUp(table,x,xLow,&moves))
+            goto zddGroupSiftingAuxOutOfMem;
+        /* at this point x == xHigh, unless early term */
+
+        if (moves) {
+            x = moves->x;
+        }
+        while ((unsigned) x < table->subtableZ[x].next)
+            x = table->subtableZ[x].next;
+#ifdef DD_DEBUG
+        /* x is bottom of a group */
+        assert((unsigned) x >= table->subtableZ[x].next);
+#endif
+
+        if (!zddGroupSiftingDown(table,x,xHigh,&moves))
+            goto zddGroupSiftingAuxOutOfMem;
+
+        /* move backward and stop at best position */
+        result = zddGroupSiftingBackward(table,moves,initialSize);
+#ifdef DD_DEBUG
+        assert(table->keysZ <= (unsigned) initialSize);
+#endif
+        if (!result) goto zddGroupSiftingAuxOutOfMem;
+    }
+
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+
+    return(1);
+
+zddGroupSiftingAuxOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+
+    return(0);
+
+} /* end of zddGroupSiftingAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts up a variable until either it reaches position xLow
+  or the size of the DD heap increases too much.]
+
+  Description [Sifts up a variable until either it reaches position
+  xLow or the size of the DD heap increases too much. Assumes that y is
+  the top of a group (or a singleton).  Checks y for aggregation to the
+  adjacent variables. Records all the moves that are appended to the
+  list of moves received as input and returned as a side effect.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddGroupSiftingUp(
+  DdManager * table,
+  int  y,
+  int  xLow,
+  Move ** moves)
+{
+    Move *move;
+    int  x;
+    int  size;
+    int  gxtop;
+    int  limitSize;
+
+    limitSize = table->keysZ;
+
+    x = cuddZddNextLow(table,y);
+    while (x >= xLow) {
+        gxtop = table->subtableZ[x].next;
+        if (table->subtableZ[x].next == (unsigned) x &&
+            table->subtableZ[y].next == (unsigned) y) {
+            /* x and y are self groups */
+            size = cuddZddSwapInPlace(table,x,y);
+#ifdef DD_DEBUG
+            assert(table->subtableZ[x].next == (unsigned) x);
+            assert(table->subtableZ[y].next == (unsigned) y);
+#endif
+            if (size == 0) goto zddGroupSiftingUpOutOfMem;
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL) goto zddGroupSiftingUpOutOfMem;
+            move->x = x;
+            move->y = y;
+            move->flags = MTR_DEFAULT;
+            move->size = size;
+            move->next = *moves;
+            *moves = move;
+
+#ifdef DD_DEBUG
+            if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingUp (2 single groups):\n");
+#endif
+            if ((double) size > (double) limitSize * table->maxGrowth)
+                return(1);
+            if (size < limitSize) limitSize = size;
+        } else { /* group move */
+            size = zddGroupMove(table,x,y,moves);
+            if (size == 0) goto zddGroupSiftingUpOutOfMem;
+            if ((double) size > (double) limitSize * table->maxGrowth)
+                return(1);
+            if (size < limitSize) limitSize = size;
+        }
+        y = gxtop;
+        x = cuddZddNextLow(table,y);
+    }
+
+    return(1);
+
+zddGroupSiftingUpOutOfMem:
+    while (*moves != NULL) {
+        move = (*moves)->next;
+        cuddDeallocMove(table, *moves);
+        *moves = move;
+    }
+    return(0);
+
+} /* end of zddGroupSiftingUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts down a variable until it reaches position xHigh.]
+
+  Description [Sifts down a variable until it reaches position xHigh.
+  Assumes that x is the bottom of a group (or a singleton).  Records
+  all the moves.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddGroupSiftingDown(
+  DdManager * table,
+  int  x,
+  int  xHigh,
+  Move ** moves)
+{
+    Move *move;
+    int  y;
+    int  size;
+    int  limitSize;
+    int  gybot;
+
+
+    /* Initialize R */
+    limitSize = size = table->keysZ;
+    y = cuddZddNextHigh(table,x);
+    while (y <= xHigh) {
+        /* Find bottom of y group. */
+        gybot = table->subtableZ[y].next;
+        while (table->subtableZ[gybot].next != (unsigned) y)
+            gybot = table->subtableZ[gybot].next;
+
+        if (table->subtableZ[x].next == (unsigned) x &&
+            table->subtableZ[y].next == (unsigned) y) {
+            /* x and y are self groups */
+            size = cuddZddSwapInPlace(table,x,y);
+#ifdef DD_DEBUG
+            assert(table->subtableZ[x].next == (unsigned) x);
+            assert(table->subtableZ[y].next == (unsigned) y);
+#endif
+            if (size == 0) goto zddGroupSiftingDownOutOfMem;
+
+            /* Record move. */
+            move = (Move *) cuddDynamicAllocNode(table);
+            if (move == NULL) goto zddGroupSiftingDownOutOfMem;
+            move->x = x;
+            move->y = y;
+            move->flags = MTR_DEFAULT;
+            move->size = size;
+            move->next = *moves;
+            *moves = move;
+
+#ifdef DD_DEBUG
+            if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingDown (2 single groups):\n");
+#endif
+            if ((double) size > (double) limitSize * table->maxGrowth)
+                return(1);
+            if (size < limitSize) limitSize = size;
+            x = y;
+            y = cuddZddNextHigh(table,x);
+        } else { /* Group move */
+            size = zddGroupMove(table,x,y,moves);
+            if (size == 0) goto zddGroupSiftingDownOutOfMem;
+            if ((double) size > (double) limitSize * table->maxGrowth)
+                return(1);
+            if (size < limitSize) limitSize = size;
+        }
+        x = gybot;
+        y = cuddZddNextHigh(table,x);
+    }
+
+    return(1);
+
+zddGroupSiftingDownOutOfMem:
+    while (*moves != NULL) {
+        move = (*moves)->next;
+        cuddDeallocMove(table, *moves);
+        *moves = move;
+    }
+
+    return(0);
+
+} /* end of zddGroupSiftingDown */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Swaps two groups and records the move.]
+
+  Description [Swaps two groups and records the move. Returns the
+  number of keys in the DD table in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddGroupMove(
+  DdManager * table,
+  int  x,
+  int  y,
+  Move ** moves)
+{
+    Move *move;
+    int  size;
+    int  i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
+    int  swapx=-1,swapy=-1;
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    int  initialSize,bestSize;
+#endif
+
+#ifdef DD_DEBUG
+    /* We assume that x < y */
+    assert(x < y);
+#endif
+    /* Find top, bottom, and size for the two groups. */
+    xbot = x;
+    xtop = table->subtableZ[x].next;
+    xsize = xbot - xtop + 1;
+    ybot = y;
+    while ((unsigned) ybot < table->subtableZ[ybot].next)
+        ybot = table->subtableZ[ybot].next;
+    ytop = y;
+    ysize = ybot - ytop + 1;
+
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    initialSize = bestSize = table->keysZ;
+#endif
+    /* Sift the variables of the second group up through the first group */
+    for (i = 1; i <= ysize; i++) {
+        for (j = 1; j <= xsize; j++) {
+            size = cuddZddSwapInPlace(table,x,y);
+            if (size == 0) goto zddGroupMoveOutOfMem;
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+            if (size < bestSize)
+                bestSize = size;
+#endif
+            swapx = x; swapy = y;
+            y = x;
+            x = cuddZddNextLow(table,y);
+        }
+        y = ytop + i;
+        x = cuddZddNextLow(table,y);
+    }
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    if ((bestSize < initialSize) && (bestSize < size))
+        (void) fprintf(table->out,"Missed local minimum: initialSize:%d  bestSize:%d  finalSize:%d\n",initialSize,bestSize,size);
+#endif
+
+    /* fix groups */
+    y = xtop; /* ytop is now where xtop used to be */
+    for (i = 0; i < ysize - 1; i++) {
+        table->subtableZ[y].next = cuddZddNextHigh(table,y);
+        y = cuddZddNextHigh(table,y);
+    }
+    table->subtableZ[y].next = xtop; /* y is bottom of its group, join */
+                                    /* it to top of its group */
+    x = cuddZddNextHigh(table,y);
+    newxtop = x;
+    for (i = 0; i < xsize - 1; i++) {
+        table->subtableZ[x].next = cuddZddNextHigh(table,x);
+        x = cuddZddNextHigh(table,x);
+    }
+    table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */
+                                    /* it to top of its group */
+#ifdef DD_DEBUG
+    if (pr > 0) (void) fprintf(table->out,"zddGroupMove:\n");
+#endif
+
+    /* Store group move */
+    move = (Move *) cuddDynamicAllocNode(table);
+    if (move == NULL) goto zddGroupMoveOutOfMem;
+    move->x = swapx;
+    move->y = swapy;
+    move->flags = MTR_DEFAULT;
+    move->size = table->keysZ;
+    move->next = *moves;
+    *moves = move;
+
+    return(table->keysZ);
+
+zddGroupMoveOutOfMem:
+    while (*moves != NULL) {
+        move = (*moves)->next;
+        cuddDeallocMove(table, *moves);
+        *moves = move;
+    }
+    return(0);
+
+} /* end of zddGroupMove */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Undoes the swap two groups.]
+
+  Description [Undoes the swap two groups.  Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddGroupMoveBackward(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int size;
+    int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
+
+
+#ifdef DD_DEBUG
+    /* We assume that x < y */
+    assert(x < y);
+#endif
+
+    /* Find top, bottom, and size for the two groups. */
+    xbot = x;
+    xtop = table->subtableZ[x].next;
+    xsize = xbot - xtop + 1;
+    ybot = y;
+    while ((unsigned) ybot < table->subtableZ[ybot].next)
+        ybot = table->subtableZ[ybot].next;
+    ytop = y;
+    ysize = ybot - ytop + 1;
+
+    /* Sift the variables of the second group up through the first group */
+    for (i = 1; i <= ysize; i++) {
+        for (j = 1; j <= xsize; j++) {
+            size = cuddZddSwapInPlace(table,x,y);
+            if (size == 0)
+                return(0);
+            y = x;
+            x = cuddZddNextLow(table,y);
+        }
+        y = ytop + i;
+        x = cuddZddNextLow(table,y);
+    }
+
+    /* fix groups */
+    y = xtop;
+    for (i = 0; i < ysize - 1; i++) {
+        table->subtableZ[y].next = cuddZddNextHigh(table,y);
+        y = cuddZddNextHigh(table,y);
+    }
+    table->subtableZ[y].next = xtop; /* y is bottom of its group, join */
+                                    /* to its top */
+    x = cuddZddNextHigh(table,y);
+    newxtop = x;
+    for (i = 0; i < xsize - 1; i++) {
+        table->subtableZ[x].next = cuddZddNextHigh(table,x);
+        x = cuddZddNextHigh(table,x);
+    }
+    table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */
+                                    /* to its top */
+#ifdef DD_DEBUG
+    if (pr > 0) (void) fprintf(table->out,"zddGroupMoveBackward:\n");
+#endif
+
+    return(1);
+
+} /* end of zddGroupMoveBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Determines the best position for a variables and returns
+  it there.]
+
+  Description [Determines the best position for a variables and returns
+  it there.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddGroupSiftingBackward(
+  DdManager * table,
+  Move * moves,
+  int  size)
+{
+    Move *move;
+    int  res;
+
+
+    for (move = moves; move != NULL; move = move->next) {
+        if (move->size < size) {
+            size = move->size;
+        }
+    }
+
+    for (move = moves; move != NULL; move = move->next) {
+        if (move->size == size) return(1);
+        if ((table->subtableZ[move->x].next == move->x) &&
+        (table->subtableZ[move->y].next == move->y)) {
+            res = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
+            if (!res) return(0);
+#ifdef DD_DEBUG
+            if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingBackward:\n");
+            assert(table->subtableZ[move->x].next == move->x);
+            assert(table->subtableZ[move->y].next == move->y);
+#endif
+        } else { /* Group move necessary */
+            res = zddGroupMoveBackward(table,(int)move->x,(int)move->y);
+            if (!res) return(0);
+        }
+    }
+
+    return(1);
+
+} /* end of zddGroupSiftingBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Merges groups in the DD table.]
+
+  Description [Creates a single group from low to high and adjusts the
+  idex field of the tree node.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+zddMergeGroups(
+  DdManager * table,
+  MtrNode * treenode,
+  int  low,
+  int  high)
+{
+    int i;
+    MtrNode *auxnode;
+    int saveindex;
+    int newindex;
+
+    /* Merge all variables from low to high in one group, unless
+    ** this is the topmost group. In such a case we do not merge lest
+    ** we lose the symmetry information. */
+    if (treenode != table->treeZ) {
+        for (i = low; i < high; i++)
+            table->subtableZ[i].next = i+1;
+        table->subtableZ[high].next = low;
+    }
+
+    /* Adjust the index fields of the tree nodes. If a node is the
+    ** first child of its parent, then the parent may also need adjustment. */
+    saveindex = treenode->index;
+    newindex = table->invpermZ[low];
+    auxnode = treenode;
+    do {
+        auxnode->index = newindex;
+        if (auxnode->parent == NULL ||
+                (int) auxnode->parent->index != saveindex)
+            break;
+        auxnode = auxnode->parent;
+    } while (1);
+    return;
+
+} /* end of zddMergeGroups */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddZddIsop.c b/abc-build/src/bdd/cudd/cuddZddIsop.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddZddIsop.c
@@ -0,0 +1,919 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddIsop.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions to find irredundant SOP covers as ZDDs from BDDs.]
+
+  Description [External procedures included in this module:
+                    <ul>
+                    <li> Cudd_bddIsop()
+                    <li> Cudd_zddIsop()
+                    <li> Cudd_MakeBddFromZddCover()
+                    </ul>
+               Internal procedures included in this module:
+                    <ul>
+                    <li> cuddBddIsop()
+                    <li> cuddZddIsop()
+                    <li> cuddMakeBddFromZddCover()
+                    </ul>
+               Static procedures included in this module:
+                    <ul>
+                    </ul>
+              ]
+
+  SeeAlso     []
+
+  Author      [In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddIsop.c,v 1.20 2009/02/19 16:26:12 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Computes an ISOP in ZDD form from BDDs.]
+
+  Description [Computes an irredundant sum of products (ISOP) in ZDD
+  form from BDDs. The two BDDs L and U represent the lower bound and
+  the upper bound, respectively, of the function. The ISOP uses two
+  ZDD variables for each BDD variable: One for the positive literal,
+  and one for the negative literal. These two variables should be
+  adjacent in the ZDD order. The two ZDD variables corresponding to
+  BDD variable <code>i</code> should have indices <code>2i</code> and
+  <code>2i+1</code>.  The result of this procedure depends on the
+  variable order. If successful, Cudd_zddIsop returns the BDD for
+  the function chosen from the interval. The ZDD representing the
+  irredundant cover is returned as a side effect in zdd_I. In case of
+  failure, NULL is returned.]
+
+  SideEffects [zdd_I holds the pointer to the ZDD for the ISOP on
+  successful return.]
+
+  SeeAlso     [Cudd_bddIsop Cudd_zddVarsFromBddVars]
+
+******************************************************************************/
+DdNode  *
+Cudd_zddIsop(
+  DdManager * dd,
+  DdNode * L,
+  DdNode * U,
+  DdNode ** zdd_I)
+{
+    DdNode      *res;
+    int         autoDynZ;
+
+    autoDynZ = dd->autoDynZ;
+    dd->autoDynZ = 0;
+
+    do {
+        dd->reordered = 0;
+        res = cuddZddIsop(dd, L, U, zdd_I);
+    } while (dd->reordered == 1);
+    dd->autoDynZ = autoDynZ;
+    return(res);
+
+} /* end of Cudd_zddIsop */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a BDD in the interval between L and U with a
+  simple sum-of-produuct cover.]
+
+  Description [Computes a BDD in the interval between L and U with a
+  simple sum-of-produuct cover. This procedure is similar to
+  Cudd_zddIsop, but it does not return the ZDD for the cover. Returns
+  a pointer to the BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddIsop]
+
+******************************************************************************/
+DdNode  *
+Cudd_bddIsop(
+  DdManager * dd,
+  DdNode * L,
+  DdNode * U)
+{
+    DdNode      *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddBddIsop(dd, L, U);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddIsop */
+
+
+/**Function********************************************************************
+
+  Synopsis [Converts a ZDD cover to a BDD graph.]
+
+  Description [Converts a ZDD cover to a BDD graph. If successful, it
+  returns a BDD node, otherwise it returns NULL.]
+
+  SideEffects []
+
+  SeeAlso     [cuddMakeBddFromZddCover]
+
+******************************************************************************/
+DdNode  *
+Cudd_MakeBddFromZddCover(
+  DdManager * dd,
+  DdNode * node)
+{
+    DdNode      *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddMakeBddFromZddCover(dd, node);
+    } while (dd->reordered == 1);
+    return(res);
+} /* end of Cudd_MakeBddFromZddCover */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddIsop.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddIsop]
+
+******************************************************************************/
+DdNode  *
+cuddZddIsop(
+  DdManager * dd,
+  DdNode * L,
+  DdNode * U,
+  DdNode ** zdd_I)
+{
+    DdNode      *one = DD_ONE(dd);
+    DdNode      *zero = Cudd_Not(one);
+    DdNode      *zdd_one = DD_ONE(dd);
+    DdNode      *zdd_zero = DD_ZERO(dd);
+    int         v, top_l, top_u;
+    DdNode      *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud;
+    DdNode      *Lsuper0, *Usuper0, *Lsuper1, *Usuper1;
+    DdNode      *Isub0, *Isub1, *Id;
+    DdNode      *zdd_Isub0, *zdd_Isub1, *zdd_Id;
+    DdNode      *x;
+    DdNode      *term0, *term1, *sum;
+    DdNode      *Lv, *Uv, *Lnv, *Unv;
+    DdNode      *r, *y, *z;
+    int         index;
+    DD_CTFP     cacheOp;
+
+    statLine(dd);
+    if (L == zero) {
+        *zdd_I = zdd_zero;
+        return(zero);
+    }
+    if (U == one) {
+        *zdd_I = zdd_one;
+        return(one);
+    }
+
+    if (U == zero || L == one) {
+        printf("*** ERROR : illegal condition for ISOP (U < L).\n");
+        exit(1);
+    }
+
+    /* Check the cache. We store two results for each recursive call.
+    ** One is the BDD, and the other is the ZDD. Both are needed.
+    ** Hence we need a double hit in the cache to terminate the
+    ** recursion. Clearly, collisions may evict only one of the two
+    ** results. */
+    cacheOp = (DD_CTFP) cuddZddIsop;
+    r = cuddCacheLookup2(dd, cuddBddIsop, L, U);
+    if (r) {
+        *zdd_I = cuddCacheLookup2Zdd(dd, cacheOp, L, U);
+        if (*zdd_I)
+            return(r);
+        else {
+            /* The BDD result may have been dead. In that case
+            ** cuddCacheLookup2 would have called cuddReclaim,
+            ** whose effects we now have to undo. */
+            cuddRef(r);
+            Cudd_RecursiveDeref(dd, r);
+        }
+    }
+
+    top_l = dd->perm[Cudd_Regular(L)->index];
+    top_u = dd->perm[Cudd_Regular(U)->index];
+    v = ddMin(top_l, top_u);
+
+    /* Compute cofactors. */
+    if (top_l == v) {
+        index = Cudd_Regular(L)->index;
+        Lv = Cudd_T(L);
+        Lnv = Cudd_E(L);
+        if (Cudd_IsComplement(L)) {
+            Lv = Cudd_Not(Lv);
+            Lnv = Cudd_Not(Lnv);
+        }
+    }
+    else {
+        index = Cudd_Regular(U)->index;
+        Lv = Lnv = L;
+    }
+
+    if (top_u == v) {
+        Uv = Cudd_T(U);
+        Unv = Cudd_E(U);
+        if (Cudd_IsComplement(U)) {
+            Uv = Cudd_Not(Uv);
+            Unv = Cudd_Not(Unv);
+        }
+    }
+    else {
+        Uv = Unv = U;
+    }
+
+    Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv));
+    if (Lsub0 == NULL)
+        return(NULL);
+    Cudd_Ref(Lsub0);
+    Usub0 = Unv;
+    Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv));
+    if (Lsub1 == NULL) {
+        Cudd_RecursiveDeref(dd, Lsub0);
+        return(NULL);
+    }
+    Cudd_Ref(Lsub1);
+    Usub1 = Uv;
+
+    Isub0 = cuddZddIsop(dd, Lsub0, Usub0, &zdd_Isub0);
+    if (Isub0 == NULL) {
+        Cudd_RecursiveDeref(dd, Lsub0);
+        Cudd_RecursiveDeref(dd, Lsub1);
+        return(NULL);
+    }
+    /*
+    if ((!cuddIsConstant(Cudd_Regular(Isub0))) &&
+        (Cudd_Regular(Isub0)->index != zdd_Isub0->index / 2 ||
+        dd->permZ[index * 2] > dd->permZ[zdd_Isub0->index])) {
+        printf("*** ERROR : illegal permutation in ZDD. ***\n");
+    }
+    */
+    Cudd_Ref(Isub0);
+    Cudd_Ref(zdd_Isub0);
+    Isub1 = cuddZddIsop(dd, Lsub1, Usub1, &zdd_Isub1);
+    if (Isub1 == NULL) {
+        Cudd_RecursiveDeref(dd, Lsub0);
+        Cudd_RecursiveDeref(dd, Lsub1);
+        Cudd_RecursiveDeref(dd, Isub0);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+        return(NULL);
+    }
+    /*
+    if ((!cuddIsConstant(Cudd_Regular(Isub1))) &&
+        (Cudd_Regular(Isub1)->index != zdd_Isub1->index / 2 ||
+        dd->permZ[index * 2] > dd->permZ[zdd_Isub1->index])) {
+        printf("*** ERROR : illegal permutation in ZDD. ***\n");
+    }
+    */
+    Cudd_Ref(Isub1);
+    Cudd_Ref(zdd_Isub1);
+    Cudd_RecursiveDeref(dd, Lsub0);
+    Cudd_RecursiveDeref(dd, Lsub1);
+
+    Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0));
+    if (Lsuper0 == NULL) {
+        Cudd_RecursiveDeref(dd, Isub0);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+        Cudd_RecursiveDeref(dd, Isub1);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+        return(NULL);
+    }
+    Cudd_Ref(Lsuper0);
+    Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1));
+    if (Lsuper1 == NULL) {
+        Cudd_RecursiveDeref(dd, Isub0);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+        Cudd_RecursiveDeref(dd, Isub1);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+        Cudd_RecursiveDeref(dd, Lsuper0);
+        return(NULL);
+    }
+    Cudd_Ref(Lsuper1);
+    Usuper0 = Unv;
+    Usuper1 = Uv;
+
+    /* Ld = Lsuper0 + Lsuper1 */
+    Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1));
+    if (Ld == NULL) {
+        Cudd_RecursiveDeref(dd, Isub0);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+        Cudd_RecursiveDeref(dd, Isub1);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+        Cudd_RecursiveDeref(dd, Lsuper0);
+        Cudd_RecursiveDeref(dd, Lsuper1);
+        return(NULL);
+    }
+    Ld = Cudd_Not(Ld);
+    Cudd_Ref(Ld);
+    /* Ud = Usuper0 * Usuper1 */
+    Ud = cuddBddAndRecur(dd, Usuper0, Usuper1);
+    if (Ud == NULL) {
+        Cudd_RecursiveDeref(dd, Isub0);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+        Cudd_RecursiveDeref(dd, Isub1);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+        Cudd_RecursiveDeref(dd, Lsuper0);
+        Cudd_RecursiveDeref(dd, Lsuper1);
+        Cudd_RecursiveDeref(dd, Ld);
+        return(NULL);
+    }
+    Cudd_Ref(Ud);
+    Cudd_RecursiveDeref(dd, Lsuper0);
+    Cudd_RecursiveDeref(dd, Lsuper1);
+
+    Id = cuddZddIsop(dd, Ld, Ud, &zdd_Id);
+    if (Id == NULL) {
+        Cudd_RecursiveDeref(dd, Isub0);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+        Cudd_RecursiveDeref(dd, Isub1);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+        Cudd_RecursiveDeref(dd, Ld);
+        Cudd_RecursiveDeref(dd, Ud);
+        return(NULL);
+    }
+    /*
+    if ((!cuddIsConstant(Cudd_Regular(Id))) &&
+        (Cudd_Regular(Id)->index != zdd_Id->index / 2 ||
+        dd->permZ[index * 2] > dd->permZ[zdd_Id->index])) {
+        printf("*** ERROR : illegal permutation in ZDD. ***\n");
+    }
+    */
+    Cudd_Ref(Id);
+    Cudd_Ref(zdd_Id);
+    Cudd_RecursiveDeref(dd, Ld);
+    Cudd_RecursiveDeref(dd, Ud);
+
+    x = cuddUniqueInter(dd, index, one, zero);
+    if (x == NULL) {
+        Cudd_RecursiveDeref(dd, Isub0);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+        Cudd_RecursiveDeref(dd, Isub1);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+        Cudd_RecursiveDeref(dd, Id);
+        Cudd_RecursiveDerefZdd(dd, zdd_Id);
+        return(NULL);
+    }
+    Cudd_Ref(x);
+    /* term0 = x * Isub0 */
+    term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0);
+    if (term0 == NULL) {
+        Cudd_RecursiveDeref(dd, Isub0);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+        Cudd_RecursiveDeref(dd, Isub1);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+        Cudd_RecursiveDeref(dd, Id);
+        Cudd_RecursiveDerefZdd(dd, zdd_Id);
+        Cudd_RecursiveDeref(dd, x);
+        return(NULL);
+    }
+    Cudd_Ref(term0);
+    Cudd_RecursiveDeref(dd, Isub0);
+    /* term1 = x * Isub1 */
+    term1 = cuddBddAndRecur(dd, x, Isub1);
+    if (term1 == NULL) {
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+        Cudd_RecursiveDeref(dd, Isub1);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+        Cudd_RecursiveDeref(dd, Id);
+        Cudd_RecursiveDerefZdd(dd, zdd_Id);
+        Cudd_RecursiveDeref(dd, x);
+        Cudd_RecursiveDeref(dd, term0);
+        return(NULL);
+    }
+    Cudd_Ref(term1);
+    Cudd_RecursiveDeref(dd, x);
+    Cudd_RecursiveDeref(dd, Isub1);
+    /* sum = term0 + term1 */
+    sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1));
+    if (sum == NULL) {
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+        Cudd_RecursiveDeref(dd, Id);
+        Cudd_RecursiveDerefZdd(dd, zdd_Id);
+        Cudd_RecursiveDeref(dd, term0);
+        Cudd_RecursiveDeref(dd, term1);
+        return(NULL);
+    }
+    sum = Cudd_Not(sum);
+    Cudd_Ref(sum);
+    Cudd_RecursiveDeref(dd, term0);
+    Cudd_RecursiveDeref(dd, term1);
+    /* r = sum + Id */
+    r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id));
+    r = Cudd_NotCond(r, r != NULL);
+    if (r == NULL) {
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+        Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+        Cudd_RecursiveDeref(dd, Id);
+        Cudd_RecursiveDerefZdd(dd, zdd_Id);
+        Cudd_RecursiveDeref(dd, sum);
+        return(NULL);
+    }
+    Cudd_Ref(r);
+    Cudd_RecursiveDeref(dd, sum);
+    Cudd_RecursiveDeref(dd, Id);
+
+    if (zdd_Isub0 != zdd_zero) {
+        z = cuddZddGetNodeIVO(dd, index * 2 + 1, zdd_Isub0, zdd_Id);
+        if (z == NULL) {
+            Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+            Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+            Cudd_RecursiveDerefZdd(dd, zdd_Id);
+            Cudd_RecursiveDeref(dd, r);
+            return(NULL);
+        }
+    }
+    else {
+        z = zdd_Id;
+    }
+    Cudd_Ref(z);
+    if (zdd_Isub1 != zdd_zero) {
+        y = cuddZddGetNodeIVO(dd, index * 2, zdd_Isub1, z);
+        if (y == NULL) {
+            Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+            Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+            Cudd_RecursiveDerefZdd(dd, zdd_Id);
+            Cudd_RecursiveDeref(dd, r);
+            Cudd_RecursiveDerefZdd(dd, z);
+            return(NULL);
+        }
+    }
+    else
+        y = z;
+    Cudd_Ref(y);
+
+    Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+    Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+    Cudd_RecursiveDerefZdd(dd, zdd_Id);
+    Cudd_RecursiveDerefZdd(dd, z);
+
+    cuddCacheInsert2(dd, cuddBddIsop, L, U, r);
+    cuddCacheInsert2(dd, cacheOp, L, U, y);
+
+    Cudd_Deref(r);
+    Cudd_Deref(y);
+    *zdd_I = y;
+    /*
+    if (Cudd_Regular(r)->index != y->index / 2) {
+        printf("*** ERROR : mismatch in indices between BDD and ZDD. ***\n");
+    }
+    */
+    return(r);
+
+} /* end of cuddZddIsop */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_bddIsop.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIsop]
+
+******************************************************************************/
+DdNode  *
+cuddBddIsop(
+  DdManager * dd,
+  DdNode * L,
+  DdNode * U)
+{
+    DdNode      *one = DD_ONE(dd);
+    DdNode      *zero = Cudd_Not(one);
+    int         v, top_l, top_u;
+    DdNode      *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud;
+    DdNode      *Lsuper0, *Usuper0, *Lsuper1, *Usuper1;
+    DdNode      *Isub0, *Isub1, *Id;
+    DdNode      *x;
+    DdNode      *term0, *term1, *sum;
+    DdNode      *Lv, *Uv, *Lnv, *Unv;
+    DdNode      *r;
+    int         index;
+
+    statLine(dd);
+    if (L == zero)
+        return(zero);
+    if (U == one)
+        return(one);
+
+    /* Check cache */
+    r = cuddCacheLookup2(dd, cuddBddIsop, L, U);
+    if (r)
+        return(r);
+
+    top_l = dd->perm[Cudd_Regular(L)->index];
+    top_u = dd->perm[Cudd_Regular(U)->index];
+    v = ddMin(top_l, top_u);
+
+    /* Compute cofactors */
+    if (top_l == v) {
+        index = Cudd_Regular(L)->index;
+        Lv = Cudd_T(L);
+        Lnv = Cudd_E(L);
+        if (Cudd_IsComplement(L)) {
+            Lv = Cudd_Not(Lv);
+            Lnv = Cudd_Not(Lnv);
+        }
+    }
+    else {
+        index = Cudd_Regular(U)->index;
+        Lv = Lnv = L;
+    }
+
+    if (top_u == v) {
+        Uv = Cudd_T(U);
+        Unv = Cudd_E(U);
+        if (Cudd_IsComplement(U)) {
+            Uv = Cudd_Not(Uv);
+            Unv = Cudd_Not(Unv);
+        }
+    }
+    else {
+        Uv = Unv = U;
+    }
+
+    Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv));
+    if (Lsub0 == NULL)
+        return(NULL);
+    Cudd_Ref(Lsub0);
+    Usub0 = Unv;
+    Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv));
+    if (Lsub1 == NULL) {
+        Cudd_RecursiveDeref(dd, Lsub0);
+        return(NULL);
+    }
+    Cudd_Ref(Lsub1);
+    Usub1 = Uv;
+
+    Isub0 = cuddBddIsop(dd, Lsub0, Usub0);
+    if (Isub0 == NULL) {
+        Cudd_RecursiveDeref(dd, Lsub0);
+        Cudd_RecursiveDeref(dd, Lsub1);
+        return(NULL);
+    }
+    Cudd_Ref(Isub0);
+    Isub1 = cuddBddIsop(dd, Lsub1, Usub1);
+    if (Isub1 == NULL) {
+        Cudd_RecursiveDeref(dd, Lsub0);
+        Cudd_RecursiveDeref(dd, Lsub1);
+        Cudd_RecursiveDeref(dd, Isub0);
+        return(NULL);
+    }
+    Cudd_Ref(Isub1);
+    Cudd_RecursiveDeref(dd, Lsub0);
+    Cudd_RecursiveDeref(dd, Lsub1);
+
+    Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0));
+    if (Lsuper0 == NULL) {
+        Cudd_RecursiveDeref(dd, Isub0);
+        Cudd_RecursiveDeref(dd, Isub1);
+        return(NULL);
+    }
+    Cudd_Ref(Lsuper0);
+    Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1));
+    if (Lsuper1 == NULL) {
+        Cudd_RecursiveDeref(dd, Isub0);
+        Cudd_RecursiveDeref(dd, Isub1);
+        Cudd_RecursiveDeref(dd, Lsuper0);
+        return(NULL);
+    }
+    Cudd_Ref(Lsuper1);
+    Usuper0 = Unv;
+    Usuper1 = Uv;
+
+    /* Ld = Lsuper0 + Lsuper1 */
+    Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1));
+    Ld = Cudd_NotCond(Ld, Ld != NULL);
+    if (Ld == NULL) {
+        Cudd_RecursiveDeref(dd, Isub0);
+        Cudd_RecursiveDeref(dd, Isub1);
+        Cudd_RecursiveDeref(dd, Lsuper0);
+        Cudd_RecursiveDeref(dd, Lsuper1);
+        return(NULL);
+    }
+    Cudd_Ref(Ld);
+    Ud = cuddBddAndRecur(dd, Usuper0, Usuper1);
+    if (Ud == NULL) {
+        Cudd_RecursiveDeref(dd, Isub0);
+        Cudd_RecursiveDeref(dd, Isub1);
+        Cudd_RecursiveDeref(dd, Lsuper0);
+        Cudd_RecursiveDeref(dd, Lsuper1);
+        Cudd_RecursiveDeref(dd, Ld);
+        return(NULL);
+    }
+    Cudd_Ref(Ud);
+    Cudd_RecursiveDeref(dd, Lsuper0);
+    Cudd_RecursiveDeref(dd, Lsuper1);
+
+    Id = cuddBddIsop(dd, Ld, Ud);
+    if (Id == NULL) {
+        Cudd_RecursiveDeref(dd, Isub0);
+        Cudd_RecursiveDeref(dd, Isub1);
+        Cudd_RecursiveDeref(dd, Ld);
+        Cudd_RecursiveDeref(dd, Ud);
+        return(NULL);
+    }
+    Cudd_Ref(Id);
+    Cudd_RecursiveDeref(dd, Ld);
+    Cudd_RecursiveDeref(dd, Ud);
+
+    x = cuddUniqueInter(dd, index, one, zero);
+    if (x == NULL) {
+        Cudd_RecursiveDeref(dd, Isub0);
+        Cudd_RecursiveDeref(dd, Isub1);
+        Cudd_RecursiveDeref(dd, Id);
+        return(NULL);
+    }
+    Cudd_Ref(x);
+    term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0);
+    if (term0 == NULL) {
+        Cudd_RecursiveDeref(dd, Isub0);
+        Cudd_RecursiveDeref(dd, Isub1);
+        Cudd_RecursiveDeref(dd, Id);
+        Cudd_RecursiveDeref(dd, x);
+        return(NULL);
+    }
+    Cudd_Ref(term0);
+    Cudd_RecursiveDeref(dd, Isub0);
+    term1 = cuddBddAndRecur(dd, x, Isub1);
+    if (term1 == NULL) {
+        Cudd_RecursiveDeref(dd, Isub1);
+        Cudd_RecursiveDeref(dd, Id);
+        Cudd_RecursiveDeref(dd, x);
+        Cudd_RecursiveDeref(dd, term0);
+        return(NULL);
+    }
+    Cudd_Ref(term1);
+    Cudd_RecursiveDeref(dd, x);
+    Cudd_RecursiveDeref(dd, Isub1);
+    /* sum = term0 + term1 */
+    sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1));
+    sum = Cudd_NotCond(sum, sum != NULL);
+    if (sum == NULL) {
+        Cudd_RecursiveDeref(dd, Id);
+        Cudd_RecursiveDeref(dd, term0);
+        Cudd_RecursiveDeref(dd, term1);
+        return(NULL);
+    }
+    Cudd_Ref(sum);
+    Cudd_RecursiveDeref(dd, term0);
+    Cudd_RecursiveDeref(dd, term1);
+    /* r = sum + Id */
+    r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id));
+    r = Cudd_NotCond(r, r != NULL);
+    if (r == NULL) {
+        Cudd_RecursiveDeref(dd, Id);
+        Cudd_RecursiveDeref(dd, sum);
+        return(NULL);
+    }
+    Cudd_Ref(r);
+    Cudd_RecursiveDeref(dd, sum);
+    Cudd_RecursiveDeref(dd, Id);
+
+    cuddCacheInsert2(dd, cuddBddIsop, L, U, r);
+
+    Cudd_Deref(r);
+    return(r);
+
+} /* end of cuddBddIsop */
+
+
+/**Function********************************************************************
+
+  Synopsis [Converts a ZDD cover to a BDD graph.]
+
+  Description [Converts a ZDD cover to a BDD graph. If successful, it
+  returns a BDD node, otherwise it returns NULL. It is a recursive
+  algorithm as the following. First computes 3 cofactors of a ZDD cover;
+  f1, f0 and fd. Second, compute BDDs(b1, b0 and bd) of f1, f0 and fd.
+  Third, compute T=b1+bd and E=b0+bd. Fourth, compute ITE(v,T,E) where v
+  is the variable which has the index of the top node of the ZDD cover.
+  In this case, since the index of v can be larger than either one of T or
+  one of E, cuddUniqueInterIVO is called, here IVO stands for
+  independent variable ordering.]
+
+  SideEffects []
+
+  SeeAlso     [Cudd_MakeBddFromZddCover]
+
+******************************************************************************/
+DdNode  *
+cuddMakeBddFromZddCover(
+  DdManager * dd,
+  DdNode * node)
+{
+    DdNode      *neW;
+    int         v;
+    DdNode      *f1, *f0, *fd;
+    DdNode      *b1, *b0, *bd;
+    DdNode      *T, *E;
+
+    statLine(dd);
+    if (node == dd->one)
+        return(dd->one);
+    if (node == dd->zero)
+        return(Cudd_Not(dd->one));
+
+    /* Check cache */
+    neW = cuddCacheLookup1(dd, cuddMakeBddFromZddCover, node);
+    if (neW)
+        return(neW);
+
+    v = Cudd_Regular(node)->index;      /* either yi or zi */
+    if (cuddZddGetCofactors3(dd, node, v, &f1, &f0, &fd)) return(NULL);
+    Cudd_Ref(f1);
+    Cudd_Ref(f0);
+    Cudd_Ref(fd);
+
+    b1 = cuddMakeBddFromZddCover(dd, f1);
+    if (!b1) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        return(NULL);
+    }
+    Cudd_Ref(b1);
+    b0 = cuddMakeBddFromZddCover(dd, f0);
+    if (!b0) {
+        Cudd_RecursiveDerefZdd(dd, f1);
+        Cudd_RecursiveDerefZdd(dd, f0);
+        Cudd_RecursiveDerefZdd(dd, fd);
+        Cudd_RecursiveDeref(dd, b1);
+        return(NULL);
+    }
+    Cudd_Ref(b0);
+    Cudd_RecursiveDerefZdd(dd, f1);
+    Cudd_RecursiveDerefZdd(dd, f0);
+    if (fd != dd->zero) {
+        bd = cuddMakeBddFromZddCover(dd, fd);
+        if (!bd) {
+            Cudd_RecursiveDerefZdd(dd, fd);
+            Cudd_RecursiveDeref(dd, b1);
+            Cudd_RecursiveDeref(dd, b0);
+            return(NULL);
+        }
+        Cudd_Ref(bd);
+        Cudd_RecursiveDerefZdd(dd, fd);
+
+        T = cuddBddAndRecur(dd, Cudd_Not(b1), Cudd_Not(bd));
+        if (!T) {
+            Cudd_RecursiveDeref(dd, b1);
+            Cudd_RecursiveDeref(dd, b0);
+            Cudd_RecursiveDeref(dd, bd);
+            return(NULL);
+        }
+        T = Cudd_NotCond(T, T != NULL);
+        Cudd_Ref(T);
+        Cudd_RecursiveDeref(dd, b1);
+        E = cuddBddAndRecur(dd, Cudd_Not(b0), Cudd_Not(bd));
+        if (!E) {
+            Cudd_RecursiveDeref(dd, b0);
+            Cudd_RecursiveDeref(dd, bd);
+            Cudd_RecursiveDeref(dd, T);
+            return(NULL);
+        }
+        E = Cudd_NotCond(E, E != NULL);
+        Cudd_Ref(E);
+        Cudd_RecursiveDeref(dd, b0);
+        Cudd_RecursiveDeref(dd, bd);
+    }
+    else {
+        Cudd_RecursiveDerefZdd(dd, fd);
+        T = b1;
+        E = b0;
+    }
+
+    if (Cudd_IsComplement(T)) {
+        neW = cuddUniqueInterIVO(dd, v / 2, Cudd_Not(T), Cudd_Not(E));
+        if (!neW) {
+            Cudd_RecursiveDeref(dd, T);
+            Cudd_RecursiveDeref(dd, E);
+            return(NULL);
+        }
+        neW = Cudd_Not(neW);
+    }
+    else {
+        neW = cuddUniqueInterIVO(dd, v / 2, T, E);
+        if (!neW) {
+            Cudd_RecursiveDeref(dd, T);
+            Cudd_RecursiveDeref(dd, E);
+            return(NULL);
+        }
+    }
+    Cudd_Ref(neW);
+    Cudd_RecursiveDeref(dd, T);
+    Cudd_RecursiveDeref(dd, E);
+
+    cuddCacheInsert1(dd, cuddMakeBddFromZddCover, node, neW);
+    Cudd_Deref(neW);
+    return(neW);
+
+} /* end of cuddMakeBddFromZddCover */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddZddLin.c b/abc-build/src/bdd/cudd/cuddZddLin.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddZddLin.c
@@ -0,0 +1,975 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddLin.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Procedures for dynamic variable ordering of ZDDs.]
+
+  Description [Internal procedures included in this module:
+                    <ul>
+                    <li> cuddZddLinearSifting()
+                    </ul>
+               Static procedures included in this module:
+                    <ul>
+                    <li> cuddZddLinearInPlace()
+                    <li> cuddZddLinerAux()
+                    <li> cuddZddLinearUp()
+                    <li> cuddZddLinearDown()
+                    <li> cuddZddLinearBackward()
+                    <li> cuddZddUndoMoves()
+                    </ul>
+              ]
+
+  SeeAlso     [cuddLinear.c cuddZddReord.c]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define CUDD_SWAP_MOVE 0
+#define CUDD_LINEAR_TRANSFORM_MOVE 1
+#define CUDD_INVERSE_TRANSFORM_MOVE 2
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddLin.c,v 1.14 2004/08/13 18:04:53 fabio Exp $";
+#endif
+
+extern  int     *zdd_entry;
+extern  int     zddTotalNumberSwapping;
+static  int     zddTotalNumberLinearTr;
+static  DdNode  *empty;
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int cuddZddLinearInPlace (DdManager * table, int x, int y);
+static int cuddZddLinearAux (DdManager *table, int x, int xLow, int xHigh);
+static Move * cuddZddLinearUp (DdManager *table, int y, int xLow, Move *prevMoves);
+static Move * cuddZddLinearDown (DdManager *table, int x, int xHigh, Move *prevMoves);
+static int cuddZddLinearBackward (DdManager *table, int size, Move *moves);
+static Move* cuddZddUndoMoves (DdManager *table, Move *moves);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implementation of the linear sifting algorithm for ZDDs.]
+
+  Description [Implementation of the linear sifting algorithm for ZDDs.
+  Assumes that no dead nodes are present.
+    <ol>
+    <li> Order all the variables according to the number of entries
+    in each unique table.
+    <li> Sift the variable up and down and applies the XOR transformation,
+    remembering each time the total size of the DD heap.
+    <li> Select the best permutation.
+    <li> Repeat 3 and 4 for all variables.
+    </ol>
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddLinearSifting(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int i;
+    int *var;
+    int size;
+    int x;
+    int result;
+#ifdef DD_STATS
+    int previousSize;
+#endif
+
+    size = table->sizeZ;
+    empty = table->zero;
+
+    /* Find order in which to sift variables. */
+    var = NULL;
+    zdd_entry = ABC_ALLOC(int, size);
+    if (zdd_entry == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto cuddZddSiftingOutOfMem;
+    }
+    var = ABC_ALLOC(int, size);
+    if (var == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto cuddZddSiftingOutOfMem;
+    }
+
+    for (i = 0; i < size; i++) {
+        x = table->permZ[i];
+        zdd_entry[i] = table->subtableZ[x].keys;
+        var[i] = i;
+    }
+
+    qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
+
+    /* Now sift. */
+    for (i = 0; i < ddMin(table->siftMaxVar, size); i++) {
+        if (zddTotalNumberSwapping >= table->siftMaxSwap)
+            break;
+        x = table->permZ[var[i]];
+        if (x < lower || x > upper) continue;
+#ifdef DD_STATS
+        previousSize = table->keysZ;
+#endif
+        result = cuddZddLinearAux(table, x, lower, upper);
+        if (!result)
+            goto cuddZddSiftingOutOfMem;
+#ifdef DD_STATS
+        if (table->keysZ < (unsigned) previousSize) {
+            (void) fprintf(table->out,"-");
+        } else if (table->keysZ > (unsigned) previousSize) {
+            (void) fprintf(table->out,"+");     /* should never happen */
+            (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]);
+        } else {
+            (void) fprintf(table->out,"=");
+        }
+        fflush(table->out);
+#endif
+    }
+
+    ABC_FREE(var);
+    ABC_FREE(zdd_entry);
+
+    return(1);
+
+cuddZddSiftingOutOfMem:
+
+    if (zdd_entry != NULL) ABC_FREE(zdd_entry);
+    if (var != NULL) ABC_FREE(var);
+
+    return(0);
+
+} /* end of cuddZddLinearSifting */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Linearly combines two adjacent variables.]
+
+  Description [Linearly combines two adjacent variables. It assumes
+  that no dead nodes are present on entry to this procedure.  The
+  procedure then guarantees that no dead nodes will be present when it
+  terminates.  cuddZddLinearInPlace assumes that x &lt; y.  Returns the
+  number of keys in the table if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddZddSwapInPlace cuddLinearInPlace]
+
+******************************************************************************/
+static int
+cuddZddLinearInPlace(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    DdNodePtr *xlist, *ylist;
+    int         xindex, yindex;
+    int         xslots, yslots;
+    int         xshift, yshift;
+    int         oldxkeys, oldykeys;
+    int         newxkeys, newykeys;
+    int         i;
+    int         posn;
+    DdNode      *f, *f1, *f0, *f11, *f10, *f01, *f00;
+    DdNode      *newf1, *newf0, *g, *next, *previous;
+    DdNode      *special;
+
+#ifdef DD_DEBUG
+    assert(x < y);
+    assert(cuddZddNextHigh(table,x) == y);
+    assert(table->subtableZ[x].keys != 0);
+    assert(table->subtableZ[y].keys != 0);
+    assert(table->subtableZ[x].dead == 0);
+    assert(table->subtableZ[y].dead == 0);
+#endif
+
+    zddTotalNumberLinearTr++;
+
+    /* Get parameters of x subtable. */
+    xindex   = table->invpermZ[x];
+    xlist    = table->subtableZ[x].nodelist;
+    oldxkeys = table->subtableZ[x].keys;
+    xslots   = table->subtableZ[x].slots;
+    xshift   = table->subtableZ[x].shift;
+    newxkeys = 0;
+
+    /* Get parameters of y subtable. */
+    yindex   = table->invpermZ[y];
+    ylist    = table->subtableZ[y].nodelist;
+    oldykeys = table->subtableZ[y].keys;
+    yslots   = table->subtableZ[y].slots;
+    yshift   = table->subtableZ[y].shift;
+    newykeys = oldykeys;
+
+    /* The nodes in the x layer are put in two chains.  The chain
+    ** pointed by g holds the normal nodes. When re-expressed they stay
+    ** in the x list. The chain pointed by special holds the elements
+    ** that will move to the y list.
+    */
+    g = special = NULL;
+    for (i = 0; i < xslots; i++) {
+        f = xlist[i];
+        if (f == NULL) continue;
+        xlist[i] = NULL;
+        while (f != NULL) {
+            next = f->next;
+            f1 = cuddT(f);
+            /* if (f1->index == yindex) */ cuddSatDec(f1->ref);
+            f0 = cuddE(f);
+            /* if (f0->index == yindex) */ cuddSatDec(f0->ref);
+            if ((int) f1->index == yindex && cuddE(f1) == empty &&
+                (int) f0->index != yindex) {
+                f->next = special;
+                special = f;
+            } else {
+                f->next = g;
+                g = f;
+            }
+            f = next;
+        } /* while there are elements in the collision chain */
+    } /* for each slot of the x subtable */
+
+    /* Mark y nodes with pointers from above x. We mark them by
+    **  changing their index to x.
+    */
+    for (i = 0; i < yslots; i++) {
+        f = ylist[i];
+        while (f != NULL) {
+            if (f->ref != 0) {
+                f->index = xindex;
+            }
+            f = f->next;
+        } /* while there are elements in the collision chain */
+    } /* for each slot of the y subtable */
+
+    /* Move special nodes to the y list. */
+    f = special;
+    while (f != NULL) {
+        next = f->next;
+        f1 = cuddT(f);
+        f11 = cuddT(f1);
+        cuddT(f) = f11;
+        cuddSatInc(f11->ref);
+        f0 = cuddE(f);
+        cuddSatInc(f0->ref);
+        f->index = yindex;
+        /* Insert at the beginning of the list so that it will be
+        ** found first if there is a duplicate. The duplicate will
+        ** eventually be moved or garbage collected. No node
+        ** re-expression will add a pointer to it.
+        */
+        posn = ddHash(cuddF2L(f11), cuddF2L(f0), yshift);
+        f->next = ylist[posn];
+        ylist[posn] = f;
+        newykeys++;
+        f = next;
+    }
+
+    /* Take care of the remaining x nodes that must be re-expressed.
+    ** They form a linked list pointed by g.
+    */
+    f = g;
+    while (f != NULL) {
+#ifdef DD_COUNT
+        table->swapSteps++;
+#endif
+        next = f->next;
+        /* Find f1, f0, f11, f10, f01, f00. */
+        f1 = cuddT(f);
+        if ((int) f1->index == yindex || (int) f1->index == xindex) {
+            f11 = cuddT(f1); f10 = cuddE(f1);
+        } else {
+            f11 = empty; f10 = f1;
+        }
+        f0 = cuddE(f);
+        if ((int) f0->index == yindex || (int) f0->index == xindex) {
+            f01 = cuddT(f0); f00 = cuddE(f0);
+        } else {
+            f01 = empty; f00 = f0;
+        }
+        /* Create the new T child. */
+        if (f01 == empty) {
+            newf1 = f10;
+            cuddSatInc(newf1->ref);
+        } else {
+            /* Check ylist for triple (yindex, f01, f10). */
+            posn = ddHash(cuddF2L(f01), cuddF2L(f10), yshift);
+            /* For each element newf1 in collision list ylist[posn]. */
+            newf1 = ylist[posn];
+            /* Search the collision chain skipping the marked nodes. */
+            while (newf1 != NULL) {
+                if (cuddT(newf1) == f01 && cuddE(newf1) == f10 &&
+                    (int) newf1->index == yindex) {
+                    cuddSatInc(newf1->ref);
+                    break; /* match */
+                }
+                newf1 = newf1->next;
+            } /* while newf1 */
+            if (newf1 == NULL) {        /* no match */
+                newf1 = cuddDynamicAllocNode(table);
+                if (newf1 == NULL)
+                    goto zddSwapOutOfMem;
+                newf1->index = yindex; newf1->ref = 1;
+                cuddT(newf1) = f01;
+                cuddE(newf1) = f10;
+                /* Insert newf1 in the collision list ylist[pos];
+                ** increase the ref counts of f01 and f10
+                */
+                newykeys++;
+                newf1->next = ylist[posn];
+                ylist[posn] = newf1;
+                cuddSatInc(f01->ref);
+                cuddSatInc(f10->ref);
+            }
+        }
+        cuddT(f) = newf1;
+
+        /* Do the same for f0. */
+        /* Create the new E child. */
+        if (f11 == empty) {
+            newf0 = f00;
+            cuddSatInc(newf0->ref);
+        } else {
+            /* Check ylist for triple (yindex, f11, f00). */
+            posn = ddHash(cuddF2L(f11), cuddF2L(f00), yshift);
+            /* For each element newf0 in collision list ylist[posn]. */
+            newf0 = ylist[posn];
+            while (newf0 != NULL) {
+                if (cuddT(newf0) == f11 && cuddE(newf0) == f00 &&
+                    (int) newf0->index == yindex) {
+                    cuddSatInc(newf0->ref);
+                    break; /* match */
+                }
+                newf0 = newf0->next;
+            } /* while newf0 */
+            if (newf0 == NULL) {        /* no match */
+                newf0 = cuddDynamicAllocNode(table);
+                if (newf0 == NULL)
+                    goto zddSwapOutOfMem;
+                newf0->index = yindex; newf0->ref = 1;
+                cuddT(newf0) = f11; cuddE(newf0) = f00;
+                /* Insert newf0 in the collision list ylist[posn];
+                ** increase the ref counts of f11 and f00.
+                */
+                newykeys++;
+                newf0->next = ylist[posn];
+                ylist[posn] = newf0;
+                cuddSatInc(f11->ref);
+                cuddSatInc(f00->ref);
+            }
+        }
+        cuddE(f) = newf0;
+
+        /* Re-insert the modified f in xlist.
+        ** The modified f does not already exists in xlist.
+        ** (Because of the uniqueness of the cofactors.)
+        */
+        posn = ddHash(cuddF2L(newf1), cuddF2L(newf0), xshift);
+        newxkeys++;
+        f->next = xlist[posn];
+        xlist[posn] = f;
+        f = next;
+    } /* while f != NULL */
+
+    /* GC the y layer and move the marked nodes to the x list. */
+
+    /* For each node f in ylist. */
+    for (i = 0; i < yslots; i++) {
+        previous = NULL;
+        f = ylist[i];
+        while (f != NULL) {
+            next = f->next;
+            if (f->ref == 0) {
+                cuddSatDec(cuddT(f)->ref);
+                cuddSatDec(cuddE(f)->ref);
+                cuddDeallocNode(table, f);
+                newykeys--;
+                if (previous == NULL)
+                    ylist[i] = next;
+                else
+                    previous->next = next;
+            } else if ((int) f->index == xindex) { /* move marked node */
+                if (previous == NULL)
+                    ylist[i] = next;
+                else
+                    previous->next = next;
+                f1 = cuddT(f);
+                cuddSatDec(f1->ref);
+                /* Check ylist for triple (yindex, f1, empty). */
+                posn = ddHash(cuddF2L(f1), cuddF2L(empty), yshift);
+                /* For each element newf1 in collision list ylist[posn]. */
+                newf1 = ylist[posn];
+                while (newf1 != NULL) {
+                    if (cuddT(newf1) == f1 && cuddE(newf1) == empty &&
+                        (int) newf1->index == yindex) {
+                        cuddSatInc(newf1->ref);
+                        break; /* match */
+                    }
+                    newf1 = newf1->next;
+                } /* while newf1 */
+                if (newf1 == NULL) {    /* no match */
+                    newf1 = cuddDynamicAllocNode(table);
+                    if (newf1 == NULL)
+                        goto zddSwapOutOfMem;
+                    newf1->index = yindex; newf1->ref = 1;
+                    cuddT(newf1) = f1; cuddE(newf1) = empty;
+                    /* Insert newf1 in the collision list ylist[posn];
+                    ** increase the ref counts of f1 and empty.
+                    */
+                    newykeys++;
+                    newf1->next = ylist[posn];
+                    ylist[posn] = newf1;
+                    if (posn == i && previous == NULL)
+                        previous = newf1;
+                    cuddSatInc(f1->ref);
+                    cuddSatInc(empty->ref);
+                }
+                cuddT(f) = newf1;
+                f0 = cuddE(f);
+                /* Insert f in x list. */
+                posn = ddHash(cuddF2L(newf1), cuddF2L(f0), xshift);
+                newxkeys++;
+                newykeys--;
+                f->next = xlist[posn];
+                xlist[posn] = f;
+            } else {
+                previous = f;
+            }
+            f = next;
+        } /* while f */
+    } /* for i */
+
+    /* Set the appropriate fields in table. */
+    table->subtableZ[x].keys     = newxkeys;
+    table->subtableZ[y].keys     = newykeys;
+
+    table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys;
+
+    /* Update univ section; univ[x] remains the same. */
+    table->univ[y] = cuddT(table->univ[x]);
+
+#if 0
+    (void) fprintf(table->out,"x = %d  y = %d\n", x, y);
+    (void) Cudd_DebugCheck(table);
+    (void) Cudd_CheckKeys(table);
+#endif
+
+    return (table->keysZ);
+
+zddSwapOutOfMem:
+    (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n");
+
+    return (0);
+
+} /* end of cuddZddLinearInPlace */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries.]
+
+  Description [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries. Finds the best position and does the required changes.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddLinearAux(
+  DdManager * table,
+  int  x,
+  int  xLow,
+  int  xHigh)
+{
+    Move        *move;
+    Move        *moveUp;        /* list of up move */
+    Move        *moveDown;      /* list of down move */
+
+    int         initial_size;
+    int         result;
+
+    initial_size = table->keysZ;
+
+#ifdef DD_DEBUG
+    assert(table->subtableZ[x].keys > 0);
+#endif
+
+    moveDown = NULL;
+    moveUp = NULL;
+
+    if (x == xLow) {
+        moveDown = cuddZddLinearDown(table, x, xHigh, NULL);
+        /* At this point x --> xHigh. */
+        if (moveDown == (Move *) CUDD_OUT_OF_MEM)
+            goto cuddZddLinearAuxOutOfMem;
+        /* Move backward and stop at best position. */
+        result = cuddZddLinearBackward(table, initial_size, moveDown);
+        if (!result)
+            goto cuddZddLinearAuxOutOfMem;
+
+    } else if (x == xHigh) {
+        moveUp = cuddZddLinearUp(table, x, xLow, NULL);
+        /* At this point x --> xLow. */
+        if (moveUp == (Move *) CUDD_OUT_OF_MEM)
+            goto cuddZddLinearAuxOutOfMem;
+        /* Move backward and stop at best position. */
+        result = cuddZddLinearBackward(table, initial_size, moveUp);
+        if (!result)
+            goto cuddZddLinearAuxOutOfMem;
+
+    } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
+        moveDown = cuddZddLinearDown(table, x, xHigh, NULL);
+        /* At this point x --> xHigh. */
+        if (moveDown == (Move *) CUDD_OUT_OF_MEM)
+            goto cuddZddLinearAuxOutOfMem;
+        moveUp = cuddZddUndoMoves(table,moveDown);
+#ifdef DD_DEBUG
+        assert(moveUp == NULL || moveUp->x == x);
+#endif
+        moveUp = cuddZddLinearUp(table, x, xLow, moveUp);
+        if (moveUp == (Move *) CUDD_OUT_OF_MEM)
+            goto cuddZddLinearAuxOutOfMem;
+        /* Move backward and stop at best position. */
+        result = cuddZddLinearBackward(table, initial_size, moveUp);
+        if (!result)
+            goto cuddZddLinearAuxOutOfMem;
+
+    } else {
+        moveUp = cuddZddLinearUp(table, x, xLow, NULL);
+        /* At this point x --> xHigh. */
+        if (moveUp == (Move *) CUDD_OUT_OF_MEM)
+            goto cuddZddLinearAuxOutOfMem;
+        /* Then move up. */
+        moveDown = cuddZddUndoMoves(table,moveUp);
+#ifdef DD_DEBUG
+        assert(moveDown == NULL || moveDown->y == x);
+#endif
+        moveDown = cuddZddLinearDown(table, x, xHigh, moveDown);
+        if (moveDown == (Move *) CUDD_OUT_OF_MEM)
+            goto cuddZddLinearAuxOutOfMem;
+        /* Move backward and stop at best position. */
+        result = cuddZddLinearBackward(table, initial_size, moveDown);
+        if (!result)
+            goto cuddZddLinearAuxOutOfMem;
+    }
+
+    while (moveDown != NULL) {
+        move = moveDown->next;
+        cuddDeallocMove(table, moveDown);
+        moveDown = move;
+    }
+    while (moveUp != NULL) {
+        move = moveUp->next;
+        cuddDeallocMove(table, moveUp);
+        moveUp = move;
+    }
+
+    return(1);
+
+cuddZddLinearAuxOutOfMem:
+    if (moveDown != (Move *) CUDD_OUT_OF_MEM) {
+        while (moveDown != NULL) {
+            move = moveDown->next;
+            cuddDeallocMove(table, moveDown);
+            moveDown = move;
+        }
+    }
+    if (moveUp != (Move *) CUDD_OUT_OF_MEM) {
+        while (moveUp != NULL) {
+            move = moveUp->next;
+            cuddDeallocMove(table, moveUp);
+            moveUp = move;
+        }
+    }
+
+    return(0);
+
+} /* end of cuddZddLinearAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts a variable up applying the XOR transformation.]
+
+  Description [Sifts a variable up applying the XOR
+  transformation. Moves y up until either it reaches the bound (xLow)
+  or the size of the ZDD heap increases too much.  Returns the set of
+  moves in case of success; NULL if memory is full.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+cuddZddLinearUp(
+  DdManager * table,
+  int  y,
+  int  xLow,
+  Move * prevMoves)
+{
+    Move        *moves;
+    Move        *move;
+    int         x;
+    int         size, newsize;
+    int         limitSize;
+
+    moves = prevMoves;
+    limitSize = table->keysZ;
+
+    x = cuddZddNextLow(table, y);
+    while (x >= xLow) {
+        size = cuddZddSwapInPlace(table, x, y);
+        if (size == 0)
+            goto cuddZddLinearUpOutOfMem;
+        newsize = cuddZddLinearInPlace(table, x, y);
+        if (newsize == 0)
+            goto cuddZddLinearUpOutOfMem;
+        move = (Move *) cuddDynamicAllocNode(table);
+        if (move == NULL)
+            goto cuddZddLinearUpOutOfMem;
+        move->x = x;
+        move->y = y;
+        move->next = moves;
+        moves = move;
+        move->flags = CUDD_SWAP_MOVE;
+        if (newsize > size) {
+            /* Undo transformation. The transformation we apply is
+            ** its own inverse. Hence, we just apply the transformation
+            ** again.
+            */
+            newsize = cuddZddLinearInPlace(table,x,y);
+            if (newsize == 0) goto cuddZddLinearUpOutOfMem;
+#ifdef DD_DEBUG
+            if (newsize != size) {
+                (void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize);
+            }
+#endif
+        } else {
+            size = newsize;
+            move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
+        }
+        move->size = size;
+
+        if ((double)size > (double)limitSize * table->maxGrowth)
+            break;
+        if (size < limitSize)
+            limitSize = size;
+
+        y = x;
+        x = cuddZddNextLow(table, y);
+    }
+    return(moves);
+
+cuddZddLinearUpOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return((Move *) CUDD_OUT_OF_MEM);
+
+} /* end of cuddZddLinearUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts a variable down and applies the XOR transformation.]
+
+  Description [Sifts a variable down. Moves x down until either it
+  reaches the bound (xHigh) or the size of the ZDD heap increases too
+  much. Returns the set of moves in case of success; NULL if memory is
+  full.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+cuddZddLinearDown(
+  DdManager * table,
+  int  x,
+  int  xHigh,
+  Move * prevMoves)
+{
+    Move        *moves;
+    Move        *move;
+    int         y;
+    int         size, newsize;
+    int         limitSize;
+
+    moves = prevMoves;
+    limitSize = table->keysZ;
+
+    y = cuddZddNextHigh(table, x);
+    while (y <= xHigh) {
+        size = cuddZddSwapInPlace(table, x, y);
+        if (size == 0)
+            goto cuddZddLinearDownOutOfMem;
+        newsize = cuddZddLinearInPlace(table, x, y);
+        if (newsize == 0)
+            goto cuddZddLinearDownOutOfMem;
+        move = (Move *) cuddDynamicAllocNode(table);
+        if (move == NULL)
+            goto cuddZddLinearDownOutOfMem;
+        move->x = x;
+        move->y = y;
+        move->next = moves;
+        moves = move;
+        move->flags = CUDD_SWAP_MOVE;
+        if (newsize > size) {
+            /* Undo transformation. The transformation we apply is
+            ** its own inverse. Hence, we just apply the transformation
+            ** again.
+            */
+            newsize = cuddZddLinearInPlace(table,x,y);
+            if (newsize == 0) goto cuddZddLinearDownOutOfMem;
+            if (newsize != size) {
+                (void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize);
+            }
+        } else {
+            size = newsize;
+            move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
+        }
+        move->size = size;
+
+        if ((double)size > (double)limitSize * table->maxGrowth)
+            break;
+        if (size < limitSize)
+            limitSize = size;
+
+        x = y;
+        y = cuddZddNextHigh(table, x);
+    }
+    return(moves);
+
+cuddZddLinearDownOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return((Move *) CUDD_OUT_OF_MEM);
+
+} /* end of cuddZddLinearDown */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given a set of moves, returns the ZDD heap to the position
+  giving the minimum size.]
+
+  Description [Given a set of moves, returns the ZDD heap to the
+  position giving the minimum size. In case of ties, returns to the
+  closest position giving the minimum size. Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddLinearBackward(
+  DdManager * table,
+  int  size,
+  Move * moves)
+{
+    Move        *move;
+    int         res;
+
+    /* Find the minimum size among moves. */
+    for (move = moves; move != NULL; move = move->next) {
+        if (move->size < size) {
+            size = move->size;
+        }
+    }
+
+    for (move = moves; move != NULL; move = move->next) {
+        if (move->size == size) return(1);
+        if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
+            res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
+            if (!res) return(0);
+        }
+        res = cuddZddSwapInPlace(table, move->x, move->y);
+        if (!res)
+            return(0);
+        if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) {
+            res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
+            if (!res) return(0);
+        }
+    }
+
+    return(1);
+
+} /* end of cuddZddLinearBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given a set of moves, returns the ZDD heap to the order
+  in effect before the moves.]
+
+  Description [Given a set of moves, returns the ZDD heap to the
+  order in effect before the moves.  Returns 1 in case of success;
+  0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move*
+cuddZddUndoMoves(
+  DdManager * table,
+  Move * moves)
+{
+    Move *invmoves = NULL;
+    Move *move;
+    Move *invmove;
+    int size;
+
+    for (move = moves; move != NULL; move = move->next) {
+        invmove = (Move *) cuddDynamicAllocNode(table);
+        if (invmove == NULL) goto cuddZddUndoMovesOutOfMem;
+        invmove->x = move->x;
+        invmove->y = move->y;
+        invmove->next = invmoves;
+        invmoves = invmove;
+        if (move->flags == CUDD_SWAP_MOVE) {
+            invmove->flags = CUDD_SWAP_MOVE;
+            size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
+            if (!size) goto cuddZddUndoMovesOutOfMem;
+        } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
+            invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE;
+            size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
+            if (!size) goto cuddZddUndoMovesOutOfMem;
+            size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
+            if (!size) goto cuddZddUndoMovesOutOfMem;
+        } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */
+#ifdef DD_DEBUG
+            (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n");
+#endif
+            invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE;
+            size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
+            if (!size) goto cuddZddUndoMovesOutOfMem;
+            size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
+            if (!size) goto cuddZddUndoMovesOutOfMem;
+        }
+        invmove->size = size;
+    }
+
+    return(invmoves);
+
+cuddZddUndoMovesOutOfMem:
+    while (invmoves != NULL) {
+        move = invmoves->next;
+        cuddDeallocMove(table, invmoves);
+        invmoves = move;
+    }
+    return((Move *) CUDD_OUT_OF_MEM);
+
+} /* end of cuddZddUndoMoves */
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddZddMisc.c b/abc-build/src/bdd/cudd/cuddZddMisc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddZddMisc.c
@@ -0,0 +1,286 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddMisc.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Miscellaneous utility functions for ZDDs.]
+
+  Description [External procedures included in this module:
+                    <ul>
+                    <li> Cudd_zddDagSize()
+                    <li> Cudd_zddCountMinterm()
+                    <li> Cudd_zddPrintSubtable()
+                    </ul>
+               Internal procedures included in this module:
+                    <ul>
+                    </ul>
+               Static procedures included in this module:
+                    <ul>
+                    <li> cuddZddDagInt()
+                    </ul>
+              ]
+
+  SeeAlso     []
+
+  Author      [Hyong-Kyoon Shin, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include <math.h>
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddMisc.c,v 1.16 2009/02/20 02:14:58 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int cuddZddDagInt (DdNode *n, st__table *tab);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of nodes in a ZDD.]
+
+  Description [Counts the number of nodes in a ZDD. This function
+  duplicates Cudd_DagSize and is only retained for compatibility.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DagSize]
+
+******************************************************************************/
+int
+Cudd_zddDagSize(
+  DdNode * p_node)
+{
+
+    int         i;
+    st__table    *table;
+
+    table = st__init_table( st__ptrcmp, st__ptrhash);
+    i = cuddZddDagInt(p_node, table);
+    st__free_table(table);
+    return(i);
+
+} /* end of Cudd_zddDagSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of minterms of a ZDD.]
+
+  Description [Counts the number of minterms of the ZDD rooted at
+  <code>node</code>. This procedure takes a parameter
+  <code>path</code> that specifies how many variables are in the
+  support of the function. If the procedure runs out of memory, it
+  returns (double) CUDD_OUT_OF_MEM.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddCountDouble]
+
+******************************************************************************/
+double
+Cudd_zddCountMinterm(
+  DdManager * zdd,
+  DdNode * node,
+  int  path)
+{
+    double      dc_var, minterms;
+
+    dc_var = (double)((double)(zdd->sizeZ) - (double)path);
+    minterms = Cudd_zddCountDouble(zdd, node) / pow(2.0, dc_var);
+    return(minterms);
+
+} /* end of Cudd_zddCountMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the ZDD table.]
+
+  Description [Prints the ZDD table for debugging purposes.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_zddPrintSubtable(
+  DdManager * table)
+{
+    int         i, j;
+    DdNode      *z1, *z1_next, *base;
+    DdSubtable  *ZSubTable;
+
+    base = table->one;
+    for (i = table->sizeZ - 1; i >= 0; i--) {
+        ZSubTable = &(table->subtableZ[i]);
+        printf("subtable[%d]:\n", i);
+        for (j = ZSubTable->slots - 1; j >= 0; j--) {
+            z1 = ZSubTable->nodelist[j];
+            while (z1 != NIL(DdNode)) {
+                (void) fprintf(table->out,
+#if SIZEOF_VOID_P == 8
+                    "ID = 0x%lx\tindex = %u\tr = %u\t",
+                    (ptruint) z1 / (ptruint) sizeof(DdNode),
+                    z1->index, z1->ref);
+#else
+                    "ID = 0x%x\tindex = %hu\tr = %hu\t",
+                    (ptruint) z1 / (ptruint) sizeof(DdNode),
+                    z1->index, z1->ref);
+#endif
+                z1_next = cuddT(z1);
+                if (Cudd_IsConstant(z1_next)) {
+                    (void) fprintf(table->out, "T = %d\t\t",
+                        (z1_next == base));
+                }
+                else {
+#if SIZEOF_VOID_P == 8
+                    (void) fprintf(table->out, "T = 0x%lx\t",
+                        (ptruint) z1_next / (ptruint) sizeof(DdNode));
+#else
+                    (void) fprintf(table->out, "T = 0x%x\t",
+                        (ptruint) z1_next / (ptruint) sizeof(DdNode));
+#endif
+                }
+                z1_next = cuddE(z1);
+                if (Cudd_IsConstant(z1_next)) {
+                    (void) fprintf(table->out, "E = %d\n",
+                        (z1_next == base));
+                }
+                else {
+#if SIZEOF_VOID_P == 8
+                    (void) fprintf(table->out, "E = 0x%lx\n",
+                        (ptruint) z1_next / (ptruint) sizeof(DdNode));
+#else
+                    (void) fprintf(table->out, "E = 0x%x\n",
+                        (ptruint) z1_next / (ptruint) sizeof(DdNode));
+#endif
+                }
+
+                z1_next = z1->next;
+                z1 = z1_next;
+            }
+        }
+    }
+    putchar('\n');
+
+} /* Cudd_zddPrintSubtable */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddDagSize.]
+
+  Description [Performs the recursive step of Cudd_zddDagSize. Does
+  not check for out-of-memory conditions.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddDagInt(
+  DdNode * n,
+  st__table * tab)
+{
+    if (n == NIL(DdNode))
+        return(0);
+
+    if ( st__is_member(tab, (char *)n) == 1)
+        return(0);
+
+    if (Cudd_IsConstant(n))
+        return(0);
+
+    (void) st__insert(tab, (char *)n, NIL(char));
+    return(1 + cuddZddDagInt(cuddT(n), tab) +
+        cuddZddDagInt(cuddE(n), tab));
+
+} /* cuddZddDagInt */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/cuddZddPort.c b/abc-build/src/bdd/cudd/cuddZddPort.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddZddPort.c
@@ -0,0 +1,389 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddPort.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions that translate BDDs to ZDDs.]
+
+  Description [External procedures included in this module:
+                    <ul>
+                    <li> Cudd_zddPortFromBdd()
+                    <li> Cudd_zddPortToBdd()
+                    </ul>
+               Internal procedures included in this module:
+                    <ul>
+                    </ul>
+               Static procedures included in this module:
+                    <ul>
+                    <li> zddPortFromBddStep()
+                    <li> zddPortToBddStep()
+                    </ul>
+              ]
+
+  SeeAlso     []
+
+  Author      [Hyong-kyoon Shin, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddPort.c,v 1.13 2004/08/13 18:04:53 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * zddPortFromBddStep (DdManager *dd, DdNode *B, int expected);
+static DdNode * zddPortToBddStep (DdManager *dd, DdNode *f, int depth);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Converts a BDD into a ZDD.]
+
+  Description [Converts a BDD into a ZDD. This function assumes that
+  there is a one-to-one correspondence between the BDD variables and the
+  ZDD variables, and that the variable order is the same for both types
+  of variables. These conditions are established if the ZDD variables
+  are created by one call to Cudd_zddVarsFromBddVars with multiplicity =
+  1. Returns a pointer to the resulting ZDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddVarsFromBddVars]
+
+******************************************************************************/
+DdNode *
+Cudd_zddPortFromBdd(
+  DdManager * dd,
+  DdNode * B)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = zddPortFromBddStep(dd,B,0);
+    } while (dd->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_zddPortFromBdd */
+
+
+/**Function********************************************************************
+
+  Synopsis [Converts a ZDD into a BDD.]
+
+  Description [Converts a ZDD into a BDD. Returns a pointer to the resulting
+  ZDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddPortFromBdd]
+
+******************************************************************************/
+DdNode *
+Cudd_zddPortToBdd(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = zddPortToBddStep(dd,f,0);
+    } while (dd->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_zddPortToBdd */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddPortFromBdd.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+zddPortFromBddStep(
+  DdManager * dd,
+  DdNode * B,
+  int  expected)
+{
+    DdNode      *res, *prevZdd, *t, *e;
+    DdNode      *Breg, *Bt, *Be;
+    int         id, level;
+
+    statLine(dd);
+    /* Terminal cases. */
+    if (B == Cudd_Not(DD_ONE(dd)))
+        return(DD_ZERO(dd));
+    if (B == DD_ONE(dd)) {
+        if (expected >= dd->sizeZ) {
+            return(DD_ONE(dd));
+        } else {
+            return(dd->univ[expected]);
+        }
+    }
+
+    Breg = Cudd_Regular(B);
+
+    /* Computed table look-up. */
+    res = cuddCacheLookup1Zdd(dd,Cudd_zddPortFromBdd,B);
+    if (res != NULL) {
+        level = cuddI(dd,Breg->index);
+        /* Adding DC vars. */
+        if (expected < level) {
+            /* Add suppressed variables. */
+            cuddRef(res);
+            for (level--; level >= expected; level--) {
+                prevZdd = res;
+                id = dd->invperm[level];
+                res = cuddZddGetNode(dd, id, prevZdd, prevZdd);
+                if (res == NULL) {
+                    Cudd_RecursiveDerefZdd(dd, prevZdd);
+                    return(NULL);
+                }
+                cuddRef(res);
+                Cudd_RecursiveDerefZdd(dd, prevZdd);
+            }
+            cuddDeref(res);
+        }
+        return(res);
+    }   /* end of cache look-up */
+
+    if (Cudd_IsComplement(B)) {
+        Bt = Cudd_Not(cuddT(Breg));
+        Be = Cudd_Not(cuddE(Breg));
+    } else {
+        Bt = cuddT(Breg);
+        Be = cuddE(Breg);
+    }
+
+    id = Breg->index;
+    level = cuddI(dd,id);
+    t = zddPortFromBddStep(dd, Bt, level+1);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+    e = zddPortFromBddStep(dd, Be, level+1);
+    if (e == NULL) {
+        Cudd_RecursiveDerefZdd(dd, t);
+        return(NULL);
+    }
+    cuddRef(e);
+    res = cuddZddGetNode(dd, id, t, e);
+    if (res == NULL) {
+        Cudd_RecursiveDerefZdd(dd, t);
+        Cudd_RecursiveDerefZdd(dd, e);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDerefZdd(dd, t);
+    Cudd_RecursiveDerefZdd(dd, e);
+
+    cuddCacheInsert1(dd,Cudd_zddPortFromBdd,B,res);
+
+    for (level--; level >= expected; level--) {
+        prevZdd = res;
+        id = dd->invperm[level];
+        res = cuddZddGetNode(dd, id, prevZdd, prevZdd);
+        if (res == NULL) {
+            Cudd_RecursiveDerefZdd(dd, prevZdd);
+            return(NULL);
+        }
+        cuddRef(res);
+        Cudd_RecursiveDerefZdd(dd, prevZdd);
+    }
+
+    cuddDeref(res);
+    return(res);
+
+} /* end of zddPortFromBddStep */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddPortToBdd.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+zddPortToBddStep(
+  DdManager * dd /* manager */,
+  DdNode * f /* ZDD to be converted */,
+  int  depth /* recursion depth */)
+{
+    DdNode *one, *zero, *T, *E, *res, *var;
+    unsigned int index;
+    unsigned int level;
+
+    statLine(dd);
+    one = DD_ONE(dd);
+    zero = DD_ZERO(dd);
+    if (f == zero) return(Cudd_Not(one));
+
+    if (depth == dd->sizeZ) return(one);
+
+    index = dd->invpermZ[depth];
+    level = cuddIZ(dd,f->index);
+    var = cuddUniqueInter(dd,index,one,Cudd_Not(one));
+    if (var == NULL) return(NULL);
+    cuddRef(var);
+
+    if (level > (unsigned) depth) {
+        E = zddPortToBddStep(dd,f,depth+1);
+        if (E == NULL) {
+            Cudd_RecursiveDeref(dd,var);
+            return(NULL);
+        }
+        cuddRef(E);
+        res = cuddBddIteRecur(dd,var,Cudd_Not(one),E);
+        if (res == NULL) {
+            Cudd_RecursiveDeref(dd,var);
+            Cudd_RecursiveDeref(dd,E);
+            return(NULL);
+        }
+        cuddRef(res);
+        Cudd_RecursiveDeref(dd,var);
+        Cudd_RecursiveDeref(dd,E);
+        cuddDeref(res);
+        return(res);
+    }
+
+    res = cuddCacheLookup1(dd,Cudd_zddPortToBdd,f);
+    if (res != NULL) {
+        Cudd_RecursiveDeref(dd,var);
+        return(res);
+    }
+
+    T = zddPortToBddStep(dd,cuddT(f),depth+1);
+    if (T == NULL) {
+        Cudd_RecursiveDeref(dd,var);
+        return(NULL);
+    }
+    cuddRef(T);
+    E = zddPortToBddStep(dd,cuddE(f),depth+1);
+    if (E == NULL) {
+        Cudd_RecursiveDeref(dd,var);
+        Cudd_RecursiveDeref(dd,T);
+        return(NULL);
+    }
+    cuddRef(E);
+
+    res = cuddBddIteRecur(dd,var,T,E);
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd,var);
+        Cudd_RecursiveDeref(dd,T);
+        Cudd_RecursiveDeref(dd,E);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd,var);
+    Cudd_RecursiveDeref(dd,T);
+    Cudd_RecursiveDeref(dd,E);
+    cuddDeref(res);
+
+    cuddCacheInsert1(dd,Cudd_zddPortToBdd,f,res);
+
+    return(res);
+
+} /* end of zddPortToBddStep */
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddZddReord.c b/abc-build/src/bdd/cudd/cuddZddReord.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddZddReord.c
@@ -0,0 +1,1668 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddReord.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Procedures for dynamic variable ordering of ZDDs.]
+
+  Description [External procedures included in this module:
+                    <ul>
+                    <li> Cudd_zddReduceHeap()
+                    <li> Cudd_zddShuffleHeap()
+                    </ul>
+               Internal procedures included in this module:
+                    <ul>
+                    <li> cuddZddAlignToBdd()
+                    <li> cuddZddNextHigh()
+                    <li> cuddZddNextLow()
+                    <li> cuddZddUniqueCompare()
+                    <li> cuddZddSwapInPlace()
+                    <li> cuddZddSwapping()
+                    <li> cuddZddSifting()
+                    </ul>
+               Static procedures included in this module:
+                    <ul>
+                    <li> zddSwapAny()
+                    <li> cuddZddSiftingAux()
+                    <li> cuddZddSiftingUp()
+                    <li> cuddZddSiftingDown()
+                    <li> cuddZddSiftingBackward()
+                    <li> zddReorderPreprocess()
+                    <li> zddReorderPostprocess()
+                    <li> zddShuffle()
+                    <li> zddSiftUp()
+                    </ul>
+              ]
+
+  SeeAlso     []
+
+  Author      [Hyong-Kyoon Shin, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DD_MAX_SUBTABLE_SPARSITY 8
+#define DD_SHRINK_FACTOR 2
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddReord.c,v 1.47 2004/08/13 18:04:53 fabio Exp $";
+#endif
+
+int     *zdd_entry;
+
+int     zddTotalNumberSwapping;
+
+static  DdNode  *empty;
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static Move * zddSwapAny (DdManager *table, int x, int y);
+static int cuddZddSiftingAux (DdManager *table, int x, int x_low, int x_high);
+static Move * cuddZddSiftingUp (DdManager *table, int x, int x_low, int initial_size);
+static Move * cuddZddSiftingDown (DdManager *table, int x, int x_high, int initial_size);
+static int cuddZddSiftingBackward (DdManager *table, Move *moves, int size);
+static void zddReorderPreprocess (DdManager *table);
+static int zddReorderPostprocess (DdManager *table);
+static int zddShuffle (DdManager *table, int *permutation);
+static int zddSiftUp (DdManager *table, int x, int xLow);
+static void zddFixTree (DdManager *table, MtrNode *treenode);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Main dynamic reordering routine for ZDDs.]
+
+  Description [Main dynamic reordering routine for ZDDs.
+  Calls one of the possible reordering procedures:
+  <ul>
+  <li>Swapping
+  <li>Sifting
+  <li>Symmetric Sifting
+  </ul>
+
+  For sifting and symmetric sifting it is possible to request reordering
+  to convergence.<p>
+
+  The core of all methods is the reordering procedure
+  cuddZddSwapInPlace() which swaps two adjacent variables.
+  Returns 1 in case of success; 0 otherwise. In the case of symmetric
+  sifting (with and without convergence) returns 1 plus the number of
+  symmetric variables, in case of success.]
+
+  SideEffects [Changes the variable order for all ZDDs and clears
+  the cache.]
+
+******************************************************************************/
+int
+Cudd_zddReduceHeap(
+  DdManager * table /* DD manager */,
+  Cudd_ReorderingType heuristic /* method used for reordering */,
+  int minsize /* bound below which no reordering occurs */)
+{
+    DdHook       *hook;
+    int          result;
+    unsigned int nextDyn;
+#ifdef DD_STATS
+    unsigned int initialSize;
+    unsigned int finalSize;
+#endif
+    long         localTime;
+
+    /* Don't reorder if there are too many dead nodes. */
+    if (table->keysZ - table->deadZ < (unsigned) minsize)
+        return(1);
+
+    if (heuristic == CUDD_REORDER_SAME) {
+        heuristic = table->autoMethodZ;
+    }
+    if (heuristic == CUDD_REORDER_NONE) {
+        return(1);
+    }
+
+    /* This call to Cudd_zddReduceHeap does initiate reordering. Therefore
+    ** we count it.
+    */
+    table->reorderings++;
+    empty = table->zero;
+
+    localTime = util_cpu_time();
+
+    /* Run the hook functions. */
+    hook = table->preReorderingHook;
+    while (hook != NULL) {
+        int res = (hook->f)(table, "ZDD", (void *)heuristic);
+        if (res == 0) return(0);
+        hook = hook->next;
+    }
+
+    /* Clear the cache and collect garbage. */
+    zddReorderPreprocess(table);
+    zddTotalNumberSwapping = 0;
+
+#ifdef DD_STATS
+    initialSize = table->keysZ;
+
+    switch(heuristic) {
+    case CUDD_REORDER_RANDOM:
+    case CUDD_REORDER_RANDOM_PIVOT:
+        (void) fprintf(table->out,"#:I_RANDOM  ");
+        break;
+    case CUDD_REORDER_SIFT:
+    case CUDD_REORDER_SIFT_CONVERGE:
+    case CUDD_REORDER_SYMM_SIFT:
+    case CUDD_REORDER_SYMM_SIFT_CONV:
+        (void) fprintf(table->out,"#:I_SIFTING ");
+        break;
+    case CUDD_REORDER_LINEAR:
+    case CUDD_REORDER_LINEAR_CONVERGE:
+        (void) fprintf(table->out,"#:I_LINSIFT ");
+        break;
+    default:
+        (void) fprintf(table->err,"Unsupported ZDD reordering method\n");
+        return(0);
+    }
+    (void) fprintf(table->out,"%8d: initial size",initialSize); 
+#endif
+
+    result = cuddZddTreeSifting(table,heuristic);
+
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n");
+    finalSize = table->keysZ;
+    (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize); 
+    (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n",
+                   ((double)(util_cpu_time() - localTime)/1000.0)); 
+    (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n",
+                   zddTotalNumberSwapping);
+#endif
+
+    if (result == 0)
+        return(0);
+
+    if (!zddReorderPostprocess(table))
+        return(0);
+
+    if (table->realignZ) {
+        if (!cuddBddAlignToZdd(table))
+            return(0);
+    }
+
+    nextDyn = table->keysZ * DD_DYN_RATIO;
+    if (table->reorderings < 20 || nextDyn > table->nextDyn)
+        table->nextDyn = nextDyn;
+    else
+        table->nextDyn += 20;
+
+    table->reordered = 1;
+
+    /* Run hook functions. */
+    hook = table->postReorderingHook;
+    while (hook != NULL) {
+        int res = (hook->f)(table, "ZDD", (void *)localTime);
+        if (res == 0) return(0);
+        hook = hook->next;
+    }
+    /* Update cumulative reordering time. */
+    table->reordTime += util_cpu_time() - localTime;
+
+    return(result);
+
+} /* end of Cudd_zddReduceHeap */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders ZDD variables according to given permutation.]
+
+  Description [Reorders ZDD variables according to given permutation.
+  The i-th entry of the permutation array contains the index of the variable
+  that should be brought to the i-th level.  The size of the array should be
+  equal or greater to the number of variables currently in use.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [Changes the ZDD variable order for all diagrams and clears
+  the cache.]
+
+  SeeAlso [Cudd_zddReduceHeap]
+
+******************************************************************************/
+int
+Cudd_zddShuffleHeap(
+  DdManager * table /* DD manager */,
+  int * permutation /* required variable permutation */)
+{
+
+    int result;
+
+    empty = table->zero;
+    zddReorderPreprocess(table);
+
+    result = zddShuffle(table,permutation);
+
+    if (!zddReorderPostprocess(table)) return(0);
+
+    return(result);
+
+} /* end of Cudd_zddShuffleHeap */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders ZDD variables according to the order of the BDD
+  variables.]
+
+  Description [Reorders ZDD variables according to the order of the
+  BDD variables. This function can be called at the end of BDD
+  reordering to insure that the order of the ZDD variables is
+  consistent with the order of the BDD variables. The number of ZDD
+  variables must be a multiple of the number of BDD variables. Let
+  <code>M</code> be the ratio of the two numbers. cuddZddAlignToBdd
+  then considers the ZDD variables from <code>M*i</code> to
+  <code>(M+1)*i-1</code> as corresponding to BDD variable
+  <code>i</code>.  This function should be normally called from
+  Cudd_ReduceHeap, which clears the cache.  Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [Changes the ZDD variable order for all diagrams and performs
+  garbage collection of the ZDD unique table.]
+
+  SeeAlso [Cudd_zddShuffleHeap Cudd_ReduceHeap]
+
+******************************************************************************/
+int
+cuddZddAlignToBdd(
+  DdManager * table /* DD manager */)
+{
+    int *invpermZ;              /* permutation array */
+    int M;                      /* ratio of ZDD variables to BDD variables */
+    int i,j;                    /* loop indices */
+    int result;                 /* return value */
+
+    /* We assume that a ratio of 0 is OK. */
+    if (table->sizeZ == 0)
+        return(1);
+
+    empty = table->zero;
+    M = table->sizeZ / table->size;
+    /* Check whether the number of ZDD variables is a multiple of the
+    ** number of BDD variables.
+    */
+    if (M * table->size != table->sizeZ)
+        return(0);
+    /* Create and initialize the inverse permutation array. */
+    invpermZ = ABC_ALLOC(int,table->sizeZ);
+    if (invpermZ == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    for (i = 0; i < table->size; i++) {
+        int index = table->invperm[i];
+        int indexZ = index * M;
+        int levelZ = table->permZ[indexZ];
+        levelZ = (levelZ / M) * M;
+        for (j = 0; j < M; j++) {
+            invpermZ[M * i + j] = table->invpermZ[levelZ + j];
+        }
+    }
+    /* Eliminate dead nodes. Do not scan the cache again, because we
+    ** assume that Cudd_ReduceHeap has already cleared it.
+    */
+    cuddGarbageCollect(table,0);
+
+    result = zddShuffle(table, invpermZ);
+    ABC_FREE(invpermZ);
+    /* Fix the ZDD variable group tree. */
+    zddFixTree(table,table->treeZ);
+    return(result);
+    
+} /* end of cuddZddAlignToBdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the next subtable with a larger index.]
+
+  Description [Finds the next subtable with a larger index. Returns the
+  index.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddNextHigh(
+  DdManager * table,
+  int  x)
+{
+    return(x + 1);
+
+} /* end of cuddZddNextHigh */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the next subtable with a smaller index.]
+
+  Description [Finds the next subtable with a smaller index. Returns the
+  index.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddNextLow(
+  DdManager * table,
+  int  x)
+{
+    return(x - 1);
+
+} /* end of cuddZddNextLow */
+
+
+/**Function********************************************************************
+
+  Synopsis [Comparison function used by qsort.]
+
+  Description [Comparison function used by qsort to order the
+  variables according to the number of keys in the subtables.
+  Returns the difference in number of keys between the two
+  variables being compared.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddUniqueCompare(
+  int * ptr_x,
+  int * ptr_y)
+{
+    return(zdd_entry[*ptr_y] - zdd_entry[*ptr_x]);
+
+} /* end of cuddZddUniqueCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Swaps two adjacent variables.]
+
+  Description [Swaps two adjacent variables. It assumes that no dead
+  nodes are present on entry to this procedure.  The procedure then
+  guarantees that no dead nodes will be present when it terminates.
+  cuddZddSwapInPlace assumes that x &lt; y.  Returns the number of keys in
+  the table if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddSwapInPlace(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    DdNodePtr   *xlist, *ylist;
+    int         xindex, yindex;
+    int         xslots, yslots;
+    int         xshift, yshift;
+    int         oldxkeys, oldykeys;
+    int         newxkeys, newykeys;
+    int         i;
+    int         posn;
+    DdNode      *f, *f1, *f0, *f11, *f10, *f01, *f00;
+    DdNode      *newf1=NULL, *newf0, *next;
+    DdNodePtr   g, *lastP, *previousP;
+
+#ifdef DD_DEBUG
+    assert(x < y);
+    assert(cuddZddNextHigh(table,x) == y);
+    assert(table->subtableZ[x].keys != 0);
+    assert(table->subtableZ[y].keys != 0);
+    assert(table->subtableZ[x].dead == 0);
+    assert(table->subtableZ[y].dead == 0);
+#endif
+
+    zddTotalNumberSwapping++;
+
+    /* Get parameters of x subtable. */
+    xindex   = table->invpermZ[x];
+    xlist    = table->subtableZ[x].nodelist;
+    oldxkeys = table->subtableZ[x].keys;
+    xslots   = table->subtableZ[x].slots;
+    xshift   = table->subtableZ[x].shift;
+    newxkeys = 0;
+
+    yindex   = table->invpermZ[y];
+    ylist    = table->subtableZ[y].nodelist;
+    oldykeys = table->subtableZ[y].keys;
+    yslots   = table->subtableZ[y].slots;
+    yshift   = table->subtableZ[y].shift;
+    newykeys = oldykeys;
+
+    /* The nodes in the x layer that don't depend on y directly
+    ** will stay there; the others are put in a chain.
+    ** The chain is handled as a FIFO; g points to the beginning and
+    ** last points to the end.
+    */
+
+    g = NULL;
+    lastP = &g;
+    for (i = 0; i < xslots; i++) {
+        previousP = &(xlist[i]);
+        f = *previousP;
+        while (f != NULL) {
+            next = f->next;
+            f1 = cuddT(f); f0 = cuddE(f);
+            if ((f1->index != (DdHalfWord) yindex) &&
+                (f0->index != (DdHalfWord) yindex)) { /* stays */
+                newxkeys++;
+                *previousP = f;
+                previousP = &(f->next);
+            } else {
+                f->index = yindex;
+                *lastP = f;
+                lastP = &(f->next);
+            }
+            f = next;
+        } /* while there are elements in the collision chain */
+        *previousP = NULL;
+    } /* for each slot of the x subtable */
+    *lastP = NULL;
+
+
+#ifdef DD_COUNT
+    table->swapSteps += oldxkeys - newxkeys;
+#endif
+    /* Take care of the x nodes that must be re-expressed.
+    ** They form a linked list pointed by g. Their index has been
+    ** changed to yindex already.
+    */
+    f = g;
+    while (f != NULL) {
+        next = f->next;
+        /* Find f1, f0, f11, f10, f01, f00. */
+        f1 = cuddT(f);
+        if ((int) f1->index == yindex) {
+            f11 = cuddT(f1); f10 = cuddE(f1);
+        } else {
+            f11 = empty; f10 = f1;
+        }
+        f0 = cuddE(f);
+        if ((int) f0->index == yindex) {
+            f01 = cuddT(f0); f00 = cuddE(f0);
+        } else {
+            f01 = empty; f00 = f0;
+        }
+
+        /* Decrease ref count of f1. */
+        cuddSatDec(f1->ref);
+        /* Create the new T child. */
+        if (f11 == empty) {
+            if (f01 != empty) {
+                newf1 = f01;
+                cuddSatInc(newf1->ref);
+            }
+            /* else case was already handled when finding nodes
+            ** with both children below level y
+            */
+        } else {
+            /* Check xlist for triple (xindex, f11, f01). */
+            posn = ddHash(cuddF2L(f11), cuddF2L(f01), xshift);
+            /* For each element newf1 in collision list xlist[posn]. */
+            newf1 = xlist[posn];
+            while (newf1 != NULL) {
+                if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
+                    cuddSatInc(newf1->ref);
+                    break; /* match */
+                }
+                newf1 = newf1->next;
+            } /* while newf1 */
+            if (newf1 == NULL) {        /* no match */
+                newf1 = cuddDynamicAllocNode(table);
+                if (newf1 == NULL)
+                    goto zddSwapOutOfMem;
+                newf1->index = xindex; newf1->ref = 1;
+                cuddT(newf1) = f11;
+                cuddE(newf1) = f01;
+                /* Insert newf1 in the collision list xlist[pos];
+                ** increase the ref counts of f11 and f01
+                */
+                newxkeys++;
+                newf1->next = xlist[posn];
+                xlist[posn] = newf1;
+                cuddSatInc(f11->ref);
+                cuddSatInc(f01->ref);
+            }
+        }
+        cuddT(f) = newf1;
+
+        /* Do the same for f0. */
+        /* Decrease ref count of f0. */
+        cuddSatDec(f0->ref);
+        /* Create the new E child. */
+        if (f10 == empty) {
+            newf0 = f00;
+            cuddSatInc(newf0->ref);
+        } else {
+            /* Check xlist for triple (xindex, f10, f00). */
+            posn = ddHash(cuddF2L(f10), cuddF2L(f00), xshift);
+            /* For each element newf0 in collision list xlist[posn]. */
+            newf0 = xlist[posn];
+            while (newf0 != NULL) {
+                if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
+                    cuddSatInc(newf0->ref);
+                    break; /* match */
+                }
+                newf0 = newf0->next;
+            } /* while newf0 */
+            if (newf0 == NULL) {        /* no match */
+                newf0 = cuddDynamicAllocNode(table);
+                if (newf0 == NULL)
+                    goto zddSwapOutOfMem;
+                newf0->index = xindex; newf0->ref = 1;
+                cuddT(newf0) = f10; cuddE(newf0) = f00;
+                /* Insert newf0 in the collision list xlist[posn];
+                ** increase the ref counts of f10 and f00.
+                */
+                newxkeys++;
+                newf0->next = xlist[posn];
+                xlist[posn] = newf0;
+                cuddSatInc(f10->ref);
+                cuddSatInc(f00->ref);
+            }
+        }
+        cuddE(f) = newf0;
+
+        /* Insert the modified f in ylist.
+        ** The modified f does not already exists in ylist.
+        ** (Because of the uniqueness of the cofactors.)
+        */
+        posn = ddHash(cuddF2L(newf1), cuddF2L(newf0), yshift);
+        newykeys++;
+        f->next = ylist[posn];
+        ylist[posn] = f;
+        f = next;
+    } /* while f != NULL */
+
+    /* GC the y layer. */
+
+    /* For each node f in ylist. */
+    for (i = 0; i < yslots; i++) {
+        previousP = &(ylist[i]);
+        f = *previousP;
+        while (f != NULL) {
+            next = f->next;
+            if (f->ref == 0) {
+                cuddSatDec(cuddT(f)->ref);
+                cuddSatDec(cuddE(f)->ref);
+                cuddDeallocNode(table, f);
+                newykeys--;
+            } else {
+                *previousP = f;
+                previousP = &(f->next);
+            }
+            f = next;
+        } /* while f */
+        *previousP = NULL;
+    } /* for i */
+
+    /* Set the appropriate fields in table. */
+    table->subtableZ[x].nodelist = ylist;
+    table->subtableZ[x].slots    = yslots;
+    table->subtableZ[x].shift    = yshift;
+    table->subtableZ[x].keys     = newykeys;
+    table->subtableZ[x].maxKeys  = yslots * DD_MAX_SUBTABLE_DENSITY;
+
+    table->subtableZ[y].nodelist = xlist;
+    table->subtableZ[y].slots    = xslots;
+    table->subtableZ[y].shift    = xshift;
+    table->subtableZ[y].keys     = newxkeys;
+    table->subtableZ[y].maxKeys  = xslots * DD_MAX_SUBTABLE_DENSITY;
+
+    table->permZ[xindex] = y; table->permZ[yindex] = x;
+    table->invpermZ[x] = yindex; table->invpermZ[y] = xindex;
+
+    table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys;
+
+    /* Update univ section; univ[x] remains the same. */
+    table->univ[y] = cuddT(table->univ[x]);
+
+    return (table->keysZ);
+
+zddSwapOutOfMem:
+    (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n");
+
+    return (0);
+
+} /* end of cuddZddSwapInPlace */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders variables by a sequence of (non-adjacent) swaps.]
+
+  Description [Implementation of Plessier's algorithm that reorders
+  variables by a sequence of (non-adjacent) swaps.
+    <ol>
+    <li> Select two variables (RANDOM or HEURISTIC).
+    <li> Permute these variables.
+    <li> If the nodes have decreased accept the permutation.
+    <li> Otherwise reconstruct the original heap.
+    <li> Loop.
+    </ol>
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddSwapping(
+  DdManager * table,
+  int lower,
+  int upper,
+  Cudd_ReorderingType heuristic)
+{
+    int i, j;
+    int max, keys;
+    int nvars;
+    int x, y;
+    int iterate;
+    int previousSize;
+    Move *moves, *move;
+    int pivot = -1;
+    int modulo;
+    int result;
+
+#ifdef DD_DEBUG
+    /* Sanity check */
+    assert(lower >= 0 && upper < table->sizeZ && lower <= upper);
+#endif
+
+    nvars = upper - lower + 1;
+    iterate = nvars;
+
+    for (i = 0; i < iterate; i++) {
+        if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
+            /* Find pivot <= id with maximum keys. */
+            for (max = -1, j = lower; j <= upper; j++) {
+                if ((keys = table->subtableZ[j].keys) > max) {
+                    max = keys;
+                    pivot = j;
+                }
+            }
+
+            modulo = upper - pivot;
+            if (modulo == 0) {
+                y = pivot;      /* y = nvars-1 */
+            } else {
+                /* y = random # from {pivot+1 .. nvars-1} */
+                y = pivot + 1 + (int) (Cudd_Random() % modulo);
+            }
+
+            modulo = pivot - lower - 1;
+            if (modulo < 1) {   /* if pivot = 1 or 0 */
+                x = lower;
+            } else {
+                do { /* x = random # from {0 .. pivot-2} */
+                    x = (int) Cudd_Random() % modulo;
+                } while (x == y);
+                  /* Is this condition really needed, since x and y
+                     are in regions separated by pivot? */
+            }
+        } else {
+            x = (int) (Cudd_Random() % nvars) + lower;
+            do {
+                y = (int) (Cudd_Random() % nvars) + lower;
+            } while (x == y);
+        }
+
+        previousSize = table->keysZ;
+        moves = zddSwapAny(table, x, y);
+        if (moves == NULL)
+            goto cuddZddSwappingOutOfMem;
+
+        result = cuddZddSiftingBackward(table, moves, previousSize);
+        if (!result)
+            goto cuddZddSwappingOutOfMem;
+
+        while (moves != NULL) {
+            move = moves->next;
+            cuddDeallocMove(table, moves);
+            moves = move;
+        }
+#ifdef DD_STATS
+        if (table->keysZ < (unsigned) previousSize) {
+            (void) fprintf(table->out,"-");
+        } else if (table->keysZ > (unsigned) previousSize) {
+            (void) fprintf(table->out,"+");     /* should never happen */
+        } else {
+            (void) fprintf(table->out,"=");
+        }
+        fflush(table->out);
+#endif
+    }
+
+    return(1);
+
+cuddZddSwappingOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return(0);
+
+} /* end of cuddZddSwapping */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implementation of Rudell's sifting algorithm.]
+
+  Description [Implementation of Rudell's sifting algorithm.
+  Assumes that no dead nodes are present.
+    <ol>
+    <li> Order all the variables according to the number of entries
+    in each unique table.
+    <li> Sift the variable up and down, remembering each time the
+    total size of the DD heap.
+    <li> Select the best permutation.
+    <li> Repeat 3 and 4 for all variables.
+    </ol>
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddSifting(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int i;
+    int *var;
+    int size;
+    int x;
+    int result;
+#ifdef DD_STATS
+    int previousSize;
+#endif
+
+    size = table->sizeZ;
+
+    /* Find order in which to sift variables. */
+    var = NULL;
+    zdd_entry = ABC_ALLOC(int, size);
+    if (zdd_entry == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto cuddZddSiftingOutOfMem;
+    }
+    var = ABC_ALLOC(int, size);
+    if (var == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto cuddZddSiftingOutOfMem;
+    }
+
+    for (i = 0; i < size; i++) {
+        x = table->permZ[i];
+        zdd_entry[i] = table->subtableZ[x].keys;
+        var[i] = i;
+    }
+
+    qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
+
+    /* Now sift. */
+    for (i = 0; i < ddMin(table->siftMaxVar, size); i++) {
+        if (zddTotalNumberSwapping >= table->siftMaxSwap)
+            break;
+        x = table->permZ[var[i]];
+        if (x < lower || x > upper) continue;
+#ifdef DD_STATS
+        previousSize = table->keysZ;
+#endif
+        result = cuddZddSiftingAux(table, x, lower, upper);
+        if (!result)
+            goto cuddZddSiftingOutOfMem;
+#ifdef DD_STATS
+        if (table->keysZ < (unsigned) previousSize) {
+            (void) fprintf(table->out,"-");
+        } else if (table->keysZ > (unsigned) previousSize) {
+            (void) fprintf(table->out,"+");     /* should never happen */
+            (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]);
+        } else {
+            (void) fprintf(table->out,"=");
+        }
+        fflush(table->out);
+#endif
+    }
+
+    ABC_FREE(var);
+    ABC_FREE(zdd_entry);
+
+    return(1);
+
+cuddZddSiftingOutOfMem:
+
+    if (zdd_entry != NULL) ABC_FREE(zdd_entry);
+    if (var != NULL) ABC_FREE(var);
+
+    return(0);
+
+} /* end of cuddZddSifting */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Swaps any two variables.]
+
+  Description [Swaps any two variables. Returns the set of moves.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+zddSwapAny(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    Move        *move, *moves;
+    int         tmp, size;
+    int         x_ref, y_ref;
+    int         x_next, y_next;
+    int         limit_size;
+
+    if (x > y) {        /* make x precede y */
+        tmp = x; x = y; y = tmp;
+    }
+
+    x_ref = x; y_ref = y;
+
+    x_next = cuddZddNextHigh(table, x);
+    y_next = cuddZddNextLow(table, y);
+    moves = NULL;
+    limit_size = table->keysZ;
+
+    for (;;) {
+        if (x_next == y_next) { /* x < x_next = y_next < y */
+            size = cuddZddSwapInPlace(table, x, x_next);
+            if (size == 0)
+                goto zddSwapAnyOutOfMem;
+            move = (Move *) cuddDynamicAllocNode(table);
+            if (move == NULL)
+                goto zddSwapAnyOutOfMem;
+            move->x = x;
+            move->y = x_next;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+
+            size = cuddZddSwapInPlace(table, y_next, y);
+            if (size == 0)
+                goto zddSwapAnyOutOfMem;
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL)
+                goto zddSwapAnyOutOfMem;
+            move->x = y_next;
+            move->y = y;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+
+            size = cuddZddSwapInPlace(table, x, x_next);
+            if (size == 0)
+                goto zddSwapAnyOutOfMem;
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL)
+                goto zddSwapAnyOutOfMem;
+            move->x = x;
+            move->y = x_next;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+
+            tmp = x; x = y; y = tmp;
+
+        } else if (x == y_next) { /* x = y_next < y = x_next */
+            size = cuddZddSwapInPlace(table, x, x_next);
+            if (size == 0)
+                goto zddSwapAnyOutOfMem;
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL)
+                goto zddSwapAnyOutOfMem;
+            move->x = x;
+            move->y = x_next;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+
+            tmp = x; x = y;  y = tmp;
+        } else {
+            size = cuddZddSwapInPlace(table, x, x_next);
+            if (size == 0)
+                goto zddSwapAnyOutOfMem;
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL)
+                goto zddSwapAnyOutOfMem;
+            move->x = x;
+            move->y = x_next;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+
+            size = cuddZddSwapInPlace(table, y_next, y);
+            if (size == 0)
+                goto zddSwapAnyOutOfMem;
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL)
+                goto zddSwapAnyOutOfMem;
+            move->x = y_next;
+            move->y = y;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+
+            x = x_next; y = y_next;
+        }
+
+        x_next = cuddZddNextHigh(table, x);
+        y_next = cuddZddNextLow(table, y);
+        if (x_next > y_ref)
+            break;      /* if x == y_ref */
+
+        if ((double) size > table->maxGrowth * (double) limit_size)
+            break;
+        if (size < limit_size)
+            limit_size = size;
+    }
+    if (y_next >= x_ref) {
+        size = cuddZddSwapInPlace(table, y_next, y);
+        if (size == 0)
+            goto zddSwapAnyOutOfMem;
+        move = (Move *)cuddDynamicAllocNode(table);
+        if (move == NULL)
+            goto zddSwapAnyOutOfMem;
+        move->x = y_next;
+        move->y = y;
+        move->size = size;
+        move->next = moves;
+        moves = move;
+    }
+
+    return(moves);
+
+zddSwapAnyOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return(NULL);
+
+} /* end of zddSwapAny */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries.]
+
+  Description [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries. Finds the best position and does the required changes.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddSiftingAux(
+  DdManager * table,
+  int  x,
+  int  x_low,
+  int  x_high)
+{
+    Move        *move;
+    Move        *moveUp;        /* list of up move */
+    Move        *moveDown;      /* list of down move */
+
+    int         initial_size;
+    int         result;
+
+    initial_size = table->keysZ;
+
+#ifdef DD_DEBUG
+    assert(table->subtableZ[x].keys > 0);
+#endif
+
+    moveDown = NULL;
+    moveUp = NULL;
+
+    if (x == x_low) {
+        moveDown = cuddZddSiftingDown(table, x, x_high, initial_size);
+        /* after that point x --> x_high */
+        if (moveDown == NULL)
+            goto cuddZddSiftingAuxOutOfMem;
+        result = cuddZddSiftingBackward(table, moveDown,
+            initial_size);
+        /* move backward and stop at best position */
+        if (!result)
+            goto cuddZddSiftingAuxOutOfMem;
+
+    }
+    else if (x == x_high) {
+        moveUp = cuddZddSiftingUp(table, x, x_low, initial_size);
+        /* after that point x --> x_low */
+        if (moveUp == NULL)
+            goto cuddZddSiftingAuxOutOfMem;
+        result = cuddZddSiftingBackward(table, moveUp, initial_size);
+        /* move backward and stop at best position */
+        if (!result)
+            goto cuddZddSiftingAuxOutOfMem;
+    }
+    else if ((x - x_low) > (x_high - x)) {
+        /* must go down first:shorter */
+        moveDown = cuddZddSiftingDown(table, x, x_high, initial_size);
+        /* after that point x --> x_high */
+        if (moveDown == NULL)
+            goto cuddZddSiftingAuxOutOfMem;
+        moveUp = cuddZddSiftingUp(table, moveDown->y, x_low,
+            initial_size);
+        if (moveUp == NULL)
+            goto cuddZddSiftingAuxOutOfMem;
+        result = cuddZddSiftingBackward(table, moveUp, initial_size);
+        /* move backward and stop at best position */
+        if (!result)
+            goto cuddZddSiftingAuxOutOfMem;
+    }
+    else {
+        moveUp = cuddZddSiftingUp(table, x, x_low, initial_size);
+        /* after that point x --> x_high */
+        if (moveUp == NULL)
+            goto cuddZddSiftingAuxOutOfMem;
+        moveDown = cuddZddSiftingDown(table, moveUp->x, x_high,
+            initial_size);
+        /* then move up */
+        if (moveDown == NULL)
+            goto cuddZddSiftingAuxOutOfMem;
+        result = cuddZddSiftingBackward(table, moveDown,
+            initial_size);
+        /* move backward and stop at best position */
+        if (!result)
+            goto cuddZddSiftingAuxOutOfMem;
+    }
+
+    while (moveDown != NULL) {
+        move = moveDown->next;
+        cuddDeallocMove(table, moveDown);
+        moveDown = move;
+    }
+    while (moveUp != NULL) {
+        move = moveUp->next;
+        cuddDeallocMove(table, moveUp);
+        moveUp = move;
+    }
+
+    return(1);
+
+cuddZddSiftingAuxOutOfMem:
+    while (moveDown != NULL) {
+        move = moveDown->next;
+        cuddDeallocMove(table, moveDown);
+        moveDown = move;
+    }
+    while (moveUp != NULL) {
+        move = moveUp->next;
+        cuddDeallocMove(table, moveUp);
+        moveUp = move;
+    }
+
+    return(0);
+
+} /* end of cuddZddSiftingAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts a variable up.]
+
+  Description [Sifts a variable up. Moves y up until either it reaches
+  the bound (x_low) or the size of the ZDD heap increases too much.
+  Returns the set of moves in case of success; NULL if memory is full.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+cuddZddSiftingUp(
+  DdManager * table,
+  int  x,
+  int  x_low,
+  int  initial_size)
+{
+    Move        *moves;
+    Move        *move;
+    int         y;
+    int         size;
+    int         limit_size = initial_size;
+
+    moves = NULL;
+    y = cuddZddNextLow(table, x);
+    while (y >= x_low) {
+        size = cuddZddSwapInPlace(table, y, x);
+        if (size == 0)
+            goto cuddZddSiftingUpOutOfMem;
+        move = (Move *)cuddDynamicAllocNode(table);
+        if (move == NULL)
+            goto cuddZddSiftingUpOutOfMem;
+        move->x = y;
+        move->y = x;
+        move->size = size;
+        move->next = moves;
+        moves = move;
+
+        if ((double)size > (double)limit_size * table->maxGrowth)
+            break;
+        if (size < limit_size)
+            limit_size = size;
+
+        x = y;
+        y = cuddZddNextLow(table, x);
+    }
+    return(moves);
+
+cuddZddSiftingUpOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return(NULL);
+
+} /* end of cuddZddSiftingUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts a variable down.]
+
+  Description [Sifts a variable down. Moves x down until either it
+  reaches the bound (x_high) or the size of the ZDD heap increases too
+  much. Returns the set of moves in case of success; NULL if memory is
+  full.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+cuddZddSiftingDown(
+  DdManager * table,
+  int  x,
+  int  x_high,
+  int  initial_size)
+{
+    Move        *moves;
+    Move        *move;
+    int         y;
+    int         size;
+    int         limit_size = initial_size;
+
+    moves = NULL;
+    y = cuddZddNextHigh(table, x);
+    while (y <= x_high) {
+        size = cuddZddSwapInPlace(table, x, y);
+        if (size == 0)
+            goto cuddZddSiftingDownOutOfMem;
+        move = (Move *)cuddDynamicAllocNode(table);
+        if (move == NULL)
+            goto cuddZddSiftingDownOutOfMem;
+        move->x = x;
+        move->y = y;
+        move->size = size;
+        move->next = moves;
+        moves = move;
+
+        if ((double)size > (double)limit_size * table->maxGrowth)
+            break;
+        if (size < limit_size)
+            limit_size = size;
+
+        x = y;
+        y = cuddZddNextHigh(table, x);
+    }
+    return(moves);
+
+cuddZddSiftingDownOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return(NULL);
+
+} /* end of cuddZddSiftingDown */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given a set of moves, returns the ZDD heap to the position
+  giving the minimum size.]
+
+  Description [Given a set of moves, returns the ZDD heap to the
+  position giving the minimum size. In case of ties, returns to the
+  closest position giving the minimum size. Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddSiftingBackward(
+  DdManager * table,
+  Move * moves,
+  int  size)
+{
+    int         i;
+    int         i_best;
+    Move        *move;
+    int         res;
+
+    /* Find the minimum size among moves. */
+    i_best = -1;
+    for (move = moves, i = 0; move != NULL; move = move->next, i++) {
+        if (move->size < size) {
+            i_best = i;
+            size = move->size;
+        }
+    }
+
+    for (move = moves, i = 0; move != NULL; move = move->next, i++) {
+        if (i == i_best)
+            break;
+        res = cuddZddSwapInPlace(table, move->x, move->y);
+        if (!res)
+            return(0);
+        if (i_best == -1 && res == size)
+            break;
+    }
+
+    return(1);
+
+} /* end of cuddZddSiftingBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prepares the ZDD heap for dynamic reordering.]
+
+  Description [Prepares the ZDD heap for dynamic reordering. Does
+  garbage collection, to guarantee that there are no dead nodes;
+  and clears the cache, which is invalidated by dynamic reordering.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+zddReorderPreprocess(
+  DdManager * table)
+{
+
+    /* Clear the cache. */
+    cuddCacheFlush(table);
+
+    /* Eliminate dead nodes. Do not scan the cache again. */
+    cuddGarbageCollect(table,0);
+
+    return;
+
+} /* end of ddReorderPreprocess */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Shrinks almost empty ZDD subtables at the end of reordering
+  to guarantee that they have a reasonable load factor.]
+
+  Description [Shrinks almost empty subtables at the end of reordering to
+  guarantee that they have a reasonable load factor. However, if there many
+  nodes are being reclaimed, then no resizing occurs. Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddReorderPostprocess(
+  DdManager * table)
+{
+    int i, j, posn;
+    DdNodePtr *nodelist, *oldnodelist;
+    DdNode *node, *next;
+    unsigned int slots, oldslots;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+#ifdef DD_VERBOSE
+    (void) fflush(table->out);
+#endif
+
+    /* If we have very many reclaimed nodes, we do not want to shrink
+    ** the subtables, because this will lead to more garbage
+    ** collections. More garbage collections mean shorter mean life for
+    ** nodes with zero reference count; hence lower probability of finding
+    ** a result in the cache.
+    */
+    if (table->reclaimed > table->allocated / 2) return(1);
+
+    /* Resize subtables. */
+    for (i = 0; i < table->sizeZ; i++) {
+        int shift;
+        oldslots = table->subtableZ[i].slots;
+        if (oldslots < table->subtableZ[i].keys * DD_MAX_SUBTABLE_SPARSITY ||
+            oldslots <= table->initSlots) continue;
+        oldnodelist = table->subtableZ[i].nodelist;
+        slots = oldslots >> 1;
+        saveHandler = MMoutOfMemory;
+        MMoutOfMemory = Cudd_OutOfMem;
+        nodelist = ABC_ALLOC(DdNodePtr, slots);
+        MMoutOfMemory = saveHandler;
+        if (nodelist == NULL) {
+            return(1);
+        }
+        table->subtableZ[i].nodelist = nodelist;
+        table->subtableZ[i].slots = slots;
+        table->subtableZ[i].shift++;
+        table->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
+#ifdef DD_VERBOSE
+        (void) fprintf(table->err,
+                       "shrunk layer %d (%d keys) from %d to %d slots\n",
+                       i, table->subtableZ[i].keys, oldslots, slots);
+#endif
+
+        for (j = 0; (unsigned) j < slots; j++) {
+            nodelist[j] = NULL;
+        }
+        shift = table->subtableZ[i].shift;
+        for (j = 0; (unsigned) j < oldslots; j++) {
+            node = oldnodelist[j];
+            while (node != NULL) {
+                next = node->next;
+                posn = ddHash(cuddF2L(cuddT(node)), cuddF2L(cuddE(node)), shift);
+                node->next = nodelist[posn];
+                nodelist[posn] = node;
+                node = next;
+            }
+        }
+        ABC_FREE(oldnodelist);
+
+        table->memused += (slots - oldslots) * sizeof(DdNode *);
+        table->slots += slots - oldslots;
+        table->minDead = (unsigned) (table->gcFrac * (double) table->slots);
+        table->cacheSlack = (int) ddMin(table->maxCacheHard,
+            DD_MAX_CACHE_TO_SLOTS_RATIO*table->slots) -
+            2 * (int) table->cacheSlots;
+    }
+    /* We don't look at the constant subtable, because it is not
+    ** affected by reordering.
+    */
+
+    return(1);
+
+} /* end of zddReorderPostprocess */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders ZDD variables according to a given permutation.]
+
+  Description [Reorders ZDD variables according to a given permutation.
+  The i-th permutation array contains the index of the variable that
+  should be brought to the i-th level. zddShuffle assumes that no
+  dead nodes are present.  The reordering is achieved by a series of
+  upward sifts.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static int
+zddShuffle(
+  DdManager * table,
+  int * permutation)
+{
+    int         index;
+    int         level;
+    int         position;
+    int         numvars;
+    int         result;
+#ifdef DD_STATS
+    long        localTime;
+    int         initialSize;
+    int         finalSize;
+    int         previousSize;
+#endif
+
+    zddTotalNumberSwapping = 0;
+#ifdef DD_STATS
+    localTime = util_cpu_time();
+    initialSize = table->keysZ;
+    (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n",
+                   initialSize); 
+#endif
+
+    numvars = table->sizeZ;
+
+    for (level = 0; level < numvars; level++) {
+        index = permutation[level];
+        position = table->permZ[index];
+#ifdef DD_STATS
+        previousSize = table->keysZ;
+#endif
+        result = zddSiftUp(table,position,level);
+        if (!result) return(0);
+#ifdef DD_STATS
+        if (table->keysZ < (unsigned) previousSize) {
+            (void) fprintf(table->out,"-");
+        } else if (table->keysZ > (unsigned) previousSize) {
+            (void) fprintf(table->out,"+");     /* should never happen */
+        } else {
+            (void) fprintf(table->out,"=");
+        }
+        fflush(table->out);
+#endif
+    }
+
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n");
+    finalSize = table->keysZ;
+    (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize); 
+    (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n",
+        ((double)(util_cpu_time() - localTime)/1000.0)); 
+    (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n",
+                   zddTotalNumberSwapping);
+#endif
+
+    return(1);
+
+} /* end of zddShuffle */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves one ZDD variable up.]
+
+  Description [Takes a ZDD variable from position x and sifts it up to
+  position xLow;  xLow should be less than or equal to x.
+  Returns 1 if successful; 0 otherwise]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+zddSiftUp(
+  DdManager * table,
+  int  x,
+  int  xLow)
+{
+    int        y;
+    int        size;
+
+    y = cuddZddNextLow(table,x);
+    while (y >= xLow) {
+        size = cuddZddSwapInPlace(table,y,x);
+        if (size == 0) {
+            return(0);
+        }
+        x = y;
+        y = cuddZddNextLow(table,x);
+    }
+    return(1);
+
+} /* end of zddSiftUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Fixes the ZDD variable group tree after a shuffle.]
+
+  Description [Fixes the ZDD variable group tree after a
+  shuffle. Assumes that the order of the variables in a terminal node
+  has not been changed.]
+
+  SideEffects [Changes the ZDD variable group tree.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+zddFixTree(
+  DdManager * table,
+  MtrNode * treenode)
+{
+    if (treenode == NULL) return;
+    treenode->low = ((int) treenode->index < table->sizeZ) ?
+        table->permZ[treenode->index] : treenode->index;
+    if (treenode->child != NULL) {
+        zddFixTree(table, treenode->child);
+    }
+    if (treenode->younger != NULL)
+        zddFixTree(table, treenode->younger);
+    if (treenode->parent != NULL && treenode->low < treenode->parent->low) {
+        treenode->parent->low = treenode->low;
+        treenode->parent->index = treenode->index;
+    }
+    return;
+
+} /* end of zddFixTree */
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddZddSetop.c b/abc-build/src/bdd/cudd/cuddZddSetop.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddZddSetop.c
@@ -0,0 +1,1174 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddSetop.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Set operations on ZDDs.]
+
+  Description [External procedures included in this module:
+                    <ul>
+                    <li> Cudd_zddIte()
+                    <li> Cudd_zddUnion()
+                    <li> Cudd_zddIntersect()
+                    <li> Cudd_zddDiff()
+                    <li> Cudd_zddDiffConst()
+                    <li> Cudd_zddSubset1()
+                    <li> Cudd_zddSubset0()
+                    <li> Cudd_zddChange()
+                    </ul>
+               Internal procedures included in this module:
+                    <ul>
+                    <li> cuddZddIte()
+                    <li> cuddZddUnion()
+                    <li> cuddZddIntersect()
+                    <li> cuddZddDiff()
+                    <li> cuddZddChangeAux()
+                    <li> cuddZddSubset1()
+                    <li> cuddZddSubset0()
+                    </ul>
+               Static procedures included in this module:
+                    <ul>
+                    <li> zdd_subset1_aux()
+                    <li> zdd_subset0_aux()
+                    <li> zddVarToConst()
+                    </ul>
+              ]
+
+  SeeAlso     []
+
+  Author      [Hyong-Kyoon Shin, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddSetop.c,v 1.25 2004/08/13 18:04:54 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * zdd_subset1_aux (DdManager *zdd, DdNode *P, DdNode *zvar);
+static DdNode * zdd_subset0_aux (DdManager *zdd, DdNode *P, DdNode *zvar);
+static void zddVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *base, DdNode *empty);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the ITE of three ZDDs.]
+
+  Description [Computes the ITE of three ZDDs. Returns a pointer to the
+  result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_zddIte(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddZddIte(dd, f, g, h);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddIte */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the union of two ZDDs.]
+
+  Description [Computes the union of two ZDDs. Returns a pointer to the
+  result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_zddUnion(
+  DdManager * dd,
+  DdNode * P,
+  DdNode * Q)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddZddUnion(dd, P, Q);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddUnion */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the intersection of two ZDDs.]
+
+  Description [Computes the intersection of two ZDDs. Returns a pointer to
+  the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_zddIntersect(
+  DdManager * dd,
+  DdNode * P,
+  DdNode * Q)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddZddIntersect(dd, P, Q);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddIntersect */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the difference of two ZDDs.]
+
+  Description [Computes the difference of two ZDDs. Returns a pointer to the
+  result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddDiffConst]
+
+******************************************************************************/
+DdNode *
+Cudd_zddDiff(
+  DdManager * dd,
+  DdNode * P,
+  DdNode * Q)
+{
+    DdNode *res;
+
+    do {
+        dd->reordered = 0;
+        res = cuddZddDiff(dd, P, Q);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddDiff */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the inclusion test for ZDDs (P implies Q).]
+
+  Description [Inclusion test for ZDDs (P implies Q). No new nodes are
+  generated by this procedure. Returns empty if true;
+  a valid pointer different from empty or DD_NON_CONSTANT otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddDiff]
+
+******************************************************************************/
+DdNode *
+Cudd_zddDiffConst(
+  DdManager * zdd,
+  DdNode * P,
+  DdNode * Q)
+{
+    int         p_top, q_top;
+    DdNode      *empty = DD_ZERO(zdd), *t, *res;
+    DdManager   *table = zdd;
+
+    statLine(zdd);
+    if (P == empty)
+        return(empty);
+    if (Q == empty)
+        return(P);
+    if (P == Q)
+        return(empty);
+
+    /* Check cache.  The cache is shared by cuddZddDiff(). */
+    res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q);
+    if (res != NULL)
+        return(res);
+
+    if (cuddIsConstant(P))
+        p_top = P->index;
+    else
+        p_top = zdd->permZ[P->index];
+    if (cuddIsConstant(Q))
+        q_top = Q->index;
+    else
+        q_top = zdd->permZ[Q->index];
+    if (p_top < q_top) {
+        res = DD_NON_CONSTANT;
+    } else if (p_top > q_top) {
+        res = Cudd_zddDiffConst(zdd, P, cuddE(Q));
+    } else {
+        t = Cudd_zddDiffConst(zdd, cuddT(P), cuddT(Q));
+        if (t != empty)
+            res = DD_NON_CONSTANT;
+        else
+            res = Cudd_zddDiffConst(zdd, cuddE(P), cuddE(Q));
+    }
+
+    cuddCacheInsert2(table, cuddZddDiff, P, Q, res);
+
+    return(res);
+
+} /* end of Cudd_zddDiffConst */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the positive cofactor of a ZDD w.r.t. a variable.]
+
+  Description [Computes the positive cofactor of a ZDD w.r.t. a
+  variable. In terms of combinations, the result is the set of all
+  combinations in which the variable is asserted. Returns a pointer to
+  the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddSubset0]
+
+******************************************************************************/
+DdNode *
+Cudd_zddSubset1(
+  DdManager * dd,
+  DdNode * P,
+  int  var)
+{
+    DdNode      *r;
+
+    do {
+        dd->reordered = 0;
+        r = cuddZddSubset1(dd, P, var);
+    } while (dd->reordered == 1);
+
+    return(r);
+
+} /* end of Cudd_zddSubset1 */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the negative cofactor of a ZDD w.r.t. a variable.]
+
+  Description [Computes the negative cofactor of a ZDD w.r.t. a
+  variable. In terms of combinations, the result is the set of all
+  combinations in which the variable is negated. Returns a pointer to
+  the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddSubset1]
+
+******************************************************************************/
+DdNode *
+Cudd_zddSubset0(
+  DdManager * dd,
+  DdNode * P,
+  int  var)
+{
+    DdNode      *r;
+
+    do {
+        dd->reordered = 0;
+        r = cuddZddSubset0(dd, P, var);
+    } while (dd->reordered == 1);
+
+    return(r);
+
+} /* end of Cudd_zddSubset0 */
+
+
+/**Function********************************************************************
+
+  Synopsis [Substitutes a variable with its complement in a ZDD.]
+
+  Description [Substitutes a variable with its complement in a ZDD.
+  returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_zddChange(
+  DdManager * dd,
+  DdNode * P,
+  int  var)
+{
+    DdNode      *res;
+
+    if ((unsigned int) var >= CUDD_MAXINDEX - 1) return(NULL);
+    
+    do {
+        dd->reordered = 0;
+        res = cuddZddChange(dd, P, var);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddChange */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddIte.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddZddIte(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode *tautology, *empty;
+    DdNode *r,*Gv,*Gvn,*Hv,*Hvn,*t,*e;
+    unsigned int topf,topg,toph,v,top;
+    int index;
+
+    statLine(dd);
+    /* Trivial cases. */
+    /* One variable cases. */
+    if (f == (empty = DD_ZERO(dd))) {   /* ITE(0,G,H) = H */
+        return(h);
+    }
+    topf = cuddIZ(dd,f->index);
+    topg = cuddIZ(dd,g->index);
+    toph = cuddIZ(dd,h->index);
+    v = ddMin(topg,toph);
+    top  = ddMin(topf,v);
+
+    tautology = (top == CUDD_MAXINDEX) ? DD_ONE(dd) : dd->univ[top];
+    if (f == tautology) {                       /* ITE(1,G,H) = G */
+        return(g);
+    }
+
+    /* From now on, f is known to not be a constant. */
+    zddVarToConst(f,&g,&h,tautology,empty);
+
+    /* Check remaining one variable cases. */
+    if (g == h) {                       /* ITE(F,G,G) = G */
+        return(g);
+    }
+
+    if (g == tautology) {                       /* ITE(F,1,0) = F */
+        if (h == empty) return(f);
+    }
+
+    /* Check cache. */
+    r = cuddCacheLookupZdd(dd,DD_ZDD_ITE_TAG,f,g,h);
+    if (r != NULL) {
+        return(r);
+    }
+
+    /* Recompute these because they may have changed in zddVarToConst. */
+    topg = cuddIZ(dd,g->index);
+    toph = cuddIZ(dd,h->index);
+    v = ddMin(topg,toph);
+
+    if (topf < v) {
+        r = cuddZddIte(dd,cuddE(f),g,h);
+        if (r == NULL) return(NULL);
+    } else if (topf > v) {
+        if (topg > v) {
+            Gvn = g;
+            index = h->index;
+        } else {
+            Gvn = cuddE(g);
+            index = g->index;
+        }
+        if (toph > v) {
+            Hv = empty; Hvn = h;
+        } else {
+            Hv = cuddT(h); Hvn = cuddE(h);
+        }
+        e = cuddZddIte(dd,f,Gvn,Hvn);
+        if (e == NULL) return(NULL);
+        cuddRef(e);
+        r = cuddZddGetNode(dd,index,Hv,e);
+        if (r == NULL) {
+            Cudd_RecursiveDerefZdd(dd,e);
+            return(NULL);
+        }
+        cuddDeref(e);
+    } else {
+        index = f->index;
+        if (topg > v) {
+            Gv = empty; Gvn = g;
+        } else {
+            Gv = cuddT(g); Gvn = cuddE(g);
+        }
+        if (toph > v) {
+            Hv = empty; Hvn = h;
+        } else {
+            Hv = cuddT(h); Hvn = cuddE(h);
+        }
+        e = cuddZddIte(dd,cuddE(f),Gvn,Hvn);
+        if (e == NULL) return(NULL);
+        cuddRef(e);
+        t = cuddZddIte(dd,cuddT(f),Gv,Hv);
+        if (t == NULL) {
+            Cudd_RecursiveDerefZdd(dd,e);
+            return(NULL);
+        }
+        cuddRef(t);
+        r = cuddZddGetNode(dd,index,t,e);
+        if (r == NULL) {
+            Cudd_RecursiveDerefZdd(dd,e);
+            Cudd_RecursiveDerefZdd(dd,t);
+            return(NULL);
+        }
+        cuddDeref(t);
+        cuddDeref(e);
+    }
+
+    cuddCacheInsert(dd,DD_ZDD_ITE_TAG,f,g,h,r);
+
+    return(r);
+
+} /* end of cuddZddIte */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddUnion.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddZddUnion(
+  DdManager * zdd,
+  DdNode * P,
+  DdNode * Q)
+{
+    int         p_top, q_top;
+    DdNode      *empty = DD_ZERO(zdd), *t, *e, *res;
+    DdManager   *table = zdd;
+
+    statLine(zdd);
+    if (P == empty)
+        return(Q);
+    if (Q == empty)
+        return(P);
+    if (P == Q)
+        return(P);
+
+    /* Check cache */
+    res = cuddCacheLookup2Zdd(table, cuddZddUnion, P, Q);
+    if (res != NULL)
+        return(res);
+
+    if (cuddIsConstant(P))
+        p_top = P->index;
+    else
+        p_top = zdd->permZ[P->index];
+    if (cuddIsConstant(Q))
+        q_top = Q->index;
+    else
+        q_top = zdd->permZ[Q->index];
+    if (p_top < q_top) {
+        e = cuddZddUnion(zdd, cuddE(P), Q);
+        if (e == NULL) return (NULL);
+        cuddRef(e);
+        res = cuddZddGetNode(zdd, P->index, cuddT(P), e);
+        if (res == NULL) {
+            Cudd_RecursiveDerefZdd(table, e);
+            return(NULL);
+        }
+        cuddDeref(e);
+    } else if (p_top > q_top) {
+        e = cuddZddUnion(zdd, P, cuddE(Q));
+        if (e == NULL) return(NULL);
+        cuddRef(e);
+        res = cuddZddGetNode(zdd, Q->index, cuddT(Q), e);
+        if (res == NULL) {
+            Cudd_RecursiveDerefZdd(table, e);
+            return(NULL);
+        }
+        cuddDeref(e);
+    } else {
+        t = cuddZddUnion(zdd, cuddT(P), cuddT(Q));
+        if (t == NULL) return(NULL);
+        cuddRef(t);
+        e = cuddZddUnion(zdd, cuddE(P), cuddE(Q));
+        if (e == NULL) {
+            Cudd_RecursiveDerefZdd(table, t);
+            return(NULL);
+        }
+        cuddRef(e);
+        res = cuddZddGetNode(zdd, P->index, t, e);
+        if (res == NULL) {
+            Cudd_RecursiveDerefZdd(table, t);
+            Cudd_RecursiveDerefZdd(table, e);
+            return(NULL);
+        }
+        cuddDeref(t);
+        cuddDeref(e);
+    }
+
+    cuddCacheInsert2(table, cuddZddUnion, P, Q, res);
+
+    return(res);
+
+} /* end of cuddZddUnion */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddIntersect.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddZddIntersect(
+  DdManager * zdd,
+  DdNode * P,
+  DdNode * Q)
+{
+    int         p_top, q_top;
+    DdNode      *empty = DD_ZERO(zdd), *t, *e, *res;
+    DdManager   *table = zdd;
+
+    statLine(zdd);
+    if (P == empty)
+        return(empty);
+    if (Q == empty)
+        return(empty);
+    if (P == Q)
+        return(P);
+
+    /* Check cache. */
+    res = cuddCacheLookup2Zdd(table, cuddZddIntersect, P, Q);
+    if (res != NULL)
+        return(res);
+
+    if (cuddIsConstant(P))
+        p_top = P->index;
+    else
+        p_top = zdd->permZ[P->index];
+    if (cuddIsConstant(Q))
+        q_top = Q->index;
+    else
+        q_top = zdd->permZ[Q->index];
+    if (p_top < q_top) {
+        res = cuddZddIntersect(zdd, cuddE(P), Q);
+        if (res == NULL) return(NULL);
+    } else if (p_top > q_top) {
+        res = cuddZddIntersect(zdd, P, cuddE(Q));
+        if (res == NULL) return(NULL);
+    } else {
+        t = cuddZddIntersect(zdd, cuddT(P), cuddT(Q));
+        if (t == NULL) return(NULL);
+        cuddRef(t);
+        e = cuddZddIntersect(zdd, cuddE(P), cuddE(Q));
+        if (e == NULL) {
+            Cudd_RecursiveDerefZdd(table, t);
+            return(NULL);
+        }
+        cuddRef(e);
+        res = cuddZddGetNode(zdd, P->index, t, e);
+        if (res == NULL) {
+            Cudd_RecursiveDerefZdd(table, t);
+            Cudd_RecursiveDerefZdd(table, e);
+            return(NULL);
+        }
+        cuddDeref(t);
+        cuddDeref(e);
+    }
+
+    cuddCacheInsert2(table, cuddZddIntersect, P, Q, res);
+
+    return(res);
+
+} /* end of cuddZddIntersect */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddDiff.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddZddDiff(
+  DdManager * zdd,
+  DdNode * P,
+  DdNode * Q)
+{
+    int         p_top, q_top;
+    DdNode      *empty = DD_ZERO(zdd), *t, *e, *res;
+    DdManager   *table = zdd;
+
+    statLine(zdd);
+    if (P == empty)
+        return(empty);
+    if (Q == empty)
+        return(P);
+    if (P == Q)
+        return(empty);
+
+    /* Check cache.  The cache is shared by Cudd_zddDiffConst(). */
+    res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q);
+    if (res != NULL && res != DD_NON_CONSTANT)
+        return(res);
+
+    if (cuddIsConstant(P))
+        p_top = P->index;
+    else
+        p_top = zdd->permZ[P->index];
+    if (cuddIsConstant(Q))
+        q_top = Q->index;
+    else
+        q_top = zdd->permZ[Q->index];
+    if (p_top < q_top) {
+        e = cuddZddDiff(zdd, cuddE(P), Q);
+        if (e == NULL) return(NULL);
+        cuddRef(e);
+        res = cuddZddGetNode(zdd, P->index, cuddT(P), e);
+        if (res == NULL) {
+            Cudd_RecursiveDerefZdd(table, e);
+            return(NULL);
+        }
+        cuddDeref(e);
+    } else if (p_top > q_top) {
+        res = cuddZddDiff(zdd, P, cuddE(Q));
+        if (res == NULL) return(NULL);
+    } else {
+        t = cuddZddDiff(zdd, cuddT(P), cuddT(Q));
+        if (t == NULL) return(NULL);
+        cuddRef(t);
+        e = cuddZddDiff(zdd, cuddE(P), cuddE(Q));
+        if (e == NULL) {
+            Cudd_RecursiveDerefZdd(table, t);
+            return(NULL);
+        }
+        cuddRef(e);
+        res = cuddZddGetNode(zdd, P->index, t, e);
+        if (res == NULL) {
+            Cudd_RecursiveDerefZdd(table, t);
+            Cudd_RecursiveDerefZdd(table, e);
+            return(NULL);
+        }
+        cuddDeref(t);
+        cuddDeref(e);
+    }
+
+    cuddCacheInsert2(table, cuddZddDiff, P, Q, res);
+
+    return(res);
+
+} /* end of cuddZddDiff */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddChange.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddZddChangeAux(
+  DdManager * zdd,
+  DdNode * P,
+  DdNode * zvar)
+{
+    int         top_var, level;
+    DdNode      *res, *t, *e;
+    DdNode      *base = DD_ONE(zdd);
+    DdNode      *empty = DD_ZERO(zdd);
+
+    statLine(zdd);
+    if (P == empty)
+        return(empty);
+    if (P == base)
+        return(zvar);
+
+    /* Check cache. */
+    res = cuddCacheLookup2Zdd(zdd, cuddZddChangeAux, P, zvar);
+    if (res != NULL)
+        return(res);
+
+    top_var = zdd->permZ[P->index];
+    level = zdd->permZ[zvar->index];
+
+    if (top_var > level) {
+        res = cuddZddGetNode(zdd, zvar->index, P, DD_ZERO(zdd));
+        if (res == NULL) return(NULL);
+    } else if (top_var == level) {
+        res = cuddZddGetNode(zdd, zvar->index, cuddE(P), cuddT(P));
+        if (res == NULL) return(NULL);
+    } else {
+        t = cuddZddChangeAux(zdd, cuddT(P), zvar);
+        if (t == NULL) return(NULL);
+        cuddRef(t);
+        e = cuddZddChangeAux(zdd, cuddE(P), zvar);
+        if (e == NULL) {
+            Cudd_RecursiveDerefZdd(zdd, t);
+            return(NULL);
+        }
+        cuddRef(e);
+        res = cuddZddGetNode(zdd, P->index, t, e);
+        if (res == NULL) {
+            Cudd_RecursiveDerefZdd(zdd, t);
+            Cudd_RecursiveDerefZdd(zdd, e);
+            return(NULL);
+        }
+        cuddDeref(t);
+        cuddDeref(e);
+    }
+
+    cuddCacheInsert2(zdd, cuddZddChangeAux, P, zvar, res);
+
+    return(res);
+
+} /* end of cuddZddChangeAux */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the positive cofactor of a ZDD w.r.t. a variable.]
+
+  Description [Computes the positive cofactor of a ZDD w.r.t. a
+  variable. In terms of combinations, the result is the set of all
+  combinations in which the variable is asserted. Returns a pointer to
+  the result if successful; NULL otherwise. cuddZddSubset1 performs
+  the same function as Cudd_zddSubset1, but does not restart if
+  reordering has taken place. Therefore it can be called from within a
+  recursive procedure.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddZddSubset0 Cudd_zddSubset1]
+
+******************************************************************************/
+DdNode *
+cuddZddSubset1(
+  DdManager * dd,
+  DdNode * P,
+  int  var)
+{
+    DdNode      *zvar, *r;
+    DdNode      *base, *empty;
+
+    base = DD_ONE(dd);
+    empty = DD_ZERO(dd);
+
+    zvar = cuddUniqueInterZdd(dd, var, base, empty);
+    if (zvar == NULL) {
+        return(NULL);
+    } else {
+        cuddRef(zvar);
+        r = zdd_subset1_aux(dd, P, zvar);
+        if (r == NULL) {
+            Cudd_RecursiveDerefZdd(dd, zvar);
+            return(NULL);
+        }
+        cuddRef(r);
+        Cudd_RecursiveDerefZdd(dd, zvar);
+    }
+
+    cuddDeref(r);
+    return(r);
+
+} /* end of cuddZddSubset1 */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the negative cofactor of a ZDD w.r.t. a variable.]
+
+  Description [Computes the negative cofactor of a ZDD w.r.t. a
+  variable. In terms of combinations, the result is the set of all
+  combinations in which the variable is negated. Returns a pointer to
+  the result if successful; NULL otherwise. cuddZddSubset0 performs
+  the same function as Cudd_zddSubset0, but does not restart if
+  reordering has taken place. Therefore it can be called from within a
+  recursive procedure.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddZddSubset1 Cudd_zddSubset0]
+
+******************************************************************************/
+DdNode *
+cuddZddSubset0(
+  DdManager * dd,
+  DdNode * P,
+  int  var)
+{
+    DdNode      *zvar, *r;
+    DdNode      *base, *empty;
+
+    base = DD_ONE(dd);
+    empty = DD_ZERO(dd);
+
+    zvar = cuddUniqueInterZdd(dd, var, base, empty);
+    if (zvar == NULL) {
+        return(NULL);
+    } else {
+        cuddRef(zvar);
+        r = zdd_subset0_aux(dd, P, zvar);
+        if (r == NULL) {
+            Cudd_RecursiveDerefZdd(dd, zvar);
+            return(NULL);
+        }
+        cuddRef(r);
+        Cudd_RecursiveDerefZdd(dd, zvar);
+    }
+
+    cuddDeref(r);
+    return(r);
+
+} /* end of cuddZddSubset0 */
+
+
+/**Function********************************************************************
+
+  Synopsis [Substitutes a variable with its complement in a ZDD.]
+
+  Description [Substitutes a variable with its complement in a ZDD.
+  returns a pointer to the result if successful; NULL
+  otherwise. cuddZddChange performs the same function as
+  Cudd_zddChange, but does not restart if reordering has taken
+  place. Therefore it can be called from within a recursive
+  procedure.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddChange]
+
+******************************************************************************/
+DdNode *
+cuddZddChange(
+  DdManager * dd,
+  DdNode * P,
+  int  var)
+{
+    DdNode      *zvar, *res;
+
+    zvar = cuddUniqueInterZdd(dd, var, DD_ONE(dd), DD_ZERO(dd));
+    if (zvar == NULL) return(NULL);
+    cuddRef(zvar);
+
+    res = cuddZddChangeAux(dd, P, zvar);
+    if (res == NULL) {
+        Cudd_RecursiveDerefZdd(dd,zvar);
+        return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDerefZdd(dd,zvar);
+    cuddDeref(res);
+    return(res);
+
+} /* end of cuddZddChange */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddSubset1.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+zdd_subset1_aux(
+  DdManager * zdd,
+  DdNode * P,
+  DdNode * zvar)
+{
+    int         top_var, level;
+    DdNode      *res, *t, *e;
+    DdNode      *empty;
+
+    statLine(zdd);
+    empty = DD_ZERO(zdd);
+
+    /* Check cache. */
+    res = cuddCacheLookup2Zdd(zdd, zdd_subset1_aux, P, zvar);
+    if (res != NULL)
+        return(res);
+
+    if (cuddIsConstant(P)) {
+        res = empty;
+        cuddCacheInsert2(zdd, zdd_subset1_aux, P, zvar, res);
+        return(res);
+    }
+
+    top_var = zdd->permZ[P->index];
+    level = zdd->permZ[zvar->index];
+
+    if (top_var > level) {
+        res = empty;
+    } else if (top_var == level) {
+        res = cuddT(P);
+    } else {
+        t = zdd_subset1_aux(zdd, cuddT(P), zvar);
+        if (t == NULL) return(NULL);
+        cuddRef(t);
+        e = zdd_subset1_aux(zdd, cuddE(P), zvar);
+        if (e == NULL) {
+            Cudd_RecursiveDerefZdd(zdd, t);
+            return(NULL);
+        }
+        cuddRef(e);
+        res = cuddZddGetNode(zdd, P->index, t, e);
+        if (res == NULL) {
+            Cudd_RecursiveDerefZdd(zdd, t);
+            Cudd_RecursiveDerefZdd(zdd, e);
+            return(NULL);
+        }
+        cuddDeref(t);
+        cuddDeref(e);
+    }
+
+    cuddCacheInsert2(zdd, zdd_subset1_aux, P, zvar, res);
+
+    return(res);
+
+} /* end of zdd_subset1_aux */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddSubset0.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+zdd_subset0_aux(
+  DdManager * zdd,
+  DdNode * P,
+  DdNode * zvar)
+{
+    int         top_var, level;
+    DdNode      *res, *t, *e;
+
+    statLine(zdd);
+
+    /* Check cache. */
+    res = cuddCacheLookup2Zdd(zdd, zdd_subset0_aux, P, zvar);
+    if (res != NULL)
+        return(res);
+
+    if (cuddIsConstant(P)) {
+        res = P;
+        cuddCacheInsert2(zdd, zdd_subset0_aux, P, zvar, res);
+        return(res);
+    }
+
+    top_var = zdd->permZ[P->index];
+    level = zdd->permZ[zvar->index];
+
+    if (top_var > level) {
+        res = P;
+    }
+    else if (top_var == level) {
+        res = cuddE(P);
+    }
+    else {
+        t = zdd_subset0_aux(zdd, cuddT(P), zvar);
+        if (t == NULL) return(NULL);
+        cuddRef(t);
+        e = zdd_subset0_aux(zdd, cuddE(P), zvar);
+        if (e == NULL) {
+            Cudd_RecursiveDerefZdd(zdd, t);
+            return(NULL);
+        }
+        cuddRef(e);
+        res = cuddZddGetNode(zdd, P->index, t, e);
+        if (res == NULL) {
+            Cudd_RecursiveDerefZdd(zdd, t);
+            Cudd_RecursiveDerefZdd(zdd, e);
+            return(NULL);
+        }
+        cuddDeref(t);
+        cuddDeref(e);
+    }
+
+    cuddCacheInsert2(zdd, zdd_subset0_aux, P, zvar, res);
+
+    return(res);
+
+} /* end of zdd_subset0_aux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Replaces variables with constants if possible (part of
+  canonical form).]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+zddVarToConst(
+  DdNode * f,
+  DdNode ** gp,
+  DdNode ** hp,
+  DdNode * base,
+  DdNode * empty)
+{
+    DdNode *g = *gp;
+    DdNode *h = *hp;
+
+    if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */
+        *gp = base;
+    }
+
+    if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */
+        *hp = empty;
+    }
+
+} /* end of zddVarToConst */
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddZddSymm.c b/abc-build/src/bdd/cudd/cuddZddSymm.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddZddSymm.c
@@ -0,0 +1,1707 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddSymm.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for symmetry-based ZDD variable reordering.]
+
+  Description [External procedures included in this module:
+                    <ul>
+                    <li> Cudd_zddSymmProfile()
+                    </ul>
+               Internal procedures included in this module:
+                    <ul>
+                    <li> cuddZddSymmCheck()
+                    <li> cuddZddSymmSifting()
+                    <li> cuddZddSymmSiftingConv()
+                    </ul>
+               Static procedures included in this module:
+                    <ul>
+                    <li> cuddZddUniqueCompare()
+                    <li> cuddZddSymmSiftingAux()
+                    <li> cuddZddSymmSiftingConvAux()
+                    <li> cuddZddSymmSifting_up()
+                    <li> cuddZddSymmSifting_down()
+                    <li> zdd_group_move()
+                    <li> cuddZddSymmSiftingBackward()
+                    <li> zdd_group_move_backward()
+                    </ul>
+              ]
+
+  SeeAlso     [cuddSymmetry.c]
+
+  Author      [Hyong-Kyoon Shin, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define ZDD_MV_OOM (Move *)1
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddSymm.c,v 1.29 2004/08/13 18:04:54 fabio Exp $";
+#endif
+
+extern int      *zdd_entry;
+
+extern int      zddTotalNumberSwapping;
+
+static DdNode   *empty;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int cuddZddSymmSiftingAux (DdManager *table, int x, int x_low, int x_high);
+static int cuddZddSymmSiftingConvAux (DdManager *table, int x, int x_low, int x_high);
+static Move * cuddZddSymmSifting_up (DdManager *table, int x, int x_low, int initial_size);
+static Move * cuddZddSymmSifting_down (DdManager *table, int x, int x_high, int initial_size);
+static int cuddZddSymmSiftingBackward (DdManager *table, Move *moves, int size);
+static int zdd_group_move (DdManager *table, int x, int y, Move **moves);
+static int zdd_group_move_backward (DdManager *table, int x, int y);
+static void cuddZddSymmSummary (DdManager *table, int lower, int upper, int *symvars, int *symgroups);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Prints statistics on symmetric ZDD variables.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_zddSymmProfile(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int         i, x, gbot;
+    int         TotalSymm = 0;
+    int         TotalSymmGroups = 0;
+
+    for (i = lower; i < upper; i++) {
+        if (table->subtableZ[i].next != (unsigned) i) {
+            x = i;
+            (void) fprintf(table->out,"Group:");
+            do {
+                (void) fprintf(table->out,"  %d", table->invpermZ[x]);
+                TotalSymm++;
+                gbot = x;
+                x = table->subtableZ[x].next;
+            } while (x != i);
+            TotalSymmGroups++;
+#ifdef DD_DEBUG
+            assert(table->subtableZ[gbot].next == (unsigned) i);
+#endif
+            i = gbot;
+            (void) fprintf(table->out,"\n");
+        }
+    }
+    (void) fprintf(table->out,"Total Symmetric = %d\n", TotalSymm);
+    (void) fprintf(table->out,"Total Groups = %d\n", TotalSymmGroups);
+
+} /* end of Cudd_zddSymmProfile */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Checks for symmetry of x and y.]
+
+  Description [Checks for symmetry of x and y. Ignores projection
+  functions, unless they are isolated. Returns 1 in case of
+  symmetry; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddSymmCheck(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int         i;
+    DdNode      *f, *f0, *f1, *f01, *f00, *f11, *f10;
+    int         yindex;
+    int         xsymmy = 1;
+    int         xsymmyp = 1;
+    int         arccount = 0;
+    int         TotalRefCount = 0;
+    int         symm_found;
+
+    empty = table->zero;
+
+    yindex = table->invpermZ[y];
+    for (i = table->subtableZ[x].slots - 1; i >= 0; i--) {
+        f = table->subtableZ[x].nodelist[i];
+        while (f != NULL) {
+            /* Find f1, f0, f11, f10, f01, f00 */
+            f1 = cuddT(f);
+            f0 = cuddE(f);
+            if ((int) f1->index == yindex) {
+                f11 = cuddT(f1);
+                f10 = cuddE(f1);
+                if (f10 != empty)
+                    arccount++;
+            } else {
+                if ((int) f0->index != yindex) {
+                    return(0); /* f bypasses layer y */
+                }
+                f11 = empty;
+                f10 = f1;
+            }
+            if ((int) f0->index == yindex) {
+                f01 = cuddT(f0);
+                f00 = cuddE(f0);
+                if (f00 != empty)
+                    arccount++;
+            } else {
+                f01 = empty;
+                f00 = f0;
+            }
+            if (f01 != f10)
+                xsymmy = 0;
+            if (f11 != f00)
+                xsymmyp = 0;
+            if ((xsymmy == 0) && (xsymmyp == 0))
+                return(0);
+
+            f = f->next;
+        } /* for each element of the collision list */
+    } /* for each slot of the subtable */
+
+    /* Calculate the total reference counts of y
+    ** whose else arc is not empty.
+    */
+    for (i = table->subtableZ[y].slots - 1; i >= 0; i--) {
+        f = table->subtableZ[y].nodelist[i];
+        while (f != NIL(DdNode)) {
+            if (cuddE(f) != empty)
+                TotalRefCount += f->ref;
+            f = f->next;
+        }
+    }
+
+    symm_found = (arccount == TotalRefCount);
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    if (symm_found) {
+        int xindex = table->invpermZ[x];
+        (void) fprintf(table->out,
+                       "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
+                       xindex,yindex,x,y);
+    }
+#endif
+
+    return(symm_found);
+
+} /* end cuddZddSymmCheck */
+
+
+/**Function********************************************************************
+
+  Synopsis [Symmetric sifting algorithm for ZDDs.]
+
+  Description [Symmetric sifting algorithm.
+  Assumes that no dead nodes are present.
+    <ol>
+    <li> Order all the variables according to the number of entries in
+    each unique subtable.
+    <li> Sift the variable up and down, remembering each time the total
+    size of the ZDD heap and grouping variables that are symmetric.
+    <li> Select the best permutation.
+    <li> Repeat 3 and 4 for all variables.
+    </ol>
+  Returns 1 plus the number of symmetric variables if successful; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddZddSymmSiftingConv]
+
+******************************************************************************/
+int
+cuddZddSymmSifting(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int         i;
+    int         *var;
+    int         nvars;
+    int         x;
+    int         result;
+    int         symvars;
+    int         symgroups;
+    int         iteration;
+#ifdef DD_STATS
+    int         previousSize;
+#endif
+
+    nvars = table->sizeZ;
+
+    /* Find order in which to sift variables. */
+    var = NULL;
+    zdd_entry = ABC_ALLOC(int, nvars);
+    if (zdd_entry == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto cuddZddSymmSiftingOutOfMem;
+    }
+    var = ABC_ALLOC(int, nvars);
+    if (var == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto cuddZddSymmSiftingOutOfMem;
+    }
+
+    for (i = 0; i < nvars; i++) {
+        x = table->permZ[i];
+        zdd_entry[i] = table->subtableZ[x].keys;
+        var[i] = i;
+    }
+
+    qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
+
+    /* Initialize the symmetry of each subtable to itself. */
+    for (i = lower; i <= upper; i++)
+        table->subtableZ[i].next = i;
+
+    iteration = ddMin(table->siftMaxVar, nvars);
+    for (i = 0; i < iteration; i++) {
+        if (zddTotalNumberSwapping >= table->siftMaxSwap)
+            break;
+        x = table->permZ[var[i]];
+#ifdef DD_STATS
+        previousSize = table->keysZ;
+#endif
+        if (x < lower || x > upper) continue;
+        if (table->subtableZ[x].next == (unsigned) x) {
+            result = cuddZddSymmSiftingAux(table, x, lower, upper);
+            if (!result)
+                goto cuddZddSymmSiftingOutOfMem;
+#ifdef DD_STATS
+            if (table->keysZ < (unsigned) previousSize) {
+                (void) fprintf(table->out,"-");
+            } else if (table->keysZ > (unsigned) previousSize) {
+                (void) fprintf(table->out,"+");
+#ifdef DD_VERBOSE
+                (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
+#endif
+            } else {
+                (void) fprintf(table->out,"=");
+            }
+            fflush(table->out);
+#endif
+        }
+    }
+
+    ABC_FREE(var);
+    ABC_FREE(zdd_entry);
+
+    cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
+
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",symvars);
+    (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",symgroups);
+#endif
+
+    return(1+symvars);
+
+cuddZddSymmSiftingOutOfMem:
+
+    if (zdd_entry != NULL)
+        ABC_FREE(zdd_entry);
+    if (var != NULL)
+        ABC_FREE(var);
+
+    return(0);
+
+} /* end of cuddZddSymmSifting */
+
+
+/**Function********************************************************************
+
+  Synopsis [Symmetric sifting to convergence algorithm for ZDDs.]
+
+  Description [Symmetric sifting to convergence algorithm for ZDDs.
+  Assumes that no dead nodes are present.
+    <ol>
+    <li> Order all the variables according to the number of entries in
+    each unique subtable.
+    <li> Sift the variable up and down, remembering each time the total
+    size of the ZDD heap and grouping variables that are symmetric.
+    <li> Select the best permutation.
+    <li> Repeat 3 and 4 for all variables.
+    <li> Repeat 1-4 until no further improvement.
+    </ol>
+  Returns 1 plus the number of symmetric variables if successful; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddZddSymmSifting]
+
+******************************************************************************/
+int
+cuddZddSymmSiftingConv(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int         i;
+    int         *var;
+    int         nvars;
+    int         initialSize;
+    int         x;
+    int         result;
+    int         symvars;
+    int         symgroups;
+    int         classes;
+    int         iteration;
+#ifdef DD_STATS
+    int         previousSize;
+#endif
+
+    initialSize = table->keysZ;
+
+    nvars = table->sizeZ;
+
+    /* Find order in which to sift variables. */
+    var = NULL;
+    zdd_entry = ABC_ALLOC(int, nvars);
+    if (zdd_entry == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto cuddZddSymmSiftingConvOutOfMem;
+    }
+    var = ABC_ALLOC(int, nvars);
+    if (var == NULL) {
+        table->errorCode = CUDD_MEMORY_OUT;
+        goto cuddZddSymmSiftingConvOutOfMem;
+    }
+
+    for (i = 0; i < nvars; i++) {
+        x = table->permZ[i];
+        zdd_entry[i] = table->subtableZ[x].keys;
+        var[i] = i;
+    }
+
+    qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
+
+    /* Initialize the symmetry of each subtable to itself
+    ** for first pass of converging symmetric sifting.
+    */
+    for (i = lower; i <= upper; i++)
+        table->subtableZ[i].next = i;
+
+    iteration = ddMin(table->siftMaxVar, table->sizeZ);
+    for (i = 0; i < iteration; i++) {
+        if (zddTotalNumberSwapping >= table->siftMaxSwap)
+            break;
+        x = table->permZ[var[i]];
+        if (x < lower || x > upper) continue;
+        /* Only sift if not in symmetry group already. */
+        if (table->subtableZ[x].next == (unsigned) x) {
+#ifdef DD_STATS
+            previousSize = table->keysZ;
+#endif
+            result = cuddZddSymmSiftingAux(table, x, lower, upper);
+            if (!result)
+                goto cuddZddSymmSiftingConvOutOfMem;
+#ifdef DD_STATS
+            if (table->keysZ < (unsigned) previousSize) {
+                (void) fprintf(table->out,"-");
+            } else if (table->keysZ > (unsigned) previousSize) {
+                (void) fprintf(table->out,"+");
+#ifdef DD_VERBOSE
+                (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
+#endif
+            } else {
+                (void) fprintf(table->out,"=");
+            }
+            fflush(table->out);
+#endif
+        }
+    }
+
+    /* Sifting now until convergence. */
+    while ((unsigned) initialSize > table->keysZ) {
+        initialSize = table->keysZ;
+#ifdef DD_STATS
+        (void) fprintf(table->out,"\n");
+#endif
+        /* Here we consider only one representative for each symmetry class. */
+        for (x = lower, classes = 0; x <= upper; x++, classes++) {
+            while ((unsigned) x < table->subtableZ[x].next)
+                x = table->subtableZ[x].next;
+            /* Here x is the largest index in a group.
+            ** Groups consists of adjacent variables.
+            ** Hence, the next increment of x will move it to a new group.
+            */
+            i = table->invpermZ[x];
+            zdd_entry[i] = table->subtableZ[x].keys;
+            var[classes] = i;
+        }
+
+        qsort((void *)var,classes,sizeof(int),(DD_QSFP)cuddZddUniqueCompare);
+
+        /* Now sift. */
+        iteration = ddMin(table->siftMaxVar, nvars);
+        for (i = 0; i < iteration; i++) {
+            if (zddTotalNumberSwapping >= table->siftMaxSwap)
+                break;
+            x = table->permZ[var[i]];
+            if ((unsigned) x >= table->subtableZ[x].next) {
+#ifdef DD_STATS
+                previousSize = table->keysZ;
+#endif
+                result = cuddZddSymmSiftingConvAux(table, x, lower, upper);
+                if (!result)
+                    goto cuddZddSymmSiftingConvOutOfMem;
+#ifdef DD_STATS
+                if (table->keysZ < (unsigned) previousSize) {
+                    (void) fprintf(table->out,"-");
+                } else if (table->keysZ > (unsigned) previousSize) {
+                    (void) fprintf(table->out,"+");
+#ifdef DD_VERBOSE
+                (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
+#endif
+                } else {
+                    (void) fprintf(table->out,"=");
+                }
+                fflush(table->out);
+#endif
+            }
+        } /* for */
+    }
+
+    cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
+
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",
+                   symvars);
+    (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",
+                   symgroups);
+#endif
+
+    ABC_FREE(var);
+    ABC_FREE(zdd_entry);
+
+    return(1+symvars);
+
+cuddZddSymmSiftingConvOutOfMem:
+
+    if (zdd_entry != NULL)
+        ABC_FREE(zdd_entry);
+    if (var != NULL)
+        ABC_FREE(var);
+
+    return(0);
+
+} /* end of cuddZddSymmSiftingConv */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Given x_low <= x <= x_high moves x up and down between the
+  boundaries.]
+
+  Description [Given x_low <= x <= x_high moves x up and down between the
+  boundaries. Finds the best position and does the required changes.
+  Assumes that x is not part of a symmetry group. Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddSymmSiftingAux(
+  DdManager * table,
+  int  x,
+  int  x_low,
+  int  x_high)
+{
+    Move *move;
+    Move *move_up;      /* list of up move */
+    Move *move_down;    /* list of down move */
+    int  initial_size;
+    int  result;
+    int  i;
+    int  topbot;        /* index to either top or bottom of symmetry group */
+    int  init_group_size, final_group_size;
+
+    initial_size = table->keysZ;
+
+    move_down = NULL;
+    move_up = NULL;
+
+    /* Look for consecutive symmetries above x. */
+    for (i = x; i > x_low; i--) {
+        if (!cuddZddSymmCheck(table, i - 1, i))
+            break;
+        /* find top of i-1's symmetry */
+        topbot = table->subtableZ[i - 1].next;
+        table->subtableZ[i - 1].next = i;
+        table->subtableZ[x].next = topbot;
+        /* x is bottom of group so its symmetry is top of i-1's
+           group */
+        i = topbot + 1; /* add 1 for i--, new i is top of symm group */
+    }
+    /* Look for consecutive symmetries below x. */
+    for (i = x; i < x_high; i++) {
+        if (!cuddZddSymmCheck(table, i, i + 1))
+            break;
+        /* find bottom of i+1's symm group */
+        topbot = i + 1;
+        while ((unsigned) topbot < table->subtableZ[topbot].next)
+            topbot = table->subtableZ[topbot].next;
+
+        table->subtableZ[topbot].next = table->subtableZ[i].next;
+        table->subtableZ[i].next = i + 1;
+        i = topbot - 1; /* add 1 for i++,
+                           new i is bottom of symm group */
+    }
+
+    /* Now x maybe in the middle of a symmetry group. */
+    if (x == x_low) { /* Sift down */
+        /* Find bottom of x's symm group */
+        while ((unsigned) x < table->subtableZ[x].next)
+            x = table->subtableZ[x].next;
+
+        i = table->subtableZ[x].next;
+        init_group_size = x - i + 1;
+
+        move_down = cuddZddSymmSifting_down(table, x, x_high,
+            initial_size);
+        /* after that point x --> x_high, unless early term */
+        if (move_down == ZDD_MV_OOM)
+            goto cuddZddSymmSiftingAuxOutOfMem;
+
+        if (move_down == NULL ||
+            table->subtableZ[move_down->y].next != move_down->y) {
+            /* symmetry detected may have to make another complete
+               pass */
+            if (move_down != NULL)
+                x = move_down->y;
+            else
+                x = table->subtableZ[x].next;
+            i = x;
+            while ((unsigned) i < table->subtableZ[i].next) {
+                i = table->subtableZ[i].next;
+            }
+            final_group_size = i - x + 1;
+
+            if (init_group_size == final_group_size) {
+                /* No new symmetry groups detected,
+                   return to best position */
+                result = cuddZddSymmSiftingBackward(table,
+                    move_down, initial_size);
+            }
+            else {
+                initial_size = table->keysZ;
+                move_up = cuddZddSymmSifting_up(table, x, x_low,
+                    initial_size);
+                result = cuddZddSymmSiftingBackward(table, move_up,
+                    initial_size);
+            }
+        }
+        else {
+            result = cuddZddSymmSiftingBackward(table, move_down,
+                initial_size);
+            /* move backward and stop at best position */
+        }
+        if (!result)
+            goto cuddZddSymmSiftingAuxOutOfMem;
+    }
+    else if (x == x_high) { /* Sift up */
+        /* Find top of x's symm group */
+        while ((unsigned) x < table->subtableZ[x].next)
+            x = table->subtableZ[x].next;
+        x = table->subtableZ[x].next;
+
+        i = x;
+        while ((unsigned) i < table->subtableZ[i].next) {
+            i = table->subtableZ[i].next;
+        }
+        init_group_size = i - x + 1;
+
+        move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
+        /* after that point x --> x_low, unless early term */
+        if (move_up == ZDD_MV_OOM)
+            goto cuddZddSymmSiftingAuxOutOfMem;
+
+        if (move_up == NULL ||
+            table->subtableZ[move_up->x].next != move_up->x) {
+            /* symmetry detected may have to make another complete
+                pass */
+            if (move_up != NULL)
+                x = move_up->x;
+            else {
+                while ((unsigned) x < table->subtableZ[x].next)
+                    x = table->subtableZ[x].next;
+            }
+            i = table->subtableZ[x].next;
+            final_group_size = x - i + 1;
+
+            if (init_group_size == final_group_size) {
+                /* No new symmetry groups detected,
+                   return to best position */
+                result = cuddZddSymmSiftingBackward(table, move_up,
+                    initial_size);
+            }
+            else {
+                initial_size = table->keysZ;
+                move_down = cuddZddSymmSifting_down(table, x, x_high,
+                    initial_size);
+                result = cuddZddSymmSiftingBackward(table, move_down,
+                    initial_size);
+            }
+        }
+        else {
+            result = cuddZddSymmSiftingBackward(table, move_up,
+                initial_size);
+            /* move backward and stop at best position */
+        }
+        if (!result)
+            goto cuddZddSymmSiftingAuxOutOfMem;
+    }
+    else if ((x - x_low) > (x_high - x)) { /* must go down first:
+                                                shorter */
+        /* Find bottom of x's symm group */
+        while ((unsigned) x < table->subtableZ[x].next)
+            x = table->subtableZ[x].next;
+
+        move_down = cuddZddSymmSifting_down(table, x, x_high,
+            initial_size);
+        /* after that point x --> x_high, unless early term */
+        if (move_down == ZDD_MV_OOM)
+            goto cuddZddSymmSiftingAuxOutOfMem;
+
+        if (move_down != NULL) {
+            x = move_down->y;
+        }
+        else {
+            x = table->subtableZ[x].next;
+        }
+        i = x;
+        while ((unsigned) i < table->subtableZ[i].next) {
+            i = table->subtableZ[i].next;
+        }
+        init_group_size = i - x + 1;
+
+        move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
+        if (move_up == ZDD_MV_OOM)
+            goto cuddZddSymmSiftingAuxOutOfMem;
+
+        if (move_up == NULL ||
+            table->subtableZ[move_up->x].next != move_up->x) {
+            /* symmetry detected may have to make another complete
+               pass */
+            if (move_up != NULL) {
+                x = move_up->x;
+            }
+            else {
+                while ((unsigned) x < table->subtableZ[x].next)
+                    x = table->subtableZ[x].next;
+            }
+            i = table->subtableZ[x].next;
+            final_group_size = x - i + 1;
+
+            if (init_group_size == final_group_size) {
+                /* No new symmetry groups detected,
+                   return to best position */
+                result = cuddZddSymmSiftingBackward(table, move_up,
+                    initial_size);
+            }
+            else {
+                while (move_down != NULL) {
+                    move = move_down->next;
+                    cuddDeallocMove(table, move_down);
+                    move_down = move;
+                }
+                initial_size = table->keysZ;
+                move_down = cuddZddSymmSifting_down(table, x, x_high,
+                    initial_size);
+                result = cuddZddSymmSiftingBackward(table, move_down,
+                    initial_size);
+            }
+        }
+        else {
+            result = cuddZddSymmSiftingBackward(table, move_up,
+                initial_size);
+            /* move backward and stop at best position */
+        }
+        if (!result)
+            goto cuddZddSymmSiftingAuxOutOfMem;
+    }
+    else { /* moving up first:shorter */
+        /* Find top of x's symmetry group */
+        while ((unsigned) x < table->subtableZ[x].next)
+            x = table->subtableZ[x].next;
+        x = table->subtableZ[x].next;
+
+        move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
+        /* after that point x --> x_high, unless early term */
+        if (move_up == ZDD_MV_OOM)
+            goto cuddZddSymmSiftingAuxOutOfMem;
+
+        if (move_up != NULL) {
+            x = move_up->x;
+        }
+        else {
+            while ((unsigned) x < table->subtableZ[x].next)
+                x = table->subtableZ[x].next;
+        }
+        i = table->subtableZ[x].next;
+        init_group_size = x - i + 1;
+
+        move_down = cuddZddSymmSifting_down(table, x, x_high,
+            initial_size);
+        if (move_down == ZDD_MV_OOM)
+            goto cuddZddSymmSiftingAuxOutOfMem;
+
+        if (move_down == NULL ||
+            table->subtableZ[move_down->y].next != move_down->y) {
+            /* symmetry detected may have to make another complete
+               pass */
+            if (move_down != NULL) {
+                x = move_down->y;
+            }
+            else {
+                x = table->subtableZ[x].next;
+            }
+            i = x;
+            while ((unsigned) i < table->subtableZ[i].next) {
+                i = table->subtableZ[i].next;
+            }
+            final_group_size = i - x + 1;
+
+            if (init_group_size == final_group_size) {
+                /* No new symmetries detected,
+                   go back to best position */
+                result = cuddZddSymmSiftingBackward(table, move_down,
+                    initial_size);
+            }
+            else {
+                while (move_up != NULL) {
+                    move = move_up->next;
+                    cuddDeallocMove(table, move_up);
+                    move_up = move;
+                }
+                initial_size = table->keysZ;
+                move_up = cuddZddSymmSifting_up(table, x, x_low,
+                    initial_size);
+                result = cuddZddSymmSiftingBackward(table, move_up,
+                    initial_size);
+            }
+        }
+        else {
+            result = cuddZddSymmSiftingBackward(table, move_down,
+                initial_size);
+            /* move backward and stop at best position */
+        }
+        if (!result)
+            goto cuddZddSymmSiftingAuxOutOfMem;
+    }
+
+    while (move_down != NULL) {
+        move = move_down->next;
+        cuddDeallocMove(table, move_down);
+        move_down = move;
+    }
+    while (move_up != NULL) {
+        move = move_up->next;
+        cuddDeallocMove(table, move_up);
+        move_up = move;
+    }
+
+    return(1);
+
+cuddZddSymmSiftingAuxOutOfMem:
+    if (move_down != ZDD_MV_OOM) {
+        while (move_down != NULL) {
+            move = move_down->next;
+            cuddDeallocMove(table, move_down);
+            move_down = move;
+        }
+    }
+    if (move_up != ZDD_MV_OOM) {
+        while (move_up != NULL) {
+            move = move_up->next;
+            cuddDeallocMove(table, move_up);
+            move_up = move;
+        }
+    }
+
+    return(0);
+
+} /* end of cuddZddSymmSiftingAux */
+
+
+/**Function********************************************************************
+
+  Synopsis [Given x_low <= x <= x_high moves x up and down between the
+  boundaries.]
+
+  Description [Given x_low <= x <= x_high moves x up and down between the
+  boundaries. Finds the best position and does the required changes.
+  Assumes that x is either an isolated variable, or it is the bottom of
+  a symmetry group. All symmetries may not have been found, because of
+  exceeded growth limit. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddSymmSiftingConvAux(
+  DdManager * table,
+  int  x,
+  int  x_low,
+  int  x_high)
+{
+    Move        *move;
+    Move        *move_up;       /* list of up move */
+    Move        *move_down;     /* list of down move */
+    int         initial_size;
+    int         result;
+    int         i;
+    int         init_group_size, final_group_size;
+
+    initial_size = table->keysZ;
+
+    move_down = NULL;
+    move_up = NULL;
+
+    if (x == x_low) { /* Sift down */
+        i = table->subtableZ[x].next;
+        init_group_size = x - i + 1;
+
+        move_down = cuddZddSymmSifting_down(table, x, x_high,
+            initial_size);
+        /* after that point x --> x_high, unless early term */
+        if (move_down == ZDD_MV_OOM)
+            goto cuddZddSymmSiftingConvAuxOutOfMem;
+
+        if (move_down == NULL ||
+            table->subtableZ[move_down->y].next != move_down->y) {
+            /* symmetry detected may have to make another complete
+                pass */
+            if (move_down != NULL)
+                x = move_down->y;
+            else {
+                while ((unsigned) x < table->subtableZ[x].next)
+                    x = table->subtableZ[x].next;
+                x = table->subtableZ[x].next;
+            }
+            i = x;
+            while ((unsigned) i < table->subtableZ[i].next) {
+                i = table->subtableZ[i].next;
+            }
+            final_group_size = i - x + 1;
+
+            if (init_group_size == final_group_size) {
+                /* No new symmetries detected,
+                   go back to best position */
+                result = cuddZddSymmSiftingBackward(table, move_down,
+                    initial_size);
+            }
+            else {
+                initial_size = table->keysZ;
+                move_up = cuddZddSymmSifting_up(table, x, x_low,
+                    initial_size);
+                result = cuddZddSymmSiftingBackward(table, move_up,
+                    initial_size);
+            }
+        }
+        else {
+            result = cuddZddSymmSiftingBackward(table, move_down,
+                initial_size);
+            /* move backward and stop at best position */
+        }
+        if (!result)
+            goto cuddZddSymmSiftingConvAuxOutOfMem;
+    }
+    else if (x == x_high) { /* Sift up */
+        /* Find top of x's symm group */
+        while ((unsigned) x < table->subtableZ[x].next)
+            x = table->subtableZ[x].next;
+        x = table->subtableZ[x].next;
+
+        i = x;
+        while ((unsigned) i < table->subtableZ[i].next) {
+            i = table->subtableZ[i].next;
+        }
+        init_group_size = i - x + 1;
+
+        move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
+        /* after that point x --> x_low, unless early term */
+        if (move_up == ZDD_MV_OOM)
+            goto cuddZddSymmSiftingConvAuxOutOfMem;
+
+        if (move_up == NULL ||
+            table->subtableZ[move_up->x].next != move_up->x) {
+            /* symmetry detected may have to make another complete
+               pass */
+            if (move_up != NULL)
+                x = move_up->x;
+            else {
+                while ((unsigned) x < table->subtableZ[x].next)
+                    x = table->subtableZ[x].next;
+            }
+            i = table->subtableZ[x].next;
+            final_group_size = x - i + 1;
+
+            if (init_group_size == final_group_size) {
+                /* No new symmetry groups detected,
+                   return to best position */
+                result = cuddZddSymmSiftingBackward(table, move_up,
+                    initial_size);
+            }
+            else {
+                initial_size = table->keysZ;
+                move_down = cuddZddSymmSifting_down(table, x, x_high,
+                    initial_size);
+                result = cuddZddSymmSiftingBackward(table, move_down,
+                    initial_size);
+            }
+        }
+        else {
+            result = cuddZddSymmSiftingBackward(table, move_up,
+                initial_size);
+            /* move backward and stop at best position */
+        }
+        if (!result)
+            goto cuddZddSymmSiftingConvAuxOutOfMem;
+    }
+    else if ((x - x_low) > (x_high - x)) { /* must go down first:
+                                                shorter */
+        move_down = cuddZddSymmSifting_down(table, x, x_high,
+            initial_size);
+        /* after that point x --> x_high */
+        if (move_down == ZDD_MV_OOM)
+            goto cuddZddSymmSiftingConvAuxOutOfMem;
+
+        if (move_down != NULL) {
+            x = move_down->y;
+        }
+        else {
+            while ((unsigned) x < table->subtableZ[x].next)
+                x = table->subtableZ[x].next;
+            x = table->subtableZ[x].next;
+        }
+        i = x;
+        while ((unsigned) i < table->subtableZ[i].next) {
+            i = table->subtableZ[i].next;
+        }
+        init_group_size = i - x + 1;
+
+        move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
+        if (move_up == ZDD_MV_OOM)
+            goto cuddZddSymmSiftingConvAuxOutOfMem;
+
+        if (move_up == NULL ||
+            table->subtableZ[move_up->x].next != move_up->x) {
+            /* symmetry detected may have to make another complete
+               pass */
+            if (move_up != NULL) {
+                x = move_up->x;
+            }
+            else {
+                while ((unsigned) x < table->subtableZ[x].next)
+                    x = table->subtableZ[x].next;
+            }
+            i = table->subtableZ[x].next;
+            final_group_size = x - i + 1;
+
+            if (init_group_size == final_group_size) {
+                /* No new symmetry groups detected,
+                   return to best position */
+                result = cuddZddSymmSiftingBackward(table, move_up,
+                    initial_size);
+            }
+            else {
+                while (move_down != NULL) {
+                    move = move_down->next;
+                    cuddDeallocMove(table, move_down);
+                    move_down = move;
+                }
+                initial_size = table->keysZ;
+                move_down = cuddZddSymmSifting_down(table, x, x_high,
+                    initial_size);
+                result = cuddZddSymmSiftingBackward(table, move_down,
+                    initial_size);
+            }
+        }
+        else {
+            result = cuddZddSymmSiftingBackward(table, move_up,
+                initial_size);
+            /* move backward and stop at best position */
+        }
+        if (!result)
+            goto cuddZddSymmSiftingConvAuxOutOfMem;
+    }
+    else { /* moving up first:shorter */
+        /* Find top of x's symmetry group */
+        x = table->subtableZ[x].next;
+
+        move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
+        /* after that point x --> x_high, unless early term */
+        if (move_up == ZDD_MV_OOM)
+            goto cuddZddSymmSiftingConvAuxOutOfMem;
+
+        if (move_up != NULL) {
+            x = move_up->x;
+        }
+        else {
+            while ((unsigned) x < table->subtableZ[x].next)
+                x = table->subtableZ[x].next;
+        }
+        i = table->subtableZ[x].next;
+        init_group_size = x - i + 1;
+
+        move_down = cuddZddSymmSifting_down(table, x, x_high,
+            initial_size);
+        if (move_down == ZDD_MV_OOM)
+            goto cuddZddSymmSiftingConvAuxOutOfMem;
+
+        if (move_down == NULL ||
+            table->subtableZ[move_down->y].next != move_down->y) {
+            /* symmetry detected may have to make another complete
+               pass */
+            if (move_down != NULL) {
+                x = move_down->y;
+            }
+            else {
+                while ((unsigned) x < table->subtableZ[x].next)
+                    x = table->subtableZ[x].next;
+                x = table->subtableZ[x].next;
+            }
+            i = x;
+            while ((unsigned) i < table->subtableZ[i].next) {
+                i = table->subtableZ[i].next;
+            }
+            final_group_size = i - x + 1;
+
+            if (init_group_size == final_group_size) {
+                /* No new symmetries detected,
+                   go back to best position */
+                result = cuddZddSymmSiftingBackward(table, move_down,
+                    initial_size);
+            }
+            else {
+                while (move_up != NULL) {
+                    move = move_up->next;
+                    cuddDeallocMove(table, move_up);
+                    move_up = move;
+                }
+                initial_size = table->keysZ;
+                move_up = cuddZddSymmSifting_up(table, x, x_low,
+                    initial_size);
+                result = cuddZddSymmSiftingBackward(table, move_up,
+                    initial_size);
+            }
+        }
+        else {
+            result = cuddZddSymmSiftingBackward(table, move_down,
+                initial_size);
+            /* move backward and stop at best position */
+        }
+        if (!result)
+            goto cuddZddSymmSiftingConvAuxOutOfMem;
+    }
+
+    while (move_down != NULL) {
+        move = move_down->next;
+        cuddDeallocMove(table, move_down);
+        move_down = move;
+    }
+    while (move_up != NULL) {
+        move = move_up->next;
+        cuddDeallocMove(table, move_up);
+        move_up = move;
+    }
+
+    return(1);
+
+cuddZddSymmSiftingConvAuxOutOfMem:
+    if (move_down != ZDD_MV_OOM) {
+        while (move_down != NULL) {
+            move = move_down->next;
+            cuddDeallocMove(table, move_down);
+            move_down = move;
+        }
+    }
+    if (move_up != ZDD_MV_OOM) {
+        while (move_up != NULL) {
+            move = move_up->next;
+            cuddDeallocMove(table, move_up);
+            move_up = move;
+        }
+    }
+
+    return(0);
+
+} /* end of cuddZddSymmSiftingConvAux */
+
+
+/**Function********************************************************************
+
+  Synopsis [Moves x up until either it reaches the bound (x_low) or
+  the size of the ZDD heap increases too much.]
+
+  Description [Moves x up until either it reaches the bound (x_low) or
+  the size of the ZDD heap increases too much. Assumes that x is the top
+  of a symmetry group.  Checks x for symmetry to the adjacent
+  variables. If symmetry is found, the symmetry group of x is merged
+  with the symmetry group of the other variable. Returns the set of
+  moves in case of success; ZDD_MV_OOM if memory is full.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+cuddZddSymmSifting_up(
+  DdManager * table,
+  int  x,
+  int  x_low,
+  int  initial_size)
+{
+    Move        *moves;
+    Move        *move;
+    int         y;
+    int         size;
+    int         limit_size = initial_size;
+    int         i, gytop;
+
+    moves = NULL;
+    y = cuddZddNextLow(table, x);
+    while (y >= x_low) {
+        gytop = table->subtableZ[y].next;
+        if (cuddZddSymmCheck(table, y, x)) {
+            /* Symmetry found, attach symm groups */
+            table->subtableZ[y].next = x;
+            i = table->subtableZ[x].next;
+            while (table->subtableZ[i].next != (unsigned) x)
+                i = table->subtableZ[i].next;
+            table->subtableZ[i].next = gytop;
+        }
+        else if ((table->subtableZ[x].next == (unsigned) x) &&
+            (table->subtableZ[y].next == (unsigned) y)) {
+            /* x and y have self symmetry */
+            size = cuddZddSwapInPlace(table, y, x);
+            if (size == 0)
+                goto cuddZddSymmSifting_upOutOfMem;
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL)
+                goto cuddZddSymmSifting_upOutOfMem;
+            move->x = y;
+            move->y = x;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+            if ((double)size >
+                (double)limit_size * table->maxGrowth)
+                return(moves);
+            if (size < limit_size)
+                limit_size = size;
+        }
+        else { /* Group move */
+            size = zdd_group_move(table, y, x, &moves);
+            if ((double)size >
+                (double)limit_size * table->maxGrowth)
+                return(moves);
+            if (size < limit_size)
+                limit_size = size;
+        }
+        x = gytop;
+        y = cuddZddNextLow(table, x);
+    }
+
+    return(moves);
+
+cuddZddSymmSifting_upOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return(ZDD_MV_OOM);
+
+} /* end of cuddZddSymmSifting_up */
+
+
+/**Function********************************************************************
+
+  Synopsis [Moves x down until either it reaches the bound (x_high) or
+  the size of the ZDD heap increases too much.]
+
+  Description [Moves x down until either it reaches the bound (x_high)
+  or the size of the ZDD heap increases too much. Assumes that x is the
+  bottom of a symmetry group. Checks x for symmetry to the adjacent
+  variables. If symmetry is found, the symmetry group of x is merged
+  with the symmetry group of the other variable. Returns the set of
+  moves in case of success; ZDD_MV_OOM if memory is full.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+cuddZddSymmSifting_down(
+  DdManager * table,
+  int  x,
+  int  x_high,
+  int  initial_size)
+{
+    Move        *moves;
+    Move        *move;
+    int         y;
+    int         size;
+    int         limit_size = initial_size;
+    int         i, gxtop, gybot;
+
+    moves = NULL;
+    y = cuddZddNextHigh(table, x);
+    while (y <= x_high) {
+        gybot = table->subtableZ[y].next;
+        while (table->subtableZ[gybot].next != (unsigned) y)
+            gybot = table->subtableZ[gybot].next;
+        if (cuddZddSymmCheck(table, x, y)) {
+            /* Symmetry found, attach symm groups */
+            gxtop = table->subtableZ[x].next;
+            table->subtableZ[x].next = y;
+            i = table->subtableZ[y].next;
+            while (table->subtableZ[i].next != (unsigned) y)
+                i = table->subtableZ[i].next;
+            table->subtableZ[i].next = gxtop;
+        }
+        else if ((table->subtableZ[x].next == (unsigned) x) &&
+            (table->subtableZ[y].next == (unsigned) y)) {
+            /* x and y have self symmetry */
+            size = cuddZddSwapInPlace(table, x, y);
+            if (size == 0)
+                goto cuddZddSymmSifting_downOutOfMem;
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL)
+                goto cuddZddSymmSifting_downOutOfMem;
+            move->x = x;
+            move->y = y;
+            move->size = size;
+            move->next = moves;
+            moves = move;
+            if ((double)size >
+                (double)limit_size * table->maxGrowth)
+                return(moves);
+            if (size < limit_size)
+                limit_size = size;
+            x = y;
+            y = cuddZddNextHigh(table, x);
+        }
+        else { /* Group move */
+            size = zdd_group_move(table, x, y, &moves);
+            if ((double)size >
+                (double)limit_size * table->maxGrowth)
+                return(moves);
+            if (size < limit_size)
+                limit_size = size;
+        }
+        x = gybot;
+        y = cuddZddNextHigh(table, x);
+    }
+
+    return(moves);
+
+cuddZddSymmSifting_downOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return(ZDD_MV_OOM);
+
+} /* end of cuddZddSymmSifting_down */
+
+
+/**Function********************************************************************
+
+  Synopsis [Given a set of moves, returns the ZDD heap to the position
+  giving the minimum size.]
+
+  Description [Given a set of moves, returns the ZDD heap to the
+  position giving the minimum size. In case of ties, returns to the
+  closest position giving the minimum size. Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddSymmSiftingBackward(
+  DdManager * table,
+  Move * moves,
+  int  size)
+{
+    int         i;
+    int         i_best;
+    Move        *move;
+    int         res = -1;
+
+    i_best = -1;
+    for (move = moves, i = 0; move != NULL; move = move->next, i++) {
+        if (move->size < size) {
+            i_best = i;
+            size = move->size;
+        }
+    }
+
+    for (move = moves, i = 0; move != NULL; move = move->next, i++) {
+        if (i == i_best) break;
+        if ((table->subtableZ[move->x].next == move->x) &&
+            (table->subtableZ[move->y].next == move->y)) {
+            res = cuddZddSwapInPlace(table, move->x, move->y);
+            if (!res) return(0);
+        }
+        else { /* Group move necessary */
+            res = zdd_group_move_backward(table, move->x, move->y);
+        }
+        if (i_best == -1 && res == size)
+            break;
+    }
+
+    return(1);
+
+} /* end of cuddZddSymmSiftingBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis [Swaps two groups.]
+
+  Description [Swaps two groups. x is assumed to be the bottom variable
+  of the first group. y is assumed to be the top variable of the second
+  group.  Updates the list of moves. Returns the number of keys in the
+  table if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+zdd_group_move(
+  DdManager * table,
+  int  x,
+  int  y,
+  Move ** moves)
+{
+    Move        *move;
+    int         size;
+    int         i, temp, gxtop, gxbot, gybot, yprev;
+    int         swapx = -1, swapy = -1;
+
+#ifdef DD_DEBUG
+    assert(x < y);      /* we assume that x < y */
+#endif
+    /* Find top and bottom for the two groups. */
+    gxtop = table->subtableZ[x].next;
+    gxbot = x;
+    gybot = table->subtableZ[y].next;
+    while (table->subtableZ[gybot].next != (unsigned) y)
+        gybot = table->subtableZ[gybot].next;
+    yprev = gybot;
+
+    while (x <= y) {
+        while (y > gxtop) {
+            /* Set correct symmetries. */
+            temp = table->subtableZ[x].next;
+            if (temp == x)
+                temp = y;
+            i = gxtop;
+            for (;;) {
+                if (table->subtableZ[i].next == (unsigned) x) {
+                    table->subtableZ[i].next = y;
+                    break;
+                } else {
+                    i = table->subtableZ[i].next;
+                }
+            }
+            if (table->subtableZ[y].next != (unsigned) y) {
+                table->subtableZ[x].next = table->subtableZ[y].next;
+            } else {
+                table->subtableZ[x].next = x;
+            }
+
+            if (yprev != y) {
+                table->subtableZ[yprev].next = x;
+            } else {
+                yprev = x;
+            }
+            table->subtableZ[y].next = temp;
+
+            size = cuddZddSwapInPlace(table, x, y);
+            if (size == 0)
+                goto zdd_group_moveOutOfMem;
+            swapx = x;
+            swapy = y;
+            y = x;
+            x--;
+        } /* while y > gxtop */
+
+        /* Trying to find the next y. */
+        if (table->subtableZ[y].next <= (unsigned) y) {
+            gybot = y;
+        } else {
+            y = table->subtableZ[y].next;
+        }
+
+        yprev = gxtop;
+        gxtop++;
+        gxbot++;
+        x = gxbot;
+    } /* while x <= y, end of group movement */
+    move = (Move *)cuddDynamicAllocNode(table);
+    if (move == NULL)
+        goto zdd_group_moveOutOfMem;
+    move->x = swapx;
+    move->y = swapy;
+    move->size = table->keysZ;
+    move->next = *moves;
+    *moves = move;
+
+    return(table->keysZ);
+
+zdd_group_moveOutOfMem:
+    while (*moves != NULL) {
+        move = (*moves)->next;
+        cuddDeallocMove(table, *moves);
+        *moves = move;
+    }
+    return(0);
+
+} /* end of zdd_group_move */
+
+
+/**Function********************************************************************
+
+  Synopsis [Undoes the swap of two groups.]
+
+  Description [Undoes the swap of two groups. x is assumed to be the
+  bottom variable of the first group. y is assumed to be the top
+  variable of the second group.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+zdd_group_move_backward(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int        size = -1;
+    int        i, temp, gxtop, gxbot, gybot, yprev;
+
+#ifdef DD_DEBUG
+    assert(x < y);      /* we assume that x < y */
+#endif
+    /* Find top and bottom of the two groups. */
+    gxtop = table->subtableZ[x].next;
+    gxbot = x;
+    gybot = table->subtableZ[y].next;
+    while (table->subtableZ[gybot].next != (unsigned) y)
+        gybot = table->subtableZ[gybot].next;
+    yprev = gybot;
+
+    while (x <= y) {
+        while (y > gxtop) {
+            /* Set correct symmetries. */
+            temp = table->subtableZ[x].next;
+            if (temp == x)
+                temp = y;
+            i = gxtop;
+            for (;;) {
+                if (table->subtableZ[i].next == (unsigned) x) {
+                    table->subtableZ[i].next = y;
+                    break;
+                } else {
+                    i = table->subtableZ[i].next;
+                }
+            }
+            if (table->subtableZ[y].next != (unsigned) y) {
+                table->subtableZ[x].next = table->subtableZ[y].next;
+            } else {
+                table->subtableZ[x].next = x;
+            }
+
+            if (yprev != y) {
+                table->subtableZ[yprev].next = x;
+            } else {
+                yprev = x;
+            }
+            table->subtableZ[y].next = temp;
+
+            size = cuddZddSwapInPlace(table, x, y);
+            if (size == 0)
+                return(0);
+            y = x;
+            x--;
+        } /* while y > gxtop */
+
+        /* Trying to find the next y. */
+        if (table->subtableZ[y].next <= (unsigned) y) {
+            gybot = y;
+        } else {
+            y = table->subtableZ[y].next;
+        }
+
+        yprev = gxtop;
+        gxtop++;
+        gxbot++;
+        x = gxbot;
+    } /* while x <= y, end of group movement backward */
+
+    return(size);
+
+} /* end of zdd_group_move_backward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts numbers of symmetric variables and symmetry
+  groups.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+cuddZddSymmSummary(
+  DdManager * table,
+  int  lower,
+  int  upper,
+  int * symvars,
+  int * symgroups)
+{
+    int i,x,gbot;
+    int TotalSymm = 0;
+    int TotalSymmGroups = 0;
+
+    for (i = lower; i <= upper; i++) {
+        if (table->subtableZ[i].next != (unsigned) i) {
+            TotalSymmGroups++;
+            x = i;
+            do {
+                TotalSymm++;
+                gbot = x;
+                x = table->subtableZ[x].next;
+            } while (x != i);
+#ifdef DD_DEBUG
+            assert(table->subtableZ[gbot].next == (unsigned) i);
+#endif
+            i = gbot;
+        }
+    }
+    *symvars = TotalSymm;
+    *symgroups = TotalSymmGroups;
+
+    return;
+
+} /* end of cuddZddSymmSummary */
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/bdd/cudd/cuddZddUtil.c b/abc-build/src/bdd/cudd/cuddZddUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/cuddZddUtil.c
@@ -0,0 +1,1071 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddUtil.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Utility functions for ZDDs.]
+
+  Description [External procedures included in this module:
+                    <ul>
+                    <li> Cudd_zddPrintMinterm()
+                    <li> Cudd_zddPrintCover()
+                    <li> Cudd_zddPrintDebug()
+                    <li> Cudd_zddFirstPath()
+                    <li> Cudd_zddNextPath()
+                    <li> Cudd_zddCoverPathToString()
+                    <li> Cudd_zddDumpDot()
+                    </ul>
+               Internal procedures included in this module:
+                    <ul>
+                    <li> cuddZddP()
+                    </ul>
+               Static procedures included in this module:
+                    <ul>
+                    <li> zp2()
+                    <li> zdd_print_minterm_aux()
+                    <li> zddPrintCoverAux()
+                    </ul>
+              ]
+
+  SeeAlso     []
+
+  Author      [Hyong-Kyoon Shin, In-Ho Moon, Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "cuddInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddUtil.c,v 1.27 2009/03/08 02:49:02 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int zp2 (DdManager *zdd, DdNode *f, st__table *t);
+static void zdd_print_minterm_aux (DdManager *zdd, DdNode *node, int level, int *list);
+static void zddPrintCoverAux (DdManager *zdd, DdNode *node, int level, int *list);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a disjoint sum of product form for a ZDD.]
+
+  Description [Prints a disjoint sum of product form for a ZDD. Returns 1
+  if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddPrintDebug Cudd_zddPrintCover]
+
+******************************************************************************/
+int
+Cudd_zddPrintMinterm(
+  DdManager * zdd,
+  DdNode * node)
+{
+    int         i, size;
+    int         *list;
+
+    size = (int)zdd->sizeZ;
+    list = ABC_ALLOC(int, size);
+    if (list == NULL) {
+        zdd->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    for (i = 0; i < size; i++) list[i] = 3; /* bogus value should disappear */
+    zdd_print_minterm_aux(zdd, node, 0, list);
+    ABC_FREE(list);
+    return(1);
+
+} /* end of Cudd_zddPrintMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a sum of products from a ZDD representing a cover.]
+
+  Description [Prints a sum of products from a ZDD representing a cover.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddPrintMinterm]
+
+******************************************************************************/
+int
+Cudd_zddPrintCover(
+  DdManager * zdd,
+  DdNode * node)
+{
+    int         i, size;
+    int         *list;
+
+    size = (int)zdd->sizeZ;
+    if (size % 2 != 0) return(0); /* number of variables should be even */
+    list = ABC_ALLOC(int, size);
+    if (list == NULL) {
+        zdd->errorCode = CUDD_MEMORY_OUT;
+        return(0);
+    }
+    for (i = 0; i < size; i++) list[i] = 3; /* bogus value should disappear */
+    zddPrintCoverAux(zdd, node, 0, list);
+    ABC_FREE(list);
+    return(1);
+
+} /* end of Cudd_zddPrintCover */
+
+
+/**Function********************************************************************
+
+  Synopsis [Prints to the standard output a ZDD and its statistics.]
+
+  Description [Prints to the standard output a DD and its statistics.
+  The statistics include the number of nodes and the number of minterms.
+  (The number of minterms is also the number of combinations in the set.)
+  The statistics are printed if pr &gt; 0.  Specifically:
+  <ul>
+  <li> pr = 0 : prints nothing
+  <li> pr = 1 : prints counts of nodes and minterms
+  <li> pr = 2 : prints counts + disjoint sum of products
+  <li> pr = 3 : prints counts + list of nodes
+  <li> pr &gt; 3 : prints counts + disjoint sum of products + list of nodes
+  </ul>
+  Returns 1 if successful; 0 otherwise.
+  ]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_zddPrintDebug(
+  DdManager * zdd,
+  DdNode * f,
+  int  n,
+  int  pr)
+{
+    DdNode      *empty = DD_ZERO(zdd);
+    int         nodes;
+    double      minterms;
+    int         retval = 1;
+
+    if (f == empty && pr > 0) {
+        (void) fprintf(zdd->out,": is the empty ZDD\n");
+        (void) fflush(zdd->out);
+        return(1);
+    }
+
+    if (pr > 0) {
+        nodes = Cudd_zddDagSize(f);
+        if (nodes == CUDD_OUT_OF_MEM) retval = 0;
+        minterms = Cudd_zddCountMinterm(zdd, f, n);
+        if (minterms == (double)CUDD_OUT_OF_MEM) retval = 0;
+        (void) fprintf(zdd->out,": %d nodes %g minterms\n",
+                       nodes, minterms);
+        if (pr > 2)
+            if (!cuddZddP(zdd, f)) retval = 0;
+        if (pr == 2 || pr > 3) {
+            if (!Cudd_zddPrintMinterm(zdd, f)) retval = 0;
+            (void) fprintf(zdd->out,"\n");
+        }
+        (void) fflush(zdd->out);
+    }
+    return(retval);
+
+} /* end of Cudd_zddPrintDebug */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the first path of a ZDD.]
+
+  Description [Defines an iterator on the paths of a ZDD
+  and finds its first path. Returns a generator that contains the
+  information necessary to continue the enumeration if successful; NULL
+  otherwise.<p>
+  A path is represented as an array of literals, which are integers in
+  {0, 1, 2}; 0 represents an else arc out of a node, 1 represents a then arc
+  out of a node, and 2 stands for the absence of a node.
+  The size of the array equals the number of variables in the manager at
+  the time Cudd_zddFirstCube is called.<p>
+  The paths that end in the empty terminal are not enumerated.]
+
+  SideEffects [The first path is returned as a side effect.]
+
+  SeeAlso     [Cudd_zddForeachPath Cudd_zddNextPath Cudd_GenFree
+  Cudd_IsGenEmpty]
+
+******************************************************************************/
+DdGen *
+Cudd_zddFirstPath(
+  DdManager * zdd,
+  DdNode * f,
+  int ** path)
+{
+    DdGen *gen;
+    DdNode *top, *next, *prev;
+    int i;
+    int nvars;
+
+    /* Sanity Check. */
+    if (zdd == NULL || f == NULL) return(NULL);
+
+    /* Allocate generator an initialize it. */
+    gen = ABC_ALLOC(DdGen,1);
+    if (gen == NULL) {
+        zdd->errorCode = CUDD_MEMORY_OUT;
+        return(NULL);
+    }
+
+    gen->manager = zdd;
+    gen->type = CUDD_GEN_ZDD_PATHS;
+    gen->status = CUDD_GEN_EMPTY;
+    gen->gen.cubes.cube = NULL;
+    gen->gen.cubes.value = DD_ZERO_VAL;
+    gen->stack.sp = 0;
+    gen->stack.stack = NULL;
+    gen->node = NULL;
+
+    nvars = zdd->sizeZ;
+    gen->gen.cubes.cube = ABC_ALLOC(int,nvars);
+    if (gen->gen.cubes.cube == NULL) {
+        zdd->errorCode = CUDD_MEMORY_OUT;
+        ABC_FREE(gen);
+        return(NULL);
+    }
+    for (i = 0; i < nvars; i++) gen->gen.cubes.cube[i] = 2;
+
+    /* The maximum stack depth is one plus the number of variables.
+    ** because a path may have nodes at all levels, including the
+    ** constant level.
+    */
+    gen->stack.stack = ABC_ALLOC(DdNodePtr, nvars+1);
+    if (gen->stack.stack == NULL) {
+        zdd->errorCode = CUDD_MEMORY_OUT;
+        ABC_FREE(gen->gen.cubes.cube);
+        ABC_FREE(gen);
+        return(NULL);
+    }
+    for (i = 0; i <= nvars; i++) gen->stack.stack[i] = NULL;
+
+    /* Find the first path of the ZDD. */
+    gen->stack.stack[gen->stack.sp] = f; gen->stack.sp++;
+
+    while (1) {
+        top = gen->stack.stack[gen->stack.sp-1];
+        if (!cuddIsConstant(Cudd_Regular(top))) {
+            /* Take the else branch first. */
+            gen->gen.cubes.cube[Cudd_Regular(top)->index] = 0;
+            next = cuddE(Cudd_Regular(top));
+            gen->stack.stack[gen->stack.sp] = Cudd_Not(next); gen->stack.sp++;
+        } else if (Cudd_Regular(top) == DD_ZERO(zdd)) {
+            /* Backtrack. */
+            while (1) {
+                if (gen->stack.sp == 1) {
+                    /* The current node has no predecessor. */
+                    gen->status = CUDD_GEN_EMPTY;
+                    gen->stack.sp--;
+                    goto done;
+                }
+                prev = Cudd_Regular(gen->stack.stack[gen->stack.sp-2]);
+                next = cuddT(prev);
+                if (next != top) { /* follow the then branch next */
+                    gen->gen.cubes.cube[prev->index] = 1;
+                    gen->stack.stack[gen->stack.sp-1] = next;
+                    break;
+                }
+                /* Pop the stack and try again. */
+                gen->gen.cubes.cube[prev->index] = 2;
+                gen->stack.sp--;
+                top = gen->stack.stack[gen->stack.sp-1];
+            }
+        } else {
+            gen->status = CUDD_GEN_NONEMPTY;
+            gen->gen.cubes.value = cuddV(Cudd_Regular(top));
+            goto done;
+        }
+    }
+
+done:
+    *path = gen->gen.cubes.cube;
+    return(gen);
+
+} /* end of Cudd_zddFirstPath */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates the next path of a ZDD.]
+
+  Description [Generates the next path of a ZDD onset,
+  using generator gen. Returns 0 if the enumeration is completed; 1
+  otherwise.]
+
+  SideEffects [The path is returned as a side effect. The
+  generator is modified.]
+
+  SeeAlso     [Cudd_zddForeachPath Cudd_zddFirstPath Cudd_GenFree
+  Cudd_IsGenEmpty]
+
+******************************************************************************/
+int
+Cudd_zddNextPath(
+  DdGen * gen,
+  int ** path)
+{
+    DdNode *top, *next, *prev;
+    DdManager *zdd = gen->manager;
+
+    /* Backtrack from previously reached terminal node. */
+    while (1) {
+        if (gen->stack.sp == 1) {
+            /* The current node has no predecessor. */
+            gen->status = CUDD_GEN_EMPTY;
+            gen->stack.sp--;
+            goto done;
+        }
+        top = gen->stack.stack[gen->stack.sp-1];
+        prev = Cudd_Regular(gen->stack.stack[gen->stack.sp-2]);
+        next = cuddT(prev);
+        if (next != top) { /* follow the then branch next */
+            gen->gen.cubes.cube[prev->index] = 1;
+            gen->stack.stack[gen->stack.sp-1] = next;
+            break;
+        }
+        /* Pop the stack and try again. */
+        gen->gen.cubes.cube[prev->index] = 2;
+        gen->stack.sp--;
+    }
+
+    while (1) {
+        top = gen->stack.stack[gen->stack.sp-1];
+        if (!cuddIsConstant(Cudd_Regular(top))) {
+            /* Take the else branch first. */
+            gen->gen.cubes.cube[Cudd_Regular(top)->index] = 0;
+            next = cuddE(Cudd_Regular(top));
+            gen->stack.stack[gen->stack.sp] = Cudd_Not(next); gen->stack.sp++;
+        } else if (Cudd_Regular(top) == DD_ZERO(zdd)) {
+            /* Backtrack. */
+            while (1) {
+                if (gen->stack.sp == 1) {
+                    /* The current node has no predecessor. */
+                    gen->status = CUDD_GEN_EMPTY;
+                    gen->stack.sp--;
+                    goto done;
+                }
+                prev = Cudd_Regular(gen->stack.stack[gen->stack.sp-2]);
+                next = cuddT(prev);
+                if (next != top) { /* follow the then branch next */
+                    gen->gen.cubes.cube[prev->index] = 1;
+                    gen->stack.stack[gen->stack.sp-1] = next;
+                    break;
+                }
+                /* Pop the stack and try again. */
+                gen->gen.cubes.cube[prev->index] = 2;
+                gen->stack.sp--;
+                top = gen->stack.stack[gen->stack.sp-1];
+            }
+        } else {
+            gen->status = CUDD_GEN_NONEMPTY;
+            gen->gen.cubes.value = cuddV(Cudd_Regular(top));
+            goto done;
+        }
+    }
+
+done:
+    if (gen->status == CUDD_GEN_EMPTY) return(0);
+    *path = gen->gen.cubes.cube;
+    return(1);
+
+} /* end of Cudd_zddNextPath */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a path of a ZDD representing a cover to a string.]
+
+  Description [Converts a path of a ZDD representing a cover to a
+  string.  The string represents an implicant of the cover.  The path
+  is typically produced by Cudd_zddForeachPath.  Returns a pointer to
+  the string if successful; NULL otherwise.  If the str input is NULL,
+  it allocates a new string.  The string passed to this function must
+  have enough room for all variables and for the terminator.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddForeachPath]
+
+******************************************************************************/
+char *
+Cudd_zddCoverPathToString(
+  DdManager *zdd                /* DD manager */,
+  int *path                     /* path of ZDD representing a cover */,
+  char *str                     /* pointer to string to use if != NULL */
+  )
+{
+    int nvars = zdd->sizeZ;
+    int i;
+    char *res;
+
+    if (nvars & 1) return(NULL);
+    nvars >>= 1;
+    if (str == NULL) {
+        res = ABC_ALLOC(char, nvars+1);
+        if (res == NULL) return(NULL);
+    } else {
+        res = str;
+    }
+    for (i = 0; i < nvars; i++) {
+        int v = (path[2*i] << 2) | path[2*i+1];
+        switch (v) {
+        case 0:
+        case 2:
+        case 8:
+        case 10:
+            res[i] = '-';
+            break;
+        case 1:
+        case 9:
+            res[i] = '0';
+            break;
+        case 4:
+        case 6:
+            res[i] = '1';
+            break;
+        default:
+            res[i] = '?';
+        }
+    }
+    res[nvars] = 0;
+
+    return(res);
+
+} /* end of Cudd_zddCoverPathToString */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a dot file representing the argument ZDDs.]
+
+  Description [Writes a file representing the argument ZDDs in a format
+  suitable for the graph drawing program dot.
+  It returns 1 in case of success; 0 otherwise (e.g., out-of-memory,
+  file system full).
+  Cudd_zddDumpDot does not close the file: This is the caller
+  responsibility. Cudd_zddDumpDot uses a minimal unique subset of the
+  hexadecimal address of a node as name for it.
+  If the argument inames is non-null, it is assumed to hold the pointers
+  to the names of the inputs. Similarly for onames.
+  Cudd_zddDumpDot uses the following convention to draw arcs:
+    <ul>
+    <li> solid line: THEN arcs;
+    <li> dashed line: ELSE arcs.
+    </ul>
+  The dot options are chosen so that the drawing fits on a letter-size
+  sheet.
+  ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DumpDot Cudd_zddPrintDebug]
+
+******************************************************************************/
+int
+Cudd_zddDumpDot(
+  DdManager * dd /* manager */,
+  int  n /* number of output nodes to be dumped */,
+  DdNode ** f /* array of output nodes to be dumped */,
+  char ** inames /* array of input names (or NULL) */,
+  char ** onames /* array of output names (or NULL) */,
+  FILE * fp /* pointer to the dump file */)
+{
+    DdNode      *support = NULL;
+    DdNode      *scan;
+    int         *sorted = NULL;
+    int         nvars = dd->sizeZ;
+    st__table    *visited = NULL;
+    st__generator *gen;
+    int         retval;
+    int         i, j;
+    int         slots;
+    DdNodePtr   *nodelist;
+    long        refAddr, diff, mask;
+
+    /* Build a bit array with the support of f. */
+    sorted = ABC_ALLOC(int,nvars);
+    if (sorted == NULL) {
+        dd->errorCode = CUDD_MEMORY_OUT;
+        goto failure;
+    }
+    for (i = 0; i < nvars; i++) sorted[i] = 0;
+
+    /* Take the union of the supports of each output function. */
+    for (i = 0; i < n; i++) {
+        support = Cudd_Support(dd,f[i]);
+        if (support == NULL) goto failure;
+        cuddRef(support);
+        scan = support;
+        while (!cuddIsConstant(scan)) {
+            sorted[scan->index] = 1;
+            scan = cuddT(scan);
+        }
+        Cudd_RecursiveDeref(dd,support);
+    }
+    support = NULL; /* so that we do not try to free it in case of failure */
+
+    /* Initialize symbol table for visited nodes. */
+    visited = st__init_table( st__ptrcmp, st__ptrhash);
+    if (visited == NULL) goto failure;
+
+    /* Collect all the nodes of this DD in the symbol table. */
+    for (i = 0; i < n; i++) {
+        retval = cuddCollectNodes(f[i],visited);
+        if (retval == 0) goto failure;
+    }
+
+    /* Find how many most significant hex digits are identical
+    ** in the addresses of all the nodes. Build a mask based
+    ** on this knowledge, so that digits that carry no information
+    ** will not be printed. This is done in two steps.
+    **  1. We scan the symbol table to find the bits that differ
+    **     in at least 2 addresses.
+    **  2. We choose one of the possible masks. There are 8 possible
+    **     masks for 32-bit integer, and 16 possible masks for 64-bit
+    **     integers.
+    */
+
+    /* Find the bits that are different. */
+    refAddr = (long) f[0];
+    diff = 0;
+    gen = st__init_gen(visited);
+    while ( st__gen(gen, (const char **)&scan, NULL)) {
+        diff |= refAddr ^ (long) scan;
+    }
+    st__free_gen(gen);
+
+    /* Choose the mask. */
+    for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) {
+        mask = (1 << i) - 1;
+        if (diff <= mask) break;
+    }
+
+    /* Write the header and the global attributes. */
+    retval = fprintf(fp,"digraph \"ZDD\" {\n");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,
+        "size = \"7.5,10\"\ncenter = true;\nedge [dir = none];\n");
+    if (retval == EOF) return(0);
+
+    /* Write the input name subgraph by scanning the support array. */
+    retval = fprintf(fp,"{ node [shape = plaintext];\n");
+    if (retval == EOF) goto failure;
+    retval = fprintf(fp,"  edge [style = invis];\n");
+    if (retval == EOF) goto failure;
+    /* We use a name ("CONST NODES") with an embedded blank, because
+    ** it is unlikely to appear as an input name.
+    */
+    retval = fprintf(fp,"  \"CONST NODES\" [style = invis];\n");
+    if (retval == EOF) goto failure;
+    for (i = 0; i < nvars; i++) {
+        if (sorted[dd->invpermZ[i]]) {
+            if (inames == NULL) {
+                retval = fprintf(fp,"\" %d \" -> ", dd->invpermZ[i]);
+            } else {
+                retval = fprintf(fp,"\" %s \" -> ", inames[dd->invpermZ[i]]);
+            }
+            if (retval == EOF) goto failure;
+        }
+    }
+    retval = fprintf(fp,"\"CONST NODES\"; \n}\n");
+    if (retval == EOF) goto failure;
+
+    /* Write the output node subgraph. */
+    retval = fprintf(fp,"{ rank = same; node [shape = box]; edge [style = invis];\n");
+    if (retval == EOF) goto failure;
+    for (i = 0; i < n; i++) {
+        if (onames == NULL) {
+            retval = fprintf(fp,"\"F%d\"", i);
+        } else {
+            retval = fprintf(fp,"\"  %s  \"", onames[i]);
+        }
+        if (retval == EOF) goto failure;
+        if (i == n - 1) {
+            retval = fprintf(fp,"; }\n");
+        } else {
+            retval = fprintf(fp," -> ");
+        }
+        if (retval == EOF) goto failure;
+    }
+
+    /* Write rank info: All nodes with the same index have the same rank. */
+    for (i = 0; i < nvars; i++) {
+        if (sorted[dd->invpermZ[i]]) {
+            retval = fprintf(fp,"{ rank = same; ");
+            if (retval == EOF) goto failure;
+            if (inames == NULL) {
+                retval = fprintf(fp,"\" %d \";\n", dd->invpermZ[i]);
+            } else {
+                retval = fprintf(fp,"\" %s \";\n", inames[dd->invpermZ[i]]);
+            }
+            if (retval == EOF) goto failure;
+            nodelist = dd->subtableZ[i].nodelist;
+            slots = dd->subtableZ[i].slots;
+            for (j = 0; j < slots; j++) {
+                scan = nodelist[j];
+                while (scan != NULL) {
+                    if ( st__is_member(visited,(char *) scan)) {
+                        retval = fprintf(fp,"\"%p\";\n", (void *)
+                                         ((mask & (ptrint) scan) /
+                                          sizeof(DdNode)));
+                        if (retval == EOF) goto failure;
+                    }
+                    scan = scan->next;
+                }
+            }
+            retval = fprintf(fp,"}\n");
+            if (retval == EOF) goto failure;
+        }
+    }
+
+    /* All constants have the same rank. */
+    retval = fprintf(fp,
+        "{ rank = same; \"CONST NODES\";\n{ node [shape = box]; ");
+    if (retval == EOF) goto failure;
+    nodelist = dd->constants.nodelist;
+    slots = dd->constants.slots;
+    for (j = 0; j < slots; j++) {
+        scan = nodelist[j];
+        while (scan != NULL) {
+            if ( st__is_member(visited,(char *) scan)) {
+                retval = fprintf(fp,"\"%p\";\n", (void *)
+                                 ((mask & (ptrint) scan) / sizeof(DdNode)));
+                if (retval == EOF) goto failure;
+            }
+            scan = scan->next;
+        }
+    }
+    retval = fprintf(fp,"}\n}\n");
+    if (retval == EOF) goto failure;
+
+    /* Write edge info. */
+    /* Edges from the output nodes. */
+    for (i = 0; i < n; i++) {
+        if (onames == NULL) {
+            retval = fprintf(fp,"\"F%d\"", i);
+        } else {
+            retval = fprintf(fp,"\"  %s  \"", onames[i]);
+        }
+        if (retval == EOF) goto failure;
+        retval = fprintf(fp," -> \"%p\" [style = solid];\n",
+                         (void *) ((mask & (ptrint) f[i]) /
+                                          sizeof(DdNode)));
+        if (retval == EOF) goto failure;
+    }
+
+    /* Edges from internal nodes. */
+    for (i = 0; i < nvars; i++) {
+        if (sorted[dd->invpermZ[i]]) {
+            nodelist = dd->subtableZ[i].nodelist;
+            slots = dd->subtableZ[i].slots;
+            for (j = 0; j < slots; j++) {
+                scan = nodelist[j];
+                while (scan != NULL) {
+                    if ( st__is_member(visited,(char *) scan)) {
+                        retval = fprintf(fp,
+                            "\"%p\" -> \"%p\";\n",
+                            (void *) ((mask & (ptrint) scan) / sizeof(DdNode)),
+                            (void *) ((mask & (ptrint) cuddT(scan)) /
+                                      sizeof(DdNode)));
+                        if (retval == EOF) goto failure;
+                        retval = fprintf(fp,
+                                         "\"%p\" -> \"%p\" [style = dashed];\n",
+                                         (void *) ((mask & (ptrint) scan)
+                                                   / sizeof(DdNode)),
+                                         (void *) ((mask & (ptrint)
+                                                    cuddE(scan)) /
+                                                   sizeof(DdNode)));
+                        if (retval == EOF) goto failure;
+                    }
+                    scan = scan->next;
+                }
+            }
+        }
+    }
+
+    /* Write constant labels. */
+    nodelist = dd->constants.nodelist;
+    slots = dd->constants.slots;
+    for (j = 0; j < slots; j++) {
+        scan = nodelist[j];
+        while (scan != NULL) {
+            if ( st__is_member(visited,(char *) scan)) {
+                retval = fprintf(fp,"\"%p\" [label = \"%g\"];\n",
+                                 (void *) ((mask & (ptrint) scan) /
+                                           sizeof(DdNode)),
+                                 cuddV(scan));
+                if (retval == EOF) goto failure;
+            }
+            scan = scan->next;
+        }
+    }
+
+    /* Write trailer and return. */
+    retval = fprintf(fp,"}\n");
+    if (retval == EOF) goto failure;
+
+    st__free_table(visited);
+    ABC_FREE(sorted);
+    return(1);
+
+failure:
+    if (sorted != NULL) ABC_FREE(sorted);
+    if (visited != NULL) st__free_table(visited);
+    return(0);
+
+} /* end of Cudd_zddDumpBlif */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Prints a ZDD to the standard output. One line per node is
+  printed.]
+
+  Description [Prints a ZDD to the standard output. One line per node is
+  printed. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddPrintDebug]
+
+******************************************************************************/
+int
+cuddZddP(
+  DdManager * zdd,
+  DdNode * f)
+{
+    int retval;
+    st__table *table = st__init_table( st__ptrcmp, st__ptrhash);
+
+    if (table == NULL) return(0);
+
+    retval = zp2(zdd, f, table);
+    st__free_table(table);
+    (void) fputc('\n', zdd->out);
+    return(retval);
+
+} /* end of cuddZddP */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of cuddZddP.]
+
+  Description [Performs the recursive step of cuddZddP. Returns 1 in
+  case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+zp2(
+  DdManager * zdd,
+  DdNode * f,
+  st__table * t)
+{
+    DdNode      *n;
+    int         T, E;
+    DdNode      *base = DD_ONE(zdd);
+
+    if (f == NULL)
+        return(0);
+
+    if (Cudd_IsConstant(f)) {
+        (void)fprintf(zdd->out, "ID = %d\n", (f == base));
+        return(1);
+    }
+    if ( st__is_member(t, (char *)f) == 1)
+        return(1);
+
+    if ( st__insert(t, (char *) f, NULL) == st__OUT_OF_MEM)
+        return(0);
+
+#if SIZEOF_VOID_P == 8
+    (void) fprintf(zdd->out, "ID = 0x%lx\tindex = %u\tr = %u\t",
+        (ptruint)f / (ptruint) sizeof(DdNode), f->index, f->ref);
+#else
+    (void) fprintf(zdd->out, "ID = 0x%x\tindex = %hu\tr = %hu\t",
+        (ptruint)f / (ptruint) sizeof(DdNode), f->index, f->ref);
+#endif
+
+    n = cuddT(f);
+    if (Cudd_IsConstant(n)) {
+        (void) fprintf(zdd->out, "T = %d\t\t", (n == base));
+        T = 1;
+    } else {
+#if SIZEOF_VOID_P == 8
+        (void) fprintf(zdd->out, "T = 0x%lx\t", (ptruint) n /
+                       (ptruint) sizeof(DdNode));
+#else
+        (void) fprintf(zdd->out, "T = 0x%x\t", (ptruint) n /
+                       (ptruint) sizeof(DdNode));
+#endif
+        T = 0;
+    }
+
+    n = cuddE(f);
+    if (Cudd_IsConstant(n)) {
+        (void) fprintf(zdd->out, "E = %d\n", (n == base));
+        E = 1;
+    } else {
+#if SIZEOF_VOID_P == 8
+        (void) fprintf(zdd->out, "E = 0x%lx\n", (ptruint) n /
+                      (ptruint) sizeof(DdNode));
+#else
+        (void) fprintf(zdd->out, "E = 0x%x\n", (ptruint) n /
+                       (ptruint) sizeof(DdNode));
+#endif
+        E = 0;
+    }
+
+    if (E == 0)
+        if (zp2(zdd, cuddE(f), t) == 0) return(0);
+    if (T == 0)
+        if (zp2(zdd, cuddT(f), t) == 0) return(0);
+    return(1);
+
+} /* end of zp2 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddPrintMinterm.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+zdd_print_minterm_aux(
+  DdManager * zdd /* manager */,
+  DdNode * node /* current node */,
+  int  level /* depth in the recursion */,
+  int * list /* current recursion path */)
+{
+    DdNode      *Nv, *Nnv;
+    int         i, v;
+    DdNode      *base = DD_ONE(zdd);
+
+    if (Cudd_IsConstant(node)) {
+        if (node == base) {
+            /* Check for missing variable. */
+            if (level != zdd->sizeZ) {
+                list[zdd->invpermZ[level]] = 0;
+                zdd_print_minterm_aux(zdd, node, level + 1, list);
+                return;
+            }
+            /* Terminal case: Print one cube based on the current recursion
+            ** path.
+            */
+            for (i = 0; i < zdd->sizeZ; i++) {
+                v = list[i];
+                if (v == 0)
+                    (void) fprintf(zdd->out,"0");
+                else if (v == 1)
+                    (void) fprintf(zdd->out,"1");
+                else if (v == 3)
+                    (void) fprintf(zdd->out,"@");       /* should never happen */
+                else
+                    (void) fprintf(zdd->out,"-");
+            }
+            (void) fprintf(zdd->out," 1\n");
+        }
+    } else {
+        /* Check for missing variable. */
+        if (level != cuddIZ(zdd,node->index)) {
+            list[zdd->invpermZ[level]] = 0;
+            zdd_print_minterm_aux(zdd, node, level + 1, list);
+            return;
+        }
+
+        Nnv = cuddE(node);
+        Nv = cuddT(node);
+        if (Nv == Nnv) {
+            list[node->index] = 2;
+            zdd_print_minterm_aux(zdd, Nnv, level + 1, list);
+            return;
+        }
+
+        list[node->index] = 1;
+        zdd_print_minterm_aux(zdd, Nv, level + 1, list);
+        list[node->index] = 0;
+        zdd_print_minterm_aux(zdd, Nnv, level + 1, list);
+    }
+    return;
+
+} /* end of zdd_print_minterm_aux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddPrintCover.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+zddPrintCoverAux(
+  DdManager * zdd /* manager */,
+  DdNode * node /* current node */,
+  int  level /* depth in the recursion */,
+  int * list /* current recursion path */)
+{
+    DdNode      *Nv, *Nnv;
+    int         i, v;
+    DdNode      *base = DD_ONE(zdd);
+
+    if (Cudd_IsConstant(node)) {
+        if (node == base) {
+            /* Check for missing variable. */
+            if (level != zdd->sizeZ) {
+                list[zdd->invpermZ[level]] = 0;
+                zddPrintCoverAux(zdd, node, level + 1, list);
+                return;
+            }
+            /* Terminal case: Print one cube based on the current recursion
+            ** path.
+            */
+            for (i = 0; i < zdd->sizeZ; i += 2) {
+                v = list[i] * 4 + list[i+1];
+                if (v == 0)
+                    (void) putc('-',zdd->out);
+                else if (v == 4)
+                    (void) putc('1',zdd->out);
+                else if (v == 1)
+                    (void) putc('0',zdd->out);
+                else
+                    (void) putc('@',zdd->out); /* should never happen */
+            }
+            (void) fprintf(zdd->out," 1\n");
+        }
+    } else {
+        /* Check for missing variable. */
+        if (level != cuddIZ(zdd,node->index)) {
+            list[zdd->invpermZ[level]] = 0;
+            zddPrintCoverAux(zdd, node, level + 1, list);
+            return;
+        }
+
+        Nnv = cuddE(node);
+        Nv = cuddT(node);
+        if (Nv == Nnv) {
+            list[node->index] = 2;
+            zddPrintCoverAux(zdd, Nnv, level + 1, list);
+            return;
+        }
+
+        list[node->index] = 1;
+        zddPrintCoverAux(zdd, Nv, level + 1, list);
+        list[node->index] = 0;
+        zddPrintCoverAux(zdd, Nnv, level + 1, list);
+    }
+    return;
+
+} /* end of zddPrintCoverAux */
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/cudd/license b/abc-build/src/bdd/cudd/license
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/license
@@ -0,0 +1,32 @@
+Copyright (c) 1995-2004, Regents of the University of Colorado
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+Neither the name of the University of Colorado nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/abc-build/src/bdd/cudd/module.make b/abc-build/src/bdd/cudd/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/module.make
@@ -0,0 +1,61 @@
+SRC +=  src/bdd/cudd/cuddAPI.c \
+	src/bdd/cudd/cuddAddAbs.c \
+	src/bdd/cudd/cuddAddApply.c \
+	src/bdd/cudd/cuddAddFind.c \
+	src/bdd/cudd/cuddAddInv.c \
+	src/bdd/cudd/cuddAddIte.c \
+	src/bdd/cudd/cuddAddNeg.c \
+	src/bdd/cudd/cuddAddWalsh.c \
+	src/bdd/cudd/cuddAndAbs.c \
+	src/bdd/cudd/cuddAnneal.c \
+	src/bdd/cudd/cuddApa.c \
+	src/bdd/cudd/cuddApprox.c \
+	src/bdd/cudd/cuddBddAbs.c \
+	src/bdd/cudd/cuddBddCorr.c \
+	src/bdd/cudd/cuddBddIte.c \
+	src/bdd/cudd/cuddBridge.c \
+	src/bdd/cudd/cuddCache.c \
+	src/bdd/cudd/cuddCheck.c \
+	src/bdd/cudd/cuddClip.c \
+	src/bdd/cudd/cuddCof.c \
+	src/bdd/cudd/cuddCompose.c \
+	src/bdd/cudd/cuddDecomp.c \
+	src/bdd/cudd/cuddEssent.c \
+	src/bdd/cudd/cuddExact.c \
+	src/bdd/cudd/cuddExport.c \
+	src/bdd/cudd/cuddGenCof.c \
+	src/bdd/cudd/cuddGenetic.c \
+	src/bdd/cudd/cuddGroup.c \
+	src/bdd/cudd/cuddHarwell.c \
+	src/bdd/cudd/cuddInit.c \
+	src/bdd/cudd/cuddInteract.c \
+	src/bdd/cudd/cuddLCache.c \
+	src/bdd/cudd/cuddLevelQ.c \
+	src/bdd/cudd/cuddLinear.c \
+	src/bdd/cudd/cuddLiteral.c \
+	src/bdd/cudd/cuddMatMult.c \
+	src/bdd/cudd/cuddPriority.c \
+	src/bdd/cudd/cuddRead.c \
+	src/bdd/cudd/cuddRef.c \
+	src/bdd/cudd/cuddReorder.c \
+	src/bdd/cudd/cuddSat.c \
+	src/bdd/cudd/cuddSign.c \
+	src/bdd/cudd/cuddSolve.c \
+	src/bdd/cudd/cuddSplit.c \
+	src/bdd/cudd/cuddSubsetHB.c \
+	src/bdd/cudd/cuddSubsetSP.c \
+	src/bdd/cudd/cuddSymmetry.c \
+	src/bdd/cudd/cuddTable.c \
+	src/bdd/cudd/cuddUtil.c \
+	src/bdd/cudd/cuddWindow.c \
+	src/bdd/cudd/cuddZddCount.c \
+	src/bdd/cudd/cuddZddFuncs.c \
+	src/bdd/cudd/cuddZddGroup.c \
+	src/bdd/cudd/cuddZddIsop.c \
+	src/bdd/cudd/cuddZddLin.c \
+	src/bdd/cudd/cuddZddMisc.c \
+	src/bdd/cudd/cuddZddPort.c \
+	src/bdd/cudd/cuddZddReord.c \
+	src/bdd/cudd/cuddZddSetop.c \
+	src/bdd/cudd/cuddZddSymm.c \
+	src/bdd/cudd/cuddZddUtil.c 
diff --git a/abc-build/src/bdd/cudd/r7x8.1.mat b/abc-build/src/bdd/cudd/r7x8.1.mat
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/r7x8.1.mat
@@ -0,0 +1,53 @@
+7 9
+0 0 1
+0 1 1
+0 2 1
+0 3 4
+0 4 3
+0 5 3
+0 6 3
+0 8 3
+1 0 4
+1 1 3
+1 2 2
+1 3 4
+1 4 1
+1 5 2
+1 6 4
+1 8 3
+2 0 1
+2 1 1
+2 2 4
+2 4 2
+2 5 3
+2 6 3
+2 8 3
+3 0 2
+3 1 1
+3 3 4
+3 4 4
+3 5 1
+3 8 1
+4 0 2
+4 1 3
+4 2 2
+4 3 4
+4 4 1
+4 5 1
+4 6 2
+4 8 2
+5 0 3
+5 1 3
+5 2 4
+5 3 4
+5 4 1
+5 5 3
+5 6 3
+5 8 4
+6 1 1
+6 2 1
+6 3 4
+6 4 2
+6 5 4
+6 6 4
+6 8 2
diff --git a/abc-build/src/bdd/cudd/r7x8.1.out b/abc-build/src/bdd/cudd/r7x8.1.out
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/r7x8.1.out
@@ -0,0 +1,377 @@
+# TestCudd Version #1.0, Release date 3/17/01
+# ./testcudd -p 2 r7x8.1.mat
+:name: r7x8.1.mat: 7 rows 9 columns
+:1: M: 63 nodes 5 leaves 52 minterms
+000000--  1
+000001-0  1
+000001-1  4
+000010-0  4
+000010-1  3
+000011-0  2
+000011-1  4
+000100--  3
+000101-0  3
+000110-0  1
+000110-1  2
+000111-0  4
+001000--  1
+001001-0  4
+001010-0  2
+001010-1  1
+001011-1  4
+001100-0  2
+001100-1  3
+001101-0  3
+001110-0  4
+001110-1  1
+0100-0-0  3
+011000-0  3
+011010-0  1
+100000-0  2
+100000-1  3
+100001-0  2
+100001-1  4
+100010--  3
+100011--  4
+100100--  1
+100101-0  2
+100110-0  1
+100110-1  3
+100111-0  3
+101000-1  1
+101001-0  1
+101001-1  4
+101100-0  2
+101100-1  4
+101101-0  4
+110000-0  2
+110010-0  4
+111000-0  2
+
+:2: time to read the matrix = 0.00 sec
+:3: C: 22 nodes 1 leaves 52 minterms
+0000----  1
+0001-0--  1
+0001-1-0  1
+001000--  1
+001001-0  1
+001010--  1
+001011-1  1
+001100--  1
+001101-0  1
+001110--  1
+01-0-0-0  1
+1000----  1
+1001-0--  1
+1001-1-0  1
+101000-1  1
+101001--  1
+101100--  1
+101101-0  1
+1100-0-0  1
+111000-0  1
+
+Testing iterator on cubes:
+000000-- 1
+000001-0 1
+000001-1 4
+000010-0 4
+000010-1 3
+000011-0 2
+000011-1 4
+000100-- 3
+000101-0 3
+000110-0 1
+000110-1 2
+000111-0 4
+001000-- 1
+001001-0 4
+001010-0 2
+001010-1 1
+001011-1 4
+001100-0 2
+001100-1 3
+001101-0 3
+001110-0 4
+001110-1 1
+0100-0-0 3
+011000-0 3
+011010-0 1
+100000-0 2
+100000-1 3
+100001-0 2
+100001-1 4
+100010-- 3
+100011-- 4
+100100-- 1
+100101-0 2
+100110-0 1
+100110-1 3
+100111-0 3
+101000-1 1
+101001-0 1
+101001-1 4
+101100-0 2
+101100-1 4
+101101-0 4
+110000-0 2
+110010-0 4
+111000-0 2
+
+Testing prime expansion of cubes:
+-000---- 1
+-00--0-- 1
+0--0-0-0 1
+--00-0-0 1
+-0-100-- 1
+10-001-- 1
+-00----0 1
+00---0-- 1
+-1-000-0 1
+-0--01-0 1
+-0--00-1 1
+00-01--1 1
+
+Testing iterator on primes (CNF):
+-0-0---- 1
+-0---0-- 1
+0-0-0--- 1
+-0-----0 1
+---0-0-0 1
+0101-1-1 1
+--0-00-1 1
+1-0-10-0 1
+
+Cache used slots = 58.06% (expected 58.92%)
+xor1: 14 nodes 1 leaves 28 minterms
+000--1-1  1
+001-11-1  1
+01---0-0  1
+100--1-1  1
+101-00-0  1
+101-01-1  1
+110--0-0  1
+111-00-0  1
+
+Chosen minterm for Hamming distance test: : 9 nodes 1 leaves 1 minterms
+11110010  1
+
+Minimum Hamming distance = 1
+ycube: 5 nodes 1 leaves 8 minterms
+-0-0-0-0  1
+
+CP: 11 nodes 1 leaves 7 minterms
+00-0-0-0  1
+1000-0-0  1
+101000-1  1
+
+:4: ineq: 10 nodes 1 leaves 42 minterms
+001000--  1
+00101---  1
+1000----  1
+100100--  1
+10011---  1
+101-----  1
+111000--  1
+11101---  1
+
+10------ 1
+-01----- 1
+1-1----- 1
+-0-0---- 1
+1--0---- 1
+-0--10-- 1
+--1010-- 1
+1---10-- 1
+
+:4: ess: 1 nodes 1 leaves 128 minterms
+--------  1
+
+:5: shortP: 7 nodes 1 leaves 2 minterms
+000000--  1
+
+:5b: largest: 4 nodes 1 leaves 16 minterms
+01-1----  1
+
+The value of M along the chosen shortest path is 1
+:6: shortP: 5 nodes 1 leaves 8 minterms
+0000----  1
+
+Average distance: 4133.34
+Number of variables =      8	Number of slots     =   2304
+Number of keys      =    995	Number of min dead  =   9216
+walsh1: 16 nodes 2 leaves 256 minterms
+-0--0--0--0-  1
+-0--0--0--10  1
+-0--0--0--11 -1
+-0--0--10-0-  1
+-0--0--10-10  1
+-0--0--10-11 -1
+-0--0--11-0- -1
+-0--0--11-10 -1
+-0--0--11-11  1
+-0--10-0--0-  1
+-0--10-0--10  1
+-0--10-0--11 -1
+-0--10-10-0-  1
+-0--10-10-10  1
+-0--10-10-11 -1
+-0--10-11-0- -1
+-0--10-11-10 -1
+-0--10-11-11  1
+-0--11-0--0- -1
+-0--11-0--10 -1
+-0--11-0--11  1
+-0--11-10-0- -1
+-0--11-10-10 -1
+-0--11-10-11  1
+-0--11-11-0-  1
+-0--11-11-10  1
+-0--11-11-11 -1
+-10-0--0--0-  1
+-10-0--0--10  1
+-10-0--0--11 -1
+-10-0--10-0-  1
+-10-0--10-10  1
+-10-0--10-11 -1
+-10-0--11-0- -1
+-10-0--11-10 -1
+-10-0--11-11  1
+-10-10-0--0-  1
+-10-10-0--10  1
+-10-10-0--11 -1
+-10-10-10-0-  1
+-10-10-10-10  1
+-10-10-10-11 -1
+-10-10-11-0- -1
+-10-10-11-10 -1
+-10-10-11-11  1
+-10-11-0--0- -1
+-10-11-0--10 -1
+-10-11-0--11  1
+-10-11-10-0- -1
+-10-11-10-10 -1
+-10-11-10-11  1
+-10-11-11-0-  1
+-10-11-11-10  1
+-10-11-11-11 -1
+-11-0--0--0- -1
+-11-0--0--10 -1
+-11-0--0--11  1
+-11-0--10-0- -1
+-11-0--10-10 -1
+-11-0--10-11  1
+-11-0--11-0-  1
+-11-0--11-10  1
+-11-0--11-11 -1
+-11-10-0--0- -1
+-11-10-0--10 -1
+-11-10-0--11  1
+-11-10-10-0- -1
+-11-10-10-10 -1
+-11-10-10-11  1
+-11-10-11-0-  1
+-11-10-11-10  1
+-11-10-11-11 -1
+-11-11-0--0-  1
+-11-11-0--10  1
+-11-11-0--11 -1
+-11-11-10-0-  1
+-11-11-10-10  1
+-11-11-10-11 -1
+-11-11-11-0- -1
+-11-11-11-10 -1
+-11-11-11-11  1
+
+wtw: 14 nodes 2 leaves 16 minterms
+0-00-00-00-0  16
+0-00-00-01-1  16
+0-00-01-10-0  16
+0-00-01-11-1  16
+0-01-10-00-0  16
+0-01-10-01-1  16
+0-01-11-10-0  16
+0-01-11-11-1  16
+1-10-00-00-0  16
+1-10-00-01-1  16
+1-10-01-10-0  16
+1-10-01-11-1  16
+1-11-10-00-0  16
+1-11-10-01-1  16
+1-11-11-10-0  16
+1-11-11-11-1  16
+
+Average length of non-empty lists = 1
+**** CUDD modifiable parameters ****
+Hard limit for cache size: 7645866
+Cache hit threshold for resizing: 30%
+Garbage collection enabled: yes
+Limit for fast unique table growth: 4587520
+Maximum number of variables sifted per reordering: 1000
+Maximum number of variable swaps per reordering: 2000000
+Maximum growth while sifting a variable: 1.2
+Dynamic reordering of BDDs enabled: no
+Default BDD reordering method: 4
+Dynamic reordering of ZDDs enabled: no
+Default ZDD reordering method: 4
+Realignment of ZDDs to BDDs enabled: no
+Realignment of BDDs to ZDDs enabled: no
+Dead nodes counted in triggering reordering: no
+Group checking criterion: 7
+Recombination threshold: 0
+Symmetry violation threshold: 0
+Arc violation threshold: 0
+GA population size: 0
+Number of crossovers for GA: 0
+Next reordering threshold: 4004
+**** CUDD non-modifiable parameters ****
+Memory in use: 4274484
+Peak number of nodes: 2044
+Peak number of live nodes: 119
+Number of BDD variables: 9
+Number of ZDD variables: 0
+Number of cache entries: 2048
+Number of cache look-ups: 2846
+Number of cache hits: 715
+Number of cache insertions: 2289
+Number of cache collisions: 937
+Number of cache deletions: 1348
+Cache used slots = 66.02% (expected 67.30%)
+Soft limit for cache size: 13312
+Number of buckets in unique table: 2560
+Used buckets in unique table: 0.51% (expected 0.51%)
+Number of BDD and ADD nodes: 13
+Number of ZDD nodes: 0
+Number of dead BDD and ADD nodes: 0
+Number of dead ZDD nodes: 0
+Total number of nodes allocated: 1091
+Total number of nodes reclaimed: 950
+Garbage collections so far: 1
+Time for garbage collection: 0.00 sec
+Reorderings so far: 0
+Time for reordering: 0.00 sec
+total time = 0.00 sec
+Runtime Statistics
+------------------
+Machine name: jobim.colorado.edu
+User time      0.0 seconds
+System time    0.0 seconds
+
+Average resident text size       =     0K
+Average resident data+stack size =     0K
+Maximum resident size            =     0K
+
+Virtual text size                = 131644K
+Virtual data size                =   151K
+    data size initialized        =    17K
+    data size uninitialized      =     0K
+    data size sbrk               =   134K
+Virtual memory limit             = 358400K (4194304K)
+
+Major page faults = 0
+Minor page faults = 1318
+Swaps = 0
+Input blocks = 0
+Output blocks = 0
+Context switch (voluntary) = 1
+Context switch (involuntary) = 1
diff --git a/abc-build/src/bdd/cudd/testcudd.c b/abc-build/src/bdd/cudd/testcudd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/cudd/testcudd.c
@@ -0,0 +1,1073 @@
+/**CFile***********************************************************************
+
+  FileName    [testcudd.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Sanity check tests for some CUDD functions.]
+
+  Description [testcudd reads a matrix with real coefficients and
+  transforms it into an ADD. It then performs various operations on
+  the ADD and on the BDD corresponding to the ADD pattern. Finally,
+  testcudd tests functions relate to Walsh matrices and matrix
+  multiplication.]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define TESTCUDD_VERSION	"TestCudd Version #1.0, Release date 3/17/01"
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: testcudd.c,v 1.20 2009/03/08 02:49:02 fabio Exp $";
+#endif
+
+static const char *onames[] = { "C", "M" }; /* names of functions to be dumped */
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void usage (char * prog);
+static FILE *open_file (char *filename, const char *mode);
+static int testIterators (DdManager *dd, DdNode *M, DdNode *C, int pr);
+static int testXor (DdManager *dd, DdNode *f, int pr, int nvars);
+static int testHamming (DdManager *dd, DdNode *f, int pr);
+static int testWalsh (DdManager *dd, int N, int cmu, int approach, int pr);
+
+/**AutomaticEnd***************************************************************/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Main function for testcudd.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+main(int argc, char **argv)
+{
+    FILE *fp;           /* pointer to input file */
+    char *file = (char *) "";	/* input file name */
+    FILE *dfp = NULL;	/* pointer to dump file */
+    char *dfile;	/* file for DD dump */
+    DdNode *dfunc[2];	/* addresses of the functions to be dumped */
+    DdManager *dd;	/* pointer to DD manager */
+    DdNode *one;	/* fast access to constant function */
+    DdNode *M;
+    DdNode **x;		/* pointers to variables */
+    DdNode **y;		/* pointers to variables */
+    DdNode **xn;	/* complements of row variables */
+    DdNode **yn_;	/* complements of column variables */
+    DdNode **xvars;
+    DdNode **yvars;
+    DdNode *C;		/* result of converting from ADD to BDD */
+    DdNode *ess;	/* cube of essential variables */
+    DdNode *shortP;	/* BDD cube of shortest path */
+    DdNode *largest;	/* BDD of largest cube */
+    DdNode *shortA;	/* ADD cube of shortest path */
+    DdNode *constN;	/* value returned by evaluation of ADD */
+    DdNode *ycube;	/* cube of the negated y vars for c-proj */
+    DdNode *CP;		/* C-Projection of C */
+    DdNode *CPr;	/* C-Selection of C */
+    int    length;	/* length of the shortest path */
+    int    nx;			/* number of variables */
+    int    ny;
+    int    maxnx;
+    int    maxny;
+    int    m;
+    int    n;
+    int    N;
+    int    cmu;			/* use CMU multiplication */
+    int    pr;			/* verbose printout level */
+    int    harwell;
+    int    multiple;		/* read multiple matrices */
+    int    ok;
+    int    c;			/* variable to read in options */
+    int    approach;		/* reordering approach */
+    int    autodyn;		/* automatic reordering */
+    int    groupcheck;		/* option for group sifting */
+    int    profile;		/* print heap profile if != 0 */
+    int    keepperm;		/* keep track of permutation */
+    int    clearcache;		/* clear the cache after each matrix */
+    int    blifOrDot;		/* dump format: 0 -> dot, 1 -> blif, ... */
+    int    retval;		/* return value */
+    int    i;			/* loop index */
+    long   startTime;		/* initial time */
+    long   lapTime;
+    int    size;
+    unsigned int cacheSize, maxMemory;
+    unsigned int nvars,nslots;
+
+    startTime = util_cpu_time();
+
+    approach = CUDD_REORDER_NONE;
+    autodyn = 0;
+    pr = 0;
+    harwell = 0;
+    multiple = 0;
+    profile = 0;
+    keepperm = 0;
+    cmu = 0;
+    N = 4;
+    nvars = 4;
+    cacheSize = 127;
+    maxMemory = 0;
+    nslots = CUDD_UNIQUE_SLOTS;
+    clearcache = 0;
+    groupcheck = CUDD_GROUP_CHECK7;
+    dfile = NULL;
+    blifOrDot = 0; /* dot format */
+
+    /* Parse command line. */
+    while ((c = util_getopt(argc, argv, (char *) "CDHMPS:a:bcd:g:hkmn:p:v:x:X:"))
+	   != EOF) {
+	switch(c) {
+	case 'C':
+	    cmu = 1;
+	    break;
+	case 'D':
+	    autodyn = 1;
+	    break;
+	case 'H':
+	    harwell = 1;
+	    break;
+	case 'M':
+#ifdef MNEMOSYNE
+	    (void) mnem_setrecording(0);
+#endif
+	    break;
+	case 'P':
+	    profile = 1;
+	    break;
+	case 'S':
+	    nslots = atoi(util_optarg);
+	    break;
+	case 'X':
+	    maxMemory = atoi(util_optarg);
+	    break;
+	case 'a':
+	    approach = atoi(util_optarg);
+	    break;
+	case 'b':
+	    blifOrDot = 1; /* blif format */
+	    break;
+	case 'c':
+	    clearcache = 1;
+	    break;
+	case 'd':
+	    dfile = util_optarg;
+	    break;
+	case 'g':
+	    groupcheck = atoi(util_optarg);
+	    break;
+	case 'k':
+	    keepperm = 1;
+	    break;
+	case 'm':
+	    multiple = 1;
+	    break;
+	case 'n':
+	    N = atoi(util_optarg);
+	    break;
+	case 'p':
+	    pr = atoi(util_optarg);
+	    break;
+	case 'v':
+	    nvars = atoi(util_optarg);
+	    break;
+	case 'x':
+	    cacheSize = atoi(util_optarg);
+	    break;
+	case 'h':
+	default:
+	    usage(argv[0]);
+	    break;
+	}
+    }
+
+    if (argc - util_optind == 0) {
+	file = (char *) "-";
+    } else if (argc - util_optind == 1) {
+	file = argv[util_optind];
+    } else {
+	usage(argv[0]);
+    }
+    if ((approach<0) || (approach>17)) {
+	(void) fprintf(stderr,"Invalid approach: %d \n",approach);
+	usage(argv[0]);
+    }
+
+    if (pr >= 0) {
+	(void) printf("# %s\n", TESTCUDD_VERSION);
+	/* Echo command line and arguments. */
+	(void) printf("#");
+	for (i = 0; i < argc; i++) {
+	    (void) printf(" %s", argv[i]);
+	}
+	(void) printf("\n");
+	(void) fflush(stdout);
+    }
+
+    /* Initialize manager and provide easy reference to terminals. */
+    dd = Cudd_Init(nvars,0,nslots,cacheSize,maxMemory);
+    one = DD_ONE(dd);
+    dd->groupcheck = (Cudd_AggregationType) groupcheck;
+    if (autodyn) Cudd_AutodynEnable(dd,CUDD_REORDER_SAME);
+
+    /* Open input file. */
+    fp = open_file(file, "r");
+
+    /* Open dump file if requested */
+    if (dfile != NULL) {
+	dfp = open_file(dfile, "w");
+    }
+
+    x = y = xn = yn_ = NULL;
+    do {
+	/* We want to start anew for every matrix. */
+	maxnx = maxny = 0;
+	nx = maxnx; ny = maxny;
+	if (pr>0) lapTime = util_cpu_time();
+	if (harwell) {
+	    if (pr >= 0) (void) printf(":name: ");
+	    ok = Cudd_addHarwell(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny,
+	    &m, &n, 0, 2, 1, 2, pr);
+	} else {
+	    ok = Cudd_addRead(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny,
+	    &m, &n, 0, 2, 1, 2);
+	    if (pr >= 0)
+		(void) printf(":name: %s: %d rows %d columns\n", file, m, n);
+	}
+	if (!ok) {
+	    (void) fprintf(stderr, "Error reading matrix\n");
+	    exit(1);
+	}
+
+	if (nx > maxnx) maxnx = nx;
+	if (ny > maxny) maxny = ny;
+
+	/* Build cube of negated y's. */
+	ycube = DD_ONE(dd);
+	Cudd_Ref(ycube);
+	for (i = maxny - 1; i >= 0; i--) {
+	    DdNode *tmpp;
+	    tmpp = Cudd_bddAnd(dd,Cudd_Not(dd->vars[y[i]->index]),ycube);
+	    if (tmpp == NULL) exit(2);
+	    Cudd_Ref(tmpp);
+	    Cudd_RecursiveDeref(dd,ycube);
+	    ycube = tmpp;
+	}
+	/* Initialize vectors of BDD variables used by priority func. */
+	xvars = ALLOC(DdNode *, nx);
+	if (xvars == NULL) exit(2);
+	for (i = 0; i < nx; i++) {
+	    xvars[i] = dd->vars[x[i]->index];
+	}
+	yvars = ALLOC(DdNode *, ny);
+	if (yvars == NULL) exit(2);
+	for (i = 0; i < ny; i++) {
+	    yvars[i] = dd->vars[y[i]->index];
+	}
+
+	/* Clean up */
+	for (i=0; i < maxnx; i++) {
+	    Cudd_RecursiveDeref(dd, x[i]);
+	    Cudd_RecursiveDeref(dd, xn[i]);
+	}
+	FREE(x);
+	FREE(xn);
+	for (i=0; i < maxny; i++) {
+	    Cudd_RecursiveDeref(dd, y[i]);
+	    Cudd_RecursiveDeref(dd, yn_[i]);
+	}
+	FREE(y);
+	FREE(yn_);
+
+	if (pr>0) {(void) printf(":1: M"); Cudd_PrintDebug(dd,M,nx+ny,pr);}
+
+	if (pr>0) (void) printf(":2: time to read the matrix = %s\n",
+		    util_print_time(util_cpu_time() - lapTime));
+
+	C = Cudd_addBddPattern(dd, M);
+	if (C == 0) exit(2);
+	Cudd_Ref(C);
+	if (pr>0) {(void) printf(":3: C"); Cudd_PrintDebug(dd,C,nx+ny,pr);}
+
+	/* Test iterators. */
+	retval = testIterators(dd,M,C,pr);
+	if (retval == 0) exit(2);
+
+	cuddCacheProfile(dd,stdout);
+
+	/* Test XOR */
+	retval = testXor(dd,C,pr,nx+ny);
+	if (retval == 0) exit(2);
+
+	/* Test Hamming distance functions. */
+	retval = testHamming(dd,C,pr);
+	if (retval == 0) exit(2);
+
+	/* Test selection functions. */
+	CP = Cudd_CProjection(dd,C,ycube);
+	if (CP == NULL) exit(2);
+	Cudd_Ref(CP);
+	if (pr>0) {(void) printf("ycube"); Cudd_PrintDebug(dd,ycube,nx+ny,pr);}
+	if (pr>0) {(void) printf("CP"); Cudd_PrintDebug(dd,CP,nx+ny,pr);}
+
+	if (nx == ny) {
+	    CPr = Cudd_PrioritySelect(dd,C,xvars,yvars,(DdNode **)NULL,
+		(DdNode *)NULL,ny,Cudd_Xgty);
+	    if (CPr == NULL) exit(2);
+	    Cudd_Ref(CPr);
+	    if (pr>0) {(void) printf(":4: CPr"); Cudd_PrintDebug(dd,CPr,nx+ny,pr);}
+	    if (CP != CPr) {
+		(void) printf("CP != CPr!\n");
+	    }
+	    Cudd_RecursiveDeref(dd, CPr);
+	}
+
+	/* Test inequality generator. */
+	{
+	    int Nmin = ddMin(nx,ny);
+	    int q;
+	    DdGen *gen;
+	    int *cube;
+	    DdNode *f = Cudd_Inequality(dd,Nmin,2,xvars,yvars);
+	    if (f == NULL) exit(2);
+	    Cudd_Ref(f);
+	    if (pr>0) {
+		(void) printf(":4: ineq");
+		Cudd_PrintDebug(dd,f,nx+ny,pr);
+		if (pr>1) {
+		    Cudd_ForeachPrime(dd,Cudd_Not(f),Cudd_Not(f),gen,cube) {
+			for (q = 0; q < dd->size; q++) {
+			    switch (cube[q]) {
+			    case 0:
+				(void) printf("1");
+				break;
+			    case 1:
+				(void) printf("0");
+				break;
+			    case 2:
+				(void) printf("-");
+				break;
+			    default:
+				(void) printf("?");
+			    }
+			}
+			(void) printf(" 1\n");
+		    }
+		    (void) printf("\n");
+		}
+	    }
+	    Cudd_IterDerefBdd(dd, f);
+	}
+	FREE(xvars); FREE(yvars);
+
+	Cudd_RecursiveDeref(dd, CP);
+	Cudd_RecursiveDeref(dd, ycube);
+
+	/* Test functions for essential variables. */
+	ess = Cudd_FindEssential(dd,C);
+	if (ess == NULL) exit(2);
+	Cudd_Ref(ess);
+	if (pr>0) {(void) printf(":4: ess"); Cudd_PrintDebug(dd,ess,nx+ny,pr);}
+	Cudd_RecursiveDeref(dd, ess);
+
+	/* Test functions for shortest paths. */
+	shortP = Cudd_ShortestPath(dd, M, NULL, NULL, &length);
+	if (shortP == NULL) exit(2);
+	Cudd_Ref(shortP);
+	if (pr>0) {
+	    (void) printf(":5: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr);
+	}
+	/* Test functions for largest cubes. */
+	largest = Cudd_LargestCube(dd, Cudd_Not(C), &length);
+	if (largest == NULL) exit(2);
+	Cudd_Ref(largest);
+	if (pr>0) {
+	    (void) printf(":5b: largest");
+	    Cudd_PrintDebug(dd,largest,nx+ny,pr);
+	}
+	Cudd_RecursiveDeref(dd, largest);
+
+	/* Test Cudd_addEvalConst and Cudd_addIteConstant. */
+	shortA = Cudd_BddToAdd(dd,shortP);
+	if (shortA == NULL) exit(2);
+	Cudd_Ref(shortA);
+	Cudd_RecursiveDeref(dd, shortP);
+	constN = Cudd_addEvalConst(dd,shortA,M);
+	if (constN == DD_NON_CONSTANT) exit(2);
+	if (Cudd_addIteConstant(dd,shortA,M,constN) != constN) exit(2);
+	if (pr>0) {(void) printf("The value of M along the chosen shortest path is %g\n", cuddV(constN));}
+	Cudd_RecursiveDeref(dd, shortA);
+
+	shortP = Cudd_ShortestPath(dd, C, NULL, NULL, &length);
+	if (shortP == NULL) exit(2);
+	Cudd_Ref(shortP);
+	if (pr>0) {
+	    (void) printf(":6: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr);
+	}
+
+	/* Test Cudd_bddIteConstant and Cudd_bddLeq. */
+	if (!Cudd_bddLeq(dd,shortP,C)) exit(2);
+	if (Cudd_bddIteConstant(dd,Cudd_Not(shortP),one,C) != one) exit(2);
+	Cudd_RecursiveDeref(dd, shortP);
+
+	if (profile) {
+	    retval = cuddHeapProfile(dd);
+	}
+
+	size = dd->size;
+
+	if (pr>0) {
+	    (void) printf("Average distance: %g\n", Cudd_AverageDistance(dd));
+	}
+
+	/* Reorder if so requested. */
+	if (approach != CUDD_REORDER_NONE) {
+#ifndef DD_STATS
+	    retval = Cudd_EnableReorderingReporting(dd);
+	    if (retval == 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_EnableReorderingReporting\n");
+		exit(3);
+	    }
+#endif
+#ifdef DD_DEBUG
+	    retval = Cudd_DebugCheck(dd);
+	    if (retval != 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
+		exit(3);
+	    }
+	    retval = Cudd_CheckKeys(dd);
+	    if (retval != 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n");
+		exit(3);
+	    }
+#endif
+	    retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5);
+	    if (retval == 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n");
+		exit(3);
+	    }
+#ifndef DD_STATS
+	    retval = Cudd_DisableReorderingReporting(dd);
+	    if (retval == 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_DisableReorderingReporting\n");
+		exit(3);
+	    }
+#endif
+#ifdef DD_DEBUG
+	    retval = Cudd_DebugCheck(dd);
+	    if (retval != 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
+		exit(3);
+	    }
+	    retval = Cudd_CheckKeys(dd);
+	    if (retval != 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n");
+		exit(3);
+	    }
+#endif
+	    if (approach == CUDD_REORDER_SYMM_SIFT ||
+	    approach == CUDD_REORDER_SYMM_SIFT_CONV) {
+		Cudd_SymmProfile(dd,0,dd->size-1);
+	    }
+
+	    if (pr>0) {
+		(void) printf("Average distance: %g\n", Cudd_AverageDistance(dd));
+	    }
+
+	    if (keepperm) {
+		/* Print variable permutation. */
+		(void) printf("Variable Permutation:");
+		for (i=0; i<size; i++) {
+		    if (i%20 == 0) (void) printf("\n");
+		    (void) printf("%d ", dd->invperm[i]);
+		}
+		(void) printf("\n");
+		(void) printf("Inverse Permutation:");
+		for (i=0; i<size; i++) {
+		    if (i%20 == 0) (void) printf("\n");
+		    (void) printf("%d ", dd->perm[i]);
+		}
+		(void) printf("\n");
+	    }
+
+	    if (pr>0) {(void) printf("M"); Cudd_PrintDebug(dd,M,nx+ny,pr);}
+
+	    if (profile) {
+		retval = cuddHeapProfile(dd);
+	    }
+
+	}
+
+	/* Dump DDs of C and M if so requested. */
+	if (dfile != NULL) {
+	    dfunc[0] = C;
+	    dfunc[1] = M;
+	    if (blifOrDot == 1) {
+		/* Only dump C because blif cannot handle ADDs */
+		retval = Cudd_DumpBlif(dd,1,dfunc,NULL,(char **)onames,
+				       NULL,dfp,0);
+	    } else {
+		retval = Cudd_DumpDot(dd,2,dfunc,NULL,(char **)onames,dfp);
+	    }
+	    if (retval != 1) {
+		(void) fprintf(stderr,"abnormal termination\n");
+		exit(2);
+	    }
+	}
+
+	Cudd_RecursiveDeref(dd, C);
+	Cudd_RecursiveDeref(dd, M);
+
+	if (clearcache) {
+	    if (pr>0) {(void) printf("Clearing the cache... ");}
+	    for (i = dd->cacheSlots - 1; i>=0; i--) {
+		dd->cache[i].data = NIL(DdNode);
+	    }
+	    if (pr>0) {(void) printf("done\n");}
+	}
+	if (pr>0) {
+	    (void) printf("Number of variables = %6d\t",dd->size);
+	    (void) printf("Number of slots     = %6u\n",dd->slots);
+	    (void) printf("Number of keys      = %6u\t",dd->keys);
+	    (void) printf("Number of min dead  = %6u\n",dd->minDead);
+	}
+
+    } while (multiple && !feof(fp));
+
+    fclose(fp);
+    if (dfile != NULL) {
+	fclose(dfp);
+    }
+
+    /* Second phase: experiment with Walsh matrices. */
+    if (!testWalsh(dd,N,cmu,approach,pr)) {
+	exit(2);
+    }
+
+    /* Check variable destruction. */
+    assert(cuddDestroySubtables(dd,3));
+    assert(Cudd_DebugCheck(dd) == 0);
+    assert(Cudd_CheckKeys(dd) == 0);
+
+    retval = Cudd_CheckZeroRef(dd);
+    ok = retval != 0;  /* ok == 0 means O.K. */
+    if (retval != 0) {
+	(void) fprintf(stderr,
+	    "%d non-zero DD reference counts after dereferencing\n", retval);
+    }
+
+    if (pr >= 0) {
+	(void) Cudd_PrintInfo(dd,stdout);
+    }
+
+    Cudd_Quit(dd);
+
+#ifdef MNEMOSYNE
+    mnem_writestats();
+#endif
+
+    if (pr>0) (void) printf("total time = %s\n",
+		util_print_time(util_cpu_time() - startTime));
+
+    if (pr >= 0) util_print_cpu_stats(stdout);
+    exit(ok);
+    /* NOTREACHED */
+
+} /* end of main */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints usage info for testcudd.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+usage(char *prog)
+{
+    (void) fprintf(stderr, "usage: %s [options] [file]\n", prog);
+    (void) fprintf(stderr, "   -C\t\tuse CMU multiplication algorithm\n");
+    (void) fprintf(stderr, "   -D\t\tenable automatic dynamic reordering\n");
+    (void) fprintf(stderr, "   -H\t\tread matrix in Harwell format\n");
+    (void) fprintf(stderr, "   -M\t\tturns off memory allocation recording\n");
+    (void) fprintf(stderr, "   -P\t\tprint BDD heap profile\n");
+    (void) fprintf(stderr, "   -S n\t\tnumber of slots for each subtable\n");
+    (void) fprintf(stderr, "   -X n\t\ttarget maximum memory in bytes\n");
+    (void) fprintf(stderr, "   -a n\t\tchoose reordering approach (0-13)\n");
+    (void) fprintf(stderr, "   \t\t\t0: same as autoMethod\n");
+    (void) fprintf(stderr, "   \t\t\t1: no reordering (default)\n");
+    (void) fprintf(stderr, "   \t\t\t2: random\n");
+    (void) fprintf(stderr, "   \t\t\t3: pivot\n");
+    (void) fprintf(stderr, "   \t\t\t4: sifting\n");
+    (void) fprintf(stderr, "   \t\t\t5: sifting to convergence\n");
+    (void) fprintf(stderr, "   \t\t\t6: symmetric sifting\n");
+    (void) fprintf(stderr, "   \t\t\t7: symmetric sifting to convergence\n");
+    (void) fprintf(stderr, "   \t\t\t8-10: window of size 2-4\n");
+    (void) fprintf(stderr, "   \t\t\t11-13: window of size 2-4 to conv.\n");
+    (void) fprintf(stderr, "   \t\t\t14: group sifting\n");
+    (void) fprintf(stderr, "   \t\t\t15: group sifting to convergence\n");
+    (void) fprintf(stderr, "   \t\t\t16: simulated annealing\n");
+    (void) fprintf(stderr, "   \t\t\t17: genetic algorithm\n");
+    (void) fprintf(stderr, "   -b\t\tuse blif as format for dumps\n");
+    (void) fprintf(stderr, "   -c\t\tclear the cache after each matrix\n");
+    (void) fprintf(stderr, "   -d file\tdump DDs to file\n");
+    (void) fprintf(stderr, "   -g\t\tselect aggregation criterion (0,5,7)\n");
+    (void) fprintf(stderr, "   -h\t\tprints this message\n");
+    (void) fprintf(stderr, "   -k\t\tprint the variable permutation\n");
+    (void) fprintf(stderr, "   -m\t\tread multiple matrices (only with -H)\n");
+    (void) fprintf(stderr, "   -n n\t\tnumber of variables\n");
+    (void) fprintf(stderr, "   -p n\t\tcontrol verbosity\n");
+    (void) fprintf(stderr, "   -v n\t\tinitial variables in the unique table\n");
+    (void) fprintf(stderr, "   -x n\t\tinitial size of the cache\n");
+    exit(2);
+} /* end of usage */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Opens a file.]
+
+  Description [Opens a file, or fails with an error message and exits.
+  Allows '-' as a synonym for standard input.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static FILE *
+open_file(char *filename, const char *mode)
+{
+    FILE *fp;
+
+    if (strcmp(filename, "-") == 0) {
+	return mode[0] == 'r' ? stdin : stdout;
+    } else if ((fp = fopen(filename, mode)) == NULL) {
+	perror(filename);
+	exit(1);
+    }
+    return fp;
+
+} /* end of open_file */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tests Walsh matrix multiplication.]
+
+  Description [Tests Walsh matrix multiplication.  Return 1 if successful;
+  0 otherwise.]
+
+  SideEffects [May create new variables in the manager.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+testWalsh(
+  DdManager *dd /* manager */,
+  int N /* number of variables */,
+  int cmu /* use CMU approach to matrix multiplication */,
+  int approach /* reordering approach */,
+  int pr /* verbosity level */)
+{
+    DdNode *walsh1, *walsh2, *wtw;
+    DdNode **x, **v, **z;
+    int i, retval;
+    DdNode *one = DD_ONE(dd);
+    DdNode *zero = DD_ZERO(dd);
+
+    if (N > 3) {
+	x = ALLOC(DdNode *,N);
+	v = ALLOC(DdNode *,N);
+	z = ALLOC(DdNode *,N);
+
+	for (i = N-1; i >= 0; i--) {
+	    Cudd_Ref(x[i]=cuddUniqueInter(dd,3*i,one,zero));
+	    Cudd_Ref(v[i]=cuddUniqueInter(dd,3*i+1,one,zero));
+	    Cudd_Ref(z[i]=cuddUniqueInter(dd,3*i+2,one,zero));
+	}
+	Cudd_Ref(walsh1 = Cudd_addWalsh(dd,v,z,N));
+	if (pr>0) {(void) printf("walsh1"); Cudd_PrintDebug(dd,walsh1,2*N,pr);}
+	Cudd_Ref(walsh2 = Cudd_addWalsh(dd,x,v,N));
+	if (cmu) {
+	    Cudd_Ref(wtw = Cudd_addTimesPlus(dd,walsh2,walsh1,v,N));
+	} else {
+	    Cudd_Ref(wtw = Cudd_addMatrixMultiply(dd,walsh2,walsh1,v,N));
+	}
+	if (pr>0) {(void) printf("wtw"); Cudd_PrintDebug(dd,wtw,2*N,pr);}
+
+	if (approach != CUDD_REORDER_NONE) {
+#ifdef DD_DEBUG
+	    retval = Cudd_DebugCheck(dd);
+	    if (retval != 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
+		return(0);
+	    }
+#endif
+	    retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5);
+	    if (retval == 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n");
+		return(0);
+	    }
+#ifdef DD_DEBUG
+	    retval = Cudd_DebugCheck(dd);
+	    if (retval != 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
+		return(0);
+	    }
+#endif
+	    if (approach == CUDD_REORDER_SYMM_SIFT ||
+	    approach == CUDD_REORDER_SYMM_SIFT_CONV) {
+		Cudd_SymmProfile(dd,0,dd->size-1);
+	    }
+	}
+	/* Clean up. */
+	Cudd_RecursiveDeref(dd, wtw);
+	Cudd_RecursiveDeref(dd, walsh1);
+	Cudd_RecursiveDeref(dd, walsh2);
+	for (i=0; i < N; i++) {
+	    Cudd_RecursiveDeref(dd, x[i]);
+	    Cudd_RecursiveDeref(dd, v[i]);
+	    Cudd_RecursiveDeref(dd, z[i]);
+	}
+	FREE(x);
+	FREE(v);
+	FREE(z);
+    }
+    return(1);
+
+} /* end of testWalsh */
+
+/**Function********************************************************************
+
+  Synopsis    [Tests iterators.]
+
+  Description [Tests iterators on cubes and nodes.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+testIterators(
+  DdManager *dd,
+  DdNode *M,
+  DdNode *C,
+  int pr)
+{
+    int *cube;
+    CUDD_VALUE_TYPE value;
+    DdGen *gen;
+    int q;
+
+    /* Test iterator for cubes. */
+    if (pr>1) {
+	(void) printf("Testing iterator on cubes:\n");
+	Cudd_ForeachCube(dd,M,gen,cube,value) {
+	    for (q = 0; q < dd->size; q++) {
+		switch (cube[q]) {
+		case 0:
+		    (void) printf("0");
+		    break;
+		case 1:
+		    (void) printf("1");
+		    break;
+		case 2:
+		    (void) printf("-");
+		    break;
+		default:
+		    (void) printf("?");
+		}
+	    }
+	    (void) printf(" %g\n",value);
+	}
+	(void) printf("\n");
+    }
+
+    if (pr>1) {
+	(void) printf("Testing prime expansion of cubes:\n");
+	if (!Cudd_bddPrintCover(dd,C,C)) return(0);
+    }
+
+    if (pr>1) {
+	(void) printf("Testing iterator on primes (CNF):\n");
+	Cudd_ForeachPrime(dd,Cudd_Not(C),Cudd_Not(C),gen,cube) {
+	    for (q = 0; q < dd->size; q++) {
+		switch (cube[q]) {
+		case 0:
+		    (void) printf("1");
+		    break;
+		case 1:
+		    (void) printf("0");
+		    break;
+		case 2:
+		    (void) printf("-");
+		    break;
+		default:
+		    (void) printf("?");
+		}
+	    }
+	    (void) printf(" 1\n");
+	}
+	(void) printf("\n");
+    }
+
+    /* Test iterator on nodes. */
+    if (pr>2) {
+	DdNode *node;
+	(void) printf("Testing iterator on nodes:\n");
+	Cudd_ForeachNode(dd,M,gen,node) {
+	    if (Cudd_IsConstant(node)) {
+#if SIZEOF_VOID_P == 8
+		(void) printf("ID = 0x%lx\tvalue = %-9g\n",
+			      (ptruint) node /
+			      (ptruint) sizeof(DdNode),
+			      Cudd_V(node));
+#else
+		(void) printf("ID = 0x%x\tvalue = %-9g\n",
+			      (ptruint) node /
+			      (ptruint) sizeof(DdNode),
+			      Cudd_V(node));
+#endif
+	    } else {
+#if SIZEOF_VOID_P == 8
+		(void) printf("ID = 0x%lx\tindex = %u\tr = %u\n",
+			      (ptruint) node /
+			      (ptruint) sizeof(DdNode),
+			      node->index, node->ref);
+#else
+		(void) printf("ID = 0x%x\tindex = %u\tr = %u\n",
+			      (ptruint) node /
+			      (ptruint) sizeof(DdNode),
+			      node->index, node->ref);
+#endif
+	    }
+	}
+	(void) printf("\n");
+    }
+    return(1);
+
+} /* end of testIterators */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tests the functions related to the exclusive OR.]
+
+  Description [Tests the functions related to the exclusive OR. It
+  builds the boolean difference of the given function in three
+  different ways and checks that the results is the same. Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+testXor(DdManager *dd, DdNode *f, int pr, int nvars)
+{
+    DdNode *f1, *f0, *res1, *res2;
+    int x;
+
+    /* Extract cofactors w.r.t. mid variable. */
+    x = nvars / 2;
+    f1 = Cudd_Cofactor(dd,f,dd->vars[x]);
+    if (f1 == NULL) return(0);
+    Cudd_Ref(f1);
+
+    f0 = Cudd_Cofactor(dd,f,Cudd_Not(dd->vars[x]));
+    if (f0 == NULL) {
+	Cudd_RecursiveDeref(dd,f1);
+	return(0);
+    }
+    Cudd_Ref(f0);
+
+    /* Compute XOR of cofactors with ITE. */
+    res1 = Cudd_bddIte(dd,f1,Cudd_Not(f0),f0);
+    if (res1 == NULL) return(0);
+    Cudd_Ref(res1);
+
+    if (pr>0) {(void) printf("xor1"); Cudd_PrintDebug(dd,res1,nvars,pr);}
+
+    /* Compute XOR of cofactors with XOR. */
+    res2 = Cudd_bddXor(dd,f1,f0);
+    if (res2 == NULL) {
+	Cudd_RecursiveDeref(dd,res1);
+	return(0);
+    }
+    Cudd_Ref(res2);
+
+    if (res1 != res2) {
+	if (pr>0) {(void) printf("xor2"); Cudd_PrintDebug(dd,res2,nvars,pr);}
+	Cudd_RecursiveDeref(dd,res1);
+	Cudd_RecursiveDeref(dd,res2);
+	return(0);
+    }
+    Cudd_RecursiveDeref(dd,res1);
+    Cudd_RecursiveDeref(dd,f1);
+    Cudd_RecursiveDeref(dd,f0);
+
+    /* Compute boolean difference directly. */
+    res1 = Cudd_bddBooleanDiff(dd,f,x);
+    if (res1 == NULL) {
+	Cudd_RecursiveDeref(dd,res2);
+	return(0);
+    }
+    Cudd_Ref(res1);
+
+    if (res1 != res2) {
+	if (pr>0) {(void) printf("xor3"); Cudd_PrintDebug(dd,res1,nvars,pr);}
+	Cudd_RecursiveDeref(dd,res1);
+	Cudd_RecursiveDeref(dd,res2);
+	return(0);
+    }
+    Cudd_RecursiveDeref(dd,res1);
+    Cudd_RecursiveDeref(dd,res2);
+    return(1);
+
+} /* end of testXor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tests the Hamming distance functions.]
+
+  Description [Tests the Hammming distance functions. Returns
+  1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+testHamming(
+  DdManager *dd,
+  DdNode *f,
+  int pr)
+{
+    DdNode **vars, *minBdd, *zero, *scan;
+    int i;
+    int d;
+    int *minterm;
+    int size = Cudd_ReadSize(dd);
+
+    vars = ALLOC(DdNode *, size);
+    if (vars == NULL) return(0);
+    for (i = 0; i < size; i++) {
+	vars[i] = Cudd_bddIthVar(dd,i);
+    }
+
+    minBdd = Cudd_bddPickOneMinterm(dd,Cudd_Not(f),vars,size);
+    Cudd_Ref(minBdd);
+    if (pr > 0) {
+	(void) printf("Chosen minterm for Hamming distance test: ");
+	Cudd_PrintDebug(dd,minBdd,size,pr);
+    }
+
+    minterm = ALLOC(int,size);
+    if (minterm == NULL) {
+	FREE(vars);
+	Cudd_RecursiveDeref(dd,minBdd);
+	return(0);
+    }
+    scan = minBdd;
+    zero = Cudd_Not(DD_ONE(dd));
+    while (!Cudd_IsConstant(scan)) {
+	DdNode *R = Cudd_Regular(scan);
+	DdNode *T = Cudd_T(R);
+	DdNode *E = Cudd_E(R);
+	if (R != scan) {
+	    T = Cudd_Not(T);
+	    E = Cudd_Not(E);
+	}
+	if (T == zero) {
+	    minterm[R->index] = 0;
+	    scan = E;
+	} else {
+	    minterm[R->index] = 1;
+	    scan = T;
+	}
+    }
+    Cudd_RecursiveDeref(dd,minBdd);
+
+    d = Cudd_MinHammingDist(dd,f,minterm,size);
+
+    (void) printf("Minimum Hamming distance = %d\n", d);
+
+    FREE(vars);
+    FREE(minterm);
+    return(1);
+
+} /* end of testHamming */
diff --git a/abc-build/src/bdd/dsd/dsd.h b/abc-build/src/bdd/dsd/dsd.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/dsd/dsd.h
@@ -0,0 +1,133 @@
+/**CFile****************************************************************
+
+  FileName    [dsd.h]
+
+  PackageName [DSD: Disjoint-support decomposition package.]
+
+  Synopsis    [External declarations of the package.
+  This fast BDD-based recursive algorithm for simple 
+  (single-output) DSD is based on the following papers:
+  (1) V. Bertacco and M. Damiani, "Disjunctive decomposition of 
+  logic functions," Proc. ICCAD '97, pp. 78-82.
+  (2) Y. Matsunaga, "An exact and efficient algorithm for disjunctive 
+  decomposition", Proc. SASIMI '98, pp. 44-50.
+  The scope of detected decompositions is the same as in the paper:
+  T. Sasao and M. Matsuura, "DECOMPOS: An integrated system for 
+  functional decomposition," Proc. IWLS '98, pp. 471-477.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 8.0. Started - September 22, 2003.]
+
+  Revision    [$Id: dsd.h,v 1.0 2002/22/09 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__bdd__dsd__dsd_h
+#define ABC__bdd__dsd__dsd_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+// types of DSD nodes
+enum Dsd_Type_t_ { 
+    DSD_NODE_NONE   = 0,
+    DSD_NODE_CONST1 = 1,
+    DSD_NODE_BUF    = 2,
+    DSD_NODE_OR     = 3,
+    DSD_NODE_EXOR   = 4,
+    DSD_NODE_PRIME  = 5,
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      TYPEDEF DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Dsd_Manager_t_   Dsd_Manager_t;
+typedef struct Dsd_Node_t_      Dsd_Node_t;
+typedef enum   Dsd_Type_t_      Dsd_Type_t;
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+// complementation and testing for pointers for decomposition entries
+#define Dsd_IsComplement(p)  (((int)((ABC_PTRUINT_T) (p) & 01)))
+#define Dsd_Regular(p)       ((Dsd_Node_t *)((ABC_PTRUINT_T)(p) & ~01)) 
+#define Dsd_Not(p)           ((Dsd_Node_t *)((ABC_PTRUINT_T)(p) ^ 01)) 
+#define Dsd_NotCond(p,c)     ((Dsd_Node_t *)((ABC_PTRUINT_T)(p) ^ (c)))
+
+////////////////////////////////////////////////////////////////////////
+///                         ITERATORS                                ///
+////////////////////////////////////////////////////////////////////////
+
+// iterator through the transitions
+#define Dsd_NodeForEachChild( Node, Index, Child )        \
+    for ( Index = 0;                                      \
+          Index < Dsd_NodeReadDecsNum(Node) &&            \
+             ((Child = Dsd_NodeReadDec(Node,Index))>=0);  \
+          Index++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== dsdApi.c =======================================================*/
+extern Dsd_Type_t      Dsd_NodeReadType( Dsd_Node_t * p ); 
+extern DdNode *        Dsd_NodeReadFunc( Dsd_Node_t * p );
+extern DdNode *        Dsd_NodeReadSupp( Dsd_Node_t * p );
+extern Dsd_Node_t **   Dsd_NodeReadDecs( Dsd_Node_t * p );
+extern Dsd_Node_t *    Dsd_NodeReadDec ( Dsd_Node_t * p, int i );
+extern int             Dsd_NodeReadDecsNum( Dsd_Node_t * p );
+extern int             Dsd_NodeReadMark( Dsd_Node_t * p );
+extern void            Dsd_NodeSetMark( Dsd_Node_t * p, int Mark ); 
+extern DdManager *     Dsd_ManagerReadDd( Dsd_Manager_t * pMan );
+extern Dsd_Node_t *    Dsd_ManagerReadRoot( Dsd_Manager_t * pMan, int i );
+extern Dsd_Node_t *    Dsd_ManagerReadInput( Dsd_Manager_t * pMan, int i );
+extern Dsd_Node_t *    Dsd_ManagerReadConst1( Dsd_Manager_t * pMan );
+/*=== dsdMan.c =======================================================*/
+extern Dsd_Manager_t * Dsd_ManagerStart( DdManager * dd, int nSuppMax, int fVerbose );
+extern void            Dsd_ManagerStop( Dsd_Manager_t * dMan );
+/*=== dsdProc.c =======================================================*/
+extern void            Dsd_Decompose( Dsd_Manager_t * dMan, DdNode ** pbFuncs, int nFuncs );
+extern Dsd_Node_t *    Dsd_DecomposeOne( Dsd_Manager_t * pDsdMan, DdNode * bFunc );
+/*=== dsdTree.c =======================================================*/
+extern void            Dsd_TreeNodeGetInfo( Dsd_Manager_t * dMan, int * DepthMax, int * GateSizeMax );
+extern void            Dsd_TreeNodeGetInfoOne( Dsd_Node_t * pNode, int * DepthMax, int * GateSizeMax );
+extern int             Dsd_TreeGetAigCost( Dsd_Node_t * pNode );
+extern int             Dsd_TreeCountNonTerminalNodes( Dsd_Manager_t * dMan );
+extern int             Dsd_TreeCountNonTerminalNodesOne( Dsd_Node_t * pRoot );
+extern int             Dsd_TreeCountPrimeNodes( Dsd_Manager_t * pDsdMan );
+extern int             Dsd_TreeCountPrimeNodesOne( Dsd_Node_t * pRoot );
+extern int             Dsd_TreeCollectDecomposableVars( Dsd_Manager_t * dMan, int * pVars );
+extern Dsd_Node_t **   Dsd_TreeCollectNodesDfs( Dsd_Manager_t * dMan, int * pnNodes );
+extern Dsd_Node_t **   Dsd_TreeCollectNodesDfsOne( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pNode, int * pnNodes );
+extern void            Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * dMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output );
+extern void            Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode );
+/*=== dsdLocal.c =======================================================*/
+extern DdNode *        Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                           END OF FILE                            ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/bdd/dsd/dsdApi.c b/abc-build/src/bdd/dsd/dsdApi.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/dsd/dsdApi.c
@@ -0,0 +1,102 @@
+/**CFile****************************************************************
+
+  FileName    [dsdApi.c]
+
+  PackageName [DSD: Disjoint-support decomposition package.]
+
+  Synopsis    [Implementation of API functions.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 8.0. Started - September 22, 2003.]
+
+  Revision    [$Id: dsdApi.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dsdInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+ 
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [APIs of the DSD node.]
+
+  Description [The node's type can be retrieved by calling
+  Dsd_NodeReadType(). The type is one of the following: constant 1 node, 
+  the buffer (or the elementary variable), OR gate, EXOR gate, or 
+  PRIME function (a non-DSD-decomposable function with more than two 
+  inputs). The return value of Dsd_NodeReadFunc() is the global function 
+  of the DSD node. The return value of Dsd_NodeReadSupp() is the support 
+  of the global function of the DSD node. The array of DSD nodes
+  returned by Dsd_NodeReadDecs() is the array of decomposition nodes for 
+  the formal inputs of the given node. The number of decomposition entries 
+  returned by Dsd_NodeReadDecsNum() is the number of formal inputs. 
+  The mark is explained below.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dsd_Type_t    Dsd_NodeReadType( Dsd_Node_t * p )         { return p->Type;     } 
+DdNode *      Dsd_NodeReadFunc( Dsd_Node_t * p )         { return p->G;        } 
+DdNode *      Dsd_NodeReadSupp( Dsd_Node_t * p )         { return p->S;        } 
+Dsd_Node_t ** Dsd_NodeReadDecs( Dsd_Node_t * p )         { return p->pDecs;    } 
+Dsd_Node_t *  Dsd_NodeReadDec ( Dsd_Node_t * p, int i )  { return p->pDecs[i]; } 
+int           Dsd_NodeReadDecsNum( Dsd_Node_t * p )      { return p->nDecs;    } 
+int           Dsd_NodeReadMark( Dsd_Node_t * p )         { return p->Mark;     } 
+
+/**Function*************************************************************
+
+  Synopsis    [APIs of the DSD node.]
+
+  Description [This API allows the user to set the integer mark in the
+  given DSD node. The mark is guaranteed to persist as long as the
+  calls to the decomposition are not performed. In any case, the mark 
+  is useful to associate the node with some temporary information, such 
+  as its number in the DFS ordered list of the DSD nodes or its number in 
+  the BLIF file that it being written.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void          Dsd_NodeSetMark( Dsd_Node_t * p, int Mark ){ p->Mark = Mark;     } 
+
+/**Function*************************************************************
+
+  Synopsis    [APIs of the DSD manager.]
+
+  Description [Allows the use to get hold of an individual leave of
+  the DSD tree (Dsd_ManagerReadInput) or an individual root of the 
+  decomposition tree (Dsd_ManagerReadRoot). The root may have the 
+  complemented attribute.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dsd_Node_t *  Dsd_ManagerReadRoot( Dsd_Manager_t * pMan, int i )  { return pMan->pRoots[i];  } 
+Dsd_Node_t *  Dsd_ManagerReadInput( Dsd_Manager_t * pMan, int i ) { return pMan->pInputs[i]; } 
+Dsd_Node_t *  Dsd_ManagerReadConst1( Dsd_Manager_t * pMan )       { return pMan->pConst1;    } 
+DdManager *   Dsd_ManagerReadDd( Dsd_Manager_t * pMan )           { return pMan->dd;         } 
+
+////////////////////////////////////////////////////////////////////////
+///                           END OF FILE                            ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/dsd/dsdCheck.c b/abc-build/src/bdd/dsd/dsdCheck.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/dsd/dsdCheck.c
@@ -0,0 +1,319 @@
+/**CFile****************************************************************
+
+  FileName    [dsdCheck.c]
+
+  PackageName [DSD: Disjoint-support decomposition package.]
+
+  Synopsis    [Procedures to check the identity of root functions.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 8.0. Started - September 22, 2003.]
+
+  Revision    [$Id: dsdCheck.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dsdInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Dsd_Cache_t_  Dds_Cache_t;
+typedef struct Dsd_Entry_t_  Dsd_Entry_t;
+
+struct Dsd_Cache_t_
+{
+    Dsd_Entry_t *     pTable;
+    int               nTableSize;
+    int               nSuccess;
+    int               nFailure;
+};
+
+struct Dsd_Entry_t_
+{
+    DdNode * bX[5];
+};
+
+static Dds_Cache_t * pCache;
+
+static int Dsd_CheckRootFunctionIdentity_rec( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function********************************************************************
+
+  Synopsis    [(Re)allocates the local cache.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Dsd_CheckCacheAllocate( int nEntries )
+{
+    int nRequested;
+
+    pCache = ABC_ALLOC( Dds_Cache_t, 1 );
+    memset( pCache, 0, sizeof(Dds_Cache_t) );
+
+    // check what is the size of the current cache
+    nRequested = Abc_PrimeCudd( nEntries );
+    if ( pCache->nTableSize != nRequested )
+    { // the current size is different
+        // deallocate the old, allocate the new
+        if ( pCache->nTableSize )
+            Dsd_CheckCacheDeallocate();
+        // allocate memory for the hash table
+        pCache->nTableSize = nRequested;
+        pCache->pTable = ABC_ALLOC( Dsd_Entry_t, nRequested );
+    }
+    // otherwise, there is no need to allocate, just clean
+    Dsd_CheckCacheClear();
+//  printf( "\nThe number of allocated cache entries = %d.\n\n", pCache->nTableSize );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Deallocates the local cache.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Dsd_CheckCacheDeallocate()
+{
+    ABC_FREE( pCache->pTable );
+    ABC_FREE( pCache );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Clears the local cache.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Dsd_CheckCacheClear()
+{
+    int i;
+    for ( i = 0; i < pCache->nTableSize; i++ )
+        pCache->pTable[0].bX[0] = NULL;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether it is true that bF1(bC1=0) == bF2(bC2=0).]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Dsd_CheckRootFunctionIdentity( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 )
+{
+    int RetValue;
+//  pCache->nSuccess = 0;
+//  pCache->nFailure = 0;
+    RetValue = Dsd_CheckRootFunctionIdentity_rec(dd, bF1, bF2, bC1, bC2);
+//  printf( "Cache success = %d. Cache failure = %d.\n", pCache->nSuccess, pCache->nFailure );
+    return RetValue;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Dsd_CheckRootFunctionIdentity().]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Dsd_CheckRootFunctionIdentity_rec( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 )
+{
+    unsigned HKey;
+
+    // if either bC1 or bC2 is zero, the test is true
+//  if ( bC1 == b0 || bC2 == b0 )  return 1;
+    assert( bC1 != b0 );
+    assert( bC2 != b0 );
+
+    // if both bC1 and bC2 are one - perform comparison
+    if ( bC1 == b1 && bC2 == b1 )  return (int)( bF1 == bF2 );
+
+    if ( bF1 == b0 )
+        return Cudd_bddLeq( dd, bC2, Cudd_Not(bF2) );
+
+    if ( bF1 == b1 )
+        return Cudd_bddLeq( dd, bC2, bF2 );
+
+    if ( bF2 == b0 )
+        return Cudd_bddLeq( dd, bC1, Cudd_Not(bF1) );
+
+    if ( bF2 == b1 )
+        return Cudd_bddLeq( dd, bC1, bF1 );
+
+    // otherwise, keep expanding
+
+    // check cache
+//  HKey = _Hash( ((unsigned)bF1), ((unsigned)bF2), ((unsigned)bC1), ((unsigned)bC2) );
+    HKey = hashKey4( bF1, bF2, bC1, bC2, pCache->nTableSize );
+    if ( pCache->pTable[HKey].bX[0] == bF1 && 
+         pCache->pTable[HKey].bX[1] == bF2 && 
+         pCache->pTable[HKey].bX[2] == bC1 && 
+         pCache->pTable[HKey].bX[3] == bC2 )
+    {
+        pCache->nSuccess++;
+        return (int)(ABC_PTRUINT_T)pCache->pTable[HKey].bX[4]; // the last bit records the result (yes/no)
+    }
+    else
+    {
+
+        // determine the top variables
+        int RetValue;
+        DdNode * bA[4]  = { bF1, bF2, bC1, bC2 }; // arguments
+        DdNode * bAR[4] = { Cudd_Regular(bF1), Cudd_Regular(bF2), Cudd_Regular(bC1), Cudd_Regular(bC2) }; // regular arguments
+        int CurLevel[4] = { cuddI(dd,bAR[0]->index), cuddI(dd,bAR[1]->index), cuddI(dd,bAR[2]->index), cuddI(dd,bAR[3]->index) };
+        int TopLevel = CUDD_CONST_INDEX;
+        int i;
+        DdNode * bE[4], * bT[4];
+        DdNode * bF1next, * bF2next, * bC1next, * bC2next;
+
+        pCache->nFailure++;
+
+        // determine the top level
+        for ( i = 0; i < 4; i++ )
+            if ( TopLevel > CurLevel[i] )
+                 TopLevel = CurLevel[i];
+
+        // compute the cofactors
+        for ( i = 0; i < 4; i++ )
+        if ( TopLevel == CurLevel[i] )
+        {
+            if ( bA[i] != bAR[i] ) // complemented
+            {
+                bE[i] = Cudd_Not(cuddE(bAR[i]));
+                bT[i] = Cudd_Not(cuddT(bAR[i]));
+            }
+            else
+            {
+                bE[i] = cuddE(bAR[i]);
+                bT[i] = cuddT(bAR[i]);
+            }
+        }
+        else
+            bE[i] = bT[i] = bA[i];
+
+        // solve subproblems
+        // three cases are possible
+
+        // (1) the top var belongs to both C1 and C2
+        //     in this case, any cofactor of F1 and F2 will do, 
+        //     as long as the corresponding cofactor of C1 and C2 is not equal to 0
+        if ( TopLevel == CurLevel[2] && TopLevel == CurLevel[3] ) 
+        {
+            if ( bE[2] != b0 ) // C1
+            {
+                bF1next = bE[0];
+                bC1next = bE[2];
+            }
+            else
+            {
+                bF1next = bT[0];
+                bC1next = bT[2];
+            }
+            if ( bE[3] != b0 ) // C2
+            {
+                bF2next = bE[1];
+                bC2next = bE[3];
+            }
+            else
+            {
+                bF2next = bT[1];
+                bC2next = bT[3];
+            }
+            RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bF2next, bC1next, bC2next );
+        }
+        // (2) the top var belongs to either C1 or C2
+        //     in this case normal splitting of cofactors
+        else if ( TopLevel == CurLevel[2] && TopLevel != CurLevel[3] ) 
+        {
+            if ( bE[2] != b0 ) // C1
+            {
+                bF1next = bE[0];
+                bC1next = bE[2];
+            }
+            else
+            {
+                bF1next = bT[0];
+                bC1next = bT[2];
+            }
+            // split around this variable
+            RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bE[1], bC1next, bE[3] );
+            if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test
+                RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bT[1], bC1next, bT[3] );
+        }
+        else if ( TopLevel != CurLevel[2] && TopLevel == CurLevel[3] ) 
+        {
+            if ( bE[3] != b0 ) // C2
+            {
+                bF2next = bE[1];
+                bC2next = bE[3];
+            }
+            else
+            {
+                bF2next = bT[1];
+                bC2next = bT[3];
+            }
+            // split around this variable
+            RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bE[0], bF2next, bE[2], bC2next );
+            if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test
+                RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bT[0], bF2next, bT[2], bC2next );
+        }
+        // (3) the top var does not belong to C1 and C2
+        //     in this case normal splitting of cofactors
+        else // if ( TopLevel != CurLevel[2] && TopLevel != CurLevel[3] )
+        {
+            // split around this variable
+            RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bE[0], bE[1], bE[2], bE[3] );
+            if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test
+                RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bT[0], bT[1], bT[2], bT[3] );
+        }
+
+        // set cache
+        for ( i = 0; i < 4; i++ )
+            pCache->pTable[HKey].bX[i] = bA[i];
+        pCache->pTable[HKey].bX[4] = (DdNode*)(ABC_PTRUINT_T)RetValue;
+
+        return RetValue;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/dsd/dsdInt.h b/abc-build/src/bdd/dsd/dsdInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/dsd/dsdInt.h
@@ -0,0 +1,99 @@
+/**CFile****************************************************************
+
+  FileName    [dsdInt.h]
+
+  PackageName [DSD: Disjoint-support decomposition package.]
+
+  Synopsis    [Internal declarations of the package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 8.0. Started - September 22, 2003.]
+
+  Revision    [$Id: dsdInt.h,v 1.0 2002/22/09 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__bdd__dsd__dsdInt_h
+#define ABC__bdd__dsd__dsdInt_h
+
+
+#include "misc/extra/extraBdd.h"
+#include "dsd.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                      TYPEDEF DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+typedef unsigned char byte;
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+// DSD manager
+struct Dsd_Manager_t_ 
+{
+    DdManager *    dd;         // the BDD manager
+    st__table *     Table;      // the mapping of BDDs into their DEs
+    int            nInputs;    // the number of primary inputs
+    int            nRoots;     // the number of primary outputs
+    int            nRootsAlloc;// the number of primary outputs
+    Dsd_Node_t **  pInputs;    // the primary input nodes
+    Dsd_Node_t **  pRoots;     // the primary output nodes
+    Dsd_Node_t *   pConst1;    // the constant node
+    int            fVerbose;   // the verbosity level 
+};
+
+// DSD node
+struct Dsd_Node_t_
+{
+    Dsd_Type_t     Type;       // decomposition type
+    DdNode *       G;          // function of the node   
+    DdNode *       S;          // support of this function
+    Dsd_Node_t **  pDecs;      // pointer to structures for formal inputs
+    int            Mark;       // the mark used by CASE 4 of disjoint decomposition
+    short          nDecs;      // the number of formal inputs
+    short          nVisits;    // the counter of visits
+};
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+#define MAXINPUTS 1000
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DECLARATIONS                        ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== dsdCheck.c =======================================================*/
+extern void         Dsd_CheckCacheAllocate( int nEntries );
+extern void         Dsd_CheckCacheDeallocate();
+extern void         Dsd_CheckCacheClear();
+extern int          Dsd_CheckRootFunctionIdentity( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 );
+/*=== dsdTree.c =======================================================*/
+extern Dsd_Node_t * Dsd_TreeNodeCreate( int Type, int nDecs, int BlockNum );
+extern void         Dsd_TreeNodeDelete( DdManager * dd, Dsd_Node_t * pNode );
+extern void         Dsd_TreeUnmark( Dsd_Manager_t * dMan );
+extern DdNode *     Dsd_TreeGetPrimeFunctionOld( DdManager * dd, Dsd_Node_t * pNode, int fRemap );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                           END OF FILE                            ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/bdd/dsd/dsdLocal.c b/abc-build/src/bdd/dsd/dsdLocal.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/dsd/dsdLocal.c
@@ -0,0 +1,342 @@
+/**CFile****************************************************************
+
+  FileName    [dsdLocal.c]
+
+  PackageName [DSD: Disjoint-support decomposition package.]
+
+  Synopsis    [Deriving the local function of the DSD node.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 8.0. Started - September 22, 2003.]
+
+  Revision    [$Id: dsdLocal.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dsdInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      STATIC VARIABLES                            ///
+////////////////////////////////////////////////////////////////////////
+
+static DdNode * Extra_dsdRemap( DdManager * dd, DdNode * bFunc, st__table * pCache,
+    int * pVar2Form, int * pForm2Var, DdNode * pbCube0[], DdNode * pbCube1[] );
+static DdNode * Extra_bddNodePointedByCube( DdManager * dd, DdNode * bF, DdNode * bC );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the local function of the DSD node. ]
+
+  Description [The local function is computed using the global function 
+  of the node and the global functions of the formal inputs. The resulting
+  local function is mapped using the topmost N variables of the manager.
+  The number of variables N is equal to the number of formal inputs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode ) 
+{
+    int * pForm2Var;   // the mapping of each formal input into its first var
+    int * pVar2Form;   // the mapping of each var into its formal inputs
+    int i, iVar, iLev, * pPermute;
+    DdNode ** pbCube0, ** pbCube1;
+    DdNode * bFunc, * bRes, * bTemp;
+    st__table * pCache;
+    
+    pPermute  = ABC_ALLOC( int, dd->size );
+    pVar2Form = ABC_ALLOC( int, dd->size );
+    pForm2Var = ABC_ALLOC( int, dd->size );
+
+    pbCube0 = ABC_ALLOC( DdNode *, dd->size );
+    pbCube1 = ABC_ALLOC( DdNode *, dd->size );
+
+    // remap the global function in such a way that
+    // the support variables of each formal input are adjacent
+    iLev = 0;
+    for ( i = 0; i < pNode->nDecs; i++ )
+    {
+        pForm2Var[i] = dd->invperm[i];
+        for ( bTemp = pNode->pDecs[i]->S; bTemp != b1; bTemp = cuddT(bTemp) )
+        {
+            iVar = dd->invperm[iLev];
+            pPermute[bTemp->index] = iVar;
+            pVar2Form[iVar] = i;
+            iLev++;
+        }
+
+        // collect the cubes representing each assignment
+        pbCube0[i] = Extra_bddGetOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) );
+        Cudd_Ref( pbCube0[i] );
+        pbCube1[i] = Extra_bddGetOneCube( dd, pNode->pDecs[i]->G );
+        Cudd_Ref( pbCube1[i] );
+    }
+
+    // remap the function
+    bFunc = Cudd_bddPermute( dd, pNode->G, pPermute ); Cudd_Ref( bFunc );
+    // remap the cube
+    for ( i = 0; i < pNode->nDecs; i++ )
+    {
+        pbCube0[i] = Cudd_bddPermute( dd, bTemp = pbCube0[i], pPermute ); Cudd_Ref( pbCube0[i] );
+        Cudd_RecursiveDeref( dd, bTemp );
+        pbCube1[i] = Cudd_bddPermute( dd, bTemp = pbCube1[i], pPermute ); Cudd_Ref( pbCube1[i] );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+
+    // remap the function
+    pCache = st__init_table( st__ptrcmp, st__ptrhash);;
+    bRes = Extra_dsdRemap( dd, bFunc, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 );  Cudd_Ref( bRes );
+    st__free_table( pCache );
+
+    Cudd_RecursiveDeref( dd, bFunc );
+    for ( i = 0; i < pNode->nDecs; i++ )
+    {
+        Cudd_RecursiveDeref( dd, pbCube0[i] );
+        Cudd_RecursiveDeref( dd, pbCube1[i] );
+    }
+/*
+////////////
+    // permute the function once again
+    // in such a way that i-th var stood for i-th formal input
+    for ( i = 0; i < dd->size; i++ )
+        pPermute[i] = -1;
+    for ( i = 0; i < pNode->nDecs; i++ )
+        pPermute[dd->invperm[i]] = i;
+    bRes = Cudd_bddPermute( dd, bTemp = bRes, pPermute ); Cudd_Ref( bRes );
+    Cudd_RecursiveDeref( dd, bTemp );
+////////////
+*/
+    ABC_FREE(pPermute);
+    ABC_FREE(pVar2Form);
+    ABC_FREE(pForm2Var);
+    ABC_FREE(pbCube0);
+    ABC_FREE(pbCube1);
+
+    Cudd_Deref( bRes );
+    return bRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_dsdRemap( DdManager * dd, DdNode * bF, st__table * pCache,
+    int * pVar2Form, int * pForm2Var, DdNode * pbCube0[], DdNode * pbCube1[] )
+{
+    DdNode * bFR, * bF0, * bF1;
+    DdNode * bRes0, * bRes1, * bRes;
+    int iForm;
+    
+    bFR = Cudd_Regular(bF);
+    if ( cuddIsConstant(bFR) )
+        return bF;
+
+    // check the hash-table
+    if ( bFR->ref != 1 )
+    {
+        if ( st__lookup( pCache, (char *)bF, (char **)&bRes ) )
+            return bRes;
+    }
+
+    // get the formal input
+    iForm = pVar2Form[bFR->index];
+
+    // get the nodes pointed to by the cube
+    bF0 = Extra_bddNodePointedByCube( dd, bF, pbCube0[iForm] );
+    bF1 = Extra_bddNodePointedByCube( dd, bF, pbCube1[iForm] );
+
+    // call recursively for these nodes
+    bRes0 = Extra_dsdRemap( dd, bF0, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes0 );
+    bRes1 = Extra_dsdRemap( dd, bF1, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes1 );
+
+    // derive the result using ITE
+    bRes = Cudd_bddIte( dd, dd->vars[ pForm2Var[iForm] ], bRes1, bRes0 ); Cudd_Ref( bRes );
+    Cudd_RecursiveDeref( dd, bRes0 );
+    Cudd_RecursiveDeref( dd, bRes1 );
+
+    // add to the hash table
+    if ( bFR->ref != 1 )
+        st__insert( pCache, (char *)bF, (char *)bRes );
+    Cudd_Deref( bRes );
+    return bRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_bddNodePointedByCube( DdManager * dd, DdNode * bF, DdNode * bC )
+{
+    DdNode * bFR, * bCR;
+    DdNode * bF0, * bF1;
+    DdNode * bC0, * bC1;
+    int LevelF, LevelC;
+
+    assert( bC != b0 );
+    if ( bC == b1 )
+        return bF;
+
+//    bRes = cuddCacheLookup2( dd, Extra_bddNodePointedByCube, bF, bC );
+//    if ( bRes )
+//      return bRes;
+    // there is no need for caching because this operation is very fast
+    // there will no gain reusing the results of this operations
+    // instead, it will flush CUDD cache of other useful entries
+
+
+    bFR = Cudd_Regular( bF ); 
+    bCR = Cudd_Regular( bC ); 
+    assert( !cuddIsConstant( bFR ) );
+
+    LevelF = dd->perm[bFR->index];
+    LevelC = dd->perm[bCR->index];
+
+    if ( LevelF <= LevelC )
+    {
+        if ( bFR != bF )
+        {
+            bF0 = Cudd_Not( cuddE(bFR) );
+            bF1 = Cudd_Not( cuddT(bFR) );
+        }
+        else
+        {
+            bF0 = cuddE(bFR);
+            bF1 = cuddT(bFR);
+        }
+    }
+    else
+    {
+        bF0 = bF1 = bF;
+    }
+
+    if ( LevelC <= LevelF )
+    {
+        if ( bCR != bC )
+        {
+            bC0 = Cudd_Not( cuddE(bCR) );
+            bC1 = Cudd_Not( cuddT(bCR) );
+        }
+        else
+        {
+            bC0 = cuddE(bCR);
+            bC1 = cuddT(bCR);
+        }
+    }
+    else
+    {
+        bC0 = bC1 = bC;
+    }
+
+    assert( bC0 == b0 || bC1 == b0 );
+    if ( bC0 == b0 )
+        return Extra_bddNodePointedByCube( dd, bF1, bC1 );
+    return Extra_bddNodePointedByCube( dd, bF0, bC0 );
+}
+
+#if 0
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * dsdTreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode, int fRemap ) 
+{
+    DdNode * bCof0,  * bCof1, * bCube0, * bCube1, * bNewFunc, * bTemp;
+    int i;
+    int fAllBuffs = 1;
+    static int Permute[MAXINPUTS];
+
+    assert( pNode );
+    assert( !Dsd_IsComplement( pNode ) );
+    assert( pNode->Type == DT_PRIME );
+
+    // transform the function of this block to depend on inputs
+    // corresponding to the formal inputs
+
+    // first, substitute those inputs that have some blocks associated with them
+    // second, remap the inputs to the top of the manager (then, it is easy to output them)
+
+    // start the function
+    bNewFunc = pNode->G;  Cudd_Ref( bNewFunc );
+    // go over all primary inputs
+    for ( i = 0; i < pNode->nDecs; i++ )
+    if ( pNode->pDecs[i]->Type != DT_BUF ) // remap only if it is not the buffer
+    {
+        bCube0 = Extra_bddFindOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) );  Cudd_Ref( bCube0 );
+        bCof0 = Cudd_Cofactor( dd, bNewFunc, bCube0 );                     Cudd_Ref( bCof0 );
+        Cudd_RecursiveDeref( dd, bCube0 );
+
+        bCube1 = Extra_bddFindOneCube( dd,          pNode->pDecs[i]->G  );  Cudd_Ref( bCube1 );
+        bCof1 = Cudd_Cofactor( dd, bNewFunc, bCube1 );                     Cudd_Ref( bCof1 );
+        Cudd_RecursiveDeref( dd, bCube1 );
+
+        Cudd_RecursiveDeref( dd, bNewFunc );
+
+        // use the variable in the i-th level of the manager
+//      bNewFunc = Cudd_bddIte( dd, dd->vars[dd->invperm[i]],bCof1,bCof0 );     Cudd_Ref( bNewFunc );
+        // use the first variale in the support of the component
+        bNewFunc = Cudd_bddIte( dd, dd->vars[pNode->pDecs[i]->S->index],bCof1,bCof0 );     Cudd_Ref( bNewFunc );
+        Cudd_RecursiveDeref( dd, bCof0 );
+        Cudd_RecursiveDeref( dd, bCof1 );
+    }
+
+    if ( fRemap )
+    {
+        // remap the function to the top of the manager
+        // remap the function to the first variables of the manager
+        for ( i = 0; i < pNode->nDecs; i++ )
+    //      Permute[ pNode->pDecs[i]->S->index ] = dd->invperm[i];
+            Permute[ pNode->pDecs[i]->S->index ] = i;
+
+        bNewFunc = Cudd_bddPermute( dd, bTemp = bNewFunc, Permute );   Cudd_Ref( bNewFunc );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+
+    Cudd_Deref( bNewFunc );
+    return bNewFunc;
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                           END OF FILE                            ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/dsd/dsdMan.c b/abc-build/src/bdd/dsd/dsdMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/dsd/dsdMan.c
@@ -0,0 +1,119 @@
+/**CFile****************************************************************
+
+  FileName    [dsdMan.c]
+
+  PackageName [DSD: Disjoint-support decomposition package.]
+
+  Synopsis    [APIs of the DSD manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 8.0. Started - September 22, 2003.]
+
+  Revision    [$Id: dsdMan.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dsdInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       API OF DSD MANAGER                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the DSD manager.]
+
+  Description [Takes the started BDD manager and the maximum support size
+  of the function to be DSD-decomposed. The manager should have at least as
+  many variables as there are variables in the support. The functions should 
+  be expressed using the first nSuppSizeMax variables in the manager (these
+  may be ordered not necessarily on top of the manager).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dsd_Manager_t * Dsd_ManagerStart( DdManager * dd, int nSuppMax, int fVerbose )
+{
+    Dsd_Manager_t * dMan;
+    Dsd_Node_t * pNode;
+    int i;
+
+    assert( nSuppMax <= dd->size );
+
+    dMan = ABC_ALLOC( Dsd_Manager_t, 1 );
+    memset( dMan, 0, sizeof(Dsd_Manager_t) );
+    dMan->dd          = dd;
+    dMan->nInputs     = nSuppMax;
+    dMan->fVerbose    = fVerbose;
+    dMan->nRoots      = 0;
+    dMan->nRootsAlloc = 50;
+    dMan->pRoots      = (Dsd_Node_t **) ABC_ALLOC( char, dMan->nRootsAlloc * sizeof(Dsd_Node_t *) );
+    dMan->pInputs     = (Dsd_Node_t **) ABC_ALLOC( char, dMan->nInputs     * sizeof(Dsd_Node_t *) );
+
+    // create the primary inputs and insert them into the table
+    dMan->Table       = st__init_table( st__ptrcmp, st__ptrhash);
+    for ( i = 0; i < dMan->nInputs; i++ )
+    {
+        pNode = Dsd_TreeNodeCreate( DSD_NODE_BUF, 1, 0 );
+        pNode->G = dd->vars[i];  Cudd_Ref( pNode->G );
+        pNode->S = dd->vars[i];  Cudd_Ref( pNode->S );
+        st__insert( dMan->Table, (char*)dd->vars[i], (char*)pNode );
+        dMan->pInputs[i] = pNode;
+    }
+    pNode = Dsd_TreeNodeCreate( DSD_NODE_CONST1, 0, 0 );
+    pNode->G = b1;  Cudd_Ref( pNode->G );
+    pNode->S = b1;  Cudd_Ref( pNode->S );
+    st__insert( dMan->Table, (char*)b1, (char*)pNode );
+    dMan->pConst1 = pNode;
+
+    Dsd_CheckCacheAllocate( 5000 );
+    return dMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the DSD manager.]
+
+  Description [Stopping the DSD manager automatically derefereces and
+  deallocates all the DSD nodes that were created during the life time
+  of the DSD manager. As a result, the user does not need to deref or
+  deallocate any DSD nodes or trees that are derived and placed in
+  the manager while it exists.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dsd_ManagerStop( Dsd_Manager_t * dMan )
+{
+    st__generator * gen;
+    Dsd_Node_t * pNode;
+    DdNode * bFunc;
+    // delete the nodes
+    st__foreach_item( dMan->Table, gen, (const char**)&bFunc, (char**)&pNode )
+        Dsd_TreeNodeDelete( dMan->dd, Dsd_Regular(pNode) );
+    st__free_table(dMan->Table);
+    ABC_FREE( dMan->pInputs );
+    ABC_FREE( dMan->pRoots );
+    ABC_FREE( dMan );
+    Dsd_CheckCacheDeallocate();
+}
+
+////////////////////////////////////////////////////////////////////////
+///                           END OF FILE                            ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/dsd/dsdProc.c b/abc-build/src/bdd/dsd/dsdProc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/dsd/dsdProc.c
@@ -0,0 +1,1613 @@
+/**CFile****************************************************************
+
+  FileName    [dsdProc.c]
+
+  PackageName [DSD: Disjoint-support decomposition package.]
+
+  Synopsis    [The core procedures of the package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 8.0. Started - September 22, 2003.]
+
+  Revision    [$Id: dsdProc.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dsdInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+// the most important procedures
+void dsdKernelDecompose( Dsd_Manager_t * pDsdMan, DdNode ** pbFuncs, int nFuncs );
+static Dsd_Node_t * dsdKernelDecompose_rec( Dsd_Manager_t * pDsdMan, DdNode * F );
+
+// additional procedures
+static Dsd_Node_t * dsdKernelFindContainingComponent( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pWhere, DdNode * Var, int * fPolarity );
+static int dsdKernelFindCommonComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t *** pCommon, Dsd_Node_t ** pLastDiffL, Dsd_Node_t ** pLastDiffH );
+static void dsdKernelComputeSumOfComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t ** pCommon, int nCommon, DdNode ** pCompF, DdNode ** pCompS, int fExor );
+static int dsdKernelCheckContainment( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t ** pLarge, Dsd_Node_t ** pSmall );
+
+// list copying
+static void dsdKernelCopyListPlusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize );
+static void dsdKernelCopyListPlusOneMinusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize, int Skipped );
+
+// debugging procedures
+static int dsdKernelVerifyDecomposition( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pDE );
+
+////////////////////////////////////////////////////////////////////////
+///                       STATIC VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+// the counter of marks
+static int s_Mark;
+
+// debugging flag
+//static int s_Show = 0;
+// temporary var used for debugging
+static int Depth = 0;
+
+static int s_Loops1;
+static int s_Loops2;
+static int s_Loops3;
+static int s_Common;
+static int s_CommonNo;
+
+static int s_Case4Calls;
+static int s_Case4CallsSpecial;
+
+//static int s_Case5;
+//static int s_Loops2Useless;
+
+// statistical variables
+static int   s_nDecBlocks;
+static int   s_nLiterals;
+static int   s_nExorGates; 
+static int   s_nReusedBlocks;
+static int   s_nCascades;
+static int   s_nPrimeBlocks;
+
+static int HashSuccess = 0;
+static int HashFailure = 0;
+
+static int s_CacheEntries;
+
+
+////////////////////////////////////////////////////////////////////////
+///                     DECOMPOSITION FUNCTIONS                      ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DSD for the array of functions represented by BDDs.]
+
+  Description [This function takes the DSD manager, which should be
+  previously allocated by the call to Dsd_ManagerStart(). The resulting
+  DSD tree is stored in the DSD manager (pDsdMan->pRoots, pDsdMan->nRoots).
+  Access to the tree is through the APIs of the manager. The resulting
+  tree is a shared DSD DAG for the functions given in the array. For one
+  function the resulting DAG is always a tree. The root node pointers can 
+  be complemented, as discussed in the literature referred to in "dsd.h".
+  This procedure can be called repeatedly for different functions. There is
+  no need to remove the decomposition tree after it is returned, because
+  the next call to the DSD manager will "recycle" the tree. The user should
+  not modify or dereference any data associated with the nodes of the 
+  DSD trees (the user can only change the contents of a temporary
+  mark associated with each node by the calling to Dsd_NodeSetMark()).
+  All the decomposition trees and intermediate nodes will be removed when
+  the DSD manager is deallocated at the end by calling Dsd_ManagerStop().]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dsd_Decompose( Dsd_Manager_t * pDsdMan, DdNode ** pbFuncs, int nFuncs )
+{
+    DdManager * dd = pDsdMan->dd;
+    int i;
+    abctime clk;
+    Dsd_Node_t * pTemp;
+    int SumMaxGateSize = 0;
+    int nDecOutputs = 0;
+    int nCBFOutputs = 0;
+/*
+s_Loops1 = 0;
+s_Loops2 = 0;
+s_Loops3 = 0;
+s_Case4Calls = 0;
+s_Case4CallsSpecial = 0;
+s_Case5 = 0;
+s_Loops2Useless = 0;
+*/
+    // resize the number of roots in the manager
+    if ( pDsdMan->nRootsAlloc < nFuncs )
+    {
+        if ( pDsdMan->nRootsAlloc > 0 )
+            ABC_FREE( pDsdMan->pRoots );
+        pDsdMan->nRootsAlloc = nFuncs;
+        pDsdMan->pRoots = (Dsd_Node_t **) ABC_ALLOC( char, pDsdMan->nRootsAlloc * sizeof(Dsd_Node_t *) );
+    }
+
+    if ( pDsdMan->fVerbose )
+        printf( "\nDecomposability statistics for individual outputs:\n" );
+
+    // set the counter of decomposition nodes
+    s_nDecBlocks = 0;
+
+    // perform decomposition for all outputs
+    clk = Abc_Clock();
+    pDsdMan->nRoots = 0;
+    s_nCascades = 0;
+    for ( i = 0; i < nFuncs; i++ )
+    {
+        int nLiteralsPrev;
+        int nDecBlocksPrev;
+        int nExorGatesPrev;
+        int nReusedBlocksPres;
+        int nCascades;
+        int MaxBlock;
+        int nPrimeBlocks;
+        abctime clk;
+
+        clk = Abc_Clock();
+        nLiteralsPrev     = s_nLiterals;
+        nDecBlocksPrev    = s_nDecBlocks;
+        nExorGatesPrev    = s_nExorGates;
+        nReusedBlocksPres = s_nReusedBlocks;
+        nPrimeBlocks      = s_nPrimeBlocks;
+
+        pDsdMan->pRoots[ pDsdMan->nRoots++ ] = dsdKernelDecompose_rec( pDsdMan, pbFuncs[i] );
+
+        Dsd_TreeNodeGetInfoOne( pDsdMan->pRoots[i], &nCascades, &MaxBlock );
+        s_nCascades = ddMax( s_nCascades, nCascades );
+        pTemp = Dsd_Regular(pDsdMan->pRoots[i]);
+        if ( pTemp->Type != DSD_NODE_PRIME || pTemp->nDecs != Extra_bddSuppSize(dd,pTemp->S) )
+            nDecOutputs++;
+        if ( MaxBlock < 3 )
+            nCBFOutputs++;
+        SumMaxGateSize += MaxBlock;
+
+        if ( pDsdMan->fVerbose )
+        {
+            printf("#%02d: ", i );                              
+            printf("Ins=%2d. ", Cudd_SupportSize(dd,pbFuncs[i]) );                  
+            printf("Gts=%3d. ", Dsd_TreeCountNonTerminalNodesOne( pDsdMan->pRoots[i] ) ); 
+            printf("Pri=%3d. ", Dsd_TreeCountPrimeNodesOne( pDsdMan->pRoots[i] ) ); 
+            printf("Max=%3d. ", MaxBlock ); 
+            printf("Reuse=%2d. ", s_nReusedBlocks-nReusedBlocksPres ); 
+            printf("Csc=%2d. ", nCascades ); 
+            printf("T= %.2f s. ", (float)(Abc_Clock()-clk)/(float)(CLOCKS_PER_SEC) ) ;
+            printf("Bdd=%2d. ", Cudd_DagSize(pbFuncs[i]) ); 
+            printf("\n");
+            fflush( stdout );
+        }
+    }
+    assert( pDsdMan->nRoots == nFuncs );
+
+    if ( pDsdMan->fVerbose )
+    {
+        printf( "\n" );
+        printf( "The cumulative decomposability statistics:\n" );
+        printf( "  Total outputs                             = %5d\n", nFuncs );
+        printf( "  Decomposable outputs                      = %5d\n", nDecOutputs );
+        printf( "  Completely decomposable outputs           = %5d\n", nCBFOutputs );
+        printf( "  The sum of max gate sizes                 = %5d\n", SumMaxGateSize );
+        printf( "  Shared BDD size                           = %5d\n", Cudd_SharingSize( pbFuncs, nFuncs ) );
+        printf( "  Decomposition entries                     = %5d\n", st__count( pDsdMan->Table ) );
+        printf( "  Pure decomposition time                   =  %.2f sec\n", (float)(Abc_Clock() - clk)/(float)(CLOCKS_PER_SEC) );
+    }
+/*
+    printf( "s_Loops1 = %d.\n", s_Loops1 );
+    printf( "s_Loops2 = %d.\n", s_Loops2 );
+    printf( "s_Loops3 = %d.\n", s_Loops3 );
+    printf( "s_Case4Calls = %d.\n", s_Case4Calls );
+    printf( "s_Case4CallsSpecial = %d.\n", s_Case4CallsSpecial );
+    printf( "s_Case5 = %d.\n", s_Case5 );
+    printf( "s_Loops2Useless = %d.\n", s_Loops2Useless );
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs decomposition for one function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dsd_Node_t * Dsd_DecomposeOne( Dsd_Manager_t * pDsdMan, DdNode * bFunc )
+{
+    return dsdKernelDecompose_rec( pDsdMan, bFunc );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [The main function of this module. Recursive implementation of DSD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dsd_Node_t * dsdKernelDecompose_rec( Dsd_Manager_t * pDsdMan, DdNode * bFunc0 )
+{
+    DdManager * dd = pDsdMan->dd;
+    DdNode * bLow;
+    DdNode * bLowR;
+    DdNode * bHigh;
+
+    int      VarInt;
+    DdNode * bVarCur;
+    Dsd_Node_t *     pVarCurDE; 
+    // works only if var indices start from 0!!!
+    DdNode * bSuppNew = NULL, * bTemp;
+
+    int fContained;
+    int nSuppLH;
+    int nSuppL;
+    int nSuppH;
+
+
+
+    // various decomposition nodes
+    Dsd_Node_t * pThis, * pL, * pH, * pLR, * pHR;
+
+    Dsd_Node_t * pSmallR, * pLargeR;
+    Dsd_Node_t * pTableEntry;
+
+
+    // treat the complemented case
+    DdNode * bF = Cudd_Regular(bFunc0);
+    int  fCompF = (int)(bF != bFunc0);
+
+    // check cache
+    if ( st__lookup( pDsdMan->Table, (char*)bF, (char**)&pTableEntry ) )
+    { // the entry is present 
+        HashSuccess++;
+        return Dsd_NotCond( pTableEntry, fCompF );
+    }
+    HashFailure++;
+    Depth++;
+
+    // proceed to consider "four cases"
+    //////////////////////////////////////////////////////////////////////
+    // TERMINAL CASES - CASES 1 and 2
+    //////////////////////////////////////////////////////////////////////
+    bLow    = cuddE(bF);
+    bLowR   = Cudd_Regular(bLow);
+    bHigh   = cuddT(bF);
+    VarInt    = bF->index;
+    bVarCur   = dd->vars[VarInt];
+    pVarCurDE = pDsdMan->pInputs[VarInt]; 
+    // works only if var indices start from 0!!!
+    bSuppNew = NULL;
+
+    if ( bLowR->index == CUDD_CONST_INDEX || bHigh->index == CUDD_CONST_INDEX )
+    { // one of the cofactors in the constant
+        if ( bHigh == b1 )  // bHigh cannot be equal to b0, because then it will be complemented
+          if ( bLow == b0 ) // bLow cannot be equal to b1, because then the node will have bLow == bHigh
+          /////////////////////////////////////////////////////////////////
+          // bLow == 0, bHigh == 1, F = x'&0 + x&1 = x
+          /////////////////////////////////////////////////////////////////
+          { // create the elementary variable node
+            assert(0); // should be already in the hash table
+            pThis = Dsd_TreeNodeCreate( DSD_NODE_BUF, 1, s_nDecBlocks++ );
+            pThis->pDecs[0] = NULL;
+          }
+          else // if ( bLow != constant )
+          /////////////////////////////////////////////////////////////////
+          // bLow != const, bHigh == 1, F = x'&bLow + x&1 = bLow + x  --- DSD_NODE_OR(x,bLow)
+          /////////////////////////////////////////////////////////////////
+          {
+            pL  = dsdKernelDecompose_rec( pDsdMan, bLow );
+            pLR = Dsd_Regular( pL );
+            bSuppNew = Cudd_bddAnd( dd, bVarCur, pLR->S ); Cudd_Ref(bSuppNew);
+            if ( pLR->Type == DSD_NODE_OR && pL == pLR ) // OR and no complement
+            { // add to the components
+                pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pL->nDecs+1, s_nDecBlocks++ );
+                dsdKernelCopyListPlusOne( pThis, pVarCurDE, pL->pDecs, pL->nDecs );
+            }
+            else // all other cases
+            { // create a new 2-input OR-gate
+                pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ );
+                dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pL, 1 );
+            }
+          }
+        else // if ( bHigh != const ) // meaning that bLow should be a constant
+        {
+          pH = dsdKernelDecompose_rec( pDsdMan, bHigh );
+          pHR = Dsd_Regular( pH );
+          bSuppNew = Cudd_bddAnd( dd, bVarCur, pHR->S ); Cudd_Ref(bSuppNew);
+          if ( bLow == b0 )
+          /////////////////////////////////////////////////////////////////
+          // Low == 0, High != 1, F = x'&0+x&High = (x'+High')'--- NOR(x',High')
+          /////////////////////////////////////////////////////////////////
+            if ( pHR->Type == DSD_NODE_OR && pH != pHR ) // DSD_NODE_OR and complement
+            { // add to the components
+              pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pHR->nDecs+1, s_nDecBlocks++ );
+              dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), pHR->pDecs, pHR->nDecs );
+              pThis = Dsd_Not(pThis);
+            }
+            else // all other cases
+            { // create a new 2-input NOR gate
+              pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ );
+              pH = Dsd_Not(pH);
+              dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), &pH, 1 );
+              pThis = Dsd_Not(pThis);
+            }
+          else // if ( bLow == b1 )
+          /////////////////////////////////////////////////////////////////
+          // Low == 1, High != 1, F = x'&1 + x&High = x' + High --- DSD_NODE_OR(x',High)
+          /////////////////////////////////////////////////////////////////
+            if ( pHR->Type == DSD_NODE_OR && pH == pHR ) // OR and no complement
+            { // add to the components
+                pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pH->nDecs+1, s_nDecBlocks++ );
+                dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), pH->pDecs, pH->nDecs );
+            }
+            else // all other cases
+            { // create a new 2-input OR-gate
+                pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ );
+                dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), &pH, 1 );
+            }
+        }
+        goto EXIT;
+    }
+    // else if ( bLow != const && bHigh != const )
+
+    // the case of equal cofactors (up to complementation)
+    if ( bLowR == bHigh )
+    /////////////////////////////////////////////////////////////////
+    // Low == G, High == G', F = x'&G + x&G' = (x(+)G) --- EXOR(x,Low)
+    /////////////////////////////////////////////////////////////////
+    {
+        pL  = dsdKernelDecompose_rec( pDsdMan, bLow );
+        pLR = Dsd_Regular( pL );
+        bSuppNew = Cudd_bddAnd( dd, bVarCur, pLR->S ); Cudd_Ref(bSuppNew);
+        if ( pLR->Type == DSD_NODE_EXOR ) // complemented or not - does not matter!
+        { // add to the components
+            pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, pLR->nDecs+1, s_nDecBlocks++ );
+            dsdKernelCopyListPlusOne( pThis, pVarCurDE, pLR->pDecs, pLR->nDecs );
+            if ( pL != pLR )
+                pThis = Dsd_Not( pThis );
+        }
+        else // all other cases
+        { // create a new 2-input EXOR-gate
+            pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, 2, s_nDecBlocks++ );
+            if ( pL != pLR ) // complemented
+            {
+                dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pLR, 1 );
+                pThis = Dsd_Not( pThis );
+            }
+            else // non-complemented
+                dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pL, 1 );
+        }
+        goto EXIT;
+    }
+
+    //////////////////////////////////////////////////////////////////////
+    // solve subproblems
+    //////////////////////////////////////////////////////////////////////
+    pL   = dsdKernelDecompose_rec( pDsdMan, bLow );
+    pH   = dsdKernelDecompose_rec( pDsdMan, bHigh );
+    pLR  = Dsd_Regular( pL );
+    pHR  = Dsd_Regular( pH );
+
+    assert( pLR->Type == DSD_NODE_BUF || pLR->Type == DSD_NODE_OR || pLR->Type == DSD_NODE_EXOR || pLR->Type == DSD_NODE_PRIME );
+    assert( pHR->Type == DSD_NODE_BUF || pHR->Type == DSD_NODE_OR || pHR->Type == DSD_NODE_EXOR || pHR->Type == DSD_NODE_PRIME );
+
+/*
+if ( Depth == 1 )
+{
+//  PRK(bLow,pDecTreeTotal->nInputs);
+//  PRK(bHigh,pDecTreeTotal->nInputs);
+if ( s_Show )
+{
+    PRD( pL );
+    PRD( pH );
+}
+}
+*/
+    // compute the new support
+    bTemp    = Cudd_bddAnd( dd, pLR->S, pHR->S );   Cudd_Ref( bTemp );
+    nSuppL   = Extra_bddSuppSize( dd, pLR->S );
+    nSuppH   = Extra_bddSuppSize( dd, pHR->S );
+    nSuppLH  = Extra_bddSuppSize( dd, bTemp );
+    bSuppNew = Cudd_bddAnd( dd, bTemp, bVarCur );   Cudd_Ref( bSuppNew );
+    Cudd_RecursiveDeref( dd, bTemp );
+
+
+    // several possibilities are possible
+    // (1) support of one component contains another
+    // (2) none of the supports is contained in another
+    fContained = dsdKernelCheckContainment( pDsdMan, pLR, pHR, &pLargeR, &pSmallR );
+
+    //////////////////////////////////////////////////////////////////////
+    // CASE 3.b One of the cofactors in a constant (OR and EXOR)
+    //////////////////////////////////////////////////////////////////////
+    // the support of the larger component should contain the support of the smaller
+    // it is possible to have PRIME function in this role
+    // for example: F = ITE( a+b, c(+)d, e+f ), F0 = ITE( b, c(+)d, e+f ), F1 = c(+)d
+    if ( fContained )
+    {
+        Dsd_Node_t * pSmall, * pLarge;
+        int c, iCompLarge = -1; // the number of the component is Large is equal to the whole of Small; suppress "might be used uninitialized"
+        int fLowIsLarge;
+
+        DdNode * bFTemp;     // the changed input function
+        Dsd_Node_t * pDETemp, * pDENew;
+
+        Dsd_Node_t * pComp = NULL;
+        int  nComp = -1; // Suppress "might be used uninitialized"
+
+        if ( pSmallR == pLR )
+        { // Low is Small => High is Large
+            pSmall = pL;
+            pLarge = pH;
+            fLowIsLarge = 0;
+        }
+        else
+        { // vice versa
+            pSmall = pH;
+            pLarge = pL;
+            fLowIsLarge = 1;
+        }
+
+        // treat the situation when the larger is PRIME
+        if ( pLargeR->Type == DSD_NODE_PRIME ) //&& pLargeR->nDecs != pSmallR->nDecs )
+        {
+            // QUESTION: Is it possible for pLargeR->nDecs > 3 
+            // and pSmall contained as one of input in pLarge?
+            // Yes, for example F = a'c + a & MUX(b,c',d) = a'c + abc' + ab'd is non-decomposable
+            // Consider the function H(a->xy) = F( xy, b, c, d )
+            // H0 = H(x=0) = F(0,b,c,d) = c
+            // H1 = F(x=1) = F(y,b,c,d) - non-decomposable
+            //
+            // QUESTION: Is it possible that pLarge is PRIME(3) and pSmall is OR(2),
+            // which is not contained in PRIME as one input?
+            // Yes, for example F = abcd + b'c'd' + a'c'd' = PRIME(ab, c, d)
+            // F(a=0) = c'd' = NOT(OR(a,d))  F(a=1) = bcd + b'c'd' = PRIME(b,c,d)
+            // To find decomposition, we have to prove that F(a=1)|b=0 = F(a=0)
+
+            // Is it possible that (pLargeR->nDecs == pSmallR->nDecs) and yet this case holds?
+            // Yes, consider the function such that F(a=0) = PRIME(a,b+c,d,e) and F(a=1) = OR(b,c,d,e)
+            // They have the same number of inputs and it is possible that they will be the cofactors
+            // as discribed in the previous example.
+
+            // find the component, which when substituted for 0 or 1, produces the desired result
+            int g, fFoundComp = -1; // {0,1} depending on whether setting cofactor to 0 or 1 worked out; suppress "might be used uninitialized"
+
+            DdNode * bLarge, * bSmall;
+            if ( fLowIsLarge )
+            {
+                bLarge = bLow;
+                bSmall = bHigh;
+            }
+            else
+            {
+                bLarge = bHigh;
+                bSmall = bLow;
+            }
+
+            for ( g = 0; g < pLargeR->nDecs; g++ )
+//          if ( g != c )
+            {
+                pDETemp = pLargeR->pDecs[g]; // cannot be complemented
+                if ( Dsd_CheckRootFunctionIdentity( dd, bLarge, bSmall, pDETemp->G, b1 ) )
+                {
+                    fFoundComp = 1;
+                    break;
+                }
+
+                s_Loops1++;
+
+                if ( Dsd_CheckRootFunctionIdentity( dd, bLarge, bSmall, Cudd_Not(pDETemp->G), b1 ) )
+                {
+                    fFoundComp = 0;
+                    break;
+                }
+
+                s_Loops1++;
+            }
+
+            if ( g != pLargeR->nDecs ) 
+            { // decomposition is found
+                if ( fFoundComp )
+                    if ( fLowIsLarge )
+                        bFTemp = Cudd_bddOr( dd, bVarCur, pLargeR->pDecs[g]->G );
+                    else
+                        bFTemp = Cudd_bddOr( dd, Cudd_Not(bVarCur), pLargeR->pDecs[g]->G );
+                else
+                    if ( fLowIsLarge )
+                        bFTemp = Cudd_bddAnd( dd, Cudd_Not(bVarCur), pLargeR->pDecs[g]->G );
+                    else
+                        bFTemp = Cudd_bddAnd( dd, bVarCur, pLargeR->pDecs[g]->G );
+                Cudd_Ref( bFTemp );
+
+                pDENew = dsdKernelDecompose_rec( pDsdMan, bFTemp );
+                pDENew = Dsd_Regular( pDENew );
+                Cudd_RecursiveDeref( dd, bFTemp );
+
+                // get the new gate
+                pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, pLargeR->nDecs, s_nDecBlocks++ );
+                dsdKernelCopyListPlusOneMinusOne( pThis, pDENew, pLargeR->pDecs, pLargeR->nDecs, g );
+                goto EXIT;
+            }
+        }
+
+        // try to find one component in the pLarger that is equal to the whole of pSmaller
+        for ( c = 0; c < pLargeR->nDecs; c++ )
+            if ( pLargeR->pDecs[c] == pSmall || pLargeR->pDecs[c] == Dsd_Not(pSmall) )
+            {
+                iCompLarge = c;
+                break;
+            }
+
+        // assign the equal component
+        if ( c != pLargeR->nDecs )  // the decomposition is possible!
+        { 
+            pComp  = pLargeR->pDecs[iCompLarge];
+            nComp  = 1;
+        }
+        else // the decomposition is still possible
+        { // for example F = OR(ab,c,d), F(a=0) = OR(c,d), F(a=1) = OR(b,c,d)
+            // supp(F0) is contained in supp(F1), Polarity(F(a=0)) == Polarity(F(a=1))
+
+            // try to find a group of common components
+            if ( pLargeR->Type == pSmallR->Type &&
+                (pLargeR->Type == DSD_NODE_EXOR || (pSmallR->Type == DSD_NODE_OR && ((pLarge==pLargeR) == (pSmall==pSmallR)))) )
+            {
+                Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; 
+                int nCommon = dsdKernelFindCommonComponents( pDsdMan, pLargeR, pSmallR, &pCommon, &pLastDiffL, &pLastDiffH );
+                // if all the components of pSmall are contained in pLarge,
+                // then the decomposition exists
+                if ( nCommon == pSmallR->nDecs )
+                {
+                    pComp = pSmallR;
+                    nComp = pSmallR->nDecs;
+                }
+            }
+        }
+
+        if ( pComp ) // the decomposition is possible!
+        {
+//          Dsd_Node_t * pComp  = pLargeR->pDecs[iCompLarge];
+            Dsd_Node_t * pCompR = Dsd_Regular( pComp );
+            int fComp1 = (int)( pLarge != pLargeR );
+            int fComp2 = (int)( pComp  != pCompR );
+            int fComp3 = (int)( pSmall != pSmallR );
+
+            DdNode * bFuncComp;  // the function of the given component
+            DdNode * bFuncNew;   // the function of the input component
+
+            if ( pLargeR->Type == DSD_NODE_OR ) // Figure 4 of Matsunaga's paper
+            { 
+                // the decomposition exists only if the polarity assignment 
+                // along the paths is the same
+                if ( (fComp1 ^ fComp2) == fComp3 )
+                { // decomposition exists = consider 4 cases
+                    // consideration of cases leads to the following conclusion
+                    // fComp1 gives the polarity of the resulting DSD_NODE_OR gate
+                    // fComp2 gives the polarity of the common component feeding into the DSD_NODE_OR gate
+                    //
+                    //                  |  fComp1              pL/  |pS
+                    //                  <> .........<=>....... <>   |
+                    //                  |                     /     |
+                    //                [OR]                  [OR]    | fComp3
+                    //                /  \  fComp2          / | \   |
+                    //              <>    <> .......<=>... /..|..<> | 
+                    //             /        \             /   |    \|
+                    //          [OR]        [C]          S1   S2    C 
+                    //          /  \      .
+                    //        <>    \     .
+                    //       /       \    .
+                    //     [OR]      [x]  .
+                    //     /  \           .
+                    //    S1   S2         .
+                    //
+
+
+                    // at this point we have the function F (bFTemp) and the common component C (bFuncComp)
+                    // to get the remainder, R, in the relationship F = R + C, supp(R) & supp(C) = 0
+                    // we compute the following R = Exist( F - C, supp(C) )
+                    bFTemp = (fComp1)? Cudd_Not( bF ): bF;
+                    bFuncComp = (fComp2)? Cudd_Not( pCompR->G ): pCompR->G;
+                    bFuncNew  = Cudd_bddAndAbstract( dd, bFTemp, Cudd_Not(bFuncComp), pCompR->S ); Cudd_Ref( bFuncNew );
+
+                    // there is no need to copy the dec entry list first, because pComp is a component
+                    // which will not be destroyed by the recursive call to decomposition
+                    pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew );
+                    assert( Dsd_IsComplement(pDENew) ); // follows from the consideration of cases
+                    Cudd_RecursiveDeref( dd, bFuncNew );
+
+                    // get the new gate
+                    if ( nComp == 1 )
+                    {
+                        pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ );
+                        pThis->pDecs[0] = pDENew;
+                        pThis->pDecs[1] = pComp; // takes the complement
+                    }
+                    else
+                    {  // pComp is not complemented
+                        pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, nComp+1, s_nDecBlocks++ );
+                        dsdKernelCopyListPlusOne( pThis, pDENew, pComp->pDecs, nComp );
+                    }
+                    
+                    if ( fComp1 )
+                        pThis = Dsd_Not( pThis );
+                    goto EXIT;
+                }
+            }
+            else if ( pLargeR->Type == DSD_NODE_EXOR ) // Figure 5 of Matsunaga's paper (with correction)
+            { // decomposition always exists = consider 4 cases
+
+                // consideration of cases leads to the following conclusion
+                // fComp3 gives the COMPLEMENT of the polarity of the resulting EXOR gate
+                // (if fComp3 is 0, the EXOR gate is complemented, and vice versa)
+                //
+                //                  |  fComp1              pL/  |pS
+                //                  <> .........<=>....... /....|  fComp3
+                //                  |                     /     |
+                //                [XOR]                [XOR]    |
+                //                /  \  fComp2==0       / | \   |
+                //              /     \                /  |  \  | 
+                //             /        \             /   |    \|
+                //          [OR]        [C]          S1   S2    C 
+                //          /  \     .
+                //        <>    \    .
+                //       /       \   .
+                //    [XOR]      [x] .
+                //     /  \          .
+                //    S1   S2        .
+                //
+
+                assert( fComp2 == 0 );
+                // find the functionality of the lower gates
+                bFTemp = (fComp3)? bF: Cudd_Not( bF );
+                bFuncNew = Cudd_bddXor( dd, bFTemp, pComp->G );   Cudd_Ref( bFuncNew );
+
+                pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew );
+                assert( !Dsd_IsComplement(pDENew) ); // follows from the consideration of cases
+                Cudd_RecursiveDeref( dd, bFuncNew ); 
+
+                // get the new gate
+                if ( nComp == 1 )
+                {
+                    pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, 2, s_nDecBlocks++ );
+                    pThis->pDecs[0] = pDENew;
+                    pThis->pDecs[1] = pComp; 
+                }
+                else
+                {  // pComp is not complemented
+                    pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, nComp+1, s_nDecBlocks++ );
+                    dsdKernelCopyListPlusOne( pThis, pDENew, pComp->pDecs, nComp );
+                }
+
+                if ( !fComp3 )
+                    pThis = Dsd_Not( pThis );
+                goto EXIT;
+            }
+        }
+    }
+
+    // this case was added to fix the trivial bug found November 4, 2002 in Japan
+    // by running the example provided by T. Sasao
+    if ( nSuppLH == nSuppL + nSuppH ) // the supports of the components are disjoint
+    {
+        // create a new component of the type ITE( a, pH, pL )
+        pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, 3, s_nDecBlocks++ );
+        if ( dd->perm[pLR->S->index] < dd->perm[pHR->S->index] ) // pLR is higher in the varible order
+        {
+            pThis->pDecs[1] = pLR;
+            pThis->pDecs[2] = pHR;
+        }
+        else  // pHR is higher in the varible order
+        {
+            pThis->pDecs[1] = pHR;
+            pThis->pDecs[2] = pLR;
+        }
+        // add the first component
+        pThis->pDecs[0] = pVarCurDE;
+        goto EXIT;
+    }
+
+
+    //////////////////////////////////////////////////////////////////////
+    // CASE 3.a Neither of the cofactors is a constant (OR, EXOR, PRIME)
+    //////////////////////////////////////////////////////////////////////
+    // the component types are identical 
+    // and if they are OR, they are either both complemented or both not complemented
+    // and if they are PRIME, their dec numbers should be the same
+    if ( pLR->Type == pHR->Type && 
+         pLR->Type != DSD_NODE_BUF &&           
+        (pLR->Type != DSD_NODE_OR    || ( (pL == pLR && pH == pHR) || (pL != pLR && pH != pHR) ) ) &&
+        (pLR->Type != DSD_NODE_PRIME || pLR->nDecs == pHR->nDecs)  )
+    {
+        // array to store common comps in pL and pH
+        Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; 
+        int nCommon = dsdKernelFindCommonComponents( pDsdMan, pLR, pHR, &pCommon, &pLastDiffL, &pLastDiffH );
+        if ( nCommon )
+        {
+            if ( pLR->Type == DSD_NODE_OR ) // Figure 2 of Matsunaga's paper
+            { // at this point we have the function F and the group of common components C
+                // to get the remainder, R, in the relationship F = R + C, supp(R) & supp(C) = 0
+                // we compute the following R = Exist( F - C, supp(C) )
+
+                // compute the sum total of the common components and the union of their supports
+                DdNode * bCommF, * bCommS, * bFTemp, * bFuncNew;
+                Dsd_Node_t * pDENew;
+
+                dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, &bCommS, 0 );
+                Cudd_Ref( bCommF );
+                Cudd_Ref( bCommS );
+                bFTemp = ( pL != pLR )? Cudd_Not(bF): bF;
+
+                bFuncNew = Cudd_bddAndAbstract( dd, bFTemp, Cudd_Not(bCommF), bCommS ); Cudd_Ref( bFuncNew );
+                Cudd_RecursiveDeref( dd, bCommF );
+                Cudd_RecursiveDeref( dd, bCommS );
+
+                // get the new gate
+
+                // copy the components first, then call the decomposition
+                // because decomposition will distroy the list used for copying
+                pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, nCommon + 1, s_nDecBlocks++ );
+                dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon );
+
+                // call the decomposition recursively
+                pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew );
+//              assert( !Dsd_IsComplement(pDENew) ); // follows from the consideration of cases
+                Cudd_RecursiveDeref( dd, bFuncNew );
+
+                // add the first component
+                pThis->pDecs[0] = pDENew;
+                
+                if ( pL != pLR )
+                    pThis = Dsd_Not( pThis );
+                goto EXIT;
+            }
+            else
+            if ( pLR->Type == DSD_NODE_EXOR ) // Figure 3 of Matsunaga's paper
+            {
+                // compute the sum total of the common components and the union of their supports
+                DdNode * bCommF, * bFuncNew;
+                Dsd_Node_t * pDENew;
+                int fCompExor;
+
+                dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, NULL, 1 );
+                Cudd_Ref( bCommF );
+
+                bFuncNew = Cudd_bddXor( dd, bF, bCommF ); Cudd_Ref( bFuncNew );
+                Cudd_RecursiveDeref( dd, bCommF );
+
+                // get the new gate
+
+                // copy the components first, then call the decomposition
+                // because decomposition will distroy the list used for copying
+                pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, nCommon + 1, s_nDecBlocks++ );
+                dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon );
+
+                // call the decomposition recursively
+                pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew );
+                Cudd_RecursiveDeref( dd, bFuncNew );
+
+                // remember the fact that it was complemented
+                fCompExor = Dsd_IsComplement(pDENew);
+                pDENew = Dsd_Regular(pDENew);
+
+                // add the first component
+                pThis->pDecs[0] = pDENew;
+
+    
+                if ( fCompExor )
+                    pThis = Dsd_Not( pThis );
+                goto EXIT;
+            }
+            else 
+            if ( pLR->Type == DSD_NODE_PRIME && (nCommon == pLR->nDecs-1 || nCommon == pLR->nDecs) )
+            {
+                // for example the function F(a,b,c,d) = ITE(b,c,a(+)d) produces
+                // two cofactors F(a=0) = PRIME(b,c,d) and F(a=1) = PRIME(b,c,d)
+                // with exactly the same list of common components
+
+                Dsd_Node_t * pDENew;
+                DdNode * bFuncNew;
+                int fCompComp = 0;  // this flag can be {0,1,2}
+                // if it is 0 there is no identity
+                // if it is 1/2, the cofactored functions are equal in the direct/complemented polarity
+
+                if ( nCommon == pLR->nDecs )
+                {   // all the components are the same
+                    // find the formal input, in which pLow and pHigh differ (if such input exists)
+                    int m;
+                    Dsd_Node_t * pTempL, * pTempH;
+
+                    s_Common++;
+                    for ( m = 0; m < pLR->nDecs; m++ )
+                    {
+                        pTempL = pLR->pDecs[m]; // cannot be complemented
+                        pTempH = pHR->pDecs[m]; // cannot be complemented
+
+                        if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh,          pTempL->G, Cudd_Not(pTempH->G) ) &&
+                             Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pTempL->G),         pTempH->G ) )
+                        {
+                             pLastDiffL = pTempL;
+                             pLastDiffH = pTempH;
+                             assert( pLastDiffL == pLastDiffH );
+                             fCompComp = 2;
+                             break;
+                        }
+
+                        s_Loops2++;
+                        s_Loops2++;
+/* 
+                        if ( s_Loops2 % 10000  == 0 )
+                        {
+                            int i;
+                            for ( i = 0; i < pLR->nDecs; i++ )
+                                printf( " %d(s=%d)", pLR->pDecs[i]->Type,
+                                    Extra_bddSuppSize(dd, pLR->pDecs[i]->S) );
+                            printf( "\n" );
+                        }
+*/
+
+                    }
+//                    if ( pLR->nDecs == Extra_bddSuppSize(dd, pLR->S) )
+//                        s_Loops2Useless += pLR->nDecs * 2;
+
+                    if ( fCompComp )
+                    { // put the equal components into pCommon, so that they could be copied into the new dec entry
+                        nCommon = 0;
+                        for ( m = 0; m < pLR->nDecs; m++ )
+                            if ( pLR->pDecs[m] != pLastDiffL )
+                                 pCommon[nCommon++] = pLR->pDecs[m];
+                        assert( nCommon = pLR->nDecs-1 );
+                    }
+                }
+                else
+                {  // the differing components are known - check that they have compatible PRIME function
+
+                    s_CommonNo++;
+
+                    // find the numbers of different components
+                    assert( pLastDiffL );
+                    assert( pLastDiffH );
+                    // also, they cannot be complemented, because the decomposition type is PRIME
+
+                    if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pLastDiffL->G), Cudd_Not(pLastDiffH->G) ) &&
+                         Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh,          pLastDiffL->G,           pLastDiffH->G ) )
+                        fCompComp = 1;
+                    else if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh,          pLastDiffL->G, Cudd_Not(pLastDiffH->G) ) &&
+                              Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pLastDiffL->G),         pLastDiffH->G ) )
+                        fCompComp = 2;
+
+                    s_Loops3 += 4;
+                }
+
+                if ( fCompComp )
+                {
+                    if ( fCompComp == 1 ) // it is true that bLow(G=0) == bHigh(H=0) && bLow(G=1) == bHigh(H=1)
+                        bFuncNew = Cudd_bddIte( dd, bVarCur, pLastDiffH->G, pLastDiffL->G ); 
+                    else // it is true that bLow(G=0) == bHigh(H=1) && bLow(G=1) == bHigh(H=0)
+                        bFuncNew = Cudd_bddIte( dd, bVarCur, Cudd_Not(pLastDiffH->G), pLastDiffL->G ); 
+                    Cudd_Ref( bFuncNew );
+
+                    // get the new gate
+
+                    // copy the components first, then call the decomposition
+                    // because decomposition will distroy the list used for copying
+                    pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, pLR->nDecs, s_nDecBlocks++ );
+                    dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon );
+
+                    // create a new component
+                    pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew );
+                    Cudd_RecursiveDeref( dd, bFuncNew );
+                    // the BDD of the argument function in PRIME decomposition, should be regular
+                    pDENew = Dsd_Regular(pDENew);
+
+                    // add the first component
+                    pThis->pDecs[0] = pDENew;
+                    goto EXIT;
+                }
+            } // end of PRIME type
+        } // end of existing common components
+    } // end of CASE 3.a
+
+// if ( Depth != 1) 
+// {
+
+//CASE4:
+    //////////////////////////////////////////////////////////////////////
+    // CASE 4
+    //////////////////////////////////////////////////////////////////////
+    {
+    // estimate the number of entries in the list
+    int nEntriesMax = pDsdMan->nInputs - dd->perm[VarInt];
+
+    // create the new decomposition entry
+    int nEntries = 0;
+
+    DdNode * SuppL, * SuppH, * SuppL_init, * SuppH_init;
+    Dsd_Node_t *pHigher = NULL; // Suppress "might be used uninitialized"
+        Dsd_Node_t *pLower, * pTemp, * pDENew;
+
+
+    int levTopSuppL;
+    int levTopSuppH;
+    int levTop;
+
+    pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, nEntriesMax, s_nDecBlocks++ );
+    pThis->pDecs[ nEntries++ ] = pVarCurDE;
+    // other entries will be added to this list one-by-one during analysis
+
+    // count how many times does it happen that the decomposition entries are
+    s_Case4Calls++;
+ 
+    // consider the simplest case: when the supports are equal 
+    // and at least one of the components
+    // is the PRIME without decompositions, or 
+    // when both of them are without decomposition
+    if ( (((pLR->Type == DSD_NODE_PRIME && nSuppL == pLR->nDecs) || (pHR->Type == DSD_NODE_PRIME && nSuppH == pHR->nDecs)) && pLR->S == pHR->S)  ||
+          ((pLR->Type == DSD_NODE_PRIME && nSuppL == pLR->nDecs) && (pHR->Type == DSD_NODE_PRIME && nSuppH == pHR->nDecs)) )
+    {
+
+         s_Case4CallsSpecial++;
+         // walk through both supports and create the decomposition list composed of simple entries
+         SuppL = pLR->S;
+         SuppH = pHR->S;
+         do
+         {
+             // determine levels
+             levTopSuppL = cuddI(dd,SuppL->index);
+             levTopSuppH = cuddI(dd,SuppH->index);
+
+             // skip the topmost variable in both supports
+             if ( levTopSuppL <= levTopSuppH )
+             {
+                 levTop = levTopSuppL;
+                 SuppL  = cuddT(SuppL);
+             }
+             else
+                 levTop = levTopSuppH;
+
+             if ( levTopSuppH <= levTopSuppL )
+                 SuppH = cuddT(SuppH);
+
+             // set the new decomposition entry
+             pThis->pDecs[ nEntries++ ] = pDsdMan->pInputs[ dd->invperm[levTop] ];
+         }
+         while ( SuppL != b1 || SuppH != b1 );
+    }
+    else
+    {
+
+        // compare two different decomposition lists
+        SuppL_init = pLR->S;
+        SuppH_init = pHR->S;
+        // start references (because these supports will change)
+        SuppL = pLR->S;  Cudd_Ref( SuppL );
+        SuppH = pHR->S;  Cudd_Ref( SuppH );
+        while ( SuppL != b1 || SuppH != b1 )
+        {
+            // determine the top level in cofactors and
+            // whether they have the same top level
+            int TopLevL  = cuddI(dd,SuppL->index);
+            int TopLevH  = cuddI(dd,SuppH->index);
+            int TopLevel = TopLevH;
+            int fEqualLevel = 0;
+
+            DdNode * bVarTop;
+            DdNode * bSuppSubract;
+
+
+            if ( TopLevL < TopLevH )
+            {
+                pHigher = pLR;
+                pLower  = pHR;
+                TopLevel = TopLevL;
+            }
+            else if ( TopLevL > TopLevH )
+            {
+                pHigher = pHR;
+                pLower  = pLR;
+            }
+            else
+                fEqualLevel = 1;
+            assert( TopLevel != CUDD_CONST_INDEX );
+
+
+            // find the currently top variable in the decomposition lists
+            bVarTop = dd->vars[dd->invperm[TopLevel]];
+
+            if ( !fEqualLevel )
+            {
+                // find the lower support
+                DdNode * bSuppLower = (TopLevL < TopLevH)? SuppH_init: SuppL_init; 
+
+                // find the first component in pHigher 
+                // whose support does not overlap with supp(Lower) 
+                // and remember the previous component
+                int fPolarity;          
+                Dsd_Node_t * pPrev = NULL;       // the pointer to the component proceeding pCur
+                Dsd_Node_t * pCur  = pHigher;    // the first component not contained in supp(Lower)
+                while ( Extra_bddSuppOverlapping( dd, pCur->S, bSuppLower ) )
+                {   // get the next component
+                    pPrev = pCur;
+                    pCur  = dsdKernelFindContainingComponent( pDsdMan, pCur, bVarTop, &fPolarity );
+                };
+
+                // look for the possibility to subtract more than one component
+                if ( pPrev == NULL || pPrev->Type == DSD_NODE_PRIME )
+                { // if there is no previous component, or if the previous component is PRIME
+                  // there is no way to subtract more than one component
+
+                    // add the new decomposition entry (it is already regular)
+                    pThis->pDecs[ nEntries++ ] = pCur;
+                    // assign the support to be subtracted from both components
+                    bSuppSubract = pCur->S;
+                }
+                else // all other types
+                {
+                    // go through the decomposition list of pPrev and find components 
+                    // whose support does not overlap with supp(Lower) 
+
+                    static Dsd_Node_t * pNonOverlap[MAXINPUTS];
+                    int i, nNonOverlap = 0;
+                    for ( i = 0; i < pPrev->nDecs; i++ )
+                    {
+                        pTemp = Dsd_Regular( pPrev->pDecs[i] );
+                        if ( !Extra_bddSuppOverlapping( dd, pTemp->S, bSuppLower ) )
+                            pNonOverlap[ nNonOverlap++ ] = pPrev->pDecs[i];
+                    }
+                    assert( nNonOverlap > 0 );
+
+                    if ( nNonOverlap == 1 )
+                    { // one one component was found, which is the original one
+                        assert( Dsd_Regular(pNonOverlap[0]) == pCur);
+                        // add the new decomposition entry
+                        pThis->pDecs[ nEntries++ ] = pCur;
+                        // assign the support to be subtracted from both components
+                        bSuppSubract = pCur->S;
+                    }
+                    else // more than one components was found
+                    {
+                        // find the OR (EXOR) of the non-overlapping components
+                        DdNode * bCommF;
+                        dsdKernelComputeSumOfComponents( pDsdMan, pNonOverlap, nNonOverlap, &bCommF, NULL, (int)(pPrev->Type==DSD_NODE_EXOR) );
+                        Cudd_Ref( bCommF );
+
+                        // create a new gated 
+                        pDENew = dsdKernelDecompose_rec( pDsdMan, bCommF );
+                        Cudd_RecursiveDeref(dd, bCommF);
+                        // make it regular... it must be regular already
+                        assert( !Dsd_IsComplement(pDENew) );
+
+                        // add the new decomposition entry
+                        pThis->pDecs[ nEntries++ ] = pDENew;
+                        // assign the support to be subtracted from both components
+                        bSuppSubract = pDENew->S;
+                    }
+                }
+                
+                // subtract its support from the support of upper component
+                if ( TopLevL < TopLevH )
+                {
+                    SuppL = Cudd_bddExistAbstract( dd, bTemp = SuppL, bSuppSubract ); Cudd_Ref( SuppL );
+                    Cudd_RecursiveDeref(dd, bTemp);
+                }
+                else
+                {
+                    SuppH = Cudd_bddExistAbstract( dd, bTemp = SuppH, bSuppSubract ); Cudd_Ref( SuppH );
+                    Cudd_RecursiveDeref(dd, bTemp);
+                }
+            } // end of if ( !fEqualLevel )
+            else // if ( fEqualLevel ) -- they have the same top level var
+            {
+                static Dsd_Node_t * pMarkedLeft[MAXINPUTS]; // the pointers to the marked blocks
+                static char pMarkedPols[MAXINPUTS]; // polarities of the marked blocks
+                int nMarkedLeft = 0;
+
+                int fPolarity = 0;
+                Dsd_Node_t * pTempL = pLR;
+
+                int fPolarityCurH = 0;
+                Dsd_Node_t * pPrevH = NULL, * pCurH = pHR;
+
+                int fPolarityCurL = 0;
+                Dsd_Node_t * pPrevL = NULL, * pCurL = pLR; // = pMarkedLeft[0];
+                int index = 1;
+
+                // set the new mark
+                s_Mark++;
+
+                // go over the dec list of pL, mark all components that contain the given variable
+                assert( Extra_bddSuppContainVar( dd, pLR->S, bVarTop ) );
+                assert( Extra_bddSuppContainVar( dd, pHR->S, bVarTop ) );
+                do {
+                    pTempL->Mark = s_Mark;
+                    pMarkedLeft[ nMarkedLeft ] = pTempL;
+                    pMarkedPols[ nMarkedLeft ] = fPolarity;
+                    nMarkedLeft++;
+                } while ( (pTempL = dsdKernelFindContainingComponent( pDsdMan, pTempL, bVarTop, &fPolarity )) );
+
+                // go over the dec list of pH, and find the component that is marked and the previos one
+                // (such component always exists, because they have common variables)
+                while ( pCurH->Mark != s_Mark )
+                {
+                    pPrevH = pCurH;
+                    pCurH  = dsdKernelFindContainingComponent( pDsdMan, pCurH, bVarTop, &fPolarityCurH );
+                    assert( pCurH );
+                }
+
+                // go through the first list once again and find 
+                // the component proceeding the one marked found in the second list
+                while ( pCurL != pCurH )
+                {
+                    pPrevL = pCurL;
+                    pCurL  = pMarkedLeft[index];
+                    fPolarityCurL = pMarkedPols[index];
+                    index++;
+                }
+
+                // look for the possibility to subtract more than one component
+                if ( !pPrevL || !pPrevH || pPrevL->Type != pPrevH->Type || pPrevL->Type == DSD_NODE_PRIME || fPolarityCurL != fPolarityCurH )
+                { // there is no way to extract more than one
+                    pThis->pDecs[ nEntries++ ] = pCurH;
+                    // assign the support to be subtracted from both components
+                    bSuppSubract = pCurH->S;
+                }
+                else 
+                {
+                    // find the equal components in two decomposition lists
+                    Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; 
+                    int nCommon = dsdKernelFindCommonComponents( pDsdMan, pPrevL, pPrevH, &pCommon, &pLastDiffL, &pLastDiffH );
+        
+                    if ( nCommon == 0 || nCommon == 1 )
+                    { // one one component was found, which is the original one
+    //                  assert( Dsd_Regular(pCommon[0]) == pCurL);
+                        // add the new decomposition entry
+                        pThis->pDecs[ nEntries++ ] = pCurL;
+                        // assign the support to be subtracted from both components
+                        bSuppSubract = pCurL->S;
+                    }
+                    else // more than one components was found
+                    {
+                        // find the OR (EXOR) of the non-overlapping components
+                        DdNode * bCommF;
+                        dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, NULL, (int)(pPrevL->Type==DSD_NODE_EXOR) );
+                        Cudd_Ref( bCommF );
+
+                        pDENew = dsdKernelDecompose_rec( pDsdMan, bCommF );
+                        assert( !Dsd_IsComplement(pDENew) ); // cannot be complemented because of construction
+                        Cudd_RecursiveDeref( dd, bCommF );
+
+                        // add the new decomposition entry
+                        pThis->pDecs[ nEntries++ ] = pDENew;
+
+                        // assign the support to be subtracted from both components
+                        bSuppSubract = pDENew->S;
+                    }
+                }
+
+                SuppL = Cudd_bddExistAbstract( dd, bTemp = SuppL, bSuppSubract ), Cudd_Ref( SuppL );
+                Cudd_RecursiveDeref(dd, bTemp);
+
+                SuppH = Cudd_bddExistAbstract( dd, bTemp = SuppH, bSuppSubract ), Cudd_Ref( SuppH );
+                Cudd_RecursiveDeref(dd, bTemp);
+
+            } // end of if ( fEqualLevel ) 
+
+        } // end of decomposition list comparison
+        Cudd_RecursiveDeref( dd, SuppL );
+        Cudd_RecursiveDeref( dd, SuppH );
+
+    }
+
+    // check that the estimation of the number of entries was okay
+    assert( nEntries <= nEntriesMax );
+
+//    if ( nEntries != Extra_bddSuppSize(dd, bSuppNew) )
+//        s_Case5++;
+
+    // update the number of entries in the new decomposition list
+    pThis->nDecs = nEntries;
+    }
+//}
+EXIT:
+
+    {
+    // if the component created is complemented, it represents a function without complement
+    // therefore, as it is, without complement, it should recieve the complemented function
+    Dsd_Node_t * pThisR = Dsd_Regular( pThis );
+    assert( pThisR->G == NULL );
+    assert( pThisR->S == NULL );
+
+    if ( pThisR == pThis ) // set regular function
+        pThisR->G = bF; 
+    else // set complemented function
+        pThisR->G = Cudd_Not(bF);    
+    Cudd_Ref(bF);           // reference the function in the component
+
+    assert( bSuppNew );
+    pThisR->S = bSuppNew;   // takes the reference from the new support
+    if ( st__insert( pDsdMan->Table, (char*)bF, (char*)pThis ) )
+    {
+        assert( 0 );
+    }
+    s_CacheEntries++;
+
+
+/*
+    if ( dsdKernelVerifyDecomposition(dd, pThis) == 0 )
+    {
+        // write the function, for which verification does not work
+        cout << endl << "Internal verification failed!"" );
+
+        // create the variable mask
+        static int s_pVarMask[MAXINPUTS];
+        int nInputCounter = 0;
+
+        Cudd_SupportArray( dd, bF, s_pVarMask );
+        int k; 
+        for ( k = 0; k < dd->size; k++ )
+            if ( s_pVarMask[k] )
+                nInputCounter++;
+
+        cout << endl << "The problem function is "" );
+
+        DdNode * zNewFunc = Cudd_zddIsopCover( dd, bF, bF ); Cudd_Ref( zNewFunc );
+        cuddWriteFunctionSop( stdout, dd, zNewFunc, -1, dd->size, "1", s_pVarMask );
+        Cudd_RecursiveDerefZdd( dd, zNewFunc );
+    }
+*/
+
+    }
+
+    Depth--;
+    return Dsd_NotCond( pThis, fCompF );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                        OTHER FUNCTIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the corresponding decomposition entry.]
+
+  Description [This function returns the non-complemented pointer to the 
+  DecEntry of that component which contains the given variable in its 
+  support, or NULL if no such component exists]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dsd_Node_t * dsdKernelFindContainingComponent( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pWhere, DdNode * Var, int * fPolarity )
+
+{
+    Dsd_Node_t * pTemp;
+    int i;
+
+//  assert( !Dsd_IsComplement( pWhere ) );
+//  assert( Extra_bddSuppContainVar( pDsdMan->dd, pWhere->S, Var ) );
+
+    if ( pWhere->nDecs == 1 )
+        return NULL;
+
+    for( i = 0; i < pWhere->nDecs; i++ )
+    {
+        pTemp = Dsd_Regular( pWhere->pDecs[i] );
+        if ( Extra_bddSuppContainVar( pDsdMan->dd, pTemp->S, Var ) )
+        {
+            *fPolarity = (int)( pTemp != pWhere->pDecs[i] );
+            return pTemp;
+        }
+    }
+    assert( 0 );
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the common decomposition components.]
+
+  Description [This function determines the common components. It counts 
+  the number of common components in the decomposition lists of pL and pH
+  and returns their number and the lists of common components. It assumes 
+  that pL and pH are regular pointers. It retuns also the pointers to the 
+  last different components encountered in pL and pH.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int dsdKernelFindCommonComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t *** pCommon, Dsd_Node_t ** pLastDiffL, Dsd_Node_t ** pLastDiffH )
+{
+    static Dsd_Node_t * Common[MAXINPUTS];
+    int nCommon = 0;
+
+    // pointers to the current decomposition entries
+    Dsd_Node_t * pLcur;
+    Dsd_Node_t * pHcur;
+
+    // the pointers to their supports
+    DdNode * bSLcur;
+    DdNode * bSHcur;
+
+    // the top variable in the supports
+    int TopVar;
+
+    // the indices running through the components
+    int iCurL = 0;
+    int iCurH = 0;
+    while ( iCurL < pL->nDecs && iCurH < pH->nDecs )
+    { // both did not run out
+
+        pLcur = Dsd_Regular(pL->pDecs[iCurL]);
+        pHcur = Dsd_Regular(pH->pDecs[iCurH]);
+
+        bSLcur = pLcur->S;
+        bSHcur = pHcur->S;
+
+        // find out what component is higher in the BDD
+        if ( pDsdMan->dd->perm[bSLcur->index] < pDsdMan->dd->perm[bSHcur->index] )
+            TopVar = bSLcur->index;
+        else
+            TopVar = bSHcur->index;
+
+        if ( TopVar == bSLcur->index && TopVar == bSHcur->index ) 
+        {
+            // the components may be equal - should match exactly!
+            if ( pL->pDecs[iCurL] == pH->pDecs[iCurH] )
+                Common[nCommon++] = pL->pDecs[iCurL];
+            else
+            {
+                *pLastDiffL = pL->pDecs[iCurL];
+                *pLastDiffH = pH->pDecs[iCurH];
+            }
+
+            // skip both
+            iCurL++;
+            iCurH++;
+        }
+        else if ( TopVar == bSLcur->index )
+        {  // the components cannot be equal
+            // skip the top-most one
+            *pLastDiffL = pL->pDecs[iCurL++];
+        }
+        else // if ( TopVar == bSHcur->index )
+        {  // the components cannot be equal
+            // skip the top-most one
+            *pLastDiffH = pH->pDecs[iCurH++];
+        }
+    }
+
+    // if one of the lists still has components, write the first one down
+    if ( iCurL < pL->nDecs )
+        *pLastDiffL = pL->pDecs[iCurL];
+
+    if ( iCurH < pH->nDecs )
+        *pLastDiffH = pH->pDecs[iCurH];
+
+    // return the pointer to the array
+    *pCommon = Common;
+    // return the number of common components
+    return nCommon;         
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the sum (OR or EXOR) of the functions of the components.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void dsdKernelComputeSumOfComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t ** pCommon, int nCommon, DdNode ** pCompF, DdNode ** pCompS, int fExor )
+{
+    DdManager * dd = pDsdMan->dd;
+    DdNode * bF, * bFadd, * bTemp;
+        DdNode * bS = NULL; // Suppress "might be used uninitialized"
+    Dsd_Node_t * pDE, * pDER;
+    int i;
+
+    // start the function
+    bF = b0; Cudd_Ref( bF );
+    // start the support
+    if ( pCompS )
+        bS = b1, Cudd_Ref( bS );
+
+    assert( nCommon > 0 );
+    for ( i = 0; i < nCommon; i++ )
+    {
+        pDE  = pCommon[i];
+        pDER = Dsd_Regular( pDE );
+        bFadd = (pDE != pDER)? Cudd_Not(pDER->G): pDER->G;
+        // add to the function
+        if ( fExor )
+            bF = Cudd_bddXor( dd, bTemp = bF, bFadd );
+        else
+            bF = Cudd_bddOr( dd, bTemp = bF, bFadd );
+        Cudd_Ref( bF );
+        Cudd_RecursiveDeref( dd, bTemp );
+        if ( pCompS )
+        {
+            // add to the support
+            bS = Cudd_bddAnd( dd, bTemp = bS, pDER->S );  Cudd_Ref( bS );
+            Cudd_RecursiveDeref( dd, bTemp );
+        }
+    }
+    // return the function
+    Cudd_Deref( bF );
+    *pCompF = bF;
+
+    // return the support
+    if ( pCompS )
+        Cudd_Deref( bS ), *pCompS = bS;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks support containment of the decomposition components.]
+
+  Description [This function returns 1 if support of one component is contained 
+  in that of another. In this case, pLarge (pSmall) is assigned to point to the 
+  larger (smaller) support. If the supports are identical return 0, and does not 
+  assign the components.]
+]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int dsdKernelCheckContainment( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t ** pLarge, Dsd_Node_t ** pSmall )
+{
+    DdManager * dd = pDsdMan->dd;
+    DdNode * bSuppLarge, * bSuppSmall;
+    int RetValue;
+    
+    RetValue = Extra_bddSuppCheckContainment( dd, pL->S, pH->S, &bSuppLarge, &bSuppSmall );
+
+    if ( RetValue == 0 ) 
+        return 0;
+
+    if ( pH->S == bSuppLarge )
+    {
+        *pLarge = pH;
+        *pSmall = pL;
+    }
+    else // if ( pL->S == bSuppLarge )
+    {
+        *pLarge = pL;
+        *pSmall = pH;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Copies the list of components plus one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void dsdKernelCopyListPlusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize )
+{
+    int i;
+    assert( nListSize+1 == p->nDecs );
+    p->pDecs[0] = First;
+    for( i = 0; i < nListSize; i++ )
+        p->pDecs[i+1] = ppList[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Copies the list of components plus one, and skips one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void dsdKernelCopyListPlusOneMinusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize, int iSkipped )
+{
+    int i, Counter;
+    assert( nListSize == p->nDecs );
+    p->pDecs[0] = First;
+    for( i = 0, Counter = 1; i < nListSize; i++ )
+        if ( i != iSkipped )
+            p->pDecs[Counter++] = ppList[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Debugging procedure to compute the functionality of the decomposed structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int dsdKernelVerifyDecomposition( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pDE )
+{
+    DdManager * dd = pDsdMan->dd;
+    Dsd_Node_t * pR    = Dsd_Regular(pDE);
+    int RetValue;
+
+    DdNode * bRes;
+    if ( pR->Type == DSD_NODE_CONST1 )
+        bRes = b1;
+    else if ( pR->Type == DSD_NODE_BUF )
+        bRes = pR->G;
+    else if ( pR->Type == DSD_NODE_OR || pR->Type == DSD_NODE_EXOR )
+        dsdKernelComputeSumOfComponents( pDsdMan, pR->pDecs, pR->nDecs, &bRes, NULL, (int)(pR->Type == DSD_NODE_EXOR) );
+    else if ( pR->Type == DSD_NODE_PRIME )
+    {
+        int i;
+        static DdNode * bGVars[MAXINPUTS];
+        // transform the function of this block, so that it depended on inputs
+        // corresponding to the formal inputs
+        DdNode * bNewFunc = Dsd_TreeGetPrimeFunctionOld( dd, pR, 1 );  Cudd_Ref( bNewFunc );
+
+        // compose this function with the inputs
+        // create the elementary permutation
+        for ( i = 0; i < dd->size; i++ )
+            bGVars[i] = dd->vars[i];
+
+        // assign functions to be composed
+        for ( i = 0; i < pR->nDecs; i++ )
+            bGVars[dd->invperm[i]] = pR->pDecs[i]->G;
+
+        // perform the composition
+        bRes = Cudd_bddVectorCompose( dd, bNewFunc, bGVars );      Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( dd, bNewFunc );
+
+        /////////////////////////////////////////////////////////
+        RetValue = (int)( bRes == pR->G );//|| bRes == Cudd_Not(pR->G) );
+        /////////////////////////////////////////////////////////
+        Cudd_Deref( bRes );
+    }
+    else
+    {
+        assert(0);
+    }
+
+    Cudd_Ref( bRes );
+    RetValue = (int)( bRes == pR->G );//|| bRes == Cudd_Not(pR->G) );
+    Cudd_RecursiveDeref( dd, bRes );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                           END OF FILE                            ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/dsd/dsdTree.c b/abc-build/src/bdd/dsd/dsdTree.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/dsd/dsdTree.c
@@ -0,0 +1,1067 @@
+/**CFile****************************************************************
+
+  FileName    [dsdTree.c]
+
+  PackageName [DSD: Disjoint-support decomposition package.]
+
+  Synopsis    [Managing the decomposition tree.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 8.0. Started - September 22, 2003.]
+
+  Revision    [$Id: dsdTree.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dsdInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+static void Dsd_TreeUnmark_rec( Dsd_Node_t * pNode );
+static void Dsd_TreeGetInfo_rec( Dsd_Node_t * pNode, int RankCur );
+static int  Dsd_TreeCountNonTerminalNodes_rec( Dsd_Node_t * pNode );
+static int  Dsd_TreeCountPrimeNodes_rec( Dsd_Node_t * pNode );
+static int  Dsd_TreeCollectDecomposableVars_rec( DdManager * dd, Dsd_Node_t * pNode, int * pVars, int * nVars );
+static void Dsd_TreeCollectNodesDfs_rec( Dsd_Node_t * pNode, Dsd_Node_t * ppNodes[], int * pnNodes );
+static void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fCcmp, char * pInputNames[], char * pOutputName, int nOffset, int * pSigCounter, int fShortNames );
+static void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOutputName, int nOffset, int * pSigCounter );
+
+////////////////////////////////////////////////////////////////////////
+///                      STATIC VARIABLES                            ///
+////////////////////////////////////////////////////////////////////////
+
+static int s_DepthMax;
+static int s_GateSizeMax;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Create the DSD node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dsd_Node_t * Dsd_TreeNodeCreate( int Type, int nDecs, int BlockNum )
+{
+    // allocate memory for this node 
+    Dsd_Node_t * p = (Dsd_Node_t *) ABC_ALLOC( char, sizeof(Dsd_Node_t) );
+    memset( p, 0, sizeof(Dsd_Node_t) );
+    p->Type       = (Dsd_Type_t)Type;       // the type of this block
+    p->nDecs      = nDecs;                  // the number of decompositions
+    if ( p->nDecs )
+    {
+        p->pDecs      = (Dsd_Node_t **) ABC_ALLOC( char, p->nDecs * sizeof(Dsd_Node_t *) );
+        p->pDecs[0]   = NULL;
+    }
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the DSD node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dsd_TreeNodeDelete( DdManager * dd, Dsd_Node_t * pNode )
+{
+    if ( pNode->G )  Cudd_RecursiveDeref( dd, pNode->G );
+    if ( pNode->S )  Cudd_RecursiveDeref( dd, pNode->S );
+    ABC_FREE( pNode->pDecs );
+    ABC_FREE( pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Unmarks the decomposition tree.]
+
+  Description [This function assumes that originally pNode->nVisits are 
+  set to zero!]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dsd_TreeUnmark( Dsd_Manager_t * pDsdMan )
+{
+    int i;
+    for ( i = 0; i < pDsdMan->nRoots; i++ )
+        Dsd_TreeUnmark_rec( Dsd_Regular( pDsdMan->pRoots[i] ) );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursive unmarking.]
+
+  Description [This function should be called with a non-complemented 
+  pointer.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dsd_TreeUnmark_rec( Dsd_Node_t * pNode )
+{
+    int i;
+
+    assert( pNode );
+    assert( !Dsd_IsComplement( pNode ) );
+    assert( pNode->nVisits > 0 );
+
+    if ( --pNode->nVisits ) // if this is not the last visit, return
+        return;
+
+    // upon the last visit, go through the list of successors and call recursively 
+    if ( pNode->Type != DSD_NODE_BUF && pNode->Type != DSD_NODE_CONST1 )
+    for ( i = 0; i < pNode->nDecs; i++ )
+        Dsd_TreeUnmark_rec( Dsd_Regular(pNode->pDecs[i]) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Getting information about the node.]
+
+  Description [This function computes the max depth and the max gate size 
+  of the tree rooted at the node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dsd_TreeNodeGetInfo( Dsd_Manager_t * pDsdMan, int * DepthMax, int * GateSizeMax )
+{
+    int i;
+    s_DepthMax    = 0;
+    s_GateSizeMax = 0;
+
+    for ( i = 0; i < pDsdMan->nRoots; i++ )
+        Dsd_TreeGetInfo_rec( Dsd_Regular( pDsdMan->pRoots[i] ), 0 );
+
+    if ( DepthMax ) 
+        *DepthMax     = s_DepthMax;
+    if ( GateSizeMax ) 
+        *GateSizeMax  = s_GateSizeMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Getting information about the node.]
+
+  Description [This function computes the max depth and the max gate size 
+  of the tree rooted at the node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dsd_TreeNodeGetInfoOne( Dsd_Node_t * pNode, int * DepthMax, int * GateSizeMax )
+{
+    s_DepthMax    = 0;
+    s_GateSizeMax = 0;
+
+    Dsd_TreeGetInfo_rec( Dsd_Regular(pNode), 0 );
+
+    if ( DepthMax ) 
+        *DepthMax     = s_DepthMax;
+    if ( GateSizeMax ) 
+        *GateSizeMax  = s_GateSizeMax;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs the recursive step of Dsd_TreeNodeGetInfo().]
+
+  Description [pNode is the node, for the tree rooted in which we are 
+  determining info. RankCur is the current rank to assign to the node.
+  fSetRank is the flag saying whether the rank will be written in the 
+  node. s_DepthMax is the maximum depths of the tree. s_GateSizeMax is 
+  the maximum gate size.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dsd_TreeGetInfo_rec( Dsd_Node_t * pNode, int RankCur )
+{
+    int i;
+    int GateSize;
+
+    assert( pNode );
+    assert( !Dsd_IsComplement( pNode ) );
+    assert( pNode->nVisits >= 0 );
+
+    // we don't want the two-input gates to count for non-decomposable blocks
+    if ( pNode->Type == DSD_NODE_OR  || 
+         pNode->Type == DSD_NODE_EXOR )
+        GateSize = 2;
+    else
+        GateSize = pNode->nDecs;
+
+    // update the max size of the node
+    if ( s_GateSizeMax < GateSize )
+         s_GateSizeMax = GateSize;
+
+    if ( pNode->nDecs < 2 )
+        return;
+
+    // update the max rank
+    if ( s_DepthMax < RankCur+1 )
+         s_DepthMax = RankCur+1;
+
+    // call recursively
+    for ( i = 0; i < pNode->nDecs; i++ )
+        Dsd_TreeGetInfo_rec( Dsd_Regular(pNode->pDecs[i]), RankCur+1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts AIG nodes needed to implement this node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dsd_TreeGetAigCost_rec( Dsd_Node_t * pNode )
+{
+    int i, Counter = 0;
+
+    assert( pNode );
+    assert( !Dsd_IsComplement( pNode ) );
+    assert( pNode->nVisits >= 0 );
+
+    if ( pNode->nDecs < 2 )
+        return 0;
+
+    // we don't want the two-input gates to count for non-decomposable blocks
+    if ( pNode->Type == DSD_NODE_OR )
+        Counter += pNode->nDecs - 1;
+    else if ( pNode->Type == DSD_NODE_EXOR )
+        Counter += 3*(pNode->nDecs - 1);
+    else if ( pNode->Type == DSD_NODE_PRIME && pNode->nDecs == 3 )
+        Counter += 3;
+
+    // call recursively
+    for ( i = 0; i < pNode->nDecs; i++ )
+        Counter += Dsd_TreeGetAigCost_rec( Dsd_Regular(pNode->pDecs[i]) );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts AIG nodes needed to implement this node.]
+
+  Description [Assumes that the only primes of the DSD tree are MUXes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dsd_TreeGetAigCost( Dsd_Node_t * pNode )
+{
+    return Dsd_TreeGetAigCost_rec( Dsd_Regular(pNode) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts non-terminal nodes of the DSD tree.]
+
+  Description [Nonterminal nodes include all the nodes with the
+  support more than 1. These are OR, EXOR, and PRIME nodes. They
+  do not include the elementary variable nodes and the constant 1
+  node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dsd_TreeCountNonTerminalNodes( Dsd_Manager_t * pDsdMan )
+{
+    int Counter, i;
+    Counter = 0;
+    for ( i = 0; i < pDsdMan->nRoots; i++ )
+        Counter += Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular( pDsdMan->pRoots[i] ) );
+    Dsd_TreeUnmark( pDsdMan );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dsd_TreeCountNonTerminalNodesOne( Dsd_Node_t * pRoot )
+{
+    int Counter = 0;
+
+    // go through the list of successors and call recursively 
+    Counter = Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular(pRoot) );
+
+    Dsd_TreeUnmark_rec( Dsd_Regular(pRoot) );
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Counts non-terminal nodes for one root.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dsd_TreeCountNonTerminalNodes_rec( Dsd_Node_t * pNode )
+{
+    int i;
+    int Counter = 0;
+
+    assert( pNode );
+    assert( !Dsd_IsComplement( pNode ) );
+    assert( pNode->nVisits >= 0 );
+
+    if ( pNode->nVisits++ ) // if this is not the first visit, return zero
+        return 0;
+
+    if ( pNode->nDecs <= 1 )
+        return 0;
+
+    // upon the first visit, go through the list of successors and call recursively 
+    for ( i = 0; i < pNode->nDecs; i++ )
+        Counter += Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular(pNode->pDecs[i]) );
+
+    return Counter + 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Counts prime nodes of the DSD tree.]
+
+  Description [Prime nodes are nodes with the support more than 2,
+  that is not an OR or EXOR gate.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dsd_TreeCountPrimeNodes( Dsd_Manager_t * pDsdMan )
+{
+    int Counter, i;
+    Counter = 0;
+    for ( i = 0; i < pDsdMan->nRoots; i++ )
+        Counter += Dsd_TreeCountPrimeNodes_rec( Dsd_Regular( pDsdMan->pRoots[i] ) );
+    Dsd_TreeUnmark( pDsdMan );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts prime nodes for one root.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dsd_TreeCountPrimeNodesOne( Dsd_Node_t * pRoot )
+{
+    int Counter = 0;
+
+    // go through the list of successors and call recursively 
+    Counter = Dsd_TreeCountPrimeNodes_rec( Dsd_Regular(pRoot) );
+
+    Dsd_TreeUnmark_rec( Dsd_Regular(pRoot) );
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dsd_TreeCountPrimeNodes_rec( Dsd_Node_t * pNode )
+{
+    int i;
+    int Counter = 0;
+
+    assert( pNode );
+    assert( !Dsd_IsComplement( pNode ) );
+    assert( pNode->nVisits >= 0 );
+
+    if ( pNode->nVisits++ ) // if this is not the first visit, return zero
+        return 0;
+
+    if ( pNode->nDecs <= 1 )
+        return 0;
+
+    // upon the first visit, go through the list of successors and call recursively 
+    for ( i = 0; i < pNode->nDecs; i++ )
+        Counter += Dsd_TreeCountPrimeNodes_rec( Dsd_Regular(pNode->pDecs[i]) );
+
+    if ( pNode->Type == DSD_NODE_PRIME )
+        Counter++;
+
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the decomposable vars on the PI side.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dsd_TreeCollectDecomposableVars( Dsd_Manager_t * pDsdMan, int * pVars )
+{
+    int nVars;
+
+    // set the vars collected to 0
+    nVars = 0;
+    Dsd_TreeCollectDecomposableVars_rec( pDsdMan->dd, Dsd_Regular(pDsdMan->pRoots[0]), pVars, &nVars );
+    // return the number of collected vars
+    return nVars;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements the recursive part of Dsd_TreeCollectDecomposableVars().]
+
+  Description [Adds decomposable variables as they are found to pVars and increments 
+  nVars. Returns 1 if a non-dec node with more than 4 inputs was encountered 
+  in the processed subtree. Returns 0, otherwise. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dsd_TreeCollectDecomposableVars_rec( DdManager * dd, Dsd_Node_t * pNode, int * pVars, int * nVars )
+{
+    int fSkipThisNode, i;
+    Dsd_Node_t * pTemp;
+    int fVerbose = 0;
+
+    assert( pNode );
+    assert( !Dsd_IsComplement( pNode ) );
+
+    if ( pNode->nDecs <= 1 )
+        return 0;
+
+    // go through the list of successors and call recursively 
+    fSkipThisNode = 0;
+    for ( i = 0; i < pNode->nDecs; i++ )
+        if ( Dsd_TreeCollectDecomposableVars_rec(dd, Dsd_Regular(pNode->pDecs[i]), pVars, nVars) )
+            fSkipThisNode = 1;
+
+    if ( !fSkipThisNode && (pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR || pNode->nDecs <= 4) )
+    {
+if ( fVerbose )
+printf( "Node of type <%d> (OR=6,EXOR=8,RAND=1): ", pNode->Type );
+
+        for ( i = 0; i < pNode->nDecs; i++ )
+        {
+            pTemp = Dsd_Regular(pNode->pDecs[i]);
+            if ( pTemp->Type == DSD_NODE_BUF )
+            {
+                if ( pVars )
+                    pVars[ (*nVars)++ ] = pTemp->S->index;
+                else
+                    (*nVars)++;
+                    
+if ( fVerbose )
+printf( "%d ", pTemp->S->index );
+            }
+        }
+if ( fVerbose )
+printf( "\n" );
+    }
+    else
+        fSkipThisNode = 1;
+
+
+    return fSkipThisNode;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the DFS ordered array of DSD nodes in the tree.]
+
+  Description [The collected nodes do not include the terminal nodes
+  and the constant 1 node. The array of nodes is returned. The number
+  of entries in the array is returned in the variale pnNodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dsd_Node_t ** Dsd_TreeCollectNodesDfs( Dsd_Manager_t * pDsdMan, int * pnNodes )
+{
+    Dsd_Node_t ** ppNodes;
+    int nNodes, nNodesAlloc;
+    int i;
+
+    nNodesAlloc = Dsd_TreeCountNonTerminalNodes(pDsdMan);
+    nNodes  = 0;
+    ppNodes = ABC_ALLOC( Dsd_Node_t *, nNodesAlloc );
+    for ( i = 0; i < pDsdMan->nRoots; i++ )
+        Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pDsdMan->pRoots[i]), ppNodes, &nNodes );
+    Dsd_TreeUnmark( pDsdMan );
+    assert( nNodesAlloc == nNodes );
+    *pnNodes = nNodes;
+    return ppNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the DFS ordered array of DSD nodes in the tree.]
+
+  Description [The collected nodes do not include the terminal nodes
+  and the constant 1 node. The array of nodes is returned. The number
+  of entries in the array is returned in the variale pnNodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dsd_Node_t ** Dsd_TreeCollectNodesDfsOne( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pNode, int * pnNodes )
+{
+    Dsd_Node_t ** ppNodes;
+    int nNodes, nNodesAlloc;
+    nNodesAlloc = Dsd_TreeCountNonTerminalNodesOne(pNode);
+    nNodes  = 0;
+    ppNodes = ABC_ALLOC( Dsd_Node_t *, nNodesAlloc );
+    Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pNode), ppNodes, &nNodes );
+    Dsd_TreeUnmark_rec(Dsd_Regular(pNode));
+    assert( nNodesAlloc == nNodes );
+    *pnNodes = nNodes;
+    return ppNodes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dsd_TreeCollectNodesDfs_rec( Dsd_Node_t * pNode, Dsd_Node_t * ppNodes[], int * pnNodes )
+{
+    int i;
+    assert( pNode );
+    assert( !Dsd_IsComplement(pNode) );
+    assert( pNode->nVisits >= 0 );
+
+    if ( pNode->nVisits++ ) // if this is not the first visit, return zero
+        return;
+    if ( pNode->nDecs <= 1 )
+        return;
+
+    // upon the first visit, go through the list of successors and call recursively 
+    for ( i = 0; i < pNode->nDecs; i++ )
+        Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pNode->pDecs[i]), ppNodes, pnNodes );
+
+    ppNodes[ (*pnNodes)++ ] = pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the decompostion tree into file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * pDsdMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output )
+{
+    Dsd_Node_t * pNode;
+    int SigCounter;
+    int i;
+    SigCounter = 1;
+
+    if ( Output == -1 )
+    {
+        for ( i = 0; i < pDsdMan->nRoots; i++ )
+        {
+            pNode = Dsd_Regular( pDsdMan->pRoots[i] );
+            Dsd_TreePrint_rec( pFile, pNode, (pNode != pDsdMan->pRoots[i]), pInputNames, pOutputNames[i], 0, &SigCounter, fShortNames );
+        }
+    }
+    else
+    {
+        assert( Output >= 0 && Output < pDsdMan->nRoots );
+        pNode = Dsd_Regular( pDsdMan->pRoots[Output] );
+        Dsd_TreePrint_rec( pFile, pNode, (pNode != pDsdMan->pRoots[Output]), pInputNames, pOutputNames[Output], 0, &SigCounter, fShortNames );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the decompostion tree into file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInputNames[], char * pOutputName, int nOffset, int * pSigCounter, int fShortNames )
+{
+    char Buffer[100];
+    Dsd_Node_t * pInput;
+    int * pInputNums;
+    int fCompNew, i;
+
+    assert( pNode->Type == DSD_NODE_BUF || pNode->Type == DSD_NODE_CONST1 || 
+        pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR ); 
+
+    Extra_PrintSymbols( pFile, ' ', nOffset, 0 );
+    if ( !fComp )
+        fprintf( pFile, "%s = ", pOutputName );
+    else
+        fprintf( pFile, "NOT(%s) = ", pOutputName );
+    pInputNums = ABC_ALLOC( int, pNode->nDecs );
+    if ( pNode->Type == DSD_NODE_CONST1 )
+    {
+        fprintf( pFile, " Constant 1.\n" );
+    }
+    else if ( pNode->Type == DSD_NODE_BUF )
+    {
+        if ( fShortNames )
+            fprintf( pFile, "%d", 'a' + pNode->S->index );
+        else
+            fprintf( pFile, "%s", pInputNames[pNode->S->index] );
+        fprintf( pFile, "\n" );
+    }
+    else if ( pNode->Type == DSD_NODE_PRIME )
+    {
+        // print the line
+        fprintf( pFile, "PRIME(" );
+        for ( i = 0; i < pNode->nDecs; i++ )
+        {
+            pInput   = Dsd_Regular( pNode->pDecs[i] );
+            fCompNew = (int)( pInput != pNode->pDecs[i] );
+            if ( i )
+                fprintf( pFile, "," );
+            if ( fCompNew )
+                fprintf( pFile, " NOT(" );
+            else
+                fprintf( pFile, " " );
+            if ( pInput->Type == DSD_NODE_BUF )
+            {
+                pInputNums[i] = 0;
+                if ( fShortNames )
+                    fprintf( pFile, "%d", pInput->S->index );
+                else
+                    fprintf( pFile, "%s", pInputNames[pInput->S->index] );
+            }
+            else
+            {
+                pInputNums[i] = (*pSigCounter)++;
+                fprintf( pFile, "<%d>", pInputNums[i] );
+            }
+            if ( fCompNew )
+                fprintf( pFile, ")" );
+        }
+        fprintf( pFile, " )\n" );
+        // call recursively for the following blocks
+        for ( i = 0; i < pNode->nDecs; i++ )
+            if ( pInputNums[i] )
+            {
+                pInput   = Dsd_Regular( pNode->pDecs[i] );
+                sprintf( Buffer, "<%d>", pInputNums[i] );
+                Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames );
+            }
+    }
+    else if ( pNode->Type == DSD_NODE_OR )
+    {
+        // print the line
+        fprintf( pFile, "OR(" );
+        for ( i = 0; i < pNode->nDecs; i++ )
+        {
+            pInput = Dsd_Regular( pNode->pDecs[i] );
+            fCompNew  = (int)( pInput != pNode->pDecs[i] );
+            if ( i )
+                fprintf( pFile, "," );
+            if ( fCompNew )
+                fprintf( pFile, " NOT(" );
+            else
+                fprintf( pFile, " " );
+            if ( pInput->Type == DSD_NODE_BUF )
+            {
+                pInputNums[i] = 0;
+                if ( fShortNames )
+                    fprintf( pFile, "%c", 'a' + pInput->S->index );
+                else
+                    fprintf( pFile, "%s", pInputNames[pInput->S->index] );
+            }
+            else
+            {
+                pInputNums[i] = (*pSigCounter)++;
+                fprintf( pFile, "<%d>", pInputNums[i] );
+            }
+            if ( fCompNew )
+                fprintf( pFile, ")" );
+        }
+        fprintf( pFile, " )\n" );
+        // call recursively for the following blocks
+        for ( i = 0; i < pNode->nDecs; i++ )
+            if ( pInputNums[i] )
+            {
+                pInput = Dsd_Regular( pNode->pDecs[i] );
+                sprintf( Buffer, "<%d>", pInputNums[i] );
+                Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames );
+            }
+    }
+    else if ( pNode->Type == DSD_NODE_EXOR )
+    {
+        // print the line
+        fprintf( pFile, "EXOR(" );
+        for ( i = 0; i < pNode->nDecs; i++ )
+        {
+            pInput = Dsd_Regular( pNode->pDecs[i] );
+            fCompNew  = (int)( pInput != pNode->pDecs[i] );
+            if ( i )
+                fprintf( pFile, "," );
+            if ( fCompNew )
+                fprintf( pFile, " NOT(" );
+            else
+                fprintf( pFile, " " );
+            if ( pInput->Type == DSD_NODE_BUF )
+            {
+                pInputNums[i] = 0;
+                if ( fShortNames )
+                    fprintf( pFile, "%c", 'a' + pInput->S->index );
+                else
+                    fprintf( pFile, "%s", pInputNames[pInput->S->index] );
+            }
+            else
+            {
+                pInputNums[i] = (*pSigCounter)++;
+                fprintf( pFile, "<%d>", pInputNums[i] );
+            }
+            if ( fCompNew )
+                fprintf( pFile, ")" );
+        }
+        fprintf( pFile, " )\n" );
+        // call recursively for the following blocks
+        for ( i = 0; i < pNode->nDecs; i++ )
+            if ( pInputNums[i] )
+            {
+                pInput = Dsd_Regular( pNode->pDecs[i] );
+                sprintf( Buffer, "<%d>", pInputNums[i] );
+                Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames );
+            }
+    }
+    ABC_FREE( pInputNums );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the decompostion tree into file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode )
+{
+    Dsd_Node_t * pNodeR;
+    int SigCounter = 1;
+    pNodeR = Dsd_Regular(pNode);
+    Dsd_NodePrint_rec( pFile, pNodeR, pNodeR != pNode, "F", 0, &SigCounter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints one node of the decomposition tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOutputName, int nOffset, int * pSigCounter )
+{
+    char Buffer[100];
+    Dsd_Node_t * pInput;
+    int * pInputNums;
+    int fCompNew, i;
+
+    assert( pNode->Type == DSD_NODE_BUF || pNode->Type == DSD_NODE_CONST1 || 
+        pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR ); 
+
+    Extra_PrintSymbols( pFile, ' ', nOffset, 0 );
+    if ( !fComp )
+        fprintf( pFile, "%s = ", pOutputName );
+    else
+        fprintf( pFile, "NOT(%s) = ", pOutputName );
+    pInputNums = ABC_ALLOC( int, pNode->nDecs );
+    if ( pNode->Type == DSD_NODE_CONST1 )
+    {
+        fprintf( pFile, " Constant 1.\n" );
+    }
+    else if ( pNode->Type == DSD_NODE_BUF )
+    {
+        fprintf( pFile, " " );
+        fprintf( pFile, "%c", 'a' + pNode->S->index );
+        fprintf( pFile, "\n" );
+    }
+    else if ( pNode->Type == DSD_NODE_PRIME )
+    {
+        // print the line
+        fprintf( pFile, "PRIME(" );
+        for ( i = 0; i < pNode->nDecs; i++ )
+        {
+            pInput   = Dsd_Regular( pNode->pDecs[i] );
+            fCompNew = (int)( pInput != pNode->pDecs[i] );
+            assert( fCompNew == 0 );
+            if ( i )
+                fprintf( pFile, "," );
+            if ( pInput->Type == DSD_NODE_BUF )
+            {
+                pInputNums[i] = 0;
+                fprintf( pFile, " %c", 'a' + pInput->S->index );
+            }
+            else
+            {
+                pInputNums[i] = (*pSigCounter)++;
+                fprintf( pFile, " <%d>", pInputNums[i] );
+            }
+            if ( fCompNew )
+                fprintf( pFile, "\'" );
+        }
+        fprintf( pFile, " )\n" );
+/*
+        fprintf( pFile, " )  " );  
+        {
+            DdNode * bLocal;
+            bLocal = Dsd_TreeGetPrimeFunction( dd, pNodeDsd );  Cudd_Ref( bLocal );
+            Extra_bddPrint( dd, bLocal );
+            Cudd_RecursiveDeref( dd, bLocal );
+        }
+*/
+        // call recursively for the following blocks
+        for ( i = 0; i < pNode->nDecs; i++ )
+            if ( pInputNums[i] )
+            {
+                pInput   = Dsd_Regular( pNode->pDecs[i] );
+                sprintf( Buffer, "<%d>", pInputNums[i] );
+                Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter );
+            }
+    }
+    else if ( pNode->Type == DSD_NODE_OR )
+    {
+        // print the line
+        fprintf( pFile, "OR(" );
+        for ( i = 0; i < pNode->nDecs; i++ )
+        {
+            pInput = Dsd_Regular( pNode->pDecs[i] );
+            fCompNew  = (int)( pInput != pNode->pDecs[i] );
+            if ( i )
+                fprintf( pFile, "," );
+            if ( pInput->Type == DSD_NODE_BUF )
+            {
+                pInputNums[i] = 0;
+                fprintf( pFile, " %c", 'a' + pInput->S->index );
+            }
+            else
+            {
+                pInputNums[i] = (*pSigCounter)++;
+                fprintf( pFile, " <%d>", pInputNums[i] );
+            }
+            if ( fCompNew )
+                fprintf( pFile, "\'" );
+        }
+        fprintf( pFile, " )\n" );
+        // call recursively for the following blocks
+        for ( i = 0; i < pNode->nDecs; i++ )
+            if ( pInputNums[i] )
+            {
+                pInput = Dsd_Regular( pNode->pDecs[i] );
+                sprintf( Buffer, "<%d>", pInputNums[i] );
+                Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter );
+            }
+    }
+    else if ( pNode->Type == DSD_NODE_EXOR )
+    {
+        // print the line
+        fprintf( pFile, "EXOR(" );
+        for ( i = 0; i < pNode->nDecs; i++ )
+        {
+            pInput = Dsd_Regular( pNode->pDecs[i] );
+            fCompNew  = (int)( pInput != pNode->pDecs[i] );
+            assert( fCompNew == 0 );
+            if ( i )
+                fprintf( pFile, "," );
+            if ( pInput->Type == DSD_NODE_BUF )
+            {
+                pInputNums[i] = 0;
+                fprintf( pFile, " %c", 'a' + pInput->S->index );
+            }
+            else
+            {
+                pInputNums[i] = (*pSigCounter)++;
+                fprintf( pFile, " <%d>", pInputNums[i] );
+            }
+            if ( fCompNew )
+                fprintf( pFile, "\'" );
+        }
+        fprintf( pFile, " )\n" );
+        // call recursively for the following blocks
+        for ( i = 0; i < pNode->nDecs; i++ )
+            if ( pInputNums[i] )
+            {
+                pInput = Dsd_Regular( pNode->pDecs[i] );
+                sprintf( Buffer, "<%d>", pInputNums[i] );
+                Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter );
+            }
+    }
+    ABC_FREE( pInputNums );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Retuns the function of one node of the decomposition tree.]
+
+  Description [This is the old procedure. It is now superceded by the
+  procedure Dsd_TreeGetPrimeFunction() found in "dsdLocal.c".]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Dsd_TreeGetPrimeFunctionOld( DdManager * dd, Dsd_Node_t * pNode, int fRemap ) 
+{
+    DdNode * bCof0,  * bCof1, * bCube0, * bCube1, * bNewFunc, * bTemp;
+    int i;
+    static int Permute[MAXINPUTS];
+
+    assert( pNode );
+    assert( !Dsd_IsComplement( pNode ) );
+    assert( pNode->Type == DSD_NODE_PRIME );
+
+    // transform the function of this block to depend on inputs
+    // corresponding to the formal inputs
+
+    // first, substitute those inputs that have some blocks associated with them
+    // second, remap the inputs to the top of the manager (then, it is easy to output them)
+
+    // start the function
+    bNewFunc = pNode->G;  Cudd_Ref( bNewFunc );
+    // go over all primary inputs
+    for ( i = 0; i < pNode->nDecs; i++ )
+    if ( pNode->pDecs[i]->Type != DSD_NODE_BUF ) // remap only if it is not the buffer
+    {
+        bCube0 = Extra_bddFindOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) );  Cudd_Ref( bCube0 );
+        bCof0 = Cudd_Cofactor( dd, bNewFunc, bCube0 );                     Cudd_Ref( bCof0 );
+        Cudd_RecursiveDeref( dd, bCube0 );
+
+        bCube1 = Extra_bddFindOneCube( dd,          pNode->pDecs[i]->G  );  Cudd_Ref( bCube1 );
+        bCof1 = Cudd_Cofactor( dd, bNewFunc, bCube1 );                     Cudd_Ref( bCof1 );
+        Cudd_RecursiveDeref( dd, bCube1 );
+
+        Cudd_RecursiveDeref( dd, bNewFunc );
+
+        // use the variable in the i-th level of the manager
+//      bNewFunc = Cudd_bddIte( dd, dd->vars[dd->invperm[i]],bCof1,bCof0 );     Cudd_Ref( bNewFunc );
+        // use the first variale in the support of the component
+        bNewFunc = Cudd_bddIte( dd, dd->vars[pNode->pDecs[i]->S->index],bCof1,bCof0 );     Cudd_Ref( bNewFunc );
+        Cudd_RecursiveDeref( dd, bCof0 );
+        Cudd_RecursiveDeref( dd, bCof1 );
+    }
+
+    if ( fRemap )
+    {
+        // remap the function to the top of the manager
+        // remap the function to the first variables of the manager
+        for ( i = 0; i < pNode->nDecs; i++ )
+    //      Permute[ pNode->pDecs[i]->S->index ] = dd->invperm[i];
+            Permute[ pNode->pDecs[i]->S->index ] = i;
+
+        bNewFunc = Cudd_bddPermute( dd, bTemp = bNewFunc, Permute );   Cudd_Ref( bNewFunc );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+
+    Cudd_Deref( bNewFunc );
+    return bNewFunc;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                           END OF FILE                            ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/dsd/module.make b/abc-build/src/bdd/dsd/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/dsd/module.make
@@ -0,0 +1,6 @@
+SRC +=	src/bdd/dsd/dsdApi.c \
+	src/bdd/dsd/dsdCheck.c \
+	src/bdd/dsd/dsdLocal.c \
+	src/bdd/dsd/dsdMan.c \
+	src/bdd/dsd/dsdProc.c \
+	src/bdd/dsd/dsdTree.c
diff --git a/abc-build/src/bdd/epd/epd.c b/abc-build/src/bdd/epd/epd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/epd/epd.c
@@ -0,0 +1,1347 @@
+/**CFile***********************************************************************
+
+  FileName    [epd.c]
+
+  PackageName [epd]
+
+  Synopsis    [Arithmetic functions with extended double precision.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+  Revision    [$Id: epd.c,v 1.10 2004/08/13 18:20:30 fabio Exp $]
+
+******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "misc/util/util_hack.h"
+#include "epd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates an EpDouble struct.]
+
+  Description [Allocates an EpDouble struct.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+EpDouble *
+EpdAlloc(void)
+{
+  EpDouble      *epd;
+
+  epd = ABC_ALLOC(EpDouble, 1);
+  return(epd);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two EpDouble struct.]
+
+  Description [Compares two EpDouble struct.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+EpdCmp(const char *key1, const char *key2)
+{
+  EpDouble *epd1 = (EpDouble *) key1;
+  EpDouble *epd2 = (EpDouble *) key2;
+  if (epd1->type.value != epd2->type.value ||
+      epd1->exponent != epd2->exponent) {
+    return(1);
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees an EpDouble struct.]
+
+  Description [Frees an EpDouble struct.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdFree(EpDouble *epd)
+{
+  ABC_FREE(epd);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts an arbitrary precision double value to a string.]
+
+  Description [Converts an arbitrary precision double value to a string.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdGetString(EpDouble *epd, char *str)
+{
+  double        value;
+  int           exponent;
+  char          *pos;
+
+  if (IsNanDouble(epd->type.value)) {
+    sprintf(str, "NaN");
+    return;
+  } else if (IsInfDouble(epd->type.value)) {
+    if (epd->type.bits.sign == 1)
+      sprintf(str, "-Inf");
+    else
+      sprintf(str, "Inf");
+    return;
+  }
+
+  assert(epd->type.bits.exponent == EPD_MAX_BIN ||
+         epd->type.bits.exponent == 0);
+
+  EpdGetValueAndDecimalExponent(epd, &value, &exponent);
+  sprintf(str, "%e", value);
+  pos = strstr(str, "e");
+  if (exponent >= 0) {
+    if (exponent < 10)
+      sprintf(pos + 1, "+0%d", exponent);
+    else
+      sprintf(pos + 1, "+%d", exponent);
+  } else {
+    exponent *= -1;
+    if (exponent < 10)
+      sprintf(pos + 1, "-0%d", exponent);
+    else
+      sprintf(pos + 1, "-%d", exponent);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts double to EpDouble struct.]
+
+  Description [Converts double to EpDouble struct.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdConvert(double value, EpDouble *epd)
+{
+  epd->type.value = value;
+  epd->exponent = 0;
+  EpdNormalize(epd);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Multiplies two arbitrary precision double values.]
+
+  Description [Multiplies two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdMultiply(EpDouble *epd1, double value)
+{
+  EpDouble      epd2;
+  double        tmp;
+  int           exponent;
+
+  if (EpdIsNan(epd1) || IsNanDouble(value)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || IsInfDouble(value)) {
+    int sign;
+
+    EpdConvert(value, &epd2);
+    sign = epd1->type.bits.sign ^ epd2.type.bits.sign;
+    EpdMakeInf(epd1, sign);
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+
+  EpdConvert(value, &epd2);
+  tmp = epd1->type.value * epd2.type.value;
+  exponent = epd1->exponent + epd2.exponent;
+  epd1->type.value = tmp;
+  epd1->exponent = exponent;
+  EpdNormalize(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Multiplies two arbitrary precision double values.]
+
+  Description [Multiplies two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdMultiply2(EpDouble *epd1, EpDouble *epd2)
+{
+  double        value;
+  int           exponent;
+
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int sign;
+
+    sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+    EpdMakeInf(epd1, sign);
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+  assert(epd2->type.bits.exponent == EPD_MAX_BIN);
+
+  value = epd1->type.value * epd2->type.value;
+  exponent = epd1->exponent + epd2->exponent;
+  epd1->type.value = value;
+  epd1->exponent = exponent;
+  EpdNormalize(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Multiplies two arbitrary precision double values.]
+
+  Description [Multiplies two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdMultiply2Decimal(EpDouble *epd1, EpDouble *epd2)
+{
+  double        value;
+  int           exponent;
+
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int sign;
+
+    sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+    EpdMakeInf(epd1, sign);
+    return;
+  }
+
+  value = epd1->type.value * epd2->type.value;
+  exponent = epd1->exponent + epd2->exponent;
+  epd1->type.value = value;
+  epd1->exponent = exponent;
+  EpdNormalizeDecimal(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Multiplies two arbitrary precision double values.]
+
+  Description [Multiplies two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdMultiply3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3)
+{
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int sign;
+
+    sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+    EpdMakeInf(epd3, sign);
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+  assert(epd2->type.bits.exponent == EPD_MAX_BIN);
+
+  epd3->type.value = epd1->type.value * epd2->type.value;
+  epd3->exponent = epd1->exponent + epd2->exponent;
+  EpdNormalize(epd3);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Multiplies two arbitrary precision double values.]
+
+  Description [Multiplies two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdMultiply3Decimal(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3)
+{
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int sign;
+
+    sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+    EpdMakeInf(epd3, sign);
+    return;
+  }
+
+  epd3->type.value = epd1->type.value * epd2->type.value;
+  epd3->exponent = epd1->exponent + epd2->exponent;
+  EpdNormalizeDecimal(epd3);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Divides two arbitrary precision double values.]
+
+  Description [Divides two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdDivide(EpDouble *epd1, double value)
+{
+  EpDouble      epd2;
+  double        tmp;
+  int           exponent;
+
+  if (EpdIsNan(epd1) || IsNanDouble(value)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || IsInfDouble(value)) {
+    int sign;
+
+    EpdConvert(value, &epd2);
+    if (EpdIsInf(epd1) && IsInfDouble(value)) {
+      EpdMakeNan(epd1);
+    } else if (EpdIsInf(epd1)) {
+      sign = epd1->type.bits.sign ^ epd2.type.bits.sign;
+      EpdMakeInf(epd1, sign);
+    } else {
+      sign = epd1->type.bits.sign ^ epd2.type.bits.sign;
+      EpdMakeZero(epd1, sign);
+    }
+    return;
+  }
+
+  if (value == 0.0) {
+    EpdMakeNan(epd1);
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+
+  EpdConvert(value, &epd2);
+  tmp = epd1->type.value / epd2.type.value;
+  exponent = epd1->exponent - epd2.exponent;
+  epd1->type.value = tmp;
+  epd1->exponent = exponent;
+  EpdNormalize(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Divides two arbitrary precision double values.]
+
+  Description [Divides two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdDivide2(EpDouble *epd1, EpDouble *epd2)
+{
+  double        value;
+  int           exponent;
+
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int sign;
+
+    if (EpdIsInf(epd1) && EpdIsInf(epd2)) {
+      EpdMakeNan(epd1);
+    } else if (EpdIsInf(epd1)) {
+      sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+      EpdMakeInf(epd1, sign);
+    } else {
+      sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+      EpdMakeZero(epd1, sign);
+    }
+    return;
+  }
+
+  if (epd2->type.value == 0.0) {
+    EpdMakeNan(epd1);
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+  assert(epd2->type.bits.exponent == EPD_MAX_BIN);
+
+  value = epd1->type.value / epd2->type.value;
+  exponent = epd1->exponent - epd2->exponent;
+  epd1->type.value = value;
+  epd1->exponent = exponent;
+  EpdNormalize(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Divides two arbitrary precision double values.]
+
+  Description [Divides two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdDivide3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3)
+{
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd3);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int sign;
+
+    if (EpdIsInf(epd1) && EpdIsInf(epd2)) {
+      EpdMakeNan(epd3);
+    } else if (EpdIsInf(epd1)) {
+      sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+      EpdMakeInf(epd3, sign);
+    } else {
+      sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+      EpdMakeZero(epd3, sign);
+    }
+    return;
+  }
+
+  if (epd2->type.value == 0.0) {
+    EpdMakeNan(epd3);
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+  assert(epd2->type.bits.exponent == EPD_MAX_BIN);
+
+  epd3->type.value = epd1->type.value / epd2->type.value;
+  epd3->exponent = epd1->exponent - epd2->exponent;
+  EpdNormalize(epd3);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds two arbitrary precision double values.]
+
+  Description [Adds two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdAdd(EpDouble *epd1, double value)
+{
+  EpDouble      epd2;
+  double        tmp;
+  int           exponent, diff;
+
+  if (EpdIsNan(epd1) || IsNanDouble(value)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || IsInfDouble(value)) {
+    int sign;
+
+    EpdConvert(value, &epd2);
+    if (EpdIsInf(epd1) && IsInfDouble(value)) {
+      sign = epd1->type.bits.sign ^ epd2.type.bits.sign;
+      if (sign == 1)
+        EpdMakeNan(epd1);
+    } else if (EpdIsInf(&epd2)) {
+      EpdCopy(&epd2, epd1);
+    }
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+
+  EpdConvert(value, &epd2);
+  if (epd1->exponent > epd2.exponent) {
+    diff = epd1->exponent - epd2.exponent;
+    if (diff <= EPD_MAX_BIN)
+      tmp = epd1->type.value + epd2.type.value / pow((double)2.0, (double)diff);
+    else
+      tmp = epd1->type.value;
+    exponent = epd1->exponent;
+  } else if (epd1->exponent < epd2.exponent) {
+    diff = epd2.exponent - epd1->exponent;
+    if (diff <= EPD_MAX_BIN)
+      tmp = epd1->type.value / pow((double)2.0, (double)diff) + epd2.type.value;
+    else
+      tmp = epd2.type.value;
+    exponent = epd2.exponent;
+  } else {
+    tmp = epd1->type.value + epd2.type.value;
+    exponent = epd1->exponent;
+  }
+  epd1->type.value = tmp;
+  epd1->exponent = exponent;
+  EpdNormalize(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds two arbitrary precision double values.]
+
+  Description [Adds two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdAdd2(EpDouble *epd1, EpDouble *epd2)
+{
+  double        value;
+  int           exponent, diff;
+
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int sign;
+
+    if (EpdIsInf(epd1) && EpdIsInf(epd2)) {
+      sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+      if (sign == 1)
+        EpdMakeNan(epd1);
+    } else if (EpdIsInf(epd2)) {
+      EpdCopy(epd2, epd1);
+    }
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+  assert(epd2->type.bits.exponent == EPD_MAX_BIN);
+
+  if (epd1->exponent > epd2->exponent) {
+    diff = epd1->exponent - epd2->exponent;
+    if (diff <= EPD_MAX_BIN) {
+      value = epd1->type.value +
+                epd2->type.value / pow((double)2.0, (double)diff);
+    } else
+      value = epd1->type.value;
+    exponent = epd1->exponent;
+  } else if (epd1->exponent < epd2->exponent) {
+    diff = epd2->exponent - epd1->exponent;
+    if (diff <= EPD_MAX_BIN) {
+      value = epd1->type.value / pow((double)2.0, (double)diff) +
+                epd2->type.value;
+    } else
+      value = epd2->type.value;
+    exponent = epd2->exponent;
+  } else {
+    value = epd1->type.value + epd2->type.value;
+    exponent = epd1->exponent;
+  }
+  epd1->type.value = value;
+  epd1->exponent = exponent;
+  EpdNormalize(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds two arbitrary precision double values.]
+
+  Description [Adds two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdAdd3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3)
+{
+  double        value;
+  int           exponent, diff;
+
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd3);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int sign;
+
+    if (EpdIsInf(epd1) && EpdIsInf(epd2)) {
+      sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+      if (sign == 1)
+        EpdMakeNan(epd3);
+      else
+        EpdCopy(epd1, epd3);
+    } else if (EpdIsInf(epd1)) {
+      EpdCopy(epd1, epd3);
+    } else {
+      EpdCopy(epd2, epd3);
+    }
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+  assert(epd2->type.bits.exponent == EPD_MAX_BIN);
+
+  if (epd1->exponent > epd2->exponent) {
+    diff = epd1->exponent - epd2->exponent;
+    if (diff <= EPD_MAX_BIN) {
+      value = epd1->type.value +
+                epd2->type.value / pow((double)2.0, (double)diff);
+    } else
+      value = epd1->type.value;
+    exponent = epd1->exponent;
+  } else if (epd1->exponent < epd2->exponent) {
+    diff = epd2->exponent - epd1->exponent;
+    if (diff <= EPD_MAX_BIN) {
+      value = epd1->type.value / pow((double)2.0, (double)diff) +
+                epd2->type.value;
+    } else
+      value = epd2->type.value;
+    exponent = epd2->exponent;
+  } else {
+    value = epd1->type.value + epd2->type.value;
+    exponent = epd1->exponent;
+  }
+  epd3->type.value = value;
+  epd3->exponent = exponent;
+  EpdNormalize(epd3);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Subtracts two arbitrary precision double values.]
+
+  Description [Subtracts two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdSubtract(EpDouble *epd1, double value)
+{
+  EpDouble      epd2;
+  double        tmp;
+  int           exponent, diff;
+
+  if (EpdIsNan(epd1) || IsNanDouble(value)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || IsInfDouble(value)) {
+    int sign;
+
+    EpdConvert(value, &epd2);
+    if (EpdIsInf(epd1) && IsInfDouble(value)) {
+      sign = epd1->type.bits.sign ^ epd2.type.bits.sign;
+      if (sign == 0)
+        EpdMakeNan(epd1);
+    } else if (EpdIsInf(&epd2)) {
+      EpdCopy(&epd2, epd1);
+    }
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+
+  EpdConvert(value, &epd2);
+  if (epd1->exponent > epd2.exponent) {
+    diff = epd1->exponent - epd2.exponent;
+    if (diff <= EPD_MAX_BIN)
+      tmp = epd1->type.value - epd2.type.value / pow((double)2.0, (double)diff);
+    else
+      tmp = epd1->type.value;
+    exponent = epd1->exponent;
+  } else if (epd1->exponent < epd2.exponent) {
+    diff = epd2.exponent - epd1->exponent;
+    if (diff <= EPD_MAX_BIN)
+      tmp = epd1->type.value / pow((double)2.0, (double)diff) - epd2.type.value;
+    else
+      tmp = epd2.type.value * (double)(-1.0);
+    exponent = epd2.exponent;
+  } else {
+    tmp = epd1->type.value - epd2.type.value;
+    exponent = epd1->exponent;
+  }
+  epd1->type.value = tmp;
+  epd1->exponent = exponent;
+  EpdNormalize(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Subtracts two arbitrary precision double values.]
+
+  Description [Subtracts two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdSubtract2(EpDouble *epd1, EpDouble *epd2)
+{
+  double        value;
+  int           exponent, diff;
+
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int sign;
+
+    if (EpdIsInf(epd1) && EpdIsInf(epd2)) {
+      sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+      if (sign == 0)
+        EpdMakeNan(epd1);
+    } else if (EpdIsInf(epd2)) {
+      EpdCopy(epd2, epd1);
+    }
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+  assert(epd2->type.bits.exponent == EPD_MAX_BIN);
+
+  if (epd1->exponent > epd2->exponent) {
+    diff = epd1->exponent - epd2->exponent;
+    if (diff <= EPD_MAX_BIN) {
+      value = epd1->type.value -
+                epd2->type.value / pow((double)2.0, (double)diff);
+    } else
+      value = epd1->type.value;
+    exponent = epd1->exponent;
+  } else if (epd1->exponent < epd2->exponent) {
+    diff = epd2->exponent - epd1->exponent;
+    if (diff <= EPD_MAX_BIN) {
+      value = epd1->type.value / pow((double)2.0, (double)diff) -
+                epd2->type.value;
+    } else
+      value = epd2->type.value * (double)(-1.0);
+    exponent = epd2->exponent;
+  } else {
+    value = epd1->type.value - epd2->type.value;
+    exponent = epd1->exponent;
+  }
+  epd1->type.value = value;
+  epd1->exponent = exponent;
+  EpdNormalize(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Subtracts two arbitrary precision double values.]
+
+  Description [Subtracts two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdSubtract3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3)
+{
+  double        value;
+  int           exponent, diff;
+
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd3);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int sign;
+
+    if (EpdIsInf(epd1) && EpdIsInf(epd2)) {
+      sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+      if (sign == 0)
+        EpdCopy(epd1, epd3);
+      else
+        EpdMakeNan(epd3);
+    } else if (EpdIsInf(epd1)) {
+      EpdCopy(epd1, epd1);
+    } else {
+      sign = epd2->type.bits.sign ^ 0x1;
+      EpdMakeInf(epd3, sign);
+    }
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+  assert(epd2->type.bits.exponent == EPD_MAX_BIN);
+
+  if (epd1->exponent > epd2->exponent) {
+    diff = epd1->exponent - epd2->exponent;
+    if (diff <= EPD_MAX_BIN) {
+      value = epd1->type.value -
+                epd2->type.value / pow((double)2.0, (double)diff);
+    } else
+      value = epd1->type.value;
+    exponent = epd1->exponent;
+  } else if (epd1->exponent < epd2->exponent) {
+    diff = epd2->exponent - epd1->exponent;
+    if (diff <= EPD_MAX_BIN) {
+      value = epd1->type.value / pow((double)2.0, (double)diff) -
+                epd2->type.value;
+    } else
+      value = epd2->type.value * (double)(-1.0);
+    exponent = epd2->exponent;
+  } else {
+    value = epd1->type.value - epd2->type.value;
+    exponent = epd1->exponent;
+  }
+  epd3->type.value = value;
+  epd3->exponent = exponent;
+  EpdNormalize(epd3);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes arbitrary precision pow of base 2.]
+
+  Description [Computes arbitrary precision pow of base 2.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdPow2(int n, EpDouble *epd)
+{
+  if (n <= EPD_MAX_BIN) {
+    EpdConvert(pow((double)2.0, (double)n), epd);
+  } else {
+    EpDouble    epd1, epd2;
+    int         n1, n2;
+
+    n1 = n / 2;
+    n2 = n - n1;
+    EpdPow2(n1, &epd1);
+    EpdPow2(n2, &epd2);
+    EpdMultiply3(&epd1, &epd2, epd);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes arbitrary precision pow of base 2.]
+
+  Description [Computes arbitrary precision pow of base 2.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdPow2Decimal(int n, EpDouble *epd)
+{
+  if (n <= EPD_MAX_BIN) {
+    epd->type.value = pow((double)2.0, (double)n);
+    epd->exponent = 0;
+    EpdNormalizeDecimal(epd);
+  } else {
+    EpDouble    epd1, epd2;
+    int         n1, n2;
+
+    n1 = n / 2;
+    n2 = n - n1;
+    EpdPow2Decimal(n1, &epd1);
+    EpdPow2Decimal(n2, &epd2);
+    EpdMultiply3Decimal(&epd1, &epd2, epd);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Normalize an arbitrary precision double value.]
+
+  Description [Normalize an arbitrary precision double value.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdNormalize(EpDouble *epd)
+{
+  int           exponent;
+
+  if (IsNanOrInfDouble(epd->type.value)) {
+    epd->exponent = 0;
+    return;
+  }
+
+  exponent = EpdGetExponent(epd->type.value);
+  if (exponent == EPD_MAX_BIN)
+    return;
+  exponent -= EPD_MAX_BIN;
+  epd->type.bits.exponent = EPD_MAX_BIN;
+  epd->exponent += exponent;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Normalize an arbitrary precision double value.]
+
+  Description [Normalize an arbitrary precision double value.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdNormalizeDecimal(EpDouble *epd)
+{
+  int           exponent;
+
+  if (IsNanOrInfDouble(epd->type.value)) {
+    epd->exponent = 0;
+    return;
+  }
+
+  exponent = EpdGetExponentDecimal(epd->type.value);
+  epd->type.value /= pow((double)10.0, (double)exponent);
+  epd->exponent += exponent;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns value and decimal exponent of EpDouble.]
+
+  Description [Returns value and decimal exponent of EpDouble.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdGetValueAndDecimalExponent(EpDouble *epd, double *value, int *exponent)
+{
+  EpDouble      epd1, epd2;
+
+  if (EpdIsNanOrInf(epd))
+    return;
+
+  if (EpdIsZero(epd)) {
+    *value = 0.0;
+    *exponent = 0;
+    return;
+  }
+
+  epd1.type.value = epd->type.value;
+  epd1.exponent = 0;
+  EpdPow2Decimal(epd->exponent, &epd2);
+  EpdMultiply2Decimal(&epd1, &epd2);
+
+  *value = epd1.type.value;
+  *exponent = epd1.exponent;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the exponent value of a double.]
+
+  Description [Returns the exponent value of a double.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+EpdGetExponent(double value)
+{
+  int           exponent;
+  EpDouble      epd;
+
+  epd.type.value = value;
+  exponent = epd.type.bits.exponent;
+  return(exponent);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the decimal exponent value of a double.]
+
+  Description [Returns the decimal exponent value of a double.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+EpdGetExponentDecimal(double value)
+{
+  char  *pos, str[24];
+  int   exponent;
+
+  sprintf(str, "%E", value);
+  pos = strstr(str, "E");
+  sscanf(pos, "E%d", &exponent);
+  return(exponent);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes EpDouble Inf.]
+
+  Description [Makes EpDouble Inf.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdMakeInf(EpDouble *epd, int sign)
+{
+  epd->type.bits.mantissa1 = 0;
+  epd->type.bits.mantissa0 = 0;
+  epd->type.bits.exponent = EPD_EXP_INF;
+  epd->type.bits.sign = sign;
+  epd->exponent = 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes EpDouble Zero.]
+
+  Description [Makes EpDouble Zero.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdMakeZero(EpDouble *epd, int sign)
+{
+  epd->type.bits.mantissa1 = 0;
+  epd->type.bits.mantissa0 = 0;
+  epd->type.bits.exponent = 0;
+  epd->type.bits.sign = sign;
+  epd->exponent = 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes EpDouble NaN.]
+
+  Description [Makes EpDouble NaN.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdMakeNan(EpDouble *epd)
+{
+  epd->type.nan.mantissa1 = 0;
+  epd->type.nan.mantissa0 = 0;
+  epd->type.nan.quiet_bit = 1;
+  epd->type.nan.exponent = EPD_EXP_INF;
+  epd->type.nan.sign = 1;
+  epd->exponent = 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Copies a EpDouble struct.]
+
+  Description [Copies a EpDouble struct.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdCopy(EpDouble *from, EpDouble *to)
+{
+  to->type.value = from->type.value;
+  to->exponent = from->exponent;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the value is Inf.]
+
+  Description [Checks whether the value is Inf.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+EpdIsInf(EpDouble *epd)
+{
+  return(IsInfDouble(epd->type.value));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the value is Zero.]
+
+  Description [Checks whether the value is Zero.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+EpdIsZero(EpDouble *epd)
+{
+  if (epd->type.value == 0.0)
+    return(1);
+  else
+    return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the value is NaN.]
+
+  Description [Checks whether the value is NaN.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+EpdIsNan(EpDouble *epd)
+{
+  return(IsNanDouble(epd->type.value));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the value is NaN or Inf.]
+
+  Description [Checks whether the value is NaN or Inf.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+EpdIsNanOrInf(EpDouble *epd)
+{
+  return(IsNanOrInfDouble(epd->type.value));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the value is Inf.]
+
+  Description [Checks whether the value is Inf.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+IsInfDouble(double value)
+{
+  EpType val;
+
+  val.value = value;
+  if (val.bits.exponent == EPD_EXP_INF &&
+      val.bits.mantissa0 == 0 &&
+      val.bits.mantissa1 == 0) {
+    if (val.bits.sign == 0)
+      return(1);
+    else
+      return(-1);
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the value is NaN.]
+
+  Description [Checks whether the value is NaN.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+IsNanDouble(double value)
+{
+  EpType        val;
+  
+  val.value = value;
+  if (val.nan.exponent == EPD_EXP_INF &&
+      val.nan.sign == 1 &&
+      val.nan.quiet_bit == 1 &&
+      val.nan.mantissa0 == 0 &&
+      val.nan.mantissa1 == 0) {
+    return(1);
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the value is NaN or Inf.]
+
+  Description [Checks whether the value is NaN or Inf.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+IsNanOrInfDouble(double value)
+{
+  EpType        val;
+
+  val.value = value;
+  if (val.nan.exponent == EPD_EXP_INF &&
+      val.nan.mantissa0 == 0 &&
+      val.nan.mantissa1 == 0 &&
+      (val.nan.sign == 1 || val.nan.quiet_bit == 0)) {
+    return(1);
+  }
+  return(0);
+}
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/bdd/epd/epd.h b/abc-build/src/bdd/epd/epd.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/epd/epd.h
@@ -0,0 +1,196 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [epd.h]
+
+  PackageName [epd]
+
+  Synopsis    [The University of Colorado extended double precision package.]
+
+  Description [arithmetic functions with extended double precision.]
+
+  SeeAlso     []
+
+  Author      [In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+  Revision    [$Id: epd.h,v 1.9 2004/08/13 18:20:30 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef ABC__bdd__epd__epd_h
+#define ABC__bdd__epd__epd_h
+
+ABC_NAMESPACE_HEADER_START
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define EPD_MAX_BIN     1023
+#define EPD_MAX_DEC     308
+#define EPD_EXP_INF     0x7ff
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [IEEE double struct.]
+
+  Description [IEEE double struct.]
+
+  SeeAlso     []
+
+******************************************************************************/
+#ifdef  EPD_BIG_ENDIAN
+struct IeeeDoubleStruct {       /* BIG_ENDIAN */
+  unsigned int sign: 1;
+  unsigned int exponent: 11;
+  unsigned int mantissa0: 20;
+  unsigned int mantissa1: 32;
+};
+#else
+struct IeeeDoubleStruct {       /* LITTLE_ENDIAN */
+  unsigned int mantissa1: 32;
+  unsigned int mantissa0: 20;
+  unsigned int exponent: 11;
+  unsigned int sign: 1;
+};
+#endif
+
+/**Struct**********************************************************************
+
+  Synopsis    [IEEE double NaN struct.]
+
+  Description [IEEE double NaN struct.]
+
+  SeeAlso     []
+
+******************************************************************************/
+#ifdef  EPD_BIG_ENDIAN
+struct IeeeNanStruct {  /* BIG_ENDIAN */
+  unsigned int sign: 1;
+  unsigned int exponent: 11;
+  unsigned int quiet_bit: 1;
+  unsigned int mantissa0: 19;
+  unsigned int mantissa1: 32;
+};
+#else
+struct IeeeNanStruct {  /* LITTLE_ENDIAN */
+  unsigned int mantissa1: 32;
+  unsigned int mantissa0: 19;
+  unsigned int quiet_bit: 1;
+  unsigned int exponent: 11;
+  unsigned int sign: 1;
+};
+#endif
+
+/**Struct**********************************************************************
+
+  Synopsis    [Extended precision double to keep very large value.]
+
+  Description [Extended precision double to keep very large value.]
+
+  SeeAlso     []
+
+******************************************************************************/
+union EpTypeUnion {
+  double                        value;
+  struct IeeeDoubleStruct       bits;
+  struct IeeeNanStruct          nan;
+};
+
+struct EpDoubleStruct {
+  union EpTypeUnion             type;
+  int                           exponent;
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct EpDoubleStruct EpDouble;
+typedef struct IeeeDoubleStruct IeeeDouble;
+typedef struct IeeeNanStruct IeeeNan;
+typedef union EpTypeUnion EpType;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+extern EpDouble *EpdAlloc(void);
+extern int EpdCmp(const char *key1, const char *key2);
+extern void EpdFree(EpDouble *epd);
+extern void EpdGetString(EpDouble *epd, char *str);
+extern void EpdConvert(double value, EpDouble *epd);
+extern void EpdMultiply(EpDouble *epd1, double value);
+extern void EpdMultiply2(EpDouble *epd1, EpDouble *epd2);
+extern void EpdMultiply2Decimal(EpDouble *epd1, EpDouble *epd2);
+extern void EpdMultiply3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3);
+extern void EpdMultiply3Decimal(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3);
+extern void EpdDivide(EpDouble *epd1, double value);
+extern void EpdDivide2(EpDouble *epd1, EpDouble *epd2);
+extern void EpdDivide3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3);
+extern void EpdAdd(EpDouble *epd1, double value);
+extern void EpdAdd2(EpDouble *epd1, EpDouble *epd2);
+extern void EpdAdd3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3);
+extern void EpdSubtract(EpDouble *epd1, double value);
+extern void EpdSubtract2(EpDouble *epd1, EpDouble *epd2);
+extern void EpdSubtract3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3);
+extern void EpdPow2(int n, EpDouble *epd);
+extern void EpdPow2Decimal(int n, EpDouble *epd);
+extern void EpdNormalize(EpDouble *epd);
+extern void EpdNormalizeDecimal(EpDouble *epd);
+extern void EpdGetValueAndDecimalExponent(EpDouble *epd, double *value, int *exponent);
+extern int EpdGetExponent(double value);
+extern int EpdGetExponentDecimal(double value);
+extern void EpdMakeInf(EpDouble *epd, int sign);
+extern void EpdMakeZero(EpDouble *epd, int sign);
+extern void EpdMakeNan(EpDouble *epd);
+extern void EpdCopy(EpDouble *from, EpDouble *to);
+extern int EpdIsInf(EpDouble *epd);
+extern int EpdIsZero(EpDouble *epd);
+extern int EpdIsNan(EpDouble *epd);
+extern int EpdIsNanOrInf(EpDouble *epd);
+extern int IsInfDouble(double value);
+extern int IsNanDouble(double value);
+extern int IsNanOrInfDouble(double value);
+
+/**AutomaticEnd***************************************************************/
+
+ABC_NAMESPACE_HEADER_END
+
+#endif /* _EPD */
diff --git a/abc-build/src/bdd/epd/module.make b/abc-build/src/bdd/epd/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/epd/module.make
@@ -0,0 +1,1 @@
+SRC +=  src/bdd/epd/epd.c
diff --git a/abc-build/src/bdd/mtr/module.make b/abc-build/src/bdd/mtr/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/mtr/module.make
@@ -0,0 +1,2 @@
+SRC +=  src/bdd/mtr/mtrBasic.c \
+	src/bdd/mtr/mtrGroup.c
diff --git a/abc-build/src/bdd/mtr/mtr.h b/abc-build/src/bdd/mtr/mtr.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/mtr/mtr.h
@@ -0,0 +1,187 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [mtr.h]
+
+  PackageName [mtr]
+
+  Synopsis    [Multiway-branch tree manipulation]
+
+  Description [This package provides two layers of functions. Functions
+  of the lower level manipulate multiway-branch trees, implemented
+  according to the classical scheme whereby each node points to its
+  first child and its previous and next siblings. These functions are
+  collected in mtrBasic.c.<p>
+  Functions of the upper layer deal with group trees, that is the trees
+  used by group sifting to represent the grouping of variables. These
+  functions are collected in mtrGroup.c.]
+
+  SeeAlso     [The CUDD package documentation; specifically on group
+  sifting.]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+  Revision    [$Id: mtr.h,v 1.14 2009/02/20 02:03:47 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef ABC__bdd__mtr__mtr_h
+#define ABC__bdd__mtr__mtr_h
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+ABC_NAMESPACE_HEADER_START
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef SIZEOF_VOID_P
+#define SIZEOF_VOID_P 4
+#endif
+#ifndef SIZEOF_INT
+#define SIZEOF_INT 4
+#endif
+
+#undef CONST
+#if defined(__STDC__) || defined(__cplusplus)
+#define CONST           const
+#else /* !(__STDC__ || __cplusplus) */
+#define CONST
+#endif /* !(__STDC__ || __cplusplus) */
+
+#if defined(__GNUC__)
+#define MTR_INLINE __inline__
+# if (__GNUC__ >2 || __GNUC_MINOR__ >=7)
+#   define MTR_UNUSED __attribute__ ((unused))
+# else
+#   define MTR_UNUSED
+# endif
+#else
+#define MTR_INLINE
+#define MTR_UNUSED
+#endif
+
+/* Flag definitions */
+#define MTR_DEFAULT     0x00000000
+#define MTR_TERMINAL    0x00000001
+#define MTR_SOFT        0x00000002
+#define MTR_FIXED       0x00000004
+#define MTR_NEWNODE     0x00000008
+
+/* MTR_MAXHIGH is defined in such a way that on 32-bit and 64-bit
+** machines one can cast a value to (int) without generating a negative
+** number.
+*/
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define MTR_MAXHIGH     (((MtrHalfWord) ~0) >> 1)
+#else
+#define MTR_MAXHIGH     ((MtrHalfWord) ~0)
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+typedef unsigned int   MtrHalfWord;
+#else
+typedef unsigned short MtrHalfWord;
+#endif
+
+typedef struct MtrNode {
+    MtrHalfWord flags;
+    MtrHalfWord low;
+    MtrHalfWord size;
+    MtrHalfWord index;
+    struct MtrNode *parent;
+    struct MtrNode *child;
+    struct MtrNode *elder;
+    struct MtrNode *younger;
+} MtrNode;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/* Flag manipulation macros */
+#define MTR_SET(node, flag)             (node->flags |= (flag))
+#define MTR_RESET(node, flag)   (node->flags &= ~ (flag))
+#define MTR_TEST(node, flag)    (node->flags & (flag))
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+extern MtrNode * Mtr_AllocNode (void);
+extern void Mtr_DeallocNode (MtrNode *node);
+extern MtrNode * Mtr_InitTree (void);
+extern void Mtr_FreeTree (MtrNode *node);
+extern MtrNode * Mtr_CopyTree (MtrNode *node, int expansion);
+extern void Mtr_MakeFirstChild (MtrNode *parent, MtrNode *child);
+extern void Mtr_MakeLastChild (MtrNode *parent, MtrNode *child);
+extern MtrNode * Mtr_CreateFirstChild (MtrNode *parent);
+extern MtrNode * Mtr_CreateLastChild (MtrNode *parent);
+extern void Mtr_MakeNextSibling (MtrNode *first, MtrNode *second);
+extern void Mtr_PrintTree (MtrNode *node);
+extern MtrNode * Mtr_InitGroupTree (int lower, int size);
+extern MtrNode * Mtr_MakeGroup (MtrNode *root, unsigned int low, unsigned int high, unsigned int flags);
+extern MtrNode * Mtr_DissolveGroup (MtrNode *group);
+extern MtrNode * Mtr_FindGroup (MtrNode *root, unsigned int low, unsigned int high);
+extern int Mtr_SwapGroups (MtrNode *first, MtrNode *second);
+extern void Mtr_PrintGroups (MtrNode *root, int silent);
+extern MtrNode * Mtr_ReadGroups (FILE *fp, int nleaves);
+
+/**AutomaticEnd***************************************************************/
+
+ABC_NAMESPACE_HEADER_END
+
+#endif /* __MTR */
diff --git a/abc-build/src/bdd/mtr/mtrBasic.c b/abc-build/src/bdd/mtr/mtrBasic.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/mtr/mtrBasic.c
@@ -0,0 +1,453 @@
+/**CFile***********************************************************************
+
+  FileName    [mtrBasic.c]
+
+  PackageName [mtr]
+
+  Synopsis    [Basic manipulation of multiway branching trees.]
+
+  Description [External procedures included in this module:
+            <ul>
+            <li> Mtr_AllocNode()
+            <li> Mtr_DeallocNode()
+            <li> Mtr_InitTree()
+            <li> Mtr_FreeTree()
+            <li> Mtr_CopyTree()
+            <li> Mtr_MakeFirstChild()
+            <li> Mtr_MakeLastChild()
+            <li> Mtr_CreateFirstChild()
+            <li> Mtr_CreateLastChild()
+            <li> Mtr_MakeNextSibling()
+            <li> Mtr_PrintTree()
+            </ul>
+            ]
+
+  SeeAlso     [cudd package]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "mtrInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] MTR_UNUSED = "$Id: mtrBasic.c,v 1.13 2009/02/20 02:03:47 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates new tree node.]
+
+  Description [Allocates new tree node. Returns pointer to node.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_DeallocNode]
+
+******************************************************************************/
+MtrNode *
+Mtr_AllocNode(void)
+{
+    MtrNode *node;
+
+    node = ABC_ALLOC(MtrNode,1);
+    return node;
+
+} /* Mtr_AllocNode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Deallocates tree node.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_AllocNode]
+
+******************************************************************************/
+void
+Mtr_DeallocNode(
+  MtrNode * node /* node to be deallocated */)
+{
+    ABC_FREE(node);
+    return;
+
+} /* end of Mtr_DeallocNode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes tree with one node.]
+
+  Description [Initializes tree with one node. Returns pointer to node.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_FreeTree Mtr_InitGroupTree]
+
+******************************************************************************/
+MtrNode *
+Mtr_InitTree(void)
+{
+    MtrNode *node;
+
+    node = Mtr_AllocNode();
+    if (node == NULL) return(NULL);
+
+    node->parent = node->child = node->elder = node->younger = NULL;
+    node->flags = 0;
+
+    return(node);
+
+} /* end of Mtr_InitTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disposes of tree rooted at node.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_InitTree]
+
+******************************************************************************/
+void
+Mtr_FreeTree(
+  MtrNode * node)
+{
+    if (node == NULL) return;
+    if (! MTR_TEST(node,MTR_TERMINAL)) Mtr_FreeTree(node->child);
+    Mtr_FreeTree(node->younger);
+    Mtr_DeallocNode(node);
+    return;
+
+} /* end of Mtr_FreeTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes a copy of tree.]
+
+  Description [Makes a copy of tree. If parameter expansion is greater
+  than 1, it will expand the tree by that factor. It is an error for
+  expansion to be less than 1. Returns a pointer to the copy if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_InitTree]
+
+******************************************************************************/
+MtrNode *
+Mtr_CopyTree(
+  MtrNode * node,
+  int  expansion)
+{
+    MtrNode *copy;
+
+    if (node == NULL) return(NULL);
+    if (expansion < 1) return(NULL);
+    copy = Mtr_AllocNode();
+    if (copy == NULL) return(NULL);
+    copy->parent = copy->elder = copy->child = copy->younger = NULL;
+    if (node->child != NULL) {
+        copy->child = Mtr_CopyTree(node->child, expansion);
+        if (copy->child == NULL) {
+            Mtr_DeallocNode(copy);
+            return(NULL);
+        }
+    }
+    if (node->younger != NULL) {
+        copy->younger = Mtr_CopyTree(node->younger, expansion);
+        if (copy->younger == NULL) {
+            Mtr_FreeTree(copy);
+            return(NULL);
+        }
+    }
+    copy->flags = node->flags;
+    copy->low = node->low * expansion;
+    copy->size = node->size * expansion;
+    copy->index = node->index * expansion;
+    if (copy->younger) copy->younger->elder = copy;
+    if (copy->child) {
+        MtrNode *auxnode = copy->child;
+        while (auxnode != NULL) {
+            auxnode->parent = copy;
+            auxnode = auxnode->younger;
+        }
+    }
+    return(copy);
+
+} /* end of Mtr_CopyTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes child the first child of parent.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_MakeLastChild Mtr_CreateFirstChild]
+
+******************************************************************************/
+void
+Mtr_MakeFirstChild(
+  MtrNode * parent,
+  MtrNode * child)
+{
+    child->parent = parent;
+    child->younger = parent->child;
+    child->elder = NULL;
+    if (parent->child != NULL) {
+#ifdef MTR_DEBUG
+        assert(parent->child->elder == NULL);
+#endif
+        parent->child->elder = child;
+    }
+    parent->child = child;
+    return;
+
+} /* end of Mtr_MakeFirstChild */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes child the last child of parent.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_MakeFirstChild Mtr_CreateLastChild]
+
+******************************************************************************/
+void
+Mtr_MakeLastChild(
+  MtrNode * parent,
+  MtrNode * child)
+{
+    MtrNode *node;
+
+    child->younger = NULL;
+
+    if (parent->child == NULL) {
+        parent->child = child;
+        child->elder = NULL;
+    } else {
+        for (node = parent->child;
+             node->younger != NULL;
+             node = node->younger);
+        node->younger = child;
+        child->elder = node;
+    }
+    child->parent = parent;
+    return;
+
+} /* end of Mtr_MakeLastChild */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a new node and makes it the first child of parent.]
+
+  Description [Creates a new node and makes it the first child of
+  parent. Returns pointer to new child.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_MakeFirstChild Mtr_CreateLastChild]
+
+******************************************************************************/
+MtrNode *
+Mtr_CreateFirstChild(
+  MtrNode * parent)
+{
+    MtrNode *child;
+
+    child = Mtr_AllocNode();
+    if (child == NULL) return(NULL);
+
+    child->child = child->younger = child-> elder = NULL;
+    child->flags = 0;
+    Mtr_MakeFirstChild(parent,child);
+    return(child);
+
+} /* end of Mtr_CreateFirstChild */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a new node and makes it the last child of parent.]
+
+  Description [Creates a new node and makes it the last child of parent.
+  Returns pointer to new child.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_MakeLastChild Mtr_CreateFirstChild]
+
+******************************************************************************/
+MtrNode *
+Mtr_CreateLastChild(
+  MtrNode * parent)
+{
+    MtrNode *child;
+
+    child = Mtr_AllocNode();
+    if (child == NULL) return(NULL);
+
+    child->child = child->younger = child->elder = NULL;
+    child->flags = 0;
+    Mtr_MakeLastChild(parent,child);
+    return(child);
+
+} /* end of Mtr_CreateLastChild */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes second the next sibling of first.]
+
+  Description [Makes second the next sibling of first. Second becomes a
+  child of the parent of first.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Mtr_MakeNextSibling(
+  MtrNode * first,
+  MtrNode * second)
+{
+    second->younger = first->younger;
+    if (first->younger != NULL) {
+        first->younger->elder = second;
+    }
+    second->parent = first->parent;
+    first->younger = second;
+    second->elder = first;
+    return;
+
+} /* end of Mtr_MakeNextSibling */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a tree, one node per line.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_PrintGroups]
+
+******************************************************************************/
+void
+Mtr_PrintTree(
+  MtrNode * node)
+{
+    if (node == NULL) return;
+    (void) fprintf(stdout,
+#if SIZEOF_VOID_P == 8
+    "N=0x%-8lx C=0x%-8lx Y=0x%-8lx E=0x%-8lx P=0x%-8lx F=%x L=%u S=%u\n",
+    (unsigned long) node, (unsigned long) node->child,
+    (unsigned long) node->younger, (unsigned long) node->elder,
+    (unsigned long) node->parent, node->flags, node->low, node->size);
+#else
+    "N=0x%-8x C=0x%-8x Y=0x%-8x E=0x%-8x P=0x%-8x F=%x L=%hu S=%hu\n",
+    (unsigned) node, (unsigned) node->child,
+    (unsigned) node->younger, (unsigned) node->elder,
+    (unsigned) node->parent, node->flags, node->low, node->size);
+#endif
+    if (!MTR_TEST(node,MTR_TERMINAL)) Mtr_PrintTree(node->child);
+    Mtr_PrintTree(node->younger);
+    return;
+
+} /* end of Mtr_PrintTree */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/bdd/mtr/mtrGroup.c b/abc-build/src/bdd/mtr/mtrGroup.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/mtr/mtrGroup.c
@@ -0,0 +1,734 @@
+/**CFile***********************************************************************
+
+  FileName    [mtrGroup.c]
+
+  PackageName [mtr]
+
+  Synopsis    [Functions to support group specification for reordering.]
+
+  Description [External procedures included in this module:
+            <ul>
+            <li> Mtr_InitGroupTree()
+            <li> Mtr_MakeGroup()
+            <li> Mtr_DissolveGroup()
+            <li> Mtr_FindGroup()
+            <li> Mtr_SwapGroups()
+            <li> Mtr_PrintGroups()
+            <li> Mtr_ReadGroups()
+            </ul>
+        Static procedures included in this module:
+            <ul>
+            <li> mtrShiftHL
+            </ul>
+            ]
+
+  SeeAlso     [cudd package]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "misc/util/util_hack.h"
+#include "mtrInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] MTR_UNUSED = "$Id: mtrGroup.c,v 1.18 2009/02/20 02:03:47 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int mtrShiftHL (MtrNode *node, int shift);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocate new tree.]
+
+  Description [Allocate new tree with one node, whose low and size
+  fields are specified by the lower and size parameters.
+  Returns pointer to tree root.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_InitTree Mtr_FreeTree]
+
+******************************************************************************/
+MtrNode *
+Mtr_InitGroupTree(
+  int  lower,
+  int  size)
+{
+    MtrNode *root;
+
+    root = Mtr_InitTree();
+    if (root == NULL) return(NULL);
+    root->flags = MTR_DEFAULT;
+    root->low = lower;
+    root->size = size;
+    return(root);
+
+} /* end of Mtr_InitGroupTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes a new group with size leaves starting at low.]
+
+  Description [Makes a new group with size leaves starting at low.
+  If the new group intersects an existing group, it must
+  either contain it or be contained by it.  This procedure relies on
+  the low and size fields of each node. It also assumes that the
+  children of each node are sorted in order of increasing low.  In
+  case of a valid request, the flags of the new group are set to the
+  value passed in `flags.' This can also be used to change the flags
+  of an existing group.  Returns the pointer to the root of the new
+  group upon successful termination; NULL otherwise. If the group
+  already exists, the pointer to its root is returned.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_DissolveGroup Mtr_ReadGroups Mtr_FindGroup]
+
+******************************************************************************/
+MtrNode *
+Mtr_MakeGroup(
+  MtrNode * root /* root of the group tree */,
+  unsigned int  low /* lower bound of the group */,
+  unsigned int  size /* upper bound of the group */,
+  unsigned int  flags /* flags for the new group */)
+{
+    MtrNode *node,
+            *first,
+            *last,
+            *previous,
+            *newn;
+
+    /* Sanity check. */
+    if (size == 0)
+        return(NULL);
+
+    /* Check whether current group includes new group.  This check is
+    ** necessary at the top-level call.  In the subsequent calls it is
+    ** redundant. */
+    if (low < (unsigned int) root->low ||
+        low + size > (unsigned int) (root->low + root->size))
+        return(NULL);
+
+    /* Trying to create an existing group has the effect of updating
+    ** the flags. */
+    if (root->size == size && root->low == low) {
+        root->flags = flags;
+        return(root);
+    }
+
+    /* At this point we know that the new group is properly contained
+    ** in the group of root. We have two possible cases here: - root
+    ** is a terminal node; - root has children. */
+
+    /* Root has no children: create a new group. */
+    if (root->child == NULL) {
+        newn = Mtr_AllocNode();
+        if (newn == NULL) return(NULL); /* out of memory */
+        newn->low = low;
+        newn->size = size;
+        newn->flags = flags;
+        newn->parent = root;
+        newn->elder = newn->younger = newn->child = NULL;
+        root->child = newn;
+        return(newn);
+    }
+
+    /* Root has children: Find all chidren of root that are included
+    ** in the new group. If the group of any child entirely contains
+    ** the new group, call Mtr_MakeGroup recursively. */
+    previous = NULL;
+    first = root->child; /* guaranteed to be non-NULL */
+    while (first != NULL && low >= (unsigned int) (first->low + first->size)) {
+        previous = first;
+        first = first->younger;
+    }
+    if (first == NULL) {
+        /* We have scanned the entire list and we need to append a new
+        ** child at the end of it.  Previous points to the last child
+        ** of root. */
+        newn = Mtr_AllocNode();
+        if (newn == NULL) return(NULL); /* out of memory */
+        newn->low = low;
+        newn->size = size;
+        newn->flags = flags;
+        newn->parent = root;
+        newn->elder = previous;
+        previous->younger = newn;
+        newn->younger = newn->child = NULL;
+        return(newn);
+    }
+    /* Here first is non-NULL and low < first->low + first->size. */
+    if (low >= (unsigned int) first->low &&
+        low + size <= (unsigned int) (first->low + first->size)) {
+        /* The new group is contained in the group of first. */
+        newn = Mtr_MakeGroup(first, low, size, flags);
+        return(newn);
+    } else if (low + size <= first->low) {
+        /* The new group is entirely contained in the gap between
+        ** previous and first. */
+        newn = Mtr_AllocNode();
+        if (newn == NULL) return(NULL); /* out of memory */
+        newn->low = low;
+        newn->size = size;
+        newn->flags = flags;
+        newn->child = NULL;
+        newn->parent = root;
+        newn->elder = previous;
+        newn->younger = first;
+        first->elder = newn;
+        if (previous != NULL) {
+            previous->younger = newn;
+        } else {
+            root->child = newn;
+        }
+        return(newn);
+    } else if (low < (unsigned int) first->low &&
+               low + size < (unsigned int) (first->low + first->size)) {
+        /* Trying to cut an existing group: not allowed. */
+        return(NULL);
+    } else if (low > first->low) {
+        /* The new group neither is contained in the group of first
+        ** (this was tested above) nor contains it. It is therefore
+        ** trying to cut an existing group: not allowed. */
+        return(NULL);
+    }
+
+    /* First holds the pointer to the first child contained in the new
+    ** group. Here low <= first->low and low + size >= first->low +
+    ** first->size.  One of the two inequalities is strict. */
+    last = first->younger;
+    while (last != NULL &&
+           (unsigned int) (last->low + last->size) < low + size) {
+        last = last->younger;
+    }
+    if (last == NULL) {
+        /* All the chilren of root from first onward become children
+        ** of the new group. */
+        newn = Mtr_AllocNode();
+        if (newn == NULL) return(NULL); /* out of memory */
+        newn->low = low;
+        newn->size = size;
+        newn->flags = flags;
+        newn->child = first;
+        newn->parent = root;
+        newn->elder = previous;
+        newn->younger = NULL;
+        first->elder = NULL;
+        if (previous != NULL) {
+            previous->younger = newn;
+        } else {
+            root->child = newn;
+        }
+        last = first;
+        while (last != NULL) {
+            last->parent = newn;
+            last = last->younger;
+        }
+        return(newn);
+    }
+
+    /* Here last != NULL and low + size <= last->low + last->size. */
+    if (low + size - 1 >= (unsigned int) last->low &&
+        low + size < (unsigned int) (last->low + last->size)) {
+        /* Trying to cut an existing group: not allowed. */
+        return(NULL);
+    }
+
+    /* First and last point to the first and last of the children of
+    ** root that are included in the new group. Allocate a new node
+    ** and make all children of root between first and last chidren of
+    ** the new node.  Previous points to the child of root immediately
+    ** preceeding first. If it is NULL, then first is the first child
+    ** of root. */
+    newn = Mtr_AllocNode();
+    if (newn == NULL) return(NULL);     /* out of memory */
+    newn->low = low;
+    newn->size = size;
+    newn->flags = flags;
+    newn->child = first;
+    newn->parent = root;
+    if (previous == NULL) {
+        root->child = newn;
+    } else {
+        previous->younger = newn;
+    }
+    newn->elder = previous;
+    newn->younger = last->younger;
+    if (last->younger != NULL) {
+        last->younger->elder = newn;
+    }
+    last->younger = NULL;
+    first->elder = NULL;
+    for (node = first; node != NULL; node = node->younger) {
+        node->parent = newn;
+    }
+
+    return(newn);
+
+} /* end of Mtr_MakeGroup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Merges the children of `group' with the children of its
+  parent.]
+
+  Description [Merges the children of `group' with the children of its
+  parent. Disposes of the node pointed by group. If group is the
+  root of the group tree, this procedure leaves the tree unchanged.
+  Returns the pointer to the parent of `group' upon successful
+  termination; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_MakeGroup]
+
+******************************************************************************/
+MtrNode *
+Mtr_DissolveGroup(
+  MtrNode * group /* group to be dissolved */)
+{
+    MtrNode *parent;
+    MtrNode *last;
+
+    parent = group->parent;
+
+    if (parent == NULL) return(NULL);
+    if (MTR_TEST(group,MTR_TERMINAL) || group->child == NULL) return(NULL);
+
+    /* Make all children of group children of its parent, and make
+    ** last point to the last child of group. */
+    for (last = group->child; last->younger != NULL; last = last->younger) {
+        last->parent = parent;
+    }
+    last->parent = parent;
+
+    last->younger = group->younger;
+    if (group->younger != NULL) {
+        group->younger->elder = last;
+    }
+
+    group->child->elder = group->elder;
+    if (group == parent->child) {
+        parent->child = group->child;
+    } else {
+        group->elder->younger = group->child;
+    }
+
+    Mtr_DeallocNode(group);
+    return(parent);
+
+} /* end of Mtr_DissolveGroup */
+
+
+/**Function********************************************************************
+
+  Synopsis [Finds a group with size leaves starting at low, if it exists.]
+
+  Description [Finds a group with size leaves starting at low, if it
+  exists.  This procedure relies on the low and size fields of each
+  node. It also assumes that the children of each node are sorted in
+  order of increasing low.  Returns the pointer to the root of the
+  group upon successful termination; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+MtrNode *
+Mtr_FindGroup(
+  MtrNode * root /* root of the group tree */,
+  unsigned int  low /* lower bound of the group */,
+  unsigned int  size /* upper bound of the group */)
+{
+    MtrNode *node;
+
+#ifdef MTR_DEBUG
+    /* We cannot have a non-empty proper subgroup of a singleton set. */
+    assert(!MTR_TEST(root,MTR_TERMINAL));
+#endif
+
+    /* Sanity check. */
+    if (size < 1) return(NULL);
+
+    /* Check whether current group includes the group sought.  This
+    ** check is necessary at the top-level call.  In the subsequent
+    ** calls it is redundant. */
+    if (low < (unsigned int) root->low ||
+        low + size > (unsigned int) (root->low + root->size))
+        return(NULL);
+
+    if (root->size == size && root->low == low)
+        return(root);
+
+    if (root->child == NULL)
+        return(NULL);
+
+    /* Find all chidren of root that are included in the new group. If
+    ** the group of any child entirely contains the new group, call
+    ** Mtr_MakeGroup recursively.  */
+    node = root->child;
+    while (low >= (unsigned int) (node->low + node->size)) {
+        node = node->younger;
+    }
+    if (low + size <= (unsigned int) (node->low + node->size)) {
+        /* The group is contained in the group of node. */
+        node = Mtr_FindGroup(node, low, size);
+        return(node);
+    } else {
+        return(NULL);
+    }
+
+} /* end of Mtr_FindGroup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Swaps two children of a tree node.]
+
+  Description [Swaps two children of a tree node. Adjusts the high and
+  low fields of the two nodes and their descendants.  The two children
+  must be adjacent. However, first may be the younger sibling of second.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Mtr_SwapGroups(
+  MtrNode * first /* first node to be swapped */,
+  MtrNode * second /* second node to be swapped */)
+{
+    MtrNode *node;
+    MtrNode *parent;
+    int sizeFirst;
+    int sizeSecond;
+
+    if (second->younger == first) { /* make first first */
+        node = first;
+        first = second;
+        second = node;
+    } else if (first->younger != second) { /* non-adjacent */
+        return(0);
+    }
+
+    sizeFirst = first->size;
+    sizeSecond = second->size;
+
+    /* Swap the two nodes. */
+    parent = first->parent;
+    if (parent == NULL || second->parent != parent) return(0);
+    if (parent->child == first) {
+        parent->child = second;
+    } else { /* first->elder != NULL */
+        first->elder->younger = second;
+    }
+    if (second->younger != NULL) {
+        second->younger->elder = first;
+    }
+    first->younger = second->younger;
+    second->elder = first->elder;
+    first->elder = second;
+    second->younger = first;
+
+    /* Adjust the high and low fields. */
+    if (!mtrShiftHL(first,sizeSecond)) return(0);
+    if (!mtrShiftHL(second,-sizeFirst)) return(0);
+
+    return(1);
+
+} /* end of Mtr_SwapGroups */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the groups as a parenthesized list.]
+
+  Description [Prints the groups as a parenthesized list. After each
+  group, the group's flag are printed, preceded by a `|'.  For each
+  flag (except MTR_TERMINAL) a character is printed.
+  <ul>
+  <li>F: MTR_FIXED
+  <li>N: MTR_NEWNODE
+  <li>S: MTR_SOFT
+  </ul>
+  The second argument, silent, if different from 0, causes
+  Mtr_PrintGroups to only check the syntax of the group tree.
+  ]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_PrintTree]
+
+******************************************************************************/
+void
+Mtr_PrintGroups(
+  MtrNode * root /* root of the group tree */,
+  int  silent /* flag to check tree syntax only */)
+{
+    MtrNode *node;
+
+    assert(root != NULL);
+    assert(root->younger == NULL || root->younger->elder == root);
+    assert(root->elder == NULL || root->elder->younger == root);
+#if SIZEOF_VOID_P == 8
+    if (!silent) (void) printf("(%u",root->low);
+#else
+    if (!silent) (void) printf("(%hu",root->low);
+#endif
+    if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) {
+        if (!silent) (void) printf(",");
+    } else {
+        node = root->child;
+        while (node != NULL) {
+            assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size));
+            assert(node->parent == root);
+            Mtr_PrintGroups(node,silent);
+            node = node->younger;
+        }
+    }
+    if (!silent) {
+#if SIZEOF_VOID_P == 8
+        (void) printf("%u", root->low + root->size - 1);
+#else
+        (void) printf("%hu", root->low + root->size - 1);
+#endif
+        if (root->flags != MTR_DEFAULT) {
+            (void) printf("|");
+            if (MTR_TEST(root,MTR_FIXED)) (void) printf("F");
+            if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N");
+            if (MTR_TEST(root,MTR_SOFT)) (void) printf("S");
+        }
+        (void) printf(")");
+        if (root->parent == NULL) (void) printf("\n");
+    }
+    assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0);
+    return;
+
+} /* end of Mtr_PrintGroups */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads groups from a file and creates a group tree.]
+
+  Description [Reads groups from a file and creates a group tree.
+  Each group is specified by three fields:
+  <xmp>
+       low size flags.
+  </xmp>
+  Low and size are (short) integers. Flags is a string composed of the
+  following characters (with associated translation):
+  <ul>
+  <li>D: MTR_DEFAULT
+  <li>F: MTR_FIXED
+  <li>N: MTR_NEWNODE
+  <li>S: MTR_SOFT
+  <li>T: MTR_TERMINAL
+  </ul>
+  Normally, the only flags that are needed are D and F.  Groups and
+  fields are separated by white space (spaces, tabs, and newlines).
+  Returns a pointer to the group tree if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_InitGroupTree Mtr_MakeGroup]
+
+******************************************************************************/
+MtrNode *
+Mtr_ReadGroups(
+  FILE * fp /* file pointer */,
+  int  nleaves /* number of leaves of the new tree */)
+{
+    int low;
+    int size;
+    int err;
+    unsigned int flags;
+    MtrNode *root;
+    MtrNode *node;
+    char attrib[8*sizeof(unsigned int)+1];
+    char *c;
+
+    root = Mtr_InitGroupTree(0,nleaves);
+    if (root == NULL) return NULL;
+
+    while (! feof(fp)) {
+        /* Read a triple and check for consistency. */
+        err = fscanf(fp, "%d %d %s", &low, &size, attrib);
+        if (err == EOF) {
+            break;
+        } else if (err != 3) {
+            Mtr_FreeTree(root);
+            return(NULL);
+        } else if (low < 0 || low+size > nleaves || size < 1) {
+            Mtr_FreeTree(root);
+            return(NULL);
+        } else if (strlen(attrib) > 8 * sizeof(MtrHalfWord)) {
+            /* Not enough bits in the flags word to store these many
+            ** attributes. */
+            Mtr_FreeTree(root);
+            return(NULL);
+        }
+
+        /* Parse the flag string. Currently all flags are permitted,
+        ** to make debugging easier. Normally, specifying NEWNODE
+        ** wouldn't be allowed. */
+        flags = MTR_DEFAULT;
+        for (c=attrib; *c != 0; c++) {
+            switch (*c) {
+            case 'D':
+                break;
+            case 'F':
+                flags |= MTR_FIXED;
+                break;
+            case 'N':
+                flags |= MTR_NEWNODE;
+                break;
+            case 'S':
+                flags |= MTR_SOFT;
+                break;
+            case 'T':
+                flags |= MTR_TERMINAL;
+                break;
+            default:
+                return NULL;
+            }
+        }
+        node = Mtr_MakeGroup(root, (MtrHalfWord) low, (MtrHalfWord) size,
+                             flags);
+        if (node == NULL) {
+            Mtr_FreeTree(root);
+            return(NULL);
+        }
+    }
+
+    return(root);
+
+} /* end of Mtr_ReadGroups */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adjusts the low fields of a node and its descendants.]
+
+  Description [Adjusts the low fields of a node and its
+  descendants. Adds shift to low of each node. Checks that no
+  out-of-bounds values result.  Returns 1 in case of success; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+mtrShiftHL(
+  MtrNode * node /* group tree node */,
+  int  shift /* amount by which low should be changed */)
+{
+    MtrNode *auxnode;
+    int low;
+
+    low = (int) node->low;
+
+
+    low += shift;
+
+    if (low < 0 || low + (int) (node->size - 1) > (int) MTR_MAXHIGH) return(0);
+
+    node->low = (MtrHalfWord) low;
+
+    if (!MTR_TEST(node,MTR_TERMINAL) && node->child != NULL) {
+        auxnode = node->child;
+        do {
+            if (!mtrShiftHL(auxnode,shift)) return(0);
+            auxnode = auxnode->younger;
+        } while (auxnode != NULL);
+    }
+
+    return(1);
+
+} /* end of mtrShiftHL */
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/bdd/mtr/mtrInt.h b/abc-build/src/bdd/mtr/mtrInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/mtr/mtrInt.h
@@ -0,0 +1,94 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [mtrInt.h]
+
+  PackageName [mtr]
+
+  Synopsis    [Internal data structures of the mtr package]
+
+  Description [In this package all definitions are external.]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+  Revision    [$Id: mtrInt.h,v 1.2 2004/08/13 18:15:12 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef ABC__bdd__mtr__mtrInt_h
+#define ABC__bdd__mtr__mtrInt_h
+
+#include "mtr.h"
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+ABC_NAMESPACE_HEADER_START
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+ABC_NAMESPACE_HEADER_END
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _MTRINT */
diff --git a/abc-build/src/bdd/parse/module.make b/abc-build/src/bdd/parse/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/parse/module.make
@@ -0,0 +1,3 @@
+SRC +=  src/bdd/parse/parseCore.c \
+	src/bdd/parse/parseEqn.c \
+	src/bdd/parse/parseStack.c
diff --git a/abc-build/src/bdd/parse/parse.h b/abc-build/src/bdd/parse/parse.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/parse/parse.h
@@ -0,0 +1,62 @@
+/**CFile****************************************************************
+
+  FileName    [parse.h]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Parsing symbolic Boolean formulas into BDDs.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: parse.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__bdd__parse__parse_h
+#define ABC__bdd__parse__parse_h
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== parseCore.c =============================================================*/
+extern DdNode * Parse_FormulaParser( FILE * pOutput, char * pFormula, int nVars, int nRanks, 
+      char * ppVarNames[], DdManager * dd, DdNode * pbVars[] );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/bdd/parse/parseCore.c b/abc-build/src/bdd/parse/parseCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/parse/parseCore.c
@@ -0,0 +1,536 @@
+/**CFile****************************************************************
+
+  FileNameIn  [parseCore.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Boolean formula parser.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: parseCore.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+/*
+        Some aspects of Boolean Formula Parser:
+
+ 1) The names in the boolean formulas can be any strings of symbols
+    that start with char or underscore and contain chars, digits 
+    and underscores: For example: 1) a&b <+> c'&d => a + b;   
+    2) a1 b2 c3' dummy' + (a2+b2')c3 dummy
+ 2) Constant values 0 and 1 can be used just like normal variables
+ 3) Any boolean operator (listed below) and parantheses can be used
+    any number of times provided there are equal number of opening
+    and closing parantheses.
+ 4) By default, absence of an operator between vars and before and 
+    after parantheses is taken for AND. 
+ 5) Both complementation prefix and complementation suffix can be 
+    used at the same time (but who needs this?)
+ 6) Spaces (tabs, end-of-lines) may be inserted anywhere,
+    except between characters of the operations: <=>, =>, <=, <+>
+ 7) The stack size is defined by macro STACKSIZE and is used by the 
+    stack constructor.
+*/
+ 
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#include "parseInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+// the list of operation symbols to be used in expressions
+#define PARSE_SYM_OPEN    '('   // opening paranthesis
+#define PARSE_SYM_CLOSE   ')'   // closing paranthesis
+#define PARSE_SYM_LOWER   '['   // shifts one rank down 
+#define PARSE_SYM_RAISE   ']'   // shifts one rank up
+#define PARSE_SYM_CONST0  '0'   // constant 0
+#define PARSE_SYM_CONST1  '1'   // constant 1
+#define PARSE_SYM_NEGBEF1 '!'   // negation before the variable
+#define PARSE_SYM_NEGBEF2 '~'   // negation before the variable
+#define PARSE_SYM_NEGAFT  '\''  // negation after the variable
+#define PARSE_SYM_AND1    '&'   // logic AND
+#define PARSE_SYM_AND2    '*'   // logic AND
+#define PARSE_SYM_XOR1    '<'   // logic EXOR   (the 1st symbol) 
+#define PARSE_SYM_XOR2    '+'   // logic EXOR   (the 2nd symbol)
+#define PARSE_SYM_XOR3    '>'   // logic EXOR   (the 3rd symbol)
+#define PARSE_SYM_XOR     '^'   // logic XOR
+#define PARSE_SYM_OR1     '+'   // logic OR
+#define PARSE_SYM_OR2     '|'   // logic OR
+#define PARSE_SYM_EQU1    '<'   // equvalence   (the 1st symbol)
+#define PARSE_SYM_EQU2    '='   // equvalence   (the 2nd symbol)
+#define PARSE_SYM_EQU3    '>'   // equvalence   (the 3rd symbol)
+#define PARSE_SYM_FLR1    '='   // implication  (the 1st symbol)
+#define PARSE_SYM_FLR2    '>'   // implication  (the 2nd symbol)
+#define PARSE_SYM_FLL1    '<'   // backward imp (the 1st symbol)
+#define PARSE_SYM_FLL2    '='   // backward imp (the 2nd symbol)
+// PARSE_SYM_FLR1 and PARSE_SYM_FLR2 should be the same as PARSE_SYM_EQU2 and PARSE_SYM_EQU3!
+
+// the list of opcodes (also specifying operation precedence)
+#define PARSE_OPER_NEG 10  // negation
+#define PARSE_OPER_AND  9  // logic AND
+#define PARSE_OPER_XOR  8  // logic EXOR   (a'b | ab')   
+#define PARSE_OPER_OR   7  // logic OR
+#define PARSE_OPER_EQU  6  // equvalence   (a'b'| ab )
+#define PARSE_OPER_FLR  5  // implication  ( a' | b )
+#define PARSE_OPER_FLL  4  // backward imp ( 'b | a )
+#define PARSE_OPER_MARK 1  // OpStack token standing for an opening paranthesis
+
+// these are values of the internal Flag
+#define PARSE_FLAG_START  1 // after the opening parenthesis 
+#define PARSE_FLAG_VAR    2 // after operation is received
+#define PARSE_FLAG_OPER   3 // after operation symbol is received
+#define PARSE_FLAG_ERROR  4 // when error is detected
+
+#define STACKSIZE 1000
+
+static DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the BDD corresponding to the formula in language L.]
+
+  Description [Takes the stream to output messages, the formula, the number
+  variables and the rank in the formula. The array of variable names is also 
+  given. The BDD manager and the elementary 0-rank variable are the last two
+  arguments. The manager should have at least as many variables as 
+  nVars * (nRanks + 1). The 0-rank variables should have numbers larger 
+  than the variables of other ranks.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Parse_FormulaParser( FILE * pOutput, char * pFormulaInit, int nVars, int nRanks, 
+      char * ppVarNames[], DdManager * dd, DdNode * pbVars[] )
+{
+    char * pFormula;
+    Parse_StackFn_t * pStackFn;
+    Parse_StackOp_t * pStackOp;
+    DdNode * bFunc, * bTemp;
+    char * pTemp;
+    int nParans, fFound, Flag;
+	int Oper, Oper1, Oper2;
+    int i, fLower;
+    int v = -1; // Suppress "might be used uninitialized"
+
+    // make sure that the number of vars and ranks is correct
+    if ( nVars * (nRanks + 1) > dd->size )
+    {
+        printf( "Parse_FormulaParser(): The BDD manager does not have enough variables.\n" );
+        return NULL;
+    }
+
+    // make sure that the number of opening and closing parantheses is the same
+    nParans = 0;
+    for ( pTemp = pFormulaInit; *pTemp; pTemp++ )
+        if ( *pTemp == '(' )
+            nParans++;
+        else if ( *pTemp == ')' )
+            nParans--;
+    if ( nParans != 0 )
+    {
+        fprintf( pOutput, "Parse_FormulaParser(): Different number of opening and closing parantheses ().\n" );
+        return NULL;
+    }
+
+    nParans = 0;
+    for ( pTemp = pFormulaInit; *pTemp; pTemp++ )
+        if ( *pTemp == '[' )
+            nParans++;
+        else if ( *pTemp == ']' )
+            nParans--;
+    if ( nParans != 0 )
+    {
+        fprintf( pOutput, "Parse_FormulaParser(): Different number of opening and closing brackets [].\n" );
+        return NULL;
+    }
+
+    // copy the formula
+    pFormula = ABC_ALLOC( char, strlen(pFormulaInit) + 3 );
+    sprintf( pFormula, "(%s)", pFormulaInit );
+
+    // start the stacks
+    pStackFn = Parse_StackFnStart( STACKSIZE );
+    pStackOp = Parse_StackOpStart( STACKSIZE );
+
+    Flag = PARSE_FLAG_START;
+    fLower = 0;
+    for ( pTemp = pFormula; *pTemp; pTemp++ )
+	{
+		switch ( *pTemp )
+	    {
+		// skip all spaces, tabs, and end-of-lines
+        case ' ':
+        case '\t':
+        case '\r':
+        case '\n':
+			continue;
+
+		// treat Constant 0 as a variable
+		case PARSE_SYM_CONST0:
+		    Parse_StackFnPush( pStackFn, b0 );   Cudd_Ref( b0 );
+			if ( Flag == PARSE_FLAG_VAR )
+			{
+				fprintf( pOutput, "Parse_FormulaParser(): No operation symbol before constant 0.\n" );
+				Flag = PARSE_FLAG_ERROR; 
+                break;
+			}
+            Flag = PARSE_FLAG_VAR; 
+            break;
+
+		// the same for Constant 1
+		case PARSE_SYM_CONST1:
+		    Parse_StackFnPush( pStackFn, b1 );    Cudd_Ref( b1 );
+			if ( Flag == PARSE_FLAG_VAR )
+			{
+				fprintf( pOutput, "Parse_FormulaParser(): No operation symbol before constant 1.\n" );
+				Flag = PARSE_FLAG_ERROR; 
+                break;
+			}
+            Flag = PARSE_FLAG_VAR; 
+            break;
+
+		case PARSE_SYM_NEGBEF1:
+		case PARSE_SYM_NEGBEF2:
+			if ( Flag == PARSE_FLAG_VAR )
+			{// if NEGBEF follows a variable, AND is assumed
+				Parse_StackOpPush( pStackOp, PARSE_OPER_AND );
+				Flag = PARSE_FLAG_OPER;
+			}
+    		Parse_StackOpPush( pStackOp, PARSE_OPER_NEG );
+			break;
+
+		case PARSE_SYM_NEGAFT:
+			if ( Flag != PARSE_FLAG_VAR )
+			{// if there is no variable before NEGAFT, it is an error
+				fprintf( pOutput, "Parse_FormulaParser(): No variable is specified before the negation suffix.\n" );
+				Flag = PARSE_FLAG_ERROR; 
+                break;
+			}
+			else // if ( Flag == PARSE_FLAG_VAR )
+				Parse_StackFnPush( pStackFn, Cudd_Not( Parse_StackFnPop(pStackFn) ) );
+			break;
+
+        case PARSE_SYM_AND1:
+        case PARSE_SYM_AND2:
+        case PARSE_SYM_OR1:
+        case PARSE_SYM_OR2:
+        case PARSE_SYM_XOR:
+			if ( Flag != PARSE_FLAG_VAR )
+			{
+				fprintf( pOutput, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR.\n" );
+				Flag = PARSE_FLAG_ERROR; 
+                break;
+			}
+			if ( *pTemp == PARSE_SYM_AND1 || *pTemp == PARSE_SYM_AND2 )
+				Parse_StackOpPush( pStackOp, PARSE_OPER_AND );
+			else if ( *pTemp == PARSE_SYM_OR1 || *pTemp == PARSE_SYM_OR2 )
+				Parse_StackOpPush( pStackOp, PARSE_OPER_OR );
+			else //if ( Str[Pos] == PARSE_SYM_XOR )
+				Parse_StackOpPush( pStackOp, PARSE_OPER_XOR );
+			Flag = PARSE_FLAG_OPER; 
+            break;
+
+		case PARSE_SYM_EQU1:
+			if ( Flag != PARSE_FLAG_VAR )
+			{ 
+				fprintf( pOutput, "Parse_FormulaParser(): There is no variable before Equivalence or Implication\n" );
+				Flag = PARSE_FLAG_ERROR; break;
+			}
+			if ( pTemp[1] == PARSE_SYM_EQU2 )
+			{ // check what is the next symbol in the string
+                pTemp++; 
+				if ( pTemp[1] == PARSE_SYM_EQU3 )
+			    {   
+                    pTemp++; 
+                    Parse_StackOpPush( pStackOp, PARSE_OPER_EQU ); 
+                }
+			    else
+			    {   
+                    Parse_StackOpPush( pStackOp, PARSE_OPER_FLL ); 
+                }
+			}
+			else if ( pTemp[1] == PARSE_SYM_XOR2 )
+            {
+                pTemp++; 
+				if ( pTemp[1] == PARSE_SYM_XOR3 )
+			    {   
+                    pTemp++; 
+                    Parse_StackOpPush( pStackOp, PARSE_OPER_XOR ); 
+                }
+			    else
+			    {   
+				    fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c%c\"\n", PARSE_SYM_EQU1, PARSE_SYM_XOR2 );
+				    Flag = PARSE_FLAG_ERROR; 
+                    break;
+                }
+            }
+			else
+			{
+				fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c\"\n", PARSE_SYM_EQU1 );
+				Flag = PARSE_FLAG_ERROR; 
+                break;
+			}
+			Flag = PARSE_FLAG_OPER; 
+            break;
+
+		case PARSE_SYM_EQU2:
+			if ( Flag != PARSE_FLAG_VAR )
+			{
+				fprintf( pOutput, "Parse_FormulaParser(): There is no variable before Reverse Implication\n" );
+				Flag = PARSE_FLAG_ERROR; 
+                break;
+			}
+			if ( pTemp[1] == PARSE_SYM_EQU3 )
+            {   
+                pTemp++; 
+                Parse_StackOpPush( pStackOp, PARSE_OPER_FLR ); 
+            }
+			else
+			{
+				fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c\"\n", PARSE_SYM_EQU2 );
+				Flag = PARSE_FLAG_ERROR; 
+                break;
+			}
+			Flag = PARSE_FLAG_OPER; 
+            break;
+
+        case PARSE_SYM_LOWER:
+		case PARSE_SYM_OPEN:
+			if ( Flag == PARSE_FLAG_VAR )
+				Parse_StackOpPush( pStackOp, PARSE_OPER_AND );
+			Parse_StackOpPush( pStackOp, PARSE_OPER_MARK );
+			// after an opening bracket, it feels like starting over again
+			Flag = PARSE_FLAG_START; 
+            break;
+
+        case PARSE_SYM_RAISE:
+            fLower = 1;
+		case PARSE_SYM_CLOSE:
+			if ( !Parse_StackOpIsEmpty( pStackOp ) )
+            {
+				while ( 1 )
+			    {
+				    if ( Parse_StackOpIsEmpty( pStackOp ) )
+					{
+						fprintf( pOutput, "Parse_FormulaParser(): There is no opening paranthesis\n" );
+						Flag = PARSE_FLAG_ERROR; 
+                        break;
+					}
+					Oper = Parse_StackOpPop( pStackOp );
+					if ( Oper == PARSE_OPER_MARK )
+						break;
+
+                    // perform the given operation
+                    if ( Parse_ParserPerformTopOp( dd, pStackFn, Oper ) == NULL )
+	                {
+		                fprintf( pOutput, "Parse_FormulaParser(): Unknown operation\n" );
+                        ABC_FREE( pFormula );
+		                return NULL;
+	                }
+			    }
+
+                if ( fLower )
+                {
+                    bFunc = (DdNode *)Parse_StackFnPop( pStackFn );
+                    bFunc = Extra_bddMove( dd, bTemp = bFunc, -nVars );   Cudd_Ref( bFunc );
+                    Cudd_RecursiveDeref( dd, bTemp );
+					Parse_StackFnPush( pStackFn, bFunc );
+                }
+            }
+		    else
+			{
+				fprintf( pOutput, "Parse_FormulaParser(): There is no opening paranthesis\n" );
+				Flag = PARSE_FLAG_ERROR; 
+                break;
+			}
+			if ( Flag != PARSE_FLAG_ERROR )
+			    Flag = PARSE_FLAG_VAR; 
+            fLower = 0;
+			break;
+
+
+		default:
+            // scan the next name
+/*
+            fFound = 0;
+            for ( i = 0; pTemp[i] && pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n'; i++ )
+            {
+                for ( v = 0; v < nVars; v++ )
+                    if ( strncmp( pTemp, ppVarNames[v], i+1 ) == 0 && strlen(ppVarNames[v]) == (unsigned)(i+1) )
+                    {
+                        pTemp += i;
+                        fFound = 1;
+                        break;
+                    }
+                if ( fFound )
+                    break;
+            }
+*/ 
+            // bug fix by SV (9/11/08)
+            fFound = 0;
+            for ( i = 0; pTemp[i] && pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' && 
+                         pTemp[i] != PARSE_SYM_AND1 && pTemp[i] != PARSE_SYM_AND2 && pTemp[i] != PARSE_SYM_XOR1 &&
+                         pTemp[i] != PARSE_SYM_XOR2 && pTemp[i] != PARSE_SYM_XOR3 && pTemp[i] != PARSE_SYM_XOR  &&
+                         pTemp[i] != PARSE_SYM_OR1  && pTemp[i] != PARSE_SYM_OR2  && pTemp[i] != PARSE_SYM_CLOSE &&
+                         pTemp[i] != PARSE_SYM_NEGAFT;
+                  i++ )
+            {}
+            for ( v = 0; v < nVars; v++ ) 
+            {
+                if ( strncmp( pTemp, ppVarNames[v], i ) == 0 && strlen(ppVarNames[v]) == (unsigned)(i) )
+                {
+                    pTemp += i-1;
+                    fFound = 1;
+                    break;
+                }
+            }
+
+            if ( !fFound )
+			{ 
+				fprintf( pOutput, "Parse_FormulaParser(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); 
+				Flag = PARSE_FLAG_ERROR; 
+                break; 
+			}
+			// assume operation AND, if vars follow one another
+			if ( Flag == PARSE_FLAG_VAR )
+				Parse_StackOpPush( pStackOp, PARSE_OPER_AND );
+			Parse_StackFnPush( pStackFn, pbVars[v] );  Cudd_Ref( pbVars[v] );
+            Flag = PARSE_FLAG_VAR; 
+            break;
+	    }
+
+		if ( Flag == PARSE_FLAG_ERROR )
+			break;      // error exit
+		else if ( Flag == PARSE_FLAG_START )
+			continue;  //  go on parsing
+		else if ( Flag == PARSE_FLAG_VAR )
+			while ( 1 )
+			{  // check if there are negations in the OpStack     
+				if ( Parse_StackOpIsEmpty(pStackOp) )
+					break;
+                Oper = Parse_StackOpPop( pStackOp );
+				if ( Oper != PARSE_OPER_NEG )
+                {
+					Parse_StackOpPush( pStackOp, Oper );
+					break;
+                }
+				else
+				{
+      				Parse_StackFnPush( pStackFn, Cudd_Not(Parse_StackFnPop(pStackFn)) );
+				}
+			}
+		else // if ( Flag == PARSE_FLAG_OPER )
+			while ( 1 )
+			{  // execute all the operations in the OpStack
+			   // with precedence higher or equal than the last one
+				Oper1 = Parse_StackOpPop( pStackOp ); // the last operation
+				if ( Parse_StackOpIsEmpty(pStackOp) ) 
+				{  // if it is the only operation, push it back
+					Parse_StackOpPush( pStackOp, Oper1 );
+					break;
+				}
+				Oper2 = Parse_StackOpPop( pStackOp ); // the operation before the last one
+				if ( Oper2 >= Oper1 )  
+				{  // if Oper2 precedence is higher or equal, execute it
+//					Parse_StackPush( pStackFn,  Operation( FunStack.Pop(), FunStack.Pop(), Oper2 ) );
+                    if ( Parse_ParserPerformTopOp( dd, pStackFn, Oper2 ) == NULL )
+	                {
+		                fprintf( pOutput, "Parse_FormulaParser(): Unknown operation\n" );
+                        ABC_FREE( pFormula );
+		                return NULL;
+	                }
+					Parse_StackOpPush( pStackOp,  Oper1 );     // push the last operation back
+				}
+				else
+				{  // if Oper2 precedence is lower, push them back and done
+					Parse_StackOpPush( pStackOp, Oper2 );
+					Parse_StackOpPush( pStackOp, Oper1 );
+					break;
+				}
+			}
+    }
+
+	if ( Flag != PARSE_FLAG_ERROR )
+    {
+		if ( !Parse_StackFnIsEmpty(pStackFn) )
+	    {	
+			bFunc = (DdNode *)Parse_StackFnPop(pStackFn);
+			if ( Parse_StackFnIsEmpty(pStackFn) )
+				if ( Parse_StackOpIsEmpty(pStackOp) )
+                {
+                    Parse_StackFnFree(pStackFn);
+                    Parse_StackOpFree(pStackOp);
+                    Cudd_Deref( bFunc );
+                    ABC_FREE( pFormula );
+					return bFunc;
+                }
+				else
+					fprintf( pOutput, "Parse_FormulaParser(): Something is left in the operation stack\n" );
+			else
+				fprintf( pOutput, "Parse_FormulaParser(): Something is left in the function stack\n" );
+	    }
+	    else
+			fprintf( pOutput, "Parse_FormulaParser(): The input string is empty\n" );
+    }
+    ABC_FREE( pFormula );
+	return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs the operation on the top entries in the stack.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper )
+{
+    DdNode * bArg1, * bArg2, * bFunc;
+    // perform the given operation
+    bArg2 = (DdNode *)Parse_StackFnPop( pStackFn );
+    bArg1 = (DdNode *)Parse_StackFnPop( pStackFn );
+	if ( Oper == PARSE_OPER_AND )
+		bFunc = Cudd_bddAnd( dd, bArg1, bArg2 );
+	else if ( Oper == PARSE_OPER_XOR )
+		bFunc = Cudd_bddXor( dd, bArg1, bArg2 );
+	else if ( Oper == PARSE_OPER_OR )
+		bFunc = Cudd_bddOr( dd, bArg1, bArg2 );
+	else if ( Oper == PARSE_OPER_EQU )
+		bFunc = Cudd_bddXnor( dd, bArg1, bArg2 );
+	else if ( Oper == PARSE_OPER_FLR )
+		bFunc = Cudd_bddOr( dd, Cudd_Not(bArg1), bArg2 );
+	else if ( Oper == PARSE_OPER_FLL )
+		bFunc = Cudd_bddOr( dd, Cudd_Not(bArg2), bArg1 );
+	else
+		return NULL;
+    Cudd_Ref( bFunc );
+    Cudd_RecursiveDeref( dd, bArg1 );
+    Cudd_RecursiveDeref( dd, bArg2 );
+	Parse_StackFnPush( pStackFn,  bFunc );
+    return bFunc;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/parse/parseEqn.c b/abc-build/src/bdd/parse/parseEqn.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/parse/parseEqn.c
@@ -0,0 +1,358 @@
+/**CFile****************************************************************
+
+  FileNameIn  [parseEqn.c]
+
+  PackageName [ABC: Logic synthesis and verification system.]
+
+  Synopsis    [Boolean formula parser.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - December 18, 2006.]
+
+  Revision    [$Id: parseEqn.c,v 1.0 2006/12/18 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#include "parseInt.h"
+#include "misc/vec/vec.h"
+#include "aig/hop/hop.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+// the list of operation symbols to be used in expressions
+#define PARSE_EQN_SYM_OPEN    '('   // opening paranthesis
+#define PARSE_EQN_SYM_CLOSE   ')'   // closing paranthesis
+#define PARSE_EQN_SYM_CONST0  '0'   // constant 0
+#define PARSE_EQN_SYM_CONST1  '1'   // constant 1
+#define PARSE_EQN_SYM_NEG     '!'   // negation before the variable
+#define PARSE_EQN_SYM_AND     '*'   // logic AND
+#define PARSE_EQN_SYM_OR      '+'   // logic OR
+
+// the list of opcodes (also specifying operation precedence)
+#define PARSE_EQN_OPER_NEG    10    // negation
+#define PARSE_EQN_OPER_AND     9    // logic AND
+#define PARSE_EQN_OPER_OR      7    // logic OR
+#define PARSE_EQN_OPER_MARK    1    // OpStack token standing for an opening paranthesis
+
+// these are values of the internal Flag
+#define PARSE_EQN_FLAG_START   1    // after the opening parenthesis 
+#define PARSE_EQN_FLAG_VAR     2    // after operation is received
+#define PARSE_EQN_FLAG_OPER    3    // after operation symbol is received
+#define PARSE_EQN_FLAG_ERROR   4    // when error is detected
+
+#define PARSE_EQN_STACKSIZE 1000
+
+static Hop_Obj_t * Parse_ParserPerformTopOp( Hop_Man_t * pMan, Parse_StackFn_t * pStackFn, int Oper );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the AIG corresponding to the equation.]
+
+  Description [Takes the stream to output messages, the formula, the vector
+  of variable names and the AIG manager.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Parse_FormulaParserEqn( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan )
+{
+    char * pFormula;
+    Parse_StackFn_t * pStackFn;
+    Parse_StackOp_t * pStackOp;
+    Hop_Obj_t * gFunc;
+    char * pTemp, * pName;
+    int nParans, fFound, Flag;
+	int Oper, Oper1, Oper2;
+    int i, v;
+
+    // make sure that the number of opening and closing parantheses is the same
+    nParans = 0;
+    for ( pTemp = pFormInit; *pTemp; pTemp++ )
+        if ( *pTemp == '(' )
+            nParans++;
+        else if ( *pTemp == ')' )
+            nParans--;
+    if ( nParans != 0 )
+    {
+        fprintf( pOutput, "Parse_FormulaParserEqn(): Different number of opening and closing parantheses ().\n" );
+        return NULL;
+    }
+
+    // copy the formula
+    pFormula = ABC_ALLOC( char, strlen(pFormInit) + 3 );
+    sprintf( pFormula, "(%s)", pFormInit );
+
+    // start the stacks
+    pStackFn = Parse_StackFnStart( PARSE_EQN_STACKSIZE );
+    pStackOp = Parse_StackOpStart( PARSE_EQN_STACKSIZE );
+
+    Flag = PARSE_EQN_FLAG_START;
+    for ( pTemp = pFormula; *pTemp; pTemp++ )
+	{
+		switch ( *pTemp )
+	    {
+		// skip all spaces, tabs, and end-of-lines
+        case ' ':
+        case '\t':
+        case '\r':
+        case '\n':
+			continue;
+		case PARSE_EQN_SYM_CONST0:
+		    Parse_StackFnPush( pStackFn, Hop_ManConst0(pMan) );  // Cudd_Ref( b0 );
+			if ( Flag == PARSE_EQN_FLAG_VAR )
+			{
+				fprintf( pOutput, "Parse_FormulaParserEqn(): No operation symbol before constant 0.\n" );
+				Flag = PARSE_EQN_FLAG_ERROR; 
+                break;
+			}
+            Flag = PARSE_EQN_FLAG_VAR; 
+            break;
+		case PARSE_EQN_SYM_CONST1:
+		    Parse_StackFnPush( pStackFn, Hop_ManConst1(pMan) );  //  Cudd_Ref( b1 );
+			if ( Flag == PARSE_EQN_FLAG_VAR )
+			{
+				fprintf( pOutput, "Parse_FormulaParserEqn(): No operation symbol before constant 1.\n" );
+				Flag = PARSE_EQN_FLAG_ERROR; 
+                break;
+			}
+            Flag = PARSE_EQN_FLAG_VAR; 
+            break;
+		case PARSE_EQN_SYM_NEG:
+			if ( Flag == PARSE_EQN_FLAG_VAR )
+			{// if NEGBEF follows a variable, AND is assumed
+				Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND );
+				Flag = PARSE_EQN_FLAG_OPER;
+			}
+    		Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_NEG );
+			break;
+        case PARSE_EQN_SYM_AND:
+        case PARSE_EQN_SYM_OR:
+			if ( Flag != PARSE_EQN_FLAG_VAR )
+			{
+				fprintf( pOutput, "Parse_FormulaParserEqn(): There is no variable before AND, EXOR, or OR.\n" );
+				Flag = PARSE_EQN_FLAG_ERROR; 
+                break;
+			}
+			if ( *pTemp == PARSE_EQN_SYM_AND )
+				Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND );
+			else //if ( *pTemp == PARSE_EQN_SYM_OR )
+				Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_OR );
+			Flag = PARSE_EQN_FLAG_OPER; 
+            break;
+		case PARSE_EQN_SYM_OPEN:
+			if ( Flag == PARSE_EQN_FLAG_VAR )
+            {
+//				Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND );
+				fprintf( pOutput, "Parse_FormulaParserEqn(): An opening paranthesis follows a var without operation sign.\n" ); 
+				Flag = PARSE_EQN_FLAG_ERROR; 
+                break; 
+            }
+			Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_MARK );
+			// after an opening bracket, it feels like starting over again
+			Flag = PARSE_EQN_FLAG_START; 
+            break;
+		case PARSE_EQN_SYM_CLOSE:
+			if ( !Parse_StackOpIsEmpty( pStackOp ) )
+            {
+				while ( 1 )
+			    {
+				    if ( Parse_StackOpIsEmpty( pStackOp ) )
+					{
+						fprintf( pOutput, "Parse_FormulaParserEqn(): There is no opening paranthesis\n" );
+						Flag = PARSE_EQN_FLAG_ERROR; 
+                        break;
+					}
+					Oper = Parse_StackOpPop( pStackOp );
+					if ( Oper == PARSE_EQN_OPER_MARK )
+						break;
+
+                    // perform the given operation
+                    if ( Parse_ParserPerformTopOp( pMan, pStackFn, Oper ) == NULL )
+	                {
+                        Parse_StackFnFree( pStackFn );
+                        Parse_StackOpFree( pStackOp );
+		                fprintf( pOutput, "Parse_FormulaParserEqn(): Unknown operation\n" );
+                        ABC_FREE( pFormula );
+		                return NULL;
+	                }
+			    }
+            }
+		    else
+			{
+				fprintf( pOutput, "Parse_FormulaParserEqn(): There is no opening paranthesis\n" );
+				Flag = PARSE_EQN_FLAG_ERROR; 
+                break;
+			}
+			if ( Flag != PARSE_EQN_FLAG_ERROR )
+			    Flag = PARSE_EQN_FLAG_VAR; 
+			break;
+
+
+		default:
+            // scan the next name
+            for ( i = 0; pTemp[i] && 
+                         pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' &&
+                         pTemp[i] != PARSE_EQN_SYM_AND && pTemp[i] != PARSE_EQN_SYM_OR && pTemp[i] != PARSE_EQN_SYM_CLOSE; i++ )
+              {
+				    if ( pTemp[i] == PARSE_EQN_SYM_NEG || pTemp[i] == PARSE_EQN_SYM_OPEN )
+				    {
+					    fprintf( pOutput, "Parse_FormulaParserEqn(): The negation sign or an opening paranthesis inside the variable name.\n" );
+					    Flag = PARSE_EQN_FLAG_ERROR; 
+                        break;
+				    }
+              }
+            // variable name is found
+            fFound = 0;
+            Vec_PtrForEachEntry( char *, vVarNames, pName, v )
+                if ( strncmp(pTemp, pName, i) == 0 && strlen(pName) == (unsigned)i )
+                {
+                    pTemp += i-1;
+                    fFound = 1;
+                    break;
+                }
+            if ( !fFound )
+			{ 
+				fprintf( pOutput, "Parse_FormulaParserEqn(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); 
+				Flag = PARSE_EQN_FLAG_ERROR; 
+                break; 
+			}
+			if ( Flag == PARSE_EQN_FLAG_VAR )
+            {
+				fprintf( pOutput, "Parse_FormulaParserEqn(): The variable name \"%s\" follows another var without operation sign.\n", pTemp ); 
+				Flag = PARSE_EQN_FLAG_ERROR; 
+                break; 
+            }
+			Parse_StackFnPush( pStackFn, Hop_IthVar( pMan, v ) ); // Cudd_Ref( pbVars[v] );
+            Flag = PARSE_EQN_FLAG_VAR; 
+            break;
+	    }
+
+		if ( Flag == PARSE_EQN_FLAG_ERROR )
+			break;      // error exit
+		else if ( Flag == PARSE_EQN_FLAG_START )
+			continue;  //  go on parsing
+		else if ( Flag == PARSE_EQN_FLAG_VAR )
+			while ( 1 )
+			{  // check if there are negations in the OpStack     
+				if ( Parse_StackOpIsEmpty(pStackOp) )
+					break;
+                Oper = Parse_StackOpPop( pStackOp );
+				if ( Oper != PARSE_EQN_OPER_NEG )
+                {
+					Parse_StackOpPush( pStackOp, Oper );
+					break;
+                }
+				else
+				{
+      				Parse_StackFnPush( pStackFn, Hop_Not((Hop_Obj_t *)Parse_StackFnPop(pStackFn)) );
+				}
+			}
+		else // if ( Flag == PARSE_EQN_FLAG_OPER )
+			while ( 1 )
+			{  // execute all the operations in the OpStack
+			   // with precedence higher or equal than the last one
+				Oper1 = Parse_StackOpPop( pStackOp ); // the last operation
+				if ( Parse_StackOpIsEmpty(pStackOp) ) 
+				{  // if it is the only operation, push it back
+					Parse_StackOpPush( pStackOp, Oper1 );
+					break;
+				}
+				Oper2 = Parse_StackOpPop( pStackOp ); // the operation before the last one
+				if ( Oper2 >= Oper1 )  
+				{  // if Oper2 precedence is higher or equal, execute it
+                    if ( Parse_ParserPerformTopOp( pMan, pStackFn, Oper2 ) == NULL )
+	                {
+		                fprintf( pOutput, "Parse_FormulaParserEqn(): Unknown operation\n" );
+                        ABC_FREE( pFormula );
+                        Parse_StackFnFree( pStackFn );
+                        Parse_StackOpFree( pStackOp );
+		                return NULL;
+	                }
+					Parse_StackOpPush( pStackOp,  Oper1 );     // push the last operation back
+				}
+				else
+				{  // if Oper2 precedence is lower, push them back and done
+					Parse_StackOpPush( pStackOp, Oper2 );
+					Parse_StackOpPush( pStackOp, Oper1 );
+					break;
+				}
+			}
+    }
+
+	if ( Flag != PARSE_EQN_FLAG_ERROR )
+    {
+		if ( !Parse_StackFnIsEmpty(pStackFn) )
+	    {	
+			gFunc = (Hop_Obj_t *)Parse_StackFnPop(pStackFn);
+			if ( Parse_StackFnIsEmpty(pStackFn) )
+				if ( Parse_StackOpIsEmpty(pStackOp) )
+                {
+                    Parse_StackFnFree(pStackFn);
+                    Parse_StackOpFree(pStackOp);
+//                    Cudd_Deref( gFunc );
+                    ABC_FREE( pFormula );
+					return gFunc;
+                }
+				else
+					fprintf( pOutput, "Parse_FormulaParserEqn(): Something is left in the operation stack\n" );
+			else
+				fprintf( pOutput, "Parse_FormulaParserEqn(): Something is left in the function stack\n" );
+	    }
+	    else
+			fprintf( pOutput, "Parse_FormulaParserEqn(): The input string is empty\n" );
+    }
+    ABC_FREE( pFormula );
+	return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs the operation on the top entries in the stack.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Parse_ParserPerformTopOp( Hop_Man_t * pMan, Parse_StackFn_t * pStackFn, int Oper )
+{
+    Hop_Obj_t * gArg1, * gArg2, * gFunc;
+    // perform the given operation
+    gArg2 = (Hop_Obj_t *)Parse_StackFnPop( pStackFn );
+    gArg1 = (Hop_Obj_t *)Parse_StackFnPop( pStackFn );
+	if ( Oper == PARSE_EQN_OPER_AND )
+		gFunc = Hop_And( pMan, gArg1, gArg2 );
+	else if ( Oper == PARSE_EQN_OPER_OR )
+		gFunc = Hop_Or( pMan, gArg1, gArg2 );
+	else
+		return NULL;
+//    Cudd_Ref( gFunc );
+//    Cudd_RecursiveDeref( dd, gArg1 );
+//    Cudd_RecursiveDeref( dd, gArg2 );
+	Parse_StackFnPush( pStackFn,  gFunc );
+    return gFunc;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/parse/parseInt.h b/abc-build/src/bdd/parse/parseInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/parse/parseInt.h
@@ -0,0 +1,79 @@
+/**CFile****************************************************************
+
+  FileName    [parseInt.h]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Parsing symbolic Boolean formulas into BDDs.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: parseInt.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__bdd__parse__parseInt_h
+#define ABC__bdd__parse__parseInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+#include <stdio.h>
+#include "misc/extra/extraBdd.h"
+#include "parse.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct ParseStackFnStruct    Parse_StackFn_t;    // the function stack
+typedef struct ParseStackOpStruct    Parse_StackOp_t;    // the operation stack
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== parseStack.c =============================================================*/
+extern Parse_StackFn_t *  Parse_StackFnStart  ( int nDepth );
+extern int                Parse_StackFnIsEmpty( Parse_StackFn_t * p );
+extern void               Parse_StackFnPush   ( Parse_StackFn_t * p, void * bFunc );
+extern void *             Parse_StackFnPop    ( Parse_StackFn_t * p );
+extern void               Parse_StackFnFree   ( Parse_StackFn_t * p );
+
+extern Parse_StackOp_t *  Parse_StackOpStart  ( int nDepth );
+extern int                Parse_StackOpIsEmpty( Parse_StackOp_t * p );
+extern void               Parse_StackOpPush   ( Parse_StackOp_t * p, int Oper );
+extern int                Parse_StackOpPop    ( Parse_StackOp_t * p );
+extern void               Parse_StackOpFree   ( Parse_StackOp_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/bdd/parse/parseStack.c b/abc-build/src/bdd/parse/parseStack.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/parse/parseStack.c
@@ -0,0 +1,248 @@
+/**CFile****************************************************************
+
+  FileName    [parseStack.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Stacks used by the formula parser.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 18, 2003.]
+
+  Revision    [$Id: parseStack.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "parseInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+struct ParseStackFnStruct
+{
+    void **     pData;        // the array of elements
+    int           Top;          // the index
+    int           Size;         // the stack size
+};
+
+struct ParseStackOpStruct
+{
+    int *         pData;        // the array of elements
+    int           Top;          // the index
+    int           Size;         // the stack size
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the stack.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Parse_StackFn_t * Parse_StackFnStart( int nDepth )
+{
+    Parse_StackFn_t * p;
+    p = ABC_ALLOC( Parse_StackFn_t, 1 );
+    memset( p, 0, sizeof(Parse_StackFn_t) );
+    p->pData = ABC_ALLOC( void *, nDepth );
+    p->Size = nDepth;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks whether the stack is empty.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Parse_StackFnIsEmpty( Parse_StackFn_t * p )
+{
+    return (int)(p->Top == 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Pushes an entry into the stack.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Parse_StackFnPush( Parse_StackFn_t * p, void * bFunc )
+{
+    if ( p->Top >= p->Size )
+    {
+        printf( "Parse_StackFnPush(): Stack size is too small!\n" );
+        return;
+    }
+    p->pData[ p->Top++ ] = bFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Pops an entry out of the stack.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Parse_StackFnPop( Parse_StackFn_t * p )
+{
+    if ( p->Top == 0 )
+    {
+        printf( "Parse_StackFnPush(): Trying to extract data from the empty stack!\n" );
+        return NULL;
+    }
+    return p->pData[ --p->Top ];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the stack.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Parse_StackFnFree( Parse_StackFn_t * p )
+{
+    ABC_FREE( p->pData );
+    ABC_FREE( p );
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the stack.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Parse_StackOp_t * Parse_StackOpStart( int nDepth )
+{
+    Parse_StackOp_t * p;
+    p = ABC_ALLOC( Parse_StackOp_t, 1 );
+    memset( p, 0, sizeof(Parse_StackOp_t) );
+    p->pData = ABC_ALLOC( int, nDepth );
+    p->Size = nDepth;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks whether the stack is empty.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Parse_StackOpIsEmpty( Parse_StackOp_t * p )
+{
+    return (int)(p->Top == 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Pushes an entry into the stack.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Parse_StackOpPush( Parse_StackOp_t * p, int Oper )
+{
+    if ( p->Top >= p->Size )
+    {
+        printf( "Parse_StackOpPush(): Stack size is too small!\n" );
+        return;
+    }
+    p->pData[ p->Top++ ] = Oper;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Pops an entry out of the stack.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Parse_StackOpPop( Parse_StackOp_t * p )
+{
+    if ( p->Top == 0 )
+    {
+        printf( "Parse_StackOpPush(): Trying to extract data from the empty stack!\n" );
+        return -1;
+    }
+    return p->pData[ --p->Top ];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the stack.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Parse_StackOpFree( Parse_StackOp_t * p )
+{
+    ABC_FREE( p->pData );
+    ABC_FREE( p );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/reo/module.make b/abc-build/src/bdd/reo/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/reo/module.make
@@ -0,0 +1,8 @@
+SRC +=	src/bdd/reo/reoApi.c \
+	src/bdd/reo/reoCore.c \
+	src/bdd/reo/reoProfile.c \
+	src/bdd/reo/reoShuffle.c \
+	src/bdd/reo/reoSift.c \
+	src/bdd/reo/reoSwap.c \
+	src/bdd/reo/reoTransfer.c \
+	src/bdd/reo/reoUnits.c
diff --git a/abc-build/src/bdd/reo/reo.h b/abc-build/src/bdd/reo/reo.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/reo/reo.h
@@ -0,0 +1,234 @@
+/**CFile****************************************************************
+
+  FileName    [reo.h]
+
+  PackageName [REO: A specialized DD reordering engine.]
+
+  Synopsis    [External and internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 15, 2002.]
+
+  Revision    [$Id: reo.h,v 1.0 2002/15/10 03:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__bdd__reo__reo_h
+#define ABC__bdd__reo__reo_h
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "misc/extra/extraBdd.h"
+
+////////////////////////////////////////////////////////////////////////
+///                     MACRO DEFINITIONS                            ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+// reordering parameters
+#define REO_REORDER_LIMIT      1.15  // determines the quality/runtime trade-off
+#define REO_QUAL_PAR              3  // the quality [1 = simple lower bound, 2 = strict, larger = heuristic]
+// internal parameters
+#define REO_CONST_LEVEL       30000  // the number of the constant level
+#define REO_TOPREF_UNDEF      30000  // the undefined top reference
+#define REO_CHUNK_SIZE         5000  // the number of units allocated at one time
+#define REO_COST_EPSILON  0.0000001  // difference in cost large enough so that it counted as an error
+#define REO_HIGH_VALUE     10000000  // a large value used to initialize some variables
+// interface parameters
+#define REO_ENABLE                1  // the value of the enable flag
+#define REO_DISABLE               0  // the value of the disable flag
+
+// the types of minimization currently supported
+typedef enum {
+	REO_MINIMIZE_NODES,
+	REO_MINIMIZE_WIDTH,   // may not work for BDDs with complemented edges
+	REO_MINIMIZE_APL
+} reo_min_type;
+
+////////////////////////////////////////////////////////////////////////
+///                      DATA STRUCTURES                             ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct _reo_unit     reo_unit;    // the unit representing one DD node during reordering
+typedef struct _reo_plane    reo_plane;   // the set of nodes on one level
+typedef struct _reo_hash     reo_hash;    // the entry in the hash table
+typedef struct _reo_man      reo_man;     // the reordering manager
+typedef struct _reo_test     reo_test;    // 
+
+struct _reo_unit
+{
+	short       lev;             // the level of this node at the beginning
+	short       TopRef;          // the top level from which this node is refed (used to update BDD width)
+	short       TopRefNew;       // the new top level from which this node is refed (used to update BDD width)
+	short       n;               // the number of incoming edges (similar to ref count in the BDD)
+	int         Sign;            // the signature
+
+	reo_unit *  pE;              // the pointer to the "else" branch
+	reo_unit *  pT;              // the pointer to the "then" branch
+	reo_unit *  Next;            // the link to the next one in the list
+	double      Weight;          // the probability of traversing this node
+};
+
+struct _reo_plane
+{
+	int         fSifted;         // to mark the sifted variables
+	int         statsNodes;      // the number of nodes in the current level
+	int         statsWidth;      // the width on the current level
+	double      statsApl;        // the sum of node probabilities on this level
+	double      statsCost;       // the current cost is stored here
+	double      statsCostAbove;  // the current cost is stored here
+	double      statsCostBelow;  // the current cost is stored here
+
+	reo_unit *  pHead;           // the pointer to the beginning of the unit list
+};
+
+struct _reo_hash
+{
+	int         Sign;            // signature of the current cache operation
+	reo_unit *  Arg1;            // the first argument
+	reo_unit *  Arg2;            // the second argument
+	reo_unit *  Arg3;            // the third argument
+};
+
+struct _reo_man
+{
+	// these paramaters can be set by the API functions
+	int         fMinWidth;       // the flag to enable reordering for minimum width
+	int         fMinApl;         // the flag to enable reordering for minimum APL
+	int         fVerbose;        // the verbosity level
+	int         fVerify;         // the flag toggling verification
+	int         fRemapUp;        // the flag to enable remapping   
+	int         nIters;          // the number of interations of sifting to perform
+
+	// parameters given by the user when reordering is called
+	DdManager * dd;              // the CUDD BDD manager
+	int *       pOrder;          // the resulting variable order will be returned here
+
+	// derived parameters
+	int         fThisIsAdd;      // this flag is one if the function is the ADD 
+	int *       pSupp;           // the support of the given function
+	int         nSuppAlloc;      // the max allowed number of support variables
+	int         nSupp;           // the number of support variables
+	int *       pOrderInt;       // the array storing the internal variable permutation
+	double *    pVarCosts;       // other arrays
+	int *       pLevelOrder;     // other arrays
+	reo_unit ** pWidthCofs;      // temporary storage for cofactors used during reordering for width
+
+	// parameters related to cost
+	int         nNodesBeg;
+	int         nNodesCur;
+	int         nNodesEnd;
+	int         nWidthCur;
+	int         nWidthBeg;
+	int         nWidthEnd;
+	double      nAplCur;
+	double      nAplBeg;
+	double      nAplEnd;
+
+	// mapping of the function into planes and back
+	int *       pMapToPlanes;    // the mapping of var indexes into plane levels
+	int *       pMapToDdVarsOrig;// the mapping of plane levels into the original indexes
+	int *       pMapToDdVarsFinal;// the mapping of plane levels into the final indexes
+
+	// the planes table
+	reo_plane * pPlanes;
+	int         nPlanes;
+	reo_unit ** pTops;
+	int         nTops;
+	int         nTopsAlloc;
+
+	// the hash table
+	reo_hash *  HTable;           // the table itself
+	int         nTableSize;       // the size of the hash table
+	int         Signature;        // the signature counter
+
+	// the referenced node list
+	int         nNodesMaxAlloc;   // this parameters determins how much memory is allocated
+	DdNode **   pRefNodes;
+	int         nRefNodes;
+	int         nRefNodesAlloc;
+
+	// unit memory management
+	reo_unit *  pUnitFreeList;
+	reo_unit ** pMemChunks;
+	int         nMemChunks;
+	int         nMemChunksAlloc;
+	int         nUnitsUsed;
+
+	// statistic variables
+	int         HashSuccess;
+	int         HashFailure;
+	int         nSwaps;            // the number of swaps
+	int         nNISwaps;          // the number of swaps without interaction
+};
+
+// used to manipulate units
+#define Unit_Regular(u)     ((reo_unit *)((ABC_PTRUINT_T)(u) & ~01))
+#define Unit_Not(u)         ((reo_unit *)((ABC_PTRUINT_T)(u) ^ 01))
+#define Unit_NotCond(u,c)   ((reo_unit *)((ABC_PTRUINT_T)(u) ^ (c)))
+#define Unit_IsConstant(u)  ((int)((u)->lev == REO_CONST_LEVEL))
+
+////////////////////////////////////////////////////////////////////////
+///                   FUNCTION DECLARATIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+// ======================= reoApi.c ========================================
+extern reo_man *  Extra_ReorderInit( int nDdVarsMax, int nNodesMax );
+extern void       Extra_ReorderQuit( reo_man * p );
+extern void       Extra_ReorderSetMinimizationType( reo_man * p, reo_min_type fMinType );
+extern void       Extra_ReorderSetRemapping( reo_man * p, int fRemapUp );
+extern void       Extra_ReorderSetIterations( reo_man * p, int nIters );
+extern void       Extra_ReorderSetVerbosity( reo_man * p, int fVerbose );
+extern void       Extra_ReorderSetVerification( reo_man * p, int fVerify );
+extern DdNode *   Extra_Reorder( reo_man * p, DdManager * dd, DdNode * Func, int * pOrder );
+extern void       Extra_ReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder );
+// ======================= reoCore.c =======================================
+extern void       reoReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder );
+extern void       reoResizeStructures( reo_man * p, int nDdVarsMax, int nNodesMax, int nFuncs );
+// ======================= reoProfile.c ======================================
+extern void       reoProfileNodesStart( reo_man * p );
+extern void       reoProfileAplStart( reo_man * p );
+extern void       reoProfileWidthStart( reo_man * p );
+extern void       reoProfileWidthStart2( reo_man * p );
+extern void       reoProfileAplPrint( reo_man * p );
+extern void       reoProfileNodesPrint( reo_man * p );
+extern void       reoProfileWidthPrint( reo_man * p );
+extern void       reoProfileWidthVerifyLevel( reo_plane * pPlane, int Level );
+// ======================= reoSift.c =======================================
+extern void       reoReorderSift( reo_man * p );
+// ======================= reoSwap.c =======================================
+extern double     reoReorderSwapAdjacentVars( reo_man * p, int Level, int fMovingUp );
+// ======================= reoTransfer.c ===================================
+extern reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F );
+extern DdNode *   reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit );
+// ======================= reoUnits.c ======================================
+extern reo_unit * reoUnitsGetNextUnit(reo_man * p );
+extern void       reoUnitsRecycleUnit( reo_man * p, reo_unit * pUnit );
+extern void       reoUnitsRecycleUnitList( reo_man * p, reo_plane * pPlane );
+extern void       reoUnitsAddUnitToPlane( reo_plane * pPlane, reo_unit * pUnit );
+extern void       reoUnitsStopDispenser( reo_man * p );
+// ======================= reoTest.c =======================================
+extern void       Extra_ReorderTest( DdManager * dd, DdNode * Func );
+extern DdNode *   Extra_ReorderCudd( DdManager * dd, DdNode * aFunc, int pPermuteReo[] );
+extern int        Extra_bddReorderTest( DdManager * dd, DdNode * bF ); 
+extern int        Extra_addReorderTest( DdManager * dd, DdNode * aF ); 
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                         END OF FILE                              ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/bdd/reo/reoApi.c b/abc-build/src/bdd/reo/reoApi.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/reo/reoApi.c
@@ -0,0 +1,294 @@
+/**CFile****************************************************************
+
+  FileName    [reoApi.c]
+
+  PackageName [REO: A specialized DD reordering engine.]
+
+  Synopsis    [Implementation of API functions.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 15, 2002.]
+
+  Revision    [$Id: reoApi.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "reo.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Initializes the reordering engine.]
+
+  Description [The first argument is the max number of variables in the
+  CUDD DD manager which will be used with the reordering engine 
+  (this number of should be the maximum of BDD and ZDD parts). 
+  The second argument is the maximum number of BDD nodes in the BDDs 
+  to be reordered. These limits are soft. Setting lower limits will later 
+  cause the reordering manager to resize internal data structures. 
+  However, setting the exact values will make reordering more efficient 
+  because resizing will be not necessary.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+reo_man * Extra_ReorderInit( int nDdVarsMax, int nNodesMax )
+{
+	reo_man * p;
+	// allocate and clean the data structure
+	p = ABC_ALLOC( reo_man, 1 );
+	memset( p, 0, sizeof(reo_man) );
+	// resize the manager to meet user's needs	
+	reoResizeStructures( p, nDdVarsMax, nNodesMax, 100 );
+	// set the defaults
+	p->fMinApl   = 0;
+	p->fMinWidth = 0;
+	p->fRemapUp  = 0;
+	p->fVerbose  = 0;
+	p->fVerify   = 0;
+	p->nIters    = 1;
+	return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Disposes of the reordering engine.]
+
+  Description [Removes all memory associated with the reordering engine.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_ReorderQuit( reo_man * p )
+{
+	ABC_FREE( p->pTops );
+	ABC_FREE( p->pSupp );
+	ABC_FREE( p->pOrderInt );
+	ABC_FREE( p->pWidthCofs );
+	ABC_FREE( p->pMapToPlanes );
+	ABC_FREE( p->pMapToDdVarsOrig );
+	ABC_FREE( p->pMapToDdVarsFinal );
+	ABC_FREE( p->pPlanes );
+	ABC_FREE( p->pVarCosts );
+	ABC_FREE( p->pLevelOrder );
+	ABC_FREE( p->HTable );
+	ABC_FREE( p->pRefNodes );
+	reoUnitsStopDispenser( p );
+	ABC_FREE( p->pMemChunks );
+	ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the type of DD minimizationl that will be performed.]
+
+  Description [Currently, three different types of minimization are supported.
+  It is possible to minimize the number of BDD nodes. This is a classical type
+  of minimization, which is attempting to reduce the total number of nodes in
+  the (shared) BDD of the given Boolean functions. It is also possible to 
+  minimize the BDD width, defined as the sum total of the number of cofactors 
+  on each level in the (shared) BDD (note that the number of cofactors on the 
+  given level may be larger than the number of nodes appearing on the given level).
+  It is also possible to minimize the average path length in the (shared) BDD 
+  defined as the sum of products, for all BDD paths from the top node to any 
+  terminal node, of the number of minterms on the path by the number of nodes 
+  on the path. The default reordering type is minimization for the number of 
+  BDD nodes. Calling this function with REO_MINIMIZE_WIDTH or REO_MINIMIZE_APL
+  as the second argument, changes the default minimization option for all the 
+  reorder calls performed afterwards.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_ReorderSetMinimizationType( reo_man * p, reo_min_type fMinType )
+{
+	if ( fMinType == REO_MINIMIZE_NODES ) 
+	{
+		p->fMinWidth = 0;
+		p->fMinApl   = 0;
+	}
+	else if ( fMinType == REO_MINIMIZE_WIDTH )
+	{
+		p->fMinWidth = 1;
+		p->fMinApl   = 0;
+	}
+	else if ( fMinType == REO_MINIMIZE_APL )
+	{
+		p->fMinWidth = 0;
+		p->fMinApl   = 1;
+	}
+	else 
+	{
+		assert( 0 );
+	}
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the type of remapping performed by the engine.]
+
+  Description [The remapping refers to the way the resulting BDD
+  is expressed using the elementary variables of the CUDD BDD manager.
+  Currently, two types possibilities are supported: remapping and no
+  remapping. Remapping means that the function(s) after reordering
+  depend on the topmost variables in the manager. No remapping means 
+  that the function(s) after reordering depend on the same variables 
+  as before. Consider the following example. Suppose the initial four
+  variable function depends on variables 2,4,5, and 9 on the CUDD BDD
+  manager, which may be found anywhere in the current variable order.
+  If remapping is set, the function after ordering depends on the 
+  topmost variables in the manager, which may or may not be the same
+  as the variables 2,4,5, and 9. If no remapping is set, then the 
+  reordered function depend on the same variables 2,4,5, and 9, but
+  the meaning of each variale has changed according to the new ordering.
+  The resulting ordering is returned in the array "pOrder" filled out
+  by the reordering engine in the call to Extra_Reorder(). The default
+  is no remapping.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_ReorderSetRemapping( reo_man * p, int fRemapUp )
+{
+	p->fRemapUp = fRemapUp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the number of iterations of sifting performed.]
+
+  Description [The default is one iteration. But a higher minimization
+  quality is desired, it is possible to set the number of iterations 
+  to any number larger than 1. Convergence is often reached after
+  several iterations, so typically it make no sense to set the number
+  of iterations higher than 3.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_ReorderSetIterations( reo_man * p, int nIters )
+{
+	p->nIters = nIters;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the verification mode.]
+
+  Description [Setting the level to 1 results in verifying the results
+  of variable reordering. Verification is performed by remapping the
+  resulting functions into the original variable order and comparing
+  them with the original functions given by the user. Enabling verification
+  typically leads to 20-30% increase in the total runtime of REO.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_ReorderSetVerification( reo_man * p, int fVerify )
+{
+	p->fVerify = fVerify;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the verbosity level.]
+
+  Description [Setting the level to 1 results in printing statistics
+  before and after the reordering.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_ReorderSetVerbosity( reo_man * p, int fVerbose )
+{
+	p->fVerbose = fVerbose;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs reordering of the function.]
+
+  Description [Returns the DD minimized by variable reordering in the REO 
+  engine. Takes the CUDD decision diagram manager (dd) and the function (Func) 
+  represented as a BDD or ADD (MTBDD). If the variable array (pOrder) is not NULL, 
+  returns the resulting  variable permutation. The permutation is such that if the resulting 
+  function is permuted by Cudd_(add,bdd)Permute() using pOrder as the permutation 
+  array, the initial function (Func) results.
+  Several flag set by other interface functions specify reordering options: 
+  - Remappig can be set by Extra_ReorderSetRemapping(). Then the resulting DD after 
+  reordering is remapped into the topmost levels of the DD manager. Otherwise, 
+  the resulting DD after reordering is mapped using the same variables, on which it 
+  originally depended, only (possibly) permuted as a result of reordering.
+  - Minimization type can be set by Extra_ReorderSetMinimizationType(). Note
+  that when the BDD is minimized for the total width of the total APL, the number
+  BDD nodes can increase. The total width is defines as sum total of widths on each 
+  level. The width on one level is defined as the number of distinct BDD nodes 
+  pointed by the nodes situated above the given level.
+  - The number of iterations of sifting can be set by Extra_ReorderSetIterations().
+  The decision diagram returned by this procedure is not referenced.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_Reorder( reo_man * p, DdManager * dd, DdNode * Func, int * pOrder )
+{
+	DdNode * FuncRes;
+	Extra_ReorderArray( p, dd, &Func, &FuncRes, 1, pOrder );
+	Cudd_Deref( FuncRes );
+	return FuncRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs reordering of the array of functions.]
+
+  Description [The options are similar to the procedure Extra_Reorder(), except that
+  the user should also provide storage for the resulting DDs, which are returned 
+  referenced.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_ReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder )
+{
+	reoReorderArray( p, dd, Funcs, FuncsRes, nFuncs, pOrder );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                         END OF FILE                              ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/reo/reoCore.c b/abc-build/src/bdd/reo/reoCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/reo/reoCore.c
@@ -0,0 +1,441 @@
+/**CFile****************************************************************
+
+  FileName    [reoCore.c]
+
+  PackageName [REO: A specialized DD reordering engine.]
+
+  Synopsis    [Implementation of the core reordering procedure.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 15, 2002.]
+
+  Revision    [$Id: reoCore.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "reo.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int  reoRecursiveDeref( reo_unit * pUnit );
+static int  reoCheckZeroRefs( reo_plane * pPlane );
+static int  reoCheckLevels( reo_man * p );
+
+double s_AplBefore;
+double s_AplAfter;
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void reoReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder )
+{
+	int Counter, i;
+
+	// set the initial parameters
+	p->dd     = dd;
+	p->pOrder = pOrder;
+	p->nTops  = nFuncs;
+	// get the initial number of nodes
+	p->nNodesBeg = Cudd_SharingSize( Funcs, nFuncs );     
+	// resize the internal data structures of the manager if necessary
+	reoResizeStructures( p, ddMax(dd->size,dd->sizeZ), p->nNodesBeg, nFuncs );
+	// compute the support
+	p->pSupp = Extra_VectorSupportArray( dd, Funcs, nFuncs, p->pSupp );
+	// get the number of support variables
+	p->nSupp = 0;
+	for ( i = 0; i < dd->size; i++ )
+		p->nSupp += p->pSupp[i];
+
+	// if it is the constant function, no need to reorder
+	if ( p->nSupp == 0 )
+	{
+		for ( i = 0; i < nFuncs; i++ )
+		{
+			FuncsRes[i] = Funcs[i]; Cudd_Ref( FuncsRes[i] );
+		}
+		return;
+	}
+
+	// create the internal variable maps
+	// go through variable levels in the manager
+	Counter = 0;
+	for ( i = 0; i < dd->size; i++ )
+		if ( p->pSupp[ dd->invperm[i] ] )
+		{
+			p->pMapToPlanes[ dd->invperm[i] ] = Counter;
+			p->pMapToDdVarsOrig[Counter]      = dd->invperm[i];
+			if ( !p->fRemapUp )
+				p->pMapToDdVarsFinal[Counter] = dd->invperm[i];
+			else
+				p->pMapToDdVarsFinal[Counter] = dd->invperm[Counter];
+			p->pOrderInt[Counter]        = Counter;
+			Counter++;
+		}
+
+	// set the initial parameters
+	p->nUnitsUsed = 0;
+	p->nNodesCur  = 0;
+	p->fThisIsAdd = 0;
+	p->Signature++;
+	// transfer the function from the CUDD package into REO"s internal data structure
+	for ( i = 0; i < nFuncs; i++ )
+		p->pTops[i] = reoTransferNodesToUnits_rec( p, Funcs[i] );
+	assert( p->nNodesBeg == p->nNodesCur );
+
+	if ( !p->fThisIsAdd && p->fMinWidth )
+	{
+		printf( "An important message from the REO reordering engine:\n" );
+		printf( "The BDD given to the engine for reordering contains complemented edges.\n" );
+		printf( "Currently, such BDDs cannot be reordered for the minimum width.\n" );
+		printf( "Therefore, minimization for the number of BDD nodes is performed.\n" );
+		fflush( stdout );
+		p->fMinApl   = 0;
+		p->fMinWidth = 0;
+	}
+
+	if ( p->fMinWidth )
+		reoProfileWidthStart(p);
+	else if ( p->fMinApl )
+		reoProfileAplStart(p);
+	else 
+		reoProfileNodesStart(p);
+
+	if ( p->fVerbose )
+	{
+		printf( "INITIAL:\n" );
+		if ( p->fMinWidth )
+			reoProfileWidthPrint(p);
+		else if ( p->fMinApl )
+			reoProfileAplPrint(p);
+		else
+			reoProfileNodesPrint(p);
+	}
+ 
+	///////////////////////////////////////////////////////////////////
+	// performs the reordering
+	p->nSwaps   = 0;
+	p->nNISwaps = 0;
+	for ( i = 0; i < p->nIters; i++ )
+	{
+		reoReorderSift( p );
+		// print statistics after each iteration
+		if ( p->fVerbose )
+		{
+			printf( "ITER #%d:\n", i+1 );
+			if ( p->fMinWidth )
+				reoProfileWidthPrint(p);
+			else if ( p->fMinApl )
+				reoProfileAplPrint(p);
+			else
+				reoProfileNodesPrint(p);
+		}
+		// if the cost function did not change, stop iterating
+		if ( p->fMinWidth )
+		{
+			p->nWidthEnd = p->nWidthCur;
+			assert( p->nWidthEnd <= p->nWidthBeg );
+			if ( p->nWidthEnd == p->nWidthBeg )
+				break;
+		}
+		else if ( p->fMinApl )
+		{
+			p->nAplEnd = p->nAplCur;
+			assert( p->nAplEnd <= p->nAplBeg );
+			if ( p->nAplEnd == p->nAplBeg )
+				break;
+		}
+		else
+		{
+			p->nNodesEnd = p->nNodesCur;
+			assert( p->nNodesEnd <= p->nNodesBeg );
+			if ( p->nNodesEnd == p->nNodesBeg )
+				break;
+		}
+	}
+	assert( reoCheckLevels( p ) );
+	///////////////////////////////////////////////////////////////////
+
+s_AplBefore = p->nAplBeg;
+s_AplAfter  = p->nAplEnd;
+
+	// set the initial parameters
+	p->nRefNodes  = 0;
+	p->nNodesCur  = 0;
+	p->Signature++;
+	// transfer the BDDs from REO's internal data structure to CUDD
+	for ( i = 0; i < nFuncs; i++ )
+	{
+		FuncsRes[i] = reoTransferUnitsToNodes_rec( p, p->pTops[i] ); Cudd_Ref( FuncsRes[i] );
+	}
+	// undo the DDs referenced for storing in the cache
+	for ( i = 0; i < p->nRefNodes; i++ )
+		Cudd_RecursiveDeref( dd, p->pRefNodes[i] );
+	// verify zero refs of the terminal nodes
+	for ( i = 0; i < nFuncs; i++ )
+	{
+		assert( reoRecursiveDeref( p->pTops[i] ) );
+	}
+	assert( reoCheckZeroRefs( &(p->pPlanes[p->nSupp]) ) );
+
+	// prepare the variable map to return to the user
+	if ( p->pOrder )
+	{
+		// i is the current level in the planes data structure
+		// p->pOrderInt[i] is the original level in the planes data structure
+		// p->pMapToDdVarsOrig[i] is the variable, into which we remap when we construct the BDD from planes
+		// p->pMapToDdVarsOrig[ p->pOrderInt[i] ] is the original BDD variable corresponding to this level
+		// Therefore, p->pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ]
+		// creates the permutation, which remaps the resulting BDD variable into the original BDD variable
+		for ( i = 0; i < p->nSupp; i++ )
+			p->pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ]; 
+	}
+
+	if ( p->fVerify )
+	{
+		int fVerification;
+		DdNode * FuncRemapped;
+		int * pOrder;
+
+		if ( p->pOrder == NULL )
+		{
+			pOrder = ABC_ALLOC( int, p->nSupp );
+			for ( i = 0; i < p->nSupp; i++ )
+				pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ]; 
+		}
+		else
+			pOrder = p->pOrder;
+
+		fVerification = 1;
+		for ( i = 0; i < nFuncs; i++ )
+		{
+			// verify the result
+			if ( p->fThisIsAdd )
+				FuncRemapped = Cudd_addPermute( dd, FuncsRes[i], pOrder );
+			else
+				FuncRemapped = Cudd_bddPermute( dd, FuncsRes[i], pOrder );
+			Cudd_Ref( FuncRemapped );
+
+			if ( FuncRemapped != Funcs[i] )
+			{
+				fVerification = 0;
+				printf( "REO: Internal verification has failed!\n" );
+				fflush( stdout );
+			}
+			Cudd_RecursiveDeref( dd, FuncRemapped );
+		}
+		if ( fVerification )
+			printf( "REO: Internal verification is okay!\n" );
+
+		if ( p->pOrder == NULL )
+			ABC_FREE( pOrder );
+	}
+
+	// recycle the data structure
+	for ( i = 0; i <= p->nSupp; i++ )
+		reoUnitsRecycleUnitList( p, p->pPlanes + i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the internal manager data structures.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void reoResizeStructures( reo_man * p, int nDdVarsMax, int nNodesMax, int nFuncs )
+{
+	// resize data structures depending on the number of variables in the DD manager
+	if ( p->nSuppAlloc == 0 )
+	{
+		p->pSupp             = ABC_ALLOC( int,        nDdVarsMax + 1 );
+		p->pOrderInt         = ABC_ALLOC( int,        nDdVarsMax + 1 );
+		p->pMapToPlanes      = ABC_ALLOC( int,        nDdVarsMax + 1 );
+		p->pMapToDdVarsOrig  = ABC_ALLOC( int,        nDdVarsMax + 1 );
+		p->pMapToDdVarsFinal = ABC_ALLOC( int,        nDdVarsMax + 1 );
+		p->pPlanes           = ABC_CALLOC( reo_plane, nDdVarsMax + 1 );
+		p->pVarCosts         = ABC_ALLOC( double,     nDdVarsMax + 1 );
+		p->pLevelOrder       = ABC_ALLOC( int,        nDdVarsMax + 1 );
+		p->nSuppAlloc        = nDdVarsMax + 1;
+	}
+	else if ( p->nSuppAlloc < nDdVarsMax )
+	{
+		ABC_FREE( p->pSupp );
+		ABC_FREE( p->pOrderInt );
+		ABC_FREE( p->pMapToPlanes );
+		ABC_FREE( p->pMapToDdVarsOrig );
+		ABC_FREE( p->pMapToDdVarsFinal );
+		ABC_FREE( p->pPlanes );
+		ABC_FREE( p->pVarCosts );
+		ABC_FREE( p->pLevelOrder );
+
+		p->pSupp             = ABC_ALLOC( int,        nDdVarsMax + 1 );
+		p->pOrderInt         = ABC_ALLOC( int,        nDdVarsMax + 1 );
+		p->pMapToPlanes      = ABC_ALLOC( int,        nDdVarsMax + 1 );
+		p->pMapToDdVarsOrig  = ABC_ALLOC( int,        nDdVarsMax + 1 );
+		p->pMapToDdVarsFinal = ABC_ALLOC( int,        nDdVarsMax + 1 );
+		p->pPlanes           = ABC_CALLOC( reo_plane, nDdVarsMax + 1 );
+		p->pVarCosts         = ABC_ALLOC( double,     nDdVarsMax + 1 );
+		p->pLevelOrder       = ABC_ALLOC( int,        nDdVarsMax + 1 );
+		p->nSuppAlloc        = nDdVarsMax + 1;
+	}
+
+	// resize the data structures depending on the number of nodes
+	if ( p->nRefNodesAlloc == 0 )
+	{
+		p->nNodesMaxAlloc  = nNodesMax;
+		p->nTableSize      = 3*nNodesMax + 1;
+		p->nRefNodesAlloc  = 3*nNodesMax + 1;
+		p->nMemChunksAlloc = (10*nNodesMax + 1)/REO_CHUNK_SIZE + 1;
+
+		p->HTable          = ABC_CALLOC( reo_hash,  p->nTableSize );
+		p->pRefNodes       = ABC_ALLOC( DdNode *,   p->nRefNodesAlloc );
+		p->pWidthCofs      = ABC_ALLOC( reo_unit *, p->nRefNodesAlloc );
+		p->pMemChunks      = ABC_ALLOC( reo_unit *, p->nMemChunksAlloc );
+	}
+	else if ( p->nNodesMaxAlloc < nNodesMax )
+	{
+		reo_unit ** pTemp;
+		int nMemChunksAllocPrev = p->nMemChunksAlloc;
+
+		p->nNodesMaxAlloc  = nNodesMax;
+		p->nTableSize      = 3*nNodesMax + 1;
+		p->nRefNodesAlloc  = 3*nNodesMax + 1;
+		p->nMemChunksAlloc = (10*nNodesMax + 1)/REO_CHUNK_SIZE + 1;
+
+		ABC_FREE( p->HTable );
+		ABC_FREE( p->pRefNodes );
+		ABC_FREE( p->pWidthCofs );
+		p->HTable          = ABC_CALLOC( reo_hash,    p->nTableSize );
+		p->pRefNodes       = ABC_ALLOC(  DdNode *,    p->nRefNodesAlloc );
+		p->pWidthCofs      = ABC_ALLOC(  reo_unit *,  p->nRefNodesAlloc );
+		// p->pMemChunks should be reallocated because it contains pointers currently in use
+		pTemp              = ABC_ALLOC(  reo_unit *,  p->nMemChunksAlloc );
+		memmove( pTemp, p->pMemChunks, sizeof(reo_unit *) * nMemChunksAllocPrev );
+		ABC_FREE( p->pMemChunks );
+		p->pMemChunks      = pTemp;
+	}
+
+	// resize the data structures depending on the number of functions
+	if ( p->nTopsAlloc == 0 )
+	{
+		p->pTops      = ABC_ALLOC( reo_unit *, nFuncs );
+		p->nTopsAlloc = nFuncs;
+	}
+	else if ( p->nTopsAlloc < nFuncs )
+	{
+		ABC_FREE( p->pTops );
+		p->pTops      = ABC_ALLOC( reo_unit *, nFuncs );
+		p->nTopsAlloc = nFuncs;
+	}
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences units the data structure after reordering.]
+
+  Description [This function is only useful for debugging.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int reoRecursiveDeref( reo_unit * pUnit )
+{
+	reo_unit * pUnitR;
+	pUnitR = Unit_Regular(pUnit);
+	pUnitR->n--;
+	if ( Unit_IsConstant(pUnitR) )
+		return 1;
+	if ( pUnitR->n == 0 )
+	{
+		reoRecursiveDeref( pUnitR->pE );
+		reoRecursiveDeref( pUnitR->pT );
+	}
+	return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the zero references for the given plane.]
+
+  Description [This function is only useful for debugging.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int reoCheckZeroRefs( reo_plane * pPlane )
+{
+	reo_unit * pUnit;
+	for ( pUnit = pPlane->pHead; pUnit; pUnit = pUnit->Next )
+	{
+		if ( pUnit->n != 0 )
+		{
+			assert( 0 );
+		}
+	}
+	return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the zero references for the given plane.]
+
+  Description [This function is only useful for debugging.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int reoCheckLevels( reo_man * p )
+{
+	reo_unit * pUnit;
+	int i;
+
+	for ( i = 0; i < p->nSupp; i++ )
+	{
+		// there are some nodes left on each level
+		assert( p->pPlanes[i].statsNodes );
+		for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next )
+		{
+			// the level is properly set
+			assert( pUnit->lev == i );
+		}
+	}
+	return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                         END OF FILE                              ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/reo/reoProfile.c b/abc-build/src/bdd/reo/reoProfile.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/reo/reoProfile.c
@@ -0,0 +1,370 @@
+/**CFile****************************************************************
+
+  FileName    [reoProfile.c]
+
+  PackageName [REO: A specialized DD reordering engine.]
+
+  Synopsis    [Procudures that compute variables profiles (nodes, width, APL).]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 15, 2002.]
+
+  Revision    [$Id: reoProfile.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "reo.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function********************************************************************
+
+  Synopsis    [Start the profile for the BDD nodes.]
+
+  Description [TopRef is the first level, on this the given node counts towards 
+  the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void reoProfileNodesStart( reo_man * p )
+{
+	int Total, i;
+	Total = 0;
+	for ( i = 0; i <= p->nSupp; i++ )
+	{
+		p->pPlanes[i].statsCost = p->pPlanes[i].statsNodes;
+		Total += p->pPlanes[i].statsNodes;
+	}
+	assert( Total == p->nNodesCur );
+	p->nNodesBeg = p->nNodesCur;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Start the profile for the APL.]
+
+  Description [Computes the total path length. The path length is normalized
+  by dividing it by 2^|supp(f)|. To get the "real" APL, multiply by 2^|supp(f)|.
+  This procedure assumes that Weight field of all nodes has been set to 0.0 
+  before the call, except for the weight of the topmost node, which is set to 1.0 
+  (1.0 is the probability of traversing the topmost node). This procedure 
+  assigns the edge weights. Because of the equal probability of selecting 0 and 1 
+  assignment at a node, the edge weights are the same for the node. 
+  Instead of storing them, we store the weight of the node, which is the probability 
+  of traversing the node (pUnit->Weight) during the top down evalation of the BDD. ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void reoProfileAplStart( reo_man * p )
+{
+	reo_unit * pER, * pTR;
+	reo_unit * pUnit;
+	double Res, Half;
+	int i;
+
+	// clean the weights of all nodes
+	for ( i = 0; i < p->nSupp; i++ )
+		for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next )
+			pUnit->Weight = 0.0;
+	// to assign the node weights (the probability of visiting each node)
+	// we visit the node after visiting its predecessors
+
+	// set the probability of visits to the top nodes
+	for ( i = 0; i < p->nTops; i++ )
+		Unit_Regular(p->pTops[i])->Weight += 1.0;
+
+	// to compute the path length (the sum of products of edge weight by edge length)
+	// we visit the nodes in any order (the above order will do)
+	Res = 0.0;
+	for ( i = 0; i < p->nSupp; i++ )
+	{
+		p->pPlanes[i].statsCost = 0.0;
+		for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next )
+		{
+			pER  = Unit_Regular(pUnit->pE);
+			pTR  = Unit_Regular(pUnit->pT);
+			Half = 0.5 * pUnit->Weight;
+			pER->Weight += Half;
+			pTR->Weight += Half;
+			// add to the path length
+			p->pPlanes[i].statsCost += pUnit->Weight;
+		}
+		Res += p->pPlanes[i].statsCost;
+	}
+	p->pPlanes[p->nSupp].statsCost = 0.0;
+	p->nAplBeg = p->nAplCur = Res;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Start the profile for the BDD width. Complexity of the algorithm is O(N + n).]
+
+  Description [TopRef is the first level, on which the given node counts towards 
+  the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void reoProfileWidthStart( reo_man * p )
+{
+	reo_unit * pUnit;
+	int * pWidthStart;
+	int * pWidthStop;
+	int v;
+
+	// allocate and clean the storage for starting and stopping levels
+	pWidthStart = ABC_ALLOC( int, p->nSupp + 1 );
+	pWidthStop  = ABC_ALLOC( int, p->nSupp + 1 );
+	memset( pWidthStart, 0, sizeof(int) * (p->nSupp + 1) );
+	memset( pWidthStop, 0, sizeof(int) * (p->nSupp + 1) );
+
+	// go through the non-constant nodes and set the topmost level of their cofactors
+	for ( v = 0; v <= p->nSupp; v++ )
+	for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next )
+	{
+		pUnit->TopRef = REO_TOPREF_UNDEF;
+		pUnit->Sign   = 0;
+	}
+
+	// add the topmost level of the width profile
+	for ( v = 0; v < p->nTops; v++ )
+	{
+		pUnit = Unit_Regular(p->pTops[v]);
+		if ( pUnit->TopRef == REO_TOPREF_UNDEF )
+		{
+			// set the starting level
+			pUnit->TopRef = 0;
+			pWidthStart[pUnit->TopRef]++;
+			// set the stopping level
+			if ( pUnit->lev != REO_CONST_LEVEL )
+				pWidthStop[pUnit->lev+1]++;
+		}
+	}
+
+	for ( v = 0; v < p->nSupp; v++ )
+	for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next )
+	{
+		if ( pUnit->pE->TopRef == REO_TOPREF_UNDEF )
+		{
+			// set the starting level
+			pUnit->pE->TopRef = pUnit->lev + 1;
+			pWidthStart[pUnit->pE->TopRef]++;
+			// set the stopping level
+			if ( pUnit->pE->lev != REO_CONST_LEVEL )
+				pWidthStop[pUnit->pE->lev+1]++;
+		}
+		if ( pUnit->pT->TopRef == REO_TOPREF_UNDEF )
+		{
+			// set the starting level
+			pUnit->pT->TopRef = pUnit->lev + 1;
+			pWidthStart[pUnit->pT->TopRef]++;
+			// set the stopping level
+			if ( pUnit->pT->lev != REO_CONST_LEVEL )
+				pWidthStop[pUnit->pT->lev+1]++;
+		}
+	}
+
+	// verify the top reference
+	for ( v = 0; v < p->nSupp; v++ )
+		reoProfileWidthVerifyLevel( p->pPlanes + v, v );
+
+	// derive the profile
+	p->nWidthCur = 0;
+	for ( v = 0; v <= p->nSupp; v++ )
+	{
+		if ( v == 0 )
+			p->pPlanes[v].statsWidth = pWidthStart[v] - pWidthStop[v];
+		else
+			p->pPlanes[v].statsWidth = p->pPlanes[v-1].statsWidth + pWidthStart[v] - pWidthStop[v];
+		p->pPlanes[v].statsCost = p->pPlanes[v].statsWidth;
+		p->nWidthCur += p->pPlanes[v].statsWidth;
+		printf( "Level %2d: Width = %5d.\n", v, p->pPlanes[v].statsWidth );
+	}
+	p->nWidthBeg = p->nWidthCur;
+	ABC_FREE( pWidthStart );
+	ABC_FREE( pWidthStop );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Start the profile for the BDD width. Complexity of the algorithm is O(N * n).]
+
+  Description [TopRef is the first level, on which the given node counts towards 
+  the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void reoProfileWidthStart2( reo_man * p )
+{
+	reo_unit * pUnit;
+	int i, v;
+
+	// clean the profile
+	for ( i = 0; i <= p->nSupp; i++ )
+		p->pPlanes[i].statsWidth = 0;
+	
+	// clean the node structures
+	for ( v = 0; v <= p->nSupp; v++ )
+	for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next )
+	{
+		pUnit->TopRef = REO_TOPREF_UNDEF;
+		pUnit->Sign   = 0;
+	}
+
+	// set the topref to the topmost nodes
+	for ( i = 0; i < p->nTops; i++ )
+		Unit_Regular(p->pTops[i])->TopRef = 0;
+
+	// go through the non-constant nodes and set the topmost level of their cofactors
+	for ( i = 0; i < p->nSupp; i++ )
+		for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next )
+		{
+			if ( pUnit->pE->TopRef > i+1 )
+				 pUnit->pE->TopRef = i+1;
+			if ( pUnit->pT->TopRef > i+1 )
+				 pUnit->pT->TopRef = i+1;
+		}
+
+	// verify the top reference
+	for ( i = 0; i < p->nSupp; i++ )
+		reoProfileWidthVerifyLevel( p->pPlanes + i, i );
+
+	// compute the profile for the internal nodes
+	for ( i = 0; i < p->nSupp; i++ )
+		for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next )
+			for ( v = pUnit->TopRef; v <= pUnit->lev; v++ )
+				p->pPlanes[v].statsWidth++;
+
+	// compute the profile for the constant nodes
+	for ( pUnit = p->pPlanes[p->nSupp].pHead; pUnit; pUnit = pUnit->Next )
+		for ( v = pUnit->TopRef; v <= p->nSupp; v++ )
+			p->pPlanes[v].statsWidth++;
+
+	// get the width cost
+	p->nWidthCur = 0;
+	for ( i = 0; i <= p->nSupp; i++ )
+	{
+		p->pPlanes[i].statsCost = p->pPlanes[i].statsWidth;
+		p->nWidthCur           += p->pPlanes[i].statsWidth;
+	}
+	p->nWidthBeg = p->nWidthCur;
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void reoProfileNodesPrint( reo_man * p )
+{
+	printf( "NODES: Total = %6d. Average = %6.2f.\n", p->nNodesCur, p->nNodesCur / (float)p->nSupp );
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void reoProfileAplPrint( reo_man * p )
+{
+	printf( "APL: Total = %8.2f. Average =%6.2f.\n", p->nAplCur, p->nAplCur / (float)p->nSupp );
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void reoProfileWidthPrint( reo_man * p )
+{
+	int WidthMax;
+	int TotalWidth;
+	int i;
+
+	WidthMax   = 0;
+	TotalWidth = 0;
+	for ( i = 0; i <= p->nSupp; i++ )
+	{
+		printf( "Level = %2d. Width = %3d.\n", i, p->pPlanes[i].statsWidth );
+		if ( WidthMax < p->pPlanes[i].statsWidth )
+			 WidthMax = p->pPlanes[i].statsWidth;
+		TotalWidth += p->pPlanes[i].statsWidth;
+	}
+	assert( p->nWidthCur == TotalWidth );
+	printf( "WIDTH: " );
+	printf( "Maximum = %5d.  ", WidthMax );
+	printf( "Total = %7d.  ", p->nWidthCur );
+	printf( "Average = %6.2f.\n", TotalWidth / (float)p->nSupp );
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void reoProfileWidthVerifyLevel( reo_plane * pPlane, int Level )
+{
+	reo_unit * pUnit;
+	for ( pUnit = pPlane->pHead; pUnit; pUnit = pUnit->Next )
+	{
+		assert( pUnit->TopRef     <= Level );
+		assert( pUnit->pE->TopRef <= Level + 1 );
+		assert( pUnit->pT->TopRef <= Level + 1 );
+	}
+}
+
+////////////////////////////////////////////////////////////////////////
+///                         END OF FILE                              ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/reo/reoShuffle.c b/abc-build/src/bdd/reo/reoShuffle.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/reo/reoShuffle.c
@@ -0,0 +1,230 @@
+/**CFile****************************************************************
+
+  FileName    [reoShuffle.c]
+
+  PackageName [REO: A specialized DD reordering engine.]
+
+  Synopsis    [Implementation of the two-variable swap.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 15, 2002.]
+
+  Revision    [$Id: reoShuffle.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "reo.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure is similar to Cudd_ShuffleHeap() and Cudd_bddPermute().]
+
+  Description [The first argument is the REO manager. The 2nd/3d
+  arguments are the function and its CUDD manager. The last argument
+  is the permutation to be implemented. The i-th entry of the permutation 
+  array contains the index of the variable that should be brought to the 
+  i-th level.  The size of the array should be equal or greater to 
+  the number of variables currently in use (that is, the size of CUDD
+  manager and the size of REO manager).]
+
+  SideEffects [Note that the resulting BDD is not referenced.]
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * reoShuffle( reo_man * p, DdManager * dd, DdNode * bFunc, int * pPerm, int * pPermInv )
+{
+    DdNode * bFuncRes = NULL;
+    int i, k, v;
+
+    if ( Cudd_IsConstant(bFunc) )
+        return bFunc;
+
+	// set the initial parameters
+	p->dd    = dd;
+    p->nSupp = Cudd_SupportSize( dd, bFunc );
+	p->nTops = 1;
+//    p->nNodesBeg = Cudd_DagSize( bFunc );
+
+    // set the starting permutation
+	for ( i = 0; i < p->nSupp; i++ )
+    {
+        p->pOrderInt[i] = i;
+		p->pMapToPlanes[ dd->invperm[i] ] = i;
+		p->pMapToDdVarsFinal[i] = dd->invperm[i];
+    }
+
+	// set the initial parameters
+	p->nUnitsUsed = 0;
+	p->nNodesCur  = 0;
+	p->fThisIsAdd = 0;
+	p->Signature++;
+
+	// transfer the function from the CUDD package into REO's internal data structure
+    p->pTops[0] = reoTransferNodesToUnits_rec( p, bFunc );
+//	assert( p->nNodesBeg == p->nNodesCur );
+
+    // reorder one variable at a time
+    for ( i = 0; i < p->nSupp; i++ )
+    {
+        if ( p->pOrderInt[i] == pPerm[i] )
+            continue;
+        // find where is variable number pPerm[i]
+        for ( k = i + 1; k < p->nSupp; k++ )
+            if ( pPerm[i] == p->pOrderInt[k] )
+                break;
+        if ( k == p->nSupp )
+        {
+            printf( "reoShuffle() Error: Cannot find a variable.\n" );
+            goto finish;
+        }
+        // move the variable up
+        for ( v = k - 1; v >= i; v-- )
+        {
+            reoReorderSwapAdjacentVars( p, v, 1 );
+            // check if the number of nodes is not too large
+            if ( p->nNodesCur > 10000 )
+            {
+                printf( "reoShuffle() Error: BDD size is too large.\n" );
+                goto finish;
+            }
+        }
+        assert( p->pOrderInt[i] == pPerm[i] );
+    }
+
+	// set the initial parameters
+	p->nRefNodes  = 0;
+	p->nNodesCur  = 0;
+	p->Signature++;
+	// transfer the BDDs from REO's internal data structure to CUDD
+    bFuncRes = reoTransferUnitsToNodes_rec( p, p->pTops[0] ); Cudd_Ref( bFuncRes );
+	// undo the DDs referenced for storing in the cache
+	for ( i = 0; i < p->nRefNodes; i++ )
+		Cudd_RecursiveDeref( dd, p->pRefNodes[i] );
+
+	// verify zero refs of the terminal nodes
+//    assert( reoRecursiveDeref( p->pTops[0] ) );
+//    assert( reoCheckZeroRefs( &(p->pPlanes[p->nSupp]) ) );
+
+    // perform verification
+	if ( p->fVerify )
+	{
+		DdNode * bFuncPerm;
+		bFuncPerm = Cudd_bddPermute( dd, bFunc, pPermInv );  Cudd_Ref( bFuncPerm );
+		if ( bFuncPerm != bFuncRes )
+		{
+			printf( "REO: Internal verification has failed!\n" );
+			fflush( stdout );
+		}
+		Cudd_RecursiveDeref( dd, bFuncPerm );
+	}
+
+	// recycle the data structure
+	for ( i = 0; i <= p->nSupp; i++ )
+		reoUnitsRecycleUnitList( p, p->pPlanes + i );
+
+finish :
+    if ( bFuncRes )
+        Cudd_Deref( bFuncRes );
+    return bFuncRes;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reorders the DD using REO and CUDD.]
+
+  Description [This function can be used to test the performance of the reordering package.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_ShuffleTest( reo_man * pReo, DdManager * dd, DdNode * Func )
+{
+//    extern int runtime1, runtime2;
+
+	DdNode * Temp, * bRemap;
+    int nSuppSize, OffSet, Num, i;
+    abctime clk;
+	int pOrder[1000], pOrderInv[1000];
+    assert( dd->size < 1000 );
+
+    srand( 0x12341234 );
+    nSuppSize = Cudd_SupportSize( dd, Func );
+    if ( nSuppSize < 2 )
+        return;
+
+    for ( i = 0; i < nSuppSize; i++ )
+        pOrder[i] = i;
+    for ( i = 0; i < 120; i++ )
+    {
+        OffSet = rand() % (nSuppSize - 1);
+        Num = pOrder[OffSet];
+        pOrder[OffSet] = pOrder[OffSet+1];
+        pOrder[OffSet+1] = Num;
+    }
+    for ( i = 0; i < nSuppSize; i++ )
+        pOrderInv[pOrder[i]] = i;
+
+/*
+    printf( "Permutation: " );
+    for ( i = 0; i < nSuppSize; i++ )
+        printf( "%d ", pOrder[i] );
+    printf( "\n" );
+    printf( "Inverse permutation: " );
+    for ( i = 0; i < nSuppSize; i++ )
+        printf( "%d ", pOrderInv[i] );
+    printf( "\n" );
+*/
+
+    // create permutation
+//    Extra_ReorderSetVerification( pReo, 1 );
+    bRemap = Extra_bddRemapUp( dd, Func );  Cudd_Ref( bRemap );
+
+clk = Abc_Clock();
+	Temp  = reoShuffle( pReo, dd, bRemap, pOrder, pOrderInv );  Cudd_Ref( Temp );
+//runtime1 += Abc_Clock() - clk;
+
+//printf( "Initial = %d. Final = %d.\n", Cudd_DagSize(bRemap), Cudd_DagSize(Temp)  );
+
+	{
+		DdNode * bFuncPerm;
+clk = Abc_Clock();
+		bFuncPerm = Cudd_bddPermute( dd, bRemap, pOrderInv );  Cudd_Ref( bFuncPerm );
+//runtime2 += Abc_Clock() - clk;
+		if ( bFuncPerm != Temp )
+		{
+			printf( "REO: Internal verification has failed!\n" );
+			fflush( stdout );
+		}
+		Cudd_RecursiveDeref( dd, bFuncPerm );
+	}
+
+	Cudd_RecursiveDeref( dd, Temp );
+	Cudd_RecursiveDeref( dd, bRemap );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                         END OF FILE                              ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/reo/reoSift.c b/abc-build/src/bdd/reo/reoSift.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/reo/reoSift.c
@@ -0,0 +1,346 @@
+/**CFile****************************************************************
+
+  FileName    [reoSift.c]
+
+  PackageName [REO: A specialized DD reordering engine.]
+
+  Synopsis    [Implementation of the sifting algorihtm.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 15, 2002.]
+
+  Revision    [$Id: reoSift.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "reo.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Implements the variable sifting algorithm.]
+
+  Description [Performs a sequence of adjacent variable swaps known as "sifting".
+  Uses the cost functions determined by the flag.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void reoReorderSift( reo_man * p )
+{
+	double CostCurrent;  // the cost of the current permutation
+	double CostLimit;    // the maximum increase in cost that can be tolerated
+	double CostBest;     // the best cost
+	int BestQ;           // the best position
+	int VarCurrent;      // the current variable to move   
+	int q;               // denotes the current position of the variable
+	int c;               // performs the loops over variables until all of them are sifted
+	int v;               // used for other purposes
+
+	assert( p->nSupp > 0 );
+
+	// set the current cost depending on the minimization criteria
+	if ( p->fMinWidth )
+		CostCurrent = p->nWidthCur;
+	else if ( p->fMinApl )
+		CostCurrent = p->nAplCur;
+	else
+		CostCurrent = p->nNodesCur;
+
+	// find the upper bound on tbe cost growth
+	CostLimit = 1 + (int)(REO_REORDER_LIMIT * CostCurrent);
+
+	// perform sifting for each of p->nSupp variables
+	for ( c = 0; c < p->nSupp; c++ )
+	{
+		// select the current variable to be the one with the largest number of nodes that is not sifted yet
+		VarCurrent = -1;
+		CostBest   = -1.0;
+		for ( v = 0; v < p->nSupp; v++ )
+		{
+			p->pVarCosts[v] = REO_HIGH_VALUE;
+			if ( !p->pPlanes[v].fSifted )
+			{
+//				VarCurrent = v;
+//				if ( CostBest < p->pPlanes[v].statsCost )
+				if ( CostBest < p->pPlanes[v].statsNodes )
+				{
+//					CostBest   = p->pPlanes[v].statsCost;
+					CostBest   = p->pPlanes[v].statsNodes;
+					VarCurrent = v;
+				}
+
+			}
+		}
+		assert( VarCurrent != -1 );
+		// mark this variable as sifted
+		p->pPlanes[VarCurrent].fSifted = 1;
+
+		// set the current value
+		p->pVarCosts[VarCurrent] = CostCurrent;
+
+		// set the best cost
+		CostBest = CostCurrent;
+		BestQ    = VarCurrent; 
+
+		// determine which way to move the variable first (up or down)
+		// the rationale is that if we move the shorter way first
+		// it is more likely that the best position will be found on the longer way
+		// and the reverse movement (to take the best position) will be faster
+		if ( VarCurrent < p->nSupp/2 ) // move up first, then down
+		{
+			// set the total cost on all levels above the current level
+			p->pPlanes[0].statsCostAbove = 0;
+			for ( v = 1; v <= VarCurrent; v++ )
+				p->pPlanes[v].statsCostAbove = p->pPlanes[v-1].statsCostAbove + p->pPlanes[v-1].statsCost;
+			// set the total cost on all levels below the current level
+			p->pPlanes[p->nSupp].statsCostBelow = 0;
+			for ( v = p->nSupp - 1; v >= VarCurrent; v-- )
+				p->pPlanes[v].statsCostBelow = p->pPlanes[v+1].statsCostBelow + p->pPlanes[v+1].statsCost;
+
+			assert( CostCurrent == p->pPlanes[VarCurrent].statsCostAbove + 
+									p->pPlanes[VarCurrent].statsCost +
+				                    p->pPlanes[VarCurrent].statsCostBelow );
+
+			// move up
+			for ( q = VarCurrent-1; q >= 0; q-- )
+			{
+				CostCurrent -= reoReorderSwapAdjacentVars( p, q, 1 );
+				// now q points to the position of this var in the order
+				p->pVarCosts[q] = CostCurrent;
+				// update the lower bound (assuming that for level q+1 it is set correctly)
+				p->pPlanes[q].statsCostBelow = p->pPlanes[q+1].statsCostBelow + p->pPlanes[q+1].statsCost;
+				// check the upper bound
+				if ( CostCurrent >= CostLimit )
+					break;
+				// check the lower bound
+				if ( p->pPlanes[q].statsCostBelow + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostAbove/REO_QUAL_PAR >= CostBest )
+					break;
+				// update the best cost
+				if ( CostBest > CostCurrent )
+				{
+					CostBest = CostCurrent;
+					BestQ    = q;
+					// adjust node limit
+					CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) );
+				}
+
+				// when we are reordering for width or APL, it may happen that
+				// the number of nodes has grown above certain limit,
+				// in which case we have to resize the data structures
+				if ( p->fMinWidth || p->fMinApl )
+				{
+					if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc )
+					{
+//						printf( "Resizing data structures. Old size = %6d. New size = %6d.\n",  p->nNodesMaxAlloc, p->nNodesCur );
+						reoResizeStructures( p, 0, p->nNodesCur, 0 );
+					}
+				}
+			}
+			// fix the plane index
+			if ( q == -1 )
+				q++;
+			// now p points to the position of this var in the order
+
+			// move down
+			for ( ; q < p->nSupp-1; )
+			{
+				CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 );
+				q++;    // change q to point to the position of this var in the order
+				// sanity check: the number of nodes on the back pass should be the same
+				if ( p->pVarCosts[q] != REO_HIGH_VALUE && fabs( p->pVarCosts[q] - CostCurrent ) > REO_COST_EPSILON )
+					printf("reoReorderSift(): Error! On the backward move, the costs are different.\n");
+				p->pVarCosts[q] = CostCurrent;
+				// update the lower bound (assuming that for level q-1 it is set correctly)
+				p->pPlanes[q].statsCostAbove = p->pPlanes[q-1].statsCostAbove + p->pPlanes[q-1].statsCost;
+				// check the bounds only if the variable already reached its previous position
+				if ( q >= BestQ )
+				{
+					// check the upper bound
+					if ( CostCurrent >= CostLimit )
+						break;
+					// check the lower bound
+					if ( p->pPlanes[q].statsCostAbove + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostBelow/REO_QUAL_PAR >= CostBest )
+						break;
+				}
+				// update the best cost
+				if ( CostBest >= CostCurrent )
+				{
+					CostBest = CostCurrent;
+					BestQ    = q;
+					// adjust node limit
+					CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) );
+				}
+
+				// when we are reordering for width or APL, it may happen that
+				// the number of nodes has grown above certain limit,
+				// in which case we have to resize the data structures
+				if ( p->fMinWidth || p->fMinApl )
+				{
+					if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc )
+					{
+//						printf( "Resizing data structures. Old size = %6d. New size = %6d.\n",  p->nNodesMaxAlloc, p->nNodesCur );
+						reoResizeStructures( p, 0, p->nNodesCur, 0 );
+					}
+				}
+			}
+			// move the variable up from the given position (q) to the best position (BestQ)
+			assert( q >= BestQ );
+			for ( ; q > BestQ; q-- )
+			{
+				CostCurrent -= reoReorderSwapAdjacentVars( p, q-1, 1 );
+				// sanity check: the number of nodes on the back pass should be the same
+				if ( fabs( p->pVarCosts[q-1] - CostCurrent ) > REO_COST_EPSILON )
+				{
+					printf("reoReorderSift():  Error! On the return move, the costs are different.\n" );
+					fflush(stdout);
+				}
+			}
+		}
+		else // move down first, then up
+		{
+			// set the current number of nodes on all levels above the given level
+			p->pPlanes[0].statsCostAbove = 0;
+			for ( v = 1; v <= VarCurrent; v++ )
+				p->pPlanes[v].statsCostAbove = p->pPlanes[v-1].statsCostAbove + p->pPlanes[v-1].statsCost;
+			// set the current number of nodes on all levels below the given level
+			p->pPlanes[p->nSupp].statsCostBelow = 0;
+			for ( v = p->nSupp - 1; v >= VarCurrent; v-- )
+				p->pPlanes[v].statsCostBelow = p->pPlanes[v+1].statsCostBelow + p->pPlanes[v+1].statsCost;
+			
+			assert( CostCurrent == p->pPlanes[VarCurrent].statsCostAbove + 
+									p->pPlanes[VarCurrent].statsCost +
+				                    p->pPlanes[VarCurrent].statsCostBelow );
+
+			// move down
+			for ( q = VarCurrent; q < p->nSupp-1; )
+			{
+				CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 );
+				q++;    // change q to point to the position of this var in the order
+				p->pVarCosts[q] = CostCurrent;
+				// update the lower bound (assuming that for level q-1 it is set correctly)
+				p->pPlanes[q].statsCostAbove = p->pPlanes[q-1].statsCostAbove + p->pPlanes[q-1].statsCost;
+				// check the upper bound
+				if ( CostCurrent >= CostLimit )
+					break;
+				// check the lower bound
+				if ( p->pPlanes[q].statsCostAbove + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostBelow/REO_QUAL_PAR >= CostBest )
+					break;
+				// update the best cost
+				if ( CostBest > CostCurrent )
+				{
+					CostBest = CostCurrent;
+					BestQ    = q;
+					// adjust node limit
+					CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) );
+				}
+
+				// when we are reordering for width or APL, it may happen that
+				// the number of nodes has grown above certain limit,
+				// in which case we have to resize the data structures
+				if ( p->fMinWidth || p->fMinApl )
+				{
+					if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc )
+					{
+//						printf( "Resizing data structures. Old size = %6d. New size = %6d.\n",  p->nNodesMaxAlloc, p->nNodesCur );
+						reoResizeStructures( p, 0, p->nNodesCur, 0 );
+					}
+				}
+			}
+
+			// move up
+			for ( --q; q >= 0; q-- )
+			{
+				CostCurrent -= reoReorderSwapAdjacentVars( p, q, 1 );
+				// now q points to the position of this var in the order
+				// sanity check: the number of nodes on the back pass should be the same
+				if ( p->pVarCosts[q] != REO_HIGH_VALUE && fabs( p->pVarCosts[q] - CostCurrent ) > REO_COST_EPSILON )
+					printf("reoReorderSift(): Error! On the backward move, the costs are different.\n");
+				p->pVarCosts[q] = CostCurrent;
+				// update the lower bound (assuming that for level q+1 it is set correctly)
+				p->pPlanes[q].statsCostBelow = p->pPlanes[q+1].statsCostBelow + p->pPlanes[q+1].statsCost;
+				// check the bounds only if the variable already reached its previous position
+				if ( q <= BestQ )
+				{
+					// check the upper bound
+					if ( CostCurrent >= CostLimit )
+						break;
+					// check the lower bound
+					if ( p->pPlanes[q].statsCostBelow + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostAbove/REO_QUAL_PAR >= CostBest )
+						break;
+				}
+				// update the best cost
+				if ( CostBest >= CostCurrent )
+				{
+					CostBest = CostCurrent;
+					BestQ    = q;
+					// adjust node limit
+					CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) );
+				}
+
+				// when we are reordering for width or APL, it may happen that
+				// the number of nodes has grown above certain limit,
+				// in which case we have to resize the data structures
+				if ( p->fMinWidth || p->fMinApl )
+				{
+					if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc )
+					{
+//						printf( "Resizing data structures. Old size = %6d. New size = %6d.\n",  p->nNodesMaxAlloc, p->nNodesCur );
+						reoResizeStructures( p, 0, p->nNodesCur, 0 );
+					}
+				}
+			}
+			// fix the plane index
+			if ( q == -1 )
+				q++;
+			// now q points to the position of this var in the order
+			// move the variable down from the given position (q) to the best position (BestQ)
+			assert( q <= BestQ );
+			for ( ; q < BestQ; q++ )
+			{
+				CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 );
+				// sanity check: the number of nodes on the back pass should be the same
+				if ( fabs( p->pVarCosts[q+1] - CostCurrent ) > REO_COST_EPSILON )
+				{
+					printf("reoReorderSift(): Error! On the return move, the costs are different.\n" );
+					fflush(stdout);
+				}
+			}
+		}
+		assert( fabs( CostBest - CostCurrent ) < REO_COST_EPSILON );
+
+		// update the cost 
+		if ( p->fMinWidth )
+			p->nWidthCur = (int)CostBest;
+		else if ( p->fMinApl )
+			p->nAplCur = CostCurrent;
+		else
+			p->nNodesCur = (int)CostBest;
+	}
+
+	// remove the sifted attributes if any
+	for ( v = 0; v < p->nSupp; v++ )
+		p->pPlanes[v].fSifted = 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                         END OF FILE                              ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/reo/reoSwap.c b/abc-build/src/bdd/reo/reoSwap.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/reo/reoSwap.c
@@ -0,0 +1,905 @@
+/**CFile****************************************************************
+
+  FileName    [reoSwap.c]
+
+  PackageName [REO: A specialized DD reordering engine.]
+
+  Synopsis    [Implementation of the two-variable swap.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 15, 2002.]
+
+  Revision    [$Id: reoSwap.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "reo.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define AddToLinkedList( ppList, pLink )   (((pLink)->Next = *(ppList)), (*(ppList) = (pLink)))
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description [Takes the level (lev0) of the plane, which should be swapped 
+  with the next plane. Returns the gain using the current cost function.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp )
+{
+	// the levels in the decision diagram
+	int lev1 = lev0 + 1, lev2 = lev0 + 2;
+	// the new nodes on lev0
+	reo_unit * pLoop, * pUnit;
+	// the new nodes on lev1
+	reo_unit * pNewPlane20 = NULL, * pNewPlane21 = NULL; // Suppress "might be used uninitialized"
+        reo_unit * pNewPlane20R;
+	reo_unit * pUnitE, * pUnitER, * pUnitT;
+	// the nodes below lev1
+	reo_unit * pNew1E, * pNew1T, * pNew2E, * pNew2T;
+	reo_unit * pNew1ER, * pNew2ER;
+	// the old linked lists
+	reo_unit * pListOld0 = p->pPlanes[lev0].pHead;
+	reo_unit * pListOld1 = p->pPlanes[lev1].pHead;
+	// working planes and one more temporary plane
+	reo_unit * pListNew0 = NULL, ** ppListNew0 = &pListNew0;
+	reo_unit * pListNew1 = NULL, ** ppListNew1 = &pListNew1; 
+	reo_unit * pListTemp = NULL, ** ppListTemp = &pListTemp; 
+	// various integer variables
+	int fComp, fCompT, fFound, HKey, fInteract, temp, c;
+        int nWidthCofs = -1; // Suppress "might be used uninitialized"
+	// statistical variables
+	int nNodesUpMovedDown  = 0;
+	int nNodesDownMovedUp  = 0;
+	int nNodesUnrefRemoved = 0;
+	int nNodesUnrefAdded   = 0;
+	int nWidthReduction    = 0;
+	double AplWeightTotalLev0 = 0.0; // Suppress "might be used uninitialized"
+	double AplWeightTotalLev1 = 0.0; // Suppress "might be used uninitialized"
+	double AplWeightHalf      = 0.0; // Suppress "might be used uninitialized"
+	double AplWeightPrev      = 0.0; // Suppress "might be used uninitialized"
+	double AplWeightAfter     = 0.0; // Suppress "might be used uninitialized"
+	double nCostGain;     
+
+	// set the old lists
+	assert( lev0 >= 0 && lev1 < p->nSupp );
+	pListOld0 = p->pPlanes[lev0].pHead;
+	pListOld1 = p->pPlanes[lev1].pHead;
+
+	// make sure the planes have nodes
+	assert( p->pPlanes[lev0].statsNodes && p->pPlanes[lev1].statsNodes );
+	assert( pListOld0 && pListOld1 );
+
+	if ( p->fMinWidth )
+	{
+		// verify that the width parameters are set correctly
+		reoProfileWidthVerifyLevel( p->pPlanes + lev0, lev0 );
+		reoProfileWidthVerifyLevel( p->pPlanes + lev1, lev1 );
+		// start the storage for cofactors
+		nWidthCofs = 0;
+	}
+	else if ( p->fMinApl )
+	{
+		AplWeightPrev      = p->nAplCur;
+		AplWeightAfter     = p->nAplCur;
+		AplWeightTotalLev0 = 0.0;
+		AplWeightTotalLev1 = 0.0;
+	}
+
+	// check if the planes interact
+	fInteract = 0; // assume that they do not interact
+	for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next )
+	{
+		if ( pUnit->pT->lev == lev1 || Unit_Regular(pUnit->pE)->lev == lev1 )
+		{
+			fInteract = 1;
+			break;
+		}
+		// change the level now, this is done for efficiency reasons
+		pUnit->lev = lev1;
+	}
+
+	// set the new signature for hashing
+	p->nSwaps++;
+	if ( !fInteract )
+//	if ( 0 )
+	{
+		// perform the swap without interaction
+		p->nNISwaps++;
+
+		// change the levels
+		if ( p->fMinWidth )
+		{
+			// go through the current lower level, which will become upper
+			for ( pUnit = pListOld1; pUnit; pUnit = pUnit->Next )
+			{
+				pUnit->lev = lev0;
+
+				pUnitER = Unit_Regular(pUnit->pE);
+				if ( pUnitER->TopRef > lev0 )
+				{
+					if ( pUnitER->Sign != p->nSwaps )
+					{
+						if ( pUnitER->TopRef == lev2 )
+						{
+							pUnitER->TopRef = lev1;
+							nWidthReduction--;
+						}
+						else
+						{
+							assert( pUnitER->TopRef == lev1 );
+						}
+						pUnitER->Sign   = p->nSwaps;
+					}
+				}
+
+				pUnitT  = pUnit->pT;
+				if ( pUnitT->TopRef > lev0 )
+				{
+					if ( pUnitT->Sign != p->nSwaps )
+					{
+						if ( pUnitT->TopRef == lev2 )
+						{
+							pUnitT->TopRef = lev1;
+							nWidthReduction--;
+						}
+						else
+						{
+							assert( pUnitT->TopRef == lev1 );
+						}
+						pUnitT->Sign   = p->nSwaps;
+					}
+				}
+
+			}
+
+			// go through the current upper level, which will become lower
+			for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next )
+			{
+				pUnit->lev = lev1;
+
+				pUnitER = Unit_Regular(pUnit->pE);
+				if ( pUnitER->TopRef > lev0 )
+				{
+					if ( pUnitER->Sign != p->nSwaps )
+					{
+						assert( pUnitER->TopRef == lev1 );
+						pUnitER->TopRef = lev2;
+						pUnitER->Sign   = p->nSwaps;
+						nWidthReduction++;
+					}
+				}
+
+				pUnitT  = pUnit->pT;
+				if ( pUnitT->TopRef > lev0 )
+				{
+					if ( pUnitT->Sign != p->nSwaps )
+					{
+						assert( pUnitT->TopRef == lev1 );
+						pUnitT->TopRef = lev2;
+						pUnitT->Sign   = p->nSwaps;
+						nWidthReduction++;
+					}
+				}
+			}
+		}
+		else
+		{
+//			for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next )
+//				pUnit->lev = lev1;
+			for ( pUnit = pListOld1; pUnit; pUnit = pUnit->Next )
+				pUnit->lev = lev0;
+		}
+
+		// set the new linked lists, which will be attached to the planes
+		pListNew0 = pListOld1;
+		pListNew1 = pListOld0;
+
+		if ( p->fMinApl )
+		{
+			AplWeightTotalLev0 = p->pPlanes[lev1].statsCost;
+			AplWeightTotalLev1 = p->pPlanes[lev0].statsCost;
+		}
+		
+		// set the changes in terms of nodes
+		nNodesUpMovedDown = p->pPlanes[lev0].statsNodes; 
+		nNodesDownMovedUp = p->pPlanes[lev1].statsNodes; 
+		goto finish;
+	}
+	p->Signature++;
+
+
+	// two-variable swap is done in three easy steps
+	// previously I thought that steps (1) and (2) can be merged into one step
+	// now it is clear that this cannot be done without changing a lot of other stuff...
+
+	// (1) walk through the upper level, find units without cofactors in the lower level 
+	//     and move them to the new lower level (while adding to the cache)
+	// (2) walk through the uppoer level, and tranform all the remaning nodes 
+	//     while employing cache for the new lower level
+	// (3) walk through the old lower level, find those nodes whose ref counters are not zero, 
+	//     and move them to the new uppoer level, free other nodes
+
+	// (1) walk through the upper level, find units without cofactors in the lower level 
+	//     and move them to the new lower level (while adding to the cache)
+	for ( pLoop = pListOld0; pLoop; )
+	{
+		pUnit = pLoop;
+		pLoop = pLoop->Next;
+
+		pUnitE  = pUnit->pE;
+		pUnitER = Unit_Regular(pUnitE);
+		pUnitT  = pUnit->pT;
+
+		if ( pUnitER->lev != lev1 && pUnitT->lev != lev1 )
+		{
+			//                before                        after
+			//
+			//                 <p1>                                 .
+			//              0 /    \ 1                              .
+			//               /      \                               .
+			//              /        \                              .
+			//             /          \                     <p2n>   .
+			//            /            \                  0 /  \ 1  .
+			//           /              \                  /    \   .
+			//          /                \                /      \  .
+			//         F0                F1              F0      F1
+
+			// move to plane-2-new
+			// nothing changes in the process (cofactors, ref counter, APL weight)
+			pUnit->lev = lev1;
+			AddToLinkedList( ppListNew1, pUnit );
+			if ( p->fMinApl )
+				AplWeightTotalLev1 += pUnit->Weight;
+
+			// add to cache - find the cell with different signature (not the current one!)
+			for (  HKey = hashKey3(p->Signature, pUnitE, pUnitT, p->nTableSize);
+			       p->HTable[HKey].Sign == p->Signature;
+				   HKey = (HKey+1) % p->nTableSize );
+			assert( p->HTable[HKey].Sign != p->Signature );
+			p->HTable[HKey].Sign = p->Signature;
+			p->HTable[HKey].Arg1 = pUnitE;
+			p->HTable[HKey].Arg2 = pUnitT;
+			p->HTable[HKey].Arg3 = pUnit;
+
+			nNodesUpMovedDown++;
+
+			if ( p->fMinWidth )
+			{
+				// update the cofactors's top ref
+				if ( pUnitER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
+				{
+					assert( pUnitER->TopRef == lev1 );
+					pUnitER->TopRefNew = lev2;
+					if ( pUnitER->Sign != p->nSwaps )
+					{
+						pUnitER->Sign      = p->nSwaps;  // set the current signature
+						p->pWidthCofs[ nWidthCofs++ ] = pUnitER;
+					}
+				}
+				if ( pUnitT->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
+				{
+					assert( pUnitT->TopRef == lev1 );
+					pUnitT->TopRefNew = lev2;
+					if ( pUnitT->Sign != p->nSwaps )
+					{
+						pUnitT->Sign      = p->nSwaps;  // set the current signature
+						p->pWidthCofs[ nWidthCofs++ ] = pUnitT;
+					}
+				}
+			}
+		}
+		else
+		{
+			// add to the temporary plane
+			AddToLinkedList( ppListTemp, pUnit );
+		}
+	}
+
+
+	// (2) walk through the uppoer level, and tranform all the remaning nodes 
+	//     while employing cache for the new lower level
+	for ( pLoop = pListTemp; pLoop; )
+	{
+		pUnit = pLoop;
+		pLoop = pLoop->Next;
+
+		pUnitE  = pUnit->pE;
+		pUnitER = Unit_Regular(pUnitE);
+		pUnitT  = pUnit->pT;
+		fComp   = (int)(pUnitER != pUnitE);
+
+		// count the amount of weight to reduce the APL of the children of this node
+		if ( p->fMinApl )
+			AplWeightHalf = 0.5 * pUnit->Weight;
+
+		// determine what situation is this
+		if ( pUnitER->lev == lev1 && pUnitT->lev == lev1 )
+		{
+			if ( fComp == 0 )
+			{
+				//                before                        after
+				//
+				//                 <p1>                          <p1n>              .
+				//              0 /    \ 1                    0 /    \ 1            .
+				//               /      \                      /      \             .
+				//              /        \                    /        \            .
+				//           <p2>        <p2>              <p2n>       <p2n>        .
+				//        0 /   \ 1    0 /  \ 1          0 /  \ 1    0 /   \ 1      .
+				//         /     \      /    \            /    \      /     \       .
+				//        /       \    /      \          /      \    /       \      .
+				//       F0       F1  F2      F3        F0      F2  F1       F3     .
+				//                                 pNew1E   pNew1T  pNew2E   pNew2T
+				//
+				pNew1E = pUnitE->pE;   // F0
+				pNew1T = pUnitT->pE;   // F2
+
+				pNew2E = pUnitE->pT;   // F1
+				pNew2T = pUnitT->pT;   // F3
+			}
+			else
+			{
+				//                before                        after
+				//
+				//                 <p1>                          <p1n>           .
+				//              0 .    \ 1                    0 /    \ 1         .
+				//               .      \                      /      \          .
+				//              .        \                    /        \         .
+				//           <p2>        <p2>              <p2n>       <p2n>     .
+				//        0 /   \ 1    0 /  \ 1          0 .  \ 1    0 .   \ 1   .
+				//         /     \      /    \            .    \      .     \    .
+				//        /       \    /      \          .      \    .       \   .
+				//       F0       F1  F2      F3        F0      F2  F1       F3  .
+				//                                 pNew1E   pNew1T  pNew2E   pNew2T
+				//
+				pNew1E = Unit_Not(pUnitER->pE);  // F0
+				pNew1T =          pUnitT->pE;    // F2
+
+				pNew2E = Unit_Not(pUnitER->pT);  // F1
+				pNew2T =          pUnitT->pT;    // F3
+			}
+			// subtract ref counters - on the level P2
+			pUnitER->n--;
+			pUnitT->n--;
+
+			// mark the change in the APL weights
+			if ( p->fMinApl )
+			{
+				pUnitER->Weight -= AplWeightHalf;
+				pUnitT->Weight  -= AplWeightHalf;
+				AplWeightAfter  -= pUnit->Weight;
+			}
+		}
+		else if ( pUnitER->lev == lev1 )
+		{
+			if ( fComp == 0 )
+			{
+				//                before                        after
+				//
+				//                 <p1>                          <p1n>          .
+				//              0 /    \ 1                    0 /    \ 1        .
+				//               /      \                      /      \         .
+				//              /        \                    /        \        .
+				//           <p2>         \               <p2n>       <p2n>     .
+				//        0 /   \ 1        \            0 /  \ 1    0 /   \ 1   .
+				//         /     \          \            /    \      /     \    .
+				//        /       \          \          /      \    /       \   .
+				//       F0       F1         F3        F0      F3  F1       F3  .
+				//                                 pNew1E   pNew1T  pNew2E   pNew2T
+				//
+				pNew1E = pUnitER->pE;	  // F0
+				pNew1T = pUnitT;          // F3
+
+				pNew2E = pUnitER->pT;     // F1
+				pNew2T = pUnitT;          // F3
+			}
+			else
+			{
+				//                before                        after
+				//
+				//                 <p1>                          <p1n>          .
+				//              0 .    \ 1                    0 /    \ 1        .
+				//               .      \                      /      \         .
+				//              .        \                    /        \        .
+				//           <p2>         \                <p2n>       <p2n>    .
+				//        0 /   \ 1        \            0 .  \ 1    0 .   \ 1   .
+				//         /     \          \            .    \      .     \    .
+				//        /       \          \          .      \    .       \   .
+				//       F0       F1         F3        F0      F3  F1       F3  .
+				//                                 pNew1E   pNew1T  pNew2E   pNew2T
+				//
+				pNew1E = Unit_Not(pUnitER->pE);  // F0
+				pNew1T =          pUnitT;        // F3
+
+				pNew2E = Unit_Not(pUnitER->pT);  // F1
+				pNew2T =          pUnitT;        // F3
+			}
+			// subtract ref counter - on the level P2
+			pUnitER->n--;
+			// subtract ref counter - on other levels
+			pUnitT->n--;  ///
+
+			// mark the change in the APL weights
+			if ( p->fMinApl )
+			{
+				pUnitER->Weight -= AplWeightHalf;
+				AplWeightAfter  -= AplWeightHalf;
+			}
+		}
+		else if ( pUnitT->lev == lev1 )
+		{
+			//                before                        after
+			//
+			//                 <p1>                          <p1n>           .
+			//              0 /    \ 1                    0 /    \ 1         .
+			//               /      \                      /      \          .
+			//              /        \                    /        \         .
+			//             /         <p2>              <p2n>       <p2n>     .
+			//            /       0 /   \ 1          0 /  \ 1    0 /   \ 1   .
+			//           /         /     \            /    \      /     \    .
+			//          /         /       \          /      \    /       \   .
+			//         F0        F2       F3        F0      F2  F0       F3  .
+			//                                 pNew1E   pNew1T  pNew2E   pNew2T
+			//
+			pNew1E =     pUnitE;    // F0
+			pNew1T = pUnitT->pE;    // F2
+
+			pNew2E =     pUnitE;    // F0
+			pNew2T = pUnitT->pT;    // F3
+
+			// subtract incoming edge counter - on the level P2
+			pUnitT->n--;
+			// subtract ref counter - on other levels
+			pUnitER->n--;  ///
+
+			// mark the change in the APL weights
+			if ( p->fMinApl )
+			{
+				pUnitT->Weight  -= AplWeightHalf;
+				AplWeightAfter  -= AplWeightHalf;
+			}
+		}
+		else 
+		{
+			assert( 0 ); // should never happen
+		}
+
+
+		// consider all the cases except the last one
+		if ( pNew1E == pNew1T )
+		{
+			pNewPlane20 = pNew1T;
+			
+			if ( p->fMinWidth )
+			{
+				// update the cofactors's top ref
+				if ( pNew1T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
+				{
+					pNew1T->TopRefNew = lev1;
+					if ( pNew1T->Sign  != p->nSwaps )
+					{
+						pNew1T->Sign      = p->nSwaps;  // set the current signature
+						p->pWidthCofs[ nWidthCofs++ ] = pNew1T;
+					}
+				}
+			}
+		}
+		else
+		{
+			// pNew1T can be complemented
+			fCompT = Cudd_IsComplement(pNew1T);
+			if ( fCompT )
+			{
+				pNew1E = Unit_Not(pNew1E);
+				pNew1T = Unit_Not(pNew1T);
+			}
+
+			// check the hash-table 
+			fFound = 0;
+			for (  HKey = hashKey3(p->Signature, pNew1E, pNew1T, p->nTableSize);
+			       p->HTable[HKey].Sign == p->Signature;
+				   HKey = (HKey+1) % p->nTableSize )
+			if ( p->HTable[HKey].Arg1 == pNew1E && p->HTable[HKey].Arg2 == pNew1T )
+			{ // the entry is present 
+				// assign this entry
+				pNewPlane20 = p->HTable[HKey].Arg3;
+				assert( pNewPlane20->lev == lev1 );
+				fFound = 1;
+				p->HashSuccess++;
+				break;
+			}
+
+			if ( !fFound )
+			{ // create the new entry
+				pNewPlane20 = reoUnitsGetNextUnit( p ); // increments the unit counter
+				pNewPlane20->pE  = pNew1E;
+				pNewPlane20->pT  = pNew1T;
+				pNewPlane20->n   = 0;       // ref will be added later
+				pNewPlane20->lev = lev1; 
+				if ( p->fMinWidth )
+				{
+					pNewPlane20->TopRef = lev1;
+					pNewPlane20->Sign   = 0;
+				}
+				// set the weight of this node
+				if ( p->fMinApl )
+					pNewPlane20->Weight = 0.0;
+
+				// increment ref counters of children
+				pNew1ER = Unit_Regular(pNew1E);
+				pNew1ER->n++;  //
+				pNew1T->n++;   //
+
+				// insert into the data structure
+				AddToLinkedList( ppListNew1, pNewPlane20 );
+
+				// add this entry to cache
+				assert( p->HTable[HKey].Sign != p->Signature );
+				p->HTable[HKey].Sign = p->Signature;
+				p->HTable[HKey].Arg1 = pNew1E;
+				p->HTable[HKey].Arg2 = pNew1T;
+				p->HTable[HKey].Arg3 = pNewPlane20;
+
+				nNodesUnrefAdded++;
+						
+				if ( p->fMinWidth )
+				{
+					// update the cofactors's top ref
+					if ( pNew1ER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
+					{
+						if ( pNew1ER->Sign != p->nSwaps )
+						{
+							pNew1ER->TopRefNew = lev2;
+							if ( pNew1ER->Sign != p->nSwaps )
+							{
+								pNew1ER->Sign      = p->nSwaps;  // set the current signature
+								p->pWidthCofs[ nWidthCofs++ ] = pNew1ER;
+							}
+						}
+						// otherwise the level is already set correctly
+						else
+						{
+							assert( pNew1ER->TopRefNew == lev1 || pNew1ER->TopRefNew == lev2 );
+						}
+					}
+					// update the cofactors's top ref
+					if ( pNew1T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
+					{
+						if ( pNew1T->Sign != p->nSwaps )
+						{
+							pNew1T->TopRefNew = lev2;
+							if ( pNew1T->Sign  != p->nSwaps )
+							{
+								pNew1T->Sign      = p->nSwaps;  // set the current signature
+								p->pWidthCofs[ nWidthCofs++ ] = pNew1T;
+							}
+						}
+						// otherwise the level is already set correctly
+						else
+						{
+							assert( pNew1T->TopRefNew == lev1 || pNew1T->TopRefNew == lev2 );
+						}
+					}
+				}
+			}
+
+			if ( p->fMinApl )
+			{
+				// increment the weight of this node
+				pNewPlane20->Weight += AplWeightHalf;
+				// mark the change in the APL weight
+				AplWeightAfter      += AplWeightHalf;
+				// update the total weight of this level
+				AplWeightTotalLev1  += AplWeightHalf;
+			}
+
+			if ( fCompT )
+				pNewPlane20 = Unit_Not(pNewPlane20);
+		}
+
+		if ( pNew2E == pNew2T )
+		{
+			pNewPlane21 = pNew2T;
+			
+			if ( p->fMinWidth )
+			{
+				// update the cofactors's top ref
+				if ( pNew2T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
+				{
+					pNew2T->TopRefNew = lev1;
+					if ( pNew2T->Sign != p->nSwaps )
+					{
+						pNew2T->Sign      = p->nSwaps;  // set the current signature
+						p->pWidthCofs[ nWidthCofs++ ] = pNew2T;
+					}
+				}
+			}
+		}
+		else
+		{
+			assert( !Cudd_IsComplement(pNew2T) );
+
+			// check the hash-table
+			fFound = 0;
+			for (  HKey = hashKey3(p->Signature, pNew2E, pNew2T, p->nTableSize);
+				   p->HTable[HKey].Sign == p->Signature;
+				   HKey = (HKey+1) % p->nTableSize )
+			if ( p->HTable[HKey].Arg1 == pNew2E && p->HTable[HKey].Arg2 == pNew2T )
+			{ // the entry is present 
+				// assign this entry
+				pNewPlane21 = p->HTable[HKey].Arg3;
+				assert( pNewPlane21->lev == lev1 );
+				fFound = 1;
+				p->HashSuccess++;
+				break;
+			}
+
+			if ( !fFound )
+			{ // create the new entry
+				pNewPlane21 = reoUnitsGetNextUnit( p ); // increments the unit counter
+				pNewPlane21->pE  = pNew2E;
+				pNewPlane21->pT  = pNew2T;
+				pNewPlane21->n   = 0;       // ref will be added later
+				pNewPlane21->lev = lev1; 
+				if ( p->fMinWidth )
+				{
+					pNewPlane21->TopRef = lev1;
+					pNewPlane21->Sign   = 0;
+				}
+				// set the weight of this node
+				if ( p->fMinApl )
+					pNewPlane21->Weight = 0.0;
+
+				// increment ref counters of children
+				pNew2ER = Unit_Regular(pNew2E);
+				pNew2ER->n++; //
+				pNew2T->n++;  //
+
+				// insert into the data structure
+//				reoUnitsAddUnitToPlane( &P2new, pNewPlane21 );
+				AddToLinkedList( ppListNew1, pNewPlane21 );
+
+				// add this entry to cache
+				assert( p->HTable[HKey].Sign != p->Signature );
+				p->HTable[HKey].Sign = p->Signature;
+				p->HTable[HKey].Arg1 = pNew2E;
+				p->HTable[HKey].Arg2 = pNew2T;
+				p->HTable[HKey].Arg3 = pNewPlane21;
+
+				nNodesUnrefAdded++;
+
+						
+				if ( p->fMinWidth )
+				{
+					// update the cofactors's top ref
+					if ( pNew2ER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
+					{
+						if ( pNew2ER->Sign != p->nSwaps )
+						{
+							pNew2ER->TopRefNew = lev2;
+							if ( pNew2ER->Sign != p->nSwaps )
+							{
+								pNew2ER->Sign      = p->nSwaps;  // set the current signature
+								p->pWidthCofs[ nWidthCofs++ ] = pNew2ER;
+							}
+						}
+						// otherwise the level is already set correctly
+						else
+						{
+							assert( pNew2ER->TopRefNew == lev1 || pNew2ER->TopRefNew == lev2 );
+						}
+					}
+					// update the cofactors's top ref
+					if ( pNew2T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
+					{
+						if ( pNew2T->Sign != p->nSwaps )
+						{
+							pNew2T->TopRefNew = lev2;
+							if ( pNew2T->Sign != p->nSwaps )
+							{
+								pNew2T->Sign      = p->nSwaps;  // set the current signature
+								p->pWidthCofs[ nWidthCofs++ ] = pNew2T;
+							}
+						}
+						// otherwise the level is already set correctly
+						else
+						{
+							assert( pNew2T->TopRefNew == lev1 || pNew2T->TopRefNew == lev2 );
+						}
+					}
+				}
+			}
+
+			if ( p->fMinApl )
+			{
+				// increment the weight of this node
+				pNewPlane21->Weight += AplWeightHalf;
+				// mark the change in the APL weight
+				AplWeightAfter      += AplWeightHalf;
+				// update the total weight of this level
+				AplWeightTotalLev1  += AplWeightHalf;
+			}
+		}
+		// in all cases, the node will be added to the plane-1
+		// this should be the same node (pUnit) as was originally there
+		// because it is referenced by the above nodes
+
+		assert( !Cudd_IsComplement(pNewPlane21) );
+		// should be the case; otherwise reordering is not a local operation
+
+		pUnit->pE  = pNewPlane20;
+		pUnit->pT  = pNewPlane21;
+		assert( pUnit->lev == lev0 ); 
+		// reference counter remains the same; the APL weight remains the same
+
+		// increment ref counters of children
+		pNewPlane20R = Unit_Regular(pNewPlane20);
+		pNewPlane20R->n++; ///
+		pNewPlane21->n++;  ///
+
+		// insert into the data structure
+		AddToLinkedList( ppListNew0, pUnit );
+		if ( p->fMinApl )
+			AplWeightTotalLev0 += pUnit->Weight;
+	}
+
+	// (3) walk through the old lower level, find those nodes whose ref counters are not zero, 
+	//     and move them to the new uppoer level, free other nodes
+	for ( pLoop = pListOld1; pLoop; )
+	{
+		pUnit = pLoop;
+		pLoop = pLoop->Next;
+		if ( pUnit->n )
+		{ 
+			assert( !p->fMinApl || pUnit->Weight > 0.0 );
+			// the node should be added to the new level
+			// no need to check the hash table
+			pUnit->lev = lev0;
+			AddToLinkedList( ppListNew0, pUnit );
+			if ( p->fMinApl )
+				AplWeightTotalLev0 += pUnit->Weight;
+
+			nNodesDownMovedUp++;
+
+			if ( p->fMinWidth )
+			{
+				pUnitER = Unit_Regular(pUnit->pE);
+				pUnitT  = pUnit->pT;
+
+				// update the cofactors's top ref
+				if ( pUnitER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
+				{
+					pUnitER->TopRefNew = lev1;
+					if ( pUnitER->Sign != p->nSwaps )
+					{
+						pUnitER->Sign      = p->nSwaps;  // set the current signature
+						p->pWidthCofs[ nWidthCofs++ ] = pUnitER;
+					}
+				}
+				if ( pUnitT->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
+				{
+					pUnitT->TopRefNew = lev1;
+					if ( pUnitT->Sign != p->nSwaps )
+					{
+						pUnitT->Sign      = p->nSwaps;  // set the current signature
+						p->pWidthCofs[ nWidthCofs++ ] = pUnitT;
+					}
+				}
+			}
+		}
+		else
+		{
+			assert( !p->fMinApl || pUnit->Weight == 0.0 );
+			// decrement reference counters of children
+			pUnitER = Unit_Regular(pUnit->pE);
+			pUnitT  = pUnit->pT;
+			pUnitER->n--;  ///
+			pUnitT->n--;   ///
+			// the node should be thrown away
+			reoUnitsRecycleUnit( p, pUnit );
+			nNodesUnrefRemoved++;
+		}
+	}
+
+finish:
+
+	// attach the new levels to the planes
+	p->pPlanes[lev0].pHead = pListNew0;
+	p->pPlanes[lev1].pHead = pListNew1;
+
+	// swap the sift status
+	temp                     = p->pPlanes[lev0].fSifted;
+	p->pPlanes[lev0].fSifted = p->pPlanes[lev1].fSifted;
+	p->pPlanes[lev1].fSifted = temp;
+
+	// swap variables in the variable map
+	if ( p->pOrderInt )
+	{
+		temp               = p->pOrderInt[lev0];
+		p->pOrderInt[lev0] = p->pOrderInt[lev1];
+		p->pOrderInt[lev1] = temp;
+	}
+
+	// adjust the node profile
+	p->pPlanes[lev0].statsNodes  -= (nNodesUpMovedDown - nNodesDownMovedUp);
+	p->pPlanes[lev1].statsNodes  -= (nNodesDownMovedUp - nNodesUpMovedDown) + nNodesUnrefRemoved - nNodesUnrefAdded;
+	p->nNodesCur                 -=  nNodesUnrefRemoved - nNodesUnrefAdded;
+
+	// adjust the node profile on this level
+	if ( p->fMinWidth )
+	{
+		for ( c = 0; c < nWidthCofs; c++ )
+		{
+			if ( p->pWidthCofs[c]->TopRefNew < p->pWidthCofs[c]->TopRef )
+			{
+				p->pWidthCofs[c]->TopRef = p->pWidthCofs[c]->TopRefNew;
+				nWidthReduction--;
+			}
+			else if ( p->pWidthCofs[c]->TopRefNew > p->pWidthCofs[c]->TopRef )
+			{
+				p->pWidthCofs[c]->TopRef = p->pWidthCofs[c]->TopRefNew;
+				nWidthReduction++;
+			}
+		}
+		// verify that the profile is okay
+		reoProfileWidthVerifyLevel( p->pPlanes + lev0, lev0 );
+		reoProfileWidthVerifyLevel( p->pPlanes + lev1, lev1 );
+
+		// compute the total gain in terms of width
+		nCostGain = (nNodesDownMovedUp - nNodesUpMovedDown + nNodesUnrefRemoved - nNodesUnrefAdded) + nWidthReduction;
+		// adjust the width on this level
+		p->pPlanes[lev1].statsWidth -= (int)nCostGain; 
+		// set the cost
+		p->pPlanes[lev1].statsCost   = p->pPlanes[lev1].statsWidth;
+	}
+	else if ( p->fMinApl )
+	{
+		// compute the total gain in terms of APL
+		nCostGain = AplWeightPrev - AplWeightAfter;
+		// make sure that the ALP is updated correctly
+//		assert( p->pPlanes[lev0].statsCost + p->pPlanes[lev1].statsCost - nCostGain ==
+//			    AplWeightTotalLev0 + AplWeightTotalLev1 );			    
+		// adjust the profile 
+		p->pPlanes[lev0].statsApl  = AplWeightTotalLev0;
+		p->pPlanes[lev1].statsApl  = AplWeightTotalLev1;
+		// set the cost
+		p->pPlanes[lev0].statsCost = p->pPlanes[lev0].statsApl;
+		p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsApl;
+	}
+	else
+	{
+		// compute the total gain in terms of the number of nodes
+		nCostGain = nNodesUnrefRemoved - nNodesUnrefAdded;
+		// adjust the profile (adjusted above)
+		// set the cost
+		p->pPlanes[lev0].statsCost   = p->pPlanes[lev0].statsNodes;
+		p->pPlanes[lev1].statsCost   = p->pPlanes[lev1].statsNodes;
+	}
+
+	return nCostGain;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                         END OF FILE                              ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/reo/reoTest.c b/abc-build/src/bdd/reo/reoTest.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/reo/reoTest.c
@@ -0,0 +1,256 @@
+/**CFile****************************************************************
+
+  FileName    [reoTest.c]
+
+  PackageName [REO: A specialized DD reordering engine.]
+
+  Synopsis    [Various testing procedures (may be outdated).]
+
+  Author      [Alan Mishchenko <alanmi@ece.pdx.edu>]
+  
+  Affiliation [ECE Department. Portland State University, Portland, Oregon.]
+
+  Date        [Ver. 1.0. Started - October 15, 2002.]
+
+  Revision    [$Id: reoTest.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "reo.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reorders the DD using REO and CUDD.]
+
+  Description [This function can be used to test the performance of the reordering package.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_ReorderTest( DdManager * dd, DdNode * Func )
+{
+	reo_man * pReo;
+	DdNode * Temp, * Temp1;
+	int pOrder[1000];
+
+	pReo = Extra_ReorderInit( 100, 100 );
+
+//Extra_DumpDot( dd, &Func, 1, "beforReo.dot", 0 );
+	Temp  = Extra_Reorder( pReo, dd, Func, pOrder );  Cudd_Ref( Temp );
+//Extra_DumpDot( dd, &Temp, 1, "afterReo.dot", 0 );
+
+	Temp1 = Extra_ReorderCudd(dd, Func, NULL );           Cudd_Ref( Temp1 );
+printf( "Initial = %d. Final = %d. Cudd = %d.\n", Cudd_DagSize(Func), Cudd_DagSize(Temp), Cudd_DagSize(Temp1)  );
+	Cudd_RecursiveDeref( dd, Temp1 );
+	Cudd_RecursiveDeref( dd, Temp );
+ 
+	Extra_ReorderQuit( pReo );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reorders the DD using REO and CUDD.]
+
+  Description [This function can be used to test the performance of the reordering package.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_ReorderTestArray( DdManager * dd, DdNode * Funcs[], int nFuncs )
+{
+	reo_man * pReo;
+	DdNode * FuncsRes[1000];
+	int pOrder[1000];
+	int i;
+
+	pReo = Extra_ReorderInit( 100, 100 );
+	Extra_ReorderArray( pReo, dd, Funcs, FuncsRes, nFuncs, pOrder );  
+	Extra_ReorderQuit( pReo );
+
+printf( "Initial = %d. Final = %d.\n", Cudd_SharingSize(Funcs,nFuncs), Cudd_SharingSize(FuncsRes,nFuncs) );
+
+	for ( i = 0; i < nFuncs; i++ )
+		Cudd_RecursiveDeref( dd, FuncsRes[i] );
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reorders the DD using CUDD package.]
+
+  Description [Transfers the DD into a temporary manager in such a way
+  that the level correspondence is preserved. Reorders the manager
+  and transfers the DD back into the original manager using the topmost
+  levels of the manager, in such a way that the ordering of levels is
+  preserved. The resulting permutation is returned in the array
+  given by the user.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_ReorderCudd( DdManager * dd, DdNode * aFunc, int pPermuteReo[] )
+{
+	static DdManager * ddReorder = NULL;
+	static int * Permute     = NULL;
+	static int * PermuteReo1 = NULL;
+	static int * PermuteReo2 = NULL;
+	DdNode * aFuncReorder, * aFuncNew;
+	int lev, var;
+
+	// start the reordering manager
+	if ( ddReorder == NULL )
+	{
+		Permute       = ABC_ALLOC( int, dd->size );
+		PermuteReo1   = ABC_ALLOC( int, dd->size );
+		PermuteReo2   = ABC_ALLOC( int, dd->size );
+		ddReorder = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+		Cudd_AutodynDisable(ddReorder);
+	}
+
+	// determine the permutation of variable to make sure that var order in bFunc
+	// will not change when this function is transfered into the new manager
+	for ( lev = 0; lev < dd->size; lev++ )
+	{
+		Permute[ dd->invperm[lev] ] = ddReorder->invperm[lev];
+		PermuteReo1[ ddReorder->invperm[lev] ] = dd->invperm[lev];
+	}
+	// transfer this function into the new manager in such a way that ordering of vars does not change
+	aFuncReorder = Extra_TransferPermute( dd, ddReorder, aFunc, Permute );  Cudd_Ref( aFuncReorder );
+//	assert( Cudd_DagSize(aFunc) == Cudd_DagSize(aFuncReorder)  );
+
+	// perform the reordering
+printf( "Nodes before = %d.\n", Cudd_DagSize(aFuncReorder) );
+	Cudd_ReduceHeap( ddReorder, CUDD_REORDER_SYMM_SIFT, 1 );
+printf( "Nodes before = %d.\n", Cudd_DagSize(aFuncReorder) );
+
+	// determine the reverse variable permutation
+	for ( lev = 0; lev < dd->size; lev++ )
+	{
+		Permute[ ddReorder->invperm[lev] ] = dd->invperm[lev];
+		PermuteReo2[ dd->invperm[lev] ] = ddReorder->invperm[lev];
+	}
+
+	// transfer this function into the new manager in such a way that ordering of vars does not change
+	aFuncNew = Extra_TransferPermute( ddReorder, dd, aFuncReorder, Permute );  Cudd_Ref( aFuncNew );
+//	assert( Cudd_DagSize(aFuncNew) == Cudd_DagSize(aFuncReorder)  );
+	Cudd_RecursiveDeref( ddReorder, aFuncReorder );
+
+	// derive the resulting variable ordering
+	if ( pPermuteReo )
+		for ( var = 0; var < dd->size; var++ )
+			pPermuteReo[var] = PermuteReo1[ PermuteReo2[var] ];
+
+	Cudd_Deref( aFuncNew );
+	return aFuncNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description [Transfers the BDD into another manager minimizes it and 
+  returns the min number of nodes; disposes of the BDD in the new manager.
+  Useful for debugging or comparing the performance of other reordering
+  procedures.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_bddReorderTest( DdManager * dd, DdNode * bF )
+{
+	static DdManager * s_ddmin;
+	DdNode * bFmin;
+	int  nNodes;
+//	abctime clk1;
+
+	if ( s_ddmin == NULL )
+		s_ddmin = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0);
+
+//	Cudd_ShuffleHeap( s_ddmin, dd->invperm );
+
+//	clk1 = Abc_Clock();
+	bFmin = Cudd_bddTransfer( dd, s_ddmin, bF );  Cudd_Ref( bFmin );
+	Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SIFT,1);
+//	Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT,1);
+	nNodes = Cudd_DagSize( bFmin );
+	Cudd_RecursiveDeref( s_ddmin, bFmin );
+
+//	printf( "Classical variable reordering time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+	return nNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description [Transfers the ADD into another manager minimizes it and 
+  returns the min number of nodes; disposes of the BDD in the new manager.
+  Useful for debugging or comparing the performance of other reordering
+  procedures.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_addReorderTest( DdManager * dd, DdNode * aF )
+{
+	static DdManager * s_ddmin;
+	DdNode * bF;
+	DdNode * bFmin;
+	DdNode * aFmin;
+	int  nNodesBeg;
+	int  nNodesEnd;
+	abctime clk1;
+
+	if ( s_ddmin == NULL )
+		s_ddmin = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0);
+
+//	Cudd_ShuffleHeap( s_ddmin, dd->invperm );
+
+	clk1 = Abc_Clock();
+	bF    = Cudd_addBddPattern( dd, aF );         Cudd_Ref( bF );
+	bFmin = Cudd_bddTransfer( dd, s_ddmin, bF );  Cudd_Ref( bFmin );
+	Cudd_RecursiveDeref( dd, bF );
+	aFmin = Cudd_BddToAdd( s_ddmin, bFmin );      Cudd_Ref( aFmin );
+	Cudd_RecursiveDeref( s_ddmin, bFmin );
+
+	nNodesBeg = Cudd_DagSize( aFmin );
+	Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SIFT,1);
+//	Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT,1);
+	nNodesEnd = Cudd_DagSize( aFmin );
+	Cudd_RecursiveDeref( s_ddmin, aFmin );
+
+	printf( "Classical reordering of ADDs: Before = %d. After = %d.\n", nNodesBeg, nNodesEnd );
+	printf( "Classical variable reordering time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+	return nNodesEnd;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                         END OF FILE                              ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/reo/reoTransfer.c b/abc-build/src/bdd/reo/reoTransfer.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/reo/reoTransfer.c
@@ -0,0 +1,206 @@
+/**CFile****************************************************************
+
+  FileName    [reoTransfer.c]
+
+  PackageName [REO: A specialized DD reordering engine.]
+
+  Synopsis    [Transfering a DD from the CUDD manager into REO"s internal data structures and back.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 15, 2002.]
+
+  Revision    [$Id: reoTransfer.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "reo.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the DD into the internal reordering data structure.]
+
+  Description [It is important that the hash table is lossless.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F )
+{
+	DdManager * dd = p->dd;
+	reo_unit * pUnit;
+	int HKey = -1; // Suppress "might be used uninitialized"
+        int fComp;
+	
+	fComp = Cudd_IsComplement(F);
+	F = Cudd_Regular(F);
+
+	// check the hash-table
+	if ( F->ref != 1 )
+	{
+		// search cache - use linear probing
+		for ( HKey = hashKey2(p->Signature,F,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize )
+			if ( p->HTable[HKey].Arg1 == (reo_unit *)F )
+			{
+				pUnit = p->HTable[HKey].Arg2;  
+				assert( pUnit );
+				// increment the edge counter
+				pUnit->n++;
+				return Unit_NotCond( pUnit, fComp );
+			}
+	}
+	// the entry in not found in the cache
+	
+	// create a new entry
+	pUnit         = reoUnitsGetNextUnit( p );
+	pUnit->n      = 1;
+	if ( cuddIsConstant(F) )
+	{
+		pUnit->lev    = REO_CONST_LEVEL;
+		pUnit->pE     = (reo_unit*)(ABC_PTRUINT_T)(cuddV(F));
+		pUnit->pT     = NULL;
+		// check if the diagram that is being reordering has complement edges
+		if ( F != dd->one )
+			p->fThisIsAdd = 1;
+		// insert the unit into the corresponding plane
+		reoUnitsAddUnitToPlane( &(p->pPlanes[p->nSupp]), pUnit ); // increments the unit counter
+	}
+	else
+	{
+		pUnit->lev    = p->pMapToPlanes[F->index];
+		pUnit->pE     = reoTransferNodesToUnits_rec( p, cuddE(F) );
+		pUnit->pT     = reoTransferNodesToUnits_rec( p, cuddT(F) );
+		// insert the unit into the corresponding plane
+		reoUnitsAddUnitToPlane( &(p->pPlanes[pUnit->lev]), pUnit ); // increments the unit counter
+	}
+
+	// add to the hash table
+	if ( F->ref != 1 )
+	{
+		// the next free entry is already found - it is pointed to by HKey
+		// while we traversed the diagram, the hash entry to which HKey points,
+		// might have been used. Make sure that its signature is different.
+		for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize );
+		p->HTable[HKey].Sign = p->Signature;
+		p->HTable[HKey].Arg1 = (reo_unit *)F;
+		p->HTable[HKey].Arg2 = pUnit;
+	}
+
+	// increment the counter of nodes
+	p->nNodesCur++;
+	return Unit_NotCond( pUnit, fComp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the DD from the internal reordering data structure.]
+
+  Description [It is important that the hash table is lossless.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit )
+{
+	DdManager * dd = p->dd;
+	DdNode * bRes, * E, * T;
+	int HKey = -1; // Suppress "might be used uninitialized"
+        int fComp;
+
+	fComp = Cudd_IsComplement(pUnit);
+	pUnit = Unit_Regular(pUnit);
+
+	// check the hash-table
+	if ( pUnit->n != 1 )
+	{
+		for ( HKey = hashKey2(p->Signature,pUnit,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize )
+			if ( p->HTable[HKey].Arg1 == pUnit )
+			{
+				bRes = (DdNode*) p->HTable[HKey].Arg2;  
+				assert( bRes );
+				return Cudd_NotCond( bRes, fComp );
+			}
+	}
+
+	// treat the case of constants
+	if ( Unit_IsConstant(pUnit) )
+	{
+		bRes = cuddUniqueConst( dd, ((double)((int)(ABC_PTRUINT_T)(pUnit->pE))) );
+		cuddRef( bRes );
+	}
+	else
+	{
+		// split and recur on children of this node
+		E = reoTransferUnitsToNodes_rec( p, pUnit->pE );
+		if ( E == NULL )
+			return NULL;
+		cuddRef(E);
+
+		T = reoTransferUnitsToNodes_rec( p, pUnit->pT );
+		if ( T == NULL )
+		{
+			Cudd_RecursiveDeref(dd, E);
+			return NULL;
+		}
+		cuddRef(T);
+		
+		// consider the case when Res0 and Res1 are the same node
+		assert( E != T );
+		assert( !Cudd_IsComplement(T) );
+
+		bRes = cuddUniqueInter( dd, p->pMapToDdVarsFinal[pUnit->lev], T, E );
+		if ( bRes == NULL ) 
+		{
+			Cudd_RecursiveDeref(dd,E);
+			Cudd_RecursiveDeref(dd,T);
+			return NULL;
+		}
+		cuddRef( bRes );
+		cuddDeref( E );
+		cuddDeref( T );
+	}
+
+	// do not keep the result if the ref count is only 1, since it will not be visited again
+	if ( pUnit->n != 1 )
+	{
+		 // while we traversed the diagram, the hash entry to which HKey points,
+		 // might have been used. Make sure that its signature is different.
+		 for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize );
+		 p->HTable[HKey].Sign = p->Signature;
+		 p->HTable[HKey].Arg1 = pUnit;
+		 p->HTable[HKey].Arg2 = (reo_unit *)bRes;  
+
+		 // add the DD to the referenced DD list in order to be able to store it in cache
+		 p->pRefNodes[p->nRefNodes++] = bRes;  Cudd_Ref( bRes ); 
+		 // no need to do this, because the garbage collection will not take bRes away
+		 // it is held by the diagram in the making
+	}
+	// increment the counter of nodes
+	p->nNodesCur++;
+	cuddDeref( bRes );
+	return Cudd_NotCond( bRes, fComp );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                         END OF FILE                              ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bdd/reo/reoUnits.c b/abc-build/src/bdd/reo/reoUnits.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bdd/reo/reoUnits.c
@@ -0,0 +1,190 @@
+/**CFile****************************************************************
+
+  FileName    [reoUnits.c]
+
+  PackageName [REO: A specialized DD reordering engine.]
+
+  Synopsis    [Procedures which support internal data structures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 15, 2002.]
+
+  Revision    [$Id: reoUnits.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "reo.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void reoUnitsAddToFreeUnitList( reo_man * p );
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Extract the next unit from the free unit list.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+reo_unit * reoUnitsGetNextUnit(reo_man * p )
+{
+	reo_unit * pUnit;
+	// check there are stil units to extract
+	if ( p->pUnitFreeList == NULL )
+		reoUnitsAddToFreeUnitList( p );
+	// extract the next unit from the linked list
+	pUnit            = p->pUnitFreeList;
+	p->pUnitFreeList = pUnit->Next;
+	p->nUnitsUsed++;
+	return pUnit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the unit to the free unit list.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void reoUnitsRecycleUnit( reo_man * p, reo_unit * pUnit )
+{
+	pUnit->Next      = p->pUnitFreeList;
+	p->pUnitFreeList = pUnit;
+	p->nUnitsUsed--;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the list of units to the free unit list.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void reoUnitsRecycleUnitList( reo_man * p, reo_plane * pPlane )
+{
+	reo_unit * pUnit;
+	reo_unit * pTail = NULL; // Suppress "might be used uninitialized"
+
+	if ( pPlane->pHead == NULL )
+		return;
+
+	// find the tail
+	for ( pUnit = pPlane->pHead; pUnit; pUnit = pUnit->Next )
+		pTail = pUnit;
+	pTail->Next = p->pUnitFreeList;
+	p->pUnitFreeList    = pPlane->pHead;
+	memset( pPlane, 0, sizeof(reo_plane) );
+//    pPlane->pHead = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the unit dispenser.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void reoUnitsStopDispenser( reo_man * p )
+{
+	int i;
+	for ( i = 0; i < p->nMemChunks; i++ )
+		ABC_FREE( p->pMemChunks[i] );
+//	printf("\nThe number of chunks used is %d, each of them %d units\n", p->nMemChunks, REO_CHUNK_SIZE );
+	p->nMemChunks = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one unit to the list of units which constitutes the plane.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void reoUnitsAddUnitToPlane( reo_plane * pPlane, reo_unit * pUnit )
+{
+	if ( pPlane->pHead == NULL )
+	{
+		pPlane->pHead = pUnit;
+		pUnit->Next   = NULL;
+	}
+	else
+	{
+		pUnit->Next   = pPlane->pHead;
+		pPlane->pHead = pUnit;
+	}
+	pPlane->statsNodes++;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void reoUnitsAddToFreeUnitList( reo_man * p )
+{
+	int c;
+	// check that we still have chunks left
+	if ( p->nMemChunks == p->nMemChunksAlloc )
+	{
+		printf( "reoUnitsAddToFreeUnitList(): Memory manager ran out of memory!\n" );
+		fflush( stdout );
+		return;
+	}
+	// allocate the next chunk
+	assert( p->pUnitFreeList == NULL );
+	p->pUnitFreeList = ABC_ALLOC( reo_unit, REO_CHUNK_SIZE );
+	// split chunks into list-connected units
+	for ( c = 0; c < REO_CHUNK_SIZE-1; c++ )
+		(p->pUnitFreeList + c)->Next = p->pUnitFreeList + c + 1;
+	// set the last pointer to NULL
+	(p->pUnitFreeList + REO_CHUNK_SIZE-1)->Next = NULL;
+	// add the chunk to the array of chunks
+	p->pMemChunks[p->nMemChunks++] = p->pUnitFreeList;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                         END OF FILE                              ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/bdc/bdc.h b/abc-build/src/bool/bdc/bdc.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/bdc/bdc.h
@@ -0,0 +1,98 @@
+/**CFile****************************************************************
+
+  FileName    [bdc.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Truth-table-based bi-decomposition engine.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 30, 2007.]
+
+  Revision    [$Id: bdc.h,v 1.00 2007/01/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__bdc__bdc_h
+#define ABC__aig__bdc__bdc_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+ 
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Bdc_Fun_t_ Bdc_Fun_t;
+typedef struct Bdc_Man_t_ Bdc_Man_t;
+typedef struct Bdc_Par_t_ Bdc_Par_t;
+struct Bdc_Par_t_
+{
+    // general parameters
+    int           nVarsMax;      // the maximum support
+    int           fVerbose;      // enable basic stats
+    int           fVeryVerbose;  // enable detailed stats
+};
+
+// working with complemented attributes of objects
+static inline int         Bdc_IsComplement( Bdc_Fun_t * p )      { return (int)((ABC_PTRUINT_T)p & (ABC_PTRUINT_T)01);              }
+static inline Bdc_Fun_t * Bdc_Regular( Bdc_Fun_t * p )           { return (Bdc_Fun_t *)((ABC_PTRUINT_T)p & ~(ABC_PTRUINT_T)01);     }
+static inline Bdc_Fun_t * Bdc_Not( Bdc_Fun_t * p )               { return (Bdc_Fun_t *)((ABC_PTRUINT_T)p ^  (ABC_PTRUINT_T)01);     }
+static inline Bdc_Fun_t * Bdc_NotCond( Bdc_Fun_t * p, int c )    { return (Bdc_Fun_t *)((ABC_PTRUINT_T)p ^  (ABC_PTRUINT_T)(c!=0)); }
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== bdcCore.c ==========================================================*/
+extern Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars );
+extern void        Bdc_ManFree( Bdc_Man_t * p );
+extern void        Bdc_ManDecPrint( Bdc_Man_t * p );
+extern int         Bdc_ManDecompose( Bdc_Man_t * p, unsigned * puFunc, unsigned * puCare, int nVars, Vec_Ptr_t * vDivs, int nNodesMax );
+extern Bdc_Fun_t * Bdc_ManFunc( Bdc_Man_t * p, int i );
+extern Bdc_Fun_t * Bdc_ManRoot( Bdc_Man_t * p );
+extern int         Bdc_ManNodeNum( Bdc_Man_t * p );
+extern int         Bdc_ManAndNum( Bdc_Man_t * p );
+extern Bdc_Fun_t * Bdc_FuncFanin0( Bdc_Fun_t * p );
+extern Bdc_Fun_t * Bdc_FuncFanin1( Bdc_Fun_t * p );
+extern void *      Bdc_FuncCopy( Bdc_Fun_t * p );
+extern int         Bdc_FuncCopyInt( Bdc_Fun_t * p );
+extern void        Bdc_FuncSetCopy( Bdc_Fun_t * p, void * pCopy );
+extern void        Bdc_FuncSetCopyInt( Bdc_Fun_t * p, int iCopy );
+
+/*=== working with saved copies ==========================================*/
+static inline int  Bdc_FunObjCopy( Bdc_Fun_t * pObj )     { return Abc_LitNotCond( Bdc_FuncCopyInt(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) );  }
+static inline int  Bdc_FunFanin0Copy( Bdc_Fun_t * pObj )  { return Bdc_FunObjCopy( Bdc_FuncFanin0(pObj) );                                        }
+static inline int  Bdc_FunFanin1Copy( Bdc_Fun_t * pObj )  { return Bdc_FunObjCopy( Bdc_FuncFanin1(pObj) );                                        }
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/bool/bdc/bdcCore.c b/abc-build/src/bool/bdc/bdcCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/bdc/bdcCore.c
@@ -0,0 +1,374 @@
+/**CFile****************************************************************
+
+  FileName    [bdcCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Truth-table-based bi-decomposition engine.]
+
+  Synopsis    [The gateway to bi-decomposition.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 30, 2007.]
+
+  Revision    [$Id: bdcCore.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bdcInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Accessing contents of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bdc_Fun_t *  Bdc_ManFunc( Bdc_Man_t * p, int i )               { return Bdc_FunWithId(p, i); }
+Bdc_Fun_t *  Bdc_ManRoot( Bdc_Man_t * p )                      { return p->pRoot;            }
+int          Bdc_ManNodeNum( Bdc_Man_t * p )                   { return p->nNodes;           }
+int          Bdc_ManAndNum( Bdc_Man_t * p )                    { return p->nNodes-p->nVars-1;}
+Bdc_Fun_t *  Bdc_FuncFanin0( Bdc_Fun_t * p )                   { return p->pFan0;            }
+Bdc_Fun_t *  Bdc_FuncFanin1( Bdc_Fun_t * p )                   { return p->pFan1;            }
+void *       Bdc_FuncCopy( Bdc_Fun_t * p )                     { return p->pCopy;            }
+int          Bdc_FuncCopyInt( Bdc_Fun_t * p )                  { return p->iCopy;            }
+void         Bdc_FuncSetCopy( Bdc_Fun_t * p, void * pCopy )    { p->pCopy = pCopy;           }
+void         Bdc_FuncSetCopyInt( Bdc_Fun_t * p, int iCopy )    { p->iCopy = iCopy;           }
+
+/**Function*************************************************************
+
+  Synopsis    [Allocate resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars )
+{
+    Bdc_Man_t * p;
+    p = ABC_ALLOC( Bdc_Man_t, 1 );
+    memset( p, 0, sizeof(Bdc_Man_t) );
+    assert( pPars->nVarsMax > 1 && pPars->nVarsMax < 16 );
+    p->pPars = pPars;
+    p->nWords = Kit_TruthWordNum( pPars->nVarsMax );
+    p->nDivsLimit = 200;
+    // internal nodes
+    p->nNodesAlloc = 512;
+    p->pNodes = ABC_ALLOC( Bdc_Fun_t, p->nNodesAlloc );
+    // memory
+    p->vMemory = Vec_IntStart( 8 * p->nWords * p->nNodesAlloc );
+    Vec_IntClear(p->vMemory);
+    // set up hash table
+    p->nTableSize = (1 << p->pPars->nVarsMax);
+    p->pTable = ABC_ALLOC( Bdc_Fun_t *, p->nTableSize );
+    memset( p->pTable, 0, sizeof(Bdc_Fun_t *) * p->nTableSize );
+    p->vSpots = Vec_IntAlloc( 256 );
+    // truth tables
+    p->vTruths = Vec_PtrAllocTruthTables( p->pPars->nVarsMax );
+    p->puTemp1 = ABC_ALLOC( unsigned, 4 * p->nWords );
+    p->puTemp2 = p->puTemp1 + p->nWords;
+    p->puTemp3 = p->puTemp2 + p->nWords;
+    p->puTemp4 = p->puTemp3 + p->nWords;
+    // start the internal ISFs
+    p->pIsfOL = &p->IsfOL;  Bdc_IsfStart( p, p->pIsfOL );
+    p->pIsfOR = &p->IsfOR;  Bdc_IsfStart( p, p->pIsfOR );
+    p->pIsfAL = &p->IsfAL;  Bdc_IsfStart( p, p->pIsfAL );
+    p->pIsfAR = &p->IsfAR;  Bdc_IsfStart( p, p->pIsfAR );   
+    return p; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocate resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bdc_ManFree( Bdc_Man_t * p )
+{
+    if ( p->pPars->fVerbose )
+    {
+        printf( "Bi-decomposition stats: Calls = %d.  Nodes = %d. Reuse = %d.\n", 
+            p->numCalls, p->numNodes, p->numReuse );
+        printf( "ANDs = %d.  ORs = %d.  Weak = %d.  Muxes = %d.  Memory = %.2f K\n", 
+            p->numAnds, p->numOrs, p->numWeaks, p->numMuxes, 4.0 * Vec_IntSize(p->vMemory) / (1<<10) );
+        ABC_PRT( "Cache", p->timeCache );
+        ABC_PRT( "Check", p->timeCheck );
+        ABC_PRT( "Muxes", p->timeMuxes );
+        ABC_PRT( "Supps", p->timeSupps );
+        ABC_PRT( "TOTAL", p->timeTotal );
+    }
+    Vec_IntFree( p->vMemory );
+    Vec_IntFree( p->vSpots );
+    Vec_PtrFree( p->vTruths );
+    ABC_FREE( p->puTemp1 );
+    ABC_FREE( p->pNodes );
+    ABC_FREE( p->pTable );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Clears the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bdc_ManPrepare( Bdc_Man_t * p, Vec_Ptr_t * vDivs )
+{
+    unsigned * puTruth;
+    Bdc_Fun_t * pNode;
+    int i;
+    Bdc_TableClear( p );
+    Vec_IntClear( p->vMemory );
+    // add constant 1 and elementary vars
+    p->nNodes = 0;
+    p->nNodesNew = - 1 - p->nVars - (vDivs? Vec_PtrSize(vDivs) : 0);
+    // add constant 1
+    pNode = Bdc_FunNew( p );
+    pNode->Type = BDC_TYPE_CONST1;
+    pNode->puFunc = (unsigned *)Vec_IntFetch(p->vMemory, p->nWords); 
+    Kit_TruthFill( pNode->puFunc, p->nVars );
+    pNode->uSupp = 0;
+    Bdc_TableAdd( p, pNode );
+    // add variables
+    for ( i = 0; i < p->nVars; i++ )
+    {
+        pNode = Bdc_FunNew( p );
+        pNode->Type = BDC_TYPE_PI;
+        pNode->puFunc = (unsigned *)Vec_PtrEntry( p->vTruths, i );
+        pNode->uSupp = (1 << i);
+        Bdc_TableAdd( p, pNode );
+    }
+    // add the divisors
+    if ( vDivs )
+    Vec_PtrForEachEntry( unsigned *, vDivs, puTruth, i )
+    {
+        pNode = Bdc_FunNew( p );
+        pNode->Type = BDC_TYPE_PI;
+        pNode->puFunc = puTruth;
+        pNode->uSupp = Kit_TruthSupport( puTruth, p->nVars );
+        Bdc_TableAdd( p, pNode );
+        if ( i == p->nDivsLimit )
+            break;
+    }
+    assert( p->nNodesNew == 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints bi-decomposition in a simple format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bdc_ManDecPrintSimple( Bdc_Man_t * p )
+{
+    Bdc_Fun_t * pNode;
+    int i;
+    printf( " 0 : Const 1\n" );
+    for ( i = 1; i < p->nNodes; i++ )
+    {
+        printf( " %d : ", i );
+        pNode = p->pNodes + i;
+        if ( pNode->Type == BDC_TYPE_PI )
+            printf( "PI   " );
+        else
+        {
+            printf( "%s%d &", Bdc_IsComplement(pNode->pFan0)? "-":"", Bdc_FunId(p,Bdc_Regular(pNode->pFan0)) );
+            printf( " %s%d   ", Bdc_IsComplement(pNode->pFan1)? "-":"", Bdc_FunId(p,Bdc_Regular(pNode->pFan1)) );
+        }
+//        Extra_PrintBinary( stdout, pNode->puFunc, (1<<p->nVars) );
+        printf( "\n" );
+    }
+    printf( "Root = %s%d.\n", Bdc_IsComplement(p->pRoot)? "-":"", Bdc_FunId(p,Bdc_Regular(p->pRoot)) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints bi-decomposition recursively.]
+
+  Description [This procedure prints bi-decomposition as a factored form.
+  In doing so, logic sharing, if present, will be replicated several times.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bdc_ManDecPrint_rec( Bdc_Man_t * p, Bdc_Fun_t * pNode )
+{
+    if ( pNode->Type == BDC_TYPE_PI )
+        printf( "%c", 'a' + Bdc_FunId(p,pNode) - 1 );
+    else if ( pNode->Type == BDC_TYPE_AND )
+    {
+        Bdc_Fun_t * pNode0 = Bdc_FuncFanin0( pNode );
+        Bdc_Fun_t * pNode1 = Bdc_FuncFanin1( pNode );
+
+        if ( Bdc_IsComplement(pNode0) )
+            printf( "!" );
+        if ( Bdc_IsComplement(pNode0) && Bdc_Regular(pNode0)->Type != BDC_TYPE_PI )
+            printf( "(" );
+        Bdc_ManDecPrint_rec( p, Bdc_Regular(pNode0) );
+        if ( Bdc_IsComplement(pNode0) && Bdc_Regular(pNode0)->Type != BDC_TYPE_PI )
+            printf( ")" );
+
+        if ( Bdc_IsComplement(pNode1) )
+            printf( "!" );
+        if ( Bdc_IsComplement(pNode1) && Bdc_Regular(pNode1)->Type != BDC_TYPE_PI )
+            printf( "(" );
+        Bdc_ManDecPrint_rec( p, Bdc_Regular(pNode1) );
+        if ( Bdc_IsComplement(pNode1) && Bdc_Regular(pNode1)->Type != BDC_TYPE_PI )
+            printf( ")" );
+    }
+    else assert( 0 );
+}
+void Bdc_ManDecPrint( Bdc_Man_t * p )
+{
+    Bdc_Fun_t * pRoot = Bdc_Regular(p->pRoot);
+
+    printf( "F = " );
+    if ( pRoot->Type == BDC_TYPE_CONST1 ) // constant 0
+        printf( "Constant %d", !Bdc_IsComplement(p->pRoot) );
+    else if ( pRoot->Type == BDC_TYPE_PI ) // literal
+        printf( "%s%d", Bdc_IsComplement(p->pRoot) ? "!" : "", Bdc_FunId(p,pRoot)-1 );
+    else
+    {
+        if ( Bdc_IsComplement(p->pRoot) )
+            printf( "!(" );
+        Bdc_ManDecPrint_rec( p, pRoot );
+        if ( Bdc_IsComplement(p->pRoot) )
+            printf( ")" );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs decomposition of one function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bdc_ManDecompose( Bdc_Man_t * p, unsigned * puFunc, unsigned * puCare, int nVars, Vec_Ptr_t * vDivs, int nNodesMax )
+{
+    Bdc_Isf_t Isf, * pIsf = &Isf;
+    abctime clk = Abc_Clock();
+    assert( nVars <= p->pPars->nVarsMax );
+    // set current manager parameters
+    p->nVars = nVars;
+    p->nWords = Kit_TruthWordNum( nVars );
+    p->nNodesMax = nNodesMax;
+    Bdc_ManPrepare( p, vDivs );
+    if ( puCare && Kit_TruthIsConst0( puCare, nVars ) )
+    {
+        p->pRoot = Bdc_Not(p->pNodes);
+        return 0;
+    }
+    // copy the function
+    Bdc_IsfStart( p, pIsf );
+    if ( puCare )
+    {
+        Kit_TruthAnd( pIsf->puOn, puCare, puFunc, p->nVars );
+        Kit_TruthSharp( pIsf->puOff, puCare, puFunc, p->nVars );
+    }
+    else
+    {
+        Kit_TruthCopy( pIsf->puOn, puFunc, p->nVars );
+        Kit_TruthNot( pIsf->puOff, puFunc, p->nVars );
+    }
+    Bdc_SuppMinimize( p, pIsf );
+    // call decomposition
+    p->pRoot = Bdc_ManDecompose_rec( p, pIsf );
+    p->timeTotal += Abc_Clock() - clk;
+    p->numCalls++;
+    p->numNodes += p->nNodesNew;
+    if ( p->pRoot == NULL )
+        return -1;
+    if ( !Bdc_ManNodeVerify( p, pIsf, p->pRoot ) )
+        printf( "Bdc_ManDecompose(): Internal verification failed.\n" );
+//    assert( Bdc_ManNodeVerify( p, pIsf, p->pRoot ) );
+    return p->nNodesNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs decomposition of one function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bdc_ManDecomposeTest( unsigned uTruth, int nVars )
+{
+    static int Counter = 0;
+    static int Total = 0;
+    Bdc_Par_t Pars = {0}, * pPars = &Pars;
+    Bdc_Man_t * p;
+    int RetValue;
+//    unsigned uCare = ~0x888f888f;
+    unsigned uCare = ~0;
+//    unsigned uFunc =  0x88888888;
+//    unsigned uFunc =  0xf888f888;
+//    unsigned uFunc =  0x117e117e;
+//    unsigned uFunc =  0x018b018b;
+    unsigned uFunc = uTruth; 
+
+    pPars->nVarsMax = 8;
+    p = Bdc_ManAlloc( pPars );
+    RetValue = Bdc_ManDecompose( p, &uFunc, &uCare, nVars, NULL, 1000 );
+    Total += RetValue;
+    printf( "%5d : Nodes = %5d. Total = %8d.\n", ++Counter, RetValue, Total );
+//    Bdc_ManDecPrint( p );
+    Bdc_ManFree( p );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/bdc/bdcDec.c b/abc-build/src/bool/bdc/bdcDec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/bdc/bdcDec.c
@@ -0,0 +1,751 @@
+/**CFile****************************************************************
+
+  FileName    [bdcDec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Truth-table-based bi-decomposition engine.]
+
+  Synopsis    [Decomposition procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 30, 2007.]
+
+  Revision    [$Id: bdcDec.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bdcInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Minimizes the support of the ISF.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bdc_SuppMinimize2( Bdc_Man_t * p, Bdc_Isf_t * pIsf )
+{
+    int v;
+    abctime clk = 0; // Suppress "might be used uninitialized"
+    if ( p->pPars->fVerbose )
+        clk = Abc_Clock();
+    // compute support
+    pIsf->uSupp = Kit_TruthSupport( pIsf->puOn, p->nVars ) | 
+        Kit_TruthSupport( pIsf->puOff, p->nVars );
+    // go through the support variables
+    for ( v = 0; v < p->nVars; v++ )
+    {
+        if ( (pIsf->uSupp & (1 << v)) == 0 )
+            continue;
+        Kit_TruthExistNew( p->puTemp1, pIsf->puOn, p->nVars, v );
+        Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, v );
+        if ( !Kit_TruthIsDisjoint( p->puTemp1, p->puTemp2, p->nVars ) )
+            continue;
+//        if ( !Kit_TruthVarIsVacuous( pIsf->puOn, pIsf->puOff, p->nVars, v ) )
+//            continue;
+        // remove the variable
+        Kit_TruthCopy( pIsf->puOn, p->puTemp1, p->nVars );
+        Kit_TruthCopy( pIsf->puOff, p->puTemp2, p->nVars );
+//        Kit_TruthExist( pIsf->puOn, p->nVars, v );
+//        Kit_TruthExist( pIsf->puOff, p->nVars, v );
+        pIsf->uSupp &= ~(1 << v);
+    }
+    if ( p->pPars->fVerbose )
+        p->timeSupps += Abc_Clock() - clk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Minimizes the support of the ISF.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf )
+{
+    int v;
+    abctime clk = 0; // Suppress "might be used uninitialized"
+    if ( p->pPars->fVerbose )
+        clk = Abc_Clock();
+    // go through the support variables
+    pIsf->uSupp = 0;
+    for ( v = 0; v < p->nVars; v++ )
+    {
+        if ( !Kit_TruthVarInSupport( pIsf->puOn, p->nVars, v ) && 
+             !Kit_TruthVarInSupport( pIsf->puOff, p->nVars, v ) )
+              continue;
+        if ( Kit_TruthVarIsVacuous( pIsf->puOn, pIsf->puOff, p->nVars, v ) )
+        {
+            Kit_TruthExist( pIsf->puOn, p->nVars, v );
+            Kit_TruthExist( pIsf->puOff, p->nVars, v );
+            continue;
+        }
+        pIsf->uSupp |= (1 << v);
+    }
+    if ( p->pPars->fVerbose )
+        p->timeSupps += Abc_Clock() - clk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the ISF of the right after the left was decompoosed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bdc_DecomposeUpdateRight( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR, Bdc_Fun_t * pFunc0, Bdc_Type_t Type )
+{
+    unsigned * puTruth = p->puTemp1;
+    // get the truth table of the left branch
+    if ( Bdc_IsComplement(pFunc0) )
+        Kit_TruthNot( puTruth, Bdc_Regular(pFunc0)->puFunc, p->nVars );
+    else
+        Kit_TruthCopy( puTruth, pFunc0->puFunc, p->nVars );
+    // split into parts
+	if ( Type == BDC_TYPE_OR ) 
+	{
+//		Right.Q = bdd_appex( Q, CompSpecLeftF, bddop_diff, setRightRes );
+//		Right.R = bdd_exist( R, setRightRes );
+
+//		if ( pR->Q )  Cudd_RecursiveDeref( dd, pR->Q );
+//		if ( pR->R )  Cudd_RecursiveDeref( dd, pR->R );
+//		pR->Q = Cudd_bddAndAbstract( dd, pF->Q, Cudd_Not(CompSpecF), pL->V );	Cudd_Ref( pR->Q );
+//		pR->R = Cudd_bddExistAbstract( dd, pF->R, pL->V );                      Cudd_Ref( pR->R );
+
+//		assert( pR->R != b0 );
+//		return (int)( pR->Q == b0 );
+
+        Kit_TruthSharp( pIsfR->puOn, pIsf->puOn, puTruth, p->nVars );
+        Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uUniq ); 
+        Kit_TruthExistSet( pIsfR->puOff, pIsf->puOff, p->nVars, pIsfL->uUniq ); 
+//        assert( Kit_TruthIsDisjoint(pIsfR->puOn, pIsfR->puOff, p->nVars) );
+        assert( !Kit_TruthIsConst0(pIsfR->puOff, p->nVars) );
+        return Kit_TruthIsConst0(pIsfR->puOn, p->nVars);
+	}
+	else if ( Type == BDC_TYPE_AND )
+	{
+//		Right.R = bdd_appex( R, CompSpecLeftF, bddop_and, setRightRes );
+//		Right.Q = bdd_exist( Q, setRightRes );
+
+//		if ( pR->Q )  Cudd_RecursiveDeref( dd, pR->Q );
+//		if ( pR->R )  Cudd_RecursiveDeref( dd, pR->R );
+//		pR->R = Cudd_bddAndAbstract( dd, pF->R, CompSpecF, pL->V );	            Cudd_Ref( pR->R );
+//		pR->Q = Cudd_bddExistAbstract( dd, pF->Q, pL->V );                      Cudd_Ref( pR->Q );
+
+//		assert( pR->Q != b0 );
+//		return (int)( pR->R == b0 );
+
+        Kit_TruthAnd( pIsfR->puOff, pIsf->puOff, puTruth, p->nVars );
+        Kit_TruthExistSet( pIsfR->puOff, pIsfR->puOff, p->nVars, pIsfL->uUniq ); 
+        Kit_TruthExistSet( pIsfR->puOn, pIsf->puOn, p->nVars, pIsfL->uUniq ); 
+//        assert( Kit_TruthIsDisjoint(pIsfR->puOn, pIsfR->puOff, p->nVars) );
+        assert( !Kit_TruthIsConst0(pIsfR->puOn, p->nVars) );
+        return Kit_TruthIsConst0(pIsfR->puOff, p->nVars);
+	}
+	return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks existence of OR-bidecomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Bdc_DecomposeGetCost( Bdc_Man_t * p, int nLeftVars, int nRightVars )
+{
+	assert( nLeftVars > 0 );
+	assert( nRightVars > 0 );
+	// compute the decomposition coefficient
+	if ( nLeftVars >= nRightVars )
+		return BDC_SCALE * (p->nVars * nRightVars + nLeftVars);
+	else // if ( nLeftVars < nRightVars )
+		return BDC_SCALE * (p->nVars * nLeftVars + nRightVars);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks existence of weak OR-bidecomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bdc_DecomposeFindInitialVarSet( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR )
+{
+    char pVars[16];
+	int v, nVars, Beg, End;
+
+	assert( pIsfL->uSupp == 0 );
+	assert( pIsfR->uSupp == 0 );
+
+	// fill in the variables
+    nVars = 0;
+	for ( v = 0; v < p->nVars; v++ )
+        if ( pIsf->uSupp & (1 << v) )
+            pVars[nVars++] = v;
+
+    // try variable pairs
+    for ( Beg = 0; Beg < nVars; Beg++ )
+    {
+        Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, pVars[Beg] ); 
+        for ( End = nVars - 1; End > Beg; End-- )
+        {
+            Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, pVars[End] ); 
+            if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp1, p->puTemp2, p->nVars) )
+            {
+		        pIsfL->uUniq = (1 << pVars[Beg]);
+		        pIsfR->uUniq = (1 << pVars[End]);
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks existence of weak OR-bidecomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bdc_DecomposeWeakOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR )
+{
+	int v, VarCost;
+  int VarBest = -1; // Suppress "might be used uninitialized"
+  int Cost, VarCostBest = 0;
+
+    for ( v = 0; v < p->nVars; v++ )
+	{
+        if ( (pIsf->uSupp & (1 << v)) == 0 )
+            continue;
+//		if ( (Q & !bdd_exist( R, VarSetXa )) != bddfalse )
+//		Exist = Cudd_bddExistAbstract( dd, pF->R, Var );   Cudd_Ref( Exist );
+//		if ( Cudd_bddIteConstant( dd, pF->Q, Cudd_Not(Exist), b0 ) != b0 )
+
+        Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, v );
+        if ( !Kit_TruthIsImply( pIsf->puOn, p->puTemp1, p->nVars ) )
+		{
+			// measure the cost of this variable
+//			VarCost = bdd_satcountset( bdd_forall( Q, VarSetXa ), VarCube );
+//			Univ = Cudd_bddUnivAbstract( dd, pF->Q, Var );   Cudd_Ref( Univ );
+//			VarCost = Kit_TruthCountOnes( Univ, p->nVars );
+//			Cudd_RecursiveDeref( dd, Univ );
+
+            Kit_TruthForallNew( p->puTemp2, pIsf->puOn, p->nVars, v );
+            VarCost = Kit_TruthCountOnes( p->puTemp2, p->nVars );
+			if ( VarCost == 0 )
+				VarCost = 1;
+			if ( VarCostBest < VarCost )
+			{
+				VarCostBest = VarCost;
+				VarBest = v;
+			}
+		}
+	}
+
+	// derive the components for weak-bi-decomposition if the variable is found
+	if ( VarCostBest )
+	{
+//		funQLeftRes = Q & bdd_exist( R, setRightORweak );
+//		Temp = Cudd_bddExistAbstract( dd, pF->R, VarBest );     Cudd_Ref( Temp );
+//		pL->Q = Cudd_bddAnd( dd, pF->Q, Temp );			        Cudd_Ref( pL->Q );
+//		Cudd_RecursiveDeref( dd, Temp );
+
+        Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, VarBest );
+        Kit_TruthAnd( pIsfL->puOn, pIsf->puOn, p->puTemp1, p->nVars );
+
+//		pL->R = pF->R;		                                    Cudd_Ref( pL->R );
+//		pL->V = VarBest;                                        Cudd_Ref( pL->V );
+        Kit_TruthCopy( pIsfL->puOff, pIsf->puOff, p->nVars );
+        pIsfL->uUniq = (1 << VarBest);
+        pIsfR->uUniq = 0;
+
+//		assert( pL->Q != b0 );
+//		assert( pL->R != b0 );
+//		assert( Cudd_bddIteConstant( dd, pL->Q, pL->R, b0 ) == b0 );
+//        assert( Kit_TruthIsDisjoint(pIsfL->puOn, pIsfL->puOff, p->nVars) );
+
+		// express cost in percents of the covered boolean space
+		Cost = VarCostBest * BDC_SCALE / (1<<p->nVars);
+		if ( Cost == 0 )
+			Cost = 1;
+        return Cost;
+	}
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks existence of OR-bidecomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bdc_DecomposeOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR )
+{
+    unsigned uSupportRem;
+	int v, nLeftVars = 1, nRightVars = 1; 
+    // clean the var sets
+    Bdc_IsfStart( p, pIsfL );
+    Bdc_IsfStart( p, pIsfR );
+    // check that the support is correct
+    assert( Kit_TruthSupport(pIsf->puOn, p->nVars) == Kit_TruthSupport(pIsf->puOff, p->nVars) );
+    assert( pIsf->uSupp == Kit_TruthSupport(pIsf->puOn, p->nVars) );
+    // find initial variable sets
+    if ( !Bdc_DecomposeFindInitialVarSet( p, pIsf, pIsfL, pIsfR ) )
+        return Bdc_DecomposeWeakOr( p, pIsf, pIsfL, pIsfR );
+    // prequantify the variables in the offset
+    Kit_TruthExistSet( p->puTemp1, pIsf->puOff, p->nVars, pIsfL->uUniq ); 
+    Kit_TruthExistSet( p->puTemp2, pIsf->puOff, p->nVars, pIsfR->uUniq );
+    // go through the remaining variables
+    uSupportRem = pIsf->uSupp & ~pIsfL->uUniq & ~pIsfR->uUniq;
+    for ( v = 0; v < p->nVars; v++ )
+    {
+        if ( (uSupportRem & (1 << v)) == 0 )
+            continue;
+        // prequantify this variable
+        Kit_TruthExistNew( p->puTemp3, p->puTemp1, p->nVars, v );
+        Kit_TruthExistNew( p->puTemp4, p->puTemp2, p->nVars, v );
+		if ( nLeftVars < nRightVars )
+		{
+//			if ( (Q & bdd_exist( pF->R, pL->V & VarNew ) & bdd_exist( pF->R, pR->V )) == bddfalse )
+//			if ( VerifyORCondition( dd, pF->Q, pF->R, pL->V, pR->V, VarNew ) )
+			if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp3, p->puTemp2, p->nVars) )
+			{
+//				pL->V &= VarNew;
+                pIsfL->uUniq |= (1 << v);
+				nLeftVars++;
+                Kit_TruthCopy( p->puTemp1, p->puTemp3, p->nVars );
+			}
+//			else if ( (Q & bdd_exist( pF->R, pR->V & VarNew ) & bdd_exist( pF->R, pL->V )) == bddfalse )
+			else if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp4, p->puTemp1, p->nVars) )
+			{
+//				pR->V &= VarNew;
+                pIsfR->uUniq |= (1 << v);
+				nRightVars++;
+                Kit_TruthCopy( p->puTemp2, p->puTemp4, p->nVars );
+			}
+		}
+		else
+		{
+//			if ( (Q & bdd_exist( pF->R, pR->V & VarNew ) & bdd_exist( pF->R, pL->V )) == bddfalse )
+			if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp4, p->puTemp1, p->nVars) )
+			{
+//				pR->V &= VarNew;
+                pIsfR->uUniq |= (1 << v);
+				nRightVars++;
+                Kit_TruthCopy( p->puTemp2, p->puTemp4, p->nVars );
+			}
+//			else if ( (Q & bdd_exist( pF->R, pL->V & VarNew ) & bdd_exist( pF->R, pR->V )) == bddfalse )
+			else if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp3, p->puTemp2, p->nVars) )
+			{
+//				pL->V &= VarNew;
+                pIsfL->uUniq |= (1 << v);
+				nLeftVars++;
+                Kit_TruthCopy( p->puTemp1, p->puTemp3, p->nVars );
+			}
+		}
+    }
+
+	// derive the functions Q and R for the left branch
+//	pL->Q = bdd_appex( pF->Q, bdd_exist( pF->R, pL->V ), bddop_and, pR->V );
+//	pL->R = bdd_exist( pF->R, pR->V );
+
+//	Temp = Cudd_bddExistAbstract( dd, pF->R, pL->V );      Cudd_Ref( Temp );
+//	pL->Q = Cudd_bddAndAbstract( dd, pF->Q, Temp, pR->V ); Cudd_Ref( pL->Q );
+//	Cudd_RecursiveDeref( dd, Temp );
+//	pL->R = Cudd_bddExistAbstract( dd, pF->R, pR->V );     Cudd_Ref( pL->R );
+
+    Kit_TruthAnd( pIsfL->puOn, pIsf->puOn, p->puTemp1, p->nVars );
+    Kit_TruthExistSet( pIsfL->puOn, pIsfL->puOn, p->nVars, pIsfR->uUniq );
+    Kit_TruthCopy( pIsfL->puOff, p->puTemp2, p->nVars );
+
+//	assert( pL->Q != b0 );
+//	assert( pL->R != b0 );
+//	assert( Cudd_bddIteConstant( dd, pL->Q, pL->R, b0 ) == b0 );
+    assert( !Kit_TruthIsConst0(pIsfL->puOn, p->nVars) );
+    assert( !Kit_TruthIsConst0(pIsfL->puOff, p->nVars) );
+//    assert( Kit_TruthIsDisjoint(pIsfL->puOn, pIsfL->puOff, p->nVars) );
+
+	// derive the functions Q and R for the right branch
+//	Temp = Cudd_bddExistAbstract( dd, pF->R, pR->V );      Cudd_Ref( Temp );
+//	pR->Q = Cudd_bddAndAbstract( dd, pF->Q, Temp, pL->V ); Cudd_Ref( pR->Q );
+//	Cudd_RecursiveDeref( dd, Temp );
+//	pR->R = Cudd_bddExistAbstract( dd, pF->R, pL->V );     Cudd_Ref( pR->R );
+
+    Kit_TruthAnd( pIsfR->puOn, pIsf->puOn, p->puTemp2, p->nVars );
+    Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uUniq );
+    Kit_TruthCopy( pIsfR->puOff, p->puTemp1, p->nVars );
+
+    assert( !Kit_TruthIsConst0(pIsfR->puOn, p->nVars) );
+    assert( !Kit_TruthIsConst0(pIsfR->puOff, p->nVars) );
+//    assert( Kit_TruthIsDisjoint(pIsfR->puOn, pIsfR->puOff, p->nVars) );
+
+    assert( pIsfL->uUniq );
+    assert( pIsfR->uUniq );
+	return Bdc_DecomposeGetCost( p, nLeftVars, nRightVars );		
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one step of bi-decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bdc_Type_t Bdc_DecomposeStep( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR )
+{
+    int WeightOr, WeightAnd, WeightOrL, WeightOrR, WeightAndL, WeightAndR;
+
+    Bdc_IsfClean( p->pIsfOL );
+    Bdc_IsfClean( p->pIsfOR );
+    Bdc_IsfClean( p->pIsfAL );
+    Bdc_IsfClean( p->pIsfAR );
+
+    // perform OR decomposition
+    WeightOr = Bdc_DecomposeOr( p, pIsf, p->pIsfOL, p->pIsfOR );
+
+    // perform AND decomposition
+    Bdc_IsfNot( pIsf );
+    WeightAnd = Bdc_DecomposeOr( p, pIsf, p->pIsfAL, p->pIsfAR );
+    Bdc_IsfNot( pIsf );
+    Bdc_IsfNot( p->pIsfAL );
+    Bdc_IsfNot( p->pIsfAR );
+
+    // check the case when decomposition does not exist
+    if ( WeightOr == 0 && WeightAnd == 0 )
+    {
+        Bdc_IsfCopy( pIsfL, p->pIsfOL );
+        Bdc_IsfCopy( pIsfR, p->pIsfOR );
+        return BDC_TYPE_MUX;
+    }
+    // check the hash table
+    assert( WeightOr || WeightAnd );
+    WeightOrL = WeightOrR = 0;
+    if ( WeightOr )
+    {
+        if ( p->pIsfOL->uUniq )
+        {
+            Bdc_SuppMinimize( p, p->pIsfOL );
+            WeightOrL = (Bdc_TableLookup(p, p->pIsfOL) != NULL);
+        }
+        if ( p->pIsfOR->uUniq )
+        {
+            Bdc_SuppMinimize( p, p->pIsfOR );
+            WeightOrR = (Bdc_TableLookup(p, p->pIsfOR) != NULL);
+        }
+    }
+    WeightAndL = WeightAndR = 0;
+    if ( WeightAnd )
+    {
+        if ( p->pIsfAL->uUniq )
+        {
+            Bdc_SuppMinimize( p, p->pIsfAL );
+            WeightAndL = (Bdc_TableLookup(p, p->pIsfAL) != NULL);
+        }
+        if ( p->pIsfAR->uUniq )
+        {
+            Bdc_SuppMinimize( p, p->pIsfAR );
+            WeightAndR = (Bdc_TableLookup(p, p->pIsfAR) != NULL);
+        }
+    }
+
+    // check if there is any reuse for the components
+    if ( WeightOrL + WeightOrR > WeightAndL + WeightAndR )
+    {
+        p->numReuse++;
+        p->numOrs++;
+        Bdc_IsfCopy( pIsfL, p->pIsfOL );
+        Bdc_IsfCopy( pIsfR, p->pIsfOR );
+        return BDC_TYPE_OR;
+    }
+    if ( WeightOrL + WeightOrR < WeightAndL + WeightAndR )
+    {
+        p->numReuse++;
+        p->numAnds++;
+        Bdc_IsfCopy( pIsfL, p->pIsfAL );
+        Bdc_IsfCopy( pIsfR, p->pIsfAR );
+        return BDC_TYPE_AND; 
+    }
+
+    // compare the two-component costs
+    if ( WeightOr > WeightAnd )
+    {
+        if ( WeightOr < BDC_SCALE )
+            p->numWeaks++;
+        p->numOrs++;
+        Bdc_IsfCopy( pIsfL, p->pIsfOL );
+        Bdc_IsfCopy( pIsfR, p->pIsfOR );
+        return BDC_TYPE_OR;
+    }
+    if ( WeightAnd < BDC_SCALE )
+        p->numWeaks++;
+    p->numAnds++;
+    Bdc_IsfCopy( pIsfL, p->pIsfAL );
+    Bdc_IsfCopy( pIsfR, p->pIsfAR );
+    return BDC_TYPE_AND;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find variable that leads to minimum sum of support sizes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bdc_DecomposeStepMux( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR )
+{
+    int Var, VarMin, nSuppMin, nSuppCur;
+    unsigned uSupp0, uSupp1;
+    abctime clk = 0; // Suppress "might be used uninitialized"
+    if ( p->pPars->fVerbose )
+        clk = Abc_Clock();
+    VarMin = -1;
+    nSuppMin = 1000;
+	for ( Var = 0; Var < p->nVars; Var++ )
+    {
+        if ( (pIsf->uSupp & (1 << Var)) == 0 )
+            continue;
+        Kit_TruthCofactor0New( pIsfL->puOn,  pIsf->puOn,  p->nVars, Var );
+        Kit_TruthCofactor0New( pIsfL->puOff, pIsf->puOff, p->nVars, Var );
+        Kit_TruthCofactor1New( pIsfR->puOn,  pIsf->puOn,  p->nVars, Var );
+        Kit_TruthCofactor1New( pIsfR->puOff, pIsf->puOff, p->nVars, Var );
+        uSupp0 = Kit_TruthSupport( pIsfL->puOn, p->nVars ) & Kit_TruthSupport( pIsfL->puOff, p->nVars );
+        uSupp1 = Kit_TruthSupport( pIsfR->puOn, p->nVars ) & Kit_TruthSupport( pIsfR->puOff, p->nVars );
+        nSuppCur = Kit_WordCountOnes(uSupp0) + Kit_WordCountOnes(uSupp1);  
+        if ( nSuppMin > nSuppCur )
+        {
+            nSuppMin = nSuppCur;
+            VarMin = Var;
+            break;
+        }
+    }
+    if ( VarMin >= 0 )
+    {
+        Kit_TruthCofactor0New( pIsfL->puOn,  pIsf->puOn,  p->nVars, VarMin );
+        Kit_TruthCofactor0New( pIsfL->puOff, pIsf->puOff, p->nVars, VarMin );
+        Kit_TruthCofactor1New( pIsfR->puOn,  pIsf->puOn,  p->nVars, VarMin );
+        Kit_TruthCofactor1New( pIsfR->puOff, pIsf->puOff, p->nVars, VarMin );
+        Bdc_SuppMinimize( p, pIsfL );
+        Bdc_SuppMinimize( p, pIsfR );
+    }
+    if ( p->pPars->fVerbose )
+        p->timeMuxes += Abc_Clock() - clk;
+    return VarMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bdc_ManNodeVerify( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Fun_t * pFunc )
+{
+    unsigned * puTruth = p->puTemp1;
+    if ( Bdc_IsComplement(pFunc) )
+        Kit_TruthNot( puTruth, Bdc_Regular(pFunc)->puFunc, p->nVars );
+    else
+        Kit_TruthCopy( puTruth, pFunc->puFunc, p->nVars );
+    return Bdc_TableCheckContainment( p, pIsf, puTruth );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bdc_Fun_t * Bdc_ManCreateGate( Bdc_Man_t * p, Bdc_Fun_t * pFunc0, Bdc_Fun_t * pFunc1, Bdc_Type_t Type )
+{
+    Bdc_Fun_t * pFunc;
+    pFunc = Bdc_FunNew( p );
+    if ( pFunc == NULL )
+        return NULL;
+    pFunc->Type = Type;
+    pFunc->pFan0 = pFunc0;
+    pFunc->pFan1 = pFunc1;
+    pFunc->puFunc = (unsigned *)Vec_IntFetch(p->vMemory, p->nWords); 
+    // get the truth table of the left branch
+    if ( Bdc_IsComplement(pFunc0) )
+        Kit_TruthNot( p->puTemp1, Bdc_Regular(pFunc0)->puFunc, p->nVars );
+    else
+        Kit_TruthCopy( p->puTemp1, pFunc0->puFunc, p->nVars );
+    // get the truth table of the right branch
+    if ( Bdc_IsComplement(pFunc1) )
+        Kit_TruthNot( p->puTemp2, Bdc_Regular(pFunc1)->puFunc, p->nVars );
+    else
+        Kit_TruthCopy( p->puTemp2, pFunc1->puFunc, p->nVars );
+    // compute the function of node
+    if ( pFunc->Type == BDC_TYPE_AND )
+    {
+        Kit_TruthAnd( pFunc->puFunc, p->puTemp1, p->puTemp2, p->nVars );
+    }
+    else if ( pFunc->Type == BDC_TYPE_OR )
+    {
+        Kit_TruthOr( pFunc->puFunc, p->puTemp1, p->puTemp2, p->nVars );
+        // transform to AND gate
+        pFunc->Type = BDC_TYPE_AND;
+        pFunc->pFan0 = Bdc_Not(pFunc->pFan0);
+        pFunc->pFan1 = Bdc_Not(pFunc->pFan1);
+        Kit_TruthNot( pFunc->puFunc, pFunc->puFunc, p->nVars );
+        pFunc = Bdc_Not(pFunc);
+    }
+    else 
+        assert( 0 );
+    // add to table
+    Bdc_Regular(pFunc)->uSupp = Kit_TruthSupport( Bdc_Regular(pFunc)->puFunc, p->nVars );
+    Bdc_TableAdd( p, Bdc_Regular(pFunc) );
+    return pFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one step of bi-decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bdc_Fun_t * Bdc_ManDecompose_rec( Bdc_Man_t * p, Bdc_Isf_t * pIsf )
+{
+//    int static Counter = 0;
+//    int LocalCounter = Counter++;
+    Bdc_Type_t Type;
+    Bdc_Fun_t * pFunc, * pFunc0, * pFunc1;
+    Bdc_Isf_t IsfL, * pIsfL = &IsfL;
+    Bdc_Isf_t IsfB, * pIsfR = &IsfB;
+    int iVar;
+    abctime clk = 0; // Suppress "might be used uninitialized"
+/*
+printf( "Init function (%d):\n", LocalCounter );
+Extra_PrintBinary( stdout, pIsf->puOn, 1<<4 );printf("\n");
+Extra_PrintBinary( stdout, pIsf->puOff, 1<<4 );printf("\n");
+*/
+    // check computed results
+    assert( Kit_TruthIsDisjoint(pIsf->puOn, pIsf->puOff, p->nVars) );
+    if ( p->pPars->fVerbose )
+        clk = Abc_Clock();
+    pFunc = Bdc_TableLookup( p, pIsf );
+    if ( p->pPars->fVerbose )
+        p->timeCache += Abc_Clock() - clk;
+    if ( pFunc )
+        return pFunc;
+    // decide on the decomposition type
+    if ( p->pPars->fVerbose )
+        clk = Abc_Clock();
+    Type = Bdc_DecomposeStep( p, pIsf, pIsfL, pIsfR );
+    if ( p->pPars->fVerbose )
+        p->timeCheck += Abc_Clock() - clk;
+    if ( Type == BDC_TYPE_MUX )
+    {
+        if ( p->pPars->fVerbose )
+            clk = Abc_Clock();
+        iVar = Bdc_DecomposeStepMux( p, pIsf, pIsfL, pIsfR );
+        if ( p->pPars->fVerbose )
+            p->timeMuxes += Abc_Clock() - clk;
+        p->numMuxes++;
+        pFunc0 = Bdc_ManDecompose_rec( p, pIsfL );
+        pFunc1 = Bdc_ManDecompose_rec( p, pIsfR );
+        if ( pFunc0 == NULL || pFunc1 == NULL )
+            return NULL;
+        pFunc  = Bdc_FunWithId( p, iVar + 1 );
+        pFunc0 = Bdc_ManCreateGate( p, Bdc_Not(pFunc), pFunc0, BDC_TYPE_AND );
+        pFunc1 = Bdc_ManCreateGate( p, pFunc,  pFunc1, BDC_TYPE_AND );
+        if ( pFunc0 == NULL || pFunc1 == NULL )
+            return NULL;
+        pFunc = Bdc_ManCreateGate( p, pFunc0, pFunc1, BDC_TYPE_OR );
+    }
+    else
+    {
+        pFunc0 = Bdc_ManDecompose_rec( p, pIsfL );
+        if ( pFunc0 == NULL )
+            return NULL;
+        // decompose the right branch
+        if ( Bdc_DecomposeUpdateRight( p, pIsf, pIsfL, pIsfR, pFunc0, Type ) )
+        {
+            p->nNodesNew--;
+            return pFunc0;
+        }
+        Bdc_SuppMinimize( p, pIsfR );
+        pFunc1 = Bdc_ManDecompose_rec( p, pIsfR );
+        if ( pFunc1 == NULL )
+            return NULL;
+        // create new gate
+        pFunc = Bdc_ManCreateGate( p, pFunc0, pFunc1, Type );
+    }
+    return pFunc;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/bdc/bdcInt.h b/abc-build/src/bool/bdc/bdcInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/bdc/bdcInt.h
@@ -0,0 +1,165 @@
+/**CFile****************************************************************
+
+  FileName    [bdcInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Truth-table-based bi-decomposition engine.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 15, 2007.]
+
+  Revision    [$Id: resInt.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__bdc__bdcInt_h
+#define ABC__aig__bdc__bdcInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "bool/kit/kit.h"
+#include "bdc.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+#define BDC_SCALE 1000  // value used to compute the cost
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// network types
+typedef enum { 
+    BDC_TYPE_NONE = 0,  // 0:  unknown
+    BDC_TYPE_CONST1,    // 1:  constant 1
+    BDC_TYPE_PI,        // 2:  primary input
+    BDC_TYPE_AND,       // 3:  AND-gate
+    BDC_TYPE_OR,        // 4:  OR-gate (temporary)
+    BDC_TYPE_XOR,       // 5:  XOR-gate
+    BDC_TYPE_MUX,       // 6:  MUX-gate
+    BDC_TYPE_OTHER      // 7:  unused
+} Bdc_Type_t;
+
+struct Bdc_Fun_t_
+{
+    int              Type;         // Const1, PI, AND, XOR, MUX
+    Bdc_Fun_t *      pFan0;        // fanin of the given node
+    Bdc_Fun_t *      pFan1;        // fanin of the given node
+    unsigned         uSupp;        // bit mask of current support
+    unsigned *       puFunc;       // the function of the node
+    Bdc_Fun_t *      pNext;        // next function with same support
+    union { int      iCopy;        // the literal of the node (AIG)
+    void *           pCopy; };     // the function of the node (BDD or AIG)
+
+};
+
+typedef struct Bdc_Isf_t_ Bdc_Isf_t;
+struct Bdc_Isf_t_
+{
+    unsigned         uSupp;        // the complete support of this component
+    unsigned         uUniq;        // the unique variables of this component
+    unsigned *       puOn;         // on-set
+    unsigned *       puOff;        // off-set
+};
+
+struct Bdc_Man_t_
+{
+    // external parameters
+    Bdc_Par_t *      pPars;        // parameter set
+    int              nVars;        // the number of variables
+    int              nWords;       // the number of words 
+    int              nNodesMax;    // the limit on the number of new nodes
+    int              nDivsLimit;   // the limit on the number of divisors
+    // internal nodes
+    Bdc_Fun_t *      pNodes;       // storage for decomposition nodes
+    int              nNodesAlloc;  // the number of nodes allocated  
+    int              nNodes;       // the number of all nodes created so far
+    int              nNodesNew;    // the number of new AND nodes created so far
+    Bdc_Fun_t *      pRoot;        // the root node
+    // resub candidates
+    Bdc_Fun_t **     pTable;       // hash table of candidates
+    int              nTableSize;   // hash table size (1 << nVarsMax)
+    Vec_Int_t *      vSpots;       // the occupied spots in the table
+    // elementary truth tables 
+    Vec_Ptr_t *      vTruths;      // for const 1 and elementary variables
+    unsigned *       puTemp1;      // temporary truth table
+    unsigned *       puTemp2;      // temporary truth table
+    unsigned *       puTemp3;      // temporary truth table
+    unsigned *       puTemp4;      // temporary truth table
+    // temporary ISFs
+    Bdc_Isf_t * pIsfOL, IsfOL;
+    Bdc_Isf_t * pIsfOR, IsfOR;
+    Bdc_Isf_t * pIsfAL, IsfAL;
+    Bdc_Isf_t * pIsfAR, IsfAR;
+    // internal memory manager
+    Vec_Int_t *      vMemory;      // memory for internal truth tables
+    // statistics
+    int              numCalls;
+    int              numNodes;
+    int              numMuxes;
+    int              numAnds;
+    int              numOrs;
+    int              numWeaks;
+    int              numReuse;
+    // runtime
+    abctime          timeCache;
+    abctime          timeCheck;
+    abctime          timeMuxes;
+    abctime          timeSupps;
+    abctime          timeTotal;
+};
+
+static inline Bdc_Fun_t * Bdc_FunNew( Bdc_Man_t * p )                   { Bdc_Fun_t * pRes; if ( p->nNodes >= p->nNodesAlloc || p->nNodesNew >= p->nNodesMax ) return NULL; pRes = p->pNodes + p->nNodes++; p->nNodesNew++; memset( pRes, 0, sizeof(Bdc_Fun_t) ); return pRes; }
+static inline Bdc_Fun_t * Bdc_FunWithId( Bdc_Man_t * p, int Id )        { assert( Id < p->nNodes ); return p->pNodes + Id; }
+static inline int         Bdc_FunId( Bdc_Man_t * p, Bdc_Fun_t * pFun )  { return pFun - p->pNodes; }
+static inline void        Bdc_IsfStart( Bdc_Man_t * p, Bdc_Isf_t * pF ) { pF->uSupp = 0; pF->uUniq = 0; pF->puOn = Vec_IntFetch( p->vMemory, p->nWords ); pF->puOff = Vec_IntFetch( p->vMemory, p->nWords ); assert( pF->puOff && pF->puOn ); }
+static inline void        Bdc_IsfClean( Bdc_Isf_t * p )                 { p->uSupp = 0; p->uUniq = 0;                                      }
+static inline void        Bdc_IsfCopy( Bdc_Isf_t * p, Bdc_Isf_t * q )   { Bdc_Isf_t T = *p; *p = *q; *q = T;                               }
+static inline void        Bdc_IsfNot( Bdc_Isf_t * p )                   { unsigned * puT = p->puOn; p->puOn = p->puOff; p->puOff = puT;    }
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== bdcDec.c ==========================================================*/
+extern Bdc_Fun_t *      Bdc_ManDecompose_rec( Bdc_Man_t * p, Bdc_Isf_t * pIsf );
+extern void             Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf );
+extern int              Bdc_ManNodeVerify( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Fun_t * pFunc );
+/*=== bdcTable.c ==========================================================*/
+extern Bdc_Fun_t *      Bdc_TableLookup( Bdc_Man_t * p, Bdc_Isf_t * pIsf );
+extern void             Bdc_TableAdd( Bdc_Man_t * p, Bdc_Fun_t * pFunc );
+extern void             Bdc_TableClear( Bdc_Man_t * p );
+extern int              Bdc_TableCheckContainment( Bdc_Man_t * p, Bdc_Isf_t * pIsf, unsigned * puTruth );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/bool/bdc/bdcSpfd.c b/abc-build/src/bool/bdc/bdcSpfd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/bdc/bdcSpfd.c
@@ -0,0 +1,1183 @@
+/**CFile****************************************************************
+
+  FileName    [bdcSpfd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Truth-table-based bi-decomposition engine.]
+
+  Synopsis    [The gateway to bi-decomposition.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 30, 2007.]
+
+  Revision    [$Id: bdcSpfd.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bdcInt.h"
+#include "aig/aig/aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Bdc_Nod_t_ Bdc_Nod_t;
+struct Bdc_Nod_t_
+{
+    unsigned         iFan0g :  8;
+    unsigned         iFan0n : 12;
+    unsigned         Type   : 12;  // 0-3 = AND; 4 = XOR
+
+    unsigned         iFan1g :  8;
+    unsigned         iFan1n : 12;
+    unsigned         Weight : 12;
+
+    word             Truth;
+};
+
+static word Truths[6] = {
+    ABC_CONST(0xAAAAAAAAAAAAAAAA),
+    ABC_CONST(0xCCCCCCCCCCCCCCCC),
+    ABC_CONST(0xF0F0F0F0F0F0F0F0),
+    ABC_CONST(0xFF00FF00FF00FF00),
+    ABC_CONST(0xFFFF0000FFFF0000),
+    ABC_CONST(0xFFFFFFFF00000000)
+};
+
+static inline int Bdc_CountOnes( word t )
+{
+    t =    (t & ABC_CONST(0x5555555555555555)) + ((t>> 1) & ABC_CONST(0x5555555555555555));
+    t =    (t & ABC_CONST(0x3333333333333333)) + ((t>> 2) & ABC_CONST(0x3333333333333333));
+    t =    (t & ABC_CONST(0x0F0F0F0F0F0F0F0F)) + ((t>> 4) & ABC_CONST(0x0F0F0F0F0F0F0F0F));
+    t =    (t & ABC_CONST(0x00FF00FF00FF00FF)) + ((t>> 8) & ABC_CONST(0x00FF00FF00FF00FF));
+    t =    (t & ABC_CONST(0x0000FFFF0000FFFF)) + ((t>>16) & ABC_CONST(0x0000FFFF0000FFFF));
+    return (t & ABC_CONST(0x00000000FFFFFFFF)) +  (t>>32);
+}
+
+static inline int Bdc_CountSpfd( word t, word f )
+{
+    int n00 = Bdc_CountOnes( ~t & ~f );
+    int n01 = Bdc_CountOnes(  t & ~f );
+    int n10 = Bdc_CountOnes( ~t &  f );
+    int n11 = Bdc_CountOnes(  t &  f );
+    return n00 * n11 + n10 * n01;
+}
+
+static inline word Bdc_Cof6( word t, int iVar, int fCof1 )
+{
+    assert( iVar >= 0 && iVar < 6 );
+    if ( fCof1 )
+        return (t & Truths[iVar]) | ((t & Truths[iVar]) >> (1<<iVar));
+    else
+        return (t &~Truths[iVar]) | ((t &~Truths[iVar]) << (1<<iVar));
+}
+
+int Bdc_SpfdAdjCost( word t )
+{
+    word c0, c1;
+    int v, Cost = 0;
+    for ( v = 0; v < 6; v++ )
+    {
+        c0 = Bdc_Cof6( t, v, 0 );
+        c1 = Bdc_Cof6( t, v, 1 );
+        Cost += Bdc_CountOnes( c0 ^ c1 );
+    }
+    return Cost;
+}
+
+
+extern void  Abc_Show6VarFunc( word F0, word F1 );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bdc_SpfdPrint_rec( Bdc_Nod_t * pNode, int Level, Vec_Ptr_t * vLevels )
+{
+    assert( Level > 0 );
+    printf( "(" );
+
+    if ( pNode->Type & 1 )
+        printf( "!" );
+    if ( pNode->iFan0g == 0 )
+        printf( "%c", 'a' + pNode->iFan0n );
+    else
+    {
+        Bdc_Nod_t * pNode0 = (Bdc_Nod_t *)Vec_PtrEntry(vLevels, pNode->iFan0g);
+        Bdc_SpfdPrint_rec( pNode0 + pNode->iFan0n, pNode->iFan0g, vLevels );
+    }
+
+    if ( pNode->Type & 4 )
+        printf( "+" );
+    else
+        printf( "*" );
+
+    if ( pNode->Type & 2 )
+        printf( "!" );
+    if ( pNode->iFan1g == 0 )
+        printf( "%c", 'a' + pNode->iFan1n );
+    else
+    {
+        Bdc_Nod_t * pNode1 = (Bdc_Nod_t *)Vec_PtrEntry(vLevels, pNode->iFan1g);
+        Bdc_SpfdPrint_rec( pNode1 + pNode->iFan1n, pNode->iFan1g, vLevels );
+    }
+
+    printf( ")" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bdc_SpfdPrint( Bdc_Nod_t * pNode, int Level, Vec_Ptr_t * vLevels, word Truth )
+{
+    word Diff = Truth ^ pNode->Truth;
+    Extra_PrintHex( stdout, (unsigned *)&pNode->Truth, 6 ); printf( "   " );
+    Extra_PrintHex( stdout, (unsigned *)&Diff, 6 );         printf( "   " );
+    Bdc_SpfdPrint_rec( pNode, Level, vLevels );
+    printf( "    %d\n", pNode->Weight );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bdc_SpfdDecompose( word Truth, int nVars, int nCands, int nGatesMax )
+{
+    int nSize = nCands * nCands * (nGatesMax + 1) * 5;
+    Vec_Ptr_t * vLevels;
+    Vec_Int_t * vBegs, * vWeight;
+    Bdc_Nod_t * pNode, * pNode0, * pNode1, * pNode2;
+    int Count0, Count1, * pPerm;
+    int i, j, k, c, n;
+    abctime clk;
+    assert( nGatesMax < (1<<8) );
+    assert( nCands < (1<<12) );
+    assert( (1<<(nVars-1))*(1<<(nVars-1)) < (1<<12) ); // max SPFD
+
+    printf( "Storage size = %d (%d * %d * %d * %d).\n", nSize, nCands, nCands, nGatesMax + 1, 5 );
+
+    printf( "SPFD = %d.\n", Bdc_CountOnes(Truth) * Bdc_CountOnes(~Truth) );
+
+    // consider elementary functions
+    if ( Truth == 0 || Truth == ~0 )
+    {
+        printf( "Function is a constant.\n" );
+        return;
+    }
+    for ( i = 0; i < nVars; i++ )
+        if ( Truth == Truths[i] || Truth == ~Truths[i] )
+        {
+            printf( "Function is an elementary variable.\n" );
+            return;
+        }
+
+    // allocate
+    vLevels = Vec_PtrAlloc( 100 );
+    vBegs = Vec_IntAlloc( 100 );
+    vWeight = Vec_IntAlloc( 100 );
+
+    // initialize elementary variables
+    pNode = ABC_CALLOC( Bdc_Nod_t, nVars );
+    for ( i = 0; i < nVars; i++ )
+        pNode[i].Truth  = Truths[i];
+    for ( i = 0; i < nVars; i++ )
+        pNode[i].Weight = Bdc_CountSpfd( pNode[i].Truth, Truth );
+    Vec_PtrPush( vLevels, pNode );
+    Vec_IntPush( vBegs, nVars );
+
+    // the next level
+clk = Abc_Clock();
+    pNode0 = pNode;
+    pNode  = ABC_CALLOC( Bdc_Nod_t, 5 * nVars * (nVars - 1) / 2 );
+    for ( c = i = 0; i < nVars; i++ )
+    for ( j = i+1; j < nVars; j++ )
+    {
+        pNode[c].Truth =  pNode0[i].Truth &  pNode0[j].Truth;  pNode[c].iFan0n = i; pNode[c].iFan1n = j;  pNode[c++].Type = 0;
+        pNode[c].Truth = ~pNode0[i].Truth &  pNode0[j].Truth;  pNode[c].iFan0n = i; pNode[c].iFan1n = j;  pNode[c++].Type = 1;
+        pNode[c].Truth =  pNode0[i].Truth & ~pNode0[j].Truth;  pNode[c].iFan0n = i; pNode[c].iFan1n = j;  pNode[c++].Type = 2;
+        pNode[c].Truth = ~pNode0[i].Truth & ~pNode0[j].Truth;  pNode[c].iFan0n = i; pNode[c].iFan1n = j;  pNode[c++].Type = 3;
+        pNode[c].Truth =  pNode0[i].Truth ^  pNode0[j].Truth;  pNode[c].iFan0n = i; pNode[c].iFan1n = j;  pNode[c++].Type = 4;
+    }
+    assert( c == 5 * nVars * (nVars - 1) / 2 );
+    Vec_PtrPush( vLevels, pNode );
+    Vec_IntPush( vBegs, c );
+    for ( i = 0; i < c; i++ )
+    {
+        pNode[i].Weight = Bdc_CountSpfd( pNode[i].Truth, Truth );
+//Bdc_SpfdPrint( pNode + i, 1, vLevels );
+        if ( Truth == pNode[i].Truth || Truth == ~pNode[i].Truth )
+        {
+            printf( "Function can be implemented using 1 gate.\n" );
+            pNode = NULL;
+            goto cleanup;
+        }
+    }
+printf( "Selected %6d gates on level %2d.   ", c, 1 );
+Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+
+
+    // iterate through levels
+    pNode = ABC_CALLOC( Bdc_Nod_t, nSize );
+    for ( n = 2; n <= nGatesMax; n++ )
+    {
+clk = Abc_Clock();
+        c = 0;
+        pNode1 = (Bdc_Nod_t *)Vec_PtrEntry( vLevels, n-1 );
+        Count1 = Vec_IntEntry( vBegs, n-1 );
+        // go through previous levels
+        for ( k = 0; k < n-1; k++ )
+        {
+            pNode0 = (Bdc_Nod_t *)Vec_PtrEntry( vLevels, k );
+            Count0 = Vec_IntEntry( vBegs, k );
+            for ( i = 0; i < Count0; i++ )
+            for ( j = 0; j < Count1; j++ )
+            {
+                pNode[c].Truth =  pNode0[i].Truth &  pNode1[j].Truth;  pNode[c].iFan0g = k; pNode[c].iFan1g = n-1;  pNode[c].iFan0n = i; pNode[c].iFan1n = j;  pNode[c++].Type = 0;
+                pNode[c].Truth = ~pNode0[i].Truth &  pNode1[j].Truth;  pNode[c].iFan0g = k; pNode[c].iFan1g = n-1;  pNode[c].iFan0n = i; pNode[c].iFan1n = j;  pNode[c++].Type = 1;
+                pNode[c].Truth =  pNode0[i].Truth & ~pNode1[j].Truth;  pNode[c].iFan0g = k; pNode[c].iFan1g = n-1;  pNode[c].iFan0n = i; pNode[c].iFan1n = j;  pNode[c++].Type = 2;
+                pNode[c].Truth = ~pNode0[i].Truth & ~pNode1[j].Truth;  pNode[c].iFan0g = k; pNode[c].iFan1g = n-1;  pNode[c].iFan0n = i; pNode[c].iFan1n = j;  pNode[c++].Type = 3;
+                pNode[c].Truth =  pNode0[i].Truth ^  pNode1[j].Truth;  pNode[c].iFan0g = k; pNode[c].iFan1g = n-1;  pNode[c].iFan0n = i; pNode[c].iFan1n = j;  pNode[c++].Type = 4;
+            }
+            assert( c < nSize );
+        }
+        // go through current level
+        for ( i = 0; i < Count1; i++ )
+        for ( j = i+1; j < Count1; j++ )
+        {
+            pNode[c].Truth =  pNode1[i].Truth &  pNode1[j].Truth;  pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1;  pNode[c].iFan0n = i; pNode[c].iFan1n = j;  pNode[c++].Type = 0;
+            pNode[c].Truth = ~pNode1[i].Truth &  pNode1[j].Truth;  pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1;  pNode[c].iFan0n = i; pNode[c].iFan1n = j;  pNode[c++].Type = 1;
+            pNode[c].Truth =  pNode1[i].Truth & ~pNode1[j].Truth;  pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1;  pNode[c].iFan0n = i; pNode[c].iFan1n = j;  pNode[c++].Type = 2;
+            pNode[c].Truth = ~pNode1[i].Truth & ~pNode1[j].Truth;  pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1;  pNode[c].iFan0n = i; pNode[c].iFan1n = j;  pNode[c++].Type = 3;
+            pNode[c].Truth =  pNode1[i].Truth ^  pNode1[j].Truth;  pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1;  pNode[c].iFan0n = i; pNode[c].iFan1n = j;  pNode[c++].Type = 4;
+        }
+        assert( c < nSize );
+        // sort
+        Vec_IntClear( vWeight );
+        for ( i = 0; i < c; i++ )
+        {
+            pNode[i].Weight = Bdc_CountSpfd( pNode[i].Truth, Truth );
+if ( pNode[i].Weight > 300 )
+Bdc_SpfdPrint( pNode + i, 1, vLevels, Truth );
+            Vec_IntPush( vWeight, pNode[i].Weight );
+
+            if ( Truth == pNode[i].Truth || Truth == ~pNode[i].Truth )
+            {
+                printf( "Function can be implemented using %d gates.\n", n );
+                Bdc_SpfdPrint( pNode + i, n, vLevels, Truth );
+                goto cleanup;
+            }
+        }
+        pPerm = Abc_MergeSortCost( Vec_IntArray(vWeight), c );
+        assert( Vec_IntEntry(vWeight, pPerm[0]) <= Vec_IntEntry(vWeight, pPerm[c-1]) );
+
+        printf( "Best SPFD = %d.\n", Vec_IntEntry(vWeight, pPerm[c-1]) );
+//        for ( i = 0; i < c; i++ )
+//printf( "%d ", Vec_IntEntry(vWeight, pPerm[i]) );
+
+        // choose the best ones
+        pNode2 = ABC_CALLOC( Bdc_Nod_t, nCands );
+        for ( j = 0, i = c-1; i >= 0; i-- )
+        {
+            pNode2[j++] = pNode[pPerm[i]];
+            if ( j == nCands )
+                break;
+        }
+        ABC_FREE( pPerm );
+        Vec_PtrPush( vLevels, pNode2 );
+        Vec_IntPush( vBegs, j );
+
+printf( "Selected %6d gates (out of %6d) on level %2d.   ", j, c, n );
+Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+
+        for ( i = 0; i < 10; i++ )
+            Bdc_SpfdPrint( pNode2 + i, n, vLevels, Truth );
+    }
+
+cleanup:
+    ABC_FREE( pNode );
+    Vec_PtrForEachEntry( Bdc_Nod_t *, vLevels, pNode, i )
+        ABC_FREE( pNode );
+    Vec_PtrFree( vLevels );
+    Vec_IntFree( vBegs );
+    Vec_IntFree( vWeight );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bdc_SpfdDecomposeTest_()
+{
+    int fTry = 0;
+//    word T[17];
+//    int i;
+
+//    word Truth    = Truths[0] & ~Truths[3];
+//    word Truth    = (Truths[0] & Truths[1]) | (Truths[2] & Truths[3]) | (Truths[4] & Truths[5]);
+//    word Truth    = (Truths[0] & Truths[1]) | ((Truths[2] & ~Truths[3]) ^ (Truths[4] & ~Truths[5]));
+//    word Truth    = (Truths[0] & Truths[1]) | (Truths[2] & Truths[3]);
+//    word Truth = 0x9ef7a8d9c7193a0f;  // AAFFAAFF0A0F0A0F
+//    word Truth = 0x34080226CD163000;
+    word Truth = ABC_CONST(0x5052585a0002080a);
+    int nVars     =    6;
+    int nCands    =  200;// 75;
+    int nGatesMax =   20;
+
+    if ( fTry )
+    Bdc_SpfdDecompose( Truth, nVars, nCands, nGatesMax );
+/*
+    for ( i = 0; i < 6; i++ )
+        T[i] = Truths[i];
+    T[7]  = 0;
+    T[8]  = ~T[1]  &  T[3];
+    T[9]  = ~T[8]  &  T[0];
+    T[10] =  T[1]  &  T[4];
+    T[11] =  T[10] &  T[2];
+    T[12] =  T[11] &  T[9];
+    T[13] = ~T[0]  &  T[5];
+    T[14] =  T[2]  &  T[13];
+    T[15] = ~T[12] & ~T[14];
+    T[16] = ~T[15];
+//    if ( T[16] != Truth )
+//        printf( "Failed\n" );
+
+    for ( i = 0; i < 17; i++ )
+    {
+//        printf( "%2d = %3d  ", i, Bdc_CountSpfd(T[i], Truth) );
+        printf( "%2d = %3d  ", i, Bdc_CountSpfd(T[i], T[16]) );
+        Extra_PrintBinary( stdout, (unsigned *)&T[i], 64 ); printf( "\n" );
+    }
+//    Extra_PrintBinary( stdout, (unsigned *)&Truth, 64 ); printf( "\n" );
+*/
+}
+
+
+
+
+typedef struct Bdc_Ent_t_ Bdc_Ent_t; // 24 bytes
+struct Bdc_Ent_t_
+{
+    unsigned         iFan0   : 29;
+    unsigned         fCompl0 :  1;
+    unsigned         fCompl  :  1;
+    unsigned         fMark0  :  1;
+    unsigned         iFan1   : 29;
+    unsigned         fCompl1 :  1;
+    unsigned         fExor   :  1;
+    unsigned         fMark1  :  1;
+    int              iNext;
+    int              iList;
+    word             Truth;
+};
+
+#define BDC_TERM 0x1FFFFFFF
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bdc_SpfdMark0( Bdc_Ent_t * p, Bdc_Ent_t * pEnt )
+{
+    if ( pEnt->iFan0 == BDC_TERM )
+        return 0;
+    if ( pEnt->fMark0 )
+        return 0;
+    pEnt->fMark0 = 1;
+    return pEnt->fMark1 + 
+        Bdc_SpfdMark0(p, p + pEnt->iFan0) + 
+        Bdc_SpfdMark0(p, p + pEnt->iFan1);
+}
+int Bdc_SpfdMark1( Bdc_Ent_t * p, Bdc_Ent_t * pEnt )
+{
+    if ( pEnt->iFan0 == BDC_TERM )
+        return 0;
+    if ( pEnt->fMark1 )
+        return 0;
+    pEnt->fMark1 = 1;
+    return pEnt->fMark0 + 
+        Bdc_SpfdMark1(p, p + pEnt->iFan0) + 
+        Bdc_SpfdMark1(p, p + pEnt->iFan1);
+}
+void Bdc_SpfdUnmark0( Bdc_Ent_t * p, Bdc_Ent_t * pEnt )
+{
+    if ( pEnt->iFan0 == BDC_TERM )
+        return;
+    pEnt->fMark0 = 0;
+    Bdc_SpfdUnmark0( p, p + pEnt->iFan0 );
+    Bdc_SpfdUnmark0( p, p + pEnt->iFan1 );
+}
+void Bdc_SpfdUnmark1( Bdc_Ent_t * p, Bdc_Ent_t * pEnt )
+{
+    if ( pEnt->iFan0 == BDC_TERM )
+        return;
+    pEnt->fMark1 = 0;
+    Bdc_SpfdUnmark1( p, p + pEnt->iFan0 );
+    Bdc_SpfdUnmark1( p, p + pEnt->iFan1 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bdc_SpfdCheckOverlap( Bdc_Ent_t * p, Bdc_Ent_t * pEnt0, Bdc_Ent_t * pEnt1 )
+{
+    int RetValue;
+    RetValue = Bdc_SpfdMark0( p, pEnt0 );
+    assert( RetValue == 0 );
+    RetValue = Bdc_SpfdMark1( p, pEnt1 );
+    Bdc_SpfdUnmark0( p, pEnt0 );
+    Bdc_SpfdUnmark1( p, pEnt1 );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bdc_SpfdHashValue( word t, int Size )
+{
+    // http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
+    // 53,
+    // 97,
+    // 193,
+    // 389,
+    // 769,
+    // 1543,
+    // 3079,
+    // 6151,
+    // 12289,
+    // 24593,
+    // 49157,
+    // 98317,
+    // 196613,
+    // 393241,
+    // 786433,
+    // 1572869,
+    // 3145739,
+    // 6291469,
+    // 12582917,
+    // 25165843,
+    // 50331653,
+    // 100663319,
+    // 201326611,
+    // 402653189,
+    // 805306457,
+    // 1610612741,
+    static unsigned BigPrimes[8] = {12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741};
+    unsigned char * s = (unsigned char *)&t;
+    unsigned i, Value = 0;
+    for ( i = 0; i < 8; i++ )
+        Value ^= BigPrimes[i] * s[i];
+    return Value % Size;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Bdc_SpfdHashLookup( Bdc_Ent_t * p, int Size, word t )
+{
+    Bdc_Ent_t * pBin = p + Bdc_SpfdHashValue( t, Size );
+    if ( pBin->iList == 0 )
+        return &pBin->iList;
+    for ( pBin = p + pBin->iList; ; pBin = p + pBin->iNext )
+    {
+        if ( pBin->Truth == t )
+            return NULL;
+        if ( pBin->iNext == 0 )
+            return &pBin->iNext;
+    }
+    assert( 0 );
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Wrd_t * Bdc_SpfdDecomposeTest__( Vec_Int_t ** pvWeights )
+{
+//    int nFuncs = 8000000; // the number of functions to compute
+//    int nSize  = 2777111; // the hash table size to use
+//    int Limit  = 6;
+    
+//    int nFuncs = 51000000; // the number of functions to compute
+//    int nSize  = 50331653; // the hash table size to use
+//    int Limit  = 6;
+    
+    int nFuncs = 250000000; // the number of functions to compute
+    int nSize  = 201326611; // the hash table size to use
+    int Limit  = 6;
+
+    int * pPlace, i, n, m, k, s, fCompl;
+    abctime clk = Abc_Clock(), clk2;
+    Vec_Int_t * vStops;
+    Vec_Wrd_t * vTruths;
+    Vec_Int_t * vWeights;
+    Bdc_Ent_t * p, * q, * pBeg0, * pEnd0, * pBeg1, * pEnd1, * pThis0, * pThis1;
+    word t0, t1, t;
+    assert( nSize <= nFuncs );
+
+    printf( "Allocating %.2f MB of internal memory.\n", 1.0*sizeof(Bdc_Ent_t)*nFuncs/(1<<20) );
+
+    p = (Bdc_Ent_t *)calloc( nFuncs, sizeof(Bdc_Ent_t) );
+    memset( p, 255, sizeof(Bdc_Ent_t) );
+    p->iList = 0;
+    for ( q = p; q < p+nFuncs; q++ )
+       q->iList = 0;
+    q = p + 1;
+    printf( "Added %d + %d + 0 = %d. Total = %8d.\n", 0, 0, 0, (int)(q-p) );
+
+    vTruths  = Vec_WrdStart( nFuncs );
+    vWeights = Vec_IntStart( nFuncs );
+    Vec_WrdClear( vTruths );
+    Vec_IntClear( vWeights );
+
+    // create elementary vars
+    vStops = Vec_IntAlloc( 10 );
+    Vec_IntPush( vStops, 1 );
+    for ( i = 0; i < 6; i++ )
+    {
+        q->iFan0 = BDC_TERM;
+        q->iFan1 = i;
+        q->Truth = Truths[i];
+        pPlace   = Bdc_SpfdHashLookup( p, nSize, q->Truth );
+        *pPlace  = q-p;
+        q++;
+        Vec_WrdPush( vTruths, Truths[i] );
+        Vec_IntPush( vWeights, 0 );
+    }
+    Vec_IntPush( vStops, 7 );
+    printf( "Added %d + %d + 0 = %d. Total = %8d.\n", 0, 0, 0, (int)(q-p) );
+
+    // create gates
+    for ( n = 0; n < Limit; n++ )
+    {
+        // try previous
+        for ( k = 0; k < Limit; k++ )
+        for ( m = 0; m < Limit; m++ )
+        {
+            if ( k + m != n || k > m )
+                continue;
+            // set the start and stop
+            pBeg0 = p + Vec_IntEntry( vStops, k );
+            pEnd0 = p + Vec_IntEntry( vStops, k+1 );
+            // set the start and stop
+            pBeg1 = p + Vec_IntEntry( vStops, m );
+            pEnd1 = p + Vec_IntEntry( vStops, m+1 );
+
+            clk2 = Abc_Clock();
+            printf( "Trying %7d  x %7d.  ", (int)(pEnd0-pBeg0), (int)(pEnd1-pBeg1) );
+            for ( pThis0 = pBeg0; pThis0 < pEnd0; pThis0++ )
+            for ( pThis1 = pBeg1; pThis1 < pEnd1; pThis1++ )
+            if ( k < m || pThis1 > pThis0 )
+//            if ( n < 5 || Bdc_SpfdCheckOverlap(p, pThis0, pThis1) )
+            for ( s = 0; s < 5; s++ )
+            {
+                t0 = (s&1)      ? ~pThis0->Truth : pThis0->Truth;
+                t1 = ((s>>1)&1) ? ~pThis1->Truth : pThis1->Truth;
+                t  = ((s>>2)&1) ? t0 ^ t1 : t0 & t1;
+                fCompl = t & 1;
+                if ( fCompl )
+                    t = ~t;
+                if ( t == 0 )
+                    continue;
+                pPlace = Bdc_SpfdHashLookup( p, nSize, t );
+                if ( pPlace == NULL )
+                    continue;
+                q->iFan0   = pThis0-p;
+                q->fCompl0 = s&1;
+                q->iFan1   = pThis1-p;
+                q->fCompl1 = (s>>1)&1;
+                q->fExor   = (s>>2)&1;
+                q->Truth   = t;
+                q->fCompl  = fCompl;
+                *pPlace = q-p;
+                q++;
+                Vec_WrdPush( vTruths, t );
+//                Vec_IntPush( vWeights, n == 5 ? n : n+1 );
+                Vec_IntPush( vWeights, n+1 );
+                if ( q-p == nFuncs )
+                {
+                    printf( "Reached limit of %d functions.\n", nFuncs );
+                    goto finish;
+                }
+            }
+            printf( "Added %d + %d + 1 = %d. Total = %8d.   ", k, m, n+1, (int)(q-p) );
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 );
+        }
+        Vec_IntPush( vStops, q-p );
+    }
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+
+
+    {
+        FILE * pFile = fopen( "func6v6n_bin.txt", "wb" );
+        fwrite( Vec_WrdArray(vTruths), sizeof(word), Vec_WrdSize(vTruths), pFile );
+        fclose( pFile );
+    }
+    {
+        FILE * pFile = fopen( "func6v6nW_bin.txt", "wb" );
+        fwrite( Vec_IntArray(vWeights), sizeof(int), Vec_IntSize(vWeights), pFile );
+        fclose( pFile );
+    }
+
+
+finish:
+    Vec_IntFree( vStops );
+    free( p );
+
+    *pvWeights = vWeights;
+//    Vec_WrdFree( vTruths );
+    return vTruths;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Wrd_t * Bdc_SpfdReadFiles5( Vec_Int_t ** pvWeights )
+{
+    Vec_Int_t * vWeights;
+    Vec_Wrd_t * vDivs;
+    FILE * pFile;
+    int RetValue;
+    
+    vDivs = Vec_WrdStart( 3863759 );
+    pFile = fopen( "func6v5n_bin.txt", "rb" );
+    RetValue = fread( Vec_WrdArray(vDivs), sizeof(word), Vec_WrdSize(vDivs), pFile );
+    fclose( pFile );
+
+    vWeights = Vec_IntStart( 3863759 );
+    pFile = fopen( "func6v5nW_bin.txt", "rb" );
+    RetValue = fread( Vec_IntArray(vWeights), sizeof(int), Vec_IntSize(vWeights), pFile );
+    fclose( pFile );
+
+    *pvWeights = vWeights;
+    return vDivs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Wrd_t * Bdc_SpfdReadFiles6( Vec_Int_t ** pvWeights )
+{
+    Vec_Int_t * vWeights;
+    Vec_Wrd_t * vDivs = Vec_WrdStart( 12776759 );
+    FILE * pFile = fopen( "func6v6n_bin.txt", "rb" );
+    int RetValue;
+    RetValue = fread( Vec_WrdArray(vDivs), sizeof(word), Vec_WrdSize(vDivs), pFile );
+    fclose( pFile );
+
+    vWeights = Vec_IntStart( 12776759 );
+    pFile = fopen( "func6v6nW_bin.txt", "rb" );
+    RetValue = fread( Vec_IntArray(vWeights), sizeof(int), Vec_IntSize(vWeights), pFile );
+    fclose( pFile );
+
+    *pvWeights = vWeights;
+    return vDivs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bdc_SpfdComputeCost( word f, int i, Vec_Int_t * vWeights )
+{
+    int Ones = Bdc_CountOnes(f);
+    if ( Ones == 0 )
+        return -1;
+    return 7*Ones + 10*(8 - Vec_IntEntry(vWeights, i));
+//    return Bdc_CountOnes(f);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word Bdc_SpfdFindBest( Vec_Wrd_t * vDivs, Vec_Int_t * vWeights, word F0, word F1, int * pCost )
+{
+    word Func, FuncBest;
+    int i, Cost, CostBest = -1, NumBest = -1;
+    Vec_WrdForEachEntry( vDivs, Func, i )
+    {
+        if ( (Func & F0) == 0 )
+        {
+            Cost = Bdc_SpfdComputeCost(Func & F1, i, vWeights);
+            if ( CostBest < Cost )
+            {
+                CostBest = Cost;
+                FuncBest = Func;
+                NumBest  = i;
+            }
+        }
+        if ( (Func & F1) == 0 )
+        {
+            Cost = Bdc_SpfdComputeCost(Func & F0, i, vWeights);
+            if ( CostBest < Cost )
+            {
+                CostBest = Cost;
+                FuncBest = Func;
+                NumBest  = i;
+            }
+        }
+        if ( (~Func & F0) == 0 )
+        {
+            Cost = Bdc_SpfdComputeCost(~Func & F1, i, vWeights);
+            if ( CostBest < Cost )
+            {
+                CostBest = Cost;
+                FuncBest = ~Func;
+                NumBest  = i;
+            }
+        }
+        if ( (~Func & F1) == 0 )
+        {
+            Cost = Bdc_SpfdComputeCost(~Func & F0, i, vWeights);
+            if ( CostBest < Cost )
+            {
+                CostBest = Cost;
+                FuncBest = ~Func;
+                NumBest  = i;
+            }
+        }
+    }
+    (*pCost) += Vec_IntEntry(vWeights, NumBest);
+    assert( CostBest > 0 );
+    printf( "Selected %8d with cost %2d and weight %d: ", NumBest, 0, Vec_IntEntry(vWeights, NumBest) );
+    Extra_PrintHex( stdout, (unsigned *)&FuncBest, 6 ); printf( "\n" );
+    return FuncBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bdc_SpfdDecomposeTestOne( word t, Vec_Wrd_t * vDivs, Vec_Int_t * vWeights )
+{
+    word F1 = t;
+    word F0 = ~F1;
+    word Func;
+    int i, Cost = 0;
+    printf( "Trying: " );
+    Extra_PrintHex( stdout, (unsigned *)&t, 6 ); printf( "\n" );
+//    Abc_Show6VarFunc( F0, F1 );   
+    for ( i = 0; F0 && F1; i++ )
+    {
+        printf( "*** ITER %2d   ", i );
+        Func = Bdc_SpfdFindBest( vDivs, vWeights, F0, F1, &Cost );
+        F0 &= ~Func;
+        F1 &= ~Func;
+//        Abc_Show6VarFunc( F0, F1 );    
+    }
+    Cost += (i-1);
+    printf( "Produce solution with cost %2d (with adj cost %4d).\n", Cost, Bdc_SpfdAdjCost(t) );
+    return Cost;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bdc_SpfdDecomposeTest44()
+{
+//    word t = 0x5052585a0002080a;
+
+    word t = ABC_CONST(0x9ef7a8d9c7193a0f);
+//    word t = 0x6BFDA276C7193A0F;
+//    word t = 0xA3756AFE0B1DF60B;
+
+//    word t = 0xFEF7AEBFCE80AA0F;
+//    word t = 0x9EF7FDBFC77F6F0F;
+//    word t = 0xDEF7FDFF377F6FFF;
+
+//    word t = 0x345D02736DB390A5; // xor with var 0
+
+//    word t = 0x3EFDA2736D139A0F; // best solution after changes
+
+    Vec_Int_t * vWeights;
+    Vec_Wrd_t * vDivs;
+    word c0, c1, s, tt, tbest;
+    int i, j, Cost, CostBest = 100000;
+    abctime clk = Abc_Clock();
+
+    return;
+
+//    printf( "%d\n", RAND_MAX );
+
+    vDivs = Bdc_SpfdDecomposeTest__( &vWeights );
+//    vDivs = Bdc_SpfdReadFiles5( &vWeights );
+
+//    Abc_Show6VarFunc( ~t, t );  
+
+    // try function
+    tt = t;
+    Cost = Bdc_SpfdDecomposeTestOne( tt, vDivs, vWeights );
+    if ( CostBest > Cost )
+    {
+        CostBest = Cost;
+        tbest = tt;
+    }
+    printf( "\n" );
+
+    // try complemented output
+    for ( i = 0; i < 6; i++ )
+    {
+        tt = t ^ Truths[i];
+        Cost = Bdc_SpfdDecomposeTestOne( tt, vDivs, vWeights );
+        if ( CostBest > Cost )
+        {
+            CostBest = Cost;
+            tbest = tt;
+        }
+    }
+    printf( "\n" );
+
+    // try complemented input
+    for ( i = 0; i < 6; i++ )
+    for ( j = 0; j < 6; j++ )
+    {
+        if ( i == j )
+            continue;
+        c0 = Bdc_Cof6( t, i, 0 );
+        c1 = Bdc_Cof6( t, i, 1 );
+        s  = Truths[i] ^ Truths[j];
+        tt = (~s & c0) | (s & c1);
+
+        Cost = Bdc_SpfdDecomposeTestOne( tt, vDivs, vWeights );
+        if ( CostBest > Cost )
+        {
+            CostBest = Cost;
+            tbest = tt;
+        }
+    }
+
+/*
+    for ( i = 0; i < 6; i++ )
+    for ( j = 0; j < 6; j++ )
+    {
+        if ( i == j )
+            continue;
+        c0 = Bdc_Cof6( t, i, 0 );
+        c1 = Bdc_Cof6( t, i, 1 );
+        s  = Truths[i] ^ Truths[j];
+        tt = (~s & c0) | (s & c1);
+
+        for ( k = 0; k < 6; k++ )
+        for ( n = 0; n < 6; n++ )
+        {
+            if ( k == n )
+                continue;
+            c0 = Bdc_Cof6( tt, k, 0 );
+            c1 = Bdc_Cof6( tt, k, 1 );
+            s  = Truths[k] ^ Truths[n];
+            ttt= (~s & c0) | (s & c1);
+
+            Cost = Bdc_SpfdDecomposeTestOne( ttt, vDivs, vWeights );
+            if ( CostBest > Cost )
+            {
+                CostBest = Cost;
+                tbest = ttt;
+            }
+        }
+    }
+*/
+
+    printf( "Best solution found with cost %d.  ", CostBest );
+    Extra_PrintHex( stdout, (unsigned *)&tbest, 6 ); //printf( "\n" );
+    Abc_PrintTime( 1, "  Time", Abc_Clock() - clk );
+
+    Vec_WrdFree( vDivs );
+    Vec_IntFree( vWeights );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bdc_SpfdDecomposeTest3()
+{
+    int nSizeM = (1 << 26);
+    int nSizeK = (1 << 3);
+    Vec_Wrd_t * v1M;
+    Vec_Wrd_t * v1K;
+    int i, k, Counter;
+    abctime clk;
+//    int EntryM, EntryK;
+    Aig_ManRandom64( 1 );
+
+    v1M = Vec_WrdAlloc( nSizeM );
+    for ( i = 0; i < nSizeM; i++ )
+        Vec_WrdPush( v1M, Aig_ManRandom64(0) );
+
+    v1K = Vec_WrdAlloc( nSizeK );
+    for ( i = 0; i < nSizeK; i++ )
+        Vec_WrdPush( v1K, Aig_ManRandom64(0) );
+
+    clk = Abc_Clock();
+    Counter = 0;
+    for ( i = 0; i < nSizeM; i++ )
+    for ( k = 0; k < nSizeK; k++ )
+        Counter += ((v1M->pArray[i] & v1K->pArray[k]) == v1K->pArray[k]);
+//    Vec_WrdForEachEntry( v1M, EntryM, i )
+//    Vec_WrdForEachEntry( v1K, EntryK, k )
+//        Counter += ((EntryM & EntryK) == EntryK);
+
+    printf( "Total = %8d.  ", Counter );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+
+    clk = Abc_Clock();
+    Counter = 0;
+    for ( k = 0; k < nSizeK; k++ )
+    for ( i = 0; i < nSizeM; i++ )
+        Counter += ((v1M->pArray[i] & v1K->pArray[k]) == v1K->pArray[k]);
+    printf( "Total = %8d.  ", Counter );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bdc_SpfdDecomposeTest8()
+{
+//    word t = 0x9ef7a8d9c7193a0f;
+//    word t = 0x9EF7FDBFC77F6F0F;
+    word t = ABC_CONST(0x513B57150819050F);
+
+    Vec_Int_t * vWeights;
+    Vec_Wrd_t * vDivs;
+    word Func, FuncBest;
+    int Cost, CostBest = ABC_INFINITY;
+    int i;
+    abctime clk = Abc_Clock();
+
+//    return;
+
+    vDivs = Bdc_SpfdReadFiles5( &vWeights );
+
+    printf( "Best init = %4d.  ", Bdc_SpfdAdjCost(t) );
+    Extra_PrintHex( stdout, (unsigned *)&t, 6 ); //printf( "\n" );
+    Abc_PrintTime( 1, "  Time", Abc_Clock() - clk );
+
+    Vec_WrdForEachEntry( vDivs, Func, i )
+    {
+        Cost = Bdc_SpfdAdjCost( t ^ Func );
+        if ( CostBest > Cost )
+        {
+            CostBest = Cost;
+            FuncBest = Func;
+        }
+    }
+
+    printf( "Best cost = %4d.  ", CostBest );
+    Extra_PrintHex( stdout, (unsigned *)&FuncBest, 6 ); //printf( "\n" );
+    Abc_PrintTime( 1, "  Time", Abc_Clock() - clk );
+
+Abc_Show6VarFunc( 0, t );
+Abc_Show6VarFunc( 0, FuncBest );
+Abc_Show6VarFunc( 0, (FuncBest ^ t) );
+
+    FuncBest ^= t;
+    Extra_PrintHex( stdout, (unsigned *)&FuncBest, 6 ); printf( "\n" );
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bdc_SpfdDecomposeTest()
+{
+  int nSizeM = (1 << 26);  // big array size
+  int nSizeK = (1 << 3);   // small array size
+  Vec_Wrd_t * v1M, * v1K;
+  int EntryM, EntryK;
+  int i, k, Counter;
+  abctime clk;
+
+  Aig_ManRandom64( 1 );
+
+  v1M = Vec_WrdAlloc( nSizeM );
+  for ( i = 0; i < nSizeM; i++ )
+      Vec_WrdPush( v1M, Aig_ManRandom64(0) );
+
+  v1K = Vec_WrdAlloc( nSizeK );
+  for ( i = 0; i < nSizeK; i++ )
+      Vec_WrdPush( v1K, Aig_ManRandom64(0) );
+
+  clk = Abc_Clock();
+  Counter = 0;
+//  for ( i = 0; i < nSizeM; i++ )
+//  for ( k = 0; k < nSizeK; k++ )
+//      Counter += ((v1M->pArray[i] & v1K->pArray[k]) == v1K->pArray[k]);
+  Vec_WrdForEachEntry( v1M, EntryM, i )
+  Vec_WrdForEachEntry( v1K, EntryK, k )
+      Counter += ((EntryM & EntryK) == EntryK);
+  printf( "Total = %8d.  ", Counter );
+  Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+
+  clk = Abc_Clock();
+  Counter = 0;
+//  for ( k = 0; k < nSizeK; k++ )
+//  for ( i = 0; i < nSizeM; i++ )
+//      Counter += ((v1M->pArray[i] & v1K->pArray[k]) == v1K->pArray[k]);
+  Vec_WrdForEachEntry( v1K, EntryK, k )
+  Vec_WrdForEachEntry( v1M, EntryM, i )
+      Counter += ((EntryM & EntryK) == EntryK);
+  printf( "Total = %8d.  ", Counter );
+  Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/bdc/bdcTable.c b/abc-build/src/bool/bdc/bdcTable.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/bdc/bdcTable.c
@@ -0,0 +1,134 @@
+/**CFile****************************************************************
+
+  FileName    [bdcTable.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Truth-table-based bi-decomposition engine.]
+
+  Synopsis    [Hash table for intermediate nodes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 30, 2007.]
+
+  Revision    [$Id: bdcTable.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bdcInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Checks containment of the function in the ISF.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bdc_TableCheckContainment( Bdc_Man_t * p, Bdc_Isf_t * pIsf, unsigned * puTruth )
+{
+    return Kit_TruthIsImply( pIsf->puOn, puTruth, p->nVars ) &&
+         Kit_TruthIsDisjoint( puTruth, pIsf->puOff, p->nVars );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the new entry to the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bdc_Fun_t * Bdc_TableLookup( Bdc_Man_t * p, Bdc_Isf_t * pIsf )
+{
+    int fDisableCache = 0;
+    Bdc_Fun_t * pFunc;
+    if ( fDisableCache && Kit_WordCountOnes(pIsf->uSupp) > 1 )
+        return NULL;
+    if ( pIsf->uSupp == 0 )
+    {
+        assert( p->pTable[pIsf->uSupp] == p->pNodes );
+        if ( Kit_TruthIsConst1( pIsf->puOn, p->nVars ) )
+            return p->pNodes;
+        assert( Kit_TruthIsConst1( pIsf->puOff, p->nVars ) );
+        return Bdc_Not(p->pNodes);
+    }
+    for ( pFunc = p->pTable[pIsf->uSupp]; pFunc; pFunc = pFunc->pNext )
+        if ( Bdc_TableCheckContainment( p, pIsf, pFunc->puFunc ) )
+             return pFunc;
+    Bdc_IsfNot( pIsf );
+    for ( pFunc = p->pTable[pIsf->uSupp]; pFunc; pFunc = pFunc->pNext )
+        if ( Bdc_TableCheckContainment( p, pIsf, pFunc->puFunc ) )
+        {
+            Bdc_IsfNot( pIsf );
+            return Bdc_Not(pFunc);
+        }
+    Bdc_IsfNot( pIsf );
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the new entry to the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bdc_TableAdd( Bdc_Man_t * p, Bdc_Fun_t * pFunc )
+{
+    if ( p->pTable[pFunc->uSupp] == NULL )
+        Vec_IntPush( p->vSpots, pFunc->uSupp );
+    pFunc->pNext = p->pTable[pFunc->uSupp];
+    p->pTable[pFunc->uSupp] = pFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the new entry to the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bdc_TableClear( Bdc_Man_t * p )
+{
+    int Spot, i;
+    Vec_IntForEachEntry( p->vSpots, Spot, i )
+        p->pTable[Spot] = NULL;
+    Vec_IntClear( p->vSpots );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/bdc/bdc_.c b/abc-build/src/bool/bdc/bdc_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/bdc/bdc_.c
@@ -0,0 +1,54 @@
+/**CFile****************************************************************
+
+  FileName    [bdc_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Truth-table-based bi-decomposition engine.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 30, 2007.]
+
+  Revision    [$Id: bdc_.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bdcInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/bdc/module.make b/abc-build/src/bool/bdc/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/bdc/module.make
@@ -0,0 +1,5 @@
+SRC +=  src/bool/bdc/bdcCore.c \
+	src/bool/bdc/bdcDec.c \
+	src/bool/bdc/bdcSpfd.c \
+	src/bool/bdc/bdcTable.c
+
diff --git a/abc-build/src/bool/dec/dec.h b/abc-build/src/bool/dec/dec.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/dec/dec.h
@@ -0,0 +1,725 @@
+/**CFile****************************************************************
+
+  FileName    [dec.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [A simple decomposition tree/node data structure and its APIs.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: dec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__opt__dec__dec_h
+#define ABC__opt__dec__dec_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Dec_Edge_t_ Dec_Edge_t;
+struct Dec_Edge_t_
+{
+    unsigned          fCompl   :  1;   // the complemented bit
+    unsigned          Node     : 30;   // the decomposition node pointed by the edge
+};
+
+typedef struct Dec_Node_t_ Dec_Node_t;
+struct Dec_Node_t_
+{
+    Dec_Edge_t        eEdge0;          // the left child of the node
+    Dec_Edge_t        eEdge1;          // the right child of the node
+    // other info
+    union { int       iFunc;           // the literal of the node (AIG)
+    void *            pFunc; };        // the function of the node (BDD or AIG)
+    unsigned          Level    : 14;   // the level of this node in the global AIG
+    // printing info 
+    unsigned          fNodeOr  :  1;   // marks the original OR node
+    unsigned          fCompl0  :  1;   // marks the original complemented edge
+    unsigned          fCompl1  :  1;   // marks the original complemented edge
+    // latch info
+    unsigned          nLat0    :  5;   // the number of latches on the first edge
+    unsigned          nLat1    :  5;   // the number of latches on the second edge
+    unsigned          nLat2    :  5;   // the number of latches on the output edge
+};
+
+typedef struct Dec_Graph_t_ Dec_Graph_t;
+struct Dec_Graph_t_
+{
+    int               fConst;          // marks the constant 1 graph
+    int               nLeaves;         // the number of leaves
+    int               nSize;           // the number of nodes (including the leaves) 
+    int               nCap;            // the number of allocated nodes
+    Dec_Node_t *      pNodes;          // the array of leaves and internal nodes
+    Dec_Edge_t        eRoot;           // the pointer to the topmost node
+};
+
+typedef struct Dec_Man_t_ Dec_Man_t;
+struct Dec_Man_t_
+{
+    void *            pMvcMem;         // memory manager for MVC cover (used for factoring)
+    Vec_Int_t *       vCubes;          // storage for cubes
+    Vec_Int_t *       vLits;           // storage for literals 
+    // precomputation information about 4-variable functions
+    unsigned short *  puCanons;        // canonical forms
+    char *            pPhases;         // canonical phases
+    char *            pPerms;          // canonical permutations
+    unsigned char *   pMap;            // mapping of functions into class numbers
+};
+
+
+////////////////////////////////////////////////////////////////////////
+///                        ITERATORS                                 ///
+////////////////////////////////////////////////////////////////////////
+
+// interator throught the leaves
+#define Dec_GraphForEachLeaf( pGraph, pLeaf, i )                                              \
+    for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Dec_GraphNode(pGraph, i)), 1); i++ )
+// interator throught the internal nodes
+#define Dec_GraphForEachNode( pGraph, pAnd, i )                                               \
+    for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Dec_GraphNode(pGraph, i)), 1); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== decAbc.c ========================================================*/
+/*=== decFactor.c ========================================================*/
+extern Dec_Graph_t *  Dec_Factor( char * pSop );
+/*=== decMan.c ========================================================*/
+extern Dec_Man_t *    Dec_ManStart();
+extern void           Dec_ManStop( Dec_Man_t * p );
+/*=== decPrint.c ========================================================*/
+extern void           Dec_GraphPrint( FILE * pFile, Dec_Graph_t * pGraph, char * pNamesIn[], char * pNameOut );
+/*=== decUtil.c ========================================================*/
+extern unsigned       Dec_GraphDeriveTruth( Dec_Graph_t * pGraph );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates an edge pointing to the node in the given polarity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_EdgeCreate( int Node, int fCompl )   
+{
+    Dec_Edge_t eEdge = { fCompl, Node }; 
+    return eEdge; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the edge into unsigned integer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Dec_EdgeToInt( Dec_Edge_t eEdge )   
+{
+    return (eEdge.Node << 1) | eEdge.fCompl; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts unsigned integer into the edge.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_IntToEdge( unsigned Edge )   
+{
+    return Dec_EdgeCreate( Edge >> 1, Edge & 1 ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the edge into unsigned integer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned    Dec_EdgeToInt_( Dec_Edge_t m )  { union { Dec_Edge_t x; unsigned y; } v; v.x = m; return v.y;  }
+/*
+static inline unsigned Dec_EdgeToInt_( Dec_Edge_t eEdge )   
+{
+    return *(unsigned *)&eEdge;
+}
+*/
+
+/**Function*************************************************************
+
+  Synopsis    [Converts unsigned integer into the edge.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Edge_t  Dec_IntToEdge_( unsigned m )    { union { Dec_Edge_t x; unsigned y; } v; v.y = m; return v.x;  }
+/*
+static inline Dec_Edge_t Dec_IntToEdge_( unsigned Edge )   
+{
+    return *(Dec_Edge_t *)&Edge;
+}
+*/
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a graph with the given number of leaves.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Graph_t * Dec_GraphCreate( int nLeaves )   
+{
+    Dec_Graph_t * pGraph;
+    pGraph = ABC_ALLOC( Dec_Graph_t, 1 );
+    memset( pGraph, 0, sizeof(Dec_Graph_t) );
+    pGraph->nLeaves = nLeaves;
+    pGraph->nSize = nLeaves;
+    pGraph->nCap = 2 * nLeaves + 50;
+    pGraph->pNodes = ABC_ALLOC( Dec_Node_t, pGraph->nCap );
+    memset( pGraph->pNodes, 0, sizeof(Dec_Node_t) * pGraph->nSize );
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates constant 0 graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Graph_t * Dec_GraphCreateConst0()   
+{
+    Dec_Graph_t * pGraph;
+    pGraph = ABC_ALLOC( Dec_Graph_t, 1 );
+    memset( pGraph, 0, sizeof(Dec_Graph_t) );
+    pGraph->fConst = 1;
+    pGraph->eRoot.fCompl = 1;
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates constant 1 graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Graph_t * Dec_GraphCreateConst1()   
+{
+    Dec_Graph_t * pGraph;
+    pGraph = ABC_ALLOC( Dec_Graph_t, 1 );
+    memset( pGraph, 0, sizeof(Dec_Graph_t) );
+    pGraph->fConst = 1;
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the literal graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Graph_t * Dec_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl )   
+{
+    Dec_Graph_t * pGraph;
+    assert( 0 <= iLeaf && iLeaf < nLeaves );
+    pGraph = Dec_GraphCreate( nLeaves );
+    pGraph->eRoot.Node   = iLeaf;
+    pGraph->eRoot.fCompl = fCompl;
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a graph with the given number of leaves.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Dec_GraphFree( Dec_Graph_t * pGraph )   
+{
+    ABC_FREE( pGraph->pNodes );
+    ABC_FREE( pGraph );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the graph is a constant.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphIsConst( Dec_Graph_t * pGraph )   
+{
+    return pGraph->fConst;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the graph is constant 0.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphIsConst0( Dec_Graph_t * pGraph )   
+{
+    return pGraph->fConst && pGraph->eRoot.fCompl;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the graph is constant 1.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphIsConst1( Dec_Graph_t * pGraph )   
+{
+    return pGraph->fConst && !pGraph->eRoot.fCompl;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the graph is complemented.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphIsComplement( Dec_Graph_t * pGraph )   
+{
+    return pGraph->eRoot.fCompl;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the graph is complemented.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Dec_GraphComplement( Dec_Graph_t * pGraph )   
+{
+    pGraph->eRoot.fCompl ^= 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of leaves.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphLeaveNum( Dec_Graph_t * pGraph )   
+{
+    return pGraph->nLeaves;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphNodeNum( Dec_Graph_t * pGraph )   
+{
+    return pGraph->nSize - pGraph->nLeaves;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the pointer to the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Node_t * Dec_GraphNode( Dec_Graph_t * pGraph, int i )   
+{
+    return pGraph->pNodes + i;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the pointer to the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Node_t * Dec_GraphNodeLast( Dec_Graph_t * pGraph )   
+{
+    return pGraph->pNodes + pGraph->nSize - 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphNodeInt( Dec_Graph_t * pGraph, Dec_Node_t * pNode )   
+{
+    return pNode - pGraph->pNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check if the graph represents elementary variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphIsVar( Dec_Graph_t * pGraph )   
+{
+    return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check if the graph represents elementary variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode )   
+{
+    return Dec_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the elementary variable elementary variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Node_t * Dec_GraphVar( Dec_Graph_t * pGraph )   
+{
+    assert( Dec_GraphIsVar( pGraph ) );
+    return Dec_GraphNode( pGraph, pGraph->eRoot.Node );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of the elementary variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphVarInt( Dec_Graph_t * pGraph )   
+{
+    assert( Dec_GraphIsVar( pGraph ) );
+    return Dec_GraphNodeInt( pGraph, Dec_GraphVar(pGraph) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the root of the graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Dec_GraphSetRoot( Dec_Graph_t * pGraph, Dec_Edge_t eRoot )   
+{
+    pGraph->eRoot = eRoot;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Appends a new node to the graph.]
+
+  Description [This procedure is meant for internal use.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Node_t * Dec_GraphAppendNode( Dec_Graph_t * pGraph )   
+{
+    Dec_Node_t * pNode;
+    if ( pGraph->nSize == pGraph->nCap )
+    {
+        pGraph->pNodes = ABC_REALLOC( Dec_Node_t, pGraph->pNodes, 2 * pGraph->nCap ); 
+        pGraph->nCap   = 2 * pGraph->nCap;
+    }
+    pNode = pGraph->pNodes + pGraph->nSize++;
+    memset( pNode, 0, sizeof(Dec_Node_t) );
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates an AND node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_GraphAddNodeAnd( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 )
+{
+    Dec_Node_t * pNode;
+    // get the new node
+    pNode = Dec_GraphAppendNode( pGraph );
+    // set the inputs and other info
+    pNode->eEdge0 = eEdge0;
+    pNode->eEdge1 = eEdge1;
+    pNode->fCompl0 = eEdge0.fCompl;
+    pNode->fCompl1 = eEdge1.fCompl;
+    return Dec_EdgeCreate( pGraph->nSize - 1, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates an OR node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 )
+{
+    Dec_Node_t * pNode;
+    // get the new node
+    pNode = Dec_GraphAppendNode( pGraph );
+    // set the inputs and other info
+    pNode->eEdge0 = eEdge0;
+    pNode->eEdge1 = eEdge1;
+    pNode->fCompl0 = eEdge0.fCompl;
+    pNode->fCompl1 = eEdge1.fCompl;
+    // make adjustments for the OR gate
+    pNode->fNodeOr = 1;
+    pNode->eEdge0.fCompl = !pNode->eEdge0.fCompl;
+    pNode->eEdge1.fCompl = !pNode->eEdge1.fCompl;
+    return Dec_EdgeCreate( pGraph->nSize - 1, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates an XOR node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1, int Type )
+{
+    Dec_Edge_t eNode0, eNode1, eNode;
+    if ( Type == 0 )
+    {
+        // derive the first AND
+        eEdge0.fCompl ^= 1;
+        eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+        eEdge0.fCompl ^= 1;
+        // derive the second AND
+        eEdge1.fCompl ^= 1;
+        eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+        // derive the final OR
+        eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+    }
+    else
+    {
+        // derive the first AND
+        eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+        // derive the second AND
+        eEdge0.fCompl ^= 1;
+        eEdge1.fCompl ^= 1;
+        eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+        // derive the final OR
+        eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+        eNode.fCompl ^= 1;
+    }
+    return eNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates an XOR node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_GraphAddNodeMux( Dec_Graph_t * pGraph, Dec_Edge_t eEdgeC, Dec_Edge_t eEdgeT, Dec_Edge_t eEdgeE, int Type )
+{
+    Dec_Edge_t eNode0, eNode1, eNode;
+    if ( Type == 0 )
+    {
+        // derive the first AND
+        eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
+        // derive the second AND
+        eEdgeC.fCompl ^= 1;
+        eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
+        // derive the final OR
+        eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+    }
+    else
+    {
+        // complement the arguments
+        eEdgeT.fCompl ^= 1;
+        eEdgeE.fCompl ^= 1;
+        // derive the first AND
+        eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
+        // derive the second AND
+        eEdgeC.fCompl ^= 1;
+        eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
+        // derive the final OR
+        eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+        eNode.fCompl ^= 1;
+    }
+    return eNode;
+}
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/bool/dec/decAbc.c b/abc-build/src/bool/dec/decAbc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/dec/decAbc.c
@@ -0,0 +1,358 @@
+/**CFile****************************************************************
+
+  FileName    [decAbc.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Interface between the decomposition package and ABC network.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: decAbc.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "aig/ivy/ivy.h"
+#include "dec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the decomposition graph into the AIG.]
+
+  Description [AIG nodes for the fanins should be assigned to pNode->pFunc
+  of the leaves of the graph before calling this procedure.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph )
+{
+    Abc_Obj_t * pAnd0, * pAnd1;
+    Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized"
+    int i;
+    // check for constant function
+    if ( Dec_GraphIsConst(pGraph) )
+        return Abc_ObjNotCond( Abc_AigConst1(pNtk), Dec_GraphIsComplement(pGraph) );
+    // check for a literal
+    if ( Dec_GraphIsVar(pGraph) )
+        return Abc_ObjNotCond( (Abc_Obj_t *)Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
+    // build the AIG nodes corresponding to the AND gates of the graph
+    Dec_GraphForEachNode( pGraph, pNode, i )
+    {
+        pAnd0 = Abc_ObjNotCond( (Abc_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); 
+        pAnd1 = Abc_ObjNotCond( (Abc_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); 
+        pNode->pFunc = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pAnd0, pAnd1 );
+    }
+    // complement the result if necessary
+    return Abc_ObjNotCond( (Abc_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the decomposition graph into the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Dec_SopToAig( Abc_Ntk_t * pNtk, char * pSop, Vec_Ptr_t * vFaninAigs )
+{
+    Abc_Obj_t * pFunc;
+    Dec_Graph_t * pFForm;
+    Dec_Node_t * pNode;
+    int i;
+    pFForm = Dec_Factor( pSop );
+    Dec_GraphForEachLeaf( pFForm, pNode, i )
+        pNode->pFunc = Vec_PtrEntry( vFaninAigs, i );
+    pFunc = Dec_GraphToNetwork( pNtk, pFForm );
+    Dec_GraphFree( pFForm );
+    return pFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the decomposition graph into the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Dec_GraphToAig( Abc_Ntk_t * pNtk, Dec_Graph_t * pFForm, Vec_Ptr_t * vFaninAigs )
+{
+    Abc_Obj_t * pFunc;
+    Dec_Node_t * pNode;
+    int i;
+    Dec_GraphForEachLeaf( pFForm, pNode, i )
+        pNode->pFunc = Vec_PtrEntry( vFaninAigs, i );
+    pFunc = Dec_GraphToNetwork( pNtk, pFForm );
+    return pFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the decomposition graph into the AIG.]
+
+  Description [AIG nodes for the fanins should be assigned to pNode->pFunc
+  of the leaves of the graph before calling this procedure.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Dec_GraphToNetworkNoStrash( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph )
+{
+    Abc_Obj_t * pAnd, * pAnd0, * pAnd1;
+    Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized"
+    int i;
+    // check for constant function
+    if ( Dec_GraphIsConst(pGraph) )
+        return Abc_ObjNotCond( Abc_AigConst1(pNtk), Dec_GraphIsComplement(pGraph) );
+    // check for a literal
+    if ( Dec_GraphIsVar(pGraph) )
+        return Abc_ObjNotCond( (Abc_Obj_t *)Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
+    // build the AIG nodes corresponding to the AND gates of the graph
+    Dec_GraphForEachNode( pGraph, pNode, i )
+    {
+        pAnd0 = Abc_ObjNotCond( (Abc_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); 
+        pAnd1 = Abc_ObjNotCond( (Abc_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); 
+//        pNode->pFunc = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pAnd0, pAnd1 );
+        pAnd = Abc_NtkCreateNode( pNtk );
+        Abc_ObjAddFanin( pAnd, pAnd0 );
+        Abc_ObjAddFanin( pAnd, pAnd1 );
+        pNode->pFunc = pAnd;
+    }
+    // complement the result if necessary
+    return Abc_ObjNotCond( (Abc_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of new nodes added when using this graph.]
+
+  Description [AIG nodes for the fanins should be assigned to pNode->pFunc 
+  of the leaves of the graph before calling this procedure. 
+  Returns -1 if the number of nodes and levels exceeded the given limit or 
+  the number of levels exceeded the maximum allowed level.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax )
+{
+    Abc_Aig_t * pMan = (Abc_Aig_t *)pRoot->pNtk->pManFunc;
+    Dec_Node_t * pNode, * pNode0, * pNode1;
+    Abc_Obj_t * pAnd, * pAnd0, * pAnd1;
+    int i, Counter, LevelNew, LevelOld;
+    // check for constant function or a literal
+    if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) )
+        return 0;
+    // set the levels of the leaves
+    Dec_GraphForEachLeaf( pGraph, pNode, i )
+        pNode->Level = Abc_ObjRegular((Abc_Obj_t *)pNode->pFunc)->Level;
+    // compute the AIG size after adding the internal nodes
+    Counter = 0;
+    Dec_GraphForEachNode( pGraph, pNode, i )
+    {
+        // get the children of this node
+        pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node );
+        pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node );
+        // get the AIG nodes corresponding to the children 
+        pAnd0 = (Abc_Obj_t *)pNode0->pFunc; 
+        pAnd1 = (Abc_Obj_t *)pNode1->pFunc; 
+        if ( pAnd0 && pAnd1 )
+        {
+            // if they are both present, find the resulting node
+            pAnd0 = Abc_ObjNotCond( pAnd0, pNode->eEdge0.fCompl );
+            pAnd1 = Abc_ObjNotCond( pAnd1, pNode->eEdge1.fCompl );
+            pAnd  = Abc_AigAndLookup( pMan, pAnd0, pAnd1 );
+            // return -1 if the node is the same as the original root
+            if ( Abc_ObjRegular(pAnd) == pRoot )
+                return -1;
+        }
+        else
+            pAnd = NULL;
+        // count the number of added nodes
+        if ( pAnd == NULL || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pAnd)) )
+        {
+            if ( ++Counter > NodeMax )
+                return -1;
+        }
+        // count the number of new levels
+        LevelNew = 1 + Abc_MaxInt( pNode0->Level, pNode1->Level );
+        if ( pAnd )
+        {
+            if ( Abc_ObjRegular(pAnd) == Abc_AigConst1(pRoot->pNtk) )
+                LevelNew = 0;
+            else if ( Abc_ObjRegular(pAnd) == Abc_ObjRegular(pAnd0) )
+                LevelNew = (int)Abc_ObjRegular(pAnd0)->Level;
+            else if ( Abc_ObjRegular(pAnd) == Abc_ObjRegular(pAnd1) )
+                LevelNew = (int)Abc_ObjRegular(pAnd1)->Level;
+            LevelOld = (int)Abc_ObjRegular(pAnd)->Level;
+//            assert( LevelNew == LevelOld );
+        }
+        if ( LevelNew > LevelMax )
+            return -1;
+        pNode->pFunc = pAnd;
+        pNode->Level = LevelNew;
+    }
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces MFFC of the node by the new factored form.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain )
+{
+    extern Abc_Obj_t *    Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph );
+    Abc_Obj_t * pRootNew;
+    Abc_Ntk_t * pNtk = pRoot->pNtk;
+    int nNodesNew, nNodesOld;
+    nNodesOld = Abc_NtkNodeNum(pNtk);
+    // create the new structure of nodes
+    pRootNew = Dec_GraphToNetwork( pNtk, pGraph );
+    // remove the old nodes
+    Abc_AigReplace( (Abc_Aig_t *)pNtk->pManFunc, pRoot, pRootNew, fUpdateLevel );
+    // compare the gains
+    nNodesNew = Abc_NtkNodeNum(pNtk);
+    assert( nGain <= nNodesOld - nNodesNew );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the decomposition graph into the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Dec_GraphToNetworkAig( Hop_Man_t * pMan, Dec_Graph_t * pGraph )
+{
+    Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized"
+    Hop_Obj_t * pAnd0, * pAnd1;
+    int i;
+    // check for constant function
+    if ( Dec_GraphIsConst(pGraph) )
+        return Hop_NotCond( Hop_ManConst1(pMan), Dec_GraphIsComplement(pGraph) );
+    // check for a literal
+    if ( Dec_GraphIsVar(pGraph) )
+        return Hop_NotCond( (Hop_Obj_t *)Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
+    // build the AIG nodes corresponding to the AND gates of the graph
+    Dec_GraphForEachNode( pGraph, pNode, i )
+    {
+        pAnd0 = Hop_NotCond( (Hop_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); 
+        pAnd1 = Hop_NotCond( (Hop_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); 
+        pNode->pFunc = Hop_And( pMan, pAnd0, pAnd1 );
+    }
+    // complement the result if necessary
+    return Hop_NotCond( (Hop_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes one logic node using its SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Dec_GraphFactorSop( Hop_Man_t * pMan, char * pSop )
+{
+    Hop_Obj_t * pFunc;
+    Dec_Graph_t * pFForm;
+    Dec_Node_t * pNode;
+    int i;
+    // perform factoring
+    pFForm = Dec_Factor( pSop );
+    // collect the fanins
+    Dec_GraphForEachLeaf( pFForm, pNode, i )
+        pNode->pFunc = Hop_IthVar( pMan, i );
+    // perform strashing
+    pFunc = Dec_GraphToNetworkAig( pMan, pFForm );
+    Dec_GraphFree( pFForm );
+    return pFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the decomposition graph into the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ivy_Obj_t * Dec_GraphToNetworkIvy( Ivy_Man_t * pMan, Dec_Graph_t * pGraph )
+{
+    Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized"
+    Ivy_Obj_t * pAnd0, * pAnd1;
+    int i;
+    // check for constant function
+    if ( Dec_GraphIsConst(pGraph) )
+        return Ivy_NotCond( Ivy_ManConst1(pMan), Dec_GraphIsComplement(pGraph) );
+    // check for a literal
+    if ( Dec_GraphIsVar(pGraph) )
+        return Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
+    // build the AIG nodes corresponding to the AND gates of the graph
+    Dec_GraphForEachNode( pGraph, pNode, i )
+    {
+        pAnd0 = Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); 
+        pAnd1 = Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); 
+        pNode->pFunc = Ivy_And( pMan, pAnd0, pAnd1 );
+    }
+    // complement the result if necessary
+    return Ivy_NotCond( (Ivy_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/dec/decFactor.c b/abc-build/src/bool/dec/decFactor.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/dec/decFactor.c
@@ -0,0 +1,399 @@
+/**CFile****************************************************************
+
+  FileName    [ftFactor.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Procedures for algebraic factoring.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: ftFactor.c,v 1.3 2003/09/01 04:56:43 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/main.h"
+#include "misc/mvc/mvc.h"
+#include "misc/extra/extraBdd.h"
+#include "dec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Dec_Edge_t       Dec_Factor_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover );
+static Dec_Edge_t       Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple );
+static Dec_Edge_t       Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover );
+static Dec_Edge_t       Dec_FactorTrivialCube( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube, Vec_Int_t * vEdgeLits );
+static Dec_Edge_t       Dec_FactorTrivialTree_rec( Dec_Graph_t * pFForm, Dec_Edge_t * peNodes, int nNodes, int fNodeOr );
+static int              Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm );
+static Mvc_Cover_t *    Dec_ConvertSopToMvc( char * pSop );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Factors the cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Dec_Factor( char * pSop )
+{
+    Mvc_Cover_t * pCover;
+    Dec_Graph_t * pFForm;
+    Dec_Edge_t eRoot;
+
+    // derive the cover from the SOP representation
+    pCover = Dec_ConvertSopToMvc( pSop );
+
+    // make sure the cover is CCS free (should be done before CST)
+    Mvc_CoverContain( pCover );
+    // check for trivial functions
+    if ( Mvc_CoverIsEmpty(pCover) )
+    {
+        Mvc_CoverFree( pCover );
+        return Dec_GraphCreateConst0();
+    }
+    if ( Mvc_CoverIsTautology(pCover) )
+    {
+        Mvc_CoverFree( pCover );
+        return Dec_GraphCreateConst1();
+    }
+
+    // perform CST
+    Mvc_CoverInverse( pCover ); // CST
+    // start the factored form
+    pFForm = Dec_GraphCreate( Abc_SopGetVarNum(pSop) );
+    // factor the cover
+    eRoot = Dec_Factor_rec( pFForm, pCover );
+    // finalize the factored form
+    Dec_GraphSetRoot( pFForm, eRoot );
+    // complement the factored form if SOP is complemented
+    if ( Abc_SopIsComplement(pSop) )
+        Dec_GraphComplement( pFForm );
+    // verify the factored form
+//    if ( !Dec_FactorVerify( pSop, pFForm ) )
+//        printf( "Verification has failed.\n" );
+//    Mvc_CoverInverse( pCover ); // undo CST
+    Mvc_CoverFree( pCover );
+    return pFForm;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Internal recursive factoring procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Edge_t Dec_Factor_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover )
+{
+    Mvc_Cover_t * pDiv, * pQuo, * pRem, * pCom;
+    Dec_Edge_t eNodeDiv, eNodeQuo, eNodeRem;
+    Dec_Edge_t eNodeAnd, eNode;
+
+    // make sure the cover contains some cubes
+    assert( Mvc_CoverReadCubeNum(pCover) );
+
+    // get the divisor
+    pDiv = Mvc_CoverDivisor( pCover );
+    if ( pDiv == NULL )
+        return Dec_FactorTrivial( pFForm, pCover );
+
+    // divide the cover by the divisor
+    Mvc_CoverDivideInternal( pCover, pDiv, &pQuo, &pRem );
+    assert( Mvc_CoverReadCubeNum(pQuo) );
+
+    Mvc_CoverFree( pDiv );
+    Mvc_CoverFree( pRem );
+
+    // check the trivial case
+    if ( Mvc_CoverReadCubeNum(pQuo) == 1 )
+    {
+        eNode = Dec_FactorLF_rec( pFForm, pCover, pQuo );
+        Mvc_CoverFree( pQuo );
+        return eNode;
+    }
+
+    // make the quotient cube ABC_FREE
+    Mvc_CoverMakeCubeFree( pQuo );
+
+    // divide the cover by the quotient
+    Mvc_CoverDivideInternal( pCover, pQuo, &pDiv, &pRem );
+
+    // check the trivial case
+    if ( Mvc_CoverIsCubeFree( pDiv ) )
+    {
+        eNodeDiv = Dec_Factor_rec( pFForm, pDiv );
+        eNodeQuo = Dec_Factor_rec( pFForm, pQuo );
+        Mvc_CoverFree( pDiv );
+        Mvc_CoverFree( pQuo );
+        eNodeAnd = Dec_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo );
+        if ( Mvc_CoverReadCubeNum(pRem) == 0 )
+        {
+            Mvc_CoverFree( pRem );
+            return eNodeAnd;
+        }
+        else
+        {
+            eNodeRem = Dec_Factor_rec( pFForm, pRem );
+            Mvc_CoverFree( pRem );
+            return Dec_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem );
+        }
+    }
+
+    // get the common cube
+    pCom = Mvc_CoverCommonCubeCover( pDiv );
+    Mvc_CoverFree( pDiv );
+    Mvc_CoverFree( pQuo );
+    Mvc_CoverFree( pRem );
+
+    // solve the simple problem
+    eNode = Dec_FactorLF_rec( pFForm, pCover, pCom );
+    Mvc_CoverFree( pCom );
+    return eNode;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Internal recursive factoring procedure for the leaf case.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple )
+{
+    Dec_Man_t * pManDec = (Dec_Man_t *)Abc_FrameReadManDec();
+    Vec_Int_t * vEdgeLits  = pManDec->vLits;
+    Mvc_Cover_t * pDiv, * pQuo, * pRem;
+    Dec_Edge_t eNodeDiv, eNodeQuo, eNodeRem;
+    Dec_Edge_t eNodeAnd;
+
+    // get the most often occurring literal
+    pDiv = Mvc_CoverBestLiteralCover( pCover, pSimple );
+    // divide the cover by the literal
+    Mvc_CoverDivideByLiteral( pCover, pDiv, &pQuo, &pRem );
+    // get the node pointer for the literal
+    eNodeDiv = Dec_FactorTrivialCube( pFForm, pDiv, Mvc_CoverReadCubeHead(pDiv), vEdgeLits );
+    Mvc_CoverFree( pDiv );
+    // factor the quotient and remainder
+    eNodeQuo = Dec_Factor_rec( pFForm, pQuo );
+    Mvc_CoverFree( pQuo );
+    eNodeAnd = Dec_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo );
+    if ( Mvc_CoverReadCubeNum(pRem) == 0 )
+    {
+        Mvc_CoverFree( pRem );
+        return eNodeAnd;
+    }
+    else
+    {
+        eNodeRem = Dec_Factor_rec( pFForm, pRem );
+        Mvc_CoverFree( pRem );
+        return Dec_GraphAddNodeOr( pFForm,  eNodeAnd, eNodeRem );
+    }
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Factoring the cover, which has no algebraic divisors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover )
+{
+    Dec_Man_t * pManDec = (Dec_Man_t *)Abc_FrameReadManDec();
+    Vec_Int_t * vEdgeCubes = pManDec->vCubes;
+    Vec_Int_t * vEdgeLits  = pManDec->vLits;
+    Dec_Edge_t eNode;
+    Mvc_Cube_t * pCube;
+    // create the factored form for each cube
+    Vec_IntClear( vEdgeCubes );
+    Mvc_CoverForEachCube( pCover, pCube )
+    {
+        eNode = Dec_FactorTrivialCube( pFForm, pCover, pCube, vEdgeLits );
+        Vec_IntPush( vEdgeCubes, Dec_EdgeToInt_(eNode) );
+    }
+    // balance the factored forms
+    return Dec_FactorTrivialTree_rec( pFForm, (Dec_Edge_t *)vEdgeCubes->pArray, vEdgeCubes->nSize, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Factoring the cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Edge_t Dec_FactorTrivialCube( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube, Vec_Int_t * vEdgeLits )
+{
+    Dec_Edge_t eNode;
+    int iBit, Value;
+    // create the factored form for each literal
+    Vec_IntClear( vEdgeLits );
+    Mvc_CubeForEachBit( pCover, pCube, iBit, Value )
+        if ( Value )
+        {
+            eNode = Dec_EdgeCreate( iBit/2, iBit%2 ); // CST
+            Vec_IntPush( vEdgeLits, Dec_EdgeToInt_(eNode) );
+        }
+    // balance the factored forms
+    return Dec_FactorTrivialTree_rec( pFForm, (Dec_Edge_t *)vEdgeLits->pArray, vEdgeLits->nSize, 0 );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Create the well-balanced tree of nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Edge_t Dec_FactorTrivialTree_rec( Dec_Graph_t * pFForm, Dec_Edge_t * peNodes, int nNodes, int fNodeOr )
+{
+    Dec_Edge_t eNode1, eNode2;
+    int nNodes1, nNodes2;
+
+    if ( nNodes == 1 )
+        return peNodes[0];
+
+    // split the nodes into two parts
+    nNodes1 = nNodes/2;
+    nNodes2 = nNodes - nNodes1;
+//    nNodes2 = nNodes/2;
+//    nNodes1 = nNodes - nNodes2;
+
+    // recursively construct the tree for the parts
+    eNode1 = Dec_FactorTrivialTree_rec( pFForm, peNodes,           nNodes1, fNodeOr );
+    eNode2 = Dec_FactorTrivialTree_rec( pFForm, peNodes + nNodes1, nNodes2, fNodeOr );
+
+    if ( fNodeOr )
+        return Dec_GraphAddNodeOr( pFForm, eNode1, eNode2 );
+    else
+        return Dec_GraphAddNodeAnd( pFForm, eNode1, eNode2 );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Converts SOP into MVC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop )
+{
+    Dec_Man_t * pManDec = (Dec_Man_t *)Abc_FrameReadManDec();
+    Mvc_Manager_t * pMem = (Mvc_Manager_t *)pManDec->pMvcMem;
+    Mvc_Cover_t * pMvc;
+    Mvc_Cube_t * pMvcCube;
+    char * pCube;
+    int nVars, Value, v;
+
+    // start the cover
+    nVars = Abc_SopGetVarNum(pSop);
+    pMvc = Mvc_CoverAlloc( pMem, nVars * 2 );
+    // check the logic function of the node
+    Abc_SopForEachCube( pSop, nVars, pCube )
+    {
+        // create and add the cube
+        pMvcCube = Mvc_CubeAlloc( pMvc );
+        Mvc_CoverAddCubeTail( pMvc, pMvcCube );
+        // fill in the literals
+        Mvc_CubeBitFill( pMvcCube );
+        Abc_CubeForEachVar( pCube, Value, v )
+        {
+            if ( Value == '0' )
+                Mvc_CubeBitRemove( pMvcCube, v * 2 + 1 );
+            else if ( Value == '1' )
+                Mvc_CubeBitRemove( pMvcCube, v * 2 );
+        }
+    }
+    return pMvc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies that the factoring is correct.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm )
+{
+    extern DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop, DdNode ** pbVars );
+    extern DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph );
+    DdManager * dd = (DdManager *)Abc_FrameReadManDd();
+    DdNode * bFunc1, * bFunc2;
+    int RetValue;
+    bFunc1 = Abc_ConvertSopToBdd( dd, pSop, NULL );    Cudd_Ref( bFunc1 );
+    bFunc2 = Dec_GraphDeriveBdd( dd, pFForm );   Cudd_Ref( bFunc2 );
+//Extra_bddPrint( dd, bFunc1 ); printf("\n");
+//Extra_bddPrint( dd, bFunc2 ); printf("\n");
+    RetValue = (bFunc1 == bFunc2);
+    if ( bFunc1 != bFunc2 )
+    {
+        int s;
+        Extra_bddPrint( dd, bFunc1 ); printf("\n");
+        Extra_bddPrint( dd, bFunc2 ); printf("\n");
+        s  = 0;
+    }
+    Cudd_RecursiveDeref( dd, bFunc1 );
+    Cudd_RecursiveDeref( dd, bFunc2 );
+    return RetValue;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/dec/decMan.c b/abc-build/src/bool/dec/decMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/dec/decMan.c
@@ -0,0 +1,88 @@
+/**CFile****************************************************************
+
+  FileName    [decMan.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Decomposition manager.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: decMan.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/mvc/mvc.h"
+#include "dec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Start the MVC manager used in the factoring package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Man_t * Dec_ManStart()
+{
+    Dec_Man_t * p;
+//    abctime clk = Abc_Clock();
+    p = ABC_ALLOC( Dec_Man_t, 1 );
+    p->pMvcMem = Mvc_ManagerStart();
+    p->vCubes = Vec_IntAlloc( 8 );
+    p->vLits = Vec_IntAlloc( 8 );
+    // canonical forms, phases, perms
+    Extra_Truth4VarNPN( &p->puCanons, &p->pPhases, &p->pPerms, &p->pMap );
+//ABC_PRT( "NPN classes precomputation time", Abc_Clock() - clk ); 
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the MVC maanager used in the factoring package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dec_ManStop( Dec_Man_t * p )
+{
+    Mvc_ManagerFree( (Mvc_Manager_t *)p->pMvcMem );
+    Vec_IntFree( p->vCubes );
+    Vec_IntFree( p->vLits );
+    ABC_FREE( p->puCanons );
+    ABC_FREE( p->pPhases );
+    ABC_FREE( p->pPerms );
+    ABC_FREE( p->pMap );
+    ABC_FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/dec/decPrint.c b/abc-build/src/bool/dec/decPrint.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/dec/decPrint.c
@@ -0,0 +1,289 @@
+/**CFile****************************************************************
+
+  FileName    [decPrint.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Procedures to print the decomposition graphs (factored forms).]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: decPrint.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "dec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void   Dec_GraphPrint_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax );
+static int    Dec_GraphPrintGetLeafName( FILE * pFile, int iLeaf, int fCompl, char * pNamesIn[] );
+static void   Dec_GraphPrintUpdatePos( FILE * pFile, int * pPos, int LitSizeMax );
+static int    Dec_GraphPrintOutputName( FILE * pFile, char * pNameOut );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the decomposition graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dec_GraphPrint( FILE * pFile, Dec_Graph_t * pGraph, char * pNamesIn[], char * pNameOut )
+{
+    Vec_Ptr_t * vNamesIn = NULL;
+    int LitSizeMax, LitSizeCur, Pos, i;
+
+    // create the names if not given by the user
+    if ( pNamesIn == NULL )
+    {
+        vNamesIn = Abc_NodeGetFakeNames( Dec_GraphLeaveNum(pGraph) );
+        pNamesIn = (char **)vNamesIn->pArray;
+    }
+    if ( pNameOut == NULL )
+        pNameOut = "F";
+
+    // get the size of the longest literal
+    LitSizeMax = 0;
+    for ( i = 0; i < Dec_GraphLeaveNum(pGraph); i++ )
+    {
+        LitSizeCur = strlen(pNamesIn[i]);
+        if ( LitSizeMax < LitSizeCur )
+            LitSizeMax = LitSizeCur;
+    }
+    if ( LitSizeMax > 50 )
+        LitSizeMax = 20;
+
+    // write the decomposition graph (factored form)
+    if ( Dec_GraphIsConst(pGraph) ) // constant
+    {
+        Pos = Dec_GraphPrintOutputName( pFile, pNameOut );
+        fprintf( pFile, "Constant %d", !Dec_GraphIsComplement(pGraph) );
+    }
+    else if ( Dec_GraphIsVar(pGraph) ) // literal
+    {
+        Pos = Dec_GraphPrintOutputName( pFile, pNameOut );
+        Dec_GraphPrintGetLeafName( pFile, Dec_GraphVarInt(pGraph), Dec_GraphIsComplement(pGraph), pNamesIn );
+    }
+    else
+    {
+        Pos = Dec_GraphPrintOutputName( pFile, pNameOut );
+        Dec_GraphPrint_rec( pFile, pGraph, Dec_GraphNodeLast(pGraph), Dec_GraphIsComplement(pGraph), pNamesIn, &Pos, LitSizeMax );
+    }
+    fprintf( pFile, "\n" );
+
+    if ( vNamesIn )
+        Abc_NodeFreeNames( vNamesIn );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dec_GraphPrint2_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax )
+{
+    Dec_Node_t * pNode0, * pNode1;
+    pNode0 = Dec_GraphNode(pGraph, pNode->eEdge0.Node);
+    pNode1 = Dec_GraphNode(pGraph, pNode->eEdge1.Node);
+    if ( Dec_GraphNodeIsVar(pGraph, pNode) ) // FT_NODE_LEAF )
+    {
+        (*pPos) += Dec_GraphPrintGetLeafName( pFile, Dec_GraphNodeInt(pGraph,pNode), fCompl, pNamesIn );
+        return;
+    }
+    if ( !pNode->fNodeOr ) // FT_NODE_AND )
+    {
+        if ( !pNode0->fNodeOr ) // != FT_NODE_OR )
+            Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax );
+        else
+        {
+            fprintf( pFile, "(" );
+            (*pPos)++;
+            Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax );
+            fprintf( pFile, ")" );
+            (*pPos)++;
+        }
+        fprintf( pFile, " " );
+        (*pPos)++;
+
+        Dec_GraphPrintUpdatePos( pFile, pPos, LitSizeMax );
+
+        if ( !pNode1->fNodeOr ) // != FT_NODE_OR )
+            Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax );
+        else
+        {
+            fprintf( pFile, "(" );
+            (*pPos)++;
+            Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax );
+            fprintf( pFile, ")" );
+            (*pPos)++;
+        }
+        return;
+    }
+    if ( pNode->fNodeOr ) // FT_NODE_OR )
+    {
+        Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax );
+        fprintf( pFile, " + " );
+        (*pPos) += 3;
+
+        Dec_GraphPrintUpdatePos( pFile, pPos, LitSizeMax );
+
+        Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax );
+        return;
+    }
+    assert( 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dec_GraphPrint_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax )
+{
+    Dec_Node_t * pNode0, * pNode1;
+    Dec_Node_t * pNode00, * pNode01, * pNode10, * pNode11;
+    pNode0 = Dec_GraphNode(pGraph, pNode->eEdge0.Node);
+    pNode1 = Dec_GraphNode(pGraph, pNode->eEdge1.Node);
+    if ( Dec_GraphNodeIsVar(pGraph, pNode) ) // FT_NODE_LEAF )
+    {
+        (*pPos) += Dec_GraphPrintGetLeafName( pFile, Dec_GraphNodeInt(pGraph,pNode), fCompl, pNamesIn );
+        return;
+    }
+    if ( !Dec_GraphNodeIsVar(pGraph, pNode0) && !Dec_GraphNodeIsVar(pGraph, pNode1) )
+    {
+        pNode00 = Dec_GraphNode(pGraph, pNode0->eEdge0.Node);
+        pNode01 = Dec_GraphNode(pGraph, pNode0->eEdge1.Node);
+        pNode10 = Dec_GraphNode(pGraph, pNode1->eEdge0.Node);
+        pNode11 = Dec_GraphNode(pGraph, pNode1->eEdge1.Node);
+        if ( (pNode00 == pNode10 || pNode00 == pNode11) && (pNode01 == pNode10 || pNode01 == pNode11) )
+        {
+            fprintf( pFile, "(" );
+            (*pPos)++;
+            Dec_GraphPrint_rec( pFile, pGraph, pNode00, pNode00->fCompl0, pNamesIn, pPos, LitSizeMax );
+            fprintf( pFile, " # " );
+            (*pPos) += 3;
+            Dec_GraphPrint_rec( pFile, pGraph, pNode01, pNode01->fCompl1, pNamesIn, pPos, LitSizeMax );
+            fprintf( pFile, ")" );
+            (*pPos)++;
+            return;
+        }
+    }
+    if ( fCompl )
+    {
+        fprintf( pFile, "(" );
+        (*pPos)++;
+        Dec_GraphPrint_rec( pFile, pGraph, pNode0, !pNode->eEdge0.fCompl, pNamesIn, pPos, LitSizeMax );
+        fprintf( pFile, " + " );
+        (*pPos) += 3;
+        Dec_GraphPrint_rec( pFile, pGraph, pNode1, !pNode->eEdge1.fCompl, pNamesIn, pPos, LitSizeMax );
+        fprintf( pFile, ")" );
+        (*pPos)++;
+    }
+    else
+    {
+        fprintf( pFile, "(" );
+        (*pPos)++;
+        Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->eEdge0.fCompl, pNamesIn, pPos, LitSizeMax );
+        Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->eEdge1.fCompl, pNamesIn, pPos, LitSizeMax );
+        fprintf( pFile, ")" );
+        (*pPos)++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dec_GraphPrintGetLeafName( FILE * pFile, int iLeaf, int fCompl, char * pNamesIn[] )
+{
+    static char Buffer[100];
+    sprintf( Buffer, "%s%s", fCompl? "!" : "", pNamesIn[iLeaf] );
+    fprintf( pFile, "%s", Buffer );
+    return strlen( Buffer );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dec_GraphPrintUpdatePos( FILE * pFile, int * pPos, int LitSizeMax )
+{
+    int i;
+    if ( *pPos + LitSizeMax < 77 )
+        return;
+    fprintf( pFile, "\n" );
+    for ( i = 0; i < 10; i++ )
+        fprintf( pFile, " " );
+    *pPos = 10;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the printout for a decomposition graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dec_GraphPrintOutputName( FILE * pFile, char * pNameOut )
+{
+    if ( pNameOut == NULL )
+        return 0;
+    fprintf( pFile, "%6s = ", pNameOut );
+    return 10;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/dec/decUtil.c b/abc-build/src/bool/dec/decUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/dec/decUtil.c
@@ -0,0 +1,141 @@
+/**CFile****************************************************************
+
+  FileName    [decUtil.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Decomposition unitilies.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: decUtil.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "misc/extra/extraBdd.h"
+#include "dec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Converts graph to BDD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph )
+{
+    DdNode * bFunc, * bFunc0, * bFunc1;
+    Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized"
+    int i;
+
+    // sanity checks
+    assert( Dec_GraphLeaveNum(pGraph) >= 0 );
+    assert( Dec_GraphLeaveNum(pGraph) <= pGraph->nSize );
+
+    // check for constant function
+    if ( Dec_GraphIsConst(pGraph) )
+        return Cudd_NotCond( b1, Dec_GraphIsComplement(pGraph) );
+    // check for a literal
+    if ( Dec_GraphIsVar(pGraph) )
+        return Cudd_NotCond( Cudd_bddIthVar(dd, Dec_GraphVarInt(pGraph)), Dec_GraphIsComplement(pGraph) );
+
+    // assign the elementary variables
+    Dec_GraphForEachLeaf( pGraph, pNode, i )
+        pNode->pFunc = Cudd_bddIthVar( dd, i );
+
+    // compute the function for each internal node
+    Dec_GraphForEachNode( pGraph, pNode, i )
+    {
+        bFunc0 = Cudd_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); 
+        bFunc1 = Cudd_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); 
+        pNode->pFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 );   Cudd_Ref( (DdNode *)pNode->pFunc );
+    }
+
+    // deref the intermediate results
+    bFunc = (DdNode *)pNode->pFunc;   Cudd_Ref( bFunc );
+    Dec_GraphForEachNode( pGraph, pNode, i )
+        Cudd_RecursiveDeref( dd, (DdNode *)pNode->pFunc );
+    Cudd_Deref( bFunc );
+
+    // complement the result if necessary
+    return Cudd_NotCond( bFunc, Dec_GraphIsComplement(pGraph) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Dec_GraphDeriveTruth( Dec_Graph_t * pGraph )
+{
+    unsigned uTruths[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+    unsigned uTruth = 0; // Suppress "might be used uninitialized"
+    unsigned uTruth0, uTruth1;
+    Dec_Node_t * pNode;
+    int i;
+
+    // sanity checks
+    assert( Dec_GraphLeaveNum(pGraph) >= 0 );
+    assert( Dec_GraphLeaveNum(pGraph) <= pGraph->nSize );
+    assert( Dec_GraphLeaveNum(pGraph) <= 5 );
+
+    // check for constant function
+    if ( Dec_GraphIsConst(pGraph) )
+        return Dec_GraphIsComplement(pGraph)? 0 : ~((unsigned)0);
+    // check for a literal
+    if ( Dec_GraphIsVar(pGraph) )
+        return Dec_GraphIsComplement(pGraph)? ~uTruths[Dec_GraphVarInt(pGraph)] : uTruths[Dec_GraphVarInt(pGraph)];
+
+    // assign the elementary variables
+    Dec_GraphForEachLeaf( pGraph, pNode, i )
+        pNode->pFunc = (void *)(ABC_PTRUINT_T)uTruths[i];
+
+    // compute the function for each internal node
+    Dec_GraphForEachNode( pGraph, pNode, i )
+    {
+        uTruth0 = (unsigned)(ABC_PTRUINT_T)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc;
+        uTruth1 = (unsigned)(ABC_PTRUINT_T)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc;
+        uTruth0 = pNode->eEdge0.fCompl? ~uTruth0 : uTruth0;
+        uTruth1 = pNode->eEdge1.fCompl? ~uTruth1 : uTruth1;
+        uTruth = uTruth0 & uTruth1;
+        pNode->pFunc = (void *)(ABC_PTRUINT_T)uTruth;
+    }
+
+    // complement the result if necessary
+    return Dec_GraphIsComplement(pGraph)? ~uTruth : uTruth;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/dec/module.make b/abc-build/src/bool/dec/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/dec/module.make
@@ -0,0 +1,5 @@
+SRC +=  src/bool/dec/decAbc.c \
+        src/bool/dec/decFactor.c \
+        src/bool/dec/decMan.c \
+        src/bool/dec/decPrint.c \
+        src/bool/dec/decUtil.c 
diff --git a/abc-build/src/bool/deco/deco.h b/abc-build/src/bool/deco/deco.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/deco/deco.h
@@ -0,0 +1,714 @@
+/**CFile****************************************************************
+
+  FileName    [deco.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [A simple decomposition tree/node data structure and its APIs.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: deco.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__deco__deco_h
+#define ABC__aig__deco__deco_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Dec_Edge_t_ Dec_Edge_t;
+struct Dec_Edge_t_
+{
+    unsigned          fCompl   :  1;   // the complemented bit
+    unsigned          Node     : 30;   // the decomposition node pointed by the edge
+};
+
+typedef struct Dec_Node_t_ Dec_Node_t;
+struct Dec_Node_t_
+{
+    Dec_Edge_t        eEdge0;          // the left child of the node
+    Dec_Edge_t        eEdge1;          // the right child of the node
+    // other info
+    union { int       iFunc;           // the literal of the node (AIG)
+    void *            pFunc; };        // the function of the node (BDD or AIG)
+    unsigned          Level    : 14;   // the level of this node in the global AIG
+    // printing info 
+    unsigned          fNodeOr  :  1;   // marks the original OR node
+    unsigned          fCompl0  :  1;   // marks the original complemented edge
+    unsigned          fCompl1  :  1;   // marks the original complemented edge
+    // latch info
+    unsigned          nLat0    :  5;   // the number of latches on the first edge
+    unsigned          nLat1    :  5;   // the number of latches on the second edge
+    unsigned          nLat2    :  5;   // the number of latches on the output edge
+};
+
+typedef struct Dec_Graph_t_ Dec_Graph_t;
+struct Dec_Graph_t_
+{
+    int               fConst;          // marks the constant 1 graph
+    int               nLeaves;         // the number of leaves
+    int               nSize;           // the number of nodes (including the leaves) 
+    int               nCap;            // the number of allocated nodes
+    Dec_Node_t *      pNodes;          // the array of leaves and internal nodes
+    Dec_Edge_t        eRoot;           // the pointer to the topmost node
+};
+
+typedef struct Dec_Man_t_ Dec_Man_t;
+struct Dec_Man_t_
+{
+    void *            pMvcMem;         // memory manager for MVC cover (used for factoring)
+    Vec_Int_t *       vCubes;          // storage for cubes
+    Vec_Int_t *       vLits;           // storage for literals 
+    // precomputation information about 4-variable functions
+    unsigned short *  puCanons;        // canonical forms
+    char *            pPhases;         // canonical phases
+    char *            pPerms;          // canonical permutations
+    unsigned char *   pMap;            // mapping of functions into class numbers
+};
+
+
+////////////////////////////////////////////////////////////////////////
+///                        ITERATORS                                 ///
+////////////////////////////////////////////////////////////////////////
+
+// interator throught the leaves
+#define Dec_GraphForEachLeaf( pGraph, pLeaf, i )                                              \
+    for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Dec_GraphNode(pGraph, i)), 1); i++ )
+// interator throught the internal nodes
+#define Dec_GraphForEachNode( pGraph, pAnd, i )                                               \
+    for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Dec_GraphNode(pGraph, i)), 1); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates an edge pointing to the node in the given polarity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_EdgeCreate( int Node, int fCompl )   
+{
+    Dec_Edge_t eEdge = { fCompl, Node }; 
+    return eEdge; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the edge into unsigned integer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Dec_EdgeToInt( Dec_Edge_t eEdge )   
+{
+    return (eEdge.Node << 1) | eEdge.fCompl; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts unsigned integer into the edge.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_IntToEdge( unsigned Edge )   
+{
+    return Dec_EdgeCreate( Edge >> 1, Edge & 1 ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the edge into unsigned integer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Dec_EdgeToInt_( Dec_Edge_t m )  { union { Dec_Edge_t x; unsigned y; } v; v.x = m; return v.y;  }
+/*
+static inline unsigned Dec_EdgeToInt_( Dec_Edge_t eEdge )   
+{
+    return *(unsigned *)&eEdge;
+}
+*/
+
+/**Function*************************************************************
+
+  Synopsis    [Converts unsigned integer into the edge.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_IntToEdge_( unsigned m )    { union { Dec_Edge_t x; unsigned y; } v; v.y = m; return v.x;  }
+/*
+static inline Dec_Edge_t Dec_IntToEdge_( unsigned Edge )   
+{
+    return *(Dec_Edge_t *)&Edge;
+}
+*/
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a graph with the given number of leaves.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Graph_t * Dec_GraphCreate( int nLeaves )   
+{
+    Dec_Graph_t * pGraph;
+    pGraph = ABC_ALLOC( Dec_Graph_t, 1 );
+    memset( pGraph, 0, sizeof(Dec_Graph_t) );
+    pGraph->nLeaves = nLeaves;
+    pGraph->nSize = nLeaves;
+    pGraph->nCap = 2 * nLeaves + 50;
+    pGraph->pNodes = ABC_ALLOC( Dec_Node_t, pGraph->nCap );
+    memset( pGraph->pNodes, 0, sizeof(Dec_Node_t) * pGraph->nSize );
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates constant 0 graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Graph_t * Dec_GraphCreateConst0()   
+{
+    Dec_Graph_t * pGraph;
+    pGraph = ABC_ALLOC( Dec_Graph_t, 1 );
+    memset( pGraph, 0, sizeof(Dec_Graph_t) );
+    pGraph->fConst = 1;
+    pGraph->eRoot.fCompl = 1;
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates constant 1 graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Graph_t * Dec_GraphCreateConst1()   
+{
+    Dec_Graph_t * pGraph;
+    pGraph = ABC_ALLOC( Dec_Graph_t, 1 );
+    memset( pGraph, 0, sizeof(Dec_Graph_t) );
+    pGraph->fConst = 1;
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the literal graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Graph_t * Dec_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl )   
+{
+    Dec_Graph_t * pGraph;
+    assert( 0 <= iLeaf && iLeaf < nLeaves );
+    pGraph = Dec_GraphCreate( nLeaves );
+    pGraph->eRoot.Node   = iLeaf;
+    pGraph->eRoot.fCompl = fCompl;
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a graph with the given number of leaves.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Dec_GraphFree( Dec_Graph_t * pGraph )   
+{
+    ABC_FREE( pGraph->pNodes );
+    ABC_FREE( pGraph );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the graph is a constant.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphIsConst( Dec_Graph_t * pGraph )   
+{
+    return pGraph->fConst;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the graph is constant 0.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphIsConst0( Dec_Graph_t * pGraph )   
+{
+    return pGraph->fConst && pGraph->eRoot.fCompl;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the graph is constant 1.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphIsConst1( Dec_Graph_t * pGraph )   
+{
+    return pGraph->fConst && !pGraph->eRoot.fCompl;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the graph is complemented.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphIsComplement( Dec_Graph_t * pGraph )   
+{
+    return pGraph->eRoot.fCompl;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the graph is complemented.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Dec_GraphComplement( Dec_Graph_t * pGraph )   
+{
+    pGraph->eRoot.fCompl ^= 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of leaves.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphLeaveNum( Dec_Graph_t * pGraph )   
+{
+    return pGraph->nLeaves;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphNodeNum( Dec_Graph_t * pGraph )   
+{
+    return pGraph->nSize - pGraph->nLeaves;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the pointer to the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Node_t * Dec_GraphNode( Dec_Graph_t * pGraph, int i )   
+{
+    return pGraph->pNodes + i;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the pointer to the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Node_t * Dec_GraphNodeLast( Dec_Graph_t * pGraph )   
+{
+    return pGraph->pNodes + pGraph->nSize - 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphNodeInt( Dec_Graph_t * pGraph, Dec_Node_t * pNode )   
+{
+    return pNode - pGraph->pNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check if the graph represents elementary variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphIsVar( Dec_Graph_t * pGraph )   
+{
+    return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check if the graph represents elementary variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode )   
+{
+    return Dec_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the elementary variable elementary variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Node_t * Dec_GraphVar( Dec_Graph_t * pGraph )   
+{
+    assert( Dec_GraphIsVar( pGraph ) );
+    return Dec_GraphNode( pGraph, pGraph->eRoot.Node );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of the elementary variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dec_GraphVarInt( Dec_Graph_t * pGraph )   
+{
+    assert( Dec_GraphIsVar( pGraph ) );
+    return Dec_GraphNodeInt( pGraph, Dec_GraphVar(pGraph) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the root of the graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Dec_GraphSetRoot( Dec_Graph_t * pGraph, Dec_Edge_t eRoot )   
+{
+    pGraph->eRoot = eRoot;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Appends a new node to the graph.]
+
+  Description [This procedure is meant for internal use.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Node_t * Dec_GraphAppendNode( Dec_Graph_t * pGraph )   
+{
+    Dec_Node_t * pNode;
+    if ( pGraph->nSize == pGraph->nCap )
+    {
+        pGraph->pNodes = ABC_REALLOC( Dec_Node_t, pGraph->pNodes, 2 * pGraph->nCap ); 
+        pGraph->nCap   = 2 * pGraph->nCap;
+    }
+    pNode = pGraph->pNodes + pGraph->nSize++;
+    memset( pNode, 0, sizeof(Dec_Node_t) );
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates an AND node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_GraphAddNodeAnd( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 )
+{
+    Dec_Node_t * pNode;
+    // get the new node
+    pNode = Dec_GraphAppendNode( pGraph );
+    // set the inputs and other info
+    pNode->eEdge0 = eEdge0;
+    pNode->eEdge1 = eEdge1;
+    pNode->fCompl0 = eEdge0.fCompl;
+    pNode->fCompl1 = eEdge1.fCompl;
+    return Dec_EdgeCreate( pGraph->nSize - 1, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates an OR node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 )
+{
+    Dec_Node_t * pNode;
+    // get the new node
+    pNode = Dec_GraphAppendNode( pGraph );
+    // set the inputs and other info
+    pNode->eEdge0 = eEdge0;
+    pNode->eEdge1 = eEdge1;
+    pNode->fCompl0 = eEdge0.fCompl;
+    pNode->fCompl1 = eEdge1.fCompl;
+    // make adjustments for the OR gate
+    pNode->fNodeOr = 1;
+    pNode->eEdge0.fCompl = !pNode->eEdge0.fCompl;
+    pNode->eEdge1.fCompl = !pNode->eEdge1.fCompl;
+    return Dec_EdgeCreate( pGraph->nSize - 1, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates an XOR node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1, int Type )
+{
+    Dec_Edge_t eNode0, eNode1, eNode;
+    if ( Type == 0 )
+    {
+        // derive the first AND
+        eEdge0.fCompl ^= 1;
+        eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+        eEdge0.fCompl ^= 1;
+        // derive the second AND
+        eEdge1.fCompl ^= 1;
+        eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+        // derive the final OR
+        eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+    }
+    else
+    {
+        // derive the first AND
+        eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+        // derive the second AND
+        eEdge0.fCompl ^= 1;
+        eEdge1.fCompl ^= 1;
+        eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+        // derive the final OR
+        eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+        eNode.fCompl ^= 1;
+    }
+    return eNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates an XOR node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_GraphAddNodeMux( Dec_Graph_t * pGraph, Dec_Edge_t eEdgeC, Dec_Edge_t eEdgeT, Dec_Edge_t eEdgeE, int Type )
+{
+    Dec_Edge_t eNode0, eNode1, eNode;
+    if ( Type == 0 )
+    {
+        // derive the first AND
+        eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
+        // derive the second AND
+        eEdgeC.fCompl ^= 1;
+        eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
+        // derive the final OR
+        eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+    }
+    else
+    {
+        // complement the arguments
+        eEdgeT.fCompl ^= 1;
+        eEdgeE.fCompl ^= 1;
+        // derive the first AND
+        eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
+        // derive the second AND
+        eEdgeC.fCompl ^= 1;
+        eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
+        // derive the final OR
+        eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+        eNode.fCompl ^= 1;
+    }
+    return eNode;
+}
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/bool/deco/module.make b/abc-build/src/bool/deco/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/deco/module.make
@@ -0,0 +1,1 @@
+SRC += 
diff --git a/abc-build/src/bool/kit/cloud.c b/abc-build/src/bool/kit/cloud.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/cloud.c
@@ -0,0 +1,993 @@
+/**CFile****************************************************************
+
+  FileName    [cloudCore.c]
+
+  PackageName [Fast application-specific BDD package.]
+
+  Synopsis    [The package core.]
+
+  Author      [Alan Mishchenko <alanmi@ece.pdx.edu>]
+  
+  Affiliation [ECE Department. Portland State University, Portland, Oregon.]
+
+  Date        [Ver. 1.0. Started - June 10, 2002.]
+
+  Revision    [$Id: cloudCore.c,v 1.0 2002/06/10 03:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <string.h>
+#include "cloud.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+// the number of operators using cache
+static int CacheOperNum = 4;
+
+// the ratio of cache size to the unique table size for each operator
+static int CacheLogRatioDefault[4] = {
+	2, // CLOUD_OPER_AND, 
+	8, // CLOUD_OPER_XOR, 
+	8, // CLOUD_OPER_BDIFF, 
+	8  // CLOUD_OPER_LEQ 
+};
+
+// the ratio of cache size to the unique table size for each operator
+static int CacheSize[4] = {
+	2, // CLOUD_OPER_AND, 
+	2, // CLOUD_OPER_XOR, 
+	2, // CLOUD_OPER_BDIFF, 
+	2  // CLOUD_OPER_LEQ 
+};
+
+////////////////////////////////////////////////////////////////////////
+///                       FUNCTION DECLARATIONS                      ///
+////////////////////////////////////////////////////////////////////////
+
+// static functions
+static CloudNode * cloudMakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e );
+static void        cloudCacheAllocate( CloudManager * dd, CloudOper oper );
+
+////////////////////////////////////////////////////////////////////////
+///                       FUNCTION DEFINITIONS                       ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function********************************************************************
+
+  Synopsis    [Starts the cloud manager.]
+
+  Description [The first arguments is the number of elementary variables used.
+  The second arguments is the number of bits of the unsigned integer used to 
+  represent nodes in the unique table. If the second argument is 0, the package 
+  assumes 23 to represent nodes, which is equivalent to 2^23 = 8,388,608 nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+CloudManager * Cloud_Init( int nVars, int nBits )
+{
+	CloudManager * dd;
+	int i;
+	abctime clk1, clk2;
+
+	assert( nVars <= 100000 );
+	assert( nBits < 32 );
+
+	// assign the defaults
+	if ( nBits == 0 )
+		nBits = CLOUD_NODE_BITS;
+
+	// start the manager
+	dd = ABC_CALLOC( CloudManager, 1 );
+	dd->nMemUsed          += sizeof(CloudManager);
+
+	// variables
+	dd->nVars             = nVars;              // the number of variables allocated
+	// bits
+	dd->bitsNode          = nBits;              // the number of bits used for the node
+	for ( i = 0; i < CacheOperNum; i++ )
+		dd->bitsCache[i]  = nBits - CacheLogRatioDefault[i];
+	// shifts
+	dd->shiftUnique       = 8*sizeof(unsigned) - (nBits + 1); // gets node index in the hash table
+	for ( i = 0; i < CacheOperNum; i++ )
+		dd->shiftCache[i] = 8*sizeof(unsigned) - dd->bitsCache[i];
+	// nodes
+	dd->nNodesAlloc       = (1 << (nBits + 1)); // 2 ^ (nBits + 1)
+	dd->nNodesLimit       = (1 << nBits);       // 2 ^  nBits
+
+	// unique table
+clk1 = Abc_Clock();
+	dd->tUnique           = ABC_CALLOC( CloudNode, dd->nNodesAlloc );
+	dd->nMemUsed         += sizeof(CloudNode) * dd->nNodesAlloc;
+clk2 = Abc_Clock();
+//ABC_PRT( "calloc() time", clk2 - clk1 ); 
+
+	// set up the constant node (the only node that is not in the hash table)
+	dd->nSignCur          = 1;
+	dd->tUnique[0].s      = dd->nSignCur;
+	dd->tUnique[0].v      = CLOUD_CONST_INDEX;
+	dd->tUnique[0].e      = NULL;
+	dd->tUnique[0].t      = NULL;
+	dd->one               = dd->tUnique;
+	dd->zero              = Cloud_Not(dd->one);
+	dd->nNodesCur         = 1;
+
+	// special nodes
+	dd->pNodeStart        = dd->tUnique + 1;
+	dd->pNodeEnd          = dd->tUnique + dd->nNodesAlloc;
+
+	// set up the elementary variables
+	dd->vars              = ABC_ALLOC( CloudNode *, dd->nVars );
+	dd->nMemUsed         += sizeof(CloudNode *) * dd->nVars;
+	for ( i = 0; i < dd->nVars; i++ )
+		dd->vars[i]   = cloudMakeNode( dd, i, dd->one, dd->zero );
+
+	return dd;
+};
+
+/**Function********************************************************************
+
+  Synopsis    [Stops the cloud manager.]
+
+  Description [The first arguments tells show many elementary variables are used.
+  The second arguments tells how many bits of the unsigned integer are used
+  to represent regular nodes in the unique table.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Cloud_Quit( CloudManager * dd )
+{
+	int i;
+    ABC_FREE( dd->ppNodes );
+	ABC_FREE( dd->tUnique ); 
+	ABC_FREE( dd->vars ); 
+	for ( i = 0; i < 4; i++ )
+		ABC_FREE( dd->tCaches[i] );
+	ABC_FREE( dd ); 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prepares the manager for another run.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Cloud_Restart( CloudManager * dd )
+{
+    int i;
+    assert( dd->one->s == dd->nSignCur );
+    dd->nSignCur++;
+    dd->one->s++;
+	for ( i = 0; i < dd->nVars; i++ )
+		dd->vars[i]->s++;
+    dd->nNodesCur = 1 + dd->nVars;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This optional function allocates operation cache of the given size.]
+
+  Description [Cache for each operation is allocated independently when the first 
+  operation of the given type is performed. The user can allocate cache of his/her 
+  preferred size by calling Cloud_CacheAllocate before the first operation of the 
+  given type is performed, but this call is optional. Argument "logratio" gives
+  the binary logarithm of the ratio of the size of the unique table to that of cache.
+  For example, if "logratio" is equal to 3, and the unique table will be 2^3=8 times
+  larger than cache; so, if unique table is 2^23 = 8,388,608 nodes, the cache size 
+  will be 2^3=8 times smaller and equal to 2^20 = 1,048,576 entries.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Cloud_CacheAllocate( CloudManager * dd, CloudOper oper, int logratio )
+{
+	assert( logratio > 0 );            // cache cannot be larger than the unique table 
+	assert( logratio < dd->bitsNode ); // cache cannot be smaller than 2 entries
+
+	if ( logratio )
+	{
+		dd->bitsCache[oper]  = dd->bitsNode - logratio;
+		dd->shiftCache[oper] = 8*sizeof(unsigned) - dd->bitsCache[oper];
+	}
+	cloudCacheAllocate( dd, oper );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Internal cache allocation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void cloudCacheAllocate( CloudManager * dd, CloudOper oper )
+{
+	int nCacheEntries = (1 << dd->bitsCache[oper]);
+
+	if ( CacheSize[oper] == 1 )
+	{
+		dd->tCaches[oper] = (CloudCacheEntry2 *)ABC_CALLOC( CloudCacheEntry1, nCacheEntries );
+		dd->nMemUsed     += sizeof(CloudCacheEntry1) * nCacheEntries;
+	}
+	else if ( CacheSize[oper] == 2 )
+	{
+		dd->tCaches[oper] = (CloudCacheEntry2 *)ABC_CALLOC( CloudCacheEntry2, nCacheEntries );
+		dd->nMemUsed     += sizeof(CloudCacheEntry2) * nCacheEntries;
+	}
+	else if ( CacheSize[oper] == 3 )
+	{
+		dd->tCaches[oper] = (CloudCacheEntry2 *)ABC_CALLOC( CloudCacheEntry3, nCacheEntries );
+		dd->nMemUsed     += sizeof(CloudCacheEntry3) * nCacheEntries;
+	}
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns or creates a new node]
+
+  Description [Checks the unique table for the existance of the node. If the node is 
+  present, returns the node. If the node is absent, creates a new node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+CloudNode * Cloud_MakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e )
+{
+	CloudNode * pRes;
+	CLOUD_ASSERT(t); 
+	CLOUD_ASSERT(e);
+    assert( v < Cloud_V(t) && v < Cloud_V(e) );       // variable should be above in the order
+    if ( Cloud_IsComplement(t) )
+    {
+        pRes = cloudMakeNode( dd, v, Cloud_Not(t), Cloud_Not(e) );
+        if ( pRes != NULL )
+            pRes = Cloud_Not(pRes);            
+    }
+    else
+        pRes = cloudMakeNode( dd, v, t, e );
+    return pRes;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns or creates a new node]
+
+  Description [Checks the unique table for the existance of the node. If the node is 
+  present, returns the node. If the node is absent, creates a new node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+CloudNode * cloudMakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e )
+{
+	CloudNode * entryUnique;
+
+	CLOUD_ASSERT(t); 
+	CLOUD_ASSERT(e);
+
+	assert( ((int)v) >= 0 && ((int)v) < dd->nVars );  // the variable must be in the range
+    assert( v < Cloud_V(t) && v < Cloud_V(e) );       // variable should be above in the order
+	assert( !Cloud_IsComplement(t) );                 // the THEN edge must not be complemented
+
+	// make sure we are not searching for the constant node
+	assert( t && e );
+
+	// get the unique entry
+	entryUnique = dd->tUnique + cloudHashCudd3(v, t, e, dd->shiftUnique);
+	while ( entryUnique->s == dd->nSignCur )
+	{
+		// compare the node
+		if ( entryUnique->v == v && entryUnique->t == t && entryUnique->e == e )
+		{ // the node is found
+			dd->nUniqueHits++;
+			return entryUnique;  // returns the node
+		}
+		// increment the hash value modulus the hash table size
+		if ( ++entryUnique - dd->tUnique == dd->nNodesAlloc )
+			entryUnique = dd->tUnique + 1;
+		// increment the number of steps through the table
+		dd->nUniqueSteps++;
+	}
+	dd->nUniqueMisses++;
+
+	// check if the new node can be created
+	if ( ++dd->nNodesCur == dd->nNodesLimit ) 
+	{ // initiate the restart
+		printf( "Cloud needs restart!\n" );
+//		fflush( stdout );
+//		exit(1);
+		return NULL;
+	}
+	// create the node
+	entryUnique->s   = dd->nSignCur;
+	entryUnique->v   = v;
+	entryUnique->t   = t;
+	entryUnique->e   = e;
+	return entryUnique;  // returns the node
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the AND or two BDDs]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+CloudNode * cloudBddAnd( CloudManager * dd, CloudNode * f, CloudNode * g )
+{
+	CloudNode * F, * G, * r;
+	CloudCacheEntry2 * cacheEntry;
+	CloudNode * fv, * fnv, * gv, * gnv, * t, * e;
+	CloudVar  var;
+
+	assert( f <= g );
+
+	// terminal cases
+	F = Cloud_Regular(f);
+	G = Cloud_Regular(g);
+	if ( F == G )
+	{
+		if ( f == g )
+			return f;
+		else
+			return dd->zero;
+	}
+	if ( F == dd->one )
+	{
+		if ( f == dd->one )
+			return g;
+		else
+			return f;
+	}
+
+	// check cache
+	cacheEntry = dd->tCaches[CLOUD_OPER_AND] + cloudHashCudd2(f, g, dd->shiftCache[CLOUD_OPER_AND]);
+//	cacheEntry = dd->tCaches[CLOUD_OPER_AND] + cloudHashBuddy2(f, g, dd->shiftCache[CLOUD_OPER_AND]);
+	r = cloudCacheLookup2( cacheEntry, dd->nSignCur, f, g );
+	if ( r != NULL )
+	{
+		dd->nCacheHits++;
+		return r;
+	}
+	dd->nCacheMisses++;
+
+
+	// compute cofactors
+	if ( cloudV(F) <= cloudV(G) )
+	{
+		var = cloudV(F);
+		if ( Cloud_IsComplement(f) )
+		{
+			fnv = Cloud_Not(cloudE(F));
+			fv  = Cloud_Not(cloudT(F));
+		}
+		else
+		{
+			fnv = cloudE(F);
+			fv  = cloudT(F);
+		}
+	}
+	else
+	{
+		var = cloudV(G);
+		fv  = fnv = f;
+	}
+
+	if ( cloudV(G) <= cloudV(F) )
+	{
+		if ( Cloud_IsComplement(g) )
+		{
+			gnv = Cloud_Not(cloudE(G));
+			gv  = Cloud_Not(cloudT(G));
+		}
+		else
+		{
+			gnv = cloudE(G);
+			gv  = cloudT(G);
+		}
+	}
+	else
+	{
+		gv = gnv = g;
+	}
+
+	if ( fv <= gv )
+		t = cloudBddAnd( dd, fv, gv );
+	else
+		t = cloudBddAnd( dd, gv, fv );
+
+	if ( t == NULL )
+		return NULL;
+
+	if ( fnv <= gnv )
+		e = cloudBddAnd( dd, fnv, gnv );
+	else
+		e = cloudBddAnd( dd, gnv, fnv );
+
+	if ( e == NULL )
+		return NULL;
+
+	if ( t == e )
+		r = t;
+	else
+	{
+		if ( Cloud_IsComplement(t) )
+		{
+			r = cloudMakeNode( dd, var, Cloud_Not(t), Cloud_Not(e) );
+			if ( r == NULL )
+				return NULL;
+			r = Cloud_Not(r);
+		}
+		else
+		{
+			r = cloudMakeNode( dd, var, t, e );
+			if ( r == NULL )
+				return NULL;
+		}
+	}
+	cloudCacheInsert2( cacheEntry, dd->nSignCur, f, g, r );
+	return r;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the AND or two BDDs]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static inline CloudNode * cloudBddAnd_gate( CloudManager * dd, CloudNode * f, CloudNode * g )
+{
+	if ( f <= g )
+		return cloudBddAnd(dd,f,g);
+	else
+		return cloudBddAnd(dd,g,f);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the AND or two BDDs]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+CloudNode * Cloud_bddAnd( CloudManager * dd, CloudNode * f, CloudNode * g )
+{
+    if ( Cloud_Regular(f) == NULL || Cloud_Regular(g) == NULL )
+        return NULL;
+	CLOUD_ASSERT(f);
+	CLOUD_ASSERT(g);
+	if ( dd->tCaches[CLOUD_OPER_AND] == NULL )
+		cloudCacheAllocate( dd, CLOUD_OPER_AND );
+	return cloudBddAnd_gate( dd, f, g );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the OR or two BDDs]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+CloudNode * Cloud_bddOr( CloudManager * dd, CloudNode * f, CloudNode * g )
+{
+	CloudNode * res;
+    if ( Cloud_Regular(f) == NULL || Cloud_Regular(g) == NULL )
+        return NULL;
+	CLOUD_ASSERT(f);
+	CLOUD_ASSERT(g);
+	if ( dd->tCaches[CLOUD_OPER_AND] == NULL )
+		cloudCacheAllocate( dd, CLOUD_OPER_AND );
+	res = cloudBddAnd_gate( dd, Cloud_Not(f), Cloud_Not(g) );
+	res = Cloud_NotCond( res, res != NULL );
+	return res;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the XOR or two BDDs]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+CloudNode * Cloud_bddXor( CloudManager * dd, CloudNode * f, CloudNode * g )
+{
+	CloudNode * t0, * t1, * r;
+    if ( Cloud_Regular(f) == NULL || Cloud_Regular(g) == NULL )
+        return NULL;
+	CLOUD_ASSERT(f);
+	CLOUD_ASSERT(g);
+	if ( dd->tCaches[CLOUD_OPER_AND] == NULL )
+		cloudCacheAllocate( dd, CLOUD_OPER_AND );
+	t0 = cloudBddAnd_gate( dd, f, Cloud_Not(g) );
+	if ( t0 == NULL )
+		return NULL;
+	t1 = cloudBddAnd_gate( dd, Cloud_Not(f), g );
+	if ( t1 == NULL )
+		return NULL;
+	r  = Cloud_bddOr( dd, t0, t1 );
+	return r;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs a DFS from f, clearing the LSB of the next
+  pointers.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cloudSupport cloudDagSize]
+
+******************************************************************************/
+static void cloudClearMark( CloudManager * dd, CloudNode * n )
+{
+	if ( !cloudNodeIsMarked(n) )
+		return;
+	// clear visited flag
+	cloudNodeUnmark(n);
+	if ( cloudIsConstant(n) )
+		return;
+	cloudClearMark( dd, cloudT(n) );
+	cloudClearMark( dd, Cloud_Regular(cloudE(n)) );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cloud_Support.]
+
+  Description [Performs the recursive step of Cloud_Support. Performs a
+  DFS from f. The support is accumulated in supp as a side effect. Uses
+  the LSB of the then pointer as visited flag.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void cloudSupport( CloudManager * dd, CloudNode * n, int * support )
+{
+	if ( cloudIsConstant(n) || cloudNodeIsMarked(n) )
+		return;
+	// set visited flag
+	cloudNodeMark(n);
+	support[cloudV(n)] = 1;
+	cloudSupport( dd, cloudT(n), support );
+	cloudSupport( dd, Cloud_Regular(cloudE(n)), support );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the variables on which a DD depends.]
+
+  Description [Finds the variables on which a DD depends.
+  Returns a BDD consisting of the product of the variables if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+CloudNode * Cloud_Support( CloudManager * dd, CloudNode * n )
+{
+	CloudNode * res;
+	int * support, i;
+
+	CLOUD_ASSERT(n);
+
+	// allocate and initialize support array for cloudSupport
+	support = ABC_CALLOC( int, dd->nVars );
+
+	// compute support and clean up markers
+	cloudSupport( dd, Cloud_Regular(n), support );
+	cloudClearMark( dd, Cloud_Regular(n) );
+
+	// transform support from array to cube
+	res = dd->one;
+	for ( i = dd->nVars - 1; i >= 0; i-- ) // for each level bottom-up 
+		if ( support[i] == 1 )
+		{
+			res = Cloud_bddAnd( dd, res, dd->vars[i] );
+			if ( res == NULL )
+				break;
+		}
+	ABC_FREE( support );
+	return res;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the variables on which a DD depends.]
+
+  Description [Counts the variables on which a DD depends.
+  Returns the number of the variables if successful; Cloud_OUT_OF_MEM
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int Cloud_SupportSize( CloudManager * dd, CloudNode * n )
+{
+	int * support, i, count;
+
+	CLOUD_ASSERT(n);
+
+	// allocate and initialize support array for cloudSupport
+	support = ABC_CALLOC( int, dd->nVars );
+
+	// compute support and clean up markers
+	cloudSupport( dd, Cloud_Regular(n), support );
+	cloudClearMark( dd, Cloud_Regular(n) );
+
+	// count support variables
+	count = 0;
+	for ( i = 0; i < dd->nVars; i++ )
+	{
+		if ( support[i] == 1 )
+			count++;
+	}
+
+	ABC_FREE( support );
+	return count;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cloud_DagSize.]
+
+  Description [Performs the recursive step of Cloud_DagSize. Returns the
+  number of nodes in the graph rooted at n.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int cloudDagSize( CloudManager * dd, CloudNode * n )
+{
+	int tval, eval;
+	if ( cloudNodeIsMarked(n) )
+		return 0;
+	// set visited flag
+	cloudNodeMark(n);
+	if ( cloudIsConstant(n) )
+		return 1;
+	tval = cloudDagSize( dd, cloudT(n) );
+	eval = cloudDagSize( dd, Cloud_Regular(cloudE(n)) );
+	return tval + eval + 1;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of nodes in a DD.]
+
+  Description [Counts the number of nodes in a DD. Returns the number
+  of nodes in the graph rooted at node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Cloud_DagSize( CloudManager * dd, CloudNode * n )
+{
+	int res;
+	res = cloudDagSize( dd, Cloud_Regular( n ) );
+	cloudClearMark( dd, Cloud_Regular( n ) );
+	return res;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cloud_DagSize.]
+
+  Description [Performs the recursive step of Cloud_DagSize. Returns the
+  number of nodes in the graph rooted at n.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int Cloud_DagCollect_rec( CloudManager * dd, CloudNode * n, int * pCounter )
+{
+	int tval, eval;
+	if ( cloudNodeIsMarked(n) )
+		return 0;
+	// set visited flag
+	cloudNodeMark(n);
+	if ( cloudIsConstant(n) )
+    {
+        dd->ppNodes[(*pCounter)++] = n;
+		return 1;
+    }
+	tval = Cloud_DagCollect_rec( dd, cloudT(n), pCounter );
+	eval = Cloud_DagCollect_rec( dd, Cloud_Regular(cloudE(n)), pCounter );
+    dd->ppNodes[(*pCounter)++] = n;
+	return tval + eval + 1;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of nodes in a DD.]
+
+  Description [Counts the number of nodes in a DD. Returns the number
+  of nodes in the graph rooted at node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Cloud_DagCollect( CloudManager * dd, CloudNode * n )
+{
+	int res, Counter = 0;
+    if ( dd->ppNodes == NULL )
+        dd->ppNodes = ABC_ALLOC( CloudNode *, dd->nNodesLimit );
+	res = Cloud_DagCollect_rec( dd, Cloud_Regular( n ), &Counter );
+	cloudClearMark( dd, Cloud_Regular( n ) );
+    assert( res == Counter );
+	return res;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of nodes in an array of DDs.]
+
+  Description [Counts the number of nodes in a DD. Returns the number
+  of nodes in the graph rooted at node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Cloud_SharingSize( CloudManager * dd, CloudNode ** pn, int nn )
+{
+	int res, i;
+	res = 0;
+	for ( i = 0; i < nn; i++ )
+		res += cloudDagSize( dd, Cloud_Regular( pn[i] ) );
+	for ( i = 0; i < nn; i++ )
+		cloudClearMark( dd, Cloud_Regular( pn[i] ) );
+	return res;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns one cube contained in the given BDD.]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+CloudNode * Cloud_GetOneCube( CloudManager * dd, CloudNode * bFunc )
+{
+	CloudNode * bFunc0, * bFunc1, * res;
+
+	if ( Cloud_IsConstant(bFunc) )
+		return bFunc;
+
+	// cofactor
+	if ( Cloud_IsComplement(bFunc) )
+	{
+		bFunc0 = Cloud_Not( cloudE(bFunc) );
+		bFunc1 = Cloud_Not( cloudT(bFunc) );
+	}
+	else
+	{
+		bFunc0 = cloudE(bFunc);
+		bFunc1 = cloudT(bFunc);
+	}
+
+	// try to find the cube with the negative literal
+	res = Cloud_GetOneCube( dd, bFunc0 );
+	if ( res == NULL )
+		return NULL;
+
+	if ( res != dd->zero )
+	{
+		res = Cloud_bddAnd( dd, res, Cloud_Not(dd->vars[Cloud_V(bFunc)]) );
+	}
+	else
+	{
+		// try to find the cube with the positive literal
+		res = Cloud_GetOneCube( dd, bFunc1 );
+		if ( res == NULL )
+			return NULL;
+		assert( res != dd->zero );
+		res = Cloud_bddAnd( dd, res, dd->vars[Cloud_V(bFunc)] );
+	}
+	return res;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the BDD as a set of disjoint cubes to the standard output.]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+void Cloud_bddPrint( CloudManager * dd, CloudNode * Func )
+{
+	CloudNode * Cube;
+	int fFirst = 1;
+
+	if ( Func == dd->zero )
+		printf( "Constant 0." );
+	else if ( Func == dd->one )
+		printf( "Constant 1." );
+	else
+	{
+		while ( 1 )
+		{
+			Cube = Cloud_GetOneCube( dd, Func );
+			if ( Cube == NULL || Cube == dd->zero )
+				break;
+			if ( fFirst )   	fFirst = 0;
+			else				printf( " + " );
+			Cloud_bddPrintCube( dd, Cube );
+			Func = Cloud_bddAnd( dd, Func, Cloud_Not(Cube) );
+		} 
+	}
+	printf( "\n" );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints one cube.]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+void Cloud_bddPrintCube( CloudManager * dd, CloudNode * bCube )
+{
+	CloudNode * bCube0, * bCube1;
+
+	assert( !Cloud_IsConstant(bCube) );
+	while ( 1 )
+	{
+		// get the node structure
+		if ( Cloud_IsConstant(bCube) )
+			break;
+
+		// cofactor the cube
+		if ( Cloud_IsComplement(bCube) )
+		{
+			bCube0 = Cloud_Not( cloudE(bCube) );
+			bCube1 = Cloud_Not( cloudT(bCube) );
+		}
+		else
+		{
+			bCube0 = cloudE(bCube);
+			bCube1 = cloudT(bCube);
+		}
+
+		if ( bCube0 != dd->zero )
+		{
+			assert( bCube1 == dd->zero );
+			printf( "[%d]'", cloudV(bCube) );
+			bCube = bCube0;
+		}
+		else
+		{
+			assert( bCube1 != dd->zero );
+			printf( "[%d]", cloudV(bCube) );
+			bCube = bCube1;
+		}
+	}
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints info.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Cloud_PrintInfo( CloudManager * dd )
+{
+    if ( dd == NULL ) return;
+	printf( "The number of unique table nodes allocated = %12d.\n", dd->nNodesAlloc );
+	printf( "The number of unique table nodes present   = %12d.\n", dd->nNodesCur );
+	printf( "The number of unique table hits            = %12d.\n", dd->nUniqueHits );
+	printf( "The number of unique table misses          = %12d.\n", dd->nUniqueMisses );
+	printf( "The number of unique table steps           = %12d.\n", dd->nUniqueSteps );
+	printf( "The number of cache hits                   = %12d.\n", dd->nCacheHits );
+	printf( "The number of cache misses                 = %12d.\n", dd->nCacheMisses );
+	printf( "The current signature                      = %12d.\n", dd->nSignCur );
+	printf( "The total memory in use                    = %12d.\n", dd->nMemUsed );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the state of the hash table.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Cloud_PrintHashTable( CloudManager * dd )
+{
+	int i;
+
+	for ( i = 0; i < dd->nNodesAlloc; i++ )
+		if ( dd->tUnique[i].v == CLOUD_CONST_INDEX )
+			printf( "-" );
+		else
+			printf( "+" );
+	printf( "\n" );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/kit/cloud.h b/abc-build/src/bool/kit/cloud.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/cloud.h
@@ -0,0 +1,254 @@
+/**CFile****************************************************************
+
+  FileName    [cloud.h]
+
+  PackageName [Fast application-specific BDD package.]
+
+  Synopsis    [Interface of the package.]
+
+  Author      [Alan Mishchenko <alanmi@ece.pdx.edu>]
+  
+  Affiliation [ECE Department. Portland State University, Portland, Oregon.]
+
+  Date        [Ver. 1.0. Started - June 10, 2002.]
+
+  Revision    [$Id: cloud.h,v 1.0 2002/06/10 03:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__kit__cloud_h
+#define ABC__aig__kit__cloud_h
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "misc/util/abc_global.h"
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+#ifdef _WIN32
+#define inline __inline // compatible with MS VS 6.0
+#endif
+
+////////////////////////////////////////////////////////////////////////
+//  n |  2^n ||  n |    2^n ||  n |        2^n ||  n |           2^n  //
+//====================================================================//
+//  1 |    2 ||  9 |    512 || 17 |    131,072 || 25 |    33,554,432  //
+//  2 |    4 || 10 |  1,024 || 18 |    262,144 || 26 |    67,108,864  // 
+//  3 |    8 || 11 |  2,048 || 19 |    524,288 || 27 |   134,217,728  //
+//  4 |   16 || 12 |  4,096 || 20 |  1,048,576 || 28 |   268,435,456  //
+//  5 |   32 || 13 |  8,192 || 21 |  2,097,152 || 29 |   536,870,912  //
+//  6 |   64 || 14 | 16,384 || 22 |  4,194,304 || 30 | 1,073,741,824  //
+//  7 |  128 || 15 | 32,768 || 23 |  8,388,608 || 31 | 2,147,483,648  //
+//  8 |  256 || 16 | 65,536 || 24 | 16,777,216 || 32 | 4,294,967,296  //
+////////////////////////////////////////////////////////////////////////
+
+// data structure typedefs
+typedef struct cloudManager       CloudManager;
+typedef unsigned                  CloudVar;
+typedef unsigned                  CloudSign;
+typedef struct cloudNode          CloudNode;
+typedef struct cloudCacheEntry1   CloudCacheEntry1;
+typedef struct cloudCacheEntry2   CloudCacheEntry2;
+typedef struct cloudCacheEntry3   CloudCacheEntry3;
+
+// operation codes used to set up the cache
+typedef enum { 
+	CLOUD_OPER_AND, 
+	CLOUD_OPER_XOR, 
+	CLOUD_OPER_BDIFF, 
+	CLOUD_OPER_LEQ 
+} CloudOper;
+
+/*
+// the number of operators using cache
+static int CacheOperNum = 4;
+
+// the ratio of cache size to the unique table size for each operator
+static int CacheLogRatioDefault[4] = {
+	4, // CLOUD_OPER_AND, 
+	8, // CLOUD_OPER_XOR, 
+	8, // CLOUD_OPER_BDIFF, 
+	8  // CLOUD_OPER_LEQ 
+};
+
+// the ratio of cache size to the unique table size for each operator
+static int CacheSize[4] = {
+	2, // CLOUD_OPER_AND, 
+	2, // CLOUD_OPER_XOR, 
+	2, // CLOUD_OPER_BDIFF, 
+	2  // CLOUD_OPER_LEQ 
+};
+*/
+
+// data structure definitions
+struct cloudManager            // the fast bdd manager     
+{
+	// variables
+	int nVars;                 // the number of variables allocated
+	// bits
+	int bitsNode;              // the number of bits used for the node
+	int bitsCache[4];          // default: bitsNode - CacheSizeRatio[i]
+	// shifts
+	int shiftUnique;           // 8*sizeof(unsigned) - (bitsNode + 1)
+	int shiftCache[4];         // 8*sizeof(unsigned) -  bitsCache[i]
+	// nodes 
+	int nNodesAlloc;           // 2 ^ (bitsNode + 1)
+	int nNodesLimit;           // 2 ^  bitsNode
+	int nNodesCur;             // the current number of nodes (including const1 and vars)
+	// signature
+	CloudSign nSignCur;
+
+	// statistics
+	int nMemUsed;              // memory usage in bytes
+	// cache stats
+	int nUniqueHits;           // hits in the unique table
+	int nUniqueMisses;         // misses in the unique table
+	int nCacheHits;            // hits in the caches
+	int nCacheMisses;          // misses in the caches
+	// the number of steps through the hash table
+	int nUniqueSteps;
+
+	// tables
+	CloudNode * tUnique;       // the unique table to store BDD nodes
+
+	// special nodes
+	CloudNode * pNodeStart;    // the pointer to the first node
+	CloudNode * pNodeEnd;      // the pointer to the first node out of the table
+
+	// constants and variables
+	CloudNode *  one;          // the one function
+	CloudNode *  zero;         // the zero function
+	CloudNode ** vars;         // the elementary variables
+
+    // temporary storage for nodes
+    CloudNode ** ppNodes;
+
+	// caches
+	CloudCacheEntry2 * tCaches[20];    // caches
+};
+
+struct cloudNode   // representation of the node in the unique table
+{
+	CloudSign   s;         // signature
+	CloudVar    v;         // variable
+	CloudNode * e;         // negative cofactor
+	CloudNode * t;         // positive cofactor
+};
+struct cloudCacheEntry1  // one-argument cache
+{
+	CloudSign   s;         // signature
+	CloudNode * a;         // argument 1
+	CloudNode * r;         // result
+};
+struct cloudCacheEntry2  // the two-argument cache
+{
+	CloudSign   s;         // signature
+	CloudNode * a;
+	CloudNode * b;
+	CloudNode * r;
+};
+struct cloudCacheEntry3  // the three-argument cache
+{
+	CloudSign   s;         // signature
+	CloudNode * a;
+	CloudNode * b;
+	CloudNode * c;
+	CloudNode * r;
+};
+
+
+// parameters
+#define CLOUD_NODE_BITS              23
+
+#define CLOUD_CONST_INDEX            ((unsigned)0x0fffffff)
+#define CLOUD_MARK_ON                ((unsigned)0x10000000)
+#define CLOUD_MARK_OFF               ((unsigned)0xefffffff)
+
+// hash functions a la Buddy
+#define cloudHashBuddy2(x,y,s)       ((((x)+(y))*((x)+(y)+1)/2) & ((1<<(32-(s)))-1))
+#define cloudHashBuddy3(x,y,z,s)     (cloudHashBuddy2((cloudHashBuddy2((x),(y),(s))),(z),(s)) & ((1<<(32-(s)))-1))
+// hash functions a la Cudd
+#define DD_P1		  	             12582917
+#define DD_P2			             4256249
+#define DD_P3			             741457
+#define DD_P4			             1618033999
+#define cloudHashCudd2(f,g,s)        ((((unsigned)(ABC_PTRUINT_T)(f) * DD_P1 + (unsigned)(ABC_PTRUINT_T)(g)) * DD_P2) >> (s))
+#define cloudHashCudd3(f,g,h,s)      (((((unsigned)(ABC_PTRUINT_T)(f) * DD_P1 + (unsigned)(ABC_PTRUINT_T)(g)) * DD_P2 + (unsigned)(ABC_PTRUINT_T)(h)) * DD_P3) >> (s))
+
+// node complementation (using node)
+#define Cloud_Regular(p)             ((CloudNode*)(((ABC_PTRUINT_T)(p)) & ~01))   // get the regular node (w/o bubble)
+#define Cloud_Not(p)                 ((CloudNode*)(((ABC_PTRUINT_T)(p)) ^  01))   // complement the node
+#define Cloud_NotCond(p,c)           ((CloudNode*)(((ABC_PTRUINT_T)(p)) ^ (c)))   // complement the node conditionally
+#define Cloud_IsComplement(p)        ((int)(((ABC_PTRUINT_T)(p)) & 01))           // check if complemented
+// checking constants (using node)
+#define Cloud_IsConstant(p)          (((Cloud_Regular(p))->v & CLOUD_MARK_OFF) == CLOUD_CONST_INDEX)
+#define cloudIsConstant(p)           (((p)->v & CLOUD_MARK_OFF) == CLOUD_CONST_INDEX)
+
+// retrieving values from the node (using node structure)
+#define Cloud_V(p)                   ((Cloud_Regular(p))->v)
+#define Cloud_E(p)                   ((Cloud_Regular(p))->e)
+#define Cloud_T(p)                   ((Cloud_Regular(p))->t)
+// retrieving values from the regular node (using node structure)
+#define cloudV(p)                    ((p)->v)
+#define cloudE(p)                    ((p)->e)
+#define cloudT(p)                    ((p)->t)
+// marking/unmarking (using node structure)
+#define cloudNodeMark(p)             ((p)->v       |= CLOUD_MARK_ON)
+#define cloudNodeUnmark(p)           ((p)->v       &= CLOUD_MARK_OFF)
+#define cloudNodeIsMarked(p)         ((int)((p)->v &  CLOUD_MARK_ON))
+
+// cache lookups and inserts (using node)
+#define cloudCacheLookup1(p,sign,f)     (((p)->s == (sign) && (p)->a == (f))? ((p)->r): (0))
+#define cloudCacheLookup2(p,sign,f,g)   (((p)->s == (sign) && (p)->a == (f) && (p)->b == (g))? ((p)->r): (0))
+#define cloudCacheLookup3(p,sign,f,g,h) (((p)->s == (sign) && (p)->a == (f) && (p)->b == (g) && (p)->c == (h))? ((p)->r): (0))
+// cache inserts
+#define cloudCacheInsert1(p,sign,f,r)     (((p)->s = (sign)), ((p)->a = (f)), ((p)->r = (r)))
+#define cloudCacheInsert2(p,sign,f,g,r)   (((p)->s = (sign)), ((p)->a = (f)), ((p)->b = (g)), ((p)->r = (r)))
+#define cloudCacheInsert3(p,sign,f,g,h,r) (((p)->s = (sign)), ((p)->a = (f)), ((p)->b = (g)), ((p)->c = (h)), ((p)->r = (r)))
+
+//#define CLOUD_ASSERT(p)              (assert((p) >= (dd->pNodeStart-1) && (p) < dd->pNodeEnd))
+#define CLOUD_ASSERT(p)            assert((p) >= dd->tUnique && (p) < dd->tUnique+dd->nNodesAlloc)
+
+////////////////////////////////////////////////////////////////////////
+///                       FUNCTION DECLARATIONS                      ///
+////////////////////////////////////////////////////////////////////////
+// starting/stopping 
+extern CloudManager * Cloud_Init( int nVars, int nBits );
+extern void           Cloud_Quit( CloudManager * dd );
+extern void           Cloud_Restart( CloudManager * dd );
+extern void           Cloud_CacheAllocate( CloudManager * dd, CloudOper oper, int size );
+extern CloudNode *    Cloud_MakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e );
+// support and node count
+extern CloudNode *    Cloud_Support( CloudManager * dd, CloudNode * n );
+extern int            Cloud_SupportSize( CloudManager * dd, CloudNode * n );
+extern int            Cloud_DagSize( CloudManager * dd, CloudNode * n );
+extern int            Cloud_DagCollect( CloudManager * dd, CloudNode * n );
+extern int            Cloud_SharingSize( CloudManager * dd, CloudNode * * pn, int nn );
+// cubes
+extern CloudNode *    Cloud_GetOneCube( CloudManager * dd, CloudNode * n );
+extern void           Cloud_bddPrint( CloudManager * dd, CloudNode * Func );
+extern void           Cloud_bddPrintCube( CloudManager * dd, CloudNode * Cube );
+// operations
+extern CloudNode *    Cloud_bddAnd( CloudManager * dd, CloudNode * f, CloudNode * g );
+extern CloudNode *    Cloud_bddOr( CloudManager * dd, CloudNode * f, CloudNode * g );
+// stats 
+extern void           Cloud_PrintInfo( CloudManager * dd );
+extern void           Cloud_PrintHashTable( CloudManager * dd );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                            END OF FILE                           ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/bool/kit/kit.h b/abc-build/src/bool/kit/kit.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/kit.h
@@ -0,0 +1,649 @@
+/**CFile****************************************************************
+
+  FileName    [kit.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Computation kit.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 6, 2006.]
+
+  Revision    [$Id: kit.h,v 1.00 2006/12/06 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__kit__kit_h
+#define ABC__aig__kit__kit_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+#include "misc/extra/extraBdd.h"
+#include "cloud.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Kit_Sop_t_ Kit_Sop_t;
+struct Kit_Sop_t_
+{
+    int               nLits;          // the number of literals
+    int               nCubes;         // the number of cubes
+    unsigned *        pCubes;         // the storage for cubes
+};
+
+typedef struct Kit_Edge_t_ Kit_Edge_t;
+struct Kit_Edge_t_
+{
+    unsigned          fCompl   :  1;   // the complemented bit
+    unsigned          Node     : 30;   // the decomposition node pointed by the edge
+};
+
+typedef struct Kit_Node_t_ Kit_Node_t;
+struct Kit_Node_t_
+{
+    Kit_Edge_t        eEdge0;          // the left child of the node
+    Kit_Edge_t        eEdge1;          // the right child of the node
+    // other info
+    union { int       iFunc;           // the function of the node (BDD or AIG)
+    void *            pFunc; };        // the function of the node (BDD or AIG)
+    unsigned          Level    : 14;   // the level of this node in the global AIG
+    // printing info 
+    unsigned          fNodeOr  :  1;   // marks the original OR node
+    unsigned          fCompl0  :  1;   // marks the original complemented edge
+    unsigned          fCompl1  :  1;   // marks the original complemented edge
+    // latch info
+    unsigned          nLat0    :  5;   // the number of latches on the first edge
+    unsigned          nLat1    :  5;   // the number of latches on the second edge
+    unsigned          nLat2    :  5;   // the number of latches on the output edge
+};
+
+typedef struct Kit_Graph_t_ Kit_Graph_t;
+struct Kit_Graph_t_
+{
+    int               fConst;          // marks the constant 1 graph
+    int               nLeaves;         // the number of leaves
+    int               nSize;           // the number of nodes (including the leaves) 
+    int               nCap;            // the number of allocated nodes
+    Kit_Node_t *      pNodes;          // the array of leaves and internal nodes
+    Kit_Edge_t        eRoot;           // the pointer to the topmost node
+};
+
+
+// DSD node types
+typedef enum { 
+    KIT_DSD_NONE  = 0,  // 0: unknown
+    KIT_DSD_CONST1,     // 1: constant 1
+    KIT_DSD_VAR,        // 2: elementary variable
+    KIT_DSD_AND,        // 3: multi-input AND
+    KIT_DSD_XOR,        // 4: multi-input XOR
+    KIT_DSD_PRIME       // 5: arbitrary function of 3+ variables
+} Kit_Dsd_t;
+
+// DSD node
+typedef struct Kit_DsdObj_t_ Kit_DsdObj_t;
+struct Kit_DsdObj_t_
+{ 
+    unsigned       Id         : 6;  // the number of this node
+    unsigned       Type       : 3;  // none, const, var, AND, XOR, MUX, PRIME
+    unsigned       fMark      : 1;  // finished checking output
+    unsigned       Offset     : 8;  // offset to the truth table
+    unsigned       nRefs      : 8;  // offset to the truth table
+    unsigned       nFans      : 6;  // the number of fanins of this node
+    unsigned short pFans[0];        // the fanin literals
+};
+
+// DSD network
+typedef struct Kit_DsdNtk_t_ Kit_DsdNtk_t;
+struct Kit_DsdNtk_t_
+{
+    unsigned short nVars;           // at most 16 (perhaps 18?)
+    unsigned short nNodesAlloc;     // the number of allocated nodes (at most nVars)
+    unsigned short nNodes;          // the number of nodes
+    unsigned short Root;            // the root of the tree
+    unsigned *     pMem;            // memory for the truth tables (memory manager?)
+    unsigned *     pSupps;          // supports of the nodes
+    Kit_DsdObj_t** pNodes;          // the nodes
+};
+
+// DSD manager
+typedef struct Kit_DsdMan_t_ Kit_DsdMan_t;
+struct Kit_DsdMan_t_
+{
+    int            nVars;           // the maximum number of variables
+    int            nWords;          // the number of words in TTs
+    Vec_Ptr_t *    vTtElems;        // elementary truth tables
+    Vec_Ptr_t *    vTtNodes;        // the node truth tables
+    // BDD representation
+    CloudManager * dd;              // BDD package
+    Vec_Ptr_t *    vTtBdds;         // the node truth tables
+    Vec_Int_t *    vNodes;          // temporary array for BDD nodes
+};
+ 
+static inline unsigned        Kit_DsdObjOffset( int nFans )          { return (nFans >> 1) + ((nFans & 1) > 0);                    }
+static inline unsigned *      Kit_DsdObjTruth( Kit_DsdObj_t * pObj ) { return pObj->Type == KIT_DSD_PRIME ? (unsigned *)pObj->pFans + pObj->Offset: NULL; }
+static inline int             Kit_DsdNtkObjNum( Kit_DsdNtk_t * pNtk ){ return pNtk->nVars + pNtk->nNodes; }
+static inline Kit_DsdObj_t *  Kit_DsdNtkObj( Kit_DsdNtk_t * pNtk, int Id )      { assert( Id >= 0 && Id < pNtk->nVars + pNtk->nNodes ); return Id < pNtk->nVars ? NULL : pNtk->pNodes[Id - pNtk->nVars]; }
+static inline Kit_DsdObj_t *  Kit_DsdNtkRoot( Kit_DsdNtk_t * pNtk )             { return Kit_DsdNtkObj( pNtk, Abc_Lit2Var(pNtk->Root) );                      }
+static inline int             Kit_DsdLitIsLeaf( Kit_DsdNtk_t * pNtk, int Lit )   { int Id = Abc_Lit2Var(Lit); assert( Id >= 0 && Id < pNtk->nVars + pNtk->nNodes ); return Id < pNtk->nVars; }
+static inline unsigned        Kit_DsdLitSupport( Kit_DsdNtk_t * pNtk, int Lit )  { int Id = Abc_Lit2Var(Lit); assert( Id >= 0 && Id < pNtk->nVars + pNtk->nNodes ); return pNtk->pSupps? (Id < pNtk->nVars? (1 << Id) : pNtk->pSupps[Id - pNtk->nVars]) : 0; }
+
+#define Kit_DsdNtkForEachObj( pNtk, pObj, i )                                      \
+    for ( i = 0; (i < (pNtk)->nNodes) && ((pObj) = (pNtk)->pNodes[i]); i++ )
+#define Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )                              \
+    for ( i = 0; (i < (int)(pObj)->nFans) && ((iLit) = (pObj)->pFans[i], 1); i++ )
+#define Kit_DsdObjForEachFaninReverse( pNtk, pObj, iLit, i )                       \
+    for ( i = (int)(pObj)->nFans - 1; (i >= 0) && ((iLit) = (pObj)->pFans[i], 1); i-- )
+
+#define Kit_PlaForEachCube( pSop, nFanins, pCube )                \
+    for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 )
+#define Kit_PlaCubeForEachVar( pCube, Value, i )                     \
+    for ( i = 0; (pCube[i] != ' ') && (Value = pCube[i]); i++ )           
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define KIT_MIN(a,b)       (((a) < (b))? (a) : (b))
+#define KIT_MAX(a,b)       (((a) > (b))? (a) : (b))
+#define KIT_INFINITY       (100000000)
+
+static inline int          Kit_CubeHasLit( unsigned uCube, int i )                        { return(uCube &  (unsigned)(1<<i)) > 0;  }
+static inline unsigned     Kit_CubeSetLit( unsigned uCube, int i )                        { return uCube |  (unsigned)(1<<i);       }
+static inline unsigned     Kit_CubeXorLit( unsigned uCube, int i )                        { return uCube ^  (unsigned)(1<<i);       }
+static inline unsigned     Kit_CubeRemLit( unsigned uCube, int i )                        { return uCube & ~(unsigned)(1<<i);       }
+
+static inline int          Kit_CubeContains( unsigned uLarge, unsigned uSmall )           { return (uLarge & uSmall) == uSmall;     }
+static inline unsigned     Kit_CubeSharp( unsigned uCube, unsigned uMask )                { return uCube & ~uMask;                  }
+static inline unsigned     Kit_CubeMask( int nVar )                                       { return (~(unsigned)0) >> (32-nVar);     }
+
+static inline int          Kit_CubeIsMarked( unsigned uCube )                             { return Kit_CubeHasLit( uCube, 31 );     }
+static inline unsigned     Kit_CubeMark( unsigned uCube )                                 { return Kit_CubeSetLit( uCube, 31 );     }
+static inline unsigned     Kit_CubeUnmark( unsigned uCube )                               { return Kit_CubeRemLit( uCube, 31 );     }
+
+static inline int          Kit_SopCubeNum( Kit_Sop_t * cSop )                             { return cSop->nCubes;                    }
+static inline unsigned     Kit_SopCube( Kit_Sop_t * cSop, int i )                         { return cSop->pCubes[i];                 }
+static inline void         Kit_SopShrink( Kit_Sop_t * cSop, int nCubesNew )               { cSop->nCubes = nCubesNew;               }
+static inline void         Kit_SopPushCube( Kit_Sop_t * cSop, unsigned uCube )            { cSop->pCubes[cSop->nCubes++] = uCube;   }
+static inline void         Kit_SopWriteCube( Kit_Sop_t * cSop, unsigned uCube, int i )    { cSop->pCubes[i] = uCube;                }
+
+static inline Kit_Edge_t   Kit_EdgeCreate( int Node, int fCompl )                         { Kit_Edge_t eEdge = { fCompl, Node }; return eEdge;  }
+static inline unsigned     Kit_EdgeToInt( Kit_Edge_t eEdge )                              { return (eEdge.Node << 1) | eEdge.fCompl;            }
+static inline Kit_Edge_t   Kit_IntToEdge( unsigned Edge )                                 { return Kit_EdgeCreate( Edge >> 1, Edge & 1 );       }
+//static inline unsigned     Kit_EdgeToInt_( Kit_Edge_t eEdge )                             { return *(unsigned *)&eEdge;                         }
+//static inline Kit_Edge_t   Kit_IntToEdge_( unsigned Edge )                                { return *(Kit_Edge_t *)&Edge;                        }
+static inline unsigned     Kit_EdgeToInt_( Kit_Edge_t m )                                 { union { Kit_Edge_t x; unsigned y; } v; v.x = m; return v.y;  }
+static inline Kit_Edge_t   Kit_IntToEdge_( unsigned m )                                   { union { Kit_Edge_t x; unsigned y; } v; v.y = m; return v.x;  }
+
+static inline int          Kit_GraphIsConst( Kit_Graph_t * pGraph )                       { return pGraph->fConst;                              }
+static inline int          Kit_GraphIsConst0( Kit_Graph_t * pGraph )                      { return pGraph->fConst && pGraph->eRoot.fCompl;      }
+static inline int          Kit_GraphIsConst1( Kit_Graph_t * pGraph )                      { return pGraph->fConst && !pGraph->eRoot.fCompl;     }
+static inline int          Kit_GraphIsComplement( Kit_Graph_t * pGraph )                  { return pGraph->eRoot.fCompl;                        }
+static inline int          Kit_GraphIsVar( Kit_Graph_t * pGraph )                         { return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves; }
+static inline void         Kit_GraphComplement( Kit_Graph_t * pGraph )                    { pGraph->eRoot.fCompl ^= 1;                          }
+static inline void         Kit_GraphSetRoot( Kit_Graph_t * pGraph, Kit_Edge_t eRoot )     { pGraph->eRoot = eRoot;                              }
+static inline int          Kit_GraphLeaveNum( Kit_Graph_t * pGraph )                      { return pGraph->nLeaves;                             }
+static inline int          Kit_GraphNodeNum( Kit_Graph_t * pGraph )                       { return pGraph->nSize - pGraph->nLeaves;             }
+static inline Kit_Node_t * Kit_GraphNode( Kit_Graph_t * pGraph, int i )                   { return pGraph->pNodes + i;                          }
+static inline Kit_Node_t * Kit_GraphNodeLast( Kit_Graph_t * pGraph )                      { return pGraph->pNodes + pGraph->nSize - 1;          }
+static inline int          Kit_GraphNodeInt( Kit_Graph_t * pGraph, Kit_Node_t * pNode )   { return pNode - pGraph->pNodes;                      }
+static inline int          Kit_GraphNodeIsVar( Kit_Graph_t * pGraph, Kit_Node_t * pNode ) { return Kit_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves; }
+static inline Kit_Node_t * Kit_GraphVar( Kit_Graph_t * pGraph )                           { assert( Kit_GraphIsVar( pGraph ) );    return Kit_GraphNode( pGraph, pGraph->eRoot.Node );      }
+static inline int          Kit_GraphVarInt( Kit_Graph_t * pGraph )                        { assert( Kit_GraphIsVar( pGraph ) );    return Kit_GraphNodeInt( pGraph, Kit_GraphVar(pGraph) ); }
+static inline Kit_Node_t * Kit_GraphNodeFanin0( Kit_Graph_t * pGraph, Kit_Node_t * pNode ){ return Kit_GraphNodeIsVar(pGraph, pNode)? NULL : Kit_GraphNode(pGraph, pNode->eEdge0.Node);     }
+static inline Kit_Node_t * Kit_GraphNodeFanin1( Kit_Graph_t * pGraph, Kit_Node_t * pNode ){ return Kit_GraphNodeIsVar(pGraph, pNode)? NULL : Kit_GraphNode(pGraph, pNode->eEdge1.Node);     }
+static inline int          Kit_GraphRootLevel( Kit_Graph_t * pGraph )                     { return Kit_GraphNode(pGraph, pGraph->eRoot.Node)->Level;                                        }
+
+static inline int          Kit_SuppIsMinBase( int Supp )                                  { return (Supp & (Supp+1)) == 0;                      }
+
+static inline int          Kit_BitWordNum( int nBits )    { return nBits/(8*sizeof(unsigned)) + ((nBits%(8*sizeof(unsigned))) > 0); }
+static inline int          Kit_TruthWordNum( int nVars )  { return nVars <= 5 ? 1 : (1 << (nVars - 5));                             }
+static inline unsigned     Kit_BitMask( int nBits )       { assert( nBits <= 32 ); return ~((~(unsigned)0) << nBits);               }
+
+static inline void         Kit_TruthSetBit( unsigned * p, int Bit )   { p[Bit>>5] |= (1<<(Bit & 31));               }
+static inline void         Kit_TruthXorBit( unsigned * p, int Bit )   { p[Bit>>5] ^= (1<<(Bit & 31));               }
+static inline int          Kit_TruthHasBit( unsigned * p, int Bit )   { return (p[Bit>>5] & (1<<(Bit & 31))) > 0;   }
+
+static inline int Kit_WordFindFirstBit( unsigned uWord )
+{
+    int i;
+    for ( i = 0; i < 32; i++ )
+        if ( uWord & (1 << i) )
+            return i;
+    return -1;
+}
+static inline int Kit_WordHasOneBit( unsigned uWord )
+{
+    return (uWord & (uWord - 1)) == 0;
+}
+static inline int Kit_WordCountOnes( unsigned uWord )
+{
+    uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555);
+    uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333);
+    uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F);
+    uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF);
+    return  (uWord & 0x0000FFFF) + (uWord>>16);
+}
+static inline int Kit_TruthCountOnes( unsigned * pIn, int nVars )
+{
+    int w, Counter = 0;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        Counter += Kit_WordCountOnes(pIn[w]);
+    return Counter;
+}
+static inline int Kit_TruthFindFirstBit( unsigned * pIn, int nVars )
+{
+    int w;
+    for ( w = 0; w < Kit_TruthWordNum(nVars); w++ )
+        if ( pIn[w] )
+            return 32*w + Kit_WordFindFirstBit(pIn[w]);
+    return -1;
+}
+static inline int Kit_TruthFindFirstZero( unsigned * pIn, int nVars )
+{
+    int w;
+    for ( w = 0; w < Kit_TruthWordNum(nVars); w++ )
+        if ( ~pIn[w] )
+            return 32*w + Kit_WordFindFirstBit(~pIn[w]);
+    return -1;
+}
+static inline int Kit_TruthIsEqual( unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        if ( pIn0[w] != pIn1[w] )
+            return 0;
+    return 1;
+}
+static inline int Kit_TruthIsEqualWithCare( unsigned * pIn0, unsigned * pIn1, unsigned * pCare, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        if ( (pIn0[w] & pCare[w]) != (pIn1[w] & pCare[w]) )
+            return 0;
+    return 1;
+}
+static inline int Kit_TruthIsOpposite( unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        if ( pIn0[w] != ~pIn1[w] )
+            return 0;
+    return 1;
+}
+static inline int Kit_TruthIsEqualWithPhase( unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+    int w;
+    if ( (pIn0[0] & 1) == (pIn1[0] & 1) )
+    {
+        for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+            if ( pIn0[w] != pIn1[w] )
+                return 0;
+    }
+    else
+    {
+        for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+            if ( pIn0[w] != ~pIn1[w] )
+                return 0;
+    }
+    return 1;
+}
+static inline int Kit_TruthIsConst0( unsigned * pIn, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        if ( pIn[w] )
+            return 0;
+    return 1;
+}
+static inline int Kit_TruthIsConst1( unsigned * pIn, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        if ( pIn[w] != ~(unsigned)0 )
+            return 0;
+    return 1;
+}
+static inline int Kit_TruthIsImply( unsigned * pIn1, unsigned * pIn2, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        if ( pIn1[w] & ~pIn2[w] )
+            return 0;
+    return 1;
+}
+static inline int Kit_TruthIsDisjoint( unsigned * pIn1, unsigned * pIn2, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        if ( pIn1[w] & pIn2[w] )
+            return 0;
+    return 1;
+}
+static inline int Kit_TruthIsDisjoint3( unsigned * pIn1, unsigned * pIn2, unsigned * pIn3, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        if ( pIn1[w] & pIn2[w] & pIn3[w] )
+            return 0;
+    return 1;
+}
+static inline void Kit_TruthCopy( unsigned * pOut, unsigned * pIn, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = pIn[w];
+}
+static inline void Kit_TruthClear( unsigned * pOut, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = 0;
+}
+static inline void Kit_TruthFill( unsigned * pOut, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = ~(unsigned)0;
+}
+static inline void Kit_TruthNot( unsigned * pOut, unsigned * pIn, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = ~pIn[w];
+}
+static inline void Kit_TruthAnd( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = pIn0[w] & pIn1[w];
+}
+static inline void Kit_TruthOr( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = pIn0[w] | pIn1[w];
+}
+static inline void Kit_TruthXor( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = pIn0[w] ^ pIn1[w];
+}
+static inline void Kit_TruthSharp( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = pIn0[w] & ~pIn1[w];
+}
+static inline void Kit_TruthNand( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = ~(pIn0[w] & pIn1[w]);
+}
+static inline void Kit_TruthAndPhase( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars, int fCompl0, int fCompl1 )
+{
+    int w;
+    if ( fCompl0 && fCompl1 )
+    {
+        for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+            pOut[w] = ~(pIn0[w] | pIn1[w]);
+    }
+    else if ( fCompl0 && !fCompl1 )
+    {
+        for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+            pOut[w] = ~pIn0[w] & pIn1[w];
+    }
+    else if ( !fCompl0 && fCompl1 )
+    {
+        for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+            pOut[w] = pIn0[w] & ~pIn1[w];
+    }
+    else // if ( !fCompl0 && !fCompl1 )
+    {
+        for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+            pOut[w] = pIn0[w] & pIn1[w];
+    }
+}
+static inline void Kit_TruthOrPhase( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars, int fCompl0, int fCompl1 )
+{
+    int w;
+    if ( fCompl0 && fCompl1 )
+    {
+        for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+            pOut[w] = ~(pIn0[w] & pIn1[w]);
+    }
+    else if ( fCompl0 && !fCompl1 )
+    {
+        for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+            pOut[w] = ~pIn0[w] | pIn1[w];
+    }
+    else if ( !fCompl0 && fCompl1 )
+    {
+        for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+            pOut[w] = pIn0[w] | ~pIn1[w];
+    }
+    else // if ( !fCompl0 && !fCompl1 )
+    {
+        for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+            pOut[w] = pIn0[w] | pIn1[w];
+    }
+}
+static inline void Kit_TruthMux( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, unsigned * pCtrl, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = (pIn0[w] & ~pCtrl[w]) | (pIn1[w] & pCtrl[w]);
+}
+static inline void Kit_TruthMuxPhase( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, unsigned * pCtrl, int nVars, int fComp0 )
+{
+    int w;
+    if ( fComp0 )
+        for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+            pOut[w] = (~pIn0[w] & ~pCtrl[w]) | (pIn1[w] & pCtrl[w]);
+    else
+        for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- )
+            pOut[w] = (pIn0[w] & ~pCtrl[w]) | (pIn1[w] & pCtrl[w]);
+}
+static inline void Kit_TruthIthVar( unsigned * pTruth, int nVars, int iVar )
+{
+    unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+    int k, nWords = (nVars <= 5 ? 1 : (1 << (nVars - 5)));
+    if ( iVar < 5 )
+    {
+        for ( k = 0; k < nWords; k++ )
+            pTruth[k] = Masks[iVar];
+    }
+    else
+    {
+        for ( k = 0; k < nWords; k++ )
+            if ( k & (1 << (iVar-5)) )
+                pTruth[k] = ~(unsigned)0;
+            else
+                pTruth[k] = 0;
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                           ITERATORS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define Kit_SopForEachCube( cSop, uCube, i )                                      \
+    for ( i = 0; (i < Kit_SopCubeNum(cSop)) && ((uCube) = Kit_SopCube(cSop, i)); i++ )
+#define Kit_CubeForEachLiteral( uCube, Lit, nLits, i )                            \
+    for ( i = 0; (i < (nLits)) && ((Lit) = Kit_CubeHasLit(uCube, i)); i++ )
+
+#define Kit_GraphForEachLeaf( pGraph, pLeaf, i )                                              \
+    for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Kit_GraphNode(pGraph, i)), 1); i++ )
+#define Kit_GraphForEachNode( pGraph, pAnd, i )                                               \
+    for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Kit_GraphNode(pGraph, i)), 1); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== kitBdd.c ==========================================================*/
+extern DdNode *        Kit_SopToBdd( DdManager * dd, Kit_Sop_t * cSop, int nVars );
+extern DdNode *        Kit_GraphToBdd( DdManager * dd, Kit_Graph_t * pGraph );
+extern DdNode *        Kit_TruthToBdd( DdManager * dd, unsigned * pTruth, int nVars, int fMSBonTop );
+/*=== kitCloud.c ==========================================================*/
+extern CloudNode *     Kit_TruthToCloud( CloudManager * dd, unsigned * pTruth, int nVars );
+extern unsigned *      Kit_CloudToTruth( Vec_Int_t * vNodes, int nVars, Vec_Ptr_t * vStore, int fInv );
+extern int             Kit_CreateCloud( CloudManager * dd, CloudNode * pFunc, Vec_Int_t * vNodes );
+extern int             Kit_CreateCloudFromTruth( CloudManager * dd, unsigned * pTruth, int nVars, Vec_Int_t * vNodes );
+extern unsigned *      Kit_TruthCompose( CloudManager * dd, unsigned * pTruth, int nVars, unsigned ** pInputs, int nVarsAll, Vec_Ptr_t * vStore, Vec_Int_t * vNodes );
+extern void            Kit_TruthCofSupports( Vec_Int_t * vBddDir, Vec_Int_t * vBddInv, int nVars, Vec_Int_t * vMemory, unsigned * puSupps );
+/*=== kitDsd.c ==========================================================*/
+extern Kit_DsdMan_t *  Kit_DsdManAlloc( int nVars, int nNodes );
+extern void            Kit_DsdManFree( Kit_DsdMan_t * p );
+extern Kit_DsdNtk_t *  Kit_DsdDeriveNtk( unsigned * pTruth, int nVars, int nLutSize );
+extern unsigned *      Kit_DsdTruthCompute( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk );
+extern void            Kit_DsdTruth( Kit_DsdNtk_t * pNtk, unsigned * pTruthRes );
+extern void            Kit_DsdTruthPartial( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned * pTruthRes, unsigned uSupp );
+extern void            Kit_DsdTruthPartialTwo( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned uSupp, int iVar, unsigned * pTruthCo, unsigned * pTruthDec );
+extern void            Kit_DsdPrint( FILE * pFile, Kit_DsdNtk_t * pNtk );
+extern void            Kit_DsdPrintExpanded( Kit_DsdNtk_t * pNtk );
+extern void            Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars );
+extern void            Kit_DsdPrintFromTruth2( FILE * pFile, unsigned * pTruth, int nVars );
+extern void            Kit_DsdWriteFromTruth( char * pBuffer, unsigned * pTruth, int nVars );
+extern Kit_DsdNtk_t *  Kit_DsdDecompose( unsigned * pTruth, int nVars );
+extern Kit_DsdNtk_t *  Kit_DsdDecomposeExpand( unsigned * pTruth, int nVars );
+extern Kit_DsdNtk_t *  Kit_DsdDecomposeMux( unsigned * pTruth, int nVars, int nDecMux );
+extern void            Kit_DsdVerify( Kit_DsdNtk_t * pNtk, unsigned * pTruth, int nVars );
+extern void            Kit_DsdNtkFree( Kit_DsdNtk_t * pNtk );
+extern int             Kit_DsdNonDsdSizeMax( Kit_DsdNtk_t * pNtk );
+extern Kit_DsdObj_t *  Kit_DsdNonDsdPrimeMax( Kit_DsdNtk_t * pNtk );
+extern unsigned        Kit_DsdNonDsdSupports( Kit_DsdNtk_t * pNtk );
+extern int             Kit_DsdCountAigNodes( Kit_DsdNtk_t * pNtk );
+extern unsigned        Kit_DsdGetSupports( Kit_DsdNtk_t * p );
+extern Kit_DsdNtk_t *  Kit_DsdExpand( Kit_DsdNtk_t * p );
+extern Kit_DsdNtk_t *  Kit_DsdShrink( Kit_DsdNtk_t * p, int pPrios[] );
+extern void            Kit_DsdRotate( Kit_DsdNtk_t * p, int pFreqs[] );
+extern int             Kit_DsdCofactoring( unsigned * pTruth, int nVars, int * pCofVars, int nLimit, int fVerbose );
+/*=== kitFactor.c ==========================================================*/
+extern Kit_Graph_t *   Kit_SopFactor( Vec_Int_t * vCover, int fCompl, int nVars, Vec_Int_t * vMemory );
+/*=== kitGraph.c ==========================================================*/
+extern Kit_Graph_t *   Kit_GraphCreate( int nLeaves );   
+extern Kit_Graph_t *   Kit_GraphCreateConst0();   
+extern Kit_Graph_t *   Kit_GraphCreateConst1();   
+extern Kit_Graph_t *   Kit_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl );   
+extern void            Kit_GraphFree( Kit_Graph_t * pGraph );   
+extern Kit_Node_t *    Kit_GraphAppendNode( Kit_Graph_t * pGraph );   
+extern Kit_Edge_t      Kit_GraphAddNodeAnd( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1 );
+extern Kit_Edge_t      Kit_GraphAddNodeOr( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1 );
+extern Kit_Edge_t      Kit_GraphAddNodeXor( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1, int Type );
+extern Kit_Edge_t      Kit_GraphAddNodeMux( Kit_Graph_t * pGraph, Kit_Edge_t eEdgeC, Kit_Edge_t eEdgeT, Kit_Edge_t eEdgeE, int Type );
+extern unsigned        Kit_GraphToTruth( Kit_Graph_t * pGraph );
+extern Kit_Graph_t *   Kit_TruthToGraph( unsigned * pTruth, int nVars, Vec_Int_t * vMemory );
+extern int             Kit_GraphLeafDepth_rec( Kit_Graph_t * pGraph, Kit_Node_t * pNode, Kit_Node_t * pLeaf );
+/*=== kitHop.c ==========================================================*/
+//extern int             Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash );
+//extern Hop_Obj_t *     Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph );
+//extern Hop_Obj_t *     Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory );
+//extern Hop_Obj_t *     Kit_CoverToHop( Hop_Man_t * pMan, Vec_Int_t * vCover, int nVars, Vec_Int_t * vMemory );
+/*=== kitIsop.c ==========================================================*/
+extern int             Kit_TruthIsop( unsigned * puTruth, int nVars, Vec_Int_t * vMemory, int fTryBoth );
+extern void            Kit_TruthIsopPrint( unsigned * puTruth, int nVars, Vec_Int_t * vMemory, int fTryBoth );
+/*=== kitPla.c ==========================================================*/
+extern int             Kit_PlaIsConst0( char * pSop );
+extern int             Kit_PlaIsConst1( char * pSop );
+extern int             Kit_PlaIsBuf( char * pSop );
+extern int             Kit_PlaIsInv( char * pSop );
+extern int             Kit_PlaGetVarNum( char * pSop );
+extern int             Kit_PlaGetCubeNum( char * pSop );
+extern int             Kit_PlaIsComplement( char * pSop );
+extern void            Kit_PlaComplement( char * pSop );
+extern char *          Kit_PlaStart( void * p, int nCubes, int nVars );
+extern char *          Kit_PlaCreateFromIsop( void * p, int nVars, Vec_Int_t * vCover );
+extern void            Kit_PlaToIsop( char * pSop, Vec_Int_t * vCover );
+extern char *          Kit_PlaStoreSop( void * p, char * pSop );
+extern char *          Kit_PlaFromTruth( void * p, unsigned * pTruth, int nVars, Vec_Int_t * vCover );
+extern char *          Kit_PlaFromTruthNew( unsigned * pTruth, int nVars, Vec_Int_t * vCover, Vec_Str_t * vStr );
+extern ABC_UINT64_T    Kit_PlaToTruth6( char * pSop, int nVars );
+extern void            Kit_PlaToTruth( char * pSop, int nVars, Vec_Ptr_t * vVars, unsigned * pTemp, unsigned * pTruth );
+/*=== kitSop.c ==========================================================*/
+extern void            Kit_SopCreate( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nVars, Vec_Int_t * vMemory );
+extern void            Kit_SopCreateInverse( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nVars, Vec_Int_t * vMemory );
+extern void            Kit_SopDup( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory );
+extern void            Kit_SopDivideByLiteralQuo( Kit_Sop_t * cSop, int iLit );
+extern void            Kit_SopDivideByCube( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory );
+extern void            Kit_SopDivideInternal( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory );
+extern void            Kit_SopMakeCubeFree( Kit_Sop_t * cSop );
+extern int             Kit_SopIsCubeFree( Kit_Sop_t * cSop );
+extern void            Kit_SopCommonCubeCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory );
+extern int             Kit_SopAnyLiteral( Kit_Sop_t * cSop, int nLits );
+extern int             Kit_SopDivisor( Kit_Sop_t * cResult, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory );
+extern void            Kit_SopBestLiteralCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, unsigned uCube, int nLits, Vec_Int_t * vMemory );
+/*=== kitTruth.c ==========================================================*/
+extern void            Kit_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int Start );
+extern void            Kit_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn );
+extern void            Kit_TruthPermute( unsigned * pOut, unsigned * pIn, int nVars, char * pPerm, int fReturnIn );
+extern void            Kit_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn );
+extern int             Kit_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar );
+extern int             Kit_TruthSupportSize( unsigned * pTruth, int nVars );
+extern unsigned        Kit_TruthSupport( unsigned * pTruth, int nVars );
+extern void            Kit_TruthCofactor0( unsigned * pTruth, int nVars, int iVar );
+extern void            Kit_TruthCofactor1( unsigned * pTruth, int nVars, int iVar );
+extern void            Kit_TruthCofactor0New( unsigned * pOut, unsigned * pIn, int nVars, int iVar );
+extern void            Kit_TruthCofactor1New( unsigned * pOut, unsigned * pIn, int nVars, int iVar );
+extern int             Kit_TruthVarIsVacuous( unsigned * pOnset, unsigned * pOffset, int nVars, int iVar );
+extern void            Kit_TruthExist( unsigned * pTruth, int nVars, int iVar );
+extern void            Kit_TruthExistNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar );
+extern void            Kit_TruthExistSet( unsigned * pRes, unsigned * pTruth, int nVars, unsigned uMask );
+extern void            Kit_TruthForall( unsigned * pTruth, int nVars, int iVar );
+extern void            Kit_TruthForallNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar );
+extern void            Kit_TruthForallSet( unsigned * pRes, unsigned * pTruth, int nVars, unsigned uMask );
+extern void            Kit_TruthUniqueNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar );
+extern void            Kit_TruthMuxVar( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar );
+extern void            Kit_TruthMuxVarPhase( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar, int fCompl0 );
+extern void            Kit_TruthChangePhase( unsigned * pTruth, int nVars, int iVar );
+extern int             Kit_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1, unsigned * pCof0, unsigned * pCof1 );
+extern int             Kit_TruthVarsAntiSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1, unsigned * pCof0, unsigned * pCof1 );
+extern int             Kit_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin );
+extern int             Kit_TruthBestCofVar( unsigned * pTruth, int nVars, unsigned * pCof0, unsigned * pCof1 );
+extern void            Kit_TruthCountOnesInCofs( unsigned * pTruth, int nVars, int * pStore );
+extern void            Kit_TruthCountOnesInCofs0( unsigned * pTruth, int nVars, int * pStore );
+extern void            Kit_TruthCountOnesInCofsSlow( unsigned * pTruth, int nVars, int * pStore, unsigned * pAux );
+extern unsigned        Kit_TruthHash( unsigned * pIn, int nWords );
+extern unsigned        Kit_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm );
+extern char *          Kit_TruthDumpToFile( unsigned * pTruth, int nVars, int nFile );
+extern void            Kit_TruthPrintProfile( unsigned * pTruth, int nVars );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/bool/kit/kitAig.c b/abc-build/src/bool/kit/kitAig.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/kitAig.c
@@ -0,0 +1,126 @@
+/**CFile****************************************************************
+
+  FileName    [kitAig.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Computation kit.]
+
+  Synopsis    [Procedures involving AIGs.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 6, 2006.]
+
+  Revision    [$Id: kitAig.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "kit.h"
+#include "aig/aig/aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the decomposition graph into the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Kit_GraphToAigInternal( Aig_Man_t * pMan, Kit_Graph_t * pGraph )
+{
+    Kit_Node_t * pNode = NULL;
+    Aig_Obj_t * pAnd0, * pAnd1;
+    int i;
+    // check for constant function
+    if ( Kit_GraphIsConst(pGraph) )
+        return Aig_NotCond( Aig_ManConst1(pMan), Kit_GraphIsComplement(pGraph) );
+    // check for a literal
+    if ( Kit_GraphIsVar(pGraph) )
+        return Aig_NotCond( (Aig_Obj_t *)Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) );
+    // build the AIG nodes corresponding to the AND gates of the graph
+    Kit_GraphForEachNode( pGraph, pNode, i )
+    {
+        pAnd0 = Aig_NotCond( (Aig_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); 
+        pAnd1 = Aig_NotCond( (Aig_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); 
+        pNode->pFunc = Aig_And( pMan, pAnd0, pAnd1 );
+    }
+    // complement the result if necessary
+    return Aig_NotCond( (Aig_Obj_t *)pNode->pFunc, Kit_GraphIsComplement(pGraph) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes one logic node using its SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Kit_GraphToAig( Aig_Man_t * pMan, Aig_Obj_t ** pFanins, Kit_Graph_t * pGraph )
+{
+    Kit_Node_t * pNode = NULL;
+    int i;
+    // collect the fanins
+    Kit_GraphForEachLeaf( pGraph, pNode, i )
+        pNode->pFunc = pFanins[i];
+    // perform strashing
+    return Kit_GraphToAigInternal( pMan, pGraph );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashed onen logic nodes using its truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Kit_TruthToAig( Aig_Man_t * pMan, Aig_Obj_t ** pFanins, unsigned * pTruth, int nVars, Vec_Int_t * vMemory )
+{
+    Aig_Obj_t * pObj;
+    Kit_Graph_t * pGraph;
+    // transform truth table into the decomposition tree
+    if ( vMemory == NULL )
+    {
+        vMemory = Vec_IntAlloc( 0 );
+        pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory );
+        Vec_IntFree( vMemory );
+    }
+    else
+        pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory );
+    // derive the AIG for the decomposition tree
+    pObj = Kit_GraphToAig( pMan, pFanins, pGraph );
+    Kit_GraphFree( pGraph );
+    return pObj;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/kit/kitBdd.c b/abc-build/src/bool/kit/kitBdd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/kitBdd.c
@@ -0,0 +1,236 @@
+/**CFile****************************************************************
+
+  FileName    [kitBdd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Computation kit.]
+
+  Synopsis    [Procedures involving BDDs.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 6, 2006.]
+
+  Revision    [$Id: kitBdd.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "kit.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the BDD for the given SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Kit_SopToBdd( DdManager * dd, Kit_Sop_t * cSop, int nVars )
+{
+    DdNode * bSum, * bCube, * bTemp, * bVar;
+    unsigned uCube;
+    int Value, i, v;
+    assert( nVars < 16 );
+    // start the cover
+    bSum = Cudd_ReadLogicZero(dd);   Cudd_Ref( bSum );
+   // check the logic function of the node
+    Kit_SopForEachCube( cSop, uCube, i )
+    {
+        bCube = Cudd_ReadOne(dd);   Cudd_Ref( bCube );
+        for ( v = 0; v < nVars; v++ )
+        {
+            Value = ((uCube >> 2*v) & 3);
+            if ( Value == 1 )
+                bVar = Cudd_Not( Cudd_bddIthVar( dd, v ) );
+            else if ( Value == 2 )
+                bVar = Cudd_bddIthVar( dd, v );
+            else
+                continue;
+            bCube  = Cudd_bddAnd( dd, bTemp = bCube, bVar );   Cudd_Ref( bCube );
+            Cudd_RecursiveDeref( dd, bTemp );
+        }
+        bSum = Cudd_bddOr( dd, bTemp = bSum, bCube );   
+        Cudd_Ref( bSum );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bCube );
+    }
+    // complement the result if necessary
+    Cudd_Deref( bSum );
+    return bSum;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts graph to BDD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Kit_GraphToBdd( DdManager * dd, Kit_Graph_t * pGraph )
+{
+    DdNode * bFunc, * bFunc0, * bFunc1;
+    Kit_Node_t * pNode = NULL; // Suppress "might be used uninitialized"
+    int i;
+
+    // sanity checks
+    assert( Kit_GraphLeaveNum(pGraph) >= 0 );
+    assert( Kit_GraphLeaveNum(pGraph) <= pGraph->nSize );
+
+    // check for constant function
+    if ( Kit_GraphIsConst(pGraph) )
+        return Cudd_NotCond( b1, Kit_GraphIsComplement(pGraph) );
+    // check for a literal
+    if ( Kit_GraphIsVar(pGraph) )
+        return Cudd_NotCond( Cudd_bddIthVar(dd, Kit_GraphVarInt(pGraph)), Kit_GraphIsComplement(pGraph) );
+
+    // assign the elementary variables
+    Kit_GraphForEachLeaf( pGraph, pNode, i )
+        pNode->pFunc = Cudd_bddIthVar( dd, i );
+
+    // compute the function for each internal node
+    Kit_GraphForEachNode( pGraph, pNode, i )
+    {
+        bFunc0 = Cudd_NotCond( Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); 
+        bFunc1 = Cudd_NotCond( Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); 
+        pNode->pFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 );   Cudd_Ref( (DdNode *)pNode->pFunc );
+    }
+
+    // deref the intermediate results
+    bFunc = (DdNode *)pNode->pFunc;   Cudd_Ref( bFunc );
+    Kit_GraphForEachNode( pGraph, pNode, i )
+        Cudd_RecursiveDeref( dd, (DdNode *)pNode->pFunc );
+    Cudd_Deref( bFunc );
+
+    // complement the result if necessary
+    return Cudd_NotCond( bFunc, Kit_GraphIsComplement(pGraph) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Kit_TruthToBdd_rec( DdManager * dd, unsigned * pTruth, int iBit, int nVars, int nVarsTotal, int fMSBonTop )
+{
+    DdNode * bF0, * bF1, * bF;
+    int Var;
+    if ( nVars <= 5 )
+    {
+        unsigned uTruth, uMask;
+        uMask = ((~(unsigned)0) >> (32 - (1<<nVars)));
+        uTruth = (pTruth[iBit>>5] >> (iBit&31)) & uMask;
+        if ( uTruth == 0 )
+            return b0;
+        if ( uTruth == uMask )
+            return b1;        
+    }
+    // find the variable to use
+    Var = fMSBonTop? nVarsTotal-nVars : nVars-1;
+    // other special cases can be added
+    bF0 = Kit_TruthToBdd_rec( dd, pTruth, iBit,                nVars-1, nVarsTotal, fMSBonTop );  Cudd_Ref( bF0 );
+    bF1 = Kit_TruthToBdd_rec( dd, pTruth, iBit+(1<<(nVars-1)), nVars-1, nVarsTotal, fMSBonTop );  Cudd_Ref( bF1 );
+    bF  = Cudd_bddIte( dd, dd->vars[Var], bF1, bF0 );                     Cudd_Ref( bF );
+    Cudd_RecursiveDeref( dd, bF0 );
+    Cudd_RecursiveDeref( dd, bF1 );
+    Cudd_Deref( bF );
+    return bF;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute BDD corresponding to the truth table.]
+
+  Description [If truth table has N vars, the BDD depends on N topmost
+  variables of the BDD manager. The most significant variable of the table
+  is encoded by the topmost variable of the manager. BDD construction is 
+  efficient in this case because BDD is constructed one node at a time, 
+  by simply adding BDD nodes on top of existent BDD nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Kit_TruthToBdd( DdManager * dd, unsigned * pTruth, int nVars, int fMSBonTop )
+{
+    return Kit_TruthToBdd_rec( dd, pTruth, 0, nVars, nVars, fMSBonTop );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies that the factoring is correct.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_SopFactorVerify( Vec_Int_t * vCover, Kit_Graph_t * pFForm, int nVars )
+{
+    static DdManager * dd = NULL;
+    Kit_Sop_t Sop, * cSop = &Sop;
+    DdNode * bFunc1, * bFunc2;
+    Vec_Int_t * vMemory;
+    int RetValue;
+    // get the manager
+    if ( dd == NULL )
+        dd = Cudd_Init( 16, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    // derive SOP
+    vMemory = Vec_IntAlloc( Vec_IntSize(vCover) );
+    Kit_SopCreate( cSop, vCover, nVars, vMemory );
+    // get the functions
+    bFunc1 = Kit_SopToBdd( dd, cSop, nVars );      Cudd_Ref( bFunc1 );
+    bFunc2 = Kit_GraphToBdd( dd, pFForm );         Cudd_Ref( bFunc2 );
+//Extra_bddPrint( dd, bFunc1 ); printf("\n");
+//Extra_bddPrint( dd, bFunc2 ); printf("\n");
+    RetValue = (bFunc1 == bFunc2);
+    if ( bFunc1 != bFunc2 )
+    {
+        int s;
+        Extra_bddPrint( dd, bFunc1 ); printf("\n");
+        Extra_bddPrint( dd, bFunc2 ); printf("\n");
+        s  = 0;
+    }
+    Cudd_RecursiveDeref( dd, bFunc1 );
+    Cudd_RecursiveDeref( dd, bFunc2 );
+    Vec_IntFree( vMemory );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/kit/kitCloud.c b/abc-build/src/bool/kit/kitCloud.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/kitCloud.c
@@ -0,0 +1,378 @@
+/**CFile****************************************************************
+
+  FileName    [kitCloud.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Computation kit.]
+
+  Synopsis    [Procedures using BDD package CLOUD.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 6, 2006.]
+
+  Revision    [$Id: kitCloud.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// internal representation of the function to be decomposed
+typedef struct Kit_Mux_t_ Kit_Mux_t;
+struct Kit_Mux_t_
+{
+    unsigned      v  :  5;          // variable 
+    unsigned      t  : 12;          // then edge
+    unsigned      e  : 12;          // else edge
+    unsigned      c  :  1;          // complemented attr of else edge
+    unsigned      i  :  1;          // complemented attr of top node
+};
+
+static inline int        Kit_Mux2Int( Kit_Mux_t m )  { union { Kit_Mux_t x; int y; } v; v.x = m; return v.y;  }
+static inline Kit_Mux_t  Kit_Int2Mux( int m )        { union { Kit_Mux_t x; int y; } v; v.y = m; return v.x;  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derive BDD from the truth table for 5 variable functions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+CloudNode * Kit_TruthToCloud5_rec( CloudManager * dd, unsigned uTruth, int nVars, int nVarsAll )
+{
+    static unsigned uVars[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+    CloudNode * pCof0, * pCof1;
+    unsigned uCof0, uCof1;
+    assert( nVars <= 5 );
+    if ( uTruth == 0 )
+        return dd->zero;
+    if ( uTruth == ~0 )
+        return dd->one;
+    if ( nVars == 1 )
+    {
+        if ( uTruth == uVars[0] )
+            return dd->vars[nVarsAll-1];
+        if ( uTruth == ~uVars[0] )
+            return Cloud_Not(dd->vars[nVarsAll-1]);
+        assert( 0 );
+    }
+//    Count++;
+    assert( nVars > 1 );
+    uCof0 = uTruth & ~uVars[nVars-1];
+    uCof1 = uTruth &  uVars[nVars-1];
+    uCof0 |= uCof0 << (1<<(nVars-1));
+    uCof1 |= uCof1 >> (1<<(nVars-1));
+    if ( uCof0 == uCof1 )
+        return Kit_TruthToCloud5_rec( dd, uCof0, nVars - 1, nVarsAll );
+    if ( uCof0 == ~uCof1 )
+    {
+        pCof0 = Kit_TruthToCloud5_rec( dd, uCof0, nVars - 1, nVarsAll );
+        pCof1 = Cloud_Not( pCof0 );
+    }
+    else
+    {
+        pCof0 = Kit_TruthToCloud5_rec( dd, uCof0, nVars - 1, nVarsAll );
+        pCof1 = Kit_TruthToCloud5_rec( dd, uCof1, nVars - 1, nVarsAll );
+    }
+    return Cloud_MakeNode( dd, nVarsAll - nVars, pCof1, pCof0 );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compute BDD for the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+CloudNode * Kit_TruthToCloud_rec( CloudManager * dd, unsigned * pTruth, int nVars, int nVarsAll )
+{
+    CloudNode * pCof0, * pCof1;
+    unsigned * pTruth0, * pTruth1;
+    if ( nVars <= 5 )
+        return Kit_TruthToCloud5_rec( dd, pTruth[0], nVars, nVarsAll );
+    if ( Kit_TruthIsConst0(pTruth, nVars) )
+        return dd->zero;
+    if ( Kit_TruthIsConst1(pTruth, nVars) )
+        return dd->one;
+//    Count++;
+    pTruth0 = pTruth;
+    pTruth1 = pTruth + Kit_TruthWordNum(nVars-1);
+    if ( Kit_TruthIsEqual( pTruth0, pTruth1, nVars - 1 ) )
+        return Kit_TruthToCloud_rec( dd, pTruth0, nVars - 1, nVarsAll );
+    if ( Kit_TruthIsOpposite( pTruth0, pTruth1, nVars - 1 ) )
+    {
+        pCof0 = Kit_TruthToCloud_rec( dd, pTruth0, nVars - 1, nVarsAll );
+        pCof1 = Cloud_Not( pCof0 );
+    }
+    else
+    {
+        pCof0 = Kit_TruthToCloud_rec( dd, pTruth0, nVars - 1, nVarsAll );
+        pCof1 = Kit_TruthToCloud_rec( dd, pTruth1, nVars - 1, nVarsAll );
+    }
+    return Cloud_MakeNode( dd, nVarsAll - nVars, pCof1, pCof0 );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compute BDD for the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+CloudNode * Kit_TruthToCloud( CloudManager * dd, unsigned * pTruth, int nVars )
+{
+    CloudNode * pRes;
+    pRes = Kit_TruthToCloud_rec( dd, pTruth, nVars, nVars );
+//    printf( "%d/%d  ", Count, Cloud_DagSize(dd, pRes) );
+    return pRes;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Transforms the array of BDDs into the integer array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Kit_CreateCloud( CloudManager * dd, CloudNode * pFunc, Vec_Int_t * vNodes )
+{
+    Kit_Mux_t Mux;
+    int nNodes, i;
+    // collect BDD nodes
+    nNodes = Cloud_DagCollect( dd, pFunc );
+    if ( nNodes >= (1<<12) ) // because in Kit_Mux_t edge is 12 bit
+        return 0;
+    assert( nNodes == Cloud_DagSize( dd, pFunc ) );
+    assert( nNodes < dd->nNodesLimit );
+    Vec_IntClear( vNodes );
+    Vec_IntPush( vNodes, 0 ); // const1 node
+    dd->ppNodes[0]->s = 0;
+    for ( i = 1; i < nNodes; i++ )
+    {
+        dd->ppNodes[i]->s = i;
+        Mux.v = dd->ppNodes[i]->v;
+        Mux.t = dd->ppNodes[i]->t->s;
+        Mux.e = Cloud_Regular(dd->ppNodes[i]->e)->s;
+        Mux.c = Cloud_IsComplement(dd->ppNodes[i]->e); 
+        Mux.i = (i == nNodes - 1)? Cloud_IsComplement(pFunc) : 0;
+        // put the MUX into the array
+        Vec_IntPush( vNodes, Kit_Mux2Int(Mux) );
+    }
+    assert( Vec_IntSize(vNodes) == nNodes );
+    // reset signatures
+    for ( i = 0; i < nNodes; i++ )
+        dd->ppNodes[i]->s = dd->nSignCur;
+    return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Transforms the array of BDDs into the integer array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Kit_CreateCloudFromTruth( CloudManager * dd, unsigned * pTruth, int nVars, Vec_Int_t * vNodes )
+{
+    CloudNode * pFunc;
+    Cloud_Restart( dd );
+    pFunc = Kit_TruthToCloud( dd, pTruth, nVars );
+    Vec_IntClear( vNodes );
+    return Kit_CreateCloud( dd, pFunc, vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes composition of truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Kit_CloudToTruth( Vec_Int_t * vNodes, int nVars, Vec_Ptr_t * vStore, int fInv )
+{
+    unsigned * pThis, * pFan0, * pFan1;
+    Kit_Mux_t Mux;
+    int i, Entry;
+    assert( Vec_IntSize(vNodes) <= Vec_PtrSize(vStore) );
+    pThis = (unsigned *)Vec_PtrEntry( vStore, 0 );
+    Kit_TruthFill( pThis, nVars );
+    Vec_IntForEachEntryStart( vNodes, Entry, i, 1 )
+    {
+        Mux = Kit_Int2Mux(Entry);
+        assert( (int)Mux.e < i && (int)Mux.t < i && (int)Mux.v < nVars );          
+        pFan0 = (unsigned *)Vec_PtrEntry( vStore, Mux.e );
+        pFan1 = (unsigned *)Vec_PtrEntry( vStore, Mux.t );
+        pThis = (unsigned *)Vec_PtrEntry( vStore, i );
+        Kit_TruthMuxVarPhase( pThis, pFan0, pFan1, nVars, fInv? Mux.v : nVars-1-Mux.v, Mux.c );
+    } 
+    // complement the result
+    if ( Mux.i )
+        Kit_TruthNot( pThis, pThis, nVars );
+    return pThis;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes composition of truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Kit_TruthCompose( CloudManager * dd, unsigned * pTruth, int nVars, 
+    unsigned ** pInputs, int nVarsAll, Vec_Ptr_t * vStore, Vec_Int_t * vNodes )
+{
+    CloudNode * pFunc;
+    unsigned * pThis, * pFan0, * pFan1;
+    Kit_Mux_t Mux;
+    int i, Entry, RetValue;
+    // derive BDD from truth table
+    Cloud_Restart( dd );
+    pFunc = Kit_TruthToCloud( dd, pTruth, nVars );
+    // convert it into nodes
+    RetValue = Kit_CreateCloud( dd, pFunc, vNodes );
+    if ( RetValue == 0 )
+        printf( "Kit_TruthCompose(): Internal failure!!!\n" );
+    // verify the result
+//    pFan0 = Kit_CloudToTruth( vNodes, nVars, vStore, 0 );
+//    if ( !Kit_TruthIsEqual( pTruth, pFan0, nVars ) )
+//        printf( "Failed!\n" );
+    // compute truth table from the BDD
+    assert( Vec_IntSize(vNodes) <= Vec_PtrSize(vStore) );
+    pThis = (unsigned *)Vec_PtrEntry( vStore, 0 );
+    Kit_TruthFill( pThis, nVarsAll );
+    Vec_IntForEachEntryStart( vNodes, Entry, i, 1 )
+    {
+        Mux = Kit_Int2Mux(Entry);
+        pFan0 = (unsigned *)Vec_PtrEntry( vStore, Mux.e );
+        pFan1 = (unsigned *)Vec_PtrEntry( vStore, Mux.t );
+        pThis = (unsigned *)Vec_PtrEntry( vStore, i );
+        Kit_TruthMuxPhase( pThis, pFan0, pFan1, pInputs[nVars-1-Mux.v], nVarsAll, Mux.c );
+    }
+    // complement the result
+    if ( Mux.i )
+        Kit_TruthNot( pThis, pThis, nVarsAll );
+    return pThis;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compute BDD for the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Kit_TruthCofSupports( Vec_Int_t * vBddDir, Vec_Int_t * vBddInv, int nVars, Vec_Int_t * vMemory, unsigned * puSupps )
+{
+    Kit_Mux_t Mux;
+    unsigned * puSuppAll;
+    unsigned * pThis = NULL; // Suppress "might be used uninitialized"
+    unsigned * pFan0, * pFan1;
+    int i, v, Var, Entry, nSupps;
+    nSupps = 2 * nVars;
+
+    // extend storage
+    if ( Vec_IntSize( vMemory ) < nSupps * Vec_IntSize(vBddDir) )
+        Vec_IntGrow( vMemory, nSupps * Vec_IntSize(vBddDir) );
+    puSuppAll = (unsigned *)Vec_IntArray( vMemory );
+    // clear storage for the const node
+    memset( puSuppAll, 0, sizeof(unsigned) * nSupps );
+    // compute supports from nodes
+    Vec_IntForEachEntryStart( vBddDir, Entry, i, 1 )
+    {
+        Mux = Kit_Int2Mux(Entry);
+        Var = nVars - 1 - Mux.v;
+        pFan0 = puSuppAll + nSupps * Mux.e;
+        pFan1 = puSuppAll + nSupps * Mux.t;
+        pThis = puSuppAll + nSupps * i;
+        for ( v = 0; v < nSupps; v++ )
+            pThis[v] = pFan0[v] | pFan1[v] | (1<<Var);
+        assert( pFan0[2*Var + 0] == pFan0[2*Var + 1] );
+        assert( pFan1[2*Var + 0] == pFan1[2*Var + 1] );
+        pThis[2*Var + 0] = pFan0[2*Var + 0];// | pFan0[2*Var + 1];
+        pThis[2*Var + 1] = pFan1[2*Var + 0];// | pFan1[2*Var + 1];
+    }
+    // copy the result
+    memcpy( puSupps, pThis, sizeof(unsigned) * nSupps );
+    // compute the inverse
+
+    // extend storage
+    if ( Vec_IntSize( vMemory ) < nSupps * Vec_IntSize(vBddInv) )
+        Vec_IntGrow( vMemory, nSupps * Vec_IntSize(vBddInv) );
+    puSuppAll = (unsigned *)Vec_IntArray( vMemory );
+    // clear storage for the const node
+    memset( puSuppAll, 0, sizeof(unsigned) * nSupps );
+    // compute supports from nodes
+    Vec_IntForEachEntryStart( vBddInv, Entry, i, 1 )
+    {
+        Mux = Kit_Int2Mux(Entry);
+//        Var = nVars - 1 - Mux.v;
+        Var = Mux.v;
+        pFan0 = puSuppAll + nSupps * Mux.e;
+        pFan1 = puSuppAll + nSupps * Mux.t;
+        pThis = puSuppAll + nSupps * i;
+        for ( v = 0; v < nSupps; v++ )
+            pThis[v] = pFan0[v] | pFan1[v] | (1<<Var);
+        assert( pFan0[2*Var + 0] == pFan0[2*Var + 1] );
+        assert( pFan1[2*Var + 0] == pFan1[2*Var + 1] );
+        pThis[2*Var + 0] = pFan0[2*Var + 0];// | pFan0[2*Var + 1];
+        pThis[2*Var + 1] = pFan1[2*Var + 0];// | pFan1[2*Var + 1];
+    }
+
+    // merge supports
+    for ( Var = 0; Var < nSupps; Var++ )
+        puSupps[Var] = (puSupps[Var] & Kit_BitMask(Var/2)) | (pThis[Var] & ~Kit_BitMask(Var/2));
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/kit/kitDec.c b/abc-build/src/bool/kit/kitDec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/kitDec.c
@@ -0,0 +1,343 @@
+/**CFile****************************************************************
+
+  FileName    [kitDec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Computation kit.]
+
+  Synopsis    [Decomposition manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 18, 2009.]
+
+  Revision    [$Id: kitDec.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// decomposition manager
+typedef struct Kit_ManDec_t_ Kit_ManDec_t;
+struct Kit_ManDec_t_ 
+{
+    int             nVarsMax;     // the max number of variables
+    int             nWordsMax;    // the max number of words
+    Vec_Ptr_t *     vTruthVars;   // elementary truth tables
+    Vec_Ptr_t *     vTruthNodes;  // internal truth tables
+    // current problem
+    int             nVarsIn;      // the current number of variables
+    Vec_Int_t *     vLutsIn;      // LUT truth tables
+    Vec_Int_t *     vSuppIn;      // LUT supports
+    char            ATimeIn[64];  // variable arrival times
+    // extracted information
+    unsigned *      pTruthIn;     // computed truth table
+    unsigned *      pTruthOut;    // computed truth table
+    int             nVarsOut;     // the current number of variables
+    int             nWordsOut;    // the current number of words
+    char            Order[32];    // new vars into old vars after supp minimization
+    // computed information
+    Vec_Int_t *     vLutsOut;     // problem decomposition
+    Vec_Int_t *     vSuppOut;     // problem decomposition
+    char            ATimeOut[64]; // variable arrival times
+};
+
+static inline int   Kit_DecOuputArrival( int nVars, Vec_Int_t * vLuts, char ATimes[] ) { return ATimes[nVars + Vec_IntSize(vLuts) - 1]; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts Decmetry manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_ManDec_t * Kit_ManDecStart( int nVarsMax )
+{
+    Kit_ManDec_t * p;
+    assert( nVarsMax <= 20 );
+    p = ABC_CALLOC( Kit_ManDec_t, 1 );
+    p->nVarsMax   = nVarsMax;
+    p->nWordsMax  = Kit_TruthWordNum( p->nVarsMax );
+    p->vTruthVars = Vec_PtrAllocTruthTables( p->nVarsMax );
+    p->vTruthNodes = Vec_PtrAllocSimInfo( 64, p->nWordsMax );
+    p->vLutsIn    = Vec_IntAlloc( 50 );
+    p->vSuppIn    = Vec_IntAlloc( 50 );
+    p->vLutsOut   = Vec_IntAlloc( 50 );
+    p->vSuppOut   = Vec_IntAlloc( 50 );
+    p->pTruthIn   = ABC_ALLOC( unsigned, p->nWordsMax );
+    p->pTruthOut  = ABC_ALLOC( unsigned, p->nWordsMax );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops Decmetry manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_ManDecStop( Kit_ManDec_t * p )
+{
+    ABC_FREE( p->pTruthIn );
+    ABC_FREE( p->pTruthOut );
+    Vec_IntFreeP( &p->vLutsIn );
+    Vec_IntFreeP( &p->vSuppIn );
+    Vec_IntFreeP( &p->vLutsOut );
+    Vec_IntFreeP( &p->vSuppOut );
+    Vec_PtrFreeP( &p->vTruthVars );
+    Vec_PtrFreeP( &p->vTruthNodes );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Deriving timing information for the decomposed structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DecComputeOuputArrival( int nVars, Vec_Int_t * vSupps, int LutSize, char ATimesIn[], char ATimesOut[] )
+{
+    int i, v, iVar, nLuts, Delay;
+    nLuts = Vec_IntSize(vSupps) / LutSize;
+    assert( nLuts > 0 );
+    assert( Vec_IntSize(vSupps) % LutSize == 0 );
+    for ( v = 0; v < nVars; v++ )
+        ATimesOut[v] = ATimesIn[v];
+    for ( v = 0; v < nLuts; v++ )
+    {
+        Delay = 0;
+        for ( i = 0; i < LutSize; i++ )
+        {
+            iVar = Vec_IntEntry( vSupps, v * LutSize + i );
+            assert( iVar < nVars + v );
+            Delay = Abc_MaxInt( Delay, ATimesOut[iVar] );
+        }
+        ATimesOut[nVars + v] = Delay + 1;
+    }
+    return ATimesOut[nVars + nLuts - 1];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DecComputeTruthOne( int LutSize, unsigned * pTruthLut, int nVars, unsigned * pTruths[], unsigned * pTemp, unsigned * pRes )
+{
+    int i, v;
+    Kit_TruthClear( pRes, nVars );
+    for ( i = 0; i < (1<<LutSize); i++ )
+    {
+        if ( !Kit_TruthHasBit( pTruthLut, i ) )
+            continue;
+        Kit_TruthFill( pTemp, nVars );
+        for ( v = 0; v < LutSize; v++ )
+            if ( i & (1<<v) )
+                Kit_TruthAnd( pTemp, pTemp, pTruths[v], nVars );
+            else
+                Kit_TruthSharp( pTemp, pTemp, pTruths[v], nVars );
+        Kit_TruthOr( pRes, pRes, pTemp, nVars );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DecComputeTruth( Kit_ManDec_t * p, int nVars, Vec_Int_t * vSupps, int LutSize, Vec_Int_t * vLuts, unsigned * pRes )
+{
+    unsigned * pResult, * pTruthLuts, * pTruths[17];
+    int nTruthLutWords, i, v, iVar, nLuts;
+    nLuts = Vec_IntSize(vSupps) / LutSize;
+    pTruthLuts = (unsigned *)Vec_IntArray( vLuts );
+    nTruthLutWords = Kit_TruthWordNum( LutSize );
+    assert( nLuts > 0 );
+    assert( Vec_IntSize(vSupps) % LutSize == 0 );
+    assert( nLuts * nTruthLutWords == Vec_IntSize(vLuts) );
+    for ( v = 0; v < nLuts; v++ )
+    {
+        for ( i = 0; i < LutSize; i++ )
+        {
+            iVar = Vec_IntEntry( vSupps, v * LutSize + i );
+            assert( iVar < nVars + v );
+            pTruths[i] = (iVar < nVars)? (unsigned *)Vec_PtrEntry(p->vTruthVars, iVar) : (unsigned *)Vec_PtrEntry(p->vTruthNodes, iVar-nVars);
+        }
+        pResult = (v == nLuts - 1) ? pRes : (unsigned *)Vec_PtrEntry(p->vTruthNodes, v);
+        Kit_DecComputeTruthOne( LutSize, pTruthLuts, nVars, pTruths, (unsigned *)Vec_PtrEntry(p->vTruthNodes, v+1), pResult );
+        pTruthLuts += nTruthLutWords;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DecComputePattern( int nVars, unsigned * pTruth, int LutSize, int Pattern[] )
+{
+    int nCofs = (1 << LutSize);
+    int i, k, nMyu = 0;
+    assert( LutSize <= 6 );
+    assert( LutSize < nVars );
+    if ( nVars - LutSize <= 5 )
+    {
+        unsigned uCofs[64];
+        int nBits = (1 << (nVars - LutSize));
+        for ( i = 0; i < nCofs; i++ )
+            uCofs[i] = (pTruth[(i*nBits)/32] >> ((i*nBits)%32)) & ((1<<nBits)-1);
+        for ( i = 0; i < nCofs; i++ )
+        {
+            for ( k = 0; k < nMyu; k++ )
+                if ( uCofs[i] == uCofs[k] )
+                {
+                    Pattern[i] = k;
+                    break;
+                }
+            if ( k == i )
+                Pattern[nMyu++] = i;
+        }
+    }
+    else
+    {
+        unsigned * puCofs[64];
+        int nWords = (1 << (nVars - LutSize - 5));
+        for ( i = 0; i < nCofs; i++ )
+            puCofs[i] = pTruth + nWords;
+        for ( i = 0; i < nCofs; i++ )
+        {
+            for ( k = 0; k < nMyu; k++ )
+                if ( Kit_TruthIsEqual( puCofs[i], puCofs[k], nVars - LutSize - 5 ) )
+                {
+                    Pattern[i] = k;
+                    break;
+                }
+            if ( k == i )
+                Pattern[nMyu++] = i;
+        }
+    }
+    return nMyu;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of shared variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DecComputeShared_rec( int Pattern[], int Vars[], int nVars, int Shared[], int iVarTry )
+{
+    int Pat0[32], Pat1[32], Shared0[5], Shared1[5], VarsNext[5];
+    int v, u, iVarsNext, iPat0, iPat1, m, nMints = (1 << nVars);
+    int nShared0, nShared1, nShared = 0;
+    for ( v = iVarTry; v < nVars; v++ )
+    {
+        iVarsNext = 0;
+        for ( u = 0; u < nVars; u++ )
+            if ( u == v )
+                VarsNext[iVarsNext++] = Vars[u];
+        iPat0 = iPat1 = 0;
+        for ( m = 0; m < nMints; m++ )
+            if ( m & (1 << v) )
+                Pat1[iPat1++] = m;
+            else
+                Pat0[iPat0++] = m;
+        assert( iPat0 == nMints / 2 );
+        assert( iPat1 == nMints / 2 );
+        nShared0 = Kit_DecComputeShared_rec( Pat0, VarsNext, nVars-1, Shared0, v + 1 );
+        if ( nShared0 == 0 )
+            continue;
+        nShared1 = Kit_DecComputeShared_rec( Pat1, VarsNext, nVars-1, Shared1, v + 1 );
+        if ( nShared1 == 0 )
+            continue;
+        Shared[nShared++] = v;
+        for ( u = 0; u < nShared0; u++ )
+        for ( m = 0; m < nShared1; m++ )
+            if ( Shared0[u] >= 0 && Shared1[m] >= 0 && Shared0[u] == Shared1[m] )
+            {
+                Shared[nShared++] = Shared0[u];
+                Shared0[u] = Shared1[m] = -1;
+            }
+        return nShared;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of shared variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DecComputeShared( int Pattern[], int LutSize, int Shared[] )
+{
+    int i, Vars[6];
+    assert( LutSize <= 6 );
+    for ( i = 0; i < LutSize; i++ )
+        Vars[i] = i;
+    return Kit_DecComputeShared_rec( Pattern, Vars, LutSize, Shared, 0 );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/kit/kitDsd.c b/abc-build/src/bool/kit/kitDsd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/kitDsd.c
@@ -0,0 +1,3284 @@
+/**CFile****************************************************************
+
+  FileName    [kitDsd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Computation kit.]
+
+  Synopsis    [Performs disjoint-support decomposition based on truth tables.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 6, 2006.]
+
+  Revision    [$Id: kitDsd.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the DSD manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_DsdMan_t * Kit_DsdManAlloc( int nVars, int nNodes )
+{
+    Kit_DsdMan_t * p;
+    p = ABC_ALLOC( Kit_DsdMan_t, 1 );
+    memset( p, 0, sizeof(Kit_DsdMan_t) );
+    p->nVars    = nVars;
+    p->nWords   = Kit_TruthWordNum( p->nVars );
+    p->vTtElems = Vec_PtrAllocTruthTables( p->nVars );
+    p->vTtNodes = Vec_PtrAllocSimInfo( nNodes, p->nWords );
+    p->dd       = Cloud_Init( 16, 14 );
+    p->vTtBdds  = Vec_PtrAllocSimInfo( (1<<12), p->nWords );
+    p->vNodes   = Vec_IntAlloc( 512 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the DSD manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdManFree( Kit_DsdMan_t * p )
+{
+    Cloud_Quit( p->dd );
+    Vec_IntFree( p->vNodes );
+    Vec_PtrFree( p->vTtBdds );
+    Vec_PtrFree( p->vTtElems );
+    Vec_PtrFree( p->vTtNodes );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the DSD node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_DsdObj_t * Kit_DsdObjAlloc( Kit_DsdNtk_t * pNtk, Kit_Dsd_t Type, int nFans )
+{
+    Kit_DsdObj_t * pObj;
+    int nSize = sizeof(Kit_DsdObj_t) + sizeof(unsigned) * (Kit_DsdObjOffset(nFans) + (Type == KIT_DSD_PRIME) * Kit_TruthWordNum(nFans));
+    pObj = (Kit_DsdObj_t *)ABC_ALLOC( char, nSize );
+    memset( pObj, 0, nSize );
+    pObj->Id = pNtk->nVars + pNtk->nNodes;
+    pObj->Type = Type;
+    pObj->nFans = nFans;
+    pObj->Offset = Kit_DsdObjOffset( nFans );
+    // add the object
+    if ( pNtk->nNodes == pNtk->nNodesAlloc )
+    {
+        pNtk->nNodesAlloc *= 2;
+        pNtk->pNodes = ABC_REALLOC( Kit_DsdObj_t *, pNtk->pNodes, pNtk->nNodesAlloc ); 
+    }
+    assert( pNtk->nNodes < pNtk->nNodesAlloc );
+    pNtk->pNodes[pNtk->nNodes++] = pObj;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the DSD node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdObjFree( Kit_DsdNtk_t * p, Kit_DsdObj_t * pObj )
+{
+    ABC_FREE( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the DSD network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_DsdNtk_t * Kit_DsdNtkAlloc( int nVars )
+{
+    Kit_DsdNtk_t * pNtk;
+    pNtk = ABC_ALLOC( Kit_DsdNtk_t, 1 );
+    memset( pNtk, 0, sizeof(Kit_DsdNtk_t) );
+    pNtk->pNodes = ABC_ALLOC( Kit_DsdObj_t *, nVars+1 );
+    pNtk->nVars = nVars;
+    pNtk->nNodesAlloc = nVars+1;
+    pNtk->pMem = ABC_ALLOC( unsigned, 6 * Kit_TruthWordNum(nVars) );
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocate the DSD network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdNtkFree( Kit_DsdNtk_t * pNtk )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned i;
+    Kit_DsdNtkForEachObj( pNtk, pObj, i )
+        ABC_FREE( pObj );
+    ABC_FREE( pNtk->pSupps );
+    ABC_FREE( pNtk->pNodes );
+    ABC_FREE( pNtk->pMem );
+    ABC_FREE( pNtk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the hex unsigned into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdPrintHex( FILE * pFile, unsigned * pTruth, int nFans )
+{
+    int nDigits, Digit, k;
+    nDigits = (1 << nFans) / 4;
+    for ( k = nDigits - 1; k >= 0; k-- )
+    {
+        Digit = ((pTruth[k/8] >> ((k%8) * 4)) & 15);
+        if ( Digit < 10 )
+            fprintf( pFile, "%d", Digit );
+        else
+            fprintf( pFile, "%c", 'A' + Digit-10 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the hex unsigned into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Kit_DsdWriteHex( char * pBuff, unsigned * pTruth, int nFans )
+{
+    int nDigits, Digit, k;
+    nDigits = (1 << nFans) / 4;
+    for ( k = nDigits - 1; k >= 0; k-- )
+    {
+        Digit = ((pTruth[k/8] >> ((k%8) * 4)) & 15);
+        if ( Digit < 10 )
+            *pBuff++ = '0' + Digit;
+        else
+            *pBuff++ = 'A' + Digit-10;
+    }
+    return pBuff;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively print the DSD formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdPrint2_rec( FILE * pFile, Kit_DsdNtk_t * pNtk, int Id )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned iLit, i;
+    char Symbol;
+
+    pObj = Kit_DsdNtkObj( pNtk, Id );
+    if ( pObj == NULL )
+    {
+        assert( Id < pNtk->nVars );
+        fprintf( pFile, "%c", 'a' + Id );
+        return;
+    }
+
+    if ( pObj->Type == KIT_DSD_CONST1 )
+    {
+        assert( pObj->nFans == 0 );
+        fprintf( pFile, "Const1" );
+        return;
+    }
+
+    if ( pObj->Type == KIT_DSD_VAR )
+        assert( pObj->nFans == 1 );
+
+    if ( pObj->Type == KIT_DSD_AND )
+        Symbol = '*';
+    else if ( pObj->Type == KIT_DSD_XOR )
+        Symbol = '+';
+    else 
+        Symbol = ',';
+
+    if ( pObj->Type == KIT_DSD_PRIME )
+        fprintf( pFile, "[" );
+    else
+        fprintf( pFile, "(" );
+    Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+    {
+        if ( Abc_LitIsCompl(iLit) ) 
+            fprintf( pFile, "!" );
+        Kit_DsdPrint2_rec( pFile, pNtk, Abc_Lit2Var(iLit) );
+        if ( i < pObj->nFans - 1 )
+            fprintf( pFile, "%c", Symbol );
+    }
+    if ( pObj->Type == KIT_DSD_PRIME )
+        fprintf( pFile, "]" );
+    else
+        fprintf( pFile, ")" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print the DSD formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdPrint2( FILE * pFile, Kit_DsdNtk_t * pNtk )
+{
+//    fprintf( pFile, "F = " );
+    if ( Abc_LitIsCompl(pNtk->Root) )
+        fprintf( pFile, "!" );
+    Kit_DsdPrint2_rec( pFile, pNtk, Abc_Lit2Var(pNtk->Root) );
+//    fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively print the DSD formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdPrint_rec( FILE * pFile, Kit_DsdNtk_t * pNtk, int Id )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned iLit, i;
+    char Symbol;
+
+    pObj = Kit_DsdNtkObj( pNtk, Id );
+    if ( pObj == NULL )
+    {
+        assert( Id < pNtk->nVars );
+        fprintf( pFile, "%c", 'a' + Id );
+        return;
+    }
+
+    if ( pObj->Type == KIT_DSD_CONST1 )
+    {
+        assert( pObj->nFans == 0 );
+        fprintf( pFile, "Const1" );
+        return;
+    }
+
+    if ( pObj->Type == KIT_DSD_VAR )
+        assert( pObj->nFans == 1 );
+
+    if ( pObj->Type == KIT_DSD_AND )
+        Symbol = '*';
+    else if ( pObj->Type == KIT_DSD_XOR )
+        Symbol = '+';
+    else 
+        Symbol = ',';
+
+    if ( pObj->Type == KIT_DSD_PRIME )
+        Kit_DsdPrintHex( pFile, Kit_DsdObjTruth(pObj), pObj->nFans );
+
+    fprintf( pFile, "(" );
+    Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+    {
+        if ( Abc_LitIsCompl(iLit) ) 
+            fprintf( pFile, "!" );
+        Kit_DsdPrint_rec( pFile, pNtk, Abc_Lit2Var(iLit) );
+        if ( i < pObj->nFans - 1 )
+            fprintf( pFile, "%c", Symbol );
+    }
+    fprintf( pFile, ")" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print the DSD formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdPrint( FILE * pFile, Kit_DsdNtk_t * pNtk )
+{
+    fprintf( pFile, "F = " );
+    if ( Abc_LitIsCompl(pNtk->Root) )
+        fprintf( pFile, "!" );
+    Kit_DsdPrint_rec( pFile, pNtk, Abc_Lit2Var(pNtk->Root) );
+//    fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively print the DSD formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Kit_DsdWrite_rec( char * pBuff, Kit_DsdNtk_t * pNtk, int Id )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned iLit, i;
+    char Symbol;
+
+    pObj = Kit_DsdNtkObj( pNtk, Id );
+    if ( pObj == NULL )
+    {
+        assert( Id < pNtk->nVars );
+        *pBuff++ = 'a' + Id;
+        return pBuff;
+    }
+
+    if ( pObj->Type == KIT_DSD_CONST1 )
+    {
+        assert( pObj->nFans == 0 );
+        sprintf( pBuff, "%s", "Const1" );
+        return pBuff + strlen("Const1");
+    }
+
+    if ( pObj->Type == KIT_DSD_VAR )
+        assert( pObj->nFans == 1 );
+
+    if ( pObj->Type == KIT_DSD_AND )
+        Symbol = '*';
+    else if ( pObj->Type == KIT_DSD_XOR )
+        Symbol = '+';
+    else 
+        Symbol = ',';
+
+    if ( pObj->Type == KIT_DSD_PRIME )
+        pBuff = Kit_DsdWriteHex( pBuff, Kit_DsdObjTruth(pObj), pObj->nFans );
+
+    *pBuff++ = '(';
+    Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+    {
+        if ( Abc_LitIsCompl(iLit) ) 
+            *pBuff++ = '!';
+        pBuff = Kit_DsdWrite_rec( pBuff, pNtk, Abc_Lit2Var(iLit) );
+        if ( i < pObj->nFans - 1 )
+            *pBuff++ = Symbol;
+    }
+    *pBuff++ = ')';
+    return pBuff;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print the DSD formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdWrite( char * pBuff, Kit_DsdNtk_t * pNtk )
+{
+    if ( Abc_LitIsCompl(pNtk->Root) )
+        *pBuff++ = '!';
+    pBuff = Kit_DsdWrite_rec( pBuff, pNtk, Abc_Lit2Var(pNtk->Root) );
+    *pBuff = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print the DSD formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdPrintExpanded( Kit_DsdNtk_t * pNtk )
+{
+    Kit_DsdNtk_t * pTemp;
+    pTemp = Kit_DsdExpand( pNtk );
+    Kit_DsdPrint( stdout, pTemp );
+    Kit_DsdNtkFree( pTemp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print the DSD formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars )
+{
+    Kit_DsdNtk_t * pTemp, * pTemp2;
+//    pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 5 );
+    pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 8 );
+//    Kit_DsdPrintExpanded( pTemp );
+    pTemp2 = Kit_DsdExpand( pTemp );
+    Kit_DsdPrint( stdout, pTemp2 );
+    Kit_DsdVerify( pTemp2, pTruth, nVars ); 
+    Kit_DsdNtkFree( pTemp2 );
+    Kit_DsdNtkFree( pTemp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print the DSD formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdPrintFromTruth2( FILE * pFile, unsigned * pTruth, int nVars )
+{
+    Kit_DsdNtk_t * pTemp, * pTemp2;
+    pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 0 );
+    pTemp2 = Kit_DsdExpand( pTemp );
+    Kit_DsdPrint2( pFile, pTemp2 );
+    Kit_DsdVerify( pTemp2, pTruth, nVars ); 
+    Kit_DsdNtkFree( pTemp2 );
+    Kit_DsdNtkFree( pTemp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print the DSD formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdWriteFromTruth( char * pBuffer, unsigned * pTruth, int nVars )
+{
+    Kit_DsdNtk_t * pTemp, * pTemp2;
+//    pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 5 );
+    pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 8 );
+//    Kit_DsdPrintExpanded( pTemp );
+    pTemp2 = Kit_DsdExpand( pTemp );
+    Kit_DsdWrite( pBuffer, pTemp2 );
+    Kit_DsdVerify( pTemp2, pTruth, nVars ); 
+    Kit_DsdNtkFree( pTemp2 );
+    Kit_DsdNtkFree( pTemp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table of the DSD node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Kit_DsdTruthComputeNode_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, int Id )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned * pTruthRes, * pTruthFans[16], * pTruthTemp;
+    unsigned i, iLit, fCompl;
+//    unsigned m, nMints, * pTruthPrime, * pTruthMint; 
+
+    // get the node with this ID
+    pObj = Kit_DsdNtkObj( pNtk, Id );
+    pTruthRes = (unsigned *)Vec_PtrEntry( p->vTtNodes, Id );
+
+    // special case: literal of an internal node
+    if ( pObj == NULL )
+    {
+        assert( Id < pNtk->nVars );
+        return pTruthRes;
+    }
+
+    // constant node
+    if ( pObj->Type == KIT_DSD_CONST1 )
+    {
+        assert( pObj->nFans == 0 );
+        Kit_TruthFill( pTruthRes, pNtk->nVars );
+        return pTruthRes;
+    }
+
+    // elementary variable node
+    if ( pObj->Type == KIT_DSD_VAR )
+    {
+        assert( pObj->nFans == 1 );
+        iLit = pObj->pFans[0];
+        pTruthFans[0] = Kit_DsdTruthComputeNode_rec( p, pNtk, Abc_Lit2Var(iLit) );
+        if ( Abc_LitIsCompl(iLit) )
+            Kit_TruthNot( pTruthRes, pTruthFans[0], pNtk->nVars );
+        else
+            Kit_TruthCopy( pTruthRes, pTruthFans[0], pNtk->nVars );
+        return pTruthRes;
+    }
+
+    // collect the truth tables of the fanins
+    Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+        pTruthFans[i] = Kit_DsdTruthComputeNode_rec( p, pNtk, Abc_Lit2Var(iLit) );
+    // create the truth table
+
+    // simple gates
+    if ( pObj->Type == KIT_DSD_AND )
+    {
+        Kit_TruthFill( pTruthRes, pNtk->nVars );
+        Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+            Kit_TruthAndPhase( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars, 0, Abc_LitIsCompl(iLit) );
+        return pTruthRes;
+    }
+    if ( pObj->Type == KIT_DSD_XOR )
+    {
+        Kit_TruthClear( pTruthRes, pNtk->nVars );
+        fCompl = 0;
+        Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+        {
+            Kit_TruthXor( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars );
+            fCompl ^= Abc_LitIsCompl(iLit);
+        }
+        if ( fCompl )
+            Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars );
+        return pTruthRes;
+    }
+    assert( pObj->Type == KIT_DSD_PRIME );
+/*
+    // get the truth table of the prime node
+    pTruthPrime = Kit_DsdObjTruth( pObj );
+    // get storage for the temporary minterm
+    pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes);
+    // go through the minterms
+    nMints = (1 << pObj->nFans);
+    Kit_TruthClear( pTruthRes, pNtk->nVars );
+    for ( m = 0; m < nMints; m++ )
+    {
+        if ( !Kit_TruthHasBit(pTruthPrime, m) )
+            continue;
+        Kit_TruthFill( pTruthMint, pNtk->nVars );
+        Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+            Kit_TruthAndPhase( pTruthMint, pTruthMint, pTruthFans[i], pNtk->nVars, 0, ((m & (1<<i)) == 0) ^ Abc_LitIsCompl(iLit) );
+        Kit_TruthOr( pTruthRes, pTruthRes, pTruthMint, pNtk->nVars );
+    }
+*/
+    Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+        if ( Abc_LitIsCompl(iLit) )
+            Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->nVars );
+    pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes );
+    Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars );
+    return pTruthRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table of the DSD network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Kit_DsdTruthCompute( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk )
+{
+    unsigned * pTruthRes;
+    int i;
+    // assign elementary truth ables
+    assert( pNtk->nVars <= p->nVars );
+    for ( i = 0; i < (int)pNtk->nVars; i++ )
+        Kit_TruthCopy( (unsigned *)Vec_PtrEntry(p->vTtNodes, i), (unsigned *)Vec_PtrEntry(p->vTtElems, i), p->nVars );
+    // compute truth table for each node
+    pTruthRes = Kit_DsdTruthComputeNode_rec( p, pNtk, Abc_Lit2Var(pNtk->Root) );
+    // complement the truth table if needed
+    if ( Abc_LitIsCompl(pNtk->Root) )
+        Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars );
+    return pTruthRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table of the DSD node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Kit_DsdTruthComputeNodeOne_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, int Id, unsigned uSupp )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned * pTruthRes, * pTruthFans[16], * pTruthTemp;
+    unsigned i, iLit, fCompl, nPartial = 0;
+//    unsigned m, nMints, * pTruthPrime, * pTruthMint; 
+
+    // get the node with this ID
+    pObj = Kit_DsdNtkObj( pNtk, Id );
+    pTruthRes = (unsigned *)Vec_PtrEntry( p->vTtNodes, Id );
+
+    // special case: literal of an internal node
+    if ( pObj == NULL )
+    {
+        assert( Id < pNtk->nVars );
+        assert( !uSupp || uSupp != (uSupp & ~(1<<Id)) );
+        return pTruthRes;
+    }
+
+    // constant node
+    if ( pObj->Type == KIT_DSD_CONST1 )
+    {
+        assert( pObj->nFans == 0 );
+        Kit_TruthFill( pTruthRes, pNtk->nVars );
+        return pTruthRes;
+    }
+
+    // elementary variable node
+    if ( pObj->Type == KIT_DSD_VAR )
+    {
+        assert( pObj->nFans == 1 );
+        iLit = pObj->pFans[0];
+        assert( Kit_DsdLitIsLeaf( pNtk, iLit ) );
+        pTruthFans[0] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Abc_Lit2Var(iLit), uSupp );
+        if ( Abc_LitIsCompl(iLit) )
+            Kit_TruthNot( pTruthRes, pTruthFans[0], pNtk->nVars );
+        else
+            Kit_TruthCopy( pTruthRes, pTruthFans[0], pNtk->nVars );
+        return pTruthRes;
+    }
+
+    // collect the truth tables of the fanins
+    if ( uSupp )
+    {
+        Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+            if ( uSupp != (uSupp & ~Kit_DsdLitSupport(pNtk, iLit)) )
+                pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Abc_Lit2Var(iLit), uSupp );
+            else
+            {
+                pTruthFans[i] = NULL;
+                nPartial = 1;
+            }
+    }
+    else
+    {
+        Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+            pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Abc_Lit2Var(iLit), uSupp );
+    }
+    // create the truth table
+
+    // simple gates
+    if ( pObj->Type == KIT_DSD_AND )
+    {
+        Kit_TruthFill( pTruthRes, pNtk->nVars );
+        Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+            if ( pTruthFans[i] )
+                Kit_TruthAndPhase( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars, 0, Abc_LitIsCompl(iLit) );
+        return pTruthRes;
+    }
+    if ( pObj->Type == KIT_DSD_XOR )
+    {
+        Kit_TruthClear( pTruthRes, pNtk->nVars );
+        fCompl = 0;
+        Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+        {
+            if ( pTruthFans[i] )
+            {
+                Kit_TruthXor( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars );
+                fCompl ^= Abc_LitIsCompl(iLit);
+            }
+        }
+        if ( fCompl )
+            Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars );
+        return pTruthRes;
+    }
+    assert( pObj->Type == KIT_DSD_PRIME );
+
+    if ( uSupp && nPartial )
+    {
+        // find the only non-empty component
+        Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+            if ( pTruthFans[i] )
+                break;
+        assert( i < pObj->nFans );
+        return pTruthFans[i];
+    }
+/*
+    // get the truth table of the prime node
+    pTruthPrime = Kit_DsdObjTruth( pObj );
+    // get storage for the temporary minterm
+    pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes);
+    // go through the minterms
+    nMints = (1 << pObj->nFans);
+    Kit_TruthClear( pTruthRes, pNtk->nVars );
+    for ( m = 0; m < nMints; m++ )
+    {
+        if ( !Kit_TruthHasBit(pTruthPrime, m) )
+            continue;
+        Kit_TruthFill( pTruthMint, pNtk->nVars );
+        Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+            Kit_TruthAndPhase( pTruthMint, pTruthMint, pTruthFans[i], pNtk->nVars, 0, ((m & (1<<i)) == 0) ^ Abc_LitIsCompl(iLit) );
+        Kit_TruthOr( pTruthRes, pTruthRes, pTruthMint, pNtk->nVars );
+    }
+*/
+    Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+        if ( Abc_LitIsCompl(iLit) )
+            Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->nVars );
+    pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes );
+    Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars );
+    return pTruthRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table of the DSD network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Kit_DsdTruthComputeOne( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned uSupp )
+{
+    unsigned * pTruthRes;
+    int i;
+    // if support is specified, request that supports are available
+    if ( uSupp )
+        Kit_DsdGetSupports( pNtk );
+    // assign elementary truth tables
+    assert( pNtk->nVars <= p->nVars );
+    for ( i = 0; i < (int)pNtk->nVars; i++ )
+        Kit_TruthCopy( (unsigned *)Vec_PtrEntry(p->vTtNodes, i), (unsigned *)Vec_PtrEntry(p->vTtElems, i), p->nVars );
+    // compute truth table for each node
+    pTruthRes = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Abc_Lit2Var(pNtk->Root), uSupp );
+    // complement the truth table if needed
+    if ( Abc_LitIsCompl(pNtk->Root) )
+        Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars );
+    return pTruthRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table of the DSD node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Kit_DsdTruthComputeNodeTwo_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, int Id, unsigned uSupp, int iVar, unsigned * pTruthDec )
+{
+    Kit_DsdObj_t * pObj;
+    int pfBoundSet[16];
+    unsigned * pTruthRes, * pTruthFans[16], * pTruthTemp;
+    unsigned i, iLit, fCompl, nPartial, uSuppFan, uSuppCur;
+//    unsigned m, nMints, * pTruthPrime, * pTruthMint; 
+    assert( uSupp > 0 );
+
+    // get the node with this ID
+    pObj = Kit_DsdNtkObj( pNtk, Id );
+    pTruthRes = (unsigned *)Vec_PtrEntry( p->vTtNodes, Id );
+    if ( pObj == NULL )
+    {
+        assert( Id < pNtk->nVars );
+        return pTruthRes;
+    }
+    assert( pObj->Type != KIT_DSD_CONST1 );
+    assert( pObj->Type != KIT_DSD_VAR );
+
+    // count the number of intersecting fanins 
+    // collect the total support of the intersecting fanins
+    nPartial = 0;
+    uSuppFan = 0;
+    Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+    {
+        uSuppCur = Kit_DsdLitSupport(pNtk, iLit);
+        if ( uSupp & uSuppCur )
+        {
+            nPartial++;
+            uSuppFan |= uSuppCur;
+        }
+    }
+
+    // if there is no intersection, or full intersection, use simple procedure
+    if ( nPartial == 0 || nPartial == pObj->nFans )
+        return Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Id, 0 );
+
+    // if support of the component includes some other variables
+    // we need to continue constructing it as usual by the two-function procedure
+    if ( uSuppFan != (uSuppFan & uSupp) )
+    {
+        assert( nPartial == 1 );
+//        return Kit_DsdTruthComputeNodeTwo_rec( p, pNtk, Id, uSupp, iVar, pTruthDec );
+        Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+        {
+            if ( uSupp & Kit_DsdLitSupport(pNtk, iLit) )
+                pTruthFans[i] = Kit_DsdTruthComputeNodeTwo_rec( p, pNtk, Abc_Lit2Var(iLit), uSupp, iVar, pTruthDec );
+            else
+                pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Abc_Lit2Var(iLit), 0 );
+        }
+
+        // create composition/decomposition functions
+        if ( pObj->Type == KIT_DSD_AND )
+        {
+            Kit_TruthFill( pTruthRes, pNtk->nVars );
+            Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+                Kit_TruthAndPhase( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars, 0, Abc_LitIsCompl(iLit) );
+            return pTruthRes;
+        }
+        if ( pObj->Type == KIT_DSD_XOR )
+        {
+            Kit_TruthClear( pTruthRes, pNtk->nVars );
+            fCompl = 0;
+            Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+            {
+                fCompl ^= Abc_LitIsCompl(iLit);
+                Kit_TruthXor( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars );
+            }
+            if ( fCompl )
+                Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars );
+            return pTruthRes;
+        }
+        assert( pObj->Type == KIT_DSD_PRIME );
+    }
+    else
+    {
+        assert( uSuppFan == (uSuppFan & uSupp) );
+        assert( nPartial < pObj->nFans );
+        // the support of the insecting component(s) is contained in the bound-set
+        // and yet there are components that are not contained in the bound set
+
+        // solve the fanins and collect info, which components belong to the bound set
+        Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+        {
+            pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Abc_Lit2Var(iLit), 0 );
+            pfBoundSet[i] = (int)((uSupp & Kit_DsdLitSupport(pNtk, iLit)) > 0);
+        }
+
+        // create composition/decomposition functions
+        if ( pObj->Type == KIT_DSD_AND )
+        {
+            Kit_TruthIthVar( pTruthRes, pNtk->nVars, iVar );
+            Kit_TruthFill( pTruthDec, pNtk->nVars );
+            Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+                if ( pfBoundSet[i] )
+                    Kit_TruthAndPhase( pTruthDec, pTruthDec, pTruthFans[i], pNtk->nVars, 0, Abc_LitIsCompl(iLit) );
+                else
+                    Kit_TruthAndPhase( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars, 0, Abc_LitIsCompl(iLit) );
+            return pTruthRes;
+        }
+        if ( pObj->Type == KIT_DSD_XOR )
+        {
+            Kit_TruthIthVar( pTruthRes, pNtk->nVars, iVar );
+            Kit_TruthClear( pTruthDec, pNtk->nVars );
+            fCompl = 0;
+            Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+            {
+                fCompl ^= Abc_LitIsCompl(iLit);
+                if ( pfBoundSet[i] )
+                    Kit_TruthXor( pTruthDec, pTruthDec, pTruthFans[i], pNtk->nVars );
+                else
+                    Kit_TruthXor( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars );
+            }
+            if ( fCompl )
+                Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars );
+            return pTruthRes;
+        }
+        assert( pObj->Type == KIT_DSD_PRIME );
+        assert( nPartial == 1 );
+
+        // find the only non-empty component
+        Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+            if ( pfBoundSet[i] )
+                break;
+        assert( i < pObj->nFans );
+
+        // save this component as the decomposed function
+        Kit_TruthCopy( pTruthDec, pTruthFans[i], pNtk->nVars );
+        // set the corresponding component to be the new variable
+        Kit_TruthIthVar( pTruthFans[i], pNtk->nVars, iVar );
+    }
+/*
+    // get the truth table of the prime node
+    pTruthPrime = Kit_DsdObjTruth( pObj );
+    // get storage for the temporary minterm
+    pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes);
+    // go through the minterms
+    nMints = (1 << pObj->nFans);
+    Kit_TruthClear( pTruthRes, pNtk->nVars );
+    for ( m = 0; m < nMints; m++ )
+    {
+        if ( !Kit_TruthHasBit(pTruthPrime, m) )
+            continue;
+        Kit_TruthFill( pTruthMint, pNtk->nVars );
+        Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+            Kit_TruthAndPhase( pTruthMint, pTruthMint, pTruthFans[i], pNtk->nVars, 0, ((m & (1<<i)) == 0) ^ Abc_LitIsCompl(iLit) );
+        Kit_TruthOr( pTruthRes, pTruthRes, pTruthMint, pNtk->nVars );
+    }
+*/
+//    Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+//        assert( !Abc_LitIsCompl(iLit) );
+    Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+        if ( Abc_LitIsCompl(iLit) )
+            Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->nVars );
+    pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes );
+    Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars );
+    return pTruthRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table of the DSD network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Kit_DsdTruthComputeTwo( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned uSupp, int iVar, unsigned * pTruthDec )
+{
+    unsigned * pTruthRes, uSuppAll;
+    int i;
+    assert( uSupp > 0 );
+    assert( pNtk->nVars <= p->nVars );
+    // compute support of all nodes
+    uSuppAll = Kit_DsdGetSupports( pNtk );
+    // consider special case - there is no overlap
+    if ( (uSupp & uSuppAll) == 0 )
+    {
+        Kit_TruthClear( pTruthDec, pNtk->nVars );
+        return Kit_DsdTruthCompute( p, pNtk );
+    }
+    // consider special case - support is fully contained
+    if ( (uSupp & uSuppAll) == uSuppAll )
+    {
+        pTruthRes = Kit_DsdTruthCompute( p, pNtk );
+        Kit_TruthCopy( pTruthDec, pTruthRes, pNtk->nVars );
+        Kit_TruthIthVar( pTruthRes, pNtk->nVars, iVar );
+        return pTruthRes;
+    }
+    // assign elementary truth tables
+    for ( i = 0; i < (int)pNtk->nVars; i++ )
+        Kit_TruthCopy( (unsigned *)Vec_PtrEntry(p->vTtNodes, i), (unsigned *)Vec_PtrEntry(p->vTtElems, i), p->nVars );
+    // compute truth table for each node
+    pTruthRes = Kit_DsdTruthComputeNodeTwo_rec( p, pNtk, Abc_Lit2Var(pNtk->Root), uSupp, iVar, pTruthDec );
+    // complement the truth table if needed
+    if ( Abc_LitIsCompl(pNtk->Root) )
+        Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars );
+    return pTruthRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table of the DSD network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdTruth( Kit_DsdNtk_t * pNtk, unsigned * pTruthRes )
+{
+    Kit_DsdMan_t * p;
+    unsigned * pTruth;
+    p = Kit_DsdManAlloc( pNtk->nVars, Kit_DsdNtkObjNum(pNtk) );
+    pTruth = Kit_DsdTruthCompute( p, pNtk );
+    Kit_TruthCopy( pTruthRes, pTruth, pNtk->nVars );
+    Kit_DsdManFree( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table of the DSD network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdTruthPartialTwo( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned uSupp, int iVar, unsigned * pTruthCo, unsigned * pTruthDec )
+{
+    unsigned * pTruth = Kit_DsdTruthComputeTwo( p, pNtk, uSupp, iVar, pTruthDec );
+    if ( pTruthCo )
+        Kit_TruthCopy( pTruthCo, pTruth, pNtk->nVars );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table of the DSD network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdTruthPartial( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned * pTruthRes, unsigned uSupp )
+{
+    unsigned * pTruth = Kit_DsdTruthComputeOne( p, pNtk, uSupp );
+    Kit_TruthCopy( pTruthRes, pTruth, pNtk->nVars );
+/*
+    // verification
+    {
+        // compute the same function using different procedure
+        unsigned * pTruthTemp = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes + 1);
+        pNtk->pSupps = NULL;
+        Kit_DsdTruthComputeTwo( p, pNtk, uSupp, -1, pTruthTemp );
+//        if ( !Kit_TruthIsEqual( pTruthTemp, pTruthRes, pNtk->nVars ) )
+        if ( !Kit_TruthIsEqualWithPhase( pTruthTemp, pTruthRes, pNtk->nVars ) )
+        {
+            printf( "Verification FAILED!\n" );
+            Kit_DsdPrint( stdout, pNtk );
+            Kit_DsdPrintFromTruth( pTruthRes, pNtk->nVars );
+            Kit_DsdPrintFromTruth( pTruthTemp, pNtk->nVars );
+        }
+//        else
+//            printf( "Verification successful.\n" );
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of blocks of the given number of inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DsdCountLuts_rec( Kit_DsdNtk_t * pNtk, int nLutSize, int Id, int * pCounter )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned iLit, i, Res0, Res1;
+    pObj = Kit_DsdNtkObj( pNtk, Id );
+    if ( pObj == NULL )
+        return 0;
+    if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR )
+    {
+        assert( pObj->nFans == 2 );
+        Res0 = Kit_DsdCountLuts_rec( pNtk, nLutSize, Abc_Lit2Var(pObj->pFans[0]), pCounter );
+        Res1 = Kit_DsdCountLuts_rec( pNtk, nLutSize, Abc_Lit2Var(pObj->pFans[1]), pCounter );
+        if ( Res0 == 0 && Res1 > 0 )
+            return Res1 - 1;
+        if ( Res0 > 0 && Res1 == 0 )
+            return Res0 - 1;
+        (*pCounter)++;
+        return nLutSize - 2;
+    }
+    assert( pObj->Type == KIT_DSD_PRIME );
+    if ( (int)pObj->nFans > nLutSize ) //+ 1 )
+    {
+        *pCounter = 1000;
+        return 0;
+    }
+    Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+        Kit_DsdCountLuts_rec( pNtk, nLutSize, Abc_Lit2Var(iLit), pCounter );
+    (*pCounter)++;
+//    if ( (int)pObj->nFans == nLutSize + 1 )
+//        (*pCounter)++;
+    return nLutSize - pObj->nFans;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of blocks of the given number of inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DsdCountLuts( Kit_DsdNtk_t * pNtk, int nLutSize )
+{
+    int Counter = 0;
+    if ( Kit_DsdNtkRoot(pNtk)->Type == KIT_DSD_CONST1 )
+        return 0;
+    if ( Kit_DsdNtkRoot(pNtk)->Type == KIT_DSD_VAR )
+        return 0;
+    Kit_DsdCountLuts_rec( pNtk, nLutSize, Abc_Lit2Var(pNtk->Root), &Counter );
+    if ( Counter >= 1000 )
+        return -1;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the size of the largest non-DSD block.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DsdNonDsdSizeMax( Kit_DsdNtk_t * pNtk )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned i, nSizeMax = 0;
+    Kit_DsdNtkForEachObj( pNtk, pObj, i )
+    {
+        if ( pObj->Type != KIT_DSD_PRIME )
+            continue;
+        if ( nSizeMax < pObj->nFans )
+            nSizeMax = pObj->nFans;
+    }
+    return nSizeMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the largest non-DSD block.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_DsdObj_t * Kit_DsdNonDsdPrimeMax( Kit_DsdNtk_t * pNtk )
+{
+    Kit_DsdObj_t * pObj, * pObjMax = NULL;
+    unsigned i, nSizeMax = 0;
+    Kit_DsdNtkForEachObj( pNtk, pObj, i )
+    {
+        if ( pObj->Type != KIT_DSD_PRIME )
+            continue;
+        if ( nSizeMax < pObj->nFans )
+        {
+            nSizeMax = pObj->nFans;
+            pObjMax = pObj;
+        }
+    }
+    return pObjMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the union of supports of the non-DSD blocks.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Kit_DsdNonDsdSupports( Kit_DsdNtk_t * pNtk )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned i, uSupport = 0;
+//    ABC_FREE( pNtk->pSupps );
+    Kit_DsdGetSupports( pNtk );
+    Kit_DsdNtkForEachObj( pNtk, pObj, i )
+    {
+        if ( pObj->Type != KIT_DSD_PRIME )
+            continue;
+        uSupport |= Kit_DsdLitSupport( pNtk, Abc_Var2Lit(pObj->Id,0) );
+    }
+    return uSupport;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Expands the node.]
+
+  Description [Returns the new literal.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdExpandCollectAnd_rec( Kit_DsdNtk_t * p, unsigned iLit, unsigned * piLitsNew, int * nLitsNew )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned i, iLitFanin;
+    // check the end of the supergate
+    pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) );
+    if ( Abc_LitIsCompl(iLit) || Abc_Lit2Var(iLit) < p->nVars || pObj->Type != KIT_DSD_AND )
+    {
+        piLitsNew[(*nLitsNew)++] = iLit;
+        return;
+    }
+    // iterate through the fanins
+    Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i )
+        Kit_DsdExpandCollectAnd_rec( p, iLitFanin, piLitsNew, nLitsNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Expands the node.]
+
+  Description [Returns the new literal.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdExpandCollectXor_rec( Kit_DsdNtk_t * p, unsigned iLit, unsigned * piLitsNew, int * nLitsNew )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned i, iLitFanin;
+    // check the end of the supergate
+    pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) );
+    if ( Abc_Lit2Var(iLit) < p->nVars || pObj->Type != KIT_DSD_XOR )
+    {
+        piLitsNew[(*nLitsNew)++] = iLit;
+        return;
+    }
+    // iterate through the fanins
+    pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) );
+    Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i )
+        Kit_DsdExpandCollectXor_rec( p, iLitFanin, piLitsNew, nLitsNew );
+    // if the literal was complemented, pass the complemented attribute somewhere
+    if ( Abc_LitIsCompl(iLit) )
+        piLitsNew[0] = Abc_LitNot( piLitsNew[0] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Expands the node.]
+
+  Description [Returns the new literal.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DsdExpandNode_rec( Kit_DsdNtk_t * pNew, Kit_DsdNtk_t * p, int iLit )
+{
+    unsigned * pTruth, * pTruthNew;
+    unsigned i, iLitFanin, piLitsNew[16], nLitsNew = 0;
+    Kit_DsdObj_t * pObj, * pObjNew;
+
+    // consider the case of simple gate
+    pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) );
+    if ( pObj == NULL )
+        return iLit;
+    if ( pObj->Type == KIT_DSD_AND )
+    {
+        Kit_DsdExpandCollectAnd_rec( p, Abc_LitRegular(iLit), piLitsNew, (int *)&nLitsNew );
+        pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_AND, nLitsNew );
+        for ( i = 0; i < pObjNew->nFans; i++ )
+            pObjNew->pFans[i] = Kit_DsdExpandNode_rec( pNew, p, piLitsNew[i] );
+        return Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(iLit) );
+    }
+    if ( pObj->Type == KIT_DSD_XOR )
+    {
+        int fCompl = Abc_LitIsCompl(iLit);
+        Kit_DsdExpandCollectXor_rec( p, Abc_LitRegular(iLit), piLitsNew, (int *)&nLitsNew );
+        pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_XOR, nLitsNew );
+        for ( i = 0; i < pObjNew->nFans; i++ )
+        {
+            pObjNew->pFans[i] = Kit_DsdExpandNode_rec( pNew, p, Abc_LitRegular(piLitsNew[i]) );
+            fCompl ^= Abc_LitIsCompl(piLitsNew[i]);
+        }
+        return Abc_Var2Lit( pObjNew->Id, fCompl );
+    }
+    assert( pObj->Type == KIT_DSD_PRIME );
+
+    // create new PRIME node
+    pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_PRIME, pObj->nFans );
+    // copy the truth table
+    pTruth = Kit_DsdObjTruth( pObj );
+    pTruthNew = Kit_DsdObjTruth( pObjNew );
+    Kit_TruthCopy( pTruthNew, pTruth, pObj->nFans );
+    // create fanins
+    Kit_DsdObjForEachFanin( pNtk, pObj, iLitFanin, i )
+    {
+        pObjNew->pFans[i] = Kit_DsdExpandNode_rec( pNew, p, iLitFanin );
+        // complement the corresponding inputs of the truth table
+        if ( Abc_LitIsCompl(pObjNew->pFans[i]) )
+        {
+            pObjNew->pFans[i] = Abc_LitRegular(pObjNew->pFans[i]);
+            Kit_TruthChangePhase( pTruthNew, pObjNew->nFans, i );
+        }
+    }
+
+    if ( pObj->nFans == 3 && 
+        (pTruthNew[0] == 0xCACACACA || pTruthNew[0] == 0xC5C5C5C5 || 
+         pTruthNew[0] == 0x3A3A3A3A || pTruthNew[0] == 0x35353535) )
+    {
+        // translate into regular MUXes
+        if ( pTruthNew[0] == 0xC5C5C5C5 )
+            pObjNew->pFans[0] = Abc_LitNot(pObjNew->pFans[0]);
+        else if ( pTruthNew[0] == 0x3A3A3A3A )
+            pObjNew->pFans[1] = Abc_LitNot(pObjNew->pFans[1]);
+        else if ( pTruthNew[0] == 0x35353535 )
+        {
+            pObjNew->pFans[0] = Abc_LitNot(pObjNew->pFans[0]);
+            pObjNew->pFans[1] = Abc_LitNot(pObjNew->pFans[1]);
+        }
+        pTruthNew[0] = 0xCACACACA;
+        // resolve the complemented control input
+        if ( Abc_LitIsCompl(pObjNew->pFans[2]) )
+        {
+            unsigned char Temp = pObjNew->pFans[0];
+            pObjNew->pFans[0] = pObjNew->pFans[1];
+            pObjNew->pFans[1] = Temp;
+            pObjNew->pFans[2] = Abc_LitNot(pObjNew->pFans[2]);
+        }
+        // resolve the complemented true input
+        if ( Abc_LitIsCompl(pObjNew->pFans[1]) )
+        {
+            iLit = Abc_LitNot(iLit);
+            pObjNew->pFans[0] = Abc_LitNot(pObjNew->pFans[0]);
+            pObjNew->pFans[1] = Abc_LitNot(pObjNew->pFans[1]);
+        }
+        return Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(iLit) );
+    }
+    else
+    {
+        // if the incoming phase is complemented, absorb it into the prime node
+        if ( Abc_LitIsCompl(iLit) )
+            Kit_TruthNot( pTruthNew, pTruthNew, pObj->nFans );
+        return Abc_Var2Lit( pObjNew->Id, 0 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Expands the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_DsdNtk_t * Kit_DsdExpand( Kit_DsdNtk_t * p )
+{
+    Kit_DsdNtk_t * pNew;
+    Kit_DsdObj_t * pObjNew;
+    assert( p->nVars <= 16 );
+    // create a new network
+    pNew = Kit_DsdNtkAlloc( p->nVars );
+    // consider simple special cases
+    if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 )
+    {
+        pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_CONST1, 0 );
+        pNew->Root = Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(p->Root) );
+        return pNew;
+    }
+    if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR )
+    {
+        pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_VAR, 1 );
+        pObjNew->pFans[0] = Kit_DsdNtkRoot(p)->pFans[0];
+        pNew->Root = Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(p->Root) );
+        return pNew;
+    }
+    // convert the root node
+    pNew->Root = Kit_DsdExpandNode_rec( pNew, p, p->Root );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts the literals by their support.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdCompSort( int pPrios[], unsigned uSupps[], unsigned short * piLits, int nVars, unsigned piLitsRes[] )
+{
+    int nSuppSizes[16], Priority[16], pOrder[16];
+    int i, k, iVarBest, SuppMax, PrioMax;
+    // compute support sizes and priorities of the components
+    for ( i = 0; i < nVars; i++ )
+    {
+        assert( uSupps[i] );
+        pOrder[i] = i;
+        Priority[i] = KIT_INFINITY;
+        for ( k = 0; k < 16; k++ )
+            if ( uSupps[i] & (1 << k) )
+                Priority[i] = KIT_MIN( Priority[i], pPrios[k] );
+        assert( Priority[i] != 16 );
+        nSuppSizes[i] = Kit_WordCountOnes(uSupps[i]);
+    }
+    // sort the components by pririty
+    Extra_BubbleSort( pOrder, Priority, nVars, 0 );
+    // find the component by with largest size and lowest priority
+    iVarBest = -1;
+    SuppMax  = 0;
+    PrioMax  = 0;
+    for ( i = 0; i < nVars; i++ )
+    {
+        if ( SuppMax < nSuppSizes[i] || (SuppMax == nSuppSizes[i] && PrioMax < Priority[i]) )
+        {
+            SuppMax  = nSuppSizes[i];
+            PrioMax  = Priority[i];
+            iVarBest = i;
+        }
+    }
+    assert( iVarBest != -1 );
+    // copy the resulting literals
+    k = 0;
+    piLitsRes[k++] = piLits[iVarBest];
+    for ( i = 0; i < nVars; i++ )
+    {
+        if ( pOrder[i] == iVarBest )
+            continue;
+        piLitsRes[k++] = piLits[pOrder[i]];
+    }
+    assert( k == nVars );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Shrinks multi-input nodes.]
+
+  Description [Takes the array of variable priorities pPrios.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DsdShrink_rec( Kit_DsdNtk_t * pNew, Kit_DsdNtk_t * p, int iLit, int pPrios[] )
+{
+    Kit_DsdObj_t * pObj;
+    Kit_DsdObj_t * pObjNew = NULL; // Suppress "might be used uninitialized"
+    unsigned * pTruth, * pTruthNew;
+    unsigned i, piLitsNew[16], uSupps[16];
+    int iLitFanin, iLitNew;
+
+    // consider the case of simple gate
+    pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) );
+    if ( pObj == NULL )
+        return iLit;
+    if ( pObj->Type == KIT_DSD_AND )
+    {
+        // get the supports
+        Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i )
+            uSupps[i] = Kit_DsdLitSupport( p, iLitFanin );
+        // put the largest component last
+        // sort other components in the decreasing order of priority of their vars
+        Kit_DsdCompSort( pPrios, uSupps, pObj->pFans, pObj->nFans, piLitsNew );
+        // construct the two-input node network
+        iLitNew = Kit_DsdShrink_rec( pNew, p, piLitsNew[0], pPrios );
+        for ( i = 1; i < pObj->nFans; i++ )
+        {
+            pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_AND, 2 );
+            pObjNew->pFans[0] = Kit_DsdShrink_rec( pNew, p, piLitsNew[i], pPrios );
+            pObjNew->pFans[1] = iLitNew;
+            iLitNew = Abc_Var2Lit( pObjNew->Id, 0 );
+        }
+        return Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(iLit) );
+    }
+    if ( pObj->Type == KIT_DSD_XOR )
+    {
+        // get the supports
+        Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i )
+        {
+            assert( !Abc_LitIsCompl(iLitFanin) );
+            uSupps[i] = Kit_DsdLitSupport( p, iLitFanin );
+        }
+        // put the largest component last
+        // sort other components in the decreasing order of priority of their vars
+        Kit_DsdCompSort( pPrios, uSupps, pObj->pFans, pObj->nFans, piLitsNew );
+        // construct the two-input node network
+        iLitNew = Kit_DsdShrink_rec( pNew, p, piLitsNew[0], pPrios );
+        for ( i = 1; i < pObj->nFans; i++ )
+        {
+            pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_XOR, 2 );
+            pObjNew->pFans[0] = Kit_DsdShrink_rec( pNew, p, piLitsNew[i], pPrios );
+            pObjNew->pFans[1] = iLitNew;
+            iLitNew = Abc_Var2Lit( pObjNew->Id, 0 );
+        }
+        return Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(iLit) );
+    }
+    assert( pObj->Type == KIT_DSD_PRIME );
+
+    // create new PRIME node
+    pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_PRIME, pObj->nFans );
+    // copy the truth table
+    pTruth = Kit_DsdObjTruth( pObj );
+    pTruthNew = Kit_DsdObjTruth( pObjNew );
+    Kit_TruthCopy( pTruthNew, pTruth, pObj->nFans );
+    // create fanins
+    Kit_DsdObjForEachFanin( pNtk, pObj, iLitFanin, i )
+    {
+        pObjNew->pFans[i] = Kit_DsdShrink_rec( pNew, p, iLitFanin, pPrios );
+        // complement the corresponding inputs of the truth table
+        if ( Abc_LitIsCompl(pObjNew->pFans[i]) )
+        {
+            pObjNew->pFans[i] = Abc_LitRegular(pObjNew->pFans[i]);
+            Kit_TruthChangePhase( pTruthNew, pObjNew->nFans, i );
+        }
+    }
+    // if the incoming phase is complemented, absorb it into the prime node
+    if ( Abc_LitIsCompl(iLit) )
+        Kit_TruthNot( pTruthNew, pTruthNew, pObj->nFans );
+    return Abc_Var2Lit( pObjNew->Id, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Shrinks the network.]
+
+  Description [Transforms the network to have two-input nodes so that the
+  higher-ordered nodes were decomposed out first.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_DsdNtk_t * Kit_DsdShrink( Kit_DsdNtk_t * p, int pPrios[] )
+{
+    Kit_DsdNtk_t * pNew;
+    Kit_DsdObj_t * pObjNew;
+    assert( p->nVars <= 16 );
+    // create a new network
+    pNew = Kit_DsdNtkAlloc( p->nVars );
+    // consider simple special cases
+    if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 )
+    {
+        pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_CONST1, 0 );
+        pNew->Root = Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(p->Root) );
+        return pNew;
+    }
+    if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR )
+    {
+        pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_VAR, 1 );
+        pObjNew->pFans[0] = Kit_DsdNtkRoot(p)->pFans[0];
+        pNew->Root = Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(p->Root) );
+        return pNew;
+    }
+    // convert the root node
+    pNew->Root = Kit_DsdShrink_rec( pNew, p, p->Root, pPrios );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Rotates the network.]
+
+  Description [Transforms prime nodes to have the fanin with the
+  highest frequency of supports go first.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdRotate( Kit_DsdNtk_t * p, int pFreqs[] )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned * pIn, * pOut, * pTemp, k;
+    int i, v, Temp, uSuppFanin, iFaninLit, WeightMax, FaninMax, nSwaps;
+    int Weights[16];
+    // go through the prime nodes
+    Kit_DsdNtkForEachObj( p, pObj, i )
+    {
+        if ( pObj->Type != KIT_DSD_PRIME )
+            continue;
+        // count the fanin frequencies
+        Kit_DsdObjForEachFanin( p, pObj, iFaninLit, k )
+        {
+            uSuppFanin = Kit_DsdLitSupport( p, iFaninLit );
+            Weights[k] = 0;
+            for ( v = 0; v < 16; v++ )
+                if ( uSuppFanin & (1 << v) )
+                    Weights[k] += pFreqs[v] - 1;
+        }
+        // find the most frequent fanin
+        WeightMax = 0; 
+        FaninMax = -1;
+        for ( k = 0; k < pObj->nFans; k++ )
+            if ( WeightMax < Weights[k] )
+            {
+                WeightMax = Weights[k];
+                FaninMax = k;
+            }
+        // no need to reorder if there are no frequent fanins
+        if ( FaninMax == -1 )
+            continue;
+        // move the fanins number k to the first place
+        nSwaps = 0;
+        pIn = Kit_DsdObjTruth(pObj);
+        pOut = p->pMem;
+//        for ( v = FaninMax; v < ((int)pObj->nFans)-1; v++ )
+        for ( v = FaninMax-1; v >= 0; v-- )
+        {
+            // swap the fanins
+            Temp = pObj->pFans[v];
+            pObj->pFans[v] = pObj->pFans[v+1];
+            pObj->pFans[v+1] = Temp;
+            // swap the truth table variables
+            Kit_TruthSwapAdjacentVars( pOut, pIn, pObj->nFans, v );
+            pTemp = pIn; pIn = pOut; pOut = pTemp;
+            nSwaps++;
+        }
+        if ( nSwaps & 1 )
+            Kit_TruthCopy( pOut, pIn, pObj->nFans );
+    }    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the support.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Kit_DsdGetSupports_rec( Kit_DsdNtk_t * p, int iLit )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned uSupport, k;
+    int iFaninLit;
+    pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) );
+    if ( pObj == NULL )
+        return Kit_DsdLitSupport( p, iLit );
+    uSupport = 0;
+    Kit_DsdObjForEachFanin( p, pObj, iFaninLit, k )
+        uSupport |= Kit_DsdGetSupports_rec( p, iFaninLit );
+    p->pSupps[pObj->Id - p->nVars] = uSupport;
+    assert( uSupport <= 0xFFFF );
+    return uSupport;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the support.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Kit_DsdGetSupports( Kit_DsdNtk_t * p )
+{
+    Kit_DsdObj_t * pRoot;
+    unsigned uSupport;
+    assert( p->pSupps == NULL );
+    p->pSupps = ABC_ALLOC( unsigned, p->nNodes );
+    // consider simple special cases
+    pRoot = Kit_DsdNtkRoot(p);
+    if ( pRoot->Type == KIT_DSD_CONST1 )
+    {
+        assert( p->nNodes == 1 );
+        uSupport = p->pSupps[0] = 0;
+    }
+    if ( pRoot->Type == KIT_DSD_VAR )
+    {
+        assert( p->nNodes == 1 );
+        uSupport = p->pSupps[0] = Kit_DsdLitSupport( p, pRoot->pFans[0] );
+    }
+    else
+        uSupport = Kit_DsdGetSupports_rec( p, p->Root );
+    assert( uSupport <= 0xFFFF );
+    return uSupport;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if there is a component with more than 3 inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DsdFindLargeBox_rec( Kit_DsdNtk_t * pNtk, int Id, int Size )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned iLit, i, RetValue;
+    pObj = Kit_DsdNtkObj( pNtk, Id );
+    if ( pObj == NULL )
+        return 0;
+    if ( pObj->Type == KIT_DSD_PRIME && (int)pObj->nFans > Size )
+        return 1;
+    RetValue = 0;
+    Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+        RetValue |= Kit_DsdFindLargeBox_rec( pNtk, Abc_Lit2Var(iLit), Size );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if there is a component with more than 3 inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DsdFindLargeBox( Kit_DsdNtk_t * pNtk, int Size )
+{
+    return Kit_DsdFindLargeBox_rec( pNtk, Abc_Lit2Var(pNtk->Root), Size );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if there is a component with more than 3 inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DsdCountAigNodes_rec( Kit_DsdNtk_t * pNtk, int Id )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned iLit, i, RetValue;
+    pObj = Kit_DsdNtkObj( pNtk, Id );
+    if ( pObj == NULL )
+        return 0;
+    if ( pObj->Type == KIT_DSD_CONST1 || pObj->Type == KIT_DSD_VAR )
+        return 0;
+    if ( pObj->nFans < 2 ) // why this happens? - need to figure out
+        return 0; 
+    assert( pObj->nFans > 1 );
+    if ( pObj->Type == KIT_DSD_AND )
+        RetValue = ((int)pObj->nFans - 1);
+    else if ( pObj->Type == KIT_DSD_XOR )
+        RetValue = ((int)pObj->nFans - 1) * 3;
+    else if ( pObj->Type == KIT_DSD_PRIME )
+    {
+        // assuming MUX decomposition
+        assert( (int)pObj->nFans == 3 );
+        RetValue = 3;
+    }
+    else assert( 0 );
+    Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+        RetValue += Kit_DsdCountAigNodes_rec( pNtk, Abc_Lit2Var(iLit) );
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if there is a component with more than 3 inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DsdCountAigNodes2( Kit_DsdNtk_t * pNtk )
+{
+    return Kit_DsdCountAigNodes_rec( pNtk, Abc_Lit2Var(pNtk->Root) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if there is a component with more than 3 inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DsdCountAigNodes( Kit_DsdNtk_t * pNtk )
+{
+    Kit_DsdObj_t * pObj;
+    int i, Counter = 0;
+    for ( i = 0; i < pNtk->nNodes; i++ )
+    {
+        pObj = pNtk->pNodes[i];
+        if ( pObj->Type == KIT_DSD_AND )
+            Counter += ((int)pObj->nFans - 1);
+        else if ( pObj->Type == KIT_DSD_XOR )
+            Counter += ((int)pObj->nFans - 1) * 3;
+        else if ( pObj->Type == KIT_DSD_PRIME ) // assuming MUX decomposition
+            Counter += 3;
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the non-DSD 4-var func is implementable with two 3-LUTs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DsdRootNodeHasCommonVars( Kit_DsdObj_t * pObj0, Kit_DsdObj_t * pObj1 )
+{
+    unsigned i, k;
+    for ( i = 0; i < pObj0->nFans; i++ )
+    {
+        if ( Abc_Lit2Var(pObj0->pFans[i]) >= 4 )
+            continue;
+        for ( k = 0; k < pObj1->nFans; k++ )
+            if ( Abc_Lit2Var(pObj0->pFans[i]) == Abc_Lit2Var(pObj1->pFans[k]) )
+                return 1;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the non-DSD 4-var func is implementable with two 3-LUTs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DsdCheckVar4Dec2( Kit_DsdNtk_t * pNtk0, Kit_DsdNtk_t * pNtk1 )
+{
+    assert( pNtk0->nVars == 4 );
+    assert( pNtk1->nVars == 4 );
+    if ( Kit_DsdFindLargeBox(pNtk0, 2) )
+        return 0;
+    if ( Kit_DsdFindLargeBox(pNtk1, 2) )
+        return 0;
+    return Kit_DsdRootNodeHasCommonVars( Kit_DsdNtkRoot(pNtk0), Kit_DsdNtkRoot(pNtk1) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs decomposition of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdDecompose_rec( Kit_DsdNtk_t * pNtk, Kit_DsdObj_t * pObj, unsigned uSupp, unsigned short * pPar, int nDecMux )
+{
+    Kit_DsdObj_t * pRes, * pRes0, * pRes1;
+    int nWords = Kit_TruthWordNum(pObj->nFans);
+    unsigned * pTruth = Kit_DsdObjTruth(pObj);
+    unsigned * pCofs2[2] = { pNtk->pMem, pNtk->pMem + nWords };
+    unsigned * pCofs4[2][2] = { {pNtk->pMem + 2 * nWords, pNtk->pMem + 3 * nWords}, {pNtk->pMem + 4 * nWords, pNtk->pMem + 5 * nWords} };
+    int i, iLit0, iLit1, nFans0, nFans1, nPairs;
+    int fEquals[2][2], fOppos, fPairs[4][4];
+    unsigned j, k, nFansNew, uSupp0, uSupp1;
+
+    assert( pObj->nFans > 0 );
+    assert( pObj->Type == KIT_DSD_PRIME );
+    assert( uSupp == (uSupp0 = (unsigned)Kit_TruthSupport(pTruth, pObj->nFans)) );
+
+    // compress the truth table
+    if ( uSupp != Kit_BitMask(pObj->nFans) )
+    {
+        nFansNew = Kit_WordCountOnes(uSupp);
+        Kit_TruthShrink( pNtk->pMem, pTruth, nFansNew, pObj->nFans, uSupp, 1 );
+        for ( j = k = 0; j < pObj->nFans; j++ )
+            if ( uSupp & (1 << j) )
+                pObj->pFans[k++] = pObj->pFans[j];
+        assert( k == nFansNew );
+        pObj->nFans = k;
+        uSupp = Kit_BitMask(pObj->nFans);
+    }
+
+    // consider the single variable case
+    if ( pObj->nFans == 1 )
+    {
+        pObj->Type = KIT_DSD_NONE;
+        if ( pTruth[0] == 0x55555555 )
+            pObj->pFans[0] = Abc_LitNot(pObj->pFans[0]);
+        else
+            assert( pTruth[0] == 0xAAAAAAAA );
+        // update the parent pointer
+        *pPar = Abc_LitNotCond( pObj->pFans[0], Abc_LitIsCompl(*pPar) );
+        return;
+    }
+
+    // decompose the output
+    if ( !pObj->fMark )
+    for ( i = pObj->nFans - 1; i >= 0; i-- )
+    {
+        // get the two-variable cofactors
+        Kit_TruthCofactor0New( pCofs2[0], pTruth, pObj->nFans, i );
+        Kit_TruthCofactor1New( pCofs2[1], pTruth, pObj->nFans, i );
+//        assert( !Kit_TruthVarInSupport( pCofs2[0], pObj->nFans, i) );
+//        assert( !Kit_TruthVarInSupport( pCofs2[1], pObj->nFans, i) );
+        // get the constant cofs
+        fEquals[0][0] = Kit_TruthIsConst0( pCofs2[0], pObj->nFans );
+        fEquals[0][1] = Kit_TruthIsConst0( pCofs2[1], pObj->nFans );
+        fEquals[1][0] = Kit_TruthIsConst1( pCofs2[0], pObj->nFans );
+        fEquals[1][1] = Kit_TruthIsConst1( pCofs2[1], pObj->nFans );
+        fOppos        = Kit_TruthIsOpposite( pCofs2[0], pCofs2[1], pObj->nFans );
+        assert( !Kit_TruthIsEqual(pCofs2[0], pCofs2[1], pObj->nFans) );
+        if ( fEquals[0][0] + fEquals[0][1] + fEquals[1][0] + fEquals[1][1] + fOppos == 0 )
+        {
+            // check the MUX decomposition
+            uSupp0 = Kit_TruthSupport( pCofs2[0], pObj->nFans );
+            uSupp1 = Kit_TruthSupport( pCofs2[1], pObj->nFans );
+            assert( uSupp == (uSupp0 | uSupp1 | (1<<i)) );
+            if ( uSupp0 & uSupp1 )
+                continue;
+            // perform MUX decomposition
+            pRes0 = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, pObj->nFans );
+            pRes1 = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, pObj->nFans );
+            for ( k = 0; k < pObj->nFans; k++ )
+            {
+                pRes0->pFans[k] = (uSupp0 & (1 << k))? pObj->pFans[k] : 127;
+                pRes1->pFans[k] = (uSupp1 & (1 << k))? pObj->pFans[k] : 127;
+            }
+            Kit_TruthCopy( Kit_DsdObjTruth(pRes0), pCofs2[0], pObj->nFans );        
+            Kit_TruthCopy( Kit_DsdObjTruth(pRes1), pCofs2[1], pObj->nFans ); 
+            // update the current one
+            assert( pObj->Type == KIT_DSD_PRIME );
+            pTruth[0] = 0xCACACACA;
+            pObj->nFans = 3;
+            pObj->pFans[2] = pObj->pFans[i];
+            pObj->pFans[0] = 2*pRes0->Id; pRes0->nRefs++;
+            pObj->pFans[1] = 2*pRes1->Id; pRes1->nRefs++;
+            // call recursively
+            Kit_DsdDecompose_rec( pNtk, pRes0, uSupp0, pObj->pFans + 0, nDecMux );
+            Kit_DsdDecompose_rec( pNtk, pRes1, uSupp1, pObj->pFans + 1, nDecMux );
+            return;
+        }
+
+        // create the new node
+        pRes = Kit_DsdObjAlloc( pNtk, KIT_DSD_AND, 2 );
+        pRes->nRefs++;
+        pRes->nFans = 2;
+        pRes->pFans[0] = pObj->pFans[i];  pObj->pFans[i] = 127;  uSupp &= ~(1 << i);
+        pRes->pFans[1] = 2*pObj->Id;
+        // update the parent pointer
+        *pPar = Abc_LitNotCond( 2 * pRes->Id, Abc_LitIsCompl(*pPar) );
+        // consider different decompositions
+        if ( fEquals[0][0] )
+        {
+            Kit_TruthCopy( pTruth, pCofs2[1], pObj->nFans );
+        }
+        else if ( fEquals[0][1] )
+        {
+            pRes->pFans[0] = Abc_LitNot(pRes->pFans[0]);
+            Kit_TruthCopy( pTruth, pCofs2[0], pObj->nFans );
+        }
+        else if ( fEquals[1][0] )
+        {
+            *pPar = Abc_LitNot(*pPar);
+            pRes->pFans[1] = Abc_LitNot(pRes->pFans[1]);
+            Kit_TruthCopy( pTruth, pCofs2[1], pObj->nFans );
+        }
+        else if ( fEquals[1][1] )
+        {
+            *pPar = Abc_LitNot(*pPar);
+            pRes->pFans[0] = Abc_LitNot(pRes->pFans[0]);  
+            pRes->pFans[1] = Abc_LitNot(pRes->pFans[1]);
+            Kit_TruthCopy( pTruth, pCofs2[0], pObj->nFans );
+        }
+        else if ( fOppos )
+        {
+            pRes->Type = KIT_DSD_XOR;
+            Kit_TruthCopy( pTruth, pCofs2[0], pObj->nFans );
+        }
+        else
+            assert( 0 );
+        // decompose the remainder
+        assert( Kit_DsdObjTruth(pObj) == pTruth );
+        Kit_DsdDecompose_rec( pNtk, pObj, uSupp, pRes->pFans + 1, nDecMux );
+        return;
+    }
+    pObj->fMark = 1;
+
+    // decompose the input
+    for ( i = pObj->nFans - 1; i >= 0; i-- )
+    {
+        assert( Kit_TruthVarInSupport( pTruth, pObj->nFans, i ) );
+        // get the single variale cofactors
+        Kit_TruthCofactor0New( pCofs2[0], pTruth, pObj->nFans, i );
+        Kit_TruthCofactor1New( pCofs2[1], pTruth, pObj->nFans, i );
+        // check the existence of MUX decomposition
+        uSupp0 = Kit_TruthSupport( pCofs2[0], pObj->nFans );
+        uSupp1 = Kit_TruthSupport( pCofs2[1], pObj->nFans );
+        assert( uSupp == (uSupp0 | uSupp1 | (1<<i)) );
+        // if one of the cofs is a constant, it is time to check the output again
+        if ( uSupp0 == 0 || uSupp1 == 0 )
+        {
+            pObj->fMark = 0;
+            Kit_DsdDecompose_rec( pNtk, pObj, uSupp, pPar, nDecMux );
+            return;
+        }
+        assert( uSupp0 && uSupp1 );
+        // get the number of unique variables
+        nFans0 = Kit_WordCountOnes( uSupp0 & ~uSupp1 );
+        nFans1 = Kit_WordCountOnes( uSupp1 & ~uSupp0 );
+        if ( nFans0 == 1 && nFans1 == 1 )
+        {
+            // get the cofactors w.r.t. the unique variables
+            iLit0 = Kit_WordFindFirstBit( uSupp0 & ~uSupp1 );
+            iLit1 = Kit_WordFindFirstBit( uSupp1 & ~uSupp0 );
+            // get four cofactors                                        
+            Kit_TruthCofactor0New( pCofs4[0][0], pCofs2[0], pObj->nFans, iLit0 );
+            Kit_TruthCofactor1New( pCofs4[0][1], pCofs2[0], pObj->nFans, iLit0 );
+            Kit_TruthCofactor0New( pCofs4[1][0], pCofs2[1], pObj->nFans, iLit1 );
+            Kit_TruthCofactor1New( pCofs4[1][1], pCofs2[1], pObj->nFans, iLit1 );
+            // check existence conditions
+            fEquals[0][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[1][0], pObj->nFans );
+            fEquals[0][1] = Kit_TruthIsEqual( pCofs4[0][1], pCofs4[1][1], pObj->nFans );
+            fEquals[1][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[1][1], pObj->nFans );
+            fEquals[1][1] = Kit_TruthIsEqual( pCofs4[0][1], pCofs4[1][0], pObj->nFans );
+            if ( (fEquals[0][0] && fEquals[0][1]) || (fEquals[1][0] && fEquals[1][1]) )
+            {
+                // construct the MUX
+                pRes = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, 3 );
+                Kit_DsdObjTruth(pRes)[0] = 0xCACACACA;
+                pRes->nRefs++;
+                pRes->nFans = 3;
+                pRes->pFans[0] = pObj->pFans[iLit0]; pObj->pFans[iLit0] = 127;  uSupp &= ~(1 << iLit0);
+                pRes->pFans[1] = pObj->pFans[iLit1]; pObj->pFans[iLit1] = 127;  uSupp &= ~(1 << iLit1);
+                pRes->pFans[2] = pObj->pFans[i];     pObj->pFans[i] = 2 * pRes->Id; // remains in support
+                // update the node
+//                if ( fEquals[0][0] && fEquals[0][1] )
+//                    Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[0][1], pObj->nFans, i );
+//                else
+//                    Kit_TruthMuxVar( pTruth, pCofs4[0][1], pCofs4[0][0], pObj->nFans, i );
+                Kit_TruthMuxVar( pTruth, pCofs4[1][0], pCofs4[1][1], pObj->nFans, i );
+                if ( fEquals[1][0] && fEquals[1][1] )
+                    pRes->pFans[0] = Abc_LitNot(pRes->pFans[0]);
+                // decompose the remainder
+                Kit_DsdDecompose_rec( pNtk, pObj, uSupp, pPar, nDecMux );
+                return;
+            }
+        }
+
+        // try other inputs
+        for ( k = i+1; k < pObj->nFans; k++ )
+        {
+            // get four cofactors                                                ik
+            Kit_TruthCofactor0New( pCofs4[0][0], pCofs2[0], pObj->nFans, k ); // 00 
+            Kit_TruthCofactor1New( pCofs4[0][1], pCofs2[0], pObj->nFans, k ); // 01 
+            Kit_TruthCofactor0New( pCofs4[1][0], pCofs2[1], pObj->nFans, k ); // 10 
+            Kit_TruthCofactor1New( pCofs4[1][1], pCofs2[1], pObj->nFans, k ); // 11 
+            // compare equal pairs
+            fPairs[0][1] = fPairs[1][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[0][1], pObj->nFans );
+            fPairs[0][2] = fPairs[2][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[1][0], pObj->nFans );
+            fPairs[0][3] = fPairs[3][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[1][1], pObj->nFans );
+            fPairs[1][2] = fPairs[2][1] = Kit_TruthIsEqual( pCofs4[0][1], pCofs4[1][0], pObj->nFans );
+            fPairs[1][3] = fPairs[3][1] = Kit_TruthIsEqual( pCofs4[0][1], pCofs4[1][1], pObj->nFans );
+            fPairs[2][3] = fPairs[3][2] = Kit_TruthIsEqual( pCofs4[1][0], pCofs4[1][1], pObj->nFans );
+            nPairs = fPairs[0][1] + fPairs[0][2] + fPairs[0][3] + fPairs[1][2] + fPairs[1][3] + fPairs[2][3];
+            if ( nPairs != 3 && nPairs != 2 )
+                continue;
+
+            // decomposition exists
+            pRes = Kit_DsdObjAlloc( pNtk, KIT_DSD_AND, 2 );
+            pRes->nRefs++;
+            pRes->nFans = 2;
+            pRes->pFans[0] = pObj->pFans[k]; pObj->pFans[k] = 2 * pRes->Id;  // remains in support
+            pRes->pFans[1] = pObj->pFans[i]; pObj->pFans[i] = 127;       uSupp &= ~(1 << i);
+            if ( !fPairs[0][1] && !fPairs[0][2] && !fPairs[0][3] ) // 00
+            {
+                pRes->pFans[0] = Abc_LitNot(pRes->pFans[0]);  
+                pRes->pFans[1] = Abc_LitNot(pRes->pFans[1]);
+                Kit_TruthMuxVar( pTruth, pCofs4[1][1], pCofs4[0][0], pObj->nFans, k );
+            }
+            else if ( !fPairs[1][0] && !fPairs[1][2] && !fPairs[1][3] ) // 01
+            {
+                pRes->pFans[1] = Abc_LitNot(pRes->pFans[1]);  
+                Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[0][1], pObj->nFans, k );
+            }
+            else if ( !fPairs[2][0] && !fPairs[2][1] && !fPairs[2][3] ) // 10
+            {
+                pRes->pFans[0] = Abc_LitNot(pRes->pFans[0]);  
+                Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[1][0], pObj->nFans, k );
+            }
+            else if ( !fPairs[3][0] && !fPairs[3][1] && !fPairs[3][2] ) // 11
+            {
+//                unsigned uSupp0 = Kit_TruthSupport(pCofs4[0][0], pObj->nFans);
+//                unsigned uSupp1 = Kit_TruthSupport(pCofs4[1][1], pObj->nFans);
+//                unsigned uSupp;
+//                Extra_PrintBinary( stdout, &uSupp0, pObj->nFans ); printf( "\n" );
+//                Extra_PrintBinary( stdout, &uSupp1, pObj->nFans ); printf( "\n" );
+                Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[1][1], pObj->nFans, k );
+//                uSupp = Kit_TruthSupport(pTruth, pObj->nFans);
+//                Extra_PrintBinary( stdout, &uSupp, pObj->nFans ); printf( "\n" ); printf( "\n" );
+            }
+            else
+            {
+                assert( fPairs[0][3] && fPairs[1][2] );
+                pRes->Type = KIT_DSD_XOR;;
+                Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[0][1], pObj->nFans, k );
+            }
+            // decompose the remainder
+            Kit_DsdDecompose_rec( pNtk, pObj, uSupp, pPar, nDecMux );
+            return;
+        }
+    }
+
+    // if all decomposition methods failed and we are still above the limit, perform MUX-decomposition
+    if ( nDecMux > 0 && (int)pObj->nFans > nDecMux )
+    {
+        int iBestVar = Kit_TruthBestCofVar( pTruth, pObj->nFans, pCofs2[0], pCofs2[1] );
+        uSupp0 = Kit_TruthSupport( pCofs2[0], pObj->nFans );
+        uSupp1 = Kit_TruthSupport( pCofs2[1], pObj->nFans );
+        // perform MUX decomposition
+        pRes0 = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, pObj->nFans );
+        pRes1 = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, pObj->nFans );
+        for ( k = 0; k < pObj->nFans; k++ )
+            pRes0->pFans[k] = pRes1->pFans[k] = pObj->pFans[k];
+        Kit_TruthCopy( Kit_DsdObjTruth(pRes0), pCofs2[0], pObj->nFans );        
+        Kit_TruthCopy( Kit_DsdObjTruth(pRes1), pCofs2[1], pObj->nFans ); 
+        // update the current one
+        assert( pObj->Type == KIT_DSD_PRIME );
+        pTruth[0] = 0xCACACACA;
+        pObj->nFans = 3;
+        pObj->pFans[2] = pObj->pFans[iBestVar];
+        pObj->pFans[0] = 2*pRes0->Id; pRes0->nRefs++;
+        pObj->pFans[1] = 2*pRes1->Id; pRes1->nRefs++;
+        // call recursively
+        Kit_DsdDecompose_rec( pNtk, pRes0, uSupp0, pObj->pFans + 0, nDecMux );
+        Kit_DsdDecompose_rec( pNtk, pRes1, uSupp1, pObj->pFans + 1, nDecMux );
+    }
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs decomposition of the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_DsdNtk_t * Kit_DsdDecomposeInt( unsigned * pTruth, int nVars, int nDecMux )
+{
+    Kit_DsdNtk_t * pNtk;
+    Kit_DsdObj_t * pObj;
+    unsigned uSupp;
+    int i, nVarsReal;
+    assert( nVars <= 16 );
+    pNtk = Kit_DsdNtkAlloc( nVars );
+    pNtk->Root = Abc_Var2Lit( pNtk->nVars, 0 );
+    // create the first node
+    pObj = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, nVars );
+    assert( pNtk->pNodes[0] == pObj );
+    for ( i = 0; i < nVars; i++ )
+       pObj->pFans[i] = Abc_Var2Lit( i, 0 );
+    Kit_TruthCopy( Kit_DsdObjTruth(pObj), pTruth, nVars );
+    uSupp = Kit_TruthSupport( pTruth, nVars );
+    // consider special cases
+    nVarsReal = Kit_WordCountOnes( uSupp );
+    if ( nVarsReal == 0 )
+    {
+        pObj->Type = KIT_DSD_CONST1;
+        pObj->nFans = 0;
+        if ( pTruth[0] == 0 )
+             pNtk->Root = Abc_LitNot(pNtk->Root);
+        return pNtk;
+    }
+    if ( nVarsReal == 1 )
+    {
+        pObj->Type = KIT_DSD_VAR;
+        pObj->nFans = 1;
+        pObj->pFans[0] = Abc_Var2Lit( Kit_WordFindFirstBit(uSupp), (pTruth[0] & 1) );
+        return pNtk;
+    }
+    Kit_DsdDecompose_rec( pNtk, pNtk->pNodes[0], uSupp, &pNtk->Root, nDecMux );
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs decomposition of the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_DsdNtk_t * Kit_DsdDecompose( unsigned * pTruth, int nVars )
+{
+    return Kit_DsdDecomposeInt( pTruth, nVars, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs decomposition of the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_DsdNtk_t * Kit_DsdDecomposeExpand( unsigned * pTruth, int nVars )
+{
+    Kit_DsdNtk_t * pNtk, * pTemp;
+    pNtk = Kit_DsdDecomposeInt( pTruth, nVars, 0 );
+    pNtk = Kit_DsdExpand( pTemp = pNtk );      
+    Kit_DsdNtkFree( pTemp );
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs decomposition of the truth table.]
+
+  Description [Uses MUXes to break-down large prime nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_DsdNtk_t *  Kit_DsdDecomposeMux( unsigned * pTruth, int nVars, int nDecMux )
+{
+/*
+    Kit_DsdNtk_t * pNew;
+    Kit_DsdObj_t * pObjNew;
+    assert( nVars <= 16 );
+    // create a new network
+    pNew = Kit_DsdNtkAlloc( nVars );
+    // consider simple special cases
+    if ( nVars == 0 )
+    {
+        pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_CONST1, 0 );
+        pNew->Root = Abc_Var2Lit( pObjNew->Id, (int)(pTruth[0] == 0) );
+        return pNew;
+    }
+    if ( nVars == 1 )
+    {
+        pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_VAR, 1 );
+        pObjNew->pFans[0] = Abc_Var2Lit( 0, 0 );
+        pNew->Root = Abc_Var2Lit( pObjNew->Id, (int)(pTruth[0] != 0xAAAAAAAA) );
+        return pNew;
+    }
+*/
+    return Kit_DsdDecomposeInt( pTruth, nVars, nDecMux );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs decomposition of the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DsdTestCofs( Kit_DsdNtk_t * pNtk, unsigned * pTruthInit )
+{
+    Kit_DsdNtk_t * pNtk0, * pNtk1, * pTemp;
+//    Kit_DsdObj_t * pRoot;
+    unsigned * pCofs2[2] = { pNtk->pMem, pNtk->pMem + Kit_TruthWordNum(pNtk->nVars) };
+    unsigned i, * pTruth;
+    int fVerbose = 1;
+    int RetValue = 0;
+
+    pTruth = pTruthInit;
+//    pRoot = Kit_DsdNtkRoot(pNtk);
+//    pTruth = Kit_DsdObjTruth(pRoot);
+//    assert( pRoot->nFans == pNtk->nVars );
+
+    if ( fVerbose )
+    {
+        printf( "Function: " );
+//        Extra_PrintBinary( stdout, pTruth, (1 << pNtk->nVars) ); 
+        Extra_PrintHexadecimal( stdout, pTruth, pNtk->nVars ); 
+        printf( "\n" );
+        Kit_DsdPrint( stdout, pNtk ), printf( "\n" );
+    }
+    for ( i = 0; i < pNtk->nVars; i++ )
+    {
+        Kit_TruthCofactor0New( pCofs2[0], pTruth, pNtk->nVars, i );
+        pNtk0 = Kit_DsdDecompose( pCofs2[0], pNtk->nVars );
+        pNtk0 = Kit_DsdExpand( pTemp = pNtk0 );
+        Kit_DsdNtkFree( pTemp );
+
+        if ( fVerbose )
+        {
+            printf( "Cof%d0: ", i );
+            Kit_DsdPrint( stdout, pNtk0 ), printf( "\n" );
+        }
+
+        Kit_TruthCofactor1New( pCofs2[1], pTruth, pNtk->nVars, i );
+        pNtk1 = Kit_DsdDecompose( pCofs2[1], pNtk->nVars );
+        pNtk1 = Kit_DsdExpand( pTemp = pNtk1 );
+        Kit_DsdNtkFree( pTemp );
+
+        if ( fVerbose )
+        {
+            printf( "Cof%d1: ", i );
+            Kit_DsdPrint( stdout, pNtk1 ), printf( "\n" );
+        }
+
+//        if ( Kit_DsdCheckVar4Dec2( pNtk0, pNtk1 ) )
+//            RetValue = 1;
+
+        Kit_DsdNtkFree( pNtk0 );
+        Kit_DsdNtkFree( pNtk1 );
+    }
+    if ( fVerbose )
+        printf( "\n" );
+
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs decomposition of the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DsdEval( unsigned * pTruth, int nVars, int nLutSize )
+{
+    Kit_DsdMan_t * p;
+    Kit_DsdNtk_t * pNtk;
+    unsigned * pTruthC;
+    int Result;
+
+    // decompose the function
+    pNtk = Kit_DsdDecompose( pTruth, nVars );
+    Result = Kit_DsdCountLuts( pNtk, nLutSize );
+//    printf( "\n" );
+//    Kit_DsdPrint( stdout, pNtk );
+//    printf( "Eval = %d.\n", Result );
+
+    // recompute the truth table
+    p = Kit_DsdManAlloc( nVars, Kit_DsdNtkObjNum(pNtk) );
+    pTruthC = Kit_DsdTruthCompute( p, pNtk );
+    if ( !Kit_TruthIsEqual( pTruth, pTruthC, nVars ) )
+        printf( "Verification failed.\n" );
+    Kit_DsdManFree( p );
+
+    Kit_DsdNtkFree( pNtk );
+    return Result;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs decomposition of the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdVerify( Kit_DsdNtk_t * pNtk, unsigned * pTruth, int nVars )
+{
+    Kit_DsdMan_t * p;
+    unsigned * pTruthC;
+    p = Kit_DsdManAlloc( nVars, Kit_DsdNtkObjNum(pNtk)+2 );
+    pTruthC = Kit_DsdTruthCompute( p, pNtk );
+    if ( !Extra_TruthIsEqual( pTruth, pTruthC, nVars ) )
+        printf( "Verification failed.\n" );
+    Kit_DsdManFree( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs decomposition of the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdTest( unsigned * pTruth, int nVars )
+{
+    Kit_DsdMan_t * p;
+    unsigned * pTruthC;
+    Kit_DsdNtk_t * pNtk, * pTemp;
+    pNtk = Kit_DsdDecompose( pTruth, nVars );
+
+//    if ( Kit_DsdFindLargeBox(pNtk, Abc_Lit2Var(pNtk->Root)) )
+//        Kit_DsdPrint( stdout, pNtk );
+
+//    if ( Kit_DsdNtkRoot(pNtk)->nFans == (unsigned)nVars && nVars == 6 )
+
+//    printf( "\n" );
+//    Kit_DsdPrint( stdout, pNtk );
+
+    pNtk = Kit_DsdExpand( pTemp = pNtk );
+    Kit_DsdNtkFree( pTemp );
+
+    Kit_DsdPrint( stdout, pNtk ), printf( "\n" );
+
+//    if ( Kit_DsdFindLargeBox(pNtk, Abc_Lit2Var(pNtk->Root)) )
+//        Kit_DsdTestCofs( pNtk, pTruth );
+
+    // recompute the truth table
+    p = Kit_DsdManAlloc( nVars, Kit_DsdNtkObjNum(pNtk) );
+    pTruthC = Kit_DsdTruthCompute( p, pNtk );
+//    Extra_PrintBinary( stdout, pTruth, 1 << nVars ); printf( "\n" );
+//    Extra_PrintBinary( stdout, pTruthC, 1 << nVars ); printf( "\n" );
+    if ( Extra_TruthIsEqual( pTruth, pTruthC, nVars ) )
+    {
+//        printf( "Verification is okay.\n" );
+    }
+    else
+        printf( "Verification failed.\n" );
+    Kit_DsdManFree( p );
+
+
+    Kit_DsdNtkFree( pNtk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs decomposition of the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdPrecompute4Vars()
+{
+    Kit_DsdMan_t * p;
+    Kit_DsdNtk_t * pNtk, * pTemp;
+    FILE * pFile;
+    unsigned uTruth;
+    unsigned * pTruthC;
+    char Buffer[256];
+    int i, RetValue;
+    int Counter1 = 0, Counter2 = 0;
+
+    pFile = fopen( "5npn/npn4.txt", "r" );
+    for ( i = 0; fgets( Buffer, 100, pFile ); i++ )
+    {
+        Buffer[6] = 0;
+        Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 );
+        uTruth = ((uTruth & 0xffff) << 16) | (uTruth & 0xffff);
+        pNtk = Kit_DsdDecompose( &uTruth, 4 );
+
+        pNtk = Kit_DsdExpand( pTemp = pNtk );
+        Kit_DsdNtkFree( pTemp );
+
+
+        if ( Kit_DsdFindLargeBox(pNtk, 3) )
+        {
+//            RetValue = 0;
+            RetValue = Kit_DsdTestCofs( pNtk, &uTruth );
+            printf( "\n" );
+            printf( "%3d : Non-DSD function  %s  %s\n", i, Buffer + 2, RetValue? "implementable" : "" );
+            Kit_DsdPrint( stdout, pNtk ), printf( "\n" );
+
+            Counter1++;
+            Counter2 += RetValue;
+        }
+
+/*
+        printf( "%3d : Function  %s   ", i, Buffer + 2 );
+        if ( !Kit_DsdFindLargeBox(pNtk, 3) )
+            Kit_DsdPrint( stdout, pNtk );
+        else
+            printf( "\n" );
+*/
+
+        p = Kit_DsdManAlloc( 4, Kit_DsdNtkObjNum(pNtk) );
+        pTruthC = Kit_DsdTruthCompute( p, pNtk );
+        if ( !Extra_TruthIsEqual( &uTruth, pTruthC, 4 ) )
+            printf( "Verification failed.\n" );
+        Kit_DsdManFree( p );
+
+        Kit_DsdNtkFree( pNtk );
+    }
+    fclose( pFile );
+    printf( "non-DSD = %d   implementable = %d\n", Counter1, Counter2 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the set of cofactoring variables.]
+
+  Description [If there is no DSD components returns 0.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DsdCofactoringGetVars( Kit_DsdNtk_t ** ppNtk, int nSize, int * pVars )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned m;
+    int i, k, v, Var, nVars, iFaninLit;
+    // go through all the networks
+    nVars = 0;
+    for ( i = 0; i < nSize; i++ )
+    {
+        // go through the prime objects of each networks
+        Kit_DsdNtkForEachObj( ppNtk[i], pObj, k )     
+        {
+            if ( pObj->Type != KIT_DSD_PRIME )
+                continue;
+            if ( pObj->nFans == 3 )
+                continue;
+            // collect direct fanin variables
+            Kit_DsdObjForEachFanin( ppNtk[i], pObj, iFaninLit, m )
+            {
+                if ( !Kit_DsdLitIsLeaf(ppNtk[i], iFaninLit) )
+                    continue;
+                // add it to the array
+                Var = Abc_Lit2Var( iFaninLit );
+                for ( v = 0; v < nVars; v++ )
+                    if ( pVars[v] == Var )
+                        break;
+                if ( v == nVars )
+                    pVars[nVars++] = Var;
+            }
+        }
+    }
+    return nVars;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Canonical decomposition into completely DSD-structure.]
+
+  Description [Returns the number of cofactoring steps. Also returns
+  the cofactoring variables in pVars.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_DsdCofactoring( unsigned * pTruth, int nVars, int * pCofVars, int nLimit, int fVerbose )
+{
+    Kit_DsdNtk_t * ppNtks[5][16] = {
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
+    };
+    Kit_DsdNtk_t * pTemp;
+    unsigned * ppCofs[5][16];
+    int pTryVars[16], nTryVars;
+    int nPrimeSizeMin, nPrimeSizeMax, nPrimeSizeCur;
+    int nSuppSizeMin, nSuppSizeMax, iVarBest;
+    int i, k, v, nStep, nSize, nMemSize;
+    assert( nLimit < 5 );
+
+    // allocate storage for cofactors
+    nMemSize = Kit_TruthWordNum(nVars);
+    ppCofs[0][0] = ABC_ALLOC( unsigned, 80 * nMemSize );
+    nSize = 0;
+    for ( i = 0; i <  5; i++ )
+    for ( k = 0; k < 16; k++ )
+        ppCofs[i][k] = ppCofs[0][0] + nMemSize * nSize++;
+    assert( nSize == 80 );
+
+    // copy the function
+    Kit_TruthCopy( ppCofs[0][0], pTruth, nVars );
+    ppNtks[0][0] = Kit_DsdDecompose( ppCofs[0][0], nVars );
+
+    if ( fVerbose )
+        printf( "\nProcessing prime function with %d support variables:\n", nVars );
+
+    // perform recursive cofactoring
+    for ( nStep = 0; nStep < nLimit; nStep++ )
+    {
+        nSize = (1 << nStep);
+        // find the variables to use in the cofactoring step
+        nTryVars = Kit_DsdCofactoringGetVars( ppNtks[nStep], nSize, pTryVars );
+        if ( nTryVars == 0 )
+            break;
+        // cofactor w.r.t. the above variables
+        iVarBest = -1;
+        nPrimeSizeMin = 10000;
+        nSuppSizeMin  = 10000;
+        for ( v = 0; v < nTryVars; v++ )
+        {
+            nPrimeSizeMax = 0;
+            nSuppSizeMax = 0;
+            for ( i = 0; i < nSize; i++ )
+            {
+                // cofactor and decompose cofactors          
+                Kit_TruthCofactor0New( ppCofs[nStep+1][2*i+0], ppCofs[nStep][i], nVars, pTryVars[v] );
+                Kit_TruthCofactor1New( ppCofs[nStep+1][2*i+1], ppCofs[nStep][i], nVars, pTryVars[v] );
+                ppNtks[nStep+1][2*i+0] = Kit_DsdDecompose( ppCofs[nStep+1][2*i+0], nVars );
+                ppNtks[nStep+1][2*i+1] = Kit_DsdDecompose( ppCofs[nStep+1][2*i+1], nVars );
+                // compute the largest non-decomp block
+                nPrimeSizeCur  = Kit_DsdNonDsdSizeMax(ppNtks[nStep+1][2*i+0]);
+                nPrimeSizeMax  = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur );
+                nPrimeSizeCur  = Kit_DsdNonDsdSizeMax(ppNtks[nStep+1][2*i+1]);
+                nPrimeSizeMax  = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur );
+                // compute the sum total of supports
+                nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nStep+1][2*i+0], nVars );
+                nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nStep+1][2*i+1], nVars );
+                // free the networks
+                Kit_DsdNtkFree( ppNtks[nStep+1][2*i+0] );
+                Kit_DsdNtkFree( ppNtks[nStep+1][2*i+1] );
+            }
+            // find the min max support size of the prime component
+            if ( nPrimeSizeMin > nPrimeSizeMax || (nPrimeSizeMin == nPrimeSizeMax && nSuppSizeMin > nSuppSizeMax) )
+            {
+                nPrimeSizeMin = nPrimeSizeMax;
+                nSuppSizeMin  = nSuppSizeMax;
+                iVarBest      = pTryVars[v];
+            }
+        }
+        assert( iVarBest != -1 );
+        // save the variable
+        if ( pCofVars )
+            pCofVars[nStep] = iVarBest;
+        // cofactor w.r.t. the best
+        for ( i = 0; i < nSize; i++ )
+        {
+            Kit_TruthCofactor0New( ppCofs[nStep+1][2*i+0], ppCofs[nStep][i], nVars, iVarBest );
+            Kit_TruthCofactor1New( ppCofs[nStep+1][2*i+1], ppCofs[nStep][i], nVars, iVarBest );
+            ppNtks[nStep+1][2*i+0] = Kit_DsdDecompose( ppCofs[nStep+1][2*i+0], nVars );
+            ppNtks[nStep+1][2*i+1] = Kit_DsdDecompose( ppCofs[nStep+1][2*i+1], nVars );
+            if ( fVerbose )
+            {
+                ppNtks[nStep+1][2*i+0] = Kit_DsdExpand( pTemp = ppNtks[nStep+1][2*i+0] );
+                Kit_DsdNtkFree( pTemp );
+                ppNtks[nStep+1][2*i+1] = Kit_DsdExpand( pTemp = ppNtks[nStep+1][2*i+1] );
+                Kit_DsdNtkFree( pTemp );
+
+                printf( "Cof%d%d: ", nStep+1, 2*i+0 );
+                Kit_DsdPrint( stdout, ppNtks[nStep+1][2*i+0] ), printf( "\n" );
+                printf( "Cof%d%d: ", nStep+1, 2*i+1 );
+                Kit_DsdPrint( stdout, ppNtks[nStep+1][2*i+1] ), printf( "\n" );
+            }
+        }
+    }
+
+    // free the networks
+    for ( i = 0; i <  5; i++ )
+    for ( k = 0; k < 16; k++ )
+        if ( ppNtks[i][k] )
+            Kit_DsdNtkFree( ppNtks[i][k] );
+    ABC_FREE( ppCofs[0][0] );
+
+    assert( nStep <= nLimit );
+    return nStep;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Canonical decomposition into completely DSD-structure.]
+
+  Description [Returns the number of cofactoring steps. Also returns
+  the cofactoring variables in pVars.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_DsdPrintCofactors( unsigned * pTruth, int nVars, int nCofLevel, int fVerbose )
+{
+    Kit_DsdNtk_t * ppNtks[32] = {0}, * pTemp;
+    unsigned * ppCofs[5][16];
+    int piCofVar[5];
+    int nPrimeSizeMax, nPrimeSizeCur, nSuppSizeMax;
+    int i, k, v1, v2, v3, v4, s, nSteps, nSize, nMemSize;
+    assert( nCofLevel < 5 );
+
+    // print the function
+    ppNtks[0] = Kit_DsdDecompose( pTruth, nVars );
+    ppNtks[0] = Kit_DsdExpand( pTemp = ppNtks[0] );
+    Kit_DsdNtkFree( pTemp );
+    if ( fVerbose )
+        Kit_DsdPrint( stdout, ppNtks[0] ), printf( "\n" );
+    Kit_DsdNtkFree( ppNtks[0] );
+
+    // allocate storage for cofactors
+    nMemSize = Kit_TruthWordNum(nVars);
+    ppCofs[0][0] = ABC_ALLOC( unsigned, 80 * nMemSize );
+    nSize = 0;
+    for ( i = 0; i <  5; i++ )
+    for ( k = 0; k < 16; k++ )
+        ppCofs[i][k] = ppCofs[0][0] + nMemSize * nSize++;
+    assert( nSize == 80 );
+
+    // copy the function
+    Kit_TruthCopy( ppCofs[0][0], pTruth, nVars );
+
+    if ( nCofLevel == 1 )
+    for ( v1 = 0; v1 < nVars; v1++ )
+    {
+        nSteps = 0;
+        piCofVar[nSteps++] = v1;
+
+        printf( "    Variables { " );
+        for ( i = 0; i < nSteps; i++ )
+            printf( "%c ", 'a' + piCofVar[i] );
+        printf( "}\n" );
+
+        // single cofactors
+        for ( s = 1; s <= nSteps; s++ )
+        {
+            for ( k = 0; k < s; k++ )
+            {
+                nSize = (1 << k);
+                for ( i = 0; i < nSize; i++ )
+                {
+                    Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] );
+                    Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] );
+                }
+            }
+        }
+        // compute DSD networks
+        nSize = (1 << nSteps);
+        nPrimeSizeMax = 0;
+        nSuppSizeMax = 0;
+        for ( i = 0; i < nSize; i++ )
+        {
+            ppNtks[i] = Kit_DsdDecompose( ppCofs[nSteps][i], nVars );
+            ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] );
+            Kit_DsdNtkFree( pTemp );
+            if ( fVerbose )
+            {
+                printf( "Cof%d%d: ", nSteps, i );
+                Kit_DsdPrint( stdout, ppNtks[i] ), printf( "\n" );
+            }
+            // compute the largest non-decomp block
+            nPrimeSizeCur  = Kit_DsdNonDsdSizeMax(ppNtks[i]);
+            nPrimeSizeMax  = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur );
+            Kit_DsdNtkFree( ppNtks[i] );
+            nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nSteps][i], nVars );
+        }
+        printf( "Max = %2d. Supps = %2d.\n", nPrimeSizeMax, nSuppSizeMax );
+    }
+
+    if ( nCofLevel == 2 )
+    for ( v1 = 0; v1 < nVars; v1++ )
+    for ( v2 = v1+1; v2 < nVars; v2++ )
+    {
+        nSteps = 0;
+        piCofVar[nSteps++] = v1;
+        piCofVar[nSteps++] = v2;
+
+        printf( "    Variables { " );
+        for ( i = 0; i < nSteps; i++ )
+            printf( "%c ", 'a' + piCofVar[i] );
+        printf( "}\n" );
+
+        // single cofactors
+        for ( s = 1; s <= nSteps; s++ )
+        {
+            for ( k = 0; k < s; k++ )
+            {
+                nSize = (1 << k);
+                for ( i = 0; i < nSize; i++ )
+                {
+                    Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] );
+                    Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] );
+                }
+            }
+        }
+        // compute DSD networks
+        nSize = (1 << nSteps);
+        nPrimeSizeMax = 0;
+        nSuppSizeMax = 0;
+        for ( i = 0; i < nSize; i++ )
+        {
+            ppNtks[i] = Kit_DsdDecompose( ppCofs[nSteps][i], nVars );
+            ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] );
+            Kit_DsdNtkFree( pTemp );
+            if ( fVerbose )
+            {
+                printf( "Cof%d%d: ", nSteps, i );
+                Kit_DsdPrint( stdout, ppNtks[i] ), printf( "\n" );
+            }
+            // compute the largest non-decomp block
+            nPrimeSizeCur  = Kit_DsdNonDsdSizeMax(ppNtks[i]);
+            nPrimeSizeMax  = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur );
+            Kit_DsdNtkFree( ppNtks[i] );
+            nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nSteps][i], nVars );
+        }
+        printf( "Max = %2d. Supps = %2d.\n", nPrimeSizeMax, nSuppSizeMax );
+    }
+
+    if ( nCofLevel == 3 )
+    for ( v1 = 0; v1 < nVars; v1++ )
+    for ( v2 = v1+1; v2 < nVars; v2++ )
+    for ( v3 = v2+1; v3 < nVars; v3++ )
+    {
+        nSteps = 0;
+        piCofVar[nSteps++] = v1;
+        piCofVar[nSteps++] = v2;
+        piCofVar[nSteps++] = v3;
+
+        printf( "    Variables { " );
+        for ( i = 0; i < nSteps; i++ )
+            printf( "%c ", 'a' + piCofVar[i] );
+        printf( "}\n" );
+
+        // single cofactors
+        for ( s = 1; s <= nSteps; s++ )
+        {
+            for ( k = 0; k < s; k++ )
+            {
+                nSize = (1 << k);
+                for ( i = 0; i < nSize; i++ )
+                {
+                    Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] );
+                    Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] );
+                }
+            }
+        }
+        // compute DSD networks
+        nSize = (1 << nSteps);
+        nPrimeSizeMax = 0;
+        nSuppSizeMax = 0;
+        for ( i = 0; i < nSize; i++ )
+        {
+            ppNtks[i] = Kit_DsdDecompose( ppCofs[nSteps][i], nVars );
+            ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] );
+            Kit_DsdNtkFree( pTemp );
+            if ( fVerbose )
+            {
+                printf( "Cof%d%d: ", nSteps, i );
+                Kit_DsdPrint( stdout, ppNtks[i] ), printf( "\n" );
+            }
+            // compute the largest non-decomp block
+            nPrimeSizeCur  = Kit_DsdNonDsdSizeMax(ppNtks[i]);
+            nPrimeSizeMax  = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur );
+            Kit_DsdNtkFree( ppNtks[i] );
+            nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nSteps][i], nVars );
+        }
+        printf( "Max = %2d. Supps = %2d.\n", nPrimeSizeMax, nSuppSizeMax );
+    }
+
+    if ( nCofLevel == 4 )
+    for ( v1 = 0; v1 < nVars; v1++ )
+    for ( v2 = v1+1; v2 < nVars; v2++ )
+    for ( v3 = v2+1; v3 < nVars; v3++ )
+    for ( v4 = v3+1; v4 < nVars; v4++ )
+    {
+        nSteps = 0;
+        piCofVar[nSteps++] = v1;
+        piCofVar[nSteps++] = v2;
+        piCofVar[nSteps++] = v3;
+        piCofVar[nSteps++] = v4;
+
+        printf( "    Variables { " );
+        for ( i = 0; i < nSteps; i++ )
+            printf( "%c ", 'a' + piCofVar[i] );
+        printf( "}\n" );
+
+        // single cofactors
+        for ( s = 1; s <= nSteps; s++ )
+        {
+            for ( k = 0; k < s; k++ )
+            {
+                nSize = (1 << k);
+                for ( i = 0; i < nSize; i++ )
+                {
+                    Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] );
+                    Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] );
+                }
+            }
+        }
+        // compute DSD networks
+        nSize = (1 << nSteps);
+        nPrimeSizeMax = 0;
+        nSuppSizeMax = 0;
+        for ( i = 0; i < nSize; i++ )
+        {
+            ppNtks[i] = Kit_DsdDecompose( ppCofs[nSteps][i], nVars );
+            ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] );
+            Kit_DsdNtkFree( pTemp );
+            if ( fVerbose )
+            {
+                printf( "Cof%d%d: ", nSteps, i );
+                Kit_DsdPrint( stdout, ppNtks[i] ), printf( "\n" );
+            }
+            // compute the largest non-decomp block
+            nPrimeSizeCur  = Kit_DsdNonDsdSizeMax(ppNtks[i]);
+            nPrimeSizeMax  = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur );
+            Kit_DsdNtkFree( ppNtks[i] );
+            nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nSteps][i], nVars );
+        }
+        printf( "Max = %2d. Supps = %2d.\n", nPrimeSizeMax, nSuppSizeMax );
+    }
+
+
+    ABC_FREE( ppCofs[0][0] );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char ** Kit_DsdNpn4ClassNames()
+{
+    static const char * pNames[222] = {
+        "F = 0",                     /*   0 */ 
+        "F = (!d*(!c*(!b*!a)))",     /*   1 */
+        "F = (!d*(!c*!b))",          /*   2 */
+        "F = (!d*(!c*(b+a)))",       /*   3 */
+        "F = (!d*(!c*!(b*a)))",      /*   4 */
+        "F = (!d*!c)",               /*   5 */
+        "F = (!d*16(a,b,c))",        /*   6 */
+        "F = (!d*17(a,b,c))",        /*   7 */
+        "F = (!d*18(a,b,c))",        /*   8 */
+        "F = (!d*19(a,b,c))",        /*   9 */
+        "F = (!d*CA(!b,!c,a))",      /*  10 */
+        "F = (!d*(c+!(!b*!a)))",     /*  11 */
+        "F = (!d*!(c*!(!b*!a)))",    /*  12 */
+        "F = (!d*(c+b))",            /*  13 */
+        "F = (!d*3D(a,b,c))",        /*  14 */
+        "F = (!d*!(c*b))",           /*  15 */
+        "F = (!d*(c+(b+!a)))",       /*  16 */
+        "F = (!d*6B(a,b,c))",        /*  17 */
+        "F = (!d*!(c*!(b+a)))",      /*  18 */
+        "F = (!d*7E(a,b,c))",        /*  19 */
+        "F = (!d*!(c*(b*a)))",       /*  20 */
+        "F = (!d)",                  /*  21 */
+        "F = 0116(a,b,c,d)",         /*  22 */
+        "F = 0117(a,b,c,d)",         /*  23 */
+        "F = 0118(a,b,c,d)",         /*  24 */
+        "F = 0119(a,b,c,d)",         /*  25 */
+        "F = 011A(a,b,c,d)",         /*  26 */
+        "F = 011B(a,b,c,d)",         /*  27 */
+        "F = 29((!b*!a),c,d)",       /*  28 */
+        "F = 2B((!b*!a),c,d)",       /*  29 */
+        "F = 012C(a,b,c,d)",         /*  30 */
+        "F = 012D(a,b,c,d)",         /*  31 */
+        "F = 012F(a,b,c,d)",         /*  32 */
+        "F = 013C(a,b,c,d)",         /*  33 */
+        "F = 013D(a,b,c,d)",         /*  34 */
+        "F = 013E(a,b,c,d)",         /*  35 */
+        "F = 013F(a,b,c,d)",         /*  36 */
+        "F = 0168(a,b,c,d)",         /*  37 */
+        "F = 0169(a,b,c,d)",         /*  38 */
+        "F = 016A(a,b,c,d)",         /*  39 */
+        "F = 016B(a,b,c,d)",         /*  40 */
+        "F = 016E(a,b,c,d)",         /*  41 */
+        "F = 016F(a,b,c,d)",         /*  42 */
+        "F = 017E(a,b,c,d)",         /*  43 */
+        "F = 017F(a,b,c,d)",         /*  44 */
+        "F = 0180(a,b,c,d)",         /*  45 */
+        "F = 0181(a,b,c,d)",         /*  46 */
+        "F = 0182(a,b,c,d)",         /*  47 */
+        "F = 0183(a,b,c,d)",         /*  48 */
+        "F = 0186(a,b,c,d)",         /*  49 */
+        "F = 0187(a,b,c,d)",         /*  50 */
+        "F = 0189(a,b,c,d)",         /*  51 */
+        "F = 018B(a,b,c,d)",         /*  52 */
+        "F = 018F(a,b,c,d)",         /*  53 */
+        "F = 0196(a,b,c,d)",         /*  54 */
+        "F = 0197(a,b,c,d)",         /*  55 */
+        "F = 0198(a,b,c,d)",         /*  56 */
+        "F = 0199(a,b,c,d)",         /*  57 */
+        "F = 019A(a,b,c,d)",         /*  58 */
+        "F = 019B(a,b,c,d)",         /*  59 */
+        "F = 019E(a,b,c,d)",         /*  60 */
+        "F = 019F(a,b,c,d)",         /*  61 */
+        "F = 42(a,(!c*!b),d)",       /*  62 */
+        "F = 46(a,(!c*!b),d)",       /*  63 */
+        "F = 4A(a,(!c*!b),d)",       /*  64 */
+        "F = CA((!c*!b),!d,a)",      /*  65 */
+        "F = 01AC(a,b,c,d)",         /*  66 */
+        "F = 01AD(a,b,c,d)",         /*  67 */
+        "F = 01AE(a,b,c,d)",         /*  68 */
+        "F = 01AF(a,b,c,d)",         /*  69 */
+        "F = 01BC(a,b,c,d)",         /*  70 */
+        "F = 01BD(a,b,c,d)",         /*  71 */
+        "F = 01BE(a,b,c,d)",         /*  72 */
+        "F = 01BF(a,b,c,d)",         /*  73 */
+        "F = 01E8(a,b,c,d)",         /*  74 */
+        "F = 01E9(a,b,c,d)",         /*  75 */
+        "F = 01EA(a,b,c,d)",         /*  76 */
+        "F = 01EB(a,b,c,d)",         /*  77 */
+        "F = 25((!b*!a),c,d)",       /*  78 */
+        "F = !CA(d,c,(!b*!a))",      /*  79 */
+        "F = (d+!(!c*(!b*!a)))",     /*  80 */
+        "F = 16(b,c,d)",             /*  81 */
+        "F = 033D(a,b,c,d)",         /*  82 */
+        "F = 17(b,c,d)",             /*  83 */
+        "F = ((!d*!a)+(!c*!b))",     /*  84 */
+        "F = !(!(!c*!b)*!(!d*!a))",  /*  85 */
+        "F = 0358(a,b,c,d)",         /*  86 */
+        "F = 0359(a,b,c,d)",         /*  87 */
+        "F = 035A(a,b,c,d)",         /*  88 */
+        "F = 035B(a,b,c,d)",         /*  89 */
+        "F = 035E(a,b,c,d)",         /*  90 */
+        "F = 035F(a,b,c,d)",         /*  91 */
+        "F = 0368(a,b,c,d)",         /*  92 */
+        "F = 0369(a,b,c,d)",         /*  93 */
+        "F = 036A(a,b,c,d)",         /*  94 */
+        "F = 036B(a,b,c,d)",         /*  95 */
+        "F = 036C(a,b,c,d)",         /*  96 */
+        "F = 036D(a,b,c,d)",         /*  97 */
+        "F = 036E(a,b,c,d)",         /*  98 */
+        "F = 036F(a,b,c,d)",         /*  99 */
+        "F = 037C(a,b,c,d)",         /* 100 */
+        "F = 037D(a,b,c,d)",         /* 101 */
+        "F = 037E(a,b,c,d)",         /* 102 */
+        "F = 18(b,c,d)",             /* 103 */
+        "F = 03C1(a,b,c,d)",         /* 104 */
+        "F = 19(b,c,d)",             /* 105 */
+        "F = 03C5(a,b,c,d)",         /* 106 */
+        "F = 03C6(a,b,c,d)",         /* 107 */
+        "F = 03C7(a,b,c,d)",         /* 108 */
+        "F = CA(!c,!d,b)",           /* 109 */
+        "F = 03D4(a,b,c,d)",         /* 110 */
+        "F = 03D5(a,b,c,d)",         /* 111 */
+        "F = 03D6(a,b,c,d)",         /* 112 */
+        "F = 03D7(a,b,c,d)",         /* 113 */
+        "F = 03D8(a,b,c,d)",         /* 114 */
+        "F = 03D9(a,b,c,d)",         /* 115 */
+        "F = 03DB(a,b,c,d)",         /* 116 */
+        "F = 03DC(a,b,c,d)",         /* 117 */
+        "F = 03DD(a,b,c,d)",         /* 118 */
+        "F = 03DE(a,b,c,d)",         /* 119 */
+        "F = (d+!(!c*!b))",          /* 120 */
+        "F = ((d+c)*(b+a))",         /* 121 */
+        "F = 0661(a,b,c,d)",         /* 122 */
+        "F = 0662(a,b,c,d)",         /* 123 */
+        "F = 0663(a,b,c,d)",         /* 124 */
+        "F = (!(d*c)*(b+a))",        /* 125 */
+        "F = 0667(a,b,c,d)",         /* 126 */
+        "F = 29((b+a),c,d)",         /* 127 */
+        "F = 066B(a,b,c,d)",         /* 128 */
+        "F = 2B((b+a),c,d)",         /* 129 */
+        "F = 0672(a,b,c,d)",         /* 130 */
+        "F = 0673(a,b,c,d)",         /* 131 */
+        "F = 0676(a,b,c,d)",         /* 132 */
+        "F = 0678(a,b,c,d)",         /* 133 */
+        "F = 0679(a,b,c,d)",         /* 134 */
+        "F = 067A(a,b,c,d)",         /* 135 */
+        "F = 067B(a,b,c,d)",         /* 136 */
+        "F = 067E(a,b,c,d)",         /* 137 */
+        "F = 24((b+a),c,d)",         /* 138 */
+        "F = 0691(a,b,c,d)",         /* 139 */
+        "F = 0693(a,b,c,d)",         /* 140 */
+        "F = 26((b+a),c,d)",         /* 141 */
+        "F = 0697(a,b,c,d)",         /* 142 */
+        "F = !CA(d,c,(b+a))",        /* 143 */
+        "F = 06B0(a,b,c,d)",         /* 144 */
+        "F = 06B1(a,b,c,d)",         /* 145 */
+        "F = 06B2(a,b,c,d)",         /* 146 */
+        "F = 06B3(a,b,c,d)",         /* 147 */
+        "F = 06B4(a,b,c,d)",         /* 148 */
+        "F = 06B5(a,b,c,d)",         /* 149 */
+        "F = 06B6(a,b,c,d)",         /* 150 */
+        "F = 06B7(a,b,c,d)",         /* 151 */
+        "F = 06B9(a,b,c,d)",         /* 152 */
+        "F = 06BD(a,b,c,d)",         /* 153 */
+        "F = 2C((b+a),c,d)",         /* 154 */
+        "F = 06F1(a,b,c,d)",         /* 155 */
+        "F = 06F2(a,b,c,d)",         /* 156 */
+        "F = CA((b+a),!d,c)",        /* 157 */
+        "F = (d+!(!c*!(b+!a)))",     /* 158 */
+        "F = 0776(a,b,c,d)",         /* 159 */
+        "F = 16((b*a),c,d)",         /* 160 */
+        "F = 0779(a,b,c,d)",         /* 161 */
+        "F = 077A(a,b,c,d)",         /* 162 */
+        "F = 077E(a,b,c,d)",         /* 163 */
+        "F = 07B0(a,b,c,d)",         /* 164 */
+        "F = 07B1(a,b,c,d)",         /* 165 */
+        "F = 07B4(a,b,c,d)",         /* 166 */
+        "F = 07B5(a,b,c,d)",         /* 167 */
+        "F = 07B6(a,b,c,d)",         /* 168 */
+        "F = 07BC(a,b,c,d)",         /* 169 */
+        "F = 07E0(a,b,c,d)",         /* 170 */
+        "F = 07E1(a,b,c,d)",         /* 171 */
+        "F = 07E2(a,b,c,d)",         /* 172 */
+        "F = 07E3(a,b,c,d)",         /* 173 */
+        "F = 07E6(a,b,c,d)",         /* 174 */
+        "F = 07E9(a,b,c,d)",         /* 175 */
+        "F = 1C((b*a),c,d)",         /* 176 */
+        "F = 07F1(a,b,c,d)",         /* 177 */
+        "F = 07F2(a,b,c,d)",         /* 178 */
+        "F = (d+!(!c*!(b*a)))",      /* 179 */
+        "F = (d+c)",                 /* 180 */
+        "F = 1668(a,b,c,d)",         /* 181 */
+        "F = 1669(a,b,c,d)",         /* 182 */
+        "F = 166A(a,b,c,d)",         /* 183 */
+        "F = 166B(a,b,c,d)",         /* 184 */
+        "F = 166E(a,b,c,d)",         /* 185 */
+        "F = 167E(a,b,c,d)",         /* 186 */
+        "F = 1681(a,b,c,d)",         /* 187 */
+        "F = 1683(a,b,c,d)",         /* 188 */
+        "F = 1686(a,b,c,d)",         /* 189 */
+        "F = 1687(a,b,c,d)",         /* 190 */
+        "F = 1689(a,b,c,d)",         /* 191 */
+        "F = 168B(a,b,c,d)",         /* 192 */
+        "F = 168E(a,b,c,d)",         /* 193 */
+        "F = 1696(a,b,c,d)",         /* 194 */
+        "F = 1697(a,b,c,d)",         /* 195 */
+        "F = 1698(a,b,c,d)",         /* 196 */
+        "F = 1699(a,b,c,d)",         /* 197 */
+        "F = 169A(a,b,c,d)",         /* 198 */
+        "F = 169B(a,b,c,d)",         /* 199 */
+        "F = 169E(a,b,c,d)",         /* 200 */
+        "F = 16A9(a,b,c,d)",         /* 201 */
+        "F = 16AC(a,b,c,d)",         /* 202 */
+        "F = 16AD(a,b,c,d)",         /* 203 */
+        "F = 16BC(a,b,c,d)",         /* 204 */
+        "F = (d+E9(a,b,c))",         /* 205 */
+        "F = 177E(a,b,c,d)",         /* 206 */
+        "F = 178E(a,b,c,d)",         /* 207 */
+        "F = 1796(a,b,c,d)",         /* 208 */
+        "F = 1798(a,b,c,d)",         /* 209 */
+        "F = 179A(a,b,c,d)",         /* 210 */
+        "F = 17AC(a,b,c,d)",         /* 211 */
+        "F = (d+E8(a,b,c))",         /* 212 */
+        "F = (d+E7(a,b,c))",         /* 213 */
+        "F = 19E1(a,b,c,d)",         /* 214 */
+        "F = 19E3(a,b,c,d)",         /* 215 */
+        "F = (d+E6(a,b,c))",         /* 216 */
+        "F = 1BD8(a,b,c,d)",         /* 217 */
+        "F = (d+CA(b,c,a))",         /* 218 */
+        "F = (d+(c+(!b*!a)))",       /* 219 */
+        "F = (d+(c+!b))",            /* 220 */
+        "F = (d+(c+(b+a)))"          /* 221 */
+    };
+    return (char **)pNames;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/kit/kitFactor.c b/abc-build/src/bool/kit/kitFactor.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/kitFactor.c
@@ -0,0 +1,344 @@
+/**CFile****************************************************************
+
+  FileName    [kitFactor.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Computation kit.]
+
+  Synopsis    [Algebraic factoring.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 6, 2006.]
+
+  Revision    [$Id: kitFactor.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// factoring fails if intermediate memory usage exceed this limit
+#define KIT_FACTOR_MEM_LIMIT  (1<<20)
+
+static Kit_Edge_t  Kit_SopFactor_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory );
+static Kit_Edge_t  Kit_SopFactorLF_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, Kit_Sop_t * cSimple, int nLits, Vec_Int_t * vMemory );
+static Kit_Edge_t  Kit_SopFactorTrivial( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits );
+static Kit_Edge_t  Kit_SopFactorTrivialCube( Kit_Graph_t * pFForm, unsigned uCube, int nLits );
+
+extern int         Kit_SopFactorVerify( Vec_Int_t * cSop, Kit_Graph_t * pFForm, int nVars );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Factors the cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_Graph_t * Kit_SopFactor( Vec_Int_t * vCover, int fCompl, int nVars, Vec_Int_t * vMemory )
+{
+    Kit_Sop_t Sop, * cSop = &Sop;
+    Kit_Graph_t * pFForm;
+    Kit_Edge_t eRoot;
+//    int nCubes;
+
+    // works for up to 15 variables because division procedure
+    // used the last bit for marking the cubes going to the remainder
+    assert( nVars < 16 );
+
+    // check for trivial functions
+    if ( Vec_IntSize(vCover) == 0 )
+        return Kit_GraphCreateConst0();
+    if ( Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover, 0) == 0 )
+        return Kit_GraphCreateConst1();
+
+    // prepare memory manager
+//    Vec_IntClear( vMemory );
+    Vec_IntGrow( vMemory, KIT_FACTOR_MEM_LIMIT );
+
+    // perform CST
+    Kit_SopCreateInverse( cSop, vCover, 2 * nVars, vMemory ); // CST
+
+    // start the factored form
+    pFForm = Kit_GraphCreate( nVars );
+    // factor the cover
+    eRoot = Kit_SopFactor_rec( pFForm, cSop, 2 * nVars, vMemory );
+    // finalize the factored form
+    Kit_GraphSetRoot( pFForm, eRoot );
+    if ( fCompl )
+        Kit_GraphComplement( pFForm );
+
+    // verify the factored form
+//    nCubes = Vec_IntSize(vCover);
+//    Vec_IntShrink( vCover, nCubes );
+//    if ( !Kit_SopFactorVerify( vCover, pFForm, nVars ) )
+//        printf( "Verification has failed.\n" );
+    return pFForm;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursive factoring procedure.]
+
+  Description [For the pseudo-code, see Hachtel/Somenzi, 
+  Logic synthesis and verification algorithms, Kluwer, 1996, p. 432.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_Edge_t Kit_SopFactor_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory )
+{
+    Kit_Sop_t Div, Quo, Rem, Com;
+    Kit_Sop_t * cDiv = &Div, * cQuo = &Quo, * cRem = &Rem, * cCom = &Com;
+    Kit_Edge_t eNodeDiv, eNodeQuo, eNodeRem, eNodeAnd;
+
+    // make sure the cover contains some cubes
+    assert( Kit_SopCubeNum(cSop) > 0 );
+
+    // get the divisor
+    if ( !Kit_SopDivisor(cDiv, cSop, nLits, vMemory) )
+        return Kit_SopFactorTrivial( pFForm, cSop, nLits );
+
+    // divide the cover by the divisor
+    Kit_SopDivideInternal( cSop, cDiv, cQuo, cRem, vMemory );
+
+    // check the trivial case
+    assert( Kit_SopCubeNum(cQuo) > 0 );
+    if ( Kit_SopCubeNum(cQuo) == 1 )
+        return Kit_SopFactorLF_rec( pFForm, cSop, cQuo, nLits, vMemory );
+
+    // make the quotient cube ABC_FREE
+    Kit_SopMakeCubeFree( cQuo );
+
+    // divide the cover by the quotient
+    Kit_SopDivideInternal( cSop, cQuo, cDiv, cRem, vMemory );
+
+    // check the trivial case
+    if ( Kit_SopIsCubeFree( cDiv ) )
+    {
+        eNodeDiv = Kit_SopFactor_rec( pFForm, cDiv, nLits, vMemory );
+        eNodeQuo = Kit_SopFactor_rec( pFForm, cQuo, nLits, vMemory );
+        eNodeAnd = Kit_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo );
+        if ( Kit_SopCubeNum(cRem) == 0 )
+            return eNodeAnd;
+        eNodeRem = Kit_SopFactor_rec( pFForm, cRem, nLits, vMemory );
+        return Kit_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem );
+    }
+
+    // get the common cube
+    Kit_SopCommonCubeCover( cCom, cDiv, vMemory );
+
+    // solve the simple problem
+    return Kit_SopFactorLF_rec( pFForm, cSop, cCom, nLits, vMemory );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Internal recursive factoring procedure for the leaf case.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_Edge_t Kit_SopFactorLF_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, Kit_Sop_t * cSimple, int nLits, Vec_Int_t * vMemory )
+{
+    Kit_Sop_t Div, Quo, Rem;
+    Kit_Sop_t * cDiv = &Div, * cQuo = &Quo, * cRem = &Rem;
+    Kit_Edge_t eNodeDiv, eNodeQuo, eNodeRem, eNodeAnd;
+    assert( Kit_SopCubeNum(cSimple) == 1 );
+    // get the most often occurring literal
+    Kit_SopBestLiteralCover( cDiv, cSop, Kit_SopCube(cSimple, 0), nLits, vMemory );
+    // divide the cover by the literal
+    Kit_SopDivideByCube( cSop, cDiv, cQuo, cRem, vMemory );
+    // get the node pointer for the literal
+    eNodeDiv = Kit_SopFactorTrivialCube( pFForm, Kit_SopCube(cDiv, 0), nLits );
+    // factor the quotient and remainder
+    eNodeQuo = Kit_SopFactor_rec( pFForm, cQuo, nLits, vMemory );
+    eNodeAnd = Kit_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo );
+    if ( Kit_SopCubeNum(cRem) == 0 )
+        return eNodeAnd;
+    eNodeRem = Kit_SopFactor_rec( pFForm, cRem, nLits, vMemory );
+    return Kit_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Factoring cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_Edge_t Kit_SopFactorTrivialCube_rec( Kit_Graph_t * pFForm, unsigned uCube, int nStart, int nFinish )
+{
+    Kit_Edge_t eNode1, eNode2;
+    int i, iLit = -1, nLits, nLits1, nLits2;
+    assert( uCube );
+    // count the number of literals in this interval
+    nLits = 0;
+    for ( i = nStart; i < nFinish; i++ )
+        if ( Kit_CubeHasLit(uCube, i) )
+        {
+            iLit = i;
+            nLits++;
+        }
+    assert( iLit != -1 );
+    // quit if there is only one literal        
+    if ( nLits == 1 )
+        return Kit_EdgeCreate( iLit/2, iLit%2 ); // CST
+    // split the literals into two parts
+    nLits1 = nLits/2;
+    nLits2 = nLits - nLits1;
+//    nLits2 = nLits/2;
+//    nLits1 = nLits - nLits2;
+    // find the splitting point
+    nLits = 0;
+    for ( i = nStart; i < nFinish; i++ )
+        if ( Kit_CubeHasLit(uCube, i) )
+        {
+            if ( nLits == nLits1 )
+                break;
+            nLits++;
+        }
+    // recursively construct the tree for the parts
+    eNode1 = Kit_SopFactorTrivialCube_rec( pFForm, uCube, nStart, i  );
+    eNode2 = Kit_SopFactorTrivialCube_rec( pFForm, uCube, i, nFinish );
+    return Kit_GraphAddNodeAnd( pFForm, eNode1, eNode2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Factoring cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_Edge_t Kit_SopFactorTrivialCube( Kit_Graph_t * pFForm, unsigned uCube, int nLits )
+{
+    return Kit_SopFactorTrivialCube_rec( pFForm, uCube, 0, nLits );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Factoring SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_Edge_t Kit_SopFactorTrivial_rec( Kit_Graph_t * pFForm, unsigned * pCubes, int nCubes, int nLits )
+{
+    Kit_Edge_t eNode1, eNode2;
+    int nCubes1, nCubes2;
+    if ( nCubes == 1 )
+        return Kit_SopFactorTrivialCube_rec( pFForm, pCubes[0], 0, nLits );
+    // split the cubes into two parts
+    nCubes1 = nCubes/2;
+    nCubes2 = nCubes - nCubes1;
+//    nCubes2 = nCubes/2;
+//    nCubes1 = nCubes - nCubes2;
+    // recursively construct the tree for the parts
+    eNode1 = Kit_SopFactorTrivial_rec( pFForm, pCubes,           nCubes1, nLits );
+    eNode2 = Kit_SopFactorTrivial_rec( pFForm, pCubes + nCubes1, nCubes2, nLits );
+    return Kit_GraphAddNodeOr( pFForm, eNode1, eNode2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Factoring the cover, which has no algebraic divisors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_Edge_t Kit_SopFactorTrivial( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits )
+{
+    return Kit_SopFactorTrivial_rec( pFForm, cSop->pCubes, cSop->nCubes, nLits );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Testing procedure for the factoring code.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_FactorTest( unsigned * pTruth, int nVars )
+{
+    Vec_Int_t * vCover, * vMemory;
+    Kit_Graph_t * pGraph;
+//    unsigned uTruthRes;
+    int RetValue;
+
+    // derive SOP
+    vCover = Vec_IntAlloc( 0 );
+    RetValue = Kit_TruthIsop( pTruth, nVars, vCover, 0 );
+    assert( RetValue == 0 );
+
+    // derive factored form
+    vMemory = Vec_IntAlloc( 0 );
+    pGraph = Kit_SopFactor( vCover, 0, nVars, vMemory );
+/*
+    // derive truth table
+    assert( nVars <= 5 );
+    uTruthRes = Kit_GraphToTruth( pGraph );
+    if ( uTruthRes != pTruth[0] )
+        printf( "Verification failed!" );
+*/
+    printf( "Vars = %2d. Cubes = %3d. FFNodes = %3d. FF_memory = %3d.\n",
+        nVars, Vec_IntSize(vCover), Kit_GraphNodeNum(pGraph), Vec_IntSize(vMemory) );
+
+    Vec_IntFree( vMemory );
+    Vec_IntFree( vCover );
+    Kit_GraphFree( pGraph );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/kit/kitGraph.c b/abc-build/src/bool/kit/kitGraph.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/kitGraph.c
@@ -0,0 +1,402 @@
+/**CFile****************************************************************
+
+  FileName    [kitGraph.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Computation kit.]
+
+  Synopsis    [Decomposition graph representation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 6, 2006.]
+
+  Revision    [$Id: kitGraph.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a graph with the given number of leaves.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_Graph_t * Kit_GraphCreate( int nLeaves )   
+{
+    Kit_Graph_t * pGraph;
+    pGraph = ABC_ALLOC( Kit_Graph_t, 1 );
+    memset( pGraph, 0, sizeof(Kit_Graph_t) );
+    pGraph->nLeaves = nLeaves;
+    pGraph->nSize = nLeaves;
+    pGraph->nCap = 2 * nLeaves + 50;
+    pGraph->pNodes = ABC_ALLOC( Kit_Node_t, pGraph->nCap );
+    memset( pGraph->pNodes, 0, sizeof(Kit_Node_t) * pGraph->nSize );
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates constant 0 graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_Graph_t * Kit_GraphCreateConst0()   
+{
+    Kit_Graph_t * pGraph;
+    pGraph = ABC_ALLOC( Kit_Graph_t, 1 );
+    memset( pGraph, 0, sizeof(Kit_Graph_t) );
+    pGraph->fConst = 1;
+    pGraph->eRoot.fCompl = 1;
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates constant 1 graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_Graph_t * Kit_GraphCreateConst1()   
+{
+    Kit_Graph_t * pGraph;
+    pGraph = ABC_ALLOC( Kit_Graph_t, 1 );
+    memset( pGraph, 0, sizeof(Kit_Graph_t) );
+    pGraph->fConst = 1;
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the literal graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_Graph_t * Kit_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl )   
+{
+    Kit_Graph_t * pGraph;
+    assert( 0 <= iLeaf && iLeaf < nLeaves );
+    pGraph = Kit_GraphCreate( nLeaves );
+    pGraph->eRoot.Node   = iLeaf;
+    pGraph->eRoot.fCompl = fCompl;
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a graph with the given number of leaves.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_GraphFree( Kit_Graph_t * pGraph )   
+{
+    ABC_FREE( pGraph->pNodes );
+    ABC_FREE( pGraph );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Appends a new node to the graph.]
+
+  Description [This procedure is meant for internal use.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_Node_t * Kit_GraphAppendNode( Kit_Graph_t * pGraph )   
+{
+    Kit_Node_t * pNode;
+    if ( pGraph->nSize == pGraph->nCap )
+    {
+        pGraph->pNodes = ABC_REALLOC( Kit_Node_t, pGraph->pNodes, 2 * pGraph->nCap ); 
+        pGraph->nCap   = 2 * pGraph->nCap;
+    }
+    pNode = pGraph->pNodes + pGraph->nSize++;
+    memset( pNode, 0, sizeof(Kit_Node_t) );
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates an AND node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_Edge_t Kit_GraphAddNodeAnd( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1 )
+{
+    Kit_Node_t * pNode;
+    // get the new node
+    pNode = Kit_GraphAppendNode( pGraph );
+    // set the inputs and other info
+    pNode->eEdge0 = eEdge0;
+    pNode->eEdge1 = eEdge1;
+    pNode->fCompl0 = eEdge0.fCompl;
+    pNode->fCompl1 = eEdge1.fCompl;
+    return Kit_EdgeCreate( pGraph->nSize - 1, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates an OR node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_Edge_t Kit_GraphAddNodeOr( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1 )
+{
+    Kit_Node_t * pNode;
+    // get the new node
+    pNode = Kit_GraphAppendNode( pGraph );
+    // set the inputs and other info
+    pNode->eEdge0 = eEdge0;
+    pNode->eEdge1 = eEdge1;
+    pNode->fCompl0 = eEdge0.fCompl;
+    pNode->fCompl1 = eEdge1.fCompl;
+    // make adjustments for the OR gate
+    pNode->fNodeOr = 1;
+    pNode->eEdge0.fCompl = !pNode->eEdge0.fCompl;
+    pNode->eEdge1.fCompl = !pNode->eEdge1.fCompl;
+    return Kit_EdgeCreate( pGraph->nSize - 1, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates an XOR node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_Edge_t Kit_GraphAddNodeXor( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1, int Type )
+{
+    Kit_Edge_t eNode0, eNode1, eNode;
+    if ( Type == 0 )
+    {
+        // derive the first AND
+        eEdge0.fCompl ^= 1;
+        eNode0 = Kit_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+        eEdge0.fCompl ^= 1;
+        // derive the second AND
+        eEdge1.fCompl ^= 1;
+        eNode1 = Kit_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+        // derive the final OR
+        eNode = Kit_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+    }
+    else
+    {
+        // derive the first AND
+        eNode0 = Kit_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+        // derive the second AND
+        eEdge0.fCompl ^= 1;
+        eEdge1.fCompl ^= 1;
+        eNode1 = Kit_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+        // derive the final OR
+        eNode = Kit_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+        eNode.fCompl ^= 1;
+    }
+    return eNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates an XOR node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_Edge_t Kit_GraphAddNodeMux( Kit_Graph_t * pGraph, Kit_Edge_t eEdgeC, Kit_Edge_t eEdgeT, Kit_Edge_t eEdgeE, int Type )
+{
+    Kit_Edge_t eNode0, eNode1, eNode;
+    if ( Type == 0 )
+    {
+        // derive the first AND
+        eNode0 = Kit_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
+        // derive the second AND
+        eEdgeC.fCompl ^= 1;
+        eNode1 = Kit_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
+        // derive the final OR
+        eNode = Kit_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+    }
+    else
+    {
+        // complement the arguments
+        eEdgeT.fCompl ^= 1;
+        eEdgeE.fCompl ^= 1;
+        // derive the first AND
+        eNode0 = Kit_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
+        // derive the second AND
+        eEdgeC.fCompl ^= 1;
+        eNode1 = Kit_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
+        // derive the final OR
+        eNode = Kit_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+        eNode.fCompl ^= 1;
+    }
+    return eNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Kit_GraphToTruth( Kit_Graph_t * pGraph )
+{
+    unsigned uTruths[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+    unsigned uTruth = 0, uTruth0, uTruth1;
+    Kit_Node_t * pNode;
+    int i;
+
+    // sanity checks
+    assert( Kit_GraphLeaveNum(pGraph) >= 0 );
+    assert( Kit_GraphLeaveNum(pGraph) <= pGraph->nSize );
+    assert( Kit_GraphLeaveNum(pGraph) <= 5 );
+
+    // check for constant function
+    if ( Kit_GraphIsConst(pGraph) )
+        return Kit_GraphIsComplement(pGraph)? 0 : ~((unsigned)0);
+    // check for a literal
+    if ( Kit_GraphIsVar(pGraph) )
+        return Kit_GraphIsComplement(pGraph)? ~uTruths[Kit_GraphVarInt(pGraph)] : uTruths[Kit_GraphVarInt(pGraph)];
+
+    // assign the elementary variables
+    Kit_GraphForEachLeaf( pGraph, pNode, i )
+        pNode->pFunc = (void *)(long)uTruths[i];
+
+    // compute the function for each internal node
+    Kit_GraphForEachNode( pGraph, pNode, i )
+    {
+        uTruth0 = (unsigned)(long)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc;
+        uTruth1 = (unsigned)(long)Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc;
+        uTruth0 = pNode->eEdge0.fCompl? ~uTruth0 : uTruth0;
+        uTruth1 = pNode->eEdge1.fCompl? ~uTruth1 : uTruth1;
+        uTruth = uTruth0 & uTruth1;
+        pNode->pFunc = (void *)(long)uTruth;
+    }
+
+    // complement the result if necessary
+    return Kit_GraphIsComplement(pGraph)? ~uTruth : uTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the factored form from the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Kit_Graph_t * Kit_TruthToGraph( unsigned * pTruth, int nVars, Vec_Int_t * vMemory )
+{
+    Kit_Graph_t * pGraph;
+    int RetValue;
+    // derive SOP
+    RetValue = Kit_TruthIsop( pTruth, nVars, vMemory, 1 ); // tried 1 and found not useful in "renode"
+    if ( RetValue == -1 )
+        return NULL;
+    if ( Vec_IntSize(vMemory) > (1<<16) )
+        return NULL;
+//    printf( "Isop size = %d.\n", Vec_IntSize(vMemory) );
+    assert( RetValue == 0 || RetValue == 1 );
+    // derive factored form
+    pGraph = Kit_SopFactor( vMemory, RetValue, nVars, vMemory );
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the maximum depth from the leaf to the root.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_GraphLeafDepth_rec( Kit_Graph_t * pGraph, Kit_Node_t * pNode, Kit_Node_t * pLeaf )
+{
+    int Depth0, Depth1, Depth;
+    if ( pNode == pLeaf )
+        return 0;
+    if ( Kit_GraphNodeIsVar(pGraph, pNode) )
+        return -100;
+    Depth0 = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeFanin0(pGraph, pNode), pLeaf );
+    Depth1 = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeFanin1(pGraph, pNode), pLeaf );
+    Depth = KIT_MAX( Depth0, Depth1 );
+    Depth = (Depth == -100) ? -100 : Depth + 1;
+    return Depth;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/kit/kitHop.c b/abc-build/src/bool/kit/kitHop.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/kitHop.c
@@ -0,0 +1,200 @@
+/**CFile****************************************************************
+
+  FileName    [kitHop.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Computation kit.]
+
+  Synopsis    [Procedures involving AIGs.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 6, 2006.]
+
+  Revision    [$Id: kitHop.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "kit.h"
+#include "aig/hop/hop.h"
+#include "aig/gia/gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the decomposition graph into the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_GraphToGiaInternal( Gia_Man_t * pMan, Kit_Graph_t * pGraph, int fHash )
+{
+    Kit_Node_t * pNode = NULL;
+    int i, pAnd0, pAnd1;
+    // check for constant function
+    if ( Kit_GraphIsConst(pGraph) )
+        return Abc_LitNotCond( 1, Kit_GraphIsComplement(pGraph) );
+    // check for a literal
+    if ( Kit_GraphIsVar(pGraph) )
+        return Abc_LitNotCond( Kit_GraphVar(pGraph)->iFunc, Kit_GraphIsComplement(pGraph) );
+    // build the AIG nodes corresponding to the AND gates of the graph
+    Kit_GraphForEachNode( pGraph, pNode, i )
+    {
+        pAnd0 = Abc_LitNotCond( Kit_GraphNode(pGraph, pNode->eEdge0.Node)->iFunc, pNode->eEdge0.fCompl ); 
+        pAnd1 = Abc_LitNotCond( Kit_GraphNode(pGraph, pNode->eEdge1.Node)->iFunc, pNode->eEdge1.fCompl ); 
+        if ( fHash )
+            pNode->iFunc = Gia_ManHashAnd( pMan, pAnd0, pAnd1 );
+        else
+            pNode->iFunc = Gia_ManAppendAnd( pMan, pAnd0, pAnd1 );
+    }
+    // complement the result if necessary
+    return Abc_LitNotCond( pNode->iFunc, Kit_GraphIsComplement(pGraph) );
+}
+int Kit_GraphToGia( Gia_Man_t * pMan, Kit_Graph_t * pGraph, Vec_Int_t * vLeaves, int fHash )
+{
+    Kit_Node_t * pNode = NULL;
+    int i;
+    // collect the fanins
+    Kit_GraphForEachLeaf( pGraph, pNode, i )
+        pNode->iFunc = vLeaves ? Vec_IntEntry(vLeaves, i) : Gia_Obj2Lit(pMan, Gia_ManPi(pMan, i));
+    // perform strashing
+    return Kit_GraphToGiaInternal( pMan, pGraph, fHash );
+}
+int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash )
+{
+    int iLit;
+    Kit_Graph_t * pGraph;
+    // transform truth table into the decomposition tree
+    if ( vMemory == NULL )
+    {
+        vMemory = Vec_IntAlloc( 0 );
+        pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory );
+        Vec_IntFree( vMemory );
+    }
+    else
+        pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory );
+    if ( pGraph == NULL )
+    {
+        printf( "Kit_TruthToGia(): Converting truth table to AIG has failed for function:\n" );
+        Kit_DsdPrintFromTruth( pTruth, nVars ); printf( "\n" );
+    }
+    // derive the AIG for the decomposition tree
+    iLit = Kit_GraphToGia( pMan, pGraph, vLeaves, fHash );
+    Kit_GraphFree( pGraph );
+    return iLit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the decomposition graph into the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Kit_GraphToHopInternal( Hop_Man_t * pMan, Kit_Graph_t * pGraph )
+{
+    Kit_Node_t * pNode = NULL;
+    Hop_Obj_t * pAnd0, * pAnd1;
+    int i;
+    // check for constant function
+    if ( Kit_GraphIsConst(pGraph) )
+        return Hop_NotCond( Hop_ManConst1(pMan), Kit_GraphIsComplement(pGraph) );
+    // check for a literal
+    if ( Kit_GraphIsVar(pGraph) )
+        return Hop_NotCond( (Hop_Obj_t *)Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) );
+    // build the AIG nodes corresponding to the AND gates of the graph
+    Kit_GraphForEachNode( pGraph, pNode, i )
+    {
+        pAnd0 = Hop_NotCond( (Hop_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); 
+        pAnd1 = Hop_NotCond( (Hop_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); 
+        pNode->pFunc = Hop_And( pMan, pAnd0, pAnd1 );
+    }
+    // complement the result if necessary
+    return Hop_NotCond( (Hop_Obj_t *)pNode->pFunc, Kit_GraphIsComplement(pGraph) );
+}
+Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph )
+{
+    Kit_Node_t * pNode = NULL;
+    int i;
+    // collect the fanins
+    Kit_GraphForEachLeaf( pGraph, pNode, i )
+        pNode->pFunc = Hop_IthVar( pMan, i );
+    // perform strashing
+    return Kit_GraphToHopInternal( pMan, pGraph );
+}
+Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory )
+{
+    Hop_Obj_t * pObj;
+    Kit_Graph_t * pGraph;
+    // transform truth table into the decomposition tree
+    if ( vMemory == NULL )
+    {
+        vMemory = Vec_IntAlloc( 0 );
+        pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory );
+        Vec_IntFree( vMemory );
+    }
+    else
+        pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory );
+    if ( pGraph == NULL )
+    {
+        printf( "Kit_TruthToHop(): Converting truth table to AIG has failed for function:\n" );
+        Kit_DsdPrintFromTruth( pTruth, nVars ); printf( "\n" );
+    }
+    // derive the AIG for the decomposition tree
+    pObj = Kit_GraphToHop( pMan, pGraph );
+    Kit_GraphFree( pGraph );
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes one logic node using its SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Kit_CoverToHop( Hop_Man_t * pMan, Vec_Int_t * vCover, int nVars, Vec_Int_t * vMemory )
+{
+    Kit_Graph_t * pGraph;
+    Hop_Obj_t * pFunc;
+    // perform factoring
+    Vec_IntClear( vMemory );
+    pGraph = Kit_SopFactor( vCover, 0, nVars, vMemory );
+    // convert graph to the AIG
+    pFunc = Kit_GraphToHop( pMan, pGraph );
+    Kit_GraphFree( pGraph );
+    return pFunc;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/kit/kitIsop.c b/abc-build/src/bool/kit/kitIsop.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/kitIsop.c
@@ -0,0 +1,365 @@
+/**CFile****************************************************************
+
+  FileName    [kitIsop.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Computation kit.]
+
+  Synopsis    [ISOP computation based on Morreale's algorithm.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 6, 2006.]
+
+  Revision    [$Id: kitIsop.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// ISOP computation fails if intermediate memory usage exceed this limit
+#define KIT_ISOP_MEM_LIMIT  (1<<20)
+
+// static procedures to compute ISOP
+static unsigned * Kit_TruthIsop_rec( unsigned * puOn, unsigned * puOnDc, int nVars, Kit_Sop_t * pcRes, Vec_Int_t * vStore );
+static unsigned   Kit_TruthIsop5_rec( unsigned uOn, unsigned uOnDc, int nVars, Kit_Sop_t * pcRes, Vec_Int_t * vStore );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes ISOP from TT.]
+
+  Description [Returns the cover in vMemory. Uses the rest of array in vMemory
+  as an intermediate memory storage. Returns the cover with -1 cubes, if the
+  the computation exceeded the memory limit (KIT_ISOP_MEM_LIMIT words of
+  intermediate data).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_TruthIsop( unsigned * puTruth, int nVars, Vec_Int_t * vMemory, int fTryBoth )
+{
+    Kit_Sop_t cRes, * pcRes = &cRes;
+    Kit_Sop_t cRes2, * pcRes2 = &cRes2;
+    unsigned * pResult;
+    int RetValue = 0;
+    assert( nVars >= 0 && nVars < 16 );
+    // if nVars < 5, make sure it does not depend on those vars
+//    for ( i = nVars; i < 5; i++ )
+//        assert( !Kit_TruthVarInSupport(puTruth, 5, i) );
+    // prepare memory manager
+    Vec_IntClear( vMemory );
+    Vec_IntGrow( vMemory, KIT_ISOP_MEM_LIMIT );
+    // compute ISOP for the direct polarity
+    pResult = Kit_TruthIsop_rec( puTruth, puTruth, nVars, pcRes, vMemory );
+    if ( pcRes->nCubes == -1 )
+    {
+        vMemory->nSize = -1;
+        return -1;
+    }
+    assert( Kit_TruthIsEqual( puTruth, pResult, nVars ) );
+    if ( pcRes->nCubes == 0 || (pcRes->nCubes == 1 && pcRes->pCubes[0] == 0) )
+    {
+        vMemory->pArray[0] = 0;
+        Vec_IntShrink( vMemory, pcRes->nCubes );
+        return 0;
+    }
+    if ( fTryBoth )
+    {
+        // compute ISOP for the complemented polarity
+        Kit_TruthNot( puTruth, puTruth, nVars );
+        pResult = Kit_TruthIsop_rec( puTruth, puTruth, nVars, pcRes2, vMemory );
+        if ( pcRes2->nCubes >= 0 )
+        {
+            assert( Kit_TruthIsEqual( puTruth, pResult, nVars ) );
+            if ( pcRes->nCubes > pcRes2->nCubes || (pcRes->nCubes == pcRes2->nCubes && pcRes->nLits > pcRes2->nLits) )
+            {
+                RetValue = 1;
+                pcRes = pcRes2;
+            }
+        }
+        Kit_TruthNot( puTruth, puTruth, nVars );
+    }
+//    printf( "%d ", vMemory->nSize );
+    // move the cover representation to the beginning of the memory buffer
+    memmove( vMemory->pArray, pcRes->pCubes, pcRes->nCubes * sizeof(unsigned) );
+    Vec_IntShrink( vMemory, pcRes->nCubes );
+    return RetValue;
+}
+void Kit_TruthIsopPrintCover( Vec_Int_t * vCover, int nVars, int fCompl )
+{
+    int i, k, Entry, Literal;
+    if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover, 0) == 0) )
+    {
+        printf( "Constant %d\n", Vec_IntSize(vCover) );
+        return;
+    }
+    Vec_IntForEachEntry( vCover, Entry, i )
+    { 
+        for ( k = 0; k < nVars; k++ )
+        {
+            Literal = 3 & (Entry >> (k << 1));
+            if ( Literal == 1 ) // neg literal
+                printf( "0" );
+            else if ( Literal == 2 ) // pos literal
+                printf( "1" );
+            else if ( Literal == 0 ) 
+                printf( "-" );
+            else assert( 0 );
+        }
+        printf( " %d\n", !fCompl );
+    }
+}
+void Kit_TruthIsopPrint( unsigned * puTruth, int nVars, Vec_Int_t * vCover, int fTryBoth )
+{
+    int fCompl = Kit_TruthIsop( puTruth, nVars, vCover, fTryBoth );
+    Kit_TruthIsopPrintCover( vCover, nVars, fCompl );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes ISOP 6 variables or more.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Kit_TruthIsop_rec( unsigned * puOn, unsigned * puOnDc, int nVars, Kit_Sop_t * pcRes, Vec_Int_t * vStore )
+{
+    Kit_Sop_t cRes0, cRes1, cRes2;
+    Kit_Sop_t * pcRes0 = &cRes0, * pcRes1 = &cRes1, * pcRes2 = &cRes2;
+    unsigned * puRes0, * puRes1, * puRes2;
+    unsigned * puOn0, * puOn1, * puOnDc0, * puOnDc1, * pTemp, * pTemp0, * pTemp1;
+    int i, k, Var, nWords, nWordsAll;
+//    assert( Kit_TruthIsImply( puOn, puOnDc, nVars ) );
+    // allocate room for the resulting truth table
+    nWordsAll = Kit_TruthWordNum( nVars );
+    pTemp = Vec_IntFetch( vStore, nWordsAll );
+    if ( pTemp == NULL )
+    {
+        pcRes->nCubes = -1;
+        return NULL;
+    }
+    // check for constants
+    if ( Kit_TruthIsConst0( puOn, nVars ) )
+    {
+        pcRes->nLits  = 0;
+        pcRes->nCubes = 0;
+        pcRes->pCubes = NULL;
+        Kit_TruthClear( pTemp, nVars );
+        return pTemp;
+    }
+    if ( Kit_TruthIsConst1( puOnDc, nVars ) )
+    {
+        pcRes->nLits  = 0;
+        pcRes->nCubes = 1;
+        pcRes->pCubes = Vec_IntFetch( vStore, 1 );
+        if ( pcRes->pCubes == NULL )
+        {
+            pcRes->nCubes = -1;
+            return NULL;
+        }
+        pcRes->pCubes[0] = 0;
+        Kit_TruthFill( pTemp, nVars );
+        return pTemp;
+    }
+    assert( nVars > 0 );
+    // find the topmost var
+    for ( Var = nVars-1; Var >= 0; Var-- )
+        if ( Kit_TruthVarInSupport( puOn, nVars, Var ) || 
+             Kit_TruthVarInSupport( puOnDc, nVars, Var ) )
+             break;
+    assert( Var >= 0 );
+    // consider a simple case when one-word computation can be used
+    if ( Var < 5 )
+    {
+        unsigned uRes = Kit_TruthIsop5_rec( puOn[0], puOnDc[0], Var+1, pcRes, vStore );
+        for ( i = 0; i < nWordsAll; i++ )
+            pTemp[i] = uRes;
+        return pTemp;
+    }
+    assert( Var >= 5 );
+    nWords = Kit_TruthWordNum( Var );
+    // cofactor
+    puOn0   = puOn;    puOn1   = puOn + nWords;
+    puOnDc0 = puOnDc;  puOnDc1 = puOnDc + nWords;
+    pTemp0  = pTemp;   pTemp1  = pTemp + nWords;
+    // solve for cofactors
+    Kit_TruthSharp( pTemp0, puOn0, puOnDc1, Var );
+    puRes0 = Kit_TruthIsop_rec( pTemp0, puOnDc0, Var, pcRes0, vStore );
+    if ( pcRes0->nCubes == -1 )
+    {
+        pcRes->nCubes = -1;
+        return NULL;
+    }
+    Kit_TruthSharp( pTemp1, puOn1, puOnDc0, Var );
+    puRes1 = Kit_TruthIsop_rec( pTemp1, puOnDc1, Var, pcRes1, vStore );
+    if ( pcRes1->nCubes == -1 )
+    {
+        pcRes->nCubes = -1;
+        return NULL;
+    }
+    Kit_TruthSharp( pTemp0, puOn0, puRes0, Var );
+    Kit_TruthSharp( pTemp1, puOn1, puRes1, Var );
+    Kit_TruthOr( pTemp0, pTemp0, pTemp1, Var );
+    Kit_TruthAnd( pTemp1, puOnDc0, puOnDc1, Var );
+    puRes2 = Kit_TruthIsop_rec( pTemp0, pTemp1, Var, pcRes2, vStore );
+    if ( pcRes2->nCubes == -1 )
+    {
+        pcRes->nCubes = -1;
+        return NULL;
+    }
+    // create the resulting cover
+    pcRes->nLits  = pcRes0->nLits  + pcRes1->nLits  + pcRes2->nLits + pcRes0->nCubes + pcRes1->nCubes;
+    pcRes->nCubes = pcRes0->nCubes + pcRes1->nCubes + pcRes2->nCubes;
+    pcRes->pCubes = Vec_IntFetch( vStore, pcRes->nCubes );
+    if ( pcRes->pCubes == NULL )
+    {
+        pcRes->nCubes = -1;
+        return NULL;
+    }
+    k = 0;
+    for ( i = 0; i < pcRes0->nCubes; i++ )
+        pcRes->pCubes[k++] = pcRes0->pCubes[i] | (1 << ((Var<<1)+0));
+    for ( i = 0; i < pcRes1->nCubes; i++ )
+        pcRes->pCubes[k++] = pcRes1->pCubes[i] | (1 << ((Var<<1)+1));
+    for ( i = 0; i < pcRes2->nCubes; i++ )
+        pcRes->pCubes[k++] = pcRes2->pCubes[i];
+    assert( k == pcRes->nCubes );
+    // create the resulting truth table
+    Kit_TruthOr( pTemp0, puRes0, puRes2, Var );
+    Kit_TruthOr( pTemp1, puRes1, puRes2, Var );
+    // copy the table if needed
+    nWords <<= 1;
+    for ( i = 1; i < nWordsAll/nWords; i++ )
+        for ( k = 0; k < nWords; k++ )
+            pTemp[i*nWords + k] = pTemp[k];
+    // verify in the end
+//    assert( Kit_TruthIsImply( puOn, pTemp, nVars ) );
+//    assert( Kit_TruthIsImply( pTemp, puOnDc, nVars ) );
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes ISOP for 5 variables or less.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Kit_TruthIsop5_rec( unsigned uOn, unsigned uOnDc, int nVars, Kit_Sop_t * pcRes, Vec_Int_t * vStore )
+{
+    unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+    Kit_Sop_t cRes0, cRes1, cRes2;
+    Kit_Sop_t * pcRes0 = &cRes0, * pcRes1 = &cRes1, * pcRes2 = &cRes2;
+    unsigned uOn0, uOn1, uOnDc0, uOnDc1, uRes0, uRes1, uRes2;
+    int i, k, Var;
+    assert( nVars <= 5 );
+    assert( (uOn & ~uOnDc) == 0 );
+    if ( uOn == 0 )
+    {
+        pcRes->nLits  = 0;
+        pcRes->nCubes = 0;
+        pcRes->pCubes = NULL;
+        return 0;
+    }
+    if ( uOnDc == 0xFFFFFFFF )
+    {
+        pcRes->nLits  = 0;
+        pcRes->nCubes = 1;
+        pcRes->pCubes = Vec_IntFetch( vStore, 1 );
+        if ( pcRes->pCubes == NULL )
+        {
+            pcRes->nCubes = -1;
+            return 0;
+        }
+        pcRes->pCubes[0] = 0;
+        return 0xFFFFFFFF;
+    }
+    assert( nVars > 0 );
+    // find the topmost var
+    for ( Var = nVars-1; Var >= 0; Var-- )
+        if ( Kit_TruthVarInSupport( &uOn, 5, Var ) || 
+             Kit_TruthVarInSupport( &uOnDc, 5, Var ) )
+             break;
+    assert( Var >= 0 );
+    // cofactor
+    uOn0   = uOn1   = uOn;
+    uOnDc0 = uOnDc1 = uOnDc;
+    Kit_TruthCofactor0( &uOn0, Var + 1, Var );
+    Kit_TruthCofactor1( &uOn1, Var + 1, Var );
+    Kit_TruthCofactor0( &uOnDc0, Var + 1, Var );
+    Kit_TruthCofactor1( &uOnDc1, Var + 1, Var );
+    // solve for cofactors
+    uRes0 = Kit_TruthIsop5_rec( uOn0 & ~uOnDc1, uOnDc0, Var, pcRes0, vStore );
+    if ( pcRes0->nCubes == -1 )
+    {
+        pcRes->nCubes = -1;
+        return 0;
+    }
+    uRes1 = Kit_TruthIsop5_rec( uOn1 & ~uOnDc0, uOnDc1, Var, pcRes1, vStore );
+    if ( pcRes1->nCubes == -1 )
+    {
+        pcRes->nCubes = -1;
+        return 0;
+    }
+    uRes2 = Kit_TruthIsop5_rec( (uOn0 & ~uRes0) | (uOn1 & ~uRes1), uOnDc0 & uOnDc1, Var, pcRes2, vStore );
+    if ( pcRes2->nCubes == -1 )
+    {
+        pcRes->nCubes = -1;
+        return 0;
+    }
+    // create the resulting cover
+    pcRes->nLits  = pcRes0->nLits  + pcRes1->nLits  + pcRes2->nLits + pcRes0->nCubes + pcRes1->nCubes;
+    pcRes->nCubes = pcRes0->nCubes + pcRes1->nCubes + pcRes2->nCubes;
+    pcRes->pCubes = Vec_IntFetch( vStore, pcRes->nCubes );
+    if ( pcRes->pCubes == NULL )
+    {
+        pcRes->nCubes = -1;
+        return 0;
+    }
+    k = 0;
+    for ( i = 0; i < pcRes0->nCubes; i++ )
+        pcRes->pCubes[k++] = pcRes0->pCubes[i] | (1 << ((Var<<1)+0));
+    for ( i = 0; i < pcRes1->nCubes; i++ )
+        pcRes->pCubes[k++] = pcRes1->pCubes[i] | (1 << ((Var<<1)+1));
+    for ( i = 0; i < pcRes2->nCubes; i++ )
+        pcRes->pCubes[k++] = pcRes2->pCubes[i];
+    assert( k == pcRes->nCubes );
+    // derive the final truth table
+    uRes2 |= (uRes0 & ~uMasks[Var]) | (uRes1 & uMasks[Var]);
+//    assert( (uOn & ~uRes2) == 0 );
+//    assert( (uRes2 & ~uOnDc) == 0 );
+    return uRes2;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/kit/kitPerm.c b/abc-build/src/bool/kit/kitPerm.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/kitPerm.c
@@ -0,0 +1,357 @@
+/**CFile****************************************************************
+
+  FileName    [kitPerm.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Computation kit.]
+
+  Synopsis    [Procedures for permuting truth tables.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Oct 26, 2011.]
+
+  Revision    [$Id: kitPerm.c,v 1.00 2011/11/26 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "kit.h"
+
+#define inline __inline // compatible with MS VS 6.0
+
+//ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef unsigned __int64 word;
+typedef unsigned short   shot;
+typedef unsigned char    byte;
+
+static shot S[256] =
+{
+    0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015,
+    0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055,
+    0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115,
+    0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155,
+    0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415,
+    0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455,
+    0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515,
+    0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555,
+    0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015,
+    0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055,
+    0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115,
+    0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155,
+    0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415,
+    0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455,
+    0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515,
+    0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555,
+    0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015,
+    0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055,
+    0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115,
+    0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155,
+    0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415,
+    0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455,
+    0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515,
+    0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555,
+    0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015,
+    0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055,
+    0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115,
+    0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155,
+    0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415,
+    0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455,
+    0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515,
+    0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555
+};
+
+static byte P[256] =
+{
+    0x00, 0x01, 0x10, 0x11, 0x04, 0x05, 0x14, 0x15, 0x40, 0x41, 0x50, 0x51, 0x44, 0x45, 0x54, 0x55,
+    0x02, 0x03, 0x12, 0x13, 0x06, 0x07, 0x16, 0x17, 0x42, 0x43, 0x52, 0x53, 0x46, 0x47, 0x56, 0x57,
+    0x20, 0x21, 0x30, 0x31, 0x24, 0x25, 0x34, 0x35, 0x60, 0x61, 0x70, 0x71, 0x64, 0x65, 0x74, 0x75,
+    0x22, 0x23, 0x32, 0x33, 0x26, 0x27, 0x36, 0x37, 0x62, 0x63, 0x72, 0x73, 0x66, 0x67, 0x76, 0x77,
+    0x08, 0x09, 0x18, 0x19, 0x0c, 0x0d, 0x1c, 0x1d, 0x48, 0x49, 0x58, 0x59, 0x4c, 0x4d, 0x5c, 0x5d,
+    0x0a, 0x0b, 0x1a, 0x1b, 0x0e, 0x0f, 0x1e, 0x1f, 0x4a, 0x4b, 0x5a, 0x5b, 0x4e, 0x4f, 0x5e, 0x5f,
+    0x28, 0x29, 0x38, 0x39, 0x2c, 0x2d, 0x3c, 0x3d, 0x68, 0x69, 0x78, 0x79, 0x6c, 0x6d, 0x7c, 0x7d,
+    0x2a, 0x2b, 0x3a, 0x3b, 0x2e, 0x2f, 0x3e, 0x3f, 0x6a, 0x6b, 0x7a, 0x7b, 0x6e, 0x6f, 0x7e, 0x7f,
+    0x80, 0x81, 0x90, 0x91, 0x84, 0x85, 0x94, 0x95, 0xc0, 0xc1, 0xd0, 0xd1, 0xc4, 0xc5, 0xd4, 0xd5,
+    0x82, 0x83, 0x92, 0x93, 0x86, 0x87, 0x96, 0x97, 0xc2, 0xc3, 0xd2, 0xd3, 0xc6, 0xc7, 0xd6, 0xd7,
+    0xa0, 0xa1, 0xb0, 0xb1, 0xa4, 0xa5, 0xb4, 0xb5, 0xe0, 0xe1, 0xf0, 0xf1, 0xe4, 0xe5, 0xf4, 0xf5,
+    0xa2, 0xa3, 0xb2, 0xb3, 0xa6, 0xa7, 0xb6, 0xb7, 0xe2, 0xe3, 0xf2, 0xf3, 0xe6, 0xe7, 0xf6, 0xf7,
+    0x88, 0x89, 0x98, 0x99, 0x8c, 0x8d, 0x9c, 0x9d, 0xc8, 0xc9, 0xd8, 0xd9, 0xcc, 0xcd, 0xdc, 0xdd,
+    0x8a, 0x8b, 0x9a, 0x9b, 0x8e, 0x8f, 0x9e, 0x9f, 0xca, 0xcb, 0xda, 0xdb, 0xce, 0xcf, 0xde, 0xdf,
+    0xa8, 0xa9, 0xb8, 0xb9, 0xac, 0xad, 0xbc, 0xbd, 0xe8, 0xe9, 0xf8, 0xf9, 0xec, 0xed, 0xfc, 0xfd,
+    0xaa, 0xab, 0xba, 0xbb, 0xae, 0xaf, 0xbe, 0xbf, 0xea, 0xeb, 0xfa, 0xfb, 0xee, 0xef, 0xfe, 0xff
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_PermCreateS()
+{
+    int i, n, r;
+    for ( i = 0; i < 256; i++ )
+    {
+        if ( i % 8 == 0 )
+            printf( "\n" );
+        for ( r = n = 0; n < 8; n++ )
+            r |= ((i & (1 << n)) << n);
+        printf( "0x%04x, ", r );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_PermCreateP()
+{
+    int i, s1, s2, r;
+    for ( i = 0; i < 256; i++ )
+    {
+        if ( i % 16 == 0 )
+            printf( "\n" );
+        s1 = i & 0x0A;
+        s2 = i & 0x50;
+        r = i ^ s1 ^ s2 ^ (s1 << 3) ^ (s2 >> 3);
+        assert( r < 256 );
+        printf( "0x%02x, ", r );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Kit_PermCycleOne( shot * s, byte * b, int v )
+{
+    int i, n = (1 << (v-3));
+    assert( v > 2 && v < 16 );
+    for ( i = 0; i < n; i++ )
+        s[i] = S[b[i]] | (S[b[i+n]] << 1);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Kit_PermCycleMany( shot * s, byte * b, int V, int v )
+{
+    int i, n = (1 << (V - 1 - v)), m = (1 << (v-2));
+    assert( v > 2 && v < V );
+    for ( i = 0; i < n; i++, s += (m >> 1), b += m )
+        Kit_PermCycleOne( s, b, v );   
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_PermCompute( word * o, word * i, int V )
+{
+    word * t;
+    int v, n = (1 << (V-3));
+    assert( V >= 6 && V <= 16 );
+    for ( v = 0; v < n; v++ )
+        ((byte *)i)[v] = P[((byte *)i)[v]];
+    for ( v = 3; v < V; v++ )
+    {
+        Kit_PermCycleMany( (shot *)o, (byte *)i, V, v );
+        t = i; i = o; o = t;
+    }
+    if ( V & 1 )
+    {
+        n = (1 << (V-6));
+        for ( v = 0; v < n; v++ )
+            o[v] = i[v];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_PermComputeNaive( word * F, int nVars )
+{
+    extern void If_CluReverseOrder( word * pF, int nVars, int * V2P, int * P2V, int iVarStart );
+    int i, V2P[16], P2V[16];
+    for ( i = 0; i < nVars; i++ )
+        V2P[i] = P2V[i] = i;
+    If_CluReverseOrder( F, nVars, V2P, P2V, 0 );
+}
+
+
+word M ( word f1, word f2, int n)
+{
+    word temp = 0;
+    word a = 1;
+    int i;
+    for(  i = 0; i < n; i++)
+        temp = temp + (((f1>>i)&a) << (2*i) ) + (((f2>>i)&a) << (2*i+1));
+    return temp;
+}
+
+word Tf ( word f, int n)
+{
+    if(n==1)
+        return f;
+    else
+    {
+//        int x = (int)pow(2,n-1);
+        int x;
+        x = (1 << (n-1));
+        return (  M (Tf( (f << x) >> x, n-1), Tf( (f >> x), n-1), x) );     //def. of M just below the function
+     }
+}
+
+
+//#define ABC_PRT(a,t)    (printf("%s = ", (a)), printf("%7.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)))
+#define NFUNCS (1<<20)
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_PermComputeTest()
+{
+    word * T = (word *)malloc( 8 * NFUNCS );
+    word i, o, w = 0;
+    int k, b;
+    abctime clk;
+
+    srand( 0 );
+
+    clk = Abc_Clock();
+    for ( k = 0; k < NFUNCS; k++ )
+        for ( b = 0; b < 8; b++ )
+            ((byte *)(T + k))[b] = (byte)(rand() & 0xFF);
+    ABC_PRT( "Assign", Abc_Clock() - clk );
+
+//    T[0] = 0xacaccacaaccaacca;
+//    Kit_DsdPrintFromTruth( T, 6 );
+
+    // perform measurements
+    clk = Abc_Clock();
+    for ( k = 0; k < NFUNCS; k++ )
+    {
+        i = T[k];
+//        Kit_PermComputeNaive( &i, 6 );
+        Tf( i, 6 );
+    }
+    ABC_PRT( "Perm1 ", Abc_Clock() - clk );
+
+    // perform measurements
+    clk = Abc_Clock();
+    for ( k = 0; k < NFUNCS; k++ )
+    {
+        i = T[k];
+        Kit_PermCompute( &o, &i, 6 );
+
+//        w = T[k];
+//        Kit_PermComputeNaive( &w, 6 );
+//        assert( w == o );
+    }
+    ABC_PRT( "Perm2 ", Abc_Clock() - clk );
+
+    assert( w == 0 );
+    free( T );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+`
+***********************************************************************/
+void Kit_PermComputeTest_()
+{
+    word t, s;
+    t = 0xacaccacaaccaacca;
+//    Kit_DsdPrintFromTruth( &t, 6 ); printf( "\n" );
+    s = Tf( t, 6 );
+//    Kit_PermComputeNaive( &t, 6 );
+//    Kit_DsdPrintFromTruth( &s, 6 ); printf( "\n" );
+}
+
+/*
+    {
+        extern void Kit_PermComputeTest();
+        Kit_PermComputeTest();
+    }
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+//ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/kit/kitPla.c b/abc-build/src/bool/kit/kitPla.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/kitPla.c
@@ -0,0 +1,535 @@
+/**CFile****************************************************************
+
+  FileName    [kitPla.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Computation kit.]
+
+  Synopsis    [Manipulating SOP in the form of a C-string.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 6, 2006.]
+
+  Revision    [$Id: kitPla.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "kit.h"
+#include "aig/aig/aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the cover is constant 0.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_PlaIsConst0( char * pSop )
+{
+    return pSop[0] == ' ' && pSop[1] == '0';
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the cover is constant 1.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_PlaIsConst1( char * pSop )
+{
+    return pSop[0] == ' ' && pSop[1] == '1';
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the cover is a buffer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_PlaIsBuf( char * pSop )
+{
+    if ( pSop[4] != 0 )
+        return 0;
+    if ( (pSop[0] == '1' && pSop[2] == '1') || (pSop[0] == '0' && pSop[2] == '0') )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the cover is an inverter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_PlaIsInv( char * pSop )
+{
+    if ( pSop[4] != 0 )
+        return 0;
+    if ( (pSop[0] == '0' && pSop[2] == '1') || (pSop[0] == '1' && pSop[2] == '0') )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the number of variables in the cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_PlaGetVarNum( char * pSop )
+{
+    char * pCur;
+    for ( pCur = pSop; *pCur != '\n'; pCur++ )
+        if ( *pCur == 0 )
+            return -1;
+    return pCur - pSop - 2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the number of cubes in the cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_PlaGetCubeNum( char * pSop )
+{
+    char * pCur;
+    int nCubes = 0;
+    if ( pSop == NULL )
+        return 0;
+    for ( pCur = pSop; *pCur; pCur++ )
+        nCubes += (*pCur == '\n');
+    return nCubes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_PlaIsComplement( char * pSop )
+{
+    char * pCur;
+    for ( pCur = pSop; *pCur; pCur++ )
+        if ( *pCur == '\n' )
+            return (int)(*(pCur - 1) == '0' || *(pCur - 1) == 'n');
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_PlaComplement( char * pSop )
+{
+    char * pCur;
+    for ( pCur = pSop; *pCur; pCur++ )
+        if ( *pCur == '\n' )
+        {
+            if ( *(pCur - 1) == '0' )
+                *(pCur - 1) = '1';
+            else if ( *(pCur - 1) == '1' )
+                *(pCur - 1) = '0';
+            else if ( *(pCur - 1) == 'x' )
+                *(pCur - 1) = 'n';
+            else if ( *(pCur - 1) == 'n' )
+                *(pCur - 1) = 'x';
+            else
+                assert( 0 );
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the constant 1 cover with the given number of variables and cubes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Kit_PlaStart( void * p, int nCubes, int nVars )
+{
+    Aig_MmFlex_t * pMan = (Aig_MmFlex_t *)p;
+    char * pSopCover, * pCube;
+    int i, Length;
+
+    Length = nCubes * (nVars + 3);
+    pSopCover = Aig_MmFlexEntryFetch( pMan, Length + 1 );
+    memset( pSopCover, '-', Length );
+    pSopCover[Length] = 0;
+
+    for ( i = 0; i < nCubes; i++ )
+    {
+        pCube = pSopCover + i * (nVars + 3);
+        pCube[nVars + 0] = ' ';
+        pCube[nVars + 1] = '1';
+        pCube[nVars + 2] = '\n';
+    }
+    return pSopCover;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the cover from the ISOP computed from TT.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Kit_PlaCreateFromIsop( void * p, int nVars, Vec_Int_t * vCover )
+{
+    Aig_MmFlex_t * pMan = (Aig_MmFlex_t *)p;
+    char * pSop, * pCube;
+    int i, k, Entry, Literal;
+    assert( Vec_IntSize(vCover) > 0 );
+    if ( Vec_IntSize(vCover) == 0 )
+        return NULL;
+    // start the cover
+    pSop = Kit_PlaStart( pMan, Vec_IntSize(vCover), nVars );
+    // create cubes
+    Vec_IntForEachEntry( vCover, Entry, i )
+    {
+        pCube = pSop + i * (nVars + 3);
+        for ( k = 0; k < nVars; k++ )
+        {
+            Literal = 3 & (Entry >> (k << 1));
+            if ( Literal == 1 )
+                pCube[k] = '0';
+            else if ( Literal == 2 )
+                pCube[k] = '1';
+            else if ( Literal != 0 )
+                assert( 0 );
+        }
+    }
+    return pSop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the cover from the ISOP computed from TT.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_PlaToIsop( char * pSop, Vec_Int_t * vCover )
+{
+    char * pCube;
+    int k, nVars, Entry;
+    nVars = Kit_PlaGetVarNum( pSop );
+    assert( nVars > 0 );
+    // create cubes
+    Vec_IntClear( vCover );
+    for ( pCube = pSop; *pCube; pCube += nVars + 3 )
+    {
+        Entry = 0;
+        for ( k = nVars - 1; k >= 0; k-- )
+            if ( pCube[k] == '0' )
+                Entry = (Entry << 2) | 1;
+            else if ( pCube[k] == '1' )
+                Entry = (Entry << 2) | 2;
+            else if ( pCube[k] == '-' )
+                Entry = (Entry << 2);
+            else 
+                assert( 0 );
+        Vec_IntPush( vCover, Entry );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates memory and copies the SOP into it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Kit_PlaStoreSop( void * p, char * pSop )
+{
+    Aig_MmFlex_t * pMan = (Aig_MmFlex_t *)p;
+    char * pStore;
+    pStore = Aig_MmFlexEntryFetch( pMan, strlen(pSop) + 1 );
+    strcpy( pStore, pSop );
+    return pStore;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms truth table into the SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Kit_PlaFromTruth( void * p, unsigned * pTruth, int nVars, Vec_Int_t * vCover )
+{
+    Aig_MmFlex_t * pMan = (Aig_MmFlex_t *)p;
+    char * pSop;
+    int RetValue;
+    if ( Kit_TruthIsConst0(pTruth, nVars) )
+        return Kit_PlaStoreSop( pMan, " 0\n" );
+    if ( Kit_TruthIsConst1(pTruth, nVars) )
+        return Kit_PlaStoreSop( pMan, " 1\n" );
+    RetValue = Kit_TruthIsop( pTruth, nVars, vCover, 0 ); // 1 );
+    assert( RetValue == 0 || RetValue == 1 );
+    pSop = Kit_PlaCreateFromIsop( pMan, nVars, vCover );
+    if ( RetValue )
+        Kit_PlaComplement( pSop );
+    return pSop;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the cover from the ISOP computed from TT.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Kit_PlaFromIsop( Vec_Str_t * vStr, int nVars, Vec_Int_t * vCover )
+{
+    int i, k, Entry, Literal;
+    assert( Vec_IntSize(vCover) > 0 );
+    if ( Vec_IntSize(vCover) == 0 )
+        return NULL;
+    Vec_StrClear( vStr );
+    Vec_IntForEachEntry( vCover, Entry, i )
+    {
+        for ( k = 0; k < nVars; k++ )
+        {
+            Literal = 3 & (Entry >> (k << 1));
+            if ( Literal == 1 )
+                Vec_StrPush( vStr, '0' );
+            else if ( Literal == 2 )
+                Vec_StrPush( vStr, '1' );
+            else if ( Literal == 0 )
+                Vec_StrPush( vStr, '-' );
+            else
+                assert( 0 );
+        }
+        Vec_StrPush( vStr, ' ' );
+        Vec_StrPush( vStr, '1' );
+        Vec_StrPush( vStr, '\n' );
+    }
+    Vec_StrPush( vStr, '\0' );
+    return Vec_StrArray( vStr );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the SOP from TT.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Kit_PlaFromTruthNew( unsigned * pTruth, int nVars, Vec_Int_t * vCover, Vec_Str_t * vStr )
+{
+    char * pResult;
+    // transform truth table into the SOP
+    int RetValue = Kit_TruthIsop( pTruth, nVars, vCover, 1 );
+    assert( RetValue == 0 || RetValue == 1 );
+    // check the case of constant cover
+    if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) )
+    {
+        assert( RetValue == 0 );
+        Vec_StrClear( vStr );
+        Vec_StrAppend( vStr, (Vec_IntSize(vCover) == 0) ? " 0\n" : " 1\n" );
+        Vec_StrPush( vStr, '\0' );
+        return Vec_StrArray( vStr );
+    }
+    pResult = Kit_PlaFromIsop( vStr, nVars, vCover );
+    if ( RetValue )
+        Kit_PlaComplement( pResult );
+    if ( nVars < 6 )
+        assert( pTruth[0] == (unsigned)Kit_PlaToTruth6(pResult, nVars) );
+    else if ( nVars == 6 )
+        assert( *((ABC_UINT64_T*)pTruth) == Kit_PlaToTruth6(pResult, nVars) );
+    return pResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts SOP into a truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+ABC_UINT64_T Kit_PlaToTruth6( char * pSop, int nVars )
+{
+    static ABC_UINT64_T Truth[8] = {
+        ABC_CONST(0xAAAAAAAAAAAAAAAA),
+        ABC_CONST(0xCCCCCCCCCCCCCCCC),
+        ABC_CONST(0xF0F0F0F0F0F0F0F0),
+        ABC_CONST(0xFF00FF00FF00FF00),
+        ABC_CONST(0xFFFF0000FFFF0000),
+        ABC_CONST(0xFFFFFFFF00000000),
+        ABC_CONST(0x0000000000000000),
+        ABC_CONST(0xFFFFFFFFFFFFFFFF)
+    };
+    ABC_UINT64_T valueAnd, valueOr = Truth[6];
+    int v, lit = 0;
+    assert( nVars < 7 );
+    do {
+        valueAnd = Truth[7];
+        for ( v = 0; v < nVars; v++, lit++ )
+        {
+            if ( pSop[lit] == '1' )
+                valueAnd &=  Truth[v];
+            else if ( pSop[lit] == '0' )
+                valueAnd &= ~Truth[v];
+            else if ( pSop[lit] != '-' )
+                assert( 0 );
+        }
+        valueOr |= valueAnd;
+        assert( pSop[lit] == ' ' );
+        lit++;
+        lit++;
+        assert( pSop[lit] == '\n' );
+        lit++;
+    } while ( pSop[lit] );
+    if ( Kit_PlaIsComplement(pSop) )
+        valueOr = ~valueOr;
+    return valueOr;
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Converting SOP into a truth table.]
+
+  Description [The SOP is represented as a C-string, as documented in 
+  file "bblif.h". The truth table is returned as a bit-string composed 
+  of 2^nVars bits. For functions of less than 6 variables, the full
+  machine word is returned. (The truth table looks as if the function
+  had 5 variables.) The use of this procedure should be limited to 
+  Boolean functions with no more than 16 inputs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_PlaToTruth( char * pSop, int nVars, Vec_Ptr_t * vVars, unsigned * pTemp, unsigned * pTruth )
+{
+    int v, c, nCubes, fCompl = 0;
+    assert( pSop != NULL );
+    assert( nVars >= 0 );
+    if ( strlen(pSop) % (nVars + 3) != 0 )
+    {
+        printf( "Kit_PlaToTruth(): SOP is represented incorrectly.\n" );
+        return;
+    }
+    // iterate through the cubes
+    Kit_TruthClear( pTruth, nVars );
+    nCubes =  strlen(pSop) / (nVars + 3);
+    for ( c = 0; c < nCubes; c++ )
+    {
+        fCompl = (pSop[nVars+1] == '0');
+        Kit_TruthFill( pTemp, nVars );
+        // iterate through the literals of the cube
+        for ( v = 0; v < nVars; v++ )
+            if ( pSop[v] == '1' )
+                Kit_TruthAnd( pTemp, pTemp, (unsigned *)Vec_PtrEntry(vVars, v), nVars );
+            else if ( pSop[v] == '0' )
+                Kit_TruthSharp( pTemp, pTemp, (unsigned *)Vec_PtrEntry(vVars, v), nVars );
+        // add cube to storage
+        Kit_TruthOr( pTruth, pTruth, pTemp, nVars );
+        // go to the next cube
+        pSop += (nVars + 3);
+    }
+    if ( fCompl )
+        Kit_TruthNot( pTruth, pTruth, nVars );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/kit/kitSop.c b/abc-build/src/bool/kit/kitSop.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/kitSop.c
@@ -0,0 +1,579 @@
+/**CFile****************************************************************
+
+  FileName    [kitSop.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Computation kit.]
+
+  Synopsis    [Procedures involving SOPs.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 6, 2006.]
+
+  Revision    [$Id: kitSop.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates SOP from the cube array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_SopCreate( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nVars, Vec_Int_t * vMemory )
+{
+    unsigned uCube;
+    int i;
+    // start the cover
+    cResult->nCubes = 0;
+    cResult->pCubes = Vec_IntFetch( vMemory, Vec_IntSize(vInput) );
+    // add the cubes
+    Vec_IntForEachEntry( vInput, uCube, i )
+        Kit_SopPushCube( cResult, uCube );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates SOP from the cube array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_SopCreateInverse( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nLits, Vec_Int_t * vMemory )
+{
+    unsigned uCube, uMask = 0;
+    int i, nCubes = Vec_IntSize(vInput);
+    // start the cover
+    cResult->nCubes = 0;
+    cResult->pCubes = Vec_IntFetch( vMemory, nCubes );
+    // add the cubes
+//    Vec_IntForEachEntry( vInput, uCube, i )
+    for ( i = 0; i < nCubes; i++ )
+    {
+        uCube = Vec_IntEntry( vInput, i );
+        uMask = ((uCube | (uCube >> 1)) & 0x55555555);
+        uMask |= (uMask << 1);
+        Kit_SopPushCube( cResult, uCube ^ uMask );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_SopDup( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory )
+{
+    unsigned uCube;
+    int i;
+    // start the cover
+    cResult->nCubes = 0;
+    cResult->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) );
+    // add the cubes
+    Kit_SopForEachCube( cSop, uCube, i )
+        Kit_SopPushCube( cResult, uCube );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the quotient of division by literal.]
+
+  Description [Reduces the cover to be equal to the result of
+  division of the given cover by the literal.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_SopDivideByLiteralQuo( Kit_Sop_t * cSop, int iLit )
+{
+    unsigned uCube;
+    int i, k = 0;
+    Kit_SopForEachCube( cSop, uCube, i )
+    {
+        if ( Kit_CubeHasLit(uCube, iLit) )
+            Kit_SopWriteCube( cSop, Kit_CubeRemLit(uCube, iLit), k++ );
+    }
+    Kit_SopShrink( cSop, k );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Divides cover by one cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_SopDivideByCube( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory )
+{
+    unsigned uCube, uDiv;
+    int i;
+    // get the only cube
+    assert( Kit_SopCubeNum(cDiv) == 1 );
+    uDiv = Kit_SopCube(cDiv, 0);
+    // allocate covers
+    vQuo->nCubes = 0;
+    vQuo->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) );
+    vRem->nCubes = 0;
+    vRem->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) );
+    // sort the cubes
+    Kit_SopForEachCube( cSop, uCube, i )
+    {
+        if ( Kit_CubeContains( uCube, uDiv ) )
+            Kit_SopPushCube( vQuo, Kit_CubeSharp(uCube, uDiv) );
+        else
+            Kit_SopPushCube( vRem, uCube );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Divides cover by one cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_SopDivideInternal( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory )
+{
+    unsigned uCube, uDiv;
+    unsigned uCube2 = 0; // Suppress "might be used uninitialized"
+    unsigned uDiv2, uQuo;
+    int i, i2, k, k2, nCubesRem;
+    assert( Kit_SopCubeNum(cSop) >= Kit_SopCubeNum(cDiv) );
+    // consider special case
+    if ( Kit_SopCubeNum(cDiv) == 1 )
+    {
+        Kit_SopDivideByCube( cSop, cDiv, vQuo, vRem, vMemory );
+        return;
+    }
+    // allocate quotient
+    vQuo->nCubes = 0;
+    vQuo->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) / Kit_SopCubeNum(cDiv) );
+    // for each cube of the cover
+    // it either belongs to the quotient or to the remainder
+    Kit_SopForEachCube( cSop, uCube, i )
+    {
+        // skip taken cubes
+        if ( Kit_CubeIsMarked(uCube) )
+            continue;
+        // find a matching cube in the divisor
+        uDiv = ~0;
+        Kit_SopForEachCube( cDiv, uDiv, k )
+            if ( Kit_CubeContains( uCube, uDiv ) )
+                break;
+        // the cube is not found 
+        if ( k == Kit_SopCubeNum(cDiv) )
+            continue;
+        // the quotient cube exists
+        uQuo = Kit_CubeSharp( uCube, uDiv );
+        // find corresponding cubes for other cubes of the divisor
+        uDiv2 = ~0;
+        Kit_SopForEachCube( cDiv, uDiv2, k2 )
+        {
+            if ( k2 == k )
+                continue;
+            // find a matching cube
+            Kit_SopForEachCube( cSop, uCube2, i2 )
+            {
+                // skip taken cubes
+                if ( Kit_CubeIsMarked(uCube2) )
+                    continue;
+                // check if the cube can be used
+                if ( Kit_CubeContains( uCube2, uDiv2 ) && uQuo == Kit_CubeSharp( uCube2, uDiv2 ) )
+                    break;
+            }
+            // the case when the cube is not found
+            if ( i2 == Kit_SopCubeNum(cSop) )
+                break;
+        }
+        // we did not find some cubes - continue looking at other cubes
+        if ( k2 != Kit_SopCubeNum(cDiv) )
+            continue;
+        // we found all cubes - add the quotient cube
+        Kit_SopPushCube( vQuo, uQuo );
+
+        // mark the first cube
+        Kit_SopWriteCube( cSop, Kit_CubeMark(uCube), i );
+        // mark other cubes that have this quotient
+        Kit_SopForEachCube( cDiv, uDiv2, k2 )
+        {
+            if ( k2 == k )
+                continue;
+            // find a matching cube
+            Kit_SopForEachCube( cSop, uCube2, i2 )
+            {
+                // skip taken cubes
+                if ( Kit_CubeIsMarked(uCube2) )
+                    continue;
+                // check if the cube can be used
+                if ( Kit_CubeContains( uCube2, uDiv2 ) && uQuo == Kit_CubeSharp( uCube2, uDiv2 ) )
+                    break;
+            }
+            assert( i2 < Kit_SopCubeNum(cSop) );
+            // the cube is found, mark it 
+            // (later we will add all unmarked cubes to the remainder)
+            Kit_SopWriteCube( cSop, Kit_CubeMark(uCube2), i2 );
+        }
+    }
+    // determine the number of cubes in the remainder
+    nCubesRem = Kit_SopCubeNum(cSop) - Kit_SopCubeNum(vQuo) * Kit_SopCubeNum(cDiv);
+    // allocate remainder
+    vRem->nCubes = 0;
+    vRem->pCubes = Vec_IntFetch( vMemory, nCubesRem );
+    // finally add the remaining unmarked cubes to the remainder 
+    // and clean the marked cubes in the cover
+    Kit_SopForEachCube( cSop, uCube, i )
+    {
+        if ( !Kit_CubeIsMarked(uCube) )
+        {
+            Kit_SopPushCube( vRem, uCube );
+            continue;
+        }
+        Kit_SopWriteCube( cSop, Kit_CubeUnmark(uCube), i );
+    }
+    assert( nCubesRem == Kit_SopCubeNum(vRem) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the common cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Kit_SopCommonCube( Kit_Sop_t * cSop )
+{
+    unsigned uMask, uCube;
+    int i;
+    uMask = ~(unsigned)0;
+    Kit_SopForEachCube( cSop, uCube, i )
+        uMask &= uCube;
+    return uMask;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Makes the cover cube-free.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_SopMakeCubeFree( Kit_Sop_t * cSop )
+{
+    unsigned uMask, uCube;
+    int i;
+    uMask = Kit_SopCommonCube( cSop );
+    if ( uMask == 0 )
+        return;
+    // remove the common cube
+    Kit_SopForEachCube( cSop, uCube, i )
+        Kit_SopWriteCube( cSop, Kit_CubeSharp(uCube, uMask), i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the cover is cube-free.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_SopIsCubeFree( Kit_Sop_t * cSop )
+{
+    return Kit_SopCommonCube( cSop ) == 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates SOP composes of the common cube of the given SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_SopCommonCubeCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory )
+{
+    assert( Kit_SopCubeNum(cSop) > 0 );
+    cResult->nCubes = 0;
+    cResult->pCubes = Vec_IntFetch( vMemory, 1 );
+    Kit_SopPushCube( cResult, Kit_SopCommonCube(cSop) );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Find any literal that occurs more than once.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_SopAnyLiteral( Kit_Sop_t * cSop, int nLits )
+{
+    unsigned uCube;
+    int i, k, nLitsCur;
+    // go through each literal
+    for ( i = 0; i < nLits; i++ )
+    {
+        // go through all the cubes
+        nLitsCur = 0;
+        Kit_SopForEachCube( cSop, uCube, k )
+            if ( Kit_CubeHasLit(uCube, i) )
+                nLitsCur++;
+        if ( nLitsCur > 1 )
+            return i;
+    }
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the least often occurring literal.]
+
+  Description [Find the least often occurring literal among those
+  that occur more than once.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_SopWorstLiteral( Kit_Sop_t * cSop, int nLits )
+{
+    unsigned uCube;
+    int i, k, iMin, nLitsMin, nLitsCur;
+    int fUseFirst = 1;
+
+    // go through each literal
+    iMin = -1;
+    nLitsMin = 1000000;
+    for ( i = 0; i < nLits; i++ )
+    {
+        // go through all the cubes
+        nLitsCur = 0;
+        Kit_SopForEachCube( cSop, uCube, k )
+            if ( Kit_CubeHasLit(uCube, i) )
+                nLitsCur++;
+        // skip the literal that does not occur or occurs once
+        if ( nLitsCur < 2 )
+            continue;
+        // check if this is the best literal
+        if ( fUseFirst )
+        {
+            if ( nLitsMin > nLitsCur )
+            {
+                nLitsMin = nLitsCur;
+                iMin = i;
+            }
+        }
+        else
+        {
+            if ( nLitsMin >= nLitsCur )
+            {
+                nLitsMin = nLitsCur;
+                iMin = i;
+            }
+        }
+    }
+    if ( nLitsMin < 1000000 )
+        return iMin;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the least often occurring literal.]
+
+  Description [Find the least often occurring literal among those
+  that occur more than once.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_SopBestLiteral( Kit_Sop_t * cSop, int nLits, unsigned uMask )
+{
+    unsigned uCube;
+    int i, k, iMax, nLitsMax, nLitsCur;
+    int fUseFirst = 1;
+
+    // go through each literal
+    iMax = -1;
+    nLitsMax = -1;
+    for ( i = 0; i < nLits; i++ )
+    {
+        if ( !Kit_CubeHasLit(uMask, i) )
+            continue;
+        // go through all the cubes
+        nLitsCur = 0;
+        Kit_SopForEachCube( cSop, uCube, k )
+            if ( Kit_CubeHasLit(uCube, i) )
+                nLitsCur++;
+        // skip the literal that does not occur or occurs once
+        if ( nLitsCur < 2 )
+            continue;
+        // check if this is the best literal
+        if ( fUseFirst )
+        {
+            if ( nLitsMax < nLitsCur )
+            {
+                nLitsMax = nLitsCur;
+                iMax = i;
+            }
+        }
+        else
+        {
+            if ( nLitsMax <= nLitsCur )
+            {
+                nLitsMax = nLitsCur;
+                iMax = i;
+            }
+        }
+    }
+    if ( nLitsMax >= 0 )
+        return iMax;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes a level-zero kernel.]
+
+  Description [Modifies the cover to contain one level-zero kernel.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_SopDivisorZeroKernel_rec( Kit_Sop_t * cSop, int nLits )
+{
+    int iLit;
+    // find any literal that occurs at least two times
+    iLit = Kit_SopWorstLiteral( cSop, nLits );
+    if ( iLit == -1 )
+        return;
+    // derive the cube-free quotient
+    Kit_SopDivideByLiteralQuo( cSop, iLit ); // the same cover
+    Kit_SopMakeCubeFree( cSop );             // the same cover
+    // call recursively
+    Kit_SopDivisorZeroKernel_rec( cSop, nLits );    // the same cover
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the quick divisor of the cover.]
+
+  Description [Returns 0, if there is no divisor other than trivial.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_SopDivisor( Kit_Sop_t * cResult, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory )
+{
+    if ( Kit_SopCubeNum(cSop) <= 1 )
+        return 0;
+    if ( Kit_SopAnyLiteral( cSop, nLits ) == -1 )
+        return 0;
+    // duplicate the cover
+    Kit_SopDup( cResult, cSop, vMemory );
+    // perform the kerneling
+    Kit_SopDivisorZeroKernel_rec( cResult, nLits );
+    assert( Kit_SopCubeNum(cResult) > 0 );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Create the one-literal cover with the best literal from cSop.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_SopBestLiteralCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, unsigned uCube, int nLits, Vec_Int_t * vMemory )
+{
+    int iLitBest;
+    // get the best literal
+    iLitBest = Kit_SopBestLiteral( cSop, nLits, uCube );
+    // start the cover
+    cResult->nCubes = 0;
+    cResult->pCubes = Vec_IntFetch( vMemory, 1 );
+    // set the cube
+    Kit_SopPushCube( cResult, Kit_CubeSetLit(0, iLitBest) );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/kit/kitTruth.c b/abc-build/src/bool/kit/kitTruth.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/kitTruth.c
@@ -0,0 +1,2224 @@
+/**CFile****************************************************************
+
+  FileName    [kitTruth.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Computation kit.]
+
+  Synopsis    [Procedures involving truth tables.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 6, 2006.]
+
+  Revision    [$Id: kitTruth.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Swaps two adjacent variables in the truth table.]
+
+  Description [Swaps var number Start and var number Start+1 (0-based numbers).
+  The input truth table is pIn. The output truth table is pOut.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int iVar )
+{
+    static unsigned PMasks[4][3] = {
+        { 0x99999999, 0x22222222, 0x44444444 },
+        { 0xC3C3C3C3, 0x0C0C0C0C, 0x30303030 },
+        { 0xF00FF00F, 0x00F000F0, 0x0F000F00 },
+        { 0xFF0000FF, 0x0000FF00, 0x00FF0000 }
+    };
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Step, Shift;
+
+    assert( iVar < nVars - 1 );
+    if ( iVar < 4 )
+    {
+        Shift = (1 << iVar);
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift);
+    }
+    else if ( iVar > 4 )
+    {
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 4*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                pOut[i] = pIn[i];
+            for ( i = 0; i < Step; i++ )
+                pOut[Step+i] = pIn[2*Step+i];
+            for ( i = 0; i < Step; i++ )
+                pOut[2*Step+i] = pIn[Step+i];
+            for ( i = 0; i < Step; i++ )
+                pOut[3*Step+i] = pIn[3*Step+i];
+            pIn  += 4*Step;
+            pOut += 4*Step;
+        }
+    }
+    else // if ( iVar == 4 )
+    {
+        for ( i = 0; i < nWords; i += 2 )
+        {
+            pOut[i]   = (pIn[i]   & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16);
+            pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i]   & 0xFFFF0000) >> 16);
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Swaps two adjacent variables in the truth table.]
+
+  Description [Swaps var number Start and var number Start+1 (0-based numbers).
+  The input truth table is pIn. The output truth table is pOut.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthSwapAdjacentVars2( unsigned * pIn, unsigned * pOut, int nVars, int Start )
+{
+    int nWords = (nVars <= 5)? 1 : (1 << (nVars-5));
+    int i, k, Step;
+
+    assert( Start < nVars - 1 );
+    switch ( Start )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0x99999999) | ((pIn[i] & 0x22222222) << 1) | ((pIn[i] & 0x44444444) >> 1);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0xC3C3C3C3) | ((pIn[i] & 0x0C0C0C0C) << 2) | ((pIn[i] & 0x30303030) >> 2);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0xF00FF00F) | ((pIn[i] & 0x00F000F0) << 4) | ((pIn[i] & 0x0F000F00) >> 4);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0xFF0000FF) | ((pIn[i] & 0x0000FF00) << 8) | ((pIn[i] & 0x00FF0000) >> 8);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i += 2 )
+        {
+            pOut[i]   = (pIn[i]   & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16);
+            pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i]   & 0xFFFF0000) >> 16);
+        }
+        return;
+    default:
+        Step = (1 << (Start - 5));
+        for ( k = 0; k < nWords; k += 4*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                pOut[i] = pIn[i];
+            for ( i = 0; i < Step; i++ )
+                pOut[Step+i] = pIn[2*Step+i];
+            for ( i = 0; i < Step; i++ )
+                pOut[2*Step+i] = pIn[Step+i];
+            for ( i = 0; i < Step; i++ )
+                pOut[3*Step+i] = pIn[3*Step+i];
+            pIn  += 4*Step;
+            pOut += 4*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Expands the truth table according to the phase.]
+
+  Description [The input and output truth tables are in pIn/pOut. The current number
+  of variables is nVars. The total number of variables in nVarsAll. The last argument
+  (Phase) contains shows where the variables should go.]
+               
+  SideEffects [The input truth table is modified.]
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn )
+{
+    unsigned * pTemp;
+    int i, k, Var = nVars - 1, Counter = 0;
+    for ( i = nVarsAll - 1; i >= 0; i-- )
+        if ( Phase & (1 << i) )
+        {
+            for ( k = Var; k < i; k++ )
+            {
+                Kit_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k );
+                pTemp = pIn; pIn = pOut; pOut = pTemp;
+                Counter++;
+            }
+            Var--;
+        }
+    assert( Var == -1 );
+    // swap if it was moved an even number of times
+    if ( fReturnIn ^ !(Counter & 1) )
+        Kit_TruthCopy( pOut, pIn, nVarsAll );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Shrinks the truth table according to the phase.]
+
+  Description [The input and output truth tables are in pIn/pOut. The current number
+  of variables is nVars. The total number of variables in nVarsAll. The last argument
+  (Phase) shows what variables should remain.]
+               
+  SideEffects [The input truth table is modified.]
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn )
+{
+    unsigned * pTemp;
+    int i, k, Var = 0, Counter = 0;
+    for ( i = 0; i < nVarsAll; i++ )
+        if ( Phase & (1 << i) )
+        {
+            for ( k = i-1; k >= Var; k-- )
+            {
+                Kit_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k );
+                pTemp = pIn; pIn = pOut; pOut = pTemp;
+                Counter++;
+            }
+            Var++;
+        }
+    assert( Var == nVars );
+    // swap if it was moved an even number of times
+    if ( fReturnIn ^ !(Counter & 1) )
+        Kit_TruthCopy( pOut, pIn, nVarsAll );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implement give permutation.]
+
+  Description [The input and output truth tables are in pIn/pOut. 
+  The number of variables is nVars. Permutation is in pPerm.]
+               
+  SideEffects [The input truth table is modified.]
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthPermute( unsigned * pOut, unsigned * pIn, int nVars, char * pPerm, int fReturnIn )
+{
+    unsigned * pTemp;
+    int i, Temp, fChange, Counter = 0;
+    do {
+        fChange = 0;
+        for ( i = 0; i < nVars-1; i++ )
+        {
+            assert( pPerm[i] != pPerm[i+1] );
+            if ( pPerm[i] <= pPerm[i+1] )
+                continue;
+            Counter++;
+            fChange = 1;
+
+            Temp = pPerm[i];
+            pPerm[i] = pPerm[i+1];
+            pPerm[i+1] = Temp;
+
+            Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i );
+            pTemp = pIn; pIn = pOut; pOut = pTemp;
+        }
+    } while ( fChange );
+    if ( fReturnIn ^ !(Counter & 1) )
+        Kit_TruthCopy( pOut, pIn, nVars );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if TT depends on the given variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            if ( (pTruth[i] & 0x55555555) != ((pTruth[i] & 0xAAAAAAAA) >> 1) )
+                return 1;
+        return 0;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            if ( (pTruth[i] & 0x33333333) != ((pTruth[i] & 0xCCCCCCCC) >> 2) )
+                return 1;
+        return 0;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            if ( (pTruth[i] & 0x0F0F0F0F) != ((pTruth[i] & 0xF0F0F0F0) >> 4) )
+                return 1;
+        return 0;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            if ( (pTruth[i] & 0x00FF00FF) != ((pTruth[i] & 0xFF00FF00) >> 8) )
+                return 1;
+        return 0;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            if ( (pTruth[i] & 0x0000FFFF) != ((pTruth[i] & 0xFFFF0000) >> 16) )
+                return 1;
+        return 0;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                if ( pTruth[i] != pTruth[Step+i] )
+                    return 1;
+            pTruth += 2*Step;
+        }
+        return 0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of support vars.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_TruthSupportSize( unsigned * pTruth, int nVars )
+{
+    int i, Counter = 0;
+    for ( i = 0; i < nVars; i++ )
+        Counter += Kit_TruthVarInSupport( pTruth, nVars, i );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns support of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Kit_TruthSupport( unsigned * pTruth, int nVars )
+{
+    int i, Support = 0;
+    for ( i = 0; i < nVars; i++ )
+        if ( Kit_TruthVarInSupport( pTruth, nVars, i ) )
+            Support |= (1 << i);
+    return Support;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes negative cofactor of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthCofactor0( unsigned * pTruth, int nVars, int iVar )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0x55555555) | ((pTruth[i] & 0x55555555) << 1);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0x33333333) | ((pTruth[i] & 0x33333333) << 2);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0x0F0F0F0F) | ((pTruth[i] & 0x0F0F0F0F) << 4);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0x00FF00FF) | ((pTruth[i] & 0x00FF00FF) << 8);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0x0000FFFF) | ((pTruth[i] & 0x0000FFFF) << 16);
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                pTruth[Step+i] = pTruth[i];
+            pTruth += 2*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes negative cofactor of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_TruthCofactor0Count( unsigned * pTruth, int nVars, int iVar )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Step, Counter = 0;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            Counter += Kit_WordCountOnes(pTruth[i] & 0x55555555);
+        return Counter;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            Counter += Kit_WordCountOnes(pTruth[i] & 0x33333333);
+        return Counter;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            Counter += Kit_WordCountOnes(pTruth[i] & 0x0F0F0F0F);
+        return Counter;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            Counter += Kit_WordCountOnes(pTruth[i] & 0x00FF00FF);
+        return Counter;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            Counter += Kit_WordCountOnes(pTruth[i] & 0x0000FFFF);
+        return Counter;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                Counter += Kit_WordCountOnes(pTruth[i]);
+            pTruth += 2*Step;
+        }
+        return Counter;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes positive cofactor of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthCofactor1( unsigned * pTruth, int nVars, int iVar )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0xAAAAAAAA) | ((pTruth[i] & 0xAAAAAAAA) >> 1);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0xCCCCCCCC) | ((pTruth[i] & 0xCCCCCCCC) >> 2);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0xF0F0F0F0) | ((pTruth[i] & 0xF0F0F0F0) >> 4);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0xFF00FF00) | ((pTruth[i] & 0xFF00FF00) >> 8);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0xFFFF0000) | ((pTruth[i] & 0xFFFF0000) >> 16);
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                pTruth[i] = pTruth[Step+i];
+            pTruth += 2*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes positive cofactor of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthCofactor0New( unsigned * pOut, unsigned * pIn, int nVars, int iVar )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0x55555555) | ((pIn[i] & 0x55555555) << 1);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0x33333333) | ((pIn[i] & 0x33333333) << 2);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0x0F0F0F0F) | ((pIn[i] & 0x0F0F0F0F) << 4);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0x00FF00FF) | ((pIn[i] & 0x00FF00FF) << 8);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i] & 0x0000FFFF) << 16);
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                pOut[i] = pOut[Step+i] = pIn[i];
+            pIn += 2*Step;
+            pOut += 2*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes positive cofactor of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthCofactor1New( unsigned * pOut, unsigned * pIn, int nVars, int iVar )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0xAAAAAAAA) | ((pIn[i] & 0xAAAAAAAA) >> 1);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0xCCCCCCCC) | ((pIn[i] & 0xCCCCCCCC) >> 2);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0xF0F0F0F0) | ((pIn[i] & 0xF0F0F0F0) >> 4);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0xFF00FF00) | ((pIn[i] & 0xFF00FF00) >> 8);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16);
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                pOut[i] = pOut[Step+i] = pIn[Step+i];
+            pIn += 2*Step;
+            pOut += 2*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes negative cofactor of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+int Kit_TruthVarIsVacuous( unsigned * pOnset, unsigned * pOffset, int nVars, int iVar )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            if ( ((pOnset[i] & (pOffset[i] >> 1)) | (pOffset[i] & (pOnset[i] >> 1))) & 0x55555555 )
+                 return 0;
+        return 1;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            if ( ((pOnset[i] & (pOffset[i] >> 2)) | (pOffset[i] & (pOnset[i] >> 2))) & 0x33333333 )
+                 return 0;
+            return 1;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            if ( ((pOnset[i] & (pOffset[i] >> 4)) | (pOffset[i] & (pOnset[i] >> 4))) & 0x0F0F0F0F )
+                 return 0;
+        return 1;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            if ( ((pOnset[i] & (pOffset[i] >> 8)) | (pOffset[i] & (pOnset[i] >> 8))) & 0x00FF00FF )
+                 return 0;
+        return 1;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            if ( ((pOnset[i] & (pOffset[i] >> 16)) | (pOffset[i] & (pOnset[i] >> 16))) & 0x0000FFFF )
+                 return 0;
+        return 1;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                if ( (pOnset[i] & pOffset[Step+i]) | (pOffset[i] & pOnset[Step+i]) )
+                     return 0;
+            pOnset += 2*Step;
+            pOffset += 2*Step;
+        }
+        return 1;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Existentially quantifies the variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthExist( unsigned * pTruth, int nVars, int iVar )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] |=  ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] |=  ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] |=  ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] |=  ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] |=  ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16);
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+            {
+                pTruth[i]     |= pTruth[Step+i];
+                pTruth[Step+i] = pTruth[i];
+            }
+            pTruth += 2*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Existentially quantifies the variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthExistNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pRes[i] =  pTruth[i] | ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pRes[i] =  pTruth[i] | ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pRes[i] =  pTruth[i] | ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pRes[i] =  pTruth[i] | ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pRes[i] =  pTruth[i] | ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16);
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+            {
+                pRes[i]      = pTruth[i] | pTruth[Step+i];
+                pRes[Step+i] = pRes[i];
+            }
+            pRes += 2*Step;
+            pTruth += 2*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Existantially quantifies the set of variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthExistSet( unsigned * pRes, unsigned * pTruth, int nVars, unsigned uMask )
+{
+    int v;
+    Kit_TruthCopy( pRes, pTruth, nVars );
+    for ( v = 0; v < nVars; v++ )
+        if ( uMask & (1 << v) )
+            Kit_TruthExist( pRes, nVars, v );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Unversally quantifies the variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthForall( unsigned * pTruth, int nVars, int iVar )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] &=  ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] &=  ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] &=  ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] &=  ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] &=  ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16);
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+            {
+                pTruth[i]     &= pTruth[Step+i];
+                pTruth[Step+i] = pTruth[i];
+            }
+            pTruth += 2*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Universally quantifies the variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthForallNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pRes[i] =  pTruth[i] & (((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1));
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pRes[i] =  pTruth[i] & (((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2));
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pRes[i] =  pTruth[i] & (((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4));
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pRes[i] =  pTruth[i] & (((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8));
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pRes[i] =  pTruth[i] & (((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16));
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+            {
+                pRes[i]      = pTruth[i] & pTruth[Step+i];
+                pRes[Step+i] = pRes[i];
+            }
+            pRes += 2*Step;
+            pTruth += 2*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Universally quantifies the variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthUniqueNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pRes[i] =  pTruth[i] ^ (((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1));
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pRes[i] =  pTruth[i] ^ (((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2));
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pRes[i] =  pTruth[i] ^ (((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4));
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pRes[i] =  pTruth[i] ^ (((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8));
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pRes[i] =  pTruth[i] ^ (((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16));
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+            {
+                pRes[i]      = pTruth[i] ^ pTruth[Step+i];
+                pRes[Step+i] = pRes[i];
+            }
+            pRes += 2*Step;
+            pTruth += 2*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of minterms in the Boolean difference.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_TruthBooleanDiffCount( unsigned * pTruth, int nVars, int iVar )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Step, Counter = 0;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >> 1)) & 0x55555555 );
+        return Counter;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >> 2)) & 0x33333333 );
+        return Counter;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >> 4)) & 0x0F0F0F0F );
+        return Counter;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >> 8)) & 0x00FF00FF );
+        return Counter;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >>16)) & 0x0000FFFF );
+        return Counter;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                Counter += Kit_WordCountOnes( pTruth[i] ^ pTruth[Step+i] );
+            pTruth += 2*Step;
+        }
+        return Counter;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of minterms in the Boolean difference.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_TruthXorCount( unsigned * pTruth0, unsigned * pTruth1, int nVars )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, Counter = 0;
+    for ( i = 0; i < nWords; i++ )
+        Counter += Kit_WordCountOnes( pTruth0[i] ^ pTruth1[i] );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Universally quantifies the set of variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthForallSet( unsigned * pRes, unsigned * pTruth, int nVars, unsigned uMask )
+{
+    int v;
+    Kit_TruthCopy( pRes, pTruth, nVars );
+    for ( v = 0; v < nVars; v++ )
+        if ( uMask & (1 << v) )
+            Kit_TruthForall( pRes, nVars, v );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Multiplexes two functions with the given variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthMuxVar( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pCof0[i] & 0x55555555) | (pCof1[i] & 0xAAAAAAAA);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pCof0[i] & 0x33333333) | (pCof1[i] & 0xCCCCCCCC);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pCof0[i] & 0x0F0F0F0F) | (pCof1[i] & 0xF0F0F0F0);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pCof0[i] & 0x00FF00FF) | (pCof1[i] & 0xFF00FF00);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pCof0[i] & 0x0000FFFF) | (pCof1[i] & 0xFFFF0000);
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+            {
+                pOut[i]      = pCof0[i];
+                pOut[Step+i] = pCof1[Step+i];
+            }
+            pOut += 2*Step;
+            pCof0 += 2*Step;
+            pCof1 += 2*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Multiplexes two functions with the given variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthMuxVarPhase( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar, int fCompl0 )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Step;
+
+    if ( fCompl0 == 0 )
+    {
+        Kit_TruthMuxVar( pOut, pCof0, pCof1, nVars, iVar );
+        return;
+    }
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (~pCof0[i] & 0x55555555) | (pCof1[i] & 0xAAAAAAAA);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (~pCof0[i] & 0x33333333) | (pCof1[i] & 0xCCCCCCCC);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (~pCof0[i] & 0x0F0F0F0F) | (pCof1[i] & 0xF0F0F0F0);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (~pCof0[i] & 0x00FF00FF) | (pCof1[i] & 0xFF00FF00);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (~pCof0[i] & 0x0000FFFF) | (pCof1[i] & 0xFFFF0000);
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+            {
+                pOut[i]      = ~pCof0[i];
+                pOut[Step+i] = pCof1[Step+i];
+            }
+            pOut += 2*Step;
+            pCof0 += 2*Step;
+            pCof1 += 2*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks symmetry of two variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1, unsigned * pCof0, unsigned * pCof1 )
+{
+    static unsigned uTemp0[32], uTemp1[32];
+    if ( pCof0 == NULL )
+    {
+        assert( nVars <= 10 );
+        pCof0 = uTemp0;
+    }
+    if ( pCof1 == NULL )
+    {
+        assert( nVars <= 10 );
+        pCof1 = uTemp1;
+    }
+    // compute Cof01
+    Kit_TruthCopy( pCof0, pTruth, nVars );
+    Kit_TruthCofactor0( pCof0, nVars, iVar0 );
+    Kit_TruthCofactor1( pCof0, nVars, iVar1 );
+    // compute Cof10
+    Kit_TruthCopy( pCof1, pTruth, nVars );
+    Kit_TruthCofactor1( pCof1, nVars, iVar0 );
+    Kit_TruthCofactor0( pCof1, nVars, iVar1 );
+    // compare
+    return Kit_TruthIsEqual( pCof0, pCof1, nVars );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks antisymmetry of two variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_TruthVarsAntiSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1, unsigned * pCof0, unsigned * pCof1 )
+{
+    static unsigned uTemp0[32], uTemp1[32];
+    if ( pCof0 == NULL )
+    {
+        assert( nVars <= 10 );
+        pCof0 = uTemp0;
+    }
+    if ( pCof1 == NULL )
+    {
+        assert( nVars <= 10 );
+        pCof1 = uTemp1;
+    }
+    // compute Cof00
+    Kit_TruthCopy( pCof0, pTruth, nVars );
+    Kit_TruthCofactor0( pCof0, nVars, iVar0 );
+    Kit_TruthCofactor0( pCof0, nVars, iVar1 );
+    // compute Cof11
+    Kit_TruthCopy( pCof1, pTruth, nVars );
+    Kit_TruthCofactor1( pCof1, nVars, iVar0 );
+    Kit_TruthCofactor1( pCof1, nVars, iVar1 );
+    // compare
+    return Kit_TruthIsEqual( pCof0, pCof1, nVars );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Changes phase of the function w.r.t. one variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthChangePhase( unsigned * pTruth, int nVars, int iVar )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Step;
+    unsigned Temp;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ((pTruth[i] & 0x55555555) << 1) | ((pTruth[i] & 0xAAAAAAAA) >> 1);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ((pTruth[i] & 0x33333333) << 2) | ((pTruth[i] & 0xCCCCCCCC) >> 2);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ((pTruth[i] & 0x0F0F0F0F) << 4) | ((pTruth[i] & 0xF0F0F0F0) >> 4);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ((pTruth[i] & 0x00FF00FF) << 8) | ((pTruth[i] & 0xFF00FF00) >> 8);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ((pTruth[i] & 0x0000FFFF) << 16) | ((pTruth[i] & 0xFFFF0000) >> 16);
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+            {
+                Temp = pTruth[i];
+                pTruth[i] = pTruth[Step+i];
+                pTruth[Step+i] = Temp;
+            }
+            pTruth += 2*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes minimum overlap in supports of cofactors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin )
+{
+    static unsigned uCofactor[16];
+    int i, ValueCur, ValueMin, VarMin;
+    unsigned uSupp0, uSupp1;
+    int nVars0, nVars1;
+    assert( nVars <= 9 );
+    ValueMin = 32;
+    VarMin   = -1;
+    for ( i = 0; i < nVars; i++ )
+    {
+        // get negative cofactor
+        Kit_TruthCopy( uCofactor, pTruth, nVars );
+        Kit_TruthCofactor0( uCofactor, nVars, i );
+        uSupp0 = Kit_TruthSupport( uCofactor, nVars );
+        nVars0 = Kit_WordCountOnes( uSupp0 );
+//Kit_PrintBinary( stdout, &uSupp0, 8 ); printf( "\n" );
+        // get positive cofactor
+        Kit_TruthCopy( uCofactor, pTruth, nVars );
+        Kit_TruthCofactor1( uCofactor, nVars, i );
+        uSupp1 = Kit_TruthSupport( uCofactor, nVars );
+        nVars1 = Kit_WordCountOnes( uSupp1 );
+//Kit_PrintBinary( stdout, &uSupp1, 8 ); printf( "\n" );
+        // get the number of common vars
+        ValueCur = Kit_WordCountOnes( uSupp0 & uSupp1 );
+        if ( ValueMin > ValueCur && nVars0 <= 5 && nVars1 <= 5 )
+        {
+            ValueMin = ValueCur;
+            VarMin = i;
+        }
+        if ( ValueMin == 0 )
+            break;
+    }
+    if ( pVarMin )
+        *pVarMin = VarMin;
+    return ValueMin;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Find the best cofactoring variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_TruthBestCofVar( unsigned * pTruth, int nVars, unsigned * pCof0, unsigned * pCof1 )
+{
+    int i, iBestVar, nSuppSizeCur0, nSuppSizeCur1, nSuppSizeCur, nSuppSizeMin;
+    if ( Kit_TruthIsConst0(pTruth, nVars) || Kit_TruthIsConst1(pTruth, nVars) )
+        return -1;
+    // iterate through variables
+    iBestVar = -1;
+    nSuppSizeMin = KIT_INFINITY;
+    for ( i = 0; i < nVars; i++ )
+    {
+        // cofactor the functiona and get support sizes
+        Kit_TruthCofactor0New( pCof0, pTruth, nVars, i );
+        Kit_TruthCofactor1New( pCof1, pTruth, nVars, i );
+        nSuppSizeCur0 = Kit_TruthSupportSize( pCof0, nVars );
+        nSuppSizeCur1 = Kit_TruthSupportSize( pCof1, nVars );
+        nSuppSizeCur  = nSuppSizeCur0 + nSuppSizeCur1;
+        // compare this variable with other variables
+        if ( nSuppSizeMin > nSuppSizeCur ) 
+        {
+            nSuppSizeMin = nSuppSizeCur;
+            iBestVar = i;
+        }
+    }
+    assert( iBestVar != -1 );
+    // cofactor w.r.t. this variable
+    Kit_TruthCofactor0New( pCof0, pTruth, nVars, iBestVar );
+    Kit_TruthCofactor1New( pCof1, pTruth, nVars, iBestVar );
+    return iBestVar;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of 1's in each cofactor.]
+
+  Description [The resulting numbers are stored in the array of ints, 
+  whose length is 2*nVars. The number of 1's is counted in a different
+  space than the original function. For example, if the function depends 
+  on k variables, the cofactors are assumed to depend on k-1 variables.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthCountOnesInCofs( unsigned * pTruth, int nVars, int * pStore )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Counter;
+    memset( pStore, 0, sizeof(int) * 2 * nVars );
+    if ( nVars <= 5 )
+    {
+        if ( nVars > 0 )
+        {
+            pStore[2*0+0] = Kit_WordCountOnes( pTruth[0] & 0x55555555 );
+            pStore[2*0+1] = Kit_WordCountOnes( pTruth[0] & 0xAAAAAAAA );
+        }
+        if ( nVars > 1 )
+        {
+            pStore[2*1+0] = Kit_WordCountOnes( pTruth[0] & 0x33333333 );
+            pStore[2*1+1] = Kit_WordCountOnes( pTruth[0] & 0xCCCCCCCC );
+        }
+        if ( nVars > 2 )
+        {
+            pStore[2*2+0] = Kit_WordCountOnes( pTruth[0] & 0x0F0F0F0F );
+            pStore[2*2+1] = Kit_WordCountOnes( pTruth[0] & 0xF0F0F0F0 );
+        }
+        if ( nVars > 3 )
+        {
+            pStore[2*3+0] = Kit_WordCountOnes( pTruth[0] & 0x00FF00FF );
+            pStore[2*3+1] = Kit_WordCountOnes( pTruth[0] & 0xFF00FF00 );
+        }
+        if ( nVars > 4 )
+        {
+            pStore[2*4+0] = Kit_WordCountOnes( pTruth[0] & 0x0000FFFF );
+            pStore[2*4+1] = Kit_WordCountOnes( pTruth[0] & 0xFFFF0000 );
+        }
+        return;
+    }
+    // nVars >= 6
+    // count 1's for all other variables
+    for ( k = 0; k < nWords; k++ )
+    {
+        Counter = Kit_WordCountOnes( pTruth[k] );
+        for ( i = 5; i < nVars; i++ )
+            if ( k & (1 << (i-5)) )
+                pStore[2*i+1] += Counter;
+            else
+                pStore[2*i+0] += Counter;
+    }
+    // count 1's for the first five variables
+    for ( k = 0; k < nWords/2; k++ )
+    {
+        pStore[2*0+0] += Kit_WordCountOnes( (pTruth[0] & 0x55555555) | ((pTruth[1] & 0x55555555) <<  1) );
+        pStore[2*0+1] += Kit_WordCountOnes( (pTruth[0] & 0xAAAAAAAA) | ((pTruth[1] & 0xAAAAAAAA) >>  1) );
+        pStore[2*1+0] += Kit_WordCountOnes( (pTruth[0] & 0x33333333) | ((pTruth[1] & 0x33333333) <<  2) );
+        pStore[2*1+1] += Kit_WordCountOnes( (pTruth[0] & 0xCCCCCCCC) | ((pTruth[1] & 0xCCCCCCCC) >>  2) );
+        pStore[2*2+0] += Kit_WordCountOnes( (pTruth[0] & 0x0F0F0F0F) | ((pTruth[1] & 0x0F0F0F0F) <<  4) );
+        pStore[2*2+1] += Kit_WordCountOnes( (pTruth[0] & 0xF0F0F0F0) | ((pTruth[1] & 0xF0F0F0F0) >>  4) );
+        pStore[2*3+0] += Kit_WordCountOnes( (pTruth[0] & 0x00FF00FF) | ((pTruth[1] & 0x00FF00FF) <<  8) );
+        pStore[2*3+1] += Kit_WordCountOnes( (pTruth[0] & 0xFF00FF00) | ((pTruth[1] & 0xFF00FF00) >>  8) );
+        pStore[2*4+0] += Kit_WordCountOnes( (pTruth[0] & 0x0000FFFF) | ((pTruth[1] & 0x0000FFFF) << 16) );
+        pStore[2*4+1] += Kit_WordCountOnes( (pTruth[0] & 0xFFFF0000) | ((pTruth[1] & 0xFFFF0000) >> 16) );
+        pTruth += 2;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of 1's in each negative cofactor.]
+
+  Description [The resulting numbers are stored in the array of ints, 
+  whose length is nVars. The number of 1's is counted in a different
+  space than the original function. For example, if the function depends 
+  on k variables, the cofactors are assumed to depend on k-1 variables.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthCountOnesInCofs0( unsigned * pTruth, int nVars, int * pStore )
+{
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, k, Counter;
+    memset( pStore, 0, sizeof(int) * nVars );
+    if ( nVars <= 5 )
+    {
+        if ( nVars > 0 )
+            pStore[0] = Kit_WordCountOnes( pTruth[0] & 0x55555555 );
+        if ( nVars > 1 )
+            pStore[1] = Kit_WordCountOnes( pTruth[0] & 0x33333333 );
+        if ( nVars > 2 )
+            pStore[2] = Kit_WordCountOnes( pTruth[0] & 0x0F0F0F0F );
+        if ( nVars > 3 )
+            pStore[3] = Kit_WordCountOnes( pTruth[0] & 0x00FF00FF );
+        if ( nVars > 4 )
+            pStore[4] = Kit_WordCountOnes( pTruth[0] & 0x0000FFFF );
+        return;
+    }
+    // nVars >= 6
+    // count 1's for all other variables
+    for ( k = 0; k < nWords; k++ )
+    {
+        Counter = Kit_WordCountOnes( pTruth[k] );
+        for ( i = 5; i < nVars; i++ )
+            if ( (k & (1 << (i-5))) == 0 )
+                pStore[i] += Counter;
+    }
+    // count 1's for the first five variables
+    for ( k = 0; k < nWords/2; k++ )
+    {
+        pStore[0] += Kit_WordCountOnes( (pTruth[0] & 0x55555555) | ((pTruth[1] & 0x55555555) <<  1) );
+        pStore[1] += Kit_WordCountOnes( (pTruth[0] & 0x33333333) | ((pTruth[1] & 0x33333333) <<  2) );
+        pStore[2] += Kit_WordCountOnes( (pTruth[0] & 0x0F0F0F0F) | ((pTruth[1] & 0x0F0F0F0F) <<  4) );
+        pStore[3] += Kit_WordCountOnes( (pTruth[0] & 0x00FF00FF) | ((pTruth[1] & 0x00FF00FF) <<  8) );
+        pStore[4] += Kit_WordCountOnes( (pTruth[0] & 0x0000FFFF) | ((pTruth[1] & 0x0000FFFF) << 16) );
+        pTruth += 2;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of 1's in each cofactor.]
+
+  Description [Verifies the above procedure.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthCountOnesInCofsSlow( unsigned * pTruth, int nVars, int * pStore, unsigned * pAux )
+{
+    int i;
+    for ( i = 0; i < nVars; i++ )
+    {
+        Kit_TruthCofactor0New( pAux, pTruth, nVars, i );
+        pStore[2*i+0] = Kit_TruthCountOnes( pAux, nVars ) / 2;
+        Kit_TruthCofactor1New( pAux, pTruth, nVars, i );
+        pStore[2*i+1] = Kit_TruthCountOnes( pAux, nVars ) / 2;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Canonicize the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Kit_TruthHash( unsigned * pIn, int nWords )
+{
+    // The 1,024 smallest prime numbers used to compute the hash value
+    // http://www.math.utah.edu/~alfeld/math/primelist.html
+    static int HashPrimes[1024] = { 2, 3, 5, 
+    7, 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, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 
+    641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 
+    757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 
+    881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 
+    1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 
+    1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 
+    1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 
+    1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 
+    1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 
+    1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 
+    1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 
+    1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 
+    1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 
+    1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 
+    2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 
+    2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 
+    2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 
+    2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 
+    2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 
+    2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 
+    2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 
+    2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 
+    2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 
+    3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 
+    3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 
+    3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 
+    3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 
+    3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 
+    3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 
+    3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 
+    3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 
+    3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 
+    4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 
+    4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 
+    4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 
+    4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 
+    4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 
+    4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 
+    4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 
+    4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 
+    5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 
+    5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 
+    5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 
+    5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 
+    5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 
+    5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 
+    5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 
+    5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 
+    6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 
+    6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 
+    6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 
+    6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 
+    6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 
+    6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 
+    6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 
+    6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 
+    6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 
+    7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 
+    7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 
+    7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 
+    7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 
+    7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 
+    7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 
+    7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 
+    8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, 
+    8147, 8161 };
+    int i;
+    unsigned uHashKey;
+    assert( nWords <= 1024 );
+    uHashKey = 0;
+    for ( i = 0; i < nWords; i++ )
+        uHashKey ^= HashPrimes[i] * pIn[i];
+    return uHashKey;
+}
+
+ 
+/**Function*************************************************************
+
+  Synopsis    [Canonicize the truth table.]
+
+  Description [Returns the phase. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Kit_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm )
+{
+    int pStore[32];
+    unsigned * pIn = pInOut, * pOut = pAux, * pTemp;
+    int nWords = Kit_TruthWordNum( nVars );
+    int i, Temp, fChange, Counter, nOnes;//, k, j, w, Limit;
+    unsigned uCanonPhase;
+
+    // canonicize output
+    uCanonPhase = 0;
+    for ( i = 0; i < nVars; i++ )
+        pCanonPerm[i] = i;
+
+    nOnes = Kit_TruthCountOnes(pIn, nVars);
+    //if(pIn[0] & 1)
+    if ( (nOnes > nWords * 16) )//|| ((nOnes == nWords * 16) && (pIn[0] & 1)) )
+    {
+        uCanonPhase |= (1 << nVars);
+        Kit_TruthNot( pIn, pIn, nVars );
+    }
+
+    // collect the minterm counts
+    Kit_TruthCountOnesInCofs( pIn, nVars, pStore );
+/*
+    Kit_TruthCountOnesInCofsSlow( pIn, nVars, pStore2, pAux );
+    for ( i = 0; i < 2*nVars; i++ )
+    {
+        assert( pStore[i] == pStore2[i] );
+    }
+*/
+    // canonicize phase
+    for ( i = 0; i < nVars; i++ )
+    {
+        if ( pStore[2*i+0] >= pStore[2*i+1] )
+            continue;
+        uCanonPhase |= (1 << i);
+        Temp = pStore[2*i+0];
+        pStore[2*i+0] = pStore[2*i+1];
+        pStore[2*i+1] = Temp;
+        Kit_TruthChangePhase( pIn, nVars, i );
+    }
+
+//    Kit_PrintHexadecimal( stdout, pIn, nVars );
+//    printf( "\n" );
+
+    // permute
+    Counter = 0;
+    do {
+        fChange = 0;
+        for ( i = 0; i < nVars-1; i++ )
+        {
+            if ( pStore[2*i] >= pStore[2*(i+1)] )
+                continue;
+            Counter++;
+            fChange = 1;
+
+            Temp = pCanonPerm[i];
+            pCanonPerm[i] = pCanonPerm[i+1];
+            pCanonPerm[i+1] = Temp;
+
+            Temp = pStore[2*i];
+            pStore[2*i] = pStore[2*(i+1)];
+            pStore[2*(i+1)] = Temp;
+
+            Temp = pStore[2*i+1];
+            pStore[2*i+1] = pStore[2*(i+1)+1];
+            pStore[2*(i+1)+1] = Temp;
+
+            // if the polarity of variables is different, swap them
+            if ( ((uCanonPhase & (1 << i)) > 0) != ((uCanonPhase & (1 << (i+1))) > 0) )
+            {
+                uCanonPhase ^= (1 << i);
+                uCanonPhase ^= (1 << (i+1));
+            }
+
+            Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i );
+            pTemp = pIn; pIn = pOut; pOut = pTemp;
+        }
+    } while ( fChange );
+
+
+/*
+    Extra_PrintBinary( stdout, &uCanonPhase, nVars+1 ); printf( " : " );
+    for ( i = 0; i < nVars; i++ )
+        printf( "%d=%d/%d  ", pCanonPerm[i], pStore[2*i], pStore[2*i+1] );
+    printf( "  C = %d\n", Counter );
+    Extra_PrintHexadecimal( stdout, pIn, nVars );
+    printf( "\n" );
+*/
+
+/*
+    // process symmetric variable groups
+    uSymms = 0;
+    for ( i = 0; i < nVars-1; i++ )
+    {
+        if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric
+            continue;
+        if ( pStore[2*i] != pStore[2*i+1] )
+            continue;
+        if ( Kit_TruthVarsSymm( pIn, nVars, i, i+1 ) )
+            continue;
+        if ( Kit_TruthVarsAntiSymm( pIn, nVars, i, i+1 ) )
+            Kit_TruthChangePhase( pIn, nVars, i+1 );
+    }
+*/
+
+/*
+    // process symmetric variable groups
+    uSymms = 0;
+    for ( i = 0; i < nVars-1; i++ )
+    {
+        if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric
+            continue;
+        // i and i+1 can be symmetric
+        // find the end of this group
+        for ( k = i+1; k < nVars; k++ )
+            if ( pStore[2*i] != pStore[2*k] ) 
+                break;
+        Limit = k;
+        assert( i < Limit-1 );
+        // go through the variables in this group
+        for ( j = i + 1; j < Limit; j++ )
+        {
+            // check symmetry
+            if ( Kit_TruthVarsSymm( pIn, nVars, i, j ) )
+            {
+                uSymms |= (1 << j);
+                continue;
+            }
+            // they are phase-unknown
+            if ( pStore[2*i] == pStore[2*i+1] ) 
+            {
+                if ( Kit_TruthVarsAntiSymm( pIn, nVars, i, j ) )
+                {
+                    Kit_TruthChangePhase( pIn, nVars, j );
+                    uCanonPhase ^= (1 << j);
+                    uSymms |= (1 << j);
+                    continue;
+                }
+            }
+
+            // they are not symmetric - move j as far as it goes in the group
+            for ( k = j; k < Limit-1; k++ )
+            {
+                Counter++;
+
+                Temp = pCanonPerm[k];
+                pCanonPerm[k] = pCanonPerm[k+1];
+                pCanonPerm[k+1] = Temp;
+
+                assert( pStore[2*k] == pStore[2*(k+1)] );
+                Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, k );
+                pTemp = pIn; pIn = pOut; pOut = pTemp;
+            }
+            Limit--;
+            j--;
+        }
+        i = Limit - 1;
+    }
+*/
+
+    // swap if it was moved an even number of times
+    if ( Counter & 1 )
+        Kit_TruthCopy( pOut, pIn, nVars );
+    return uCanonPhase;
+}
+
+ 
+/**Function*************************************************************
+
+  Synopsis    [Fast counting minterms in the cofactors of a function.]
+
+  Description [Returns the total number of minterms in the function.
+  The resulting array (pRes) contains the number of minterms in 0-cofactor
+  w.r.t. each variables. The additional array (pBytes) is used for internal 
+  storage. It should have the size equal to the number of truth table bytes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Kit_TruthCountMinterms( unsigned * pTruth, int nVars, int * pRes, int * pBytesInit )
+{
+    // the number of 1s if every byte as well as in the 0-cofactors w.r.t. three variables
+    static unsigned Table[256] = {
+        0x00000000, 0x01010101, 0x01010001, 0x02020102, 0x01000101, 0x02010202, 0x02010102, 0x03020203,
+        0x01000001, 0x02010102, 0x02010002, 0x03020103, 0x02000102, 0x03010203, 0x03010103, 0x04020204,
+        0x00010101, 0x01020202, 0x01020102, 0x02030203, 0x01010202, 0x02020303, 0x02020203, 0x03030304,
+        0x01010102, 0x02020203, 0x02020103, 0x03030204, 0x02010203, 0x03020304, 0x03020204, 0x04030305,
+        0x00010001, 0x01020102, 0x01020002, 0x02030103, 0x01010102, 0x02020203, 0x02020103, 0x03030204,
+        0x01010002, 0x02020103, 0x02020003, 0x03030104, 0x02010103, 0x03020204, 0x03020104, 0x04030205,
+        0x00020102, 0x01030203, 0x01030103, 0x02040204, 0x01020203, 0x02030304, 0x02030204, 0x03040305,
+        0x01020103, 0x02030204, 0x02030104, 0x03040205, 0x02020204, 0x03030305, 0x03030205, 0x04040306,
+        0x00000101, 0x01010202, 0x01010102, 0x02020203, 0x01000202, 0x02010303, 0x02010203, 0x03020304,
+        0x01000102, 0x02010203, 0x02010103, 0x03020204, 0x02000203, 0x03010304, 0x03010204, 0x04020305,
+        0x00010202, 0x01020303, 0x01020203, 0x02030304, 0x01010303, 0x02020404, 0x02020304, 0x03030405,
+        0x01010203, 0x02020304, 0x02020204, 0x03030305, 0x02010304, 0x03020405, 0x03020305, 0x04030406,
+        0x00010102, 0x01020203, 0x01020103, 0x02030204, 0x01010203, 0x02020304, 0x02020204, 0x03030305,
+        0x01010103, 0x02020204, 0x02020104, 0x03030205, 0x02010204, 0x03020305, 0x03020205, 0x04030306,
+        0x00020203, 0x01030304, 0x01030204, 0x02040305, 0x01020304, 0x02030405, 0x02030305, 0x03040406,
+        0x01020204, 0x02030305, 0x02030205, 0x03040306, 0x02020305, 0x03030406, 0x03030306, 0x04040407,
+        0x00000001, 0x01010102, 0x01010002, 0x02020103, 0x01000102, 0x02010203, 0x02010103, 0x03020204,
+        0x01000002, 0x02010103, 0x02010003, 0x03020104, 0x02000103, 0x03010204, 0x03010104, 0x04020205,
+        0x00010102, 0x01020203, 0x01020103, 0x02030204, 0x01010203, 0x02020304, 0x02020204, 0x03030305,
+        0x01010103, 0x02020204, 0x02020104, 0x03030205, 0x02010204, 0x03020305, 0x03020205, 0x04030306,
+        0x00010002, 0x01020103, 0x01020003, 0x02030104, 0x01010103, 0x02020204, 0x02020104, 0x03030205,
+        0x01010003, 0x02020104, 0x02020004, 0x03030105, 0x02010104, 0x03020205, 0x03020105, 0x04030206,
+        0x00020103, 0x01030204, 0x01030104, 0x02040205, 0x01020204, 0x02030305, 0x02030205, 0x03040306,
+        0x01020104, 0x02030205, 0x02030105, 0x03040206, 0x02020205, 0x03030306, 0x03030206, 0x04040307,
+        0x00000102, 0x01010203, 0x01010103, 0x02020204, 0x01000203, 0x02010304, 0x02010204, 0x03020305,
+        0x01000103, 0x02010204, 0x02010104, 0x03020205, 0x02000204, 0x03010305, 0x03010205, 0x04020306,
+        0x00010203, 0x01020304, 0x01020204, 0x02030305, 0x01010304, 0x02020405, 0x02020305, 0x03030406,
+        0x01010204, 0x02020305, 0x02020205, 0x03030306, 0x02010305, 0x03020406, 0x03020306, 0x04030407,
+        0x00010103, 0x01020204, 0x01020104, 0x02030205, 0x01010204, 0x02020305, 0x02020205, 0x03030306,
+        0x01010104, 0x02020205, 0x02020105, 0x03030206, 0x02010205, 0x03020306, 0x03020206, 0x04030307,
+        0x00020204, 0x01030305, 0x01030205, 0x02040306, 0x01020305, 0x02030406, 0x02030306, 0x03040407,
+        0x01020205, 0x02030306, 0x02030206, 0x03040307, 0x02020306, 0x03030407, 0x03030307, 0x04040408
+    };
+    unsigned uSum;
+    unsigned char * pTruthC, * pLimit;
+    int * pBytes = pBytesInit;
+    int i, iVar, Step, nWords, nBytes, nTotal;
+
+    assert( nVars <= 20 );
+
+    // clear storage
+    memset( pRes, 0, sizeof(int) * nVars );
+
+    // count the number of one's in 0-cofactors of the first three variables
+    nTotal = uSum = 0;
+    nWords = Kit_TruthWordNum( nVars );
+    nBytes = nWords * 4;
+    pTruthC = (unsigned char *)pTruth;
+    pLimit = pTruthC + nBytes;
+    for ( ; pTruthC < pLimit; pTruthC++ )
+    {
+        uSum += Table[*pTruthC];
+        *pBytes++ = (Table[*pTruthC] & 0xff);
+        if ( (uSum & 0xff) > 246 )
+        {
+            nTotal += (uSum & 0xff);
+            pRes[0] += ((uSum >>  8) & 0xff);
+            pRes[2] += ((uSum >> 16) & 0xff);
+            pRes[3] += ((uSum >> 24) & 0xff);
+            uSum = 0;
+        }
+    }
+    if ( uSum )
+    {
+        nTotal += (uSum & 0xff);
+        pRes[0] += ((uSum >>  8) & 0xff);
+        pRes[1] += ((uSum >> 16) & 0xff);
+        pRes[2] += ((uSum >> 24) & 0xff);
+    }
+
+    // count all other variables
+    for ( iVar = 3, Step = 1; Step < nBytes; Step *= 2, iVar++ )
+        for ( i = 0; i < nBytes; i += Step + Step )
+        {
+            pRes[iVar] += pBytesInit[i];
+            pBytesInit[i] += pBytesInit[i+Step];
+        }
+    assert( pBytesInit[0] == nTotal );
+    assert( iVar == nVars );
+
+    for ( i = 0; i < nVars; i++ )
+        assert( pRes[i] == Kit_TruthCofactor0Count(pTruth, nVars, i) );
+    return nTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the hex unsigned into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars )
+{
+    int nDigits, Digit, k;
+    // write the number into the file
+    nDigits = (1 << nVars) / 4;
+    for ( k = nDigits - 1; k >= 0; k-- )
+    {
+        Digit = ((Sign[k/8] >> ((k%8) * 4)) & 15);
+        if ( Digit < 10 )
+            fprintf( pFile, "%d", Digit );
+        else
+            fprintf( pFile, "%c", 'a' + Digit-10 );
+    }
+//    fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fast counting minterms for the functions.]
+
+  Description [Returns 0 if the function is a constant.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthCountMintermsPrecomp()
+{
+    int bit_count[256] = {
+      0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+      3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+    };
+    unsigned i, uWord;
+    for ( i = 0; i < 256; i++ )
+    {
+        if ( i % 8 == 0 )
+            printf( "\n" );
+        uWord  =  bit_count[i];
+        uWord |= (bit_count[i & 0x55] <<  8);
+        uWord |= (bit_count[i & 0x33] << 16);
+        uWord |= (bit_count[i & 0x0f] << 24);
+        printf( "0x" );
+        Kit_PrintHexadecimal( stdout, &uWord, 5 );
+        printf( ", " );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dumps truth table into a file.]
+
+  Description [Generates script file for reading into ABC.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Kit_TruthDumpToFile( unsigned * pTruth, int nVars, int nFile )
+{
+    static char pFileName[100];
+    FILE * pFile;
+    sprintf( pFileName, "tt\\s%04d", nFile );
+    pFile = fopen( pFileName, "w" );
+    fprintf( pFile, "rt " );
+    Kit_PrintHexadecimal( pFile, pTruth, nVars );
+    fprintf( pFile, "; bdd; sop; ps\n" );
+    fclose( pFile );
+    return pFileName;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Dumps truth table into a file.]
+
+  Description [Generates script file for reading into ABC.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthPrintProfile_int( unsigned * pTruth, int nVars )
+{
+    int Mints[20];
+    int Mints0[20];
+    int Mints1[20];
+    int Unique1[20];
+    int Total2[20][20];
+    int Unique2[20][20];
+    int Common2[20][20];
+    int nWords = Kit_TruthWordNum( nVars );
+    int * pBytes    = ABC_ALLOC( int, nWords * 4 );
+    unsigned * pIn  = ABC_ALLOC( unsigned, nWords );
+    unsigned * pOut = ABC_ALLOC( unsigned, nWords );
+    unsigned * pCof00 = ABC_ALLOC( unsigned, nWords );
+    unsigned * pCof01 = ABC_ALLOC( unsigned, nWords );
+    unsigned * pCof10 = ABC_ALLOC( unsigned, nWords );
+    unsigned * pCof11 = ABC_ALLOC( unsigned, nWords );
+    unsigned * pTemp;
+    int nTotalMints, nTotalMints0, nTotalMints1;
+    int v, u, i, iVar, nMints1;
+    int Cof00, Cof01, Cof10, Cof11;
+    int Coz00, Coz01, Coz10, Coz11;
+    assert( nVars <= 20 );
+    assert( nVars >=  6 );
+
+    nTotalMints = Kit_TruthCountMinterms( pTruth, nVars, Mints, pBytes );
+    for ( v = 0; v < nVars; v++ )
+        Unique1[v] = Kit_TruthBooleanDiffCount( pTruth, nVars, v );
+
+    for ( v = 0; v < nVars; v++ )
+    for ( u = 0; u < nVars; u++ )
+        Total2[v][u] = Unique2[v][u] = Common2[v][u] = -1;
+
+    nMints1 = (1<<(nVars-2));
+    for ( v = 0; v < nVars; v++ )
+    {
+        // move this var to be the first
+        Kit_TruthCopy( pIn, pTruth, nVars );
+//        Extra_PrintBinary( stdout, pIn, (1<<nVars) ); printf( "\n" );
+        for ( i = v; i < nVars - 1; i++ )
+        {
+            Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i );
+            pTemp = pIn; pIn = pOut; pOut = pTemp;
+        }
+//        Extra_PrintBinary( stdout, pIn, (1<<nVars) ); printf( "\n" );
+//        printf( "\n" );
+
+
+        // count minterms in both cofactor
+        nTotalMints0 = Kit_TruthCountMinterms( pIn,          nVars-1, Mints0, pBytes );
+        nTotalMints1 = Kit_TruthCountMinterms( pIn+nWords/2, nVars-1, Mints1, pBytes );
+        assert( nTotalMints == nTotalMints0 + nTotalMints1 );
+/*
+        for ( u = 0; u < nVars-1; u++ )
+            printf( "%2d ", Mints0[u] );
+        printf( "\n" );
+
+        for ( u = 0; u < nVars-1; u++ )
+            printf( "%2d ", Mints1[u] );
+        printf( "\n" );
+*/
+        for ( u = 0; u < nVars-1; u++ )
+        {
+            if ( u < v )
+                iVar = u;
+            else 
+                iVar = u + 1;
+            assert( v != iVar );
+            // get minter counts in the cofactors
+            Cof00 =              Mints0[u]; Coz00 = nMints1 - Cof00;              
+            Cof01 = nTotalMints0-Mints0[u]; Coz01 = nMints1 - Cof01;
+            Cof10 =              Mints1[u]; Coz10 = nMints1 - Cof10;
+            Cof11 = nTotalMints1-Mints1[u]; Coz11 = nMints1 - Cof11;
+
+            assert( Cof00 >= 0 && Cof00 <= nMints1 );
+            assert( Cof01 >= 0 && Cof01 <= nMints1 );
+            assert( Cof10 >= 0 && Cof10 <= nMints1 );
+            assert( Cof11 >= 0 && Cof11 <= nMints1 );
+
+            assert( Coz00 >= 0 && Coz00 <= nMints1 );
+            assert( Coz01 >= 0 && Coz01 <= nMints1 );
+            assert( Coz10 >= 0 && Coz10 <= nMints1 );
+            assert( Coz11 >= 0 && Coz11 <= nMints1 );
+
+            Common2[v][iVar] = Common2[iVar][v] = Cof00 * Coz11 + Coz00 * Cof11 + Cof01 * Coz10 + Coz01 * Cof10;
+
+            Total2[v][iVar] = Total2[iVar][v] = 
+                Cof00 * Coz01 + Coz00 * Cof01 + 
+                Cof00 * Coz10 + Coz00 * Cof10 + 
+                Cof00 * Coz11 + Coz00 * Cof11 + 
+                Cof01 * Coz10 + Coz01 * Cof10 + 
+                Cof01 * Coz11 + Coz01 * Cof11 + 
+                Cof10 * Coz11 + Coz10 * Cof11 ;
+
+            
+            Kit_TruthCofactor0New( pCof00, pIn,          nVars-1, u );
+            Kit_TruthCofactor1New( pCof01, pIn,          nVars-1, u );
+            Kit_TruthCofactor0New( pCof10, pIn+nWords/2, nVars-1, u );
+            Kit_TruthCofactor1New( pCof11, pIn+nWords/2, nVars-1, u );
+
+            Unique2[v][iVar] = Unique2[iVar][v] = 
+                Kit_TruthXorCount( pCof00, pCof01, nVars-1 ) +
+                Kit_TruthXorCount( pCof00, pCof10, nVars-1 ) +
+                Kit_TruthXorCount( pCof00, pCof11, nVars-1 ) +
+                Kit_TruthXorCount( pCof01, pCof10, nVars-1 ) +
+                Kit_TruthXorCount( pCof01, pCof11, nVars-1 ) +
+                Kit_TruthXorCount( pCof10, pCof11, nVars-1 );
+        }
+    }
+
+    printf( "\n" );
+    printf( " V: " );
+    for ( v = 0; v < nVars; v++ )
+        printf( "%8c  ", v+'a' );
+    printf( "\n" );
+
+    printf( " M: " );
+    for ( v = 0; v < nVars; v++ )
+        printf( "%8d  ", Mints[v] );
+    printf( "\n" );
+
+    printf( " U: " );
+    for ( v = 0; v < nVars; v++ )
+        printf( "%8d  ", Unique1[v] );
+    printf( "\n" );
+    printf( "\n" );
+
+    printf( "Unique:\n" );
+    for ( i = 0; i < nVars; i++ )
+    {
+    printf( " %2d ", i );
+    for ( v = 0; v < nVars; v++ )
+        printf( "%8d  ", Unique2[i][v] );
+    printf( "\n" );
+    }
+
+    printf( "Common:\n" );
+    for ( i = 0; i < nVars; i++ )
+    {
+    printf( " %2d ", i );
+    for ( v = 0; v < nVars; v++ )
+        printf( "%8d  ", Common2[i][v] );
+    printf( "\n" );
+    }
+
+    printf( "Total:\n" );
+    for ( i = 0; i < nVars; i++ )
+    {
+    printf( " %2d ", i );
+    for ( v = 0; v < nVars; v++ )
+        printf( "%8d  ", Total2[i][v] );
+    printf( "\n" );
+    }
+
+    ABC_FREE( pIn );
+    ABC_FREE( pOut );
+    ABC_FREE( pCof00 );
+    ABC_FREE( pCof01 );
+    ABC_FREE( pCof10 );
+    ABC_FREE( pCof11 );
+    ABC_FREE( pBytes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dumps truth table into a file.]
+
+  Description [Generates script file for reading into ABC.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Kit_TruthPrintProfile( unsigned * pTruth, int nVars )
+{
+    unsigned uTruth[2];
+    if ( nVars >= 6 )
+    {
+        Kit_TruthPrintProfile_int( pTruth, nVars );
+        return;
+    }
+    assert( nVars >= 2 );
+    uTruth[0] = pTruth[0];
+    uTruth[1] = pTruth[0];
+    Kit_TruthPrintProfile( uTruth, 6 );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/kit/kit_.c b/abc-build/src/bool/kit/kit_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/kit_.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+  FileName    [kit_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Computation kit.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 6, 2006.]
+
+  Revision    [$Id: kit_.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/kit/module.make b/abc-build/src/bool/kit/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/kit/module.make
@@ -0,0 +1,11 @@
+SRC +=  src/bool/kit/kitAig.c \
+	src/bool/kit/kitBdd.c \
+	src/bool/kit/kitCloud.c src/bool/kit/cloud.c \
+	src/bool/kit/kitDsd.c \
+	src/bool/kit/kitFactor.c \
+	src/bool/kit/kitGraph.c \
+	src/bool/kit/kitHop.c \
+	src/bool/kit/kitIsop.c \
+	src/bool/kit/kitPla.c \
+	src/bool/kit/kitSop.c \
+	src/bool/kit/kitTruth.c
diff --git a/abc-build/src/bool/lucky/lucky.c b/abc-build/src/bool/lucky/lucky.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/lucky/lucky.c
@@ -0,0 +1,705 @@
+/**CFile****************************************************************
+
+  FileName    [lucky.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Semi-canonical form computation package.]
+
+  Synopsis    [Truth table minimization procedures.]
+
+  Author      [Jake]
+
+  Date        [Started - August 2012]
+
+***********************************************************************/
+
+#include "luckyInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+int memCompare(word* x, word*  y, int nVars)
+{
+    int i;
+    for(i=Kit_TruthWordNum_64bit( nVars )-1;i>=0;i--)
+    {
+        if(x[i]==y[i])
+            continue;
+        else if(x[i]>y[i])
+            return 1;
+        else
+            return -1;
+    }
+    return 0;
+}
+///////sort Word* a///////////////////////////////////////////////////////////////////////////////////////////////////////
+ int compareWords1 (const void * a, const void * b)
+ {
+     if( *(word*)a > *(word*)b )
+         return 1;
+     else
+         return( *(word*)a < *(word*)b ) ? -1: 0;
+     
+ }
+ 
+ void sortAndUnique1(word* a, Abc_TtStore_t* p)
+ {
+     int i, count=1, WordsN = p->nFuncs;
+     word tempWord;
+     qsort(a,WordsN,sizeof(word),compareWords1);
+     tempWord = a[0];
+     for(i=1;i<WordsN;i++)  
+         if(tempWord != a[i])
+         {
+             a[count] = a[i];
+             tempWord = a[i];
+             count++;
+         }
+         p->nFuncs = count;
+}
+//////////sort Word** a//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+int compareWords2 (const void ** x, const void ** y)
+{
+    
+    if(**(word**)x > **(word**)y)
+        return 1;
+    else if(**(word**)x < **(word**)y)
+        return -1;
+    else
+        return 0;   
+    
+}
+int compareWords (const void ** a, const void ** b)
+{
+     if( memcmp(*(word**)a,*(word**)b,sizeof(word)*1) > 0 )
+         return 1;
+     else
+         return ( memcmp(*(word**)a,*(word**)b,sizeof(word)*1) < 0 ) ? -1: 0;       
+}
+int compareWords3 (const void ** x, const void ** y)
+{
+    return memCompare(*(word**)x, *(word**)y, 16);   
+} 
+void sortAndUnique(word** a, Abc_TtStore_t* p)
+{
+     int i, count=1, WordsPtrN = p->nFuncs;
+     word* tempWordPtr;
+     qsort(a,WordsPtrN,sizeof(word*),(int(*)(const void *,const void *))compareWords3);
+     tempWordPtr = a[0];
+     for(i=1;i<WordsPtrN;i++)   
+         if(memcmp(a[i],tempWordPtr,sizeof(word)*(p->nWords)) != 0)
+         {
+             a[count] = a[i];
+             tempWordPtr = a[i];
+             count++;
+         }
+         p->nFuncs = count;
+}
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+typedef struct
+{
+     int totalCycles;
+     int maxNCycles;
+     int minNCycles;
+     
+}cycleCtr;
+cycleCtr* setCycleCtrPtr()
+{
+     cycleCtr* x = (cycleCtr*) malloc(sizeof(cycleCtr));
+     x->totalCycles=0;
+     x->maxNCycles=0;
+     x->minNCycles=111111111;
+     return x;
+}
+void freeCycleCtr(cycleCtr* x)
+{
+    free(x);
+}
+word** makeArray(Abc_TtStore_t* p)
+{
+    int i;
+    word** a;
+    a = (word**)malloc(sizeof(word*)*(p->nFuncs));
+    for(i=0;i<p->nFuncs;i++)
+    {
+        a[i] = (word*)malloc(sizeof(word)*(p->nWords));
+        memcpy(a[i],p->pFuncs[i],sizeof(word)*(p->nWords));
+
+    }
+    return a;
+}
+void freeArray(word** a,Abc_TtStore_t* p)
+{
+    int i;
+    for(i=0;i<p->nFuncs;i++)
+        free(a[i]);
+    free(a);
+}
+
+word* makeArrayB(word** a, int nFuncs)
+{
+    int i;
+    word* b;
+    b = (word*)malloc(sizeof(word)*(nFuncs));
+    for(i=0;i<nFuncs;i++)
+        b[i] = a[i][0];
+
+    return b;
+}
+void freeArrayB(word* b)
+{
+    free(b);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+
+// if highest bit in F ( all ones min term ) is one => inverse 
+// if pInOnt changed(minimized) by function return 1 if not 0
+// int minimalInitialFlip_propper(word* pInOut, word* pDuplicat, int  nVars)
+// {
+//  word oneWord=1;
+//  Kit_TruthCopy_64bit( pDuplicat, pInOut, nVars );
+//  Kit_TruthNot_64bit( pDuplicat, nVars );
+//  if( memCompare(pDuplicat,pInOut,nVars) == -1)
+//  {
+//      Kit_TruthCopy_64bit(pInOut, pDuplicat, nVars );
+//      return 1;
+//  }
+//  return 0;
+// }
+// int minimalFlip(word* pInOut, word* pMinimal, word* PDuplicat, int  nVars) 
+// {
+//  int i;
+//  int blockSize = Kit_TruthWordNum_64bit( nVars )*sizeof(word);
+//  memcpy(pMinimal, pInOut, blockSize);
+//  memcpy(PDuplicat, pInOut, blockSize);
+//  for(i=0;i<nVars;i++)
+//  {
+//      Kit_TruthChangePhase_64bit( pInOut, nVars, i );
+//      if( memCompare(pMinimal,pInOut,nVars) == 1)
+//          memcpy(pMinimal, pInOut, blockSize);
+//      memcpy(pInOut,PDuplicat,blockSize);
+//  }
+//  memcpy(pInOut,pMinimal,blockSize);
+//  if(memCompare(pMinimal,PDuplicat,nVars) == 0)
+//      return 0;
+//  else
+//      return 1;
+// }
+// int minimalSwap(word* pInOut, word* pMinimal, word* PDuplicat, int  nVars) 
+// {
+//  int i;  
+//  int blockSize = Kit_TruthWordNum_64bit( nVars )*sizeof(word);
+//  memcpy(pMinimal, pInOut, blockSize);
+//  memcpy(PDuplicat, pInOut, blockSize);
+//  for(i=0;i<nVars-1;i++)
+//  {
+//      Kit_TruthSwapAdjacentVars_64bit( pInOut, nVars, i );
+//      if(memCompare(pMinimal,pInOut,nVars) == 1)
+//          memcpy(pMinimal, pInOut, blockSize);
+//      memcpy(pInOut,PDuplicat,blockSize);
+//  }
+//  memcpy(pInOut,pMinimal,blockSize);
+//  if(memCompare(pMinimal,PDuplicat,nVars) == 0)
+//      return 0;
+//  else
+//      return 1;
+// }
+// 
+// void luckyCanonicizer(word* pInOut, word* pAux, word* pAux1, int  nVars, cycleCtr* cCtr)
+// {
+//  int counter=1, cycles=0;   
+//  assert( nVars <= 16 );
+//  while(counter>0 )   //  && cycles < 10 if we wanna limit cycles
+//  {
+//      counter=0;
+//      counter += minimalInitialFlip(pInOut, nVars);
+//      counter += minimalFlip(pInOut, pAux, pAux1, nVars);
+//      counter += minimalSwap(pInOut, pAux, pAux1, nVars);
+//      cCtr->totalCycles++;
+//      cycles++;
+//  }
+//  if(cycles < cCtr->minNCycles)
+//      cCtr->minNCycles = cycles;
+//  else if(cycles > cCtr->maxNCycles)
+//      cCtr->maxNCycles = cycles;
+// }
+//  runs paralel F and ~F in luckyCanonicizer
+// void luckyCanonicizer2(word* pInOut, word* pAux, word* pAux1, word* temp, int  nVars)
+// {
+//  int nWords = Kit_TruthWordNum_64bit( nVars );
+//  int counter=1, nOnes;   
+//  assert( nVars <= 16 );
+//  nOnes = Kit_TruthCountOnes_64bit(pInOut, nVars);
+//  
+//     if ( (nOnes*2 == nWords * 32) )
+//     { 
+//      Kit_TruthCopy_64bit( temp, pInOut, nVars );
+//      Kit_TruthNot_64bit( temp, nVars );
+//         luckyCanonicizer1_simple(pInOut, pAux, pAux1, nVars);
+//      luckyCanonicizer1_simple(temp, pAux, pAux1, nVars);
+//      if( memCompare(temp,pInOut,nVars) == -1)        
+//          Kit_TruthCopy_64bit(pInOut, temp, nVars );  
+//      return;     
+//     }
+//  while(counter>0 )   //  && cycles < 10 if we wanna limit cycles
+//  {
+//      counter=0;
+//      counter += minimalInitialFlip_propper(pInOut, pAux, nVars);
+//      counter += minimalFlip1(pInOut, pAux, pAux1, nVars);
+//      counter += minimalSwap1(pInOut, pAux, pAux1, nVars);
+//  }
+// }
+// same as luckyCanonicizer + cycleCtr stutistics 
+// void luckyCanonicizer1(word* pInOut, word* pAux, word* pAux1, int  nVars, cycleCtr* cCtr)
+// {
+//  int counter=1, cycles=0;   
+//  assert( nVars <= 16 );
+//  while(counter>0 )   //  && cycles < 10 if we wanna limit cycles
+//  {
+//      counter=0;
+//      counter += minimalInitialFlip1(pInOut, nVars);
+//      counter += minimalFlip1(pInOut, pAux, pAux1, nVars);
+//      counter += minimalSwap1(pInOut, pAux, pAux1, nVars);
+//      cCtr->totalCycles++;
+//      cycles++;
+//  }
+//  if(cycles < cCtr->minNCycles)
+//      cCtr->minNCycles = cycles;
+//  else if(cycles > cCtr->maxNCycles)
+//      cCtr->maxNCycles = cycles;
+// }
+// luckyCanonicizer 
+
+void printCCtrInfo(cycleCtr* cCtr, int nFuncs)
+{
+    printf("maxNCycles = %d\n",cCtr->maxNCycles);
+    printf("minNCycles = %d\n",cCtr->minNCycles);
+    printf("average NCycles = %.3f\n",cCtr->totalCycles/(double)nFuncs);
+}
+////////////////////////////////////////New Faster versoin/////////////////////////////////////////////////////////
+
+// if highest bit in F ( all ones min term ) is one => inverse 
+// returns: if pInOnt changed(minimized) by function return 1 if not 0
+int minimalInitialFlip1(word* pInOut, int  nVars)
+{
+    word oneWord=1;
+    if(  (pInOut[Kit_TruthWordNum_64bit( nVars ) -1]>>63) & oneWord )
+    {
+        Kit_TruthNot_64bit( pInOut, nVars );
+        return 1;
+    }
+    return 0;
+}
+
+// compare F with  F1 = (F with changed phase in one of the vars).
+// keeps smaller.
+// same for all vars in F.
+// returns: if pInOnt changed(minimized) by function return 1 if not 0
+int minimalFlip1(word* pInOut, word* pMinimal, word* PDuplicat, int  nVars) 
+{
+    int i;
+    int blockSize = Kit_TruthWordNum_64bit( nVars )*sizeof(word);
+    memcpy(pMinimal, pInOut, blockSize);
+    memcpy(PDuplicat, pInOut, blockSize);
+    Kit_TruthChangePhase_64bit( pInOut, nVars, 0 );
+    for(i=1;i<nVars;i++)
+    {
+        if( memCompare(pMinimal,pInOut,nVars) == 1)
+        {
+            memcpy(pMinimal, pInOut, blockSize);
+            Kit_TruthChangePhase_64bit( pInOut, nVars, i );
+        }
+        else
+        {
+            memcpy(pInOut, pMinimal, blockSize);
+            Kit_TruthChangePhase_64bit( pInOut, nVars, i );
+        }
+    }
+    if( memCompare(pMinimal,pInOut,nVars) == -1)
+        memcpy(pInOut, pMinimal, blockSize);
+    if(memcmp(pInOut,PDuplicat,blockSize) == 0)
+        return 0;
+    else
+        return 1;
+}
+// compare F with  F1 = (F with swapped two adjacent vars).
+// keeps smaller.
+// same for all vars in F.
+// returns: if pInOnt changed(minimized) by function return 1 if not 0
+int minimalSwap1(word* pInOut, word* pMinimal, word* PDuplicat, int  nVars) 
+{
+    int i;
+    int blockSize = Kit_TruthWordNum_64bit( nVars )*sizeof(word);
+    memcpy(pMinimal, pInOut, blockSize);
+    memcpy(PDuplicat, pInOut, blockSize);
+    Kit_TruthSwapAdjacentVars_64bit( pInOut, nVars, 0 );
+    for(i=1;i<nVars-1;i++)
+    {
+        if( memCompare(pMinimal,pInOut,nVars) == 1)
+        {
+            memcpy(pMinimal, pInOut, blockSize);
+            Kit_TruthSwapAdjacentVars_64bit( pInOut, nVars, i );
+        }
+        else
+        {
+            memcpy(pInOut, pMinimal, blockSize);
+            Kit_TruthSwapAdjacentVars_64bit( pInOut, nVars, i );
+        }
+    }
+    if( memCompare(pMinimal,pInOut,nVars) == -1)
+        memcpy(pInOut, pMinimal, blockSize);
+    if(memcmp(pInOut,PDuplicat,blockSize) == 0)
+        return 0;
+    else
+        return 1;
+}
+
+// if highest bit in F ( all ones min term ) is one => inverse 
+// returns: if pInOnt changed(minimized) by function return 1 if not 0
+int minimalInitialFlip(word* pInOut, int  nVars, unsigned* p_uCanonPhase)
+{
+    word oneWord=1;
+    if(  (pInOut[Kit_TruthWordNum_64bit( nVars ) -1]>>63) & oneWord )
+    {
+        Kit_TruthNot_64bit( pInOut, nVars );
+        *p_uCanonPhase ^= (1 << nVars);
+        return 1;
+    }
+    return 0;
+}
+
+// compare F with  F1 = (F with changed phase in one of the vars).
+// keeps smaller.
+// same for all vars in F.
+// returns: if pInOnt changed(minimized) by function return 1 if not 0
+int minimalFlip(word* pInOut, word* pMinimal, word* PDuplicat, int  nVars, unsigned* p_uCanonPhase)
+{
+    int i;
+    unsigned minTemp = *p_uCanonPhase;
+    int blockSize = Kit_TruthWordNum_64bit( nVars )*sizeof(word);
+    memcpy(pMinimal, pInOut, blockSize);
+    memcpy(PDuplicat, pInOut, blockSize);       //////////////need one more unsigned!!!!!!!!!!!!!
+    Kit_TruthChangePhase_64bit( pInOut, nVars, 0 );
+    *p_uCanonPhase ^= (unsigned)1;
+    for(i=1;i<nVars;i++)
+    {
+        if( memCompare(pMinimal,pInOut,nVars) == 1)
+        {
+            memcpy(pMinimal, pInOut, blockSize);
+            minTemp = *p_uCanonPhase;
+        }
+        else
+        {
+            memcpy(pInOut, pMinimal, blockSize);
+            *p_uCanonPhase = minTemp;
+        }
+        Kit_TruthChangePhase_64bit( pInOut, nVars, i );
+        *p_uCanonPhase ^= (1 << i);
+    }
+    if( memCompare(pMinimal,pInOut,nVars) == -1)
+    {
+        memcpy(pInOut, pMinimal, blockSize);
+        *p_uCanonPhase = minTemp;
+    }
+    if(memcmp(pInOut,PDuplicat,blockSize) == 0) 
+        return 0;
+    else
+        return 1;
+}
+
+// swaps iVar and iVar+1 elements in pCanonPerm ant p_uCanonPhase
+void swapInfoAdjacentVars(int iVar, char * pCanonPerm, unsigned* p_uCanonPhase)
+{
+    char Temp = pCanonPerm[iVar];
+    pCanonPerm[iVar] = pCanonPerm[iVar+1];
+    pCanonPerm[iVar+1] = Temp;
+    
+    // if the polarity of variables is different, swap them
+    if ( ((*p_uCanonPhase & (1 << iVar)) > 0) != ((*p_uCanonPhase & (1 << (iVar+1))) > 0) )
+    {
+        *p_uCanonPhase ^= (1 << iVar);
+        *p_uCanonPhase ^= (1 << (iVar+1));
+    }
+            
+}
+
+
+// compare F with  F1 = (F with swapped two adjacent vars).
+// keeps smaller.
+// same for all vars in F.
+// returns: if pInOnt changed(minimized) by function return 1 if not 0
+
+
+/*
+// this version is buggy and is fixed below
+int minimalSwap(word* pInOut, word* pMinimal, word* PDuplicat, int  nVars, char * pCanonPerm, char * tempArray, unsigned* p_uCanonPhase) 
+{
+    int i;  
+    int blockSizeWord = Kit_TruthWordNum_64bit( nVars )*sizeof(word);
+    int blockSizeChar = nVars *sizeof(char);
+    memcpy(pMinimal, pInOut, blockSizeWord);
+    memcpy(PDuplicat, pInOut, blockSizeWord);
+    memcpy(tempArray, pCanonPerm, blockSizeChar);  
+    Kit_TruthSwapAdjacentVars_64bit( pInOut, nVars, 0 );
+    swapInfoAdjacentVars(0, pCanonPerm, p_uCanonPhase);
+    for(i=1;i<nVars-1;i++)
+    {
+        if( memCompare(pMinimal,pInOut,nVars) == 1)
+        {
+            memcpy(pMinimal, pInOut, blockSizeWord);
+            memcpy(tempArray, pCanonPerm, blockSizeChar);
+        }
+        else
+        {
+            memcpy(pInOut, pMinimal, blockSizeWord);
+            memcpy(pCanonPerm, tempArray, blockSizeChar);   
+        }
+        Kit_TruthSwapAdjacentVars_64bit( pInOut, nVars, i );
+        swapInfoAdjacentVars(i, pCanonPerm, p_uCanonPhase);
+    }
+    if( memCompare(pMinimal,pInOut,nVars) == -1)
+    {
+        memcpy(pInOut, pMinimal, blockSizeWord);
+        memcpy(pCanonPerm, tempArray, blockSizeChar);
+    }
+    if(memcmp(pInOut,PDuplicat,blockSizeWord) == 0)
+        return 0;
+    else
+        return 1;
+}
+*/
+
+int minimalSwap(word* pInOut, word* pMinimal, word* PDuplicat, int  nVars, char * pCanonPerm, char * tempArray, unsigned* p_uCanonPhase) 
+{
+    int i;  
+    int blockSizeWord = Kit_TruthWordNum_64bit( nVars )*sizeof(word);
+    int blockSizeChar = nVars *sizeof(char);
+    unsigned TempuCanonPhase = *p_uCanonPhase;
+    memcpy(pMinimal, pInOut, blockSizeWord);
+    memcpy(PDuplicat, pInOut, blockSizeWord);
+    memcpy(tempArray, pCanonPerm, blockSizeChar);  
+    Kit_TruthSwapAdjacentVars_64bit( pInOut, nVars, 0 );
+    swapInfoAdjacentVars(0, pCanonPerm, p_uCanonPhase);
+    for(i=1;i<nVars-1;i++)
+    {
+        if( memCompare(pMinimal,pInOut,nVars) == 1)
+        {
+            memcpy(pMinimal, pInOut, blockSizeWord);
+            memcpy(tempArray, pCanonPerm, blockSizeChar);
+            TempuCanonPhase = *p_uCanonPhase;
+            
+        }
+        else
+        {
+            memcpy(pInOut, pMinimal, blockSizeWord);
+            memcpy(pCanonPerm, tempArray, blockSizeChar);
+            *p_uCanonPhase = TempuCanonPhase;
+        }
+        Kit_TruthSwapAdjacentVars_64bit( pInOut, nVars, i );
+        swapInfoAdjacentVars(i, pCanonPerm, p_uCanonPhase);
+    }
+    if( memCompare(pMinimal,pInOut,nVars) == -1)
+    {
+        memcpy(pInOut, pMinimal, blockSizeWord);
+        memcpy(pCanonPerm, tempArray, blockSizeChar);
+        *p_uCanonPhase = TempuCanonPhase;
+    }
+    if(memcmp(pInOut,PDuplicat,blockSizeWord) == 0)
+        return 0;
+    else
+        return 1;
+}
+
+
+//////////////// functions below just for Alan if he want to double check my program//////////////////////////////////
+/////////////////You need swap_ij function or analogical one//////////////////////////////////////////////////////////
+/*
+void swapAndFlip(word* pAfter, int nVars, int iVarInPosition, int jVar, char * pCanonPerm, unsigned* pUCanonPhase)
+{
+    int Temp;
+    swap_ij(pAfter, nVars, iVarInPosition, jVar);
+    
+    Temp = pCanonPerm[iVarInPosition];
+    pCanonPerm[iVarInPosition] = pCanonPerm[jVar];
+    pCanonPerm[jVar] = Temp;
+    
+    if ( ((*pUCanonPhase & (1 << iVarInPosition)) > 0) != ((*pUCanonPhase & (1 << jVar)) > 0) )
+    {
+        *pUCanonPhase ^= (1 << iVarInPosition);
+        *pUCanonPhase ^= (1 << jVar);
+    }
+    if(*pUCanonPhase>>iVarInPosition & (unsigned)1 == 1)
+        Kit_TruthChangePhase_64bit( pAfter, nVars, iVarInPosition );
+    
+}
+int luckyCheck(word* pAfter, word* pBefore, int nVars, char * pCanonPerm, unsigned uCanonPhase)
+{
+    int i,j;
+    char tempChar;
+    for(j=0;j<nVars;j++)
+    {
+        tempChar = 'a'+ j;
+        for(i=j;i<nVars;i++)
+        {
+            if(tempChar != pCanonPerm[i])
+                continue;
+            swapAndFlip(pAfter , nVars, j, i, pCanonPerm, &uCanonPhase);
+            break;
+        }
+    }
+    if(uCanonPhase>>nVars & (unsigned)1 == 1)
+        Kit_TruthNot_64bit(pAfter, nVars );
+    if(memcmp(pAfter, pBefore, Kit_TruthWordNum_64bit( nVars )*sizeof(word)) == 0)
+        return 0;
+    else
+        return 1;
+}
+*/
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+void luckyCanonicizer(word* pInOut, word* pAux, word* pAux1, int  nVars, char * pCanonPerm, char * tempArray, unsigned* p_uCanonPhase)
+{
+    int counter=1;
+    assert( nVars <= 16 );
+    while(counter>0 )   //  && cycles < 10 if we wanna limit cycles
+    {
+        counter=0;
+        counter += minimalInitialFlip(pInOut, nVars, p_uCanonPhase);
+        counter += minimalFlip(pInOut, pAux, pAux1, nVars, p_uCanonPhase);
+        counter += minimalSwap(pInOut, pAux, pAux1, nVars, pCanonPerm, tempArray, p_uCanonPhase);   
+    }
+}
+// tries to find minimal F till F at the beginning of the loop is the same as at the end - irreducible 
+unsigned luckyCanonicizer1_simple(word* pInOut, word* pAux, word* pAux1, int  nVars, char * pCanonPerm, unsigned CanonPhase)
+{
+    int counter=1;
+    assert( nVars <= 16 );
+    while(counter>0 )   //  && cycles < 10 if we wanna limit cycles
+    {
+        counter=0;
+        counter += minimalInitialFlip1(pInOut, nVars);
+        counter += minimalFlip1(pInOut, pAux, pAux1, nVars);
+        counter += minimalSwap1(pInOut, pAux, pAux1, nVars);    
+    }
+    return CanonPhase;
+}
+
+void luckyCanonicizer_final(word* pInOut, word* pAux, word* pAux1, int  nVars)
+{
+    Kit_TruthSemiCanonicize_Yasha_simple( pInOut, nVars, NULL );
+    luckyCanonicizer1_simple(pInOut, pAux, pAux1, nVars, NULL, 0);
+}
+
+// this procedure calls internal canoniziers
+// it returns canonical phase (as return value) and canonical permutation (in pCanonPerm)
+unsigned Kit_TruthSemiCanonicize_new_internal( word * pInOut, int nVars, char * pCanonPerm )
+{
+    word pAux[1024], pAux1[1024];
+    char tempArray[16];
+    unsigned CanonPhase;
+    assert( nVars <= 16 );
+    CanonPhase = Kit_TruthSemiCanonicize_Yasha( pInOut, nVars, pCanonPerm );
+    luckyCanonicizer(pInOut, pAux, pAux1, nVars, pCanonPerm, tempArray, &CanonPhase);
+    return CanonPhase;
+}
+
+// this procedure is translates truth table from 'unsingeds' into 'words' 
+unsigned Kit_TruthSemiCanonicize_new( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm )
+{
+    unsigned Result;
+    if ( nVars < 6 )
+    {
+         word Temp = ((word)pInOut[0] << 32) | (word)pInOut[0];
+         Result = Kit_TruthSemiCanonicize_new_internal( &Temp, nVars, pCanonPerm );
+         pInOut[0] = (unsigned)Temp;
+    }
+    else
+         Result = Kit_TruthSemiCanonicize_new_internal( (word *)pInOut, nVars, pCanonPerm );
+    return Result;
+}
+
+
+
+// compile main() procedure only if running outside of ABC environment
+#ifndef _RUNNING_ABC_
+
+int main () 
+{
+//  char * pFileInput  = "nonDSDfunc06var1M.txt";
+//  char * pFileInput1 = "partDSDfunc06var1M.txt";
+//  char * pFileInput2 = "fullDSDfunc06var1M.txt";
+
+//  char * pFileInput  = "nonDSDfunc10var100K.txt";
+//  char * pFileInput1 = "partDSDfunc10var100K.txt";
+//  char * pFileInput2 = "fullDSDfunc10var100K.txt";
+
+//  char * pFileInput = "partDSDfunc12var100K.txt";
+//  char * pFileInput  = "nonDSDfunc12var100K.txt";
+//  char * pFileInput1 = "partDSDfunc12var100K.txt";
+//  char * pFileInput2 = "fullDSDfunc12var100K.txt";
+
+//  char * pFileInput  = "nonDSDfunc14var10K.txt";
+//  char * pFileInput1 = "partDSDfunc14var10K.txt";
+//  char * pFileInput2 = "fullDSDfunc14var10K.txt";
+
+    char * pFileInput  = "nonDSDfunc16var10K.txt";
+    char * pFileInput1 = "partDSDfunc16var10K.txt";
+    char * pFileInput2 = "fullDSDfunc16var10K.txt";
+
+    int i, j, tempNF;
+    char** charArray;
+    word** a, ** b;
+    Abc_TtStore_t* p;
+    word * pAux, * pAux1;
+    int * pStore;
+//  cycleCtr* cCtr;
+    charArray = (char**)malloc(sizeof(char*)*3);
+
+    charArray[0] = pFileInput;
+    charArray[1] = pFileInput1;
+    charArray[2] = pFileInput2;
+    for(j=0;j<3;j++)
+    {
+        p = setTtStore(charArray[j]);   
+//      p = setTtStore(pFileInput); 
+        a = makeArray(p);
+        b = makeArray(p);   
+//      cCtr = setCycleCtrPtr();
+
+        pAux = (word*)malloc(sizeof(word)*(p->nWords));
+        pAux1 = (word*)malloc(sizeof(word)*(p->nWords));    
+        pStore = (int*)malloc(sizeof(int)*(p->nVars));
+        printf("In %s Fs at start = %d\n",charArray[j],p->nFuncs);
+        
+        tempNF = p->nFuncs;
+
+        TimePrint("start");     
+        for(i=0;i<p->nFuncs;i++)        
+            luckyCanonicizer_final(a[i], pAux, pAux1, p->nVars, pStore);        
+        TimePrint("done with A");
+
+        sortAndUnique(a, p);
+        printf("F left in A final = %d\n",p->nFuncs);
+        freeArray(a,p);
+        TimePrint("Done with sort");
+        
+
+// delete data-structures   
+        free(pAux);
+        free(pAux1);    
+        free(pStore);
+//      freeCycleCtr(cCtr);
+        Abc_TruthStoreFree( p );
+    }
+    return 0;
+}
+
+#endif
+
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/bool/lucky/lucky.h b/abc-build/src/bool/lucky/lucky.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/lucky/lucky.h
@@ -0,0 +1,44 @@
+/**CFile****************************************************************
+
+  FileName    [lucky.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Semi-canonical form computation package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Jake]
+
+  Date        [Started - August 2012]
+
+***********************************************************************/
+
+#ifndef ABC__bool__lucky__LUCKY_H_
+#define ABC__bool__lucky__LUCKY_H_
+
+
+ABC_NAMESPACE_HEADER_START
+
+typedef struct
+{
+    int varN;
+    int* swapArray;
+    int swapCtr;
+    int totalSwaps;
+    int* flipArray;
+    int flipCtr;
+    int totalFlips; 
+}permInfo;
+
+extern unsigned Kit_TruthSemiCanonicize_new( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm );
+extern unsigned luckyCanonicizer_final_fast( word * pInOut, int nVars, char * pCanonPerm );
+extern unsigned luckyCanonicizer_final_fast1( word * pInOut, int nVars, char * pCanonPerm );
+extern void resetPCanonPermArray(char* x, int nVars); 
+extern permInfo* setPermInfoPtr(int var);
+extern void freePermInfoPtr(permInfo* x);
+extern void simpleMinimal(word* x, word* pAux,word* minimal, permInfo* pi, int nVars);
+
+ABC_NAMESPACE_HEADER_END
+
+#endif /* LUCKY_H_ */
diff --git a/abc-build/src/bool/lucky/luckyFast16.c b/abc-build/src/bool/lucky/luckyFast16.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/lucky/luckyFast16.c
@@ -0,0 +1,872 @@
+/**CFile****************************************************************
+
+  FileName    [luckyFast16.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Semi-canonical form computation package.]
+
+  Synopsis    [Truth table minimization procedures for up to  16 vars.]
+
+  Author      [Jake]
+
+  Date        [Started - September 2012]
+
+***********************************************************************/
+
+#include "luckyInt.h"
+//#define LUCKY_VERIFY
+
+ABC_NAMESPACE_IMPL_START
+
+static word SFmask[5][4] = {
+    {ABC_CONST(0x8888888888888888),ABC_CONST(0x4444444444444444),ABC_CONST(0x2222222222222222),ABC_CONST(0x1111111111111111)},
+    {ABC_CONST(0xC0C0C0C0C0C0C0C0),ABC_CONST(0x3030303030303030),ABC_CONST(0x0C0C0C0C0C0C0C0C),ABC_CONST(0x0303030303030303)},
+    {ABC_CONST(0xF000F000F000F000),ABC_CONST(0x0F000F000F000F00),ABC_CONST(0x00F000F000F000F0),ABC_CONST(0x000F000F000F000F)},
+    {ABC_CONST(0xFF000000FF000000),ABC_CONST(0x00FF000000FF0000),ABC_CONST(0x0000FF000000FF00),ABC_CONST(0x000000FF000000FF)},
+    {ABC_CONST(0xFFFF000000000000),ABC_CONST(0x0000FFFF00000000),ABC_CONST(0x00000000FFFF0000),ABC_CONST(0x000000000000FFFF)}   
+};
+
+// we need next two functions only for verification of lucky method in debugging mode 
+void swapAndFlip(word* pAfter, int nVars, int iVarInPosition, int jVar, char * pCanonPerm, unsigned* pUCanonPhase)
+{
+    int Temp;
+    swap_ij(pAfter, nVars, iVarInPosition, jVar);
+    
+    Temp = pCanonPerm[iVarInPosition];
+    pCanonPerm[iVarInPosition] = pCanonPerm[jVar];
+    pCanonPerm[jVar] = Temp;
+    
+    if ( ((*pUCanonPhase & (1 << iVarInPosition)) > 0) != ((*pUCanonPhase & (1 << jVar)) > 0) )
+    {
+        *pUCanonPhase ^= (1 << iVarInPosition);
+        *pUCanonPhase ^= (1 << jVar);
+    }
+    if((*pUCanonPhase>>iVarInPosition) & 1)
+        Kit_TruthChangePhase_64bit( pAfter, nVars, iVarInPosition );
+    
+}
+int luckyCheck(word* pAfter, word* pBefore, int nVars, char * pCanonPerm, unsigned uCanonPhase)
+{
+    int i,j;
+    char tempChar;
+    for(j=0;j<nVars;j++)
+    {
+        tempChar = 'a'+ j;
+        for(i=j;i<nVars;i++)
+        {
+            if(tempChar != pCanonPerm[i])
+                continue;
+            swapAndFlip(pAfter , nVars, j, i, pCanonPerm, &uCanonPhase);
+            break;
+        }
+    }
+    if((uCanonPhase>>nVars) & 1)
+        Kit_TruthNot_64bit(pAfter, nVars );
+    if(memcmp(pAfter, pBefore, Kit_TruthWordNum_64bit( nVars )*sizeof(word)) == 0)
+        return 0;
+    else
+        return 1;
+}
+
+////////////////////////////////////lessThen5/////////////////////////////////////////////////////////////////////////////////////////////
+
+// there are 4 parts in every block to compare and rearrange - quoters(0Q,1Q,2Q,3Q)
+//updataInfo updates CanonPerm and CanonPhase based on what quoter in position iQ and jQ
+void updataInfo(int iQ, int jQ, int iVar,  char * pCanonPerm, unsigned* pCanonPhase)
+{
+    *pCanonPhase = adjustInfoAfterSwap(pCanonPerm, *pCanonPhase, iVar, ((abs(iQ-jQ)-1)<<2) + iQ );
+
+}
+
+// returns the first shift from the left in word x that has One bit in it.
+// blockSize = ShiftSize/4
+int firstShiftWithOneBit(word x, int blockSize)
+{
+    int n = 0;
+    if(blockSize == 16){ return 0;}     
+    if (x >= ABC_CONST(0x0000000100000000)) {n = n + 32; x = x >> 32;} 
+    if(blockSize == 8){ return (64-n)/32;}  
+    if (x >= ABC_CONST(0x0000000000010000)) {n = n + 16; x = x >> 16;} 
+    if(blockSize == 4){ return (64-n)/16;}
+    if (x >= ABC_CONST(0x0000000000000100)) {n = n + 8; x = x >> 8;}
+    if(blockSize == 2){ return (64-n)/8;}
+    if (x >= ABC_CONST(0x0000000000000010)) {n = n + 4; x = x >> 4;} 
+    return (64-n)/4;    
+    
+}
+
+// It rearranges InOut (swaps and flips through rearrangement of quoters)
+// It updates Info at the end
+void arrangeQuoters_superFast_lessThen5(word* pInOut, int start, int iQ, int jQ, int kQ, int lQ, int iVar, int nWords, char * pCanonPerm, unsigned* pCanonPhase)
+{
+    int i, blockSize = 1<<iVar;
+//     printf("in arrangeQuoters_superFast_lessThen5\n");
+//     printf("start = %d, iQ = %d,jQ = %d,kQ = %d,lQ = %d, iVar = %d, nWords = %d\n", start, iQ, jQ, kQ , lQ, iVar, nWords);
+    for(i=start;i>=0;i--)
+    {   
+        assert( iQ*blockSize < 64 );
+        assert( jQ*blockSize < 64 );
+        assert( kQ*blockSize < 64 );
+        assert( lQ*blockSize < 64 );
+        assert( 3*blockSize < 64 );
+        pInOut[i] = (pInOut[i] & SFmask[iVar][iQ])<<(iQ*blockSize) |
+            (((pInOut[i] & SFmask[iVar][jQ])<<(jQ*blockSize))>>blockSize) |
+            (((pInOut[i] & SFmask[iVar][kQ])<<(kQ*blockSize))>>2*blockSize) |
+            (((pInOut[i] & SFmask[iVar][lQ])<<(lQ*blockSize))>>3*blockSize);
+    }
+    updataInfo(iQ, jQ, iVar, pCanonPerm, pCanonPhase);
+//     printf("out arrangeQuoters_superFast_lessThen5\n");
+
+}
+// static word SFmask[5][4] = {
+//     {0x8888888888888888,0x4444444444444444,0x2222222222222222,0x1111111111111111},
+//     {0xC0C0C0C0C0C0C0C0,0x3030303030303030,0x0C0C0C0C0C0C0C0C,0x0303030303030303},
+//     {0xF000F000F000F000,0x0F000F000F000F00,0x00F000F000F000F0,0x000F000F000F000F},
+//     {0xFF000000FF000000,0x00FF000000FF0000,0x0000FF000000FF00,0x000000FF000000FF},
+//     {0xFFFF000000000000,0x0000FFFF00000000,0x00000000FFFF0000,0x000000000000FFFF}   
+// };
+//It compares 0Q and 3Q and returns 0 if 0Q is smaller then 3Q ( comparison starts at highest bit) and visa versa
+// DifStart contains the information about the first different bit in 0Q and 3Q
+int minTemp0_fast(word* pInOut, int iVar, int nWords, int* pDifStart)
+{
+    int i, blockSize = 1<<iVar;
+    word temp;
+    for(i=nWords - 1; i>=0; i--)
+    {
+        assert( 3*blockSize < 64 );
+        temp = ((pInOut[i] & SFmask[iVar][0])) ^ ((pInOut[i] & SFmask[iVar][3])<<(3*blockSize));
+        if( temp == 0)
+            continue;
+        else
+        {
+            *pDifStart = i*100 + 20 - firstShiftWithOneBit(temp, blockSize);
+            if( ((pInOut[i] & SFmask[iVar][0])) < ((pInOut[i] & SFmask[iVar][3])<<(3*blockSize)) )
+                return 0;
+            else
+                return 3;
+        }
+    }
+    *pDifStart=0;
+    return 0;
+
+}
+
+//It compares 1Q and 2Q and returns 1 if 1Q is smaller then 2Q ( comparison starts at highest bit) and visa versa
+// DifStart contains the information about the first different bit in 1Q and 2Q
+int minTemp1_fast(word* pInOut, int iVar, int nWords, int* pDifStart)
+{
+    int i, blockSize = 1<<iVar;
+    word temp;
+    for(i=nWords - 1; i>=0; i--)
+    {
+        assert( 2*blockSize < 64 );
+        temp = ((pInOut[i] & SFmask[iVar][1])<<(blockSize)) ^ ((pInOut[i] & SFmask[iVar][2])<<(2*blockSize));
+        if( temp == 0)
+            continue;
+        else
+        {
+            *pDifStart = i*100 + 20 - firstShiftWithOneBit(temp, blockSize);
+            if( ((pInOut[i] & SFmask[iVar][1])<<(blockSize)) < ((pInOut[i] & SFmask[iVar][2])<<(2*blockSize)) )
+                return 1;
+            else
+                return 2;
+        }
+    }
+    *pDifStart=0;
+    return 1;
+}
+
+//It compares iQ and jQ and returns 0 if iQ is smaller then jQ ( comparison starts at highest bit) and 1 if jQ is
+// DifStart contains the information about the first different bit in iQ and jQ
+int minTemp2_fast(word* pInOut, int iVar, int iQ, int jQ, int nWords, int* pDifStart)
+{
+    int i, blockSize = 1<<iVar;
+    word temp;
+    for(i=nWords - 1; i>=0; i--)
+    {
+        assert( jQ*blockSize < 64 );
+        temp = ((pInOut[i] & SFmask[iVar][iQ])<<(iQ*blockSize)) ^ ((pInOut[i] & SFmask[iVar][jQ])<<(jQ*blockSize));
+        if( temp == 0)
+            continue;
+        else
+        {
+            *pDifStart = i*100 + 20 - firstShiftWithOneBit(temp, blockSize);
+            if( ((pInOut[i] & SFmask[iVar][iQ])<<(iQ*blockSize)) <= ((pInOut[i] & SFmask[iVar][jQ])<<(jQ*blockSize)) )
+                return 0;
+            else
+                return 1;
+        }
+    }
+    *pDifStart=0;
+    return 0;
+}
+// same as minTemp2_fast but this one has a start position
+int minTemp3_fast(word* pInOut, int iVar, int start, int finish, int iQ, int jQ, int* pDifStart)
+{
+    int i, blockSize = 1<<iVar;
+    word temp;
+    for(i=start; i>=finish; i--)
+    {
+        assert( jQ*blockSize < 64 );
+        temp = ((pInOut[i] & SFmask[iVar][iQ])<<(iQ*blockSize)) ^ ((pInOut[i] & SFmask[iVar][jQ])<<(jQ*blockSize));
+        if( temp == 0)
+            continue;
+        else
+        {
+            *pDifStart = i*100 + 20 - firstShiftWithOneBit(temp, blockSize);
+            if( ((pInOut[i] & SFmask[iVar][iQ])<<(iQ*blockSize)) <= ((pInOut[i] & SFmask[iVar][jQ])<<(jQ*blockSize)) )
+                return 0;
+            else
+                return 1;
+        }
+    }
+    *pDifStart=0;
+    return 0;
+}
+
+// It considers all swap and flip possibilities of iVar and iVar+1 and switches InOut to a minimal of them  
+void minimalSwapAndFlipIVar_superFast_lessThen5(word* pInOut, int iVar, int nWords, char * pCanonPerm, unsigned* pCanonPhase)
+{
+    int min1, min2, DifStart0, DifStart1, DifStartMin, DifStart4=0;
+    int M[2];   
+    M[0] = minTemp0_fast(pInOut, iVar, nWords, &DifStart0); // 0, 3
+    M[1] = minTemp1_fast(pInOut, iVar, nWords, &DifStart1); // 1, 2
+    min1 = minTemp2_fast(pInOut, iVar, M[0], M[1], nWords, &DifStartMin);
+//     printf("\nDifStart0 = %d, DifStart1 = %d, DifStartMin = %d\n",DifStart0, DifStart1, DifStartMin);
+//     printf("M[0] = %d, M[1] = %d, min1 = %d\n", M[0], M[1], min1);
+    if(DifStart0 != DifStart1)
+    {
+//         printf("if\n");
+        if( DifStartMin>=DifStart1 && DifStartMin>=DifStart0 )
+            arrangeQuoters_superFast_lessThen5(pInOut, DifStartMin/100, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, nWords, pCanonPerm, pCanonPhase);
+        else if( DifStart0 > DifStart1)
+            arrangeQuoters_superFast_lessThen5(pInOut,luckyMax(DifStartMin/100, DifStart0/100), M[0], M[1], 3 - M[1], 3 - M[0], iVar, nWords, pCanonPerm, pCanonPhase);
+        else
+            arrangeQuoters_superFast_lessThen5(pInOut,luckyMax(DifStartMin/100, DifStart1/100), M[1], M[0], 3 - M[0], 3 - M[1], iVar, nWords, pCanonPerm, pCanonPhase);
+    }
+    else
+    {
+//         printf("else\n");
+        if(DifStartMin>=DifStart0)
+            arrangeQuoters_superFast_lessThen5(pInOut, DifStartMin/100, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, nWords, pCanonPerm, pCanonPhase);
+        else
+        {
+            min2 = minTemp3_fast(pInOut, iVar, DifStart0/100, DifStartMin/100, 3-M[0], 3-M[1], &DifStart4);  // no reuse DifStart1 because DifStart1 = DifStart1=0
+//             printf("after minTemp3_fast min2 = %d, DifStart4 = %d\n", min2, DifStart4);
+            if(DifStart4>DifStartMin)
+                arrangeQuoters_superFast_lessThen5(pInOut, DifStart0/100, M[(min2+1)&1], M[min2], 3 - M[min2], 3 - M[(min2+1)&1], iVar, nWords, pCanonPerm, pCanonPhase);
+            else
+                arrangeQuoters_superFast_lessThen5(pInOut, DifStart0/100, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, nWords, pCanonPerm, pCanonPhase);
+        }
+    }
+}
+
+void minimalSwapAndFlipIVar_superFast_lessThen5_noEBFC(word* pInOut, int iVar, int nWords, char * pCanonPerm, unsigned* pCanonPhase)
+{
+    int DifStart1;
+    if(minTemp1_fast(pInOut, iVar, nWords, &DifStart1) == 2)
+        arrangeQuoters_superFast_lessThen5(pInOut, DifStart1/100, 0, 2, 1, 3, iVar, nWords, pCanonPerm, pCanonPhase); 
+}
+////////////////////////////////////iVar = 5/////////////////////////////////////////////////////////////////////////////////////////////
+
+// It rearranges InOut (swaps and flips through rearrangement of quoters)
+// It updates Info at the end
+void arrangeQuoters_superFast_iVar5(unsigned* pInOut, unsigned* temp, int start,  int iQ, int jQ, int kQ, int lQ, char * pCanonPerm, unsigned* pCanonPhase)
+{
+    int i,blockSize,shiftSize;
+    unsigned* tempPtr = temp+start;
+//     printf("in arrangeQuoters_superFast_iVar5\n");
+
+    if(iQ == 0 && jQ == 1)
+        return; 
+    blockSize = sizeof(unsigned);
+    shiftSize = 4;
+    for(i=start-1;i>0;i-=shiftSize)
+    {       
+        tempPtr -= 1;       
+        memcpy(tempPtr, pInOut+i-iQ, blockSize);
+        tempPtr -= 1;
+        memcpy(tempPtr, pInOut+i-jQ, blockSize);
+        tempPtr -= 1;
+        memcpy(tempPtr, pInOut+i-kQ, blockSize);
+        tempPtr -= 1;
+        memcpy(tempPtr, pInOut+i-lQ, blockSize);        
+    }   
+    memcpy(pInOut, temp, start*sizeof(unsigned));
+    updataInfo(iQ, jQ, 5, pCanonPerm, pCanonPhase);
+}
+
+//It compares 0Q and 3Q and returns 0 if 0Q is smaller then 3Q ( comparison starts at highest bit) and visa versa
+// DifStart contains the information about the first different bit in 0Q and 3Q
+int minTemp0_fast_iVar5(unsigned* pInOut, int nWords, int* pDifStart)
+{
+    int i, temp;
+//     printf("in minTemp0_fast_iVar5\n");
+    for(i=(nWords)*2 - 1; i>=0; i-=4)   
+    {
+        temp = CompareWords(pInOut[i],pInOut[i-3]);
+        if(temp == 0)
+            continue;
+        else if(temp == -1)
+        {
+            *pDifStart = i+1;
+            return 0;
+        }
+        else
+        {
+            *pDifStart = i+1;
+            return 3;
+        }
+    }
+    *pDifStart=0;
+    return 0;
+}
+
+//It compares 1Q and 2Q and returns 1 if 1Q is smaller then 2Q ( comparison starts at highest bit) and visa versa
+// DifStart contains the information about the first different bit in 1Q and 2Q
+int minTemp1_fast_iVar5(unsigned* pInOut, int nWords, int* pDifStart)
+{
+    int i, temp;
+//     printf("in minTemp1_fast_iVar5\n");
+    for(i=(nWords)*2 - 2; i>=0; i-=4)   
+    {
+        temp = CompareWords(pInOut[i],pInOut[i-1]);
+        if(temp == 0)
+            continue;
+        else if(temp == -1)
+        {
+            *pDifStart = i+2;
+            return 1;
+        }
+        else
+        {
+            *pDifStart = i+2;
+            return 2;
+        }
+    }
+    *pDifStart=0;
+    return 1;
+}
+
+//It compares iQ and jQ and returns 0 if iQ is smaller then jQ ( comparison starts at highest bit) and visa versa
+// DifStart contains the information about the first different bit in iQ and jQ
+int minTemp2_fast_iVar5(unsigned* pInOut, int iQ, int jQ, int nWords, int* pDifStart)
+{
+    int i, temp;
+//     printf("in minTemp2_fast_iVar5\n");
+
+    for(i=(nWords)*2 - 1; i>=0; i-=4)   
+    {
+        temp = CompareWords(pInOut[i-iQ],pInOut[i-jQ]);
+        if(temp == 0)
+            continue;
+        else if(temp == -1)
+        {
+            *pDifStart = i+1;
+            return 0;
+        }
+        else
+        {
+            *pDifStart = i+1;
+            return 1;
+        }
+    }
+    *pDifStart=0;
+    return 0;
+}
+
+// same as minTemp2_fast but this one has a start position
+int minTemp3_fast_iVar5(unsigned* pInOut, int start, int finish, int iQ, int jQ, int* pDifStart)
+{
+    int i, temp;
+//     printf("in minTemp3_fast_iVar5\n");
+
+    for(i=start-1; i>=finish; i-=4) 
+    {
+        temp = CompareWords(pInOut[i-iQ],pInOut[i-jQ]);
+        if(temp == 0)
+            continue;
+        else if(temp == -1)
+        {
+            *pDifStart = i+1;
+            return 0;
+        }
+        else
+        {
+            *pDifStart = i+1;
+            return 1;
+        }
+    }
+    *pDifStart=0;
+    return 0;
+}
+
+// It considers all swap and flip possibilities of iVar and iVar+1 and switches InOut to a minimal of them 
+void minimalSwapAndFlipIVar_superFast_iVar5(unsigned* pInOut, int nWords, char * pCanonPerm, unsigned* pCanonPhase)
+{
+    int min1, min2, DifStart0, DifStart1, DifStartMin;
+    int M[2];
+    unsigned temp[2048];
+//     printf("in minimalSwapAndFlipIVar_superFast_iVar5\n");
+    M[0] = minTemp0_fast_iVar5(pInOut, nWords, &DifStart0); // 0, 3
+    M[1] = minTemp1_fast_iVar5(pInOut, nWords, &DifStart1); // 1, 2
+    min1 = minTemp2_fast_iVar5(pInOut, M[0], M[1], nWords, &DifStartMin);
+    if(DifStart0 != DifStart1)
+    {   
+        if( DifStartMin>=DifStart1 && DifStartMin>=DifStart0 )
+            arrangeQuoters_superFast_iVar5(pInOut, temp, DifStartMin, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], pCanonPerm, pCanonPhase);
+        else if( DifStart0 > DifStart1)
+            arrangeQuoters_superFast_iVar5(pInOut, temp, luckyMax(DifStartMin,DifStart0), M[0], M[1], 3 - M[1], 3 - M[0], pCanonPerm, pCanonPhase);
+        else
+            arrangeQuoters_superFast_iVar5(pInOut, temp, luckyMax(DifStartMin,DifStart1), M[1], M[0], 3 - M[0], 3 - M[1], pCanonPerm, pCanonPhase);
+    }
+    else
+    {
+        if(DifStartMin>=DifStart0)
+            arrangeQuoters_superFast_iVar5(pInOut, temp, DifStartMin, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], pCanonPerm, pCanonPhase);
+        else
+        {
+            min2 = minTemp3_fast_iVar5(pInOut, DifStart0, DifStartMin, 3-M[0], 3-M[1], &DifStart1);  // reuse DifStart1 because DifStart1 = DifStart1=0
+            if(DifStart1>DifStartMin)
+                arrangeQuoters_superFast_iVar5(pInOut, temp, DifStart0, M[(min2+1)&1], M[min2], 3 - M[min2], 3 - M[(min2+1)&1], pCanonPerm, pCanonPhase);
+            else
+                arrangeQuoters_superFast_iVar5(pInOut, temp, DifStart0, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], pCanonPerm, pCanonPhase);
+        }
+    }
+}
+
+void minimalSwapAndFlipIVar_superFast_iVar5_noEBFC(unsigned* pInOut, int nWords, char * pCanonPerm, unsigned* pCanonPhase)
+{
+    int DifStart1;
+    unsigned temp[2048];
+    if(minTemp1_fast_iVar5(pInOut, nWords, &DifStart1) == 2)
+        arrangeQuoters_superFast_iVar5(pInOut, temp, DifStart1, 0, 2, 1, 3, pCanonPerm, pCanonPhase); 
+}
+
+////////////////////////////////////moreThen5/////////////////////////////////////////////////////////////////////////////////////////////
+
+// It rearranges InOut (swaps and flips through rearrangement of quoters)
+// It updates Info at the end
+void arrangeQuoters_superFast_moreThen5(word* pInOut, word* temp, int start,  int iQ, int jQ, int kQ, int lQ, int iVar, char * pCanonPerm, unsigned* pCanonPhase)
+{
+    int i,wordBlock,blockSize,shiftSize;
+    word* tempPtr = temp+start;
+//     printf("in arrangeQuoters_superFast_moreThen5\n");
+
+    if(iQ == 0 && jQ == 1)
+        return;
+    wordBlock = (1<<(iVar-6));
+    blockSize = wordBlock*sizeof(word);
+    shiftSize = wordBlock*4;
+    for(i=start-wordBlock;i>0;i-=shiftSize)
+    {       
+        tempPtr -= wordBlock;       
+        memcpy(tempPtr, pInOut+i-iQ*wordBlock, blockSize);
+        tempPtr -= wordBlock;
+        memcpy(tempPtr, pInOut+i-jQ*wordBlock, blockSize);
+        tempPtr -= wordBlock;
+        memcpy(tempPtr, pInOut+i-kQ*wordBlock, blockSize);
+        tempPtr -= wordBlock;
+        memcpy(tempPtr, pInOut+i-lQ*wordBlock, blockSize);      
+    }   
+    memcpy(pInOut, temp, start*sizeof(word));
+    updataInfo(iQ, jQ, iVar, pCanonPerm, pCanonPhase);
+//    printf("out arrangeQuoters_superFast_moreThen5\n");
+
+}
+
+//It compares 0Q and 3Q and returns 0 if 0Q is smaller then 3Q ( comparison starts at highest bit) and visa versa
+// DifStart contains the information about the first different bit in 0Q and 3Q
+int minTemp0_fast_moreThen5(word* pInOut, int iVar, int nWords, int* pDifStart)
+{
+    int i, j, temp;
+    int  wordBlock = 1<<(iVar-6);
+    int wordDif = 3*wordBlock;
+    int  shiftBlock = wordBlock*4;
+//    printf("in minTemp0_fast_moreThen5\n");
+
+    for(i=nWords - 1; i>=0; i-=shiftBlock)
+        for(j=0;j<wordBlock;j++)
+        {
+            temp = CompareWords(pInOut[i-j],pInOut[i-j-wordDif]);
+            if(temp == 0)
+                continue;
+            else if(temp == -1)
+            {
+                *pDifStart = i+1;
+                return 0;
+            }
+            else
+            {
+                *pDifStart = i+1;
+                return 3;
+            }
+        }
+    *pDifStart=0;
+//    printf("out minTemp0_fast_moreThen5\n");
+
+    return 0;
+}
+
+//It compares 1Q and 2Q and returns 1 if 1Q is smaller then 2Q ( comparison starts at highest bit) and visa versa
+// DifStart contains the information about the first different bit in 1Q and 2Q
+int minTemp1_fast_moreThen5(word* pInOut, int iVar, int nWords, int* pDifStart)
+{
+    int i, j, temp;
+    int  wordBlock = 1<<(iVar-6);
+    int  shiftBlock = wordBlock*4;
+//    printf("in minTemp1_fast_moreThen5\n");
+
+    for(i=nWords - wordBlock - 1; i>=0; i-=shiftBlock)
+        for(j=0;j<wordBlock;j++)
+        {
+            temp = CompareWords(pInOut[i-j],pInOut[i-j-wordBlock]);
+            if(temp == 0)
+                continue;
+            else if(temp == -1)
+            {
+                *pDifStart = i+wordBlock+1;
+                return 1;
+            }
+            else
+            {
+                *pDifStart = i+wordBlock+1;
+                return 2;
+            }
+        }
+    *pDifStart=0;
+//    printf("out minTemp1_fast_moreThen5\n");
+
+    return 1;
+}
+
+//It compares iQ and jQ and returns 0 if iQ is smaller then jQ ( comparison starts at highest bit) and visa versa
+// DifStart contains the information about the first different bit in iQ and jQ
+int minTemp2_fast_moreThen5(word* pInOut, int iVar, int iQ, int jQ, int nWords, int* pDifStart)
+{
+    int i, j, temp;
+    int  wordBlock = 1<<(iVar-6);
+    int  shiftBlock = wordBlock*4;
+//    printf("in minTemp2_fast_moreThen5\n");
+
+    for(i=nWords - 1; i>=0; i-=shiftBlock)
+        for(j=0;j<wordBlock;j++)
+        {
+            temp = CompareWords(pInOut[i-j-iQ*wordBlock],pInOut[i-j-jQ*wordBlock]);
+            if(temp == 0)
+                continue;
+            else if(temp == -1)
+            {
+                *pDifStart = i+1;
+                return 0;
+            }
+            else
+            {
+                *pDifStart = i+1;
+                return 1;
+            }
+        }
+    *pDifStart=0;
+//    printf("out minTemp2_fast_moreThen5\n");
+    
+    return 0;
+}
+
+// same as minTemp2_fast but this one has a start position
+int minTemp3_fast_moreThen5(word* pInOut, int iVar, int start, int finish, int iQ, int jQ, int* pDifStart)
+{
+    int i, j, temp;
+    int  wordBlock = 1<<(iVar-6);
+    int  shiftBlock = wordBlock*4;
+//    printf("in minTemp3_fast_moreThen5\n");
+
+    for(i=start-1; i>=finish; i-=shiftBlock)
+        for(j=0;j<wordBlock;j++)
+        {
+            temp = CompareWords(pInOut[i-j-iQ*wordBlock],pInOut[i-j-jQ*wordBlock]);
+            if(temp == 0)
+                continue;
+            else if(temp == -1)
+            {
+                *pDifStart = i+1;
+                return 0;
+            }
+            else
+            {
+                *pDifStart = i+1;
+                return 1;
+            }
+        }
+    *pDifStart=0;
+//    printf("out minTemp3_fast_moreThen5\n");
+
+    return 0;
+}
+
+// It considers all swap and flip possibilities of iVar and iVar+1 and switches InOut to a minimal of them 
+void minimalSwapAndFlipIVar_superFast_moreThen5(word* pInOut, int iVar, int nWords, char * pCanonPerm, unsigned* pCanonPhase)
+{
+    int min1, min2, DifStart0, DifStart1, DifStartMin;
+    int M[2];
+    word temp[1024];
+//    printf("in minimalSwapAndFlipIVar_superFast_moreThen5\n");
+    M[0] = minTemp0_fast_moreThen5(pInOut, iVar, nWords, &DifStart0); // 0, 3
+    M[1] = minTemp1_fast_moreThen5(pInOut, iVar, nWords, &DifStart1); // 1, 2
+    min1 = minTemp2_fast_moreThen5(pInOut, iVar, M[0], M[1], nWords, &DifStartMin);
+    if(DifStart0 != DifStart1)
+    {   
+        if( DifStartMin>=DifStart1 && DifStartMin>=DifStart0 )
+            arrangeQuoters_superFast_moreThen5(pInOut, temp, DifStartMin, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, pCanonPerm, pCanonPhase);
+        else if( DifStart0 > DifStart1)
+            arrangeQuoters_superFast_moreThen5(pInOut, temp, luckyMax(DifStartMin,DifStart0), M[0], M[1], 3 - M[1], 3 - M[0], iVar, pCanonPerm, pCanonPhase);
+        else
+            arrangeQuoters_superFast_moreThen5(pInOut, temp, luckyMax(DifStartMin,DifStart1), M[1], M[0], 3 - M[0], 3 - M[1], iVar, pCanonPerm, pCanonPhase);
+    }
+    else
+    {
+        if(DifStartMin>=DifStart0)
+            arrangeQuoters_superFast_moreThen5(pInOut, temp, DifStartMin, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, pCanonPerm, pCanonPhase);
+        else
+        {
+            min2 = minTemp3_fast_moreThen5(pInOut, iVar, DifStart0, DifStartMin, 3-M[0], 3-M[1], &DifStart1);  // reuse DifStart1 because DifStart1 = DifStart1=0
+            if(DifStart1>DifStartMin)
+                arrangeQuoters_superFast_moreThen5(pInOut, temp, DifStart0, M[(min2+1)&1], M[min2], 3 - M[min2], 3 - M[(min2+1)&1], iVar, pCanonPerm, pCanonPhase);
+            else
+                arrangeQuoters_superFast_moreThen5(pInOut, temp, DifStart0, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, pCanonPerm, pCanonPhase);
+        }
+    }
+//    printf("out minimalSwapAndFlipIVar_superFast_moreThen5\n");
+
+}
+
+void minimalSwapAndFlipIVar_superFast_moreThen5_noEBFC(word* pInOut, int iVar, int nWords, char * pCanonPerm, unsigned* pCanonPhase)
+{
+    int DifStart1;
+    word temp[1024];
+    if(minTemp1_fast_moreThen5(pInOut, iVar, nWords, &DifStart1) == 2)
+        arrangeQuoters_superFast_moreThen5(pInOut, temp, DifStart1, 0, 2, 1, 3, iVar, pCanonPerm, pCanonPhase); 
+}
+
+/////////////////////////////////// for all /////////////////////////////////////////////////////////////////////////////////////////////
+void minimalInitialFlip_fast_16Vars(word* pInOut, int  nVars, unsigned* pCanonPhase)
+{
+    word oneWord=1;
+    if(  (pInOut[Kit_TruthWordNum_64bit( nVars ) -1]>>63) & oneWord )
+    {
+        Kit_TruthNot_64bit( pInOut, nVars );
+        (* pCanonPhase) ^=(1<<nVars);       
+    }
+
+}
+
+// this function finds minimal for all TIED(and tied only) iVars 
+//it finds tied vars based on rearranged  Store info - group of tied vars has the same bit count in Store
+int minimalSwapAndFlipIVar_superFast_all(word* pInOut, int nVars, int nWords, int * pStore, char * pCanonPerm, unsigned* pCanonPhase)
+{
+    int i;
+    word pDuplicate[1024];  
+    int bitInfoTemp = pStore[0];
+    memcpy(pDuplicate,pInOut,nWords*sizeof(word));
+//    printf("in minimalSwapAndFlipIVar_superFast_all\n");
+    for(i=0;i<5;i++)
+    {
+        if(bitInfoTemp == pStore[i+1])
+            minimalSwapAndFlipIVar_superFast_lessThen5(pInOut, i, nWords, pCanonPerm, pCanonPhase);
+        else
+        {
+            bitInfoTemp = pStore[i+1];
+            continue;
+        }
+    }
+    if(bitInfoTemp == pStore[i+1])
+        minimalSwapAndFlipIVar_superFast_iVar5((unsigned*) pInOut, nWords, pCanonPerm, pCanonPhase);
+    else    
+        bitInfoTemp = pStore[i+1];
+    
+    for(i=6;i<nVars-1;i++)
+    {
+        if(bitInfoTemp == pStore[i+1])
+            minimalSwapAndFlipIVar_superFast_moreThen5(pInOut, i, nWords, pCanonPerm, pCanonPhase);
+        else
+        {
+            bitInfoTemp = pStore[i+1];
+            continue;
+        }
+    }
+//    printf("out minimalSwapAndFlipIVar_superFast_all\n");
+
+    if(memcmp(pInOut,pDuplicate , nWords*sizeof(word)) == 0)
+        return 0;
+    else
+        return 1;
+}
+
+int minimalSwapAndFlipIVar_superFast_all_noEBFC(word* pInOut, int nVars, int nWords, int * pStore, char * pCanonPerm, unsigned* pCanonPhase)
+{
+    int i;
+    word pDuplicate[1024];  
+    int bitInfoTemp = pStore[0];
+    memcpy(pDuplicate,pInOut,nWords*sizeof(word));
+    for(i=0;i<5;i++)
+    {
+        if(bitInfoTemp == pStore[i+1])
+            minimalSwapAndFlipIVar_superFast_lessThen5_noEBFC(pInOut, i, nWords, pCanonPerm, pCanonPhase);
+        else
+        {
+            bitInfoTemp = pStore[i+1];
+            continue;
+        }
+    }
+    if(bitInfoTemp == pStore[i+1])
+        minimalSwapAndFlipIVar_superFast_iVar5_noEBFC((unsigned*) pInOut, nWords, pCanonPerm, pCanonPhase);
+    else    
+        bitInfoTemp = pStore[i+1];
+    
+    for(i=6;i<nVars-1;i++)
+    {
+        if(bitInfoTemp == pStore[i+1])
+            minimalSwapAndFlipIVar_superFast_moreThen5_noEBFC(pInOut, i, nWords, pCanonPerm, pCanonPhase);
+        else
+        {
+            bitInfoTemp = pStore[i+1];
+            continue;
+        }
+    }
+    if(memcmp(pInOut,pDuplicate , nWords*sizeof(word)) == 0)
+        return 0;
+    else
+        return 1;
+}
+
+
+// old version with out noEBFC
+// void luckyCanonicizerS_F_first_16Vars(word* pInOut, int  nVars, int nWords, int * pStore, char * pCanonPerm, unsigned* pCanonPhase)
+// {
+//     while( minimalSwapAndFlipIVar_superFast_all(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase) != 0)
+//         continue;
+// }
+
+void luckyCanonicizerS_F_first_16Vars1(word* pInOut, int  nVars, int nWords, int * pStore, char * pCanonPerm, unsigned* pCanonPhase)
+{
+    if(((* pCanonPhase) >> (nVars+1)) & 1)
+        while( minimalSwapAndFlipIVar_superFast_all(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase) != 0)
+            continue;
+    else
+        while( minimalSwapAndFlipIVar_superFast_all_noEBFC(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase) != 0)
+            continue;
+}
+
+void luckyCanonicizerS_F_first_16Vars11(word* pInOut, int  nVars, int nWords, int * pStore, char * pCanonPerm, unsigned* pCanonPhase)
+{
+    word duplicate[1024];
+    char pCanonPerm1[16];
+    unsigned uCanonPhase1;
+
+    if((* pCanonPhase) >> (nVars+2) )
+    {  
+        memcpy(duplicate, pInOut, sizeof(word)*nWords);
+        Kit_TruthNot_64bit(duplicate, nVars);
+        uCanonPhase1 = *pCanonPhase;
+        uCanonPhase1 ^= (1 << nVars);
+        memcpy(pCanonPerm1,pCanonPerm,sizeof(char)*16);
+        luckyCanonicizerS_F_first_16Vars1(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase); 
+        luckyCanonicizerS_F_first_16Vars1(duplicate, nVars, nWords, pStore, pCanonPerm1, &uCanonPhase1);
+        if(memCompare(pInOut, duplicate,nVars) == 1)
+        {
+            *pCanonPhase = uCanonPhase1;
+            memcpy(pCanonPerm,pCanonPerm1,sizeof(char)*16);
+            memcpy(pInOut, duplicate, sizeof(word)*nWords);
+        }
+    }
+    else 
+    {
+        luckyCanonicizerS_F_first_16Vars1(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase);
+    }
+}
+
+void luckyCanonicizer_final_fast_16Vars(word* pInOut, int  nVars, int nWords, int * pStore, char * pCanonPerm, unsigned* pCanonPhase)
+{
+    assert( nVars > 6 && nVars <= 16 );
+    (* pCanonPhase) = Kit_TruthSemiCanonicize_Yasha1( pInOut, nVars, pCanonPerm, pStore );
+    luckyCanonicizerS_F_first_16Vars1(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase ); 
+}
+
+void bitReverceOrder(word* x, int  nVars)
+{
+    int i;
+    for(i= nVars-1;i>=0;i--)
+        Kit_TruthChangePhase_64bit( x, nVars, i );
+}
+
+
+void luckyCanonicizer_final_fast_16Vars1(word* pInOut, int  nVars, int nWords, int * pStore, char * pCanonPerm, unsigned* pCanonPhase)
+{   
+    assert( nVars > 6 && nVars <= 16 );
+    (* pCanonPhase) = Kit_TruthSemiCanonicize_Yasha1( pInOut, nVars, pCanonPerm, pStore );
+    luckyCanonicizerS_F_first_16Vars11(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase ); 
+    bitReverceOrder(pInOut, nVars);
+    (*pCanonPhase) ^= (1<<nVars) -1;
+    luckyCanonicizerS_F_first_16Vars11(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase );
+//     bitReverceOrder(pInOut, nVars);
+//     (*pCanonPhase) ^= (1<<nVars) -1;
+//     luckyCanonicizerS_F_first_16Vars11(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase );
+}
+
+
+// top-level procedure calling two special cases (nVars <= 6 and nVars <= 16)
+unsigned luckyCanonicizer_final_fast( word * pInOut, int nVars, char * pCanonPerm )
+{
+    int nWords;
+    int pStore[16];
+    unsigned uCanonPhase = 0;
+#ifdef LUCKY_VERIFY
+    word temp[1024] = {0};
+    word duplicate[1024] = {0};
+    Kit_TruthCopy_64bit( duplicate, pInOut, nVars );
+#endif
+    if ( nVars <= 6 )
+        pInOut[0] = luckyCanonicizer_final_fast_6Vars( pInOut[0], pStore, pCanonPerm, &uCanonPhase);
+    else if ( nVars <= 16 )
+    {
+        nWords = (nVars <= 6) ? 1 : (1 << (nVars - 6));
+        luckyCanonicizer_final_fast_16Vars( pInOut, nVars, nWords, pStore, pCanonPerm, &uCanonPhase );
+    }
+    else assert( 0 );
+#ifdef LUCKY_VERIFY
+    Kit_TruthCopy_64bit( temp, pInOut, nVars );
+    assert( ! luckyCheck(temp, duplicate, nVars, pCanonPerm, uCanonPhase) );
+#endif
+        return uCanonPhase;
+}
+
+unsigned luckyCanonicizer_final_fast1( word * pInOut, int nVars, char * pCanonPerm)
+{
+    int nWords;
+    int pStore[16];
+    unsigned uCanonPhase = 0;
+#ifdef LUCKY_VERIFY
+    word temp[1024] = {0};
+    word duplicate[1024] = {0};
+    Kit_TruthCopy_64bit( duplicate, pInOut, nVars );
+#endif
+    if ( nVars <= 6 )
+        pInOut[0] = luckyCanonicizer_final_fast_6Vars1( pInOut[0], pStore, pCanonPerm, &uCanonPhase);
+    else if ( nVars <= 16 )
+    {
+        nWords = 1 << (nVars - 6);
+        luckyCanonicizer_final_fast_16Vars1( pInOut, nVars, nWords, pStore, pCanonPerm, &uCanonPhase );
+    }
+    else assert( 0 );
+#ifdef LUCKY_VERIFY
+    Kit_TruthCopy_64bit( temp, pInOut, nVars );
+    assert( ! luckyCheck(temp, duplicate, nVars, pCanonPerm, uCanonPhase) );
+#endif
+    return uCanonPhase;
+}
+
+
+ABC_NAMESPACE_IMPL_END
+
+
+
diff --git a/abc-build/src/bool/lucky/luckyFast6.c b/abc-build/src/bool/lucky/luckyFast6.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/lucky/luckyFast6.c
@@ -0,0 +1,285 @@
+/**CFile****************************************************************
+
+  FileName    [luckyFast6.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Semi-canonical form computation package.]
+
+  Synopsis    [Truth table minimization procedures for 6 vars.]
+
+  Author      [Jake]
+
+  Date        [Started - September 2012]
+
+***********************************************************************/
+
+#include "luckyInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+void resetPCanonPermArray_6Vars(char* x)
+{
+    x[0]='a';
+    x[1]='b';
+    x[2]='c';
+    x[3]='d';
+    x[4]='e';
+    x[5]='f';
+}
+void resetPCanonPermArray(char* x, int nVars)
+{
+    int i;
+    for(i=0;i<nVars;i++)
+        x[i] = 'a'+i;
+}
+
+
+
+ word Abc_allFlip(word x, unsigned* pCanonPhase)
+{
+    if(  (x>>63) )
+    {
+        (* pCanonPhase) ^=(1<<6);
+        return ~x;
+    }
+    else 
+        return x;
+    
+}
+
+unsigned adjustInfoAfterSwap(char* pCanonPerm, unsigned uCanonPhase, int iVar, unsigned info)
+{   
+    if(info<4)
+        return (uCanonPhase ^= (info << iVar));
+    else
+    {
+        char temp;
+        uCanonPhase ^= ((info-4) << iVar);
+        temp=pCanonPerm[iVar];
+        pCanonPerm[iVar]=pCanonPerm[iVar+1];
+        pCanonPerm[iVar+1]=temp;
+        if ( ((uCanonPhase & (1 << iVar)) > 0) != ((uCanonPhase & (1 << (iVar+1))) > 0) )
+        {
+            uCanonPhase ^= (1 << iVar);
+            uCanonPhase ^= (1 << (iVar+1));
+        }
+        return uCanonPhase; 
+    }
+
+
+}
+
+word Extra_Truth6SwapAdjacent( word t, int iVar )
+{
+    // variable swapping code
+    static word PMasks[5][3] = {
+        { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) },
+        { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) },
+        { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) },
+        { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) },
+        { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) }
+    };
+    assert( iVar < 5 );
+    return (t & PMasks[iVar][0]) | ((t & PMasks[iVar][1]) << (1 << iVar)) | ((t & PMasks[iVar][2]) >> (1 << iVar));
+}
+word Extra_Truth6ChangePhase( word t, int iVar)
+{
+    // elementary truth tables
+    static word Truth6[6] = {
+        ABC_CONST(0xAAAAAAAAAAAAAAAA),
+        ABC_CONST(0xCCCCCCCCCCCCCCCC),
+        ABC_CONST(0xF0F0F0F0F0F0F0F0),
+        ABC_CONST(0xFF00FF00FF00FF00),
+        ABC_CONST(0xFFFF0000FFFF0000),
+        ABC_CONST(0xFFFFFFFF00000000)
+    };
+    assert( iVar < 6 );
+    return ((t & ~Truth6[iVar]) << (1 << iVar)) | ((t & Truth6[iVar]) >> (1 << iVar));
+}
+
+word Extra_Truth6MinimumRoundOne( word t, int iVar, char* pCanonPerm, unsigned* pCanonPhase )
+{
+    word tCur, tMin = t; // ab 
+    unsigned info =0;
+    assert( iVar >= 0 && iVar < 5 );
+    
+    tCur = Extra_Truth6ChangePhase( t, iVar );    // !a b
+    if(tCur<tMin)
+    {
+        info = 1;
+        tMin = tCur;
+    }
+    tCur = Extra_Truth6ChangePhase( t, iVar+1 );  // a !b
+    if(tCur<tMin)
+    {
+        info = 2;
+        tMin = tCur;
+    }
+    tCur = Extra_Truth6ChangePhase( tCur, iVar ); // !a !b
+    if(tCur<tMin)
+    {
+        info = 3;
+        tMin = tCur;
+    }
+    
+    t    = Extra_Truth6SwapAdjacent( t, iVar );   // b a
+    if(t<tMin)
+    {
+        info = 4;
+        tMin = t;
+    }
+    
+    tCur = Extra_Truth6ChangePhase( t, iVar );    // !b a
+    if(tCur<tMin)
+    {
+        info = 6;
+        tMin = tCur;
+    }
+    tCur = Extra_Truth6ChangePhase( t, iVar+1 );  // b !a
+    if(tCur<tMin)
+    {
+        info = 5;
+        tMin = tCur;
+    }
+    tCur = Extra_Truth6ChangePhase( tCur, iVar ); // !b !a
+    if(tCur<tMin)
+    {
+        (* pCanonPhase) = adjustInfoAfterSwap(pCanonPerm, * pCanonPhase, iVar, 7);
+        return tCur;
+    }
+    else
+    {
+        (* pCanonPhase) = adjustInfoAfterSwap(pCanonPerm, * pCanonPhase, iVar, info);
+        return tMin;
+    }
+}
+
+word Extra_Truth6MinimumRoundOne_noEBFC( word t, int iVar,  char* pCanonPerm, unsigned* pCanonPhase)
+{
+    word tMin;     
+    assert( iVar >= 0 && iVar < 5 );  
+    
+    tMin = Extra_Truth6SwapAdjacent( t, iVar );   // b a
+    if(t<tMin)
+        return t;
+    else
+    {
+        (* pCanonPhase) = adjustInfoAfterSwap(pCanonPerm, * pCanonPhase, iVar, 4);
+        return tMin;
+    }
+}
+
+
+// this function finds minimal for all TIED(and tied only) iVars 
+//it finds tied vars based on rearranged  Store info - group of tied vars has the same bit count in Store
+word Extra_Truth6MinimumRoundMany( word t, int* pStore, char* pCanonPerm, unsigned* pCanonPhase )
+{
+    int i, bitInfoTemp;
+    word tMin0, tMin=t;
+    do
+    {
+        bitInfoTemp = pStore[0];
+        tMin0 = tMin;
+        for ( i = 0; i < 5; i++ )
+        {
+            if(bitInfoTemp == pStore[i+1])          
+                tMin = Extra_Truth6MinimumRoundOne( tMin, i, pCanonPerm, pCanonPhase );         
+            else
+                bitInfoTemp = pStore[i+1];
+        }
+    }while ( tMin0 != tMin );
+    return tMin;
+}
+
+word Extra_Truth6MinimumRoundMany_noEBFC( word t, int* pStore, char* pCanonPerm, unsigned* pCanonPhase )
+{
+    int i, bitInfoTemp;
+    word tMin0, tMin=t;
+    do
+    {
+        bitInfoTemp = pStore[0];
+        tMin0 = tMin;
+        for ( i = 0; i < 5; i++ )
+        {
+            if(bitInfoTemp == pStore[i+1])          
+                tMin = Extra_Truth6MinimumRoundOne_noEBFC( tMin, i, pCanonPerm, pCanonPhase );         
+            else
+                bitInfoTemp = pStore[i+1];
+        } 
+    }while ( tMin0 != tMin );
+    return tMin;
+}
+word Extra_Truth6MinimumRoundMany1( word t, int* pStore, char* pCanonPerm, unsigned* pCanonPhase )
+{
+    word tMin0, tMin=t;
+    char pCanonPerm1[16];
+    unsigned uCanonPhase1;
+    switch ((* pCanonPhase) >> 7)
+    {
+    case 0 :
+        {
+
+    	    return Extra_Truth6MinimumRoundMany_noEBFC( t, pStore, pCanonPerm, pCanonPhase);
+        }
+    case 1 :
+        {            
+            return Extra_Truth6MinimumRoundMany( t, pStore, pCanonPerm, pCanonPhase);
+        }
+    case 2 :
+        { 
+            uCanonPhase1 = *pCanonPhase;
+            uCanonPhase1 ^= (1 << 6);
+            memcpy(pCanonPerm1,pCanonPerm,sizeof(char)*16);
+            tMin0 = Extra_Truth6MinimumRoundMany_noEBFC( t, pStore, pCanonPerm, pCanonPhase);
+            tMin =  Extra_Truth6MinimumRoundMany_noEBFC( ~t, pStore, pCanonPerm1, &uCanonPhase1);
+            if(tMin0 <=tMin)
+                return tMin0;
+            else
+            {
+                *pCanonPhase = uCanonPhase1;
+                memcpy(pCanonPerm,pCanonPerm1,sizeof(char)*16);
+                return tMin;
+            }
+        }
+    case 3 :
+        {
+            uCanonPhase1 = *pCanonPhase;
+            uCanonPhase1 ^= (1 << 6);
+            memcpy(pCanonPerm1,pCanonPerm,sizeof(char)*16);
+            tMin0 = Extra_Truth6MinimumRoundMany( t, pStore, pCanonPerm, pCanonPhase);
+            tMin =  Extra_Truth6MinimumRoundMany( ~t, pStore, pCanonPerm1, &uCanonPhase1);
+            if(tMin0 <=tMin)
+                return tMin0;
+            else
+            {
+                *pCanonPhase = uCanonPhase1;
+                memcpy(pCanonPerm,pCanonPerm1,sizeof(char)*16);
+                return tMin;
+            }
+        }
+    }
+    return Extra_Truth6MinimumRoundMany( t, pStore, pCanonPerm, pCanonPhase);
+}
+
+word luckyCanonicizer_final_fast_6Vars(word InOut, int* pStore, char* pCanonPerm, unsigned* pCanonPhase)
+{
+    (* pCanonPhase) = Kit_TruthSemiCanonicize_Yasha1( &InOut, 6, pCanonPerm, pStore);
+    return Extra_Truth6MinimumRoundMany1(InOut, pStore, pCanonPerm, pCanonPhase); 
+}
+word luckyCanonicizer_final_fast_6Vars1(word InOut, int* pStore, char* pCanonPerm, unsigned* pCanonPhase )
+{
+    (* pCanonPhase) = Kit_TruthSemiCanonicize_Yasha1( &InOut, 6, pCanonPerm, pStore);
+    InOut = Extra_Truth6MinimumRoundMany1(InOut, pStore, pCanonPerm, pCanonPhase);
+    Kit_TruthChangePhase_64bit( &InOut, 6, 5 );
+    Kit_TruthChangePhase_64bit( &InOut, 6, 4 );
+    Kit_TruthChangePhase_64bit( &InOut, 6, 3 );
+    Kit_TruthChangePhase_64bit( &InOut, 6, 2 );
+    Kit_TruthChangePhase_64bit( &InOut, 6, 1 );        
+    Kit_TruthChangePhase_64bit( &InOut, 6, 0 );
+    (*pCanonPhase) ^= 0x3F;
+    return Extra_Truth6MinimumRoundMany1(InOut, pStore, pCanonPerm, pCanonPhase); 
+}
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/bool/lucky/luckyInt.h b/abc-build/src/bool/lucky/luckyInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/lucky/luckyInt.h
@@ -0,0 +1,136 @@
+/**CFile****************************************************************
+
+  FileName    [luckyInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Semi-canonical form computation package.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Jake]
+
+  Date        [Started - August 2012]
+
+***********************************************************************/
+
+#ifndef ABC__bool__lucky__LUCKY_INT_H_
+#define ABC__bool__lucky__LUCKY_INT_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+
+// comment out this line to run Lucky Code outside of ABC
+#define _RUNNING_ABC_
+
+#ifdef _RUNNING_ABC_
+
+#include "misc/util/abc_global.h"
+#include "lucky.h"
+
+#else
+
+#define ABC_NAMESPACE_HEADER_START
+#define ABC_NAMESPACE_HEADER_END
+#define ABC_NAMESPACE_IMPL_START
+#define ABC_NAMESPACE_IMPL_END
+typedef unsigned __int64  word;
+#define bool int
+#define false 0
+#define true 1
+#define inline __inline  // compatible with MS VS 6.0
+#define ABC_ALLOC(type, num)    ((type *) malloc(sizeof(type) * (num)))
+// #define LUCKY_VERIFY
+
+typedef struct
+{
+    int varN;
+    int* swapArray;
+    int swapCtr;
+    int totalSwaps;
+    int* flipArray;
+    int flipCtr;
+    int totalFlips; 
+}permInfo;
+
+#endif
+
+
+ABC_NAMESPACE_HEADER_START
+
+typedef struct  
+{
+    int      nVars;
+    int      nWords;
+    int      nFuncs;
+    word **  pFuncs;
+}Abc_TtStore_t;
+
+typedef struct 
+{
+    int direction; 
+    int position;
+} varInfo;
+
+
+typedef struct 
+{
+    varInfo* posArray;
+    int* realArray;
+    int varN;
+    int positionToSwap1;
+    int positionToSwap2;
+} swapInfo;
+
+
+static inline void TimePrint( char* Message )
+{
+    static int timeBegin;
+    double time = 1.0*(Abc_Clock() - timeBegin)/CLOCKS_PER_SEC ;
+    if ( Message != NULL)
+        printf("%s = %f sec.\n", Message, time);
+    timeBegin = Abc_Clock();
+}
+
+static inline int CompareWords( word x, word y)
+{
+    if( x > y )
+        return 1;
+    if( x < y )
+        return -1;
+    return 0;
+}
+
+static inline int       luckyMin( int x, int y ) { return (x < y) ? x : y; }
+static inline int       luckyMax( int x, int y ) { return (x < y) ? y : x; }
+
+
+extern  int             memCompare(word* x, word*  y, int nVars);
+extern  int             Kit_TruthWordNum_64bit( int nVars );
+extern  Abc_TtStore_t * setTtStore(char * pFileInput);
+extern  void            Abc_TruthStoreFree( Abc_TtStore_t * p );
+extern  void            Kit_TruthChangePhase_64bit( word * pInOut, int nVars, int iVar );
+extern  void            Kit_TruthNot_64bit(word * pIn, int nVars );
+extern  void            Kit_TruthCopy_64bit( word * pOut, word * pIn, int nVars );
+extern  void            Kit_TruthSwapAdjacentVars_64bit( word * pInOut, int nVars, int iVar );
+extern  int             Kit_TruthCountOnes_64bit( word* pIn, int nVars );
+extern  void            simpleMinimal(word* x, word* pAux,word* minimal, permInfo* pi, int nVars);
+extern  permInfo *      setPermInfoPtr(int var);
+extern  void            freePermInfoPtr(permInfo* x);
+extern  void            Kit_TruthSemiCanonicize_Yasha_simple( word* pInOut, int nVars, int * pStore );
+extern  unsigned        Kit_TruthSemiCanonicize_Yasha( word* pInOut, int nVars, char * pCanonPerm);
+extern  unsigned        Kit_TruthSemiCanonicize_Yasha1( word* pInOut, int nVars, char * pCanonPerm, int * pStore);
+extern  word            luckyCanonicizer_final_fast_6Vars(word InOut, int* pStore, char* pCanonPerm, unsigned* pCanonPhase);
+extern  word            luckyCanonicizer_final_fast_6Vars1(word InOut, int* pStore, char* pCanonPerm, unsigned* pCanonPhase);
+extern  unsigned        adjustInfoAfterSwap(char* pCanonPerm, unsigned uCanonPhase, int iVar, unsigned info);
+extern  void            resetPCanonPermArray_6Vars(char* x);
+extern  void            swap_ij( word* f,int totalVars, int varI, int varJ);
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif /* LUCKY_H_ */
diff --git a/abc-build/src/bool/lucky/luckyRead.c b/abc-build/src/bool/lucky/luckyRead.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/lucky/luckyRead.c
@@ -0,0 +1,333 @@
+/**CFile****************************************************************
+
+  FileName    [luckyRead.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Semi-canonical form computation package.]
+
+  Synopsis    [Reading truth tables from file.]
+
+  Author      [Jake]
+
+  Date        [Started - August 2012]
+
+***********************************************************************/
+
+#include "luckyInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+// read/write/flip i-th bit of a bit string table:
+static inline int     Abc_TruthGetBit( word * p, int i )         { return (int)(p[i>>6] >> (i & 63)) & 1;        }
+static inline void    Abc_TruthSetBit( word * p, int i )         { p[i>>6] |= (((word)1)<<(i & 63));             }
+static inline void    Abc_TruthXorBit( word * p, int i )         { p[i>>6] ^= (((word)1)<<(i & 63));             }
+
+// read/write k-th digit d of a hexadecimal number:
+static inline int     Abc_TruthGetHex( word * p, int k )         { return (int)(p[k>>4] >> ((k<<2) & 63)) & 15;  }
+static inline void    Abc_TruthSetHex( word * p, int k, int d )  { p[k>>4] |= (((word)d)<<((k<<2) & 63));        }
+static inline void    Abc_TruthXorHex( word * p, int k, int d )  { p[k>>4] ^= (((word)d)<<((k<<2) & 63));        }
+
+// read one hex character
+static inline int  Abc_TruthReadHexDigit( char HexChar )
+{
+    if ( HexChar >= '0' && HexChar <= '9' )
+        return HexChar - '0';
+    if ( HexChar >= 'A' && HexChar <= 'F' )
+        return HexChar - 'A' + 10;
+    if ( HexChar >= 'a' && HexChar <= 'f' )
+        return HexChar - 'a' + 10;
+    assert( 0 ); // not a hexadecimal symbol
+    return -1; // return value which makes no sense
+}
+
+// write one hex character
+static inline void Abc_TruthWriteHexDigit( FILE * pFile, int HexDigit )
+{
+    assert( HexDigit >= 0 && HexDigit < 16 );
+    if ( HexDigit < 10 )
+        fprintf( pFile, "%d", HexDigit );
+    else
+        fprintf( pFile, "%c", 'A' + HexDigit-10 );
+}
+
+// read one truth table in hexadecimal
+static inline void Abc_TruthReadHex( word * pTruth, char * pString, int nVars )
+{
+    int nWords = (nVars < 7)? 1 : (1 << (nVars-6));
+    int k, Digit, nDigits = (nWords << 4);
+    char EndSymbol;
+    // skip the first 2 symbols if they are "0x"
+    if ( pString[0] == '0' && pString[1] == 'x' )
+        pString += 2;
+    // get the last symbol
+    EndSymbol = pString[nDigits];
+    // the end symbol of the TT (the one immediately following hex digits)
+    // should be one of the following: space, a new-line, or a zero-terminator
+    // (note that on Windows symbols '\r' can be inserted before each '\n')
+    assert( EndSymbol == ' ' || EndSymbol == '\n' || EndSymbol == '\r' || EndSymbol == '\0' );
+    // read hexadecimal digits in the reverse order
+    // (the last symbol in the string is the least significant digit)
+    for ( k = 0; k < nDigits; k++ )
+    {
+        Digit = Abc_TruthReadHexDigit( pString[nDigits - 1 - k] );
+        assert( Digit >= 0 && Digit < 16 );
+        Abc_TruthSetHex( pTruth, k, Digit );
+    }
+}
+
+// write one truth table in hexadecimal (do not add end-of-line!)
+static inline void Abc_TruthWriteHex( FILE * pFile, word * pTruth, int nVars )
+{
+    int nDigits, Digit, k;
+    // write hexadecimal digits in the reverse order
+    // (the last symbol in the string is the least significant digit)
+    nDigits = (1 << (nVars-2));
+    for ( k = 0; k < nDigits; k++ )
+    {
+        Digit = Abc_TruthGetHex( pTruth, nDigits - 1 - k );
+        assert( Digit >= 0 && Digit < 16 );
+        Abc_TruthWriteHexDigit( pFile, Digit );
+    }
+}
+
+// allocate and clear memory to store 'nTruths' truth tables of 'nVars' variables
+static inline Abc_TtStore_t * Abc_TruthStoreAlloc( int nVars, int nFuncs )
+{
+    Abc_TtStore_t * p;
+    int i;
+    p = (Abc_TtStore_t *)malloc( sizeof(Abc_TtStore_t) );
+    p->nVars  =  nVars;
+    p->nWords = (nVars < 7) ? 1 : (1 << (nVars-6));
+    p->nFuncs =  nFuncs;
+    // alloc array of 'nFuncs' pointers to truth tables
+    p->pFuncs = (word **)malloc( sizeof(word *) * p->nFuncs );
+    // alloc storage for 'nFuncs' truth tables as one chunk of memory
+    p->pFuncs[0] = (word *)calloc( sizeof(word), p->nFuncs * p->nWords );
+    // split it up into individual truth tables
+    for ( i = 1; i < p->nFuncs; i++ )
+        p->pFuncs[i] = p->pFuncs[i-1] + p->nWords;
+    return p;
+}
+
+// free memory previously allocated for storing truth tables
+void Abc_TruthStoreFree( Abc_TtStore_t * p )
+{
+    free( p->pFuncs[0] );
+    free( p->pFuncs );
+    free( p );
+}
+
+// read file contents
+static char * Abc_FileRead( char * pFileName )
+{
+    FILE * pFile;
+    char * pBuffer;
+    int nFileSize;
+    int RetValue;
+    pFile = fopen( pFileName, "r" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\" for reading.\n", pFileName );
+        return NULL;
+    }
+    // get the file size, in bytes
+    fseek( pFile, 0, SEEK_END );  
+    nFileSize = ftell( pFile );  
+    // move the file current reading position to the beginning
+    rewind( pFile ); 
+    // load the contents of the file into memory
+    pBuffer = (char *)malloc( nFileSize + 3 );
+    RetValue = fread( pBuffer, nFileSize, 1, pFile );
+    // add several empty lines at the end
+    // (these will be used to signal the end of parsing)
+    pBuffer[ nFileSize + 0] = '\n';
+    pBuffer[ nFileSize + 1] = '\n';
+    // terminate the string with '\0'
+    pBuffer[ nFileSize + 2] = '\0';
+    fclose( pFile );
+    return pBuffer;
+}
+
+// determine the number of variables by reading the first line
+// determine the number of functions by counting the lines
+static void Abc_TruthGetParams( char * pFileName, int * pnVars, int * pnTruths )
+{
+    char * pContents;
+    int i, nVars, nLines;
+    // prepare the output 
+    if ( pnVars )
+        *pnVars = 0;
+    if ( pnTruths )
+        *pnTruths = 0;
+    // read data from file
+    pContents = Abc_FileRead( pFileName );
+    if ( pContents == NULL )
+        return;
+    // count the number of symbols before the first space or new-line
+    // (note that on Windows symbols '\r' can be inserted before each '\n')
+    for ( i = 0; pContents[i]; i++ )
+        if ( pContents[i] == ' ' || pContents[i] == '\n' || pContents[i] == '\r' )
+            break;
+    if ( pContents[i] == 0 )
+        printf( "Strange, the input file does not have spaces and new-lines...\n" );
+
+    // account for the fact that truth tables may have "0x" at the beginning of each line
+    if ( pContents[0] == '0' && pContents[1] == 'x' )
+        i = i - 2;
+
+    // determine the number of variables
+    for ( nVars = 0; nVars < 32; nVars++ )
+        if ( 4 * i == (1 << nVars) ) // the number of bits equal to the size of truth table
+            break;
+    if ( nVars < 2 || nVars > 16 )
+    {
+        printf( "Does not look like the input file contains truth tables...\n" );
+        return;
+    }
+    if ( pnVars )
+        *pnVars = nVars;
+
+    // determine the number of functions by counting the lines
+    nLines = 0;
+    for ( i = 0; pContents[i]; i++ )
+        nLines += (pContents[i] == '\n');
+    if ( pnTruths )
+        *pnTruths = nLines;
+}
+
+static Abc_TtStore_t * Abc_Create_TtSpore (char * pFileInput)
+{
+    int nVars, nTruths;
+    Abc_TtStore_t * p;
+    Abc_TruthGetParams( pFileInput, &nVars, &nTruths );
+    p = Abc_TruthStoreAlloc( nVars, nTruths );
+    return p;
+
+}
+// read truth tables from file
+static void Abc_TruthStoreRead( char * pFileName, Abc_TtStore_t* p )
+{
+    char * pContents;
+    int i, nLines;
+    pContents = Abc_FileRead( pFileName );
+    if ( pContents == NULL )
+        return;
+    // here it is assumed (without checking!) that each line of the file 
+    // begins with a string of hexadecimal chars followed by space
+
+    // the file will be read till the first empty line (pContents[i] == '\n')
+    // (note that Abc_FileRead() added several empty lines at the end of the file contents)
+    for ( nLines = i = 0; pContents[i] != '\n'; )
+    {
+        // read one line
+        Abc_TruthReadHex( p->pFuncs[nLines++], &pContents[i], p->nVars );
+        // skip till after the end-of-line symbol
+        // (note that end-of-line symbol is also skipped)
+        while ( pContents[i++] != '\n' );
+    }
+    // adjust the number of functions read 
+    // (we may have allocated more storage because some lines in the file were empty)
+    assert( p->nFuncs >= nLines );
+    p->nFuncs = nLines;
+}
+
+// write truth tables into file
+// (here we write one symbol at a time - it can be optimized by writing 
+// each truth table into a string and then writing the string into a file)
+static void Abc_TruthStoreWrite( char * pFileName, Abc_TtStore_t * p )
+{
+    FILE * pFile;
+    int i;
+    pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\" for writing.\n", pFileName );
+        return;
+    }
+    for ( i = 0; i < p->nFuncs; i++ )
+    {
+        Abc_TruthWriteHex( pFile, p->pFuncs[i], p->nVars );
+        fprintf( pFile, "\n" );
+    }
+    fclose( pFile );
+}
+
+static void WriteToFile(char * pFileName, Abc_TtStore_t * p, word* a)
+{
+    FILE * pFile;
+    int i;
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\" for writing.\n", pFileName );
+        return;
+    }
+    for ( i = 0; i < p->nFuncs; i++ )
+    {
+        Abc_TruthWriteHex( pFile, &a[i], p->nVars );
+        fprintf( pFile, "\n" );
+    }
+    fclose( pFile );
+}
+
+static void WriteToFile1(char * pFileName, Abc_TtStore_t * p, word** a)
+{
+    FILE * pFile;
+    int i,j;
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\" for writing.\n", pFileName );
+        return;
+    }
+    for ( i = 0; i < p->nFuncs; i++ )
+    {
+        fprintf( pFile, "0" );
+        fprintf( pFile, "x" );
+        for ( j=p->nWords-1; j >= 0; j-- )
+            Abc_TruthWriteHex( pFile, &a[i][j], p->nVars );
+        fprintf( pFile, "\n" );
+    }
+    fprintf( pFile, "\n" );
+    fclose( pFile );
+}
+static void WriteToFile2(char * pFileName, Abc_TtStore_t * p, word* a)
+{
+    FILE * pFile;
+    int i,j;
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\" for writing.\n", pFileName );
+        return;
+    }
+    for ( i = 0; i < p->nFuncs; i++ )
+    {
+        fprintf( pFile, "0" );
+        fprintf( pFile, "x" );
+        for ( j=p->nWords-1; j >= 0; j-- )
+            Abc_TruthWriteHex( pFile, a+i, p->nVars );
+        fprintf( pFile, "\n" );
+    }
+    fprintf( pFile, "\n" );
+    fclose( pFile );
+}
+
+
+Abc_TtStore_t * setTtStore(char * pFileInput)
+{
+    int nVars, nTruths;
+    Abc_TtStore_t * p;
+    // figure out how many truth table and how many variables
+    Abc_TruthGetParams( pFileInput, &nVars, &nTruths );
+    // allocate data-structure
+    p = Abc_TruthStoreAlloc( nVars, nTruths );
+
+    Abc_TruthStoreRead( pFileInput, p );
+    return p;
+}
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/bool/lucky/luckySimple.c b/abc-build/src/bool/lucky/luckySimple.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/lucky/luckySimple.c
@@ -0,0 +1,183 @@
+/**CFile****************************************************************
+
+  FileName    [luckySimple.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Semi-canonical form computation package.]
+
+  Synopsis    [Truth table minimization procedures.]
+
+  Author      [Jake]
+
+  Date        [Started - August 2012]
+
+***********************************************************************/
+
+#include "luckyInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+static swapInfo* setSwapInfoPtr(int varsN)
+{
+	int i;
+	swapInfo* x = (swapInfo*) malloc(sizeof(swapInfo));
+	x->posArray = (varInfo*) malloc (sizeof(varInfo)*(varsN+2));
+	x->realArray = (int*) malloc (sizeof(int)*(varsN+2));
+	x->varN = varsN;
+	x->realArray[0]=varsN+100;
+	for(i=1;i<=varsN;i++)
+	{
+		x->posArray[i].position=i;
+		x->posArray[i].direction=-1;
+		x->realArray[i]=i;
+	}	
+	x->realArray[varsN+1]=varsN+10;
+	return x;
+}
+
+
+static void freeSwapInfoPtr(swapInfo* x)
+{
+	free(x->posArray);
+	free(x->realArray);
+	free(x);
+}
+
+int nextSwap(swapInfo* x)
+{
+	int i,j,temp;
+	for(i=x->varN;i>1;i--)
+	{
+		if( i > x->realArray[x->posArray[i].position + x->posArray[i].direction] )
+		{
+			x->posArray[i].position = x->posArray[i].position + x->posArray[i].direction;
+			temp = x->realArray[x->posArray[i].position];
+			x->realArray[x->posArray[i].position] = i; 
+			x->realArray[x->posArray[i].position - x->posArray[i].direction] = temp;
+			x->posArray[temp].position = x->posArray[i].position - x->posArray[i].direction; 
+			for(j=x->varN;j>i;j--)
+			{
+				x->posArray[j].direction = 	x->posArray[j].direction * -1;
+			}
+			x->positionToSwap1 = x->posArray[temp].position - 1;
+			x->positionToSwap2 = x->posArray[i].position - 1;			
+			return 1;
+		}
+		
+	}
+	return 0;	
+}
+
+void fillInSwapArray(permInfo* pi)
+{
+	int counter=pi->totalSwaps-1;
+	swapInfo* x= setSwapInfoPtr(pi->varN);
+	while(nextSwap(x)==1)
+	{
+		if(x->positionToSwap1<x->positionToSwap2)
+			pi->swapArray[counter--]=x->positionToSwap1;
+		else
+			pi->swapArray[counter--]=x->positionToSwap2;
+	}
+	
+	freeSwapInfoPtr(x);	
+}
+int oneBitPosition(int x, int size)
+{
+	int i;
+	for(i=0;i<size;i++)
+		if((x>>i)&1)
+			return i;
+	return -1;
+}
+void fillInFlipArray(permInfo* pi)
+{
+	int i, temp=0, grayNumber;
+	for(i=1;i<=pi->totalFlips;i++)
+	{
+		grayNumber = i^(i>>1);
+		pi->flipArray[pi->totalFlips-i]=oneBitPosition(temp^grayNumber, pi->varN);
+		temp = grayNumber;		
+	}
+	
+	
+}
+inline int factorial(int n)
+{
+	return (n == 1 || n == 0) ? 1 : factorial(n - 1) * n;
+}
+permInfo* setPermInfoPtr(int var)
+{
+	permInfo* x;
+	x = (permInfo*) malloc(sizeof(permInfo));
+	x->flipCtr=0;
+	x->varN = var; 
+	x->totalFlips=(1<<var)-1;
+	x->swapCtr=0;
+	x->totalSwaps=factorial(var)-1;
+	x->flipArray = (int*) malloc(sizeof(int)*x->totalFlips);
+	x->swapArray = (int*) malloc(sizeof(int)*x->totalSwaps);
+	fillInSwapArray(x);
+	fillInFlipArray(x);
+	return x;
+}
+
+void freePermInfoPtr(permInfo* x)
+{
+    free(x->flipArray);
+    free(x->swapArray);
+    free(x);
+}
+inline void minWord(word* a, word* b, word* minimal, int nVars)
+{
+    if(memCompare(a, b, nVars) == -1)
+        Kit_TruthCopy_64bit( minimal, a, nVars );
+    else
+        Kit_TruthCopy_64bit( minimal, b, nVars );
+}
+inline void minWord3(word* a, word* b, word* minimal, int nVars)
+{ 
+    if (memCompare(a, b, nVars) <= 0)
+    {
+        if (memCompare(a, minimal, nVars) < 0) 
+            Kit_TruthCopy_64bit( minimal, a, nVars ); 
+        else 
+            return ;
+    }	
+    if (memCompare(b, minimal, nVars) <= 0)
+        Kit_TruthCopy_64bit( minimal, b, nVars );
+}
+void simpleMinimal(word* x, word* pAux,word* minimal, permInfo* pi, int nVars)
+{
+    int i,j=0;
+    Kit_TruthCopy_64bit( pAux, x, nVars );
+    Kit_TruthNot_64bit( x, nVars );
+    
+    minWord(x, pAux, minimal, nVars);
+    
+    for(i=pi->totalSwaps-1;i>=0;i--)
+    {
+        Kit_TruthSwapAdjacentVars_64bit(x, nVars, pi->swapArray[i]);
+        Kit_TruthSwapAdjacentVars_64bit(pAux, nVars, pi->swapArray[i]);
+        minWord3(x, pAux, minimal, nVars);
+    }
+    for(j=pi->totalFlips-1;j>=0;j--)
+    {
+        Kit_TruthSwapAdjacentVars_64bit(x, nVars, 0);
+        Kit_TruthSwapAdjacentVars_64bit(pAux, nVars, 0);
+        Kit_TruthChangePhase_64bit(x, nVars, pi->flipArray[j]);
+        Kit_TruthChangePhase_64bit(pAux, nVars, pi->flipArray[j]);
+        minWord3(x, pAux, minimal, nVars);
+        for(i=pi->totalSwaps-1;i>=0;i--)
+        {
+            Kit_TruthSwapAdjacentVars_64bit(x, nVars, pi->swapArray[i]);
+            Kit_TruthSwapAdjacentVars_64bit(pAux, nVars, pi->swapArray[i]);
+            minWord3(x, pAux, minimal, nVars);
+        }
+    } 
+    Kit_TruthCopy_64bit( x, minimal, nVars );	
+}
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/bool/lucky/luckySwap.c b/abc-build/src/bool/lucky/luckySwap.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/lucky/luckySwap.c
@@ -0,0 +1,402 @@
+/**CFile****************************************************************
+
+  FileName    [luckySwap.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Semi-canonical form computation package.]
+
+  Synopsis    [Swapping variables in the truth table.]
+
+  Author      [Jake]
+
+  Date        [Started - August 2012]
+
+***********************************************************************/
+
+#include "luckyInt.h"
+
+
+ABC_NAMESPACE_IMPL_START
+
+
+static word mask0[6] = { ABC_CONST(0x5555555555555555),ABC_CONST(0x3333333333333333), ABC_CONST(0x0F0F0F0F0F0F0F0F),ABC_CONST(0x00FF00FF00FF00FF),ABC_CONST(0x0000FFFF0000FFFF), ABC_CONST(0x00000000FFFFFFFF)};  
+/*
+static word mask1[6] = { 0xAAAAAAAAAAAAAAAA,0xCCCCCCCCCCCCCCCC, 0xF0F0F0F0F0F0F0F0,0xFF00FF00FF00FF00,0xFFFF0000FFFF0000, 0xFFFFFFFF00000000 };
+static word mask[6][2] =   {
+    {0x5555555555555555,0xAAAAAAAAAAAAAAAA},
+    {0x3333333333333333,0xCCCCCCCCCCCCCCCC},
+    {0x0F0F0F0F0F0F0F0F,0xF0F0F0F0F0F0F0F0},
+    {0x00FF00FF00FF00FF,0xFF00FF00FF00FF00},
+    {0x0000FFFF0000FFFF,0xFFFF0000FFFF0000},
+    {0x00000000FFFFFFFF,0xFFFFFFFF00000000}
+};
+*/
+
+int Kit_TruthWordNum_64bit( int nVars )  { return nVars <= 6 ? 1 : (1 << (nVars - 6));}
+
+int Kit_WordCountOnes_64bit(word x)
+{
+    x = x - ((x >> 1) & ABC_CONST(0x5555555555555555));   
+    x = (x & ABC_CONST(0x3333333333333333)) + ((x >> 2) & ABC_CONST(0x3333333333333333));    
+    x = (x + (x >> 4)) & ABC_CONST(0x0F0F0F0F0F0F0F0F);    
+    x = x + (x >> 8);
+    x = x + (x >> 16);
+    x = x + (x >> 32); 
+    return (int)(x & 0xFF);
+}
+
+int Kit_TruthCountOnes_64bit( word* pIn, int nVars )
+{
+    int w, Counter = 0;
+    for ( w = Kit_TruthWordNum_64bit(nVars)-1; w >= 0; w-- )
+        Counter += Kit_WordCountOnes_64bit(pIn[w]);
+    return Counter;
+}
+
+void Kit_TruthCountOnesInCofs_64bit( word * pTruth, int nVars, int * pStore )
+{    
+    int nWords = Kit_TruthWordNum_64bit( nVars );
+    int i, k, Counter;
+    memset( pStore, 0, sizeof(int) * nVars );
+    if ( nVars <= 6 )
+    {
+        if ( nVars > 0 )        
+            pStore[0] = Kit_WordCountOnes_64bit( pTruth[0] & ABC_CONST(0x5555555555555555) );  
+        if ( nVars > 1 )       
+            pStore[1] = Kit_WordCountOnes_64bit( pTruth[0] & ABC_CONST(0x3333333333333333) );     
+        if ( nVars > 2 )       
+            pStore[2] = Kit_WordCountOnes_64bit( pTruth[0] & ABC_CONST(0x0F0F0F0F0F0F0F0F) );   
+        if ( nVars > 3 )       
+            pStore[3] = Kit_WordCountOnes_64bit( pTruth[0] & ABC_CONST(0x00FF00FF00FF00FF) );     
+        if ( nVars > 4 )       
+            pStore[4] = Kit_WordCountOnes_64bit( pTruth[0] & ABC_CONST(0x0000FFFF0000FFFF) ); 
+        if ( nVars > 5 )       
+            pStore[5] = Kit_WordCountOnes_64bit( pTruth[0] & ABC_CONST(0x00000000FFFFFFFF) );      
+        return;
+    }
+    // nVars > 6
+    // count 1's for all other variables
+    for ( k = 0; k < nWords; k++ )
+    {
+        Counter = Kit_WordCountOnes_64bit( pTruth[k] );
+        for ( i = 6; i < nVars; i++ )
+            if ( (k & (1 << (i-6))) == 0)
+                pStore[i] += Counter;
+    }
+    // count 1's for the first six variables
+    for ( k = nWords/2; k>0; k-- )
+    {
+        pStore[0] += Kit_WordCountOnes_64bit( (pTruth[0] & ABC_CONST(0x5555555555555555)) | ((pTruth[1] & ABC_CONST(0x5555555555555555)) <<  1) );
+        pStore[1] += Kit_WordCountOnes_64bit( (pTruth[0] & ABC_CONST(0x3333333333333333)) | ((pTruth[1] & ABC_CONST(0x3333333333333333)) <<  2) );
+        pStore[2] += Kit_WordCountOnes_64bit( (pTruth[0] & ABC_CONST(0x0F0F0F0F0F0F0F0F)) | ((pTruth[1] & ABC_CONST(0x0F0F0F0F0F0F0F0F)) <<  4) );
+        pStore[3] += Kit_WordCountOnes_64bit( (pTruth[0] & ABC_CONST(0x00FF00FF00FF00FF)) | ((pTruth[1] & ABC_CONST(0x00FF00FF00FF00FF)) <<  8) );
+        pStore[4] += Kit_WordCountOnes_64bit( (pTruth[0] & ABC_CONST(0x0000FFFF0000FFFF)) | ((pTruth[1] & ABC_CONST(0x0000FFFF0000FFFF)) <<  16) );
+        pStore[5] += Kit_WordCountOnes_64bit( (pTruth[0] & ABC_CONST(0x00000000FFFFFFFF)) | ((pTruth[1] & ABC_CONST(0x00000000FFFFFFFF)) <<  32) );  
+        pTruth += 2;
+    }
+}
+
+void Kit_TruthChangePhase_64bit( word * pInOut, int nVars, int iVar )
+{
+    int nWords = Kit_TruthWordNum_64bit( nVars );
+    int i, Step,SizeOfBlock;
+    word Temp[512];
+    
+    assert( iVar < nVars );
+    if(iVar<=5)
+    {
+        for ( i = 0; i < nWords; i++ )
+            pInOut[i] = ((pInOut[i] & mask0[iVar]) << (1<<(iVar))) | ((pInOut[i] & ~mask0[iVar]) >> (1<<(iVar)));
+    }
+    else
+    {
+        Step = (1 << (iVar - 6));
+        SizeOfBlock = sizeof(word)*Step;
+        for ( i = 0; i < nWords; i += 2*Step )
+        {   
+            memcpy(Temp,pInOut,SizeOfBlock);
+            memcpy(pInOut,pInOut+Step,SizeOfBlock);
+            memcpy(pInOut+Step,Temp,SizeOfBlock);
+            //          Temp = pInOut[i];
+            //          pInOut[i] = pInOut[Step+i];
+            //          pInOut[Step+i] = Temp;          
+            pInOut += 2*Step;
+        }
+    }
+    
+}
+
+void Kit_TruthNot_64bit(word * pIn, int nVars )
+{
+    int w;
+    for ( w = Kit_TruthWordNum_64bit(nVars)-1; w >= 0; w-- )
+        pIn[w] = ~pIn[w];
+}
+void Kit_TruthCopy_64bit( word * pOut, word * pIn, int nVars )
+{ 
+    memcpy(pOut,pIn,Kit_TruthWordNum_64bit(nVars)*sizeof(word));
+}
+
+void Kit_TruthSwapAdjacentVars_64bit( word * pInOut, int nVars, int iVar )
+{
+    int i, Step, Shift, SizeOfBlock;                   //
+    word temp[256];                   // to make only pInOut possible
+    static word PMasks[5][3] = {
+        { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) },
+        { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) },
+        { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) },
+        { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) },
+        { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) }
+    };
+    int nWords = Kit_TruthWordNum_64bit( nVars ); 
+    
+    assert( iVar < nVars - 1 );
+    if ( iVar < 5 )
+    {
+        Shift = (1 << iVar);
+        for ( i = 0; i < nWords; i++ )
+            pInOut[i] = (pInOut[i] & PMasks[iVar][0]) | ((pInOut[i] & PMasks[iVar][1]) << Shift) | ((pInOut[i] & PMasks[iVar][2]) >> Shift);
+    }
+    else if ( iVar > 5 )
+    {
+        Step = 1 << (iVar - 6);
+        SizeOfBlock = sizeof(word)*Step;
+        pInOut += 2*Step;
+        for(i=2*Step; i<nWords; i+=4*Step)
+        {           
+            memcpy(temp,pInOut-Step,SizeOfBlock);
+            memcpy(pInOut-Step,pInOut,SizeOfBlock);
+            memcpy(pInOut,temp,SizeOfBlock);
+            pInOut += 4*Step;
+        }
+    }
+    else // if ( iVar == 5 )
+    {
+        for ( i = 0; i < nWords; i += 2 )
+        {
+            temp[0] = pInOut[i+1] << 32;
+            pInOut[i+1] ^= (temp[0] ^ pInOut[i]) >> 32;
+            pInOut[i] = (pInOut[i] & 0x00000000FFFFFFFF) | temp[0];
+            
+        }
+    }
+}
+
+unsigned  Kit_TruthSemiCanonicize_Yasha( word* pInOut, int nVars, char * pCanonPerm )
+{
+    int pStore[16];
+    int nWords = Kit_TruthWordNum_64bit( nVars );
+    int i, Temp, fChange, nOnes;
+    unsigned  uCanonPhase=0;
+    assert( nVars <= 16 );
+    
+    nOnes = Kit_TruthCountOnes_64bit(pInOut, nVars);
+    
+    if ( (nOnes > nWords * 32) )
+    {
+        uCanonPhase |= (1 << nVars);
+        Kit_TruthNot_64bit( pInOut, nVars );
+        nOnes = nWords*64 - nOnes;
+    }
+    
+    // collect the minterm counts
+    Kit_TruthCountOnesInCofs_64bit( pInOut, nVars, pStore );
+    
+    // canonicize phase
+    for ( i = 0; i < nVars; i++ )
+    {
+        if ( pStore[i] >= nOnes-pStore[i])
+            continue;
+        uCanonPhase |= (1 << i);
+        pStore[i] = nOnes-pStore[i]; 
+        Kit_TruthChangePhase_64bit( pInOut, nVars, i );
+    }  
+    
+    do {
+        fChange = 0;
+        for ( i = 0; i < nVars-1; i++ )
+        {
+            if ( pStore[i] <= pStore[i+1] )
+                continue;            
+            fChange = 1;
+            
+            Temp = pCanonPerm[i];
+            pCanonPerm[i] = pCanonPerm[i+1];
+            pCanonPerm[i+1] = Temp;
+            
+            Temp = pStore[i];
+            pStore[i] = pStore[i+1];
+            pStore[i+1] = Temp;
+            
+            // if the polarity of variables is different, swap them
+            if ( ((uCanonPhase & (1 << i)) > 0) != ((uCanonPhase & (1 << (i+1))) > 0) )
+            {
+                uCanonPhase ^= (1 << i);
+                uCanonPhase ^= (1 << (i+1));
+            }
+            
+            Kit_TruthSwapAdjacentVars_64bit( pInOut, nVars, i );            
+        }
+    } while ( fChange );
+    return uCanonPhase;
+}
+
+unsigned  Kit_TruthSemiCanonicize_Yasha1( word* pInOut, int nVars, char * pCanonPerm, int * pStore )
+{
+    int nWords = Kit_TruthWordNum_64bit( nVars );
+    int i, fChange, nOnes;
+    int Temp;
+    unsigned  uCanonPhase=0;
+    assert( nVars <= 16 );
+    
+    nOnes = Kit_TruthCountOnes_64bit(pInOut, nVars);
+    if ( nOnes == nWords * 32 )
+        uCanonPhase |= (1 << (nVars+2));
+    
+    else if ( (nOnes > nWords * 32) )
+    {
+        uCanonPhase |= (1 << nVars);
+        Kit_TruthNot_64bit( pInOut, nVars );
+        nOnes = nWords*64 - nOnes;
+    }
+    
+    // collect the minterm counts
+    Kit_TruthCountOnesInCofs_64bit( pInOut, nVars, pStore );
+    
+    // canonicize phase
+    for ( i = 0; i < nVars; i++ )
+    {
+        if (  2*pStore[i]  == nOnes)
+        {
+            uCanonPhase |= (1 << (nVars+1));
+            continue;
+        }
+        if ( pStore[i] > nOnes-pStore[i])
+            continue;
+        uCanonPhase |= (1 << i);
+        pStore[i] = nOnes-pStore[i]; 
+        Kit_TruthChangePhase_64bit( pInOut, nVars, i );
+    }  
+    
+    do {
+        fChange = 0;
+        for ( i = 0; i < nVars-1; i++ )
+        {
+            if ( pStore[i] <= pStore[i+1] )
+                continue;            
+            fChange = 1;
+            
+            Temp = pCanonPerm[i];
+            pCanonPerm[i] = pCanonPerm[i+1];
+            pCanonPerm[i+1] = Temp;
+            
+            Temp = pStore[i];
+            pStore[i] = pStore[i+1];
+            pStore[i+1] = Temp;
+            
+            // if the polarity of variables is different, swap them
+            if ( ((uCanonPhase & (1 << i)) > 0) != ((uCanonPhase & (1 << (i+1))) > 0) )
+            {
+                uCanonPhase ^= (1 << i);
+                uCanonPhase ^= (1 << (i+1));
+            }
+            
+            Kit_TruthSwapAdjacentVars_64bit( pInOut, nVars, i );            
+        }
+    } while ( fChange );
+    return uCanonPhase;
+}
+
+
+// unsigned  Kit_TruthSemiCanonicize_Yasha_simple( word* pInOut, int nVars, char * pCanonPerm )
+// {
+//     unsigned uCanonPhase = 0;
+//     int pStore[16];
+//     int nWords = Kit_TruthWordNum_64bit( nVars );
+//     int i, Temp, fChange, nOnes; 
+//  assert( nVars <= 16 );
+//  
+//     nOnes = Kit_TruthCountOnes_64bit(pInOut, nVars);
+//  
+//     if ( (nOnes > nWords * 32) )
+//     { 
+//         Kit_TruthNot_64bit( pInOut, nVars );
+//      nOnes = nWords*64 - nOnes;
+//     }
+//  
+//     // collect the minterm counts
+//     Kit_TruthCountOnesInCofs_64bit( pInOut, nVars, pStore );
+//  
+//     // canonicize phase
+//     for ( i = 0; i < nVars; i++ )
+//     {
+//         if ( pStore[i] >= nOnes-pStore[i])
+//             continue;        
+//         pStore[i] = nOnes-pStore[i]; 
+//         Kit_TruthChangePhase_64bit( pInOut, nVars, i );
+//     }  
+//  
+//     do {
+//         fChange = 0;
+//         for ( i = 0; i < nVars-1; i++ )
+//         {
+//             if ( pStore[i] <= pStore[i+1] )
+//                 continue;            
+//             fChange = 1;         
+//          
+//             Temp = pStore[i];
+//             pStore[i] = pStore[i+1];
+//             pStore[i+1] = Temp;
+//          
+//             Kit_TruthSwapAdjacentVars_64bit( pInOut, nVars, i );             
+//         }
+//     } while ( fChange ); 
+//     return uCanonPhase;
+// }
+
+void  Kit_TruthSemiCanonicize_Yasha_simple( word* pInOut, int nVars, int * pStore )
+{
+    int nWords = Kit_TruthWordNum_64bit( nVars );
+    int i, Temp, fChange, nOnes; 
+    assert( nVars <= 16 );
+    
+    nOnes = Kit_TruthCountOnes_64bit(pInOut, nVars);
+    
+    if ( (nOnes > nWords * 32) )
+    { 
+        Kit_TruthNot_64bit( pInOut, nVars );
+        nOnes = nWords*64 - nOnes;
+    }
+    
+    // collect the minterm counts
+    Kit_TruthCountOnesInCofs_64bit( pInOut, nVars, pStore );
+    
+    // canonicize phase
+    for ( i = 0; i < nVars; i++ )
+    {
+        if ( pStore[i] >= nOnes-pStore[i])
+            continue;        
+        pStore[i] = nOnes-pStore[i]; 
+        Kit_TruthChangePhase_64bit( pInOut, nVars, i );
+    }  
+    
+    do {
+        fChange = 0;
+        for ( i = 0; i < nVars-1; i++ )
+        {
+            if ( pStore[i] <= pStore[i+1] )
+                continue;            
+            fChange = 1;            
+            
+            Temp = pStore[i];
+            pStore[i] = pStore[i+1];
+            pStore[i+1] = Temp;
+            
+            Kit_TruthSwapAdjacentVars_64bit( pInOut, nVars, i );            
+        }
+    } while ( fChange ); 
+}
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/bool/lucky/luckySwapIJ.c b/abc-build/src/bool/lucky/luckySwapIJ.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/lucky/luckySwapIJ.c
@@ -0,0 +1,102 @@
+/**CFile****************************************************************
+
+  FileName    [luckySwapIJ.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Semi-canonical form computation package.]
+
+  Synopsis    [just for support of swap_ij() function]
+
+  Author      [Jake]
+
+  Date        [Started - September 2012]
+
+***********************************************************************/
+
+#include "luckyInt.h"
+
+
+ABC_NAMESPACE_IMPL_START
+
+
+void swap_ij_case1( word* f,int totalVars, int i, int j)
+{
+    int e,wordsNumber,n,shift;
+    word maskArray[45]=
+    {   ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) ,ABC_CONST(0xA5A5A5A5A5A5A5A5), ABC_CONST(0x0A0A0A0A0A0A0A0A), ABC_CONST(0x5050505050505050),
+        ABC_CONST(0xAA55AA55AA55AA55), ABC_CONST(0x00AA00AA00AA00AA), ABC_CONST(0x5500550055005500) ,ABC_CONST(0xAAAA5555AAAA5555), ABC_CONST(0x0000AAAA0000AAAA), ABC_CONST(0x5555000055550000),
+        ABC_CONST(0xAAAAAAAA55555555), ABC_CONST(0x00000000AAAAAAAA), ABC_CONST(0x5555555500000000) ,ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030),
+        ABC_CONST(0xCC33CC33CC33CC33), ABC_CONST(0x00CC00CC00CC00CC), ABC_CONST(0x3300330033003300) ,ABC_CONST(0xCCCC3333CCCC3333), ABC_CONST(0x0000CCCC0000CCCC), ABC_CONST(0x3333000033330000),
+        ABC_CONST(0xCCCCCCCC33333333), ABC_CONST(0x00000000CCCCCCCC), ABC_CONST(0x3333333300000000) ,ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00),
+        ABC_CONST(0xF0F00F0FF0F00F0F), ABC_CONST(0x0000F0F00000F0F0), ABC_CONST(0x0F0F00000F0F0000) ,ABC_CONST(0xF0F0F0F00F0F0F0F), ABC_CONST(0x00000000F0F0F0F0), ABC_CONST(0x0F0F0F0F00000000),
+        ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) ,ABC_CONST(0xFF00FF0000FF00FF), ABC_CONST(0x00000000FF00FF00), ABC_CONST(0x00FF00FF00000000),
+        ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000)
+    };
+    e = 3*((9*i - i*i -2)/2 + j);          //  Exact formula for index in maskArray
+    wordsNumber = Kit_TruthWordNum_64bit(totalVars);
+    shift = (1<<j)-(1<<i);
+    for(n = 0; n < wordsNumber; n++)
+        f[n] = (f[n]&maskArray[e])+((f[n]&(maskArray[e+1]))<< shift)+((f[n]&(maskArray[e+2]))>> shift);
+}
+//  "width" - how many "Words" in a row have "1s" (or "0s")in position "i"
+//   wi - width of i
+//   wj - width of j
+//   wwi = 2*wi; wwj = 2*wj;
+
+void swap_ij_case2( word* f,int totalVars, int i, int j)
+{
+    word mask[] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0),
+                    ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) };
+    word temp;
+    int x,y,wj;
+    int WORDS_IN_TT = Kit_TruthWordNum_64bit(totalVars);
+    //  int forShift = ((Word)1)<<i;
+    int forShift = (1<<i);
+    wj = 1 << (j - 6);
+    x = 0;
+    y = wj;
+    for(y=wj; y<WORDS_IN_TT;y+=2*wj)
+        for(x=y-wj; x < y; x++)
+        {
+            temp = f[x+wj];
+            f[x+wj] = ((f[x+wj])&(mask[i])) + (((f[x]) & (mask[i])) >> forShift);
+            f[x] = ((f[x])&(~mask[i])) + ((temp&(~mask[i])) << forShift);
+        }
+}
+
+void swap_ij_case3( word* f,int totalVars, int i, int j)
+{
+    int x,y,wwi,wwj,shift;
+    int WORDS_IN_TT;
+    int SizeOfBlock;
+    word* temp;
+    wwi = 1 << (i - 5);
+    wwj = 1 << (j - 5);
+    shift = (wwj - wwi)/2;
+    WORDS_IN_TT = Kit_TruthWordNum_64bit(totalVars);
+    SizeOfBlock = sizeof(word)*wwi/2;
+    temp = (word *)malloc(SizeOfBlock);
+    for(y=wwj/2; y<WORDS_IN_TT; y+=wwj)
+        for(x=y-shift; x<y; x+=wwi)
+        {
+            memcpy(temp,&f[x],SizeOfBlock);
+            memcpy(&f[x],&f[x+shift],SizeOfBlock);
+            memcpy(&f[x+shift],temp,SizeOfBlock);
+        }
+}
+void swap_ij( word* f,int totalVars, int varI, int varJ)
+{
+    if (varI == varJ)
+        return;
+    else if(varI>varJ)
+        swap_ij( f,totalVars,varJ,varI);
+    else if((varI <= 4) && (varJ <= 5))
+        swap_ij_case1(f,totalVars, varI, varJ);
+    else if((varI <= 5) && (varJ > 5))
+        swap_ij_case2(f,totalVars, varI, varJ);
+    else if((varI > 5) && (varJ > 5))
+        swap_ij_case3(f,totalVars,varI,varJ);
+}
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/bool/lucky/module.make b/abc-build/src/bool/lucky/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/lucky/module.make
@@ -0,0 +1,7 @@
+SRC +=  src/bool/lucky/lucky.c \
+	src/bool/lucky/luckyFast16.c \
+	src/bool/lucky/luckyFast6.c \
+	src/bool/lucky/luckyRead.c \
+	src/bool/lucky/luckySimple.c \
+	src/bool/lucky/luckySwapIJ.c \
+	src/bool/lucky/luckySwap.c
diff --git a/abc-build/src/bool/rpo/literal.h b/abc-build/src/bool/rpo/literal.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/rpo/literal.h
@@ -0,0 +1,297 @@
+/**CFile****************************************************************
+
+  FileName    [literal.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [RPO]
+
+  Synopsis    [Literal structure]
+
+  Author      [Mayler G. A. Martins / Vinicius Callegaro]
+  
+  Affiliation [UFRGS]
+
+  Date        [Ver. 1.0. Started - May 08, 2013.]
+
+  Revision    [$Id: literal.h,v 1.00 2013/05/08 00:00:00 mgamartins Exp $]
+
+ ***********************************************************************/
+
+#ifndef ABC__bool__rpo__literal_h
+#define ABC__bool__rpo__literal_h
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "bool/kit/kit.h"
+#include "misc/vec/vec.h"
+#include "misc/util/abc_global.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+// associations
+typedef enum {
+    LIT_NONE = 0, // 0: unknown
+    LIT_AND, // 1: AND association
+    LIT_OR, // 2: OR association
+    LIT_XOR // 3: XOR association (not used yet)
+} Operator_t;
+
+
+typedef struct Literal_t_ Literal_t;
+
+struct Literal_t_ {
+    unsigned * transition;
+    unsigned * function;
+    Vec_Str_t * expression;
+};
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the positive transition]
+
+  Description [The inputs are a function, the number of variables and a variable index and the output is a function]
+               
+  SideEffects [Should this function be in kitTruth.c ?]
+
+  SeeAlso     []
+//
+***********************************************************************/
+
+static inline void Lit_TruthPositiveTransition( unsigned * pIn, unsigned * pOut, int nVars, int varIdx )
+{
+    unsigned * cof0 = ABC_ALLOC (unsigned, Kit_TruthWordNum(nVars) );
+    unsigned * cof1 = ABC_ALLOC (unsigned, Kit_TruthWordNum(nVars) );
+    unsigned * ncof0;
+    Kit_TruthCofactor0New(cof0, pIn,nVars,varIdx);
+    Kit_TruthCofactor1New(cof1, pIn,nVars,varIdx);
+    ncof0 = ABC_ALLOC (unsigned, Kit_TruthWordNum(nVars) );
+    Kit_TruthNot(ncof0,cof0,nVars);
+    Kit_TruthAnd(pOut,ncof0,cof1, nVars);
+    ABC_FREE(cof0);
+    ABC_FREE(ncof0);
+    ABC_FREE(cof1);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the negative transition]
+
+  Description [The inputs are a function, the number of variables and a variable index and the output is a function]
+               
+  SideEffects [Should this function be in kitTruth.c ?]
+
+  SeeAlso     []
+
+***********************************************************************/
+
+static inline void Lit_TruthNegativeTransition( unsigned * pIn, unsigned * pOut, int nVars, int varIdx )
+{
+    unsigned * cof0 = ABC_ALLOC (unsigned, Kit_TruthWordNum(nVars) );
+    unsigned * cof1 = ABC_ALLOC (unsigned, Kit_TruthWordNum(nVars) );
+    unsigned * ncof1;
+    Kit_TruthCofactor0New(cof0, pIn,nVars,varIdx);
+    Kit_TruthCofactor1New(cof1, pIn,nVars,varIdx);
+    ncof1 = ABC_ALLOC (unsigned, Kit_TruthWordNum(nVars) );
+    Kit_TruthNot(ncof1,cof1,nVars);
+    Kit_TruthAnd(pOut,ncof1,cof0,nVars);
+    ABC_FREE(cof0);
+    ABC_FREE(cof1);
+    ABC_FREE(ncof1);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Create a literal given a polarity ]
+
+  Description [The inputs are the function, index and its polarity and a the output is a literal]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+ ***********************************************************************/
+
+static inline Literal_t* Lit_Alloc(unsigned* pTruth, int nVars, int varIdx, char pol) {
+    unsigned * transition;
+    unsigned * function;
+    Vec_Str_t * exp;
+    Literal_t* lit;
+    assert(pol == '+' || pol == '-');
+    transition = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars));
+    if (pol == '+') {
+        Lit_TruthPositiveTransition(pTruth, transition, nVars, varIdx);
+    } else {
+        Lit_TruthNegativeTransition(pTruth, transition, nVars, varIdx);
+    }
+    if (!Kit_TruthIsConst0(transition,nVars)) {
+        function = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars));
+        Kit_TruthIthVar(function, nVars, varIdx);
+        //Abc_Print(-2, "Allocating function %X %d %c \n", *function, varIdx, pol);
+        exp = Vec_StrAlloc(5);
+        if (pol == '-') {
+            Kit_TruthNot(function, function, nVars);
+            Vec_StrPutC(exp, '!');
+        }
+        Vec_StrPutC(exp, (char)('a' + varIdx));
+        Vec_StrPutC(exp, '\0');
+        lit = ABC_ALLOC(Literal_t, 1);
+        lit->function = function;
+        lit->transition = transition;
+        lit->expression = exp;
+        return lit;
+    } else {
+        ABC_FREE(transition); // free the function.
+        return NULL;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Group 2 literals using AND or OR]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+ ***********************************************************************/
+
+static inline Literal_t* Lit_GroupLiterals(Literal_t* lit1, Literal_t* lit2, Operator_t op, int nVars) {
+    unsigned * newFunction = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars));
+    unsigned * newTransition = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars));
+    Vec_Str_t * newExp = Vec_StrAlloc(lit1->expression->nSize + lit2->expression->nSize + 3);
+    Literal_t* newLiteral;
+    char opChar = '%';
+    switch (op) {
+        case LIT_AND:
+        {
+            //Abc_Print(-2, "Grouping AND %X %X \n", *lit1->function, *lit2->function);
+            Kit_TruthAnd(newFunction, lit1->function, lit2->function, nVars);
+            opChar = '*';
+            break;
+        }
+        case LIT_OR:
+        {
+            //Abc_Print(-2, "Grouping OR %X %X \n", *lit1->function, *lit2->function);
+            Kit_TruthOr(newFunction, lit1->function, lit2->function, nVars);
+            opChar = '+';
+            break;
+        }
+        default:
+        {
+            Abc_Print(-2, "Lit_GroupLiterals with op not defined.");
+            //TODO Call ABC Abort
+        }
+    }
+
+    Kit_TruthOr(newTransition, lit1->transition, lit2->transition, nVars);
+    // create a new expression.
+    Vec_StrPutC(newExp, '(');
+    Vec_StrAppend(newExp, lit1->expression->pArray);
+    //Vec_StrPop(newExp); // pop the \0
+    Vec_StrPutC(newExp, opChar);
+    Vec_StrAppend(newExp, lit2->expression->pArray);
+    //Vec_StrPop(newExp); // pop the \0
+    Vec_StrPutC(newExp, ')');
+    Vec_StrPutC(newExp, '\0');
+
+    newLiteral = ABC_ALLOC(Literal_t, 1);
+    newLiteral->function = newFunction;
+    newLiteral->transition = newTransition;
+    newLiteral->expression = newExp;
+    return newLiteral;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Create a const literal ]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+ ***********************************************************************/
+
+static inline Literal_t* Lit_CreateLiteralConst(unsigned* pTruth, int nVars, int constant) {
+    Vec_Str_t * exp = Vec_StrAlloc(3);
+    Literal_t* lit;
+    Vec_StrPutC(exp, (char)('0' + constant));
+    Vec_StrPutC(exp, '\0');
+    lit = ABC_ALLOC(Literal_t, 1);
+    lit->expression = exp;
+    lit->function = pTruth;
+    lit->transition = pTruth; // wrong but no effect ###
+    return lit;
+}
+
+static inline Literal_t* Lit_Copy(Literal_t* lit, int nVars) {
+    Literal_t* newLit = ABC_ALLOC(Literal_t,1);
+    newLit->function = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars));
+    Kit_TruthCopy(newLit->function,lit->function,nVars);
+    newLit->transition = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars));
+    Kit_TruthCopy(newLit->transition,lit->transition,nVars);
+    newLit->expression = Vec_StrDup(lit->expression);
+//    Abc_Print(-2,"Copying: %s\n",newLit->expression->pArray); 
+    return newLit;
+}
+
+static inline void Lit_PrintTT(unsigned* tt, int nVars) {
+    int w;
+    for(w=nVars-1; w>=0; w--) {
+            Abc_Print(-2, "%08X", tt[w]);
+    }
+}
+
+static inline void Lit_PrintExp(Literal_t* lit) {
+    Abc_Print(-2, "%s", lit->expression->pArray);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Delete the literal ]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+ ***********************************************************************/
+
+static inline void Lit_Free(Literal_t * lit) {
+    if(lit == NULL) {
+        return;
+    }
+//    Abc_Print(-2,"Freeing: %s\n",lit->expression->pArray); 
+    ABC_FREE(lit->function);
+    ABC_FREE(lit->transition);
+    Vec_StrFree(lit->expression);
+    ABC_FREE(lit);
+}
+
+ABC_NAMESPACE_HEADER_END
+
+#endif	/* LITERAL_H */
+
diff --git a/abc-build/src/bool/rpo/module.make b/abc-build/src/bool/rpo/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/rpo/module.make
@@ -0,0 +1,1 @@
+SRC += src/bool/rpo/rpo.c
diff --git a/abc-build/src/bool/rpo/rpo.c b/abc-build/src/bool/rpo/rpo.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/rpo/rpo.c
@@ -0,0 +1,383 @@
+/**CFile****************************************************************
+
+  FileName    [rpo.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [RPO]
+
+  Synopsis    [Performs read polarity once factorization.]
+
+  Author      [Mayler G. A. Martins / Vinicius Callegaro]
+  
+  Affiliation [UFRGS]
+
+  Date        [Ver. 1.0. Started - May 08, 2013.]
+
+  Revision    [$Id: rpo.c,v 1.00 2013/05/08 00:00:00 mgamartins Exp $]
+
+ ***********************************************************************/
+
+#include <stdio.h>
+
+#include "literal.h"
+#include "rpo.h"
+#include "bool/kit/kit.h"
+#include "misc/util/abc_global.h"
+#include "misc/vec/vec.h"
+
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+
+typedef struct Rpo_Man_t_ Rpo_Man_t;
+
+struct Rpo_Man_t_ {
+    unsigned * target;
+    int nVars;
+
+    Literal_t ** literals;
+    int nLits;
+    int nLitsMax;
+
+    Rpo_LCI_Edge_t* lci;
+    int nLCIElems;
+
+    int thresholdMax;
+
+};
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Check if two literals are AND-grouped]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+ ***********************************************************************/
+int Rpo_CheckANDGroup(Literal_t* lit1, Literal_t* lit2, int nVars) {
+    unsigned* notLit1Func = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars));
+    unsigned* notLit2Func = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars));
+    unsigned* and1;
+    unsigned* and2;
+    int isZero;
+
+    Kit_TruthNot(notLit1Func, lit1->function, nVars);
+    Kit_TruthNot(notLit2Func, lit2->function, nVars);
+    and1 = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars));
+    and2 = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars));
+    Kit_TruthAnd(and1, lit1->transition, notLit2Func, nVars);
+    isZero = Kit_TruthIsConst0(and1, nVars);
+    if (isZero) {
+        Kit_TruthAnd(and2, lit2->transition, notLit1Func, nVars);
+        isZero = Kit_TruthIsConst0(and2, nVars);
+    }
+    ABC_FREE(notLit1Func);
+    ABC_FREE(notLit2Func);
+    ABC_FREE(and1);
+    ABC_FREE(and2);
+    return isZero;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check if two literals are AND-grouped]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+ ***********************************************************************/
+int Rpo_CheckORGroup(Literal_t* lit1, Literal_t* lit2, int nVars) {
+    unsigned* and1 = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars));
+    unsigned* and2 = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars));
+    int isZero;
+    Kit_TruthAnd(and1, lit1->transition, lit2->function, nVars);
+    isZero = Kit_TruthIsConst0(and1, nVars);
+    if (isZero) {
+        Kit_TruthAnd(and2, lit2->transition, lit1->function, nVars);
+        isZero = Kit_TruthIsConst0(and2, nVars);
+    }
+    ABC_FREE(and1);
+    ABC_FREE(and2);
+    return isZero;
+}
+
+Rpo_LCI_Edge_t* Rpo_CreateEdge(Operator_t op, int i, int j, int* vertexDegree) {
+    Rpo_LCI_Edge_t* edge = ABC_ALLOC(Rpo_LCI_Edge_t, 1);
+    edge->connectionType = op;
+    edge->idx1 = i;
+    edge->idx2 = j;
+    edge->visited = 0;
+    vertexDegree[i]++;
+    vertexDegree[j]++;
+    return edge;
+}
+
+int Rpo_computeMinEdgeCost(Rpo_LCI_Edge_t** edges, int edgeCount, int* vertexDegree) {
+    int minCostIndex = -1;
+    int minVertexIndex = -1;
+    unsigned int minCost = ~0;
+    Rpo_LCI_Edge_t* edge;
+    unsigned int edgeCost;
+    int minVertex;
+    int i;
+    for (i = 0; i < edgeCount; ++i) {
+        edge = edges[i];
+        if (!edge->visited) {
+            edgeCost = vertexDegree[edge->idx1] + vertexDegree[edge->idx2];
+            minVertex = (edge->idx1 < edge->idx2) ? edge->idx1 : edge->idx2;
+            if (edgeCost < minCost) {
+                minCost = edgeCost;
+                minCostIndex = i;
+                minVertexIndex = minVertex;
+            } else if ((edgeCost == minCost) && minVertex < minVertexIndex) {
+                minCost = edgeCost;
+                minCostIndex = i;
+                minVertexIndex = minVertex;
+            }
+        }
+    }
+    return minCostIndex;
+}
+
+void Rpo_PrintEdge(Rpo_LCI_Edge_t* edge) {
+    Abc_Print(-2, "Edge (%d,%d)/%d\n", edge->idx1, edge->idx2, edge->connectionType);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Test]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+ ***********************************************************************/
+Literal_t* Rpo_Factorize(unsigned* target, int nVars, int nThreshold, int verbose) {
+
+    int nLitCap = nVars * 2;
+    int nLit = 0;
+    int w;
+    Literal_t** vecLit;
+    Literal_t* lit;
+    Literal_t* result;
+    int thresholdCount = 0;
+
+    if (Kit_TruthIsConst0(target, nVars)) {
+        return Lit_CreateLiteralConst(target, nVars, 0);
+    } else if (Kit_TruthIsConst1(target, nVars)) {
+        return Lit_CreateLiteralConst(target, nVars, 1);
+    }
+
+    //    if (nThreshold == -1) {
+    //        nThreshold = nLitCap + nVars;
+    //    }
+    if (verbose) {
+        Abc_Print(-2, "Target: ");
+        Lit_PrintTT(target, nVars);
+        Abc_Print(-2, "\n");
+    }
+    vecLit = ABC_ALLOC(Literal_t*, nLitCap);
+
+    for (w = nVars - 1; w >= 0; w--) {
+        lit = Lit_Alloc(target, nVars, w, '+');
+        if (lit != NULL) {
+            vecLit[nLit] = lit;
+            nLit++;
+        }
+        lit = Lit_Alloc(target, nVars, w, '-');
+        if (lit != NULL) {
+            vecLit[nLit] = lit;
+            nLit++;
+        }
+    }
+    if (verbose) {
+        Abc_Print(-2, "Allocated %d literal clusters\n", nLit);
+    }
+
+    result = Rpo_Recursion(target, vecLit, nLit, nLit, nVars, &thresholdCount, nThreshold, verbose);
+
+    //freeing the memory
+    for (w = 0; w < nLit; ++w) {
+        Lit_Free(vecLit[w]);
+    }
+    ABC_FREE(vecLit);
+
+    return result;
+
+}
+
+Literal_t* Rpo_Recursion(unsigned* target, Literal_t** vecLit, int nLit, int nLitCount, int nVars, int* thresholdCount, int thresholdMax, int verbose) {
+    int i, j, k;
+    Literal_t* copyResult;
+    int* vertexDegree;
+    int v;
+    int edgeSize;
+    Rpo_LCI_Edge_t** edges;
+    int edgeCount = 0;
+    int isAnd;
+    int isOr;
+    Rpo_LCI_Edge_t* edge;
+    Literal_t* result = NULL;
+    int edgeIndex;
+    int minLitIndex;
+    int maxLitIndex;
+    Literal_t* oldLit1;
+    Literal_t* oldLit2;
+    Literal_t* newLit;
+
+    *thresholdCount = *thresholdCount + 1;
+    if (*thresholdCount == thresholdMax) {
+        return NULL;
+    }
+    if (verbose) {
+        Abc_Print(-2, "Entering recursion %d\n", *thresholdCount);
+    }
+    // verify if solution is the target or not
+    if (nLitCount == 1) {
+        if (verbose) {
+            Abc_Print(-2, "Checking solution: ");
+        }
+        for (k = 0; k < nLit; ++k) {
+            if (vecLit[k] != NULL) {
+                if (Kit_TruthIsEqual(target, vecLit[k]->function, nVars)) {
+                    copyResult = Lit_Copy(vecLit[k], nVars);
+                    if (verbose) {
+                        Abc_Print(-2, "FOUND!\n", thresholdCount);
+                    }
+                    thresholdCount = 0; //??
+                    return copyResult;
+                }
+            }
+        }
+        if (verbose) {
+            Abc_Print(-2, "FAILED!\n", thresholdCount);
+        }
+        return NULL;
+    }
+
+    vertexDegree = ABC_ALLOC(int, nLit);
+    //    if(verbose) {
+    //        Abc_Print(-2,"Allocating vertexDegree...\n");
+    //    }
+    for (v = 0; v < nLit; v++) {
+        vertexDegree[v] = 0;
+    }
+    // building edges
+    edgeSize = (nLit * (nLit - 1)) / 2;
+    edges = ABC_ALLOC(Rpo_LCI_Edge_t*, edgeSize);
+    if (verbose) {
+        Abc_Print(-2, "Creating Edges: \n");
+    }
+
+    for (i = 0; i < nLit; ++i) {
+        if (vecLit[i] == NULL) {
+            continue;
+        }
+        for (j = i; j < nLit; ++j) {
+            if (vecLit[j] == NULL) {
+                continue;
+            }
+            isAnd = Rpo_CheckANDGroup(vecLit[i], vecLit[j], nVars);
+            isOr = Rpo_CheckORGroup(vecLit[i], vecLit[j], nVars);
+            if (isAnd) {
+                if (verbose) {
+                    Abc_Print(-2, "Grouped: ");
+                    Lit_PrintExp(vecLit[j]);
+                    Abc_Print(-2, " AND ");
+                    Lit_PrintExp(vecLit[i]);
+                    Abc_Print(-2, "\n");
+                }
+                // add edge
+                edge = Rpo_CreateEdge(LIT_AND, i, j, vertexDegree);
+                edges[edgeCount++] = edge;
+            }
+            if (isOr) {
+                if (verbose) {
+                    Abc_Print(-2, "Grouped: ");
+                    Lit_PrintExp(vecLit[j]);
+                    Abc_Print(-2, " OR ");
+                    Lit_PrintExp(vecLit[i]);
+                    Abc_Print(-2, "\n");
+                }
+                // add edge
+                edge = Rpo_CreateEdge(LIT_OR, i, j, vertexDegree);
+                edges[edgeCount++] = edge;
+            }
+        }
+    }
+    if (verbose) {
+        Abc_Print(-2, "%d edges created.\n", edgeCount);
+    }
+
+
+    //traverse the edges, grouping new Literal Clusters
+    do {
+        edgeIndex = Rpo_computeMinEdgeCost(edges, edgeCount, vertexDegree);
+        if (edgeIndex < 0) {
+            if (verbose) {
+                Abc_Print(-2, "There is no edges unvisited... Exiting recursion.\n");
+                //exit(-1);
+            }
+            break;
+            //return NULL; // the graph does not have unvisited edges
+        }
+        edge = edges[edgeIndex];
+        edge->visited = 1;
+        //Rpo_PrintEdge(edge);
+        minLitIndex = (edge->idx1 < edge->idx2) ? edge->idx1 : edge->idx2;
+        maxLitIndex = (edge->idx1 > edge->idx2) ? edge->idx1 : edge->idx2;
+        oldLit1 = vecLit[minLitIndex];
+        oldLit2 = vecLit[maxLitIndex];
+        newLit = Lit_GroupLiterals(oldLit1, oldLit2, (Operator_t)edge->connectionType, nVars);
+        vecLit[minLitIndex] = newLit;
+        vecLit[maxLitIndex] = NULL;
+
+        if (verbose) {
+            Abc_Print(-2, "New Literal Cluster found: ");
+            Lit_PrintExp(newLit);
+            Abc_Print(-2, " -> ");
+            Lit_PrintTT(newLit->function, nVars);
+            Abc_Print(-2, "\n");
+        }
+        result = Rpo_Recursion(target, vecLit, nLit, (nLitCount - 1), nVars, thresholdCount, thresholdMax, verbose);
+        //independent of result, free the newLit and restore the vector of Literal Clusters
+        Lit_Free(newLit);
+        vecLit[minLitIndex] = oldLit1;
+        vecLit[maxLitIndex] = oldLit2;
+        if (*thresholdCount == thresholdMax) {
+            break;
+        }
+    } while (result == NULL);
+    //freeing memory
+    //    if(verbose) {
+    //        Abc_Print(-2,"Freeing vertexDegree...\n");
+    //    }
+    ABC_FREE(vertexDegree);
+    for (i = 0; i < edgeCount; ++i) {
+        //Abc_Print(-2, "%p ", edges[i]);
+        ABC_FREE(edges[i]);
+    }
+    ABC_FREE(edges);
+    return result;
+}
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/bool/rpo/rpo.h b/abc-build/src/bool/rpo/rpo.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/rpo/rpo.h
@@ -0,0 +1,58 @@
+/**CFile****************************************************************
+
+  FileName    [rpo.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [RPO]
+
+  Synopsis    [Rpo Header]
+
+  Author      [Mayler G. A. Martins / Vinicius Callegaro]
+  
+  Affiliation [UFRGS]
+
+  Date        [Ver. 1.0. Started - May 08, 2013.]
+
+  Revision    [$Id: rpo.h,v 1.00 2013/05/08 00:00:00 mgamartins Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__bool__rpo__rpo_h
+#define ABC__bool__rpo__rpo_h
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "literal.h"
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Rpo_LCI_Edge_t_ Rpo_LCI_Edge_t;
+
+struct Rpo_LCI_Edge_t_ {
+    unsigned long visited : 1;
+    unsigned long connectionType : 2;
+    unsigned long reserved : 1;
+    unsigned long idx1 : 30;
+    unsigned long idx2 : 30;
+};
+
+void Rpo_PrintEdge(Rpo_LCI_Edge_t* edge);
+int Rpo_CheckANDGroup(Literal_t* lit1, Literal_t* lit2, int nVars);
+int Rpo_CheckORGroup(Literal_t* lit1, Literal_t* lit2, int nVars);
+Literal_t* Rpo_Factorize(unsigned* target, int nVars, int nThreshold, int verbose);
+Literal_t* Rpo_Recursion(unsigned* target, Literal_t** vecLit, int nLit, int nLitCount, int nVars, int* thresholdCount, int thresholdMax, int verbose);
+Rpo_LCI_Edge_t* Rpo_CreateEdge(Operator_t op, int i, int j, int* vertexDegree);
+int Rpo_computeMinEdgeCost(Rpo_LCI_Edge_t** edges, int edgeCount, int* vertexDegree);
+
+ABC_NAMESPACE_HEADER_END
+        
+#endif
+
+  
diff --git a/abc-build/src/bool/rsb/module.make b/abc-build/src/bool/rsb/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/rsb/module.make
@@ -0,0 +1,2 @@
+SRC +=	src/bool/rsb/rsbDec6.c \
+	src/bool/rsb/rsbMan.c
diff --git a/abc-build/src/bool/rsb/rsb.h b/abc-build/src/bool/rsb/rsb.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/rsb/rsb.h
@@ -0,0 +1,65 @@
+/**CFile****************************************************************
+
+  FileName    [rsb.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Truth-table based resubstitution.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rsb.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__bool_Rsb_h
+#define ABC__bool_Rsb_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Rsb_Man_t_ Rsb_Man_t;
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== rsbMan.c ==========================================================*/
+extern Rsb_Man_t *  Rsb_ManAlloc( int nLeafMax, int nDivMax, int nDecMax, int fVerbose );
+extern void         Rsb_ManFree( Rsb_Man_t * p );
+extern Vec_Int_t *  Rsb_ManGetFanins( Rsb_Man_t * p );
+extern Vec_Int_t *  Rsb_ManGetFaninsOld( Rsb_Man_t * p );
+/*=== rsbDec6.c ==========================================================*/
+extern int          Rsb_ManPerformResub6( Rsb_Man_t * p, int nVars, word uTruth, Vec_Wrd_t * vDivTruths, word * puTruth0, word * puTruth1, int fVerbose );
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/bool/rsb/rsbDec6.c b/abc-build/src/bool/rsb/rsbDec6.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/rsb/rsbDec6.c
@@ -0,0 +1,770 @@
+/**CFile****************************************************************
+
+  FileName    [rsbDec6.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Truth-table-based resubstitution.]
+
+  Synopsis    [Implementation of the algorithm.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rsbDec6.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rsbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Rsb_DecTry0( word c ) 
+{
+    return (unsigned)(c != 0);
+}
+static inline unsigned Rsb_DecTry1( word c, word f1 ) 
+{
+    return (Rsb_DecTry0(c&f1) << 1) | Rsb_DecTry0(c&~f1);
+}
+static inline unsigned Rsb_DecTry2( word c, word f1, word f2 ) 
+{
+    return (Rsb_DecTry1(c&f2, f1) << 2) | Rsb_DecTry1(c&~f2, f1);
+}
+static inline unsigned Rsb_DecTry3( word c, word f1, word f2, word f3 ) 
+{
+    return (Rsb_DecTry2(c&f3, f1, f2) << 4) | Rsb_DecTry2(c&~f3, f1, f2);
+}
+static inline unsigned Rsb_DecTry4( word c, word f1, word f2, word f3, word f4 ) 
+{
+    return (Rsb_DecTry3(c&f4, f1, f2, f3) << 8) | Rsb_DecTry3(c&~f4, f1, f2, f3);
+}
+static inline unsigned Rsb_DecTry5( word c, word f1, word f2, word f3, word f4, word f5 ) 
+{
+    return (Rsb_DecTry4(c&f5, f1, f2, f3, f4) << 16) | Rsb_DecTry4(c&~f5, f1, f2, f3, f4);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Rsb_DecTryCex( word * g, int iCexA, int iCexB ) 
+{
+    return Abc_TtGetBit(g, iCexA) == Abc_TtGetBit(g, iCexB);
+}
+static inline void Rsb_DecVerifyCex( word * f, word ** g, int nGs, int iCexA, int iCexB ) 
+{
+    int i;
+    // f distinquished it
+    if ( Rsb_DecTryCex( f, iCexA, iCexB ) )
+        printf( "Verification of CEX has failed: f(A) == f(B)!!!\n" );
+    // g do not distinguish it
+    for ( i = 0; i < nGs; i++ )
+        if ( !Rsb_DecTryCex( g[i], iCexA, iCexB ) )
+            printf( "Verification of CEX has failed: g[%d](A) != g[%d](B)!!!\n", i, i );
+}
+static inline void Rsb_DecRecordCex( word ** g, int nGs, int iCexA, int iCexB, word * pCexes, int nCexes ) 
+{
+    int i;
+    assert( nCexes < 64 );
+    for ( i = 0; i < nGs; i++ )
+        if ( Rsb_DecTryCex(g[i], iCexA, iCexB) )
+            Abc_TtSetBit( pCexes + i, nCexes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks decomposability of f with divisors g.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Rsb_DecCofactor( word ** g, int nGs, int w, int iMint ) 
+{
+    int i;
+    word Cof = ~(word)0;
+    for ( i = 0; i < nGs; i++ )
+        Cof &=  ((iMint >> i) & 1) ? g[i][w] : ~g[i][w];
+    return Cof;
+}
+unsigned Rsb_DecCheck( int nVars, word * f, word ** g, int nGs, unsigned * pPat, int * pCexA, int * pCexB ) 
+{
+    word CofA, CofB;
+    int nWords = Abc_TtWordNum( nVars );
+    int w, k, iMint, iShift = ( 1 << nGs );
+    unsigned uMask = (~(unsigned)0) >> (32-iShift);
+    unsigned uTotal = 0;
+    assert( nGs > 0 && nGs < 5 );
+    for ( w = 0; w < nWords; w++ )
+    {
+        // generate decomposition pattern
+        if ( nGs == 1 )
+            pPat[w] = Rsb_DecTry2( ~(word)0, g[0][w], f[w] );
+        else if ( nGs == 2 )
+            pPat[w] = Rsb_DecTry3( ~(word)0, g[0][w], g[1][w], f[w] );
+        else if ( nGs == 3 )
+            pPat[w] = Rsb_DecTry4( ~(word)0, g[0][w], g[1][w], g[2][w], f[w] );
+        else if ( nGs == 4 )
+            pPat[w] = Rsb_DecTry5( ~(word)0, g[0][w], g[1][w], g[2][w], g[3][w], f[w] );
+        // check if it is consistent
+        iMint = Abc_Tt6FirstBit( (pPat[w] >> iShift) & pPat[w] & uMask );
+        if ( iMint >= 0 )
+        {   // generate a cex
+            CofA = Rsb_DecCofactor( g, nGs, w, iMint );
+            assert( (~f[w] & CofA) && (f[w] & CofA) );
+            *pCexA = w * 64 + Abc_Tt6FirstBit( ~f[w] & CofA );
+            *pCexB = w * 64 + Abc_Tt6FirstBit(  f[w] & CofA );
+            return 0;
+        }
+        uTotal |= pPat[w];
+        if ( w == 0 )
+            continue;
+        // check if it is consistent with other patterns seen so far
+        iMint = Abc_Tt6FirstBit( (uTotal >> iShift) & uTotal & uMask );
+        if ( iMint == -1 )
+            continue;
+        // find an overlap and generate a cex
+        for ( k = 0; k < w; k++ )
+        {
+            iMint = Abc_Tt6FirstBit( ((pPat[k] | pPat[w]) >> iShift) & (pPat[k] | pPat[w]) & uMask );
+            if ( iMint == -1 )
+                continue;
+            CofA = Rsb_DecCofactor( g, nGs, k, iMint );
+            CofB = Rsb_DecCofactor( g, nGs, w, iMint );
+            if ( (~f[k] & CofA) && (f[w] & CofB) )
+            {
+                *pCexA = k * 64 + Abc_Tt6FirstBit( ~f[k] & CofA );
+                *pCexB = w * 64 + Abc_Tt6FirstBit(  f[w] & CofB );
+            }
+            else
+            {
+                assert( (f[k] & CofA) && (~f[w] & CofB) );
+                *pCexA = k * 64 + Abc_Tt6FirstBit(  f[k] & CofA );
+                *pCexB = w * 64 + Abc_Tt6FirstBit( ~f[w] & CofB );
+            }
+            return 0;
+        }
+    }
+    return uTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rsb_DecPrintTable( word * pCexes, int nGs, int nGsAll, Vec_Int_t * vTries ) 
+{
+    int pCands[16], nCands;
+    int i, c, Cand, iStart = 0;
+    if ( Vec_IntSize(vTries) == 0 )
+        return;
+
+//    printf( "\n" );
+    for ( i = 0; i < 4; i++ )
+        printf( "    " );
+    printf( "  " );
+    for ( i = 0; i < nGs; i++ )
+        printf( "%d", (i % 100) / 10 );
+    printf( "|" );
+    for ( ; i < nGsAll; i++ )
+        printf( "%d", (i % 100) / 10 );
+    printf( "\n" );
+
+    for ( i = 0; i < 4; i++ )
+        printf( "    " );
+    printf( "  " );
+    for ( i = 0; i < nGs; i++ )
+        printf( "%d", i % 10 );
+    printf( "|" );
+    for ( ; i < nGsAll; i++ )
+        printf( "%d", i % 10 );
+    printf( "\n" );
+    printf( "\n" );
+
+    for ( c = 0; iStart < Vec_IntSize(vTries); c++ )
+    {
+        // collect candidates
+        for ( i = 0; i < 4; i++ )
+            pCands[i] = -1;
+        nCands = 0;
+        Vec_IntForEachEntryStart( vTries, Cand, i, iStart )
+            if ( Cand == -1 )
+            {
+                iStart = i + 1;
+                break;
+            }
+            else
+                pCands[nCands++] = Cand;
+        assert( nCands <= 4 );
+        // print them
+        for ( i = 0; i < 4; i++ )
+            if ( pCands[i] >= 0 )
+                printf( "%4d", pCands[i] );
+            else
+                printf( "    " );
+        // print the bit-string
+        printf( "  " );
+        for ( i = 0; i < nGs; i++ )
+            printf( "%c", Abc_TtGetBit( pCexes + i, c ) ? '.' : '+' );
+        printf( "|" );
+        for ( ; i < nGsAll; i++ )
+            printf( "%c", Abc_TtGetBit( pCexes + i, c ) ? '.' : '+' );
+        printf( "  %3d\n", c );
+    }
+    printf( "\n" );
+
+    // write the number of ones
+    for ( i = 0; i < 4; i++ )
+        printf( "    " );
+    printf( "  " );
+    for ( i = 0; i < nGs; i++ )
+        printf( "%d", Abc_TtCountOnes(pCexes[i]) / 10 );
+    printf( "|" );
+    for ( ; i < nGsAll; i++ )
+        printf( "%d", Abc_TtCountOnes(pCexes[i]) / 10 );
+    printf( "\n" );
+
+    for ( i = 0; i < 4; i++ )
+        printf( "    " );
+    printf( "  " );
+    for ( i = 0; i < nGs; i++ )
+        printf( "%d", Abc_TtCountOnes(pCexes[i]) % 10 );
+    printf( "|" );
+    for ( ; i < nGsAll; i++ )
+        printf( "%d", Abc_TtCountOnes(pCexes[i]) % 10 );
+    printf( "\n" );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Init ]
+
+  Description [Returns the numbers of the decomposition functions and 
+  the truth table of a function up to 4 variables.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rsb_DecInitCexes( int nVars, word * f, word ** g, int nGs, int nGsAll, word * pCexes, Vec_Int_t * vTries ) 
+{
+    int nWords = Abc_TtWordNum( nVars );
+    int ValueB = Abc_TtGetBit( f, 0 );
+    int ValueE = Abc_TtGetBit( f, 64*nWords-1 );
+    int iCexT0, iCexT1, iCexF0, iCexF1;
+
+    iCexT0 = ValueB  ? 0           : Abc_TtFindFirstBit( f, nVars );
+    iCexT1 = ValueE  ? 64*nWords-1 : Abc_TtFindLastBit( f, nVars );
+
+    iCexF0 = !ValueB ? 0           : Abc_TtFindFirstZero( f, nVars );
+    iCexF1 = !ValueE ? 64*nWords-1 : Abc_TtFindLastZero( f, nVars );
+
+    assert( !Rsb_DecTryCex( f, iCexT0, iCexF0 ) );
+    assert( !Rsb_DecTryCex( f, iCexT0, iCexF1 ) );
+    assert( !Rsb_DecTryCex( f, iCexT1, iCexF0 ) );
+    assert( !Rsb_DecTryCex( f, iCexT1, iCexF1 ) );
+
+    Rsb_DecRecordCex( g, nGsAll, iCexT0, iCexF0, pCexes, 0 );
+    Rsb_DecRecordCex( g, nGsAll, iCexT0, iCexF1, pCexes, 1 );
+    Rsb_DecRecordCex( g, nGsAll, iCexT1, iCexF0, pCexes, 2 );
+    Rsb_DecRecordCex( g, nGsAll, iCexT1, iCexF1, pCexes, 3 );
+
+    if ( vTries )
+    {
+    Vec_IntPush( vTries, -1 );
+    Vec_IntPush( vTries, -1 );
+    Vec_IntPush( vTries, -1 );
+    Vec_IntPush( vTries, -1 );
+    }
+    return 4;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds a setset of gs to decompose f.]
+
+  Description [Returns the numbers of the decomposition functions and 
+  the truth table of a function up to 4 variables.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Rsb_DecPerformInt( Rsb_Man_t * p, int nVars, word * f, word ** g, int nGs, int nGsAll, int fFindAll ) 
+{
+    word * pCexes = Vec_WrdArray(p->vCexes);
+    unsigned * pPat = (unsigned *)Vec_IntArray(p->vDecPats);
+    /*
+    The following filtering hueristic can be used:
+    after the first round (if there is more than 5 cexes, 
+    remove all the divisors, except fanins of the node
+    This should lead to a speadup without sacrifying quality.
+
+    Another idea is to precompute several counter-examples
+    like the first and last 0 and 1 mints of the function
+    which yields 4 cexes.
+    */
+
+    word * pDivs[16];
+    unsigned uTruth = 0;
+    int i, k, j, n, iCexA, iCexB, nCexes = 0;
+    memset( pCexes, 0, sizeof(word) * nGsAll );  
+    Vec_IntClear( p->vTries );
+    // populate the counter-examples with the three most obvious
+//    nCexes = Rsb_DecInitCexes( nVars, f, g, nGs, nGsAll, pCexes, vTries );
+    // start by checking each function
+    p->vFanins->nSize = 1;
+    for ( i = 0; i < nGs; i++ )
+    {
+        if ( pCexes[i] )
+            continue;
+        pDivs[0] = g[i];  p->vFanins->pArray[0] = i;
+        uTruth = Rsb_DecCheck( nVars, f, pDivs, Vec_IntSize(p->vFanins), pPat, &iCexA, &iCexB );
+        if ( uTruth )
+        {
+            if ( fFindAll )
+            {
+                uTruth = (unsigned)Abc_Tt6Stretch( (word)uTruth, 1 );
+                Kit_DsdPrintFromTruth( &uTruth, 1 ); printf( "   " );
+                Vec_IntPrint(p->vFanins);
+                continue;
+            }
+            else
+                return uTruth;
+        }
+        if ( nCexes == 64 )
+            return 0;
+        Rsb_DecVerifyCex( f, pDivs, Vec_IntSize(p->vFanins), iCexA, iCexB );
+        Rsb_DecRecordCex( g, nGsAll, iCexA, iCexB, pCexes, nCexes++ );
+        if ( !p->fVerbose )
+            continue;
+        Vec_IntPush( p->vTries, i );
+        Vec_IntPush( p->vTries, -1 );
+    }
+    if ( p->nDecMax == 1 )
+        return 0;
+    // continue by checking pairs
+    p->vFanins->nSize = 2;
+    for ( i = 1; i < nGs; i++ )
+    for ( k = 0; k < i; k++ )
+    {
+        if ( pCexes[i] & pCexes[k] )
+            continue;
+        pDivs[0] = g[i];  p->vFanins->pArray[0] = i;
+        pDivs[1] = g[k];  p->vFanins->pArray[1] = k;
+        uTruth = Rsb_DecCheck( nVars, f, pDivs, Vec_IntSize(p->vFanins), pPat, &iCexA, &iCexB );
+        if ( uTruth )
+        {
+            if ( fFindAll )
+            {
+                uTruth = (unsigned)Abc_Tt6Stretch( (word)uTruth, 2 );
+                Kit_DsdPrintFromTruth( &uTruth, 2 ); printf( "   " );
+                Vec_IntPrint(p->vFanins);
+                continue;
+            }
+            else
+                return uTruth;
+        }
+        if ( nCexes == 64 )
+            return 0;
+        Rsb_DecVerifyCex( f, pDivs, Vec_IntSize(p->vFanins), iCexA, iCexB );
+        Rsb_DecRecordCex( g, nGsAll, iCexA, iCexB, pCexes, nCexes++ );
+        if ( !p->fVerbose )
+            continue;
+        Vec_IntPush( p->vTries, i );
+        Vec_IntPush( p->vTries, k );
+        Vec_IntPush( p->vTries, -1 );
+    }
+    if ( p->nDecMax == 2 )
+        return 0;
+    // continue by checking triples
+    p->vFanins->nSize = 3;
+    for ( i = 2; i < nGs; i++ )
+    for ( k = 1; k < i; k++ )
+    for ( j = 0; j < k; j++ )
+    {
+        if ( pCexes[i] & pCexes[k] & pCexes[j] )
+            continue;
+        pDivs[0] = g[i];  p->vFanins->pArray[0] = i;
+        pDivs[1] = g[k];  p->vFanins->pArray[1] = k;
+        pDivs[2] = g[j];  p->vFanins->pArray[2] = j;
+        uTruth = Rsb_DecCheck( nVars, f, pDivs, Vec_IntSize(p->vFanins), pPat, &iCexA, &iCexB );
+        if ( uTruth )
+        {
+            if ( fFindAll )
+            {
+                uTruth = (unsigned)Abc_Tt6Stretch( (word)uTruth, 3 );
+                Kit_DsdPrintFromTruth( &uTruth, 3 ); printf( "   " );
+                Vec_IntPrint(p->vFanins);
+                continue;
+            }
+            else
+                return uTruth;
+        }
+        if ( nCexes == 64 )
+            return 0;
+        Rsb_DecVerifyCex( f, pDivs, Vec_IntSize(p->vFanins), iCexA, iCexB );
+        Rsb_DecRecordCex( g, nGsAll, iCexA, iCexB, pCexes, nCexes++ );
+        if ( !p->fVerbose )
+            continue;
+        Vec_IntPush( p->vTries, i );
+        Vec_IntPush( p->vTries, k );
+        Vec_IntPush( p->vTries, j );
+        Vec_IntPush( p->vTries, -1 );
+    }
+    if ( p->nDecMax == 3 )
+        return 0;
+    // continue by checking quadras
+    p->vFanins->nSize = 4;
+    for ( i = 3; i < nGs; i++ )
+    for ( k = 2; k < i; k++ )
+    for ( j = 1; j < k; j++ )
+    for ( n = 0; n < j; n++ )
+    {
+        if ( pCexes[i] & pCexes[k] & pCexes[j] & pCexes[n] )
+            continue;
+        pDivs[0] = g[i];  p->vFanins->pArray[0] = i;
+        pDivs[1] = g[k];  p->vFanins->pArray[1] = k;
+        pDivs[2] = g[j];  p->vFanins->pArray[2] = j;
+        pDivs[3] = g[n];  p->vFanins->pArray[3] = n;
+        uTruth = Rsb_DecCheck( nVars, f, pDivs, Vec_IntSize(p->vFanins), pPat, &iCexA, &iCexB );
+        if ( uTruth )
+        {
+            if ( fFindAll )
+            {
+                uTruth = (unsigned)Abc_Tt6Stretch( (word)uTruth, 4 );
+                Kit_DsdPrintFromTruth( &uTruth, 4 ); printf( "   " );
+                Vec_IntPrint(p->vFanins);
+                continue;
+            }
+            else
+                return uTruth;
+        }
+        if ( nCexes == 64 )
+            return 0;
+        Rsb_DecVerifyCex( f, pDivs, Vec_IntSize(p->vFanins), iCexA, iCexB );
+        Rsb_DecRecordCex( g, nGsAll, iCexA, iCexB, pCexes, nCexes++ );
+        if ( !p->fVerbose )
+            continue;
+        Vec_IntPush( p->vTries, i );
+        Vec_IntPush( p->vTries, k );
+        Vec_IntPush( p->vTries, j );
+        Vec_IntPush( p->vTries, n );
+        Vec_IntPush( p->vTries, -1 );
+    }
+//    printf( "%d ", nCexes );
+    if ( p->nDecMax == 4 )
+        return 0;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies 4-input decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rsb_DecPrintFunc( Rsb_Man_t * p, unsigned Truth4, word * f, word ** ppGs, int nGs, int nVarsAll )
+{
+    int nVars  =  Vec_IntSize(p->vFanins);
+    word Copy  =  Truth4;
+    word wOn   =  Abc_Tt6Stretch( Copy >> (1 << nVars), nVars );
+    word wOnDc = ~Abc_Tt6Stretch( Copy, nVars );
+    word wIsop =  Abc_Tt6Isop( wOn, wOnDc, nVars, NULL );
+    int i;
+
+    printf( "Offset : " );
+    Abc_TtPrintBinary( &Copy, nVars );  //printf( "\n" );
+    Copy >>= ((word)1 << nVars);
+    printf( "Onset  : " );
+    Abc_TtPrintBinary( &Copy, nVars );  //printf( "\n" );
+    printf( "Result : " );
+    Abc_TtPrintBinary( &wIsop, nVars ); //printf( "\n" );
+    Kit_DsdPrintFromTruth( (unsigned *)&wIsop, nVars );  printf( "\n" );
+
+    // print functions
+    printf( "Func   : " );
+    Abc_TtPrintBinary( f, nVarsAll );   //printf( "\n" );
+    Kit_DsdPrintFromTruth( (unsigned *)f, nVarsAll );    printf( "\n" );
+    for ( i = 0; i < nGs; i++ )
+    {
+        printf( "Div%3d : ", i );
+        Kit_DsdPrintFromTruth( (unsigned *)ppGs[i], nVarsAll );  printf( "\n" );
+    }
+    printf( "Solution : " );
+    for ( i = 0; i < Vec_IntSize(p->vFanins); i++ )
+        printf( "%d ", Vec_IntEntry(p->vFanins, i) );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies 4-input decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rsb_DecVerify( Rsb_Man_t * p, int nVars, word * f, word ** g, int nGs, unsigned Truth4, word * pTemp1, word * pTemp2 )
+{
+    word * pFanins[16];
+    int b, m, Num, nSuppSize;
+    int nWords = Abc_TtWordNum(nVars);
+    Truth4 >>= (1 << Vec_IntSize(p->vFanins));
+    Truth4 = (unsigned)Abc_Tt6Stretch( (word)Truth4, Vec_IntSize(p->vFanins) );
+//Kit_DsdPrintFromTruth( (unsigned *)&Truth4, Vec_IntSize(p->vFanins) );
+//printf( "\n" );
+//    nSuppSize = Rsb_Word6SupportSize( Truth4 );
+//    assert( nSuppSize == Vec_IntSize(p->vFanins) );
+    nSuppSize = Vec_IntSize(p->vFanins);
+    // collect the fanins
+    Vec_IntForEachEntry( p->vFanins, Num, b )
+    {
+        assert( Num < nGs );
+        pFanins[b] = g[Num];
+    }
+    // create the or of ands
+    Abc_TtClear( pTemp1, nWords );
+    for ( m = 0; m < (1<<nSuppSize); m++ )
+    {
+        if ( ((Truth4 >> m) & 1) == 0 )
+            continue;
+        Abc_TtFill( pTemp2, nWords );
+        for ( b = 0; b < nSuppSize; b++ )
+            if ( (m >> b) & 1 )
+                Abc_TtAnd( pTemp2, pTemp2, pFanins[b], nWords, 0 );
+            else
+                Abc_TtSharp( pTemp2, pTemp2, pFanins[b], nWords );
+        Abc_TtOr( pTemp1, pTemp1, pTemp2, nWords );
+    }
+    // check the function
+    if ( !Abc_TtEqual( pTemp1, f, nWords ) )
+        printf( "Verification failed.\n" );
+//    else
+//        printf( "Verification passed.\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds a setset of gs to decompose f.]
+
+  Description [Returns the numbers of the decomposition functions and 
+  the truth table of a function up to 4 variables.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Rsb_ManPerform( Rsb_Man_t * p, int nVars, word * f, word ** g, int nGs, int nGsAll, int fVerbose0 ) 
+{
+    word * pCexes = Vec_WrdArray(p->vCexes);
+    unsigned * pPat = (unsigned *)Vec_IntArray(p->vDecPats);
+    int fVerbose = 0;//(nGs > 40);
+    Vec_Int_t * vTries = NULL;
+    unsigned uTruth;
+
+    // verify original decomposition
+    if ( Vec_IntSize(p->vFaninsOld) && Vec_IntSize(p->vFaninsOld) <= 4 )
+    {
+        word * pDivs[8];
+        int i, Entry, iCexA, iCexB;
+        Vec_IntForEachEntry( p->vFaninsOld, Entry, i )
+            pDivs[i] = g[Entry];
+        uTruth = Rsb_DecCheck( nVars, f, pDivs, Vec_IntSize(p->vFaninsOld), pPat, &iCexA, &iCexB );
+//        assert( uTruth != 0 );
+        if ( fVerbose )
+        {
+            printf( "Verified orig decomp with %d vars {", Vec_IntSize(p->vFaninsOld) );
+            Vec_IntForEachEntry( p->vFaninsOld, Entry, i )
+                printf( " %d", Entry );
+            printf( " }\n" );
+        }
+        if ( uTruth )
+        {
+//            if ( fVerbose )
+//                Rsb_DecPrintFunc( p, uTruth );
+        }
+        else 
+        {
+            printf( "Verified orig decomp with %d vars {", Vec_IntSize(p->vFaninsOld) );
+            Vec_IntForEachEntry( p->vFaninsOld, Entry, i )
+                printf( " %d", Entry );
+            printf( " }\n" );
+            printf( "Verification FAILED.\n" );
+        }
+    }
+    // start tries
+if ( fVerbose )
+vTries = Vec_IntAlloc( 100 );
+    assert( nGs < nGsAll );
+    uTruth = Rsb_DecPerformInt( p, nVars, f, g, nGs, nGsAll, 0 );
+
+    if ( uTruth )
+    {
+        if ( fVerbose )
+        {
+            int i, Entry;
+            printf( "Found decomp with %d vars {", Vec_IntSize(p->vFanins) );
+            Vec_IntForEachEntry( p->vFanins, Entry, i )
+                printf( " %d", Entry );
+            printf( " }\n" );
+//            Rsb_DecPrintFunc( p, uTruth );
+//            Rsb_DecVerify( nVars, f, g, nGs, p->vFanins, uTruth, g[nGsAll], g[nGsAll+1] );
+        }
+    }
+    else 
+    {
+        Vec_IntShrink( p->vFanins, 0 );
+        if ( fVerbose )
+        printf( "Did not find decomposition with 4 variables.\n" );
+    }
+
+if ( fVerbose )
+Rsb_DecPrintTable( pCexes, nGs, nGsAll, vTries );
+if ( fVerbose )
+Vec_IntFree( vTries );
+    return uTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rsb_ManPerformResub6( Rsb_Man_t * p, int nVarsAll, word uTruth, Vec_Wrd_t * vDivTruths, word * puTruth0, word * puTruth1, int fVerbose )
+{
+    word * pGs[200];
+    unsigned uTruthRes;
+    int i, nVars, nGs = Vec_WrdSize(vDivTruths);
+    assert( nGs < 200 );
+    for ( i = 0; i < nGs; i++ )
+        pGs[i] = Vec_WrdEntryP(vDivTruths,i);
+    uTruthRes = Rsb_DecPerformInt( p, nVarsAll, &uTruth, pGs, nGs, nGs, 0 );
+    if ( uTruthRes == 0 )
+        return 0;
+
+    if ( fVerbose )
+        Rsb_DecPrintFunc( p, uTruthRes, &uTruth, pGs, nGs, nVarsAll );
+    if ( fVerbose )
+        Rsb_DecPrintTable( Vec_WrdArray(p->vCexes), nGs, nGs, p->vTries );
+
+    nVars = Vec_IntSize(p->vFanins);
+    *puTruth0 = Abc_Tt6Stretch( uTruthRes,                 nVars );
+    *puTruth1 = Abc_Tt6Stretch( uTruthRes >> (1 << nVars), nVars );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rsb_ManPerformResub6Test()
+{
+    Rsb_Man_t * p;
+    Vec_Wrd_t * vDivTruths;
+    int RetValue;
+    word a = s_Truths6[0];
+    word b = s_Truths6[1];
+    word c = s_Truths6[2];
+    word d = s_Truths6[3];
+    word e = s_Truths6[4];
+    word f = s_Truths6[5];
+    word ab = a & b;
+    word cd = c & d;
+    word ef = e & f;
+    word F = ab | cd | ef;
+    word uTruth0, uTruth1;
+
+    vDivTruths = Vec_WrdAlloc( 100 );
+    Vec_WrdPush( vDivTruths, a );
+    Vec_WrdPush( vDivTruths, b );
+    Vec_WrdPush( vDivTruths, c );
+    Vec_WrdPush( vDivTruths, d );
+    Vec_WrdPush( vDivTruths, e );
+    Vec_WrdPush( vDivTruths, f );
+    Vec_WrdPush( vDivTruths, ab );
+    Vec_WrdPush( vDivTruths, cd );
+    Vec_WrdPush( vDivTruths, ef );
+
+    p = Rsb_ManAlloc( 6, 64, 4, 1 );
+
+    RetValue = Rsb_ManPerformResub6( p, 6, F, vDivTruths, &uTruth0, &uTruth1, 1 );
+
+    Rsb_ManFree( p );
+    Vec_WrdFree( vDivTruths );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/bool/rsb/rsbInt.h b/abc-build/src/bool/rsb/rsbInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/rsb/rsbInt.h
@@ -0,0 +1,84 @@
+/**CFile****************************************************************
+
+  FileName    [rsbInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Truth-table based resubstitution.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rsbInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__bool_RsbInt_h
+#define ABC__bool_RsbInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+#include "misc/util/utilTruth.h"
+#include "bool/kit/kit.h"
+#include "rsb.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// truth table computation manager
+struct Rsb_Man_t_
+{
+    // parameters
+    int                nLeafMax;     // the max number of leaves of a cut
+    int                nDivMax;      // the max number of divisors to collect
+    int                nDecMax;      // the max number of decompositions
+    int                fVerbose;     // verbosity level
+    // decomposition
+    Vec_Wrd_t *        vCexes;       // counter-examples
+    Vec_Int_t *        vDecPats;     // decomposition patterns
+    Vec_Int_t *        vFanins;      // the result of decomposition
+    Vec_Int_t *        vFaninsOld;   // original fanins
+    Vec_Int_t *        vTries;       // intermediate
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== rsbMan.c ==========================================================*/
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/bool/rsb/rsbMan.c b/abc-build/src/bool/rsb/rsbMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/bool/rsb/rsbMan.c
@@ -0,0 +1,99 @@
+/**CFile****************************************************************
+
+  FileName    [rsbMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Truth-table based resubstitution.]
+
+  Synopsis    [Manager maintenance.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rsbMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rsbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Rsb_Man_t * Rsb_ManAlloc( int nLeafMax, int nDivMax, int nDecMax, int fVerbose )
+{
+    Rsb_Man_t * p;
+    assert( nLeafMax <= 20 );
+    assert( nDivMax  <= 200 );
+    p = ABC_CALLOC( Rsb_Man_t, 1 );
+    p->nLeafMax   = nLeafMax;
+    p->nDivMax    = nDivMax;
+    p->nDecMax    = nDecMax;
+    p->fVerbose   = fVerbose;
+    // decomposition
+    p->vCexes     = Vec_WrdAlloc( nDivMax + 150 );
+    p->vDecPats   = Vec_IntAlloc( Abc_TtWordNum(nLeafMax) );
+    p->vFanins    = Vec_IntAlloc( 10 );
+    p->vFaninsOld = Vec_IntAlloc( 10 );
+    p->vTries     = Vec_IntAlloc( 10 );
+    return p;
+}
+void Rsb_ManFree( Rsb_Man_t * p )
+{
+    Vec_WrdFree( p->vCexes );
+    Vec_IntFree( p->vDecPats );
+    Vec_IntFree( p->vFanins );
+    Vec_IntFree( p->vFaninsOld );
+    Vec_IntFree( p->vTries );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Rsb_ManGetFanins( Rsb_Man_t * p )
+{
+    return p->vFanins;
+}
+Vec_Int_t * Rsb_ManGetFaninsOld( Rsb_Man_t * p )
+{
+    return p->vFaninsOld;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/demo.c b/abc-build/src/demo.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/demo.c
@@ -0,0 +1,181 @@
+/**CFile****************************************************************
+
+  FileName    [demo.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [ABC as a static library.]
+
+  Synopsis    [A demo program illustrating the use of ABC as a static library.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: demo.c,v 1.00 2005/11/14 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <time.h>
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// procedures to start and stop the ABC framework
+// (should be called before and after the ABC procedures are called)
+extern void   Abc_Start();
+extern void   Abc_Stop();
+
+// procedures to get the ABC framework and execute commands in it
+extern void * Abc_FrameGetGlobalFrame();
+extern int    Cmd_CommandExecute( void * pAbc, char * sCommand );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [The main() procedure.]
+
+  Description [This procedure compiles into a stand-alone program for 
+  DAG-aware rewriting of the AIGs. A BLIF or PLA file to be considered
+  for rewriting should be given as a command-line argument. Implementation 
+  of the rewriting is inspired by the paper: Per Bjesse, Arne Boralv, 
+  "DAG-aware circuit compression for formal verification", Proc. ICCAD 2004.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int main( int argc, char * argv[] )
+{
+    // parameters
+    int fUseResyn2  = 0;
+    int fPrintStats = 1;
+    int fVerify     = 1;
+    // variables
+    void * pAbc;
+    char * pFileName;
+    char Command[1000];
+    clock_t clkRead, clkResyn, clkVer, clk;
+
+    //////////////////////////////////////////////////////////////////////////
+    // get the input file name
+    if ( argc != 2 )
+    {
+        printf( "Wrong number of command-line arguments.\n" );
+        return 1;
+    }
+    pFileName = argv[1];
+
+    //////////////////////////////////////////////////////////////////////////
+    // start the ABC framework
+    Abc_Start();
+	pAbc = Abc_FrameGetGlobalFrame();
+
+clk = clock();
+    //////////////////////////////////////////////////////////////////////////
+    // read the file
+    sprintf( Command, "read %s", pFileName );
+    if ( Cmd_CommandExecute( pAbc, Command ) )
+    {
+        fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+        return 1;
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+    // balance
+    sprintf( Command, "balance" );
+    if ( Cmd_CommandExecute( pAbc, Command ) )
+    {
+        fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+        return 1;
+    }
+clkRead = clock() - clk;
+
+    //////////////////////////////////////////////////////////////////////////
+    // print stats
+    if ( fPrintStats )
+    {
+        sprintf( Command, "print_stats" );
+        if ( Cmd_CommandExecute( pAbc, Command ) )
+        {
+            fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+            return 1;
+        }
+    }
+
+clk = clock();
+    //////////////////////////////////////////////////////////////////////////
+    // synthesize
+    if ( fUseResyn2 )
+    {
+        sprintf( Command, "balance; rewrite -l; refactor -l; balance; rewrite -l; rewrite -lz; balance; refactor -lz; rewrite -lz; balance" );
+        if ( Cmd_CommandExecute( pAbc, Command ) )
+        {
+            fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+            return 1;
+        }
+    }
+    else
+    {
+        sprintf( Command, "balance; rewrite -l; rewrite -lz; balance; rewrite -lz; balance" );
+        if ( Cmd_CommandExecute( pAbc, Command ) )
+        {
+            fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+            return 1;
+        }
+    }
+clkResyn = clock() - clk;
+
+    //////////////////////////////////////////////////////////////////////////
+    // print stats
+    if ( fPrintStats )
+    {
+        sprintf( Command, "print_stats" );
+        if ( Cmd_CommandExecute( pAbc, Command ) )
+        {
+            fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+            return 1;
+        }
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+    // write the result in blif
+    sprintf( Command, "write_blif result.blif" );
+    if ( Cmd_CommandExecute( pAbc, Command ) )
+    {
+        fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+        return 1;
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+    // perform verification
+clk = clock();
+    if ( fVerify )
+    {
+        sprintf( Command, "cec %s result.blif", pFileName );
+        if ( Cmd_CommandExecute( pAbc, Command ) )
+        {
+            fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+            return 1;
+        }
+    }
+clkVer = clock() - clk;
+
+    printf( "Reading = %6.2f sec   ",     (float)(clkRead)/(float)(CLOCKS_PER_SEC) );
+    printf( "Rewriting = %6.2f sec   ",   (float)(clkResyn)/(float)(CLOCKS_PER_SEC) );
+    printf( "Verification = %6.2f sec\n", (float)(clkVer)/(float)(CLOCKS_PER_SEC) );
+
+    //////////////////////////////////////////////////////////////////////////
+    // stop the ABC framework
+    Abc_Stop();
+    return 0;
+}
+
diff --git a/abc-build/src/generic.c b/abc-build/src/generic.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/generic.c
@@ -0,0 +1,52 @@
+/**CFile****************************************************************
+
+  FileName    [.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName []
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: .c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "__Int.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/generic.h b/abc-build/src/generic.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/generic.h
@@ -0,0 +1,63 @@
+/**CFile****************************************************************
+
+  FileName    [.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName []
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: .h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__generic_h
+#define ABC__generic_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== zzz.c ==========================================================*/
+ 
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/map/amap/amap.h b/abc-build/src/map/amap/amap.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/amap/amap.h
@@ -0,0 +1,97 @@
+/**CFile****************************************************************
+
+  FileName    [amap.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Technology mapper for standard cells.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: amap.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__map__amap__amap_h
+#define ABC__map__amap__amap_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Amap_Lib_t_ Amap_Lib_t;
+
+typedef struct Amap_Par_t_ Amap_Par_t;
+struct Amap_Par_t_
+{
+    int    nIterFlow;   // iterations of area flow
+    int    nIterArea;   // iteratoins of exact area
+    int    nCutsMax;    // the maximum number of cuts at a node
+    int    fUseMuxes;   // enables the use of MUXes
+    int    fUseXors;    // enables the use of XORs
+    int    fFreeInvs;   // assume inverters are free (area = 0)
+    float  fEpsilon;    // used to compare floating point numbers
+    float  fADratio;    // ratio of area/delay improvement
+    int    fVerbose;    // verbosity flag
+};
+
+typedef struct Amap_Out_t_ Amap_Out_t;
+struct Amap_Out_t_
+{
+    char * pName;     // gate name
+    short  Type;      // node type   (-1=input; 0=internal; 1=output)
+    short  nFans;     // number of fanins
+    int    pFans[0];  // fanin
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== amapCore.c ==========================================================*/
+extern void          Amap_ManSetDefaultParams( Amap_Par_t * pPars );
+//extern Vec_Ptr_t * Amap_ManTest( Aig_Man_t * pAig, Amap_Par_t * pPars );
+/*=== amapLib.c ==========================================================*/
+extern void          Amap_LibFree( Amap_Lib_t * p );
+extern void          Amap_LibPrintSelectedGates( Amap_Lib_t * p, int fAllGates );
+extern Amap_Lib_t *  Amap_LibReadAndPrepare( char * pFileName, char * pBuffer, int fVerbose, int fVeryVerbose );
+/*=== amapLiberty.c ==========================================================*/
+extern int           Amap_LibertyParse( char * pFileName, int fVerbose );
+extern Vec_Str_t *   Amap_LibertyParseStr( char * pFileName, int fVerbose );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/map/amap/amapCore.c b/abc-build/src/map/amap/amapCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/amap/amapCore.c
@@ -0,0 +1,110 @@
+/**CFile****************************************************************
+
+  FileName    [amapCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Technology mapper for standard cells.]
+
+  Synopsis    [Core mapping procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: amapCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_ManSetDefaultParams( Amap_Par_t * p )
+{
+    memset( p, 0, sizeof(Amap_Par_t) );
+    p->nIterFlow = 1;            // iterations of area flow
+    p->nIterArea = 4;            // iteratoins of exact area
+    p->nCutsMax  = 500;          // the maximum number of cuts at a node
+    p->fUseMuxes = 0;            // enables the use of MUXes
+    p->fUseXors  = 1;            // enables the use of XORs
+    p->fFreeInvs = 0;            // assume inverters are free (area = 0)
+    p->fEpsilon  = (float)0.001; // used to compare floating point numbers
+    p->fVerbose  = 0;            // verbosity flag
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Amap_ManTest( Aig_Man_t * pAig, Amap_Par_t * pPars )
+{
+//    extern void * Abc_FrameReadLibGen2();
+    Vec_Ptr_t * vRes;
+    Amap_Man_t * p;
+    Amap_Lib_t * pLib;
+    abctime clkTotal = Abc_Clock();
+    pLib = (Amap_Lib_t *)Abc_FrameReadLibGen2();
+    if ( pLib == NULL )
+    {
+        printf( "Library is not available.\n" );
+        return NULL;
+    }
+    p = Amap_ManStart( Aig_ManNodeNum(pAig) );
+    p->pPars = pPars;
+    p->pLib  = pLib;
+    p->fAreaInv = pPars->fFreeInvs? 0.0 : pLib->pGateInv->dArea;
+    p->fUseMux = pPars->fUseMuxes && pLib->fHasMux;
+    p->fUseXor = pPars->fUseXors && pLib->fHasXor;
+    p->ppCutsTemp = ABC_CALLOC( Amap_Cut_t *, 2 * pLib->nNodes );
+    p->pMatsTemp = ABC_CALLOC( int, 2 * pLib->nNodes );
+    Amap_ManCreate( p, pAig );
+    Amap_ManMap( p );
+    vRes = NULL;
+    vRes = Amap_ManProduceMapped( p );
+    Amap_ManStop( p );
+if ( pPars->fVerbose )
+{
+ABC_PRT( "Total runtime", Abc_Clock() - clkTotal );
+}
+    return vRes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/amap/amapGraph.c b/abc-build/src/map/amap/amapGraph.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/amap/amapGraph.c
@@ -0,0 +1,399 @@
+/**CFile****************************************************************
+
+  FileName    [amapGraph.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Technology mapper for standard cells.]
+
+  Synopsis    [Internal AIG manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: amapGraph.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Obj_t * Amap_ManSetupObj( Amap_Man_t * p )
+{
+    Amap_Obj_t * pObj;
+    pObj = (Amap_Obj_t *)Aig_MmFixedEntryFetch( p->pMemObj );
+    memset( pObj, 0, sizeof(Amap_Obj_t) );
+    pObj->nFouts[0] = 1; // needed for flow to work in the first pass
+    pObj->Id = Vec_PtrSize(p->vObjs);
+    Vec_PtrPush( p->vObjs, pObj );
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates constant 1 node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Obj_t * Amap_ManCreateConst1( Amap_Man_t * p )
+{
+    Amap_Obj_t * pObj;
+    pObj = Amap_ManSetupObj( p );
+    pObj->Type   = AMAP_OBJ_CONST1;
+    pObj->fPhase = 1;
+    p->nObjs[AMAP_OBJ_CONST1]++;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates primary input.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Obj_t * Amap_ManCreatePi( Amap_Man_t * p )
+{
+    Amap_Obj_t * pObj;
+    pObj = Amap_ManSetupObj( p );
+    pObj->Type  = AMAP_OBJ_PI;
+    pObj->IdPio = Vec_PtrSize( p->vPis );
+    Vec_PtrPush( p->vPis, pObj );
+    p->nObjs[AMAP_OBJ_PI]++;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates primary output with the given driver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Obj_t * Amap_ManCreatePo( Amap_Man_t * p, Amap_Obj_t * pFan0 )
+{
+    Amap_Obj_t * pObj;
+    pObj = Amap_ManSetupObj( p );
+    pObj->IdPio  = Vec_PtrSize( p->vPos );
+    Vec_PtrPush( p->vPos, pObj );
+    pObj->Type   = AMAP_OBJ_PO;
+    pObj->Fan[0] = Amap_ObjToLit(pFan0);  Amap_Regular(pFan0)->nRefs++;
+    pObj->Level  = Amap_Regular(pFan0)->Level;
+    if ( p->nLevelMax < (int)pObj->Level )
+        p->nLevelMax = (int)pObj->Level;
+    assert( p->nLevelMax < 4094 ); // 2^12-2
+    p->nObjs[AMAP_OBJ_PO]++;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the new node assuming it does not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Obj_t * Amap_ManCreateAnd( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 )
+{
+    Amap_Obj_t * pObj;
+    pObj = Amap_ManSetupObj( p );
+    pObj->Type   = AMAP_OBJ_AND;
+    pObj->Fan[0] = Amap_ObjToLit(pFan0);  Amap_Regular(pFan0)->nRefs++;
+    pObj->Fan[1] = Amap_ObjToLit(pFan1);  Amap_Regular(pFan1)->nRefs++;
+    assert( Abc_Lit2Var(pObj->Fan[0]) != Abc_Lit2Var(pObj->Fan[1]) );
+    pObj->fPhase = Amap_ObjPhaseReal(pFan0) & Amap_ObjPhaseReal(pFan1);
+    pObj->Level  = 1 + Abc_MaxInt( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level );
+    if ( p->nLevelMax < (int)pObj->Level )
+        p->nLevelMax = (int)pObj->Level;
+    assert( p->nLevelMax < 4094 ); // 2^12-2
+    p->nObjs[AMAP_OBJ_AND]++;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the new node assuming it does not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Obj_t * Amap_ManCreateXor( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 )
+{
+    Amap_Obj_t * pObj;
+    pObj = Amap_ManSetupObj( p );
+    pObj->Type   = AMAP_OBJ_XOR;
+    pObj->Fan[0] = Amap_ObjToLit(pFan0);  Amap_Regular(pFan0)->nRefs++;
+    pObj->Fan[1] = Amap_ObjToLit(pFan1);  Amap_Regular(pFan1)->nRefs++;
+    pObj->fPhase = Amap_ObjPhaseReal(pFan0) ^ Amap_ObjPhaseReal(pFan1);
+    pObj->Level  = 2 + Abc_MaxInt( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level );
+    if ( p->nLevelMax < (int)pObj->Level )
+        p->nLevelMax = (int)pObj->Level;
+    assert( p->nLevelMax < 4094 ); // 2^12-2
+    p->nObjs[AMAP_OBJ_XOR]++;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the new node assuming it does not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Obj_t * Amap_ManCreateMux( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1, Amap_Obj_t * pFanC )
+{
+    Amap_Obj_t * pObj;
+    pObj = Amap_ManSetupObj( p );
+    pObj->Type   = AMAP_OBJ_MUX;
+    pObj->Fan[0] = Amap_ObjToLit(pFan0);  Amap_Regular(pFan0)->nRefs++;
+    pObj->Fan[1] = Amap_ObjToLit(pFan1);  Amap_Regular(pFan1)->nRefs++;
+    pObj->Fan[2] = Amap_ObjToLit(pFanC);  Amap_Regular(pFanC)->nRefs++;
+    pObj->fPhase = (Amap_ObjPhaseReal(pFan1) &  Amap_ObjPhaseReal(pFanC)) | 
+                   (Amap_ObjPhaseReal(pFan0) & ~Amap_ObjPhaseReal(pFanC));
+    pObj->Level  = Abc_MaxInt( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level );
+    pObj->Level  = 2 + Abc_MaxInt( pObj->Level, Amap_Regular(pFanC)->Level );
+    if ( p->nLevelMax < (int)pObj->Level )
+        p->nLevelMax = (int)pObj->Level;
+    assert( p->nLevelMax < 4094 ); // 2^12-2
+    p->nObjs[AMAP_OBJ_MUX]++;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the choice node.]
+
+  Description [Should be called after the equivalence class nodes are linked.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_ManCreateChoice( Amap_Man_t * p, Amap_Obj_t * pObj )
+{
+    Amap_Obj_t * pTemp;
+    // mark the node as a representative if its class
+//    assert( pObj->fRepr == 0 );
+    pObj->fRepr = 1;
+    // update the level of this node (needed for correct required time computation)
+    for ( pTemp = pObj; pTemp; pTemp = Amap_ObjChoice(p, pTemp) )
+    {
+        pObj->Level = Abc_MaxInt( pObj->Level, pTemp->Level );
+//        pTemp->nVisits++; pTemp->nVisitsCopy++;
+    }
+    // mark the largest level
+    if ( p->nLevelMax < (int)pObj->Level )
+        p->nLevelMax = (int)pObj->Level;
+    assert( p->nLevelMax < 4094 ); // 2^12-2
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates XOR/MUX choices for the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_ManCreateXorChoices( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1, Amap_Obj_t * pChoices[] )
+{
+    pChoices[0] = Amap_ManCreateXor( p, pFan0,           pFan1 );
+    pChoices[1] = Amap_ManCreateXor( p, Amap_Not(pFan0), pFan1 );
+    pChoices[2] = Amap_ManCreateXor( p, pFan0,           Amap_Not(pFan1) );
+    pChoices[3] = Amap_ManCreateXor( p, Amap_Not(pFan0), Amap_Not(pFan1) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates XOR/MUX choices for the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_ManCreateMuxChoices( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1, Amap_Obj_t * pFanC, Amap_Obj_t * pChoices[] )
+{
+    pChoices[0] = Amap_ManCreateMux( p, pFan0,           pFan1,           pFanC           );
+    pChoices[1] = Amap_ManCreateMux( p, Amap_Not(pFan0), Amap_Not(pFan1), pFanC           );
+    pChoices[2] = Amap_ManCreateMux( p, pFan1,           pFan0,           Amap_Not(pFanC) );
+    pChoices[3] = Amap_ManCreateMux( p, Amap_Not(pFan1), Amap_Not(pFan0), Amap_Not(pFanC) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Drags pointer out through the copy.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Amap_Obj_t * Amap_AndToObj( Aig_Obj_t * pObj )
+{
+    return Amap_NotCond( (Amap_Obj_t *)Aig_Regular(pObj)->pData, Aig_IsComplement(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Obj_t * Amap_ManGetLast_rec( Amap_Man_t * p, Amap_Obj_t * pObj )
+{
+    if ( pObj->Equiv == 0 )
+        return pObj;
+    return Amap_ManGetLast_rec( p, Amap_ObjChoice(p, pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_ManCreate( Amap_Man_t * p, Aig_Man_t * pAig )
+{
+    Vec_Ptr_t * vNodes;
+    Amap_Obj_t * pChoices[4];
+    Aig_Obj_t * pObj, * pFanin, * pPrev, * pFan0, * pFan1, * pFanC;
+    int i, fChoices;
+    if ( pAig->pEquivs )
+        vNodes = Aig_ManDfsChoices( pAig );
+    else
+        vNodes = Aig_ManDfs( pAig, 1 );
+    p->pConst1 = Amap_ManCreateConst1( p );
+    // print warning about excessive memory usage
+    if ( p->pPars->fVerbose )
+    {
+        if ( 1.0 * Aig_ManObjNum(pAig) * sizeof(Amap_Obj_t) / (1<<30) > 0.1 )
+        printf( "Warning: Mapper allocates %.3f GB for subject graph with %d objects.\n", 
+            1.0 * Aig_ManObjNum(pAig) * sizeof(Amap_Obj_t) / (1<<30), Aig_ManObjNum(pAig) );
+    }
+    // create PIs and remember them in the old nodes
+    Aig_ManCleanData(pAig);
+    Aig_ManConst1(pAig)->pData = Amap_ManConst1( p );
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->pData = Amap_ManCreatePi( p );
+    // load the AIG into the mapper
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        fChoices = 0;
+        if ( p->fUseXor && Aig_ObjRecognizeExor(pObj, &pFan0, &pFan1 ) )
+        {
+            Amap_ManCreateXorChoices( p, Amap_AndToObj(pFan0), Amap_AndToObj(pFan1), pChoices );
+            fChoices = 1;
+        }
+        else if ( p->fUseMux && Aig_ObjIsMuxType(pObj) )
+        {
+            pFanC = Aig_ObjRecognizeMux( pObj, &pFan1, &pFan0 );
+            Amap_ManCreateMuxChoices( p, Amap_AndToObj(pFan0), Amap_AndToObj(pFan1), Amap_AndToObj(pFanC), pChoices );
+            fChoices = 1;
+        }
+        pObj->pData = Amap_ManCreateAnd( p, (Amap_Obj_t *)Aig_ObjChild0Copy(pObj), (Amap_Obj_t *)Aig_ObjChild1Copy(pObj) );
+        if ( fChoices )
+        {
+            p->nChoicesAdded++;
+            Amap_ObjSetChoice( (Amap_Obj_t *)pObj->pData, pChoices[0] );
+            Amap_ObjSetChoice( pChoices[0], pChoices[1] );
+            Amap_ObjSetChoice( pChoices[1], pChoices[2] );
+            Amap_ObjSetChoice( pChoices[2], pChoices[3] );
+            Amap_ManCreateChoice( p, (Amap_Obj_t *)pObj->pData );
+        }
+        if ( Aig_ObjIsChoice( pAig, pObj ) )
+        {
+//            assert( !fChoices );
+            p->nChoicesGiven++;
+            for ( pPrev = pObj, pFanin = Aig_ObjEquiv(pAig, pObj); pFanin; pPrev = pFanin, pFanin = Aig_ObjEquiv(pAig, pFanin) )
+            {
+                ((Amap_Obj_t *)pFanin->pData)->fRepr = 0;
+                Amap_ObjSetChoice( Amap_ManGetLast_rec(p, (Amap_Obj_t *)pPrev->pData), 
+                    (Amap_Obj_t *)pFanin->pData );
+            }
+            Amap_ManCreateChoice( p, (Amap_Obj_t *)pObj->pData );
+        }
+    }
+    Vec_PtrFree( vNodes );
+    // set the primary outputs without copying the phase
+    Aig_ManForEachCo( pAig, pObj, i )
+        pObj->pData = Amap_ManCreatePo( p, (Amap_Obj_t *)Aig_ObjChild0Copy(pObj) );
+    if ( p->pPars->fVerbose )
+        printf( "Performing mapping with %d given and %d created choices.\n", 
+            p->nChoicesGiven, p->nChoicesAdded );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/amap/amapInt.h b/abc-build/src/map/amap/amapInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/amap/amapInt.h
@@ -0,0 +1,376 @@
+/**CFile****************************************************************
+
+  FileName    [amapInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Technology mapper for standard cells.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: amapInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__map__amap__amapInt_h
+#define ABC__map__amap__amapInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "misc/extra/extra.h"
+#include "aig/aig/aig.h"
+#include "amap.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+// the largest gate size in the library
+// (gates above this size will be ignored)
+#define AMAP_MAXINS 15
+
+#define AMAP_STRING_CONST0     "CONST0"
+#define AMAP_STRING_CONST1     "CONST1"
+
+// object types
+typedef enum { 
+    AMAP_OBJ_NONE,    // 0: non-existent object
+    AMAP_OBJ_CONST1,  // 1: constant 1 
+    AMAP_OBJ_PI,      // 2: primary input
+    AMAP_OBJ_PO,      // 3: primary output
+    AMAP_OBJ_AND,     // 4: AND node
+    AMAP_OBJ_XOR,     // 5: XOR node
+    AMAP_OBJ_MUX,     // 6: MUX node
+    AMAP_OBJ_VOID     // 7: unused object
+} Amap_Type_t;
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Amap_Pin_t_ Amap_Pin_t;
+typedef struct Amap_Gat_t_ Amap_Gat_t;
+typedef struct Amap_Nod_t_ Amap_Nod_t;
+typedef struct Amap_Set_t_ Amap_Set_t;
+
+typedef struct Amap_Man_t_ Amap_Man_t;
+typedef struct Amap_Obj_t_ Amap_Obj_t;
+typedef struct Amap_Cut_t_ Amap_Cut_t;
+typedef struct Amap_Mat_t_ Amap_Mat_t;
+
+struct Amap_Man_t_
+{
+    // user data
+    Amap_Par_t *       pPars;
+    Amap_Lib_t *       pLib;
+    // internal parameters
+    float              fEpsilonInternal;
+    float              fAreaInv;
+    int                fUseXor;    
+    int                fUseMux;    
+    // internal AIG with choices
+    Vec_Ptr_t *        vPis;
+    Vec_Ptr_t *        vPos;
+    Vec_Ptr_t *        vObjs;
+    Aig_MmFixed_t *    pMemObj;
+    Aig_MmFlex_t *     pMemCuts;
+    Aig_MmFlex_t *     pMemCutBest;
+    Aig_MmFlex_t *     pMemTemp;
+    Amap_Obj_t *       pConst1;
+    int                nObjs[AMAP_OBJ_VOID];
+    int                nLevelMax;
+    int                nChoicesGiven;
+    int                nChoicesAdded;
+    // mapping data-structures
+    Vec_Int_t *        vTemp;
+    int *              pMatsTemp;
+    Amap_Cut_t **      ppCutsTemp;
+    Amap_Cut_t *       pCutsPi;
+    Vec_Ptr_t *        vCuts0;
+    Vec_Ptr_t *        vCuts1;
+    Vec_Ptr_t *        vCuts2;
+    // statistics
+    int                nCutsUsed;
+    int                nCutsTried;
+    int                nCutsTried3;
+    int                nBytesUsed;
+};
+struct Amap_Lib_t_
+{
+    char *             pName;       // library name
+    Vec_Ptr_t *        vGates;      // represenation of gates
+    Vec_Ptr_t *        vSorted;     // gates sorted for area-only mapping
+    Vec_Ptr_t *        vSelect;     // gates selected for area-only mapping
+    Amap_Gat_t *       pGate0;      // the constant zero gate
+    Amap_Gat_t *       pGate1;      // the constant one gate
+    Amap_Gat_t *       pGateBuf;    // the buffer
+    Amap_Gat_t *       pGateInv;    // the inverter
+    Aig_MmFlex_t *     pMemGates;   // memory manager for objects
+    int                fHasXor;     // XOR/NXOR gates are present
+    int                fHasMux;     // MUX/NMUX gates are present
+    // structural representation
+    int                fVerbose;    // enable detailed statistics
+    Amap_Nod_t *       pNodes;      // representation nodes
+    int                nNodes;      // the number of nodes used
+    int                nNodesAlloc; // the number of nodes allocated
+    Vec_Ptr_t *        vRules;      // the rule of AND gate
+    Vec_Ptr_t *        vRulesX;     // the rule of XOR gate
+    Vec_Int_t *        vRules3;     // the rule of MUX gate
+    int **             pRules;      // simplified representation
+    int **             pRulesX;     // simplified representation
+    Aig_MmFlex_t *     pMemSet;     // memory manager for sets
+    int                nSets;       // the number of sets created
+};
+struct Amap_Pin_t_
+{
+    char *             pName;
+    int                Phase;
+    double             dLoadInput;
+    double             dLoadMax;
+    double             dDelayBlockRise;
+    double             dDelayFanoutRise;
+    double             dDelayBlockFall;
+    double             dDelayFanoutFall;
+    double             dDelayBlockMax;
+};
+struct Amap_Gat_t_
+{
+    Amap_Lib_t *       pLib;            // library   
+    Amap_Gat_t *       pTwin;           // twin gate
+    char *             pName;           // the name of the gate
+    char *             pOutName;        // name of the output
+    double             dArea;           // the area of the gate
+    char *             pForm;           // the formula describing functionality
+    unsigned *         pFunc;           // truth table
+    unsigned           Id     :   23;   // unique number of the gate
+    unsigned           fMux   :    1;   // denotes MUX-gates
+    unsigned           nPins  :    8;   // number of inputs
+    Amap_Pin_t         Pins[0];         // description of inputs
+};
+struct Amap_Set_t_
+{
+    Amap_Set_t *       pNext;
+    unsigned           iGate    : 16;
+    unsigned           fInv     :  1;
+    unsigned           nIns     : 15;
+    char               Ins[AMAP_MAXINS];// mapping from gate inputs into fanins
+};
+struct Amap_Nod_t_
+{
+    unsigned           Id       : 16;   // ID of the node
+    unsigned           nSuppSize:  8;   // support size
+    unsigned           Type     :  8;   // the type of node
+    short              iFan0;           // fanin0
+    short              iFan1;           // fanin1
+    short              iFan2;           // fanin2
+    short              Unused;          // 
+    Amap_Set_t *       pSets;           // implementable gates
+};
+struct Amap_Cut_t_
+{
+    unsigned           iMat     : 16;
+    unsigned           fInv     :  1;
+    unsigned           nFans  : 15;
+    int                Fans[0];
+};
+struct Amap_Mat_t_
+{
+    Amap_Cut_t *       pCut;           // the cut
+    Amap_Set_t *       pSet;           // the set
+    float              Area;           // area flow / exact area of the node
+    float              AveFan;         // edge flow of the node
+    float              Delay;          // delay of the node
+};
+struct Amap_Obj_t_
+{
+    unsigned           Type     :  3;   
+    unsigned           Id       : 29;
+    unsigned           IdPio    : 29;
+    unsigned           fPhase   :  1;
+    unsigned           fRepr    :  1;
+    unsigned           fPolar   :  1;  // pCutBest->fInv ^ pSetBest->fInv
+    unsigned           Level    : 12;  // 20  (July 16, 2009)
+    unsigned           nCuts    : 20;  // 12  (July 16, 2009)
+    int                nRefs;
+    int                Equiv;
+    int                Fan[3];
+    union {
+    void *             pData;
+    int                iData;
+    };
+    // match of the node
+    float              EstRefs;        // the number of estimated fanouts
+    int                nFouts[2];      // the number of refs in each polarity
+    Amap_Mat_t         Best;           // the best match of the node
+};
+
+static inline Amap_Obj_t * Amap_Regular( Amap_Obj_t * p )                          { return (Amap_Obj_t *)((ABC_PTRUINT_T)(p) & ~01);  }
+static inline Amap_Obj_t * Amap_Not( Amap_Obj_t * p )                              { return (Amap_Obj_t *)((ABC_PTRUINT_T)(p) ^  01);  }
+static inline Amap_Obj_t * Amap_NotCond( Amap_Obj_t * p, int c )                   { return (Amap_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c));  }
+static inline int          Amap_IsComplement( Amap_Obj_t * p )                     { return (int )(((ABC_PTRUINT_T)p) & 01);           }
+
+static inline int          Amap_ManPiNum( Amap_Man_t * p )                         { return p->nObjs[AMAP_OBJ_PI];                      }
+static inline int          Amap_ManPoNum( Amap_Man_t * p )                         { return p->nObjs[AMAP_OBJ_PO];                      }
+static inline int          Amap_ManAndNum( Amap_Man_t * p )                        { return p->nObjs[AMAP_OBJ_AND];                     }
+static inline int          Amap_ManXorNum( Amap_Man_t * p )                        { return p->nObjs[AMAP_OBJ_XOR];                     }
+static inline int          Amap_ManMuxNum( Amap_Man_t * p )                        { return p->nObjs[AMAP_OBJ_MUX];                     }
+static inline int          Amap_ManObjNum( Amap_Man_t * p )                        { return Vec_PtrSize(p->vObjs);                      }
+static inline int          Amap_ManNodeNum( Amap_Man_t * p )                       { return p->nObjs[AMAP_OBJ_AND] + p->nObjs[AMAP_OBJ_XOR] + p->nObjs[AMAP_OBJ_MUX];   }
+
+static inline Amap_Obj_t * Amap_ManConst1( Amap_Man_t * p )                        { return p->pConst1;                                 }
+static inline Amap_Obj_t * Amap_ManPi( Amap_Man_t * p, int i )                     { return (Amap_Obj_t *)Vec_PtrEntry( p->vPis, i );   }
+static inline Amap_Obj_t * Amap_ManPo( Amap_Man_t * p, int i )                     { return (Amap_Obj_t *)Vec_PtrEntry( p->vPos, i );   }
+static inline Amap_Obj_t * Amap_ManObj( Amap_Man_t * p, int i )                    { return (Amap_Obj_t *)Vec_PtrEntry( p->vObjs, i );  }
+
+static inline int          Amap_ObjIsConst1( Amap_Obj_t * pObj )                   { return pObj->Type == AMAP_OBJ_CONST1;              }
+static inline int          Amap_ObjIsPi( Amap_Obj_t * pObj )                       { return pObj->Type == AMAP_OBJ_PI;                  }
+static inline int          Amap_ObjIsPo( Amap_Obj_t * pObj )                       { return pObj->Type == AMAP_OBJ_PO;                  }
+static inline int          Amap_ObjIsAnd( Amap_Obj_t * pObj )                      { return pObj->Type == AMAP_OBJ_AND;                 }
+static inline int          Amap_ObjIsXor( Amap_Obj_t * pObj )                      { return pObj->Type == AMAP_OBJ_XOR;                 }
+static inline int          Amap_ObjIsMux( Amap_Obj_t * pObj )                      { return pObj->Type == AMAP_OBJ_MUX;                 }
+static inline int          Amap_ObjIsNode( Amap_Obj_t * pObj )                     { return pObj->Type == AMAP_OBJ_AND || pObj->Type == AMAP_OBJ_XOR || pObj->Type == AMAP_OBJ_MUX;  }
+
+static inline int          Amap_ObjToLit( Amap_Obj_t * pObj )                      { return Abc_Var2Lit( Amap_Regular(pObj)->Id, Amap_IsComplement(pObj) ); }
+static inline Amap_Obj_t * Amap_ObjFanin0( Amap_Man_t * p, Amap_Obj_t * pObj )     { return Amap_ManObj(p, Abc_Lit2Var(pObj->Fan[0])); }
+static inline Amap_Obj_t * Amap_ObjFanin1( Amap_Man_t * p, Amap_Obj_t * pObj )     { return Amap_ManObj(p, Abc_Lit2Var(pObj->Fan[1])); }
+static inline Amap_Obj_t * Amap_ObjFanin2( Amap_Man_t * p, Amap_Obj_t * pObj )     { return Amap_ManObj(p, Abc_Lit2Var(pObj->Fan[2])); }
+static inline int          Amap_ObjFaninC0( Amap_Obj_t * pObj )                    { return Abc_LitIsCompl(pObj->Fan[0]);              }
+static inline int          Amap_ObjFaninC1( Amap_Obj_t * pObj )                    { return Abc_LitIsCompl(pObj->Fan[1]);              }
+static inline int          Amap_ObjFaninC2( Amap_Obj_t * pObj )                    { return Abc_LitIsCompl(pObj->Fan[2]);              }
+static inline void *       Amap_ObjCopy( Amap_Obj_t * pObj )                       { return pObj->pData;                                }
+static inline int          Amap_ObjLevel( Amap_Obj_t * pObj )                      { return pObj->Level;                                }
+static inline void         Amap_ObjSetLevel( Amap_Obj_t * pObj, int Level )        { pObj->Level = Level;                               }
+static inline void         Amap_ObjSetCopy( Amap_Obj_t * pObj, void * pCopy )      { pObj->pData = pCopy;                               }
+static inline Amap_Obj_t * Amap_ObjChoice( Amap_Man_t * p, Amap_Obj_t * pObj )     { return pObj->Equiv? Amap_ManObj(p, pObj->Equiv) : NULL; }
+static inline void         Amap_ObjSetChoice( Amap_Obj_t * pObj, Amap_Obj_t * pEqu){ assert(pObj->Equiv==0); pObj->Equiv = pEqu->Id;                            }
+static inline int          Amap_ObjPhaseReal( Amap_Obj_t * pObj )                  { return Amap_Regular(pObj)->fPhase ^ Amap_IsComplement(pObj);   }
+static inline int          Amap_ObjRefsTotal( Amap_Obj_t * pObj )                  { return pObj->nFouts[0] + pObj->nFouts[1];          }
+
+static inline Amap_Gat_t * Amap_LibGate( Amap_Lib_t * p, int i ) { return (Amap_Gat_t *)Vec_PtrEntry(p->vGates, i); }
+static inline Amap_Nod_t * Amap_LibNod( Amap_Lib_t * p, int i )  { return p->pNodes + i;           }
+
+// returns pointer to the next cut (internal cuts only)
+static inline Amap_Cut_t * Amap_ManCutNext( Amap_Cut_t * pCut )
+{ return (Amap_Cut_t *)(((int *)pCut)+pCut->nFans+1); }
+// returns pointer to the place of the next cut (temporary cuts only)
+static inline Amap_Cut_t ** Amap_ManCutNextP( Amap_Cut_t * pCut )
+{ return (Amap_Cut_t **)(((int *)pCut)+pCut->nFans+1); }
+
+extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars );
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+// iterator over the primary inputs
+#define Amap_ManForEachPi( p, pObj, i )                                    \
+    Vec_PtrForEachEntry( Amap_Obj_t *, p->vPis, pObj, i )
+// iterator over the primary outputs
+#define Amap_ManForEachPo( p, pObj, i )                                    \
+    Vec_PtrForEachEntry( Amap_Obj_t *, p->vPos, pObj, i )
+// iterator over all objects, including those currently not used
+#define Amap_ManForEachObj( p, pObj, i )                                   \
+    Vec_PtrForEachEntry( Amap_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else
+// iterator over all nodes
+#define Amap_ManForEachNode( p, pObj, i )                                  \
+    Vec_PtrForEachEntry( Amap_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL || !Amap_ObjIsNode(pObj) ) {} else
+
+// iterator through all gates of the library
+#define Amap_LibForEachGate( pLib, pGate, i )                              \
+    Vec_PtrForEachEntry( Amap_Gat_t *, pLib->vGates, pGate, i )
+// iterator through all pins of the gate
+#define Amap_GateForEachPin( pGate, pPin )                                 \
+    for ( pPin = pGate->Pins; pPin < pGate->Pins + pGate->nPins; pPin++ )
+
+// iterator through all cuts of the node
+#define Amap_NodeForEachCut( pNode, pCut, i )                              \
+    for ( i = 0, pCut = (Amap_Cut_t *)pNode->pData; i < (int)pNode->nCuts; \
+        i++, pCut = Amap_ManCutNext(pCut) )
+
+// iterator through all sets of one library node
+#define Amap_LibNodeForEachSet( pNod, pSet )                               \
+    for ( pSet = pNod->pSets; pSet; pSet = pSet->pNext )
+
+// iterates through each fanin of the match
+#define Amap_MatchForEachFaninCompl( p, pM, pFanin, fCompl, i )            \
+    for ( i = 0; i < (int)(pM)->pCut->nFans &&                             \
+        ((pFanin = Amap_ManObj((p), Abc_Lit2Var((pM)->pCut->Fans[Abc_Lit2Var((pM)->pSet->Ins[i])]))), 1) && \
+        ((fCompl = Abc_LitIsCompl((pM)->pSet->Ins[i]) ^ Abc_LitIsCompl((pM)->pCut->Fans[Abc_Lit2Var((pM)->pSet->Ins[i])])), 1); \
+        i++ )
+
+// iterates through each fanin of the match
+#define Amap_MatchForEachFanin( p, pM, pFanin, i )                         \
+    for ( i = 0; i < (int)(pM)->pCut->nFans &&                             \
+        ((pFanin = Amap_ManObj((p), Abc_Lit2Var((pM)->pCut->Fans[Abc_Lit2Var((pM)->pSet->Ins[i])]))), 1); \
+        i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== amapCore.c ==========================================================*/
+/*=== amapGraph.c ==========================================================*/
+extern Amap_Obj_t *  Amap_ManCreatePi( Amap_Man_t * p );
+extern Amap_Obj_t *  Amap_ManCreatePo( Amap_Man_t * p, Amap_Obj_t * pFan0 );
+extern Amap_Obj_t *  Amap_ManCreateAnd( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 );
+extern Amap_Obj_t *  Amap_ManCreateXor( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 );
+extern Amap_Obj_t *  Amap_ManCreateMux( Amap_Man_t * p, Amap_Obj_t * pFanC, Amap_Obj_t * pFan1, Amap_Obj_t * pFan0 );
+extern void          Amap_ManCreateChoice( Amap_Man_t * p, Amap_Obj_t * pObj );
+extern void          Amap_ManCreate( Amap_Man_t * p, Aig_Man_t * pAig );
+/*=== amapLib.c ==========================================================*/
+extern Amap_Lib_t *  Amap_LibAlloc();
+extern int           Amap_LibNumPinsMax( Amap_Lib_t * p );
+extern void          Amap_LibWrite( FILE * pFile, Amap_Lib_t * pLib, int fPrintDsd );
+extern Vec_Ptr_t *   Amap_LibSelectGates( Amap_Lib_t * p, int fVerbose );
+/*=== amapMan.c ==========================================================*/
+extern Amap_Man_t *  Amap_ManStart( int nNodes );
+extern void          Amap_ManStop( Amap_Man_t * p );
+/*=== amapMatch.c ==========================================================*/
+extern void          Amap_ManMap( Amap_Man_t * p );
+/*=== amapMerge.c ==========================================================*/
+extern void          Amap_ManMerge( Amap_Man_t * p );
+/*=== amapOutput.c ==========================================================*/
+extern Vec_Ptr_t *   Amap_ManProduceMapped( Amap_Man_t * p );
+/*=== amapParse.c ==========================================================*/
+extern int           Amap_LibParseEquations( Amap_Lib_t * p, int fVerbose );
+/*=== amapPerm.c ==========================================================*/
+/*=== amapRead.c ==========================================================*/
+extern Amap_Lib_t *  Amap_LibReadBuffer( char * pBuffer, int fVerbose );
+extern Amap_Lib_t *  Amap_LibReadFile( char * pFileName, int fVerbose );
+/*=== amapRule.c ==========================================================*/
+extern short *       Amap_LibTableFindNode( Amap_Lib_t * p, int iFan0, int iFan1, int fXor );
+extern void          Amap_LibCreateRules( Amap_Lib_t * p, int fVeryVerbose );
+/*=== amapUniq.c ==========================================================*/
+extern int           Amap_LibFindNode( Amap_Lib_t * pLib, int iFan0, int iFan1, int fXor );
+extern int           Amap_LibFindMux( Amap_Lib_t * p, int iFan0, int iFan1, int iFan2 );
+extern int           Amap_LibCreateVar( Amap_Lib_t * p );
+extern int           Amap_LibCreateNode( Amap_Lib_t * p, int iFan0, int iFan1, int fXor );
+extern int           Amap_LibCreateMux( Amap_Lib_t * p, int iFan0, int iFan1, int iFan2 );
+extern int **        Amap_LibLookupTableAlloc( Vec_Ptr_t * vVec, int fVerbose );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/map/amap/amapLib.c b/abc-build/src/map/amap/amapLib.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/amap/amapLib.c
@@ -0,0 +1,374 @@
+/**CFile****************************************************************
+
+  FileName    [amapLib.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Technology mapper for standard cells.]
+
+  Synopsis    [Standard-cell library.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: amapLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocs a library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Lib_t * Amap_LibAlloc()
+{
+    Amap_Lib_t * p;
+    p = (Amap_Lib_t *)ABC_ALLOC( Amap_Lib_t, 1 );
+    memset( p, 0, sizeof(Amap_Lib_t) );
+    p->vGates = Vec_PtrAlloc( 100 );
+    p->pMemGates = Aig_MmFlexStart();
+    p->pMemSet = Aig_MmFlexStart();
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocs a library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_LibFree( Amap_Lib_t * p )
+{
+    if ( p == NULL )
+        return;
+    if ( p->vSelect )
+        Vec_PtrFree( p->vSelect );
+    if ( p->vSorted )
+        Vec_PtrFree( p->vSorted );
+    if ( p->vGates )
+        Vec_PtrFree( p->vGates );
+    if ( p->vRules )
+        Vec_VecFree( (Vec_Vec_t *)p->vRules );
+    if ( p->vRulesX )
+        Vec_VecFree( (Vec_Vec_t *)p->vRulesX );
+    if ( p->vRules3 )
+        Vec_IntFree( p->vRules3 );
+    Aig_MmFlexStop( p->pMemGates, 0 );
+    Aig_MmFlexStop( p->pMemSet, 0 );
+    ABC_FREE( p->pRules );
+    ABC_FREE( p->pRulesX );
+    ABC_FREE( p->pNodes );
+    ABC_FREE( p->pName );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the largest gate size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_LibNumPinsMax( Amap_Lib_t * p )
+{
+    Amap_Gat_t * pGate;
+    int i, Counter = 0;
+    Amap_LibForEachGate( p, pGate, i )
+        if ( Counter < (int)pGate->nPins )
+            Counter = pGate->nPins;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes one pin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_LibWritePin( FILE * pFile, Amap_Pin_t * pPin )
+{
+    char * pPhaseNames[10] = { "UNKNOWN", "INV", "NONINV" };
+    fprintf( pFile, "    PIN " );
+    fprintf( pFile, "%9s ",     pPin->pName );
+    fprintf( pFile, "%10s ",    pPhaseNames[pPin->Phase] );
+    fprintf( pFile, "%6d ",     (int)pPin->dLoadInput );
+    fprintf( pFile, "%6d ",     (int)pPin->dLoadMax );
+    fprintf( pFile, "%6.2f ",   pPin->dDelayBlockRise );
+    fprintf( pFile, "%6.2f ",   pPin->dDelayFanoutRise );
+    fprintf( pFile, "%6.2f ",   pPin->dDelayBlockFall );
+    fprintf( pFile, "%6.2f",    pPin->dDelayFanoutFall );
+    fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes one gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_LibWriteGate( FILE * pFile, Amap_Gat_t * pGate, int fPrintDsd )
+{
+    Amap_Pin_t * pPin;
+    fprintf( pFile, "GATE " );
+    fprintf( pFile, "%12s ",      pGate->pName );
+    fprintf( pFile, "%10.2f   ",  pGate->dArea );
+    fprintf( pFile, "%s=%s;\n",   pGate->pOutName,    pGate->pForm );
+    if ( fPrintDsd )
+    {
+        if ( pGate->pFunc == NULL )
+            printf( "Truth table is not available.\n" );
+        else
+            Kit_DsdPrintFromTruth( pGate->pFunc, pGate->nPins );
+    }
+    Amap_GateForEachPin( pGate, pPin )
+        Amap_LibWritePin( pFile, pPin );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_LibWrite( FILE * pFile, Amap_Lib_t * pLib, int fPrintDsd )
+{
+    Amap_Gat_t * pGate;
+    int i;
+    fprintf( pFile, "# The genlib library \"%s\".\n", pLib->pName );
+    Amap_LibForEachGate( pLib, pGate, i )
+        Amap_LibWriteGate( pFile, pGate, fPrintDsd );
+}
+        
+/**Function*************************************************************
+
+  Synopsis    [Compares two gates by area.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_LibCompareGatesByArea( Amap_Gat_t ** pp1, Amap_Gat_t ** pp2 )
+{
+    double Diff = (*pp1)->dArea - (*pp2)->dArea;
+    if ( Diff < 0.0 )
+        return -1;
+    if ( Diff > 0.0 ) 
+        return 1;
+    return 0; 
+}
+        
+/**Function*************************************************************
+
+  Synopsis    [Compares gates by area.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Amap_LibSortGatesByArea( Amap_Lib_t * pLib )
+{
+    Vec_Ptr_t * vSorted;
+    vSorted = Vec_PtrDup( pLib->vGates );
+    qsort( (void *)Vec_PtrArray(vSorted), Vec_PtrSize(vSorted), sizeof(void *), 
+            (int (*)(const void *, const void *)) Amap_LibCompareGatesByArea );
+    return vSorted;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds min-area gate with the given function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Gat_t * Amap_LibFindGate( Amap_Lib_t * p, unsigned uTruth )
+{
+    Amap_Gat_t * pGate;
+    int i;
+    Vec_PtrForEachEntry( Amap_Gat_t *, p->vSorted, pGate, i )
+        if ( pGate->nPins <= 5 && pGate->pFunc[0] == uTruth )
+            return pGate;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Selects gates useful for area-only mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Amap_LibSelectGates( Amap_Lib_t * p, int fVerbose )
+{
+    Vec_Ptr_t * vSelect;
+    Amap_Gat_t * pGate, * pGate2;
+    int i, k;//, clk = Abc_Clock();
+    p->pGate0   = Amap_LibFindGate( p, 0 );
+    p->pGate1   = Amap_LibFindGate( p, ~0 );
+    p->pGateBuf = Amap_LibFindGate( p, 0xAAAAAAAA );
+    p->pGateInv = Amap_LibFindGate( p, ~0xAAAAAAAA );
+    vSelect = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Amap_Gat_t *, p->vSorted, pGate, i )
+    {
+        if ( pGate->pFunc == NULL || pGate->pTwin != NULL )
+            continue;
+        Vec_PtrForEachEntryStop( Amap_Gat_t *, p->vSorted, pGate2, k, i )
+        {
+            if ( pGate2->pFunc == NULL || pGate2->pTwin != NULL )
+                continue;
+            if ( pGate2->nPins != pGate->nPins )
+                continue;
+            if ( !memcmp( pGate2->pFunc, pGate->pFunc, sizeof(unsigned) * Abc_TruthWordNum(pGate->nPins) ) )
+                break;
+        }
+        if ( k < i )
+            continue;
+        Vec_PtrPush( vSelect, pGate );            
+    }
+    return vSelect;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Selects gates useful for area-only mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_LibPrintSelectedGates( Amap_Lib_t * p, int fAllGates )
+{
+    Vec_Ptr_t * vArray;
+    Amap_Gat_t * pGate;
+    int i;
+    vArray = fAllGates? p->vGates : p->vSelect;
+    Vec_PtrForEachEntry( Amap_Gat_t *, vArray, pGate, i )
+    {
+        printf( "%3d :%12s %d %9.2f  ", i, pGate->pName, pGate->nPins, pGate->dArea );
+        printf( "%4s=%40s  ", pGate->pOutName, pGate->pForm );
+        printf( "DSD: " );
+        Kit_DsdPrintFromTruth( pGate->pFunc, pGate->nPins );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses equations for the gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Lib_t * Amap_LibReadAndPrepare( char * pFileName, char * pBuffer, int fVerbose, int fVeryVerbose )
+{
+    Amap_Lib_t * p;
+    abctime clk = Abc_Clock();
+    if ( pBuffer == NULL )
+        p = Amap_LibReadFile( pFileName, fVerbose );
+    else
+    {
+        p = Amap_LibReadBuffer( pBuffer, fVerbose );
+        if ( p )
+            p->pName = Abc_UtilStrsav( pFileName );
+    }
+    if ( fVerbose )
+        printf( "Read %d gates from file \"%s\".\n", Vec_PtrSize(p->vGates), pFileName );
+    if ( p == NULL )
+        return NULL;
+    if ( !Amap_LibParseEquations( p, fVerbose ) )
+    {
+        Amap_LibFree( p );
+        return NULL;
+    }
+    p->vSorted = Amap_LibSortGatesByArea( p );
+    p->vSelect = Amap_LibSelectGates( p, fVerbose );
+    if ( fVerbose )
+    {
+        printf( "Selected %d functionally unique gates. ", Vec_PtrSize(p->vSelect) );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+//       Amap_LibPrintSelectedGates( p, 0 );
+    }
+    clk = Abc_Clock();
+    Amap_LibCreateRules( p, fVeryVerbose );
+    if ( fVerbose )
+    {
+        printf( "Created %d rules and %d matches. ", p->nNodes, p->nSets );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    return p;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/amap/amapLiberty.c b/abc-build/src/map/amap/amapLiberty.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/amap/amapLiberty.c
@@ -0,0 +1,1103 @@
+/**CFile****************************************************************
+
+  FileHead    [amapLiberty.c]
+
+  SystemHead  [ABC: Logic synthesis and verification system.]
+
+  PackageHead [Technology mapper for standard cells.]
+
+  Synopsis    [Liberty parser.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: amapLiberty.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define ABC_MAX_LIB_STR_LEN 5000
+
+// entry types
+typedef enum { 
+    AMAP_LIBERTY_NONE = 0,        // 0:  unknown
+    AMAP_LIBERTY_PROC,            // 1:  procedure :  key(head){body}
+    AMAP_LIBERTY_EQUA,            // 2:  equation  :  key:head;
+    AMAP_LIBERTY_LIST             // 3:  list      :  key(head) 
+} Amap_LibertyType_t;
+
+typedef struct Amap_Pair_t_ Amap_Pair_t;
+struct Amap_Pair_t_
+{
+    int             Beg;          // item beginning
+    int             End;          // item end
+};
+
+typedef struct Amap_Item_t_ Amap_Item_t;
+struct Amap_Item_t_
+{
+    int             Type;         // Amap_LibertyType_t
+    int             iLine;        // file line where the item's spec begins
+    Amap_Pair_t     Key;          // key part
+    Amap_Pair_t     Head;         // head part 
+    Amap_Pair_t     Body;         // body part
+    int             Next;         // next item in the list 
+    int             Child;        // first child item 
+};
+
+typedef struct Amap_Tree_t_ Amap_Tree_t;
+struct Amap_Tree_t_
+{
+    char *          pFileName;    // input Liberty file name
+    char *          pContents;    // file contents
+    int             nContents;    // file size
+    int             nLines;       // line counter
+    int             nItems;       // number of items
+    int             nItermAlloc;  // number of items allocated
+    Amap_Item_t *   pItems;       // the items
+    char *          pError;       // the error string
+};
+
+static inline Amap_Item_t *  Amap_LibertyRoot( Amap_Tree_t * p )                                       { return p->pItems;                                                 }
+static inline Amap_Item_t *  Amap_LibertyItem( Amap_Tree_t * p, int v )                                { assert( v < p->nItems ); return v < 0 ? NULL : p->pItems + v;     }
+static inline int            Amap_LibertyCompare( Amap_Tree_t * p, Amap_Pair_t Pair, char * pStr )     { return strncmp( p->pContents+Pair.Beg, pStr, Pair.End-Pair.Beg ); }
+static inline void           Amap_PrintWord( FILE * pFile, Amap_Tree_t * p, Amap_Pair_t Pair )         { char * pBeg = p->pContents+Pair.Beg, * pEnd = p->pContents+Pair.End; while ( pBeg < pEnd ) fputc( *pBeg++, pFile ); }
+static inline void           Amap_PrintSpace( FILE * pFile, int nOffset )                              { int i; for ( i = 0; i < nOffset; i++ ) fputc(' ', pFile);         }
+static inline int            Amap_LibertyItemId( Amap_Tree_t * p, Amap_Item_t * pItem )                { return pItem - p->pItems;                                         }
+
+#define Amap_ItemForEachChild( p, pItem, pChild ) \
+    for ( pChild = Amap_LibertyItem(p, pItem->Child); pChild; pChild = Amap_LibertyItem(p, pChild->Next) )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Prints parse tree in Liberty format.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_LibertyPrintLibertyItem( FILE * pFile, Amap_Tree_t * p, Amap_Item_t * pItem, int nOffset )
+{
+    if ( pItem->Type == AMAP_LIBERTY_PROC )
+    {
+        Amap_PrintSpace( pFile, nOffset );
+        Amap_PrintWord( pFile, p, pItem->Key );
+        fprintf( pFile, "(" );
+        Amap_PrintWord( pFile, p, pItem->Head );
+        fprintf( pFile, ") {\n" );
+        if ( Amap_LibertyItem(p, pItem->Child) )
+            Amap_LibertyPrintLibertyItem( pFile, p, Amap_LibertyItem(p, pItem->Child), nOffset + 1 );
+        Amap_PrintSpace( pFile, nOffset );
+        fprintf( pFile, "}\n" );
+    }
+    else if ( pItem->Type == AMAP_LIBERTY_EQUA )
+    {
+        Amap_PrintSpace( pFile, nOffset );
+        Amap_PrintWord( pFile, p, pItem->Key );
+        fprintf( pFile, " : " );
+        Amap_PrintWord( pFile, p, pItem->Head );
+        fprintf( pFile, ";\n" );
+    }
+    else if ( pItem->Type == AMAP_LIBERTY_LIST )
+    {
+        Amap_PrintSpace( pFile, nOffset );
+        Amap_PrintWord( pFile, p, pItem->Key );
+        fprintf( pFile, "(" );
+        Amap_PrintWord( pFile, p, pItem->Head );
+        fprintf( pFile, ");\n" );
+    }
+    else assert( 0 );
+    if ( Amap_LibertyItem(p, pItem->Next) )
+        Amap_LibertyPrintLibertyItem( pFile, p, Amap_LibertyItem(p, pItem->Next), nOffset );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints parse tree in Liberty format.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_LibertyPrintLiberty( Amap_Tree_t * p, char * pFileName )
+{
+    FILE * pFile;
+    if ( pFileName == NULL )
+        pFile = stdout;
+    else
+    {
+        pFile = fopen( pFileName, "w" );
+        if ( pFile == NULL )
+        {
+            printf( "Amap_LibertyPrintLiberty(): The output file is unavailable (absent or open).\n" );
+            return 0;
+        }
+    }
+    Amap_LibertyPrintLibertyItem( pFile, p, Amap_LibertyRoot(p), 0 );
+    if ( pFile != stdout )
+        fclose( pFile );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the time stamp.]
+
+  Description [The file should be closed.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Amap_LibertyTimeStamp()
+{
+    static char Buffer[100];
+	char * TimeStamp;
+	time_t ltime;
+    // get the current time
+	time( &ltime );
+	TimeStamp = asctime( localtime( &ltime ) );
+	TimeStamp[ strlen(TimeStamp) - 1 ] = 0;
+    assert( strlen(TimeStamp) < 100 );
+    strcpy( Buffer, TimeStamp );
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns cell's function.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_LibertyCellIsFlop( Amap_Tree_t * p, Amap_Item_t * pCell )
+{
+    Amap_Item_t * pAttr;
+    Amap_ItemForEachChild( p, pCell, pAttr )
+        if ( !Amap_LibertyCompare(p, pAttr->Key, "ff") ||
+             !Amap_LibertyCompare(p, pAttr->Key, "latch") )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns pin's function.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Item_t * Amap_LibertyPinFunction( Amap_Tree_t * p, Amap_Item_t * pPin )
+{
+    Amap_Item_t * pFunc;
+    Amap_ItemForEachChild( p, pPin, pFunc )
+        if ( !Amap_LibertyCompare(p, pFunc->Key, "function") )
+            return pFunc;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns output pin(s).]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Item_t * Amap_LibertyCellOutput( Amap_Tree_t * p, Amap_Item_t * pCell )
+{
+    Amap_Item_t * pPin;
+    Amap_ItemForEachChild( p, pCell, pPin )
+    {
+        if ( Amap_LibertyCompare(p, pPin->Key, "pin") )
+            continue;
+        if ( Amap_LibertyPinFunction(p, pPin) )
+            return pPin;
+    }
+    return NULL;
+}
+Vec_Ptr_t * Amap_LibertyCellOutputs( Amap_Tree_t * p, Amap_Item_t * pCell )
+{
+    Amap_Item_t * pPin;
+    Vec_Ptr_t * vOutPins;
+    vOutPins = Vec_PtrAlloc( 2 );
+    Amap_ItemForEachChild( p, pCell, pPin )
+    {
+        if ( Amap_LibertyCompare(p, pPin->Key, "pin") )
+            continue;
+        if ( Amap_LibertyPinFunction(p, pPin) )
+            Vec_PtrPush( vOutPins, pPin );
+    }
+    return vOutPins;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns cell's area.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Item_t * Amap_LibertyCellArea( Amap_Tree_t * p, Amap_Item_t * pCell )
+{
+    Amap_Item_t * pArea;
+    Amap_ItemForEachChild( p, pCell, pArea )
+    {
+        if ( Amap_LibertyCompare(p, pArea->Key, "area") )
+            continue;
+        return pArea;
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count cell's output pins (pins with a logic function).]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_LibertyCellCountOutputs( Amap_Tree_t * p, Amap_Item_t * pCell )
+{
+    Amap_Item_t * pPin;
+    int Counter = 0;
+    Amap_ItemForEachChild( p, pCell, pPin )
+    {
+        if ( Amap_LibertyCompare(p, pPin->Key, "pin") )
+            continue;
+        if ( Amap_LibertyPinFunction(p, pPin) )
+            Counter++;
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gets the name to write.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Amap_LibertyGetString( Amap_Tree_t * p, Amap_Pair_t Pair )   
+{ 
+    static char Buffer[ABC_MAX_LIB_STR_LEN]; 
+    assert( Pair.End-Pair.Beg < ABC_MAX_LIB_STR_LEN );
+    strncpy( Buffer, p->pContents+Pair.Beg, Pair.End-Pair.Beg ); 
+    Buffer[Pair.End-Pair.Beg] = 0;
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gets the name to write.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Amap_LibertyGetStringFormula( Amap_Tree_t * p, Amap_Pair_t Pair )   
+{ 
+    static char Buffer[ABC_MAX_LIB_STR_LEN]; 
+    assert( Pair.End-Pair.Beg-2 < ABC_MAX_LIB_STR_LEN );
+    strncpy( Buffer, p->pContents+Pair.Beg+1, Pair.End-Pair.Beg-2 ); 
+    Buffer[Pair.End-Pair.Beg-2] = 0;
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints parse tree in Genlib format.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_LibertyPrintGenlib( Amap_Tree_t * p, char * pFileName, int fVerbose )
+{
+    FILE * pFile;
+    Vec_Ptr_t * vOutputs;
+    Amap_Item_t * pCell, * pArea, * pFunc, * pPin, * pOutput;
+    char * pForm;
+    int i, Counter;
+    if ( pFileName == NULL )
+        pFile = stdout;
+    else
+    {
+        pFile = fopen( pFileName, "w" );
+        if ( pFile == NULL )
+        {
+            printf( "Amap_LibertyPrintGenlib(): The output file is unavailable (absent or open).\n" );
+            return 0;
+        }
+    }
+    fprintf( pFile, "# This Genlib file was generated by ABC on %s\n", Amap_LibertyTimeStamp() );
+    fprintf( pFile, "# The standard cell library \"%s\" is from Liberty file \"%s\"\n", Amap_LibertyGetString(p, Amap_LibertyRoot(p)->Head), p->pFileName );
+    fprintf( pFile, "# (To find out more about Genlib format, google for \"sis_paper.ps\")\n" );
+
+    fprintf( pFile, "GATE  " );
+    fprintf( pFile, "%16s  ", "_const0_" );
+    fprintf( pFile, "%f  ",   0.0 );
+    fprintf( pFile, "%s=",    "z" );
+    fprintf( pFile, "%s;\n",  "CONST0" );
+
+    fprintf( pFile, "GATE  " );
+    fprintf( pFile, "%16s  ", "_const1_" );
+    fprintf( pFile, "%f  ",   0.0 );
+    fprintf( pFile, "%s=",    "z" );
+    fprintf( pFile, "%s;\n",  "CONST1" );
+
+    Amap_ItemForEachChild( p, Amap_LibertyRoot(p), pCell )
+    {
+/*
+    if ( strcmp(Amap_LibertyGetString(p, pCell->Head), "HA1SVTX1") == 0 )
+    {
+        int s = 0;
+    }
+*/
+        if ( Amap_LibertyCompare(p, pCell->Key, "cell") )
+            continue;
+        if ( Amap_LibertyCellIsFlop(p, pCell) )
+        {
+            if ( fVerbose )
+                printf( "Amap_LibertyPrintGenlib() skipped sequential cell \"%s\".\n", Amap_LibertyGetString(p, pCell->Head) );
+            continue;
+        }
+        Counter = Amap_LibertyCellCountOutputs( p, pCell );
+        if ( Counter == 0 )
+        {
+            if ( fVerbose )
+                printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" without logic function.\n", Amap_LibertyGetString(p, pCell->Head) );
+            continue;
+        }
+/*
+        if ( Counter > 1 )
+        {
+            if ( fVerbose )
+                printf( "Amap_LibertyPrintGenlib() skipped multi-output cell \"%s\".\n", Amap_LibertyGetString(p, pCell->Head) );
+            continue;
+        }
+*/
+        pArea = Amap_LibertyCellArea( p, pCell );
+        if ( pArea == NULL )
+        {
+            if ( fVerbose )
+                printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" with unspecified area.\n", Amap_LibertyGetString(p, pCell->Head) );
+            continue;
+        }
+//        pOutput = Amap_LibertyCellOutput( p, pCell );
+        vOutputs = Amap_LibertyCellOutputs( p, pCell );
+        Vec_PtrForEachEntry( Amap_Item_t *, vOutputs, pOutput, i )
+        {
+            pFunc   = Amap_LibertyPinFunction( p, pOutput );
+            pForm   = Amap_LibertyGetStringFormula( p, pFunc->Head );
+            if ( !strcmp(pForm, "0") || !strcmp(pForm, "1") )
+            {
+                if ( fVerbose )
+                    printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" with constant formula \"%s\".\n", Amap_LibertyGetString(p, pCell->Head), pForm );
+                continue;
+            }
+            fprintf( pFile, "GATE  " );
+            fprintf( pFile, "%16s  ", Amap_LibertyGetString(p, pCell->Head) );
+            fprintf( pFile, "%f  ",   atof(Amap_LibertyGetString(p, pArea->Head)) );
+            fprintf( pFile, "%s=",    Amap_LibertyGetString(p, pOutput->Head) );
+            fprintf( pFile, "%s;\n",  Amap_LibertyGetStringFormula(p, pFunc->Head) );
+            Amap_ItemForEachChild( p, pCell, pPin )
+                if ( Vec_PtrFind(vOutputs, pPin) == -1 && !Amap_LibertyCompare(p, pPin->Key, "pin") )
+                    fprintf( pFile, "    PIN  %13s  UNKNOWN  1  999  1.00  0.00  1.00  0.00\n", Amap_LibertyGetString(p, pPin->Head) );
+        }
+        Vec_PtrFree( vOutputs );
+    }
+    if ( pFile != stdout )
+        fclose( pFile );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints parse tree in Genlib format.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Amap_LibertyPrintGenlibStr( Amap_Tree_t * p, int fVerbose )
+{
+    Vec_Str_t * vStr;
+    char Buffer[100];
+    Vec_Ptr_t * vOutputs;
+    Amap_Item_t * pCell, * pArea, * pFunc, * pPin, * pOutput;
+    int i, Counter;
+    char * pForm;
+
+    vStr = Vec_StrAlloc( 1000 );
+
+    Vec_StrPrintStr( vStr, "GATE          _const0_  0.000000  z=CONST0;\n" );
+    Vec_StrPrintStr( vStr, "GATE          _const1_  0.000000  z=CONST1;\n" );
+    Amap_ItemForEachChild( p, Amap_LibertyRoot(p), pCell )
+    {
+        if ( Amap_LibertyCompare(p, pCell->Key, "cell") )
+            continue;
+        if ( Amap_LibertyCellIsFlop(p, pCell) )
+        {
+            if ( fVerbose )
+                printf( "Amap_LibertyPrintGenlib() skipped sequential cell \"%s\".\n", Amap_LibertyGetString(p, pCell->Head) );
+            continue;
+        }
+        Counter = Amap_LibertyCellCountOutputs( p, pCell );
+        if ( Counter == 0 )
+        {
+            if ( fVerbose )
+                printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" without logic function.\n", Amap_LibertyGetString(p, pCell->Head) );
+            continue;
+        }
+        pArea = Amap_LibertyCellArea( p, pCell );
+        if ( pArea == NULL )
+        {
+            if ( fVerbose )
+                printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" with unspecified area.\n", Amap_LibertyGetString(p, pCell->Head) );
+            continue;
+        }
+        vOutputs = Amap_LibertyCellOutputs( p, pCell );
+        Vec_PtrForEachEntry( Amap_Item_t *, vOutputs, pOutput, i )
+        {
+            pFunc   = Amap_LibertyPinFunction( p, pOutput );
+            pForm   = Amap_LibertyGetStringFormula( p, pFunc->Head );
+            if ( !strcmp(pForm, "0") || !strcmp(pForm, "1") )
+            {
+                if ( fVerbose )
+                    printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" with constant formula \"%s\".\n", Amap_LibertyGetString(p, pCell->Head), pForm );
+                continue;
+            }
+/*
+            fprintf( pFile, "GATE  " );
+            fprintf( pFile, "%16s  ", Amap_LibertyGetString(p, pCell->Head) );
+            fprintf( pFile, "%f  ",   atof(Amap_LibertyGetString(p, pArea->Head)) );
+            fprintf( pFile, "%s=",    Amap_LibertyGetString(p, pOutput->Head) );
+            fprintf( pFile, "%s;\n",  Amap_LibertyGetStringFormula(p, pFunc->Head) );
+            Amap_ItemForEachChild( p, pCell, pPin )
+                if ( Vec_PtrFind(vOutputs, pPin) == -1 && !Amap_LibertyCompare(p, pPin->Key, "pin") )
+                    fprintf( pFile, "    PIN  %13s  UNKNOWN  1  999  1.00  0.00  1.00  0.00\n", Amap_LibertyGetString(p, pPin->Head) );
+*/
+            Vec_StrPrintStr( vStr, "GATE " );
+            Vec_StrPrintStr( vStr, Amap_LibertyGetString(p, pCell->Head) );
+            Vec_StrPrintStr( vStr, " " );
+            sprintf( Buffer, "%f", atof(Amap_LibertyGetString(p, pArea->Head)) );
+            Vec_StrPrintStr( vStr, Buffer );
+            Vec_StrPrintStr( vStr, " " );
+            Vec_StrPrintStr( vStr, Amap_LibertyGetString(p, pOutput->Head) );
+            Vec_StrPrintStr( vStr, "=" );
+            Vec_StrPrintStr( vStr, Amap_LibertyGetStringFormula(p, pFunc->Head) );
+            Vec_StrPrintStr( vStr, ";\n" );
+            Amap_ItemForEachChild( p, pCell, pPin )
+                if ( Vec_PtrFind(vOutputs, pPin) == -1 && !Amap_LibertyCompare(p, pPin->Key, "pin") )
+                {
+                    Vec_StrPrintStr( vStr, "  PIN " );
+                    Vec_StrPrintStr( vStr, Amap_LibertyGetString(p, pPin->Head) );
+                    Vec_StrPrintStr( vStr, " UNKNOWN  1  999  1.00  0.00  1.00  0.00\n" );
+                }
+        }
+        Vec_PtrFree( vOutputs );
+    }
+    Vec_StrPrintStr( vStr, "\n.end\n" );
+    Vec_StrPush( vStr, '\0' );
+//    printf( "%s", Vec_StrArray(vStr) );
+    return vStr;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the file size.]
+
+  Description [The file should be closed.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_LibertyFileSize( char * pFileName )
+{
+    FILE * pFile;
+    int nFileSize;
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Amap_LibertyFileSize(): The input file is unavailable (absent or open).\n" );
+        return 0;
+    }
+    fseek( pFile, 0, SEEK_END );  
+    nFileSize = ftell( pFile ); 
+    fclose( pFile );
+    return nFileSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_LibertyFixFileHead( char * pFileName )
+{
+    char * pHead;
+    for ( pHead = pFileName; *pHead; pHead++ )
+        if ( *pHead == '>' )
+            *pHead = '\\';
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_LibertyCountItems( char * pBeg, char * pEnd )
+{
+    int Counter = 0;
+    for ( ; pBeg < pEnd; pBeg++ )
+        Counter += (*pBeg == '(' || *pBeg == ':');
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes C-style comments.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_LibertyWipeOutComments( char * pBeg, char * pEnd )
+{
+    char * pCur, * pStart;
+    for ( pCur = pBeg; pCur < pEnd; pCur++ )
+    if ( pCur[0] == '/' && pCur[1] == '*' )
+        for ( pStart = pCur; pCur < pEnd; pCur++ )
+        if ( pCur[0] == '*' && pCur[1] == '/' )
+        {
+            for ( ; pStart < pCur + 2; pStart++ )
+            if ( *pStart != '\n' ) *pStart = ' ';
+            break;
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the character is space.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Amap_LibertyCharIsSpace( char c )
+{
+    return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\\';
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Skips spaces.]
+
+  Description [Returns 1 if reached the end.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Amap_LibertySkipSpaces( Amap_Tree_t * p, char ** ppPos, char * pEnd, int fStopAtNewLine )
+{
+    char * pPos = *ppPos;
+    for ( ; pPos < pEnd; pPos++ )
+    {
+        if ( *pPos == '\n' )
+        {
+            p->nLines++;
+            if ( fStopAtNewLine )
+                break;
+        }        
+        if ( !Amap_LibertyCharIsSpace(*pPos) )
+            break;
+    }
+    *ppPos = pPos;
+    return pPos == pEnd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Skips entry delimited by " :;(){}" ]
+
+  Description [Returns 1 if reached the end.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Amap_LibertySkipEntry( char ** ppPos, char * pEnd )
+{
+    char * pPos = *ppPos;
+    if ( *pPos == '\"' )
+    {
+        for ( pPos++; pPos < pEnd; pPos++ )
+            if ( *pPos == '\"' )
+            {
+                pPos++;
+                break;
+            }
+    }
+    else
+    {
+        for ( ; pPos < pEnd; pPos++ )
+            if ( *pPos == ' ' || *pPos == '\r' || *pPos == '\n' || *pPos == '\t' ||
+                 *pPos == ':' || *pPos == ';'  || 
+                 *pPos == '(' || *pPos == ')'  || 
+                 *pPos == '{' || *pPos == '}' )
+                break;
+    }
+    *ppPos = pPos;
+    return pPos == pEnd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the matching closing symbol.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline char * Amap_LibertyFindMatch( char * pPos, char * pEnd )
+{
+    int Counter = 0;
+    assert( *pPos == '(' || *pPos == '{' );
+    if ( *pPos == '(' )
+    {
+        for ( ; pPos < pEnd; pPos++ )
+        {
+            if ( *pPos == '(' )
+                Counter++;
+            if ( *pPos == ')' )
+                Counter--;
+            if ( Counter == 0 )
+                break;
+        }
+    }
+    else
+    {
+        for ( ; pPos < pEnd; pPos++ )
+        {
+            if ( *pPos == '{' )
+                Counter++;
+            if ( *pPos == '}' )
+                Counter--;
+            if ( Counter == 0 )
+                break;
+        }
+    }
+    assert( *pPos == ')' || *pPos == '}' );
+    return pPos;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the matching closing symbol.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Amap_Pair_t Amap_LibertyUpdateHead( Amap_Tree_t * p, Amap_Pair_t Head )
+{
+    Amap_Pair_t Res;
+    char * pBeg = p->pContents + Head.Beg;
+    char * pEnd = p->pContents + Head.End;
+    char * pFirstNonSpace = NULL;
+    char * pLastNonSpace = NULL;
+    char * pChar;
+    for ( pChar = pBeg; pChar < pEnd; pChar++ )
+    {
+        if ( *pChar == '\n' )
+            p->nLines++;
+        if ( Amap_LibertyCharIsSpace(*pChar) )
+            continue;
+        pLastNonSpace = pChar;
+        if ( pFirstNonSpace == NULL )
+            pFirstNonSpace = pChar;
+    }
+    if ( pFirstNonSpace == NULL || pLastNonSpace == NULL )
+        return Head;
+    assert( pFirstNonSpace && pLastNonSpace );
+    Res.Beg = pFirstNonSpace - p->pContents;
+    Res.End = pLastNonSpace  - p->pContents + 1;
+    return Res;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns free item.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Amap_Item_t * Amap_LibertyNewItem( Amap_Tree_t * p, int Type )
+{
+    p->pItems[p->nItems].iLine = p->nLines;
+    p->pItems[p->nItems].Type  = Type;
+    p->pItems[p->nItems].Child = -1;
+    p->pItems[p->nItems].Next  = -1;
+    return p->pItems + p->nItems++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns free item.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_LibertyBuildItem( Amap_Tree_t * p, char ** ppPos, char * pEnd )
+{
+    Amap_Item_t * pItem;
+    Amap_Pair_t Key, Head, Body;
+    char * pNext, * pStop;
+    Key.End = 0;
+    if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
+        return -2;
+    Key.Beg = *ppPos - p->pContents;
+    if ( Amap_LibertySkipEntry( ppPos, pEnd ) )
+        goto exit;
+    Key.End = *ppPos - p->pContents;
+    if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
+        goto exit;
+    pNext = *ppPos;
+    if ( *pNext == ':' )
+    {
+        *ppPos = pNext + 1;
+        if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
+            goto exit;
+        Head.Beg = *ppPos - p->pContents;
+        if ( Amap_LibertySkipEntry( ppPos, pEnd ) )
+            goto exit;
+        Head.End = *ppPos - p->pContents;
+        if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 1 ) )
+            goto exit;
+        pNext = *ppPos;
+        if ( *pNext != ';' && *pNext != '\n' )
+            goto exit;
+        *ppPos = pNext + 1;
+        // end of equation
+        pItem = Amap_LibertyNewItem( p, AMAP_LIBERTY_EQUA );
+        pItem->Key  = Key;
+        pItem->Head = Amap_LibertyUpdateHead( p, Head );
+        pItem->Next = Amap_LibertyBuildItem( p, ppPos, pEnd );
+        if ( pItem->Next == -1 )
+            goto exit;
+        return Amap_LibertyItemId( p, pItem );
+    }
+    if ( *pNext == '(' )
+    {
+        pStop = Amap_LibertyFindMatch( pNext, pEnd );
+        Head.Beg = pNext - p->pContents + 1;
+        Head.End = pStop - p->pContents;
+        *ppPos = pStop + 1;
+        if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
+        {
+            // end of list
+            pItem = Amap_LibertyNewItem( p, AMAP_LIBERTY_LIST );
+            pItem->Key  = Key;
+            pItem->Head = Amap_LibertyUpdateHead( p, Head );
+            return Amap_LibertyItemId( p, pItem );
+        }
+        pNext = *ppPos;
+        if ( *pNext == '{' ) // beginning of body
+        {
+            pStop = Amap_LibertyFindMatch( pNext, pEnd );
+            Body.Beg = pNext - p->pContents + 1;
+            Body.End = pStop - p->pContents;
+            // end of body
+            pItem = Amap_LibertyNewItem( p, AMAP_LIBERTY_PROC );
+            pItem->Key  = Key;
+            pItem->Head = Amap_LibertyUpdateHead( p, Head );
+            pItem->Body = Body;
+            *ppPos = pNext + 1;
+            pItem->Child = Amap_LibertyBuildItem( p, ppPos, pStop );
+            if ( pItem->Child == -1 )
+                goto exit;
+            *ppPos = pStop + 1;
+            pItem->Next = Amap_LibertyBuildItem( p, ppPos, pEnd );
+            if ( pItem->Next == -1 )
+                goto exit;
+            return Amap_LibertyItemId( p, pItem );
+        }
+        // end of list
+        if ( *pNext == ';' )
+            *ppPos = pNext + 1;
+        pItem = Amap_LibertyNewItem( p, AMAP_LIBERTY_LIST );
+        pItem->Key  = Key;
+        pItem->Head = Amap_LibertyUpdateHead( p, Head );
+        pItem->Next = Amap_LibertyBuildItem( p, ppPos, pEnd );
+        if ( pItem->Next == -1 )
+            goto exit;
+        return Amap_LibertyItemId( p, pItem );
+    }
+exit:
+    if ( p->pError == NULL )
+    {
+        p->pError = ABC_ALLOC( char, 1000 );
+        sprintf( p->pError, "File \"%s\". Line %6d. Failed to parse entry \"%s\".\n", 
+            p->pFileName, p->nLines, Amap_LibertyGetString(p, Key) );
+    }
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the parsing manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Tree_t * Amap_LibertyStart( char * pFileName )
+{
+    FILE * pFile;
+    Amap_Tree_t * p;
+    int RetValue;
+    // start the manager
+    p = ABC_ALLOC( Amap_Tree_t, 1 );
+    memset( p, 0, sizeof(Amap_Tree_t) );
+    // read the file into the buffer
+    Amap_LibertyFixFileHead( pFileName );
+    p->nContents = Amap_LibertyFileSize( pFileName );
+    if ( p->nContents == 0 )
+    {
+        ABC_FREE( p );
+        return NULL;
+    }
+    pFile = fopen( pFileName, "rb" );
+    p->pContents = ABC_ALLOC( char, p->nContents+1 );
+    RetValue = fread( p->pContents, p->nContents, 1, pFile );
+    fclose( pFile );
+    p->pContents[p->nContents] = 0;
+    // other 
+    p->pFileName = Abc_UtilStrsav( pFileName );
+    p->nItermAlloc = 10 + Amap_LibertyCountItems( p->pContents, p->pContents+p->nContents );
+    p->pItems = ABC_CALLOC( Amap_Item_t, p->nItermAlloc );
+    p->nItems = 0;
+    p->nLines = 1;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the parsing manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_LibertyStop( Amap_Tree_t * p )
+{
+    ABC_FREE( p->pFileName );
+    ABC_FREE( p->pContents );
+    ABC_FREE( p->pItems );
+    ABC_FREE( p->pError );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the standard cell library in Liberty format.]
+
+  Description [Writes the resulting file in Genlib format.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_LibertyParse( char * pFileName, int fVerbose )
+{
+    Amap_Tree_t * p;
+    char * pPos;
+    abctime clk = Abc_Clock();
+    int RetValue;
+    p = Amap_LibertyStart( pFileName );
+    if ( p == NULL )
+        return 0;
+    pPos = p->pContents;
+    Amap_LibertyWipeOutComments( p->pContents, p->pContents+p->nContents );
+    if ( Amap_LibertyBuildItem( p, &pPos, p->pContents + p->nContents ) == 0 )
+    {
+        if ( fVerbose )
+        printf( "Parsing finished successfully.\n" );
+//        Amap_LibertyPrintLiberty( p, "temp_.lib" );
+        Amap_LibertyPrintGenlib( p, Extra_FileNameGenericAppend(pFileName, ".genlib"), fVerbose );
+        RetValue = 1;
+    }
+    else
+    {
+        if ( p->pError )
+            printf( "%s", p->pError );
+        if ( fVerbose )
+        printf( "Parsing failed.\n" );
+        RetValue = 0;
+    }
+    if ( fVerbose )
+    {
+    printf( "Memory = %7.2f MB. ", 1.0*(p->nContents+p->nItermAlloc*sizeof(Amap_Item_t))/(1<<20) );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    Amap_LibertyStop( p );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the standard cell library in Liberty format.]
+
+  Description [Writes the resulting file in Genlib format.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Amap_LibertyParseStr( char * pFileName, int fVerbose )
+{
+    Amap_Tree_t * p;
+    Vec_Str_t * vStr = NULL;
+    char * pPos;
+    abctime clk = Abc_Clock();
+    int RetValue;
+    p = Amap_LibertyStart( pFileName );
+    if ( p == NULL )
+        return 0;
+    pPos = p->pContents;
+    Amap_LibertyWipeOutComments( p->pContents, p->pContents+p->nContents );
+    if ( Amap_LibertyBuildItem( p, &pPos, p->pContents + p->nContents ) == 0 )
+    {
+        if ( fVerbose )
+        printf( "Parsing finished successfully.\n" );
+//        Amap_LibertyPrintLiberty( p, "temp_.lib" );
+        vStr = Amap_LibertyPrintGenlibStr( p, fVerbose );
+        RetValue = 1;
+    }
+    else
+    {
+        if ( p->pError )
+            printf( "%s", p->pError );
+        if ( fVerbose )
+        printf( "Parsing failed.\n" );
+        RetValue = 0;
+    }
+    if ( fVerbose )
+    {
+    printf( "Memory = %7.2f MB. ", 1.0*(p->nContents+p->nItermAlloc*sizeof(Amap_Item_t))/(1<<20) );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    Amap_LibertyStop( p );
+    return vStr;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/amap/amapMan.c b/abc-build/src/map/amap/amapMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/amap/amapMan.c
@@ -0,0 +1,104 @@
+/**CFile****************************************************************
+
+  FileName    [amapMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Technology mapper for standard cells.]
+
+  Synopsis    [Mapping manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: amapMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Man_t * Amap_ManStart( int nNodes )
+{
+    Amap_Man_t * p;
+    // start the manager
+    p = ABC_ALLOC( Amap_Man_t, 1 );
+    memset( p, 0, sizeof(Amap_Man_t) );
+    p->fEpsilonInternal = (float)0.01;
+    // allocate arrays for nodes
+    p->vPis    = Vec_PtrAlloc( 100 );
+    p->vPos    = Vec_PtrAlloc( 100 );
+    p->vObjs   = Vec_PtrAlloc( 100 );
+    p->vTemp   = Vec_IntAlloc( 100 );
+    p->vCuts0  = Vec_PtrAlloc( 100 );
+    p->vCuts1  = Vec_PtrAlloc( 100 );
+    p->vCuts2  = Vec_PtrAlloc( 100 );
+    // prepare the memory manager
+    p->pMemObj = Aig_MmFixedStart( sizeof(Amap_Obj_t), nNodes );
+    p->pMemCuts = Aig_MmFlexStart();
+    p->pMemCutBest = Aig_MmFlexStart();
+    p->pMemTemp = Aig_MmFlexStart();
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_ManStop( Amap_Man_t * p )
+{
+    Vec_PtrFree( p->vPis );
+    Vec_PtrFree( p->vPos );
+    Vec_PtrFree( p->vObjs );
+    Vec_PtrFree( p->vCuts0 );
+    Vec_PtrFree( p->vCuts1 );
+    Vec_PtrFree( p->vCuts2 );
+    Vec_IntFree( p->vTemp );
+    Aig_MmFixedStop( p->pMemObj, 0 );
+    Aig_MmFlexStop( p->pMemCuts, 0 );
+    Aig_MmFlexStop( p->pMemCutBest, 0 );
+    Aig_MmFlexStop( p->pMemTemp, 0 );
+    ABC_FREE( p->pMatsTemp );
+    ABC_FREE( p->ppCutsTemp );
+    ABC_FREE( p->pCutsPi );
+    ABC_FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/amap/amapMatch.c b/abc-build/src/map/amap/amapMatch.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/amap/amapMatch.c
@@ -0,0 +1,616 @@
+/**CFile****************************************************************
+
+  FileName    [amapMatch.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Technology mapper for standard cells.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: amapMatch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the cut using new memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Cut_t * Amap_ManDupCut( Amap_Man_t * p, Amap_Cut_t * pCut )
+{
+    Amap_Cut_t * pNew;
+    int nBytes = sizeof(Amap_Cut_t) + sizeof(int) * pCut->nFans;
+    pNew = (Amap_Cut_t *)Aig_MmFlexEntryFetch( p->pMemCutBest, nBytes );
+    memcpy( pNew, pCut, nBytes );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the match with cut and set.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Amap_ManMatchStart( Amap_Mat_t * p, Amap_Cut_t * pCut, Amap_Set_t * pSet )
+{
+    memset( p, 0, sizeof(Amap_Mat_t) );
+    p->pCut = pCut;
+    p->pSet = pSet;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans reference counters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_ManCleanRefs( Amap_Man_t * p )
+{
+    Amap_Obj_t * pObj;
+    int i;
+    Amap_ManForEachObj( p, pObj, i )
+        pObj->nFouts[0] = pObj->nFouts[1] = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes delay.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Amap_ManMaxDelay( Amap_Man_t * p )
+{
+    Amap_Obj_t * pObj;
+    float Delay = 0.0;
+    int i;
+    Amap_ManForEachPo( p, pObj, i )
+        Delay = Abc_MaxInt( Delay, Amap_ObjFanin0(p,pObj)->Best.Delay );
+    return Delay;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans reference counters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_ManCleanData( Amap_Man_t * p )
+{
+    Amap_Obj_t * pObj;
+    int i;
+//    Amap_ManForEachNode( p, pObj, i )
+//        ABC_FREE( pObj->pData );
+    Amap_ManForEachObj( p, pObj, i )
+        pObj->pData = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute nodes used in the mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Amap_ManComputeMapping_rec( Amap_Man_t * p, Amap_Obj_t * pObj, int fCompl )
+{
+    Amap_Mat_t * pM = &pObj->Best;
+    Amap_Obj_t * pFanin;
+    Amap_Gat_t * pGate;
+    int i, iFanin, fComplFanin;
+    float Area;
+    if ( pObj->nFouts[fCompl]++ + pObj->nFouts[!fCompl] > 0 )
+        return 0.0;
+    if ( Amap_ObjIsPi(pObj) || Amap_ObjIsConst1(pObj) )
+        return 0.0;
+    pGate = Amap_LibGate( p->pLib, pM->pSet->iGate );
+    assert( pGate->nPins == pM->pCut->nFans );
+    Area = pGate->dArea;
+    for ( i = 0; i < (int)pGate->nPins; i++ )
+    {
+        iFanin = Abc_Lit2Var( pM->pSet->Ins[i] );
+        pFanin = Amap_ManObj( p, Abc_Lit2Var(pM->pCut->Fans[iFanin]) );
+        fComplFanin = Abc_LitIsCompl( pM->pSet->Ins[i] ) ^ Abc_LitIsCompl( pM->pCut->Fans[iFanin] );
+        Area += Amap_ManComputeMapping_rec( p, pFanin, fComplFanin );
+    }
+    return Area;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute nodes used in the mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Amap_ManComputeMapping( Amap_Man_t * p )
+{
+    Amap_Obj_t * pObj;
+    float Area = 0.0;
+    int i;
+    Amap_ManCleanRefs( p );
+    Amap_ManForEachPo( p, pObj, i )
+        Area += Amap_ManComputeMapping_rec( p, Amap_ObjFanin0(p, pObj), Amap_ObjFaninC0(pObj) );
+    return Area;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of inverters to be added.]
+
+  Description [Should be called after mapping has been set.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_ManCountInverters( Amap_Man_t * p )
+{
+    Amap_Obj_t * pObj;
+    int i, Counter = 0;
+    Amap_ManForEachObj( p, pObj, i )
+        Counter += (int)(pObj->nFouts[!pObj->fPolar] > 0);
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compare two matches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Amap_CutCompareDelay( Amap_Man_t * p, Amap_Mat_t * pM0, Amap_Mat_t * pM1 )
+{
+    // compare delay
+    if ( pM0->Delay < pM1->Delay - p->pPars->fEpsilon )
+        return -1;
+    if ( pM0->Delay > pM1->Delay + p->pPars->fEpsilon )
+        return 1;
+
+    // compare area flows
+    if ( pM0->Area < pM1->Area - p->pPars->fEpsilon )
+        return -1;
+    if ( pM0->Area > pM1->Area + p->pPars->fEpsilon )
+        return 1;
+
+    // compare average fanouts
+    if ( pM0->AveFan > pM1->AveFan - p->pPars->fEpsilon )
+        return -1;
+    if ( pM0->AveFan < pM1->AveFan + p->pPars->fEpsilon )
+        return 1;
+    return 1;
+}
+static inline int Amap_CutCompareArea( Amap_Man_t * p, Amap_Mat_t * pM0, Amap_Mat_t * pM1 )
+{
+    // compare area flows
+    if ( pM0->Area < pM1->Area - p->pPars->fEpsilon )
+        return -1;
+    if ( pM0->Area > pM1->Area + p->pPars->fEpsilon )
+        return 1;
+
+    // compare average fanouts
+    if ( pM0->AveFan > pM1->AveFan - p->pPars->fEpsilon )
+        return -1;
+    if ( pM0->AveFan < pM1->AveFan + p->pPars->fEpsilon )
+        return 1;
+
+    // compare delay
+    if ( pM0->Delay < pM1->Delay - p->pPars->fEpsilon )
+        return -1;
+    if ( pM0->Delay > pM1->Delay + p->pPars->fEpsilon )
+        return 1;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts area while dereferencing the match.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline float Amap_CutAreaDeref( Amap_Man_t * p, Amap_Mat_t * pM )
+{
+    Amap_Obj_t * pFanin;
+    int i, fCompl;
+    float Area = Amap_LibGate( p->pLib, pM->pSet->iGate )->dArea;
+    Amap_MatchForEachFaninCompl( p, pM, pFanin, fCompl, i )
+    {
+        assert( Amap_ObjRefsTotal(pFanin) > 0 );
+        if ( (int)pFanin->fPolar != fCompl && pFanin->nFouts[fCompl] == 1 )
+            Area += p->fAreaInv;
+        if ( --pFanin->nFouts[fCompl] + pFanin->nFouts[!fCompl] == 0 && Amap_ObjIsNode(pFanin) )
+            Area += Amap_CutAreaDeref( p, &pFanin->Best );
+    }
+    return Area;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts area while referencing the match.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline float Amap_CutAreaRef( Amap_Man_t * p, Amap_Mat_t * pM )
+{
+    Amap_Obj_t * pFanin;
+    int i, fCompl;
+    float Area = Amap_LibGate( p->pLib, pM->pSet->iGate )->dArea;
+    Amap_MatchForEachFaninCompl( p, pM, pFanin, fCompl, i )
+    {
+        assert( Amap_ObjRefsTotal(pFanin) >= 0 );
+        if ( (int)pFanin->fPolar != fCompl && pFanin->nFouts[fCompl] == 0 )
+            Area += p->fAreaInv;
+        if ( pFanin->nFouts[fCompl]++ + pFanin->nFouts[!fCompl] == 0 && Amap_ObjIsNode(pFanin) )
+            Area += Amap_CutAreaRef( p, &pFanin->Best );
+    }
+    return Area;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives area of the match for a non-referenced node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline float Amap_CutAreaDerefed( Amap_Man_t * p, Amap_Obj_t * pNode, Amap_Mat_t * pM )
+{
+    float aResult, aResult2;
+    int fComplNew;
+    aResult2 = Amap_CutAreaRef( p, pM );
+    aResult  = Amap_CutAreaDeref( p, pM );
+    assert( aResult > aResult2 - p->fEpsilonInternal );
+    assert( aResult < aResult2 + p->fEpsilonInternal );
+    // if node is needed in another polarity, add inverter
+    fComplNew = pM->pCut->fInv ^ pM->pSet->fInv;
+    if ( pNode->nFouts[fComplNew] == 0 && pNode->nFouts[!fComplNew] > 0 )
+        aResult += p->fAreaInv;
+    return aResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Amap_CutAreaTest( Amap_Man_t * p, Amap_Obj_t * pNode )
+{
+    float aResult, aResult2;
+    if ( Amap_ObjRefsTotal(pNode) == 0 )
+    {
+        aResult2 = Amap_CutAreaRef( p, &pNode->Best );
+        aResult  = Amap_CutAreaDeref( p, &pNode->Best );
+        assert( aResult > aResult2 - p->fEpsilonInternal );
+        assert( aResult < aResult2 + p->fEpsilonInternal );
+    }
+    else
+    {
+        aResult  = Amap_CutAreaDeref( p, &pNode->Best );
+        aResult2 = Amap_CutAreaRef( p, &pNode->Best );
+        assert( aResult > aResult2 - p->fEpsilonInternal );
+        assert( aResult < aResult2 + p->fEpsilonInternal );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives parameters for the match.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Amap_ManMatchGetFlows( Amap_Man_t * p, Amap_Mat_t * pM )
+{
+    Amap_Mat_t * pMFanin;
+    Amap_Obj_t * pFanin;
+    Amap_Gat_t * pGate;
+    int i;
+    pGate = Amap_LibGate( p->pLib, pM->pSet->iGate );
+    assert( pGate->nPins == pM->pCut->nFans );
+    assert( pM->Area == 0.0 );
+    pM->Area = pGate->dArea;
+    pM->AveFan = 0.0;
+    pM->Delay = 0.0;
+    Amap_MatchForEachFanin( p, pM, pFanin, i )
+    {
+        pMFanin = &pFanin->Best;
+        pM->Delay = Abc_MaxInt( pM->Delay, pMFanin->Delay );
+        pM->AveFan += Amap_ObjRefsTotal(pFanin);
+        if ( Amap_ObjRefsTotal(pFanin) == 0 )
+            pM->Area += pMFanin->Area;
+        else
+            pM->Area += pMFanin->Area / pFanin->EstRefs;
+    }
+    pM->AveFan /= pGate->nPins;
+    pM->Delay += 1.0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives parameters for the match.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Amap_ManMatchGetExacts( Amap_Man_t * p, Amap_Obj_t * pNode, Amap_Mat_t * pM )
+{
+    Amap_Mat_t * pMFanin;
+    Amap_Obj_t * pFanin;
+    Amap_Gat_t * pGate;
+    int i;
+    pGate = Amap_LibGate( p->pLib, pM->pSet->iGate );
+    assert( pGate->nPins == pM->pCut->nFans );
+    assert( pM->Area == 0.0 );
+    pM->AveFan = 0.0;
+    pM->Delay = 0.0;
+    Amap_MatchForEachFanin( p, pM, pFanin, i )
+    {
+        pMFanin = &pFanin->Best;
+        pM->Delay = Abc_MaxInt( pM->Delay, pMFanin->Delay );
+        pM->AveFan += Amap_ObjRefsTotal(pFanin);
+    }
+    pM->AveFan /= pGate->nPins;
+    pM->Delay += 1.0;
+    pM->Area = Amap_CutAreaDerefed( p, pNode, pM );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the best match at each node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_ManMatchNode( Amap_Man_t * p, Amap_Obj_t * pNode, int fFlow, int fRefs )
+{
+    int fVerbose = 0; //(pNode->Level == 2 || pNode->Level == 4);
+    int fVeryVerbose = fVerbose;
+
+    Amap_Mat_t MA = {0}, MD = {0}, M = {0};
+    Amap_Mat_t * pMBestA = &MA, * pMBestD = &MD, * pMThis = &M, * pMBest;
+    Amap_Cut_t * pCut;
+    Amap_Set_t * pSet;
+    Amap_Nod_t * pNod;
+    int i;
+
+    if ( fRefs )
+        pNode->EstRefs = (float)((2.0 * pNode->EstRefs + Amap_ObjRefsTotal(pNode)) / 3.0);
+    else
+        pNode->EstRefs = (float)pNode->nRefs;
+    if ( fRefs && Amap_ObjRefsTotal(pNode) > 0 )
+        Amap_CutAreaDeref( p, &pNode->Best );
+
+    if ( fVerbose )
+        printf( "\nNode %d (%d)\n", pNode->Id, pNode->Level );
+
+    pMBestA->pCut = pMBestD->pCut = NULL;
+    Amap_NodeForEachCut( pNode, pCut, i )
+    {
+        if ( pCut->iMat == 0 )
+            continue;
+        pNod = Amap_LibNod( p->pLib, pCut->iMat );
+        Amap_LibNodeForEachSet( pNod, pSet )
+        {
+            Amap_ManMatchStart( pMThis, pCut, pSet );
+            if ( fFlow )
+                Amap_ManMatchGetFlows( p, pMThis );
+            else
+                Amap_ManMatchGetExacts( p, pNode, pMThis );
+            if ( pMBestD->pCut == NULL || Amap_CutCompareDelay(p, pMBestD, pMThis) == 1 )
+                *pMBestD = *pMThis;
+            if ( pMBestA->pCut == NULL || Amap_CutCompareArea(p, pMBestA, pMThis) == 1 )
+                *pMBestA = *pMThis;
+
+            if ( fVeryVerbose ) 
+            {
+                printf( "Cut %2d (%d) :  ", i, pCut->nFans );
+                printf( "Gate %10s  ",      Amap_LibGate(p->pLib, pMThis->pSet->iGate)->pName );
+                printf( "%s  ",             pMThis->pSet->fInv ? "inv" : "   " );
+                printf( "Delay %5.2f  ",    pMThis->Delay );
+                printf( "Area %5.2f  ",     pMThis->Area );
+                printf( "\n" );
+            }
+        }
+    }
+
+    if ( Abc_AbsFloat(pMBestA->Area - pMBestD->Area) / pMBestD->Area >= p->pPars->fADratio * Abc_AbsFloat(pMBestA->Delay - pMBestD->Delay) / pMBestA->Delay )
+        pMBest = pMBestA;
+    else
+        pMBest = pMBestD;
+
+    if ( fVerbose )
+    {
+        printf( "BEST MATCHA:  " );
+        printf( "Gate %10s  ",    Amap_LibGate(p->pLib, pMBestA->pSet->iGate)->pName );
+        printf( "%s  ",           pMBestA->pSet->fInv ? "inv" : "   " );
+        printf( "Delay %5.2f  ",  pMBestA->Delay );
+        printf( "Area %5.2f  ",   pMBestA->Area );
+        printf( "\n" ); 
+
+        printf( "BEST MATCHD:  " );
+        printf( "Gate %10s  ",    Amap_LibGate(p->pLib, pMBestD->pSet->iGate)->pName );
+        printf( "%s  ",           pMBestD->pSet->fInv ? "inv" : "   " );
+        printf( "Delay %5.2f  ",  pMBestD->Delay );
+        printf( "Area %5.2f  ",   pMBestD->Area );
+        printf( "\n" ); 
+
+        printf( "BEST MATCH :  " );
+        printf( "Gate %10s  ",    Amap_LibGate(p->pLib, pMBest->pSet->iGate)->pName );
+        printf( "%s  ",           pMBest->pSet->fInv ? "inv" : "   " );
+        printf( "Delay %5.2f  ",  pMBest->Delay );
+        printf( "Area %5.2f  ",   pMBest->Area );
+        printf( "\n" ); 
+    }
+
+    pNode->fPolar = pMBest->pCut->fInv ^ pMBest->pSet->fInv;
+    pNode->Best = *pMBest;
+    pNode->Best.pCut = Amap_ManDupCut( p, pNode->Best.pCut );
+    if ( fRefs && Amap_ObjRefsTotal(pNode) > 0 )
+        Amap_CutAreaRef( p, &pNode->Best );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one round of mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_ManMatch( Amap_Man_t * p, int fFlow, int fRefs )
+{
+    Aig_MmFlex_t * pMemOld;
+    Amap_Obj_t * pObj;
+    float Area;
+    int i, nInvs;
+    abctime clk = Abc_Clock();
+    pMemOld = p->pMemCutBest;
+    p->pMemCutBest = Aig_MmFlexStart();
+    Amap_ManForEachNode( p, pObj, i )
+        if ( pObj->pData )
+            Amap_ManMatchNode( p, pObj, fFlow, fRefs );
+    Aig_MmFlexStop( pMemOld, 0 );
+    Area = Amap_ManComputeMapping( p );
+    nInvs = Amap_ManCountInverters( p );
+if ( p->pPars->fVerbose )
+{
+    printf( "Area =%9.2f. Gate =%9.2f. Inv =%9.2f. (%6d.) Delay =%6.2f. ", 
+        Area + nInvs * p->fAreaInv, 
+        Area, nInvs * p->fAreaInv, nInvs,
+        Amap_ManMaxDelay(p) );
+ABC_PRT( "Time ", Abc_Clock() - clk );
+}
+    // test procedures
+//    Amap_ManForEachNode( p, pObj, i )
+//        Amap_CutAreaTest( p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_ManMap( Amap_Man_t * p )
+{
+    int i;
+    Amap_ManMerge( p );
+    for ( i = 0; i < p->pPars->nIterFlow; i++ )
+        Amap_ManMatch( p, 1, i>0 );
+    for ( i = 0; i < p->pPars->nIterArea; i++ )
+        Amap_ManMatch( p, 0, p->pPars->nIterFlow>0||i>0 );
+/*
+    for ( i = 0; i < p->pPars->nIterFlow; i++ )
+        Amap_ManMatch( p, 1, 1 );
+    for ( i = 0; i < p->pPars->nIterArea; i++ )
+        Amap_ManMatch( p, 0, 1 );
+*/
+    Amap_ManCleanData( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/amap/amapMerge.c b/abc-build/src/map/amap/amapMerge.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/amap/amapMerge.c
@@ -0,0 +1,541 @@
+/**CFile****************************************************************
+
+  FileName    [amapMerge.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Technology mapper for standard cells.]
+
+  Synopsis    [Computing cuts for the node.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: amapMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates new cut and adds it to storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Cut_t * Amap_ManSetupPis( Amap_Man_t * p )
+{
+    Amap_Obj_t * pObj;
+    Amap_Cut_t * pCut;
+    int i, nBytes = sizeof(Amap_Cut_t) + sizeof(int);
+    char * pBuffer = ABC_ALLOC( char, Amap_ManPiNum(p) * nBytes );
+    Amap_ManForEachPi( p, pObj, i )
+    {
+        pCut = (Amap_Cut_t *)( pBuffer + i*nBytes );
+        pCut->iMat = 0;
+        pCut->fInv = 0;
+        pCut->nFans = 1;
+        pCut->Fans[0] = Abc_Var2Lit( pObj->Id, 0 );
+        pObj->pData = pCut;
+        pObj->nCuts = 1;
+        pObj->EstRefs = (float)1.0;
+    }
+    return (Amap_Cut_t *)pBuffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates new cut and adds it to storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Cut_t * Amap_ManCutStore( Amap_Man_t * p, Amap_Cut_t * pCut, int fCompl )
+{
+    Amap_Cut_t * pNew;
+    int iFan, nBytes = sizeof(Amap_Cut_t) + sizeof(int) * pCut->nFans + sizeof(Amap_Cut_t *);
+    pNew = (Amap_Cut_t *)Aig_MmFlexEntryFetch( p->pMemTemp, nBytes );
+    pNew->iMat  = pCut->iMat;
+    pNew->fInv  = pCut->fInv ^ fCompl;
+    pNew->nFans = pCut->nFans;
+    memcpy( pNew->Fans, pCut->Fans, sizeof(int) * pCut->nFans );
+    // add it to storage
+    iFan = Abc_Var2Lit( pNew->iMat, pNew->fInv );
+    if ( p->ppCutsTemp[ iFan ] == NULL )
+        Vec_IntPushOrder( p->vTemp, iFan );
+    *Amap_ManCutNextP( pNew ) = p->ppCutsTemp[ iFan ];
+    p->ppCutsTemp[ iFan ] = pNew;
+    return pNew;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Creates new cut and adds it to storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Cut_t * Amap_ManCutCreate( Amap_Man_t * p, 
+    Amap_Cut_t * pCut0, Amap_Cut_t * pCut1, int iMat )
+{
+    Amap_Cut_t * pCut;
+    int i, nSize  = pCut0->nFans + pCut1->nFans;
+    int nBytes = sizeof(Amap_Cut_t) + sizeof(int) * nSize + sizeof(Amap_Cut_t *);
+    assert( pCut0->iMat >= pCut1->iMat );
+    pCut = (Amap_Cut_t *)Aig_MmFlexEntryFetch( p->pMemTemp, nBytes );
+    pCut->iMat  = iMat;
+    pCut->fInv  = 0;
+    pCut->nFans = nSize;
+    for ( i = 0; i < (int)pCut0->nFans; i++ )
+        pCut->Fans[i] = pCut0->Fans[i];
+    for ( i = 0; i < (int)pCut1->nFans; i++ )
+        pCut->Fans[pCut0->nFans+i] = pCut1->Fans[i];
+    // add it to storage
+    if ( p->ppCutsTemp[ pCut->iMat ] == NULL )
+        Vec_IntPushOrder( p->vTemp, pCut->iMat );
+    *Amap_ManCutNextP( pCut ) = p->ppCutsTemp[ pCut->iMat ];
+    p->ppCutsTemp[ pCut->iMat ] = pCut;
+    return pCut;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Creates new cut and adds it to storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Cut_t * Amap_ManCutCreate3( Amap_Man_t * p, 
+    Amap_Cut_t * pCut0, Amap_Cut_t * pCut1, Amap_Cut_t * pCut2, int iMat )
+{
+    Amap_Cut_t * pCut;
+    int i, nSize  = pCut0->nFans + pCut1->nFans + pCut2->nFans;
+    int nBytes = sizeof(Amap_Cut_t) + sizeof(int) * nSize + sizeof(Amap_Cut_t *);
+    pCut = (Amap_Cut_t *)Aig_MmFlexEntryFetch( p->pMemTemp, nBytes );
+    pCut->iMat  = iMat;
+    pCut->fInv  = 0;
+    pCut->nFans = nSize;
+    for ( i = 0; i < (int)pCut0->nFans; i++ )
+        pCut->Fans[i] = pCut0->Fans[i];
+    for ( i = 0; i < (int)pCut1->nFans; i++ )
+        pCut->Fans[pCut0->nFans+i] = pCut1->Fans[i];
+    for ( i = 0; i < (int)pCut2->nFans; i++ )
+        pCut->Fans[pCut0->nFans+pCut1->nFans+i] = pCut2->Fans[i];
+    // add it to storage
+    if ( p->ppCutsTemp[ pCut->iMat ] == NULL )
+        Vec_IntPushOrder( p->vTemp, pCut->iMat );
+    *Amap_ManCutNextP( pCut ) = p->ppCutsTemp[ pCut->iMat ];
+    p->ppCutsTemp[ pCut->iMat ] = pCut;
+    return pCut;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Removes cuts from the temporary storage.]
+
+  Description [] 
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+void Amap_ManCutSaveStored( Amap_Man_t * p, Amap_Obj_t * pNode )
+{
+    int nMaxCuts = p->pPars->nCutsMax;
+    int * pBuffer;
+    Amap_Cut_t * pNext, * pCut;
+    int i, nWords, Entry, nCuts, nCuts2;
+    assert( pNode->pData == NULL );
+    // count memory needed
+    nCuts = 1;
+    nWords = 2;
+    Vec_IntForEachEntry( p->vTemp, Entry, i )
+    {
+        for ( pCut = p->ppCutsTemp[Entry]; pCut; pCut = *Amap_ManCutNextP(pCut) )
+        {
+            nCuts++;
+            if ( nCuts < nMaxCuts )
+                nWords += pCut->nFans + 1;
+        }
+    }
+    p->nBytesUsed += 4*nWords;
+    // allocate memory
+    pBuffer = (int *)Aig_MmFlexEntryFetch( p->pMemCuts, 4*nWords );
+    pNext = (Amap_Cut_t *)pBuffer;
+    // add the first cut
+    pNext->iMat  = 0; 
+    pNext->fInv  = 0;
+    pNext->nFans = 1;
+    pNext->Fans[0] = Abc_Var2Lit(pNode->Id, 0);
+    pNext  = (Amap_Cut_t *)(pBuffer + 2);
+    // add other cuts
+    nCuts2 = 1;
+    Vec_IntForEachEntry( p->vTemp, Entry, i )
+    {
+        for ( pCut = p->ppCutsTemp[Entry]; pCut; pCut = *Amap_ManCutNextP(pCut) )
+        {
+            nCuts2++;
+            if ( nCuts2 < nMaxCuts )
+            {
+                memcpy( pNext, pCut, sizeof(int) * (pCut->nFans + 1) );
+                pNext = (Amap_Cut_t *)((int *)pNext + pCut->nFans + 1);
+            }
+        }
+        p->ppCutsTemp[Entry] = NULL;
+    }
+    assert( nCuts == nCuts2 );
+    assert( (int *)pNext - pBuffer == nWords );
+    // restore the storage
+    Vec_IntClear( p->vTemp );
+    Aig_MmFlexRestart( p->pMemTemp );
+    for ( i = 0; i < 2*p->pLib->nNodes; i++ )
+        if ( p->ppCutsTemp[i] != NULL )
+            printf( "Amap_ManCutSaveStored(): Error!\n" );
+    pNode->pData = (Amap_Cut_t *)pBuffer;
+    pNode->nCuts = Abc_MinInt( nCuts, nMaxCuts-1 );
+    assert( nCuts < (1<<20) );
+//    printf("%d ", nCuts );
+    // verify cuts
+    pCut = NULL;
+    Amap_NodeForEachCut( pNode, pNext, i )
+//        for ( i = 0, pNext = (Amap_Cut_t *)pNode->pData; i < (int)pNode->nCuts; 
+//        i++, pNext = Amap_ManCutNext(pNext) )
+    {
+        if ( i == nMaxCuts )
+            break;
+        assert( pCut == NULL || pCut->iMat <= pNext->iMat );
+        pCut = pNext;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of possible new cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_ManMergeCountCuts( Amap_Man_t * p, Amap_Obj_t * pNode )
+{
+    Amap_Obj_t * pFanin0 = Amap_ObjFanin0( p, pNode );
+    Amap_Obj_t * pFanin1 = Amap_ObjFanin1( p, pNode );
+    Amap_Cut_t * pCut0, * pCut1;
+    int Entry, c0, c1, iCompl0, iCompl1, iFan0, iFan1;
+    int Counter = 1;
+    Amap_NodeForEachCut( pFanin0, pCut0, c0 )
+    Amap_NodeForEachCut( pFanin1, pCut1, c1 )
+    {
+        iCompl0 = pCut0->fInv ^ Amap_ObjFaninC0(pNode);
+        iCompl1 = pCut1->fInv ^ Amap_ObjFaninC1(pNode);
+        iFan0   = !pCut0->iMat? 0: Abc_Var2Lit( pCut0->iMat, iCompl0 );
+        iFan1   = !pCut1->iMat? 0: Abc_Var2Lit( pCut1->iMat, iCompl1 );
+        Entry = Amap_LibFindNode( p->pLib, iFan0, iFan1, pNode->Type == AMAP_OBJ_XOR );
+        Counter += ( Entry >=0 );
+//        if ( Entry >=0 )
+//            printf( "Full: %d + %d = %d\n", iFan0, iFan1, Entry );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_ManPrintCuts( Amap_Obj_t * pNode )
+{
+    Amap_Cut_t * pCut;
+    int c, i;
+    printf( "NODE %5d : Type = ", pNode->Id );
+    if ( pNode->Type == AMAP_OBJ_AND )
+        printf( "AND" );
+    else if ( pNode->Type == AMAP_OBJ_XOR )
+        printf( "XOR" );
+    else if ( pNode->Type == AMAP_OBJ_MUX )
+        printf( "MUX" );
+    printf( "  Cuts = %d\n", pNode->nCuts );
+    Amap_NodeForEachCut( pNode, pCut, c )
+    {
+        printf( "%3d :  Mat= %3d  Inv=%d  ", c, pCut->iMat, pCut->fInv );
+        for ( i = 0; i < (int)pCut->nFans; i++ )
+            printf( "%d%c ", Abc_Lit2Var(pCut->Fans[i]), Abc_LitIsCompl(pCut->Fans[i])?'-':'+' );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives cuts for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_ManMergeNodeChoice( Amap_Man_t * p, Amap_Obj_t * pNode )
+{
+    Amap_Obj_t * pTemp;
+    Amap_Cut_t * pCut;
+    int c;
+    // go through the nodes of the choice node
+    for ( pTemp = pNode; pTemp; pTemp = Amap_ObjChoice(p, pTemp) )
+    {
+        Amap_NodeForEachCut( pTemp, pCut, c )
+        {
+            if (!pCut) break;   // mikelee added; abort when pCut is NULL
+            if ( pCut->iMat )
+                Amap_ManCutStore( p, pCut, pNode->fPhase ^ pTemp->fPhase );
+        }
+        pTemp->pData = NULL;
+    }
+    Amap_ManCutSaveStored( p, pNode );
+
+//    Amap_ManPrintCuts( pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives cuts for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_ManFindCut( Amap_Obj_t * pNode, Amap_Obj_t * pFanin, int fComplFanin, int Val, Vec_Ptr_t * vCuts )
+{
+    Amap_Cut_t * pCut;
+    int c, iCompl, iFan;
+    Vec_PtrClear( vCuts );
+    Amap_NodeForEachCut( pFanin, pCut, c )
+    {
+        iCompl = pCut->fInv ^ fComplFanin;
+        iFan   = !pCut->iMat? 0: Abc_Var2Lit( pCut->iMat, iCompl );
+        if ( iFan == Val )
+            Vec_PtrPush( vCuts, pCut );
+    }
+    return Vec_PtrSize(vCuts) == 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives cuts for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_ManMergeNodeCutsMux( Amap_Man_t * p, Amap_Obj_t * pNode )
+{
+    Vec_Int_t * vRules = p->pLib->vRules3;
+    Amap_Obj_t * pFanin0 = Amap_ObjFanin0( p, pNode );
+    Amap_Obj_t * pFanin1 = Amap_ObjFanin1( p, pNode );
+    Amap_Obj_t * pFanin2 = Amap_ObjFanin2( p, pNode );
+    int fComplFanin0 = Amap_ObjFaninC0( pNode );
+    int fComplFanin1 = Amap_ObjFaninC1( pNode );
+    int fComplFanin2 = Amap_ObjFaninC2( pNode );
+    Amap_Cut_t * pCut0, * pCut1, * pCut2;
+    int x, c0, c1, c2;
+    assert( pNode->pData == NULL );
+    assert( pNode->Type == AMAP_OBJ_MUX );
+    assert( pNode->fRepr == 0 );
+    // go through the rules
+    for ( x = 0; x < Vec_IntSize(vRules); x += 4 )
+    {
+        if ( Amap_ManFindCut( pNode, pFanin0, fComplFanin0, Vec_IntEntry(vRules, x), p->vCuts0 ) )
+            continue;
+        if ( Amap_ManFindCut( pNode, pFanin1, fComplFanin1, Vec_IntEntry(vRules, x+1), p->vCuts1 ) )
+            continue;
+        if ( Amap_ManFindCut( pNode, pFanin2, fComplFanin2, Vec_IntEntry(vRules, x+2), p->vCuts2 ) )
+            continue;
+        Vec_PtrForEachEntry( Amap_Cut_t *, p->vCuts0, pCut0, c0 )
+        Vec_PtrForEachEntry( Amap_Cut_t *, p->vCuts1, pCut1, c1 )
+        Vec_PtrForEachEntry( Amap_Cut_t *, p->vCuts2, pCut2, c2 )
+        {
+            Amap_Nod_t * pNod = Amap_LibNod( p->pLib, Vec_IntEntry(vRules, x+3) );
+            if ( pNod->pSets == NULL )
+                continue;
+            // complement literals
+            if ( pCut0->nFans == 1 && (pCut0->fInv ^ fComplFanin0) )
+                pCut0->Fans[0] = Abc_LitNot(pCut0->Fans[0]);
+            if ( pCut1->nFans == 1 && (pCut1->fInv ^ fComplFanin1) )
+                pCut1->Fans[0] = Abc_LitNot(pCut1->Fans[0]);
+            if ( pCut2->nFans == 1 && (pCut2->fInv ^ fComplFanin2) )
+                pCut2->Fans[0] = Abc_LitNot(pCut2->Fans[0]);
+            // create new cut
+            Amap_ManCutCreate3( p, pCut0, pCut1, pCut2, Vec_IntEntry(vRules, x+3) );
+            // uncomplement literals
+            if ( pCut0->nFans == 1 && (pCut0->fInv ^ fComplFanin0) )
+                pCut0->Fans[0] = Abc_LitNot(pCut0->Fans[0]);
+            if ( pCut1->nFans == 1 && (pCut1->fInv ^ fComplFanin1) )
+                pCut1->Fans[0] = Abc_LitNot(pCut1->Fans[0]);
+            if ( pCut2->nFans == 1 && (pCut2->fInv ^ fComplFanin2) )
+                pCut2->Fans[0] = Abc_LitNot(pCut2->Fans[0]);
+        }
+    }
+    Amap_ManCutSaveStored( p, pNode );
+    p->nCutsUsed += pNode->nCuts;
+    p->nCutsTried3 += pFanin0->nCuts * pFanin1->nCuts * pFanin2->nCuts;
+
+//    Amap_ManPrintCuts( pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives cuts for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_ManMergeNodeCuts( Amap_Man_t * p, Amap_Obj_t * pNode )
+{
+    Amap_Obj_t * pFanin0 = Amap_ObjFanin0( p, pNode );
+    Amap_Obj_t * pFanin1 = Amap_ObjFanin1( p, pNode );
+    Amap_Cut_t * pCut0, * pCut1;
+    int ** pRules, Entry, i, k, c, iCompl0, iCompl1, iFan0, iFan1;
+    assert( pNode->pData == NULL );
+    if ( pNode->Type == AMAP_OBJ_MUX )
+    {
+        Amap_ManMergeNodeCutsMux( p, pNode );
+        return;
+    }
+    assert( pNode->Type != AMAP_OBJ_MUX );
+    pRules = (pNode->Type == AMAP_OBJ_AND)? p->pLib->pRules: p->pLib->pRulesX;
+    Amap_NodeForEachCut( pFanin0, pCut0, c )
+    {
+        iCompl0 = pCut0->fInv ^ Amap_ObjFaninC0(pNode);
+        iFan0   = !pCut0->iMat? 0: Abc_Var2Lit( pCut0->iMat, iCompl0 );
+        // complement literals
+        if ( pCut0->nFans == 1 && iCompl0 )
+            pCut0->Fans[0] = Abc_LitNot(pCut0->Fans[0]);
+        // label resulting sets
+        for ( i = 0; (Entry = pRules[iFan0][i]); i++ )
+            p->pMatsTemp[Entry & 0xffff] = (Entry >> 16);
+        // iterate through the cuts
+        Amap_NodeForEachCut( pFanin1, pCut1, k )
+        {
+            iCompl1 = pCut1->fInv ^ Amap_ObjFaninC1(pNode);
+            iFan1   = !pCut1->iMat? 0: Abc_Var2Lit( pCut1->iMat, iCompl1 );
+            if ( p->pMatsTemp[iFan1] == 0 )
+                continue;
+            // complement literals
+            if ( pCut1->nFans == 1 && iCompl1 )
+                pCut1->Fans[0] = Abc_LitNot(pCut1->Fans[0]);
+            // create new cut
+            if ( iFan0 >= iFan1 )
+                Amap_ManCutCreate( p, pCut0, pCut1, p->pMatsTemp[iFan1] );
+            else
+                Amap_ManCutCreate( p, pCut1, pCut0, p->pMatsTemp[iFan1] );
+            // uncomplement literals
+            if ( pCut1->nFans == 1 && iCompl1 )
+                pCut1->Fans[0] = Abc_LitNot(pCut1->Fans[0]);
+        }
+        // uncomplement literals
+        if ( pCut0->nFans == 1 && iCompl0 )
+            pCut0->Fans[0] = Abc_LitNot(pCut0->Fans[0]);
+        // label resulting sets
+        for ( i = 0; (Entry = pRules[iFan0][i]); i++ )
+            p->pMatsTemp[Entry & 0xffff] = 0;
+    }
+    Amap_ManCutSaveStored( p, pNode );
+    p->nCutsUsed += pNode->nCuts;
+    p->nCutsTried += pFanin0->nCuts * pFanin1->nCuts;
+//    assert( (int)pNode->nCuts == Amap_ManMergeCountCuts(p, pNode) );
+    if ( pNode->fRepr )
+        Amap_ManMergeNodeChoice( p, pNode );
+
+//    Amap_ManPrintCuts( pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives cuts for all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_ManMerge( Amap_Man_t * p )
+{
+    Amap_Obj_t * pObj;
+    int i;
+    abctime clk = Abc_Clock();
+    p->pCutsPi = Amap_ManSetupPis( p );
+    Amap_ManForEachNode( p, pObj, i )
+        Amap_ManMergeNodeCuts( p, pObj );
+    if ( p->pPars->fVerbose )
+    {
+        printf( "AIG object is %d bytes.  ", (int)sizeof(Amap_Obj_t) );
+        printf( "Internal AIG = %5.2f MB.  Cuts = %5.2f MB.  CutsMax = %d.\n", 
+            1.0*Amap_ManObjNum(p)*sizeof(Amap_Obj_t)/(1<<20), 1.0*p->nBytesUsed/(1<<20), p->pPars->nCutsMax );
+        printf( "Node =%6d. Try =%9d. Try3 =%10d. Used =%7d. R =%6.2f.  ", 
+            Amap_ManNodeNum(p), p->nCutsTried, p->nCutsTried3, p->nCutsUsed, 
+            1.0*p->nCutsUsed/Amap_ManNodeNum(p) );
+ABC_PRT( "Time ", Abc_Clock() - clk );
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/amap/amapOutput.c b/abc-build/src/map/amap/amapOutput.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/amap/amapOutput.c
@@ -0,0 +1,186 @@
+/**CFile****************************************************************
+
+  FileName    [amapOutput.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Technology mapper for standard cells.]
+
+  Synopsis    [Core mapping procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: amapOutput.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline char * Amap_OuputStrsav( Aig_MmFlex_t * p, char * pStr ) 
+{ return pStr ? strcpy(Aig_MmFlexEntryFetch(p, strlen(pStr)+1), pStr) : NULL; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates structure for storing one gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Out_t * Amap_OutputStructAlloc( Aig_MmFlex_t * pMem, Amap_Gat_t * pGate )
+{
+    Amap_Out_t * pRes;
+    int nFans = pGate? pGate->nPins : 1;
+    pRes = (Amap_Out_t *)Aig_MmFlexEntryFetch( pMem, sizeof(Amap_Out_t)+sizeof(int)*nFans );
+    memset( pRes, 0, sizeof(Amap_Out_t) );
+    memset( pRes->pFans, 0xff, sizeof(int)*nFans );
+    pRes->pName = pGate? Amap_OuputStrsav( pMem, pGate->pName ) : NULL;
+    pRes->nFans = nFans;
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns mapped network as an array of structures.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Amap_ManProduceMapped( Amap_Man_t * p )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_MmFlex_t * pMem;
+    Amap_Obj_t * pObj, * pFanin;
+    Amap_Gat_t * pGate;
+    Amap_Out_t * pRes;
+    int i, k, iFanin, fCompl;
+    float TotalArea = 0.0;
+    pMem = Aig_MmFlexStart();
+    // create mapping object for each node used in the mapping
+    vNodes = Vec_PtrAlloc( 10 );
+    Amap_ManForEachObj( p, pObj, i )
+    {
+        if ( Amap_ObjIsPi(pObj) )
+        {
+            assert( pObj->fPolar == 0 );
+            pRes = Amap_OutputStructAlloc( pMem, NULL );
+            pRes->Type  = -1;
+            pRes->nFans = 0;
+            // save this structure
+            pObj->iData = Vec_PtrSize( vNodes );
+            Vec_PtrPush( vNodes, pRes );
+            // create invertor if needed
+            if ( pObj->nFouts[1] ) // this PI is used in the neg polarity
+            {
+                pRes = Amap_OutputStructAlloc( pMem, p->pLib->pGateInv );
+                pRes->pFans[0] = pObj->iData;
+                // save this structure
+                Vec_PtrPush( vNodes, pRes );
+                TotalArea += p->pLib->pGateInv->dArea;
+            }
+            continue;
+        }
+        if ( Amap_ObjIsNode(pObj) )
+        {
+            // skip the node that is not used in the mapping
+            if ( Amap_ObjRefsTotal(pObj) == 0 )
+                continue;
+            // get the gate
+            pGate = Amap_LibGate( p->pLib, pObj->Best.pSet->iGate );
+            assert( pGate->nPins == pObj->Best.pCut->nFans );
+            // allocate structure
+            pRes = Amap_OutputStructAlloc( pMem, pGate );
+            Amap_MatchForEachFaninCompl( p, &pObj->Best, pFanin, fCompl, k )
+            {
+                assert( Amap_ObjRefsTotal(pFanin) );
+                if ( (int)pFanin->fPolar == fCompl )
+                    pRes->pFans[k] = pFanin->iData;
+                else
+                    pRes->pFans[k] = pFanin->iData + 1;
+            }
+            // save this structure
+            pObj->iData = Vec_PtrSize( vNodes );
+            Vec_PtrPush( vNodes, pRes );
+            TotalArea += pGate->dArea;
+            // create invertor if needed
+            if ( pObj->nFouts[!pObj->fPolar] ) // needed in the opposite polarity
+            {
+                pRes = Amap_OutputStructAlloc( pMem, p->pLib->pGateInv );
+                pRes->pFans[0] = pObj->iData;
+                // save this structure
+                Vec_PtrPush( vNodes, pRes );
+                TotalArea += p->pLib->pGateInv->dArea;
+            }
+            continue;
+        }
+        if ( Amap_ObjIsPo(pObj) )
+        {
+            assert( pObj->fPolar == 0 );
+            pFanin = Amap_ObjFanin0(p, pObj);
+            assert( Amap_ObjRefsTotal(pFanin) );
+            if ( Amap_ObjIsConst1(pFanin)  )
+            { // create constant node
+                if ( Amap_ObjFaninC0(pObj) )
+                {
+                    pRes = Amap_OutputStructAlloc( pMem, p->pLib->pGate0 );
+                    TotalArea += p->pLib->pGate0->dArea;
+                }
+                else
+                {
+                    pRes = Amap_OutputStructAlloc( pMem, p->pLib->pGate1 );
+                    TotalArea += p->pLib->pGate1->dArea;
+                }
+                // save this structure
+                iFanin = Vec_PtrSize( vNodes );
+                Vec_PtrPush( vNodes, pRes );
+            }
+            else 
+            {
+                if ( (int)pFanin->fPolar == Amap_ObjFaninC0(pObj) )
+                    iFanin = pFanin->iData;
+                else
+                    iFanin = pFanin->iData + 1;
+            }
+            // create PO node
+            pRes = Amap_OutputStructAlloc( pMem, NULL );
+            pRes->Type     = 1;
+            pRes->pFans[0] = iFanin;
+            // save this structure
+            Vec_PtrPush( vNodes, pRes );
+        }
+    }
+    // return memory manager in the last entry of the array
+    Vec_PtrPush( vNodes, pMem );
+    return vNodes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/amap/amapParse.c b/abc-build/src/map/amap/amapParse.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/amap/amapParse.c
@@ -0,0 +1,480 @@
+/**CFile****************************************************************
+
+  FileName    [amapParse.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Technology mapper for standard cells.]
+
+  Synopsis    [Parses representations of gates.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: amapParse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+#include "aig/hop/hop.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// the list of operation symbols to be used in expressions
+#define AMAP_EQN_SYM_OPEN    '('   // opening paranthesis
+#define AMAP_EQN_SYM_CLOSE   ')'   // closing paranthesis
+#define AMAP_EQN_SYM_CONST0  '0'   // constant 0
+#define AMAP_EQN_SYM_CONST1  '1'   // constant 1
+#define AMAP_EQN_SYM_NEG     '!'   // negation before the variable
+#define AMAP_EQN_SYM_NEGAFT  '\''  // negation after the variable
+#define AMAP_EQN_SYM_AND     '*'   // logic AND
+#define AMAP_EQN_SYM_AND2    '&'   // logic AND
+#define AMAP_EQN_SYM_XOR     '^'   // logic XOR
+#define AMAP_EQN_SYM_OR      '+'   // logic OR
+#define AMAP_EQN_SYM_OR2     '|'   // logic OR
+
+// the list of opcodes (also specifying operation precedence)
+#define AMAP_EQN_OPER_NEG    10    // negation
+#define AMAP_EQN_OPER_AND     9    // logic AND
+#define AMAP_EQN_OPER_XOR     8    // logic XOR
+#define AMAP_EQN_OPER_OR      7    // logic OR
+#define AMAP_EQN_OPER_MARK    1    // OpStack token standing for an opening paranthesis
+
+// these are values of the internal Flag
+#define AMAP_EQN_FLAG_START   1    // after the opening parenthesis 
+#define AMAP_EQN_FLAG_VAR     2    // after operation is received
+#define AMAP_EQN_FLAG_OPER    3    // after operation symbol is received
+#define AMAP_EQN_FLAG_ERROR   4    // when error is detected
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs the operation on the top entries in the stack.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Amap_ParseFormulaOper( Hop_Man_t * pMan, Vec_Ptr_t * pStackFn, int Oper )
+{
+    Hop_Obj_t * gArg1, * gArg2, * gFunc;
+    // perform the given operation
+    gArg2 = (Hop_Obj_t *)Vec_PtrPop( pStackFn );
+    gArg1 = (Hop_Obj_t *)Vec_PtrPop( pStackFn );
+	if ( Oper == AMAP_EQN_OPER_AND )
+		gFunc = Hop_And( pMan, gArg1, gArg2 );
+	else if ( Oper == AMAP_EQN_OPER_OR )
+		gFunc = Hop_Or( pMan, gArg1, gArg2 );
+	else if ( Oper == AMAP_EQN_OPER_XOR )
+		gFunc = Hop_Exor( pMan, gArg1, gArg2 );
+	else
+		return NULL;
+//    Cudd_Ref( gFunc );
+//    Cudd_RecursiveDeref( dd, gArg1 );
+//    Cudd_RecursiveDeref( dd, gArg2 );
+	Vec_PtrPush( pStackFn,  gFunc );
+    return gFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the AIG corresponding to the equation.]
+
+  Description [Takes the stream to output messages, the formula, the vector
+  of variable names and the AIG manager.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Amap_ParseFormula( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan )
+{
+    char * pFormula;
+    Vec_Ptr_t * pStackFn;
+    Vec_Int_t * pStackOp;
+    Hop_Obj_t * gFunc;
+    char * pTemp, * pName;
+    int nParans, fFound, Flag;
+	int Oper, Oper1, Oper2;
+    int i, v;
+
+    // make sure that the number of opening and closing parantheses is the same
+    nParans = 0;
+    for ( pTemp = pFormInit; *pTemp; pTemp++ )
+        if ( *pTemp == '(' )
+            nParans++;
+        else if ( *pTemp == ')' )
+            nParans--;
+    if ( nParans != 0 )
+    {
+        fprintf( pOutput, "Amap_ParseFormula(): Different number of opening and closing parantheses ().\n" );
+        return NULL;
+    }
+
+    // copy the formula
+    pFormula = ABC_ALLOC( char, strlen(pFormInit) + 3 );
+    sprintf( pFormula, "(%s)", pFormInit );
+
+    // start the stacks
+    pStackFn = Vec_PtrAlloc( 100 );
+    pStackOp = Vec_IntAlloc( 100 );
+
+    Flag = AMAP_EQN_FLAG_START;
+    for ( pTemp = pFormula; *pTemp; pTemp++ )
+	{
+		switch ( *pTemp )
+	    {
+		// skip all spaces, tabs, and end-of-lines
+        case ' ':
+        case '\t':
+        case '\r':
+        case '\n':
+			continue;
+		case AMAP_EQN_SYM_CONST0:
+		    Vec_PtrPush( pStackFn, Hop_ManConst0(pMan) );  // Cudd_Ref( b0 );
+			if ( Flag == AMAP_EQN_FLAG_VAR )
+			{
+				fprintf( pOutput, "Amap_ParseFormula(): No operation symbol before constant 0.\n" );
+				Flag = AMAP_EQN_FLAG_ERROR; 
+                break;
+			}
+            Flag = AMAP_EQN_FLAG_VAR; 
+            break;
+		case AMAP_EQN_SYM_CONST1:
+		    Vec_PtrPush( pStackFn, Hop_ManConst1(pMan) );  //  Cudd_Ref( b1 );
+			if ( Flag == AMAP_EQN_FLAG_VAR )
+			{
+				fprintf( pOutput, "Amap_ParseFormula(): No operation symbol before constant 1.\n" );
+				Flag = AMAP_EQN_FLAG_ERROR; 
+                break;
+			}
+            Flag = AMAP_EQN_FLAG_VAR; 
+            break;
+		case AMAP_EQN_SYM_NEG:
+			if ( Flag == AMAP_EQN_FLAG_VAR )
+			{// if NEGBEF follows a variable, AND is assumed
+				Vec_IntPush( pStackOp, AMAP_EQN_OPER_AND );
+				Flag = AMAP_EQN_FLAG_OPER;
+			}
+    		Vec_IntPush( pStackOp, AMAP_EQN_OPER_NEG );
+			break;
+		case AMAP_EQN_SYM_NEGAFT:
+			if ( Flag != AMAP_EQN_FLAG_VAR )
+			{// if there is no variable before NEGAFT, it is an error
+				fprintf( pOutput, "Amap_ParseFormula(): No variable is specified before the negation suffix.\n" );
+				Flag = AMAP_EQN_FLAG_ERROR; 
+                break;
+			}
+			else // if ( Flag == PARSE_FLAG_VAR )
+				Vec_PtrPush( pStackFn, Hop_Not( (Hop_Obj_t *)Vec_PtrPop(pStackFn) ) );
+			break;
+        case AMAP_EQN_SYM_AND:
+        case AMAP_EQN_SYM_AND2:
+        case AMAP_EQN_SYM_OR:
+        case AMAP_EQN_SYM_OR2:
+        case AMAP_EQN_SYM_XOR:
+			if ( Flag != AMAP_EQN_FLAG_VAR )
+			{
+				fprintf( pOutput, "Amap_ParseFormula(): There is no variable before AND, EXOR, or OR.\n" );
+				Flag = AMAP_EQN_FLAG_ERROR; 
+                break;
+			}
+			if ( *pTemp == AMAP_EQN_SYM_AND || *pTemp == AMAP_EQN_SYM_AND2 )
+				Vec_IntPush( pStackOp, AMAP_EQN_OPER_AND );
+			else if ( *pTemp == AMAP_EQN_SYM_OR || *pTemp == AMAP_EQN_SYM_OR2 )
+				Vec_IntPush( pStackOp, AMAP_EQN_OPER_OR );
+			else //if ( *pTemp == AMAP_EQN_SYM_XOR )
+				Vec_IntPush( pStackOp, AMAP_EQN_OPER_XOR );
+			Flag = AMAP_EQN_FLAG_OPER; 
+            break;
+		case AMAP_EQN_SYM_OPEN:
+			if ( Flag == AMAP_EQN_FLAG_VAR )
+            {
+				Vec_IntPush( pStackOp, AMAP_EQN_OPER_AND );
+//				fprintf( pOutput, "Amap_ParseFormula(): An opening paranthesis follows a var without operation sign.\n" ); 
+//				Flag = AMAP_EQN_FLAG_ERROR; 
+//              break; 
+            }
+			Vec_IntPush( pStackOp, AMAP_EQN_OPER_MARK );
+			// after an opening bracket, it feels like starting over again
+			Flag = AMAP_EQN_FLAG_START; 
+            break;
+		case AMAP_EQN_SYM_CLOSE:
+			if ( Vec_IntSize( pStackOp ) != 0 )
+            {
+				while ( 1 )
+			    {
+				    if ( Vec_IntSize( pStackOp ) == 0 )
+					{
+						fprintf( pOutput, "Amap_ParseFormula(): There is no opening paranthesis\n" );
+						Flag = AMAP_EQN_FLAG_ERROR; 
+                        break;
+					}
+					Oper = Vec_IntPop( pStackOp );
+					if ( Oper == AMAP_EQN_OPER_MARK )
+						break;
+
+                    // perform the given operation
+                    if ( Amap_ParseFormulaOper( pMan, pStackFn, Oper ) == NULL )
+	                {
+		                fprintf( pOutput, "Amap_ParseFormula(): Unknown operation\n" );
+                        ABC_FREE( pFormula );
+                        Vec_PtrFreeP( &pStackFn );
+                        Vec_IntFreeP( &pStackOp );
+		                return NULL;
+	                }
+			    }
+            }
+		    else
+			{
+				fprintf( pOutput, "Amap_ParseFormula(): There is no opening paranthesis\n" );
+				Flag = AMAP_EQN_FLAG_ERROR; 
+                break;
+			}
+			if ( Flag != AMAP_EQN_FLAG_ERROR )
+			    Flag = AMAP_EQN_FLAG_VAR; 
+			break;
+
+
+		default:
+            // scan the next name
+            for ( i = 0; pTemp[i] && 
+                         pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' &&
+                         pTemp[i] != AMAP_EQN_SYM_AND && pTemp[i] != AMAP_EQN_SYM_AND2 && pTemp[i] != AMAP_EQN_SYM_OR && pTemp[i] != AMAP_EQN_SYM_OR2 && 
+                         pTemp[i] != AMAP_EQN_SYM_XOR && pTemp[i] != AMAP_EQN_SYM_NEGAFT && pTemp[i] != AMAP_EQN_SYM_CLOSE; 
+                  i++ )
+              {
+				    if ( pTemp[i] == AMAP_EQN_SYM_NEG || pTemp[i] == AMAP_EQN_SYM_OPEN )
+				    {
+					    fprintf( pOutput, "Amap_ParseFormula(): The negation sign or an opening paranthesis inside the variable name.\n" );
+					    Flag = AMAP_EQN_FLAG_ERROR; 
+                        break;
+				    }
+              }
+            // variable name is found
+            fFound = 0;
+            Vec_PtrForEachEntry( char *, vVarNames, pName, v )
+                if ( strncmp(pTemp, pName, i) == 0 && strlen(pName) == (unsigned)i )
+                {
+                    pTemp += i-1;
+                    fFound = 1;
+                    break;
+                }
+            if ( !fFound )
+			{ 
+				fprintf( pOutput, "Amap_ParseFormula(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); 
+				Flag = AMAP_EQN_FLAG_ERROR; 
+                break; 
+			}
+/*
+			if ( Flag == AMAP_EQN_FLAG_VAR )
+            {
+				fprintf( pOutput, "Amap_ParseFormula(): The variable name \"%s\" follows another var without operation sign.\n", pTemp ); 
+				Flag = AMAP_EQN_FLAG_ERROR; 
+                break; 
+            }
+*/
+			if ( Flag == AMAP_EQN_FLAG_VAR )
+				Vec_IntPush( pStackOp, AMAP_EQN_OPER_AND );
+
+			Vec_PtrPush( pStackFn, Hop_IthVar( pMan, v ) ); // Cudd_Ref( pbVars[v] );
+            Flag = AMAP_EQN_FLAG_VAR; 
+            break;
+	    }
+
+		if ( Flag == AMAP_EQN_FLAG_ERROR )
+			break;      // error exit
+		else if ( Flag == AMAP_EQN_FLAG_START )
+			continue;  //  go on parsing
+		else if ( Flag == AMAP_EQN_FLAG_VAR )
+			while ( 1 )
+			{  // check if there are negations in the OpStack     
+				if ( Vec_IntSize( pStackOp ) == 0 )
+					break;
+                Oper = Vec_IntPop( pStackOp );
+				if ( Oper != AMAP_EQN_OPER_NEG )
+                {
+					Vec_IntPush( pStackOp, Oper );
+					break;
+                }
+				else
+				{
+      				Vec_PtrPush( pStackFn, Hop_Not((Hop_Obj_t *)Vec_PtrPop(pStackFn)) );
+				}
+			}
+		else // if ( Flag == AMAP_EQN_FLAG_OPER )
+			while ( 1 )
+			{  // execute all the operations in the OpStack
+			   // with precedence higher or equal than the last one
+				Oper1 = Vec_IntPop( pStackOp ); // the last operation
+				if ( Vec_IntSize( pStackOp ) == 0 ) 
+				{  // if it is the only operation, push it back
+					Vec_IntPush( pStackOp, Oper1 );
+					break;
+				}
+				Oper2 = Vec_IntPop( pStackOp ); // the operation before the last one
+				if ( Oper2 >= Oper1 )  
+				{  // if Oper2 precedence is higher or equal, execute it
+                    if ( Amap_ParseFormulaOper( pMan, pStackFn, Oper2 ) == NULL )
+	                {
+		                fprintf( pOutput, "Amap_ParseFormula(): Unknown operation\n" );
+                        ABC_FREE( pFormula );
+                        Vec_PtrFreeP( &pStackFn );
+                        Vec_IntFreeP( &pStackOp );
+		                return NULL;
+	                }
+					Vec_IntPush( pStackOp,  Oper1 );     // push the last operation back
+				}
+				else
+				{  // if Oper2 precedence is lower, push them back and done
+					Vec_IntPush( pStackOp, Oper2 );
+					Vec_IntPush( pStackOp, Oper1 );
+					break;
+				}
+			}
+    }
+
+	if ( Flag != AMAP_EQN_FLAG_ERROR )
+    {
+		if ( Vec_PtrSize(pStackFn) != 0 )
+	    {	
+			gFunc = (Hop_Obj_t *)Vec_PtrPop(pStackFn);
+			if ( Vec_PtrSize(pStackFn) == 0 )
+				if ( Vec_IntSize( pStackOp ) == 0 )
+                {
+//                    Cudd_Deref( gFunc );
+                    ABC_FREE( pFormula );
+                    Vec_PtrFreeP( &pStackFn );
+                    Vec_IntFreeP( &pStackOp );
+					return gFunc;
+                }
+				else
+					fprintf( pOutput, "Amap_ParseFormula(): Something is left in the operation stack\n" );
+			else
+				fprintf( pOutput, "Amap_ParseFormula(): Something is left in the function stack\n" );
+	    }
+	    else
+			fprintf( pOutput, "Amap_ParseFormula(): The input string is empty\n" );
+    }
+    ABC_FREE( pFormula );
+    Vec_PtrFreeP( &pStackFn );
+    Vec_IntFreeP( &pStackOp );
+	return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses equations for the gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_LibParseEquations( Amap_Lib_t * p, int fVerbose )
+{
+//    extern int Kit_TruthSupportSize( unsigned * pTruth, int nVars );
+    Hop_Man_t * pMan;
+    Hop_Obj_t * pObj;
+    Vec_Ptr_t * vNames;
+    Vec_Int_t * vTruth;
+    Amap_Gat_t * pGate;
+    Amap_Pin_t * pPin;
+    unsigned * pTruth;
+    int i, nPinMax;
+    nPinMax = Amap_LibNumPinsMax(p);
+    if ( nPinMax > AMAP_MAXINS )
+        printf( "Gates with more than %d inputs will be ignored.\n", AMAP_MAXINS );
+    vTruth = Vec_IntAlloc( 1 << 16 );
+    vNames = Vec_PtrAlloc( 100 );
+    pMan = Hop_ManStart();
+    Hop_IthVar( pMan, nPinMax - 1 );
+    Vec_PtrForEachEntry( Amap_Gat_t *, p->vGates, pGate, i )
+    {
+        if ( pGate->nPins == 0 )
+        {
+            pGate->pFunc = (unsigned *)Aig_MmFlexEntryFetch( p->pMemGates, 4 );
+            if ( strcmp( pGate->pForm, AMAP_STRING_CONST0 ) == 0 )
+                pGate->pFunc[0] = 0;
+            else if ( strcmp( pGate->pForm, AMAP_STRING_CONST1 ) == 0 )
+                pGate->pFunc[0] = ~0;
+            else
+            {
+                printf( "Cannot parse formula \"%s\" of gate \"%s\" with no pins.\n", pGate->pForm, pGate->pName );
+                break;
+            }
+            continue;
+        }
+        if ( pGate->nPins > AMAP_MAXINS )
+            continue;
+        Vec_PtrClear( vNames );
+        Amap_GateForEachPin( pGate, pPin )
+            Vec_PtrPush( vNames, pPin->pName );
+        pObj = Amap_ParseFormula( stdout, pGate->pForm, vNames, pMan );
+        if ( pObj == NULL )
+            break;
+        pTruth = Hop_ManConvertAigToTruth( pMan, pObj, pGate->nPins, vTruth, 0 );
+        if ( Kit_TruthSupportSize(pTruth, pGate->nPins) < (int)pGate->nPins )
+        {
+            if ( fVerbose )
+                printf( "Skipping gate \"%s\" because its output \"%s\" does not depend on all input variables.\n", pGate->pName, pGate->pForm );
+            continue;
+        }
+        pGate->pFunc = (unsigned *)Aig_MmFlexEntryFetch( p->pMemGates, sizeof(unsigned)*Abc_TruthWordNum(pGate->nPins) );
+        memcpy( pGate->pFunc, pTruth, sizeof(unsigned)*Abc_TruthWordNum(pGate->nPins) );
+    }
+    Vec_PtrFree( vNames );
+    Vec_IntFree( vTruth );
+    Hop_ManStop( pMan );
+    return i == Vec_PtrSize(p->vGates);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses equations for the gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_LibParseTest( char * pFileName )
+{
+    int fVerbose = 0;
+    Amap_Lib_t * p;
+    abctime clk = Abc_Clock();
+    p = Amap_LibReadFile( pFileName, fVerbose );
+    if ( p == NULL )
+        return;
+    Amap_LibParseEquations( p, fVerbose );
+    Amap_LibFree( p );
+    ABC_PRT( "Total time", Abc_Clock() - clk );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/amap/amapPerm.c b/abc-build/src/map/amap/amapPerm.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/amap/amapPerm.c
@@ -0,0 +1,380 @@
+/**CFile****************************************************************
+
+  FileName    [amapPerm.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Technology mapper for standard cells.]
+
+  Synopsis    [Deriving permutation for the gate.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: amapPerm.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Collects fanins of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_LibCollectFanins_rec( Amap_Lib_t * pLib, Amap_Nod_t * pNod, Vec_Int_t * vFanins )
+{
+    Amap_Nod_t * pFan0, * pFan1;
+    if ( pNod->Id == 0 )
+    {
+        Vec_IntPush( vFanins, 0 );
+        return;
+    }
+    pFan0 = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan0) );
+    if ( Abc_LitIsCompl(pNod->iFan0) || pFan0->Type != pNod->Type )
+        Vec_IntPush( vFanins, pNod->iFan0 );
+    else
+        Amap_LibCollectFanins_rec( pLib, pFan0, vFanins );
+    pFan1 = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan1) );
+    if ( Abc_LitIsCompl(pNod->iFan1) || pFan1->Type != pNod->Type )
+        Vec_IntPush( vFanins, pNod->iFan1 );
+    else
+        Amap_LibCollectFanins_rec( pLib, pFan1, vFanins );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects fanins of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Amap_LibCollectFanins( Amap_Lib_t * pLib, Amap_Nod_t * pNod )
+{
+    Vec_Int_t * vFanins = Vec_IntAlloc( 10 );
+    Amap_LibCollectFanins_rec( pLib, pNod, vFanins );
+    return vFanins;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Matches the node with the DSD node.]
+
+  Description [Returns perm if the node can be matched.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Amap_LibDeriveGatePerm_rec( Amap_Lib_t * pLib, Kit_DsdNtk_t * pNtk, int iLit, Amap_Nod_t * pNod )
+{
+    Vec_Int_t * vPerm, * vPermFanin, * vNodFanin, * vDsdLits;
+    Kit_DsdObj_t * pDsdObj, * pDsdFanin;
+    Amap_Nod_t * pNodFanin;
+    int iDsdFanin, iNodFanin, Value, iDsdLit, i, k, j;
+//    assert( !Abc_LitIsCompl(iLit) );
+    pDsdObj = Kit_DsdNtkObj( pNtk, Abc_Lit2Var(iLit) );
+    if ( pDsdObj == NULL )
+    {
+        vPerm = Vec_IntAlloc( 1 );
+        Vec_IntPush( vPerm, iLit );
+        return vPerm;
+    }
+    if ( pDsdObj->Type == KIT_DSD_PRIME && pNod->Type == AMAP_OBJ_MUX )
+    {
+        vPerm = Vec_IntAlloc( 10 );
+
+        iDsdFanin  = pDsdObj->pFans[0];
+        pNodFanin  = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan0) );
+        vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin );
+        if ( vPermFanin == NULL )
+        {
+            Vec_IntFree( vPerm );
+            return NULL;
+        }
+        Vec_IntForEachEntry( vPermFanin, Value, k )
+            Vec_IntPush( vPerm, Value );
+        Vec_IntFree( vPermFanin );
+
+        iDsdFanin  = pDsdObj->pFans[1];
+        pNodFanin  = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan1) );
+        vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin );
+        if ( vPermFanin == NULL )
+        {
+            Vec_IntFree( vPerm );
+            return NULL;
+        }
+        Vec_IntForEachEntry( vPermFanin, Value, k )
+            Vec_IntPush( vPerm, Value );
+        Vec_IntFree( vPermFanin );
+
+        iDsdFanin  = pDsdObj->pFans[2];
+        pNodFanin  = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan2) );
+        vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin );
+        if ( vPermFanin == NULL )
+        {
+            Vec_IntFree( vPerm );
+            return NULL;
+        }
+        Vec_IntForEachEntry( vPermFanin, Value, k )
+            Vec_IntPush( vPerm, Value );
+        Vec_IntFree( vPermFanin );
+
+        return vPerm;
+    }
+    // return if wrong types
+    if ( pDsdObj->Type == KIT_DSD_PRIME || pNod->Type == AMAP_OBJ_MUX )
+        return NULL;
+    // return if sizes do not agree
+    vNodFanin = Amap_LibCollectFanins( pLib, pNod );
+    if ( Vec_IntSize(vNodFanin) != (int)pDsdObj->nFans )
+    {
+        Vec_IntFree( vNodFanin );
+        return NULL;
+    }
+    // match fanins of DSD with fanins of nodes
+    // clean the mark and save variable literals
+    vPerm = Vec_IntAlloc( 10 );
+    vDsdLits = Vec_IntAlloc( 10 );
+    Kit_DsdObjForEachFaninReverse( pNtk, pDsdObj, iDsdFanin, i )
+    {
+        pDsdFanin = Kit_DsdNtkObj( pNtk, Abc_Lit2Var(iDsdFanin) );
+        if ( pDsdFanin )
+            pDsdFanin->fMark = 0;
+        else
+            Vec_IntPush( vDsdLits, iDsdFanin );
+    }
+    // match each fanins of the node
+    iDsdLit = 0;
+    Vec_IntForEachEntry( vNodFanin, iNodFanin, k )
+    {
+        if ( iNodFanin == 0 )
+        {
+            if ( iDsdLit >= Vec_IntSize(vDsdLits) )
+            {
+                Vec_IntFree( vPerm );
+                Vec_IntFree( vDsdLits );
+                Vec_IntFree( vNodFanin );
+                return NULL;
+            }
+            iDsdFanin = Vec_IntEntry( vDsdLits, iDsdLit++ );
+            Vec_IntPush( vPerm, iDsdFanin );
+            continue;
+        }
+        // find a matching component
+        pNodFanin = Amap_LibNod( pLib, Abc_Lit2Var(iNodFanin) );
+        Kit_DsdObjForEachFaninReverse( pNtk, pDsdObj, iDsdFanin, i )
+        {
+            pDsdFanin = Kit_DsdNtkObj( pNtk, Abc_Lit2Var(iDsdFanin) );
+            if ( pDsdFanin == NULL )
+                continue;
+            if ( pDsdFanin->fMark == 1 )
+                continue;
+            if ( !((pDsdFanin->Type == KIT_DSD_AND && pNodFanin->Type == AMAP_OBJ_AND) ||
+                   (pDsdFanin->Type == KIT_DSD_XOR && pNodFanin->Type == AMAP_OBJ_XOR) ||
+                   (pDsdFanin->Type == KIT_DSD_PRIME && pNodFanin->Type == AMAP_OBJ_MUX)) )
+                   continue;
+            vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, Abc_LitRegular(iDsdFanin), pNodFanin );
+            if ( vPermFanin == NULL )
+            {
+                Vec_IntFree( vNodFanin );
+                Vec_IntFree( vDsdLits );
+                Vec_IntFree( vPerm );
+                return NULL;
+            }
+            pDsdFanin->fMark = 1;
+            Vec_IntForEachEntry( vPermFanin, Value, j )
+                Vec_IntPush( vPerm, Value );
+            Vec_IntFree( vPermFanin );
+            break;
+        }
+    }
+//    assert( iDsdLit == Vec_IntSize(vDsdLits) );
+    if ( iDsdLit != Vec_IntSize(vDsdLits) )
+        Vec_IntFreeP( &vPerm );
+    Vec_IntFree( vNodFanin );
+    Vec_IntFree( vDsdLits );
+    return vPerm;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs verification of one gate and one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Amap_LibVerifyPerm_rec( Amap_Lib_t * pLib, Amap_Nod_t * pNod, 
+    Vec_Ptr_t * vTtElems, Vec_Int_t * vTruth, int nWords, int * piInput )
+{
+    Amap_Nod_t * pFan0, * pFan1;
+    unsigned * pTruth0, * pTruth1, * pTruth;
+    int i;
+    assert( pNod->Type != AMAP_OBJ_MUX );
+    if ( pNod->Id == 0 )
+        return (unsigned *)Vec_PtrEntry( vTtElems, (*piInput)++ );
+    pFan0 = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan0) );
+    pTruth0 = Amap_LibVerifyPerm_rec( pLib, pFan0, vTtElems, vTruth, nWords, piInput );
+    pFan1 = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan1) );
+    pTruth1 = Amap_LibVerifyPerm_rec( pLib, pFan1, vTtElems, vTruth, nWords, piInput );
+    pTruth  = Vec_IntFetch( vTruth, nWords );
+    if ( pNod->Type == AMAP_OBJ_XOR )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = pTruth0[i] ^ pTruth1[i];
+    else if ( !Abc_LitIsCompl(pNod->iFan0) && !Abc_LitIsCompl(pNod->iFan1) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = pTruth0[i] & pTruth1[i];
+    else if ( !Abc_LitIsCompl(pNod->iFan0) && Abc_LitIsCompl(pNod->iFan1) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = pTruth0[i] & ~pTruth1[i];
+    else if ( Abc_LitIsCompl(pNod->iFan0) && !Abc_LitIsCompl(pNod->iFan1) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ~pTruth0[i] & pTruth1[i];
+    else // if ( Abc_LitIsCompl(pNod->iFan0) && Hop_ObjFaninC1(pObj) )
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ~pTruth0[i] & ~pTruth1[i];
+    return pTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs verification of one gate and one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_LibVerifyPerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t * pNtk, Amap_Nod_t * pNod, int * pArray )
+{
+    Vec_Ptr_t * vTtElems;
+    Vec_Ptr_t * vTtElemsPol;
+    Vec_Int_t * vTruth;
+    unsigned * pTruth;
+    int i, nWords;
+    int iInput = 0;
+
+    // allocate storage for truth tables
+    assert( pGate->nPins > 1 );
+    nWords = Kit_TruthWordNum( pGate->nPins );
+    vTruth = Vec_IntAlloc( nWords * AMAP_MAXINS );
+    vTtElems = Vec_PtrAllocTruthTables( pGate->nPins );
+    vTtElemsPol = Vec_PtrAlloc( pGate->nPins );
+    for ( i = 0; i < (int)pGate->nPins; i++ )
+    {
+        pTruth = (unsigned *)Vec_PtrEntry( vTtElems, Abc_Lit2Var(pArray[i]) );
+        if ( Abc_LitIsCompl( pArray[i] ) )
+            Kit_TruthNot( pTruth, pTruth, pGate->nPins );
+        Vec_PtrPush( vTtElemsPol, pTruth );
+    }
+//Extra_PrintBinary( stdout, Vec_PtrEntry(vTtElemsPol, 0), 4 ); printf("\n" );
+//Extra_PrintBinary( stdout, Vec_PtrEntry(vTtElemsPol, 1), 4 ); printf("\n" );
+    // compute the truth table recursively
+    pTruth = Amap_LibVerifyPerm_rec( pLib, pNod, vTtElemsPol, vTruth, nWords, &iInput );
+    assert( iInput == (int)pGate->nPins );
+    if ( Abc_LitIsCompl(pNtk->Root) )
+        Kit_TruthNot( pTruth, pTruth, pGate->nPins );
+//Extra_PrintBinary( stdout, pTruth, 4 ); printf("\n" );
+//Extra_PrintBinary( stdout, pGate->pFunc, 4 ); printf("\n" );
+    // compare
+    if ( !Kit_TruthIsEqual(pGate->pFunc, pTruth, pGate->nPins) )
+        printf( "Verification failed for gate %d (%s) and node %d.\n",
+            pGate->Id, pGate->pForm, pNod->Id );
+    Vec_IntFree( vTruth );
+    Vec_PtrFree( vTtElems );
+    Vec_PtrFree( vTtElemsPol );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Matches the node with the DSD of a gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_LibDeriveGatePerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t * pNtk, Amap_Nod_t * pNod, char * pArray )
+{
+    int fVerbose = 0;
+    Vec_Int_t * vPerm;
+    int Entry, Entry2, i, k;
+//    Kit_DsdPrint( stdout, pNtk );
+
+    vPerm = Amap_LibDeriveGatePerm_rec( pLib, pNtk, Abc_LitRegular(pNtk->Root), pNod );
+    if ( vPerm == NULL )
+        return 0;
+    // check that the permutation is valid
+    assert( Vec_IntSize(vPerm) == (int)pNod->nSuppSize );
+    Vec_IntForEachEntry( vPerm, Entry, i )
+        Vec_IntForEachEntryStart( vPerm, Entry2, k, i+1 )
+            if ( Abc_Lit2Var(Entry) == Abc_Lit2Var(Entry2) )
+            {
+                Vec_IntFree( vPerm );
+                return 0;
+            }
+
+    // reverse the permutation
+    Vec_IntForEachEntry( vPerm, Entry, i )
+    {
+        assert( Entry < 2 * (int)pNod->nSuppSize );
+        pArray[Abc_Lit2Var(Entry)] = Abc_Var2Lit( i, Abc_LitIsCompl(Entry) );
+//        pArray[i] = Entry;
+//printf( "%d=%d%c ", Abc_Lit2Var(Entry), i, Abc_LitIsCompl(Entry)?'-':'+' );
+    }
+//printf( "\n" );
+//    if ( Kit_DsdNonDsdSizeMax(pNtk) < 3 )
+//        Amap_LibVerifyPerm( pLib, pGate, pNtk, pNod, Vec_IntArray(vPerm) );
+    Vec_IntFree( vPerm );
+    // print the result
+    if ( fVerbose )
+    {
+    printf( "node %4d : ", pNod->Id );
+    for ( i = 0; i < (int)pNod->nSuppSize; i++ )
+        printf( "%d=%d%c ", i, Abc_Lit2Var(pArray[i]), Abc_LitIsCompl(pArray[i])?'-':'+' );
+    printf( "\n" );
+    }
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/amap/amapRead.c b/abc-build/src/map/amap/amapRead.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/amap/amapRead.c
@@ -0,0 +1,493 @@
+/**CFile****************************************************************
+
+  FileName    [amapRead.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Technology mapper for standard cells.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: amapRead.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+#include "base/io/ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define AMAP_STRING_GATE       "GATE"
+#define AMAP_STRING_PIN        "PIN"
+#define AMAP_STRING_NONINV     "NONINV"
+#define AMAP_STRING_INV        "INV"
+#define AMAP_STRING_UNKNOWN    "UNKNOWN"
+
+// these symbols (and no other) can appear in the formulas
+#define AMAP_SYMB_AND    '*'
+#define AMAP_SYMB_OR1    '+'
+#define AMAP_SYMB_OR2    '|'
+#define AMAP_SYMB_XOR    '^'
+#define AMAP_SYMB_NOT    '!'
+#define AMAP_SYMB_AFTNOT '\''
+#define AMAP_SYMB_OPEN   '('
+#define AMAP_SYMB_CLOSE  ')'
+
+typedef enum { 
+    AMAP_PHASE_UNKNOWN, 
+    AMAP_PHASE_INV, 
+    AMAP_PHASE_NONINV 
+} Amap_PinPhase_t;
+
+static inline Amap_Gat_t * Amap_ParseGateAlloc( Aig_MmFlex_t * p, int nPins ) 
+{ return (Amap_Gat_t *)Aig_MmFlexEntryFetch( p, sizeof(Amap_Gat_t)+sizeof(Amap_Pin_t)*nPins ); }
+static inline char * Amap_ParseStrsav( Aig_MmFlex_t * p, char * pStr ) 
+{ return pStr ? strcpy(Aig_MmFlexEntryFetch(p, strlen(pStr)+1), pStr) : NULL; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Loads the file into temporary buffer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Amap_LoadFile( char * pFileName )
+{
+//    extern FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose );
+    FILE * pFile;
+    char * pBuffer;
+    int nFileSize;
+    int RetValue;
+    // open the BLIF file for binary reading
+    pFile = Io_FileOpen( pFileName, "open_path", "rb", 1 );
+//    pFile = fopen( FileName, "rb" );
+    // if we got this far, file should be okay otherwise would
+    // have been detected by caller
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\".\n", pFileName );
+        return NULL;
+    }
+    assert ( pFile != NULL );
+    // get the file size, in bytes
+    fseek( pFile, 0, SEEK_END );  
+    nFileSize = ftell( pFile );  
+    // move the file current reading position to the beginning
+    rewind( pFile ); 
+    // load the contents of the file into memory
+    pBuffer = ABC_ALLOC( char, nFileSize + 10 );
+    RetValue = fread( pBuffer, nFileSize, 1, pFile );
+    // terminate the string with '\0'
+    pBuffer[ nFileSize ] = '\0';
+    strcat( pBuffer, "\n.end\n" );
+    // close file
+    fclose( pFile );
+    return pBuffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Eliminates comments from the input file.]
+
+  Description [As a byproduct, this procedure also counts the number
+  lines and dot-statements in the input file. This also joins non-comment 
+  lines that are joined with a backspace '\']
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_RemoveComments( char * pBuffer, int * pnDots, int * pnLines )
+{
+    char * pCur;
+    int nDots, nLines;
+    // scan through the buffer and eliminate comments
+    // (in the BLIF file, comments are lines starting with "#")
+    nDots = nLines = 0;
+    for ( pCur = pBuffer; *pCur; pCur++ )
+    {
+        // if this is the beginning of comment
+        // clean it with spaces until the new line statement
+        if ( *pCur == '#' )
+            while ( *pCur != '\n' )
+                *pCur++ = ' ';
+	
+        // count the number of new lines and dots
+        if ( *pCur == '\n' ) {
+	    if (*(pCur-1)=='\r') {
+		// DOS(R) file support
+		if (*(pCur-2)!='\\') nLines++;
+		else {
+		    // rewind to backslash and overwrite with a space
+		    *(pCur-2) = ' ';
+		    *(pCur-1) = ' ';
+		    *pCur = ' ';
+		}
+	    } else {
+		// UNIX(TM) file support
+		if (*(pCur-1)!='\\') nLines++;
+		else {
+		    // rewind to backslash and overwrite with a space
+		    *(pCur-1) = ' ';
+		    *pCur = ' ';
+		}
+	    }
+	}
+        else if ( *pCur == '.' )
+            nDots++;
+    }
+    if ( pnDots )
+        *pnDots = nDots; 
+    if ( pnLines )
+        *pnLines = nLines; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Splits the stream into tokens.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Amap_DeriveTokens( char * pBuffer )
+{
+    Vec_Ptr_t * vTokens;
+    char * pToken;
+    vTokens = Vec_PtrAlloc( 1000 );
+    pToken = strtok( pBuffer, " =\t\r\n" );
+    while ( pToken )
+    {
+        Vec_PtrPush( vTokens, pToken );
+        pToken = strtok( NULL, " =\t\r\n" );
+        // skip latches
+        if ( pToken && strcmp( pToken, "LATCH" ) == 0 )
+            while ( pToken && strcmp( pToken, "GATE" ) != 0 )
+                pToken = strtok( NULL, " =\t\r\n" );
+    }
+    return vTokens;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the number of pins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_ParseCountPins( Vec_Ptr_t * vTokens, int iPos )
+{
+    char * pToken;
+    int i, Counter = 0;
+    Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, iPos )
+        if ( !strcmp( pToken, AMAP_STRING_PIN ) )
+            Counter++;
+        else if ( !strcmp( pToken, AMAP_STRING_GATE ) )
+            return Counter;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect the pin names used in the formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_GateCollectNames( Aig_MmFlex_t * pMem, char * pForm, char * pPinNames[] )
+{
+    char Buffer[1000];
+    char * pTemp;
+    int nPins, i;
+    // save the formula as it was
+    strcpy( Buffer, pForm );
+    // remove the non-name symbols
+    for ( pTemp = Buffer; *pTemp; pTemp++ )
+        if ( *pTemp == AMAP_SYMB_AND || *pTemp == AMAP_SYMB_OR1 || *pTemp == AMAP_SYMB_OR2 
+          || *pTemp == AMAP_SYMB_XOR || *pTemp == AMAP_SYMB_NOT || *pTemp == AMAP_SYMB_OPEN 
+          || *pTemp == AMAP_SYMB_CLOSE || *pTemp == AMAP_SYMB_AFTNOT )
+            *pTemp = ' ';
+    // save the names
+    nPins = 0;
+    pTemp = strtok( Buffer, " " );
+    while ( pTemp )
+    {
+        for ( i = 0; i < nPins; i++ )
+            if ( strcmp( pTemp, pPinNames[i] ) == 0 )
+                break;
+        if ( i == nPins )
+        { // cannot find this name; save it
+            pPinNames[nPins++] = Amap_ParseStrsav( pMem, pTemp );
+        }
+        // get the next name
+        pTemp = strtok( NULL, " " );
+    }
+    return nPins;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a duplicate gate with pins specified.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Gat_t * Amap_ParseGateWithSamePins( Amap_Gat_t * p )
+{
+    Amap_Gat_t * pGate;
+    Amap_Pin_t * pPin;
+    char * pPinNames[128];
+    int nPinNames;
+    assert( p->nPins == 1 && !strcmp( p->Pins->pName, "*" ) );
+    nPinNames = Amap_GateCollectNames( p->pLib->pMemGates, p->pForm, pPinNames );
+    pGate = Amap_ParseGateAlloc( p->pLib->pMemGates, nPinNames );
+    *pGate = *p;
+    pGate->nPins = nPinNames;
+    Amap_GateForEachPin( pGate, pPin )
+    {
+        *pPin = *p->Pins;
+        pPin->pName = pPinNames[pPin - pGate->Pins];
+    }
+    return pGate;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_CollectFormulaTokens( Vec_Ptr_t * vTokens, char * pToken, int iPos )
+{
+    char * pNext, * pPrev;
+    pPrev = pToken + strlen(pToken);
+    while ( *(pPrev-1) != ';' )
+    {
+        *pPrev++ = ' ';
+        pNext = (char *)Vec_PtrEntry(vTokens, iPos++);
+        while ( *pNext )
+            *pPrev++ = *pNext++;
+    }
+    *(pPrev-1) = 0;
+    return iPos;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Lib_t * Amap_ParseTokens( Vec_Ptr_t * vTokens, int fVerbose )
+{
+    Amap_Lib_t * p;
+    Amap_Gat_t * pGate, * pPrev;
+    Amap_Pin_t * pPin;
+    char * pToken, * pMoGate = NULL;
+    int i, nPins, iPos = 0, Count = 0;
+    p = Amap_LibAlloc();
+    pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
+    do 
+    {
+        if ( strcmp( pToken, AMAP_STRING_GATE ) )
+        {
+            Amap_LibFree( p );
+            printf( "The first line should begin with %s.\n", AMAP_STRING_GATE );
+            return NULL;
+        }
+        // start gate
+        nPins = Amap_ParseCountPins( vTokens, iPos );
+        pGate = Amap_ParseGateAlloc( p->pMemGates, nPins );
+        memset( pGate, 0, sizeof(Amap_Gat_t) );
+        pGate->Id = Vec_PtrSize( p->vGates );
+        Vec_PtrPush( p->vGates, pGate );
+        pGate->pLib = p;
+        pGate->nPins = nPins;
+        // read gate
+        pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
+        pGate->pName = Amap_ParseStrsav( p->pMemGates, pToken );    
+        pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
+        pGate->dArea = atof( pToken );
+        pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
+        pGate->pOutName = Amap_ParseStrsav( p->pMemGates, pToken ); 
+        pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
+        iPos = Amap_CollectFormulaTokens( vTokens, pToken, iPos );
+        pGate->pForm = Amap_ParseStrsav( p->pMemGates, pToken ); 
+        // read pins
+        Amap_GateForEachPin( pGate, pPin )
+        {
+            pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
+            if ( strcmp( pToken, AMAP_STRING_PIN ) )
+            {
+                Amap_LibFree( p );
+                printf( "Cannot parse gate %s.\n", pGate->pName );
+                return NULL;
+            }
+            // read pin
+            pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
+            pPin->pName = Amap_ParseStrsav( p->pMemGates, pToken );   
+            pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
+            if ( strcmp( pToken, AMAP_STRING_UNKNOWN ) == 0 )
+                pPin->Phase = AMAP_PHASE_UNKNOWN;
+            else if ( strcmp( pToken, AMAP_STRING_INV ) == 0 )
+                pPin->Phase = AMAP_PHASE_INV;
+            else if ( strcmp( pToken, AMAP_STRING_NONINV ) == 0 )
+                pPin->Phase = AMAP_PHASE_NONINV;
+            else 
+            {
+                Amap_LibFree( p );
+                printf( "Cannot read phase of pin %s of gate %s\n", pPin->pName, pGate->pName );
+                return NULL;
+            }
+            pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
+            pPin->dLoadInput = atof( pToken );
+            pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
+            pPin->dLoadMax = atof( pToken );
+            pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
+            pPin->dDelayBlockRise = atof( pToken );
+            pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
+            pPin->dDelayFanoutRise = atof( pToken );
+            pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
+            pPin->dDelayBlockFall = atof( pToken );
+            pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
+            pPin->dDelayFanoutFall = atof( pToken );
+            if ( pPin->dDelayBlockRise > pPin->dDelayBlockFall )
+                pPin->dDelayBlockMax = pPin->dDelayBlockRise;
+            else
+                pPin->dDelayBlockMax = pPin->dDelayBlockFall;
+        }
+        // fix the situation when all pins are represented as one
+        if ( pGate->nPins == 1 && !strcmp( pGate->Pins->pName, "*" ) )
+        {
+            pGate = Amap_ParseGateWithSamePins( pGate );
+            Vec_PtrPop( p->vGates );
+            Vec_PtrPush( p->vGates, pGate );
+        }
+        pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
+//printf( "Finished reading gate %s (%s)\n", pGate->pName, pGate->pOutName );
+    }
+    while ( strcmp( pToken, ".end" ) );
+
+    // check if there are gates with identical names
+    pPrev = NULL;
+    Amap_LibForEachGate( p, pGate, i )
+    {
+        if ( pPrev && !strcmp(pPrev->pName, pGate->pName) )
+        {
+            pPrev->pTwin = pGate, pGate->pTwin = pPrev;
+//            printf( "Warning: Detected multi-output gate \"%s\".\n", pGate->pName );
+            if ( pMoGate == NULL )
+                pMoGate = pGate->pName;
+            Count++;
+        }
+        pPrev = pGate;
+    }
+    if ( Count )
+        printf( "Warning: Detected %d multi-output gates (for example, \"%s\").\n", Count, pMoGate );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the library from the input file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Lib_t * Amap_LibReadBuffer( char * pBuffer, int fVerbose )
+{
+    Amap_Lib_t * pLib;
+    Vec_Ptr_t * vTokens;
+    Amap_RemoveComments( pBuffer, NULL, NULL );
+    vTokens = Amap_DeriveTokens( pBuffer );
+    pLib = Amap_ParseTokens( vTokens, fVerbose );
+    if ( pLib == NULL )
+    {
+        Vec_PtrFree( vTokens );
+        return NULL;
+    }
+    Vec_PtrFree( vTokens );
+    return pLib;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the library from the input file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Lib_t * Amap_LibReadFile( char * pFileName, int fVerbose )
+{
+    Amap_Lib_t * pLib;
+    char * pBuffer;
+    pBuffer = Amap_LoadFile( pFileName );
+    if ( pBuffer == NULL )
+        return NULL;
+    pLib = Amap_LibReadBuffer( pBuffer, fVerbose );
+    if ( pLib )
+        pLib->pName = Abc_UtilStrsav( pFileName );
+    ABC_FREE( pBuffer );
+    return pLib;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/amap/amapRule.c b/abc-build/src/map/amap/amapRule.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/amap/amapRule.c
@@ -0,0 +1,462 @@
+/**CFile****************************************************************
+
+  FileName    [amapRule.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Technology mapper for standard cells.]
+
+  Synopsis    [Matching rules.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: amapRule.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Amap_LibDeriveGatePerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t * pNtk, Amap_Nod_t * pNod, char * pArray );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the three-argument rule exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Amap_CreateRulesPrime( Amap_Lib_t * p, Vec_Int_t * vNods0, Vec_Int_t * vNods1, Vec_Int_t * vNods2 )
+{
+    Vec_Int_t * vRes;
+    int i, k, j, iNod, iNod0, iNod1, iNod2;
+    if ( p->vRules3 == NULL )
+        p->vRules3 = Vec_IntAlloc( 100 );
+    vRes = Vec_IntAlloc( 10 );
+    Vec_IntForEachEntry( vNods0, iNod0, i )
+    Vec_IntForEachEntry( vNods1, iNod1, k )
+    Vec_IntForEachEntry( vNods2, iNod2, j )
+    {
+        iNod = Amap_LibFindMux( p, iNod0, iNod1, iNod2 );
+        if ( iNod == -1 )
+            iNod = Amap_LibCreateMux( p, iNod0, iNod1, iNod2 );
+        Vec_IntPush( vRes, Abc_Var2Lit(iNod, 0) );
+    }
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_CreateRulesTwo( Amap_Lib_t * p, Vec_Int_t * vNods, Vec_Int_t * vNods0, Vec_Int_t * vNods1, int fXor )
+{
+    int i, k, iNod, iNod0, iNod1;
+    Vec_IntForEachEntry( vNods0, iNod0, i )
+    Vec_IntForEachEntry( vNods1, iNod1, k )
+    {
+        iNod = Amap_LibFindNode( p, iNod0, iNod1, fXor );
+        if ( iNod == -1 )
+            iNod = Amap_LibCreateNode( p, iNod0, iNod1, fXor );
+        Vec_IntPushUnique( vNods, Abc_Var2Lit(iNod, 0) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_CreateCheckAllZero( Vec_Ptr_t * vVecNods )
+{
+    Vec_Int_t * vNods;
+    int i;
+    Vec_PtrForEachEntryReverse( Vec_Int_t *, vVecNods, vNods, i )
+        if ( Vec_IntSize(vNods) != 1 || Vec_IntEntry(vNods,0) != 0 )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Amap_CreateRulesVector_rec( Amap_Lib_t * p, Vec_Ptr_t * vVecNods, int fXor )
+{
+    Vec_Ptr_t * vVecNods0, * vVecNods1;
+    Vec_Int_t * vRes, * vNods, * vNods0, * vNods1;
+    int i, k;
+    if ( Vec_PtrSize(vVecNods) == 1 )
+        return Vec_IntDup( (Vec_Int_t *)Vec_PtrEntry(vVecNods, 0) );
+    vRes = Vec_IntAlloc( 10 );
+    vVecNods0 = Vec_PtrAlloc( Vec_PtrSize(vVecNods) );
+    vVecNods1 = Vec_PtrAlloc( Vec_PtrSize(vVecNods) );
+    if ( Amap_CreateCheckAllZero(vVecNods) )
+    {
+        for ( i = Vec_PtrSize(vVecNods)-1; i > 0; i-- )
+        {
+            Vec_PtrClear( vVecNods0 );
+            Vec_PtrClear( vVecNods1 );
+            Vec_PtrForEachEntryStop( Vec_Int_t *, vVecNods, vNods, k, i )
+                Vec_PtrPush( vVecNods0, vNods );
+            Vec_PtrForEachEntryStart( Vec_Int_t *, vVecNods, vNods, k, i )
+                Vec_PtrPush( vVecNods1, vNods );
+            vNods0 = Amap_CreateRulesVector_rec( p, vVecNods0, fXor );
+            vNods1 = Amap_CreateRulesVector_rec( p, vVecNods1, fXor );
+            Amap_CreateRulesTwo( p, vRes, vNods0, vNods1, fXor );
+            Vec_IntFree( vNods0 );
+            Vec_IntFree( vNods1 );
+        }
+    }
+    else
+    {
+        int Limit = (1 << Vec_PtrSize(vVecNods))-2;
+        for ( i = 1; i < Limit; i++ )
+        {
+            Vec_PtrClear( vVecNods0 );
+            Vec_PtrClear( vVecNods1 );
+            Vec_PtrForEachEntryReverse( Vec_Int_t *, vVecNods, vNods, k )
+            {
+                if ( i & (1 << k) )
+                    Vec_PtrPush( vVecNods1, vNods );
+                else
+                    Vec_PtrPush( vVecNods0, vNods );
+            }
+            assert( Vec_PtrSize(vVecNods0) > 0 );
+            assert( Vec_PtrSize(vVecNods1) > 0 );
+            assert( Vec_PtrSize(vVecNods0) < Vec_PtrSize(vVecNods) );
+            assert( Vec_PtrSize(vVecNods1) < Vec_PtrSize(vVecNods) );
+            vNods0 = Amap_CreateRulesVector_rec( p, vVecNods0, fXor );
+            vNods1 = Amap_CreateRulesVector_rec( p, vVecNods1, fXor );
+            Amap_CreateRulesTwo( p, vRes, vNods0, vNods1, fXor );
+            Vec_IntFree( vNods0 );
+            Vec_IntFree( vNods1 );
+        }
+    }
+    Vec_PtrFree( vVecNods0 );
+    Vec_PtrFree( vVecNods1 );
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Amap_CreateRulesFromDsd_rec( Amap_Lib_t * pLib, Kit_DsdNtk_t * p, int iLit )
+{
+    Vec_Int_t * vRes;
+    Vec_Ptr_t * vVecNods;
+    Vec_Int_t * vNodsFanin;
+    Kit_DsdObj_t * pObj;
+    unsigned i;
+    int iFanin, iNod, k;
+    assert( !Abc_LitIsCompl(iLit) );
+    pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) );
+    if ( pObj == NULL )
+        return Vec_IntStartNatural( 1 );
+    // solve for the inputs
+    vVecNods = Vec_PtrAlloc( pObj->nFans );
+    Kit_DsdObjForEachFanin( p, pObj, iFanin, i )
+    {
+        vNodsFanin = Amap_CreateRulesFromDsd_rec( pLib, p, Abc_LitRegular(iFanin) );
+        if ( Abc_LitIsCompl(iFanin) )
+        {
+            Vec_IntForEachEntry( vNodsFanin, iNod, k )
+                if ( iNod > 0 )
+                    Vec_IntWriteEntry( vNodsFanin, k, Abc_LitNot(iNod) );
+        }
+        Vec_PtrPush( vVecNods, vNodsFanin );
+    }
+    if ( pObj->Type == KIT_DSD_AND )
+        vRes = Amap_CreateRulesVector_rec( pLib, vVecNods, 0 );
+    else if ( pObj->Type == KIT_DSD_XOR )
+        vRes = Amap_CreateRulesVector_rec( pLib, vVecNods, 1 );
+    else if ( pObj->Type == KIT_DSD_PRIME )
+    {
+        assert( pObj->nFans == 3 );
+        assert( Kit_DsdObjTruth(pObj)[0] == 0xCACACACA );
+        vRes = Amap_CreateRulesPrime( pLib, (Vec_Int_t *)Vec_PtrEntry(vVecNods, 0),
+            (Vec_Int_t *)Vec_PtrEntry(vVecNods, 1), (Vec_Int_t *)Vec_PtrEntry(vVecNods, 2) );
+    }
+    else assert( 0 );
+    Vec_PtrForEachEntry( Vec_Int_t *, vVecNods, vNodsFanin, k )
+        Vec_IntFree( vNodsFanin );
+    Vec_PtrFree( vVecNods );
+    return vRes;
+}
+Vec_Int_t * Amap_CreateRulesFromDsd( Amap_Lib_t * pLib, Kit_DsdNtk_t * p )
+{
+    Vec_Int_t * vNods;
+    int iNod, i;
+    assert( p->nVars >= 2 );
+    vNods = Amap_CreateRulesFromDsd_rec( pLib, p, Abc_LitRegular(p->Root) );
+    if ( vNods == NULL )
+        return NULL;
+    if ( Abc_LitIsCompl(p->Root) )
+    {
+        Vec_IntForEachEntry( vNods, iNod, i )
+            Vec_IntWriteEntry( vNods, i, Abc_LitNot(iNod) );
+    }
+    return vNods;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if DSD network contains asymentry due to complements.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_CreateCheckEqual_rec( Kit_DsdNtk_t * p, int iLit0, int iLit1 )
+{
+    Kit_DsdObj_t * pObj0, * pObj1; 
+    int i;
+    assert( !Abc_LitIsCompl(iLit0) );
+    assert( !Abc_LitIsCompl(iLit1) );
+    pObj0 = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit0) );
+    pObj1 = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit1) );
+    if ( pObj0 == NULL && pObj1 == NULL )
+        return 1;
+    if ( pObj0 == NULL || pObj1 == NULL )
+        return 0;
+    if ( pObj0->Type != pObj1->Type )
+        return 0;
+    if ( pObj0->nFans != pObj1->nFans )
+        return 0;
+    if ( pObj0->Type == KIT_DSD_PRIME )
+        return 0;
+    assert( pObj0->Type == KIT_DSD_AND || pObj0->Type == KIT_DSD_XOR );
+    for ( i = 0; i < (int)pObj0->nFans; i++ )
+    {
+        if ( Abc_LitIsCompl(pObj0->pFans[i]) != Abc_LitIsCompl(pObj1->pFans[i]) )
+            return 0;
+        if ( !Amap_CreateCheckEqual_rec( p, Abc_LitRegular(pObj0->pFans[i]), Abc_LitRegular(pObj1->pFans[i]) ) )
+            return 0;
+    }
+    return 1;
+}
+void Amap_CreateCheckAsym_rec( Kit_DsdNtk_t * p, int iLit, Vec_Int_t ** pvSyms )
+{
+    Kit_DsdObj_t * pObj; 
+    int i, k, iFanin;
+    assert( !Abc_LitIsCompl(iLit) );
+    pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) );
+    if ( pObj == NULL )
+        return;
+    Kit_DsdObjForEachFanin( p, pObj, iFanin, i )
+        Amap_CreateCheckAsym_rec( p, Abc_LitRegular(iFanin), pvSyms );
+    if ( pObj->Type == KIT_DSD_PRIME )
+        return;
+    assert( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR );
+    for ( i = 0; i < (int)pObj->nFans; i++ )
+    for ( k = i+1; k < (int)pObj->nFans; k++ )
+    {
+        if ( Abc_LitIsCompl(pObj->pFans[i]) != Abc_LitIsCompl(pObj->pFans[k]) && 
+             Kit_DsdNtkObj(p, Abc_Lit2Var(pObj->pFans[i])) == NULL && 
+             Kit_DsdNtkObj(p, Abc_Lit2Var(pObj->pFans[k])) == NULL )
+        {
+            if ( *pvSyms == NULL )
+                *pvSyms = Vec_IntAlloc( 16 );
+            Vec_IntPush( *pvSyms, (Abc_Lit2Var(pObj->pFans[i]) << 8) | Abc_Lit2Var(pObj->pFans[k]) );
+        }
+    }
+}
+void Amap_CreateCheckAsym( Kit_DsdNtk_t * p, Vec_Int_t ** pvSyms )
+{
+    Amap_CreateCheckAsym_rec( p, Abc_LitRegular(p->Root), pvSyms );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates rules for the given gate]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_CreateRulesForGate( Amap_Lib_t * pLib, Amap_Gat_t * pGate )
+{ 
+    Kit_DsdNtk_t * pNtk, * pTemp;
+    Vec_Int_t * vSyms = NULL;
+    Vec_Int_t * vNods;
+    Amap_Nod_t * pNod;
+    Amap_Set_t * pSet, * pSet2;
+    int iNod, i, k, Entry;
+//    if ( pGate->nPins > 4 )
+//        return;
+    pNtk = Kit_DsdDecomposeMux( pGate->pFunc, pGate->nPins, 2 );
+    if ( pGate->nPins == 2 && (pGate->pFunc[0] == 0x66666666 || pGate->pFunc[0] == ~0x66666666) )
+         pLib->fHasXor = 1;
+    if ( Kit_DsdNonDsdSizeMax(pNtk) == 3 )
+        pLib->fHasMux = pGate->fMux = 1;
+    pNtk = Kit_DsdExpand( pTemp = pNtk );
+    Kit_DsdNtkFree( pTemp );
+    Kit_DsdVerify( pNtk, pGate->pFunc, pGate->nPins ); 
+    // check symmetries
+    Amap_CreateCheckAsym( pNtk, &vSyms );
+//    if ( vSyms )
+//        Kit_DsdPrint( stdout, pNtk ), printf( "\n" );
+
+if ( pLib->fVerbose )
+//if ( pGate->fMux )
+{
+printf( "\nProcessing library gate %4d: %10s ", pGate->Id, pGate->pName );
+Kit_DsdPrint( stdout, pNtk );
+}
+    vNods = Amap_CreateRulesFromDsd( pLib, pNtk );
+    if ( vNods )
+    {
+        Vec_IntForEachEntry( vNods, iNod, i )
+        {
+            assert( iNod > 1 );
+            pNod = Amap_LibNod( pLib, Abc_Lit2Var(iNod) );
+//            assert( pNod->Type == AMAP_OBJ_MUX || pNod->nSuppSize == pGate->nPins );
+            pSet = (Amap_Set_t *)Aig_MmFlexEntryFetch( pLib->pMemSet, sizeof(Amap_Set_t) );
+            memset( pSet, 0, sizeof(Amap_Set_t) );
+            pSet->iGate = pGate->Id;
+            pSet->fInv  = Abc_LitIsCompl(iNod);
+            pSet->nIns  = pGate->nPins;
+            if ( Amap_LibDeriveGatePerm( pLib, pGate, pNtk, pNod, pSet->Ins ) == 0 )
+            {
+if ( pLib->fVerbose )
+{
+                printf( "Cound not prepare gate \"%s\": ", pGate->pName );
+                Kit_DsdPrint( stdout, pNtk );
+}
+                continue;
+            }
+            pSet->pNext = pNod->pSets;
+            pNod->pSets = pSet;
+            pLib->nSets++;
+            if ( vSyms == NULL )
+                continue;
+//            continue;
+            // add sets equivalent due to symmetry
+            Vec_IntForEachEntry( vSyms, Entry, k )
+            {
+                int iThis = Entry & 0xff;
+                int iThat = Entry >> 8;
+//                printf( "%d %d\n", iThis, iThat );
+                // create new set
+                pSet2 = (Amap_Set_t *)Aig_MmFlexEntryFetch( pLib->pMemSet, sizeof(Amap_Set_t) );
+                memset( pSet2, 0, sizeof(Amap_Set_t) );
+                pSet2->iGate = pGate->Id;
+                pSet2->fInv  = Abc_LitIsCompl(iNod);
+                pSet2->nIns  = pGate->nPins;
+                memcpy( pSet2->Ins, pSet->Ins, pGate->nPins );
+                // update inputs
+                pSet2->Ins[iThis] = Abc_Var2Lit( Abc_Lit2Var(pSet->Ins[iThat]), Abc_LitIsCompl(pSet->Ins[iThis]) );
+                pSet2->Ins[iThat] = Abc_Var2Lit( Abc_Lit2Var(pSet->Ins[iThis]), Abc_LitIsCompl(pSet->Ins[iThat]) );
+                // add set to collection
+                pSet2->pNext = pNod->pSets;
+                pNod->pSets  = pSet2;
+                pLib->nSets++;
+            }
+        }
+        Vec_IntFree( vNods );
+    }
+    Kit_DsdNtkFree( pNtk );
+    Vec_IntFreeP( &vSyms );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates rules for the given gate]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Amap_LibCreateRules( Amap_Lib_t * pLib, int fVeryVerbose )
+{
+    Amap_Gat_t * pGate;
+    int i, nGates = 0;
+//    abctime clk = Abc_Clock();
+    pLib->fVerbose = fVeryVerbose;
+    pLib->vRules   = Vec_PtrAlloc( 100 );
+    pLib->vRulesX  = Vec_PtrAlloc( 100 );
+    pLib->vRules3  = Vec_IntAlloc( 100 );
+    Amap_LibCreateVar( pLib );
+    Vec_PtrForEachEntry( Amap_Gat_t *, pLib->vSelect, pGate, i )
+    {
+        if ( pGate->nPins < 2 )
+            continue;
+        if ( pGate->pFunc == NULL )
+        {
+            printf( "Amap_LibCreateRules(): Skipping gate %s (%s).\n", pGate->pName, pGate->pForm );
+            continue;
+        }
+        Amap_CreateRulesForGate( pLib, pGate );
+        nGates++;
+    }
+    assert( Vec_PtrSize(pLib->vRules)  == 2*pLib->nNodes );
+    assert( Vec_PtrSize(pLib->vRulesX) == 2*pLib->nNodes );
+    pLib->pRules  = Amap_LibLookupTableAlloc( pLib->vRules, 0 );
+    pLib->pRulesX = Amap_LibLookupTableAlloc( pLib->vRulesX, 0 );
+    Vec_VecFree( (Vec_Vec_t *)pLib->vRules );  pLib->vRules  = NULL;
+    Vec_VecFree( (Vec_Vec_t *)pLib->vRulesX ); pLib->vRulesX = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/amap/amapUniq.c b/abc-build/src/map/amap/amapUniq.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/amap/amapUniq.c
@@ -0,0 +1,317 @@
+/**CFile****************************************************************
+
+  FileName    [amapUniq.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Technology mapper for standard cells.]
+
+  Synopsis    [Checks if the structural node already exists.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: amapUniq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the entry exists and returns value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntCheckWithMask( Vec_Int_t * p, int Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( (0xffff & p->pArray[i]) == (0xffff & Entry) )
+            return p->pArray[i] >> 16;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Pushes entry in the natural order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntPushOrderWithMask( Vec_Int_t * p, int Entry )
+{
+    int i;
+    if ( p->nSize == p->nCap )
+        Vec_IntGrow( p, 2 * p->nCap );
+    p->nSize++;
+    for ( i = p->nSize-2; i >= 0; i-- )
+        if ( (0xffff & p->pArray[i]) > (0xffff & Entry) )
+            p->pArray[i+1] = p->pArray[i];
+        else
+            break;
+    p->pArray[i+1] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_LibFindNode( Amap_Lib_t * pLib, int iFan0, int iFan1, int fXor )
+{
+    if ( fXor )
+        return Vec_IntCheckWithMask( (Vec_Int_t *)Vec_PtrEntry(pLib->vRulesX, iFan0), iFan1 );
+    else
+        return Vec_IntCheckWithMask( (Vec_Int_t *)Vec_PtrEntry(pLib->vRules, iFan0), iFan1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the three-argument rule exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_LibFindMux( Amap_Lib_t * p, int iFan0, int iFan1, int iFan2 )
+{
+    int x;
+    for ( x = 0; x < Vec_IntSize(p->vRules3); x += 4 )
+    {
+        if ( Vec_IntEntry(p->vRules3, x)   == iFan0 &&
+             Vec_IntEntry(p->vRules3, x+1) == iFan1 &&
+             Vec_IntEntry(p->vRules3, x+2) == iFan2 )
+        {
+            return Vec_IntEntry(p->vRules3, x+3);
+        }
+    }
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Amap_Nod_t * Amap_LibCreateObj( Amap_Lib_t * p )
+{
+    Amap_Nod_t * pNode;
+    if ( p->nNodes == p->nNodesAlloc )
+    {
+        p->pNodes = ABC_REALLOC( Amap_Nod_t, p->pNodes, 2*p->nNodesAlloc );
+        p->nNodesAlloc *= 2;
+    }
+    pNode = Amap_LibNod( p, p->nNodes );
+    memset( pNode, 0, sizeof(Amap_Nod_t) );
+    pNode->Id = p->nNodes++;
+    Vec_PtrPush( p->vRules, Vec_IntAlloc(8) );
+    Vec_PtrPush( p->vRules, Vec_IntAlloc(8) );
+    Vec_PtrPush( p->vRulesX, Vec_IntAlloc(8) );
+    Vec_PtrPush( p->vRulesX, Vec_IntAlloc(8) );
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_LibCreateVar( Amap_Lib_t * p )
+{
+    Amap_Nod_t * pNode;
+    // start the manager
+    assert( p->pNodes == NULL );
+    p->nNodesAlloc = 256;
+    p->pNodes = ABC_ALLOC( Amap_Nod_t, p->nNodesAlloc );
+    // create the first node
+    pNode = Amap_LibCreateObj( p );
+    p->pNodes->Type = AMAP_OBJ_PI;
+    p->pNodes->nSuppSize = 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_LibCreateNode( Amap_Lib_t * p, int iFan0, int iFan1, int fXor )
+{
+    Amap_Nod_t * pNode;
+    int iFan;
+    if ( iFan0 < iFan1 )
+    {
+        iFan  = iFan0;
+        iFan0 = iFan1;
+        iFan1 = iFan;
+    }
+    pNode = Amap_LibCreateObj( p );
+    pNode->Type  = fXor? AMAP_OBJ_XOR : AMAP_OBJ_AND;
+    pNode->nSuppSize = p->pNodes[Abc_Lit2Var(iFan0)].nSuppSize + p->pNodes[Abc_Lit2Var(iFan1)].nSuppSize;
+    pNode->iFan0 = iFan0;
+    pNode->iFan1 = iFan1;
+if ( p->fVerbose )
+printf( "Creating node %5d %c :  iFan0 = %5d%c  iFan1 = %5d%c\n", 
+pNode->Id, (fXor?'x':' '), 
+Abc_Lit2Var(iFan0), (Abc_LitIsCompl(iFan0)?'-':'+'), 
+Abc_Lit2Var(iFan1), (Abc_LitIsCompl(iFan1)?'-':'+') );
+
+    if ( fXor )
+    {
+        if ( iFan0 == iFan1 )
+            Vec_IntPushOrderWithMask( (Vec_Int_t *)Vec_PtrEntry(p->vRulesX, iFan0), (pNode->Id << 16) | iFan1 );
+        else
+        {
+            Vec_IntPushOrderWithMask( (Vec_Int_t *)Vec_PtrEntry(p->vRulesX, iFan0), (pNode->Id << 16) | iFan1 );
+            Vec_IntPushOrderWithMask( (Vec_Int_t *)Vec_PtrEntry(p->vRulesX, iFan1), (pNode->Id << 16) | iFan0 );
+        }
+    }
+    else
+    {
+        if ( iFan0 == iFan1 )
+            Vec_IntPushOrderWithMask( (Vec_Int_t *)Vec_PtrEntry(p->vRules, iFan0), (pNode->Id << 16) | iFan1 );
+        else
+        {
+            Vec_IntPushOrderWithMask( (Vec_Int_t *)Vec_PtrEntry(p->vRules, iFan0), (pNode->Id << 16) | iFan1 );
+            Vec_IntPushOrderWithMask( (Vec_Int_t *)Vec_PtrEntry(p->vRules, iFan1), (pNode->Id << 16) | iFan0 );
+        }
+    }
+    return pNode->Id;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Amap_LibCreateMux( Amap_Lib_t * p, int iFan0, int iFan1, int iFan2 )
+{
+    Amap_Nod_t * pNode;
+    pNode = Amap_LibCreateObj( p );
+    pNode->Type  = AMAP_OBJ_MUX;
+    pNode->nSuppSize = p->pNodes[Abc_Lit2Var(iFan0)].nSuppSize + p->pNodes[Abc_Lit2Var(iFan1)].nSuppSize + p->pNodes[Abc_Lit2Var(iFan2)].nSuppSize;
+    pNode->iFan0 = iFan0;
+    pNode->iFan1 = iFan1;
+    pNode->iFan2 = iFan2;
+if ( p->fVerbose )
+printf( "Creating node %5d %c :  iFan0 = %5d%c  iFan1 = %5d%c  iFan2 = %5d%c\n", 
+pNode->Id, 'm', 
+Abc_Lit2Var(iFan0), (Abc_LitIsCompl(iFan0)?'-':'+'), 
+Abc_Lit2Var(iFan1), (Abc_LitIsCompl(iFan1)?'-':'+'), 
+Abc_Lit2Var(iFan2), (Abc_LitIsCompl(iFan2)?'-':'+') );
+
+    Vec_IntPush( p->vRules3, iFan0 );
+    Vec_IntPush( p->vRules3, iFan1 );
+    Vec_IntPush( p->vRules3, iFan2 );
+    Vec_IntPush( p->vRules3, pNode->Id );
+    return pNode->Id;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates triangular lookup table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int ** Amap_LibLookupTableAlloc( Vec_Ptr_t * vVec, int fVerbose )
+{
+    Vec_Int_t * vOne;
+    int ** pRes, * pBuffer;
+    int i, k, nTotal, nSize, nEntries, Value;
+    // count the total size
+    nEntries = nSize = Vec_PtrSize( vVec );
+    Vec_PtrForEachEntry( Vec_Int_t *, vVec, vOne, i )
+        nEntries += Vec_IntSize(vOne);
+    pBuffer = ABC_ALLOC( int, nSize * sizeof(void *) + nEntries );
+    pRes = (int **)pBuffer;
+    pRes[0] = pBuffer + nSize * sizeof(void *);
+    nTotal = 0;
+    Vec_PtrForEachEntry( Vec_Int_t *, vVec, vOne, i )
+    {
+        pRes[i] = pRes[0] + nTotal;
+        nTotal += Vec_IntSize(vOne) + 1;
+        if ( fVerbose )
+        printf( "%d : ", i );
+        Vec_IntForEachEntry( vOne, Value, k )
+        {
+            pRes[i][k] = Value;
+            if ( fVerbose )
+            printf( "%d(%d) ", Value&0xffff, Value>>16 );
+        }
+        if ( fVerbose )
+        printf( "\n" );
+        pRes[i][k] = 0;
+    }
+    assert( nTotal == nEntries );
+    return pRes;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/amap/module.make b/abc-build/src/map/amap/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/amap/module.make
@@ -0,0 +1,13 @@
+SRC +=  src/map/amap/amapCore.c \
+	src/map/amap/amapGraph.c \
+	src/map/amap/amapLib.c \
+	src/map/amap/amapLiberty.c \
+	src/map/amap/amapMan.c \
+	src/map/amap/amapMatch.c \
+	src/map/amap/amapMerge.c \
+	src/map/amap/amapOutput.c \
+	src/map/amap/amapParse.c \
+	src/map/amap/amapPerm.c \
+	src/map/amap/amapRead.c \
+	src/map/amap/amapRule.c \
+	src/map/amap/amapUniq.c
diff --git a/abc-build/src/map/cov/cov.h b/abc-build/src/map/cov/cov.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/cov/cov.h
@@ -0,0 +1,109 @@
+/**CFile****************************************************************
+
+  FileName    [cov.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Mapping into network of SOPs/ESOPs.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+   
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cov.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__map__cov__cov_h
+#define ABC__map__cov__cov_h
+
+#include "base/abc/abc.h"
+#include "covInt.h"
+
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Cov_Man_t_  Cov_Man_t;
+typedef struct Cov_Obj_t_  Cov_Obj_t;
+
+// storage for node information
+struct Cov_Obj_t_
+{
+    Min_Cube_t *      pCover[3];    // pos/neg/esop
+    Vec_Int_t *       vSupp;        // computed support (all nodes except CIs)
+};
+
+// storage for additional information
+struct Cov_Man_t_
+{
+    // general characteristics
+    int               nFaninMax;    // the number of vars
+    int               nCubesMax;    // the limit on the number of cubes in the intermediate covers
+    int               nWords;       // the number of words
+    Vec_Int_t *       vFanCounts;   // fanout counts
+    Vec_Ptr_t *       vObjStrs;     // object structures
+    void *            pMemory;      // memory for the internal data strctures
+    Min_Man_t *       pManMin;      // the cube manager
+    int               fUseEsop;     // enables ESOPs
+    int               fUseSop;      // enables SOPs
+    // arrays to map local variables
+    Vec_Int_t *       vComTo0;      // mapping of common variables into first fanin
+    Vec_Int_t *       vComTo1;      // mapping of common variables into second fanin
+    Vec_Int_t *       vPairs0;      // the first var in each pair of common vars
+    Vec_Int_t *       vPairs1;      // the second var in each pair of common vars
+    Vec_Int_t *       vTriv0;       // trival support of the first node
+    Vec_Int_t *       vTriv1;       // trival support of the second node
+    // statistics
+    int               nSupps;       // supports created
+    int               nSuppsMax;    // the maximum number of supports
+    int               nBoundary;    // the boundary size
+    int               nNodes;       // the number of nodes processed
+};
+
+static inline Cov_Obj_t *  Abc_ObjGetStr( Abc_Obj_t * pObj )                       { return (Cov_Obj_t *)Vec_PtrEntry(((Cov_Man_t *)pObj->pNtk->pManCut)->vObjStrs, pObj->Id); }
+
+static inline void         Abc_ObjSetSupp( Abc_Obj_t * pObj, Vec_Int_t * vVec )    { Abc_ObjGetStr(pObj)->vSupp = vVec;   }
+static inline Vec_Int_t *  Abc_ObjGetSupp( Abc_Obj_t * pObj )                      { return Abc_ObjGetStr(pObj)->vSupp;   }
+
+static inline void         Abc_ObjSetCover2( Abc_Obj_t * pObj, Min_Cube_t * pCov ) { Abc_ObjGetStr(pObj)->pCover[2] = pCov; }
+static inline Min_Cube_t * Abc_ObjGetCover2( Abc_Obj_t * pObj )                    { return Abc_ObjGetStr(pObj)->pCover[2]; }
+
+static inline void         Abc_ObjSetCover( Abc_Obj_t * pObj, Min_Cube_t * pCov, int Pol ) { Abc_ObjGetStr(pObj)->pCover[Pol] = pCov; }
+static inline Min_Cube_t * Abc_ObjGetCover( Abc_Obj_t * pObj, int Pol )                    { return Abc_ObjGetStr(pObj)->pCover[Pol]; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== covBuild.c ==========================================================*/
+extern Abc_Ntk_t * Abc_NtkCovDerive( Cov_Man_t * p, Abc_Ntk_t * pNtk );
+extern Abc_Ntk_t * Abc_NtkCovDeriveClean( Cov_Man_t * p, Abc_Ntk_t * pNtk );
+extern Abc_Ntk_t * Abc_NtkCovDeriveRegular( Cov_Man_t * p, Abc_Ntk_t * pNtk );
+/*=== covCore.c ===========================================================*/
+extern Abc_Ntk_t * Abc_NtkSopEsopCover( Abc_Ntk_t * pNtk, int nFaninMax, int fUseEsop, int fUseSop, int fUseInvs, int fVerbose );
+/*=== covMan.c ============================================================*/
+extern Cov_Man_t * Cov_ManAlloc( Abc_Ntk_t * pNtk, int nFaninMax );
+extern void        Cov_ManFree( Cov_Man_t * p );
+extern void        Abc_NodeCovDropData( Cov_Man_t * p, Abc_Obj_t * pObj );
+/*=== covTest.c ===========================================================*/
+extern Abc_Ntk_t * Abc_NtkCovTestSop( Abc_Ntk_t * pNtk );
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+
diff --git a/abc-build/src/map/cov/covBuild.c b/abc-build/src/map/cov/covBuild.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/cov/covBuild.c
@@ -0,0 +1,544 @@
+/**CFile****************************************************************
+
+  FileName    [covBuild.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Mapping into network of SOPs/ESOPs.]
+
+  Synopsis    [Network construction procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: covBuild.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cov.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the decomposed network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkCovDeriveCube( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, Min_Cube_t * pCube, Vec_Int_t * vSupp, int fCompl )
+{
+    Vec_Int_t * vLits;
+    Abc_Obj_t * pNodeNew, * pFanin;
+    int i, iFanin, Lit;
+    // create empty cube
+    if ( pCube->nLits == 0 )
+    {
+        if ( fCompl )
+            return Abc_NtkCreateNodeConst0(pNtkNew);
+        return Abc_NtkCreateNodeConst1(pNtkNew);
+    }
+    // get the literals of this cube
+    vLits = Vec_IntAlloc( 10 );
+    Min_CubeGetLits( pCube, vLits );
+    assert( pCube->nLits == (unsigned)vLits->nSize );
+    // create special case when there is only one literal
+    if ( pCube->nLits == 1 )
+    {
+        iFanin = Vec_IntEntry(vLits,0);
+        pFanin = Abc_NtkObj( pObj->pNtk, Vec_IntEntry(vSupp, iFanin) );
+        Lit = Min_CubeGetVar(pCube, iFanin);
+        assert( Lit == 1 || Lit == 2 );
+        Vec_IntFree( vLits );
+        if ( (Lit == 1) ^ fCompl )// negative
+            return Abc_NtkCreateNodeInv( pNtkNew, pFanin->pCopy );
+        return pFanin->pCopy;
+    }
+    assert( pCube->nLits > 1 );
+    // create the AND cube
+    pNodeNew = Abc_NtkCreateNode( pNtkNew );
+    for ( i = 0; i < vLits->nSize; i++ )
+    {
+        iFanin = Vec_IntEntry(vLits,i);
+        pFanin = Abc_NtkObj( pObj->pNtk, Vec_IntEntry(vSupp, iFanin) );
+        Lit = Min_CubeGetVar(pCube, iFanin);
+        assert( Lit == 1 || Lit == 2 );
+        Vec_IntWriteEntry( vLits, i, Lit==1 );
+        Abc_ObjAddFanin( pNodeNew, pFanin->pCopy );
+    }
+    pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, vLits->nSize, vLits->pArray );
+    if ( fCompl )
+        Abc_SopComplement( (char *)pNodeNew->pData );
+    Vec_IntFree( vLits );
+    return pNodeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the decomposed network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkCovDeriveNode_rec( Cov_Man_t * p, Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int Level )
+{
+    Min_Cube_t * pCover, * pCube;
+    Abc_Obj_t * pFaninNew, * pNodeNew, * pFanin;
+    Vec_Int_t * vSupp;
+    int Entry, nCubes, i;
+
+    if ( Abc_ObjIsCi(pObj) )
+        return pObj->pCopy;
+    assert( Abc_ObjIsNode(pObj) );
+    // skip if already computed
+    if ( pObj->pCopy )
+        return pObj->pCopy;
+
+    // get the support and the cover
+    vSupp  = Abc_ObjGetSupp( pObj ); 
+    pCover = Abc_ObjGetCover2( pObj );
+    assert( vSupp );
+/*
+    if ( pCover &&  pCover->nVars - Min_CoverSuppVarNum(p->pManMin, pCover) > 0 )
+    {
+        printf( "%d\n ", pCover->nVars - Min_CoverSuppVarNum(p->pManMin, pCover) );
+        Min_CoverWrite( stdout, pCover );
+    }
+*/
+/*
+    // print the support of this node
+    printf( "{ " );
+    Vec_IntForEachEntry( vSupp, Entry, i )
+        printf( "%d ", Entry );
+    printf( "}  cubes = %d\n", Min_CoverCountCubes( pCover ) );
+*/
+    // process the fanins
+    Vec_IntForEachEntry( vSupp, Entry, i )
+    {
+        pFanin = Abc_NtkObj(pObj->pNtk, Entry);
+        Abc_NtkCovDeriveNode_rec( p, pNtkNew, pFanin, Level+1 );
+    }
+
+    // for each cube, construct the node
+    nCubes = Min_CoverCountCubes( pCover );
+    if ( nCubes == 0 )
+        pNodeNew = Abc_NtkCreateNodeConst0(pNtkNew);
+    else if ( nCubes == 1 )
+        pNodeNew = Abc_NtkCovDeriveCube( pNtkNew, pObj, pCover, vSupp, 0 );
+    else
+    {
+        pNodeNew = Abc_NtkCreateNode( pNtkNew );
+        Min_CoverForEachCube( pCover, pCube )
+        {
+            pFaninNew = Abc_NtkCovDeriveCube( pNtkNew, pObj, pCube, vSupp, 0 );
+            Abc_ObjAddFanin( pNodeNew, pFaninNew );
+        }
+        pNodeNew->pData = Abc_SopCreateXorSpecial( (Mem_Flex_t *)pNtkNew->pManFunc, nCubes );
+    }
+/*
+    printf( "Created node %d(%d) at level %d: ", pNodeNew->Id, pObj->Id, Level );
+    Vec_IntForEachEntry( vSupp, Entry, i )
+    {
+        pFanin = Abc_NtkObj(pObj->pNtk, Entry);
+        printf( "%d(%d) ", pFanin->pCopy->Id, pFanin->Id );
+    }
+    printf( "\n" );
+    Min_CoverWrite( stdout, pCover );
+*/
+    pObj->pCopy = pNodeNew;
+    return pNodeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the decomposed network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCovDerive( Cov_Man_t * p, Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObj;
+    int i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // perform strashing
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+    // reconstruct the network
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        Abc_NtkCovDeriveNode_rec( p, pNtkNew, Abc_ObjFanin0(pObj), 0 );
+//        printf( "*** CO %s : %d -> %d \n", Abc_ObjName(pObj), pObj->pCopy->Id, Abc_ObjFanin0(pObj)->pCopy->Id );
+    }
+    // add the COs
+    Abc_NtkFinalize( pNtk, pNtkNew );
+    Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 );
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkCovDerive: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the decomposed network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkCovDeriveInv( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCompl )
+{
+    assert( pObj->pCopy );
+    if ( !fCompl )
+        return pObj->pCopy;
+    if ( pObj->pCopy->pCopy == NULL )
+        pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy );
+    return pObj->pCopy->pCopy;
+ }
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the decomposed network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkCovDeriveCubeInv( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, Min_Cube_t * pCube, Vec_Int_t * vSupp )
+{
+    Vec_Int_t * vLits;
+    Abc_Obj_t * pNodeNew, * pFanin;
+    int i, iFanin, Lit;
+    // create empty cube
+    if ( pCube->nLits == 0 )
+        return Abc_NtkCreateNodeConst1(pNtkNew);
+    // get the literals of this cube
+    vLits = Vec_IntAlloc( 10 );
+    Min_CubeGetLits( pCube, vLits );
+    assert( pCube->nLits == (unsigned)vLits->nSize );
+    // create special case when there is only one literal
+    if ( pCube->nLits == 1 )
+    {
+        iFanin = Vec_IntEntry(vLits,0);
+        pFanin = Abc_NtkObj( pObj->pNtk, Vec_IntEntry(vSupp, iFanin) );
+        Lit = Min_CubeGetVar(pCube, iFanin);
+        assert( Lit == 1 || Lit == 2 );
+        Vec_IntFree( vLits );
+//        if ( Lit == 1 )// negative
+//            return Abc_NtkCreateNodeInv( pNtkNew, pFanin->pCopy );
+//        return pFanin->pCopy;
+        return Abc_NtkCovDeriveInv( pNtkNew, pFanin, Lit==1 );
+    }
+    assert( pCube->nLits > 1 );
+    // create the AND cube
+    pNodeNew = Abc_NtkCreateNode( pNtkNew );
+    for ( i = 0; i < vLits->nSize; i++ )
+    {
+        iFanin = Vec_IntEntry(vLits,i);
+        pFanin = Abc_NtkObj( pObj->pNtk, Vec_IntEntry(vSupp, iFanin) );
+        Lit = Min_CubeGetVar(pCube, iFanin);
+        assert( Lit == 1 || Lit == 2 );
+        Vec_IntWriteEntry( vLits, i, Lit==1 );
+//        Abc_ObjAddFanin( pNodeNew, pFanin->pCopy );
+        Abc_ObjAddFanin( pNodeNew, Abc_NtkCovDeriveInv( pNtkNew, pFanin, Lit==1 ) );
+    }
+//    pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, vLits->nSize, vLits->pArray );
+    pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, vLits->nSize, NULL );
+    Vec_IntFree( vLits );
+    return pNodeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the decomposed network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkCovDeriveNodeInv_rec( Cov_Man_t * p, Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCompl )
+{
+    Min_Cube_t * pCover, * pCube;
+    Abc_Obj_t * pFaninNew, * pNodeNew, * pFanin;
+    Vec_Int_t * vSupp;
+    int Entry, nCubes, i;
+
+    // skip if already computed
+    if ( pObj->pCopy )
+        return Abc_NtkCovDeriveInv( pNtkNew, pObj, fCompl );
+    assert( Abc_ObjIsNode(pObj) );
+
+    // get the support and the cover
+    vSupp  = Abc_ObjGetSupp( pObj ); 
+    pCover = Abc_ObjGetCover2( pObj );
+    assert( vSupp );
+
+    // process the fanins
+    Vec_IntForEachEntry( vSupp, Entry, i )
+    {
+        pFanin = Abc_NtkObj(pObj->pNtk, Entry);
+        Abc_NtkCovDeriveNodeInv_rec( p, pNtkNew, pFanin, 0 );
+    }
+
+    // for each cube, construct the node
+    nCubes = Min_CoverCountCubes( pCover );
+    if ( nCubes == 0 )
+        pNodeNew = Abc_NtkCreateNodeConst0(pNtkNew);
+    else if ( nCubes == 1 )
+        pNodeNew = Abc_NtkCovDeriveCubeInv( pNtkNew, pObj, pCover, vSupp );
+    else
+    {
+        pNodeNew = Abc_NtkCreateNode( pNtkNew );
+        Min_CoverForEachCube( pCover, pCube )
+        {
+            pFaninNew = Abc_NtkCovDeriveCubeInv( pNtkNew, pObj, pCube, vSupp );
+            Abc_ObjAddFanin( pNodeNew, pFaninNew );
+        }
+        pNodeNew->pData = Abc_SopCreateXorSpecial( (Mem_Flex_t *)pNtkNew->pManFunc, nCubes );
+    }
+
+    pObj->pCopy = pNodeNew;
+    return Abc_NtkCovDeriveInv( pNtkNew, pObj, fCompl );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the decomposed network.]
+
+  Description [The resulting network contains only pure AND/OR/EXOR gates
+  and inverters. This procedure is usedful to generate Verilog.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCovDeriveClean( Cov_Man_t * p, Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObj, * pNodeNew;
+    int i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // perform strashing
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+    // reconstruct the network
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        pNodeNew = Abc_NtkCovDeriveNodeInv_rec( p, pNtkNew, Abc_ObjFanin0(pObj), Abc_ObjFaninC0(pObj) );
+        Abc_ObjAddFanin( pObj->pCopy, pNodeNew );
+    }
+    // add the COs
+    Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkCovDeriveInv: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the decomposed network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkCovDerive_rec( Cov_Man_t * p, Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj )
+{
+    int fVerbose = 0;
+    Min_Cube_t * pCover, * pCovers[3];
+    Abc_Obj_t * pNodeNew, * pFanin;
+    Vec_Int_t * vSupp;
+    Vec_Str_t * vCover;
+    int i, Entry, nCubes, Type;
+    // skip if already computed
+    if ( pObj->pCopy )
+        return pObj->pCopy;
+    assert( Abc_ObjIsNode(pObj) );
+    // get the support and the cover
+    vSupp  = Abc_ObjGetSupp( pObj ); 
+    assert( vSupp );
+    // choose the cover to implement
+    pCovers[0] = Abc_ObjGetCover( pObj, 0 );
+    pCovers[1] = Abc_ObjGetCover( pObj, 1 );
+    pCovers[2] = Abc_ObjGetCover2( pObj );
+    // use positive polarity
+    if ( pCovers[0] 
+        && (!pCovers[1] || Min_CoverCountCubes(pCovers[0]) <= Min_CoverCountCubes(pCovers[1]))
+        && (!pCovers[2] || Min_CoverCountCubes(pCovers[0]) <= Min_CoverCountCubes(pCovers[2]))   )
+    {
+        pCover = pCovers[0];
+        Type = '1';
+    }
+    else 
+    // use negative polarity
+    if ( pCovers[1] 
+        && (!pCovers[0] || Min_CoverCountCubes(pCovers[1]) <= Min_CoverCountCubes(pCovers[0]))
+        && (!pCovers[2] || Min_CoverCountCubes(pCovers[1]) <= Min_CoverCountCubes(pCovers[2]))   )
+    {
+        pCover = pCovers[1];
+        Type = '0';
+    }
+    else 
+    // use XOR polarity
+    if ( pCovers[2] 
+        && (!pCovers[0] || Min_CoverCountCubes(pCovers[2]) < Min_CoverCountCubes(pCovers[0]))
+        && (!pCovers[1] || Min_CoverCountCubes(pCovers[2]) < Min_CoverCountCubes(pCovers[1]))   )
+    {
+        pCover = pCovers[2];
+        Type = 'x';
+    }
+    else
+        assert( 0 );
+    // print the support of this node
+    if ( fVerbose )
+    {
+        printf( "{ " );
+        Vec_IntForEachEntry( vSupp, Entry, i )
+            printf( "%d ", Entry );
+        printf( "}  cubes = %d\n", Min_CoverCountCubes( pCover ) );
+    }
+    // process the fanins
+    Vec_IntForEachEntry( vSupp, Entry, i )
+    {
+        pFanin = Abc_NtkObj(pObj->pNtk, Entry);
+        Abc_NtkCovDerive_rec( p, pNtkNew, pFanin );
+    }
+    // for each cube, construct the node
+    nCubes = Min_CoverCountCubes( pCover );
+    if ( nCubes == 0 )
+        pNodeNew = Abc_NtkCreateNodeConst0(pNtkNew);
+    else if ( nCubes == 1 )
+        pNodeNew = Abc_NtkCovDeriveCube( pNtkNew, pObj, pCover, vSupp, Type == '0' );
+    else
+    {
+        // create the node
+        pNodeNew = Abc_NtkCreateNode( pNtkNew );
+        Vec_IntForEachEntry( vSupp, Entry, i )
+        {
+            pFanin = Abc_NtkObj(pObj->pNtk, Entry);
+            Abc_ObjAddFanin( pNodeNew, pFanin->pCopy );
+        }
+        // derive the function
+        vCover = Vec_StrAlloc( 100 );
+        Min_CoverCreate( vCover, pCover, (char)Type );
+        pNodeNew->pData = Abc_SopRegister((Mem_Flex_t *)pNtkNew->pManFunc, Vec_StrArray(vCover) );
+        Vec_StrFree( vCover );
+    }
+
+/*
+    printf( "Created node %d(%d) at level %d: ", pNodeNew->Id, pObj->Id, Level );
+    Vec_IntForEachEntry( vSupp, Entry, i )
+    {
+        pFanin = Abc_NtkObj(pObj->pNtk, Entry);
+        printf( "%d(%d) ", pFanin->pCopy->Id, pFanin->Id );
+    }
+    printf( "\n" );
+    Min_CoverWrite( stdout, pCover );
+*/
+    return pObj->pCopy = pNodeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the decomposed network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCovDeriveRegular( Cov_Man_t * p, Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObj, * pNodeNew;
+    int i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    // perform strashing
+    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+    // reconstruct the network
+    if ( Abc_ObjFanoutNum(Abc_AigConst1(pNtk)) > 0 )
+        Abc_AigConst1(pNtk)->pCopy = Abc_NtkCreateNodeConst1(pNtkNew);
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        pNodeNew = Abc_NtkCovDerive_rec( p, pNtkNew, Abc_ObjFanin0(pObj) );
+        if ( Abc_ObjFaninC0(pObj) )
+        {
+            if ( pNodeNew->pData && Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 1 )
+                Abc_SopComplement( (char *)pNodeNew->pData );
+            else
+                pNodeNew = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew );
+        }
+        Abc_ObjAddFanin( pObj->pCopy, pNodeNew );
+    }
+    // add the COs
+    Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+    // make sure everything is okay
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkCovDerive: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/cov/covCore.c b/abc-build/src/map/cov/covCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/cov/covCore.c
@@ -0,0 +1,1030 @@
+/**CFile****************************************************************
+
+  FileName    [covCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Mapping into network of SOPs/ESOPs.]
+
+  Synopsis    [Core procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: covCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cov.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void         Abc_NtkCovCovers( Cov_Man_t * p, Abc_Ntk_t * pNtk, int fVerbose );
+static int          Abc_NtkCovCoversOne( Cov_Man_t * p, Abc_Ntk_t * pNtk, int fVerbose );
+static void         Abc_NtkCovCovers_rec( Cov_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vBoundary );
+/*
+static int          Abc_NodeCovPropagateEsop( Cov_Man_t * p, Abc_Obj_t * pObj, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1 );
+static int          Abc_NodeCovPropagateSop( Cov_Man_t * p, Abc_Obj_t * pObj, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1 );
+static int          Abc_NodeCovUnionEsop( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int nSupp );
+static int          Abc_NodeCovUnionSop( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int nSupp );
+static int          Abc_NodeCovProductEsop( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int nSupp );
+static int          Abc_NodeCovProductSop( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int nSupp );
+*/
+static int          Abc_NodeCovPropagate( Cov_Man_t * p, Abc_Obj_t * pObj );
+static Min_Cube_t * Abc_NodeCovProduct( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int fEsop, int nSupp );
+static Min_Cube_t * Abc_NodeCovSum( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int fEsop, int nSupp );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkSopEsopCover( Abc_Ntk_t * pNtk, int nFaninMax, int fUseEsop, int fUseSop, int fUseInvs, int fVerbose )
+{
+    Abc_Ntk_t * pNtkNew;
+    Cov_Man_t * p;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    // create the manager
+    p = Cov_ManAlloc( pNtk, nFaninMax );
+    p->fUseEsop = fUseEsop;
+    p->fUseSop  = fUseSop;
+    pNtk->pManCut = p;
+
+    // perform mapping
+    Abc_NtkCovCovers( p, pNtk, fVerbose );
+
+    // derive the final network
+//    if ( fUseInvs )
+//        pNtkNew = Abc_NtkCovDeriveClean( p, pNtk );
+//      else
+//       pNtkNew = Abc_NtkCovDerive( p, pNtk );
+//    pNtkNew = NULL;
+    pNtkNew = Abc_NtkCovDeriveRegular( p, pNtk );
+
+    Cov_ManFree( p );
+    pNtk->pManCut = NULL;
+
+    // make sure that everything is okay
+    if ( pNtkNew && !Abc_NtkCheck( pNtkNew ) )
+    {
+        printf( "Abc_NtkCov: The network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the supports.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCovCovers( Cov_Man_t * p, Abc_Ntk_t * pNtk, int fVerbose )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    abctime clk = Abc_Clock();
+
+    // start the manager
+    p->vFanCounts = Abc_NtkFanoutCounts(pNtk);
+
+    // set trivial cuts for the constant and the CIs
+    pObj = Abc_AigConst1(pNtk);
+    pObj->fMarkA = 1;
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->fMarkA = 1;
+
+    // perform iterative decomposition
+    for ( i = 0; ; i++ )
+    {
+        if ( fVerbose )
+        printf( "Iter %d : ", i+1 );
+        if ( Abc_NtkCovCoversOne(p, pNtk, fVerbose) )
+            break;
+    }
+
+    // clean the cut-point markers
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->fMarkA = 0;
+
+if ( fVerbose )
+{
+ABC_PRT( "Total", Abc_Clock() - clk );
+}
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the supports.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCovCoversOne( Cov_Man_t * p, Abc_Ntk_t * pNtk, int fVerbose )
+{
+    ProgressBar * pProgress;
+    Abc_Obj_t * pObj;
+    Vec_Ptr_t * vBoundary;
+    int i;
+    abctime clk = Abc_Clock();
+    int Counter = 0;
+    int fStop = 1;
+
+    // array to collect the nodes in the new boundary
+    vBoundary = Vec_PtrAlloc( 100 );
+
+    // start from the COs and mark visited nodes using pObj->fMarkB
+    pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        // skip the solved nodes (including the CIs)
+        pObj = Abc_ObjFanin0(pObj);
+        if ( pObj->fMarkA )
+        {
+            Counter++;
+            continue;
+        } 
+
+        // traverse the cone starting from this node
+        if ( Abc_ObjGetSupp(pObj) == NULL )
+            Abc_NtkCovCovers_rec( p, pObj, vBoundary );
+
+        // count the number of solved cones
+        if ( Abc_ObjGetSupp(pObj) == NULL )
+            fStop = 0;
+        else
+            Counter++;
+
+/*
+        printf( "%-15s : ", Abc_ObjName(pObj) ); 
+        printf( "lev = %5d  ", pObj->Level );
+        if ( Abc_ObjGetSupp(pObj) == NULL )
+        {
+            printf( "\n" );
+            continue;
+        }
+        printf( "supp = %3d  ", Abc_ObjGetSupp(pObj)->nSize ); 
+        printf( "esop = %3d  ", Min_CoverCountCubes( Abc_ObjGetCover2(pObj) ) ); 
+        printf( "\n" );
+*/
+    }
+    Extra_ProgressBarStop( pProgress );
+
+    // clean visited nodes
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->fMarkB = 0;
+
+    // create the new boundary
+    p->nBoundary = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vBoundary, pObj, i )
+    {
+        if ( !pObj->fMarkA )
+        {
+            pObj->fMarkA = 1;
+            p->nBoundary++;
+        }
+    }
+    Vec_PtrFree( vBoundary );
+
+if ( fVerbose )
+{
+    printf( "Outs = %4d (%4d) Node = %6d (%6d) Max = %6d  Bound = %4d  ", 
+        Counter, Abc_NtkCoNum(pNtk), p->nSupps, Abc_NtkNodeNum(pNtk), p->nSuppsMax, p->nBoundary );
+ABC_PRT( "T", Abc_Clock() - clk );
+}
+    return fStop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCovCovers_rec( Cov_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vBoundary )
+{
+    Abc_Obj_t * pObj0, * pObj1;
+    // return if the support is already computed
+    if ( pObj->fMarkB || pObj->fMarkA )//|| Abc_ObjGetSupp(pObj) ) // why do we need Supp check here???
+        return;
+    // mark as visited
+    pObj->fMarkB = 1;
+    // get the fanins
+    pObj0 = Abc_ObjFanin0(pObj);
+    pObj1 = Abc_ObjFanin1(pObj);
+    // solve for the fanins
+    Abc_NtkCovCovers_rec( p, pObj0, vBoundary );
+    Abc_NtkCovCovers_rec( p, pObj1, vBoundary );
+    // skip the node that spaced out
+    if ( (!pObj0->fMarkA && !Abc_ObjGetSupp(pObj0)) ||  // fanin is not ready
+         (!pObj1->fMarkA && !Abc_ObjGetSupp(pObj1)) ||  // fanin is not ready
+         !Abc_NodeCovPropagate( p, pObj ) )           // node's support or covers cannot be computed
+    {
+        // save the nodes of the future boundary
+        if ( !pObj0->fMarkA && Abc_ObjGetSupp(pObj0) )
+            Vec_PtrPush( vBoundary, pObj0 );
+        if ( !pObj1->fMarkA && Abc_ObjGetSupp(pObj1) )
+            Vec_PtrPush( vBoundary, pObj1 );
+        return;
+    }
+    // consider dropping the fanin supports
+//    Abc_NodeCovDropData( p, pObj0 );
+//    Abc_NodeCovDropData( p, pObj1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NodeCovSupport( Cov_Man_t * p, Vec_Int_t * vSupp0, Vec_Int_t * vSupp1 )
+{
+    Vec_Int_t * vSupp;
+    int k0, k1;
+
+    assert( vSupp0 && vSupp1 );
+    Vec_IntFill( p->vComTo0, vSupp0->nSize + vSupp1->nSize, -1 );
+    Vec_IntFill( p->vComTo1, vSupp0->nSize + vSupp1->nSize, -1 );
+    Vec_IntClear( p->vPairs0 );
+    Vec_IntClear( p->vPairs1 );
+
+    vSupp = Vec_IntAlloc( vSupp0->nSize + vSupp1->nSize );
+    for ( k0 = k1 = 0; k0 < vSupp0->nSize && k1 < vSupp1->nSize; )
+    {
+        if ( vSupp0->pArray[k0] == vSupp1->pArray[k1] )
+        {
+            Vec_IntWriteEntry( p->vComTo0, vSupp->nSize, k0 );
+            Vec_IntWriteEntry( p->vComTo1, vSupp->nSize, k1 );
+            Vec_IntPush( p->vPairs0, k0 );
+            Vec_IntPush( p->vPairs1, k1 );
+            Vec_IntPush( vSupp, vSupp0->pArray[k0] );
+            k0++; k1++;
+        }
+        else if ( vSupp0->pArray[k0] < vSupp1->pArray[k1] )
+        {
+            Vec_IntWriteEntry( p->vComTo0, vSupp->nSize, k0 );
+            Vec_IntPush( vSupp, vSupp0->pArray[k0] );
+            k0++;
+        }
+        else 
+        {
+            Vec_IntWriteEntry( p->vComTo1, vSupp->nSize, k1 );
+            Vec_IntPush( vSupp, vSupp1->pArray[k1] );
+            k1++;
+        }
+    }
+    for ( ; k0 < vSupp0->nSize; k0++ )
+    {
+        Vec_IntWriteEntry( p->vComTo0, vSupp->nSize, k0 );
+        Vec_IntPush( vSupp, vSupp0->pArray[k0] );
+    }
+    for ( ; k1 < vSupp1->nSize; k1++ )
+    {
+        Vec_IntWriteEntry( p->vComTo1, vSupp->nSize, k1 );
+        Vec_IntPush( vSupp, vSupp1->pArray[k1] );
+    }
+/*
+    printf( "Zero : " );
+    for ( k0 = 0; k0 < vSupp0->nSize; k0++ )
+        printf( "%d ", vSupp0->pArray[k0] );
+    printf( "\n" );
+
+    printf( "One  : " );
+    for ( k1 = 0; k1 < vSupp1->nSize; k1++ )
+        printf( "%d ", vSupp1->pArray[k1] );
+    printf( "\n" );
+
+    printf( "Sum  : " );
+    for ( k0 = 0; k0 < vSupp->nSize; k0++ )
+        printf( "%d ", vSupp->pArray[k0] );
+    printf( "\n" );
+    printf( "\n" );
+*/
+    return vSupp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagates all types of covers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCovPropagate( Cov_Man_t * p, Abc_Obj_t * pObj )
+{
+    Min_Cube_t * pCoverP = NULL, * pCoverN = NULL, * pCoverX = NULL;
+    Min_Cube_t * pCov0, * pCov1, * pCover0, * pCover1;
+    Vec_Int_t * vSupp, * vSupp0, * vSupp1;
+    Abc_Obj_t * pObj0, * pObj1;
+    int fCompl0, fCompl1;
+
+    pObj0 = Abc_ObjFanin0( pObj );
+    pObj1 = Abc_ObjFanin1( pObj );
+
+    if ( pObj0->fMarkA )  Vec_IntWriteEntry( p->vTriv0, 0, pObj0->Id );
+    if ( pObj1->fMarkA )  Vec_IntWriteEntry( p->vTriv1, 0, pObj1->Id );
+ 
+    // get the resulting support
+    vSupp0 = pObj0->fMarkA? p->vTriv0 : Abc_ObjGetSupp(pObj0);
+    vSupp1 = pObj1->fMarkA? p->vTriv1 : Abc_ObjGetSupp(pObj1);
+    vSupp  = Abc_NodeCovSupport( p, vSupp0, vSupp1 );
+
+    // quit if support if too large
+    if ( vSupp->nSize > p->nFaninMax )
+    {
+        Vec_IntFree( vSupp );
+        return 0;
+    }
+
+    // get the complemented attributes
+    fCompl0 = Abc_ObjFaninC0( pObj );
+    fCompl1 = Abc_ObjFaninC1( pObj );
+
+    // propagate ESOP
+    if ( p->fUseEsop )
+    {
+        // get the covers
+        pCov0 = pObj0->fMarkA? p->pManMin->pTriv0[0] : Abc_ObjGetCover2(pObj0);
+        pCov1 = pObj1->fMarkA? p->pManMin->pTriv1[0] : Abc_ObjGetCover2(pObj1);
+        if ( pCov0 && pCov1 )
+        {
+            // complement the first if needed
+            if ( !fCompl0 )
+                pCover0 = pCov0;
+            else if ( pCov0 && pCov0->nLits == 0 ) // topmost one is the tautology cube
+                pCover0 = pCov0->pNext;
+            else
+                pCover0 = p->pManMin->pOne0, p->pManMin->pOne0->pNext = pCov0;
+
+            // complement the second if needed
+            if ( !fCompl1 )
+                pCover1 = pCov1;
+            else if ( pCov1 && pCov1->nLits == 0 ) // topmost one is the tautology cube
+                pCover1 = pCov1->pNext;
+            else
+                pCover1 = p->pManMin->pOne1, p->pManMin->pOne1->pNext = pCov1;
+
+            // derive the new cover
+            pCoverX = Abc_NodeCovProduct( p, pCover0, pCover1, 1, vSupp->nSize );
+        }
+    }
+    // propagate SOPs
+    if ( p->fUseSop )
+    {
+        // get the covers for the direct polarity
+        pCover0 = pObj0->fMarkA? p->pManMin->pTriv0[fCompl0] : Abc_ObjGetCover(pObj0, fCompl0);
+        pCover1 = pObj1->fMarkA? p->pManMin->pTriv1[fCompl1] : Abc_ObjGetCover(pObj1, fCompl1);
+        // derive the new cover
+        if ( pCover0 && pCover1 )
+            pCoverP = Abc_NodeCovProduct( p, pCover0, pCover1, 0, vSupp->nSize );
+
+        // get the covers for the inverse polarity
+        pCover0 = pObj0->fMarkA? p->pManMin->pTriv0[!fCompl0] : Abc_ObjGetCover(pObj0, !fCompl0);
+        pCover1 = pObj1->fMarkA? p->pManMin->pTriv1[!fCompl1] : Abc_ObjGetCover(pObj1, !fCompl1);
+        // derive the new cover
+        if ( pCover0 && pCover1 )
+            pCoverN = Abc_NodeCovSum( p, pCover0, pCover1, 0, vSupp->nSize );
+    }
+
+    // if none of the covers can be computed quit
+    if ( !pCoverX && !pCoverP && !pCoverN )
+    {
+        Vec_IntFree( vSupp );
+        return 0;
+    }
+
+    // set the covers
+    assert( Abc_ObjGetSupp(pObj) == NULL );
+    Abc_ObjSetSupp( pObj, vSupp );
+    Abc_ObjSetCover( pObj, pCoverP, 0 );
+    Abc_ObjSetCover( pObj, pCoverN, 1 );
+    Abc_ObjSetCover2( pObj, pCoverX );
+//printf( "%3d : %4d  %4d  %4d\n", pObj->Id, Min_CoverCountCubes(pCoverP), Min_CoverCountCubes(pCoverN), Min_CoverCountCubes(pCoverX) );
+
+    // count statistics
+    p->nSupps++;
+    p->nSuppsMax = Abc_MaxInt( p->nSuppsMax, p->nSupps );
+    return 1;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Min_Cube_t * Abc_NodeCovProduct( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int fEsop, int nSupp )
+{
+    Min_Cube_t * pCube, * pCube0, * pCube1;
+    Min_Cube_t * pCover;
+    int i, Val0, Val1;
+    assert( pCover0 && pCover1 );
+
+    // clean storage
+    Min_ManClean( p->pManMin, nSupp );
+    // go through the cube pairs
+    Min_CoverForEachCube( pCover0, pCube0 )
+    Min_CoverForEachCube( pCover1, pCube1 )
+    {
+        // go through the support variables of the cubes
+        for ( i = 0; i < p->vPairs0->nSize; i++ )
+        {
+            Val0 = Min_CubeGetVar( pCube0, p->vPairs0->pArray[i] );
+            Val1 = Min_CubeGetVar( pCube1, p->vPairs1->pArray[i] );
+            if ( (Val0 & Val1) == 0 )
+                break;
+        }
+        // check disjointness
+        if ( i < p->vPairs0->nSize )
+            continue;
+
+        if ( p->pManMin->nCubes > p->nCubesMax )
+        {
+            pCover = Min_CoverCollect( p->pManMin, nSupp );
+//Min_CoverWriteFile( pCover, "large", 1 );
+            Min_CoverRecycle( p->pManMin, pCover );
+            return NULL;
+        }
+
+        // create the product cube
+        pCube = Min_CubeAlloc( p->pManMin );
+
+        // add the literals
+        pCube->nLits = 0;
+        for ( i = 0; i < nSupp; i++ )
+        {
+            if ( p->vComTo0->pArray[i] == -1 )
+                Val0 = 3;
+            else
+                Val0 = Min_CubeGetVar( pCube0, p->vComTo0->pArray[i] );
+
+            if ( p->vComTo1->pArray[i] == -1 )
+                Val1 = 3;
+            else
+                Val1 = Min_CubeGetVar( pCube1, p->vComTo1->pArray[i] );
+
+            if ( (Val0 & Val1) == 3 )
+                continue;
+
+            Min_CubeXorVar( pCube, i, (Val0 & Val1) ^ 3 );
+            pCube->nLits++;
+        }
+        // add the cube to storage
+        if ( fEsop ) 
+            Min_EsopAddCube( p->pManMin, pCube );
+        else
+            Min_SopAddCube( p->pManMin, pCube );
+    }
+
+    // minimize the cover
+    if ( fEsop ) 
+        Min_EsopMinimize( p->pManMin );
+    else
+        Min_SopMinimize( p->pManMin );
+    pCover = Min_CoverCollect( p->pManMin, nSupp );
+
+    // quit if the cover is too large
+    if ( Min_CoverCountCubes(pCover) > p->nFaninMax )
+    {
+/*        
+Min_CoverWriteFile( pCover, "large", 1 );
+        Min_CoverExpand( p->pManMin, pCover );
+        Min_EsopMinimize( p->pManMin );
+        Min_EsopMinimize( p->pManMin );
+        Min_EsopMinimize( p->pManMin );
+        Min_EsopMinimize( p->pManMin );
+        Min_EsopMinimize( p->pManMin );
+        Min_EsopMinimize( p->pManMin );
+        Min_EsopMinimize( p->pManMin );
+        Min_EsopMinimize( p->pManMin );
+        Min_EsopMinimize( p->pManMin );
+        pCover = Min_CoverCollect( p->pManMin, nSupp );
+*/
+        Min_CoverRecycle( p->pManMin, pCover );
+        return NULL;
+    }
+    return pCover;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Min_Cube_t * Abc_NodeCovSum( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int fEsop, int nSupp )
+{
+    Min_Cube_t * pCube, * pCube0, * pCube1;
+    Min_Cube_t * pCover;
+    int i, Val0, Val1;
+    assert( pCover0 && pCover1 );
+
+    // clean storage
+    Min_ManClean( p->pManMin, nSupp );
+    Min_CoverForEachCube( pCover0, pCube0 )
+    {
+        // create the cube
+        pCube = Min_CubeAlloc( p->pManMin );
+        pCube->nLits = 0;
+        for ( i = 0; i < p->vComTo0->nSize; i++ )
+        {
+            if ( p->vComTo0->pArray[i] == -1 )
+                continue;
+            Val0 = Min_CubeGetVar( pCube0, p->vComTo0->pArray[i] );
+            if ( Val0 == 3 )
+                continue;
+            Min_CubeXorVar( pCube, i, Val0 ^ 3 );
+            pCube->nLits++;
+        }
+        if ( p->pManMin->nCubes > p->nCubesMax )
+        {
+            pCover = Min_CoverCollect( p->pManMin, nSupp );
+            Min_CoverRecycle( p->pManMin, pCover );
+            return NULL;
+        }
+        // add the cube to storage
+        if ( fEsop )
+            Min_EsopAddCube( p->pManMin, pCube );
+        else
+            Min_SopAddCube( p->pManMin, pCube );
+    }
+    Min_CoverForEachCube( pCover1, pCube1 )
+    {
+        // create the cube
+        pCube = Min_CubeAlloc( p->pManMin );
+        pCube->nLits = 0;
+        for ( i = 0; i < p->vComTo1->nSize; i++ )
+        {
+            if ( p->vComTo1->pArray[i] == -1 )
+                continue;
+            Val1 = Min_CubeGetVar( pCube1, p->vComTo1->pArray[i] );
+            if ( Val1 == 3 )
+                continue;
+            Min_CubeXorVar( pCube, i, Val1 ^ 3 );
+            pCube->nLits++;
+        }
+        if ( p->pManMin->nCubes > p->nCubesMax )
+        {
+            pCover = Min_CoverCollect( p->pManMin, nSupp );
+            Min_CoverRecycle( p->pManMin, pCover );
+            return NULL;
+        }
+        // add the cube to storage
+        if ( fEsop )
+            Min_EsopAddCube( p->pManMin, pCube );
+        else
+            Min_SopAddCube( p->pManMin, pCube );
+    }
+
+    // minimize the cover
+    if ( fEsop ) 
+        Min_EsopMinimize( p->pManMin );
+    else
+        Min_SopMinimize( p->pManMin );
+    pCover = Min_CoverCollect( p->pManMin, nSupp );
+
+    // quit if the cover is too large
+    if ( Min_CoverCountCubes(pCover) > p->nFaninMax )
+    {
+        Min_CoverRecycle( p->pManMin, pCover );
+        return NULL;
+    }
+    return pCover;
+}
+
+
+
+
+
+
+
+#if 0
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCovPropagateEsop( Cov_Man_t * p, Abc_Obj_t * pObj, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1 )
+{
+    Min_Cube_t * pCover, * pCover0, * pCover1, * pCov0, * pCov1;
+    Vec_Int_t * vSupp, * vSupp0, * vSupp1;
+
+    if ( pObj0->fMarkA )  Vec_IntWriteEntry( p->vTriv0, 0, pObj0->Id );
+    if ( pObj1->fMarkA )  Vec_IntWriteEntry( p->vTriv1, 0, pObj1->Id );
+
+    // get the resulting support
+    vSupp0 = pObj0->fMarkA? p->vTriv0 : Abc_ObjGetSupp(pObj0);
+    vSupp1 = pObj1->fMarkA? p->vTriv1 : Abc_ObjGetSupp(pObj1);
+    vSupp  = Abc_NodeCovSupport( p, vSupp0, vSupp1 );
+
+    // quit if support if too large
+    if ( vSupp->nSize > p->nFaninMax )
+    {
+        Vec_IntFree( vSupp );
+        return 0;
+    }
+   
+    // get the covers
+    pCov0 = pObj0->fMarkA? p->pManMin->pTriv0[0] : Abc_ObjGetCover2(pObj0);
+    pCov1 = pObj1->fMarkA? p->pManMin->pTriv1[0] : Abc_ObjGetCover2(pObj1);
+
+    // complement the first if needed
+    if ( !Abc_ObjFaninC0(pObj) )
+        pCover0 = pCov0;
+    else if ( pCov0 && pCov0->nLits == 0 ) // topmost one is the tautology cube
+        pCover0 = pCov0->pNext;
+    else
+        pCover0 = p->pManMin->pOne0, p->pManMin->pOne0->pNext = pCov0;
+
+    // complement the second if needed
+    if ( !Abc_ObjFaninC1(pObj) )
+        pCover1 = pCov1;
+    else if ( pCov1 && pCov1->nLits == 0 ) // topmost one is the tautology cube
+        pCover1 = pCov1->pNext;
+    else
+        pCover1 = p->pManMin->pOne1, p->pManMin->pOne1->pNext = pCov1;
+
+    // derive and minimize the cover (quit if too large)
+    if ( !Abc_NodeCovProductEsop( p, pCover0, pCover1, vSupp->nSize ) )
+    {
+        pCover = Min_CoverCollect( p->pManMin, vSupp->nSize );
+        Min_CoverRecycle( p->pManMin, pCover );
+        Vec_IntFree( vSupp );
+        return 0;
+    }
+
+    // minimize the cover
+    Min_EsopMinimize( p->pManMin );
+    pCover = Min_CoverCollect( p->pManMin, vSupp->nSize );
+
+    // quit if the cover is too large
+    if ( Min_CoverCountCubes(pCover) > p->nFaninMax )
+    {
+        Min_CoverRecycle( p->pManMin, pCover );
+        Vec_IntFree( vSupp );
+        return 0;
+    }
+
+    // count statistics
+    p->nSupps++;
+    p->nSuppsMax = Abc_MaxInt( p->nSuppsMax, p->nSupps );
+
+    // set the covers
+    assert( Abc_ObjGetSupp(pObj) == NULL );
+    Abc_ObjSetSupp( pObj, vSupp );
+    Abc_ObjSetCover2( pObj, pCover );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCovPropagateSop( Cov_Man_t * p, Abc_Obj_t * pObj, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1 )
+{
+    Min_Cube_t * pCoverP, * pCoverN, * pCover0, * pCover1;
+    Vec_Int_t * vSupp, * vSupp0, * vSupp1;
+    int fCompl0, fCompl1;
+
+    if ( pObj0->fMarkA )  Vec_IntWriteEntry( p->vTriv0, 0, pObj0->Id );
+    if ( pObj1->fMarkA )  Vec_IntWriteEntry( p->vTriv1, 0, pObj1->Id );
+
+    // get the resulting support
+    vSupp0 = pObj0->fMarkA? p->vTriv0 : Abc_ObjGetSupp(pObj0);
+    vSupp1 = pObj1->fMarkA? p->vTriv1 : Abc_ObjGetSupp(pObj1);
+    vSupp  = Abc_NodeCovSupport( p, vSupp0, vSupp1 );
+
+    // quit if support if too large
+    if ( vSupp->nSize > p->nFaninMax )
+    {
+        Vec_IntFree( vSupp );
+        return 0;
+    }
+
+    // get the complemented attributes
+    fCompl0 = Abc_ObjFaninC0(pObj);
+    fCompl1 = Abc_ObjFaninC1(pObj);
+   
+    // prepare the positive cover
+    pCover0 = pObj0->fMarkA? p->pManMin->pTriv0[fCompl0] : Abc_ObjGetCover(pObj0, fCompl0);
+    pCover1 = pObj1->fMarkA? p->pManMin->pTriv1[fCompl1] : Abc_ObjGetCover(pObj1, fCompl1);
+
+    // derive and minimize the cover (quit if too large)
+    if ( !pCover0 || !pCover1 )
+        pCoverP = NULL;
+    else if ( !Abc_NodeCovProductSop( p, pCover0, pCover1, vSupp->nSize ) )
+    {
+        pCoverP = Min_CoverCollect( p->pManMin, vSupp->nSize );
+        Min_CoverRecycle( p->pManMin, pCoverP );
+        pCoverP = NULL;
+    }
+    else
+    {
+        Min_SopMinimize( p->pManMin );
+        pCoverP = Min_CoverCollect( p->pManMin, vSupp->nSize );
+        // quit if the cover is too large
+        if ( Min_CoverCountCubes(pCoverP) > p->nFaninMax )
+        {
+            Min_CoverRecycle( p->pManMin, pCoverP );
+            pCoverP = NULL;
+        }
+    }
+   
+    // prepare the negative cover
+    pCover0 = pObj0->fMarkA? p->pManMin->pTriv0[!fCompl0] : Abc_ObjGetCover(pObj0, !fCompl0);
+    pCover1 = pObj1->fMarkA? p->pManMin->pTriv1[!fCompl1] : Abc_ObjGetCover(pObj1, !fCompl1);
+
+    // derive and minimize the cover (quit if too large)
+    if ( !pCover0 || !pCover1 )
+        pCoverN = NULL;
+    else if ( !Abc_NodeCovUnionSop( p, pCover0, pCover1, vSupp->nSize ) )
+    {
+        pCoverN = Min_CoverCollect( p->pManMin, vSupp->nSize );
+        Min_CoverRecycle( p->pManMin, pCoverN );
+        pCoverN = NULL;
+    }
+    else
+    {
+        Min_SopMinimize( p->pManMin );
+        pCoverN = Min_CoverCollect( p->pManMin, vSupp->nSize );
+        // quit if the cover is too large
+        if ( Min_CoverCountCubes(pCoverN) > p->nFaninMax )
+        {
+            Min_CoverRecycle( p->pManMin, pCoverN );
+            pCoverN = NULL;
+        }
+    }
+
+    if ( pCoverP == NULL && pCoverN == NULL )
+    {
+        Vec_IntFree( vSupp );
+        return 0;
+    }
+
+    // count statistics
+    p->nSupps++;
+    p->nSuppsMax = Abc_MaxInt( p->nSuppsMax, p->nSupps );
+
+    // set the covers
+    assert( Abc_ObjGetSupp(pObj) == NULL );
+    Abc_ObjSetSupp( pObj, vSupp );
+    Abc_ObjSetCover( pObj, pCoverP, 0 );
+    Abc_ObjSetCover( pObj, pCoverN, 1 );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCovProductEsop( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int nSupp )
+{
+    Min_Cube_t * pCube, * pCube0, * pCube1;
+    int i, Val0, Val1;
+
+    // clean storage
+    Min_ManClean( p->pManMin, nSupp );
+    if ( pCover0 == NULL || pCover1 == NULL )
+        return 1;
+
+    // go through the cube pairs
+    Min_CoverForEachCube( pCover0, pCube0 )
+    Min_CoverForEachCube( pCover1, pCube1 )
+    {
+        // go through the support variables of the cubes
+        for ( i = 0; i < p->vPairs0->nSize; i++ )
+        {
+            Val0 = Min_CubeGetVar( pCube0, p->vPairs0->pArray[i] );
+            Val1 = Min_CubeGetVar( pCube1, p->vPairs1->pArray[i] );
+            if ( (Val0 & Val1) == 0 )
+                break;
+        }
+        // check disjointness
+        if ( i < p->vPairs0->nSize )
+            continue;
+
+        if ( p->pManMin->nCubes >= p->nCubesMax )
+            return 0;
+
+        // create the product cube
+        pCube = Min_CubeAlloc( p->pManMin );
+
+        // add the literals
+        pCube->nLits = 0;
+        for ( i = 0; i < nSupp; i++ )
+        {
+            if ( p->vComTo0->pArray[i] == -1 )
+                Val0 = 3;
+            else
+                Val0 = Min_CubeGetVar( pCube0, p->vComTo0->pArray[i] );
+
+            if ( p->vComTo1->pArray[i] == -1 )
+                Val1 = 3;
+            else
+                Val1 = Min_CubeGetVar( pCube1, p->vComTo1->pArray[i] );
+
+            if ( (Val0 & Val1) == 3 )
+                continue;
+
+            Min_CubeXorVar( pCube, i, (Val0 & Val1) ^ 3 );
+            pCube->nLits++;
+        }
+        // add the cube to storage
+        Min_EsopAddCube( p->pManMin, pCube );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCovProductSop( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int nSupp )
+{
+    return 1;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCovUnionEsop( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int nSupp )
+{
+    Min_Cube_t * pCube, * pCube0, * pCube1;
+    int i, Val0, Val1;
+
+    // clean storage
+    Min_ManClean( p->pManMin, nSupp );
+    if ( pCover0 )
+    {
+        Min_CoverForEachCube( pCover0, pCube0 )
+        {
+            // create the cube
+            pCube = Min_CubeAlloc( p->pManMin );
+            pCube->nLits = 0;
+            for ( i = 0; i < p->vComTo0->nSize; i++ )
+            {
+                if ( p->vComTo0->pArray[i] == -1 )
+                    continue;
+                Val0 = Min_CubeGetVar( pCube0, p->vComTo0->pArray[i] );
+                if ( Val0 == 3 )
+                    continue;
+                Min_CubeXorVar( pCube, i, Val0 ^ 3 );
+                pCube->nLits++;
+            }
+            if ( p->pManMin->nCubes >= p->nCubesMax )
+                return 0;
+            // add the cube to storage
+            Min_EsopAddCube( p->pManMin, pCube );
+        }
+    }
+    if ( pCover1 )
+    {
+        Min_CoverForEachCube( pCover1, pCube1 )
+        {
+            // create the cube
+            pCube = Min_CubeAlloc( p->pManMin );
+            pCube->nLits = 0;
+            for ( i = 0; i < p->vComTo1->nSize; i++ )
+            {
+                if ( p->vComTo1->pArray[i] == -1 )
+                    continue;
+                Val1 = Min_CubeGetVar( pCube1, p->vComTo1->pArray[i] );
+                if ( Val1 == 3 )
+                    continue;
+                Min_CubeXorVar( pCube, i, Val1 ^ 3 );
+                pCube->nLits++;
+            }
+            if ( p->pManMin->nCubes >= p->nCubesMax )
+                return 0;
+            // add the cube to storage
+            Min_EsopAddCube( p->pManMin, pCube );
+        }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeCovUnionSop( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int nSupp )
+{
+    return 1;
+}
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/cov/covInt.h b/abc-build/src/map/cov/covInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/cov/covInt.h
@@ -0,0 +1,654 @@
+/**CFile****************************************************************
+
+  FileName    [covInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Mapping into network of SOPs/ESOPs.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: covInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__map__cov__covInt_h
+#define ABC__map__cov__covInt_h
+
+#include "base/abc/abc.h"
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Min_Man_t_  Min_Man_t;
+typedef struct Min_Cube_t_ Min_Cube_t;
+
+struct Min_Man_t_
+{
+    int               nVars;          // the number of vars
+    int               nWords;         // the number of words
+    Extra_MmFixed_t * pMemMan;        // memory manager for cubes
+    // temporary cubes
+    Min_Cube_t *      pOne0;          // tautology cube
+    Min_Cube_t *      pOne1;          // tautology cube
+    Min_Cube_t *      pTriv0[2];      // trivial cube
+    Min_Cube_t *      pTriv1[2];      // trivial cube
+    Min_Cube_t *      pTemp;          // cube for computing the distance
+    Min_Cube_t *      pBubble;        // cube used as a separator
+    // temporary storage for the new cover
+    int               nCubes;         // the number of cubes
+    Min_Cube_t **     ppStore;        // storage for cubes by number of literals
+};
+
+struct Min_Cube_t_
+{
+    Min_Cube_t *      pNext;          // the pointer to the next cube in the cover
+    unsigned          nVars    : 10;  // the number of variables
+    unsigned          nWords   : 12;  // the number of machine words
+    unsigned          nLits    : 10;  // the number of literals in the cube
+    unsigned          uData[1];       // the bit-data for the cube
+};
+
+
+// iterators through the entries in the linked lists of cubes
+#define Min_CoverForEachCube( pCover, pCube )                   \
+    for ( pCube = pCover;                                       \
+          pCube;                                                \
+          pCube = pCube->pNext )
+#define Min_CoverForEachCubeSafe( pCover, pCube, pCube2 )       \
+    for ( pCube = pCover,                                       \
+          pCube2 = pCube? pCube->pNext: NULL;                   \
+          pCube;                                                \
+          pCube = pCube2,                                       \
+          pCube2 = pCube? pCube->pNext: NULL )
+#define Min_CoverForEachCubePrev( pCover, pCube, ppPrev )       \
+    for ( pCube = pCover,                                       \
+          ppPrev = &(pCover);                                   \
+          pCube;                                                \
+          ppPrev = &pCube->pNext,                               \
+          pCube = pCube->pNext )
+
+// macros to get hold of bits and values in the cubes
+static inline int  Min_CubeHasBit( Min_Cube_t * p, int i )              { return (p->uData[(i)>>5] & (1<<((i) & 31))) > 0;     }
+static inline void Min_CubeSetBit( Min_Cube_t * p, int i )              { p->uData[(i)>>5] |= (1<<((i) & 31));                 }
+static inline void Min_CubeXorBit( Min_Cube_t * p, int i )              { p->uData[(i)>>5] ^= (1<<((i) & 31));                 }
+static inline int  Min_CubeGetVar( Min_Cube_t * p, int Var )            { return 3 & (p->uData[(2*Var)>>5] >> ((2*Var) & 31)); }
+static inline void Min_CubeXorVar( Min_Cube_t * p, int Var, int Value ) { p->uData[(2*Var)>>5] ^= (Value<<((2*Var) & 31));     }
+
+/*=== covMinEsop.c ==========================================================*/
+extern void         Min_EsopMinimize( Min_Man_t * p );
+extern void         Min_EsopAddCube( Min_Man_t * p, Min_Cube_t * pCube );
+/*=== covMinSop.c ==========================================================*/
+extern void         Min_SopMinimize( Min_Man_t * p );
+extern void         Min_SopAddCube( Min_Man_t * p, Min_Cube_t * pCube );
+/*=== covMinMan.c ==========================================================*/
+extern Min_Man_t *  Min_ManAlloc( int nVars );
+extern void         Min_ManClean( Min_Man_t * p, int nSupp );
+extern void         Min_ManFree( Min_Man_t * p );
+/*=== covMinUtil.c ==========================================================*/
+extern void         Min_CoverCreate( Vec_Str_t * vCover, Min_Cube_t * pCover, char Type );
+extern void         Min_CubeWrite( FILE * pFile, Min_Cube_t * pCube );
+extern void         Min_CoverWrite( FILE * pFile, Min_Cube_t * pCover );
+extern void         Min_CoverWriteStore( FILE * pFile, Min_Man_t * p );
+extern void         Min_CoverWriteFile( Min_Cube_t * pCover, char * pName, int fEsop );
+extern void         Min_CoverCheck( Min_Man_t * p );
+extern int          Min_CubeCheck( Min_Cube_t * pCube );
+extern Min_Cube_t * Min_CoverCollect( Min_Man_t * p, int nSuppSize );
+extern void         Min_CoverExpand( Min_Man_t * p, Min_Cube_t * pCover );
+extern int          Min_CoverSuppVarNum( Min_Man_t * p, Min_Cube_t * pCover );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Min_Cube_t * Min_CubeAlloc( Min_Man_t * p )
+{
+    Min_Cube_t * pCube;
+    pCube = (Min_Cube_t *)Extra_MmFixedEntryFetch( p->pMemMan );
+    pCube->pNext  = NULL;
+    pCube->nVars  = p->nVars;
+    pCube->nWords = p->nWords;
+    pCube->nLits  = 0;
+    memset( pCube->uData, 0xff, sizeof(unsigned) * p->nWords );
+    return pCube;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the cube representing elementary var.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Min_Cube_t * Min_CubeAllocVar( Min_Man_t * p, int iVar, int fCompl )
+{
+    Min_Cube_t * pCube;
+    pCube = Min_CubeAlloc( p );
+    Min_CubeXorBit( pCube, iVar*2+fCompl );
+    pCube->nLits = 1;
+    return pCube;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Min_Cube_t * Min_CubeDup( Min_Man_t * p, Min_Cube_t * pCopy )
+{
+    Min_Cube_t * pCube;
+    pCube = Min_CubeAlloc( p );
+    memcpy( pCube->uData, pCopy->uData, sizeof(unsigned) * p->nWords );
+    pCube->nLits = pCopy->nLits;
+    return pCube;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Min_CubeRecycle( Min_Man_t * p, Min_Cube_t * pCube )
+{
+    Extra_MmFixedEntryRecycle( p->pMemMan, (char *)pCube );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the cube cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Min_CoverRecycle( Min_Man_t * p, Min_Cube_t * pCover )
+{
+    Min_Cube_t * pCube, * pCube2;
+    Min_CoverForEachCubeSafe( pCover, pCube, pCube2 )
+        Extra_MmFixedEntryRecycle( p->pMemMan, (char *)pCube );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of cubes in the cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Min_CubeCountLits( Min_Cube_t * pCube )
+{
+    unsigned uData;
+    int Count = 0, i, w;
+    for ( w = 0; w < (int)pCube->nWords; w++ )
+    {
+        uData = pCube->uData[w] ^ (pCube->uData[w] >> 1);
+        for ( i = 0; i < 32; i += 2 )
+            if ( uData & (1 << i) )
+                Count++;
+    }
+    return Count;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of cubes in the cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Min_CubeGetLits( Min_Cube_t * pCube, Vec_Int_t * vLits )
+{
+    unsigned uData;
+    int i, w;
+    Vec_IntClear( vLits );
+    for ( w = 0; w < (int)pCube->nWords; w++ )
+    {
+        uData = pCube->uData[w] ^ (pCube->uData[w] >> 1);
+        for ( i = 0; i < 32; i += 2 )
+            if ( uData & (1 << i) )
+                Vec_IntPush( vLits, w*16 + i/2 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of cubes in the cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Min_CoverCountCubes( Min_Cube_t * pCover )
+{
+    Min_Cube_t * pCube;
+    int Count = 0;
+    Min_CoverForEachCube( pCover, pCube )
+        Count++;
+    return Count;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if two cubes are disjoint.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Min_CubesDisjoint( Min_Cube_t * pCube0, Min_Cube_t * pCube1 )
+{
+    unsigned uData;
+    int i;
+    assert( pCube0->nVars == pCube1->nVars );
+    for ( i = 0; i < (int)pCube0->nWords; i++ )
+    {
+        uData = pCube0->uData[i] & pCube1->uData[i];
+        uData = (uData | (uData >> 1)) & 0x55555555;
+        if ( uData != 0x55555555 )
+            return 1;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the disjoint variables of the two cubes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Min_CoverGetDisjVars( Min_Cube_t * pThis, Min_Cube_t * pCube, Vec_Int_t * vVars )
+{
+    unsigned uData;
+    int i, w;
+    Vec_IntClear( vVars );
+    for ( w = 0; w < (int)pCube->nWords; w++ )
+    {
+        uData  = pThis->uData[w] & (pThis->uData[w] >> 1) & 0x55555555;
+        uData &= (pCube->uData[w] ^ (pCube->uData[w] >> 1));
+        if ( uData == 0 )
+            continue;
+        for ( i = 0; i < 32; i += 2 )
+            if ( uData & (1 << i) )
+                Vec_IntPush( vVars, w*16 + i/2 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if two cubes are disjoint.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Min_CubesDistOne( Min_Cube_t * pCube0, Min_Cube_t * pCube1, Min_Cube_t * pTemp )
+{
+    unsigned uData;
+    int i, fFound = 0;
+    for ( i = 0; i < (int)pCube0->nWords; i++ )
+    {
+        uData = pCube0->uData[i] ^ pCube1->uData[i];
+        if ( uData == 0 )
+        {
+            if ( pTemp ) pTemp->uData[i] = 0;
+            continue;
+        }
+        if ( fFound )
+            return 0;
+        uData = (uData | (uData >> 1)) & 0x55555555;
+        if ( (uData & (uData-1)) > 0 ) // more than one 1
+            return 0;
+        if ( pTemp ) pTemp->uData[i] = uData | (uData << 1);
+        fFound = 1;
+    }
+    if ( fFound == 0 )
+    {
+        printf( "\n" );
+        Min_CubeWrite( stdout, pCube0 );
+        Min_CubeWrite( stdout, pCube1 );
+        printf( "Error: Min_CubesDistOne() looks at two equal cubes!\n" );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if two cubes are disjoint.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Min_CubesDistTwo( Min_Cube_t * pCube0, Min_Cube_t * pCube1, int * pVar0, int * pVar1 )
+{
+    unsigned uData;//, uData2;
+    int i, k, Var0 = -1, Var1 = -1;
+    for ( i = 0; i < (int)pCube0->nWords; i++ )
+    {
+        uData = pCube0->uData[i] ^ pCube1->uData[i];
+        if ( uData == 0 )
+            continue;
+        if ( Var0 >= 0 && Var1 >= 0 ) // more than two 1s
+            return 0;
+        uData = (uData | (uData >> 1)) & 0x55555555;
+        if ( (Var0 >= 0 || Var1 >= 0) && (uData & (uData-1)) > 0 )
+            return 0;
+        for ( k = 0; k < 32; k += 2 )
+            if ( uData & (1 << k) )
+            {
+                if ( Var0 == -1 )
+                    Var0 = 16 * i + k/2;
+                else if ( Var1 == -1 )
+                    Var1 = 16 * i + k/2;
+                else
+                    return 0;
+            }
+        /*
+        if ( Var0 >= 0 )
+        {
+            uData &= 0xFFFF;
+            uData2 = (uData >> 16);
+            if ( uData && uData2 )
+                return 0;
+            if ( uData )
+            {
+            }
+            uData }= uData2;
+            uData &= 0x
+        }
+        */
+    }
+    if ( Var0 >= 0 && Var1 >= 0 )
+    {
+        *pVar0 = Var0;
+        *pVar1 = Var1;
+        return 1;
+    }
+    if ( Var0 == -1 || Var1 == -1 )
+    {
+        printf( "\n" );
+        Min_CubeWrite( stdout, pCube0 );
+        Min_CubeWrite( stdout, pCube1 );
+        printf( "Error: Min_CubesDistTwo() looks at two equal cubes or dist1 cubes!\n" );
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Makes the produce of two cubes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Min_Cube_t * Min_CubesProduct( Min_Man_t * p, Min_Cube_t * pCube0, Min_Cube_t * pCube1 )
+{
+    Min_Cube_t * pCube;
+    int i;
+    assert( pCube0->nVars == pCube1->nVars );
+    pCube = Min_CubeAlloc( p );
+    for ( i = 0; i < p->nWords; i++ )
+        pCube->uData[i] = pCube0->uData[i] & pCube1->uData[i];
+    pCube->nLits = Min_CubeCountLits( pCube );
+    return pCube;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Makes the produce of two cubes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Min_Cube_t * Min_CubesXor( Min_Man_t * p, Min_Cube_t * pCube0, Min_Cube_t * pCube1 )
+{
+    Min_Cube_t * pCube;
+    int i;
+    assert( pCube0->nVars == pCube1->nVars );
+    pCube = Min_CubeAlloc( p );
+    for ( i = 0; i < p->nWords; i++ )
+        pCube->uData[i] = pCube0->uData[i] ^ pCube1->uData[i];
+    pCube->nLits = Min_CubeCountLits( pCube );
+    return pCube;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Makes the produce of two cubes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Min_CubesAreEqual( Min_Cube_t * pCube0, Min_Cube_t * pCube1 )
+{
+    int i;
+    for ( i = 0; i < (int)pCube0->nWords; i++ )
+        if ( pCube0->uData[i] != pCube1->uData[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pCube1 is contained in pCube0, bitwise.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Min_CubeIsContained( Min_Cube_t * pCube0, Min_Cube_t * pCube1 )
+{
+    int i;
+    for ( i = 0; i < (int)pCube0->nWords; i++ )
+        if ( (pCube0->uData[i] & pCube1->uData[i]) != pCube1->uData[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the cube into the result of merging.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Min_CubesTransform( Min_Cube_t * pCube, Min_Cube_t * pDist, Min_Cube_t * pMask )
+{
+    int w;
+    for ( w = 0; w < (int)pCube->nWords; w++ )
+    {
+        pCube->uData[w]  =  pCube->uData[w] ^ pDist->uData[w];
+        pCube->uData[w] |= (pDist->uData[w] & ~pMask->uData[w]);
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the cube into the result of distance-1 merging.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Min_CubesTransformOr( Min_Cube_t * pCube, Min_Cube_t * pDist )
+{
+    int w;
+    for ( w = 0; w < (int)pCube->nWords; w++ )
+        pCube->uData[w] |= pDist->uData[w];
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts the cover in the increasing number of literals.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Min_CoverExpandRemoveEqual( Min_Man_t * p, Min_Cube_t * pCover )
+{
+    Min_Cube_t * pCube, * pCube2, * pThis;
+    if ( pCover == NULL )
+    {
+        Min_ManClean( p, p->nVars );
+        return;
+    }
+    Min_ManClean( p, pCover->nVars );
+    Min_CoverForEachCubeSafe( pCover, pCube, pCube2 )
+    {
+        // go through the linked list
+        Min_CoverForEachCube( p->ppStore[pCube->nLits], pThis )
+            if ( Min_CubesAreEqual( pCube, pThis ) )
+            {
+                Min_CubeRecycle( p, pCube );
+                break;
+            }
+        if ( pThis != NULL )
+            continue;
+        pCube->pNext = p->ppStore[pCube->nLits];
+        p->ppStore[pCube->nLits] = pCube;
+        p->nCubes++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the given cube is contained in one of the cubes of the cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Min_CoverContainsCube( Min_Man_t * p, Min_Cube_t * pCube )
+{
+    Min_Cube_t * pThis;
+    int i;
+/*
+    // this cube cannot be equal to any cube
+    Min_CoverForEachCube( p->ppStore[pCube->nLits], pThis )
+    {
+        if ( Min_CubesAreEqual( pCube, pThis ) )
+        {
+            Min_CubeWrite( stdout, pCube );
+            assert( 0 );
+        }
+    }
+*/
+    // try to find a containing cube
+    for ( i = 0; i <= (int)pCube->nLits; i++ )
+    Min_CoverForEachCube( p->ppStore[i], pThis )
+    {
+        // skip the bubble
+        if ( pThis != p->pBubble && Min_CubeIsContained( pThis, pCube ) )
+            return 1;
+    }
+    return 0;
+}
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/map/cov/covMan.c b/abc-build/src/map/cov/covMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/cov/covMan.c
@@ -0,0 +1,149 @@
+/**CFile****************************************************************
+
+  FileName    [covMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Mapping into network of SOPs/ESOPs.]
+
+  Synopsis    [Decomposition manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: covMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cov.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cov_Man_t * Cov_ManAlloc( Abc_Ntk_t * pNtk, int nFaninMax )
+{
+    Cov_Man_t * pMan;
+    Cov_Obj_t * pMem;
+    Abc_Obj_t * pObj;
+    int i;
+    assert( pNtk->pManCut == NULL );
+
+    // start the manager
+    pMan = ABC_ALLOC( Cov_Man_t, 1 );
+    memset( pMan, 0, sizeof(Cov_Man_t) );
+    pMan->nFaninMax = nFaninMax;
+    pMan->nCubesMax = 2 * pMan->nFaninMax;
+    pMan->nWords    = Abc_BitWordNum( nFaninMax * 2 );
+
+    // get the cubes
+    pMan->vComTo0 = Vec_IntAlloc( 2*nFaninMax );
+    pMan->vComTo1 = Vec_IntAlloc( 2*nFaninMax );
+    pMan->vPairs0 = Vec_IntAlloc( nFaninMax );
+    pMan->vPairs1 = Vec_IntAlloc( nFaninMax );
+    pMan->vTriv0  = Vec_IntAlloc( 1 );  Vec_IntPush( pMan->vTriv0, -1 ); 
+    pMan->vTriv1  = Vec_IntAlloc( 1 );  Vec_IntPush( pMan->vTriv1, -1 ); 
+
+    // allocate memory for object structures
+    pMan->pMemory = pMem = ABC_ALLOC( Cov_Obj_t, sizeof(Cov_Obj_t) * Abc_NtkObjNumMax(pNtk) );
+    memset( pMem, 0, sizeof(Cov_Obj_t) * Abc_NtkObjNumMax(pNtk) );
+    // allocate storage for the pointers to the memory
+    pMan->vObjStrs = Vec_PtrAlloc( Abc_NtkObjNumMax(pNtk) );
+    Vec_PtrFill( pMan->vObjStrs, Abc_NtkObjNumMax(pNtk), NULL );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        Vec_PtrWriteEntry( pMan->vObjStrs, i, pMem + i );
+    // create the cube manager
+    pMan->pManMin = Min_ManAlloc( nFaninMax );
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cov_ManFree( Cov_Man_t * p )
+{
+    Vec_Int_t * vSupp;
+    int i;
+    for ( i = 0; i < p->vObjStrs->nSize; i++ )
+    {
+        vSupp = ((Cov_Obj_t *)p->vObjStrs->pArray[i])->vSupp;
+        if ( vSupp ) Vec_IntFree( vSupp );
+    }
+
+    Min_ManFree( p->pManMin );
+    Vec_PtrFree( p->vObjStrs );
+    Vec_IntFree( p->vFanCounts );
+    Vec_IntFree( p->vTriv0 );
+    Vec_IntFree( p->vTriv1 );
+    Vec_IntFree( p->vComTo0 );
+    Vec_IntFree( p->vComTo1 );
+    Vec_IntFree( p->vPairs0 );
+    Vec_IntFree( p->vPairs1 );
+    ABC_FREE( p->pMemory );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Drop the covers at the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeCovDropData( Cov_Man_t * p, Abc_Obj_t * pObj )
+{
+    int nFanouts;
+    assert( p->vFanCounts );
+    nFanouts = Vec_IntEntry( p->vFanCounts, pObj->Id );
+    assert( nFanouts > 0 );
+    if ( --nFanouts == 0 )
+    {
+        Vec_IntFree( Abc_ObjGetSupp(pObj) );
+        Abc_ObjSetSupp( pObj, NULL );
+        Min_CoverRecycle( p->pManMin, Abc_ObjGetCover2(pObj) );
+        Abc_ObjSetCover2( pObj, NULL );
+        p->nSupps--;
+    }
+    Vec_IntWriteEntry( p->vFanCounts, pObj->Id, nFanouts );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/cov/covMinEsop.c b/abc-build/src/map/cov/covMinEsop.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/cov/covMinEsop.c
@@ -0,0 +1,304 @@
+/**CFile****************************************************************
+
+  FileName    [covMinEsop.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Mapping into network of SOPs/ESOPs.]
+
+  Synopsis    [ESOP manipulation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: covMinEsop.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "covInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Min_EsopRewrite( Min_Man_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_EsopMinimize( Min_Man_t * p )
+{
+    int nCubesInit, nCubesOld, nIter;
+    if ( p->nCubes < 3 )
+        return;
+    nIter = 0;
+    nCubesInit = p->nCubes;
+    do {
+        nCubesOld = p->nCubes;
+        Min_EsopRewrite( p );
+        nIter++;
+    }
+    while ( 100.0*(nCubesOld - p->nCubes)/nCubesOld > 3.0 );
+
+//    printf( "%d:%d->%d ", nIter, nCubesInit, p->nCubes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one round of rewriting using distance 2 cubes.]
+
+  Description [The weakness of this procedure is that it tries each cube
+  with only one distance-2 cube. If this pair does not lead to improvement
+  the cube is inserted into the cover anyhow, and we try another pair.
+  A possible improvement would be to try this cube with all distance-2
+  cubes, until an improvement is found, or until all such cubes are tried.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_EsopRewrite( Min_Man_t * p )
+{
+    Min_Cube_t * pCube, ** ppPrev;
+    Min_Cube_t * pThis, ** ppPrevT;
+    int v00, v01, v10, v11, Var0, Var1, Index, nCubesOld;
+    int nPairs = 0;
+
+    // insert the bubble before the first cube
+    p->pBubble->pNext = p->ppStore[0];
+    p->ppStore[0] = p->pBubble;
+    p->pBubble->nLits = 0;
+
+    // go through the cubes
+    while ( 1 )
+    {
+        // get the index of the bubble
+        Index = p->pBubble->nLits;
+
+        // find the bubble
+        Min_CoverForEachCubePrev( p->ppStore[Index], pCube, ppPrev )
+            if ( pCube == p->pBubble )
+                break;
+        assert( pCube == p->pBubble );
+
+        // remove the bubble, get the next cube after the bubble
+        *ppPrev = p->pBubble->pNext;
+        pCube = p->pBubble->pNext;
+        if ( pCube == NULL )
+            for ( Index++; Index <= p->nVars; Index++ )
+                if ( p->ppStore[Index] )
+                {
+                    ppPrev = &(p->ppStore[Index]);
+                    pCube = p->ppStore[Index];
+                    break;
+                }
+        // stop if there is no more cubes
+        if ( pCube == NULL )
+            break;
+
+        // find the first dist2 cube
+        Min_CoverForEachCubePrev( pCube->pNext, pThis, ppPrevT )
+            if ( Min_CubesDistTwo( pCube, pThis, &Var0, &Var1 ) )
+                break;
+        if ( pThis == NULL && Index < p->nVars )
+        Min_CoverForEachCubePrev( p->ppStore[Index+1], pThis, ppPrevT )
+            if ( Min_CubesDistTwo( pCube, pThis, &Var0, &Var1 ) )
+                break;
+        if ( pThis == NULL && Index < p->nVars - 1 )
+        Min_CoverForEachCubePrev( p->ppStore[Index+2], pThis, ppPrevT )
+            if ( Min_CubesDistTwo( pCube, pThis, &Var0, &Var1 ) )
+                break;
+        // continue if there is no dist2 cube
+        if ( pThis == NULL )
+        {
+            // insert the bubble after the cube
+            p->pBubble->pNext = pCube->pNext;
+            pCube->pNext = p->pBubble;
+            p->pBubble->nLits = pCube->nLits;
+            continue;
+        }
+        nPairs++;
+
+        // remove the cubes, insert the bubble instead of pCube
+        *ppPrevT = pThis->pNext;
+        *ppPrev = p->pBubble;
+        p->pBubble->pNext = pCube->pNext;
+        p->pBubble->nLits = pCube->nLits;
+        p->nCubes -= 2;
+
+        // Exorlink-2:
+        // A{v00}     B{v01}      +  A{v10}     B{v11}     =
+        // A{v00+v10} B{v01}      +  A{v10}     B{v01+v11} =
+        // A{v00}     B{v01+v11}  +  A{v00+v10} B{v11}
+
+        // save the dist2 parameters
+        v00 = Min_CubeGetVar( pCube, Var0 );
+        v01 = Min_CubeGetVar( pCube, Var1 );
+        v10 = Min_CubeGetVar( pThis, Var0 );
+        v11 = Min_CubeGetVar( pThis, Var1 );
+//printf( "\n" );
+//Min_CubeWrite( stdout, pCube );
+//Min_CubeWrite( stdout, pThis );
+
+        // derive the first pair of resulting cubes
+        Min_CubeXorVar( pCube, Var0, v10 );
+        pCube->nLits -= (v00 != 3);
+        pCube->nLits += ((v00 ^ v10) != 3);
+        Min_CubeXorVar( pThis, Var1, v01 );
+        pThis->nLits -= (v11 != 3);
+        pThis->nLits += ((v01 ^ v11) != 3);
+
+        // add the cubes
+        nCubesOld = p->nCubes;
+        Min_EsopAddCube( p, pCube );
+        Min_EsopAddCube( p, pThis );
+        // check if the cubes were absorbed
+        if ( p->nCubes < nCubesOld + 2 )
+            continue;
+
+        // pull out both cubes
+        assert( pThis == p->ppStore[pThis->nLits] );
+        p->ppStore[pThis->nLits] = pThis->pNext;
+        assert( pCube == p->ppStore[pCube->nLits] );
+        p->ppStore[pCube->nLits] = pCube->pNext;
+        p->nCubes -= 2;
+
+        // derive the second pair of resulting cubes
+        Min_CubeXorVar( pCube, Var0, v10 );
+        pCube->nLits -= ((v00 ^ v10) != 3);
+        pCube->nLits += (v00 != 3);
+        Min_CubeXorVar( pCube, Var1, v11 );
+        pCube->nLits -= (v01 != 3);
+        pCube->nLits += ((v01 ^ v11) != 3);
+
+        Min_CubeXorVar( pThis, Var0, v00 );
+        pThis->nLits -= (v10 != 3);
+        pThis->nLits += ((v00 ^ v10) != 3);
+        Min_CubeXorVar( pThis, Var1, v01 );
+        pThis->nLits -= ((v01 ^ v11) != 3);
+        pThis->nLits += (v11 != 3);
+
+        // add them anyhow
+        Min_EsopAddCube( p, pCube );
+        Min_EsopAddCube( p, pThis );
+    }
+//    printf( "Pairs = %d  ", nPairs );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the cube to storage.]
+
+  Description [Returns 0 if the cube is added or removed. Returns 1
+  if the cube is glued with some other cube and has to be added again.
+  Do not forget to clean the storage!]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Min_EsopAddCubeInt( Min_Man_t * p, Min_Cube_t * pCube )
+{
+    Min_Cube_t * pThis, ** ppPrev;
+    // try to find the identical cube
+    Min_CoverForEachCubePrev( p->ppStore[pCube->nLits], pThis, ppPrev )
+    {
+        if ( Min_CubesAreEqual( pCube, pThis ) )
+        {
+            *ppPrev = pThis->pNext;
+            Min_CubeRecycle( p, pCube );
+            Min_CubeRecycle( p, pThis );
+            p->nCubes--;
+            return 0;
+        }
+    }
+    // find a distance-1 cube if it exists
+    if ( pCube->nLits < pCube->nVars )
+    Min_CoverForEachCubePrev( p->ppStore[pCube->nLits+1], pThis, ppPrev )
+    {
+        if ( Min_CubesDistOne( pCube, pThis, p->pTemp ) )
+        {
+            *ppPrev = pThis->pNext;
+            Min_CubesTransform( pCube, pThis, p->pTemp );
+            pCube->nLits++;
+            Min_CubeRecycle( p, pThis );
+            p->nCubes--;
+            return 1;
+        }
+    }
+    Min_CoverForEachCubePrev( p->ppStore[pCube->nLits], pThis, ppPrev )
+    {
+        if ( Min_CubesDistOne( pCube, pThis, p->pTemp ) )
+        {
+            *ppPrev = pThis->pNext;
+            Min_CubesTransform( pCube, pThis, p->pTemp );
+            pCube->nLits--;
+            Min_CubeRecycle( p, pThis );
+            p->nCubes--;
+            return 1;
+        }
+    }
+    if ( pCube->nLits > 0 )
+    Min_CoverForEachCubePrev( p->ppStore[pCube->nLits-1], pThis, ppPrev )
+    {
+        if ( Min_CubesDistOne( pCube, pThis, p->pTemp ) )
+        {
+            *ppPrev = pThis->pNext;
+            Min_CubesTransform( pCube, pThis, p->pTemp );
+            Min_CubeRecycle( p, pThis );
+            p->nCubes--;
+            return 1;
+        }
+    }
+    // add the cube
+    pCube->pNext = p->ppStore[pCube->nLits];
+    p->ppStore[pCube->nLits] = pCube;
+    p->nCubes++;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the cube to storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_EsopAddCube( Min_Man_t * p, Min_Cube_t * pCube )
+{
+    assert( pCube != p->pBubble );
+    assert( (int)pCube->nLits == Min_CubeCountLits(pCube) );
+    while ( Min_EsopAddCubeInt( p, pCube ) );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/cov/covMinMan.c b/abc-build/src/map/cov/covMinMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/cov/covMinMan.c
@@ -0,0 +1,118 @@
+/**CFile****************************************************************
+
+  FileName    [covMinMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Mapping into network of SOPs/ESOPs.]
+
+  Synopsis    [SOP manipulation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: covMinMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "covInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the minimization manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Min_Man_t * Min_ManAlloc( int nVars )
+{
+    Min_Man_t * pMan;
+    // start the manager
+    pMan = ABC_ALLOC( Min_Man_t, 1 );
+    memset( pMan, 0, sizeof(Min_Man_t) );
+    pMan->nVars   = nVars;
+    pMan->nWords  = Abc_BitWordNum( nVars * 2 );
+    pMan->pMemMan = Extra_MmFixedStart( sizeof(Min_Cube_t) + sizeof(unsigned) * (pMan->nWords - 1) );
+    // allocate storage for the temporary cover
+    pMan->ppStore = ABC_ALLOC( Min_Cube_t *, pMan->nVars + 1 );
+    // create tautology cubes
+    Min_ManClean( pMan, nVars );
+    pMan->pOne0  = Min_CubeAlloc( pMan );
+    pMan->pOne1  = Min_CubeAlloc( pMan );
+    pMan->pTemp  = Min_CubeAlloc( pMan );
+    pMan->pBubble = Min_CubeAlloc( pMan );  pMan->pBubble->uData[0] = 0;
+    // create trivial cubes
+    Min_ManClean( pMan, 1 );
+    pMan->pTriv0[0] = Min_CubeAllocVar( pMan, 0, 0 );
+    pMan->pTriv0[1] = Min_CubeAllocVar( pMan, 0, 1 );   
+    pMan->pTriv1[0] = Min_CubeAllocVar( pMan, 0, 0 );
+    pMan->pTriv1[1] = Min_CubeAllocVar( pMan, 0, 1 );   
+    Min_ManClean( pMan, nVars );
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the minimization manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_ManClean( Min_Man_t * p, int nSupp )
+{
+    // set the size of the cube manager
+    p->nVars  = nSupp;
+    p->nWords = Abc_BitWordNum(2*nSupp);
+    // clean the storage
+    memset( p->ppStore, 0, sizeof(Min_Cube_t *) * (nSupp + 1) );
+    p->nCubes = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the minimization manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_ManFree( Min_Man_t * p )
+{
+    Extra_MmFixedStop( p->pMemMan );
+    ABC_FREE( p->ppStore );
+    ABC_FREE( p );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/cov/covMinSop.c b/abc-build/src/map/cov/covMinSop.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/cov/covMinSop.c
@@ -0,0 +1,620 @@
+/**CFile****************************************************************
+
+  FileName    [covMinSop.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Mapping into network of SOPs/ESOPs.]
+
+  Synopsis    [SOP manipulation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: covMinSop.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "covInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Min_SopRewrite( Min_Man_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_SopMinimize( Min_Man_t * p )
+{
+    int nCubesInit, nCubesOld, nIter;
+    if ( p->nCubes < 3 )
+        return;
+    nIter = 0;
+    nCubesInit = p->nCubes;
+    do {
+        nCubesOld = p->nCubes;
+        Min_SopRewrite( p );
+        nIter++;
+//    printf( "%d:%d->%d ", nIter, nCubesInit, p->nCubes );
+    }
+    while ( 100.0*(nCubesOld - p->nCubes)/nCubesOld > 3.0 );
+//    printf( "\n" );
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_SopRewrite( Min_Man_t * p )
+{
+    Min_Cube_t * pCube, ** ppPrev;
+    Min_Cube_t * pThis, ** ppPrevT;
+    Min_Cube_t * pTemp;
+    int v00, v01, v10, v11, Var0, Var1, Index, fCont0, fCont1, nCubesOld;
+    int nPairs = 0;
+/*    
+    {
+        Min_Cube_t * pCover;
+        pCover = Min_CoverCollect( p, p->nVars );
+printf( "\n\n" );
+Min_CoverWrite( stdout, pCover );
+        Min_CoverExpand( p, pCover );
+    }
+*/
+
+    // insert the bubble before the first cube
+    p->pBubble->pNext = p->ppStore[0];
+    p->ppStore[0] = p->pBubble;
+    p->pBubble->nLits = 0;
+
+    // go through the cubes
+    while ( 1 )
+    {
+        // get the index of the bubble
+        Index = p->pBubble->nLits;
+
+        // find the bubble
+        Min_CoverForEachCubePrev( p->ppStore[Index], pCube, ppPrev )
+            if ( pCube == p->pBubble )
+                break;
+        assert( pCube == p->pBubble );
+
+        // remove the bubble, get the next cube after the bubble
+        *ppPrev = p->pBubble->pNext;
+        pCube = p->pBubble->pNext;
+        if ( pCube == NULL )
+            for ( Index++; Index <= p->nVars; Index++ )
+                if ( p->ppStore[Index] )
+                {
+                    ppPrev = &(p->ppStore[Index]);
+                    pCube = p->ppStore[Index];
+                    break;
+                }
+        // stop if there is no more cubes
+        if ( pCube == NULL )
+            break;
+
+        // find the first dist2 cube
+        Min_CoverForEachCubePrev( pCube->pNext, pThis, ppPrevT )
+            if ( Min_CubesDistTwo( pCube, pThis, &Var0, &Var1 ) )
+                break;
+        if ( pThis == NULL && Index < p->nVars )
+        Min_CoverForEachCubePrev( p->ppStore[Index+1], pThis, ppPrevT )
+            if ( Min_CubesDistTwo( pCube, pThis, &Var0, &Var1 ) )
+                break;
+        // continue if there is no dist2 cube
+        if ( pThis == NULL )
+        {
+            // insert the bubble after the cube
+            p->pBubble->pNext = pCube->pNext;
+            pCube->pNext = p->pBubble;
+            p->pBubble->nLits = pCube->nLits;
+            continue;
+        }
+        nPairs++;
+/*
+printf( "\n" );
+Min_CubeWrite( stdout, pCube );
+Min_CubeWrite( stdout, pThis );
+*/
+        // remove the cubes, insert the bubble instead of pCube
+        *ppPrevT = pThis->pNext;
+        *ppPrev = p->pBubble;
+        p->pBubble->pNext = pCube->pNext;
+        p->pBubble->nLits = pCube->nLits;
+        p->nCubes -= 2;
+
+        assert( pCube != p->pBubble && pThis != p->pBubble );
+
+
+        // save the dist2 parameters
+        v00 = Min_CubeGetVar( pCube, Var0 );
+        v01 = Min_CubeGetVar( pCube, Var1 );
+        v10 = Min_CubeGetVar( pThis, Var0 );
+        v11 = Min_CubeGetVar( pThis, Var1 );
+        assert( v00 != v10 && v01 != v11 );
+        assert( v00 != 3   || v01 != 3 );
+        assert( v10 != 3   || v11 != 3 );
+
+//printf( "\n" );
+//Min_CubeWrite( stdout, pCube );
+//Min_CubeWrite( stdout, pThis );
+
+//printf( "\n" );
+//Min_CubeWrite( stdout, pCube );
+//Min_CubeWrite( stdout, pThis );
+
+        // consider the case when both cubes have non-empty literals
+        if ( v00 != 3 && v01 != 3 && v10 != 3 && v11 != 3 )
+        {
+            assert( v00 == (v10 ^ 3) );
+            assert( v01 == (v11 ^ 3) );
+            // create the temporary cube equal to the first corner
+            Min_CubeXorVar( pCube, Var0, 3 );
+            // check if this cube is contained
+            fCont0 = Min_CoverContainsCube( p, pCube );
+            // create the temporary cube equal to the first corner
+            Min_CubeXorVar( pCube, Var0, 3 );
+            Min_CubeXorVar( pCube, Var1, 3 );
+//printf( "\n" );
+//Min_CubeWrite( stdout, pCube );
+//Min_CubeWrite( stdout, pThis );
+            // check if this cube is contained
+            fCont1 = Min_CoverContainsCube( p, pCube );
+            // undo the change
+            Min_CubeXorVar( pCube, Var1, 3 );
+
+            // check if the cubes can be overwritten
+            if ( fCont0 && fCont1 )
+            {
+                // one of the cubes can be recycled, the other expanded and added
+                Min_CubeRecycle( p, pThis );
+                // remove the literals
+                Min_CubeXorVar( pCube, Var0, v00 ^ 3 );
+                Min_CubeXorVar( pCube, Var1, v01 ^ 3 );
+                pCube->nLits -= 2;
+                Min_SopAddCube( p, pCube );
+            }
+            else if ( fCont0 )
+            {
+                // expand both cubes and add them
+                Min_CubeXorVar( pCube, Var0, v00 ^ 3 );
+                pCube->nLits--;
+                Min_SopAddCube( p, pCube );
+                Min_CubeXorVar( pThis, Var1, v11 ^ 3 );
+                pThis->nLits--;
+                Min_SopAddCube( p, pThis );
+            }
+            else if ( fCont1 )
+            {
+                // expand both cubes and add them
+                Min_CubeXorVar( pCube, Var1, v01 ^ 3 );
+                pCube->nLits--;
+                Min_SopAddCube( p, pCube );
+                Min_CubeXorVar( pThis, Var0, v10 ^ 3 );
+                pThis->nLits--;
+                Min_SopAddCube( p, pThis );
+            }
+            else
+            {
+                Min_SopAddCube( p, pCube );
+                Min_SopAddCube( p, pThis );
+            }
+            // otherwise, no change is possible
+            continue;
+        }
+
+        // if one of them does not have DC lit, move it
+        if ( v00 != 3 && v01 != 3 )
+        {
+            assert( v10 == 3 || v11 == 3 );
+            pTemp = pCube; pCube = pThis; pThis = pTemp;
+            Index = v00; v00 = v10; v10 = Index;
+            Index = v01; v01 = v11; v11 = Index;
+        }
+
+        // make sure the first cube has first var DC
+        if ( v00 != 3 )
+        {
+            assert( v01 == 3 );
+            Index = Var0; Var0 = Var1; Var1 = Index;
+            Index = v00; v00 = v01; v01 = Index;
+            Index = v10; v10 = v11; v11 = Index;
+        }
+
+        // consider both cases: both have DC lit
+        if ( v00 == 3 && v11 == 3 )
+        {
+            assert( v01 != 3 && v10 != 3 );
+            // try the remaining minterm
+            // create the temporary cube equal to the first corner
+            Min_CubeXorVar( pCube, Var0, v10 );
+            Min_CubeXorVar( pCube, Var1, 3   );
+            pCube->nLits++;
+            // check if this cube is contained
+            fCont0 = Min_CoverContainsCube( p, pCube );
+            // undo the cube transformations
+            Min_CubeXorVar( pCube, Var0, v10 );
+            Min_CubeXorVar( pCube, Var1, 3   );
+            pCube->nLits--;
+            // check the case when both are covered
+            if ( fCont0 )
+            {
+                // one of the cubes can be recycled, the other expanded and added
+                Min_CubeRecycle( p, pThis );
+                // remove the literals
+                Min_CubeXorVar( pCube, Var1, v01 ^ 3 );
+                pCube->nLits--;
+                Min_SopAddCube( p, pCube );
+            }
+            else
+            {
+                // try two reduced cubes
+                Min_CubeXorVar( pCube, Var0, v10 );
+                pCube->nLits++;
+                // remember the cubes
+                nCubesOld = p->nCubes;
+                Min_SopAddCube( p, pCube );
+                // check if the cube is absorbed
+                if ( p->nCubes < nCubesOld + 1 )
+                { // absorbed - add the second cube
+                    Min_SopAddCube( p, pThis );
+                }
+                else
+                { // remove this cube, and try another one
+                    assert( pCube == p->ppStore[pCube->nLits] );
+                    p->ppStore[pCube->nLits] = pCube->pNext;
+                    p->nCubes--;
+
+                    // return the cube to the previous state
+                    Min_CubeXorVar( pCube, Var0, v10 );
+                    pCube->nLits--;
+
+                    // generate another reduced cube
+                    Min_CubeXorVar( pThis, Var1, v01 );
+                    pThis->nLits++;
+
+                    // add both cubes
+                    Min_SopAddCube( p, pCube );
+                    Min_SopAddCube( p, pThis );
+                }
+            }
+        }
+        else // the first cube has DC lit
+        {
+            assert( v01 != 3 && v10 != 3 && v11 != 3 );
+            // try the remaining minterm
+            // create the temporary cube equal to the minterm
+            Min_CubeXorVar( pThis, Var0, 3 );
+            // check if this cube is contained
+            fCont0 = Min_CoverContainsCube( p, pThis );
+            // undo the cube transformations
+            Min_CubeXorVar( pThis, Var0, 3 );
+            // check the case when both are covered
+            if ( fCont0 )
+            {
+                // one of the cubes can be recycled, the other expanded and added
+                Min_CubeRecycle( p, pThis );
+                // remove the literals
+                Min_CubeXorVar( pCube, Var1, v01 ^ 3 );
+                pCube->nLits--;
+                Min_SopAddCube( p, pCube );
+            }
+            else
+            {
+                // try reshaping the cubes
+                // reduce the first cube
+                Min_CubeXorVar( pCube, Var0, v10 );
+                pCube->nLits++;
+                // expand the second cube
+                Min_CubeXorVar( pThis, Var1, v11 ^ 3 );
+                pThis->nLits--;
+                // add both cubes
+                Min_SopAddCube( p, pCube );
+                Min_SopAddCube( p, pThis );
+            }
+        }
+    }
+//    printf( "Pairs = %d  ", nPairs );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds cube to the SOP cover stored in the manager.]
+
+  Description [Returns 0 if the cube is added or removed. Returns 1
+  if the cube is glued with some other cube and has to be added again.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Min_SopAddCubeInt( Min_Man_t * p, Min_Cube_t * pCube )
+{
+    Min_Cube_t * pThis, * pThis2, ** ppPrev;
+    int i;
+    // try to find the identical cube
+    Min_CoverForEachCube( p->ppStore[pCube->nLits], pThis )
+    {
+        if ( Min_CubesAreEqual( pCube, pThis ) )
+        {
+            Min_CubeRecycle( p, pCube );
+            return 0;
+        }
+    }
+    // try to find a containing cube
+    for ( i = 0; i < (int)pCube->nLits; i++ )
+    Min_CoverForEachCube( p->ppStore[i], pThis )
+    {
+        if ( pThis != p->pBubble && Min_CubeIsContained( pThis, pCube ) )
+        {
+            Min_CubeRecycle( p, pCube );
+            return 0;
+        }
+    }
+    // try to find distance one in the same bin
+    Min_CoverForEachCubePrev( p->ppStore[pCube->nLits], pThis, ppPrev )
+    {
+        if ( Min_CubesDistOne( pCube, pThis, NULL ) )
+        {
+            *ppPrev = pThis->pNext;
+            Min_CubesTransformOr( pCube, pThis );
+            pCube->nLits--;
+            Min_CubeRecycle( p, pThis );
+            p->nCubes--;
+            return 1;
+        }
+    }
+
+    // clean the other cubes using this one
+    for ( i = pCube->nLits + 1; i <= (int)pCube->nVars; i++ )
+    {
+        ppPrev = &p->ppStore[i];
+        Min_CoverForEachCubeSafe( p->ppStore[i], pThis, pThis2 )
+        {
+            if ( pThis != p->pBubble && Min_CubeIsContained( pCube, pThis ) )
+            {
+                *ppPrev = pThis->pNext;
+                Min_CubeRecycle( p, pThis );
+                p->nCubes--;
+            }
+            else
+                ppPrev = &pThis->pNext;
+        }
+    }
+
+    // add the cube
+    pCube->pNext = p->ppStore[pCube->nLits];
+    p->ppStore[pCube->nLits] = pCube;
+    p->nCubes++;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the cube to storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_SopAddCube( Min_Man_t * p, Min_Cube_t * pCube )
+{
+    assert( Min_CubeCheck( pCube ) );
+    assert( pCube != p->pBubble );
+    assert( (int)pCube->nLits == Min_CubeCountLits(pCube) );
+    while ( Min_SopAddCubeInt( p, pCube ) );
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_SopContain( Min_Man_t * p )
+{
+    Min_Cube_t * pCube, * pCube2, ** ppPrev;
+    int i, k;
+    for ( i = 0; i <= p->nVars; i++ )
+    {
+        Min_CoverForEachCube( p->ppStore[i], pCube )
+        Min_CoverForEachCubePrev( pCube->pNext, pCube2, ppPrev )
+        {
+            if ( !Min_CubesAreEqual( pCube, pCube2 ) )
+                continue;
+            *ppPrev = pCube2->pNext;
+            Min_CubeRecycle( p, pCube2 );
+            p->nCubes--;
+        }
+        for ( k = i + 1; k <= p->nVars; k++ )
+        Min_CoverForEachCubePrev( p->ppStore[k], pCube2, ppPrev )
+        {
+            if ( !Min_CubeIsContained( pCube, pCube2 ) )
+                continue;
+            *ppPrev = pCube2->pNext;
+            Min_CubeRecycle( p, pCube2 );
+            p->nCubes--;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_SopDist1Merge( Min_Man_t * p )
+{
+    Min_Cube_t * pCube, * pCube2, * pCubeNew;
+    int i;
+    for ( i = p->nVars; i >= 0; i-- )
+    {
+        Min_CoverForEachCube( p->ppStore[i], pCube )
+        Min_CoverForEachCube( pCube->pNext, pCube2 )
+        {
+            assert( pCube->nLits == pCube2->nLits );
+            if ( !Min_CubesDistOne( pCube, pCube2, NULL ) )
+                continue;
+            pCubeNew = Min_CubesXor( p, pCube, pCube2 );
+            assert( pCubeNew->nLits == pCube->nLits - 1 );
+            pCubeNew->pNext = p->ppStore[pCubeNew->nLits];
+            p->ppStore[pCubeNew->nLits] = pCubeNew;
+            p->nCubes++;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Min_Cube_t * Min_SopComplement( Min_Man_t * p, Min_Cube_t * pSharp )
+{
+     Vec_Int_t * vVars;
+     Min_Cube_t * pCover, * pCube, * pNext, * pReady, * pThis, ** ppPrev;
+     int Num, Value, i;
+
+     // get the variables
+     vVars = Vec_IntAlloc( 100 );
+    // create the tautology cube
+     pCover = Min_CubeAlloc( p );
+     // sharp it with all cubes
+     Min_CoverForEachCube( pSharp, pCube )
+     Min_CoverForEachCubePrev( pCover, pThis, ppPrev )
+     {
+        if ( Min_CubesDisjoint( pThis, pCube ) )
+            continue;
+        // remember the next pointer
+        pNext = pThis->pNext;
+        // get the variables, in which pThis is '-' while pCube is fixed
+        Min_CoverGetDisjVars( pThis, pCube, vVars );
+        // generate the disjoint cubes
+        pReady = pThis;
+        Vec_IntForEachEntryReverse( vVars, Num, i )
+        {
+            // correct the literal
+            Min_CubeXorVar( pReady, vVars->pArray[i], 3 );
+            if ( i == 0 )
+                break;
+            // create the new cube and clean this value
+            Value = Min_CubeGetVar( pReady, vVars->pArray[i] );
+            pReady = Min_CubeDup( p, pReady );
+            Min_CubeXorVar( pReady, vVars->pArray[i], 3 ^ Value );
+            // add to the cover
+            *ppPrev = pReady;
+            ppPrev = &pReady->pNext;
+        }
+        pThis = pReady;
+        pThis->pNext = pNext;
+     }
+     Vec_IntFree( vVars );
+
+     // perform dist-1 merge and contain
+     Min_CoverExpandRemoveEqual( p, pCover );
+     Min_SopDist1Merge( p );
+     Min_SopContain( p );
+     return Min_CoverCollect( p, p->nVars );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Min_SopCheck( Min_Man_t * p )
+{
+    Min_Cube_t * pCube, * pThis;
+    int i;
+
+    pCube = Min_CubeAlloc( p );
+    Min_CubeXorBit( pCube, 2*0+1 );
+    Min_CubeXorBit( pCube, 2*1+1 );
+    Min_CubeXorBit( pCube, 2*2+0 );
+    Min_CubeXorBit( pCube, 2*3+0 );
+    Min_CubeXorBit( pCube, 2*4+0 );
+    Min_CubeXorBit( pCube, 2*5+1 );
+    Min_CubeXorBit( pCube, 2*6+1 );
+    pCube->nLits = 7;
+
+//    Min_CubeWrite( stdout, pCube );
+
+    // check that the cubes contain it
+    for ( i = 0; i <= p->nVars; i++ )
+        Min_CoverForEachCube( p->ppStore[i], pThis )
+            if ( pThis != p->pBubble && Min_CubeIsContained( pThis, pCube ) )
+            {
+                Min_CubeRecycle( p, pCube );
+                return 1;
+            }
+    Min_CubeRecycle( p, pCube );
+    return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/cov/covMinUtil.c b/abc-build/src/map/cov/covMinUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/cov/covMinUtil.c
@@ -0,0 +1,343 @@
+/**CFile****************************************************************
+
+  FileName    [covMinUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Mapping into network of SOPs/ESOPs.]
+
+  Synopsis    [Utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: covMinUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "covInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_CubeCreate( Vec_Str_t * vCover, Min_Cube_t * pCube, char Type )
+{
+    int i;
+    assert( (int)pCube->nLits == Min_CubeCountLits(pCube) );
+    for ( i = 0; i < (int)pCube->nVars; i++ )
+        if ( Min_CubeHasBit(pCube, i*2) )
+        {
+            if ( Min_CubeHasBit(pCube, i*2+1) )
+//                fprintf( pFile, "-" );
+                Vec_StrPush( vCover, '-' );
+            else
+//                fprintf( pFile, "0" );
+                Vec_StrPush( vCover, '0' );
+        }
+        else
+        {
+            if ( Min_CubeHasBit(pCube, i*2+1) )
+ //               fprintf( pFile, "1" );
+                Vec_StrPush( vCover, '1' );
+            else
+//                fprintf( pFile, "?" );
+                Vec_StrPush( vCover, '?' );
+        }
+//    fprintf( pFile, " 1\n" );
+    Vec_StrPush( vCover, ' ' );
+    Vec_StrPush( vCover, Type );
+    Vec_StrPush( vCover, '\n' );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_CoverCreate( Vec_Str_t * vCover, Min_Cube_t * pCover, char Type )
+{
+    Min_Cube_t * pCube;
+    assert( pCover != NULL );
+    Vec_StrClear( vCover );
+    Min_CoverForEachCube( pCover, pCube )
+        Min_CubeCreate( vCover, pCube, Type );
+    Vec_StrPush( vCover, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_CubeWrite( FILE * pFile, Min_Cube_t * pCube )
+{
+    int i;
+    assert( (int)pCube->nLits == Min_CubeCountLits(pCube) );
+    for ( i = 0; i < (int)pCube->nVars; i++ )
+        if ( Min_CubeHasBit(pCube, i*2) )
+        {
+            if ( Min_CubeHasBit(pCube, i*2+1) )
+                fprintf( pFile, "-" );
+            else
+                fprintf( pFile, "0" );
+        }
+        else
+        {
+            if ( Min_CubeHasBit(pCube, i*2+1) )
+                fprintf( pFile, "1" );
+            else
+                fprintf( pFile, "?" );
+        }
+    fprintf( pFile, " 1\n" );
+//    fprintf( pFile, " %d\n", pCube->nLits );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_CoverWrite( FILE * pFile, Min_Cube_t * pCover )
+{
+    Min_Cube_t * pCube;
+    Min_CoverForEachCube( pCover, pCube )
+        Min_CubeWrite( pFile, pCube );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_CoverWriteStore( FILE * pFile, Min_Man_t * p )
+{
+    Min_Cube_t * pCube;
+    int i;
+    for ( i = 0; i <= p->nVars; i++ )
+    {
+        Min_CoverForEachCube( p->ppStore[i], pCube )
+        {
+            printf( "%2d : ", i );
+            if ( pCube == p->pBubble )
+            {
+                printf( "Bubble\n" );
+                continue;
+            }
+            Min_CubeWrite( pFile, pCube );
+        }
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_CoverWriteFile( Min_Cube_t * pCover, char * pName, int fEsop )
+{
+    char Buffer[1000];
+    Min_Cube_t * pCube;
+    FILE * pFile;
+    int i;
+    sprintf( Buffer, "%s.%s", pName, fEsop? "esop" : "pla" );
+    for ( i = strlen(Buffer) - 1; i >= 0; i-- )
+        if ( Buffer[i] == '<' || Buffer[i] == '>' )
+            Buffer[i] = '_';
+    pFile = fopen( Buffer, "w" );
+    fprintf( pFile, "# %s cover for output %s generated by ABC on %s\n", fEsop? "ESOP":"SOP", pName, Extra_TimeStamp() );
+    fprintf( pFile, ".i %d\n", pCover? pCover->nVars : 0 );
+    fprintf( pFile, ".o %d\n", 1 );
+    fprintf( pFile, ".p %d\n", Min_CoverCountCubes(pCover) );
+    if ( fEsop ) fprintf( pFile, ".type esop\n" );
+    Min_CoverForEachCube( pCover, pCube )
+        Min_CubeWrite( pFile, pCube );
+    fprintf( pFile, ".e\n" );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_CoverCheck( Min_Man_t * p )
+{
+    Min_Cube_t * pCube;
+    int i;
+    for ( i = 0; i <= p->nVars; i++ )
+        Min_CoverForEachCube( p->ppStore[i], pCube )
+            assert( i == (int)pCube->nLits );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Min_CubeCheck( Min_Cube_t * pCube )
+{
+    int i;
+    for ( i = 0; i < (int)pCube->nVars; i++ )
+        if ( Min_CubeGetVar( pCube, i ) == 0 )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the cover from the sorted structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Min_Cube_t * Min_CoverCollect( Min_Man_t * p, int nSuppSize )
+{
+    Min_Cube_t * pCov = NULL, ** ppTail = &pCov;
+    Min_Cube_t * pCube, * pCube2;
+    int i;
+    for ( i = 0; i <= nSuppSize; i++ )
+    {
+        Min_CoverForEachCubeSafe( p->ppStore[i], pCube, pCube2 )
+        {
+            assert( i == (int)pCube->nLits );
+            *ppTail = pCube; 
+            ppTail = &pCube->pNext;
+            assert( pCube->uData[0] ); // not a bubble
+        }
+    }
+    *ppTail = NULL;
+    return pCov;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts the cover in the increasing number of literals.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Min_CoverExpand( Min_Man_t * p, Min_Cube_t * pCover )
+{
+    Min_Cube_t * pCube, * pCube2;
+    Min_ManClean( p, p->nVars );
+    Min_CoverForEachCubeSafe( pCover, pCube, pCube2 )
+    {
+        pCube->pNext = p->ppStore[pCube->nLits];
+        p->ppStore[pCube->nLits] = pCube;
+        p->nCubes++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts the cover in the increasing number of literals.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Min_CoverSuppVarNum( Min_Man_t * p, Min_Cube_t * pCover )
+{
+    Min_Cube_t * pCube;
+    int i, Counter;
+    if ( pCover == NULL )
+        return 0;
+    // clean the cube
+    for ( i = 0; i < (int)pCover->nWords; i++ )
+        p->pTemp->uData[i]  = ~((unsigned)0);
+    // add the bit data
+    Min_CoverForEachCube( pCover, pCube )
+        for ( i = 0; i < (int)pCover->nWords; i++ )
+            p->pTemp->uData[i] &= pCube->uData[i];
+    // count the vars
+    Counter = 0;
+    for ( i = 0; i < (int)pCover->nVars; i++ )
+        Counter += ( Min_CubeGetVar(p->pTemp, i) != 3 );
+    return Counter;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/cov/covTest.c b/abc-build/src/map/cov/covTest.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/cov/covTest.c
@@ -0,0 +1,422 @@
+/**CFile****************************************************************
+
+  FileName    [covTest.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+ 
+  PackageName [Mapping into network of SOPs/ESOPs.]
+
+  Synopsis    [Testing procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: covTest.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cov.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Min_Cube_t * Abc_NodeDeriveCoverPro( Min_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1 )
+{
+    Min_Cube_t * pCover;
+    Min_Cube_t * pCube0, * pCube1, * pCube;
+    if ( pCover0 == NULL || pCover1 == NULL )
+        return NULL;
+    // clean storage
+    Min_ManClean( p, p->nVars );
+    // go through the cube pairs
+    Min_CoverForEachCube( pCover0, pCube0 )
+    Min_CoverForEachCube( pCover1, pCube1 )
+    {
+        if ( Min_CubesDisjoint( pCube0, pCube1 ) )
+            continue;
+        pCube = Min_CubesProduct( p, pCube0, pCube1 );
+        // add the cube to storage
+        Min_SopAddCube( p, pCube );
+    }
+    Min_SopMinimize( p );
+    pCover = Min_CoverCollect( p, p->nVars );
+    assert( p->nCubes == Min_CoverCountCubes(pCover) );
+    return pCover;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Min_Cube_t * Abc_NodeDeriveCoverSum( Min_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1 )
+{
+    Min_Cube_t * pCover;
+    Min_Cube_t * pThis, * pCube;
+    if ( pCover0 == NULL || pCover1 == NULL )
+        return NULL;
+    // clean storage
+    Min_ManClean( p, p->nVars );
+    // add the cubes to storage
+    Min_CoverForEachCube( pCover0, pThis )
+    {
+        pCube = Min_CubeDup( p, pThis );
+        Min_SopAddCube( p, pCube );
+    }
+    Min_CoverForEachCube( pCover1, pThis )
+    {
+        pCube = Min_CubeDup( p, pThis );
+        Min_SopAddCube( p, pCube );
+    }
+    Min_SopMinimize( p );
+    pCover = Min_CoverCollect( p, p->nVars );
+    assert( p->nCubes == Min_CoverCountCubes(pCover) );
+    return pCover;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeDeriveSops( Min_Man_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vSupp, Vec_Ptr_t * vNodes )
+{
+    Min_Cube_t * pCov0[2], * pCov1[2];
+    Min_Cube_t * pCoverP, * pCoverN;
+    Abc_Obj_t * pObj;
+    int i, nCubes, fCompl0, fCompl1;
+
+    // set elementary vars
+    Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i )
+    {
+        pObj->pCopy = (Abc_Obj_t *)Min_CubeAllocVar( p, i, 0 );
+        pObj->pNext = (Abc_Obj_t *)Min_CubeAllocVar( p, i, 1 );
+    }
+
+    // get the cover for each node in the array
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        // get the complements
+        fCompl0 = Abc_ObjFaninC0(pObj);
+        fCompl1 = Abc_ObjFaninC1(pObj);
+        // get the covers
+        pCov0[0] = (Min_Cube_t *)Abc_ObjFanin0(pObj)->pCopy;
+        pCov0[1] = (Min_Cube_t *)Abc_ObjFanin0(pObj)->pNext;
+        pCov1[0] = (Min_Cube_t *)Abc_ObjFanin1(pObj)->pCopy;
+        pCov1[1] = (Min_Cube_t *)Abc_ObjFanin1(pObj)->pNext;
+        // compute the covers
+        pCoverP = Abc_NodeDeriveCoverPro( p, pCov0[ fCompl0], pCov1[ fCompl1] );
+        pCoverN = Abc_NodeDeriveCoverSum( p, pCov0[!fCompl0], pCov1[!fCompl1] );
+        // set the covers
+        pObj->pCopy = (Abc_Obj_t *)pCoverP;
+        pObj->pNext = (Abc_Obj_t *)pCoverN;
+    }
+
+     nCubes = ABC_MIN( Min_CoverCountCubes(pCoverN), Min_CoverCountCubes(pCoverP) );
+
+/*
+printf( "\n\n" );
+Min_CoverWrite( stdout, pCoverP );
+printf( "\n\n" );
+Min_CoverWrite( stdout, pCoverN );
+*/
+
+//    printf( "\n" );
+//    Min_CoverWrite( stdout, pCoverP );
+
+//    Min_CoverExpand( p, pCoverP );
+//    Min_SopMinimize( p );
+//    pCoverP = Min_CoverCollect( p, p->nVars );
+
+//    printf( "\n" );
+//    Min_CoverWrite( stdout, pCoverP );
+
+//    nCubes = Min_CoverCountCubes(pCoverP);
+
+    // clean the copy fields
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        pObj->pCopy = pObj->pNext = NULL;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i )
+        pObj->pCopy = pObj->pNext = NULL;
+
+//    Min_CoverWriteFile( pCoverP, Abc_ObjName(pRoot), 0 );
+//    printf( "\n" );
+//    Min_CoverWrite( stdout, pCoverP );
+
+//    printf( "\n" );
+//    Min_CoverWrite( stdout, pCoverP );
+//    printf( "\n" );
+//    Min_CoverWrite( stdout, pCoverN );
+    return nCubes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTestSop( Abc_Ntk_t * pNtk )
+{
+    Min_Man_t * p;
+    Vec_Ptr_t * vSupp, * vNodes;
+    Abc_Obj_t * pObj;
+    int i, nCubes;
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    Abc_NtkCleanCopy(pNtk);
+    Abc_NtkCleanNext(pNtk);
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        if ( !Abc_ObjIsNode(Abc_ObjFanin0(pObj)) )
+        {
+            printf( "%-20s :  Trivial.\n", Abc_ObjName(pObj) );
+            continue;
+        }
+
+        vSupp  = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
+        vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 );
+
+        printf( "%20s :  Cone = %5d.  Supp = %5d.  ", 
+            Abc_ObjName(pObj), vNodes->nSize, vSupp->nSize );
+//        if ( vSupp->nSize <= 128 )
+        {
+            p = Min_ManAlloc( vSupp->nSize );
+            nCubes = Abc_NodeDeriveSops( p, pObj, vSupp, vNodes );
+            printf( "Cubes = %5d.  ", nCubes );
+            Min_ManFree( p );
+        }
+        printf( "\n" );
+
+
+        Vec_PtrFree( vNodes );
+        Vec_PtrFree( vSupp );
+    }
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Min_Cube_t * Abc_NodeDeriveCover( Min_Man_t * p, Min_Cube_t * pCov0, Min_Cube_t * pCov1, int fComp0, int fComp1 )
+{
+    Min_Cube_t * pCover0, * pCover1, * pCover;
+    Min_Cube_t * pCube0, * pCube1, * pCube;
+
+    // complement the first if needed
+    if ( !fComp0 )
+        pCover0 = pCov0;
+    else if ( pCov0 && pCov0->nLits == 0 ) // topmost one is the tautology cube
+        pCover0 = pCov0->pNext;
+    else
+        pCover0 = p->pOne0, p->pOne0->pNext = pCov0;
+
+    // complement the second if needed
+    if ( !fComp1 )
+        pCover1 = pCov1;
+    else if ( pCov1 && pCov1->nLits == 0 ) // topmost one is the tautology cube
+        pCover1 = pCov1->pNext;
+    else
+        pCover1 = p->pOne1, p->pOne1->pNext = pCov1;
+
+    if ( pCover0 == NULL || pCover1 == NULL )
+        return NULL;
+
+    // clean storage
+    Min_ManClean( p, p->nVars );
+    // go through the cube pairs
+    Min_CoverForEachCube( pCover0, pCube0 )
+    Min_CoverForEachCube( pCover1, pCube1 )
+    {
+        if ( Min_CubesDisjoint( pCube0, pCube1 ) )
+            continue;
+        pCube = Min_CubesProduct( p, pCube0, pCube1 );
+        // add the cube to storage
+        Min_EsopAddCube( p, pCube );
+    }
+ 
+    if ( p->nCubes > 10 )
+    {
+//        printf( "(%d,", p->nCubes );
+        Min_EsopMinimize( p );
+//        printf( "%d) ", p->nCubes );
+    }
+
+    pCover = Min_CoverCollect( p, p->nVars );
+    assert( p->nCubes == Min_CoverCountCubes(pCover) );
+
+//    if ( p->nCubes > 1000 )
+//        printf( "%d ", p->nCubes );
+    return pCover;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeDeriveEsops( Min_Man_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vSupp, Vec_Ptr_t * vNodes )
+{
+    Min_Cube_t * pCover, * pCube;
+    Abc_Obj_t * pObj;
+    int i;
+
+    // set elementary vars
+    Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)Min_CubeAllocVar( p, i, 0 );
+
+    // get the cover for each node in the array
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        pCover = Abc_NodeDeriveCover( p,  
+            (Min_Cube_t *)Abc_ObjFanin0(pObj)->pCopy,  
+            (Min_Cube_t *)Abc_ObjFanin1(pObj)->pCopy,
+            Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+        pObj->pCopy = (Abc_Obj_t *)pCover;
+        if ( p->nCubes > 3000 )
+            return -1;
+    }
+
+    // add complement if needed
+    if ( Abc_ObjFaninC0(pRoot) )
+    {
+        if ( pCover && pCover->nLits == 0 ) // topmost one is the tautology cube
+        {
+            pCube = pCover;
+            pCover = pCover->pNext;
+            Min_CubeRecycle( p, pCube );
+            p->nCubes--;
+        }
+        else
+        {
+            pCube = Min_CubeAlloc( p );
+            pCube->pNext = pCover;
+            p->nCubes++;
+        }
+    }
+/*
+    Min_CoverExpand( p, pCover );
+    Min_EsopMinimize( p );
+    pCover = Min_CoverCollect( p, p->nVars );
+*/
+    // clean the copy fields
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        pObj->pCopy = NULL;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i )
+        pObj->pCopy = NULL;
+
+//    Min_CoverWriteFile( pCover, Abc_ObjName(pRoot), 1 );
+//    Min_CoverWrite( stdout, pCover );
+    return p->nCubes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkTestEsop( Abc_Ntk_t * pNtk )
+{
+    Min_Man_t * p;
+    Vec_Ptr_t * vSupp, * vNodes;
+    Abc_Obj_t * pObj;
+    int i, nCubes;
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    Abc_NtkCleanCopy(pNtk);
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        if ( !Abc_ObjIsNode(Abc_ObjFanin0(pObj)) )
+        {
+            printf( "%-20s :  Trivial.\n", Abc_ObjName(pObj) );
+            continue;
+        }
+
+        vSupp  = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
+        vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 );
+
+        printf( "%20s :  Cone = %5d.  Supp = %5d.  ", 
+            Abc_ObjName(pObj), vNodes->nSize, vSupp->nSize );
+//        if ( vSupp->nSize <= 128 )
+        {
+            p = Min_ManAlloc( vSupp->nSize );
+            nCubes = Abc_NodeDeriveEsops( p, pObj, vSupp, vNodes );
+            printf( "Cubes = %5d.  ", nCubes );
+            Min_ManFree( p );
+        }
+        printf( "\n" );
+
+
+        Vec_PtrFree( vNodes );
+        Vec_PtrFree( vSupp );
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/cov/module.make b/abc-build/src/map/cov/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/cov/module.make
@@ -0,0 +1,7 @@
+SRC +=	src/map/cov/covBuild.c \
+	src/map/cov/covCore.c \
+	src/map/cov/covMan.c \
+	src/map/cov/covMinEsop.c \
+	src/map/cov/covMinMan.c \
+	src/map/cov/covMinSop.c \
+	src/map/cov/covMinUtil.c
diff --git a/abc-build/src/map/fpga/fpga.c b/abc-build/src/map/fpga/fpga.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/fpga/fpga.c
@@ -0,0 +1,288 @@
+/**CFile****************************************************************
+
+  FileName    [fpga.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Command file for the FPGA package.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - August 18, 2004.]
+
+  Revision    [$Id: fpga.c,v 1.4 2004/10/28 17:36:07 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv );
+static int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv );
+
+// the library file format should be as follows:
+/*
+# The area/delay of k-variable LUTs:
+# k  area   delay
+1      1      1
+2      2      2
+3      4      3
+4      8      4
+5     16      5
+6     32      6
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Package initialization procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_Init( Abc_Frame_t * pAbc )
+{
+    // set the default library
+    //Fpga_LutLib_t s_LutLib = { "lutlib", 6, 0, {0,1,2,4,8,16,32}, {{0},{1},{2},{3},{4},{5},{6}} };
+//    Fpga_LutLib_t s_LutLib = { "lutlib", 5, 0, {0,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1}} };
+    Fpga_LutLib_t s_LutLib = { "lutlib", 4, 0, {0,1,1,1,1}, {{0},{1},{1},{1},{1}} };
+    //Fpga_LutLib_t s_LutLib = { "lutlib", 3, 0, {0,1,1,1}, {{0},{1},{1},{1}} };
+
+    Abc_FrameSetLibLut( Fpga_LutLibDup(&s_LutLib) );
+
+    Cmd_CommandAdd( pAbc, "FPGA mapping", "read_lut",   Fpga_CommandReadLibrary,   0 ); 
+    Cmd_CommandAdd( pAbc, "FPGA mapping", "print_lut",  Fpga_CommandPrintLibrary,  0 ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Package ending procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_End( Abc_Frame_t * pAbc )
+{
+    Fpga_LutLibFree( (Fpga_LutLib_t *)Abc_FrameReadLibLut() );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Command procedure to read LUT libraries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    FILE * pFile;
+    FILE * pOut, * pErr;
+    Fpga_LutLib_t * pLib;
+    Abc_Ntk_t * pNet;
+    char * FileName;
+    int fVerbose;
+    int c;
+
+    pNet = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    // set the defaults
+    fVerbose = 1;
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) 
+    {
+        switch (c) 
+        {
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+                break;
+            default:
+                goto usage;
+        }
+    }
+
+
+    if ( argc != globalUtilOptind + 1 )
+    {
+        goto usage;
+    }
+
+    // get the input file name
+    FileName = argv[globalUtilOptind];
+    if ( (pFile = fopen( FileName, "r" )) == NULL )
+    {
+        fprintf( pErr, "Cannot open input file \"%s\". ", FileName );
+        if ( (FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL )) )
+            fprintf( pErr, "Did you mean \"%s\"?", FileName );
+        fprintf( pErr, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+
+    // set the new network
+    pLib = Fpga_LutLibRead( FileName, fVerbose );
+    if ( pLib == NULL )
+    {
+        fprintf( pErr, "Reading LUT library has failed.\n" );
+        goto usage;
+    }
+    // replace the current library
+    Fpga_LutLibFree( (Fpga_LutLib_t *)Abc_FrameReadLibLut() );
+    Abc_FrameSetLibLut( pLib );
+    return 0;
+
+usage:
+    fprintf( pErr, "usage: read_lut [-vh]\n");
+    fprintf( pErr, "\t          read the LUT library from the file\n" );  
+    fprintf( pErr, "\t-v      : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") );
+    fprintf( pErr, "\t-h      : print the command usage\n");
+    fprintf( pErr, "\t                                        \n");
+    fprintf( pErr, "\t          File format for a LUT library:\n");
+    fprintf( pErr, "\t          (the default library is shown)\n");
+    fprintf( pErr, "\t                                        \n");
+    fprintf( pErr, "\t          # The area/delay of k-variable LUTs:\n");
+    fprintf( pErr, "\t          # k  area   delay\n");
+    fprintf( pErr, "\t          1      1      1\n");
+    fprintf( pErr, "\t          2      2      2\n");
+    fprintf( pErr, "\t          3      4      3\n");
+    fprintf( pErr, "\t          4      8      4\n");
+    fprintf( pErr, "\t          5     16      5\n");
+    fprintf( pErr, "\t          6     32      6\n");
+    return 1;       /* error exit */
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Command procedure to read LUT libraries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    FILE * pOut, * pErr;
+    Abc_Ntk_t * pNet;
+    int fVerbose;
+    int c;
+
+    pNet = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    // set the defaults
+    fVerbose = 1;
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) 
+    {
+        switch (c) 
+        {
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+                break;
+            default:
+                goto usage;
+        }
+    }
+
+
+    if ( argc != globalUtilOptind )
+    {
+        goto usage;
+    }
+
+    // set the new network
+    Fpga_LutLibPrint( (Fpga_LutLib_t *)Abc_FrameReadLibLut() );
+    return 0;
+
+usage:
+    fprintf( pErr, "usage: print_lut [-vh]\n");
+    fprintf( pErr, "\t          print the current LUT library\n" );  
+    fprintf( pErr, "\t-v      : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") );
+    fprintf( pErr, "\t-h      : print the command usage\n");
+    return 1;       /* error exit */
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets simple LUT library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_SetSimpleLutLib( int nLutSize )
+{
+    Fpga_LutLib_t s_LutLib10= { "lutlib",10, 0, {0,1,1,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1},{1},{1}} };
+    Fpga_LutLib_t s_LutLib9 = { "lutlib", 9, 0, {0,1,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1},{1}} };
+    Fpga_LutLib_t s_LutLib8 = { "lutlib", 8, 0, {0,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1}} };
+    Fpga_LutLib_t s_LutLib7 = { "lutlib", 7, 0, {0,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1}} };
+    Fpga_LutLib_t s_LutLib6 = { "lutlib", 6, 0, {0,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1}} };
+    Fpga_LutLib_t s_LutLib5 = { "lutlib", 5, 0, {0,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1}} };
+    Fpga_LutLib_t s_LutLib4 = { "lutlib", 4, 0, {0,1,1,1,1}, {{0},{1},{1},{1},{1}} };
+    Fpga_LutLib_t s_LutLib3 = { "lutlib", 3, 0, {0,1,1,1}, {{0},{1},{1},{1}} };
+    Fpga_LutLib_t * pLutLib;
+    assert( nLutSize >= 3 && nLutSize <= 10 );
+    switch ( nLutSize )
+    {
+        case 3:  pLutLib = &s_LutLib3; break;
+        case 4:  pLutLib = &s_LutLib4; break;
+        case 5:  pLutLib = &s_LutLib5; break;
+        case 6:  pLutLib = &s_LutLib6; break;
+        case 7:  pLutLib = &s_LutLib7; break;
+        case 8:  pLutLib = &s_LutLib8; break;
+        case 9:  pLutLib = &s_LutLib9; break;
+        case 10: pLutLib = &s_LutLib10; break;
+        default: pLutLib = NULL; break;
+    }
+    if ( pLutLib == NULL )
+        return;
+    Fpga_LutLibFree( (Fpga_LutLib_t *)Abc_FrameReadLibLut() );
+    Abc_FrameSetLibLut( Fpga_LutLibDup(pLutLib) );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/fpga/fpga.h b/abc-build/src/map/fpga/fpga.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/fpga/fpga.h
@@ -0,0 +1,175 @@
+/**CFile****************************************************************
+
+  FileName    [fpga.h]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Technology mapping for variable-size-LUT FPGAs.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - August 18, 2004.]
+
+  Revision    [$Id: fpga.h,v 1.7 2004/09/30 21:18:09 satrajit Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__map__fpga__fpga_h
+#define ABC__map__fpga__fpga_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+// the maximum size of LUTs used for mapping
+#define FPGA_MAX_LUTSIZE   32
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Fpga_ManStruct_t_         Fpga_Man_t;
+typedef struct Fpga_NodeStruct_t_        Fpga_Node_t;
+typedef struct Fpga_NodeVecStruct_t_     Fpga_NodeVec_t;
+typedef struct Fpga_CutStruct_t_         Fpga_Cut_t;
+typedef struct Fpga_LutLibStruct_t_      Fpga_LutLib_t;
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+ 
+#define Fpga_IsComplement(p)    (((int)((ABC_PTRUINT_T) (p) & 01)))
+#define Fpga_Regular(p)         ((Fpga_Node_t *)((ABC_PTRUINT_T)(p) & ~01)) 
+#define Fpga_Not(p)             ((Fpga_Node_t *)((ABC_PTRUINT_T)(p) ^ 01)) 
+#define Fpga_NotCond(p,c)       ((Fpga_Node_t *)((ABC_PTRUINT_T)(p) ^ (c)))
+
+#define Fpga_Ref(p)   
+#define Fpga_Deref(p)
+#define Fpga_RecursiveDeref(p,c)
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== fpgaCreate.c =============================================================*/
+extern Fpga_Man_t *    Fpga_ManCreate( int nInputs, int nOutputs, int fVerbose );
+extern Fpga_Node_t *   Fpga_NodeCreate( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 );
+extern void            Fpga_ManFree( Fpga_Man_t * pMan );
+extern void            Fpga_ManPrintTimeStats( Fpga_Man_t * p );
+
+extern int             Fpga_ManReadInputNum( Fpga_Man_t * p );
+extern int             Fpga_ManReadOutputNum( Fpga_Man_t * p );
+extern Fpga_Node_t **  Fpga_ManReadInputs ( Fpga_Man_t * p );
+extern Fpga_Node_t **  Fpga_ManReadOutputs( Fpga_Man_t * p );
+extern Fpga_Node_t *   Fpga_ManReadConst1 ( Fpga_Man_t * p );
+extern float *         Fpga_ManReadInputArrivals( Fpga_Man_t * p );
+extern int             Fpga_ManReadVerbose( Fpga_Man_t * p );
+extern int             Fpga_ManReadVarMax( Fpga_Man_t * p );
+extern float *         Fpga_ManReadLutAreas( Fpga_Man_t * p );
+extern Fpga_NodeVec_t* Fpga_ManReadMapping( Fpga_Man_t * p );
+extern void            Fpga_ManSetOutputNames( Fpga_Man_t * p, char ** ppNames );
+extern void            Fpga_ManSetInputArrivals( Fpga_Man_t * p, float * pArrivals );
+extern void            Fpga_ManSetAreaRecovery( Fpga_Man_t * p, int fAreaRecovery );
+extern void            Fpga_ManSetDelayLimit( Fpga_Man_t * p, float DelayLimit );
+extern void            Fpga_ManSetAreaLimit( Fpga_Man_t * p, float AreaLimit );
+extern void            Fpga_ManSetObeyFanoutLimits( Fpga_Man_t * p, int fObeyFanoutLimits );              
+extern void            Fpga_ManSetNumIterations( Fpga_Man_t * p, int nNumIterations );
+extern int             Fpga_ManReadFanoutViolations( Fpga_Man_t * p );
+extern void            Fpga_ManSetFanoutViolations( Fpga_Man_t * p, int nVio );
+extern void            Fpga_ManSetChoiceNodeNum( Fpga_Man_t * p, int nChoiceNodes );
+extern void            Fpga_ManSetChoiceNum( Fpga_Man_t * p, int nChoices );
+extern void            Fpga_ManSetVerbose( Fpga_Man_t * p, int fVerbose );
+extern void            Fpga_ManSetSwitching( Fpga_Man_t * p, int fSwitching );
+extern void            Fpga_ManSetLatchPaths( Fpga_Man_t * p, int fLatchPaths );
+extern void            Fpga_ManSetLatchNum( Fpga_Man_t * p, int nLatches );
+extern void            Fpga_ManSetDelayTarget( Fpga_Man_t * p, float DelayTarget );
+extern void            Fpga_ManSetName( Fpga_Man_t * p, char * pFileName );
+
+extern int             Fpga_LibReadLutMax( Fpga_LutLib_t * pLib );
+
+extern char *          Fpga_NodeReadData0( Fpga_Node_t * p );
+extern Fpga_Node_t *   Fpga_NodeReadData1( Fpga_Node_t * p );
+extern int             Fpga_NodeReadRefs( Fpga_Node_t * p );
+extern int             Fpga_NodeReadNum( Fpga_Node_t * p );
+extern int             Fpga_NodeReadLevel( Fpga_Node_t * p );
+extern Fpga_Cut_t *    Fpga_NodeReadCuts( Fpga_Node_t * p );
+extern Fpga_Cut_t *    Fpga_NodeReadCutBest( Fpga_Node_t * p );
+extern Fpga_Node_t *   Fpga_NodeReadOne( Fpga_Node_t * p );
+extern Fpga_Node_t *   Fpga_NodeReadTwo( Fpga_Node_t * p );
+extern void            Fpga_NodeSetLevel( Fpga_Node_t * p, Fpga_Node_t * pNode );
+extern void            Fpga_NodeSetData0( Fpga_Node_t * p, char * pData );
+extern void            Fpga_NodeSetData1( Fpga_Node_t * p, Fpga_Node_t * pNode );
+extern void            Fpga_NodeSetArrival( Fpga_Node_t * p, float Time );
+extern void            Fpga_NodeSetNextE( Fpga_Node_t * p, Fpga_Node_t * pNextE );
+extern void            Fpga_NodeSetRepr( Fpga_Node_t * p, Fpga_Node_t * pRepr );
+extern void            Fpga_NodeSetSwitching( Fpga_Node_t * p, float Switching );
+
+extern int             Fpga_NodeIsConst( Fpga_Node_t * p );
+extern int             Fpga_NodeIsVar( Fpga_Node_t * p );
+extern int             Fpga_NodeIsAnd( Fpga_Node_t * p );
+extern int             Fpga_NodeComparePhase( Fpga_Node_t * p1, Fpga_Node_t * p2 );
+
+extern int             Fpga_CutReadLeavesNum( Fpga_Cut_t * p );
+extern Fpga_Node_t **  Fpga_CutReadLeaves( Fpga_Cut_t * p );
+
+extern Fpga_Node_t *   Fpga_NodeAnd( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 );
+extern Fpga_Node_t *   Fpga_NodeOr( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 );
+extern Fpga_Node_t *   Fpga_NodeExor( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 );
+extern Fpga_Node_t *   Fpga_NodeMux( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Node_t * pNodeT, Fpga_Node_t * pNodeE );
+extern void            Fpga_NodeSetChoice( Fpga_Man_t * pMan, Fpga_Node_t * pNodeOld, Fpga_Node_t * pNodeNew );
+
+extern void            Fpga_ManStats( Fpga_Man_t * p );
+
+/*=== fpgaCore.c =============================================================*/
+extern int             Fpga_Mapping( Fpga_Man_t * p );
+/*=== fpgaCut.c ===============================================================*/
+extern void            Fpga_MappingCreatePiCuts( Fpga_Man_t * p );
+extern void            Fpga_CutsCleanSign( Fpga_Man_t * pMan );
+extern void            Fpga_CutsCleanRoot( Fpga_Man_t * pMan );
+/*=== fpgaCutUtils.c =============================================================*/
+extern void            Fpga_CutCreateFromNode( Fpga_Man_t * p, int iRoot, int * pLeaves, int nLeaves );
+extern void            Fpga_MappingSetUsedCuts( Fpga_Man_t * p );
+/*=== fpgaLib.c =============================================================*/
+extern Fpga_LutLib_t * Fpga_LutLibDup( Fpga_LutLib_t * p );
+extern int             Fpga_LutLibReadVarMax( Fpga_LutLib_t * p );
+extern float *         Fpga_LutLibReadLutAreas( Fpga_LutLib_t * p );
+extern float *         Fpga_LutLibReadLutDelays( Fpga_LutLib_t * p );
+extern float           Fpga_LutLibReadLutArea( Fpga_LutLib_t * p, int Size );
+extern float           Fpga_LutLibReadLutDelay( Fpga_LutLib_t * p, int Size );
+/*=== fpgaTruth.c =============================================================*/
+extern void *          Fpga_TruthsCutBdd( void * dd, Fpga_Cut_t * pCut );
+extern int             Fpga_CutVolume( Fpga_Cut_t * pCut );
+/*=== fpgaUtil.c =============================================================*/
+extern int             Fpga_ManCheckConsistency( Fpga_Man_t * p );
+extern void            Fpga_ManCleanData0( Fpga_Man_t * pMan );
+extern Fpga_NodeVec_t * Fpga_CollectNodeTfo( Fpga_Man_t * pMan, Fpga_Node_t * pNode );
+/*=== fpga.c =============================================================*/
+extern void            Fpga_SetSimpleLutLib( int nLutSize );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/map/fpga/fpgaCore.c b/abc-build/src/map/fpga/fpgaCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/fpga/fpgaCore.c
@@ -0,0 +1,194 @@
+/**CFile****************************************************************
+
+  FileName    [fpgaCore.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Technology mapping for variable-size-LUT FPGAs.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - August 18, 2004.]
+
+  Revision    [$Id: fpgaCore.c,v 1.7 2004/10/01 23:41:04 satrajit Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int  Fpga_MappingPostProcess( Fpga_Man_t * p );
+
+extern clock_t s_MappingTime;
+extern int s_MappingMem;
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs technology mapping for the given object graph.]
+
+  Description [The object graph is stored in the mapping manager.
+  First, all the AND-nodes, which fanout into the POs, are collected
+  in the DFS fashion. Next, three steps are performed: the k-feasible
+  cuts are computed for each node, the truth tables are computed for
+  each cut, and the delay-optimal matches are assigned for each node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_Mapping( Fpga_Man_t * p )
+{
+    clock_t clk, clkTotal = clock();
+ 
+    // collect the nodes reachable from POs in the DFS order (including the choices)
+    p->vAnds = Fpga_MappingDfs( p, 1 );
+    Fpga_ManReportChoices( p ); // recomputes levels
+    Fpga_MappingSetChoiceLevels( p );
+
+    // compute the cuts of nodes in the DFS order
+    clk = clock();
+    Fpga_MappingCuts( p );
+    p->timeCuts = clock() - clk;
+
+    // match the truth tables to the supergates
+    clk = clock();
+    if ( !Fpga_MappingMatches( p, 1 ) )
+        return 0;
+    p->timeMatch = clock() - clk;
+
+    // perform area recovery
+    clk = clock();
+    if ( !Fpga_MappingPostProcess( p ) )
+        return 0;
+    p->timeRecover = clock() - clk;
+//ABC_PRT( "Total mapping time", clock() - clkTotal );
+
+    s_MappingTime = clock() - clkTotal;
+    s_MappingMem = Fpga_CutCountAll(p) * (sizeof(Fpga_Cut_t) - sizeof(int) * (FPGA_MAX_LEAVES - p->nVarsMax));
+
+    // print the AI-graph used for mapping
+    //Fpga_ManShow( p, "test" );
+//    if ( p->fVerbose )
+//        Fpga_MappingPrintOutputArrivals( p );
+    if ( p->fVerbose )
+    {
+        ABC_PRT( "Total time", clock() - clkTotal );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Postprocesses the mapped network for area recovery.]
+
+  Description [This procedure assumes that the mapping is assigned.
+  It iterates the loop, in which the required times are computed and
+  the mapping is updated. It is conceptually similar to the paper: 
+  V. Manohararajah, S. D. Brown, Z. G. Vranesic, Heuristics for area 
+  minimization in LUT-based FPGA technology mapping. Proc. IWLS '04.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_MappingPostProcess( Fpga_Man_t * p )
+{
+    int fShowSwitching    = 0;
+    int fRecoverAreaFlow  = 1;
+    int fRecoverArea      = 1;
+    float aAreaTotalCur, aAreaTotalCur2;
+    int Iter;
+    clock_t clk;
+
+//if ( p->fVerbose )
+//    printf( "Best clock period = %5.2f\n", Fpga_TimeComputeArrivalMax(p) );
+
+    // compute area, set references, and collect nodes used in the mapping
+    Iter = 1;
+    aAreaTotalCur = Fpga_MappingSetRefsAndArea( p );
+if ( p->fVerbose )
+{
+printf( "Iteration %dD :  Area = %8.1f  ", Iter++, aAreaTotalCur );
+if ( fShowSwitching )
+printf( "Switch = %8.1f  ", Fpga_MappingGetSwitching(p,p->vMapping) );
+else
+printf( "Delay = %5.2f  ", Fpga_TimeComputeArrivalMax(p) );
+
+ABC_PRT( "Time", p->timeMatch );
+}
+
+    if ( !p->fAreaRecovery )
+        return 1;
+
+    if ( fRecoverAreaFlow )
+    {
+clk = clock();
+        // compute the required times and the fanouts
+        Fpga_TimeComputeRequiredGlobal( p, 1 );
+        // remap topologically
+        Fpga_MappingMatches( p, 0 );
+        // get the resulting area
+//        aAreaTotalCur = Fpga_MappingSetRefsAndArea( p );
+        aAreaTotalCur = Fpga_MappingAreaTrav( p );
+        // note that here we do not update the reference counter
+        // for some reason, this works better on benchmarks
+if ( p->fVerbose )
+{
+printf( "Iteration %dF :  Area = %8.1f  ", Iter++, aAreaTotalCur );
+if ( fShowSwitching )
+printf( "Switch = %8.1f  ", Fpga_MappingGetSwitching(p,p->vMapping) );
+else
+printf( "Delay = %5.2f  ", Fpga_TimeComputeArrivalMax(p) );
+ABC_PRT( "Time", clock() - clk );
+}
+    }
+
+    // update reference counters
+    aAreaTotalCur2 = Fpga_MappingSetRefsAndArea( p );
+    assert( aAreaTotalCur == aAreaTotalCur2 );
+
+    if ( fRecoverArea )
+    {
+clk = clock();
+        // compute the required times and the fanouts
+        Fpga_TimeComputeRequiredGlobal( p, 0 );
+        // remap topologically
+        if ( p->fSwitching )
+            Fpga_MappingMatchesSwitch( p );
+        else
+            Fpga_MappingMatchesArea( p );
+        // get the resulting area
+        aAreaTotalCur = Fpga_MappingSetRefsAndArea( p );
+if ( p->fVerbose )
+{
+printf( "Iteration %d%s :  Area = %8.1f  ", Iter++, (p->fSwitching?"S":"A"), aAreaTotalCur );
+if ( fShowSwitching )
+printf( "Switch = %8.1f  ", Fpga_MappingGetSwitching(p,p->vMapping) );
+else
+printf( "Delay = %5.2f  ", Fpga_TimeComputeArrivalMax(p) );
+ABC_PRT( "Time", clock() - clk );
+}
+    }
+
+    p->fAreaGlo = aAreaTotalCur;
+    return 1;
+}
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/fpga/fpgaCreate.c b/abc-build/src/map/fpga/fpgaCreate.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/fpga/fpgaCreate.c
@@ -0,0 +1,584 @@
+/**CFile****************************************************************
+
+  FileName    [fpgaCreate.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Technology mapping for variable-size-LUT FPGAs.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - August 18, 2004.]
+
+  Revision    [$Id: fpgaCreate.c,v 1.8 2004/09/30 21:18:09 satrajit Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void            Fpga_TableCreate( Fpga_Man_t * p );
+static void            Fpga_TableResize( Fpga_Man_t * p );
+static Fpga_Node_t *   Fpga_TableLookup( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 );
+
+// hash key for the structural hash table
+static inline unsigned Fpga_HashKey2( Fpga_Node_t * p0, Fpga_Node_t * p1, int TableSize ) { return (unsigned)(((ABC_PTRUINT_T)(p0) + (ABC_PTRUINT_T)(p1) * 12582917) % TableSize); }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reads parameters of the mapping manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int             Fpga_ManReadInputNum( Fpga_Man_t * p )                    { return p->nInputs;    }
+int             Fpga_ManReadOutputNum( Fpga_Man_t * p )                   { return p->nOutputs;   }
+Fpga_Node_t **  Fpga_ManReadInputs ( Fpga_Man_t * p )                     { return p->pInputs;    }
+Fpga_Node_t **  Fpga_ManReadOutputs( Fpga_Man_t * p )                     { return p->pOutputs;   }
+Fpga_Node_t *   Fpga_ManReadConst1 ( Fpga_Man_t * p )                     { return p->pConst1;    }
+float *         Fpga_ManReadInputArrivals( Fpga_Man_t * p )               { return p->pInputArrivals;}
+int             Fpga_ManReadVerbose( Fpga_Man_t * p )                     { return p->fVerbose;   }
+int             Fpga_ManReadVarMax( Fpga_Man_t * p )                      { return p->pLutLib->LutMax;     }
+float *         Fpga_ManReadLutAreas( Fpga_Man_t * p )                    { return p->pLutLib->pLutAreas;  }
+Fpga_NodeVec_t* Fpga_ManReadMapping( Fpga_Man_t * p )                     { return p->vMapping;   }
+void            Fpga_ManSetOutputNames( Fpga_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames; }
+void            Fpga_ManSetInputArrivals( Fpga_Man_t * p, float * pArrivals ) { p->pInputArrivals = pArrivals; }
+void            Fpga_ManSetAreaRecovery( Fpga_Man_t * p, int fAreaRecovery ) { p->fAreaRecovery = fAreaRecovery;}
+void            Fpga_ManSetDelayLimit( Fpga_Man_t * p, float DelayLimit )    { p->DelayLimit   = DelayLimit;    }
+void            Fpga_ManSetAreaLimit( Fpga_Man_t * p, float AreaLimit )      { p->AreaLimit    = AreaLimit;     }
+void            Fpga_ManSetChoiceNodeNum( Fpga_Man_t * p, int nChoiceNodes ) { p->nChoiceNodes = nChoiceNodes;  }  
+void            Fpga_ManSetChoiceNum( Fpga_Man_t * p, int nChoices )         { p->nChoices = nChoices;          }   
+void            Fpga_ManSetVerbose( Fpga_Man_t * p, int fVerbose )           { p->fVerbose = fVerbose;          }   
+void            Fpga_ManSetSwitching( Fpga_Man_t * p, int fSwitching )       { p->fSwitching = fSwitching;      }   
+void            Fpga_ManSetLatchPaths( Fpga_Man_t * p, int fLatchPaths )     { p->fLatchPaths = fLatchPaths;    }   
+void            Fpga_ManSetLatchNum( Fpga_Man_t * p, int nLatches )          { p->nLatches = nLatches;          }   
+void            Fpga_ManSetDelayTarget( Fpga_Man_t * p, float DelayTarget )  { p->DelayTarget = DelayTarget;    }   
+void            Fpga_ManSetName( Fpga_Man_t * p, char * pFileName )          { p->pFileName = pFileName;        }   
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the parameters of the LUT library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int             Fpga_LibReadLutMax( Fpga_LutLib_t * pLib )  { return pLib->LutMax; }
+
+/**Function*************************************************************
+
+  Synopsis    [Reads parameters of the mapping node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char *          Fpga_NodeReadData0( Fpga_Node_t * p )                   { return p->pData0;    }
+Fpga_Node_t *   Fpga_NodeReadData1( Fpga_Node_t * p )                   { return p->pLevel;    }
+int             Fpga_NodeReadRefs( Fpga_Node_t * p )                    { return p->nRefs;     }
+int             Fpga_NodeReadNum( Fpga_Node_t * p )                     { return p->Num;       }
+int             Fpga_NodeReadLevel( Fpga_Node_t * p )                   { return Fpga_Regular(p)->Level;  }
+Fpga_Cut_t *    Fpga_NodeReadCuts( Fpga_Node_t * p )                    { return p->pCuts;     }
+Fpga_Cut_t *    Fpga_NodeReadCutBest( Fpga_Node_t * p )                 { return p->pCutBest;  }
+Fpga_Node_t *   Fpga_NodeReadOne( Fpga_Node_t * p )                     { return p->p1;        }
+Fpga_Node_t *   Fpga_NodeReadTwo( Fpga_Node_t * p )                     { return p->p2;        }
+void            Fpga_NodeSetData0( Fpga_Node_t * p, char * pData )         { p->pData0 = pData;  }
+void            Fpga_NodeSetData1( Fpga_Node_t * p, Fpga_Node_t * pNode )  { p->pLevel = pNode;  }
+void            Fpga_NodeSetNextE( Fpga_Node_t * p, Fpga_Node_t * pNextE ) { p->pNextE = pNextE; }
+void            Fpga_NodeSetRepr( Fpga_Node_t * p, Fpga_Node_t * pRepr )   { p->pRepr = pRepr;   }
+void            Fpga_NodeSetSwitching( Fpga_Node_t * p, float Switching )  { p->Switching = Switching;   }
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the type of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int             Fpga_NodeIsConst( Fpga_Node_t * p )    {  return (Fpga_Regular(p))->Num == -1;    }
+int             Fpga_NodeIsVar( Fpga_Node_t * p )      {  return (Fpga_Regular(p))->p1 == NULL && (Fpga_Regular(p))->Num >= 0; }
+int             Fpga_NodeIsAnd( Fpga_Node_t * p )      {  return (Fpga_Regular(p))->p1 != NULL;  }
+int             Fpga_NodeComparePhase( Fpga_Node_t * p1, Fpga_Node_t * p2 ) { assert( !Fpga_IsComplement(p1) ); assert( !Fpga_IsComplement(p2) ); return p1->fInv ^ p2->fInv; }
+
+/**Function*************************************************************
+
+  Synopsis    [Reads parameters from the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int             Fpga_CutReadLeavesNum( Fpga_Cut_t * p )            {  return p->nLeaves;  }
+Fpga_Node_t **  Fpga_CutReadLeaves( Fpga_Cut_t * p )               {  return p->ppLeaves; }
+
+
+/**Function*************************************************************
+
+  Synopsis    [Create the mapping manager.]
+
+  Description [The number of inputs and outputs is assumed to be
+  known is advance. It is much simpler to have them fixed upfront.
+  When it comes to representing the object graph in the form of
+  AIG, the resulting manager is similar to the regular AIG manager, 
+  except that it does not use reference counting (and therefore
+  does not have garbage collections). It does have table resizing.
+  The data structure is more flexible to represent additional 
+  information needed for mapping.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Man_t * Fpga_ManCreate( int nInputs, int nOutputs, int fVerbose )
+{
+    Fpga_Man_t * p;
+    int i;
+
+    // start the manager
+    p = ABC_ALLOC( Fpga_Man_t, 1 );
+    memset( p, 0, sizeof(Fpga_Man_t) );
+    p->pLutLib   = (Fpga_LutLib_t *)Abc_FrameReadLibLut();
+    p->nVarsMax  = p->pLutLib->LutMax;
+    p->fVerbose  = fVerbose;
+    p->fAreaRecovery = 1;
+    p->fEpsilon  = (float)0.001;
+
+    Fpga_TableCreate( p );
+//if ( p->fVerbose )
+//    printf( "Node = %d (%d) bytes. Cut = %d bytes.\n", sizeof(Fpga_Node_t), FPGA_NUM_BYTES(sizeof(Fpga_Node_t)), sizeof(Fpga_Cut_t) ); 
+    p->mmNodes  = Extra_MmFixedStart( FPGA_NUM_BYTES(sizeof(Fpga_Node_t)) );
+    p->mmCuts   = Extra_MmFixedStart( sizeof(Fpga_Cut_t) );
+
+    assert( p->nVarsMax > 0 );
+//    Fpga_MappingSetupTruthTables( p->uTruths );
+
+    // make sure the constant node will get index -1
+    p->nNodes = -1;
+    // create the constant node
+    p->pConst1 = Fpga_NodeCreate( p, NULL, NULL );
+    p->vNodesAll = Fpga_NodeVecAlloc( 1000 );
+    p->vMapping = Fpga_NodeVecAlloc( 1000 );
+
+    // create the PI nodes
+    p->nInputs = nInputs;
+    p->pInputs = ABC_ALLOC( Fpga_Node_t *, nInputs );
+    for ( i = 0; i < nInputs; i++ )
+        p->pInputs[i] = Fpga_NodeCreate( p, NULL, NULL );
+
+    // create the place for the output nodes
+    p->nOutputs = nOutputs;
+    p->pOutputs = ABC_ALLOC( Fpga_Node_t *, nOutputs );
+    memset( p->pOutputs, 0, sizeof(Fpga_Node_t *) * nOutputs );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the mapping manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_ManFree( Fpga_Man_t * p )
+{
+//    Fpga_ManStats( p );
+//    int i;
+//    for ( i = 0; i < p->vNodesAll->nSize; i++ )
+//        Fpga_NodeVecFree( p->vNodesAll->pArray[i]->vFanouts );
+//    Fpga_NodeVecFree( p->pConst1->vFanouts );
+    if ( p->vMapping )
+        Fpga_NodeVecFree( p->vMapping );
+    if ( p->vAnds )    
+        Fpga_NodeVecFree( p->vAnds );
+    if ( p->vNodesAll )    
+        Fpga_NodeVecFree( p->vNodesAll );
+    Extra_MmFixedStop( p->mmNodes );
+    Extra_MmFixedStop( p->mmCuts );
+    ABC_FREE( p->ppOutputNames );
+    ABC_FREE( p->pInputArrivals );
+    ABC_FREE( p->pInputs );
+    ABC_FREE( p->pOutputs );
+    ABC_FREE( p->pBins );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints runtime statistics of the mapping manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_ManPrintTimeStats( Fpga_Man_t * p )
+{
+//    extern char * pNetName;
+//    extern int TotalLuts;
+//    FILE * pTable;
+
+    
+/*
+    pTable = fopen( "stats.txt", "a+" );
+    fprintf( pTable, "%s ", pNetName );
+    fprintf( pTable, "%.0f ", p->fRequiredGlo );
+//    fprintf( pTable, "%.0f ", p->fAreaGlo );//+ (float)nOutputInvs );
+    fprintf( pTable, "%.0f ", (float)TotalLuts );
+    fprintf( pTable, "%4.2f\n", (float)(p->timeTotal-p->timeToMap)/(float)(CLOCKS_PER_SEC) );
+    fclose( pTable );
+*/
+
+//    printf( "N-canonical = %d. Matchings = %d.  ", p->nCanons, p->nMatches );
+//    printf( "Choice nodes = %d. Choices = %d.\n", p->nChoiceNodes, p->nChoices );
+    ABC_PRT( "ToMap", p->timeToMap );
+    ABC_PRT( "Cuts ", p->timeCuts );
+    ABC_PRT( "Match", p->timeMatch );
+    ABC_PRT( "Area ", p->timeRecover );
+    ABC_PRT( "ToNet", p->timeToNet );
+    ABC_PRT( "TOTAL", p->timeTotal );
+    if ( p->time1 ) { ABC_PRT( "time1", p->time1 ); }
+    if ( p->time2 ) { ABC_PRT( "time2", p->time2 ); }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new node.]
+
+  Description [This procedure should be called to create the constant
+  node and the PI nodes first.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeCreate( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 )
+{
+    Fpga_Node_t * pNode;
+    // create the node
+    pNode = (Fpga_Node_t *)Extra_MmFixedEntryFetch( p->mmNodes );
+    memset( pNode, 0, sizeof(Fpga_Node_t) );
+    // set very large required time
+    pNode->tRequired = FPGA_FLOAT_LARGE;
+    pNode->aEstFanouts = -1;
+    pNode->p1  = p1; 
+    pNode->p2  = p2;
+    // set the number of this node
+    pNode->Num = p->nNodes++;
+    // place to store the fanouts
+//    pNode->vFanouts = Fpga_NodeVecAlloc( 5 );
+    // store this node in the internal array
+    if ( pNode->Num >= 0 )
+        Fpga_NodeVecPush( p->vNodesAll, pNode );
+    else
+        pNode->fInv = 1;
+    // set the level of this node
+    if ( p1 ) 
+    {
+#ifdef FPGA_ALLOCATE_FANOUT
+        // create the fanout info
+        Fpga_NodeAddFaninFanout( Fpga_Regular(p1), pNode );
+        Fpga_NodeAddFaninFanout( Fpga_Regular(p2), pNode );
+#endif
+        // compute the level
+        pNode->Level = 1 + FPGA_MAX(Fpga_Regular(p1)->Level, Fpga_Regular(p2)->Level);
+        pNode->fInv  = Fpga_NodeIsSimComplement(p1) & Fpga_NodeIsSimComplement(p2);
+    }
+    // reference the inputs 
+    if ( p1 ) Fpga_NodeRef(p1);
+    if ( p2 ) Fpga_NodeRef(p2);
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the unique table of AND gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_TableCreate( Fpga_Man_t * pMan )
+{
+    assert( pMan->pBins == NULL );
+    pMan->nBins = Abc_PrimeCudd(50000);
+    pMan->pBins = ABC_ALLOC( Fpga_Node_t *, pMan->nBins );
+    memset( pMan->pBins, 0, sizeof(Fpga_Node_t *) * pMan->nBins );
+    pMan->nNodes = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Looks up the AND2 node in the unique table.]
+
+  Description [This procedure implements one-level hashing. All the nodes
+  are hashed by their children. If the node with the same children was already
+  created, it is returned by the call to this procedure. If it does not exist,
+  this procedure creates a new node with these children. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_TableLookup( Fpga_Man_t * pMan, Fpga_Node_t * p1, Fpga_Node_t * p2 )
+{
+    Fpga_Node_t * pEnt;
+    unsigned Key;
+
+    if ( p1 == p2 )
+        return p1;
+    if ( p1 == Fpga_Not(p2) )
+        return Fpga_Not(pMan->pConst1);
+    if ( Fpga_NodeIsConst(p1) )
+    {
+        if ( p1 == pMan->pConst1 )
+            return p2;
+        return Fpga_Not(pMan->pConst1);
+    }
+    if ( Fpga_NodeIsConst(p2) )
+    {
+        if ( p2 == pMan->pConst1 )
+            return p1;
+        return Fpga_Not(pMan->pConst1);
+    }
+
+    if ( Fpga_Regular(p1)->Num > Fpga_Regular(p2)->Num )
+        pEnt = p1, p1 = p2, p2 = pEnt;
+
+    Key = Fpga_HashKey2( p1, p2, pMan->nBins );
+    for ( pEnt = pMan->pBins[Key]; pEnt; pEnt = pEnt->pNext )
+        if ( pEnt->p1 == p1 && pEnt->p2 == p2 )
+            return pEnt;
+    // resize the table
+    if ( pMan->nNodes >= 2 * pMan->nBins )
+    {
+        Fpga_TableResize( pMan );
+        Key = Fpga_HashKey2( p1, p2, pMan->nBins );
+    }
+    // create the new node
+    pEnt = Fpga_NodeCreate( pMan, p1, p2 );
+    // add the node to the corresponding linked list in the table
+    pEnt->pNext = pMan->pBins[Key];
+    pMan->pBins[Key] = pEnt;
+    return pEnt;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_TableResize( Fpga_Man_t * pMan )
+{
+    Fpga_Node_t ** pBinsNew;
+    Fpga_Node_t * pEnt, * pEnt2;
+    int nBinsNew, Counter, i;
+    clock_t clk;
+    unsigned Key;
+
+clk = clock();
+    // get the new table size
+    nBinsNew = Abc_PrimeCudd(2 * pMan->nBins); 
+    // allocate a new array
+    pBinsNew = ABC_ALLOC( Fpga_Node_t *, nBinsNew );
+    memset( pBinsNew, 0, sizeof(Fpga_Node_t *) * nBinsNew );
+    // rehash the entries from the old table
+    Counter = 0;
+    for ( i = 0; i < pMan->nBins; i++ )
+        for ( pEnt = pMan->pBins[i], pEnt2 = pEnt? pEnt->pNext: NULL; pEnt; 
+              pEnt = pEnt2, pEnt2 = pEnt? pEnt->pNext: NULL )
+        {
+            Key = Fpga_HashKey2( pEnt->p1, pEnt->p2, nBinsNew );
+            pEnt->pNext = pBinsNew[Key];
+            pBinsNew[Key] = pEnt;
+            Counter++;
+        }
+    assert( Counter == pMan->nNodes - pMan->nInputs );
+    if ( pMan->fVerbose )
+    {
+//        printf( "Increasing the unique table size from %6d to %6d. ", pMan->nBins, nBinsNew );
+//        ABC_PRT( "Time", clock() - clk );
+    }
+    // replace the table and the parameters
+    ABC_FREE( pMan->pBins );
+    pMan->pBins = pBinsNew;
+    pMan->nBins = nBinsNew;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Elementary AND operation on the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeAnd( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 )
+{
+    Fpga_Node_t * pNode;
+    pNode = Fpga_TableLookup( p, p1, p2 );     
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Elementary OR operation on the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeOr( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 )
+{
+    Fpga_Node_t * pNode;
+    pNode = Fpga_Not( Fpga_TableLookup( p, Fpga_Not(p1), Fpga_Not(p2) ) );  
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Elementary EXOR operation on the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeExor( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 )
+{
+    return Fpga_NodeMux( p, p1, Fpga_Not(p2), p2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Elementary MUX operation on the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeMux( Fpga_Man_t * p, Fpga_Node_t * pC, Fpga_Node_t * pT, Fpga_Node_t * pE )
+{
+    Fpga_Node_t * pAnd1, * pAnd2, * pRes;
+    pAnd1 = Fpga_TableLookup( p, pC,           pT ); 
+    pAnd2 = Fpga_TableLookup( p, Fpga_Not(pC), pE ); 
+    pRes  = Fpga_NodeOr( p, pAnd1, pAnd2 );           
+    return pRes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the node to be equivalent to the given one.]
+
+  Description [This procedure is a work-around for the equivalence check.
+  Does not verify the equivalence. Use at the user's risk.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_NodeSetChoice( Fpga_Man_t * pMan, Fpga_Node_t * pNodeOld, Fpga_Node_t * pNodeNew )
+{
+    pNodeNew->pNextE = pNodeOld->pNextE;
+    pNodeOld->pNextE = pNodeNew;
+    pNodeNew->pRepr  = pNodeOld;
+}
+
+
+    
+/**Function*************************************************************
+
+  Synopsis    [Prints some interesting stats.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_ManStats( Fpga_Man_t * p )
+{
+    FILE * pTable;
+    pTable = fopen( "stats.txt", "a+" );
+    fprintf( pTable, "%s ", p->pFileName );
+    fprintf( pTable, "%4d ", p->nInputs - p->nLatches );
+    fprintf( pTable, "%4d ", p->nOutputs - p->nLatches );
+    fprintf( pTable, "%4d ", p->nLatches );
+    fprintf( pTable, "%7d ", p->vAnds->nSize );
+    fprintf( pTable, "%7d ", Fpga_CutCountAll(p) );
+    fprintf( pTable, "%2d\n", (int)p->fRequiredGlo );
+    fclose( pTable );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/fpga/fpgaCut.c b/abc-build/src/map/fpga/fpgaCut.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/fpga/fpgaCut.c
@@ -0,0 +1,1186 @@
+/**CFile****************************************************************
+
+  FileName    [fpgaCut.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - August 18, 2004.]
+
+  Revision    [$Id: fpgaCut.c,v 1.3 2004/07/06 04:55:57 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include "fpgaInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Fpga_CutTableStrutct_t Fpga_CutTable_t;
+struct Fpga_CutTableStrutct_t
+{
+    Fpga_Cut_t ** pBins;        // the table used for linear probing
+    int           nBins;        // the size of the table
+    int *         pCuts;        // the array of cuts currently stored 
+    int           nCuts;        // the number of cuts currently stored 
+    Fpga_Cut_t ** pArray;       // the temporary array of cuts
+    Fpga_Cut_t ** pCuts1;       // the temporary array of cuts
+    Fpga_Cut_t ** pCuts2;       // the temporary array of cuts
+};
+
+// the largest number of cuts considered
+//#define  FPGA_CUTS_MAX_COMPUTE   500
+#define  FPGA_CUTS_MAX_COMPUTE   2000
+// the largest number of cuts used
+//#define  FPGA_CUTS_MAX_USE       200
+#define  FPGA_CUTS_MAX_USE       1000
+
+// primes used to compute the hash key
+static int s_HashPrimes[10] = { 109, 499, 557, 619, 631, 709, 797, 881, 907, 991 };
+
+static int bit_count[256] = {
+  0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+  1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+  1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+  2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+  1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+  2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+  2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+  3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
+
+#define FPGA_COUNT_ONES(u) (bit_count[(u)&255]+bit_count[((u)>>8)&255]+bit_count[((u)>>16)&255]+bit_count[(u)>>24])
+
+static Fpga_Cut_t *      Fpga_CutCompute( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Node_t * pNode );
+static void              Fpga_CutFilter( Fpga_Man_t * p, Fpga_Node_t * pNode );
+static Fpga_Cut_t *      Fpga_CutMergeLists( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 );
+static int               Fpga_CutMergeTwo( Fpga_Cut_t * pCut1, Fpga_Cut_t * pCut2, Fpga_Node_t * ppNodes[], int nNodesMax );
+static Fpga_Cut_t *      Fpga_CutUnionLists( Fpga_Cut_t * pList1, Fpga_Cut_t * pList2 );
+static int               Fpga_CutBelongsToList( Fpga_Cut_t * pList, Fpga_Node_t * ppNodes[], int nNodes );
+extern Fpga_Cut_t *      Fpga_CutAlloc( Fpga_Man_t * p );
+extern int               Fpga_CutCountAll( Fpga_Man_t * pMan );
+
+static void              Fpga_CutListPrint( Fpga_Man_t * pMan, Fpga_Node_t * pRoot );
+static void              Fpga_CutListPrint2( Fpga_Man_t * pMan, Fpga_Node_t * pRoot );
+static void              Fpga_CutPrint_( Fpga_Man_t * pMan, Fpga_Cut_t * pCut, Fpga_Node_t * pRoot );
+
+static Fpga_CutTable_t * Fpga_CutTableStart( Fpga_Man_t * pMan );
+static void              Fpga_CutTableStop( Fpga_CutTable_t * p );
+static unsigned          Fpga_CutTableHash( Fpga_Node_t * ppNodes[], int nNodes );
+static int               Fpga_CutTableLookup( Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes );
+static Fpga_Cut_t *      Fpga_CutTableConsider( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes );
+static void              Fpga_CutTableRestart( Fpga_CutTable_t * p );
+
+static int               Fpga_CutSortCutsCompare( Fpga_Cut_t ** pC1, Fpga_Cut_t ** pC2 );
+static Fpga_Cut_t *      Fpga_CutSortCuts( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Cut_t * pList );
+static int               Fpga_CutList2Array( Fpga_Cut_t ** pArray, Fpga_Cut_t * pList );
+static Fpga_Cut_t *      Fpga_CutArray2List( Fpga_Cut_t ** pArray, int nCuts );
+
+
+// iterator through all the cuts of the list
+#define Fpga_ListForEachCut( pList, pCut )                \
+    for ( pCut = pList;                                   \
+          pCut;                                           \
+          pCut = pCut->pNext )
+#define Fpga_ListForEachCutSafe( pList, pCut, pCut2 )     \
+    for ( pCut = pList,                                   \
+          pCut2 = pCut? pCut->pNext: NULL;                \
+          pCut;                                           \
+          pCut = pCut2,                                   \
+          pCut2 = pCut? pCut->pNext: NULL )
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for each node in the object graph.]
+
+  Description [The cuts are computed in one sweep over the mapping graph. 
+  First, the elementary cuts, which include the node itself, are assigned 
+  to the PI nodes. The internal nodes are considered in the DFS order.
+  Each node is two-input AND-gate. So to compute the cuts at a node, we
+  need to merge the sets of cuts of its two predecessors. The merged set
+  contains only unique cuts with the number of inputs equal to k or less.
+  Finally, the elementary cut, composed of the node itself, is added to
+  the set of cuts for the node.
+  
+  This procedure is pretty fast for 5-feasible cuts, but it dramatically
+  slows down on some "dense" networks when computing 6-feasible cuts.
+  The problem is that there are too many cuts in this case. We should
+  think how to heuristically trim the number of cuts in such cases, 
+  to have reasonable runtime.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_MappingCuts( Fpga_Man_t * p )
+{
+    ProgressBar * pProgress;
+    Fpga_CutTable_t * pTable;
+    Fpga_Node_t * pNode;
+    int nCuts, nNodes, i;
+    clock_t clk = clock();
+
+    // set the elementary cuts for the PI variables
+    assert( p->nVarsMax > 1 && p->nVarsMax < 11 );
+    Fpga_MappingCreatePiCuts( p );
+
+    // compute the cuts for the internal nodes
+    nNodes = p->vAnds->nSize;
+    pProgress = Extra_ProgressBarStart( stdout, nNodes );
+    pTable = Fpga_CutTableStart( p );
+    for ( i = 0; i < nNodes; i++ )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, "Cuts ..." );
+        pNode = p->vAnds->pArray[i];
+        if ( !Fpga_NodeIsAnd( pNode ) )
+            continue;
+        Fpga_CutCompute( p, pTable, pNode );
+    }
+    Extra_ProgressBarStop( pProgress );
+    Fpga_CutTableStop( pTable );
+
+    // report the stats
+    if ( p->fVerbose )
+    {
+        nCuts = Fpga_CutCountAll(p);
+        printf( "Nodes = %6d. Total %d-cuts = %d. Cuts per node = %.1f. ", 
+               p->nNodes, p->nVarsMax, nCuts, ((float)nCuts)/p->nNodes );
+        ABC_PRT( "Time", clock() - clk );
+    }
+
+    // print the cuts for the first primary output
+//    Fpga_CutListPrint( p, Fpga_Regular(p->pOutputs[0]) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs technology mapping for variable-size-LUTs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_MappingCreatePiCuts( Fpga_Man_t * p )
+{
+    Fpga_Cut_t * pCut;
+    int i;
+
+    // set the elementary cuts for the PI variables
+    for ( i = 0; i < p->nInputs; i++ )
+    {
+        pCut = Fpga_CutAlloc( p );
+        pCut->nLeaves = 1;
+        pCut->ppLeaves[0] = p->pInputs[i];
+        pCut->uSign = (1 << (i%31));
+        p->pInputs[i]->pCuts   = pCut;
+        p->pInputs[i]->pCutBest = pCut;
+        // set the input arrival times
+//        p->pInputs[i]->pCut[1]->tArrival = p->pInputArrivals[i];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutCompute( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Node_t * pNode )
+{
+    Fpga_Node_t * pTemp;
+    Fpga_Cut_t * pList, * pList1, * pList2;
+    Fpga_Cut_t * pCut;
+    int fTree = 0;
+    int fPivot1 = fTree && (Fpga_NodeReadRef(pNode->p1)>2);
+    int fPivot2 = fTree && (Fpga_NodeReadRef(pNode->p2)>2);
+
+    // if the cuts are computed return them
+    if ( pNode->pCuts )
+        return pNode->pCuts;
+
+    // compute the cuts for the children
+    pList1 = Fpga_Regular(pNode->p1)->pCuts;
+    pList2 = Fpga_Regular(pNode->p2)->pCuts;
+    // merge the lists
+    pList = Fpga_CutMergeLists( p, pTable, pList1, pList2, 
+        Fpga_IsComplement(pNode->p1), Fpga_IsComplement(pNode->p2),
+        fPivot1, fPivot2 );
+    // if there are functionally equivalent nodes, union them with this list
+    assert( pList );
+    // only add to the list of cuts if the node is a representative one
+    if ( pNode->pRepr == NULL )
+    {
+        for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE )
+        {
+            assert( pTemp->pCuts );
+            pList = Fpga_CutUnionLists( pList, pTemp->pCuts );
+            assert( pTemp->pCuts );
+            pList = Fpga_CutSortCuts( p, pTable, pList );
+        }
+    }
+    // add the new cut
+    pCut = Fpga_CutAlloc( p );
+    pCut->nLeaves = 1;
+    pCut->ppLeaves[0] = pNode;
+    pCut->uSign = (1 << (pNode->Num%31));
+    pCut->fLevel = (float)pCut->ppLeaves[0]->Level;
+    // append (it is important that the elementary cut is appended first)
+    pCut->pNext = pList;
+    // set at the node
+    pNode->pCuts = pCut;
+    // remove the dominated cuts
+//    Fpga_CutFilter( p, pNode );
+    // set the phase correctly
+    if ( pNode->pRepr && Fpga_NodeComparePhase(pNode, pNode->pRepr) )
+    {
+        Fpga_ListForEachCut( pNode->pCuts, pCut )
+            pCut->Phase = 1;
+    }
+
+
+/*
+    { 
+        Fpga_Cut_t * pPrev;
+        int i, Counter = 0;
+        for ( pCut = pNode->pCuts->pNext, pPrev = pNode->pCuts; pCut; pCut = pCut->pNext )
+        {
+            for ( i = 0; i < pCut->nLeaves; i++ )
+                if ( pCut->ppLeaves[i]->Level >= pNode->Level )
+                    break;
+            if ( i != pCut->nLeaves )
+                pPrev->pNext = pCut->pNext;
+            else 
+                pPrev = pCut; 
+        }
+    }
+    { 
+        int i, Counter = 0;;
+        for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+            for ( i = 0; i < pCut->nLeaves; i++ )
+                Counter += (pCut->ppLeaves[i]->Level >= pNode->Level);
+        if ( Counter )
+            printf( " %d", Counter );
+    }
+*/
+
+    return pCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Filter the cuts using dominance.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_CutFilter( Fpga_Man_t * p, Fpga_Node_t * pNode )
+{ 
+    Fpga_Cut_t * pTemp, * pPrev, * pCut, * pCut2;
+    int i, k, Counter;
+
+    Counter = 0;
+    pPrev = pNode->pCuts;
+    Fpga_ListForEachCutSafe( pNode->pCuts->pNext, pCut, pCut2 )
+    {
+        // go through all the previous cuts up to pCut
+        for ( pTemp = pNode->pCuts->pNext; pTemp != pCut; pTemp = pTemp->pNext )
+        {
+            // check if every node in pTemp is contained in pCut
+            for ( i = 0; i < pTemp->nLeaves; i++ )
+            {
+                for ( k = 0; k < pCut->nLeaves; k++ )
+                    if ( pTemp->ppLeaves[i] == pCut->ppLeaves[k] )
+                        break;
+                if ( k == pCut->nLeaves ) // node i in pTemp is not contained in pCut
+                    break;
+            }
+            if ( i == pTemp->nLeaves ) // every node in pTemp is contained in pCut
+            {
+                Counter++;
+                break;
+            }
+        }
+        if ( pTemp != pCut ) // pTemp contain pCut
+        {
+            pPrev->pNext = pCut->pNext;  // skip pCut
+            // recycle pCut
+            Fpga_CutFree( p, pCut );
+        }
+        else 
+            pPrev = pCut; 
+    }
+//  printf( "Dominated = %3d. \n", Counter );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two lists of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutMergeLists( Fpga_Man_t * p, Fpga_CutTable_t * pTable, 
+    Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 )
+{
+    Fpga_Node_t * ppNodes[FPGA_MAX_LEAVES];
+    Fpga_Cut_t * pListNew, ** ppListNew, * pLists[FPGA_MAX_LEAVES+1] = { NULL };
+    Fpga_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2;
+    int nNodes, Counter, i;
+    Fpga_Cut_t ** ppArray1, ** ppArray2, ** ppArray3;
+    int nCuts1, nCuts2, nCuts3, k, fComp3;
+
+    ppArray1 = pTable->pCuts1;
+    ppArray2 = pTable->pCuts2;
+    nCuts1 = Fpga_CutList2Array( ppArray1, pList1 );
+    nCuts2 = Fpga_CutList2Array( ppArray2, pList2 );
+    if ( fPivot1 )
+        nCuts1 = 1;
+    if ( fPivot2 )
+        nCuts2 = 1;
+    // swap the lists based on their length
+    if ( nCuts1 > nCuts2 )
+    {
+         ppArray3 = ppArray1;
+         ppArray1 = ppArray2;
+         ppArray2 = ppArray3;
+
+         nCuts3 = nCuts1;
+         nCuts1 = nCuts2;
+         nCuts2 = nCuts3;
+
+         fComp3 = fComp1;
+         fComp1 = fComp2;
+         fComp2 = fComp3;
+    }
+    // pList1 is shorter or equal length compared to pList2
+ 
+    // prepare the manager for the cut computation
+    Fpga_CutTableRestart( pTable );
+    // go through the cut pairs
+    Counter = 0;
+//    for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext )
+//        for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext )
+    for ( i = 0; i < nCuts1; i++ )
+    {
+        for ( k = 0; k <= i; k++ )
+        {
+            pTemp1 = ppArray1[i];
+            pTemp2 = ppArray2[k];
+
+            if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax )
+            {
+                if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] )
+                    continue;
+                if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] )
+                    continue;
+            }
+
+            // check if k-feasible cut exists
+            nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
+            if ( nNodes == 0 )
+                continue;
+            // consider the cut for possible addition to the set of new cuts
+            pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes );
+            if ( pCut == NULL )
+                continue;
+            // add data to the cut
+            pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 );
+            pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 );
+            // create the signature
+            pCut->uSign = pTemp1->uSign | pTemp2->uSign;
+            // add it to the corresponding list
+            pCut->pNext = pLists[(int)pCut->nLeaves];
+            pLists[(int)pCut->nLeaves] = pCut;
+            // count this cut and quit if limit is reached
+            Counter++;
+            if ( Counter == FPGA_CUTS_MAX_COMPUTE )
+                goto QUITS;
+        }
+        for ( k = 0; k < i; k++ )
+        {
+            pTemp1 = ppArray1[k];
+            pTemp2 = ppArray2[i];
+
+            if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax )
+            {
+                if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] )
+                    continue;
+                if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] )
+                    continue;
+            }
+
+
+            // check if k-feasible cut exists
+            nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
+            if ( nNodes == 0 )
+                continue;
+            // consider the cut for possible addition to the set of new cuts
+            pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes );
+            if ( pCut == NULL )
+                continue;
+            // add data to the cut
+            pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 );
+            pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 );
+            // create the signature
+            pCut->uSign = pTemp1->uSign | pTemp2->uSign;
+            // add it to the corresponding list
+            pCut->pNext = pLists[(int)pCut->nLeaves];
+            pLists[(int)pCut->nLeaves] = pCut;
+            // count this cut and quit if limit is reached
+            Counter++;
+            if ( Counter == FPGA_CUTS_MAX_COMPUTE )
+                goto QUITS;
+        }
+    }
+    // consider the rest of them
+    for ( i = nCuts1; i < nCuts2; i++ )
+        for ( k = 0; k < nCuts1; k++ )
+        {
+            pTemp1 = ppArray1[k];
+            pTemp2 = ppArray2[i];
+
+            if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax )
+            {
+                if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] )
+                    continue;
+                if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] )
+                    continue;
+                if ( pTemp1->ppLeaves[2] != pTemp2->ppLeaves[2] )
+                    continue;
+            }
+
+
+            // check if k-feasible cut exists
+            nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
+            if ( nNodes == 0 )
+                continue;
+            // consider the cut for possible addition to the set of new cuts
+            pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes );
+            if ( pCut == NULL )
+                continue;
+            // add data to the cut
+            pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 );
+            pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 );
+            // create the signature
+            pCut->uSign = pTemp1->uSign | pTemp2->uSign;
+            // add it to the corresponding list
+            pCut->pNext = pLists[(int)pCut->nLeaves];
+            pLists[(int)pCut->nLeaves] = pCut;
+            // count this cut and quit if limit is reached
+            Counter++;
+            if ( Counter == FPGA_CUTS_MAX_COMPUTE )
+                goto QUITS;
+        }
+QUITS :
+    // combine all the lists into one
+    pListNew  = NULL;
+    ppListNew = &pListNew;
+    for ( i = 1; i <= p->nVarsMax; i++ )
+    {
+        if ( pLists[i] == NULL )
+            continue;
+        // find the last entry
+        for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; 
+            pPrev = pCut, pCut = pCut->pNext );
+        // connect these lists
+        *ppListNew = pLists[i];
+        ppListNew  = &pPrev->pNext;
+    }
+    *ppListNew = NULL;
+    // sort the cuts by arrival times and use only the first FPGA_CUTS_MAX_USE
+    pListNew = Fpga_CutSortCuts( p, pTable, pListNew );
+    return pListNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two lists of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutMergeLists2( Fpga_Man_t * p, Fpga_CutTable_t * pTable, 
+    Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 )
+{
+    Fpga_Node_t * ppNodes[FPGA_MAX_LEAVES];
+    Fpga_Cut_t * pListNew, ** ppListNew, * pLists[FPGA_MAX_LEAVES+1] = { NULL };
+    Fpga_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2;
+    int nNodes, Counter, i;
+
+    // prepare the manager for the cut computation
+    Fpga_CutTableRestart( pTable );
+    // go through the cut pairs
+    Counter = 0;
+    for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext )
+        for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext )
+        {
+            // check if k-feasible cut exists
+            nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
+            if ( nNodes == 0 )
+                continue;
+            // consider the cut for possible addition to the set of new cuts
+            pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes );
+            if ( pCut == NULL )
+                continue;
+            // add data to the cut
+            pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 );
+            pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 );
+            // add it to the corresponding list
+            pCut->pNext = pLists[(int)pCut->nLeaves];
+            pLists[(int)pCut->nLeaves] = pCut;
+            // count this cut and quit if limit is reached
+            Counter++;
+            if ( Counter == FPGA_CUTS_MAX_COMPUTE )
+                goto QUITS;
+        }
+QUITS :
+    // combine all the lists into one
+    pListNew  = NULL;
+    ppListNew = &pListNew;
+    for ( i = 1; i <= p->nVarsMax; i++ )
+    {
+        if ( pLists[i] == NULL )
+            continue;
+        // find the last entry
+        for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; 
+            pPrev = pCut, pCut = pCut->pNext );
+        // connect these lists
+        *ppListNew = pLists[i];
+        ppListNew  = &pPrev->pNext;
+    }
+    *ppListNew = NULL;
+    // sort the cuts by arrival times and use only the first FPGA_CUTS_MAX_USE
+    pListNew = Fpga_CutSortCuts( p, pTable, pListNew );
+    return pListNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two cuts.]
+
+  Description [Returns the number of nodes in the resulting cut, or 0 if the
+  cut is infeasible. Returns the resulting nodes in the array ppNodes[].]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_CutMergeTwo( Fpga_Cut_t * pCut1, Fpga_Cut_t * pCut2, Fpga_Node_t * ppNodes[], int nNodesMax )
+{
+    Fpga_Node_t * pNodeTemp;
+    int nTotal, i, k, min, Counter;
+    unsigned uSign;
+
+    // use quick prefiltering
+    uSign = pCut1->uSign | pCut2->uSign;
+    Counter = FPGA_COUNT_ONES(uSign);
+    if ( Counter > nNodesMax )
+        return 0;
+/*
+    // check the special case when at least of the cuts is the largest
+    if ( pCut1->nLeaves == nNodesMax )
+    {
+        if ( pCut2->nLeaves == nNodesMax )
+        {
+            // return 0 if the cuts are different
+            for ( i = 0; i < nNodesMax; i++ )
+                if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i] )
+                    return 0;
+            // return nNodesMax if they are the same
+            for ( i = 0; i < nNodesMax; i++ )
+                ppNodes[i] = pCut1->ppLeaves[i];
+            return nNodesMax;
+        }
+        else if ( pCut2->nLeaves == nNodesMax - 1 ) 
+        {
+            // return 0 if the cuts are different
+            fMismatch = 0;
+            for ( i = 0; i < nNodesMax; i++ )
+                if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i - fMismatch] )
+                {
+                    if ( fMismatch == 1 )
+                        return 0;
+                    fMismatch = 1;
+                }
+            // return nNodesMax if they are the same
+            for ( i = 0; i < nNodesMax; i++ )
+                ppNodes[i] = pCut1->ppLeaves[i];
+            return nNodesMax;
+        }
+    }
+    else if ( pCut1->nLeaves == nNodesMax - 1 && pCut2->nLeaves == nNodesMax )
+    {
+        // return 0 if the cuts are different
+        fMismatch = 0;
+        for ( i = 0; i < nNodesMax; i++ )
+            if ( pCut1->ppLeaves[i - fMismatch] != pCut2->ppLeaves[i] )
+            {
+                if ( fMismatch == 1 )
+                    return 0;
+                fMismatch = 1;
+            }
+        // return nNodesMax if they are the same
+        for ( i = 0; i < nNodesMax; i++ )
+            ppNodes[i] = pCut2->ppLeaves[i];
+        return nNodesMax;
+    }
+*/
+    // count the number of unique entries in pCut2
+    nTotal = pCut1->nLeaves;
+    for ( i = 0; i < pCut2->nLeaves; i++ )
+    {
+        // try to find this entry among the leaves of pCut1
+        for ( k = 0; k < pCut1->nLeaves; k++ )
+            if ( pCut2->ppLeaves[i] == pCut1->ppLeaves[k] )
+                break;
+        if ( k < pCut1->nLeaves ) // found
+            continue;
+        // we found a new entry to add
+        if ( nTotal == nNodesMax )
+            return 0;
+        ppNodes[nTotal++] = pCut2->ppLeaves[i];
+    }
+    // we know that the feasible cut exists
+
+    // add the starting entries
+    for ( k = 0; k < pCut1->nLeaves; k++ )
+        ppNodes[k] = pCut1->ppLeaves[k];
+
+    // selection-sort the entries
+    for ( i = 0; i < nTotal - 1; i++ )
+    {
+        min = i;
+        for ( k = i+1; k < nTotal; k++ )
+//            if ( ppNodes[k] < ppNodes[min] ) // reported bug fix (non-determinism!)
+            if ( ppNodes[k]->Num < ppNodes[min]->Num )
+                min = k;
+        pNodeTemp    = ppNodes[i];
+        ppNodes[i]   = ppNodes[min];
+        ppNodes[min] = pNodeTemp;
+    }
+
+    return nTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the union of the two lists of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutUnionLists( Fpga_Cut_t * pList1, Fpga_Cut_t * pList2 )
+{
+    Fpga_Cut_t * pTemp, * pRoot;
+    // find the last cut in the first list
+    pRoot = pList1;
+    Fpga_ListForEachCut( pList1, pTemp )
+        pRoot = pTemp;
+    // attach the non-trival part of the second cut to the end of the first
+    assert( pRoot->pNext == NULL );
+    pRoot->pNext = pList2->pNext;   
+    pList2->pNext = NULL;
+    return pList1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks whether the given cut belongs to the list.]
+
+  Description [This procedure takes most of the runtime in the cut 
+  computation.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_CutBelongsToList( Fpga_Cut_t * pList, Fpga_Node_t * ppNodes[], int nNodes )
+{
+    Fpga_Cut_t * pTemp;
+    int i;
+    for ( pTemp = pList; pTemp; pTemp = pTemp->pNext )
+    {
+        for ( i = 0; i < nNodes; i++ )
+            if ( pTemp->ppLeaves[i] != ppNodes[i] )
+                break;
+        if ( i == nNodes )
+            return 1;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts all the cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_CutCountAll( Fpga_Man_t * pMan )
+{
+    Fpga_Node_t * pNode;
+    Fpga_Cut_t * pCut;
+    int i, nCuts;
+    // go through all the nodes in the unique table of the manager
+    nCuts = 0;
+    for ( i = 0; i < pMan->nBins; i++ )
+        for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext )
+            for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext )
+                if ( pCut->nLeaves > 1 ) // skip the elementary cuts
+                {
+//                    Fpga_CutVolume( pCut );
+                    nCuts++;
+                }
+    return nCuts;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Clean the signatures.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_CutsCleanSign( Fpga_Man_t * pMan )
+{
+    Fpga_Node_t * pNode;
+    Fpga_Cut_t * pCut;
+    int i;
+    for ( i = 0; i < pMan->nBins; i++ )
+        for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext )
+            for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext )
+                pCut->uSign = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Clean the signatures.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_CutsCleanRoot( Fpga_Man_t * pMan )
+{
+    Fpga_Node_t * pNode;
+    Fpga_Cut_t * pCut;
+    int i;
+    for ( i = 0; i < pMan->nBins; i++ )
+        for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext )
+            for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext )
+                pCut->pRoot = NULL;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the cuts in the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_CutListPrint( Fpga_Man_t * pMan, Fpga_Node_t * pRoot )
+{
+    Fpga_Cut_t * pTemp;
+    int Counter;
+    for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ )
+    {
+        printf( "%2d : ", Counter + 1 );
+        Fpga_CutPrint_( pMan, pTemp, pRoot );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the cuts in the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_CutListPrint2( Fpga_Man_t * pMan, Fpga_Node_t * pRoot )
+{
+    Fpga_Cut_t * pTemp;
+    int Counter;
+    for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ )
+    {
+        printf( "%2d : ", Counter + 1 );
+        Fpga_CutPrint_( pMan, pTemp, pRoot );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_CutPrint_( Fpga_Man_t * pMan, Fpga_Cut_t * pCut, Fpga_Node_t * pRoot )
+{
+    int i;
+    printf( "(%3d)  {", pRoot->Num );
+    for ( i = 0; i < pMan->nVarsMax; i++ )
+        if ( pCut->ppLeaves[i] )
+            printf( " %3d", pCut->ppLeaves[i]->Num );
+    printf( " }\n" );
+}
+
+
+
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the hash table to canonicize cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_CutTable_t * Fpga_CutTableStart( Fpga_Man_t * pMan )
+{
+    Fpga_CutTable_t * p;
+    // allocate the table
+    p = ABC_ALLOC( Fpga_CutTable_t, 1 );
+    memset( p, 0, sizeof(Fpga_CutTable_t) );
+    p->nBins = Abc_PrimeCudd( 10 * FPGA_CUTS_MAX_COMPUTE );
+    p->pBins = ABC_ALLOC( Fpga_Cut_t *, p->nBins );
+    memset( p->pBins, 0, sizeof(Fpga_Cut_t *) * p->nBins );
+    p->pCuts = ABC_ALLOC( int, 2 * FPGA_CUTS_MAX_COMPUTE );
+    p->pArray = ABC_ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE );
+    p->pCuts1 = ABC_ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE );
+    p->pCuts2 = ABC_ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_CutTableStop( Fpga_CutTable_t * p )
+{
+    ABC_FREE( p->pCuts1 );
+    ABC_FREE( p->pCuts2 );
+    ABC_FREE( p->pArray );
+    ABC_FREE( p->pBins );
+    ABC_FREE( p->pCuts );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the hash value of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Fpga_CutTableHash( Fpga_Node_t * ppNodes[], int nNodes )
+{
+    unsigned uRes;
+    int i;
+    uRes = 0;
+    for ( i = 0; i < nNodes; i++ )
+        uRes += s_HashPrimes[i] * ppNodes[i]->Num;
+    return uRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Looks up the table for the available cut.]
+
+  Description [Returns -1 if the same cut is found. Returns the index
+  of the cell where the cut should be added, if it does not exist.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_CutTableLookup( Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes )
+{
+    Fpga_Cut_t * pCut;
+    unsigned Key;
+    int b, i;
+
+    Key = Fpga_CutTableHash(ppNodes, nNodes) % p->nBins; 
+    for ( b = Key; p->pBins[b]; b = (b+1) % p->nBins )
+    {
+        pCut = p->pBins[b];
+        if ( pCut->nLeaves != nNodes )
+            continue;
+        for ( i = 0; i < nNodes; i++ )
+            if ( pCut->ppLeaves[i] != ppNodes[i] )
+                break;
+        if ( i == nNodes )
+            return -1;
+    }
+    return b;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the hash table to canonicize cuts.]
+
+  Description [Considers addition of the cut to the hash table.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutTableConsider( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes )
+{
+    Fpga_Cut_t * pCut;
+    int Place, i;
+    // check the cut
+    Place = Fpga_CutTableLookup( p, ppNodes, nNodes );
+    if ( Place == -1 )
+        return NULL;
+    assert( nNodes > 0 );
+    // create the new cut
+    pCut = Fpga_CutAlloc( pMan );
+    pCut->nLeaves = nNodes;
+    pCut->fLevel = 0.0;
+    for ( i = 0; i < nNodes; i++ )
+    {
+        pCut->ppLeaves[i] = ppNodes[i];
+        pCut->fLevel += ppNodes[i]->Level;
+    }
+    pCut->fLevel /= nNodes;
+    // add the cut to the table
+    assert( p->pBins[Place] == NULL );
+    p->pBins[Place] = pCut;
+    // add the cut to the new list
+    p->pCuts[ p->nCuts++ ] = Place;
+    return pCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the table to be used with other cuts.]
+
+  Description [Restarts the table by cleaning the info about cuts stored
+  when the previous node was considered.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_CutTableRestart( Fpga_CutTable_t * p )
+{
+    int i;
+    for ( i = 0; i < p->nCuts; i++ )
+    {
+        assert( p->pBins[ p->pCuts[i] ] );
+        p->pBins[ p->pCuts[i] ] = NULL;
+    }
+    p->nCuts = 0;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the cuts by the number of leaves and then by delay.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_CutSortCutsCompare( Fpga_Cut_t ** pC1, Fpga_Cut_t ** pC2 )
+{
+    if ( (*pC1)->nLeaves < (*pC2)->nLeaves )
+        return -1;
+    if ( (*pC1)->nLeaves > (*pC2)->nLeaves )
+        return 1;
+/*
+    if ( (*pC1)->fLevel > (*pC2)->fLevel )
+        return -1;
+    if ( (*pC1)->fLevel < (*pC2)->fLevel )
+        return 1;
+*/
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts the cuts by average arrival time.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutSortCuts( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Cut_t * pList )
+{
+    Fpga_Cut_t * pListNew;
+    int nCuts, i;
+    // move the cuts from the list into the array
+    nCuts = Fpga_CutList2Array( p->pCuts1, pList );
+    assert( nCuts <= FPGA_CUTS_MAX_COMPUTE );
+    // sort the cuts
+    qsort( (void *)p->pCuts1, nCuts, sizeof(void *), 
+            (int (*)(const void *, const void *)) Fpga_CutSortCutsCompare );
+    // move them back into the list
+    if ( nCuts > FPGA_CUTS_MAX_USE - 1 )
+    {
+//        printf( "*" );
+        // free the remaining cuts
+        for ( i = FPGA_CUTS_MAX_USE - 1; i < nCuts; i++ )
+            Extra_MmFixedEntryRecycle( pMan->mmCuts, (char *)p->pCuts1[i] );
+        // update the number of cuts
+        nCuts = FPGA_CUTS_MAX_USE - 1;
+    }
+    pListNew = Fpga_CutArray2List( p->pCuts1, nCuts );
+    return pListNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Moves the nodes from the list into the array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_CutList2Array( Fpga_Cut_t ** pArray, Fpga_Cut_t * pList )
+{
+    int i;
+    for ( i = 0; pList; pList = pList->pNext, i++ )
+        pArray[i] = pList;
+    return i;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Moves the nodes from the array into the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutArray2List( Fpga_Cut_t ** pArray, int nCuts )
+{
+    Fpga_Cut_t * pListNew, ** ppListNew;
+    int i;
+    pListNew  = NULL;
+    ppListNew = &pListNew;
+    for ( i = 0; i < nCuts; i++ )
+    {
+        // connect these lists
+        *ppListNew = pArray[i];
+        ppListNew  = &pArray[i]->pNext;
+//printf( " %d(%.2f)", pArray[i]->nLeaves, pArray[i]->fLevel );
+    }
+//printf( "\n" );
+
+    *ppListNew = NULL;
+    return pListNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/fpga/fpgaCutUtils.c b/abc-build/src/map/fpga/fpgaCutUtils.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/fpga/fpgaCutUtils.c
@@ -0,0 +1,476 @@
+/**CFile****************************************************************
+
+  FileName    [fpgaCutUtils.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - August 18, 2004.]
+
+  Revision    [$Id: fpgaCutUtils.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutAlloc( Fpga_Man_t * p )
+{
+    Fpga_Cut_t * pCut;
+    pCut = (Fpga_Cut_t *)Extra_MmFixedEntryFetch( p->mmCuts );
+    memset( pCut, 0, sizeof(Fpga_Cut_t) );
+    return pCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutDup( Fpga_Man_t * p, Fpga_Cut_t * pCutOld )
+{
+    Fpga_Cut_t * pCutNew;
+    int i;
+    pCutNew = Fpga_CutAlloc( p );
+    pCutNew->pRoot   = pCutOld->pRoot;
+    pCutNew->nLeaves = pCutOld->nLeaves;
+    for ( i = 0; i < pCutOld->nLeaves; i++ )
+        pCutNew->ppLeaves[i] = pCutOld->ppLeaves[i];
+    return pCutNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_CutFree( Fpga_Man_t * p, Fpga_Cut_t * pCut )
+{
+    if ( pCut )
+    Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pCut );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_CutPrint( Fpga_Man_t * p, Fpga_Node_t * pRoot, Fpga_Cut_t * pCut )
+{
+    int i;
+    printf( "CUT:  Delay = %4.2f. Area = %4.2f. Nodes = %d -> {", 
+        pCut->tArrival, pCut->aFlow, pRoot->Num );
+    for ( i = 0; i < pCut->nLeaves; i++ )
+        printf( " %d", pCut->ppLeaves[i]->Num );
+    printf( " } \n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutCreateSimple( Fpga_Man_t * p, Fpga_Node_t * pNode )
+{
+    Fpga_Cut_t * pCut;
+    pCut = Fpga_CutAlloc( p );
+    pCut->pRoot       = pNode;
+    pCut->nLeaves     = 1;
+    pCut->ppLeaves[0] = pNode;
+    pCut->uSign = FPGA_SEQ_SIGN(pCut->ppLeaves[0]);
+    return pCut;
+}
+
+
+/**function*************************************************************
+
+  synopsis    [Computes the exact area associated with the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Fpga_CutGetRootArea( Fpga_Man_t * p, Fpga_Cut_t * pCut )
+{
+    return p->pLutLib->pLutAreas[(int)pCut->nLeaves];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutListAppend( Fpga_Cut_t * pSetAll, Fpga_Cut_t * pSets )
+{
+    Fpga_Cut_t * pPrev = NULL; // Suppress "might be used uninitialized"
+    Fpga_Cut_t * pTemp;
+    if ( pSetAll == NULL )
+        return pSets;
+    if ( pSets == NULL )
+        return pSetAll;
+    // find the last one
+    for ( pTemp = pSets; pTemp; pTemp = pTemp->pNext )
+        pPrev = pTemp;
+    // append all the end of the current set
+    assert( pPrev->pNext == NULL );
+    pPrev->pNext = pSetAll;
+    return pSets;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_CutListRecycle( Fpga_Man_t * p, Fpga_Cut_t * pSetList, Fpga_Cut_t * pSave )
+{
+    Fpga_Cut_t * pNext, * pTemp;
+    for ( pTemp = pSetList, pNext = pTemp? pTemp->pNext : NULL; 
+          pTemp; 
+          pTemp = pNext, pNext = pNext? pNext->pNext : NULL )
+        if ( pTemp != pSave )
+            Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pTemp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_CutListCount( Fpga_Cut_t * pSets )
+{
+    Fpga_Cut_t * pTemp;
+    int i;
+    for ( i = 0, pTemp = pSets; pTemp; pTemp = pTemp->pNext, i++ );
+    return i;
+}
+
+#if 0
+
+/**function*************************************************************
+
+  synopsis    [Removes the fanouts of the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+void Fpga_CutRemoveFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut )
+{
+    Fpga_NodeVec_t * vFanouts;
+    int i, k;
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        vFanouts = pCut->ppLeaves[i]->vFanouts;
+        for ( k = 0; k < vFanouts->nSize; k++ )
+            if ( vFanouts->pArray[k] == pNode )
+                break;
+        assert( k != vFanouts->nSize );
+        for ( k++; k < vFanouts->nSize; k++ )
+            vFanouts->pArray[k-1] = vFanouts->pArray[k];
+        vFanouts->nSize--;
+    }
+}
+
+/**function*************************************************************
+
+  synopsis    [Removes the fanouts of the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+void Fpga_CutInsertFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut )
+{
+    int i;
+    for ( i = 0; i < pCut->nLeaves; i++ )
+        Fpga_NodeVecPush( pCut->ppLeaves[i]->vFanouts, pNode );
+}
+#endif
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the arrival time and the area flow of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_CutGetParameters( Fpga_Man_t * pMan, Fpga_Cut_t * pCut )
+{
+    Fpga_Cut_t * pFaninCut;
+    int i;
+    pCut->tArrival = -FPGA_FLOAT_LARGE;
+    pCut->aFlow    = pMan->pLutLib->pLutAreas[(int)pCut->nLeaves];
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        pFaninCut = pCut->ppLeaves[i]->pCutBest;
+        if ( pCut->tArrival < pFaninCut->tArrival )
+             pCut->tArrival = pFaninCut->tArrival;
+        // if the fanout count is not set, assume it to be 1
+        if ( pCut->ppLeaves[i]->nRefs == 0 )
+            pCut->aFlow += pFaninCut->aFlow;
+        else
+//            pCut->aFlow += pFaninCut->aFlow / pCut->ppLeaves[i]->nRefs;
+            pCut->aFlow += pFaninCut->aFlow / pCut->ppLeaves[i]->aEstFanouts;
+    }
+    // use the first pin to compute the delay of the LUT 
+    // (this mapper does not support the variable pin delay model)
+    pCut->tArrival += pMan->pLutLib->pLutDelays[(int)pCut->nLeaves][0];
+}
+
+
+/**function*************************************************************
+
+  synopsis    [Computes the area flow of the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Fpga_CutGetAreaFlow( Fpga_Man_t * pMan, Fpga_Cut_t * pCut )
+{
+    Fpga_Cut_t * pCutFanin;
+    int i;
+    pCut->aFlow = pMan->pLutLib->pLutAreas[(int)pCut->nLeaves];
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        // get the cut implementing this phase of the fanin
+        pCutFanin  = pCut->ppLeaves[i]->pCutBest;   
+        assert( pCutFanin );
+        pCut->aFlow  += pCutFanin->aFlow / pCut->ppLeaves[i]->nRefs;
+    }
+    return pCut->aFlow;
+}
+
+/**function*************************************************************
+
+  synopsis    [Computes the exact area associated with the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Fpga_CutGetAreaRefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut )
+{
+    float aResult, aResult2;
+    if ( pCut->nLeaves == 1 )
+        return 0;
+    aResult  = Fpga_CutDeref( pMan, NULL, pCut, 0 );
+    aResult2 = Fpga_CutRef( pMan, NULL, pCut, 0 );
+    assert( Fpga_FloatEqual( pMan, aResult, aResult2 ) );
+    return aResult;
+}
+
+/**function*************************************************************
+
+  synopsis    [Computes the exact area associated with the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Fpga_CutGetAreaDerefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut )
+{
+    float aResult, aResult2;
+    if ( pCut->nLeaves == 1 )
+        return 0;
+    aResult2 = Fpga_CutRef( pMan, NULL, pCut, 0 );
+    aResult  = Fpga_CutDeref( pMan, NULL, pCut, 0 );
+    assert( Fpga_FloatEqual( pMan, aResult, aResult2 ) );
+    return aResult;
+}
+
+/**function*************************************************************
+
+  synopsis    [References the cut.]
+
+  description [This procedure is similar to the procedure NodeReclaim.]
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Fpga_CutRef( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts )
+{
+    Fpga_Node_t * pNodeChild;
+    float aArea;
+    int i;
+
+    // deref the fanouts
+//    if ( fFanouts ) 
+//        Fpga_CutInsertFanouts( pMan, pNode, pCut );
+
+    // start the area of this cut
+    aArea = pMan->pLutLib->pLutAreas[(int)pCut->nLeaves];
+    // go through the children
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        pNodeChild = pCut->ppLeaves[i];
+        assert( pNodeChild->nRefs >= 0 );
+        if ( pNodeChild->nRefs++ > 0 )  
+            continue;
+        if ( !Fpga_NodeIsAnd(pNodeChild) ) 
+            continue;
+        aArea += Fpga_CutRef( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts );
+    }
+    return aArea;
+}
+
+/**function*************************************************************
+
+  synopsis    [Dereferences the cut.]
+
+  description [This procedure is similar to the procedure NodeRecusiveDeref.]
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Fpga_CutDeref( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts )
+{
+    Fpga_Node_t * pNodeChild;
+    float aArea;
+    int i;
+
+    // deref the fanouts
+//    if ( fFanouts ) 
+//        Fpga_CutRemoveFanouts( pMan, pNode, pCut );
+
+    // start the area of this cut
+    aArea = pMan->pLutLib->pLutAreas[(int)pCut->nLeaves];
+    // go through the children
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        pNodeChild = pCut->ppLeaves[i];
+        assert( pNodeChild->nRefs > 0 );
+        if ( --pNodeChild->nRefs > 0 )  
+            continue;
+        if ( !Fpga_NodeIsAnd(pNodeChild) ) 
+            continue;
+        aArea += Fpga_CutDeref( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts );
+    }
+    return aArea;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the used cuts to be the currently selected ones.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_MappingSetUsedCuts( Fpga_Man_t * pMan )
+{
+    int i;
+    for ( i = 0; i < pMan->vNodesAll->nSize; i++ )
+        if ( pMan->vNodesAll->pArray[i]->pCutOld )
+        {
+            pMan->vNodesAll->pArray[i]->pCutBest = pMan->vNodesAll->pArray[i]->pCutOld;
+            pMan->vNodesAll->pArray[i]->pCutOld  = NULL;
+        }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/fpga/fpgaFanout.c b/abc-build/src/map/fpga/fpgaFanout.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/fpga/fpgaFanout.c
@@ -0,0 +1,146 @@
+/**CFile****************************************************************
+
+  FileName    [fpgaFanout.c]
+
+  PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+  Synopsis    [Procedures to manipulate fanouts of the FRAIG nodes.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - August 18, 2004.]
+
+  Revision    [$Id: fpgaFanout.c,v 1.1 2005/01/23 06:59:41 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+#ifdef MAP_ALLOCATE_FANOUT
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Add the fanout to the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_NodeAddFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanout )
+{
+    Fpga_Node_t * pPivot;
+
+    // pFanins is a fanin of pFanout
+    assert( !Fpga_IsComplement(pFanin) );
+    assert( !Fpga_IsComplement(pFanout) );
+    assert( Fpga_Regular(pFanout->p1) == pFanin || Fpga_Regular(pFanout->p2) == pFanin );
+
+    pPivot = pFanin->pFanPivot;
+    if ( pPivot == NULL )
+    {
+        pFanin->pFanPivot = pFanout;
+        return;
+    }
+
+    if ( Fpga_Regular(pPivot->p1) == pFanin )
+    {
+        if ( Fpga_Regular(pFanout->p1) == pFanin )
+        {
+            pFanout->pFanFanin1 = pPivot->pFanFanin1;
+            pPivot->pFanFanin1  = pFanout;
+        }
+        else // if ( Fpga_Regular(pFanout->p2) == pFanin )
+        {
+            pFanout->pFanFanin2 = pPivot->pFanFanin1;
+            pPivot->pFanFanin1  = pFanout;
+        }
+    }
+    else // if ( Fpga_Regular(pPivot->p2) == pFanin )
+    {
+        assert( Fpga_Regular(pPivot->p2) == pFanin );
+        if ( Fpga_Regular(pFanout->p1) == pFanin )
+        {
+            pFanout->pFanFanin1 = pPivot->pFanFanin2;
+            pPivot->pFanFanin2  = pFanout;
+        }
+        else // if ( Fpga_Regular(pFanout->p2) == pFanin )
+        {
+            pFanout->pFanFanin2 = pPivot->pFanFanin2;
+            pPivot->pFanFanin2  = pFanout;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add the fanout to the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_NodeRemoveFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanoutToRemove )
+{
+    Fpga_Node_t * pFanout, * pFanout2, ** ppFanList;
+    // start the linked list of fanouts
+    ppFanList = &pFanin->pFanPivot; 
+    // go through the fanouts
+    Fpga_NodeForEachFanoutSafe( pFanin, pFanout, pFanout2 )
+    {
+        // skip the fanout-to-remove
+        if ( pFanout == pFanoutToRemove )
+            continue;
+        // add useful fanouts to the list
+        *ppFanList = pFanout;
+        ppFanList = Fpga_NodeReadNextFanoutPlace( pFanin, pFanout );
+    }
+    *ppFanList = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of fanouts of a node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_NodeGetFanoutNum( Fpga_Node_t * pNode )
+{
+    Fpga_Node_t * pFanout;
+    int Counter = 0;
+    Fpga_NodeForEachFanout( pNode, pFanout )
+        Counter++;
+    return Counter;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/fpga/fpgaGENERIC.c b/abc-build/src/map/fpga/fpgaGENERIC.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/fpga/fpgaGENERIC.c
@@ -0,0 +1,51 @@
+/**CFile****************************************************************
+
+  FileName    [fpga__.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: fpga__.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/fpga/fpgaInt.h b/abc-build/src/map/fpga/fpgaInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/fpga/fpgaInt.h
@@ -0,0 +1,389 @@
+/**CFile****************************************************************
+
+  FileName    [fpgaInt.h]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Technology mapping for variable-size-LUT FPGAs.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - August 18, 2004.]
+
+  Revision    [$Id: fpgaInt.h,v 1.8 2004/09/30 21:18:10 satrajit Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__map__fpga__fpgaInt_h
+#define ABC__map__fpga__fpgaInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc/extra/extra.h"
+#include "fpga.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+ 
+// uncomment to have fanouts represented in the mapping graph
+//#define FPGA_ALLOCATE_FANOUT  1
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+#ifdef _WIN32
+#define inline __inline // compatible with MS VS 6.0
+#endif
+
+// the maximum number of cut leaves (currently does not work for 7)
+#define FPGA_MAX_LEAVES           6   
+
+// the bit masks
+#define FPGA_MASK(n)             ((~((unsigned)0)) >> (32-(n)))
+#define FPGA_FULL                 (~((unsigned)0))
+#define FPGA_NO_VAR               (-9999.0)
+#define FPGA_NUM_BYTES(n)         (((n)/16 + (((n)%16) > 0))*16)
+
+// maximum/minimum operators
+#define FPGA_MIN(a,b)             (((a) < (b))? (a) : (b))
+#define FPGA_MAX(a,b)             (((a) > (b))? (a) : (b))
+
+// the small and large numbers (min/max float are 1.17e-38/3.40e+38)
+#define FPGA_FLOAT_LARGE          ((float)1.0e+20)
+#define FPGA_FLOAT_SMALL          ((float)1.0e-20)
+#define FPGA_INT_LARGE            (10000000)
+
+// the macro to compute the signature
+#define FPGA_SEQ_SIGN(p)        (1 << (((ABC_PTRUINT_T)p)%31));
+
+// internal macros to work with cuts
+#define Fpga_CutIsComplement(p)  (((int)((ABC_PTRUINT_T)(p) & 01)))
+#define Fpga_CutRegular(p)       ((Fpga_Cut_t *)((ABC_PTRUINT_T)(p) & ~01)) 
+#define Fpga_CutNot(p)           ((Fpga_Cut_t *)((ABC_PTRUINT_T)(p) ^ 01)) 
+#define Fpga_CutNotCond(p,c)     ((Fpga_Cut_t *)((ABC_PTRUINT_T)(p) ^ (c)))
+
+// the cut nodes
+#define Fpga_SeqIsComplement( p )      (((int)((ABC_PTRUINT_T) (p) & 01)))
+#define Fpga_SeqRegular( p )           ((Fpga_Node_t *)((ABC_PTRUINT_T)(p) & ~015))
+#define Fpga_SeqIndex( p )             ((((ABC_PTRUINT_T)(p)) >> 1) & 07)
+#define Fpga_SeqIndexCreate( p, Ind )  (((ABC_PTRUINT_T)(p)) | (1 << (((ABC_PTRUINT_T)(Ind)) & 07)))
+
+// internal macros for referencing of nodes
+#define Fpga_NodeReadRef(p)      ((Fpga_Regular(p))->nRefs)
+#define Fpga_NodeRef(p)          ((Fpga_Regular(p))->nRefs++)
+
+// returns the complemented attribute of the node
+#define Fpga_NodeIsSimComplement(p) (Fpga_IsComplement(p)? !(Fpga_Regular(p)->fInv) : (p)->fInv)
+
+// generating random unsigned (#define RAND_MAX 0x7fff)
+#define FPGA_RANDOM_UNSIGNED   ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand()))
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+// the mapping manager
+struct Fpga_ManStruct_t_
+{
+    // the mapping graph
+    Fpga_Node_t **      pBins;         // the table of nodes hashed by their children
+    int                 nBins;         // the size of the table
+    Fpga_Node_t **      pInputs;       // the array of inputs
+    int                 nInputs;       // the number of inputs
+    Fpga_Node_t **      pOutputs;      // the array of outputs
+    int                 nOutputs;      // the number of outputs
+    int                 nNodes;        // the total number of nodes
+    int                 nLatches;      // the number of latches in the circuit
+    Fpga_Node_t *       pConst1;       // the constant 1 node
+    Fpga_NodeVec_t *    vNodesAll;     // the nodes by number
+    Fpga_NodeVec_t *    vAnds;         // the nodes reachable from COs
+    Fpga_NodeVec_t *    vMapping;      // the nodes used in the current mapping
+
+    // info about the original circuit
+    char *              pFileName;     // the file name
+    char **             ppOutputNames; // the primary output names
+    float *             pInputArrivals;// the PI arrival times
+
+    // mapping parameters
+    int                 nVarsMax;      // the max number of variables
+    int                 fAreaRecovery; // the flag to use area flow as the first parameter
+    int                 fVerbose;      // the verbosiness flag
+    int                 fSwitching;    // minimize the switching activity (instead of area)
+    int                 fLatchPaths;   // optimize latch paths for delay, other paths for area
+    int                 nTravIds;      // the counter of traversal IDs
+    float               DelayTarget;   // the target required times
+
+    // support of choice nodes
+    int                 nChoiceNodes;  // the number of choice nodes
+    int                 nChoices;      // the number of all choices
+
+    int                 nCanons;
+    int                 nMatches;
+ 
+    // the supergate library
+    Fpga_LutLib_t *     pLutLib;       // the current LUT library
+
+    // the memory managers
+    Extra_MmFixed_t *   mmNodes;       // the memory manager for nodes
+    Extra_MmFixed_t *   mmCuts;        // the memory manager for cuts
+
+    // resynthesis parameters
+    int                 fResynthesis;  // the resynthesis flag
+    float               fRequiredGlo;  // the global required times
+    float               fRequiredShift;// the shift of the required times
+    float               fRequiredStart;// the starting global required times
+    float               fRequiredGain; // the reduction in delay
+    float               fAreaGlo;      // the total area
+    float               fAreaGain;     // the reduction in area
+    float               fEpsilon;      // the epsilon used to compare floats
+    float               fDelayWindow;  // the delay window for delay-oriented resynthesis
+    float               DelayLimit;    // for resynthesis
+    float               AreaLimit;     // for resynthesis
+    float               TimeLimit;     // for resynthesis
+
+    // runtime statistics
+    clock_t             timeToMap;     // time to transfer to the mapping structure
+    clock_t             timeCuts;      // time to compute k-feasible cuts
+    clock_t             timeTruth;     // time to compute the truth table for each cut
+    clock_t             timeMatch;     // time to perform matching for each node
+    clock_t             timeRecover;   // time to perform area recovery
+    clock_t             timeToNet;     // time to transfer back to the network
+    clock_t             timeTotal;     // the total mapping time
+    clock_t             time1;         // time to transfer to the mapping structure
+    clock_t             time2;         // time to transfer to the mapping structure
+};
+
+// the LUT library
+struct Fpga_LutLibStruct_t_
+{
+    char *              pName;         // the name of the LUT library
+    int                 LutMax;        // the maximum LUT size 
+    int                 fVarPinDelays; // set to 1 if variable pin delays are specified
+    float               pLutAreas[FPGA_MAX_LUTSIZE+1]; // the areas of LUTs
+    float               pLutDelays[FPGA_MAX_LUTSIZE+1][FPGA_MAX_LUTSIZE+1];// the delays of LUTs
+};
+
+// the mapping node
+struct Fpga_NodeStruct_t_ 
+{
+    // general information about the node
+    Fpga_Node_t *       pNext;         // the next node in the hash table
+    Fpga_Node_t *       pLevel;        // the next node in the linked list by level
+    int                 Num;           // the unique number of this node
+    int                 NumA;          // the unique number of this node
+    int                 Num2;          // the temporary number of this node
+    int                 nRefs;         // the number of references (fanouts) of the given node
+    unsigned            fMark0 : 1;    // the mark used for traversals
+    unsigned            fMark1 : 1;    // the mark used for traversals
+    unsigned            fInv   : 1;    // the complemented attribute for the equivalent nodes
+    unsigned            Value  : 2;    // the value of the nodes
+    unsigned            fUsed  : 1;    // the flag indicating that the node is used in the mapping
+    unsigned            fTemp  : 1;    // unused
+    unsigned            Level  :11;    // the level of the given node
+    unsigned            uData  :14;    // used to mark the fanins, for which resynthesis was tried
+    int                 TravId;
+
+    // the successors of this node     
+    Fpga_Node_t *       p1;            // the first child
+    Fpga_Node_t *       p2;            // the second child
+    Fpga_Node_t *       pNextE;        // the next functionally equivalent node
+    Fpga_Node_t *       pRepr;         // the representative of the functionally equivalent class
+
+#ifdef FPGA_ALLOCATE_FANOUT
+    // representation of node's fanouts
+    Fpga_Node_t *       pFanPivot;     // the first fanout of this node
+    Fpga_Node_t *       pFanFanin1;    // the next fanout of p1
+    Fpga_Node_t *       pFanFanin2;    // the next fanout of p2
+//    Fpga_NodeVec_t *    vFanouts;      // the array of fanouts of the gate
+#endif
+
+    // the delay information
+    float               tRequired;     // the best area flow 
+    float               aEstFanouts;   // the fanout estimation
+    float               Switching;     // the probability of switching
+    int                 LValue;        // the l-value of the node
+    short               nLatches1;     // the number of latches on the first edge
+    short               nLatches2;     // the number of latches on the second edge
+
+    // cut information
+    Fpga_Cut_t *        pCutBest;      // the best mapping
+    Fpga_Cut_t *        pCutOld;       // the old mapping
+    Fpga_Cut_t *        pCuts;         // mapping choices for the node (elementary comes first)
+    Fpga_Cut_t *        pCutsN;        // mapping choices for the node (elementary comes first)
+
+    // misc information  
+    char *              pData0;        // temporary storage for the corresponding network node
+}; 
+  
+// the cuts used for matching
+struct Fpga_CutStruct_t_  
+{
+    Fpga_Cut_t *        pOne;          // the father of this cut
+    Fpga_Cut_t *        pTwo;          // the mother of this cut
+    Fpga_Node_t *       pRoot;         // the root of the cut
+    Fpga_Node_t *       ppLeaves[FPGA_MAX_LEAVES+1];   // the leaves of this cut
+    float               fLevel;        // the average level of the fanins
+    unsigned            uSign;         // signature for quick comparison
+    char                fMark;         // the mark to denote visited cut
+    char                Phase;         // the mark to denote complemented cut
+    char                nLeaves;       // the number of leaves of this cut
+    char                nVolume;       // the volume of this cut
+    float               tArrival;      // the arrival time 
+    float               aFlow;         // the area flow of the cut
+    Fpga_Cut_t *        pNext;         // the pointer to the next cut in the list
+};
+
+// the vector of nodes
+struct Fpga_NodeVecStruct_t_
+{
+    Fpga_Node_t **      pArray;        // the array of nodes
+    int                 nSize;         // the number of entries in the array
+    int                 nCap;          // the number of allocated entries
+};
+
+// getting hold of the next fanout of the node
+#define Fpga_NodeReadNextFanout( pNode, pFanout )                \
+    ( ( pFanout == NULL )? NULL :                                \
+        ((Fpga_Regular((pFanout)->p1) == (pNode))?               \
+             (pFanout)->pFanFanin1 : (pFanout)->pFanFanin2) )
+
+// getting hold of the place where the next fanout will be attached
+#define Fpga_NodeReadNextFanoutPlace( pNode, pFanout )           \
+    ( (Fpga_Regular((pFanout)->p1) == (pNode))?                  \
+         &(pFanout)->pFanFanin1 : &(pFanout)->pFanFanin2 )
+
+// iterator through the fanouts of the node
+#define Fpga_NodeForEachFanout( pNode, pFanout )                 \
+    for ( pFanout = (pNode)->pFanPivot; pFanout;                 \
+          pFanout = Fpga_NodeReadNextFanout(pNode, pFanout) )
+
+// safe iterator through the fanouts of the node
+#define Fpga_NodeForEachFanoutSafe( pNode, pFanout, pFanout2 )   \
+    for ( pFanout  = (pNode)->pFanPivot,                         \
+          pFanout2 = Fpga_NodeReadNextFanout(pNode, pFanout);    \
+          pFanout;                                               \
+          pFanout  = pFanout2,                                   \
+          pFanout2 = Fpga_NodeReadNextFanout(pNode, pFanout) )
+
+static inline int Fpga_FloatMoreThan( Fpga_Man_t * p, float Arg1, float Arg2 ) { return Arg1 > Arg2 + p->fEpsilon; }
+static inline int Fpga_FloatLessThan( Fpga_Man_t * p, float Arg1, float Arg2 ) { return Arg1 < Arg2 - p->fEpsilon; }
+static inline int Fpga_FloatEqual( Fpga_Man_t * p, float Arg1, float Arg2 )    { return Arg1 > Arg2 - p->fEpsilon && Arg1 < Arg2 + p->fEpsilon; }
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== fpgaCut.c ===============================================================*/
+extern void              Fpga_MappingCuts( Fpga_Man_t * p );
+extern void              Fpga_MappingCreatePiCuts( Fpga_Man_t * p );
+extern int               Fpga_CutCountAll( Fpga_Man_t * pMan );
+/*=== fpgaCutUtils.c ===============================================================*/
+extern Fpga_Cut_t *      Fpga_CutAlloc( Fpga_Man_t * p );
+extern Fpga_Cut_t *      Fpga_CutDup( Fpga_Man_t * p, Fpga_Cut_t * pCutOld );
+extern void              Fpga_CutFree( Fpga_Man_t * p, Fpga_Cut_t * pCut );
+extern void              Fpga_CutPrint( Fpga_Man_t * p, Fpga_Node_t * pRoot, Fpga_Cut_t * pCut );
+extern Fpga_Cut_t *      Fpga_CutCreateSimple( Fpga_Man_t * p, Fpga_Node_t * pNode );
+extern float             Fpga_CutGetRootArea( Fpga_Man_t * p, Fpga_Cut_t * pCut );
+extern Fpga_Cut_t *      Fpga_CutListAppend( Fpga_Cut_t * pSetAll, Fpga_Cut_t * pSets );
+extern void              Fpga_CutListRecycle( Fpga_Man_t * p, Fpga_Cut_t * pSetList, Fpga_Cut_t * pSave );
+extern int               Fpga_CutListCount( Fpga_Cut_t * pSets );
+extern void              Fpga_CutRemoveFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut );
+extern void              Fpga_CutInsertFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut );
+extern float             Fpga_CutGetAreaRefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut );
+extern float             Fpga_CutGetAreaDerefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut );
+extern float             Fpga_CutRef( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts );
+extern float             Fpga_CutDeref( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts );
+extern float             Fpga_CutGetAreaFlow( Fpga_Man_t * pMan, Fpga_Cut_t * pCut );
+extern void              Fpga_CutGetParameters( Fpga_Man_t * pMan, Fpga_Cut_t * pCut );
+/*=== fraigFanout.c =============================================================*/
+extern void              Fpga_NodeAddFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanout );
+extern void              Fpga_NodeRemoveFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanoutToRemove );
+extern int               Fpga_NodeGetFanoutNum( Fpga_Node_t * pNode );
+/*=== fpgaLib.c ============================================================*/
+extern Fpga_LutLib_t *   Fpga_LutLibRead( char * FileName, int fVerbose );
+extern void              Fpga_LutLibFree( Fpga_LutLib_t * p );
+extern void              Fpga_LutLibPrint( Fpga_LutLib_t * pLutLib );
+extern int               Fpga_LutLibDelaysAreDiscrete( Fpga_LutLib_t * pLutLib );
+/*=== fpgaMatch.c ===============================================================*/
+extern int               Fpga_MappingMatches( Fpga_Man_t * p, int fDelayOriented );
+extern int               Fpga_MappingMatchesArea( Fpga_Man_t * p );
+extern int               Fpga_MappingMatchesSwitch( Fpga_Man_t * p );
+/*=== fpgaShow.c =============================================================*/
+extern void              Fpga_MappingShow( Fpga_Man_t * pMan, char * pFileName );
+extern void              Fpga_MappingShowNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppRoots, int nRoots, char * pFileName );
+/*=== fpgaSwitch.c =============================================================*/
+extern float             Fpga_CutGetSwitchDerefed( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut );
+extern float             Fpga_CutRefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts );
+extern float             Fpga_CutDerefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts );
+extern float             Fpga_MappingGetSwitching( Fpga_Man_t * pMan, Fpga_NodeVec_t * vMapping );
+/*=== fpgaTime.c ===============================================================*/
+extern float             Fpga_TimeCutComputeArrival( Fpga_Man_t * pMan, Fpga_Cut_t * pCut );
+extern float             Fpga_TimeCutComputeArrival_rec( Fpga_Man_t * pMan, Fpga_Cut_t * pCut );
+extern float             Fpga_TimeComputeArrivalMax( Fpga_Man_t * p );
+extern void              Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p, int fFirstTime );
+extern void              Fpga_TimeComputeRequired( Fpga_Man_t * p, float fRequired );
+extern void              Fpga_TimePropagateRequired( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes );
+extern void              Fpga_TimePropagateArrival( Fpga_Man_t * p );
+/*=== fpgaVec.c =============================================================*/
+extern Fpga_NodeVec_t *  Fpga_NodeVecAlloc( int nCap );
+extern void              Fpga_NodeVecFree( Fpga_NodeVec_t * p );
+extern Fpga_Node_t **    Fpga_NodeVecReadArray( Fpga_NodeVec_t * p );
+extern int               Fpga_NodeVecReadSize( Fpga_NodeVec_t * p );
+extern void              Fpga_NodeVecGrow( Fpga_NodeVec_t * p, int nCapMin );
+extern void              Fpga_NodeVecShrink( Fpga_NodeVec_t * p, int nSizeNew );
+extern void              Fpga_NodeVecClear( Fpga_NodeVec_t * p );
+extern void              Fpga_NodeVecPush( Fpga_NodeVec_t * p, Fpga_Node_t * Entry );
+extern int               Fpga_NodeVecPushUnique( Fpga_NodeVec_t * p, Fpga_Node_t * Entry );
+extern Fpga_Node_t *     Fpga_NodeVecPop( Fpga_NodeVec_t * p );
+extern void              Fpga_NodeVecWriteEntry( Fpga_NodeVec_t * p, int i, Fpga_Node_t * Entry );
+extern Fpga_Node_t *     Fpga_NodeVecReadEntry( Fpga_NodeVec_t * p, int i );
+extern void              Fpga_NodeVecSortByLevel( Fpga_NodeVec_t * p );
+extern void              Fpga_SortNodesByArrivalTimes( Fpga_NodeVec_t * p );
+extern void              Fpga_NodeVecUnion( Fpga_NodeVec_t * p, Fpga_NodeVec_t * p1, Fpga_NodeVec_t * p2 );
+extern void              Fpga_NodeVecPushOrder( Fpga_NodeVec_t * vNodes, Fpga_Node_t * pNode, int fIncreasing );
+extern void              Fpga_NodeVecReverse( Fpga_NodeVec_t * vNodes );
+
+/*=== fpgaUtils.c ===============================================================*/
+extern Fpga_NodeVec_t *  Fpga_MappingDfs( Fpga_Man_t * pMan, int fCollectEquiv );
+extern Fpga_NodeVec_t *  Fpga_MappingDfsNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppNodes, int nNodes, int fEquiv );
+extern int               Fpga_CountLevels( Fpga_Man_t * pMan );
+extern float             Fpga_MappingGetAreaFlow( Fpga_Man_t * p );
+extern float             Fpga_MappingArea( Fpga_Man_t * pMan );
+extern float             Fpga_MappingAreaTrav( Fpga_Man_t * pMan );
+extern float             Fpga_MappingSetRefsAndArea( Fpga_Man_t * pMan );
+extern void              Fpga_MappingPrintOutputArrivals( Fpga_Man_t * p );
+extern void              Fpga_MappingSetupTruthTables( unsigned uTruths[][2] );
+extern void              Fpga_MappingSetupMask( unsigned uMask[], int nVarsMax );
+extern void              Fpga_MappingSortByLevel( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes, int fIncreasing );
+extern Fpga_NodeVec_t *  Fpga_DfsLim( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int nLevels );
+extern Fpga_NodeVec_t *  Fpga_MappingLevelize( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes );
+extern int               Fpga_MappingMaxLevel( Fpga_Man_t * pMan );
+extern void              Fpga_ManReportChoices( Fpga_Man_t * pMan );
+extern void              Fpga_MappingSetChoiceLevels( Fpga_Man_t * pMan );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/map/fpga/fpgaLib.c b/abc-build/src/map/fpga/fpgaLib.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/fpga/fpgaLib.c
@@ -0,0 +1,255 @@
+/**CFile****************************************************************
+
+  FileName    [fpgaLib.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Technology mapping for variable-size-LUT FPGAs.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - August 18, 2004.]
+
+  Revision    [$Id: fpgaLib.c,v 1.4 2005/01/23 06:59:41 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [APIs to access LUT library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int         Fpga_LutLibReadVarMax( Fpga_LutLib_t * p )               { return p->LutMax;     }
+float *     Fpga_LutLibReadLutAreas( Fpga_LutLib_t * p )             { return p->pLutAreas;  }
+float       Fpga_LutLibReadLutArea( Fpga_LutLib_t * p, int Size )    { assert( Size <= p->LutMax ); return p->pLutAreas[Size];  }
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the description of LUTs from the LUT library file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_LutLib_t * Fpga_LutLibRead( char * FileName, int fVerbose )
+{
+    char pBuffer[1000], * pToken;
+    Fpga_LutLib_t * p;
+    FILE * pFile;
+    int i, k;
+
+    pFile = fopen( FileName, "r" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open LUT library file \"%s\".\n", FileName );
+        return NULL;
+    }
+
+    p = ABC_ALLOC( Fpga_LutLib_t, 1 );
+    memset( p, 0, sizeof(Fpga_LutLib_t) );
+    p->pName = Extra_UtilStrsav( FileName );
+
+    i = 1;
+    while ( fgets( pBuffer, 1000, pFile ) != NULL )
+    {
+        pToken = strtok( pBuffer, " \t\n" );
+        if ( pToken == NULL )
+            continue;
+        if ( pToken[0] == '#' )
+            continue;
+        if ( i != atoi(pToken) )
+        {
+            printf( "Error in the LUT library file \"%s\".\n", FileName );
+            ABC_FREE( p );
+            return NULL;
+        }
+
+        // read area
+        pToken = strtok( NULL, " \t\n" );
+        p->pLutAreas[i] = (float)atof(pToken);
+
+        // read delays
+        k = 0;
+        while ( (pToken = strtok( NULL, " \t\n" )) )
+            p->pLutDelays[i][k++] = (float)atof(pToken);
+
+        // check for out-of-bound
+        if ( k > i )
+        {
+            printf( "LUT %d has too many pins (%d). Max allowed is %d.\n", i, k, i );
+            return NULL;
+        }
+
+        // check if var delays are specifies
+        if ( k > 1 )
+            p->fVarPinDelays = 1;
+
+        if ( i == FPGA_MAX_LUTSIZE )
+        {
+            printf( "Skipping LUTs of size more than %d.\n", i );
+            return NULL;
+        }
+        i++;
+    }
+    p->LutMax = i-1;
+/*
+    if ( p->LutMax > FPGA_MAX_LEAVES )
+    {
+        p->LutMax = FPGA_MAX_LEAVES;
+        printf( "Warning: LUTs with more than %d inputs will not be used.\n", FPGA_MAX_LEAVES );
+    }
+*/
+    // check the library
+    if ( p->fVarPinDelays )
+    {
+        for ( i = 1; i <= p->LutMax; i++ )
+            for ( k = 0; k < i; k++ )
+            {
+                if ( p->pLutDelays[i][k] <= 0.0 )
+                    printf( "Warning: Pin %d of LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n", 
+                        k, i, p->pLutDelays[i][k] );
+                if ( k && p->pLutDelays[i][k-1] > p->pLutDelays[i][k] )
+                    printf( "Warning: Pin %d of LUT %d has delay %f. Pin %d of LUT %d has delay %f. Pin delays should be in non-decreasing order. Technology mapping may not work correctly.\n", 
+                        k-1, i, p->pLutDelays[i][k-1], 
+                        k, i, p->pLutDelays[i][k] );
+            }
+    }
+    else
+    {
+        for ( i = 1; i <= p->LutMax; i++ )
+        {
+            if ( p->pLutDelays[i][0] <= 0.0 )
+                printf( "Warning: LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n", 
+                    i, p->pLutDelays[i][0] );
+        }
+    }
+
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the LUT library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_LutLib_t * Fpga_LutLibDup( Fpga_LutLib_t * p )
+{
+    Fpga_LutLib_t * pNew;
+    pNew = ABC_ALLOC( Fpga_LutLib_t, 1 );
+    *pNew = *p;
+    pNew->pName = Extra_UtilStrsav( pNew->pName );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the LUT library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_LutLibFree( Fpga_LutLib_t * pLutLib )
+{
+    if ( pLutLib == NULL )
+        return;
+    ABC_FREE( pLutLib->pName );
+    ABC_FREE( pLutLib );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the LUT library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_LutLibPrint( Fpga_LutLib_t * pLutLib )
+{
+    int i, k;
+    printf( "# The area/delay of k-variable LUTs:\n" );
+    printf( "# k    area     delay\n" );
+    if ( pLutLib->fVarPinDelays )
+    {
+        for ( i = 1; i <= pLutLib->LutMax; i++ )
+        {
+            printf( "%d   %7.2f  ", i, pLutLib->pLutAreas[i] );
+            for ( k = 0; k < i; k++ )
+                printf( " %7.2f", pLutLib->pLutDelays[i][k] );
+            printf( "\n" );
+        }
+    }
+    else
+        for ( i = 1; i <= pLutLib->LutMax; i++ )
+            printf( "%d   %7.2f   %7.2f\n", i, pLutLib->pLutAreas[i], pLutLib->pLutDelays[i][0] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the delays are discrete.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_LutLibDelaysAreDiscrete( Fpga_LutLib_t * pLutLib )
+{
+    float Delay;
+    int i;
+    for ( i = 1; i <= pLutLib->LutMax; i++ )
+    {
+        Delay = pLutLib->pLutDelays[i][0];
+        if ( ((float)((int)Delay)) != Delay )
+            return 0;
+    }
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/fpga/fpgaMatch.c b/abc-build/src/map/fpga/fpgaMatch.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/fpga/fpgaMatch.c
@@ -0,0 +1,800 @@
+/**CFile****************************************************************
+
+  FileName    [fpgaMatch.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Technology mapping for variable-size-LUT FPGAs.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - August 18, 2004.]
+
+  Revision    [$Id: fpgaMatch.c,v 1.7 2004/09/30 21:18:10 satrajit Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int          Fpga_MatchNode( Fpga_Man_t * p, Fpga_Node_t * pNode, int fDelayOriented );
+static int          Fpga_MatchNodeArea( Fpga_Man_t * p, Fpga_Node_t * pNode );
+static int          Fpga_MatchNodeSwitch( Fpga_Man_t * p, Fpga_Node_t * pNode );
+
+static Fpga_Cut_t * Fpga_MappingAreaWithoutNode( Fpga_Man_t * p, Fpga_Node_t * pFanout, Fpga_Node_t * pNodeNo );
+static int          Fpga_MappingMatchesAreaArray( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the best delay assignment of LUTs.]
+
+  Description [This procedure iterates through all the nodes
+  of the object graph reachable from the POs and assigns the best
+  match to each of them. If the flag fDelayOriented is set to 1, it 
+  tries to minimize the arrival time and uses the area flow as a
+  tie-breaker. If the flag is set to 0, it considers all the cuts,
+  whose arrival times matches the required time at the node, and
+  minimizes the area flow using the arrival time as a tie-breaker.
+  
+  Before this procedure is called, the required times should be set
+  and the fanout counts should be computed. In the first iteration,
+  the required times are set to very large number (by NodeCreate) 
+  and the fanout counts are set to the number of fanouts in the AIG.
+  In the following iterations, the required times are set by the
+  backward traversal, while the fanouts are estimated approximately.
+  
+  If the arrival times of the PI nodes are given, they should be 
+  assigned to the PIs after the cuts are computed and before this
+  procedure is called for the first time.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_MappingMatches( Fpga_Man_t * p, int fDelayOriented )
+{
+    ProgressBar * pProgress;
+    Fpga_Node_t * pNode;
+    int i, nNodes;
+    
+    // assign the arrival times of the PIs
+    for ( i = 0; i < p->nInputs; i++ )
+        p->pInputs[i]->pCutBest->tArrival = p->pInputArrivals[i];
+
+    // match LUTs with nodes in the topological order
+    nNodes = p->vAnds->nSize;
+    pProgress = Extra_ProgressBarStart( stdout, nNodes );
+    for ( i = 0; i < nNodes; i++ )
+    {
+        pNode = p->vAnds->pArray[i];
+        if ( !Fpga_NodeIsAnd( pNode ) )
+            continue;
+        // skip a secondary node
+        if ( pNode->pRepr )
+            continue;
+        // match the node
+        Fpga_MatchNode( p, pNode, fDelayOriented );
+        Extra_ProgressBarUpdate( pProgress, i, "Matches ..." );
+    }
+    Extra_ProgressBarStop( pProgress );
+/*
+    if ( !fDelayOriented )
+    {
+        float Area = 0.0;
+        for ( i = 0; i < p->nOutputs; i++ )
+        {
+            printf( "%5.2f ", Fpga_Regular(p->pOutputs[i])->pCutBest->aFlow );
+            Area += Fpga_Regular(p->pOutputs[i])->pCutBest->aFlow;
+        }
+        printf( "\nTotal = %5.2f\n", Area );
+    }
+*/
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the best matching for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_MatchNode( Fpga_Man_t * p, Fpga_Node_t * pNode, int fDelayOriented )
+{
+    Fpga_Cut_t * pCut, * pCutBestOld;
+    clock_t clk;
+    // make sure that at least one cut other than the trivial is present
+    if ( pNode->pCuts->pNext == NULL )
+    {
+        printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" );
+        return 0;
+    }
+
+    // estimate the fanouts of the node
+    if ( pNode->aEstFanouts < 0 )
+        pNode->aEstFanouts = (float)pNode->nRefs;
+    else
+        pNode->aEstFanouts = (float)((2.0 * pNode->aEstFanouts + pNode->nRefs) / 3.0);
+//        pNode->aEstFanouts = (float)pNode->nRefs;
+
+    pCutBestOld = pNode->pCutBest;
+    pNode->pCutBest = NULL;
+    for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+    {
+        // compute the arrival time of the cut and its area flow
+clk = clock();
+        Fpga_CutGetParameters( p, pCut );
+//p->time2 += clock() - clk;
+        // drop the cut if it does not meet the required times
+        if ( Fpga_FloatMoreThan(p, pCut->tArrival, pNode->tRequired) )
+            continue;
+        // if no cut is assigned, use the current one
+        if ( pNode->pCutBest == NULL )
+        {
+            pNode->pCutBest = pCut;
+            continue;
+        }
+        // choose the best cut using one of the two criteria:
+        // (1) delay oriented mapping (first traversal), delay first, area-flow as a tie-breaker
+        // (2) area recovery (subsequent traversals), area-flow first, delay as a tie-breaker
+        if ( (fDelayOriented && 
+               (Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival) || 
+                (Fpga_FloatEqual(p, pNode->pCutBest->tArrival, pCut->tArrival) && Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow)) )) ||
+             (!fDelayOriented && 
+               (Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) || 
+                (Fpga_FloatEqual(p, pNode->pCutBest->aFlow, pCut->aFlow) && Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival))))  )
+        {
+            pNode->pCutBest = pCut;
+        }
+    }
+
+    // make sure the match is found
+    if ( pNode->pCutBest == NULL )
+    {
+        if ( pCutBestOld == NULL )
+        {
+//            printf( "\nError: Could not match a node in the object graph.\n" );
+            return 0;
+        }
+        pNode->pCutBest = pCutBestOld;
+    }
+    return 1;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the best area assignment of LUTs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_MappingMatchesArea( Fpga_Man_t * p )
+{
+    ProgressBar * pProgress;
+    Fpga_Node_t * pNode;
+    int i, nNodes;
+    
+    // assign the arrival times of the PIs
+    for ( i = 0; i < p->nInputs; i++ )
+        p->pInputs[i]->pCutBest->tArrival = p->pInputArrivals[i];
+
+    // match LUTs with nodes in the topological order
+    nNodes = p->vAnds->nSize;
+    pProgress = Extra_ProgressBarStart( stdout, nNodes );
+    for ( i = 0; i < nNodes; i++ )
+    {
+        pNode = p->vAnds->pArray[i];
+        if ( !Fpga_NodeIsAnd( pNode ) )
+            continue;
+        // skip a secondary node
+        if ( pNode->pRepr )
+            continue;
+        // match the node
+        Fpga_MatchNodeArea( p, pNode );
+        Extra_ProgressBarUpdate( pProgress, i, "Matches ..." );
+    }
+    Extra_ProgressBarStop( pProgress );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the best area assignment of LUTs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_MappingMatchesAreaArray( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes )
+{
+    Fpga_Node_t * pNode;
+    int i;
+
+    // match LUTs with nodes in the topological order
+    for ( i = 0; i < vNodes->nSize; i++ )
+    {
+        pNode = vNodes->pArray[i];
+        if ( !Fpga_NodeIsAnd( pNode ) )
+            continue;
+        // skip a secondary node
+        if ( pNode->pRepr )
+            continue;
+        // match the node
+        if ( !Fpga_MatchNodeArea( p, pNode ) )
+            return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the best matching for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_MatchNodeArea( Fpga_Man_t * p, Fpga_Node_t * pNode )
+{
+    Fpga_Cut_t * pCut, * pCutBestOld;
+    float aAreaCutBest;
+    clock_t clk;
+    // make sure that at least one cut other than the trivial is present
+    if ( pNode->pCuts->pNext == NULL )
+    {
+        printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" );
+        return 0;
+    }
+
+    // remember the old cut
+    pCutBestOld = pNode->pCutBest;
+    // deref the old cut
+    if ( pNode->nRefs ) 
+        aAreaCutBest = Fpga_CutDeref( p, pNode, pNode->pCutBest, 0 );
+
+    // search for a better cut
+    pNode->pCutBest = NULL;
+    for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+    {
+        // compute the arrival time of the cut and its area flow
+clk = clock();
+        pCut->tArrival = Fpga_TimeCutComputeArrival( p, pCut );
+//p->time2 += clock() - clk;
+        // drop the cut if it does not meet the required times
+        if ( Fpga_FloatMoreThan( p, pCut->tArrival, pNode->tRequired ) )
+            continue;
+        // get the area of this cut
+        pCut->aFlow = Fpga_CutGetAreaDerefed( p, pCut );
+        // if no cut is assigned, use the current one
+        if ( pNode->pCutBest == NULL )
+        {
+            pNode->pCutBest = pCut;
+            continue;
+        }
+        // choose the best cut as follows: exact area first, delay as a tie-breaker
+        if ( Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) || 
+             (Fpga_FloatEqual(p, pNode->pCutBest->aFlow, pCut->aFlow) && Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival)) )
+        {
+            pNode->pCutBest = pCut;
+        }
+    }
+
+    // make sure the match is found
+    if ( pNode->pCutBest == NULL )
+    {
+        pNode->pCutBest = pCutBestOld; 
+        // insert the new cut
+        if ( pNode->nRefs ) 
+            pNode->pCutBest->aFlow = Fpga_CutRef( p, pNode, pNode->pCutBest, 0 );
+//        printf( "\nError: Could not match a node in the object graph.\n" );
+        return 0;
+    }
+
+    // insert the new cut
+    // make sure the area selected is not worse then the original area
+    if ( pNode->nRefs ) 
+    {
+        pNode->pCutBest->aFlow = Fpga_CutRef( p, pNode, pNode->pCutBest, 0 );
+//        assert( pNode->pCutBest->aFlow <= aAreaCutBest );
+//        assert( pNode->tRequired < FPGA_FLOAT_LARGE );
+    }
+    return 1;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the best area assignment of LUTs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_MappingMatchesSwitch( Fpga_Man_t * p )
+{
+    ProgressBar * pProgress;
+    Fpga_Node_t * pNode;
+    int i, nNodes;
+    
+    // assign the arrival times of the PIs
+    for ( i = 0; i < p->nInputs; i++ )
+        p->pInputs[i]->pCutBest->tArrival = p->pInputArrivals[i];
+
+    // match LUTs with nodes in the topological order
+    nNodes = p->vAnds->nSize;
+    pProgress = Extra_ProgressBarStart( stdout, nNodes );
+    for ( i = 0; i < nNodes; i++ )
+    {
+        pNode = p->vAnds->pArray[i];
+        if ( !Fpga_NodeIsAnd( pNode ) )
+            continue;
+        // skip a secondary node
+        if ( pNode->pRepr )
+            continue;
+        // match the node
+        Fpga_MatchNodeSwitch( p, pNode );
+        Extra_ProgressBarUpdate( pProgress, i, "Matches ..." );
+    }
+    Extra_ProgressBarStop( pProgress );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the best matching for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_MatchNodeSwitch( Fpga_Man_t * p, Fpga_Node_t * pNode )
+{
+    Fpga_Cut_t * pCut, * pCutBestOld;
+    float aAreaCutBest = FPGA_FLOAT_LARGE;
+    clock_t clk;
+    // make sure that at least one cut other than the trivial is present
+    if ( pNode->pCuts->pNext == NULL )
+    {
+        printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" );
+        return 0;
+    }
+
+    // remember the old cut
+    pCutBestOld = pNode->pCutBest;
+    // deref the old cut
+    if ( pNode->nRefs ) 
+        aAreaCutBest = Fpga_CutDerefSwitch( p, pNode, pNode->pCutBest, 0 );
+
+    // search for a better cut
+    pNode->pCutBest = NULL;
+    for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+    {
+        // compute the arrival time of the cut and its area flow
+clk = clock();
+        pCut->tArrival = Fpga_TimeCutComputeArrival( p, pCut );
+//p->time2 += clock() - clk;
+        // drop the cut if it does not meet the required times
+        if ( Fpga_FloatMoreThan( p, pCut->tArrival, pNode->tRequired ) )
+            continue;
+        // get the area of this cut
+        pCut->aFlow = Fpga_CutGetSwitchDerefed( p, pNode, pCut );
+        // if no cut is assigned, use the current one
+        if ( pNode->pCutBest == NULL )
+        {
+            pNode->pCutBest = pCut;
+            continue;
+        }
+        // choose the best cut as follows: exact area first, delay as a tie-breaker
+        if ( Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) || 
+             (Fpga_FloatEqual(p, pNode->pCutBest->aFlow, pCut->aFlow) && Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival)) )
+        {
+            pNode->pCutBest = pCut;
+        }
+    }
+
+    // make sure the match is found
+    if ( pNode->pCutBest == NULL )
+    {
+        pNode->pCutBest = pCutBestOld; 
+        // insert the new cut
+        if ( pNode->nRefs ) 
+            pNode->pCutBest->aFlow = Fpga_CutRefSwitch( p, pNode, pNode->pCutBest, 0 );
+//        printf( "\nError: Could not match a node in the object graph.\n" );
+        return 0;
+    }
+
+    // insert the new cut
+    // make sure the area selected is not worse then the original area
+    if ( pNode->nRefs ) 
+    {
+        pNode->pCutBest->aFlow = Fpga_CutRefSwitch( p, pNode, pNode->pCutBest, 0 );
+        assert( pNode->pCutBest->aFlow <= aAreaCutBest + 0.001 );
+//        assert( pNode->tRequired < FPGA_FLOAT_LARGE );
+    }
+    return 1;
+}
+
+
+#if 0
+/**function*************************************************************
+
+  synopsis    [References the cut.]
+
+  description [This procedure is similar to the procedure NodeReclaim.]
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+void Fpga_Experiment( Fpga_Man_t * p )
+{
+    int Counter[10] = {0};
+    Fpga_Node_t * pNode;
+    int i;
+
+    for ( i = 0; i < p->nOutputs; i++ )
+    {
+        pNode = Fpga_Regular(p->pOutputs[i]);
+        pNode->vFanouts = NULL;
+    }
+
+    for ( i = 0; i < p->vAnds->nSize; i++ )
+    {
+        pNode = p->vAnds->pArray[i];
+        if ( !Fpga_NodeIsAnd( pNode ) )
+            continue;
+        if ( pNode->vFanouts == NULL )
+            continue;
+        if ( pNode->vFanouts->nSize >= 10 )
+            continue;
+        Counter[pNode->vFanouts->nSize]++;
+    }
+
+    printf( "Fanout stats: " );
+    for ( i = 0; i < 10; i++ )
+        printf( " %d=%d", i, Counter[i] );
+    printf( "\n" );
+    printf( "Area before = %4.2f.\n", Fpga_MappingArea(p) );
+
+    for ( i = 0; i < p->vAnds->nSize; i++ )
+    {
+        Fpga_NodeVec_t * vNodesTfo;
+        float AreaBefore;
+
+        pNode = p->vAnds->pArray[i];
+        if ( !Fpga_NodeIsAnd( pNode ) )
+            continue;
+        if ( pNode->vFanouts == NULL )
+            continue;
+        if ( pNode->vFanouts->nSize != 1 && pNode->vFanouts->nSize != 2 && pNode->vFanouts->nSize != 3 )
+            continue;
+
+//        assert( pNode->nRefs > 0 );
+        if ( pNode->nRefs == 0 )
+            continue;
+
+        AreaBefore = pNode->pCutBest->aFlow;
+        pNode->pCutBest->aFlow = FPGA_FLOAT_LARGE;
+
+        Fpga_TimeComputeRequiredGlobal( p, 0 );
+
+        vNodesTfo = Fpga_CollectNodeTfo( p, pNode );
+        if ( Fpga_MappingMatchesAreaArray( p, vNodesTfo ) == 0 )
+            printf( "attempt failed\n" );
+        else
+            printf( "attempt succeeded\n" );
+        Fpga_NodeVecFree( vNodesTfo );
+
+        pNode->pCutBest->aFlow = AreaBefore;
+//        break;
+    }
+    printf( "Area after = %4.2f.\n", Fpga_MappingArea(p) );
+//    printf( "AREA GAIN = %4.2f (%.2f %%)\n", GainTotal, 100.0 * GainTotal / Fpga_MappingArea(p) );
+}
+
+
+
+/**function*************************************************************
+
+  synopsis    [References the cut.]
+
+  description [This procedure is similar to the procedure NodeReclaim.]
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+void Fpga_Experiment2( Fpga_Man_t * p )
+{
+    int Counter[10] = {0};
+    Fpga_Cut_t * ppCutsNew[10];
+    Fpga_Cut_t * ppCutsOld[10];
+    Fpga_Node_t * pFanout, * pNode;
+    float Gain, Loss, GainTotal,  Area1, Area2;
+    int i, k;
+
+    for ( i = 0; i < p->nOutputs; i++ )
+    {
+        pNode = Fpga_Regular(p->pOutputs[i]);
+        pNode->vFanouts = NULL;
+    }
+
+    for ( i = 0; i < p->vAnds->nSize; i++ )
+    {
+        pNode = p->vAnds->pArray[i];
+        if ( !Fpga_NodeIsAnd( pNode ) )
+            continue;
+        if ( pNode->vFanouts == NULL )
+            continue;
+        if ( pNode->vFanouts->nSize >= 10 )
+            continue;
+        Counter[pNode->vFanouts->nSize]++;
+    }
+
+    printf( "Fanout stats: " );
+    for ( i = 0; i < 10; i++ )
+        printf( " %d=%d", i, Counter[i] );
+    printf( "\n" );
+    printf( "Area before = %4.2f.\n", Fpga_MappingArea(p) );
+
+    GainTotal = 0;
+    for ( i = 0; i < p->vAnds->nSize; i++ )
+    {
+        pNode = p->vAnds->pArray[i];
+        if ( !Fpga_NodeIsAnd( pNode ) )
+            continue;
+        if ( pNode->vFanouts == NULL )
+            continue;
+        if ( pNode->vFanouts->nSize != 2 )//&& pNode->vFanouts->nSize != 2 && pNode->vFanouts->nSize != 3 )
+            continue;
+
+        assert( pNode->nRefs > 0 );
+
+        // for all fanouts, find the best cut without this node
+        for ( k = 0; k < pNode->vFanouts->nSize; k++ )
+        {
+            pFanout = pNode->vFanouts->pArray[k];
+            ppCutsOld[k] = pFanout->pCutBest;
+            ppCutsNew[k] = Fpga_MappingAreaWithoutNode( p, pFanout, pNode );
+            if ( ppCutsNew[k] == NULL )
+                break;
+        }
+        if ( k != pNode->vFanouts->nSize )
+        {
+            printf( "Node %4d: Skipped.\n", pNode->Num );
+            continue;
+        }
+
+
+        // compute the area after replacing all the cuts
+        Gain = 0;
+        for ( k = 0; k < pNode->vFanouts->nSize; k++ )
+        {
+            pFanout = pNode->vFanouts->pArray[k];
+            // deref old cut
+            Area1 = Fpga_MatchAreaDeref( p, ppCutsOld[k] );
+            // assign new cut
+            pFanout->pCutBest = ppCutsNew[k];
+            // ref new cut
+            Area2 = Fpga_MatchAreaRef( p, ppCutsNew[k] );
+            // compute the gain
+            Gain += Area1 - Area2;
+        }
+
+        printf( "%d ", pNode->nRefs );
+
+        // undo the whole thing
+        Loss = 0;
+        for ( k = 0; k < pNode->vFanouts->nSize; k++ )
+        {
+            pFanout = pNode->vFanouts->pArray[k];
+            // deref old cut
+            Area1 = Fpga_MatchAreaDeref( p, ppCutsNew[k] );
+            // assign new cut
+            pFanout->pCutBest = ppCutsOld[k];
+            // ref new cut
+            Area2 = Fpga_MatchAreaRef( p, ppCutsOld[k] );
+            // compute the gain
+            Loss += Area2 - Area1;
+        }
+        assert( Gain == Loss );
+
+
+        printf( "Node %4d: Fanouts = %d. Cut area = %4.2f. Gain = %4.2f.\n", 
+            pNode->Num, pNode->nRefs, pNode->pCutBest->aFlow, Gain );
+
+        if ( Gain > 0 )
+            GainTotal += Gain;
+    }
+    printf( "Area after = %4.2f.\n", Fpga_MappingArea(p) );
+    printf( "AREA GAIN = %4.2f (%.2f %%)\n", GainTotal, 100.0 * GainTotal / Fpga_MappingArea(p) );
+}
+
+
+/**function*************************************************************
+
+  synopsis    [Computes the loss of area when node is not allowed.]
+
+  description [Returning FPGA_FLOAT_LARGE means it does not exist.]
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_MappingAreaWithoutNode( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Node_t * pNodeNo )
+{
+    Fpga_Cut_t * pCut, * pCutBestOld, * pCutRes;
+    float aAreaCutBest;
+    int i;
+    clock_t clk;
+    // make sure that at least one cut other than the trivial is present
+    if ( pNode->pCuts->pNext == NULL )
+    {
+        printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" );
+        return 0;
+    }
+
+    assert( pNode->nRefs > 0 );
+
+    // remember the old cut
+    pCutBestOld = pNode->pCutBest;
+    // deref the old cut
+    aAreaCutBest = Fpga_MatchAreaDeref( p, pNode->pCutBest );
+
+    // search for a better cut
+    pNode->pCutBest = NULL;
+    for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+    {
+        // compute the arrival time of the cut and its area flow
+clk = clock();
+        Fpga_MatchCutGetArrTime( p, pCut );
+//p->time2 += clock() - clk;
+        // drop the cut if it does not meet the required times
+        if ( pCut->tArrival > pNode->tRequired )
+            continue;
+
+        // skip the cut if it contains the no-node
+        for ( i = 0; i < pCut->nLeaves; i++ )
+            if ( pCut->ppLeaves[i] == pNodeNo )
+                break;
+        if ( i != pCut->nLeaves )
+            continue;
+
+        // get the area of this cut
+        pCut->aFlow = Fpga_MatchAreaCount( p, pCut );
+        // if no cut is assigned, use the current one
+        if ( pNode->pCutBest == NULL )
+        {
+            pNode->pCutBest = pCut;
+            continue;
+        }
+        // choose the best cut as follows: exact area first, delay as a tie-breaker
+        if ( pNode->pCutBest->aFlow >  pCut->aFlow || 
+             pNode->pCutBest->aFlow == pCut->aFlow && pNode->pCutBest->tArrival > pCut->tArrival  )
+        {
+            pNode->pCutBest = pCut;
+        }
+    }
+
+    // make sure the match is found
+    if ( pNode->pCutBest == NULL )
+    {
+        pNode->pCutBest = pCutBestOld;
+        // insert the new cut
+        pNode->pCutBest->aFlow = Fpga_MatchAreaRef( p, pNode->pCutBest );
+        return NULL;
+    }
+
+    pCutRes = pNode->pCutBest;
+    pNode->pCutBest = pCutBestOld;
+
+    // insert the new cut
+    pNode->pCutBest->aFlow = Fpga_MatchAreaRef( p, pNode->pCutBest );
+
+    // make sure the area selected is not worse then the original area
+    assert( pNode->pCutBest->aFlow == aAreaCutBest );
+    assert( pNode->tRequired < FPGA_FLOAT_LARGE );
+    return pCutRes;
+}
+
+#endif
+
+
+/**function*************************************************************
+
+  synopsis    [Performs area minimization using a heuristic algorithm.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Fpga_FindBestNode( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes, Fpga_Node_t ** ppNode, Fpga_Cut_t ** ppCutBest )
+{
+    Fpga_Node_t * pNode;
+    Fpga_Cut_t * pCut;
+    float Gain, CutArea1, CutArea2, CutArea3;
+    int i;
+
+    Gain = 0;
+    for ( i = 0; i < vNodes->nSize; i++ )
+    {
+        pNode = vNodes->pArray[i];
+        // deref the current cut
+        CutArea1 = Fpga_CutDeref( p, pNode, pNode->pCutBest, 0 );
+
+        // ref all the cuts
+        for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+        {
+            if ( pCut == pNode->pCutBest )
+                continue;
+            if ( pCut->tArrival > pNode->tRequired )
+                continue;
+
+            CutArea2 = Fpga_CutGetAreaDerefed( p, pCut );
+            if ( Gain < CutArea1 - CutArea2 )
+            {
+                *ppNode = pNode;
+                *ppCutBest = pCut;
+                Gain = CutArea1 - CutArea2;
+            }
+        }
+        // ref the old cut
+        CutArea3 = Fpga_CutRef( p, pNode, pNode->pCutBest, 0 );
+        assert( CutArea1 == CutArea3 );
+    }
+    if ( Gain == 0 )
+        printf( "Returning no gain.\n" );
+
+    return Gain;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/fpga/fpgaSwitch.c b/abc-build/src/map/fpga/fpgaSwitch.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/fpga/fpgaSwitch.c
@@ -0,0 +1,156 @@
+/**CFile****************************************************************
+
+  FileName    [fpgaSwitch.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: fpgaSwitch.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**function*************************************************************
+
+  synopsis    [Computes the exact area associated with the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Fpga_CutGetSwitchDerefed( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut )
+{
+    float aResult, aResult2;
+    aResult2 = Fpga_CutRefSwitch( pMan, pNode, pCut, 0 );
+    aResult  = Fpga_CutDerefSwitch( pMan, pNode, pCut, 0 );
+//    assert( aResult == aResult2 );
+    return aResult;
+}
+
+/**function*************************************************************
+
+  synopsis    [References the cut.]
+
+  description [This procedure is similar to the procedure NodeReclaim.]
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Fpga_CutRefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts )
+{
+    Fpga_Node_t * pNodeChild;
+    float aArea;
+    int i;
+    // start the area of this cut
+    aArea = pNode->Switching;
+    if ( pCut->nLeaves == 1 )
+        return aArea;
+    // go through the children
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        pNodeChild = pCut->ppLeaves[i];
+        assert( pNodeChild->nRefs >= 0 );
+        if ( pNodeChild->nRefs++ > 0 )  
+            continue;
+        aArea += Fpga_CutRefSwitch( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts );
+    }
+    return aArea;
+}
+
+/**function*************************************************************
+
+  synopsis    [Dereferences the cut.]
+
+  description [This procedure is similar to the procedure NodeRecusiveDeref.]
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Fpga_CutDerefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts )
+{
+    Fpga_Node_t * pNodeChild;
+    float aArea;
+    int i;
+    // start the area of this cut
+    aArea = pNode->Switching;
+    if ( pCut->nLeaves == 1 )
+        return aArea;
+    // go through the children
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        pNodeChild = pCut->ppLeaves[i];
+        assert( pNodeChild->nRefs > 0 );
+        if ( --pNodeChild->nRefs > 0 )  
+            continue;
+        aArea += Fpga_CutDerefSwitch( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts );
+    }
+    return aArea;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the array of mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Fpga_MappingGetSwitching( Fpga_Man_t * pMan, Fpga_NodeVec_t * vMapping )
+{
+    Fpga_Node_t * pNode;
+    float Switch;
+    int i;
+    Switch = 0.0;
+    for ( i = 0; i < vMapping->nSize; i++ )
+    {
+        pNode = vMapping->pArray[i];
+        // at least one phase has the best cut assigned
+        assert( !Fpga_NodeIsAnd(pNode) || pNode->pCutBest != NULL );
+        // at least one phase is used in the mapping
+        assert( pNode->nRefs > 0 );
+        // compute the array due to the supergate
+        Switch += pNode->Switching;
+    }
+    // add buffer for each CO driven by a CI
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        if ( Fpga_NodeIsVar(Fpga_Regular(pMan->pOutputs[i])) && !Fpga_IsComplement(pMan->pOutputs[i]) )
+            Switch += Fpga_Regular(pMan->pOutputs[i])->Switching;
+    return Switch;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/fpga/fpgaTime.c b/abc-build/src/map/fpga/fpgaTime.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/fpga/fpgaTime.c
@@ -0,0 +1,267 @@
+/**CFile****************************************************************
+
+  FileName    [fpgaTime.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Technology mapping for variable-size-LUT FPGAs.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - August 18, 2004.]
+
+  Revision    [$Id: fpgaTime.c,v 1.1 2005/01/23 06:59:42 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the arrival times of the cut.]
+
+  Description [Computes the maximum arrival time of the cut leaves and
+  adds the delay of the LUT.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Fpga_TimeCutComputeArrival( Fpga_Man_t * pMan, Fpga_Cut_t * pCut )
+{
+    int i;
+    float tArrival;
+    tArrival = -FPGA_FLOAT_LARGE;
+    for ( i = 0; i < pCut->nLeaves; i++ )
+        if ( tArrival < pCut->ppLeaves[i]->pCutBest->tArrival )
+            tArrival = pCut->ppLeaves[i]->pCutBest->tArrival;
+    tArrival += pMan->pLutLib->pLutDelays[(int)pCut->nLeaves][0];
+    return tArrival;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the arrival times of the cut recursively.]
+
+  Description [When computing the arrival time for the previously unused 
+  cuts, their arrival time may be incorrect because their fanins have 
+  incorrect arrival time. This procedure is called to fix this problem.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Fpga_TimeCutComputeArrival_rec( Fpga_Man_t * pMan, Fpga_Cut_t * pCut )
+{
+    int i;
+    for ( i = 0; i < pCut->nLeaves; i++ )
+        if ( pCut->ppLeaves[i]->nRefs == 0 )
+            Fpga_TimeCutComputeArrival_rec( pMan, pCut->ppLeaves[i]->pCutBest );
+    return Fpga_TimeCutComputeArrival( pMan, pCut );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the maximum arrival times.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Fpga_TimeComputeArrivalMax( Fpga_Man_t * p )
+{
+    float fRequired;
+    int i;
+    if ( p->fLatchPaths && p->nLatches == 0 )
+    {
+        printf( "Delay optimization of latch path is not performed because there is no latches.\n" );
+        p->fLatchPaths = 0;
+    }
+    // get the critical PO arrival time
+    fRequired = -FPGA_FLOAT_LARGE;
+    if ( p->fLatchPaths )
+    {
+        for ( i = p->nOutputs - p->nLatches; i < p->nOutputs; i++ )
+        {
+            if ( Fpga_NodeIsConst(p->pOutputs[i]) )
+                continue;
+            fRequired = FPGA_MAX( fRequired, Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival );
+//            printf( " %5.1f", Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival );
+        }
+//        printf( "Required latches = %5.1f\n", fRequired );
+    }
+    else
+    {
+        for ( i = 0; i < p->nOutputs; i++ )
+        {
+            if ( Fpga_NodeIsConst(p->pOutputs[i]) )
+                continue;
+            fRequired = FPGA_MAX( fRequired, Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival );
+//            printf( " %5.1f", Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival );
+        }
+//        printf( "Required outputs = %5.1f\n", fRequired );
+    }
+    return fRequired;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the required times of all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p, int fFirstTime )
+{
+    p->fRequiredGlo = Fpga_TimeComputeArrivalMax( p );
+    // update the required times according to the target
+    if ( p->DelayTarget != -1 )
+    {
+        if ( p->fRequiredGlo > p->DelayTarget + p->fEpsilon )
+        {
+            if ( fFirstTime )
+                printf( "Cannot meet the target required times (%4.2f). Mapping continues anyway.\n", p->DelayTarget );
+        }
+        else if ( p->fRequiredGlo < p->DelayTarget - p->fEpsilon )
+        {
+            if ( fFirstTime )
+                printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->fRequiredGlo, p->DelayTarget );
+            p->fRequiredGlo = p->DelayTarget;
+        }
+    }
+    Fpga_TimeComputeRequired( p, p->fRequiredGlo );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the required times of all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_TimeComputeRequired( Fpga_Man_t * p, float fRequired )
+{
+    int i;
+    // clean the required times and the fanout counts for all nodes
+    for ( i = 0; i < p->vAnds->nSize; i++ )
+        p->vAnds->pArray[i]->tRequired = FPGA_FLOAT_LARGE;
+    // set the required times for the POs
+    if ( p->fLatchPaths )
+        for ( i = p->nOutputs - p->nLatches; i < p->nOutputs; i++ )
+            Fpga_Regular(p->pOutputs[i])->tRequired = fRequired;
+    else
+        for ( i = 0; i < p->nOutputs; i++ )
+            Fpga_Regular(p->pOutputs[i])->tRequired = fRequired;
+    // collect nodes reachable from POs in the DFS order through the best cuts
+    Fpga_TimePropagateRequired( p, p->vMapping );
+/*
+    {
+        int Counter = 0;
+        for ( i = 0; i < p->vAnds->nSize; i++ )
+            if ( p->vAnds->pArray[i]->tRequired > FPGA_FLOAT_LARGE - 100 )
+                Counter++;
+        printf( "The number of nodes with large required times = %d.\n", Counter );
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the required times of the given nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_TimePropagateRequired( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes )
+{
+    Fpga_Node_t * pNode, * pChild;
+    float fRequired;
+    int i, k;
+
+    // sorts the nodes in the decreasing order of levels
+//    Fpga_MappingSortByLevel( p, vNodes, 0 );
+    // the nodes area already sorted in Fpga_MappingSetRefsAndArea()
+
+    // go through the nodes in the reverse topological order
+    for ( k = 0; k < vNodes->nSize; k++ )
+    {
+        pNode = vNodes->pArray[k];
+        if ( !Fpga_NodeIsAnd(pNode) )
+            continue;
+        // get the required time for children
+        fRequired = pNode->tRequired - p->pLutLib->pLutDelays[(int)pNode->pCutBest->nLeaves][0];
+        // update the required time of the children
+        for ( i = 0; i < pNode->pCutBest->nLeaves; i++ )
+        {
+            pChild = pNode->pCutBest->ppLeaves[i];
+            pChild->tRequired = FPGA_MIN( pChild->tRequired, fRequired );
+        }
+    }
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the required times of all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_TimePropagateArrival( Fpga_Man_t * p )
+{
+    Fpga_Node_t * pNode;
+    Fpga_Cut_t * pCut;
+    int i;
+
+    // clean the required times and the fanout counts for all nodes
+    for ( i = 0; i < p->vAnds->nSize; i++ )
+    {
+        pNode = p->vAnds->pArray[i];
+        for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+            pCut->tArrival = Fpga_TimeCutComputeArrival( p, pCut );
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/fpga/fpgaTruth.c b/abc-build/src/map/fpga/fpgaTruth.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/fpga/fpgaTruth.c
@@ -0,0 +1,171 @@
+/**CFile****************************************************************
+
+  FileName    [fpgaTruth.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Technology mapping for variable-size-LUT FPGAs.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - August 18, 2004.]
+
+  Revision    [$Id: fpgaTruth.c,v 1.4 2005/01/23 06:59:42 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+#include "bdd/cudd/cudd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively derives the truth table for the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Fpga_TruthsCutBdd_rec( DdManager * dd, Fpga_Cut_t * pCut, Fpga_NodeVec_t * vVisited )
+{
+    DdNode * bFunc, * bFunc0, * bFunc1;
+    assert( !Fpga_IsComplement(pCut) );
+    // if the cut is visited, return the result
+    if ( pCut->uSign )
+        return (DdNode *)(ABC_PTRUINT_T)pCut->uSign;
+    // compute the functions of the children
+    bFunc0 = Fpga_TruthsCutBdd_rec( dd, Fpga_CutRegular(pCut->pOne), vVisited );   Cudd_Ref( bFunc0 );
+    bFunc0 = Cudd_NotCond( bFunc0, Fpga_CutIsComplement(pCut->pOne) );
+    bFunc1 = Fpga_TruthsCutBdd_rec( dd, Fpga_CutRegular(pCut->pTwo), vVisited );   Cudd_Ref( bFunc1 );
+    bFunc1 = Cudd_NotCond( bFunc1, Fpga_CutIsComplement(pCut->pTwo) );
+    // get the function of the cut
+    bFunc  = Cudd_bddAnd( dd, bFunc0, bFunc1 );   Cudd_Ref( bFunc );
+    bFunc  = Cudd_NotCond( bFunc, pCut->Phase );
+    Cudd_RecursiveDeref( dd, bFunc0 );
+    Cudd_RecursiveDeref( dd, bFunc1 );
+    assert( pCut->uSign == 0 );
+    pCut->uSign = (unsigned)(ABC_PTRUINT_T)bFunc;
+    // add this cut to the visited list
+    Fpga_NodeVecPush( vVisited, (Fpga_Node_t *)pCut );
+    return bFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table for one cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Fpga_TruthsCutBdd( void * dd, Fpga_Cut_t * pCut )
+{
+    Fpga_NodeVec_t * vVisited;
+    DdNode * bFunc;
+    int i;
+    assert( pCut->nLeaves > 1 );
+    // set the leaf variables
+    for ( i = 0; i < pCut->nLeaves; i++ )
+        pCut->ppLeaves[i]->pCuts->uSign = (unsigned)(ABC_PTRUINT_T)Cudd_bddIthVar( (DdManager *)dd, i );
+    // recursively compute the function
+    vVisited = Fpga_NodeVecAlloc( 10 );
+    bFunc = Fpga_TruthsCutBdd_rec( (DdManager *)dd, pCut, vVisited );   Cudd_Ref( bFunc );
+    // clean the intermediate BDDs
+    for ( i = 0; i < pCut->nLeaves; i++ )
+        pCut->ppLeaves[i]->pCuts->uSign = 0;
+    for ( i = 0; i < vVisited->nSize; i++ )
+    {
+        pCut = (Fpga_Cut_t *)vVisited->pArray[i];
+        Cudd_RecursiveDeref( (DdManager *)dd, (DdNode*)(ABC_PTRUINT_T)pCut->uSign );
+        pCut->uSign = 0;
+    }
+//    printf( "%d ", vVisited->nSize );
+    Fpga_NodeVecFree( vVisited );
+    Cudd_Deref( bFunc );
+    return bFunc;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively derives the truth table for the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_CutVolume_rec( Fpga_Cut_t * pCut, Fpga_NodeVec_t * vVisited )
+{
+    assert( !Fpga_IsComplement(pCut) );
+    if ( pCut->fMark )
+        return;
+    pCut->fMark = 1;
+    Fpga_CutVolume_rec( Fpga_CutRegular(pCut->pOne), vVisited );
+    Fpga_CutVolume_rec( Fpga_CutRegular(pCut->pTwo), vVisited );
+    Fpga_NodeVecPush( vVisited, (Fpga_Node_t *)pCut );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table for one cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_CutVolume( Fpga_Cut_t * pCut )
+{
+    Fpga_NodeVec_t * vVisited;
+    int Volume, i;
+    assert( pCut->nLeaves > 1 );
+    // set the leaf variables
+    for ( i = 0; i < pCut->nLeaves; i++ )
+        pCut->ppLeaves[i]->pCuts->fMark = 1;
+    // recursively compute the function
+    vVisited = Fpga_NodeVecAlloc( 10 );
+    Fpga_CutVolume_rec( pCut, vVisited ); 
+    // clean the marks
+    for ( i = 0; i < pCut->nLeaves; i++ )
+        pCut->ppLeaves[i]->pCuts->fMark = 0;
+    for ( i = 0; i < vVisited->nSize; i++ )
+    {
+        pCut = (Fpga_Cut_t *)vVisited->pArray[i];
+        pCut->fMark = 0;
+    }
+    Volume = vVisited->nSize;
+    printf( "%d ", Volume );
+    Fpga_NodeVecFree( vVisited );
+    return Volume;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/fpga/fpgaUtils.c b/abc-build/src/map/fpga/fpgaUtils.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/fpga/fpgaUtils.c
@@ -0,0 +1,990 @@
+/**CFile****************************************************************
+
+  FileName    [fpgaUtils.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Technology mapping for variable-size-LUT FPGAs.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - August 18, 2004.]
+
+  Revision    [$Id: fpgaUtils.c,v 1.3 2004/07/06 04:55:58 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define FPGA_CO_LIST_SIZE  5
+
+static void  Fpga_MappingDfs_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes, int fCollectEquiv );
+static void  Fpga_MappingDfsCuts_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes );
+static int   Fpga_MappingCompareOutputDelay( Fpga_Node_t ** ppNode1, Fpga_Node_t ** ppNode2 );
+static void  Fpga_MappingFindLatest( Fpga_Man_t * p, int * pNodes, int nNodesMax );
+static void  Fpga_DfsLim_rec( Fpga_Node_t * pNode, int Level, Fpga_NodeVec_t * vNodes );
+static int   Fpga_CollectNodeTfo_rec( Fpga_Node_t * pNode, Fpga_Node_t * pPivot, Fpga_NodeVec_t * vVisited, Fpga_NodeVec_t * vTfo );
+static Fpga_NodeVec_t * Fpga_MappingOrderCosByLevel( Fpga_Man_t * pMan );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the DFS ordering of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_NodeVec_t * Fpga_MappingDfs( Fpga_Man_t * pMan, int fCollectEquiv )
+{
+    Fpga_NodeVec_t * vNodes;//, * vNodesCo;
+    Fpga_Node_t * pNode;
+    int i;
+    // collect the CO nodes by level
+//    vNodesCo = Fpga_MappingOrderCosByLevel( pMan );
+    // start the array
+    vNodes = Fpga_NodeVecAlloc( 100 );
+    // collect the PIs
+    for ( i = 0; i < pMan->nInputs; i++ )
+    {
+        pNode = pMan->pInputs[i];
+        Fpga_NodeVecPush( vNodes, pNode );
+        pNode->fMark0 = 1;
+    }
+    // perform the traversal
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        Fpga_MappingDfs_rec( Fpga_Regular(pMan->pOutputs[i]), vNodes, fCollectEquiv );
+//    for ( i = vNodesCo->nSize - 1; i >= 0 ; i-- )
+//        for ( pNode = vNodesCo->pArray[i]; pNode; pNode = (Fpga_Node_t *)pNode->pData0 )
+//            Fpga_MappingDfs_rec( pNode, vNodes, fCollectEquiv );
+    // clean the node marks
+    for ( i = 0; i < vNodes->nSize; i++ )
+        vNodes->pArray[i]->fMark0 = 0;
+//    for ( i = 0; i < pMan->nOutputs; i++ )
+//        Fpga_MappingUnmark_rec( Fpga_Regular(pMan->pOutputs[i]) );
+//    Fpga_NodeVecFree( vNodesCo );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively computes the DFS ordering of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_MappingDfs_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes, int fCollectEquiv )
+{
+    assert( !Fpga_IsComplement(pNode) );
+    if ( pNode->fMark0 )
+        return;
+    // visit the transitive fanin
+    if ( Fpga_NodeIsAnd(pNode) )
+    {
+        Fpga_MappingDfs_rec( Fpga_Regular(pNode->p1), vNodes, fCollectEquiv );
+        Fpga_MappingDfs_rec( Fpga_Regular(pNode->p2), vNodes, fCollectEquiv );
+    }
+    // visit the equivalent nodes
+    if ( fCollectEquiv && pNode->pNextE )
+        Fpga_MappingDfs_rec( pNode->pNextE, vNodes, fCollectEquiv );
+    // make sure the node is not visited through the equivalent nodes
+    assert( pNode->fMark0 == 0 );
+    // mark the node as visited
+    pNode->fMark0 = 1;
+    // add the node to the list
+    Fpga_NodeVecPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the DFS ordering of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_NodeVec_t * Fpga_MappingDfsNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppNodes, int nNodes, int fEquiv )
+{
+    Fpga_NodeVec_t * vNodes;
+    int i;
+    // perform the traversal
+    vNodes = Fpga_NodeVecAlloc( 200 );
+    for ( i = 0; i < nNodes; i++ )
+        Fpga_MappingDfs_rec( ppNodes[i], vNodes, fEquiv );
+    for ( i = 0; i < vNodes->nSize; i++ )
+        vNodes->pArray[i]->fMark0 = 0;
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Fpga_MappingGetAreaFlow( Fpga_Man_t * p )
+{
+    float aFlowFlowTotal = 0;
+    int i;
+    for ( i = 0; i < p->nOutputs; i++ )
+    {
+        if ( Fpga_NodeIsConst(p->pOutputs[i]) )
+            continue;
+        aFlowFlowTotal += Fpga_Regular(p->pOutputs[i])->pCutBest->aFlow;
+    }
+    return aFlowFlowTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the area of the current mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Fpga_MappingArea( Fpga_Man_t * pMan )
+{
+    Fpga_Node_t * pNode;
+    float aTotal;
+    int i;
+    // perform the traversal
+    aTotal = 0;
+    for ( i = 0; i < pMan->vMapping->nSize; i++ )
+    {
+        pNode = pMan->vMapping->pArray[i];
+        aTotal += pMan->pLutLib->pLutAreas[(int)pNode->pCutBest->nLeaves];
+    }
+    return aTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively computes the DFS ordering of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Fpga_MappingArea_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes )
+{
+    float aArea;
+    int i;
+    assert( !Fpga_IsComplement(pNode) );
+    if ( !Fpga_NodeIsAnd(pNode) )
+        return 0;
+    if ( pNode->fMark0 )
+        return 0;
+    assert( pNode->pCutBest != NULL );
+    // visit the transitive fanin of the selected cut
+    aArea = 0;
+    for ( i = 0; i < pNode->pCutBest->nLeaves; i++ )
+        aArea += Fpga_MappingArea_rec( pMan, pNode->pCutBest->ppLeaves[i], vNodes );
+    // make sure the node is not visited through the fanin nodes
+    assert( pNode->fMark0 == 0 );
+    // mark the node as visited
+    pNode->fMark0 = 1;
+    // add the node to the list
+    aArea += pMan->pLutLib->pLutAreas[(int)pNode->pCutBest->nLeaves];
+    // add the node to the list
+    Fpga_NodeVecPush( vNodes, pNode );
+    return aArea;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the area of the current mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Fpga_MappingAreaTrav( Fpga_Man_t * pMan )
+{
+    Fpga_NodeVec_t * vNodes;
+    float aTotal;
+    int i;
+    // perform the traversal
+    aTotal = 0;
+    vNodes = Fpga_NodeVecAlloc( 100 );
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        aTotal += Fpga_MappingArea_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), vNodes );
+    for ( i = 0; i < vNodes->nSize; i++ )
+        vNodes->pArray[i]->fMark0 = 0;
+    Fpga_NodeVecFree( vNodes );
+    return aTotal;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively computes the DFS ordering of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Fpga_MappingSetRefsAndArea_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Node_t ** ppStore )
+{
+    float aArea;
+    int i;
+    assert( !Fpga_IsComplement(pNode) );
+    if ( pNode->nRefs++ )
+        return 0;
+    if ( !Fpga_NodeIsAnd(pNode) )
+        return 0;
+    assert( pNode->pCutBest != NULL );
+    // store the node in the structure by level
+    pNode->pData0 = (char *)ppStore[pNode->Level]; 
+    ppStore[pNode->Level] = pNode;
+    // visit the transitive fanin of the selected cut
+    aArea = pMan->pLutLib->pLutAreas[(int)pNode->pCutBest->nLeaves];
+    for ( i = 0; i < pNode->pCutBest->nLeaves; i++ )
+        aArea += Fpga_MappingSetRefsAndArea_rec( pMan, pNode->pCutBest->ppLeaves[i], ppStore );
+    return aArea;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the correct reference counts for the mapping.]
+
+  Description [Collects the nodes in reverse topological order
+  and places in them in array pMan->vMapping.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Fpga_MappingSetRefsAndArea( Fpga_Man_t * pMan )
+{
+    Fpga_Node_t * pNode, ** ppStore;
+    float aArea;
+    int i, LevelMax;
+
+    // clean all references
+    for ( i = 0; i < pMan->vNodesAll->nSize; i++ )
+        pMan->vNodesAll->pArray[i]->nRefs = 0;
+
+    // allocate place to store the nodes
+    LevelMax = Fpga_MappingMaxLevel( pMan );
+    ppStore = ABC_ALLOC( Fpga_Node_t *, LevelMax + 1 );
+    memset( ppStore, 0, sizeof(Fpga_Node_t *) * (LevelMax + 1) );
+
+    // collect nodes reachable from POs in the DFS order through the best cuts
+    aArea = 0;
+    for ( i = 0; i < pMan->nOutputs; i++ )
+    {
+        pNode = Fpga_Regular(pMan->pOutputs[i]);
+        if ( pNode == pMan->pConst1 )
+            continue;
+        aArea += Fpga_MappingSetRefsAndArea_rec( pMan, pNode, ppStore );
+        pNode->nRefs++;
+    }
+
+    // reconnect the nodes in reverse topological order
+    pMan->vMapping->nSize = 0;
+    for ( i = LevelMax; i >= 0; i-- )
+        for ( pNode = ppStore[i]; pNode; pNode = (Fpga_Node_t *)pNode->pData0 )
+            Fpga_NodeVecPush( pMan->vMapping, pNode );
+    ABC_FREE( ppStore );
+    return aArea;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the outputs by their arrival times.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_MappingCompareOutputDelay( Fpga_Node_t ** ppNode1, Fpga_Node_t ** ppNode2 )
+{
+    Fpga_Node_t * pNode1 = Fpga_Regular(*ppNode1);
+    Fpga_Node_t * pNode2 = Fpga_Regular(*ppNode2);
+    float Arrival1 = pNode1->pCutBest? pNode1->pCutBest->tArrival : 0;
+    float Arrival2 = pNode2->pCutBest? pNode2->pCutBest->tArrival : 0;
+    if ( Arrival1 < Arrival2 )
+        return -1;
+    if ( Arrival1 > Arrival2 )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds given number of latest arriving COs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_MappingFindLatest( Fpga_Man_t * p, int * pNodes, int nNodesMax )
+{
+    int nNodes, i, k, v;
+    assert( p->nOutputs >= nNodesMax );
+    pNodes[0] = 0;
+    nNodes = 1;
+    for ( i = 1; i < p->nOutputs; i++ )
+    {
+        for ( k = nNodes - 1; k >= 0; k-- )
+            if ( Fpga_MappingCompareOutputDelay( &p->pOutputs[pNodes[k]], &p->pOutputs[i] ) >= 0 )
+                break;
+        if ( k == nNodesMax - 1 )
+            continue;
+        if ( nNodes < nNodesMax )
+            nNodes++;
+        for ( v = nNodes - 1; v > k+1; v-- )
+            pNodes[v] = pNodes[v-1];
+        pNodes[k+1] = i;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints a bunch of latest arriving outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_MappingPrintOutputArrivals( Fpga_Man_t * p )
+{
+    Fpga_Node_t * pNode;
+    int pSorted[FPGA_CO_LIST_SIZE];
+    int fCompl, Limit, MaxNameSize, i;
+
+    // determine the number of nodes to print
+    Limit = (p->nOutputs > FPGA_CO_LIST_SIZE)? FPGA_CO_LIST_SIZE : p->nOutputs;
+
+    // determine the order
+    Fpga_MappingFindLatest( p, pSorted, Limit );
+
+    // determine max size of the node's name
+    MaxNameSize = 0;
+    for ( i = 0; i < Limit; i++ )
+        if ( MaxNameSize < (int)strlen(p->ppOutputNames[pSorted[i]]) )
+            MaxNameSize = strlen(p->ppOutputNames[pSorted[i]]);
+
+    // print the latest outputs
+    for ( i = 0; i < Limit; i++ )
+    {
+        // get the i-th latest output
+        pNode  = Fpga_Regular(p->pOutputs[pSorted[i]]);
+        fCompl = Fpga_IsComplement(p->pOutputs[pSorted[i]]);
+        // print out the best arrival time
+        printf( "Output  %-*s : ", MaxNameSize + 3, p->ppOutputNames[pSorted[i]] );
+        printf( "Delay = %8.2f  ",     (double)pNode->pCutBest->tArrival );
+        if ( fCompl )
+            printf( "NEG" );
+        else
+            printf( "POS" );
+        printf( "\n" );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sets up the truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_MappingSetupTruthTables( unsigned uTruths[][2] )
+{
+    int m, v;
+    // set up the truth tables
+    for ( m = 0; m < 32; m++ )
+        for ( v = 0; v < 5; v++ )
+            if ( m & (1 << v) )
+                uTruths[v][0] |= (1 << m);
+    // make adjustments for the case of 6 variables
+    for ( v = 0; v < 5; v++ )
+        uTruths[v][1] = uTruths[v][0];
+    uTruths[5][0] = 0;
+    uTruths[5][1] = FPGA_FULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets up the mask.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_MappingSetupMask( unsigned uMask[], int nVarsMax )
+{
+    if ( nVarsMax == 6 )
+        uMask[0] = uMask[1] = FPGA_FULL;
+    else
+    {
+        uMask[0] = FPGA_MASK(1 << nVarsMax);
+        uMask[1] = 0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verify one useful property.]
+
+  Description [This procedure verifies one useful property. After 
+  the FRAIG construction with choice nodes is over, each primary node 
+  should have fanins that are primary nodes. The primary nodes is the 
+  one that does not have pNode->pRepr set to point to another node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_ManCheckConsistency( Fpga_Man_t * p )
+{
+    Fpga_Node_t * pNode;
+    Fpga_NodeVec_t * pVec;
+    int i;
+    pVec = Fpga_MappingDfs( p, 0 );
+    for ( i = 0; i < pVec->nSize; i++ )
+    {
+        pNode = pVec->pArray[i];
+        if ( Fpga_NodeIsVar(pNode) )
+        {
+            if ( pNode->pRepr )
+                printf( "Primary input %d is a secondary node.\n", pNode->Num );
+        }
+        else if ( Fpga_NodeIsConst(pNode) )
+        {
+            if ( pNode->pRepr )
+                printf( "Constant 1 %d is a secondary node.\n", pNode->Num );
+        }
+        else
+        {
+            if ( pNode->pRepr )
+                printf( "Internal node %d is a secondary node.\n", pNode->Num );
+            if ( Fpga_Regular(pNode->p1)->pRepr )
+                printf( "Internal node %d has first fanin that is a secondary node.\n", pNode->Num );
+            if ( Fpga_Regular(pNode->p2)->pRepr )
+                printf( "Internal node %d has second fanin that is a secondary node.\n", pNode->Num );
+        }
+    }
+    Fpga_NodeVecFree( pVec );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the supergates by their level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_CompareNodesByLevelDecreasing( Fpga_Node_t ** ppS1, Fpga_Node_t ** ppS2 )
+{
+    if ( Fpga_Regular(*ppS1)->Level > Fpga_Regular(*ppS2)->Level )
+        return -1;
+    if ( Fpga_Regular(*ppS1)->Level < Fpga_Regular(*ppS2)->Level )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the supergates by their level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_CompareNodesByLevelIncreasing( Fpga_Node_t ** ppS1, Fpga_Node_t ** ppS2 )
+{
+    if ( Fpga_Regular(*ppS1)->Level < Fpga_Regular(*ppS2)->Level )
+        return -1;
+    if ( Fpga_Regular(*ppS1)->Level > Fpga_Regular(*ppS2)->Level )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Orders the nodes in the decreasing order of levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_MappingSortByLevel( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes, int fIncreasing )
+{
+    if ( fIncreasing )
+        qsort( (void *)vNodes->pArray, vNodes->nSize, sizeof(Fpga_Node_t *), 
+                (int (*)(const void *, const void *)) Fpga_CompareNodesByLevelIncreasing );
+    else
+        qsort( (void *)vNodes->pArray, vNodes->nSize, sizeof(Fpga_Node_t *), 
+                (int (*)(const void *, const void *)) Fpga_CompareNodesByLevelDecreasing );
+//    assert( Fpga_CompareNodesByLevel( vNodes->pArray, vNodes->pArray + vNodes->nSize - 1 ) <= 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the limited DFS ordering for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_NodeVec_t * Fpga_DfsLim( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int nLevels )
+{
+    Fpga_NodeVec_t * vNodes;
+    int i;
+    // perform the traversal
+    vNodes = Fpga_NodeVecAlloc( 100 );
+    Fpga_DfsLim_rec( pNode, nLevels, vNodes );
+    for ( i = 0; i < vNodes->nSize; i++ )
+        vNodes->pArray[i]->fMark0 = 0;
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively computes the DFS ordering of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_DfsLim_rec( Fpga_Node_t * pNode, int Level, Fpga_NodeVec_t * vNodes )
+{
+    assert( !Fpga_IsComplement(pNode) );
+    if ( pNode->fMark0 )
+        return;
+    pNode->fMark0 = 1;
+    // visit the transitive fanin
+    Level--;
+    if ( Level > 0 && Fpga_NodeIsAnd(pNode) )
+    {
+        Fpga_DfsLim_rec( Fpga_Regular(pNode->p1), Level, vNodes );
+        Fpga_DfsLim_rec( Fpga_Regular(pNode->p2), Level, vNodes );
+    }
+    // add the node to the list
+    Fpga_NodeVecPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the limited DFS ordering for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_ManCleanData0( Fpga_Man_t * pMan )
+{
+    int i;
+    for ( i = 0; i < pMan->vNodesAll->nSize; i++ )
+        pMan->vNodesAll->pArray[i]->pData0 = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the TFO of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_NodeVec_t * Fpga_CollectNodeTfo( Fpga_Man_t * pMan, Fpga_Node_t * pNode )
+{
+    Fpga_NodeVec_t * vVisited, * vTfo;
+    int i;
+    // perform the traversal
+    vVisited = Fpga_NodeVecAlloc( 100 );
+    vTfo     = Fpga_NodeVecAlloc( 100 );
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        Fpga_CollectNodeTfo_rec( Fpga_Regular(pMan->pOutputs[i]), pNode, vVisited, vTfo );
+    for ( i = 0; i < vVisited->nSize; i++ )
+        vVisited->pArray[i]->fMark0 = vVisited->pArray[i]->fMark1 = 0;
+    Fpga_NodeVecFree( vVisited );
+    return vTfo;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the TFO of the node.]
+
+  Description [Returns 1 if the node should be collected.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_CollectNodeTfo_rec( Fpga_Node_t * pNode, Fpga_Node_t * pPivot, Fpga_NodeVec_t * vVisited, Fpga_NodeVec_t * vTfo )
+{
+    int Ret1, Ret2;
+    assert( !Fpga_IsComplement(pNode) );
+    // skip visited nodes
+    if ( pNode->fMark0 )
+        return pNode->fMark1;
+    pNode->fMark0 = 1;
+    Fpga_NodeVecPush( vVisited, pNode );
+
+    // return the pivot node
+    if ( pNode == pPivot )
+    {
+        pNode->fMark1 = 1;
+        return 1;
+    }
+    if ( pNode->Level < pPivot->Level )
+    {
+        pNode->fMark1 = 0;
+        return 0;
+    }
+    // visit the transitive fanin
+    assert( Fpga_NodeIsAnd(pNode) );
+    Ret1 = Fpga_CollectNodeTfo_rec( Fpga_Regular(pNode->p1), pPivot, vVisited, vTfo );
+    Ret2 = Fpga_CollectNodeTfo_rec( Fpga_Regular(pNode->p2), pPivot, vVisited, vTfo );
+    if ( Ret1 || Ret2 )
+    {
+        pNode->fMark1 = 1;
+        Fpga_NodeVecPush( vTfo, pNode );
+    }
+    else
+        pNode->fMark1 = 0;
+    return pNode->fMark1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Levelizes the nodes accessible from the POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_NodeVec_t * Fpga_MappingLevelize( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes )
+{
+    Fpga_NodeVec_t * vLevels;
+    Fpga_Node_t ** ppNodes;
+    Fpga_Node_t * pNode;
+    int nNodes, nLevelsMax, i;
+
+    // reassign the levels (this may be necessary for networks which choices)
+    ppNodes = vNodes->pArray;
+    nNodes  = vNodes->nSize;
+    for ( i = 0; i < nNodes; i++ )
+    {
+        pNode = ppNodes[i];
+        if ( !Fpga_NodeIsAnd(pNode) )
+        {
+            pNode->Level = 0;
+            continue;
+        }
+        pNode->Level = 1 + FPGA_MAX( Fpga_Regular(pNode->p1)->Level, Fpga_Regular(pNode->p2)->Level );
+    }
+
+    // get the max levels
+    nLevelsMax = 0;
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        nLevelsMax = FPGA_MAX( nLevelsMax, (int)Fpga_Regular(pMan->pOutputs[i])->Level );
+    nLevelsMax++;
+
+    // allocate storage for levels
+    vLevels = Fpga_NodeVecAlloc( nLevelsMax );
+    for ( i = 0; i < nLevelsMax; i++ )
+        Fpga_NodeVecPush( vLevels, NULL );
+
+    // go through the nodes and add them to the levels
+    for ( i = 0; i < nNodes; i++ )
+    {
+        pNode = ppNodes[i];
+        pNode->pLevel = NULL;
+        if ( !Fpga_NodeIsAnd(pNode) )
+            continue;
+        // attach the node to this level
+        pNode->pLevel = Fpga_NodeVecReadEntry( vLevels, pNode->Level );
+        Fpga_NodeVecWriteEntry( vLevels, pNode->Level, pNode );
+    }
+    return vLevels;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets up the mask.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_MappingMaxLevel( Fpga_Man_t * pMan )
+{
+    int nLevelMax, i;
+    nLevelMax = 0;
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        nLevelMax = nLevelMax > (int)Fpga_Regular(pMan->pOutputs[i])->Level? 
+                nLevelMax : (int)Fpga_Regular(pMan->pOutputs[i])->Level;
+    return nLevelMax;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Analyses choice nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_MappingUpdateLevel_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int fMaximum )
+{
+    Fpga_Node_t * pTemp;
+    int Level1, Level2, LevelE;
+    assert( !Fpga_IsComplement(pNode) );
+    if ( !Fpga_NodeIsAnd(pNode) )
+        return pNode->Level;
+    // skip the visited node
+    if ( pNode->TravId == pMan->nTravIds )
+        return pNode->Level;
+    pNode->TravId = pMan->nTravIds;
+    // compute levels of the children nodes
+    Level1 = Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pNode->p1), fMaximum );
+    Level2 = Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pNode->p2), fMaximum );
+    pNode->Level = 1 + FPGA_MAX( Level1, Level2 );
+    if ( pNode->pNextE )
+    {
+        LevelE = Fpga_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum );
+        if ( fMaximum )
+        {
+            if ( pNode->Level < (unsigned)LevelE )
+                pNode->Level = LevelE;
+        }
+        else
+        {
+            if ( pNode->Level > (unsigned)LevelE )
+                pNode->Level = LevelE;
+        }
+        // set the level of all equivalent nodes to be the same minimum
+        if ( pNode->pRepr == NULL ) // the primary node
+            for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE )
+                pTemp->Level = pNode->Level;
+    }
+    return pNode->Level;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resets the levels of the nodes in the choice graph.]
+
+  Description [Makes the level of the choice nodes to be equal to the
+  maximum of the level of the nodes in the equivalence class. This way
+  sorting by level leads to the reverse topological order, which is
+  needed for the required time computation.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_MappingSetChoiceLevels( Fpga_Man_t * pMan )
+{
+    int i;
+    pMan->nTravIds++;
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports statistics on choice nodes.]
+
+  Description [The number of choice nodes is the number of primary nodes,
+  which has pNextE set to a pointer. The number of choices is the number
+  of entries in the equivalent-node lists of the primary nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_ManReportChoices( Fpga_Man_t * pMan )
+{
+    Fpga_Node_t * pNode, * pTemp;
+    int nChoiceNodes, nChoices;
+    int i, LevelMax1, LevelMax2;
+
+    // report the number of levels
+    LevelMax1 = Fpga_MappingMaxLevel( pMan );
+    pMan->nTravIds++;
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), 0 );
+    LevelMax2 = Fpga_MappingMaxLevel( pMan );
+
+    // report statistics about choices
+    nChoiceNodes = nChoices = 0;
+    for ( i = 0; i < pMan->vAnds->nSize; i++ )
+    {
+        pNode = pMan->vAnds->pArray[i];
+        if ( pNode->pRepr == NULL && pNode->pNextE != NULL )
+        { // this is a choice node = the primary node that has equivalent nodes
+            nChoiceNodes++;
+            for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE )
+                nChoices++;
+        }
+    }
+    if ( pMan->fVerbose )
+    {
+    printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 );
+    printf( "Choice stats:  Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices );
+    }
+/*
+    {
+        FILE * pTable;
+        pTable = fopen( "stats_choice.txt", "a+" );
+        fprintf( pTable, "%s ", pMan->pFileName );
+        fprintf( pTable, "%4d ", LevelMax1 );
+        fprintf( pTable, "%4d ", pMan->vAnds->nSize - pMan->nInputs );
+        fprintf( pTable, "%4d ", LevelMax2 );
+        fprintf( pTable, "%7d ", nChoiceNodes );
+        fprintf( pTable, "%7d ", nChoices + nChoiceNodes );
+        fprintf( pTable, "\n" );
+        fclose( pTable );
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of CO nodes sorted by level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_NodeVec_t * Fpga_MappingOrderCosByLevel( Fpga_Man_t * pMan )
+{
+    Fpga_Node_t * pNode;
+    Fpga_NodeVec_t * vNodes;
+    int i, nLevels;
+    // get the largest level of a CO
+    nLevels = Fpga_MappingMaxLevel( pMan );
+    // allocate the array of nodes
+    vNodes = Fpga_NodeVecAlloc( nLevels + 1 );
+    for ( i = 0; i <= nLevels; i++ )
+        Fpga_NodeVecPush( vNodes, NULL );
+    // clean the marks
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        Fpga_Regular(pMan->pOutputs[i])->fMark0 = 0;
+    // put the nodes into the structure
+    for ( i = 0; i < pMan->nOutputs; i++ )
+    {
+        pNode = Fpga_Regular(pMan->pOutputs[i]);
+        if ( pNode->fMark0 )
+            continue;
+        pNode->fMark0 = 1;
+        pNode->pData0 = (char *)Fpga_NodeVecReadEntry( vNodes, pNode->Level );
+        Fpga_NodeVecWriteEntry( vNodes, pNode->Level, pNode );
+    }
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        Fpga_Regular(pMan->pOutputs[i])->fMark0 = 0;
+    return vNodes;
+
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/fpga/fpgaVec.c b/abc-build/src/map/fpga/fpgaVec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/fpga/fpgaVec.c
@@ -0,0 +1,413 @@
+/**CFile****************************************************************
+
+  FileName    [fpgaVec.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Technology mapping for variable-size-LUT FPGAs.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - August 18, 2004.]
+
+  Revision    [$Id: fpgaVec.c,v 1.3 2005/01/23 06:59:42 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Fpga_NodeVecCompareLevels( Fpga_Node_t ** pp1, Fpga_Node_t ** pp2 );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_NodeVec_t * Fpga_NodeVecAlloc( int nCap )
+{
+    Fpga_NodeVec_t * p;
+    p = ABC_ALLOC( Fpga_NodeVec_t, 1 );
+    if ( nCap > 0 && nCap < 16 )
+        nCap = 16;
+    p->nSize  = 0;
+    p->nCap   = nCap;
+    p->pArray = p->nCap? ABC_ALLOC( Fpga_Node_t *, p->nCap ) : NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_NodeVecFree( Fpga_NodeVec_t * p )
+{
+    ABC_FREE( p->pArray );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Node_t ** Fpga_NodeVecReadArray( Fpga_NodeVec_t * p )
+{
+    return p->pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_NodeVecReadSize( Fpga_NodeVec_t * p )
+{
+    return p->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the vector to the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_NodeVecGrow( Fpga_NodeVec_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pArray = ABC_REALLOC( Fpga_Node_t *, p->pArray, nCapMin ); 
+    p->nCap   = nCapMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_NodeVecShrink( Fpga_NodeVec_t * p, int nSizeNew )
+{
+    assert( p->nSize >= nSizeNew );
+    p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_NodeVecClear( Fpga_NodeVec_t * p )
+{
+    p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_NodeVecPush( Fpga_NodeVec_t * p, Fpga_Node_t * Entry )
+{
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Fpga_NodeVecGrow( p, 16 );
+        else
+            Fpga_NodeVecGrow( p, 2 * p->nCap );
+    }
+    p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add the element while ensuring uniqueness.]
+
+  Description [Returns 1 if the element was found, and 0 if it was new. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_NodeVecPushUnique( Fpga_NodeVec_t * p, Fpga_Node_t * Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            return 1;
+    Fpga_NodeVecPush( p, Entry );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeVecPop( Fpga_NodeVec_t * p )
+{
+    return p->pArray[--p->nSize];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_NodeVecWriteEntry( Fpga_NodeVec_t * p, int i, Fpga_Node_t * Entry )
+{
+    assert( i >= 0 && i < p->nSize );
+    p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeVecReadEntry( Fpga_NodeVec_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_NodeVecCompareLevels( Fpga_Node_t ** pp1, Fpga_Node_t ** pp2 )
+{
+    int Level1 = Fpga_Regular(*pp1)->Level;
+    int Level2 = Fpga_Regular(*pp2)->Level;
+    if ( Level1 < Level2 )
+        return -1;
+    if ( Level1 > Level2 )
+        return 1;
+    if ( Fpga_Regular(*pp1)->Num < Fpga_Regular(*pp2)->Num )
+        return -1;
+    if ( Fpga_Regular(*pp1)->Num > Fpga_Regular(*pp2)->Num )
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting the entries by their integer value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_NodeVecSortByLevel( Fpga_NodeVec_t * p )
+{
+    qsort( (void *)p->pArray, p->nSize, sizeof(Fpga_Node_t *), 
+            (int (*)(const void *, const void *)) Fpga_NodeVecCompareLevels );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the arrival times.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fpga_NodeVecCompareArrivals( Fpga_Node_t ** ppS1, Fpga_Node_t ** ppS2 )
+{
+    if ( (*ppS1)->pCutBest->tArrival < (*ppS2)->pCutBest->tArrival )
+        return -1;
+    if ( (*ppS1)->pCutBest->tArrival > (*ppS2)->pCutBest->tArrival )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Orders the nodes in the increasing order of the arrival times.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_SortNodesByArrivalTimes( Fpga_NodeVec_t * p )
+{
+    qsort( (void *)p->pArray, p->nSize, sizeof(Fpga_Node_t *), 
+            (int (*)(const void *, const void *)) Fpga_NodeVecCompareArrivals );
+//    assert( Fpga_CompareNodesByLevel( p->pArray, p->pArray + p->nSize - 1 ) <= 0 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the union of nodes in two arrays.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_NodeVecUnion( Fpga_NodeVec_t * p, Fpga_NodeVec_t * p1, Fpga_NodeVec_t * p2 )
+{
+    int i;
+    Fpga_NodeVecClear( p );
+    for ( i = 0; i < p1->nSize; i++ )
+        Fpga_NodeVecPush( p, p1->pArray[i] );
+    for ( i = 0; i < p2->nSize; i++ )
+        Fpga_NodeVecPush( p, p2->pArray[i] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts a new node in the order by arrival times.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_NodeVecPushOrder( Fpga_NodeVec_t * vNodes, Fpga_Node_t * pNode, int fIncreasing )
+{
+    Fpga_Node_t * pNode1, * pNode2;
+    int i;
+    Fpga_NodeVecPush( vNodes, pNode );
+    // find the place of the node
+    for ( i = vNodes->nSize-1; i > 0; i-- )
+    {
+        pNode1 = vNodes->pArray[i  ];
+        pNode2 = vNodes->pArray[i-1];
+        if (( fIncreasing && pNode1->pCutBest->tArrival >= pNode2->pCutBest->tArrival) ||
+            (!fIncreasing && pNode1->pCutBest->tArrival <= pNode2->pCutBest->tArrival) )
+            break;
+        vNodes->pArray[i  ] = pNode2;
+        vNodes->pArray[i-1] = pNode1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts a new node in the order by arrival times.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fpga_NodeVecReverse( Fpga_NodeVec_t * vNodes )
+{
+    Fpga_Node_t * pNode1, * pNode2;
+    int i;
+    for ( i = 0; i < vNodes->nSize/2; i++ )
+    {
+        pNode1 = vNodes->pArray[i];
+        pNode2 = vNodes->pArray[vNodes->nSize-1-i];
+        vNodes->pArray[i]                 = pNode2;
+        vNodes->pArray[vNodes->nSize-1-i] = pNode1;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/fpga/module.make b/abc-build/src/map/fpga/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/fpga/module.make
@@ -0,0 +1,13 @@
+SRC +=  src/map/fpga/fpga.c \
+	src/map/fpga/fpgaCore.c \
+	src/map/fpga/fpgaCreate.c \
+	src/map/fpga/fpgaCut.c \
+	src/map/fpga/fpgaCutUtils.c \
+	src/map/fpga/fpgaFanout.c \
+	src/map/fpga/fpgaLib.c \
+	src/map/fpga/fpgaMatch.c \
+	src/map/fpga/fpgaSwitch.c \
+	src/map/fpga/fpgaTime.c \
+	src/map/fpga/fpgaTruth.c \
+	src/map/fpga/fpgaUtils.c \
+	src/map/fpga/fpgaVec.c
diff --git a/abc-build/src/map/if/if.h b/abc-build/src/map/if/if.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/if.h
@@ -0,0 +1,643 @@
+/**CFile****************************************************************
+
+  FileName    [if.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: if.h,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__map__if__if_h
+#define ABC__map__if__if_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+ 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+#include "misc/mem/mem.h"
+#include "misc/tim/tim.h"
+#include "misc/util/utilNam.h"
+#include "misc/vec/vecMem.h"
+#include "misc/util/utilTruth.h"
+#include "opt/dau/dau.h"
+#include "misc/vec/vecHash.h"
+#include "misc/vec/vecWec.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+ 
+// the maximum size of LUTs used for mapping (should be the same as FPGA_MAX_LUTSIZE defined in "fpga.h"!!!)
+#define IF_MAX_LUTSIZE       32
+// the largest possible number of LUT inputs when funtionality of the LUTs are computed
+#define IF_MAX_FUNC_LUTSIZE  15
+// a very large number
+#define IF_INFINITY          100000000  
+// the largest possible user cut cost
+#define IF_COST_MAX          8191 // ((1<<13)-1)
+
+#define IF_BIG_CHAR ((char)120)
+
+// object types
+typedef enum { 
+    IF_NONE,     // 0: non-existent object
+    IF_CONST1,   // 1: constant 1 
+    IF_CI,       // 2: combinational input
+    IF_CO,       // 3: combinational output
+    IF_AND,      // 4: AND node
+    IF_VOID      // 5: unused object
+} If_Type_t;
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct If_Man_t_     If_Man_t;
+typedef struct If_Par_t_     If_Par_t;
+typedef struct If_Obj_t_     If_Obj_t;
+typedef struct If_Cut_t_     If_Cut_t;
+typedef struct If_Set_t_     If_Set_t;
+typedef struct If_LibLut_t_  If_LibLut_t;
+typedef struct If_LibBox_t_  If_LibBox_t;
+typedef struct If_DsdMan_t_  If_DsdMan_t;
+
+typedef struct Ifif_Par_t_   Ifif_Par_t;
+struct Ifif_Par_t_
+{
+    int                nLutSize;      // the LUT size
+    If_LibLut_t *      pLutLib;       // the LUT library
+    float              pLutDelays[IF_MAX_LUTSIZE];  // pin-to-pin delays of the max LUT
+    float              DelayWire;     // wire delay
+    int                nDegree;       // structure degree 
+    int                fCascade;      // cascade
+    int                fVerbose;      // verbose
+    int                fVeryVerbose;  // verbose
+};
+
+// parameters
+struct If_Par_t_
+{
+    // user-controlable parameters
+    int                nLutSize;      // the LUT size
+    int                nCutsMax;      // the max number of cuts
+    int                nFlowIters;    // the number of iterations of area recovery
+    int                nAreaIters;    // the number of iterations of area recovery
+    int                nGateSize;     // the max size of the AND/OR gate to map into
+    int                nNonDecLimit;  // the max size of non-dec nodes
+    float              DelayTarget;   // delay target
+    float              Epsilon;       // value used in comparison floating point numbers
+    int                nRelaxRatio;   // delay relaxation ratio
+    int                nStructType;   // type of the structure
+    int                fPreprocess;   // preprossing
+    int                fArea;         // area-oriented mapping
+    int                fFancy;        // a fancy feature
+    int                fExpRed;       // expand/reduce of the best cuts
+    int                fLatchPaths;   // reset timing on latch paths
+    int                fEdge;         // uses edge-based cut selection heuristics
+    int                fPower;        // uses power-aware cut selection heuristics
+    int                fCutMin;       // performs cut minimization by removing functionally reducdant variables
+    int                fDelayOpt;     // special delay optimization
+    int                fDelayOptLut;  // delay optimization for LUTs
+    int                fDsdBalance;   // special delay optimization
+    int                fUserRecLib;   // use recorded library
+    int                fBidec;        // use bi-decomposition
+    int                fUseBat;       // use one specialized feature
+    int                fUseBuffs;     // use buffers to decouple outputs
+    int                fEnableCheck07;// enable additional checking
+    int                fEnableCheck08;// enable additional checking
+    int                fEnableCheck10;// enable additional checking
+    int                fEnableCheck75;// enable additional checking
+    int                fEnableCheck75u;// enable additional checking
+    int                fUseDsd;       // compute DSD of the cut functions
+    int                fUseTtPerm;    // compute truth tables of the cut functions
+    int                fDeriveLuts;   // enables deriving LUT structures
+    int                fDoAverage;    // optimize average rather than maximum level
+    int                fVerbose;      // the verbosity flag
+    char *             pLutStruct;    // LUT structure
+    float              WireDelay;     // wire delay
+    // internal parameters
+    int                fSkipCutFilter;// skip cut filter
+    int                fAreaOnly;     // area only mode
+    int                fTruth;        // truth table computation enabled
+    int                fUsePerm;      // use permutation (delay info)
+    int                fUseBdds;      // use local BDDs as a cost function
+    int                fUseSops;      // use local SOPs as a cost function
+    int                fUseCnfs;      // use local CNFs as a cost function
+    int                fUseMv;        // use local MV-SOPs as a cost function
+    int                nLatchesCi;    // the number of latches among the CIs
+    int                nLatchesCo;    // the number of latches among the COs
+    int                nLatchesCiBox; // the number of white box outputs among the CIs
+    int                nLatchesCoBox; // the number of white box inputs among the COs
+    int                fLiftLeaves;   // shift the leaves for seq mapping
+    int                fUseCoAttrs;   // use CO attributes
+    float              DelayTargetNew;// new delay target
+    float              FinalDelay;    // final delay after mapping
+    If_LibLut_t *      pLutLib;       // the LUT library
+    float *            pTimesArr;     // arrival times
+    float *            pTimesReq;     // required times
+    int (* pFuncCost)  (If_Man_t *, If_Cut_t *);  // procedure to compute the user's cost of a cut
+    int (* pFuncUser)  (If_Man_t *, If_Obj_t *, If_Cut_t *);        //  procedure called for each cut when cut computation is finished
+    int (* pFuncCell)  (If_Man_t *, unsigned *, int, int, char *);  //  procedure called for cut functions
+    void *             pReoMan;       // reordering manager
+};
+
+// the LUT library
+struct If_LibLut_t_
+{
+    char *             pName;         // the name of the LUT library
+    int                LutMax;        // the maximum LUT size 
+    int                fVarPinDelays; // set to 1 if variable pin delays are specified
+    float              pLutAreas[IF_MAX_LUTSIZE+1]; // the areas of LUTs
+    float              pLutDelays[IF_MAX_LUTSIZE+1][IF_MAX_LUTSIZE+1];// the delays of LUTs
+};
+
+// manager
+struct If_Man_t_
+{
+    char *             pName;
+    // mapping parameters
+    If_Par_t *         pPars;
+    // mapping nodes
+    If_Obj_t *         pConst1;       // the constant 1 node
+    Vec_Ptr_t *        vCis;          // the primary inputs
+    Vec_Ptr_t *        vCos;          // the primary outputs
+    Vec_Ptr_t *        vObjs;         // all objects
+    Vec_Ptr_t *        vObjsRev;      // reverse topological order of objects
+    Vec_Ptr_t *        vTemp;         // temporary array
+    int                nObjs[IF_VOID];// the number of objects by type
+    // various data
+    int                nLevelMax;     // the max number of AIG levels
+    float              fEpsilon;      // epsilon used for comparison
+    float              RequiredGlo;   // global required times
+    float              RequiredGlo2;  // global required times
+    float              AreaGlo;       // global area
+    int                nNets;         // the sum total of fanins of all LUTs in the mapping
+    float              dPower;        // the sum total of switching activities of all LUTs in the mapping
+    int                nCutsUsed;     // the number of cuts currently used
+    int                nCutsMerged;   // the total number of cuts merged
+    unsigned *         puTemp[4];     // used for the truth table computation
+    word *             puTempW;       // used for the truth table computation
+    int                SortMode;      // one of the three sorting modes
+    int                fNextRound;    // set to 1 after the first round
+    int                nChoices;      // the number of choice nodes
+    Vec_Int_t *        vSwitching;    // switching activity of each node
+    int                pPerm[3][IF_MAX_LUTSIZE]; // permutations
+    unsigned           uSharedMask;   // mask of shared variables
+    int                nShared;       // the number of shared variables
+    int                fReqTimeWarn;  // warning about exceeding required times was printed
+    // SOP balancing
+    Vec_Int_t *        vCover;        // used to compute ISOP
+    Vec_Int_t *        vArray;        // intermediate storage
+    Vec_Wrd_t *        vAnds;         // intermediate storage
+    Vec_Wrd_t *        vOrGate;       // intermediate storage
+    Vec_Wrd_t *        vAndGate;      // intermediate storage
+    // sequential mapping
+    Vec_Ptr_t *        vLatchOrder;   // topological ordering of latches
+    Vec_Int_t *        vLags;         // sequentail lags of all nodes
+    int                nAttempts;     // the number of attempts in binary search
+    int                nMaxIters;     // the maximum number of iterations
+    int                Period;        // the current value of the clock period (for seq mapping)
+    // memory management
+    int                nTruth6Words[IF_MAX_FUNC_LUTSIZE+1];  // the size of the truth table if allocated
+    int                nPermWords;    // the size of the permutation array (in words)
+    int                nObjBytes;     // the size of the object
+    int                nCutBytes;     // the size of the cut
+    int                nSetBytes;     // the size of the cut set
+    Mem_Fixed_t *      pMemObj;       // memory manager for objects (entrysize = nEntrySize)
+    Mem_Fixed_t *      pMemSet;       // memory manager for sets of cuts (entrysize = nCutSize*(nCutsMax+1))
+    If_Set_t *         pMemCi;        // memory for CI cutsets
+    If_Set_t *         pMemAnd;       // memory for AND cutsets
+    If_Set_t *         pFreeList;     // the list of free cutsets
+    int                nSmallSupp;    // the small support
+    int                nCutsTotal;
+    int                nCutsUseless[32];
+    int                nCutsCount[32];
+    int                nCutsCountAll;
+    int                nCutsUselessAll;
+    int                nCuts5, nCuts5a;
+    If_DsdMan_t *      pIfDsdMan;     // DSD manager
+    Vec_Mem_t *        vTtMem[IF_MAX_FUNC_LUTSIZE+1];   // truth table memory and hash table
+    Vec_Wec_t *        vTtIsops[IF_MAX_FUNC_LUTSIZE+1]; // mapping of truth table into DSD
+    Vec_Int_t *        vTtDsds[IF_MAX_FUNC_LUTSIZE+1];  // mapping of truth table into DSD
+    Vec_Str_t *        vTtPerms[IF_MAX_FUNC_LUTSIZE+1]; // mapping of truth table into permutations
+    Hash_IntMan_t *    vPairHash;     // hashing pairs of truth tables
+    Vec_Int_t *        vPairRes;      // resulting truth table
+    Vec_Str_t *        vPairPerms;    // resulting permutation
+    char               pCanonPerm[IF_MAX_LUTSIZE];
+    unsigned           uCanonPhase;
+    int                nCacheHits;
+    int                nCacheMisses;
+    abctime            timeCache[6];
+    int                nBestCutSmall[2];
+    int                nCountNonDec[2];
+    Vec_Int_t *        vCutData;      // cut data storage
+
+    // timing manager
+    Tim_Man_t *        pManTim;
+    Vec_Int_t *        vCoAttrs;      // CO attributes   0=optimize; 1=keep; 2=relax
+    // hash table for functions
+    int                nTableSize[2];    // hash table size
+    int                nTableEntries[2]; // hash table entries
+    void **            pHashTable[2];    // hash table bins
+    Mem_Fixed_t *      pMemEntries;      // memory manager for hash table entries
+    // statistics 
+//    abctime                timeTruth;
+};
+
+// priority cut
+struct If_Cut_t_
+{
+    float              Area;          // area (or area-flow) of the cut
+    float              Edge;          // the edge flow
+    float              Power;         // the power flow
+    float              Delay;         // delay of the cut
+    int                iCutFunc;      // TT ID of the cut
+    int                uMaskFunc;     // polarity bitmask
+    unsigned           uSign;         // cut signature
+    unsigned           Cost    : 13;  // the user's cost of the cut (related to IF_COST_MAX)
+    unsigned           fCompl  :  1;  // the complemented attribute 
+    unsigned           fUser   :  1;  // using the user's area and delay
+    unsigned           fUseless:  1;  // using the user's area and delay
+    unsigned           nLimit  :  8;  // the maximum number of leaves
+    unsigned           nLeaves :  8;  // the number of leaves
+    int                pLeaves[0];
+};
+
+// set of priority cut
+struct If_Set_t_
+{
+    short              nCutsMax;      // the max number of cuts
+    short              nCuts;         // the current number of cuts
+    If_Set_t *         pNext;         // next cutset in the free list
+    If_Cut_t **        ppCuts;        // the array of pointers to the cuts
+};
+
+// node extension
+struct If_Obj_t_
+{
+    unsigned           Type    :  4;  // object
+    unsigned           fCompl0 :  1;  // complemented attribute
+    unsigned           fCompl1 :  1;  // complemented attribute
+    unsigned           fPhase  :  1;  // phase of the node
+    unsigned           fRepr   :  1;  // representative of the equivalence class
+    unsigned           fMark   :  1;  // multipurpose mark
+    unsigned           fVisit  :  1;  // multipurpose mark
+    unsigned           fSpec   :  1;  // multipurpose mark
+    unsigned           fDriver :  1;  // multipurpose mark
+    unsigned           fSkipCut:  1;  // multipurpose mark
+    unsigned           Level   : 19;  // logic level of the node
+    int                Id;            // integer ID
+    int                IdPio;         // integer ID of PIs/POs
+    int                nRefs;         // the number of references
+    int                nVisits;       // the number of visits to this node
+    int                nVisitsCopy;   // the number of visits to this node
+    If_Obj_t *         pFanin0;       // the first fanin 
+    If_Obj_t *         pFanin1;       // the second fanin
+    If_Obj_t *         pEquiv;        // the choice node
+    float              EstRefs;       // estimated reference counter
+    float              Required;      // required time of the onde
+    float              LValue;        // sequential arrival time of the node
+    union{
+    void *             pCopy;         // used for object duplication
+    int                iCopy;
+    };
+    
+    If_Set_t *         pCutSet;       // the pointer to the cutset
+    If_Cut_t           CutBest;       // the best cut selected 
+};
+
+typedef struct If_Box_t_ If_Box_t;
+struct If_Box_t_
+{
+    char *             pName;
+    char               fSeq;
+    char               fBlack;
+    char               fOuter;
+    char               fUnused;
+    int                Id;
+    int                nPis;
+    int                nPos;
+    int *              pDelays;
+};
+
+struct If_LibBox_t_
+{
+    Vec_Ptr_t *        vBoxes;
+};
+
+static inline If_Obj_t * If_Regular( If_Obj_t * p )                          { return (If_Obj_t *)((ABC_PTRUINT_T)(p) & ~01);  }
+static inline If_Obj_t * If_Not( If_Obj_t * p )                              { return (If_Obj_t *)((ABC_PTRUINT_T)(p) ^  01);  }
+static inline If_Obj_t * If_NotCond( If_Obj_t * p, int c )                   { return (If_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c));  }
+static inline int        If_IsComplement( If_Obj_t * p )                     { return (int )(((ABC_PTRUINT_T)p) & 01);         }
+
+static inline int        If_ManCiNum( If_Man_t * p )                         { return p->nObjs[IF_CI];               }
+static inline int        If_ManCoNum( If_Man_t * p )                         { return p->nObjs[IF_CO];               }
+static inline int        If_ManAndNum( If_Man_t * p )                        { return p->nObjs[IF_AND];              }
+static inline int        If_ManObjNum( If_Man_t * p )                        { return Vec_PtrSize(p->vObjs);         }
+
+static inline If_Obj_t * If_ManConst1( If_Man_t * p )                        { return p->pConst1;                              }
+static inline If_Obj_t * If_ManCi( If_Man_t * p, int i )                     { return (If_Obj_t *)Vec_PtrEntry( p->vCis, i );  }
+static inline If_Obj_t * If_ManCo( If_Man_t * p, int i )                     { return (If_Obj_t *)Vec_PtrEntry( p->vCos, i );  }
+static inline If_Obj_t * If_ManLi( If_Man_t * p, int i )                     { return (If_Obj_t *)Vec_PtrEntry( p->vCos, If_ManCoNum(p) - p->pPars->nLatchesCo + i );  }
+static inline If_Obj_t * If_ManLo( If_Man_t * p, int i )                     { return (If_Obj_t *)Vec_PtrEntry( p->vCis, If_ManCiNum(p) - p->pPars->nLatchesCi + i );  }
+static inline If_Obj_t * If_ManObj( If_Man_t * p, int i )                    { return (If_Obj_t *)Vec_PtrEntry( p->vObjs, i ); }
+
+static inline int        If_ObjIsConst1( If_Obj_t * pObj )                   { return pObj->Type == IF_CONST1;       }
+static inline int        If_ObjIsCi( If_Obj_t * pObj )                       { return pObj->Type == IF_CI;           }
+static inline int        If_ObjIsCo( If_Obj_t * pObj )                       { return pObj->Type == IF_CO;           }
+static inline int        If_ObjIsTerm( If_Obj_t * pObj )                     { return pObj->Type == IF_CI || pObj->Type == IF_CO; }
+static inline int        If_ObjIsLatch( If_Obj_t * pObj )                    { return If_ObjIsCi(pObj) && pObj->pFanin0 != NULL;  }
+static inline int        If_ObjIsAnd( If_Obj_t * pObj )                      { return pObj->Type == IF_AND;          }
+
+static inline int        If_ObjId( If_Obj_t * pObj )                         { return pObj->Id;                      }
+static inline If_Obj_t * If_ObjFanin0( If_Obj_t * pObj )                     { return pObj->pFanin0;                 }
+static inline If_Obj_t * If_ObjFanin1( If_Obj_t * pObj )                     { return pObj->pFanin1;                 }
+static inline int        If_ObjFaninC0( If_Obj_t * pObj )                    { return pObj->fCompl0;                 }
+static inline int        If_ObjFaninC1( If_Obj_t * pObj )                    { return pObj->fCompl1;                 }
+static inline void *     If_ObjCopy( If_Obj_t * pObj )                       { return pObj->pCopy;                   }
+static inline int        If_ObjLevel( If_Obj_t * pObj )                      { return pObj->Level;                   }
+static inline void       If_ObjSetLevel( If_Obj_t * pObj, int Level )        { pObj->Level = Level;                  }
+static inline void       If_ObjSetCopy( If_Obj_t * pObj, void * pCopy )      { pObj->pCopy = pCopy;                  }
+static inline void       If_ObjSetChoice( If_Obj_t * pObj, If_Obj_t * pEqu ) { pObj->pEquiv = pEqu;                  }
+
+static inline int        If_CutLeaveNum( If_Cut_t * pCut )                   { return pCut->nLeaves;                             }
+static inline int *      If_CutLeaves( If_Cut_t * pCut )                     { return pCut->pLeaves;                             }
+static inline If_Obj_t * If_CutLeaf( If_Man_t * p, If_Cut_t * pCut, int i )  { assert(i >= 0 && i < (int)pCut->nLeaves); return If_ManObj(p, pCut->pLeaves[i]);                         }
+static inline unsigned   If_CutSuppMask( If_Cut_t * pCut )                   { return (~(unsigned)0) >> (32-pCut->nLeaves);      }
+static inline int        If_CutTruthWords( int nVarsMax )                    { return nVarsMax <= 5 ? 2 : (1 << (nVarsMax - 5)); }
+static inline int        If_CutPermWords( int nVarsMax )                     { return nVarsMax / sizeof(int) + ((nVarsMax % sizeof(int)) > 0); }
+static inline int        If_CutLeafBit( If_Cut_t * pCut, int i )             { return (pCut->uMaskFunc >> i) & 1;                }
+static inline char *     If_CutPerm( If_Cut_t * pCut )                       { return (char *)(pCut->pLeaves + pCut->nLeaves);   }
+static inline void       If_CutCopy( If_Man_t * p, If_Cut_t * pDst, If_Cut_t * pSrc ) { memcpy( pDst, pSrc, p->nCutBytes );      }
+static inline void       If_CutSetup( If_Man_t * p, If_Cut_t * pCut        ) { memset(pCut, 0, p->nCutBytes); pCut->nLimit = p->pPars->nLutSize; }
+
+static inline If_Cut_t * If_ObjCutBest( If_Obj_t * pObj )                    { return &pObj->CutBest;                }
+static inline unsigned   If_ObjCutSign( unsigned ObjId )                     { return (1 << (ObjId % 31));           }
+static inline unsigned   If_ObjCutSignCompute( If_Cut_t * p )                { unsigned s = 0; int i; for ( i = 0; i < If_CutLeaveNum(p); i++ ) s |= If_ObjCutSign(p->pLeaves[i]); return s; }
+
+static inline float      If_ObjArrTime( If_Obj_t * pObj )                    { return If_ObjCutBest(pObj)->Delay;    }
+static inline void       If_ObjSetArrTime( If_Obj_t * pObj, float ArrTime )  { If_ObjCutBest(pObj)->Delay = ArrTime; }
+
+static inline float      If_ObjLValue( If_Obj_t * pObj )                     { return pObj->LValue;                  }
+static inline void       If_ObjSetLValue( If_Obj_t * pObj, float LValue )    { pObj->LValue = LValue;                }
+
+static inline void *     If_CutData( If_Cut_t * pCut )                       { return *(void **)pCut;                }
+static inline void       If_CutSetData( If_Cut_t * pCut, void * pData )      { *(void **)pCut = pData;               }
+
+static inline int        If_CutDataInt( If_Cut_t * pCut )                    { return *(int *)pCut;                  }
+static inline void       If_CutSetDataInt( If_Cut_t * pCut, int Data )       { *(int *)pCut = Data;                  }
+
+static inline int        If_CutTruthLit( If_Cut_t * pCut )                   { assert( pCut->iCutFunc >= 0 ); return pCut->iCutFunc;             }
+static inline int        If_CutTruthIsCompl( If_Cut_t * pCut )               { assert( pCut->iCutFunc >= 0 ); return Abc_LitIsCompl(pCut->iCutFunc);                               }
+static inline word *     If_CutTruthWR( If_Man_t * p, If_Cut_t * pCut )      { return p->vTtMem ? Vec_MemReadEntry(p->vTtMem[pCut->nLeaves], Abc_Lit2Var(pCut->iCutFunc)) : NULL;  }
+static inline unsigned * If_CutTruthUR( If_Man_t * p, If_Cut_t * pCut)       { return (unsigned *)If_CutTruthWR(p, pCut);                        }
+static inline word *     If_CutTruthW( If_Man_t * p, If_Cut_t * pCut )       { if ( p->vTtMem == NULL ) return NULL; assert( pCut->iCutFunc >= 0 ); Abc_TtCopy( p->puTempW, If_CutTruthWR(p, pCut), p->nTruth6Words[pCut->nLeaves], If_CutTruthIsCompl(pCut) ); return p->puTempW;  }
+static inline unsigned * If_CutTruth( If_Man_t * p, If_Cut_t * pCut )        { return (unsigned *)If_CutTruthW(p, pCut);                         }
+
+static inline int        If_CutDsdLit( If_Man_t * p, If_Cut_t * pCut )       { return Abc_Lit2LitL( Vec_IntArray(p->vTtDsds[pCut->nLeaves]), If_CutTruthLit(pCut) );               }
+static inline int        If_CutDsdIsCompl( If_Man_t * p, If_Cut_t * pCut )   { return Abc_LitIsCompl( If_CutDsdLit(p, pCut) );                                                     }
+static inline char *     If_CutDsdPerm( If_Man_t * p, If_Cut_t * pCut )      { return Vec_StrEntryP( p->vTtPerms[pCut->nLeaves], Abc_Lit2Var(pCut->iCutFunc) * Abc_MaxInt(6, pCut->nLeaves) );           }
+
+static inline float      If_CutLutArea( If_Man_t * p, If_Cut_t * pCut )      { return pCut->fUser? (float)pCut->Cost : (p->pPars->pLutLib? p->pPars->pLutLib->pLutAreas[pCut->nLeaves] : (float)1.0);    }
+static inline float      If_CutLutDelay( If_LibLut_t * p, int Size, int iPin )  { return p ? (p->fVarPinDelays ? p->pLutDelays[Size][iPin] : p->pLutDelays[Size][0]) : 1.0;                              }
+
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define IF_MIN(a,b)      (((a) < (b))? (a) : (b))
+#define IF_MAX(a,b)      (((a) > (b))? (a) : (b))
+
+// the small and large numbers (min/max float are 1.17e-38/3.40e+38)
+#define IF_FLOAT_LARGE   ((float)1.0e+20)
+#define IF_FLOAT_SMALL   ((float)1.0e-20)
+#define IF_INT_LARGE     (10000000)
+
+// iterator over the primary inputs
+#define If_ManForEachCi( p, pObj, i )                                          \
+    Vec_PtrForEachEntry( If_Obj_t *, p->vCis, pObj, i )
+// iterator over the primary outputs
+#define If_ManForEachCo( p, pObj, i )                                          \
+    Vec_PtrForEachEntry( If_Obj_t *, p->vCos, pObj, i )
+// iterator over the primary inputs
+#define If_ManForEachPi( p, pObj, i )                                          \
+    Vec_PtrForEachEntryStop( If_Obj_t *, p->vCis, pObj, i, If_ManCiNum(p) - p->pPars->nLatchesCi - p->pPars->nLatchesCiBox )
+// iterator over the primary outputs
+#define If_ManForEachPo( p, pObj, i )                                          \
+    Vec_PtrForEachEntryStartStop( If_Obj_t *, p->vCos, pObj, i, p->pPars->nLatchesCoBox, If_ManCoNum(p) - p->pPars->nLatchesCo )
+// iterator over the latches 
+#define If_ManForEachLatchInput( p, pObj, i )                                  \
+    Vec_PtrForEachEntryStart( If_Obj_t *, p->vCos, pObj, i, If_ManCoNum(p) - p->pPars->nLatchesCo )
+#define If_ManForEachLatchOutput( p, pObj, i )                                 \
+    Vec_PtrForEachEntryStartStop( If_Obj_t *, p->vCis, pObj, i, If_ManCiNum(p) - p->pPars->nLatchesCi - p->pPars->nLatchesCiBox, If_ManCiNum(p) - p->pPars->nLatchesCiBox )
+// iterator over all objects in topological order
+#define If_ManForEachObj( p, pObj, i )                                         \
+    Vec_PtrForEachEntry( If_Obj_t *, p->vObjs, pObj, i )
+// iterator over all objects in reverse topological order
+#define If_ManForEachObjReverse( p, pObj, i )                                  \
+    Vec_PtrForEachEntry( If_Obj_t *, p->vObjsRev, pObj, i )
+// iterator over logic nodes 
+#define If_ManForEachNode( p, pObj, i )                                        \
+    If_ManForEachObj( p, pObj, i ) if ( pObj->Type != IF_AND ) {} else
+// iterator over cuts of the node
+#define If_ObjForEachCut( pObj, pCut, i )                                      \
+    for ( i = 0; (i < (pObj)->pCutSet->nCuts) && ((pCut) = (pObj)->pCutSet->ppCuts[i]); i++ )
+// iterator over the leaves of the cut
+#define If_CutForEachLeaf( p, pCut, pLeaf, i )                                 \
+    for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i])); i++ )
+#define If_CutForEachLeafReverse( p, pCut, pLeaf, i )                                 \
+    for ( i = (int)(pCut)->nLeaves - 1; (i >= 0) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i])); i-- )
+//#define If_CutForEachLeaf( p, pCut, pLeaf, i )                                 \ \\prevent multiline comment
+//    for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, p->pPars->fLiftLeaves? (pCut)->pLeaves[i] >> 8 : (pCut)->pLeaves[i])); i++ )
+// iterator over the leaves of the sequential cut
+#define If_CutForEachLeafSeq( p, pCut, pLeaf, Shift, i )                       \
+    for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i] >> 8)) && (((Shift) = ((pCut)->pLeaves[i] & 255)) >= 0); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== ifCore.c ===========================================================*/
+extern void            If_ManSetDefaultPars( If_Par_t * pPars );
+extern int             If_ManPerformMapping( If_Man_t * p );
+extern int             If_ManPerformMappingComb( If_Man_t * p );
+extern void            If_ManComputeSwitching( If_Man_t * p );
+/*=== ifCut.c ============================================================*/
+extern int             If_CutVerifyCuts( If_Set_t * pCutSet, int fOrdered );
+extern int             If_CutFilter( If_Set_t * pCutSet, If_Cut_t * pCut, int fSaveCut0 );
+extern void            If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut );
+extern void            If_CutOrder( If_Cut_t * pCut );
+extern int             If_CutMergeOrdered( If_Man_t * p, If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut );
+extern int             If_CutMerge( If_Man_t * p, If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut );
+extern int             If_CutCheck( If_Cut_t * pCut );
+extern void            If_CutPrint( If_Cut_t * pCut );
+extern void            If_CutPrintTiming( If_Man_t * p, If_Cut_t * pCut );
+extern void            If_CutLift( If_Cut_t * pCut );
+extern void            If_CutCopy( If_Man_t * p, If_Cut_t * pCutDest, If_Cut_t * pCutSrc );
+extern float           If_CutAreaFlow( If_Man_t * p, If_Cut_t * pCut );
+extern float           If_CutEdgeFlow( If_Man_t * p, If_Cut_t * pCut );
+extern float           If_CutPowerFlow( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot );
+extern float           If_CutAverageRefs( If_Man_t * p, If_Cut_t * pCut );
+extern float           If_CutAreaDeref( If_Man_t * p, If_Cut_t * pCut );
+extern float           If_CutAreaRef( If_Man_t * p, If_Cut_t * pCut );
+extern float           If_CutAreaDerefed( If_Man_t * p, If_Cut_t * pCut );
+extern float           If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut );
+extern float           If_CutEdgeDeref( If_Man_t * p, If_Cut_t * pCut );
+extern float           If_CutEdgeRef( If_Man_t * p, If_Cut_t * pCut );
+extern float           If_CutEdgeDerefed( If_Man_t * p, If_Cut_t * pCut );
+extern float           If_CutEdgeRefed( If_Man_t * p, If_Cut_t * pCut );
+extern float           If_CutPowerDeref( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot );
+extern float           If_CutPowerRef( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot );
+extern float           If_CutPowerDerefed( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot );
+extern float           If_CutPowerRefed( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot );
+/*=== ifDec.c =============================================================*/
+extern word            If_CutPerformDerive07( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
+extern int             If_CutPerformCheck07( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
+extern int             If_CutPerformCheck08( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
+extern int             If_CutPerformCheck10( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
+extern int             If_CutPerformCheck16( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
+extern int             If_CutPerformCheck45( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
+extern int             If_CutPerformCheck54( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
+extern int             If_CutPerformCheck75( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
+extern float           If_CutDelayLutStruct( If_Man_t * p, If_Cut_t * pCut, char * pStr, float WireDelay );
+extern int             If_CluCheckExt( void * p, word * pTruth, int nVars, int nLutLeaf, int nLutRoot, 
+                           char * pLut0, char * pLut1, word * pFunc0, word * pFunc1 );
+extern int             If_CluCheckExt3( void * p, word * pTruth, int nVars, int nLutLeaf, int nLutLeaf2, int nLutRoot, 
+                           char * pLut0, char * pLut1, char * pLut2, word * pFunc0, word * pFunc1, word * pFunc2 );
+/*=== ifDelay.c =============================================================*/
+extern int             If_CutDelaySop( If_Man_t * p, If_Cut_t * pCut );
+extern int             If_CutSopBalanceEvalInt( Vec_Int_t * vCover, int * pTimes, int * pFaninLits, Vec_Int_t * vAig, int * piRes, int nSuppAll, int * pArea );
+extern int             If_CutSopBalanceEval( If_Man_t * p, If_Cut_t * pCut, Vec_Int_t * vAig );
+extern int             If_CutSopBalancePinDelaysInt( Vec_Int_t * vCover, int * pTimes, word * pFaninRes, int nSuppAll, word * pRes );
+extern int             If_CutSopBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm );
+extern int             If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut );
+extern int             If_CutLutBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm );
+/*=== ifDsd.c =============================================================*/
+extern If_DsdMan_t *   If_DsdManAlloc( int nVars, int nLutSize );
+extern void            If_DsdManAllocIsops( If_DsdMan_t * p, int nLutSize );
+extern void            If_DsdManPrint( If_DsdMan_t * p, char * pFileName, int Number, int Support, int fOccurs, int fTtDump, int fVerbose );
+extern void            If_DsdManTune( If_DsdMan_t * p, int LutSize, int fFast, int fAdd, int fSpec, int fVerbose );
+extern void            If_DsdManFree( If_DsdMan_t * p, int fVerbose );
+extern void            If_DsdManSave( If_DsdMan_t * p, char * pFileName );
+extern If_DsdMan_t *   If_DsdManLoad( char * pFileName );
+extern void            If_DsdManMerge( If_DsdMan_t * p, If_DsdMan_t * pNew );
+extern void            If_DsdManClean( If_DsdMan_t * p, int fVerbose );
+extern int             If_DsdManCompute( If_DsdMan_t * p, word * pTruth, int nLeaves, unsigned char * pPerm, char * pLutStruct );
+extern char *          If_DsdManFileName( If_DsdMan_t * p );
+extern int             If_DsdManVarNum( If_DsdMan_t * p );
+extern int             If_DsdManLutSize( If_DsdMan_t * p );
+extern int             If_DsdManSuppSize( If_DsdMan_t * p, int iDsd );
+extern int             If_DsdManCheckDec( If_DsdMan_t * p, int iDsd );
+extern unsigned        If_DsdManCheckXY( If_DsdMan_t * p, int iDsd, int LutSize, int fDerive, unsigned uMaskNot, int fHighEffort, int fVerbose );
+extern int             If_CutDsdBalanceEval( If_Man_t * p, If_Cut_t * pCut, Vec_Int_t * vAig );
+extern int             If_CutDsdBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm );
+/*=== ifLib.c =============================================================*/
+extern If_LibLut_t *   If_LibLutRead( char * FileName );
+extern If_LibLut_t *   If_LibLutDup( If_LibLut_t * p );
+extern void            If_LibLutFree( If_LibLut_t * pLutLib );
+extern void            If_LibLutPrint( If_LibLut_t * pLutLib );
+extern int             If_LibLutDelaysAreDiscrete( If_LibLut_t * pLutLib );
+extern int             If_LibLutDelaysAreDifferent( If_LibLut_t * pLutLib );
+extern If_LibLut_t *   If_LibLutSetSimple( int nLutSize );
+extern float           If_LibLutFastestPinDelay( If_LibLut_t * p );
+extern float           If_LibLutSlowestPinDelay( If_LibLut_t * p );
+/*=== ifLibBox.c =============================================================*/
+extern If_LibBox_t *   If_LibBoxStart();
+extern void            If_LibBoxFree( If_LibBox_t * p );
+extern If_Box_t *      If_LibBoxReadBox( If_LibBox_t * p, int Id );
+extern If_Box_t *      If_LibBoxFindBox( If_LibBox_t * p, char * pName );
+extern void            If_LibBoxAdd( If_LibBox_t * p, If_Box_t * pBox );
+extern If_LibBox_t *   If_LibBoxRead( char * pFileName );
+extern If_LibBox_t *   If_LibBoxRead2( char * pFileName );
+extern void            If_LibBoxPrint( FILE * pFile, If_LibBox_t * p );
+extern void            If_LibBoxWrite( char * pFileName, If_LibBox_t * p );
+extern int             If_LibBoxLoad( char * pFileName );
+/*=== ifMan.c =============================================================*/
+extern If_Man_t *      If_ManStart( If_Par_t * pPars );
+extern void            If_ManRestart( If_Man_t * p );
+extern void            If_ManStop( If_Man_t * p );
+extern If_Obj_t *      If_ManCreateCi( If_Man_t * p );
+extern If_Obj_t *      If_ManCreateCo( If_Man_t * p, If_Obj_t * pDriver );
+extern If_Obj_t *      If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 );
+extern If_Obj_t *      If_ManCreateXor( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 );
+extern If_Obj_t *      If_ManCreateMux( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1, If_Obj_t * pCtrl );
+extern void            If_ManCreateChoice( If_Man_t * p, If_Obj_t * pRepr );
+extern void            If_ManSetupCutTriv( If_Man_t * p, If_Cut_t * pCut, int ObjId );
+extern void            If_ManSetupCiCutSets( If_Man_t * p );
+extern If_Set_t *      If_ManSetupNodeCutSet( If_Man_t * p, If_Obj_t * pObj );
+extern void            If_ManDerefNodeCutSet( If_Man_t * p, If_Obj_t * pObj );
+extern void            If_ManDerefChoiceCutSet( If_Man_t * p, If_Obj_t * pObj );
+extern void            If_ManSetupSetAll( If_Man_t * p, int nCrossCut );
+/*=== ifMap.c =============================================================*/
+extern void            If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess, int fFirst );
+extern void            If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess );
+extern int             If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPreprocess, int fFirst, char * pLabel );
+/*=== ifReduce.c ==========================================================*/
+extern void            If_ManImproveMapping( If_Man_t * p );
+/*=== ifSat.c ==========================================================*/
+extern void *          If_ManSatBuildXY( int nLutSize );
+extern void *          If_ManSatBuildXYZ( int nLutSize );
+extern void            If_ManSatUnbuild( void * p );
+extern int             If_ManSatCheckXY( void * pSat, int nLutSize, word * pTruth, int nVars, unsigned uSet, word * pTBound, word * pTFree, Vec_Int_t * vLits );
+extern unsigned        If_ManSatCheckXYall( void * pSat, int nLutSize, word * pTruth, int nVars, Vec_Int_t * vLits );
+/*=== ifSeq.c =============================================================*/
+extern int             If_ManPerformMappingSeq( If_Man_t * p );
+/*=== ifTime.c ============================================================*/
+extern float           If_CutDelay( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut );
+extern void            If_CutPropagateRequired( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut, float Required );
+extern float           If_ManDelayMax( If_Man_t * p, int fSeq );
+extern void            If_ManComputeRequired( If_Man_t * p );
+/*=== ifTruth.c ===========================================================*/
+extern void            If_CutRotatePins( If_Man_t * p, If_Cut_t * pCut );
+extern int             If_CutComputeTruth( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 );
+extern int             If_CutComputeTruthPerm( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 );
+/*=== ifUtil.c ============================================================*/
+extern void            If_ManCleanNodeCopy( If_Man_t * p );
+extern void            If_ManCleanCutData( If_Man_t * p );
+extern void            If_ManCleanMarkV( If_Man_t * p );
+extern float           If_ManScanMapping( If_Man_t * p );
+extern float           If_ManScanMappingDirect( If_Man_t * p );
+extern float           If_ManScanMappingSeq( If_Man_t * p );
+extern void            If_ManResetOriginalRefs( If_Man_t * p );
+extern int             If_ManCrossCut( If_Man_t * p );
+
+extern Vec_Ptr_t *     If_ManReverseOrder( If_Man_t * p );
+extern void            If_ManMarkMapping( If_Man_t * p );
+extern Vec_Ptr_t *     If_ManCollectMappingDirect( If_Man_t * p );
+extern Vec_Int_t *     If_ManCollectMappingInt( If_Man_t * p );
+
+extern int             If_ManCountSpecialPos( If_Man_t * p );
+extern void            If_CutTraverse( If_Man_t * p, If_Obj_t * pRoot, If_Cut_t * pCut, Vec_Ptr_t * vNodes );
+extern void            If_ObjPrint( If_Obj_t * pObj );
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/map/if/ifCache.c b/abc-build/src/map/if/ifCache.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifCache.c
@@ -0,0 +1,100 @@
+/**CFile****************************************************************
+
+  FileName    [ifCache.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifCache.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+#include "misc/vec/vecHsh.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManCacheRecord( If_Man_t * p, int iDsd0, int iDsd1, int nShared, int iDsd )
+{
+    assert( nShared >= 0 && nShared <= p->pPars->nLutSize );
+    if ( p->vCutData == NULL )
+        p->vCutData = Vec_IntAlloc( 10000 );
+    if ( iDsd0 > iDsd1 )
+        ABC_SWAP( int, iDsd0, iDsd1 );
+    Vec_IntPush( p->vCutData, iDsd0 );
+    Vec_IntPush( p->vCutData, iDsd1 );
+    Vec_IntPush( p->vCutData, nShared );
+    Vec_IntPush( p->vCutData, iDsd );
+//    printf( "%6d %6d %6d %6d\n", iDsd0, iDsd1, nShared, iDsd );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManCacheAnalize( If_Man_t * p )
+{
+    Vec_Int_t * vRes, * vTest[32];
+    int i, Entry, uUnique;
+    vRes = Hsh_IntManHashArray( p->vCutData, 4 );
+    for ( i = 0; i <= p->pPars->nLutSize; i++ )
+        vTest[i] = Vec_IntAlloc( 1000 );
+    Vec_IntForEachEntry( vRes, Entry, i )
+        Vec_IntPush( vTest[Vec_IntEntry(p->vCutData, 4*i+2)], Entry );
+    for ( i = 0; i <= p->pPars->nLutSize; i++ )
+    {
+        uUnique = Vec_IntCountUnique(vTest[i]);
+        printf( "%2d-var entries = %8d. (%6.2f %%)  Unique entries = %8d. (%6.2f %%)\n", 
+            i, Vec_IntSize(vTest[i]), 100.0*Vec_IntSize(vTest[i])/Abc_MaxInt(1, Vec_IntSize(vRes)), 
+            uUnique, 100.0*uUnique/Abc_MaxInt(1, Vec_IntSize(vTest[i])) );
+    }
+    for ( i = 0; i <= p->pPars->nLutSize; i++ )
+        Vec_IntFree( vTest[i] );
+    uUnique = Vec_IntCountUnique(vRes);
+    printf( "Total  entries = %8d. (%6.2f %%)  Unique entries = %8d. (%6.2f %%)\n", 
+        Vec_IntSize(p->vCutData)/4, 100.0, uUnique, 100.0*uUnique/Abc_MaxInt(1, Vec_IntSize(p->vCutData)/4) );
+    Vec_IntFree( vRes );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifCheck.c b/abc-build/src/map/if/ifCheck.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifCheck.c
@@ -0,0 +1,204 @@
+/**CFile****************************************************************
+
+  FileName    [ifCheck.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Sequential mapping.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifCheck.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#ifdef WIN32
+typedef unsigned __int64 word;
+#else
+typedef unsigned long long word;
+#endif
+
+// elementary truth tables
+static word Truths6[6] = {
+    0xAAAAAAAAAAAAAAAA,
+    0xCCCCCCCCCCCCCCCC,
+    0xF0F0F0F0F0F0F0F0,
+    0xFF00FF00FF00FF00,
+    0xFFFF0000FFFF0000,
+    0xFFFFFFFF00000000
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node Leaf is reachable on the path.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManCutReach_rec( If_Obj_t * pPath, If_Obj_t * pLeaf )
+{
+    if ( pPath == pLeaf )
+        return 1;
+    if ( pPath->fMark )
+        return 0;
+    assert( If_ObjIsAnd(pPath) );
+    if ( If_ManCutReach_rec( If_ObjFanin0(pPath), pLeaf ) )
+        return 1;
+    if ( If_ManCutReach_rec( If_ObjFanin1(pPath), pLeaf ) )
+        return 1;
+    return 0;
+}
+int If_ManCutReach( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pPath, If_Obj_t * pLeaf )
+{
+    If_Obj_t * pTemp;
+    int i, RetValue;
+    If_CutForEachLeaf( p, pCut, pTemp, i )
+        pTemp->fMark = 1;
+    RetValue = If_ManCutReach_rec( pPath, pLeaf );
+    If_CutForEachLeaf( p, pCut, pTemp, i )
+        pTemp->fMark = 0;
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive truth table for each cofactor.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManCutTruthCheck_rec( If_Obj_t * pObj, word * pTruths )
+{
+    word T0, T1;
+    if ( pObj->fMark )
+        return pTruths[If_ObjId(pObj)];
+    assert( If_ObjIsAnd(pObj) );
+    T0 = If_ManCutTruthCheck_rec( If_ObjFanin0(pObj), pTruths );
+    T1 = If_ManCutTruthCheck_rec( If_ObjFanin1(pObj), pTruths );
+    T0 = If_ObjFaninC0(pObj) ? ~T0 : T0;
+    T1 = If_ObjFaninC1(pObj) ? ~T1 : T1;
+    return T0 & T1;
+}
+int If_ManCutTruthCheck( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut, If_Obj_t * pLeaf, int Cof, word * pTruths )
+{
+    word Truth;
+    If_Obj_t * pTemp;
+    int i, k = 0;
+    assert( Cof == 0 || Cof == 1 );
+    If_CutForEachLeaf( p, pCut, pTemp, i )
+    {
+        assert( pTemp->fMark == 0 );
+        pTemp->fMark = 1;
+        if ( pLeaf == pTemp )
+            pTruths[If_ObjId(pTemp)] = (Cof ? ~((word)0) : 0);
+        else
+            pTruths[If_ObjId(pTemp)] = Truths6[k++] ;
+    }
+    assert( k + 1 == If_CutLeaveNum(pCut) );
+    // compute truth table
+    Truth = If_ManCutTruthCheck_rec( pObj, pTruths );
+    If_CutForEachLeaf( p, pCut, pTemp, i )
+        pTemp->fMark = 0;
+    return Truth == 0 || Truth == ~((word)0);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if cut can be structurally/functionally decomposed.]
+
+  Description [The decomposition is Fn(a,b,c,...) = F2(a, Fn-1(b,c,...)).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManCutCheck( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut )
+{
+    static int nDecCalls    = 0;
+    static int nDecStruct   = 0;
+    static int nDecStruct2  = 0;
+    static int nDecFunction = 0;
+    word * pTruths;
+    If_Obj_t * pLeaf, * pPath;
+    int i;
+    if ( pCut == NULL )
+    {
+        printf( "DecStr  = %9d (%6.2f %%).\n", nDecStruct,   100.0*nDecStruct/nDecCalls );
+        printf( "DecStr2 = %9d (%6.2f %%).\n", nDecStruct2,  100.0*nDecStruct2/nDecCalls );
+        printf( "DecFunc = %9d (%6.2f %%).\n", nDecFunction, 100.0*nDecFunction/nDecCalls );
+        printf( "Total   = %9d (%6.2f %%).\n", nDecCalls,    100.0*nDecCalls/nDecCalls );
+        return;
+    }
+    assert( If_ObjIsAnd(pObj) );
+    assert( pCut->nLeaves <= 7 );
+    nDecCalls++;
+    // check structural decomposition
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+        if ( pLeaf == If_ObjFanin0(pObj) || pLeaf == If_ObjFanin1(pObj) )
+            break;
+    if ( i < If_CutLeaveNum(pCut) )
+    {
+        pPath = (pLeaf == If_ObjFanin0(pObj)) ? If_ObjFanin1(pObj) : If_ObjFanin0(pObj);
+        if ( !If_ManCutReach( p, pCut, pPath, pLeaf ) )
+        {
+            nDecStruct++;
+//            nDecFunction++;
+//            return;
+        }
+        else
+            nDecStruct2++;
+    }
+    // check functional decomposition
+    pTruths = malloc( sizeof(word) * If_ManObjNum(p) );
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+    {
+        if ( If_ManCutTruthCheck( p, pObj, pCut, pLeaf, 0, pTruths ) )
+        {
+            nDecFunction++;
+            break;
+        }
+        if ( If_ManCutTruthCheck( p, pObj, pCut, pLeaf, 1, pTruths ) )
+        {
+            nDecFunction++;
+            break;
+        }
+    }
+    free( pTruths );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifCom.c b/abc-build/src/map/if/ifCom.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifCom.c
@@ -0,0 +1,372 @@
+/**CFile****************************************************************
+
+  FileName    [ifCom.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Command handlers.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifCom.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int If_CommandReadLut ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int If_CommandPrintLut( Abc_Frame_t * pAbc, int argc, char **argv );
+static int If_CommandReadBox ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int If_CommandPrintBox( Abc_Frame_t * pAbc, int argc, char **argv );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Package initialization procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_Init( Abc_Frame_t * pAbc )
+{
+    // set the default library
+    If_LibLut_t s_LutLib = { "lutlib", 4, 0, {0,1,1,1,1}, {{0},{1},{1},{1},{1}} };
+    Abc_FrameSetLibLut( If_LibLutDup(&s_LutLib) );
+
+    Cmd_CommandAdd( pAbc, "FPGA mapping", "read_lut",   If_CommandReadLut,   0 ); 
+    Cmd_CommandAdd( pAbc, "FPGA mapping", "print_lut",  If_CommandPrintLut,  0 ); 
+
+    Cmd_CommandAdd( pAbc, "FPGA mapping", "read_box",   If_CommandReadBox,   0 ); 
+    Cmd_CommandAdd( pAbc, "FPGA mapping", "print_box",  If_CommandPrintBox,  0 ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Package ending procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_End( Abc_Frame_t * pAbc )
+{
+    If_LibLutFree( (If_LibLut_t *)   Abc_FrameReadLibLut() );
+    If_LibBoxFree( (If_LibBox_t *)Abc_FrameReadLibBox() );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Command procedure to read LUT libraries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CommandReadLut( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    FILE * pFile;
+    FILE * pOut, * pErr;
+    If_LibLut_t * pLib;
+    Abc_Ntk_t * pNet;
+    char * FileName;
+    int fVerbose;
+    int c;
+
+    pNet = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    // set the defaults
+    fVerbose = 1;
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) 
+    {
+        switch (c) 
+        {
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+                break;
+            default:
+                goto usage;
+        }
+    }
+
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+
+    // get the input file name
+    FileName = argv[globalUtilOptind];
+    if ( (pFile = fopen( FileName, "r" )) == NULL )
+    {
+        fprintf( pErr, "Cannot open input file \"%s\". ", FileName );
+        if ( (FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL )) )
+            fprintf( pErr, "Did you mean \"%s\"?", FileName );
+        fprintf( pErr, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+
+    // set the new network
+    pLib = If_LibLutRead( FileName );
+    if ( pLib == NULL )
+    {
+        fprintf( pErr, "Reading LUT library has failed.\n" );
+        goto usage;
+    }
+    // replace the current library
+    If_LibLutFree( (If_LibLut_t *)Abc_FrameReadLibLut() );
+    Abc_FrameSetLibLut( pLib );
+    return 0;
+
+usage:
+    fprintf( pErr, "\nusage: read_lut [-vh]\n");
+    fprintf( pErr, "\t          read the LUT library from the file\n" );  
+    fprintf( pErr, "\t-v      : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") );
+    fprintf( pErr, "\t-h      : print the command usage\n");
+    fprintf( pErr, "\t                                        \n");
+    fprintf( pErr, "\t          File format for a LUT library:\n");
+    fprintf( pErr, "\t          (the default library is shown)\n");
+    fprintf( pErr, "\t                                        \n");
+    fprintf( pErr, "\t          # The area/delay of k-variable LUTs:\n");
+    fprintf( pErr, "\t          # k  area   delay\n");
+    fprintf( pErr, "\t          1      1      1\n");
+    fprintf( pErr, "\t          2      2      2\n");
+    fprintf( pErr, "\t          3      4      3\n");
+    fprintf( pErr, "\t          4      8      4\n");
+    fprintf( pErr, "\t          5     16      5\n");
+    fprintf( pErr, "\t          6     32      6\n");
+    return 1;       /* error exit */
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Command procedure to read LUT libraries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CommandPrintLut( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    FILE * pOut, * pErr;
+    Abc_Ntk_t * pNet;
+    int fVerbose;
+    int c;
+
+    pNet = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    // set the defaults
+    fVerbose = 1;
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) 
+    {
+        switch (c) 
+        {
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+                break;
+            default:
+                goto usage;
+        }
+    }
+
+    if ( argc != globalUtilOptind )
+        goto usage;
+
+    // set the new network
+    If_LibLutPrint( (If_LibLut_t *)Abc_FrameReadLibLut() );
+    return 0;
+
+usage:
+    fprintf( pErr, "\nusage: print_lut [-vh]\n");
+    fprintf( pErr, "\t          print the current LUT library\n" );  
+    fprintf( pErr, "\t-v      : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") );
+    fprintf( pErr, "\t-h      : print the command usage\n");
+    return 1;       /* error exit */
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CommandReadBox( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    FILE * pFile;
+    FILE * pOut, * pErr;
+    If_LibBox_t * pLib;
+    Abc_Ntk_t * pNet;
+    char * FileName;
+    int fExtended;
+    int fVerbose;
+    int c;
+
+    pNet = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    // set the defaults
+    fExtended = 0;
+    fVerbose = 1;
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "evh")) != EOF ) 
+    {
+        switch (c) 
+        {
+            case 'e':
+                fExtended ^= 1;
+                break;
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+                break;
+            default:
+                goto usage;
+        }
+    }
+
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+
+    // get the input file name
+    FileName = argv[globalUtilOptind];
+    if ( (pFile = fopen( FileName, "r" )) == NULL )
+    {
+        fprintf( pErr, "Cannot open input file \"%s\". ", FileName );
+        if ( (FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL )) )
+            fprintf( pErr, "Did you mean \"%s\"?", FileName );
+        fprintf( pErr, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+
+    // set the new network
+    pLib = fExtended ? If_LibBoxRead2( FileName ) : If_LibBoxRead( FileName );
+    if ( pLib == NULL )
+    {
+        fprintf( pErr, "Reading box library has failed.\n" );
+        goto usage;
+    }
+    // replace the current library
+    If_LibBoxFree( (If_LibBox_t *)Abc_FrameReadLibBox() );
+    Abc_FrameSetLibBox( pLib );
+    return 0;
+
+usage:
+    fprintf( pErr, "\nusage: read_box [-evh]\n");
+    fprintf( pErr, "\t          read the box library from the file\n" );  
+    fprintf( pErr, "\t-e      : toggles reading extended format [default = %s]\n", (fExtended? "yes" : "no") );
+    fprintf( pErr, "\t-v      : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") );
+    fprintf( pErr, "\t-h      : print the command usage\n");
+    return 1;       /* error exit */
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Command procedure to read LUT libraries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CommandPrintBox( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    FILE * pOut, * pErr;
+    Abc_Ntk_t * pNet;
+    int fVerbose;
+    int c;
+
+    pNet = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    // set the defaults
+    fVerbose = 1;
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) 
+    {
+        switch (c) 
+        {
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+                break;
+            default:
+                goto usage;
+        }
+    }
+
+    if ( argc != globalUtilOptind )
+        goto usage;
+
+    // set the new network
+    If_LibBoxPrint( stdout, (If_LibBox_t *)Abc_FrameReadLibBox() );
+    return 0;
+
+usage:
+    fprintf( pErr, "\nusage: print_box [-vh]\n");
+    fprintf( pErr, "\t          print the current box library\n" );  
+    fprintf( pErr, "\t-v      : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") );
+    fprintf( pErr, "\t-h      : print the command usage\n");
+    return 1;       /* error exit */
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifCore.c b/abc-build/src/map/if/ifCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifCore.c
@@ -0,0 +1,199 @@
+/**CFile****************************************************************
+
+  FileName    [ifCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [The central part of the mapper.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifCore.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern abctime s_MappingTime;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManSetDefaultPars( If_Par_t * pPars )
+{
+    memset( pPars, 0, sizeof(If_Par_t) );
+    pPars->nLutSize    = -1;
+    pPars->nCutsMax    =  8;
+    pPars->nFlowIters  =  1;
+    pPars->nAreaIters  =  2;
+    pPars->DelayTarget = -1;
+    pPars->Epsilon     =  (float)0.005;
+    pPars->fPreprocess =  1;
+    pPars->fArea       =  0;
+    pPars->fFancy      =  0;
+    pPars->fExpRed     =  1;
+    pPars->fLatchPaths =  0;
+    pPars->fEdge       =  1;
+    pPars->fPower      =  0;
+    pPars->fCutMin     =  0;
+    pPars->fBidec      =  0;
+    pPars->fVerbose    =  0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManPerformMapping( If_Man_t * p )
+{
+    p->pPars->fAreaOnly = p->pPars->fArea; // temporary
+    // create the CI cutsets
+    If_ManSetupCiCutSets( p );
+    // allocate memory for other cutsets
+    If_ManSetupSetAll( p, If_ManCrossCut(p) );
+    // derive reverse top order
+    p->vObjsRev = If_ManReverseOrder( p );
+    return If_ManPerformMappingComb( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManPerformMappingComb( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    abctime clkTotal = Abc_Clock();
+    int i;
+
+    // set arrival times and fanout estimates
+    If_ManForEachCi( p, pObj, i )
+    {
+        If_ObjSetArrTime( pObj, p->pPars->pTimesArr ? p->pPars->pTimesArr[i] : (float)0.0 );
+        pObj->EstRefs = (float)1.0;
+    }
+
+    // delay oriented mapping
+    if ( p->pPars->fPreprocess && !p->pPars->fArea )
+    {
+        // map for delay
+        If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, 1, "Delay" );
+        // map for delay second option
+        p->pPars->fFancy = 1;
+        If_ManResetOriginalRefs( p );
+        If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, 0, "Delay-2" );
+        p->pPars->fFancy = 0;
+        // map for area
+        p->pPars->fArea = 1;
+        If_ManResetOriginalRefs( p );
+        If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, 0, "Area" );
+        p->pPars->fArea = 0;
+    }
+    else
+        If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 0, 1, "Delay" );
+
+    // try to improve area by expanding and reducing the cuts
+    if ( p->pPars->fExpRed )
+        If_ManImproveMapping( p );
+
+    // area flow oriented mapping
+    for ( i = 0; i < p->pPars->nFlowIters; i++ )
+    {
+        If_ManPerformMappingRound( p, p->pPars->nCutsMax, 1, 0, 0, "Flow" );
+        if ( p->pPars->fExpRed )
+            If_ManImproveMapping( p );
+    }
+
+    // area oriented mapping
+    for ( i = 0; i < p->pPars->nAreaIters; i++ )
+    {
+        If_ManPerformMappingRound( p, p->pPars->nCutsMax, 2, 0, 0, "Area" );
+        if ( p->pPars->fExpRed )
+            If_ManImproveMapping( p );
+    }
+
+    if ( p->pPars->fVerbose )
+    {
+//        Abc_Print( 1, "Total memory = %7.2f MB. Peak cut memory = %7.2f MB.  ", 
+//            1.0 * (p->nObjBytes + 2*sizeof(void *)) * If_ManObjNum(p) / (1<<20), 
+//            1.0 * p->nSetBytes * Mem_FixedReadMaxEntriesUsed(p->pMemSet) / (1<<20) );
+        Abc_PrintTime( 1, "Total time", Abc_Clock() - clkTotal );
+    }
+//    Abc_Print( 1, "Cross cut memory = %d.\n", Mem_FixedReadMaxEntriesUsed(p->pMemSet) );
+    s_MappingTime = Abc_Clock() - clkTotal;
+//    Abc_Print( 1, "Special POs = %d.\n", If_ManCountSpecialPos(p) );
+
+/*
+    {
+        static char * pLastName = NULL;
+        FILE * pTable = fopen( "fpga/ucsb/stats.txt", "a+" );
+        if ( pLastName == NULL || strcmp(pLastName, p->pName) )
+        {
+            fprintf( pTable, "\n" );
+            fprintf( pTable, "%s ", p->pName );
+
+            fprintf( pTable, "%d ", If_ManCiNum(p) );
+            fprintf( pTable, "%d ", If_ManCoNum(p) );
+            fprintf( pTable, "%d ", If_ManAndNum(p) );
+
+            ABC_FREE( pLastName );
+            pLastName = Abc_UtilStrsav( p->pName );
+        }
+
+        fprintf( pTable, "%d ", (int)p->AreaGlo );
+        fprintf( pTable, "%d ", (int)p->RequiredGlo );
+        fclose( pTable );
+    }
+*/
+    p->pPars->FinalDelay = p->RequiredGlo;
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifCount.h b/abc-build/src/map/if/ifCount.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifCount.h
@@ -0,0 +1,521 @@
+/**CFile****************************************************************
+
+  FileName    [ifCount.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifCount.h,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__map__if__if_Count_h
+#define ABC__map__if__if_Count_h
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+ 
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int If_LogCreateAnd( Vec_Int_t * vAig, int iLit0, int iLit1, int nSuppAll )
+{
+    int iObjId = Vec_IntSize(vAig)/2 + nSuppAll;
+    assert( Abc_Lit2Var(iLit0) != Abc_Lit2Var(iLit1) );
+    Vec_IntPush( vAig, iLit0 );
+    Vec_IntPush( vAig, iLit1 );
+    return Abc_Var2Lit( iObjId, 0 );
+}
+static inline int If_LogCreateMux( Vec_Int_t * vAig, int iLitC, int iLit1, int iLit0, int nSuppAll )
+{
+    int iFanLit0 = If_LogCreateAnd( vAig, iLitC, iLit1, nSuppAll );
+    int iFanLit1 = If_LogCreateAnd( vAig, Abc_LitNot(iLitC), iLit0, nSuppAll );
+    int iResLit  = If_LogCreateAnd( vAig, Abc_LitNot(iFanLit0), Abc_LitNot(iFanLit1), nSuppAll );
+    return Abc_LitNot(iResLit);
+}
+static inline int If_LogCreateXor( Vec_Int_t * vAig, int iLit0, int iLit1, int nSuppAll )
+{
+    return If_LogCreateMux( vAig, iLit0, Abc_LitNot(iLit1), iLit1, nSuppAll );
+}
+static inline int If_LogCreateAndXor( Vec_Int_t * vAig, int iLit0, int iLit1, int nSuppAll, int fXor )
+{
+    return fXor ? If_LogCreateXor(vAig, iLit0, iLit1, nSuppAll) : If_LogCreateAnd(vAig, iLit0, iLit1, nSuppAll);
+}
+static inline int If_LogCreateAndXorMulti( Vec_Int_t * vAig, int * pFaninLits, int nFanins, int nSuppAll, int fXor )
+{
+    int i;
+    assert( nFanins > 0 );
+    for ( i = nFanins - 1; i > 0; i-- )
+        pFaninLits[i-1] = If_LogCreateAndXor( vAig, pFaninLits[i], pFaninLits[i-1], nSuppAll, fXor );
+    return pFaninLits[0];
+}
+static inline int If_LogCounterAddAig( int * pTimes, int * pnTimes, int * pFaninLits, int Num, int iLit, Vec_Int_t * vAig, int nSuppAll, int fXor )
+{
+    int nTimes = *pnTimes;
+    if ( vAig )
+        pFaninLits[nTimes] = iLit;
+    pTimes[nTimes++] = Num;
+    if ( nTimes > 1 )
+    {
+        int i, k;
+        for ( k = nTimes-1; k > 0; k-- )
+        {
+            if ( pTimes[k] < pTimes[k-1] )
+                break;
+            if ( pTimes[k] > pTimes[k-1] )
+            { 
+                ABC_SWAP( int, pTimes[k], pTimes[k-1] ); 
+                if ( vAig )
+                    ABC_SWAP( int, pFaninLits[k], pFaninLits[k-1] ); 
+                continue; 
+            }
+            pTimes[k-1] += 1 + fXor;
+            if ( vAig )
+                pFaninLits[k-1] = If_LogCreateAndXor( vAig, pFaninLits[k], pFaninLits[k-1], nSuppAll, fXor );
+            for ( nTimes--, i = k; i < nTimes; i++ )
+            {
+                pTimes[i] = pTimes[i+1];
+                if ( vAig )
+                    pFaninLits[i] = pFaninLits[i+1];
+            }
+        }
+    }
+    assert( nTimes > 0 );
+    *pnTimes = nTimes;
+    return pTimes[0] + (nTimes > 1 ? 1 + fXor : 0);
+}
+static inline int If_LogCounterDelayXor( int * pTimes, int nTimes )
+{
+    int i;
+    assert( nTimes > 0 );
+    for ( i = nTimes - 1; i > 0; i-- )
+        pTimes[i-1] = 2 + Abc_MaxInt( pTimes[i], pTimes[i-1] );
+    return pTimes[0];
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compute delay/area profile of the structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int  If_CutPinDelayGet( word D, int v )           { assert(v >= 0 && v < IF_MAX_FUNC_LUTSIZE); return (int)((D >> (v << 2)) & 0xF);                             }
+static inline void If_CutPinDelaySet( word * pD, int v, int d ) { assert(v >= 0 && v < IF_MAX_FUNC_LUTSIZE); assert(d >= 0 && d < IF_MAX_FUNC_LUTSIZE); *pD |= ((word)d << (v << 2)); }
+static inline word If_CutPinDelayInit( int v )                  { assert(v >= 0 && v < IF_MAX_FUNC_LUTSIZE); return (word)1 << (v << 2);                                      }
+static inline word If_CutPinDelayMax( word D1, word D2, int nVars, int AddOn )
+{
+    int v, Max;
+    word D = 0;
+    for ( v = 0; v < nVars; v++ )
+        if ( (Max = Abc_MaxInt(If_CutPinDelayGet(D1, v), If_CutPinDelayGet(D2, v))) )
+            If_CutPinDelaySet( &D, v, Abc_MinInt(Max + AddOn, 15) );
+    return D;
+}
+static inline word If_CutPinDelayDecrement( word D1, int nVars )
+{
+    int v;
+    word D = 0;
+    for ( v = 0; v < nVars; v++ )
+        if ( If_CutPinDelayGet(D1, v) )
+            If_CutPinDelaySet( &D, v, If_CutPinDelayGet(D1, v) - 1 );
+    return D;
+}
+static inline int If_CutPinDelayEqual( word D1, word D2, int nVars ) // returns 1 if D1 has the same delays than D2
+{
+    int v;
+    for ( v = 0; v < nVars; v++ )
+        if ( If_CutPinDelayGet(D1, v) != If_CutPinDelayGet(D2, v) )
+            return 0;
+    return 1;
+}
+static inline int If_CutPinDelayDom( word D1, word D2, int nVars ) // returns 1 if D1 has the same or smaller delays than D2
+{
+    int v;
+    for ( v = 0; v < nVars; v++ )
+        if ( If_CutPinDelayGet(D1, v) > If_CutPinDelayGet(D2, v) )
+            return 0;
+    return 1;
+}
+static inline void If_CutPinDelayTranslate( word D, int nVars, char * pPerm ) 
+{
+    int v, Delay;
+    for ( v = 0; v < nVars; v++ )
+    {
+        Delay = If_CutPinDelayGet(D, v);
+        assert( Delay > 1 );
+        pPerm[v] = Delay - 1;
+    }
+}
+static inline void If_CutPinDelayPrint( word D, int nVars )
+{
+    int v;
+    printf( "Delay profile = {" );
+    for ( v = 0; v < nVars; v++ )
+        printf( " %d", If_CutPinDelayGet(D, v) );
+    printf( " }\n" );
+}
+static inline int If_LogCounterPinDelays( int * pTimes, int * pnTimes, word * pPinDels, int Num, word PinDel, int nSuppAll, int fXor )
+{
+    int nTimes = *pnTimes;
+    pPinDels[nTimes] = PinDel;
+    pTimes[nTimes++] = Num;
+    if ( nTimes > 1 )
+    {
+        int i, k;
+        for ( k = nTimes-1; k > 0; k-- )
+        {
+            if ( pTimes[k] < pTimes[k-1] )
+                break;
+            if ( pTimes[k] > pTimes[k-1] )
+            { 
+                ABC_SWAP( int, pTimes[k], pTimes[k-1] ); 
+                ABC_SWAP( word, pPinDels[k], pPinDels[k-1] ); 
+                continue; 
+            }
+            pTimes[k-1] += 1 + fXor;
+            pPinDels[k-1] = If_CutPinDelayMax( pPinDels[k], pPinDels[k-1], nSuppAll, 1 + fXor );
+            for ( nTimes--, i = k; i < nTimes; i++ )
+            {
+                pTimes[i] = pTimes[i+1];
+                pPinDels[i] = pPinDels[i+1];
+            }
+        }
+    }
+    assert( nTimes > 0 );
+    *pnTimes = nTimes;
+    return pTimes[0] + (nTimes > 1 ? 1 + fXor : 0);
+}
+static inline word If_LogPinDelaysMulti( word * pPinDels, int nFanins, int nSuppAll, int fXor )
+{
+    int i;
+    assert( nFanins > 0 );
+    for ( i = nFanins - 1; i > 0; i-- )
+        pPinDels[i-1] = If_CutPinDelayMax( pPinDels[i], pPinDels[i-1], nSuppAll, 1 + fXor );
+    return pPinDels[0];
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word If_AigVerifyArray( Vec_Int_t * vAig, int nLeaves )
+{
+    assert( Vec_IntSize(vAig) > 0 );
+    assert( Vec_IntEntryLast(vAig) < 2 );
+    if ( Vec_IntSize(vAig) == 1 ) // const
+        return Vec_IntEntry(vAig, 0) ? ~((word)0) : 0;
+    if ( Vec_IntSize(vAig) == 2 ) // variable
+    {
+        assert( Vec_IntEntry(vAig, 0) == 0 );
+        return Vec_IntEntry(vAig, 1) ? ~s_Truths6[0] : s_Truths6[0];
+    }
+    else
+    {
+        word Truth0 = 0, Truth1 = 0, TruthR;
+        int i, iVar0, iVar1, iLit0, iLit1;
+        assert( Vec_IntSize(vAig) & 1 );
+        Vec_IntForEachEntryDouble( vAig, iLit0, iLit1, i )
+        {
+            iVar0 = Abc_Lit2Var( iLit0 );
+            iVar1 = Abc_Lit2Var( iLit1 );
+            Truth0 = iVar0 < nLeaves ? s_Truths6[iVar0] : Vec_WrdEntry( (Vec_Wrd_t *)vAig, iVar0 - nLeaves );
+            Truth1 = iVar1 < nLeaves ? s_Truths6[iVar1] : Vec_WrdEntry( (Vec_Wrd_t *)vAig, iVar1 - nLeaves );
+            if ( Abc_LitIsCompl(iLit0) )
+                Truth0 = ~Truth0;
+            if ( Abc_LitIsCompl(iLit1) )
+                Truth1 = ~Truth1;
+            assert( (i & 1) == 0 );
+            Vec_WrdWriteEntry( (Vec_Wrd_t *)vAig, Abc_Lit2Var(i), Truth0 & Truth1 );  // overwriting entries
+        }
+        assert( i == Vec_IntSize(vAig) - 1 );
+        TruthR = Truth0 & Truth1;
+        if ( Vec_IntEntry(vAig, i) )
+            TruthR = ~TruthR;
+        Vec_IntClear( vAig ); // useless
+        return TruthR;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void If_AigPrintArray( Vec_Int_t * vAig, int nLeaves )
+{
+    assert( Vec_IntSize(vAig) > 0 );
+    assert( Vec_IntEntryLast(vAig) < 2 );
+    if ( Vec_IntSize(vAig) == 1 ) // const
+        printf( "Const %d\n", Vec_IntEntry(vAig, 0) );
+    else if ( Vec_IntSize(vAig) == 2 ) // variable
+        printf( "Variable %s\n", Vec_IntEntry(vAig, 1) ? "Compl" : "" );
+    else
+    {
+        int i, iLit0, iLit1;
+        assert( Vec_IntSize(vAig) & 1 );
+        Vec_IntForEachEntryDouble( vAig, iLit0, iLit1, i )
+            printf( "%d %d\n", iLit0, iLit1 );
+        assert( i == Vec_IntSize(vAig) - 1 );
+        printf( "%s\n", Vec_IntEntry(vAig, i) ? "Compl" : "" );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Naive implementation of log-counter.]
+
+  Description [Incrementally computes [log2(SUMi(2^di)).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int If_LogCounter64Eval( word Count )
+{
+    int n = ((Count & (Count - 1)) > 0) ? -1 : 0;
+    assert( Count > 0 );
+    if ( (Count & ABC_CONST(0xFFFFFFFF00000000)) == 0 ) { n += 32; Count <<= 32; }
+    if ( (Count & ABC_CONST(0xFFFF000000000000)) == 0 ) { n += 16; Count <<= 16; }
+    if ( (Count & ABC_CONST(0xFF00000000000000)) == 0 ) { n +=  8; Count <<=  8; }
+    if ( (Count & ABC_CONST(0xF000000000000000)) == 0 ) { n +=  4; Count <<=  4; }
+    if ( (Count & ABC_CONST(0xC000000000000000)) == 0 ) { n +=  2; Count <<=  2; }
+    if ( (Count & ABC_CONST(0x8000000000000000)) == 0 ) { n++; }
+    return 63 - n;
+}
+static word If_LogCounter64Add( word Count, int Num )
+{
+    assert( Num < 48 );
+    return Count + (((word)1) << Num);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implementation of log-counter.]
+
+  Description [Incrementally computes [log2(SUMi(2^di)).
+  Supposed to work correctly up to 16 entries.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int If_LogCounter32Eval( unsigned Count, int Start )
+{
+    int n = (Abc_LitIsCompl(Start) || (Count & (Count - 1)) > 0) ? -1 : 0;
+    assert( Count > 0 );
+    if ( (Count & 0xFFFF0000) == 0 ) { n += 16; Count <<= 16; }
+    if ( (Count & 0xFF000000) == 0 ) { n +=  8; Count <<=  8; }
+    if ( (Count & 0xF0000000) == 0 ) { n +=  4; Count <<=  4; }
+    if ( (Count & 0xC0000000) == 0 ) { n +=  2; Count <<=  2; }
+    if ( (Count & 0x80000000) == 0 ) { n++; }
+    return Abc_Lit2Var(Start) + 31 - n;
+}
+static unsigned If_LogCounter32Add( unsigned Count, int * pStart, int Num )
+{
+    int Start = Abc_Lit2Var(*pStart);
+    if ( Num < Start )
+    {
+        *pStart |= 1;
+        return Count;
+    }
+    if ( Num > Start + 16 )
+    {
+        int Shift = Num - (Start + 16);
+        if ( !Abc_LitIsCompl(*pStart) && (Shift >= 32 ? Count : Count & ~(~0 << Shift)) > 0 )
+            *pStart |= 1;
+        Count >>= Shift;
+        Start += Shift;
+        *pStart = Abc_Var2Lit( Start, Abc_LitIsCompl(*pStart) );
+        assert( Num <= Start + 16 );
+    }
+    return Count + (1 << (Num-Start));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Testing of the counter]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+void If_LogCounterTest2()
+{
+    word Count64 = 0;
+
+    unsigned Count = 0; 
+    int Start = 0;
+
+    int Result, Result64;
+
+    Count = If_LogCounter32Add( Count, &Start, 39 );
+    Count = If_LogCounter32Add( Count, &Start, 35 );
+    Count = If_LogCounter32Add( Count, &Start, 35 );
+    Count = If_LogCounter32Add( Count, &Start, 36 );
+    Count = If_LogCounter32Add( Count, &Start, 37 );
+    Count = If_LogCounter32Add( Count, &Start, 38 );
+    Count = If_LogCounter32Add( Count, &Start, 40 );
+    Count = If_LogCounter32Add( Count, &Start, 1 );
+    Count = If_LogCounter32Add( Count, &Start, 41 );
+    Count = If_LogCounter32Add( Count, &Start, 42 );
+
+    Count64 = If_LogCounter64Add( Count64, 1 );
+    Count64 = If_LogCounter64Add( Count64, 35 );
+    Count64 = If_LogCounter64Add( Count64, 35 );
+    Count64 = If_LogCounter64Add( Count64, 36 );
+    Count64 = If_LogCounter64Add( Count64, 37 );
+    Count64 = If_LogCounter64Add( Count64, 38 );
+    Count64 = If_LogCounter64Add( Count64, 39 );
+    Count64 = If_LogCounter64Add( Count64, 40 );
+    Count64 = If_LogCounter64Add( Count64, 41 );
+    Count64 = If_LogCounter64Add( Count64, 42 );
+
+    Result = If_LogCounter32Eval( Count, Start );
+    Result64 = If_LogCounter64Eval( Count64 );
+
+    printf( "%d  %d\n", Result, Result64 );
+}
+*/
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the number to the numbers stored.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int If_LogCounterAdd( int * pTimes, int * pnTimes, int Num, int fXor )
+{
+    int nTimes = *pnTimes;
+    pTimes[nTimes++] = Num;
+    if ( nTimes > 1 )
+    {
+        int i, k;
+        for ( k = nTimes-1; k > 0; k-- )
+        {
+            if ( pTimes[k] < pTimes[k-1] )
+                break;
+            if ( pTimes[k] > pTimes[k-1] )
+            { 
+                ABC_SWAP( int, pTimes[k], pTimes[k-1] ); 
+                continue; 
+            }
+            pTimes[k-1] += 1 + fXor;
+            for ( nTimes--, i = k; i < nTimes; i++ )
+                pTimes[i] = pTimes[i+1];
+        }
+    }
+    assert( nTimes > 0 );
+    *pnTimes = nTimes;
+    return pTimes[0] + (nTimes > 1 ? 1 + fXor : 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Testing of the counter]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+void If_LogCounterTest()
+{
+    int pArray[10] = { 1, 2, 4, 5, 6, 3, 1 };
+    int i, nSize = 4;
+
+    word Count64 = 0;
+    int Result, Result64;
+
+    int pTimes[100];
+    int nTimes = 0;
+
+    for ( i = 0; i < nSize; i++ )
+        Count64 = If_LogCounter64Add( Count64, pArray[i] );
+    Result64 = If_LogCounter64Eval( Count64 );
+
+    for ( i = 0; i < nSize; i++ )
+        Result = If_LogCounterAdd( pTimes, &nTimes, pArray[i], 0 );
+
+    printf( "%d  %d\n", Result64, Result );
+}
+*/
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/map/if/ifCut.c b/abc-build/src/map/if/ifCut.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifCut.c
@@ -0,0 +1,1476 @@
+/**CFile****************************************************************
+
+  FileName    [ifCut.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Cut computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifCut.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Check correctness of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int If_CutVerifyCut( If_Cut_t * pBase, If_Cut_t * pCut ) // check if pCut is contained in pBase
+{
+    int nSizeB = pBase->nLeaves;
+    int nSizeC = pCut->nLeaves;
+    int * pB = pBase->pLeaves;
+    int * pC = pCut->pLeaves;
+    int i, k;
+    for ( i = 0; i < nSizeC; i++ )
+    {
+        for ( k = 0; k < nSizeB; k++ )
+            if ( pC[i] == pB[k] )
+                break;
+        if ( k == nSizeB )
+            return 0;
+    }
+    return 1;
+}
+int If_CutVerifyCuts( If_Set_t * pCutSet, int fOrdered )
+{
+    static int Count = 0;
+    If_Cut_t * pCut0, * pCut1; 
+    int i, k, m, n, Value;
+    assert( pCutSet->nCuts > 0 );
+    for ( i = 0; i < pCutSet->nCuts; i++ )
+    {
+        pCut0 = pCutSet->ppCuts[i];
+        assert( pCut0->uSign == If_ObjCutSignCompute(pCut0) );
+        if ( fOrdered )
+        {
+            // check duplicates
+            for ( m = 1; m < (int)pCut0->nLeaves; m++ )
+                assert( pCut0->pLeaves[m-1] < pCut0->pLeaves[m] );
+        }
+        else
+        {
+            // check duplicates
+            for ( m = 0; m < (int)pCut0->nLeaves; m++ )
+            for ( n = m+1; n < (int)pCut0->nLeaves; n++ )
+            assert( pCut0->pLeaves[m] != pCut0->pLeaves[n] );
+        }
+        // check pairs
+        for ( k = 0; k < pCutSet->nCuts; k++ )
+        {
+            pCut1 = pCutSet->ppCuts[k];
+            if ( pCut0 == pCut1 )
+                continue;
+            Count++;
+            // check containments
+            Value = If_CutVerifyCut( pCut0, pCut1 );
+//            assert( Value == 0 );
+            if ( Value )
+            {
+                assert( pCut0->uSign == If_ObjCutSignCompute(pCut0) );
+                assert( pCut1->uSign == If_ObjCutSignCompute(pCut1) );
+                If_CutPrint( pCut0 );
+                If_CutPrint( pCut1 );
+                assert( 0 );
+            }
+        }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pDom is contained in pCut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int If_CutCheckDominance( If_Cut_t * pDom, If_Cut_t * pCut )
+{
+    int i, k;
+    assert( pDom->nLeaves <= pCut->nLeaves );
+    for ( i = 0; i < (int)pDom->nLeaves; i++ )
+    {
+        for ( k = 0; k < (int)pCut->nLeaves; k++ )
+            if ( pDom->pLeaves[i] == pCut->pLeaves[k] )
+                break;
+        if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut
+            return 0;
+    }
+    // every node in pDom is contained in pCut
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the cut is contained.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutFilter( If_Set_t * pCutSet, If_Cut_t * pCut, int fSaveCut0 )
+{ 
+    If_Cut_t * pTemp;
+    int i, k;
+    assert( pCutSet->ppCuts[pCutSet->nCuts] == pCut );
+    for ( i = 0; i < pCutSet->nCuts; i++ )
+    {
+        pTemp = pCutSet->ppCuts[i];
+        if ( pTemp->nLeaves > pCut->nLeaves )
+        {
+            // do not fiter the first cut
+            if ( i == 0 && ((pCutSet->nCuts > 1 && pCutSet->ppCuts[1]->fUseless) || (fSaveCut0 && pCutSet->nCuts == 1)) )
+                continue;
+            // skip the non-contained cuts
+            if ( (pTemp->uSign & pCut->uSign) != pCut->uSign )
+                continue;
+            // check containment seriously
+            if ( If_CutCheckDominance( pCut, pTemp ) )
+            {
+//                p->ppCuts[i] = p->ppCuts[p->nCuts-1];
+//                p->ppCuts[p->nCuts-1] = pTemp;
+//                p->nCuts--;
+//                i--;
+                // remove contained cut
+                for ( k = i; k < pCutSet->nCuts; k++ )
+                    pCutSet->ppCuts[k] = pCutSet->ppCuts[k+1];
+                pCutSet->ppCuts[pCutSet->nCuts] = pTemp;
+                pCutSet->nCuts--;
+                i--;
+            }
+         }
+        else
+        {
+            // skip the non-contained cuts
+            if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign )
+                continue;
+            // check containment seriously
+            if ( If_CutCheckDominance( pTemp, pCut ) )
+                return 1;
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the object for FPGA mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutMergeOrdered_( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC1, If_Cut_t * pC )
+{ 
+    int nSizeC0 = pC0->nLeaves;
+    int nSizeC1 = pC1->nLeaves;
+    int nLimit  = pC0->nLimit;
+    int i, k, c, s;
+
+    // both cuts are the largest
+    if ( nSizeC0 == nLimit && nSizeC1 == nLimit )
+    {
+        for ( i = 0; i < nSizeC0; i++ )
+        {
+            if ( pC0->pLeaves[i] != pC1->pLeaves[i] )
+                return 0;
+            p->pPerm[0][i] = p->pPerm[1][i] = p->pPerm[2][i] = i;
+            pC->pLeaves[i] = pC0->pLeaves[i];
+        }
+        pC->nLeaves = nLimit;
+        pC->uSign = pC0->uSign | pC1->uSign;
+        p->uSharedMask = Abc_InfoMask( nLimit );
+        return 1;
+    }
+
+    // compare two cuts with different numbers
+    i = k = c = s = 0;
+    p->uSharedMask = 0;
+    if ( nSizeC0 == 0 ) goto FlushCut1;
+    if ( nSizeC1 == 0 ) goto FlushCut0;
+    while ( 1 )
+    {
+        if ( c == nLimit ) return 0;
+        if ( pC0->pLeaves[i] < pC1->pLeaves[k] )
+        {
+            p->pPerm[0][i] = c;
+            pC->pLeaves[c++] = pC0->pLeaves[i++];
+            if ( i == nSizeC0 ) goto FlushCut1;
+        }
+        else if ( pC0->pLeaves[i] > pC1->pLeaves[k] )
+        {
+            p->pPerm[1][k] = c;
+            pC->pLeaves[c++] = pC1->pLeaves[k++];
+            if ( k == nSizeC1 ) goto FlushCut0;
+        }
+        else
+        {
+            p->uSharedMask |= (1 << c);
+            p->pPerm[0][i] = p->pPerm[1][k] = p->pPerm[2][s++] = c;
+            pC->pLeaves[c++] = pC0->pLeaves[i++]; k++;
+            if ( i == nSizeC0 ) goto FlushCut1;
+            if ( k == nSizeC1 ) goto FlushCut0;
+        }
+    }
+
+FlushCut0:
+    if ( c + nSizeC0 > nLimit + i ) return 0;
+    while ( i < nSizeC0 )
+    {
+        p->pPerm[0][i] = c;
+        pC->pLeaves[c++] = pC0->pLeaves[i++];
+    }
+    pC->nLeaves = c;
+    pC->uSign = pC0->uSign | pC1->uSign;
+    assert( c > 0 );
+    return 1;
+
+FlushCut1:
+    if ( c + nSizeC1 > nLimit + k ) return 0;
+    while ( k < nSizeC1 )
+    {
+        p->pPerm[1][k] = c;
+        pC->pLeaves[c++] = pC1->pLeaves[k++];
+    }
+    pC->nLeaves = c;
+    pC->uSign = pC0->uSign | pC1->uSign;
+    assert( c > 0 );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the object for FPGA mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutMergeOrdered( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC1, If_Cut_t * pC )
+{ 
+    int nSizeC0 = pC0->nLeaves;
+    int nSizeC1 = pC1->nLeaves;
+    int nLimit  = pC0->nLimit;
+    int i, k, c, s;
+
+    // both cuts are the largest
+    if ( nSizeC0 == nLimit && nSizeC1 == nLimit )
+    {
+        for ( i = 0; i < nSizeC0; i++ )
+        {
+            if ( pC0->pLeaves[i] != pC1->pLeaves[i] )
+                return 0;
+            pC->pLeaves[i] = pC0->pLeaves[i];
+        }
+        pC->nLeaves = nLimit;
+        pC->uSign = pC0->uSign | pC1->uSign;
+        return 1;
+    }
+
+    // compare two cuts with different numbers
+    i = k = c = s = 0; 
+    if ( nSizeC0 == 0 ) goto FlushCut1;
+    if ( nSizeC1 == 0 ) goto FlushCut0;
+    while ( 1 )
+    {
+        if ( c == nLimit ) return 0;
+        if ( pC0->pLeaves[i] < pC1->pLeaves[k] )
+        {
+            pC->pLeaves[c++] = pC0->pLeaves[i++];
+            if ( i == nSizeC0 ) goto FlushCut1;
+        }
+        else if ( pC0->pLeaves[i] > pC1->pLeaves[k] )
+        {
+            pC->pLeaves[c++] = pC1->pLeaves[k++];
+            if ( k == nSizeC1 ) goto FlushCut0;
+        }
+        else
+        {
+            pC->pLeaves[c++] = pC0->pLeaves[i++]; k++;
+            if ( i == nSizeC0 ) goto FlushCut1;
+            if ( k == nSizeC1 ) goto FlushCut0;
+        }
+    }
+
+FlushCut0:
+    if ( c + nSizeC0 > nLimit + i ) return 0;
+    while ( i < nSizeC0 )
+        pC->pLeaves[c++] = pC0->pLeaves[i++];
+    pC->nLeaves = c;
+    pC->uSign = pC0->uSign | pC1->uSign;
+    return 1;
+
+FlushCut1:
+    if ( c + nSizeC1 > nLimit + k ) return 0;
+    while ( k < nSizeC1 )
+        pC->pLeaves[c++] = pC1->pLeaves[k++];
+    pC->nLeaves = c;
+    pC->uSign = pC0->uSign | pC1->uSign;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the object for FPGA mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutMerge( If_Man_t * p, If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut )
+{ 
+    int nLutSize = pCut0->nLimit;
+    int nSize0 = pCut0->nLeaves;
+    int nSize1 = pCut1->nLeaves;
+    int * pC0 = pCut0->pLeaves;
+    int * pC1 = pCut1->pLeaves;
+    int * pC = pCut->pLeaves;
+    int i, k, c;
+    // compare two cuts with different numbers
+    c = nSize0; 
+    for ( i = 0; i < nSize1; i++ )
+    {
+        for ( k = 0; k < nSize0; k++ )
+            if ( pC1[i] == pC0[k] )
+                break;
+        if ( k < nSize0 )
+        {
+            p->pPerm[1][i] = k;
+            continue;
+        }
+        if ( c == nLutSize )
+            return 0;
+        p->pPerm[1][i] = c;
+        pC[c++] = pC1[i];
+    }
+    for ( i = 0; i < nSize0; i++ )
+        pC[i] = pC0[i];
+    pCut->nLeaves = c;
+    pCut->uSign = pCut0->uSign | pCut1->uSign;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the object for FPGA mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutCompareDelay( If_Man_t * p, If_Cut_t ** ppC0, If_Cut_t ** ppC1 )
+{
+    If_Cut_t * pC0 = *ppC0;
+    If_Cut_t * pC1 = *ppC1;
+    if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+        return -1;
+    if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+        return 1;
+    if ( pC0->nLeaves < pC1->nLeaves )
+        return -1;
+    if ( pC0->nLeaves > pC1->nLeaves )
+        return 1;
+    if ( pC0->Area < pC1->Area - p->fEpsilon )
+        return -1;
+    if ( pC0->Area > pC1->Area + p->fEpsilon )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the object for FPGA mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutCompareDelayOld( If_Man_t * p, If_Cut_t ** ppC0, If_Cut_t ** ppC1 )
+{
+    If_Cut_t * pC0 = *ppC0;
+    If_Cut_t * pC1 = *ppC1;
+    if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+        return -1;
+    if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+        return 1;
+    if ( pC0->Area < pC1->Area - p->fEpsilon )
+        return -1;
+    if ( pC0->Area > pC1->Area + p->fEpsilon )
+        return 1;
+    if ( pC0->nLeaves < pC1->nLeaves )
+        return -1;
+    if ( pC0->nLeaves > pC1->nLeaves )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the object for FPGA mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutCompareArea( If_Man_t * p, If_Cut_t ** ppC0, If_Cut_t ** ppC1 )
+{
+    If_Cut_t * pC0 = *ppC0;
+    If_Cut_t * pC1 = *ppC1;
+    if ( pC0->Area < pC1->Area - p->fEpsilon )
+        return -1;
+    if ( pC0->Area > pC1->Area + p->fEpsilon )
+        return 1;
+//    if ( pC0->AveRefs > pC1->AveRefs )
+//        return -1;
+//    if ( pC0->AveRefs < pC1->AveRefs )
+//        return 1;
+    if ( pC0->nLeaves < pC1->nLeaves )
+        return -1;
+    if ( pC0->nLeaves > pC1->nLeaves )
+        return 1;
+    if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+        return -1;
+    if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison function for two cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int If_ManSortCompare( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC1 )
+{
+    if ( p->pPars->fPower )
+    {
+        if ( p->SortMode == 1 ) // area flow       
+        {
+            if ( pC0->Area < pC1->Area - p->fEpsilon )
+                return -1;
+            if ( pC0->Area > pC1->Area + p->fEpsilon )
+                return 1;
+            //Abc_Print( 1,"area(%.2f, %.2f), power(%.2f, %.2f), edge(%.2f, %.2f)\n",
+            //         pC0->Area, pC1->Area, pC0->Power, pC1->Power, pC0->Edge, pC1->Edge);
+            if ( pC0->Power < pC1->Power - p->fEpsilon )
+                return -1;
+            if ( pC0->Power > pC1->Power + p->fEpsilon )
+                return 1;
+            if ( pC0->Edge < pC1->Edge - p->fEpsilon )
+                return -1;
+            if ( pC0->Edge > pC1->Edge + p->fEpsilon )
+                return 1;
+//            if ( pC0->AveRefs > pC1->AveRefs )
+//                return -1;
+//            if ( pC0->AveRefs < pC1->AveRefs )
+//                return 1;
+            if ( pC0->nLeaves < pC1->nLeaves )
+                return -1;
+            if ( pC0->nLeaves > pC1->nLeaves )
+                return 1;
+            if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+                return -1;
+            if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+                return 1;
+            return 0;
+        }
+        if ( p->SortMode == 0 ) // delay
+        {
+            if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+                return -1;
+            if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+                return 1;
+            if ( pC0->nLeaves < pC1->nLeaves )
+                return -1;
+            if ( pC0->nLeaves > pC1->nLeaves )
+                return 1;
+            if ( pC0->Area < pC1->Area - p->fEpsilon )
+                return -1;
+            if ( pC0->Area > pC1->Area + p->fEpsilon )
+                return 1;
+            if ( pC0->Power < pC1->Power - p->fEpsilon  )
+                return -1;
+            if ( pC0->Power > pC1->Power + p->fEpsilon  )
+                return 1;
+            if ( pC0->Edge < pC1->Edge - p->fEpsilon )
+                return -1;
+            if ( pC0->Edge > pC1->Edge + p->fEpsilon )
+                return 1;
+            return 0;
+        }
+        assert( p->SortMode == 2 ); // delay old, exact area
+        if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+            return -1;
+        if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+            return 1;
+        if ( pC0->Power < pC1->Power - p->fEpsilon  )
+            return -1;
+        if ( pC0->Power > pC1->Power + p->fEpsilon  )
+            return 1;
+        if ( pC0->Edge < pC1->Edge - p->fEpsilon )
+            return -1;
+        if ( pC0->Edge > pC1->Edge + p->fEpsilon )
+            return 1;
+        if ( pC0->Area < pC1->Area - p->fEpsilon )
+            return -1;
+        if ( pC0->Area > pC1->Area + p->fEpsilon )
+            return 1;
+        if ( pC0->nLeaves < pC1->nLeaves )
+            return -1;
+        if ( pC0->nLeaves > pC1->nLeaves )
+            return 1;
+        return 0;
+    } 
+    else  // regular
+    {
+        if ( p->SortMode == 1 ) // area
+        {
+            if ( pC0->Area < pC1->Area - p->fEpsilon )
+                return -1;
+            if ( pC0->Area > pC1->Area + p->fEpsilon )
+                return 1;
+            if ( pC0->Edge < pC1->Edge - p->fEpsilon )
+                return -1;
+            if ( pC0->Edge > pC1->Edge + p->fEpsilon )
+                return 1;
+            if ( pC0->Power < pC1->Power - p->fEpsilon )
+                return -1;
+            if ( pC0->Power > pC1->Power + p->fEpsilon )
+                return 1;
+//            if ( pC0->AveRefs > pC1->AveRefs )
+//                return -1;
+//            if ( pC0->AveRefs < pC1->AveRefs )
+//                return 1;
+            if ( pC0->nLeaves < pC1->nLeaves )
+                return -1;
+            if ( pC0->nLeaves > pC1->nLeaves )
+                return 1;
+            if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+                return -1;
+            if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+                return 1;
+            return 0;
+        }
+        if ( p->SortMode == 0 ) // delay
+        {
+            if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+                return -1;
+            if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+                return 1;
+            if ( pC0->nLeaves < pC1->nLeaves )
+                return -1;
+            if ( pC0->nLeaves > pC1->nLeaves )
+                return 1;
+            if ( pC0->Area < pC1->Area - p->fEpsilon )
+                return -1;
+            if ( pC0->Area > pC1->Area + p->fEpsilon )
+                return 1;
+            if ( pC0->Edge < pC1->Edge - p->fEpsilon )
+                return -1;
+            if ( pC0->Edge > pC1->Edge + p->fEpsilon )
+                return 1;
+            if ( pC0->Power < pC1->Power - p->fEpsilon )
+                return -1;
+            if ( pC0->Power > pC1->Power + p->fEpsilon )
+                return 1;
+            return 0;
+        }
+        assert( p->SortMode == 2 ); // delay old
+        if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+            return -1;
+        if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+            return 1;
+        if ( pC0->Area < pC1->Area - p->fEpsilon )
+            return -1;
+        if ( pC0->Area > pC1->Area + p->fEpsilon )
+            return 1;
+        if ( pC0->Edge < pC1->Edge - p->fEpsilon )
+            return -1;
+        if ( pC0->Edge > pC1->Edge + p->fEpsilon )
+            return 1;
+        if ( pC0->Power < pC1->Power - p->fEpsilon )
+            return -1;
+        if ( pC0->Power > pC1->Power + p->fEpsilon )
+            return 1;
+        if ( pC0->nLeaves < pC1->nLeaves )
+            return -1;
+        if ( pC0->nLeaves > pC1->nLeaves )
+            return 1;
+        return 0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison function for two cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int If_ManSortCompare_old( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC1 )
+{
+    if ( p->SortMode == 1 ) // area
+    {
+        if ( pC0->Area < pC1->Area - p->fEpsilon )
+            return -1;
+        if ( pC0->Area > pC1->Area + p->fEpsilon )
+            return 1;
+//        if ( pC0->AveRefs > pC1->AveRefs )
+//            return -1;
+//        if ( pC0->AveRefs < pC1->AveRefs )
+//            return 1;
+        if ( pC0->nLeaves < pC1->nLeaves )
+            return -1;
+        if ( pC0->nLeaves > pC1->nLeaves )
+            return 1;
+        if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+            return -1;
+        if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+            return 1;
+        return 0;
+    }
+    if ( p->SortMode == 0 ) // delay
+    {
+        if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+            return -1;
+        if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+            return 1;
+        if ( pC0->nLeaves < pC1->nLeaves )
+            return -1;
+        if ( pC0->nLeaves > pC1->nLeaves )
+            return 1;
+        if ( pC0->Area < pC1->Area - p->fEpsilon )
+            return -1;
+        if ( pC0->Area > pC1->Area + p->fEpsilon )
+            return 1;
+        return 0;
+    }
+    assert( p->SortMode == 2 ); // delay old
+    if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+        return -1;
+    if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+        return 1;
+    if ( pC0->Area < pC1->Area - p->fEpsilon )
+        return -1;
+    if ( pC0->Area > pC1->Area + p->fEpsilon )
+        return 1;
+    if ( pC0->nLeaves < pC1->nLeaves )
+        return -1;
+    if ( pC0->nLeaves > pC1->nLeaves )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs incremental sorting of cuts.]
+
+  Description [Currently only the trivial sorting is implemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut )
+{
+//    int Counter = 0;
+    int i;
+
+    // the new cut is the last one
+    assert( pCutSet->ppCuts[pCutSet->nCuts] == pCut );
+    assert( pCutSet->nCuts <= pCutSet->nCutsMax );
+
+    // cut structure is empty
+    if ( pCutSet->nCuts == 0 )
+    {
+        pCutSet->nCuts++;
+        return;
+    }
+
+    if ( !pCut->fUseless && 
+         (p->pPars->fUseDsd || p->pPars->fUseBat || 
+          p->pPars->pLutStruct || p->pPars->fUserRecLib || 
+          p->pPars->fEnableCheck07 || p->pPars->fEnableCheck08 || 
+          p->pPars->fEnableCheck10 || p->pPars->fEnableCheck75 || 
+          p->pPars->fEnableCheck75u) )
+    {
+        If_Cut_t * pFirst = pCutSet->ppCuts[0];
+        if ( pFirst->fUseless || If_ManSortCompare(p, pFirst, pCut) == 1 )
+        {
+            pCutSet->ppCuts[0] = pCut;
+            pCutSet->ppCuts[pCutSet->nCuts] = pFirst;
+            If_CutSort( p, pCutSet, pFirst );
+            return;
+        }
+    }
+
+    // the cut will be added - find its place
+    for ( i = pCutSet->nCuts-1; i >= 0; i-- )
+    {
+//        Counter++;
+        if ( If_ManSortCompare( p, pCutSet->ppCuts[i], pCut ) <= 0 || (i == 0 && !pCutSet->ppCuts[0]->fUseless && pCut->fUseless) )
+            break;
+        pCutSet->ppCuts[i+1] = pCutSet->ppCuts[i];
+        pCutSet->ppCuts[i] = pCut;
+    }
+//    Abc_Print( 1, "%d ", Counter );
+
+    // update the number of cuts
+    if ( pCutSet->nCuts < pCutSet->nCutsMax )
+        pCutSet->nCuts++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Orders the leaves of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_CutOrder( If_Cut_t * pCut )
+{
+    int i, Temp, fChanges;
+    do {
+        fChanges = 0;
+        for ( i = 0; i < (int)pCut->nLeaves - 1; i++ )
+        {
+            assert( pCut->pLeaves[i] != pCut->pLeaves[i+1] );
+            if ( pCut->pLeaves[i] <= pCut->pLeaves[i+1] )
+                continue;
+            Temp = pCut->pLeaves[i];
+            pCut->pLeaves[i] = pCut->pLeaves[i+1];
+            pCut->pLeaves[i+1] = Temp;
+            fChanges = 1;
+        }
+    } while ( fChanges );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks correctness of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutCheck( If_Cut_t * pCut )
+{
+    int i;
+    assert( pCut->nLeaves <= pCut->nLimit );
+    if ( pCut->nLeaves < 2 )
+        return 1;
+    for ( i = 1; i < (int)pCut->nLeaves; i++ )
+    {
+        if ( pCut->pLeaves[i-1] >= pCut->pLeaves[i] )
+        {
+            Abc_Print( -1, "If_CutCheck(): Cut has wrong ordering of inputs.\n" );
+            return 0;
+        }
+        assert( pCut->pLeaves[i-1] < pCut->pLeaves[i] );
+    }
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints one cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_CutPrint( If_Cut_t * pCut )
+{
+    unsigned i;
+    Abc_Print( 1, "{" );
+    for ( i = 0; i < pCut->nLeaves; i++ )
+        Abc_Print( 1, " %s%d", If_CutLeafBit(pCut, i) ? "!":"", pCut->pLeaves[i] );
+    Abc_Print( 1, " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints one cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_CutPrintTiming( If_Man_t * p, If_Cut_t * pCut )
+{
+    If_Obj_t * pLeaf;
+    unsigned i;
+    Abc_Print( 1, "{" );
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+        Abc_Print( 1, " %d(%.2f/%.2f)", pLeaf->Id, If_ObjCutBest(pLeaf)->Delay, pLeaf->Required );
+    Abc_Print( 1, " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Moves the cut over the latch.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_CutLift( If_Cut_t * pCut )
+{
+    unsigned i;
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        assert( (pCut->pLeaves[i] & 255) < 255 );
+        pCut->pLeaves[i]++;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area flow.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_CutAreaFlow( If_Man_t * p, If_Cut_t * pCut )
+{
+    If_Obj_t * pLeaf;
+    float Flow;
+    int i;
+    Flow = If_CutLutArea(p, pCut);
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+    {
+        if ( pLeaf->nRefs == 0 || If_ObjIsConst1(pLeaf) )
+            Flow += If_ObjCutBest(pLeaf)->Area;
+        else 
+        {
+            assert( pLeaf->EstRefs > p->fEpsilon );
+            Flow += If_ObjCutBest(pLeaf)->Area / pLeaf->EstRefs;
+        }
+    }
+    return Flow;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area flow.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_CutEdgeFlow( If_Man_t * p, If_Cut_t * pCut )
+{
+    If_Obj_t * pLeaf;
+    float Flow;
+    int i;
+    Flow = pCut->nLeaves;
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+    {
+        if ( pLeaf->nRefs == 0 || If_ObjIsConst1(pLeaf) )
+            Flow += If_ObjCutBest(pLeaf)->Edge;
+        else 
+        {
+            assert( pLeaf->EstRefs > p->fEpsilon );
+            Flow += If_ObjCutBest(pLeaf)->Edge / pLeaf->EstRefs;
+        }
+    }
+    return Flow;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area flow.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_CutPowerFlow( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot )
+{
+    If_Obj_t * pLeaf;
+    float * pSwitching = (float *)p->vSwitching->pArray;
+    float Power = 0;
+    int i;
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+    {
+        Power += pSwitching[pLeaf->Id];
+        if ( pLeaf->nRefs == 0 || If_ObjIsConst1(pLeaf) )
+            Power += If_ObjCutBest(pLeaf)->Power;
+        else 
+        {
+            assert( pLeaf->EstRefs > p->fEpsilon );
+            Power += If_ObjCutBest(pLeaf)->Power / pLeaf->EstRefs;
+        }
+    }
+    return Power;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Average number of references of the leaves.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_CutAverageRefs( If_Man_t * p, If_Cut_t * pCut )
+{
+    If_Obj_t * pLeaf;
+    int nRefsTotal, i;
+    nRefsTotal = 0;
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+        nRefsTotal += pLeaf->nRefs;
+    return ((float)nRefsTotal)/pCut->nLeaves;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area of the first level.]
+
+  Description [The cut need to be derefed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+float If_CutAreaDeref( If_Man_t * p, If_Cut_t * pCut )
+{
+    If_Obj_t * pLeaf;
+    float Area;
+    int i;
+    Area = If_CutLutArea(p, pCut);
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+    {
+        assert( pLeaf->nRefs > 0 );
+        if ( --pLeaf->nRefs > 0 || !If_ObjIsAnd(pLeaf) )
+            continue;
+        Area += If_CutAreaDeref( p, If_ObjCutBest(pLeaf) );
+    }
+    return Area;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area of the first level.]
+
+  Description [The cut need to be derefed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_CutAreaRef( If_Man_t * p, If_Cut_t * pCut )
+{
+    If_Obj_t * pLeaf;
+    float Area;
+    int i;
+    Area = If_CutLutArea(p, pCut);
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+    {
+        assert( pLeaf->nRefs >= 0 );
+        if ( pLeaf->nRefs++ > 0 || !If_ObjIsAnd(pLeaf) )
+            continue;
+        Area += If_CutAreaRef( p, If_ObjCutBest(pLeaf) );
+    }
+    return Area;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area of the first level.]
+
+  Description [The cut need to be derefed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_CutAreaDerefed( If_Man_t * p, If_Cut_t * pCut )
+{
+    float aResult, aResult2;
+    if ( pCut->nLeaves < 2 )
+        return 0;
+    aResult2 = If_CutAreaRef( p, pCut );
+    aResult  = If_CutAreaDeref( p, pCut );
+    assert( aResult > aResult2 - p->fEpsilon );
+    assert( aResult < aResult2 + p->fEpsilon );
+    return aResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area of the first level.]
+
+  Description [The cut need to be derefed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut )
+{
+    float aResult, aResult2;
+    if ( pCut->nLeaves < 2 )
+        return 0;
+    aResult2 = If_CutAreaDeref( p, pCut );
+    aResult  = If_CutAreaRef( p, pCut );
+    assert( aResult > aResult2 - p->fEpsilon );
+    assert( aResult < aResult2 + p->fEpsilon );
+    return aResult;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area of the first level.]
+
+  Description [The cut need to be derefed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+float If_CutEdgeDeref( If_Man_t * p, If_Cut_t * pCut )
+{
+    If_Obj_t * pLeaf;
+    float Edge;
+    int i;
+    Edge = pCut->nLeaves;
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+    {
+        assert( pLeaf->nRefs > 0 );
+        if ( --pLeaf->nRefs > 0 || !If_ObjIsAnd(pLeaf) )
+            continue;
+        Edge += If_CutEdgeDeref( p, If_ObjCutBest(pLeaf) );
+    }
+    return Edge;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area of the first level.]
+
+  Description [The cut need to be derefed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_CutEdgeRef( If_Man_t * p, If_Cut_t * pCut )
+{
+    If_Obj_t * pLeaf;
+    float Edge;
+    int i;
+    Edge = pCut->nLeaves;
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+    {
+        assert( pLeaf->nRefs >= 0 );
+        if ( pLeaf->nRefs++ > 0 || !If_ObjIsAnd(pLeaf) )
+            continue;
+        Edge += If_CutEdgeRef( p, If_ObjCutBest(pLeaf) );
+    }
+    return Edge;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes edge of the first level.]
+
+  Description [The cut need to be derefed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_CutEdgeDerefed( If_Man_t * p, If_Cut_t * pCut )
+{
+    float aResult, aResult2;
+    if ( pCut->nLeaves < 2 )
+        return pCut->nLeaves;
+    aResult2 = If_CutEdgeRef( p, pCut );
+    aResult  = If_CutEdgeDeref( p, pCut );
+    assert( aResult > aResult2 - p->fEpsilon );
+    assert( aResult < aResult2 + p->fEpsilon );
+    return aResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area of the first level.]
+
+  Description [The cut need to be derefed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_CutEdgeRefed( If_Man_t * p, If_Cut_t * pCut )
+{
+    float aResult, aResult2;
+    if ( pCut->nLeaves < 2 )
+        return pCut->nLeaves;
+    aResult2 = If_CutEdgeDeref( p, pCut );
+    aResult  = If_CutEdgeRef( p, pCut );
+    assert( aResult > aResult2 - p->fEpsilon );
+    assert( aResult < aResult2 + p->fEpsilon );
+    return aResult;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area of the first level.]
+
+  Description [The cut need to be derefed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+float If_CutPowerDeref( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot )
+{
+    If_Obj_t * pLeaf;
+    float * pSwitching = (float *)p->vSwitching->pArray;
+    float Power = 0;
+    int i;
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+    {
+        Power += pSwitching[pLeaf->Id];
+        assert( pLeaf->nRefs > 0 );
+        if ( --pLeaf->nRefs > 0 || !If_ObjIsAnd(pLeaf) )
+            continue;
+        Power += If_CutPowerDeref( p, If_ObjCutBest(pLeaf), pRoot );
+    }
+    return Power;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area of the first level.]
+
+  Description [The cut need to be derefed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_CutPowerRef( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot )
+{
+    If_Obj_t * pLeaf;
+    float * pSwitching = (float *)p->vSwitching->pArray;
+    float Power = 0;
+    int i;
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+    {
+        Power += pSwitching[pLeaf->Id];
+        assert( pLeaf->nRefs >= 0 );
+        if ( pLeaf->nRefs++ > 0 || !If_ObjIsAnd(pLeaf) )
+            continue;
+        Power += If_CutPowerRef( p, If_ObjCutBest(pLeaf), pRoot );
+    }
+    return Power;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes Power of the first level.]
+
+  Description [The cut need to be derefed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_CutPowerDerefed( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot )
+{
+    float aResult, aResult2;
+    if ( pCut->nLeaves < 2 )
+        return 0;
+    aResult2 = If_CutPowerRef( p, pCut, pRoot );
+    aResult  = If_CutPowerDeref( p, pCut, pRoot );
+    assert( aResult > aResult2 - p->fEpsilon );
+    assert( aResult < aResult2 + p->fEpsilon );
+    return aResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area of the first level.]
+
+  Description [The cut need to be derefed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_CutPowerRefed( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot )
+{
+    float aResult, aResult2;
+    if ( pCut->nLeaves < 2 )
+        return 0;
+    aResult2 = If_CutPowerDeref( p, pCut, pRoot );
+    aResult  = If_CutPowerRef( p, pCut, pRoot );
+    assert( aResult > aResult2 - p->fEpsilon );
+    assert( aResult < aResult2 + p->fEpsilon );
+    return aResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cone of the cut in AIG with choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutGetCutMinLevel( If_Man_t * p, If_Cut_t * pCut )
+{
+    If_Obj_t * pLeaf;
+    int i, nMinLevel = IF_INFINITY;
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+        nMinLevel = IF_MIN( nMinLevel, (int)pLeaf->Level );
+    return nMinLevel;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cone of the cut in AIG with choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutGetCone_rec( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut )
+{
+    If_Obj_t * pTemp;
+    int i, RetValue;
+    // check if the node is in the cut
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        if ( pCut->pLeaves[i] == pObj->Id )
+            return 1;
+        else if ( pCut->pLeaves[i] > pObj->Id )
+            break;
+    // return if we reached the boundary
+    if ( If_ObjIsCi(pObj) )
+        return 0;
+    // check the choice node
+    for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv )
+    {
+        // check if the node itself is bound
+        RetValue = If_CutGetCone_rec( p, If_ObjFanin0(pTemp), pCut );
+        if ( RetValue )
+            RetValue &= If_CutGetCone_rec( p, If_ObjFanin1(pTemp), pCut );
+        if ( RetValue )
+            return 1;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cone of the cut in AIG with choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutGetCones( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    int i, Counter = 0;
+    abctime clk = Abc_Clock();
+    If_ManForEachObj( p, pObj, i )
+    {
+        if ( If_ObjIsAnd(pObj) && pObj->nRefs )
+        {
+            Counter += !If_CutGetCone_rec( p, pObj, If_ObjCutBest(pObj) );
+//            Abc_Print( 1, "%d ", If_CutGetCutMinLevel( p, If_ObjCutBest(pObj) ) );
+        }
+    }
+    Abc_Print( 1, "Cound not find boundary for %d nodes.\n", Counter );
+    Abc_PrintTime( 1, "Cones", Abc_Clock() - clk );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cone of the cut in AIG with choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_CutFoundFanins_rec( If_Obj_t * pObj, Vec_Int_t * vLeaves )
+{
+    if ( pObj->nRefs || If_ObjIsCi(pObj) )
+    {
+        Vec_IntPushUnique( vLeaves, pObj->Id );
+        return;
+    }
+    If_CutFoundFanins_rec( If_ObjFanin0(pObj), vLeaves );
+    If_CutFoundFanins_rec( If_ObjFanin1(pObj), vLeaves );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cone of the cut in AIG with choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutCountTotalFanins( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    Vec_Int_t * vLeaves;
+    int i, nFaninsTotal = 0, Counter = 0;
+    abctime clk = Abc_Clock();
+    vLeaves = Vec_IntAlloc( 100 );
+    If_ManForEachObj( p, pObj, i )
+    {
+        if ( If_ObjIsAnd(pObj) && pObj->nRefs )
+        {
+            nFaninsTotal += If_ObjCutBest(pObj)->nLeaves;
+            Vec_IntClear( vLeaves );
+            If_CutFoundFanins_rec( If_ObjFanin0(pObj), vLeaves );
+            If_CutFoundFanins_rec( If_ObjFanin1(pObj), vLeaves );
+            Counter += Vec_IntSize(vLeaves);
+        }
+    }
+    Abc_Print( 1, "Total cut inputs = %d. Total fanins incremental = %d.\n", nFaninsTotal, Counter );
+    Abc_PrintTime( 1, "Fanins", Abc_Clock() - clk );
+    Vec_IntFree( vLeaves );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifDec07.c b/abc-build/src/map/if/ifDec07.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifDec07.c
@@ -0,0 +1,1125 @@
+/**CFile****************************************************************
+
+  FileName    [ifDec07.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Performs additional check.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifDec07.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+#include "misc/extra/extra.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// the bit count for the first 256 integer numbers
+static int BitCount8[256] = {
+    0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
+// variable swapping code
+static word PMasks[5][3] = {
+    { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) },
+    { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) },
+    { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) },
+    { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) },
+    { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) }
+};
+// elementary truth tables
+static word Truth6[6] = {
+    ABC_CONST(0xAAAAAAAAAAAAAAAA),
+    ABC_CONST(0xCCCCCCCCCCCCCCCC),
+    ABC_CONST(0xF0F0F0F0F0F0F0F0),
+    ABC_CONST(0xFF00FF00FF00FF00),
+    ABC_CONST(0xFFFF0000FFFF0000),
+    ABC_CONST(0xFFFFFFFF00000000)
+};
+static word Truth7[7][2] = {
+    {ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA)},
+    {ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC)},
+    {ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0)},
+    {ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00)},
+    {ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000)},
+    {ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000)},
+    {ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF)}
+};
+
+extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars );
+extern void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+void If_DecPrintConfig( word z )
+{
+   unsigned S[1];
+   S[0] = (z & 0xffff) | ((z & 0xffff) << 16);
+   Extra_PrintBinary( stdout, S, 16 ); 
+   printf( " " );
+   Kit_DsdPrintFromTruth( S, 4 );
+   printf( " " );
+   printf( " %d", (int)((z >> 16) & 7) );
+   printf( " %d", (int)((z >> 20) & 7) );
+   printf( " %d", (int)((z >> 24) & 7) );
+   printf( " %d", (int)((z >> 28) & 7) );
+   printf( "   " );
+   S[0] = ((z >> 32) & 0xffff) | (((z >> 32) & 0xffff) << 16);
+   Extra_PrintBinary( stdout, S, 16 );
+   printf( " " );
+   Kit_DsdPrintFromTruth( S, 4 );
+   printf( " " );
+   printf( " %d", (int)((z >> 48) & 7) );
+   printf( " %d", (int)((z >> 52) & 7) );
+   printf( " %d", (int)((z >> 56) & 7) );
+   printf( " %d", (int)((z >> 60) & 7) );
+   printf( "\n" );
+}
+
+// verification for 6-input function
+static word If_Dec6ComposeLut4( int t, word f[4] )
+{
+    int m, v;
+    word c, r = 0;
+    for ( m = 0; m < 16; m++ )
+    {
+        if ( !((t >> m) & 1) )
+            continue;
+        c = ~(word)0;
+        for ( v = 0; v < 4; v++ )
+            c &= ((m >> v) & 1) ? f[v] : ~f[v];
+        r |= c;
+    }
+    return r;
+}
+word If_Dec6Truth( word z )
+{
+    word r, q, f[4];
+    int i, v;
+    assert( z );
+    for ( i = 0; i < 4; i++ )
+    {
+        v = (z >> (16+(i<<2))) & 7;
+        assert( v != 7 );
+        if ( v == 6 )
+            continue;
+        f[i] = Truth6[v];
+    }
+    q = If_Dec6ComposeLut4( (int)(z & 0xffff), f );
+    for ( i = 0; i < 4; i++ )
+    {
+        v = (z >> (48+(i<<2))) & 7;
+        if ( v == 6 )
+            continue;
+        f[i] = (v == 7) ? q : Truth6[v];
+    }
+    r = If_Dec6ComposeLut4( (int)((z >> 32) & 0xffff), f );
+    return r;
+}
+void If_Dec6Verify( word t, word z )
+{
+    word r = If_Dec6Truth( z );
+    if ( r != t )
+	{
+        If_DecPrintConfig( z );
+        Kit_DsdPrintFromTruth( (unsigned*)&t, 6 ); printf( "\n" );
+//        Kit_DsdPrintFromTruth( (unsigned*)&q, 6 ); printf( "\n" );
+        Kit_DsdPrintFromTruth( (unsigned*)&r, 6 ); printf( "\n" );
+        printf( "Verification failed!\n" );
+	}
+}
+// verification for 7-input function
+static void If_Dec7ComposeLut4( int t, word f[4][2], word r[2] )
+{
+    int m, v;
+    word c[2];
+    r[0] = r[1] = 0;
+    for ( m = 0; m < 16; m++ )
+    {
+        if ( !((t >> m) & 1) )
+            continue;
+        c[0] = c[1] = ~(word)0;
+        for ( v = 0; v < 4; v++ )
+        {
+            c[0] &= ((m >> v) & 1) ? f[v][0] : ~f[v][0];
+            c[1] &= ((m >> v) & 1) ? f[v][1] : ~f[v][1];
+        }
+        r[0] |= c[0];
+        r[1] |= c[1];
+    }
+}
+void If_Dec7Verify( word t[2], word z )
+{
+    word f[4][2], r[2];
+    int i, v;
+    assert( z );
+    for ( i = 0; i < 4; i++ )
+    {
+        v = (z >> (16+(i<<2))) & 7;
+        f[i][0] = Truth7[v][0];
+        f[i][1] = Truth7[v][1];
+    }
+    If_Dec7ComposeLut4( (int)(z & 0xffff), f, r );
+    f[3][0] = r[0];
+    f[3][1] = r[1];
+    for ( i = 0; i < 3; i++ )
+    {
+        v = (z >> (48+(i<<2))) & 7;
+        f[i][0] = Truth7[v][0];
+        f[i][1] = Truth7[v][1];
+    }
+    If_Dec7ComposeLut4( (int)((z >> 32) & 0xffff), f, r );
+    if ( r[0] != t[0] || r[1] != t[1] )
+    {
+        If_DecPrintConfig( z );
+        Kit_DsdPrintFromTruth( (unsigned*)t, 7 ); printf( "\n" );
+        Kit_DsdPrintFromTruth( (unsigned*)r, 7 ); printf( "\n" );
+        printf( "Verification failed!\n" );
+    }
+}
+
+
+// count the number of unique cofactors
+static inline int If_Dec6CofCount2( word t )
+{
+    int i, Mask = 0;
+    for ( i = 0; i < 16; i++ )
+        Mask |= (1 << ((t >> (i<<2)) & 15));
+    return BitCount8[((unsigned char*)&Mask)[0]] + BitCount8[((unsigned char*)&Mask)[1]];
+}
+// count the number of unique cofactors (up to 3)
+static inline int If_Dec7CofCount3( word t[2] )
+{
+    unsigned char * pTruth = (unsigned char *)t;
+    int i, iCof2 = 0;
+    for ( i = 1; i < 16; i++ )
+    {
+        if ( pTruth[i] == pTruth[0] )
+            continue;
+        if ( iCof2 == 0 )
+            iCof2 = i;
+        else if ( pTruth[i] != pTruth[iCof2] )
+            return 3;
+    }
+    assert( iCof2 );
+    return 2;
+}
+
+// permute 6-input function
+static inline word If_Dec6SwapAdjacent( word t, int v )
+{
+    assert( v < 5 );
+    return (t & PMasks[v][0]) | ((t & PMasks[v][1]) << (1 << v)) | ((t & PMasks[v][2]) >> (1 << v));
+}
+static inline word If_Dec6MoveTo( word t, int v, int p, int Pla2Var[6], int Var2Pla[6] )
+{
+    int iPlace0, iPlace1;
+    assert( Var2Pla[v] >= p );
+    while ( Var2Pla[v] != p )
+    {
+        iPlace0 = Var2Pla[v]-1;
+        iPlace1 = Var2Pla[v];
+        t = If_Dec6SwapAdjacent( t, iPlace0 );
+        Var2Pla[Pla2Var[iPlace0]]++;
+        Var2Pla[Pla2Var[iPlace1]]--;
+        Pla2Var[iPlace0] ^= Pla2Var[iPlace1];
+        Pla2Var[iPlace1] ^= Pla2Var[iPlace0];
+        Pla2Var[iPlace0] ^= Pla2Var[iPlace1];
+    }
+    assert( Pla2Var[p] == v );
+    return t;
+}
+
+// permute 7-input function
+static inline void If_Dec7SwapAdjacent( word t[2], int v )
+{
+    if ( v == 5 )
+    {
+        unsigned Temp = (t[0] >> 32);
+        t[0]  = (t[0] & 0xFFFFFFFF) | ((t[1] & 0xFFFFFFFF) << 32);
+        t[1] ^= (t[1] & 0xFFFFFFFF) ^ Temp;
+        return;
+    }
+    assert( v < 5 );
+    t[0] = If_Dec6SwapAdjacent( t[0], v );
+    t[1] = If_Dec6SwapAdjacent( t[1], v );
+}
+static inline void If_Dec7MoveTo( word t[2], int v, int p, int Pla2Var[7], int Var2Pla[7] )
+{
+    int iPlace0, iPlace1;
+    assert( Var2Pla[v] >= p );
+    while ( Var2Pla[v] != p )
+    {
+        iPlace0 = Var2Pla[v]-1;
+        iPlace1 = Var2Pla[v];
+        If_Dec7SwapAdjacent( t, iPlace0 );
+        Var2Pla[Pla2Var[iPlace0]]++;
+        Var2Pla[Pla2Var[iPlace1]]--;
+        Pla2Var[iPlace0] ^= Pla2Var[iPlace1];
+        Pla2Var[iPlace1] ^= Pla2Var[iPlace0];
+        Pla2Var[iPlace0] ^= Pla2Var[iPlace1];
+    }
+    assert( Pla2Var[p] == v );
+}
+
+// derive binary function
+static inline int If_Dec6DeriveCount2( word t, int * pCof0, int * pCof1 )
+{
+    int i, Mask = 0;
+	*pCof0 = (t & 15);
+	*pCof1 = (t & 15);
+    for ( i = 1; i < 16; i++ )
+		if ( *pCof0 != ((t >> (i<<2)) & 15) )
+		{
+			*pCof1 = ((t >> (i<<2)) & 15);
+			Mask |= (1 << i);
+		}
+	return Mask;
+}
+static inline int If_Dec7DeriveCount3( word t[2], int * pCof0, int * pCof1 )
+{
+    unsigned char * pTruth = (unsigned char *)t;
+    int i, Mask = 0;
+	*pCof0 = pTruth[0];
+	*pCof1 = pTruth[0];
+    for ( i = 1; i < 16; i++ )
+		if ( *pCof0 != pTruth[i] )
+		{
+			*pCof1 = pTruth[i];
+			Mask |= (1 << i);
+		}
+	return Mask;
+}
+
+// derives decomposition
+static inline word If_Dec6Cofactor( word t, int iVar, int fCof1 )
+{
+    assert( iVar >= 0 && iVar < 6 );
+    if ( fCof1 )
+        return (t & Truth6[iVar]) | ((t & Truth6[iVar]) >> (1<<iVar));
+    else
+        return (t &~Truth6[iVar]) | ((t &~Truth6[iVar]) << (1<<iVar));
+}
+static word If_Dec6DeriveDisjoint( word t, int Pla2Var[6], int Var2Pla[6] )
+{
+	int i, Cof0, Cof1;
+    word z = If_Dec6DeriveCount2( t, &Cof0, &Cof1 );
+	for ( i = 0; i < 4; i++ )
+		z |= (((word)Pla2Var[i+2]) << (16 + 4*i));
+	z |= ((word)((Cof1 << 4) | Cof0) << 32);
+	z |= ((word)((Cof1 << 4) | Cof0) << 40);
+	for ( i = 0; i < 2; i++ )
+		z |= (((word)Pla2Var[i]) << (48 + 4*i));
+    z |= (((word)7) << (48 + 4*i++));
+    assert( i == 3 );
+    return z;
+}
+static word If_Dec6DeriveNonDisjoint( word t, int s, int Pla2Var0[6], int Var2Pla0[6] )
+{
+    word z, c0, c1;
+	int Cof0[2], Cof1[2];
+	int Truth0, Truth1, i;
+    int Pla2Var[6], Var2Pla[6];
+	assert( s >= 2 && s <= 5 );
+    for ( i = 0; i < 6; i++ )
+    {
+        Pla2Var[i] = Pla2Var0[i];
+        Var2Pla[i] = Var2Pla0[i];
+    }
+	for ( i = s; i < 5; i++ )
+	{
+        t = If_Dec6SwapAdjacent( t, i );
+        Var2Pla[Pla2Var[i]]++;
+        Var2Pla[Pla2Var[i+1]]--;
+        Pla2Var[i] ^= Pla2Var[i+1];
+        Pla2Var[i+1] ^= Pla2Var[i];
+        Pla2Var[i] ^= Pla2Var[i+1];
+	}
+    c0 = If_Dec6Cofactor( t, 5, 0 );
+    c1 = If_Dec6Cofactor( t, 5, 1 );
+    assert( 2 >= If_Dec6CofCount2(c0) );
+    assert( 2 >= If_Dec6CofCount2(c1) );
+	Truth0 = If_Dec6DeriveCount2( c0, &Cof0[0], &Cof0[1] );
+	Truth1 = If_Dec6DeriveCount2( c1, &Cof1[0], &Cof1[1] );
+	z = ((Truth1 & 0xFF) << 8) | (Truth0 & 0xFF);
+	for ( i = 0; i < 4; i++ )
+		z |= (((word)Pla2Var[i+2]) << (16 + 4*i));
+	z |= ((word)((Cof0[1] << 4) | Cof0[0]) << 32);
+	z |= ((word)((Cof1[1] << 4) | Cof1[0]) << 40);
+	for ( i = 0; i < 2; i++ )
+		z |= (((word)Pla2Var[i]) << (48 + 4*i));
+    z |= (((word)7) << (48 + 4*i++));
+    z |= (((word)Pla2Var[5]) << (48 + 4*i++));
+    assert( i == 4 );
+    return z;
+}
+static word If_Dec7DeriveDisjoint( word t[2], int Pla2Var[7], int Var2Pla[7] )
+{
+	int i, Cof0, Cof1;
+    word z = If_Dec7DeriveCount3( t, &Cof0, &Cof1 );
+	for ( i = 0; i < 4; i++ )
+		z |= (((word)Pla2Var[i+3]) << (16 + 4*i));
+	z |= ((word)((Cof1 << 8) | Cof0) << 32);
+	for ( i = 0; i < 3; i++ )
+		z |= (((word)Pla2Var[i]) << (48 + 4*i));
+	z |= (((word)7) << (48 + 4*i));
+    return z;
+}
+
+static inline int If_Dec6CountOnes( word t )
+{
+    t =    (t & ABC_CONST(0x5555555555555555)) + ((t>> 1) & ABC_CONST(0x5555555555555555));
+    t =    (t & ABC_CONST(0x3333333333333333)) + ((t>> 2) & ABC_CONST(0x3333333333333333));
+    t =    (t & ABC_CONST(0x0F0F0F0F0F0F0F0F)) + ((t>> 4) & ABC_CONST(0x0F0F0F0F0F0F0F0F));
+    t =    (t & ABC_CONST(0x00FF00FF00FF00FF)) + ((t>> 8) & ABC_CONST(0x00FF00FF00FF00FF));
+    t =    (t & ABC_CONST(0x0000FFFF0000FFFF)) + ((t>>16) & ABC_CONST(0x0000FFFF0000FFFF));
+    return (t & ABC_CONST(0x00000000FFFFFFFF)) +  (t>>32);
+}
+static inline int If_Dec6HasVar( word t, int v )
+{
+    return ((t & Truth6[v]) >> (1<<v)) != (t & ~Truth6[v]);
+}
+static inline int If_Dec7HasVar( word t[2], int v )
+{
+    assert( v >= 0 && v < 7 );
+    if ( v == 6 )
+        return t[0] != t[1]; 
+    return ((t[0] & Truth6[v]) >> (1<<v)) != (t[0] & ~Truth6[v])
+        || ((t[1] & Truth6[v]) >> (1<<v)) != (t[1] & ~Truth6[v]);
+}
+
+static inline void If_DecVerifyPerm( int Pla2Var[6], int Var2Pla[6] )
+{
+    int i;
+    for ( i = 0; i < 6; i++ )
+        assert( Pla2Var[Var2Pla[i]] == i );
+} 
+word If_Dec6Perform( word t, int fDerive )
+{ 
+	word r = 0;
+    int i, v, u, x, Count, Pla2Var[6], Var2Pla[6];
+    // start arrays
+    for ( i = 0; i < 6; i++ )
+    {
+        assert( If_Dec6HasVar( t, i ) );
+        Pla2Var[i] = Var2Pla[i] = i;
+    }
+    // generate permutations
+    i = 0;
+    for ( v = 0;   v < 6; v++ )
+    for ( u = v+1; u < 6; u++, i++ )
+    {
+        t = If_Dec6MoveTo( t, v, 0, Pla2Var, Var2Pla );
+        t = If_Dec6MoveTo( t, u, 1, Pla2Var, Var2Pla );
+//        If_DecVerifyPerm( Pla2Var, Var2Pla );
+        Count = If_Dec6CofCount2( t );
+        assert( Count > 1 );
+        if ( Count == 2 )
+            return !fDerive ? 1 : If_Dec6DeriveDisjoint( t, Pla2Var, Var2Pla );
+        // check non-disjoint decomposition
+        if ( !r && (Count == 3 || Count == 4) )
+        {
+            for ( x = 0; x < 4; x++ )
+            {
+                word c0 = If_Dec6Cofactor( t, x+2, 0 );
+                word c1 = If_Dec6Cofactor( t, x+2, 1 );
+                if ( If_Dec6CofCount2( c0 ) <= 2 && If_Dec6CofCount2( c1 ) <= 2 )
+                {
+					r = !fDerive ? 1 : If_Dec6DeriveNonDisjoint( t, x+2, Pla2Var, Var2Pla );
+					break;
+                }
+            }
+        }
+    }
+    assert( i == 15 );
+    return r;
+}
+word If_Dec7Perform( word t0[2], int fDerive )
+{
+    word t[2] = {t0[0], t0[1]}; 
+    int i, v, u, y, Pla2Var[7], Var2Pla[7];
+    // start arrays
+    for ( i = 0; i < 7; i++ )
+    {
+/*
+        if ( i < 6 )
+            assert( If_Dec6HasVar( t[0], i ) || If_Dec6HasVar( t[1], i ) );
+        else
+            assert( t[0] != t[1] );
+*/
+        Pla2Var[i] = Var2Pla[i] = i;
+    }
+    // generate permutations
+    for ( v = 0;   v < 7; v++ )
+    for ( u = v+1; u < 7; u++ )
+    for ( y = u+1; y < 7; y++ )
+    {
+        If_Dec7MoveTo( t, v, 0, Pla2Var, Var2Pla );
+        If_Dec7MoveTo( t, u, 1, Pla2Var, Var2Pla );
+        If_Dec7MoveTo( t, y, 2, Pla2Var, Var2Pla );
+//        If_DecVerifyPerm( Pla2Var, Var2Pla );
+        if ( If_Dec7CofCount3( t ) == 2 )
+        {
+            return !fDerive ? 1 : If_Dec7DeriveDisjoint( t, Pla2Var, Var2Pla );
+        }
+    }
+    return 0;
+}
+
+
+// support minimization
+static inline int If_DecSuppIsMinBase( int Supp )
+{
+    return (Supp & (Supp+1)) == 0;
+}
+static inline word If_Dec6TruthShrink( word uTruth, int nVars, int nVarsAll, unsigned Phase )
+{
+    int i, k, Var = 0;
+    assert( nVarsAll <= 6 );
+    for ( i = 0; i < nVarsAll; i++ )
+        if ( Phase & (1 << i) )
+        {
+            for ( k = i-1; k >= Var; k-- )
+                uTruth = If_Dec6SwapAdjacent( uTruth, k );
+            Var++;
+        }
+    assert( Var == nVars );
+    return uTruth;
+}
+word If_Dec6MinimumBase( word uTruth, int * pSupp, int nVarsAll, int * pnVars )
+{
+    int v, iVar = 0, uSupp = 0;
+    assert( nVarsAll <= 6 );
+    for ( v = 0; v < nVarsAll; v++ )
+        if ( If_Dec6HasVar( uTruth, v ) )
+        {
+            uSupp |= (1 << v);
+            if ( pSupp )
+                pSupp[iVar] = pSupp[v];
+            iVar++;
+        }
+    if ( pnVars )
+        *pnVars = iVar;
+    if ( If_DecSuppIsMinBase( uSupp ) )
+        return uTruth;
+    return If_Dec6TruthShrink( uTruth, iVar, nVarsAll, uSupp );
+}
+
+static inline void If_Dec7TruthShrink( word uTruth[2], int nVars, int nVarsAll, unsigned Phase )
+{
+    int i, k, Var = 0;
+    assert( nVarsAll <= 7 );
+    for ( i = 0; i < nVarsAll; i++ )
+        if ( Phase & (1 << i) )
+        {
+            for ( k = i-1; k >= Var; k-- )
+                If_Dec7SwapAdjacent( uTruth, k );
+            Var++;
+        }
+    assert( Var == nVars );
+}
+void If_Dec7MinimumBase( word uTruth[2], int * pSupp, int nVarsAll, int * pnVars )
+{
+    int v, iVar = 0, uSupp = 0;
+    assert( nVarsAll <= 7 );
+    for ( v = 0; v < nVarsAll; v++ )
+        if ( If_Dec7HasVar( uTruth, v ) )
+        {
+            uSupp |= (1 << v);
+            if ( pSupp )
+                pSupp[iVar] = pSupp[v];
+            iVar++;
+        }
+    if ( pnVars )
+        *pnVars = iVar;
+    if ( If_DecSuppIsMinBase( uSupp ) )
+        return;
+    If_Dec7TruthShrink( uTruth, iVar, nVarsAll, uSupp );
+}
+
+
+
+// check for MUX decomposition
+static inline int If_Dec6SuppSize( word t )
+{
+    int v, Count = 0;
+    for ( v = 0; v < 6; v++ )
+        if ( If_Dec6Cofactor(t, v, 0) != If_Dec6Cofactor(t, v, 1) )
+            Count++;
+    return Count;
+}
+static inline int If_Dec6CheckMux( word t )
+{
+    int v;
+    for ( v = 0; v < 6; v++ )
+        if ( If_Dec6SuppSize(If_Dec6Cofactor(t, v, 0)) < 5 &&
+             If_Dec6SuppSize(If_Dec6Cofactor(t, v, 1)) < 5 )
+             return v;
+    return -1;
+}
+
+// check for MUX decomposition
+static inline void If_Dec7Cofactor( word t[2], int iVar, int fCof1, word r[2] )
+{
+    assert( iVar >= 0 && iVar < 7 );
+    if ( iVar == 6 )
+    {
+        if ( fCof1 )
+            r[0] = r[1] = t[1];
+        else
+            r[0] = r[1] = t[0];
+    }
+    else
+    {
+        if ( fCof1 )
+        {
+            r[0] = (t[0] & Truth6[iVar]) | ((t[0] & Truth6[iVar]) >> (1<<iVar));
+            r[1] = (t[1] & Truth6[iVar]) | ((t[1] & Truth6[iVar]) >> (1<<iVar));
+        }
+        else
+        {
+            r[0] = (t[0] &~Truth6[iVar]) | ((t[0] &~Truth6[iVar]) << (1<<iVar));
+            r[1] = (t[1] &~Truth6[iVar]) | ((t[1] &~Truth6[iVar]) << (1<<iVar));
+        }
+    }
+}
+static inline int If_Dec7SuppSize( word t[2] )
+{
+    word c0[2], c1[2];
+    int v, Count = 0;
+    for ( v = 0; v < 7; v++ )
+    {
+        If_Dec7Cofactor( t, v, 0, c0 );
+        If_Dec7Cofactor( t, v, 1, c1 );
+        if ( c0[0] != c1[0] || c0[1] != c1[1] )
+            Count++;
+    }
+    return Count;
+}
+static inline int If_Dec7CheckMux( word t[2] )
+{
+    word c0[2], c1[2];
+    int v;
+    for ( v = 0; v < 7; v++ )
+    {
+        If_Dec7Cofactor( t, v, 0, c0 );
+        If_Dec7Cofactor( t, v, 1, c1 );
+        if ( If_Dec7SuppSize(c0) < 5 && If_Dec7SuppSize(c1) < 5 )
+            return v;
+    }
+    return -1;
+}
+
+// find the best MUX decomposition
+int If_Dec6PickBestMux( word t, word Cofs[2] )
+{
+    int v, vBest = -1, Count0, Count1, CountBest = 1000;
+    for ( v = 0; v < 6; v++ )
+    {
+        Count0 = If_Dec6SuppSize( If_Dec6Cofactor(t, v, 0) );
+        Count1 = If_Dec6SuppSize( If_Dec6Cofactor(t, v, 1) );
+        if ( Count0 < 5 && Count1 < 5 && CountBest > Count0 + Count1 )
+        {
+            CountBest = Count0 + Count1;
+            vBest = v;
+            Cofs[0] = If_Dec6Cofactor(t, v, 0);
+            Cofs[1] = If_Dec6Cofactor(t, v, 1);
+        }
+    }
+    return vBest;
+}
+int If_Dec7PickBestMux( word t[2], word c0r[2], word c1r[2] )
+{
+    word c0[2], c1[2];
+    int v, vBest = -1, Count0, Count1, CountBest = 1000;
+    for ( v = 0; v < 7; v++ )
+    {
+        If_Dec7Cofactor( t, v, 0, c0 );
+        If_Dec7Cofactor( t, v, 1, c1 );
+        Count0 = If_Dec7SuppSize(c0);
+        Count1 = If_Dec7SuppSize(c1);
+        if ( Count0 < 5 && Count1 < 5 && CountBest > Count0 + Count1 )
+        {
+            CountBest = Count0 + Count1;
+            vBest = v;
+            c0r[0] = c0[0]; c0r[1] = c0[1];
+            c1r[0] = c1[0]; c1r[1] = c1[1];
+        }
+    }
+    return vBest;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks decomposability ]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+// count the number of unique cofactors
+static inline word If_Dec5CofCount2( word t, int x, int y, int * Pla2Var, word t0, int fDerive )
+{
+    int m, i, Mask;
+    assert( x >= 0 && x < 4 );
+    assert( y >= 0 && y < 4 );
+    for ( m = 0; m < 4; m++ )
+    {
+        for ( Mask = i = 0; i < 16; i++ )
+            if ( ((i >> x) & 1) == ((m >> 0) & 1) && ((i >> y) & 1) == ((m >> 1) & 1) )
+                Mask |= (1 << ((t >> (i<<1)) & 3));
+        if ( BitCount8[Mask & 0xF] > 2 )
+            return 0;
+    }
+//    Kit_DsdPrintFromTruth( (unsigned *)&t, 5 ); printf( "\n" );
+    if ( !fDerive )
+        return 1;
+    else
+    {
+        int fHas2, fHas3;
+        // composition function C depends on {x, y, Out, v[0]}
+        // decomposed function D depends on {x, y, z1, z2}
+        word F[4] = { 0, ABC_CONST(0x5555555555555555), ABC_CONST(0xAAAAAAAAAAAAAAAA), ~((word)0) };
+        word C2[4], D2[4] = {0}, C1[2], D1[2], C, D, z;
+        int v, zz1 = -1, zz2 = -1;
+        // find two variables
+        for ( v = 0; v < 4; v++ )
+            if ( v != x && v != y )
+                {  zz1 = v; break; }
+        for ( v = 1; v < 4; v++ )
+            if ( v != x && v != y && v != zz1 )
+                {  zz2 = v; break; }
+        assert( zz1 != -1 && zz2 != -1 );
+        // find the cofactors
+        for ( m = 0; m < 4; m++ )
+        {
+            // for each cofactor, derive C2 and D2
+            for ( Mask = i = 0; i < 16; i++ )
+                if ( ((i >> x) & 1) == ((m >> 0) & 1) && ((i >> y) & 1) == ((m >> 1) & 1) )
+                    Mask |= (1 << ((t >> (i<<1)) & 3));
+            // find the values
+            if ( BitCount8[Mask & 0xF] == 1 )
+            {
+                C2[m] = F[Abc_Tt6FirstBit( Mask )];
+                D2[m] = ~(word)0;
+            }
+            else if ( BitCount8[Mask & 0xF] == 2 )
+            {
+                int Bit0 = Abc_Tt6FirstBit( Mask );
+                int Bit1 = Abc_Tt6FirstBit( Mask ^ (((word)1)<<Bit0) );
+                C2[m] = (F[Bit1] & Truth6[1]) | (F[Bit0] & ~Truth6[1]);
+                // find Bit1 appears
+                for ( Mask = i = 0; i < 16; i++ )
+                    if ( ((i >> x) & 1) == ((m >> 0) & 1) && ((i >> y) & 1) == ((m >> 1) & 1) )
+                        if ( Bit1 == ((t >> (i<<1)) & 3) )
+                            D2[m] |= (((word)1) << ( (((i >> zz2) & 1) << 1) | ((i >> zz1) & 1) ));
+            }
+            else assert( 0 );
+            D2[m] = Abc_Tt6Stretch( D2[m], 2 );
+        }
+
+        // combine
+        C1[0] = (C2[1] & Truth6[2]) | (C2[0] & ~Truth6[2]);
+        C1[1] = (C2[3] & Truth6[2]) | (C2[2] & ~Truth6[2]);
+        C     = (C1[1] & Truth6[3]) | (C1[0] & ~Truth6[3]);
+
+        // combine
+        D1[0] = (D2[1] & Truth6[2]) | (D2[0] & ~Truth6[2]);
+        D1[1] = (D2[3] & Truth6[2]) | (D2[2] & ~Truth6[2]);
+        D     = (D1[1] & Truth6[3]) | (D1[0] & ~Truth6[3]);
+
+//        printf( "\n" );
+//        Kit_DsdPrintFromTruth( (unsigned *)&C, 5 ); printf("\n");
+//        Kit_DsdPrintFromTruth( (unsigned *)&D, 5 ); printf("\n");
+
+        // create configuration
+        // find one
+        fHas2 = Abc_TtHasVar(&D, 5, 2);
+        fHas3 = Abc_TtHasVar(&D, 5, 3);
+        if ( fHas2 && fHas3 )
+        {
+            z = D & 0xFFFF;
+		    z |= (((word)Pla2Var[zz1+1]) << (16 + 4*0));
+		    z |= (((word)Pla2Var[zz2+1]) << (16 + 4*1));
+		    z |= (((word)Pla2Var[x+1])   << (16 + 4*2));
+		    z |= (((word)Pla2Var[y+1])   << (16 + 4*3));
+        }
+        else if ( fHas2 && !fHas3 )
+        {
+            z = D & 0xFFFF;
+		    z |= (((word)Pla2Var[zz1+1]) << (16 + 4*0));
+		    z |= (((word)Pla2Var[zz2+1]) << (16 + 4*1));
+		    z |= (((word)Pla2Var[x+1])   << (16 + 4*2));
+		    z |= (((word)6)              << (16 + 4*3));
+        }
+        else if ( !fHas2 && fHas3 )
+        {
+            Abc_TtSwapVars( &D, 5, 2, 3 );
+            z = D & 0xFFFF;
+		    z |= (((word)Pla2Var[zz1+1]) << (16 + 4*0));
+		    z |= (((word)Pla2Var[zz2+1]) << (16 + 4*1));
+		    z |= (((word)Pla2Var[y+1])   << (16 + 4*2));
+		    z |= (((word)6)              << (16 + 4*3));
+        }
+        else 
+        {
+            z = D & 0xFFFF;
+		    z |= (((word)Pla2Var[zz1+1]) << (16 + 4*0));
+		    z |= (((word)Pla2Var[zz2+1]) << (16 + 4*1));
+		    z |= (((word)6)              << (16 + 4*2));
+		    z |= (((word)6)              << (16 + 4*3));
+        }
+
+        // second one
+        fHas2 = Abc_TtHasVar(&C, 5, 2);
+        fHas3 = Abc_TtHasVar(&C, 5, 3);
+        if ( fHas2 && fHas3 )
+        {
+	        z |= ((C & 0xFFFF) << 32);
+		    z |= (((word)Pla2Var[0])     << (48 + 4*0));
+		    z |= (((word)7)              << (48 + 4*1));
+		    z |= (((word)Pla2Var[x+1])   << (48 + 4*2));
+		    z |= (((word)Pla2Var[y+1])   << (48 + 4*3));
+        }
+        else if ( fHas2 && !fHas3 )
+        {
+	        z |= ((C & 0xFFFF) << 32);
+		    z |= (((word)Pla2Var[0])     << (48 + 4*0));
+		    z |= (((word)7)              << (48 + 4*1));
+		    z |= (((word)Pla2Var[x+1])   << (48 + 4*2));
+		    z |= (((word)6)              << (48 + 4*3));
+        }
+        else if ( !fHas2 && fHas3 )
+        {
+            Abc_TtSwapVars( &C, 5, 2, 3 );
+	        z |= ((C & 0xFFFF) << 32);
+		    z |= (((word)Pla2Var[0])     << (48 + 4*0));
+		    z |= (((word)7)              << (48 + 4*1));
+		    z |= (((word)Pla2Var[y+1])   << (48 + 4*2));
+		    z |= (((word)6)              << (48 + 4*3));
+        }
+        else 
+        {
+	        z |= ((C & 0xFFFF) << 32);
+		    z |= (((word)Pla2Var[0])     << (48 + 4*0));
+		    z |= (((word)7)              << (48 + 4*1));
+		    z |= (((word)6)              << (48 + 4*2));
+		    z |= (((word)6)              << (48 + 4*3));
+        }
+
+        // verify
+        {
+            word t1 = If_Dec6Truth( z );
+            if ( t1 != t0 )
+            {
+                printf( "\n" );
+                Kit_DsdPrintFromTruth( (unsigned *)&C2[0], 5 ); printf("\n");
+                Kit_DsdPrintFromTruth( (unsigned *)&C2[1], 5 ); printf("\n");
+                Kit_DsdPrintFromTruth( (unsigned *)&C2[2], 5 ); printf("\n");
+                Kit_DsdPrintFromTruth( (unsigned *)&C2[3], 5 ); printf("\n");
+
+                printf( "\n" );
+                Kit_DsdPrintFromTruth( (unsigned *)&D2[0], 5 ); printf("\n");
+                Kit_DsdPrintFromTruth( (unsigned *)&D2[1], 5 ); printf("\n");
+                Kit_DsdPrintFromTruth( (unsigned *)&D2[2], 5 ); printf("\n");
+                Kit_DsdPrintFromTruth( (unsigned *)&D2[3], 5 ); printf("\n");
+
+                printf( "\n" );
+                Kit_DsdPrintFromTruth( (unsigned *)&C, 5 ); printf("\n");
+                Kit_DsdPrintFromTruth( (unsigned *)&D, 5 ); printf("\n");
+
+                printf( "\n" );
+                Kit_DsdPrintFromTruth( (unsigned *)&t1, 5 ); printf("\n");
+                Kit_DsdPrintFromTruth( (unsigned *)&t0, 5 ); printf("\n");
+            }
+            assert( t1 == t0 );
+        }
+        return z;
+    }
+}
+word If_Dec5Perform( word t, int fDerive )
+{
+    int Pla2Var[7], Var2Pla[7];
+    int i, j, v;
+    word t0 = t;
+/*
+    word c0, c1, c00, c01, c10, c11;
+    for ( i = 0; i < 5; i++ )
+    {
+        c0 = If_Dec6Cofactor( t, i, 0 );
+        c1 = If_Dec6Cofactor( t, i, 1 );
+        if ( c0 == 0 )
+            return 1;
+        if ( ~c0 == 0 )
+            return 1;
+        if ( c1 == 0 )
+            return 1;
+        if ( ~c1 == 0 )
+            return 1;
+       if ( c0 == ~c1 )
+            return 1;
+    }
+    for ( i = 0; i < 4; i++ )
+    {
+        c0 = If_Dec6Cofactor( t, i, 0 );
+        c1 = If_Dec6Cofactor( t, i, 1 );
+        for ( j = i + 1; j < 5; j++ )
+        {
+            c00 = If_Dec6Cofactor( c0, j, 0 );
+            c01 = If_Dec6Cofactor( c0, j, 1 );
+            c10 = If_Dec6Cofactor( c1, j, 0 );
+            c11 = If_Dec6Cofactor( c1, j, 1 );
+            if ( c00 == c01 && c00 == c10 )
+                return 1;
+            if ( c11 == c01 && c11 == c10 )
+                return 1;
+            if ( c11 == c00 && c11 == c01 )
+                return 1;
+            if ( c11 == c00 && c11 == c10 )
+                return 1;
+            if ( c00 == c11 && c01 == c10 )
+                return 1;
+        }
+    }
+*/
+    // start arrays
+    for ( i = 0; i < 7; i++ )
+        Pla2Var[i] = Var2Pla[i] = i;
+    // generate permutations
+    for ( v = 0; v < 5; v++ )
+    {
+        t = If_Dec6MoveTo( t, v, 0, Pla2Var, Var2Pla );
+        If_DecVerifyPerm( Pla2Var, Var2Pla );
+        for ( i = 0; i < 4; i++ )
+            for ( j = i + 1; j < 4; j++ )
+            {
+                word z = If_Dec5CofCount2( t, i, j, Pla2Var, t0, fDerive );
+                if ( z )
+                {
+/*
+                    if ( v == 0 && i == 1 && j == 2 )
+                    {
+                          Kit_DsdPrintFromTruth( (unsigned *)&t, 5 ); printf( "\n" );
+                    }
+*/
+                    return z;
+                }
+            }
+    }
+
+/*
+    // start arrays
+    for ( i = 0; i < 7; i++ )
+        Pla2Var[i] = Var2Pla[i] = i;
+
+    t = t0;
+    for ( v = 0; v < 5; v++ )
+    {
+        int x, y;
+
+        t = If_Dec6MoveTo( t, v, 0, Pla2Var, Var2Pla );
+        If_DecVerifyPerm( Pla2Var, Var2Pla );
+
+        for ( i = 0; i < 16; i++ )
+            printf( "%d ", ((t >> (i<<1)) & 3) );
+        printf( "\n" );
+
+        for ( x = 0; x < 4; x++ )
+        for ( y = x + 1; y < 4; y++ )
+        {
+            for ( i = 0; i < 16; i++ )
+                if ( !((i >> x) & 1) && !((i >> y) & 1) )
+                    printf( "%d ", ((t >> (i<<1)) & 3) );
+            printf( "\n" );
+
+            for ( i = 0; i < 16; i++ )
+                if ( ((i >> x) & 1) && !((i >> y) & 1) )
+                    printf( "%d ", ((t >> (i<<1)) & 3) );
+            printf( "\n" );
+
+            for ( i = 0; i < 16; i++ )
+                if ( !((i >> x) & 1) && ((i >> y) & 1) )
+                    printf( "%d ", ((t >> (i<<1)) & 3) );
+            printf( "\n" );
+
+            for ( i = 0; i < 16; i++ )
+                if ( ((i >> x) & 1) && ((i >> y) & 1) )
+                    printf( "%d ", ((t >> (i<<1)) & 3) );
+            printf( "\n" );
+            printf( "\n" );
+        }
+    }
+*/
+
+//    Kit_DsdPrintFromTruth( (unsigned *)&t, 5 ); printf( "\n" );
+    return 0;
+}
+
+word If_Dec5PerformEx()
+{
+    word z;
+    // find one
+    z = (word)(0x17ac & 0xFFFF);
+	z |= (((word)3) << (16 + 4*0));
+	z |= (((word)4) << (16 + 4*1));
+	z |= (((word)1) << (16 + 4*2));
+	z |= (((word)2) << (16 + 4*3));
+    // second one
+	z |= (((word)(0x179a & 0xFFFF)) << 32);
+	z |= (((word)0) << (48 + 4*0));
+	z |= (((word)7) << (48 + 4*1));
+	z |= (((word)1) << (48 + 4*2));
+	z |= (((word)2) << (48 + 4*3));
+    return z;
+}
+void If_Dec5PerformTest()
+{
+    word z, t, t1;
+//    s = If_Dec5PerformEx();
+//    t = If_Dec6Truth( s );
+    t = 0xB0F3B0FFB0F3B0FF;
+
+    Kit_DsdPrintFromTruth( (unsigned *)&t, 5 ); printf("\n");
+
+    z = If_Dec5Perform( t, 1 );
+    t1 = If_Dec6Truth( z );
+    assert( t == t1 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs additional check.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word If_CutPerformDerive07( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr )
+{
+    if ( nLeaves < 5 )
+        return 1;
+    if ( nLeaves == 5 )
+    {
+        word z, t = ((word)pTruth[0] << 32) | (word)pTruth[0];
+        z = If_Dec5Perform( t, 1 );
+        If_Dec6Verify( t, z );
+        return z;
+    }
+    if ( nLeaves == 6 )
+    {
+        word z, t = ((word *)pTruth)[0];
+        z = If_Dec6Perform( t, 1 );
+        If_Dec6Verify( t, z );
+        return z;
+    }
+    if ( nLeaves == 7 )
+    {
+        word z, t[2];
+        t[0] = ((word *)pTruth)[0];
+        t[1] = ((word *)pTruth)[1];
+        z = If_Dec7Perform( t, 1 );
+        If_Dec7Verify( t, z );
+        return z;
+    }
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs additional check.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutPerformCheck07( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr )
+{
+	int fDerive = 0;
+    int v;
+    // skip non-support minimal
+    for ( v = 0; v < nLeaves; v++ )
+        if ( !Abc_TtHasVar( (word *)pTruth, nVars, v ) )
+            return 0;
+    // check
+    if ( nLeaves < 5 )
+        return 1;
+    if ( nLeaves == 5 )
+    {
+        word z, t = ((word)pTruth[0] << 32) | (word)pTruth[0];
+        z = If_Dec5Perform( t, fDerive );
+        if ( fDerive && z )
+            If_Dec6Verify( t, z );
+        return z != 0;
+    }
+    if ( nLeaves == 6 )
+    {
+        word z, t = ((word *)pTruth)[0];
+        z = If_Dec6Perform( t, fDerive );
+        if ( fDerive && z )
+        {
+//            If_DecPrintConfig( z );
+            If_Dec6Verify( t, z );
+        }
+//        if ( z == 0 )
+//            Extra_PrintHex(stdout, (unsigned *)&t, 6), printf( "  " ), Kit_DsdPrintFromTruth( (unsigned *)&t, 6 ), printf( "\n" );
+        return z != 0;
+    }
+    if ( nLeaves == 7 )
+    {
+        word z, t[2];
+        t[0] = ((word *)pTruth)[0];
+        t[1] = ((word *)pTruth)[1];
+//        if ( If_Dec7CheckMux(t) >= 0 )
+//            return 1;
+        z = If_Dec7Perform( t, fDerive );
+        if ( fDerive && z )
+            If_Dec7Verify( t, z );
+        return z != 0;
+    }
+    assert( 0 );
+    return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifDec08.c b/abc-build/src/map/if/ifDec08.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifDec08.c
@@ -0,0 +1,507 @@
+/**CFile****************************************************************
+
+  FileName    [ifDec08.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Performs additional check.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifDec08.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+#include "misc/extra/extra.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// the bit count for the first 256 integer numbers
+static int BitCount8[256] = {
+    0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
+// variable swapping code
+static word PMasks[5][3] = {
+    { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) },
+    { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) },
+    { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) },
+    { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) },
+    { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) }
+};
+// elementary truth tables
+static word Truth6[6] = {
+    ABC_CONST(0xAAAAAAAAAAAAAAAA),
+    ABC_CONST(0xCCCCCCCCCCCCCCCC),
+    ABC_CONST(0xF0F0F0F0F0F0F0F0),
+    ABC_CONST(0xFF00FF00FF00FF00),
+    ABC_CONST(0xFFFF0000FFFF0000),
+    ABC_CONST(0xFFFFFFFF00000000)
+};
+static word Truth10[10][16] = {
+    {ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA)},
+    {ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC)},
+    {ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0)},
+    {ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00)},
+    {ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000)},
+    {ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000)},
+    {ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF)},
+    {ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF)},
+    {ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF)},
+    {ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF)}
+};
+
+extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars );
+extern void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int If_Dec08WordNum( int nVars )
+{
+    return nVars <= 6 ? 1 : 1 << (nVars-6);
+}
+static void If_Dec08PrintConfigOne( unsigned z )
+{
+    unsigned t;
+    t = (z & 0xffff) | ((z & 0xffff) << 16);
+    Extra_PrintBinary( stdout, &t, 16 ); 
+    printf( " " );
+    Kit_DsdPrintFromTruth( &t, 4 );
+    printf( " " );
+    printf( " %d", (z >> 16) & 7 );
+    printf( " %d", (z >> 20) & 7 );
+    printf( " %d", (z >> 24) & 7 );
+    printf( " %d", (z >> 28) & 7 );
+    printf( "\n" );
+}
+void If_Dec08PrintConfig( unsigned * pZ )
+{
+    while ( *pZ )
+        If_Dec08PrintConfigOne( *pZ++ );
+}
+static inline void If_Dec08ComposeLut4( int t, word ** pF, word * pR, int nVars )
+{
+    word pC[16];
+    int m, w, v, nWords;
+    assert( nVars <= 10 );
+    nWords = If_Dec08WordNum( nVars );
+    for ( w = 0; w < nWords; w++ )
+        pR[w] = 0;
+    for ( m = 0; m < 16; m++ )
+    {
+        if ( !((t >> m) & 1) )
+            continue;
+        for ( w = 0; w < nWords; w++ )
+            pC[w] = ~(word)0;
+        for ( v = 0; v < 4; v++ )
+            for ( w = 0; w < nWords; w++ )
+                pC[w] &= ((m >> v) & 1) ? pF[v][w] : ~pF[v][w];
+        for ( w = 0; w < nWords; w++ )
+            pR[w] |= pC[w];
+    }
+}
+void If_Dec08Verify( word * pF, int nVars, unsigned * pZ )
+{
+    word pN[16][16], * pG[4];
+    int i, w, v, k, nWords;
+    unsigned z;
+    nWords = If_Dec08WordNum( nVars );
+    for ( k = 0; k < nVars; k++ )
+        for ( w = 0; w < nWords; w++ )
+            pN[k][w] = Truth10[k][w];
+    for ( i = 0; (z = pZ[i]); i++, k++ )
+    {
+        for ( v = 0; v < 4; v++ )
+            pG[v] = pN[ (z >> (16+(v<<2))) & 7 ];
+        If_Dec08ComposeLut4( (int)(z & 0xffff), pG, pN[k], nVars );
+    }
+    k--;
+    for ( w = 0; w < nWords; w++ )
+        if ( pN[k][w] != pF[w] )
+        {
+            If_Dec08PrintConfig( pZ );
+            Kit_DsdPrintFromTruth( (unsigned*)pF, nVars ); printf( "\n" );
+            Kit_DsdPrintFromTruth( (unsigned*)pN[k], nVars ); printf( "\n" );
+            printf( "Verification failed!\n" );
+            break;
+        }
+}
+
+
+// count the number of unique cofactors
+static inline int If_Dec08CofCount2( word * pF, int nVars )
+{
+    int nShift = (1 << (nVars - 3));
+    word Mask  = (((word)1) << nShift) - 1;
+    word iCof0 = pF[0] & Mask;
+    word iCof1 = iCof0, iCof;
+    int i;
+    assert( nVars >= 6 && nVars <= 8 );
+//    if ( nVars == 10 )
+//        Mask = ~(word)0;
+    for ( i = 1; i < 8; i++ )
+    {
+        iCof = (pF[(i * nShift) / 64] >> ((i * nShift) & 63)) & Mask;
+        if ( iCof == iCof0 )
+            continue;
+        if ( iCof1 == iCof0 )
+            iCof1 = iCof;
+        else if ( iCof != iCof1 )
+            return 3;
+    }
+    return 2;
+}
+static inline int If_Dec08CofCount( word * pF, int nVars )
+{
+    int nShift = (1 << (nVars - 3));
+    word Mask  = (((word)1) << nShift) - 1;
+    word iCofs[16], iCof;
+    int i, c, nCofs = 1;
+//    if ( nVars == 10 )
+//        Mask = ~(word)0;
+    iCofs[0] = pF[0] & Mask;
+    for ( i = 1; i < 8; i++ )
+    {
+        iCof = (pF[(i * nShift) / 64] >> ((i * nShift) & 63)) & Mask;
+        for ( c = 0; c < nCofs; c++ )
+            if ( iCof == iCofs[c] )
+                break;
+        if ( c == nCofs )
+            iCofs[nCofs++] = iCof;
+    }
+    return nCofs;
+}
+
+
+// variable permutation for large functions
+static inline void If_Dec08Copy( word * pOut, word * pIn, int nVars )
+{
+    int w, nWords = If_Dec08WordNum( nVars );
+    for ( w = 0; w < nWords; w++ )
+        pOut[w] = pIn[w];
+}
+static inline void If_Dec08SwapAdjacent( word * pOut, word * pIn, int iVar, int nVars )
+{
+    int i, k, nWords = If_Dec08WordNum( nVars );
+    assert( iVar < nVars - 1 );
+    if ( iVar < 5 )
+    {
+        int Shift = (1 << iVar);
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift);
+    }
+    else if ( iVar > 5 )
+    {
+        int Step = (1 << (iVar - 6));
+        for ( k = 0; k < nWords; k += 4*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                pOut[i] = pIn[i];
+            for ( i = 0; i < Step; i++ )
+                pOut[Step+i] = pIn[2*Step+i];
+            for ( i = 0; i < Step; i++ )
+                pOut[2*Step+i] = pIn[Step+i];
+            for ( i = 0; i < Step; i++ )
+                pOut[3*Step+i] = pIn[3*Step+i];
+            pIn  += 4*Step;
+            pOut += 4*Step;
+        }
+    }
+    else // if ( iVar == 5 )
+    {
+        for ( i = 0; i < nWords; i += 2 )
+        {
+            pOut[i]   = (pIn[i]   & ABC_CONST(0x00000000FFFFFFFF)) | ((pIn[i+1] & ABC_CONST(0x00000000FFFFFFFF)) << 32);
+            pOut[i+1] = (pIn[i+1] & ABC_CONST(0xFFFFFFFF00000000)) | ((pIn[i]   & ABC_CONST(0xFFFFFFFF00000000)) >> 32);
+        }
+    }
+}
+static inline void If_Dec08MoveTo( word * pF, int nVars, int v, int p, int Pla2Var[], int Var2Pla[] )
+{
+    word pG[16], * pIn = pF, * pOut = pG, * pTemp;
+    int iPlace0, iPlace1, Count = 0;
+    assert( Var2Pla[v] <= p );
+    while ( Var2Pla[v] != p )
+    {
+        iPlace0 = Var2Pla[v];
+        iPlace1 = Var2Pla[v]+1;
+        If_Dec08SwapAdjacent( pOut, pIn, iPlace0, nVars );
+        pTemp = pIn; pIn = pOut, pOut = pTemp;
+        Var2Pla[Pla2Var[iPlace0]]++;
+        Var2Pla[Pla2Var[iPlace1]]--;
+        Pla2Var[iPlace0] ^= Pla2Var[iPlace1];
+        Pla2Var[iPlace1] ^= Pla2Var[iPlace0];
+        Pla2Var[iPlace0] ^= Pla2Var[iPlace1];
+        Count++;
+    }
+    if ( Count & 1 )
+        If_Dec08Copy( pF, pIn, nVars );
+    assert( Pla2Var[p] == v );
+}
+/*
+// derive binary function
+static inline int If_Dec08DeriveCount2( word * pF, word * pRes, int nVars )
+{
+    int nShift = (1 << (nVars - 4));
+    word Mask  = (((word)1) << nShift) - 1;
+    int i, MaskDec = 0;
+	word iCof0 = pF[0] & Mask;
+	word iCof1 = pF[0] & Mask;
+    word iCof, * pCof0, * pCof1;
+    if ( nVars == 10 )
+        Mask = ~(word)0;
+    for ( i = 1; i < 16; i++ )
+    {
+        iCof = (pF[(i * nShift) / 64] >> ((i * nShift) & 63)) & Mask;
+        if ( *pCof0 != iCof )
+		{
+			*pCof1 = iCof;
+			MaskDec |= (1 << i);
+		}
+    }
+    *pRes = ((iCof1 << nShift) | iCof0);
+	return MaskDec;
+}
+static inline word If_DecTruthStretch( word t, int nVars )
+{
+    assert( nVars > 1 );
+    if ( nVars == 1 )
+        nVars++, t = (t & 0x3) | ((t & 0x3) << 2);
+    if ( nVars == 2 )
+        nVars++, t = (t & 0xF) | ((t & 0xF) << 4);
+    if ( nVars == 3 )
+        nVars++, t = (t & 0xFF) | ((t & 0xFF) << 8);
+    if ( nVars == 4 )
+        nVars++, t = (t & 0xFFFF) | ((t & 0xFFFF) << 16);
+    if ( nVars == 5 )
+        nVars++, t = (t & 0xFFFFFFFF) | ((t & 0xFFFFFFFF) << 32);
+    assert( nVars >= 6 );
+}
+*/
+
+// support minimization
+static inline int If_DecSuppIsMinBase( int Supp )
+{
+    return (Supp & (Supp+1)) == 0;
+}
+static inline int If_Dec08HasVar( word * t, int nVars, int iVar )
+{
+    int nWords = If_Dec08WordNum( nVars );
+    assert( iVar < nVars );
+    if ( iVar < 6 )
+    {
+        int i, Shift = (1 << iVar);
+        for ( i = 0; i < nWords; i++ )
+            if ( (t[i] & ~Truth6[iVar]) != ((t[i] & Truth6[iVar]) >> Shift) )
+                return 1;
+        return 0;
+    }
+    else
+    {
+        int i, k, Step = (1 << (iVar - 6));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                if ( t[i] != t[Step+i] )
+                    return 1;
+            t += 2*Step;
+        }
+        return 0;
+    }
+}
+static inline int If_Dec08Support( word * t, int nVars )
+{
+    int v, Supp = 0;
+    for ( v = 0; v < nVars; v++ )
+        if ( If_Dec08HasVar( t, nVars, v ) )
+            Supp |= (1 << v);
+    return Supp;
+}
+
+// checks
+void If_Dec08Cofactors( word * pF, int nVars, int iVar, word * pCof0, word * pCof1 )
+{
+    int nWords = If_Dec08WordNum( nVars );
+    assert( iVar < nVars );
+    if ( iVar < 6 )
+    {
+        int i, Shift = (1 << iVar);
+        for ( i = 0; i < nWords; i++ )
+        {
+            pCof0[i] = (pF[i] & ~Truth6[iVar]) | ((pF[i] & ~Truth6[iVar]) << Shift);
+            pCof1[i] = (pF[i] &  Truth6[iVar]) | ((pF[i] &  Truth6[iVar]) >> Shift);
+        }
+        return;
+    }
+    else
+    {
+        int i, k, Step = (1 << (iVar - 6));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+            {
+                pCof0[i] = pCof0[Step+i] = pF[i];
+                pCof1[i] = pCof1[Step+i] = pF[Step+i];
+            }
+            pF    += 2*Step;
+            pCof0 += 2*Step;
+            pCof1 += 2*Step;
+        }
+        return;
+    }
+}
+static inline int If_Dec08Count16( int Num16 )
+{
+    assert( Num16 < (1<<16)-1 );
+    return BitCount8[Num16 & 255] + BitCount8[(Num16 >> 8) & 255];
+}
+static inline void If_DecVerifyPerm( int Pla2Var[10], int Var2Pla[10], int nVars )
+{
+    int i;
+    for ( i = 0; i < nVars; i++ )
+        assert( Pla2Var[Var2Pla[i]] == i );
+} 
+int If_Dec08Perform( word * pF, int nVars, int fDerive )
+{ 
+//    static int Cnt = 0;
+    word pCof0[16], pCof1[16];
+    int Pla2Var[10], Var2Pla[10], Count[210], Masks[210];
+    int i, i0,i1,i2, v, x;
+    assert( nVars >= 6 && nVars <= 8 );
+    // start arrays
+    for ( i = 0; i < nVars; i++ )
+    {
+        assert( If_Dec08HasVar( pF, nVars, i ) );
+        Pla2Var[i] = Var2Pla[i] = i;
+    }
+/*
+    Cnt++;
+//if ( Cnt == 108 )
+{
+printf( "%d\n", Cnt );
+//Extra_PrintHex( stdout, (unsigned *)pF, nVars );
+//printf( "\n" ); 
+Kit_DsdPrintFromTruth( (unsigned *)pF, nVars );
+printf( "\n" );
+printf( "\n" );
+}
+*/
+    // generate permutations
+    v = 0;
+    for ( i0 = 0;    i0 < nVars; i0++ )
+    for ( i1 = i0+1; i1 < nVars; i1++ )
+    for ( i2 = i1+1; i2 < nVars; i2++, v++ )
+    {
+        If_Dec08MoveTo( pF, nVars, i0, nVars-1, Pla2Var, Var2Pla );
+        If_Dec08MoveTo( pF, nVars, i1, nVars-2, Pla2Var, Var2Pla );
+        If_Dec08MoveTo( pF, nVars, i2, nVars-3, Pla2Var, Var2Pla );
+        If_DecVerifyPerm( Pla2Var, Var2Pla, nVars );
+        Count[v] = If_Dec08CofCount( pF, nVars );
+        Masks[v] = (1 << i0) | (1 << i1) | (1 << i2);
+        assert( Count[v] > 1 );
+//printf( "%d ", Count[v] );
+        if ( Count[v] == 2 || Count[v] > 5 )
+            continue;
+        for ( x = 0; x < 4; x++ )
+        {
+            If_Dec08Cofactors( pF, nVars, nVars-1-x, pCof0, pCof1 );
+            if ( If_Dec08CofCount2(pCof0, nVars) <= 2 && If_Dec08CofCount2(pCof1, nVars) <= 2 )
+            {
+                Count[v] = -Count[v];
+                break;
+            }
+        }
+    }
+//printf( "\n" );
+    assert( v <= 210 );
+    // check if there are compatible bound sets
+    for ( i0 = 0; i0 < v; i0++ )
+    for ( i1 = i0+1; i1 < v; i1++ )
+    {
+        if ( If_Dec08Count16(Masks[i0] & Masks[i1]) > 8 - nVars )
+            continue;
+        if ( nVars == 8 )
+        {
+            if ( Count[i0] == 2 && Count[i1] == 2 )
+                return 1;
+        }
+        else if ( nVars == 7 )
+        {
+            if ( (Count[i0] == 2 && Count[i1] == 2) || 
+                 (Count[i0] == 2 && Count[i1] <  0) || 
+                 (Count[i0] <  0 && Count[i1] == 2) )
+                return 1;
+        }
+        else
+        {
+            if ( (Count[i0] == 2 && Count[i1] == 2) || 
+                 (Count[i0] == 2 && Count[i1] <  0) || 
+                 (Count[i0] <  0 && Count[i1] == 2) || 
+                 (Count[i0] <  0 && Count[i1] <  0) )
+                return 1;
+        }
+    }
+//    printf( "not found\n" );
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs additional check.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutPerformCheck08( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr )
+{
+	int nSupp, fDerive = 0;
+    word pF[16];
+    if ( nLeaves <= 5 )
+        return 1;
+    If_Dec08Copy( pF, (word *)pTruth, nVars );
+    nSupp = If_Dec08Support( pF, nLeaves );
+    if ( !nSupp || !If_DecSuppIsMinBase(nSupp) )
+        return 0;
+    if ( If_Dec08Perform( pF, nLeaves, fDerive ) )
+    {
+//        printf( "1" );
+        return 1;
+//        If_Dec08Verify( t, nLeaves, NULL );
+    }
+//    printf( "0" );
+    return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifDec10.c b/abc-build/src/map/if/ifDec10.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifDec10.c
@@ -0,0 +1,506 @@
+/**CFile****************************************************************
+
+  FileName    [ifDec10.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Performs additional check.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifDec10.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+#include "misc/extra/extra.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// the bit count for the first 256 integer numbers
+static int BitCount8[256] = {
+    0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
+// variable swapping code
+static word PMasks[5][3] = {
+    { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) },
+    { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) },
+    { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) },
+    { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) },
+    { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) }
+};
+// elementary truth tables
+static word Truth6[6] = {
+    ABC_CONST(0xAAAAAAAAAAAAAAAA),
+    ABC_CONST(0xCCCCCCCCCCCCCCCC),
+    ABC_CONST(0xF0F0F0F0F0F0F0F0),
+    ABC_CONST(0xFF00FF00FF00FF00),
+    ABC_CONST(0xFFFF0000FFFF0000),
+    ABC_CONST(0xFFFFFFFF00000000)
+};
+static word Truth10[10][16] = {
+    {ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA)},
+    {ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC)},
+    {ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0)},
+    {ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00)},
+    {ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000)},
+    {ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000)},
+    {ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF)},
+    {ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF)},
+    {ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF)},
+    {ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF)}
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int If_Dec10WordNum( int nVars )
+{
+    return nVars <= 6 ? 1 : 1 << (nVars-6);
+}
+static void If_Dec10PrintConfigOne( unsigned z )
+{
+    unsigned t;
+    t = (z & 0xffff) | ((z & 0xffff) << 16);
+    Extra_PrintBinary( stdout, &t, 16 ); 
+    printf( " " );
+    Kit_DsdPrintFromTruth( &t, 4 );
+    printf( " " );
+    printf( " %d", (z >> 16) & 7 );
+    printf( " %d", (z >> 20) & 7 );
+    printf( " %d", (z >> 24) & 7 );
+    printf( " %d", (z >> 28) & 7 );
+    printf( "\n" );
+}
+void If_Dec10PrintConfig( unsigned * pZ )
+{
+    while ( *pZ )
+        If_Dec10PrintConfigOne( *pZ++ );
+}
+static inline void If_Dec10ComposeLut4( int t, word ** pF, word * pR, int nVars )
+{
+    word pC[16];
+    int m, w, v, nWords;
+    assert( nVars <= 10 );
+    nWords = If_Dec10WordNum( nVars );
+    for ( w = 0; w < nWords; w++ )
+        pR[w] = 0;
+    for ( m = 0; m < 16; m++ )
+    {
+        if ( !((t >> m) & 1) )
+            continue;
+        for ( w = 0; w < nWords; w++ )
+            pC[w] = ~(word)0;
+        for ( v = 0; v < 4; v++ )
+            for ( w = 0; w < nWords; w++ )
+                pC[w] &= ((m >> v) & 1) ? pF[v][w] : ~pF[v][w];
+        for ( w = 0; w < nWords; w++ )
+            pR[w] |= pC[w];
+    }
+}
+void If_Dec10Verify( word * pF, int nVars, unsigned * pZ )
+{
+    word pN[16][16], * pG[4];
+    int i, w, v, k, nWords;
+    unsigned z;
+    nWords = If_Dec10WordNum( nVars );
+    for ( k = 0; k < nVars; k++ )
+        for ( w = 0; w < nWords; w++ )
+            pN[k][w] = Truth10[k][w];
+    for ( i = 0; (z = pZ[i]); i++, k++ )
+    {
+        for ( v = 0; v < 4; v++ )
+            pG[v] = pN[ (z >> (16+(v<<2))) & 7 ];
+        If_Dec10ComposeLut4( (int)(z & 0xffff), pG, pN[k], nVars );
+    }
+    k--;
+    for ( w = 0; w < nWords; w++ )
+        if ( pN[k][w] != pF[w] )
+        {
+            If_Dec10PrintConfig( pZ );
+            Kit_DsdPrintFromTruth( (unsigned*)pF, nVars ); printf( "\n" );
+            Kit_DsdPrintFromTruth( (unsigned*)pN[k], nVars ); printf( "\n" );
+            printf( "Verification failed!\n" );
+            break;
+        }
+}
+
+
+// count the number of unique cofactors
+static inline int If_Dec10CofCount2( word * pF, int nVars )
+{
+    int nShift = (1 << (nVars - 4));
+    word Mask  = (((word)1) << nShift) - 1;
+    word iCof0 = pF[0] & Mask;
+    word iCof1 = iCof0, iCof;
+    int i;
+    assert( nVars > 6 && nVars <= 10 );
+    if ( nVars == 10 )
+        Mask = ~(word)0;
+    for ( i = 1; i < 16; i++ )
+    {
+        iCof = (pF[(i * nShift) / 64] >> ((i * nShift) & 63)) & Mask;
+        if ( iCof == iCof0 )
+            continue;
+        if ( iCof1 == iCof0 )
+            iCof1 = iCof;
+        else if ( iCof != iCof1 )
+            return 3;
+    }
+    return 2;
+}
+static inline int If_Dec10CofCount( word * pF, int nVars )
+{
+    int nShift = (1 << (nVars - 4));
+    word Mask  = (((word)1) << nShift) - 1;
+    word iCofs[16], iCof;
+    int i, c, nCofs = 1;
+    if ( nVars == 10 )
+        Mask = ~(word)0;
+    iCofs[0] = pF[0] & Mask;
+    for ( i = 1; i < 16; i++ )
+    {
+        iCof = (pF[(i * nShift) / 64] >> ((i * nShift) & 63)) & Mask;
+        for ( c = 0; c < nCofs; c++ )
+            if ( iCof == iCofs[c] )
+                break;
+        if ( c == nCofs )
+            iCofs[nCofs++] = iCof;
+    }
+    return nCofs;
+}
+
+
+// variable permutation for large functions
+static inline void If_Dec10Copy( word * pOut, word * pIn, int nVars )
+{
+    int w, nWords = If_Dec10WordNum( nVars );
+    for ( w = 0; w < nWords; w++ )
+        pOut[w] = pIn[w];
+}
+static inline void If_Dec10SwapAdjacent( word * pOut, word * pIn, int iVar, int nVars )
+{
+    int i, k, nWords = If_Dec10WordNum( nVars );
+    assert( iVar < nVars - 1 );
+    if ( iVar < 5 )
+    {
+        int Shift = (1 << iVar);
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift);
+    }
+    else if ( iVar > 5 )
+    {
+        int Step = (1 << (iVar - 6));
+        for ( k = 0; k < nWords; k += 4*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                pOut[i] = pIn[i];
+            for ( i = 0; i < Step; i++ )
+                pOut[Step+i] = pIn[2*Step+i];
+            for ( i = 0; i < Step; i++ )
+                pOut[2*Step+i] = pIn[Step+i];
+            for ( i = 0; i < Step; i++ )
+                pOut[3*Step+i] = pIn[3*Step+i];
+            pIn  += 4*Step;
+            pOut += 4*Step;
+        }
+    }
+    else // if ( iVar == 5 )
+    {
+        for ( i = 0; i < nWords; i += 2 )
+        {
+            pOut[i]   = (pIn[i]   & ABC_CONST(0x00000000FFFFFFFF)) | ((pIn[i+1] & ABC_CONST(0x00000000FFFFFFFF)) << 32);
+            pOut[i+1] = (pIn[i+1] & ABC_CONST(0xFFFFFFFF00000000)) | ((pIn[i]   & ABC_CONST(0xFFFFFFFF00000000)) >> 32);
+        }
+    }
+}
+static inline void If_Dec10MoveTo( word * pF, int nVars, int v, int p, int Pla2Var[], int Var2Pla[] )
+{
+    word pG[16], * pIn = pF, * pOut = pG, * pTemp;
+    int iPlace0, iPlace1, Count = 0;
+    assert( Var2Pla[v] <= p );
+    while ( Var2Pla[v] != p )
+    {
+        iPlace0 = Var2Pla[v];
+        iPlace1 = Var2Pla[v]+1;
+        If_Dec10SwapAdjacent( pOut, pIn, iPlace0, nVars );
+        pTemp = pIn; pIn = pOut, pOut = pTemp;
+        Var2Pla[Pla2Var[iPlace0]]++;
+        Var2Pla[Pla2Var[iPlace1]]--;
+        Pla2Var[iPlace0] ^= Pla2Var[iPlace1];
+        Pla2Var[iPlace1] ^= Pla2Var[iPlace0];
+        Pla2Var[iPlace0] ^= Pla2Var[iPlace1];
+        Count++;
+    }
+    if ( Count & 1 )
+        If_Dec10Copy( pF, pIn, nVars );
+    assert( Pla2Var[p] == v );
+}
+/*
+// derive binary function
+static inline int If_Dec10DeriveCount2( word * pF, word * pRes, int nVars )
+{
+    int nShift = (1 << (nVars - 4));
+    word Mask  = (((word)1) << nShift) - 1;
+    int i, MaskDec = 0;
+	word iCof0 = pF[0] & Mask;
+	word iCof1 = pF[0] & Mask;
+    word iCof, * pCof0, * pCof1;
+    if ( nVars == 10 )
+        Mask = ~(word)0;
+    for ( i = 1; i < 16; i++ )
+    {
+        iCof = (pF[(i * nShift) / 64] >> ((i * nShift) & 63)) & Mask;
+        if ( *pCof0 != iCof )
+		{
+			*pCof1 = iCof;
+			MaskDec |= (1 << i);
+		}
+    }
+    *pRes = ((iCof1 << nShift) | iCof0);
+	return MaskDec;
+}
+static inline word If_DecTruthStretch( word t, int nVars )
+{
+    assert( nVars > 1 );
+    if ( nVars == 1 )
+        nVars++, t = (t & 0x3) | ((t & 0x3) << 2);
+    if ( nVars == 2 )
+        nVars++, t = (t & 0xF) | ((t & 0xF) << 4);
+    if ( nVars == 3 )
+        nVars++, t = (t & 0xFF) | ((t & 0xFF) << 8);
+    if ( nVars == 4 )
+        nVars++, t = (t & 0xFFFF) | ((t & 0xFFFF) << 16);
+    if ( nVars == 5 )
+        nVars++, t = (t & 0xFFFFFFFF) | ((t & 0xFFFFFFFF) << 32);
+    assert( nVars >= 6 );
+}
+*/
+
+// support minimization
+static inline int If_DecSuppIsMinBase( int Supp )
+{
+    return (Supp & (Supp+1)) == 0;
+}
+static inline int If_Dec10HasVar( word * t, int nVars, int iVar )
+{
+    int nWords = If_Dec10WordNum( nVars );
+    assert( iVar < nVars );
+    if ( iVar < 6 )
+    {
+        int i, Shift = (1 << iVar);
+        for ( i = 0; i < nWords; i++ )
+            if ( (t[i] & ~Truth6[iVar]) != ((t[i] & Truth6[iVar]) >> Shift) )
+                return 1;
+        return 0;
+    }
+    else
+    {
+        int i, k, Step = (1 << (iVar - 6));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                if ( t[i] != t[Step+i] )
+                    return 1;
+            t += 2*Step;
+        }
+        return 0;
+    }
+}
+static inline int If_Dec10Support( word * t, int nVars )
+{
+    int v, Supp = 0;
+    for ( v = 0; v < nVars; v++ )
+        if ( If_Dec10HasVar( t, nVars, v ) )
+            Supp |= (1 << v);
+    return Supp;
+}
+
+// checks
+void If_Dec10Cofactors( word * pF, int nVars, int iVar, word * pCof0, word * pCof1 )
+{
+    int nWords = If_Dec10WordNum( nVars );
+    assert( iVar < nVars );
+    if ( iVar < 6 )
+    {
+        int i, Shift = (1 << iVar);
+        for ( i = 0; i < nWords; i++ )
+        {
+            pCof0[i] = (pF[i] & ~Truth6[iVar]) | ((pF[i] & ~Truth6[iVar]) << Shift);
+            pCof1[i] = (pF[i] &  Truth6[iVar]) | ((pF[i] &  Truth6[iVar]) >> Shift);
+        }
+        return;
+    }
+    else
+    {
+        int i, k, Step = (1 << (iVar - 6));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+            {
+                pCof0[i] = pCof0[Step+i] = pF[i];
+                pCof1[i] = pCof1[Step+i] = pF[Step+i];
+            }
+            pF    += 2*Step;
+            pCof0 += 2*Step;
+            pCof1 += 2*Step;
+        }
+        return;
+    }
+}
+static inline int If_Dec10Count16( int Num16 )
+{
+    assert( Num16 < (1<<16)-1 );
+    return BitCount8[Num16 & 255] + BitCount8[(Num16 >> 8) & 255];
+}
+static inline void If_DecVerifyPerm( int Pla2Var[10], int Var2Pla[10], int nVars )
+{
+    int i;
+    for ( i = 0; i < nVars; i++ )
+        assert( Pla2Var[Var2Pla[i]] == i );
+} 
+int If_Dec10Perform( word * pF, int nVars, int fDerive )
+{ 
+//    static int Cnt = 0;
+    word pCof0[16], pCof1[16];
+    int Pla2Var[10], Var2Pla[10], Count[210], Masks[210];
+    int i, i0,i1,i2,i3, v, x;
+    assert( nVars >= 6 && nVars <= 10 );
+    // start arrays
+    for ( i = 0; i < nVars; i++ )
+    {
+        assert( If_Dec10HasVar( pF, nVars, i ) );
+        Pla2Var[i] = Var2Pla[i] = i;
+    }
+/*
+    Cnt++;
+//if ( Cnt == 108 )
+{
+printf( "%d\n", Cnt );
+//Extra_PrintHex( stdout, (unsigned *)pF, nVars );
+//printf( "\n" ); 
+Kit_DsdPrintFromTruth( (unsigned *)pF, nVars );
+printf( "\n" );
+printf( "\n" );
+}
+*/
+    // generate permutations
+    v = 0;
+    for ( i0 = 0;    i0 < nVars; i0++ )
+    for ( i1 = i0+1; i1 < nVars; i1++ )
+    for ( i2 = i1+1; i2 < nVars; i2++ )
+    for ( i3 = i2+1; i3 < nVars; i3++, v++ )
+    {
+        If_Dec10MoveTo( pF, nVars, i0, nVars-1, Pla2Var, Var2Pla );
+        If_Dec10MoveTo( pF, nVars, i1, nVars-2, Pla2Var, Var2Pla );
+        If_Dec10MoveTo( pF, nVars, i2, nVars-3, Pla2Var, Var2Pla );
+        If_Dec10MoveTo( pF, nVars, i3, nVars-4, Pla2Var, Var2Pla );
+        If_DecVerifyPerm( Pla2Var, Var2Pla, nVars );
+        Count[v] = If_Dec10CofCount( pF, nVars );
+        Masks[v] = (1 << i0) | (1 << i1) | (1 << i2) | (1 << i3);
+        assert( Count[v] > 1 );
+//printf( "%d ", Count[v] );
+        if ( Count[v] == 2 || Count[v] > 5 )
+            continue;
+        for ( x = 0; x < 4; x++ )
+        {
+            If_Dec10Cofactors( pF, nVars, nVars-1-x, pCof0, pCof1 );
+            if ( If_Dec10CofCount2(pCof0, nVars) <= 2 && If_Dec10CofCount2(pCof1, nVars) <= 2 )
+            {
+                Count[v] = -Count[v];
+                break;
+            }
+        }
+    }
+//printf( "\n" );
+    assert( v <= 210 );
+    // check if there are compatible bound sets
+    for ( i0 = 0; i0 < v; i0++ )
+    for ( i1 = i0+1; i1 < v; i1++ )
+    {
+        if ( If_Dec10Count16(Masks[i0] & Masks[i1]) > 10 - nVars )
+            continue;
+        if ( nVars == 10 )
+        {
+            if ( Count[i0] == 2 && Count[i1] == 2 )
+                return 1;
+        }
+        else if ( nVars == 9 )
+        {
+            if ( (Count[i0] == 2 && Count[i1] == 2) || 
+                 (Count[i0] == 2 && Count[i1] <  0) || 
+                 (Count[i0] <  0 && Count[i1] == 2) )
+                return 1;
+        }
+        else
+        {
+            if ( (Count[i0] == 2 && Count[i1] == 2) || 
+                 (Count[i0] == 2 && Count[i1] <  0) || 
+                 (Count[i0] <  0 && Count[i1] == 2) || 
+                 (Count[i0] <  0 && Count[i1] <  0) )
+                return 1;
+        }
+    }
+//    printf( "not found\n" );
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs additional check.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutPerformCheck10( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr )
+{
+	int nSupp, fDerive = 0;
+    word pF[16];
+    if ( nLeaves <= 6 )
+        return 1;
+    If_Dec10Copy( pF, (word *)pTruth, nVars );
+    nSupp = If_Dec10Support( pF, nLeaves );
+    if ( !nSupp || !If_DecSuppIsMinBase(nSupp) )
+        return 0;
+    if ( If_Dec10Perform( pF, nLeaves, fDerive ) )
+    {
+//        printf( "1" );
+        return 1;
+//        If_Dec10Verify( t, nLeaves, NULL );
+    }
+//    printf( "0" );
+    return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifDec16.c b/abc-build/src/map/if/ifDec16.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifDec16.c
@@ -0,0 +1,2374 @@
+/**CFile****************************************************************
+
+  FileName    [ifDec16.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Fast checking procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifDec16.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+#include "bool/kit/kit.h"
+#include "misc/vec/vecMem.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define CLU_VAR_MAX  16
+#define CLU_WRD_MAX  (1 << ((CLU_VAR_MAX)-6))
+#define CLU_MEM_MAX  1000  // 1 GB
+#define CLU_UNUSED   0xff
+
+// decomposition
+typedef struct If_Grp_t_ If_Grp_t;
+struct If_Grp_t_
+{
+    char       nVars;
+    char       nMyu;
+    char       pVars[CLU_VAR_MAX];
+};
+
+// hash table entry
+typedef struct If_Hte_t_ If_Hte_t;
+struct If_Hte_t_
+{
+    If_Hte_t * pNext;
+    unsigned   Group;
+    unsigned   Counter;
+    word       pTruth[1];
+};
+
+// variable swapping code
+static word PMasks[5][3] = {
+    { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) },
+    { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) },
+    { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) },
+    { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) },
+    { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) }
+};
+// elementary truth tables
+static word Truth6[6] = {
+    ABC_CONST(0xAAAAAAAAAAAAAAAA),
+    ABC_CONST(0xCCCCCCCCCCCCCCCC),
+    ABC_CONST(0xF0F0F0F0F0F0F0F0),
+    ABC_CONST(0xFF00FF00FF00FF00),
+    ABC_CONST(0xFFFF0000FFFF0000),
+    ABC_CONST(0xFFFFFFFF00000000)
+};
+static word TruthAll[CLU_VAR_MAX][CLU_WRD_MAX] = {{0}};
+
+extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars );
+extern void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits );
+
+extern int If_CluSupportSize( word * t, int nVars );
+
+int s_Count2 = 0;
+int s_Count3 = 0;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+static inline unsigned If_CluGrp2Uns( If_Grp_t * pG )
+{
+    char * pChar = (char *)pG;
+    unsigned Res = 0;
+    int i;
+    for ( i = 0; i < 8; i++ )
+        Res |= ((pChar[i] & 15) << (i << 2));
+    return Res;
+}
+
+static inline void If_CluUns2Grp( unsigned Group, If_Grp_t * pG )
+{
+    char * pChar = (char *)pG;
+    int i;
+    for ( i = 0; i < 8; i++ )
+        pChar[i] = ((Group >> (i << 2)) & 15);
+}
+
+unsigned int If_CluPrimeCudd( unsigned int p )
+{
+    int i,pn;
+
+    p--;
+    do {
+        p++;
+        if (p&1) {
+	    pn = 1;
+	    i = 3;
+	    while ((unsigned) (i * i) <= p) {
+		if (p % i == 0) {
+		    pn = 0;
+		    break;
+		}
+		i += 2;
+	    }
+	} else {
+	    pn = 0;
+	}
+    } while (!pn);
+    return(p);
+
+} /* end of Cudd_Prime */
+
+// hash table
+static inline int If_CluWordNum( int nVars )
+{
+    return nVars <= 6 ? 1 : 1 << (nVars-6);
+}
+static inline int If_CluCountOnes( word t )
+{
+    t =    (t & ABC_CONST(0x5555555555555555)) + ((t>> 1) & ABC_CONST(0x5555555555555555));
+    t =    (t & ABC_CONST(0x3333333333333333)) + ((t>> 2) & ABC_CONST(0x3333333333333333));
+    t =    (t & ABC_CONST(0x0F0F0F0F0F0F0F0F)) + ((t>> 4) & ABC_CONST(0x0F0F0F0F0F0F0F0F));
+    t =    (t & ABC_CONST(0x00FF00FF00FF00FF)) + ((t>> 8) & ABC_CONST(0x00FF00FF00FF00FF));
+    t =    (t & ABC_CONST(0x0000FFFF0000FFFF)) + ((t>>16) & ABC_CONST(0x0000FFFF0000FFFF));
+    return (t & ABC_CONST(0x00000000FFFFFFFF)) +  (t>>32);
+}
+
+void If_CluHashTableCheck( If_Man_t * p )
+{
+    int t = 1;
+    If_Hte_t * pEntry;
+    int i, RetValue, Status;
+    for ( i = 0; i < p->nTableSize[t]; i++ )
+    {
+        for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[i]; pEntry; pEntry = pEntry->pNext )
+        {        
+            Status = ((pEntry->Group & 15) > 0);
+            RetValue = If_CutPerformCheck16( NULL, (unsigned *)pEntry->pTruth, 13, If_CluSupportSize(pEntry->pTruth, 13), "555" );
+            if ( RetValue != Status ) 
+            {
+                Kit_DsdPrintFromTruth( (unsigned*)pEntry->pTruth, 13 ); printf( "\n" );
+                RetValue = If_CutPerformCheck16( NULL, (unsigned *)pEntry->pTruth, 13, If_CluSupportSize(pEntry->pTruth, 13), "555" );
+                printf( "Hash table problem!!!\n" );
+            }
+        }
+    }
+}
+void If_CluHashPrintStats( If_Man_t * p, int t )
+{
+    If_Hte_t * pEntry;
+    int i, Counter;
+    for ( i = 0; i < p->nTableSize[t]; i++ )
+    {
+        Counter = 0;
+        for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[i]; pEntry; pEntry = pEntry->pNext )
+            Counter++;
+        if ( Counter == 0 )
+            continue;
+        if ( Counter < 10 )
+            continue;
+        printf( "%d=%d ", i, Counter );
+    }
+}
+int If_CluHashFindMedian( If_Man_t * p, int t )
+{
+    If_Hte_t * pEntry;
+    Vec_Int_t * vCounters;
+    int i, Max = 0, Total = 0, Half = 0;
+    vCounters = Vec_IntStart( 1000 );
+    for ( i = 0; i < p->nTableSize[t]; i++ )
+    {
+        for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[i]; pEntry; pEntry = pEntry->pNext )
+        {
+            if ( Max < (int)pEntry->Counter )
+            {
+                Max = pEntry->Counter;
+                Vec_IntSetEntry( vCounters, pEntry->Counter, 0 );
+            }
+            Vec_IntAddToEntry( vCounters, pEntry->Counter, 1 );
+            Total++;
+        }
+    }
+    for ( i = Max; i > 0; i-- )
+    {
+        Half += Vec_IntEntry( vCounters, i );
+        if ( Half > Total/2 )
+            break;
+    }
+/*
+    printf( "total = %d  ", Total );
+    printf( "half = %d  ", Half );
+    printf( "i = %d  ", i );
+    printf( "Max = %d.\n", Max );
+*/
+    Vec_IntFree( vCounters );
+    return Abc_MaxInt( i, 1 );
+}
+int If_CluHashKey( word * pTruth, int nWords, int Size )
+{
+    static unsigned BigPrimes[8] = {12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741};
+    unsigned Value = 0;
+    int i;
+    if ( nWords < 4 )
+    {
+        unsigned char * s = (unsigned char *)pTruth;
+        for ( i = 0; i < 8 * nWords; i++ )
+            Value ^= BigPrimes[i % 7] * s[i];
+    }
+    else
+    {
+        unsigned * s = (unsigned *)pTruth;
+        for ( i = 0; i < 2 * nWords; i++ )
+            Value ^= BigPrimes[i % 7] * s[i];
+    }
+    return Value % Size;
+}
+unsigned * If_CluHashLookup( If_Man_t * p, word * pTruth, int t )
+{
+    If_Hte_t * pEntry, * pPrev;
+    int nWords, HashKey;
+    if ( p == NULL )
+        return NULL;
+    nWords = If_CluWordNum(p->pPars->nLutSize);
+    if ( p->pMemEntries == NULL )
+        p->pMemEntries = Mem_FixedStart( sizeof(If_Hte_t) + sizeof(word) * (If_CluWordNum(p->pPars->nLutSize) - 1) );
+    if ( p->pHashTable[t] == NULL )
+    {
+        // decide how large should be the table
+        int nEntriesMax1 = 4 * If_CluPrimeCudd( Vec_PtrSize(p->vObjs) * p->pPars->nCutsMax );
+        int nEntriesMax2 = (int)(((double)CLU_MEM_MAX * (1 << 20)) / If_CluWordNum(p->pPars->nLutSize) / 8);
+//        int nEntriesMax2 = 10000;
+        // create table
+        p->nTableSize[t] = If_CluPrimeCudd( Abc_MinInt(nEntriesMax1, nEntriesMax2)/2 );
+        p->pHashTable[t] = ABC_CALLOC( void *, p->nTableSize[t] );
+    }
+    // check if this entry exists
+    HashKey = If_CluHashKey( pTruth, nWords, p->nTableSize[t] );
+    for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[HashKey]; pEntry; pEntry = pEntry->pNext )
+        if ( memcmp(pEntry->pTruth, pTruth, sizeof(word) * nWords) == 0 )
+        {
+            pEntry->Counter++;
+            return &pEntry->Group;
+        }
+    // resize the hash table
+    if ( p->nTableEntries[t] >= 2 * p->nTableSize[t] )
+    {
+        // collect useful entries
+        If_Hte_t * pPrev;
+        Vec_Ptr_t * vUseful = Vec_PtrAlloc( p->nTableEntries[t] );
+        int i, Median = If_CluHashFindMedian( p, t );
+        for ( i = 0; i < p->nTableSize[t]; i++ )
+        {
+            for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[i]; pEntry; )
+            {
+                if ( (int)pEntry->Counter > Median )
+                {
+                    Vec_PtrPush( vUseful, pEntry );
+                    pEntry = pEntry->pNext;
+                }
+                else
+                {
+                    pPrev = pEntry->pNext;
+                    Mem_FixedEntryRecycle( p->pMemEntries, (char *)pEntry );
+                    pEntry = pPrev;
+                }
+            }
+        }
+        // add useful entries
+        memset( p->pHashTable[t], 0, sizeof(void *) * p->nTableSize[t] );
+        Vec_PtrForEachEntry( If_Hte_t *, vUseful, pEntry, i )
+        {
+            HashKey = If_CluHashKey( pEntry->pTruth, nWords, p->nTableSize[t] );
+            pPrev = ((If_Hte_t **)p->pHashTable[t])[HashKey];
+            if ( pPrev == NULL || pEntry->Counter >= pPrev->Counter )
+            {
+                pEntry->pNext = pPrev;
+                ((If_Hte_t **)p->pHashTable[t])[HashKey] = pEntry;
+            }
+            else
+            {
+                while ( pPrev->pNext && pEntry->Counter < pPrev->pNext->Counter )
+                    pPrev = pPrev->pNext;
+                pEntry->pNext = pPrev->pNext;
+                pPrev->pNext = pEntry;
+            }
+        }
+        p->nTableEntries[t] = Vec_PtrSize( vUseful );
+        Vec_PtrFree( vUseful );
+    }
+    // create entry
+    p->nTableEntries[t]++;
+    pEntry = (If_Hte_t *)Mem_FixedEntryFetch( p->pMemEntries );
+    memcpy( pEntry->pTruth, pTruth, sizeof(word) * nWords );
+    pEntry->Group = CLU_UNUSED;
+    pEntry->Counter = 1;
+    // insert at the beginning
+//    pEntry->pNext = ((If_Hte_t **)p->pHashTable[t])[HashKey];
+//    ((If_Hte_t **)p->pHashTable[t])[HashKey] = pEntry;
+    // insert at the end
+    pEntry->pNext = NULL;
+    for ( pPrev = ((If_Hte_t **)p->pHashTable[t])[HashKey]; pPrev && pPrev->pNext; pPrev = pPrev->pNext );
+    if ( pPrev == NULL )
+        ((If_Hte_t **)p->pHashTable[t])[HashKey] = pEntry;
+    else
+        pPrev->pNext = pEntry;
+    return &pEntry->Group;
+}
+
+// variable permutation for large functions
+static inline void If_CluClear( word * pIn, int nVars )
+{
+    int w, nWords = If_CluWordNum( nVars );
+    for ( w = 0; w < nWords; w++ )
+        pIn[w] = 0;
+}
+static inline void If_CluFill( word * pIn, int nVars )
+{
+    int w, nWords = If_CluWordNum( nVars );
+    for ( w = 0; w < nWords; w++ )
+        pIn[w] = ~(word)0;
+}
+static inline void If_CluCopy( word * pOut, word * pIn, int nVars )
+{
+    int w, nWords = If_CluWordNum( nVars );
+    for ( w = 0; w < nWords; w++ )
+        pOut[w] = pIn[w];
+}
+static inline int If_CluEqual( word * pOut, word * pIn, int nVars )
+{
+    int w, nWords = If_CluWordNum( nVars );
+    for ( w = 0; w < nWords; w++ )
+        if ( pOut[w] != pIn[w] )
+            return 0;
+    return 1;
+}
+static inline void If_CluAnd( word * pRes, word * pIn1, word * pIn2, int nVars )
+{
+    int w, nWords = If_CluWordNum( nVars );
+    for ( w = 0; w < nWords; w++ )
+        pRes[w] = pIn1[w] & pIn2[w];
+}
+static inline void If_CluSharp( word * pRes, word * pIn1, word * pIn2, int nVars )
+{
+    int w, nWords = If_CluWordNum( nVars );
+    for ( w = 0; w < nWords; w++ )
+        pRes[w] = pIn1[w] & ~pIn2[w];
+} 
+static inline void If_CluOr( word * pRes, word * pIn1, word * pIn2, int nVars )
+{
+    int w, nWords = If_CluWordNum( nVars );
+    for ( w = 0; w < nWords; w++ )
+        pRes[w] = pIn1[w] | pIn2[w];
+}
+static inline word If_CluAdjust( word t, int nVars )
+{
+    assert( nVars >= 0 && nVars <= 6 );
+    if ( nVars == 6 )
+        return t;
+    t &= (((word)1) << (1 << nVars)) - 1;
+    if ( nVars == 0 )
+        t |= t << (1<<nVars++);
+    if ( nVars == 1 )
+        t |= t << (1<<nVars++);
+    if ( nVars == 2 )
+        t |= t << (1<<nVars++);
+    if ( nVars == 3 )
+        t |= t << (1<<nVars++);
+    if ( nVars == 4 )
+        t |= t << (1<<nVars++);
+    if ( nVars == 5 )
+        t |= t << (1<<nVars++);
+    return t;
+}
+static inline void If_CluAdjustBig( word * pF, int nVarsCur, int nVarsMax )
+{
+    int v, nWords;
+    if ( nVarsCur == nVarsMax )
+        return;
+    assert( nVarsCur < nVarsMax );
+    for ( v = Abc_MaxInt( nVarsCur, 6 ); v < nVarsMax; v++ )
+    {
+        nWords = If_CluWordNum( v );
+        If_CluCopy( pF + nWords, pF, v );
+    }
+}
+static inline void If_CluSwapAdjacent( word * pOut, word * pIn, int iVar, int nVars )
+{
+    int i, k, nWords = If_CluWordNum( nVars );
+    assert( iVar < nVars - 1 );
+    if ( iVar < 5 )
+    {
+        int Shift = (1 << iVar);
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift);
+    }
+    else if ( iVar > 5 )
+    {
+        int Step = (1 << (iVar - 6));
+        for ( k = 0; k < nWords; k += 4*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                pOut[i] = pIn[i];
+            for ( i = 0; i < Step; i++ )
+                pOut[Step+i] = pIn[2*Step+i];
+            for ( i = 0; i < Step; i++ )
+                pOut[2*Step+i] = pIn[Step+i];
+            for ( i = 0; i < Step; i++ )
+                pOut[3*Step+i] = pIn[3*Step+i];
+            pIn  += 4*Step;
+            pOut += 4*Step;
+        }
+    }
+    else // if ( iVar == 5 )
+    {
+        for ( i = 0; i < nWords; i += 2 )
+        {
+            pOut[i]   = (pIn[i]   & ABC_CONST(0x00000000FFFFFFFF)) | ((pIn[i+1] & ABC_CONST(0x00000000FFFFFFFF)) << 32);
+            pOut[i+1] = (pIn[i+1] & ABC_CONST(0xFFFFFFFF00000000)) | ((pIn[i]   & ABC_CONST(0xFFFFFFFF00000000)) >> 32);
+        }
+    }
+}
+
+void If_CluChangePhase( word * pF, int nVars, int iVar )
+{
+    int nWords = If_CluWordNum( nVars );
+    assert( iVar < nVars );
+    if ( iVar < 6 )
+    {
+        int i, Shift = (1 << iVar);
+        for ( i = 0; i < nWords; i++ )
+            pF[i] = ((pF[i] & ~Truth6[iVar]) << Shift) | ((pF[i] & Truth6[iVar]) >> Shift);
+    }
+    else
+    {
+        word Temp;
+        int i, k, Step = (1 << (iVar - 6));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+            {
+                Temp = pF[i];
+                pF[i] = pF[Step+i];
+                pF[Step+i] = Temp;
+            }
+            pF += 2*Step;
+        }
+    }
+}
+void If_CluCountOnesInCofs( word * pTruth, int nVars, int * pStore )
+{
+    int nWords = If_CluWordNum( nVars );
+    int i, k, nOnes = 0, Limit = Abc_MinInt( nVars, 6 );
+    memset( pStore, 0, sizeof(int) * 2 * nVars );
+    // compute positive cofactors
+    for ( k = 0; k < nWords; k++ )
+        for ( i = 0; i < Limit; i++ )
+            pStore[2*i+1] += If_CluCountOnes( pTruth[k] & Truth6[i] );
+    if ( nVars > 6 )
+    for ( k = 0; k < nWords; k++ )
+        for ( i = 6; i < nVars; i++ )
+            if ( k & (1 << (i-6)) )
+                pStore[2*i+1] += If_CluCountOnes( pTruth[k] );
+    // compute negative cofactors
+    for ( k = 0; k < nWords; k++ )
+        nOnes += If_CluCountOnes( pTruth[k] );
+    for ( i = 0; i < nVars; i++ )
+        pStore[2*i] = nOnes - pStore[2*i+1];
+}
+unsigned If_CluSemiCanonicize( word * pTruth, int nVars, int * pCanonPerm )
+{
+    word pFunc[CLU_WRD_MAX], * pIn = pTruth, * pOut = pFunc, * pTemp;
+    int pStore[CLU_VAR_MAX*2];
+    unsigned uCanonPhase = 0;
+    int i, Temp, fChange, Counter = 0;
+//Kit_DsdPrintFromTruth( (unsigned*)pTruth, nVars ); printf( "\n" );
+
+    // collect signatures 
+    If_CluCountOnesInCofs( pTruth, nVars, pStore );
+    // canonicize phase
+    for ( i = 0; i < nVars; i++ )
+    {
+        if ( pStore[2*i+0] <= pStore[2*i+1] )
+            continue;
+        uCanonPhase |= (1 << i);
+        Temp = pStore[2*i+0];
+        pStore[2*i+0] = pStore[2*i+1];
+        pStore[2*i+1] = Temp;
+        If_CluChangePhase( pIn, nVars, i );
+    }
+    // compute permutation
+    for ( i = 0; i < nVars; i++ )
+        pCanonPerm[i] = i;
+    do {
+        fChange = 0;
+        for ( i = 0; i < nVars-1; i++ )
+        {
+            if ( pStore[2*i] <= pStore[2*(i+1)] )
+                continue;
+            Counter++;
+            fChange = 1;
+
+            Temp = pCanonPerm[i];
+            pCanonPerm[i] = pCanonPerm[i+1];
+            pCanonPerm[i+1] = Temp;
+
+            Temp = pStore[2*i];
+            pStore[2*i] = pStore[2*(i+1)];
+            pStore[2*(i+1)] = Temp;
+
+            Temp = pStore[2*i+1];
+            pStore[2*i+1] = pStore[2*(i+1)+1];
+            pStore[2*(i+1)+1] = Temp;
+
+            If_CluSwapAdjacent( pOut, pIn, i, nVars );
+            pTemp = pIn; pIn = pOut; pOut = pTemp;
+        }
+    } while ( fChange );
+    // swap if it was moved an odd number of times
+    if ( Counter & 1 )
+        If_CluCopy( pOut, pIn, nVars );
+    return uCanonPhase;
+}
+void If_CluSemiCanonicizeVerify( word * pTruth, word * pTruth0, int nVars, int * pCanonPerm, unsigned uCanonPhase )
+{
+    word pFunc[CLU_WRD_MAX], pGunc[CLU_WRD_MAX], * pIn = pTruth, * pOut = pFunc, * pTemp;
+    int i, Temp, fChange, Counter = 0;
+    If_CluCopy( pGunc, pTruth, nVars );
+    // undo permutation
+    do {
+        fChange = 0;
+        for ( i = 0; i < nVars-1; i++ )
+        {
+            if ( pCanonPerm[i] < pCanonPerm[i+1] )
+                continue;
+
+            Counter++;
+            fChange = 1;
+
+            Temp = pCanonPerm[i];
+            pCanonPerm[i] = pCanonPerm[i+1];
+            pCanonPerm[i+1] = Temp;
+
+            If_CluSwapAdjacent( pOut, pIn, i, nVars );
+            pTemp = pIn; pIn = pOut; pOut = pTemp;
+        }
+    } while ( fChange );
+    if ( Counter & 1 )
+        If_CluCopy( pOut, pIn, nVars );
+    // undo phase
+    for ( i = 0; i < nVars; i++ )
+        if ( (uCanonPhase >> i) & 1 )
+            If_CluChangePhase( pTruth, nVars, i );
+    // compare
+    if ( !If_CluEqual(pTruth0, pTruth, nVars) )
+    {
+        Kit_DsdPrintFromTruth( (unsigned*)pTruth0, nVars ); printf( "\n" );
+        Kit_DsdPrintFromTruth( (unsigned*)pGunc, nVars ); printf( "\n" );
+        Kit_DsdPrintFromTruth( (unsigned*)pTruth, nVars ); printf( "\n" );
+        printf( "SemiCanonical verification FAILED!\n" );
+    }
+}
+
+
+void If_CluPrintGroup( If_Grp_t * g )
+{
+    int i;
+    printf( "Vars = %d   ", g->nVars );
+    printf( "Myu = %d   {", g->nMyu );
+    for ( i = 0; i < g->nVars; i++ )
+        printf( " %c", 'a' + g->pVars[i] );
+    printf( " }\n" );
+}
+
+void If_CluPrintConfig( int nVars, If_Grp_t * g, If_Grp_t * r, word BStruth, word * pFStruth )
+{
+    assert( r->nVars == nVars - g->nVars + 1 + (g->nMyu > 2) );
+    If_CluPrintGroup( g );
+    if ( g->nVars < 6 )
+        BStruth = If_CluAdjust( BStruth, g->nVars );
+    Kit_DsdPrintFromTruth( (unsigned *)&BStruth, g->nVars );
+    printf( "\n" );
+    If_CluPrintGroup( r );
+    if ( r->nVars < 6 )
+        pFStruth[0] = If_CluAdjust( pFStruth[0], r->nVars );
+    Kit_DsdPrintFromTruth( (unsigned *)pFStruth, r->nVars );
+    printf( "\n" );
+}
+
+
+void If_CluInitTruthTables()
+{
+    int i, k;
+    assert( CLU_VAR_MAX <= 16 );
+    for ( i = 0; i < 6; i++ )
+        for ( k = 0; k < CLU_WRD_MAX; k++ )
+            TruthAll[i][k] = Truth6[i];
+    for ( i = 6; i < CLU_VAR_MAX; i++ )
+        for ( k = 0; k < CLU_WRD_MAX; k++ )
+            TruthAll[i][k] = ((k >> (i-6)) & 1) ? ~(word)0 : 0;
+
+//    Extra_PrintHex( stdout, TruthAll[6], 8 ); printf( "\n" );
+//    Extra_PrintHex( stdout, TruthAll[7], 8 ); printf( "\n" );
+}
+
+
+// verification
+static void If_CluComposeLut( int nVars, If_Grp_t * g, word * t, word f[6][CLU_WRD_MAX], word * r )
+{
+    word c[CLU_WRD_MAX];
+    int m, v;
+    If_CluClear( r, nVars ); 
+    for ( m = 0; m < (1<<g->nVars); m++ )
+    {
+        if ( !((t[m >> 6] >> (m & 63)) & 1) )
+            continue;
+        If_CluFill( c, nVars );
+        for ( v = 0; v < g->nVars; v++ )
+            if ( (m >> v) & 1 )
+                If_CluAnd( c, c, f[v], nVars );
+            else
+                If_CluSharp( c, c, f[v], nVars );
+        If_CluOr( r, r, c, nVars );
+    }
+}
+void If_CluVerify( word * pF, int nVars, If_Grp_t * g, If_Grp_t * r, word BStruth, word * pFStruth )
+{
+    word pTTFans[6][CLU_WRD_MAX], pTTWire[CLU_WRD_MAX], pTTRes[CLU_WRD_MAX];
+    int i;
+    assert( g->nVars <= 6 && r->nVars <= 6 );
+
+    if ( TruthAll[0][0] == 0 )
+        If_CluInitTruthTables();
+
+    for ( i = 0; i < g->nVars; i++ )
+        If_CluCopy( pTTFans[i], TruthAll[(int)g->pVars[i]], nVars );
+    If_CluComposeLut( nVars, g, &BStruth, pTTFans, pTTWire );
+
+    for ( i = 0; i < r->nVars; i++ )
+        if ( r->pVars[i] == nVars )
+            If_CluCopy( pTTFans[i], pTTWire, nVars );
+        else
+            If_CluCopy( pTTFans[i], TruthAll[(int)r->pVars[i]], nVars );
+    If_CluComposeLut( nVars, r, pFStruth, pTTFans, pTTRes );
+
+    if ( !If_CluEqual(pTTRes, pF, nVars) )
+	{
+        printf( "\n" );
+        If_CluPrintConfig( nVars, g, r, BStruth, pFStruth );
+        Kit_DsdPrintFromTruth( (unsigned*)pTTRes, nVars ); printf( "\n" );
+        Kit_DsdPrintFromTruth( (unsigned*)pF, nVars ); printf( "\n" );
+//        Extra_PrintHex( stdout, (unsigned *)pF, nVars ); printf( "\n" );
+        printf( "Verification FAILED!\n" );
+	}
+//    else
+//        printf( "Verification succeed!\n" );
+}
+void If_CluVerify3( word * pF, int nVars, If_Grp_t * g, If_Grp_t * g2, If_Grp_t * r, word BStruth, word BStruth2, word FStruth )
+{
+    word pTTFans[6][CLU_WRD_MAX], pTTWire[CLU_WRD_MAX], pTTWire2[CLU_WRD_MAX], pTTRes[CLU_WRD_MAX];
+    int i;
+    assert( g->nVars >= 2 && g2->nVars >= 2 && r->nVars >= 2 );
+    assert( g->nVars <= 6 && g2->nVars <= 6 && r->nVars <= 6 );
+
+    if ( TruthAll[0][0] == 0 )
+        If_CluInitTruthTables();
+
+    for ( i = 0; i < g->nVars; i++ )
+        If_CluCopy( pTTFans[i], TruthAll[(int)g->pVars[i]], nVars );
+    If_CluComposeLut( nVars, g, &BStruth, pTTFans, pTTWire );
+
+    for ( i = 0; i < g2->nVars; i++ )
+        If_CluCopy( pTTFans[i], TruthAll[(int)g2->pVars[i]], nVars );
+    If_CluComposeLut( nVars, g2, &BStruth2, pTTFans, pTTWire2 );
+
+    for ( i = 0; i < r->nVars; i++ )
+        if ( r->pVars[i] == nVars )
+            If_CluCopy( pTTFans[i], pTTWire, nVars );
+        else if ( r->pVars[i] == nVars + 1 )
+            If_CluCopy( pTTFans[i], pTTWire2, nVars );
+        else
+            If_CluCopy( pTTFans[i], TruthAll[(int)r->pVars[i]], nVars );
+    If_CluComposeLut( nVars, r, &FStruth, pTTFans, pTTRes );
+
+    if ( !If_CluEqual(pTTRes, pF, nVars) )
+	{
+        printf( "%d\n", nVars );
+//        If_CluPrintConfig( nVars, g, r, BStruth, pFStruth );
+//        Extra_PrintHex( stdout, (unsigned *)pF, nVars ); printf( "\n" );
+
+        Kit_DsdPrintFromTruth( (unsigned*)&BStruth, g->nVars );   printf( "    " ); If_CluPrintGroup(g);  // printf( "\n" );
+        Kit_DsdPrintFromTruth( (unsigned*)&BStruth2, g2->nVars ); printf( "    " ); If_CluPrintGroup(g2); // printf( "\n" );
+        Kit_DsdPrintFromTruth( (unsigned*)&FStruth, r->nVars );   printf( "    " ); If_CluPrintGroup(r);  // printf( "\n" );
+
+        Kit_DsdPrintFromTruth( (unsigned*)pTTWire, nVars ); printf( "\n" );
+        Kit_DsdPrintFromTruth( (unsigned*)pTTWire2, nVars ); printf( "\n" );
+        Kit_DsdPrintFromTruth( (unsigned*)pTTRes, nVars ); printf( "\n" );
+        Kit_DsdPrintFromTruth( (unsigned*)pF, nVars ); printf( "\n" );
+//        Extra_PrintHex( stdout, (unsigned *)pF, nVars ); printf( "\n" );
+        printf( "Verification FAILED!\n" );
+	}
+//    else
+//        printf( "Verification succeed!\n" );
+}
+
+
+
+void If_CluSwapVars( word * pTruth, int nVars, int * V2P, int * P2V, int iVar, int jVar )
+{
+	word low2High, high2Low, temp;
+	int nWords = If_CluWordNum(nVars);
+	int shift, step, iStep, jStep;
+	int w = 0, i = 0, j = 0;
+	static word PPMasks[6][6] = {
+		{ ABC_CONST(0x2222222222222222), ABC_CONST(0x0A0A0A0A0A0A0A0A), ABC_CONST(0x00AA00AA00AA00AA), ABC_CONST(0x0000AAAA0000AAAA), ABC_CONST(0x00000000AAAAAAAA), ABC_CONST(0xAAAAAAAAAAAAAAAA) },
+		{ ABC_CONST(0x0000000000000000), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x00CC00CC00CC00CC), ABC_CONST(0x0000CCCC0000CCCC), ABC_CONST(0x00000000CCCCCCCC), ABC_CONST(0xCCCCCCCCCCCCCCCC) },
+		{ ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0000F0F00000F0F0), ABC_CONST(0x00000000F0F0F0F0), ABC_CONST(0xF0F0F0F0F0F0F0F0) },
+		{ ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00000000FF00FF00), ABC_CONST(0xFF00FF00FF00FF00) },
+		{ ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0xFFFF0000FFFF0000) },
+		{ ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFF00000000) }
+	};
+	if( iVar == jVar )
+		return;
+	if( jVar < iVar )
+	{
+		int varTemp = jVar;
+		jVar = iVar;
+		iVar = varTemp;
+	}
+	if ( iVar <= 5 && jVar <= 5 )
+	{
+		shift = (1 <<  jVar) - (1 << iVar);
+		for ( w = 0; w < nWords; w++ )
+		{
+			low2High = (pTruth[w] & PPMasks[iVar][jVar - 1] ) << shift;
+			pTruth[w] &= ~PPMasks[iVar][jVar - 1];
+			high2Low = (pTruth[w] & (PPMasks[iVar][jVar - 1] << shift )) >> shift;
+			pTruth[w] &= ~ (PPMasks[iVar][jVar - 1] << shift);
+			pTruth[w] = pTruth[w] | low2High | high2Low;
+		}
+	}
+	else if( iVar <= 5 && jVar > 5 )
+	{
+		step = If_CluWordNum(jVar + 1)/2;
+		shift = 1 << iVar;
+		for ( w = 0; w < nWords; w += 2*step )
+		{
+			for (j = 0; j < step; j++)
+			{
+				low2High = (pTruth[w + j] & PPMasks[iVar][5]) >> shift;
+				pTruth[w + j] &= ~PPMasks[iVar][5];
+				high2Low = (pTruth[w + step + j] & (PPMasks[iVar][5] >> shift)) << shift;
+				pTruth[w + step + j] &= ~(PPMasks[iVar][5] >> shift);
+				pTruth[w + j] |= high2Low;
+				pTruth[w + step + j] |= low2High;			
+			}
+		}
+	}
+	else
+	{
+		iStep = If_CluWordNum(iVar + 1)/2;
+		jStep = If_CluWordNum(jVar + 1)/2;
+		for (w = 0; w < nWords; w += 2*jStep)
+		{
+			for (i = 0; i < jStep; i += 2*iStep)
+			{
+				for (j = 0; j < iStep; j++)
+				{
+					temp = pTruth[w + iStep + i + j];
+					pTruth[w + iStep + i + j] = pTruth[w + jStep + i + j];
+					pTruth[w + jStep + i + j] = temp;
+				}
+			}
+		}
+	}	
+    if ( V2P && P2V )
+    {
+        V2P[P2V[iVar]] = jVar;
+        V2P[P2V[jVar]] = iVar;
+        P2V[iVar] ^= P2V[jVar];
+        P2V[jVar] ^= P2V[iVar];
+        P2V[iVar] ^= P2V[jVar];
+    }
+}
+void If_CluReverseOrder( word * pTruth, int nVars, int * V2P, int * P2V, int iVarStart )
+{
+    int i, j, k;
+    for ( k = 0; k < (nVars-iVarStart)/2 ; k++ )
+    {
+        i = iVarStart + k;
+        j = nVars - 1 - k;
+        If_CluSwapVars( pTruth, nVars, V2P, P2V, i, j );
+    }
+}
+
+// moves one var (v) to the given position (p)
+void If_CluMoveVar2( word * pF, int nVars, int * Var2Pla, int * Pla2Var, int v, int p )
+{
+    If_CluSwapVars( pF, nVars, Var2Pla, Pla2Var, Var2Pla[v], p );
+}
+
+// moves one var (v) to the given position (p)
+void If_CluMoveVar( word * pF, int nVars, int * Var2Pla, int * Pla2Var, int v, int p )
+{
+    word pG[CLU_WRD_MAX], * pIn = pF, * pOut = pG, * pTemp;
+    int iPlace0, iPlace1, Count = 0;
+    assert( v >= 0 && v < nVars );
+    while ( Var2Pla[v] < p )
+    {
+        iPlace0 = Var2Pla[v];
+        iPlace1 = Var2Pla[v]+1;
+        If_CluSwapAdjacent( pOut, pIn, iPlace0, nVars );
+        pTemp = pIn; pIn = pOut, pOut = pTemp;
+        Var2Pla[Pla2Var[iPlace0]]++;
+        Var2Pla[Pla2Var[iPlace1]]--;
+        Pla2Var[iPlace0] ^= Pla2Var[iPlace1];
+        Pla2Var[iPlace1] ^= Pla2Var[iPlace0];
+        Pla2Var[iPlace0] ^= Pla2Var[iPlace1];
+        Count++;
+    }
+    while ( Var2Pla[v] > p )
+    {
+        iPlace0 = Var2Pla[v]-1;
+        iPlace1 = Var2Pla[v];
+        If_CluSwapAdjacent( pOut, pIn, iPlace0, nVars );
+        pTemp = pIn; pIn = pOut, pOut = pTemp;
+        Var2Pla[Pla2Var[iPlace0]]++;
+        Var2Pla[Pla2Var[iPlace1]]--;
+        Pla2Var[iPlace0] ^= Pla2Var[iPlace1];
+        Pla2Var[iPlace1] ^= Pla2Var[iPlace0];
+        Pla2Var[iPlace0] ^= Pla2Var[iPlace1];
+        Count++;
+    }
+    if ( Count & 1 )
+        If_CluCopy( pF, pIn, nVars );
+    assert( Pla2Var[p] == v );
+}
+
+// moves vars to be the most signiticant ones (Group[0] is MSB)
+void If_CluMoveGroupToMsb( word * pF, int nVars, int * V2P, int * P2V, If_Grp_t * g )
+{
+    int v;
+    for ( v = 0; v < g->nVars; v++ )
+        If_CluMoveVar( pF, nVars, V2P, P2V, g->pVars[g->nVars - 1 - v], nVars - 1 - v );
+}
+
+
+// reverses the variable order
+void If_CluReverseOrder_old( word * pF, int nVars, int * V2P, int * P2V, int iVarStart )
+{
+    word pG[CLU_WRD_MAX];
+    int v;
+
+    If_CluCopy( pG, pF, nVars );
+
+//    for ( v = 0; v < nVars; v++ )
+//        printf( "%c ", 'a' + P2V[v] );
+//    printf( "  ---  " );
+
+    for ( v = iVarStart; v < nVars; v++ )
+        If_CluMoveVar( pF, nVars, V2P, P2V, P2V[iVarStart], nVars - 1 - (v - iVarStart) );
+
+//    for ( v = 0; v < nVars; v++ )
+//        printf( "%c ", 'a' + P2V[v] );
+//    printf( "\n" );
+
+//    if ( iVarStart > 0 )
+//        return;
+
+    If_CluReverseOrder( pG, nVars, NULL, NULL, iVarStart );
+    if ( If_CluEqual( pG, pF, nVars ) )
+    {
+//        printf( "+" );
+    }
+    else
+    {
+/*
+        printf( "\n" );
+        Kit_DsdPrintFromTruth( (unsigned*)pF, nVars ); printf( "\n" );
+        Kit_DsdPrintFromTruth( (unsigned*)pG, nVars ); 
+        printf( "\n" );
+*/
+        printf( "%d ", nVars );
+    }
+}
+
+// return the number of cofactors w.r.t. the topmost vars (nBSsize)
+int If_CluCountCofs( word * pF, int nVars, int nBSsize, int iShift, word pCofs[3][CLU_WRD_MAX/4] )
+{
+    word iCofs[128], iCof, Result = 0;
+    word * pCofA, * pCofB;
+    int nMints = (1 << nBSsize);
+    int i, c, w, nCofs;
+    assert( nBSsize >= 2 && nBSsize <= 7 && nBSsize < nVars );
+    if ( nVars - nBSsize < 6 )
+    {
+        int nShift = (1 << (nVars - nBSsize));
+        word Mask  = ((((word)1) << nShift) - 1);
+        for ( nCofs = i = 0; i < nMints; i++ )
+        {
+            iCof = (pF[(iShift + i * nShift) / 64] >> ((iShift + i * nShift) & 63)) & Mask;
+            for ( c = 0; c < nCofs; c++ )
+                if ( iCof == iCofs[c] )
+                    break;
+            if ( c == nCofs )
+                iCofs[nCofs++] = iCof;
+            if ( pCofs && iCof != iCofs[0] )
+                Result |= (((word)1) << i);
+            if ( nCofs == 5 )
+                break;
+        }
+        if ( nCofs <= 2 && pCofs )
+        {
+            assert( nBSsize <= 6 );
+            pCofs[0][0] = iCofs[0];
+            pCofs[1][0] = (nCofs == 2) ? iCofs[1] : iCofs[0];
+            pCofs[2][0] = Result;
+        }
+    }
+    else
+    {
+        int nWords = If_CluWordNum( nVars - nBSsize );
+        assert( nWords * nMints == If_CluWordNum(nVars) );
+        for ( nCofs = i = 0; i < nMints; i++ )
+        {
+            pCofA = pF + i * nWords;
+            for ( c = 0; c < nCofs; c++ )
+            {
+                pCofB = pF + iCofs[c] * nWords;
+                for ( w = 0; w < nWords; w++ )
+                    if ( pCofA[w] != pCofB[w] )
+                        break;
+                if ( w == nWords )
+                    break;
+            }
+            if ( c == nCofs )
+                iCofs[nCofs++] = i;
+            if ( pCofs )
+            {
+                assert( nBSsize <= 6 );
+                pCofB = pF + iCofs[0] * nWords;
+                for ( w = 0; w < nWords; w++ )
+                    if ( pCofA[w] != pCofB[w] )
+                        break;
+                if ( w != nWords )
+                    Result |= (((word)1) << i);
+            }
+            if ( nCofs == 5 )
+                break;
+        }
+        if ( nCofs <= 2 && pCofs )
+        {
+            If_CluCopy( pCofs[0], pF + iCofs[0] * nWords, nVars - nBSsize );
+            If_CluCopy( pCofs[1], pF + ((nCofs == 2) ? iCofs[1] : iCofs[0]) * nWords, nVars - nBSsize );
+            pCofs[2][0] = Result;
+        }
+    }
+    assert( nCofs >= 1 && nCofs <= 5 );
+    return nCofs;
+}
+
+// return the number of cofactors w.r.t. the topmost vars (nBSsize)
+int If_CluCountCofs4( word * pF, int nVars, int nBSsize, word pCofs[6][CLU_WRD_MAX/4] )
+{
+    word iCofs[128], iCof, Result0 = 0, Result1 = 0;
+    int nMints = (1 << nBSsize);
+    int i, c, nCofs;
+    assert( pCofs );
+    assert( nBSsize >= 2 && nBSsize <= 6 && nBSsize < nVars );
+    if ( nVars - nBSsize < 6 )
+    {
+        int nShift = (1 << (nVars - nBSsize));
+        word Mask  = ((((word)1) << nShift) - 1);
+        for ( nCofs = i = 0; i < nMints; i++ )
+        {
+            iCof = (pF[(i * nShift) / 64] >> ((i * nShift) & 63)) & Mask;
+            for ( c = 0; c < nCofs; c++ )
+                if ( iCof == iCofs[c] )
+                    break;
+            if ( c == nCofs )
+                iCofs[nCofs++] = iCof;
+            if ( c == 1 || c == 3 )
+                Result0 |= (((word)1) << i);
+            if ( c == 2 || c == 3 )
+                Result1 |= (((word)1) << i);
+        }
+        assert( nCofs >= 3 && nCofs <= 4 );
+        pCofs[0][0] = iCofs[0];
+        pCofs[1][0] = iCofs[1];
+        pCofs[2][0] = iCofs[2];
+        pCofs[3][0] = (nCofs == 4) ? iCofs[3] : iCofs[2];
+        pCofs[4][0] = Result0;
+        pCofs[5][0] = Result1;
+    }
+    else
+        assert( 0 );
+    return nCofs;
+}
+
+void If_CluCofactors( word * pF, int nVars, int iVar, word * pCof0, word * pCof1 )
+{
+    int nWords = If_CluWordNum( nVars );
+    assert( iVar < nVars );
+    if ( iVar < 6 )
+    {
+        int i, Shift = (1 << iVar);
+        for ( i = 0; i < nWords; i++ )
+        {
+            pCof0[i] = (pF[i] & ~Truth6[iVar]) | ((pF[i] & ~Truth6[iVar]) << Shift);
+            pCof1[i] = (pF[i] &  Truth6[iVar]) | ((pF[i] &  Truth6[iVar]) >> Shift);
+        }
+    }
+    else
+    {
+        int i, k, Step = (1 << (iVar - 6));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+            {
+                pCof0[i] = pCof0[Step+i] = pF[i];
+                pCof1[i] = pCof1[Step+i] = pF[Step+i];
+            }
+            pF    += 2*Step;
+            pCof0 += 2*Step;
+            pCof1 += 2*Step;
+        }
+    }
+}
+
+// returns 1 if we have special case of cofactors; otherwise, returns 0
+int If_CluDetectSpecialCaseCofs( word * pF, int nVars, int iVar )
+{
+    word Cof0, Cof1;
+    int State[6] = {0};
+    int i, nWords = If_CluWordNum( nVars );
+    assert( iVar < nVars );
+    if ( iVar < 6 )
+    {
+        int Shift = (1 << iVar);
+        for ( i = 0; i < nWords; i++ )
+        {
+            Cof0 =  (pF[i] & ~Truth6[iVar]);
+            Cof1 = ((pF[i] &  Truth6[iVar]) >> Shift);
+
+            if ( Cof0 == 0 )
+                State[0]++;
+            else if ( Cof0 == ~Truth6[iVar] )
+                State[1]++;
+            else if ( Cof1 == 0 )
+                State[2]++;
+            else if ( Cof1 == ~Truth6[iVar] )
+                State[3]++;
+            else if ( Cof0 == ~Cof1 )
+                State[4]++;
+            else if ( Cof0 == Cof1 )
+                State[5]++;
+        }
+    }
+    else
+    {
+        int k, Step = (1 << (iVar - 6));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+            {
+                Cof0 = pF[i];
+                Cof1 = pF[Step+i];
+
+                if ( Cof0 == 0 )
+                    State[0]++;
+                else if ( Cof0 == ~(word)0 )
+                    State[1]++;
+                else if ( Cof1 == 0 )
+                    State[2]++;
+                else if ( Cof1 == ~(word)0 )
+                    State[3]++;
+                else if ( Cof0 == ~Cof1 )
+                    State[4]++;
+                else if ( Cof0 == Cof1 )
+                    State[5]++;
+            }
+            pF    += 2*Step;
+        }
+        nWords /= 2;
+    }
+    assert( State[5] != nWords );
+    for ( i = 0; i < 5; i++ )
+    {
+        assert( State[i] <= nWords );
+        if ( State[i] == nWords )
+            return i;
+    }
+    return -1;
+}
+
+// returns 1 if we have special case of cofactors; otherwise, returns 0
+If_Grp_t If_CluDecUsingCofs( word * pTruth, int nVars, int nLutLeaf )
+{
+    If_Grp_t G = {0};
+    word pF2[CLU_WRD_MAX], * pF = pF2;
+    int Var2Pla[CLU_VAR_MAX+2], Pla2Var[CLU_VAR_MAX+2];
+    int V2P[CLU_VAR_MAX+2], P2V[CLU_VAR_MAX+2];
+    int nVarsNeeded = nVars - nLutLeaf;
+    int v, i, k, iVar, State;
+//Kit_DsdPrintFromTruth( (unsigned*)pTruth, nVars ); printf( "\n" );
+    // create local copy
+    If_CluCopy( pF, pTruth, nVars );
+    for ( k = 0; k < nVars; k++ )
+        Var2Pla[k] = Pla2Var[k] = k;
+    // find decomposable vars 
+    for ( i = 0; i < nVarsNeeded; i++ )
+    {
+        for ( v = nVars - 1; v >= 0; v-- )
+        {
+            State = If_CluDetectSpecialCaseCofs( pF, nVars, v );
+            if ( State == -1 )
+                continue;
+            // update the variable place
+            iVar = Pla2Var[v];
+            while ( Var2Pla[iVar] < nVars - 1 )
+            {
+                int iPlace0 = Var2Pla[iVar];
+                int iPlace1 = Var2Pla[iVar]+1;
+                Var2Pla[Pla2Var[iPlace0]]++;
+                Var2Pla[Pla2Var[iPlace1]]--;
+                Pla2Var[iPlace0] ^= Pla2Var[iPlace1];
+                Pla2Var[iPlace1] ^= Pla2Var[iPlace0];
+                Pla2Var[iPlace0] ^= Pla2Var[iPlace1];
+            }
+            // move this variable to the top
+            for ( k = 0; k < nVars; k++ )
+                V2P[k] = P2V[k] = k;
+//Kit_DsdPrintFromTruth( (unsigned*)pF, nVars ); printf( "\n" );
+            If_CluMoveVar( pF, nVars, V2P, P2V, v, nVars - 1 );
+//Kit_DsdPrintFromTruth( (unsigned*)pF, nVars ); printf( "\n" );
+            // choose cofactor to follow
+            iVar = nVars - 1;
+            if ( State == 0 || State == 1 ) // need cof1
+            {
+                if ( iVar < 6 )
+                    pF[0] = (pF[0] &  Truth6[iVar]) | ((pF[0] &  Truth6[iVar]) >> (1 << iVar));
+                else
+                    pF += If_CluWordNum( nVars ) / 2;
+            }
+            else // need cof0
+            {
+                if ( iVar < 6 )
+                    pF[0] = (pF[0] & ~Truth6[iVar]) | ((pF[0] & ~Truth6[iVar]) << (1 << iVar));
+            }
+            // update the variable count
+            nVars--;
+            break;
+        }
+        if ( v == -1 )
+            return G;
+    }
+    // create the resulting group
+    G.nVars = nLutLeaf;
+    G.nMyu = 2;
+    for ( v = 0; v < G.nVars; v++ )
+        G.pVars[v] = Pla2Var[v];
+    return G;
+}
+
+
+
+// deriving decomposition
+word If_CluDeriveDisjoint( word * pF, int nVars, int * V2P, int * P2V, If_Grp_t * g, If_Grp_t * r )
+{
+    word pCofs[3][CLU_WRD_MAX/4];
+    int i, RetValue, nFSset = nVars - g->nVars;
+    RetValue = If_CluCountCofs( pF, nVars, g->nVars, 0, pCofs );
+//    assert( RetValue == 2 );
+
+    if ( nFSset < 6 )
+        pF[0] = (pCofs[1][0] << (1 << nFSset)) | pCofs[0][0];
+    else
+    {
+        If_CluCopy( pF, pCofs[0], nFSset );
+        If_CluCopy( pF + If_CluWordNum(nFSset), pCofs[1], nFSset );
+    }
+    // create the resulting group
+    if ( r )
+    {
+        r->nVars = nFSset + 1;
+        r->nMyu = 0;
+        for ( i = 0; i < nFSset; i++ )
+            r->pVars[i] = P2V[i];
+        r->pVars[nFSset] = nVars;
+    }
+    return pCofs[2][0];
+}
+void If_CluDeriveDisjoint4( word * pF, int nVars, int * V2P, int * P2V, If_Grp_t * g, If_Grp_t * r, word * pTruth0, word * pTruth1 )
+{
+    word pCofs[6][CLU_WRD_MAX/4];
+    word Cof0, Cof1;
+    int i, RetValue, nFSset = nVars - g->nVars;
+
+    assert( g->nVars <= 6 && nFSset <= 4 );
+
+    RetValue = If_CluCountCofs4( pF, nVars, g->nVars, pCofs );
+    if ( RetValue != 3 && RetValue != 4 )
+        printf( "If_CluDeriveDisjoint4(): Error!!!\n" );
+
+    Cof0  = (pCofs[1][0] << (1 << nFSset)) | pCofs[0][0];
+    Cof1  = (pCofs[3][0] << (1 << nFSset)) | pCofs[2][0];
+    pF[0] = (Cof1 << (1 << (nFSset+1))) | Cof0;
+    pF[0] = If_CluAdjust( pF[0], nFSset + 2 );
+
+    // create the resulting group
+    r->nVars = nFSset + 2;
+    r->nMyu = 0;
+    for ( i = 0; i < nFSset; i++ )
+        r->pVars[i] = P2V[i];
+    r->pVars[nFSset] = nVars;
+    r->pVars[nFSset+1] = nVars+1;
+
+    *pTruth0 = If_CluAdjust( pCofs[4][0], g->nVars );
+    *pTruth1 = If_CluAdjust( pCofs[5][0], g->nVars );
+}
+
+word If_CluDeriveNonDisjoint( word * pF, int nVars, int * V2P, int * P2V, If_Grp_t * g, If_Grp_t * r )
+{
+    word pCofs[2][CLU_WRD_MAX];
+    word Truth0, Truth1, Truth;
+    int i, nFSset = nVars - g->nVars, nFSset1 = nFSset + 1;
+    If_CluCofactors( pF, nVars, nVars - 1, pCofs[0], pCofs[1] );
+
+//    Extra_PrintHex( stdout, (unsigned *)pCofs[0], nVars ); printf( "\n" );
+//    Extra_PrintHex( stdout, (unsigned *)pCofs[1], nVars ); printf( "\n" );
+
+    g->nVars--;
+    Truth0 = If_CluDeriveDisjoint( pCofs[0], nVars - 1, V2P, P2V, g, NULL );
+    Truth1 = If_CluDeriveDisjoint( pCofs[1], nVars - 1, V2P, P2V, g, NULL );
+    Truth  = (Truth1 << (1 << g->nVars)) | Truth0;
+    g->nVars++;
+    if ( nFSset1 < 6 )
+        pF[0] = (pCofs[1][0] << (1 << nFSset1)) | pCofs[0][0];
+    else
+    {
+        If_CluCopy( pF, pCofs[0], nFSset1 );
+        If_CluCopy( pF + If_CluWordNum(nFSset1), pCofs[1], nFSset1 );
+    }
+
+//    Extra_PrintHex( stdout, (unsigned *)&Truth0, 6 ); printf( "\n" );
+//    Extra_PrintHex( stdout, (unsigned *)&Truth1, 6 ); printf( "\n" );
+//    Extra_PrintHex( stdout, (unsigned *)&pCofs[0][0], 6 ); printf( "\n" );
+//    Extra_PrintHex( stdout, (unsigned *)&pCofs[1][0], 6 ); printf( "\n" );
+//    Extra_PrintHex( stdout, (unsigned *)&Truth, 6 ); printf( "\n" );
+//    Extra_PrintHex( stdout, (unsigned *)&pF[0], 6 ); printf( "\n" );
+
+    // create the resulting group
+    r->nVars = nFSset + 2;
+    r->nMyu = 0;
+    for ( i = 0; i < nFSset; i++ )
+        r->pVars[i] = P2V[i];
+    r->pVars[nFSset] = nVars;
+    r->pVars[nFSset+1] = g->pVars[g->nVars - 1];
+    return Truth;
+}
+
+// check non-disjoint decomposition
+int If_CluCheckNonDisjointGroup( word * pF, int nVars, int * V2P, int * P2V, If_Grp_t * g )
+{
+    int v, i, nCofsBest2;
+    if ( (g->nMyu == 3 || g->nMyu == 4) )
+    {
+        word pCofs[2][CLU_WRD_MAX];
+        // try cofactoring w.r.t. each variable
+        for ( v = 0; v < g->nVars; v++ )
+        {
+            If_CluCofactors( pF, nVars, V2P[(int)g->pVars[v]], pCofs[0], pCofs[1] );
+            nCofsBest2 = If_CluCountCofs( pCofs[0], nVars, g->nVars, 0, NULL );
+            if ( nCofsBest2 > 2 )
+                continue;
+            nCofsBest2 = If_CluCountCofs( pCofs[1], nVars, g->nVars, 0, NULL );
+            if ( nCofsBest2 > 2 )
+                continue;
+            // found good shared variable - move to the end
+            If_CluMoveVar( pF, nVars, V2P, P2V, g->pVars[v], nVars-1 );
+            for ( i = 0; i < g->nVars; i++ )
+                g->pVars[i] = P2V[nVars-g->nVars+i];
+            return 1;
+        }
+    }
+    return 0;
+}
+
+
+// finds a good var group (cof count < 6; vars are MSBs)
+If_Grp_t If_CluFindGroup( word * pF, int nVars, int iVarStart, int iVarStop, int * V2P, int * P2V, int nBSsize, int fDisjoint )
+{
+    int fVerbose = 0;
+    int nRounds = 2;//nBSsize;
+    If_Grp_t G = {0}, * g = &G;//, BestG = {0};
+    int i, r, v, nCofs, VarBest, nCofsBest2;
+    assert( nVars > nBSsize && nVars >= nBSsize + iVarStart && nVars <= CLU_VAR_MAX );
+    assert( nBSsize >= 2 && nBSsize <= 6 );
+    assert( !iVarStart || !iVarStop );
+    // start with the default group
+    g->nVars = nBSsize;
+    g->nMyu = If_CluCountCofs( pF, nVars, nBSsize, 0, NULL );
+    for ( i = 0; i < nBSsize; i++ )
+        g->pVars[i] = P2V[nVars-nBSsize+i];
+    // check if good enough
+    if ( g->nMyu == 2 )
+        return G;
+    if ( !fDisjoint && If_CluCheckNonDisjointGroup( pF, nVars, V2P, P2V, g ) )
+    {
+//        BestG = G;
+        return G;
+    }
+    if ( nVars == nBSsize + iVarStart )
+    {
+        g->nVars = 0;
+        return G;
+    }
+
+    if ( fVerbose )
+    {
+        printf( "Iter %2d  ", -1 );
+        If_CluPrintGroup( g );
+    }
+
+    // try to find better group
+    for ( r = 0; r < nRounds; r++ )
+    {
+        if ( nBSsize < nVars-1 )
+        {
+            // find the best var to add
+            VarBest = P2V[nVars-1-nBSsize];
+            nCofsBest2 = If_CluCountCofs( pF, nVars, nBSsize+1, 0, NULL );
+            for ( v = nVars-2-nBSsize; v >= iVarStart; v-- )
+            {
+//                If_CluMoveVar( pF, nVars, V2P, P2V, P2V[v], nVars-1-nBSsize );
+                If_CluMoveVar2( pF, nVars, V2P, P2V, P2V[v], nVars-1-nBSsize );
+                nCofs = If_CluCountCofs( pF, nVars, nBSsize+1, 0, NULL );
+                if ( nCofsBest2 >= nCofs )
+                {
+                    nCofsBest2 = nCofs;
+                    VarBest = P2V[nVars-1-nBSsize];
+                }
+            }
+            // go back
+//            If_CluMoveVar( pF, nVars, V2P, P2V, VarBest, nVars-1-nBSsize );
+            If_CluMoveVar2( pF, nVars, V2P, P2V, VarBest, nVars-1-nBSsize );
+            // update best bound set
+            nCofs = If_CluCountCofs( pF, nVars, nBSsize+1, 0, NULL );
+            assert( nCofs == nCofsBest2 );
+        }
+
+        // find the best var to remove
+        VarBest = P2V[nVars-1-nBSsize];
+        nCofsBest2 = If_CluCountCofs( pF, nVars, nBSsize, 0, NULL );
+        for ( v = nVars-nBSsize; v < nVars-iVarStop; v++ )
+        {
+//            If_CluMoveVar( pF, nVars, V2P, P2V, P2V[v], nVars-1-nBSsize );
+            If_CluMoveVar2( pF, nVars, V2P, P2V, P2V[v], nVars-1-nBSsize );
+            nCofs = If_CluCountCofs( pF, nVars, nBSsize, 0, NULL );
+            if ( nCofsBest2 >= nCofs )
+            {
+                nCofsBest2 = nCofs;
+                VarBest = P2V[nVars-1-nBSsize];
+            }
+        }
+
+        // go back
+//        If_CluMoveVar( pF, nVars, V2P, P2V, VarBest, nVars-1-nBSsize );
+        If_CluMoveVar2( pF, nVars, V2P, P2V, VarBest, nVars-1-nBSsize );
+        // update best bound set
+        nCofs = If_CluCountCofs( pF, nVars, nBSsize, 0, NULL );
+        assert( nCofs == nCofsBest2 );
+        if ( g->nMyu >= nCofs )
+        {
+            g->nVars = nBSsize;
+            g->nMyu = nCofs;
+            for ( i = 0; i < nBSsize; i++ )
+                g->pVars[i] = P2V[nVars-nBSsize+i];
+        }
+
+        if ( fVerbose )
+        {
+            printf( "Iter %2d  ", r );
+            If_CluPrintGroup( g );
+        }
+
+        // check if good enough
+        if ( g->nMyu == 2 )
+            return G;
+        if ( !fDisjoint && If_CluCheckNonDisjointGroup( pF, nVars, V2P, P2V, g ) )
+        {
+//            BestG = G;
+            return G;
+        }
+    }
+
+    assert( r == nRounds );
+    g->nVars = 0;
+    return G;
+//    return BestG;
+}
+
+
+// double check that the given group has a decomposition
+void If_CluCheckGroup( word * pTruth, int nVars, If_Grp_t * g )
+{
+    word pF[CLU_WRD_MAX];
+    int v, nCofs, V2P[CLU_VAR_MAX], P2V[CLU_VAR_MAX];
+    assert( g->nVars >= 2 && g->nVars <= 6 ); // vars
+    assert( g->nMyu >= 2 && g->nMyu <= 4 ); // cofs
+    // create permutation
+    for ( v = 0; v < nVars; v++ )
+        V2P[v] = P2V[v] = v;
+    // create truth table
+    If_CluCopy( pF, pTruth, nVars );
+    // move group up
+    If_CluMoveGroupToMsb( pF, nVars, V2P, P2V, g );
+    // check the number of cofactors
+    nCofs = If_CluCountCofs( pF, nVars, g->nVars, 0, NULL );
+    if ( nCofs != g->nMyu )
+        printf( "Group check 0 has failed.\n" );
+    // check compatible
+    if ( nCofs > 2 )
+    {
+        nCofs = If_CluCountCofs( pF, nVars-1, g->nVars-1, 0, NULL );
+        if ( nCofs > 2 )
+            printf( "Group check 1 has failed.\n" );
+        nCofs = If_CluCountCofs( pF, nVars-1, g->nVars-1, (1 << (nVars-1)), NULL );
+        if ( nCofs > 2 )
+            printf( "Group check 2 has failed.\n" );
+    }
+}
+
+
+// double check that the permutation derived is correct
+void If_CluCheckPerm( word * pTruth, word * pF, int nVars, int * V2P, int * P2V )
+{
+    int i;
+    for ( i = 0; i < nVars; i++ )
+        If_CluMoveVar( pF, nVars, V2P, P2V, i, i );
+
+    if ( !If_CluEqual( pTruth, pF, nVars ) )
+        printf( "Permutation FAILED.\n" );
+//    else
+//        printf( "Permutation successful\n" );
+}
+
+
+
+
+static inline int If_CluSuppIsMinBase( int Supp )
+{
+    return (Supp & (Supp+1)) == 0;
+}
+static inline int If_CluHasVar( word * t, int nVars, int iVar )
+{
+    int nWords = If_CluWordNum( nVars );
+    assert( iVar < nVars );
+    if ( iVar < 6 )
+    {
+        int i, Shift = (1 << iVar);
+        for ( i = 0; i < nWords; i++ )
+            if ( (t[i] & ~Truth6[iVar]) != ((t[i] & Truth6[iVar]) >> Shift) )
+                return 1;
+        return 0;
+    }
+    else
+    {
+        int i, k, Step = (1 << (iVar - 6));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                if ( t[i] != t[Step+i] )
+                    return 1;
+            t += 2*Step;
+        }
+        return 0;
+    }
+}
+static inline int If_CluSupport( word * t, int nVars )
+{
+    int v, Supp = 0;
+    for ( v = 0; v < nVars; v++ )
+        if ( If_CluHasVar( t, nVars, v ) )
+            Supp |= (1 << v);
+    return Supp;
+}
+int If_CluSupportSize( word * t, int nVars )
+{
+    int v, SuppSize = 0;
+    for ( v = 0; v < nVars; v++ )
+        if ( If_CluHasVar( t, nVars, v ) )
+            SuppSize++;
+    return SuppSize;
+}
+static inline void If_CluTruthShrink( word * pF, int nVars, int nVarsAll, unsigned Phase )
+{
+    word pG[CLU_WRD_MAX], * pIn = pF, * pOut = pG, * pTemp;
+    int i, k, Var = 0, Counter = 0;
+    assert( nVarsAll <= 16 );
+    for ( i = 0; i < nVarsAll; i++ )
+        if ( Phase & (1 << i) )
+        {
+            for ( k = i-1; k >= Var; k-- )
+            {
+                If_CluSwapAdjacent( pOut, pIn, k, nVarsAll );
+                pTemp = pIn; pIn = pOut, pOut = pTemp;
+                Counter++;
+            }
+            Var++;
+        }
+    assert( Var == nVars );
+    // swap if it was moved an odd number of times
+    if ( Counter & 1 )
+        If_CluCopy( pOut, pIn, nVarsAll );
+}
+int If_CluMinimumBase( word * t, int * pSupp, int nVarsAll, int * pnVars )
+{
+    int v, iVar = 0, uSupp = 0;
+    assert( nVarsAll <= 16 );
+    for ( v = 0; v < nVarsAll; v++ )
+        if ( If_CluHasVar( t, nVarsAll, v ) )
+        {
+            uSupp |= (1 << v);
+            if ( pSupp )
+                pSupp[iVar] = pSupp[v];
+            iVar++;
+        }
+    if ( pnVars )
+        *pnVars = iVar;
+    if ( If_CluSuppIsMinBase( uSupp ) )
+        return 0;
+    If_CluTruthShrink( t, iVar, nVarsAll, uSupp );
+    return 1;
+}
+
+// returns the best group found
+If_Grp_t If_CluCheck( If_Man_t * p, word * pTruth0, int nVars, int iVarStart, int iVarStop, int nLutLeaf, int nLutRoot, 
+                     If_Grp_t * pR, word * pFunc0, word * pFunc1, word * pLeftOver, int fHashing )
+{
+//    int fEnableHashing = 0;
+    If_Grp_t G1 = {0}, R = {0};
+    unsigned * pHashed = NULL;
+    word Truth, pTruth[CLU_WRD_MAX], pF[CLU_WRD_MAX];//, pG[CLU_WRD_MAX];
+    int V2P[CLU_VAR_MAX+2], P2V[CLU_VAR_MAX+2], pCanonPerm[CLU_VAR_MAX];
+    int i, nSupp, uCanonPhase;
+    int nLutSize = p ? p->pPars->nLutSize : nVars;
+    assert( nVars <= CLU_VAR_MAX );
+    assert( nVars <= nLutLeaf + nLutRoot - 1 );
+
+    if ( pR )
+    {
+        pR->nVars = 0;
+        *pFunc0 = 0;
+        *pFunc1 = 0;
+    }
+
+    // canonicize truth table
+    If_CluCopy( pTruth, pTruth0, nLutSize );
+
+    if ( 0 )
+    {
+        uCanonPhase = If_CluSemiCanonicize( pTruth, nVars, pCanonPerm );
+        If_CluAdjustBig( pTruth, nVars, nLutSize );
+    }
+
+//    If_CluSemiCanonicizeVerify( pTruth, pTruth0, nVars, pCanonPerm, uCanonPhase );
+//    If_CluCopy( pTruth, pTruth0, nLutSize );
+
+ /*
+    {
+        int pCanonPerm[32];
+        short pStore[32];
+        unsigned uCanonPhase;
+        If_CluCopy( pF, pTruth, nVars );
+        uCanonPhase = Kit_TruthSemiCanonicize( pF, pG, nVars, pCanonPerm );
+        G1.nVars = 1;
+        return G1;
+    }
+*/
+    // check minnimum base
+    If_CluCopy( pF, pTruth, nVars );
+    for ( i = 0; i < nVars; i++ )
+        V2P[i] = P2V[i] = i;
+    // check support
+    nSupp = If_CluSupport( pF, nVars );
+//Extra_PrintBinary( stdout, &nSupp, 16 );  printf( "\n" );
+    if ( !nSupp || !If_CluSuppIsMinBase(nSupp) )
+    {
+//        assert( 0 );     
+        return G1;
+    }
+
+    // check hash table
+    if ( p && fHashing )
+    {
+        pHashed = If_CluHashLookup( p, pTruth, 0 );
+        if ( pHashed && *pHashed != CLU_UNUSED )
+            If_CluUns2Grp( *pHashed, &G1 );
+    }
+
+    // update the variable order so that the first var was the last one
+    if ( iVarStop )
+        If_CluMoveVar( pF, nVars, V2P, P2V, 0, nVars-1 );
+
+    if ( G1.nVars == 0 ) 
+    {
+        s_Count2++;
+
+        // detect easy cofs
+        if ( iVarStart == 0 )
+            G1 = If_CluDecUsingCofs( pTruth, nVars, nLutLeaf );
+        if ( G1.nVars == 0 )
+        {
+            // perform testing
+            G1 = If_CluFindGroup( pF, nVars, iVarStart, iVarStop, V2P, P2V, nLutLeaf, nLutLeaf + nLutRoot == nVars + 1 );
+    //        If_CluCheckPerm( pTruth, pF, nVars, V2P, P2V );
+            if ( G1.nVars == 0 )
+            {
+                // perform testing with a smaller set
+                if ( nVars < nLutLeaf + nLutRoot - 2 )
+                {
+                    nLutLeaf--;
+                    G1 = If_CluFindGroup( pF, nVars, iVarStart, iVarStop, V2P, P2V, nLutLeaf, nLutLeaf + nLutRoot == nVars + 1 );
+                    nLutLeaf++;
+                }
+                // perform testing with a smaller set
+                if ( nLutLeaf > 4 && nVars < nLutLeaf + nLutRoot - 3 )
+                {
+                    nLutLeaf--;
+                    nLutLeaf--;
+                    G1 = If_CluFindGroup( pF, nVars, iVarStart, iVarStop, V2P, P2V, nLutLeaf, nLutLeaf + nLutRoot == nVars + 1 );
+                    nLutLeaf++;
+                    nLutLeaf++;
+                }
+                if ( G1.nVars == 0 )
+                {
+                    // perform testing with a different order
+                    If_CluReverseOrder( pF, nVars, V2P, P2V, iVarStart );
+                    G1 = If_CluFindGroup( pF, nVars, iVarStart, iVarStop, V2P, P2V, nLutLeaf, nLutLeaf + nLutRoot == nVars + 1 );
+
+                    // check permutation
+    //                If_CluCheckPerm( pTruth, pF, nVars, V2P, P2V );
+                    if ( G1.nVars == 0 )
+                    {
+                        // remember free set, just in case
+//                        for ( i = 0; i < nVars - nLutLeaf; i++ )
+///                           G1.pVars[nLutLeaf+i] = P2V[i];
+                        // if <XY>, this will not be used
+                        // if <XYZ>, this will not be hashed
+
+    /*
+                        if ( nVars == 6 )
+                        {
+                            Extra_PrintHex( stdout, (unsigned *)pF, nVars );  printf( "    " );
+                            Kit_DsdPrintFromTruth( (unsigned*)pF, nVars );  printf( "\n" );
+                            if ( !If_CutPerformCheck07( (unsigned *)pF, 6, 6, NULL ) )
+                                printf( "no\n" );
+                        } 
+    */
+                        if ( pHashed )
+                            *pHashed = If_CluGrp2Uns( &G1 );
+                        return G1;
+                    }
+                }
+            }
+        }
+    }
+
+    // derive
+    if ( pR )
+    {
+        int iNewPos;
+
+        If_CluMoveGroupToMsb( pF, nVars, V2P, P2V, &G1 );
+        if ( G1.nMyu == 2 )
+        {
+            Truth = If_CluDeriveDisjoint( pF, nVars, V2P, P2V, &G1, &R );
+            iNewPos = R.nVars - 1;
+        }
+        else
+        {
+            Truth = If_CluDeriveNonDisjoint( pF, nVars, V2P, P2V, &G1, &R );
+            iNewPos = R.nVars - 2;
+        }
+        assert( R.pVars[iNewPos] == nVars );
+
+        // adjust the functions
+        Truth = If_CluAdjust( Truth, G1.nVars );
+        if ( R.nVars < 6 )
+            pF[0] = If_CluAdjust( pF[0], R.nVars );
+
+//        Kit_DsdPrintFromTruth( (unsigned*)&Truth, G1.nVars ); printf( "  ...1\n" );
+//        Kit_DsdPrintFromTruth( (unsigned*)pF, R.nVars );      printf( "  ...1\n" );
+
+        // update the variable order of R so that the new var was the first one
+//        if ( iVarStart == 0 )
+        {
+            int k, V2P2[CLU_VAR_MAX+2], P2V2[CLU_VAR_MAX+2];
+            assert( iNewPos >= iVarStart );
+            for ( k = 0; k < R.nVars; k++ )
+                V2P2[k] = P2V2[k] = k;
+            If_CluMoveVar( pF, R.nVars, V2P2, P2V2, iNewPos, iVarStart );
+            for ( k = iNewPos; k > iVarStart; k-- )
+                R.pVars[k] = R.pVars[k-1];
+            R.pVars[iVarStart] = nVars;
+        }
+
+//        Kit_DsdPrintFromTruth( (unsigned*)pF, R.nVars ); printf( "  ...2\n" );
+
+        if ( pLeftOver )
+        {
+            if ( R.nVars < 6 )
+                *pLeftOver = If_CluAdjust( pF[0], R.nVars );
+            else
+                If_CluCopy( pLeftOver, pF, R.nVars );
+            If_CluAdjustBig( pLeftOver, R.nVars, nLutSize );
+        }
+
+        // perform checking
+        if ( 0 )
+        {
+            If_CluCheckGroup( pTruth, nVars, &G1 );
+            If_CluVerify( pTruth, nVars, &G1, &R, Truth, pF );
+        } 
+
+        // save functions
+        *pR = R;
+        if ( pFunc0 )
+            *pFunc0 = pF[0];
+        if ( pFunc1 )
+            *pFunc1 = Truth;
+    }
+
+    if ( pHashed )
+        *pHashed = If_CluGrp2Uns( &G1 );
+    return G1;
+}
+
+/*
+static inline word Abc_Tt6Cofactor0( word t, int iVar )
+{
+    assert( iVar >= 0 && iVar < 6 );
+    return (t &~Truth6[iVar]) | ((t &~Truth6[iVar]) << (1<<iVar));
+}
+static inline word Abc_Tt6Cofactor1( word t, int iVar )
+{
+    assert( iVar >= 0 && iVar < 6 );
+    return (t & Truth6[iVar]) | ((t & Truth6[iVar]) >> (1<<iVar));
+}
+*/
+int If_CluCheckDecInAny( word t, int nVars )
+{
+    int v, u, Cof2[2], Cof4[4];
+    for ( v = 0; v < nVars; v++ )
+    {
+        Cof2[0] = Abc_Tt6Cofactor0( t, v );
+        Cof2[1] = Abc_Tt6Cofactor1( t, v );
+        for ( u = v+1; u < nVars; u++ )
+        {
+            Cof4[0] = Abc_Tt6Cofactor0( Cof2[0], u );
+            Cof4[1] = Abc_Tt6Cofactor1( Cof2[0], u );
+            Cof4[2] = Abc_Tt6Cofactor0( Cof2[1], u );
+            Cof4[3] = Abc_Tt6Cofactor1( Cof2[1], u );
+            if ( Cof4[0] == Cof4[1] && Cof4[0] == Cof4[2] )
+                return 1;
+            if ( Cof4[0] == Cof4[2] && Cof4[0] == Cof4[3] )
+                return 1;
+            if ( Cof4[0] == Cof4[1] && Cof4[0] == Cof4[3] )
+                return 1;
+            if ( Cof4[1] == Cof4[2] && Cof4[1] == Cof4[3] )
+                return 1;
+        }
+    }
+    return 0;
+}
+int If_CluCheckDecIn( word t, int nVars )
+{
+    int v, u, Cof2[2], Cof4[4];
+//    for ( v = 0; v < nVars; v++ )
+    for ( v = 0; v < 1; v++ ) // restrict to the first (decomposed) input
+    {
+        Cof2[0] = Abc_Tt6Cofactor0( t, v );
+        Cof2[1] = Abc_Tt6Cofactor1( t, v );
+        for ( u = v+1; u < nVars; u++ )
+        {
+            Cof4[0] = Abc_Tt6Cofactor0( Cof2[0], u );
+            Cof4[1] = Abc_Tt6Cofactor1( Cof2[0], u );
+            Cof4[2] = Abc_Tt6Cofactor0( Cof2[1], u );
+            Cof4[3] = Abc_Tt6Cofactor1( Cof2[1], u );
+            if ( Cof4[0] == Cof4[1] && Cof4[0] == Cof4[2] )
+                return 1;
+            if ( Cof4[0] == Cof4[2] && Cof4[0] == Cof4[3] )
+                return 1;
+            if ( Cof4[0] == Cof4[1] && Cof4[0] == Cof4[3] )
+                return 1;
+            if ( Cof4[1] == Cof4[2] && Cof4[1] == Cof4[3] )
+                return 1;
+        }
+    }
+    return 0;
+}
+int If_CluCheckDecInU( word t, int nVars )
+{
+    int v, u, Cof2[2], Cof4[4];
+//    for ( v = 0; v < nVars; v++ )
+    for ( v = 0; v < 1; v++ ) // restrict to the first (decomposed) input
+    {
+        Cof2[0] = Abc_Tt6Cofactor0( t, v );
+        Cof2[1] = Abc_Tt6Cofactor1( t, v );
+        for ( u = v+1; u < nVars; u++ )
+        {
+            Cof4[0] = Abc_Tt6Cofactor0( Cof2[0], u ); // 00
+            Cof4[1] = Abc_Tt6Cofactor1( Cof2[0], u ); // 01
+            Cof4[2] = Abc_Tt6Cofactor0( Cof2[1], u ); // 10
+            Cof4[3] = Abc_Tt6Cofactor1( Cof2[1], u ); // 11 
+            if ( Cof4[0] == Cof4[1] && Cof4[0] == Cof4[2] ) //  F * a
+                return 1;
+            if ( Cof4[0] == Cof4[2] && Cof4[0] == Cof4[3] ) // !F * a
+                return 1;
+        }
+    }
+    return 0;
+}
+int If_CluCheckDecOut( word t, int nVars )
+{
+    int v;
+    for ( v = 0; v < nVars; v++ )
+        if ( 
+             (t & Truth6[v]) == 0   ||  //  F * !a
+             (~t & Truth6[v]) == 0  ||  // !F * !a
+             (t & ~Truth6[v]) == 0  ||  //  F *  a
+             (~t & ~Truth6[v]) == 0     // !F *  a   
+           )
+            return 1;
+    return 0;
+}
+int If_CluCheckDecOutU( word t, int nVars )
+{
+    int v;
+    for ( v = 0; v < nVars; v++ )
+        if ( 
+             (t & ~Truth6[v]) == 0  ||  //  F *  a
+             (~t & ~Truth6[v]) == 0     // !F *  a   
+           )
+            return 1;
+    return 0;
+}
+
+int If_CutPerformCheck45( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr )
+{    
+    // 5LUT -> 4LUT
+    If_Grp_t G, R;
+    word Func0, Func1;
+    G = If_CluCheck( p, (word *)pTruth, nLeaves, 0, 0, 5, 4, &R, &Func0, &Func1, NULL, 0 );
+    if ( G.nVars == 0 )
+        return 0;
+    Func0 = If_CluAdjust( Func0, R.nVars );
+    Func1 = If_CluAdjust( Func1, G.nVars );
+#if 0
+    Kit_DsdPrintFromTruth( pTruth, nVars ); printf( "\n" );
+    Kit_DsdPrintFromTruth( (unsigned*)&Func0, R.nVars ); printf( "\n" );
+    Kit_DsdPrintFromTruth( (unsigned*)&Func1, G.nVars ); printf( "\n" );
+    If_CluPrintGroup( &R );
+    If_CluPrintGroup( &G );
+#endif
+    if ( G.nVars < 5 || (p->pPars->fEnableCheck75 && If_CluCheckDecOut(Func1, 5)) || (p->pPars->fEnableCheck75u && If_CluCheckDecOutU(Func1, 5)) )
+        return 1;
+    return 0;
+}
+int If_CutPerformCheck54( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr )
+{    
+    // 4LUT -> 5LUT
+    If_Grp_t G, R;
+    word Func0, Func1;
+    G = If_CluCheck( p, (word *)pTruth, nLeaves, 0, 0, 4, 5, &R, &Func0, &Func1, NULL, 0 );
+    if ( G.nVars == 0 )
+        return 0;
+    Func0 = If_CluAdjust( Func0, R.nVars );
+    Func1 = If_CluAdjust( Func1, G.nVars );
+#if 0
+    Kit_DsdPrintFromTruth( pTruth, nVars ); printf( "\n" );
+    Kit_DsdPrintFromTruth( (unsigned*)&Func0, R.nVars ); printf( "\n" );
+    Kit_DsdPrintFromTruth( (unsigned*)&Func1, G.nVars ); printf( "\n" );
+    If_CluPrintGroup( &R );
+    If_CluPrintGroup( &G );
+#endif
+    if ( R.nVars < 5 || (p->pPars->fEnableCheck75 && If_CluCheckDecIn(Func0, 5)) || (p->pPars->fEnableCheck75u && If_CluCheckDecInU(Func0, 5)) )
+        return 1;
+    return 0;
+}
+
+// returns the best group found
+If_Grp_t If_CluCheck3( If_Man_t * p, word * pTruth0, int nVars, int nLutLeaf, int nLutLeaf2, int nLutRoot, 
+                      If_Grp_t * pR, If_Grp_t * pG2, word * pFunc0, word * pFunc1, word * pFunc2 )
+{
+    int fEnableHashing = 0;
+    static int Counter = 0;
+    unsigned * pHashed = NULL;
+    word pLeftOver[CLU_WRD_MAX], Func0, Func1, Func2;
+    If_Grp_t G1 = {0}, G2 = {0}, R = {0}, R2 = {0};
+    int i;
+    Counter++;
+//    if ( Counter == 37590 )
+//    {
+//        int ns = 0;
+//    }
+
+    // check hash table
+    if ( p && fEnableHashing )
+    {
+        pHashed = If_CluHashLookup( p, pTruth0, 1 );
+        if ( pHashed && *pHashed != CLU_UNUSED )
+        {
+            If_CluUns2Grp( *pHashed, &G1 );
+            return G1;
+        }
+    }
+    s_Count3++;
+
+    // check two-node decomposition
+    G1 = If_CluCheck( p, pTruth0, nVars, 0, 0, nLutLeaf, nLutRoot + nLutLeaf2 - 1, &R2, &Func0, &Func1, pLeftOver, 0 );
+    // decomposition does not exist
+    if ( G1.nVars == 0 )
+    {
+        // check for decomposition with two outputs
+        if ( (G1.nMyu == 3 || G1.nMyu == 4) && nLutLeaf == nLutLeaf2 && nVars - nLutLeaf + 2 <= nLutRoot )
+        {
+            int V2P[CLU_VAR_MAX+2], P2V[CLU_VAR_MAX+2];
+            word Func0, Func1, Func2;
+            int iVar0, iVar1;
+
+            G1.nVars = nLutLeaf;
+            If_CluCopy( pLeftOver, pTruth0, nVars );
+            for ( i = 0; i < nVars; i++ )
+                V2P[i] = P2V[i] = i;
+
+            If_CluMoveGroupToMsb( pLeftOver, nVars, V2P, P2V, &G1 );
+            If_CluDeriveDisjoint4( pLeftOver, nVars, V2P, P2V, &G1, &R, &Func1, &Func2 );
+
+            // move the two vars to the front
+            for ( i = 0; i < R.nVars; i++ )
+                V2P[i] = P2V[i] = i;
+            If_CluMoveVar( pLeftOver, R.nVars, V2P, P2V, R.nVars-2, 0 );
+            If_CluMoveVar( pLeftOver, R.nVars, V2P, P2V, R.nVars-1, 1 );
+            iVar0 = R.pVars[R.nVars-2];
+            iVar1 = R.pVars[R.nVars-1];
+            for ( i = R.nVars-1; i > 1; i-- )
+                R.pVars[i] = R.pVars[i-2];
+            R.pVars[0] = iVar0;
+            R.pVars[1] = iVar1;
+
+            Func0 = pLeftOver[0];
+            If_CluVerify3( pTruth0, nVars, &G1, &G1, &R, Func1, Func2, Func0 );
+            if ( pFunc1 && pFunc2 )
+            {
+                *pFunc0 = Func0;
+                *pFunc1 = Func1;
+                *pFunc2 = Func2;
+                *pG2 = G1;
+                *pR = R;
+            }
+
+            if ( pHashed )
+                *pHashed = If_CluGrp2Uns( &G1 );
+//                Kit_DsdPrintFromTruth( (unsigned*)pTruth0, nVars );  printf( "\n" );
+//                If_CluPrintGroup( &G1 );
+            return G1;
+        }
+
+/*
+//        if ( nVars == 6 )
+        {
+//            Extra_PrintHex( stdout, (unsigned *)pTruth0, nVars );  printf( "    " );
+            Kit_DsdPrintFromTruth( (unsigned*)pTruth0, nVars );  printf( "\n" );
+            if ( p != NULL )
+            If_CluCheck3( NULL, pTruth0, nVars, nLutLeaf, nLutLeaf2, nLutRoot, pR, pG2, pFunc0, pFunc1, pFunc2 );
+        } 
+*/
+        if ( pHashed )
+            *pHashed = If_CluGrp2Uns( &G1 );
+        return G1;
+    }
+    // decomposition exists and sufficient
+    if ( R2.nVars <= nLutRoot )
+    {
+        if ( pG2 )     *pG2 = G2;
+        if ( pR )      *pR  = R2;
+        if ( pFunc0 )  *pFunc0 = Func0;
+        if ( pFunc1 )  *pFunc1 = Func1;
+        if ( pFunc2 )  *pFunc2 = 0;
+        if ( pHashed )
+            *pHashed = If_CluGrp2Uns( &G1 );
+        return G1;
+    }
+
+    // try second decomposition
+    {
+        int Test = 0;
+        if ( Test )
+        {
+            Kit_DsdPrintFromTruth( (unsigned*)&pLeftOver, R2.nVars ); printf( "\n" );
+        }
+    }
+
+    // the new variable is at the bottom - skip it (iVarStart = 1)
+    if ( p->pPars->nStructType == 0 ) // allowed
+        G2 = If_CluCheck( p, pLeftOver, R2.nVars, 0, 0, nLutLeaf2, nLutRoot, &R, &Func0, &Func2, NULL, 0 );
+    else if ( p->pPars->nStructType == 1 ) // not allowed
+        G2 = If_CluCheck( p, pLeftOver, R2.nVars, 1, 0, nLutLeaf2, nLutRoot, &R, &Func0, &Func2, NULL, 0 );
+    else if ( p->pPars->nStructType == 2 ) // required
+        G2 = If_CluCheck( p, pLeftOver, R2.nVars, 0, 1, nLutLeaf2, nLutRoot, &R, &Func0, &Func2, NULL, 0 );
+    else assert( 0 );
+
+    if ( G2.nVars == 0 )
+    {
+        if ( pHashed )
+            *pHashed = If_CluGrp2Uns( &G2 );
+        return G2;
+    }
+    // remap variables
+    for ( i = 0; i < G2.nVars; i++ )
+    {
+        assert( G2.pVars[i] < R2.nVars );
+        G2.pVars[i] = R2.pVars[ (int)G2.pVars[i] ];
+    }
+    // remap variables
+    for ( i = 0; i < R.nVars; i++ )
+    {
+        if ( R.pVars[i] == R2.nVars )
+            R.pVars[i] = nVars + 1;
+        else
+            R.pVars[i] = R2.pVars[ (int)R.pVars[i] ];
+    }
+
+    // decomposition exist
+    if ( pG2 )     *pG2 = G2;
+    if ( pR )      *pR  = R;
+    if ( pFunc0 )  *pFunc0 = Func0;
+    if ( pFunc1 )  *pFunc1 = Func1;
+    if ( pFunc2 )  *pFunc2 = Func2;
+    if ( pHashed )
+        *pHashed = If_CluGrp2Uns( &G1 );
+
+    // verify
+//    If_CluVerify3( pTruth0, nVars, &G1, &G2, &R, Func1, Func2, Func0 );
+    return G1;
+}
+
+// returns the best group found
+int If_CluCheckExt( void * pMan, word * pTruth, int nVars, int nLutLeaf, int nLutRoot, 
+                   char * pLut0, char * pLut1, word * pFunc0, word * pFunc1 )
+{
+	If_Man_t * p = (If_Man_t *)pMan;
+    If_Grp_t G, R;
+    G = If_CluCheck( p, pTruth, nVars, 0, 0, nLutLeaf, nLutRoot, &R, pFunc0, pFunc1, NULL, 0 );
+    memcpy( pLut0, &R, sizeof(If_Grp_t) );
+    memcpy( pLut1, &G, sizeof(If_Grp_t) );
+//    memcpy( pLut2, &G2, sizeof(If_Grp_t) );
+    return (G.nVars > 0);
+}
+
+// returns the best group found
+int If_CluCheckExt3( void * pMan, word * pTruth, int nVars, int nLutLeaf, int nLutLeaf2, int nLutRoot, 
+                    char * pLut0, char * pLut1, char * pLut2, word * pFunc0, word * pFunc1, word * pFunc2 )
+{
+	If_Man_t * p = (If_Man_t *)pMan;
+    If_Grp_t G, G2, R;
+    G = If_CluCheck3( p, pTruth, nVars, nLutLeaf, nLutLeaf2, nLutRoot, &R, &G2, pFunc0, pFunc1, pFunc2 );
+    memcpy( pLut0, &R, sizeof(If_Grp_t) );
+    memcpy( pLut1, &G, sizeof(If_Grp_t) );
+    memcpy( pLut2, &G2, sizeof(If_Grp_t) );
+    return (G.nVars > 0);
+}
+
+
+// computes delay of the decomposition
+float If_CluDelayMax( If_Grp_t * g, float * pDelays )
+{
+    float Delay = 0.0;
+    int i;
+    for ( i = 0; i < g->nVars; i++ )
+        Delay = Abc_MaxFloat( Delay, pDelays[(int)g->pVars[i]] );
+    return Delay;
+}
+
+// returns delay of the decomposition;  sets area of the cut as its cost
+float If_CutDelayLutStruct( If_Man_t * p, If_Cut_t * pCut, char * pStr, float WireDelay )
+{
+    float Delays[CLU_VAR_MAX+2];
+    int fUsed[CLU_VAR_MAX+2] = {0};
+    If_Obj_t * pLeaf;
+    If_Grp_t G1 = {0}, G2 = {0}, G3 = {0};
+    int nLeaves = If_CutLeaveNum(pCut);
+    int i, nLutLeaf, nLutRoot;
+    // mark the cut as user cut
+//    pCut->fUser = 1;
+    // quit if parameters are wrong
+    if ( strlen(pStr) != 2 )
+    {
+        printf( "Wrong LUT struct (%s)\n", pStr );
+        return ABC_INFINITY;
+    }
+    nLutLeaf = pStr[0] - '0';
+    if ( nLutLeaf < 3 || nLutLeaf > 6 )
+    {
+        printf( "Leaf size (%d) should belong to {3,4,5,6}.\n", nLutLeaf );
+        return ABC_INFINITY;
+    }
+    nLutRoot = pStr[1] - '0';
+    if ( nLutRoot < 3 || nLutRoot > 6 )
+    {
+        printf( "Root size (%d) should belong to {3,4,5,6}.\n", nLutRoot );
+        return ABC_INFINITY;
+    }
+    if ( nLeaves > nLutLeaf + nLutRoot - 1 )
+    {
+        printf( "The cut size (%d) is too large for the LUT structure %d%d.\n", If_CutLeaveNum(pCut), nLutLeaf, nLutRoot );
+        return ABC_INFINITY;
+    }
+
+    // remember the delays
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+        Delays[i] = If_ObjCutBest(pLeaf)->Delay;
+
+    // consider easy case
+    if ( nLeaves <= Abc_MaxInt( nLutLeaf, nLutRoot ) )
+    {
+        char * pPerm = If_CutPerm( pCut );
+        assert( nLeaves <= 6 );
+        for ( i = 0; i < nLeaves; i++ )
+        {
+            pPerm[i] = 1;
+            G1.pVars[i] = i;
+        }
+        G1.nVars = nLeaves;
+        return 1.0 + If_CluDelayMax( &G1, Delays );
+    }
+
+    // derive the first group
+    G1 = If_CluCheck( p, If_CutTruthW(p, pCut), nLeaves, 0, 0, nLutLeaf, nLutRoot, NULL, NULL, NULL, NULL, 1 );
+    if ( G1.nVars == 0 )
+        return ABC_INFINITY;
+
+    // compute the delay
+    Delays[nLeaves] = If_CluDelayMax( &G1, Delays ) + ((WireDelay == 0.0)?1.0:WireDelay);
+    if ( G2.nVars )
+        Delays[nLeaves+1] = If_CluDelayMax( &G2, Delays ) + ((WireDelay == 0.0)?1.0:WireDelay);
+
+    // mark used groups
+    for ( i = 0; i < G1.nVars; i++ )
+        fUsed[(int)G1.pVars[i]] = 1;
+    for ( i = 0; i < G2.nVars; i++ )
+        fUsed[(int)G2.pVars[i]] = 1;
+    // mark unused groups
+    assert( G1.nMyu >= 2 && G1.nMyu <= 4 );
+    if ( G1.nMyu > 2 )
+        fUsed[(int)G1.pVars[G1.nVars-1]] = 0;
+    assert( !G2.nVars || (G2.nMyu >= 2 && G2.nMyu <= 4) );
+    if ( G2.nMyu > 2 )
+        fUsed[(int)G2.pVars[G2.nVars-1]] = 0;
+
+    // create remaining group
+    assert( G3.nVars == 0 );
+    for ( i = 0; i < nLeaves; i++ )
+        if ( !fUsed[i] )
+            G3.pVars[(int)G3.nVars++] = i;
+    G3.pVars[(int)G3.nVars++] = nLeaves;
+    if ( G2.nVars )
+        G3.pVars[(int)G3.nVars++] = nLeaves+1;
+    assert( G1.nVars + G2.nVars + G3.nVars == nLeaves + 
+        (G1.nVars > 0) + (G2.nVars > 0) + (G1.nMyu > 2) + (G2.nMyu > 2) );
+    // what if both non-disjoint vars are the same???
+
+    pCut->Cost = 2 + (G2.nVars > 0);
+    return 1.0 + If_CluDelayMax( &G3, Delays );
+}
+
+//#define IF_TRY_NEW
+
+#ifdef IF_TRY_NEW
+static Vec_Mem_t * s_vTtMem = NULL;
+static Vec_Mem_t * s_vTtMem2 = NULL;
+int If_TtMemCutNum()  { return Vec_MemEntryNum(s_vTtMem); }
+int If_TtMemCutNum2() { return Vec_MemEntryNum(s_vTtMem2); }
+//        printf( "Unique TTs = %d.  Unique classes = %d.    ", If_TtMemCutNum(), If_TtMemCutNum2() );
+//        printf( "Check2 = %d.  Check3 = %d.\n", s_Count2, s_Count3 );
+#endif
+
+/**Function*************************************************************
+
+  Synopsis    [Performs additional check.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutPerformCheck16( If_Man_t * p, unsigned * pTruth0, int nVars, int nLeaves, char * pStr )
+{
+    unsigned pTruth[IF_MAX_FUNC_LUTSIZE > 5 ? 1 << (IF_MAX_FUNC_LUTSIZE - 5) : 1];
+    If_Grp_t G1 = {0};//, G3 = {0};
+    int i, nLutLeaf, nLutLeaf2, nLutRoot, Length;
+    // stretch the truth table
+    assert( nVars >= 6 );
+    memcpy( pTruth, pTruth0, sizeof(word) * Abc_TtWordNum(nVars) );
+    Abc_TtStretch6( (word *)pTruth, nLeaves, p->pPars->nLutSize );
+
+#ifdef IF_TRY_NEW
+    {
+        word pCopy[1024];
+        int nWords = Abc_TruthWordNum(nVars);
+        int iNum;
+        if ( s_vTtMem == NULL )
+        {
+            s_vTtMem = Vec_MemAlloc( Abc_Truth6WordNum(nVars), 12 ); // 32 KB/page for 6-var functions
+            Vec_MemHashAlloc( s_vTtMem, 10000 );
+        }
+        if ( s_vTtMem2 == NULL )
+        {
+            s_vTtMem2 = Vec_MemAlloc( Abc_Truth6WordNum(nVars), 12 ); // 32 KB/page for 6-var functions
+            Vec_MemHashAlloc( s_vTtMem2, 10000 );
+        }
+        memcpy( pCopy, pTruth, sizeof(word) * Abc_Truth6WordNum(nVars) );
+        if ( pCopy[0] & 1 )
+            for ( i = 0; i < nWords; i++ )
+                pCopy[i] = ~pCopy[i];
+        iNum = Vec_MemHashInsert( s_vTtMem, pCopy );
+        if ( iNum == Vec_MemEntryNum(s_vTtMem) - 1 )
+        {
+            int pCanonPerm[16];
+            char pCanonPermC[16];
+            Abc_TtCanonicize( pCopy, nVars, pCanonPermC );
+//            If_CluSemiCanonicize( pCopy, nVars, pCanonPerm );
+            Vec_MemHashInsert( s_vTtMem2, pCopy );
+        }
+    }
+#endif
+
+    // if cutmin is disabled, minimize the function
+    if ( !p->pPars->fCutMin )
+        nLeaves = Abc_TtMinBase( (word *)pTruth, NULL, nLeaves, nVars );
+
+    // quit if parameters are wrong
+    Length = strlen(pStr);
+    if ( Length != 2 && Length != 3 )
+    {
+        printf( "Wrong LUT struct (%s)\n", pStr );
+        return 0;
+    }
+    for ( i = 0; i < Length; i++ )
+        if ( pStr[i] - '0' < 3 || pStr[i] - '0' > 6 )
+        {
+            printf( "The LUT size (%d) should belong to {3,4,5,6}.\n", pStr[i] - '0' );
+            return 0;
+        }
+
+    nLutLeaf  =                   pStr[0] - '0';
+    nLutLeaf2 = ( Length == 3 ) ? pStr[1] - '0' : 0;
+    nLutRoot  =                   pStr[Length-1] - '0';
+    if ( nLeaves > nLutLeaf - 1 + (nLutLeaf2 ? nLutLeaf2 - 1 : 0) + nLutRoot )
+    {
+        printf( "The cut size (%d) is too large for the LUT structure %s.\n", nLeaves, pStr );
+        return 0;
+    }
+    // consider easy case
+    if ( nLeaves <= Abc_MaxInt( nLutLeaf2, Abc_MaxInt(nLutLeaf, nLutRoot) ) )
+        return 1;
+
+    // derive the first group
+    if ( Length == 2 )
+        G1 = If_CluCheck( p, (word *)pTruth, nLeaves, 0, 0, nLutLeaf, nLutRoot, NULL, NULL, NULL, NULL, 1 );
+    else
+        G1 = If_CluCheck3( p, (word *)pTruth, nLeaves, nLutLeaf, nLutLeaf2, nLutRoot, NULL, NULL, NULL, NULL, NULL );
+
+//    if ( G1.nVars > 0 )
+//        If_CluPrintGroup( &G1 );
+
+    return (int)(G1.nVars > 0);
+}
+
+
+// testing procedure
+void If_CluTest()
+{
+//    word t = 0xff00f0f0ccccaaaa;
+//    word t = 0xfedcba9876543210;
+//    word t = 0xec64000000000000;
+//    word t = 0x0100200000000001;
+//    word t2[4] = { 0x0000800080008000, 0x8000000000008000, 0x8000000080008000, 0x0000000080008000 };
+//    word t = 0x07770FFF07770FFF;
+//    word t = 0x002000D000D00020;
+//    word t = 0x000F000E000F000F;
+//    word t = 0xF7FFF7F7F7F7F7F7;
+//    word t = 0x0234AFDE23400BCE;
+//    word t = 0x0080008880A088FF;
+//    word s = t;
+//    word t = 0xFFBBBBFFF0B0B0F0;
+    word t = ABC_CONST(0x6DD9926D962D6996);
+    int nVars     = 6;
+    int nLutLeaf  = 4;
+    int nLutLeaf2 = 4;
+    int nLutRoot  = 4;
+/*
+    word t2[2] = { 0x7f807f807f80807f, 0x7f807f807f807f80 };
+    int nVars     = 7;
+    int nLutLeaf  = 3;
+    int nLutLeaf2 = 3;
+    int nLutRoot  = 3;
+*/
+
+    If_Grp_t G;
+    If_Grp_t G2, R;
+    word Func0, Func1, Func2;
+
+
+    return;
+
+/*
+    int pCanonPerm[CLU_VAR_MAX];
+    int uCanonPhase;
+
+    Kit_DsdPrintFromTruth( (unsigned*)&s, nVars ); printf( "\n" );
+    uCanonPhase = If_CluSemiCanonicize( &s, nVars, pCanonPerm );
+    Kit_DsdPrintFromTruth( (unsigned*)&s, nVars ); printf( "\n" );
+
+    If_CluSemiCanonicizeVerify( &s, &t, nVars, pCanonPerm, uCanonPhase );
+*/
+
+    Kit_DsdPrintFromTruth( (unsigned*)&t, nVars ); printf( "\n" );
+    G = If_CluCheck3( NULL, &t, nVars, nLutLeaf, nLutLeaf2, nLutRoot, &R, &G2, &Func0, &Func1, &Func2 );
+    If_CluPrintGroup( &G );
+    If_CluPrintGroup( &G2 );
+    If_CluPrintGroup( &R );
+
+//    If_CluVerify3( &t, nVars, &G, &G2, &R, Func1, Func2, Func0 );
+
+    return;
+
+//    If_CutPerformCheck07( NULL, (unsigned *)&t, 6, 6, NULL );
+//    return;
+
+//    Kit_DsdPrintFromTruth( (unsigned*)&t, nVars ); printf( "\n" );
+//    G = If_CluCheck( NULL, &t, nVars, 0, nLutLeaf, nLutRoot, NULL, NULL, NULL, NULL, 0 );
+//    If_CluPrintGroup( &G );
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifDec75.c b/abc-build/src/map/if/ifDec75.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifDec75.c
@@ -0,0 +1,341 @@
+/**CFile****************************************************************
+
+  FileName    [ifDec75.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Performs additional check.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifDec75.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+#include "misc/extra/extra.h"
+#include "bool/kit/kit.h"
+#include "opt/dau/dau.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Finds all boundsets for which decomposition exists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dau_DsdCheckDecExist_rec( char * pStr, char ** p, int * pMatches, int * pnSupp )
+{
+    if ( **p == '!' )
+        (*p)++;
+    while ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') )
+        (*p)++;
+    if ( **p >= 'a' && **p <= 'z' ) // var
+    {
+        (*pnSupp)++;
+        return 0;
+    }
+    if ( **p == '(' || **p == '[' ) // and/xor
+    {
+        unsigned Mask = 0;
+        int m, pSupps[8] = {0}, nParts = 0, nMints;
+        char * q = pStr + pMatches[ *p - pStr ];
+        assert( *q == **p + 1 + (**p != '(') );
+        for ( (*p)++; *p < q; (*p)++ )
+        {
+            Mask |= Dau_DsdCheckDecExist_rec( pStr, p, pMatches, &pSupps[nParts] );
+            *pnSupp += pSupps[nParts++];
+        }
+        assert( *p == q );
+        assert( nParts > 1 );
+        nMints = (1 << nParts);
+        for ( m = 1; m < nMints; m++ )
+        {
+            int i, Sum = 0;
+            for ( i = 0; i < nParts; i++ )
+                if ( (m >> i) & 1 )
+                    Sum += pSupps[i];
+            assert( Sum > 0 && Sum <= 8 );
+            if ( Sum >= 2 )
+                Mask |= (1 << Sum);
+        }
+        return Mask;
+    }
+    if ( **p == '<' || **p == '{' ) // mux
+    {
+        int uSupp;
+        unsigned Mask = 0;
+        char * q = pStr + pMatches[ *p - pStr ];
+        assert( *q == **p + 1 + (**p != '(') );
+        for ( (*p)++; *p < q; (*p)++ )
+        {
+            uSupp = 0;
+            Mask |= Dau_DsdCheckDecExist_rec( pStr, p, pMatches, &uSupp );
+            *pnSupp += uSupp;
+        }
+        assert( *p == q );
+        Mask |= (1 << *pnSupp);
+        return Mask;
+    }
+    assert( 0 );
+    return 0;
+}
+int Dau_DsdCheckDecExist( char * pDsd )
+{
+    int nSupp = 0;
+    if ( pDsd[1] == 0 )
+        return 0;
+    return Dau_DsdCheckDecExist_rec( pDsd, &pDsd, Dau_DsdComputeMatches(pDsd), &nSupp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds all boundsets for which AND-decomposition exists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dau_DsdCheckDecAndExist_rec( char * pStr, char ** p, int * pMatches, int * pnSupp )
+{
+    if ( **p == '!' )
+        (*p)++;
+    while ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') )
+        (*p)++;
+    if ( **p >= 'a' && **p <= 'z' ) // var
+    {
+        (*pnSupp)++;
+        return 0;
+    }
+    if ( **p == '(' ) // and
+    {
+        unsigned Mask = 0;
+        int m, i, pSupps[8] = {0}, nParts = 0, nSimple = 0, nMints;
+        char * q = pStr + pMatches[ *p - pStr ];
+        assert( *q == **p + 1 + (**p != '(') );
+        for ( (*p)++; *p < q; (*p)++ )
+        {
+            Mask |= Dau_DsdCheckDecAndExist_rec( pStr, p, pMatches, &pSupps[nParts] );
+            nSimple += (pSupps[nParts] == 1);
+            *pnSupp += pSupps[nParts++];
+        }
+        assert( *p == q );
+        assert( nParts > 1 );
+        if ( nSimple > 0 )
+        {
+            nMints = (1 << nParts);
+            for ( m = 1; m < nMints; m++ )
+            {
+                int Sum = 0;
+                for ( i = 0; i < nParts; i++ )
+                    if ( pSupps[i] > 1 && ((m >> i) & 1) )
+                        Sum += pSupps[i];
+                assert( Sum <= 8 );
+                if ( Sum >= 2 )
+                    for ( i = 0; i < nSimple; i++ )
+                        Mask |= (1 << (Sum + i));
+            }
+            for ( i = 2; i < nSimple; i++ )
+                Mask |= (1 << i);
+        }
+        return Mask;
+    }
+    if ( **p == '<' || **p == '{' || **p == '[' ) // mux/xor/nondec
+    {
+        int uSupp;
+        unsigned Mask = 0;
+        char * q = pStr + pMatches[ *p - pStr ];
+        assert( *q == **p + 1 + (**p != '(') );
+        for ( (*p)++; *p < q; (*p)++ )
+        {
+            uSupp = 0;
+            Mask |= Dau_DsdCheckDecAndExist_rec( pStr, p, pMatches, &uSupp );
+            *pnSupp += uSupp;
+        }
+        assert( *p == q );
+        return Mask;
+    }
+    assert( 0 );
+    return 0;
+}
+int Dau_DsdCheckDecAndExist( char * pDsd )
+{
+    int nSupp = 0;
+    if ( pDsd[1] == 0 )
+        return 1;
+    return Dau_DsdCheckDecAndExist_rec( pDsd, &pDsd, Dau_DsdComputeMatches(pDsd), &nSupp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs additional check.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutPerformCheck75__( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr )
+{
+    char pDsdStr[1000];
+    int nSizeNonDec, nDecExists, nDecAndExists;
+    static int Counter = 0;
+    Counter++;
+    if ( nLeaves < 6 )
+        return 1;
+    assert( nLeaves <= 8 );
+    if ( nLeaves < 8 && If_CutPerformCheck16( p, pTruth, nVars, nLeaves, "44" ) )
+        return 1;
+    // check decomposability
+    nSizeNonDec = Dau_DsdDecompose( (word *)pTruth, nLeaves, 0, 0, pDsdStr );
+//    printf( "Vars = %d  %s", nLeaves, pDsdStr );    printf( "\n" );
+//    Extra_PrintBinary( stdout, &nDecExists, 8 );    printf( "\n" );
+//    Extra_PrintBinary( stdout, &nDecAndExists, 8 ); printf( "\n" );
+    if ( nLeaves == 8 )
+    {
+        if ( nSizeNonDec >= 5 )
+            return 0;
+        nDecAndExists = Dau_DsdCheckDecAndExist( pDsdStr );
+        if ( nDecAndExists & 0x10 ) // bit 4
+            return 1;
+        else
+            return 0;
+    }
+    if ( nLeaves == 7 )
+    {
+        extern void If_Dec7MinimumBase( word uTruth[2], int * pSupp, int nVarsAll, int * pnVars );
+        word * pT = (word *)pTruth;
+        word pCof0[2], pCof1[2];
+        int v, nVarsMin;
+        if ( nSizeNonDec < 5 )
+        {
+            nDecExists = Dau_DsdCheckDecExist( pDsdStr );
+            if ( nDecExists & 0x10 ) // bit 4
+                return 1;
+            nDecAndExists = Dau_DsdCheckDecAndExist( pDsdStr );
+            if ( nDecAndExists & 0x18 ) // bit 4, 3
+                return 1;
+        }
+        // check cofactors
+        for ( v = 0; v < 7; v++ )
+        {
+            pCof0[0] = pCof1[0] = pT[0];
+            pCof0[1] = pCof1[1] = pT[1];
+            Abc_TtCofactor0( pCof0, 2, v );
+            Abc_TtCofactor1( pCof1, 2, v );
+            if ( Abc_TtSupportSize(pCof0, 7) < 4 )
+            {
+                If_Dec7MinimumBase( pCof1, NULL, 7, &nVarsMin );
+                nSizeNonDec = Dau_DsdDecompose( pCof1, nVarsMin, 0, 0, pDsdStr );
+                if ( nSizeNonDec >= 5 )
+                    continue;
+                nDecExists = Dau_DsdCheckDecExist( pDsdStr );
+                if ( nDecExists & 0x18 ) // bit 4, 3
+                    return 1;
+            }
+            else if ( Abc_TtSupportSize(pCof1, 7) < 4 )
+            {
+                If_Dec7MinimumBase( pCof0, NULL, 7, &nVarsMin );
+                nSizeNonDec = Dau_DsdDecompose( pCof0, nVarsMin, 0, 0, pDsdStr );
+                if ( nSizeNonDec >= 5 )
+                    continue;
+                nDecExists = Dau_DsdCheckDecExist( pDsdStr );
+                if ( nDecExists & 0x18 ) // bit 4, 3
+                    return 1;
+            }
+        }
+        return 0;
+    }
+    if ( nLeaves == 6 )
+    {
+        if ( nSizeNonDec < 5 )
+        {
+            nDecExists = Dau_DsdCheckDecExist( pDsdStr );
+            if ( nDecExists & 0x18 ) // bit 4, 3
+                return 1;
+            nDecAndExists = Dau_DsdCheckDecAndExist( pDsdStr );
+            if ( nDecAndExists & 0x1C ) // bit 4, 3, 2
+                return 1;
+        }
+        return If_CutPerformCheck07( p, pTruth, nVars, nLeaves, pStr );
+    }
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs additional check.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutPerformCheck75( If_Man_t * p, unsigned * pTruth0, int nVars, int nLeaves, char * pStr )
+{
+    word * pTruthW = (word *)pTruth0;
+    word pTruth[4] = { pTruthW[0], pTruthW[1], pTruthW[2], pTruthW[3] };
+    assert( nLeaves <= 8 );
+    if ( !p->pPars->fCutMin )
+        Abc_TtMinimumBase( pTruth, NULL, nLeaves, &nLeaves );
+    if ( nLeaves < 6 )
+        return 1;
+//    if ( nLeaves < 8 && If_CutPerformCheck07( p, (unsigned *)pTruth, nVars, nLeaves, "44" ) )
+    if ( nLeaves < 8 && If_CutPerformCheck16( p, (unsigned *)pTruth, nVars, nLeaves, "44" ) )
+        return 1;
+    // this is faster but not compatible with -z
+    if ( !p->pPars->fDeriveLuts && p->pPars->fEnableCheck75 && nLeaves == 8 )
+    {
+//        char pDsdStr[1000] = "(!(abd)!(c!([fe][gh])))";
+        char pDsdStr[1000];
+        int nSizeNonDec = Dau_DsdDecompose( (word *)pTruth, nLeaves, 0, 0, pDsdStr );
+        if ( nSizeNonDec >= 5 )
+            return 0;
+        if ( Dau_DsdCheckDecAndExist(pDsdStr) & 0x10 ) // bit 4
+            return 1;
+        return 0;
+    }
+    if ( If_CutPerformCheck45( p, (unsigned *)pTruth, nVars, nLeaves, pStr ) )
+        return 1;
+    if ( If_CutPerformCheck54( p, (unsigned *)pTruth, nVars, nLeaves, pStr ) )
+        return 1;
+    return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifDelay.c b/abc-build/src/map/if/ifDelay.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifDelay.c
@@ -0,0 +1,417 @@
+/**CFile****************************************************************
+
+  FileName    [ifDelay.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Delay balancing for cut functions.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifDelay.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+#include "ifCount.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define IF_MAX_CUBES 70
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    [Computes the SOP delay using balanced AND decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int If_CutMaxCubeSize( Vec_Int_t * vCover, int nVars )
+{
+    int i, k, Entry, Literal, Count, CountMax = 0;
+    Vec_IntForEachEntry( vCover, Entry, i )
+    {
+        Count = 0;
+        for ( k = 0; k < nVars; k++ )
+        {
+            Literal = (3 & (Entry >> (k << 1)));
+            if ( Literal == 1 || Literal == 2 )
+                Count++;
+        }
+        CountMax = Abc_MaxInt( CountMax, Count );
+    }
+    return CountMax;
+}
+int If_CutDelaySop( If_Man_t * p, If_Cut_t * pCut )
+{
+    char * pPerm = If_CutPerm( pCut );
+    // delay is calculated using 1+log2(NumFanins)
+    static double GateDelays[20] = { 1.00, 1.00, 2.00, 2.58, 3.00, 3.32, 3.58, 3.81, 4.00, 4.17, 4.32, 4.46, 4.58, 4.70, 4.81, 4.91, 5.00, 5.09, 5.17, 5.25 };
+    Vec_Int_t * vCover;
+    If_Obj_t * pLeaf;
+    int i, nLitMax, Delay, DelayMax;
+    // mark cut as a user cut
+    pCut->fUser = 1;
+    if ( pCut->nLeaves == 0 )
+        return 0;
+    if ( pCut->nLeaves == 1 )
+        return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay;
+    vCover = Vec_WecEntry( p->vTtIsops[pCut->nLeaves], Abc_Lit2Var(If_CutTruthLit(pCut)) );
+    if ( Vec_IntSize(vCover) == 0 )
+        return -1;
+    // mark the output as complemented
+//    vAnds = If_CutDelaySopAnds( p, pCut, vCover, RetValue ^ pCut->fCompl );
+    if ( Vec_IntSize(vCover) > p->pPars->nGateSize )
+        return -1;
+    // set the area cost
+    assert( If_CutLeaveNum(pCut) >= 0 && If_CutLeaveNum(pCut) <= 16 );
+    // compute the gate delay
+    nLitMax = If_CutMaxCubeSize( vCover, If_CutLeaveNum(pCut) );
+    if ( Vec_IntSize(vCover) < 2 )
+    {
+        pCut->Cost = Vec_IntSize(vCover);
+        Delay = (int)(GateDelays[If_CutLeaveNum(pCut)] + 0.5);
+        DelayMax = 0;
+        If_CutForEachLeaf( p, pCut, pLeaf, i )
+            DelayMax = Abc_MaxInt( DelayMax, If_ObjCutBest(pLeaf)->Delay + (pPerm[i] = (char)Delay) );
+    }
+    else
+    {
+        pCut->Cost = Vec_IntSize(vCover) + 1;
+        Delay = (int)(GateDelays[If_CutLeaveNum(pCut)] + GateDelays[nLitMax] + 0.5);
+        DelayMax = 0;
+        If_CutForEachLeaf( p, pCut, pLeaf, i )
+            DelayMax = Abc_MaxInt( DelayMax, If_ObjCutBest(pLeaf)->Delay + (pPerm[i] = (char)Delay) );
+    }
+    return DelayMax;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compute pin delays.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutSopBalancePinDelaysInt( Vec_Int_t * vCover, int * pTimes, word * pFaninRes, int nSuppAll, word * pRes )
+{
+    word pPinDelsAnd[IF_MAX_FUNC_LUTSIZE], pPinDelsOr[IF_MAX_CUBES];
+    int nCounterAnd, pCounterAnd[IF_MAX_FUNC_LUTSIZE];
+    int nCounterOr,  pCounterOr[IF_MAX_CUBES];
+    int i, k, Entry, Literal, Delay = 0;
+    word ResAnd;
+    if ( Vec_IntSize(vCover) > IF_MAX_CUBES )
+        return -1;
+    nCounterOr = 0;
+    Vec_IntForEachEntry( vCover, Entry, i )
+    { 
+        nCounterAnd = 0;
+        for ( k = 0; k < nSuppAll; k++ )
+        {
+            Literal = 3 & (Entry >> (k << 1));
+            if ( Literal == 1 || Literal == 2 ) // neg or pos literal
+                Delay = If_LogCounterPinDelays( pCounterAnd, &nCounterAnd, pPinDelsAnd, pTimes[k], pFaninRes[k], nSuppAll, 0 );
+            else if ( Literal != 0 ) 
+                assert( 0 );
+        }
+        assert( nCounterAnd > 0 );
+        ResAnd = If_LogPinDelaysMulti( pPinDelsAnd, nCounterAnd, nSuppAll, 0 );
+        Delay = If_LogCounterPinDelays( pCounterOr, &nCounterOr, pPinDelsOr, Delay, ResAnd, nSuppAll, 0 );
+    }
+    assert( nCounterOr > 0 );
+    *pRes = If_LogPinDelaysMulti( pPinDelsOr, nCounterOr, nSuppAll, 0 );
+    return Delay;
+}
+int If_CutSopBalancePinDelaysIntInt( Vec_Int_t * vCover, int * pTimes, int nSuppAll, char * pPerm )
+{
+    int i, Delay;
+    word Res, FaninRes[IF_MAX_FUNC_LUTSIZE];
+    for ( i = 0; i < nSuppAll; i++ )
+        FaninRes[i] = If_CutPinDelayInit(i);
+    Delay = If_CutSopBalancePinDelaysInt( vCover, pTimes, FaninRes, nSuppAll, &Res );
+    If_CutPinDelayTranslate( Res, nSuppAll, pPerm );
+    return Delay;
+}
+int If_CutSopBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm )
+{
+    if ( pCut->nLeaves == 0 ) // const
+        return 0;
+    if ( pCut->nLeaves == 1 ) // variable
+    {
+        pPerm[0] = 0;
+        return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay;
+    }
+    else
+    {
+        Vec_Int_t * vCover;
+        int i, pTimes[IF_MAX_FUNC_LUTSIZE];
+        vCover = Vec_WecEntry( p->vTtIsops[pCut->nLeaves], Abc_Lit2Var(If_CutTruthLit(pCut)) );
+        if ( Vec_IntSize(vCover) == 0 )
+            return -1;
+        for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+            pTimes[i] = (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; 
+        return If_CutSopBalancePinDelaysIntInt( vCover, pTimes, If_CutLeaveNum(pCut), pPerm );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluate delay using SOP balancing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutSopBalanceEvalInt( Vec_Int_t * vCover, int * pTimes, int * pFaninLits, Vec_Int_t * vAig, int * piRes, int nSuppAll, int * pArea )
+{
+    int nCounterAnd, pCounterAnd[IF_MAX_FUNC_LUTSIZE], pFaninLitsAnd[IF_MAX_FUNC_LUTSIZE];
+    int nCounterOr,  pCounterOr[IF_MAX_CUBES],  pFaninLitsOr[IF_MAX_CUBES];
+    int i, k, Entry, Literal, nLits, Delay = 0, iRes = 0;
+    if ( Vec_IntSize(vCover) > IF_MAX_CUBES )
+        return -1;
+    nCounterOr = 0;
+    Vec_IntForEachEntry( vCover, Entry, i )
+    { 
+        nCounterAnd = nLits = 0;
+        for ( k = 0; k < nSuppAll; k++ )
+        {
+            Literal = 3 & (Entry >> (k << 1));
+            if ( Literal == 1 ) // neg literal
+                nLits++, Delay = If_LogCounterAddAig( pCounterAnd, &nCounterAnd, pFaninLitsAnd, pTimes[k], Abc_LitNot(pFaninLits[k]), vAig, nSuppAll, 0 );
+            else if ( Literal == 2 ) // pos literal
+                nLits++, Delay = If_LogCounterAddAig( pCounterAnd, &nCounterAnd, pFaninLitsAnd, pTimes[k], pFaninLits[k], vAig, nSuppAll, 0 );
+            else if ( Literal != 0 ) 
+                assert( 0 );
+        }
+        assert( nCounterAnd > 0 );
+        assert( nLits > 0 );
+        if ( vAig )
+            iRes = If_LogCreateAndXorMulti( vAig, pFaninLitsAnd, nCounterAnd, nSuppAll, 0 );
+        else
+            *pArea += nLits == 1 ? 0 : nLits - 1;
+        Delay = If_LogCounterAddAig( pCounterOr, &nCounterOr, pFaninLitsOr, Delay, Abc_LitNot(iRes), vAig, nSuppAll, 0 );
+    }
+    assert( nCounterOr > 0 );
+    if ( vAig )
+    {
+        *piRes = Abc_LitNot( If_LogCreateAndXorMulti( vAig, pFaninLitsOr, nCounterOr, nSuppAll, 0 ) );
+        if ( ((vCover->nCap >> 16) & 1) )  // hack to remember complemented attribute
+            *piRes = Abc_LitNot( *piRes );
+    }
+    else       
+        *pArea += Vec_IntSize(vCover) == 1 ? 0 : Vec_IntSize(vCover) - 1;
+    return Delay;
+}
+int If_CutSopBalanceEvalIntInt( Vec_Int_t * vCover, int nLeaves, int * pTimes, Vec_Int_t * vAig, int fCompl, int * pArea ) 
+{
+    int pFaninLits[IF_MAX_FUNC_LUTSIZE];
+    int iRes = 0, Res, k;
+    if ( vAig )
+        for ( k = 0; k < nLeaves; k++ )
+            pFaninLits[k] = Abc_Var2Lit(k, 0);
+    Res = If_CutSopBalanceEvalInt( vCover, pTimes, pFaninLits, vAig, &iRes, nLeaves, pArea );
+    if ( Res == -1 )
+        return -1;
+    assert( vAig == NULL || Abc_Lit2Var(iRes) == nLeaves + Abc_Lit2Var(Vec_IntSize(vAig)) - 1 );
+    if ( vAig )
+        Vec_IntPush( vAig, Abc_LitIsCompl(iRes) ^ fCompl );
+    assert( vAig == NULL || (Vec_IntSize(vAig) & 1) );
+    return Res;
+}
+int If_CutSopBalanceEval( If_Man_t * p, If_Cut_t * pCut, Vec_Int_t * vAig )
+{
+    pCut->fUser = 1;
+    if ( vAig )
+        Vec_IntClear( vAig );
+    if ( pCut->nLeaves == 0 ) // const
+    {
+        assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 );
+        if ( vAig )
+            Vec_IntPush( vAig, Abc_LitIsCompl(If_CutTruthLit(pCut)) );
+        pCut->Cost = 0;
+        return 0;
+    }
+    if ( pCut->nLeaves == 1 ) // variable
+    {
+        assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 1 );
+        if ( vAig )
+            Vec_IntPush( vAig, 0 );
+        if ( vAig )
+            Vec_IntPush( vAig, Abc_LitIsCompl(If_CutTruthLit(pCut)) );
+        pCut->Cost = 0;
+        return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay;
+    }
+    else
+    {
+        Vec_Int_t * vCover = Vec_WecEntry( p->vTtIsops[pCut->nLeaves], Abc_Lit2Var(If_CutTruthLit(pCut)) );
+        int Delay, Area = 0;
+        int i, pTimes[IF_MAX_FUNC_LUTSIZE];
+        if ( vCover == NULL )
+            return -1;
+        assert( Vec_IntSize(vCover) > 0 );
+        for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+            pTimes[i] = (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; 
+        Delay = If_CutSopBalanceEvalIntInt( vCover, If_CutLeaveNum(pCut), pTimes, vAig, Abc_LitIsCompl(If_CutTruthLit(pCut)) ^ pCut->fCompl, &Area );
+        pCut->Cost = Area;
+        return Delay;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluate delay using SOP balancing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutLutBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm )
+{
+    if ( pCut->nLeaves == 0 ) // const
+        return 0;
+    if ( pCut->nLeaves == 1 ) // variable
+    {
+        pPerm[0] = 0;
+        return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay;
+    }
+    else
+    {
+        char * pCutPerm = If_CutDsdPerm( p, pCut );
+        int LutSize = p->pPars->pLutStruct[0] - '0';
+        int i, Delay, DelayMax = -1;
+        assert( (If_CutLeaveNum(pCut) > LutSize) == (pCut->uMaskFunc > 0) );
+        for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+        {
+            if ( If_CutLeaveNum(pCut) > LutSize && ((pCut->uMaskFunc >> (i << 1)) & 1) )
+                pPerm[Abc_Lit2Var((int)pCutPerm[i])] = 2;
+            else
+                pPerm[Abc_Lit2Var((int)pCutPerm[i])] = 1;
+        }
+        for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+        {
+            Delay = (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay;
+            DelayMax = Abc_MaxInt( DelayMax, Delay + (int)pPerm[i] );
+        }
+        return DelayMax;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluate delay using SOP balancing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut )
+{
+    pCut->fUser = 1;
+    pCut->Cost = pCut->nLeaves > 1 ? 1 : 0;
+    pCut->uMaskFunc = 0;
+    if ( pCut->nLeaves == 0 ) // const
+    {
+        assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 );
+        return 0;
+    }
+    if ( pCut->nLeaves == 1 ) // variable
+    {
+        assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 1 );
+        return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay;
+    }
+    else
+    {
+        char * pCutPerm = If_CutDsdPerm( p, pCut );
+        int LutSize = p->pPars->pLutStruct[0] - '0';
+        int i, pTimes[IF_MAX_FUNC_LUTSIZE];
+        int DelayMax = -1, nLeafMax = 0;
+        unsigned uLeafMask = 0;
+        for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+        {
+            pTimes[i] = (int)If_ObjCutBest(If_CutLeaf(p, pCut, Abc_Lit2Var((int)pCutPerm[i])))->Delay; 
+            if ( DelayMax < pTimes[i] )
+                DelayMax = pTimes[i], nLeafMax = 1, uLeafMask = (1 << (i << 1));
+            else if ( DelayMax == pTimes[i] )
+                nLeafMax++, uLeafMask |= (1 << (i << 1));
+        }
+        if ( If_CutLeaveNum(pCut) <= LutSize )
+            return DelayMax + 1;
+        pCut->Cost = 2;
+        if ( nLeafMax <= LutSize - 1 )
+        {
+            pCut->uMaskFunc = If_DsdManCheckXY( p->pIfDsdMan, If_CutDsdLit(p, pCut), LutSize, 1, uLeafMask, 0, 0 );
+            if ( pCut->uMaskFunc > 0 )
+                return DelayMax + 1;
+        }
+        pCut->uMaskFunc = If_DsdManCheckXY( p->pIfDsdMan, If_CutDsdLit(p, pCut), LutSize, 1, 0, 0, 0 );
+        if ( pCut->uMaskFunc == 0 )
+            return -1;
+        return DelayMax + 2;
+    }
+}
+/*
+int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut )
+{
+    char pPerm[16];
+    int Delay2, Delay = If_CutLutBalanceEvalInt( p, pCut );
+    if ( Delay == -1 )
+        return -1;
+    Delay2 = If_CutLutBalancePinDelays( p, pCut, pPerm );
+    if ( Delay2 != Delay )
+    {
+        int s = 0;
+        char * pCutPerm = If_CutDsdPerm( p, pCut );
+        If_DsdManPrintNode( p->pIfDsdMan, If_CutDsdLit(p, pCut) );        Dau_DecPrintSet( pCut->uMaskFunc, pCut->nLeaves, 1 );
+        Kit_DsdPrintFromTruth( If_CutTruthUR(p, pCut), pCut->nLeaves ); printf( "\n" );
+        for ( s = 0; s < pCut->nLeaves; s++ )
+//            printf( "%d ", (int)If_ObjCutBest(If_CutLeaf(p, pCut, Abc_Lit2Var((int)pCutPerm[s])))->Delay );
+            printf( "%d ", (int)If_ObjCutBest(If_CutLeaf(p, pCut, s))->Delay );
+        printf( "\n" );
+
+        Delay  = If_CutLutBalanceEvalInt( p, pCut );
+        Delay2 = If_CutLutBalancePinDelays( p, pCut, pPerm );
+    }
+
+    return Delay;
+}
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifDsd.c b/abc-build/src/map/if/ifDsd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifDsd.c
@@ -0,0 +1,2172 @@
+/**CFile****************************************************************
+
+  FileName    [ifDsd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Computation of DSD representation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifTruth.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <math.h>
+#include "if.h"
+#include "ifCount.h"
+#include "misc/extra/extra.h"
+#include "sat/bsat/satSolver.h"
+#include "aig/gia/gia.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// network types
+typedef enum { 
+    IF_DSD_NONE = 0,               // 0:  unknown
+    IF_DSD_CONST0,                 // 1:  constant
+    IF_DSD_VAR,                    // 2:  variable
+    IF_DSD_AND,                    // 3:  AND
+    IF_DSD_XOR,                    // 4:  XOR
+    IF_DSD_MUX,                    // 5:  MUX
+    IF_DSD_PRIME                   // 6:  PRIME
+} If_DsdType_t;
+
+typedef struct If_DsdObj_t_ If_DsdObj_t;
+struct If_DsdObj_t_
+{
+    unsigned       Id;             // node ID
+    unsigned       Type    :  3;   // node type
+    unsigned       nSupp   :  5;   // variable
+    unsigned       fMark   :  1;   // user mark
+    unsigned       Count   : 18;   // variable
+    unsigned       nFans   :  5;   // fanin count
+    unsigned       pFans[0];       // fanins
+};
+
+struct If_DsdMan_t_
+{
+    char *         pStore;         // input/output file
+    int            nVars;          // max var number
+    int            LutSize;        // LUT size
+    int            nWords;         // word number
+    int            nBins;          // table size
+    unsigned *     pBins;          // hash table
+    Mem_Flex_t *   pMem;           // memory for nodes
+    Vec_Ptr_t      vObjs;          // objects
+    Vec_Int_t      vNexts;         // next pointers
+    Vec_Int_t      vTruths;        // truth IDs of prime nodes
+    Vec_Int_t *    vTemp1;         // temp
+    Vec_Int_t *    vTemp2;         // temp
+    word **        pTtElems;       // elementary TTs
+    Vec_Mem_t *    vTtMem[IF_MAX_FUNC_LUTSIZE+1];  // truth table memory and hash table
+    Vec_Ptr_t *    vTtDecs[IF_MAX_FUNC_LUTSIZE+1]; // truth table decompositions
+    Vec_Wec_t *    vIsops[IF_MAX_FUNC_LUTSIZE+1];  // ISOP for each function
+    int *          pSched[IF_MAX_FUNC_LUTSIZE];    // grey code schedules
+    Gia_Man_t *    pTtGia;         // GIA to represent truth tables
+    Vec_Int_t *    vCover;         // temporary memory
+    void *         pSat;           // SAT solver
+    int            nUniqueHits;    // statistics
+    int            nUniqueMisses;  // statistics
+    abctime        timeDsd;        // statistics
+    abctime        timeCanon;      // statistics
+    abctime        timeCheck;      // statistics
+    abctime        timeCheck2;     // statistics
+    abctime        timeVerify;     // statistics
+};
+
+static inline int           If_DsdObjWordNum( int nFans )                                    { return sizeof(If_DsdObj_t) / 8 + nFans / 2 + ((nFans & 1) > 0);              }
+static inline int           If_DsdObjTruthId( If_DsdMan_t * p, If_DsdObj_t * pObj )          { return (pObj->Type == IF_DSD_PRIME && pObj->nFans > 2) ? Vec_IntEntry(&p->vTruths, pObj->Id) : -1;     }
+static inline word *        If_DsdObjTruth( If_DsdMan_t * p, If_DsdObj_t * pObj )            { return Vec_MemReadEntry(p->vTtMem[pObj->nFans], If_DsdObjTruthId(p, pObj));  }
+static inline void          If_DsdObjSetTruth( If_DsdMan_t * p, If_DsdObj_t * pObj, int Id ) { assert( pObj->Type == IF_DSD_PRIME && pObj->nFans > 2 ); Vec_IntWriteEntry(&p->vTruths, pObj->Id, Id); }
+
+static inline void          If_DsdObjClean( If_DsdObj_t * pObj )                       { memset( pObj, 0, sizeof(If_DsdObj_t) );                                            }
+static inline int           If_DsdObjId( If_DsdObj_t * pObj )                          { return pObj->Id;                                                                   }
+static inline int           If_DsdObjType( If_DsdObj_t * pObj )                        { return pObj->Type;                                                                 }
+static inline int           If_DsdObjIsVar( If_DsdObj_t * pObj )                       { return (int)(pObj->Type == IF_DSD_VAR);                                            }
+static inline int           If_DsdObjSuppSize( If_DsdObj_t * pObj )                    { return pObj->nSupp;                                                                }
+static inline int           If_DsdObjFaninNum( If_DsdObj_t * pObj )                    { return pObj->nFans;                                                                }
+static inline int           If_DsdObjFaninC( If_DsdObj_t * pObj, int i )               { assert(i < (int)pObj->nFans); return Abc_LitIsCompl(pObj->pFans[i]);               }
+static inline int           If_DsdObjFaninLit( If_DsdObj_t * pObj, int i )             { assert(i < (int)pObj->nFans); return pObj->pFans[i];                               }
+
+static inline If_DsdObj_t * If_DsdVecObj( Vec_Ptr_t * p, int Id )                      { return (If_DsdObj_t *)Vec_PtrEntry(p, Id);                                         }
+static inline If_DsdObj_t * If_DsdVecConst0( Vec_Ptr_t * p )                           { return If_DsdVecObj( p, 0 );                                                       }
+static inline If_DsdObj_t * If_DsdVecVar( Vec_Ptr_t * p, int v )                       { return If_DsdVecObj( p, v+1 );                                                     }
+static inline int           If_DsdVecObjSuppSize( Vec_Ptr_t * p, int iObj )            { return If_DsdVecObj( p, iObj )->nSupp;                                             }
+static inline int           If_DsdVecLitSuppSize( Vec_Ptr_t * p, int iLit )            { return If_DsdVecObjSuppSize( p, Abc_Lit2Var(iLit) );                               }
+static inline int           If_DsdVecObjRef( Vec_Ptr_t * p, int iObj )                 { return If_DsdVecObj( p, iObj )->Count;                                             }
+static inline void          If_DsdVecObjIncRef( Vec_Ptr_t * p, int iObj )              { if ( If_DsdVecObjRef(p, iObj) < 0x3FFFF ) If_DsdVecObj( p, iObj )->Count++;        }
+static inline If_DsdObj_t * If_DsdObjFanin( Vec_Ptr_t * p, If_DsdObj_t * pObj, int i ) { assert(i < (int)pObj->nFans); return If_DsdVecObj(p, Abc_Lit2Var(pObj->pFans[i])); }
+static inline int           If_DsdVecObjMark( Vec_Ptr_t * p, int iObj )                { return If_DsdVecObj( p, iObj )->fMark;                                             }
+static inline void          If_DsdVecObjSetMark( Vec_Ptr_t * p, int iObj )             { If_DsdVecObj( p, iObj )->fMark = 1;                                                }
+static inline void          If_DsdVecObjClearMark( Vec_Ptr_t * p, int iObj )           { If_DsdVecObj( p, iObj )->fMark = 0;                                                }
+
+#define If_DsdVecForEachObj( vVec, pObj, i )                \
+    Vec_PtrForEachEntry( If_DsdObj_t *, vVec, pObj, i )
+#define If_DsdVecForEachObjVec( vNodes, vVec, pObj, i )      \
+    for ( i = 0; (i < Vec_IntSize(vNodes)) && ((pObj) = If_DsdVecObj(vVec, Vec_IntEntry(vNodes,i))); i++ )
+#define If_DsdVecForEachNode( vVec, pObj, i )               \
+    Vec_PtrForEachEntryStart( If_DsdObj_t *, vVec, pObj, i, 2 )
+#define If_DsdObjForEachFanin( vVec, pObj, pFanin, i )      \
+    for ( i = 0; (i < If_DsdObjFaninNum(pObj)) && ((pFanin) = If_DsdObjFanin(vVec, pObj, i)); i++ )
+#define If_DsdObjForEachFaninLit( vVec, pObj, iLit, i )      \
+    for ( i = 0; (i < If_DsdObjFaninNum(pObj)) && ((iLit) = If_DsdObjFaninLit(pObj, i)); i++ )
+
+extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * If_DsdManFileName( If_DsdMan_t * p )
+{
+    return p->pStore;
+}
+int If_DsdManVarNum( If_DsdMan_t * p )
+{
+    return p->nVars;
+}
+int If_DsdManLutSize( If_DsdMan_t * p )
+{
+    return p->LutSize;
+}
+int If_DsdManSuppSize( If_DsdMan_t * p, int iDsd )
+{
+    return If_DsdVecLitSuppSize( &p->vObjs, iDsd );
+}
+int If_DsdManCheckDec( If_DsdMan_t * p, int iDsd )
+{
+    return If_DsdVecObjMark( &p->vObjs, Abc_Lit2Var(iDsd) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [DSD manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word ** If_ManDsdTtElems()
+{
+    static word TtElems[DAU_MAX_VAR+1][DAU_MAX_WORD], * pTtElems[DAU_MAX_VAR+1] = {NULL};
+    if ( pTtElems[0] == NULL )
+    {
+        int v;
+        for ( v = 0; v <= DAU_MAX_VAR; v++ )
+            pTtElems[v] = TtElems[v];
+        Abc_TtElemInit( pTtElems, DAU_MAX_VAR );
+    }
+    return pTtElems;
+}
+If_DsdObj_t * If_DsdObjAlloc( If_DsdMan_t * p, int Type, int nFans )
+{
+    int nWords = If_DsdObjWordNum( nFans );
+    If_DsdObj_t * pObj = (If_DsdObj_t *)Mem_FlexEntryFetch( p->pMem, sizeof(word) * nWords );
+    If_DsdObjClean( pObj );
+    pObj->Type   = Type;
+    pObj->nFans  = nFans;
+    pObj->Id     = Vec_PtrSize( &p->vObjs );
+    pObj->fMark  = 0;
+    pObj->Count  = 0;
+    Vec_PtrPush( &p->vObjs, pObj );
+    Vec_IntPush( &p->vNexts, 0 );
+    Vec_IntPush( &p->vTruths, -1 );
+    assert( Vec_IntSize(&p->vNexts) == Vec_PtrSize(&p->vObjs) );
+    assert( Vec_IntSize(&p->vTruths) == Vec_PtrSize(&p->vObjs) );
+    return pObj;
+}
+If_DsdMan_t * If_DsdManAlloc( int nVars, int LutSize )
+{
+    If_DsdMan_t * p; int v;
+    char pFileName[10];
+    sprintf( pFileName, "%02d.dsd", nVars );
+    p = ABC_CALLOC( If_DsdMan_t, 1 );
+    p->pStore  = Abc_UtilStrsav( pFileName );
+    p->nVars   = nVars;
+    p->LutSize = LutSize;
+    p->nWords  = Abc_TtWordNum( nVars );
+    p->nBins   = Abc_PrimeCudd( 100000 );
+    p->pBins   = ABC_CALLOC( unsigned, p->nBins );
+    p->pMem    = Mem_FlexStart();
+    Vec_PtrGrow( &p->vObjs, 10000 );
+    Vec_IntGrow( &p->vNexts, 10000 );
+    Vec_IntGrow( &p->vTruths, 10000 );
+    If_DsdObjAlloc( p, IF_DSD_CONST0, 0 );
+    If_DsdObjAlloc( p, IF_DSD_VAR, 0 )->nSupp = 1;
+    p->vTemp1   = Vec_IntAlloc( 32 );
+    p->vTemp2   = Vec_IntAlloc( 32 );
+    p->pTtElems = If_ManDsdTtElems();
+    for ( v = 3; v <= nVars; v++ )
+    {
+        p->vTtMem[v] = Vec_MemAlloc( Abc_TtWordNum(v), 12 );
+        Vec_MemHashAlloc( p->vTtMem[v], 10000 );
+        p->vTtDecs[v] = Vec_PtrAlloc( 1000 );
+    }
+/*
+    p->pTtGia   = Gia_ManStart( nVars );
+    Gia_ManHashAlloc( p->pTtGia );
+    for ( v = 0; v < nVars; v++ )
+        Gia_ManAppendCi( p->pTtGia );
+*/
+    for ( v = 2; v < nVars; v++ )
+        p->pSched[v] = Extra_GreyCodeSchedule( v );
+    if ( LutSize )
+    p->pSat     = If_ManSatBuildXY( LutSize );
+    p->vCover   = Vec_IntAlloc( 0 );
+    return p;
+}
+void If_DsdManAllocIsops( If_DsdMan_t * p, int nLutSize )
+{
+    Vec_Int_t * vLevel;
+    int v, i, fCompl;
+    word * pTruth;
+    if ( p->vIsops[3] != NULL )
+        return;
+    if ( Vec_PtrSize(&p->vObjs) > 2 )
+        printf( "Warning: DSD manager is already started without ISOPs.\n" );
+    for ( v = 3; v <= nLutSize; v++ )
+    {
+        p->vIsops[v] = Vec_WecAlloc( 100 );
+        Vec_MemForEachEntry( p->vTtMem[v], pTruth, i )
+        {
+            vLevel = Vec_WecPushLevel( p->vIsops[v] );
+            fCompl = Kit_TruthIsop( (unsigned *)pTruth, v, p->vCover, 1 );
+            if ( fCompl >= 0 && Vec_IntSize(p->vCover) <= 8 )
+            {
+                Vec_IntGrow( vLevel, Vec_IntSize(p->vCover) );
+                Vec_IntAppend( vLevel, p->vCover );
+                if ( fCompl )
+                    vLevel->nCap ^= (1<<16); // hack to remember complemented attribute
+            }
+        }
+        assert( Vec_WecSize(p->vIsops[v]) == Vec_MemEntryNum(p->vTtMem[v]) );
+    }
+}
+void If_DsdManFree( If_DsdMan_t * p, int fVerbose )
+{
+    int v;
+//    If_DsdManDumpDsd( p );
+    if ( fVerbose )
+        If_DsdManPrint( p, NULL, 0, 0, 0, 0, 0 );
+    if ( fVerbose )
+    {
+        char FileName[10];
+        for ( v = 3; v <= p->nVars; v++ )
+        {
+            sprintf( FileName, "dumpdsd%02d", v );
+            Vec_MemDumpTruthTables( p->vTtMem[v], FileName, v );
+        }
+    }
+    for ( v = 2; v < p->nVars; v++ )
+        ABC_FREE( p->pSched[v] );
+    for ( v = 3; v <= p->nVars; v++ )
+    {
+        Vec_MemHashFree( p->vTtMem[v] );
+        Vec_MemFree( p->vTtMem[v] );
+        Vec_VecFree( (Vec_Vec_t *)(p->vTtDecs[v]) );
+        if ( p->vIsops[v] )
+            Vec_WecFree( p->vIsops[v] );
+    }
+    Vec_IntFreeP( &p->vTemp1 );
+    Vec_IntFreeP( &p->vTemp2 );
+    ABC_FREE( p->vObjs.pArray );
+    ABC_FREE( p->vNexts.pArray );
+    ABC_FREE( p->vTruths.pArray );
+    Mem_FlexStop( p->pMem, 0 );
+    Gia_ManStopP( &p->pTtGia );
+    Vec_IntFreeP( &p->vCover );
+    If_ManSatUnbuild( p->pSat );
+    ABC_FREE( p->pStore );
+    ABC_FREE( p->pBins );
+    ABC_FREE( p );
+}
+void If_DsdManDumpDsd( If_DsdMan_t * p, int Support )
+{
+    char * pFileName = "tts_nondsd.txt";
+    If_DsdObj_t * pObj; 
+    Vec_Int_t * vMap;
+    FILE * pFile = fopen( pFileName, "wb" );
+    int v, i;
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\".\n", pFileName );
+        return;
+    }
+    for ( v = 3; v <= p->nVars; v++ )
+    {
+        vMap = Vec_IntStart( Vec_MemEntryNum(p->vTtMem[v]) );
+        If_DsdVecForEachObj( &p->vObjs, pObj, i )
+        {
+            if ( Support && Support != If_DsdObjSuppSize(pObj) )
+                continue;
+            if ( If_DsdObjType(pObj) != IF_DSD_PRIME )
+                continue;
+            if ( Vec_IntEntry(vMap, If_DsdObjTruthId(p, pObj)) )
+                continue;
+            Vec_IntWriteEntry(vMap, If_DsdObjTruthId(p, pObj), 1);
+            fprintf( pFile, "0x" );
+            Abc_TtPrintHexRev( pFile, If_DsdObjTruth(p, pObj), Support ? Abc_MaxInt(Support, 6) : v );
+            fprintf( pFile, "\n" );
+            //printf( "    " );
+            //Dau_DsdPrintFromTruth( If_DsdObjTruth(p, pObj), p->nVars );
+        }
+        Vec_IntFree( vMap );
+    }
+    fclose( pFile );
+}
+void If_DsdManDumpAll( If_DsdMan_t * p, int Support )
+{
+    extern word * If_DsdManComputeTruth( If_DsdMan_t * p, int iDsd, unsigned char * pPermLits );
+    char * pFileName = "tts_all.txt";
+    If_DsdObj_t * pObj;
+    word * pRes; int i;
+    FILE * pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\".\n", pFileName );
+        return;
+    }
+    If_DsdVecForEachObj( &p->vObjs, pObj, i )
+    {
+        if ( Support && Support != If_DsdObjSuppSize(pObj) )
+            continue;
+        pRes = If_DsdManComputeTruth( p, Abc_Var2Lit(i, 0), NULL );
+        fprintf( pFile, "0x" );
+        Abc_TtPrintHexRev( pFile, pRes, Support ? Abc_MaxInt(Support, 6) : p->nVars );
+        fprintf( pFile, "\n" );
+//        printf( "    " );
+//        Dau_DsdPrintFromTruth( pRes, p->nVars );
+    }
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Printing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_DsdManHashProfile( If_DsdMan_t * p )
+{
+    If_DsdObj_t * pObj;
+    unsigned * pSpot;
+    int i, Counter;
+    for ( i = 0; i < p->nBins; i++ )
+    {
+        Counter = 0;
+        for ( pSpot = p->pBins + i; *pSpot; pSpot = (unsigned *)Vec_IntEntryP(&p->vNexts, pObj->Id), Counter++ )
+             pObj = If_DsdVecObj( &p->vObjs, *pSpot );
+//        if ( Counter > 5 )
+//            printf( "%d ", Counter );
+//        if ( i > 10000 )
+//            break;
+    }
+//    printf( "\n" );
+}
+int If_DsdManCheckNonDec_rec( If_DsdMan_t * p, int Id )
+{
+    If_DsdObj_t * pObj;
+    int i, iFanin;
+    pObj = If_DsdVecObj( &p->vObjs, Id );
+    if ( If_DsdObjType(pObj) == IF_DSD_CONST0 )
+        return 0;
+    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
+        return 0;
+    if ( If_DsdObjType(pObj) == IF_DSD_PRIME )
+        return 1;
+    If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
+        if ( If_DsdManCheckNonDec_rec( p, Abc_Lit2Var(iFanin) ) )
+            return 1;
+    return 0;
+}
+void If_DsdManPrint_rec( FILE * pFile, If_DsdMan_t * p, int iDsdLit, unsigned char * pPermLits, int * pnSupp )
+{
+    char OpenType[7]  = {0, 0, 0, '(', '[', '<', '{'};
+    char CloseType[7] = {0, 0, 0, ')', ']', '>', '}'};
+    If_DsdObj_t * pObj;
+    int i, iFanin;
+    fprintf( pFile, "%s", Abc_LitIsCompl(iDsdLit) ? "!" : ""  );
+    pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iDsdLit) );
+    if ( If_DsdObjType(pObj) == IF_DSD_CONST0 )
+        { fprintf( pFile, "0" ); return; }
+    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
+    {
+        int iPermLit = pPermLits ? (int)pPermLits[(*pnSupp)++] : Abc_Var2Lit((*pnSupp)++, 0);
+        fprintf( pFile, "%s%c", Abc_LitIsCompl(iPermLit)? "!":"", 'a' + Abc_Lit2Var(iPermLit) );
+        return;
+    }
+    if ( If_DsdObjType(pObj) == IF_DSD_PRIME )
+        Abc_TtPrintHexRev( pFile, If_DsdObjTruth(p, pObj), If_DsdObjFaninNum(pObj) );
+    fprintf( pFile, "%c", OpenType[If_DsdObjType(pObj)] );
+    If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
+        If_DsdManPrint_rec( pFile, p, iFanin, pPermLits, pnSupp );
+    fprintf( pFile, "%c", CloseType[If_DsdObjType(pObj)] );
+}
+void If_DsdManPrintOne( FILE * pFile, If_DsdMan_t * p, int iObjId, unsigned char * pPermLits, int fNewLine )
+{
+    int nSupp = 0;
+    fprintf( pFile, "%6d : ", iObjId );
+    fprintf( pFile, "%2d ",   If_DsdVecObjSuppSize(&p->vObjs, iObjId) );
+    fprintf( pFile, "%8d ",   If_DsdVecObjRef(&p->vObjs, iObjId) );
+    fprintf( pFile, "%d  ",    If_DsdVecObjMark(&p->vObjs, iObjId) );
+    If_DsdManPrint_rec( pFile, p, Abc_Var2Lit(iObjId, 0), pPermLits, &nSupp );
+    if ( fNewLine )
+        fprintf( pFile, "\n" );
+    assert( nSupp == If_DsdVecObjSuppSize(&p->vObjs, iObjId) );
+}
+#define DSD_ARRAY_LIMIT 16
+void If_DsdManPrintDecs( FILE * pFile, If_DsdMan_t * p )
+{
+    Vec_Int_t * vDecs;
+    int i, k, v, nSuppSize, nDecMax = 0;
+    int pDecMax[IF_MAX_FUNC_LUTSIZE] = {0};
+    int pCountsAll[IF_MAX_FUNC_LUTSIZE] = {0};
+    int pCountsSSizes[IF_MAX_FUNC_LUTSIZE] = {0};
+    int pCounts[IF_MAX_FUNC_LUTSIZE][DSD_ARRAY_LIMIT+2] = {{0}};
+    word * pTruth;
+    for ( v = 3; v <= p->nVars; v++ )
+    {
+        assert( Vec_MemEntryNum(p->vTtMem[v]) == Vec_PtrSize(p->vTtDecs[v]) );
+        // find max number of decompositions
+        Vec_PtrForEachEntry( Vec_Int_t *, p->vTtDecs[v], vDecs, i )
+        {
+            pTruth = Vec_MemReadEntry( p->vTtMem[v], i );
+            nSuppSize = Abc_TtSupportSize( pTruth, p->nVars );
+            pDecMax[nSuppSize] = Abc_MaxInt( pDecMax[nSuppSize], Vec_IntSize(vDecs) );
+            nDecMax = Abc_MaxInt( nDecMax, Vec_IntSize(vDecs) );
+        }
+        // fill up
+        Vec_PtrForEachEntry( Vec_Int_t *, p->vTtDecs[v], vDecs, i )
+        {
+            pTruth = Vec_MemReadEntry( p->vTtMem[v], i );
+            nSuppSize = Abc_TtSupportSize( pTruth, p->nVars );
+            pCountsAll[nSuppSize]++;
+            pCountsSSizes[nSuppSize] += Vec_IntSize(vDecs);
+            pCounts[nSuppSize][Abc_MinInt(DSD_ARRAY_LIMIT+1,Vec_IntSize(vDecs))]++;
+    //        pCounts[nSuppSize][Abc_MinInt(DSD_ARRAY_LIMIT+1,Vec_IntSize(vDecs)?1+(Vec_IntSize(vDecs)/10):0)]++;
+    /*
+            if ( nSuppSize == 6 && Vec_IntSize(vDecs) == pDecMax[6] )
+            {
+                fprintf( pFile, "0x" );
+                Abc_TtPrintHex( pTruth, nSuppSize );
+                Dau_DecPrintSets( vDecs, nSuppSize );
+            }
+    */
+        }
+    }
+    // print header
+    fprintf( pFile, " N :  " );
+    fprintf( pFile, " Total  " );
+    for ( k = 0; k <= DSD_ARRAY_LIMIT; k++ )
+        fprintf( pFile, "%6d", k );
+    fprintf( pFile, "  " );
+    fprintf( pFile, "  More" );
+    fprintf( pFile, "     Ave" );
+    fprintf( pFile, "     Max" );
+    fprintf( pFile, "\n" );
+    // print rows
+    for ( i = 0; i <= p->nVars; i++ )
+    {
+        fprintf( pFile, "%2d :  ", i );
+        fprintf( pFile, "%6d  ", pCountsAll[i] );
+        for ( k = 0; k <= DSD_ARRAY_LIMIT; k++ )
+//            fprintf( pFile, "%6d", pCounts[i][k] );
+            fprintf( pFile, "%6.1f", 100.0*pCounts[i][k]/Abc_MaxInt(1,pCountsAll[i]) );
+        fprintf( pFile, "  " );
+//        fprintf( pFile, "%6d", pCounts[i][k] );
+        fprintf( pFile, "%6.1f", 100.0*pCounts[i][k]/Abc_MaxInt(1,pCountsAll[i]) );
+        fprintf( pFile, "  " );
+        fprintf( pFile, "%6.1f", 1.0*pCountsSSizes[i]/Abc_MaxInt(1,pCountsAll[i]) );
+        fprintf( pFile, "  " );
+        fprintf( pFile, "%6d", pDecMax[i] );
+        fprintf( pFile, "\n" );
+    }
+}
+void If_DsdManPrintOccurs( FILE * pFile, If_DsdMan_t * p )
+{
+    char Buffer[100];
+    If_DsdObj_t * pObj;
+    Vec_Int_t * vOccurs;
+    int nOccurs, nOccursMax, nOccursAll;
+    int i, k, nSizeMax, Counter = 0;
+    // determine the largest fanin and fanout
+    nOccursMax = nOccursAll = 0;
+    If_DsdVecForEachNode( &p->vObjs, pObj, i )
+    {
+        nOccurs = pObj->Count;
+        nOccursAll += nOccurs;
+        nOccursMax  = Abc_MaxInt( nOccursMax, nOccurs );
+    }
+    // allocate storage for fanin/fanout numbers
+    nSizeMax = 10 * (Abc_Base10Log(nOccursMax) + 1);
+    vOccurs  = Vec_IntStart( nSizeMax );
+    // count the number of fanins and fanouts
+    If_DsdVecForEachNode( &p->vObjs, pObj, i )
+    {
+        nOccurs = pObj->Count;
+        if ( nOccurs < 10 )
+            Vec_IntAddToEntry( vOccurs, nOccurs, 1 );
+        else if ( nOccurs < 100 )
+            Vec_IntAddToEntry( vOccurs, 10 + nOccurs/10, 1 );
+        else if ( nOccurs < 1000 )
+            Vec_IntAddToEntry( vOccurs, 20 + nOccurs/100, 1 );
+        else if ( nOccurs < 10000 )
+            Vec_IntAddToEntry( vOccurs, 30 + nOccurs/1000, 1 );
+        else if ( nOccurs < 100000 )
+            Vec_IntAddToEntry( vOccurs, 40 + nOccurs/10000, 1 );
+        else if ( nOccurs < 1000000 )
+            Vec_IntAddToEntry( vOccurs, 50 + nOccurs/100000, 1 );
+        else if ( nOccurs < 10000000 )
+            Vec_IntAddToEntry( vOccurs, 60 + nOccurs/1000000, 1 );
+    }
+    fprintf( pFile, "The distribution of object occurrences:\n" );
+    for ( k = 0; k < nSizeMax; k++ )
+    {
+        if ( Vec_IntEntry(vOccurs, k) == 0 )
+            continue;
+        if ( k < 10 )
+            fprintf( pFile, "%15d : ", k );
+        else
+        {
+            sprintf( Buffer, "%d - %d", (int)pow((double)10, k/10) * (k%10), (int)pow((double)10, k/10) * (k%10+1) - 1 );
+            fprintf( pFile, "%15s : ", Buffer );
+        }
+        fprintf( pFile, "%12d   ", Vec_IntEntry(vOccurs, k) );
+        Counter += Vec_IntEntry(vOccurs, k);
+        fprintf( pFile, "(%6.2f %%)", 100.0*Counter/Vec_PtrSize(&p->vObjs) );
+        fprintf( pFile, "\n" );
+    }
+    Vec_IntFree( vOccurs );
+    fprintf( pFile, "Fanins: Max = %d. Ave = %.2f.\n", nOccursMax,  1.0*nOccursAll/Vec_PtrSize(&p->vObjs) );
+}
+
+void If_DsdManPrintDistrib( If_DsdMan_t * p )
+{
+    If_DsdObj_t * pObj; int i;
+    int CountObj[IF_MAX_FUNC_LUTSIZE+2] = {0};
+    int CountObjNon[IF_MAX_FUNC_LUTSIZE+2] = {0};
+    int CountObjNpn[IF_MAX_FUNC_LUTSIZE+2] = {0};
+    int CountStr[IF_MAX_FUNC_LUTSIZE+2] = {0};
+    int CountStrNon[IF_MAX_FUNC_LUTSIZE+2] = {0};
+    int CountMarked[IF_MAX_FUNC_LUTSIZE+2] = {0};
+    for ( i = 3; i <= p->nVars; i++ )
+    {
+        CountObjNpn[i] = Vec_MemEntryNum(p->vTtMem[i]);
+        CountObjNpn[p->nVars+1] += Vec_MemEntryNum(p->vTtMem[i]);
+    }
+    If_DsdVecForEachObj( &p->vObjs, pObj, i )
+    {
+        CountObj[If_DsdObjFaninNum(pObj)]++,        CountObj[p->nVars+1]++;
+        if ( If_DsdObjType(pObj) == IF_DSD_PRIME )
+            CountObjNon[If_DsdObjFaninNum(pObj)]++, CountObjNon[p->nVars+1]++;
+        CountStr[If_DsdObjSuppSize(pObj)]++,        CountStr[p->nVars+1]++;
+        if ( If_DsdManCheckNonDec_rec(p, i) )
+            CountStrNon[If_DsdObjSuppSize(pObj)]++, CountStrNon[p->nVars+1]++;
+        if ( If_DsdVecObjMark(&p->vObjs, i) )
+            CountMarked[If_DsdObjSuppSize(pObj)]++, CountMarked[p->nVars+1]++;
+    }
+    printf( "***** DSD MANAGER STATISTICS *****\n" );
+    printf( "Support     " );
+    printf( "Obj   " );
+    printf( "ObjNDSD            " );
+    printf( "NPNNDSD                  " );
+    printf( "Str   " );
+    printf( "StrNDSD             " );
+    printf( "Marked  " );
+    printf( "\n" );
+    for ( i = 0; i <= p->nVars + 1; i++ )
+    {
+        if ( i == p->nVars + 1 )
+            printf( "All : " );
+        else
+            printf( "%3d : ", i );
+        printf( "%9d ", CountObj[i] );
+        printf( "%9d ", CountObjNon[i] );
+        printf( "%6.2f %% ", 100.0 * CountObjNon[i] / Abc_MaxInt(1, CountObj[i]) );
+        printf( "%9d ", CountObjNpn[i] );
+        printf( "%6.2f %% ", 100.0 * CountObjNpn[i] / Abc_MaxInt(1, CountObj[i]) );
+        printf( "  " );
+        printf( "%9d ", CountStr[i] );
+        printf( "%9d ", CountStrNon[i] );
+        printf( "%6.2f %% ", 100.0 * CountStrNon[i] / Abc_MaxInt(1, CountStr[i]) );
+        printf( "%9d ", CountMarked[i] );
+        printf( "%6.2f %%",  100.0 * CountMarked[i] / Abc_MaxInt(1, CountStr[i]) );
+        printf( "\n" );
+    }
+}
+void If_DsdManPrint( If_DsdMan_t * p, char * pFileName, int Number, int Support, int fOccurs, int fTtDump, int fVerbose )
+{
+    If_DsdObj_t * pObj;
+    Vec_Int_t * vStructs, * vCounts;
+    int CountUsed = 0, CountNonDsd = 0, CountNonDsdStr = 0, CountMarked = 0, CountPrime = 0;
+    int i, v, * pPerm, DsdMax = 0, MemSizeTTs = 0, MemSizeDecs = 0;
+    FILE * pFile;
+    pFile = pFileName ? fopen( pFileName, "wb" ) : stdout;
+    if ( pFileName && pFile == NULL )
+    {
+        printf( "cannot open output file\n" );
+        return;
+    }
+    If_DsdVecForEachObj( &p->vObjs, pObj, i )
+    {
+        if ( If_DsdObjType(pObj) == IF_DSD_PRIME )
+            DsdMax = Abc_MaxInt( DsdMax, pObj->nFans ); 
+        CountPrime += If_DsdObjType(pObj) == IF_DSD_PRIME;
+        CountNonDsdStr += If_DsdManCheckNonDec_rec( p, pObj->Id );
+        CountUsed += ( If_DsdVecObjRef(&p->vObjs, pObj->Id) > 0 );
+        CountMarked += If_DsdVecObjMark( &p->vObjs, i );
+    }
+    for ( v = 3; v <= p->nVars; v++ )
+    {
+        CountNonDsd += Vec_MemEntryNum(p->vTtMem[v]);
+        MemSizeTTs += Vec_MemEntrySize(p->vTtMem[v]) * Vec_MemEntryNum(p->vTtMem[v]);
+        MemSizeDecs += (int)Vec_VecMemoryInt((Vec_Vec_t *)(p->vTtDecs[v]));
+    }
+    If_DsdManPrintDistrib( p );
+    if ( p->pTtGia )
+    fprintf( pFile, "Non-DSD AIG nodes          = %8d\n", Gia_ManAndNum(p->pTtGia) );
+    fprintf( pFile, "Unique table misses        = %8d\n", p->nUniqueMisses );
+    fprintf( pFile, "Unique table hits          = %8d\n", p->nUniqueHits );
+    fprintf( pFile, "Memory used for objects    = %8.2f MB.\n", 1.0*Mem_FlexReadMemUsage(p->pMem)/(1<<20) );
+    fprintf( pFile, "Memory used for functions  = %8.2f MB.\n", 8.0*(MemSizeTTs+sizeof(int)*Vec_IntCap(&p->vTruths))/(1<<20) );
+    fprintf( pFile, "Memory used for hash table = %8.2f MB.\n", 1.0*sizeof(int)*(p->nBins+Vec_IntCap(&p->vNexts))/(1<<20) );
+    fprintf( pFile, "Memory used for bound sets = %8.2f MB.\n", 1.0*MemSizeDecs/(1<<20) );
+    fprintf( pFile, "Memory used for array      = %8.2f MB.\n", 1.0*sizeof(void *)*Vec_PtrCap(&p->vObjs)/(1<<20) );
+    if ( p->pTtGia )
+    fprintf( pFile, "Memory used for AIG        = %8.2f MB.\n", 8.0*Gia_ManAndNum(p->pTtGia)/(1<<20) );
+    if ( p->timeDsd )
+    {
+        Abc_PrintTime( 1, "Time DSD   ", p->timeDsd    );
+        Abc_PrintTime( 1, "Time canon ", p->timeCanon-p->timeCheck  );
+        Abc_PrintTime( 1, "Time check ", p->timeCheck  );
+        Abc_PrintTime( 1, "Time check2", p->timeCheck2 );
+        Abc_PrintTime( 1, "Time verify", p->timeVerify );
+    }
+    if ( fOccurs )
+        If_DsdManPrintOccurs( stdout, p );
+//    If_DsdManHashProfile( p );
+    if ( fTtDump )
+        If_DsdManDumpDsd( p, Support );
+    if ( fTtDump )
+        If_DsdManDumpAll( p, Support );
+//    If_DsdManPrintDecs( stdout, p );
+    if ( !fVerbose )
+        return;
+    vStructs = Vec_IntAlloc( 1000 );
+    vCounts  = Vec_IntAlloc( 1000 );
+    If_DsdVecForEachObj( &p->vObjs, pObj, i )
+    {
+        if ( Number && i % Number )
+            continue;
+        if ( Support && Support != If_DsdObjSuppSize(pObj) )
+            continue;
+        Vec_IntPush( vStructs, i );
+        Vec_IntPush( vCounts, -(int)pObj->Count );
+//        If_DsdManPrintOne( pFile, p, pObj->Id, NULL, 1 );
+    }
+//    fprintf( pFile, "\n" );
+    pPerm = Abc_MergeSortCost( Vec_IntArray(vCounts), Vec_IntSize(vCounts) );
+    for ( i = 0; i < Abc_MinInt(Vec_IntSize(vCounts), 20); i++ )
+    {
+        printf( "%2d : ", i+1 );
+        pObj = If_DsdVecObj( &p->vObjs, Vec_IntEntry(vStructs, pPerm[i]) );
+        If_DsdManPrintOne( pFile, p, pObj->Id, NULL, 1 );
+    }
+    ABC_FREE( pPerm );
+    Vec_IntFree( vStructs );
+    Vec_IntFree( vCounts );
+    if ( pFileName )
+        fclose( pFile );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Sorting DSD literals.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_DsdObjCompare( If_DsdMan_t * pMan, Vec_Ptr_t * p, int iLit0, int iLit1 )
+{
+    If_DsdObj_t * p0 = If_DsdVecObj(p, Abc_Lit2Var(iLit0));
+    If_DsdObj_t * p1 = If_DsdVecObj(p, Abc_Lit2Var(iLit1));
+    int i, Res;
+    if ( If_DsdObjType(p0) < If_DsdObjType(p1) )
+        return -1;
+    if ( If_DsdObjType(p0) > If_DsdObjType(p1) )
+        return 1;
+    if ( If_DsdObjType(p0) < IF_DSD_AND )
+        return 0;
+    if ( If_DsdObjFaninNum(p0) < If_DsdObjFaninNum(p1) )
+        return -1;
+    if ( If_DsdObjFaninNum(p0) > If_DsdObjFaninNum(p1) )
+        return 1;
+    if ( If_DsdObjType(p0) == IF_DSD_PRIME )
+    {
+        if ( If_DsdObjTruthId(pMan, p0) < If_DsdObjTruthId(pMan, p1) )
+            return -1;
+        if ( If_DsdObjTruthId(pMan, p0) > If_DsdObjTruthId(pMan, p1) )
+            return 1;
+    }
+    for ( i = 0; i < If_DsdObjFaninNum(p0); i++ )
+    {
+        Res = If_DsdObjCompare( pMan, p, If_DsdObjFaninLit(p0, i), If_DsdObjFaninLit(p1, i) );
+        if ( Res != 0 )
+            return Res;
+    }
+    if ( Abc_LitIsCompl(iLit0) > Abc_LitIsCompl(iLit1) )
+        return -1;
+    if ( Abc_LitIsCompl(iLit0) < Abc_LitIsCompl(iLit1) )
+        return 1;
+    assert( iLit0 == iLit1 );
+    return 0;
+}
+void If_DsdObjSort( If_DsdMan_t * pMan, Vec_Ptr_t * p, int * pLits, int nLits, int * pPerm )
+{
+    int i, j, best_i;
+    for ( i = 0; i < nLits-1; i++ )
+    {
+        best_i = i;
+        for ( j = i+1; j < nLits; j++ )
+            if ( If_DsdObjCompare(pMan, p, pLits[best_i], pLits[j]) == 1 )
+                best_i = j;
+        if ( i == best_i )
+            continue;
+        ABC_SWAP( int, pLits[i], pLits[best_i] );
+        if ( pPerm )
+            ABC_SWAP( int, pPerm[i], pPerm[best_i] );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned If_DsdObjHashKey( If_DsdMan_t * p, int Type, int * pLits, int nLits, int truthId )
+{
+    static int s_Primes[24] = { 1049, 1297, 1559, 1823, 2089, 2371, 2663, 2909, 
+                                3221, 3517, 3779, 4073, 4363, 4663, 4973, 5281, 
+                                5573, 5861, 6199, 6481, 6803, 7109, 7477, 7727 };
+    int i;
+    unsigned uHash = Type * 7873 + nLits * 8147;
+    for ( i = 0; i < nLits; i++ )
+        uHash += pLits[i] * s_Primes[i & 0xF];
+    if ( Type == IF_DSD_PRIME )
+        uHash += truthId * s_Primes[i & 0xF];
+    return uHash % p->nBins;
+}
+unsigned * If_DsdObjHashLookup( If_DsdMan_t * p, int Type, int * pLits, int nLits, int truthId )
+{
+    If_DsdObj_t * pObj;
+    unsigned * pSpot = p->pBins + If_DsdObjHashKey(p, Type, pLits, nLits, truthId);
+    for ( ; *pSpot; pSpot = (unsigned *)Vec_IntEntryP(&p->vNexts, pObj->Id) )
+    {
+        pObj = If_DsdVecObj( &p->vObjs, *pSpot );
+        if ( If_DsdObjType(pObj) == Type && 
+             If_DsdObjFaninNum(pObj) == nLits && 
+             !memcmp(pObj->pFans, pLits, sizeof(int)*If_DsdObjFaninNum(pObj)) &&
+             truthId == If_DsdObjTruthId(p, pObj) )
+        {
+            p->nUniqueHits++;
+            return pSpot;
+        }
+    }
+    p->nUniqueMisses++;
+    return pSpot;
+}
+static void If_DsdObjHashResize( If_DsdMan_t * p )
+{
+    If_DsdObj_t * pObj;
+    unsigned * pSpot;
+    int i, Prev = p->nUniqueMisses;
+    p->nBins = Abc_PrimeCudd( 2 * p->nBins );
+    p->pBins = ABC_REALLOC( unsigned, p->pBins, p->nBins );
+    memset( p->pBins, 0, sizeof(unsigned) * p->nBins );
+    Vec_IntFill( &p->vNexts, Vec_PtrSize(&p->vObjs), 0 );
+    If_DsdVecForEachNode( &p->vObjs, pObj, i )
+    {
+        pSpot = If_DsdObjHashLookup( p, pObj->Type, (int *)pObj->pFans, pObj->nFans, If_DsdObjTruthId(p, pObj) );
+        assert( *pSpot == 0 );
+        *pSpot = pObj->Id;
+    }
+    assert( p->nUniqueMisses - Prev == Vec_PtrSize(&p->vObjs) - 2 );
+    p->nUniqueMisses = Prev;
+}
+
+int If_DsdObjCreate( If_DsdMan_t * p, int Type, int * pLits, int nLits, int truthId )
+{
+    If_DsdObj_t * pObj, * pFanin;
+    int i, iPrev = -1;
+    // check structural canonicity
+    assert( Type != DAU_DSD_MUX || nLits == 3 );
+//    assert( Type != DAU_DSD_MUX || !Abc_LitIsCompl(pLits[0]) );
+    assert( Type != DAU_DSD_MUX || !Abc_LitIsCompl(pLits[1]) || !Abc_LitIsCompl(pLits[2]) );
+    // check that leaves are in good order
+    if ( Type == DAU_DSD_AND || Type == DAU_DSD_XOR )
+    {
+        for ( i = 0; i < nLits; i++ )
+        {
+            pFanin = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(pLits[i]) );
+            assert( Type != DAU_DSD_AND || Abc_LitIsCompl(pLits[i]) || If_DsdObjType(pFanin) != DAU_DSD_AND );
+            assert( Type != DAU_DSD_XOR || If_DsdObjType(pFanin) != DAU_DSD_XOR );
+            assert( iPrev == -1 || If_DsdObjCompare(p, &p->vObjs, iPrev, pLits[i]) <= 0 );
+            iPrev = pLits[i];
+        }
+    }
+    // create new node
+    pObj = If_DsdObjAlloc( p, Type, nLits );
+    if ( Type == DAU_DSD_PRIME )
+        If_DsdObjSetTruth( p, pObj, truthId );
+    assert( pObj->nSupp == 0 );
+    for ( i = 0; i < nLits; i++ )
+    {
+        pObj->pFans[i] = pLits[i];
+        pObj->nSupp += If_DsdVecLitSuppSize(&p->vObjs, pLits[i]);
+    }
+    // check decomposability
+    if ( p->LutSize && !If_DsdManCheckXY(p, Abc_Var2Lit(pObj->Id, 0), p->LutSize, 0, 0, 0, 0) )
+        If_DsdVecObjSetMark( &p->vObjs, pObj->Id );
+    return pObj->Id;
+}
+int If_DsdObjFindOrAdd( If_DsdMan_t * p, int Type, int * pLits, int nLits, word * pTruth )
+{
+    int PrevSize       = (Type == IF_DSD_PRIME) ? Vec_MemEntryNum( p->vTtMem[nLits] ) : -1;   
+    int objId, truthId = (Type == IF_DSD_PRIME) ? Vec_MemHashInsert(p->vTtMem[nLits], pTruth) : -1;
+    unsigned * pSpot = If_DsdObjHashLookup( p, Type, pLits, nLits, truthId );
+//abctime clk;
+    if ( *pSpot )
+        return (int)*pSpot;
+//clk = Abc_Clock();
+    if ( p->LutSize && truthId >= 0 && truthId == Vec_PtrSize(p->vTtDecs[nLits]) )
+    {
+        Vec_Int_t * vSets = Dau_DecFindSets_int( pTruth, nLits, p->pSched );
+        assert( truthId == Vec_MemEntryNum(p->vTtMem[nLits])-1 );
+        Vec_PtrPush( p->vTtDecs[nLits], vSets );
+//        Dau_DecPrintSets( vSets, nLits );
+    }
+    if ( p->vIsops[nLits] && truthId >= 0 && PrevSize != Vec_MemEntryNum(p->vTtMem[nLits]) )
+    {
+        Vec_Int_t * vLevel = Vec_WecPushLevel( p->vIsops[nLits] );
+        int fCompl = Kit_TruthIsop( (unsigned *)pTruth, nLits, p->vCover, 1 );
+        if ( fCompl >= 0 && Vec_IntSize(p->vCover) <= 8 )
+        {
+            Vec_IntGrow( vLevel, Vec_IntSize(p->vCover) );
+            Vec_IntAppend( vLevel, p->vCover );
+            if ( fCompl )
+                vLevel->nCap ^= (1<<16); // hack to remember complemented attribute
+        }
+        assert( Vec_WecSize(p->vIsops[nLits]) == Vec_MemEntryNum(p->vTtMem[nLits]) );
+    }
+    if ( p->pTtGia && truthId >= 0 && truthId == Vec_MemEntryNum(p->vTtMem[nLits])-1 )
+    {
+//        int nObjOld = Gia_ManAndNum(p->pTtGia);
+        int Lit = Kit_TruthToGia( p->pTtGia, (unsigned *)pTruth, nLits, p->vCover, NULL, 1 );
+//        printf( "%d ", Gia_ManAndNum(p->pTtGia)-nObjOld );
+        Gia_ManAppendCo( p->pTtGia, Lit );
+    }
+//p->timeCheck += Abc_Clock() - clk;
+    *pSpot = Vec_PtrSize( &p->vObjs );
+    objId = If_DsdObjCreate( p, Type, pLits, nLits, truthId );
+    if ( Vec_PtrSize(&p->vObjs) > p->nBins )
+        If_DsdObjHashResize( p );
+    return objId;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Saving/loading DSD manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_DsdManSave( If_DsdMan_t * p, char * pFileName )
+{
+    If_DsdObj_t * pObj; 
+    Vec_Int_t * vSets;
+    char * pBuffer = "dsd0";
+    word * pTruth; 
+    int i, v, Num;
+    FILE * pFile = fopen( pFileName ? pFileName : p->pStore, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Writing DSD manager file \"%s\" has failed.\n", pFileName ? pFileName : p->pStore );
+        return;
+    }
+    fwrite( pBuffer, 4, 1, pFile );
+    Num = p->nVars;
+    fwrite( &Num, 4, 1, pFile );
+    Num = p->LutSize;
+    fwrite( &Num, 4, 1, pFile );
+    Num = Vec_PtrSize(&p->vObjs);
+    fwrite( &Num, 4, 1, pFile );
+    Vec_PtrForEachEntryStart( If_DsdObj_t *, &p->vObjs, pObj, i, 2 )
+    {
+        Num = If_DsdObjWordNum( pObj->nFans );
+        fwrite( &Num, 4, 1, pFile );
+        fwrite( pObj, sizeof(word)*Num, 1, pFile );
+        if ( pObj->Type == IF_DSD_PRIME )
+            fwrite( Vec_IntEntryP(&p->vTruths, i), 4, 1, pFile );
+    }
+    for ( v = 3; v <= p->nVars; v++ )
+    {
+        int nBytes = sizeof(word)*Vec_MemEntrySize(p->vTtMem[v]);
+        Num = Vec_MemEntryNum(p->vTtMem[v]);
+        fwrite( &Num, 4, 1, pFile );
+        Vec_MemForEachEntry( p->vTtMem[v], pTruth, i )
+            fwrite( pTruth, nBytes, 1, pFile );
+        Num = Vec_PtrSize(p->vTtDecs[v]);
+        fwrite( &Num, 4, 1, pFile );
+        Vec_PtrForEachEntry( Vec_Int_t *, p->vTtDecs[v], vSets, i )
+        {
+            Num = Vec_IntSize(vSets);
+            fwrite( &Num, 4, 1, pFile );
+            fwrite( Vec_IntArray(vSets), sizeof(int)*Num, 1, pFile );
+        }
+    }
+    fclose( pFile );
+}
+If_DsdMan_t * If_DsdManLoad( char * pFileName )
+{
+    If_DsdMan_t * p;
+    If_DsdObj_t * pObj; 
+    Vec_Int_t * vSets;
+    char pBuffer[10];
+    unsigned * pSpot;
+    word * pTruth;
+    int i, v, Num, Num2, RetValue;
+    FILE * pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Reading DSD manager file \"%s\" has failed.\n", pFileName );
+        return NULL;
+    }
+    RetValue = fread( pBuffer, 4, 1, pFile );
+    if ( pBuffer[0] != 'd' && pBuffer[1] != 's' && pBuffer[2] != 'd' && pBuffer[3] != '0' )
+    {
+        printf( "Unrecognized format of file \"%s\".\n", pFileName );
+        return NULL;
+    }
+    RetValue = fread( &Num, 4, 1, pFile );
+    p = If_DsdManAlloc( Num, 0 );
+    ABC_FREE( p->pStore );
+    p->pStore = Abc_UtilStrsav( pFileName );
+    RetValue = fread( &Num, 4, 1, pFile );
+    p->LutSize = Num;
+    p->pSat  = If_ManSatBuildXY( p->LutSize );
+    RetValue = fread( &Num, 4, 1, pFile );
+    assert( Num >= 2 );
+    Vec_PtrFillExtra( &p->vObjs, Num, NULL );
+    Vec_IntFill( &p->vNexts, Num, 0 );
+    Vec_IntFill( &p->vTruths, Num, -1 );
+    p->nBins = Abc_PrimeCudd( 2*Num );
+    p->pBins = ABC_REALLOC( unsigned, p->pBins, p->nBins );
+    memset( p->pBins, 0, sizeof(unsigned) * p->nBins );
+    for ( i = 2; i < Vec_PtrSize(&p->vObjs); i++ )
+    {
+        RetValue = fread( &Num, 4, 1, pFile );
+        pObj = (If_DsdObj_t *)Mem_FlexEntryFetch( p->pMem, sizeof(word) * Num );
+        RetValue = fread( pObj, sizeof(word)*Num, 1, pFile );
+        Vec_PtrWriteEntry( &p->vObjs, i, pObj );
+        if ( pObj->Type == IF_DSD_PRIME )
+        {
+            RetValue = fread( &Num, 4, 1, pFile );
+            Vec_IntWriteEntry( &p->vTruths, i, Num );
+        }
+        pSpot = If_DsdObjHashLookup( p, pObj->Type, (int *)pObj->pFans, pObj->nFans, If_DsdObjTruthId(p, pObj) );
+        assert( *pSpot == 0 );
+        *pSpot = pObj->Id;
+    }
+    assert( p->nUniqueMisses == Vec_PtrSize(&p->vObjs) - 2 );
+    p->nUniqueMisses = 0;
+    pTruth = ABC_ALLOC( word, p->nWords );
+    for ( v = 3; v <= p->nVars; v++ )
+    {
+        int nBytes = sizeof(word)*Vec_MemEntrySize(p->vTtMem[v]);
+        RetValue = fread( &Num, 4, 1, pFile );
+        for ( i = 0; i < Num; i++ )
+        {
+            RetValue = fread( pTruth, nBytes, 1, pFile );
+            Vec_MemHashInsert( p->vTtMem[v], pTruth );
+        }
+        assert( Num == Vec_MemEntryNum(p->vTtMem[v]) );
+        RetValue = fread( &Num2, 4, 1, pFile );
+        for ( i = 0; i < Num2; i++ )
+        {
+            RetValue = fread( &Num, 4, 1, pFile );
+            vSets = Vec_IntAlloc( Num );
+            RetValue = fread( Vec_IntArray(vSets), sizeof(int)*Num, 1, pFile );
+            vSets->nSize = Num;
+            Vec_PtrPush( p->vTtDecs[v], vSets );
+        }
+        assert( Num2 == Vec_PtrSize(p->vTtDecs[v]) ); 
+    }
+    ABC_FREE( pTruth );
+    fclose( pFile );
+    return p;
+}
+void If_DsdManMerge( If_DsdMan_t * p, If_DsdMan_t * pNew )
+{
+    If_DsdObj_t * pObj; 
+    Vec_Int_t * vMap;
+    int pFanins[DAU_MAX_VAR];
+    int i, k, iFanin, Id;
+    if ( p->nVars < pNew->nVars )
+    {
+        printf( "The number of variables should be the same or smaller.\n" );
+        return;
+    }
+    if ( p->LutSize != pNew->LutSize )
+    {
+        printf( "LUT size should be the same.\n" );
+        return;
+    }
+    vMap = Vec_IntAlloc( Vec_PtrSize(&pNew->vObjs) );
+    Vec_IntPush( vMap, 0 );
+    Vec_IntPush( vMap, 1 );
+    If_DsdVecForEachNode( &pNew->vObjs, pObj, i )
+    {
+        If_DsdObjForEachFaninLit( &pNew->vObjs, pObj, iFanin, k )
+            pFanins[k] = Abc_Lit2LitV( Vec_IntArray(vMap), iFanin );
+        Id = If_DsdObjFindOrAdd( p, pObj->Type, pFanins, pObj->nFans, pObj->Type == IF_DSD_PRIME ? If_DsdObjTruth(pNew, pObj) : NULL );
+        Vec_IntPush( vMap, Id );
+    }
+    assert( Vec_IntSize(vMap) == Vec_PtrSize(&pNew->vObjs) );
+    Vec_IntFree( vMap );
+}
+void If_DsdManClean( If_DsdMan_t * p, int fVerbose )
+{
+    If_DsdObj_t * pObj; 
+    int i;
+    If_DsdVecForEachObj( &p->vObjs, pObj, i )
+        pObj->Count = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect nodes of the tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_DsdManCollect_rec( If_DsdMan_t * p, int Id, Vec_Int_t * vNodes, Vec_Int_t * vFirsts, int * pnSupp )
+{
+    int i, iFanin, iFirst;
+    If_DsdObj_t * pObj = If_DsdVecObj( &p->vObjs, Id );
+    if ( If_DsdObjType(pObj) == IF_DSD_CONST0 )
+        return;
+    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
+    {
+        (*pnSupp)++;
+        return;
+    }
+    iFirst = *pnSupp;
+    If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
+        If_DsdManCollect_rec( p, Abc_Lit2Var(iFanin), vNodes, vFirsts, pnSupp );
+    Vec_IntPush( vNodes, Id );
+    Vec_IntPush( vFirsts, iFirst );
+}
+void If_DsdManCollect( If_DsdMan_t * p, int Id, Vec_Int_t * vNodes, Vec_Int_t * vFirsts )
+{
+    int nSupp = 0;
+    Vec_IntClear( vNodes );
+    Vec_IntClear( vFirsts );
+    If_DsdManCollect_rec( p, Id, vNodes, vFirsts, &nSupp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_DsdManComputeTruth_rec( If_DsdMan_t * p, int iDsd, word * pRes, unsigned char * pPermLits, int * pnSupp )
+{
+    int i, iFanin, fCompl = Abc_LitIsCompl(iDsd);
+    If_DsdObj_t * pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iDsd) );
+    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
+    {
+        int iPermLit = pPermLits ? (int)pPermLits[*pnSupp] : Abc_Var2Lit(*pnSupp, 0);
+        (*pnSupp)++;
+        assert( (*pnSupp) <= p->nVars );
+        Abc_TtCopy( pRes, p->pTtElems[Abc_Lit2Var(iPermLit)], p->nWords, fCompl ^ Abc_LitIsCompl(iPermLit) );
+        return;
+    }
+    if ( If_DsdObjType(pObj) == IF_DSD_AND || If_DsdObjType(pObj) == IF_DSD_XOR )
+    {
+        word pTtTemp[DAU_MAX_WORD];
+        if ( If_DsdObjType(pObj) == IF_DSD_AND )
+            Abc_TtConst1( pRes, p->nWords );
+        else
+            Abc_TtConst0( pRes, p->nWords );
+        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
+        {
+            If_DsdManComputeTruth_rec( p, iFanin, pTtTemp, pPermLits, pnSupp );
+            if ( If_DsdObjType(pObj) == IF_DSD_AND )
+                Abc_TtAnd( pRes, pRes, pTtTemp, p->nWords, 0 );
+            else
+                Abc_TtXor( pRes, pRes, pTtTemp, p->nWords, 0 );
+        }
+        if ( fCompl ) Abc_TtNot( pRes, p->nWords );
+        return;
+    }
+    if ( If_DsdObjType(pObj) == IF_DSD_MUX ) // mux
+    {
+        word pTtTemp[3][DAU_MAX_WORD];
+        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
+            If_DsdManComputeTruth_rec( p, iFanin, pTtTemp[i], pPermLits, pnSupp );
+        assert( i == 3 );
+        Abc_TtMux( pRes, pTtTemp[0], pTtTemp[1], pTtTemp[2], p->nWords );
+        if ( fCompl ) Abc_TtNot( pRes, p->nWords );
+        return;
+    }
+    if ( If_DsdObjType(pObj) == IF_DSD_PRIME ) // function
+    {
+        word pFanins[DAU_MAX_VAR][DAU_MAX_WORD];
+        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
+            If_DsdManComputeTruth_rec( p, iFanin, pFanins[i], pPermLits, pnSupp );
+        Dau_DsdTruthCompose_rec( If_DsdObjTruth(p, pObj), pFanins, pRes, pObj->nFans, p->nWords );
+        if ( fCompl ) Abc_TtNot( pRes, p->nWords );
+        return;
+    }
+    assert( 0 );
+
+}
+word * If_DsdManComputeTruth( If_DsdMan_t * p, int iDsd, unsigned char * pPermLits )
+{
+    int nSupp = 0;
+    word * pRes = p->pTtElems[DAU_MAX_VAR];
+    If_DsdObj_t * pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iDsd) );
+    if ( iDsd == 0 )
+        Abc_TtConst0( pRes, p->nWords );
+    else if ( iDsd == 1 )
+        Abc_TtConst1( pRes, p->nWords );
+    else if ( pObj->Type == IF_DSD_VAR )
+    {
+        int iPermLit = pPermLits ? (int)pPermLits[nSupp] : Abc_Var2Lit(nSupp, 0);
+        nSupp++;
+        Abc_TtCopy( pRes, p->pTtElems[Abc_Lit2Var(iPermLit)], p->nWords, Abc_LitIsCompl(iDsd) ^ Abc_LitIsCompl(iPermLit) );
+    }
+    else
+        If_DsdManComputeTruth_rec( p, iDsd, pRes, pPermLits, &nSupp );
+    assert( nSupp == If_DsdVecLitSuppSize(&p->vObjs, iDsd) );
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedures to propagate the invertor.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_DsdManCheckInv_rec( If_DsdMan_t * p, int iLit )
+{
+    If_DsdObj_t * pObj;
+    int i, iFanin;
+    pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iLit) );
+    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
+        return 1;
+    if ( If_DsdObjType(pObj) == IF_DSD_AND || If_DsdObjType(pObj) == IF_DSD_PRIME )
+        return 0;
+    if ( If_DsdObjType(pObj) == IF_DSD_XOR )
+    {
+        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
+            if ( If_DsdManCheckInv_rec(p, iFanin) )
+                return 1;
+        return 0;
+    }
+    if ( If_DsdObjType(pObj) == IF_DSD_MUX )
+        return If_DsdManCheckInv_rec(p, pObj->pFans[1]) && If_DsdManCheckInv_rec(p, pObj->pFans[2]);
+    assert( 0 );
+    return 0;
+}
+int If_DsdManPushInv_rec( If_DsdMan_t * p, int iLit, unsigned char * pPerm )
+{
+    If_DsdObj_t * pObj;
+    int i, iFanin;
+    pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iLit) );
+    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
+        pPerm[0] = (unsigned char)Abc_LitNot((int)pPerm[0]);
+    else if ( If_DsdObjType(pObj) == IF_DSD_XOR )
+    {
+        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
+        {
+            if ( If_DsdManCheckInv_rec(p, iFanin) )
+            {
+                If_DsdManPushInv_rec( p, iFanin, pPerm );
+                break;
+            }
+            pPerm += If_DsdVecLitSuppSize(&p->vObjs, iFanin);
+        }
+    }
+    else if ( If_DsdObjType(pObj) == IF_DSD_MUX )
+    {
+        assert( If_DsdManCheckInv_rec(p, pObj->pFans[1]) && If_DsdManCheckInv_rec(p, pObj->pFans[2]) );
+        pPerm += If_DsdVecLitSuppSize(&p->vObjs, pObj->pFans[0]);
+        If_DsdManPushInv_rec(p, pObj->pFans[1], pPerm);
+        pPerm += If_DsdVecLitSuppSize(&p->vObjs, pObj->pFans[1]);
+        If_DsdManPushInv_rec(p, pObj->pFans[2], pPerm);
+    }
+    else assert( 0 );
+    return 1;
+}
+int If_DsdManPushInv( If_DsdMan_t * p, int iLit, unsigned char * pPerm )
+{
+    if ( Abc_LitIsCompl(iLit) && If_DsdManCheckInv_rec(p, iLit) )
+        return If_DsdManPushInv_rec( p, iLit, pPerm );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DSD operation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_DsdManComputeFirstArray( If_DsdMan_t * p, int * pLits, int nLits, int * pFirsts )
+{
+    int i, nSSize = 0;
+    for ( i = 0; i < nLits; i++ )
+    {
+        pFirsts[i] = nSSize;
+        nSSize += If_DsdVecLitSuppSize(&p->vObjs, pLits[i]);
+    }
+    return nSSize;
+}
+int If_DsdManComputeFirst( If_DsdMan_t * p, If_DsdObj_t * pObj, int * pFirsts )
+{
+    return If_DsdManComputeFirstArray( p, (int *)pObj->pFans, pObj->nFans, pFirsts );
+}
+int If_DsdManOperation( If_DsdMan_t * p, int Type, int * pLits, int nLits, unsigned char * pPerm, word * pTruth )
+{
+    If_DsdObj_t * pObj, * pFanin;
+    unsigned char pPermNew[DAU_MAX_VAR], * pPermStart = pPerm;
+    int nChildren = 0, pChildren[DAU_MAX_VAR], pBegEnd[DAU_MAX_VAR];
+    int i, k, j, Id, iFanin, fCompl = 0, nSSize = 0;
+    if ( Type == IF_DSD_AND || Type == IF_DSD_XOR )
+    {
+        for ( k = 0; k < nLits; k++ )
+        {
+            if ( Type == IF_DSD_XOR && Abc_LitIsCompl(pLits[k]) )
+            {
+                pLits[k] = Abc_LitNot(pLits[k]);
+                fCompl ^= 1;
+            }
+            pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(pLits[k]) );
+            if ( Type == If_DsdObjType(pObj) && (Type == IF_DSD_XOR || !Abc_LitIsCompl(pLits[k])) )
+            {
+                If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
+                {
+                    assert( Type == IF_DSD_AND || !Abc_LitIsCompl(iFanin) );
+                    pChildren[nChildren] = iFanin;
+                    pBegEnd[nChildren++] = (nSSize << 16) | (nSSize + If_DsdVecLitSuppSize(&p->vObjs, iFanin));
+                    nSSize += If_DsdVecLitSuppSize(&p->vObjs, iFanin);
+                }
+            }
+            else
+            {
+                pChildren[nChildren] = Abc_LitNotCond( pLits[k], If_DsdManPushInv(p, pLits[k], pPermStart) );
+                pBegEnd[nChildren++] = (nSSize << 16) | (nSSize + If_DsdObjSuppSize(pObj));
+                nSSize += If_DsdObjSuppSize(pObj);
+            }
+            pPermStart += If_DsdObjSuppSize(pObj);
+        }
+        If_DsdObjSort( p, &p->vObjs, pChildren, nChildren, pBegEnd );
+        // create permutation
+        for ( j = i = 0; i < nChildren; i++ )
+            for ( k = (pBegEnd[i] >> 16); k < (pBegEnd[i] & 0xFF); k++ )
+                pPermNew[j++] = pPerm[k];
+        assert( j == nSSize );
+        for ( j = 0; j < nSSize; j++ )
+            pPerm[j] = pPermNew[j];
+    }
+    else if ( Type == IF_DSD_MUX )
+    {
+        int RetValue;
+        assert( nLits == 3 );
+        for ( k = 0; k < nLits; k++ )
+        {
+            pFanin = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(pLits[k]) );
+            pLits[k] = Abc_LitNotCond( pLits[k], If_DsdManPushInv(p, pLits[k], pPermStart) );
+            pPermStart += pFanin->nSupp;
+        }
+        RetValue = If_DsdObjCompare( p, &p->vObjs, pLits[1], pLits[2] );
+        if ( RetValue == 1 || (RetValue == 0 && Abc_LitIsCompl(pLits[0])) )
+        {
+            int nSupp0 = If_DsdVecLitSuppSize( &p->vObjs, pLits[0] );
+            int nSupp1 = If_DsdVecLitSuppSize( &p->vObjs, pLits[1] );
+            int nSupp2 = If_DsdVecLitSuppSize( &p->vObjs, pLits[2] );
+            pLits[0] = Abc_LitNot(pLits[0]);
+            ABC_SWAP( int, pLits[1], pLits[2] );
+            for ( j = k = 0; k < nSupp0; k++ )
+                pPermNew[j++] = pPerm[k];
+            for ( k = 0; k < nSupp2; k++ )
+                pPermNew[j++] = pPerm[nSupp0 + nSupp1 + k];
+            for ( k = 0; k < nSupp1; k++ )
+                pPermNew[j++] = pPerm[nSupp0 + k];
+            for ( j = 0; j < nSupp0 + nSupp1 + nSupp2; j++ )
+                pPerm[j] = pPermNew[j];
+        }
+        if ( Abc_LitIsCompl(pLits[1]) )
+        {
+            pLits[1] = Abc_LitNot(pLits[1]);
+            pLits[2] = Abc_LitNot(pLits[2]);
+            fCompl ^= 1;
+        }
+        pPermStart = pPerm;
+        for ( k = 0; k < nLits; k++ )
+        {
+            pFanin = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(pLits[k]) );
+            pChildren[nChildren++] = Abc_LitNotCond( pLits[k], If_DsdManPushInv(p, pLits[k], pPermStart) );
+            pPermStart += pFanin->nSupp;
+        }
+    }
+    else if ( Type == IF_DSD_PRIME )
+    {
+        char pCanonPerm[DAU_MAX_VAR];
+        int i, uCanonPhase, pFirsts[DAU_MAX_VAR];
+        uCanonPhase = Abc_TtCanonicize( pTruth, nLits, pCanonPerm );
+        fCompl = ((uCanonPhase >> nLits) & 1);
+        nSSize = If_DsdManComputeFirstArray( p, pLits, nLits, pFirsts );
+        for ( j = i = 0; i < nLits; i++ )
+        {
+            int iLitNew = Abc_LitNotCond( pLits[(int)pCanonPerm[i]], ((uCanonPhase>>i)&1) );
+            pFanin = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iLitNew) );
+            pPermStart = pPerm + pFirsts[(int)pCanonPerm[i]];
+            pChildren[nChildren++] = Abc_LitNotCond( iLitNew, If_DsdManPushInv(p, iLitNew, pPermStart) );
+            for ( k = 0; k < (int)pFanin->nSupp; k++ )            
+                pPermNew[j++] = pPermStart[k];
+        }
+        assert( j == nSSize );
+        for ( j = 0; j < nSSize; j++ )
+            pPerm[j] = pPermNew[j];
+        Abc_TtStretch6( pTruth, nLits, p->nVars );
+    }
+    else assert( 0 );
+    // create new graph
+    Id = If_DsdObjFindOrAdd( p, Type, pChildren, nChildren, pTruth );
+    return Abc_Var2Lit( Id, fCompl );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creating DSD network from SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void If_DsdMergeMatches( char * pDsd, int * pMatches )
+{
+    int pNested[DAU_MAX_VAR];
+    int i, nNested = 0;
+    for ( i = 0; pDsd[i]; i++ )
+    {
+        pMatches[i] = 0;
+        if ( pDsd[i] == '(' || pDsd[i] == '[' || pDsd[i] == '<' || pDsd[i] == '{' )
+            pNested[nNested++] = i;
+        else if ( pDsd[i] == ')' || pDsd[i] == ']' || pDsd[i] == '>' || pDsd[i] == '}' )
+            pMatches[pNested[--nNested]] = i;
+        assert( nNested < DAU_MAX_VAR );
+    }
+    assert( nNested == 0 );
+}
+int If_DsdManAddDsd_rec( char * pStr, char ** p, int * pMatches, If_DsdMan_t * pMan, word * pTruth, unsigned char * pPerm, int * pnSupp )
+{
+    unsigned char * pPermStart = pPerm + *pnSupp;
+    int iRes = -1, fCompl = 0;
+    if ( **p == '!' )
+    {
+        fCompl = 1;
+        (*p)++;
+    }
+    if ( **p >= 'a' && **p <= 'z' ) // var
+    {
+        pPerm[(*pnSupp)++] = Abc_Var2Lit( **p - 'a', fCompl );
+        return 2;
+    }
+    if ( **p == '(' || **p == '[' || **p == '<' || **p == '{' ) // and/or/xor
+    {
+        int Type, nLits = 0, pLits[DAU_MAX_VAR];
+        char * q = pStr + pMatches[ *p - pStr ];
+        if ( **p == '(' )
+            Type = DAU_DSD_AND;
+        else if ( **p == '[' )
+            Type = DAU_DSD_XOR;
+        else if ( **p == '<' )
+            Type = DAU_DSD_MUX;
+        else if ( **p == '{' )
+            Type = DAU_DSD_PRIME;
+        else assert( 0 );
+        assert( *q == **p + 1 + (**p != '(') );
+        for ( (*p)++; *p < q; (*p)++ )
+            pLits[nLits++] = If_DsdManAddDsd_rec( pStr, p, pMatches, pMan, pTruth, pPerm, pnSupp );
+        assert( *p == q );
+        iRes = If_DsdManOperation( pMan, Type, pLits, nLits, pPermStart, pTruth );
+        return Abc_LitNotCond( iRes, fCompl );
+    }
+    if ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') )
+    {
+        word pFunc[DAU_MAX_WORD];
+        int nLits = 0, pLits[DAU_MAX_VAR];
+        char * q;
+        int i, nVarsF = Abc_TtReadHex( pFunc, *p );
+        *p += Abc_TtHexDigitNum( nVarsF );
+        q = pStr + pMatches[ *p - pStr ];
+        assert( **p == '{' && *q == '}' );
+        for ( i = 0, (*p)++; *p < q; (*p)++, i++ )
+            pLits[nLits++] = If_DsdManAddDsd_rec( pStr, p, pMatches, pMan, pTruth, pPerm, pnSupp );
+        assert( i == nVarsF );
+        assert( *p == q );
+        iRes = If_DsdManOperation( pMan, DAU_DSD_PRIME, pLits, nLits, pPermStart, pFunc );
+        return Abc_LitNotCond( iRes, fCompl );
+    }
+    assert( 0 );
+    return -1;
+}
+int If_DsdManAddDsd( If_DsdMan_t * p, char * pDsd, word * pTruth, unsigned char * pPerm, int * pnSupp )
+{
+    int iRes = -1, fCompl = 0;
+    if ( *pDsd == '!' )
+         pDsd++, fCompl = 1;
+    if ( Dau_DsdIsConst0(pDsd) )
+        iRes = 0;
+    else if ( Dau_DsdIsConst1(pDsd) )
+        iRes = 1;
+    else if ( Dau_DsdIsVar(pDsd) )
+    {
+        pPerm[(*pnSupp)++] = Dau_DsdReadVar(pDsd);
+        iRes = 2;
+    }
+    else
+    {
+        int pMatches[DAU_MAX_STR];
+        If_DsdMergeMatches( pDsd, pMatches );
+        iRes = If_DsdManAddDsd_rec( pDsd, &pDsd, pMatches, p, pTruth, pPerm, pnSupp );
+    }
+    return Abc_LitNotCond( iRes, fCompl );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if XY-decomposability holds to this LUT size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+// create signature of the support of the node
+unsigned If_DsdSign_rec( If_DsdMan_t * p, If_DsdObj_t * pObj, int * pnSupp )
+{
+    unsigned uSign = 0; int i;
+    If_DsdObj_t * pFanin;
+    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
+        return (1 << (2*(*pnSupp)++));
+    If_DsdObjForEachFanin( &p->vObjs, pObj, pFanin, i )
+        uSign |= If_DsdSign_rec( p, pFanin, pnSupp );
+    return uSign;
+}
+unsigned If_DsdSign( If_DsdMan_t * p, If_DsdObj_t * pObj, int iFan, int iFirst, int fShared )
+{
+    If_DsdObj_t * pFanin = If_DsdObjFanin( &p->vObjs, pObj, iFan );
+    unsigned uSign = If_DsdSign_rec( p, pFanin, &iFirst );
+    return fShared ? (uSign << 1) | uSign : uSign;
+}
+// collect supports of the node
+void If_DsdManGetSuppSizes( If_DsdMan_t * p, If_DsdObj_t * pObj, int * pSSizes )
+{
+    If_DsdObj_t * pFanin; int i;
+    If_DsdObjForEachFanin( &p->vObjs, pObj, pFanin, i )
+        pSSizes[i] = If_DsdObjSuppSize(pFanin);    
+}
+// checks if there is a way to package some fanins 
+unsigned If_DsdManCheckAndXor( If_DsdMan_t * p, int iFirst, unsigned uMaskNot, If_DsdObj_t * pObj, int nSuppAll, int LutSize, int fDerive, int fVerbose )
+{
+    int i[6], LimitOut, SizeIn, SizeOut, pSSizes[DAU_MAX_VAR];
+    int nFans = If_DsdObjFaninNum(pObj), pFirsts[DAU_MAX_VAR];
+    unsigned uRes;
+    assert( pObj->nFans > 2 );
+    assert( If_DsdObjSuppSize(pObj) > LutSize );
+    If_DsdManGetSuppSizes( p, pObj, pSSizes );
+    LimitOut = LutSize - (nSuppAll - pObj->nSupp + 1);
+    assert( LimitOut < LutSize );
+    for ( i[0] = 0;      i[0] < nFans; i[0]++ )
+    for ( i[1] = i[0]+1; i[1] < nFans; i[1]++ )
+    {
+        SizeIn = pSSizes[i[0]] + pSSizes[i[1]];
+        SizeOut = pObj->nSupp - SizeIn;
+        if ( SizeIn > LutSize || SizeOut > LimitOut )
+            continue;
+        if ( !fDerive )
+            return ~0;
+        If_DsdManComputeFirst( p, pObj, pFirsts );
+        uRes = If_DsdSign(p, pObj, i[0], iFirst + pFirsts[i[0]], 0) | 
+               If_DsdSign(p, pObj, i[1], iFirst + pFirsts[i[1]], 0);
+        if ( uRes & uMaskNot )
+            continue;
+        return uRes;
+    }
+    if ( pObj->nFans == 3 )
+        return 0;
+    for ( i[0] = 0;      i[0] < nFans; i[0]++ )
+    for ( i[1] = i[0]+1; i[1] < nFans; i[1]++ )
+    for ( i[2] = i[1]+1; i[2] < nFans; i[2]++ )
+    {
+        SizeIn = pSSizes[i[0]] + pSSizes[i[1]] + pSSizes[i[2]];
+        SizeOut = pObj->nSupp - SizeIn;
+        if ( SizeIn > LutSize || SizeOut > LimitOut )
+            continue;
+        if ( !fDerive )
+            return ~0;
+        If_DsdManComputeFirst( p, pObj, pFirsts );
+        uRes = If_DsdSign(p, pObj, i[0], iFirst + pFirsts[i[0]], 0) | 
+               If_DsdSign(p, pObj, i[1], iFirst + pFirsts[i[1]], 0) | 
+               If_DsdSign(p, pObj, i[2], iFirst + pFirsts[i[2]], 0);
+        if ( uRes & uMaskNot )
+            continue;
+        return uRes;
+    }
+    if ( pObj->nFans == 4 )
+        return 0;
+    for ( i[0] = 0;      i[0] < nFans; i[0]++ )
+    for ( i[1] = i[0]+1; i[1] < nFans; i[1]++ )
+    for ( i[2] = i[1]+1; i[2] < nFans; i[2]++ )
+    for ( i[3] = i[2]+1; i[3] < nFans; i[3]++ )
+    {
+        SizeIn = pSSizes[i[0]] + pSSizes[i[1]] + pSSizes[i[2]] + pSSizes[i[3]];
+        SizeOut = pObj->nSupp - SizeIn;
+        if ( SizeIn > LutSize || SizeOut > LimitOut )
+            continue;
+        if ( !fDerive )
+            return ~0;
+        If_DsdManComputeFirst( p, pObj, pFirsts );
+        uRes = If_DsdSign(p, pObj, i[0], iFirst + pFirsts[i[0]], 0) | 
+               If_DsdSign(p, pObj, i[1], iFirst + pFirsts[i[1]], 0) | 
+               If_DsdSign(p, pObj, i[2], iFirst + pFirsts[i[2]], 0) | 
+               If_DsdSign(p, pObj, i[3], iFirst + pFirsts[i[3]], 0);
+        if ( uRes & uMaskNot )
+            continue;
+        return uRes;
+    }
+    return 0;
+}
+// checks if there is a way to package some fanins 
+unsigned If_DsdManCheckMux( If_DsdMan_t * p, int iFirst, unsigned uMaskNot, If_DsdObj_t * pObj, int nSuppAll, int LutSize, int fDerive, int fVerbose )
+{
+    int LimitOut, SizeIn, SizeOut, pSSizes[DAU_MAX_VAR], pFirsts[DAU_MAX_VAR];
+    unsigned uRes;
+    assert( If_DsdObjFaninNum(pObj) == 3 );
+    assert( If_DsdObjSuppSize(pObj) > LutSize );
+    If_DsdManGetSuppSizes( p, pObj, pSSizes );
+    LimitOut = LutSize - (nSuppAll - If_DsdObjSuppSize(pObj) + 1);
+    assert( LimitOut < LutSize );
+    // first input
+    SizeIn = pSSizes[0] + pSSizes[1];
+    SizeOut = pSSizes[0] + pSSizes[2] + 1;
+    if ( SizeIn <= LutSize && SizeOut <= LimitOut )
+    {
+        if ( !fDerive )
+            return ~0;
+        If_DsdManComputeFirst( p, pObj, pFirsts );
+        uRes = If_DsdSign(p, pObj, 0, iFirst + pFirsts[0], 1) | If_DsdSign(p, pObj, 1, iFirst + pFirsts[1], 0);
+        if ( (uRes & uMaskNot) == 0 )
+            return uRes;
+    }
+    // second input
+    SizeIn = pSSizes[0] + pSSizes[2];
+    SizeOut = pSSizes[0] + pSSizes[1] + 1;
+    if ( SizeIn <= LutSize && SizeOut <= LimitOut )
+    {
+        if ( !fDerive )
+            return ~0;
+        If_DsdManComputeFirst( p, pObj, pFirsts );
+        uRes = If_DsdSign(p, pObj, 0, iFirst + pFirsts[0], 1) | If_DsdSign(p, pObj, 2, iFirst + pFirsts[2], 0);
+        if ( (uRes & uMaskNot) == 0 )
+            return uRes;
+    }
+    return 0;
+}
+// checks if there is a way to package some fanins 
+unsigned If_DsdManCheckPrime( If_DsdMan_t * p, int iFirst, unsigned uMaskNot, If_DsdObj_t * pObj, int nSuppAll, int LutSize, int fDerive, int fVerbose )
+{
+    int i, v, set, LimitOut, SizeIn, SizeOut, pSSizes[DAU_MAX_VAR], pFirsts[DAU_MAX_VAR];
+    int truthId = If_DsdObjTruthId(p, pObj);
+    int nFans = If_DsdObjFaninNum(pObj);
+    Vec_Int_t * vSets = (Vec_Int_t *)Vec_PtrEntry(p->vTtDecs[pObj->nFans], truthId);
+if ( fVerbose )
+printf( "\n" );
+if ( fVerbose )
+Dau_DecPrintSets( vSets, nFans );
+    assert( If_DsdObjFaninNum(pObj) > 2 );
+    assert( If_DsdObjSuppSize(pObj) > LutSize );
+    If_DsdManGetSuppSizes( p, pObj, pSSizes );
+    LimitOut = LutSize - (nSuppAll - If_DsdObjSuppSize(pObj) + 1);
+    assert( LimitOut < LutSize );
+    Vec_IntForEachEntry( vSets, set, i )
+    {
+        SizeIn = SizeOut = 0;
+        for ( v = 0; v < nFans; v++ )
+        {
+            int Value = ((set >> (v << 1)) & 3);
+            if ( Value == 0 )
+                SizeOut += pSSizes[v];
+            else if ( Value == 1 )
+                SizeIn += pSSizes[v];
+            else if ( Value == 3 )
+            {
+                SizeIn += pSSizes[v];
+                SizeOut += pSSizes[v];
+            }
+            else assert( 0 );
+            if ( SizeIn > LutSize || SizeOut > LimitOut )
+                break;
+        }
+        if ( v == nFans )
+        {
+            unsigned uRes = 0;
+            if ( !fDerive )
+                return ~0;
+            If_DsdManComputeFirst( p, pObj, pFirsts );
+            for ( v = 0; v < nFans; v++ )
+            {
+                int Value = ((set >> (v << 1)) & 3);
+                if ( Value == 0 )
+                {}
+                else if ( Value == 1 )
+                    uRes |= If_DsdSign(p, pObj, v, iFirst + pFirsts[v], 0);
+                else if ( Value == 3 )
+                    uRes |= If_DsdSign(p, pObj, v, iFirst + pFirsts[v], 1);
+                else assert( 0 );
+            }
+            if ( uRes & uMaskNot )
+                continue;
+            return uRes;
+        }
+    }
+    return 0;
+}
+unsigned If_DsdManCheckXY_int( If_DsdMan_t * p, int iDsd, int LutSize, int fDerive, unsigned uMaskNot, int fVerbose )
+{
+    If_DsdObj_t * pObj, * pTemp; 
+    int i, Mask, iFirst;
+    unsigned uRes;
+    pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iDsd) );
+    if ( fVerbose )
+    If_DsdManPrintOne( stdout, p, Abc_Lit2Var(iDsd), NULL, 0 );
+    if ( If_DsdObjSuppSize(pObj) <= LutSize )
+    {
+        if ( fVerbose )
+        printf( "    Trivial\n" );
+        return ~0;
+    }
+    If_DsdManCollect( p, pObj->Id, p->vTemp1, p->vTemp2 );
+    If_DsdVecForEachObjVec( p->vTemp1, &p->vObjs, pTemp, i )
+        if ( If_DsdObjSuppSize(pTemp) <= LutSize && If_DsdObjSuppSize(pObj) - If_DsdObjSuppSize(pTemp) <= LutSize - 1 )
+        {
+            if ( fVerbose )
+            printf( "    Dec using node " );
+            if ( fVerbose )
+            If_DsdManPrintOne( stdout, p, pTemp->Id, NULL, 1 );
+            iFirst = Vec_IntEntry(p->vTemp2, i);
+            uRes = If_DsdSign_rec(p, pTemp, &iFirst);
+            if ( uRes & uMaskNot )
+                continue;
+            return uRes;
+        }
+    If_DsdVecForEachObjVec( p->vTemp1, &p->vObjs, pTemp, i )
+        if ( (If_DsdObjType(pTemp) == IF_DSD_AND || If_DsdObjType(pTemp) == IF_DSD_XOR) && If_DsdObjFaninNum(pTemp) > 2 && If_DsdObjSuppSize(pTemp) > LutSize )
+        {
+            if ( (Mask = If_DsdManCheckAndXor(p, Vec_IntEntry(p->vTemp2, i), uMaskNot, pTemp, If_DsdObjSuppSize(pObj), LutSize, fDerive, fVerbose)) )
+            {
+                if ( fVerbose )
+                printf( "    " );
+                if ( fVerbose )
+                Abc_TtPrintBinary( (word *)&Mask, 4 ); 
+                if ( fVerbose )
+                printf( "    Using multi-input AND/XOR node\n" );
+                return Mask;
+            }
+        }
+    If_DsdVecForEachObjVec( p->vTemp1, &p->vObjs, pTemp, i )
+        if ( If_DsdObjType(pTemp) == IF_DSD_MUX && If_DsdObjSuppSize(pTemp) > LutSize )
+        {
+            if ( (Mask = If_DsdManCheckMux(p, Vec_IntEntry(p->vTemp2, i), uMaskNot, pTemp, If_DsdObjSuppSize(pObj), LutSize, fDerive, fVerbose)) )
+            {
+                if ( fVerbose )
+                printf( "    " );
+                if ( fVerbose )
+                Abc_TtPrintBinary( (word *)&Mask, 4 ); 
+                if ( fVerbose )
+                printf( "    Using multi-input MUX node\n" );
+                return Mask;
+            }
+        }
+    If_DsdVecForEachObjVec( p->vTemp1, &p->vObjs, pTemp, i )
+        if ( If_DsdObjType(pTemp) == IF_DSD_PRIME && If_DsdObjSuppSize(pTemp) > LutSize )
+        {
+            if ( (Mask = If_DsdManCheckPrime(p, Vec_IntEntry(p->vTemp2, i), uMaskNot, pTemp, If_DsdObjSuppSize(pObj), LutSize, fDerive, fVerbose)) )
+            {
+                if ( fVerbose )
+                printf( "    " );
+                if ( fVerbose )
+                Dau_DecPrintSet( Mask, If_DsdObjFaninNum(pTemp), 0 );
+                if ( fVerbose )
+                printf( "    Using prime node\n" );
+                return Mask;
+            }
+        }
+    if ( fVerbose )
+    printf( "    UNDEC\n" );
+//    If_DsdManPrintOne( stdout, p, Abc_Lit2Var(iDsd), NULL, 1 );
+    return 0;
+}
+unsigned If_DsdManCheckXY( If_DsdMan_t * p, int iDsd, int LutSize, int fDerive, unsigned uMaskNot, int fHighEffort, int fVerbose )
+{
+    unsigned uSet = If_DsdManCheckXY_int( p, iDsd, LutSize, fDerive, uMaskNot, fVerbose );
+    if ( uSet == 0 && fHighEffort )
+    {
+//        abctime clk = Abc_Clock();
+        int nVars = If_DsdVecLitSuppSize( &p->vObjs, iDsd );
+        word * pRes = If_DsdManComputeTruth( p, iDsd, NULL );
+        uSet = If_ManSatCheckXYall( p->pSat, LutSize, pRes, nVars, p->vTemp1 );
+        if ( uSet )
+        {
+//            If_DsdManPrintOne( stdout, p, Abc_Lit2Var(iDsd), NULL, 1 );
+//            Dau_DecPrintSet( uSet, nVars, 1 );
+        }
+//        p->timeCheck2 += Abc_Clock() - clk;
+    }
+    return uSet;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks existence of decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned If_DsdManCheckXYZ( If_DsdMan_t * p, int iDsd, int LutSize, int fDerive, int fVerbose ) 
+{
+    return ~0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add the function to the DSD manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_DsdManCompute( If_DsdMan_t * p, word * pTruth, int nLeaves, unsigned char * pPerm, char * pLutStruct )
+{
+    word pCopy[DAU_MAX_WORD], * pRes;
+    char pDsd[DAU_MAX_STR];
+    int iDsd, nSizeNonDec, nSupp = 0;
+    int nWords = Abc_TtWordNum(nLeaves);
+//    abctime clk = 0;
+    assert( nLeaves <= DAU_MAX_VAR );
+    Abc_TtCopy( pCopy, pTruth, nWords, 0 );
+//clk = Abc_Clock();
+    nSizeNonDec = Dau_DsdDecompose( pCopy, nLeaves, 0, 1, pDsd );
+//p->timeDsd += Abc_Clock() - clk;
+    if ( nSizeNonDec > 0 )
+        Abc_TtStretch6( pCopy, nSizeNonDec, p->nVars );
+    memset( pPerm, 0xFF, nLeaves );
+//clk = Abc_Clock();
+    iDsd = If_DsdManAddDsd( p, pDsd, pCopy, pPerm, &nSupp );
+//p->timeCanon += Abc_Clock() - clk;
+    assert( nSupp == nLeaves );
+    // verify the result
+//clk = Abc_Clock();
+    pRes = If_DsdManComputeTruth( p, iDsd, pPerm );
+//p->timeVerify += Abc_Clock() - clk;
+    if ( !Abc_TtEqual(pRes, pTruth, nWords) )
+    {
+//        If_DsdManPrint( p, NULL );
+        printf( "\n" );
+        printf( "Verification failed!\n" );
+        printf( "%s\n", pDsd );
+        Dau_DsdPrintFromTruth( pTruth, nLeaves );
+        Dau_DsdPrintFromTruth( pRes, nLeaves );
+        If_DsdManPrintOne( stdout, p, Abc_Lit2Var(iDsd), pPerm, 1 );
+        printf( "\n" );
+    }
+    If_DsdVecObjIncRef( &p->vObjs, Abc_Lit2Var(iDsd) );
+    assert( If_DsdVecLitSuppSize(&p->vObjs, iDsd) == nLeaves );
+    return iDsd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks existence of decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_DsdManTest()
+{
+    Vec_Int_t * vSets;
+    word t = 0x5277;
+    t = Abc_Tt6Stretch( t, 4 );
+//    word t = 0xD9D900D900D900001010001000100000;
+    vSets = Dau_DecFindSets( &t, 6 );
+    Vec_IntFree( vSets );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compute pin delays.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutDsdBalancePinDelays_rec( If_DsdMan_t * p, int Id, int * pTimes, word * pRes, int * pnSupp, int nSuppAll, char * pPermLits )
+{
+    If_DsdObj_t * pObj = If_DsdVecObj( &p->vObjs, Id );
+    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
+    {
+        int iCutVar = Abc_Lit2Var(pPermLits[(*pnSupp)++]);
+        *pRes = If_CutPinDelayInit(iCutVar);
+        return pTimes[iCutVar];
+    }
+    if ( If_DsdObjType(pObj) == IF_DSD_MUX )
+    {
+        word pFaninRes[3], Res0, Res1;
+        int i, iFanin, Delays[3];
+        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
+            Delays[i] = If_CutDsdBalancePinDelays_rec( p, Abc_Lit2Var(iFanin), pTimes, pFaninRes+i, pnSupp, nSuppAll, pPermLits );
+        Res0 = If_CutPinDelayMax( pFaninRes[0], pFaninRes[1], nSuppAll, 1 );
+        Res1 = If_CutPinDelayMax( pFaninRes[0], pFaninRes[2], nSuppAll, 1 );
+        *pRes = If_CutPinDelayMax( Res0, Res1, nSuppAll, 1 );
+        return 2 + Abc_MaxInt(Delays[0], Abc_MaxInt(Delays[1], Delays[2]));
+    }
+    if ( If_DsdObjType(pObj) == IF_DSD_PRIME )
+    {
+        word pFaninRes[IF_MAX_FUNC_LUTSIZE];
+        int i, iFanin, Delays[IF_MAX_FUNC_LUTSIZE];
+        Vec_Int_t * vCover = Vec_WecEntry( p->vIsops[pObj->nFans], If_DsdObjTruthId(p, pObj) );
+        assert( Vec_IntSize(vCover) > 0 );
+        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
+            Delays[i] = If_CutDsdBalancePinDelays_rec( p, Abc_Lit2Var(iFanin), pTimes, pFaninRes+i, pnSupp, nSuppAll, pPermLits );
+        return If_CutSopBalancePinDelaysInt( vCover, Delays, pFaninRes, nSuppAll, pRes );
+    }
+    assert( If_DsdObjType(pObj) == IF_DSD_AND || If_DsdObjType(pObj) == IF_DSD_XOR );
+    {
+        word pFaninRes[IF_MAX_FUNC_LUTSIZE];
+        int i, iFanin, Delay, Result = 0;
+        int fXor = (If_DsdObjType(pObj) == IF_DSD_XOR);
+        int nCounter = 0, pCounter[IF_MAX_FUNC_LUTSIZE];
+        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
+        {
+            Delay = If_CutDsdBalancePinDelays_rec( p, Abc_Lit2Var(iFanin), pTimes, pFaninRes+i, pnSupp, nSuppAll, pPermLits );
+            Result = If_LogCounterPinDelays( pCounter, &nCounter, pFaninRes, Delay, pFaninRes[i], nSuppAll, fXor );
+        }
+        assert( nCounter > 0 );
+        if ( fXor )
+            Result = If_LogCounterDelayXor( pCounter, nCounter ); // estimation
+        *pRes = If_LogPinDelaysMulti( pFaninRes, nCounter, nSuppAll, fXor );
+        return Result;
+    }
+}
+int If_CutDsdBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm )
+{
+    if ( pCut->nLeaves == 0 ) // const
+        return 0;
+    if ( pCut->nLeaves == 1 ) // variable
+    {
+        pPerm[0] = 0;
+        return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay;
+    }
+    else
+    {
+        word Result = 0;
+        int i, Delay, nSupp = 0, pTimes[IF_MAX_FUNC_LUTSIZE];
+        for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+            pTimes[i] = (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; 
+        Delay = If_CutDsdBalancePinDelays_rec( p->pIfDsdMan, Abc_Lit2Var(If_CutDsdLit(p, pCut)), pTimes, &Result, &nSupp, If_CutLeaveNum(pCut), If_CutDsdPerm(p, pCut) );
+        assert( nSupp == If_CutLeaveNum(pCut) );
+        If_CutPinDelayTranslate( Result, If_CutLeaveNum(pCut), pPerm );
+        return Delay;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluate delay using DSD balancing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutDsdBalanceEval_rec( If_DsdMan_t * p, int Id, int * pTimes, int * pnSupp, Vec_Int_t * vAig, int * piLit, int nSuppAll, int * pArea, char * pPermLits )
+{
+    If_DsdObj_t * pObj = If_DsdVecObj( &p->vObjs, Id );
+    if ( If_DsdObjType(pObj) == IF_DSD_VAR )
+    {
+        int iCutVar = Abc_Lit2Var( pPermLits[*pnSupp] );
+        if ( vAig )
+            *piLit = Abc_Var2Lit( iCutVar, Abc_LitIsCompl(pPermLits[*pnSupp]) );
+        (*pnSupp)++;
+        return pTimes[iCutVar];
+    }
+    if ( If_DsdObjType(pObj) == IF_DSD_MUX )
+    {
+        int i, iFanin, Delays[3], pFaninLits[3];
+        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
+        {
+            Delays[i] = If_CutDsdBalanceEval_rec( p, Abc_Lit2Var(iFanin), pTimes, pnSupp, vAig, pFaninLits+i, nSuppAll, pArea, pPermLits );
+            if ( Delays[i] == -1 )
+                return -1;
+            pFaninLits[i] = Abc_LitNotCond( pFaninLits[i], Abc_LitIsCompl(iFanin) );
+        }
+        if ( vAig )
+            *piLit = If_LogCreateMux( vAig, pFaninLits[0], pFaninLits[1], pFaninLits[2], nSuppAll );
+        else
+            *pArea += 3;
+        return 2 + Abc_MaxInt(Delays[0], Abc_MaxInt(Delays[1], Delays[2]));
+    }
+    if ( If_DsdObjType(pObj) == IF_DSD_PRIME )
+    {
+        int i, iFanin, Delays[IF_MAX_FUNC_LUTSIZE], pFaninLits[IF_MAX_FUNC_LUTSIZE];
+        Vec_Int_t * vCover = Vec_WecEntry( p->vIsops[pObj->nFans], If_DsdObjTruthId(p, pObj) );
+        if ( Vec_IntSize(vCover) == 0 )
+            return -1;
+        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
+        {
+            Delays[i] = If_CutDsdBalanceEval_rec( p, Abc_Lit2Var(iFanin), pTimes, pnSupp, vAig, pFaninLits+i, nSuppAll, pArea, pPermLits );
+            if ( Delays[i] == -1 )
+                return -1;
+            pFaninLits[i] = Abc_LitNotCond( pFaninLits[i], Abc_LitIsCompl(iFanin) );
+        }
+        return If_CutSopBalanceEvalInt( vCover, Delays, pFaninLits, vAig, piLit, nSuppAll, pArea );
+    }
+    assert( If_DsdObjType(pObj) == IF_DSD_AND || If_DsdObjType(pObj) == IF_DSD_XOR );
+    {
+        int i, iFanin, Delay, Result = 0;
+        int fXor = (If_DsdObjType(pObj) == IF_DSD_XOR);
+        int nCounter = 0, pCounter[IF_MAX_FUNC_LUTSIZE], pFaninLits[IF_MAX_FUNC_LUTSIZE];
+        If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i )
+        {
+            Delay = If_CutDsdBalanceEval_rec( p, Abc_Lit2Var(iFanin), pTimes, pnSupp, vAig, pFaninLits+i, nSuppAll, pArea, pPermLits );
+            if ( Delay == -1 )
+                return -1;
+            pFaninLits[i] = Abc_LitNotCond( pFaninLits[i], Abc_LitIsCompl(iFanin) );
+            Result = If_LogCounterAddAig( pCounter, &nCounter, pFaninLits, Delay, pFaninLits[i], vAig, nSuppAll, fXor );
+        }
+        assert( nCounter > 0 );
+        if ( fXor )
+            Result = If_LogCounterDelayXor( pCounter, nCounter ); // estimation
+        if ( vAig )
+            *piLit = If_LogCreateAndXorMulti( vAig, pFaninLits, nCounter, nSuppAll, fXor );
+        else
+            *pArea += (pObj->nFans - 1) * (1 + 2 * fXor);
+        return Result;
+    }
+}
+int If_CutDsdBalanceEvalInt( If_DsdMan_t * p, int iDsd, int * pTimes, Vec_Int_t * vAig, int * pArea, char * pPermLits )
+{
+    int nSupp = 0, iLit = 0;
+    int nSuppAll = If_DsdVecLitSuppSize( &p->vObjs, iDsd );
+    int Res = If_CutDsdBalanceEval_rec( p, Abc_Lit2Var(iDsd), pTimes, &nSupp, vAig, &iLit, nSuppAll, pArea, pPermLits );
+    if ( Res == -1 )
+        return -1;
+    assert( nSupp == nSuppAll );
+    assert( vAig == NULL || Abc_Lit2Var(iLit) == nSupp + Abc_Lit2Var(Vec_IntSize(vAig)) - 1 );
+    if ( vAig )
+        Vec_IntPush( vAig, Abc_LitIsCompl(iLit) ^ Abc_LitIsCompl(iDsd) );
+    assert( vAig == NULL || (Vec_IntSize(vAig) & 1) );
+    return Res;
+}
+int If_CutDsdBalanceEval( If_Man_t * p, If_Cut_t * pCut, Vec_Int_t * vAig )
+{
+    pCut->fUser = 1;
+    if ( vAig )
+        Vec_IntClear( vAig );
+    if ( pCut->nLeaves == 0 ) // const
+    {
+        assert( Abc_Lit2Var(If_CutDsdLit(p, pCut)) == 0 );
+        if ( vAig )
+            Vec_IntPush( vAig, Abc_LitIsCompl(If_CutDsdLit(p, pCut)) );
+        pCut->Cost = 0;
+        return 0;
+    }
+    if ( pCut->nLeaves == 1 ) // variable
+    {
+        assert( Abc_Lit2Var(If_CutDsdLit(p, pCut)) == 1 );
+        if ( vAig )
+            Vec_IntPush( vAig, 0 );
+        if ( vAig )
+            Vec_IntPush( vAig, Abc_LitIsCompl(If_CutDsdLit(p, pCut)) );
+        pCut->Cost = 0;
+        return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay;
+    }
+    else
+    {
+        int i, pTimes[IF_MAX_FUNC_LUTSIZE];
+        int Delay, Area = 0;
+        for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+            pTimes[i] = (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; 
+        Delay = If_CutDsdBalanceEvalInt( p->pIfDsdMan, Abc_LitNotCond(If_CutDsdLit(p, pCut), pCut->fCompl), pTimes, vAig, &Area, If_CutDsdPerm(p, pCut) );
+        pCut->Cost = Area;
+        return Delay;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_DsdManTune( If_DsdMan_t * p, int LutSize, int fFast, int fAdd, int fSpec, int fVerbose )
+{
+    ProgressBar * pProgress = NULL;
+    sat_solver * pSat = NULL;
+    If_DsdObj_t * pObj;
+    Vec_Int_t * vLits;
+    int i, Value, nVars;
+    word * pTruth;
+    if ( !fAdd || !LutSize )
+        If_DsdVecForEachObj( &p->vObjs, pObj, i )
+            pObj->fMark = 0;
+    if ( LutSize == 0 )
+        return;
+    vLits = Vec_IntAlloc( 1000 );
+    pSat = (sat_solver *)If_ManSatBuildXY( LutSize );
+    pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(&p->vObjs) );
+    If_DsdVecForEachObj( &p->vObjs, pObj, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        nVars = If_DsdObjSuppSize(pObj);
+        if ( nVars <= LutSize )
+            continue;
+        if ( fAdd && !pObj->fMark )
+            continue;
+        pObj->fMark = 0;
+        if ( If_DsdManCheckXY(p, Abc_Var2Lit(i, 0), LutSize, 0, 0, 0, 0) )
+            continue;
+        if ( fFast )
+            Value = 0;
+        else
+        {
+            pTruth = If_DsdManComputeTruth( p, Abc_Var2Lit(i, 0), NULL );
+            Value = If_ManSatCheckXYall( pSat, LutSize, pTruth, nVars, vLits );
+        }
+        if ( Value )
+            continue;
+        If_DsdVecObjSetMark( &p->vObjs, i );
+    }
+    Extra_ProgressBarStop( pProgress );
+    If_ManSatUnbuild( pSat );
+    Vec_IntFree( vLits );
+    if ( fVerbose )
+        If_DsdManPrintDistrib( p );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifLibBox.c b/abc-build/src/map/if/ifLibBox.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifLibBox.c
@@ -0,0 +1,401 @@
+/**CFile****************************************************************
+
+  FileName    [ifLibBox.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Box library.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifLibBox.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+#include "misc/extra/extra.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define If_LibBoxForEachBox( p, pBox, i )     \
+    Vec_PtrForEachEntry( If_Box_t *, p->vBoxes, pBox, i ) if ( pBox == NULL ) {} else
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Box_t * If_BoxStart( char * pName, int Id, int nPis, int nPos, int fSeq, int fBlack, int fOuter )
+{
+    If_Box_t * p;
+    p = ABC_CALLOC( If_Box_t, 1 );
+    p->pName   = pName; // consumes memory
+    p->Id      = Id;
+    p->fSeq    = (char)fSeq;
+    p->fBlack  = (char)fBlack;
+    p->fOuter  = (char)fOuter;
+    p->nPis    = nPis;
+    p->nPos    = nPos;
+    p->pDelays = ABC_CALLOC( int, nPis * nPos );
+    return p;
+}
+If_Box_t * If_BoxDup( If_Box_t * p )
+{
+    If_Box_t * pNew = NULL;
+    return pNew;
+}
+void If_BoxFree( If_Box_t * p )
+{
+    ABC_FREE( p->pDelays );
+    ABC_FREE( p->pName );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_LibBox_t * If_LibBoxStart()
+{
+    If_LibBox_t * p;
+    p = ABC_CALLOC( If_LibBox_t, 1 );
+    p->vBoxes = Vec_PtrAlloc( 100 );
+    return p;
+}
+If_LibBox_t * If_LibBoxDup( If_Box_t * p )
+{
+    If_LibBox_t * pNew = NULL;
+    return pNew;
+}
+void If_LibBoxFree( If_LibBox_t * p )
+{
+    If_Box_t * pBox;
+    int i;
+    if ( p == NULL )
+        return;
+    If_LibBoxForEachBox( p, pBox, i )
+        If_BoxFree( pBox );
+    Vec_PtrFree( p->vBoxes );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Box_t * If_LibBoxReadBox( If_LibBox_t * p, int Id )
+{
+    return (If_Box_t *)Vec_PtrEntry( p->vBoxes, Id );
+}
+If_Box_t * If_LibBoxFindBox( If_LibBox_t * p, char * pName )
+{
+    If_Box_t * pBox;
+    int i;
+    if ( p == NULL )
+        return NULL;
+    If_LibBoxForEachBox( p, pBox, i )
+        if ( !strcmp(pBox->pName, pName) )
+            return pBox;
+    return NULL;
+}
+void If_LibBoxAdd( If_LibBox_t * p, If_Box_t * pBox )
+{
+    if ( pBox->Id >= Vec_PtrSize(p->vBoxes) )
+        Vec_PtrFillExtra( p->vBoxes, 2 * pBox->Id + 10, NULL );
+    assert( Vec_PtrEntry( p->vBoxes, pBox->Id ) == NULL );
+    Vec_PtrWriteEntry( p->vBoxes, pBox->Id, pBox );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_LibBox_t * If_LibBoxRead2( char * pFileName )
+{
+    int nSize = 100000;
+    char * pBuffer;
+    FILE * pFile;
+    If_LibBox_t * p = NULL;
+    If_Box_t * pBox = NULL;
+    char * pToken, * pName;
+    int fSeq, fBlack, fOuter;
+    int i, Id, nPis, nPos;
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\".\n", pFileName );
+        return NULL;
+    }
+    // read lines
+    nPis = nPos = 0;
+    pBuffer = ABC_ALLOC( char, nSize );
+    while ( fgets( pBuffer, nSize, pFile ) )
+    {
+        pToken = strtok( pBuffer, " \n\r\t" );
+        if ( pToken == NULL )
+            continue;
+        if ( pToken[0] == '.' )
+        {
+            if ( !strcmp(pToken, ".box") )
+            {
+                // save ID
+                pToken = strtok( NULL, " \n\r\t" );
+                Id     = atoi( pToken );
+                // save name
+                pToken = strtok( NULL, " \n\r\t" );
+                pName  = Abc_UtilStrsav(pToken);
+                // save PIs
+                pToken = strtok( NULL, " \n\r\t" );
+                nPis   = atoi( pToken );
+                // save POs
+                pToken = strtok( NULL, " \n\r\t" );
+                nPos   = atoi( pToken );
+                // save attributes
+                fSeq = fBlack = fOuter = 0;
+                pToken = strtok( NULL, " \n\r\t" );
+                while ( pToken )
+                {
+                    if ( !strcmp(pToken, "seq") )
+                        fSeq = 1;
+                    else if ( !strcmp(pToken, "black") )
+                        fBlack = 1;
+                    else if ( !strcmp(pToken, "outer") )
+                        fOuter = 1;
+                    else assert( !strcmp(pToken, "comb") || !strcmp(pToken, "white") || !strcmp(pToken, "inner") );
+                    pToken = strtok( NULL, " \n\r\t" );
+                }
+                // create library
+                if ( p == NULL )
+                    p = If_LibBoxStart();
+                // create box
+                pBox = If_BoxStart( pName, Id, nPis, nPos, fSeq, fBlack, fOuter );
+                If_LibBoxAdd( p, pBox );
+            }
+            continue;
+        }
+        // read the table
+        assert( nPis > 0 && nPos > 0 );
+        for ( i = 0; i < nPis * nPos; i++ )
+        {
+            while ( pToken == NULL )
+            {
+                if ( fgets( pBuffer, nSize, pFile ) == NULL )
+                { printf( "The table does not have enough entries.\n" ); fflush(stdout); assert( 0 ); }
+                pToken = strtok( pBuffer, " \n\r\t" );
+            }
+            pBox->pDelays[i] = (pToken[0] == '-') ? -1 : atoi(pToken);
+            pToken = strtok( NULL, " \n\r\t" );
+        }
+        pBox = NULL;
+    }
+    ABC_FREE( pBuffer );
+    fclose( pFile );
+    return p;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * If_LibBoxGetToken( FILE * pFile )
+{
+    static char pBuffer[1000];
+    char c, * pTemp = pBuffer;
+    while ( (c = fgetc(pFile)) != EOF )
+    {
+        if ( c == '#' )
+        {
+            while ( (c = fgetc(pFile)) != EOF )
+                if ( c == '\n' )
+                    break;
+        }
+        if ( c == ' ' || c == '\t' || c == '\n' || c == '\r' )
+        {
+            if ( pTemp > pBuffer )
+                break;
+            continue;
+        }
+        *pTemp++ = c;
+    }
+    *pTemp = 0;
+    return pTemp > pBuffer ? pBuffer : NULL;
+}
+If_LibBox_t * If_LibBoxRead( char * pFileName )
+{
+    FILE * pFile;
+    If_LibBox_t * p;
+    If_Box_t * pBox;
+    char * pToken, * pName;
+    int i, Id, fBlack, nPis, nPos;
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\".\n", pFileName );
+        return NULL;
+    }
+    // get the library name
+    pToken = If_LibBoxGetToken( pFile );
+    if ( pToken == NULL )
+    {
+        fclose( pFile );
+        printf( "Cannot read library name from file \"%s\".\n", pFileName );
+        return NULL;
+    }
+    if ( pToken[0] == '.' )    
+    {
+        fclose( pFile );
+        printf( "Wrong box format. Please try \"read_box -e\".\n" );
+        return NULL;
+    }
+       
+    // create library
+    p = If_LibBoxStart();
+    while ( pToken )
+    {
+        // save name
+        pName  = Abc_UtilStrsav(pToken);
+        // save ID
+        pToken = If_LibBoxGetToken( pFile );
+        Id     = atoi( pToken );
+        // save white/black
+        pToken = If_LibBoxGetToken( pFile );
+        fBlack = !atoi( pToken );
+        // save PIs
+        pToken = If_LibBoxGetToken( pFile );
+        nPis   = atoi( pToken );
+        // save POs
+        pToken = If_LibBoxGetToken( pFile );
+        nPos   = atoi( pToken );
+        // create box
+        pBox   = If_BoxStart( pName, Id, nPis, nPos, 0, fBlack, 0 );
+        If_LibBoxAdd( p, pBox );
+        // read the table
+        for ( i = 0; i < nPis * nPos; i++ )
+        {
+            pToken = If_LibBoxGetToken( pFile );
+            pBox->pDelays[i] = (pToken[0] == '-') ? -1 : atoi(pToken);
+        }
+        // extract next name
+        pToken = If_LibBoxGetToken( pFile );
+    }
+    fclose( pFile );
+    return p;
+}
+void If_LibBoxPrint( FILE * pFile, If_LibBox_t * p )
+{
+    If_Box_t * pBox;
+    int i, j, k;
+    fprintf( pFile, "# Box library written by ABC on %s.\n", Extra_TimeStamp() );
+    fprintf( pFile, "# <Name> <ID> <Type> <I> <O>\n" );
+    If_LibBoxForEachBox( p, pBox, i )
+    {
+        fprintf( pFile, "%s %d %d %d %d\n", pBox->pName, pBox->Id, !pBox->fBlack, pBox->nPis, pBox->nPos );
+        for ( j = 0; j < pBox->nPos; j++, printf("\n") )
+            for ( k = 0; k < pBox->nPis; k++ )
+                if ( pBox->pDelays[j * pBox->nPis + k] == -1 )
+                    fprintf( pFile, "    - " );
+                else
+                    fprintf( pFile, "%5d ", pBox->pDelays[j * pBox->nPis + k] );
+    }
+}
+void If_LibBoxWrite( char * pFileName, If_LibBox_t * p )
+{
+    FILE * pFile;
+    pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\".\n", pFileName );
+        return;
+    }
+    If_LibBoxPrint( pFile, p );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_LibBoxLoad( char * pFileName )
+{
+    FILE * pFile;
+    If_LibBox_t * pLib;
+    char * pFileNameOther;
+    // check if library can be read
+    pFileNameOther = Extra_FileNameGenericAppend( pFileName, ".cdl" );
+    pFile = fopen( pFileNameOther, "r" );
+    if ( pFile == NULL )
+        return 0;
+    fclose( pFile );
+    // read library
+    pLib = If_LibBoxRead2( pFileNameOther );
+    // replace the current library
+    If_LibBoxFree( (If_LibBox_t *)Abc_FrameReadLibBox() );
+    Abc_FrameSetLibBox( pLib );
+    return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifLibLut.c b/abc-build/src/map/if/ifLibLut.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifLibLut.c
@@ -0,0 +1,346 @@
+/**CFile****************************************************************
+
+  FileName    [ifLibLut.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [LUT library.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifLibLut.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline char * If_UtilStrsav( char *s ) {  return !s ? s : strcpy(ABC_ALLOC(char, strlen(s)+1), s);  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the description of LUTs from the LUT library file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_LibLut_t * If_LibLutRead( char * FileName )
+{
+    char pBuffer[1000], * pToken;
+    If_LibLut_t * p;
+    FILE * pFile;
+    int i, k;
+
+    pFile = fopen( FileName, "r" );
+    if ( pFile == NULL )
+    {
+        Abc_Print( -1, "Cannot open LUT library file \"%s\".\n", FileName );
+        return NULL;
+    }
+
+    p = ABC_ALLOC( If_LibLut_t, 1 );
+    memset( p, 0, sizeof(If_LibLut_t) );
+    p->pName = If_UtilStrsav( FileName );
+
+    i = 1;
+    while ( fgets( pBuffer, 1000, pFile ) != NULL )
+    {
+        pToken = strtok( pBuffer, " \t\n" );
+        if ( pToken == NULL )
+            continue;
+        if ( pToken[0] == '#' )
+            continue;
+        if ( i != atoi(pToken) )
+        {
+            Abc_Print( 1, "Error in the LUT library file \"%s\".\n", FileName );
+            ABC_FREE( p->pName );
+            ABC_FREE( p );
+            return NULL;
+        }
+
+        // read area
+        pToken = strtok( NULL, " \t\n" );
+        p->pLutAreas[i] = (float)atof(pToken);
+
+        // read delays
+        k = 0;
+        while ( (pToken = strtok( NULL, " \t\n" )) )
+            p->pLutDelays[i][k++] = (float)atof(pToken);
+
+        // check for out-of-bound
+        if ( k > i )
+        {
+            ABC_FREE( p->pName );
+            ABC_FREE( p );
+            Abc_Print( 1, "LUT %d has too many pins (%d). Max allowed is %d.\n", i, k, i );
+            return NULL;
+        }
+
+        // check if var delays are specified
+        if ( k > 1 )
+            p->fVarPinDelays = 1;
+
+        if ( i == IF_MAX_LUTSIZE )
+        {
+            ABC_FREE( p->pName );
+            ABC_FREE( p );
+            Abc_Print( 1, "Skipping LUTs of size more than %d.\n", i );
+            return NULL;
+        }
+        i++;
+    }
+    p->LutMax = i-1;
+
+    // check the library
+    if ( p->fVarPinDelays )
+    {
+        for ( i = 1; i <= p->LutMax; i++ )
+            for ( k = 0; k < i; k++ )
+            {
+                if ( p->pLutDelays[i][k] <= 0.0 )
+                    Abc_Print( 0, "Pin %d of LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n", 
+                        k, i, p->pLutDelays[i][k] );
+                if ( k && p->pLutDelays[i][k-1] > p->pLutDelays[i][k] )
+                    Abc_Print( 0, "Pin %d of LUT %d has delay %f. Pin %d of LUT %d has delay %f. Pin delays should be in non-decreasing order. Technology mapping may not work correctly.\n", 
+                        k-1, i, p->pLutDelays[i][k-1], 
+                        k, i, p->pLutDelays[i][k] );
+            }
+    }
+    else
+    {
+        for ( i = 1; i <= p->LutMax; i++ )
+        {
+            if ( p->pLutDelays[i][0] <= 0.0 )
+                Abc_Print( 0, "LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n", 
+                    i, p->pLutDelays[i][0] );
+        }
+    }
+
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the LUT library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_LibLut_t * If_LibLutDup( If_LibLut_t * p )
+{
+    If_LibLut_t * pNew;
+    pNew = ABC_ALLOC( If_LibLut_t, 1 );
+    *pNew = *p;
+    pNew->pName = If_UtilStrsav( pNew->pName );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the LUT library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_LibLutFree( If_LibLut_t * pLutLib )
+{
+    if ( pLutLib == NULL )
+        return;
+    ABC_FREE( pLutLib->pName );
+    ABC_FREE( pLutLib );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the LUT library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_LibLutPrint( If_LibLut_t * pLutLib )
+{
+    int i, k;
+    Abc_Print( 1, "# The area/delay of k-variable LUTs:\n" );
+    Abc_Print( 1, "# k    area     delay\n" );
+    if ( pLutLib->fVarPinDelays )
+    {
+        for ( i = 1; i <= pLutLib->LutMax; i++ )
+        {
+            Abc_Print( 1, "%d   %7.2f  ", i, pLutLib->pLutAreas[i] );
+            for ( k = 0; k < i; k++ )
+                Abc_Print( 1, " %7.2f", pLutLib->pLutDelays[i][k] );
+            Abc_Print( 1, "\n" );
+        }
+    }
+    else
+        for ( i = 1; i <= pLutLib->LutMax; i++ )
+            Abc_Print( 1, "%d   %7.2f   %7.2f\n", i, pLutLib->pLutAreas[i], pLutLib->pLutDelays[i][0] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the delays are discrete.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_LibLutDelaysAreDiscrete( If_LibLut_t * pLutLib )
+{
+    float Delay;
+    int i;
+    for ( i = 1; i <= pLutLib->LutMax; i++ )
+    {
+        Delay = pLutLib->pLutDelays[i][0];
+        if ( ((float)((int)Delay)) != Delay )
+            return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the delays are discrete.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_LibLutDelaysAreDifferent( If_LibLut_t * pLutLib )
+{
+    int i, k;
+    float Delay = pLutLib->pLutDelays[1][0];
+    if ( pLutLib->fVarPinDelays )
+    {
+        for ( i = 2; i <= pLutLib->LutMax; i++ )
+        for ( k = 0; k < i; k++ )
+            if ( pLutLib->pLutDelays[i][k] != Delay )
+                return 1;
+    }
+    else
+    {
+        for ( i = 2; i <= pLutLib->LutMax; i++ )
+            if ( pLutLib->pLutDelays[i][0] != Delay )
+                return 1;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets simple LUT library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_LibLut_t * If_LibLutSetSimple( int nLutSize )
+{
+    If_LibLut_t s_LutLib10= { "lutlib",10, 0, {0,1,1,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1},{1},{1}} };
+    If_LibLut_t s_LutLib9 = { "lutlib", 9, 0, {0,1,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1},{1}} };
+    If_LibLut_t s_LutLib8 = { "lutlib", 8, 0, {0,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1}} };
+    If_LibLut_t s_LutLib7 = { "lutlib", 7, 0, {0,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1}} };
+    If_LibLut_t s_LutLib6 = { "lutlib", 6, 0, {0,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1}} };
+    If_LibLut_t s_LutLib5 = { "lutlib", 5, 0, {0,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1}} };
+    If_LibLut_t s_LutLib4 = { "lutlib", 4, 0, {0,1,1,1,1}, {{0},{1},{1},{1},{1}} };
+    If_LibLut_t s_LutLib3 = { "lutlib", 3, 0, {0,1,1,1}, {{0},{1},{1},{1}} };
+    If_LibLut_t * pLutLib;
+    assert( nLutSize >= 3 && nLutSize <= 10 );
+    switch ( nLutSize )
+    {
+        case 3:  pLutLib = &s_LutLib3; break;
+        case 4:  pLutLib = &s_LutLib4; break;
+        case 5:  pLutLib = &s_LutLib5; break;
+        case 6:  pLutLib = &s_LutLib6; break;
+        case 7:  pLutLib = &s_LutLib7; break;
+        case 8:  pLutLib = &s_LutLib8; break;
+        case 9:  pLutLib = &s_LutLib9; break;
+        case 10: pLutLib = &s_LutLib10; break;
+        default: pLutLib = NULL; break;
+    }
+    if ( pLutLib == NULL )
+        return NULL;
+    return If_LibLutDup(pLutLib);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gets the delay of the fastest pin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_LibLutFastestPinDelay( If_LibLut_t * p )
+{
+    return !p? 1.0 : p->pLutDelays[p->LutMax][0];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gets the delay of the slowest pin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_LibLutSlowestPinDelay( If_LibLut_t * p )
+{
+    return !p? 1.0 : (p->fVarPinDelays? p->pLutDelays[p->LutMax][p->LutMax-1]: p->pLutDelays[p->LutMax][0]);
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifMan.c b/abc-build/src/map/if/ifMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifMan.c
@@ -0,0 +1,669 @@
+/**CFile****************************************************************
+
+  FileName    [ifMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Mapping manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifMan.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static If_Obj_t * If_ManSetupObj( If_Man_t * p );
+
+static void       If_ManCutSetRecycle( If_Man_t * p, If_Set_t * pSet ) { pSet->pNext = p->pFreeList; p->pFreeList = pSet;                            }
+static If_Set_t * If_ManCutSetFetch( If_Man_t * p )                    { If_Set_t * pTemp = p->pFreeList; p->pFreeList = p->pFreeList->pNext; return pTemp; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Man_t * If_ManStart( If_Par_t * pPars )
+{
+    If_Man_t * p; int v;
+    assert( !pPars->fUseDsd || !pPars->fUseTtPerm );
+    // start the manager
+    p = ABC_ALLOC( If_Man_t, 1 );
+    memset( p, 0, sizeof(If_Man_t) );
+    p->pPars    = pPars;
+    p->fEpsilon = pPars->Epsilon;
+    // allocate arrays for nodes
+    p->vCis     = Vec_PtrAlloc( 100 );
+    p->vCos     = Vec_PtrAlloc( 100 );
+    p->vObjs    = Vec_PtrAlloc( 100 );
+    p->vTemp    = Vec_PtrAlloc( 100 );
+    // prepare the memory manager
+    if ( p->pPars->fTruth )
+    {
+        for ( v = 0; v <= p->pPars->nLutSize; v++ )
+            p->nTruth6Words[v] = Abc_Truth6WordNum( v );
+        for ( v = 6; v <= Abc_MaxInt(6,p->pPars->nLutSize); v++ )
+            p->vTtMem[v] = Vec_MemAllocForTT( v, pPars->fUseTtPerm );
+        for ( v = 0; v < 6; v++ )
+            p->vTtMem[v] = p->vTtMem[6];
+        if ( p->pPars->fDelayOpt || pPars->nGateSize > 0 )
+        {
+            for ( v = 6; v <= Abc_MaxInt(6,p->pPars->nLutSize); v++ )
+                p->vTtIsops[v] = Vec_WecAlloc( 1000 );
+            for ( v = 6; v <= Abc_MaxInt(6,p->pPars->nLutSize); v++ )
+                Vec_WecInit( p->vTtIsops[v], 2 );
+            for ( v = 0; v < 6; v++ )
+                p->vTtIsops[v] = p->vTtIsops[6];
+        }
+        if ( p->pPars->fDelayOpt || pPars->nGateSize > 0 || p->pPars->fDsdBalance );
+        {
+            p->vCover = Vec_IntAlloc( 0 );
+            p->vArray = Vec_IntAlloc( 1000 );
+        }
+    }
+    p->nPermWords  = p->pPars->fUsePerm? If_CutPermWords( p->pPars->nLutSize ) : 0;
+    p->nObjBytes   = sizeof(If_Obj_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermWords);
+    p->nCutBytes   = sizeof(If_Cut_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermWords);
+    p->nSetBytes   = sizeof(If_Set_t) + (sizeof(If_Cut_t *) + p->nCutBytes) * (p->pPars->nCutsMax + 1);
+    p->pMemObj     = Mem_FixedStart( p->nObjBytes );
+    // report expected memory usage
+    if ( p->pPars->fVerbose )
+        Abc_Print( 1, "K = %d. Memory (bytes): Truth = %4d. Cut = %4d. Obj = %4d. Set = %4d. CutMin = %s\n", 
+            p->pPars->nLutSize, 8 * p->nTruth6Words[p->pPars->nLutSize], p->nCutBytes, p->nObjBytes, p->nSetBytes, p->pPars->fCutMin? "yes":"no" );
+    // room for temporary truth tables
+    p->puTemp[0] = p->pPars->fTruth? ABC_ALLOC( unsigned, 8 * p->nTruth6Words[p->pPars->nLutSize] ) : NULL;
+    p->puTemp[1] = p->puTemp[0] + p->nTruth6Words[p->pPars->nLutSize]*2;
+    p->puTemp[2] = p->puTemp[1] + p->nTruth6Words[p->pPars->nLutSize]*2;
+    p->puTemp[3] = p->puTemp[2] + p->nTruth6Words[p->pPars->nLutSize]*2;
+    p->puTempW   = p->pPars->fTruth? ABC_ALLOC( word, p->nTruth6Words[p->pPars->nLutSize] ) : NULL;
+    if ( pPars->fUseDsd )
+    {
+        for ( v = 6; v <= Abc_MaxInt(6,p->pPars->nLutSize); v++ )
+        {
+            p->vTtDsds[v] = Vec_IntAlloc( 1000 );
+            Vec_IntPush( p->vTtDsds[v], 0 );
+            Vec_IntPush( p->vTtDsds[v], 2 );
+            p->vTtPerms[v] = Vec_StrAlloc( 10000 );
+            Vec_StrFill( p->vTtPerms[v], 2 * v, IF_BIG_CHAR );
+            Vec_StrWriteEntry( p->vTtPerms[v], v, 0 );
+        }
+        for ( v = 0; v < 6; v++ )
+        {
+            p->vTtDsds[v]  = p->vTtDsds[6];
+            p->vTtPerms[v] = p->vTtPerms[6];
+        }
+    }
+    if ( pPars->fUseTtPerm )
+    {
+        p->vPairHash = Hash_IntManStart( 10000 );
+        p->vPairPerms = Vec_StrAlloc( 10000 );
+        Vec_StrFill( p->vPairPerms, p->pPars->nLutSize, 0 );
+        p->vPairRes = Vec_IntAlloc( 1000 );
+        Vec_IntPush( p->vPairRes, -1 );
+    }
+    // create the constant node
+    p->pConst1   = If_ManSetupObj( p );
+    p->pConst1->Type   = IF_CONST1;
+    p->pConst1->fPhase = 1;
+    p->nObjs[IF_CONST1]++;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManRestart( If_Man_t * p )
+{
+    ABC_FREE( p->pMemCi );
+    Vec_PtrClear( p->vCis );
+    Vec_PtrClear( p->vCos );
+    Vec_PtrClear( p->vObjs );
+    Vec_PtrClear( p->vTemp );
+    Mem_FixedRestart( p->pMemObj );
+    // create the constant node
+    p->pConst1 = If_ManSetupObj( p );
+    p->pConst1->Type = IF_CONST1;
+    p->pConst1->fPhase = 1;
+    // reset the counter of other nodes
+    p->nObjs[IF_CI] = p->nObjs[IF_CO] = p->nObjs[IF_AND] = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManStop( If_Man_t * p )
+{
+    extern void If_ManCacheAnalize( If_Man_t * p );
+    int i;
+    if ( p->pPars->fVerbose && p->vCutData )
+        If_ManCacheAnalize( p );
+    if ( p->pPars->fVerbose && p->pPars->fTruth )
+    {
+        int nUnique = 0, nMemTotal = 0;
+        for ( i = 6; i <= Abc_MaxInt(6,p->pPars->nLutSize); i++ )
+            nUnique += Vec_MemEntryNum(p->vTtMem[i]);
+        for ( i = 6; i <= Abc_MaxInt(6,p->pPars->nLutSize); i++ )
+            nMemTotal += (int)Vec_MemMemory(p->vTtMem[i]);
+        printf( "Unique truth tables = %d   Memory = %.2f MB   ", nUnique, 1.0 * nMemTotal / (1<<20) ); 
+        Abc_PrintTime( 1, "Time", p->timeCache[4] );
+        if ( p->nCacheMisses )
+        {
+            printf( "Cache hits = %d. Cache misses = %d  (%.2f %%)\n", p->nCacheHits, p->nCacheMisses, 100.0 * p->nCacheMisses / (p->nCacheHits + p->nCacheMisses) ); 
+            Abc_PrintTime( 1, "Non-DSD   ", p->timeCache[0] );
+            Abc_PrintTime( 1, "DSD hits  ", p->timeCache[1] );
+            Abc_PrintTime( 1, "DSD misses", p->timeCache[2] );
+            Abc_PrintTime( 1, "TOTAL     ", p->timeCache[0] + p->timeCache[1] + p->timeCache[2] );
+            Abc_PrintTime( 1, "Canon     ", p->timeCache[3] );
+        }
+    }
+    if ( p->pPars->fVerbose && p->nCutsUselessAll )
+    {
+        for ( i = 0; i <= 16; i++ )
+            if ( p->nCutsUseless[i] )
+                Abc_Print( 1, "Useless cuts %2d  = %9d  (out of %9d)  (%6.2f %%)\n", i, p->nCutsUseless[i], p->nCutsCount[i], 100.0*p->nCutsUseless[i]/(p->nCutsCount[i]+1) );
+        Abc_Print( 1, "Useless cuts all = %9d  (out of %9d)  (%6.2f %%)\n", p->nCutsUselessAll, p->nCutsCountAll, 100.0*p->nCutsUselessAll/(p->nCutsCountAll+1) );
+    }
+//    if ( p->pPars->fVerbose && p->nCuts5 )
+//        Abc_Print( 1, "Statistics about 5-cuts: Total = %d  Non-decomposable = %d (%.2f %%)\n", p->nCuts5, p->nCuts5-p->nCuts5a, 100.0*(p->nCuts5-p->nCuts5a)/p->nCuts5 );
+    if ( p->pIfDsdMan )
+        p->pIfDsdMan = NULL;
+    if ( p->pPars->fUseDsd && (p->nCountNonDec[0] || p->nCountNonDec[1]) )
+        printf( "NonDec0 = %d.  NonDec1 = %d.\n", p->nCountNonDec[0], p->nCountNonDec[1] );
+    Vec_IntFreeP( &p->vCoAttrs );
+    Vec_PtrFree( p->vCis );
+    Vec_PtrFree( p->vCos );
+    Vec_PtrFree( p->vObjs );
+    Vec_PtrFree( p->vTemp );
+    Vec_IntFreeP( &p->vCover );
+    Vec_IntFreeP( &p->vArray );
+    Vec_WrdFreeP( &p->vAnds );
+    Vec_WrdFreeP( &p->vAndGate );
+    Vec_WrdFreeP( &p->vOrGate );
+    Vec_PtrFreeP( &p->vObjsRev );
+    Vec_PtrFreeP( &p->vLatchOrder );
+    Vec_IntFreeP( &p->vLags );
+    for ( i = 6; i <= Abc_MaxInt(6,p->pPars->nLutSize); i++ )
+        Vec_IntFreeP( &p->vTtDsds[i] );
+    for ( i = 6; i <= Abc_MaxInt(6,p->pPars->nLutSize); i++ )
+        Vec_StrFreeP( &p->vTtPerms[i] );
+    Vec_IntFreeP( &p->vCutData );
+    Vec_IntFreeP( &p->vPairRes );
+    Vec_StrFreeP( &p->vPairPerms );
+    if ( p->vPairHash )
+        Hash_IntManStop( p->vPairHash );
+    for ( i = 6; i <= Abc_MaxInt(6,p->pPars->nLutSize); i++ )
+        Vec_MemHashFree( p->vTtMem[i] );
+    for ( i = 6; i <= Abc_MaxInt(6,p->pPars->nLutSize); i++ )
+        Vec_MemFreeP( &p->vTtMem[i] );
+    for ( i = 6; i <= Abc_MaxInt(6,p->pPars->nLutSize); i++ )
+        Vec_WecFreeP( &p->vTtIsops[i] );
+    Mem_FixedStop( p->pMemObj, 0 );
+    ABC_FREE( p->pMemCi );
+    ABC_FREE( p->pMemAnd );
+    ABC_FREE( p->puTemp[0] );
+    ABC_FREE( p->puTempW );
+    // free pars memory
+    ABC_FREE( p->pPars->pTimesArr );
+    ABC_FREE( p->pPars->pTimesReq );
+    if ( p->pManTim )
+        Tim_ManStop( p->pManTim );
+    if ( p->vSwitching )
+        Vec_IntFree( p->vSwitching );
+    // hash table
+//    if ( p->pPars->fVerbose && p->nTableEntries[0] )
+//        printf( "Hash table 2:  Entries = %7d.  Size = %7d.\n", p->nTableEntries[0], p->nTableSize[0] );
+//    if ( p->pPars->fVerbose && p->nTableEntries[1] )
+//        printf( "Hash table 3:  Entries = %7d.  Size = %7d.\n", p->nTableEntries[1], p->nTableSize[1] );
+    ABC_FREE( p->pHashTable[0] );
+    ABC_FREE( p->pHashTable[1] );
+    if ( p->pMemEntries )
+        Mem_FixedStop( p->pMemEntries, 0 );
+    ABC_FREE( p->pName );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates primary input.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Obj_t * If_ManCreateCi( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    pObj = If_ManSetupObj( p );
+    pObj->Type = IF_CI;
+    pObj->IdPio = Vec_PtrSize( p->vCis );
+    Vec_PtrPush( p->vCis, pObj );
+    p->nObjs[IF_CI]++;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates primary output with the given driver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Obj_t * If_ManCreateCo( If_Man_t * p, If_Obj_t * pDriver )
+{
+    If_Obj_t * pObj;
+    pObj = If_ManSetupObj( p );
+    pObj->IdPio = Vec_PtrSize( p->vCos );
+    Vec_PtrPush( p->vCos, pObj );
+    pObj->Type = IF_CO;
+    pObj->fCompl0 = If_IsComplement(pDriver); pDriver = If_Regular(pDriver);
+    pObj->pFanin0 = pDriver; pDriver->nRefs++; 
+    pObj->fPhase  = (pObj->fCompl0 ^ pDriver->fPhase);
+    pObj->Level   = pDriver->Level;
+    if ( p->nLevelMax < (int)pObj->Level )
+        p->nLevelMax = (int)pObj->Level;
+    p->nObjs[IF_CO]++;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the new node assuming it does not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 )
+{
+    If_Obj_t * pObj;
+    // perform constant propagation
+    if ( pFan0 == pFan1 )
+        return pFan0;
+    if ( pFan0 == If_Not(pFan1) )
+        return If_Not(p->pConst1);
+    if ( If_Regular(pFan0) == p->pConst1 )
+        return pFan0 == p->pConst1 ? pFan1 : If_Not(p->pConst1);
+    if ( If_Regular(pFan1) == p->pConst1 )
+        return pFan1 == p->pConst1 ? pFan0 : If_Not(p->pConst1);
+    // get memory for the new object
+    pObj = If_ManSetupObj( p );
+    pObj->Type    = IF_AND;
+    pObj->fCompl0 = If_IsComplement(pFan0); pFan0 = If_Regular(pFan0);
+    pObj->fCompl1 = If_IsComplement(pFan1); pFan1 = If_Regular(pFan1);
+    pObj->pFanin0 = pFan0; pFan0->nRefs++; pFan0->nVisits++; pFan0->nVisitsCopy++;
+    pObj->pFanin1 = pFan1; pFan1->nRefs++; pFan1->nVisits++; pFan1->nVisitsCopy++;
+    pObj->fPhase  = (pObj->fCompl0 ^ pFan0->fPhase) & (pObj->fCompl1 ^ pFan1->fPhase);
+    pObj->Level   = 1 + IF_MAX( pFan0->Level, pFan1->Level );
+    if ( p->nLevelMax < (int)pObj->Level )
+        p->nLevelMax = (int)pObj->Level;
+    p->nObjs[IF_AND]++;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the new node assuming it does not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Obj_t * If_ManCreateXor( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 )
+{
+    If_Obj_t * pRes1, * pRes2;
+    pRes1 = If_ManCreateAnd( p, If_Not(pFan0), pFan1 );
+    pRes2 = If_ManCreateAnd( p, pFan0, If_Not(pFan1) );
+    return If_Not( If_ManCreateAnd( p, If_Not(pRes1), If_Not(pRes2) ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the new node assuming it does not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Obj_t * If_ManCreateMux( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1, If_Obj_t * pCtrl )
+{
+    If_Obj_t * pRes1, * pRes2;
+    pRes1 = If_ManCreateAnd( p, pFan0, If_Not(pCtrl) );
+    pRes2 = If_ManCreateAnd( p, pFan1, pCtrl );
+    return If_Not( If_ManCreateAnd( p, If_Not(pRes1), If_Not(pRes2) ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the choice node.]
+
+  Description [Should be called after the equivalence class nodes are linked.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pObj )
+{
+    If_Obj_t * pTemp;
+    // mark the node as a representative if its class
+    assert( pObj->fRepr == 0 );
+    pObj->fRepr = 1;
+    // update the level of this node (needed for correct required time computation)
+    for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv )
+    {
+        pObj->Level = IF_MAX( pObj->Level, pTemp->Level );
+        pTemp->nVisits++; pTemp->nVisitsCopy++;
+    }
+    // mark the largest level
+    if ( p->nLevelMax < (int)pObj->Level )
+        p->nLevelMax = (int)pObj->Level;
+    p->nChoices++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares memory for one cutset.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManSetupSet( If_Man_t * p, If_Set_t * pSet )
+{
+    char * pArray;
+    int i;
+    pSet->nCuts = 0;
+    pSet->nCutsMax = p->pPars->nCutsMax;
+    pSet->ppCuts = (If_Cut_t **)(pSet + 1);
+    pArray = (char *)pSet->ppCuts + sizeof(If_Cut_t *) * (pSet->nCutsMax+1);
+    for ( i = 0; i <= pSet->nCutsMax; i++ )
+    {
+        pSet->ppCuts[i] = (If_Cut_t *)(pArray + i * p->nCutBytes); 
+        If_CutSetup( p, pSet->ppCuts[i] );
+    }
+//    pArray += (pSet->nCutsMax + 1) * p->nCutBytes;
+//    assert( ((char *)pArray) - ((char *)pSet) == p->nSetBytes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares memory for one cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManSetupCutTriv( If_Man_t * p, If_Cut_t * pCut, int ObjId )
+{
+    pCut->fCompl     = 0;
+    pCut->nLimit     = p->pPars->nLutSize;
+    pCut->nLeaves    = 1;
+    pCut->pLeaves[0] = p->pPars->fLiftLeaves? (ObjId << 8) : ObjId;
+    pCut->uSign      = If_ObjCutSign( pCut->pLeaves[0] );
+    pCut->iCutFunc   = p->pPars->fUseTtPerm ? 3 : (p->pPars->fTruth ? 2: -1);
+    pCut->uMaskFunc  = 0;
+    assert( pCut->pLeaves[0] < p->vObjs->nSize );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares memory for the node with cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Obj_t * If_ManSetupObj( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    // get memory for the object
+    pObj = (If_Obj_t *)Mem_FixedEntryFetch( p->pMemObj );
+    memset( pObj, 0, sizeof(If_Obj_t) );
+    If_CutSetup( p, &pObj->CutBest );
+    // assign ID and save 
+    pObj->Id = Vec_PtrSize(p->vObjs);
+    Vec_PtrPush( p->vObjs, pObj );
+    // set the required times
+    pObj->Required = IF_FLOAT_LARGE;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares memory for one cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManSetupCiCutSets( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    int i;
+    assert( p->pMemCi == NULL );
+    // create elementary cuts for the CIs
+    If_ManForEachCi( p, pObj, i )
+        If_ManSetupCutTriv( p, &pObj->CutBest, pObj->Id );
+    // create elementary cutsets for the CIs
+    p->pMemCi = (If_Set_t *)ABC_ALLOC( char, If_ManCiNum(p) * (sizeof(If_Set_t) + sizeof(void *)) );
+    If_ManForEachCi( p, pObj, i )
+    {
+        pObj->pCutSet = (If_Set_t *)((char *)p->pMemCi + i * (sizeof(If_Set_t) + sizeof(void *)));
+        pObj->pCutSet->nCuts = 1;
+        pObj->pCutSet->nCutsMax = p->pPars->nCutsMax;
+        pObj->pCutSet->ppCuts = (If_Cut_t **)(pObj->pCutSet + 1);
+        pObj->pCutSet->ppCuts[0] = &pObj->CutBest;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares cutset of the node.]
+
+  Description [Elementary cutset will be added last.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Set_t * If_ManSetupNodeCutSet( If_Man_t * p, If_Obj_t * pObj )
+{
+    assert( If_ObjIsAnd(pObj) );
+    assert( pObj->pCutSet == NULL );
+//    pObj->pCutSet = (If_Set_t *)Mem_FixedEntryFetch( p->pMemSet );
+//    If_ManSetupSet( p, pObj->pCutSet );
+    pObj->pCutSet = If_ManCutSetFetch( p );
+    pObj->pCutSet->nCuts = 0;
+    pObj->pCutSet->nCutsMax = p->pPars->nCutsMax;
+    return pObj->pCutSet;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences cutset of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManDerefNodeCutSet( If_Man_t * p, If_Obj_t * pObj )
+{
+    If_Obj_t * pFanin;
+    assert( If_ObjIsAnd(pObj) );
+    // consider the node
+    assert( pObj->nVisits >= 0 );
+    if ( pObj->nVisits == 0 )
+    {
+//        Mem_FixedEntryRecycle( p->pMemSet, (char *)pObj->pCutSet );
+        If_ManCutSetRecycle( p, pObj->pCutSet );
+        pObj->pCutSet = NULL;
+    }
+    // consider the first fanin
+    pFanin = If_ObjFanin0(pObj);
+    assert( pFanin->nVisits > 0 );
+    if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
+    {
+//        Mem_FixedEntryRecycle( p->pMemSet, (char *)pFanin->pCutSet );
+        If_ManCutSetRecycle( p, pFanin->pCutSet );
+        pFanin->pCutSet = NULL;
+    }
+    // consider the second fanin
+    pFanin = If_ObjFanin1(pObj);
+    assert( pFanin->nVisits > 0 );
+    if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
+    {
+//        Mem_FixedEntryRecycle( p->pMemSet, (char *)pFanin->pCutSet );
+        If_ManCutSetRecycle( p, pFanin->pCutSet );
+        pFanin->pCutSet = NULL;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences cutset of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManDerefChoiceCutSet( If_Man_t * p, If_Obj_t * pObj )
+{
+    If_Obj_t * pTemp;
+    assert( If_ObjIsAnd(pObj) );
+    assert( pObj->fRepr );
+    assert( pObj->nVisits > 0 );
+    // consider the nodes in the choice class
+    for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv )
+    {
+//        assert( pTemp == pObj || pTemp->nVisits == 1 );
+        if ( --pTemp->nVisits == 0 )
+        {
+//            Mem_FixedEntryRecycle( p->pMemSet, (char *)pTemp->pCutSet );
+            If_ManCutSetRecycle( p, pTemp->pCutSet );
+            pTemp->pCutSet = NULL;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences cutset of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManSetupSetAll( If_Man_t * p, int nCrossCut )
+{
+    If_Set_t * pCutSet;
+    int i, nCutSets;
+    nCutSets = 128 + nCrossCut;
+    p->pFreeList = p->pMemAnd = pCutSet = (If_Set_t *)ABC_ALLOC( char, nCutSets * p->nSetBytes );
+    for ( i = 0; i < nCutSets; i++ )
+    {
+        If_ManSetupSet( p, pCutSet );
+        if ( i == nCutSets - 1 )
+            pCutSet->pNext = NULL;
+        else
+            pCutSet->pNext = (If_Set_t *)( (char *)pCutSet + p->nSetBytes );
+        pCutSet = pCutSet->pNext;
+    }
+    assert( pCutSet == NULL );
+
+    if ( p->pPars->fVerbose )
+    {
+        Abc_Print( 1, "Node = %7d.  Ch = %5d.  Total mem = %7.2f MB. Peak cut mem = %7.2f MB.\n", 
+            If_ManAndNum(p), p->nChoices,
+            1.0 * (p->nObjBytes + 2*sizeof(void *)) * If_ManObjNum(p) / (1<<20), 
+            1.0 * p->nSetBytes * nCrossCut / (1<<20) );
+    }
+//    Abc_Print( 1, "Cross cut = %d.\n", nCrossCut );
+
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifMap.c b/abc-build/src/map/if/ifMap.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifMap.c
@@ -0,0 +1,534 @@
+/**CFile****************************************************************
+
+  FileName    [ifMap.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Mapping procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifMap.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern char * Dau_DsdMerge( char * pDsd0i, int * pPerm0, char * pDsd1i, int * pPerm1, int fCompl0, int fCompl1, int nVars );
+extern int    If_CutDelayRecCost3(If_Man_t* p, If_Cut_t* pCut, If_Obj_t * pObj);
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of 1s in the signature.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int If_WordCountOnes( unsigned uWord )
+{
+    uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555);
+    uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333);
+    uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F);
+    uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF);
+    return  (uWord & 0x0000FFFF) + (uWord>>16);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of 1s in the signature.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_CutDelaySpecial( If_Man_t * p, If_Cut_t * pCut, int fCarry )
+{
+    static float Pin2Pin[2][3] = { {1.0, 1.0, 1.0}, {1.0, 1.0, 0.0} };
+    If_Obj_t * pLeaf;
+    float DelayCur, Delay = -IF_FLOAT_LARGE;
+    int i;
+    assert( pCut->nLeaves <= 3 );
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+    {
+        DelayCur = If_ObjCutBest(pLeaf)->Delay;
+        Delay = IF_MAX( Delay, Pin2Pin[fCarry][i] + DelayCur );
+    }
+    return Delay;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the best cut for the given node.]
+
+  Description [Mapping modes: delay (0), area flow (1), area (2).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess, int fFirst )
+{
+    If_Set_t * pCutSet;
+    If_Cut_t * pCut0, * pCut1, * pCut;
+    If_Cut_t * pCut0R, * pCut1R;
+    int fFunc0R, fFunc1R;
+    int i, k, v, iCutDsd, fChange;
+    int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib;
+    assert( !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->pCutSet->nCuts > 0 );
+    assert( !If_ObjIsAnd(pObj->pFanin1) || pObj->pFanin1->pCutSet->nCuts > 0 );
+
+    // prepare
+    if ( Mode == 0 )
+        pObj->EstRefs = (float)pObj->nRefs;
+    else if ( Mode == 1 )
+        pObj->EstRefs = (float)((2.0 * pObj->EstRefs + pObj->nRefs) / 3.0);
+    // deref the selected cut
+    if ( Mode && pObj->nRefs > 0 )
+        If_CutAreaDeref( p, If_ObjCutBest(pObj) );
+
+    // prepare the cutset
+    pCutSet = If_ManSetupNodeCutSet( p, pObj );
+
+    // get the current assigned best cut
+    pCut = If_ObjCutBest(pObj);
+    if ( !fFirst )
+    {
+        // recompute the parameters of the best cut
+        if ( p->pPars->fDelayOpt )
+            pCut->Delay = If_CutSopBalanceEval( p, pCut, NULL );
+        else if ( p->pPars->fDsdBalance )
+            pCut->Delay = If_CutDsdBalanceEval( p, pCut, NULL );
+        else if ( p->pPars->fUserRecLib )
+            pCut->Delay = If_CutDelayRecCost3( p, pCut, pObj ); 
+        else if ( p->pPars->fDelayOptLut )
+            pCut->Delay = If_CutLutBalanceEval( p, pCut );
+        else if( p->pPars->nGateSize > 0 )
+            pCut->Delay = If_CutDelaySop( p, pCut );
+        else
+            pCut->Delay = If_CutDelay( p, pObj, pCut );
+        assert( pCut->Delay != -1 );
+//        assert( pCut->Delay <= pObj->Required + p->fEpsilon );
+        if ( pCut->Delay > pObj->Required + 2*p->fEpsilon )
+            Abc_Print( 1, "If_ObjPerformMappingAnd(): Warning! Delay of node %d (%f) exceeds the required times (%f).\n", 
+                pObj->Id, pCut->Delay, pObj->Required + p->fEpsilon );
+        pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut ) : If_CutAreaFlow( p, pCut );
+        if ( p->pPars->fEdge )
+            pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( p, pCut );
+        if ( p->pPars->fPower )
+            pCut->Power = (Mode == 2)? If_CutPowerDerefed( p, pCut, pObj ) : If_CutPowerFlow( p, pCut, pObj );
+        // save the best cut from the previous iteration
+        if ( !fPreprocess )
+            If_CutCopy( p, pCutSet->ppCuts[pCutSet->nCuts++], pCut );
+    }
+
+    // generate cuts
+    If_ObjForEachCut( pObj->pFanin0, pCut0, i )
+    If_ObjForEachCut( pObj->pFanin1, pCut1, k )
+    {
+        // get the next free cut
+        assert( pCutSet->nCuts <= pCutSet->nCutsMax );
+        pCut = pCutSet->ppCuts[pCutSet->nCuts];
+        // make sure K-feasible cut exists
+        if ( If_WordCountOnes(pCut0->uSign | pCut1->uSign) > p->pPars->nLutSize )
+            continue;
+
+        pCut0R = pCut0;
+        pCut1R = pCut1;
+        fFunc0R = pCut0->iCutFunc ^ pCut0->fCompl ^ pObj->fCompl0;
+        fFunc1R = pCut1->iCutFunc ^ pCut1->fCompl ^ pObj->fCompl1;
+        if ( !p->pPars->fUseTtPerm || pCut0->nLeaves > pCut1->nLeaves || (pCut0->nLeaves == pCut1->nLeaves && fFunc0R > fFunc1R) )
+        {
+        }
+        else
+        {
+            ABC_SWAP( If_Cut_t *, pCut0R, pCut1R );
+            ABC_SWAP( int, fFunc0R, fFunc1R );
+        }        
+
+        // merge the cuts
+        if ( p->pPars->fUseTtPerm )
+        {
+            if ( !If_CutMerge( p, pCut0R, pCut1R, pCut ) )
+                continue;
+        }
+        else
+        {
+            if ( !If_CutMergeOrdered( p, pCut0, pCut1, pCut ) )
+                continue;
+        }
+        if ( pObj->fSpec && pCut->nLeaves == (unsigned)p->pPars->nLutSize )
+            continue;
+        p->nCutsMerged++;
+        p->nCutsTotal++;
+        // check if this cut is contained in any of the available cuts
+        if ( !p->pPars->fSkipCutFilter && If_CutFilter( pCutSet, pCut, fSave0 ) )
+            continue;
+        // compute the truth table
+        pCut->iCutFunc = -1;
+        pCut->fCompl = 0;
+        if ( p->pPars->fTruth )
+        {
+//            int nShared = pCut0->nLeaves + pCut1->nLeaves - pCut->nLeaves;
+            abctime clk = 0;
+            if ( p->pPars->fVerbose )
+                clk = Abc_Clock();
+            if ( p->pPars->fUseTtPerm )
+                fChange = If_CutComputeTruthPerm( p, pCut, pCut0R, pCut1R, fFunc0R, fFunc1R );
+            else
+                fChange = If_CutComputeTruth( p, pCut, pCut0, pCut1, pObj->fCompl0, pObj->fCompl1 );
+            if ( p->pPars->fVerbose )
+                p->timeCache[4] += Abc_Clock() - clk;
+            if ( !p->pPars->fSkipCutFilter && fChange && If_CutFilter( pCutSet, pCut, fSave0 ) )
+                continue;
+            if ( p->pPars->fUseDsd )
+            {
+                extern void If_ManCacheRecord( If_Man_t * p, int iDsd0, int iDsd1, int nShared, int iDsd );
+                int truthId = Abc_Lit2Var(pCut->iCutFunc);
+                if ( truthId >= Vec_IntSize(p->vTtDsds[pCut->nLeaves]) || Vec_IntEntry(p->vTtDsds[pCut->nLeaves], truthId) == -1 )
+                {
+                    while ( truthId >= Vec_IntSize(p->vTtDsds[pCut->nLeaves]) )
+                    {
+                        Vec_IntPush( p->vTtDsds[pCut->nLeaves], -1 );
+                        for ( v = 0; v < Abc_MaxInt(6, pCut->nLeaves); v++ )
+                            Vec_StrPush( p->vTtPerms[pCut->nLeaves], IF_BIG_CHAR );
+                    }
+                    iCutDsd = If_DsdManCompute( p->pIfDsdMan, If_CutTruthWR(p, pCut), pCut->nLeaves, (unsigned char *)If_CutDsdPerm(p, pCut), p->pPars->pLutStruct );
+                    Vec_IntWriteEntry( p->vTtDsds[pCut->nLeaves], truthId, iCutDsd );
+                }
+                assert( If_DsdManSuppSize(p->pIfDsdMan, If_CutDsdLit(p, pCut)) == (int)pCut->nLeaves );
+                //If_ManCacheRecord( p, If_CutDsdLit(p, pCut0), If_CutDsdLit(p, pCut1), nShared, If_CutDsdLit(p, pCut) );
+            }
+            // run user functions
+            pCut->fUseless = 0;
+            if ( p->pPars->pFuncCell )
+            {
+                assert( p->pPars->fUseTtPerm == 0 );
+                assert( pCut->nLimit >= 4 && pCut->nLimit <= 16 );
+                if ( p->pPars->fUseDsd )
+                    pCut->fUseless = If_DsdManCheckDec( p->pIfDsdMan, If_CutDsdLit(p, pCut) );
+                else
+                    pCut->fUseless = !p->pPars->pFuncCell( p, If_CutTruth(p, pCut), Abc_MaxInt(6, pCut->nLeaves), pCut->nLeaves, p->pPars->pLutStruct );
+                p->nCutsUselessAll += pCut->fUseless;
+                p->nCutsUseless[pCut->nLeaves] += pCut->fUseless;
+                p->nCutsCountAll++;
+                p->nCutsCount[pCut->nLeaves]++;
+                // skip 5-input cuts, which cannot be decomposed
+                if ( (p->pPars->fEnableCheck75 || p->pPars->fEnableCheck75u) && pCut->nLeaves == 5 && pCut->nLimit == 5 )
+                {
+                    extern int If_CluCheckDecInAny( word t, int nVars );
+                    extern int If_CluCheckDecOut( word t, int nVars );
+                    unsigned TruthU = *If_CutTruth(p, pCut);
+                    word Truth = (((word)TruthU << 32) | (word)TruthU);
+                    p->nCuts5++;
+                    if ( If_CluCheckDecInAny( Truth, 5 ) )
+                        p->nCuts5a++;
+                    else
+                        continue;
+                }
+                else if ( p->pPars->fVerbose && pCut->nLeaves == 5 )
+                {
+                    extern int If_CluCheckDecInAny( word t, int nVars );
+                    extern int If_CluCheckDecOut( word t, int nVars );
+                    unsigned TruthU = *If_CutTruth(p, pCut);
+                    word Truth = (((word)TruthU << 32) | (word)TruthU);
+                    p->nCuts5++;
+                    if ( If_CluCheckDecInAny( Truth, 5 ) || If_CluCheckDecOut( Truth, 5 ) )
+                        p->nCuts5a++;
+                }
+            }
+        }
+        
+        // compute the application-specific cost and depth
+        pCut->fUser = (p->pPars->pFuncCost != NULL);
+        pCut->Cost = p->pPars->pFuncCost? p->pPars->pFuncCost(p, pCut) : 0;
+        if ( pCut->Cost == IF_COST_MAX )
+            continue;
+        // check if the cut satisfies the required times
+        if ( p->pPars->fDelayOpt )
+        {
+            pCut->Delay = If_CutSopBalanceEval( p, pCut, NULL );
+//            if ( pCut->Delay >= pObj->Level && pCut->nLeaves > 2 )
+//                pCut->Delay += 1;
+        }
+        else if ( p->pPars->fDsdBalance )
+        {
+            pCut->Delay = If_CutDsdBalanceEval( p, pCut, NULL );
+//            if ( pCut->Delay >= pObj->Level && pCut->nLeaves > 2 )
+//                pCut->Delay += 1;
+        }
+        else if ( p->pPars->fUserRecLib )
+        {
+            pCut->Delay = If_CutDelayRecCost3( p, pCut, pObj ); 
+//            if ( pCut->Delay >= pObj->Level && pCut->nLeaves > 2 )
+//                pCut->Delay += 1;
+        }
+        else if ( p->pPars->fDelayOptLut )
+            pCut->Delay = If_CutLutBalanceEval( p, pCut );
+        else if( p->pPars->nGateSize > 0 )
+            pCut->Delay = If_CutDelaySop( p, pCut );
+        else 
+            pCut->Delay = If_CutDelay( p, pObj, pCut );
+        if ( pCut->Delay == -1 )
+            continue;
+        if ( Mode && pCut->Delay > pObj->Required + p->fEpsilon )
+            continue;
+        // compute area of the cut (this area may depend on the application specific cost)
+        pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut ) : If_CutAreaFlow( p, pCut );
+        if ( p->pPars->fEdge )
+            pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( p, pCut );
+        if ( p->pPars->fPower )
+            pCut->Power = (Mode == 2)? If_CutPowerDerefed( p, pCut, pObj ) : If_CutPowerFlow( p, pCut, pObj );
+//        pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut );
+        // insert the cut into storage
+        If_CutSort( p, pCutSet, pCut );
+//        If_CutTraverse( p, pObj, pCut );
+    } 
+    assert( pCutSet->nCuts > 0 );
+//    If_CutVerifyCuts( pCutSet, !p->pPars->fUseTtPerm );
+
+    // update the best cut
+    if ( !fPreprocess || pCutSet->ppCuts[0]->Delay <= pObj->Required + p->fEpsilon )
+    {
+        If_CutCopy( p, If_ObjCutBest(pObj), pCutSet->ppCuts[0] );
+        if(p->pPars->fUserRecLib)
+            assert(If_ObjCutBest(pObj)->Cost < IF_COST_MAX && If_ObjCutBest(pObj)->Delay < ABC_INFINITY);
+    }
+    // add the trivial cut to the set
+    if ( !pObj->fSkipCut && If_ObjCutBest(pObj)->nLeaves > 1 )
+    {
+        If_ManSetupCutTriv( p, pCutSet->ppCuts[pCutSet->nCuts++], pObj->Id );
+        assert( pCutSet->nCuts <= pCutSet->nCutsMax+1 );
+    }
+//    if ( If_ObjCutBest(pObj)->nLeaves == 0 )
+//        p->nBestCutSmall[0]++;
+//    else if ( If_ObjCutBest(pObj)->nLeaves == 1 )
+//        p->nBestCutSmall[1]++;
+
+    // ref the selected cut
+    if ( Mode && pObj->nRefs > 0 )
+        If_CutAreaRef( p, If_ObjCutBest(pObj) );
+    if ( If_ObjCutBest(pObj)->fUseless )
+        Abc_Print( 1, "The best cut is useless.\n" );
+    // call the user specified function for each cut
+    if ( p->pPars->pFuncUser )
+        If_ObjForEachCut( pObj, pCut, i )
+            p->pPars->pFuncUser( p, pObj, pCut );
+    // free the cuts
+    If_ManDerefNodeCutSet( p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the best cut for the choice node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess )
+{
+    If_Set_t * pCutSet;
+    If_Obj_t * pTemp;
+    If_Cut_t * pCutTemp, * pCut;
+    int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib;
+    assert( pObj->pEquiv != NULL );
+
+    // prepare
+    if ( Mode && pObj->nRefs > 0 )
+        If_CutAreaDeref( p, If_ObjCutBest(pObj) );
+
+    // remove elementary cuts
+    for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv )
+        pTemp->pCutSet->nCuts--;
+
+    // update the cutset of the node
+    pCutSet = pObj->pCutSet;
+
+    // generate cuts
+    for ( pTemp = pObj->pEquiv; pTemp; pTemp = pTemp->pEquiv )
+    {
+        if ( pTemp->pCutSet->nCuts == 0 )
+            continue;
+        // go through the cuts of this node
+        If_ObjForEachCut( pTemp, pCutTemp, i )
+        {
+            if ( pCutTemp->fUseless )
+                continue;
+            // get the next free cut
+            assert( pCutSet->nCuts <= pCutSet->nCutsMax );
+            pCut = pCutSet->ppCuts[pCutSet->nCuts];
+            // copy the cut into storage
+            If_CutCopy( p, pCut, pCutTemp );
+            // check if this cut is contained in any of the available cuts
+            if ( If_CutFilter( pCutSet, pCut, fSave0 ) )
+                continue;
+            // check if the cut satisfies the required times
+//            assert( pCut->Delay == If_CutDelay( p, pTemp, pCut ) );
+            if ( Mode && pCut->Delay > pObj->Required + p->fEpsilon )
+                continue;
+            // set the phase attribute
+            pCut->fCompl = pObj->fPhase ^ pTemp->fPhase;
+            // compute area of the cut (this area may depend on the application specific cost)
+            pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut ) : If_CutAreaFlow( p, pCut );
+            if ( p->pPars->fEdge )
+                pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( p, pCut );
+            if ( p->pPars->fPower )
+                pCut->Power = (Mode == 2)? If_CutPowerDerefed( p, pCut, pObj ) : If_CutPowerFlow( p, pCut, pObj );
+//            pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut );
+            // insert the cut into storage
+            If_CutSort( p, pCutSet, pCut );
+        }
+    } 
+    assert( pCutSet->nCuts > 0 );
+
+    // update the best cut
+    if ( !fPreprocess || pCutSet->ppCuts[0]->Delay <= pObj->Required + p->fEpsilon )
+        If_CutCopy( p, If_ObjCutBest(pObj), pCutSet->ppCuts[0] );
+    // add the trivial cut to the set
+    if ( !pObj->fSkipCut && If_ObjCutBest(pObj)->nLeaves > 1 )
+    {
+        If_ManSetupCutTriv( p, pCutSet->ppCuts[pCutSet->nCuts++], pObj->Id );
+        assert( pCutSet->nCuts <= pCutSet->nCutsMax+1 );
+    }
+
+    // ref the selected cut
+    if ( Mode && pObj->nRefs > 0 )
+        If_CutAreaRef( p, If_ObjCutBest(pObj) );
+    // free the cuts
+    If_ManDerefChoiceCutSet( p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one mapping pass over all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPreprocess, int fFirst, char * pLabel )
+{
+//    ProgressBar * pProgress;
+    If_Obj_t * pObj;
+    int i;
+    abctime clk = Abc_Clock();
+    float arrTime;
+    assert( Mode >= 0 && Mode <= 2 );
+    p->nBestCutSmall[0] = p->nBestCutSmall[1] = 0;
+    // set the sorting function
+    if ( Mode || p->pPars->fArea ) // area
+        p->SortMode = 1;
+    else if ( p->pPars->fFancy )
+        p->SortMode = 2;
+    else
+        p->SortMode = 0;
+    // set the cut number
+    p->nCutsUsed   = nCutsUsed;
+    p->nCutsMerged = 0;
+    // make sure the visit counters are all zero
+    If_ManForEachNode( p, pObj, i )
+        assert( pObj->nVisits == pObj->nVisitsCopy );
+    // map the internal nodes
+    if ( p->pManTim != NULL )
+    {
+        Tim_ManIncrementTravId( p->pManTim );
+        If_ManForEachObj( p, pObj, i )
+        {
+            if ( If_ObjIsAnd(pObj) )
+            {
+                If_ObjPerformMappingAnd( p, pObj, Mode, fPreprocess, fFirst );
+                if ( pObj->fRepr )
+                    If_ObjPerformMappingChoice( p, pObj, Mode, fPreprocess );
+            }
+            else if ( If_ObjIsCi(pObj) )
+            {
+//Abc_Print( 1, "processing CI %d\n", pObj->Id );
+                arrTime = Tim_ManGetCiArrival( p->pManTim, pObj->IdPio );
+                If_ObjSetArrTime( pObj, arrTime );
+            }
+            else if ( If_ObjIsCo(pObj) )
+            {
+                arrTime = If_ObjArrTime( If_ObjFanin0(pObj) );
+                Tim_ManSetCoArrival( p->pManTim, pObj->IdPio, arrTime );
+            }
+            else if ( If_ObjIsConst1(pObj) )
+            {
+            }
+            else
+                assert( 0 );
+        }
+//        Tim_ManPrint( p->pManTim );
+    }
+    else
+    {
+    //    pProgress = Extra_ProgressBarStart( stdout, If_ManObjNum(p) );
+        If_ManForEachNode( p, pObj, i )
+        {
+    //        Extra_ProgressBarUpdate( pProgress, i, pLabel );
+            If_ObjPerformMappingAnd( p, pObj, Mode, fPreprocess, fFirst );
+            if ( pObj->fRepr )
+                If_ObjPerformMappingChoice( p, pObj, Mode, fPreprocess );
+        }
+    }
+//    Extra_ProgressBarStop( pProgress );
+    // make sure the visit counters are all zero
+    If_ManForEachNode( p, pObj, i )
+        assert( pObj->nVisits == 0 );
+    // compute required times and stats
+    If_ManComputeRequired( p );
+//    Tim_ManPrint( p->pManTim );
+    if ( p->pPars->fVerbose )
+    {
+        char Symb = fPreprocess? 'P' : ((Mode == 0)? 'D' : ((Mode == 1)? 'F' : 'A'));
+        Abc_Print( 1, "%c:  Del = %7.2f.  Ar = %9.1f.  Edge = %8d.  ", 
+            Symb, p->RequiredGlo, p->AreaGlo, p->nNets );
+        if ( p->dPower )
+        Abc_Print( 1, "Switch = %7.2f.  ", p->dPower );
+        Abc_Print( 1, "Cut = %8d.  ", p->nCutsMerged );
+        Abc_PrintTime( 1, "T", Abc_Clock() - clk );
+//    Abc_Print( 1, "Max number of cuts = %d. Average number of cuts = %5.2f.\n", 
+//        p->nCutsMax, 1.0 * p->nCutsMerged / If_ManAndNum(p) );
+    }
+    return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifReduce.c b/abc-build/src/map/if/ifReduce.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifReduce.c
@@ -0,0 +1,466 @@
+/**CFile****************************************************************
+
+  FileName    [ifExpand.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Incremental improvement of current mapping.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifExpand.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void If_ManImproveExpand( If_Man_t * p, int nLimit );
+static void If_ManImproveNodeExpand( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited );
+static void If_ManImproveNodePrepare( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited );
+static void If_ManImproveNodeUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront );
+static void If_ManImproveNodeFaninCompact( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Improves current mapping using expand/Expand of one cut.]
+
+  Description [Assumes current mapping assigned and required times computed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManImproveMapping( If_Man_t * p )
+{
+    abctime clk;
+
+    clk = Abc_Clock();
+    If_ManImproveExpand( p, p->pPars->nLutSize );
+    If_ManComputeRequired( p );
+    if ( p->pPars->fVerbose )
+    {
+        Abc_Print( 1, "E:  Del = %7.2f.  Ar = %9.1f.  Edge = %8d.  ", 
+            p->RequiredGlo, p->AreaGlo, p->nNets );
+        if ( p->dPower )
+        Abc_Print( 1, "Switch = %7.2f.  ", p->dPower );
+        Abc_Print( 1, "Cut = %8d.  ", p->nCutsMerged );
+        Abc_PrintTime( 1, "T", Abc_Clock() - clk );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs area recovery for each node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManImproveExpand( If_Man_t * p, int nLimit )
+{
+    Vec_Ptr_t * vFront, * vFrontOld, * vVisited;
+    If_Obj_t * pObj;
+    int i;
+    vFront    = Vec_PtrAlloc( nLimit );
+    vFrontOld = Vec_PtrAlloc( nLimit );
+    vVisited  = Vec_PtrAlloc( 100 );
+    // iterate through all nodes in the topological order
+    If_ManForEachNode( p, pObj, i )
+        If_ManImproveNodeExpand( p, pObj, nLimit, vFront, vFrontOld, vVisited );
+    Vec_PtrFree( vFront );
+    Vec_PtrFree( vFrontOld );
+    Vec_PtrFree( vVisited );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of nodes with no external fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManImproveCutCost( If_Man_t * p, Vec_Ptr_t * vFront )
+{
+    If_Obj_t * pFanin;
+    int i, Counter = 0;
+    Vec_PtrForEachEntry( If_Obj_t *, vFront, pFanin, i )
+        if ( pFanin->nRefs == 0 )
+            Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs area recovery for each node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManImproveNodeExpand( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited )
+{
+    If_Obj_t * pFanin;
+    If_Cut_t * pCut;
+    int CostBef, CostAft, i;
+    float DelayOld, AreaBef, AreaAft;
+    pCut = If_ObjCutBest(pObj);
+    pCut->Delay = If_CutDelay( p, pObj, pCut );
+    assert( pCut->Delay <= pObj->Required + p->fEpsilon );
+    if ( pObj->nRefs == 0 )
+        return;
+    // get the delay
+    DelayOld = pCut->Delay;
+    // get the area
+    AreaBef = If_CutAreaRefed( p, pCut );
+//    if ( AreaBef == 1 )
+//        return;
+    // the cut is non-trivial
+    If_ManImproveNodePrepare( p, pObj, nLimit, vFront, vFrontOld, vVisited );
+    // iteratively modify the cut
+    If_CutAreaDeref( p, pCut );
+    CostBef = If_ManImproveCutCost( p, vFront );
+    If_ManImproveNodeFaninCompact( p, pObj, nLimit, vFront, vVisited );
+    CostAft = If_ManImproveCutCost( p, vFront );
+    If_CutAreaRef( p, pCut );
+    assert( CostBef >= CostAft );
+    // clean up
+    Vec_PtrForEachEntry( If_Obj_t *, vVisited, pFanin, i )
+        pFanin->fMark = 0;
+    // update the node
+    If_ManImproveNodeUpdate( p, pObj, vFront );
+    pCut->Delay = If_CutDelay( p, pObj, pCut );
+    // get the new area
+    AreaAft = If_CutAreaRefed( p, pCut );
+    if ( AreaAft > AreaBef || pCut->Delay > pObj->Required + p->fEpsilon )
+    {
+        If_ManImproveNodeUpdate( p, pObj, vFrontOld );
+        AreaAft = If_CutAreaRefed( p, pCut );
+        assert( AreaAft == AreaBef );
+        pCut->Delay = DelayOld;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs area recovery for each node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManImproveMark_rec( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vVisited )
+{
+    if ( pObj->fMark )
+        return;
+    assert( If_ObjIsAnd(pObj) );
+    If_ManImproveMark_rec( p, If_ObjFanin0(pObj), vVisited );
+    If_ManImproveMark_rec( p, If_ObjFanin1(pObj), vVisited );
+    Vec_PtrPush( vVisited, pObj );
+    pObj->fMark = 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares node mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManImproveNodePrepare( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited )
+{
+    If_Cut_t * pCut;
+    If_Obj_t * pLeaf;
+    int i;
+    Vec_PtrClear( vFront );
+    Vec_PtrClear( vFrontOld );
+    Vec_PtrClear( vVisited );
+    // expand the cut downwards from the given place
+    pCut = If_ObjCutBest(pObj);
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+    {
+        Vec_PtrPush( vFront, pLeaf );
+        Vec_PtrPush( vFrontOld, pLeaf );
+        Vec_PtrPush( vVisited, pLeaf );
+        pLeaf->fMark = 1;
+    }
+    // mark the nodes in the cone
+    If_ManImproveMark_rec( p, pObj, vVisited );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the frontier.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManImproveNodeUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront )
+{
+    If_Cut_t * pCut;
+    If_Obj_t * pFanin;
+    int i;
+    pCut = If_ObjCutBest(pObj);
+    // deref node's cut
+    If_CutAreaDeref( p, pCut );
+    // update the node's cut
+    pCut->nLeaves = Vec_PtrSize(vFront);
+    Vec_PtrForEachEntry( If_Obj_t *, vFront, pFanin, i )
+        pCut->pLeaves[i] = pFanin->Id;
+    If_CutOrder( pCut );
+    pCut->uSign = If_ObjCutSignCompute(pCut);
+    // ref the new cut
+    If_CutAreaRef( p, pCut );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the number of fanins will grow.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManImproveNodeWillGrow( If_Man_t * p, If_Obj_t * pObj )
+{
+    If_Obj_t * pFanin0, * pFanin1;
+    assert( If_ObjIsAnd(pObj) );
+    pFanin0 = If_ObjFanin0(pObj);
+    pFanin1 = If_ObjFanin1(pObj);
+    return !pFanin0->fMark && !pFanin1->fMark;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the increase in the number of fanins with no external refs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManImproveNodeFaninCost( If_Man_t * p, If_Obj_t * pObj )
+{
+    int Counter = 0;
+    assert( If_ObjIsAnd(pObj) );
+    // check if the node has external refs
+    if ( pObj->nRefs == 0 )
+        Counter--;
+    // increment the number of fanins without external refs
+    if ( !If_ObjFanin0(pObj)->fMark && If_ObjFanin0(pObj)->nRefs == 0 )
+        Counter++;
+    // increment the number of fanins without external refs
+    if ( !If_ObjFanin1(pObj)->fMark && If_ObjFanin1(pObj)->nRefs == 0 )
+        Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the frontier.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManImproveNodeFaninUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
+{
+    If_Obj_t * pFanin;
+    assert( If_ObjIsAnd(pObj) );
+    Vec_PtrRemove( vFront, pObj );
+    pFanin = If_ObjFanin0(pObj);
+    if ( !pFanin->fMark )
+    {
+        Vec_PtrPush( vFront, pFanin );
+        Vec_PtrPush( vVisited, pFanin );
+        pFanin->fMark = 1;
+    }
+    pFanin = If_ObjFanin1(pObj);
+    if ( !pFanin->fMark )
+    {
+        Vec_PtrPush( vFront, pFanin );
+        Vec_PtrPush( vVisited, pFanin );
+        pFanin->fMark = 1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compacts the number of external refs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManImproveNodeFaninCompact0( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
+{
+    If_Obj_t * pFanin;
+    int i;
+    Vec_PtrForEachEntry( If_Obj_t *, vFront, pFanin, i )
+    {
+        if ( If_ObjIsCi(pFanin) )
+            continue;
+        if ( If_ManImproveNodeWillGrow(p, pFanin) )
+            continue;
+        if ( If_ManImproveNodeFaninCost(p, pFanin) <= 0 )
+        {
+            If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited );
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compacts the number of external refs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManImproveNodeFaninCompact1( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
+{
+    If_Obj_t * pFanin;
+    int i;
+    Vec_PtrForEachEntry( If_Obj_t *, vFront, pFanin, i )
+    {
+        if ( If_ObjIsCi(pFanin) )
+            continue;
+        if ( If_ManImproveNodeFaninCost(p, pFanin) < 0 )
+        {
+            If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited );
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compacts the number of external refs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManImproveNodeFaninCompact2( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
+{
+    If_Obj_t * pFanin;
+    int i;
+    Vec_PtrForEachEntry( If_Obj_t *, vFront, pFanin, i )
+    {
+        if ( If_ObjIsCi(pFanin) )
+            continue;
+        if ( If_ManImproveNodeFaninCost(p, pFanin) <= 0 )
+        {
+            If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited );
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compacts the number of external refs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManImproveNodeFaninCompact_int( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
+{
+    if ( If_ManImproveNodeFaninCompact0(p, pObj, nLimit, vFront, vVisited) )
+        return 1;
+    if (  Vec_PtrSize(vFront) < nLimit && If_ManImproveNodeFaninCompact1(p, pObj, nLimit, vFront, vVisited) )
+        return 1;
+//    if ( Vec_PtrSize(vFront) < nLimit && If_ManImproveNodeFaninCompact2(p, pObj, nLimit, vFront, vVisited) )
+//        return 1;
+    assert( Vec_PtrSize(vFront) <= nLimit );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compacts the number of external refs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManImproveNodeFaninCompact( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
+{
+    while ( If_ManImproveNodeFaninCompact_int( p, pObj, nLimit, vFront, vVisited ) );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifSat.c b/abc-build/src/map/if/ifSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifSat.c
@@ -0,0 +1,547 @@
+/**CFile****************************************************************
+
+  FileName    [ifSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [SAT-based evaluation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifSat.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+#include "sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    [Builds SAT instance for the given structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * If_ManSatBuildXY( int nLutSize )
+{
+    int nMintsL = (1 << nLutSize);
+    int nMintsF = (1 << (2 * nLutSize - 1));
+    int nVars   = 2 * nMintsL + nMintsF;
+    int iVarP0  = 0;           // LUT0 parameters (total nMintsL)
+    int iVarP1  = nMintsL;     // LUT1 parameters (total nMintsL)
+    int m,iVarM = 2 * nMintsL; // MUX vars        (total nMintsF)
+    sat_solver * p = sat_solver_new();
+    sat_solver_setnvars( p, nVars );
+    for ( m = 0; m < nMintsF; m++ )
+        sat_solver_add_mux( p, 
+            iVarP0 + m % nMintsL, 
+            iVarP1 + 2 * (m / nMintsL) + 1, 
+            iVarP1 + 2 * (m / nMintsL), 
+            iVarM + m );
+    return p;
+}
+void * If_ManSatBuildXYZ( int nLutSize )
+{
+    int nMintsL = (1 << nLutSize);
+    int nMintsF = (1 << (3 * nLutSize - 2));
+    int nVars   = 3 * nMintsL + nMintsF;
+    int iVarP0  = 0;           // LUT0 parameters (total nMintsL)
+    int iVarP1  = nMintsL;     // LUT1 parameters (total nMintsL)
+    int iVarP2  = 2 * nMintsL; // LUT2 parameters (total nMintsL)
+    int m,iVarM = 3 * nMintsL; // MUX vars        (total nMintsF)
+    sat_solver * p = sat_solver_new();
+    sat_solver_setnvars( p, nVars );
+    for ( m = 0; m < nMintsF; m++ )
+        sat_solver_add_mux41( p, 
+            iVarP0 + m % nMintsL, 
+            iVarP1 + (m >> nLutSize) % nMintsL, 
+            iVarP2 + 4 * (m >> (2 * nLutSize)) + 0, 
+            iVarP2 + 4 * (m >> (2 * nLutSize)) + 1, 
+            iVarP2 + 4 * (m >> (2 * nLutSize)) + 2, 
+            iVarP2 + 4 * (m >> (2 * nLutSize)) + 3, 
+            iVarM + m );
+    return p;
+}
+void If_ManSatUnbuild( void * p )
+{
+    if ( p )
+        sat_solver_delete( (sat_solver *)p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verification for 6-input function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static word If_ManSat6ComposeLut4( int t, word f[4], int k )
+{
+    int m, v, nMints = (1 << k);
+    word c, r = 0;
+    assert( k <= 4 );
+    for ( m = 0; m < nMints; m++ )
+    {
+        if ( !((t >> m) & 1) )
+            continue;
+        c = ~(word)0;
+        for ( v = 0; v < k; v++ )
+            c &= ((m >> v) & 1) ? f[v] : ~f[v];
+        r |= c;
+    }
+    return r;
+}
+word If_ManSat6Truth( word uBound, word uFree, int * pBSet, int nBSet, int * pSSet, int nSSet, int * pFSet, int nFSet )
+{
+    word r, q, f[4];
+    int i, k = 0;
+    // bound set vars
+    for ( i = 0; i < nSSet; i++ )
+        f[k++] = s_Truths6[pSSet[i]];
+    for ( i = 0; i < nBSet; i++ )
+        f[k++] = s_Truths6[pBSet[i]];
+    q = If_ManSat6ComposeLut4( (int)(uBound & 0xffff), f, k );
+    // free set vars
+    k = 0;
+    f[k++] = q;
+    for ( i = 0; i < nSSet; i++ )
+        f[k++] = s_Truths6[pSSet[i]];
+    for ( i = 0; i < nFSet; i++ )
+        f[k++] = s_Truths6[pFSet[i]];
+    r = If_ManSat6ComposeLut4( (int)(uFree & 0xffff), f, k );
+    return r;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns config string for the given truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManSatCheckXY( void * pSat, int nLutSize, word * pTruth, int nVars, unsigned uSet, word * pTBound, word * pTFree, Vec_Int_t * vLits )
+{
+    sat_solver * p = (sat_solver *)pSat;
+    int iBSet, nBSet = 0, pBSet[IF_MAX_FUNC_LUTSIZE];
+    int iSSet, nSSet = 0, pSSet[IF_MAX_FUNC_LUTSIZE];
+    int iFSet, nFSet = 0, pFSet[IF_MAX_FUNC_LUTSIZE];
+    int nMintsL = (1 << nLutSize);
+    int nMintsF = (1 << (2 * nLutSize - 1));
+    int v, Value, m, mNew, nMintsFNew, nMintsLNew;
+    word Res;
+    // collect variable sets
+    Dau_DecSortSet( uSet, nVars, &nBSet, &nSSet, &nFSet );
+    assert( nBSet + nSSet + nFSet == nVars );
+    // check variable bounds
+    assert( nSSet + nBSet <= nLutSize );
+    assert( nLutSize + nSSet + nFSet <= 2*nLutSize - 1 );
+    nMintsFNew = (1 << (nLutSize + nSSet + nFSet));
+    // remap minterms
+    Vec_IntFill( vLits, nMintsF, -1 );
+    for ( m = 0; m < (1 << nVars); m++ )
+    {
+        mNew = iBSet = iSSet = iFSet = 0;
+        for ( v = 0; v < nVars; v++ )
+        {
+            Value = ((uSet >> (v << 1)) & 3);
+            if ( Value == 0 ) // FS
+            {
+                if ( ((m >> v) & 1) )
+                    mNew |= 1 << (nLutSize + nSSet + iFSet), pFSet[iFSet] = v;
+                iFSet++;
+            }
+            else if ( Value == 1 ) // BS
+            {
+                if ( ((m >> v) & 1) )
+                    mNew |= 1 << (nSSet + iBSet), pBSet[iBSet] = v;
+                iBSet++;
+            }
+            else if ( Value == 3 ) // SS
+            {
+                if ( ((m >> v) & 1) )
+                {
+                    mNew |= 1 << iSSet;
+                    mNew |= 1 << (nLutSize + iSSet);
+                    pSSet[iSSet] = v;
+                }
+                iSSet++;
+            }
+            else assert( Value == 0 );
+        }
+        assert( iBSet == nBSet && iFSet == nFSet );
+        assert( Vec_IntEntry(vLits, mNew) == -1 );
+        Vec_IntWriteEntry( vLits, mNew, Abc_TtGetBit(pTruth, m) );
+    }
+    // find assumptions
+    v = 0;
+    Vec_IntForEachEntry( vLits, Value, m )
+    {
+//        printf( "%d", (Value >= 0) ? Value : 2 );
+        if ( Value >= 0 )
+            Vec_IntWriteEntry( vLits, v++, Abc_Var2Lit(2 * nMintsL + m, !Value) );
+    }
+    Vec_IntShrink( vLits, v );
+//    printf( " %d\n", Vec_IntSize(vLits) );
+    // run SAT solver
+    Value = sat_solver_solve( p, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 );
+    if ( Value != l_True )
+        return 0;
+    if ( pTBound && pTFree )
+    {
+        // collect config
+        assert( nSSet + nBSet <= nLutSize );
+        *pTBound = 0;
+        nMintsLNew = (1 << (nSSet + nBSet));
+        for ( m = 0; m < nMintsLNew; m++ )
+            if ( sat_solver_var_value(p, m) )
+                Abc_TtSetBit( pTBound, m );
+        *pTBound = Abc_Tt6Stretch( *pTBound, nSSet + nBSet );
+        // collect configs
+        assert( nSSet + nFSet + 1 <= nLutSize );
+        *pTFree = 0;
+        nMintsLNew = (1 << (1 + nSSet + nFSet));
+        for ( m = 0; m < nMintsLNew; m++ )
+            if ( sat_solver_var_value(p, nMintsL+m) )
+                Abc_TtSetBit( pTFree, m );
+        *pTFree = Abc_Tt6Stretch( *pTFree, 1 + nSSet + nFSet );
+        if ( nVars != 6 || nLutSize != 4 )
+            return 1;
+        // verify the result
+        Res = If_ManSat6Truth( *pTBound, *pTFree, pBSet, nBSet, pSSet, nSSet, pFSet, nFSet );
+        if ( pTruth[0] != Res )
+	    {
+            Dau_DsdPrintFromTruth( pTruth,  nVars );
+            Dau_DsdPrintFromTruth( &Res,    nVars );
+            Dau_DsdPrintFromTruth( pTBound, nSSet+nBSet );
+            Dau_DsdPrintFromTruth( pTFree,  nSSet+nFSet+1 );
+            printf( "Verification failed!\n" );
+	    }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns config string for the given truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned If_ManSatCheckXYall_int( void * pSat, int nLutSize, word * pTruth, int nVars, Vec_Int_t * vLits )
+{
+    unsigned uSet = 0;
+    int nTotal = 2 * nLutSize - 1;
+    int nShared = nTotal - nVars;
+    int i[6], s[4];
+    assert( nLutSize >= 2 && nLutSize <= 6 );
+    assert( nLutSize < nVars && nVars <= nTotal );
+    assert( nShared >= 0 && nShared < nLutSize - 1 );
+    if ( nLutSize == 2 )
+    {
+        assert( nShared == 0 );
+        for ( i[0] = 0;      i[0] < nVars; i[0]++ )
+        for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ )
+        {
+            uSet = (1 << (2*i[0])) | (1 << (2*i[1]));
+            if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet, NULL, NULL, vLits) )
+                return uSet;
+        }
+    }
+    else if ( nLutSize == 3 )
+    {
+        for ( i[0] = 0;      i[0] < nVars; i[0]++ )
+        for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ )
+        for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ )
+        {
+            uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2]));
+            if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet, NULL, NULL, vLits) )
+                return uSet;
+        }
+        if ( nShared < 1 )
+            return 0;
+        for ( i[0] = 0;      i[0] < nVars; i[0]++ )
+        for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ )
+        for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ )
+        {
+            uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2]));
+            for ( s[0] = 0; s[0] < nLutSize; s[0]++ )
+                if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])), NULL, NULL, vLits) )
+                    return uSet | (3 << (2*i[s[0]]));
+        }
+    }
+    else if ( nLutSize == 4 )
+    {
+        for ( i[0] = 0;      i[0] < nVars; i[0]++ )
+        for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ )
+        for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ )
+        for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ )
+        {
+            uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3]));
+            if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet, NULL, NULL, vLits) )
+                return uSet;
+        }
+        if ( nShared < 1 )
+            return 0;
+        for ( i[0] = 0;      i[0] < nVars; i[0]++ )
+        for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ )
+        for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ )
+        for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ )
+        {
+            uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3]));
+            for ( s[0] = 0; s[0] < nLutSize; s[0]++ )
+                if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])), NULL, NULL, vLits) )
+                    return uSet | (3 << (2*i[s[0]]));
+        }
+        if ( nShared < 2 )
+            return 0;
+        for ( i[0] = 0;      i[0] < nVars; i[0]++ )
+        for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ )
+        for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ )
+        for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ )
+        {
+            uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3]));
+            {
+                for ( s[0] = 0;      s[0] < nLutSize; s[0]++ )
+                for ( s[1] = s[0]+1; s[1] < nLutSize; s[1]++ )
+                    if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])), NULL, NULL, vLits) )
+                        return uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]]));
+            }
+        }
+    }
+    else if ( nLutSize == 5 )
+    {
+        for ( i[0] = 0;      i[0] < nVars; i[0]++ )
+        for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ )
+        for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ )
+        for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ )
+        for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ )
+        {
+            uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4]));
+            if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet, NULL, NULL, vLits) )
+                return uSet;
+        }
+        if ( nShared < 1 )
+            return 0;
+        for ( i[0] = 0;      i[0] < nVars; i[0]++ )
+        for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ )
+        for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ )
+        for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ )
+        for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ )
+        {
+            uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4]));
+            for ( s[0] = 0; s[0] < nLutSize; s[0]++ )
+                if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])), NULL, NULL, vLits) )
+                    return uSet | (3 << (2*i[s[0]]));
+        }
+        if ( nShared < 2 )
+            return 0;
+        for ( i[0] = 0;      i[0] < nVars; i[0]++ )
+        for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ )
+        for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ )
+        for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ )
+        for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ )
+        {
+            uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4]));
+            for ( s[0] = 0;      s[0] < nLutSize; s[0]++ )
+            for ( s[1] = s[0]+1; s[1] < nLutSize; s[1]++ )
+                if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])), NULL, NULL, vLits) )
+                    return uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]]));
+        }
+        if ( nShared < 3 )
+            return 0;
+        for ( i[0] = 0;      i[0] < nVars; i[0]++ )
+        for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ )
+        for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ )
+        for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ )
+        for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ )
+        {
+            uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4]));
+            for ( s[0] = 0;      s[0] < nLutSize; s[0]++ )
+            for ( s[1] = s[0]+1; s[1] < nLutSize; s[1]++ )
+            for ( s[2] = s[1]+1; s[2] < nLutSize; s[2]++ )
+                if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])) | (3 << (2*i[s[2]])), NULL, NULL, vLits) )
+                    return uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])) | (3 << (2*i[s[2]]));
+        }
+    }
+    else if ( nLutSize == 6 )
+    {
+        for ( i[0] = 0;      i[0] < nVars; i[0]++ )
+        for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ )
+        for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ )
+        for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ )
+        for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ )
+        for ( i[5] = i[4]+1; i[5] < nVars; i[5]++ )
+        {
+            uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4])) | (1 << (2*i[5]));
+            if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet, NULL, NULL, vLits) )
+                return uSet;
+        }
+        if ( nShared < 1 )
+            return 0;
+        for ( i[0] = 0;      i[0] < nVars; i[0]++ )
+        for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ )
+        for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ )
+        for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ )
+        for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ )
+        for ( i[5] = i[4]+1; i[5] < nVars; i[5]++ )
+        {
+            uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4])) | (1 << (2*i[5]));
+            for ( s[0] = 0; s[0] < nLutSize; s[0]++ )
+                if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])), NULL, NULL, vLits) )
+                    return uSet | (3 << (2*i[s[0]]));
+        }
+        if ( nShared < 2 )
+            return 0;
+        for ( i[0] = 0;      i[0] < nVars; i[0]++ )
+        for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ )
+        for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ )
+        for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ )
+        for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ )
+        for ( i[5] = i[4]+1; i[5] < nVars; i[5]++ )
+        {
+            uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4])) | (1 << (2*i[5]));
+            for ( s[0] = 0;      s[0] < nLutSize; s[0]++ )
+            for ( s[1] = s[0]+1; s[1] < nLutSize; s[1]++ )
+                if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])), NULL, NULL, vLits) )
+                    return uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]]));
+        }
+        if ( nShared < 3 )
+            return 0;
+        for ( i[0] = 0;      i[0] < nVars; i[0]++ )
+        for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ )
+        for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ )
+        for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ )
+        for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ )
+        for ( i[5] = i[4]+1; i[5] < nVars; i[5]++ )
+        {
+            uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4])) | (1 << (2*i[5]));
+            for ( s[0] = 0;      s[0] < nLutSize; s[0]++ )
+            for ( s[1] = s[0]+1; s[1] < nLutSize; s[1]++ )
+            for ( s[2] = s[1]+1; s[2] < nLutSize; s[2]++ )
+                if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])) | (3 << (2*i[s[2]])), NULL, NULL, vLits) )
+                    return uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])) | (3 << (2*i[s[2]]));
+        }
+        if ( nShared < 4 )
+            return 0;
+        for ( i[0] = 0;      i[0] < nVars; i[0]++ )
+        for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ )
+        for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ )
+        for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ )
+        for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ )
+        for ( i[5] = i[4]+1; i[5] < nVars; i[5]++ )
+        {
+            uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4])) | (1 << (2*i[5]));
+            for ( s[0] = 0;      s[0] < nLutSize; s[0]++ )
+            for ( s[1] = s[0]+1; s[1] < nLutSize; s[1]++ )
+            for ( s[2] = s[1]+1; s[2] < nLutSize; s[2]++ )
+            for ( s[3] = s[1]+1; s[3] < nLutSize; s[3]++ )
+                if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])) | (3 << (2*i[s[2]])) | (3 << (2*i[s[3]])), NULL, NULL, vLits) )
+                    return uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])) | (3 << (2*i[s[2]])) | (3 << (2*i[s[3]]));
+        }
+    }
+    return 0;
+}
+unsigned If_ManSatCheckXYall( void * pSat, int nLutSize, word * pTruth, int nVars, Vec_Int_t * vLits )
+{
+    unsigned uSet = If_ManSatCheckXYall_int( pSat, nLutSize, pTruth, nVars, vLits );
+//    Dau_DecPrintSet( uSet, nVars, 1 );
+    return uSet;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Test procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManSatTest2()
+{
+    int nVars = 6;
+    int nLutSize = 4;
+    sat_solver * p = (sat_solver *)If_ManSatBuildXY( nLutSize );
+//    char * pDsd = "(abcdefg)";
+//    char * pDsd = "([a!bc]d!e)";
+    char * pDsd = "0123456789ABCDEF{abcdef}";
+    word * pTruth = Dau_DsdToTruth( pDsd, nVars );
+    word uBound, uFree;
+    Vec_Int_t * vLits = Vec_IntAlloc( 100 );
+//    unsigned uSet = (1 << 0) | (1 << 2) | (1 << 4) | (1 << 6);
+//    unsigned uSet = (3 << 0) | (1 << 2) | (1 << 8) | (1 << 4);
+    unsigned uSet = (1 << 0) | (3 << 2) | (1 << 4) | (1 << 6);
+    int RetValue = If_ManSatCheckXY( p, nLutSize, pTruth, nVars, uSet, &uBound, &uFree, vLits );
+    assert( RetValue );
+    
+//    Abc_TtPrintBinary( pTruth, nVars );
+//    Abc_TtPrintBinary( &uBound, nLutSize );
+//    Abc_TtPrintBinary( &uFree, nLutSize );
+
+    Dau_DsdPrintFromTruth( pTruth, nVars );
+    Dau_DsdPrintFromTruth( &uBound, nLutSize );
+    Dau_DsdPrintFromTruth( &uFree, nLutSize );
+    sat_solver_delete(p);
+    Vec_IntFree( vLits );
+}
+void If_ManSatTest3()
+{
+    int nVars = 6;
+    int nLutSize = 4;
+    sat_solver * p = (sat_solver *)If_ManSatBuildXY( nLutSize );
+//    char * pDsd = "(abcdefg)";
+//    char * pDsd = "([a!bc]d!e)";
+    char * pDsd = "0123456789ABCDEF{abcdef}";
+    word * pTruth = Dau_DsdToTruth( pDsd, nVars );
+    Vec_Int_t * vLits = Vec_IntAlloc( 100 );
+//    unsigned uSet = (1 << 0) | (1 << 2) | (1 << 4) | (1 << 6);
+//    unsigned uSet = (3 << 0) | (1 << 2) | (1 << 8) | (1 << 4);
+    unsigned uSet = (1 << 0) | (3 << 2) | (1 << 4) | (1 << 6);
+    uSet = If_ManSatCheckXYall( p, nLutSize, pTruth, nVars, vLits );
+    Dau_DecPrintSet( uSet, nVars, 1 );
+
+    sat_solver_delete(p);
+    Vec_IntFree( vLits );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifSelect.c b/abc-build/src/map/if/ifSelect.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifSelect.c
@@ -0,0 +1,601 @@
+/**CFile****************************************************************
+
+  FileName    [ifSelect.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Cut selection procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifSelect.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+#include "sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the logic cone with choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ObjConePrint_rec( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited )
+{
+    If_Cut_t * pCut;
+    pCut = If_ObjCutBest(pIfObj);
+    if ( If_CutDataInt(pCut) )
+        return;
+    Vec_PtrPush( vVisited, pCut );
+    // insert the worst case
+    If_CutSetDataInt( pCut, ~0 );
+    // skip in case of primary input
+    if ( If_ObjIsCi(pIfObj) )
+        return;
+    // compute the functions of the children
+    if ( pIfObj->pEquiv ) 
+    If_ObjConePrint_rec( pIfMan, pIfObj->pEquiv, vVisited );
+    If_ObjConePrint_rec( pIfMan, pIfObj->pFanin0, vVisited );
+    If_ObjConePrint_rec( pIfMan, pIfObj->pFanin1, vVisited );
+    printf( "%5d = %5d & %5d | %5d\n", pIfObj->Id, pIfObj->pFanin0->Id, pIfObj->pFanin1->Id, pIfObj->pEquiv ? pIfObj->pEquiv->Id : 0 );
+}
+void If_ObjConePrint( If_Man_t * pIfMan, If_Obj_t * pIfObj )
+{
+    If_Cut_t * pCut;
+    If_Obj_t * pLeaf;
+    int i;
+    Vec_PtrClear( pIfMan->vTemp );
+    If_ObjConePrint_rec( pIfMan, pIfObj, pIfMan->vTemp );
+    Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i )
+        If_CutSetDataInt( pCut, 0 );
+    // print the leaf variables
+    printf( "Cut " );
+    pCut = If_ObjCutBest(pIfObj);
+    If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+        printf( "%d ", pLeaf->Id );
+    printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively derives local AIG for the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManNodeShapeMap_rec( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited, Vec_Int_t * vShape )
+{
+    If_Cut_t * pCut;
+    If_Obj_t * pTemp;
+    int i, iFunc0, iFunc1;
+    // get the best cut
+    pCut = If_ObjCutBest(pIfObj);
+    // if the cut is visited, return the result
+    if ( If_CutDataInt(pCut) )
+        return If_CutDataInt(pCut);
+    // mark the node as visited
+    Vec_PtrPush( vVisited, pCut );
+    // insert the worst case
+    If_CutSetDataInt( pCut, ~0 );
+    // skip in case of primary input
+    if ( If_ObjIsCi(pIfObj) )
+        return If_CutDataInt(pCut);
+    // compute the functions of the children
+    for ( i = 0, pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv, i++ )
+    {
+        iFunc0 = If_ManNodeShapeMap_rec( pIfMan, pTemp->pFanin0, vVisited, vShape );
+        if ( iFunc0 == ~0 )
+            continue;
+        iFunc1 = If_ManNodeShapeMap_rec( pIfMan, pTemp->pFanin1, vVisited, vShape );
+        if ( iFunc1 == ~0 )
+            continue;
+        // both branches are solved
+        Vec_IntPush( vShape, pIfObj->Id );
+        Vec_IntPush( vShape, pTemp->Id );
+        If_CutSetDataInt( pCut, 1 );
+        break;
+    }
+    return If_CutDataInt(pCut);
+}
+int If_ManNodeShapeMap( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vShape )
+{
+    If_Cut_t * pCut;
+    If_Obj_t * pLeaf;
+    int i, iRes;
+    // get the best cut
+    pCut = If_ObjCutBest(pIfObj);
+    assert( pCut->nLeaves > 1 );
+    // set the leaf variables
+    If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+    {
+        assert( If_CutDataInt( If_ObjCutBest(pLeaf) ) == 0 );
+        If_CutSetDataInt( If_ObjCutBest(pLeaf), 1 );
+    }
+    // recursively compute the function while collecting visited cuts
+    Vec_IntClear( vShape );
+    Vec_PtrClear( pIfMan->vTemp );
+    iRes = If_ManNodeShapeMap_rec( pIfMan, pIfObj, pIfMan->vTemp, vShape ); 
+    if ( iRes == ~0 )
+    {
+        Abc_Print( -1, "If_ManNodeShapeMap(): Computing local AIG has failed.\n" );
+        return 0;
+    }
+    // clean the cuts
+    If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+        If_CutSetDataInt( If_ObjCutBest(pLeaf), 0 );
+    Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i )
+        If_CutSetDataInt( pCut, 0 );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively derives the local AIG for the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int  If_WordCountOnes( unsigned uWord )
+{
+    uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555);
+    uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333);
+    uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F);
+    uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF);
+    return  (uWord & 0x0000FFFF) + (uWord>>16);
+}
+int If_ManNodeShapeMap2_rec( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited, Vec_Int_t * vShape )
+{
+    If_Cut_t * pCut;
+    If_Obj_t * pTemp, * pTempBest = NULL;
+    int i, iFunc, iFunc0, iFunc1, iBest = 0;
+    // get the best cut
+    pCut = If_ObjCutBest(pIfObj);
+    // if the cut is visited, return the result
+    if ( If_CutDataInt(pCut) )
+        return If_CutDataInt(pCut);
+    // mark the node as visited
+    Vec_PtrPush( vVisited, pCut );
+    // insert the worst case
+    If_CutSetDataInt( pCut, ~0 );
+    // skip in case of primary input
+    if ( If_ObjIsCi(pIfObj) )
+        return If_CutDataInt(pCut);
+    // compute the functions of the children
+    for ( i = 0, pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv, i++ )
+    {
+        iFunc0 = If_ManNodeShapeMap2_rec( pIfMan, pTemp->pFanin0, vVisited, vShape );
+        if ( iFunc0 == ~0 )
+            continue;
+        iFunc1 = If_ManNodeShapeMap2_rec( pIfMan, pTemp->pFanin1, vVisited, vShape );
+        if ( iFunc1 == ~0 )
+            continue;
+        iFunc = iFunc0 | iFunc1;
+//        if ( If_WordCountOnes(iBest) <= If_WordCountOnes(iFunc) )
+        if ( iBest < iFunc )
+        {
+            iBest = iFunc;
+            pTempBest = pTemp;
+        }
+    }
+    if ( pTempBest )
+    {
+        Vec_IntPush( vShape, pIfObj->Id );
+        Vec_IntPush( vShape, pTempBest->Id );
+        If_CutSetDataInt( pCut, iBest );
+    }
+    return If_CutDataInt(pCut);
+}
+int If_ManNodeShapeMap2( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vShape )
+{
+    If_Cut_t * pCut;
+    If_Obj_t * pLeaf;
+    int i, iRes;
+    // get the best cut
+    pCut = If_ObjCutBest(pIfObj);
+    assert( pCut->nLeaves > 1 );
+    // set the leaf variables
+    If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+        If_CutSetDataInt( If_ObjCutBest(pLeaf), (1 << i) );
+    // recursively compute the function while collecting visited cuts
+    Vec_IntClear( vShape );
+    Vec_PtrClear( pIfMan->vTemp );
+    iRes = If_ManNodeShapeMap2_rec( pIfMan, pIfObj, pIfMan->vTemp, vShape ); 
+    if ( iRes == ~0 )
+    {
+        Abc_Print( -1, "If_ManNodeShapeMap2(): Computing local AIG has failed.\n" );
+        return 0;
+    }
+    // clean the cuts
+    If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+        If_CutSetDataInt( If_ObjCutBest(pLeaf), 0 );
+    Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i )
+        If_CutSetDataInt( pCut, 0 );
+    return 1;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects logic cone with choices]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManConeCollect_rec( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited, Vec_Ptr_t * vCone )
+{
+    If_Cut_t * pCut;
+    If_Obj_t * pTemp;
+    int iFunc0, iFunc1;
+    int fRootAdded = 0;
+    int fNodeAdded = 0;
+    // get the best cut
+    pCut = If_ObjCutBest(pIfObj);
+    // if the cut is visited, return the result
+    if ( If_CutDataInt(pCut) )
+        return If_CutDataInt(pCut);
+    // mark the node as visited
+    Vec_PtrPush( vVisited, pCut );
+    // insert the worst case
+    If_CutSetDataInt( pCut, ~0 );
+    // skip in case of primary input
+    if ( If_ObjIsCi(pIfObj) )
+        return If_CutDataInt(pCut);
+    // compute the functions of the children
+    for ( pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv )
+    {
+        iFunc0 = If_ManConeCollect_rec( pIfMan, pTemp->pFanin0, vVisited, vCone );
+        if ( iFunc0 == ~0 )
+            continue;
+        iFunc1 = If_ManConeCollect_rec( pIfMan, pTemp->pFanin1, vVisited, vCone );
+        if ( iFunc1 == ~0 )
+            continue;
+        fNodeAdded = 1;
+        If_CutSetDataInt( pCut, 1 );
+        Vec_PtrPush( vCone, pTemp );
+        if ( fRootAdded == 0 && pTemp == pIfObj )
+            fRootAdded = 1;
+    }
+    if ( fNodeAdded && !fRootAdded )
+        Vec_PtrPush( vCone, pIfObj );
+    return If_CutDataInt(pCut);
+}
+Vec_Ptr_t * If_ManConeCollect( If_Man_t * pIfMan, If_Obj_t * pIfObj, If_Cut_t * pCut )
+{
+    Vec_Ptr_t * vCone;
+    If_Obj_t * pLeaf;
+    int i, RetValue;
+    // set the leaf variables
+    If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+    {
+        assert( If_CutDataInt( If_ObjCutBest(pLeaf) ) == 0 );
+        If_CutSetDataInt( If_ObjCutBest(pLeaf), 1 );
+    }
+    // recursively compute the function while collecting visited cuts
+    vCone = Vec_PtrAlloc( 100 );
+    Vec_PtrClear( pIfMan->vTemp );
+    RetValue = If_ManConeCollect_rec( pIfMan, pIfObj, pIfMan->vTemp, vCone ); 
+    assert( RetValue );
+    // clean the cuts
+    If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+        If_CutSetDataInt( If_ObjCutBest(pLeaf), 0 );
+    Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i )
+        If_CutSetDataInt( pCut, 0 );
+    return vCone;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adding clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void sat_solver_add_choice( sat_solver * pSat, int iVar, Vec_Int_t * vVars )
+{
+    int * pVars = Vec_IntArray(vVars);
+    int nVars = Vec_IntSize(vVars);
+    int i, k, Lits[2], Value;
+    assert( Vec_IntSize(vVars) < Vec_IntCap(vVars) );
+    // create literals
+    for ( i = 0; i < nVars; i++ )
+        pVars[i] = Abc_Var2Lit( pVars[i], 0 );
+    pVars[i] = Abc_Var2Lit( iVar, 1 );
+    // add clause
+    Value = sat_solver_addclause( pSat, pVars, pVars + nVars + 1 );
+    assert( Value );
+    // undo literals
+    for ( i = 0; i < nVars; i++ )
+        pVars[i] = Abc_Lit2Var( pVars[i] );
+    // add !out => !in
+    Lits[0] = Abc_Var2Lit( iVar, 0 );
+    for ( i = 0; i < nVars; i++ )
+    {
+        Lits[1] = Abc_Var2Lit( pVars[i], 1 );
+        Value = sat_solver_addclause( pSat, Lits, Lits + 2 );
+        assert( Value );
+    }
+    // add excluvisity
+    for ( i = 0; i < nVars; i++ )
+    for ( k = i+1; k < nVars; k++ )
+    {
+        Lits[0] = Abc_Var2Lit( pVars[i], 1 );
+        Lits[1] = Abc_Var2Lit( pVars[k], 1 );
+        Value = sat_solver_addclause( pSat, Lits, Lits + 2 );
+        assert( Value );
+    }
+}
+static inline int  If_ObjSatVar( If_Obj_t * pIfObj )            { return If_CutDataInt(If_ObjCutBest(pIfObj));  }
+static inline void If_ObjSetSatVar( If_Obj_t * pIfObj, int v )  { If_CutSetDataInt( If_ObjCutBest(pIfObj), v ); }
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively derives the local AIG for the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManNodeShape2_rec( sat_solver * pSat, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vShape )
+{
+    If_Obj_t * pTemp;
+    assert( sat_solver_var_value(pSat, If_ObjSatVar(pIfObj)) == 1 );
+    if ( pIfObj->fMark )
+        return;
+    pIfObj->fMark = 1;
+    for ( pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv )
+        if ( sat_solver_var_value(pSat, If_ObjSatVar(pTemp)+1) == 1 )
+            break;
+    assert( pTemp != NULL );
+    If_ManNodeShape2_rec( pSat, pIfMan, pTemp->pFanin0, vShape );
+    If_ManNodeShape2_rec( pSat, pIfMan, pTemp->pFanin1, vShape );
+    Vec_IntPush( vShape, pIfObj->Id );
+    Vec_IntPush( vShape, pTemp->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Solve the problem of selecting choices for the given cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManNodeShapeSat( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vShape )
+{
+    sat_solver * pSat;
+    If_Cut_t * pCut;
+    Vec_Ptr_t * vCone;
+    Vec_Int_t * vFanins;
+    If_Obj_t * pObj, * pTemp;
+    int i, Lit, Status;
+
+    // get best cut
+    pCut = If_ObjCutBest(pIfObj);
+    assert( pCut->nLeaves > 1 );
+
+    // collect the cone
+    vCone = If_ManConeCollect( pIfMan, pIfObj, pCut );
+
+    // assign SAT variables
+    // EXTERNAL variable is even numbered
+    // INTERNAL variable is odd numbered
+    If_CutForEachLeaf( pIfMan, pCut, pObj, i )
+    {
+        assert( If_ObjSatVar(pObj) == 0 );
+        If_ObjSetSatVar( pObj, 2*(i+1) );
+    }
+    Vec_PtrForEachEntry( If_Obj_t *, vCone, pObj, i )
+    {
+        assert( If_ObjSatVar(pObj) == 0 );
+        If_ObjSetSatVar( pObj, 2*(i+1+pCut->nLeaves) );
+    }
+
+    // start SAT solver
+    pSat = sat_solver_new();
+    sat_solver_setnvars( pSat, 2 * (pCut->nLeaves + Vec_PtrSize(vCone) + 1) );
+
+    // add constraints
+    vFanins = Vec_IntAlloc( 100 );
+    Vec_PtrForEachEntry( If_Obj_t *, vCone, pObj, i )
+    {
+        assert( If_ObjIsAnd(pObj) );
+        Vec_IntClear( vFanins );
+        for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv )
+            if ( If_ObjSatVar(pTemp) )
+                Vec_IntPush( vFanins, If_ObjSatVar(pTemp)+1 ); // internal
+        assert( Vec_IntSize(vFanins) > 0 );
+        sat_solver_add_choice( pSat, If_ObjSatVar(pObj), vFanins ); // external
+        assert( If_ObjSatVar(pObj) > 0 );
+//        sat_solver_add_and( pSat, If_ObjSatVar(pObj)+1, If_ObjSatVar(pObj->pFanin0), If_ObjSatVar(pObj->pFanin1), 0, 0, 0 );
+        if ( If_ObjSatVar(pObj->pFanin0) > 0 && If_ObjSatVar(pObj->pFanin1) > 0 )
+        {
+            int Lits[2];
+            Lits[0] = Abc_Var2Lit( If_ObjSatVar(pObj)+1,        1 );
+            Lits[1] = Abc_Var2Lit( If_ObjSatVar(pObj->pFanin0), 0 );
+            Status = sat_solver_addclause( pSat, Lits, Lits + 2 );
+            assert( Status );
+
+            Lits[0] = Abc_Var2Lit( If_ObjSatVar(pObj)+1,        1 );
+            Lits[1] = Abc_Var2Lit( If_ObjSatVar(pObj->pFanin1), 0 );
+            Status = sat_solver_addclause( pSat, Lits, Lits + 2 );
+            assert( Status );
+        }
+    }
+    Vec_IntFree( vFanins );
+
+    // set cut variables to 1
+    pCut = If_ObjCutBest(pIfObj);
+    If_CutForEachLeaf( pIfMan, pCut, pObj, i )
+    {
+        Lit = Abc_Var2Lit( If_ObjSatVar(pObj), 0 ); // external
+        Status = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
+        assert( Status );
+    }
+    // set output variable to 1
+    Lit = Abc_Var2Lit( If_ObjSatVar(pIfObj), 0 ); // external
+    Status = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
+    assert( Status );
+
+    // solve the problem
+    Status = sat_solver_solve( pSat, NULL, NULL, 0, 0, 0, 0 );
+    assert( Status == l_True );
+
+    // mark cut nodes
+    If_CutForEachLeaf( pIfMan, pCut, pObj, i )
+    {
+        assert( pObj->fMark == 0 );
+        pObj->fMark = 1;
+    }
+
+    // select the node's shape
+    Vec_IntClear( vShape );
+    assert( pIfObj->fMark == 0 );
+    If_ManNodeShape2_rec( pSat, pIfMan, pIfObj, vShape ); 
+
+    // cleanup
+    sat_solver_delete( pSat );
+    If_CutForEachLeaf( pIfMan, pCut, pObj, i )
+    {
+        If_ObjSetSatVar( pObj, 0 );
+        pObj->fMark = 0;
+    }
+    Vec_PtrForEachEntry( If_Obj_t *, vCone, pObj, i )
+    {
+        If_ObjSetSatVar( pObj, 0 );
+        pObj->fMark = 0;
+    }
+    Vec_PtrFree( vCone );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Verify that the shape is correct.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManCheckShape( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vShape )
+{
+    If_Cut_t * pCut;
+    If_Obj_t * pLeaf;
+    int i, Entry1, Entry2, RetValue = 1;
+    // check that the marks are not set
+    pCut = If_ObjCutBest(pIfObj);
+    If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+        assert( pLeaf->fMark == 0 );
+    // set the marks of the shape
+    Vec_IntForEachEntryDouble( vShape, Entry1, Entry2, i )
+    {
+        pLeaf = If_ManObj(pIfMan, Entry2);
+        pLeaf->pFanin0->fMark = 1;
+        pLeaf->pFanin1->fMark = 1;
+    }
+    // check that the leaves are marked
+    If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+        if ( pLeaf->fMark == 0 )
+            RetValue = 0;
+        else
+            pLeaf->fMark = 0;
+    // clean the inner marks
+    Vec_IntForEachEntryDouble( vShape, Entry1, Entry2, i )
+    {
+        pLeaf = If_ManObj(pIfMan, Entry2);
+        pLeaf->pFanin0->fMark = 0;
+        pLeaf->pFanin1->fMark = 0;
+    }
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively compute the set of nodes supported by the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManNodeShape( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vShape, int fExact )
+{
+    int RetValue;
+//    if ( pIfMan->nChoices == 0 )
+    {
+        RetValue = If_ManNodeShapeMap( pIfMan, pIfObj, vShape );
+        assert( RetValue );
+        if ( !fExact || If_ManCheckShape(pIfMan, pIfObj, vShape) )
+            return 1;
+    }
+//    if ( pIfObj->Id == 1254 && If_ObjCutBest(pIfObj)->nLeaves == 7 )
+//        If_ObjConePrint( pIfMan, pIfObj );
+    RetValue = If_ManNodeShapeMap2( pIfMan, pIfObj, vShape );
+    assert( RetValue );
+    RetValue = If_ManCheckShape(pIfMan, pIfObj, vShape);
+//    assert( RetValue );
+//    printf( "%d", RetValue );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifSeq.c b/abc-build/src/map/if/ifSeq.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifSeq.c
@@ -0,0 +1,397 @@
+/**CFile****************************************************************
+
+  FileName    [ifSeq.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Sequential mapping.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifSeq.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern abctime s_MappingTime;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares for sequential mapping by linking the latches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManPrepareMappingSeq( If_Man_t * p )
+{
+    If_Obj_t * pObjLi, * pObjLo;
+    int i;
+
+    // link the latch outputs (CIs) directly to the drivers of latch inputs (COs)
+    for ( i = 0; i < p->pPars->nLatchesCi; i++ )
+    {
+        pObjLi = If_ManLi( p, i );
+        pObjLo = If_ManLo( p, i );
+        pObjLo->pFanin0 = If_ObjFanin0( pObjLi );
+        pObjLo->fCompl0 = If_ObjFaninC0( pObjLi );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects latches in the topological order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+void If_ManCollectLatches_rec( If_Obj_t * pObj, Vec_Ptr_t * vLatches )
+{
+    if ( !If_ObjIsLatch(pObj) )
+        return;
+    if ( pObj->fMark )
+        return;
+    pObj->fMark = 1;
+    If_ManCollectLatches_rec( pObj->pFanin0, vLatches );
+    Vec_PtrPush( vLatches, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects latches in the topological order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * If_ManCollectLatches( If_Man_t * p )
+{
+    Vec_Ptr_t * vLatches;
+    If_Obj_t * pObj;
+    int i;
+    // collect latches 
+    vLatches = Vec_PtrAlloc( p->pPars->nLatchesCi );
+    If_ManForEachLatchOutput( p, pObj, i )
+        If_ManCollectLatches_rec( pObj, vLatches );
+    // clean marks
+    Vec_PtrForEachEntry( If_Obj_t *, vLatches, pObj, i )
+        pObj->fMark = 0;
+    assert( Vec_PtrSize(vLatches) == p->pPars->nLatchesCi );
+    return vLatches;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one pass of l-value computation over all nodes.]
+
+  Description [Experimentally it was found that checking POs changes
+  is not enough to detect the convergence of l-values in the network.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManPerformMappingRoundSeq( If_Man_t * p, int nIter )
+{
+    If_Obj_t * pObj;
+    int i;
+    abctime clk = Abc_Clock();
+    int fVeryVerbose = 0;
+    int fChange = 0;
+
+    if ( nIter == 1 )
+    {
+        // if some latches depend on PIs, update their values
+        Vec_PtrForEachEntry( If_Obj_t *, p->vLatchOrder, pObj, i )
+        {
+            If_ObjSetLValue( pObj, If_ObjLValue(If_ObjFanin0(pObj)) - p->Period );
+            If_ObjSetArrTime( pObj, If_ObjLValue(pObj) );
+        }
+    }
+
+    // map the internal nodes
+    p->nCutsMerged = 0;
+    If_ManForEachNode( p, pObj, i )
+    {
+        If_ObjPerformMappingAnd( p, pObj, 0, 0, 0 );
+        if ( pObj->fRepr )
+            If_ObjPerformMappingChoice( p, pObj, 0, 0 );
+    }
+
+    // postprocess the mapping
+//Abc_Print( 1, "Itereation %d: \n", nIter );
+    If_ManForEachNode( p, pObj, i )
+    {
+        // update the LValues stored separately
+        if ( If_ObjLValue(pObj) < If_ObjCutBest(pObj)->Delay - p->fEpsilon )
+        {
+            If_ObjSetLValue( pObj, If_ObjCutBest(pObj)->Delay );
+            fChange = 1;
+        }
+//Abc_Print( 1, "%d ", (int)If_ObjLValue(pObj) );
+        // reset the visit counters
+        assert( pObj->nVisits == 0 );
+        pObj->nVisits = pObj->nVisitsCopy;
+    }
+//Abc_Print( 1, "\n" );
+
+    // propagate LValues over the registers
+    Vec_PtrForEachEntry( If_Obj_t *, p->vLatchOrder, pObj, i )
+    {
+        If_ObjSetLValue( pObj, If_ObjLValue(If_ObjFanin0(pObj)) - p->Period );
+        If_ObjSetArrTime( pObj, If_ObjLValue(pObj) );
+    }
+
+    // compute area and delay
+    If_ManMarkMapping( p );
+    if ( fVeryVerbose )
+    {
+        p->RequiredGlo = If_ManDelayMax( p, 1 );
+//        p->AreaGlo = If_ManScanMapping(p);
+        Abc_Print( 1, "S%d:  Fi = %6.2f. Del = %6.2f. Area = %8.2f. Cuts = %8d. ", 
+             nIter, (float)p->Period, p->RequiredGlo, p->AreaGlo, p->nCutsMerged );
+        Abc_PrintTime( 1, "T", Abc_Clock() - clk );
+    }
+    return fChange;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if retiming with this clock period is feasible.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManBinarySearchPeriod( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    int i, c, fConverged;
+//    int fResetRefs = 0;
+    p->nAttempts++;
+
+    // reset initial LValues (PIs to 0; others to -inf)
+    If_ManForEachObj( p, pObj, i )
+    {
+        If_ObjSetLValue( pObj, (float)-IF_INFINITY );
+        If_ObjSetArrTime( pObj, (float)-IF_INFINITY );
+        // undo any previous mapping, except for CIs
+        if ( If_ObjIsAnd(pObj) )
+            If_ObjCutBest(pObj)->nLeaves = 0;
+    }
+    pObj = If_ManConst1( p );
+    If_ObjSetLValue( pObj, (float)0.0 );
+    If_ObjSetArrTime( pObj, (float)0.0 );
+    If_ManForEachPi( p, pObj, i )
+    {
+        pObj = If_ManCi( p, i );
+        If_ObjSetLValue( pObj, (float)0.0 );
+        If_ObjSetArrTime( pObj, (float)0.0 );
+    }
+
+    // update all values iteratively
+    fConverged = 0;
+    for ( c = 1; c <= p->nMaxIters; c++ )
+    {
+        if ( !If_ManPerformMappingRoundSeq( p, c ) )
+        {
+            p->RequiredGlo = If_ManDelayMax( p, 1 );
+            fConverged = 1;
+            break;
+        }
+        p->RequiredGlo = If_ManDelayMax( p, 1 );
+//Abc_Print( 1, "Global = %d \n", (int)p->RequiredGlo );
+        if ( p->RequiredGlo > p->Period + p->fEpsilon )
+            break; 
+    }
+
+    // report the results
+    If_ManMarkMapping( p );
+    if ( p->pPars->fVerbose )
+    {
+//        p->AreaGlo = If_ManScanMapping(p);
+        Abc_Print( 1, "Attempt = %2d.  Iters = %3d.  Area = %10.2f.  Fi = %6.2f.  ", p->nAttempts, c, p->AreaGlo, (float)p->Period );
+        if ( fConverged )
+            Abc_Print( 1, "  Feasible" );
+        else if ( c > p->nMaxIters )
+            Abc_Print( 1, "Infeasible (timeout)" );
+        else
+            Abc_Print( 1, "Infeasible" );
+        Abc_Print( 1, "\n" );
+    }
+    return fConverged;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs binary search for the optimal clock period.]
+
+  Description [Assumes that FiMin is infeasible while FiMax is feasible.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManBinarySearch_rec( If_Man_t * p, int FiMin, int FiMax )
+{
+    assert( FiMin < FiMax );
+    if ( FiMin + 1 == FiMax )
+        return FiMax;
+    // compute the median
+    p->Period = FiMin + (FiMax - FiMin)/2;
+    if ( If_ManBinarySearchPeriod( p ) )
+        return If_ManBinarySearch_rec( p, FiMin, p->Period ); // Median is feasible
+    else 
+        return If_ManBinarySearch_rec( p, p->Period, FiMax ); // Median is infeasible
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs sequential mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManPerformMappingSeqPost( If_Man_t * p )
+{
+    If_Obj_t * pObjLi, * pObjLo, * pObj;
+    int i;
+    assert( 0 );
+
+    // set arrival times
+    assert( p->pPars->pTimesArr != NULL );
+    If_ManForEachLatchOutput( p, pObjLo, i )
+        p->pPars->pTimesArr[i] = If_ObjLValue(pObjLo);
+
+    // set the required times
+    assert( p->pPars->pTimesReq == NULL );
+    p->pPars->pTimesReq = ABC_ALLOC( float, If_ManCoNum(p) );
+    If_ManForEachPo( p, pObj, i )
+        p->pPars->pTimesReq[i] = p->RequiredGlo2;
+    If_ManForEachLatchInput( p, pObjLi, i )
+        p->pPars->pTimesReq[i] = If_ObjLValue(If_ObjFanin0(pObjLi));
+
+    // undo previous mapping
+    If_ManForEachObj( p, pObj, i )
+        if ( If_ObjIsAnd(pObj) )
+            If_ObjCutBest(pObj)->nLeaves = 0;
+
+    // map again combinationally
+//    p->pPars->fSeqMap = 0;
+    If_ManPerformMappingComb( p );
+//    p->pPars->fSeqMap = 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs sequential mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManPerformMappingSeq( If_Man_t * p )
+{
+    abctime clkTotal = Abc_Clock();
+    int PeriodBest;
+
+    p->SortMode = 0;
+
+    // perform combinational mapping to get the upper bound on the clock period
+    If_ManPerformMappingRound( p, 1, 0, 0, 1, NULL );
+    p->RequiredGlo  = If_ManDelayMax( p, 0 );
+    p->RequiredGlo2 = p->RequiredGlo;
+
+    // set direct linking of latches with their inputs
+    If_ManPrepareMappingSeq( p );
+
+    // collect latches
+    p->vLatchOrder = If_ManCollectLatches( p );
+
+    // set parameters
+    p->nCutsUsed = p->pPars->nCutsMax;
+    p->nAttempts = 0;
+    p->nMaxIters = 50;
+    p->Period    = (int)p->RequiredGlo;
+
+    // make sure the clock period works
+    if ( !If_ManBinarySearchPeriod( p ) )
+    {
+        Abc_Print( 1, "If_ManPerformMappingSeq(): The upper bound on the clock period cannot be computed.\n" );
+        return 0;
+    }
+
+    // perform binary search
+    PeriodBest = If_ManBinarySearch_rec( p, 0, p->Period );
+
+    // recompute the best l-values
+    if ( p->Period != PeriodBest )
+    {
+        p->Period = PeriodBest;
+        if ( !If_ManBinarySearchPeriod( p ) )
+        {
+            Abc_Print( 1, "If_ManPerformMappingSeq(): The final clock period cannot be confirmed.\n" );
+            return 0;
+        }
+    }
+//    if ( p->pPars->fVerbose )
+    {
+        Abc_Print( 1, "The best clock period is %3d.  ", p->Period );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+    }
+    p->RequiredGlo = (float)(PeriodBest);
+
+    // postprocess it using combinational mapping
+    If_ManPerformMappingSeqPost( p );
+    s_MappingTime = Abc_Clock() - clkTotal;
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifTest.c b/abc-build/src/map/if/ifTest.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifTest.c
@@ -0,0 +1,346 @@
+/**CFile****************************************************************
+
+  FileName    [ifTest.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifTest.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+#include "aig/gia/gia.h"
+
+#ifdef ABC_USE_PTHREADS
+
+#ifdef _WIN32
+#include "../lib/pthread.h"
+#else
+#include <pthread.h>
+#include <unistd.h>
+#endif
+
+#endif
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline word * Gia_ParTestObj( Gia_Man_t * p, int Id )         { return (word *)p->pData + Id * p->iData; }
+static inline void   Gia_ParTestAlloc( Gia_Man_t * p, int nWords )   { assert( !p->pData ); p->pData = (unsigned *)ABC_ALLOC(word, Gia_ManObjNum(p) * nWords); p->iData = nWords; }
+static inline void   Gia_ParTestFree( Gia_Man_t * p )                { ABC_FREE( p->pData ); p->iData = 0; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ParComputeSignature( Gia_Man_t * p, int nWords )
+{
+    Gia_Obj_t * pObj;
+    word * pData, Sign = 0;
+    int i, k;
+    Gia_ManForEachCo( p, pObj, k )
+    {
+        pData = Gia_ParTestObj( p, Gia_ObjId(p, pObj) );
+        for ( i = 0; i < p->iData; i++ )
+            Sign ^= pData[i];
+    }
+    Abc_TtPrintHexRev( stdout, &Sign, 6 );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ParTestSimulateInit( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    word * pData;
+    int i, k;
+    Gia_ManForEachCi( p, pObj, k )
+    {
+        pData = Gia_ParTestObj( p, Gia_ObjId(p, pObj) );
+        for ( i = 0; i < p->iData; i++ )
+            pData[i] = Gia_ManRandomW( 0 );
+    }
+}
+void Gia_ParTestSimulateObj( Gia_Man_t * p, int Id )
+{
+    Gia_Obj_t * pObj = Gia_ManObj( p, Id );
+    word * pData, * pData0, * pData1;
+    int i;
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        pData  = Gia_ParTestObj( p, Id );
+        pData0 = Gia_ParTestObj( p, Gia_ObjFaninId0(pObj, Id) );
+        pData1 = Gia_ParTestObj( p, Gia_ObjFaninId1(pObj, Id) );
+        if ( Gia_ObjFaninC0(pObj) )
+        {
+            if ( Gia_ObjFaninC1(pObj) )
+                for ( i = 0; i < p->iData; i++ )
+                    pData[i] = ~(pData0[i] | pData1[i]);
+            else 
+                for ( i = 0; i < p->iData; i++ )
+                    pData[i] = ~pData0[i] & pData1[i];
+        }
+        else 
+        {
+            if ( Gia_ObjFaninC1(pObj) )
+                for ( i = 0; i < p->iData; i++ )
+                    pData[i] = pData0[i] & ~pData1[i];
+            else 
+                for ( i = 0; i < p->iData; i++ )
+                    pData[i] = pData0[i] & pData1[i];
+        }
+    }
+    else if ( Gia_ObjIsCo(pObj) )
+    {
+        pData  = Gia_ParTestObj( p, Id );
+        pData0 = Gia_ParTestObj( p, Gia_ObjFaninId0(pObj, Id) );
+        if ( Gia_ObjFaninC0(pObj) )
+            for ( i = 0; i < p->iData; i++ )
+                pData[i] = ~pData0[i];
+        else 
+            for ( i = 0; i < p->iData; i++ )
+                pData[i] = pData0[i];
+    }
+    else if ( Gia_ObjIsCi(pObj) )
+    {
+    }
+    else if ( Gia_ObjIsConst0(pObj) )
+    {
+        pData = Gia_ParTestObj( p, Id );
+        for ( i = 0; i < p->iData; i++ )
+            pData[i] = 0;
+    }
+    else assert( 0 );
+}
+void Gia_ParTestSimulate( Gia_Man_t * p, int nWords )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManRandom( 1 );
+    Gia_ParTestAlloc( p, nWords );
+    Gia_ParTestSimulateInit( p );
+    Gia_ManForEachObj( p, pObj, i )
+        Gia_ParTestSimulateObj( p, i );
+//    Gia_ParComputeSignature( p, nWords ); printf( "   " );
+    Gia_ParTestFree( p );
+}
+  
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns references.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManCreateFaninCounts( Gia_Man_t * p )  
+{
+    Vec_Int_t * vCounts;
+    Gia_Obj_t * pObj; int i;
+    vCounts = Vec_IntAlloc( Gia_ManObjNum(p) );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            Vec_IntPush( vCounts, 2 );
+        else if ( Gia_ObjIsCo(pObj) )
+            Vec_IntPush( vCounts, 1 );
+        else
+            Vec_IntPush( vCounts, 0 );
+    }
+    assert( Vec_IntSize(vCounts) == Gia_ManObjNum(p) );
+    return vCounts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+#ifdef ABC_USE_PTHREADS
+#define PAR_THR_MAX 100
+typedef struct Par_ThData_t_
+{
+    Gia_Man_t * p;
+    int         Id;
+    int         Status;
+} Par_ThData_t;
+void * Gia_ParWorkerThread( void * pArg )
+{
+    Par_ThData_t * pThData = (Par_ThData_t *)pArg;
+    volatile int * pPlace = &pThData->Status;
+    while ( 1 )
+    {
+        while ( *pPlace == 0 );
+        assert( pThData->Status == 1 );
+        if ( pThData->Id == -1 )
+        {
+	        pthread_exit( NULL );
+            assert( 0 );
+            return NULL;
+        }
+        assert( pThData->Id >= 0 );
+        Gia_ParTestSimulateObj( pThData->p, pThData->Id );
+        pThData->Status = 0;
+    }
+	assert( 0 );
+	return NULL;
+}
+void Gia_ParTestSimulate2( Gia_Man_t * p, int nWords, int nProcs )
+{
+	pthread_t WorkerThread[PAR_THR_MAX];
+    Par_ThData_t ThData[PAR_THR_MAX];
+    Vec_Int_t * vStack, * vFanins;
+    int i, k, iFan, status, nCountFanins;
+    assert( nProcs <= PAR_THR_MAX );
+    Gia_ManRandom( 1 );
+    Gia_ParTestAlloc( p, nWords );
+    Gia_ParTestSimulateInit( p );
+    // start the stack
+    vStack = Vec_IntAlloc( 1000 );
+    Vec_IntForEachEntryReverse( p->vCis, iFan, i )
+        Vec_IntPush( vStack, iFan );
+    Vec_IntPush( vStack, 0 );
+    Gia_ManStaticFanoutStart( p );
+    vFanins = Gia_ManCreateFaninCounts( p );
+    nCountFanins = Vec_IntSum(vFanins);
+    // start the threads
+    for ( i = 0; i < nProcs; i++ )
+    {
+        ThData[i].p = p;
+        ThData[i].Id = -1;
+        ThData[i].Status = 0;
+        status = pthread_create( WorkerThread + i, NULL, Gia_ParWorkerThread, (void *)(ThData + i) );  assert( status == 0 );
+    }
+    while ( nCountFanins > 0 || Vec_IntSize(vStack) > 0 )
+    {
+        for ( i = 0; i < nProcs; i++ )
+        {
+            if ( ThData[i].Status )
+                continue;
+            assert( ThData[i].Status == 0 );
+            if ( ThData[i].Id >= 0 )
+            {
+                Gia_ObjForEachFanoutStaticId( p, ThData[i].Id, iFan, k )
+                {
+                    assert( Vec_IntEntry(vFanins, iFan) > 0 );
+                    if ( Vec_IntAddToEntry(vFanins, iFan, -1) == 0 )
+                        Vec_IntPush( vStack, iFan );
+                    assert( nCountFanins > 0 );
+                    nCountFanins--;
+                }
+                ThData[i].Id = -1;
+            }
+            if ( Vec_IntSize(vStack) > 0 )
+            {
+                ThData[i].Id = Vec_IntPop( vStack );
+                ThData[i].Status = 1;
+            }
+        }
+    }
+    Vec_IntForEachEntry( vFanins, iFan, k )
+        if ( iFan != 0 )
+        {
+            printf( "%d -> %d    ", k, iFan );
+            Gia_ObjPrint( p, Gia_ManObj(p, k) );
+        }
+//    assert( Vec_IntSum(vFanins) == 0 );
+    // stop the threads
+    while ( 1 )
+    {
+        for ( i = 0; i < nProcs; i++ )
+            if ( ThData[i].Status )
+                break;
+        if ( i == nProcs )
+            break;
+    }
+    for ( i = 0; i < nProcs; i++ )
+    {
+        assert( ThData[i].Status == 0 );
+        ThData[i].Id = -1;
+        ThData[i].Status = 1;
+    }
+    Gia_ManStaticFanoutStop( p );
+    Vec_IntFree( vStack );
+    Vec_IntFree( vFanins );
+//    Gia_ParComputeSignature( p, nWords ); printf( "   " );
+    Gia_ParTestFree( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ParTest( Gia_Man_t * p, int nWords, int nProcs )
+{
+    abctime clk;
+    printf( "Trying with %d words and %d threads.  ", nWords, nProcs );
+    printf( "Memory usage = %.2f MB\n", (8.0*nWords*Gia_ManObjNum(p))/(1<<20) );
+    
+    clk = Abc_Clock();
+    Gia_ParTestSimulate( p, nWords );
+    Abc_PrintTime( 1, "Regular time", Abc_Clock() - clk );
+
+    clk = Abc_Clock();
+    Gia_ParTestSimulate2( p, nWords, nProcs );
+    Abc_PrintTime( 1, "Special time", Abc_Clock() - clk );
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifTime.c b/abc-build/src/map/if/ifTime.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifTime.c
@@ -0,0 +1,512 @@
+/**CFile****************************************************************
+
+  FileName    [ifTime.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Computation of delay paramters depending on the library.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifTime.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts the pins in the decreasing order of delays.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_CutSortInputPins( If_Man_t * p, If_Cut_t * pCut, int * pPinPerm, float * pPinDelays )
+{
+    If_Obj_t * pLeaf;
+    int i, j, best_i, temp;
+    // start the trivial permutation and collect pin delays
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+    {
+        pPinPerm[i] = i;
+        pPinDelays[i] = If_ObjCutBest(pLeaf)->Delay;
+    }
+    // selection sort the pins in the decreasible order of delays
+    // this order will match the increasing order of LUT input pins
+    for ( i = 0; i < (int)pCut->nLeaves-1; i++ )
+    {
+        best_i = i;
+        for ( j = i+1; j < (int)pCut->nLeaves; j++ )
+            if ( pPinDelays[pPinPerm[j]] > pPinDelays[pPinPerm[best_i]] )
+                best_i = j;
+        if ( best_i == i )
+            continue;
+        temp = pPinPerm[i]; 
+        pPinPerm[i] = pPinPerm[best_i]; 
+        pPinPerm[best_i] = temp;
+    }
+/*
+    // verify
+    assert( pPinPerm[0] < (int)pCut->nLeaves );
+    for ( i = 1; i < (int)pCut->nLeaves; i++ )
+    {
+        assert( pPinPerm[i] < (int)pCut->nLeaves );
+        assert( pPinDelays[pPinPerm[i-1]] >= pPinDelays[pPinPerm[i]] );
+    }
+*/
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes delay.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_CutDelay( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut )
+{
+    static int pPinPerm[IF_MAX_LUTSIZE];
+    static float pPinDelays[IF_MAX_LUTSIZE];
+    char * pPerm = If_CutPerm( pCut );
+    If_Obj_t * pLeaf;
+    float Delay, DelayCur;
+    float * pLutDelays;
+    int i, Shift, Pin2PinDelay;//, iLeaf;
+    Delay = -IF_FLOAT_LARGE;
+    if ( p->pPars->pLutLib )
+    {
+        assert( !p->pPars->fLiftLeaves );
+        pLutDelays = p->pPars->pLutLib->pLutDelays[pCut->nLeaves];
+        if ( p->pPars->pLutLib->fVarPinDelays )
+        {
+            // compute the delay using sorted pins
+            If_CutSortInputPins( p, pCut, pPinPerm, pPinDelays );
+            for ( i = 0; i < (int)pCut->nLeaves; i++ )
+            {
+                DelayCur = pPinDelays[pPinPerm[i]] + pLutDelays[i];
+                Delay = IF_MAX( Delay, DelayCur );
+            }
+        }
+        else
+        {
+            If_CutForEachLeaf( p, pCut, pLeaf, i )
+            {
+                DelayCur = If_ObjCutBest(pLeaf)->Delay + pLutDelays[0];
+                Delay = IF_MAX( Delay, DelayCur );
+            }
+        }
+    }
+    else
+    {
+        if ( pCut->fUser )
+        {
+            assert( !p->pPars->fLiftLeaves );
+            If_CutForEachLeaf( p, pCut, pLeaf, i )
+            {
+                Pin2PinDelay = pPerm ? (pPerm[i] == IF_BIG_CHAR ? -IF_BIG_CHAR : pPerm[i]) : 1;
+                DelayCur = If_ObjCutBest(pLeaf)->Delay + (float)Pin2PinDelay;
+                Delay = IF_MAX( Delay, DelayCur );
+            }
+        }
+        else
+        {
+            if ( p->pPars->fLiftLeaves )
+            {
+                If_CutForEachLeafSeq( p, pCut, pLeaf, Shift, i )
+                {
+                    DelayCur = If_ObjCutBest(pLeaf)->Delay - Shift * p->Period;
+                    Delay = IF_MAX( Delay, DelayCur + 1.0 );
+                }
+            }
+            else
+            {
+                If_CutForEachLeaf( p, pCut, pLeaf, i )
+                {
+                    DelayCur = If_ObjCutBest(pLeaf)->Delay + 1.0;
+                    Delay = IF_MAX( Delay, DelayCur );
+                }
+            }
+        }
+    }
+    return Delay;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_CutPropagateRequired( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut, float ObjRequired )
+{
+    static int pPinPerm[IF_MAX_LUTSIZE];
+    static float pPinDelays[IF_MAX_LUTSIZE];
+    If_Obj_t * pLeaf;
+    float * pLutDelays;
+    float Required;
+    int i, Pin2PinDelay;//, iLeaf;
+    assert( !p->pPars->fLiftLeaves );
+    // compute the pins
+    if ( p->pPars->pLutLib )
+    {
+        pLutDelays = p->pPars->pLutLib->pLutDelays[pCut->nLeaves];
+        if ( p->pPars->pLutLib->fVarPinDelays )
+        {
+            // compute the delay using sorted pins
+            If_CutSortInputPins( p, pCut, pPinPerm, pPinDelays );
+            for ( i = 0; i < (int)pCut->nLeaves; i++ )
+            {
+                Required = ObjRequired - pLutDelays[i];
+                pLeaf = If_ManObj( p, pCut->pLeaves[pPinPerm[i]] );
+                pLeaf->Required = IF_MIN( pLeaf->Required, Required );
+            }
+        }
+        else
+        {
+            Required = ObjRequired;
+            If_CutForEachLeaf( p, pCut, pLeaf, i )
+                pLeaf->Required = IF_MIN( pLeaf->Required, Required - pLutDelays[0] );
+        }
+    }
+    else
+    {
+        if ( pCut->fUser )
+        {
+            char Perm[IF_MAX_FUNC_LUTSIZE], * pPerm = Perm;
+            if ( p->pPars->fDelayOpt )
+            {
+                int Delay = If_CutSopBalancePinDelays( p, pCut, pPerm );
+                assert( Delay == (int)pCut->Delay );
+            }
+            else if ( p->pPars->fDelayOptLut )
+            {
+                int Delay = If_CutLutBalancePinDelays( p, pCut, pPerm );
+                assert( Delay == (int)pCut->Delay );
+            }
+            else if ( p->pPars->fDsdBalance )
+            {
+                int Delay = If_CutDsdBalancePinDelays( p, pCut, pPerm );
+                assert( Delay == (int)pCut->Delay );
+            }
+            else
+                pPerm = If_CutPerm(pCut);
+            If_CutForEachLeaf( p, pCut, pLeaf, i )
+            {
+                Pin2PinDelay = pPerm ? (pPerm[i] == IF_BIG_CHAR ? -IF_BIG_CHAR : pPerm[i]) : 1;
+                Required = ObjRequired - (float)Pin2PinDelay;
+                pLeaf->Required = IF_MIN( pLeaf->Required, Required );
+            }
+        }
+        else
+        {
+            Required = ObjRequired;
+            If_CutForEachLeaf( p, pCut, pLeaf, i )
+                pLeaf->Required = IF_MIN( pLeaf->Required, Required - (float)1.0 );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the max delay of the POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_ManDelayMax( If_Man_t * p, int fSeq )
+{
+    If_Obj_t * pObj;
+    float DelayBest;
+    int i;
+    if ( p->pPars->fLatchPaths && (p->pPars->nLatchesCi == 0 || p->pPars->nLatchesCo == 0) )
+    {
+        Abc_Print( 0, "Delay optimization of latch path is not performed because there is no latches.\n" );
+        p->pPars->fLatchPaths = 0;
+    }
+    DelayBest = -IF_FLOAT_LARGE;
+    if ( fSeq )
+    {
+        assert( p->pPars->nLatchesCi > 0 );
+        If_ManForEachPo( p, pObj, i )
+            if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) )
+                 DelayBest = If_ObjArrTime(If_ObjFanin0(pObj));
+    }
+    else if ( p->pPars->fLatchPaths )
+    {
+        If_ManForEachLatchInput( p, pObj, i )
+            if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) )
+                 DelayBest = If_ObjArrTime(If_ObjFanin0(pObj));
+    }
+    else 
+    {
+        If_ManForEachCo( p, pObj, i )
+            if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) )
+                 DelayBest = If_ObjArrTime(If_ObjFanin0(pObj));
+    }
+    return DelayBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the required times of all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManComputeRequired( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    int i, Counter;
+    float reqTime;
+
+    // compute area, clean required times, collect nodes used in the mapping
+//    p->AreaGlo = If_ManScanMapping( p );
+    If_ManMarkMapping( p );
+    if ( p->pManTim == NULL )
+    {
+        // consider the case when the required times are given
+        if ( p->pPars->pTimesReq && !p->pPars->fAreaOnly )
+        {
+            // make sure that the required time hold
+            Counter = 0;
+            If_ManForEachCo( p, pObj, i )
+            {
+                if ( If_ObjArrTime(If_ObjFanin0(pObj)) > p->pPars->pTimesReq[i] + p->fEpsilon )
+                {
+                    If_ObjFanin0(pObj)->Required = If_ObjArrTime(If_ObjFanin0(pObj));
+                    Counter++;
+    //                Abc_Print( 0, "Required times are violated for output %d (arr = %d; req = %d).\n", 
+    //                    i, (int)If_ObjArrTime(If_ObjFanin0(pObj)), (int)p->pPars->pTimesReq[i] );
+                }
+                else
+                    If_ObjFanin0(pObj)->Required = p->pPars->pTimesReq[i];
+            }
+            if ( Counter && !p->fReqTimeWarn )
+            {
+                Abc_Print( 0, "Required times are exceeded at %d output%s. The earliest arrival times are used.\n", Counter, Counter > 1 ? "s":"" );
+                p->fReqTimeWarn = 1;
+            }
+        }
+        else
+        {
+            // get the global required times
+            p->RequiredGlo = If_ManDelayMax( p, 0 );
+
+            // find new delay target
+            if ( p->pPars->nRelaxRatio && p->pPars->DelayTargetNew == 0 )
+                p->pPars->DelayTargetNew = p->RequiredGlo * (100.0 + p->pPars->nRelaxRatio) / 100.0; 
+
+            // update the required times according to the target
+            if ( p->pPars->DelayTarget != -1 )
+            {
+                if ( p->RequiredGlo > p->pPars->DelayTarget + p->fEpsilon )
+                {
+                    if ( p->fNextRound == 0 )
+                    {
+                        p->fNextRound = 1;
+                        Abc_Print( 0, "Cannot meet the target required times (%4.2f). Mapping continues anyway.\n", p->pPars->DelayTarget );
+                    }
+                }
+                else if ( p->RequiredGlo < p->pPars->DelayTarget - p->fEpsilon )
+                {
+                    if ( p->fNextRound == 0 )
+                    {
+                        p->fNextRound = 1;
+//                        Abc_Print( 0, "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->RequiredGlo, p->pPars->DelayTarget );
+                    }
+                    p->RequiredGlo = p->pPars->DelayTarget;
+                }
+            }
+            else if ( p->pPars->DelayTargetNew > 0 ) // relax the required times 
+                p->RequiredGlo = p->pPars->DelayTargetNew;
+            // do not propagate required times if area minimization is requested
+            if ( p->pPars->fAreaOnly ) 
+                return;
+            // set the required times for the POs
+            if ( p->pPars->fDoAverage )
+            {
+                if ( p->pPars->nRelaxRatio )
+                {
+                    If_ManForEachCo( p, pObj, i )
+                        If_ObjFanin0(pObj)->Required = If_ObjArrTime(If_ObjFanin0(pObj)) * (100.0 + p->pPars->nRelaxRatio) / 100.0;
+                }
+                else
+                {
+                    If_ManForEachCo( p, pObj, i )
+                        If_ObjFanin0(pObj)->Required = If_ObjArrTime(If_ObjFanin0(pObj));
+                }
+            }
+            else if ( p->pPars->fLatchPaths )
+            {
+                If_ManForEachLatchInput( p, pObj, i )
+                    If_ObjFanin0(pObj)->Required = p->RequiredGlo;
+            }
+            else 
+            {
+                If_ManForEachCo( p, pObj, i )
+                    If_ObjFanin0(pObj)->Required = p->RequiredGlo;
+            }
+        }
+        // go through the nodes in the reverse topological order
+    //    Vec_PtrForEachEntry( If_Obj_t *, p->vMapped, pObj, i )
+    //        If_CutPropagateRequired( p, pObj, If_ObjCutBest(pObj), pObj->Required );
+        If_ManForEachObjReverse( p, pObj, i )
+        {
+            if ( pObj->nRefs == 0 )
+                continue;
+            If_CutPropagateRequired( p, pObj, If_ObjCutBest(pObj), pObj->Required );
+        }
+    }
+    else
+    {
+        // get the global required times
+        p->RequiredGlo = If_ManDelayMax( p, 0 );
+
+        // find new delay target
+        if ( p->pPars->nRelaxRatio && p->pPars->DelayTargetNew == 0 )
+            p->pPars->DelayTargetNew = p->RequiredGlo * (100.0 + p->pPars->nRelaxRatio) / 100.0; 
+
+        // update the required times according to the target
+        if ( p->pPars->DelayTarget != -1 )
+        {
+            if ( p->RequiredGlo > p->pPars->DelayTarget + p->fEpsilon )
+            {
+                if ( p->fNextRound == 0 )
+                {
+                    p->fNextRound = 1;
+                    Abc_Print( 0, "Cannot meet the target required times (%4.2f). Mapping continues anyway.\n", p->pPars->DelayTarget );
+                }
+            }
+            else if ( p->RequiredGlo < p->pPars->DelayTarget - p->fEpsilon )
+            {
+                if ( p->fNextRound == 0 )
+                {
+                    p->fNextRound = 1;
+//                    Abc_Print( 0, "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->RequiredGlo, p->pPars->DelayTarget );
+                }
+                p->RequiredGlo = p->pPars->DelayTarget;
+            }
+        }
+        else if ( p->pPars->DelayTargetNew > 0 ) // relax the required times 
+            p->RequiredGlo = p->pPars->DelayTargetNew;
+
+        // do not propagate required times if area minimization is requested
+        if ( p->pPars->fAreaOnly ) 
+            return;
+        // set the required times for the POs
+        Tim_ManIncrementTravId( p->pManTim );
+        if ( p->vCoAttrs )
+        {
+            assert( If_ManCoNum(p) == Vec_IntSize(p->vCoAttrs) );
+            If_ManForEachCo( p, pObj, i )
+            { 
+                if ( Vec_IntEntry(p->vCoAttrs, i) == -1 )       // -1=internal
+                    continue;
+                if ( Vec_IntEntry(p->vCoAttrs, i) == 0 )        //  0=optimize
+                    Tim_ManSetCoRequired( p->pManTim, i, p->RequiredGlo );
+                else if ( Vec_IntEntry(p->vCoAttrs, i) == 1 )   //  1=keep
+                    Tim_ManSetCoRequired( p->pManTim, i, If_ObjArrTime(If_ObjFanin0(pObj)) );
+                else if ( Vec_IntEntry(p->vCoAttrs, i) == 2 )   //  2=relax
+                    Tim_ManSetCoRequired( p->pManTim, i, IF_FLOAT_LARGE );
+                else assert( 0 );
+            }
+        }
+        else if ( p->pPars->fDoAverage )
+        {
+            if ( p->pPars->nRelaxRatio )
+            {
+                If_ManForEachCo( p, pObj, i )
+                    Tim_ManSetCoRequired( p->pManTim, i, If_ObjArrTime(If_ObjFanin0(pObj)) * (100.0 + p->pPars->nRelaxRatio) / 100.0 );
+            }
+            else
+            {
+                If_ManForEachCo( p, pObj, i )
+                    Tim_ManSetCoRequired( p->pManTim, i, If_ObjArrTime(If_ObjFanin0(pObj)) );
+            }
+        }
+        else if ( p->pPars->fLatchPaths )
+        {
+            If_ManForEachPo( p, pObj, i )
+                Tim_ManSetCoRequired( p->pManTim, i, IF_FLOAT_LARGE );
+            If_ManForEachLatchInput( p, pObj, i )
+                Tim_ManSetCoRequired( p->pManTim, i, p->RequiredGlo );
+        }
+        else  
+        {
+            Tim_ManInitPoRequiredAll( p->pManTim, p->RequiredGlo );
+//            If_ManForEachCo( p, pObj, i )
+//                Tim_ManSetCoRequired( p->pManTim, pObj->IdPio, p->RequiredGlo );
+        }
+        // go through the nodes in the reverse topological order
+        If_ManForEachObjReverse( p, pObj, i )
+        {
+            if ( If_ObjIsAnd(pObj) )
+            {
+                if ( pObj->nRefs == 0 )
+                    continue;
+                If_CutPropagateRequired( p, pObj, If_ObjCutBest(pObj), pObj->Required );
+            }
+            else if ( If_ObjIsCi(pObj) )
+            {
+                reqTime = pObj->Required;
+                Tim_ManSetCiRequired( p->pManTim, pObj->IdPio, reqTime );
+            }
+            else if ( If_ObjIsCo(pObj) )
+            {
+                reqTime = Tim_ManGetCoRequired( p->pManTim, pObj->IdPio );
+                If_ObjFanin0(pObj)->Required = IF_MIN( reqTime, If_ObjFanin0(pObj)->Required );
+            }
+            else if ( If_ObjIsConst1(pObj) )
+            {
+            }
+            else // add the node to the mapper
+                assert( 0 );
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifTruth.c b/abc-build/src/map/if/ifTruth.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifTruth.c
@@ -0,0 +1,336 @@
+/**CFile****************************************************************
+
+  FileName    [ifTruth.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Computation of truth tables of the cuts.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifTruth.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+//#define IF_TRY_NEW
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts the pins in the decreasing order of delays.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_CutTruthPermute( word * pTruth, int nLeaves, int nVars, int nWords, float * pDelays, int * pVars )
+{
+    while ( 1 )
+    {
+        int i, fChange = 0;
+        for ( i = 0; i < nLeaves - 1; i++ )
+        {
+            if ( pDelays[i] >= pDelays[i+1] )
+                continue;
+            ABC_SWAP( float, pDelays[i], pDelays[i+1] );
+            ABC_SWAP( int, pVars[i], pVars[i+1] );
+            if ( pTruth )
+                Abc_TtSwapAdjacent( pTruth, nWords, i );
+            fChange = 1;
+        }
+        if ( !fChange )
+            return;
+    }
+}
+void If_CutRotatePins( If_Man_t * p, If_Cut_t * pCut )
+{
+    If_Obj_t * pLeaf;
+    float PinDelays[IF_MAX_LUTSIZE];
+    int i, truthId;
+    assert( !p->pPars->fUseTtPerm );
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+        PinDelays[i] = If_ObjCutBest(pLeaf)->Delay;
+    if ( p->vTtMem[pCut->nLeaves] == NULL )
+    {
+        If_CutTruthPermute( NULL, If_CutLeaveNum(pCut), pCut->nLeaves, p->nTruth6Words[pCut->nLeaves], PinDelays, If_CutLeaves(pCut) );
+        return;
+    }
+    Abc_TtCopy( p->puTempW, If_CutTruthWR(p, pCut), p->nTruth6Words[pCut->nLeaves], 0 );
+    If_CutTruthPermute( p->puTempW, If_CutLeaveNum(pCut), pCut->nLeaves, p->nTruth6Words[pCut->nLeaves], PinDelays, If_CutLeaves(pCut) );
+    truthId        = Vec_MemHashInsert( p->vTtMem[pCut->nLeaves], p->puTempW );
+    pCut->iCutFunc = Abc_Var2Lit( truthId, If_CutTruthIsCompl(pCut) );
+    assert( (p->puTempW[0] & 1) == 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Truth table computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutComputeTruth( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 )
+{
+    int fCompl, truthId, nLeavesNew, RetValue = 0;
+    int PrevSize, nWords = Abc_TtWordNum( pCut->nLeaves );
+    word * pTruth0s = Vec_MemReadEntry( p->vTtMem[pCut0->nLeaves], Abc_Lit2Var(pCut0->iCutFunc) );
+    word * pTruth1s = Vec_MemReadEntry( p->vTtMem[pCut1->nLeaves], Abc_Lit2Var(pCut1->iCutFunc) );
+    word * pTruth0  = (word *)p->puTemp[0];
+    word * pTruth1  = (word *)p->puTemp[1];
+    word * pTruth   = (word *)p->puTemp[2];
+    Abc_TtCopy( pTruth0, pTruth0s, nWords, fCompl0 ^ pCut0->fCompl ^ Abc_LitIsCompl(pCut0->iCutFunc) );
+    Abc_TtCopy( pTruth1, pTruth1s, nWords, fCompl1 ^ pCut1->fCompl ^ Abc_LitIsCompl(pCut1->iCutFunc) );
+    Abc_TtStretch6( pTruth0, pCut0->nLeaves, pCut->nLeaves );
+    Abc_TtStretch6( pTruth1, pCut1->nLeaves, pCut->nLeaves );
+    Abc_TtExpand( pTruth0, pCut->nLeaves, pCut0->pLeaves, pCut0->nLeaves, pCut->pLeaves, pCut->nLeaves );
+    Abc_TtExpand( pTruth1, pCut->nLeaves, pCut1->pLeaves, pCut1->nLeaves, pCut->pLeaves, pCut->nLeaves );
+    fCompl         = (pTruth0[0] & pTruth1[0] & 1);
+    Abc_TtAnd( pTruth, pTruth0, pTruth1, nWords, fCompl );
+    if ( p->pPars->fCutMin && (pCut0->nLeaves + pCut1->nLeaves > pCut->nLeaves || pCut0->nLeaves == 0 || pCut1->nLeaves == 0) )
+    {
+        nLeavesNew = Abc_TtMinBase( pTruth, pCut->pLeaves, pCut->nLeaves, pCut->nLeaves );
+        if ( nLeavesNew < If_CutLeaveNum(pCut) )
+        {
+            pCut->nLeaves = nLeavesNew;
+            pCut->uSign   = If_ObjCutSignCompute( pCut );
+            RetValue      = 1;
+        }
+    }
+    PrevSize       = Vec_MemEntryNum( p->vTtMem[pCut->nLeaves] );   
+    truthId        = Vec_MemHashInsert( p->vTtMem[pCut->nLeaves], pTruth );
+    pCut->iCutFunc = Abc_Var2Lit( truthId, fCompl );
+    assert( (pTruth[0] & 1) == 0 );
+#ifdef IF_TRY_NEW
+    {
+        word pCopy[1024];
+        char pCanonPerm[16];
+        memcpy( pCopy, If_CutTruthW(pCut), sizeof(word) * nWords );
+        Abc_TtCanonicize( pCopy, pCut->nLeaves, pCanonPerm );
+    }
+#endif
+    if ( p->vTtIsops[pCut->nLeaves] && PrevSize != Vec_MemEntryNum(p->vTtMem[pCut->nLeaves]) )
+    {
+        Vec_Int_t * vLevel = Vec_WecPushLevel( p->vTtIsops[pCut->nLeaves] );
+        fCompl = Kit_TruthIsop( (unsigned *)pTruth, pCut->nLeaves, p->vCover, 1 );
+        if ( fCompl >= 0 )
+        {
+            Vec_IntGrow( vLevel, Vec_IntSize(p->vCover) );
+            Vec_IntAppend( vLevel, p->vCover );
+            if ( fCompl )
+                vLevel->nCap ^= (1<<16); // hack to remember complemented attribute
+        }
+        assert( Vec_WecSize(p->vTtIsops[pCut->nLeaves]) == Vec_MemEntryNum(p->vTtMem[pCut->nLeaves]) );
+    }
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Truth table computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_CutComputeTruthPerm_int( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int iCutFunc0, int iCutFunc1 )
+{
+    int fVerbose = 0;
+    abctime clk = 0;
+    int pPerm[IF_MAX_LUTSIZE];
+    int v, Place, fCompl, truthId, nLeavesNew, RetValue = 0;
+    int nWords      = Abc_TtWordNum( pCut->nLeaves );
+    word * pTruth0s = Vec_MemReadEntry( p->vTtMem[pCut0->nLeaves], Abc_Lit2Var(iCutFunc0) );
+    word * pTruth1s = Vec_MemReadEntry( p->vTtMem[pCut1->nLeaves], Abc_Lit2Var(iCutFunc1) );
+    word * pTruth0  = (word *)p->puTemp[0];
+    word * pTruth1  = (word *)p->puTemp[1];
+    word * pTruth   = (word *)p->puTemp[2];
+    assert( pCut0->uMaskFunc >= 0 );
+    assert( pCut1->uMaskFunc >= 0 );
+    Abc_TtCopy( pTruth0, pTruth0s, nWords, Abc_LitIsCompl(iCutFunc0) );
+    Abc_TtCopy( pTruth1, pTruth1s, nWords, Abc_LitIsCompl(iCutFunc1) );
+    Abc_TtStretch6( pTruth0, pCut0->nLeaves, pCut->nLeaves );
+    Abc_TtStretch6( pTruth1, pCut1->nLeaves, pCut->nLeaves );
+
+if ( fVerbose )
+{
+//Kit_DsdPrintFromTruth( pTruth0, pCut0->nLeaves ); printf( "\n" );
+//Kit_DsdPrintFromTruth( pTruth1, pCut1->nLeaves ); printf( "\n" );
+}
+    // create literals
+    for ( v = 0; v < (int)pCut0->nLeaves; v++ )
+        pCut->pLeaves[v] = Abc_Var2Lit( pCut0->pLeaves[v], If_CutLeafBit(pCut0, v) );
+    for ( v = 0; v < (int)pCut1->nLeaves; v++ )
+        if ( p->pPerm[1][v] >= (int)pCut0->nLeaves )
+            pCut->pLeaves[p->pPerm[1][v]] = Abc_Var2Lit( pCut1->pLeaves[v], If_CutLeafBit(pCut1, v) );
+        else if ( If_CutLeafBit(pCut0, p->pPerm[1][v]) != If_CutLeafBit(pCut1, v) )
+            Abc_TtFlip( pTruth1, nWords, v );  
+    // permute variables
+    for ( v = (int)pCut1->nLeaves; v < (int)pCut->nLeaves; v++ )
+        p->pPerm[1][v] = -1;
+    for ( v = 0; v < (int)pCut1->nLeaves; v++ )
+    {
+        Place = p->pPerm[1][v];
+        if ( Place == v || Place == -1 )
+            continue;
+        Abc_TtSwapVars( pTruth1, pCut->nLeaves, v, Place );
+        p->pPerm[1][v] = p->pPerm[1][Place];
+        p->pPerm[1][Place] = Place;
+        v--;
+    }
+
+if ( fVerbose )
+{
+//Kit_DsdPrintFromTruth( pTruth0, pCut0->nLeaves ); printf( "\n" );
+//Kit_DsdPrintFromTruth( pTruth1, pCut->nLeaves ); printf( "\n" );
+}
+
+    // perform operation
+    Abc_TtAnd( pTruth, pTruth0, pTruth1, nWords, 0 );
+    // minimize support
+    if ( p->pPars->fCutMin && (pCut0->nLeaves + pCut1->nLeaves > pCut->nLeaves || pCut0->nLeaves == 0 || pCut1->nLeaves == 0) )
+    {
+        nLeavesNew = Abc_TtMinBase( pTruth, pCut->pLeaves, pCut->nLeaves, pCut->nLeaves );
+        if ( nLeavesNew < If_CutLeaveNum(pCut) )
+        {
+            pCut->nLeaves = nLeavesNew;
+            RetValue      = 1;
+        }
+    }
+    // compute canonical form
+if ( p->pPars->fVerbose )
+clk = Abc_Clock();
+    p->uCanonPhase = Abc_TtCanonicize( pTruth, pCut->nLeaves, p->pCanonPerm );
+if ( p->pPars->fVerbose )
+p->timeCache[3] += Abc_Clock() - clk;
+    for ( v = 0; v < (int)pCut->nLeaves; v++ )
+        pPerm[v] = Abc_LitNotCond( pCut->pLeaves[(int)p->pCanonPerm[v]], ((p->uCanonPhase>>v)&1) );
+    pCut->uMaskFunc = 0;
+    for ( v = 0; v < (int)pCut->nLeaves; v++ )
+    {
+        pCut->pLeaves[v] = Abc_Lit2Var(pPerm[v]);
+        if ( Abc_LitIsCompl(pPerm[v]) )
+            pCut->uMaskFunc |= (1 << v);
+    }
+    // create signature after lowering literals
+    if ( RetValue )
+        pCut->uSign = If_ObjCutSignCompute( pCut );
+    else
+        assert( pCut->uSign == If_ObjCutSignCompute( pCut ) );
+
+    // hash function
+    fCompl         = ((p->uCanonPhase >> pCut->nLeaves) & 1);
+    truthId        = Vec_MemHashInsert( p->vTtMem[pCut->nLeaves], pTruth );
+    pCut->iCutFunc = Abc_Var2Lit( truthId, fCompl );
+
+if ( fVerbose )
+{
+//Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves ); printf( "\n" );
+//If_CutPrint( pCut0 );
+//If_CutPrint( pCut1 );
+//If_CutPrint( pCut );
+//printf( "%d\n\n", pCut->iCutFunc );
+}
+
+    return RetValue;
+}
+int If_CutComputeTruthPerm( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int iCutFunc0, int iCutFunc1 )
+{
+    abctime clk = 0;
+    int i, Num, nEntriesOld, RetValue;
+    if ( pCut0->nLeaves + pCut1->nLeaves > pCut->nLeaves || iCutFunc0 < 2 || iCutFunc1 < 2 )
+    {
+if ( p->pPars->fVerbose )
+clk = Abc_Clock();
+        RetValue = If_CutComputeTruthPerm_int( p, pCut, pCut0, pCut1, iCutFunc0, iCutFunc1 );
+if ( p->pPars->fVerbose )
+p->timeCache[0] += Abc_Clock() - clk;
+        return RetValue;
+    }
+    assert( pCut0->nLeaves + pCut1->nLeaves == pCut->nLeaves );
+    nEntriesOld = Hash_IntManEntryNum(p->vPairHash);
+    Num = Hash_Int2ManInsert( p->vPairHash, (iCutFunc0 << 5)|pCut0->nLeaves, (iCutFunc1 << 5)|pCut1->nLeaves, -1 );
+    assert( Num > 0 );
+    if ( nEntriesOld == Hash_IntManEntryNum(p->vPairHash) )
+    {
+        char * pCanonPerm;
+        int v, pPerm[IF_MAX_LUTSIZE];
+        pCut->iCutFunc = Vec_IntEntry( p->vPairRes, Num );
+        // move complements from the fanin cuts
+        for ( v = 0; v < (int)pCut->nLeaves; v++ )
+            if ( v < (int)pCut0->nLeaves )
+                pCut->pLeaves[v] = Abc_Var2Lit( pCut->pLeaves[v], If_CutLeafBit(pCut0, v) );
+            else
+                pCut->pLeaves[v] = Abc_Var2Lit( pCut->pLeaves[v], If_CutLeafBit(pCut1, v-(int)pCut0->nLeaves) );
+        // reorder the cut
+        pCanonPerm = Vec_StrEntryP( p->vPairPerms, Num * pCut->nLimit );
+        for ( v = 0; v < (int)pCut->nLeaves; v++ )
+            pPerm[v] = Abc_LitNotCond( pCut->pLeaves[Abc_Lit2Var((int)pCanonPerm[v])], Abc_LitIsCompl((int)pCanonPerm[v]) );
+        // generate the result
+        pCut->uMaskFunc = 0;
+        for ( v = 0; v < (int)pCut->nLeaves; v++ )
+        {
+            pCut->pLeaves[v] = Abc_Lit2Var(pPerm[v]);
+            if ( Abc_LitIsCompl(pPerm[v]) )
+                pCut->uMaskFunc |= (1 << v);
+        }
+//        printf( "Found: %d(%d) %d(%d) -> %d(%d)\n", iCutFunc0, pCut0->nLeaves, iCutFunc1, pCut0->nLeaves, pCut->iCutFunc, pCut->nLeaves );
+        p->nCacheHits++;
+//p->timeCache[1] += Abc_Clock() - clk;
+        return 0;
+    }
+if ( p->pPars->fVerbose )
+clk = Abc_Clock();
+    p->nCacheMisses++;
+    RetValue = If_CutComputeTruthPerm_int( p, pCut, pCut0, pCut1, iCutFunc0, iCutFunc1 );
+    assert( RetValue == 0 );
+//    printf( "Added: %d(%d) %d(%d) -> %d(%d)\n", iCutFunc0, pCut0->nLeaves, iCutFunc1, pCut0->nLeaves, pCut->iCutFunc, pCut->nLeaves );
+    // save the result
+    assert( Num == Vec_IntSize(p->vPairRes) );
+    Vec_IntPush( p->vPairRes, pCut->iCutFunc );
+    // save the permutation
+    assert( Num * (int)pCut->nLimit == Vec_StrSize(p->vPairPerms) );
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        Vec_StrPush( p->vPairPerms, (char)Abc_Var2Lit((int)p->pCanonPerm[i], ((p->uCanonPhase>>i)&1)) );
+    for ( i = (int)pCut0->nLeaves + (int)pCut1->nLeaves; i < (int)pCut->nLimit; i++ )
+        Vec_StrPush( p->vPairPerms, (char)-1 );
+if ( p->pPars->fVerbose )
+p->timeCache[2] += Abc_Clock() - clk;
+    return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifTune.c b/abc-build/src/map/if/ifTune.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifTune.c
@@ -0,0 +1,398 @@
+/**CFile****************************************************************
+
+  FileName    [ifTune.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Library tuning.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifTune.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+#include "aig/gia/giaAig.h"
+#include "sat/bsat/satStore.h"
+#include "sat/cnf/cnf.h"
+#include "misc/extra/extra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// network types
+typedef enum { 
+    IF_DSD_NONE = 0,               // 0:  unknown
+    IF_DSD_CONST0,                 // 1:  constant
+    IF_DSD_VAR,                    // 2:  variable
+    IF_DSD_AND,                    // 3:  AND
+    IF_DSD_XOR,                    // 4:  XOR
+    IF_DSD_MUX,                    // 5:  MUX
+    IF_DSD_PRIME                   // 6:  PRIME
+} If_DsdType_t;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManStrCheck( char * pStr, int * pnVars, int * pnObjs )
+{
+    int i, Marks[32] = {0}, MaxVar = 0, MaxDef = 0, RetValue = 1;
+    for ( i = 0; pStr[i]; i++ )
+    {
+        if ( pStr[i] == '=' || pStr[i] == ';' || 
+             pStr[i] == '(' || pStr[i] == ')' || 
+             pStr[i] == '[' || pStr[i] == ']' || 
+             pStr[i] == '<' || pStr[i] == '>' || 
+             pStr[i] == '{' || pStr[i] == '}' )
+            continue;
+        if ( pStr[i] >= 'a' && pStr[i] <= 'z' )
+        {
+            if ( pStr[i+1] == '=' )
+                Marks[pStr[i] - 'a'] = 2, MaxDef = Abc_MaxInt(MaxDef, pStr[i] - 'a');
+            continue;
+        }
+        printf( "String \"%s\" contains unrecognized symbol (%c).\n", pStr, pStr[i] );
+        RetValue = 0;
+    }
+    if ( !RetValue )
+        return 0;
+    for ( i = 0; pStr[i]; i++ )
+    {
+        if ( pStr[i] == '=' || pStr[i] == ';' || 
+             pStr[i] == '(' || pStr[i] == ')' || 
+             pStr[i] == '[' || pStr[i] == ']' || 
+             pStr[i] == '<' || pStr[i] == '>' || 
+             pStr[i] == '{' || pStr[i] == '}' )
+            continue;
+        if ( pStr[i] >= 'a' && pStr[i] <= 'z' )
+        {
+            if ( pStr[i+1] != '=' && Marks[pStr[i] - 'a'] != 2 )
+                Marks[pStr[i] - 'a'] = 1, MaxVar = Abc_MaxInt(MaxVar, pStr[i] - 'a');
+            continue;
+        }
+        printf( "String \"%s\" contains unrecognized symbol (%c).\n", pStr, pStr[i] );
+        RetValue = 0;
+    }
+    if ( !RetValue )
+        return 0;
+    MaxVar++;
+    MaxDef++;
+    for ( i = 0; i < MaxDef; i++ )
+        if ( Marks[i] == 0 )
+            printf( "String \"%s\" has no symbol (%c).\n", pStr, 'a' + i ), RetValue = 0;
+    for ( i = 0; i < MaxVar; i++ )
+        if ( Marks[i] == 2 )
+            printf( "String \"%s\" has definition of input variable (%c).\n", pStr, 'a' + i ), RetValue = 0;
+    for ( i = MaxVar; i < MaxDef; i++ )
+        if ( Marks[i] == 1 )
+            printf( "String \"%s\" has no definition for internal variable (%c).\n", pStr, 'a' + i ), RetValue = 0;
+    if ( !RetValue )
+        return 0;
+    *pnVars = MaxVar;
+    *pnObjs = MaxDef;
+    return 1;
+}
+int If_ManStrParse( char * pStr, int nVars, int nObjs, int * pTypes, int * pnFans, int ppFans[][6], int * pFirsts, int * pnSatVars )
+{
+    int i, k, n, f, nPars = nVars;
+    char Next = 0;
+    assert( nVars < nObjs );
+    for ( i = nVars; i < nObjs; i++ )
+    {
+        for ( k = 0; pStr[k]; k++ )
+            if ( pStr[k] == 'a' + i && pStr[k+1] == '=' )
+                break;
+        assert( pStr[k] );
+        if ( pStr[k+2] == '(' )
+            pTypes[i] = IF_DSD_AND, Next = ')';
+        else if ( pStr[k+2] == '[' )
+            pTypes[i] = IF_DSD_XOR, Next = ']';
+        else if ( pStr[k+2] == '<' )
+            pTypes[i] = IF_DSD_MUX, Next = '>';
+        else if ( pStr[k+2] == '{' )
+            pTypes[i] = IF_DSD_PRIME, Next = '}';
+        else assert( 0 );
+        for ( n = k + 3; pStr[n]; n++ )
+            if ( pStr[n] == Next )
+                break;
+        assert( pStr[k] );
+        pnFans[i] = n - k - 3;
+        assert( pnFans[i] > 0 && pnFans[i] <= 6 );
+        for ( f = 0; f < pnFans[i]; f++ )
+        {
+            ppFans[i][f] = pStr[k + 3 + f] - 'a';
+            assert( ppFans[i][k] < i );
+            if ( ppFans[i][f] < 0 || ppFans[i][f] >= nObjs )
+                printf( "Error!\n" );
+        }
+        if ( pTypes[i] != IF_DSD_PRIME )
+            continue;
+        pFirsts[i] = nPars;
+        nPars += (1 << pnFans[i]);
+    }
+    *pnSatVars = nPars;
+    return 1;
+}
+Gia_Man_t * If_ManStrFindModel( int nVars, int nObjs, int nSatVars, int * pTypes, int * pnFans, int ppFans[][6], int * pFirsts )
+{
+    Gia_Man_t * pNew, * pTemp;
+    int * pVarsPar, * pVarsObj;
+    int i, k, n, Step, iLit, nMints, nPars = 0;
+    pNew = Gia_ManStart( 1000 );
+    pNew->pName = Abc_UtilStrsav( "model" );
+    Gia_ManHashStart( pNew );
+    pVarsPar = ABC_ALLOC( int, nSatVars );
+    pVarsObj = ABC_ALLOC( int, nObjs );
+    for ( i = 0; i < nSatVars; i++ )
+        pVarsPar[i] = Gia_ManAppendCi(pNew);
+    for ( i = 0; i < nVars; i++ )
+        pVarsObj[i] = pVarsPar[nSatVars - nVars + i];
+    for ( i = nVars; i < nObjs; i++ )
+    {
+        if ( pTypes[i] == IF_DSD_AND )
+        {
+            iLit = 1;
+            for ( k = 0; k < pnFans[i]; k++ )
+                iLit = Gia_ManHashAnd( pNew, iLit, pVarsObj[ppFans[i][k]] );
+            pVarsObj[i] = iLit;
+        }
+        else if ( pTypes[i] == IF_DSD_XOR )
+        {
+            iLit = 0;
+            for ( k = 0; k < pnFans[i]; k++ )
+                iLit = Gia_ManHashXor( pNew, iLit, pVarsObj[ppFans[i][k]] );
+            pVarsObj[i] = iLit;
+        }
+        else if ( pTypes[i] == IF_DSD_MUX )
+        {
+            assert( pnFans[i] == 3 );
+            pVarsObj[i] = Gia_ManHashMux( pNew, pVarsObj[ppFans[i][0]], pVarsObj[ppFans[i][1]], pVarsObj[ppFans[i][2]] );
+        }
+        else if ( pTypes[i] == IF_DSD_PRIME )
+        {
+            int pVarsData[64];
+            assert( pnFans[i] >= 1 && pnFans[i] <= 6 );
+            nMints = (1 << pnFans[i]);
+            for ( k = 0; k < nMints; k++ )
+                pVarsData[k] = pVarsPar[nPars++];
+            for ( Step = 1, k = 0; k < pnFans[i]; k++, Step <<= 1 )
+                for ( n = 0; n < nMints; n += Step << 1 )
+                    pVarsData[n] = Gia_ManHashMux( pNew, pVarsObj[ppFans[i][k]], pVarsData[n+Step], pVarsData[n] );
+            assert( Step == nMints );
+            pVarsObj[i] = pVarsData[0];
+        }
+        else assert( 0 );
+    }
+    assert( nPars + nVars == nSatVars );
+    Gia_ManAppendCo( pNew, pVarsObj[nObjs-1] );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    ABC_FREE( pVarsPar );
+    ABC_FREE( pVarsObj );
+    assert( Gia_ManPiNum(pNew) == nSatVars );
+    assert( Gia_ManPoNum(pNew) == 1 );
+    return pNew;
+}
+Gia_Man_t * If_ManStrFindCofactors( int nPars, Gia_Man_t * p )
+{
+    Gia_Man_t * pNew, * pTemp; 
+    Gia_Obj_t * pObj;
+    int i, m, nMints = 1 << (Gia_ManCiNum(p) - nPars);
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        if ( i < nPars )
+            pObj->Value = Gia_ManAppendCi( pNew );
+    for ( m = 0; m < nMints; m++ )
+    {
+        Gia_ManForEachCi( p, pObj, i )
+            if ( i >= nPars )
+                pObj->Value = ((m >> (i - nPars)) & 1);
+        Gia_ManForEachAnd( p, pObj, i )
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        Gia_ManForEachPo( p, pObj, i )
+            pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Cnf_Dat_t * Cnf_DeriveGiaRemapped( Gia_Man_t * p )
+{
+    Cnf_Dat_t * pCnf;
+    Aig_Man_t * pAig = Gia_ManToAigSimple( p );
+    pAig->nRegs = 0;
+    pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) );
+    Aig_ManStop( pAig );
+    return pCnf;
+}
+sat_solver * If_ManStrFindSolver( Gia_Man_t * p, Vec_Int_t ** pvPiVars, Vec_Int_t ** pvPoVars )
+{
+    sat_solver * pSat;
+    Gia_Obj_t * pObj;
+    Cnf_Dat_t * pCnf;
+    int i;    
+    pCnf = Cnf_DeriveGiaRemapped( p );
+    // start the SAT solver
+    pSat = sat_solver_new();
+    sat_solver_setnvars( pSat, pCnf->nVars );
+    // add timeframe clauses
+    for ( i = 0; i < pCnf->nClauses; i++ )
+        if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
+            assert( 0 );
+    // inputs/outputs
+    *pvPiVars = Vec_IntAlloc( Gia_ManPiNum(p) );
+    Gia_ManForEachCi( p, pObj, i )
+        Vec_IntPush( *pvPiVars, pCnf->pVarNums[Gia_ObjId(p, pObj)] );
+    *pvPoVars = Vec_IntAlloc( Gia_ManPoNum(p) );
+    Gia_ManForEachCo( p, pObj, i )
+        Vec_IntPush( *pvPoVars, pCnf->pVarNums[Gia_ObjId(p, pObj)] );
+    Cnf_DataFree( pCnf );
+    return pSat;
+}
+
+sat_solver * If_ManSatBuild( char * pStr, Vec_Int_t ** pvPiVars, Vec_Int_t ** pvPoVars )
+{
+    int nVars, nObjs, nSatVars;
+    int pTypes[32] = {0};
+    int pnFans[32] = {0};
+    int ppFans[32][6] = {{0}};
+    int pFirsts[32] = {0};
+    Gia_Man_t * p1, * p2;
+    sat_solver * pSat = NULL;
+    *pvPiVars = *pvPoVars = NULL;
+    if ( !If_ManStrCheck(pStr, &nVars, &nObjs) )
+        return NULL;
+    if ( !If_ManStrParse(pStr, nVars, nObjs, pTypes, pnFans, ppFans, pFirsts, &nSatVars) )
+        return NULL;
+    p1 = If_ManStrFindModel(nVars, nObjs, nSatVars, pTypes, pnFans, ppFans, pFirsts);
+    if ( p1 == NULL )
+        return NULL;
+//    Gia_AigerWrite( p1, "satbuild.aig", 0, 0 );
+    p2 = If_ManStrFindCofactors( nSatVars - nVars, p1 );
+    Gia_ManStop( p1 );
+    if ( p2 == NULL )
+        return NULL;
+//    Gia_AigerWrite( p2, "satbuild2.aig", 0, 0 );
+    pSat = If_ManStrFindSolver( p2, pvPiVars, pvPoVars );
+    Gia_ManStop( p2 );
+    return pSat;
+}
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManSatPrintPerm( char * pPerms, int nVars )
+{
+    int i;
+    for ( i = 0; i < nVars; i++ )
+        printf( "%c", 'a' + pPerms[i] );
+    printf( "\n" );
+}
+int If_ManSatCheckOne( sat_solver * pSat, Vec_Int_t * vPoVars, word * pTruth, int nVars, int * pPerm, int nVarsAll, Vec_Int_t * vLits )
+{
+    int v, Value, m, mNew, nMints = (1 << nVars);
+    assert( (1 << nVarsAll) == Vec_IntSize(vPoVars) );
+    assert( nMints <= Vec_IntSize(vPoVars) );
+    // remap minterms
+    Vec_IntFill( vLits, Vec_IntSize(vPoVars), -1 );
+    for ( m = 0; m < nMints; m++ )
+    {
+        mNew = 0;
+        for ( v = 0; v < nVarsAll; v++ )
+        {
+            assert( pPerm[v] < nVars );
+            if ( ((m >> pPerm[v]) & 1) )
+                mNew |= (1 << v);
+        }
+        assert( Vec_IntEntry(vLits, mNew) == -1 );
+        Vec_IntWriteEntry( vLits, mNew, Abc_TtGetBit(pTruth, m) );
+    }
+    // find assumptions
+    v = 0;
+    Vec_IntForEachEntry( vLits, Value, m )
+        if ( Value >= 0 )
+            Vec_IntWriteEntry( vLits, v++, Abc_Var2Lit(Vec_IntEntry(vPoVars, m), !Value) );
+    Vec_IntShrink( vLits, v );
+    // run SAT solver
+    Value = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 );
+    return (int)(Value == l_True);
+}
+void If_ManSatDeriveOne( sat_solver * pSat, Vec_Int_t * vPiVars, Vec_Int_t * vValues )
+{
+    int i, iVar;
+    Vec_IntClear( vValues );
+    Vec_IntForEachEntry( vPiVars, iVar, i )
+        Vec_IntPush( vValues, sat_solver_var_value(pSat, iVar) );
+}
+int If_ManSatCheckAll_int( sat_solver * pSat, Vec_Int_t * vPoVars, word * pTruth, int nVars, Vec_Int_t * vLits, char ** pPerms, int nPerms )
+{
+    int pPerm[IF_MAX_FUNC_LUTSIZE];
+    int p, i;
+    for ( p = 0; p < nPerms; p++ )
+    {
+        for ( i = 0; i < nVars; i++ )
+            pPerm[i] = (int)pPerms[p][i];
+        if ( If_ManSatCheckOne(pSat, vPoVars, pTruth, nVars, pPerm, nVars, vLits) )
+            return p;
+    }
+    return -1;
+}
+int If_ManSatCheckAll( sat_solver * pSat, Vec_Int_t * vPoVars, word * pTruth, int nVars, Vec_Int_t * vLits, char ** pPerms, int nPerms )
+{
+    abctime clk = Abc_Clock();
+    int RetValue = If_ManSatCheckAll_int( pSat, vPoVars, pTruth, nVars, vLits, pPerms, nPerms );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/ifUtil.c b/abc-build/src/map/if/ifUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/ifUtil.c
@@ -0,0 +1,632 @@
+/**CFile****************************************************************
+
+  FileName    [ifUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    [Various utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: ifUtil.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Sets all the node copy to NULL.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManCleanNodeCopy( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    int i;
+    If_ManForEachObj( p, pObj, i )
+        If_ObjSetCopy( pObj, NULL );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets all the cut data to NULL.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManCleanCutData( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    int i;
+    If_ManForEachObj( p, pObj, i )
+        If_CutSetData( If_ObjCutBest(pObj), NULL );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets all visited marks to 0.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManCleanMarkV( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    int i;
+    If_ManForEachObj( p, pObj, i )
+        pObj->fVisit = 0;
+}
+ 
+#if 0
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area, references, and nodes used in the mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_ManScanMapping_rec( If_Man_t * p, If_Obj_t * pObj, If_Obj_t ** ppStore )
+{
+    If_Obj_t * pLeaf;
+    If_Cut_t * pCutBest;
+    float aArea;
+    int i;
+    if ( pObj->nRefs++ || If_ObjIsCi(pObj) || If_ObjIsConst1(pObj) )
+        return 0.0;
+    // store the node in the structure by level
+    assert( If_ObjIsAnd(pObj) );
+    pObj->pCopy = (char *)ppStore[pObj->Level]; 
+    ppStore[pObj->Level] = pObj;
+    // visit the transitive fanin of the selected cut
+    pCutBest = If_ObjCutBest(pObj);
+    p->nNets += pCutBest->nLeaves;
+    aArea = If_CutLutArea( p, pCutBest );
+    If_CutForEachLeaf( p, pCutBest, pLeaf, i )
+        aArea += If_ManScanMapping_rec( p, pLeaf, ppStore );
+    return aArea;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area, references, and nodes used in the mapping.]
+
+  Description [Collects the nodes in reverse topological order in array 
+  p->vMapping.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_ManScanMapping( If_Man_t * p )
+{
+    If_Obj_t * pObj, ** ppStore;
+    float aArea;
+    int i;
+    assert( !p->pPars->fLiftLeaves );
+    // clean all references
+    p->nNets = 0;
+    If_ManForEachObj( p, pObj, i )
+    {
+        pObj->Required = IF_FLOAT_LARGE;
+        pObj->nVisits  = pObj->nVisitsCopy;
+        pObj->nRefs    = 0;
+    }
+    // allocate place to store the nodes
+    ppStore = ABC_ALLOC( If_Obj_t *, p->nLevelMax + 1 );
+    memset( ppStore, 0, sizeof(If_Obj_t *) * (p->nLevelMax + 1) );
+    // collect nodes reachable from POs in the DFS order through the best cuts
+    aArea = 0;
+    If_ManForEachCo( p, pObj, i )
+        aArea += If_ManScanMapping_rec( p, If_ObjFanin0(pObj), ppStore );
+    // reconnect the nodes in reverse topological order
+    Vec_PtrClear( p->vMapped );
+    for ( i = p->nLevelMax; i >= 0; i-- )
+        for ( pObj = ppStore[i]; pObj; pObj = pObj->pCopy )
+            Vec_PtrPush( p->vMapped, pObj );
+    ABC_FREE( ppStore );
+    return aArea;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area, references, and nodes used in the mapping.]
+
+  Description [Collects the nodes in reverse topological order in array 
+  p->vMapping.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_ManScanMappingDirect( If_Man_t * p )
+{
+    If_Obj_t * pObj, ** ppStore;
+    float aArea;
+    int i;
+    assert( !p->pPars->fLiftLeaves );
+    // clean all references
+    If_ManForEachObj( p, pObj, i )
+    {
+        pObj->Required = IF_FLOAT_LARGE;
+        pObj->nVisits  = pObj->nVisitsCopy;
+        pObj->nRefs    = 0;
+    }
+    // allocate place to store the nodes
+    ppStore = ABC_ALLOC( If_Obj_t *, p->nLevelMax + 1 );
+    memset( ppStore, 0, sizeof(If_Obj_t *) * (p->nLevelMax + 1) );
+    // collect nodes reachable from POs in the DFS order through the best cuts
+    aArea = 0;
+    If_ManForEachCo( p, pObj, i )
+        aArea += If_ManScanMapping_rec( p, If_ObjFanin0(pObj), ppStore );
+    // reconnect the nodes in reverse topological order
+    Vec_PtrClear( p->vMapped );
+//    for ( i = p->nLevelMax; i >= 0; i-- )
+    for ( i = 0; i <= p->nLevelMax; i++ )
+        for ( pObj = ppStore[i]; pObj; pObj = pObj->pCopy )
+            Vec_PtrPush( p->vMapped, pObj );
+    ABC_FREE( ppStore );
+    return aArea;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area, references, and nodes used in the mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_ManScanMappingSeq_rec( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vMapped )
+{
+    If_Obj_t * pLeaf;
+    If_Cut_t * pCutBest;
+    float aArea;
+    int i, Shift;
+    // treat latches transparently
+    if ( If_ObjIsLatch(pObj) )
+        return If_ManScanMappingSeq_rec( p, If_ObjFanin0(pObj), vMapped );
+    // consider trivial cases
+    if ( pObj->nRefs++ || If_ObjIsPi(pObj) || If_ObjIsConst1(pObj) )
+        return 0.0;
+    // store the node in the structure by level
+    assert( If_ObjIsAnd(pObj) );
+    // visit the transitive fanin of the selected cut
+    pCutBest = If_ObjCutBest(pObj);
+    aArea = If_ObjIsAnd(pObj)? If_CutLutArea(p, pCutBest) : (float)0.0;
+    If_CutForEachLeafSeq( p, pCutBest, pLeaf, Shift, i )
+        aArea += If_ManScanMappingSeq_rec( p, pLeaf, vMapped );
+    // add the node
+    Vec_PtrPush( vMapped, pObj );
+    return aArea;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area, references, and nodes used in the mapping.]
+
+  Description [Collects the nodes in reverse topological order in array 
+  p->vMapping.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_ManScanMappingSeq( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    float aArea;
+    int i;
+    assert( p->pPars->fLiftLeaves );
+    // clean all references
+    If_ManForEachObj( p, pObj, i )
+        pObj->nRefs = 0;
+    // collect nodes reachable from POs in the DFS order through the best cuts
+    aArea = 0;
+    Vec_PtrClear( p->vMapped );
+    If_ManForEachPo( p, pObj, i )
+        aArea += If_ManScanMappingSeq_rec( p, If_ObjFanin0(pObj), p->vMapped );
+    return aArea;
+}
+
+#endif
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area, references, and nodes used in the mapping.]
+
+  Description [Collects the nodes in reverse topological order in array 
+  p->vMapping.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManResetOriginalRefs( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    int i;
+    If_ManForEachObj( p, pObj, i )
+        pObj->nRefs = 0;
+    If_ManForEachObj( p, pObj, i )
+    {
+        if ( If_ObjIsAnd(pObj) )
+        {
+            pObj->pFanin0->nRefs++;
+            pObj->pFanin1->nRefs++;
+        }
+        else if ( If_ObjIsCo(pObj) )
+            pObj->pFanin0->nRefs++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes cross-cut of the circuit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManCrossCut( If_Man_t * p )
+{
+    If_Obj_t * pObj, * pFanin;
+    int i, nCutSize = 0, nCutSizeMax = 0;
+    If_ManForEachObj( p, pObj, i )
+    {
+        if ( !If_ObjIsAnd(pObj) )
+            continue;
+        // consider the node
+        if ( nCutSizeMax < ++nCutSize )
+            nCutSizeMax = nCutSize;
+        if ( pObj->nVisits == 0 )
+            nCutSize--;
+        // consider the fanins
+        pFanin = If_ObjFanin0(pObj);
+        if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
+            nCutSize--;
+        pFanin = If_ObjFanin1(pObj);
+        if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
+            nCutSize--;
+        // consider the choice class
+        if ( pObj->fRepr )
+            for ( pFanin = pObj; pFanin; pFanin = pFanin->pEquiv )
+                if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
+                    nCutSize--;
+    }
+    If_ManForEachObj( p, pObj, i )
+    {
+        assert( If_ObjIsCi(pObj) || pObj->fVisit == 0 );
+        pObj->nVisits = pObj->nVisitsCopy;
+    }
+    assert( nCutSize == 0 );
+//    Abc_Print( 1, "Max cross cut size = %6d.\n", nCutSizeMax );
+    return nCutSizeMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the reverse topological order of nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * If_ManReverseOrder( If_Man_t * p )
+{
+    Vec_Ptr_t * vOrder;
+    If_Obj_t * pObj, ** ppStore;
+    int i;
+    // allocate place to store the nodes
+    ppStore = ABC_ALLOC( If_Obj_t *, p->nLevelMax + 1 );
+    memset( ppStore, 0, sizeof(If_Obj_t *) * (p->nLevelMax + 1) );
+    // add the nodes
+    If_ManForEachObj( p, pObj, i )
+    {
+        assert( pObj->Level >= 0 && pObj->Level <= (unsigned)p->nLevelMax );
+        pObj->pCopy = (char *)ppStore[pObj->Level]; 
+        ppStore[pObj->Level] = pObj;
+    }
+    vOrder = Vec_PtrAlloc( If_ManObjNum(p) );
+    for ( i = p->nLevelMax; i >= 0; i-- )
+        for ( pObj = ppStore[i]; pObj; pObj = (If_Obj_t *)pObj->pCopy )
+            Vec_PtrPush( vOrder, pObj );
+    ABC_FREE( ppStore );
+    // print the order
+//    Vec_PtrForEachEntry( If_Obj_t *, vOrder, pObj, i )
+//        Abc_Print( 1, "Obj %2d   Type %d  Level = %d\n", pObj->Id, pObj->Type, pObj->Level );
+    return vOrder;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Computes area, references, and nodes used in the mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float If_ManMarkMapping_rec( If_Man_t * p, If_Obj_t * pObj )
+{
+    If_Obj_t * pLeaf;
+    If_Cut_t * pCutBest;
+    float * pSwitching = p->vSwitching? (float*)p->vSwitching->pArray : NULL;
+    float aArea;
+    int i;
+    if ( pObj->nRefs++ || If_ObjIsCi(pObj) || If_ObjIsConst1(pObj) )
+        return 0.0;
+    // store the node in the structure by level
+    assert( If_ObjIsAnd(pObj) );
+    // visit the transitive fanin of the selected cut
+    pCutBest = If_ObjCutBest(pObj);
+    p->nNets += pCutBest->nLeaves;
+    aArea = If_CutLutArea( p, pCutBest );
+    If_CutForEachLeaf( p, pCutBest, pLeaf, i )
+    {
+        p->dPower += pSwitching? pSwitching[pLeaf->Id] : 0.0;
+        aArea += If_ManMarkMapping_rec( p, pLeaf );
+    }
+    return aArea;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area, references, and nodes used in the mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManMarkMapping( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    int i;
+    If_ManForEachObj( p, pObj, i )
+    {
+        pObj->Required = IF_FLOAT_LARGE;
+        pObj->nVisits = pObj->nVisitsCopy;
+        pObj->nRefs = 0;
+    }
+    p->nNets = 0;
+    p->dPower = 0.0;
+    p->AreaGlo = 0.0;
+    If_ManForEachCo( p, pObj, i )
+        p->AreaGlo += If_ManMarkMapping_rec( p, If_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes used in the mapping in the topological order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * If_ManCollectMappingDirect( If_Man_t * p )
+{
+    Vec_Ptr_t * vOrder;
+    If_Obj_t * pObj;
+    int i;
+    If_ManMarkMapping( p );
+    vOrder = Vec_PtrAlloc( If_ManObjNum(p) );
+    If_ManForEachObj( p, pObj, i )
+        if ( If_ObjIsAnd(pObj) && pObj->nRefs )
+            Vec_PtrPush( vOrder, pObj );
+    return vOrder;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes used in the mapping in the topological order.]
+
+  Description [Represents mapping as an array of integers.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * If_ManCollectMappingInt( If_Man_t * p )
+{
+    Vec_Int_t * vOrder;
+    If_Cut_t * pCutBest;
+    If_Obj_t * pObj;
+    int i, k, nLeaves, * ppLeaves;
+    If_ManMarkMapping( p );
+    vOrder = Vec_IntAlloc( If_ManObjNum(p) );
+    If_ManForEachObj( p, pObj, i )
+        if ( If_ObjIsAnd(pObj) && pObj->nRefs )
+        {
+            pCutBest = If_ObjCutBest( pObj );
+            nLeaves  = If_CutLeaveNum( pCutBest ); 
+            ppLeaves = If_CutLeaves( pCutBest );
+            // save the number of leaves, the leaves, and finally, the root
+            Vec_IntPush( vOrder, nLeaves );
+            for ( k = 0; k < nLeaves; k++ )
+                Vec_IntPush( vOrder, ppLeaves[k] );
+            Vec_IntPush( vOrder, pObj->Id );
+        }
+    return vOrder;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of POs pointing to the same internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManCountSpecialPos( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    int i, Counter = 0;
+    // clean all marks
+    If_ManForEachPo( p, pObj, i )
+        If_ObjFanin0(pObj)->fMark = 0;
+    // label nodes 
+    If_ManForEachPo( p, pObj, i )
+        if ( !If_ObjFaninC0(pObj) )
+            If_ObjFanin0(pObj)->fMark = 1;
+    // label nodes 
+    If_ManForEachPo( p, pObj, i )
+        if ( If_ObjFaninC0(pObj) )
+            Counter += If_ObjFanin0(pObj)->fMark;
+    // clean all marks
+    If_ManForEachPo( p, pObj, i )
+        If_ObjFanin0(pObj)->fMark = 0;
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Traverse the cut and counts its volume.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void If_CutTraverse_rec( If_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    if ( pNode->fMark )
+        return;
+    pNode->fMark = 1;
+//    assert( !If_ObjIsCi(pNode) ); // does not hold with cut minimization
+    if ( If_ObjIsAnd(pNode) )
+        If_CutTraverse_rec( If_ObjFanin0(pNode), vNodes );
+    if ( If_ObjIsAnd(pNode) )
+        If_CutTraverse_rec( If_ObjFanin1(pNode), vNodes );
+    Vec_PtrPush( vNodes, pNode );
+}
+void If_CutTraverse( If_Man_t * p, If_Obj_t * pRoot, If_Cut_t * pCut, Vec_Ptr_t * vNodes )
+{
+    If_Obj_t * pLeaf;
+    int i;
+    // collect the internal nodes of the cut
+    Vec_PtrClear( vNodes );
+    If_CutForEachLeaf( p, pCut, pLeaf, i )
+    {
+        Vec_PtrPush( vNodes, pLeaf );
+        assert( pLeaf->fMark == 0 );
+        pLeaf->fMark = 1;
+    }
+    // collect other nodes
+    If_CutTraverse_rec( pRoot, vNodes );
+    // clean the mark
+    Vec_PtrForEachEntry( If_Obj_t *, vNodes, pLeaf, i )
+        pLeaf->fMark = 0;
+}
+void If_CutTraverseTest( If_Man_t * p, If_Obj_t * pRoot, If_Cut_t * pCut )
+{
+    Vec_Ptr_t * vNodes;
+    vNodes = Vec_PtrAlloc( 1000 );
+    If_CutTraverse( p, pRoot, pCut, vNodes );
+//if ( Vec_PtrSize(vNodes) > 30 )
+//printf( "%d ", Vec_PtrSize(vNodes) );
+    Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ObjPrint( If_Obj_t * pObj )
+{
+    if ( pObj == NULL )
+    {
+        printf( "Object is NULL." );
+        return;
+    }
+    printf( "Obj %4d : ", If_ObjId(pObj) );
+    if ( If_ObjIsConst1(pObj) )
+        printf( "constant 1" );
+    else if ( If_ObjIsCi(pObj) )
+        printf( "PI" );
+    else if ( If_ObjIsCo(pObj) )
+        printf( "PO( %4d%s )", If_ObjId(If_ObjFanin0(pObj)), (If_ObjFaninC0(pObj)? "\'" : " ") );
+    else
+        printf( "AND( %4d%s, %4d%s )", 
+            If_ObjId(If_ObjFanin0(pObj)), (If_ObjFaninC0(pObj)? "\'" : " "), 
+            If_ObjId(If_ObjFanin1(pObj)), (If_ObjFaninC1(pObj)? "\'" : " ") );
+    printf( " (refs = %3d)", pObj->nVisitsCopy );
+    printf( "\n" );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/if_.c b/abc-build/src/map/if/if_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/if_.c
@@ -0,0 +1,52 @@
+/**CFile****************************************************************
+
+  FileName    [if_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [FPGA mapping based on priority cuts.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 21, 2006.]
+
+  Revision    [$Id: if_.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/if/module.make b/abc-build/src/map/if/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/if/module.make
@@ -0,0 +1,24 @@
+SRC +=  src/map/if/ifCom.c \
+	src/map/if/ifCache.c \
+	src/map/if/ifCore.c \
+	src/map/if/ifCut.c \
+	src/map/if/ifDec07.c \
+	src/map/if/ifDec08.c \
+	src/map/if/ifDec10.c \
+	src/map/if/ifDec16.c \
+	src/map/if/ifDec75.c \
+	src/map/if/ifDelay.c \
+	src/map/if/ifDsd.c \
+	src/map/if/ifLibBox.c \
+	src/map/if/ifLibLut.c \
+	src/map/if/ifMan.c \
+	src/map/if/ifMap.c \
+	src/map/if/ifReduce.c \
+	src/map/if/ifSat.c \
+	src/map/if/ifSelect.c \
+	src/map/if/ifSeq.c \
+	src/map/if/ifTest.c \
+	src/map/if/ifTime.c \
+	src/map/if/ifTruth.c \
+	src/map/if/ifTune.c \
+	src/map/if/ifUtil.c 
diff --git a/abc-build/src/map/mapper/mapper.c b/abc-build/src/map/mapper/mapper.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapper.c
@@ -0,0 +1,185 @@
+/**CFile****************************************************************
+
+  FileName    [mapper.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Command file for the mapper package.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapper.c,v 1.7 2005/01/23 06:59:42 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "base/main/mainInt.h"
+#include "map/mio/mio.h"
+#include "mapperInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Map_CommandReadLibrary ( Abc_Frame_t * pAbc, int argc, char **argv );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_Init( Abc_Frame_t * pAbc )
+{
+    Cmd_CommandAdd( pAbc, "SC mapping", "read_super",  Map_CommandReadLibrary, 0 ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_End( Abc_Frame_t * pAbc )
+{
+//    Map_SuperLibFree( s_pSuperLib );
+     Map_SuperLibFree( (Map_SuperLib_t *)Abc_FrameReadLibSuper() );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    FILE * pFile;
+    FILE * pOut, * pErr;
+    Map_SuperLib_t * pLib;
+    Abc_Ntk_t * pNet;
+    char * FileName, * ExcludeFile;
+    int fVerbose;
+    int fAlgorithm;
+    int c;
+
+    pNet = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    // set the defaults
+    fVerbose = 1;
+    fAlgorithm = 1;
+    ExcludeFile = 0;
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "eovh")) != EOF ) 
+    {
+        switch (c) 
+        {
+            case 'e':
+                ExcludeFile = argv[globalUtilOptind];
+                if ( ExcludeFile == 0 )
+                    goto usage;
+                globalUtilOptind++;
+                break;
+            case 'o':
+                fAlgorithm ^= 1;
+                break;
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+                break;
+            default:
+                goto usage;
+        }
+    }
+
+
+    if ( argc != globalUtilOptind + 1 )
+    {
+        goto usage;
+    }
+
+    // get the input file name
+    FileName = argv[globalUtilOptind];
+    if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL )
+//    if ( (pFile = fopen( FileName, "r" )) == NULL )
+    {
+        fprintf( pErr, "Cannot open input file \"%s\". ", FileName );
+        if (( FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL )) )
+            fprintf( pErr, "Did you mean \"%s\"?", FileName );
+        fprintf( pErr, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+
+    if ( Abc_FrameReadLibGen() == NULL )
+    {
+        fprintf( pErr, "Genlib library should be read in first..\n" );
+        return 1;
+    }
+
+    // set the new network
+    pLib = Map_SuperLibCreate( (Mio_Library_t *)Abc_FrameReadLibGen(), NULL, FileName, ExcludeFile, fAlgorithm, fVerbose );
+    if ( pLib == NULL )
+    {
+        fprintf( pErr, "Reading supergate library has failed.\n" );
+        return 1;
+    }
+    // replace the current library
+//    Map_SuperLibFree( s_pSuperLib );
+//    s_pSuperLib = pLib;
+    Map_SuperLibFree( (Map_SuperLib_t *)Abc_FrameReadLibSuper() );
+    Abc_FrameSetLibSuper( pLib );
+    // replace the current genlib library
+//    Mio_LibraryDelete( (Mio_Library_t *)Abc_FrameReadLibGen() );
+//    Abc_FrameSetLibGen( (Mio_Library_t *)pLib->pGenlib );
+    return 0;
+
+usage:
+    fprintf( pErr, "\nusage: read_super [-ovh]\n");
+    fprintf( pErr, "\t         read the supergate library from the file\n" );  
+    fprintf( pErr, "\t-e file : file contains list of genlib gates to exclude\n" );
+    fprintf( pErr, "\t-o      : toggles the use of old file format [default = %s]\n", (fAlgorithm? "new" : "old") );
+    fprintf( pErr, "\t-v      : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") );
+    fprintf( pErr, "\t-h      : print the command usage\n");
+    return 1;       /* error exit */
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/mapper.h b/abc-build/src/map/mapper/mapper.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapper.h
@@ -0,0 +1,199 @@
+/**CFile****************************************************************
+
+  FileName    [mapper.h]
+ 
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapper.h,v 1.11 2005/02/28 05:34:26 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__map__mapper__mapper_h
+#define ABC__map__mapper__mapper_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Map_ManStruct_t_         Map_Man_t;
+typedef struct Map_NodeStruct_t_        Map_Node_t;
+typedef struct Map_NodeVecStruct_t_     Map_NodeVec_t;
+typedef struct Map_CutStruct_t_         Map_Cut_t;
+typedef struct Map_MatchStruct_t_       Map_Match_t;
+typedef struct Map_SuperStruct_t_       Map_Super_t;
+typedef struct Map_SuperLibStruct_t_    Map_SuperLib_t;
+typedef struct Map_HashTableStruct_t_   Map_HashTable_t;
+typedef struct Map_HashEntryStruct_t_   Map_HashEntry_t;
+typedef struct Map_TimeStruct_t_        Map_Time_t;
+
+// the pair of rise/fall time parameters
+struct Map_TimeStruct_t_
+{
+    float              Rise;
+    float              Fall;
+    float              Worst;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+ 
+#define Map_IsComplement(p)    (((int)((ABC_PTRUINT_T) (p) & 01)))
+#define Map_Regular(p)         ((Map_Node_t *)((ABC_PTRUINT_T)(p) & ~01)) 
+#define Map_Not(p)             ((Map_Node_t *)((ABC_PTRUINT_T)(p) ^ 01)) 
+#define Map_NotCond(p,c)       ((Map_Node_t *)((ABC_PTRUINT_T)(p) ^ (c)))
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== mapperCreate.c =============================================================*/
+extern Map_Man_t *     Map_ManCreate( int nInputs, int nOutputs, int fVerbose );
+extern Map_Node_t *    Map_NodeCreate( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 );
+extern void            Map_ManCreateNodeDelays( Map_Man_t * p, int LogFan );
+extern void            Map_ManFree( Map_Man_t * pMan );
+extern void            Map_ManPrintTimeStats( Map_Man_t * p );
+extern void            Map_ManPrintStatsToFile( char * pName, float Area, float Delay, abctime Time );
+extern int             Map_ManReadInputNum( Map_Man_t * p );
+extern int             Map_ManReadOutputNum( Map_Man_t * p );
+extern int             Map_ManReadBufNum( Map_Man_t * p );
+extern Map_Node_t **   Map_ManReadInputs ( Map_Man_t * p );
+extern Map_Node_t **   Map_ManReadOutputs( Map_Man_t * p );
+extern Map_Node_t **   Map_ManReadBufs( Map_Man_t * p );
+extern Map_Node_t *    Map_ManReadBufDriver( Map_Man_t * p, int i );
+extern Map_Node_t *    Map_ManReadConst1 ( Map_Man_t * p );
+extern Map_Time_t *    Map_ManReadInputArrivals( Map_Man_t * p );
+extern Mio_Library_t * Map_ManReadGenLib ( Map_Man_t * p );
+extern int             Map_ManReadVerbose( Map_Man_t * p );
+extern float           Map_ManReadAreaFinal( Map_Man_t * p );
+extern float           Map_ManReadRequiredGlo( Map_Man_t * p );
+extern void            Map_ManSetOutputNames( Map_Man_t * p, char ** ppNames );
+extern void            Map_ManSetAreaRecovery( Map_Man_t * p, int fAreaRecovery );
+extern void            Map_ManSetDelayTarget( Map_Man_t * p, float DelayTarget );
+extern void            Map_ManSetInputArrivals( Map_Man_t * p, Map_Time_t * pArrivals );
+extern void            Map_ManSetOutputRequireds( Map_Man_t * p, Map_Time_t * pArrivals );
+extern void            Map_ManSetObeyFanoutLimits( Map_Man_t * p, int  fObeyFanoutLimits );              
+extern void            Map_ManSetNumIterations( Map_Man_t * p, int nNumIterations );
+extern int             Map_ManReadPass( Map_Man_t * p );
+extern void            Map_ManSetPass( Map_Man_t * p, int nPass );
+extern int             Map_ManReadFanoutViolations( Map_Man_t * p );
+extern void            Map_ManSetFanoutViolations( Map_Man_t * p, int nVio );
+extern void            Map_ManSetChoiceNodeNum( Map_Man_t * p, int nChoiceNodes );
+extern void            Map_ManSetChoiceNum( Map_Man_t * p, int nChoices );
+extern void            Map_ManSetVerbose( Map_Man_t * p, int fVerbose );
+extern void            Map_ManSetSwitching( Map_Man_t * p, int fSwitching );
+
+extern Map_Man_t *     Map_NodeReadMan( Map_Node_t * p );
+extern char *          Map_NodeReadData( Map_Node_t * p, int fPhase );
+extern int             Map_NodeReadNum( Map_Node_t * p );
+extern int             Map_NodeReadLevel( Map_Node_t * p );
+extern Map_Cut_t *     Map_NodeReadCuts( Map_Node_t * p );
+extern Map_Cut_t *     Map_NodeReadCutBest( Map_Node_t * p, int fPhase );
+extern Map_Node_t *    Map_NodeReadOne( Map_Node_t * p );
+extern Map_Node_t *    Map_NodeReadTwo( Map_Node_t * p );
+extern void            Map_NodeSetData( Map_Node_t * p, int fPhase, char * pData );
+extern void            Map_NodeSetNextE( Map_Node_t * p, Map_Node_t * pNextE );
+extern void            Map_NodeSetRepr( Map_Node_t * p, Map_Node_t * pRepr );
+extern void            Map_NodeSetSwitching( Map_Node_t * p, float Switching );
+
+extern int             Map_NodeIsConst( Map_Node_t * p );
+extern int             Map_NodeIsVar( Map_Node_t * p );
+extern int             Map_NodeIsBuf( Map_Node_t * p );
+extern int             Map_NodeIsAnd( Map_Node_t * p );
+extern int             Map_NodeComparePhase( Map_Node_t * p1, Map_Node_t * p2 );
+
+extern Map_Super_t *   Map_CutReadSuperBest( Map_Cut_t * p, int fPhase );
+extern Map_Super_t *   Map_CutReadSuper0( Map_Cut_t * p );
+extern Map_Super_t *   Map_CutReadSuper1( Map_Cut_t * p );
+extern int             Map_CutReadLeavesNum( Map_Cut_t * p );
+extern Map_Node_t **   Map_CutReadLeaves( Map_Cut_t * p );
+extern unsigned        Map_CutReadPhaseBest( Map_Cut_t * p, int fPhase );
+extern unsigned        Map_CutReadPhase0( Map_Cut_t * p );
+extern unsigned        Map_CutReadPhase1( Map_Cut_t * p );
+extern Map_Cut_t *     Map_CutReadNext( Map_Cut_t * p );
+
+extern char *          Map_SuperReadFormula( Map_Super_t * p );
+extern Mio_Gate_t *    Map_SuperReadRoot( Map_Super_t * p );
+extern int             Map_SuperReadNum( Map_Super_t * p );
+extern Map_Super_t **  Map_SuperReadFanins( Map_Super_t * p );
+extern int             Map_SuperReadFaninNum( Map_Super_t * p );
+extern Map_Super_t *   Map_SuperReadNext( Map_Super_t * p );
+extern int             Map_SuperReadNumPhases( Map_Super_t * p );
+extern unsigned char * Map_SuperReadPhases( Map_Super_t * p );
+extern int             Map_SuperReadFanoutLimit( Map_Super_t * p );
+
+extern Mio_Library_t * Map_SuperLibReadGenLib( Map_SuperLib_t * p );
+extern float           Map_SuperLibReadAreaInv( Map_SuperLib_t * p );
+extern Map_Time_t      Map_SuperLibReadDelayInv( Map_SuperLib_t * p );
+extern int             Map_SuperLibReadVarsMax( Map_SuperLib_t * p );
+
+extern Map_Node_t *    Map_NodeAnd( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 );
+extern Map_Node_t *    Map_NodeBuf( Map_Man_t * p, Map_Node_t * p1 );
+extern void            Map_NodeSetChoice( Map_Man_t * pMan, Map_Node_t * pNodeOld, Map_Node_t * pNodeNew );
+
+/*=== resmCanon.c =============================================================*/
+extern int             Map_CanonComputeSlow( unsigned uTruths[][2], int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] );
+extern int             Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] );
+/*=== mapperCut.c =============================================================*/
+extern Map_Cut_t *     Map_CutAlloc( Map_Man_t * p );
+/*=== mapperCutUtils.c =============================================================*/
+extern void            Map_CutCreateFromNode( Map_Man_t * p, Map_Super_t * pSuper, int iRoot, unsigned uPhaseRoot, 
+                           int * pLeaves, int nLeaves, unsigned uPhaseLeaves );
+/*=== mapperCore.c =============================================================*/
+extern int             Map_Mapping( Map_Man_t * p );
+/*=== mapperLib.c =============================================================*/
+extern int             Map_SuperLibDeriveFromGenlib( Mio_Library_t * pLib, int fVerbose );
+extern void            Map_SuperLibFree( Map_SuperLib_t * p );
+/*=== mapperMntk.c =============================================================*/
+//extern Mntk_Man_t *    Map_ConvertMappingToMntk( Map_Man_t * pMan );
+/*=== mapperSuper.c =============================================================*/
+extern char *          Map_LibraryReadFormulaStep( char * pFormula, char * pStrings[], int * pnStrings );
+/*=== mapperSweep.c =============================================================*/
+extern void            Map_NetworkSweep( Abc_Ntk_t * pNet );
+/*=== mapperTable.c =============================================================*/
+extern Map_Super_t *   Map_SuperTableLookupC( Map_SuperLib_t * pLib, unsigned uTruth[] );
+/*=== mapperTime.c =============================================================*/
+/*=== mapperUtil.c =============================================================*/
+extern int             Map_ManCheckConsistency( Map_Man_t * p );
+extern st__table *      Map_CreateTableGate2Super( Map_Man_t * p );
+extern void            Map_ManCleanData( Map_Man_t * p );
+extern void            Map_MappingSetupTruthTables( unsigned uTruths[][2] );
+extern void            Map_MappingSetupTruthTablesLarge( unsigned uTruths[][32] );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/map/mapper/mapperCanon.c b/abc-build/src/map/mapper/mapperCanon.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperCanon.c
@@ -0,0 +1,277 @@
+/**CFile****************************************************************
+
+  FileName    [mapperCanon.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapperCanon.c,v 1.2 2005/01/23 06:59:42 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static unsigned Map_CanonComputePhase( unsigned uTruths[][2], int nVars, unsigned uTruth, unsigned uPhase );
+static void     Map_CanonComputePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the N-canonical form of the Boolean function.]
+
+  Description [The N-canonical form is defined as the truth table with 
+  the minimum integer value. This function exhaustively enumerates 
+  through the complete set of 2^N phase assignments.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_CanonComputeSlow( unsigned uTruths[][2], int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] )
+{
+    unsigned  uTruthPerm[2];
+    int nMints, nPhases, m;
+
+    nPhases = 0;
+    nMints = (1 << nVarsReal);
+    if ( nVarsMax < 6 )
+    {
+        uTruthRes[0] = MAP_MASK(32);
+        for ( m = 0; m < nMints; m++ )
+        {
+            uTruthPerm[0] = Map_CanonComputePhase( uTruths, nVarsMax, uTruth[0], m );
+            if ( uTruthRes[0] > uTruthPerm[0] )
+            {
+                uTruthRes[0] = uTruthPerm[0];
+                nPhases      = 0;
+                puPhases[nPhases++] = (unsigned char)m;
+            }
+            else if ( uTruthRes[0] == uTruthPerm[0] )
+            {
+                if ( nPhases < 4 ) // the max number of phases in Map_Super_t
+                    puPhases[nPhases++] = (unsigned char)m;
+            }
+        }
+        uTruthRes[1] = uTruthRes[0];
+    }
+    else
+    {
+        uTruthRes[0] = MAP_MASK(32);
+        uTruthRes[1] = MAP_MASK(32);
+        for ( m = 0; m < nMints; m++ )
+        {
+            Map_CanonComputePhase6( uTruths, nVarsMax, uTruth, m, uTruthPerm );
+            if ( uTruthRes[1] > uTruthPerm[1] || (uTruthRes[1] == uTruthPerm[1] && uTruthRes[0] > uTruthPerm[0]) )
+            {
+                uTruthRes[0] = uTruthPerm[0];
+                uTruthRes[1] = uTruthPerm[1];
+                nPhases      = 0;
+                puPhases[nPhases++] = (unsigned char)m;
+            }
+            else if ( uTruthRes[1] == uTruthPerm[1] && uTruthRes[0] == uTruthPerm[0] )
+            {
+                if ( nPhases < 4 ) // the max number of phases in Map_Super_t
+                    puPhases[nPhases++] = (unsigned char)m;
+            }
+        }
+    }
+    assert( nPhases > 0 );
+//    printf( "%d ", nPhases );
+    return nPhases;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs phase transformation for one function of less than 6 variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Map_CanonComputePhase( unsigned uTruths[][2], int nVars, unsigned uTruth, unsigned uPhase )
+{
+    int v, Shift;
+    for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 )
+        if ( uPhase & Shift )
+            uTruth = (((uTruth & ~uTruths[v][0]) << Shift) | ((uTruth & uTruths[v][0]) >> Shift));
+    return uTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs phase transformation for one function of 6 variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_CanonComputePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] )
+{
+    unsigned uTemp;
+    int v, Shift;
+
+    // initialize the result
+    uTruthRes[0] = uTruth[0];
+    uTruthRes[1] = uTruth[1];
+    if ( uPhase == 0 )
+        return;
+    // compute the phase 
+    for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 )
+        if ( uPhase & Shift )
+        {
+            if ( Shift < 32 )
+            {
+                uTruthRes[0] = (((uTruthRes[0] & ~uTruths[v][0]) << Shift) | ((uTruthRes[0] & uTruths[v][0]) >> Shift));
+                uTruthRes[1] = (((uTruthRes[1] & ~uTruths[v][1]) << Shift) | ((uTruthRes[1] & uTruths[v][1]) >> Shift));
+            }
+            else
+            {
+                uTemp        = uTruthRes[0];
+                uTruthRes[0] = uTruthRes[1];
+                uTruthRes[1] = uTemp;
+            }
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the N-canonical form of the Boolean function.]
+
+  Description [The N-canonical form is defined as the truth table with 
+  the minimum integer value. This function exhaustively enumerates 
+  through the complete set of 2^N phase assignments.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] )
+{
+    unsigned uTruth0, uTruth1;
+    unsigned uCanon0, uCanon1, uCanonBest;
+    unsigned uPhaseBest = 16; // Suppress "might be used uninitialized" (asserts require < 16)
+    int i, Limit;
+
+    if ( nVarsMax == 6 )
+        return Map_CanonComputeSlow( p->uTruths, nVarsMax, nVarsReal, uTruth, puPhases, uTruthRes );
+
+    if ( nVarsReal < 5 )
+    {
+//        return Map_CanonComputeSlow( p->uTruths, nVarsMax, nVarsReal, uTruth, puPhases, uTruthRes );
+
+        uTruth0 = uTruth[0] & 0xFFFF;
+        assert( p->pCounters[uTruth0] > 0 );
+        uTruthRes[0] = (p->uCanons[uTruth0] << 16) | p->uCanons[uTruth0];
+        uTruthRes[1] = uTruthRes[0];
+        puPhases[0] = p->uPhases[uTruth0][0];
+        return 1;
+    }
+
+    assert( nVarsMax == 5 );
+    assert( nVarsReal == 5 );
+    uTruth0 = uTruth[0] & 0xFFFF;
+    uTruth1 = (uTruth[0] >> 16);
+    if ( uTruth1 == 0 )
+    {
+        uTruthRes[0] = p->uCanons[uTruth0];
+        uTruthRes[1] = uTruthRes[0];
+        Limit = (p->pCounters[uTruth0] > 4)? 4 : p->pCounters[uTruth0];
+        for ( i = 0; i < Limit; i++ )
+            puPhases[i] = p->uPhases[uTruth0][i];
+        return Limit;
+    }
+    else if ( uTruth0 == 0 )
+    {
+        uTruthRes[0] = p->uCanons[uTruth1];
+        uTruthRes[1] = uTruthRes[0];
+        Limit = (p->pCounters[uTruth1] > 4)? 4 : p->pCounters[uTruth1];
+        for ( i = 0; i < Limit; i++ )
+        {
+            puPhases[i] = p->uPhases[uTruth1][i];
+            puPhases[i] |= (1 << 4);
+        }
+        return Limit;
+    }
+    uCanon0 = p->uCanons[uTruth0];
+    uCanon1 = p->uCanons[uTruth1];
+    if ( uCanon0 >= uCanon1 ) // using nCanon1 as the main one
+    {
+        assert( p->pCounters[uTruth1] > 0 );
+        uCanonBest = 0xFFFFFFFF;
+        for ( i = 0; i < p->pCounters[uTruth1]; i++ )
+        {
+            uCanon0 = Extra_TruthPolarize( uTruth0, p->uPhases[uTruth1][i], 4 );
+            if ( uCanonBest > uCanon0 )
+            {
+                uCanonBest = uCanon0;
+                uPhaseBest = p->uPhases[uTruth1][i];
+                assert( uPhaseBest < 16 );
+            }
+        }
+        uTruthRes[0] = (uCanon1 << 16) | uCanonBest;
+        uTruthRes[1] = uTruthRes[0];
+        puPhases[0] = uPhaseBest;
+        return 1;
+    }
+    else if ( uCanon0 < uCanon1 )
+    {
+        assert( p->pCounters[uTruth0] > 0 );
+        uCanonBest = 0xFFFFFFFF;
+        for ( i = 0; i < p->pCounters[uTruth0]; i++ )
+        {
+            uCanon1 = Extra_TruthPolarize( uTruth1, p->uPhases[uTruth0][i], 4 );
+            if ( uCanonBest > uCanon1 )
+            {
+                uCanonBest = uCanon1;
+                uPhaseBest = p->uPhases[uTruth0][i];
+                assert( uPhaseBest < 16 );
+            }
+        }
+        uTruthRes[0] = (uCanon0 << 16) | uCanonBest;
+        uTruthRes[1] = uTruthRes[0];
+        puPhases[0] = uPhaseBest | (1 << 4);
+        return 1;
+    }
+    else
+    {
+        assert( 0 );
+        return Map_CanonComputeSlow( p->uTruths, nVarsMax, nVarsReal, uTruth, puPhases, uTruthRes );
+    }
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/mapperCore.c b/abc-build/src/map/mapper/mapperCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperCore.c
@@ -0,0 +1,231 @@
+/**CFile****************************************************************
+
+  FileName    [mapperCore.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapperCore.c,v 1.7 2004/10/01 23:41:04 satrajit Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+//#include "resm.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs technology mapping for the given object graph.]
+
+  Description [The object graph is stored in the mapping manager.
+  First, the AND nodes that fanout into POs are collected in the DFS order.
+  Two preprocessing steps are performed: the k-feasible cuts are computed 
+  for each node and the truth tables are computed for each cut. Next, the 
+  delay-optimal matches are assigned for each node, followed by several 
+  iterations of area recoveryd: using area flow (global optimization) 
+  and using exact area at a node (local optimization).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_Mapping( Map_Man_t * p )
+{
+    int fShowSwitching         = 0;
+    int fUseAreaFlow           = 1;
+    int fUseExactArea          = !p->fSwitching;
+    int fUseExactAreaWithPhase = !p->fSwitching;
+    abctime clk;
+
+    //////////////////////////////////////////////////////////////////////
+    // perform pre-mapping computations
+    if ( p->fVerbose )
+        Map_MappingReportChoices( p ); 
+    Map_MappingSetChoiceLevels( p ); // should always be called before mapping!
+//    return 1;
+
+    // compute the cuts of nodes in the DFS order
+    clk = Abc_Clock();
+    Map_MappingCuts( p );
+    p->timeCuts = Abc_Clock() - clk;
+    // derive the truth tables 
+    clk = Abc_Clock();
+    Map_MappingTruths( p );
+    p->timeTruth = Abc_Clock() - clk;
+    //////////////////////////////////////////////////////////////////////
+//ABC_PRT( "Truths", Abc_Clock() - clk );
+
+    //////////////////////////////////////////////////////////////////////
+    // compute the minimum-delay mapping
+    clk = Abc_Clock();
+    p->fMappingMode = 0;
+    if ( !Map_MappingMatches( p ) )
+        return 0;
+    p->timeMatch = Abc_Clock() - clk;
+    // compute the references and collect the nodes used in the mapping
+    Map_MappingSetRefs( p );
+    p->AreaBase = Map_MappingGetArea( p );
+if ( p->fVerbose )
+{
+printf( "Delay    : %s = %8.2f  Flow = %11.1f  Area = %11.1f  %4.1f %%   ", 
+                    fShowSwitching? "Switch" : "Delay", 
+                    fShowSwitching? Map_MappingGetSwitching(p) : p->fRequiredGlo, 
+                    Map_MappingGetAreaFlow(p), p->AreaBase, 0.0 );
+ABC_PRT( "Time", p->timeMatch );
+}
+    //////////////////////////////////////////////////////////////////////
+
+    if ( !p->fAreaRecovery )
+    {
+        if ( p->fVerbose )
+            Map_MappingPrintOutputArrivals( p );
+        return 1;
+    }
+
+    //////////////////////////////////////////////////////////////////////
+    // perform area recovery using area flow
+    clk = Abc_Clock();
+    if ( fUseAreaFlow )
+    {
+        // compute the required times
+        Map_TimeComputeRequiredGlobal( p );
+        // recover area flow
+        p->fMappingMode = 1;
+        Map_MappingMatches( p );
+        // compute the references and collect the nodes used in the mapping
+        Map_MappingSetRefs( p );
+        p->AreaFinal = Map_MappingGetArea( p );
+if ( p->fVerbose )
+{
+printf( "AreaFlow : %s = %8.2f  Flow = %11.1f  Area = %11.1f  %4.1f %%   ", 
+                    fShowSwitching? "Switch" : "Delay", 
+                    fShowSwitching? Map_MappingGetSwitching(p) : p->fRequiredGlo, 
+                    Map_MappingGetAreaFlow(p), p->AreaFinal, 
+                    100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase );
+ABC_PRT( "Time", Abc_Clock() - clk );
+}
+    }
+    p->timeArea += Abc_Clock() - clk;
+    //////////////////////////////////////////////////////////////////////
+
+    //////////////////////////////////////////////////////////////////////
+    // perform area recovery using exact area
+    clk = Abc_Clock();
+    if ( fUseExactArea )
+    {
+        // compute the required times
+        Map_TimeComputeRequiredGlobal( p );
+        // recover area
+        p->fMappingMode = 2;
+        Map_MappingMatches( p );
+        // compute the references and collect the nodes used in the mapping
+        Map_MappingSetRefs( p );
+        p->AreaFinal = Map_MappingGetArea( p );
+if ( p->fVerbose )
+{
+printf( "Area     : %s = %8.2f  Flow = %11.1f  Area = %11.1f  %4.1f %%   ", 
+                    fShowSwitching? "Switch" : "Delay", 
+                    fShowSwitching? Map_MappingGetSwitching(p) : p->fRequiredGlo, 
+                    0.0, p->AreaFinal, 
+                    100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase );
+ABC_PRT( "Time", Abc_Clock() - clk );
+}
+    }
+    p->timeArea += Abc_Clock() - clk;
+    //////////////////////////////////////////////////////////////////////
+
+    //////////////////////////////////////////////////////////////////////
+    // perform area recovery using exact area
+    clk = Abc_Clock();
+    if ( fUseExactAreaWithPhase )
+    {
+        // compute the required times
+        Map_TimeComputeRequiredGlobal( p );
+        // recover area
+        p->fMappingMode = 3;
+        Map_MappingMatches( p );
+        // compute the references and collect the nodes used in the mapping
+        Map_MappingSetRefs( p );
+        p->AreaFinal = Map_MappingGetArea( p );
+if ( p->fVerbose )
+{
+printf( "Area     : %s = %8.2f  Flow = %11.1f  Area = %11.1f  %4.1f %%   ", 
+                    fShowSwitching? "Switch" : "Delay", 
+                    fShowSwitching? Map_MappingGetSwitching(p) : p->fRequiredGlo, 
+                    0.0, p->AreaFinal, 
+                    100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase );
+ABC_PRT( "Time", Abc_Clock() - clk );
+}
+    }
+    p->timeArea += Abc_Clock() - clk;
+    //////////////////////////////////////////////////////////////////////
+
+    //////////////////////////////////////////////////////////////////////
+    // perform area recovery using exact area
+    clk = Abc_Clock();
+    if ( p->fSwitching )
+    {
+        // compute the required times
+        Map_TimeComputeRequiredGlobal( p );
+        // recover switching activity
+        p->fMappingMode = 4;
+        Map_MappingMatches( p );
+        // compute the references and collect the nodes used in the mapping
+        Map_MappingSetRefs( p );
+        p->AreaFinal = Map_MappingGetArea( p );
+if ( p->fVerbose )
+{
+printf( "Switching: %s = %8.2f  Flow = %11.1f  Area = %11.1f  %4.1f %%   ", 
+                    fShowSwitching? "Switch" : "Delay", 
+                    fShowSwitching? Map_MappingGetSwitching(p) : p->fRequiredGlo, 
+                    0.0, p->AreaFinal, 
+                    100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase );
+ABC_PRT( "Time", Abc_Clock() - clk );
+}
+
+        // compute the required times
+        Map_TimeComputeRequiredGlobal( p );
+        // recover switching activity
+        p->fMappingMode = 4;
+        Map_MappingMatches( p );
+        // compute the references and collect the nodes used in the mapping
+        Map_MappingSetRefs( p );
+        p->AreaFinal = Map_MappingGetArea( p );
+if ( p->fVerbose )
+{
+printf( "Switching: %s = %8.2f  Flow = %11.1f  Area = %11.1f  %4.1f %%   ", 
+                    fShowSwitching? "Switch" : "Delay", 
+                    fShowSwitching? Map_MappingGetSwitching(p) : p->fRequiredGlo, 
+                    0.0, p->AreaFinal, 
+                    100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase );
+ABC_PRT( "Time", Abc_Clock() - clk );
+}
+    }
+    p->timeArea += Abc_Clock() - clk;
+    //////////////////////////////////////////////////////////////////////
+
+    // print the arrival times of the latest outputs
+    if ( p->fVerbose )
+        Map_MappingPrintOutputArrivals( p );
+    return 1;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/mapperCreate.c b/abc-build/src/map/mapper/mapperCreate.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperCreate.c
@@ -0,0 +1,585 @@
+/**CFile****************************************************************
+
+  FileName    [mapperCreate.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapperCreate.c,v 1.15 2005/02/28 05:34:26 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void            Map_TableCreate( Map_Man_t * p );
+static void            Map_TableResize( Map_Man_t * p );
+
+// hash key for the structural hash table
+static inline unsigned Map_HashKey2( Map_Node_t * p0, Map_Node_t * p1, int TableSize ) { return (unsigned)(((ABC_PTRUINT_T)(p0) + (ABC_PTRUINT_T)(p1) * 12582917) % TableSize); }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reads parameters from the mapping manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int             Map_ManReadInputNum( Map_Man_t * p )                    { return p->nInputs;    }
+int             Map_ManReadOutputNum( Map_Man_t * p )                   { return p->nOutputs;   }
+int             Map_ManReadBufNum( Map_Man_t * p )                      { return Map_NodeVecReadSize(p->vMapBufs);   }
+Map_Node_t **   Map_ManReadInputs ( Map_Man_t * p )                     { return p->pInputs;    }
+Map_Node_t **   Map_ManReadOutputs( Map_Man_t * p )                     { return p->pOutputs;   }
+Map_Node_t **   Map_ManReadBufs( Map_Man_t * p )                        { return Map_NodeVecReadArray(p->vMapBufs);  }
+Map_Node_t *    Map_ManReadBufDriver( Map_Man_t * p, int i )            { return Map_ManReadBufs(p)[i]->p1;           }
+Map_Node_t *    Map_ManReadConst1 ( Map_Man_t * p )                     { return p->pConst1;    }
+Map_Time_t *    Map_ManReadInputArrivals( Map_Man_t * p )               { return p->pInputArrivals; }
+Map_Time_t *    Map_ManReadOutputRequireds( Map_Man_t * p )             { return p->pOutputRequireds; }
+Mio_Library_t * Map_ManReadGenLib ( Map_Man_t * p )                     { return p->pSuperLib->pGenlib; }
+int             Map_ManReadVerbose( Map_Man_t * p )                     { return p->fVerbose;   }
+float           Map_ManReadAreaFinal( Map_Man_t * p )                   { return p->AreaFinal;  }
+float           Map_ManReadRequiredGlo( Map_Man_t * p )                 { return p->fRequiredGlo; }
+void            Map_ManSetOutputNames( Map_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames;}
+void            Map_ManSetAreaRecovery( Map_Man_t * p, int fAreaRecovery ) { p->fAreaRecovery = fAreaRecovery;}
+void            Map_ManSetDelayTarget( Map_Man_t * p, float DelayTarget ) { p->DelayTarget = DelayTarget;}
+void            Map_ManSetInputArrivals( Map_Man_t * p, Map_Time_t * pArrivals )     { p->pInputArrivals = pArrivals;    }
+void            Map_ManSetOutputRequireds( Map_Man_t * p, Map_Time_t * pRequireds )  { p->pOutputRequireds = pRequireds; }
+void            Map_ManSetObeyFanoutLimits( Map_Man_t * p, int  fObeyFanoutLimits )  { p->fObeyFanoutLimits = fObeyFanoutLimits;     }
+void            Map_ManSetNumIterations( Map_Man_t * p, int nIterations )            { p->nIterations = nIterations;     }
+int             Map_ManReadFanoutViolations( Map_Man_t * p )            { return p->nFanoutViolations;   }  
+void            Map_ManSetFanoutViolations( Map_Man_t * p, int nVio )   { p->nFanoutViolations = nVio;   }  
+void            Map_ManSetChoiceNodeNum( Map_Man_t * p, int nChoiceNodes ) { p->nChoiceNodes = nChoiceNodes; }  
+void            Map_ManSetChoiceNum( Map_Man_t * p, int nChoices )         { p->nChoices = nChoices;     }   
+void            Map_ManSetVerbose( Map_Man_t * p, int fVerbose )           { p->fVerbose = fVerbose;     }   
+void            Map_ManSetSwitching( Map_Man_t * p, int fSwitching )       { p->fSwitching = fSwitching; }   
+
+/**Function*************************************************************
+
+  Synopsis    [Reads parameters from the mapping node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Man_t *     Map_NodeReadMan( Map_Node_t * p )                     { return p->p;                  }
+char *          Map_NodeReadData( Map_Node_t * p, int fPhase )        { return fPhase? p->pData1 : p->pData0;  }
+int             Map_NodeReadNum( Map_Node_t * p )                     { return p->Num;                }
+int             Map_NodeReadLevel( Map_Node_t * p )                   { return Map_Regular(p)->Level; }
+Map_Cut_t *     Map_NodeReadCuts( Map_Node_t * p )                    { return p->pCuts;              }
+Map_Cut_t *     Map_NodeReadCutBest( Map_Node_t * p, int fPhase )     { return p->pCutBest[fPhase];   }
+Map_Node_t *    Map_NodeReadOne( Map_Node_t * p )                     { return p->p1;                 }
+Map_Node_t *    Map_NodeReadTwo( Map_Node_t * p )                     { return p->p2;                 }
+void            Map_NodeSetData( Map_Node_t * p, int fPhase, char * pData ) { if (fPhase) p->pData1 = pData; else p->pData0 = pData; }
+void            Map_NodeSetNextE( Map_Node_t * p, Map_Node_t * pNextE )     { p->pNextE = pNextE;       }
+void            Map_NodeSetRepr( Map_Node_t * p, Map_Node_t * pRepr )       { p->pRepr = pRepr;         }
+void            Map_NodeSetSwitching( Map_Node_t * p, float Switching )     { p->Switching = Switching; }
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the type of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int             Map_NodeIsConst( Map_Node_t * p )    {  return (Map_Regular(p))->Num == -1;    }
+int             Map_NodeIsVar( Map_Node_t * p )      {  return (Map_Regular(p))->p1 == NULL && (Map_Regular(p))->Num >= 0; }
+int             Map_NodeIsBuf( Map_Node_t * p )      {  return (Map_Regular(p))->p1 != NULL && (Map_Regular(p))->p2 == NULL;  }
+int             Map_NodeIsAnd( Map_Node_t * p )      {  return (Map_Regular(p))->p1 != NULL && (Map_Regular(p))->p2 != NULL;  }
+int             Map_NodeComparePhase( Map_Node_t * p1, Map_Node_t * p2 ) { assert( !Map_IsComplement(p1) ); assert( !Map_IsComplement(p2) ); return p1->fInv ^ p2->fInv; }
+
+/**Function*************************************************************
+
+  Synopsis    [Reads parameters from the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Super_t *   Map_CutReadSuperBest( Map_Cut_t * p, int fPhase ) { return p->M[fPhase].pSuperBest;}
+Map_Super_t *   Map_CutReadSuper0( Map_Cut_t * p )                { return p->M[0].pSuperBest;}
+Map_Super_t *   Map_CutReadSuper1( Map_Cut_t * p )                { return p->M[1].pSuperBest;}
+int             Map_CutReadLeavesNum( Map_Cut_t * p )             { return p->nLeaves;  }
+Map_Node_t **   Map_CutReadLeaves( Map_Cut_t * p )                { return p->ppLeaves; }
+unsigned        Map_CutReadPhaseBest( Map_Cut_t * p, int fPhase ) { return p->M[fPhase].uPhaseBest;}
+unsigned        Map_CutReadPhase0( Map_Cut_t * p )                { return p->M[0].uPhaseBest;}
+unsigned        Map_CutReadPhase1( Map_Cut_t * p )                { return p->M[1].uPhaseBest;}
+Map_Cut_t *     Map_CutReadNext( Map_Cut_t * p )                  { return p->pNext;          }
+
+/**Function*************************************************************
+
+  Synopsis    [Reads parameters from the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char *          Map_SuperReadFormula( Map_Super_t * p )          {  return p->pFormula; }
+Mio_Gate_t *    Map_SuperReadRoot( Map_Super_t * p )             {  return p->pRoot;    }
+int             Map_SuperReadNum( Map_Super_t * p )              {  return p->Num;      }
+Map_Super_t **  Map_SuperReadFanins( Map_Super_t * p )           {  return p->pFanins;  }
+int             Map_SuperReadFaninNum( Map_Super_t * p )         {  return p->nFanins;  }
+Map_Super_t *   Map_SuperReadNext( Map_Super_t * p )             {  return p->pNext;    }
+int             Map_SuperReadNumPhases( Map_Super_t * p )        {  return p->nPhases;  }
+unsigned char * Map_SuperReadPhases( Map_Super_t * p )           {  return p->uPhases;  }
+int             Map_SuperReadFanoutLimit( Map_Super_t * p )      {  return p->nFanLimit;}
+
+Mio_Library_t * Map_SuperLibReadGenLib( Map_SuperLib_t * p )     {  return p->pGenlib;  }
+float           Map_SuperLibReadAreaInv( Map_SuperLib_t * p )    {  return p->AreaInv;  }
+Map_Time_t      Map_SuperLibReadDelayInv( Map_SuperLib_t * p )   {  return p->tDelayInv;}
+int             Map_SuperLibReadVarsMax( Map_SuperLib_t * p )    {  return p->nVarsMax; }
+
+
+/**Function*************************************************************
+
+  Synopsis    [Create the mapping manager.]
+
+  Description [The number of inputs and outputs is assumed to be
+  known is advance. It is much simpler to have them fixed upfront.
+  When it comes to representing the object graph in the form of
+  AIG, the resulting manager is similar to the regular AIG manager, 
+  except that it does not use reference counting (and therefore
+  does not have garbage collections). It does have table resizing.
+  The data structure is more flexible to represent additional 
+  information needed for mapping.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Man_t * Map_ManCreate( int nInputs, int nOutputs, int fVerbose )
+{
+    Map_Man_t * p;
+    int i;
+
+    // derive the supergate library
+    if ( Abc_FrameReadLibSuper() == NULL )
+    {
+        printf( "The supergate library is not specified. Use \"read_super\".\n" );
+        return NULL;
+    }
+
+    // start the manager
+    p = ABC_ALLOC( Map_Man_t, 1 );
+    memset( p, 0, sizeof(Map_Man_t) );
+    p->pSuperLib = (Map_SuperLib_t *)Abc_FrameReadLibSuper();
+    p->nVarsMax  = p->pSuperLib->nVarsMax;
+    p->fVerbose  = fVerbose;
+    p->fEpsilon  = (float)0.001;
+    assert( p->nVarsMax > 0 );
+
+    if ( p->nVarsMax == 5 )
+        Extra_Truth4VarN( &p->uCanons, &p->uPhases, &p->pCounters, 8 );
+
+    // start various data structures
+    Map_TableCreate( p );
+    Map_MappingSetupTruthTables( p->uTruths );
+    Map_MappingSetupTruthTablesLarge( p->uTruthsLarge );
+//    printf( "Node = %d bytes. Cut = %d bytes. Super = %d bytes.\n", sizeof(Map_Node_t), sizeof(Map_Cut_t), sizeof(Map_Super_t) ); 
+    p->mmNodes    = Extra_MmFixedStart( sizeof(Map_Node_t) );
+    p->mmCuts     = Extra_MmFixedStart( sizeof(Map_Cut_t) );
+
+    // make sure the constant node will get index -1
+    p->nNodes = -1;
+    // create the constant node
+    p->pConst1    = Map_NodeCreate( p, NULL, NULL );
+    p->vMapObjs   = Map_NodeVecAlloc( 100 );
+    p->vMapBufs   = Map_NodeVecAlloc( 100 );
+    p->vVisited   = Map_NodeVecAlloc( 100 );
+
+    // create the PI nodes
+    p->nInputs = nInputs;
+    p->pInputs = ABC_ALLOC( Map_Node_t *, nInputs );
+    for ( i = 0; i < nInputs; i++ )
+        p->pInputs[i] = Map_NodeCreate( p, NULL, NULL );
+
+    // create the place for the output nodes
+    p->nOutputs = nOutputs;
+    p->pOutputs = ABC_ALLOC( Map_Node_t *, nOutputs );
+    memset( p->pOutputs, 0, sizeof(Map_Node_t *) * nOutputs );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the mapping manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_ManFree( Map_Man_t * p )
+{
+//    int i;
+//    for ( i = 0; i < p->vMapObjs->nSize; i++ )
+//        Map_NodeVecFree( p->vMapObjs->pArray[i]->vFanouts );
+//    Map_NodeVecFree( p->pConst1->vFanouts );
+    Map_NodeVecFree( p->vMapObjs );
+    Map_NodeVecFree( p->vMapBufs );
+    Map_NodeVecFree( p->vVisited );
+    if ( p->uCanons )   ABC_FREE( p->uCanons );
+    if ( p->uPhases )   ABC_FREE( p->uPhases );
+    if ( p->pCounters ) ABC_FREE( p->pCounters );
+    Extra_MmFixedStop( p->mmNodes );
+    Extra_MmFixedStop( p->mmCuts );
+    ABC_FREE( p->pNodeDelays );
+    ABC_FREE( p->pInputArrivals );
+    ABC_FREE( p->pOutputRequireds );
+    ABC_FREE( p->pInputs );
+    ABC_FREE( p->pOutputs );
+    ABC_FREE( p->pBins );
+    ABC_FREE( p->ppOutputNames );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates node delays.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_ManCreateNodeDelays( Map_Man_t * p, int LogFan )
+{
+    Map_Node_t * pNode;
+    int k;
+    assert( p->pNodeDelays == NULL );
+    p->pNodeDelays = ABC_CALLOC( float, p->vMapObjs->nSize );
+    for ( k = 0; k < p->vMapObjs->nSize; k++ )
+    {
+        pNode = p->vMapObjs->pArray[k];
+        if ( pNode->nRefs == 0 )
+            continue;
+        p->pNodeDelays[k] = 0.014426 * LogFan * p->pSuperLib->tDelayInv.Worst * log( (double)pNode->nRefs ); // 1.4426 = 1/ln(2)
+//        printf( "%d = %d (%.2f)  ", k, pNode->nRefs, p->pNodeDelays[k] );
+    }
+//    printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the mapping manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_ManPrintTimeStats( Map_Man_t * p )
+{
+    printf( "N-canonical = %d. Matchings = %d.  Phases = %d.  ", p->nCanons, p->nMatches, p->nPhases );
+    printf( "Choice nodes = %d. Choices = %d.\n", p->nChoiceNodes, p->nChoices );
+    ABC_PRT( "ToMap", p->timeToMap );
+    ABC_PRT( "Cuts ", p->timeCuts  );
+    ABC_PRT( "Truth", p->timeTruth );
+    ABC_PRT( "Match", p->timeMatch );
+    ABC_PRT( "Area ", p->timeArea  );
+    ABC_PRT( "Sweep", p->timeSweep );
+    ABC_PRT( "ToNet", p->timeToNet );
+    ABC_PRT( "TOTAL", p->timeTotal );
+    if ( p->time1 ) { ABC_PRT( "time1", p->time1 ); }
+    if ( p->time2 ) { ABC_PRT( "time2", p->time2 ); }
+    if ( p->time3 ) { ABC_PRT( "time3", p->time3 ); }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the mapping stats.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_ManPrintStatsToFile( char * pName, float Area, float Delay, abctime Time )
+{
+    FILE * pTable;
+    pTable = fopen( "map_stats.txt", "a+" );
+    fprintf( pTable, "%s ", pName );
+    fprintf( pTable, "%4.2f ", Area );
+    fprintf( pTable, "%4.2f ", Delay );
+    fprintf( pTable, "%4.2f\n", (float)(Time)/(float)(CLOCKS_PER_SEC) );
+    fclose( pTable );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new node.]
+
+  Description [This procedure should be called to create the constant
+  node and the PI nodes first.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Node_t * Map_NodeCreate( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 )
+{
+    Map_Node_t * pNode;
+    // create the node
+    pNode = (Map_Node_t *)Extra_MmFixedEntryFetch( p->mmNodes );
+    memset( pNode, 0, sizeof(Map_Node_t) );
+    pNode->tRequired[0].Rise = pNode->tRequired[0].Fall = pNode->tRequired[0].Worst = MAP_FLOAT_LARGE;
+    pNode->tRequired[1].Rise = pNode->tRequired[1].Fall = pNode->tRequired[1].Worst = MAP_FLOAT_LARGE;
+    pNode->p1  = p1; 
+    pNode->p2  = p2;
+    pNode->p = p;
+    // set the number of this node
+    pNode->Num = p->nNodes++;
+    // place to store the fanouts
+//    pNode->vFanouts = Map_NodeVecAlloc( 5 );
+    // store this node in the internal array
+    if ( pNode->Num >= 0 )
+        Map_NodeVecPush( p->vMapObjs, pNode );
+    else
+        pNode->fInv = 1;
+    // set the level of this node
+    if ( p1 ) 
+    {
+#ifdef MAP_ALLOCATE_FANOUT
+        // create the fanout info
+        Map_NodeAddFaninFanout( Map_Regular(p1), pNode );
+        if ( p2 )
+        Map_NodeAddFaninFanout( Map_Regular(p2), pNode );
+#endif
+
+        if ( p2 )
+        {
+            pNode->Level = 1 + MAP_MAX(Map_Regular(pNode->p1)->Level, Map_Regular(pNode->p2)->Level);
+            pNode->fInv  = Map_NodeIsSimComplement(p1) & Map_NodeIsSimComplement(p2);
+        }
+        else
+        {
+            pNode->Level = Map_Regular(pNode->p1)->Level;
+            pNode->fInv  = Map_NodeIsSimComplement(p1);
+        }
+    }
+    // reference the inputs (will be used to compute the number of fanouts)
+    if ( p1 ) Map_NodeRef(p1);
+    if ( p2 ) Map_NodeRef(p2);
+
+    pNode->nRefEst[0] = pNode->nRefEst[1] = -1;
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create the unique table of AND gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_TableCreate( Map_Man_t * pMan )
+{
+    assert( pMan->pBins == NULL );
+    pMan->nBins = Abc_PrimeCudd(5000);
+    pMan->pBins = ABC_ALLOC( Map_Node_t *, pMan->nBins );
+    memset( pMan->pBins, 0, sizeof(Map_Node_t *) * pMan->nBins );
+    pMan->nNodes = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Looks up the AND2 node in the unique table.]
+
+  Description [This procedure implements one-level hashing. All the nodes
+  are hashed by their children. If the node with the same children was already
+  created, it is returned by the call to this procedure. If it does not exist,
+  this procedure creates a new node with these children. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Node_t * Map_NodeAnd( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2 )
+{
+    Map_Node_t * pEnt;
+    unsigned Key;
+
+    if ( p1 == p2 )
+        return p1;
+    if ( p1 == Map_Not(p2) )
+        return Map_Not(pMan->pConst1);
+    if ( Map_NodeIsConst(p1) )
+    {
+        if ( p1 == pMan->pConst1 )
+            return p2;
+        return Map_Not(pMan->pConst1);
+    }
+    if ( Map_NodeIsConst(p2) )
+    {
+        if ( p2 == pMan->pConst1 )
+            return p1;
+        return Map_Not(pMan->pConst1);
+    }
+
+    if ( Map_Regular(p1)->Num > Map_Regular(p2)->Num )
+        pEnt = p1, p1 = p2, p2 = pEnt;
+
+    Key = Map_HashKey2( p1, p2, pMan->nBins );
+    for ( pEnt = pMan->pBins[Key]; pEnt; pEnt = pEnt->pNext )
+        if ( pEnt->p1 == p1 && pEnt->p2 == p2 )
+            return pEnt;
+    // resize the table
+    if ( pMan->nNodes >= 2 * pMan->nBins )
+    {
+        Map_TableResize( pMan );
+        Key = Map_HashKey2( p1, p2, pMan->nBins );
+    }
+    // create the new node
+    pEnt = Map_NodeCreate( pMan, p1, p2 );
+    // add the node to the corresponding linked list in the table
+    pEnt->pNext = pMan->pBins[Key];
+    pMan->pBins[Key] = pEnt;
+    return pEnt;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_TableResize( Map_Man_t * pMan )
+{
+    Map_Node_t ** pBinsNew;
+    Map_Node_t * pEnt, * pEnt2;
+    int nBinsNew, Counter, i;
+    abctime clk;
+    unsigned Key;
+
+clk = Abc_Clock();
+    // get the new table size
+    nBinsNew = Abc_PrimeCudd(2 * pMan->nBins); 
+    // allocate a new array
+    pBinsNew = ABC_ALLOC( Map_Node_t *, nBinsNew );
+    memset( pBinsNew, 0, sizeof(Map_Node_t *) * nBinsNew );
+    // rehash the entries from the old table
+    Counter = 0;
+    for ( i = 0; i < pMan->nBins; i++ )
+        for ( pEnt = pMan->pBins[i], pEnt2 = pEnt? pEnt->pNext: NULL; pEnt; 
+              pEnt = pEnt2, pEnt2 = pEnt? pEnt->pNext: NULL )
+        {
+            Key = Map_HashKey2( pEnt->p1, pEnt->p2, nBinsNew );
+            pEnt->pNext = pBinsNew[Key];
+            pBinsNew[Key] = pEnt;
+            Counter++;
+        }
+    assert( Counter == pMan->nNodes - pMan->nInputs );
+    if ( pMan->fVerbose )
+    {
+//        printf( "Increasing the unique table size from %6d to %6d. ", pMan->nBins, nBinsNew );
+//        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    // replace the table and the parameters
+    ABC_FREE( pMan->pBins );
+    pMan->pBins = pBinsNew;
+    pMan->nBins = nBinsNew;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Node_t * Map_NodeBuf( Map_Man_t * p, Map_Node_t * p1 )
+{
+    Map_Node_t * pNode = Map_NodeCreate( p, p1, NULL );
+    Map_NodeVecPush( p->vMapBufs, pNode );
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the node to be equivalent to the given one.]
+
+  Description [This procedure is a work-around for the equivalence check.
+  Does not verify the equivalence. Use at the user's risk.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_NodeSetChoice( Map_Man_t * pMan, Map_Node_t * pNodeOld, Map_Node_t * pNodeNew )
+{
+    pNodeNew->pNextE = pNodeOld->pNextE;
+    pNodeOld->pNextE = pNodeNew;
+    pNodeNew->pRepr  = pNodeOld;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/mapperCut.c b/abc-build/src/map/mapper/mapperCut.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperCut.c
@@ -0,0 +1,1178 @@
+/**CFile****************************************************************
+
+  FileName    [mapperCut.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapperCut.c,v 1.12 2005/02/28 05:34:27 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// the largest number of cuts considered
+#define  MAP_CUTS_MAX_COMPUTE   1000
+// the largest number of cuts used
+#define  MAP_CUTS_MAX_USE       250
+
+// temporary hash table to store the cuts
+typedef struct Map_CutTableStrutct_t Map_CutTable_t;
+struct Map_CutTableStrutct_t
+{
+    Map_Cut_t ** pBins;        // the table used for linear probing
+    int          nBins;        // the size of the table
+    int *        pCuts;        // the array of cuts currently stored 
+    int          nCuts;        // the number of cuts currently stored 
+    Map_Cut_t ** pArray;       // the temporary array of cuts
+    Map_Cut_t ** pCuts1;       // the temporary array of cuts
+    Map_Cut_t ** pCuts2;       // the temporary array of cuts
+};
+
+// primes used to compute the hash key
+static int s_HashPrimes[10] = { 109, 499, 557, 619, 631, 709, 797, 881, 907, 991 };
+
+static Map_Cut_t *      Map_CutCompute( Map_Man_t * p, Map_CutTable_t * pTable, Map_Node_t * pNode );
+static void             Map_CutFilter( Map_Man_t * p, Map_Node_t * pNode );
+static Map_Cut_t *      Map_CutMergeLists( Map_Man_t * p, Map_CutTable_t * pTable, Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 );
+static int              Map_CutMergeTwo( Map_Cut_t * pCut1, Map_Cut_t * pCut2, Map_Node_t * ppNodes[], int nNodesMax );
+static Map_Cut_t *      Map_CutUnionLists( Map_Cut_t * pList1, Map_Cut_t * pList2 );
+static int              Map_CutBelongsToList( Map_Cut_t * pList, Map_Node_t * ppNodes[], int nNodes );
+
+static void             Map_CutListPrint( Map_Man_t * pMan, Map_Node_t * pRoot );
+static void             Map_CutListPrint2( Map_Man_t * pMan, Map_Node_t * pRoot );
+static void             Map_CutPrint_( Map_Man_t * pMan, Map_Cut_t * pCut, Map_Node_t * pRoot );
+
+static Map_CutTable_t * Map_CutTableStart( Map_Man_t * pMan );
+static void             Map_CutTableStop( Map_CutTable_t * p );
+static unsigned         Map_CutTableHash( Map_Node_t * ppNodes[], int nNodes );
+static int              Map_CutTableLookup( Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes );
+static Map_Cut_t *      Map_CutTableConsider( Map_Man_t * pMan, Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes );
+static void             Map_CutTableRestart( Map_CutTable_t * p );
+
+static Map_Cut_t *      Map_CutSortCuts( Map_Man_t * pMan, Map_CutTable_t * p, Map_Cut_t * pList );
+static int              Map_CutList2Array( Map_Cut_t ** pArray, Map_Cut_t * pList );
+static Map_Cut_t *      Map_CutArray2List( Map_Cut_t ** pArray, int nCuts );
+
+static unsigned         Map_CutComputeTruth( Map_Man_t * p, Map_Cut_t * pCut, Map_Cut_t * pTemp0, Map_Cut_t * pTemp1, int fComp0, int fComp1 );
+
+// iterator through all the cuts of the list
+#define Map_ListForEachCut( pList, pCut )                 \
+    for ( pCut = pList;                                   \
+          pCut;                                           \
+          pCut = pCut->pNext )
+#define Map_ListForEachCutSafe( pList, pCut, pCut2 )      \
+    for ( pCut = pList,                                   \
+          pCut2 = pCut? pCut->pNext: NULL;                \
+          pCut;                                           \
+          pCut = pCut2,                                   \
+          pCut2 = pCut? pCut->pNext: NULL )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Counts all the cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_MappingCountAllCuts( Map_Man_t * pMan )
+{
+    Map_Node_t * pNode;
+    Map_Cut_t * pCut;
+    int i, nCuts;
+//    int nCuts55 = 0, nCuts5x = 0, nCuts4x = 0, nCuts3x = 0;
+//    int pCounts[7] = {0};
+    nCuts = 0;
+    for ( i = 0; i < pMan->nBins; i++ )
+        for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext )
+            for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext )
+                if ( pCut->nLeaves > 1 ) // skip the elementary cuts
+                {
+                    nCuts++;
+/*
+                    if ( Map_CutRegular(pCut->pOne)->nLeaves == 5 && Map_CutRegular(pCut->pTwo)->nLeaves == 5 )
+                        nCuts55++;
+                    if ( Map_CutRegular(pCut->pOne)->nLeaves == 5 || Map_CutRegular(pCut->pTwo)->nLeaves == 5 )
+                        nCuts5x++;
+                    else if ( Map_CutRegular(pCut->pOne)->nLeaves == 4 || Map_CutRegular(pCut->pTwo)->nLeaves == 4 )
+                        nCuts4x++;
+                    else if ( Map_CutRegular(pCut->pOne)->nLeaves == 3 || Map_CutRegular(pCut->pTwo)->nLeaves == 3 )
+                        nCuts3x++;
+*/                  
+//                    pCounts[ Map_CutRegular(pCut->pOne)->nLeaves ]++;
+//                    pCounts[ Map_CutRegular(pCut->pTwo)->nLeaves ]++;
+                }
+//    printf( "Total cuts = %6d. 55 = %6d. 5x = %6d. 4x = %6d. 3x = %6d.\n", nCuts, nCuts55, nCuts5x, nCuts4x, nCuts3x );
+
+//    printf( "Total cuts = %6d. 6= %6d. 5= %6d. 4= %6d. 3= %6d. 2= %6d. 1= %6d.\n", 
+//        nCuts, pCounts[6], pCounts[5], pCounts[4], pCounts[3], pCounts[2], pCounts[1] );
+    return nCuts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for each node in the object graph.]
+
+  Description [The cuts are computed in one sweep over the mapping graph. 
+  First, the elementary cuts, which include the node itself, are assigned 
+  to the PI nodes. The internal nodes are considered in the DFS order.
+  Each node is two-input AND-gate. So to compute the cuts at a node, we
+  need to merge the sets of cuts of its two predecessors. The merged set
+  contains only unique cuts with the number of inputs equal to k or less.
+  Finally, the elementary cut, composed of the node itself, is added to
+  the set of cuts for the node.
+  
+  This procedure is pretty fast for 5-feasible cuts, but it dramatically
+  slows down on some "dense" networks when computing 6-feasible cuts.
+  The problem is that there are too many cuts in this case. We should
+  think how to heuristically trim the number of cuts in such cases, 
+  to have reasonable runtime.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingCutsInput( Map_Man_t * p, Map_Node_t * pNode )
+{
+    Map_Cut_t * pCut;
+    assert( Map_NodeIsVar(pNode) || Map_NodeIsBuf(pNode) );
+    pCut = Map_CutAlloc( p );
+    pCut->nLeaves = 1;
+    pCut->ppLeaves[0] = pNode;
+    pNode->pCuts   = pCut;
+    pNode->pCutBest[0] = NULL; // negative polarity is not mapped
+    pNode->pCutBest[1] = pCut; // positive polarity is a trivial cut
+    pCut->uTruth = 0xAAAAAAAA; // the first variable "1010"
+    pCut->M[0].AreaFlow = 0.0;
+    pCut->M[1].AreaFlow = 0.0;
+}
+void Map_MappingCuts( Map_Man_t * p )
+{
+    ProgressBar * pProgress;
+    Map_CutTable_t * pTable;
+    Map_Node_t * pNode;
+    int nCuts, nNodes, i;
+    abctime clk = Abc_Clock();
+    // set the elementary cuts for the PI variables
+    assert( p->nVarsMax > 1 && p->nVarsMax < 7 );
+    for ( i = 0; i < p->nInputs; i++ )
+        Map_MappingCutsInput( p, p->pInputs[i] );
+
+    // compute the cuts for the internal nodes
+    nNodes = p->vMapObjs->nSize;
+    pProgress = Extra_ProgressBarStart( stdout, nNodes );
+    pTable = Map_CutTableStart( p );
+    for ( i = 0; i < nNodes; i++ )
+    {
+        pNode = p->vMapObjs->pArray[i];
+        if ( Map_NodeIsBuf(pNode) )
+            Map_MappingCutsInput( p, pNode );
+        else if ( Map_NodeIsAnd(pNode) )
+            Map_CutCompute( p, pTable, pNode );
+        else continue;
+        Extra_ProgressBarUpdate( pProgress, i, "Cuts ..." );
+    }
+    Extra_ProgressBarStop( pProgress );
+    Map_CutTableStop( pTable );
+
+    // report the stats
+    if ( p->fVerbose )
+    {
+        nCuts = Map_MappingCountAllCuts(p);
+        printf( "Nodes = %6d.  Total %d-feasible cuts = %10d.  Per node = %.1f. ", 
+               p->nNodes, p->nVarsMax, nCuts, ((float)nCuts)/p->nNodes );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+
+    // print the cuts for the first primary output
+//    Map_CutListPrint( p, Map_Regular(p->pOutputs[0]) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Cut_t * Map_CutCompute( Map_Man_t * p, Map_CutTable_t * pTable, Map_Node_t * pNode )
+{
+    Map_Node_t * pTemp;
+    Map_Cut_t * pList, * pList1, * pList2;
+    Map_Cut_t * pCut;
+
+    // if the cuts are computed return them
+    if ( pNode->pCuts )
+        return pNode->pCuts;
+
+    // compute the cuts for the children
+    pList1 = Map_Regular(pNode->p1)->pCuts;
+    pList2 = Map_Regular(pNode->p2)->pCuts;
+    // merge the lists
+    pList = Map_CutMergeLists( p, pTable, pList1, pList2, 
+        Map_IsComplement(pNode->p1), Map_IsComplement(pNode->p2) );
+    // if there are functionally equivalent nodes, union them with this list
+    assert( pList );
+    // only add to the list of cuts if the node is a representative one
+    if ( pNode->pRepr == NULL )
+    {
+        for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE )
+        {
+            assert( pTemp->pCuts );
+            pList = Map_CutUnionLists( pList, pTemp->pCuts );
+            assert( pTemp->pCuts );
+            pList = Map_CutSortCuts( p, pTable, pList );
+        }
+    }
+    // add the new cut
+    pCut = Map_CutAlloc( p );
+    pCut->nLeaves = 1;
+    pCut->ppLeaves[0] = pNode;
+    pCut->uTruth = 0xAAAAAAAA;
+    // append (it is important that the elementary cut is appended first)
+    pCut->pNext = pList;
+    // set at the node
+    pNode->pCuts = pCut;
+    // remove the dominated cuts
+    Map_CutFilter( p, pNode );
+    // set the phase correctly
+    if ( pNode->pRepr && Map_NodeComparePhase(pNode, pNode->pRepr) )
+    {
+        Map_ListForEachCut( pNode->pCuts, pCut )
+            pCut->Phase = 1;
+    }
+/*
+    { 
+        int i, Counter = 0;;
+        for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+            for ( i = 0; i < pCut->nLeaves; i++ )
+                Counter += (pCut->ppLeaves[i]->Level >= pNode->Level);
+//        if ( Counter )
+//            printf( " %d", Counter );
+    }
+*/
+    return pCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Filter the cuts using dominance.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_CutFilter( Map_Man_t * p, Map_Node_t * pNode )
+{ 
+    Map_Cut_t * pTemp, * pPrev, * pCut, * pCut2;
+    int i, k, Counter;
+
+    Counter = 0;
+    pPrev = pNode->pCuts;
+    Map_ListForEachCutSafe( pNode->pCuts->pNext, pCut, pCut2 )
+    {
+        // go through all the previous cuts up to pCut
+        for ( pTemp = pNode->pCuts->pNext; pTemp != pCut; pTemp = pTemp->pNext )
+        {
+            // check if every node in pTemp is contained in pCut
+            for ( i = 0; i < pTemp->nLeaves; i++ )
+            {
+                for ( k = 0; k < pCut->nLeaves; k++ )
+                    if ( pTemp->ppLeaves[i] == pCut->ppLeaves[k] )
+                        break;
+                if ( k == pCut->nLeaves ) // node i in pTemp is not contained in pCut
+                    break;
+            }
+            if ( i == pTemp->nLeaves ) // every node in pTemp is contained in pCut
+            {
+                Counter++;
+                break;
+            }
+        }
+        if ( pTemp != pCut ) // pTemp contain pCut
+        {
+            pPrev->pNext = pCut->pNext;  // skip pCut
+            // recycle pCut
+            Map_CutFree( p, pCut );
+        }
+        else 
+            pPrev = pCut; 
+    }
+//  printf( "Dominated = %3d. \n", Counter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two lists of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Cut_t * Map_CutMergeLists( Map_Man_t * p, Map_CutTable_t * pTable, 
+    Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 )
+{
+    Map_Node_t * ppNodes[6];
+    Map_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL };
+    Map_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2;
+    int nNodes, Counter, i;
+    Map_Cut_t ** ppArray1, ** ppArray2, ** ppArray3;
+    int nCuts1, nCuts2, nCuts3, k, fComp3;
+
+    ppArray1 = pTable->pCuts1;
+    ppArray2 = pTable->pCuts2;
+    nCuts1 = Map_CutList2Array( ppArray1, pList1 );
+    nCuts2 = Map_CutList2Array( ppArray2, pList2 );
+    // swap the lists based on their length
+    if ( nCuts1 > nCuts2 )
+    {
+         ppArray3 = ppArray1;
+         ppArray1 = ppArray2;
+         ppArray2 = ppArray3;
+
+         nCuts3 = nCuts1;
+         nCuts1 = nCuts2;
+         nCuts2 = nCuts3;
+
+         fComp3 = fComp1;
+         fComp1 = fComp2;
+         fComp2 = fComp3;
+    }
+    // pList1 is shorter or equal length compared to pList2
+ 
+    // prepare the manager for the cut computation
+    Map_CutTableRestart( pTable );
+    // go through the cut pairs
+    Counter = 0;
+//    for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext )
+//        for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext )
+    for ( i = 0; i < nCuts1; i++ )
+    {
+        for ( k = 0; k <= i; k++ )
+        {
+            pTemp1 = ppArray1[i];
+            pTemp2 = ppArray2[k];
+
+            if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax )
+            {
+                if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] )
+                    continue;
+                if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] )
+                    continue;
+            }
+
+            // check if k-feasible cut exists
+            nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
+            if ( nNodes == 0 )
+                continue;
+            // consider the cut for possible addition to the set of new cuts
+            pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes );
+            if ( pCut == NULL )
+                continue;
+            // add data to the cut
+            pCut->pOne = Map_CutNotCond( pTemp1, fComp1 );
+            pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 );
+//            if ( p->nVarsMax == 5 )
+//            pCut->uTruth = Map_CutComputeTruth( p, pCut, pTemp1, pTemp2, fComp1, fComp2 );
+            // add it to the corresponding list
+            pCut->pNext = pLists[(int)pCut->nLeaves];
+            pLists[(int)pCut->nLeaves] = pCut;
+            // count this cut and quit if limit is reached
+            Counter++;
+            if ( Counter == MAP_CUTS_MAX_COMPUTE )
+                goto QUITS;
+        }
+        for ( k = 0; k < i; k++ )
+        {
+            pTemp1 = ppArray1[k];
+            pTemp2 = ppArray2[i];
+
+            if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax )
+            {
+                if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] )
+                    continue;
+                if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] )
+                    continue;
+            }
+
+            // check if k-feasible cut exists
+            nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
+            if ( nNodes == 0 )
+                continue;
+            // consider the cut for possible addition to the set of new cuts
+            pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes );
+            if ( pCut == NULL )
+                continue;
+            // add data to the cut
+            pCut->pOne = Map_CutNotCond( pTemp1, fComp1 );
+            pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 );
+//            if ( p->nVarsMax == 5 )
+//            pCut->uTruth = Map_CutComputeTruth( p, pCut, pTemp1, pTemp2, fComp1, fComp2 );
+            // add it to the corresponding list
+            pCut->pNext = pLists[(int)pCut->nLeaves];
+            pLists[(int)pCut->nLeaves] = pCut;
+            // count this cut and quit if limit is reached
+            Counter++;
+            if ( Counter == MAP_CUTS_MAX_COMPUTE )
+                goto QUITS;
+        }
+    }
+    // consider the rest of them
+    for ( i = nCuts1; i < nCuts2; i++ )
+        for ( k = 0; k < nCuts1; k++ )
+        {
+            pTemp1 = ppArray1[k];
+            pTemp2 = ppArray2[i];
+
+            if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax )
+            {
+                if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] )
+                    continue;
+                if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] )
+                    continue;
+            }
+
+            // check if k-feasible cut exists
+            nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
+            if ( nNodes == 0 )
+                continue;
+            // consider the cut for possible addition to the set of new cuts
+            pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes );
+            if ( pCut == NULL )
+                continue;
+            // add data to the cut
+            pCut->pOne = Map_CutNotCond( pTemp1, fComp1 );
+            pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 );
+//            if ( p->nVarsMax == 5 )
+//            pCut->uTruth = Map_CutComputeTruth( p, pCut, pTemp1, pTemp2, fComp1, fComp2 );
+            // add it to the corresponding list
+            pCut->pNext = pLists[(int)pCut->nLeaves];
+            pLists[(int)pCut->nLeaves] = pCut;
+            // count this cut and quit if limit is reached
+            Counter++;
+            if ( Counter == MAP_CUTS_MAX_COMPUTE )
+                goto QUITS;
+        }
+QUITS :
+    // combine all the lists into one
+    pListNew  = NULL;
+    ppListNew = &pListNew;
+    for ( i = 1; i <= p->nVarsMax; i++ )
+    {
+        if ( pLists[i] == NULL )
+            continue;
+        // find the last entry
+        for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; 
+            pPrev = pCut, pCut = pCut->pNext );
+        // connect these lists
+        *ppListNew = pLists[i];
+        ppListNew  = &pPrev->pNext;
+    }
+    *ppListNew = NULL;
+    // soft the cuts by arrival times and use only the first MAP_CUTS_MAX_USE
+    pListNew = Map_CutSortCuts( p, pTable, pListNew );
+    return pListNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two lists of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Cut_t * Map_CutMergeLists2( Map_Man_t * p, Map_CutTable_t * pTable, 
+    Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 )
+{
+    Map_Node_t * ppNodes[6];
+    Map_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL };
+    Map_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2;
+    int nNodes, Counter, i;
+
+    // prepare the manager for the cut computation
+    Map_CutTableRestart( pTable );
+    // go through the cut pairs
+    Counter = 0;
+    for ( pTemp1 = pList1; pTemp1; pTemp1 = pTemp1->pNext )
+        for ( pTemp2 = pList2; pTemp2; pTemp2 = pTemp2->pNext )
+        {
+            // check if k-feasible cut exists
+            nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
+            if ( nNodes == 0 )
+                continue;
+            // consider the cut for possible addition to the set of new cuts
+            pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes );
+            if ( pCut == NULL )
+                continue;
+            // add data to the cut
+            pCut->pOne = Map_CutNotCond( pTemp1, fComp1 );
+            pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 );
+            // add it to the corresponding list
+            pCut->pNext = pLists[(int)pCut->nLeaves];
+            pLists[(int)pCut->nLeaves] = pCut;
+            // count this cut and quit if limit is reached
+            Counter++;
+            if ( Counter == MAP_CUTS_MAX_COMPUTE )
+                goto QUITS;
+        }
+QUITS :
+    // combine all the lists into one
+    pListNew  = NULL;
+    ppListNew = &pListNew;
+    for ( i = 1; i <= p->nVarsMax; i++ )
+    {
+        if ( pLists[i] == NULL )
+            continue;
+        // find the last entry
+        for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; 
+            pPrev = pCut, pCut = pCut->pNext );
+        // connect these lists
+        *ppListNew = pLists[i];
+        ppListNew  = &pPrev->pNext;
+    }
+    *ppListNew = NULL;
+    // soft the cuts by arrival times and use only the first MAP_CUTS_MAX_USE
+    pListNew = Map_CutSortCuts( p, pTable, pListNew );
+    return pListNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two cuts.]
+
+  Description [Returns the number of nodes in the resulting cut, or 0 if the
+  cut is infeasible. Returns the resulting nodes in the array ppNodes[].]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_CutMergeTwo( Map_Cut_t * pCut1, Map_Cut_t * pCut2, Map_Node_t * ppNodes[], int nNodesMax )
+{
+    Map_Node_t * pNodeTemp;
+    int nTotal, i, k, min, fMismatch;
+
+    // check the special case when at least of the cuts is the largest
+    if ( pCut1->nLeaves == nNodesMax )
+    {
+        if ( pCut2->nLeaves == nNodesMax )
+        {
+            // return 0 if the cuts are different
+            for ( i = 0; i < nNodesMax; i++ )
+                if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i] )
+                    return 0;
+            // return nNodesMax if they are the same
+            for ( i = 0; i < nNodesMax; i++ )
+                ppNodes[i] = pCut1->ppLeaves[i];
+            return nNodesMax;
+        }
+        else if ( pCut2->nLeaves == nNodesMax - 1 ) 
+        {
+            // return 0 if the cuts are different
+            fMismatch = 0;
+            for ( i = 0; i < nNodesMax; i++ )
+                if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i - fMismatch] )
+                {
+                    if ( fMismatch == 1 )
+                        return 0;
+                    fMismatch = 1;
+                }
+            // return nNodesMax if they are the same
+            for ( i = 0; i < nNodesMax; i++ )
+                ppNodes[i] = pCut1->ppLeaves[i];
+            return nNodesMax;
+        }
+    }
+    else if ( pCut1->nLeaves == nNodesMax - 1 && pCut2->nLeaves == nNodesMax )
+    {
+        // return 0 if the cuts are different
+        fMismatch = 0;
+        for ( i = 0; i < nNodesMax; i++ )
+            if ( pCut1->ppLeaves[i - fMismatch] != pCut2->ppLeaves[i] )
+            {
+                if ( fMismatch == 1 )
+                    return 0;
+                fMismatch = 1;
+            }
+        // return nNodesMax if they are the same
+        for ( i = 0; i < nNodesMax; i++ )
+            ppNodes[i] = pCut2->ppLeaves[i];
+        return nNodesMax;
+    }
+
+    // count the number of unique entries in pCut2
+    nTotal = pCut1->nLeaves;
+    for ( i = 0; i < pCut2->nLeaves; i++ )
+    {
+        // try to find this entry among the leaves of pCut1
+        for ( k = 0; k < pCut1->nLeaves; k++ )
+            if ( pCut2->ppLeaves[i] == pCut1->ppLeaves[k] )
+                break;
+        if ( k < pCut1->nLeaves ) // found
+            continue;
+        // we found a new entry to add
+        if ( nTotal == nNodesMax )
+            return 0;
+        ppNodes[nTotal++] = pCut2->ppLeaves[i];
+    }
+    // we know that the feasible cut exists
+
+    // add the starting entries
+    for ( k = 0; k < pCut1->nLeaves; k++ )
+        ppNodes[k] = pCut1->ppLeaves[k];
+
+    // selection-sort the entries
+    for ( i = 0; i < nTotal - 1; i++ )
+    {
+        min = i;
+        for ( k = i+1; k < nTotal; k++ )
+//            if ( ppNodes[k] < ppNodes[min] ) // reported bug fix (non-determinism!)
+            if ( ppNodes[k]->Num < ppNodes[min]->Num )
+                min = k;
+        pNodeTemp    = ppNodes[i];
+        ppNodes[i]   = ppNodes[min];
+        ppNodes[min] = pNodeTemp;
+    }
+
+    return nTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the union of the two lists of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Cut_t * Map_CutUnionLists( Map_Cut_t * pList1, Map_Cut_t * pList2 )
+{
+    Map_Cut_t * pTemp, * pRoot;
+    // find the last cut in the first list
+    pRoot = pList1;
+    Map_ListForEachCut( pList1, pTemp )
+        pRoot = pTemp;
+    // attach the non-trival part of the second cut to the end of the first
+    assert( pRoot->pNext == NULL );
+    pRoot->pNext = pList2->pNext;   
+    pList2->pNext = NULL;
+    return pList1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks whether the given cut belongs to the list.]
+
+  Description [This procedure takes most of the runtime in the cut 
+  computation.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_CutBelongsToList( Map_Cut_t * pList, Map_Node_t * ppNodes[], int nNodes )
+{
+    Map_Cut_t * pTemp;
+    int i;
+    for ( pTemp = pList; pTemp; pTemp = pTemp->pNext )
+    {
+        for ( i = 0; i < nNodes; i++ )
+            if ( pTemp->ppLeaves[i] != ppNodes[i] )
+                break;
+        if ( i == nNodes )
+            return 1;
+    }
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the cuts in the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_CutListPrint( Map_Man_t * pMan, Map_Node_t * pRoot )
+{
+    Map_Cut_t * pTemp;
+    int Counter;
+    for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ )
+    {
+        printf( "%2d : ", Counter + 1 );
+        Map_CutPrint_( pMan, pTemp, pRoot );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the cuts in the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_CutListPrint2( Map_Man_t * pMan, Map_Node_t * pRoot )
+{
+    Map_Cut_t * pTemp;
+    int Counter;
+    for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ )
+    {
+        printf( "%2d : ", Counter + 1 );
+        Map_CutPrint_( pMan, pTemp, pRoot );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_CutPrint_( Map_Man_t * pMan, Map_Cut_t * pCut, Map_Node_t * pRoot )
+{
+    int i;
+    printf( "(%3d)  {", pRoot->Num );
+    for ( i = 0; i < pMan->nVarsMax; i++ )
+        if ( pCut->ppLeaves[i] )
+            printf( " %3d", pCut->ppLeaves[i]->Num );
+    printf( " }\n" );
+}
+
+
+
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the hash table to canonicize cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_CutTable_t * Map_CutTableStart( Map_Man_t * pMan )
+{
+    Map_CutTable_t * p;
+    // allocate the table
+    p = ABC_ALLOC( Map_CutTable_t, 1 );
+    memset( p, 0, sizeof(Map_CutTable_t) );
+    p->nBins = Abc_PrimeCudd( 10 * MAP_CUTS_MAX_COMPUTE );
+    p->pBins = ABC_ALLOC( Map_Cut_t *, p->nBins );
+    memset( p->pBins, 0, sizeof(Map_Cut_t *) * p->nBins );
+    p->pCuts = ABC_ALLOC( int, 2 * MAP_CUTS_MAX_COMPUTE );
+    p->pArray = ABC_ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE );
+    p->pCuts1 = ABC_ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE );
+    p->pCuts2 = ABC_ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_CutTableStop( Map_CutTable_t * p )
+{
+    ABC_FREE( p->pCuts1 );
+    ABC_FREE( p->pCuts2 );
+    ABC_FREE( p->pArray );
+    ABC_FREE( p->pBins );
+    ABC_FREE( p->pCuts );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the hash value of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Map_CutTableHash( Map_Node_t * ppNodes[], int nNodes )
+{
+    unsigned uRes;
+    int i;
+    uRes = 0;
+    for ( i = 0; i < nNodes; i++ )
+        uRes += s_HashPrimes[i] * ppNodes[i]->Num;
+    return uRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Looks up the table for the available cut.]
+
+  Description [Returns -1 if the same cut is found. Returns the index
+  of the cell where the cut should be added, if it does not exist.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_CutTableLookup( Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes )
+{
+    Map_Cut_t * pCut;
+    unsigned Key;
+    int b, i;
+
+    Key = Map_CutTableHash(ppNodes, nNodes) % p->nBins; 
+    for ( b = Key; p->pBins[b]; b = (b+1) % p->nBins )
+    {
+        pCut = p->pBins[b];
+        if ( pCut->nLeaves != nNodes )
+            continue;
+        for ( i = 0; i < nNodes; i++ )
+            if ( pCut->ppLeaves[i] != ppNodes[i] )
+                break;
+        if ( i == nNodes )
+            return -1;
+    }
+    return b;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the hash table to canonicize cuts.]
+
+  Description [Considers addition of the cut to the hash table.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Cut_t * Map_CutTableConsider( Map_Man_t * pMan, Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes )
+{
+    Map_Cut_t * pCut;
+    int Place, i;
+//    abctime clk;
+    // check the cut
+    Place = Map_CutTableLookup( p, ppNodes, nNodes );
+    if ( Place == -1 )
+        return NULL;
+    assert( nNodes > 0 );
+    // create the new cut
+//clk = Abc_Clock();
+    pCut = Map_CutAlloc( pMan );
+//pMan->time1 += Abc_Clock() - clk;
+    pCut->nLeaves = nNodes;
+    for ( i = 0; i < nNodes; i++ )
+        pCut->ppLeaves[i] = ppNodes[i];
+    // add the cut to the table
+    assert( p->pBins[Place] == NULL );
+    p->pBins[Place] = pCut;
+    // add the cut to the new list
+    p->pCuts[ p->nCuts++ ] = Place;
+    return pCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the table to be used with other cuts.]
+
+  Description [Restarts the table by cleaning the info about cuts stored
+  when the previous node was considered.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_CutTableRestart( Map_CutTable_t * p )
+{
+    int i;
+    for ( i = 0; i < p->nCuts; i++ )
+    {
+        assert( p->pBins[ p->pCuts[i] ] );
+        p->pBins[ p->pCuts[i] ] = NULL;
+    }
+    p->nCuts = 0;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the cuts by the number of leaves and then by delay.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_CutSortCutsCompare( Map_Cut_t ** pC1, Map_Cut_t ** pC2 )
+{
+    if ( (*pC1)->nLeaves < (*pC2)->nLeaves )
+        return -1;
+    if ( (*pC1)->nLeaves > (*pC2)->nLeaves )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts the cuts by average arrival time.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Cut_t * Map_CutSortCuts( Map_Man_t * pMan, Map_CutTable_t * p, Map_Cut_t * pList )
+{
+    Map_Cut_t * pListNew;
+    int nCuts, i;
+//    abctime clk;
+    // move the cuts from the list into the array
+    nCuts = Map_CutList2Array( p->pCuts1, pList );
+    assert( nCuts <= MAP_CUTS_MAX_COMPUTE );
+    // sort the cuts
+//clk = Abc_Clock();
+    qsort( (void *)p->pCuts1, nCuts, sizeof(Map_Cut_t *), 
+            (int (*)(const void *, const void *)) Map_CutSortCutsCompare );
+//pMan->time2 += Abc_Clock() - clk;
+    // move them back into the list
+    if ( nCuts > MAP_CUTS_MAX_USE - 1 )
+    {
+        // free the remaining cuts
+        for ( i = MAP_CUTS_MAX_USE - 1; i < nCuts; i++ )
+            Extra_MmFixedEntryRecycle( pMan->mmCuts, (char *)p->pCuts1[i] );
+        // update the number of cuts
+        nCuts = MAP_CUTS_MAX_USE - 1;
+    }
+    pListNew = Map_CutArray2List( p->pCuts1, nCuts );
+    return pListNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Moves the nodes from the list into the array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_CutList2Array( Map_Cut_t ** pArray, Map_Cut_t * pList )
+{
+    int i;
+    for ( i = 0; pList; pList = pList->pNext, i++ )
+        pArray[i] = pList;
+    return i;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Moves the nodes from the array into the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Cut_t * Map_CutArray2List( Map_Cut_t ** pArray, int nCuts )
+{
+    Map_Cut_t * pListNew, ** ppListNew;
+    int i;
+    pListNew  = NULL;
+    ppListNew = &pListNew;
+    for ( i = 0; i < nCuts; i++ )
+    {
+        // connect these lists
+        *ppListNew = pArray[i];
+        ppListNew  = &pArray[i]->pNext;
+    }
+//printf( "\n" );
+
+    *ppListNew = NULL;
+    return pListNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the truth table of the 5-input cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Map_CutComputeTruth( Map_Man_t * p, Map_Cut_t * pCut, Map_Cut_t * pTemp0, Map_Cut_t * pTemp1, int fComp0, int fComp1 )
+{
+    static unsigned ** pPerms53 = NULL;
+    static unsigned ** pPerms54 = NULL;
+
+    unsigned uPhase, uTruth, uTruth0, uTruth1;
+    int i, k;
+
+    if ( pPerms53 == NULL )
+    {
+        pPerms53 = (unsigned **)Extra_TruthPerm53();
+        pPerms54 = (unsigned **)Extra_TruthPerm54();
+    }
+
+    // find the mapping from the old nodes to the new
+    if ( pTemp0->nLeaves == pCut->nLeaves )
+        uTruth0 = pTemp0->uTruth;
+    else
+    {
+        assert( pTemp0->nLeaves < pCut->nLeaves );
+        uPhase = 0;
+        for ( i = 0; i < (int)pTemp0->nLeaves; i++ )
+        {
+            for ( k = 0; k < pCut->nLeaves; k++ )
+                if ( pTemp0->ppLeaves[i] == pCut->ppLeaves[k] )
+                    break;
+            uPhase |= (1 << k);
+        }
+        assert( uPhase < 32 );
+        if ( pTemp0->nLeaves == 4 )
+        {
+            if ( uPhase == 31-16 ) // 01111
+                uTruth0 = pTemp0->uTruth;
+            else if ( uPhase == 31-8 ) // 10111
+                uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][0];
+            else if ( uPhase == 31-4 ) // 11011
+                uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][1];
+            else if ( uPhase == 31-2 ) // 11101
+                uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][2];
+            else if ( uPhase == 31-1 ) // 11110
+                uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][3];
+            else
+                assert( 0 );
+        }
+        else
+            uTruth0 = pPerms53[pTemp0->uTruth & 0xFF][uPhase];
+    }
+    uTruth0 = fComp0? ~uTruth0: uTruth0;
+
+    // find the mapping from the old nodes to the new
+    if ( pTemp1->nLeaves == pCut->nLeaves )
+        uTruth1 = pTemp1->uTruth;
+    else
+    {
+        assert( pTemp1->nLeaves < pCut->nLeaves );
+        uPhase = 0;
+        for ( i = 0; i < (int)pTemp1->nLeaves; i++ )
+        {
+            for ( k = 0; k < pCut->nLeaves; k++ )
+                if ( pTemp1->ppLeaves[i] == pCut->ppLeaves[k] )
+                    break;
+            uPhase |= (1 << k);
+        }
+        assert( uPhase < 32 );
+        if ( pTemp1->nLeaves == 4 )
+        {
+            if ( uPhase == 31-16 ) // 01111
+                uTruth1 = pTemp1->uTruth;
+            else if ( uPhase == 31-8 ) // 10111
+                uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][0];
+            else if ( uPhase == 31-4 ) // 11011
+                uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][1];
+            else if ( uPhase == 31-2 ) // 11101
+                uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][2];
+            else if ( uPhase == 31-1 ) // 11110
+                uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][3];
+            else
+                assert( 0 );
+        }
+        else
+            uTruth1 = pPerms53[pTemp1->uTruth & 0xFF][uPhase];
+    }
+    uTruth1 = fComp1? ~uTruth1: uTruth1;
+    uTruth  = uTruth0 & uTruth1;
+    return uTruth;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/mapperCutUtils.c b/abc-build/src/map/mapper/mapperCutUtils.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperCutUtils.c
@@ -0,0 +1,279 @@
+/**CFile****************************************************************
+
+  FileName    [mapperCutUtils.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapperCutUtils.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Cut_t * Map_CutAlloc( Map_Man_t * p )
+{
+    Map_Cut_t * pCut;
+    Map_Match_t * pMatch;
+    pCut = (Map_Cut_t *)Extra_MmFixedEntryFetch( p->mmCuts );
+    memset( pCut, 0, sizeof(Map_Cut_t) );
+
+    pMatch = pCut->M;
+    pMatch->AreaFlow       = MAP_FLOAT_LARGE; // unassigned
+    pMatch->tArrive.Rise   = MAP_FLOAT_LARGE; // unassigned
+    pMatch->tArrive.Fall   = MAP_FLOAT_LARGE; // unassigned
+    pMatch->tArrive.Worst  = MAP_FLOAT_LARGE; // unassigned
+
+    pMatch = pCut->M + 1;
+    pMatch->AreaFlow       = MAP_FLOAT_LARGE; // unassigned
+    pMatch->tArrive.Rise   = MAP_FLOAT_LARGE; // unassigned
+    pMatch->tArrive.Fall   = MAP_FLOAT_LARGE; // unassigned
+    pMatch->tArrive.Worst  = MAP_FLOAT_LARGE; // unassigned
+    return pCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_CutFree( Map_Man_t * p, Map_Cut_t * pCut )
+{
+    if ( pCut )
+    Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pCut );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_CutPrint( Map_Man_t * p, Map_Node_t * pRoot, Map_Cut_t * pCut, int fPhase )
+{
+    int i;
+    printf( "CUT:  Delay = (%4.2f, %4.2f). Area = %4.2f. Nodes = %d -> {", 
+        pCut->M[fPhase].tArrive.Rise, pCut->M[fPhase].tArrive.Fall, pCut->M[fPhase].AreaFlow, pRoot->Num );
+    for ( i = 0; i < pCut->nLeaves; i++ )
+        printf( " %d", pCut->ppLeaves[i]->Num );
+    printf( " } \n" );
+}
+
+
+/**function*************************************************************
+
+  synopsis    [Computes the exact area associated with the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Map_CutGetRootArea( Map_Cut_t * pCut, int fPhase )
+{
+    assert( pCut->M[fPhase].pSuperBest );
+    return pCut->M[fPhase].pSuperBest->Area;
+}
+
+/**function*************************************************************
+
+  synopsis    [Computes the exact area associated with the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+int Map_CutGetLeafPhase( Map_Cut_t * pCut, int fPhase, int iLeaf )
+{
+    assert( pCut->M[fPhase].pSuperBest );
+    return (( pCut->M[fPhase].uPhaseBest & (1<<iLeaf) ) == 0);
+}
+
+/**function*************************************************************
+
+  synopsis    [Computes the exact area associated with the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+int Map_NodeGetLeafPhase( Map_Node_t * pNode, int fPhase, int iLeaf )
+{
+    assert( pNode->pCutBest[fPhase]->M[fPhase].pSuperBest );
+    return (( pNode->pCutBest[fPhase]->M[fPhase].uPhaseBest & (1<<iLeaf) ) == 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Cut_t * Map_CutListAppend( Map_Cut_t * pSetAll, Map_Cut_t * pSets )
+{
+    Map_Cut_t * pPrev = NULL; // Suppress "might be used uninitialized"
+    Map_Cut_t * pTemp;
+    if ( pSetAll == NULL )
+        return pSets;
+    if ( pSets == NULL )
+        return pSetAll;
+    // find the last one
+    for ( pTemp = pSets; pTemp; pTemp = pTemp->pNext )
+        pPrev = pTemp;
+    // append all the end of the current set
+    assert( pPrev->pNext == NULL );
+    pPrev->pNext = pSetAll;
+    return pSets;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_CutListRecycle( Map_Man_t * p, Map_Cut_t * pSetList, Map_Cut_t * pSave )
+{
+    Map_Cut_t * pNext, * pTemp;
+    for ( pTemp = pSetList, pNext = pTemp? pTemp->pNext : NULL; 
+          pTemp; 
+          pTemp = pNext, pNext = pNext? pNext->pNext : NULL )
+        if ( pTemp != pSave )
+            Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pTemp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_CutListCount( Map_Cut_t * pSets )
+{
+    Map_Cut_t * pTemp;
+    int i;
+    for ( i = 0, pTemp = pSets; pTemp; pTemp = pTemp->pNext, i++ );
+    return i;
+}
+
+#if 0
+
+/**function*************************************************************
+
+  synopsis    [Removes the fanouts of the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+void Map_CutRemoveFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase )
+{
+    Map_NodeVec_t * vFanouts;
+    int i, k;
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        vFanouts = pCut->ppLeaves[i]->vFanouts;
+        for ( k = 0; k < vFanouts->nSize; k++ )
+            if ( vFanouts->pArray[k] == pNode )
+                break;
+        assert( k != vFanouts->nSize );
+        for ( k++; k < vFanouts->nSize; k++ )
+            vFanouts->pArray[k-1] = vFanouts->pArray[k];
+        vFanouts->nSize--;
+    }
+}
+
+/**function*************************************************************
+
+  synopsis    [Removes the fanouts of the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+void Map_CutInsertFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase )
+{
+    int i;
+    for ( i = 0; i < pCut->nLeaves; i++ )
+        Map_NodeVecPush( pCut->ppLeaves[i]->vFanouts, pNode );
+}
+
+#endif
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/mapperFanout.c b/abc-build/src/map/mapper/mapperFanout.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperFanout.c
@@ -0,0 +1,146 @@
+/**CFile****************************************************************
+
+  FileName    [mapperFanout.c]
+
+  PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+  Synopsis    [Procedures to manipulate fanouts of the FRAIG nodes.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapperFanout.c,v 1.5 2005/01/23 06:59:43 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+#ifdef MAP_ALLOCATE_FANOUT
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Add the fanout to the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_NodeAddFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanout )
+{
+    Map_Node_t * pPivot;
+
+    // pFanins is a fanin of pFanout
+    assert( !Map_IsComplement(pFanin) );
+    assert( !Map_IsComplement(pFanout) );
+    assert( Map_Regular(pFanout->p1) == pFanin || Map_Regular(pFanout->p2) == pFanin );
+
+    pPivot = pFanin->pFanPivot;
+    if ( pPivot == NULL )
+    {
+        pFanin->pFanPivot = pFanout;
+        return;
+    }
+
+    if ( Map_Regular(pPivot->p1) == pFanin )
+    {
+        if ( Map_Regular(pFanout->p1) == pFanin )
+        {
+            pFanout->pFanFanin1 = pPivot->pFanFanin1;
+            pPivot->pFanFanin1  = pFanout;
+        }
+        else // if ( Map_Regular(pFanout->p2) == pFanin )
+        {
+            pFanout->pFanFanin2 = pPivot->pFanFanin1;
+            pPivot->pFanFanin1  = pFanout;
+        }
+    }
+    else // if ( Map_Regular(pPivot->p2) == pFanin )
+    {
+        assert( Map_Regular(pPivot->p2) == pFanin );
+        if ( Map_Regular(pFanout->p1) == pFanin )
+        {
+            pFanout->pFanFanin1 = pPivot->pFanFanin2;
+            pPivot->pFanFanin2  = pFanout;
+        }
+        else // if ( Map_Regular(pFanout->p2) == pFanin )
+        {
+            pFanout->pFanFanin2 = pPivot->pFanFanin2;
+            pPivot->pFanFanin2  = pFanout;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add the fanout to the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_NodeRemoveFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanoutToRemove )
+{
+    Map_Node_t * pFanout, * pFanout2, ** ppFanList;
+    // start the linked list of fanouts
+    ppFanList = &pFanin->pFanPivot; 
+    // go through the fanouts
+    Map_NodeForEachFanoutSafe( pFanin, pFanout, pFanout2 )
+    {
+        // skip the fanout-to-remove
+        if ( pFanout == pFanoutToRemove )
+            continue;
+        // add useful fanouts to the list
+        *ppFanList = pFanout;
+        ppFanList = Map_NodeReadNextFanoutPlace( pFanin, pFanout );
+    }
+    *ppFanList = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of fanouts of a node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_NodeGetFanoutNum( Map_Node_t * pNode )
+{
+    Map_Node_t * pFanout;
+    int Counter = 0;
+    Map_NodeForEachFanout( pNode, pFanout )
+        Counter++;
+    return Counter;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/mapperInt.h b/abc-build/src/map/mapper/mapperInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperInt.h
@@ -0,0 +1,466 @@
+/**CFile****************************************************************
+
+  FileName    [mapperInt.h]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapperInt.h,v 1.8 2004/09/30 21:18:10 satrajit Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__map__mapper__mapperInt_h
+#define ABC__map__mapper__mapperInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+ 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+#include "base/main/main.h"
+#include "map/mio/mio.h"
+#include "mapper.h"
+#include "misc/extra/extraBdd.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+// uncomment to have fanouts represented in the mapping graph
+//#define MAP_ALLOCATE_FANOUT  1
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+// the bit masks
+#define MAP_MASK(n)             ((~((unsigned)0)) >> (32-(n)))
+#define MAP_FULL                 (~((unsigned)0))
+#define MAP_NO_VAR               (-9999.0)
+
+// maximum/minimum operators
+#define MAP_MIN(a,b)             (((a) < (b))? (a) : (b))
+#define MAP_MAX(a,b)             (((a) > (b))? (a) : (b))
+
+// the small and large numbers (min/max float are 1.17e-38/3.40e+38)
+#define MAP_FLOAT_LARGE          ((float)(FLT_MAX/10))
+#define MAP_FLOAT_SMALL          ((float)1.0e-03)
+
+// generating random unsigned (#define RAND_MAX 0x7fff)
+#define MAP_RANDOM_UNSIGNED   ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand()))
+
+// internal macros to work with cuts
+#define Map_CutIsComplement(p)  (((int)((ABC_PTRUINT_T) (p) & 01)))
+#define Map_CutRegular(p)       ((Map_Cut_t *)((ABC_PTRUINT_T)(p) & ~01)) 
+#define Map_CutNot(p)           ((Map_Cut_t *)((ABC_PTRUINT_T)(p) ^ 01)) 
+#define Map_CutNotCond(p,c)     ((Map_Cut_t *)((ABC_PTRUINT_T)(p) ^ (c)))
+
+// internal macros for referencing of nodes
+#define Map_NodeReadRef(p)      ((Map_Regular(p))->nRefs)
+#define Map_NodeRef(p)          ((Map_Regular(p))->nRefs++)
+
+// macros to get hold of the bits in the support info
+#define Map_InfoSetVar(p,i)     (p[(i)>>5] |=  (1<<((i) & 31)))
+#define Map_InfoRemVar(p,i)     (p[(i)>>5] &= ~(1<<((i) & 31)))
+#define Map_InfoFlipVar(p,i)    (p[(i)>>5] ^=  (1<<((i) & 31)))
+#define Map_InfoReadVar(p,i)   ((p[(i)>>5]  &  (1<<((i) & 31))) > 0)
+
+// returns the complemented attribute of the node
+#define Map_NodeIsSimComplement(p) (Map_IsComplement(p)? !(Map_Regular(p)->fInv) : (p)->fInv)
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+// the mapping manager
+struct Map_ManStruct_t_
+{
+    // the mapping graph
+    Map_Node_t **       pBins;         // the table of nodes hashed by their children
+    int                 nBins;         // the size of the table
+    Map_Node_t **       pInputs;       // the array of inputs
+    int                 nInputs;       // the number of inputs
+    Map_Node_t **       pOutputs;      // the array of outputs
+    int                 nOutputs;      // the number of outputs
+    int                 nNodes;        // the total number of nodes
+    Map_Node_t *        pConst1;       // the constant 1 node
+    Map_NodeVec_t *     vMapObjs;      // the array of all nodes
+    Map_NodeVec_t *     vMapBufs;      // the array of all nodes
+    float *             pNodeDelays;   // the array of node delays
+
+    // info about the original circuit
+    char **             ppOutputNames; // the primary output names
+    Map_Time_t *        pInputArrivals;// the PI arrival times
+    Map_Time_t *        pOutputRequireds;// the PI arrival times
+
+    // mapping parameters
+    int                 nVarsMax;      // the max number of variables
+    int                 fAreaRecovery; // the flag to enable area recovery
+    int                 fVerbose;      // the verbosiness flag
+    int                 fMappingMode;  // set to 1 when doing area
+    float               fRequiredGlo;  // the global required times
+    float               fEpsilon;      // the epsilon used to compare floats
+    float               AreaBase;      // the area after delay-oriented mapping
+    float               AreaFinal;     // the area after delay-oriented mapping
+    int                 nIterations;   // How many matching passes to do
+    int                 fObeyFanoutLimits;// Should mapper try to obey fanout limits or not
+    float               DelayTarget;   // the required times set by the user
+    int                 nTravIds;      // the traversal counter
+    int                 fSwitching;    // Should mapper try to obey fanout limits or not
+
+    // the supergate library
+    Map_SuperLib_t *    pSuperLib;     // the current supergate library
+    unsigned            uTruths[6][2]; // the elementary truth tables
+    unsigned            uTruthsLarge[10][32]; // the elementary truth tables
+    int                 nCounts[32];   // the counter of minterms
+    int                 nCountsBest[32];// the counter of minterms
+    Map_NodeVec_t *     vVisited;      // the visited cuts during cut computation
+
+    // the memory managers
+    Extra_MmFixed_t *   mmNodes;       // the memory manager for nodes
+    Extra_MmFixed_t *   mmCuts;        // the memory manager for cuts
+
+    // precomputed N-canonical forms
+    unsigned short *    uCanons;       // N-canonical forms
+    char **             uPhases;       // N-canonical phases
+    char *              pCounters;     // counters of phases
+
+    // various statistical variables
+    int                 nChoiceNodes;  // the number of choice nodes
+    int                 nChoices;      // the number of all choices
+    int                 nCanons;       // the number of times N-canonical form was computed
+    int                 nMatches;      // the number of times supergate matching was performed
+    int                 nPhases;       // the number of phases considered during matching
+    int                 nFanoutViolations;  // the number of nodes in mapped circuit violating fanout
+
+    // runtime statistics
+    abctime             timeToMap;     // time to transfer to the mapping structure
+    abctime             timeCuts;      // time to compute k-feasible cuts
+    abctime             timeTruth;     // time to compute the truth table for each cut
+    abctime             timeMatch;     // time to perform matching for each node
+    abctime             timeArea;      // time to recover area after delay oriented mapping
+    abctime             timeSweep;     // time to perform technology dependent sweep
+    abctime             timeToNet;     // time to transfer back to the network
+    abctime             timeTotal;     // the total mapping time
+    abctime             time1;         // time to transfer to the mapping structure
+    abctime             time2;         // time to transfer to the mapping structure
+    abctime             time3;         // time to transfer to the mapping structure
+};
+
+// the supergate library
+struct Map_SuperLibStruct_t_
+{
+    // general info
+    char *              pName;         // the name of the supergate library
+    Mio_Library_t *     pGenlib;       // the generic library
+
+    // other info
+    int                 nVarsMax;      // the max number of variables
+    int                 nSupersAll;    // the total number of supergates
+    int                 nSupersReal;   // the total number of supergates
+    int                 nLines;        // the total number of lines in the supergate file
+    int                 fVerbose;      // the verbosity flag
+
+    // hash tables
+    Map_Super_t **      ppSupers;      // the array of supergates
+    Map_HashTable_t *   tTableC;       // the table mapping N-canonical forms into supergates
+    Map_HashTable_t *   tTable;        // the table mapping truth tables into supergates
+
+    // data structures for N-canonical form computation
+    unsigned            uTruths[6][2]; // the elementary truth tables
+    unsigned            uMask[2];      // the mask for the truth table
+
+    // the invertor
+    Mio_Gate_t *        pGateInv;      // the pointer to the intertor gate
+    Map_Time_t          tDelayInv;     // the delay of the inverter
+    float               AreaInv;       // the area of the inverter
+    float               AreaBuf;       // the area of the buffer
+    Map_Super_t *       pSuperInv;     // the supergate representing the inverter
+
+    // the memory manager for the internal table
+    Extra_MmFixed_t *   mmSupers;      // the mamory manager for supergates
+    Extra_MmFixed_t *   mmEntries;     // the memory manager for the entries
+    Extra_MmFlex_t *    mmForms;       // the memory manager for formulas
+};
+
+// the mapping node
+struct Map_NodeStruct_t_ 
+{
+    // general information about the node
+    Map_Man_t *         p;             // the mapping manager
+    Map_Node_t *        pNext;         // the next node in the hash table
+    int                 Num;           // the unique number of this node
+    int                 TravId;        // the traversal ID (use to avoid cleaning marks)
+    int                 nRefs;         // the number of references (fanouts) of the given node
+    unsigned            fMark0 : 1;    // the mark used for traversals
+    unsigned            fMark1 : 1;    // the mark used for traversals
+    unsigned            fUsed  : 1;    // the mark to mark the node or its fanins
+    unsigned            fInv   : 1;    // the complemented attribute for the equivalent nodes
+    unsigned            fInvert: 1;    // the flag to denote the use of interter
+    unsigned            Level  :16;    // the level of the given node
+    unsigned            NumTemp:10;    // the level of the given node
+    int                 nRefAct[3];    // estimated fanout for current covering phase, neg and pos and sum
+    float               nRefEst[3];    // actual fanout for previous covering phase, neg and pos and sum
+    float               Switching;     // the probability of switching
+
+    // connectivity
+    Map_Node_t *        p1;            // the first child
+    Map_Node_t *        p2;            // the second child
+    Map_Node_t *        pNextE;        // the next functionally equivalent node
+    Map_Node_t *        pRepr;         // the representative of the functionally equivalent class
+
+#ifdef MAP_ALLOCATE_FANOUT
+    // representation of node's fanouts
+    Map_Node_t *        pFanPivot;     // the first fanout of this node
+    Map_Node_t *        pFanFanin1;    // the next fanout of p1
+    Map_Node_t *        pFanFanin2;    // the next fanout of p2
+//    Map_NodeVec_t *     vFanouts;      // the array of fanouts of the gate
+#endif
+
+    // the delay information
+    Map_Time_t          tArrival[2];   // the best arrival time of the neg (0) and pos (1) phases
+    Map_Time_t          tRequired[2];  // the required time of the neg (0) and pos (1) phases
+
+    // misc information  
+    Map_Cut_t *         pCutBest[2];   // the best mapping for neg and pos phase
+    Map_Cut_t *         pCuts;         // mapping choices for the node (elementary comes first)
+    char *              pData0;        // temporary storage for the corresponding network node
+    char *              pData1;        // temporary storage for the corresponding network node
+}; 
+
+// the match of the cut
+struct Map_MatchStruct_t_  
+{
+    // information used for matching
+    Map_Super_t *       pSupers;     
+    unsigned            uPhase;  
+    // information about the best selected match
+    unsigned            uPhaseBest;    // the best phase (the EXOR of match's phase and gate's phase)
+    Map_Super_t *       pSuperBest;    // the best supergate matched
+    // the parameters of the match
+    Map_Time_t          tArrive;       // the arrival time of this match
+    float               AreaFlow;      // the area flow or area of this match
+};
+  
+// the cuts used for matching
+struct Map_CutStruct_t_  
+{
+    Map_Cut_t *         pNext;         // the pointer to the next cut in the list
+    Map_Cut_t *         pOne;          // the father of this cut
+    Map_Cut_t *         pTwo;          // the mother of this cut
+    Map_Node_t *        ppLeaves[6];   // the leaves of this cut
+    unsigned            uTruth;        // truth table for five-input cuts
+    char                nLeaves;       // the number of leaves
+    char                nVolume;       // the volume of this cut
+    char                fMark;         // the mark to denote visited cut
+    char                Phase;         // the mark to denote complemented cut
+    Map_Match_t         M[2];          // the matches for positive/negative phase
+};
+
+// the supergate internally represented
+struct Map_SuperStruct_t_  
+{
+    int                 Num;           // the ID of the supergate
+    unsigned            fSuper  :  1;  // the flag to distinquish a real super from a fake one
+    unsigned            fExclude:  1;  // the flag if set causes gate to be excluded from being used for mapping
+    unsigned            nFanins :  3;  // the number of inputs
+    unsigned            nGates  :  3;  // the number of gates inside this supergate
+    unsigned            nFanLimit: 4;  // the max number of fanout count
+    unsigned            nSupers : 16;  // the number of supergates in the list
+    unsigned            nPhases :  4;  // the number of phases for matching with canonical form
+    unsigned char       uPhases[4];    // the maximum of 4 phases for matching with canonical form
+    int                 nUsed;         // the number of times the supergate is used
+    Map_Super_t *       pFanins[6];    // the fanins of the gate
+    Mio_Gate_t *        pRoot;         // the root gate
+    unsigned            uTruth[2];     // the truth table
+    Map_Time_t          tDelaysR[6];   // the pin-to-pin delay constraints for the rise of the output
+    Map_Time_t          tDelaysF[6];   // the pin-to-pin delay constraints for the rise of the output
+    Map_Time_t          tDelayMax;     // the maximum delay
+    float               Area;          // the area
+    char *              pFormula;      // the symbolic formula
+    Map_Super_t *       pNext;         // the pointer to the next super in the list
+};
+
+// the vector of nodes
+struct Map_NodeVecStruct_t_
+{
+    Map_Node_t **       pArray;        // the array of nodes
+    int                 nSize;         // the number of entries in the array
+    int                 nCap;          // the number of allocated entries
+};
+
+// the hash table 
+struct Map_HashTableStruct_t_
+{
+    Map_HashEntry_t **  pBins;         // the table bins
+    int                 nBins;         // the size of the table
+    int                 nEntries;      // the total number of entries in the table
+    Extra_MmFixed_t *   mmMan;         // the memory manager for entries
+};
+
+// the entry in the hash table
+struct Map_HashEntryStruct_t_
+{
+    unsigned            uTruth[2];     // the truth table for 6-var function
+    unsigned            uPhase;        // the phase to tranform it into the canonical form
+    Map_Super_t *       pGates;        // the linked list of matching supergates
+    Map_HashEntry_t *   pNext;         // the next entry in the hash table
+};
+
+// getting hold of the next fanout of the node
+#define Map_NodeReadNextFanout( pNode, pFanout )                \
+    ( ( pFanout == NULL )? NULL :                               \
+        ((Map_Regular((pFanout)->p1) == (pNode))?               \
+             (pFanout)->pFanFanin1 : (pFanout)->pFanFanin2) )
+
+// getting hold of the place where the next fanout will be attached
+#define Map_NodeReadNextFanoutPlace( pNode, pFanout )           \
+    ( (Map_Regular((pFanout)->p1) == (pNode))?                  \
+         &(pFanout)->pFanFanin1 : &(pFanout)->pFanFanin2 )
+
+// iterator through the fanouts of the node
+#define Map_NodeForEachFanout( pNode, pFanout )                 \
+    for ( pFanout = (pNode)->pFanPivot; pFanout;                \
+          pFanout = Map_NodeReadNextFanout(pNode, pFanout) )
+
+// safe iterator through the fanouts of the node
+#define Map_NodeForEachFanoutSafe( pNode, pFanout, pFanout2 )   \
+    for ( pFanout  = (pNode)->pFanPivot,                        \
+          pFanout2 = Map_NodeReadNextFanout(pNode, pFanout);    \
+          pFanout;                                              \
+          pFanout  = pFanout2,                                  \
+          pFanout2 = Map_NodeReadNextFanout(pNode, pFanout) )
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== mapperCanon.c =============================================================*/
+/*=== mapperCut.c ===============================================================*/
+extern void              Map_MappingCuts( Map_Man_t * p );
+/*=== mapperCutUtils.c ===============================================================*/
+extern Map_Cut_t *       Map_CutAlloc( Map_Man_t * p );
+extern void              Map_CutFree( Map_Man_t * p, Map_Cut_t * pCut );
+extern void              Map_CutPrint( Map_Man_t * p, Map_Node_t * pRoot, Map_Cut_t * pCut, int fPhase );
+extern float             Map_CutGetRootArea( Map_Cut_t * pCut, int fPhase );
+extern int               Map_CutGetLeafPhase( Map_Cut_t * pCut, int fPhase, int iLeaf );
+extern int               Map_NodeGetLeafPhase( Map_Node_t * pNode, int fPhase, int iLeaf );
+extern Map_Cut_t *       Map_CutListAppend( Map_Cut_t * pSetAll, Map_Cut_t * pSets );
+extern void              Map_CutListRecycle( Map_Man_t * p, Map_Cut_t * pSetList, Map_Cut_t * pSave );
+extern int               Map_CutListCount( Map_Cut_t * pSets );
+extern void              Map_CutRemoveFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase );
+extern void              Map_CutInsertFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase );
+/*=== mapperFanout.c =============================================================*/
+extern void              Map_NodeAddFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanout );
+extern void              Map_NodeRemoveFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanoutToRemove );
+extern int               Map_NodeGetFanoutNum( Map_Node_t * pNode );
+/*=== mapperLib.c ============================================================*/
+extern Map_SuperLib_t *  Map_SuperLibCreate( Mio_Library_t * pGenlib, Vec_Str_t * vStr, char * pFileName, char * pExcludeFile, int  fAlgorithm, int  fVerbose );
+extern void              Map_SuperLibFree( Map_SuperLib_t * p );
+/*=== mapperMatch.c ===============================================================*/
+extern int               Map_MappingMatches( Map_Man_t * p );
+/*=== mapperRefs.c =============================================================*/
+extern void              Map_MappingEstimateRefsInit( Map_Man_t * p );
+extern void              Map_MappingEstimateRefs( Map_Man_t * p );
+extern float             Map_CutGetAreaFlow( Map_Cut_t * pCut, int fPhase );
+extern float             Map_CutGetAreaRefed( Map_Cut_t * pCut, int fPhase );
+extern float             Map_CutGetAreaDerefed( Map_Cut_t * pCut, int fPhase );
+extern float             Map_CutRef( Map_Cut_t * pCut, int fPhase );
+extern float             Map_CutDeref( Map_Cut_t * pCut, int fPhase );
+extern void              Map_MappingSetRefs( Map_Man_t * pMan );
+extern float             Map_MappingGetArea( Map_Man_t * pMan );
+/*=== mapperSwitch.c =============================================================*/
+extern float             Map_SwitchCutGetDerefed( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase );
+extern float             Map_SwitchCutRef( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase );
+extern float             Map_SwitchCutDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase );
+extern float             Map_MappingGetSwitching( Map_Man_t * pMan );
+/*=== mapperTree.c ===============================================================*/
+extern int               Map_LibraryDeriveGateInfo( Map_SuperLib_t * pLib, st__table * tExcludeGate );
+extern int               Map_LibraryReadFileTreeStr( Map_SuperLib_t * pLib, Mio_Library_t * pGenlib, Vec_Str_t * vStr, char * pFileName );
+extern int               Map_LibraryReadTree( Map_SuperLib_t * pLib, Mio_Library_t * pGenlib, char * pFileName, char * pExcludeFile );
+extern void              Map_LibraryPrintTree( Map_SuperLib_t * pLib );
+/*=== mapperSuper.c ===============================================================*/
+extern int               Map_LibraryRead( Map_SuperLib_t * p, char * pFileName );
+extern void              Map_LibraryPrintSupergate( Map_Super_t * pGate );
+/*=== mapperTable.c ============================================================*/
+extern Map_HashTable_t * Map_SuperTableCreate( Map_SuperLib_t * pLib );
+extern void              Map_SuperTableFree( Map_HashTable_t * p );
+extern int               Map_SuperTableInsertC( Map_HashTable_t * pLib, unsigned uTruthC[], Map_Super_t * pGate );
+extern int               Map_SuperTableInsert( Map_HashTable_t * pLib, unsigned uTruth[], Map_Super_t * pGate, unsigned uPhase );
+extern Map_Super_t *     Map_SuperTableLookup( Map_HashTable_t * p, unsigned uTruth[], unsigned * puPhase );
+extern void              Map_SuperTableSortSupergates( Map_HashTable_t * p, int nSupersMax );
+extern void              Map_SuperTableSortSupergatesByDelay( Map_HashTable_t * p, int nSupersMax );
+/*=== mapperTime.c =============================================================*/
+extern float             Map_TimeCutComputeArrival( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float tWorstCaseLimit );
+extern float             Map_TimeComputeArrivalMax( Map_Man_t * p );
+extern void              Map_TimeComputeRequiredGlobal( Map_Man_t * p );
+/*=== mapperTruth.c ===============================================================*/
+extern void              Map_MappingTruths( Map_Man_t * pMan );
+extern int               Map_TruthsCutDontCare( Map_Man_t * pMan, Map_Cut_t * pCut, unsigned * uTruthDc );
+extern int               Map_TruthCountOnes( unsigned * uTruth, int nLeaves );
+extern int               Map_TruthDetectTwoFirst( unsigned * uTruth, int nLeaves );
+/*=== mapperUtils.c ===============================================================*/
+extern Map_NodeVec_t *   Map_MappingDfs( Map_Man_t * pMan, int fCollectEquiv );
+extern int               Map_MappingCountLevels( Map_Man_t * pMan );
+extern void              Map_MappingUnmark( Map_Man_t * pMan );
+extern void              Map_MappingMark_rec( Map_Node_t * pNode );
+extern void              Map_MappingUnmark_rec( Map_Node_t * pNode );
+extern void              Map_MappingPrintOutputArrivals( Map_Man_t * p );
+extern void              Map_MappingSetupMask( unsigned uMask[], int nVarsMax );
+extern int               Map_MappingNodeIsViolator( Map_Node_t * pNode, Map_Cut_t * pCut, int fPosPol );
+extern float             Map_MappingGetAreaFlow( Map_Man_t * p );
+extern void              Map_MappingSortByLevel( Map_Man_t * pMan, Map_NodeVec_t * vNodes );
+extern int               Map_MappingCountDoubles( Map_Man_t * pMan, Map_NodeVec_t * vNodes );
+extern void              Map_MappingExpandTruth( unsigned uTruth[2], int nVars );
+extern float             Map_MappingPrintSwitching( Map_Man_t * pMan );
+extern void              Map_MappingSetPlacementInfo( Map_Man_t * p );
+extern float             Map_MappingPrintWirelength( Map_Man_t * p );
+extern void              Map_MappingWireReport( Map_Man_t * p );
+extern float             Map_MappingComputeDelayWithFanouts( Map_Man_t * p );
+extern int               Map_MappingGetMaxLevel( Map_Man_t * pMan );
+extern void              Map_MappingSetChoiceLevels( Map_Man_t * pMan );
+extern void              Map_MappingReportChoices( Map_Man_t * pMan );
+/*=== mapperVec.c =============================================================*/
+extern Map_NodeVec_t *   Map_NodeVecAlloc( int nCap );
+extern void              Map_NodeVecFree( Map_NodeVec_t * p );
+extern Map_NodeVec_t *   Map_NodeVecDup( Map_NodeVec_t * p );
+extern Map_Node_t **     Map_NodeVecReadArray( Map_NodeVec_t * p );
+extern int               Map_NodeVecReadSize( Map_NodeVec_t * p );
+extern void              Map_NodeVecGrow( Map_NodeVec_t * p, int nCapMin );
+extern void              Map_NodeVecShrink( Map_NodeVec_t * p, int nSizeNew );
+extern void              Map_NodeVecClear( Map_NodeVec_t * p );
+extern void              Map_NodeVecPush( Map_NodeVec_t * p, Map_Node_t * Entry );
+extern int               Map_NodeVecPushUnique( Map_NodeVec_t * p, Map_Node_t * Entry );
+extern Map_Node_t *      Map_NodeVecPop( Map_NodeVec_t * p );
+extern void              Map_NodeVecRemove( Map_NodeVec_t * p, Map_Node_t * Entry );
+extern void              Map_NodeVecWriteEntry( Map_NodeVec_t * p, int i, Map_Node_t * Entry );
+extern Map_Node_t *      Map_NodeVecReadEntry( Map_NodeVec_t * p, int i );
+extern void              Map_NodeVecSortByLevel( Map_NodeVec_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/map/mapper/mapperLib.c b/abc-build/src/map/mapper/mapperLib.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperLib.c
@@ -0,0 +1,258 @@
+/**CFile****************************************************************
+
+  FileName    [mapperLib.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapperLib.c,v 1.6 2005/01/23 06:59:44 alanmi Exp $]
+
+***********************************************************************/
+#define _BSD_SOURCE
+
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+#include "mapperInt.h"
+#include "map/super/super.h"
+#include "map/mapper/mapperInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reads in the supergate library and prepares it for use.]
+
+  Description [The supergates library comes in a .super file. This file
+  contains descriptions of supergates along with some relevant information.
+  This procedure reads the supergate file, canonicizes the supergates,
+  and constructs an additional lookup table, which can be used to map
+  truth tables of the cuts into the pair (phase, supergate). The phase
+  indicates how the current truth table should be phase assigned to 
+  match the canonical form of the supergate. The resulting phase is the
+  bitwise EXOR of the phase needed to canonicize the supergate and the
+  phase needed to transform the truth table into its canonical form.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_SuperLib_t * Map_SuperLibCreate( Mio_Library_t * pGenlib, Vec_Str_t * vStr, char * pFileName, char * pExcludeFile, int fAlgorithm, int fVerbose )
+{
+    Map_SuperLib_t * p;
+    abctime clk;
+
+    // start the supergate library
+    p = ABC_ALLOC( Map_SuperLib_t, 1 );
+    memset( p, 0, sizeof(Map_SuperLib_t) );
+    p->pName     = Abc_UtilStrsav(pFileName);
+    p->fVerbose  = fVerbose;
+    p->mmSupers  = Extra_MmFixedStart( sizeof(Map_Super_t) );
+    p->mmEntries = Extra_MmFixedStart( sizeof(Map_HashEntry_t) );
+    p->mmForms   = Extra_MmFlexStart();
+    Map_MappingSetupTruthTables( p->uTruths );
+
+    // start the hash table
+    p->tTableC = Map_SuperTableCreate( p );
+    p->tTable  = Map_SuperTableCreate( p );
+
+    // read the supergate library from file
+clk = Abc_Clock();
+    if ( vStr != NULL )
+    {
+        // read the supergate library from file
+        int Status = Map_LibraryReadFileTreeStr( p, pGenlib, vStr, pFileName );
+        if ( Status == 0 )
+        {
+            Map_SuperLibFree( p );
+            return NULL;
+        }
+        // prepare the info about the library
+        Status = Map_LibraryDeriveGateInfo( p, NULL );
+        if ( Status == 0 )
+        {
+            Map_SuperLibFree( p );
+            return NULL;
+        }
+        assert( p->nVarsMax > 0 );
+    }
+    else if ( fAlgorithm )
+    {
+        if ( !Map_LibraryReadTree( p, pGenlib, pFileName, pExcludeFile ) )
+        {
+            Map_SuperLibFree( p );
+            return NULL;
+        }
+    }
+    else
+    {
+        if ( pExcludeFile != 0 )
+        {
+            Map_SuperLibFree( p );
+            printf ("Error: Exclude file support not present for old format. Stop.\n");
+            return NULL;
+        }
+        if ( !Map_LibraryRead( p, pFileName ) )
+        {
+            Map_SuperLibFree( p );
+            return NULL;
+        }
+    }
+    assert( p->nVarsMax > 0 );
+
+    // report the stats
+    if ( fVerbose ) 
+    {
+        printf( "Loaded %d unique %d-input supergates from \"%s\".  ", 
+            p->nSupersReal, p->nVarsMax, pFileName );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+
+    // assign the interver parameters
+    p->pGateInv        = Mio_LibraryReadInv( p->pGenlib );
+    p->tDelayInv.Rise  = Mio_LibraryReadDelayInvRise( p->pGenlib );
+    p->tDelayInv.Fall  = Mio_LibraryReadDelayInvFall( p->pGenlib );
+    p->tDelayInv.Worst = MAP_MAX( p->tDelayInv.Rise, p->tDelayInv.Fall );
+    p->AreaInv         = Mio_LibraryReadAreaInv( p->pGenlib );
+    p->AreaBuf         = Mio_LibraryReadAreaBuf( p->pGenlib );
+
+    // assign the interver supergate
+    p->pSuperInv = (Map_Super_t *)Extra_MmFixedEntryFetch( p->mmSupers );
+    memset( p->pSuperInv, 0, sizeof(Map_Super_t) );
+    p->pSuperInv->Num         = -1;
+    p->pSuperInv->nGates      =  1;
+    p->pSuperInv->nFanins     =  1;
+    p->pSuperInv->nFanLimit   = 10;
+    p->pSuperInv->pFanins[0]  = p->ppSupers[0];
+    p->pSuperInv->pRoot       = p->pGateInv;
+    p->pSuperInv->Area        = p->AreaInv;
+    p->pSuperInv->tDelayMax   = p->tDelayInv;
+    p->pSuperInv->tDelaysR[0].Rise = MAP_NO_VAR;
+    p->pSuperInv->tDelaysR[0].Fall = p->tDelayInv.Rise;
+    p->pSuperInv->tDelaysF[0].Rise = p->tDelayInv.Fall;
+    p->pSuperInv->tDelaysF[0].Fall = MAP_NO_VAR;
+    return p;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the supergate library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_SuperLibFree( Map_SuperLib_t * p )
+{
+    if ( p == NULL ) return;
+    if ( p->pGenlib )
+    {
+        if ( p->pGenlib != Abc_FrameReadLibGen() )
+            Mio_LibraryDelete( p->pGenlib );
+        p->pGenlib = NULL;
+    }
+    if ( p->tTableC )
+        Map_SuperTableFree( p->tTableC );
+    if ( p->tTable )
+        Map_SuperTableFree( p->tTable );
+    Extra_MmFixedStop( p->mmSupers );
+    Extra_MmFixedStop( p->mmEntries );
+    Extra_MmFlexStop( p->mmForms );
+    ABC_FREE( p->ppSupers );
+    ABC_FREE( p->pName );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the library from the genlib library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_SuperLibDeriveFromGenlib( Mio_Library_t * pLib, int fVerbose )
+{
+    Map_SuperLib_t * pLibSuper;
+    Vec_Str_t * vStr;
+    char * pFileName;
+    if ( pLib == NULL )
+        return 0;
+
+    // compute supergates
+    vStr = Super_PrecomputeStr( pLib, 5, 1, 100000000, 10000000, 10000000, 100, 1, 0 );
+    if ( vStr == NULL )
+        return 0;
+
+    // create supergate library
+    pFileName = Extra_FileNameGenericAppend( Mio_LibraryReadName(pLib), ".super" );
+    pLibSuper = Map_SuperLibCreate( pLib, vStr, pFileName, NULL, 1, 0 );
+    Vec_StrFree( vStr );
+
+    // replace the library
+    Map_SuperLibFree( (Map_SuperLib_t *)Abc_FrameReadLibSuper() );
+    Abc_FrameSetLibSuper( pLibSuper );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the library from the genlib library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_SuperLibDeriveFromGenlib2( Mio_Library_t * pLib, int fVerbose )
+{
+    Abc_Frame_t * pAbc = Abc_FrameGetGlobalFrame();
+    char * pFileName;
+    if ( pLib == NULL )
+        return 0;
+    // compute supergates
+    pFileName = Extra_FileNameGenericAppend(Mio_LibraryReadName(pLib), ".super");
+    Super_Precompute( pLib, 5, 1, 100000000, 10000000, 10000000, 100, 1, 0, pFileName );
+    // assuming that it terminated successfully
+    if ( Cmd_CommandExecute( pAbc, pFileName ) )
+    {
+        fprintf( stdout, "Cannot execute command \"read_super %s\".\n", pFileName );
+        return 0;
+    }
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/mapperMatch.c b/abc-build/src/map/mapper/mapperMatch.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperMatch.c
@@ -0,0 +1,636 @@
+/**CFile****************************************************************
+
+  FileName    [mapperMatch.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapperMatch.c,v 1.7 2004/09/30 21:18:10 satrajit Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+    A potential improvement:
+    When an internal node is not used in the mapping, its required times 
+    are set to be +infinity. So when we recover area, we try to find the 
+    best match for area and completely disregard the delay for the nodes
+    that are not currently used in the mapping because any match whose 
+    arrival times are less than the required times (+infinity) can be used.
+    It may be possible to develop a better approach to recover area for
+    the nodes that are not currently used in the mapping...
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the match.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MatchClean( Map_Match_t * pMatch )
+{
+    memset( pMatch, 0, sizeof(Map_Match_t) );
+    pMatch->AreaFlow          = MAP_FLOAT_LARGE; // unassigned
+    pMatch->tArrive.Rise   = MAP_FLOAT_LARGE; // unassigned
+    pMatch->tArrive.Fall   = MAP_FLOAT_LARGE; // unassigned
+    pMatch->tArrive.Worst  = MAP_FLOAT_LARGE; // unassigned
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares two matches.]
+
+  Description [Returns 1 if the second match is better. Otherwise returns 0.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_MatchCompare( Map_Man_t * pMan, Map_Match_t * pM1, Map_Match_t * pM2, int fDoingArea )
+{
+    if ( !fDoingArea )
+    {
+        // compare the arrival times
+        if ( pM1->tArrive.Worst < pM2->tArrive.Worst - pMan->fEpsilon )
+            return 0;
+        if ( pM1->tArrive.Worst > pM2->tArrive.Worst + pMan->fEpsilon )
+            return 1;
+        // compare the areas or area flows
+        if ( pM1->AreaFlow < pM2->AreaFlow - pMan->fEpsilon )
+            return 0;
+        if ( pM1->AreaFlow > pM2->AreaFlow + pMan->fEpsilon )
+            return 1;
+        // compare the fanout limits
+        if ( pM1->pSuperBest->nFanLimit > pM2->pSuperBest->nFanLimit )
+            return 0;
+        if ( pM1->pSuperBest->nFanLimit < pM2->pSuperBest->nFanLimit )
+            return 1;
+        // compare the number of leaves
+        if ( pM1->pSuperBest->nFanins < pM2->pSuperBest->nFanins )
+            return 0;
+        if ( pM1->pSuperBest->nFanins > pM2->pSuperBest->nFanins )
+            return 1;
+        // otherwise prefer the old cut
+        return 0;
+    }
+    else
+    {
+        // compare the areas or area flows
+        if ( pM1->AreaFlow < pM2->AreaFlow - pMan->fEpsilon )
+            return 0;
+        if ( pM1->AreaFlow > pM2->AreaFlow + pMan->fEpsilon )
+            return 1;
+        // compare the arrival times
+        if ( pM1->tArrive.Worst < pM2->tArrive.Worst - pMan->fEpsilon )
+            return 0;
+        if ( pM1->tArrive.Worst > pM2->tArrive.Worst + pMan->fEpsilon )
+            return 1;
+        // compare the fanout limits
+        if ( pM1->pSuperBest->nFanLimit > pM2->pSuperBest->nFanLimit )
+            return 0;
+        if ( pM1->pSuperBest->nFanLimit < pM2->pSuperBest->nFanLimit )
+            return 1;
+        // compare the number of leaves
+        if ( pM1->pSuperBest->nFanins < pM2->pSuperBest->nFanins )
+            return 0;
+        if ( pM1->pSuperBest->nFanins > pM2->pSuperBest->nFanins )
+            return 1;
+        // otherwise prefer the old cut
+        return 0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the best matching of the cut.]
+
+  Description [The parameters: the node (pNode), the cut (pCut), the phase to be matched 
+  (fPhase), and the upper bound on the arrival times of the cut (fWorstLimit). This 
+  procedure goes through the matching supergates up to the phase assignment, and selects the
+  best supergate, which will be used to map the cut. As a result of calling this procedure
+  the matching information is written into pMatch.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_MatchNodeCut( Map_Man_t * p, Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float fWorstLimit )
+{
+    Map_Match_t MatchBest, * pMatch = pCut->M + fPhase;
+    Map_Super_t * pSuper;
+    int i, Counter;
+
+    // save the current match of the cut
+    MatchBest = *pMatch;
+    // go through the supergates
+    for ( pSuper = pMatch->pSupers, Counter = 0; pSuper; pSuper = pSuper->pNext, Counter++ )
+    {
+        p->nMatches++;
+        // this is an attempt to reduce the runtime of matching and area 
+        // at the cost of rare and very minor increase in delay
+        // (the supergates are sorted by increasing area)
+        if ( Counter == 30 )
+           break;
+
+        // go through different phases of the given match and supergate
+        pMatch->pSuperBest = pSuper;
+        for ( i = 0; i < (int)pSuper->nPhases; i++ )
+        {
+            p->nPhases++;
+            // find the overall phase of this match
+            pMatch->uPhaseBest = pMatch->uPhase ^ pSuper->uPhases[i];
+            if ( p->fMappingMode == 0 )
+            {
+                // get the arrival time
+                Map_TimeCutComputeArrival( pNode, pCut, fPhase, fWorstLimit );
+                // skip the cut if the arrival times exceed the required times
+                if ( pMatch->tArrive.Worst > fWorstLimit + p->fEpsilon )
+                    continue;
+                // get the area (area flow)
+                pMatch->AreaFlow = Map_CutGetAreaFlow( pCut, fPhase );
+            }
+            else
+            {
+                // get the area (area flow)
+                if ( p->fMappingMode == 2 || p->fMappingMode == 3 )
+                    pMatch->AreaFlow = Map_CutGetAreaDerefed( pCut, fPhase );
+                else if ( p->fMappingMode == 4 )
+                    pMatch->AreaFlow = Map_SwitchCutGetDerefed( pNode, pCut, fPhase );
+                else 
+                    pMatch->AreaFlow = Map_CutGetAreaFlow( pCut, fPhase );
+                // skip if the cut is too large
+                if ( pMatch->AreaFlow > MatchBest.AreaFlow + p->fEpsilon )
+                    continue;
+                // get the arrival time
+                Map_TimeCutComputeArrival( pNode, pCut, fPhase, fWorstLimit );
+                // skip the cut if the arrival times exceed the required times
+                if ( pMatch->tArrive.Worst > fWorstLimit + p->fEpsilon )
+                    continue;
+            }
+
+            // if the cut is non-trivial, compare it
+            if ( Map_MatchCompare( p, &MatchBest, pMatch, p->fMappingMode ) )
+            {
+                MatchBest = *pMatch;
+                // if we are mapping for delay, the worst-case limit should be reduced
+                if ( p->fMappingMode == 0 )
+                    fWorstLimit = MatchBest.tArrive.Worst;
+            }
+        }
+    }
+    // set the best match
+    *pMatch = MatchBest;
+
+    // recompute the arrival time and area (area flow) of this cut
+    if ( pMatch->pSuperBest )
+    {
+        Map_TimeCutComputeArrival( pNode, pCut, fPhase, MAP_FLOAT_LARGE );
+        if ( p->fMappingMode == 2 || p->fMappingMode == 3 )
+            pMatch->AreaFlow = Map_CutGetAreaDerefed( pCut, fPhase );
+        else if ( p->fMappingMode == 4 )
+            pMatch->AreaFlow = Map_SwitchCutGetDerefed( pNode, pCut, fPhase );
+        else 
+            pMatch->AreaFlow = Map_CutGetAreaFlow( pCut, fPhase );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the matching of one polarity of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_MatchNodePhase( Map_Man_t * p, Map_Node_t * pNode, int fPhase )
+{
+    Map_Match_t MatchBest, * pMatch;
+    Map_Cut_t * pCut, * pCutBest;
+    float Area1 = 0.0; // Suppress "might be used uninitialized
+    float Area2, fWorstLimit;
+
+    // skip the cuts that have been unassigned during area recovery
+    pCutBest = pNode->pCutBest[fPhase];
+    if ( p->fMappingMode != 0 && pCutBest == NULL )
+        return 1;
+
+    // recompute the arrival times of the current best match 
+    // because the arrival times of the fanins may have changed 
+    // as a result of remapping fanins in the topological order
+    if ( p->fMappingMode != 0 )
+    {
+        Map_TimeCutComputeArrival( pNode, pCutBest, fPhase, MAP_FLOAT_LARGE );
+        // make sure that the required times are met
+//        assert( pCutBest->M[fPhase].tArrive.Rise < pNode->tRequired[fPhase].Rise + p->fEpsilon );
+//        assert( pCutBest->M[fPhase].tArrive.Fall < pNode->tRequired[fPhase].Fall + p->fEpsilon );
+    }
+
+    // recompute the exact area of the current best match
+    // because the exact area of the fanins may have changed
+    // as a result of remapping fanins in the topological order
+    if ( p->fMappingMode == 2 || p->fMappingMode == 3 )
+    {
+        pMatch = pCutBest->M + fPhase;
+        if ( pNode->nRefAct[fPhase] > 0 || 
+            (pNode->pCutBest[!fPhase] == NULL && pNode->nRefAct[!fPhase] > 0) )
+            pMatch->AreaFlow = Area1 = Map_CutDeref( pCutBest, fPhase );
+        else
+            pMatch->AreaFlow = Area1 = Map_CutGetAreaDerefed( pCutBest, fPhase );
+    }
+    else if ( p->fMappingMode == 4 )
+    {
+        pMatch = pCutBest->M + fPhase;
+        if ( pNode->nRefAct[fPhase] > 0 || 
+            (pNode->pCutBest[!fPhase] == NULL && pNode->nRefAct[!fPhase] > 0) )
+            pMatch->AreaFlow = Area1 = Map_SwitchCutDeref( pNode, pCutBest, fPhase );
+        else
+            pMatch->AreaFlow = Area1 = Map_SwitchCutGetDerefed( pNode, pCutBest, fPhase );
+    }
+
+    // save the old mapping
+    if ( pCutBest )
+        MatchBest = pCutBest->M[fPhase];
+    else
+        Map_MatchClean( &MatchBest );
+ 
+    // select the new best cut
+    fWorstLimit = pNode->tRequired[fPhase].Worst;
+    for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+    {
+        // limit gate sizes based on fanout count
+        if ( (pNode->nRefs > 3 && pCut->nLeaves > 2) || (pNode->nRefs > 1 && pCut->nLeaves > 3) )
+            continue;
+        pMatch = pCut->M + fPhase;
+        if ( pMatch->pSupers == NULL )
+            continue;
+
+        // find the matches for the cut
+        Map_MatchNodeCut( p, pNode, pCut, fPhase, fWorstLimit );
+        if ( pMatch->pSuperBest == NULL || pMatch->tArrive.Worst > fWorstLimit + p->fEpsilon )
+            continue;
+
+        // if the cut can be matched compare the matchings
+        if ( Map_MatchCompare( p, &MatchBest, pMatch, p->fMappingMode ) )
+        {
+            pCutBest  =  pCut;
+            MatchBest = *pMatch;
+            // if we are mapping for delay, the worst-case limit should be tightened
+            if ( p->fMappingMode == 0 )
+                fWorstLimit = MatchBest.tArrive.Worst;
+        }
+    }
+
+    if ( pCutBest == NULL )
+        return 1;
+
+    // set the new mapping
+    pNode->pCutBest[fPhase] = pCutBest;
+    pCutBest->M[fPhase]     = MatchBest;
+
+    // reference the new cut if it used
+    if ( p->fMappingMode >= 2 && 
+         (pNode->nRefAct[fPhase] > 0 || 
+         (pNode->pCutBest[!fPhase] == NULL && pNode->nRefAct[!fPhase] > 0)) )
+    {
+        if ( p->fMappingMode == 2 || p->fMappingMode == 3 )
+            Area2 = Map_CutRef( pNode->pCutBest[fPhase], fPhase );
+        else if ( p->fMappingMode == 4 )
+            Area2 = Map_SwitchCutRef( pNode, pNode->pCutBest[fPhase], fPhase );
+        else 
+            assert( 0 );
+//        assert( Area2 < Area1 + p->fEpsilon );
+    }
+
+    // make sure that the requited times are met
+//    assert( MatchBest.tArrive.Rise < pNode->tRequired[fPhase].Rise + p->fEpsilon );
+//    assert( MatchBest.tArrive.Fall < pNode->tRequired[fPhase].Fall + p->fEpsilon );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the PI arrival times.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingSetPiArrivalTimes( Map_Man_t * p )
+{
+    Map_Node_t * pNode;
+    int i;
+    for ( i = 0; i < p->nInputs; i++ )
+    {
+        pNode = p->pInputs[i];
+        // set the arrival time of the positive phase
+        pNode->tArrival[1] = p->pInputArrivals[i];
+        pNode->tArrival[1].Rise  += p->pNodeDelays ? p->pNodeDelays[pNode->Num] : 0;
+        pNode->tArrival[1].Fall  += p->pNodeDelays ? p->pNodeDelays[pNode->Num] : 0;
+        pNode->tArrival[1].Worst += p->pNodeDelays ? p->pNodeDelays[pNode->Num] : 0;
+        // set the arrival time of the negative phase
+        pNode->tArrival[0].Rise  = pNode->tArrival[1].Fall + p->pSuperLib->tDelayInv.Rise;
+        pNode->tArrival[0].Fall  = pNode->tArrival[1].Rise + p->pSuperLib->tDelayInv.Fall;
+        pNode->tArrival[0].Worst = MAP_MAX(pNode->tArrival[0].Rise, pNode->tArrival[0].Fall);
+    }
+}
+
+/**function*************************************************************
+
+  synopsis    [Computes the exact area associated with the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Map_TimeMatchWithInverter( Map_Man_t * p, Map_Match_t * pMatch )
+{
+    Map_Time_t tArrInv;
+    tArrInv.Fall  = pMatch->tArrive.Rise + p->pSuperLib->tDelayInv.Fall;
+    tArrInv.Rise  = pMatch->tArrive.Fall + p->pSuperLib->tDelayInv.Rise;
+    tArrInv.Worst = MAP_MAX( tArrInv.Rise, tArrInv.Fall ); 
+    return tArrInv.Worst;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Attempts dropping one phase of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_NodeTryDroppingOnePhase( Map_Man_t * p, Map_Node_t * pNode )
+{
+    Map_Match_t * pMatchBest0, * pMatchBest1;
+    float tWorst0Using1, tWorst1Using0; 
+    int fUsePhase1, fUsePhase0;
+
+    // nothing to do if one of the phases is already dropped
+    if ( pNode->pCutBest[0] == NULL || pNode->pCutBest[1] == NULL )
+        return;
+
+    // do not drop while recovering area flow
+    if ( p->fMappingMode == 1 )//|| p->fMappingMode == 2 )
+        return;
+
+    // get the pointers to the matches of the best cuts
+    pMatchBest0 = pNode->pCutBest[0]->M + 0;
+    pMatchBest1 = pNode->pCutBest[1]->M + 1;
+
+    // get the worst arrival times of each phase
+    // implemented using the other phase with inverter added
+    tWorst0Using1 = Map_TimeMatchWithInverter( p, pMatchBest1 );
+    tWorst1Using0 = Map_TimeMatchWithInverter( p, pMatchBest0 );
+
+    // consider the case of mapping for delay
+    if ( p->fMappingMode == 0 && p->DelayTarget < ABC_INFINITY )
+    { 
+        // if the arrival time of a phase is larger than the arrival time 
+        // of the opposite phase plus the inverter, drop this phase
+        if ( pMatchBest0->tArrive.Worst > tWorst0Using1 + p->fEpsilon ) 
+            pNode->pCutBest[0] = NULL;
+        else if ( pMatchBest1->tArrive.Worst > tWorst1Using0 + p->fEpsilon ) 
+            pNode->pCutBest[1] = NULL;
+        return;
+    }
+
+    // do not perform replacement if one of the phases is unused
+    if ( pNode->nRefAct[0] == 0 || pNode->nRefAct[1] == 0 )
+        return;
+ 
+    // check if replacement of each phase is possible using required times
+    fUsePhase0 = fUsePhase1 = 0;
+    if ( p->fMappingMode == 2 )
+    {
+        fUsePhase0 = (pNode->tRequired[1].Worst > tWorst1Using0 + 3*p->pSuperLib->tDelayInv.Worst + p->fEpsilon);
+        fUsePhase1 = (pNode->tRequired[0].Worst > tWorst0Using1 + 3*p->pSuperLib->tDelayInv.Worst + p->fEpsilon);
+    }
+    else if ( p->fMappingMode == 3 || p->fMappingMode == 4 )
+    {
+        fUsePhase0 = (pNode->tRequired[1].Worst > tWorst1Using0 + p->fEpsilon);
+        fUsePhase1 = (pNode->tRequired[0].Worst > tWorst0Using1 + p->fEpsilon);
+    }
+    if ( !fUsePhase0 && !fUsePhase1 )
+        return;
+
+    // if replacement is possible both ways, use the one that works better
+    if ( fUsePhase0 && fUsePhase1 )
+    {
+        if ( pMatchBest0->AreaFlow < pMatchBest1->AreaFlow )
+            fUsePhase1 = 0;
+        else
+            fUsePhase0 = 0;
+    }
+    // only one phase should be used
+    assert( fUsePhase0 ^ fUsePhase1 );
+
+    // set the corresponding cut to NULL
+    if ( fUsePhase0 )
+    {
+        // deref phase 1 cut if necessary
+        if ( p->fMappingMode >= 2 && pNode->nRefAct[1] > 0 )
+            Map_CutDeref( pNode->pCutBest[1], 1 );
+        // get rid of the cut
+        pNode->pCutBest[1] = NULL;
+        // ref phase 0 cut if necessary
+        if ( p->fMappingMode >= 2 && pNode->nRefAct[0] == 0 )
+            Map_CutRef( pNode->pCutBest[0], 0 );
+    }
+    else
+    {
+        // deref phase 0 cut if necessary
+        if ( p->fMappingMode >= 2 && pNode->nRefAct[0] > 0 )
+            Map_CutDeref( pNode->pCutBest[0], 0 );
+        // get rid of the cut
+        pNode->pCutBest[0] = NULL;
+        // ref phase 1 cut if necessary
+        if ( p->fMappingMode >= 2 && pNode->nRefAct[1] == 0 )
+            Map_CutRef( pNode->pCutBest[1], 1 );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the arrival times from the best cuts to the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_NodeTransferArrivalTimes( Map_Man_t * p, Map_Node_t * pNode )
+{
+    // if both phases are available, set their arrival times
+    if ( pNode->pCutBest[0] && pNode->pCutBest[1] )
+    {
+        pNode->tArrival[0] = pNode->pCutBest[0]->M[0].tArrive;
+        pNode->tArrival[1] = pNode->pCutBest[1]->M[1].tArrive;
+    }
+    // if only one phase is available, compute the arrival time of other phase
+    else if ( pNode->pCutBest[0] )
+    {
+        pNode->tArrival[0] = pNode->pCutBest[0]->M[0].tArrive;
+        pNode->tArrival[1].Rise  = pNode->tArrival[0].Fall + p->pSuperLib->tDelayInv.Rise;
+        pNode->tArrival[1].Fall  = pNode->tArrival[0].Rise + p->pSuperLib->tDelayInv.Fall;
+        pNode->tArrival[1].Worst = MAP_MAX(pNode->tArrival[1].Rise, pNode->tArrival[1].Fall);
+    }
+    else if ( pNode->pCutBest[1] )
+    {
+        pNode->tArrival[1] = pNode->pCutBest[1]->M[1].tArrive;
+        pNode->tArrival[0].Rise  = pNode->tArrival[1].Fall + p->pSuperLib->tDelayInv.Rise;
+        pNode->tArrival[0].Fall  = pNode->tArrival[1].Rise + p->pSuperLib->tDelayInv.Fall;
+        pNode->tArrival[0].Worst = MAP_MAX(pNode->tArrival[0].Rise, pNode->tArrival[0].Fall);
+    }
+    else 
+    {
+        assert( 0 );
+    }
+
+//    assert( pNode->tArrival[0].Rise < pNode->tRequired[0].Rise + p->fEpsilon );
+//    assert( pNode->tArrival[0].Fall < pNode->tRequired[0].Fall + p->fEpsilon );
+
+//    assert( pNode->tArrival[1].Rise < pNode->tRequired[1].Rise + p->fEpsilon );
+//    assert( pNode->tArrival[1].Fall < pNode->tRequired[1].Fall + p->fEpsilon );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the best matches of the nodes.]
+
+  Description [Uses parameter p->fMappingMode to decide how to assign
+  the matches for both polarities of the node. While the matches are 
+  being assigned, one of them may turn out to be better than the other 
+  (in terms of delay, for example). In this case, the worse match can 
+  be permanently dropped, and the corresponding pointer set to NULL.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_MappingMatches( Map_Man_t * p )
+{
+    ProgressBar * pProgress;
+    Map_Node_t * pNode;
+    int i;
+
+    assert( p->fMappingMode >= 0 && p->fMappingMode <= 4 );
+
+    // use the externally given PI arrival times
+    if ( p->fMappingMode == 0 )
+        Map_MappingSetPiArrivalTimes( p );
+
+    // estimate the fanouts
+    if ( p->fMappingMode == 0 )
+        Map_MappingEstimateRefsInit( p );
+    else if ( p->fMappingMode == 1 )
+        Map_MappingEstimateRefs( p );
+
+    // the PI cuts are matched in the cut computation package
+    // in the loop below we match the internal nodes
+    pProgress = Extra_ProgressBarStart( stdout, p->vMapObjs->nSize );
+    for ( i = 0; i < p->vMapObjs->nSize; i++ )
+    {
+        pNode = p->vMapObjs->pArray[i];
+        if ( Map_NodeIsBuf(pNode) )
+        {
+            assert( pNode->p2 == NULL );
+            pNode->tArrival[0] = Map_Regular(pNode->p1)->tArrival[ Map_IsComplement(pNode->p1)];
+            pNode->tArrival[1] = Map_Regular(pNode->p1)->tArrival[!Map_IsComplement(pNode->p1)];
+            continue;
+        }
+
+        // skip primary inputs and secondary nodes if mapping with choices
+        if ( !Map_NodeIsAnd( pNode ) || pNode->pRepr )
+            continue;
+
+        // make sure that at least one non-trival cut is present
+        if ( pNode->pCuts->pNext == NULL )
+        {
+            Extra_ProgressBarStop( pProgress );
+            printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" );
+            return 0;
+        }
+
+        // match negative phase
+        if ( !Map_MatchNodePhase( p, pNode, 0 ) )
+        {
+            Extra_ProgressBarStop( pProgress );
+            return 0;
+        }
+        // match positive phase
+        if ( !Map_MatchNodePhase( p, pNode, 1 ) )
+        {
+            Extra_ProgressBarStop( pProgress );
+            return 0;
+        }
+
+        // make sure that at least one phase is mapped
+        if ( pNode->pCutBest[0] == NULL && pNode->pCutBest[1] == NULL )
+        {
+            printf( "\nError: Could not match both phases of AIG node %d.\n", pNode->Num );
+            printf( "Please make sure that the supergate library has equivalents of AND2 or NAND2.\n" );
+            printf( "If such supergates exist in the library, report a bug.\n" );
+            Extra_ProgressBarStop( pProgress );
+            return 0;
+        }
+
+        // if both phases are assigned, check if one of them can be dropped
+        Map_NodeTryDroppingOnePhase( p, pNode );
+        // set the arrival times of the node using the best cuts
+        Map_NodeTransferArrivalTimes( p, pNode );
+
+        // update the progress bar
+        Extra_ProgressBarUpdate( pProgress, i, "Matches ..." );
+    }
+    Extra_ProgressBarStop( pProgress );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/mapperRefs.c b/abc-build/src/map/mapper/mapperRefs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperRefs.c
@@ -0,0 +1,519 @@
+/**CFile****************************************************************
+
+  FileName    [mapperRefs.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapperRefs.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the actual reference counter of a phase.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_NodeReadRefPhaseAct( Map_Node_t * pNode, int fPhase )
+{
+    assert( !Map_IsComplement(pNode) );
+    if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned
+        return pNode->nRefAct[fPhase];
+    assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned
+    return pNode->nRefAct[2];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the estimated reference counter of a phase.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Map_NodeReadRefPhaseEst( Map_Node_t * pNode, int fPhase )
+{
+    assert( !Map_IsComplement(pNode) );
+    if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned
+        return pNode->nRefEst[fPhase];
+    assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned
+//    return pNode->nRefEst[0] + pNode->nRefEst[1];
+    return pNode->nRefEst[2];
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Increments the actual reference counter of a phase.]
+
+  Description [Returns the old reference counter.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_NodeIncRefPhaseAct( Map_Node_t * pNode, int fPhase )
+{
+    assert( !Map_IsComplement(pNode) );
+    if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned
+        return pNode->nRefAct[fPhase]++;
+    assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned
+    return pNode->nRefAct[2]++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Decrements the actual reference counter of a phase.]
+
+  Description [Returns the new reference counter.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_NodeDecRefPhaseAct( Map_Node_t * pNode, int fPhase )
+{
+    assert( !Map_IsComplement(pNode) );
+    if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned
+        return --pNode->nRefAct[fPhase];
+    assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned
+    return --pNode->nRefAct[2];
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the estimated reference counter for the PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingEstimateRefsInit( Map_Man_t * p )
+{
+    Map_Node_t * pNode;
+    int i;
+    for ( i = 0; i < p->vMapObjs->nSize; i++ )
+    {
+        pNode = p->vMapObjs->pArray[i];
+//        pNode->nRefEst[0] = pNode->nRefEst[1] = ((float)pNode->nRefs)*(float)2.0;
+        pNode->nRefEst[0] = pNode->nRefEst[1] = pNode->nRefEst[2] = ((float)pNode->nRefs);
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the estimated reference counter.]
+
+  Description [When this procedure is called for the first time,
+  the reference counter is estimated from the AIG. Otherwise, it is
+  a linear combination of reference counters in the last two iterations.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingEstimateRefs( Map_Man_t * p )
+{
+    Map_Node_t * pNode;
+    int i;
+    for ( i = 0; i < p->vMapObjs->nSize; i++ )
+    {
+        pNode = p->vMapObjs->pArray[i];
+//        pNode->nRefEst[0] = (float)((2.0 * pNode->nRefEst[0] + 1.0 * pNode->nRefAct[0]) / 3.0);
+//        pNode->nRefEst[1] = (float)((2.0 * pNode->nRefEst[1] + 1.0 * pNode->nRefAct[1]) / 3.0);
+//        pNode->nRefEst[2] = (float)((2.0 * pNode->nRefEst[2] + 1.0 * pNode->nRefAct[2]) / 3.0);
+        pNode->nRefEst[0] = (float)((3.0 * pNode->nRefEst[0] + 1.0 * pNode->nRefAct[0]) / 4.0);
+        pNode->nRefEst[1] = (float)((3.0 * pNode->nRefEst[1] + 1.0 * pNode->nRefAct[1]) / 4.0);
+        pNode->nRefEst[2] = (float)((3.0 * pNode->nRefEst[2] + 1.0 * pNode->nRefAct[2]) / 4.0);
+    }
+}
+
+/**function*************************************************************
+
+  synopsis    [Computes the area flow of the cut.]
+
+  description [Computes the area flow of the cut if it is implemented using 
+  the best supergate with the best phase.]
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Map_CutGetAreaFlow( Map_Cut_t * pCut, int fPhase )
+{
+    Map_Match_t * pM = pCut->M + fPhase;
+    Map_Super_t * pSuper = pM->pSuperBest;
+    unsigned uPhaseTot = pM->uPhaseBest;
+    Map_Cut_t * pCutFanin;
+    float aFlowRes, aFlowFanin, nRefs;
+    int i, fPinPhasePos;
+
+    // start the resulting area flow
+    aFlowRes = pSuper->Area;
+    // iterate through the leaves
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        // get the phase of this fanin
+        fPinPhasePos = ((uPhaseTot & (1 << i)) == 0);
+        // get the cut implementing this phase of the fanin
+        pCutFanin = pCut->ppLeaves[i]->pCutBest[fPinPhasePos];
+        // if the cut is not available, we have to use the opposite phase
+        if ( pCutFanin == NULL )
+        {
+            fPinPhasePos = !fPinPhasePos;
+            pCutFanin = pCut->ppLeaves[i]->pCutBest[fPinPhasePos];
+        }
+        aFlowFanin = pCutFanin->M[fPinPhasePos].AreaFlow; // ignores the area of the interter
+        // get the fanout count of the cut in the given phase
+        nRefs = Map_NodeReadRefPhaseEst( pCut->ppLeaves[i], fPinPhasePos );
+        // if the node does no fanout, assume fanout count equal to 1
+        if ( nRefs == (float)0.0 )
+            nRefs = (float)1.0;
+        // add the area flow due to the fanin
+        aFlowRes += aFlowFanin / nRefs;
+    }
+    pM->AreaFlow = aFlowRes;
+    return aFlowRes;
+}
+
+
+/**function*************************************************************
+
+  synopsis    [References or dereferences the cut.]
+
+  description [This reference part is similar to Cudd_NodeReclaim(). 
+  The dereference part is similar to Cudd_RecursiveDeref().]
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Map_CutRefDeref( Map_Cut_t * pCut, int fPhase, int fReference )
+{
+    Map_Node_t * pNodeChild;
+    Map_Cut_t * pCutChild;
+    float aArea;
+    int i, fPhaseChild;
+//    int nRefs;
+
+    // consider the elementary variable
+    if ( pCut->nLeaves == 1 )
+        return 0;
+    // start the area of this cut
+    aArea = Map_CutGetRootArea( pCut, fPhase );
+    // go through the children
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        pNodeChild  = pCut->ppLeaves[i];
+        fPhaseChild = Map_CutGetLeafPhase( pCut, fPhase, i );
+        // get the reference counter of the child
+/*
+        // this code does not take inverters into account
+        // the quality of area recovery seems to always be a little worse
+        if ( fReference )
+            nRefs = Map_NodeIncRefPhaseAct( pNodeChild, fPhaseChild );
+        else
+            nRefs = Map_NodeDecRefPhaseAct( pNodeChild, fPhaseChild );
+        assert( nRefs >= 0 );
+        // skip if the child was already reference before
+        if ( nRefs > 0 )
+            continue;
+*/
+
+        if ( fReference )
+        {
+            if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present
+            {
+                // if this phase of the node is referenced, there is no recursive call
+                pNodeChild->nRefAct[2]++;
+                if ( pNodeChild->nRefAct[fPhaseChild]++ > 0 )
+                    continue;
+            }
+            else // only one phase is present
+            {
+                // inverter should be added if the phase
+                // (a) has no reference and (b) is implemented using other phase
+                if ( pNodeChild->nRefAct[fPhaseChild]++ == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL )
+                    aArea += pNodeChild->p->pSuperLib->AreaInv;
+                // if the node is referenced, there is no recursive call
+                if ( pNodeChild->nRefAct[2]++ > 0 )
+                    continue;
+            }
+        }
+        else
+        {
+            if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present
+            {
+                // if this phase of the node is referenced, there is no recursive call
+                --pNodeChild->nRefAct[2];
+                if ( --pNodeChild->nRefAct[fPhaseChild] > 0 )
+                    continue;
+            }
+            else // only one phase is present
+            {
+                // inverter should be added if the phase
+                // (a) has no reference and (b) is implemented using other phase
+                if ( --pNodeChild->nRefAct[fPhaseChild] == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL )
+                    aArea += pNodeChild->p->pSuperLib->AreaInv;
+                // if the node is referenced, there is no recursive call
+                if ( --pNodeChild->nRefAct[2] > 0 )
+                    continue;
+            }
+            assert( pNodeChild->nRefAct[fPhaseChild] >= 0 );
+        }
+
+        // get the child cut
+        pCutChild = pNodeChild->pCutBest[fPhaseChild];
+        // if the child does not have this phase mapped, take the opposite phase
+        if ( pCutChild == NULL )
+        {
+            fPhaseChild = !fPhaseChild;
+            pCutChild   = pNodeChild->pCutBest[fPhaseChild];
+        }
+        // reference and compute area recursively
+        aArea += Map_CutRefDeref( pCutChild, fPhaseChild, fReference );
+    }
+    return aArea;
+}
+
+/**function*************************************************************
+
+  synopsis    [Computes the exact area associated with the cut.]
+
+  description [Assumes that the cut is referenced.]
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Map_CutGetAreaRefed( Map_Cut_t * pCut, int fPhase )
+{
+    float aResult, aResult2;
+    aResult2 = Map_CutRefDeref( pCut, fPhase, 0 ); // dereference
+    aResult  = Map_CutRefDeref( pCut, fPhase, 1 ); // reference
+//    assert( aResult == aResult2 );
+    return aResult;
+}
+
+/**function*************************************************************
+
+  synopsis    [Computes the exact area associated with the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Map_CutGetAreaDerefed( Map_Cut_t * pCut, int fPhase )
+{
+    float aResult, aResult2;
+    aResult2 = Map_CutRefDeref( pCut, fPhase, 1 ); // reference
+    aResult  = Map_CutRefDeref( pCut, fPhase, 0 ); // dereference
+//    assert( aResult == aResult2 );
+    return aResult;
+}
+
+/**function*************************************************************
+
+  synopsis    [References the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Map_CutRef( Map_Cut_t * pCut, int fPhase )
+{
+    return Map_CutRefDeref( pCut, fPhase, 1 ); // reference
+}
+
+/**function*************************************************************
+
+  synopsis    [Dereferences the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Map_CutDeref( Map_Cut_t * pCut, int fPhase )
+{
+    return Map_CutRefDeref( pCut, fPhase, 0 ); // dereference
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes actual reference counters.]
+
+  Description [Collects the nodes used in the mapping in array pMan->vMapping.
+  Nodes are collected in reverse topological order to facilitate the 
+  computation of required times.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingSetRefs_rec( Map_Man_t * pMan, Map_Node_t * pNode )
+{
+    Map_Cut_t * pCut;
+    Map_Node_t * pNodeR;
+    unsigned uPhase;
+    int i, fPhase, fInvPin;
+    // get the regular node and its phase
+    pNodeR = Map_Regular(pNode);
+    fPhase = !Map_IsComplement(pNode);
+    pNodeR->nRefAct[2]++;
+    // quit if the node was already visited in this phase
+    if ( pNodeR->nRefAct[fPhase]++ )
+        return;
+    // quit if this is a PI node
+    if ( Map_NodeIsVar(pNodeR) )
+        return;
+    // propagate through buffer
+    if ( Map_NodeIsBuf(pNodeR) )
+    {
+        Map_MappingSetRefs_rec( pMan, Map_NotCond(pNodeR->p1, Map_IsComplement(pNode)) );
+        return;
+    }
+    assert( Map_NodeIsAnd(pNode) );
+    // get the cut implementing this or opposite polarity
+    pCut = pNodeR->pCutBest[fPhase];
+    if ( pCut == NULL )
+    {
+        fPhase = !fPhase;
+        pCut   = pNodeR->pCutBest[fPhase];
+    }
+    // visit the transitive fanin
+    uPhase = pCut->M[fPhase].uPhaseBest;
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        fInvPin = ((uPhase & (1 << i)) > 0);
+        Map_MappingSetRefs_rec( pMan, Map_NotCond(pCut->ppLeaves[i], fInvPin) );
+    }
+}
+void Map_MappingSetRefs( Map_Man_t * pMan )
+{
+    Map_Node_t * pNode;
+    int i;
+    // clean all references
+    for ( i = 0; i < pMan->vMapObjs->nSize; i++ )
+    {
+        pNode = pMan->vMapObjs->pArray[i];
+        pNode->nRefAct[0] = 0;
+        pNode->nRefAct[1] = 0;
+        pNode->nRefAct[2] = 0;
+    }
+    // visit nodes reachable from POs in the DFS order through the best cuts
+    for ( i = 0; i < pMan->nOutputs; i++ )
+    {
+        pNode = pMan->pOutputs[i];
+        if ( !Map_NodeIsConst(pNode) )
+            Map_MappingSetRefs_rec( pMan, pNode );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the array of mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Map_MappingGetArea( Map_Man_t * pMan )
+{
+    Map_Node_t * pNode;
+    float Area = 0.0;
+    int i;
+    for ( i = 0; i < pMan->vMapObjs->nSize; i++ )
+    {
+        pNode = pMan->vMapObjs->pArray[i];
+        if ( pNode->nRefAct[2] == 0 )
+            continue;
+        if ( Map_NodeIsBuf(pNode) )
+            continue;
+        // at least one phase has the best cut assigned
+        assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL );
+        // at least one phase is used in the mapping
+        assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 );
+        // compute the array due to the supergate
+        if ( Map_NodeIsAnd(pNode) )
+        {
+            // count area of the negative phase
+            if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) )
+                Area += pNode->pCutBest[0]->M[0].pSuperBest->Area;
+            // count area of the positive phase
+            if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) )
+                Area += pNode->pCutBest[1]->M[1].pSuperBest->Area;
+        }
+        // count area of the interver if we need to implement one phase with another phase
+        if ( (pNode->pCutBest[0] == NULL && pNode->nRefAct[0] > 0) || 
+             (pNode->pCutBest[1] == NULL && pNode->nRefAct[1] > 0) )
+            Area += pMan->pSuperLib->AreaInv;
+    }
+    // add buffers for each CO driven by a CI
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        if ( Map_NodeIsVar(pMan->pOutputs[i]) && !Map_IsComplement(pMan->pOutputs[i]) )
+            Area += pMan->pSuperLib->AreaBuf;
+    return Area;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/mapperSuper.c b/abc-build/src/map/mapper/mapperSuper.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperSuper.c
@@ -0,0 +1,456 @@
+/**CFile****************************************************************
+
+  FileName    [mapperSuper.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapperSuper.c,v 1.6 2005/01/23 06:59:44 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int           Map_LibraryReadFile( Map_SuperLib_t * pLib, FILE * pFile );
+static Map_Super_t * Map_LibraryReadGate( Map_SuperLib_t * pLib, char * pBuffer, int nVars );
+static int           Map_LibraryTruthVerify( Map_SuperLib_t * pLib, Map_Super_t * pGate );
+static void          Map_LibraryComputeTruth( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthRes[] );
+static void          Map_LibraryComputeTruth_rec( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthsIn[][2], unsigned uTruthRes[] );
+static void          Map_LibraryPrintClasses( Map_SuperLib_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the supergate library from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_LibraryRead( Map_SuperLib_t * pLib, char * pFileName )
+{
+    FILE * pFile;
+    int Status;
+    // read the beginning of the file
+    assert( pLib->pGenlib == NULL );
+    pFile = fopen( pFileName, "r" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open input file \"%s\".\n", pFileName );
+        return 0;
+    }
+    Status = Map_LibraryReadFile( pLib, pFile );
+    fclose( pFile );
+//    Map_LibraryPrintClasses( pLib );
+    return Status;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the library file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_LibraryReadFile( Map_SuperLib_t * pLib, FILE * pFile )
+{
+    ProgressBar * pProgress;
+    char pBuffer[5000];
+    FILE * pFileGen;
+    Map_Super_t * pGate;
+    char * pTemp = NULL; // Suppress "might be used uninitialized"
+    char * pLibName;
+    int nCounter, nGatesTotal;
+    unsigned uCanon[2];
+    int RetValue;
+
+    // skip empty and comment lines
+    while ( fgets( pBuffer, 2000, pFile ) != NULL )
+    {
+        // skip leading spaces
+        for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ );
+        // skip comment lines and empty lines
+        if ( *pTemp != 0 && *pTemp != '#' )
+            break;
+    }
+
+    // get the genlib file name
+    pLibName = strtok( pTemp, " \t\r\n" );
+    if ( strcmp( pLibName, "GATE" ) == 0 )
+    {
+        printf( "The input file \"%s\" looks like a genlib file and not a supergate library file.\n", pLib->pName );
+        return 0;
+    }
+    pFileGen = fopen( pLibName, "r" );
+    if ( pFileGen == NULL )
+    {
+        printf( "Cannot open the genlib file \"%s\".\n", pLibName );
+        return 0;
+    }
+    fclose( pFileGen );
+
+    // read the genlib library
+    pLib->pGenlib = Mio_LibraryRead( pLibName, NULL, 0, 0 );
+    if ( pLib->pGenlib == NULL )
+    {
+        printf( "Cannot read genlib file \"%s\".\n", pLibName );
+        return 0;
+    }
+
+    // read the number of variables
+    RetValue = fscanf( pFile, "%d\n", &pLib->nVarsMax );
+    if ( pLib->nVarsMax < 2 || pLib->nVarsMax > 10 )
+    {
+        printf( "Suspicious number of variables (%d).\n", pLib->nVarsMax );
+        return 0;
+    }
+
+    // read the number of gates
+    RetValue = fscanf( pFile, "%d\n", &nGatesTotal );
+    if ( nGatesTotal < 1 || nGatesTotal > 10000000 )
+    {
+        printf( "Suspicious number of gates (%d).\n", nGatesTotal );
+        return 0;
+    }
+
+    // read the lines
+    nCounter = 0;
+    pProgress = Extra_ProgressBarStart( stdout, nGatesTotal );
+    while ( fgets( pBuffer, 5000, pFile ) != NULL )
+    {
+        for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ );
+        if ( pTemp[0] == '\0' )
+            continue;
+        // get the gate
+        pGate = Map_LibraryReadGate( pLib, pTemp, pLib->nVarsMax );
+        assert( pGate->Num == nCounter + 1 );
+        // count the number of parantheses in the formula - this is the number of gates
+        for ( pTemp = pGate->pFormula; *pTemp; pTemp++ )
+            pGate->nGates += (*pTemp == '(');
+        // verify the truth table
+        assert( Map_LibraryTruthVerify(pLib, pGate) );
+
+        // find the N-canonical form of this supergate
+        pGate->nPhases = Map_CanonComputeSlow( pLib->uTruths, pLib->nVarsMax, pLib->nVarsMax, pGate->uTruth, pGate->uPhases, uCanon );
+        // add the supergate into the table by its N-canonical table
+        Map_SuperTableInsertC( pLib->tTableC, uCanon, pGate );
+        // update the progress bar
+        Extra_ProgressBarUpdate( pProgress, ++nCounter, NULL );
+    }
+    Extra_ProgressBarStop( pProgress );
+    pLib->nSupersAll = nCounter;
+    if ( nCounter != nGatesTotal )
+        printf( "The number of gates read (%d) is different what the file says (%d).\n", nGatesTotal, nCounter );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Super_t * Map_LibraryReadGate( Map_SuperLib_t * pLib, char * pBuffer, int nVars )
+{
+    Map_Super_t * pGate;
+    char * pTemp;
+    int i;
+
+    // start and clean the gate
+    pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers );
+    memset( pGate, 0, sizeof(Map_Super_t) );
+
+    // read the number
+    pTemp = strtok( pBuffer, " " );
+    pGate->Num = atoi(pTemp);
+
+    // read the signature
+    pTemp = strtok( NULL, " " );
+    if ( pLib->nVarsMax < 6 )
+    {
+        pGate->uTruth[0] = Extra_ReadBinary(pTemp);
+        pGate->uTruth[1] = 0;
+    }
+    else
+    {
+        pGate->uTruth[0] = Extra_ReadBinary(pTemp+32);
+        pTemp[32] = 0;
+        pGate->uTruth[1] = Extra_ReadBinary(pTemp);
+    }
+
+    // read the max delay
+    pTemp = strtok( NULL, " " );
+    pGate->tDelayMax.Rise = (float)atof(pTemp);
+    pGate->tDelayMax.Fall = pGate->tDelayMax.Rise;
+
+    // read the pin-to-pin delay
+    for ( i = 0; i < nVars; i++ )
+    {
+        pTemp = strtok( NULL, " " );
+        pGate->tDelaysR[i].Rise = (float)atof(pTemp);
+        pGate->tDelaysF[i].Fall = pGate->tDelaysR[i].Rise;
+    }
+
+    // read the area
+    pTemp = strtok( NULL, " " );
+    pGate->Area = (float)atof(pTemp);
+
+    // the rest is the gate name
+    pTemp = strtok( NULL, " \r\n" );
+    if ( strlen(pTemp) == 0 )
+        printf( "A gate name is empty.\n" );
+
+    // save the gate name
+    pGate->pFormula = Extra_MmFlexEntryFetch( pLib->mmForms, strlen(pTemp) + 1 );
+    strcpy( pGate->pFormula, pTemp );
+
+    // the rest is the gate name
+    pTemp = strtok( NULL, " \n\0" );
+    if ( pTemp != NULL )
+        printf( "The following trailing symbols found \"%s\".\n", pTemp );
+    return pGate;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one step of parsing the formula into parts.]
+
+  Description [This function will eventually be replaced when the
+  tree-supergate library representation will become standard.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Map_LibraryReadFormulaStep( char * pFormula, char * pStrings[], int * pnStrings )
+{
+    char * pName, * pPar1, * pPar2, * pCur;
+    int nStrings, CountPars;
+
+    // skip leading spaces
+    for ( pName = pFormula; *pName && *pName == ' '; pName++ );
+    assert( *pName );
+    // find the first opening paranthesis
+    for ( pPar1 = pName; *pPar1 && *pPar1 != '('; pPar1++ );
+    if ( *pPar1 == 0 )
+    {
+        *pnStrings = 0;
+        return pName;
+    }
+    // overwrite it with space
+    assert( *pPar1 == '(' );
+    *pPar1 = 0;
+    // find the corresponding closing paranthesis
+    for ( CountPars = 1, pPar2 = pPar1 + 1; *pPar2 && CountPars; pPar2++ )
+        if ( *pPar2 == '(' )
+            CountPars++;
+        else if ( *pPar2 == ')' )
+            CountPars--;
+    pPar2--;
+    assert( CountPars == 0 );
+    // overwrite it with space
+    assert( *pPar2 == ')' );
+    *pPar2 = 0;
+    // save the intervals between the commas
+    nStrings = 0;
+    pCur = pPar1 + 1;
+    while ( 1 )
+    {
+        // save the current string
+        pStrings[ nStrings++ ] = pCur;
+        // find the beginning of the next string
+        for ( CountPars = 0; *pCur && (CountPars || *pCur != ','); pCur++ )
+            if ( *pCur == '(' )
+                CountPars++;
+            else if ( *pCur == ')' )
+                CountPars--;
+        if ( *pCur == 0 )
+            break;
+        assert( *pCur == ',' );
+        *pCur = 0;
+        pCur++;
+    }
+    // save the results and return
+    *pnStrings = nStrings;
+    return pName;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the truth table of the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_LibraryTruthVerify( Map_SuperLib_t * pLib, Map_Super_t * pGate )
+{
+    unsigned uTruthRes[2];
+    Map_LibraryComputeTruth( pLib, pGate->pFormula, uTruthRes );
+    if ( uTruthRes[0] != pGate->uTruth[0] || uTruthRes[1] != pGate->uTruth[1] )
+        return 0;
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the functionality of the supergate.]
+
+  Description [This procedure is useful for verification the supergate 
+  library. The truth table derived by this procedure should be the same
+  as the one contained in the original supergate file.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_LibraryComputeTruth( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthRes[] )
+{
+    char Buffer[1000];
+    strcpy( Buffer, pFormula );
+    Map_LibraryComputeTruth_rec( pLib, Buffer, pLib->uTruths, uTruthRes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the functionality of the supergate.]
+
+  Description [This procedure is useful for verification the supergate 
+  library. The truth table derived by this procedure should be the same
+  as the one contained in the original supergate file.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_LibraryComputeTruth_rec( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthsIn[][2], unsigned uTruthRes[] )
+{
+    Mio_Gate_t * pMioGate;
+    char * pGateName, * pStrings[6];
+    unsigned uTruthsFanins[6][2];
+    int nStrings, i;
+
+    // perform one step parsing of the formula
+    // detect the root gate name, the next-step strings, and their number
+    pGateName = Map_LibraryReadFormulaStep( pFormula, pStrings, &nStrings );
+    if ( nStrings == 0 ) // elementary variable
+    {
+        assert( pGateName[0] - 'a' < pLib->nVarsMax );
+        uTruthRes[0] = uTruthsIn[pGateName[0] - 'a'][0];
+        uTruthRes[1] = uTruthsIn[pGateName[0] - 'a'][1];
+        return;
+    }
+    // derive the functionality of the fanins
+    for ( i = 0; i < nStrings; i++ )
+        Map_LibraryComputeTruth_rec( pLib, pStrings[i], uTruthsIn, uTruthsFanins[i] );
+    // get the root supergate
+    pMioGate = Mio_LibraryReadGateByName( pLib->pGenlib, pGateName, NULL );
+    if ( pMioGate == NULL )
+        printf( "A supergate contains gate \"%s\" that is not in \"%s\".\n", pGateName, Mio_LibraryReadName(pLib->pGenlib) ); 
+    // derive the functionality of the output of the supergate
+    Mio_DeriveTruthTable( pMioGate, uTruthsFanins, nStrings, pLib->nVarsMax, uTruthRes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_LibraryPrintSupergate( Map_Super_t * pGate )
+{
+    printf( "%5d : ",  pGate->nUsed );
+    printf( "%5d   ",  pGate->Num );
+    printf( "A = %5.2f   ",  pGate->Area );
+    printf( "D = %5.2f/%5.2f/%5.2f   ", pGate->tDelayMax.Rise, pGate->tDelayMax.Fall, pGate->tDelayMax.Worst );
+    printf( "%s",    pGate->pFormula );
+    printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints N-classes of supergates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_LibraryPrintClasses( Map_SuperLib_t * p )
+{
+/*
+    st__generator * gen;
+    Map_Super_t * pSuper, * pSuper2;
+    unsigned Key, uTruth;
+    int Counter = 0;
+    // copy all the supergates into one array
+    st__foreach_item( p->tSuplib, gen, (char **)&Key, (char **)&pSuper )
+    {
+        for ( pSuper2 = pSuper; pSuper2; pSuper2 = pSuper2->pNext )
+        {
+            uTruth = pSuper2->Phase;
+            Extra_PrintBinary( stdout, &uTruth, 5 );
+            printf( "  %5d   ",  pSuper2->Num );
+            printf( "%s",    pSuper2->pFormula );
+            printf( "\n" );
+        }
+        printf( "\n" );
+        if ( ++ Counter == 100 )
+            break;
+    }
+*/
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/mapperSwitch.c b/abc-build/src/map/mapper/mapperSwitch.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperSwitch.c
@@ -0,0 +1,229 @@
+/**CFile****************************************************************
+
+  FileName    [mapperSwitch.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: mapperSwitch.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static float Map_SwitchCutRefDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, int fReference );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**function*************************************************************
+
+  synopsis    [Computes the exact area associated with the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Map_SwitchCutGetDerefed( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase )
+{
+    float aResult, aResult2;
+//    assert( pNode->Switching > 0 );
+    aResult2 = Map_SwitchCutRefDeref( pNode, pCut, fPhase, 1 ); // reference
+    aResult  = Map_SwitchCutRefDeref( pNode, pCut, fPhase, 0 ); // dereference
+//    assert( aResult == aResult2 );
+    return aResult;
+}
+
+/**function*************************************************************
+
+  synopsis    [References the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Map_SwitchCutRef( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase )
+{
+    return Map_SwitchCutRefDeref( pNode, pCut, fPhase, 1 ); // reference
+}
+
+/**function*************************************************************
+
+  synopsis    [References the cut.]
+
+  description []
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Map_SwitchCutDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase )
+{
+    return Map_SwitchCutRefDeref( pNode, pCut, fPhase, 0 ); // dereference
+}
+
+/**function*************************************************************
+
+  synopsis    [References or dereferences the cut.]
+
+  description [This reference part is similar to Cudd_NodeReclaim(). 
+  The dereference part is similar to Cudd_RecursiveDeref().]
+               
+  sideeffects []
+
+  seealso     []
+
+***********************************************************************/
+float Map_SwitchCutRefDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, int fReference )
+{
+    Map_Node_t * pNodeChild;
+    Map_Cut_t * pCutChild;
+    float aSwitchActivity;
+    int i, fPhaseChild;
+
+    // start switching activity for the node
+    aSwitchActivity = pNode->Switching;
+    // consider the elementary variable
+    if ( pCut->nLeaves == 1 )
+        return aSwitchActivity;
+
+    // go through the children
+    assert( pCut->M[fPhase].pSuperBest );
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        pNodeChild  = pCut->ppLeaves[i];
+        fPhaseChild = Map_CutGetLeafPhase( pCut, fPhase, i );
+        // get the reference counter of the child
+
+        if ( fReference )
+        {
+            if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present
+            {
+                // if this phase of the node is referenced, there is no recursive call
+                pNodeChild->nRefAct[2]++;
+                if ( pNodeChild->nRefAct[fPhaseChild]++ > 0 )
+                    continue;
+            }
+            else // only one phase is present
+            {
+                // inverter should be added if the phase
+                // (a) has no reference and (b) is implemented using other phase
+                if ( pNodeChild->nRefAct[fPhaseChild]++ == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL )
+                    aSwitchActivity += pNodeChild->Switching; // inverter switches the same as the node
+                // if the node is referenced, there is no recursive call
+                if ( pNodeChild->nRefAct[2]++ > 0 )
+                    continue;
+            }
+        }
+        else
+        {
+            if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present
+            {
+                // if this phase of the node is referenced, there is no recursive call
+                --pNodeChild->nRefAct[2];
+                if ( --pNodeChild->nRefAct[fPhaseChild] > 0 )
+                    continue;
+            }
+            else // only one phase is present
+            {
+                // inverter should be added if the phase
+                // (a) has no reference and (b) is implemented using other phase
+                if ( --pNodeChild->nRefAct[fPhaseChild] == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL )
+                    aSwitchActivity += pNodeChild->Switching; // inverter switches the same as the node
+                // if the node is referenced, there is no recursive call
+                if ( --pNodeChild->nRefAct[2] > 0 )
+                    continue;
+            }
+            assert( pNodeChild->nRefAct[fPhaseChild] >= 0 );
+        }
+
+        // get the child cut
+        pCutChild = pNodeChild->pCutBest[fPhaseChild];
+        // if the child does not have this phase mapped, take the opposite phase
+        if ( pCutChild == NULL )
+        {
+            fPhaseChild = !fPhaseChild;
+            pCutChild   = pNodeChild->pCutBest[fPhaseChild];
+        }
+        // reference and compute area recursively
+        aSwitchActivity += Map_SwitchCutRefDeref( pNodeChild, pCutChild, fPhaseChild, fReference );
+    }
+    return aSwitchActivity;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the array of mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Map_MappingGetSwitching( Map_Man_t * pMan )
+{
+    Map_Node_t * pNode;
+    float Switch = 0.0;
+    int i;
+    for ( i = 0; i < pMan->vMapObjs->nSize; i++ )
+    {
+        pNode = pMan->vMapObjs->pArray[i];
+        if ( pNode->nRefAct[2] == 0 )
+            continue;
+        // at least one phase has the best cut assigned
+        assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL );
+        // at least one phase is used in the mapping
+        assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 );
+        // compute the array due to the supergate
+        if ( Map_NodeIsAnd(pNode) )
+        {
+            // count switching of the negative phase
+            if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) )
+                Switch += pNode->Switching;
+            // count switching of the positive phase
+            if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) )
+                Switch += pNode->Switching;
+        }
+        // count switching of the interver if we need to implement one phase with another phase
+        if ( (pNode->pCutBest[0] == NULL && pNode->nRefAct[0] > 0) || 
+             (pNode->pCutBest[1] == NULL && pNode->nRefAct[1] > 0) )
+            Switch += pNode->Switching; // inverter switches the same as the node
+    }
+    // add buffers for each CO driven by a CI
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        if ( Map_NodeIsVar(pMan->pOutputs[i]) && !Map_IsComplement(pMan->pOutputs[i]) )
+            Switch += pMan->pOutputs[i]->Switching;
+    return Switch;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/mapperTable.c b/abc-build/src/map/mapper/mapperTable.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperTable.c
@@ -0,0 +1,407 @@
+/**CFile****************************************************************
+
+  FileName    [mapperTable.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapperTable.c,v 1.6 2005/01/23 06:59:44 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// the table function for the tables
+#define  MAP_TABLE_HASH(u1,u2,nSize)  (((u1) + 2003 * (u2)) % nSize)
+
+static void Map_SuperTableResize( Map_HashTable_t * pLib );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the hash table for supergates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_HashTable_t * Map_SuperTableCreate( Map_SuperLib_t * pLib )
+{
+    Map_HashTable_t * p;
+    // allocate the table
+    p = ABC_ALLOC( Map_HashTable_t, 1 );
+    memset( p, 0, sizeof(Map_HashTable_t) );
+    p->mmMan = pLib->mmEntries;
+    // allocate and clean the bins
+    p->nBins = Abc_PrimeCudd(20000);
+    p->pBins = ABC_ALLOC( Map_HashEntry_t *, p->nBins );
+    memset( p->pBins, 0, sizeof(Map_HashEntry_t *) * p->nBins );
+    return p;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the supergate hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_SuperTableFree( Map_HashTable_t * p )
+{
+    ABC_FREE( p->pBins );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts a new entry into the hash table.]
+
+  Description [This function inserts the new gate (pGate), which will be
+  accessible through its canonical form (uTruthC).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_SuperTableInsertC( Map_HashTable_t * p, unsigned uTruthC[], Map_Super_t * pGate )
+{
+    Map_HashEntry_t * pEnt;
+    unsigned Key;
+    // resize the table
+    if ( p->nEntries >= 2 * p->nBins )
+        Map_SuperTableResize( p );
+    // check if another supergate with the same canonical form exists
+    Key = MAP_TABLE_HASH( uTruthC[0], uTruthC[1], p->nBins );
+    for ( pEnt = p->pBins[Key]; pEnt; pEnt = pEnt->pNext )
+        if ( pEnt->uTruth[0] == uTruthC[0] && pEnt->uTruth[1] == uTruthC[1] )
+            break;
+    // create a new entry if it does not exist
+    if ( pEnt == NULL )
+    {
+        // add the new entry to the table
+        pEnt = (Map_HashEntry_t *)Extra_MmFixedEntryFetch( p->mmMan );
+        memset( pEnt, 0, sizeof(Map_HashEntry_t) );
+        pEnt->uTruth[0] = uTruthC[0];
+        pEnt->uTruth[1] = uTruthC[1];
+        // add the hash table entry to the corresponding linked list in the table
+        pEnt->pNext   = p->pBins[Key];
+        p->pBins[Key] = pEnt;
+        p->nEntries++;
+    }
+    // add the supergate to the entry
+    pGate->pNext = pEnt->pGates;
+    pEnt->pGates = pGate;
+    return 0;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts a new entry into the library.]
+
+  Description [This function inserts the new gate (pGate), which will be
+  accessible through its unfolded function (uTruth).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_SuperTableInsert( Map_HashTable_t * p, unsigned uTruth[], Map_Super_t * pGate, unsigned uPhase )
+{
+    Map_HashEntry_t * pEnt;
+    unsigned Key;
+    // resize the table
+    if ( p->nEntries >= 2 * p->nBins )
+        Map_SuperTableResize( p );
+    // check if this entry already exists
+    Key = MAP_TABLE_HASH( uTruth[0], uTruth[1], p->nBins );
+    for ( pEnt = p->pBins[Key]; pEnt; pEnt = pEnt->pNext )
+        if ( pEnt->uTruth[0] == uTruth[0] && pEnt->uTruth[1] == uTruth[1] )
+            return 1;
+    // add the new hash table entry to the table
+    pEnt = (Map_HashEntry_t *)Extra_MmFixedEntryFetch( p->mmMan );
+    memset( pEnt, 0, sizeof(Map_HashEntry_t) );
+    pEnt->uTruth[0] = uTruth[0];
+    pEnt->uTruth[1] = uTruth[1];
+    pEnt->pGates    = pGate;
+    pEnt->uPhase    = uPhase;
+    // add the hash table to the corresponding linked list in the table
+    pEnt->pNext   = p->pBins[Key];
+    p->pBins[Key] = pEnt;
+    p->nEntries++;
+/*
+printf( "Adding gate: %10u ", Key );
+Map_LibraryPrintSupergate( pGate );
+Extra_PrintBinary( stdout, uTruth, 32 );
+printf( "\n" );
+*/
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Looks up an entry in the library.]
+
+  Description [This function looks up the function, given by its truth table,
+  and return two things: (1) the linked list of supergates, which can implement
+  the functions of this N-class; (2) the phase, which should be applied to the
+  given function, in order to derive the canonical form of this N-class.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Super_t * Map_SuperTableLookupC( Map_SuperLib_t * p, unsigned uTruth[] )
+{
+    Map_HashEntry_t * pEnt;
+    unsigned Key;
+    Key = MAP_TABLE_HASH( uTruth[0], uTruth[1], p->tTableC->nBins );
+    for ( pEnt = p->tTableC->pBins[Key]; pEnt; pEnt = pEnt->pNext )
+        if ( pEnt->uTruth[0] == uTruth[0] && pEnt->uTruth[1] == uTruth[1] )
+            return pEnt->pGates;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Looks up an entry in the library.]
+
+  Description [This function looks up the function, given by its truth table,
+  and return two things: (1) the linked list of supergates, which can implement
+  the functions of this N-class; (2) the phase, which should be applied to the
+  given function, in order to derive the canonical form of this N-class.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Super_t * Map_SuperTableLookup( Map_HashTable_t * p, unsigned uTruth[], unsigned * puPhase )
+{
+    Map_HashEntry_t * pEnt;
+    unsigned Key;
+    Key = MAP_TABLE_HASH( uTruth[0], uTruth[1], p->nBins );
+    for ( pEnt = p->pBins[Key]; pEnt; pEnt = pEnt->pNext )
+        if ( pEnt->uTruth[0] == uTruth[0] && pEnt->uTruth[1] == uTruth[1] )
+        {
+            *puPhase = pEnt->uPhase;
+            return pEnt->pGates;
+        }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_SuperTableResize( Map_HashTable_t * p )
+{
+    Map_HashEntry_t ** pBinsNew;
+    Map_HashEntry_t * pEnt, * pEnt2;
+    int nBinsNew, Counter, i;
+    unsigned Key;
+    // get the new table size
+    nBinsNew = Abc_PrimeCudd(2 * p->nBins); 
+    // allocate a new array
+    pBinsNew = ABC_ALLOC( Map_HashEntry_t *, nBinsNew );
+    memset( pBinsNew, 0, sizeof(Map_HashEntry_t *) * nBinsNew );
+    // rehash the entries from the old table
+    Counter = 0;
+    for ( i = 0; i < p->nBins; i++ )
+        for ( pEnt = p->pBins[i], pEnt2 = pEnt? pEnt->pNext: NULL; pEnt; 
+              pEnt = pEnt2, pEnt2 = pEnt? pEnt->pNext: NULL )
+        {
+            Key = MAP_TABLE_HASH( pEnt->uTruth[0], pEnt->uTruth[1], nBinsNew );
+            pEnt->pNext   = pBinsNew[Key];
+            pBinsNew[Key] = pEnt;
+            Counter++;
+        }
+    assert( Counter == p->nEntries );
+    // replace the table and the parameters
+    ABC_FREE( p->pBins );
+    p->pBins = pBinsNew;
+    p->nBins = nBinsNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the supergates by the number of times they are used.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_SuperTableCompareSupergates( Map_Super_t ** ppS1, Map_Super_t ** ppS2 )
+{
+    if ( (*ppS1)->nUsed > (*ppS2)->nUsed )
+        return -1;
+    if ( (*ppS1)->nUsed < (*ppS2)->nUsed )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the supergates by the number of times they are used.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_SuperTableCompareGatesInList( Map_Super_t ** ppS1, Map_Super_t ** ppS2 )
+{
+//   if ( (*ppS1)->tDelayMax.Rise > (*ppS2)->tDelayMax.Rise )
+    if ( (*ppS1)->Area > (*ppS2)->Area )
+        return -1;
+//   if ( (*ppS1)->tDelayMax.Rise < (*ppS2)->tDelayMax.Rise )
+    if ( (*ppS1)->Area < (*ppS2)->Area )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts supergates by usefulness and prints out most useful.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_SuperTableSortSupergates( Map_HashTable_t * p, int nSupersMax )
+{
+    Map_HashEntry_t * pEnt;
+    Map_Super_t ** ppSupers;
+    Map_Super_t * pSuper;
+    int nSupers, i;
+
+    // copy all the supergates into one array
+    ppSupers = ABC_ALLOC( Map_Super_t *, nSupersMax );
+    nSupers = 0;
+    for ( i = 0; i < p->nBins; i++ )
+        for ( pEnt = p->pBins[i]; pEnt; pEnt = pEnt->pNext )
+            for ( pSuper = pEnt->pGates; pSuper; pSuper = pSuper->pNext )
+                ppSupers[nSupers++] = pSuper;
+
+    // sort by usage
+    qsort( (void *)ppSupers, nSupers, sizeof(Map_Super_t *), 
+            (int (*)(const void *, const void *)) Map_SuperTableCompareSupergates );
+    assert( Map_SuperTableCompareSupergates( ppSupers, ppSupers + nSupers - 1 ) <= 0 );
+
+    // print out the "top ten"
+//    for ( i = 0; i < nSupers; i++ )
+    for ( i = 0; i < 10; i++ )
+    {
+        if ( ppSupers[i]->nUsed == 0 )
+            break;
+        printf( "%5d : ",        ppSupers[i]->nUsed );
+        printf( "%5d   ",        ppSupers[i]->Num );
+        printf( "A = %5.2f   ",  ppSupers[i]->Area );
+        printf( "D = %5.2f   ",  ppSupers[i]->tDelayMax.Rise );
+        printf( "%s",            ppSupers[i]->pFormula );
+        printf( "\n" );
+    }
+    ABC_FREE( ppSupers );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts supergates by max delay for each truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_SuperTableSortSupergatesByDelay( Map_HashTable_t * p, int nSupersMax )
+{
+    Map_HashEntry_t * pEnt;
+    Map_Super_t ** ppSupers;
+    Map_Super_t * pSuper;
+    int nSupers, i, k;
+
+    ppSupers = ABC_ALLOC( Map_Super_t *, nSupersMax );
+    for ( i = 0; i < p->nBins; i++ )
+        for ( pEnt = p->pBins[i]; pEnt; pEnt = pEnt->pNext )
+        {
+            // collect the gates in this entry
+            nSupers = 0;
+            for ( pSuper = pEnt->pGates; pSuper; pSuper = pSuper->pNext )
+            {
+                // skip supergates, whose root is the AND gate
+//                if ( strcmp( Mio_GateReadName(pSuper->pRoot), "and" ) == 0 )
+//                    continue;
+                ppSupers[nSupers++] = pSuper;
+            }
+            pEnt->pGates = NULL;
+            if ( nSupers == 0 )
+                continue;
+            // sort the gates by delay
+            qsort( (void *)ppSupers, nSupers, sizeof(Map_Super_t *), 
+                    (int (*)(const void *, const void *)) Map_SuperTableCompareGatesInList );
+            assert( Map_SuperTableCompareGatesInList( ppSupers, ppSupers + nSupers - 1 ) <= 0 );
+            // link them in the reverse order
+            for ( k = 0; k < nSupers; k++ )
+            {
+                ppSupers[k]->pNext = pEnt->pGates;
+                pEnt->pGates = ppSupers[k];
+            }
+            // save the number of supergates in the list
+            pEnt->pGates->nSupers = nSupers;
+        }
+    ABC_FREE( ppSupers );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/mapperTime.c b/abc-build/src/map/mapper/mapperTime.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperTime.c
@@ -0,0 +1,438 @@
+/**CFile****************************************************************
+
+  FileName    [mapperTime.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapperTime.c,v 1.3 2005/03/02 02:35:54 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the maximum arrival times.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Map_TimeComputeArrivalMax( Map_Man_t * p )
+{
+    float tReqMax, tReq;
+    int i, fPhase;
+    // get the critical PO arrival time
+    tReqMax = -MAP_FLOAT_LARGE;
+    for ( i = 0; i < p->nOutputs; i++ )
+    {
+        if ( Map_NodeIsConst(p->pOutputs[i]) )
+            continue;
+        fPhase  = !Map_IsComplement(p->pOutputs[i]);
+        tReq    = Map_Regular(p->pOutputs[i])->tArrival[fPhase].Worst;
+        tReqMax = MAP_MAX( tReqMax, tReq );
+    }
+    return tReqMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the arrival times of the cut.]
+
+  Description [Computes the arrival times of the cut if it is implemented using 
+  the given supergate with the given phase. Uses the constraint-type specification
+  of rise/fall arrival times.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Map_TimeCutComputeArrival( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float tWorstLimit )
+{
+    Map_Match_t * pM = pCut->M + fPhase;
+    Map_Super_t * pSuper = pM->pSuperBest;
+    unsigned uPhaseTot = pM->uPhaseBest;
+    Map_Time_t * ptArrRes = &pM->tArrive;
+    Map_Time_t * ptArrIn;
+    int fPinPhase;
+    float tDelay, tExtra;
+    int i;
+
+    tExtra = pNode->p->pNodeDelays ? pNode->p->pNodeDelays[pNode->Num] : 0;
+    ptArrRes->Rise  = ptArrRes->Fall = 0.0;
+    ptArrRes->Worst = MAP_FLOAT_LARGE;
+    for ( i = pCut->nLeaves - 1; i >= 0; i-- )
+    {
+        // get the phase of the given pin
+        fPinPhase = ((uPhaseTot & (1 << i)) == 0);
+        ptArrIn = pCut->ppLeaves[i]->tArrival + fPinPhase;
+
+        // get the rise of the output due to rise of the inputs
+        if ( pSuper->tDelaysR[i].Rise > 0 )
+        {
+            tDelay = ptArrIn->Rise + pSuper->tDelaysR[i].Rise + tExtra;
+            if ( tDelay > tWorstLimit )
+                return MAP_FLOAT_LARGE;
+            if ( ptArrRes->Rise < tDelay )
+                ptArrRes->Rise = tDelay;
+        }
+
+        // get the rise of the output due to fall of the inputs
+        if ( pSuper->tDelaysR[i].Fall > 0 )
+        {
+            tDelay = ptArrIn->Fall + pSuper->tDelaysR[i].Fall + tExtra;
+            if ( tDelay > tWorstLimit )
+                return MAP_FLOAT_LARGE;
+            if ( ptArrRes->Rise < tDelay )
+                ptArrRes->Rise = tDelay;
+        }
+
+        // get the fall of the output due to rise of the inputs
+        if ( pSuper->tDelaysF[i].Rise > 0 )
+        {
+            tDelay = ptArrIn->Rise + pSuper->tDelaysF[i].Rise + tExtra;
+            if ( tDelay > tWorstLimit )
+                return MAP_FLOAT_LARGE;
+            if ( ptArrRes->Fall < tDelay )
+                ptArrRes->Fall = tDelay;
+        }
+
+        // get the fall of the output due to fall of the inputs
+        if ( pSuper->tDelaysF[i].Fall > 0 )
+        {
+            tDelay = ptArrIn->Fall + pSuper->tDelaysF[i].Fall + tExtra;
+            if ( tDelay > tWorstLimit )
+                return MAP_FLOAT_LARGE;
+            if ( ptArrRes->Fall < tDelay )
+                ptArrRes->Fall = tDelay;
+        }
+    }
+    // return the worst-case of rise/fall arrival times
+    ptArrRes->Worst = MAP_MAX(ptArrRes->Rise, ptArrRes->Fall);
+    return ptArrRes->Worst;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_TimePropagateRequiredPhase( Map_Man_t * p, Map_Node_t * pNode, int fPhase )
+{
+    Map_Time_t * ptReqIn, * ptReqOut;
+    Map_Cut_t * pCut;
+    Map_Super_t * pSuper;
+    float tNewReqTime, tExtra;
+    unsigned uPhase;
+    int fPinPhase, i;
+
+    tExtra = pNode->p->pNodeDelays ? pNode->p->pNodeDelays[pNode->Num] : 0;
+    // get the cut to be propagated
+    pCut = pNode->pCutBest[fPhase];
+    assert( pCut != NULL );
+    // get the supergate and its polarity
+    pSuper  = pCut->M[fPhase].pSuperBest;
+    uPhase  = pCut->M[fPhase].uPhaseBest;
+    // get the required time of the output of the supergate
+    ptReqOut = pNode->tRequired + fPhase;
+    // set the required time of the children
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        // get the phase of the given pin of the supergate
+        fPinPhase = ((uPhase & (1 << i)) == 0);
+        ptReqIn = pCut->ppLeaves[i]->tRequired + fPinPhase;
+        assert( pCut->ppLeaves[i]->nRefAct[2] > 0 );
+
+        // get the rise of the output due to rise of the inputs
+//            if ( ptArrOut->Rise < ptArrIn->Rise + pSuper->tDelaysR[i].Rise )
+//                ptArrOut->Rise = ptArrIn->Rise + pSuper->tDelaysR[i].Rise;
+        if ( pSuper->tDelaysR[i].Rise > 0 )
+        {
+            tNewReqTime = ptReqOut->Rise - pSuper->tDelaysR[i].Rise - tExtra;
+            ptReqIn->Rise = MAP_MIN( ptReqIn->Rise, tNewReqTime );
+        }
+
+        // get the rise of the output due to fall of the inputs
+//            if ( ptArrOut->Rise < ptArrIn->Fall + pSuper->tDelaysR[i].Fall )
+//                ptArrOut->Rise = ptArrIn->Fall + pSuper->tDelaysR[i].Fall;
+        if ( pSuper->tDelaysR[i].Fall > 0 )
+        {
+            tNewReqTime = ptReqOut->Rise - pSuper->tDelaysR[i].Fall - tExtra;
+            ptReqIn->Fall = MAP_MIN( ptReqIn->Fall, tNewReqTime );
+        }
+
+        // get the fall of the output due to rise of the inputs
+//            if ( ptArrOut->Fall < ptArrIn->Rise + pSuper->tDelaysF[i].Rise )
+//                ptArrOut->Fall = ptArrIn->Rise + pSuper->tDelaysF[i].Rise;
+        if ( pSuper->tDelaysF[i].Rise > 0 )
+        {
+            tNewReqTime = ptReqOut->Fall - pSuper->tDelaysF[i].Rise - tExtra;
+            ptReqIn->Rise = MAP_MIN( ptReqIn->Rise, tNewReqTime );
+        }
+
+        // get the fall of the output due to fall of the inputs
+//            if ( ptArrOut->Fall < ptArrIn->Fall + pSuper->tDelaysF[i].Fall )
+//                ptArrOut->Fall = ptArrIn->Fall + pSuper->tDelaysF[i].Fall;
+        if ( pSuper->tDelaysF[i].Fall > 0 )
+        {
+            tNewReqTime = ptReqOut->Fall - pSuper->tDelaysF[i].Fall - tExtra;
+            ptReqIn->Fall = MAP_MIN( ptReqIn->Fall, tNewReqTime );
+        }
+    }
+
+    // compare the required times with the arrival times
+//    assert( pNode->tArrival[fPhase].Rise < ptReqOut->Rise + p->fEpsilon );
+//    assert( pNode->tArrival[fPhase].Fall < ptReqOut->Fall + p->fEpsilon );
+}
+float Map_MatchComputeReqTimes( Map_Cut_t * pCut, int fPhase, Map_Time_t * ptArrRes )
+{
+    Map_Time_t * ptArrIn;
+    Map_Super_t * pSuper;
+    unsigned uPhaseTot;
+    int fPinPhase, i;
+    float tDelay;
+
+    // get the supergate and the phase
+    pSuper = pCut->M[fPhase].pSuperBest;
+    uPhaseTot = pCut->M[fPhase].uPhaseBest;
+
+    // propagate the arrival times 
+    ptArrRes->Rise = ptArrRes->Fall = -MAP_FLOAT_LARGE;
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        // get the phase of the given pin
+        fPinPhase = ((uPhaseTot & (1 << i)) == 0);
+        ptArrIn = pCut->ppLeaves[i]->tRequired + fPinPhase;
+//        assert( ptArrIn->Worst < MAP_FLOAT_LARGE );
+
+        // get the rise of the output due to rise of the inputs
+        if ( pSuper->tDelaysR[i].Rise > 0 )
+        {
+            tDelay = ptArrIn->Rise + pSuper->tDelaysR[i].Rise;
+            if ( ptArrRes->Rise < tDelay )
+                ptArrRes->Rise = tDelay;
+        }
+
+        // get the rise of the output due to fall of the inputs
+        if ( pSuper->tDelaysR[i].Fall > 0 )
+        {
+            tDelay = ptArrIn->Fall + pSuper->tDelaysR[i].Fall;
+            if ( ptArrRes->Rise < tDelay )
+                ptArrRes->Rise = tDelay;
+        }
+
+        // get the fall of the output due to rise of the inputs
+        if ( pSuper->tDelaysF[i].Rise > 0 )
+        {
+            tDelay = ptArrIn->Rise + pSuper->tDelaysF[i].Rise;
+            if ( ptArrRes->Fall < tDelay )
+                ptArrRes->Fall = tDelay;
+        }
+
+        // get the fall of the output due to fall of the inputs
+        if ( pSuper->tDelaysF[i].Fall > 0 )
+        {
+            tDelay = ptArrIn->Fall + pSuper->tDelaysF[i].Fall;
+            if ( ptArrRes->Fall < tDelay )
+                ptArrRes->Fall = tDelay;
+        }
+    }
+    // return the worst-case of rise/fall arrival times
+    return MAP_MAX(ptArrRes->Rise, ptArrRes->Fall);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the required times of all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_TimePropagateRequired( Map_Man_t * p )
+{
+    Map_Node_t * pNode;
+    Map_Time_t tReqOutTest, * ptReqOutTest = &tReqOutTest;
+    Map_Time_t * ptReqIn, * ptReqOut;
+    int fPhase, k;
+
+    // go through the nodes in the reverse topological order
+    for ( k = p->vMapObjs->nSize - 1; k >= 0; k-- )
+    {
+        pNode = p->vMapObjs->pArray[k];
+        if ( pNode->nRefAct[2] == 0 )
+            continue;
+
+        // propagate required times through the buffer
+        if ( Map_NodeIsBuf(pNode) )
+        {
+            assert( pNode->p2 == NULL );
+            Map_Regular(pNode->p1)->tRequired[ Map_IsComplement(pNode->p1)] = pNode->tRequired[0];
+            Map_Regular(pNode->p1)->tRequired[!Map_IsComplement(pNode->p1)] = pNode->tRequired[1];
+            continue;
+        }
+
+        // this computation works for regular nodes only
+        assert( !Map_IsComplement(pNode) );
+        // at least one phase should be mapped
+        assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL );
+        // the node should be used in the currently assigned mapping
+        assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 );
+
+        // if one of the cuts is not given, project the required times from the other cut
+        if ( pNode->pCutBest[0] == NULL || pNode->pCutBest[1] == NULL )
+        {
+//            assert( 0 );
+            // get the missing phase 
+            fPhase = (pNode->pCutBest[1] == NULL); 
+            // check if the missing phase is needed in the mapping
+            if ( pNode->nRefAct[fPhase] > 0 )
+            {
+                // get the pointers to the required times of the missing phase
+                ptReqOut = pNode->tRequired +  fPhase;
+//                assert( ptReqOut->Fall < MAP_FLOAT_LARGE );
+                // get the pointers to the required times of the present phase
+                ptReqIn  = pNode->tRequired + !fPhase;
+                // propagate the required times from the missing phase to the present phase
+    //            tArrInv.Fall  = pMatch->tArrive.Rise + p->pSuperLib->tDelayInv.Fall;
+    //            tArrInv.Rise  = pMatch->tArrive.Fall + p->pSuperLib->tDelayInv.Rise;
+                ptReqIn->Fall = MAP_MIN( ptReqIn->Fall, ptReqOut->Rise - p->pSuperLib->tDelayInv.Rise );
+                ptReqIn->Rise = MAP_MIN( ptReqIn->Rise, ptReqOut->Fall - p->pSuperLib->tDelayInv.Fall );
+            }
+        }
+
+        // finalize the worst case computation
+        pNode->tRequired[0].Worst = MAP_MIN( pNode->tRequired[0].Fall, pNode->tRequired[0].Rise );
+        pNode->tRequired[1].Worst = MAP_MIN( pNode->tRequired[1].Fall, pNode->tRequired[1].Rise );
+
+        // skip the PIs
+        if ( !Map_NodeIsAnd(pNode) )
+            continue;
+
+        // propagate required times of different phases of the node
+        // the ordering of phases does not matter since they are mapped independently
+        if ( pNode->pCutBest[0] && pNode->tRequired[0].Worst < MAP_FLOAT_LARGE )
+            Map_TimePropagateRequiredPhase( p, pNode, 0 );
+        if ( pNode->pCutBest[1] && pNode->tRequired[1].Worst < MAP_FLOAT_LARGE )
+            Map_TimePropagateRequiredPhase( p, pNode, 1 );
+    }
+
+    // in the end, we verify the required times
+    // for this, we compute the arrival times of the outputs of each phase 
+    // of the supergates using the fanins' required times as the fanins' arrival times
+    // the resulting arrival time of the supergate should be less than the actual required time
+    for ( k = p->vMapObjs->nSize - 1; k >= 0; k-- )
+    {
+        pNode = p->vMapObjs->pArray[k];
+        if ( pNode->nRefAct[2] == 0 )
+            continue;
+        if ( !Map_NodeIsAnd(pNode) )
+            continue;
+        // verify that the required times are propagated correctly
+//        if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) )
+        if ( pNode->pCutBest[0] && pNode->tRequired[0].Worst < MAP_FLOAT_LARGE/2 )
+        {
+            Map_MatchComputeReqTimes( pNode->pCutBest[0], 0, ptReqOutTest );
+//            assert( ptReqOutTest->Rise < pNode->tRequired[0].Rise + p->fEpsilon );
+//            assert( ptReqOutTest->Fall < pNode->tRequired[0].Fall + p->fEpsilon );
+        }
+//        if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) )
+        if ( pNode->pCutBest[1] && pNode->tRequired[1].Worst < MAP_FLOAT_LARGE/2 )
+        {
+            Map_MatchComputeReqTimes( pNode->pCutBest[1], 1, ptReqOutTest );
+//            assert( ptReqOutTest->Rise < pNode->tRequired[1].Rise + p->fEpsilon );
+//            assert( ptReqOutTest->Fall < pNode->tRequired[1].Fall + p->fEpsilon );
+        }
+    }
+}
+void Map_TimeComputeRequiredGlobal( Map_Man_t * p )
+{
+    Map_Time_t * ptTime, * ptTimeA;
+    int fPhase, i;
+    // update the required times according to the target
+    p->fRequiredGlo = Map_TimeComputeArrivalMax( p );
+    if ( p->DelayTarget != -1 )
+    {
+        if ( p->fRequiredGlo > p->DelayTarget + p->fEpsilon )
+        {
+            if ( p->fMappingMode == 1 )
+                printf( "Cannot meet the target required times (%4.2f). Continue anyway.\n", p->DelayTarget );
+        }
+        else if ( p->fRequiredGlo < p->DelayTarget - p->fEpsilon )
+        {
+            if ( p->fMappingMode == 1 && p->fVerbose )
+                printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->fRequiredGlo, p->DelayTarget );
+            p->fRequiredGlo = p->DelayTarget;
+        }
+    }
+    // clean the required times
+    for ( i = 0; i < p->vMapObjs->nSize; i++ )
+    {
+        p->vMapObjs->pArray[i]->tRequired[0].Rise  = MAP_FLOAT_LARGE;
+        p->vMapObjs->pArray[i]->tRequired[0].Fall  = MAP_FLOAT_LARGE;
+        p->vMapObjs->pArray[i]->tRequired[0].Worst = MAP_FLOAT_LARGE;
+        p->vMapObjs->pArray[i]->tRequired[1].Rise  = MAP_FLOAT_LARGE;
+        p->vMapObjs->pArray[i]->tRequired[1].Fall  = MAP_FLOAT_LARGE;
+        p->vMapObjs->pArray[i]->tRequired[1].Worst = MAP_FLOAT_LARGE;
+    }
+    // set the required times for the POs
+    for ( i = 0; i < p->nOutputs; i++ )
+    {
+        fPhase  = !Map_IsComplement(p->pOutputs[i]);
+        ptTime  =  Map_Regular(p->pOutputs[i])->tRequired + fPhase;
+        ptTimeA =  Map_Regular(p->pOutputs[i])->tArrival + fPhase;
+
+        // if external required time can be achieved, use it
+        if ( p->pOutputRequireds && p->pOutputRequireds[i].Worst > 0 && ptTimeA->Worst <= p->pOutputRequireds[i].Worst )//&& p->pOutputRequireds[i].Worst <= p->fRequiredGlo )
+            ptTime->Rise = ptTime->Fall = ptTime->Worst = p->pOutputRequireds[i].Worst;
+        // if external required cannot be achieved, set the earliest possible arrival time
+        else if ( p->pOutputRequireds && p->pOutputRequireds[i].Worst > 0 && ptTimeA->Worst > p->pOutputRequireds[i].Worst )
+            ptTime->Rise = ptTime->Fall = ptTime->Worst = ptTimeA->Worst;
+        // otherwise, set the global required time
+        else
+            ptTime->Rise = ptTime->Fall = ptTime->Worst = p->fRequiredGlo;
+    }
+    // visit nodes in the reverse topological order
+    Map_TimePropagateRequired( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/mapperTree.c b/abc-build/src/map/mapper/mapperTree.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperTree.c
@@ -0,0 +1,1042 @@
+/**CFile****************************************************************
+
+  FileName    [mapperTree.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapperTree.c,v 1.9 2005/01/23 06:59:45 alanmi Exp $]
+
+***********************************************************************/
+
+#ifdef __linux__
+#include <libgen.h>
+#endif
+
+#include "mapperInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void      Map_LibraryAddFaninDelays( Map_SuperLib_t * pLib, Map_Super_t * pGate, Map_Super_t * pFanin, Mio_Pin_t * pPin );
+static int       Map_LibraryGetMaxSuperPi_rec( Map_Super_t * pGate );
+static unsigned  Map_LibraryGetGateSupp_rec( Map_Super_t * pGate );
+
+// fanout limits
+static const int s_MapFanoutLimits[10] = { 1/*0*/, 10/*1*/, 5/*2*/, 2/*3*/, 1/*4*/, 1/*5*/, 1/*6*/ };
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reads one gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Super_t * Map_LibraryReadGateTree( Map_SuperLib_t * pLib, char * pBuffer, int Number, int nVarsMax )
+{
+    Map_Super_t * pGate;
+    char * pTemp;
+    int i, Num;
+
+    // start and clean the gate
+    pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers );
+    memset( pGate, 0, sizeof(Map_Super_t) );
+
+    // set the gate number
+    pGate->Num = Number;
+
+    // read the mark
+    pTemp = strtok( pBuffer, " " );
+    if ( pTemp[0] == '*' )
+    {
+        pGate->fSuper = 1;
+        pTemp = strtok( NULL, " " );
+    }
+
+    // read the root gate
+    pGate->pRoot = Mio_LibraryReadGateByName( pLib->pGenlib, pTemp, NULL );
+    if ( pGate->pRoot == NULL )
+    {
+        printf( "Cannot read the root gate names %s.\n", pTemp );
+        return NULL;
+    }
+    // set the max number of fanouts
+    pGate->nFanLimit = s_MapFanoutLimits[ Mio_GateReadPinNum(pGate->pRoot) ];
+
+    // read the pin-to-pin delay
+    for ( i = 0; ( pTemp = strtok( NULL, " \n\0" ) ); i++ )
+    {
+        if ( pTemp[0] == '#' )
+            break;
+        if ( i == nVarsMax )
+        {
+            printf( "There are too many entries on the line.\n" );
+            return NULL;
+        }
+        Num = atoi(pTemp);
+        if ( Num < 0 )
+        {
+            printf( "The number of a child supergate is negative.\n" );
+            return NULL;
+        }
+        if ( Num > pLib->nLines )
+        {
+            printf( "The number of a child supergate (%d) exceeded the number of lines (%d).\n", 
+                Num, pLib->nLines );
+            return NULL;
+        }
+        pGate->pFanins[i] = pLib->ppSupers[Num];
+    }
+    pGate->nFanins = i;
+    if ( pGate->nFanins != (unsigned)Mio_GateReadPinNum(pGate->pRoot) )
+    {
+        printf( "The number of fanins of a root gate is wrong.\n" );
+        return NULL;
+    }
+
+    // save the gate name, just in case
+    if ( pTemp && pTemp[0] == '#' )
+    {
+        if ( pTemp[1] == 0 )
+            pTemp = strtok( NULL, " \n\0" );
+        else // skip spaces
+            for ( pTemp++; *pTemp == ' '; pTemp++ );
+        // save the formula
+        pGate->pFormula = Extra_MmFlexEntryFetch( pLib->mmForms, strlen(pTemp)+1 );
+        strcpy( pGate->pFormula, pTemp );
+    }
+    // check the rest of the string
+    pTemp = strtok( NULL, " \n\0" );
+    if ( pTemp != NULL )
+        printf( "The following trailing symbols found \"%s\".\n", pTemp );
+    return pGate;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the supergate library from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+int Map_LibraryReadFileTree( Map_SuperLib_t * pLib, FILE * pFile, char *pFileName )
+{
+    ProgressBar * pProgress;
+    char pBuffer[5000];
+    Map_Super_t * pGate;
+    char * pTemp = 0, * pLibName;
+    int nCounter, k, i;
+    int RetValue;
+
+    // skip empty and comment lines
+    while ( fgets( pBuffer, 5000, pFile ) != NULL )
+    {
+        // skip leading spaces
+        for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ );
+        // skip comment lines and empty lines
+        if ( *pTemp != 0 && *pTemp != '#' )
+            break;
+    }
+
+    pLibName = strtok( pTemp, " \t\r\n" );
+    pLib->pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen();
+    if ( pLib->pGenlib == NULL || strcmp( Mio_LibraryReadName(pLib->pGenlib), pLibName ) )
+    {
+        printf( "Supergate library \"%s\" requires the use of genlib library \"%s\".\n", pFileName, pLibName );
+        return 0;
+    }
+
+    // read the number of variables
+    RetValue = fscanf( pFile, "%d\n", &pLib->nVarsMax );
+    if ( pLib->nVarsMax < 2 || pLib->nVarsMax > 10 )
+    {
+        printf( "Suspicious number of variables (%d).\n", pLib->nVarsMax );
+        return 0;
+    }
+
+    // read the number of gates
+    RetValue = fscanf( pFile, "%d\n", &pLib->nSupersReal );
+    if ( pLib->nSupersReal < 1 || pLib->nSupersReal > 10000000 )
+    {
+        printf( "Suspicious number of gates (%d).\n", pLib->nSupersReal );
+        return 0;
+    }
+
+    // read the number of lines
+    RetValue = fscanf( pFile, "%d\n", &pLib->nLines );
+    if ( pLib->nLines < 1 || pLib->nLines > 10000000 )
+    {
+        printf( "Suspicious number of lines (%d).\n", pLib->nLines );
+        return 0;
+    }
+
+    // allocate room for supergate pointers
+    pLib->ppSupers = ABC_ALLOC( Map_Super_t *, pLib->nLines + 10000 );
+
+    // create the elementary supergates
+    for ( i = 0; i < pLib->nVarsMax; i++ )
+    {
+        // get a new gate
+        pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers );
+        memset( pGate, 0, sizeof(Map_Super_t) );
+        // assign the elementary variable, the truth table, and the delays
+        pGate->Num = i;
+        // set the truth table
+        pGate->uTruth[0] = pLib->uTruths[i][0];
+        pGate->uTruth[1] = pLib->uTruths[i][1];
+        // set the arrival times of all input to non-existent delay
+        for ( k = 0; k < pLib->nVarsMax; k++ )
+        {
+            pGate->tDelaysR[k].Rise = pGate->tDelaysR[k].Fall = MAP_NO_VAR;
+            pGate->tDelaysF[k].Rise = pGate->tDelaysF[k].Fall = MAP_NO_VAR;
+        }
+        // set an existent arrival time for rise and fall
+        pGate->tDelaysR[i].Rise = 0.0;
+        pGate->tDelaysF[i].Fall = 0.0;
+        // set the gate
+        pLib->ppSupers[i] = pGate;
+    }
+
+    // read the lines
+    nCounter = pLib->nVarsMax;
+    pProgress = Extra_ProgressBarStart( stdout, pLib->nLines );
+    while ( fgets( pBuffer, 5000, pFile ) != NULL )
+    {
+        for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ );
+        if ( pTemp[0] == '\0' )
+            continue;
+//        if ( pTemp[0] == 'a' || pTemp[2] == 'a' )
+//        {
+//            pLib->nLines--;
+//            continue;
+//        }
+
+        // get the gate
+        pGate = Map_LibraryReadGateTree( pLib, pTemp, nCounter, pLib->nVarsMax );
+        if ( pGate == NULL )
+        {
+            Extra_ProgressBarStop( pProgress );
+            return 0;
+        }
+        pLib->ppSupers[nCounter++] = pGate;
+        // later we will derive: truth table, delays, area, number of component gates, etc
+
+        // update the progress bar
+        Extra_ProgressBarUpdate( pProgress, nCounter, NULL );
+    }
+    Extra_ProgressBarStop( pProgress );
+    if ( nCounter != pLib->nLines )
+        printf( "The number of lines read (%d) is different what the file says (%d).\n", nCounter, pLib->nLines );
+    pLib->nSupersAll = nCounter;
+    // count the number of real supergates
+    nCounter = 0;
+    for ( k = 0; k < pLib->nLines; k++ )
+        nCounter += pLib->ppSupers[k]->fSuper;
+    if ( nCounter != pLib->nSupersReal )
+        printf( "The number of gates read (%d) is different what the file says (%d).\n", nCounter, pLib->nSupersReal );
+    pLib->nSupersReal = nCounter;
+    return 1;
+}
+int Map_LibraryReadTree2( Map_SuperLib_t * pLib, char * pFileName, char * pExcludeFile )
+{
+    FILE * pFile;
+    int Status, num;
+    Abc_Frame_t * pAbc;
+    st__table * tExcludeGate = 0;
+
+    // read the beginning of the file
+    assert( pLib->pGenlib == NULL );
+    pFile = Io_FileOpen( pFileName, "open_path", "r", 1 );
+//    pFile = fopen( pFileName, "r" ); 
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open input file \"%s\".\n", pFileName );
+        return 0;
+    }
+
+    if ( pExcludeFile )
+    {
+        pAbc = Abc_FrameGetGlobalFrame();
+        
+        tExcludeGate = st__init_table(strcmp, st__strhash);
+        if ( (num = Mio_LibraryReadExclude( pExcludeFile, tExcludeGate )) == -1 )
+        {
+            st__free_table( tExcludeGate );
+            tExcludeGate = 0;
+            return 0;
+        }
+
+        fprintf ( Abc_FrameReadOut( pAbc ), "Read %d gates from exclude file\n", num );
+    }
+    
+    Status = Map_LibraryReadFileTree( pLib, pFile, pFileName );
+    fclose( pFile );
+    if ( Status == 0 )
+        return 0;
+    // prepare the info about the library
+    return Map_LibraryDeriveGateInfo( pLib, tExcludeGate );
+}
+*/
+
+/**Function*************************************************************
+
+  Synopsis    [Similar to fgets.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Vec_StrGets( char * pBuffer, int nBufferSize, Vec_Str_t * vStr, int * pPos )
+{
+    char * pCur;
+    char * pBeg = Vec_StrArray(vStr) + *pPos;
+    char * pEnd = Vec_StrArray(vStr) + Vec_StrSize(vStr);
+    assert( nBufferSize > 1 );
+    if ( pBeg == pEnd )
+    {
+        *pBuffer = 0;
+        return 0;
+    }
+    assert( pBeg < pEnd );
+    for ( pCur = pBeg; pCur < pEnd; pCur++ )
+    {
+        *pBuffer++ = *pCur;
+        if ( *pCur == 0 )
+        {
+            *pPos += pCur - pBeg;
+            return 0;
+        }
+        if ( *pCur == '\n' )
+        {
+            *pPos += pCur - pBeg + 1;
+            *pBuffer = 0;
+            return 1;
+        }
+        if ( pCur - pBeg == nBufferSize-1 )
+        {
+            *pPos += pCur - pBeg + 1;
+            *pBuffer = 0;
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_LibraryCompareLibNames( char * pName1, char * pName2 )
+{
+    char * p1 = Abc_UtilStrsav( pName1 );
+    char * p2 = Abc_UtilStrsav( pName2 );
+    int i, RetValue;
+    for ( i = 0; p1[i]; i++ )
+        if ( p1[i] == '>' || p1[i] == '\\' || p1[i] == '/' )
+            p1[i] = '/';
+    for ( i = 0; p2[i]; i++ )
+        if ( p2[i] == '>' || p2[i] == '\\' || p2[i] == '/' )
+            p2[i] = '/';
+    RetValue = strcmp( p1, p2 );
+    ABC_FREE( p1 );
+    ABC_FREE( p2 );
+    return RetValue; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the supergate library from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_LibraryReadFileTreeStr( Map_SuperLib_t * pLib, Mio_Library_t * pGenlib, Vec_Str_t * vStr, char * pFileName )
+{
+    ProgressBar * pProgress;
+    char pBuffer[5000];
+    Map_Super_t * pGate;
+    char * pTemp = 0, * pLibName;
+    int nCounter, k, i;
+    int RetValue, nPos = 0;
+
+    // skip empty and comment lines
+//    while ( fgets( pBuffer, 5000, pFile ) != NULL )
+    while ( 1 )
+    {
+        RetValue = Vec_StrGets( pBuffer, 5000, vStr, &nPos );
+        if ( RetValue == 0 )
+            return 0;
+        // skip leading spaces
+        for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ );
+        // skip comment lines and empty lines
+        if ( *pTemp != 0 && *pTemp != '#' )
+            break;
+    }
+
+    pLibName = strtok( pTemp, " \t\r\n" );
+//    pLib->pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen();
+    pLib->pGenlib = pGenlib;
+//    if ( pLib->pGenlib == NULL || strcmp( , pLibName ) )
+    if ( pLib->pGenlib == NULL || Map_LibraryCompareLibNames(Mio_LibraryReadName(pLib->pGenlib), pLibName) )
+    {
+        printf( "Supergate library \"%s\" requires the use of genlib library \"%s\".\n", pFileName, pLibName );
+        return 0;
+    }
+
+    // read the number of variables
+    RetValue = Vec_StrGets( pBuffer, 5000, vStr, &nPos );
+    if ( RetValue == 0 )
+        return 0;
+    RetValue = sscanf( pBuffer, "%d\n", &pLib->nVarsMax );
+    if ( pLib->nVarsMax < 2 || pLib->nVarsMax > 10 )
+    {
+        printf( "Suspicious number of variables (%d).\n", pLib->nVarsMax );
+        return 0;
+    }
+
+    // read the number of gates
+    RetValue = Vec_StrGets( pBuffer, 5000, vStr, &nPos );
+    if ( RetValue == 0 )
+        return 0;
+    RetValue = sscanf( pBuffer, "%d\n", &pLib->nSupersReal );
+    if ( pLib->nSupersReal < 1 || pLib->nSupersReal > 10000000 )
+    {
+        printf( "Suspicious number of gates (%d).\n", pLib->nSupersReal );
+        return 0;
+    }
+
+    // read the number of lines
+    RetValue = Vec_StrGets( pBuffer, 5000, vStr, &nPos );
+    if ( RetValue == 0 )
+        return 0;
+    RetValue = sscanf( pBuffer, "%d\n", &pLib->nLines );
+    if ( pLib->nLines < 1 || pLib->nLines > 10000000 )
+    {
+        printf( "Suspicious number of lines (%d).\n", pLib->nLines );
+        return 0;
+    }
+
+    // allocate room for supergate pointers
+    pLib->ppSupers = ABC_ALLOC( Map_Super_t *, pLib->nLines + 10000 );
+
+    // create the elementary supergates
+    for ( i = 0; i < pLib->nVarsMax; i++ )
+    {
+        // get a new gate
+        pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers );
+        memset( pGate, 0, sizeof(Map_Super_t) );
+        // assign the elementary variable, the truth table, and the delays
+        pGate->Num = i;
+        // set the truth table
+        pGate->uTruth[0] = pLib->uTruths[i][0];
+        pGate->uTruth[1] = pLib->uTruths[i][1];
+        // set the arrival times of all input to non-existent delay
+        for ( k = 0; k < pLib->nVarsMax; k++ )
+        {
+            pGate->tDelaysR[k].Rise = pGate->tDelaysR[k].Fall = MAP_NO_VAR;
+            pGate->tDelaysF[k].Rise = pGate->tDelaysF[k].Fall = MAP_NO_VAR;
+        }
+        // set an existent arrival time for rise and fall
+        pGate->tDelaysR[i].Rise = 0.0;
+        pGate->tDelaysF[i].Fall = 0.0;
+        // set the gate
+        pLib->ppSupers[i] = pGate;
+    }
+
+    // read the lines
+    nCounter = pLib->nVarsMax;
+    pProgress = Extra_ProgressBarStart( stdout, pLib->nLines );
+//    while ( fgets( pBuffer, 5000, pFile ) != NULL )
+    while ( Vec_StrGets( pBuffer, 5000, vStr, &nPos ) )
+    {
+        for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ );
+        if ( pTemp[0] == '\0' )
+            continue;
+//        if ( pTemp[0] == 'a' || pTemp[2] == 'a' )
+//        {
+//            pLib->nLines--;
+//            continue;
+//        }
+
+        // get the gate
+        pGate = Map_LibraryReadGateTree( pLib, pTemp, nCounter, pLib->nVarsMax );
+        if ( pGate == NULL )
+        {
+            Extra_ProgressBarStop( pProgress );
+            return 0;
+        }
+        pLib->ppSupers[nCounter++] = pGate;
+        // later we will derive: truth table, delays, area, number of component gates, etc
+
+        // update the progress bar
+        Extra_ProgressBarUpdate( pProgress, nCounter, NULL );
+    }
+    Extra_ProgressBarStop( pProgress );
+    if ( nCounter != pLib->nLines )
+        printf( "The number of lines read (%d) is different from what the file says (%d).\n", nCounter, pLib->nLines );
+    pLib->nSupersAll = nCounter;
+    // count the number of real supergates
+    nCounter = 0;
+    for ( k = 0; k < pLib->nLines; k++ )
+        nCounter += pLib->ppSupers[k]->fSuper;
+    if ( nCounter != pLib->nSupersReal )
+        printf( "The number of gates read (%d) is different what the file says (%d).\n", nCounter, pLib->nSupersReal );
+    pLib->nSupersReal = nCounter;
+    return 1;
+}
+int Map_LibraryReadTree( Map_SuperLib_t * pLib, Mio_Library_t * pGenlib, char * pFileName, char * pExcludeFile )
+{
+    char * pBuffer;
+    Vec_Str_t * vStr;
+    int Status, num;
+    Abc_Frame_t * pAbc;
+    st__table * tExcludeGate = 0;
+
+    // read the beginning of the file
+    assert( pLib->pGenlib == NULL );
+//    pFile = Io_FileOpen( pFileName, "open_path", "r", 1 );
+    pBuffer = Mio_ReadFile( pFileName, 0 );
+    if ( pBuffer == NULL )
+    {
+        printf( "Cannot open input file \"%s\".\n", pFileName );
+        return 0;
+    }
+    vStr = Vec_StrAllocArray( pBuffer, strlen(pBuffer) );
+
+    if ( pExcludeFile )
+    {
+        pAbc = Abc_FrameGetGlobalFrame();
+        
+        tExcludeGate = st__init_table(strcmp, st__strhash);
+        if ( (num = Mio_LibraryReadExclude( pExcludeFile, tExcludeGate )) == -1 )
+        {
+            st__free_table( tExcludeGate );
+            tExcludeGate = 0;
+            Vec_StrFree( vStr );
+            return 0;
+        }
+
+        fprintf ( Abc_FrameReadOut( pAbc ), "Read %d gates from exclude file\n", num );
+    }
+    
+    Status = Map_LibraryReadFileTreeStr( pLib, pGenlib, vStr, pFileName );
+    Vec_StrFree( vStr );
+    if ( Status == 0 )
+        return 0;
+    // prepare the info about the library
+    return Map_LibraryDeriveGateInfo( pLib, tExcludeGate );
+}
+
+
+
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives information about the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_LibraryDeriveGateInfo( Map_SuperLib_t * pLib, st__table * tExcludeGate )
+{
+    Map_Super_t * pGate, * pFanin;
+    Mio_Pin_t * pPin;
+    unsigned uCanon[2];
+    unsigned uTruths[6][2];
+    int i, k, nRealVars;
+
+    // set all the derivable info related to the supergates
+    for ( i = pLib->nVarsMax; i < (int)pLib->nLines; i++ )
+    {
+        pGate = pLib->ppSupers[i];
+
+        if ( tExcludeGate )
+        {
+            if ( st__is_member( tExcludeGate, Mio_GateReadName( pGate->pRoot ) ) )
+                pGate->fExclude = 1;
+            for ( k = 0; k < (int)pGate->nFanins; k++ )
+            {
+                pFanin = pGate->pFanins[k];
+                if ( pFanin->fExclude )
+                {
+                    pGate->fExclude = 1;
+                    continue;
+                }
+            }
+        }
+        
+        // collect the truth tables of the fanins
+        for ( k = 0; k < (int)pGate->nFanins; k++ )
+        {
+            pFanin = pGate->pFanins[k];
+            uTruths[k][0] = pFanin->uTruth[0];
+            uTruths[k][1] = pFanin->uTruth[1];
+        }
+        // derive the new truth table
+        Mio_DeriveTruthTable( pGate->pRoot, uTruths, pGate->nFanins, 6, pGate->uTruth );
+
+        // set the initial delays of the supergate
+        for ( k = 0; k < pLib->nVarsMax; k++ )
+        {
+            pGate->tDelaysR[k].Rise = pGate->tDelaysR[k].Fall = MAP_NO_VAR;
+            pGate->tDelaysF[k].Rise = pGate->tDelaysF[k].Fall = MAP_NO_VAR;
+        }
+        // get the linked list of pins for the given root gate
+        pPin = Mio_GateReadPins( pGate->pRoot );
+        // update the initial delay of the supergate using info from the corresponding pin
+        for ( k = 0; k < (int)pGate->nFanins; k++, pPin = Mio_PinReadNext(pPin) )
+        {
+            // if there is no corresponding pin, this is a bug, return fail
+            if ( pPin == NULL )
+            {
+                printf( "There are less pins than gate inputs.\n" );
+                return 0;
+            }
+            // update the delay information of k-th fanins info from the corresponding pin
+            Map_LibraryAddFaninDelays( pLib, pGate, pGate->pFanins[k], pPin );
+        }
+        // if there are some pins left, this is a bug, return fail
+        if ( pPin != NULL )
+        {
+            printf( "There are more pins than gate inputs.\n" );
+            return 0;
+        }
+        // find the max delay
+        pGate->tDelayMax.Rise = pGate->tDelayMax.Fall = MAP_NO_VAR;
+        for ( k = 0; k < pLib->nVarsMax; k++ )
+        {
+            // the rise of the output depends on the rise and fall of the output
+            if ( pGate->tDelayMax.Rise < pGate->tDelaysR[k].Rise )
+                pGate->tDelayMax.Rise = pGate->tDelaysR[k].Rise;
+            if ( pGate->tDelayMax.Rise < pGate->tDelaysR[k].Fall )
+                pGate->tDelayMax.Rise = pGate->tDelaysR[k].Fall;
+            // the fall of the output depends on the rise and fall of the output
+            if ( pGate->tDelayMax.Fall < pGate->tDelaysF[k].Rise )
+                pGate->tDelayMax.Fall = pGate->tDelaysF[k].Rise;
+            if ( pGate->tDelayMax.Fall < pGate->tDelaysF[k].Fall )
+                pGate->tDelayMax.Fall = pGate->tDelaysF[k].Fall;
+
+            pGate->tDelaysF[k].Worst = MAP_MAX( pGate->tDelaysF[k].Fall, pGate->tDelaysF[k].Rise );
+            pGate->tDelaysR[k].Worst = MAP_MAX( pGate->tDelaysR[k].Fall, pGate->tDelaysR[k].Rise );
+        }
+
+        // count gates and area of the supergate
+        pGate->nGates = 1;
+        pGate->Area   = (float)Mio_GateReadArea(pGate->pRoot);
+        for ( k = 0; k < (int)pGate->nFanins; k++ )
+        {
+            pGate->nGates += pGate->pFanins[k]->nGates;
+            pGate->Area   += pGate->pFanins[k]->Area;
+        }
+        // do not add the gate to the table, if this gate is an internal gate
+        // of some supegate and does not correspond to a supergate output
+        if ( ( !pGate->fSuper ) || pGate->fExclude )
+            continue;
+
+        // find the maximum index of a variable in the support of the supergates
+        // this is important for two reasons:
+        // (1) to limit the number of permutations considered for canonicization
+        // (2) to get rid of equivalence phases to speed-up matching
+        nRealVars = Map_LibraryGetMaxSuperPi_rec( pGate ) + 1;
+        assert( nRealVars > 0 && nRealVars <= pLib->nVarsMax );
+        // if there are some problems with this code, try this instead
+//        nRealVars = pLib->nVarsMax;
+
+        // find the N-canonical form of this supergate
+        pGate->nPhases = Map_CanonComputeSlow( pLib->uTruths, pLib->nVarsMax, nRealVars, pGate->uTruth, pGate->uPhases, uCanon );
+        // add the supergate into the table by its N-canonical table
+        Map_SuperTableInsertC( pLib->tTableC, uCanon, pGate );
+/*
+        {
+            int uCanon1, uCanon2;
+            uCanon1 = uCanon[0];
+            pGate->uTruth[0] = ~pGate->uTruth[0];
+            pGate->uTruth[1] = ~pGate->uTruth[1];
+            Map_CanonComputeSlow( pLib->uTruths, pLib->nVarsMax, nRealVars, pGate->uTruth, pGate->uPhases, uCanon );
+            uCanon2 = uCanon[0];
+Rwt_Man5ExploreCount( uCanon1 < uCanon2 ? uCanon1 : uCanon2 );
+        }
+*/
+    }
+    // sort the gates in each line
+    Map_SuperTableSortSupergatesByDelay( pLib->tTableC, pLib->nSupersAll );
+
+    // let the glory be manifest
+//    Map_LibraryPrintTree( pLib );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the largest PI number in the support of the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_LibraryGetMaxSuperPi_rec( Map_Super_t * pGate )
+{
+    int i, VarCur, VarMax = 0;
+    if ( pGate->pRoot == NULL )
+        return pGate->Num;
+    for ( i = 0; i < (int)pGate->nFanins; i++ )
+    {
+        VarCur = Map_LibraryGetMaxSuperPi_rec( pGate->pFanins[i] );
+        if ( VarMax < VarCur )
+            VarMax = VarCur;
+    }
+    return VarMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the largest PI number in the support of the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Map_LibraryGetGateSupp_rec( Map_Super_t * pGate )
+{
+    unsigned uSupport;
+    int i;
+    if ( pGate->pRoot == NULL )
+        return (unsigned)(1 << (pGate->Num));
+    uSupport = 0;
+    for ( i = 0; i < (int)pGate->nFanins; i++ )
+        uSupport |= Map_LibraryGetGateSupp_rec( pGate->pFanins[i] );
+    return uSupport;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the pin-to-pin delay constraints for the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_LibraryAddFaninDelays( Map_SuperLib_t * pLib, Map_Super_t * pGate, Map_Super_t * pFanin, Mio_Pin_t * pPin )
+{
+    Mio_PinPhase_t PinPhase;
+    float tDelayBlockRise, tDelayBlockFall, tDelayPin;
+    int fMaxDelay = 0;
+    int i;
+
+    // use this node to enable max-delay model
+    if ( fMaxDelay )
+    {
+        float tDelayBlockMax;
+        // get the maximum delay
+        tDelayBlockMax = (float)Mio_PinReadDelayBlockMax(pPin);
+        // go through the supergate inputs
+        for ( i = 0; i < pLib->nVarsMax; i++ )
+        {
+            if ( pFanin->tDelaysR[i].Rise < 0 )
+                continue;
+            tDelayPin = pFanin->tDelaysR[i].Rise + tDelayBlockMax;
+            if ( pGate->tDelaysR[i].Rise < tDelayPin )
+                pGate->tDelaysR[i].Rise = tDelayPin;
+        }
+        // go through the supergate inputs
+        for ( i = 0; i < pLib->nVarsMax; i++ )
+        {
+            if ( pFanin->tDelaysF[i].Fall < 0 )
+                continue;
+            tDelayPin = pFanin->tDelaysF[i].Fall + tDelayBlockMax;
+            if ( pGate->tDelaysF[i].Fall < tDelayPin )
+                pGate->tDelaysF[i].Fall = tDelayPin;
+        }
+        return;
+    }
+
+    // get the interesting parameters of this pin
+    PinPhase = Mio_PinReadPhase(pPin);
+    tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin );  
+    tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin );  
+
+    // update the rise and fall of the output depending on the phase of the pin 
+    if ( PinPhase != MIO_PHASE_INV )  // NONINV phase is present
+    {
+        // the rise of the gate is determined by the rise of the fanin
+        // the fall of the gate is determined by the fall of the fanin
+        for ( i = 0; i < pLib->nVarsMax; i++ )
+        {
+            ////////////////////////////////////////////////////////
+            // consider the rise of the gate
+            ////////////////////////////////////////////////////////
+            // check two types of constraints on the rise of the fanin:
+            // (1) the constraints related to the rise of the PIs
+            // (2) the constraints related to the fall of the PIs
+            if ( pFanin->tDelaysR[i].Rise >= 0 ) // case (1)
+            { // fanin's rise depends on the rise of i-th PI
+                // update the rise of the gate's output
+                if ( pGate->tDelaysR[i].Rise < pFanin->tDelaysR[i].Rise + tDelayBlockRise )
+                    pGate->tDelaysR[i].Rise = pFanin->tDelaysR[i].Rise + tDelayBlockRise;
+            }
+            if ( pFanin->tDelaysR[i].Fall >= 0 ) // case (2)
+            { // fanin's rise depends on the fall of i-th PI
+                // update the rise of the gate's output
+                if ( pGate->tDelaysR[i].Fall < pFanin->tDelaysR[i].Fall + tDelayBlockRise )
+                    pGate->tDelaysR[i].Fall = pFanin->tDelaysR[i].Fall + tDelayBlockRise;
+            }
+            ////////////////////////////////////////////////////////
+
+            ////////////////////////////////////////////////////////
+            // consider the fall of the gate (similar)
+            ////////////////////////////////////////////////////////
+            // check two types of constraints on the fall of the fanin:
+            // (1) the constraints related to the rise of the PIs
+            // (2) the constraints related to the fall of the PIs
+            if ( pFanin->tDelaysF[i].Rise >= 0 ) // case (1) 
+            { 
+                if ( pGate->tDelaysF[i].Rise < pFanin->tDelaysF[i].Rise + tDelayBlockFall )
+                    pGate->tDelaysF[i].Rise = pFanin->tDelaysF[i].Rise + tDelayBlockFall;
+            }
+            if ( pFanin->tDelaysF[i].Fall >= 0 ) // case (2) 
+            { 
+                if ( pGate->tDelaysF[i].Fall < pFanin->tDelaysF[i].Fall + tDelayBlockFall )
+                    pGate->tDelaysF[i].Fall = pFanin->tDelaysF[i].Fall + tDelayBlockFall;
+            }
+            ////////////////////////////////////////////////////////
+        }
+    }
+    if ( PinPhase != MIO_PHASE_NONINV )  // INV phase is present
+    {
+        // the rise of the gate is determined by the fall of the fanin
+        // the fall of the gate is determined by the rise of the fanin
+        for ( i = 0; i < pLib->nVarsMax; i++ )
+        {
+            ////////////////////////////////////////////////////////
+            // consider the rise of the gate's output
+            ////////////////////////////////////////////////////////
+            // check two types of constraints on the fall of the fanin:
+            // (1) the constraints related to the rise of the PIs
+            // (2) the constraints related to the fall of the PIs
+            if ( pFanin->tDelaysF[i].Rise >= 0 ) // case (1)
+            { // fanin's rise depends on the rise of i-th PI
+                // update the rise of the gate
+                if ( pGate->tDelaysR[i].Rise < pFanin->tDelaysF[i].Rise + tDelayBlockRise )
+                    pGate->tDelaysR[i].Rise = pFanin->tDelaysF[i].Rise + tDelayBlockRise;
+            }
+            if ( pFanin->tDelaysF[i].Fall >= 0 ) // case (2)
+            { // fanin's rise depends on the fall of i-th PI
+                // update the rise of the gate
+                if ( pGate->tDelaysR[i].Fall < pFanin->tDelaysF[i].Fall + tDelayBlockRise )
+                    pGate->tDelaysR[i].Fall = pFanin->tDelaysF[i].Fall + tDelayBlockRise;
+            }
+            ////////////////////////////////////////////////////////
+
+            ////////////////////////////////////////////////////////
+            // consider the fall of the gate (similar)
+            ////////////////////////////////////////////////////////
+            // check two types of constraints on the rise of the fanin:
+            // (1) the constraints related to the rise of the PIs
+            // (2) the constraints related to the fall of the PIs
+            if ( pFanin->tDelaysR[i].Rise >= 0 ) // case (1) 
+            { 
+                if ( pGate->tDelaysF[i].Rise < pFanin->tDelaysR[i].Rise + tDelayBlockFall )
+                    pGate->tDelaysF[i].Rise = pFanin->tDelaysR[i].Rise + tDelayBlockFall;
+            }
+            if ( pFanin->tDelaysR[i].Fall >= 0 ) // case (2) 
+            { 
+                if ( pGate->tDelaysF[i].Fall < pFanin->tDelaysR[i].Fall + tDelayBlockFall )
+                    pGate->tDelaysF[i].Fall = pFanin->tDelaysR[i].Fall + tDelayBlockFall;
+            }
+            ////////////////////////////////////////////////////////
+        }
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs phase transformation for one function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Map_CalculatePhase( unsigned uTruths[][2], int nVars, unsigned uTruth, unsigned uPhase )
+{
+    int v, Shift;
+    for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 )
+        if ( uPhase & Shift )
+            uTruth = (((uTruth & ~uTruths[v][0]) << Shift) | ((uTruth & uTruths[v][0]) >> Shift));
+    return uTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs phase transformation for one function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_CalculatePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] )
+{
+    unsigned uTemp;
+    int v, Shift;
+
+    // initialize the result
+    uTruthRes[0] = uTruth[0];
+    uTruthRes[1] = uTruth[1];
+    if ( uPhase == 0 )
+        return;
+    // compute the phase 
+    for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 )
+        if ( uPhase & Shift )
+        {
+            if ( Shift < 32 )
+            {
+                uTruthRes[0] = (((uTruthRes[0] & ~uTruths[v][0]) << Shift) | ((uTruthRes[0] & uTruths[v][0]) >> Shift));
+                uTruthRes[1] = (((uTruthRes[1] & ~uTruths[v][1]) << Shift) | ((uTruthRes[1] & uTruths[v][1]) >> Shift));
+            }
+            else
+            {
+                uTemp        = uTruthRes[0];
+                uTruthRes[0] = uTruthRes[1];
+                uTruthRes[1] = uTemp;
+            }
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the supergate library after deriving parameters.]
+
+  Description [This procedure is very useful to see the library after
+  it has been read into the mapper by "read_super" and all the information
+  about the supergates derived.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_LibraryPrintTree( Map_SuperLib_t * pLib )
+{
+    Map_Super_t * pGate;
+    int i, k;
+
+    // print all the info related to the supergates
+//    for ( i = pLib->nVarsMax; i < (int)pLib->nLines; i++ )
+    for ( i = pLib->nVarsMax; i < 20; i++ )
+    {
+        pGate = pLib->ppSupers[i];
+
+        // write the gate's fanin info and formula
+        printf( "%6d  ", pGate->Num );
+        printf( "%c ", pGate->fSuper? '*' : ' ' );
+        printf( "%6s", Mio_GateReadName(pGate->pRoot) );
+        for ( k = 0; k < (int)pGate->nFanins; k++ )
+            printf( " %6d", pGate->pFanins[k]->Num );
+        printf( "  %s", pGate->pFormula );
+        printf( "\n" );
+
+        // write the gate's derived info
+        Extra_PrintBinary( stdout, pGate->uTruth, 64 );
+        printf( "  %3d",   pGate->nGates );
+        printf( "  %6.2f", pGate->Area );
+        printf( "  (%4.2f, %4.2f)", pGate->tDelayMax.Rise, pGate->tDelayMax.Fall );
+        printf( "\n" );
+        for ( k = 0; k < pLib->nVarsMax; k++ )
+        {
+            // print the constraint on the rise of the gate in the form (D1, D2), 
+            // where D1 is the constraint related to the rise of the k-th PI
+            // where D2 is the constraint related to the fall of the k-th PI
+            if ( pGate->tDelaysR[k].Rise < 0 && pGate->tDelaysR[k].Fall < 0 )
+                printf( " (----, ----)" );
+            else if ( pGate->tDelaysR[k].Fall < 0 )
+                printf( " (%4.2f, ----)", pGate->tDelaysR[k].Rise );
+            else if ( pGate->tDelaysR[k].Rise < 0 )
+                printf( " (----, %4.2f)", pGate->tDelaysR[k].Fall );
+            else
+                printf( " (%4.2f, %4.2f)", pGate->tDelaysR[k].Rise, pGate->tDelaysR[k].Fall );
+
+            // print the constraint on the fall of the gate in the form (D1, D2), 
+            // where D1 is the constraint related to the rise of the k-th PI
+            // where D2 is the constraint related to the fall of the k-th PI
+            if ( pGate->tDelaysF[k].Rise < 0 && pGate->tDelaysF[k].Fall < 0 )
+                printf( " (----, ----)" );
+            else if ( pGate->tDelaysF[k].Fall < 0 )
+                printf( " (%4.2f, ----)", pGate->tDelaysF[k].Rise );
+            else if ( pGate->tDelaysF[k].Rise < 0 )
+                printf( " (----, %4.2f)", pGate->tDelaysF[k].Fall );
+            else
+                printf( " (%4.2f, %4.2f)", pGate->tDelaysF[k].Rise, pGate->tDelaysF[k].Fall );
+            printf( "\n" );
+        }
+        printf( "\n" );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/mapperTruth.c b/abc-build/src/map/mapper/mapperTruth.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperTruth.c
@@ -0,0 +1,315 @@
+/**CFile****************************************************************
+
+  FileName    [mapperTruth.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapperTruth.c,v 1.8 2005/01/23 06:59:45 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Map_TruthsCut( Map_Man_t * pMan, Map_Cut_t * pCut );
+extern void Map_TruthsCutOne( Map_Man_t * p, Map_Cut_t * pCut, unsigned uTruth[] );
+static void Map_CutsCollect_rec( Map_Cut_t * pCut, Map_NodeVec_t * vVisited );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives truth tables for each cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingTruths( Map_Man_t * pMan )
+{
+    ProgressBar * pProgress;
+    Map_Node_t * pNode;
+    Map_Cut_t * pCut;
+    int nNodes, i;
+    // compute the cuts for the POs
+    nNodes = pMan->vMapObjs->nSize;
+    pProgress = Extra_ProgressBarStart( stdout, nNodes );
+    for ( i = 0; i < nNodes; i++ )
+    {
+        pNode = pMan->vMapObjs->pArray[i];
+        if ( !Map_NodeIsAnd( pNode ) )
+            continue;
+        assert( pNode->pCuts );
+        assert( pNode->pCuts->nLeaves == 1 );
+
+        // match the simple cut
+        pNode->pCuts->M[0].uPhase     = 0;
+        pNode->pCuts->M[0].pSupers    = pMan->pSuperLib->pSuperInv;
+        pNode->pCuts->M[0].uPhaseBest = 0;
+        pNode->pCuts->M[0].pSuperBest = pMan->pSuperLib->pSuperInv;
+
+        pNode->pCuts->M[1].uPhase     = 0;
+        pNode->pCuts->M[1].pSupers    = pMan->pSuperLib->pSuperInv;
+        pNode->pCuts->M[1].uPhaseBest = 1;
+        pNode->pCuts->M[1].pSuperBest = pMan->pSuperLib->pSuperInv;
+
+        // match the rest of the cuts
+        for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+             Map_TruthsCut( pMan, pCut );
+        Extra_ProgressBarUpdate( pProgress, i, "Tables ..." );
+    }
+    Extra_ProgressBarStop( pProgress );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table for one cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_TruthsCut( Map_Man_t * p, Map_Cut_t * pCut )
+{ 
+//    unsigned uCanon1, uCanon2;
+    unsigned uTruth[2], uCanon[2];
+    unsigned char uPhases[16];
+    unsigned * uCanon2;
+    char * pPhases2;
+    int fUseFast = 1;
+    int fUseSlow = 0;
+    int fUseRec = 0; // this does not work for Solaris
+
+    extern int Map_CanonCompute( int nVarsMax, int nVarsReal, unsigned * pt, unsigned ** pptRes, char ** ppfRes );
+ 
+    // generally speaking, 1-input cut can be matched into a wire!
+    if ( pCut->nLeaves == 1 )
+        return;
+/*
+    if ( p->nVarsMax == 5 )
+    {
+        uTruth[0] = pCut->uTruth;
+        uTruth[1] = pCut->uTruth;
+    }
+    else
+*/
+    Map_TruthsCutOne( p, pCut, uTruth );
+
+
+    // compute the canonical form for the positive phase
+    if ( fUseFast )
+        Map_CanonComputeFast( p, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+    else if ( fUseSlow )
+        Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+    else if ( fUseRec )
+    {
+//        Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+        Extra_TruthCanonFastN( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 );
+/*
+        if ( uCanon[0] != uCanon2[0] || uPhases[0] != pPhases2[0] )
+        {
+            int k = 0;
+            Map_CanonCompute( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 );
+        }
+*/
+        uCanon[0] = uCanon2[0];
+        uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0];
+        uPhases[0] = pPhases2[0];
+    }
+    else
+        Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+    pCut->M[1].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
+    pCut->M[1].uPhase  = uPhases[0];
+    p->nCanons++;
+
+//uCanon1 = uCanon[0] & 0xFFFF;
+
+    // compute the canonical form for the negative phase
+    uTruth[0] = ~uTruth[0];
+    uTruth[1] = ~uTruth[1];
+    if ( fUseFast )
+        Map_CanonComputeFast( p, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+    else if ( fUseSlow )
+        Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+    else if ( fUseRec )
+    {
+//        Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+        Extra_TruthCanonFastN( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 );
+/*
+        if ( uCanon[0] != uCanon2[0] || uPhases[0] != pPhases2[0] )
+        {
+            int k = 0;
+            Map_CanonCompute( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 );
+        }
+*/
+        uCanon[0] = uCanon2[0];
+        uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0];
+        uPhases[0] = pPhases2[0];
+    }
+    else
+        Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+    pCut->M[0].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
+    pCut->M[0].uPhase  = uPhases[0];
+    p->nCanons++;
+
+//uCanon2 = uCanon[0] & 0xFFFF;
+//assert( p->nVarsMax == 4 );
+//Rwt_Man4ExploreCount( uCanon1 < uCanon2 ? uCanon1 : uCanon2 );
+
+    // restore the truth table
+    uTruth[0] = ~uTruth[0];
+    uTruth[1] = ~uTruth[1];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the truth table of one cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_TruthsCutOne( Map_Man_t * p, Map_Cut_t * pCut, unsigned uTruth[] )
+{
+    unsigned uTruth1[2], uTruth2[2];
+    Map_Cut_t * pTemp = NULL; // Suppress "might be used uninitialized"
+    int i;
+    // mark the cut leaves
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        pTemp = pCut->ppLeaves[i]->pCuts;
+        pTemp->fMark = 1;
+        pTemp->M[0].uPhaseBest = p->uTruths[i][0];
+        pTemp->M[1].uPhaseBest = p->uTruths[i][1];
+    }
+    assert( pCut->fMark == 0 );
+
+    // collect the cuts in the cut cone
+    p->vVisited->nSize = 0;
+    Map_CutsCollect_rec( pCut, p->vVisited );
+    assert( p->vVisited->nSize > 0 );
+    pCut->nVolume = p->vVisited->nSize;
+
+    // compute the tables and unmark
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        pTemp = pCut->ppLeaves[i]->pCuts;
+        pTemp->fMark = 0;
+    }
+    for ( i = 0; i < p->vVisited->nSize; i++ )
+    {
+        // get the cut
+        pTemp = (Map_Cut_t *)p->vVisited->pArray[i];
+        pTemp->fMark = 0;
+        // get truth table of the first branch
+        if ( Map_CutIsComplement(pTemp->pOne) )
+        {
+            uTruth1[0] = ~Map_CutRegular(pTemp->pOne)->M[0].uPhaseBest;
+            uTruth1[1] = ~Map_CutRegular(pTemp->pOne)->M[1].uPhaseBest;
+        }
+        else
+        {
+            uTruth1[0] = Map_CutRegular(pTemp->pOne)->M[0].uPhaseBest;
+            uTruth1[1] = Map_CutRegular(pTemp->pOne)->M[1].uPhaseBest;
+        }
+        // get truth table of the second branch
+        if ( Map_CutIsComplement(pTemp->pTwo) )
+        {
+            uTruth2[0] = ~Map_CutRegular(pTemp->pTwo)->M[0].uPhaseBest;
+            uTruth2[1] = ~Map_CutRegular(pTemp->pTwo)->M[1].uPhaseBest;
+        }
+        else
+        {
+            uTruth2[0] = Map_CutRegular(pTemp->pTwo)->M[0].uPhaseBest;
+            uTruth2[1] = Map_CutRegular(pTemp->pTwo)->M[1].uPhaseBest;
+        }
+        // get the truth table of the output
+        if ( !pTemp->Phase )
+        {
+            pTemp->M[0].uPhaseBest = uTruth1[0] & uTruth2[0];
+            pTemp->M[1].uPhaseBest = uTruth1[1] & uTruth2[1];
+        }
+        else
+        {
+            pTemp->M[0].uPhaseBest = ~(uTruth1[0] & uTruth2[0]);
+            pTemp->M[1].uPhaseBest = ~(uTruth1[1] & uTruth2[1]);
+        }
+    }
+    uTruth[0] = pTemp->M[0].uPhaseBest;
+    uTruth[1] = pTemp->M[1].uPhaseBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively collect the cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_CutsCollect_rec( Map_Cut_t * pCut, Map_NodeVec_t * vVisited )
+{
+    if ( pCut->fMark )
+        return;
+    Map_CutsCollect_rec( Map_CutRegular(pCut->pOne), vVisited );
+    Map_CutsCollect_rec( Map_CutRegular(pCut->pTwo), vVisited );
+    assert( pCut->fMark == 0 );
+    pCut->fMark = 1;
+    Map_NodeVecPush( vVisited, (Map_Node_t *)pCut );
+}
+
+/*
+    {
+        unsigned * uCanon2;
+        char * pPhases2;
+
+        Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+        Map_CanonCompute( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 );
+        if ( uCanon2[0] != uCanon[0] )
+        {
+            int v = 0;
+            Map_CanonCompute( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 );
+            Map_CanonComputeFast( p, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+        }
+//        else
+//        {
+//            printf( "Correct.\n" );
+//        }
+    }
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/mapperUtils.c b/abc-build/src/map/mapper/mapperUtils.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperUtils.c
@@ -0,0 +1,898 @@
+/**CFile****************************************************************
+
+  FileName    [mapperUtils.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapperUtils.c,v 1.8 2004/11/03 22:41:45 satrajit Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define MAP_CO_LIST_SIZE 5
+
+static int   Map_MappingCountLevels_rec( Map_Node_t * pNode );
+static float Map_MappingSetRefsAndArea_rec( Map_Man_t * pMan, Map_Node_t * pNode );
+static float Map_MappingSetRefsAndSwitch_rec( Map_Man_t * pMan, Map_Node_t * pNode );
+static float Map_MappingSetRefsAndWire_rec( Map_Man_t * pMan, Map_Node_t * pNode );
+static void  Map_MappingDfsCuts_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes );
+static float Map_MappingArea_rec( Map_Man_t * pMan, Map_Node_t * pNode, Map_NodeVec_t * vNodes );
+static int   Map_MappingCompareOutputDelay( Map_Node_t ** ppNode1, Map_Node_t ** ppNode2 );
+static void  Map_MappingFindLatest( Map_Man_t * p, int * pNodes, int nNodesMax );
+static unsigned Map_MappingExpandTruth_rec( unsigned uTruth, int nVars );
+static int Map_MappingCountUsedNodes( Map_Man_t * pMan, int fChoices );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the DFS ordering of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingDfs_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, int fCollectEquiv )
+{
+    assert( !Map_IsComplement(pNode) );
+    if ( pNode->fMark0 )
+        return;
+    // visit the transitive fanin
+    if ( Map_NodeIsAnd(pNode) )
+    {
+        Map_MappingDfs_rec( Map_Regular(pNode->p1), vNodes, fCollectEquiv );
+        Map_MappingDfs_rec( Map_Regular(pNode->p2), vNodes, fCollectEquiv );
+    }
+    // visit the equivalent nodes
+    if ( fCollectEquiv && pNode->pNextE )
+        Map_MappingDfs_rec( pNode->pNextE, vNodes, fCollectEquiv );
+    // make sure the node is not visited through the equivalent nodes
+    assert( pNode->fMark0 == 0 );
+    // mark the node as visited
+    pNode->fMark0 = 1;
+    // add the node to the list
+    Map_NodeVecPush( vNodes, pNode );
+}
+Map_NodeVec_t * Map_MappingDfs( Map_Man_t * pMan, int fCollectEquiv )
+{
+    Map_NodeVec_t * vNodes;
+    int i;
+    // perform the traversal
+    vNodes = Map_NodeVecAlloc( 100 );
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        Map_MappingDfs_rec( Map_Regular(pMan->pOutputs[i]), vNodes, fCollectEquiv );
+    for ( i = 0; i < vNodes->nSize; i++ )
+        vNodes->pArray[i]->fMark0 = 0;
+//    for ( i = 0; i < pMan->nOutputs; i++ )
+//        Map_MappingUnmark_rec( Map_Regular(pMan->pOutputs[i]) );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the number of logic levels not counting PIs/POs.]
+
+  Description []
+               
+  SideEffects [Note that this procedure will reassign the levels assigned
+  originally by NodeCreate() because it counts the number of levels with 
+  choices differently!]
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_MappingCountLevels( Map_Man_t * pMan )
+{
+    int i, LevelsMax, LevelsCur;
+    // perform the traversal
+    LevelsMax = -1;
+    for ( i = 0; i < pMan->nOutputs; i++ )
+    {
+        LevelsCur = Map_MappingCountLevels_rec( Map_Regular(pMan->pOutputs[i]) );
+        if ( LevelsMax < LevelsCur )
+            LevelsMax = LevelsCur;
+    }
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        Map_MappingUnmark_rec( Map_Regular(pMan->pOutputs[i]) );
+    return LevelsMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively computes the number of logic levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_MappingCountLevels_rec( Map_Node_t * pNode )
+{
+    int Level1, Level2;
+    assert( !Map_IsComplement(pNode) );
+    if ( !Map_NodeIsAnd(pNode) )
+    {
+        pNode->Level = 0;
+        return 0;
+    }
+    if ( pNode->fMark0 )
+        return pNode->Level;
+    pNode->fMark0 = 1;
+    // visit the transitive fanin
+    Level1 = Map_MappingCountLevels_rec( Map_Regular(pNode->p1) );
+    Level2 = Map_MappingCountLevels_rec( Map_Regular(pNode->p2) );
+    // set the number of levels
+    pNode->Level = 1 + ((Level1>Level2)? Level1: Level2);
+    return pNode->Level;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Unmarks the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingUnmark( Map_Man_t * pMan )
+{
+    int i;
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        Map_MappingUnmark_rec( Map_Regular(pMan->pOutputs[i]) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively unmarks the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingUnmark_rec( Map_Node_t * pNode )
+{
+    assert( !Map_IsComplement(pNode) );
+    if ( pNode->fMark0 == 0 )
+        return;
+    pNode->fMark0 = 0;
+    if ( !Map_NodeIsAnd(pNode) )
+        return;
+    Map_MappingUnmark_rec( Map_Regular(pNode->p1) );
+    Map_MappingUnmark_rec( Map_Regular(pNode->p2) );
+    // visit the equivalent nodes
+    if ( pNode->pNextE )
+        Map_MappingUnmark_rec( pNode->pNextE );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingMark_rec( Map_Node_t * pNode )
+{
+    assert( !Map_IsComplement(pNode) );
+    if ( pNode->fMark0 == 1 )
+        return;
+    pNode->fMark0 = 1;
+    if ( !Map_NodeIsAnd(pNode) )
+        return;
+    // visit the transitive fanin of the selected cut
+    Map_MappingMark_rec( Map_Regular(pNode->p1) );
+    Map_MappingMark_rec( Map_Regular(pNode->p2) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the outputs by their arrival times.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_MappingCompareOutputDelay( Map_Node_t ** ppNode1, Map_Node_t ** ppNode2 )
+{
+    Map_Node_t * pNode1 = Map_Regular(*ppNode1);
+    Map_Node_t * pNode2 = Map_Regular(*ppNode2);
+    int fPhase1 = !Map_IsComplement(*ppNode1);
+    int fPhase2 = !Map_IsComplement(*ppNode2);
+    float Arrival1 = pNode1->tArrival[fPhase1].Worst;
+    float Arrival2 = pNode2->tArrival[fPhase2].Worst;
+    if ( Arrival1 < Arrival2 )
+        return -1;
+    if ( Arrival1 > Arrival2 )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds given number of latest arriving COs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingFindLatest( Map_Man_t * p, int * pNodes, int nNodesMax )
+{
+    int nNodes, i, k, v;
+    assert( p->nOutputs >= nNodesMax );
+    pNodes[0] = 0;
+    nNodes = 1;
+    for ( i = 1; i < p->nOutputs; i++ )
+    {
+        for ( k = nNodes - 1; k >= 0; k-- )
+            if ( Map_MappingCompareOutputDelay( &p->pOutputs[pNodes[k]], &p->pOutputs[i] ) >= 0 )
+                break;
+        if ( k == nNodesMax - 1 )
+            continue;
+        if ( nNodes < nNodesMax )
+            nNodes++;
+        for ( v = nNodes - 1; v > k+1; v-- )
+            pNodes[v] = pNodes[v-1];
+        pNodes[k+1] = i;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints a bunch of latest arriving outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingPrintOutputArrivals( Map_Man_t * p )
+{
+    int pSorted[MAP_CO_LIST_SIZE];
+    Map_Time_t * pTimes;
+    Map_Node_t * pNode;
+    int fPhase, Limit, i;
+    int MaxNameSize;
+
+    // determine the number of nodes to print
+    Limit = (p->nOutputs > MAP_CO_LIST_SIZE)? MAP_CO_LIST_SIZE : p->nOutputs;
+
+    // determine the order
+    Map_MappingFindLatest( p, pSorted, Limit );
+
+    // determine max size of the node's name
+    MaxNameSize = 0;
+    for ( i = 0; i < Limit; i++ )
+        if ( MaxNameSize < (int)strlen(p->ppOutputNames[pSorted[i]]) )
+            MaxNameSize = strlen(p->ppOutputNames[pSorted[i]]);
+
+    // print the latest outputs
+    for ( i = 0; i < Limit; i++ )
+    {
+        // get the i-th latest output
+        pNode  = Map_Regular(p->pOutputs[pSorted[i]]);
+        fPhase =!Map_IsComplement(p->pOutputs[pSorted[i]]);
+        pTimes = pNode->tArrival + fPhase;
+        // print out the best arrival time
+        printf( "Output  %-*s : ", MaxNameSize + 3, p->ppOutputNames[pSorted[i]] );
+        printf( "Delay = (%5.2f, %5.2f)  ", (double)pTimes->Rise, (double)pTimes->Fall );
+        printf( "%s", fPhase? "POS" : "NEG" );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets up the truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingSetupTruthTables( unsigned uTruths[][2] )
+{
+    int m, v;
+    // set up the truth tables
+    for ( m = 0; m < 32; m++ )
+        for ( v = 0; v < 5; v++ )
+            if ( m & (1 << v) )
+                uTruths[v][0] |= (1 << m);
+    // make adjustments for the case of 6 variables
+    for ( v = 0; v < 5; v++ )
+        uTruths[v][1] = uTruths[v][0];
+    uTruths[5][0] = 0;
+    uTruths[5][1] = MAP_FULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets up the truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingSetupTruthTablesLarge( unsigned uTruths[][32] )
+{
+    int m, v;
+    // clean everything
+    for ( m = 0; m < 32; m++ )
+        for ( v = 0; v < 10; v++ )
+            uTruths[v][m] = 0;
+    // set up the truth tables
+    for ( m = 0; m < 32; m++ )
+        for ( v = 0; v < 5; v++ )
+            if ( m & (1 << v) )
+            {
+                uTruths[v][0] |= (1 << m);
+                uTruths[v+5][m] = MAP_FULL;
+            }
+    // extend this info for the rest of the first 5 variables
+    for ( m = 0; m < 32; m++ )
+        for ( v = 0; v < 5; v++ )
+            uTruths[v][m] = uTruths[v][0];
+/*
+    // verify
+    for ( m = 0; m < 1024; m++, printf("\n") )
+        for ( v = 0; v < 10; v++ )
+            if ( Map_InfoReadVar( uTruths[v], m ) )
+                printf( "1" );
+            else
+                printf( "0" );
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets up the mask.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingSetupMask( unsigned uMask[], int nVarsMax )
+{
+    if ( nVarsMax == 6 )
+        uMask[0] = uMask[1] = MAP_FULL;
+    else
+    {
+        uMask[0] = MAP_MASK(1 << nVarsMax);
+        uMask[1] = 0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verify one useful property.]
+
+  Description [This procedure verifies one useful property. After 
+  the FRAIG construction with choice nodes is over, each primary node 
+  should have fanins that are primary nodes. The primary nodes is the 
+  one that does not have pNode->pRepr set to point to another node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_ManCheckConsistency( Map_Man_t * p )
+{
+    Map_Node_t * pNode;
+    Map_NodeVec_t * pVec;
+    int i;
+    pVec = Map_MappingDfs( p, 0 );
+    for ( i = 0; i < pVec->nSize; i++ )
+    {
+        pNode = pVec->pArray[i];
+        if ( Map_NodeIsVar(pNode) )
+        {
+            if ( pNode->pRepr )
+                printf( "Primary input %d is a secondary node.\n", pNode->Num );
+        }
+        else if ( Map_NodeIsConst(pNode) )
+        {
+            if ( pNode->pRepr )
+                printf( "Constant 1 %d is a secondary node.\n", pNode->Num );
+        }
+        else
+        {
+            if ( pNode->pRepr )
+                printf( "Internal node %d is a secondary node.\n", pNode->Num );
+            if ( Map_Regular(pNode->p1)->pRepr )
+                printf( "Internal node %d has first fanin that is a secondary node.\n", pNode->Num );
+            if ( Map_Regular(pNode->p2)->pRepr )
+                printf( "Internal node %d has second fanin that is a secondary node.\n", pNode->Num );
+        }
+    }
+    Map_NodeVecFree( pVec );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if current mapping of the node violates fanout limits.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_MappingNodeIsViolator( Map_Node_t * pNode, Map_Cut_t * pCut, int fPosPol )
+{
+    return pNode->nRefAct[fPosPol] > (int)pCut->M[fPosPol].pSuperBest->nFanLimit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the total are flow of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Map_MappingGetAreaFlow( Map_Man_t * p )
+{
+    Map_Node_t * pNode;
+    Map_Cut_t * pCut;
+    float aFlowFlowTotal = 0;
+    int fPosPol, i;
+    for ( i = 0; i < p->nOutputs; i++ )
+    {
+        pNode = Map_Regular(p->pOutputs[i]);
+        if ( !Map_NodeIsAnd(pNode) )
+            continue;
+        fPosPol = !Map_IsComplement(p->pOutputs[i]);
+        pCut = pNode->pCutBest[fPosPol];
+        if ( pCut == NULL )
+        {
+            fPosPol = !fPosPol;
+            pCut = pNode->pCutBest[fPosPol];
+        }
+        aFlowFlowTotal += pNode->pCutBest[fPosPol]->M[fPosPol].AreaFlow;
+    }
+    return aFlowFlowTotal;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the supergates by their level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_CompareNodesByLevel( Map_Node_t ** ppS1, Map_Node_t ** ppS2 )
+{
+    Map_Node_t * pN1 = Map_Regular(*ppS1);
+    Map_Node_t * pN2 = Map_Regular(*ppS2);
+    if ( pN1->Level > pN2->Level )
+        return -1;
+    if ( pN1->Level < pN2->Level )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Orders the nodes in the decreasing order of levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingSortByLevel( Map_Man_t * pMan, Map_NodeVec_t * vNodes )
+{
+    qsort( (void *)vNodes->pArray, vNodes->nSize, sizeof(Map_Node_t *), 
+            (int (*)(const void *, const void *)) Map_CompareNodesByLevel );
+//    assert( Map_CompareNodesByLevel( vNodes->pArray, vNodes->pArray + vNodes->nSize - 1 ) <= 0 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the supergates by their pointer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_CompareNodesByPointer( Map_Node_t ** ppS1, Map_Node_t ** ppS2 )
+{
+    if ( *ppS1 < *ppS2 )
+        return -1;
+    if ( *ppS1 > *ppS2 )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts how many AIG nodes are mapped in both polarities.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_MappingCountDoubles( Map_Man_t * pMan, Map_NodeVec_t * vNodes )
+{
+    Map_Node_t * pNode;
+    int Counter, i;
+    // count the number of equal adjacent nodes
+    Counter = 0;
+    for ( i = 0; i < vNodes->nSize; i++ )
+    {
+        pNode = vNodes->pArray[i];
+        if ( !Map_NodeIsAnd(pNode) )
+            continue;
+        if ( (pNode->nRefAct[0] && pNode->pCutBest[0]) && 
+             (pNode->nRefAct[1] && pNode->pCutBest[1]) )
+            Counter++;
+    }
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+ st__table * Map_CreateTableGate2Super( Map_Man_t * pMan )
+{
+    Map_Super_t * pSuper;
+    st__table * tTable;
+    int i, nInputs, v;
+    tTable = st__init_table(strcmp, st__strhash);
+    for ( i = 0; i < pMan->pSuperLib->nSupersAll; i++ )
+    {
+        pSuper = pMan->pSuperLib->ppSupers[i];
+        if ( pSuper->nGates == 1 )
+        {
+            // skip different versions of the same root gate
+            nInputs = Mio_GateReadPinNum(pSuper->pRoot);
+            for ( v = 0; v < nInputs; v++ )
+                if ( pSuper->pFanins[v]->Num != nInputs - 1 - v )
+                    break;
+            if ( v != nInputs )
+                continue;
+//            printf( "%s\n", Mio_GateReadName(pSuper->pRoot) );
+            if ( st__insert( tTable, (char *)pSuper->pRoot, (char *)pSuper ) )
+            {
+                assert( 0 );
+            }
+        }
+    }
+    return tTable;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Get the FRAIG node with phase.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_ManCleanData( Map_Man_t * p )
+{
+    int i;
+    for ( i = 0; i < p->vMapObjs->nSize; i++ )
+        p->vMapObjs->pArray[i]->pData0 = p->vMapObjs->pArray[i]->pData1 = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Expand the truth table]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingExpandTruth( unsigned uTruth[2], int nVars )
+{
+    assert( nVars < 7 );
+    if ( nVars == 6 )
+        return;
+    if ( nVars < 5 )
+    {
+        uTruth[0] &= MAP_MASK( (1<<nVars) );
+        uTruth[0]  = Map_MappingExpandTruth_rec( uTruth[0], nVars );
+    }
+    uTruth[1] = uTruth[0];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Expand the truth table]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Map_MappingExpandTruth_rec( unsigned uTruth, int nVars )
+{
+    assert( nVars < 6 );
+    if ( nVars == 5 )
+        return uTruth;
+    return Map_MappingExpandTruth_rec( uTruth | (uTruth << (1 << nVars)), nVars + 1 );    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the arrival times.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Map_MappingComputeDelayWithFanouts( Map_Man_t * p )
+{
+    Map_Node_t * pNode;
+    float Result;
+    int i;
+    for ( i = 0; i < p->vMapObjs->nSize; i++ )
+    {
+        // skip primary inputs
+        pNode = p->vMapObjs->pArray[i];
+        if ( !Map_NodeIsAnd( pNode ) )
+            continue;
+        // skip a secondary node
+        if ( pNode->pRepr )
+            continue;
+        // count the switching nodes
+        if ( pNode->nRefAct[0] > 0 )
+            Map_TimeCutComputeArrival( pNode, pNode->pCutBest[0], 0, MAP_FLOAT_LARGE );
+        if ( pNode->nRefAct[1] > 0 )
+            Map_TimeCutComputeArrival( pNode, pNode->pCutBest[1], 1, MAP_FLOAT_LARGE );
+    }
+    Result = Map_TimeComputeArrivalMax(p);
+    printf( "Max arrival times with fanouts = %10.2f.\n", Result );
+    return Result;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sets up the mask.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_MappingGetMaxLevel( Map_Man_t * pMan )
+{
+    int nLevelMax, i;
+    nLevelMax = 0;
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        nLevelMax = ((unsigned)nLevelMax) > Map_Regular(pMan->pOutputs[i])->Level? 
+                nLevelMax : Map_Regular(pMan->pOutputs[i])->Level;
+    return nLevelMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Analyses choice nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_MappingUpdateLevel_rec( Map_Man_t * pMan, Map_Node_t * pNode, int fMaximum )
+{
+    Map_Node_t * pTemp;
+    int Level1, Level2, LevelE;
+    assert( !Map_IsComplement(pNode) );
+    if ( !Map_NodeIsAnd(pNode) )
+        return pNode->Level;
+    // skip the visited node
+    if ( pNode->TravId == pMan->nTravIds )
+        return pNode->Level;
+    pNode->TravId = pMan->nTravIds;
+    // compute levels of the children nodes
+    Level1 = Map_MappingUpdateLevel_rec( pMan, Map_Regular(pNode->p1), fMaximum );
+    Level2 = Map_MappingUpdateLevel_rec( pMan, Map_Regular(pNode->p2), fMaximum );
+    pNode->Level = 1 + MAP_MAX( Level1, Level2 );
+    if ( pNode->pNextE )
+    {
+        LevelE = Map_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum );
+        if ( fMaximum )
+        {
+            if ( pNode->Level < (unsigned)LevelE )
+                pNode->Level = LevelE;
+        }
+        else
+        {
+            if ( pNode->Level > (unsigned)LevelE )
+                pNode->Level = LevelE;
+        }
+        // set the level of all equivalent nodes to be the same minimum
+        if ( pNode->pRepr == NULL ) // the primary node
+            for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE )
+                pTemp->Level = pNode->Level;
+    }
+    return pNode->Level;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resets the levels of the nodes in the choice graph.]
+
+  Description [Makes the level of the choice nodes to be equal to the
+  maximum of the level of the nodes in the equivalence class. This way
+  sorting by level leads to the reverse topological order, which is
+  needed for the required time computation.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingSetChoiceLevels( Map_Man_t * pMan )
+{
+    int i;
+    pMan->nTravIds++;
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports statistics on choice nodes.]
+
+  Description [The number of choice nodes is the number of primary nodes,
+  which has pNextE set to a pointer. The number of choices is the number
+  of entries in the equivalent-node lists of the primary nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_MappingReportChoices( Map_Man_t * pMan )
+{
+    Map_Node_t * pNode, * pTemp;
+    int nChoiceNodes, nChoices;
+    int i, LevelMax1, LevelMax2;
+
+    // report the number of levels
+    LevelMax1 = Map_MappingGetMaxLevel( pMan );
+    pMan->nTravIds++;
+    for ( i = 0; i < pMan->nOutputs; i++ )
+        Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 0 );
+    LevelMax2 = Map_MappingGetMaxLevel( pMan );
+
+    // report statistics about choices
+    nChoiceNodes = nChoices = 0;
+    for ( i = 0; i < pMan->vMapObjs->nSize; i++ )
+    {
+        pNode = pMan->vMapObjs->pArray[i];
+        if ( pNode->pRepr == NULL && pNode->pNextE != NULL )
+        { // this is a choice node = the primary node that has equivalent nodes
+            nChoiceNodes++;
+            for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE )
+                nChoices++;
+        }
+    }
+    printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 );
+    printf( "Choice stats:  Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the maximum and minimum levels of the choice nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_MappingCountUsedNodes( Map_Man_t * pMan, int fChoices )
+{
+    Map_NodeVec_t * vNodes;
+    int Result;
+    vNodes = Map_MappingDfs( pMan, fChoices );
+    Result = vNodes->nSize;
+    Map_NodeVecFree( vNodes );
+    return Result;    
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/mapperVec.c b/abc-build/src/map/mapper/mapperVec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/mapperVec.c
@@ -0,0 +1,344 @@
+/**CFile****************************************************************
+
+  FileName    [mapperVec.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Generic technology mapping engine.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - June 1, 2004.]
+
+  Revision    [$Id: mapperVec.c,v 1.3 2005/01/23 06:59:45 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Map_NodeVecCompareLevels( Map_Node_t ** pp1, Map_Node_t ** pp2 );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_NodeVec_t * Map_NodeVecAlloc( int nCap )
+{
+    Map_NodeVec_t * p;
+    p = ABC_ALLOC( Map_NodeVec_t, 1 );
+    if ( nCap > 0 && nCap < 16 )
+        nCap = 16;
+    p->nSize  = 0;
+    p->nCap   = nCap;
+    p->pArray = p->nCap? ABC_ALLOC( Map_Node_t *, p->nCap ) : NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_NodeVecFree( Map_NodeVec_t * p )
+{
+    if ( p == NULL )
+        return;
+    ABC_FREE( p->pArray );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_NodeVec_t * Map_NodeVecDup( Map_NodeVec_t * p )
+{
+    Map_NodeVec_t * pNew = Map_NodeVecAlloc( p->nSize );
+    memcpy( pNew->pArray, p->pArray, sizeof(int) * p->nSize );
+    pNew->nSize = p->nSize;
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Node_t ** Map_NodeVecReadArray( Map_NodeVec_t * p )
+{
+    return p->pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_NodeVecReadSize( Map_NodeVec_t * p )
+{
+    return p->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the vector to the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_NodeVecGrow( Map_NodeVec_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pArray = ABC_REALLOC( Map_Node_t *, p->pArray, nCapMin ); 
+    p->nCap   = nCapMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_NodeVecShrink( Map_NodeVec_t * p, int nSizeNew )
+{
+    assert( p->nSize >= nSizeNew );
+    p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_NodeVecClear( Map_NodeVec_t * p )
+{
+    p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_NodeVecPush( Map_NodeVec_t * p, Map_Node_t * Entry )
+{
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Map_NodeVecGrow( p, 16 );
+        else
+            Map_NodeVecGrow( p, 2 * p->nCap );
+    }
+    p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add the element while ensuring uniqueness.]
+
+  Description [Returns 1 if the element was found, and 0 if it was new. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_NodeVecPushUnique( Map_NodeVec_t * p, Map_Node_t * Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            return 1;
+    Map_NodeVecPush( p, Entry );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Node_t * Map_NodeVecPop( Map_NodeVec_t * p )
+{
+    return p->pArray[--p->nSize];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_NodeVecRemove( Map_NodeVec_t * p, Map_Node_t * Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            break;
+    assert( i < p->nSize );
+    for ( i++; i < p->nSize; i++ )
+        p->pArray[i-1] = p->pArray[i];
+    p->nSize--;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_NodeVecWriteEntry( Map_NodeVec_t * p, int i, Map_Node_t * Entry )
+{
+    assert( i >= 0 && i < p->nSize );
+    p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Map_Node_t * Map_NodeVecReadEntry( Map_NodeVec_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting the entries by their integer value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_NodeVecSortByLevel( Map_NodeVec_t * p )
+{
+    qsort( (void *)p->pArray, p->nSize, sizeof(Map_Node_t *), 
+            (int (*)(const void *, const void *)) Map_NodeVecCompareLevels );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Map_NodeVecCompareLevels( Map_Node_t ** pp1, Map_Node_t ** pp2 )
+{
+    int Level1 = Map_Regular(*pp1)->Level;
+    int Level2 = Map_Regular(*pp2)->Level;
+    if ( Level1 < Level2 )
+        return -1;
+    if ( Level1 > Level2 )
+        return 1;
+    if ( Map_Regular(*pp1)->Num < Map_Regular(*pp2)->Num )
+        return -1;
+    if ( Map_Regular(*pp1)->Num > Map_Regular(*pp2)->Num )
+        return 1;
+    return 0; 
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mapper/module.make b/abc-build/src/map/mapper/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mapper/module.make
@@ -0,0 +1,17 @@
+SRC +=  src/map/mapper/mapper.c \
+	src/map/mapper/mapperCanon.c \
+	src/map/mapper/mapperCore.c \
+	src/map/mapper/mapperCreate.c \
+	src/map/mapper/mapperCut.c \
+	src/map/mapper/mapperCutUtils.c \
+	src/map/mapper/mapperLib.c \
+	src/map/mapper/mapperMatch.c \
+	src/map/mapper/mapperRefs.c \
+	src/map/mapper/mapperSuper.c \
+	src/map/mapper/mapperSwitch.c \
+	src/map/mapper/mapperTable.c \
+	src/map/mapper/mapperTime.c \
+	src/map/mapper/mapperTree.c \
+	src/map/mapper/mapperTruth.c \
+	src/map/mapper/mapperUtils.c \
+	src/map/mapper/mapperVec.c
diff --git a/abc-build/src/map/mio/exp.h b/abc-build/src/map/mio/exp.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mio/exp.h
@@ -0,0 +1,284 @@
+/**CFile****************************************************************
+
+  FileName    [exp.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Boolean expression.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: exp.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__map__mio__exp_h
+#define ABC__map__mio__exp_h
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define EXP_CONST0 -1
+#define EXP_CONST1 -2
+
+static inline Vec_Int_t * Exp_Const0()
+{
+    Vec_Int_t * vExp;
+    vExp = Vec_IntAlloc( 1 );
+    Vec_IntPush( vExp, EXP_CONST0 );
+    return vExp;
+}
+static inline Vec_Int_t * Exp_Const1()
+{
+    Vec_Int_t * vExp;
+    vExp = Vec_IntAlloc( 1 );
+    Vec_IntPush( vExp, EXP_CONST1 );
+    return vExp;
+}
+static inline int Exp_IsConst( Vec_Int_t * p )
+{
+    return Vec_IntEntry(p,0) == EXP_CONST0 || Vec_IntEntry(p,0) == EXP_CONST1;
+}
+static inline int Exp_IsConst0( Vec_Int_t * p )
+{
+    return Vec_IntEntry(p,0) == EXP_CONST0;
+}
+static inline int Exp_IsConst1( Vec_Int_t * p )
+{
+    return Vec_IntEntry(p,0) == EXP_CONST1;
+}
+static inline Vec_Int_t * Exp_Var( int iVar )
+{
+    Vec_Int_t * vExp;
+    vExp = Vec_IntAlloc( 1 );
+    Vec_IntPush( vExp, 2 * iVar );
+    return vExp;
+}
+static inline int Exp_LitShift( int nVars, int Lit, int Shift )
+{
+    if ( Lit < 2 * nVars )
+        return Lit;
+    return Lit + 2 * Shift;
+}
+static inline int Exp_IsLit( Vec_Int_t * p )
+{
+    return Vec_IntSize(p) == 1 && !Exp_IsConst(p);
+}
+static inline int Exp_NodeNum( Vec_Int_t * p )
+{
+    return Vec_IntSize(p)/2;
+}
+static inline Vec_Int_t * Exp_Not( Vec_Int_t * p )
+{
+    Vec_IntWriteEntry( p, 0, Vec_IntEntry(p,0) ^ 1 );
+    return p;
+}
+static inline void Exp_PrintLit( int nVars, int Lit )
+{
+    if ( Lit == EXP_CONST0 )
+        Abc_Print( 1, "Const0" );
+    else if ( Lit == EXP_CONST1 )
+        Abc_Print( 1, "Const1" );
+    else if ( Lit < 2 * nVars )
+        Abc_Print( 1, "%s%c", (Lit&1) ? "!" : " ", 'a' + Lit/2 );
+    else
+        Abc_Print( 1, "%s%d", (Lit&1) ? "!" : " ", Lit/2 );
+}
+static inline void Exp_Print( int nVars, Vec_Int_t * p )
+{
+    int i;
+    for ( i = 0; i < Exp_NodeNum(p); i++ )
+    {
+        Abc_Print( 1, "%2d = ", nVars + i );
+        Exp_PrintLit( nVars, Vec_IntEntry(p, 2*i+0) );
+        Abc_Print( 1, " & " );
+        Exp_PrintLit( nVars, Vec_IntEntry(p, 2*i+1) );
+        Abc_Print( 1, "\n" );
+    }
+    Abc_Print( 1, " F = " );
+    Exp_PrintLit( nVars, Vec_IntEntryLast(p) );
+    Abc_Print( 1, "\n" );
+}
+static inline Vec_Int_t * Exp_Reverse( Vec_Int_t * p )
+{
+    Vec_IntReverseOrder( p );
+    return p;
+}
+static inline void Exp_PrintReverse( int nVars, Vec_Int_t * p )
+{
+    Exp_Reverse( p );
+    Exp_Print( nVars, p );
+    Exp_Reverse( p );
+}
+static inline Vec_Int_t * Exp_And( int * pMan, int nVars, Vec_Int_t * p0, Vec_Int_t * p1, int fCompl0, int fCompl1 )
+{
+    int i, Len0 = Vec_IntSize(p0), Len1 = Vec_IntSize(p1);
+    Vec_Int_t * r = Vec_IntAlloc( Len0 + Len1 + 1 );
+    assert( (Len0 & 1) && (Len1 & 1) );
+    Vec_IntPush( r, 2 * (nVars + Len0/2 + Len1/2) );
+    Vec_IntPush( r, Exp_LitShift( nVars, Vec_IntEntry(p0, 0) ^ fCompl0, Len1/2 ) );
+    Vec_IntPush( r, Vec_IntEntry(p1, 0) ^ fCompl1 );
+    for ( i = 1; i < Len0; i++ )
+        Vec_IntPush( r, Exp_LitShift( nVars, Vec_IntEntry(p0, i), Len1/2 ) );
+    for ( i = 1; i < Len1; i++ )
+        Vec_IntPush( r, Vec_IntEntry(p1, i) );
+    assert( Vec_IntSize(r) == Len0 + Len1 + 1 );
+    return r;
+}
+static inline Vec_Int_t * Exp_Or( int * pMan, int nVars, Vec_Int_t * p0, Vec_Int_t * p1 )
+{
+    return Exp_Not( Exp_And(pMan, nVars, p0, p1, 1, 1) );
+}
+static inline Vec_Int_t * Exp_Xor( int * pMan, int nVars, Vec_Int_t * p0, Vec_Int_t * p1 )
+{
+    int i, Len0 = Vec_IntSize(p0), Len1 = Vec_IntSize(p1);
+    Vec_Int_t * r = Vec_IntAlloc( Len0 + Len1 + 5 );
+    assert( (Len0 & 1) && (Len1 & 1) );
+    Vec_IntPush( r, 2 * (nVars + Len0/2 + Len1/2 + 2)     );
+    Vec_IntPush( r, 2 * (nVars + Len0/2 + Len1/2 + 1) + 1 );
+    Vec_IntPush( r, 2 * (nVars + Len0/2 + Len1/2 + 0) + 1 );
+    Vec_IntPush( r, Exp_LitShift( nVars, Vec_IntEntry(p0, 0) ^ 1, Len1/2 ) );
+    Vec_IntPush( r, Vec_IntEntry(p1, 0) );
+    Vec_IntPush( r, Exp_LitShift( nVars, Vec_IntEntry(p0, 0), Len1/2 ) );
+    Vec_IntPush( r, Vec_IntEntry(p1, 0) ^ 1 );
+    for ( i = 1; i < Len0; i++ )
+        Vec_IntPush( r, Exp_LitShift( nVars, Vec_IntEntry(p0, i), Len1/2 ) );
+    for ( i = 1; i < Len1; i++ )
+        Vec_IntPush( r, Vec_IntEntry(p1, i) );
+    assert( Vec_IntSize(r) == Len0 + Len1 + 5 );
+    return Exp_Not( r );
+}
+static inline word Exp_Truth6Lit( int nVars, int Lit, word * puFanins, word * puNodes )
+{
+    if ( Lit == EXP_CONST0 )
+        return 0;
+    if ( Lit == EXP_CONST1 )
+        return ~(word)0;
+    if ( Lit < 2 * nVars )
+        return  (Lit&1) ? ~puFanins[Lit/2] : puFanins[Lit/2];
+    return (Lit&1) ? ~puNodes[Lit/2-nVars] : puNodes[Lit/2-nVars];
+}
+static inline word Exp_Truth6( int nVars, Vec_Int_t * p, word * puFanins )
+{
+    static word Truth6[6] = {
+        ABC_CONST(0xAAAAAAAAAAAAAAAA),
+        ABC_CONST(0xCCCCCCCCCCCCCCCC),
+        ABC_CONST(0xF0F0F0F0F0F0F0F0),
+        ABC_CONST(0xFF00FF00FF00FF00),
+        ABC_CONST(0xFFFF0000FFFF0000),
+        ABC_CONST(0xFFFFFFFF00000000)
+    };
+    word * puNodes, Res;
+    int i;
+    if ( puFanins == NULL )
+        puFanins = (word *)Truth6;
+    puNodes = ABC_CALLOC( word, Exp_NodeNum(p) );
+    for ( i = 0; i < Exp_NodeNum(p); i++ )
+        puNodes[i] = Exp_Truth6Lit( nVars, Vec_IntEntry(p, 2*i+0), puFanins, puNodes ) & 
+                     Exp_Truth6Lit( nVars, Vec_IntEntry(p, 2*i+1), puFanins, puNodes );
+    Res = Exp_Truth6Lit( nVars, Vec_IntEntryLast(p), puFanins, puNodes );
+    ABC_FREE( puNodes );
+    return Res;
+}
+static inline void Exp_TruthLit( int nVars, int Lit, word ** puFanins, word ** puNodes, word * pRes, int nWords )
+{
+    int w;
+    if ( Lit == EXP_CONST0 )
+        for ( w = 0; w < nWords; w++ )
+            pRes[w] = 0;
+    else if ( Lit == EXP_CONST1 )
+        for ( w = 0; w < nWords; w++ )
+            pRes[w] = ~(word)0;
+    else if ( Lit < 2 * nVars )
+        for ( w = 0; w < nWords; w++ )
+            pRes[w] = (Lit&1) ? ~puFanins[Lit/2][w] : puFanins[Lit/2][w];
+    else
+        for ( w = 0; w < nWords; w++ )
+            pRes[w] = (Lit&1) ? ~puNodes[Lit/2-nVars][w] : puNodes[Lit/2-nVars][w];
+}
+static inline void Exp_Truth( int nVars, Vec_Int_t * p, word * pRes )
+{
+    static word Truth6[6] = {
+        ABC_CONST(0xAAAAAAAAAAAAAAAA),
+        ABC_CONST(0xCCCCCCCCCCCCCCCC),
+        ABC_CONST(0xF0F0F0F0F0F0F0F0),
+        ABC_CONST(0xFF00FF00FF00FF00),
+        ABC_CONST(0xFFFF0000FFFF0000),
+        ABC_CONST(0xFFFFFFFF00000000)
+    };
+    word ** puFanins, ** puNodes, * pTemp0, * pTemp1;
+    int i, w, nWords = (nVars <= 6 ? 1 : 1 << (nVars-6));
+    // create elementary variables
+    puFanins = ABC_ALLOC( word *, nVars );
+    for ( i = 0; i < nVars; i++ )
+        puFanins[i] = ABC_ALLOC( word, nWords );
+    // assign elementary truth tables
+    for ( i = 0; i < nVars; i++ )
+        if ( i < 6 )
+            for ( w = 0; w < nWords; w++ )
+                puFanins[i][w] = Truth6[i];
+        else
+            for ( w = 0; w < nWords; w++ )
+                puFanins[i][w] = (w & (1 << (i-6))) ? ~(word)0 : 0;
+    // create intermediate nodes
+    puNodes = ABC_ALLOC( word *, Exp_NodeNum(p) );
+    for ( i = 0; i < Exp_NodeNum(p); i++ )
+        puNodes[i] = ABC_ALLOC( word, nWords );
+    // evaluate the expression
+    pTemp0 = ABC_ALLOC( word, nWords );
+    pTemp1 = ABC_ALLOC( word, nWords );
+    for ( i = 0; i < Exp_NodeNum(p); i++ )
+    {
+        Exp_TruthLit( nVars, Vec_IntEntry(p, 2*i+0), puFanins, puNodes, pTemp0, nWords );
+        Exp_TruthLit( nVars, Vec_IntEntry(p, 2*i+1), puFanins, puNodes, pTemp1, nWords );
+        for ( w = 0; w < nWords; w++ )
+            puNodes[i][w] = pTemp0[w] & pTemp1[w];
+    }
+    ABC_FREE( pTemp0 );
+    ABC_FREE( pTemp1 );
+    // copy the final result
+    Exp_TruthLit( nVars, Vec_IntEntryLast(p), puFanins, puNodes, pRes, nWords );
+    // cleanup
+    for ( i = 0; i < nVars; i++ )
+        ABC_FREE( puFanins[i] );
+    ABC_FREE( puFanins );
+    for ( i = 0; i < Exp_NodeNum(p); i++ )
+        ABC_FREE( puNodes[i] );
+    ABC_FREE( puNodes );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_END
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/map/mio/mio.c b/abc-build/src/map/mio/mio.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mio/mio.c
@@ -0,0 +1,521 @@
+/**CFile****************************************************************
+
+  pFileName    [mio.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [File reading/writing for technology mapping.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 18, 2003.]
+
+  Revision    [$Id: mio.c,v 1.4 2004/08/05 18:34:51 satrajit Exp $]
+
+***********************************************************************/
+
+#define _BSD_SOURCE
+
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+#include "base/main/main.h"
+#include "mio.h"
+#include "map/mapper/mapper.h"
+#include "map/amap/amap.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Mio_CommandReadLiberty( Abc_Frame_t * pAbc, int argc, char **argv );
+static int Mio_CommandReadGenlib( Abc_Frame_t * pAbc, int argc, char **argv );
+static int Mio_CommandWriteGenlib( Abc_Frame_t * pAbc, int argc, char **argv );
+static int Mio_CommandPrintGenlib( Abc_Frame_t * pAbc, int argc, char **argv );
+
+/*
+// internal version of genlib library
+static char * pMcncGenlib[25] = {
+    "GATE inv1    1   O=!a;             PIN * INV     1 999 0.9 0.0 0.9 0.0\n",
+    "GATE inv2    2   O=!a;             PIN * INV     2 999 1.0 0.0 1.0 0.0\n",
+    "GATE inv3    3   O=!a;             PIN * INV     3 999 1.1 0.0 1.1 0.0\n",
+    "GATE inv4    4   O=!a;             PIN * INV     4 999 1.2 0.0 1.2 0.0\n",
+    "GATE nand2   2   O=!(a*b);         PIN * INV     1 999 1.0 0.0 1.0 0.0\n",
+    "GATE nand3   3   O=!(a*b*c);       PIN * INV     1 999 1.1 0.0 1.1 0.0\n",
+    "GATE nand4   4   O=!(a*b*c*d);     PIN * INV     1 999 1.4 0.0 1.4 0.0\n",
+    "GATE nor2    2   O=!(a+b);         PIN * INV     1 999 1.4 0.0 1.4 0.0\n",
+    "GATE nor3    3   O=!(a+b+c);       PIN * INV     1 999 2.4 0.0 2.4 0.0\n",
+    "GATE nor4    4   O=!(a+b+c+d);     PIN * INV     1 999 3.8 0.0 3.8 0.0\n",
+    "GATE xora    5   O=a*!b+!a*b;      PIN * UNKNOWN 2 999 1.9 0.0 1.9 0.0\n",
+    "GATE xorb    5   O=!(a*b+!a*!b);   PIN * UNKNOWN 2 999 1.9 0.0 1.9 0.0\n",
+    "GATE xnora   5   O=a*b+!a*!b;      PIN * UNKNOWN 2 999 2.1 0.0 2.1 0.0\n",
+    "GATE xnorb   5   O=!(!a*b+a*!b);   PIN * UNKNOWN 2 999 2.1 0.0 2.1 0.0\n",
+    "GATE aoi21   3   O=!(a*b+c);       PIN * INV     1 999 1.6 0.0 1.6 0.0\n",
+    "GATE aoi22   4   O=!(a*b+c*d);     PIN * INV     1 999 2.0 0.0 2.0 0.0\n",
+    "GATE oai21   3   O=!((a+b)*c);     PIN * INV     1 999 1.6 0.0 1.6 0.0\n",
+    "GATE oai22   4   O=!((a+b)*(c+d)); PIN * INV     1 999 2.0 0.0 2.0 0.0\n",
+    "GATE buf     1   O=a;              PIN * NONINV  1 999 1.0 0.0 1.0 0.0\n",
+    "GATE zero    0   O=CONST0;\n",
+    "GATE one     0   O=CONST1;\n"
+};
+*/
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_Init( Abc_Frame_t * pAbc )
+{
+//    Cmd_CommandAdd( pAbc, "SC mapping", "read_liberty",   Mio_CommandReadLiberty,  0 ); 
+
+    Cmd_CommandAdd( pAbc, "SC mapping", "read_genlib",    Mio_CommandReadGenlib,  0 ); 
+    Cmd_CommandAdd( pAbc, "SC mapping", "write_genlib",   Mio_CommandWriteGenlib, 0 ); 
+    Cmd_CommandAdd( pAbc, "SC mapping", "print_genlib",   Mio_CommandPrintGenlib, 0 ); 
+
+    Cmd_CommandAdd( pAbc, "SC mapping", "read_library",   Mio_CommandReadGenlib,  0 ); 
+    Cmd_CommandAdd( pAbc, "SC mapping", "write_library",  Mio_CommandWriteGenlib, 0 ); 
+    Cmd_CommandAdd( pAbc, "SC mapping", "print_library",  Mio_CommandPrintGenlib, 0 ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_End( Abc_Frame_t * pAbc )
+{
+    Mio_LibraryDelete( (Mio_Library_t *)Abc_FrameReadLibGen() );
+    Amap_LibFree( (Amap_Lib_t *)Abc_FrameReadLibGen2() );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_UpdateGenlib( Mio_Library_t * pLib )
+{
+    // free the current superlib because it depends on the old Mio library
+    if ( Abc_FrameReadLibSuper() )
+    {
+        Map_SuperLibFree( (Map_SuperLib_t *)Abc_FrameReadLibSuper() );
+        Abc_FrameSetLibSuper( NULL );
+    }
+
+    // replace the current library
+    Mio_LibraryDelete( (Mio_Library_t *)Abc_FrameReadLibGen() );
+    Abc_FrameSetLibGen( pLib );
+
+    // replace the current library
+    Amap_LibFree( (Amap_Lib_t *)Abc_FrameReadLibGen2() );
+    Abc_FrameSetLibGen2( NULL );
+}
+int Mio_UpdateGenlib2( Vec_Str_t * vStr, Vec_Str_t * vStr2, char * pFileName, int fVerbose )
+{
+    Mio_Library_t * pLib;
+    // set the new network
+    pLib = Mio_LibraryRead( pFileName, Vec_StrArray(vStr), NULL, fVerbose );  
+    if ( pLib == NULL )
+        return 0;
+
+    // free the current superlib because it depends on the old Mio library
+    if ( Abc_FrameReadLibSuper() )
+    {
+        Map_SuperLibFree( (Map_SuperLib_t *)Abc_FrameReadLibSuper() );
+        Abc_FrameSetLibSuper( NULL );
+    }
+
+    // replace the current library
+    Mio_LibraryDelete( (Mio_Library_t *)Abc_FrameReadLibGen() );
+    Abc_FrameSetLibGen( pLib );
+
+    // set the new network
+    pLib = (Mio_Library_t *)Amap_LibReadAndPrepare( pFileName, Vec_StrArray(vStr2), 0, 0 );  
+    if ( pLib == NULL )
+        return 0;
+
+    // replace the current library
+    Amap_LibFree( (Amap_Lib_t *)Abc_FrameReadLibGen2() );
+    Abc_FrameSetLibGen2( pLib );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_CommandReadLiberty( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    int fUseFileInterface = 0;
+    char Command[1000];
+    FILE * pFile;
+    FILE * pOut, * pErr;
+    Abc_Ntk_t * pNet;
+    char * pFileName;
+    int fVerbose;
+    int c;
+
+    pNet = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    // set the defaults
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) 
+    {
+        switch (c) 
+        {
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+                break;
+            default:
+                goto usage;
+        }
+    }
+
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    if ( (pFile = Io_FileOpen( pFileName, "open_path", "r", 0 )) == NULL )
+    {
+        fprintf( pErr, "Cannot open input file \"%s\". ", pFileName );
+        if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".genlib", ".lib", ".scl", ".g", NULL )) )
+            fprintf( pErr, "Did you mean \"%s\"?", pFileName );
+        fprintf( pErr, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+
+    if ( fUseFileInterface )
+    {
+        if ( !Amap_LibertyParse( pFileName, fVerbose ) )
+            return 0;
+        assert( strlen(pFileName) < 900 );
+        sprintf( Command, "read_genlib %s", Extra_FileNameGenericAppend(pFileName, ".genlib") );
+        Cmd_CommandExecute( pAbc, Command );
+    }
+    else
+    {
+        Vec_Str_t * vStr, * vStr2;
+        int RetValue;
+        vStr = Amap_LibertyParseStr( pFileName, fVerbose );
+        if ( vStr == NULL )
+            return 0;
+        vStr2 = Vec_StrDup(vStr);
+        RetValue = Mio_UpdateGenlib2( vStr, vStr2, pFileName, fVerbose );
+        Vec_StrFree( vStr );
+        Vec_StrFree( vStr2 );
+        if ( !RetValue )
+            printf( "Reading library has filed.\n" );
+    }
+    return 0;
+
+usage:
+    fprintf( pErr, "usage: read_liberty [-vh]\n");
+    fprintf( pErr, "\t         read standard cell library in Liberty format\n" );  
+    fprintf( pErr, "\t         (if the library contains more than one gate\n" );  
+    fprintf( pErr, "\t         with the same Boolean function, only the gate\n" );  
+    fprintf( pErr, "\t         with the smallest area will be used)\n" );  
+    fprintf( pErr, "\t-v     : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    fprintf( pErr, "\t-h     : enable verbose output\n");
+    return 1;       
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_CommandReadGenlib( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    FILE * pFile;
+    FILE * pOut, * pErr;
+    Mio_Library_t * pLib;
+    Amap_Lib_t * pLib2;
+    Abc_Ntk_t * pNet;
+    char * pFileName;
+    char * pExcludeFile = NULL;
+    int fVerbose;
+    double WireDelay;
+    int c;
+
+    pNet = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    // set the defaults
+    WireDelay   = 0.0;
+    fVerbose = 1;
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "WEvh")) != EOF ) 
+    {
+        switch (c) 
+        {
+            case 'W':
+                if ( globalUtilOptind >= argc )
+                {
+                    Abc_Print( -1, "Command line switch \"-W\" should be followed by a floating point number.\n" );
+                    goto usage;
+                }
+                WireDelay = (float)atof(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( WireDelay <= 0.0 ) 
+                    goto usage;
+                break;
+            case 'E':
+                if ( globalUtilOptind >= argc )
+                {
+                    Abc_Print( -1, "Command line switch \"-E\" should be followed by a file name.\n" );
+                    goto usage;
+                }
+                pExcludeFile = argv[globalUtilOptind];
+                globalUtilOptind++;
+                break;
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+                break;
+            default:
+                goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+    {
+        goto usage;
+    }
+
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    if ( (pFile = Io_FileOpen( pFileName, "open_path", "r", 0 )) == NULL )
+    {
+        fprintf( pErr, "Cannot open input file \"%s\". ", pFileName );
+        if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".genlib", ".lib", ".scl", ".g", NULL )) )
+            fprintf( pErr, "Did you mean \"%s\"?", pFileName );
+        fprintf( pErr, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+
+    // set the new network
+    pLib = Mio_LibraryRead( pFileName, NULL, pExcludeFile, fVerbose );  
+    if ( pLib == NULL )
+    {
+        fprintf( pErr, "Reading genlib library has failed.\n" );
+        return 1;
+    }
+    if ( fVerbose )
+        printf( "Entered genlib library with %d gates from file \"%s\".\n", Mio_LibraryReadGateNum(pLib), pFileName );
+
+    // add the fixed number (wire delay) to all delays in the library
+    if ( WireDelay != 0.0 )
+        Mio_LibraryShiftDelay( pLib, WireDelay );
+
+    // prepare libraries
+    Mio_UpdateGenlib( pLib );
+
+    // replace the current library
+    pLib2 = Amap_LibReadAndPrepare( pFileName, NULL, 0, 0 );  
+    if ( pLib2 == NULL )
+    {
+        fprintf( pErr, "Reading second genlib library has failed.\n" );
+        return 1;
+    }
+    Abc_FrameSetLibGen2( pLib2 );
+    return 0;
+
+usage:
+    fprintf( pErr, "usage: read_genlib [-W float] [-E filename] [-vh]\n");
+    fprintf( pErr, "\t           read the library from a genlib file\n" );  
+    fprintf( pErr, "\t           (if the library contains more than one gate\n" );  
+    fprintf( pErr, "\t           with the same Boolean function, only the gate\n" );  
+    fprintf( pErr, "\t           with the smallest area will be used)\n" );  
+    fprintf( pErr, "\t-W float : wire delay (added to pin-to-pin gate delays) [default = %g]\n", WireDelay );  
+    fprintf( pErr, "\t-E file :  the file name with gates to be excluded [default = none]\n" );
+    fprintf( pErr, "\t-v       : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+    fprintf( pErr, "\t-h       : enable verbose output\n");
+    return 1;       
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Command procedure to read LUT libraries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_CommandWriteGenlib( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    FILE * pOut, * pErr, * pFile;
+    Abc_Ntk_t * pNet;
+    char * pFileName;
+    int fVerbose;
+    int c;
+
+    pNet = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    // set the defaults
+    fVerbose = 1;
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) 
+    {
+        switch (c) 
+        {
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+                break;
+            default:
+                goto usage;
+        }
+    }
+    if ( Abc_FrameReadLibGen() == NULL )
+    {
+        printf( "Library is not available.\n" );
+        return 1;
+    }
+    if ( argc != globalUtilOptind + 1 )
+    {
+        printf( "The file name is not given.\n" );
+        return 1;
+    }
+
+    pFileName = argv[globalUtilOptind];
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        printf( "Error! Cannot open file \"%s\" for writing the library.\n", pFileName );
+        return 1;
+    }
+    Mio_WriteLibrary( pFile, (Mio_Library_t *)Abc_FrameReadLibGen(), 0 );
+    fclose( pFile );
+    printf( "The current genlib library is written into file \"%s\".\n", pFileName );
+    return 0;
+
+usage:
+    fprintf( pErr, "\nusage: write_genlib [-vh] <file>\n");
+    fprintf( pErr, "\t          writes the current genlib library into a file\n" );  
+    fprintf( pErr, "\t-v      : toggles enabling of verbose output [default = %s]\n", fVerbose? "yes" : "no" );
+    fprintf( pErr, "\t-h      : print the command usage\n");
+    fprintf( pErr, "\t<file>  : optional file name to write the library\n");
+    return 1;       
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Command procedure to read LUT libraries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_CommandPrintGenlib( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    FILE * pOut, * pErr;
+    Abc_Ntk_t * pNet;
+    int fVerbose;
+    int c;
+
+    pNet = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    // set the defaults
+    fVerbose = 1;
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) 
+    {
+        switch (c) 
+        {
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+                break;
+            default:
+                goto usage;
+        }
+    }
+    if ( Abc_FrameReadLibGen() == NULL )
+    {
+        printf( "Library is not available.\n" );
+        return 1;
+    }
+    Mio_WriteLibrary( stdout, (Mio_Library_t *)Abc_FrameReadLibGen(), 0 );
+    return 0;
+
+usage:
+    fprintf( pErr, "\nusage: print_genlib [-vh]\n");
+    fprintf( pErr, "\t          print the current genlib library\n" );  
+    fprintf( pErr, "\t-v      : toggles enabling of verbose output [default = %s]\n", fVerbose? "yes" : "no" );
+    fprintf( pErr, "\t-h      : print the command usage\n");
+    return 1;       
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mio/mio.h b/abc-build/src/map/mio/mio.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mio/mio.h
@@ -0,0 +1,188 @@
+/**CFile****************************************************************
+
+  FileName    [mio.h]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [File reading/writing for technology mapping.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: mio.h,v 1.6 2004/08/09 22:16:31 satrajit Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__map__mio__mio_h
+#define ABC__map__mio__mio_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+typedef enum { MIO_PHASE_UNKNOWN, MIO_PHASE_INV, MIO_PHASE_NONINV } Mio_PinPhase_t;
+
+typedef struct  Mio_LibraryStruct_t_      Mio_Library_t;
+typedef struct  Mio_GateStruct_t_         Mio_Gate_t;
+typedef struct  Mio_PinStruct_t_          Mio_Pin_t;
+
+typedef struct Mio_Cell_t_ Mio_Cell_t; 
+struct Mio_Cell_t_
+{
+    char *          pName;          // name
+    word            uTruth;         // truth table
+    float           Area;           // area
+    unsigned        Id       : 28;  // gate ID
+    unsigned        nFanins  :  4;  // gate fanins
+    float           Delays[6];      // delay
+};
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+ 
+#define Mio_LibraryForEachGate( Lib, Gate )                   \
+    for ( Gate = Mio_LibraryReadGates(Lib);                   \
+          Gate;                                               \
+          Gate = Mio_GateReadNext(Gate) )
+#define Mio_LibraryForEachGateSafe( Lib, Gate, Gate2 )        \
+    for ( Gate = Mio_LibraryReadGates(Lib),                   \
+          Gate2 = (Gate? Mio_GateReadNext(Gate): NULL);       \
+          Gate;                                               \
+          Gate = Gate2,                                       \
+          Gate2 = (Gate? Mio_GateReadNext(Gate): NULL) )
+
+#define Mio_GateForEachPin( Gate, Pin )                       \
+    for ( Pin = Mio_GateReadPins(Gate);                       \
+          Pin;                                                \
+          Pin = Mio_PinReadNext(Pin) )
+#define Mio_GateForEachPinSafe( Gate, Pin, Pin2 )             \
+    for ( Pin = Mio_GateReadPins(Gate),                       \
+          Pin2 = (Pin? Mio_PinReadNext(Pin): NULL);           \
+          Pin;                                                \
+          Pin = Pin2,                                         \
+          Pin2 = (Pin? Mio_PinReadNext(Pin): NULL) )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== mio.c =============================================================*/
+extern void              Mio_UpdateGenlib( Mio_Library_t * pLib );
+extern int               Mio_UpdateGenlib2( Vec_Str_t * vStr, Vec_Str_t * vStr2, char * pFileName, int fVerbose );
+/*=== mioApi.c =============================================================*/
+extern char *            Mio_LibraryReadName       ( Mio_Library_t * pLib );
+extern int               Mio_LibraryReadGateNum    ( Mio_Library_t * pLib );
+extern Mio_Gate_t *      Mio_LibraryReadGates      ( Mio_Library_t * pLib );
+extern Mio_Gate_t **     Mio_LibraryReadGateArray  ( Mio_Library_t * pLib );
+extern Mio_Gate_t *      Mio_LibraryReadGateByName ( Mio_Library_t * pLib, char * pName, char * pOutName );
+extern char *            Mio_LibraryReadSopByName  ( Mio_Library_t * pLib, char * pName );    
+extern Mio_Gate_t *      Mio_LibraryReadConst0     ( Mio_Library_t * pLib );
+extern Mio_Gate_t *      Mio_LibraryReadConst1     ( Mio_Library_t * pLib );
+extern Mio_Gate_t *      Mio_LibraryReadNand2      ( Mio_Library_t * pLib );
+extern Mio_Gate_t *      Mio_LibraryReadAnd2       ( Mio_Library_t * pLib );
+extern Mio_Gate_t *      Mio_LibraryReadBuf        ( Mio_Library_t * pLib );
+extern Mio_Gate_t *      Mio_LibraryReadInv        ( Mio_Library_t * pLib );
+extern float             Mio_LibraryReadDelayInvRise( Mio_Library_t * pLib );
+extern float             Mio_LibraryReadDelayInvFall( Mio_Library_t * pLib );
+extern float             Mio_LibraryReadDelayInvMax( Mio_Library_t * pLib );
+extern float             Mio_LibraryReadDelayNand2Rise( Mio_Library_t * pLib );
+extern float             Mio_LibraryReadDelayNand2Fall( Mio_Library_t * pLib );
+extern float             Mio_LibraryReadDelayNand2Max( Mio_Library_t * pLib );
+extern float             Mio_LibraryReadDelayAnd2Max( Mio_Library_t * pLib );
+extern float             Mio_LibraryReadAreaInv    ( Mio_Library_t * pLib );
+extern float             Mio_LibraryReadAreaBuf    ( Mio_Library_t * pLib );
+extern float             Mio_LibraryReadAreaNand2  ( Mio_Library_t * pLib );
+extern int               Mio_LibraryReadGateNameMax( Mio_Library_t * pLib );
+extern char *            Mio_GateReadName          ( Mio_Gate_t * pGate );      
+extern char *            Mio_GateReadOutName       ( Mio_Gate_t * pGate );      
+extern double            Mio_GateReadArea          ( Mio_Gate_t * pGate );      
+extern char *            Mio_GateReadForm          ( Mio_Gate_t * pGate );      
+extern Mio_Pin_t *       Mio_GateReadPins          ( Mio_Gate_t * pGate );      
+extern Mio_Library_t *   Mio_GateReadLib           ( Mio_Gate_t * pGate );      
+extern Mio_Gate_t *      Mio_GateReadNext          ( Mio_Gate_t * pGate );      
+extern Mio_Gate_t *      Mio_GateReadTwin          ( Mio_Gate_t * pGate );      
+extern int               Mio_GateReadPinNum        ( Mio_Gate_t * pGate );      
+extern double            Mio_GateReadDelayMax      ( Mio_Gate_t * pGate );      
+extern char *            Mio_GateReadSop           ( Mio_Gate_t * pGate );      
+extern word              Mio_GateReadTruth         ( Mio_Gate_t * pGate );
+extern int               Mio_GateReadValue         ( Mio_Gate_t * pGate );
+extern char *            Mio_GateReadPinName       ( Mio_Gate_t * pGate, int iPin );
+extern float             Mio_GateReadPinDelay      ( Mio_Gate_t * pGate, int iPin );
+extern void              Mio_GateSetValue          ( Mio_Gate_t * pGate, int Value );
+extern char *            Mio_PinReadName           ( Mio_Pin_t * pPin );  
+extern Mio_PinPhase_t    Mio_PinReadPhase          ( Mio_Pin_t * pPin );  
+extern double            Mio_PinReadInputLoad      ( Mio_Pin_t * pPin );  
+extern double            Mio_PinReadMaxLoad        ( Mio_Pin_t * pPin );  
+extern double            Mio_PinReadDelayBlockRise ( Mio_Pin_t * pPin );  
+extern double            Mio_PinReadDelayFanoutRise( Mio_Pin_t * pPin );  
+extern double            Mio_PinReadDelayBlockFall ( Mio_Pin_t * pPin );  
+extern double            Mio_PinReadDelayFanoutFall( Mio_Pin_t * pPin );  
+extern double            Mio_PinReadDelayBlockMax  ( Mio_Pin_t * pPin );  
+extern Mio_Pin_t *       Mio_PinReadNext           ( Mio_Pin_t * pPin );  
+/*=== mioRead.c =============================================================*/
+extern char *            Mio_ReadFile( char * FileName, int fAddEnd );
+extern Mio_Library_t *   Mio_LibraryRead( char * FileName, char * pBuffer, char * ExcludeFile, int fVerbose );
+extern int               Mio_LibraryReadExclude( char * ExcludeFile, st__table * tExcludeGate );
+/*=== mioFunc.c =============================================================*/
+extern int               Mio_LibraryParseFormulas( Mio_Library_t * pLib );
+/*=== mioParse.c =============================================================*/
+extern Vec_Int_t *       Mio_ParseFormula( char * pFormInit, char ** ppVarNames, int nVars );
+extern Vec_Wrd_t *       Mio_ParseFormulaTruth( char * pFormInit, char ** ppVarNames, int nVars );
+extern int               Mio_ParseCheckFormula( Mio_Gate_t * pGate, char * pForm );
+/*=== mioSop.c =============================================================*/
+extern char *            Mio_LibDeriveSop( int nVars, Vec_Int_t * vExpr, Vec_Str_t * vStr );
+/*=== mioUtils.c =============================================================*/
+extern void              Mio_LibraryDelete( Mio_Library_t * pLib );
+extern void              Mio_GateDelete( Mio_Gate_t * pGate );
+extern void              Mio_PinDelete( Mio_Pin_t * pPin );
+extern Mio_Pin_t *       Mio_PinDup( Mio_Pin_t * pPin );
+extern void              Mio_WriteLibrary( FILE * pFile, Mio_Library_t * pLib, int fPrintSops );
+extern Mio_Gate_t **     Mio_CollectRoots( Mio_Library_t * pLib, int nInputs, float tDelay, int fSkipInv, int * pnGates, int fVerbose );
+extern Mio_Cell_t *      Mio_CollectRootsNew( Mio_Library_t * pLib, int nInputs, int * pnGates, int fVerbose );
+extern Mio_Cell_t *      Mio_CollectRootsNewDefault( int nInputs, int * pnGates, int fVerbose );
+extern word              Mio_DeriveTruthTable6( Mio_Gate_t * pGate );
+extern void              Mio_DeriveTruthTable( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nSigns, int nInputs, unsigned uTruthRes[] );
+extern void              Mio_DeriveGateDelays( Mio_Gate_t * pGate, 
+                            float ** ptPinDelays, int nPins, int nInputs, float tDelayZero, 
+                            float * ptDelaysRes, float * ptPinDelayMax );
+extern Mio_Gate_t *      Mio_GateCreatePseudo( int nInputs );
+extern void              Mio_LibraryShiftDelay( Mio_Library_t * pLib, double Shift );
+extern void              Mio_LibraryMultiArea( Mio_Library_t * pLib, double Multi );
+extern void              Mio_LibraryMultiDelay( Mio_Library_t * pLib, double Multi );
+extern void              Mio_LibraryTransferDelays( Mio_Library_t * pLibD, Mio_Library_t * pLibS );
+
+/*=== sclUtil.c =========================================================*/
+extern Mio_Library_t *   Abc_SclDeriveGenlibSimple( void * pScl );
+extern Mio_Library_t *   Abc_SclDeriveGenlib( void * pScl, float Slew, float Gain, int nGatesMin, int fVerbose );
+extern int               Abc_SclHasDelayInfo( void * pScl );
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/map/mio/mioApi.c b/abc-build/src/map/mio/mioApi.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mio/mioApi.c
@@ -0,0 +1,217 @@
+/**CFile****************************************************************
+
+  FileName    [mioApi.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [File reading/writing for technology mapping.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: mioApi.c,v 1.4 2004/06/28 14:20:25 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mioInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char *            Mio_LibraryReadName          ( Mio_Library_t * pLib )  { return pLib->pName;      }
+int               Mio_LibraryReadGateNum       ( Mio_Library_t * pLib )  { return pLib->nGates;     }
+Mio_Gate_t *      Mio_LibraryReadGates         ( Mio_Library_t * pLib )  { return pLib->pGates;     }
+Mio_Gate_t **     Mio_LibraryReadGateArray     ( Mio_Library_t * pLib )  { return pLib->ppGatesName;}
+Mio_Gate_t *      Mio_LibraryReadBuf           ( Mio_Library_t * pLib )  { return pLib->pGateBuf;   }
+Mio_Gate_t *      Mio_LibraryReadInv           ( Mio_Library_t * pLib )  { return pLib->pGateInv;   }
+Mio_Gate_t *      Mio_LibraryReadConst0        ( Mio_Library_t * pLib )  { return pLib->pGate0;     }
+Mio_Gate_t *      Mio_LibraryReadConst1        ( Mio_Library_t * pLib )  { return pLib->pGate1;     }
+Mio_Gate_t *      Mio_LibraryReadNand2         ( Mio_Library_t * pLib )  { return pLib->pGateNand2; }
+Mio_Gate_t *      Mio_LibraryReadAnd2          ( Mio_Library_t * pLib )  { return pLib->pGateAnd2;  }
+float             Mio_LibraryReadDelayInvRise  ( Mio_Library_t * pLib )  { return (float)(pLib->pGateInv?   pLib->pGateInv->pPins->dDelayBlockRise   : 0.0); }
+float             Mio_LibraryReadDelayInvFall  ( Mio_Library_t * pLib )  { return (float)(pLib->pGateInv?   pLib->pGateInv->pPins->dDelayBlockFall   : 0.0); }
+float             Mio_LibraryReadDelayInvMax   ( Mio_Library_t * pLib )  { return (float)(pLib->pGateInv?   pLib->pGateInv->pPins->dDelayBlockMax    : 0.0); }
+float             Mio_LibraryReadDelayNand2Rise( Mio_Library_t * pLib )  { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockRise : 0.0); }
+float             Mio_LibraryReadDelayNand2Fall( Mio_Library_t * pLib )  { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockFall : 0.0); }
+float             Mio_LibraryReadDelayNand2Max ( Mio_Library_t * pLib )  { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockMax  : 0.0); }
+float             Mio_LibraryReadDelayAnd2Max  ( Mio_Library_t * pLib )  { return (float)(pLib->pGateAnd2?  pLib->pGateAnd2->pPins->dDelayBlockMax   : 0.0); }
+float             Mio_LibraryReadAreaInv       ( Mio_Library_t * pLib )  { return (float)(pLib->pGateInv?   pLib->pGateInv->dArea   : 0.0); }
+float             Mio_LibraryReadAreaBuf       ( Mio_Library_t * pLib )  { return (float)(pLib->pGateBuf?   pLib->pGateBuf->dArea   : 0.0); }
+float             Mio_LibraryReadAreaNand2     ( Mio_Library_t * pLib )  { return (float)(pLib->pGateNand2? pLib->pGateNand2->dArea : 0.0); }
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the longest gate name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_LibraryReadGateNameMax( Mio_Library_t * pLib )
+{
+    Mio_Gate_t * pGate;
+    int LenMax = 0, LenCur;
+    Mio_LibraryForEachGate( pLib, pGate )
+    {
+        LenCur = strlen( Mio_GateReadName(pGate) );
+        if ( LenMax < LenCur )
+            LenMax = LenCur;
+    }
+    return LenMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read Mvc of the gate by name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mio_Gate_t * Mio_LibraryReadGateByName( Mio_Library_t * pLib, char * pName, char * pOutName )      
+{ 
+    Mio_Gate_t * pGate;
+    if ( ! st__lookup( pLib->tName2Gate, pName, (char **)&pGate ) )
+        return NULL;
+    if ( pOutName == NULL )
+        return pGate;
+    if ( !strcmp(pGate->pOutName, pOutName) )
+        return pGate;
+    if ( pGate->pTwin && !strcmp(pGate->pTwin->pOutName, pOutName) )
+        return pGate->pTwin;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read Mvc of the gate by name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Mio_LibraryReadSopByName( Mio_Library_t * pLib, char * pName )      
+{ 
+    Mio_Gate_t * pGate;
+    if ( st__lookup( pLib->tName2Gate, pName, (char **)&pGate ) )
+        return pGate->pSop;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char *            Mio_GateReadName    ( Mio_Gate_t * pGate )            { return pGate->pName;     }
+char *            Mio_GateReadOutName ( Mio_Gate_t * pGate )            { return pGate->pOutName;  }
+double            Mio_GateReadArea    ( Mio_Gate_t * pGate )            { return pGate->dArea;     }
+char *            Mio_GateReadForm    ( Mio_Gate_t * pGate )            { return pGate->pForm;     }
+Mio_Pin_t *       Mio_GateReadPins    ( Mio_Gate_t * pGate )            { return pGate->pPins;     }
+Mio_Library_t *   Mio_GateReadLib     ( Mio_Gate_t * pGate )            { return pGate->pLib;      }
+Mio_Gate_t *      Mio_GateReadNext    ( Mio_Gate_t * pGate )            { return pGate->pNext;     }
+Mio_Gate_t *      Mio_GateReadTwin    ( Mio_Gate_t * pGate )            { return pGate->pTwin;     }
+int               Mio_GateReadPinNum  ( Mio_Gate_t * pGate )            { return pGate->nInputs;   }
+double            Mio_GateReadDelayMax( Mio_Gate_t * pGate )            { return pGate->dDelayMax; }
+char *            Mio_GateReadSop     ( Mio_Gate_t * pGate )            { return pGate->pSop;      }
+word              Mio_GateReadTruth   ( Mio_Gate_t * pGate )            { return pGate->nInputs <= 6 ? pGate->uTruth : 0;   }
+word *            Mio_GateReadTruthP  ( Mio_Gate_t * pGate )            { return pGate->nInputs <= 6 ? NULL: pGate->pTruth; }
+int               Mio_GateReadValue   ( Mio_Gate_t * pGate )            { return pGate->Value;     }
+void              Mio_GateSetValue    ( Mio_Gate_t * pGate, int Value ) { pGate->Value = Value;    }
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char *            Mio_PinReadName           ( Mio_Pin_t * pPin )      { return pPin->pName;           }
+Mio_PinPhase_t    Mio_PinReadPhase          ( Mio_Pin_t * pPin )      { return pPin->Phase;           }
+double            Mio_PinReadInputLoad      ( Mio_Pin_t * pPin )      { return pPin->dLoadInput;      }
+double            Mio_PinReadMaxLoad        ( Mio_Pin_t * pPin )      { return pPin->dLoadMax;        }
+double            Mio_PinReadDelayBlockRise ( Mio_Pin_t * pPin )      { return pPin->dDelayBlockRise; }
+double            Mio_PinReadDelayFanoutRise( Mio_Pin_t * pPin )      { return pPin->dDelayFanoutRise;}
+double            Mio_PinReadDelayBlockFall ( Mio_Pin_t * pPin )      { return pPin->dDelayBlockFall; }
+double            Mio_PinReadDelayFanoutFall( Mio_Pin_t * pPin )      { return pPin->dDelayFanoutFall;}
+double            Mio_PinReadDelayBlockMax  ( Mio_Pin_t * pPin )      { return pPin->dDelayBlockMax;          }
+Mio_Pin_t *       Mio_PinReadNext           ( Mio_Pin_t * pPin )      { return pPin->pNext;           }
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Mio_GateReadPinName( Mio_Gate_t * pGate, int iPin )
+{
+    Mio_Pin_t * pPin;
+    int i = 0;
+    Mio_GateForEachPin( pGate, pPin )
+        if ( i++ == iPin )
+            return Mio_PinReadName(pPin);
+    return NULL;
+}
+float Mio_GateReadPinDelay( Mio_Gate_t * pGate, int iPin )
+{
+    Mio_Pin_t * pPin;
+    int i = 0;
+    Mio_GateForEachPin( pGate, pPin )
+        if ( i++ == iPin )
+            return 0.5 * pPin->dDelayBlockRise + 0.5 * pPin->dDelayBlockFall;
+    return ABC_INFINITY;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mio/mioForm.c b/abc-build/src/map/mio/mioForm.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mio/mioForm.c
@@ -0,0 +1,307 @@
+/**CFile****************************************************************
+
+  FileName    [mioForm.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Parsing equestion formula.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: mioForm.c,v 1.4 2004/06/28 14:20:25 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mioInt.h"
+#include "bdd/parse/parse.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// these symbols (and no other) can appear in the formulas
+#define MIO_SYMB_AND    '*'
+#define MIO_SYMB_AND2   '&'
+#define MIO_SYMB_OR     '+'
+#define MIO_SYMB_OR2    '|'
+#define MIO_SYMB_XOR    '^'
+#define MIO_SYMB_NOT    '!'
+#define MIO_SYMB_AFTNOT '\''
+#define MIO_SYMB_OPEN   '('
+#define MIO_SYMB_CLOSE  ')'
+
+static int Mio_GateParseFormula( Mio_Gate_t * pGate );
+static int Mio_GateCollectNames( char * pFormula, char * pPinNames[] );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Deriving the functionality of the gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_LibraryParseFormulas( Mio_Library_t * pLib )
+{
+    Mio_Gate_t * pGate;
+
+    // count the gates
+    pLib->nGates = 0;
+    Mio_LibraryForEachGate( pLib, pGate )
+        pLib->nGates++;        
+
+    // start a temporary BDD manager
+    pLib->dd = Cudd_Init( 20, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    // introduce ZDD variables
+    Cudd_zddVarsFromBddVars( pLib->dd, 2 );
+
+    // for each gate, derive its function
+    Mio_LibraryForEachGate( pLib, pGate )
+        if ( Mio_GateParseFormula( pGate ) )
+            return 1;
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Registers the cube string with the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Mio_SopRegister( Mem_Flex_t * pMan, char * pName )
+{
+    char * pRegName;
+    if ( pName == NULL ) return NULL;
+    pRegName = Mem_FlexEntryFetch( pMan, strlen(pName) + 1 );
+    strcpy( pRegName, pName );
+    return pRegName;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deriving the functionality of the gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_GateParseFormula( Mio_Gate_t * pGate )
+{
+    extern char * Abc_ConvertBddToSop( Mem_Flex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, int fAllPrimes, Vec_Str_t * vCube, int fMode );
+    DdManager * dd = pGate->pLib->dd;
+    char * pPinNames[100];
+    char * pPinNamesCopy[100];
+    Mio_Pin_t * pPin, ** ppPin;
+    int nPins, iPin, i;
+
+    // set the maximum delay of the gate; count pins
+    pGate->dDelayMax = 0.0;
+    nPins = 0;
+    Mio_GateForEachPin( pGate, pPin )
+    {
+        // set the maximum delay of the gate
+        if ( pGate->dDelayMax < pPin->dDelayBlockMax )
+            pGate->dDelayMax = pPin->dDelayBlockMax;
+        // count the pin
+        nPins++;
+    }
+
+    // check for the gate with const function
+    if ( nPins == 0 )
+    {
+        if ( strcmp( pGate->pForm, MIO_STRING_CONST0 ) == 0 )
+        {
+            pGate->bFunc = b0;
+            pGate->pSop = Mio_SopRegister( (Mem_Flex_t *)pGate->pLib->pMmFlex, " 0\n" );
+            pGate->pLib->pGate0 = pGate;
+        }
+        else if ( strcmp( pGate->pForm, MIO_STRING_CONST1 ) == 0 )
+        {
+            pGate->bFunc = b1;
+            pGate->pSop = Mio_SopRegister( (Mem_Flex_t *)pGate->pLib->pMmFlex, " 1\n" );
+            pGate->pLib->pGate1 = pGate;
+        }
+        else
+        {
+            printf( "Cannot parse formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName );
+            return 1;
+        }
+        Cudd_Ref( pGate->bFunc );
+        return 0;
+    }
+
+    // collect the names as they appear in the formula
+    nPins = Mio_GateCollectNames( pGate->pForm, pPinNames );
+    if ( nPins == 0 )
+    {
+        printf( "Cannot read formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName );
+        return 1;
+    }
+
+    // set the number of inputs
+    pGate->nInputs = nPins;
+
+    // consider the case when all the pins have identical pin info
+    if ( strcmp( pGate->pPins->pName, "*" ) == 0 )
+    {
+        // get the topmost (generic) pin
+        pPin = pGate->pPins;
+        ABC_FREE( pPin->pName );
+
+        // create individual pins from the generic pin
+        ppPin = &pPin->pNext;
+        for ( i = 1; i < nPins; i++ )
+        {
+            // get the new pin
+            *ppPin = Mio_PinDup( pPin );
+            // set its name
+            (*ppPin)->pName = pPinNames[i];
+            // prepare the next place in the list
+            ppPin = &((*ppPin)->pNext);
+        }
+        *ppPin = NULL;
+
+        // set the name of the topmost pin
+        pPin->pName = pPinNames[0];
+    }
+    else
+    {
+        // reorder the variable names to appear the save way as the pins
+        iPin = 0;
+        Mio_GateForEachPin( pGate, pPin )
+        {
+            // find the pin with the name pPin->pName
+            for ( i = 0; i < nPins; i++ )
+            {
+                if ( pPinNames[i] && strcmp( pPinNames[i], pPin->pName ) == 0 )
+                {
+                    // free pPinNames[i] because it is already available as pPin->pName
+                    // setting pPinNames[i] to NULL is useful to make sure that
+                    // this name is not assigned to two pins in the list
+                    ABC_FREE( pPinNames[i] );
+                    pPinNamesCopy[iPin++] = pPin->pName;
+                    break;
+                }
+                if ( i == nPins )
+                {
+                    printf( "Cannot find pin name \"%s\" in the formula \"%s\" of gate \"%s\".\n", 
+                        pPin->pName, pGate->pForm, pGate->pName );
+                    return 1;
+                }
+            }
+        }
+
+        // check for the remaining names
+        for ( i = 0; i < nPins; i++ )
+            if ( pPinNames[i] )
+            {
+                printf( "Name \"%s\" appears in the formula \"%s\" of gate \"%s\" but there is no such pin.\n", 
+                    pPinNames[i], pGate->pForm, pGate->pName );
+                return 1;
+            }
+
+        // copy the names back
+        memcpy( pPinNames, pPinNamesCopy, nPins * sizeof(char *) );
+    }
+
+    // expand the manager if necessary
+    if ( dd->size < nPins )
+    {
+        Cudd_Quit( dd );
+        dd = Cudd_Init( nPins + 10, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+        Cudd_zddVarsFromBddVars( dd, 2 );
+    }
+
+    // derive the formula as the BDD
+    pGate->bFunc = Parse_FormulaParser( stdout, pGate->pForm, nPins, 0, pPinNames, dd, dd->vars );
+    if ( pGate->bFunc == NULL )
+        return 1;
+    Cudd_Ref( pGate->bFunc );
+
+    // derive the cover (SOP)
+    pGate->pSop = Abc_ConvertBddToSop( pGate->pLib->pMmFlex, dd, pGate->bFunc, pGate->bFunc, nPins, 0, pGate->pLib->vCube, -1 );
+
+    // derive the truth table
+    if ( pGate->nInputs <= 6 )
+        pGate->uTruth = Mio_DeriveTruthTable6( pGate );
+
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect the pin names in the formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_GateCollectNames( char * pFormula, char * pPinNames[] )
+{
+    char Buffer[1000];
+    char * pTemp;
+    int nPins, i;
+
+    // save the formula as it was
+    strcpy( Buffer, pFormula );
+
+    // remove the non-name symbols
+    for ( pTemp = Buffer; *pTemp; pTemp++ )
+        if ( *pTemp == MIO_SYMB_AND  || *pTemp == MIO_SYMB_AND2   || 
+             *pTemp == MIO_SYMB_OR   || *pTemp == MIO_SYMB_OR2    || 
+             *pTemp == MIO_SYMB_XOR  || 
+             *pTemp == MIO_SYMB_NOT  || *pTemp == MIO_SYMB_AFTNOT ||
+             *pTemp == MIO_SYMB_OPEN || *pTemp == MIO_SYMB_CLOSE )
+             *pTemp = ' ';
+
+    // save the names
+    nPins = 0;
+    pTemp = strtok( Buffer, " " );
+    while ( pTemp )
+    {
+        for ( i = 0; i < nPins; i++ )
+            if ( strcmp( pTemp, pPinNames[i] ) == 0 )
+                break;
+        if ( i == nPins )
+        { // cannot find this name; save it
+            pPinNames[nPins++] = Abc_UtilStrsav(pTemp);
+        }
+        // get the next name
+        pTemp = strtok( NULL, " " );
+    }
+    return nPins;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mio/mioFunc.c b/abc-build/src/map/mio/mioFunc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mio/mioFunc.c
@@ -0,0 +1,320 @@
+/**CFile****************************************************************
+
+  FileName    [mioFunc.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [File reading/writing for technology mapping.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: mioFunc.c,v 1.4 2004/06/28 14:20:25 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mioInt.h"
+//#include "parse.h"
+#include "exp.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// these symbols (and no other) can appear in the formulas
+#define MIO_SYMB_AND    '*'
+#define MIO_SYMB_AND2   '&'
+#define MIO_SYMB_OR     '+'
+#define MIO_SYMB_OR2    '|'
+#define MIO_SYMB_XOR    '^'
+#define MIO_SYMB_NOT    '!'
+#define MIO_SYMB_AFTNOT '\''
+#define MIO_SYMB_OPEN   '('
+#define MIO_SYMB_CLOSE  ')'
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Registers the cube string with the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Mio_SopRegister( Mem_Flex_t * pMan, char * pName )
+{
+    char * pRegName;
+    if ( pName == NULL ) return NULL;
+    pRegName = Mem_FlexEntryFetch( pMan, strlen(pName) + 1 );
+    strcpy( pRegName, pName );
+    return pRegName;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect the pin names in the formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_GateCollectNames( char * pFormula, char * pPinNames[] )
+{
+    char Buffer[1000];
+    char * pTemp;
+    int nPins, i;
+
+    // save the formula as it was
+    strcpy( Buffer, pFormula );
+
+    // remove the non-name symbols
+    for ( pTemp = Buffer; *pTemp; pTemp++ )
+        if ( *pTemp == MIO_SYMB_AND  || *pTemp == MIO_SYMB_AND2   || 
+             *pTemp == MIO_SYMB_OR   || *pTemp == MIO_SYMB_OR2    || 
+             *pTemp == MIO_SYMB_XOR  || 
+             *pTemp == MIO_SYMB_NOT  || *pTemp == MIO_SYMB_AFTNOT ||
+             *pTemp == MIO_SYMB_OPEN || *pTemp == MIO_SYMB_CLOSE )
+             *pTemp = ' ';
+
+    // save the names
+    nPins = 0;
+    pTemp = strtok( Buffer, " " );
+    while ( pTemp )
+    {
+        for ( i = 0; i < nPins; i++ )
+            if ( strcmp( pTemp, pPinNames[i] ) == 0 )
+                break;
+        if ( i == nPins )
+        { // cannot find this name; save it
+            pPinNames[nPins++] = Abc_UtilStrsav(pTemp);
+        }
+        // get the next name
+        pTemp = strtok( NULL, " " );
+    }
+    return nPins;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deriving the functionality of the gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_GateParseFormula( Mio_Gate_t * pGate )
+{
+    char * pPinNames[100];
+    char * pPinNamesCopy[100];
+    Mio_Pin_t * pPin, ** ppPin;
+    int nPins, iPin, i;
+
+    // set the maximum delay of the gate; count pins
+    pGate->dDelayMax = 0.0;
+    nPins = 0;
+    Mio_GateForEachPin( pGate, pPin )
+    {
+        // set the maximum delay of the gate
+        if ( pGate->dDelayMax < pPin->dDelayBlockMax )
+            pGate->dDelayMax = pPin->dDelayBlockMax;
+        // count the pin
+        nPins++;
+    }
+
+    // check for the gate with const function
+    if ( nPins == 0 )
+    {
+        if ( strcmp( pGate->pForm, MIO_STRING_CONST0 ) == 0 )
+        {
+//            pGate->bFunc = b0;
+            pGate->vExpr = Exp_Const0();
+            pGate->pSop = Mio_SopRegister( (Mem_Flex_t *)pGate->pLib->pMmFlex, " 0\n" );
+            pGate->uTruth = 0;
+            pGate->pLib->pGate0 = pGate;
+        }
+        else if ( strcmp( pGate->pForm, MIO_STRING_CONST1 ) == 0 )
+        {
+//            pGate->bFunc = b1;
+            pGate->vExpr = Exp_Const1();
+            pGate->pSop = Mio_SopRegister( (Mem_Flex_t *)pGate->pLib->pMmFlex, " 1\n" );
+            pGate->uTruth = ~(word)0;
+            pGate->pLib->pGate1 = pGate;
+        }
+        else
+        {
+            printf( "Cannot parse formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName );
+            return 1;
+        }
+//        Cudd_Ref( pGate->bFunc );
+        return 0;
+    }
+
+    // collect the names as they appear in the formula
+    nPins = Mio_GateCollectNames( pGate->pForm, pPinNames );
+    if ( nPins == 0 )
+    {
+        printf( "Cannot read formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName );
+        return 1;
+    }
+
+    // set the number of inputs
+    pGate->nInputs = nPins;
+
+    // consider the case when all the pins have identical pin info
+    if ( strcmp( pGate->pPins->pName, "*" ) == 0 )
+    {
+        // get the topmost (generic) pin
+        pPin = pGate->pPins;
+        ABC_FREE( pPin->pName );
+
+        // create individual pins from the generic pin
+        ppPin = &pPin->pNext;
+        for ( i = 1; i < nPins; i++ )
+        {
+            // get the new pin
+            *ppPin = Mio_PinDup( pPin );
+            // set its name
+            (*ppPin)->pName = pPinNames[i];
+            // prepare the next place in the list
+            ppPin = &((*ppPin)->pNext);
+        }
+        *ppPin = NULL;
+
+        // set the name of the topmost pin
+        pPin->pName = pPinNames[0];
+    }
+    else
+    {
+        // reorder the variable names to appear the save way as the pins
+        iPin = 0;
+        Mio_GateForEachPin( pGate, pPin )
+        {
+            // find the pin with the name pPin->pName
+            for ( i = 0; i < nPins; i++ )
+            {
+                if ( pPinNames[i] && strcmp( pPinNames[i], pPin->pName ) == 0 )
+                {
+                    // free pPinNames[i] because it is already available as pPin->pName
+                    // setting pPinNames[i] to NULL is useful to make sure that
+                    // this name is not assigned to two pins in the list
+                    ABC_FREE( pPinNames[i] );
+                    pPinNamesCopy[iPin++] = pPin->pName;
+                    break;
+                }
+                if ( i == nPins )
+                {
+                    printf( "Cannot find pin name \"%s\" in the formula \"%s\" of gate \"%s\".\n", 
+                        pPin->pName, pGate->pForm, pGate->pName );
+                    return 1;
+                }
+            }
+        }
+
+        // check for the remaining names
+        for ( i = 0; i < nPins; i++ )
+            if ( pPinNames[i] )
+            {
+                printf( "Name \"%s\" appears in the formula \"%s\" of gate \"%s\" but there is no such pin.\n", 
+                    pPinNames[i], pGate->pForm, pGate->pName );
+                return 1;
+            }
+
+        // copy the names back
+        memcpy( pPinNames, pPinNamesCopy, nPins * sizeof(char *) );
+    }
+/*
+    // expand the manager if necessary
+    if ( dd->size < nPins )
+    {
+        Cudd_Quit( dd );
+        dd = Cudd_Init( nPins + 10, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+        Cudd_zddVarsFromBddVars( dd, 2 );
+    }
+    // derive formula as the BDD
+    pGate->bFunc = Parse_FormulaParser( stdout, pGate->pForm, nPins, 0, pPinNames, dd, dd->vars );
+    if ( pGate->bFunc == NULL )
+        return 1;
+    Cudd_Ref( pGate->bFunc );
+    // derive cover
+    pGate->pSop = Abc_ConvertBddToSop( pGate->pLib->pMmFlex, dd, pGate->bFunc, pGate->bFunc, nPins, 0, pGate->pLib->vCube, -1 );
+*/
+
+    // derive expression 
+    pGate->vExpr = Mio_ParseFormula( pGate->pForm, (char **)pPinNames, nPins );
+//    Mio_ParseFormulaTruthTest( pGate->pForm, (char **)pPinNames, nPins );
+    // derive cover
+    pGate->pSop = Mio_LibDeriveSop( nPins, pGate->vExpr, pGate->pLib->vCube );
+    pGate->pSop = Mio_SopRegister( (Mem_Flex_t *)pGate->pLib->pMmFlex, pGate->pSop );
+    // derive truth table
+    if ( nPins <= 6 )
+        pGate->uTruth = Exp_Truth6( nPins, pGate->vExpr, NULL );
+
+/*
+    // verify
+    if ( pGate->nInputs <= 6 )
+    {
+        extern word Abc_SopToTruth( char * pSop, int nInputs );
+        word t2 = Abc_SopToTruth( pGate->pSop, nPins );
+        if ( pGate->uTruth != t2 )
+        {
+            printf( "%s\n", pGate->pForm );
+            Exp_Print( nPins, pGate->vExpr );
+            printf( "Verification failed!\n" );
+        }
+    }
+*/
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deriving the functionality of the gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_LibraryParseFormulas( Mio_Library_t * pLib )
+{
+    Mio_Gate_t * pGate;
+
+    // count the gates
+    pLib->nGates = 0;
+    Mio_LibraryForEachGate( pLib, pGate )
+        pLib->nGates++;        
+
+    // for each gate, derive its function
+    Mio_LibraryForEachGate( pLib, pGate )
+        if ( Mio_GateParseFormula( pGate ) )
+            return 1;
+    return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mio/mioInt.h b/abc-build/src/map/mio/mioInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mio/mioInt.h
@@ -0,0 +1,141 @@
+/**CFile****************************************************************
+
+  FileName    [mioInt.h]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [File reading/writing for technology mapping.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: mioInt.h,v 1.4 2004/06/28 14:20:25 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__map__mio__mioInt_h
+#define ABC__map__mio__mioInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "misc/vec/vec.h"
+#include "misc/mem/mem.h"
+#include "misc/st/st.h"
+#include "mio.h"
+ 
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+#define    MIO_STRING_GATE       "GATE"
+#define    MIO_STRING_LATCH      "LATCH"
+#define    MIO_STRING_PIN        "PIN"
+#define    MIO_STRING_NONINV     "NONINV"
+#define    MIO_STRING_INV        "INV"
+#define    MIO_STRING_UNKNOWN    "UNKNOWN"
+
+#define    MIO_STRING_CONST0     "CONST0"
+#define    MIO_STRING_CONST1     "CONST1"
+ 
+// the bit masks
+#define    MIO_MASK(n)         ((~((unsigned)0)) >> (32-(n)))
+#define    MIO_FULL             (~((unsigned)0))
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+struct  Mio_LibraryStruct_t_
+{
+    char *             pName;       // the name of the library
+    int                nGates;      // the number of the gates
+    Mio_Gate_t **      ppGates0;    // the array of gates in the original order
+    Mio_Gate_t **      ppGatesName; // the array of gates sorted by name
+    Mio_Gate_t *       pGates;      // the linked list of all gates in no particular order
+    Mio_Gate_t *       pGate0;      // the constant zero gate
+    Mio_Gate_t *       pGate1;      // the constant one gate
+    Mio_Gate_t *       pGateBuf;    // the buffer
+    Mio_Gate_t *       pGateInv;    // the inverter
+    Mio_Gate_t *       pGateNand2;  // the NAND2 gate
+    Mio_Gate_t *       pGateAnd2;   // the AND2 gate
+    st__table *         tName2Gate;  // the mapping of gate names into their pointer
+    Mem_Flex_t *       pMmFlex;     // the memory manaqer for SOPs
+    Vec_Str_t *        vCube;       // temporary cube
+}; 
+
+struct  Mio_GateStruct_t_
+{
+    // information derived from the genlib file
+    char *             pName;       // the name of the gate
+    double             dArea;       // the area of the gate
+    char *             pForm;       // the formula describing functionality of the gate
+    Mio_Pin_t *        pPins;       // the linked list of all pins (one pin if info is the same)
+    char *             pOutName;    // the name of the output pin 
+    // the library to which this gate belongs
+    Mio_Library_t *    pLib; 
+    // the next gate in the list
+    Mio_Gate_t *       pNext;    
+    Mio_Gate_t *       pTwin;    
+
+    // the derived information
+    int                nInputs;     // the number of inputs
+    double             dDelayMax;   // the maximum delay
+    char *             pSop;        // sum-of-products
+    Vec_Int_t *        vExpr;       // boolean expression
+    union { word       uTruth;      // truth table
+    word *             pTruth; };   // pointer to the truth table
+    int                Value;       // user's information
+};
+
+struct  Mio_PinStruct_t_
+{
+    char *             pName;
+    Mio_PinPhase_t     Phase;
+    double             dLoadInput;
+    double             dLoadMax;
+    double             dDelayBlockRise;
+    double             dDelayFanoutRise;
+    double             dDelayBlockFall;
+    double             dDelayFanoutFall;
+    double             dDelayBlockMax;
+    Mio_Pin_t *        pNext;     
+};
+
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== mio.c =============================================================*/
+/*=== mioRead.c =============================================================*/
+/*=== mioUtils.c =============================================================*/
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/map/mio/mioParse.c b/abc-build/src/map/mio/mioParse.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mio/mioParse.c
@@ -0,0 +1,504 @@
+/**CFile****************************************************************
+
+  FileName    [mioParse.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Parsing Boolean expressions.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: mioParse.c,v 1.4 2004/06/28 14:20:25 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mioInt.h"
+#include "exp.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// the list of operation symbols to be used in expressions
+#define MIO_EQN_SYM_OPEN    '('   // opening paranthesis
+#define MIO_EQN_SYM_CLOSE   ')'   // closing paranthesis
+#define MIO_EQN_SYM_CONST0  '0'   // constant 0
+#define MIO_EQN_SYM_CONST1  '1'   // constant 1
+#define MIO_EQN_SYM_NEG     '!'   // negation before the variable
+#define MIO_EQN_SYM_NEGAFT  '\''  // negation after the variable
+#define MIO_EQN_SYM_AND     '*'   // logic AND
+#define MIO_EQN_SYM_AND2    '&'   // logic AND
+#define MIO_EQN_SYM_XOR     '^'   // logic XOR
+#define MIO_EQN_SYM_OR      '+'   // logic OR
+#define MIO_EQN_SYM_OR2     '|'   // logic OR
+
+// the list of opcodes (also specifying operation precedence)
+#define MIO_EQN_OPER_NEG    10    // negation
+#define MIO_EQN_OPER_AND     9    // logic AND
+#define MIO_EQN_OPER_XOR     8    // logic XOR
+#define MIO_EQN_OPER_OR      7    // logic OR
+#define MIO_EQN_OPER_MARK    1    // OpStack token standing for an opening paranthesis
+
+// these are values of the internal Flag
+#define MIO_EQN_FLAG_START   1    // after the opening parenthesis 
+#define MIO_EQN_FLAG_VAR     2    // after operation is received
+#define MIO_EQN_FLAG_OPER    3    // after operation symbol is received
+#define MIO_EQN_FLAG_ERROR   4    // when error is detected
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs the operation on the top entries in the stack.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Mio_ParseFormulaOper( int * pMan, int nVars, Vec_Ptr_t * pStackFn, int Oper )
+{
+    Vec_Int_t * gArg1, * gArg2, * gFunc;
+    // perform the given operation
+    gArg2 = (Vec_Int_t *)Vec_PtrPop( pStackFn );
+    gArg1 = (Vec_Int_t *)Vec_PtrPop( pStackFn );
+	if ( Oper == MIO_EQN_OPER_AND )
+		gFunc = Exp_And( pMan, nVars, gArg1, gArg2, 0, 0 );
+	else if ( Oper == MIO_EQN_OPER_OR )
+		gFunc = Exp_Or( pMan, nVars, gArg1, gArg2 );
+	else if ( Oper == MIO_EQN_OPER_XOR )
+		gFunc = Exp_Xor( pMan, nVars, gArg1, gArg2 );
+	else
+		return NULL;
+//    Cudd_Ref( gFunc );
+//    Cudd_RecursiveDeref( dd, gArg1 );
+//    Cudd_RecursiveDeref( dd, gArg2 );
+    Vec_IntFree( gArg1 );
+    Vec_IntFree( gArg2 );
+	Vec_PtrPush( pStackFn,  gFunc );
+    return gFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the AIG corresponding to the equation.]
+
+  Description [Takes the stream to output messages, the formula, the vector
+  of variable names and the AIG manager.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Mio_ParseFormula( char * pFormInit, char ** ppVarNames, int nVars )
+{
+    char * pFormula;
+    int Man = nVars, * pMan = &Man;
+    Vec_Ptr_t * pStackFn;
+    Vec_Int_t * pStackOp;
+    Vec_Int_t * gFunc;
+    char * pTemp, * pName;
+    int nParans, fFound, Flag;
+	int Oper, Oper1, Oper2;
+    int i, v;
+
+    // make sure that the number of opening and closing parantheses is the same
+    nParans = 0;
+    for ( pTemp = pFormInit; *pTemp; pTemp++ )
+        if ( *pTemp == '(' )
+            nParans++;
+        else if ( *pTemp == ')' )
+            nParans--;
+    if ( nParans != 0 )
+    {
+        fprintf( stdout, "Mio_ParseFormula(): Different number of opening and closing parantheses ().\n" );
+        return NULL;
+    }
+
+    // copy the formula
+    pFormula = ABC_ALLOC( char, strlen(pFormInit) + 3 );
+    sprintf( pFormula, "(%s)", pFormInit );
+
+    // start the stacks
+    pStackFn = Vec_PtrAlloc( 100 );
+    pStackOp = Vec_IntAlloc( 100 );
+
+    Flag = MIO_EQN_FLAG_START;
+    for ( pTemp = pFormula; *pTemp; pTemp++ )
+	{
+		switch ( *pTemp )
+	    {
+		// skip all spaces, tabs, and end-of-lines
+        case ' ':
+        case '\t':
+        case '\r':
+        case '\n':
+			continue;
+		case MIO_EQN_SYM_CONST0:
+		    Vec_PtrPush( pStackFn, Exp_Const0() );  // Cudd_Ref( b0 );
+			if ( Flag == MIO_EQN_FLAG_VAR )
+			{
+				fprintf( stdout, "Mio_ParseFormula(): No operation symbol before constant 0.\n" );
+				Flag = MIO_EQN_FLAG_ERROR; 
+                break;
+			}
+            Flag = MIO_EQN_FLAG_VAR; 
+            break;
+		case MIO_EQN_SYM_CONST1:
+		    Vec_PtrPush( pStackFn, Exp_Const1() );  //  Cudd_Ref( b1 );
+			if ( Flag == MIO_EQN_FLAG_VAR )
+			{
+				fprintf( stdout, "Mio_ParseFormula(): No operation symbol before constant 1.\n" );
+				Flag = MIO_EQN_FLAG_ERROR; 
+                break;
+			}
+            Flag = MIO_EQN_FLAG_VAR; 
+            break;
+		case MIO_EQN_SYM_NEG:
+			if ( Flag == MIO_EQN_FLAG_VAR )
+			{// if NEGBEF follows a variable, AND is assumed
+				Vec_IntPush( pStackOp, MIO_EQN_OPER_AND );
+				Flag = MIO_EQN_FLAG_OPER;
+			}
+    		Vec_IntPush( pStackOp, MIO_EQN_OPER_NEG );
+			break;
+		case MIO_EQN_SYM_NEGAFT:
+			if ( Flag != MIO_EQN_FLAG_VAR )
+			{// if there is no variable before NEGAFT, it is an error
+				fprintf( stdout, "Mio_ParseFormula(): No variable is specified before the negation suffix.\n" );
+				Flag = MIO_EQN_FLAG_ERROR; 
+                break;
+			}
+			else // if ( Flag == PARSE_FLAG_VAR )
+				Vec_PtrPush( pStackFn, Exp_Not( (Vec_Int_t *)Vec_PtrPop(pStackFn) ) );
+			break;
+        case MIO_EQN_SYM_AND:
+        case MIO_EQN_SYM_AND2:
+        case MIO_EQN_SYM_OR:
+        case MIO_EQN_SYM_OR2:
+        case MIO_EQN_SYM_XOR:
+			if ( Flag != MIO_EQN_FLAG_VAR )
+			{
+				fprintf( stdout, "Mio_ParseFormula(): There is no variable before AND, EXOR, or OR.\n" );
+				Flag = MIO_EQN_FLAG_ERROR; 
+                break;
+			}
+			if ( *pTemp == MIO_EQN_SYM_AND || *pTemp == MIO_EQN_SYM_AND2 )
+				Vec_IntPush( pStackOp, MIO_EQN_OPER_AND );
+			else if ( *pTemp == MIO_EQN_SYM_OR || *pTemp == MIO_EQN_SYM_OR2 )
+				Vec_IntPush( pStackOp, MIO_EQN_OPER_OR );
+			else //if ( *pTemp == MIO_EQN_SYM_XOR )
+				Vec_IntPush( pStackOp, MIO_EQN_OPER_XOR );
+			Flag = MIO_EQN_FLAG_OPER; 
+            break;
+		case MIO_EQN_SYM_OPEN:
+			if ( Flag == MIO_EQN_FLAG_VAR )
+            {
+				Vec_IntPush( pStackOp, MIO_EQN_OPER_AND );
+//				fprintf( stdout, "Mio_ParseFormula(): An opening paranthesis follows a var without operation sign.\n" ); 
+//				Flag = MIO_EQN_FLAG_ERROR; 
+//              break; 
+            }
+			Vec_IntPush( pStackOp, MIO_EQN_OPER_MARK );
+			// after an opening bracket, it feels like starting over again
+			Flag = MIO_EQN_FLAG_START; 
+            break;
+		case MIO_EQN_SYM_CLOSE:
+			if ( Vec_IntSize( pStackOp ) != 0 )
+            {
+				while ( 1 )
+			    {
+				    if ( Vec_IntSize( pStackOp ) == 0 )
+					{
+						fprintf( stdout, "Mio_ParseFormula(): There is no opening paranthesis\n" );
+						Flag = MIO_EQN_FLAG_ERROR; 
+                        break;
+					}
+					Oper = Vec_IntPop( pStackOp );
+					if ( Oper == MIO_EQN_OPER_MARK )
+						break;
+
+                    // perform the given operation
+                    if ( Mio_ParseFormulaOper( pMan, nVars, pStackFn, Oper ) == NULL )
+	                {
+		                fprintf( stdout, "Mio_ParseFormula(): Unknown operation\n" );
+                        ABC_FREE( pFormula );
+                        Vec_PtrFreeP( &pStackFn );
+                        Vec_IntFreeP( &pStackOp );
+		                return NULL;
+	                }
+			    }
+            }
+		    else
+			{
+				fprintf( stdout, "Mio_ParseFormula(): There is no opening paranthesis\n" );
+				Flag = MIO_EQN_FLAG_ERROR; 
+                break;
+			}
+			if ( Flag != MIO_EQN_FLAG_ERROR )
+			    Flag = MIO_EQN_FLAG_VAR; 
+			break;
+
+
+		default:
+            // scan the next name
+            for ( i = 0; pTemp[i] && 
+                         pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' &&
+                         pTemp[i] != MIO_EQN_SYM_AND && pTemp[i] != MIO_EQN_SYM_AND2 && pTemp[i] != MIO_EQN_SYM_OR && pTemp[i] != MIO_EQN_SYM_OR2 && 
+                         pTemp[i] != MIO_EQN_SYM_XOR && pTemp[i] != MIO_EQN_SYM_NEGAFT && pTemp[i] != MIO_EQN_SYM_CLOSE; 
+                  i++ )
+              {
+				    if ( pTemp[i] == MIO_EQN_SYM_NEG || pTemp[i] == MIO_EQN_SYM_OPEN )
+				    {
+					    fprintf( stdout, "Mio_ParseFormula(): The negation sign or an opening paranthesis inside the variable name.\n" );
+					    Flag = MIO_EQN_FLAG_ERROR; 
+                        break;
+				    }
+              }
+            // variable name is found
+            fFound = 0;
+//            Vec_PtrForEachEntry( char *, vVarNames, pName, v )
+            for ( v = 0; v < nVars; v++ )
+            {
+                pName = ppVarNames[v];
+                if ( strncmp(pTemp, pName, i) == 0 && strlen(pName) == (unsigned)i )
+                {
+                    pTemp += i-1;
+                    fFound = 1;
+                    break;
+                }
+            }
+            if ( !fFound )
+			{ 
+				fprintf( stdout, "Mio_ParseFormula(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); 
+				Flag = MIO_EQN_FLAG_ERROR; 
+                break; 
+			}
+/*
+			if ( Flag == MIO_EQN_FLAG_VAR )
+            {
+				fprintf( stdout, "Mio_ParseFormula(): The variable name \"%s\" follows another var without operation sign.\n", pTemp ); 
+				Flag = MIO_EQN_FLAG_ERROR; 
+                break; 
+            }
+*/
+			if ( Flag == MIO_EQN_FLAG_VAR )
+				Vec_IntPush( pStackOp, MIO_EQN_OPER_AND );
+
+			Vec_PtrPush( pStackFn, Exp_Var(v) ); // Cudd_Ref( pbVars[v] );
+            Flag = MIO_EQN_FLAG_VAR; 
+            break;
+	    }
+
+		if ( Flag == MIO_EQN_FLAG_ERROR )
+			break;      // error exit
+		else if ( Flag == MIO_EQN_FLAG_START )
+			continue;  //  go on parsing
+		else if ( Flag == MIO_EQN_FLAG_VAR )
+			while ( 1 )
+			{  // check if there are negations in the OpStack     
+				if ( Vec_IntSize( pStackOp ) == 0 )
+					break;
+                Oper = Vec_IntPop( pStackOp );
+				if ( Oper != MIO_EQN_OPER_NEG )
+                {
+					Vec_IntPush( pStackOp, Oper );
+					break;
+                }
+				else
+				{
+      				Vec_PtrPush( pStackFn, Exp_Not((Vec_Int_t *)Vec_PtrPop(pStackFn)) );
+				}
+			}
+		else // if ( Flag == MIO_EQN_FLAG_OPER )
+			while ( 1 )
+			{  // execute all the operations in the OpStack
+			   // with precedence higher or equal than the last one
+				Oper1 = Vec_IntPop( pStackOp ); // the last operation
+				if ( Vec_IntSize( pStackOp ) == 0 ) 
+				{  // if it is the only operation, push it back
+					Vec_IntPush( pStackOp, Oper1 );
+					break;
+				}
+				Oper2 = Vec_IntPop( pStackOp ); // the operation before the last one
+				if ( Oper2 >= Oper1 )  
+				{  // if Oper2 precedence is higher or equal, execute it
+                    if ( Mio_ParseFormulaOper( pMan, nVars, pStackFn, Oper2 ) == NULL )
+	                {
+		                fprintf( stdout, "Mio_ParseFormula(): Unknown operation\n" );
+                        ABC_FREE( pFormula );
+                        Vec_PtrFreeP( &pStackFn );
+                        Vec_IntFreeP( &pStackOp );
+		                return NULL;
+	                }
+					Vec_IntPush( pStackOp,  Oper1 );     // push the last operation back
+				}
+				else
+				{  // if Oper2 precedence is lower, push them back and done
+					Vec_IntPush( pStackOp, Oper2 );
+					Vec_IntPush( pStackOp, Oper1 );
+					break;
+				}
+			}
+    }
+
+	if ( Flag != MIO_EQN_FLAG_ERROR )
+    {
+		if ( Vec_PtrSize(pStackFn) != 0 )
+	    {	
+			gFunc = (Vec_Int_t *)Vec_PtrPop(pStackFn);
+			if ( Vec_PtrSize(pStackFn) == 0 )
+				if ( Vec_IntSize( pStackOp ) == 0 )
+                {
+//                    Cudd_Deref( gFunc );
+                    ABC_FREE( pFormula );
+                    Vec_PtrFreeP( &pStackFn );
+                    Vec_IntFreeP( &pStackOp );
+					return Exp_Reverse(gFunc);
+                }
+				else
+					fprintf( stdout, "Mio_ParseFormula(): Something is left in the operation stack\n" );
+			else
+				fprintf( stdout, "Mio_ParseFormula(): Something is left in the function stack\n" );
+	    }
+	    else
+			fprintf( stdout, "Mio_ParseFormula(): The input string is empty\n" );
+    }
+    ABC_FREE( pFormula );
+    Vec_PtrFreeP( &pStackFn );
+    Vec_IntFreeP( &pStackOp );
+	return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the TT corresponding to the equation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Wrd_t * Mio_ParseFormulaTruth( char * pFormInit, char ** ppVarNames, int nVars )
+{
+    Vec_Int_t * vExpr;
+    Vec_Wrd_t * vTruth;
+    // derive expression
+    vExpr = Mio_ParseFormula( pFormInit, ppVarNames, nVars );
+    if ( vExpr == NULL )
+        return NULL;
+    // convert it into a truth table
+    vTruth = Vec_WrdStart( Abc_Truth6WordNum(nVars) );
+    Exp_Truth( nVars, vExpr, Vec_WrdArray(vTruth) );
+    Vec_IntFree( vExpr );
+    return vTruth;
+}
+void Mio_ParseFormulaTruthTest( char * pFormInit, char ** ppVarNames, int nVars )
+{
+    Vec_Wrd_t * vTruth;
+    vTruth = Mio_ParseFormulaTruth( pFormInit, ppVarNames, nVars );
+//    Kit_DsdPrintFromTruth( (unsigned *)Vec_WrdArray(vTruth), nVars ); printf( "\n" );
+    Vec_WrdFree( vTruth );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the gate's formula essentially depends on all variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_ParseCheckName( Mio_Gate_t * pGate, char ** ppStr )
+{
+    Mio_Pin_t * pPin;
+    int i, iBest = -1;
+    // find the longest pin name that matches substring
+    char * pNameBest = NULL;
+    for ( pPin = Mio_GateReadPins(pGate), i = 0; pPin; pPin = Mio_PinReadNext(pPin), i++ )
+        if ( !strncmp( *ppStr, Mio_PinReadName(pPin), strlen(Mio_PinReadName(pPin)) ) )
+            if ( pNameBest == NULL || strlen(pNameBest) < strlen(Mio_PinReadName(pPin)) )
+                pNameBest = Mio_PinReadName(pPin), iBest = i;
+    // if pin is not found, return -1
+    if ( pNameBest )
+        *ppStr += strlen(pNameBest) - 1;
+    return iBest;
+}
+int Mio_ParseCheckFormula( Mio_Gate_t * pGate, char * pForm )
+{
+    Mio_Pin_t * pPin;
+    char * pStr;
+    int i, iPin, fVisit[32] = {0};
+    if ( Mio_GateReadPins(pGate) == NULL || !strcmp(Mio_PinReadName(Mio_GateReadPins(pGate)), "*") )
+        return 1;
+/*
+    // find the equality sign
+    pForm = strstr( pForm, "=" );
+    if ( pForm == NULL )
+    {
+        printf( "Skipping gate \"%s\" because formula \"%s\" has not equality sign (=).\n", pGate->pName, pForm );
+        return 0;
+    }
+*/
+//printf( "Checking gate %s\n", pGate->pName );
+
+    for ( pStr = pForm; *pStr; pStr++ )
+    {
+        if ( *pStr == ' ' ||
+             *pStr == MIO_EQN_SYM_OPEN ||   
+             *pStr == MIO_EQN_SYM_CLOSE ||  
+             *pStr == MIO_EQN_SYM_CONST0 || 
+             *pStr == MIO_EQN_SYM_CONST1 || 
+             *pStr == MIO_EQN_SYM_NEG ||    
+             *pStr == MIO_EQN_SYM_NEGAFT || 
+             *pStr == MIO_EQN_SYM_AND ||    
+             *pStr == MIO_EQN_SYM_AND2 ||   
+             *pStr == MIO_EQN_SYM_XOR ||    
+             *pStr == MIO_EQN_SYM_OR ||     
+             *pStr == MIO_EQN_SYM_OR2 
+           )
+           continue;
+        // return the number of the pin which has this name
+        iPin = Mio_ParseCheckName( pGate, &pStr );
+        if ( iPin == -1 )
+        {
+            printf( "Skipping gate \"%s\" because substring \"%s\" does not match with a pin name.\n", pGate->pName, pStr );
+            return 0;
+        }
+        assert( iPin < 32 );
+        fVisit[iPin] = 1;
+    }
+    // check that all pins are used
+    for ( pPin = Mio_GateReadPins(pGate), i = 0; pPin; pPin = Mio_PinReadNext(pPin), i++ )
+        if ( fVisit[i] == 0 )
+        {
+//            printf( "Skipping gate \"%s\" because pin \"%s\" does not appear in the formula \"%s\".\n", pGate->pName, Mio_PinReadName(pPin), pForm );
+            return 0;
+        }
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mio/mioRead.c b/abc-build/src/map/mio/mioRead.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mio/mioRead.c
@@ -0,0 +1,749 @@
+/**CFile****************************************************************
+
+  FileName    [mioRead.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [File reading/writing for technology mapping.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: mioRead.c,v 1.9 2004/10/19 06:40:16 satrajit Exp $]
+
+***********************************************************************/
+
+#include <ctype.h>
+#include "mioInt.h"
+#include "base/io/ioAbc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+static Mio_Library_t * Mio_LibraryReadOne( char * FileName, int fExtendedFormat, st__table * tExcludeGate, int fVerbose );
+static Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int fVerbose );
+static int             Mio_LibraryReadInternal( Mio_Library_t * pLib, char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int fVerbose );
+static Mio_Gate_t *    Mio_LibraryReadGate( char ** ppToken, int fExtendedFormat );
+static Mio_Pin_t *     Mio_LibraryReadPin( char ** ppToken, int fExtendedFormat );
+static char *          chomp( char *s );
+static void            Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib );
+static void            Io_ReadFileRemoveComments( char * pBuffer, int * pnDots, int * pnLines );
+
+/**Function*************************************************************
+
+  Synopsis    [Read the genlib type of library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mio_Library_t * Mio_LibraryRead( char * FileName, char * pBuffer, char * ExcludeFile, int fVerbose )
+{
+    Mio_Library_t * pLib;
+    int num;
+
+    st__table * tExcludeGate = 0;
+
+    if ( ExcludeFile )
+    {
+        tExcludeGate = st__init_table(strcmp, st__strhash);
+        if ( (num = Mio_LibraryReadExclude( ExcludeFile, tExcludeGate )) == -1 )
+        {
+            st__free_table( tExcludeGate );
+            tExcludeGate = 0;
+            return 0;
+        }
+        fprintf ( stdout, "Read %d gates from exclude file\n", num );
+    }
+
+    if ( pBuffer == NULL )
+        pLib = Mio_LibraryReadOne( FileName, 0, tExcludeGate, fVerbose );       // try normal format first ..
+    else
+    {
+        pLib = Mio_LibraryReadBuffer( pBuffer, 0, tExcludeGate, fVerbose );       // try normal format first ..
+        if ( pLib )
+            pLib->pName = Abc_UtilStrsav( Extra_FileNameGenericAppend(FileName, ".genlib") );
+    }
+    if ( pLib == NULL )
+    {
+        if ( pBuffer == NULL )
+            pLib = Mio_LibraryReadOne( FileName, 1, tExcludeGate, fVerbose );       // try normal format first ..
+        else
+        {
+            pLib = Mio_LibraryReadBuffer( pBuffer, 1, tExcludeGate, fVerbose );       // try normal format first ..
+            if ( pLib )
+                pLib->pName = Abc_UtilStrsav( Extra_FileNameGenericAppend(FileName, ".genlib") );
+        }
+        if ( pLib != NULL )
+            printf ( "Warning: Read extended genlib format but ignoring extensions\n" );
+    }
+    if ( tExcludeGate )
+        st__free_table( tExcludeGate );
+
+    return pLib;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read contents of the file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Mio_ReadFile( char * FileName, int fAddEnd )
+{
+    char * pBuffer;
+    FILE * pFile;
+    int nFileSize;
+    int RetValue;
+
+    // open the BLIF file for binary reading
+    pFile = Io_FileOpen( FileName, "open_path", "rb", 1 );
+//    pFile = fopen( FileName, "rb" );
+    // if we got this far, file should be okay otherwise would
+    // have been detected by caller
+    assert ( pFile != NULL );
+    // get the file size, in bytes
+    fseek( pFile, 0, SEEK_END );  
+    nFileSize = ftell( pFile );  
+    // move the file current reading position to the beginning
+    rewind( pFile ); 
+    // load the contents of the file into memory
+    pBuffer   = ABC_ALLOC( char, nFileSize + 10 );
+    RetValue = fread( pBuffer, nFileSize, 1, pFile );
+    // terminate the string with '\0'
+    pBuffer[ nFileSize ] = '\0';
+    if ( fAddEnd )
+        strcat( pBuffer, "\n.end\n" );
+    // close file
+    fclose( pFile );
+    return pBuffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read the genlib type of library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int fVerbose )
+{
+    Mio_Library_t * pLib;
+
+    // allocate the genlib structure
+    pLib = ABC_CALLOC( Mio_Library_t, 1 );
+    pLib->tName2Gate = st__init_table(strcmp, st__strhash);
+    pLib->pMmFlex = Mem_FlexStart();
+    pLib->vCube = Vec_StrAlloc( 100 );
+
+    Io_ReadFileRemoveComments( pBuffer, NULL, NULL );
+
+    // parse the contents of the file
+    if ( Mio_LibraryReadInternal( pLib, pBuffer, fExtendedFormat, tExcludeGate, fVerbose ) )
+    {
+        Mio_LibraryDelete( pLib );
+        return NULL;
+    }
+
+    // derive the functinality of gates
+    if ( Mio_LibraryParseFormulas( pLib ) )
+    {
+        printf( "Mio_LibraryRead: Had problems parsing formulas.\n" );
+        Mio_LibraryDelete( pLib );
+        return NULL;
+    }
+
+    // detect INV and NAND2
+    Mio_LibraryDetectSpecialGates( pLib );
+//Mio_WriteLibrary( stdout, pLib );
+    return pLib;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read the genlib type of library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mio_Library_t * Mio_LibraryReadOne( char * FileName, int fExtendedFormat, st__table * tExcludeGate, int fVerbose )
+{
+    Mio_Library_t * pLib;
+    char * pBuffer;
+    // read the file and clean comments
+    // pBuffer = Io_ReadFileFileContents( FileName, NULL );
+    // we don't use above function but actually do the same thing explicitly
+    // to handle open_path expansion correctly
+    pBuffer = Mio_ReadFile( FileName, 1 );
+    if ( pBuffer == NULL )
+        return NULL;
+    pLib = Mio_LibraryReadBuffer( pBuffer, fExtendedFormat, tExcludeGate, fVerbose );
+    ABC_FREE( pBuffer );
+    if ( pLib )
+        pLib->pName = Abc_UtilStrsav( FileName );
+    return pLib;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read the genlib type of library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_LibraryReadInternal( Mio_Library_t * pLib, char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int fVerbose )
+{
+    Mio_Gate_t * pGate, ** ppGate;
+    char * pToken;
+    int nGates = 0;
+    int nDel = 0;
+
+    // start the linked list of gates
+    pLib->pGates = NULL;
+    ppGate = &pLib->pGates;
+
+    // read gates one by one
+    pToken = strtok( pBuffer, " \t\r\n" );
+    while ( pToken && (strcmp( pToken, MIO_STRING_GATE ) == 0 || strcmp( pToken, MIO_STRING_LATCH ) == 0) )
+    {
+        // skip latches
+        if ( strcmp( pToken, MIO_STRING_LATCH ) == 0 )
+        {
+            while ( pToken && strcmp( pToken, MIO_STRING_GATE ) != 0 && strcmp( pToken, ".end" ) != 0 )
+            {
+                if ( strcmp( pToken, MIO_STRING_LATCH ) == 0 )
+                {
+                    pToken = strtok( NULL, " \t\r\n" );
+                    printf( "Skipping latch \"%s\"...\n", pToken );
+                    continue;
+                }
+                pToken = strtok( NULL, " \t\r\n" );
+            }
+            if ( !(pToken && strcmp( pToken, MIO_STRING_GATE ) == 0) )
+                break;
+        }
+
+        // derive the next gate
+        pGate = Mio_LibraryReadGate( &pToken, fExtendedFormat );
+        if ( pGate == NULL )
+            return 1;
+
+        // skip the gate if its formula has problems
+        if ( !Mio_ParseCheckFormula(pGate, pGate->pForm) )
+        {
+            Mio_GateDelete( pGate );
+            continue;
+        }
+       
+        // set the library
+        pGate->pLib = pLib;
+
+        // printf ("Processing: '%s'\n", pGate->pName);
+
+        if ( tExcludeGate && st__is_member( tExcludeGate, pGate->pName ) )
+        {
+            //printf ("Excluding: '%s'\n", pGate->pName);
+            Mio_GateDelete( pGate );
+            nDel++;
+        } 
+        else
+        {
+            // add this gate to the list
+            *ppGate = pGate;
+            ppGate  = &pGate->pNext;
+            nGates++;
+
+            // remember this gate by name
+            if ( ! st__is_member( pLib->tName2Gate, pGate->pName ) )
+                st__insert( pLib->tName2Gate, pGate->pName, (char *)pGate );
+            else
+            {
+                Mio_Gate_t * pBase = Mio_LibraryReadGateByName( pLib, pGate->pName, NULL );
+                if ( pBase->pTwin != NULL )
+                {
+                    printf( "Gates with more than 2 outputs are not supported.\n" );
+                    continue;
+                }
+                pBase->pTwin = pGate;
+                pGate->pTwin = pBase;
+//                printf( "Gate \"%s\" appears two times. Creating a 2-output gate.\n", pGate->pName );
+            }
+        }
+    }
+
+    if ( nGates == 0 )
+    {
+        printf( "The library contains no gates.\n" );
+        return 1;
+    }
+
+    // check what is the last word read
+    if ( pToken && strcmp( pToken, ".end" ) != 0 )
+        return 1;
+
+    if ( nDel != 0 ) 
+        printf( "Actually excluded %d cells\n", nDel );
+
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read the genlib type of gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, int fExtendedFormat )
+{
+    Mio_Gate_t * pGate;
+    Mio_Pin_t * pPin, ** ppPin;
+    char * pToken = *ppToken;
+
+    // allocate the gate structure
+    pGate = ABC_CALLOC( Mio_Gate_t, 1 );
+
+    // read the name
+    pToken = strtok( NULL, " \t\r\n" );
+    pGate->pName = Abc_UtilStrsav( pToken );
+
+    // read the area
+    pToken = strtok( NULL, " \t\r\n" );
+    pGate->dArea = atof( pToken );
+
+    // read the formula
+
+    // first the output name
+    pToken = strtok( NULL, "=" );
+    pGate->pOutName = chomp( pToken );
+
+    // then rest of the expression 
+    pToken = strtok( NULL, ";" );
+    pGate->pForm = chomp( pToken );
+
+    // read the pin info
+    // start the linked list of pins
+    pGate->pPins = NULL;
+    ppPin = &pGate->pPins;
+
+    // read gates one by one
+    pToken = strtok( NULL, " \t\r\n" );
+    while ( pToken && strcmp( pToken, MIO_STRING_PIN ) == 0 )
+    {
+        // derive the next gate
+        pPin = Mio_LibraryReadPin( &pToken, fExtendedFormat );
+        if ( pPin == NULL )
+        {
+            Mio_GateDelete( pGate );
+            *ppToken = pToken;
+            return NULL;
+        }
+        // add this pin to the list
+        *ppPin = pPin;
+        ppPin  = &pPin->pNext;
+        // get the next token
+        pToken = strtok( NULL, " \t\r\n" );
+    }
+
+    *ppToken = pToken;
+    return pGate;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Read the genlib type of pin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mio_Pin_t * Mio_LibraryReadPin( char ** ppToken, int fExtendedFormat )
+{
+    Mio_Pin_t * pPin;
+    char * pToken = *ppToken;
+
+    // allocate the gate structure
+    pPin = ABC_CALLOC( Mio_Pin_t, 1 );
+
+    // read the name
+    pToken = strtok( NULL, " \t\r\n" );
+    pPin->pName = Abc_UtilStrsav( pToken );
+
+    // read the pin phase
+    pToken = strtok( NULL, " \t\r\n" );
+    if ( strcmp( pToken, MIO_STRING_UNKNOWN ) == 0 )
+        pPin->Phase = MIO_PHASE_UNKNOWN;
+    else if ( strcmp( pToken, MIO_STRING_INV ) == 0 )
+        pPin->Phase = MIO_PHASE_INV;
+    else if ( strcmp( pToken, MIO_STRING_NONINV ) == 0 )
+        pPin->Phase = MIO_PHASE_NONINV;
+    else 
+    {
+        printf( "Cannot read pin phase specification\n" );
+        Mio_PinDelete( pPin );
+        *ppToken = pToken;
+        return NULL;
+    }
+
+    pToken = strtok( NULL, " \t\r\n" );
+    pPin->dLoadInput = atof( pToken );
+
+    pToken = strtok( NULL, " \t\r\n" );
+    pPin->dLoadMax = atof( pToken );
+
+    pToken = strtok( NULL, " \t\r\n" );
+    pPin->dDelayBlockRise = atof( pToken );
+
+    pToken = strtok( NULL, " \t\r\n" );
+    pPin->dDelayFanoutRise = atof( pToken );
+
+    pToken = strtok( NULL, " \t\r\n" );
+    pPin->dDelayBlockFall = atof( pToken );
+
+    pToken = strtok( NULL, " \t\r\n" );
+    pPin->dDelayFanoutFall = atof( pToken );
+
+    if ( fExtendedFormat )
+    {
+        /* In extended format, the field after dDelayFanoutRise
+         * is to be ignored
+         **/
+
+        pPin->dDelayBlockFall  = pPin->dDelayFanoutFall;
+
+        pToken = strtok( NULL, " \t" );
+        pPin->dDelayFanoutFall = atof( pToken );
+
+        /* last field is ignored */
+        pToken = strtok( NULL, " \t\r\n" );
+    }
+
+    if ( pPin->dDelayBlockRise > pPin->dDelayBlockFall )
+        pPin->dDelayBlockMax = pPin->dDelayBlockRise;
+    else
+        pPin->dDelayBlockMax = pPin->dDelayBlockFall;
+
+    *ppToken = pToken;
+    return pPin;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates string and returns it with leading and 
+               trailing spaces removed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * chomp( char *s )
+{
+    char *a, *b, *c;
+    // remove leading spaces
+    for ( b = s; *b; b++ )
+        if ( !isspace(*b) )
+            break;
+    // strsav the string
+    a = strcpy( ABC_ALLOC(char, strlen(b)+1), b );
+    // remove trailing spaces
+    for ( c = a+strlen(a); c > a; c-- )
+        if ( *c == 0 || isspace(*c) )
+            *c = 0;
+        else
+            break;
+    return a;
+}   
+        
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_LibraryCompareGatesByArea( Mio_Gate_t ** pp1, Mio_Gate_t ** pp2 )
+{
+    double Diff = (*pp1)->dArea - (*pp2)->dArea;
+    if ( Diff < 0.0 )
+        return -1;
+    if ( Diff > 0.0 ) 
+        return 1;
+    return 0; 
+}
+        
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_LibraryCompareGatesByName( Mio_Gate_t ** pp1, Mio_Gate_t ** pp2 )
+{
+    int Diff = strcmp( (*pp1)->pName, (*pp2)->pName );
+    if ( Diff < 0.0 )
+        return -1;
+    if ( Diff > 0.0 ) 
+        return 1;
+    return 0; 
+}
+        
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_LibrarySortGates( Mio_Library_t * pLib )
+{
+    Mio_Gate_t ** ppGates, * pGate;
+    int i = 0;
+    ppGates = ABC_ALLOC( Mio_Gate_t *, pLib->nGates );
+    Mio_LibraryForEachGate( pLib, pGate )
+        ppGates[i++] = pGate;
+    assert( i == pLib->nGates );
+    // sort gates by area
+    pLib->ppGates0 = ABC_ALLOC( Mio_Gate_t *, pLib->nGates );
+    for ( i = 0; i < pLib->nGates; i++ )
+        pLib->ppGates0[i] = ppGates[i];
+    qsort( (void *)ppGates, pLib->nGates, sizeof(void *), 
+            (int (*)(const void *, const void *)) Mio_LibraryCompareGatesByArea );
+    for ( i = 0; i < pLib->nGates; i++ )
+        ppGates[i]->pNext = (i < pLib->nGates-1)? ppGates[i+1] : NULL;
+    pLib->pGates = ppGates[0];
+    ABC_FREE( ppGates );
+    // sort gates by name
+    pLib->ppGatesName = ABC_ALLOC( Mio_Gate_t *, pLib->nGates );
+    for ( i = 0; i < pLib->nGates; i++ )
+        pLib->ppGatesName[i] = pLib->ppGates0[i];
+    qsort( (void *)pLib->ppGatesName, pLib->nGates, sizeof(void *), 
+            (int (*)(const void *, const void *)) Mio_LibraryCompareGatesByName );
+}
+        
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Mio_Gate_t * Mio_GateCompare( Mio_Gate_t * pThis, Mio_Gate_t * pNew, word uTruth )
+{
+    if ( pNew->uTruth != uTruth )
+        return pThis;
+    if ( pThis == NULL )
+        return pNew;
+    if ( pThis->dArea > pNew->dArea || (pThis->dArea == pNew->dArea && strcmp(pThis->pName, pNew->pName) > 0) )
+        return pNew;
+    return pThis;
+}
+void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib )
+{
+    Mio_Gate_t * pGate;
+    word uFuncBuf, uFuncInv, uFuncNand2, uFuncAnd2;
+
+    Mio_LibrarySortGates( pLib );
+
+    uFuncBuf   = ABC_CONST(0xAAAAAAAAAAAAAAAA);
+    uFuncAnd2  = ABC_CONST(0xAAAAAAAAAAAAAAAA) & ABC_CONST(0xCCCCCCCCCCCCCCCC);
+    uFuncInv   = ~uFuncBuf;
+    uFuncNand2 = ~uFuncAnd2;
+
+    // get smallest-area buffer
+    Mio_LibraryForEachGate( pLib, pGate )
+        pLib->pGateBuf = Mio_GateCompare( pLib->pGateBuf, pGate, uFuncBuf );
+    if ( pLib->pGateBuf == NULL )
+    {
+        printf( "Warnings: genlib library reader cannot detect the buffer gate.\n" );
+        printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" );
+    }
+ 
+    // get smallest-area inverter
+    Mio_LibraryForEachGate( pLib, pGate )
+        pLib->pGateInv = Mio_GateCompare( pLib->pGateInv, pGate, uFuncInv );
+    if ( pLib->pGateInv == NULL )
+    {
+        printf( "Warnings: genlib library reader cannot detect the invertor gate.\n" );
+        printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" );
+    }
+
+    // get smallest-area NAND2/AND2 gates
+    Mio_LibraryForEachGate( pLib, pGate )
+        pLib->pGateNand2 = Mio_GateCompare( pLib->pGateNand2, pGate, uFuncNand2 );
+    Mio_LibraryForEachGate( pLib, pGate )
+        pLib->pGateAnd2 = Mio_GateCompare( pLib->pGateAnd2, pGate, uFuncAnd2 );
+    if ( pLib->pGateAnd2 == NULL && pLib->pGateNand2 == NULL )
+    {
+        printf( "Warnings: genlib library reader cannot detect the AND2 or NAND2 gate.\n" );
+        printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [populate hash table of gates to be exlcuded from genlib]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_LibraryReadExclude( char * ExcludeFile, st__table * tExcludeGate )
+{
+    int nDel = 0;
+    FILE *pEx;
+    char buffer[128];
+
+    assert ( tExcludeGate );
+
+    if ( ExcludeFile )
+    {
+        pEx = fopen( ExcludeFile, "r" );
+
+        if ( pEx == NULL )
+        {
+            fprintf ( stdout, "Error: Could not open exclude file %s. Stop.\n", ExcludeFile );
+            return -1;
+        }
+
+        while (1 == fscanf( pEx, "%127s", buffer ))
+        {
+            //printf ("Read: '%s'\n", buffer );
+            st__insert( tExcludeGate, Abc_UtilStrsav( buffer ), (char *)0 );
+            nDel++;
+        }
+
+        fclose( pEx );
+    }
+
+    return nDel;
+}
+    
+/**Function*************************************************************
+
+  Synopsis    [Eliminates comments from the input file.]
+
+  Description [As a byproduct, this procedure also counts the number
+  lines and dot-statements in the input file. This also joins non-comment 
+  lines that are joined with a backspace '\']
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Io_ReadFileRemoveComments( char * pBuffer, int * pnDots, int * pnLines )
+{
+    char * pCur;
+    int nDots, nLines;
+    // scan through the buffer and eliminate comments
+    // (in the BLIF file, comments are lines starting with "#")
+    nDots = nLines = 0;
+    for ( pCur = pBuffer; *pCur; pCur++ )
+    {
+        // if this is the beginning of comment
+        // clean it with spaces until the new line statement
+        if ( *pCur == '#' )
+            while ( *pCur != '\n' )
+                *pCur++ = ' ';
+	
+        // count the number of new lines and dots
+        if ( *pCur == '\n' ) {
+	    if (*(pCur-1)=='\r') {
+		// DOS(R) file support
+		if (*(pCur-2)!='\\') nLines++;
+		else {
+		    // rewind to backslash and overwrite with a space
+		    *(pCur-2) = ' ';
+		    *(pCur-1) = ' ';
+		    *pCur = ' ';
+		}
+	    } else {
+		// UNIX(TM) file support
+		if (*(pCur-1)!='\\') nLines++;
+		else {
+		    // rewind to backslash and overwrite with a space
+		    *(pCur-1) = ' ';
+		    *pCur = ' ';
+		}
+	    }
+	}
+        else if ( *pCur == '.' )
+            nDots++;
+    }
+    if ( pnDots )
+        *pnDots = nDots; 
+    if ( pnLines )
+        *pnLines = nLines; 
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mio/mioSop.c b/abc-build/src/map/mio/mioSop.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mio/mioSop.c
@@ -0,0 +1,333 @@
+/**CFile****************************************************************
+
+  FileName    [mioSop.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Derives SOP from Boolean expression.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: mioSop.c,v 1.4 2004/06/28 14:20:25 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mioInt.h"
+#include "exp.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline unsigned Mio_CubeVar0( int v )                       { return (1<< (v<<1)   );                   }
+static inline unsigned Mio_CubeVar1( int v )                       { return (1<<((v<<1)+1));                   }
+static inline int      Mio_CubeHasVar0( unsigned x, int v )        { return (x & Mio_CubeVar0(v)) > 0;         }
+static inline int      Mio_CubeHasVar1( unsigned x, int v )        { return (x & Mio_CubeVar1(v)) > 0;         }
+static inline int      Mio_CubeEmpty( unsigned x )                 { return (x & (x>>1) & 0x55555555) != 0;    }
+static inline unsigned Mio_CubeAnd( unsigned x, unsigned y )       { return x | y;                             }
+static inline int      Mio_CubeContains( unsigned x, unsigned y )  { return (x | y) == y;                      } // x contains y
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Push while performing SCC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_SopPushSCC( Vec_Int_t * p, unsigned c )
+{
+    unsigned Entry;
+    int i, k = 0;
+    Vec_IntForEachEntry( p, Entry, i )
+    {
+        if ( Mio_CubeContains( Entry, c ) ) // Entry contains c
+        {
+            assert( i == k );
+            return;
+        }
+        if ( Mio_CubeContains( c, Entry ) ) // c contains Entry
+            continue;
+        Vec_IntWriteEntry( p, k++, Entry );
+    }
+    Vec_IntShrink( p, k );
+    Vec_IntPush( p, c );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Make the OR of two covers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Mio_SopCoverOr( Vec_Int_t * p, Vec_Int_t * q )
+{
+    Vec_Int_t * r;
+    unsigned Entry;
+    int i;
+    r = Vec_IntAlloc( Vec_IntSize(p) + Vec_IntSize(q) );
+    Vec_IntForEachEntry( p, Entry, i )
+        Vec_IntPush( r, Entry );
+    Vec_IntForEachEntry( q, Entry, i )
+        Mio_SopPushSCC( r, Entry );
+    return r;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Make the AND of two covers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Mio_SopCoverAnd( Vec_Int_t * p, Vec_Int_t * q )
+{
+    Vec_Int_t * r;
+    unsigned EntryP, EntryQ;
+    int i, k;
+    r = Vec_IntAlloc( Vec_IntSize(p) * Vec_IntSize(q) );
+    Vec_IntForEachEntry( p, EntryP, i )
+        Vec_IntForEachEntry( q, EntryQ, k )
+            if ( !Mio_CubeEmpty( Mio_CubeAnd(EntryP, EntryQ) ) )
+                Mio_SopPushSCC( r, Mio_CubeAnd(EntryP, EntryQ) );
+    return r;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create negative literal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Mio_SopVar0( int i )
+{
+    Vec_Int_t * vSop;
+    vSop = Vec_IntAlloc( 1 );
+    Vec_IntPush( vSop, Mio_CubeVar0(i) );
+    return vSop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create positive literal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Mio_SopVar1( int i )
+{
+    Vec_Int_t * vSop;
+    vSop = Vec_IntAlloc( 1 );
+    Vec_IntPush( vSop, Mio_CubeVar1(i) );
+    return vSop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create constant 0 literal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Mio_SopConst0()
+{
+    Vec_Int_t * vSop;
+    vSop = Vec_IntAlloc( 1 );
+    return vSop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create constant 1 literal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Mio_SopConst1()
+{
+    Vec_Int_t * vSop;
+    vSop = Vec_IntAlloc( 1 );
+    Vec_IntPush( vSop, 0 );
+    return vSop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives SOP representation as the char string.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Mio_SopDeriveFromArray( Vec_Int_t * vSop, int nVars, Vec_Str_t * vStr, int fPolarity )
+{
+    unsigned Entry;
+    int i, k;
+    Vec_StrClear( vStr );
+    if ( Vec_IntSize(vSop) == 0 )
+    {
+        Vec_StrPush( vStr, ' ' );
+        Vec_StrPush( vStr, (char)('1'-fPolarity) );
+        Vec_StrPush( vStr, '\n' );
+        Vec_StrPush( vStr, '\0' );
+        return Vec_StrArray( vStr );
+    }
+    if ( Vec_IntSize(vSop) == 1 && Vec_IntEntry(vSop, 0) == 0 )
+    {
+        Vec_StrPush( vStr, ' ' );
+        Vec_StrPush( vStr, (char)('0'+fPolarity) );
+        Vec_StrPush( vStr, '\n' );
+        Vec_StrPush( vStr, '\0' );
+        return Vec_StrArray( vStr );
+    }
+    // create cubes
+    Vec_IntForEachEntry( vSop, Entry, i )
+    {
+        for ( k = 0; k < nVars; k++ )
+        {
+            if ( Mio_CubeHasVar0( Entry, k ) )
+                Vec_StrPush( vStr, '0' );
+            else if ( Mio_CubeHasVar1( Entry, k ) )
+                Vec_StrPush( vStr, '1' );
+            else 
+                Vec_StrPush( vStr, '-' );
+        }
+        Vec_StrPush( vStr, ' ' );
+        Vec_StrPush( vStr, (char)('0'+fPolarity) );
+        Vec_StrPush( vStr, '\n' );
+    }
+    Vec_StrPush( vStr, '\0' );
+    return Vec_StrArray( vStr );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives SOP representation.]
+
+  Description [The SOP is guaranteed to be SCC-free but not minimal.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Mio_LibDeriveSop( int nVars, Vec_Int_t * vExpr, Vec_Str_t * vStr )
+{
+    Vec_Int_t * vSop;
+    Vec_Ptr_t * vSops0, * vSops1, * vTemp;
+    int i, Index0, Index1, fCompl0, fCompl1;
+    Vec_StrClear( vStr );
+    if ( Exp_IsConst0(vExpr) )
+    {
+        Vec_StrPrintStr( vStr, " 0\n" );
+        Vec_StrPush( vStr, '\0' );
+        return Vec_StrArray( vStr );
+    }
+    if ( Exp_IsConst1(vExpr) )
+    {
+        Vec_StrPrintStr( vStr, " 1\n" );
+        Vec_StrPush( vStr, '\0' );
+        return Vec_StrArray( vStr );
+    }
+    if ( Exp_IsLit(vExpr) )
+    {
+        for ( i = 0; i < nVars; i++ )
+            Vec_StrPush( vStr, '-' );
+        Vec_StrPrintStr( vStr, " 1\n" );
+        Vec_StrPush( vStr, '\0' );
+        assert( (Vec_IntEntry(vExpr,0) >> 1) < nVars );
+        Vec_StrWriteEntry( vStr, Vec_IntEntry(vExpr,0) >> 1, (char)('1' - (Vec_IntEntry(vExpr,0) & 1)) );
+        return Vec_StrArray( vStr );
+    }
+    vSops0 = Vec_PtrAlloc( nVars + Exp_NodeNum(vExpr) );
+    vSops1 = Vec_PtrAlloc( nVars + Exp_NodeNum(vExpr) );
+    for ( i = 0; i < nVars; i++ )
+    {
+        Vec_PtrPush( vSops0, Mio_SopVar0(i) );
+        Vec_PtrPush( vSops1, Mio_SopVar1(i) );
+    }
+    for ( i = 0; i < Exp_NodeNum(vExpr); i++ )
+    {
+        Index0  = Vec_IntEntry( vExpr, 2*i+0 ) >> 1;
+        Index1  = Vec_IntEntry( vExpr, 2*i+1 ) >> 1;
+        fCompl0 = Vec_IntEntry( vExpr, 2*i+0 ) & 1;
+        fCompl1 = Vec_IntEntry( vExpr, 2*i+1 ) & 1;
+        // positive polarity
+        vSop = Mio_SopCoverAnd( fCompl0 ? (Vec_Int_t *)Vec_PtrEntry(vSops0, Index0) : (Vec_Int_t *)Vec_PtrEntry(vSops1, Index0),
+                                fCompl1 ? (Vec_Int_t *)Vec_PtrEntry(vSops0, Index1) : (Vec_Int_t *)Vec_PtrEntry(vSops1, Index1) );
+        Vec_PtrPush( vSops1, vSop );
+        // negative polarity
+        vSop = Mio_SopCoverOr( fCompl0 ? (Vec_Int_t *)Vec_PtrEntry(vSops1, Index0) : (Vec_Int_t *)Vec_PtrEntry(vSops0, Index0),
+                               fCompl1 ? (Vec_Int_t *)Vec_PtrEntry(vSops1, Index1) : (Vec_Int_t *)Vec_PtrEntry(vSops0, Index1) );
+        Vec_PtrPush( vSops0, vSop );
+    }
+    // complement
+    if ( Vec_IntEntryLast(vExpr) & 1 )
+    {
+        vTemp  = vSops0;
+        vSops0 = vSops1;
+        vSops1 = vTemp;
+    }
+    // select the best polarity
+    if ( Vec_IntSize( (Vec_Int_t *)Vec_PtrEntryLast(vSops0) ) < Vec_IntSize( (Vec_Int_t *)Vec_PtrEntryLast(vSops1) ) )
+        vSop = (Vec_Int_t *)Vec_PtrEntryLast(vSops0);
+    else
+        vSop = (Vec_Int_t *)Vec_PtrEntryLast(vSops1);
+    // convert positive polarity into SOP
+    Mio_SopDeriveFromArray( vSop, nVars, vStr, (vSop == Vec_PtrEntryLast(vSops1)) );
+    Vec_VecFree( (Vec_Vec_t *)vSops0 );
+    Vec_VecFree( (Vec_Vec_t *)vSops1 );
+    return Vec_StrArray( vStr );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mio/mioUtils.c b/abc-build/src/map/mio/mioUtils.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mio/mioUtils.c
@@ -0,0 +1,1041 @@
+/**CFile****************************************************************
+
+  FileName    [mioUtils.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [File reading/writing for technology mapping.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: mioUtils.c,v 1.6 2004/09/03 18:02:20 satrajit Exp $]
+
+***********************************************************************/
+
+#include <math.h>
+#include "mioInt.h"
+#include "base/main/main.h"
+#include "exp.h"
+#include "misc/util/utilTruth.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_LibraryDelete( Mio_Library_t * pLib )
+{
+    Mio_Gate_t * pGate, * pGate2;
+    if ( pLib == NULL )
+        return;
+    // free the bindings of nodes to gates from this library for all networks
+    Abc_FrameUnmapAllNetworks( Abc_FrameGetGlobalFrame() );
+    // free the library
+    ABC_FREE( pLib->pName );
+    Mio_LibraryForEachGateSafe( pLib, pGate, pGate2 )
+        Mio_GateDelete( pGate );
+    Mem_FlexStop( pLib->pMmFlex, 0 );
+    Vec_StrFree( pLib->vCube );
+    if ( pLib->tName2Gate )
+        st__free_table( pLib->tName2Gate );
+//    if ( pLib->dd )
+//        Cudd_Quit( pLib->dd );
+    ABC_FREE( pLib->ppGates0 );
+    ABC_FREE( pLib->ppGatesName );
+    ABC_FREE( pLib );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_GateDelete( Mio_Gate_t * pGate )
+{
+    Mio_Pin_t * pPin, * pPin2;
+    if ( pGate->nInputs > 6 )
+        ABC_FREE( pGate->pTruth );
+    Vec_IntFreeP( &pGate->vExpr );
+    ABC_FREE( pGate->pOutName );
+    ABC_FREE( pGate->pName );
+    ABC_FREE( pGate->pForm );
+//    if ( pGate->bFunc )
+//        Cudd_RecursiveDeref( pGate->pLib->dd, pGate->bFunc );
+    Mio_GateForEachPinSafe( pGate, pPin, pPin2 )
+        Mio_PinDelete( pPin );   
+    ABC_FREE( pGate );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_PinDelete( Mio_Pin_t * pPin )
+{
+    ABC_FREE( pPin->pName );
+    ABC_FREE( pPin );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mio_Pin_t * Mio_PinDup( Mio_Pin_t * pPin )
+{
+    Mio_Pin_t * pPinNew;
+
+    pPinNew = ABC_ALLOC( Mio_Pin_t, 1 );
+    *pPinNew = *pPin;
+    pPinNew->pName = (pPinNew->pName ? Abc_UtilStrsav(pPinNew->pName) : NULL);
+    pPinNew->pNext = NULL;
+
+    return pPinNew;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Check if pin characteristics are the same.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_CheckPins( Mio_Pin_t * pPin1, Mio_Pin_t * pPin2 )
+{
+    if ( pPin1 == NULL || pPin2 == NULL )
+        return 1;
+    if ( pPin1->dLoadInput != pPin2->dLoadInput )
+        return 0;
+    if ( pPin1->dLoadMax != pPin2->dLoadMax )
+        return 0;
+    if ( pPin1->dDelayBlockRise != pPin2->dDelayBlockRise )
+        return 0;
+    if ( pPin1->dDelayFanoutRise != pPin2->dDelayFanoutRise )
+        return 0;
+    if ( pPin1->dDelayBlockFall != pPin2->dDelayBlockFall )
+        return 0;
+    if ( pPin1->dDelayFanoutFall != pPin2->dDelayFanoutFall )
+        return 0;
+    return 1;
+}
+int Mio_CheckGates( Mio_Library_t * pLib )
+{
+    Mio_Gate_t * pGate;
+    Mio_Pin_t * pPin0 = NULL, * pPin = NULL;
+    Mio_LibraryForEachGate( pLib, pGate )
+        Mio_GateForEachPin( pGate, pPin )
+            if ( Mio_CheckPins( pPin0, pPin ) )
+                pPin0 = pPin;
+            else
+                return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_WritePin( FILE * pFile, Mio_Pin_t * pPin, int NameLen, int fAllPins )
+{
+    char * pPhaseNames[10] = { "UNKNOWN", "INV", "NONINV" };
+    if ( fAllPins )
+        fprintf( pFile, "PIN *  " );
+    else
+        fprintf( pFile, "\n    PIN %*s  ", NameLen, pPin->pName );
+    fprintf( pFile, "%7s ",   pPhaseNames[pPin->Phase] );
+    fprintf( pFile, "%3d ",   (int)pPin->dLoadInput );
+    fprintf( pFile, "%3d ",   (int)pPin->dLoadMax );
+    fprintf( pFile, "%6.2f ", pPin->dDelayBlockRise );
+    fprintf( pFile, "%6.2f ", pPin->dDelayFanoutRise );
+    fprintf( pFile, "%6.2f ", pPin->dDelayBlockFall );
+    fprintf( pFile, "%6.2f",  pPin->dDelayFanoutFall );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_WriteGate( FILE * pFile, Mio_Gate_t * pGate, int GateLen, int NameLen, int FormLen, int fPrintSops, int fAllPins )
+{
+    char Buffer[5000];
+    Mio_Pin_t * pPin;
+    assert( NameLen+FormLen+2 < 5000 );
+    sprintf( Buffer, "%s=%s;",    pGate->pOutName, pGate->pForm );
+    fprintf( pFile, "GATE %-*s ", GateLen, pGate->pName );
+    fprintf( pFile, "%8.2f  ",    pGate->dArea );
+    fprintf( pFile, "%-*s ",      Abc_MinInt(NameLen+FormLen+2, 30), Buffer );
+    // print the pins
+    if ( fPrintSops )
+        fprintf( pFile, "%s",       pGate->pSop? pGate->pSop : "unspecified\n" );
+    if ( fAllPins && pGate->pPins ) // equal pins
+        Mio_WritePin( pFile, pGate->pPins, NameLen, 1 );
+    else // different pins
+        Mio_GateForEachPin( pGate, pPin )
+            Mio_WritePin( pFile, pPin, NameLen, 0 );
+    fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_WriteLibrary( FILE * pFile, Mio_Library_t * pLib, int fPrintSops )
+{
+    Mio_Gate_t * pGate;
+    Mio_Pin_t * pPin;
+    int i, GateLen = 0, NameLen = 0, FormLen = 0;
+    int fAllPins = Mio_CheckGates( pLib );
+    Mio_LibraryForEachGate( pLib, pGate )
+    {
+        GateLen = Abc_MaxInt( GateLen, strlen(pGate->pName) );
+        NameLen = Abc_MaxInt( NameLen, strlen(pGate->pOutName) );
+        FormLen = Abc_MaxInt( FormLen, strlen(pGate->pForm) );
+        Mio_GateForEachPin( pGate, pPin )
+            NameLen = Abc_MaxInt( NameLen, strlen(pPin->pName) );
+    }
+    fprintf( pFile, "# The genlib library \"%s\" written by ABC on %s\n\n", pLib->pName, Extra_TimeStamp() );
+    for ( i = 0; i < pLib->nGates; i++ )
+        Mio_WriteGate( pFile, pLib->ppGates0[i], GateLen, NameLen, FormLen, fPrintSops, fAllPins );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the max delay of two gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_DelayCompare( Mio_Gate_t ** ppG1, Mio_Gate_t ** ppG2 )
+{
+    if ( (*ppG1)->dDelayMax < (*ppG2)->dDelayMax )
+        return -1;
+    if ( (*ppG1)->dDelayMax > (*ppG2)->dDelayMax )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the set of root gates.]
+
+  Description [Only collects the gates with unique functionality, 
+  which have fewer inputs and shorter delay than the given limits.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mio_Gate_t ** Mio_CollectRoots( Mio_Library_t * pLib, int nInputs, float tDelay, int fSkipInv, int * pnGates, int fVerbose )
+{
+    Mio_Gate_t * pGate;
+    Mio_Gate_t ** ppGates;
+    int i, nGates, iGate;
+    nGates = Mio_LibraryReadGateNum( pLib );
+    ppGates = ABC_ALLOC( Mio_Gate_t *, nGates );
+    iGate = 0;
+    // for each functionality, select gate with the smallest area
+    // if equal areas, select gate with lexicographically smaller name
+    Mio_LibraryForEachGate( pLib, pGate )
+    {
+        if ( pGate->nInputs > nInputs )
+            continue;
+        if ( tDelay > 0.0 && pGate->dDelayMax > (double)tDelay )
+            continue;
+        if ( pGate->uTruth == 0 || pGate->uTruth == ~(word)0 )
+            continue;
+        if ( pGate->uTruth == ABC_CONST(0xAAAAAAAAAAAAAAAA) )
+            continue;
+        if ( pGate->uTruth == ~ABC_CONST(0xAAAAAAAAAAAAAAAA) && fSkipInv )
+            continue;
+        if ( pGate->pTwin ) // skip multi-output gates for now
+            continue;
+        // check if the gate with this functionality already exists
+        for ( i = 0; i < iGate; i++ )
+            if ( ppGates[i]->uTruth == pGate->uTruth )
+            {
+                if ( ppGates[i]->dArea > pGate->dArea || 
+                    (ppGates[i]->dArea == pGate->dArea && strcmp(ppGates[i]->pName, pGate->pName) > 0) )
+                    ppGates[i] = pGate;
+                break;
+            }
+        if ( i < iGate )
+            continue;
+        assert( iGate < nGates );
+        ppGates[ iGate++ ] = pGate;
+        if ( fVerbose )
+            printf( "Selected gate %3d:   %-20s  A = %7.2f  D = %7.2f  %3s = %-s\n", 
+                iGate+1, pGate->pName, pGate->dArea, pGate->dDelayMax, pGate->pOutName, pGate->pForm );
+    }
+    // sort by delay
+    if ( iGate > 0 ) 
+    {
+        qsort( (void *)ppGates, iGate, sizeof(Mio_Gate_t *), 
+                (int (*)(const void *, const void *)) Mio_DelayCompare );
+        assert( Mio_DelayCompare( ppGates, ppGates + iGate - 1 ) <= 0 );
+    }
+    if ( pnGates )
+        *pnGates = iGate;
+    return ppGates;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the max delay of two gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_DelayCompareNew( Mio_Cell_t * pG1, Mio_Cell_t * pG2 )
+{
+    if ( (pG1)->nFanins < (pG2)->nFanins )
+        return -1;
+    if ( (pG1)->nFanins > (pG2)->nFanins )
+        return 1;
+    if ( (pG1)->Area < (pG2)->Area )
+        return -1;
+    if ( (pG1)->Area > (pG2)->Area )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the set of root gates.]
+
+  Description [Only collects the gates with unique functionality, 
+  which have fewer inputs and shorter delay than the given limits.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_CollectCopy( Mio_Cell_t * pCell, Mio_Gate_t * pGate )
+{
+    Mio_Pin_t * pPin;
+    int k;
+    pCell->pName   = pGate->pName;
+    pCell->uTruth  = pGate->uTruth;
+    pCell->Area    = (float)pGate->dArea;
+    pCell->nFanins = pGate->nInputs;
+    for ( k = 0, pPin = pGate->pPins; pPin; pPin = pPin->pNext, k++ )
+        pCell->Delays[k] = (float)(0.5 * pPin->dDelayBlockRise + 0.5 * pPin->dDelayBlockFall);
+}
+
+Mio_Cell_t * Mio_CollectRootsNew( Mio_Library_t * pLib, int nInputs, int * pnGates, int fVerbose )
+{
+    Mio_Gate_t * pGate;
+    Mio_Cell_t * ppCells;
+    int i, nGates, iCell = 4;
+    nGates = Mio_LibraryReadGateNum( pLib );
+    ppCells = ABC_CALLOC( Mio_Cell_t, nGates + 4 );
+    // for each functionality, select gate with the smallest area
+    // if equal areas, select gate with lexicographically smaller name
+    Mio_LibraryForEachGate( pLib, pGate )
+    {
+        if ( pGate->nInputs > nInputs || pGate->pTwin ) // skip large and multi-output
+            continue;
+        // check if the gate with this functionality already exists
+        for ( i = 0; i < iCell; i++ )
+            if ( ppCells[i].pName && ppCells[i].uTruth == pGate->uTruth )
+            {
+                if ( ppCells[i].Area > pGate->dArea || 
+                    (ppCells[i].Area == pGate->dArea && strcmp(ppCells[i].pName, pGate->pName) > 0) )
+                {
+                    Mio_CollectCopy( ppCells + i, pGate );
+                }
+                break;
+            }
+        if ( i < iCell )
+            continue;
+        if ( pGate->uTruth == 0 || pGate->uTruth == ~(word)0 )
+        {
+            int Idx = (int)(pGate->uTruth == ~(word)0);
+            assert( pGate->nInputs == 0 );
+            Mio_CollectCopy( ppCells + Idx, pGate );
+            continue;
+        }
+        if ( pGate->uTruth == ABC_CONST(0xAAAAAAAAAAAAAAAA) || pGate->uTruth == ~ABC_CONST(0xAAAAAAAAAAAAAAAA) )
+        {
+            int Idx = 2 + (int)(pGate->uTruth == ~ABC_CONST(0xAAAAAAAAAAAAAAAA));
+            assert( pGate->nInputs == 1 );
+            Mio_CollectCopy( ppCells + Idx, pGate );
+            continue;
+        }
+        Mio_CollectCopy( ppCells + iCell++, pGate );
+    }
+    // sort by delay
+    if ( iCell > 1 ) 
+    {
+        qsort( (void *)(ppCells + 4), iCell - 4, sizeof(Mio_Cell_t), 
+                (int (*)(const void *, const void *)) Mio_DelayCompareNew );
+        assert( Mio_DelayCompareNew( ppCells + 4, ppCells + iCell - 1 ) <= 0 );
+    }
+    // assign IDs
+    for ( i = 0; i < iCell; i++ )
+        ppCells[i].Id = ppCells[i].pName ? i : -1;
+
+    // report
+    if ( fVerbose )
+    {
+        // count gates
+        int * pCounts = ABC_CALLOC( int, nGates + 4 );
+        Mio_LibraryForEachGate( pLib, pGate )
+        {
+            if ( pGate->nInputs > nInputs || pGate->pTwin ) // skip large and multi-output
+                continue;
+            for ( i = 0; i < iCell; i++ )
+                if ( ppCells[i].pName && ppCells[i].uTruth == pGate->uTruth )
+                {
+                    pCounts[i]++;
+                    break;
+                }
+            assert( i < iCell );
+        }
+        for ( i = 0; i < iCell; i++ )
+        {
+            Mio_Cell_t * pCell = ppCells + i;
+            printf( "%4d : ", i );
+            if ( pCell->pName == NULL )
+                printf( "None\n" );
+            else
+                printf( "%-20s   In = %d   N = %3d   A = %7.2f   D = %7.2f\n", 
+                    pCell->pName, pCell->nFanins, pCounts[i], pCell->Area, pCell->Delays[0] );
+        }
+        ABC_FREE( pCounts );
+    }
+    if ( pnGates )
+        *pnGates = iCell;
+    return ppCells;
+}
+Mio_Cell_t * Mio_CollectRootsNewDefault( int nInputs, int * pnGates, int fVerbose )
+{
+    return Mio_CollectRootsNew( (Mio_Library_t *)Abc_FrameReadLibGen(), nInputs, pnGates, fVerbose );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table of the gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word Mio_DeriveTruthTable6( Mio_Gate_t * pGate )
+{
+    static unsigned uTruths6[6][2] = {
+        { 0xAAAAAAAA, 0xAAAAAAAA },
+        { 0xCCCCCCCC, 0xCCCCCCCC },
+        { 0xF0F0F0F0, 0xF0F0F0F0 },
+        { 0xFF00FF00, 0xFF00FF00 },
+        { 0xFFFF0000, 0xFFFF0000 },
+        { 0x00000000, 0xFFFFFFFF }
+    };
+    unsigned uTruthRes[2];
+    assert( pGate->nInputs <= 6 );
+    Mio_DeriveTruthTable( pGate, uTruths6, pGate->nInputs, 6, uTruthRes );
+    return *((word *)uTruthRes);
+}
+
+#if 0
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively derives the truth table of the gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_DeriveTruthTable_rec( DdNode * bFunc, unsigned uTruthsIn[][2], unsigned uTruthRes[] )
+{
+    unsigned uTruthsCof0[2];
+    unsigned uTruthsCof1[2];
+
+    // complement the resulting truth table, if the function is complemented
+    if ( Cudd_IsComplement(bFunc) )
+    {
+        Mio_DeriveTruthTable_rec( Cudd_Not(bFunc), uTruthsIn, uTruthRes );
+        uTruthRes[0] = ~uTruthRes[0];
+        uTruthRes[1] = ~uTruthRes[1];
+        return;
+    }
+
+    // if the function is constant 1, return the constant 1 truth table
+	if ( bFunc->index == CUDD_CONST_INDEX )
+    {
+        uTruthRes[0] = MIO_FULL;
+        uTruthRes[1] = MIO_FULL;
+		return;
+    }
+
+    // solve the problem for both cofactors
+    Mio_DeriveTruthTable_rec( cuddE(bFunc), uTruthsIn, uTruthsCof0 );
+    Mio_DeriveTruthTable_rec( cuddT(bFunc), uTruthsIn, uTruthsCof1 );
+
+    // derive the resulting truth table using the input truth tables
+	uTruthRes[0] = (uTruthsCof0[0] & ~uTruthsIn[bFunc->index][0]) |
+		           (uTruthsCof1[0] &  uTruthsIn[bFunc->index][0]);
+	uTruthRes[1] = (uTruthsCof0[1] & ~uTruthsIn[bFunc->index][1]) |
+		           (uTruthsCof1[1] &  uTruthsIn[bFunc->index][1]);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table of the gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_DeriveTruthTable( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nSigns, int nInputs, unsigned uTruthRes[] )
+{
+    Mio_DeriveTruthTable_rec( pGate->bFunc, uTruthsIn, uTruthRes );
+}
+
+#endif
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table of the gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_DeriveTruthTable( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nSigns, int nInputs, unsigned uTruthRes[] )
+{
+    word uRes, uFanins[6];
+    int i;
+    assert( pGate->nInputs == nSigns );
+    for ( i = 0; i < nSigns; i++ )
+        uFanins[i] = (((word)uTruthsIn[i][1]) << 32) | (word)uTruthsIn[i][0];
+    uRes = Exp_Truth6( nSigns, pGate->vExpr, (word *)uFanins );
+    uTruthRes[0] = uRes & 0xFFFFFFFF;
+    uTruthRes[1] = uRes >> 32;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the number of variables in the cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mio_SopGetVarNum( char * pSop )
+{
+    char * pCur;
+    for ( pCur = pSop; *pCur != '\n'; pCur++ )
+        if ( *pCur == 0 )
+            return -1;
+    return pCur - pSop - 2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the truth table of the root of the gate.]
+
+  Description [Given the truth tables of the leaves of the gate,
+  this procedure derives the truth table of the root.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_DeriveTruthTable2( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nTruths, int nInputs, unsigned uTruthRes[] )
+{
+    unsigned uSignCube[2];
+    int i, nFanins;
+    char * pCube;
+
+    // make sure that the number of input truth tables in equal to the number of gate inputs
+    assert( pGate->nInputs == nTruths );
+    assert( nInputs < 7 );
+
+    nFanins = Mio_SopGetVarNum( pGate->pSop );
+    assert( nFanins == nInputs );
+
+    // clean the resulting truth table
+    uTruthRes[0] = 0;
+    uTruthRes[1] = 0;
+    if ( nInputs < 6 )
+    {
+//        Abc_SopForEachCube( pGate->pSop, nFanins, pCube )
+        for ( pCube = pGate->pSop; *pCube; pCube += (nFanins) + 3 )
+        {
+            // add the clause
+            uSignCube[0] = MIO_FULL;
+            for ( i = 0; i < nFanins; i++ )
+            {
+                if ( pCube[i] == '0' )
+                    uSignCube[0] &= ~uTruthsIn[i][0];
+                else if ( pCube[i] == '1' )
+                    uSignCube[0] &=  uTruthsIn[i][0];
+            }
+        }
+        if ( nInputs < 5 )
+            uTruthRes[0] &= MIO_MASK(1<<nInputs);
+    }
+    else
+    {
+        // consider the case when two unsigneds should be used
+//        Abc_SopForEachCube( pGate->pSop, nFanins, pCube )
+        for ( pCube = pGate->pSop; *pCube; pCube += (nFanins) + 3 )
+        {
+            uSignCube[0] = MIO_FULL;
+            uSignCube[1] = MIO_FULL;
+            for ( i = 0; i < nFanins; i++ )
+            {
+                if ( pCube[i] == '0' )
+                {
+                    uSignCube[0] &= ~uTruthsIn[i][0];
+                    uSignCube[1] &= ~uTruthsIn[i][1];
+                }
+                else if ( pCube[i] == '1' )
+                {
+                    uSignCube[0] &=  uTruthsIn[i][0];
+                    uSignCube[1] &=  uTruthsIn[i][1];
+                }
+            }
+            uTruthRes[0] |= uSignCube[0];
+            uTruthRes[1] |= uSignCube[1];
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the area and delay of the root of the gate.]
+
+  Description [Array of the resulting delays should be initialized 
+  to the (negative) SUPER_NO_VAR value.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_DeriveGateDelays( Mio_Gate_t * pGate, 
+    float ** ptPinDelays, int nPins, int nInputs, float tDelayZero, 
+    float * ptDelaysRes, float * ptPinDelayMax )
+{
+    Mio_Pin_t * pPin;
+    float Delay, DelayMax;
+    int i, k;
+    assert( pGate->nInputs == nPins );
+    // set all the delays to the unused delay
+    for ( i = 0; i < nInputs; i++ )
+        ptDelaysRes[i] = tDelayZero;
+    // compute the delays for each input and the max delay at the same time
+    DelayMax = 0;
+    for ( i = 0; i < nInputs; i++ )
+    {
+        for ( k = 0, pPin = pGate->pPins; pPin; pPin = pPin->pNext, k++ )
+        {
+            if ( ptPinDelays[k][i] < 0 )
+                continue;
+            Delay = ptPinDelays[k][i] + (float)pPin->dDelayBlockMax;
+            if ( ptDelaysRes[i] < Delay )
+                ptDelaysRes[i] = Delay;
+        }
+        if ( k != nPins )
+        {
+            printf ("DEBUG: problem gate is %s\n", Mio_GateReadName( pGate ));
+        }
+        assert( k == nPins );
+        if ( DelayMax < ptDelaysRes[i] )
+            DelayMax = ptDelaysRes[i];
+    }
+    *ptPinDelayMax = DelayMax;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a pseudo-gate.]
+
+  Description [The pseudo-gate is a N-input gate with all info set to 0.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mio_Gate_t * Mio_GateCreatePseudo( int nInputs )
+{
+    Mio_Gate_t * pGate;
+    Mio_Pin_t * pPin;
+    int i;
+    // allocate the gate structure
+    pGate = ABC_ALLOC( Mio_Gate_t, 1 );
+    memset( pGate, 0, sizeof(Mio_Gate_t) );
+    pGate->nInputs = nInputs;
+    // create pins
+    for ( i = 0; i < nInputs; i++ )
+    {
+        pPin = ABC_ALLOC( Mio_Pin_t, 1 );
+        memset( pPin, 0, sizeof(Mio_Pin_t) );
+        pPin->pNext = pGate->pPins;
+        pGate->pPins = pPin;
+    }
+    return pGate;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds constant value to all delay values.]
+
+  Description [The pseudo-gate is a N-input gate with all info set to 0.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_LibraryShiftDelay( Mio_Library_t * pLib, double Shift )
+{
+    Mio_Gate_t * pGate;
+    Mio_Pin_t * pPin;
+    Mio_LibraryForEachGate( pLib, pGate )
+    {
+        pGate->dDelayMax += Shift;
+        Mio_GateForEachPin( pGate, pPin )
+        {
+            pPin->dDelayBlockRise += Shift;
+            pPin->dDelayBlockFall += Shift;
+            pPin->dDelayBlockMax  += Shift;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Multiply areas/delays by values proportional to fanin count.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_LibraryMultiArea( Mio_Library_t * pLib, double Multi )
+{
+    Mio_Gate_t * pGate;
+    Mio_LibraryForEachGate( pLib, pGate )
+    {
+        if ( pGate->nInputs < 2 )
+            continue;
+//        printf( "Before %8.3f  ", pGate->dArea );
+        pGate->dArea *= pow( pGate->nInputs, Multi );
+//        printf( "After %8.3f  Inputs = %d. Factor = %8.3f\n", pGate->dArea, pGate->nInputs, pow( pGate->nInputs, Multi ) );
+    }
+}
+void Mio_LibraryMultiDelay( Mio_Library_t * pLib, double Multi )
+{
+    Mio_Gate_t * pGate;
+    Mio_Pin_t * pPin;
+    Mio_LibraryForEachGate( pLib, pGate )
+    {
+        if ( pGate->nInputs < 2 )
+            continue;
+//        printf( "Before %8.3f  ", pGate->dDelayMax );
+        pGate->dDelayMax *= pow( pGate->nInputs, Multi );
+//        printf( "After %8.3f  Inputs = %d. Factor = %8.3f\n", pGate->dDelayMax, pGate->nInputs, pow( pGate->nInputs, Multi ) );
+        Mio_GateForEachPin( pGate, pPin )
+        {
+            pPin->dDelayBlockRise *= pow( pGate->nInputs, Multi );
+            pPin->dDelayBlockFall *= pow( pGate->nInputs, Multi );
+            pPin->dDelayBlockMax  *= pow( pGate->nInputs, Multi );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers delays from the second to the first.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mio_LibraryTransferDelays( Mio_Library_t * pLibD, Mio_Library_t * pLibS )
+{
+    Mio_Gate_t * pGateD, * pGateS;
+    Mio_Pin_t * pPinD, * pPinS;
+    Mio_LibraryForEachGate( pLibS, pGateS )
+    {
+        Mio_LibraryForEachGate( pLibD, pGateD )
+        {
+            if ( pGateD->uTruth != pGateS->uTruth )
+                continue;
+            pPinS = Mio_GateReadPins( pGateS );
+            Mio_GateForEachPin( pGateD, pPinD )
+            {
+                if (pPinS)
+                {
+                    pPinD->dDelayBlockRise = pPinS->dDelayBlockRise;
+                    pPinD->dDelayBlockFall = pPinS->dDelayBlockFall;
+                    pPinD->dDelayBlockMax  = pPinS->dDelayBlockMax;
+                    pPinS = Mio_PinReadNext(pPinS);
+                }
+                else
+                {
+                    pPinD->dDelayBlockRise = 0;
+                    pPinD->dDelayBlockFall = 0;
+                    pPinD->dDelayBlockMax  = 0;
+                }
+            }
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nf_ManPrepareGate( int nVars, word uTruth, int * pComp, int * pPerm, Vec_Wrd_t * vResult )
+{
+    int nPerms = Extra_Factorial( nVars );
+    int nMints = (1 << nVars);
+    word tCur, tTemp1, tTemp2;
+    int i, p, c;
+    Vec_WrdClear( vResult );
+    for ( i = 0; i < 2; i++ )
+    {
+        tCur = i ? ~uTruth : uTruth;
+        tTemp1 = tCur;
+        for ( p = 0; p < nPerms; p++ )
+        {
+            tTemp2 = tCur;
+            for ( c = 0; c < nMints; c++ )
+            {
+                Vec_WrdPush( vResult, tCur );
+                tCur = Abc_Tt6Flip( tCur, pComp[c] );
+            }
+            assert( tTemp2 == tCur );
+            tCur = Abc_Tt6SwapAdjacent( tCur, pPerm[p] );
+        }
+        assert( tTemp1 == tCur );
+    }
+}
+void Nf_ManPreparePrint( int nVars, int * pComp, int * pPerm, char Line[2*720*64][8] )
+{
+    int nPerms = Extra_Factorial( nVars );
+    int nMints = (1 << nVars);
+    char * pChar, * pChar2;
+    int i, p, c, n = 0;
+    for ( i = 0; i < nVars; i++ )
+        Line[0][i] = 'A' + nVars - 1 - i;
+    Line[0][nVars] = '+';
+    Line[0][nVars+1] = 0;
+    for ( i = 0; i < 2; i++ )
+    {
+        Line[n][nVars] = i ? '-' : '+';
+        for ( p = 0; p < nPerms; p++ )
+        {
+            for ( c = 0; c < nMints; c++ )
+            {
+                strcpy( Line[n+1], Line[n] ); n++;
+                pChar = &Line[n][pComp[c]];
+                if ( *pChar >= 'A' && *pChar <= 'Z' )
+                    *pChar += 'a' - 'A';
+                else if ( *pChar >= 'a' && *pChar <= 'z' )
+                    *pChar -= 'a' - 'A';
+            }
+            pChar  = &Line[n][pPerm[p]];
+            pChar2 = pChar + 1;
+            ABC_SWAP( char, *pChar, *pChar2 );
+        }
+    }
+    assert( n == 2*nPerms*nMints );
+    n = 0;
+    for ( i = 0; i < 2; i++ )
+        for ( p = 0; p < nPerms; p++ )
+            for ( c = 0; c < nMints; c++ )
+                printf("%8d : %d %3d %2d : %s\n", n, i, p, c, Line[n]), n++;
+}
+
+void Nf_ManPrepareLibrary( Mio_Library_t * pLib )
+{
+    extern void Dau_DsdPrintFromTruth( word * pTruth, int nVarsInit );
+//    char Lines[2*720*64][8];
+//    Nf_ManPreparePrint( 6, pComp, pPerm, Lines );
+    int * pComp[7];
+    int * pPerm[7];
+    Mio_Gate_t ** ppGates;
+    Vec_Wrd_t * vResult;
+    word * pTruths;
+    int * pSizes;
+    int nGates, i, nClasses = 0, nTotal;
+    abctime clk = Abc_Clock();
+
+    for ( i = 2; i <= 6; i++ )
+        pComp[i] = Extra_GreyCodeSchedule( i );
+    for ( i = 2; i <= 6; i++ )
+        pPerm[i] = Extra_PermSchedule( i );
+
+    // collect truth tables
+    ppGates = Mio_CollectRoots( pLib, 6, (float)1.0e+20, 1, &nGates, 0 );
+    pSizes  = ABC_CALLOC( int, nGates );
+    pTruths = ABC_CALLOC( word, nGates );
+    vResult = Vec_WrdAlloc( 2 * 720 * 64 );
+    for ( i = 0; i < nGates; i++ )
+    {
+        pSizes[i] = Mio_GateReadPinNum( ppGates[i] );
+        assert( pSizes[i] > 1 && pSizes[i] <= 6 );
+        pTruths[i] = Mio_GateReadTruth( ppGates[i] );
+
+        Nf_ManPrepareGate( pSizes[i], pTruths[i], pComp[pSizes[i]], pPerm[pSizes[i]], vResult );
+        Vec_WrdUniqify(vResult);
+        nClasses += Vec_WrdSize(vResult);
+        nTotal = (1 << (pSizes[i]+1)) * Extra_Factorial(pSizes[i]);
+
+        printf( "%6d : ", i );
+        printf( "%16s : ", Mio_GateReadName( ppGates[i] ) );
+        printf( "%48s : ", Mio_GateReadForm( ppGates[i] ) );
+        printf( "Inputs = %2d   ", pSizes[i] );
+        printf( "Total = %6d  ", nTotal );
+        printf( "Classes = %6d ", Vec_WrdSize(vResult) );
+        printf( "Configs = %8.2f ", 1.0*nTotal/Vec_WrdSize(vResult) );
+        printf( "%6.2f %%  ", 100.0*Vec_WrdSize(vResult)/nTotal );
+        Dau_DsdPrintFromTruth( &pTruths[i], pSizes[i] );
+//        printf( "\n" );
+    }
+    Vec_WrdFree( vResult );
+    ABC_FREE( ppGates );
+    ABC_FREE( pSizes );
+    ABC_FREE( pTruths );
+
+    for ( i = 2; i <= 6; i++ )
+        ABC_FREE( pComp[i] );
+    for ( i = 2; i <= 6; i++ )
+        ABC_FREE( pPerm[i] );
+
+    printf( "Classes = %d.  ", nClasses );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+
+void Nf_ManPrepareLibraryTest2()
+{
+    Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
+    if ( pLib != NULL )
+        Nf_ManPrepareLibrary( pLib );
+    else
+        printf( "Standard cell library is not available.\n" );
+
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mio/module.make b/abc-build/src/map/mio/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mio/module.make
@@ -0,0 +1,7 @@
+SRC +=  src/map/mio/mio.c \
+	src/map/mio/mioApi.c \
+	src/map/mio/mioFunc.c \
+	src/map/mio/mioParse.c \
+	src/map/mio/mioRead.c \
+	src/map/mio/mioSop.c \
+	src/map/mio/mioUtils.c
diff --git a/abc-build/src/map/mpm/module.make b/abc-build/src/map/mpm/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mpm/module.make
@@ -0,0 +1,11 @@
+SRC +=  src/map/mpm/mpmAbc.c \
+	src/map/mpm/mpmCore.c \
+	src/map/mpm/mpmDsd.c \
+	src/map/mpm/mpmGates.c \
+	src/map/mpm/mpmLib.c \
+	src/map/mpm/mpmMan.c \
+	src/map/mpm/mpmMap.c \
+	src/map/mpm/mpmMig.c \
+	src/map/mpm/mpmPre.c \
+	src/map/mpm/mpmTruth.c \
+	src/map/mpm/mpmUtil.c 
diff --git a/abc-build/src/map/mpm/mpm.c b/abc-build/src/map/mpm/mpm.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mpm/mpm.c
@@ -0,0 +1,55 @@
+/**CFile****************************************************************
+
+  FileName    [mpm.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Configurable technology mapper.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 1, 2013.]
+
+  Revision    [$Id: mpm.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mpmInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mpm_ManTest()
+{
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mpm/mpm.h b/abc-build/src/map/mpm/mpm.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mpm/mpm.h
@@ -0,0 +1,98 @@
+/**CFile****************************************************************
+
+  FileName    [mpm.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Configurable technology mapper.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 1, 2013.]
+
+  Revision    [$Id: mpm.h,v 1.00 2013/06/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__map__mpm__h
+#define ABC__map__mpm__h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+ 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+#define MPM_VAR_MAX  12  
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Mpm_LibLut_t_ Mpm_LibLut_t;
+struct Mpm_LibLut_t_
+{
+    char *           pName;                                     // the name of the LUT library
+    int              LutMax;                                    // the maximum LUT size 
+    int              fVarPinDelays;                             // set to 1 if variable pin delays are specified
+    int              pLutAreas[MPM_VAR_MAX+1];                  // the areas of LUTs
+    int              pLutDelays[MPM_VAR_MAX+1][MPM_VAR_MAX+1];  // the delays of LUTs
+};
+
+typedef struct Mpm_Par_t_ Mpm_Par_t;
+struct Mpm_Par_t_
+{
+    Mpm_LibLut_t *   pLib;
+    void *           pScl;
+    int              nNumCuts;
+    int              DelayTarget;
+    int              fUseGates;
+    int              fUseTruth;
+    int              fUseDsd;
+    int              fCutMin;
+    int              fOneRound;
+    int              fDeriveLuts;
+    int              fMap4Cnf;
+    int              fMap4Aig;
+    int              fMap4Gates;
+    int              fVerbose;
+    int              fVeryVerbose;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== mpmCore.c ===========================================================*/
+extern void           Mpm_ManSetParsDefault( Mpm_Par_t * p );
+/*=== mpmLib.c ===========================================================*/
+extern Mpm_LibLut_t * Mpm_LibLutSetSimple( int nLutSize );
+extern void           Mpm_LibLutFree( Mpm_LibLut_t * pLib );
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/map/mpm/mpmAbc.c b/abc-build/src/map/mpm/mpmAbc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mpm/mpmAbc.c
@@ -0,0 +1,350 @@
+/**CFile****************************************************************
+
+  FileName    [mpmAbc.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Configurable technology mapper.]
+
+  Synopsis    [Interface with ABC data structures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 1, 2013.]
+
+  Revision    [$Id: mpmAbc.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig/gia/gia.h"
+#include "mpmInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mig_ManCreateChoices( Mig_Man_t * pMig, Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Mig_ManObjNum(pMig) == Gia_ManObjNum(p) );
+    assert( Vec_IntSize(&pMig->vSibls) == 0 );
+    Vec_IntFill( &pMig->vSibls, Gia_ManObjNum(p), 0 );
+    Gia_ManMarkFanoutDrivers( p );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        Gia_ObjSetPhase( p, pObj );
+        assert( Abc_Lit2Var(pObj->Value) == i );
+        Mig_ObjSetPhase( Mig_ManObj(pMig, i), pObj->fPhase );
+        if ( Gia_ObjSibl(p, i) && pObj->fMark0 )
+        {
+            Gia_Obj_t * pSibl, * pPrev;
+            for ( pPrev = pObj, pSibl = Gia_ObjSiblObj(p, i); pSibl; pPrev = pSibl, pSibl = Gia_ObjSiblObj(p, Gia_ObjId(p, pSibl)) )
+                Mig_ObjSetSiblId( Mig_ManObj(pMig, Abc_Lit2Var(pPrev->Value)), Abc_Lit2Var(pSibl->Value) );
+            pMig->nChoices++;
+        }
+    }
+    Gia_ManCleanMark0( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Mig_ObjFanin0Copy( Gia_Obj_t * pObj ) { return Abc_LitNotCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) );     }
+static inline int Mig_ObjFanin1Copy( Gia_Obj_t * pObj ) { return Abc_LitNotCond( Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC1(pObj) );     }
+Mig_Man_t * Mig_ManCreate( void * pGia )
+{
+    Gia_Man_t * p = (Gia_Man_t *)pGia;
+    Mig_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    pNew = Mig_ManStart();
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsMuxId(p, i) )
+            pObj->Value = Mig_ManAppendMux( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin2Copy(p, pObj) );
+        else if ( Gia_ObjIsXor(pObj) )
+            pObj->Value = Mig_ManAppendXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Mig_ManAppendAnd( pNew, Mig_ObjFanin0Copy(pObj), Mig_ObjFanin1Copy(pObj) );
+        else if ( Gia_ObjIsCi(pObj) )
+            pObj->Value = Mig_ManAppendCi( pNew );
+        else if ( Gia_ObjIsCo(pObj) )
+            pObj->Value = Mig_ManAppendCo( pNew, Mig_ObjFanin0Copy(pObj) );
+        else assert( 0 );
+    }
+    Mig_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    if ( Gia_ManHasChoices(p) )
+        Mig_ManCreateChoices( pNew, p );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively derives the local AIG for the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Mpm_CutDataInt( Mpm_Cut_t * pCut )                    { return pCut->hNext;  }
+static inline void     Mpm_CutSetDataInt( Mpm_Cut_t * pCut, int Data )       { pCut->hNext = Data;  }
+int Mpm_ManNodeIfToGia_rec( Gia_Man_t * pNew, Mpm_Man_t * pMan, Mig_Obj_t * pObj, Vec_Ptr_t * vVisited, int fHash )
+{
+    Mig_Obj_t * pTemp;
+    Mpm_Cut_t * pCut;
+    int iFunc, iFunc0, iFunc1, iFunc2 = 0;
+    assert( fHash == 0 );
+    // get the best cut
+    pCut = Mpm_ObjCutBestP( pMan, pObj );
+    // if the cut is visited, return the result
+    if ( Mpm_CutDataInt(pCut) )
+        return Mpm_CutDataInt(pCut);
+    // mark the node as visited
+    Vec_PtrPush( vVisited, pCut );
+    // insert the worst case
+    Mpm_CutSetDataInt( pCut, ~0 );
+    // skip in case of primary input
+    if ( Mig_ObjIsCi(pObj) )
+        return Mpm_CutDataInt(pCut);
+    // compute the functions of the children
+    for ( pTemp = pObj; pTemp; pTemp = Mig_ObjSibl(pTemp) )
+    {
+        iFunc0 = Mpm_ManNodeIfToGia_rec( pNew, pMan, Mig_ObjFanin0(pTemp), vVisited, fHash );
+        if ( iFunc0 == ~0 )
+            continue;
+        iFunc1 = Mpm_ManNodeIfToGia_rec( pNew, pMan, Mig_ObjFanin1(pTemp), vVisited, fHash );
+        if ( iFunc1 == ~0 )
+            continue;
+        if ( Mig_ObjIsNode3(pTemp) )
+        {
+            iFunc2 = Mpm_ManNodeIfToGia_rec( pNew, pMan, Mig_ObjFanin2(pTemp), vVisited, fHash );
+            if ( iFunc2 == ~0 )
+                continue;
+            iFunc2 = Abc_LitNotCond(iFunc2, Mig_ObjFaninC2(pTemp));
+        }
+        iFunc0 = Abc_LitNotCond(iFunc0, Mig_ObjFaninC0(pTemp));
+        iFunc1 = Abc_LitNotCond(iFunc1, Mig_ObjFaninC1(pTemp));
+        // both branches are solved
+        if ( fHash )
+        {
+            if ( Mig_ObjIsMux(pTemp) )
+                iFunc = Gia_ManHashMux( pNew, iFunc2, iFunc1, iFunc0 );
+            else if ( Mig_ObjIsXor(pTemp) )
+                iFunc = Gia_ManHashXor( pNew, iFunc0, iFunc1 );
+            else 
+                iFunc = Gia_ManHashAnd( pNew, iFunc0, iFunc1 ); 
+        }
+        else
+        {
+            if ( Mig_ObjIsMux(pTemp) )
+                iFunc = Gia_ManAppendMux( pNew, iFunc2, iFunc1, iFunc0 );
+            else if ( Mig_ObjIsXor(pTemp) )
+                iFunc = Gia_ManAppendXor( pNew, iFunc0, iFunc1 );
+            else 
+                iFunc = Gia_ManAppendAnd( pNew, iFunc0, iFunc1 ); 
+        }
+        if ( Mig_ObjPhase(pTemp) != Mig_ObjPhase(pObj) )
+            iFunc = Abc_LitNot(iFunc);
+        Mpm_CutSetDataInt( pCut, iFunc );
+        break;
+    }
+    return Mpm_CutDataInt(pCut);
+}
+int Mpm_ManNodeIfToGia( Gia_Man_t * pNew, Mpm_Man_t * pMan, Mig_Obj_t * pObj, Vec_Int_t * vLeaves, int fHash )
+{
+    Mpm_Cut_t * pCut;
+    Mig_Obj_t * pFanin;
+    int i, iRes;
+    // get the best cut
+    pCut = Mpm_ObjCutBestP( pMan, pObj );
+    assert( pCut->nLeaves > 1 );
+    // set the leaf variables
+    Mpm_CutForEachLeaf( pMan->pMig, pCut, pFanin, i )
+        Mpm_CutSetDataInt( Mpm_ObjCutBestP(pMan, pFanin), Vec_IntEntry(vLeaves, i) );
+    // recursively compute the function while collecting visited cuts
+    Vec_PtrClear( pMan->vTemp );
+    iRes = Mpm_ManNodeIfToGia_rec( pNew, pMan, pObj, pMan->vTemp, fHash ); 
+    if ( iRes == ~0 )
+    {
+        Abc_Print( -1, "Mpm_ManNodeIfToGia(): Computing local AIG has failed.\n" );
+        return ~0;
+    }
+    // clean the cuts
+    Mpm_CutForEachLeaf( pMan->pMig, pCut, pFanin, i )
+        Mpm_CutSetDataInt( Mpm_ObjCutBestP(pMan, pFanin), 0 );
+    Vec_PtrForEachEntry( Mpm_Cut_t *, pMan->vTemp, pCut, i )
+        Mpm_CutSetDataInt( pCut, 0 );
+    return iRes;
+}
+void * Mpm_ManFromIfLogic( Mpm_Man_t * pMan )
+{
+    Gia_Man_t * pNew;
+    Mpm_Cut_t * pCutBest;
+    Mig_Obj_t * pObj, * pFanin;
+    Vec_Int_t * vMapping, * vMapping2, * vPacking = NULL;
+    Vec_Int_t * vLeaves, * vLeaves2, * vCover;
+    word uTruth, * pTruth = &uTruth;
+    int i, k, Entry, iLitNew;
+//    assert( !pMan->pPars->fDeriveLuts || pMan->pPars->fTruth );
+    // start mapping and packing
+    vMapping  = Vec_IntStart( Mig_ManObjNum(pMan->pMig) );
+    vMapping2 = Vec_IntStart( 1 );
+    if ( 0 ) // pMan->pPars->fDeriveLuts && pMan->pPars->pLutStruct )
+    {
+        vPacking = Vec_IntAlloc( 1000 );
+        Vec_IntPush( vPacking, 0 );
+    }
+    // create new manager
+    pNew = Gia_ManStart( Mig_ManObjNum(pMan->pMig) );
+    // iterate through nodes used in the mapping
+    vCover   = Vec_IntAlloc( 1 << 16 );
+    vLeaves  = Vec_IntAlloc( 16 );
+    vLeaves2 = Vec_IntAlloc( 16 );
+    Mig_ManCleanCopy( pMan->pMig );
+    Mig_ManForEachObj( pMan->pMig, pObj )
+    {
+        if ( !Mpm_ObjMapRef(pMan, pObj) && !Mig_ObjIsTerm(pObj) )
+            continue;
+        if ( Mig_ObjIsNode(pObj) )
+        {
+            // collect leaves of the best cut
+            Vec_IntClear( vLeaves );
+            pCutBest = Mpm_ObjCutBestP( pMan, pObj );
+            Mpm_CutForEachLeaf( pMan->pMig, pCutBest, pFanin, k )
+                Vec_IntPush( vLeaves, Mig_ObjCopy(pFanin) );
+            if ( pMan->pPars->fDeriveLuts && (pMan->pPars->fUseTruth || pMan->pPars->fUseDsd) )
+            {
+                extern int Gia_ManFromIfLogicNode( void * p, Gia_Man_t * pNew, int iObj, Vec_Int_t * vLeaves, Vec_Int_t * vLeavesTemp, 
+                    word * pRes, char * pStr, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vPacking, int fCheck75, int fCheck44e );
+                if ( pMan->pPars->fUseTruth )
+                    pTruth = Mpm_CutTruth(pMan, Abc_Lit2Var(pCutBest->iFunc));
+                else
+                    uTruth = Mpm_CutTruthFromDsd( pMan, pCutBest, Abc_Lit2Var(pCutBest->iFunc) );
+//                Kit_DsdPrintFromTruth( pTruth, Vec_IntSize(vLeaves) );  printf( "\n" );
+                // perform decomposition of the cut
+                iLitNew = Gia_ManFromIfLogicNode( NULL, pNew, Mig_ObjId(pObj), vLeaves, vLeaves2, pTruth, NULL, vCover, vMapping, vMapping2, vPacking, 0, 0 );
+                iLitNew = Abc_LitNotCond( iLitNew, pCutBest->fCompl ^ Abc_LitIsCompl(pCutBest->iFunc) );
+            }
+            else
+            {
+                // perform one of the two types of mapping: with and without structures
+                iLitNew = Mpm_ManNodeIfToGia( pNew, pMan, pObj, vLeaves, 0 );
+                // write mapping
+                Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLitNew), Vec_IntSize(vMapping2) );
+                Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) );
+                Vec_IntForEachEntry( vLeaves, Entry, k )
+                    assert( Abc_Lit2Var(Entry) < Abc_Lit2Var(iLitNew) );
+                Vec_IntForEachEntry( vLeaves, Entry, k )
+                    Vec_IntPush( vMapping2, Abc_Lit2Var(Entry)  );
+                Vec_IntPush( vMapping2, Abc_Lit2Var(iLitNew) );
+            }
+        }
+        else if ( Mig_ObjIsCi(pObj) )
+            iLitNew = Gia_ManAppendCi(pNew);
+        else if ( Mig_ObjIsCo(pObj) )
+            iLitNew = Gia_ManAppendCo( pNew, Abc_LitNotCond(Mig_ObjCopy(Mig_ObjFanin0(pObj)), Mig_ObjFaninC0(pObj)) );
+        else if ( Mig_ObjIsConst0(pObj) )
+        {
+            iLitNew = 0;
+            // create const LUT
+            Vec_IntWriteEntry( vMapping, 0, Vec_IntSize(vMapping2) );
+            Vec_IntPush( vMapping2, 0 );
+            Vec_IntPush( vMapping2, 0 );
+        }
+        else assert( 0 );
+        Mig_ObjSetCopy( pObj, iLitNew );
+    }
+    Vec_IntFree( vCover );
+    Vec_IntFree( vLeaves );
+    Vec_IntFree( vLeaves2 );
+//    printf( "Mapping array size:  IfMan = %d. Gia = %d. Increase = %.2f\n", 
+//        Mig_ManObjNum(pMan), Gia_ManObjNum(pNew), 1.0 * Gia_ManObjNum(pNew) / Mig_ManObjNum(pMan) );
+    // finish mapping 
+    if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) )
+        Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) );
+    else
+        Vec_IntFillExtra( vMapping, Gia_ManObjNum(pNew), 0 );
+    assert( Vec_IntSize(vMapping) == Gia_ManObjNum(pNew) );
+    Vec_IntForEachEntry( vMapping, Entry, i )
+        if ( Entry > 0 )
+            Vec_IntAddToEntry( vMapping, i, Gia_ManObjNum(pNew) );
+    Vec_IntAppend( vMapping, vMapping2 );
+    Vec_IntFree( vMapping2 );
+    // attach mapping and packing
+    assert( pNew->vMapping == NULL );
+    assert( pNew->vPacking == NULL );
+    pNew->vMapping = vMapping;
+    pNew->vPacking = vPacking;
+    // verify that COs have mapping
+    {
+        Gia_Obj_t * pObj;
+        Gia_ManForEachCo( pNew, pObj, i )
+           assert( !Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) || Gia_ObjIsLut(pNew, Gia_ObjFaninId0p(pNew, pObj)) );
+    }
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+void Mig_ManTest2( Gia_Man_t * pGia )
+{
+    extern int Gia_ManSuppSizeTest( Gia_Man_t * p );
+    Mig_Man_t * p;
+    Gia_ManSuppSizeTest( pGia );
+    p = Mig_ManCreate( pGia );
+    Mig_ManSuppSizeTest( p );
+    Mig_ManStop( p );
+}
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mpm/mpmCore.c b/abc-build/src/map/mpm/mpmCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mpm/mpmCore.c
@@ -0,0 +1,115 @@
+/**CFile****************************************************************
+
+  FileName    [mpmCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Configurable technology mapper.]
+
+  Synopsis    [Core procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 1, 2013.]
+
+  Revision    [$Id: mpmCore.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig/gia/gia.h"
+#include "mpmInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mpm_ManSetParsDefault( Mpm_Par_t * p )
+{
+    memset( p, 0, sizeof(Mpm_Par_t) );
+    p->pLib           =   NULL;  // LUT library
+    p->nNumCuts       =      8;  // cut number
+    p->fUseTruth      =      0;  // uses truth tables
+    p->fUseDsd        =      0;  // uses DSDs
+    p->fCutMin        =      0;  // enables cut minimization
+    p->fOneRound      =      0;  // enabled one round
+    p->DelayTarget    =     -1;  // delay target
+    p->fDeriveLuts    =      0;  // use truth tables to derive AIG structure
+    p->fMap4Cnf       =      0;  // mapping for CNF
+    p->fMap4Aig       =      0;  // mapping for AIG
+    p->fMap4Gates     =      0;  // mapping for gates
+    p->fVerbose       =      0;  // verbose output
+    p->fVeryVerbose   =      0;  // verbose output
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Mpm_ManPerformLutMapping( Mig_Man_t * pMig, Mpm_Par_t * pPars )
+{
+    Gia_Man_t * pNew;
+    Mpm_Man_t * p;
+    p = Mpm_ManStart( pMig, pPars );
+    if ( p->pPars->fVerbose ) 
+        Mpm_ManPrintStatsInit( p );
+    Mpm_ManPrepare( p );
+    Mpm_ManPerform( p );
+    if ( p->pPars->fVerbose ) 
+        Mpm_ManPrintStats( p );
+    pNew = (Gia_Man_t *)Mpm_ManFromIfLogic( p );
+    Mpm_ManStop( p );
+    return pNew;
+}
+Gia_Man_t * Mpm_ManLutMapping( Gia_Man_t * pGia, Mpm_Par_t * pPars )
+{
+    Mig_Man_t * p;
+    Gia_Man_t * pNew;
+    assert( pPars->pLib->LutMax <= MPM_VAR_MAX );
+    assert( pPars->nNumCuts <= MPM_CUT_MAX );
+    if ( pPars->fUseGates )
+    {
+        pGia = Gia_ManDupMuxes( pGia, 2 );
+        p = Mig_ManCreate( pGia );
+        Gia_ManStop( pGia );
+    }
+    else
+        p = Mig_ManCreate( pGia );
+    pNew = Mpm_ManPerformLutMapping( p, pPars );
+    Mig_ManStop( p );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mpm/mpmDsd.c b/abc-build/src/map/mpm/mpmDsd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mpm/mpmDsd.c
@@ -0,0 +1,1055 @@
+/**CFile****************************************************************
+
+  FileName    [mpmDsd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Configurable technology mapper.]
+
+  Synopsis    [DSD manipulation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 1, 2013.]
+
+  Revision    [$Id: mpmDsd.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mpmInt.h"
+#include "misc/extra/extra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Mpm_Dsd_t s_DsdClass6[595] = { 
+    { 0,  0,  1, ABC_CONST(0x0000000000000000), "0" },   //    0
+    { 1,  0,  2, ABC_CONST(0xAAAAAAAAAAAAAAAA), "a" },   //    1
+    { 2,  1,  3, ABC_CONST(0x8888888888888888), "(ab)" },   //    2
+    { 2,  3,  4, ABC_CONST(0x6666666666666666), "[ab]" },   //    3
+    { 3,  2,  4, ABC_CONST(0x8080808080808080), "(abc)" },   //    4
+    { 3,  2,  4, ABC_CONST(0x7070707070707070), "(!(ab)c)" },   //    5
+    { 3,  4,  6, ABC_CONST(0x7878787878787878), "[(ab)c]" },   //    6
+    { 3,  4,  5, ABC_CONST(0x6060606060606060), "([ab]c)" },   //    7
+    { 3,  6,  8, ABC_CONST(0x9696969696969696), "[abc]" },   //    8
+    { 3,  3,  4, ABC_CONST(0xCACACACACACACACA), "<abc>" },   //    9
+    { 4,  3,  5, ABC_CONST(0x8000800080008000), "(abcd)" },   //   10
+    { 4,  3,  5, ABC_CONST(0x7F007F007F007F00), "(!(abc)d)" },   //   11
+    { 4,  5,  8, ABC_CONST(0x7F807F807F807F80), "[(abc)d]" },   //   12
+    { 4,  3,  5, ABC_CONST(0x7000700070007000), "(!(ab)cd)" },   //   13
+    { 4,  3,  5, ABC_CONST(0x8F008F008F008F00), "(!(!(ab)c)d)" },   //   14
+    { 4,  5,  8, ABC_CONST(0x8F708F708F708F70), "[(!(ab)c)d]" },   //   15
+    { 4,  5,  7, ABC_CONST(0x7800780078007800), "([(ab)c]d)" },   //   16
+    { 4,  7, 12, ABC_CONST(0x8778877887788778), "[(ab)cd]" },   //   17
+    { 4,  5,  6, ABC_CONST(0x6000600060006000), "([ab]cd)" },   //   18
+    { 4,  5,  6, ABC_CONST(0x9F009F009F009F00), "(!([ab]c)d)" },   //   19
+    { 4,  7, 10, ABC_CONST(0x9F609F609F609F60), "[([ab]c)d]" },   //   20
+    { 4,  7,  9, ABC_CONST(0x9600960096009600), "([abc]d)" },   //   21
+    { 4,  9, 16, ABC_CONST(0x6996699669966996), "[abcd]" },   //   22
+    { 4,  4,  5, ABC_CONST(0xCA00CA00CA00CA00), "(<abc>d)" },   //   23
+    { 4,  6,  8, ABC_CONST(0x35CA35CA35CA35CA), "[<abc>d]" },   //   24
+    { 4,  3,  6, ABC_CONST(0x0777077707770777), "(!(ab)!(cd))" },   //   25
+    { 4,  5,  9, ABC_CONST(0x7888788878887888), "[(ab)(cd)]" },   //   26
+    { 4,  5,  7, ABC_CONST(0x0666066606660666), "([ab]!(cd))" },   //   27
+    { 4,  7,  8, ABC_CONST(0x0660066006600660), "([ab][cd])" },   //   28
+    { 4,  4,  6, ABC_CONST(0xCAAACAAACAAACAAA), "<ab(cd)>" },   //   29
+    { 4,  6,  8, ABC_CONST(0xACCAACCAACCAACCA), "<ab[cd]>" },   //   30
+    { 4,  4,  5, ABC_CONST(0xF088F088F088F088), "<(ab)cd>" },   //   31
+    { 4,  6,  6, ABC_CONST(0xF066F066F066F066), "<[ab]cd>" },   //   32
+    { 5,  4,  6, ABC_CONST(0x8000000080000000), "(abcde)" },   //   33
+    { 5,  4,  6, ABC_CONST(0x7FFF00007FFF0000), "(!(abcd)e)" },   //   34
+    { 5,  6, 10, ABC_CONST(0x7FFF80007FFF8000), "[(abcd)e]" },   //   35
+    { 5,  4,  6, ABC_CONST(0x7F0000007F000000), "(!(abc)de)" },   //   36
+    { 5,  4,  6, ABC_CONST(0x80FF000080FF0000), "(!(!(abc)d)e)" },   //   37
+    { 5,  6, 10, ABC_CONST(0x80FF7F0080FF7F00), "[(!(abc)d)e]" },   //   38
+    { 5,  6,  9, ABC_CONST(0x7F8000007F800000), "([(abc)d]e)" },   //   39
+    { 5,  8, 16, ABC_CONST(0x807F7F80807F7F80), "[(abc)de]" },   //   40
+    { 5,  4,  6, ABC_CONST(0x7000000070000000), "(!(ab)cde)" },   //   41
+    { 5,  4,  6, ABC_CONST(0x8FFF00008FFF0000), "(!(!(ab)cd)e)" },   //   42
+    { 5,  6, 10, ABC_CONST(0x8FFF70008FFF7000), "[(!(ab)cd)e]" },   //   43
+    { 5,  4,  6, ABC_CONST(0x8F0000008F000000), "(!(!(ab)c)de)" },   //   44
+    { 5,  4,  6, ABC_CONST(0x70FF000070FF0000), "(!(!(!(ab)c)d)e)" },   //   45
+    { 5,  6, 10, ABC_CONST(0x70FF8F0070FF8F00), "[(!(!(ab)c)d)e]" },   //   46
+    { 5,  6,  9, ABC_CONST(0x8F7000008F700000), "([(!(ab)c)d]e)" },   //   47
+    { 5,  8, 16, ABC_CONST(0x708F8F70708F8F70), "[(!(ab)c)de]" },   //   48
+    { 5,  6,  8, ABC_CONST(0x7800000078000000), "([(ab)c]de)" },   //   49
+    { 5,  6,  8, ABC_CONST(0x87FF000087FF0000), "(!([(ab)c]d)e)" },   //   50
+    { 5,  8, 14, ABC_CONST(0x87FF780087FF7800), "[([(ab)c]d)e]" },   //   51
+    { 5,  8, 13, ABC_CONST(0x8778000087780000), "([(ab)cd]e)" },   //   52
+    { 5, 10, 24, ABC_CONST(0x7887877878878778), "[(ab)cde]" },   //   53
+    { 5,  6,  7, ABC_CONST(0x6000000060000000), "([ab]cde)" },   //   54
+    { 5,  6,  7, ABC_CONST(0x9FFF00009FFF0000), "(!([ab]cd)e)" },   //   55
+    { 5,  8, 12, ABC_CONST(0x9FFF60009FFF6000), "[([ab]cd)e]" },   //   56
+    { 5,  6,  7, ABC_CONST(0x9F0000009F000000), "(!([ab]c)de)" },   //   57
+    { 5,  6,  7, ABC_CONST(0x60FF000060FF0000), "(!(!([ab]c)d)e)" },   //   58
+    { 5,  8, 12, ABC_CONST(0x60FF9F0060FF9F00), "[(!([ab]c)d)e]" },   //   59
+    { 5,  8, 11, ABC_CONST(0x9F6000009F600000), "([([ab]c)d]e)" },   //   60
+    { 5, 10, 20, ABC_CONST(0x609F9F60609F9F60), "[([ab]c)de]" },   //   61
+    { 5,  8, 10, ABC_CONST(0x9600000096000000), "([abc]de)" },   //   62
+    { 5,  8, 10, ABC_CONST(0x69FF000069FF0000), "(!([abc]d)e)" },   //   63
+    { 5, 10, 18, ABC_CONST(0x69FF960069FF9600), "[([abc]d)e]" },   //   64
+    { 5, 10, 17, ABC_CONST(0x6996000069960000), "([abcd]e)" },   //   65
+    { 5, 12, 32, ABC_CONST(0x9669699696696996), "[abcde]" },   //   66
+    { 5,  5,  6, ABC_CONST(0xCA000000CA000000), "(<abc>de)" },   //   67
+    { 5,  5,  6, ABC_CONST(0x35FF000035FF0000), "(!(<abc>d)e)" },   //   68
+    { 5,  7, 10, ABC_CONST(0x35FFCA0035FFCA00), "[(<abc>d)e]" },   //   69
+    { 5,  7,  9, ABC_CONST(0x35CA000035CA0000), "([<abc>d]e)" },   //   70
+    { 5,  9, 16, ABC_CONST(0xCA3535CACA3535CA), "[<abc>de]" },   //   71
+    { 5,  4,  7, ABC_CONST(0x0777000007770000), "(!(ab)!(cd)e)" },   //   72
+    { 5,  4,  7, ABC_CONST(0xF8880000F8880000), "(!(!(ab)!(cd))e)" },   //   73
+    { 5,  6, 12, ABC_CONST(0xF8880777F8880777), "[(!(ab)!(cd))e]" },   //   74
+    { 5,  6, 10, ABC_CONST(0x7888000078880000), "([(ab)(cd)]e)" },   //   75
+    { 5,  6, 10, ABC_CONST(0x8777000087770000), "(![(ab)(cd)]e)" },   //   76
+    { 5,  8, 18, ABC_CONST(0x8777788887777888), "[(ab)(cd)e]" },   //   77
+    { 5,  6,  8, ABC_CONST(0x0666000006660000), "([ab]!(cd)e)" },   //   78
+    { 5,  6,  8, ABC_CONST(0xF9990000F9990000), "(!([ab]!(cd))e)" },   //   79
+    { 5,  8, 14, ABC_CONST(0xF9990666F9990666), "[([ab]!(cd))e]" },   //   80
+    { 5,  8,  9, ABC_CONST(0x0660000006600000), "([ab][cd]e)" },   //   81
+    { 5,  8,  9, ABC_CONST(0xF99F0000F99F0000), "(!([ab][cd])e)" },   //   82
+    { 5, 10, 16, ABC_CONST(0xF99F0660F99F0660), "[([ab][cd])e]" },   //   83
+    { 5,  5,  7, ABC_CONST(0xCAAA0000CAAA0000), "(<ab(cd)>e)" },   //   84
+    { 5,  7, 12, ABC_CONST(0x3555CAAA3555CAAA), "[<ab(cd)>e]" },   //   85
+    { 5,  7,  9, ABC_CONST(0xACCA0000ACCA0000), "(<ab[cd]>e)" },   //   86
+    { 5,  9, 16, ABC_CONST(0x5335ACCA5335ACCA), "[<ab[cd]>e]" },   //   87
+    { 5,  5,  6, ABC_CONST(0xF0880000F0880000), "(<(ab)cd>e)" },   //   88
+    { 5,  5,  6, ABC_CONST(0x0F7700000F770000), "(!<(ab)cd>e)" },   //   89
+    { 5,  7, 10, ABC_CONST(0x0F77F0880F77F088), "[<(ab)cd>e]" },   //   90
+    { 5,  7,  7, ABC_CONST(0xF0660000F0660000), "(<[ab]cd>e)" },   //   91
+    { 5,  9, 12, ABC_CONST(0x0F99F0660F99F066), "[<[ab]cd>e]" },   //   92
+    { 5,  4,  8, ABC_CONST(0x007F7F7F007F7F7F), "(!(abc)!(de))" },   //   93
+    { 5,  6, 12, ABC_CONST(0x7F8080807F808080), "[(abc)(de)]" },   //   94
+    { 5,  4,  7, ABC_CONST(0x008F8F8F008F8F8F), "(!(!(ab)c)!(de))" },   //   95
+    { 5,  6, 12, ABC_CONST(0x8F7070708F707070), "[(!(ab)c)(de)]" },   //   96
+    { 5,  6, 10, ABC_CONST(0x0078787800787878), "([(ab)c]!(de))" },   //   97
+    { 5,  6,  9, ABC_CONST(0x009F9F9F009F9F9F), "(!([ab]c)!(de))" },   //   98
+    { 5,  8, 15, ABC_CONST(0x9F6060609F606060), "[([ab]c)(de)]" },   //   99
+    { 5,  8, 13, ABC_CONST(0x0096969600969696), "([abc]!(de))" },   //  100
+    { 5,  5,  7, ABC_CONST(0x00CACACA00CACACA), "(<abc>!(de))" },   //  101
+    { 5,  7, 12, ABC_CONST(0x35CACACA35CACACA), "[<abc>(de)]" },   //  102
+    { 5,  6,  9, ABC_CONST(0x007F7F00007F7F00), "(!(abc)[de])" },   //  103
+    { 5,  6,  8, ABC_CONST(0x008F8F00008F8F00), "(!(!(ab)c)[de])" },   //  104
+    { 5,  8, 11, ABC_CONST(0x0078780000787800), "([(ab)c][de])" },   //  105
+    { 5,  8, 10, ABC_CONST(0x009F9F00009F9F00), "(!([ab]c)[de])" },   //  106
+    { 5, 10, 14, ABC_CONST(0x0096960000969600), "([abc][de])" },   //  107
+    { 5,  7,  8, ABC_CONST(0x00CACA0000CACA00), "(<abc>[de])" },   //  108
+    { 5,  5,  8, ABC_CONST(0xCAAAAAAACAAAAAAA), "<ab(cde)>" },   //  109
+    { 5,  5,  8, ABC_CONST(0xACCCAAAAACCCAAAA), "<ab(!(cd)e)>" },   //  110
+    { 5,  7, 12, ABC_CONST(0xACCCCAAAACCCCAAA), "<ab[(cd)e]>" },   //  111
+    { 5,  7, 10, ABC_CONST(0xACCAAAAAACCAAAAA), "<ab([cd]e)>" },   //  112
+    { 5,  9, 16, ABC_CONST(0xCAACACCACAACACCA), "<ab[cde]>" },   //  113
+    { 5,  6,  8, ABC_CONST(0xCCAACACACCAACACA), "<ab<cde>>" },   //  114
+    { 5,  5,  7, ABC_CONST(0xC0AAAAAAC0AAAAAA), "<a(bc)(de)>" },   //  115
+    { 5,  7,  8, ABC_CONST(0x3CAAAAAA3CAAAAAA), "<a[bc](de)>" },   //  116
+    { 5,  5,  8, ABC_CONST(0xF0888888F0888888), "<(ab)c(de)>" },   //  117
+    { 5,  7, 10, ABC_CONST(0x88F0F08888F0F088), "<(ab)c[de]>" },   //  118
+    { 5,  7, 10, ABC_CONST(0xF0666666F0666666), "<[ab]c(de)>" },   //  119
+    { 5,  9, 12, ABC_CONST(0x66F0F06666F0F066), "<[ab]c[de]>" },   //  120
+    { 5,  5,  6, ABC_CONST(0xF0008888F0008888), "<(ab)(cd)e>" },   //  121
+    { 5,  5,  6, ABC_CONST(0xF0007777F0007777), "<!(ab)(cd)e>" },   //  122
+    { 5,  7,  7, ABC_CONST(0xF0006666F0006666), "<[ab](cd)e>" },   //  123
+    { 5,  9,  8, ABC_CONST(0x0FF066660FF06666), "<[ab][cd]e>" },   //  124
+    { 5,  5,  6, ABC_CONST(0xFF008080FF008080), "<(abc)de>" },   //  125
+    { 5,  5,  6, ABC_CONST(0xFF007070FF007070), "<(!(ab)c)de>" },   //  126
+    { 5,  7,  8, ABC_CONST(0xFF007878FF007878), "<[(ab)c]de>" },   //  127
+    { 5,  7,  7, ABC_CONST(0xFF006060FF006060), "<([ab]c)de>" },   //  128
+    { 5,  9, 10, ABC_CONST(0xFF009696FF009696), "<[abc]de>" },   //  129
+    { 5,  6,  6, ABC_CONST(0xFF00CACAFF00CACA), "<<abc>de>" },   //  130
+    { 6,  5,  7, ABC_CONST(0x8000000000000000), "(abcdef)" },   //  131
+    { 6,  5,  7, ABC_CONST(0x7FFFFFFF00000000), "(!(abcde)f)" },   //  132
+    { 6,  7, 12, ABC_CONST(0x7FFFFFFF80000000), "[(abcde)f]" },   //  133
+    { 6,  5,  7, ABC_CONST(0x7FFF000000000000), "(!(abcd)ef)" },   //  134
+    { 6,  5,  7, ABC_CONST(0x8000FFFF00000000), "(!(!(abcd)e)f)" },   //  135
+    { 6,  7, 12, ABC_CONST(0x8000FFFF7FFF0000), "[(!(abcd)e)f]" },   //  136
+    { 6,  7, 11, ABC_CONST(0x7FFF800000000000), "([(abcd)e]f)" },   //  137
+    { 6,  9, 20, ABC_CONST(0x80007FFF7FFF8000), "[(abcd)ef]" },   //  138
+    { 6,  5,  7, ABC_CONST(0x7F00000000000000), "(!(abc)def)" },   //  139
+    { 6,  5,  7, ABC_CONST(0x80FFFFFF00000000), "(!(!(abc)de)f)" },   //  140
+    { 6,  7, 12, ABC_CONST(0x80FFFFFF7F000000), "[(!(abc)de)f]" },   //  141
+    { 6,  5,  7, ABC_CONST(0x80FF000000000000), "(!(!(abc)d)ef)" },   //  142
+    { 6,  5,  7, ABC_CONST(0x7F00FFFF00000000), "(!(!(!(abc)d)e)f)" },   //  143
+    { 6,  7, 12, ABC_CONST(0x7F00FFFF80FF0000), "[(!(!(abc)d)e)f]" },   //  144
+    { 6,  7, 11, ABC_CONST(0x80FF7F0000000000), "([(!(abc)d)e]f)" },   //  145
+    { 6,  9, 20, ABC_CONST(0x7F0080FF80FF7F00), "[(!(abc)d)ef]" },   //  146
+    { 6,  7, 10, ABC_CONST(0x7F80000000000000), "([(abc)d]ef)" },   //  147
+    { 6,  7, 10, ABC_CONST(0x807FFFFF00000000), "(!([(abc)d]e)f)" },   //  148
+    { 6,  9, 18, ABC_CONST(0x807FFFFF7F800000), "[([(abc)d]e)f]" },   //  149
+    { 6,  9, 17, ABC_CONST(0x807F7F8000000000), "([(abc)de]f)" },   //  150
+    { 6, 11, 32, ABC_CONST(0x7F80807F807F7F80), "[(abc)def]" },   //  151
+    { 6,  5,  7, ABC_CONST(0x7000000000000000), "(!(ab)cdef)" },   //  152
+    { 6,  5,  7, ABC_CONST(0x8FFFFFFF00000000), "(!(!(ab)cde)f)" },   //  153
+    { 6,  7, 12, ABC_CONST(0x8FFFFFFF70000000), "[(!(ab)cde)f]" },   //  154
+    { 6,  5,  7, ABC_CONST(0x8FFF000000000000), "(!(!(ab)cd)ef)" },   //  155
+    { 6,  5,  7, ABC_CONST(0x7000FFFF00000000), "(!(!(!(ab)cd)e)f)" },   //  156
+    { 6,  7, 12, ABC_CONST(0x7000FFFF8FFF0000), "[(!(!(ab)cd)e)f]" },   //  157
+    { 6,  7, 11, ABC_CONST(0x8FFF700000000000), "([(!(ab)cd)e]f)" },   //  158
+    { 6,  9, 20, ABC_CONST(0x70008FFF8FFF7000), "[(!(ab)cd)ef]" },   //  159
+    { 6,  5,  7, ABC_CONST(0x8F00000000000000), "(!(!(ab)c)def)" },   //  160
+    { 6,  5,  7, ABC_CONST(0x70FFFFFF00000000), "(!(!(!(ab)c)de)f)" },   //  161
+    { 6,  7, 12, ABC_CONST(0x70FFFFFF8F000000), "[(!(!(ab)c)de)f]" },   //  162
+    { 6,  5,  7, ABC_CONST(0x70FF000000000000), "(!(!(!(ab)c)d)ef)" },   //  163
+    { 6,  5,  7, ABC_CONST(0x8F00FFFF00000000), "(!(!(!(!(ab)c)d)e)f)" },   //  164
+    { 6,  7, 12, ABC_CONST(0x8F00FFFF70FF0000), "[(!(!(!(ab)c)d)e)f]" },   //  165
+    { 6,  7, 11, ABC_CONST(0x70FF8F0000000000), "([(!(!(ab)c)d)e]f)" },   //  166
+    { 6,  9, 20, ABC_CONST(0x8F0070FF70FF8F00), "[(!(!(ab)c)d)ef]" },   //  167
+    { 6,  7, 10, ABC_CONST(0x8F70000000000000), "([(!(ab)c)d]ef)" },   //  168
+    { 6,  7, 10, ABC_CONST(0x708FFFFF00000000), "(!([(!(ab)c)d]e)f)" },   //  169
+    { 6,  9, 18, ABC_CONST(0x708FFFFF8F700000), "[([(!(ab)c)d]e)f]" },   //  170
+    { 6,  9, 17, ABC_CONST(0x708F8F7000000000), "([(!(ab)c)de]f)" },   //  171
+    { 6, 11, 32, ABC_CONST(0x8F70708F708F8F70), "[(!(ab)c)def]" },   //  172
+    { 6,  7,  9, ABC_CONST(0x7800000000000000), "([(ab)c]def)" },   //  173
+    { 6,  7,  9, ABC_CONST(0x87FFFFFF00000000), "(!([(ab)c]de)f)" },   //  174
+    { 6,  9, 16, ABC_CONST(0x87FFFFFF78000000), "[([(ab)c]de)f]" },   //  175
+    { 6,  7,  9, ABC_CONST(0x87FF000000000000), "(!([(ab)c]d)ef)" },   //  176
+    { 6,  7,  9, ABC_CONST(0x7800FFFF00000000), "(!(!([(ab)c]d)e)f)" },   //  177
+    { 6,  9, 16, ABC_CONST(0x7800FFFF87FF0000), "[(!([(ab)c]d)e)f]" },   //  178
+    { 6,  9, 15, ABC_CONST(0x87FF780000000000), "([([(ab)c]d)e]f)" },   //  179
+    { 6, 11, 28, ABC_CONST(0x780087FF87FF7800), "[([(ab)c]d)ef]" },   //  180
+    { 6,  9, 14, ABC_CONST(0x8778000000000000), "([(ab)cd]ef)" },   //  181
+    { 6,  9, 14, ABC_CONST(0x7887FFFF00000000), "(!([(ab)cd]e)f)" },   //  182
+    { 6, 11, 26, ABC_CONST(0x7887FFFF87780000), "[([(ab)cd]e)f]" },   //  183
+    { 6, 11, 25, ABC_CONST(0x7887877800000000), "([(ab)cde]f)" },   //  184
+    { 6, 13, 48, ABC_CONST(0x8778788778878778), "[(ab)cdef]" },   //  185
+    { 6,  7,  8, ABC_CONST(0x6000000000000000), "([ab]cdef)" },   //  186
+    { 6,  7,  8, ABC_CONST(0x9FFFFFFF00000000), "(!([ab]cde)f)" },   //  187
+    { 6,  9, 14, ABC_CONST(0x9FFFFFFF60000000), "[([ab]cde)f]" },   //  188
+    { 6,  7,  8, ABC_CONST(0x9FFF000000000000), "(!([ab]cd)ef)" },   //  189
+    { 6,  7,  8, ABC_CONST(0x6000FFFF00000000), "(!(!([ab]cd)e)f)" },   //  190
+    { 6,  9, 14, ABC_CONST(0x6000FFFF9FFF0000), "[(!([ab]cd)e)f]" },   //  191
+    { 6,  9, 13, ABC_CONST(0x9FFF600000000000), "([([ab]cd)e]f)" },   //  192
+    { 6, 11, 24, ABC_CONST(0x60009FFF9FFF6000), "[([ab]cd)ef]" },   //  193
+    { 6,  7,  8, ABC_CONST(0x9F00000000000000), "(!([ab]c)def)" },   //  194
+    { 6,  7,  8, ABC_CONST(0x60FFFFFF00000000), "(!(!([ab]c)de)f)" },   //  195
+    { 6,  9, 14, ABC_CONST(0x60FFFFFF9F000000), "[(!([ab]c)de)f]" },   //  196
+    { 6,  7,  8, ABC_CONST(0x60FF000000000000), "(!(!([ab]c)d)ef)" },   //  197
+    { 6,  7,  8, ABC_CONST(0x9F00FFFF00000000), "(!(!(!([ab]c)d)e)f)" },   //  198
+    { 6,  9, 14, ABC_CONST(0x9F00FFFF60FF0000), "[(!(!([ab]c)d)e)f]" },   //  199
+    { 6,  9, 13, ABC_CONST(0x60FF9F0000000000), "([(!([ab]c)d)e]f)" },   //  200
+    { 6, 11, 24, ABC_CONST(0x9F0060FF60FF9F00), "[(!([ab]c)d)ef]" },   //  201
+    { 6,  9, 12, ABC_CONST(0x9F60000000000000), "([([ab]c)d]ef)" },   //  202
+    { 6,  9, 12, ABC_CONST(0x609FFFFF00000000), "(!([([ab]c)d]e)f)" },   //  203
+    { 6, 11, 22, ABC_CONST(0x609FFFFF9F600000), "[([([ab]c)d]e)f]" },   //  204
+    { 6, 11, 21, ABC_CONST(0x609F9F6000000000), "([([ab]c)de]f)" },   //  205
+    { 6, 13, 40, ABC_CONST(0x9F60609F609F9F60), "[([ab]c)def]" },   //  206
+    { 6,  9, 11, ABC_CONST(0x9600000000000000), "([abc]def)" },   //  207
+    { 6,  9, 11, ABC_CONST(0x69FFFFFF00000000), "(!([abc]de)f)" },   //  208
+    { 6, 11, 20, ABC_CONST(0x69FFFFFF96000000), "[([abc]de)f]" },   //  209
+    { 6,  9, 11, ABC_CONST(0x69FF000000000000), "(!([abc]d)ef)" },   //  210
+    { 6,  9, 11, ABC_CONST(0x9600FFFF00000000), "(!(!([abc]d)e)f)" },   //  211
+    { 6, 11, 20, ABC_CONST(0x9600FFFF69FF0000), "[(!([abc]d)e)f]" },   //  212
+    { 6, 11, 19, ABC_CONST(0x69FF960000000000), "([([abc]d)e]f)" },   //  213
+    { 6, 13, 36, ABC_CONST(0x960069FF69FF9600), "[([abc]d)ef]" },   //  214
+    { 6, 11, 18, ABC_CONST(0x6996000000000000), "([abcd]ef)" },   //  215
+    { 6, 11, 18, ABC_CONST(0x9669FFFF00000000), "(!([abcd]e)f)" },   //  216
+    { 6, 13, 34, ABC_CONST(0x9669FFFF69960000), "[([abcd]e)f]" },   //  217
+    { 6, 13, 33, ABC_CONST(0x9669699600000000), "([abcde]f)" },   //  218
+    { 6, 15, 64, ABC_CONST(0x6996966996696996), "[abcdef]" },   //  219
+    { 6,  6,  7, ABC_CONST(0xCA00000000000000), "(<abc>def)" },   //  220
+    { 6,  6,  7, ABC_CONST(0x35FFFFFF00000000), "(!(<abc>de)f)" },   //  221
+    { 6,  8, 12, ABC_CONST(0x35FFFFFFCA000000), "[(<abc>de)f]" },   //  222
+    { 6,  6,  7, ABC_CONST(0x35FF000000000000), "(!(<abc>d)ef)" },   //  223
+    { 6,  6,  7, ABC_CONST(0xCA00FFFF00000000), "(!(!(<abc>d)e)f)" },   //  224
+    { 6,  8, 12, ABC_CONST(0xCA00FFFF35FF0000), "[(!(<abc>d)e)f]" },   //  225
+    { 6,  8, 11, ABC_CONST(0x35FFCA0000000000), "([(<abc>d)e]f)" },   //  226
+    { 6, 10, 20, ABC_CONST(0xCA0035FF35FFCA00), "[(<abc>d)ef]" },   //  227
+    { 6,  8, 10, ABC_CONST(0x35CA000000000000), "([<abc>d]ef)" },   //  228
+    { 6,  8, 10, ABC_CONST(0xCA35FFFF00000000), "(!([<abc>d]e)f)" },   //  229
+    { 6, 10, 18, ABC_CONST(0xCA35FFFF35CA0000), "[([<abc>d]e)f]" },   //  230
+    { 6, 10, 17, ABC_CONST(0xCA3535CA00000000), "([<abc>de]f)" },   //  231
+    { 6, 12, 32, ABC_CONST(0x35CACA35CA3535CA), "[<abc>def]" },   //  232
+    { 6,  5,  8, ABC_CONST(0x0777000000000000), "(!(ab)!(cd)ef)" },   //  233
+    { 6,  5,  8, ABC_CONST(0xF888FFFF00000000), "(!(!(ab)!(cd)e)f)" },   //  234
+    { 6,  7, 14, ABC_CONST(0xF888FFFF07770000), "[(!(ab)!(cd)e)f]" },   //  235
+    { 6,  5,  8, ABC_CONST(0xF888000000000000), "(!(!(ab)!(cd))ef)" },   //  236
+    { 6,  5,  8, ABC_CONST(0x0777FFFF00000000), "(!(!(!(ab)!(cd))e)f)" },   //  237
+    { 6,  7, 14, ABC_CONST(0x0777FFFFF8880000), "[(!(!(ab)!(cd))e)f]" },   //  238
+    { 6,  7, 13, ABC_CONST(0xF888077700000000), "([(!(ab)!(cd))e]f)" },   //  239
+    { 6,  9, 24, ABC_CONST(0x0777F888F8880777), "[(!(ab)!(cd))ef]" },   //  240
+    { 6,  7, 11, ABC_CONST(0x7888000000000000), "([(ab)(cd)]ef)" },   //  241
+    { 6,  7, 11, ABC_CONST(0x8777FFFF00000000), "(!([(ab)(cd)]e)f)" },   //  242
+    { 6,  9, 20, ABC_CONST(0x8777FFFF78880000), "[([(ab)(cd)]e)f]" },   //  243
+    { 6,  7, 11, ABC_CONST(0x8777000000000000), "(![(ab)(cd)]ef)" },   //  244
+    { 6,  7, 11, ABC_CONST(0x7888FFFF00000000), "(!(![(ab)(cd)]e)f)" },   //  245
+    { 6,  9, 20, ABC_CONST(0x7888FFFF87770000), "[(![(ab)(cd)]e)f]" },   //  246
+    { 6,  9, 19, ABC_CONST(0x8777788800000000), "([(ab)(cd)e]f)" },   //  247
+    { 6, 11, 36, ABC_CONST(0x7888877787777888), "[(ab)(cd)ef]" },   //  248
+    { 6,  7,  9, ABC_CONST(0x0666000000000000), "([ab]!(cd)ef)" },   //  249
+    { 6,  7,  9, ABC_CONST(0xF999FFFF00000000), "(!([ab]!(cd)e)f)" },   //  250
+    { 6,  9, 16, ABC_CONST(0xF999FFFF06660000), "[([ab]!(cd)e)f]" },   //  251
+    { 6,  7,  9, ABC_CONST(0xF999000000000000), "(!([ab]!(cd))ef)" },   //  252
+    { 6,  7,  9, ABC_CONST(0x0666FFFF00000000), "(!(!([ab]!(cd))e)f)" },   //  253
+    { 6,  9, 16, ABC_CONST(0x0666FFFFF9990000), "[(!([ab]!(cd))e)f]" },   //  254
+    { 6,  9, 15, ABC_CONST(0xF999066600000000), "([([ab]!(cd))e]f)" },   //  255
+    { 6, 11, 28, ABC_CONST(0x0666F999F9990666), "[([ab]!(cd))ef]" },   //  256
+    { 6,  9, 10, ABC_CONST(0x0660000000000000), "([ab][cd]ef)" },   //  257
+    { 6,  9, 10, ABC_CONST(0xF99FFFFF00000000), "(!([ab][cd]e)f)" },   //  258
+    { 6, 11, 18, ABC_CONST(0xF99FFFFF06600000), "[([ab][cd]e)f]" },   //  259
+    { 6,  9, 10, ABC_CONST(0xF99F000000000000), "(!([ab][cd])ef)" },   //  260
+    { 6,  9, 10, ABC_CONST(0x0660FFFF00000000), "(!(!([ab][cd])e)f)" },   //  261
+    { 6, 11, 18, ABC_CONST(0x0660FFFFF99F0000), "[(!([ab][cd])e)f]" },   //  262
+    { 6, 11, 17, ABC_CONST(0xF99F066000000000), "([([ab][cd])e]f)" },   //  263
+    { 6, 13, 32, ABC_CONST(0x0660F99FF99F0660), "[([ab][cd])ef]" },   //  264
+    { 6,  6,  8, ABC_CONST(0xCAAA000000000000), "(<ab(cd)>ef)" },   //  265
+    { 6,  6,  8, ABC_CONST(0x3555FFFF00000000), "(!(<ab(cd)>e)f)" },   //  266
+    { 6,  8, 14, ABC_CONST(0x3555FFFFCAAA0000), "[(<ab(cd)>e)f]" },   //  267
+    { 6,  8, 13, ABC_CONST(0x3555CAAA00000000), "([<ab(cd)>e]f)" },   //  268
+    { 6, 10, 24, ABC_CONST(0xCAAA35553555CAAA), "[<ab(cd)>ef]" },   //  269
+    { 6,  8, 10, ABC_CONST(0xACCA000000000000), "(<ab[cd]>ef)" },   //  270
+    { 6,  8, 10, ABC_CONST(0x5335FFFF00000000), "(!(<ab[cd]>e)f)" },   //  271
+    { 6, 10, 18, ABC_CONST(0x5335FFFFACCA0000), "[(<ab[cd]>e)f]" },   //  272
+    { 6, 10, 17, ABC_CONST(0x5335ACCA00000000), "([<ab[cd]>e]f)" },   //  273
+    { 6, 12, 32, ABC_CONST(0xACCA53355335ACCA), "[<ab[cd]>ef]" },   //  274
+    { 6,  6,  7, ABC_CONST(0xF088000000000000), "(<(ab)cd>ef)" },   //  275
+    { 6,  6,  7, ABC_CONST(0x0F77FFFF00000000), "(!(<(ab)cd>e)f)" },   //  276
+    { 6,  8, 12, ABC_CONST(0x0F77FFFFF0880000), "[(<(ab)cd>e)f]" },   //  277
+    { 6,  6,  7, ABC_CONST(0x0F77000000000000), "(!<(ab)cd>ef)" },   //  278
+    { 6,  6,  7, ABC_CONST(0xF088FFFF00000000), "(!(!<(ab)cd>e)f)" },   //  279
+    { 6,  8, 12, ABC_CONST(0xF088FFFF0F770000), "[(!<(ab)cd>e)f]" },   //  280
+    { 6,  8, 11, ABC_CONST(0x0F77F08800000000), "([<(ab)cd>e]f)" },   //  281
+    { 6, 10, 20, ABC_CONST(0xF0880F770F77F088), "[<(ab)cd>ef]" },   //  282
+    { 6,  8,  8, ABC_CONST(0xF066000000000000), "(<[ab]cd>ef)" },   //  283
+    { 6,  8,  8, ABC_CONST(0x0F99FFFF00000000), "(!(<[ab]cd>e)f)" },   //  284
+    { 6, 10, 14, ABC_CONST(0x0F99FFFFF0660000), "[(<[ab]cd>e)f]" },   //  285
+    { 6, 10, 13, ABC_CONST(0x0F99F06600000000), "([<[ab]cd>e]f)" },   //  286
+    { 6, 12, 24, ABC_CONST(0xF0660F990F99F066), "[<[ab]cd>ef]" },   //  287
+    { 6,  5,  9, ABC_CONST(0x007F7F7F00000000), "(!(abc)!(de)f)" },   //  288
+    { 6,  5,  9, ABC_CONST(0xFF80808000000000), "(!(!(abc)!(de))f)" },   //  289
+    { 6,  7, 16, ABC_CONST(0xFF808080007F7F7F), "[(!(abc)!(de))f]" },   //  290
+    { 6,  7, 13, ABC_CONST(0x7F80808000000000), "([(abc)(de)]f)" },   //  291
+    { 6,  7, 13, ABC_CONST(0x807F7F7F00000000), "(![(abc)(de)]f)" },   //  292
+    { 6,  9, 24, ABC_CONST(0x807F7F7F7F808080), "[(abc)(de)f]" },   //  293
+    { 6,  5,  8, ABC_CONST(0x008F8F8F00000000), "(!(!(ab)c)!(de)f)" },   //  294
+    { 6,  5,  8, ABC_CONST(0xFF70707000000000), "(!(!(!(ab)c)!(de))f)" },   //  295
+    { 6,  7, 14, ABC_CONST(0xFF707070008F8F8F), "[(!(!(ab)c)!(de))f]" },   //  296
+    { 6,  7, 13, ABC_CONST(0x8F70707000000000), "([(!(ab)c)(de)]f)" },   //  297
+    { 6,  7, 13, ABC_CONST(0x708F8F8F00000000), "(![(!(ab)c)(de)]f)" },   //  298
+    { 6,  9, 24, ABC_CONST(0x708F8F8F8F707070), "[(!(ab)c)(de)f]" },   //  299
+    { 6,  7, 11, ABC_CONST(0x0078787800000000), "([(ab)c]!(de)f)" },   //  300
+    { 6,  7, 11, ABC_CONST(0xFF87878700000000), "(!([(ab)c]!(de))f)" },   //  301
+    { 6,  9, 20, ABC_CONST(0xFF87878700787878), "[([(ab)c]!(de))f]" },   //  302
+    { 6,  7, 10, ABC_CONST(0x009F9F9F00000000), "(!([ab]c)!(de)f)" },   //  303
+    { 6,  7, 10, ABC_CONST(0xFF60606000000000), "(!(!([ab]c)!(de))f)" },   //  304
+    { 6,  9, 18, ABC_CONST(0xFF606060009F9F9F), "[(!([ab]c)!(de))f]" },   //  305
+    { 6,  9, 16, ABC_CONST(0x9F60606000000000), "([([ab]c)(de)]f)" },   //  306
+    { 6,  9, 16, ABC_CONST(0x609F9F9F00000000), "(![([ab]c)(de)]f)" },   //  307
+    { 6, 11, 30, ABC_CONST(0x609F9F9F9F606060), "[([ab]c)(de)f]" },   //  308
+    { 6,  9, 14, ABC_CONST(0x0096969600000000), "([abc]!(de)f)" },   //  309
+    { 6,  9, 14, ABC_CONST(0xFF69696900000000), "(!([abc]!(de))f)" },   //  310
+    { 6, 11, 26, ABC_CONST(0xFF69696900969696), "[([abc]!(de))f]" },   //  311
+    { 6,  6,  8, ABC_CONST(0x00CACACA00000000), "(<abc>!(de)f)" },   //  312
+    { 6,  6,  8, ABC_CONST(0xFF35353500000000), "(!(<abc>!(de))f)" },   //  313
+    { 6,  8, 14, ABC_CONST(0xFF35353500CACACA), "[(<abc>!(de))f]" },   //  314
+    { 6,  8, 13, ABC_CONST(0x35CACACA00000000), "([<abc>(de)]f)" },   //  315
+    { 6, 10, 24, ABC_CONST(0xCA35353535CACACA), "[<abc>(de)f]" },   //  316
+    { 6,  7, 10, ABC_CONST(0x007F7F0000000000), "(!(abc)[de]f)" },   //  317
+    { 6,  7, 10, ABC_CONST(0xFF8080FF00000000), "(!(!(abc)[de])f)" },   //  318
+    { 6,  9, 18, ABC_CONST(0xFF8080FF007F7F00), "[(!(abc)[de])f]" },   //  319
+    { 6,  7,  9, ABC_CONST(0x008F8F0000000000), "(!(!(ab)c)[de]f)" },   //  320
+    { 6,  7,  9, ABC_CONST(0xFF7070FF00000000), "(!(!(!(ab)c)[de])f)" },   //  321
+    { 6,  9, 16, ABC_CONST(0xFF7070FF008F8F00), "[(!(!(ab)c)[de])f]" },   //  322
+    { 6,  9, 12, ABC_CONST(0x0078780000000000), "([(ab)c][de]f)" },   //  323
+    { 6,  9, 12, ABC_CONST(0xFF8787FF00000000), "(!([(ab)c][de])f)" },   //  324
+    { 6, 11, 22, ABC_CONST(0xFF8787FF00787800), "[([(ab)c][de])f]" },   //  325
+    { 6,  9, 11, ABC_CONST(0x009F9F0000000000), "(!([ab]c)[de]f)" },   //  326
+    { 6,  9, 11, ABC_CONST(0xFF6060FF00000000), "(!(!([ab]c)[de])f)" },   //  327
+    { 6, 11, 20, ABC_CONST(0xFF6060FF009F9F00), "[(!([ab]c)[de])f]" },   //  328
+    { 6, 11, 15, ABC_CONST(0x0096960000000000), "([abc][de]f)" },   //  329
+    { 6, 11, 15, ABC_CONST(0xFF6969FF00000000), "(!([abc][de])f)" },   //  330
+    { 6, 13, 28, ABC_CONST(0xFF6969FF00969600), "[([abc][de])f]" },   //  331
+    { 6,  8,  9, ABC_CONST(0x00CACA0000000000), "(<abc>[de]f)" },   //  332
+    { 6,  8,  9, ABC_CONST(0xFF3535FF00000000), "(!(<abc>[de])f)" },   //  333
+    { 6, 10, 16, ABC_CONST(0xFF3535FF00CACA00), "[(<abc>[de])f]" },   //  334
+    { 6,  6,  9, ABC_CONST(0xCAAAAAAA00000000), "(<ab(cde)>f)" },   //  335
+    { 6,  8, 16, ABC_CONST(0x35555555CAAAAAAA), "[<ab(cde)>f]" },   //  336
+    { 6,  6,  9, ABC_CONST(0xACCCAAAA00000000), "(<ab(!(cd)e)>f)" },   //  337
+    { 6,  8, 16, ABC_CONST(0x53335555ACCCAAAA), "[<ab(!(cd)e)>f]" },   //  338
+    { 6,  8, 13, ABC_CONST(0xACCCCAAA00000000), "(<ab[(cd)e]>f)" },   //  339
+    { 6, 10, 24, ABC_CONST(0x53333555ACCCCAAA), "[<ab[(cd)e]>f]" },   //  340
+    { 6,  8, 11, ABC_CONST(0xACCAAAAA00000000), "(<ab([cd]e)>f)" },   //  341
+    { 6, 10, 20, ABC_CONST(0x53355555ACCAAAAA), "[<ab([cd]e)>f]" },   //  342
+    { 6, 10, 17, ABC_CONST(0xCAACACCA00000000), "(<ab[cde]>f)" },   //  343
+    { 6, 12, 32, ABC_CONST(0x35535335CAACACCA), "[<ab[cde]>f]" },   //  344
+    { 6,  7,  9, ABC_CONST(0xCCAACACA00000000), "(<ab<cde>>f)" },   //  345
+    { 6,  9, 16, ABC_CONST(0x33553535CCAACACA), "[<ab<cde>>f]" },   //  346
+    { 6,  6,  8, ABC_CONST(0xC0AAAAAA00000000), "(<a(bc)(de)>f)" },   //  347
+    { 6,  6,  8, ABC_CONST(0x3F55555500000000), "(!<a(bc)(de)>f)" },   //  348
+    { 6,  8, 14, ABC_CONST(0x3F555555C0AAAAAA), "[<a(bc)(de)>f]" },   //  349
+    { 6,  8,  9, ABC_CONST(0x3CAAAAAA00000000), "(<a[bc](de)>f)" },   //  350
+    { 6, 10, 16, ABC_CONST(0xC35555553CAAAAAA), "[<a[bc](de)>f]" },   //  351
+    { 6,  6,  9, ABC_CONST(0xF088888800000000), "(<(ab)c(de)>f)" },   //  352
+    { 6,  6,  9, ABC_CONST(0x0F77777700000000), "(!<(ab)c(de)>f)" },   //  353
+    { 6,  8, 16, ABC_CONST(0x0F777777F0888888), "[<(ab)c(de)>f]" },   //  354
+    { 6,  8, 11, ABC_CONST(0x88F0F08800000000), "(<(ab)c[de]>f)" },   //  355
+    { 6,  8, 11, ABC_CONST(0x770F0F7700000000), "(!<(ab)c[de]>f)" },   //  356
+    { 6, 10, 20, ABC_CONST(0x770F0F7788F0F088), "[<(ab)c[de]>f]" },   //  357
+    { 6,  8, 11, ABC_CONST(0xF066666600000000), "(<[ab]c(de)>f)" },   //  358
+    { 6, 10, 20, ABC_CONST(0x0F999999F0666666), "[<[ab]c(de)>f]" },   //  359
+    { 6, 10, 13, ABC_CONST(0x66F0F06600000000), "(<[ab]c[de]>f)" },   //  360
+    { 6, 12, 24, ABC_CONST(0x990F0F9966F0F066), "[<[ab]c[de]>f]" },   //  361
+    { 6,  6,  7, ABC_CONST(0xF000888800000000), "(<(ab)(cd)e>f)" },   //  362
+    { 6,  6,  7, ABC_CONST(0x0FFF777700000000), "(!<(ab)(cd)e>f)" },   //  363
+    { 6,  8, 12, ABC_CONST(0x0FFF7777F0008888), "[<(ab)(cd)e>f]" },   //  364
+    { 6,  6,  7, ABC_CONST(0xF000777700000000), "(<!(ab)(cd)e>f)" },   //  365
+    { 6,  8, 12, ABC_CONST(0x0FFF8888F0007777), "[<!(ab)(cd)e>f]" },   //  366
+    { 6,  8,  8, ABC_CONST(0xF000666600000000), "(<[ab](cd)e>f)" },   //  367
+    { 6,  8,  8, ABC_CONST(0x0FFF999900000000), "(!<[ab](cd)e>f)" },   //  368
+    { 6, 10, 14, ABC_CONST(0x0FFF9999F0006666), "[<[ab](cd)e>f]" },   //  369
+    { 6, 10,  9, ABC_CONST(0x0FF0666600000000), "(<[ab][cd]e>f)" },   //  370
+    { 6, 12, 16, ABC_CONST(0xF00F99990FF06666), "[<[ab][cd]e>f]" },   //  371
+    { 6,  6,  7, ABC_CONST(0xFF00808000000000), "(<(abc)de>f)" },   //  372
+    { 6,  6,  7, ABC_CONST(0x00FF7F7F00000000), "(!<(abc)de>f)" },   //  373
+    { 6,  8, 12, ABC_CONST(0x00FF7F7FFF008080), "[<(abc)de>f]" },   //  374
+    { 6,  6,  7, ABC_CONST(0xFF00707000000000), "(<(!(ab)c)de>f)" },   //  375
+    { 6,  6,  7, ABC_CONST(0x00FF8F8F00000000), "(!<(!(ab)c)de>f)" },   //  376
+    { 6,  8, 12, ABC_CONST(0x00FF8F8FFF007070), "[<(!(ab)c)de>f]" },   //  377
+    { 6,  8,  9, ABC_CONST(0xFF00787800000000), "(<[(ab)c]de>f)" },   //  378
+    { 6, 10, 16, ABC_CONST(0x00FF8787FF007878), "[<[(ab)c]de>f]" },   //  379
+    { 6,  8,  8, ABC_CONST(0xFF00606000000000), "(<([ab]c)de>f)" },   //  380
+    { 6,  8,  8, ABC_CONST(0x00FF9F9F00000000), "(!<([ab]c)de>f)" },   //  381
+    { 6, 10, 14, ABC_CONST(0x00FF9F9FFF006060), "[<([ab]c)de>f]" },   //  382
+    { 6, 10, 11, ABC_CONST(0xFF00969600000000), "(<[abc]de>f)" },   //  383
+    { 6, 12, 20, ABC_CONST(0x00FF6969FF009696), "[<[abc]de>f]" },   //  384
+    { 6,  7,  7, ABC_CONST(0xFF00CACA00000000), "(<<abc>de>f)" },   //  385
+    { 6,  9, 12, ABC_CONST(0x00FF3535FF00CACA), "[<<abc>de>f]" },   //  386
+    { 6,  5, 10, ABC_CONST(0x00007FFF7FFF7FFF), "(!(abcd)!(ef))" },   //  387
+    { 6,  7, 15, ABC_CONST(0x7FFF800080008000), "[(abcd)(ef)]" },   //  388
+    { 6,  5,  8, ABC_CONST(0x000080FF80FF80FF), "(!(!(abc)d)!(ef))" },   //  389
+    { 6,  7, 15, ABC_CONST(0x80FF7F007F007F00), "[(!(abc)d)(ef)]" },   //  390
+    { 6,  7, 13, ABC_CONST(0x00007F807F807F80), "([(abc)d]!(ef))" },   //  391
+    { 6,  5,  9, ABC_CONST(0x00008FFF8FFF8FFF), "(!(!(ab)cd)!(ef))" },   //  392
+    { 6,  7, 15, ABC_CONST(0x8FFF700070007000), "[(!(ab)cd)(ef)]" },   //  393
+    { 6,  5,  9, ABC_CONST(0x000070FF70FF70FF), "(!(!(!(ab)c)d)!(ef))" },   //  394
+    { 6,  7, 15, ABC_CONST(0x70FF8F008F008F00), "[(!(!(ab)c)d)(ef)]" },   //  395
+    { 6,  7, 13, ABC_CONST(0x00008F708F708F70), "([(!(ab)c)d]!(ef))" },   //  396
+    { 6,  7, 12, ABC_CONST(0x000087FF87FF87FF), "(!([(ab)c]d)!(ef))" },   //  397
+    { 6,  9, 21, ABC_CONST(0x87FF780078007800), "[([(ab)c]d)(ef)]" },   //  398
+    { 6,  9, 19, ABC_CONST(0x0000877887788778), "([(ab)cd]!(ef))" },   //  399
+    { 6,  7, 11, ABC_CONST(0x00009FFF9FFF9FFF), "(!([ab]cd)!(ef))" },   //  400
+    { 6,  9, 18, ABC_CONST(0x9FFF600060006000), "[([ab]cd)(ef)]" },   //  401
+    { 6,  7, 10, ABC_CONST(0x000060FF60FF60FF), "(!(!([ab]c)d)!(ef))" },   //  402
+    { 6,  9, 18, ABC_CONST(0x60FF9F009F009F00), "[(!([ab]c)d)(ef)]" },   //  403
+    { 6,  9, 16, ABC_CONST(0x00009F609F609F60), "([([ab]c)d]!(ef))" },   //  404
+    { 6,  9, 15, ABC_CONST(0x000069FF69FF69FF), "(!([abc]d)!(ef))" },   //  405
+    { 6, 11, 27, ABC_CONST(0x69FF960096009600), "[([abc]d)(ef)]" },   //  406
+    { 6, 11, 25, ABC_CONST(0x0000699669966996), "([abcd]!(ef))" },   //  407
+    { 6,  6,  9, ABC_CONST(0x000035FF35FF35FF), "(!(<abc>d)!(ef))" },   //  408
+    { 6,  8, 15, ABC_CONST(0x35FFCA00CA00CA00), "[(<abc>d)(ef)]" },   //  409
+    { 6,  8, 13, ABC_CONST(0x000035CA35CA35CA), "([<abc>d]!(ef))" },   //  410
+    { 6,  5, 11, ABC_CONST(0x0000077707770777), "(!(ab)!(cd)!(ef))" },   //  411
+    { 6,  5,  9, ABC_CONST(0x0000F888F888F888), "(!(!(ab)!(cd))!(ef))" },   //  412
+    { 6,  7, 18, ABC_CONST(0xF888077707770777), "[(!(ab)!(cd))(ef)]" },   //  413
+    { 6,  7, 14, ABC_CONST(0x0000788878887888), "([(ab)(cd)]!(ef))" },   //  414
+    { 6,  7, 15, ABC_CONST(0x0000877787778777), "(![(ab)(cd)]!(ef))" },   //  415
+    { 6,  9, 27, ABC_CONST(0x8777788878887888), "[(ab)(cd)(ef)]" },   //  416
+    { 6,  7, 12, ABC_CONST(0x0000066606660666), "([ab]!(cd)!(ef))" },   //  417
+    { 6,  7, 11, ABC_CONST(0x0000F999F999F999), "(!([ab]!(cd))!(ef))" },   //  418
+    { 6,  9, 21, ABC_CONST(0xF999066606660666), "[([ab]!(cd))(ef)]" },   //  419
+    { 6,  9, 13, ABC_CONST(0x0000066006600660), "([ab][cd]!(ef))" },   //  420
+    { 6,  9, 13, ABC_CONST(0x0000F99FF99FF99F), "(!([ab][cd])!(ef))" },   //  421
+    { 6, 11, 24, ABC_CONST(0xF99F066006600660), "[([ab][cd])(ef)]" },   //  422
+    { 6,  6, 10, ABC_CONST(0x0000CAAACAAACAAA), "(<ab(cd)>!(ef))" },   //  423
+    { 6,  8, 18, ABC_CONST(0x3555CAAACAAACAAA), "[<ab(cd)>(ef)]" },   //  424
+    { 6,  8, 13, ABC_CONST(0x0000ACCAACCAACCA), "(<ab[cd]>!(ef))" },   //  425
+    { 6, 10, 24, ABC_CONST(0x5335ACCAACCAACCA), "[<ab[cd]>(ef)]" },   //  426
+    { 6,  6,  8, ABC_CONST(0x0000F088F088F088), "(<(ab)cd>!(ef))" },   //  427
+    { 6,  6,  9, ABC_CONST(0x00000F770F770F77), "(!<(ab)cd>!(ef))" },   //  428
+    { 6,  8, 15, ABC_CONST(0x0F77F088F088F088), "[<(ab)cd>(ef)]" },   //  429
+    { 6,  8, 10, ABC_CONST(0x0000F066F066F066), "(<[ab]cd>!(ef))" },   //  430
+    { 6, 10, 18, ABC_CONST(0x0F99F066F066F066), "[<[ab]cd>(ef)]" },   //  431
+    { 6,  7, 11, ABC_CONST(0x00007FFF7FFF0000), "(!(abcd)[ef])" },   //  432
+    { 6,  7,  9, ABC_CONST(0x000080FF80FF0000), "(!(!(abc)d)[ef])" },   //  433
+    { 6,  9, 14, ABC_CONST(0x00007F807F800000), "([(abc)d][ef])" },   //  434
+    { 6,  7, 10, ABC_CONST(0x00008FFF8FFF0000), "(!(!(ab)cd)[ef])" },   //  435
+    { 6,  7, 10, ABC_CONST(0x000070FF70FF0000), "(!(!(!(ab)c)d)[ef])" },   //  436
+    { 6,  9, 14, ABC_CONST(0x00008F708F700000), "([(!(ab)c)d][ef])" },   //  437
+    { 6,  9, 13, ABC_CONST(0x000087FF87FF0000), "(!([(ab)c]d)[ef])" },   //  438
+    { 6, 11, 20, ABC_CONST(0x0000877887780000), "([(ab)cd][ef])" },   //  439
+    { 6,  9, 12, ABC_CONST(0x00009FFF9FFF0000), "(!([ab]cd)[ef])" },   //  440
+    { 6,  9, 11, ABC_CONST(0x000060FF60FF0000), "(!(!([ab]c)d)[ef])" },   //  441
+    { 6, 11, 17, ABC_CONST(0x00009F609F600000), "([([ab]c)d][ef])" },   //  442
+    { 6, 11, 16, ABC_CONST(0x000069FF69FF0000), "(!([abc]d)[ef])" },   //  443
+    { 6, 13, 26, ABC_CONST(0x0000699669960000), "([abcd][ef])" },   //  444
+    { 6,  8, 10, ABC_CONST(0x000035FF35FF0000), "(!(<abc>d)[ef])" },   //  445
+    { 6, 10, 14, ABC_CONST(0x000035CA35CA0000), "([<abc>d][ef])" },   //  446
+    { 6,  7, 10, ABC_CONST(0x0000F888F8880000), "(!(!(ab)!(cd))[ef])" },   //  447
+    { 6,  9, 15, ABC_CONST(0x0000788878880000), "([(ab)(cd)][ef])" },   //  448
+    { 6,  9, 16, ABC_CONST(0x0000877787770000), "(![(ab)(cd)][ef])" },   //  449
+    { 6,  9, 12, ABC_CONST(0x0000F999F9990000), "(!([ab]!(cd))[ef])" },   //  450
+    { 6, 11, 14, ABC_CONST(0x0000066006600000), "([ab][cd][ef])" },   //  451
+    { 6, 11, 14, ABC_CONST(0x0000F99FF99F0000), "(!([ab][cd])[ef])" },   //  452
+    { 6,  8, 11, ABC_CONST(0x0000CAAACAAA0000), "(<ab(cd)>[ef])" },   //  453
+    { 6, 10, 14, ABC_CONST(0x0000ACCAACCA0000), "(<ab[cd]>[ef])" },   //  454
+    { 6,  8,  9, ABC_CONST(0x0000F088F0880000), "(<(ab)cd>[ef])" },   //  455
+    { 6,  8, 10, ABC_CONST(0x00000F770F770000), "(!<(ab)cd>[ef])" },   //  456
+    { 6, 10, 11, ABC_CONST(0x0000F066F0660000), "(<[ab]cd>[ef])" },   //  457
+    { 6,  5, 11, ABC_CONST(0x007F7F7F7F7F7F7F), "(!(abc)!(def))" },   //  458
+    { 6,  7, 16, ABC_CONST(0x7F80808080808080), "[(abc)(def)]" },   //  459
+    { 6,  5,  9, ABC_CONST(0x008F8F8F8F8F8F8F), "(!(!(ab)c)!(def))" },   //  460
+    { 6,  7, 16, ABC_CONST(0x8F70707070707070), "[(!(ab)c)(def)]" },   //  461
+    { 6,  7, 13, ABC_CONST(0x0078787878787878), "([(ab)c]!(def))" },   //  462
+    { 6,  7, 12, ABC_CONST(0x009F9F9F9F9F9F9F), "(!([ab]c)!(def))" },   //  463
+    { 6,  9, 20, ABC_CONST(0x9F60606060606060), "[([ab]c)(def)]" },   //  464
+    { 6,  9, 17, ABC_CONST(0x0096969696969696), "([abc]!(def))" },   //  465
+    { 6,  6,  9, ABC_CONST(0x00CACACACACACACA), "(<abc>!(def))" },   //  466
+    { 6,  8, 16, ABC_CONST(0x35CACACACACACACA), "[<abc>(def)]" },   //  467
+    { 6,  5,  8, ABC_CONST(0x8F0000008F8F8F8F), "(!(!(ab)c)!(!(de)f))" },   //  468
+    { 6,  7, 16, ABC_CONST(0x708F8F8F70707070), "[(!(ab)c)(!(de)f)]" },   //  469
+    { 6,  7, 11, ABC_CONST(0x7800000078787878), "([(ab)c]!(!(de)f))" },   //  470
+    { 6,  7, 10, ABC_CONST(0x9F0000009F9F9F9F), "(!([ab]c)!(!(de)f))" },   //  471
+    { 6,  9, 20, ABC_CONST(0x609F9F9F60606060), "[([ab]c)(!(de)f)]" },   //  472
+    { 6,  9, 14, ABC_CONST(0x9600000096969696), "([abc]!(!(de)f))" },   //  473
+    { 6,  6,  8, ABC_CONST(0xCA000000CACACACA), "(<abc>!(!(de)f))" },   //  474
+    { 6,  8, 16, ABC_CONST(0xCA353535CACACACA), "[<abc>(!(de)f)]" },   //  475
+    { 6,  9, 15, ABC_CONST(0x0078787878000000), "([(ab)c][(de)f])" },   //  476
+    { 6,  9, 14, ABC_CONST(0x009F9F9F9F000000), "(!([ab]c)[(de)f])" },   //  477
+    { 6, 11, 19, ABC_CONST(0x0096969696000000), "([abc][(de)f])" },   //  478
+    { 6,  8, 11, ABC_CONST(0x00CACACACA000000), "(<abc>[(de)f])" },   //  479
+    { 6,  9, 13, ABC_CONST(0x9F00009F9F9F9F9F), "(!([ab]c)!([de]f))" },   //  480
+    { 6, 11, 25, ABC_CONST(0x609F9F6060606060), "[([ab]c)([de]f)]" },   //  481
+    { 6, 11, 18, ABC_CONST(0x9600009696969696), "([abc]!([de]f))" },   //  482
+    { 6,  8, 10, ABC_CONST(0xCA0000CACACACACA), "(<abc>!([de]f))" },   //  483
+    { 6, 10, 20, ABC_CONST(0xCA3535CACACACACA), "[<abc>([de]f)]" },   //  484
+    { 6, 13, 24, ABC_CONST(0x9600009600969600), "([abc][def])" },   //  485
+    { 6, 10, 14, ABC_CONST(0xCA0000CA00CACA00), "(<abc>[def])" },   //  486
+    { 6,  7,  8, ABC_CONST(0xCACA0000CA00CA00), "(<abc><def>)" },   //  487
+    { 6,  9, 16, ABC_CONST(0x3535CACA35CA35CA), "[<abc><def>]" },   //  488
+    { 6,  6, 10, ABC_CONST(0xCAAAAAAAAAAAAAAA), "<ab(cdef)>" },   //  489
+    { 6,  6, 10, ABC_CONST(0xACCCCCCCAAAAAAAA), "<ab(!(cde)f)>" },   //  490
+    { 6,  8, 16, ABC_CONST(0xACCCCCCCCAAAAAAA), "<ab[(cde)f]>" },   //  491
+    { 6,  6, 10, ABC_CONST(0xACCCAAAAAAAAAAAA), "<ab(!(cd)ef)>" },   //  492
+    { 6,  6, 10, ABC_CONST(0xCAAACCCCAAAAAAAA), "<ab(!(!(cd)e)f)>" },   //  493
+    { 6,  8, 16, ABC_CONST(0xCAAACCCCACCCAAAA), "<ab[(!(cd)e)f]>" },   //  494
+    { 6,  8, 14, ABC_CONST(0xACCCCAAAAAAAAAAA), "<ab([(cd)e]f)>" },   //  495
+    { 6, 10, 24, ABC_CONST(0xCAAAACCCACCCCAAA), "<ab[(cd)ef]>" },   //  496
+    { 6,  8, 12, ABC_CONST(0xACCAAAAAAAAAAAAA), "<ab([cd]ef)>" },   //  497
+    { 6,  8, 12, ABC_CONST(0xCAACCCCCAAAAAAAA), "<ab(!([cd]e)f)>" },   //  498
+    { 6, 10, 20, ABC_CONST(0xCAACCCCCACCAAAAA), "<ab[([cd]e)f]>" },   //  499
+    { 6, 10, 18, ABC_CONST(0xCAACACCAAAAAAAAA), "<ab([cde]f)>" },   //  500
+    { 6, 12, 32, ABC_CONST(0xACCACAACCAACACCA), "<ab[cdef]>" },   //  501
+    { 6,  7, 10, ABC_CONST(0xCCAACACAAAAAAAAA), "<ab(<cde>f)>" },   //  502
+    { 6,  9, 16, ABC_CONST(0xAACCACACCCAACACA), "<ab[<cde>f]>" },   //  503
+    { 6,  6, 12, ABC_CONST(0xAAAAACCCACCCACCC), "<ab(!(cd)!(ef))>" },   //  504
+    { 6,  8, 18, ABC_CONST(0xACCCCAAACAAACAAA), "<ab[(cd)(ef)]>" },   //  505
+    { 6,  8, 14, ABC_CONST(0xAAAAACCAACCAACCA), "<ab([cd]!(ef))>" },   //  506
+    { 6, 10, 16, ABC_CONST(0xAAAAACCAACCAAAAA), "<ab([cd][ef])>" },   //  507
+    { 6,  7, 12, ABC_CONST(0xCCAACACACACACACA), "<ab<cd(ef)>>" },   //  508
+    { 6,  9, 16, ABC_CONST(0xCACACCAACCAACACA), "<ab<cd[ef]>>" },   //  509
+    { 6,  7, 10, ABC_CONST(0xCCCCAAAACAAACAAA), "<ab<(cd)ef>>" },   //  510
+    { 6,  9, 12, ABC_CONST(0xCCCCAAAAACCAACCA), "<ab<[cd]ef>>" },   //  511
+    { 6,  6,  9, ABC_CONST(0xC0AAAAAAAAAAAAAA), "<a(bc)(def)>" },   //  512
+    { 6,  6, 10, ABC_CONST(0xAAC0C0C0AAAAAAAA), "<a(bc)(!(de)f)>" },   //  513
+    { 6,  8, 12, ABC_CONST(0xAAC0C0AAAAAAAAAA), "<a(bc)([de]f)>" },   //  514
+    { 6,  8, 10, ABC_CONST(0x3CAAAAAAAAAAAAAA), "<a[bc](def)>" },   //  515
+    { 6,  8, 12, ABC_CONST(0xAA3C3C3CAAAAAAAA), "<a[bc](!(de)f)>" },   //  516
+    { 6, 10, 14, ABC_CONST(0xAA3C3CAAAAAAAAAA), "<a[bc]([de]f)>" },   //  517
+    { 6,  6,  8, ABC_CONST(0xC000AAAAAAAAAAAA), "<a(bcd)(ef)>" },   //  518
+    { 6,  6,  8, ABC_CONST(0x3F00AAAAAAAAAAAA), "<a(!(bc)d)(ef)>" },   //  519
+    { 6,  8, 10, ABC_CONST(0x3FC0AAAAAAAAAAAA), "<a[(bc)d](ef)>" },   //  520
+    { 6,  8,  9, ABC_CONST(0x3C00AAAAAAAAAAAA), "<a([bc]d)(ef)>" },   //  521
+    { 6, 10, 12, ABC_CONST(0xC33CAAAAAAAAAAAA), "<a[bcd](ef)>" },   //  522
+    { 6,  7,  8, ABC_CONST(0xF0CCAAAAAAAAAAAA), "<a<bcd>(ef)>" },   //  523
+    { 6,  6, 11, ABC_CONST(0xF088888888888888), "<(ab)c(def)>" },   //  524
+    { 6,  6, 10, ABC_CONST(0x88F0F0F088888888), "<(ab)c(!(de)f)>" },   //  525
+    { 6,  8, 15, ABC_CONST(0x88F0F0F0F0888888), "<(ab)c[(de)f]>" },   //  526
+    { 6,  8, 13, ABC_CONST(0x88F0F08888888888), "<(ab)c([de]f)>" },   //  527
+    { 6, 10, 20, ABC_CONST(0xF08888F088F0F088), "<(ab)c[def]>" },   //  528
+    { 6,  7, 10, ABC_CONST(0xF0F08888F088F088), "<(ab)c<def>>" },   //  529
+    { 6,  8, 14, ABC_CONST(0xF066666666666666), "<[ab]c(def)>" },   //  530
+    { 6,  8, 12, ABC_CONST(0x66F0F0F066666666), "<[ab]c(!(de)f)>" },   //  531
+    { 6, 10, 18, ABC_CONST(0x66F0F0F0F0666666), "<[ab]c[(de)f]>" },   //  532
+    { 6, 10, 16, ABC_CONST(0x66F0F06666666666), "<[ab]c([de]f)>" },   //  533
+    { 6, 12, 24, ABC_CONST(0xF06666F066F0F066), "<[ab]c[def]>" },   //  534
+    { 6,  9, 12, ABC_CONST(0xF0F06666F066F066), "<[ab]c<def>>" },   //  535
+    { 6,  6,  9, ABC_CONST(0xF000888888888888), "<(ab)(cd)(ef)>" },   //  536
+    { 6,  6,  9, ABC_CONST(0xF000777777777777), "<!(ab)(cd)(ef)>" },   //  537
+    { 6,  8, 12, ABC_CONST(0x8888F000F0008888), "<(ab)(cd)[ef]>" },   //  538
+    { 6,  8, 12, ABC_CONST(0x7777F000F0007777), "<!(ab)(cd)[ef]>" },   //  539
+    { 6,  8, 10, ABC_CONST(0x0FF0888888888888), "<(ab)[cd](ef)>" },   //  540
+    { 6,  8, 11, ABC_CONST(0xF000666666666666), "<[ab](cd)(ef)>" },   //  541
+    { 6, 10, 14, ABC_CONST(0x6666F000F0006666), "<[ab](cd)[ef]>" },   //  542
+    { 6, 10, 12, ABC_CONST(0x0FF0666666666666), "<[ab][cd](ef)>" },   //  543
+    { 6, 12, 16, ABC_CONST(0x66660FF00FF06666), "<[ab][cd][ef]>" },   //  544
+    { 6,  6, 10, ABC_CONST(0xFF00808080808080), "<(abc)d(ef)>" },   //  545
+    { 6,  8, 12, ABC_CONST(0x8080FF00FF008080), "<(abc)d[ef]>" },   //  546
+    { 6,  6, 10, ABC_CONST(0xFF00707070707070), "<(!(ab)c)d(ef)>" },   //  547
+    { 6,  8, 12, ABC_CONST(0x7070FF00FF007070), "<(!(ab)c)d[ef]>" },   //  548
+    { 6,  8, 14, ABC_CONST(0xFF00787878787878), "<[(ab)c]d(ef)>" },   //  549
+    { 6, 10, 16, ABC_CONST(0x7878FF00FF007878), "<[(ab)c]d[ef]>" },   //  550
+    { 6,  8, 12, ABC_CONST(0xFF00606060606060), "<([ab]c)d(ef)>" },   //  551
+    { 6, 10, 14, ABC_CONST(0x6060FF00FF006060), "<([ab]c)d[ef]>" },   //  552
+    { 6, 10, 18, ABC_CONST(0xFF00969696969696), "<[abc]d(ef)>" },   //  553
+    { 6, 12, 20, ABC_CONST(0x9696FF00FF009696), "<[abc]d[ef]>" },   //  554
+    { 6,  7, 10, ABC_CONST(0xFF00CACACACACACA), "<<abc>d(ef)>" },   //  555
+    { 6,  9, 12, ABC_CONST(0xCACAFF00FF00CACA), "<<abc>d[ef]>" },   //  556
+    { 6,  6,  7, ABC_CONST(0xFF00000080808080), "<(abc)(de)f>" },   //  557
+    { 6,  6,  7, ABC_CONST(0xFF0000007F7F7F7F), "<!(abc)(de)f>" },   //  558
+    { 6,  8,  8, ABC_CONST(0x00FFFF0080808080), "<(abc)[de]f>" },   //  559
+    { 6,  6,  7, ABC_CONST(0xFF00000070707070), "<(!(ab)c)(de)f>" },   //  560
+    { 6,  6,  7, ABC_CONST(0xFF0000008F8F8F8F), "<!(!(ab)c)(de)f>" },   //  561
+    { 6,  8,  8, ABC_CONST(0x00FFFF0070707070), "<(!(ab)c)[de]f>" },   //  562
+    { 6,  8,  9, ABC_CONST(0xFF00000078787878), "<[(ab)c](de)f>" },   //  563
+    { 6, 10, 10, ABC_CONST(0x00FFFF0078787878), "<[(ab)c][de]f>" },   //  564
+    { 6,  8,  8, ABC_CONST(0xFF00000060606060), "<([ab]c)(de)f>" },   //  565
+    { 6,  8,  8, ABC_CONST(0xFF0000009F9F9F9F), "<!([ab]c)(de)f>" },   //  566
+    { 6, 10,  9, ABC_CONST(0x00FFFF0060606060), "<([ab]c)[de]f>" },   //  567
+    { 6, 10, 11, ABC_CONST(0xFF00000096969696), "<[abc](de)f>" },   //  568
+    { 6, 12, 12, ABC_CONST(0x00FFFF0096969696), "<[abc][de]f>" },   //  569
+    { 6,  7,  7, ABC_CONST(0xFF000000CACACACA), "<<abc>(de)f>" },   //  570
+    { 6,  9,  8, ABC_CONST(0x00FFFF00CACACACA), "<<abc>[de]f>" },   //  571
+    { 6,  6,  7, ABC_CONST(0xFFFF000080008000), "<(abcd)ef>" },   //  572
+    { 6,  6,  7, ABC_CONST(0xFFFF00007F007F00), "<(!(abc)d)ef>" },   //  573
+    { 6,  8, 10, ABC_CONST(0xFFFF00007F807F80), "<[(abc)d]ef>" },   //  574
+    { 6,  6,  7, ABC_CONST(0xFFFF000070007000), "<(!(ab)cd)ef>" },   //  575
+    { 6,  6,  7, ABC_CONST(0xFFFF00008F008F00), "<(!(!(ab)c)d)ef>" },   //  576
+    { 6,  8, 10, ABC_CONST(0xFFFF00008F708F70), "<[(!(ab)c)d]ef>" },   //  577
+    { 6,  8,  9, ABC_CONST(0xFFFF000078007800), "<([(ab)c]d)ef>" },   //  578
+    { 6, 10, 14, ABC_CONST(0xFFFF000087788778), "<[(ab)cd]ef>" },   //  579
+    { 6,  8,  8, ABC_CONST(0xFFFF000060006000), "<([ab]cd)ef>" },   //  580
+    { 6,  8,  8, ABC_CONST(0xFFFF00009F009F00), "<(!([ab]c)d)ef>" },   //  581
+    { 6, 10, 12, ABC_CONST(0xFFFF00009F609F60), "<[([ab]c)d]ef>" },   //  582
+    { 6, 10, 11, ABC_CONST(0xFFFF000096009600), "<([abc]d)ef>" },   //  583
+    { 6, 12, 18, ABC_CONST(0xFFFF000069966996), "<[abcd]ef>" },   //  584
+    { 6,  7,  7, ABC_CONST(0xFFFF0000CA00CA00), "<(<abc>d)ef>" },   //  585
+    { 6,  9, 10, ABC_CONST(0xFFFF000035CA35CA), "<[<abc>d]ef>" },   //  586
+    { 6,  6,  8, ABC_CONST(0xFFFF000007770777), "<(!(ab)!(cd))ef>" },   //  587
+    { 6,  8, 11, ABC_CONST(0xFFFF000078887888), "<[(ab)(cd)]ef>" },   //  588
+    { 6,  8,  9, ABC_CONST(0xFFFF000006660666), "<([ab]!(cd))ef>" },   //  589
+    { 6, 10, 10, ABC_CONST(0xFFFF000006600660), "<([ab][cd])ef>" },   //  590
+    { 6,  7,  8, ABC_CONST(0xFFFF0000CAAACAAA), "<<ab(cd)>ef>" },   //  591
+    { 6,  9, 10, ABC_CONST(0xFFFF0000ACCAACCA), "<<ab[cd]>ef>" },   //  592
+    { 6,  7,  7, ABC_CONST(0xFFFF0000F088F088), "<<(ab)cd>ef>" },   //  593
+    { 6,  9,  8, ABC_CONST(0xFFFF0000F066F066), "<<[ab]cd>ef>" }    //  594
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Wrd_t * Mpm_ManGetTruthWithCnf( int Limit )
+{
+    Vec_Wrd_t * vRes = Vec_WrdAlloc( 1000 );
+    int i;
+    for ( i = 0; i < 595; i++ )
+        if ( s_DsdClass6[i].nClauses <= Limit )
+            Vec_WrdPush( vRes, s_DsdClass6[i].uTruth );
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mpm_ManPrintDsdStats( Mpm_Man_t * p )
+{
+    int i, Absent = 0;
+    for ( i = 0; i < 595; i++ )
+    {
+        if ( p->nCountDsd[i] == 0 )
+        {
+            Absent++;
+            continue;
+        }
+        if ( p->pPars->fVeryVerbose )
+        {
+            printf( "%5d  :  ", i );
+            printf( "%-20s   ", p->pDsd6[i].pStr );
+            printf( "%8d ",     p->nCountDsd[i] );
+            printf( "\n" );
+        }
+    }
+    printf( "Unused classes = %d (%.2f %%).  ",  Absent, 100.0 * Absent / 595 );
+    printf( "Non-DSD cuts = %d (%.2f %%).  ",   p->nNonDsd, 100.0 * p->nNonDsd / p->nCutsMergedAll );
+    printf( "No-match cuts = %d (%.2f %%).\n",  p->nNoMatch, 100.0 * p->nNoMatch / p->nCutsMergedAll );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hsh_IntMan_t * Mpm_ManBuildHashTable( Vec_Int_t ** pvConfgRes ) 
+{
+    FILE * pFile;
+    char * pFileName = "dsdfuncs6.dat";
+    int RetValue, size = Extra_FileSize( pFileName ) / 12;  // 2866420
+    Vec_Wrd_t * vTruthRes = Vec_WrdAlloc( size );
+    Vec_Int_t * vConfgRes = Vec_IntAlloc( size );
+    Hsh_IntMan_t * pHash;
+
+    pFile = fopen( pFileName, "rb" );
+    RetValue = fread( Vec_WrdArray(vTruthRes), sizeof(word), size, pFile );
+    RetValue = fread( Vec_IntArray(vConfgRes), sizeof(int), size, pFile );
+    vTruthRes->nSize = size;
+    vConfgRes->nSize = size;
+    // create hash table
+    pHash = Hsh_WrdManHashArrayStart( vTruthRes, 1 );
+    // cleanup
+    if ( pvConfgRes )
+        *pvConfgRes = vConfgRes;
+    else
+        Vec_IntFree( vConfgRes );
+    Vec_WrdFree( vTruthRes );
+//    Hsh_IntManStop( pHash );
+    return pHash;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mpm_ManPrintPerm( unsigned s )
+{
+    int i;
+    for ( i = 0; i < 6; i++ )
+        printf( "%d ", (s >> (3*i)) & 7 );
+    printf( "  " );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mpm_ManPrecomputePerms( Mpm_Man_t * p )
+{
+    int nVars = 6;
+    // 0(1:1) 1(2:1) 2(4:2) 3(10:6) 4(33:23) 5(131:98) 6(595:464)
+    int nClasses[7] = { 1, 2, 4, 10, 33, 131, 595 };
+    int nPerms = Extra_Factorial( nVars );
+//    int nSwaps = (1 << nVars);
+    int * pComp, * pPerm;
+    int i, k, x, One, OneCopy, Num;
+    Vec_Int_t * vVars;
+    abctime clk = Abc_Clock();
+    assert( p->pDsd6 == NULL );
+    p->pDsd6 = s_DsdClass6;
+    // precompute schedules
+    pComp = Extra_GreyCodeSchedule( nVars );
+    pPerm = Extra_PermSchedule( nVars );
+    // map numbers into perms
+    p->vMap2Perm = Vec_IntStartFull( (1<<(3*nVars)) );
+    // store permutations
+    One = 0;
+    for ( x = 0; x < nVars; x++ )
+    {
+        p->Perm6[0][x] = (char)x;
+        One |= (x << (3*x));
+    }
+//    Vec_IntWriteEntry( p->vMap2Perm, One, 0 );
+    OneCopy = One;
+    for ( k = 0; k < nPerms; k++ )
+    {
+        if ( k > 0 )
+        for ( x = 0; x < nVars; x++ )
+            p->Perm6[k][x] = p->Perm6[k-1][x];
+        ABC_SWAP( char, p->Perm6[k][pPerm[k]], p->Perm6[k][pPerm[k]+1] );
+
+        Num = ( (One >> (3*(pPerm[k]  ))) ^ (One >> (3*(pPerm[k]+1))) ) & 7;
+        One ^=  (Num << (3*(pPerm[k]  )));
+        One ^=  (Num << (3*(pPerm[k]+1)));
+
+        Vec_IntWriteEntry( p->vMap2Perm, One, k );
+        
+//        Mpm_ManPrintPerm( One );
+//        for ( x = 0; x < nVars; x++ )
+//            printf( "%d ", p->Perm6[k][x] );
+//        printf( "\n" );
+    }
+    assert( OneCopy == One );
+    // fill in the gaps
+    vVars = Vec_IntAlloc( 6 );
+    Vec_IntForEachEntry( p->vMap2Perm, Num, i )
+    {
+        // mark used variables
+        int Count = 0;
+        One = i;
+        Vec_IntFill( vVars, 6, 0 );
+        for ( k = 0; k < nVars; k++ )
+        {
+            int iVar = ((One >> (3*k)) & 7);
+            if ( iVar >= nVars && iVar < 7 )
+                break;
+            if ( iVar != 7 )
+            {
+                if ( Vec_IntEntry( vVars, iVar ) == 1 )
+                    break;
+                Vec_IntWriteEntry( vVars, iVar, 1 );
+                Count++;
+            }
+        }
+        // skip ones with dups and complete
+        if ( k < nVars || Count == nVars )
+            continue;
+        // find unused variables
+        for ( x = k = 0; k < 6; k++ )
+            if ( Vec_IntEntry(vVars, k) == 0 )
+                Vec_IntWriteEntry( vVars, x++, k );
+        Vec_IntShrink( vVars, x );
+        // fill in used variables
+        x = 0;
+        for ( k = 0; k < nVars; k++ )
+        {
+            int iVar = ((One >> (3*k)) & 7);
+            if ( iVar == 7 )
+                One ^= ((Vec_IntEntry(vVars, x++) ^ 7) << (3*k));
+        }
+        assert( x == Vec_IntSize(vVars) );
+        // save this one
+        assert( Vec_IntEntry( p->vMap2Perm, One ) != -1 );
+        Vec_IntWriteEntry( p->vMap2Perm, i, Vec_IntEntry(p->vMap2Perm, One) );
+/*
+        // mapping
+        Mpm_ManPrintPerm( i );
+        printf( "->  " );
+        Mpm_ManPrintPerm( One );
+        printf( "\n" );
+*/
+    }
+    Vec_IntFree( vVars );
+
+    // store permuted truth tables
+    assert( p->vPerm6 == NULL );
+    p->vPerm6 = Vec_WrdAlloc( nPerms * 595 );
+    for ( i = 0; i < nClasses[nVars]; i++ )
+    {
+        word uTruth = s_DsdClass6[i].uTruth;
+        for ( k = 0; k < nPerms; k++ )
+        {
+            uTruth = Abc_Tt6SwapAdjacent( uTruth, pPerm[k] );
+            Vec_WrdPush( p->vPerm6, uTruth );
+        }
+        assert( uTruth == s_DsdClass6[i].uTruth );
+    }
+    ABC_FREE( pPerm );
+    ABC_FREE( pComp );
+    // build hash table
+    p->pHash = Mpm_ManBuildHashTable( &p->vConfgRes );
+    Abc_PrintTime( 1, "Setting up DSD information", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word Mpm_CutTruthFromDsd( Mpm_Man_t * pMan, Mpm_Cut_t * pCut, int iClass )
+{
+    int i;
+    word uTruth = pMan->pDsd6[iClass].uTruth;
+    assert( pMan->pDsd6[iClass].nVars == (int)pCut->nLeaves );
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        if ( Abc_LitIsCompl(pCut->pLeaves[i]) )
+            uTruth = Abc_Tt6Flip( uTruth, i ); 
+    return uTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks hash table for DSD class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mpm_CutCheckDsd6( Mpm_Man_t * p, word t )
+{
+    int fCompl, Entry, Config;
+    if ( (fCompl = (t & 1)) )
+        t = ~t;
+    Entry = *Hsh_IntManLookup( p->pHash, (unsigned *)&t );
+    if ( Entry == -1 )
+        return -1;
+    Config = Vec_IntEntry( p->vConfgRes, Entry );
+    if ( fCompl )
+        Config ^= (1 << 16);
+    return Config;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mpm_CutComputeDsd6( Mpm_Man_t * p, Mpm_Cut_t * pCut, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, int Type )
+{
+    int fVerbose = 0;
+    int i, Config, iClass, fCompl;
+    int pLeavesNew[6] = { -1, -1, -1, -1, -1, -1 };
+    word t = 0;
+    if ( pCutC == NULL )
+    {
+        word t0, t1;
+        int iClass0  = Abc_Lit2Var(pCut0->iFunc);
+        int iClass1  = Abc_Lit2Var(pCut1->iFunc);
+        word Truth0  = p->pDsd6[iClass0].uTruth;
+        int Perm1    = Vec_IntEntry( p->vMap2Perm, p->uPermMask[1] );
+        word Truth1p = Vec_WrdEntry( p->vPerm6, iClass1 * 720 + Perm1 );
+        if ( p->uComplMask[1] )
+        {
+            for ( i = 0; i < 6; i++ )
+                if ( (p->uComplMask[1] >> i) & 1 )
+                    Truth1p = Abc_Tt6Flip( Truth1p, i );            
+        }
+        t0 = (fCompl0 ^ pCut0->fCompl ^ Abc_LitIsCompl(pCut0->iFunc)) ? ~Truth0  : Truth0;
+        t1 = (fCompl1 ^ pCut1->fCompl ^ Abc_LitIsCompl(pCut1->iFunc)) ? ~Truth1p : Truth1p;
+        if ( Type == 1 )
+            t = t0 & t1;
+        else if ( Type == 2 )
+            t = t0 ^ t1;
+        else assert( 0 );
+
+if ( fVerbose )
+{
+Mpm_ManPrintPerm( p->uPermMask[1] );               printf( "\n" );
+Kit_DsdPrintFromTruth( (unsigned *)&Truth0, 6 );   printf( "\n" );
+Kit_DsdPrintFromTruth( (unsigned *)&Truth1p, 6 );  printf( "\n" );
+Kit_DsdPrintFromTruth( (unsigned *)&t, 6 );        printf( "\n" );
+}
+    }
+    else
+    {
+        word t0, t1, tC;
+        int iClass0  = Abc_Lit2Var(pCut0->iFunc);
+        int iClass1  = Abc_Lit2Var(pCut1->iFunc);
+        int iClassC  = Abc_Lit2Var(pCutC->iFunc);
+        word Truth0  = p->pDsd6[iClass0].uTruth;
+        int Perm1    = Vec_IntEntry( p->vMap2Perm, p->uPermMask[1] );
+        int PermC    = Vec_IntEntry( p->vMap2Perm, p->uPermMask[2] );
+        word Truth1p = Vec_WrdEntry( p->vPerm6, iClass1 * 720 + Perm1 );
+        word TruthCp = Vec_WrdEntry( p->vPerm6, iClassC * 720 + PermC );
+        if ( p->uComplMask[1] )
+        {
+            for ( i = 0; i < 6; i++ )
+                if ( (p->uComplMask[1] >> i) & 1 )
+                    Truth1p = Abc_Tt6Flip( Truth1p, i );            
+        }
+        if ( p->uComplMask[2] )
+        {
+            for ( i = 0; i < 6; i++ )
+                if ( (p->uComplMask[2] >> i) & 1 )
+                    TruthCp = Abc_Tt6Flip( TruthCp, i );            
+        }
+        t0 = (fCompl0 ^ pCut0->fCompl ^ Abc_LitIsCompl(pCut0->iFunc)) ? ~Truth0  : Truth0;
+        t1 = (fCompl1 ^ pCut1->fCompl ^ Abc_LitIsCompl(pCut1->iFunc)) ? ~Truth1p : Truth1p;
+        tC = (fComplC ^ pCutC->fCompl ^ Abc_LitIsCompl(pCutC->iFunc)) ? ~TruthCp : TruthCp;
+        t = (tC & t1) | (~tC & t0);
+    }
+
+    // find configuration
+    Config = Mpm_CutCheckDsd6( p, t );
+    if ( Config == -1 )
+    {
+        p->nNonDsd++;
+        return 0;
+    }
+
+    // get the class
+    iClass = Config >> 17;
+    fCompl = (Config >> 16) & 1;
+    Config &= 0xFFFF;
+
+    // check if the gate exists
+    if ( p->pPars->fMap4Gates )
+    {
+        if ( Vec_IntSize(Vec_WecEntry(p->vNpnConfigs, iClass)) == 0 )
+        {
+            p->nNoMatch++;
+            return 0;
+        }
+    }
+
+    // set the function
+    pCut->iFunc = Abc_Var2Lit( iClass, fCompl );
+
+if ( fVerbose )
+{
+Mpm_CutPrint( pCut0 );
+Mpm_CutPrint( pCut1 );
+Mpm_CutPrint( pCut );
+}
+
+    // update cut
+    assert( (Config >> 6) < 720 );
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        pLeavesNew[(int)(p->Perm6[Config >> 6][i])] = Abc_LitNotCond( pCut->pLeaves[i], (Config >> i) & 1 );
+    pCut->nLeaves = p->pDsd6[iClass].nVars;
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        assert( pLeavesNew[i] != -1 );
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        pCut->pLeaves[i] = pLeavesNew[i];
+    p->nCountDsd[iClass]++;
+    p->nSmallSupp += (int)(pCut->nLeaves < 2);
+
+if ( fVerbose )
+{
+printf( "Computed " );
+Mpm_CutPrint( pCut );
+printf( "\n" );
+}
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mpm/mpmGates.c b/abc-build/src/map/mpm/mpmGates.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mpm/mpmGates.c
@@ -0,0 +1,307 @@
+/**CFile****************************************************************
+
+  FileName    [mpmGates.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Configurable technology mapper.]
+
+  Synopsis    [Standard-cell mapping.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 1, 2013.]
+
+  Revision    [$Id: mpmGates.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mpmInt.h"
+#include "misc/st/st.h"
+#include "map/mio/mio.h"
+#include "map/scl/sclSize.h"
+#include "map/scl/sclTime.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Finds matches fore each DSD class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Wec_t * Mpm_ManFindDsdMatches( Mpm_Man_t * p, void * pScl )
+{
+    int fVerbose = p->pPars->fVeryVerbose;
+    SC_Lib * pLib = (SC_Lib *)pScl;
+    Vec_Wec_t * vClasses;
+    Vec_Int_t * vClass;
+    SC_Cell * pRepr;
+    int i, Config, iClass;
+    word Truth;
+    vClasses = Vec_WecStart( 600 );
+    SC_LibForEachCellClass( pLib, pRepr, i )
+    {
+        if ( pRepr->n_inputs > 6 || pRepr->n_outputs > 1 )
+        {
+            if ( fVerbose )
+            printf( "Skipping cell %s with %d inputs and %d outputs\n", pRepr->pName, pRepr->n_inputs, pRepr->n_outputs );
+            continue;
+        }
+        Truth = *Vec_WrdArray( SC_CellPin(pRepr, pRepr->n_inputs)->vFunc );
+        Config = Mpm_CutCheckDsd6( p, Truth );
+        if ( Config == -1 )
+        {
+            if ( fVerbose )
+            printf( "Skipping cell %s with non-DSD function\n", pRepr->pName );
+            continue;
+        }
+        iClass = Config >> 17;
+        Config = (pRepr->Id << 17) | (Config & 0x1FFFF);
+        // write gate and NPN config for this DSD class
+        vClass = Vec_WecEntry( vClasses, iClass );
+        Vec_IntPush( vClass, Config );
+        if ( !fVerbose )
+            continue;
+
+        printf( "Gate %5d  %-30s : ", pRepr->Id, pRepr->pName );
+        printf( "Class %3d  ", iClass );
+        printf( "Area %10.3f  ", pRepr->area );
+        Extra_PrintBinary( stdout, (unsigned *)&Config, 17 );
+        printf( "   " );
+        Kit_DsdPrintFromTruth( (unsigned *)&Truth, pRepr->n_inputs ); printf( "\n" );
+    }
+    return vClasses;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find mapping of DSD classes into Genlib library cells.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Mpm_ManFindCells( Mio_Library_t * pMio, SC_Lib * pScl, Vec_Wec_t * vNpnConfigs )
+{
+    Vec_Ptr_t * vNpnGatesMio;
+    Vec_Int_t * vClass;
+    Mio_Gate_t * pMioGate;
+    SC_Cell * pCell;
+    int Config, iClass;
+    vNpnGatesMio = Vec_PtrStart( Vec_WecSize(vNpnConfigs) );
+    Vec_WecForEachLevel( vNpnConfigs, vClass, iClass )
+    {
+        if ( Vec_IntSize(vClass) == 0 )
+            continue;
+        Config = Vec_IntEntry(vClass, 0);
+        pCell = SC_LibCell( pScl, (Config >> 17) );
+        pMioGate = Mio_LibraryReadGateByName( pMio, pCell->pName, NULL );
+        if ( pMioGate == NULL )
+        {
+            Vec_PtrFree( vNpnGatesMio );
+            return NULL;
+        }
+        assert( pMioGate != NULL );
+        Vec_PtrWriteEntry( vNpnGatesMio, iClass, pMioGate );
+    }
+    return vNpnGatesMio;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive mapped network as an ABC network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Mpm_ManFindMappedNodes( Mpm_Man_t * p )
+{
+    Vec_Int_t * vNodes;
+    Mig_Obj_t * pObj;
+    vNodes = Vec_IntAlloc( 1000 );
+    Mig_ManForEachObj( p->pMig, pObj )
+        if ( Mig_ObjIsNode(pObj) && Mpm_ObjMapRef(p, pObj) )
+            Vec_IntPush( vNodes, Mig_ObjId(pObj) );
+    return vNodes;
+}
+Abc_Obj_t * Mpm_ManGetAbcNode( Abc_Ntk_t * pNtk, Vec_Int_t * vCopy, int iMigLit )
+{
+    Abc_Obj_t * pObj;
+    int iObjId = Vec_IntEntry( vCopy, iMigLit );
+    if ( iObjId >= 0 )
+        return Abc_NtkObj( pNtk, iObjId );
+    iObjId = Vec_IntEntry( vCopy, Abc_LitNot(iMigLit) );
+    assert( iObjId >= 0 );
+    pObj = Abc_NtkCreateNodeInv( pNtk, Abc_NtkObj(pNtk, iObjId) );
+    Vec_IntWriteEntry( vCopy, iMigLit, Abc_ObjId(pObj) );
+    return pObj;
+}
+Abc_Ntk_t * Mpm_ManDeriveMappedAbcNtk( Mpm_Man_t * p, Mio_Library_t * pMio )
+{
+    Abc_Ntk_t * pNtk;
+    Vec_Ptr_t * vNpnGatesMio;
+    Vec_Int_t * vNodes, * vCopy, * vClass;
+    Abc_Obj_t * pObj, * pFanin;
+    Mig_Obj_t * pNode;
+    Mpm_Cut_t * pCutBest;
+    int i, k, iNode, iMigLit, fCompl, Config;
+
+    // find mapping of SCL cells into MIO cells
+    vNpnGatesMio = Mpm_ManFindCells( pMio, (SC_Lib *)p->pPars->pScl, p->vNpnConfigs );
+    if ( vNpnGatesMio == NULL )
+    {
+        printf( "Genlib library does not match SCL library.\n" );
+        return NULL;
+    }
+
+    // create mapping for each phase of each node
+    vCopy = Vec_IntStartFull( 2 * Mig_ManObjNum(p->pMig) );
+
+    // get internal nodes
+    vNodes = Mpm_ManFindMappedNodes( p );
+
+    // start the network
+    pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_MAP, 1 );
+    pNtk->pName = Extra_UtilStrsav( p->pMig->pName );
+    pNtk->pManFunc = pMio;
+
+    // create primary inputs
+    Mig_ManForEachCi( p->pMig, pNode, i )
+    {
+        pObj = Abc_NtkCreatePi(pNtk);
+        Vec_IntWriteEntry( vCopy, Abc_Var2Lit( Mig_ObjId(pNode), 0 ), Abc_ObjId(pObj) );
+    }
+    Abc_NtkAddDummyPiNames( pNtk );
+
+    // create constant nodes
+    Mig_ManForEachCo( p->pMig, pNode, i )
+        if ( Mig_ObjFaninLit(pNode, 0) == 0 )
+        {
+            pObj = Abc_NtkCreateNodeConst0(pNtk);
+            Vec_IntWriteEntry( vCopy, Abc_Var2Lit( 0, 0 ), Abc_ObjId(pObj) );
+            break;
+        }
+    Mig_ManForEachCo( p->pMig, pNode, i )
+        if ( Mig_ObjFaninLit(pNode, 0) == 1 )
+        {
+            pObj = Abc_NtkCreateNodeConst1(pNtk);
+            Vec_IntWriteEntry( vCopy, Abc_Var2Lit( 0, 1 ), Abc_ObjId(pObj) );
+            break;
+        }
+
+    // create internal nodes
+    Vec_IntForEachEntry( vNodes, iNode, i )
+    {
+        pCutBest = Mpm_ObjCutBestP( p, Mig_ManObj(p->pMig, iNode) );
+        vClass = Vec_WecEntry( p->vNpnConfigs, Abc_Lit2Var(pCutBest->iFunc) );
+        Config = Vec_IntEntry( vClass, 0 );
+        pObj = Abc_NtkCreateNode( pNtk );
+        pObj->pData = Vec_PtrEntry( vNpnGatesMio, Abc_Lit2Var(pCutBest->iFunc) );
+        assert( pObj->pData != NULL );
+        fCompl = pCutBest->fCompl ^ Abc_LitIsCompl(pCutBest->iFunc) ^ ((Config >> 16) & 1);
+        Config &= 0xFFFF;
+        for ( k = 0; k < (int)pCutBest->nLeaves; k++ )
+        {
+            assert( (Config >> 6) < 720 );
+            iMigLit = pCutBest->pLeaves[ (int)(p->Perm6[Config >> 6][k]) ];
+            pFanin = Mpm_ManGetAbcNode( pNtk, vCopy, Abc_LitNotCond(iMigLit, (Config >> k) & 1) );
+            Abc_ObjAddFanin( pObj, pFanin );
+        }
+        Vec_IntWriteEntry( vCopy, Abc_Var2Lit(iNode, fCompl), Abc_ObjId(pObj) );
+    }
+
+    // create primary outputs
+    Mig_ManForEachCo( p->pMig, pNode, i )
+    {
+        pObj = Abc_NtkCreatePo(pNtk);
+        pFanin = Mpm_ManGetAbcNode( pNtk, vCopy, Mig_ObjFaninLit(pNode, 0) );
+        Abc_ObjAddFanin( pObj, pFanin );
+    }
+    Abc_NtkAddDummyPoNames( pNtk );
+
+    // clean up
+    Vec_PtrFree( vNpnGatesMio );
+    Vec_IntFree( vNodes );
+    Vec_IntFree( vCopy );
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Mpm_ManPerformCellMapping( Mig_Man_t * pMig, Mpm_Par_t * pPars, Mio_Library_t * pMio )
+{
+    Abc_Ntk_t * pNew;
+    Mpm_Man_t * p;
+    assert( pPars->fMap4Gates );
+    p = Mpm_ManStart( pMig, pPars );
+    if ( p->pPars->fVerbose ) 
+        Mpm_ManPrintStatsInit( p );
+    p->vNpnConfigs = Mpm_ManFindDsdMatches( p, p->pPars->pScl );
+    Mpm_ManPrepare( p );
+    Mpm_ManPerform( p );
+    if ( p->pPars->fVerbose ) 
+        Mpm_ManPrintStats( p );
+    pNew = Mpm_ManDeriveMappedAbcNtk( p, pMio );
+    Mpm_ManStop( p );
+    return pNew;
+}
+Abc_Ntk_t * Mpm_ManCellMapping( Gia_Man_t * pGia, Mpm_Par_t * pPars, void * pMio )
+{
+    Mig_Man_t * p;
+    Abc_Ntk_t * pNew;
+    assert( pMio != NULL );
+    assert( pPars->pLib->LutMax <= MPM_VAR_MAX );
+    assert( pPars->nNumCuts <= MPM_CUT_MAX );
+    if ( pPars->fUseGates )
+    {
+        pGia = Gia_ManDupMuxes( pGia, 2 );
+        p = Mig_ManCreate( pGia );
+        Gia_ManStop( pGia );
+    }
+    else
+        p = Mig_ManCreate( pGia );
+    pNew = Mpm_ManPerformCellMapping( p, pPars, (Mio_Library_t *)pMio );
+    Mig_ManStop( p );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mpm/mpmInt.h b/abc-build/src/map/mpm/mpmInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mpm/mpmInt.h
@@ -0,0 +1,265 @@
+/**CFile****************************************************************
+
+  FileName    [mpmInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Configurable technology mapper.]
+
+  Synopsis    [Interal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 1, 2013.]
+
+  Revision    [$Id: mpmInt.h,v 1.00 2013/06/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__map__mpm_Int_h
+#define ABC__map__mpm_Int_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+ 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+//#include "misc/tim/tim.h"
+#include "misc/mem/mem2.h"
+#include "misc/vec/vec.h"
+#include "misc/vec/vecMem.h"
+#include "misc/vec/vecHsh.h"
+#include "misc/vec/vecWec.h"
+#include "misc/util/utilTruth.h"
+#include "mpmMig.h"
+#include "mpm.h"
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+ 
+#define MPM_CUT_MAX      32
+
+#define MPM_UNIT_TIME     1
+#define MPM_UNIT_AREA    20
+#define MPM_UNIT_EDGE    50
+#define MPM_UNIT_REFS   100
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Mpm_Cut_t_ Mpm_Cut_t;  // 8 bytes + NLeaves * 4 bytes
+struct Mpm_Cut_t_
+{
+    int              hNext;                    // next cut
+    unsigned         iFunc     : 25;           // function
+    unsigned         fCompl    :  1;
+    unsigned         fUseless  :  1;           // internal flag
+    unsigned         nLeaves   :  5;           // leaves
+    int              pLeaves[1];               // leaves
+};
+typedef struct Mpm_Uni_t_ Mpm_Uni_t;  // 48 bytes
+struct Mpm_Uni_t_
+{ 
+    int              mTime;                    // arrival time
+    int              mArea;                    // area (flow)
+    int              mEdge;                    // edge (flow)
+    int              mAveRefs;                 // area references
+    word             uSign;                    // cut signature
+    int              Cost;                     // user cost
+    Mpm_Cut_t        pCut;                     // new cut
+    int              Data[MPM_VAR_MAX-1];      // padding
+};
+
+typedef struct Mpm_Dsd_t_ Mpm_Dsd_t;
+struct Mpm_Dsd_t_
+{
+    int              nVars;                    // support size
+    int              nAnds;                    // the number of AND gates
+    int              nClauses;                 // the number of CNF clauses
+    word             uTruth;                   // truth table
+    char *           pStr;                     // description 
+};
+
+typedef struct Mpm_Man_t_ Mpm_Man_t;
+struct Mpm_Man_t_
+{
+    Mig_Man_t *      pMig;                     // AIG manager
+    Mpm_Par_t *      pPars;                    // mapping parameters
+    // mapping parameters
+    int              nLutSize;                 // LUT size
+    int              nNumCuts;                 // cut count
+    int              nTruWords;                // words in the truth table
+    Mpm_LibLut_t *   pLibLut;                  // LUT library
+    // mapping attributes  
+    int              fMainRun;                 // after preprocessing is finished
+    int              GloRequired;              // global arrival time
+    word             GloArea;                  // total area
+    word             GloEdge;                  // total edge
+    // cut management
+    Mmr_Step_t *     pManCuts;                 // cut memory
+    // temporary cut storage
+    int              nCutStore;                // number of cuts in storage
+    Mpm_Uni_t *      pCutStore[MPM_CUT_MAX+1]; // storage for cuts
+    Mpm_Uni_t        pCutUnits[MPM_CUT_MAX+1]; // cut info units
+    Vec_Ptr_t        vFreeUnits;               // free cut info units
+    Vec_Ptr_t *      vTemp;                    // storage for cuts
+    // cut comparison
+    int (* pCutCmp) (Mpm_Uni_t *, Mpm_Uni_t *);// procedure to compare cuts
+    // fanin cuts/signatures
+    int              nCuts[3];                 // fanin cut counts
+    Mpm_Cut_t *      pCuts[3][MPM_CUT_MAX+1];  // fanin cuts
+    word             pSigns[3][MPM_CUT_MAX+1]; // fanin cut signatures
+    // truth tables
+    Vec_Mem_t *      vTtMem;                   // truth table memory and hash table
+    int              funcCst0;                 // constant 0
+    int              funcVar0;                 // variable 0
+    word             Truth0[(1 << ((MPM_VAR_MAX)-6))];
+    word             Truth1[(1 << ((MPM_VAR_MAX)-6))];
+    word             TruthC[(1 << ((MPM_VAR_MAX)-6))];
+    word             Truth[(1 << ((MPM_VAR_MAX)-6))];
+    // DSD
+    Mpm_Dsd_t *      pDsd6;                    // NPN class information
+    Hsh_IntMan_t *   pHash;                    // maps DSD functions into NPN classes
+    Vec_Int_t *      vConfgRes;                // configurations
+    Vec_Wrd_t *      vPerm6;                   // permutations of DSD classes
+    char             Perm6[720][6];            // permutations
+    Vec_Int_t *      vMap2Perm;                // maps number into its permutation
+    unsigned         uPermMask[3];
+    unsigned         uComplMask[3];
+    Vec_Wec_t *      vNpnConfigs;
+    // mapping attributes
+    Vec_Int_t        vCutBests;                // cut best
+    Vec_Int_t        vCutLists;                // cut list
+    Vec_Int_t        vMigRefs;                 // original references
+    Vec_Int_t        vMapRefs;                 // exact mapping references
+    Vec_Int_t        vEstRefs;                 // estimated mapping references
+    Vec_Int_t        vRequireds;               // required time
+    Vec_Int_t        vTimes;                   // arrival time
+    Vec_Int_t        vAreas;                   // area
+    Vec_Int_t        vEdges;                   // edge
+    int              nCountDsd[600];
+    int              nNonDsd;
+    int              nNoMatch;
+    // statistics
+    int              nCutsMerged;
+    int              nCutsMergedAll;
+    int              nSmallSupp;
+    abctime          timeDerive;
+    abctime          timeMerge;
+    abctime          timeEval;
+    abctime          timeCompare;
+    abctime          timeStore;
+    abctime          timeOther;
+    abctime          timeTotal;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int         Mpm_ObjCutBest( Mpm_Man_t * p, Mig_Obj_t * pObj )              { return Vec_IntEntry(&p->vCutBests, Mig_ObjId(pObj));            }
+static inline void        Mpm_ObjSetCutBest( Mpm_Man_t * p, Mig_Obj_t * pObj, int i )    { Vec_IntWriteEntry(&p->vCutBests, Mig_ObjId(pObj), i);           }
+
+static inline int         Mpm_CutWordNum( int nLeaves )                                  { return ((sizeof(Mpm_Cut_t) + (nLeaves << 2)) >> 3);             }
+static inline Mpm_Cut_t * Mpm_CutFetch( Mpm_Man_t * p, int h )                           { Mpm_Cut_t * pCut = (Mpm_Cut_t *)Mmr_StepEntry( p->pManCuts, h );  assert( Mpm_CutWordNum(pCut->nLeaves) == (h & p->pManCuts->uMask) ); return pCut; }
+static inline Mpm_Cut_t * Mpm_ObjCutBestP( Mpm_Man_t * p, Mig_Obj_t * pObj )             { return Mpm_CutFetch( p, Mpm_ObjCutBest(p, pObj) );              }
+
+static inline int         Mpm_ObjCutList( Mpm_Man_t * p, Mig_Obj_t * pObj )              { return Vec_IntEntry(&p->vCutLists, Mig_ObjId(pObj));            }
+static inline int *       Mpm_ObjCutListP( Mpm_Man_t * p, Mig_Obj_t * pObj )             { return Vec_IntEntryP(&p->vCutLists, Mig_ObjId(pObj));           }
+static inline void        Mpm_ObjSetCutList( Mpm_Man_t * p, Mig_Obj_t * pObj, int i )    { Vec_IntWriteEntry(&p->vCutLists, Mig_ObjId(pObj), i);           }
+
+static inline int         Mpm_CutLeafNum( Mpm_Cut_t * pCut )                             { return pCut->nLeaves;                                           }
+static inline word *      Mpm_CutTruth( Mpm_Man_t * p, int iFunc )                       { return Vec_MemReadEntry(p->vTtMem, iFunc);                      }
+
+static inline int         Mig_ObjMigRefNum( Mpm_Man_t * p, Mig_Obj_t * pObj )            { return Vec_IntEntry(&p->vMigRefs, Mig_ObjId(pObj));             }
+static inline int         Mig_ObjMigRefDec( Mpm_Man_t * p, Mig_Obj_t * pObj )            { return Vec_IntAddToEntry(&p->vMigRefs, Mig_ObjId(pObj), -1);    }
+
+static inline void        Mpm_ManCleanMapRefs( Mpm_Man_t * p )                           { Vec_IntFill( &p->vMapRefs, Mig_ManObjNum(p->pMig), 0 );         }
+static inline int         Mpm_ObjMapRef( Mpm_Man_t * p, Mig_Obj_t * pObj )               { return Vec_IntEntry(&p->vMapRefs, Mig_ObjId(pObj));             }
+static inline void        Mpm_ObjSetMapRef( Mpm_Man_t * p, Mig_Obj_t * pObj, int i )     { Vec_IntWriteEntry(&p->vMapRefs, Mig_ObjId(pObj), i);            }
+ 
+static inline int         Mpm_ObjEstRef( Mpm_Man_t * p, Mig_Obj_t * pObj )               { return Vec_IntEntry(&p->vEstRefs, Mig_ObjId(pObj));             }
+static inline void        Mpm_ObjSetEstRef( Mpm_Man_t * p, Mig_Obj_t * pObj, int i )     { Vec_IntWriteEntry(&p->vEstRefs, Mig_ObjId(pObj), i);            }
+
+static inline void        Mpm_ManCleanRequired( Mpm_Man_t * p )                          { Vec_IntFill(&p->vRequireds,Mig_ManObjNum(p->pMig),ABC_INFINITY);}
+static inline int         Mpm_ObjRequired( Mpm_Man_t * p, Mig_Obj_t * pObj )             { return Vec_IntEntry(&p->vRequireds, Mig_ObjId(pObj));           }
+static inline void        Mpm_ObjSetRequired( Mpm_Man_t * p, Mig_Obj_t * pObj, int i )   { Vec_IntWriteEntry(&p->vRequireds, Mig_ObjId(pObj), i);          }
+
+static inline int         Mpm_ObjTime( Mpm_Man_t * p, Mig_Obj_t * pObj )                 { return Vec_IntEntry(&p->vTimes, Mig_ObjId(pObj));               }
+static inline void        Mpm_ObjSetTime( Mpm_Man_t * p, Mig_Obj_t * pObj, int i )       { Vec_IntWriteEntry(&p->vTimes, Mig_ObjId(pObj), i);              }
+
+static inline int         Mpm_ObjArea( Mpm_Man_t * p, Mig_Obj_t * pObj )                 { return Vec_IntEntry(&p->vAreas, Mig_ObjId(pObj));               }
+static inline void        Mpm_ObjSetArea( Mpm_Man_t * p, Mig_Obj_t * pObj, int i )       { Vec_IntWriteEntry(&p->vAreas, Mig_ObjId(pObj), i);              }
+
+static inline int         Mpm_ObjEdge( Mpm_Man_t * p, Mig_Obj_t * pObj )                 { return Vec_IntEntry(&p->vEdges, Mig_ObjId(pObj));               }
+static inline void        Mpm_ObjSetEdge( Mpm_Man_t * p, Mig_Obj_t * pObj, int i )       { Vec_IntWriteEntry(&p->vEdges, Mig_ObjId(pObj), i);              }
+
+static inline void        Mpm_VarsClear( int * V2P, int * P2V, int nVars )               { int i; for ( i = 0; i < nVars; i++ ) V2P[i] = P2V[i] = i;       }
+static inline void        Mpm_VarsSwap( int * V2P, int * P2V, int iVar, int jVar )       { V2P[P2V[iVar]] = jVar; V2P[P2V[jVar]] = iVar; P2V[iVar] ^= P2V[jVar]; P2V[jVar] ^= P2V[iVar]; P2V[iVar] ^= P2V[jVar];  }
+
+// iterators over object cuts
+#define Mpm_ObjForEachCut( p, pObj, hCut, pCut )                         \
+    for ( hCut = Mpm_ObjCutList(p, pObj); hCut && (pCut = Mpm_CutFetch(p, hCut)); hCut = pCut->hNext )
+#define Mpm_ObjForEachCutSafe( p, pObj, hCut, pCut, hNext )              \
+    for ( hCut = Mpm_ObjCutList(p, pObj); hCut && (pCut = Mpm_CutFetch(p, hCut)) && ((hNext = pCut->hNext), 1); hCut = hNext )
+
+// iterators over cut leaves
+#define Mpm_CutForEachLeafId( pCut, iLeafId, i )                         \
+    for ( i = 0; i < (int)pCut->nLeaves && ((iLeafId = Abc_Lit2Var(pCut->pLeaves[i])), 1); i++ )
+#define Mpm_CutForEachLeafLit( pCut, iLeafLit, i )                         \
+    for ( i = 0; i < (int)pCut->nLeaves && ((iLeafLit = pCut->pLeaves[i]), 1); i++ )
+#define Mpm_CutForEachLeaf( p, pCut, pLeaf, i )                          \
+    for ( i = 0; i < (int)pCut->nLeaves && (pLeaf = Mig_ManObj(p, Abc_Lit2Var(pCut->pLeaves[i]))); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== mpmAbc.c ===========================================================*/
+extern Mig_Man_t *           Mig_ManCreate( void * pGia );
+extern void *                Mpm_ManFromIfLogic( Mpm_Man_t * pMan );
+/*=== mpmMan.c ===========================================================*/
+extern Mpm_Man_t *           Mpm_ManStart( Mig_Man_t * pMig, Mpm_Par_t * pPars );
+extern void                  Mpm_ManStop( Mpm_Man_t * p );
+extern void                  Mpm_ManPrintStatsInit( Mpm_Man_t * p );
+extern void                  Mpm_ManPrintStats( Mpm_Man_t * p );
+/*=== mpmDsd.c ===========================================================*/
+extern void                  Mpm_ManPrintDsdStats( Mpm_Man_t * p );
+extern void                  Mpm_ManPrintPerm( unsigned s );
+extern void                  Mpm_ManPrecomputePerms( Mpm_Man_t * p );
+extern word                  Mpm_CutTruthFromDsd( Mpm_Man_t * pMan, Mpm_Cut_t * pCut, int iDsdLit );
+extern int                   Mpm_CutCheckDsd6( Mpm_Man_t * p, word t );
+extern int                   Mpm_CutComputeDsd6( Mpm_Man_t * p, Mpm_Cut_t * pCut, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, int Type );
+/*=== mpmGates.c ===========================================================*/
+extern Vec_Wec_t *           Mpm_ManFindDsdMatches( Mpm_Man_t * p, void * pScl );
+/*=== mpmLib.c ===========================================================*/
+extern Mpm_LibLut_t *        Mpm_LibLutSetSimple( int nLutSize );
+extern void                  Mpm_LibLutFree( Mpm_LibLut_t * pLib );
+/*=== mpmMap.c ===========================================================*/
+extern void                  Mpm_CutPrint( Mpm_Cut_t * pCut );
+extern void                  Mpm_ManPrepare( Mpm_Man_t * p );
+extern void                  Mpm_ManPerform( Mpm_Man_t * p );
+/*=== mpmTruth.c ===========================================================*/
+extern int                   Mpm_CutComputeTruth( Mpm_Man_t * p, Mpm_Cut_t * pCut, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, int Type );
+
+extern void                  Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars );
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/map/mpm/mpmLib.c b/abc-build/src/map/mpm/mpmLib.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mpm/mpmLib.c
@@ -0,0 +1,74 @@
+/**CFile****************************************************************
+
+  FileName    [mpmLib.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Configurable technology mapper.]
+
+  Synopsis    [DSD manipulation for 6-input functions.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 1, 2013.]
+
+  Revision    [$Id: mpmLib.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mpmInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mpm_LibLut_t * Mpm_LibLutSetSimple( int nLutSize )
+{
+    Mpm_LibLut_t * pLib;
+    int i, k;
+    assert( nLutSize <= MPM_VAR_MAX );
+    pLib = ABC_CALLOC( Mpm_LibLut_t, 1 );
+    pLib->LutMax = nLutSize;
+    for ( i = 1; i <= pLib->LutMax; i++ )
+    {
+        pLib->pLutAreas[i] = MPM_UNIT_AREA;
+        for ( k = 0; k < i; k++ )
+            pLib->pLutDelays[i][k] = MPM_UNIT_TIME;
+    }
+    return pLib;
+}
+void Mpm_LibLutFree( Mpm_LibLut_t * pLib )
+{
+    if ( pLib == NULL )
+        return;
+    ABC_FREE( pLib->pName );
+    ABC_FREE( pLib );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mpm/mpmMan.c b/abc-build/src/map/mpm/mpmMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mpm/mpmMan.c
@@ -0,0 +1,207 @@
+/**CFile****************************************************************
+
+  FileName    [mpm.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Configurable technology mapper.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 1, 2013.]
+
+  Revision    [$Id: mpm.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mpmInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mpm_Man_t * Mpm_ManStart( Mig_Man_t * pMig, Mpm_Par_t * pPars )
+{
+    Mpm_Man_t * p;
+    int i;
+    assert( sizeof(Mpm_Uni_t) % sizeof(word) == 0 );      // aligned info to word boundary
+    assert( pPars->nNumCuts <= MPM_CUT_MAX );
+    assert( !pPars->fUseTruth || pPars->pLib->LutMax <= 16 );
+    assert( !pPars->fUseDsd || pPars->pLib->LutMax <= 6 );
+    Mig_ManSetRefs( pMig );
+    // alloc
+    p = ABC_CALLOC( Mpm_Man_t, 1 );
+    p->pMig      = pMig;
+    p->pPars     = pPars;
+    p->pLibLut   = pPars->pLib;
+    p->nLutSize  = pPars->pLib->LutMax;
+    p->nTruWords = pPars->fUseTruth ? Abc_Truth6WordNum(p->nLutSize) : 0;
+    p->nNumCuts  = pPars->nNumCuts;
+    // cuts
+    assert( Mpm_CutWordNum(32) < 32 ); // using 5 bits for word count
+    p->pManCuts  = Mmr_StepStart( 13, Abc_Base2Log(Mpm_CutWordNum(p->nLutSize) + 1) );
+    Vec_PtrGrow( &p->vFreeUnits, p->nNumCuts + 1 );
+    for ( i = p->nNumCuts; i >= 0; i-- )
+        Vec_PtrPush( &p->vFreeUnits, p->pCutUnits + i );
+    p->vTemp     = Vec_PtrAlloc( 1000 );
+    // mapping attributes
+    Vec_IntFill( &p->vCutBests, Mig_ManObjNum(pMig), 0 );
+    Vec_IntFill( &p->vCutLists, Mig_ManObjNum(pMig), 0 );
+    Vec_IntFill( &p->vMigRefs, Mig_ManObjNum(pMig), 0 );
+    Vec_IntFill( &p->vMapRefs, Mig_ManObjNum(pMig), 0 );
+    Vec_IntFill( &p->vEstRefs, Mig_ManObjNum(pMig), 0 );
+    Vec_IntFill( &p->vRequireds, Mig_ManObjNum(pMig), ABC_INFINITY );
+    Vec_IntFill( &p->vTimes, Mig_ManObjNum(pMig), 0 );
+    Vec_IntFill( &p->vAreas, Mig_ManObjNum(pMig), 0 );
+    Vec_IntFill( &p->vEdges, Mig_ManObjNum(pMig), 0 );
+    // start DSD manager
+    assert( !p->pPars->fUseTruth || !p->pPars->fUseDsd );
+    if ( p->pPars->fUseTruth )
+    { 
+        p->vTtMem = Vec_MemAlloc( p->nTruWords, 12 ); // 32 KB/page for 6-var functions
+        Vec_MemHashAlloc( p->vTtMem, 10000 );
+        p->funcCst0 = Vec_MemHashInsert( p->vTtMem, p->Truth );
+        Abc_TtUnit( p->Truth, p->nTruWords );
+        p->funcVar0 = Vec_MemHashInsert( p->vTtMem, p->Truth );
+    }
+    else if ( p->pPars->fUseDsd )
+    {
+        Mpm_ManPrecomputePerms( p );
+        p->funcVar0 = 1;
+    }
+    // finish
+    p->timeTotal = Abc_Clock();
+    pMig->pMan = p;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mpm_ManStop( Mpm_Man_t * p )
+{
+    if ( p->pPars->fUseTruth && p->pPars->fVeryVerbose )
+    {
+        char * pFileName = "truths.txt";
+        FILE * pFile = fopen( pFileName, "wb" );
+        Vec_MemDump( pFile, p->vTtMem );
+        fclose( pFile );
+        printf( "Dumped %d %d-var truth tables into file \"%s\" (%.2f MB).\n", 
+            Vec_MemEntryNum(p->vTtMem), p->nLutSize, pFileName,
+            (16.0 * p->nTruWords + 1.0) * Vec_MemEntryNum(p->vTtMem) / (1 << 20) );
+    }
+    if ( p->pPars->fUseDsd && p->pPars->fVerbose )
+        Mpm_ManPrintDsdStats( p );
+    if ( p->vTtMem ) 
+    {
+        Vec_MemHashFree( p->vTtMem );
+        Vec_MemFree( p->vTtMem );
+    }
+    if ( p->pHash )
+    {
+        Vec_WrdFree( p->vPerm6 );
+        Vec_IntFree( p->vMap2Perm );
+        Vec_IntFree( p->vConfgRes );
+        Vec_IntFree( p->pHash->vData );
+        Hsh_IntManStop( p->pHash );
+    }
+    Vec_WecFreeP( &p->vNpnConfigs );
+    Vec_PtrFree( p->vTemp );
+    Mmr_StepStop( p->pManCuts );
+    ABC_FREE( p->vFreeUnits.pArray );
+    // mapping attributes
+    ABC_FREE( p->vCutBests.pArray );
+    ABC_FREE( p->vCutLists.pArray );
+    ABC_FREE( p->vMigRefs.pArray );
+    ABC_FREE( p->vMapRefs.pArray );
+    ABC_FREE( p->vEstRefs.pArray );
+    ABC_FREE( p->vRequireds.pArray );
+    ABC_FREE( p->vTimes.pArray );
+    ABC_FREE( p->vAreas.pArray );
+    ABC_FREE( p->vEdges.pArray );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mpm_ManPrintStatsInit( Mpm_Man_t * p )
+{
+    printf( "K = %d.  C = %d.  Cand = %d. XOR = %d. MUX = %d. Choice = %d.  CutMin = %d. Truth = %d. DSD = %d.\n", 
+        p->nLutSize, p->nNumCuts, Mig_ManCandNum(p->pMig), 
+        Mig_ManXorNum(p->pMig), Mig_ManMuxNum(p->pMig), p->pMig->nChoices, 
+        p->pPars->fCutMin, p->pPars->fUseTruth, p->pPars->fUseDsd );
+}
+void Mpm_ManPrintStats( Mpm_Man_t * p )
+{
+    printf( "Memory usage:  Mig = %.2f MB  Map = %.2f MB  Cut = %.2f MB    Total = %.2f MB.  ", 
+        1.0 * Mig_ManObjNum(p->pMig) * sizeof(Mig_Obj_t) / (1 << 20), 
+        1.0 * Mig_ManObjNum(p->pMig) * 48 / (1 << 20), 
+        1.0 * Mmr_StepMemory(p->pManCuts) / (1 << 17), 
+        1.0 * Mig_ManObjNum(p->pMig) * sizeof(Mig_Obj_t) / (1 << 20) + 
+        1.0 * Mig_ManObjNum(p->pMig) * 48 / (1 << 20) +
+        1.0 * Mmr_StepMemory(p->pManCuts) / (1 << 17) );
+    if ( p->timeDerive )
+    {
+        printf( "\n" );
+        p->timeTotal = Abc_Clock() - p->timeTotal;
+        p->timeOther = p->timeTotal - p->timeDerive;
+
+        Abc_Print( 1, "Runtime breakdown:\n" );
+        ABC_PRTP( "Complete cut computation   ", p->timeDerive , p->timeTotal );
+        ABC_PRTP( "- Merging cuts             ", p->timeMerge  , p->timeTotal );
+        ABC_PRTP( "- Evaluting cut parameters ", p->timeEval   , p->timeTotal );
+        ABC_PRTP( "- Checking cut containment ", p->timeCompare, p->timeTotal );
+        ABC_PRTP( "- Adding cuts to storage   ", p->timeStore  , p->timeTotal );
+        ABC_PRTP( "Other                      ", p->timeOther  , p->timeTotal );
+        ABC_PRTP( "TOTAL                      ", p->timeTotal  , p->timeTotal );
+    }
+    else
+        Abc_PrintTime( 1, "Time", Abc_Clock() - p->timeTotal );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mpm/mpmMap.c b/abc-build/src/map/mpm/mpmMap.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mpm/mpmMap.c
@@ -0,0 +1,872 @@
+/**CFile****************************************************************
+
+  FileName    [mpmMap.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Configurable technology mapper.]
+
+  Synopsis    [Mapping algorithm.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 1, 2013.]
+
+  Revision    [$Id: mpmMap.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mpmInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+//#define MIG_RUNTIME
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Cut manipulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Mpm_CutAlloc( Mpm_Man_t * p, int nLeaves, Mpm_Cut_t ** ppCut )  
+{ 
+    int hHandle = Mmr_StepFetch( p->pManCuts, Mpm_CutWordNum(nLeaves) );
+    *ppCut      = (Mpm_Cut_t *)Mmr_StepEntry( p->pManCuts, hHandle );
+    (*ppCut)->nLeaves  = nLeaves;
+    (*ppCut)->hNext    = 0;
+    (*ppCut)->fUseless = 0;
+    (*ppCut)->fCompl   = 0;
+    return hHandle;
+}
+static inline int Mpm_CutCreateZero( Mpm_Man_t * p )  
+{ 
+    Mpm_Cut_t * pCut;
+    int hCut = Mpm_CutAlloc( p, 0, &pCut );
+    pCut->iFunc      = 0; // const0
+    return hCut;
+}
+static inline int Mpm_CutCreateUnit( Mpm_Man_t * p, int Id )  
+{ 
+    Mpm_Cut_t * pCut;
+    int hCut = Mpm_CutAlloc( p, 1, &pCut );
+    pCut->iFunc      = Abc_Var2Lit( p->funcVar0, 0 ); // var
+    pCut->pLeaves[0] = Abc_Var2Lit( Id, 0 );
+    return hCut;
+}
+static inline int Mpm_CutCreate( Mpm_Man_t * p, Mpm_Cut_t * pUni, Mpm_Cut_t ** ppCut )  
+{ 
+    int hCutNew = Mpm_CutAlloc( p, pUni->nLeaves, ppCut );
+    (*ppCut)->iFunc    = pUni->iFunc;
+    (*ppCut)->fCompl   = pUni->fCompl;
+    (*ppCut)->fUseless = pUni->fUseless;
+    (*ppCut)->nLeaves  = pUni->nLeaves;
+    memcpy( (*ppCut)->pLeaves, pUni->pLeaves, sizeof(int) * pUni->nLeaves );
+    return hCutNew;
+}
+static inline int Mpm_CutDup( Mpm_Man_t * p, Mpm_Cut_t * pCut, int fCompl )  
+{ 
+    Mpm_Cut_t * pCutNew;
+    int hCutNew = Mpm_CutAlloc( p, pCut->nLeaves, &pCutNew );
+    pCutNew->iFunc    = Abc_LitNotCond( pCut->iFunc, fCompl );
+    pCutNew->fUseless = pCut->fUseless;
+    pCutNew->nLeaves  = pCut->nLeaves;
+    memcpy( pCutNew->pLeaves, pCut->pLeaves, sizeof(int) * pCut->nLeaves );
+    return hCutNew;
+}
+static inline int Mpm_CutCopySet( Mpm_Man_t * p, Mig_Obj_t * pObj, int fCompl )  
+{
+    Mpm_Cut_t * pCut;
+    int hCut, iList = 0, * pList = &iList;
+    Mpm_ObjForEachCut( p, pObj, hCut, pCut )
+    {
+        *pList = Mpm_CutDup( p, pCut, fCompl );
+        pList = &Mpm_CutFetch( p, *pList )->hNext;
+    }
+    *pList = 0;
+    return iList;
+}
+void Mpm_CutPrint( Mpm_Cut_t * pCut )  
+{ 
+    int i;
+    printf( "%d : { ", pCut->nLeaves );
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        printf( "%d ", pCut->pLeaves[i] );
+    printf( "}\n" );
+}
+static inline void Mpm_CutPrintAll( Mpm_Man_t * p )  
+{ 
+    int i;
+    for ( i = 0; i < p->nCutStore; i++ )
+    {
+        printf( "%2d : ", i );
+        Mpm_CutPrint( &p->pCutStore[i]->pCut );
+    }
+}
+static inline int Mpm_CutFindLeaf( Mpm_Cut_t * pNew, int iObj )
+{
+    int i;
+    for ( i = 0; i < (int)pNew->nLeaves; i++ )
+        if ( Abc_Lit2Var(pNew->pLeaves[i]) == iObj )
+            return i;
+    return i;
+}
+static inline int Mpm_CutIsContained( Mpm_Man_t * p, Mpm_Cut_t * pBase, Mpm_Cut_t * pCut ) // check if pCut is contained pBase
+{
+    int i;
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        if ( Mpm_CutFindLeaf( pBase, Abc_Lit2Var(pCut->pLeaves[i]) ) == (int)pBase->nLeaves )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cut attibutes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Mpm_CutGetArea( Mpm_Man_t * p, Mpm_Cut_t * pCut )  
+{
+    if ( p->pPars->fMap4Cnf )
+        return MPM_UNIT_AREA * p->pDsd6[Abc_Lit2Var(pCut->iFunc)].nClauses;
+    if ( p->pPars->fMap4Aig )
+        return MPM_UNIT_AREA * p->pDsd6[Abc_Lit2Var(pCut->iFunc)].nAnds;
+    if ( p->pPars->fMap4Gates )
+        return MPM_UNIT_AREA * 1;
+    return p->pLibLut->pLutAreas[pCut->nLeaves];
+}
+static inline word Mpm_CutGetSign( Mpm_Cut_t * pCut )  
+{
+    int i, iLeaf;
+    word uSign = 0;
+    Mpm_CutForEachLeafId( pCut, iLeaf, i )
+        uSign |= ((word)1 << (iLeaf & 0x3F));
+    return uSign;
+}
+static inline int Mpm_CutGetArrTime( Mpm_Man_t * p, Mpm_Cut_t * pCut )  
+{
+    int * pmTimes = Vec_IntArray( &p->vTimes );
+    int * pDelays = p->pLibLut->pLutDelays[pCut->nLeaves];
+    int i, iLeaf, ArrTime = 0;
+    Mpm_CutForEachLeafId( pCut, iLeaf, i )
+        ArrTime = Abc_MaxInt( ArrTime, pmTimes[iLeaf] + pDelays[i] );
+    return ArrTime;
+}
+static inline Mpm_Uni_t * Mpm_CutSetupInfo( Mpm_Man_t * p, Mpm_Cut_t * pCut, int ArrTime )  
+{
+    int * pMigRefs = Vec_IntArray( &p->vMigRefs );
+    int * pMapRefs = Vec_IntArray( &p->vMapRefs );
+    int * pEstRefs = Vec_IntArray( &p->vEstRefs );
+    int * pmArea   = Vec_IntArray( &p->vAreas );
+    int * pmEdge   = Vec_IntArray( &p->vEdges );
+    int i, iLeaf;
+    Mpm_Uni_t * pUnit = (Mpm_Uni_t *)Vec_PtrEntryLast(&p->vFreeUnits);
+    assert( &pUnit->pCut == pCut );
+    pUnit->mTime    = ArrTime;
+    pUnit->mArea    = Mpm_CutGetArea( p, pCut );
+    pUnit->mEdge    = MPM_UNIT_EDGE * pCut->nLeaves;
+    pUnit->mAveRefs = 0;
+    pUnit->Cost     = 0;
+    pUnit->uSign    = 0;
+    Mpm_CutForEachLeafId( pCut, iLeaf, i )
+    {
+        if ( p->fMainRun && pMapRefs[iLeaf] == 0 ) // not used in the mapping
+        {
+            pUnit->mArea += pmArea[iLeaf];
+            pUnit->mEdge += pmEdge[iLeaf];
+        }
+        else
+        {
+            assert( pEstRefs[iLeaf] > 0 );
+            pUnit->mArea += MPM_UNIT_REFS * pmArea[iLeaf] / pEstRefs[iLeaf];
+            pUnit->mEdge += MPM_UNIT_REFS * pmEdge[iLeaf] / pEstRefs[iLeaf];
+            pUnit->mAveRefs += p->fMainRun ? pMapRefs[iLeaf] : pMigRefs[iLeaf];
+        }
+        pUnit->uSign |= ((word)1 << (iLeaf & 0x3F));
+    }
+    pUnit->mAveRefs = pUnit->mAveRefs * MPM_UNIT_EDGE / Abc_MaxInt(pCut->nLeaves, 1);
+    assert( pUnit->mTime <= 0x3FFFFFFF );
+    assert( pUnit->mArea <= 0x3FFFFFFF );
+    assert( pUnit->mEdge <= 0x3FFFFFFF );
+    return pUnit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares cut against those present in the store.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mpm_ObjAddCutToStore( Mpm_Man_t * p, Mpm_Cut_t * pCut, int ArrTime )
+{
+    int fEnableContainment = 1;
+    Mpm_Uni_t * pUnit, * pUnitNew;
+    int k, iPivot, last;
+    // create new unit
+#ifdef MIG_RUNTIME
+    abctime clk;
+clk = Abc_Clock();
+#endif
+    pUnitNew = Mpm_CutSetupInfo( p, pCut, ArrTime );
+#ifdef MIG_RUNTIME
+p->timeEval += Abc_Clock() - clk;
+#endif
+    // special case when the cut store is empty
+    if ( p->nCutStore == 0 )
+    {
+        p->pCutStore[p->nCutStore++] = pUnitNew;
+        Vec_PtrPop( &p->vFreeUnits );
+        return 1;
+    }
+    // special case when the cut store is full and last cut is better than new cut
+    if ( p->nCutStore == p->nNumCuts-1 && p->pCutCmp(pUnitNew, p->pCutStore[p->nCutStore-1]) > 0 )
+        return 0;
+
+    // find place of the given cut in the store
+    assert( p->nCutStore <= p->nNumCuts );
+    for ( iPivot = p->nCutStore - 1; iPivot >= 0; iPivot-- )
+        if ( p->pCutCmp(pUnitNew, p->pCutStore[iPivot]) > 0 ) // iPivot-th cut is better than new cut
+            break;
+
+    if ( fEnableContainment )
+    {
+#ifdef MIG_RUNTIME
+clk = Abc_Clock();
+#endif
+        // filter this cut using other cuts
+        for ( k = 0; k <= iPivot; k++ )
+        {
+            pUnit = p->pCutStore[k];
+            if ( pUnitNew->pCut.nLeaves >= pUnit->pCut.nLeaves && 
+                (pUnitNew->uSign & pUnit->uSign) == pUnit->uSign && 
+                 Mpm_CutIsContained(p, &pUnitNew->pCut, &pUnit->pCut) )
+            {
+#ifdef MIG_RUNTIME
+p->timeCompare += Abc_Clock() - clk;
+#endif
+                return 0;
+            }
+        }
+    }
+
+    // special case when the best cut is useless while the new cut is not
+    if ( p->pCutStore[0]->pCut.fUseless && !pUnitNew->pCut.fUseless )
+        iPivot = -1;
+
+    // add the cut to storage
+    assert( pUnitNew == (Mpm_Uni_t *)Vec_PtrEntryLast(&p->vFreeUnits) );
+    Vec_PtrPop( &p->vFreeUnits );
+
+    // insert this cut at location iPivot
+    iPivot++;
+    for ( k = p->nCutStore++; k > iPivot; k-- )
+        p->pCutStore[k] = p->pCutStore[k-1];
+    p->pCutStore[iPivot] = pUnitNew;
+
+    if ( fEnableContainment )
+    {
+        // filter other cuts using this cut
+        for ( k = last = iPivot+1; k < p->nCutStore; k++ )
+        {
+            pUnit = p->pCutStore[k];
+            if ( pUnitNew->pCut.nLeaves <= pUnit->pCut.nLeaves && 
+                (pUnitNew->uSign & pUnit->uSign) == pUnitNew->uSign && 
+                 Mpm_CutIsContained(p, &pUnit->pCut, &pUnitNew->pCut) )
+            {
+                Vec_PtrPush( &p->vFreeUnits, pUnit );
+                continue;
+            }
+            p->pCutStore[last++] = p->pCutStore[k];
+        }
+        p->nCutStore = last;
+#ifdef MIG_RUNTIME
+p->timeCompare += Abc_Clock() - clk;
+#endif
+    }
+
+    // remove the last cut if too many
+    if ( p->nCutStore == p->nNumCuts )
+        Vec_PtrPush( &p->vFreeUnits, p->pCutStore[--p->nCutStore] );
+    assert( p->nCutStore < p->nNumCuts );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cut enumeration.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Mpm_Cut_t * Mpm_ManMergeCuts( Mpm_Man_t * p, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCut2 )
+{
+    Mpm_Cut_t * pTemp, * pCut = &((Mpm_Uni_t *)Vec_PtrEntryLast(&p->vFreeUnits))->pCut;
+    int i, c, iPlace;
+    // base cut
+    memcpy( pCut->pLeaves, pCut0->pLeaves, sizeof(int) * pCut0->nLeaves );
+    pCut->nLeaves = pCut0->nLeaves;
+    // remaining cuts
+    if ( p->pPars->fUseDsd )
+    {
+        for ( c = 1; c < 3; c++ )
+        {
+            pTemp = (c == 1) ? pCut1 : pCut2;
+            if ( pTemp == NULL )
+                break;
+            p->uPermMask[c] = 0x3FFFF; // 18 bits
+            p->uComplMask[c] = 0;     
+            for ( i = 0; i < (int)pTemp->nLeaves; i++ )
+            {
+                iPlace = Mpm_CutFindLeaf( pCut, Abc_Lit2Var(pTemp->pLeaves[i]) );
+                if ( iPlace == (int)pCut->nLeaves )
+                {
+                    if ( (int)pCut->nLeaves == p->nLutSize )
+                        return NULL;
+                    pCut->pLeaves[pCut->nLeaves++] = pTemp->pLeaves[i];
+                }
+                p->uPermMask[c] ^= (((i & 7) ^ 7) << (3*iPlace));
+                if ( pTemp->pLeaves[i] != pCut->pLeaves[iPlace] )
+                    p->uComplMask[c] |= (1 << iPlace);
+            }
+        }
+    }
+    else
+    {
+        for ( c = 1; c < 3; c++ )
+        {
+            pTemp = (c == 1) ? pCut1 : pCut2;
+            if ( pTemp == NULL )
+                break;
+            for ( i = 0; i < (int)pTemp->nLeaves; i++ )
+            {
+                iPlace = Mpm_CutFindLeaf( pCut, Abc_Lit2Var(pTemp->pLeaves[i]) );
+                if ( iPlace == (int)pCut->nLeaves )
+                {
+                    if ( (int)pCut->nLeaves == p->nLutSize )
+                        return NULL;
+                    pCut->pLeaves[pCut->nLeaves++] = pTemp->pLeaves[i];
+                }
+            }
+        }
+    }
+    if ( pCut1 == NULL )
+    {
+        pCut->hNext    = 0;
+        pCut->iFunc    = pCut0->iFunc;
+        pCut->fUseless = pCut0->fUseless;
+        pCut->fCompl   = pCut0->fCompl;
+    }
+    else
+    {
+        pCut->hNext    = 0;
+        pCut->iFunc    = 0;  pCut->iFunc = ~pCut->iFunc;
+        pCut->fUseless = 0;
+        pCut->fCompl   = 0;
+    }
+    p->nCutsMerged++;
+    p->nCutsMergedAll++;
+    if ( p->pPars->fUseTruth )
+        Vec_IntSelectSort( pCut->pLeaves, pCut->nLeaves );
+    return pCut;
+}
+static inline int Mpm_ManExploreNewCut( Mpm_Man_t * p, Mig_Obj_t * pObj, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCut2, int Required )
+{
+    Mpm_Cut_t * pCut;
+    int ArrTime;
+#ifdef MIG_RUNTIME
+abctime clk = clock();
+#endif
+
+    if ( pCut0->nLeaves >= pCut1->nLeaves )
+    {
+        pCut = Mpm_ManMergeCuts( p, pCut0, pCut1, pCut2 );
+#ifdef MIG_RUNTIME
+p->timeMerge += clock() - clk;
+#endif
+        if ( pCut == NULL )
+            return 1;
+        if ( p->pPars->fUseTruth )
+            Mpm_CutComputeTruth( p, pCut, pCut0, pCut1, pCut2, Mig_ObjFaninC0(pObj), Mig_ObjFaninC1(pObj), Mig_ObjFaninC2(pObj), Mig_ObjNodeType(pObj) ); 
+        else if ( p->pPars->fUseDsd )
+        {
+            if ( !Mpm_CutComputeDsd6( p, pCut, pCut0, pCut1, pCut2, Mig_ObjFaninC0(pObj), Mig_ObjFaninC1(pObj), Mig_ObjFaninC2(pObj), Mig_ObjNodeType(pObj) ) )
+                return 1;
+        }
+    }
+    else
+    {
+        pCut = Mpm_ManMergeCuts( p, pCut1, pCut0, pCut2 );
+#ifdef MIG_RUNTIME
+p->timeMerge += clock() - clk;
+#endif
+        if ( pCut == NULL )
+            return 1;
+        if ( p->pPars->fUseTruth )
+            Mpm_CutComputeTruth( p, pCut, pCut1, pCut0, pCut2, Mig_ObjFaninC1(pObj), Mig_ObjFaninC0(pObj), 1 ^ Mig_ObjFaninC2(pObj), Mig_ObjNodeType(pObj) ); 
+        else if ( p->pPars->fUseDsd )
+        {
+            if ( !Mpm_CutComputeDsd6( p, pCut, pCut1, pCut0, pCut2, Mig_ObjFaninC1(pObj), Mig_ObjFaninC0(pObj), 1 ^ Mig_ObjFaninC2(pObj), Mig_ObjNodeType(pObj) ) )
+                return 1;
+        }
+    }
+
+#ifdef MIG_RUNTIME
+clk = clock();
+#endif
+    ArrTime = Mpm_CutGetArrTime( p, pCut );
+#ifdef MIG_RUNTIME
+p->timeEval += clock() - clk;
+#endif
+    if ( p->fMainRun && ArrTime > Required )
+        return 1;
+
+#ifdef MIG_RUNTIME
+clk = Abc_Clock();
+#endif
+    Mpm_ObjAddCutToStore( p, pCut, ArrTime );
+#ifdef MIG_RUNTIME
+p->timeStore += Abc_Clock() - clk;
+#endif
+
+/*
+    // return 0 if const or buffer cut is derived - reset all cuts to contain only one --- does not work
+//    if ( pCut->nLeaves < 2 && p->nCutStore == 1 )
+//        return 0;
+    if ( pCut->nLeaves < 2 ) 
+    {
+        int i;
+        assert( p->nCutStore >= 1 );
+        for ( i = 1; i < p->nCutStore; i++ )
+            Vec_PtrPush( &p->vFreeUnits, p->pCutStore[i] );
+        p->nCutStore = 1;
+        return 0;
+    }
+*/
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Mpm_ObjRecycleCuts( Mpm_Man_t * p, Mig_Obj_t * pObj )
+{
+    Mpm_Cut_t * pCut;
+    int hCut, hNext;
+    Mpm_ObjForEachCutSafe( p, pObj, hCut, pCut, hNext )
+        Mmr_StepRecycle( p->pManCuts, hCut );
+    Mpm_ObjSetCutList( p, pObj, 0 );
+}
+static inline void Mpm_ObjDerefFaninCuts( Mpm_Man_t * p, Mig_Obj_t * pObj )
+{
+    Mig_Obj_t * pFanin;
+    int i;
+    Mig_ObjForEachFanin( pObj, pFanin, i )
+        if ( Mig_ObjIsNode(pFanin) && Mig_ObjMigRefDec(p, pFanin) == 0 )
+            Mpm_ObjRecycleCuts( p, pFanin );
+    pFanin = Mig_ObjSibl(pObj);
+    if ( pFanin && Mig_ObjMigRefDec(p, pFanin) == 0 )
+        Mpm_ObjRecycleCuts( p, pFanin );
+    if ( Mig_ObjMigRefNum(p, pObj) == 0 )
+        Mpm_ObjRecycleCuts( p, pObj );
+}
+static inline void Mpm_ObjCollectFaninsAndSigns( Mpm_Man_t * p, Mig_Obj_t * pObj, int i )
+{
+    Mpm_Cut_t * pCut;
+    int hCut, nCuts = 0;
+    Mpm_ObjForEachCut( p, pObj, hCut, pCut )
+    {
+        p->pCuts[i][nCuts] = pCut;
+        p->pSigns[i][nCuts++] = Mpm_CutGetSign( pCut );
+    }
+    p->nCuts[i] = nCuts;
+}
+static inline void Mpm_ObjPrepareFanins( Mpm_Man_t * p, Mig_Obj_t * pObj )
+{
+    Mig_Obj_t * pFanin;
+    int i;
+    Mig_ObjForEachFanin( pObj, pFanin, i )
+        Mpm_ObjCollectFaninsAndSigns( p, pFanin, i );
+}
+// create storage from cuts at the node
+void Mpm_ObjAddChoiceCutsToStore( Mpm_Man_t * p, Mig_Obj_t * pRoot, Mig_Obj_t * pObj, int ReqTime )
+{
+    Mpm_Cut_t * pCut;
+    int hCut, hNext, ArrTime;
+    int fCompl = Mig_ObjPhase(pRoot) ^ Mig_ObjPhase(pObj);
+    Mpm_ObjForEachCutSafe( p, pObj, hCut, pCut, hNext )
+    {
+        if ( Abc_Lit2Var(pCut->pLeaves[0]) == Mig_ObjId(pObj) )
+            continue;
+        ArrTime = Mpm_CutGetArrTime( p, pCut );
+        if ( ArrTime > ReqTime )
+            continue;
+        pCut->fCompl ^= fCompl;
+        pCut = Mpm_ManMergeCuts( p, pCut, NULL, NULL );
+        Mpm_ObjAddCutToStore( p, pCut, ArrTime );
+    }
+}
+// create cuts at the node from storage
+void Mpm_ObjTranslateCutsFromStore( Mpm_Man_t * p, Mig_Obj_t * pObj )
+{
+    Mpm_Cut_t * pCut = NULL;
+    Mpm_Uni_t * pUnit;
+    int i, *pList = Mpm_ObjCutListP( p, pObj );
+    assert( p->nCutStore > 0 && p->nCutStore <= p->nNumCuts );
+    assert( *pList == 0 );
+    // translate cuts
+    for ( i = 0; i < p->nCutStore; i++ )
+    {
+        pUnit  = p->pCutStore[i];
+        *pList = Mpm_CutCreate( p, &pUnit->pCut, &pCut );
+        pList  = &pCut->hNext;
+        Vec_PtrPush( &p->vFreeUnits, pUnit );
+    }
+    assert( Vec_PtrSize(&p->vFreeUnits) == p->nNumCuts + 1 );
+    if ( p->nCutStore == 1 && pCut->nLeaves < 2 )
+        *pList = 0;
+    else
+        *pList = Mpm_CutCreateUnit( p, Mig_ObjId(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mpm_ManDeriveCuts( Mpm_Man_t * p, Mig_Obj_t * pObj )
+{
+    Mpm_Cut_t * pCut0, * pCut1, * pCut2;
+    int Required = Mpm_ObjRequired( p, pObj );
+    int hCutBest = Mpm_ObjCutBest( p, pObj );
+    int c0, c1, c2;
+#ifdef MIG_RUNTIME
+abctime clk;
+#endif
+
+    assert( Vec_PtrSize( &p->vFreeUnits ) == p->nNumCuts + 1 );
+    assert( Mpm_ObjCutList(p, pObj) == 0 );
+    p->nCutStore = 0;
+    if ( hCutBest > 0 ) // cut list is assigned
+    {
+        Mpm_Cut_t * pCut = Mpm_ObjCutBestP( p, pObj ); 
+        int Times = Mpm_CutGetArrTime( p, pCut );
+        assert( pCut->hNext == 0 );
+        if ( Times > Required )
+            printf( "Arrival time (%d) exceeds required time (%d) at object %d.\n", Times, Required, Mig_ObjId(pObj) );
+        if ( p->fMainRun )
+            Mpm_ObjAddCutToStore( p, Mpm_ManMergeCuts(p, pCut, NULL, NULL), Times );
+        else
+            Mpm_ObjSetTime( p, pObj, Times );
+    }
+    // start storage with choice cuts
+    if ( Mig_ManChoiceNum(p->pMig) && Mig_ObjSiblId(pObj) )
+        Mpm_ObjAddChoiceCutsToStore( p, pObj, Mig_ObjSibl(pObj), Required );
+
+#ifdef MIG_RUNTIME
+clk = Abc_Clock();
+#endif
+    Mpm_ObjPrepareFanins( p, pObj );
+    if ( Mig_ObjIsNode2(pObj) )
+    {
+        // go through cut pairs
+        for ( c0 = 0; c0 < p->nCuts[0] && (pCut0 = p->pCuts[0][c0]); c0++ )
+        for ( c1 = 0; c1 < p->nCuts[1] && (pCut1 = p->pCuts[1][c1]); c1++ )
+            if ( Abc_TtCountOnes(p->pSigns[0][c0] | p->pSigns[1][c1]) <= p->nLutSize )
+                if ( !Mpm_ManExploreNewCut( p, pObj, pCut0, pCut1, NULL, Required ) )
+                    goto finish;
+    }
+    else if ( Mig_ObjIsNode3(pObj) )
+    {
+        // go through cut triples
+        for ( c0 = 0; c0 < p->nCuts[0] && (pCut0 = p->pCuts[0][c0]); c0++ )
+        for ( c1 = 0; c1 < p->nCuts[1] && (pCut1 = p->pCuts[1][c1]); c1++ )
+        for ( c2 = 0; c2 < p->nCuts[2] && (pCut2 = p->pCuts[2][c2]); c2++ )
+            if ( Abc_TtCountOnes(p->pSigns[0][c0] | p->pSigns[1][c1] | p->pSigns[2][c2]) <= p->nLutSize )
+                if ( !Mpm_ManExploreNewCut( p, pObj, pCut0, pCut1, pCut2, Required ) )
+                    goto finish;
+    }
+    else assert( 0 );
+#ifdef MIG_RUNTIME
+p->timeDerive += Abc_Clock() - clk;
+#endif
+
+finish:
+    // save best cut
+    assert( p->nCutStore > 0 );
+    if ( p->pCutStore[0]->mTime <= Required )
+    {
+        Mpm_Cut_t * pCut;
+        if ( hCutBest )
+            Mmr_StepRecycle( p->pManCuts, hCutBest );
+        hCutBest = Mpm_CutCreate( p, &p->pCutStore[0]->pCut, &pCut );
+        Mpm_ObjSetCutBest( p, pObj, hCutBest );
+        Mpm_ObjSetTime( p, pObj, p->pCutStore[0]->mTime );
+        Mpm_ObjSetArea( p, pObj, p->pCutStore[0]->mArea );
+        Mpm_ObjSetEdge( p, pObj, p->pCutStore[0]->mEdge );
+    }
+    else assert( !p->fMainRun );
+    assert( hCutBest > 0 );
+    // transform internal storage into regular cuts
+    Mpm_ObjTranslateCutsFromStore( p, pObj );
+    // dereference fanin cuts and reference node
+    Mpm_ObjDerefFaninCuts( p, pObj );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Required times.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Mpm_ManFindArrivalMax( Mpm_Man_t * p )
+{
+    int * pmTimes = Vec_IntArray( &p->vTimes );
+    Mig_Obj_t * pObj;
+    int i, ArrMax = 0;
+    Mig_ManForEachCo( p->pMig, pObj, i )
+        ArrMax = Abc_MaxInt( ArrMax, pmTimes[ Mig_ObjFaninId0(pObj) ] );
+    return ArrMax;
+}
+static inline void Mpm_ManFinalizeRound( Mpm_Man_t * p )
+{
+    int * pMapRefs  = Vec_IntArray( &p->vMapRefs );
+    int * pRequired = Vec_IntArray( &p->vRequireds );
+    Mig_Obj_t * pObj;
+    Mpm_Cut_t * pCut;
+    int * pDelays;
+    int i, iLeaf;
+    p->GloArea = 0;
+    p->GloEdge = 0;
+    p->GloRequired = Mpm_ManFindArrivalMax(p);
+    if ( p->pPars->DelayTarget != -1 )
+        p->GloRequired = Abc_MaxInt( p->GloRequired, p->pPars->DelayTarget );
+    Mpm_ManCleanMapRefs( p );
+    Mpm_ManCleanRequired( p );
+    Mig_ManForEachObjReverse( p->pMig, pObj )
+    {
+        if ( Mig_ObjIsCo(pObj) )
+        {
+            pRequired[Mig_ObjFaninId0(pObj)] = p->GloRequired;
+            pMapRefs [Mig_ObjFaninId0(pObj)]++;
+        }
+        else if ( Mig_ObjIsNode(pObj) )
+        {
+            int Required = pRequired[Mig_ObjId(pObj)];
+            assert( Required > 0 );
+            if ( pMapRefs[Mig_ObjId(pObj)] > 0 )
+            {
+                pCut = Mpm_ObjCutBestP( p, pObj );
+                pDelays = p->pLibLut->pLutDelays[pCut->nLeaves];
+                Mpm_CutForEachLeafId( pCut, iLeaf, i )
+                {
+                    pRequired[iLeaf] = Abc_MinInt( pRequired[iLeaf], Required - pDelays[i] );
+                    pMapRefs [iLeaf]++;
+                }
+                p->GloArea += Mpm_CutGetArea( p, pCut );
+                p->GloEdge += pCut->nLeaves;
+            }
+        }
+        else if ( Mig_ObjIsBuf(pObj) )
+        {
+        }
+    }
+    p->GloArea /= MPM_UNIT_AREA;
+}
+static inline void Mpm_ManComputeEstRefs( Mpm_Man_t * p )
+{
+    int * pMapRefs  = Vec_IntArray( &p->vMapRefs );
+    int * pEstRefs  = Vec_IntArray( &p->vEstRefs );
+    int i;
+    assert( p->fMainRun );
+//  pObj->EstRefs = (float)((2.0 * pObj->EstRefs + pObj->nRefs) / 3.0);
+    for ( i = 0; i < Mig_ManObjNum(p->pMig); i++ )
+        pEstRefs[i] = (1 * pEstRefs[i] + MPM_UNIT_REFS * pMapRefs[i]) / 2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cut comparison.]
+
+  Description [Returns positive number if new one is better than old one.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mpm_CutCompareDelay( Mpm_Uni_t * pOld, Mpm_Uni_t * pNew )
+{
+    if ( pOld->mTime        != pNew->mTime         ) return pOld->mTime        - pNew->mTime;
+    if ( pOld->pCut.nLeaves != pNew->pCut.nLeaves  ) return pOld->pCut.nLeaves - pNew->pCut.nLeaves;
+    if ( pOld->mArea        != pNew->mArea         ) return pOld->mArea        - pNew->mArea;
+    if ( pOld->mEdge        != pNew->mEdge         ) return pOld->mEdge        - pNew->mEdge;
+    return 0;
+}
+int Mpm_CutCompareDelay2( Mpm_Uni_t * pOld, Mpm_Uni_t * pNew )
+{
+    if ( pOld->mTime        != pNew->mTime         ) return pOld->mTime        - pNew->mTime;
+    if ( pOld->mArea        != pNew->mArea         ) return pOld->mArea        - pNew->mArea;
+    if ( pOld->mEdge        != pNew->mEdge         ) return pOld->mEdge        - pNew->mEdge;
+    if ( pOld->pCut.nLeaves != pNew->pCut.nLeaves  ) return pOld->pCut.nLeaves - pNew->pCut.nLeaves;
+    return 0;
+}
+int Mpm_CutCompareArea( Mpm_Uni_t * pOld, Mpm_Uni_t * pNew )
+{
+    if ( pOld->mArea        != pNew->mArea         ) return pOld->mArea        - pNew->mArea;
+    if ( pOld->pCut.nLeaves != pNew->pCut.nLeaves  ) return pOld->pCut.nLeaves - pNew->pCut.nLeaves;
+    if ( pOld->mEdge        != pNew->mEdge         ) return pOld->mEdge        - pNew->mEdge;
+    if ( pOld->mAveRefs     != pNew->mAveRefs      ) return pOld->mAveRefs     - pNew->mAveRefs;
+    if ( pOld->mTime        != pNew->mTime         ) return pOld->mTime        - pNew->mTime;
+    return 0;
+}
+int Mpm_CutCompareArea2( Mpm_Uni_t * pOld, Mpm_Uni_t * pNew )
+{
+    if ( pOld->mArea        != pNew->mArea         ) return pOld->mArea        - pNew->mArea;
+    if ( pOld->mEdge        != pNew->mEdge         ) return pOld->mEdge        - pNew->mEdge;
+    if ( pOld->mAveRefs     != pNew->mAveRefs      ) return pOld->mAveRefs     - pNew->mAveRefs;
+    if ( pOld->pCut.nLeaves != pNew->pCut.nLeaves  ) return pOld->pCut.nLeaves - pNew->pCut.nLeaves;
+    if ( pOld->mTime        != pNew->mTime         ) return pOld->mTime        - pNew->mTime;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Technology mapping experiment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mpm_ManPrepare( Mpm_Man_t * p )
+{
+    Mig_Obj_t * pObj;
+    int i, hCut;
+    Mig_ManForEachCi( p->pMig, pObj, i )
+    {
+        hCut = Mpm_CutCreateUnit( p, Mig_ObjId(pObj) );
+        Mpm_ObjSetCutBest( p, pObj, hCut );
+        Mpm_ObjSetCutList( p, pObj, hCut );
+    }
+    Mig_ManForEachCand( p->pMig, pObj )
+        Mpm_ObjSetEstRef( p, pObj, MPM_UNIT_REFS * Mig_ObjRefNum(pObj) );
+}
+void Mpm_ManPerformRound( Mpm_Man_t * p )
+{
+    Mig_Obj_t * pObj;
+    abctime clk = Abc_Clock();
+    int i;
+    // copy references
+    assert( Vec_IntSize(&p->vMigRefs) == Vec_IntSize(&p->pMig->vRefs) );
+    memcpy( Vec_IntArray(&p->vMigRefs), Vec_IntArray(&p->pMig->vRefs), sizeof(int) * Mig_ManObjNum(p->pMig) );
+    Mig_ManForEachCo( p->pMig, pObj, i )
+        Mig_ObjMigRefDec( p, Mig_ObjFanin0(pObj) );
+    // derive cuts
+    p->nCutsMerged = 0;
+    Mig_ManForEachNode( p->pMig, pObj )
+        Mpm_ManDeriveCuts( p, pObj );
+    assert( Mig_ManCandNum(p->pMig) == p->pManCuts->nEntries );
+    Mpm_ManFinalizeRound( p );
+    // report results
+    if ( p->pPars->fVerbose )
+    {
+    printf( "Del =%5d.  Ar =%8d.  Edge =%8d.  Cut =%10d. Max =%8d.  Tru =%8d. Small =%6d. ", 
+        p->GloRequired, (int)p->GloArea, (int)p->GloEdge, 
+        p->nCutsMerged, p->pManCuts->nEntriesMax, 
+        p->vTtMem ? p->vTtMem->nEntries : 0, p->nSmallSupp );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+}
+void Mpm_ManPerform( Mpm_Man_t * p )
+{
+    if ( p->pPars->fMap4Cnf )
+    {
+        p->pCutCmp = Mpm_CutCompareArea;
+        Mpm_ManPerformRound( p );   
+    }
+    else
+    {
+        p->pCutCmp = Mpm_CutCompareDelay;
+        Mpm_ManPerformRound( p );
+        if ( p->pPars->fOneRound )
+            return;
+    
+        p->pCutCmp = Mpm_CutCompareDelay2;
+        Mpm_ManPerformRound( p );
+    
+        p->pCutCmp = Mpm_CutCompareArea;
+        Mpm_ManPerformRound( p );   
+
+        p->fMainRun = 1;
+
+        p->pCutCmp = Mpm_CutCompareArea;
+        Mpm_ManComputeEstRefs( p );
+        Mpm_ManPerformRound( p );
+
+        p->pCutCmp = Mpm_CutCompareArea2;
+        Mpm_ManComputeEstRefs( p );
+        Mpm_ManPerformRound( p );
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mpm/mpmMig.c b/abc-build/src/map/mpm/mpmMig.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mpm/mpmMig.c
@@ -0,0 +1,204 @@
+/**CFile****************************************************************
+
+  FileName    [mpmMig.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Configurable technology mapper.]
+
+  Synopsis    [Subject graph data structure.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 1, 2013.]
+
+  Revision    [$Id: mpmMig.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mpmInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mig_Man_t * Mig_ManStart()
+{
+    Mig_Man_t * p;
+    assert( sizeof(Mig_Obj_t) >= 16 );
+    assert( (1 << MIG_BASE) == MIG_MASK + 1 );
+    p = ABC_CALLOC( Mig_Man_t, 1 );
+    Vec_IntGrow( &p->vCis, 1024 );
+    Vec_IntGrow( &p->vCos, 1024 );
+    Mig_ManAppendObj( p ); // const0
+    return p;
+}
+void Mig_ManStop( Mig_Man_t * p )
+{
+    if ( 0 )
+    printf( "Subject graph uses %d pages of %d objects with %d entries. Total memory = %.2f MB.\n", 
+        Vec_PtrSize(&p->vPages), MIG_MASK + 1, p->nObjs,
+        1.0 * Vec_PtrSize(&p->vPages) * (MIG_MASK + 1) * 16 / (1 << 20) );
+    // attributes
+    ABC_FREE( p->vTravIds.pArray );
+    ABC_FREE( p->vCopies.pArray );
+    ABC_FREE( p->vLevels.pArray );
+    ABC_FREE( p->vRefs.pArray );
+    ABC_FREE( p->vSibls.pArray );
+    // pages
+    Vec_PtrForEachEntry( Mig_Obj_t *, &p->vPages, p->pPage, p->iPage )
+        --p->pPage, ABC_FREE( p->pPage );
+    // objects
+    ABC_FREE( p->vPages.pArray );
+    ABC_FREE( p->vCis.pArray );
+    ABC_FREE( p->vCos.pArray );
+    ABC_FREE( p->pName );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mig_ManTypeNum( Mig_Man_t * p, int Type )
+{
+    Mig_Obj_t * pObj;
+    int Counter = 0;
+    Mig_ManForEachNode( p, pObj )
+        Counter += (Mig_ObjNodeType(pObj) == Type);
+    return Counter;
+}
+int Mig_ManAndNum( Mig_Man_t * p )
+{
+    return Mig_ManTypeNum(p, 1);
+}
+int Mig_ManXorNum( Mig_Man_t * p )
+{
+    return Mig_ManTypeNum(p, 2);
+}
+int Mig_ManMuxNum( Mig_Man_t * p )
+{
+    return Mig_ManTypeNum(p, 3);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mig_ManSetRefs( Mig_Man_t * p )
+{
+    Mig_Obj_t * pObj;
+    int i, iFanin;
+    // increment references
+    Vec_IntFill( &p->vRefs, Mig_ManObjNum(p), 0 );
+    Mig_ManForEachObj( p, pObj )
+    {
+        Mig_ObjForEachFaninId( pObj, iFanin, i )
+            Vec_IntAddToEntry( &p->vRefs, iFanin, 1 );
+        if ( Mig_ObjSiblId(pObj) )
+            Vec_IntAddToEntry( &p->vRefs, Mig_ObjSiblId(pObj), 1 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mig_ManSuppSize_rec( Mig_Obj_t * pObj )
+{
+    if ( pObj == NULL )
+        return 0;
+    if ( Mig_ObjIsTravIdCurrent(pObj) )
+        return 0;
+    Mig_ObjSetTravIdCurrent(pObj);
+    if ( Mig_ObjIsCi(pObj) )
+        return 1;
+    assert( Mig_ObjIsNode(pObj) );
+    return Mig_ManSuppSize_rec( Mig_ObjFanin0(pObj) ) +
+           Mig_ManSuppSize_rec( Mig_ObjFanin1(pObj) ) +
+           Mig_ManSuppSize_rec( Mig_ObjFanin2(pObj) );
+}
+int Mig_ManSuppSize2_rec( Mig_Man_t * p, int iObj )
+{
+    Mig_Obj_t * pObj;
+    if ( iObj == MIG_NONE )
+        return 0;
+    if ( Mig_ObjIsTravIdCurrentId(p, iObj) )
+        return 0;
+    Mig_ObjSetTravIdCurrentId(p, iObj);
+    pObj = Mig_ManObj( p, iObj );
+    if ( Mig_ObjIsCi(pObj) )
+        return 1;
+    assert( Mig_ObjIsNode(pObj) );
+    return Mig_ManSuppSize2_rec( p, Mig_ObjFaninId0(pObj) ) +
+           Mig_ManSuppSize2_rec( p, Mig_ObjFaninId1(pObj) ) +
+           Mig_ManSuppSize2_rec( p, Mig_ObjFaninId2(pObj) );
+}
+int Mig_ManSuppSizeOne( Mig_Obj_t * pObj )
+{
+    Mig_ObjIncrementTravId( pObj );
+//    return Mig_ManSuppSize_rec( pObj );
+    return Mig_ManSuppSize2_rec( Mig_ObjMan(pObj), Mig_ObjId(pObj) );
+}
+int Mig_ManSuppSizeTest( Mig_Man_t * p )
+{
+    Mig_Obj_t * pObj;
+    int Counter = 0;
+    abctime clk = Abc_Clock();
+    Mig_ManForEachObj( p, pObj )
+        if ( Mig_ObjIsNode(pObj) )
+            Counter += (Mig_ManSuppSizeOne(pObj) <= 16);
+    printf( "Nodes with small support %d (out of %d)\n", Counter, Mig_ManNodeNum(p) );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return Counter;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mpm/mpmMig.h b/abc-build/src/map/mpm/mpmMig.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mpm/mpmMig.h
@@ -0,0 +1,358 @@
+/**CFile****************************************************************
+
+  FileName    [mpmMig.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Configurable technology mapper.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 1, 2013.]
+
+  Revision    [$Id: mpmMig.h,v 1.00 2013/06/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__map__mpm__mig__h
+#define ABC__map__mpm__mig__h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "misc/vec/vec.h"
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+#define MIG_NONE 0x7FFFFFFF
+//#define MIG_MASK 0x0000FFFF
+//#define MIG_BASE 16
+#define MIG_MASK 0x0000FFF
+#define MIG_BASE 12
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Mig_Fan_t_ Mig_Fan_t;
+struct Mig_Fan_t_
+{
+    unsigned       fCompl :  1;  // the complemented attribute
+    unsigned       Id     : 31;  // fanin ID
+};
+
+typedef struct Mig_Obj_t_ Mig_Obj_t;
+struct Mig_Obj_t_
+{
+    Mig_Fan_t      pFans[4];     // fanins
+};
+
+typedef struct Mig_Man_t_ Mig_Man_t;
+struct Mig_Man_t_
+{
+    char *         pName;        // name
+    int            nObjs;        // number of objects
+    int            nRegs;        // number of flops
+    int            nChoices;     // number of choices
+    Vec_Ptr_t      vPages;       // memory pages
+    Vec_Int_t      vCis;         // CI IDs
+    Vec_Int_t      vCos;         // CO IDs
+    // object iterator
+    Mig_Obj_t *    pPage;        // current page
+    int            iPage;        // current page index
+    // attributes
+    int            nTravIds;     // traversal ID counter
+    Vec_Int_t      vTravIds;     // traversal IDs
+    Vec_Int_t      vLevels;      // levels
+    Vec_Int_t      vSibls;       // choice nodes
+    Vec_Int_t      vRefs;        // ref counters
+    Vec_Int_t      vCopies;      // copies
+    void *         pMan;         // mapping manager
+};
+
+/*
+    Usage of fanin atrributes
+    --------------------------------------------------------------------------------------------------------------
+       Const0  Terminal    CI      CO     Buf     Node    Node2   Node3   And2    XOR2    MUX     MAJ    Sentinel
+    --------------------------------------------------------------------------------------------------------------
+    0    -     -/fanin0    -     fanin0  fanin0  fanin0  fanin0  fanin0  fanin0  fanin1  fanin0  fanin1     -
+    1    -        -        -       -       -     fanin1  fanin1  fanin1  fanin1  fanin0  fanin1  fanin0     -
+    2    -      CIO ID   CIO ID  CIO ID    -    -/fanin2    -    fanin2    -       -     fanin2  fanin2     -
+    3    0        ID       ID      ID      ID      ID      ID      ID      ID      ID      ID      ID       -
+    --------------------------------------------------------------------------------------------------------------
+
+    One memory page contain 2^MIG_BASE+2 16-byte objects.
+    - the first object contains the pointer to the manager (8 bytes)
+    - the next 2^MIG_BASE are potentially used as objects
+    - the last object is a sentinel to signal the end of the page
+*/
+
+static inline int          Mig_IdPage( int v )                 { return v >> MIG_BASE;                                                      }
+static inline int          Mig_IdCell( int v )                 { return v & MIG_MASK;                                                       }
+
+static inline char *       Mig_ManName( Mig_Man_t * p )        { return p->pName;                                                           }
+static inline int          Mig_ManCiNum( Mig_Man_t * p )       { return Vec_IntSize(&p->vCis);                                              }
+static inline int          Mig_ManCoNum( Mig_Man_t * p )       { return Vec_IntSize(&p->vCos);                                              }
+static inline int          Mig_ManPiNum( Mig_Man_t * p )       { return Vec_IntSize(&p->vCis) - p->nRegs;                                   }
+static inline int          Mig_ManPoNum( Mig_Man_t * p )       { return Vec_IntSize(&p->vCos) - p->nRegs;                                   }
+static inline int          Mig_ManRegNum( Mig_Man_t * p )      { return p->nRegs;                                                           }
+static inline int          Mig_ManObjNum( Mig_Man_t * p )      { return p->nObjs;                                                           }
+static inline int          Mig_ManNodeNum( Mig_Man_t * p )     { return p->nObjs - Vec_IntSize(&p->vCis) - Vec_IntSize(&p->vCos) - 1;       }
+static inline int          Mig_ManCandNum( Mig_Man_t * p )     { return Mig_ManCiNum(p) + Mig_ManNodeNum(p);                                }
+static inline int          Mig_ManChoiceNum( Mig_Man_t * p )   { return p->nChoices;                                                        }
+static inline void         Mig_ManSetRegNum( Mig_Man_t * p, int v )   { p->nRegs = v;                                                       }
+
+static inline Mig_Obj_t *  Mig_ManPage( Mig_Man_t * p, int v ) { return (Mig_Obj_t *)Vec_PtrEntry(&p->vPages, Mig_IdPage(v));               }
+static inline Mig_Obj_t *  Mig_ManObj( Mig_Man_t * p, int v )  { assert(v >= 0 && v < p->nObjs);  return Mig_ManPage(p, v) + Mig_IdCell(v); }
+static inline Mig_Obj_t *  Mig_ManCi( Mig_Man_t * p, int v )   { return Mig_ManObj( p, Vec_IntEntry(&p->vCis,v) );                          }
+static inline Mig_Obj_t *  Mig_ManCo( Mig_Man_t * p, int v )   { return Mig_ManObj( p, Vec_IntEntry(&p->vCos,v) );                          }
+static inline Mig_Obj_t *  Mig_ManPi( Mig_Man_t * p, int v )   { assert( v < Mig_ManPiNum(p) );  return Mig_ManCi( p, v );                  }
+static inline Mig_Obj_t *  Mig_ManPo( Mig_Man_t * p, int v )   { assert( v < Mig_ManPoNum(p) );  return Mig_ManCo( p, v );                  }
+static inline Mig_Obj_t *  Mig_ManRo( Mig_Man_t * p, int v )   { assert( v < Mig_ManRegNum(p) ); return Mig_ManCi( p, Mig_ManPiNum(p)+v );  }
+static inline Mig_Obj_t *  Mig_ManRi( Mig_Man_t * p, int v )   { assert( v < Mig_ManRegNum(p) ); return Mig_ManCo( p, Mig_ManPoNum(p)+v );  }
+static inline Mig_Obj_t *  Mig_ManConst0( Mig_Man_t * p )      { return Mig_ManObj(p, 0);                                                   }
+
+static inline int          Mig_FanCompl( Mig_Obj_t * p, int i )                { return p->pFans[i].fCompl;                                 }
+static inline int          Mig_FanId( Mig_Obj_t * p, int i )                   { return p->pFans[i].Id;                                     }
+static inline int          Mig_FanIsNone( Mig_Obj_t * p, int i )               { return p->pFans[i].Id == MIG_NONE;                         }
+static inline int          Mig_FanSetCompl( Mig_Obj_t * p, int i, int v )      { assert( !(v >> 1) ); return p->pFans[i].fCompl = v;        }
+static inline int          Mig_FanSetId( Mig_Obj_t * p, int i, int v )         { assert(v >= 0 && v < MIG_NONE); return p->pFans[i].Id = v; }
+
+static inline int          Mig_ObjIsNone( Mig_Obj_t * p )                      { return Mig_FanIsNone( p, 3 );                              }
+static inline int          Mig_ObjIsConst0( Mig_Obj_t * p )                    { return Mig_FanId( p, 3 ) == 0;                             } 
+static inline int          Mig_ObjIsTerm( Mig_Obj_t * p )                      { return Mig_FanIsNone( p, 1 ) && !Mig_FanIsNone( p, 2 );    }
+static inline int          Mig_ObjIsCi( Mig_Obj_t * p )                        { return Mig_ObjIsTerm(p) &&  Mig_FanIsNone( p, 0 );         } 
+static inline int          Mig_ObjIsCo( Mig_Obj_t * p )                        { return Mig_ObjIsTerm(p) && !Mig_FanIsNone( p, 0 );         } 
+static inline int          Mig_ObjIsBuf( Mig_Obj_t * p )                       { return Mig_FanIsNone( p, 1 ) && Mig_FanIsNone( p, 2 ) && !Mig_FanIsNone( p, 0 );     } 
+static inline int          Mig_ObjIsNode( Mig_Obj_t * p )                      { return!Mig_FanIsNone( p, 1 );                              } 
+static inline int          Mig_ObjIsNode2( Mig_Obj_t * p )                     { return Mig_ObjIsNode( p ) &&  Mig_FanIsNone( p, 2 );       } 
+static inline int          Mig_ObjIsNode3( Mig_Obj_t * p )                     { return Mig_ObjIsNode( p ) && !Mig_FanIsNone( p, 2 );       } 
+static inline int          Mig_ObjIsAnd( Mig_Obj_t * p )                       { return Mig_ObjIsNode2( p ) && Mig_FanId(p, 0) < Mig_FanId(p, 1); } 
+static inline int          Mig_ObjIsXor( Mig_Obj_t * p )                       { return Mig_ObjIsNode2( p ) && Mig_FanId(p, 0) > Mig_FanId(p, 1); } 
+static inline int          Mig_ObjIsMux( Mig_Obj_t * p )                       { return Mig_ObjIsNode3( p );                                } 
+static inline int          Mig_ObjIsCand( Mig_Obj_t * p )                      { return Mig_ObjIsNode(p) || Mig_ObjIsCi(p);                 } 
+static inline int          Mig_ObjNodeType( Mig_Obj_t * p )                    { return Mig_ObjIsAnd(p) ? 1 : (Mig_ObjIsXor(p) ? 2 : 3);    } 
+
+static inline int          Mig_ObjId( Mig_Obj_t * p )                          { return Mig_FanId( p, 3 );                                  }
+static inline void         Mig_ObjSetId( Mig_Obj_t * p, int v )                { Mig_FanSetId( p, 3, v );                                   }
+static inline int          Mig_ObjCioId( Mig_Obj_t * p )                       { assert( Mig_ObjIsTerm(p) ); return Mig_FanId( p, 2 );      }
+static inline void         Mig_ObjSetCioId( Mig_Obj_t * p, int v )             { assert( Mig_FanIsNone(p, 1) ); Mig_FanSetId( p, 2, v );    }
+static inline int          Mig_ObjPhase( Mig_Obj_t * p )                       { return Mig_FanCompl( p, 3 );                               }
+static inline void         Mig_ObjSetPhase( Mig_Obj_t * p, int v )             { Mig_FanSetCompl( p, 3, v );                                }
+
+static inline Mig_Man_t *  Mig_ObjMan( Mig_Obj_t * p )                         { return *((Mig_Man_t**)(p - Mig_IdCell(Mig_ObjId(p)) - 1)); }
+//static inline Mig_Obj_t ** Mig_ObjPageP( Mig_Obj_t * p )                       { return *((Mig_Obj_t***)(p - Mig_IdCell(Mig_ObjId(p))) - 1);} 
+static inline Mig_Obj_t *  Mig_ObjObj( Mig_Obj_t * p, int i )                  { return Mig_ManObj( Mig_ObjMan(p), i );                     } 
+
+static inline int          Mig_ManIdToCioId( Mig_Man_t * p, int Id )           { return Mig_ObjCioId( Mig_ManObj(p, Id) );                  }
+static inline int          Mig_ManCiIdToId( Mig_Man_t * p, int CiId )          { return Mig_ObjId( Mig_ManCi(p, CiId) );                    }
+static inline int          Mig_ManCoIdToId( Mig_Man_t * p, int CoId )          { return Mig_ObjId( Mig_ManCo(p, CoId) );                    }
+
+static inline int          Mig_ObjIsPi( Mig_Obj_t * p )                        { return Mig_ObjIsCi(p) && Mig_ObjCioId(p) < Mig_ManPiNum(Mig_ObjMan(p));   } 
+static inline int          Mig_ObjIsPo( Mig_Obj_t * p )                        { return Mig_ObjIsCo(p) && Mig_ObjCioId(p) < Mig_ManPoNum(Mig_ObjMan(p));   } 
+static inline int          Mig_ObjIsRo( Mig_Obj_t * p )                        { return Mig_ObjIsCi(p) && Mig_ObjCioId(p) >= Mig_ManPiNum(Mig_ObjMan(p));  } 
+static inline int          Mig_ObjIsRi( Mig_Obj_t * p )                        { return Mig_ObjIsCo(p) && Mig_ObjCioId(p) >= Mig_ManPoNum(Mig_ObjMan(p));  } 
+
+static inline Mig_Obj_t *  Mig_ObjRoToRi( Mig_Obj_t * p )                      { Mig_Man_t * pMan = Mig_ObjMan(p); assert( Mig_ObjIsRo(p) ); return Mig_ManCo(pMan, Mig_ManCoNum(pMan) - Mig_ManCiNum(pMan) + Mig_ObjCioId(p)); } 
+static inline Mig_Obj_t *  Mig_ObjRiToRo( Mig_Obj_t * p )                      { Mig_Man_t * pMan = Mig_ObjMan(p); assert( Mig_ObjIsRi(p) ); return Mig_ManCi(pMan, Mig_ManCiNum(pMan) - Mig_ManCoNum(pMan) + Mig_ObjCioId(p)); } 
+
+static inline int          Mig_ObjHasFanin( Mig_Obj_t * p, int i )             { return i < 3 && Mig_FanId(p, i) != MIG_NONE;               }
+static inline int          Mig_ObjFaninId( Mig_Obj_t * p, int i )              { assert( i < 3 && Mig_FanId(p, i) < Mig_ObjId(p) ); return Mig_FanId( p, i );  }
+static inline int          Mig_ObjFaninId0( Mig_Obj_t * p )                    { return Mig_FanId( p, 0 );                                  }
+static inline int          Mig_ObjFaninId1( Mig_Obj_t * p )                    { return Mig_FanId( p, 1 );                                  }
+static inline int          Mig_ObjFaninId2( Mig_Obj_t * p )                    { return Mig_FanId( p, 2 );                                  }
+static inline Mig_Obj_t *  Mig_ObjFanin( Mig_Obj_t * p, int i )                { return Mig_ManObj( Mig_ObjMan(p), Mig_ObjFaninId(p, i) );    }
+//static inline Mig_Obj_t *  Mig_ObjFanin( Mig_Obj_t * p, int i )                { return Mig_ObjPageP(p)[Mig_IdPage(Mig_ObjFaninId(p, i))] + Mig_IdCell(Mig_ObjFaninId(p, i));    }
+static inline Mig_Obj_t *  Mig_ObjFanin0( Mig_Obj_t * p )                      { return Mig_FanIsNone(p, 0) ? NULL: Mig_ObjFanin(p, 0);     }
+static inline Mig_Obj_t *  Mig_ObjFanin1( Mig_Obj_t * p )                      { return Mig_FanIsNone(p, 1) ? NULL: Mig_ObjFanin(p, 1);     }
+static inline Mig_Obj_t *  Mig_ObjFanin2( Mig_Obj_t * p )                      { return Mig_FanIsNone(p, 2) ? NULL: Mig_ObjFanin(p, 2);     }
+static inline int          Mig_ObjFaninC( Mig_Obj_t * p, int i )               { assert( i < 3 ); return Mig_FanCompl(p, i);                }
+static inline int          Mig_ObjFaninC0( Mig_Obj_t * p )                     { return Mig_FanCompl(p, 0);                                 }
+static inline int          Mig_ObjFaninC1( Mig_Obj_t * p )                     { return Mig_FanCompl(p, 1);                                 }
+static inline int          Mig_ObjFaninC2( Mig_Obj_t * p )                     { return Mig_FanCompl(p, 2);                                 }
+static inline int          Mig_ObjFaninLit( Mig_Obj_t * p, int i )             { return Abc_Var2Lit( Mig_FanId(p, i), Mig_FanCompl(p, i) ); }
+static inline void         Mig_ObjFlipFaninC( Mig_Obj_t * p, int i )           { Mig_FanSetCompl( p, i, !Mig_FanCompl(p, i) );              }
+static inline int          Mig_ObjWhatFanin( Mig_Obj_t * p, int i )            { if (Mig_FanId(p, 0) == i) return 0; if (Mig_FanId(p, 1) == i) return 1; if (Mig_FanId(p, 2) == i) return 2; return -1;           }
+static inline void         Mig_ObjSetFaninLit( Mig_Obj_t * p, int i, int l )   { assert( l >= 0 && (l >> 1) < Mig_ObjId(p) ); Mig_FanSetId(p, i, Abc_Lit2Var(l)); Mig_FanSetCompl(p, i, Abc_LitIsCompl(l));       }
+
+static inline int          Mig_ObjSiblId( Mig_Obj_t * p )                      { return Vec_IntSize(&Mig_ObjMan(p)->vSibls) == 0 ? 0: Vec_IntEntry(&Mig_ObjMan(p)->vSibls, Mig_ObjId(p));    }
+static inline void         Mig_ObjSetSiblId( Mig_Obj_t * p, int s )            { assert( s > 0 && Mig_ObjId(p) > s ); Vec_IntWriteEntry( &Mig_ObjMan(p)->vSibls, Mig_ObjId(p), s );          }
+static inline Mig_Obj_t *  Mig_ObjSibl( Mig_Obj_t * p )                        { return Mig_ObjSiblId(p) == 0 ? NULL: Mig_ObjObj(p, Mig_ObjSiblId(p));  }
+static inline int          Mig_ObjRefNum( Mig_Obj_t * p )                      { return Vec_IntEntry(&Mig_ObjMan(p)->vRefs, Mig_ObjId(p));              }
+
+static inline void         Mig_ManCleanCopy( Mig_Man_t * p )                   { if ( p->vCopies.pArray == NULL ) Vec_IntFill( &p->vCopies, Mig_ManObjNum(p), -1 );              }
+static inline int          Mig_ObjCopy( Mig_Obj_t * p )                        { return Vec_IntSize(&Mig_ObjMan(p)->vCopies) == 0 ? -1: Vec_IntEntry(&Mig_ObjMan(p)->vCopies, Mig_ObjId(p));      }
+static inline void         Mig_ObjSetCopy( Mig_Obj_t * p, int i )              { assert( Vec_IntSize(&Mig_ObjMan(p)->vCopies) != 0 ); Vec_IntWriteEntry(&Mig_ObjMan(p)->vCopies, Mig_ObjId(p), i); }
+
+static inline void         Mig_ManIncrementTravId( Mig_Man_t * p )             { if ( p->vTravIds.pArray == NULL ) Vec_IntFill( &p->vTravIds, Mig_ManObjNum(p)+500, 0 ); p->nTravIds++;      }
+static inline void         Mig_ObjIncrementTravId( Mig_Obj_t * p )             { if ( Mig_ObjMan(p)->vTravIds.pArray == NULL ) Vec_IntFill( &Mig_ObjMan(p)->vTravIds, Mig_ManObjNum(Mig_ObjMan(p))+500, 0 ); Mig_ObjMan(p)->nTravIds++;           }
+static inline void         Mig_ObjSetTravIdCurrent( Mig_Obj_t * p )            { Vec_IntSetEntry(&Mig_ObjMan(p)->vTravIds, Mig_ObjId(p), Mig_ObjMan(p)->nTravIds );              }
+static inline void         Mig_ObjSetTravIdPrevious( Mig_Obj_t * p )           { Vec_IntSetEntry(&Mig_ObjMan(p)->vTravIds, Mig_ObjId(p), Mig_ObjMan(p)->nTravIds-1 );            }
+static inline int          Mig_ObjIsTravIdCurrent( Mig_Obj_t * p )             { return (Vec_IntGetEntry(&Mig_ObjMan(p)->vTravIds, Mig_ObjId(p)) == Mig_ObjMan(p)->nTravIds);    }
+static inline int          Mig_ObjIsTravIdPrevious( Mig_Obj_t * p )            { return (Vec_IntGetEntry(&Mig_ObjMan(p)->vTravIds, Mig_ObjId(p)) == Mig_ObjMan(p)->nTravIds-1);  }
+static inline void         Mig_ObjSetTravIdCurrentId( Mig_Man_t * p, int Id )  { Vec_IntSetEntry(&p->vTravIds, Id, p->nTravIds );                                                }
+static inline int          Mig_ObjIsTravIdCurrentId( Mig_Man_t * p, int Id )   { return (Vec_IntGetEntry(&p->vTravIds, Id) == p->nTravIds);                                      }
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Mig_Obj_t * Mig_ManAppendObj( Mig_Man_t * p )
+{
+    Mig_Obj_t * pObj;
+    assert( p->nObjs < MIG_NONE );
+    if ( p->nObjs >= (Vec_PtrSize(&p->vPages) << MIG_BASE) )
+    {
+        Mig_Obj_t * pPage;// int i;
+        assert( p->nObjs == (Vec_PtrSize(&p->vPages) << MIG_BASE) );
+        pPage = ABC_FALLOC( Mig_Obj_t, MIG_MASK + 3 ); // 1 for mask, 1 for prefix, 1 for sentinel
+        *((void **)pPage) = p;
+//        *((void ***)(pPage + 1) - 1) = Vec_PtrArray(&p->vPages);
+        Vec_PtrPush( &p->vPages, pPage + 1 );
+//        if ( *((void ***)(pPage + 1) - 1) != Vec_PtrArray(&p->vPages) )
+//            Vec_PtrForEachEntry( Mig_Obj_t *, &p->vPages, pPage, i )
+//                *((void ***)pPage - 1) = Vec_PtrArray(&p->vPages);
+    }
+    pObj = Mig_ManObj( p, p->nObjs++ );
+    assert( Mig_ObjIsNone(pObj) );
+    Mig_ObjSetId( pObj, p->nObjs-1 );
+    return pObj;
+}
+static inline int Mig_ManAppendCi( Mig_Man_t * p )  
+{ 
+    Mig_Obj_t * pObj = Mig_ManAppendObj( p );
+    Mig_ObjSetCioId( pObj, Vec_IntSize(&p->vCis) );
+    Vec_IntPush( &p->vCis, Mig_ObjId(pObj) );
+    return Mig_ObjId(pObj) << 1;
+}
+static inline int Mig_ManAppendCo( Mig_Man_t * p, int iLit0 )  
+{ 
+    Mig_Obj_t * pObj;
+    assert( !Mig_ObjIsCo(Mig_ManObj(p, Abc_Lit2Var(iLit0))) );
+    pObj = Mig_ManAppendObj( p );    
+    Mig_ObjSetFaninLit( pObj, 0, iLit0 );
+    Mig_ObjSetCioId( pObj, Vec_IntSize(&p->vCos) );
+    Vec_IntPush( &p->vCos, Mig_ObjId(pObj) );
+    return Mig_ObjId( pObj ) << 1;
+}
+static inline int Mig_ManAppendBuf( Mig_Man_t * p, int iLit0 )  
+{ 
+    Mig_Obj_t * pObj;
+    pObj = Mig_ManAppendObj( p );    
+    Mig_ObjSetFaninLit( pObj, 0, iLit0 );
+    return Mig_ObjId( pObj ) << 1;
+}
+static inline int Mig_ManAppendAnd( Mig_Man_t * p, int iLit0, int iLit1 )  
+{ 
+    Mig_Obj_t * pObj = Mig_ManAppendObj( p );
+    assert( iLit0 != iLit1 );
+    Mig_ObjSetFaninLit( pObj, 0, iLit0 < iLit1 ? iLit0 : iLit1 );
+    Mig_ObjSetFaninLit( pObj, 1, iLit0 < iLit1 ? iLit1 : iLit0 );
+    return Mig_ObjId( pObj ) << 1;
+}
+static inline int Mig_ManAppendXor( Mig_Man_t * p, int iLit0, int iLit1 )  
+{ 
+    Mig_Obj_t * pObj = Mig_ManAppendObj( p );
+    assert( iLit0 != iLit1 );
+    assert( !Abc_LitIsCompl(iLit0) && !Abc_LitIsCompl(iLit1) );
+    Mig_ObjSetFaninLit( pObj, 0, iLit0 < iLit1 ? iLit1 : iLit0 );
+    Mig_ObjSetFaninLit( pObj, 1, iLit0 < iLit1 ? iLit0 : iLit1 );
+    return Mig_ObjId( pObj ) << 1;
+}
+static inline int Mig_ManAppendMux( Mig_Man_t * p, int iLit0, int iLit1, int iCtrl )  
+{ 
+    Mig_Obj_t * pObj = Mig_ManAppendObj( p );
+    assert( iLit0 != iLit1 && iLit0 != iCtrl && iLit1 != iCtrl );
+    assert( !Abc_LitIsCompl(iLit0) || !Abc_LitIsCompl(iLit1) );
+    Mig_ObjSetFaninLit( pObj, 0, iLit0 < iLit1 ? iLit0 : iLit1 );
+    Mig_ObjSetFaninLit( pObj, 1, iLit0 < iLit1 ? iLit1 : iLit0 );
+    Mig_ObjSetFaninLit( pObj, 2, iLit0 < iLit1 ? iCtrl : Abc_LitNot(iCtrl) );
+    return Mig_ObjId( pObj ) << 1;
+}
+static inline int Mig_ManAppendMaj( Mig_Man_t * p, int iLit0, int iLit1, int iLit2 )  
+{ 
+    Mig_Obj_t * pObj = Mig_ManAppendObj( p );
+    assert( iLit0 != iLit1 && iLit0 != iLit2 && iLit1 != iLit2 );
+    Mig_ObjSetFaninLit( pObj, 0, iLit0 < iLit1 ? iLit1 : iLit0 );
+    Mig_ObjSetFaninLit( pObj, 1, iLit0 < iLit1 ? iLit0 : iLit1 );
+    Mig_ObjSetFaninLit( pObj, 2, iLit2 );
+    return Mig_ObjId( pObj ) << 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+// iterators over objects
+#define Mig_ManForEachObj( p, pObj )                                    \
+    for ( p->iPage = 0; p->iPage < Vec_PtrSize(&p->vPages) &&           \
+        ((p->pPage) = (Mig_Obj_t *)Vec_PtrEntry(&p->vPages, p->iPage)); p->iPage++ ) \
+        for ( pObj = p->pPage; !Mig_ObjIsNone(pObj); pObj++ )
+#define Mig_ManForEachObj1( p, pObj )                                   \
+    for ( p->iPage = 0; p->iPage < Vec_PtrSize(&p->vPages) &&           \
+        ((p->pPage) = (Mig_Obj_t *)Vec_PtrEntry(&p->vPages, p->iPage)); p->iPage++ ) \
+        for ( pObj = p->pPage + (p->iPage == 0); !Mig_ObjIsNone(pObj); pObj++ )
+#define Mig_ManForEachObjReverse( p, pObj )                             \
+    for ( p->iPage = Vec_PtrSize(&p->vPages) - 1; p->iPage >= 0 &&      \
+        ((p->pPage) = (Mig_Obj_t *)Vec_PtrEntry(&p->vPages, p->iPage)); p->iPage-- ) \
+        for ( pObj = (p->iPage == Vec_PtrSize(&p->vPages) - 1) ?        \
+            Mig_ManObj(p, Mig_ManObjNum(p)-1) :  p->pPage + MIG_MASK;   \
+                pObj - p->pPage >= 0; pObj-- )
+
+#define Mig_ManForEachObjVec( vVec, p, pObj, i )                        \
+    for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Mig_ManObj(p, Vec_IntEntry(vVec,i))); i++ )
+
+#define Mig_ManForEachNode( p, pObj )                                   \
+    Mig_ManForEachObj( p, pObj ) if ( !Mig_ObjIsNode(pObj) ) {} else
+#define Mig_ManForEachCand( p, pObj )                                   \
+    Mig_ManForEachObj( p, pObj ) if ( !Mig_ObjIsCand(pObj) ) {} else
+
+#define Mig_ManForEachCi( p, pObj, i )                                  \
+    for ( i = 0; (i < Vec_IntSize(&p->vCis)) && ((pObj) = Mig_ManCi(p, i)); i++ )
+#define Mig_ManForEachCo( p, pObj, i )                                  \
+    for ( i = 0; (i < Vec_IntSize(&p->vCos)) && ((pObj) = Mig_ManCo(p, i)); i++ )
+
+// iterators over fanins
+#define Mig_ObjForEachFaninId( p, iFanin, i )                           \
+    for ( i = 0; Mig_ObjHasFanin(p, i) && ((iFanin) = Mig_ObjFaninId(p, i)); i++ )
+#define Mig_ObjForEachFanin( p, pFanin, i )                             \
+    for ( i = 0; Mig_ObjHasFanin(p, i) && ((pFanin) = Mig_ObjFanin(p, i)); i++ )
+
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== mpmMig.c ===========================================================*/
+extern Mig_Man_t *           Mig_ManStart();
+extern void                  Mig_ManStop( Mig_Man_t * p );
+extern void                  Mig_ManSetRefs( Mig_Man_t * p );
+extern int                   Mig_ManAndNum( Mig_Man_t * p );
+extern int                   Mig_ManXorNum( Mig_Man_t * p );
+extern int                   Mig_ManMuxNum( Mig_Man_t * p );
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/map/mpm/mpmPre.c b/abc-build/src/map/mpm/mpmPre.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mpm/mpmPre.c
@@ -0,0 +1,1029 @@
+/**CFile****************************************************************
+
+  FileName    [mpmPre.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Configurable technology mapper.]
+
+  Synopsis    [DSD-related precomputations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 1, 2013.]
+
+  Revision    [$Id: mpmPre.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+#include "misc/vec/vecHsh.h"
+#include "misc/extra/extra.h"
+#include "bool/kit/kit.h"
+#include "misc/util/utilTruth.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ifd_Obj_t_ Ifd_Obj_t;
+struct Ifd_Obj_t_
+{
+    unsigned          nFreq : 18;   // frequency
+    unsigned          nAnds :  6;   // number of AND gates
+    unsigned          nSupp :  5;   // support size
+    unsigned          Type  :  2;   // type
+    unsigned          fWay  :  1;   // transparent edge
+    unsigned          pFans[3];     // fanins
+};
+
+typedef struct Ifd_Man_t_ Ifd_Man_t;
+struct Ifd_Man_t_
+{
+    Ifd_Obj_t *       pObjs;
+    int               nObjs;
+    int               nObjsAlloc;
+    // hashing operations
+    Vec_Int_t *       vArgs;     // iDsd1 op iDsdC
+    Vec_Int_t *       vRes;      // result of operation
+    Hsh_IntMan_t *    vHash;     // hash table 
+    Vec_Int_t *       vMarks;    // marks where given N begins
+    Vec_Wrd_t *       vTruths;   // truth tables
+    Vec_Int_t *       vClauses;  // truth tables
+    // other data
+    Vec_Int_t *       vSuper;
+
+};
+
+static inline int         Ifd_ObjIsVar( Ifd_Obj_t * p ) { return p->Type == 0; }
+static inline int         Ifd_ObjIsAnd( Ifd_Obj_t * p ) { return p->Type == 1; }
+static inline int         Ifd_ObjIsXor( Ifd_Obj_t * p ) { return p->Type == 2; }
+static inline int         Ifd_ObjIsMux( Ifd_Obj_t * p ) { return p->Type == 3; }
+
+static inline Ifd_Obj_t * Ifd_ManObj( Ifd_Man_t * p, int i )           { assert( i >= 0 && i < p->nObjs );                              return p->pObjs + i;    }
+static inline Ifd_Obj_t * Ifd_ManObjFromLit( Ifd_Man_t * p, int iLit ) { return Ifd_ManObj( p, Abc_Lit2Var(iLit) );                                             }
+static inline int         Ifd_ObjId( Ifd_Man_t * p, Ifd_Obj_t * pObj ) { assert( pObj - p->pObjs >= 0 && pObj - p->pObjs < p->nObjs );  return pObj - p->pObjs; }
+static inline int         Ifd_LitSuppSize( Ifd_Man_t * p, int iLit )   { return iLit > 0 ? Ifd_ManObjFromLit(p, iLit)->nSupp : 0;                               }
+static inline int         Ifd_LitNumAnds( Ifd_Man_t * p, int iLit )    { return iLit > 0 ? Ifd_ManObjFromLit(p, iLit)->nAnds : 0;                               }
+
+#define Ifd_ManForEachNodeWithSupp( p, nVars, pLeaf, i )                       \
+    for ( i = Vec_IntEntry(p->vMarks, nVars); (i < Vec_IntEntry(p->vMarks, nVars+1)) && (pLeaf = Ifd_ManObj(p, i)); i++ )
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ifd_Man_t * Ifd_ManStart()
+{
+    Ifd_Man_t * p;
+    p = ABC_CALLOC( Ifd_Man_t, 1 );
+    p->nObjsAlloc = Abc_PrimeCudd( 50000000 );
+    p->nObjs      = 2;
+    p->pObjs      = ABC_CALLOC( Ifd_Obj_t, p->nObjsAlloc );
+    memset( p->pObjs, 0xFF, sizeof(Ifd_Obj_t) ); // const node
+    (p->pObjs + 1)->nSupp = 1;  // variable
+    (p->pObjs + 1)->fWay  = 1;  // variable
+    // hashing operations
+    p->vArgs      = Vec_IntAlloc( 4000 );
+    p->vRes       = Vec_IntAlloc( 1000 );
+    p->vHash      = Hsh_IntManStart( p->vArgs, 4, 1000 );
+    p->vMarks     = Vec_IntAlloc( 100 );
+    Vec_IntPush( p->vMarks, 0 );
+    Vec_IntPush( p->vMarks, 1 );
+    Vec_IntPush( p->vMarks, p->nObjs );
+    // other data
+    p->vSuper     = Vec_IntAlloc( 1000 );
+    p->vTruths    = Vec_WrdAlloc( 1000 );
+    p->vClauses   = Vec_IntAlloc( 1000 );
+    return p;
+}
+void Ifd_ManStop( Ifd_Man_t * p )
+{
+    int i, This, Prev = 0;
+    Vec_IntForEachEntryStart( p->vMarks, This, i, 1 )
+    {
+        printf( "%d(%d:%d) ", i-1, This, This - Prev );
+        Prev = This;
+    }
+    printf( "\n" );
+
+    Vec_IntFreeP( &p->vArgs );
+    Vec_IntFreeP( &p->vRes );
+    Vec_WrdFreeP( &p->vTruths );
+    Vec_IntFreeP( &p->vClauses );
+    Vec_IntFreeP( &p->vMarks );
+    Hsh_IntManStop( p->vHash );
+    Vec_IntFreeP( &p->vSuper );
+    ABC_FREE( p->pObjs );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Printing structures.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ifd_ObjPrint_rec( Ifd_Man_t * p, int iLit, int * pCounter, int DiffType )
+{
+    char Symb[2][4] = { {'?','(','[','<'}, {'?',')',']','>'} };
+    Ifd_Obj_t * pDsd;
+    if ( Abc_LitIsCompl(iLit) )
+        printf( "!" ), iLit = Abc_LitNot(iLit);
+    if ( iLit == 2 )
+        { printf( "%c", 'a' + (*pCounter)++ ); return; }
+    pDsd = Ifd_ManObjFromLit( p, iLit );
+    if ( DiffType )
+        printf( "%c", Symb[0][pDsd->Type] );
+    Ifd_ObjPrint_rec( p, pDsd->pFans[0], pCounter, pDsd->Type == 3 || Abc_LitIsCompl(pDsd->pFans[0]) || pDsd->Type != Ifd_ManObjFromLit(p, pDsd->pFans[0])->Type );
+    Ifd_ObjPrint_rec( p, pDsd->pFans[1], pCounter, pDsd->Type == 3 || Abc_LitIsCompl(pDsd->pFans[1]) || pDsd->Type != Ifd_ManObjFromLit(p, pDsd->pFans[1])->Type );
+    if ( pDsd->pFans[2] != -1 )
+    Ifd_ObjPrint_rec( p, pDsd->pFans[2], pCounter, pDsd->Type == 3 || Abc_LitIsCompl(pDsd->pFans[2]) || pDsd->Type != Ifd_ManObjFromLit(p, pDsd->pFans[2])->Type );
+    if ( DiffType )
+        printf( "%c", Symb[1][pDsd->Type] );
+}
+void Ifd_ObjPrint( Ifd_Man_t * p, int iLit )
+{
+    int Counter = 0;
+    if ( iLit == 0 )
+        { printf( "0" ); return; }
+    if ( iLit == 1 )
+        { printf( "1" ); return; }
+    Ifd_ObjPrint_rec( p, iLit, &Counter, 1 );
+}
+void Ifd_ManPrint2( Ifd_Man_t * p )
+{
+    int i;
+    for ( i = 0; i < p->nObjs; i++ )
+    {
+        printf( "%4d : ", i );
+        Ifd_ObjPrint( p, Abc_Var2Lit( i, 0 ) );
+        printf( "\n" );
+    }
+}
+void Ifd_ManPrint( Ifd_Man_t * p )
+{
+    int i;
+    for ( i = 0; i < p->nObjs; i++ )
+    {
+        word Fun = Vec_WrdEntry( p->vTruths, i );
+        printf( "    { " );
+        printf( "%d, ", Extra_TruthSupportSize((unsigned *)&Fun, 6) );
+        printf( "%2d, ", Ifd_LitNumAnds(p, Abc_Var2Lit(i, 0)) );
+        printf( "%2d, ", Vec_IntEntry(p->vClauses, i) );
+        printf( "ABC_CONST(" );
+        Extra_PrintHex( stdout, (unsigned *)&Fun, 6 ); 
+        printf( "), \"" );
+        Ifd_ObjPrint( p, Abc_Var2Lit( i, 0 ) );
+        printf( "\" },   // %4d \n", i );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computing truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word Ifd_ObjTruth_rec( Ifd_Man_t * p, int iLit, int * pCounter )
+{
+    static word s_Truths6[6] = {
+        ABC_CONST(0xAAAAAAAAAAAAAAAA),
+        ABC_CONST(0xCCCCCCCCCCCCCCCC),
+        ABC_CONST(0xF0F0F0F0F0F0F0F0),
+        ABC_CONST(0xFF00FF00FF00FF00),
+        ABC_CONST(0xFFFF0000FFFF0000),
+        ABC_CONST(0xFFFFFFFF00000000)
+    };
+    Ifd_Obj_t * pDsd;
+    word Fun0, Fun1, Fun2 = 0;
+    assert( !Abc_LitIsCompl(iLit) );
+    if ( iLit == 2 )
+        return s_Truths6[(*pCounter)++];
+    pDsd = Ifd_ManObjFromLit( p, iLit );
+
+    Fun0 = Ifd_ObjTruth_rec( p, Abc_LitRegular(pDsd->pFans[0]), pCounter );
+    Fun1 = Ifd_ObjTruth_rec( p, Abc_LitRegular(pDsd->pFans[1]), pCounter );
+    if ( pDsd->pFans[2] != -1 )
+    Fun2 = Ifd_ObjTruth_rec( p, Abc_LitRegular(pDsd->pFans[2]), pCounter );
+
+    Fun0 = Abc_LitIsCompl(pDsd->pFans[0]) ? ~Fun0 : Fun0;
+    Fun1 = Abc_LitIsCompl(pDsd->pFans[1]) ? ~Fun1 : Fun1;
+    if ( pDsd->pFans[2] != -1 )
+    Fun2 = Abc_LitIsCompl(pDsd->pFans[2]) ? ~Fun2 : Fun2;
+
+    if ( pDsd->Type == 1 )
+        return Fun0 & Fun1;
+    if ( pDsd->Type == 2 )
+        return Fun0 ^ Fun1;
+    if ( pDsd->Type == 3 )
+        return (Fun2 & Fun1) | (~Fun2 & Fun0);
+    assert( 0 );
+    return -1;
+}
+word Ifd_ObjTruth( Ifd_Man_t * p, int iLit )
+{
+    word Fun;
+    int Counter = 0;
+    if ( iLit == 0 )
+        return 0;
+    if ( iLit == 1 )
+        return ~(word)0;
+    Fun = Ifd_ObjTruth_rec( p, Abc_LitRegular(iLit), &Counter );
+    return Abc_LitIsCompl(iLit) ? ~Fun : Fun;
+}
+void Ifd_ManTruthAll( Ifd_Man_t * p )
+{
+    word Fun;
+    int i;
+    assert( Vec_WrdSize(p->vTruths) == 0 );
+    for ( i = 0; i < p->nObjs; i++ )
+    {
+        Fun = Ifd_ObjTruth( p, Abc_Var2Lit( i, 0 ) );
+        Vec_WrdPush( p->vTruths, Fun );
+//        Extra_PrintHex( stdout, (unsigned *)&Fun, 6 ); printf( " " );
+//        Kit_DsdPrintFromTruth( (unsigned *)&Fun, 6 ); printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mpm_ComputeCnfSizeOne( word Truth, int nVars, Vec_Int_t * vCover, Vec_Str_t * vCnf )
+{
+    Vec_StrClear( vCnf );
+    if ( Truth == 0 || ~Truth == 0 )
+    {
+//        assert( nVars == 0 );
+        Vec_StrPush( vCnf, (char)(Truth == 0) );
+        Vec_StrPush( vCnf, (char)-1 );
+        return 1;
+    }
+    else 
+    {
+        int i, k, c, RetValue, Literal, Cube, nCubes = 0;
+        assert( nVars > 0 );
+        for ( c = 0; c < 2; c ++ )
+        {
+            Truth = c ? ~Truth : Truth;
+            RetValue = Kit_TruthIsop( (unsigned *)&Truth, nVars, vCover, 0 );
+            assert( RetValue == 0 );
+            nCubes += Vec_IntSize( vCover );
+            Vec_IntForEachEntry( vCover, Cube, i )
+            {
+                for ( k = 0; k < nVars; k++ )
+                {
+                    Literal = 3 & (Cube >> (k << 1));
+                    if ( Literal == 1 )      // '0'  -> pos lit
+                        Vec_StrPush( vCnf, (char)Abc_Var2Lit(k, 0) );
+                    else if ( Literal == 2 ) // '1'  -> neg lit
+                        Vec_StrPush( vCnf, (char)Abc_Var2Lit(k, 1) );
+                    else if ( Literal != 0 )
+                        assert( 0 );
+                }
+                Vec_StrPush( vCnf, (char)Abc_Var2Lit(nVars, c) );
+                Vec_StrPush( vCnf, (char)-1 );
+            }
+        }
+        return nCubes;
+    }
+}
+void Mpm_ComputeCnfSizeAll( Ifd_Man_t * p )
+{
+    Vec_Int_t * vCover = Vec_IntAlloc( 1 << 16 );
+    Vec_Str_t * vCnf = Vec_StrAlloc( 1000 );
+    word Truth;
+    int i;
+    assert( Vec_IntSize(p->vClauses) == 0 );
+    Vec_WrdForEachEntry( p->vTruths, Truth, i )
+        Vec_IntPush( p->vClauses, Mpm_ComputeCnfSizeOne(Truth, 6, vCover, vCnf) );
+    Vec_IntFree( vCover );
+    Vec_StrFree( vCnf );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Canonicizing DSD structures.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ifd_ManHashLookup( Ifd_Man_t * p, int iDsd0, int iDsd1, int iDsdC, int Type )
+{
+    int pData[4];
+    assert( iDsdC != -1 || iDsd0 >= iDsd1 );
+    assert( iDsdC == -1 || !Abc_LitIsCompl(iDsd1) );
+    pData[0] = iDsd0;
+    pData[1] = iDsd1;
+    pData[2] = iDsdC;
+    pData[3] = Type;
+    return *Hsh_IntManLookup( p->vHash, (unsigned *)pData );
+}
+void Ifd_ManHashInsert( Ifd_Man_t * p, int iDsd0, int iDsd1, int iDsdC, int Type, int Res )
+{
+    int iObj;
+    assert( iDsdC != -1 || iDsd0 >= iDsd1 );
+    assert( iDsdC == -1 || !Abc_LitIsCompl(iDsd1) );
+    Vec_IntPush( p->vArgs, iDsd0 );
+    Vec_IntPush( p->vArgs, iDsd1 );
+    Vec_IntPush( p->vArgs, iDsdC );
+    Vec_IntPush( p->vArgs, Type );
+    iObj = Hsh_IntManAdd( p->vHash, Vec_IntSize(p->vRes) );
+    assert( iObj == Vec_IntSize(p->vRes) );
+    Vec_IntPush( p->vRes, Res );
+    assert( 4 * Vec_IntSize(p->vRes) == Vec_IntSize(p->vArgs) );
+}
+int Ifd_ManHashFindOrAdd( Ifd_Man_t * p, int iDsd0, int iDsd1, int iDsdC, int Type )
+{
+    Ifd_Obj_t * pObj;
+    int iObj, Value;
+    assert( iDsdC != -1 || iDsd0 >= iDsd1 );
+    assert( iDsdC == -1 || !Abc_LitIsCompl(iDsd1) );
+    Vec_IntPush( p->vArgs, iDsd0 );
+    Vec_IntPush( p->vArgs, iDsd1 );
+    Vec_IntPush( p->vArgs, iDsdC );
+    Vec_IntPush( p->vArgs, Type );
+    Value = Hsh_IntManAdd( p->vHash, Vec_IntSize(p->vRes) );
+    if ( Value < Vec_IntSize(p->vRes) )
+    {
+        iObj = Vec_IntEntry(p->vRes, Value);
+        Vec_IntShrink( p->vArgs, Vec_IntSize(p->vArgs) - 4 );
+        pObj = Ifd_ManObj( p, iObj );
+//        pObj->nFreq++;
+        assert( (int)pObj->Type == Type );
+        assert( (int)pObj->nSupp == Ifd_LitSuppSize(p, iDsd0) + Ifd_LitSuppSize(p, iDsd1) + Ifd_LitSuppSize(p, iDsdC) );
+    }
+    else
+    {
+        if ( p->nObjs == p->nObjsAlloc )
+            printf( "The number of nodes is more than %d\n", p->nObjs );
+        assert( p->nObjs < p->nObjsAlloc );
+        iObj = p->nObjs;
+        pObj = Ifd_ManObj( p, p->nObjs++ );
+//        pObj->nFreq = 1;
+        pObj->nSupp = Ifd_LitSuppSize(p, iDsd0) + Ifd_LitSuppSize(p, iDsd1) + Ifd_LitSuppSize(p, iDsdC); 
+        pObj->nAnds = Ifd_LitNumAnds(p, iDsd0) + Ifd_LitNumAnds(p, iDsd1) + Ifd_LitNumAnds(p, iDsdC) + ((Type == 1) ? 1 : 3); 
+        pObj->Type  = Type;
+        if ( Type == 1 )
+            pObj->fWay = 0;
+        else if ( Type == 2 )
+            pObj->fWay = Ifd_ManObjFromLit(p, iDsd0)->fWay || Ifd_ManObjFromLit(p, iDsd1)->fWay;
+        else if ( Type == 3 )
+//            pObj->fWay = (Ifd_ManObjFromLit(p, iDsd0)->fWay && Ifd_ManObjFromLit(p, iDsd1)->fWay) || (Abc_Lit2Var(iDsd0) == Abc_Lit2Var(iDsd1) && Ifd_ManObjFromLit(p, iDsdC)->fWay);
+            pObj->fWay = (Ifd_ManObjFromLit(p, iDsd0)->fWay && Ifd_ManObjFromLit(p, iDsd1)->fWay) || (iDsd0 == Abc_LitNot(iDsd1) && Ifd_ManObjFromLit(p, iDsdC)->fWay);
+        else assert( 0 );
+        pObj->pFans[0] = iDsd0;
+        pObj->pFans[1] = iDsd1;
+        pObj->pFans[2] = iDsdC;
+        Vec_IntPush( p->vRes, iObj );
+    }
+    assert( 4 * Vec_IntSize(p->vRes) == Vec_IntSize(p->vArgs) );
+    return iObj;
+}
+void Ifd_ManOperSuper_rec( Ifd_Man_t * p, int iLit, int Type, Vec_Int_t * vObjs )
+{
+    Ifd_Obj_t * pDsd = Ifd_ManObjFromLit( p, iLit );
+    if ( Abc_LitIsCompl(iLit) || (int)pDsd->Type != Type )
+        Vec_IntPush( vObjs, iLit );
+    else
+    {
+        Ifd_ManOperSuper_rec( p, pDsd->pFans[0], Type, vObjs );
+        Ifd_ManOperSuper_rec( p, pDsd->pFans[1], Type, vObjs );
+    }
+}
+int Ifd_ManOper( Ifd_Man_t * p, int iDsd0, int iDsd1, int iDsdC, int Type )
+{
+    int i, iLit0, iLit1, iThis, fCompl = 0;
+    if ( Type == 1 ) // AND
+    {
+        if ( iDsd0 == 0 || iDsd1 == 0 )
+            return 0;
+        if ( iDsd0 == 1 || iDsd1 == 1 )
+            return (iDsd0 == 1) ? iDsd1 : iDsd0;
+    }
+    else if ( Type == 2 ) // XOR
+    {
+        if ( iDsd0 < 2 )
+            return Abc_LitNotCond( iDsd1, iDsd0 );
+        if ( iDsd1 < 2 )
+            return Abc_LitNotCond( iDsd0, iDsd1 );
+        if ( Abc_LitIsCompl(iDsd0) )
+            fCompl ^= 1, iDsd0 = Abc_LitNot(iDsd0);
+        if ( Abc_LitIsCompl(iDsd1) )
+            fCompl ^= 1, iDsd1 = Abc_LitNot(iDsd1);
+    }
+    else if ( Type == 3 )
+    {
+        if ( Abc_LitIsCompl(iDsdC) )
+        {
+            ABC_SWAP( int, iDsd0, iDsd1 );
+            iDsdC = Abc_LitNot(iDsdC);
+        }
+        if ( Abc_LitIsCompl(iDsd1) )
+            fCompl ^= 1, iDsd0 = Abc_LitNot(iDsd0), iDsd1 = Abc_LitNot(iDsd1);
+    }
+    assert( iDsd0 > 1 && iDsd1 > 1 && Type >= 1 && Type <= 3 );
+/*
+    // check cache
+    iThis = Ifd_ManHashLookup( p, iDsd0, iDsd1, iDsdC, Type );
+    if ( iThis != -1 )
+        return Abc_Var2Lit( iThis, fCompl );
+*/
+    // create new entry
+    if ( Type == 3 )
+    {
+        iThis = Ifd_ManHashFindOrAdd( p, iDsd0, iDsd1, iDsdC, Type );
+        return Abc_Var2Lit( iThis, fCompl );
+    }
+    assert( iDsdC == -1 );
+    Vec_IntClear( p->vSuper );
+    Ifd_ManOperSuper_rec( p, iDsd0, Type, p->vSuper );
+    Ifd_ManOperSuper_rec( p, iDsd1, Type, p->vSuper );
+    Vec_IntSort( p->vSuper, 1 );
+    iLit0 = Vec_IntEntry( p->vSuper, 0 );
+    Vec_IntForEachEntryStart( p->vSuper, iLit1, i, 1 )
+        iLit0 = Abc_Var2Lit( Ifd_ManHashFindOrAdd(p, iLit0, iLit1, -1, Type), 0 );
+    assert( !Abc_LitIsCompl(iLit0) );
+    // insert into cache
+//    if ( Vec_IntSize(p->vSuper) > 2 )
+//        Ifd_ManHashInsert( p, iDsd0, iDsd1, iDsdC, Type, iLit0 );
+    return Abc_LitNotCond( iLit0, fCompl );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ifd_ManFindDsd_rec( Ifd_Man_t * pMan, char * pStr, char ** p, int * pMatches )
+{
+    int fCompl = 0;
+    if ( **p == '!' )
+        (*p)++, fCompl = 1;
+    if ( **p >= 'a' && **p <= 'f' ) // var
+    {
+        assert( **p - 'a' >= 0 && **p - 'a' < 6 );
+        return Abc_Var2Lit( 1, fCompl );
+    }
+    if ( **p == '(' ) // and/or
+    {
+        char * q = pStr + pMatches[ *p - pStr ];
+        int Lit, Res = 1;
+        assert( **p == '(' && *q == ')' );
+        for ( (*p)++; *p < q; (*p)++ )
+        {
+            Lit = Ifd_ManFindDsd_rec( pMan, pStr, p, pMatches );
+            Res = Ifd_ManOper( pMan, Res, Lit, 0, 1 );
+        }
+        assert( *p == q );
+        return Abc_LitNotCond( Res, fCompl );
+    }
+    if ( **p == '[' ) // xor
+    {
+        char * q = pStr + pMatches[ *p - pStr ];
+        int Lit, Res = 0;
+        assert( **p == '[' && *q == ']' );
+        for ( (*p)++; *p < q; (*p)++ )
+        {
+            Lit = Ifd_ManFindDsd_rec( pMan, pStr, p, pMatches );
+            Res = Ifd_ManOper( pMan, Res, Lit, 0, 2 );
+        }
+        assert( *p == q );
+        return Abc_LitNotCond( Res, fCompl );
+    }
+    if ( **p == '<' ) // mux
+    {
+        int Temp[3], * pTemp = Temp, Res;
+        char * q = pStr + pMatches[ *p - pStr ];
+        assert( **p == '<' && *q == '>' );
+        // derive MAX components
+        for ( (*p)++; *p < q; (*p)++ )
+            *pTemp++ = Ifd_ManFindDsd_rec( pMan, pStr, p, pMatches );
+        assert( pTemp == Temp + 3 );
+        assert( *p == q );
+//        Res = (Temp[0] & Temp[1]) | (~Temp[0] & Temp[2]);
+        Res = Ifd_ManOper( pMan, Temp[2], Temp[1], Temp[0], 3 );
+        return Abc_LitNotCond( Res, fCompl );
+    }
+    assert( 0 );
+    return 0;
+}
+#define IFM_MAX_STR  100
+#define IFM_MAX_VAR   16
+int * Ifd_ManComputeMatches( char * p )
+{
+    static int pMatches[IFM_MAX_STR];
+    int pNested[IFM_MAX_VAR];
+    int v, nNested = 0;
+    for ( v = 0; p[v]; v++ )
+    {
+        assert( v < IFM_MAX_STR );
+        pMatches[v] = 0;
+        if ( p[v] == '(' || p[v] == '[' || p[v] == '<' || p[v] == '{' )
+            pNested[nNested++] = v;
+        else if ( p[v] == ')' || p[v] == ']' || p[v] == '>' || p[v] == '}' )
+            pMatches[pNested[--nNested]] = v;
+        assert( nNested < IFM_MAX_VAR );
+    }
+    assert( nNested == 0 );
+    return pMatches;
+}
+int Ifd_ManFindDsd( Ifd_Man_t * pMan, char * p )
+{
+    int Res;
+    if ( *p == '0' && *(p+1) == 0 )
+        Res = 0;
+    else if ( *p == '1' && *(p+1) == 0 )
+        Res = 1;
+    else
+        Res = Ifd_ManFindDsd_rec( pMan, p, &p, Ifd_ManComputeMatches(p) );
+    assert( *++p == 0 );
+    return Res;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ifd_ManDsdTest2()
+{
+    char * p = "(abc)";
+//    char * q = "(a[bc])";
+//    char * r = "[<abc>(def)]";
+    Ifd_Man_t * pMan = Ifd_ManStart();
+    int iLit = Ifd_ManFindDsd( pMan, p );
+    Ifd_ObjPrint( pMan, iLit );
+    Ifd_ManStop( pMan );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Wrd_t * Ifd_ManDsdTruths( int nVars )
+{
+    int fUseMux = 1;
+    Vec_Wrd_t * vTruths;
+    Ifd_Man_t * pMan = Ifd_ManStart();
+    Ifd_Obj_t * pLeaf0, * pLeaf1, * pLeaf2;
+    int v, i, j, k, c0, c1, c2;
+    for ( v = 2; v <= nVars; v++ )
+    {
+        // create ANDs/XORs
+        for ( i = 1; i < v; i++ )
+        for ( j = 1; j < v; j++ )
+        if ( i + j == v )
+        {
+            Ifd_ManForEachNodeWithSupp( pMan, i, pLeaf0, c0 )
+            Ifd_ManForEachNodeWithSupp( pMan, j, pLeaf1, c1 )
+            {
+                assert( (int)pLeaf0->nSupp == i );
+                assert( (int)pLeaf1->nSupp == j );
+                Ifd_ManOper( pMan, Abc_Var2Lit(c0, 0), Abc_Var2Lit(c1, 0), -1, 1 );
+                if ( !pLeaf1->fWay )
+                Ifd_ManOper( pMan, Abc_Var2Lit(c0, 0), Abc_Var2Lit(c1, 1), -1, 1 );
+                if ( !pLeaf0->fWay )
+                Ifd_ManOper( pMan, Abc_Var2Lit(c0, 1), Abc_Var2Lit(c1, 0), -1, 1 );
+                if ( !pLeaf0->fWay && !pLeaf1->fWay )
+                Ifd_ManOper( pMan, Abc_Var2Lit(c0, 1), Abc_Var2Lit(c1, 1), -1, 1 );
+                Ifd_ManOper( pMan, Abc_Var2Lit(c0, 0), Abc_Var2Lit(c1, 0), -1, 2 );
+            }
+        }
+        // create MUX
+        if ( fUseMux )
+        for ( i = 1; i < v-1; i++ )
+        for ( j = 1; j < v-1; j++ )
+        for ( k = 1; k < v-1; k++ )
+        if ( i + j + k == v )
+        {
+            Ifd_ManForEachNodeWithSupp( pMan, i, pLeaf0, c0 )
+            Ifd_ManForEachNodeWithSupp( pMan, j, pLeaf1, c1 )
+            Ifd_ManForEachNodeWithSupp( pMan, k, pLeaf2, c2 )
+            {
+                assert( (int)pLeaf0->nSupp == i );
+                assert( (int)pLeaf1->nSupp == j );
+                assert( (int)pLeaf2->nSupp == k );
+//printf( "%d %d %d   ", i, j, k );
+//printf( "%d %d %d\n", Ifd_ObjId(pMan, pLeaf0), Ifd_ObjId(pMan, pLeaf1), Ifd_ObjId(pMan, pLeaf2) );
+                if ( pLeaf2->fWay && c0 < c1 )
+                    continue;
+                Ifd_ManOper( pMan, Abc_Var2Lit(c0, 0), Abc_Var2Lit(c1, 0), Abc_Var2Lit(c2, 0), 3 );
+                if ( !pLeaf0->fWay && !pLeaf1->fWay )
+                Ifd_ManOper( pMan, Abc_Var2Lit(c0, 1), Abc_Var2Lit(c1, 0), Abc_Var2Lit(c2, 0), 3 );
+            }
+        }
+        // bookmark
+        Vec_IntPush( pMan->vMarks, pMan->nObjs );
+    }
+    Ifd_ManTruthAll( pMan );
+    Mpm_ComputeCnfSizeAll( pMan );
+//    Ifd_ManPrint( pMan );
+    vTruths = pMan->vTruths; pMan->vTruths = NULL;
+    Ifd_ManStop( pMan );
+    return vTruths;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Generating the guided array for minimal permutations.]
+
+  Description [http://icodesnip.com/search/johnson%20trotter/]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ifd_ManDsdPermPrint( int * perm, int size ) 
+{
+    int i;
+    for ( i = 0; i < size; i++ )
+        printf( "%d", perm[i] );
+    printf( "\n" );
+}
+Vec_Int_t * Ifd_ManDsdPermJT( int n ) 
+{
+    Vec_Int_t * vGuide = Vec_IntAlloc( 100 );
+    int *array, *dir, tmp, tmp2, i, max;
+    array = (int*)malloc(sizeof(int) * n);
+    dir = (int*)calloc(n, sizeof(int));
+    for (i = 0; i < n; i++)
+    array[i] = i;
+    max = n - 1;
+    if (n != 1)
+    do 
+    {
+//        Ifd_ManDsdPermPrint(array, n);
+        tmp = array[max];
+        tmp2 = dir[max];
+        i = !dir[max] ? max - 1 : max + 1;
+        array[max] = array[i];
+        array[i] = tmp;
+        Vec_IntPush( vGuide, Abc_MinInt(max, i) );
+        dir[max] = dir[i];
+        dir[i] = tmp2;
+        for (i = 0; i < n; i++)
+            if (array[i] > tmp)
+                dir[i] = !dir[i];
+        max = n;
+        for (i = 0; i < n; i++)
+            if (((!dir[i] && i != 0 && array[i] > array[i-1]) || (dir[i] && i != n-1 && array[i] > array[i+1])) && (array[i] > array[max] || max == n))
+                max = i;
+    } 
+    while (max < n);
+//    Ifd_ManDsdPermPrint(array,n);
+    Vec_IntPush( vGuide, 0 );
+    free(dir);
+    free(array);
+    return vGuide;
+}
+int Ifd_ManDsdTest4() 
+{
+    int pPerm[6] = { 0, 1, 2, 3, 4, 5 };
+    Vec_Int_t * vGuide = Ifd_ManDsdPermJT( 6 );
+    int i, Entry;
+    Vec_IntForEachEntry( vGuide, Entry, i )
+    {
+        ABC_SWAP( int, pPerm[Entry], pPerm[Entry+1] );
+        Ifd_ManDsdPermPrint( pPerm, 6 );
+    }
+    Vec_IntFree( vGuide );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Extra_Truth6SwapAdjacent( word t, int iVar )
+{
+    // variable swapping code
+    static word PMasks[5][3] = {
+        { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) },
+        { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) },
+        { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) },
+        { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) },
+        { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) }
+    };
+    assert( iVar < 5 );
+    return (t & PMasks[iVar][0]) | ((t & PMasks[iVar][1]) << (1 << iVar)) | ((t & PMasks[iVar][2]) >> (1 << iVar));
+}
+static inline word Extra_Truth6ChangePhase( word t, int iVar)
+{
+    // elementary truth tables
+    static word Truth6[6] = {
+        ABC_CONST(0xAAAAAAAAAAAAAAAA),
+        ABC_CONST(0xCCCCCCCCCCCCCCCC),
+        ABC_CONST(0xF0F0F0F0F0F0F0F0),
+        ABC_CONST(0xFF00FF00FF00FF00),
+        ABC_CONST(0xFFFF0000FFFF0000),
+        ABC_CONST(0xFFFFFFFF00000000)
+    };
+    assert( iVar < 6 );
+    return ((t & ~Truth6[iVar]) << (1 << iVar)) | ((t & Truth6[iVar]) >> (1 << iVar));
+}
+Vec_Wrd_t * Extra_Truth6AllConfigs2( word t, int * pComp, int * pPerm, int nVars )
+{
+    int nPerms = Extra_Factorial( nVars );
+    int nSwaps = (1 << nVars);
+    Vec_Wrd_t * vTruths = Vec_WrdStart( nPerms * (1 << (nVars+1)) );
+    word tCur, tTemp1, tTemp2;
+    int i, p, c;
+    for ( i = 0; i < 2; i++ )
+    {
+        tCur = i ? t : ~t;
+        tTemp1 = tCur;
+        for ( p = 0; p < nPerms; p++ )
+        {
+            tTemp2 = tCur;
+            for ( c = 0; c < nSwaps; c++ )
+            {
+                Vec_WrdWriteEntry( vTruths, (p << (nVars+1))|(i << nVars)|c, tCur );
+                tCur = Extra_Truth6ChangePhase( tCur, pComp[c] );
+            }
+            assert( tTemp2 == tCur );
+            tCur = Extra_Truth6SwapAdjacent( tCur, pPerm[p] );
+        }
+        assert( tTemp1 == tCur );
+    }
+    if ( t )
+    {
+        int i;
+        word Truth;
+        Vec_WrdForEachEntry( vTruths, Truth, i )
+            assert( Truth );
+    }
+    return vTruths;
+}
+Vec_Wrd_t * Extra_Truth6AllConfigs( word t, int * pComp, int * pPerm, int nVars )
+{
+    int nPerms = Extra_Factorial( nVars );
+    int nSwaps = (1 << nVars);
+    Vec_Wrd_t * vTruths = Vec_WrdStart( nPerms * nSwaps );
+    word tCur = t, tTemp1, tTemp2;
+    int p, c, Config;
+
+    tTemp1 = tCur;
+    for ( p = 0; p < nPerms; p++ )
+    {
+        tCur = Extra_Truth6SwapAdjacent( tCur, pPerm[p] );
+        Config = 0;
+        tTemp2 = tCur;
+        for ( c = 0; c < nSwaps; c++ )
+        {
+            Vec_WrdWriteEntry( vTruths, (p << nVars)|Config, tCur );
+            tCur = Extra_Truth6ChangePhase( tCur, pComp[c] );
+            Config ^= (1 << pComp[c]);
+        }
+        assert( Config == 0 );
+        assert( tTemp2 == tCur );
+    }
+    assert( tTemp1 == tCur );
+
+    if ( t )
+    {
+        int i;
+        word Truth;
+        Vec_WrdForEachEntry( vTruths, Truth, i )
+            assert( Truth );
+    }
+    return vTruths;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ifd_ComputeSignature( word uTruth, int pCounts[6] )
+{
+    int v, Pos, Neg, Xor;
+    for ( v = 0; v < 6; v++ )
+    {
+        Neg = Abc_TtCountOnes( Abc_Tt6Cofactor0(uTruth, v) ) / 2;
+        Pos = Abc_TtCountOnes( Abc_Tt6Cofactor1(uTruth, v) ) / 2;
+        Xor = Abc_TtCountOnes( Abc_Tt6Cofactor0(uTruth, v) ^ Abc_Tt6Cofactor1(uTruth, v) ) / 2;
+        if ( Pos <= Neg )
+            pCounts[v] = (Pos << 20) | (Neg << 10) | Xor;
+        else
+            pCounts[v] = (Neg << 20) | (Pos << 10) | Xor;
+    }
+    Vec_IntSelectSort( pCounts, 6 );
+}
+int Ifd_ManDsdTest33() 
+{
+    int nVars = 6;
+    Vec_Wrd_t * vTruths = Ifd_ManDsdTruths( nVars );
+    int i, v, pCounts[6];
+    word uTruth;
+    Vec_WrdForEachEntry( vTruths, uTruth, i )
+    {
+        Ifd_ComputeSignature( uTruth, pCounts );
+        // print
+        printf( "%5d :  ", i ); 
+        for ( v = 0; v < 6; v++ )
+            printf( "%2d %2d %2d   ", (pCounts[v] >> 20) & 0xFF, (pCounts[v] >> 10) & 0xFF, (pCounts[v] >> 0) & 0xFF );
+        printf( "  " );
+        Kit_DsdPrintFromTruth( (unsigned *)&uTruth, nVars );
+        printf( "\n" );
+    }
+    Vec_WrdFree( vTruths );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ifd_ManDsdTest() 
+{
+    int nVars = 6;
+    FILE * pFile;
+    char pFileName[32];
+    Vec_Wrd_t * vTruths = Ifd_ManDsdTruths( nVars );
+    Vec_Wrd_t * vVariants;
+    Vec_Int_t * vUniques;
+    Vec_Int_t * vCompls;
+    Vec_Wrd_t * vTruthRes = Vec_WrdAlloc( 4000000 );
+    Vec_Int_t * vConfgRes = Vec_IntAlloc( 4000000 );
+    int * pComp, * pPerm;
+    word Truth, Variant;
+    int i, k, Uniq, Runner, Counter = 0;
+    assert( nVars >= 3 && nVars <= 6 );
+    assert( Vec_WrdSize(vTruths) < (1<<10) );
+    vCompls = Vec_IntAlloc( 720 * 64 );
+    pComp = Extra_GreyCodeSchedule( nVars );
+    pPerm = Extra_PermSchedule( nVars );
+    Vec_WrdForEachEntry( vTruths, Truth, i )
+    {
+        vVariants = Extra_Truth6AllConfigs( Truth, pComp, pPerm, nVars );
+        // save compl bits
+        Vec_IntClear( vCompls );
+        Vec_WrdForEachEntry( vVariants, Variant, k )
+        {
+            Vec_IntPush( vCompls, (int)(Variant & 1) );
+            Vec_WrdWriteEntry( vVariants, k, Variant & 1 ? ~Variant : Variant );
+        }
+        // uniqify
+        vUniques = Hsh_WrdManHashArray( vVariants, 1 );
+        Runner = 0;
+        Vec_IntForEachEntry( vUniques, Uniq, k )
+            if ( Runner == Uniq )
+            {
+                Variant = Vec_WrdEntry(vVariants, k);
+                assert( (Variant & 1) == 0 );
+                Vec_WrdPush( vTruthRes, Variant );
+                Vec_IntPush( vConfgRes, (i << 17)|(Vec_IntEntry(vCompls, k) << 16)|k );
+                Runner++;
+            }
+        Vec_IntUniqify( vUniques );
+        assert( Runner == Vec_IntSize(vUniques) );
+        Counter += Vec_IntSize(vUniques);
+//printf( "%5d : ", i ); Kit_DsdPrintFromTruth( &Truth, nVars ), printf( "  " ), Vec_IntPrint( vUniques ), printf( "\n" );
+        Vec_IntFree( vUniques );
+        Vec_WrdFree( vVariants );
+    } 
+    Vec_IntFree( vCompls );
+    Vec_WrdFree( vTruths );
+    ABC_FREE( pPerm );
+    ABC_FREE( pComp );
+    printf( "Total = %d.\n", Counter );
+    assert( Vec_WrdSize(vTruthRes) == Counter );
+    // write the data into a file
+    sprintf( pFileName, "dsdfuncs%d.dat", nVars );
+    pFile = fopen( pFileName, "wb" );
+    fwrite( Vec_WrdArray(vTruthRes), sizeof(word), Vec_WrdSize(vTruthRes), pFile );
+    fwrite( Vec_IntArray(vConfgRes), sizeof(int), Vec_IntSize(vConfgRes), pFile );
+    fclose( pFile );
+    printf( "File \"%s\" with %d 6-input functions has been written out.\n", pFileName, Vec_IntSize(vConfgRes) );
+    Vec_WrdFree( vTruthRes );
+    Vec_IntFree( vConfgRes );
+    return 1;
+}
+
+int Ifd_ManDsdTest55() 
+{
+    abctime clk = Abc_Clock();
+    FILE * pFile;
+    char * pFileName = "dsdfuncs6.dat";
+    int RetValue, size = Extra_FileSize( pFileName ) / 12;  // 2866420
+    Vec_Wrd_t * vTruthRes = Vec_WrdAlloc( size + 1 );
+    Vec_Int_t * vConfgRes = Vec_IntAlloc( size );
+    Hsh_IntMan_t * pHash;
+
+    pFile = fopen( pFileName, "rb" );
+    RetValue = fread( Vec_WrdArray(vTruthRes), sizeof(word), size, pFile );
+    RetValue = fread( Vec_IntArray(vConfgRes), sizeof(int), size, pFile );
+    vTruthRes->nSize = size;
+    vConfgRes->nSize = size;
+    // create hash table
+    pHash = Hsh_WrdManHashArrayStart( vTruthRes, 1 );
+    // experiment with functions
+
+    // cleanup
+    Hsh_IntManStop( pHash );
+    Vec_WrdFree( vTruthRes );
+    Vec_IntFree( vConfgRes );
+    Abc_PrintTime( 1, "Reading file", Abc_Clock() - clk );
+    return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mpm/mpmTruth.c b/abc-build/src/map/mpm/mpmTruth.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mpm/mpmTruth.c
@@ -0,0 +1,239 @@
+/**CFile****************************************************************
+
+  FileName    [mpmTruth.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Configurable technology mapper.]
+
+  Synopsis    [Truth table manipulation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 1, 2013.]
+
+  Revision    [$Id: mpmTruth.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mpmInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+//#define MPM_TRY_NEW
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Unifies variable order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Mpm_TruthStretch( word * pTruth, Mpm_Cut_t * pCut, Mpm_Cut_t * pCut0, int nLimit )
+{
+    int i, k;
+    for ( i = (int)pCut->nLeaves - 1, k = (int)pCut0->nLeaves - 1; i >= 0 && k >= 0; i-- )
+    {
+        if ( pCut0->pLeaves[k] < pCut->pLeaves[i] )
+            continue;
+        assert( pCut0->pLeaves[k] == pCut->pLeaves[i] );
+        if ( k < i )
+            Abc_TtSwapVars( pTruth, nLimit, k, i );
+        k--;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs truth table support minimization.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Mpm_CutTruthMinimize6( Mpm_Man_t * p, Mpm_Cut_t * pCut )
+{
+    unsigned uSupport;
+    int i, k, nSuppSize;
+    // compute the support of the cut's function
+    word t = *Mpm_CutTruth( p, Abc_Lit2Var(pCut->iFunc) );
+    uSupport = Abc_Tt6SupportAndSize( t, Mpm_CutLeafNum(pCut), &nSuppSize );
+    if ( nSuppSize == Mpm_CutLeafNum(pCut) )
+        return 0;
+    p->nSmallSupp += (int)(nSuppSize < 2);
+    // update leaves and signature
+    for ( i = k = 0; i < Mpm_CutLeafNum(pCut); i++ )
+    {
+        if ( ((uSupport >> i) & 1) )
+        {
+            if ( k < i )
+            {
+                pCut->pLeaves[k] = pCut->pLeaves[i];
+                Abc_TtSwapVars( &t, p->nLutSize, k, i );
+            }
+            k++;
+        }
+    }
+    assert( k == nSuppSize );
+    pCut->nLeaves = nSuppSize;
+    assert( nSuppSize == Abc_TtSupportSize(&t, 6) );
+    // save the result
+    pCut->iFunc = Abc_Var2Lit( Vec_MemHashInsert(p->vTtMem, &t), Abc_LitIsCompl(pCut->iFunc) );
+    return 1;
+}
+static inline int Mpm_CutTruthMinimize7( Mpm_Man_t * p, Mpm_Cut_t * pCut )
+{
+    unsigned uSupport;
+    int i, k, nSuppSize;
+    // compute the support of the cut's function
+    word * pTruth = Mpm_CutTruth( p, Abc_Lit2Var(pCut->iFunc) );
+    uSupport = Abc_TtSupportAndSize( pTruth, Mpm_CutLeafNum(pCut), &nSuppSize );
+    if ( nSuppSize == Mpm_CutLeafNum(pCut) )
+        return 0;
+    p->nSmallSupp += (int)(nSuppSize < 2);
+    // update leaves and signature
+    Abc_TtCopy( p->Truth, pTruth, p->nTruWords, 0 );
+    for ( i = k = 0; i < Mpm_CutLeafNum(pCut); i++ )
+    {
+        if ( ((uSupport >> i) & 1) )
+        {
+            if ( k < i )
+            {
+                pCut->pLeaves[k] = pCut->pLeaves[i];
+                Abc_TtSwapVars( p->Truth, p->nLutSize, k, i );
+            }
+            k++;
+        }
+    }
+    assert( k == nSuppSize );
+    assert( nSuppSize == Abc_TtSupportSize(p->Truth, Mpm_CutLeafNum(pCut)) );
+    pCut->nLeaves = nSuppSize;
+    // save the result
+    pCut->iFunc = Abc_Var2Lit( Vec_MemHashInsert(p->vTtMem, p->Truth), Abc_LitIsCompl(pCut->iFunc) );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs truth table computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Mpm_CutComputeTruth6( Mpm_Man_t * p, Mpm_Cut_t * pCut, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, int Type )
+{
+    word * pTruth0 = Mpm_CutTruth( p, Abc_Lit2Var(pCut0->iFunc) );
+    word * pTruth1 = Mpm_CutTruth( p, Abc_Lit2Var(pCut1->iFunc) );
+    word * pTruthC = NULL;
+    word t0 = (fCompl0 ^ pCut0->fCompl ^ Abc_LitIsCompl(pCut0->iFunc)) ? ~*pTruth0 : *pTruth0;
+    word t1 = (fCompl1 ^ pCut1->fCompl ^ Abc_LitIsCompl(pCut1->iFunc)) ? ~*pTruth1 : *pTruth1;
+    word tC = 0, t = 0;
+    Mpm_TruthStretch( &t0, pCut, pCut0, p->nLutSize );
+    Mpm_TruthStretch( &t1, pCut, pCut1, p->nLutSize );
+    if ( pCutC )
+    {
+        pTruthC = Mpm_CutTruth( p, Abc_Lit2Var(pCutC->iFunc) );
+        tC = (fComplC ^ pCutC->fCompl ^ Abc_LitIsCompl(pCutC->iFunc)) ? ~*pTruthC : *pTruthC;
+        Mpm_TruthStretch( &tC, pCut, pCutC, p->nLutSize );
+    }
+    assert( p->nLutSize <= 6 );
+    if ( Type == 1 )
+        t = t0 & t1;
+    else if ( Type == 2 )
+        t = t0 ^ t1;
+    else if ( Type == 3 )
+        t = (tC & t1) | (~tC & t0);
+    else assert( 0 );
+    // save the result
+    if ( t & 1 )
+    {
+        t = ~t;
+        pCut->iFunc = Abc_Var2Lit( Vec_MemHashInsert( p->vTtMem, &t ), 1 );
+    }
+    else
+        pCut->iFunc = Abc_Var2Lit( Vec_MemHashInsert( p->vTtMem, &t ), 0 );
+    if ( p->pPars->fCutMin )
+        return Mpm_CutTruthMinimize6( p, pCut );
+    return 1;
+}
+static inline int Mpm_CutComputeTruth7( Mpm_Man_t * p, Mpm_Cut_t * pCut, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, int Type )
+{
+    word * pTruth0 = Mpm_CutTruth( p, Abc_Lit2Var(pCut0->iFunc) );
+    word * pTruth1 = Mpm_CutTruth( p, Abc_Lit2Var(pCut1->iFunc) );
+    word * pTruthC = NULL;
+    Abc_TtCopy( p->Truth0, pTruth0, p->nTruWords, fCompl0 ^ pCut0->fCompl ^ Abc_LitIsCompl(pCut0->iFunc) );
+    Abc_TtCopy( p->Truth1, pTruth1, p->nTruWords, fCompl1 ^ pCut1->fCompl ^ Abc_LitIsCompl(pCut1->iFunc) );
+    Mpm_TruthStretch( p->Truth0, pCut, pCut0, p->nLutSize );
+    Mpm_TruthStretch( p->Truth1, pCut, pCut1, p->nLutSize );
+    if ( pCutC )
+    {
+        pTruthC = Mpm_CutTruth( p, Abc_Lit2Var(pCutC->iFunc) );
+        Abc_TtCopy( p->TruthC, pTruthC, p->nTruWords, fComplC ^ pCutC->fCompl ^ Abc_LitIsCompl(pCutC->iFunc) );
+        Mpm_TruthStretch( p->TruthC, pCut, pCutC, p->nLutSize );
+    }
+    if ( Type == 1 )
+        Abc_TtAnd( p->Truth, p->Truth0, p->Truth1, p->nTruWords, 0 );
+    else if ( Type == 2 )
+        Abc_TtXor( p->Truth, p->Truth0, p->Truth1, p->nTruWords, 0 );
+    else if ( Type == 3 )
+        Abc_TtMux( p->Truth, p->TruthC, p->Truth1, p->Truth0, p->nTruWords );
+    else assert( 0 );
+    // save the result
+    if ( p->Truth[0] & 1 )
+    {
+        Abc_TtNot( p->Truth, p->nTruWords );
+        pCut->iFunc = Abc_Var2Lit( Vec_MemHashInsert( p->vTtMem, p->Truth ), 1 );
+    }
+    else
+        pCut->iFunc = Abc_Var2Lit( Vec_MemHashInsert( p->vTtMem, p->Truth ), 0 );
+    if ( p->pPars->fCutMin )
+        return Mpm_CutTruthMinimize7( p, pCut );
+    return 1;
+}
+int Mpm_CutComputeTruth( Mpm_Man_t * p, Mpm_Cut_t * pCut, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, int Type )
+{
+    int RetValue;
+    if ( p->nLutSize <= 6 )
+        RetValue = Mpm_CutComputeTruth6( p, pCut, pCut0, pCut1, pCutC, fCompl0, fCompl1, fComplC, Type );
+    else
+        RetValue = Mpm_CutComputeTruth7( p, pCut, pCut0, pCut1, pCutC, fCompl0, fCompl1, fComplC, Type );
+#ifdef MPM_TRY_NEW
+    {
+        extern unsigned Abc_TtCanonicize( word * pTruth, int nVars, char * pCanonPerm );
+        char pCanonPerm[16];
+        memcpy( p->Truth0, p->Truth, sizeof(word) * p->nTruWords );
+        Abc_TtCanonicize( p->Truth0, pCut->nLimit, pCanonPerm );
+    }
+#endif
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/mpm/mpmUtil.c b/abc-build/src/map/mpm/mpmUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/mpm/mpmUtil.c
@@ -0,0 +1,52 @@
+/**CFile****************************************************************
+
+  FileName    [mpmUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Configurable technology mapper.]
+
+  Synopsis    [Various utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 1, 2013.]
+
+  Revision    [$Id: mpmUtil.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mpmInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/scl/module.make b/abc-build/src/map/scl/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/scl/module.make
@@ -0,0 +1,11 @@
+SRC +=  src/map/scl/scl.c \
+	src/map/scl/sclBuffer.c \
+	src/map/scl/sclBufSize.c \
+	src/map/scl/sclDnsize.c \
+	src/map/scl/sclLiberty.c \
+	src/map/scl/sclLibScl.c \
+	src/map/scl/sclLibUtil.c \
+	src/map/scl/sclLoad.c \
+	src/map/scl/sclSize.c \
+	src/map/scl/sclUpsize.c \
+	src/map/scl/sclUtil.c
diff --git a/abc-build/src/map/scl/scl.c b/abc-build/src/map/scl/scl.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/scl/scl.c
@@ -0,0 +1,1851 @@
+/**CFile****************************************************************
+
+  FileName    [scl.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Standard-cell library representation.]
+
+  Synopsis    [Relevant command handlers.]
+
+  Author      [Alan Mishchenko, Niklas Een]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 24, 2012.]
+
+  Revision    [$Id: scl.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sclSize.h"
+#include "base/main/mainInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Scl_CommandReadLib    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandWriteLib   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandReadScl    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandWriteScl   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandPrintLib   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandDumpGen    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandPrintGS    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandStime      ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandTopo       ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandUnBuffer   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandBuffer     ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandBufferOld  ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandMinsize    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandMaxsize    ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandUpsize     ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandDnsize     ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandPrintBuf   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandReadConstr ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandPrintConstr( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Scl_CommandResetConstr( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Updating library in the frameframe.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclLoad( SC_Lib * pLib, SC_Lib ** ppScl )
+{
+    if ( *ppScl )
+    {
+        Abc_SclLibFree( *ppScl );
+        *ppScl = NULL;
+    }
+    assert( *ppScl == NULL );
+    if ( pLib )
+        *(SC_Lib **)ppScl = pLib;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Scl_Init( Abc_Frame_t * pAbc )
+{
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "read_lib",      Scl_CommandReadLib,     0 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "write_lib",     Scl_CommandWriteLib,    0 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "print_lib",     Scl_CommandPrintLib,    0 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "read_scl",      Scl_CommandReadScl,     0 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "write_scl",     Scl_CommandWriteScl,    0 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "dump_genlib",   Scl_CommandDumpGen,     0 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "print_gs",      Scl_CommandPrintGS,     0 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "stime",         Scl_CommandStime,       0 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "topo",          Scl_CommandTopo,        1 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "unbuffer",      Scl_CommandUnBuffer,    1 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "buffer",        Scl_CommandBuffer,      1 ); 
+//    Cmd_CommandAdd( pAbc, "SCL mapping",  "_buffer",       Scl_CommandBufferOld,   1 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "minsize",       Scl_CommandMinsize,     1 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "maxsize",       Scl_CommandMaxsize,     1 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "upsize",        Scl_CommandUpsize,      1 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "dnsize",        Scl_CommandDnsize,      1 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "print_buf",     Scl_CommandPrintBuf,    0 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "read_constr",   Scl_CommandReadConstr,  0 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "print_constr",  Scl_CommandPrintConstr, 0 ); 
+    Cmd_CommandAdd( pAbc, "SCL mapping",  "reset_constr",  Scl_CommandResetConstr, 0 ); 
+}
+void Scl_End( Abc_Frame_t * pAbc )
+{
+    Abc_SclLoad( NULL, (SC_Lib **)&pAbc->pLibScl );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    char * pFileName;
+    FILE * pFile;
+    SC_Lib * pLib;
+    int c, fDump = 0;
+    float Slew = 0;
+    float Gain = 0;
+    int nGatesMin = 0;
+    int fVerbose = 1;
+    int fVeryVerbose = 0;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "SGMdvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            Slew = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Slew <= 0.0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            Gain = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Gain <= 0.0 )
+                goto usage;
+            break;
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nGatesMin = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nGatesMin < 0 ) 
+                goto usage;
+            break;
+        case 'd':
+            fDump ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'w':
+            fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    if ( (pFile = fopen( pFileName, "rb" )) == NULL )
+    {
+        fprintf( pAbc->Err, "Cannot open input file \"%s\". \n", pFileName );
+        return 1;
+    }
+    fclose( pFile );
+    // read new library
+    pLib = Abc_SclReadLiberty( pFileName, fVerbose, fVeryVerbose );
+    if ( pLib == NULL )
+    {
+        fprintf( pAbc->Err, "Reading SCL library from file \"%s\" has failed. \n", pFileName );
+        return 1;
+    }
+    if ( Abc_SclLibClassNum(pLib) < 3 )
+    {
+        fprintf( pAbc->Err, "Library with only %d cell classes cannot be used.\n", Abc_SclLibClassNum(pLib) );
+        Abc_SclLibFree(pLib);
+        return 0;
+    }
+    Abc_SclLoad( pLib, (SC_Lib **)&pAbc->pLibScl );
+    // dump the resulting library
+    if ( fDump && pAbc->pLibScl )
+        Abc_SclWriteLiberty( Extra_FileNameGenericAppend(pFileName, "_temp.lib"), (SC_Lib *)pAbc->pLibScl );
+    // extract genlib library
+    if ( pAbc->pLibScl )
+        Abc_SclInstallGenlib( pAbc->pLibScl, Slew, Gain, nGatesMin );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read_lib [-SG float] [-M num] [-dvwh] <file>\n" );
+    fprintf( pAbc->Err, "\t           reads Liberty library from file\n" );
+    fprintf( pAbc->Err, "\t-S float : the slew parameter used to generate the library [default = %.2f]\n", Slew );
+    fprintf( pAbc->Err, "\t-G float : the gain parameter used to generate the library [default = %.2f]\n", Gain );
+    fprintf( pAbc->Err, "\t-M num   : skip gate classes whose size is less than this [default = %d]\n", nGatesMin );
+    fprintf( pAbc->Err, "\t-d       : toggle dumping the parsed library into file \"*_temp.lib\" [default = %s]\n", fDump? "yes": "no" );
+    fprintf( pAbc->Err, "\t-v       : toggle writing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-v       : toggle writing information about skipped gates [default = %s]\n", fVeryVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h       : prints the command summary\n" );
+    fprintf( pAbc->Err, "\t<file>   : the name of a file to read\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandWriteLib( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    FILE * pFile;
+    char * pFileName;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    if ( pAbc->pLibScl == NULL )
+    {
+        fprintf( pAbc->Err, "There is no Liberty library available.\n" );
+        return 1;
+    }
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    if ( (pFile = fopen( pFileName, "wb" )) == NULL )
+    {
+        fprintf( pAbc->Err, "Cannot open output file \"%s\". \n", pFileName );
+        return 1;
+    }
+    fclose( pFile );
+
+    // save current library
+    Abc_SclWriteLiberty( pFileName, (SC_Lib *)pAbc->pLibScl );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_lib [-h] <file>\n" );
+    fprintf( pAbc->Err, "\t         write current Liberty library into file\n" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\t<file> : the name of the file to write\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandPrintLib( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    float Slew = 0; // use library
+    float Gain = 100;
+    int fInvOnly = 0;
+    int fShort = 0;
+    int c;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "SGish" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            Slew = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Slew <= 0.0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            Gain = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Gain <= 0.0 )
+                goto usage;
+            break;
+        case 'i':
+            fInvOnly ^= 1;
+            break;
+        case 's':
+            fShort ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pLibScl == NULL )
+    {
+        fprintf( pAbc->Err, "There is no Liberty library available.\n" );
+        return 1;
+    }
+
+    // save current library
+    Abc_SclPrintCells( (SC_Lib *)pAbc->pLibScl, Slew, Gain, fInvOnly, fShort );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: print_lib [-SG float] [-ish]\n" );
+    fprintf( pAbc->Err, "\t           prints statistics of Liberty library\n" );
+    fprintf( pAbc->Err, "\t-S float : the slew parameter used to generate the library [default = %.2f]\n", Slew );
+    fprintf( pAbc->Err, "\t-G float : the gain parameter used to generate the library [default = %.2f]\n", Gain );
+    fprintf( pAbc->Err, "\t-i       : toggle printing invs/bufs only [default = %s]\n", fInvOnly? "yes": "no" );
+    fprintf( pAbc->Err, "\t-s       : toggle printing in short format [default = %s]\n", fShort? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h       : print the help massage\n" );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandReadScl( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    FILE * pFile;
+    SC_Lib * pLib;
+    char * pFileName;
+    int c, fDump = 0;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'd':
+            fDump ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    if ( (pFile = fopen( pFileName, "rb" )) == NULL )
+    {
+        fprintf( pAbc->Err, "Cannot open input file \"%s\". \n", pFileName );
+        return 1;
+    }
+    fclose( pFile );
+
+    // read new library
+    pLib = Abc_SclReadFromFile( pFileName );
+    if ( pLib == NULL )
+    {
+        fprintf( pAbc->Err, "Reading SCL library from file \"%s\" has failed. \n", pFileName );
+        return 1;
+    }
+    Abc_SclLoad( pLib, (SC_Lib **)&pAbc->pLibScl );
+    if ( fDump )
+        Abc_SclWriteLiberty( Extra_FileNameGenericAppend(pFileName, "_temp.lib"), (SC_Lib *)pAbc->pLibScl );
+    // extract genlib library
+    if ( pAbc->pLibScl )
+        Abc_SclInstallGenlib( pAbc->pLibScl, 0, 0, 0 );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read_scl [-dh] <file>\n" );
+    fprintf( pAbc->Err, "\t         reads extracted Liberty library from file\n" );
+    fprintf( pAbc->Err, "\t-d     : toggle dumping the parsed library into file \"*_temp.lib\" [default = %s]\n", fDump? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\t<file> : the name of a file to read\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandWriteScl( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    FILE * pFile;
+    char * pFileName;
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+    if ( pAbc->pLibScl == NULL )
+    {
+        fprintf( pAbc->Err, "There is no Liberty library available.\n" );
+        return 1;
+    }
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    if ( (pFile = fopen( pFileName, "wb" )) == NULL )
+    {
+        fprintf( pAbc->Err, "Cannot open output file \"%s\". \n", pFileName );
+        return 1;
+    }
+    fclose( pFile );
+
+    // save current library
+    Abc_SclWriteScl( pFileName, (SC_Lib *)pAbc->pLibScl );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: write_scl [-h] <file>\n" );
+    fprintf( pAbc->Err, "\t         write extracted Liberty library into file\n" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    fprintf( pAbc->Err, "\t<file> : the name of the file to write\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandDumpGen( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    char * pFileName = NULL;
+    float Slew = 0; // use the library
+    float Gain = 200;
+    int nGatesMin = 4;
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "SGMvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            Slew = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Slew <= 0.0 )
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by a floating point number.\n" );
+                goto usage;
+            }
+            Gain = (float)atof(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( Gain <= 0.0 )
+                goto usage;
+            break;
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            nGatesMin = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( nGatesMin < 0 ) 
+                goto usage;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( pAbc->pLibScl == NULL )
+    {
+        fprintf( pAbc->Err, "There is no Liberty library available.\n" );
+        goto usage;
+    }
+    if ( argc == globalUtilOptind + 1 )
+        pFileName = argv[globalUtilOptind];
+    Abc_SclDumpGenlib( pFileName, (SC_Lib *)pAbc->pLibScl, Slew, Gain, nGatesMin );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: dump_genlib [-SG float] [-M num] [-vh] <file>\n" );
+    fprintf( pAbc->Err, "\t           writes GENLIB file for SCL library\n" );
+    fprintf( pAbc->Err, "\t-S float : the slew parameter used to generate the library [default = %.2f]\n", Slew );
+    fprintf( pAbc->Err, "\t-G float : the gain parameter used to generate the library [default = %.2f]\n", Gain );
+    fprintf( pAbc->Err, "\t-M num   : skip gate classes whose size is less than this [default = %d]\n", nGatesMin );
+    fprintf( pAbc->Err, "\t-v       : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h       : print the command usage\n");
+    fprintf( pAbc->Err, "\t<file>   : optional GENLIB file name\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandPrintGS( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    int c;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+    if ( Abc_FrameReadNtk(pAbc) == NULL )
+    {
+        fprintf( pAbc->Err, "There is no current network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkHasMapping(Abc_FrameReadNtk(pAbc)) )
+    {
+        fprintf( pAbc->Err, "The current network is not mapped.\n" );
+        return 1;
+    }
+    if ( pAbc->pLibScl == NULL )
+    {
+        fprintf( pAbc->Err, "There is no Liberty library available.\n" );
+        return 1;
+    }
+
+    // save current library
+    Abc_SclPrintGateSizes( (SC_Lib *)pAbc->pLibScl, Abc_FrameReadNtk(pAbc) );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: print_gs [-h]\n" );
+    fprintf( pAbc->Err, "\t         prints gate sizes in the current mapping\n" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandStime( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    int c;
+    int fShowAll      = 0;
+    int fUseWireLoads = 1;
+    int fPrintPath    = 0;
+    int fDumpStats    = 0;
+    int nTreeCRatio   = 0;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "Xcapdh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+            case 'X':
+                if ( globalUtilOptind >= argc )
+                {
+                    Abc_Print( -1, "Command line switch \"-X\" should be followed by a positive integer.\n" );
+                    goto usage;
+                }
+                nTreeCRatio = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( nTreeCRatio < 0 ) 
+                    goto usage;
+                break;
+            case 'c':
+                fUseWireLoads ^= 1;
+                break;
+            case 'a':
+                fShowAll ^= 1;
+                break;
+            case 'p':
+                fPrintPath ^= 1;
+                break;
+            case 'd':
+                fDumpStats ^= 1;
+                break;
+            case 'h':
+                goto usage;
+            default:
+                goto usage;
+        }
+    }
+
+    if ( Abc_FrameReadNtk(pAbc) == NULL )
+    {
+        fprintf( pAbc->Err, "There is no current network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkHasMapping(Abc_FrameReadNtk(pAbc)) )
+    {
+        fprintf( pAbc->Err, "The current network is not mapped.\n" );
+        return 1;
+    }
+    if ( !Abc_SclCheckNtk(Abc_FrameReadNtk(pAbc), 0) )
+    {
+        fprintf( pAbc->Err, "The current network is not in a topo order (run \"topo\").\n" );
+        return 1;
+    }
+    if ( pAbc->pLibScl == NULL )
+    {
+        fprintf( pAbc->Err, "There is no Liberty library available.\n" );
+        return 1;
+    }
+
+    Abc_SclTimePerform( (SC_Lib *)pAbc->pLibScl, Abc_FrameReadNtk(pAbc), nTreeCRatio, fUseWireLoads, fShowAll, fPrintPath, fDumpStats );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: stime [-X num] [-capdth]\n" );
+    fprintf( pAbc->Err, "\t         performs STA using Liberty library\n" );
+    fprintf( pAbc->Err, "\t-X     : min Cout/Cave ratio for tree estimations [default = %d]\n", nTreeCRatio );
+    fprintf( pAbc->Err, "\t-c     : toggle using wire-loads if specified [default = %s]\n", fUseWireLoads? "yes": "no" );
+    fprintf( pAbc->Err, "\t-a     : display timing information for all nodes [default = %s]\n", fShowAll? "yes": "no" );
+    fprintf( pAbc->Err, "\t-p     : display timing information for critical path [default = %s]\n", fPrintPath? "yes": "no" );
+    fprintf( pAbc->Err, "\t-d     : toggle dumping statistics into a file [default = %s]\n", fDumpStats? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h     : print the help massage\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandTopo( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Abc_Ntk_t * pNtkRes;
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "This command can only be applied to a logic network.\n" );
+        return 1;
+    }
+
+    // modify the current network
+    pNtkRes = Abc_NtkDupDfs( pNtk );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "The command has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: topo [-vh]\n" );
+    fprintf( pAbc->Err, "\t           rearranges nodes to be in a topological order\n" );
+    fprintf( pAbc->Err, "\t-v       : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h       : print the command usage\n");
+    return 1;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandUnBuffer( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    Abc_Ntk_t * pNtkRes, * pNtk = Abc_FrameReadNtk(pAbc);
+    int c, fRemInv = 0, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "ivh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'i':
+            fRemInv ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        fprintf( pAbc->Err, "There is no current network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        fprintf( pAbc->Err, "The current network is not a logic network.\n" );
+        return 1;
+    }
+    if ( fRemInv )
+        pNtkRes = Abc_SclUnBufferPhase( pNtk, fVerbose );
+    else
+        pNtkRes = Abc_SclUnBufferPerform( pNtk, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "The command has failed.\n" );
+        return 1;
+    }
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: unbuffer [-ivh]\n" );
+    fprintf( pAbc->Err, "\t           collapses buffer/inverter trees\n" );
+    fprintf( pAbc->Err, "\t-i       : toggle removing interters [default = %s]\n", fRemInv? "yes": "no" );
+    fprintf( pAbc->Err, "\t-v       : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandBuffer( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    SC_BusPars Pars, * pPars = &Pars;
+    Abc_Ntk_t * pNtkRes, * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    memset( pPars, 0, sizeof(SC_BusPars) );
+    pPars->GainRatio     =  300;
+    pPars->Slew          = pAbc->pLibScl ? Abc_SclComputeAverageSlew((SC_Lib *)pAbc->pLibScl) : 100;
+    pPars->nDegree       =   10;
+    pPars->fSizeOnly     =    0;
+    pPars->fAddBufs      =    1;
+    pPars->fBufPis       =    0;
+    pPars->fUseWireLoads =    1;
+    pPars->fVerbose      =    0;
+    pPars->fVeryVerbose  =    0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "GSNsbpcvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->GainRatio = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->GainRatio < 0 ) 
+                goto usage;
+            break;
+        case 'S':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-S\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->Slew = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->Slew < 0 ) 
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nDegree = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nDegree < 0 ) 
+                goto usage;
+            break;
+        case 's':
+            pPars->fSizeOnly ^= 1;
+            break;
+        case 'b':
+            pPars->fAddBufs ^= 1;
+            break;
+        case 'p':
+            pPars->fBufPis ^= 1;
+            break;
+        case 'c':
+            pPars->fUseWireLoads ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "This command can only be applied to a logic network.\n" );
+        return 1;
+    }
+    if ( !pPars->fSizeOnly && !pPars->fAddBufs && pNtk->vPhases == NULL )
+    {
+        Abc_Print( -1, "Fanin phase information is not avaiable.\n" );
+        return 1;
+    }
+    if ( !pAbc->pLibScl || !Abc_SclHasDelayInfo(pAbc->pLibScl) )
+    {
+        Abc_Print( -1, "Library delay info is not available.\n" );
+        return 1;
+    }
+    // modify the current network
+    pNtkRes = Abc_SclBufferingPerform( pNtk, (SC_Lib *)pAbc->pLibScl, pPars );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "The command has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: buffer [-GSN num] [-sbpcvwh]\n" );
+    fprintf( pAbc->Err, "\t           performs buffering and sizing and mapped network\n" );
+    fprintf( pAbc->Err, "\t-G <num> : target gain percentage [default = %d]\n", pPars->GainRatio );
+    fprintf( pAbc->Err, "\t-S <num> : target slew in pisoseconds [default = %d]\n", pPars->Slew );
+    fprintf( pAbc->Err, "\t-N <num> : the maximum fanout count [default = %d]\n", pPars->nDegree );
+    fprintf( pAbc->Err, "\t-s       : toggle performing only sizing [default = %s]\n", pPars->fSizeOnly? "yes": "no" );
+    fprintf( pAbc->Err, "\t-b       : toggle using buffers instead of inverters [default = %s]\n", pPars->fAddBufs? "yes": "no" );
+    fprintf( pAbc->Err, "\t-p       : toggle buffering primary inputs [default = %s]\n", pPars->fBufPis? "yes": "no" );
+    fprintf( pAbc->Err, "\t-c       : toggle using wire-loads if specified [default = %s]\n", pPars->fUseWireLoads? "yes": "no" );
+    fprintf( pAbc->Err, "\t-v       : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-w       : toggle printing more verbose information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h       : print the command usage\n");
+    return 1;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandBufferOld( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    Abc_Ntk_t * pNtkRes;
+    int FanMin, FanMax, FanMaxR, fAddInvs, fUseInvs, fBufPis, fSkipDup;
+    int c, fVerbose;
+    int fOldAlgo = 0;
+    FanMin   =  6;
+    FanMax   = 14;
+    FanMaxR  =  0;
+    fAddInvs =  0;
+    fUseInvs =  0;
+    fBufPis  =  0;
+    fSkipDup =  0;
+    fVerbose =  0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "NMRaixpdvh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            FanMin = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( FanMin < 0 ) 
+                goto usage;
+            break;
+        case 'M':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-M\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            FanMax = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( FanMax < 0 ) 
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            FanMaxR = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( FanMaxR < 0 ) 
+                goto usage;
+            break;
+        case 'a':
+            fOldAlgo ^= 1;
+            break;
+        case 'i':
+            fAddInvs ^= 1;
+            break;
+        case 'x':
+            fUseInvs ^= 1;
+            break;
+        case 'p':
+            fBufPis ^= 1;
+            break;
+        case 'd':
+            fSkipDup ^= 1;
+            break;
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        Abc_Print( -1, "Empty network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkIsLogic(pNtk) )
+    {
+        Abc_Print( -1, "This command can only be applied to a logic network.\n" );
+        return 1;
+    }
+    if ( fAddInvs && pNtk->vPhases == NULL )
+    {
+        Abc_Print( -1, "Fanin phase information is not avaiable.\n" );
+        return 1;
+    }
+    if ( !pAbc->pLibScl || !Abc_SclHasDelayInfo(pAbc->pLibScl) )
+    {
+        Abc_Print( -1, "Library delay info is not available.\n" );
+        return 1;
+    }
+
+    // modify the current network
+    if ( fAddInvs )
+        pNtkRes = Abc_SclBufferPhase( pNtk, fVerbose );
+    else if ( fOldAlgo )
+        pNtkRes = Abc_SclPerformBuffering( pNtk, FanMaxR, FanMax, fUseInvs, fVerbose );
+    else
+        pNtkRes = Abc_SclBufPerform( pNtk, FanMin, FanMax, fBufPis, fSkipDup, fVerbose );
+    if ( pNtkRes == NULL )
+    {
+        Abc_Print( -1, "The command has failed.\n" );
+        return 1;
+    }
+    // replace the current network
+    Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: _buffer [-NMR num] [-aixpdvh]\n" );
+    fprintf( pAbc->Err, "\t           performs buffering of the mapped network\n" );
+    fprintf( pAbc->Err, "\t-N <num> : the min fanout considered by the algorithm [default = %d]\n", FanMin );
+    fprintf( pAbc->Err, "\t-M <num> : the max allowed fanout count of node/buffer [default = %d]\n", FanMax );
+    fprintf( pAbc->Err, "\t-R <num> : the max allowed fanout count of root node [default = %d]\n", FanMaxR );
+    fprintf( pAbc->Err, "\t-a       : toggle using old algorithm [default = %s]\n", fOldAlgo? "yes": "no" );
+    fprintf( pAbc->Err, "\t-i       : toggle adding interters instead of buffering [default = %s]\n", fAddInvs? "yes": "no" );
+    fprintf( pAbc->Err, "\t-x       : toggle using interters instead of buffers [default = %s]\n", fUseInvs? "yes": "no" );
+    fprintf( pAbc->Err, "\t-p       : toggle buffering primary inputs [default = %s]\n", fBufPis? "yes": "no" );
+    fprintf( pAbc->Err, "\t-d       : toggle disabling gate duplication [default = %s]\n", fSkipDup? "yes": "no" );
+    fprintf( pAbc->Err, "\t-v       : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h       : print the command usage\n");
+    return 1;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandMinsize( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( Abc_FrameReadNtk(pAbc) == NULL )
+    {
+        fprintf( pAbc->Err, "There is no current network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkHasMapping(Abc_FrameReadNtk(pAbc)) )
+    {
+        fprintf( pAbc->Err, "The current network is not mapped.\n" );
+        return 1;
+    }
+    if ( !Abc_SclCheckNtk(Abc_FrameReadNtk(pAbc), 0) )
+    {
+        fprintf( pAbc->Err, "The current network is not in a topo order (run \"topo\").\n" );
+        return 1;
+    }
+    if ( pAbc->pLibScl == NULL )
+    {
+        fprintf( pAbc->Err, "There is no Liberty library available.\n" );
+        return 1;
+    }
+
+    Abc_SclMinsizePerform( (SC_Lib *)pAbc->pLibScl, pNtk, 0, fVerbose );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: minsize [-vh]\n" );
+    fprintf( pAbc->Err, "\t           downsizes all gates to their minimum size\n" );
+    fprintf( pAbc->Err, "\t-v       : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandMaxsize( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( Abc_FrameReadNtk(pAbc) == NULL )
+    {
+        fprintf( pAbc->Err, "There is no current network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkHasMapping(Abc_FrameReadNtk(pAbc)) )
+    {
+        fprintf( pAbc->Err, "The current network is not mapped.\n" );
+        return 1;
+    }
+    if ( !Abc_SclCheckNtk(Abc_FrameReadNtk(pAbc), 0) )
+    {
+        fprintf( pAbc->Err, "The current network is not in a topo order (run \"topo\").\n" );
+        return 1;
+    }
+    if ( pAbc->pLibScl == NULL )
+    {
+        fprintf( pAbc->Err, "There is no Liberty library available.\n" );
+        return 1;
+    }
+
+    Abc_SclMinsizePerform( (SC_Lib *)pAbc->pLibScl, pNtk, 1, fVerbose );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: maxsize [-vh]\n" );
+    fprintf( pAbc->Err, "\t           upsizes all gates to their maximum size\n" );
+    fprintf( pAbc->Err, "\t-v       : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandUpsize( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    SC_SizePars Pars, * pPars = &Pars;
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    memset( pPars, 0, sizeof(SC_SizePars) );
+    pPars->nIters        = 1000;
+    pPars->nIterNoChange =   50;
+    pPars->Window        =    1;
+    pPars->Ratio         =   10;
+    pPars->Notches       = 1000;
+    pPars->DelayUser     =    0;
+    pPars->DelayGap      =    0;
+    pPars->TimeOut       =    0;
+    pPars->BuffTreeEst   =    0;
+    pPars->BypassFreq    =    0;
+    pPars->fUseDept      =    1;
+    pPars->fUseWireLoads =    1;
+    pPars->fDumpStats    =    0;
+    pPars->fVerbose      =    0;
+    pPars->fVeryVerbose  =    0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "IJWRNDGTXBcsdvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nIters < 0 ) 
+                goto usage;
+            break;
+        case 'J':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-J\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nIterNoChange = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nIterNoChange < 0 ) 
+                goto usage;
+            break;
+        case 'W':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-W\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->Window = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->Window < 0 ) 
+                goto usage;
+            break;
+        case 'R':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-R\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->Ratio = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->Ratio < 0 ) 
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->Notches = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->Notches < 0 ) 
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->DelayUser = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->DelayUser < 0 ) 
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->DelayGap = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->TimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeOut < 0 ) 
+                goto usage;
+            break;
+        case 'X':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-X\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->BuffTreeEst = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->BuffTreeEst < 0 ) 
+                goto usage;
+            break;
+        case 'B':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-B\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->BypassFreq = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->BypassFreq < 0 ) 
+                goto usage;
+            break;
+        case 'c':
+            pPars->fUseWireLoads ^= 1;
+            break;
+        case 's':
+            pPars->fUseDept ^= 1;
+            break;
+        case 'd':
+            pPars->fDumpStats ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( Abc_FrameReadNtk(pAbc) == NULL )
+    {
+        fprintf( pAbc->Err, "There is no current network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkHasMapping(Abc_FrameReadNtk(pAbc)) )
+    {
+        fprintf( pAbc->Err, "The current network is not mapped.\n" );
+        return 1;
+    }
+    if ( !Abc_SclCheckNtk(Abc_FrameReadNtk(pAbc), 0) )
+    {
+        fprintf( pAbc->Err, "The current network is not in a topo order (run \"topo\").\n" );
+        return 1;
+    }
+    if ( !pAbc->pLibScl || !Abc_SclHasDelayInfo(pAbc->pLibScl) )
+    {
+        Abc_Print( -1, "Library delay info is not available.\n" );
+        return 1;
+    }
+
+    Abc_SclUpsizePerform( (SC_Lib *)pAbc->pLibScl, pNtk, pPars );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: upsize [-IJWRNDGTXB num] [-csdvwh]\n" );
+    fprintf( pAbc->Err, "\t           selectively increases gate sizes on the critical path\n" );
+    fprintf( pAbc->Err, "\t-I <num> : the number of upsizing iterations to perform [default = %d]\n", pPars->nIters );
+    fprintf( pAbc->Err, "\t-J <num> : the number of iterations without improvement to stop [default = %d]\n", pPars->nIterNoChange );
+    fprintf( pAbc->Err, "\t-W <num> : delay window (in percent) of near-critical COs [default = %d]\n", pPars->Window );
+    fprintf( pAbc->Err, "\t-R <num> : ratio of critical nodes (in percent) to update [default = %d]\n", pPars->Ratio );
+    fprintf( pAbc->Err, "\t-N <num> : limit on discrete upsizing steps at a node [default = %d]\n", pPars->Notches );
+    fprintf( pAbc->Err, "\t-D <num> : delay target set by the user, in picoseconds [default = %d]\n", pPars->DelayUser );
+    fprintf( pAbc->Err, "\t-G <num> : delay gap during updating, in picoseconds [default = %d]\n", pPars->DelayGap );
+    fprintf( pAbc->Err, "\t-T <num> : approximate timeout in seconds [default = %d]\n", pPars->TimeOut );
+    fprintf( pAbc->Err, "\t-X <num> : ratio for buffer tree estimation [default = %d]\n", pPars->BuffTreeEst );
+    fprintf( pAbc->Err, "\t-B <num> : frequency of bypass transforms [default = %d]\n", pPars->BypassFreq );
+    fprintf( pAbc->Err, "\t-c       : toggle using wire-loads if specified [default = %s]\n", pPars->fUseWireLoads? "yes": "no" );
+    fprintf( pAbc->Err, "\t-s       : toggle using slack based on departure times [default = %s]\n", pPars->fUseDept? "yes": "no" );
+    fprintf( pAbc->Err, "\t-d       : toggle dumping statistics into a file [default = %s]\n", pPars->fDumpStats? "yes": "no" );
+    fprintf( pAbc->Err, "\t-v       : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-w       : toggle printing more verbose information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandDnsize( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    SC_SizePars Pars, * pPars = &Pars;
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c;
+    memset( pPars, 0, sizeof(SC_SizePars) );
+    pPars->nIters        =    5;
+    pPars->nIterNoChange =   50;
+    pPars->Notches       = 1000;
+    pPars->DelayUser     =    0;
+    pPars->DelayGap      = 1000;
+    pPars->TimeOut       =    0;
+    pPars->BuffTreeEst   =    0;
+    pPars->fUseDept      =    1;
+    pPars->fUseWireLoads =    1;
+    pPars->fDumpStats    =    0;
+    pPars->fVerbose      =    0;
+    pPars->fVeryVerbose  =    0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "IJNDGTXcsdvwh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'I':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nIters = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nIters < 0 ) 
+                goto usage;
+            break;
+        case 'J':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-J\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->nIterNoChange = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->nIterNoChange < 0 ) 
+                goto usage;
+            break;
+        case 'N':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->Notches = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->Notches < 0 ) 
+                goto usage;
+            break;
+        case 'D':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->DelayUser = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->DelayUser < 0 ) 
+                goto usage;
+            break;
+        case 'G':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-G\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->DelayGap = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            break;
+        case 'T':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-T\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->TimeOut = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->TimeOut < 0 ) 
+                goto usage;
+            break;
+        case 'X':
+            if ( globalUtilOptind >= argc )
+            {
+                Abc_Print( -1, "Command line switch \"-X\" should be followed by a positive integer.\n" );
+                goto usage;
+            }
+            pPars->BuffTreeEst = atoi(argv[globalUtilOptind]);
+            globalUtilOptind++;
+            if ( pPars->BuffTreeEst < 0 ) 
+                goto usage;
+            break;
+        case 'c':
+            pPars->fUseWireLoads ^= 1;
+            break;
+        case 's':
+            pPars->fUseDept ^= 1;
+            break;
+        case 'd':
+            pPars->fDumpStats ^= 1;
+            break;
+        case 'v':
+            pPars->fVerbose ^= 1;
+            break;
+        case 'w':
+            pPars->fVeryVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( Abc_FrameReadNtk(pAbc) == NULL )
+    {
+        fprintf( pAbc->Err, "There is no current network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkHasMapping(Abc_FrameReadNtk(pAbc)) )
+    {
+        fprintf( pAbc->Err, "The current network is not mapped.\n" );
+        return 1;
+    }
+    if ( !Abc_SclCheckNtk(Abc_FrameReadNtk(pAbc), 0) )
+    {
+        fprintf( pAbc->Err, "The current network is not in a topo order (run \"topo\").\n" );
+        return 1;
+    }
+    if ( !pAbc->pLibScl || !Abc_SclHasDelayInfo(pAbc->pLibScl) )
+    {
+        Abc_Print( -1, "Library delay info is not available.\n" );
+        return 1;
+    }
+
+    Abc_SclDnsizePerform( (SC_Lib *)pAbc->pLibScl, pNtk, pPars );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: dnsize [-IJNDGTX num] [-csdvwh]\n" );
+    fprintf( pAbc->Err, "\t           selectively decreases gate sizes while maintaining delay\n" );
+    fprintf( pAbc->Err, "\t-I <num> : the number of upsizing iterations to perform [default = %d]\n", pPars->nIters );
+    fprintf( pAbc->Err, "\t-J <num> : the number of iterations without improvement to stop [default = %d]\n", pPars->nIterNoChange );
+    fprintf( pAbc->Err, "\t-N <num> : limit on discrete upsizing steps at a node [default = %d]\n", pPars->Notches );
+    fprintf( pAbc->Err, "\t-D <num> : delay target set by the user, in picoseconds [default = %d]\n", pPars->DelayUser );
+    fprintf( pAbc->Err, "\t-G <num> : delay gap during updating, in picoseconds [default = %d]\n", pPars->DelayGap );
+    fprintf( pAbc->Err, "\t-T <num> : approximate timeout in seconds [default = %d]\n", pPars->TimeOut );
+    fprintf( pAbc->Err, "\t-X <num> : ratio for buffer tree estimation [default = %d]\n", pPars->BuffTreeEst );
+    fprintf( pAbc->Err, "\t-c       : toggle using wire-loads if specified [default = %s]\n", pPars->fUseWireLoads? "yes": "no" );
+    fprintf( pAbc->Err, "\t-s       : toggle using slack based on departure times [default = %s]\n", pPars->fUseDept? "yes": "no" );
+    fprintf( pAbc->Err, "\t-d       : toggle dumping statistics into a file [default = %s]\n", pPars->fDumpStats? "yes": "no" );
+    fprintf( pAbc->Err, "\t-v       : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-w       : toggle printing more verbose information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandPrintBuf( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( Abc_FrameReadNtk(pAbc) == NULL )
+    {
+        fprintf( pAbc->Err, "There is no current network.\n" );
+        return 1;
+    }
+    if ( !Abc_NtkHasMapping(Abc_FrameReadNtk(pAbc)) )
+    {
+        fprintf( pAbc->Err, "The current network is not mapped.\n" );
+        return 1;
+    }
+    if ( !Abc_SclCheckNtk(Abc_FrameReadNtk(pAbc), 0) )
+    {
+        fprintf( pAbc->Err, "The current network is not in a topo order (run \"topo\").\n" );
+        return 1;
+    }
+    if ( !pAbc->pLibScl || !Abc_SclHasDelayInfo(pAbc->pLibScl) )
+    {
+        Abc_Print( -1, "Library delay info is not available.\n" );
+        return 1;
+    }
+
+    Abc_SclPrintBuffers( (SC_Lib *)pAbc->pLibScl, pNtk, fVerbose );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: print_buf [-vh]\n" );
+    fprintf( pAbc->Err, "\t           prints buffers trees of the current design\n" );
+    fprintf( pAbc->Err, "\t-v       : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h       : print the command usage\n");
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandReadConstr( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    extern void Abc_SclReadTimingConstr( Abc_Frame_t * pAbc, char * pFileName, int fVerbose );
+    FILE * pFile;
+    char * pFileName;
+    int c, fVerbose = 0;
+
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    if ( argc != globalUtilOptind + 1 )
+        goto usage;
+
+    // get the input file name
+    pFileName = argv[globalUtilOptind];
+    if ( (pFile = fopen( pFileName, "rb" )) == NULL )
+    {
+        fprintf( pAbc->Err, "Cannot open input file \"%s\". \n", pFileName );
+        return 1;
+    }
+    fclose( pFile );
+    Abc_SclReadTimingConstr( pAbc, pFileName, fVerbose );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: read_constr [-vh] <file>\n" );
+    fprintf( pAbc->Err, "\t         read file with timing constraints for standard-cell designs\n" );
+    fprintf( pAbc->Err, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\t<file> : the name of a file to read\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandPrintConstr( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    printf( "Primary input driving cell = %s\n", Abc_FrameReadDrivingCell() );
+    printf( "Primary output maximum load = %f\n", Abc_FrameReadMaxLoad() );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: print_constr [-vh] <file>\n" );
+    fprintf( pAbc->Err, "\t         prints current timing constraints\n" );
+    fprintf( pAbc->Err, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\t<file> : the name of a file to read\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_CommandResetConstr( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    int c, fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'v':
+            fVerbose ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+    Abc_FrameSetDrivingCell( NULL );
+    Abc_FrameSetMaxLoad( 0 );
+    return 0;
+
+usage:
+    fprintf( pAbc->Err, "usage: reset_constr [-vh] <file>\n" );
+    fprintf( pAbc->Err, "\t         removes current timing constraints\n" );
+    fprintf( pAbc->Err, "\t-v     : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+    fprintf( pAbc->Err, "\t-h     : prints the command summary\n" );
+    fprintf( pAbc->Err, "\t<file> : the name of a file to read\n" );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/scl/scl.h b/abc-build/src/map/scl/scl.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/scl/scl.h
@@ -0,0 +1,58 @@
+/**CFile****************************************************************
+
+  FileName    [scl.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Standard-cell library representation.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko, Niklas Een]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 24, 2012.]
+
+  Revision    [$Id: scl.h,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__map__scl__scl_h
+#define ABC__map__scl__scl_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_END
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/map/scl/sclBufSize.c b/abc-build/src/map/scl/sclBufSize.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/scl/sclBufSize.c
@@ -0,0 +1,505 @@
+/**CFile****************************************************************
+
+  FileName    [sclBufSize.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Standard-cell library representation.]
+
+  Synopsis    [Buffering and sizing combined.]
+
+  Author      [Alan Mishchenko, Niklas Een]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 24, 2012.]
+
+  Revision    [$Id: sclBufSize.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sclSize.h"
+#include "map/mio/mio.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Bus_Man_t_ Bus_Man_t;
+struct Bus_Man_t_
+{
+    // user data
+    SC_BusPars *   pPars;      // parameters    
+    Abc_Ntk_t *    pNtk;       // user's network
+    SC_Cell *      pPiDrive;   // PI driver
+    // library
+    SC_Lib *       pLib;       // cell library
+    SC_Cell *      pInv;       // base interter (largest/average/???)
+    SC_WireLoad *  pWLoadUsed; // name of the used WireLoad model
+    Vec_Flt_t *    vWireCaps;  // estimated wire loads
+    // internal
+    Vec_Flt_t *    vCins;      // input cap for fanouts
+    Vec_Flt_t *    vETimes;    // fanout edge departures
+    Vec_Flt_t *    vLoads;     // loads for all nodes
+    Vec_Flt_t *    vDepts;     // departure times
+    Vec_Ptr_t *    vFanouts;   // fanout array
+};
+
+
+static inline Bus_Man_t * Bus_SclObjMan( Abc_Obj_t * p )                     { return (Bus_Man_t *)p->pNtk->pBSMan;                                  }
+static inline float       Bus_SclObjCin( Abc_Obj_t * p )                     { return Vec_FltEntry( Bus_SclObjMan(p)->vCins, Abc_ObjId(p) );         }
+static inline void        Bus_SclObjSetCin( Abc_Obj_t * p, float cap )       { Vec_FltWriteEntry( Bus_SclObjMan(p)->vCins, Abc_ObjId(p), cap );      }
+static inline float       Bus_SclObjETime( Abc_Obj_t * p )                   { return Vec_FltEntry( Bus_SclObjMan(p)->vETimes, Abc_ObjId(p) );       }
+static inline void        Bus_SclObjSetETime( Abc_Obj_t * p, float time )    { Vec_FltWriteEntry( Bus_SclObjMan(p)->vETimes, Abc_ObjId(p), time );   }
+static inline float       Bus_SclObjLoad( Abc_Obj_t * p )                    { return Vec_FltEntry( Bus_SclObjMan(p)->vLoads, Abc_ObjId(p) );        }
+static inline void        Bus_SclObjSetLoad( Abc_Obj_t * p, float cap )      { Vec_FltWriteEntry( Bus_SclObjMan(p)->vLoads, Abc_ObjId(p), cap );     }
+static inline float       Bus_SclObjDept( Abc_Obj_t * p )                    { return Vec_FltEntry( Bus_SclObjMan(p)->vDepts, Abc_ObjId(p) );        }
+static inline void        Bus_SclObjUpdateDept( Abc_Obj_t * p, float time )  { float *q = Vec_FltEntryP( Bus_SclObjMan(p)->vDepts, Abc_ObjId(p) ); if (*q < time) *q = time;  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bus_Man_t * Bus_ManStart( Abc_Ntk_t * pNtk, SC_Lib * pLib, SC_BusPars * pPars )
+{
+    Bus_Man_t * p;
+    p = ABC_CALLOC( Bus_Man_t, 1 );
+    p->pPars     = pPars;
+    p->pNtk      = pNtk;
+    p->pLib      = pLib;
+    p->pInv      = Abc_SclFindInvertor(pLib, pPars->fAddBufs)->pRepr->pPrev;//->pAve;
+    if ( pPars->fUseWireLoads )
+    { 
+        if ( pNtk->pWLoadUsed == NULL )
+        {            
+            p->pWLoadUsed = Abc_SclFindWireLoadModel( pLib, Abc_SclGetTotalArea(pNtk) );
+            if ( p->pWLoadUsed )
+            pNtk->pWLoadUsed = Abc_UtilStrsav( p->pWLoadUsed->pName );
+        }
+        else
+            p->pWLoadUsed = Abc_SclFetchWireLoadModel( pLib, pNtk->pWLoadUsed );
+    }
+    if ( p->pWLoadUsed )
+    p->vWireCaps = Abc_SclFindWireCaps( p->pWLoadUsed, Abc_NtkGetFanoutMax(pNtk) );
+    p->vFanouts  = Vec_PtrAlloc( 100 );
+    p->vCins     = Vec_FltAlloc( 2*Abc_NtkObjNumMax(pNtk) + 1000 );
+    p->vETimes   = Vec_FltAlloc( 2*Abc_NtkObjNumMax(pNtk) + 1000 );
+    p->vLoads    = Vec_FltAlloc( 2*Abc_NtkObjNumMax(pNtk) + 1000 );
+    p->vDepts    = Vec_FltAlloc( 2*Abc_NtkObjNumMax(pNtk) + 1000 );
+    Vec_FltFill( p->vCins,   Abc_NtkObjNumMax(pNtk), 0 );
+    Vec_FltFill( p->vETimes, Abc_NtkObjNumMax(pNtk), 0 );
+    Vec_FltFill( p->vLoads,  Abc_NtkObjNumMax(pNtk), 0 );
+    Vec_FltFill( p->vDepts,  Abc_NtkObjNumMax(pNtk), 0 );
+    pNtk->pBSMan = p;
+    return p;
+}
+void Bus_ManStop( Bus_Man_t * p )
+{
+    Vec_PtrFreeP( &p->vFanouts );
+    Vec_FltFreeP( &p->vWireCaps );
+    Vec_FltFreeP( &p->vCins );
+    Vec_FltFreeP( &p->vETimes );
+    Vec_FltFreeP( &p->vLoads );
+    Vec_FltFreeP( &p->vDepts );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bus_ManReadInOutLoads( Bus_Man_t * p )
+{
+    if ( Abc_FrameReadMaxLoad() )
+    {
+        Abc_Obj_t * pObj; int i;
+        float MaxLoad = Abc_FrameReadMaxLoad();
+        Abc_NtkForEachCo( p->pNtk, pObj, i )
+            Bus_SclObjSetCin( pObj, MaxLoad );
+//        printf( "Default output load is specified (%f ff).\n", MaxLoad );
+    }
+    if ( Abc_FrameReadDrivingCell() )
+    {
+        int iCell = Abc_SclCellFind( p->pLib, Abc_FrameReadDrivingCell() );
+        if ( iCell == -1 )
+            printf( "Cannot find the default PI driving cell (%s) in the library.\n", Abc_FrameReadDrivingCell() );
+        else
+        {
+//            printf( "Default PI driving cell is specified (%s).\n", Abc_FrameReadDrivingCell() );
+            p->pPiDrive = SC_LibCell( p->pLib, iCell );
+            assert( p->pPiDrive != NULL );
+            assert( p->pPiDrive->n_inputs == 1 );
+//            printf( "Default input driving cell is specified (%s).\n", p->pPiDrive->pName );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute load and departure times of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline float Abc_NtkComputeEdgeDept( Abc_Obj_t * pFanout, int iFanin, float Slew )
+{
+    float Load = Bus_SclObjLoad( pFanout );
+    float Dept = Bus_SclObjDept( pFanout );
+    float Edge = Scl_LibPinArrivalEstimate( Abc_SclObjCell(pFanout), iFanin, Slew, Load );
+//if ( Abc_ObjFaninNum(pFanout) == 0 )
+//printf( "Edge = %.2f\n", Edge );
+    assert( Edge > 0 );
+    return Dept + Edge;
+}
+float Abc_NtkComputeNodeDeparture( Abc_Obj_t * pObj, float Slew )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    assert( Bus_SclObjDept(pObj) == 0 );
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        if ( !Abc_ObjIsCo(pFanout) ) // add required times here
+            Bus_SclObjUpdateDept( pObj, Abc_NtkComputeEdgeDept(pFanout, Abc_NodeFindFanin(pFanout, pObj), Slew) );
+    return Bus_SclObjDept( pObj );
+}
+void Abc_NtkComputeFanoutInfo( Abc_Obj_t * pObj, float Slew )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        if ( !Abc_ObjIsCo(pFanout) )
+        {
+            int iFanin = Abc_NodeFindFanin(pFanout, pObj);
+            Bus_SclObjSetETime( pFanout, Abc_NtkComputeEdgeDept(pFanout, iFanin, Slew) );
+            Bus_SclObjSetCin( pFanout, SC_CellPinCap( Abc_SclObjCell(pFanout), iFanin ) );
+        }
+}
+float Abc_NtkComputeNodeLoad( Bus_Man_t * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    float Load;
+    int i;
+    assert( Bus_SclObjLoad(pObj) == 0 );
+    Load = Abc_SclFindWireLoad( p->vWireCaps, Abc_ObjFanoutNum(pObj) );
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        Load += Bus_SclObjCin( pFanout );
+    Bus_SclObjSetLoad( pObj, Load );
+    return Load;
+}
+float Abc_NtkComputeFanoutLoad( Bus_Man_t * p, Vec_Ptr_t * vFanouts )
+{
+    Abc_Obj_t * pFanout;
+    float Load;
+    int i;
+    Load = Abc_SclFindWireLoad( p->vWireCaps, Vec_PtrSize(vFanouts) );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i )
+        Load += Bus_SclObjCin( pFanout );
+    return Load;
+}
+void Abc_NtkPrintFanoutProfile( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    printf( "Obj %6d fanouts (%d):\n", Abc_ObjId(pObj), Abc_ObjFanoutNum(pObj) );
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+    {
+        printf( "%3d : time = %7.2f ps   load = %7.2f ff  ", i, Bus_SclObjETime(pFanout), Bus_SclObjCin(pFanout) );
+        printf( "%s\n", Abc_ObjFaninPhase( pFanout, Abc_NodeFindFanin(pFanout, pObj) ) ? "*" : " " );
+    }
+    printf( "\n" );
+}
+void Abc_NtkPrintFanoutProfileVec( Abc_Obj_t * pObj, Vec_Ptr_t * vFanouts )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    printf( "Fanout profile (%d):\n", Vec_PtrSize(vFanouts) );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i )
+    {
+        printf( "%3d : time = %7.2f ps   load = %7.2f ff  ", i, Bus_SclObjETime(pFanout), Bus_SclObjCin(pFanout) );
+        if ( pObj->pNtk->vPhases )
+            printf( "%s", (pObj && Abc_ObjFanoutNum(pObj) == Vec_PtrSize(vFanouts) && Abc_ObjFaninPhase( pFanout, Abc_NodeFindFanin(pFanout, pObj) )) ? "*" : " " );
+        printf( "\n" );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compare two fanouts by their departure times.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bus_SclCompareFanouts( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 )
+{
+    float Espilon = 0;//10; // 10 ps
+    if ( Bus_SclObjETime(*pp1) < Bus_SclObjETime(*pp2) - Espilon )
+        return -1;
+    if ( Bus_SclObjETime(*pp1) > Bus_SclObjETime(*pp2) + Espilon )
+        return 1;
+    if ( Bus_SclObjCin(*pp1) > Bus_SclObjCin(*pp2) )
+        return -1;
+    if ( Bus_SclObjCin(*pp1) < Bus_SclObjCin(*pp2) )
+        return 1;
+    return -1;
+}
+void Bus_SclInsertFanout( Vec_Ptr_t * vFanouts, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pCur;
+    int i, k;
+    // compact array
+    for ( i = k = 0; i < Vec_PtrSize(vFanouts); i++ )
+        if ( Vec_PtrEntry(vFanouts, i) != NULL )
+            Vec_PtrWriteEntry( vFanouts, k++, Vec_PtrEntry(vFanouts, i) );
+    Vec_PtrShrink( vFanouts, k );
+    // insert new entry
+    Vec_PtrPush( vFanouts, pObj );
+    for ( i = Vec_PtrSize(vFanouts) - 1; i > 0; i-- )
+    {
+        pCur = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, i-1);
+        pObj = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, i);
+        if ( Bus_SclCompareFanouts( &pCur, &pObj ) == -1 )
+            break;
+        ABC_SWAP( void *, Vec_PtrArray(vFanouts)[i-1], Vec_PtrArray(vFanouts)[i] );
+    }
+}
+void Bus_SclCheckSortedFanout( Vec_Ptr_t * vFanouts )
+{
+    Abc_Obj_t * pObj, * pNext;
+    int i;
+    for ( i = 0; i < Vec_PtrSize(vFanouts) - 1; i++ )
+    {
+        pObj  = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, i);
+        pNext = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, i+1);
+        if ( Bus_SclCompareFanouts( &pObj, &pNext ) != -1 )
+        {
+            printf( "Fanouts %d and %d are out of order.\n", i, i+1 );
+            Abc_NtkPrintFanoutProfileVec( NULL, vFanouts );
+            return;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclOneNodePrint( Bus_Man_t * p, Abc_Obj_t * pObj )
+{
+    SC_Cell * pCell = Abc_SclObjCell(pObj);
+    printf( "%s%7d :  ",        (Abc_ObjFaninNum(pObj) == 0) ? " Inv" : "Node", Abc_ObjId(pObj) );
+    printf( "%d/%2d   ",        Abc_ObjFaninNum(pObj) ? Abc_ObjFaninNum(pObj) : 1, Abc_ObjFanoutNum(pObj) );
+    printf( "%12s ",            pCell->pName );
+    printf( "(%2d/%2d)  ",      pCell->Order, pCell->nGates );
+    printf( "gain =%5d  ",      (int)(100.0 * Bus_SclObjLoad(pObj) / SC_CellPinCapAve(pCell)) );
+    printf( "dept =%7.0f ps  ", Bus_SclObjDept(pObj) );
+    printf( "\n" );
+}
+Abc_Obj_t * Abc_SclAddOneInv( Bus_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vFanouts, float Gain )
+{
+    SC_Cell * pCellNew;
+    Abc_Obj_t * pFanout, * pInv;
+    float Target = SC_CellPinCap(p->pInv, 0) * Gain;
+    float LoadWirePrev, LoadWireThis, LoadNew, Load = 0;
+    int Limit = Abc_MinInt( p->pPars->nDegree, Vec_PtrSize(vFanouts) );
+    int i, iStop;
+    Bus_SclCheckSortedFanout( vFanouts );
+    Vec_PtrForEachEntryStop( Abc_Obj_t *, vFanouts, pFanout, iStop, Limit )
+    {
+        LoadWirePrev = Abc_SclFindWireLoad( p->vWireCaps, iStop );
+        LoadWireThis = Abc_SclFindWireLoad( p->vWireCaps, iStop+1 );
+        Load += Bus_SclObjCin( pFanout ) - LoadWirePrev + LoadWireThis;
+        if ( Load > Target )
+        {
+            iStop++;
+            break;
+        }
+    }
+    // create inverter
+    if ( p->pPars->fAddBufs )
+        pInv = Abc_NtkCreateNodeBuf( p->pNtk, NULL );
+    else
+        pInv = Abc_NtkCreateNodeInv( p->pNtk, NULL );
+    assert( (int)Abc_ObjId(pInv) == Vec_FltSize(p->vCins) );
+    Vec_FltPush( p->vCins,   0 );
+    Vec_FltPush( p->vETimes, 0 );
+    Vec_FltPush( p->vLoads,  0 );
+    Vec_FltPush( p->vDepts,  0 );
+    Limit = Abc_MinInt( Abc_MaxInt(iStop, 2), Vec_PtrSize(vFanouts) );
+    Vec_PtrForEachEntryStop( Abc_Obj_t *, vFanouts, pFanout, i, Limit )
+    {
+        Vec_PtrWriteEntry( vFanouts, i, NULL );
+        if ( Abc_ObjFaninNum(pFanout) == 0 )
+            Abc_ObjAddFanin( pFanout, pInv );
+        else
+            Abc_ObjPatchFanin( pFanout, pObj, pInv );
+    }
+    // set the gate
+    pCellNew = Abc_SclFindSmallestGate( p->pInv, Load / Gain );
+    Vec_IntSetEntry( p->pNtk->vGates, Abc_ObjId(pInv), pCellNew->Id );
+    // set departure and load
+    Abc_NtkComputeNodeDeparture( pInv, p->pPars->Slew );
+    LoadNew = Abc_NtkComputeNodeLoad( p, pInv );
+    assert( LoadNew - Load < 1 && Load - LoadNew < 1 );
+    // set fanout info for the inverter
+    Bus_SclObjSetCin( pInv, SC_CellPinCap(pCellNew, 0) );
+    Bus_SclObjSetETime( pInv, Abc_NtkComputeEdgeDept(pInv, 0, p->pPars->Slew) );
+    // update phases
+    if ( p->pNtk->vPhases && Abc_SclIsInv(pInv) )
+        Abc_NodeInvUpdateFanPolarity( pInv );
+    return pInv;
+}
+void Abc_SclBufSize( Bus_Man_t * p, float Gain )
+{
+    SC_Cell * pCell, * pCellNew;
+    Abc_Obj_t * pObj, * pFanout;
+    abctime clk = Abc_Clock();
+    int i, k, nObjsOld = Abc_NtkObjNumMax(p->pNtk);
+    float GainGate, GainInv, Load, LoadNew, Cin, DeptMax = 0;
+    GainGate = p->pPars->fAddBufs ? pow( Gain, 2.0 ) : Gain;
+    GainInv  = p->pPars->fAddBufs ? pow( Gain, 2.0 ) : Gain;
+    Abc_NtkForEachObjReverse( p->pNtk, pObj, i )
+    {
+        if ( !((Abc_ObjIsNode(pObj) && Abc_ObjFaninNum(pObj) > 0) || (Abc_ObjIsCi(pObj) && p->pPiDrive)) )
+            continue;
+        if ( 2 * nObjsOld < Abc_NtkObjNumMax(p->pNtk) )
+        {
+            printf( "Buffering could not be completed because the gain value (%d) is too low.\n", p->pPars->GainRatio );
+            break;
+        }
+        // compute load
+        Abc_NtkComputeFanoutInfo( pObj, p->pPars->Slew );
+        Load = Abc_NtkComputeNodeLoad( p, pObj );
+        // consider the gate
+        if ( Abc_ObjIsCi(pObj) )
+        {
+            pCell = p->pPiDrive;
+            Cin = SC_CellPinCapAve( pCell );
+        }
+        else
+        {
+            pCell = Abc_SclObjCell( pObj );
+            Cin = SC_CellPinCapAve( pCell->pAve );
+//        Cin = SC_CellPinCapAve( pCell->pRepr->pNext );
+        }
+        // consider upsizing the gate
+        if ( !p->pPars->fSizeOnly && (Abc_ObjFanoutNum(pObj) > p->pPars->nDegree || Load > GainGate * Cin) )
+        {
+            // add one or more inverters
+//            Abc_NtkPrintFanoutProfile( pObj );
+            Abc_NodeCollectFanouts( pObj, p->vFanouts );
+            Vec_PtrSort( p->vFanouts, (int(*)(void))Bus_SclCompareFanouts );
+            do 
+            {
+                Abc_Obj_t * pInv;
+                if ( p->pPars->fVeryVerbose )//|| Vec_PtrSize(p->vFanouts) == Abc_ObjFanoutNum(pObj) )
+                    Abc_NtkPrintFanoutProfileVec( pObj, p->vFanouts );
+                pInv = Abc_SclAddOneInv( p, pObj, p->vFanouts, GainInv );
+                if ( p->pPars->fVeryVerbose )
+                    Abc_SclOneNodePrint( p, pInv );
+                Bus_SclInsertFanout( p->vFanouts, pInv );
+                Load = Abc_NtkComputeFanoutLoad( p, p->vFanouts );
+            }
+            while ( Vec_PtrSize(p->vFanouts) > p->pPars->nDegree || (Vec_PtrSize(p->vFanouts) > 1 && Load > GainGate * Cin) );
+            // update node fanouts
+            Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanouts, pFanout, k )
+                if ( Abc_ObjFaninNum(pFanout) == 0 )
+                    Abc_ObjAddFanin( pFanout, pObj );
+            Bus_SclObjSetLoad( pObj, 0 );
+            LoadNew = Abc_NtkComputeNodeLoad( p, pObj );
+            assert( LoadNew - Load < 1 && Load - LoadNew < 1 );
+        } 
+        if ( Abc_ObjIsCi(pObj) )
+            continue;
+        Abc_NtkComputeNodeDeparture( pObj, p->pPars->Slew );
+        // create cell
+        pCellNew = Abc_SclFindSmallestGate( pCell, Load / GainGate );
+        Abc_SclObjSetCell( pObj, pCellNew );
+        if ( p->pPars->fVeryVerbose )
+            Abc_SclOneNodePrint( p, pObj );
+        assert( p->pPars->fSizeOnly || Abc_ObjFanoutNum(pObj) <= p->pPars->nDegree );
+    }
+    // compute departure time of the PI
+    if ( i < 0 ) // finished buffering
+    Abc_NtkForEachCi( p->pNtk, pObj, i )
+    {
+        float DeptCur = Abc_NtkComputeNodeDeparture(pObj, p->pPars->Slew);
+        if ( p->pPiDrive )
+        {
+            float Load = Bus_SclObjLoad( pObj );
+            SC_Pair ArrOut, SlewOut, LoadIn = { Load, Load }; 
+            Scl_LibHandleInputDriver( p->pPiDrive, &LoadIn, &ArrOut, &SlewOut );
+            DeptCur += 0.5 * ArrOut.fall +  0.5 * ArrOut.rise;
+        }       
+        DeptMax = Abc_MaxFloat( DeptMax, DeptCur );
+    }
+    if ( p->pPars->fVerbose )
+    {
+        printf( "WireLoads = %d  Degree = %d  Target slew =%4d ps   Gain2 =%5d  Buf = %6d  Delay =%7.0f ps   ", 
+            p->pPars->fUseWireLoads, p->pPars->nDegree, p->pPars->Slew, p->pPars->GainRatio, 
+            Abc_NtkObjNumMax(p->pNtk) - nObjsOld, DeptMax );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+}
+Abc_Ntk_t * Abc_SclBufferingPerform( Abc_Ntk_t * pNtk, SC_Lib * pLib, SC_BusPars * pPars )
+{
+    Abc_Ntk_t * pNtkNew;
+    Bus_Man_t * p;
+    if ( !Abc_SclCheckNtk( pNtk, 0 ) )
+        return NULL;
+    Abc_SclReportDupFanins( pNtk );
+    Abc_SclMioGates2SclGates( pLib, pNtk );
+    p = Bus_ManStart( pNtk, pLib, pPars );
+    Bus_ManReadInOutLoads( p );
+    Abc_SclBufSize( p, 0.01 * pPars->GainRatio );
+    Bus_ManStop( p );
+    Abc_SclSclGates2MioGates( pLib, pNtk );
+    if ( pNtk->vPhases )
+        Vec_IntFillExtra( pNtk->vPhases, Abc_NtkObjNumMax(pNtk), 0 );
+    pNtkNew = Abc_NtkDupDfs( pNtk );
+    return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/scl/sclBuffer.c b/abc-build/src/map/scl/sclBuffer.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/scl/sclBuffer.c
@@ -0,0 +1,1008 @@
+/**CFile****************************************************************
+
+  FileName    [sclBuffer.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Standard-cell library representation.]
+
+  Synopsis    [Buffering algorithms.]
+
+  Author      [Alan Mishchenko, Niklas Een]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 24, 2012.]
+
+  Revision    [$Id: sclBuffer.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sclSize.h"
+#include "map/mio/mio.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define BUF_SCALE 1000
+
+typedef struct Buf_Man_t_ Buf_Man_t;
+struct Buf_Man_t_
+{
+    // parameters
+    int            nFanMin;   // the smallest fanout count to consider
+    int            nFanMax;   // the largest fanout count allowed off CP
+    int            fBufPis;   // enables buffing of the combinational inputs
+    // internal deta
+    Abc_Ntk_t *    pNtk;      // logic network
+    Vec_Int_t *    vOffsets;  // offsets into edge delays
+    Vec_Int_t *    vEdges;    // edge delays
+    Vec_Int_t *    vArr;      // arrival times
+    Vec_Int_t *    vDep;      // departure times
+    Vec_Flt_t *    vCounts;   // fanout counts
+    Vec_Que_t *    vQue;      // queue by fanout count
+    int            nObjStart; // the number of starting objects
+    int            nObjAlloc; // the number of allocated objects
+    int            DelayMax;  // maximum delay (percentage of inverter delay)
+    float          DelayInv;  // inverter delay
+    // sorting fanouts
+    Vec_Int_t *    vOrder;    // ordering of fanouts
+    Vec_Int_t *    vDelays;   // fanout delays
+    Vec_Int_t *    vNonCrit;  // non-critical fanouts
+    Vec_Int_t *    vTfCone;   // TFI/TFO cone of the node including the node
+    Vec_Ptr_t *    vFanouts;  // temp storage for fanouts
+    // statistics
+    int            nSeparate;
+    int            nDuplicate;
+    int            nBranch0;
+    int            nBranch1;
+    int            nBranchCrit;
+};
+
+static inline int  Abc_BufNodeArr( Buf_Man_t * p, Abc_Obj_t * pObj )                     { return Vec_IntEntry( p->vArr, Abc_ObjId(pObj) );                                   }
+static inline int  Abc_BufNodeDep( Buf_Man_t * p, Abc_Obj_t * pObj )                     { return Vec_IntEntry( p->vDep, Abc_ObjId(pObj) );                                   }
+static inline void Abc_BufSetNodeArr( Buf_Man_t * p, Abc_Obj_t * pObj, int f )           { Vec_IntWriteEntry( p->vArr, Abc_ObjId(pObj), f );                                  }
+static inline void Abc_BufSetNodeDep( Buf_Man_t * p, Abc_Obj_t * pObj, int f )           { Vec_IntWriteEntry( p->vDep, Abc_ObjId(pObj), f );                                  }
+static inline int  Abc_BufEdgeDelay( Buf_Man_t * p, Abc_Obj_t * pObj, int i )            { return Vec_IntEntry( p->vEdges, Vec_IntEntry(p->vOffsets, Abc_ObjId(pObj)) + i );  }
+static inline void Abc_BufSetEdgeDelay( Buf_Man_t * p, Abc_Obj_t * pObj, int i, int f )  { Vec_IntWriteEntry( p->vEdges, Vec_IntEntry(p->vOffsets, Abc_ObjId(pObj)) + i, f ); }
+static inline int  Abc_BufNodeSlack( Buf_Man_t * p, Abc_Obj_t * pObj )                   { return p->DelayMax - Abc_BufNodeArr(p, pObj) - Abc_BufNodeDep(p, pObj);            }
+static inline int  Abc_BufEdgeSlack( Buf_Man_t * p, Abc_Obj_t * pObj, Abc_Obj_t * pFan ) { return p->DelayMax - Abc_BufNodeArr(p, pObj) - Abc_BufNodeDep(p, pFan) - Abc_BufEdgeDelay(p, pFan, Abc_NodeFindFanin(pFan, pObj)); }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Make sure fanins of gates are not duplicated.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclReportDupFanins( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj, * pFanin, * pFanin2;
+    int i, k, k2;
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Abc_ObjForEachFanin( pObj, pFanin2, k2 )
+                if ( k != k2 && pFanin == pFanin2 )
+                    printf( "Node %d has dup fanin %d.\n", i, Abc_ObjId(pFanin) );    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes buffers and inverters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_SclObjIsBufInv( Abc_Obj_t * pObj )
+{
+    return Abc_ObjIsNode(pObj) && Abc_ObjFaninNum(pObj) == 1;
+}
+int Abc_SclIsInv( Abc_Obj_t * pObj )
+{
+    assert( Abc_ObjIsNode(pObj) );
+    return Mio_GateReadTruth((Mio_Gate_t *)pObj->pData) == ABC_CONST(0x5555555555555555);
+}
+int Abc_SclGetRealFaninLit( Abc_Obj_t * pObj )
+{
+    int iLit;
+    if ( !Abc_SclObjIsBufInv(pObj) )
+        return Abc_Var2Lit( Abc_ObjId(pObj), 0 );
+    iLit = Abc_SclGetRealFaninLit( Abc_ObjFanin0(pObj) );
+    return Abc_LitNotCond( iLit, Abc_SclIsInv(pObj) );
+}
+Abc_Ntk_t * Abc_SclUnBufferPerform( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    Vec_Int_t * vLits;
+    Abc_Obj_t * pObj, * pFanin, * pFaninNew;
+    int i, k, iLit, nNodesOld = Abc_NtkObjNumMax(pNtk);
+    // assign inverters
+    vLits = Vec_IntStartFull( Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        if ( Abc_SclIsInv(pObj) && !Abc_SclObjIsBufInv(Abc_ObjFanin0(pObj)) )
+            Vec_IntWriteEntry( vLits, Abc_ObjFaninId0(pObj), Abc_ObjId(pObj) );
+    // transfer fanins
+    Abc_NtkForEachNodeCo( pNtk, pObj, i )
+    {
+        if ( i >= nNodesOld )
+            break;
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+        {
+            if ( !Abc_SclObjIsBufInv(pFanin) )
+                continue;
+            iLit = Abc_SclGetRealFaninLit( pFanin );
+            pFaninNew = Abc_NtkObj( pNtk, Abc_Lit2Var(iLit) );
+            if ( Abc_LitIsCompl(iLit) )
+            {
+                if ( Vec_IntEntry( vLits, Abc_Lit2Var(iLit) ) == -1 )
+                {
+                    pFaninNew = Abc_NtkCreateNodeInv( pNtk, pFaninNew );
+                    Vec_IntWriteEntry( vLits, Abc_Lit2Var(iLit), Abc_ObjId(pFaninNew) );
+                }
+                else
+                    pFaninNew = Abc_NtkObj( pNtk, Vec_IntEntry( vLits, Abc_Lit2Var(iLit) ) );
+                assert( Abc_ObjFaninNum(pFaninNew) == 1 );
+            }
+            if ( pFanin != pFaninNew )
+                Abc_ObjPatchFanin( pObj, pFanin, pFaninNew );
+        }
+    }
+    Vec_IntFree( vLits );
+    // duplicate network in topo order
+    return Abc_NtkDupDfs( pNtk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes buffers and inverters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SclCountMaxPhases( Abc_Ntk_t * pNtk )
+{
+    Vec_Int_t * vPhLevel;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k, Max = 0, MaxAll = 0;
+    vPhLevel = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachNodeCo( pNtk, pObj, i )
+    {
+        Max = 0;
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            Max = Abc_MaxInt( Max, Vec_IntEntry(vPhLevel, Abc_ObjId(pFanin)) + Abc_ObjFaninPhase(pObj, k) );
+        Vec_IntWriteEntry( vPhLevel, i, Max );
+        MaxAll = Abc_MaxInt( MaxAll, Max );
+    }
+    Vec_IntFree( vPhLevel );
+    return MaxAll;
+}
+Abc_Ntk_t * Abc_SclBufferPhase( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    Abc_Ntk_t * pNtkNew;
+    Vec_Int_t * vInvs;
+    Abc_Obj_t * pObj, * pFanin, * pFaninNew;
+    int nNodesOld = Abc_NtkObjNumMax(pNtk);
+    int i, k, Counter = 0, Counter2 = 0, Total = 0;
+    assert( pNtk->vPhases != NULL );
+    vInvs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachNodeCo( pNtk, pObj, i )
+    {
+        if ( i >= nNodesOld )
+            break;
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+        {
+            Total++;
+            if ( !Abc_ObjFaninPhase(pObj, k) )
+                continue;
+            if ( Vec_IntEntry(vInvs, Abc_ObjId(pFanin)) == 0 || Abc_ObjIsCi(pFanin) ) // allow PIs to have high fanout - to be fixed later
+            {
+                pFaninNew = Abc_NtkCreateNodeInv( pNtk, pFanin );
+                Vec_IntWriteEntry( vInvs, Abc_ObjId(pFanin), Abc_ObjId(pFaninNew) );
+                Counter++;
+            }
+            pFaninNew = Abc_NtkObj( pNtk, Vec_IntEntry(vInvs, Abc_ObjId(pFanin)) );
+            Abc_ObjPatchFanin( pObj, pFanin, pFaninNew );
+            Counter2++;
+        }
+    }
+    if ( fVerbose )
+        printf( "Added %d inverters (%.2f %% fanins) (%.2f %% compl fanins).\n", 
+            Counter, 100.0 * Counter / Total, 100.0 * Counter2 / Total );
+    Vec_IntFree( vInvs );
+    Vec_IntFillExtra( pNtk->vPhases, Abc_NtkObjNumMax(pNtk), 0 );
+    // duplicate network in topo order
+    vInvs = pNtk->vPhases;
+    pNtk->vPhases = NULL;
+    pNtkNew = Abc_NtkDupDfs( pNtk );
+    pNtk->vPhases = vInvs;
+    return pNtkNew;
+}
+Abc_Ntk_t * Abc_SclUnBufferPhase( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObj, * pFanin, * pFaninNew;
+    int i, k, iLit, Counter = 0, Total = 0;
+    assert( pNtk->vPhases == NULL );
+    pNtk->vPhases = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
+    Abc_NtkForEachNodeCo( pNtk, pObj, i )
+    {
+        if ( Abc_SclObjIsBufInv(pObj) )
+            continue;
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+        {
+            Total++;
+            iLit = Abc_SclGetRealFaninLit( pFanin );
+            pFaninNew = Abc_NtkObj( pNtk, Abc_Lit2Var(iLit) );
+            if ( pFaninNew == pFanin )
+                continue;
+            // skip fanins which are already fanins of the node
+            if ( Abc_NodeFindFanin( pObj, pFaninNew ) >= 0 )
+                continue;
+            Abc_ObjPatchFanin( pObj, pFanin, pFaninNew );
+            if ( Abc_LitIsCompl(iLit) )
+                Abc_ObjFaninFlipPhase( pObj, k ), Counter++;
+        }
+    }
+    if ( fVerbose )
+        printf( "Saved %d (%.2f %%) fanin phase bits.  ", Counter, 100.0 * Counter / Total );
+    // duplicate network in topo order
+    pNtkNew = Abc_NtkDupDfs( pNtk );
+    if ( fVerbose )
+        printf( "Max depth = %d.\n", Abc_SclCountMaxPhases(pNtkNew) );
+    Abc_SclReportDupFanins( pNtkNew );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Make sure the network is in topo order without dangling nodes.]
+
+  Description [Returns 1 iff the network is fine.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SclCheckNtk( Abc_Ntk_t * p, int fVerbose )
+{
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k, fFlag = 1;
+    Abc_NtkIncrementTravId( p );        
+    Abc_NtkForEachCi( p, pObj, i )
+        Abc_NodeSetTravIdCurrent( pObj );
+    Abc_NtkForEachNode( p, pObj, i )
+    {
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            if ( !Abc_NodeIsTravIdCurrent( pFanin ) )
+                printf( "obj %d and its fanin %d are not in the topo order\n", Abc_ObjId(pObj), Abc_ObjId(pFanin) ), fFlag = 0;
+        Abc_NodeSetTravIdCurrent( pObj );
+        if ( Abc_ObjFanoutNum(pObj) == 0 )
+            printf( "node %d has no fanout\n", Abc_ObjId(pObj) ), fFlag = 0;
+        if ( !fFlag )
+            break;
+    }
+    if ( fFlag && fVerbose )
+        printf( "The network is in topo order and no dangling nodes.\n" );
+    return fFlag;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs buffering of the mapped network (old code).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeInvUpdateFanPolarity( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    assert( Abc_ObjFaninNum(pObj) == 0 || Abc_SclObjIsBufInv(pObj) );
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+    {
+        assert( Abc_ObjFaninNum(pFanout) > 0 );
+        if ( Abc_SclObjIsBufInv(pFanout) )
+            Abc_NodeInvUpdateFanPolarity( pFanout );
+        else
+            Abc_ObjFaninFlipPhase( pFanout, Abc_NodeFindFanin(pFanout, pObj) );
+    }
+}
+void Abc_NodeInvUpdateObjFanoutPolarity( Abc_Obj_t * pObj, Abc_Obj_t * pFanout )
+{
+    if ( Abc_SclObjIsBufInv(pFanout) )
+        Abc_NodeInvUpdateFanPolarity( pFanout );
+    else
+        Abc_ObjFaninFlipPhase( pFanout, Abc_NodeFindFanin(pFanout, pObj) );
+}
+int Abc_NodeCompareLevels( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 )
+{
+    int Diff = Abc_ObjLevel(*pp1) - Abc_ObjLevel(*pp2);
+    if ( Diff < 0 )
+        return -1;
+    if ( Diff > 0 ) 
+        return 1;
+    Diff = (*pp1)->Id - (*pp2)->Id; // needed to make qsort() platform-infependent
+    if ( Diff < 0 )
+        return -1;
+    if ( Diff > 0 ) 
+        return 1;
+    return 0; 
+}
+int Abc_SclComputeReverseLevel( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    int i, Level = 0;
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        Level = Abc_MaxInt( Level, pFanout->Level );
+    return Level + 1;
+}
+Abc_Obj_t * Abc_SclPerformBufferingOne( Abc_Obj_t * pObj, int Degree, int fUseInvs, int fVerbose )
+{
+    Vec_Ptr_t * vFanouts;
+    Abc_Obj_t * pBuffer, * pFanout;
+    int i, Degree0 = Degree;
+    assert( Abc_ObjFanoutNum(pObj) > Degree );
+    // collect fanouts and sort by reverse level
+    vFanouts = Vec_PtrAlloc( Abc_ObjFanoutNum(pObj) );
+    Abc_NodeCollectFanouts( pObj, vFanouts );
+    Vec_PtrSort( vFanouts, (int (*)(void))Abc_NodeCompareLevels );
+    // select the first Degree fanouts
+    if ( fUseInvs )
+        pBuffer = Abc_NtkCreateNodeInv( pObj->pNtk, NULL );
+    else
+        pBuffer = Abc_NtkCreateNodeBuf( pObj->pNtk, NULL );
+    // check if it is possible to not increase level
+    if ( Vec_PtrSize(vFanouts) < 2 * Degree )
+    {
+        Abc_Obj_t * pFanPrev = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, Vec_PtrSize(vFanouts)-1-Degree);
+        Abc_Obj_t * pFanThis = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, Degree-1);
+        Abc_Obj_t * pFanLast = (Abc_Obj_t *)Vec_PtrEntryLast(vFanouts);
+        if ( Abc_ObjLevel(pFanThis) == Abc_ObjLevel(pFanLast) &&
+             Abc_ObjLevel(pFanPrev) <  Abc_ObjLevel(pFanThis) )
+        {
+            // find the first one whose level is the same as last
+            Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i )
+                if ( Abc_ObjLevel(pFanout) == Abc_ObjLevel(pFanLast) )
+                    break;
+            assert( i < Vec_PtrSize(vFanouts) );
+            if ( i > 1 )
+                Degree = i;
+        }
+        // make the last two more well-balanced
+        if ( Degree == Degree0 && Degree > Vec_PtrSize(vFanouts) - Degree )
+            Degree = Vec_PtrSize(vFanouts)/2 + (Vec_PtrSize(vFanouts) & 1);
+        assert( Degree <= Degree0 );
+    }
+    // select fanouts
+    Vec_PtrForEachEntryStop( Abc_Obj_t *, vFanouts, pFanout, i, Degree )
+        Abc_ObjPatchFanin( pFanout, pObj, pBuffer );
+    if ( fVerbose )
+    {
+        printf( "%5d : ", Abc_ObjId(pObj) );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i )
+            printf( "%d%s ", Abc_ObjLevel(pFanout), i == Degree-1 ? "  " : "" );
+        printf( "\n" );
+    }
+    Vec_PtrFree( vFanouts );
+    Abc_ObjAddFanin( pBuffer, pObj );
+    pBuffer->Level = Abc_SclComputeReverseLevel( pBuffer );
+    if ( fUseInvs )
+        Abc_NodeInvUpdateFanPolarity( pBuffer );
+    return pBuffer;
+}
+void Abc_SclPerformBuffering_rec( Abc_Obj_t * pObj, int DegreeR, int Degree, int fUseInvs, int fVerbose )
+{
+    Vec_Ptr_t * vFanouts;
+    Abc_Obj_t * pBuffer;
+    Abc_Obj_t * pFanout;
+    int i, nOldFanNum;
+    if ( Abc_NodeIsTravIdCurrent( pObj ) )
+        return;
+    Abc_NodeSetTravIdCurrent( pObj );
+    pObj->Level = 0;
+    if ( Abc_ObjIsCo(pObj) )
+        return;
+    assert( Abc_ObjIsCi(pObj) || Abc_ObjIsNode(pObj) );
+    // buffer fanouts and collect reverse levels
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        Abc_SclPerformBuffering_rec( pFanout, DegreeR, Degree, fUseInvs, fVerbose );
+    // perform buffering as long as needed
+    nOldFanNum = Abc_ObjFanoutNum(pObj);
+    while ( Abc_ObjFanoutNum(pObj) > Degree )
+        Abc_SclPerformBufferingOne( pObj, Degree, fUseInvs, fVerbose );
+    // add yet another level of buffers
+    if ( DegreeR && nOldFanNum > DegreeR )
+    {
+        if ( fUseInvs )
+            pBuffer = Abc_NtkCreateNodeInv( pObj->pNtk, NULL );
+        else
+            pBuffer = Abc_NtkCreateNodeBuf( pObj->pNtk, NULL );
+        vFanouts = Vec_PtrAlloc( Abc_ObjFanoutNum(pObj) );
+        Abc_NodeCollectFanouts( pObj, vFanouts );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i )
+            Abc_ObjPatchFanin( pFanout, pObj, pBuffer );
+        Vec_PtrFree( vFanouts );
+        Abc_ObjAddFanin( pBuffer, pObj );
+        pBuffer->Level = Abc_SclComputeReverseLevel( pBuffer );
+        if ( fUseInvs )
+            Abc_NodeInvUpdateFanPolarity( pBuffer );
+    }
+    // compute the new level of the node
+    pObj->Level = Abc_SclComputeReverseLevel( pObj );
+}
+Abc_Ntk_t * Abc_SclPerformBuffering( Abc_Ntk_t * p, int DegreeR, int Degree, int fUseInvs, int fVerbose )
+{
+    Vec_Int_t * vCiLevs;
+    Abc_Ntk_t * pNew;
+    Abc_Obj_t * pObj;
+    int i;
+    assert( Abc_NtkHasMapping(p) );
+    if ( fUseInvs )
+    {
+        printf( "Warning!!! Using inverters instead of buffers.\n" );
+        if ( p->vPhases == NULL )
+            printf( "The phases are not given. The result will not verify.\n" );
+    }
+    // remember CI levels
+    vCiLevs = Vec_IntAlloc( Abc_NtkCiNum(p) );
+    Abc_NtkForEachCi( p, pObj, i )
+        Vec_IntPush( vCiLevs, Abc_ObjLevel(pObj) );
+    // perform buffering
+    Abc_NtkIncrementTravId( p );        
+    Abc_NtkForEachCi( p, pObj, i )
+        Abc_SclPerformBuffering_rec( pObj, DegreeR, Degree, fUseInvs, fVerbose );
+    // recompute logic levels
+    Abc_NtkForEachCi( p, pObj, i )
+        pObj->Level = Vec_IntEntry( vCiLevs, i );
+    Abc_NtkForEachNode( p, pObj, i )
+        Abc_ObjLevelNew( pObj );
+    Vec_IntFree( vCiLevs );
+    // if phases are present
+    if ( p->vPhases )
+        Vec_IntFillExtra( p->vPhases, Abc_NtkObjNumMax(p), 0 );
+    // duplication in topo order
+    pNew = Abc_NtkDupDfs( p );
+    Abc_SclCheckNtk( pNew, fVerbose );
+//    Abc_NtkDelete( pNew );
+    return pNew;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Abc_BufComputeArr( Buf_Man_t * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    float DelayF, Delay = -ABC_INFINITY;
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+    {
+        if ( Vec_IntEntry(p->vOffsets, Abc_ObjId(pObj)) == -ABC_INFINITY )
+            continue;
+        DelayF = Abc_BufNodeArr(p, pFanin) + Abc_BufEdgeDelay(p, pObj, i);
+        if ( Delay < DelayF )
+            Delay = DelayF;
+    }
+    Abc_BufSetNodeArr( p, pObj, Delay );
+    return Delay;
+}
+float Abc_BufComputeDep( Buf_Man_t * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    float DelayF, Delay = -ABC_INFINITY;
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+    {
+        if ( Vec_IntEntry(p->vOffsets, Abc_ObjId(pFanout)) == -ABC_INFINITY )
+            continue;
+        DelayF = Abc_BufNodeDep(p, pFanout) + Abc_BufEdgeDelay(p, pFanout, Abc_NodeFindFanin(pFanout, pObj));
+        if ( Delay < DelayF )
+            Delay = DelayF;
+    }
+    Abc_BufSetNodeDep( p, pObj, Delay );
+    return Delay;
+}
+void Abc_BufUpdateGlobal( Buf_Man_t * p )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    p->DelayMax = 0;
+    Abc_NtkForEachCo( p->pNtk, pObj, i )
+        p->DelayMax = Abc_MaxInt( p->DelayMax, Abc_BufNodeArr(p, Abc_ObjFanin0(pObj)) );
+}
+void Abc_BufCreateEdges( Buf_Man_t * p, Abc_Obj_t * pObj )
+{
+    int k;
+    Mio_Gate_t * pGate = Abc_ObjIsCo(pObj) ? NULL : (Mio_Gate_t *)pObj->pData;
+    Vec_IntWriteEntry( p->vOffsets, Abc_ObjId(pObj), Vec_IntSize(p->vEdges) );
+    for ( k = 0; k < Abc_ObjFaninNum(pObj); k++ )
+        Vec_IntPush( p->vEdges, pGate ? (int)(1.0 * BUF_SCALE * Mio_GateReadPinDelay(pGate, k) / p->DelayInv) : 0 );
+}
+void Abc_BufAddToQue( Buf_Man_t * p, Abc_Obj_t * pObj )
+{
+    if ( Abc_ObjFanoutNum(pObj) < p->nFanMin || (!p->fBufPis && Abc_ObjIsCi(pObj)) )
+        return;
+    Vec_FltWriteEntry( p->vCounts, Abc_ObjId(pObj), Abc_ObjFanoutNum(pObj) );
+    if ( Vec_QueIsMember(p->vQue, Abc_ObjId(pObj)) )
+        Vec_QueUpdate( p->vQue, Abc_ObjId(pObj) );
+    else
+        Vec_QuePush( p->vQue, Abc_ObjId(pObj) );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_BufCollectTfoCone_rec( Abc_Obj_t * pNode, Vec_Int_t * vNodes )
+{
+    Abc_Obj_t * pNext;
+    int i;
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return;
+    Abc_NodeSetTravIdCurrent( pNode );
+    if ( Abc_ObjIsCo(pNode) )
+        return;
+    assert( Abc_ObjIsCi(pNode) || Abc_ObjIsNode(pNode) );
+    Abc_ObjForEachFanout( pNode, pNext, i )
+        Abc_BufCollectTfoCone_rec( pNext, vNodes );
+    if ( Abc_ObjIsNode(pNode) )
+        Vec_IntPush( vNodes, Abc_ObjId(pNode) );
+}
+void Abc_BufCollectTfoCone( Buf_Man_t * p, Abc_Obj_t * pObj )
+{
+    Vec_IntClear( p->vTfCone );
+    Abc_NtkIncrementTravId( p->pNtk );
+    Abc_BufCollectTfoCone_rec( pObj, p->vTfCone );
+}
+void Abc_BufUpdateArr( Buf_Man_t * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pNext;
+    int i, Delay;
+//    assert( Abc_ObjIsNode(pObj) );
+    Abc_BufCollectTfoCone( p, pObj );
+    Vec_IntReverseOrder( p->vTfCone );
+    Abc_NtkForEachObjVec( p->vTfCone, p->pNtk, pNext, i )
+    {
+        Delay = Abc_BufComputeArr( p, pNext );
+        p->DelayMax = Abc_MaxInt( p->DelayMax, Delay );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_BufCollectTfiCone_rec( Abc_Obj_t * pNode, Vec_Int_t * vNodes )
+{
+    Abc_Obj_t * pNext;
+    int i;
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return;
+    Abc_NodeSetTravIdCurrent( pNode );
+    if ( Abc_ObjIsCi(pNode) )
+        return;
+    assert( Abc_ObjIsNode(pNode) );
+    Abc_ObjForEachFanin( pNode, pNext, i )
+        Abc_BufCollectTfiCone_rec( pNext, vNodes );
+    Vec_IntPush( vNodes, Abc_ObjId(pNode) );
+}
+void Abc_BufCollectTfiCone( Buf_Man_t * p, Abc_Obj_t * pObj )
+{
+    Vec_IntClear( p->vTfCone );
+    Abc_NtkIncrementTravId( p->pNtk );
+    Abc_BufCollectTfiCone_rec( pObj, p->vTfCone );
+}
+void Abc_BufUpdateDep( Buf_Man_t * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pNext;
+    int i, Delay;
+//    assert( Abc_ObjIsNode(pObj) );
+    Abc_BufCollectTfiCone( p, pObj );
+    Vec_IntReverseOrder( p->vTfCone );
+    Abc_NtkForEachObjVec( p->vTfCone, p->pNtk, pNext, i )
+    {
+        Delay = Abc_BufComputeDep( p, pNext );
+        p->DelayMax = Abc_MaxInt( p->DelayMax, Delay );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Buf_Man_t * Buf_ManStart( Abc_Ntk_t * pNtk, int FanMin, int FanMax, int fBufPis )
+{
+    Buf_Man_t * p;
+    Abc_Obj_t * pObj;
+    Vec_Ptr_t * vNodes;
+    int i;
+    p = ABC_CALLOC( Buf_Man_t, 1 );
+    p->pNtk      = pNtk;
+    p->nFanMin   = FanMin;
+    p->nFanMax   = FanMax;
+    p->fBufPis   = fBufPis;
+    // allocate arrays
+    p->nObjStart = Abc_NtkObjNumMax(p->pNtk);
+    p->nObjAlloc = (6 * Abc_NtkObjNumMax(p->pNtk) / 3) + 100;
+    p->vOffsets  = Vec_IntAlloc( p->nObjAlloc );
+    p->vArr      = Vec_IntAlloc( p->nObjAlloc );
+    p->vDep      = Vec_IntAlloc( p->nObjAlloc );
+    p->vCounts   = Vec_FltAlloc( p->nObjAlloc );
+    p->vQue      = Vec_QueAlloc( p->nObjAlloc );
+    Vec_IntFill( p->vOffsets, p->nObjAlloc, -ABC_INFINITY );
+    Vec_IntFill( p->vArr,     p->nObjAlloc, 0 );
+    Vec_IntFill( p->vDep,     p->nObjAlloc, 0 );
+    Vec_FltFill( p->vCounts,  p->nObjAlloc, -ABC_INFINITY );
+    Vec_QueSetPriority( p->vQue, Vec_FltArrayP(p->vCounts) );
+    // collect edge delays
+    p->DelayInv  = Mio_GateReadPinDelay( Mio_LibraryReadInv((Mio_Library_t *)pNtk->pManFunc), 0 );
+    p->vEdges    = Vec_IntAlloc( 1000 );
+    // create edges
+    vNodes = Abc_NtkDfs( p->pNtk, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        Abc_BufCreateEdges( p, pObj );
+    Abc_NtkForEachCo( p->pNtk, pObj, i )
+        Abc_BufCreateEdges( p, pObj );
+    // derive delays
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        Abc_BufComputeArr( p, pObj );
+    Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pObj, i )
+        Abc_BufComputeDep( p, pObj );
+    Abc_BufUpdateGlobal( p );
+//    Abc_NtkForEachNode( p->pNtk, pObj, i )
+//        printf( "%4d : %4d %4d\n", i, Abc_BufNodeArr(p, pObj), Abc_BufNodeDep(p, pObj) );
+    // create fanout queue
+//    Abc_NtkForEachCi( p->pNtk, pObj, i )
+//        Abc_BufAddToQue( p, pObj );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        Abc_BufAddToQue( p, pObj );
+    Vec_PtrFree( vNodes );
+    p->vDelays  = Vec_IntAlloc( 100 );
+    p->vOrder   = Vec_IntAlloc( 100 );
+    p->vNonCrit = Vec_IntAlloc( 100 );
+    p->vTfCone  = Vec_IntAlloc( 100 );
+    p->vFanouts = Vec_PtrAlloc( 100 );
+    return p;
+}
+void Buf_ManStop( Buf_Man_t * p )
+{
+    printf( "Sep = %d. Dup = %d. Br0 = %d. Br1 = %d. BrC = %d.  ", 
+        p->nSeparate, p->nDuplicate, p->nBranch0, p->nBranch1, p->nBranchCrit );
+    printf( "Orig = %d. Add = %d. Rem = %d.\n", 
+        p->nObjStart, Abc_NtkObjNumMax(p->pNtk) - p->nObjStart, 
+        p->nObjAlloc - Abc_NtkObjNumMax(p->pNtk) );
+    Vec_PtrFree( p->vFanouts );
+    Vec_IntFree( p->vTfCone );
+    Vec_IntFree( p->vNonCrit );
+    Vec_IntFree( p->vDelays );
+    Vec_IntFree( p->vOrder );
+    Vec_IntFree( p->vOffsets );
+    Vec_IntFree( p->vEdges );
+    Vec_IntFree( p->vArr );
+    Vec_IntFree( p->vDep );
+//    Vec_QueCheck( p->vQue );
+    Vec_QueFree( p->vQue );
+    Vec_FltFree( p->vCounts );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_BufSortByDelay( Buf_Man_t * p, int iPivot )
+{
+    Abc_Obj_t * pObj, * pFanout;
+    int i, Slack, * pOrder;
+    Vec_IntClear( p->vDelays );
+    pObj = Abc_NtkObj( p->pNtk, iPivot );
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+    {
+        Slack = Abc_BufEdgeSlack(p, pObj, pFanout);
+        assert( Slack >= 0 );
+        Vec_IntPush( p->vDelays, Abc_MaxInt(0, Slack) );
+    }
+    pOrder = Abc_QuickSortCost( Vec_IntArray(p->vDelays), Vec_IntSize(p->vDelays), 0 );
+    Vec_IntClear( p->vOrder );
+    for ( i = 0; i < Vec_IntSize(p->vDelays); i++ )
+        Vec_IntPush( p->vOrder, Abc_ObjId(Abc_ObjFanout(pObj, pOrder[i])) );
+    ABC_FREE( pOrder );
+//    for ( i = 0; i < Vec_IntSize(p->vDelays); i++ )
+//        printf( "%5d - %5d   ", Vec_IntEntry(p->vOrder, i), Abc_BufEdgeSlack(p, pObj, Abc_NtkObj(p->pNtk, Vec_IntEntry(p->vOrder, i))) );
+    return p->vOrder;        
+}
+void Abc_BufPrintOne( Buf_Man_t * p, int iPivot )
+{
+    Abc_Obj_t * pObj, * pFanout;
+    Vec_Int_t * vOrder;
+    int i, Slack;
+    pObj = Abc_NtkObj( p->pNtk, iPivot );
+    vOrder = Abc_BufSortByDelay( p, iPivot );
+    printf( "Node %5d  Fi = %d  Fo = %3d  Lev = %3d : {", iPivot, Abc_ObjFaninNum(pObj), Abc_ObjFanoutNum(pObj), Abc_ObjLevel(pObj) );
+    Abc_NtkForEachObjVec( vOrder, p->pNtk, pFanout, i )
+    {
+        Slack = Abc_BufEdgeSlack( p, pObj, pFanout );
+        printf( " %d(%d)", Abc_ObjId(pFanout), Slack );
+    }
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_BufReplaceBufsByInvs( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj, * pInv;
+    int i, Counter = 0;
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        if ( !Abc_NodeIsBuf(pObj) )
+            continue;
+        assert( pObj->pData == Mio_LibraryReadBuf((Mio_Library_t *)pNtk->pManFunc) );
+        pObj->pData = Mio_LibraryReadInv((Mio_Library_t *)pNtk->pManFunc);
+        pInv = Abc_NtkCreateNodeInv( pNtk, Abc_ObjFanin0(pObj) );
+        Abc_ObjPatchFanin( pObj, Abc_ObjFanin0(pObj), pInv );
+        Counter++;
+    }
+    printf( "Replaced %d buffers by invertor pairs.\n", Counter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_BufComputeAverage( Buf_Man_t * p, int iPivot, Vec_Int_t * vOrder )
+{
+    Abc_Obj_t * pObj, * pFanout;
+    int i, Average = 0;
+    pObj = Abc_NtkObj( p->pNtk, iPivot );
+    Abc_NtkForEachObjVec( vOrder, p->pNtk, pFanout, i )
+        Average += Abc_BufEdgeSlack( p, pObj, pFanout );
+    return Average / Vec_IntSize(vOrder);
+}
+Abc_Obj_t * Abc_BufFindNonBuffDriver( Buf_Man_t * p, Abc_Obj_t * pObj )
+{
+    return (Abc_ObjIsNode(pObj) && Abc_NodeIsBuf(pObj)) ? Abc_BufFindNonBuffDriver(p, Abc_ObjFanin0(pObj)) : pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_BufCountNonCritical( Buf_Man_t * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    Vec_IntClear( p->vNonCrit );
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        if ( Abc_BufEdgeSlack( p, pObj, pFanout ) > 7*BUF_SCALE/2 )
+            Vec_IntPush( p->vNonCrit, Abc_ObjId(pFanout) );
+    return Vec_IntSize(p->vNonCrit);
+}
+void Abc_BufPerformOne( Buf_Man_t * p, int iPivot, int fSkipDup, int fVerbose )
+{
+    Abc_Obj_t * pObj, * pFanout;
+    int i, j, nCrit, nNonCrit;
+//    int DelayMax = p->DelayMax;
+    assert( Abc_NtkObjNumMax(p->pNtk) + 30 < p->nObjAlloc );
+    pObj     = Abc_NtkObj( p->pNtk, iPivot );
+//    assert( Vec_FltEntry(p->vCounts, iPivot) == (float)Abc_ObjFanoutNum(pObj) );
+    nNonCrit = Abc_BufCountNonCritical( p, pObj );
+    nCrit    = Abc_ObjFanoutNum(pObj) - nNonCrit;
+if ( fVerbose )
+{
+//Abc_BufPrintOne( p, iPivot );
+printf( "ObjId = %6d : %-10s   FI = %d. FO =%4d.  Crit =%4d.  ", 
+    Abc_ObjId(pObj), Mio_GateReadName((Mio_Gate_t *)pObj->pData), Abc_ObjFaninNum(pObj), Abc_ObjFanoutNum(pObj), nCrit );
+}
+    // consider three cases
+    if ( nCrit > 0 && nNonCrit > 1 )
+    {
+        // (1) both critical and non-critical are present - split them by adding buffer
+        Abc_Obj_t * pBuffer = Abc_NtkCreateNodeBuf( p->pNtk, pObj );
+        Abc_NtkForEachObjVec( p->vNonCrit, p->pNtk, pFanout, i )
+            Abc_ObjPatchFanin( pFanout, pObj, pBuffer );
+        // update timing
+        Abc_BufCreateEdges( p, pBuffer );
+        Abc_BufUpdateArr( p, pBuffer );
+        Abc_BufUpdateDep( p, pBuffer );
+        Abc_BufAddToQue( p, pObj );
+        Abc_BufAddToQue( p, pBuffer );
+        Abc_SclTimeIncUpdateLevel( pBuffer );
+        p->nSeparate++;
+if ( fVerbose )
+printf( "Adding buffer\n" );
+    }
+    else if ( !fSkipDup && nCrit > 0 && Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > p->nFanMin )//&& Abc_ObjLevel(pObj) < 4 )//&& Abc_ObjFaninNum(pObj) < 2 )
+    {
+        // (2) only critical are present - duplicate
+        Abc_Obj_t * pClone = Abc_NtkDupObj( p->pNtk, pObj, 0 );
+        Abc_ObjForEachFanin( pObj, pFanout, i )
+            Abc_ObjAddFanin( pClone, pFanout );
+        Abc_NodeCollectFanouts( pObj, p->vFanouts );
+        Vec_PtrForEachEntryStop( Abc_Obj_t *, p->vFanouts, pFanout, i, Vec_PtrSize(p->vFanouts)/2 )
+            Abc_ObjPatchFanin( pFanout, pObj, pClone );
+        // update timing
+        Abc_BufCreateEdges( p, pClone );
+        Abc_BufSetNodeArr( p, pClone, Abc_BufNodeArr(p, pObj) );
+        Abc_BufUpdateDep( p, pObj );
+        Abc_BufUpdateDep( p, pClone );
+        Abc_BufAddToQue( p, pObj );
+        Abc_BufAddToQue( p, pClone );
+        Abc_ObjForEachFanin( pObj, pFanout, i )
+            Abc_BufAddToQue( p, pFanout );
+        Abc_SclTimeIncUpdateLevel( pClone );
+        p->nDuplicate++;
+//        printf( "Duplicating %s on level %d\n", Mio_GateReadName((Mio_Gate_t *)pObj->pData), Abc_ObjLevel(pObj) );
+if ( fVerbose )
+printf( "Duplicating node\n" );
+    }
+    else if ( (nCrit > 0 && Abc_ObjFanoutNum(pObj) > 8) || Abc_ObjFanoutNum(pObj) > p->nFanMax )
+    {
+        // (2) only critical or only non-critical - add buffer/inverter tree
+        int nDegree, n1Degree, n1Number, nFirst;
+        int iFirstBuf = Abc_NtkObjNumMax( p->pNtk );
+//        nDegree  = Abc_MinInt( 3, (int)pow(Abc_ObjFanoutNum(pObj), 0.34) );
+        nDegree  = Abc_MinInt( 10, (int)pow(Abc_ObjFanoutNum(pObj), 0.5) );
+        n1Degree = Abc_ObjFanoutNum(pObj) / nDegree + 1;
+        n1Number = Abc_ObjFanoutNum(pObj) % nDegree;
+        nFirst   = n1Degree * n1Number;
+        p->nBranchCrit += (nCrit > 0);
+        // create inverters
+        Abc_NodeCollectFanouts( pObj, p->vFanouts );
+        if ( Abc_ObjIsNode(pObj) && Abc_NodeIsBuf(pObj) )
+        {
+            p->nBranch0++;
+            pObj->pData = Mio_LibraryReadInv((Mio_Library_t *)p->pNtk->pManFunc);
+            Abc_BufSetEdgeDelay( p, pObj, 0, BUF_SCALE );
+            assert( Abc_NodeIsInv(pObj) );
+            for ( i = 0; i < nDegree; i++ )
+                Abc_NtkCreateNodeInv( p->pNtk, pObj );
+if ( fVerbose )
+printf( "Adding %d inverters\n", nDegree );
+        }
+        else
+        {
+            p->nBranch1++;
+            for ( i = 0; i < nDegree; i++ )
+                Abc_NtkCreateNodeBuf( p->pNtk, pObj );
+if ( fVerbose )
+printf( "Adding %d buffers\n", nDegree );
+        }
+        // connect inverters
+        Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanouts, pFanout, i )
+        {
+            j = (i < nFirst) ? i/n1Degree : n1Number + ((i - nFirst)/(n1Degree - 1));
+            assert( j >= 0 && j < nDegree );
+            Abc_ObjPatchFanin( pFanout, pObj, Abc_NtkObj(p->pNtk, iFirstBuf + j) );
+        }
+        // update timing
+        for ( i = 0; i < nDegree; i++ )
+            Abc_BufCreateEdges( p, Abc_NtkObj(p->pNtk, iFirstBuf + i) );
+        Abc_BufUpdateArr( p, pObj );
+        for ( i = 0; i < nDegree; i++ )
+            Abc_BufComputeDep( p, Abc_NtkObj(p->pNtk, iFirstBuf + i) );
+        Abc_BufUpdateDep( p, pObj );
+        for ( i = 0; i < nDegree; i++ )
+            Abc_BufAddToQue( p, Abc_NtkObj(p->pNtk, iFirstBuf + i) );
+        for ( i = 0; i < nDegree; i++ )
+            Abc_SclTimeIncUpdateLevel( Abc_NtkObj(p->pNtk, iFirstBuf + i) );
+    }
+    else
+    {
+if ( fVerbose )
+printf( "Doing nothing\n" );
+    }
+//    if ( DelayMax != p->DelayMax )
+//        printf( "%d (%.2f)  ", p->DelayMax, 1.0 * p->DelayMax * p->DelayInv / BUF_SCALE );
+}
+Abc_Ntk_t * Abc_SclBufPerform( Abc_Ntk_t * pNtk, int FanMin, int FanMax, int fBufPis, int fSkipDup, int fVerbose )
+{
+    Abc_Ntk_t * pNew;
+    Buf_Man_t * p = Buf_ManStart( pNtk, FanMin, FanMax, fBufPis );
+    int i, Limit = ABC_INFINITY;
+    Abc_NtkLevel( pNtk );
+//    if ( Abc_NtkNodeNum(pNtk) < 1000 )
+//        fSkipDup = 1;
+    for ( i = 0; i < Limit && Vec_QueSize(p->vQue); i++ )
+        Abc_BufPerformOne( p, Vec_QuePop(p->vQue), fSkipDup, fVerbose );
+    Buf_ManStop( p );
+//    Abc_BufReplaceBufsByInvs( pNtk );
+    // duplicate network in topo order
+    pNew = Abc_NtkDupDfs( pNtk );
+    Abc_SclCheckNtk( pNew, fVerbose );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/scl/sclDnsize.c b/abc-build/src/map/scl/sclDnsize.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/scl/sclDnsize.c
@@ -0,0 +1,355 @@
+/**CFile****************************************************************
+
+  FileName    [sclDnsize.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Standard-cell library representation.]
+
+  Synopsis    [Selective decrease of gate sizes.]
+
+  Author      [Alan Mishchenko, Niklas Een]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 24, 2012.]
+
+  Revision    [$Id: sclDnsize.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sclSize.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Find the array of nodes to be updated.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclFindWindow( Abc_Obj_t * pPivot, Vec_Int_t ** pvNodes, Vec_Int_t ** pvEvals )
+{
+    Abc_Ntk_t * p = Abc_ObjNtk(pPivot);
+    Abc_Obj_t * pObj, * pNext, * pNext2;
+    Vec_Int_t * vNodes = *pvNodes;
+    Vec_Int_t * vEvals = *pvEvals;
+    int i, k;
+    assert( Abc_ObjIsNode(pPivot) );
+    // collect fanins, node, and fanouts
+    Vec_IntClear( vNodes );
+    Abc_ObjForEachFanin( pPivot, pNext, i )
+//        if ( Abc_ObjIsNode(pNext) && Abc_ObjFaninNum(pNext) > 0 )
+        if ( Abc_ObjIsCi(pNext) || Abc_ObjFaninNum(pNext) > 0 )
+            Vec_IntPush( vNodes, Abc_ObjId(pNext) );
+    Vec_IntPush( vNodes, Abc_ObjId(pPivot) );
+    Abc_ObjForEachFanout( pPivot, pNext, i )
+        if ( Abc_ObjIsNode(pNext) )
+        {
+            Vec_IntPush( vNodes, Abc_ObjId(pNext) );
+            Abc_ObjForEachFanout( pNext, pNext2, k )
+                if ( Abc_ObjIsNode(pNext2) )
+                    Vec_IntPush( vNodes, Abc_ObjId(pNext2) );
+        }
+    Vec_IntUniqify( vNodes );
+    // label nodes
+    Abc_NtkForEachObjVec( vNodes, p, pObj, i )
+    {
+        assert( pObj->fMarkB == 0 );
+        pObj->fMarkB = 1;
+    }
+    // collect nodes visible from the critical paths
+    Vec_IntClear( vEvals );
+    Abc_NtkForEachObjVec( vNodes, p, pObj, i )
+        Abc_ObjForEachFanout( pObj, pNext, k )
+            if ( !pNext->fMarkB )
+            {
+                assert( pObj->fMarkB );
+                Vec_IntPush( vEvals, Abc_ObjId(pObj) );
+                break;
+            }
+    assert( Vec_IntSize(vEvals) > 0 );
+    // label nodes
+    Abc_NtkForEachObjVec( vNodes, p, pObj, i )
+        pObj->fMarkB = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node can be improved.]
+
+  Description [Updated the node to have a new gate.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SclCheckImprovement( SC_Man * p, Abc_Obj_t * pObj, Vec_Int_t * vNodes, Vec_Int_t * vEvals, int Notches, int DelayGap )
+{
+    Abc_Obj_t * pTemp;
+    SC_Cell * pCellOld, * pCellNew;
+    float dGain, dGainBest;
+    int i, k, gateBest;
+    abctime clk;
+clk = Abc_Clock();
+//    printf( "%d -> %d\n", Vec_IntSize(vNodes), Vec_IntSize(vEvals) );
+    // save old gate, timing, fanin load
+    pCellOld = Abc_SclObjCell( pObj );
+    Abc_SclConeStore( p, vNodes );
+    Abc_SclEvalStore( p, vEvals );
+    Abc_SclLoadStore( p, pObj );
+    // try different gate sizes for this node
+    gateBest = -1;
+    dGainBest = -DelayGap;
+    SC_RingForEachCellRev( pCellOld, pCellNew, i )
+    {
+        if ( pCellNew->area >= pCellOld->area )
+            continue;
+        if ( i > Notches )
+            break;
+        // set new cell
+        Abc_SclObjSetCell( pObj, pCellNew );
+        Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew );
+        // recompute timing
+        Abc_SclTimeCone( p, vNodes );
+        // set old cell
+        Abc_SclObjSetCell( pObj, pCellOld );
+        Abc_SclLoadRestore( p, pObj );
+        // evaluate gain
+        dGain = Abc_SclEvalPerformLegal( p, vEvals, p->MaxDelay0 );
+        if ( dGain == -1 )
+            continue;
+        // save best gain
+        if ( dGainBest < dGain )
+        {
+            dGainBest = dGain;
+            gateBest = pCellNew->Id;
+        }
+    } 
+    // put back old cell and timing
+    Abc_SclObjSetCell( pObj, pCellOld );
+    Abc_SclConeRestore( p, vNodes );
+p->timeSize += Abc_Clock() - clk;
+    if ( gateBest >= 0 )
+    {
+        pCellNew = SC_LibCell( p->pLib, gateBest );
+        Abc_SclObjSetCell( pObj, pCellNew );
+        p->SumArea += pCellNew->area - pCellOld->area;
+//        printf( "%f   %f -> %f\n", pCellNew->area - pCellOld->area, p->SumArea - (pCellNew->area - pCellOld->area), p->SumArea );
+//        printf( "%6d  %20s -> %20s  %f -> %f\n", Abc_ObjId(pObj), pCellOld->pName, pCellNew->pName, pCellOld->area, pCellNew->area );
+        // mark used nodes with the current trav ID
+        Abc_NtkForEachObjVec( vNodes, p->pNtk, pTemp, k )
+            Abc_NodeSetTravIdCurrent( pTemp );
+        // update load and timing...
+        Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew );
+        Abc_SclTimeIncInsert( p, pObj );
+        return 1;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect nodes by area.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCollectNodesByArea( SC_Man * p, Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    assert( Vec_QueSize(p->vNodeByGain) == 0 );
+    Vec_QueClear( p->vNodeByGain );
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    if ( Abc_ObjFaninNum(pObj) > 0 )
+    {
+        Vec_FltWriteEntry( p->vNode2Gain, Abc_ObjId(pObj), Abc_SclObjCell(pObj)->area );
+        Vec_QuePush( p->vNodeByGain, Abc_ObjId(pObj) );
+    }
+}
+int Abc_SclCheckOverlap( Abc_Ntk_t * pNtk, Vec_Int_t * vNodes )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObjVec( vNodes, pNtk, pObj, i )
+        if ( Abc_NodeIsTravIdCurrent(pObj) )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print cumulative statistics.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclDnsizePrint( SC_Man * p, int Iter, int nAttempts, int nOverlaps, int nChanges, int fVerbose )
+{
+    if ( Iter == -1 )
+        printf( "Total : " );
+    else
+        printf( "%5d : ",    Iter );
+    printf( "Try =%6d  ",    nAttempts );
+    printf( "Over =%6d  ",   nOverlaps );
+    printf( "Fail =%6d  ",   nAttempts-nOverlaps-nChanges );
+    printf( "Win =%6d  ",    nChanges );
+    printf( "A: " );
+    printf( "%.2f ",         p->SumArea );
+    printf( "(%+5.1f %%)  ", 100.0 * (p->SumArea - p->SumArea0)/ p->SumArea0 );
+    printf( "D: " );
+    printf( "%.2f ps ",      p->MaxDelay );
+    printf( "(%+5.1f %%)  ", 100.0 * (p->MaxDelay - p->MaxDelay0)/ p->MaxDelay0 );
+    printf( "%8.2f sec    ", 1.0*(Abc_Clock() - p->timeTotal)/(CLOCKS_PER_SEC) );
+    printf( "%c", fVerbose ? '\n' : '\r' );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars )
+{
+    SC_Man * p;
+    Abc_Obj_t * pObj;
+    Vec_Int_t * vNodes, * vEvals, * vTryLater; 
+    abctime clk, nRuntimeLimit = pPars->TimeOut ? pPars->TimeOut * CLOCKS_PER_SEC + Abc_Clock() : 0;
+    int i, k;
+
+    if ( pPars->fVerbose )
+    {
+        printf( "Parameters: " );
+        printf( "Iters =%5d.  ",          pPars->nIters    );
+        printf( "UseDept =%2d. ",         pPars->fUseDept  );
+        printf( "UseWL =%2d. ",           pPars->fUseWireLoads );
+        printf( "Target =%5d ps. ",       pPars->DelayUser );
+        printf( "DelayGap =%3d ps. ",     pPars->DelayGap );
+        printf( "Timeout =%4d sec",       pPars->TimeOut   );
+        printf( "\n" );
+    }
+
+    // prepare the manager; collect init stats
+    p = Abc_SclManStart( pLib, pNtk, pPars->fUseWireLoads, pPars->fUseDept, pPars->DelayUser, pPars->BuffTreeEst );
+    p->timeTotal  = Abc_Clock();
+    assert( p->vGatesBest == NULL );
+    p->vGatesBest = Vec_IntDup( p->pNtk->vGates );
+
+    // perform upsizing
+    vNodes = Vec_IntAlloc( 1000 );
+    vEvals = Vec_IntAlloc( 1000 );
+    vTryLater = Vec_IntAlloc( 1000 );
+    for ( i = 0; i < pPars->nIters; i++ )
+    {
+        int nRounds = 0;
+        int nAttemptAll = 0, nOverlapAll = 0, nChangesAll = 0;
+        Abc_NtkCollectNodesByArea( p, pNtk );
+        while ( Vec_QueSize(p->vNodeByGain) > 0 )
+        {
+            int nAttempt = 0, nOverlap = 0, nChanges = 0;
+            Vec_IntClear( vTryLater );
+            Abc_NtkIncrementTravId( pNtk );
+            while ( Vec_QueSize(p->vNodeByGain) > 0 )
+            {
+                clk = Abc_Clock();
+                pObj = Abc_NtkObj( p->pNtk, Vec_QuePop(p->vNodeByGain) );
+                Abc_SclFindWindow( pObj, &vNodes, &vEvals );
+                p->timeCone += Abc_Clock() - clk;
+                if ( Abc_SclCheckOverlap( p->pNtk, vNodes ) )
+                    nOverlap++, Vec_IntPush( vTryLater, Abc_ObjId(pObj) );
+                else 
+                    nChanges += Abc_SclCheckImprovement( p, pObj, vNodes, vEvals, pPars->Notches, pPars->DelayGap );
+                nAttempt++;
+            }
+            Abc_NtkForEachObjVec( vTryLater, pNtk, pObj, k )
+                Vec_QuePush( p->vNodeByGain, Abc_ObjId(pObj) );
+
+            clk = Abc_Clock();
+            if ( Vec_IntSize(p->vChanged) )
+                Abc_SclTimeIncUpdate( p );
+            else
+                Abc_SclTimeNtkRecompute( p, &p->SumArea, &p->MaxDelay, pPars->fUseDept, pPars->DelayUser );
+            p->timeTime += Abc_Clock() - clk;
+
+            p->MaxDelay = Abc_SclReadMaxDelay( p );
+            if ( pPars->fUseDept && pPars->DelayUser > 0 && p->MaxDelay < pPars->DelayUser )
+                p->MaxDelay = pPars->DelayUser;
+            Abc_SclDnsizePrint( p, nRounds++, nAttempt, nOverlap, nChanges, pPars->fVeryVerbose ); 
+            nAttemptAll += nAttempt; nOverlapAll += nOverlap; nChangesAll += nChanges;
+            if ( nRuntimeLimit && Abc_Clock() > nRuntimeLimit )
+                break;
+        }
+        // recompute
+//        Abc_SclTimeNtkRecompute( p, &p->SumArea, &p->MaxDelay, pPars->fUseDept, pPars->DelayUser );
+        if ( pPars->fVerbose )
+            Abc_SclDnsizePrint( p, -1, nAttemptAll, nOverlapAll, nChangesAll, 1 ); 
+        if ( nRuntimeLimit && Abc_Clock() > nRuntimeLimit )
+            break;
+        if ( nAttemptAll == 0 )
+            break;
+    }
+    Vec_IntFree( vNodes );
+    Vec_IntFree( vEvals );
+    Vec_IntFree( vTryLater );
+    if ( !pPars->fVerbose )
+        printf( "                                                                                                                               \r" );
+
+    // report runtime
+    p->timeTotal = Abc_Clock() - p->timeTotal;
+    if ( pPars->fVerbose )
+    {
+        p->timeOther = p->timeTotal - p->timeCone - p->timeSize - p->timeTime;
+        ABC_PRTP( "Runtime: Critical path", p->timeCone,  p->timeTotal );
+        ABC_PRTP( "Runtime: Sizing eval  ", p->timeSize,  p->timeTotal );
+        ABC_PRTP( "Runtime: Timing update", p->timeTime,  p->timeTotal );
+        ABC_PRTP( "Runtime: Other        ", p->timeOther, p->timeTotal );
+        ABC_PRTP( "Runtime: TOTAL        ", p->timeTotal, p->timeTotal );
+    }
+    if ( pPars->fDumpStats )
+        Abc_SclDumpStats( p, "stats2.txt", p->timeTotal );
+    if ( nRuntimeLimit && Abc_Clock() > nRuntimeLimit )
+        printf( "Gate sizing timed out at %d seconds.\n", pPars->TimeOut );
+
+    // save the result and quit
+    Abc_SclSclGates2MioGates( pLib, pNtk ); // updates gate pointers
+    Abc_SclManFree( p );
+//    Abc_NtkCleanMarkAB( pNtk );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/scl/sclLib.h b/abc-build/src/map/scl/sclLib.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/scl/sclLib.h
@@ -0,0 +1,636 @@
+/**CFile****************************************************************
+
+  FileName    [sclLib.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Standard-cell library representation.]
+
+  Synopsis    [Simplified library representation for STA.]
+
+  Author      [Alan Mishchenko, Niklas Een]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 24, 2012.]
+
+  Revision    [$Id: sclLib.h,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__map__scl__sclLib_h
+#define ABC__map__scl__sclLib_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <math.h>
+#include "misc/vec/vec.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+#define ABC_SCL_CUR_VERSION 7
+
+typedef enum  
+{
+    sc_dir_NULL,
+    sc_dir_Input,
+    sc_dir_Output,
+    sc_dir_InOut,
+    sc_dir_Internal,
+} SC_Dir;
+
+typedef enum      // -- timing sense, positive-, negative- or non-unate
+{
+    sc_ts_NULL,
+    sc_ts_Pos,
+    sc_ts_Neg,
+    sc_ts_Non,
+} SC_TSense;
+
+typedef struct SC_Pair_         SC_Pair;
+struct SC_Pair_ 
+{
+    float      rise;
+    float      fall;
+};
+
+typedef struct SC_SizePars_    SC_SizePars;
+struct SC_SizePars_
+{
+    int        nIters;
+    int        nIterNoChange;
+    int        Window;           // used for upsizing
+    int        Ratio;            // used for upsizing
+    int        Notches;
+    int        DelayUser;
+    int        DelayGap;
+    int        TimeOut;
+    int        BuffTreeEst;      // ratio for buffer tree estimation
+    int        BypassFreq;       // frequency to try bypassing
+    int        fUseDept;
+    int        fDumpStats;
+    int        fUseWireLoads;
+    int        fVerbose;
+    int        fVeryVerbose;
+};
+
+typedef struct SC_BusPars_     SC_BusPars;
+struct SC_BusPars_
+{
+    int        GainRatio;       // target gain
+    int        Slew;            // target slew
+    int        nDegree;         // max branching factor
+    int        fSizeOnly;       // perform only sizing
+    int        fAddBufs;        // add buffers
+    int        fBufPis;         // use CI buffering
+    int        fUseWireLoads;   // wire loads
+    int        fVerbose;        // verbose
+    int        fVeryVerbose;    // verbose
+};
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct SC_WireLoad_    SC_WireLoad;
+typedef struct SC_WireLoadSel_ SC_WireLoadSel;
+typedef struct SC_TableTempl_  SC_TableTempl;
+typedef struct SC_Surface_     SC_Surface;
+typedef struct SC_Timing_      SC_Timing;
+typedef struct SC_Timings_     SC_Timings;
+typedef struct SC_Pin_         SC_Pin;
+typedef struct SC_Cell_        SC_Cell;
+typedef struct SC_Lib_         SC_Lib;
+
+struct SC_WireLoad_ 
+{
+    char *         pName;
+    float          cap;            // }- multiply estimation in 'fanout_len[].snd' with this value
+    float          slope;          // used to extrapolate wireload for large fanout count
+    Vec_Int_t *    vFanout;        // Vec<Pair<uint,float> > -- pairs '(#fanouts, est-wire-len)'
+    Vec_Flt_t *    vLen;
+};
+
+struct SC_WireLoadSel_
+{
+    char *         pName;
+    Vec_Flt_t *    vAreaFrom;      // Vec<Trip<float,float,Str> > -- triplets '(from-area, upto-area, wire-load-model)'; range is [from, upto[
+    Vec_Flt_t *    vAreaTo;
+    Vec_Ptr_t *    vWireLoadModel;
+};
+
+struct SC_TableTempl_ 
+{
+    char *         pName;
+    Vec_Ptr_t *    vVars;          // Vec<Str>         -- name of variable (numbered from 0, not 1 as in the Liberty file) 
+    Vec_Ptr_t *    vIndex;         // Vec<Vec<float> > -- this is the point of measurement in table for the given variable 
+};
+
+struct SC_Surface_ 
+{
+    char *         pName;
+    Vec_Flt_t *    vIndex0;        // Vec<float>       -- correspondes to "index_1" in the liberty file (for timing: slew)
+    Vec_Flt_t *    vIndex1;        // Vec<float>       -- correspondes to "index_2" in the liberty file (for timing: load)
+    Vec_Ptr_t *    vData;          // Vec<Vec<float> > -- 'data[i0][i1]' gives value at '(index0[i0], index1[i1])' 
+    float          approx[3][6];
+};
+
+struct SC_Timing_ 
+{
+    char *         related_pin;    // -- related pin
+    SC_TSense      tsense;         // -- timing sense (positive_unate, negative_unate, non_unate)
+    char *         when_text;      // -- logic condition on inputs triggering this delay model for the output (currently not used)
+    SC_Surface *   pCellRise;      // -- Used to compute pin-to-pin delay
+    SC_Surface *   pCellFall;
+    SC_Surface *   pRiseTrans;     // -- Used to compute output slew
+    SC_Surface *   pFallTrans;
+};
+
+struct SC_Timings_ 
+{
+    char *         pName;          // -- the 'related_pin' field
+    Vec_Ptr_t *    vTimings;       // structures of type SC_Timing
+};
+
+struct SC_Pin_ 
+{
+    char *         pName;
+    SC_Dir         dir;
+    float          cap;            // -- this value is used if 'rise_cap' and 'fall_cap' is missing (copied by 'postProcess()'). (not used)
+    float          rise_cap;       // }- used for input pins ('cap' too).
+    float          fall_cap;       // }
+    float          max_out_cap;    // } (not used)
+    float          max_out_slew;   // }- used only for output pins (max values must not be exceeded or else mapping is illegal) (not used)
+    char *         func_text;      // }
+    Vec_Wrd_t *    vFunc;          // }
+    Vec_Ptr_t *    vRTimings;      // -- for output pins
+};
+
+struct SC_Cell_ 
+{
+    char *         pName;
+    int            Id;
+    int            fSkip;          // skip this cell during genlib computation
+    int            seq;            // -- set to TRUE by parser if a sequential element
+    int            unsupp;         // -- set to TRUE by parser if cell contains information we cannot handle
+    float          area;
+    int            drive_strength; // -- some library files provide this field (currently unused, but may be a good hint for sizing) (not used)
+    Vec_Ptr_t *    vPins;          // NamedSet<SC_Pin> 
+    int            n_inputs;       // -- 'pins[0 .. n_inputs-1]' are input pins
+    int            n_outputs;      // -- 'pins[n_inputs .. n_inputs+n_outputs-1]' are output pins
+    SC_Cell *      pNext;          // same-functionality cells linked into a ring by area
+    SC_Cell *      pPrev;          // same-functionality cells linked into a ring by area
+    SC_Cell *      pRepr;          // representative of the class
+    SC_Cell *      pAve;           // average size cell of this class
+    int            Order;          // order of the gate in the list
+    int            nGates;         // the number of gates in the list      
+};
+
+struct SC_Lib_ 
+{
+    char *         pName;
+    char *         pFileName;
+    char *         default_wire_load;
+    char *         default_wire_load_sel;
+    float          default_max_out_slew;   // -- 'default_max_transition'; this is copied to each output pin where 'max_transition' is not defined  (not used)
+    int            unit_time;      // -- Valid 9..12. Unit is '10^(-val)' seconds (e.g. 9=1ns, 10=100ps, 11=10ps, 12=1ps)
+    float          unit_cap_fst;   // -- First part is a multiplier, second either 12 or 15 for 'pf' or 'ff'.
+    int            unit_cap_snd;
+    Vec_Ptr_t *    vWireLoads;     // NamedSet<SC_WireLoad>
+    Vec_Ptr_t *    vWireLoadSels;  // NamedSet<SC_WireLoadSel>
+    Vec_Ptr_t *    vTempls;        // NamedSet<SC_TableTempl>  
+    Vec_Ptr_t *    vCells;         // NamedSet<SC_Cell>
+    Vec_Ptr_t *    vCellClasses;   // NamedSet<SC_Cell>
+    int *          pBins;          // hashing gateName -> gateId
+    int            nBins;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+static inline void        SC_PairClean( SC_Pair * d )               { d->rise = d->fall = 0;                 }
+static inline float       SC_PairMax( SC_Pair * d )                 { return Abc_MaxFloat(d->rise, d->fall); }
+static inline float       SC_PairMin( SC_Pair * d )                 { return Abc_MinFloat(d->rise, d->fall); }
+static inline float       SC_PairAve( SC_Pair * d )                 { return 0.5 * d->rise + 0.5 * d->fall;  }
+static inline void        SC_PairDup( SC_Pair * d, SC_Pair * s )    { *d = *s;                               }
+static inline void        SC_PairMove( SC_Pair * d, SC_Pair * s )   { *d = *s; s->rise = s->fall = 0;        }
+static inline int         SC_PairEqual( SC_Pair * d, SC_Pair * s )  { return d->rise == s->rise && d->fall == s->fall;                }
+static inline int         SC_PairEqualE( SC_Pair * d, SC_Pair * s, float E )  { return d->rise - s->rise < E && s->rise - d->rise < E &&  d->fall - s->fall < E && s->fall - d->fall < E;    }
+
+static inline int         SC_LibCellNum( SC_Lib * p )               { return Vec_PtrSize(p->vCells);                                  }
+static inline SC_Cell *   SC_LibCell( SC_Lib * p, int i )           { return (SC_Cell *)Vec_PtrEntry(p->vCells, i);                   }
+static inline SC_Pin  *   SC_CellPin( SC_Cell * p, int i )          { return (SC_Pin *)Vec_PtrEntry(p->vPins, i);                     }
+static inline Vec_Wrd_t * SC_CellFunc( SC_Cell * p )                { return SC_CellPin(p, p->n_inputs)->vFunc;                       }
+static inline float       SC_CellPinCap( SC_Cell * p, int i )       { return 0.5 * SC_CellPin(p, i)->rise_cap + 0.5 * SC_CellPin(p, i)->fall_cap; }
+static inline float       SC_CellPinCapAve( SC_Cell * p )           { int i; float c = 0; for (i = 0; i < p->n_inputs; i++) c += SC_CellPinCap(p, i); return c / Abc_MaxInt(1, p->n_inputs); }
+static inline char *      SC_CellPinOutFunc( SC_Cell * p, int i )   { return SC_CellPin(p, p->n_inputs + i)->func_text;               }
+static inline char *      SC_CellPinName( SC_Cell * p, int i )      { return SC_CellPin(p, i)->pName;                                 }
+
+#define SC_LibForEachCell( p, pCell, i )         Vec_PtrForEachEntry( SC_Cell *, p->vCells, pCell, i )
+#define SC_LibForEachCellClass( p, pCell, i )    Vec_PtrForEachEntry( SC_Cell *, p->vCellClasses, pCell, i )
+#define SC_LibForEachWireLoad( p, pWL, i )       Vec_PtrForEachEntry( SC_WireLoad *, p->vWireLoads, pWL, i )
+#define SC_LibForEachWireLoadSel( p, pWLS, i )   Vec_PtrForEachEntry( SC_WireLoadSel *, p->vWireLoadSels, pWLS, i )
+#define SC_LibForEachTempl( p, pTempl, i )       Vec_PtrForEachEntry( SC_TableTempl *, p->vTempls, pTempl, i )
+#define SC_CellForEachPin( p, pPin, i )          Vec_PtrForEachEntry( SC_Pin *, p->vPins, pPin, i )
+#define SC_CellForEachPinIn( p, pPin, i )        Vec_PtrForEachEntryStop( SC_Pin *, p->vPins, pPin, i, p->n_inputs )
+#define SC_CellForEachPinOut( p, pPin, i )       Vec_PtrForEachEntryStart( SC_Pin *, p->vPins, pPin, i, p->n_inputs )
+#define SC_RingForEachCell( pRing, pCell, i )    for ( i = 0, pCell = pRing; i == 0 || pCell != pRing; pCell = pCell->pNext, i++ )
+#define SC_RingForEachCellRev( pRing, pCell, i ) for ( i = 0, pCell = pRing; i == 0 || pCell != pRing; pCell = pCell->pPrev, i++ )
+#define SC_PinForEachRTiming( p, pRTime, i )     Vec_PtrForEachEntry( SC_Timings *, p->vRTimings, pRTime, i )
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Constructors of the library data-structures.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline SC_WireLoad * Abc_SclWireLoadAlloc()
+{
+    SC_WireLoad * p;
+    p = ABC_CALLOC( SC_WireLoad, 1 );
+    p->vFanout = Vec_IntAlloc( 0 );
+    p->vLen    = Vec_FltAlloc( 0 );
+    return p;
+}
+static inline SC_WireLoadSel * Abc_SclWireLoadSelAlloc()
+{
+    SC_WireLoadSel * p;
+    p = ABC_CALLOC( SC_WireLoadSel, 1 );
+    p->vAreaFrom      = Vec_FltAlloc( 0 );
+    p->vAreaTo        = Vec_FltAlloc( 0 );
+    p->vWireLoadModel = Vec_PtrAlloc( 0 );
+    return p;
+}
+static inline SC_TableTempl * Abc_SclTableTemplAlloc()
+{
+    SC_TableTempl * p;
+    p = ABC_CALLOC( SC_TableTempl, 1 );
+    p->vVars  = Vec_PtrAlloc( 0 );
+    p->vIndex = Vec_PtrAlloc( 0 );
+    return p;
+}
+static inline SC_Surface * Abc_SclSurfaceAlloc()
+{
+    SC_Surface * p;
+    p = ABC_CALLOC( SC_Surface, 1 );
+    p->vIndex0   = Vec_FltAlloc( 0 );
+    p->vIndex1   = Vec_FltAlloc( 0 );
+    p->vData     = Vec_PtrAlloc( 0 );
+    return p;
+}
+static inline SC_Timing * Abc_SclTimingAlloc()
+{
+    SC_Timing * p;
+    p = ABC_CALLOC( SC_Timing, 1 );
+    p->pCellRise  = Abc_SclSurfaceAlloc();  
+    p->pCellFall  = Abc_SclSurfaceAlloc();
+    p->pRiseTrans = Abc_SclSurfaceAlloc(); 
+    p->pFallTrans = Abc_SclSurfaceAlloc();
+    return p;
+}
+static inline SC_Timings * Abc_SclTimingsAlloc()
+{
+    SC_Timings * p;
+    p = ABC_CALLOC( SC_Timings, 1 );
+    p->vTimings   = Vec_PtrAlloc( 0 );
+    return p;
+}
+static inline SC_Pin * Abc_SclPinAlloc()
+{
+    SC_Pin * p;
+    p = ABC_CALLOC( SC_Pin, 1 );
+    p->max_out_slew = -1;
+    p->vFunc        = Vec_WrdAlloc( 0 );
+    p->vRTimings    = Vec_PtrAlloc( 0 );
+    return p;
+}
+static inline SC_Cell * Abc_SclCellAlloc()
+{
+    SC_Cell * p;
+    p = ABC_CALLOC( SC_Cell, 1 );
+    p->vPins = Vec_PtrAlloc( 0 );
+    return p;
+}
+static inline SC_Lib * Abc_SclLibAlloc()
+{
+    SC_Lib * p;
+    p = ABC_CALLOC( SC_Lib, 1 );
+    p->default_max_out_slew = -1;
+    p->unit_time      = 9;
+    p->unit_cap_fst   = 1;
+    p->unit_cap_snd   = 12;
+    p->vWireLoads     = Vec_PtrAlloc( 0 );
+    p->vWireLoadSels  = Vec_PtrAlloc( 0 );
+    p->vTempls        = Vec_PtrAlloc( 0 );
+    p->vCells         = Vec_PtrAlloc( 0 );
+    p->vCellClasses   = Vec_PtrAlloc( 0 );
+    return p;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Destructors of the library data-structures.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_SclWireLoadFree( SC_WireLoad * p )
+{
+    Vec_IntFree( p->vFanout );
+    Vec_FltFree( p->vLen );
+    ABC_FREE( p->pName );
+    ABC_FREE( p );
+}
+static inline void Abc_SclWireLoadSelFree( SC_WireLoadSel * p )
+{
+    Vec_FltFree( p->vAreaFrom );
+    Vec_FltFree( p->vAreaTo );
+    Vec_PtrFreeFree( p->vWireLoadModel );
+    ABC_FREE( p->pName );
+    ABC_FREE( p );
+}
+static inline void Abc_SclTableTemplFree( SC_TableTempl * p )
+{
+    Vec_PtrFreeFree( p->vVars );
+    Vec_VecFree( (Vec_Vec_t *)p->vIndex );
+    ABC_FREE( p->pName );
+    ABC_FREE( p );
+}
+static inline void Abc_SclSurfaceFree( SC_Surface * p )
+{
+    Vec_FltFree( p->vIndex0 );
+    Vec_FltFree( p->vIndex1 );
+    Vec_VecFree( (Vec_Vec_t *)p->vData );
+    ABC_FREE( p->pName );
+    ABC_FREE( p );
+}
+static inline void Abc_SclTimingFree( SC_Timing * p )
+{
+    Abc_SclSurfaceFree( p->pCellRise );
+    Abc_SclSurfaceFree( p->pCellFall );
+    Abc_SclSurfaceFree( p->pRiseTrans );
+    Abc_SclSurfaceFree( p->pFallTrans );
+    ABC_FREE( p->related_pin );
+    ABC_FREE( p->when_text );
+    ABC_FREE( p );
+}
+static inline void Abc_SclTimingsFree( SC_Timings * p )
+{
+    SC_Timing * pTemp;
+    int i;
+    Vec_PtrForEachEntry( SC_Timing *, p->vTimings, pTemp, i )
+        Abc_SclTimingFree( pTemp );
+    Vec_PtrFree( p->vTimings );
+    ABC_FREE( p->pName );
+    ABC_FREE( p );
+}
+static inline void Abc_SclPinFree( SC_Pin * p )
+{
+    SC_Timings * pTemp;
+    int i;
+    SC_PinForEachRTiming( p, pTemp, i )
+        Abc_SclTimingsFree( pTemp );
+    Vec_PtrFree( p->vRTimings );
+    Vec_WrdFree( p->vFunc );
+    ABC_FREE( p->func_text );
+    ABC_FREE( p->pName );
+    ABC_FREE( p );
+}
+static inline void Abc_SclCellFree( SC_Cell * p )
+{
+    SC_Pin * pTemp;
+    int i;
+    SC_CellForEachPin( p, pTemp, i )
+        Abc_SclPinFree( pTemp );
+    Vec_PtrFree( p->vPins );
+    ABC_FREE( p->pName );
+    ABC_FREE( p );
+}
+static inline void Abc_SclLibFree( SC_Lib * p )
+{
+    SC_WireLoad * pWL;
+    SC_WireLoadSel * pWLS;
+    SC_TableTempl * pTempl;
+    SC_Cell * pCell;
+    int i;
+    SC_LibForEachWireLoad( p, pWL, i )
+        Abc_SclWireLoadFree( pWL );
+    Vec_PtrFree( p->vWireLoads );
+    SC_LibForEachWireLoadSel( p, pWLS, i )
+        Abc_SclWireLoadSelFree( pWLS );
+    Vec_PtrFree( p->vWireLoadSels );
+    SC_LibForEachTempl( p, pTempl, i )
+        Abc_SclTableTemplFree( pTempl );
+    Vec_PtrFree( p->vTempls );
+    SC_LibForEachCell( p, pCell, i )
+        Abc_SclCellFree( pCell );
+    Vec_PtrFree( p->vCells );
+    Vec_PtrFree( p->vCellClasses );
+    ABC_FREE( p->pName );
+    ABC_FREE( p->pFileName );
+    ABC_FREE( p->default_wire_load );
+    ABC_FREE( p->default_wire_load_sel );
+    ABC_FREE( p->pBins );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Lookup table delay computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline float Scl_LibLookup( SC_Surface * p, float slew, float load )
+{
+    float * pIndex0, * pIndex1, * pDataS, * pDataS1;
+    float sfrac, lfrac, p0, p1;
+    int s, l;
+
+    // handle constant table
+    if ( Vec_FltSize(p->vIndex0) == 1 && Vec_FltSize(p->vIndex1) == 1 )
+    {
+        Vec_Flt_t * vTemp = (Vec_Flt_t *)Vec_PtrEntry(p->vData, 0);
+        assert( Vec_PtrSize(p->vData) == 1 );
+        assert( Vec_FltSize(vTemp) == 1 );
+        return Vec_FltEntry(vTemp, 0);
+    }
+
+    // Find closest sample points in surface:
+    pIndex0 = Vec_FltArray(p->vIndex0);
+    for ( s = 1; s < Vec_FltSize(p->vIndex0)-1; s++ )
+        if ( pIndex0[s] > slew )
+            break;
+    s--;
+
+    pIndex1 = Vec_FltArray(p->vIndex1);
+    for ( l = 1; l < Vec_FltSize(p->vIndex1)-1; l++ )
+        if ( pIndex1[l] > load )
+            break;
+    l--;
+
+    // Interpolate (or extrapolate) function value from sample points:
+    sfrac = (slew - pIndex0[s]) / (pIndex0[s+1] - pIndex0[s]);
+    lfrac = (load - pIndex1[l]) / (pIndex1[l+1] - pIndex1[l]);
+
+    pDataS  = Vec_FltArray( (Vec_Flt_t *)Vec_PtrEntry(p->vData, s) );
+    pDataS1 = Vec_FltArray( (Vec_Flt_t *)Vec_PtrEntry(p->vData, s+1) );
+
+    p0 = pDataS [l] + lfrac * (pDataS [l+1] - pDataS [l]);
+    p1 = pDataS1[l] + lfrac * (pDataS1[l+1] - pDataS1[l]);
+
+    return p0 + sfrac * (p1 - p0);      // <<== multiply result with K factor here 
+}
+static inline void Scl_LibPinArrival( SC_Timing * pTime, SC_Pair * pArrIn, SC_Pair * pSlewIn, SC_Pair * pLoad, SC_Pair * pArrOut, SC_Pair * pSlewOut )
+{
+    if (pTime->tsense == sc_ts_Pos || pTime->tsense == sc_ts_Non)
+    {
+        pArrOut->rise  = Abc_MaxFloat( pArrOut->rise,  pArrIn->rise + Scl_LibLookup(pTime->pCellRise,  pSlewIn->rise, pLoad->rise) );
+        pArrOut->fall  = Abc_MaxFloat( pArrOut->fall,  pArrIn->fall + Scl_LibLookup(pTime->pCellFall,  pSlewIn->fall, pLoad->fall) );
+        pSlewOut->rise = Abc_MaxFloat( pSlewOut->rise,                Scl_LibLookup(pTime->pRiseTrans, pSlewIn->rise, pLoad->rise) );
+        pSlewOut->fall = Abc_MaxFloat( pSlewOut->fall,                Scl_LibLookup(pTime->pFallTrans, pSlewIn->fall, pLoad->fall) );
+    }
+    if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non)
+    {
+        pArrOut->rise  = Abc_MaxFloat( pArrOut->rise,  pArrIn->fall + Scl_LibLookup(pTime->pCellRise,  pSlewIn->fall, pLoad->rise) );
+        pArrOut->fall  = Abc_MaxFloat( pArrOut->fall,  pArrIn->rise + Scl_LibLookup(pTime->pCellFall,  pSlewIn->rise, pLoad->fall) );
+        pSlewOut->rise = Abc_MaxFloat( pSlewOut->rise,                Scl_LibLookup(pTime->pRiseTrans, pSlewIn->fall, pLoad->rise) );
+        pSlewOut->fall = Abc_MaxFloat( pSlewOut->fall,                Scl_LibLookup(pTime->pFallTrans, pSlewIn->rise, pLoad->fall) );
+    }
+}
+static inline void Scl_LibPinDeparture( SC_Timing * pTime, SC_Pair * pDepIn, SC_Pair * pSlewIn, SC_Pair * pLoad, SC_Pair * pDepOut )
+{
+    if (pTime->tsense == sc_ts_Pos || pTime->tsense == sc_ts_Non)
+    {
+        pDepIn->rise  = Abc_MaxFloat( pDepIn->rise,  pDepOut->rise + Scl_LibLookup(pTime->pCellRise,  pSlewIn->rise, pLoad->rise) );
+        pDepIn->fall  = Abc_MaxFloat( pDepIn->fall,  pDepOut->fall + Scl_LibLookup(pTime->pCellFall,  pSlewIn->fall, pLoad->fall) );
+    }
+    if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non)
+    {
+        pDepIn->fall  = Abc_MaxFloat( pDepIn->fall,  pDepOut->rise + Scl_LibLookup(pTime->pCellRise,  pSlewIn->fall, pLoad->rise) );
+        pDepIn->rise  = Abc_MaxFloat( pDepIn->rise,  pDepOut->fall + Scl_LibLookup(pTime->pCellFall,  pSlewIn->rise, pLoad->fall) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute one timing edge.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline SC_Timing * Scl_CellPinTime( SC_Cell * pCell, int iPin )
+{
+    SC_Pin * pPin;
+    SC_Timings * pRTime;
+    assert( iPin >= 0 && iPin < pCell->n_inputs );
+    pPin = SC_CellPin( pCell, pCell->n_inputs );
+    assert( Vec_PtrSize(pPin->vRTimings) == pCell->n_inputs );
+    pRTime = (SC_Timings *)Vec_PtrEntry( pPin->vRTimings, iPin );
+    if ( Vec_PtrSize(pRTime->vTimings) == 0 )
+        return NULL;
+    assert( Vec_PtrSize(pRTime->vTimings) == 1 );
+    return (SC_Timing *)Vec_PtrEntry( pRTime->vTimings, 0 );
+}
+static inline float Scl_LibPinArrivalEstimate( SC_Cell * pCell, int iPin, float Slew, float Load )
+{
+    SC_Pair LoadIn = { Load, Load };
+    SC_Pair ArrIn  = { 0.0, 0.0 };
+    SC_Pair ArrOut = { 0.0, 0.0 };
+    SC_Pair SlewIn = { 0.0, 0.0 };
+    SC_Pair SlewOut = { 0.0, 0.0 };
+//    Vec_Flt_t * vIndex0 = pTime->pCellRise->vIndex0; // slew
+//    SlewIn.fall = SlewIn.rise = Vec_FltEntry( vIndex0, Vec_FltSize(vIndex0)/2 );
+    SlewIn.fall = SlewIn.rise = Slew; 
+    Scl_LibPinArrival( Scl_CellPinTime(pCell, iPin), &ArrIn, &SlewIn, &LoadIn, &ArrOut, &SlewOut );
+    return  0.5 * ArrOut.fall +  0.5 * ArrOut.rise;
+}
+static inline void Scl_LibHandleInputDriver( SC_Cell * pCell, SC_Pair * pLoadIn, SC_Pair * pArrOut, SC_Pair * pSlewOut )
+{
+    SC_Pair LoadIn   = { 0.0, 0.0 }; // zero input load
+    SC_Pair ArrIn    = { 0.0, 0.0 }; // zero input time
+    SC_Pair SlewIn   = { 0.0, 0.0 }; // zero input slew
+    SC_Pair ArrOut0  = { 0.0, 0.0 }; // output time under zero load
+    SC_Pair ArrOut1  = { 0.0, 0.0 }; // output time under given load
+    SC_Pair SlewOut  = { 0.0, 0.0 }; // output slew under zero load 
+    pSlewOut->fall = pSlewOut->rise = 0;
+    assert( pCell->n_inputs == 1 );
+    Scl_LibPinArrival( Scl_CellPinTime(pCell, 0), &ArrIn, &SlewIn, &LoadIn, &ArrOut0, &SlewOut );
+    Scl_LibPinArrival( Scl_CellPinTime(pCell, 0), &ArrIn, &SlewIn, pLoadIn, &ArrOut1, pSlewOut );
+    pArrOut->fall = ArrOut1.fall - ArrOut0.fall;
+    pArrOut->rise = ArrOut1.rise - ArrOut0.rise;
+}
+
+/*=== sclLiberty.c ===============================================================*/
+extern SC_Lib *      Abc_SclReadLiberty( char * pFileName, int fVerbose, int fVeryVerbose );
+/*=== sclLibScl.c ===============================================================*/
+extern SC_Lib *      Abc_SclReadFromStr( Vec_Str_t * vOut );
+extern SC_Lib *      Abc_SclReadFromFile( char * pFileName );
+extern void          Abc_SclWriteScl( char * pFileName, SC_Lib * p );
+extern void          Abc_SclWriteLiberty( char * pFileName, SC_Lib * p );
+/*=== sclLibUtil.c ===============================================================*/
+extern void          Abc_SclHashCells( SC_Lib * p );
+extern int           Abc_SclCellFind( SC_Lib * p, char * pName );
+extern int           Abc_SclClassCellNum( SC_Cell * pClass );
+extern int           Abc_SclLibClassNum( SC_Lib * pLib );
+extern void          Abc_SclLinkCells( SC_Lib * p );
+extern void          Abc_SclPrintCells( SC_Lib * p, float Slew, float Gain, int fInvOnly, int fShort );
+extern void          Abc_SclLibNormalize( SC_Lib * p );
+extern SC_Cell *     Abc_SclFindInvertor( SC_Lib * p, int fFindBuff );
+extern SC_Cell *     Abc_SclFindSmallestGate( SC_Cell * p, float CinMin );
+extern SC_WireLoad * Abc_SclFindWireLoadModel( SC_Lib * p, float Area );
+extern SC_WireLoad * Abc_SclFetchWireLoadModel( SC_Lib * p, char * pName );
+extern int           Abc_SclHasDelayInfo( void * pScl );
+extern float         Abc_SclComputeAverageSlew( SC_Lib * p );
+extern void          Abc_SclDumpGenlib( char * pFileName, SC_Lib * p, float Slew, float Gain, int nGatesMin );
+extern void          Abc_SclInstallGenlib( void * pScl, float Slew, float Gain, int nGatesMin );
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/map/scl/sclLibScl.c b/abc-build/src/map/scl/sclLibScl.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/scl/sclLibScl.c
@@ -0,0 +1,676 @@
+/**CFile****************************************************************
+
+  FileName    [sclLibScl.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Standard-cell library representation.]
+
+  Synopsis    [Liberty abstraction for delay-oriented mapping.]
+
+  Author      [Alan Mishchenko, Niklas Een]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 24, 2012.]
+
+  Revision    [$Id: sclLibScl.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sclLib.h"
+#include "misc/st/st.h"
+#include "map/mio/mio.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reading library from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Abc_SclReadSurface( Vec_Str_t * vOut, int * pPos, SC_Surface * p )
+{
+    Vec_Flt_t * vVec;
+    int i, j;
+
+    for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- )
+        Vec_FltPush( p->vIndex0, Vec_StrGetF(vOut, pPos) );
+
+    for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- )
+        Vec_FltPush( p->vIndex1, Vec_StrGetF(vOut, pPos) );
+
+    for ( i = 0; i < Vec_FltSize(p->vIndex0); i++ )
+    {
+        vVec = Vec_FltAlloc( Vec_FltSize(p->vIndex1) );
+        Vec_PtrPush( p->vData, vVec );
+        for ( j = 0; j < Vec_FltSize(p->vIndex1); j++ )
+            Vec_FltPush( vVec, Vec_StrGetF(vOut, pPos) );
+    }
+
+    for ( i = 0; i < 3; i++ ) 
+        p->approx[0][i] = Vec_StrGetF( vOut, pPos );
+    for ( i = 0; i < 4; i++ ) 
+        p->approx[1][i] = Vec_StrGetF( vOut, pPos );
+    for ( i = 0; i < 6; i++ ) 
+        p->approx[2][i] = Vec_StrGetF( vOut, pPos );
+}
+static int Abc_SclReadLibrary( Vec_Str_t * vOut, int * pPos, SC_Lib * p )
+{
+    int i, j, k, n;
+    int version = Vec_StrGetI( vOut, pPos );
+    if ( version != ABC_SCL_CUR_VERSION )
+    { 
+        Abc_Print( -1, "Wrong version of the SCL file.\n" ); 
+        return 0; 
+    }
+    assert( version == ABC_SCL_CUR_VERSION ); // wrong version of the file
+
+    // Read non-composite fields:
+    p->pName                 = Vec_StrGetS(vOut, pPos);
+    p->default_wire_load     = Vec_StrGetS(vOut, pPos);
+    p->default_wire_load_sel = Vec_StrGetS(vOut, pPos);
+    p->default_max_out_slew  = Vec_StrGetF(vOut, pPos);
+
+    p->unit_time             = Vec_StrGetI(vOut, pPos);
+    p->unit_cap_fst          = Vec_StrGetF(vOut, pPos);
+    p->unit_cap_snd          = Vec_StrGetI(vOut, pPos);
+
+    // Read 'wire_load' vector:
+    for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- )
+    {
+        SC_WireLoad * pWL = Abc_SclWireLoadAlloc();
+        Vec_PtrPush( p->vWireLoads, pWL );
+
+        pWL->pName = Vec_StrGetS(vOut, pPos);
+        pWL->cap   = Vec_StrGetF(vOut, pPos);
+        pWL->slope = Vec_StrGetF(vOut, pPos);
+
+        for ( j = Vec_StrGetI(vOut, pPos); j != 0; j-- )
+        {
+            Vec_IntPush( pWL->vFanout, Vec_StrGetI(vOut, pPos) );
+            Vec_FltPush( pWL->vLen,    Vec_StrGetF(vOut, pPos) );
+        }
+    }
+
+    // Read 'wire_load_sel' vector:
+    for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- )
+    {
+        SC_WireLoadSel * pWLS = Abc_SclWireLoadSelAlloc();
+        Vec_PtrPush( p->vWireLoadSels, pWLS );
+
+        pWLS->pName = Vec_StrGetS(vOut, pPos);
+        for ( j = Vec_StrGetI(vOut, pPos); j != 0; j-- )
+        {
+            Vec_FltPush( pWLS->vAreaFrom,      Vec_StrGetF(vOut, pPos) );
+            Vec_FltPush( pWLS->vAreaTo,        Vec_StrGetF(vOut, pPos) );
+            Vec_PtrPush( pWLS->vWireLoadModel, Vec_StrGetS(vOut, pPos) );
+        }
+    }
+
+    for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- )
+    {
+        SC_Cell * pCell = Abc_SclCellAlloc();
+        pCell->Id = SC_LibCellNum(p);
+        Vec_PtrPush( p->vCells, pCell );
+
+        pCell->pName           = Vec_StrGetS(vOut, pPos);     
+        pCell->area           = Vec_StrGetF(vOut, pPos);
+        pCell->drive_strength = Vec_StrGetI(vOut, pPos);
+
+        pCell->n_inputs       = Vec_StrGetI(vOut, pPos);
+        pCell->n_outputs      = Vec_StrGetI(vOut, pPos);
+/*
+        printf( "%s\n", pCell->pName );
+        if ( !strcmp( "XOR3_X4M_A9TL", pCell->pName ) )
+        {
+            int s = 0;
+        }
+*/
+        for ( j = 0; j < pCell->n_inputs; j++ )
+        {
+            SC_Pin * pPin = Abc_SclPinAlloc();
+            Vec_PtrPush( pCell->vPins, pPin );
+
+            pPin->dir      = sc_dir_Input;
+            pPin->pName    = Vec_StrGetS(vOut, pPos); 
+            pPin->rise_cap = Vec_StrGetF(vOut, pPos);
+            pPin->fall_cap = Vec_StrGetF(vOut, pPos);
+        }
+
+        for ( j = 0; j < pCell->n_outputs; j++ )
+        {
+            SC_Pin * pPin = Abc_SclPinAlloc();
+            Vec_PtrPush( pCell->vPins, pPin );
+
+            pPin->dir          = sc_dir_Output;
+            pPin->pName        = Vec_StrGetS(vOut, pPos); 
+            pPin->max_out_cap  = Vec_StrGetF(vOut, pPos);
+            pPin->max_out_slew = Vec_StrGetF(vOut, pPos);
+
+            k = Vec_StrGetI(vOut, pPos);
+            assert( k == pCell->n_inputs );
+
+            // read function
+            // (possibly empty) formula is always given
+            assert( version == ABC_SCL_CUR_VERSION );
+            assert( pPin->func_text == NULL );
+            pPin->func_text = Vec_StrGetS(vOut, pPos); 
+            if ( pPin->func_text[0] == 0 )
+            {
+                // formula is not given - read truth table
+                ABC_FREE( pPin->func_text );
+                assert( Vec_WrdSize(pPin->vFunc) == 0 );
+                Vec_WrdGrow( pPin->vFunc, Abc_Truth6WordNum(pCell->n_inputs) );
+                for ( k = 0; k < Vec_WrdCap(pPin->vFunc); k++ )
+                    Vec_WrdPush( pPin->vFunc, Vec_StrGetW(vOut, pPos) );
+            }
+            else
+            {
+                // formula is given - derive truth table
+                SC_Pin * pPin2;
+                Vec_Ptr_t * vNames;
+                // collect input names
+                vNames = Vec_PtrAlloc( pCell->n_inputs );
+                SC_CellForEachPinIn( pCell, pPin2, n )
+                    Vec_PtrPush( vNames, pPin2->pName );
+                // derive truth table
+                assert( Vec_WrdSize(pPin->vFunc) == 0 );
+                Vec_WrdFree( pPin->vFunc );
+                pPin->vFunc = Mio_ParseFormulaTruth( pPin->func_text, (char **)Vec_PtrArray(vNames), pCell->n_inputs );
+                Vec_PtrFree( vNames );
+                // skip truth table
+                assert( Vec_WrdSize(pPin->vFunc) == Abc_Truth6WordNum(pCell->n_inputs) );
+                for ( k = 0; k < Vec_WrdSize(pPin->vFunc); k++ )
+                {
+                    word Value = Vec_StrGetW(vOut, pPos);
+                    assert( Value == Vec_WrdEntry(pPin->vFunc, k) );
+                }
+            }
+
+            // Read 'rtiming': (pin-to-pin timing tables for this particular output)
+            for ( k = 0; k < pCell->n_inputs; k++ )
+            {
+                SC_Timings * pRTime = Abc_SclTimingsAlloc();
+                Vec_PtrPush( pPin->vRTimings, pRTime );
+
+                pRTime->pName = Vec_StrGetS(vOut, pPos);
+                n = Vec_StrGetI(vOut, pPos); assert( n <= 1 );
+                if ( n == 1 )
+                {
+                    SC_Timing * pTime = Abc_SclTimingAlloc();
+                    Vec_PtrPush( pRTime->vTimings, pTime );
+
+                    pTime->tsense = (SC_TSense)Vec_StrGetI(vOut, pPos);
+                    Abc_SclReadSurface( vOut, pPos, pTime->pCellRise );
+                    Abc_SclReadSurface( vOut, pPos, pTime->pCellFall );
+                    Abc_SclReadSurface( vOut, pPos, pTime->pRiseTrans );
+                    Abc_SclReadSurface( vOut, pPos, pTime->pFallTrans );
+                }
+                else
+                    assert( Vec_PtrSize(pRTime->vTimings) == 0 );
+            }
+        }
+    }
+    return 1;
+}
+SC_Lib * Abc_SclReadFromStr( Vec_Str_t * vOut )
+{
+    SC_Lib * p;
+    int Pos = 0;
+    // read the library
+    p = Abc_SclLibAlloc();
+    if ( !Abc_SclReadLibrary( vOut, &Pos, p ) )
+        return NULL;
+    assert( Pos == Vec_StrSize(vOut) );
+    // hash gates by name
+    Abc_SclHashCells( p );
+    Abc_SclLinkCells( p );
+    return p;
+}
+SC_Lib * Abc_SclReadFromFile( char * pFileName )
+{
+    SC_Lib * p;
+    FILE * pFile;
+    Vec_Str_t * vOut;
+    int nFileSize;
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\" for reading.\n", pFileName );
+        return NULL;
+    }
+    // get the file size, in bytes
+    fseek( pFile, 0, SEEK_END );  
+    nFileSize = ftell( pFile );  
+    rewind( pFile ); 
+    // load the contents
+    vOut = Vec_StrAlloc( nFileSize );
+    vOut->nSize = vOut->nCap;
+    assert( nFileSize == Vec_StrSize(vOut) );
+    nFileSize = fread( Vec_StrArray(vOut), 1, Vec_StrSize(vOut), pFile );
+    assert( nFileSize == Vec_StrSize(vOut) );
+    fclose( pFile );
+    // read the library
+    p = Abc_SclReadFromStr( vOut );
+    if ( p != NULL )
+        p->pFileName = Abc_UtilStrsav( pFileName );
+    if ( p != NULL )
+        Abc_SclLibNormalize( p );
+    Vec_StrFree( vOut );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writing library into file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Abc_SclWriteSurface( Vec_Str_t * vOut, SC_Surface * p )
+{
+    Vec_Flt_t * vVec;
+    float Entry;
+    int i, k;
+
+    Vec_StrPutI( vOut, Vec_FltSize(p->vIndex0) );
+    Vec_FltForEachEntry( p->vIndex0, Entry, i )
+        Vec_StrPutF( vOut, Entry );
+
+    Vec_StrPutI( vOut, Vec_FltSize(p->vIndex1) );
+    Vec_FltForEachEntry( p->vIndex1, Entry, i )
+        Vec_StrPutF( vOut, Entry );
+
+    Vec_PtrForEachEntry( Vec_Flt_t *, p->vData, vVec, i )
+        Vec_FltForEachEntry( vVec, Entry, k )
+            Vec_StrPutF( vOut, Entry );
+
+    for ( i = 0; i < 3; i++ ) 
+        Vec_StrPutF( vOut, p->approx[0][i] );
+    for ( i = 0; i < 4; i++ ) 
+        Vec_StrPutF( vOut, p->approx[1][i] );
+    for ( i = 0; i < 6; i++ ) 
+        Vec_StrPutF( vOut, p->approx[2][i] );
+}
+static void Abc_SclWriteLibrary( Vec_Str_t * vOut, SC_Lib * p )
+{
+    SC_WireLoad * pWL;
+    SC_WireLoadSel * pWLS;
+    SC_Cell * pCell;
+    SC_Pin * pPin;
+    int n_valid_cells;
+    int i, j, k;
+
+    Vec_StrPutI( vOut, ABC_SCL_CUR_VERSION );
+
+    // Write non-composite fields:
+    Vec_StrPutS( vOut, p->pName );
+    Vec_StrPutS( vOut, p->default_wire_load );
+    Vec_StrPutS( vOut, p->default_wire_load_sel );
+    Vec_StrPutF( vOut, p->default_max_out_slew );
+
+    assert( p->unit_time >= 0 );
+    assert( p->unit_cap_snd >= 0 );
+    Vec_StrPutI( vOut, p->unit_time );
+    Vec_StrPutF( vOut, p->unit_cap_fst );
+    Vec_StrPutI( vOut, p->unit_cap_snd );
+
+    // Write 'wire_load' vector:
+    Vec_StrPutI( vOut, Vec_PtrSize(p->vWireLoads) );
+    SC_LibForEachWireLoad( p, pWL, i )
+    {
+        Vec_StrPutS( vOut, pWL->pName );
+        Vec_StrPutF( vOut, pWL->cap );
+        Vec_StrPutF( vOut, pWL->slope );
+
+        Vec_StrPutI( vOut, Vec_IntSize(pWL->vFanout) );
+        for ( j = 0; j < Vec_IntSize(pWL->vFanout); j++ )
+        {
+            Vec_StrPutI( vOut, Vec_IntEntry(pWL->vFanout, j) );
+            Vec_StrPutF( vOut, Vec_FltEntry(pWL->vLen, j) );
+        }
+    }
+
+    // Write 'wire_load_sel' vector:
+    Vec_StrPutI( vOut, Vec_PtrSize(p->vWireLoadSels) );
+    SC_LibForEachWireLoadSel( p, pWLS, i )
+    {
+        Vec_StrPutS( vOut, pWLS->pName );
+        Vec_StrPutI( vOut, Vec_FltSize(pWLS->vAreaFrom) );
+        for ( j = 0; j < Vec_FltSize(pWLS->vAreaFrom); j++)
+        {
+            Vec_StrPutF( vOut, Vec_FltEntry(pWLS->vAreaFrom, j) );
+            Vec_StrPutF( vOut, Vec_FltEntry(pWLS->vAreaTo, j) );
+            Vec_StrPutS( vOut, (char *)Vec_PtrEntry(pWLS->vWireLoadModel, j) );
+        }
+    }
+
+    // Write 'cells' vector:
+    n_valid_cells = 0;
+    SC_LibForEachCell( p, pCell, i )
+        if ( !(pCell->seq || pCell->unsupp) )
+            n_valid_cells++;
+
+    Vec_StrPutI( vOut, n_valid_cells );
+    SC_LibForEachCell( p, pCell, i )
+    {
+        if ( pCell->seq || pCell->unsupp )
+            continue;
+
+        Vec_StrPutS( vOut, pCell->pName );
+        Vec_StrPutF( vOut, pCell->area );
+        Vec_StrPutI( vOut, pCell->drive_strength );
+
+        // Write 'pins': (sorted at this point; first inputs, then outputs)
+        Vec_StrPutI( vOut, pCell->n_inputs);
+        Vec_StrPutI( vOut, pCell->n_outputs);
+
+        SC_CellForEachPinIn( pCell, pPin, j )
+        {
+            assert(pPin->dir == sc_dir_Input);
+            Vec_StrPutS( vOut, pPin->pName );
+            Vec_StrPutF( vOut, pPin->rise_cap );
+            Vec_StrPutF( vOut, pPin->fall_cap );
+        }
+
+        SC_CellForEachPinOut( pCell, pPin, j )
+        {
+            SC_Timings * pRTime;
+            word uWord;
+
+            assert(pPin->dir == sc_dir_Output);
+            Vec_StrPutS( vOut, pPin->pName );
+            Vec_StrPutF( vOut, pPin->max_out_cap );
+            Vec_StrPutF( vOut, pPin->max_out_slew );
+            Vec_StrPutI( vOut, pCell->n_inputs );
+
+            // write function
+            Vec_StrPutS( vOut, pPin->func_text ? pPin->func_text : (char *)"" );
+
+            // write truth table
+            assert( Vec_WrdSize(pPin->vFunc) == Abc_Truth6WordNum(pCell->n_inputs) );
+            Vec_WrdForEachEntry( pPin->vFunc, uWord, k ) // -- 'size = 1u << (n_vars - 6)'
+                Vec_StrPutW( vOut, uWord );  // -- 64-bit number, written uncompressed (low-byte first)
+
+            // Write 'rtiming': (pin-to-pin timing tables for this particular output)
+            assert( Vec_PtrSize(pPin->vRTimings) == pCell->n_inputs );
+            SC_PinForEachRTiming( pPin, pRTime, k )
+            {
+                Vec_StrPutS( vOut, pRTime->pName );
+                Vec_StrPutI( vOut, Vec_PtrSize(pRTime->vTimings) );
+                    // -- NOTE! After post-processing, the size of the 'rtiming[k]' vector is either
+                    // 0 or 1 (in static timing, we have merged all tables to get the worst case).
+                    // The case with size 0 should only occur for multi-output gates.
+                if ( Vec_PtrSize(pRTime->vTimings) == 1 )
+                {
+                    SC_Timing * pTime = (SC_Timing *)Vec_PtrEntry( pRTime->vTimings, 0 );
+                        // -- NOTE! We don't need to save 'related_pin' string because we have sorted 
+                        // the elements on input pins.
+                    Vec_StrPutI( vOut, (int)pTime->tsense);
+                    Abc_SclWriteSurface( vOut, pTime->pCellRise );
+                    Abc_SclWriteSurface( vOut, pTime->pCellFall );
+                    Abc_SclWriteSurface( vOut, pTime->pRiseTrans );
+                    Abc_SclWriteSurface( vOut, pTime->pFallTrans );
+                }
+                else
+                    assert( Vec_PtrSize(pRTime->vTimings) == 0 );
+            }
+        }
+    }
+}
+void Abc_SclWriteScl( char * pFileName, SC_Lib * p )
+{
+    Vec_Str_t * vOut;
+    vOut = Vec_StrAlloc( 10000 );
+    Abc_SclWriteLibrary( vOut, p );
+    if ( Vec_StrSize(vOut) > 0 )
+    {
+        FILE * pFile = fopen( pFileName, "wb" );
+        if ( pFile == NULL )
+            printf( "Cannot open file \"%s\" for writing.\n", pFileName );
+        else
+        {
+            fwrite( Vec_StrArray(vOut), 1, Vec_StrSize(vOut), pFile );
+            fclose( pFile );
+        }
+    }
+    Vec_StrFree( vOut );    
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writing library into text file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Abc_SclWriteSurfaceText( FILE * s, SC_Surface * p )
+{
+    Vec_Flt_t * vVec;
+    float Entry;
+    int i, k;
+
+    fprintf( s, "          index_1(\"" );  
+    Vec_FltForEachEntry( p->vIndex0, Entry, i )
+        fprintf( s, "%f%s", Entry, i == Vec_FltSize(p->vIndex0)-1 ? "":", " );
+    fprintf( s, "\");\n" );
+
+    fprintf( s, "          index_2(\"" );  
+    Vec_FltForEachEntry( p->vIndex1, Entry, i )
+        fprintf( s, "%f%s", Entry, i == Vec_FltSize(p->vIndex1)-1 ? "":", " );
+    fprintf( s, "\");\n" );
+
+    fprintf( s, "          values (\"" );  
+    Vec_PtrForEachEntry( Vec_Flt_t *, p->vData, vVec, i )
+    {
+        Vec_FltForEachEntry( vVec, Entry, k )
+            fprintf( s, "%f%s", Entry, i == Vec_PtrSize(p->vData)-1 && k == Vec_FltSize(vVec)-1 ? "\");":", " );
+        if ( i == Vec_PtrSize(p->vData)-1 )
+            fprintf( s, "\n" );
+        else
+        {
+            fprintf( s, "\\\n" );
+            fprintf( s, "                   " );  
+        }
+    }
+/*
+    fprintf( s, "       approximations: \n" );
+    fprintf( s, "       " );
+    for ( i = 0; i < 3; i++ ) 
+        fprintf( s, "%f ", p->approx[0][i] );
+    fprintf( s, "\n" );
+    fprintf( s, "       " );
+    for ( i = 0; i < 4; i++ ) 
+        fprintf( s, "%f ", p->approx[1][i] );
+    fprintf( s, "\n" );
+    fprintf( s, "       " );
+    for ( i = 0; i < 6; i++ ) 
+        fprintf( s, "%f ", p->approx[2][i] );
+    fprintf( s, "\n" );
+    fprintf( s, "       \n" );
+*/
+}
+static void Abc_SclWriteLibraryText( FILE * s, SC_Lib * p )
+{
+    SC_WireLoad * pWL;
+    SC_WireLoadSel * pWLS;
+    SC_Cell * pCell;
+    SC_Pin * pPin;
+    int n_valid_cells;
+    int i, j, k;
+    fprintf( s, "/* This Liberty file was generated by ABC on %s */\n", Extra_TimeStamp() );
+    fprintf( s, "/* The original unabridged library came from file \"%s\".*/\n\n", p->pFileName );
+
+//    fprintf( s, "%d", ABC_SCL_CUR_VERSION );
+    fprintf( s, "library(%s) {\n\n",                         p->pName );
+    if ( p->default_wire_load && strlen(p->default_wire_load) )
+    fprintf( s, "  default_wire_load : \"%s\";\n",           p->default_wire_load );
+    if ( p->default_wire_load_sel && strlen(p->default_wire_load_sel) )
+    fprintf( s, "  default_wire_load_selection : \"%s\";\n", p->default_wire_load_sel );
+    if ( p->default_max_out_slew != -1 )
+    fprintf( s, "  default_max_transition : %f;\n",          p->default_max_out_slew );
+    if ( p->unit_time == 9 )
+    fprintf( s, "  time_unit : \"1ns\";\n" );
+    else if ( p->unit_time == 10 )
+    fprintf( s, "  time_unit : \"100ps\";\n" );
+    else if ( p->unit_time == 11 )
+    fprintf( s, "  time_unit : \"10ps\";\n" );
+    else if ( p->unit_time == 12 )
+    fprintf( s, "  time_unit : \"1ps\";\n" );
+    else assert( 0 );
+    fprintf( s, "  capacitive_load_unit(%.1f,%s);\n",        p->unit_cap_fst, p->unit_cap_snd == 12 ? "pf" : "ff" );
+    fprintf( s, "\n" );
+
+    // Write 'wire_load' vector:
+    SC_LibForEachWireLoad( p, pWL, i )
+    {
+        fprintf( s, "  wire_load(\"%s\") {\n", pWL->pName );
+        fprintf( s, "    capacitance : %f;\n", pWL->cap );
+        fprintf( s, "    slope : %f;\n", pWL->slope );
+        for ( j = 0; j < Vec_IntSize(pWL->vFanout); j++ )
+            fprintf( s, "    fanout_length( %d, %f );\n", Vec_IntEntry(pWL->vFanout, j), Vec_FltEntry(pWL->vLen, j) );
+        fprintf( s, "  }\n\n" );
+    }
+
+    // Write 'wire_load_sel' vector:
+    SC_LibForEachWireLoadSel( p, pWLS, i )
+    {
+        fprintf( s, "  wire_load_selection(\"%s\") {\n", pWLS->pName );
+        for ( j = 0; j < Vec_FltSize(pWLS->vAreaFrom); j++)
+            fprintf( s, "    wire_load_from_area( %f, %f, %s );\n", 
+                Vec_FltEntry(pWLS->vAreaFrom, j), 
+                Vec_FltEntry(pWLS->vAreaTo, j), 
+                (char *)Vec_PtrEntry(pWLS->vWireLoadModel, j) );
+        fprintf( s, "  }\n\n" );
+    }
+
+    // Write 'cells' vector:
+    n_valid_cells = 0;
+    SC_LibForEachCell( p, pCell, i )
+        if ( !(pCell->seq || pCell->unsupp) )
+            n_valid_cells++;
+
+    SC_LibForEachCell( p, pCell, i )
+    {
+        if ( pCell->seq || pCell->unsupp )
+            continue;
+
+        fprintf( s, "\n" );
+        fprintf( s, "  cell(%s) {\n", pCell->pName );
+        fprintf( s, "    /*  n_inputs = %d  n_outputs = %d */\n", pCell->n_inputs, pCell->n_outputs );
+        fprintf( s, "    area : %f;\n", pCell->area );
+        fprintf( s, "    drive_strength : %d;\n", pCell->drive_strength );
+
+        SC_CellForEachPinIn( pCell, pPin, j )
+        {
+            assert(pPin->dir == sc_dir_Input);
+            fprintf( s, "    pin(%s) {\n", pPin->pName );
+            fprintf( s, "      direction : %s;\n", "input" );
+            fprintf( s, "      fall_capacitance : %f;\n", pPin->fall_cap );
+            fprintf( s, "      rise_capacitance : %f;\n", pPin->rise_cap );
+            fprintf( s, "    }\n" );
+        }
+
+        SC_CellForEachPinOut( pCell, pPin, j )
+        {
+            SC_Timings * pRTime;
+//            word uWord;
+            assert(pPin->dir == sc_dir_Output);
+            fprintf( s, "    pin(%s) {\n", pPin->pName );
+            fprintf( s, "      direction : %s;\n", "output" );
+            fprintf( s, "      max_capacitance : %f;\n", pPin->max_out_cap );
+            fprintf( s, "      max_transition : %f;\n", pPin->max_out_slew );
+            fprintf( s, "      function : \"%s\";\n", pPin->func_text ? pPin->func_text : "?" );
+            fprintf( s, "      /*  truth table = " );
+            Extra_PrintHex( s, (unsigned *)Vec_WrdArray(pPin->vFunc), pCell->n_inputs );
+            fprintf( s, "  */\n" );
+
+            // Write 'rtiming': (pin-to-pin timing tables for this particular output)
+            assert( Vec_PtrSize(pPin->vRTimings) == pCell->n_inputs );
+            SC_PinForEachRTiming( pPin, pRTime, k )
+            {
+                if ( Vec_PtrSize(pRTime->vTimings) == 1 )
+                {
+                    SC_Timing * pTime = (SC_Timing *)Vec_PtrEntry( pRTime->vTimings, 0 );
+                    fprintf( s, "      timing() {\n" );
+                    fprintf( s, "        related_pin : \"%s\"\n", pRTime->pName );
+                    if ( pTime->tsense == sc_ts_Pos )
+                        fprintf( s, "        timing_sense : positive_unate;\n" );
+                    else if ( pTime->tsense == sc_ts_Neg )
+                        fprintf( s, "        timing_sense : negative_unate;\n" );
+                    else if ( pTime->tsense == sc_ts_Non )
+                        fprintf( s, "        timing_sense : non_unate;\n" );
+                    else assert( 0 );
+
+                    fprintf( s, "        cell_rise() {\n" );
+                    Abc_SclWriteSurfaceText( s, pTime->pCellRise );
+                    fprintf( s, "        }\n" );
+
+                    fprintf( s, "        cell_fall() {\n" );
+                    Abc_SclWriteSurfaceText( s, pTime->pCellFall );
+                    fprintf( s, "        }\n" );
+
+                    fprintf( s, "        rise_transition() {\n" );
+                    Abc_SclWriteSurfaceText( s, pTime->pRiseTrans );
+                    fprintf( s, "        }\n" );
+
+                    fprintf( s, "        fall_transition() {\n" );
+                    Abc_SclWriteSurfaceText( s, pTime->pFallTrans );
+                    fprintf( s, "        }\n" );
+                    fprintf( s, "      }\n" );
+                }
+                else
+                    assert( Vec_PtrSize(pRTime->vTimings) == 0 );
+            }
+            fprintf( s, "    }\n" );
+        }
+        fprintf( s, "  }\n" );
+    }
+    fprintf( s, "}\n\n" );
+}
+void Abc_SclWriteLiberty( char * pFileName, SC_Lib * p )
+{
+    FILE * pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+        printf( "Cannot open text file \"%s\" for writing.\n", pFileName );
+    else
+    {
+        Abc_SclWriteLibraryText( pFile, p );
+        fclose( pFile );
+        printf( "Dumped internal library into Liberty file \"%s\".\n", pFileName );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/scl/sclLibUtil.c b/abc-build/src/map/scl/sclLibUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/scl/sclLibUtil.c
@@ -0,0 +1,852 @@
+/**CFile****************************************************************
+
+  FileName    [sclLibUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Standard-cell library representation.]
+
+  Synopsis    [Various library utilities.]
+
+  Author      [Alan Mishchenko, Niklas Een]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 24, 2012.]
+
+  Revision    [$Id: sclLibUtil.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sclLib.h"
+#include "misc/st/st.h"
+#include "map/mio/mio.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reading library from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static unsigned Abc_SclHashString( char * pName, int TableSize ) 
+{
+    static int s_Primes[10] = { 1291, 1699, 2357, 4177, 5147, 5647, 6343, 7103, 7873, 8147 };
+    unsigned i, Key = 0;
+    for ( i = 0; pName[i] != '\0'; i++ )
+        Key += s_Primes[i%10]*pName[i]*pName[i];
+    return Key % TableSize;
+}
+int * Abc_SclHashLookup( SC_Lib * p, char * pName )
+{
+    int i;
+    for ( i = Abc_SclHashString(pName, p->nBins); i < p->nBins; i = (i + 1) % p->nBins )
+        if ( p->pBins[i] == -1 || !strcmp(pName, SC_LibCell(p, p->pBins[i])->pName) )
+            return p->pBins + i;
+    assert( 0 );
+    return NULL;
+}
+void Abc_SclHashCells( SC_Lib * p )
+{
+    SC_Cell * pCell;
+    int i, * pPlace;
+    assert( p->nBins == 0 );
+    p->nBins = Abc_PrimeCudd( 5 * SC_LibCellNum(p) );
+    p->pBins = ABC_FALLOC( int, p->nBins );
+    SC_LibForEachCell( p, pCell, i )
+    {
+        pPlace = Abc_SclHashLookup( p, pCell->pName );
+        assert( *pPlace == -1 );
+        *pPlace = i;
+    }
+}
+int Abc_SclCellFind( SC_Lib * p, char * pName )
+{
+    int *pPlace = Abc_SclHashLookup( p, pName );
+    return pPlace ? *pPlace : -1;
+}
+int Abc_SclClassCellNum( SC_Cell * pClass )
+{
+    SC_Cell * pCell;
+    int i, Count = 0;
+    SC_RingForEachCell( pClass, pCell, i )
+        if ( !pCell->fSkip )
+            Count++;
+    return Count;
+}
+int Abc_SclLibClassNum( SC_Lib * pLib )
+{
+    SC_Cell * pRepr;
+    int i, Count = 0;
+    SC_LibForEachCellClass( pLib, pRepr, i )
+        Count++;
+    return Count;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Links equal gates into rings while sorting them by area.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Abc_SclCompareCells( SC_Cell ** pp1, SC_Cell ** pp2 )
+{
+    if ( (*pp1)->n_inputs < (*pp2)->n_inputs )
+        return -1;
+    if ( (*pp1)->n_inputs > (*pp2)->n_inputs )
+        return 1;
+//    if ( (*pp1)->area < (*pp2)->area )
+//        return -1;
+//    if ( (*pp1)->area > (*pp2)->area )
+//        return 1;
+    if ( SC_CellPinCapAve(*pp1) < SC_CellPinCapAve(*pp2) )
+        return -1;
+    if ( SC_CellPinCapAve(*pp1) > SC_CellPinCapAve(*pp2) )
+        return 1;
+    return strcmp( (*pp1)->pName, (*pp2)->pName );
+}
+void Abc_SclLinkCells( SC_Lib * p )
+{
+    Vec_Ptr_t * vList;
+    SC_Cell * pCell, * pRepr = NULL;
+    int i, k;
+    assert( Vec_PtrSize(p->vCellClasses) == 0 );
+    SC_LibForEachCell( p, pCell, i )
+    {
+        // find gate with the same function
+        SC_LibForEachCellClass( p, pRepr, k )
+            if ( pCell->n_inputs  == pRepr->n_inputs && 
+                 pCell->n_outputs == pRepr->n_outputs && 
+                 Vec_WrdEqual(SC_CellFunc(pCell), SC_CellFunc(pRepr)) )
+                break;
+        if ( k == Vec_PtrSize(p->vCellClasses) )
+        {
+            Vec_PtrPush( p->vCellClasses, pCell );
+            pCell->pNext = pCell->pPrev = pCell;
+            continue;
+        }
+        // add it to the list before the cell
+        pRepr->pPrev->pNext = pCell; pCell->pNext = pRepr;
+        pCell->pPrev = pRepr->pPrev; pRepr->pPrev = pCell;
+    }
+    // sort cells by size then by name
+    qsort( (void *)Vec_PtrArray(p->vCellClasses), Vec_PtrSize(p->vCellClasses), sizeof(void *), (int(*)(const void *,const void *))Abc_SclCompareCells );
+    // sort cell lists
+    vList = Vec_PtrAlloc( 100 );
+    SC_LibForEachCellClass( p, pRepr, k )
+    {
+        Vec_PtrClear( vList );
+        SC_RingForEachCell( pRepr, pCell, i )
+            Vec_PtrPush( vList, pCell );
+        qsort( (void *)Vec_PtrArray(vList), Vec_PtrSize(vList), sizeof(void *), (int(*)(const void *,const void *))Abc_SclCompareCells );
+        // create new representative
+        pRepr = (SC_Cell *)Vec_PtrEntry( vList, 0 );
+        pRepr->pNext = pRepr->pPrev = pRepr;
+        pRepr->pRepr = pRepr;
+        pRepr->pAve  = (SC_Cell *)Vec_PtrEntry( vList, Vec_PtrSize(vList)/2 );
+        pRepr->Order = 0;
+        pRepr->nGates = Vec_PtrSize(vList);
+        // relink cells
+        Vec_PtrForEachEntryStart( SC_Cell *, vList, pCell, i, 1 )
+        {
+            pRepr->pPrev->pNext = pCell; pCell->pNext = pRepr;
+            pCell->pPrev = pRepr->pPrev; pRepr->pPrev = pCell;
+            pCell->pRepr = pRepr;
+            pCell->pAve  = (SC_Cell *)Vec_PtrEntry( vList, Vec_PtrSize(vList)/2 );
+            pCell->Order = i;
+            pCell->nGates = Vec_PtrSize(vList);
+        }
+        // update list
+        Vec_PtrWriteEntry( p->vCellClasses, k, pRepr );
+    }
+    Vec_PtrFree( vList );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the largest inverter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+SC_Cell * Abc_SclFindInvertor( SC_Lib * p, int fFindBuff )
+{
+    SC_Cell * pCell = NULL;
+    word Truth = fFindBuff ? ABC_CONST(0xAAAAAAAAAAAAAAAA) : ABC_CONST(0x5555555555555555);
+    int k;
+    SC_LibForEachCellClass( p, pCell, k )
+        if ( pCell->n_inputs == 1 && Vec_WrdEntry(SC_CellPin(pCell, 1)->vFunc, 0) == Truth )
+            break;
+    // take representative
+    return pCell ? pCell->pRepr : NULL;
+}
+SC_Cell * Abc_SclFindSmallestGate( SC_Cell * p, float CinMin )
+{
+    SC_Cell * pRes = NULL;
+    int i;
+    SC_RingForEachCell( p->pRepr, pRes, i )
+        if ( SC_CellPinCapAve(pRes) > CinMin )
+            return pRes;
+    // take the largest gate
+    return p->pRepr->pPrev;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the wireload model for the given area.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+SC_WireLoad * Abc_SclFetchWireLoadModel( SC_Lib * p, char * pWLoadUsed )
+{
+    SC_WireLoad * pWL = NULL;
+    int i;
+    // Get the actual table and reformat it for 'wire_cap' output:
+    assert( pWLoadUsed != NULL );
+    SC_LibForEachWireLoad( p, pWL, i )
+        if ( !strcmp(pWL->pName, pWLoadUsed) )
+            break;
+    if ( i == Vec_PtrSize(p->vWireLoads) )
+    {
+        Abc_Print( -1, "Cannot find wire load model \"%s\".\n", pWLoadUsed );
+        exit(1);
+    }
+//    printf( "Using wireload model \"%s\".\n", pWL->pName );
+    return pWL;
+}
+SC_WireLoad * Abc_SclFindWireLoadModel( SC_Lib * p, float Area )
+{
+    char * pWLoadUsed = NULL;
+    int i;
+    if ( p->default_wire_load_sel && strlen(p->default_wire_load_sel) )
+    {
+        SC_WireLoadSel * pWLS = NULL;
+        SC_LibForEachWireLoadSel( p, pWLS, i )
+            if ( !strcmp(pWLS->pName, p->default_wire_load_sel) )
+                break;
+        if ( i == Vec_PtrSize(p->vWireLoadSels) )
+        {
+            Abc_Print( -1, "Cannot find wire load selection model \"%s\".\n", p->default_wire_load_sel );
+            exit(1);
+        }
+        for ( i = 0; i < Vec_FltSize(pWLS->vAreaFrom); i++)
+            if ( Area >= Vec_FltEntry(pWLS->vAreaFrom, i) && Area <  Vec_FltEntry(pWLS->vAreaTo, i) )
+            {
+                pWLoadUsed = (char *)Vec_PtrEntry(pWLS->vWireLoadModel, i);
+                break;
+            }
+        if ( i == Vec_FltSize(pWLS->vAreaFrom) )
+            pWLoadUsed = (char *)Vec_PtrEntryLast(pWLS->vWireLoadModel);
+    }
+    else if ( p->default_wire_load && strlen(p->default_wire_load) )
+        pWLoadUsed = p->default_wire_load;
+    else
+    {
+//        Abc_Print( 0, "No wire model given.\n" );
+        return NULL;
+    }
+    return Abc_SclFetchWireLoadModel( p, pWLoadUsed );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the library has delay info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SclHasDelayInfo( void * pScl )
+{
+    SC_Lib * p = (SC_Lib *)pScl;
+    SC_Cell * pCell;
+    SC_Timing * pTime;
+    pCell = Abc_SclFindInvertor(p, 0);
+    if ( pCell == NULL )
+        return 0;
+    pTime = Scl_CellPinTime( pCell, 0 );
+    if ( pTime == NULL )
+        return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns "average" slew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Abc_SclComputeAverageSlew( SC_Lib * p )
+{
+    SC_Cell * pCell;
+    SC_Timing * pTime;
+    Vec_Flt_t * vIndex;
+    pCell = Abc_SclFindInvertor(p, 0);
+    if ( pCell == NULL )
+        return 0;
+    pTime = Scl_CellPinTime( pCell, 0 );
+    if ( pTime == NULL )
+        return 0;
+    vIndex = pTime->pCellRise->vIndex0; // slew
+    return Vec_FltEntry( vIndex, Vec_FltSize(vIndex)/3 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute delay parameters of pin/cell/class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SclComputeParametersPin( SC_Lib * p, SC_Cell * pCell, int iPin, float Slew, float * pLD, float * pPD )
+{
+    SC_Pair Load0, Load1, Load2;
+    SC_Pair ArrIn  = { 0.0, 0.0 };
+    SC_Pair SlewIn = { Slew, Slew };
+    SC_Pair ArrOut0 = { 0.0, 0.0 };
+    SC_Pair ArrOut1 = { 0.0, 0.0 };
+    SC_Pair ArrOut2 = { 0.0, 0.0 };
+    SC_Pair SlewOut = { 0.0, 0.0 };
+    SC_Timing * pTime = Scl_CellPinTime( pCell, iPin );
+    Vec_Flt_t * vIndex = pTime ? pTime->pCellRise->vIndex1 : NULL; // capacitance
+    if ( vIndex == NULL )
+        return 0;
+    // handle constant table
+    if ( Vec_FltSize(vIndex) == 1 )
+    {
+        *pLD = 0;
+        *pPD = Vec_FltEntry( (Vec_Flt_t *)Vec_PtrEntry(pTime->pCellRise->vData, 0), 0 );
+        return 1;
+    }
+    // get load points
+    Load0.rise = Load0.fall = 0.0;
+    Load1.rise = Load1.fall = Vec_FltEntry( vIndex, 0 );
+    Load2.rise = Load2.fall = Vec_FltEntry( vIndex, Vec_FltSize(vIndex) - 2 );
+    // compute delay
+    Scl_LibPinArrival( pTime, &ArrIn, &SlewIn, &Load0, &ArrOut0, &SlewOut );
+    Scl_LibPinArrival( pTime, &ArrIn, &SlewIn, &Load1, &ArrOut1, &SlewOut );
+    Scl_LibPinArrival( pTime, &ArrIn, &SlewIn, &Load2, &ArrOut2, &SlewOut );
+    ArrOut0.rise = 0.5 * ArrOut0.rise + 0.5 * ArrOut0.fall;
+    ArrOut1.rise = 0.5 * ArrOut1.rise + 0.5 * ArrOut1.fall;
+    ArrOut2.rise = 0.5 * ArrOut2.rise + 0.5 * ArrOut2.fall;
+    // get tangent
+    *pLD = (ArrOut2.rise - ArrOut1.rise) / ((Load2.rise - Load1.rise) / SC_CellPinCap(pCell, iPin));
+    // get constant
+    *pPD = ArrOut0.rise;
+    return 1;
+}
+int Abc_SclComputeParametersCell( SC_Lib * p, SC_Cell * pCell, float Slew, float * pLD, float * pPD )
+{
+    SC_Pin * pPin;
+    float LD, PD, ld, pd;
+    int i;
+    LD = PD = ld = pd = 0;
+    SC_CellForEachPinIn( pCell, pPin, i )
+    {
+        if ( !Abc_SclComputeParametersPin( p, pCell, i, Slew, &ld, &pd ) )
+            return 0;
+        LD += ld; PD += pd;
+    }
+    *pLD = LD / Abc_MaxInt(1, pCell->n_inputs);
+    *pPD = PD / Abc_MaxInt(1, pCell->n_inputs);
+    return 1;
+}
+void Abc_SclComputeParametersClass( SC_Lib * p, SC_Cell * pRepr, float Slew, float * pLD, float * pPD )
+{
+    SC_Cell * pCell;
+    float LD, PD, ld, pd;
+    int i, Count = 0;
+    LD = PD = ld = pd = 0;
+    SC_RingForEachCell( pRepr, pCell, i )
+    {
+        Abc_SclComputeParametersCell( p, pCell, Slew, &ld, &pd );
+        LD += ld; PD += pd;
+        Count++;
+    }
+    *pLD = LD / Abc_MaxInt(1, Count);
+    *pPD = PD / Abc_MaxInt(1, Count);
+}
+void Abc_SclComputeParametersClassPin( SC_Lib * p, SC_Cell * pRepr, int iPin, float Slew, float * pLD, float * pPD )
+{
+    SC_Cell * pCell;
+    float LD, PD, ld, pd;
+    int i, Count = 0;
+    LD = PD = ld = pd = 0;
+    SC_RingForEachCell( pRepr, pCell, i )
+    {
+        Abc_SclComputeParametersPin( p, pCell, iPin, Slew, &ld, &pd );
+        LD += ld; PD += pd;
+        Count++;
+    }
+    *pLD = LD / Abc_MaxInt(1, Count);
+    *pPD = PD / Abc_MaxInt(1, Count);
+}
+float Abc_SclComputeDelayCellPin( SC_Lib * p, SC_Cell * pCell, int iPin, float Slew, float Gain )
+{
+    float LD = 0, PD = 0;
+    Abc_SclComputeParametersPin( p, pCell, iPin, Slew, &LD, &PD );
+    return 0.01 * LD * Gain + PD;
+}
+float Abc_SclComputeDelayClassPin( SC_Lib * p, SC_Cell * pRepr, int iPin, float Slew, float Gain )
+{
+    SC_Cell * pCell;
+    float Delay = 0;
+    int i, Count = 0;
+    SC_RingForEachCell( pRepr, pCell, i )
+    {
+        if ( pCell->fSkip ) 
+            continue;
+//        if ( pRepr == pCell ) // skip the first gate
+//            continue;
+        Delay += Abc_SclComputeDelayCellPin( p, pCell, iPin, Slew, Gain );
+        Count++;
+    }
+    return Delay / Abc_MaxInt(1, Count);
+}
+float Abc_SclComputeAreaClass( SC_Cell * pRepr )
+{
+    SC_Cell * pCell;
+    float Area = 0;
+    int i, Count = 0;
+    SC_RingForEachCell( pRepr, pCell, i )
+    {
+        if ( pCell->fSkip ) 
+            continue;
+        Area += pCell->area;
+        Count++;
+    }
+    return Area / Abc_MaxInt(1, Count);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print cells]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclMarkSkippedCells( SC_Lib * p )
+{
+    char FileName[1000];
+    char Buffer[1000], * pName;
+    SC_Cell * pCell;
+    FILE * pFile;
+    int CellId, nSkipped = 0;
+    sprintf( FileName, "%s.skip", p->pName );
+    pFile = fopen( FileName, "rb" );
+    if ( pFile == NULL )
+        return;
+    while ( fgets( Buffer, 999, pFile ) != NULL )
+    {
+        pName = strtok( Buffer, "\r\n\t " );
+        if ( pName == NULL )
+            continue;
+        CellId = Abc_SclCellFind( p, pName );
+        if ( CellId == -1 )
+        {
+            printf( "Cannot find cell \"%s\" in the library \"%s\".\n", pName, p->pName );
+            continue;
+        }
+        pCell = SC_LibCell( p, CellId );
+        pCell->fSkip = 1;
+        nSkipped++;
+    }
+    fclose( pFile );
+    printf( "Marked %d cells for skipping in the library \"%s\".\n", nSkipped, p->pName );
+}
+void Abc_SclPrintCells( SC_Lib * p, float SlewInit, float Gain, int fInvOnly, int fShort )
+{
+    SC_Cell * pCell, * pRepr;
+    SC_Pin * pPin;
+    int i, j, k, nLength = 0;
+    float Slew = (SlewInit == 0) ? Abc_SclComputeAverageSlew(p) : SlewInit;
+    float LD = 0, PD = 0;
+    assert( Vec_PtrSize(p->vCellClasses) > 0 );
+    printf( "Library \"%s\" ", p->pName );
+    printf( "has %d cells in %d classes.  ", 
+        Vec_PtrSize(p->vCells), Vec_PtrSize(p->vCellClasses) );
+    if ( !fShort )
+        printf( "Delay estimate is based on slew %.2f ps and gain %.2f.", Slew, Gain );
+    printf( "\n" );
+    Abc_SclMarkSkippedCells( p );
+    // find the longest name
+    SC_LibForEachCellClass( p, pRepr, k )
+        SC_RingForEachCell( pRepr, pCell, i )
+            nLength = Abc_MaxInt( nLength, strlen(pRepr->pName) );
+    // print cells
+    SC_LibForEachCellClass( p, pRepr, k )
+    {
+        if ( fInvOnly && pRepr->n_inputs != 1 )
+            continue;
+        SC_CellForEachPinOut( pRepr, pPin, i )
+        {
+            if ( i == pRepr->n_inputs )
+            {
+                printf( "Class%4d : ",   k );
+                printf( "Cells =%3d   ", Abc_SclClassCellNum(pRepr) );
+                printf( "Ins =%2d  ",    pRepr->n_inputs );
+                printf( "Outs =%2d  ",   pRepr->n_outputs );
+            }
+            else
+                printf( "                                            " );
+            if ( pPin->func_text )
+                printf( "%-30s", pPin->func_text  );
+            printf( "    "  );
+            Kit_DsdPrintFromTruth( (unsigned *)Vec_WrdArray(pPin->vFunc), pRepr->n_inputs );
+            printf( "\n" );
+            if ( fShort )
+                continue;
+            SC_RingForEachCell( pRepr, pCell, j )
+            {
+                printf( "  %3d ",           j+1 );
+                printf( "%s",               pCell->fSkip ? "s" : " " );
+                printf( " : " );
+                printf( "%-*s  ",           nLength, pCell->pName );
+                printf( "%2d   ",           pCell->drive_strength );
+                printf( "A =%8.2f    ",     pCell->area );
+                if ( pCell->n_outputs == 1 )
+                {
+                    if ( Abc_SclComputeParametersCell( p, pCell, Slew, &LD, &PD ) )
+                    {
+                        printf( "D =%6.1f ps  ",    0.01 * Gain * LD + PD );
+                        printf( "LD =%6.1f ps  ",   LD );
+                        printf( "PD =%6.1f ps    ", PD );
+                        printf( "C =%5.1f ff  ",    SC_CellPinCapAve(pCell) );
+                        printf( "Cm =%5.0f ff    ", SC_CellPin(pCell, pCell->n_inputs)->max_out_cap );
+                        printf( "Sm =%5.1f ps ",    SC_CellPin(pCell, pCell->n_inputs)->max_out_slew );
+                    }
+                }
+                printf( "\n" );
+            }
+            break;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print cells]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclLibNormalizeSurface( SC_Surface * p, float Time, float Load )
+{
+    Vec_Flt_t * vArray;
+    int i, k; float Entry;
+    Vec_FltForEachEntry( p->vIndex0, Entry, i ) // slew
+        Vec_FltWriteEntry( p->vIndex0, i, Time * Entry );
+    Vec_FltForEachEntry( p->vIndex1, Entry, i ) // load
+        Vec_FltWriteEntry( p->vIndex1, i, Load * Entry );
+    Vec_PtrForEachEntry( Vec_Flt_t *, p->vData, vArray, k )
+        Vec_FltForEachEntry( vArray, Entry, i ) // delay/slew
+            Vec_FltWriteEntry( vArray, i, Time * Entry );
+}
+void Abc_SclLibNormalize( SC_Lib * p )
+{
+    SC_WireLoad * pWL;
+    SC_Cell * pCell;
+    SC_Pin * pPin;
+    SC_Timings * pTimings;
+    SC_Timing * pTiming;
+    int i, k, m, n;
+    float Time = 1.0 * pow(10.0, 12 - p->unit_time);
+    float Load = p->unit_cap_fst * pow(10.0, 15 - p->unit_cap_snd);
+    if ( Time == 1 && Load == 1 )
+        return;
+    p->unit_time = 12;
+    p->unit_cap_fst = 1;
+    p->unit_cap_snd = 15;
+    p->default_max_out_slew *= Time;
+    SC_LibForEachWireLoad( p, pWL, i )
+        pWL->cap *= Load;
+    SC_LibForEachCell( p, pCell, i )
+    SC_CellForEachPin( pCell, pPin, k )
+    {
+        pPin->cap *= Load;
+        pPin->rise_cap *= Load;
+        pPin->fall_cap *= Load;
+        pPin->max_out_cap *= Load;
+        pPin->max_out_slew *= Time;
+        SC_PinForEachRTiming( pPin, pTimings, m )
+        Vec_PtrForEachEntry( SC_Timing *, pTimings->vTimings, pTiming, n )
+        {
+            Abc_SclLibNormalizeSurface( pTiming->pCellRise, Time, Load );
+            Abc_SclLibNormalizeSurface( pTiming->pCellFall, Time, Load );
+            Abc_SclLibNormalizeSurface( pTiming->pRiseTrans, Time, Load );
+            Abc_SclLibNormalizeSurface( pTiming->pFallTrans, Time, Load );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives simple GENLIB library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Abc_SclProduceGenlibStrSimple( SC_Lib * p )
+{
+    char Buffer[200];
+    Vec_Str_t * vStr;
+    SC_Cell * pCell;
+    SC_Pin * pPin, * pPinOut;
+    int i, j, k, Count = 2;
+    // mark skipped cells
+//    Abc_SclMarkSkippedCells( p );
+    vStr = Vec_StrAlloc( 1000 );
+    Vec_StrPrintStr( vStr, "GATE _const0_            0.00 z=CONST0;\n" );
+    Vec_StrPrintStr( vStr, "GATE _const1_            0.00 z=CONST1;\n" );
+    SC_LibForEachCell( p, pCell, i )
+    {
+        if ( pCell->n_inputs == 0 )
+            continue;
+        assert( strlen(pCell->pName) < 200 );
+        SC_CellForEachPinOut( pCell, pPinOut, j )
+        {
+            Vec_StrPrintStr( vStr, "GATE " );
+            sprintf( Buffer, "%-16s", pCell->pName );
+            Vec_StrPrintStr( vStr, Buffer );
+            Vec_StrPrintStr( vStr, " " );
+            sprintf( Buffer, "%7.2f", pCell->area );
+            Vec_StrPrintStr( vStr, Buffer );
+            Vec_StrPrintStr( vStr, " " );
+            Vec_StrPrintStr( vStr, pPinOut->pName );
+            Vec_StrPrintStr( vStr, "=" );
+            Vec_StrPrintStr( vStr, pPinOut->func_text ? pPinOut->func_text : "?" );
+            Vec_StrPrintStr( vStr, ";\n" );
+            SC_CellForEachPinIn( pCell, pPin, k )
+            {
+                Vec_StrPrintStr( vStr, "         PIN " );
+                sprintf( Buffer, "%-4s", pPin->pName );
+                Vec_StrPrintStr( vStr, Buffer );
+                sprintf( Buffer, " UNKNOWN  1  999  1.00  0.00  1.00  0.00\n" );
+                Vec_StrPrintStr( vStr, Buffer );
+            }
+            Count++;
+        }
+    }
+    Vec_StrPrintStr( vStr, "\n.end\n" );
+    Vec_StrPush( vStr, '\0' );
+//    printf( "GENLIB library with %d gates is produced:\n", Count );
+//    printf( "%s", Vec_StrArray(vStr) );
+    return vStr;
+}
+Mio_Library_t * Abc_SclDeriveGenlibSimple( void * pScl )
+{
+    SC_Lib * p = (SC_Lib *)pScl;
+    Vec_Str_t * vStr = Abc_SclProduceGenlibStrSimple( p );
+    Mio_Library_t * pLib = Mio_LibraryRead( p->pFileName, Vec_StrArray(vStr), NULL, 0 );  
+    Vec_StrFree( vStr );
+    if ( pLib )
+        printf( "Derived GENLIB library \"%s\" with %d gates.\n", p->pName, SC_LibCellNum(p) );
+    else
+        printf( "Reading library has filed.\n" );
+    return pLib;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derive GENLIB library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Abc_SclProduceGenlibStr( SC_Lib * p, float Slew, float Gain, int nGatesMin, int * pnCellCount )
+{
+    char Buffer[200];
+    Vec_Str_t * vStr;
+    SC_Cell * pRepr;
+    SC_Pin * pPin;
+    int i, k, Count = 2, nClassMax = 0;
+    // find the largest number of cells in a class
+    SC_LibForEachCellClass( p, pRepr, i )
+        if ( pRepr->n_outputs == 1 )
+            nClassMax = Abc_MaxInt( nClassMax, Abc_SclClassCellNum(pRepr) );
+    // update the number
+    if ( nGatesMin && nGatesMin >= nClassMax )
+        nGatesMin = 0;
+    // mark skipped cells
+    Abc_SclMarkSkippedCells( p );
+    vStr = Vec_StrAlloc( 1000 );
+    Vec_StrPrintStr( vStr, "GATE _const0_            0.00 z=CONST0;\n" );
+    Vec_StrPrintStr( vStr, "GATE _const1_            0.00 z=CONST1;\n" );
+    SC_LibForEachCellClass( p, pRepr, i )
+    {
+        if ( pRepr->n_inputs == 0 )
+            continue;
+        if ( pRepr->n_outputs > 1 )
+            continue;
+        if ( nGatesMin && pRepr->n_inputs > 2 && Abc_SclClassCellNum(pRepr) < nGatesMin )
+            continue;
+        assert( strlen(pRepr->pName) < 200 );
+        Vec_StrPrintStr( vStr, "GATE " );
+        sprintf( Buffer, "%-16s", pRepr->pName );
+        Vec_StrPrintStr( vStr, Buffer );
+        Vec_StrPrintStr( vStr, " " );
+//        sprintf( Buffer, "%7.2f", Abc_SclComputeAreaClass(pRepr) );
+        sprintf( Buffer, "%7.2f", pRepr->area );
+        Vec_StrPrintStr( vStr, Buffer );
+        Vec_StrPrintStr( vStr, " " );
+        Vec_StrPrintStr( vStr, SC_CellPinName(pRepr, pRepr->n_inputs) );
+        Vec_StrPrintStr( vStr, "=" );
+        Vec_StrPrintStr( vStr, SC_CellPinOutFunc(pRepr, 0) ? SC_CellPinOutFunc(pRepr, 0) : "?" );
+        Vec_StrPrintStr( vStr, ";\n" );
+        SC_CellForEachPinIn( pRepr, pPin, k )
+        {
+            float Delay = Abc_SclComputeDelayClassPin( p, pRepr, k, Slew, Gain );
+            assert( Delay > 0 );
+            Vec_StrPrintStr( vStr, "         PIN " );
+            sprintf( Buffer, "%-4s", pPin->pName );
+            Vec_StrPrintStr( vStr, Buffer );
+            sprintf( Buffer, " UNKNOWN  1  999  %7.2f  0.00  %7.2f  0.00\n", Delay, Delay );
+            Vec_StrPrintStr( vStr, Buffer );
+        }
+        Count++;
+    }
+    Vec_StrPrintStr( vStr, "\n.end\n" );
+    Vec_StrPush( vStr, '\0' );
+//    printf( "GENLIB library with %d gates is produced:\n", Count );
+//    printf( "%s", Vec_StrArray(vStr) );
+    if ( pnCellCount )
+        *pnCellCount = Count;
+    return vStr;
+}
+void Abc_SclDumpGenlib( char * pFileName, SC_Lib * p, float SlewInit, float Gain, int nGatesMin )
+{
+    int nCellCount = 0;
+    char FileName[1000];
+    float Slew = (SlewInit == 0) ? Abc_SclComputeAverageSlew(p) : SlewInit;
+    Vec_Str_t * vStr;
+    FILE * pFile;
+    if ( pFileName == NULL )
+        sprintf( FileName, "%s_s%03d_g%03d_m%d.genlib", p->pName, (int)Slew, (int)Gain, nGatesMin );
+    else
+        sprintf( FileName, "%s", pFileName );
+    pFile = fopen( FileName, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\" for writing.\n", FileName );
+        return;
+    }
+    vStr = Abc_SclProduceGenlibStr( p, Slew, Gain, nGatesMin, &nCellCount );
+    fprintf( pFile, "%s", Vec_StrArray(vStr) );
+    Vec_StrFree( vStr );
+    fclose( pFile );
+    printf( "Written GENLIB library with %d gates into file \"%s\".\n", nCellCount, FileName );
+}
+Mio_Library_t * Abc_SclDeriveGenlib( void * pScl, float SlewInit, float Gain, int nGatesMin, int fVerbose )
+{
+    int nCellCount = 0;
+    SC_Lib * p = (SC_Lib *)pScl;
+    float Slew = (SlewInit == 0) ? Abc_SclComputeAverageSlew(p) : SlewInit;
+    Vec_Str_t * vStr = Abc_SclProduceGenlibStr( p, Slew, Gain, nGatesMin, &nCellCount );
+    Mio_Library_t * pLib = Mio_LibraryRead( p->pFileName, Vec_StrArray(vStr), NULL, 0 );  
+    Vec_StrFree( vStr );
+    if ( !pLib )
+        printf( "Reading library has filed.\n" );
+    else if ( fVerbose )
+        printf( "Derived GENLIB library \"%s\" with %d gates using slew %.2f ps and gain %.2f.\n", p->pName, nCellCount, Slew, Gain );
+    return pLib;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Install library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclInstallGenlib( void * pScl, float SlewInit, float Gain, int nGatesMin )
+{
+    SC_Lib * p = (SC_Lib *)pScl;
+    Vec_Str_t * vStr, * vStr2;
+    float Slew = (SlewInit == 0) ? Abc_SclComputeAverageSlew(p) : SlewInit;
+    int RetValue, nGateCount = SC_LibCellNum(p);
+    if ( Gain == 0 )
+        vStr = Abc_SclProduceGenlibStrSimple(p);
+    else
+        vStr = Abc_SclProduceGenlibStr( p, Slew, Gain, nGatesMin, &nGateCount );
+    vStr2 = Vec_StrDup( vStr );
+    RetValue = Mio_UpdateGenlib2( vStr, vStr2, p->pName, 0 );
+    Vec_StrFree( vStr );
+    Vec_StrFree( vStr2 );
+    if ( !RetValue )
+        printf( "Reading library has filed.\n" );
+    else if ( Gain != 0 )
+        printf( "Derived GENLIB library \"%s\" with %d gates using slew %.2f ps and gain %.2f.\n", p->pName, nGateCount, Slew, Gain );
+//    else
+//        printf( "Derived unit-delay GENLIB library \"%s\" with %d gates.\n", p->pName, nGateCount );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/scl/sclLiberty.c b/abc-build/src/map/scl/sclLiberty.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/scl/sclLiberty.c
@@ -0,0 +1,1667 @@
+/**CFile****************************************************************
+
+  FileName    [sclLiberty.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Standard-cell library representation.]
+
+  Synopsis    [Liberty parser.]
+
+  Author      [Alan Mishchenko, Niklas Een]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 24, 2012.]
+
+  Revision    [$Id: sclLiberty.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sclLib.h"
+#include "misc/st/st.h"
+#include "map/mio/mio.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define ABC_MAX_LIB_STR_LEN 5000
+
+// entry types
+typedef enum { 
+    SCL_LIBERTY_NONE = 0,        // 0:  unknown
+    SCL_LIBERTY_PROC,            // 1:  procedure :  key(head){body}
+    SCL_LIBERTY_EQUA,            // 2:  equation  :  key:head;
+    SCL_LIBERTY_LIST             // 3:  list      :  key(head) 
+} Scl_LibertyType_t;
+
+typedef struct Scl_Pair_t_ Scl_Pair_t;
+struct Scl_Pair_t_
+{
+    int             Beg;          // item beginning
+    int             End;          // item end
+};
+
+typedef struct Scl_Item_t_ Scl_Item_t;
+struct Scl_Item_t_
+{
+    int             Type;         // Scl_LibertyType_t
+    int             iLine;        // file line where the item's spec begins
+    Scl_Pair_t      Key;          // key part
+    Scl_Pair_t      Head;         // head part 
+    Scl_Pair_t      Body;         // body part
+    int             Next;         // next item in the list 
+    int             Child;        // first child item 
+};
+
+typedef struct Scl_Tree_t_ Scl_Tree_t;
+struct Scl_Tree_t_
+{
+    char *          pFileName;    // input Liberty file name
+    char *          pContents;    // file contents
+    int             nContents;    // file size
+    int             nLines;       // line counter
+    int             nItems;       // number of items
+    int             nItermAlloc;  // number of items allocated
+    Scl_Item_t *    pItems;       // the items
+    char *          pError;       // the error string
+    abctime         clkStart;     // beginning time
+};
+
+static inline Scl_Item_t *  Scl_LibertyRoot( Scl_Tree_t * p )                                      { return p->pItems;                                                 }
+static inline Scl_Item_t *  Scl_LibertyItem( Scl_Tree_t * p, int v )                               { assert( v < p->nItems ); return v < 0 ? NULL : p->pItems + v;     }
+static inline int           Scl_LibertyCompare( Scl_Tree_t * p, Scl_Pair_t Pair, char * pStr )     { return strncmp( p->pContents+Pair.Beg, pStr, Pair.End-Pair.Beg ) || ((int)strlen(pStr) != Pair.End-Pair.Beg); }
+static inline void          Scl_PrintWord( FILE * pFile, Scl_Tree_t * p, Scl_Pair_t Pair )         { char * pBeg = p->pContents+Pair.Beg, * pEnd = p->pContents+Pair.End; while ( pBeg < pEnd ) fputc( *pBeg++, pFile ); }
+static inline void          Scl_PrintSpace( FILE * pFile, int nOffset )                            { int i; for ( i = 0; i < nOffset; i++ ) fputc(' ', pFile);         }
+static inline int           Scl_LibertyItemId( Scl_Tree_t * p, Scl_Item_t * pItem )                { return pItem - p->pItems;                                         }
+
+#define Scl_ItemForEachChild( p, pItem, pChild ) \
+    for ( pChild = Scl_LibertyItem(p, pItem->Child); pChild; pChild = Scl_LibertyItem(p, pChild->Next) )
+#define Scl_ItemForEachChildName( p, pItem, pChild, pName ) \
+    for ( pChild = Scl_LibertyItem(p, pItem->Child); pChild; pChild = Scl_LibertyItem(p, pChild->Next) ) if ( Scl_LibertyCompare(p, pChild->Key, pName) ) {} else
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Prints parse tree in Liberty format.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Scl_LibertyParseDumpItem( FILE * pFile, Scl_Tree_t * p, Scl_Item_t * pItem, int nOffset )
+{
+    if ( pItem->Type == SCL_LIBERTY_PROC )
+    {
+        Scl_PrintSpace( pFile, nOffset );
+        Scl_PrintWord( pFile, p, pItem->Key );
+        fprintf( pFile, "(" );
+        Scl_PrintWord( pFile, p, pItem->Head );
+        fprintf( pFile, ") {\n" );
+        if ( Scl_LibertyItem(p, pItem->Child) )
+            Scl_LibertyParseDumpItem( pFile, p, Scl_LibertyItem(p, pItem->Child), nOffset + 2 );
+        Scl_PrintSpace( pFile, nOffset );
+        fprintf( pFile, "}\n" );
+    }
+    else if ( pItem->Type == SCL_LIBERTY_EQUA )
+    {
+        Scl_PrintSpace( pFile, nOffset );
+        Scl_PrintWord( pFile, p, pItem->Key );
+        fprintf( pFile, " : " );
+        Scl_PrintWord( pFile, p, pItem->Head );
+        fprintf( pFile, ";\n" );
+    }
+    else if ( pItem->Type == SCL_LIBERTY_LIST )
+    {
+        Scl_PrintSpace( pFile, nOffset );
+        Scl_PrintWord( pFile, p, pItem->Key );
+        fprintf( pFile, "(" );
+        Scl_PrintWord( pFile, p, pItem->Head );
+        fprintf( pFile, ");\n" );
+    }
+    else assert( 0 );
+    if ( Scl_LibertyItem(p, pItem->Next) )
+        Scl_LibertyParseDumpItem( pFile, p, Scl_LibertyItem(p, pItem->Next), nOffset );
+}
+int Scl_LibertyParseDump( Scl_Tree_t * p, char * pFileName )
+{
+    FILE * pFile;
+    if ( pFileName == NULL )
+        pFile = stdout;
+    else
+    {
+        pFile = fopen( pFileName, "w" );
+        if ( pFile == NULL )
+        {
+            printf( "Scl_LibertyParseDump(): The output file is unavailable (absent or open).\n" );
+            return 0;
+        }
+    }
+    Scl_LibertyParseDumpItem( pFile, p, Scl_LibertyRoot(p), 0 );
+    if ( pFile != stdout )
+        fclose( pFile );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Gets the name to write.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_LibertyCountItems( char * pBeg, char * pEnd )
+{
+    int Counter = 0;
+    for ( ; pBeg < pEnd; pBeg++ )
+        Counter += (*pBeg == '(' || *pBeg == ':');
+    return Counter;
+}
+// removes C-style comments
+/*
+void Scl_LibertyWipeOutComments( char * pBeg, char * pEnd )
+{
+    char * pCur, * pStart;
+    for ( pCur = pBeg; pCur < pEnd; pCur++ )
+    if ( pCur[0] == '/' && pCur[1] == '*' )
+        for ( pStart = pCur; pCur < pEnd; pCur++ )
+        if ( pCur[0] == '*' && pCur[1] == '/' )
+        {
+            for ( ; pStart < pCur + 2; pStart++ )
+            if ( *pStart != '\n' ) *pStart = ' ';
+            break;
+        }
+}
+*/
+void Scl_LibertyWipeOutComments( char * pBeg, char * pEnd )
+{
+    char * pCur, * pStart;
+    for ( pCur = pBeg; pCur < pEnd-1; pCur++ )
+        if ( pCur[0] == '/' && pCur[1] == '*' )
+        {
+            for ( pStart = pCur; pCur < pEnd-1; pCur++ )
+                if ( pCur[0] == '*' && pCur[1] == '/' )
+                {
+                    for ( ; pStart < pCur + 2; pStart++ )
+                    if ( *pStart != '\n' ) *pStart = ' ';
+                    break;
+                }
+        }
+        else if ( pCur[0] == '/' && pCur[1] == '/' )
+        {
+            for ( pStart = pCur; pCur < pEnd; pCur++ )
+                if ( pCur[0] == '\n' || pCur == pEnd-1 )
+                {
+                    for ( ; pStart < pCur; pStart++ ) *pStart = ' ';
+                    break;
+                }
+        }
+}
+static inline int Scl_LibertyCharIsSpace( char c )
+{
+    return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\\';
+}
+static inline int Scl_LibertySkipSpaces( Scl_Tree_t * p, char ** ppPos, char * pEnd, int fStopAtNewLine )
+{
+    char * pPos = *ppPos;
+    for ( ; pPos < pEnd; pPos++ )
+    {
+        if ( *pPos == '\n' )
+        {
+            p->nLines++;
+            if ( fStopAtNewLine )
+                break;
+        }        
+        if ( !Scl_LibertyCharIsSpace(*pPos) )
+            break;
+    }
+    *ppPos = pPos;
+    return pPos == pEnd;
+}
+// skips entry delimited by " :;(){}" and returns 1 if reached the end
+static inline int Scl_LibertySkipEntry( char ** ppPos, char * pEnd )
+{
+    char * pPos = *ppPos;
+    if ( *pPos == '\"' )
+    {
+        for ( pPos++; pPos < pEnd; pPos++ )
+            if ( *pPos == '\"' )
+            {
+                pPos++;
+                break;
+            }
+    }
+    else
+    {
+        for ( ; pPos < pEnd; pPos++ )
+            if ( *pPos == ' ' || *pPos == '\r' || *pPos == '\n' || *pPos == '\t' ||
+                 *pPos == ':' || *pPos == ';'  || 
+                 *pPos == '(' || *pPos == ')'  || 
+                 *pPos == '{' || *pPos == '}' )
+                break;
+    }
+    *ppPos = pPos;
+    return pPos == pEnd;
+}
+// finds the matching closing symbol
+static inline char * Scl_LibertyFindMatch( char * pPos, char * pEnd )
+{
+    int Counter = 0;
+    assert( *pPos == '(' || *pPos == '{' );
+    if ( *pPos == '(' )
+    {
+        for ( ; pPos < pEnd; pPos++ )
+        {
+            if ( *pPos == '(' )
+                Counter++;
+            if ( *pPos == ')' )
+                Counter--;
+            if ( Counter == 0 )
+                break;
+        }
+    }
+    else
+    {
+        for ( ; pPos < pEnd; pPos++ )
+        {
+            if ( *pPos == '{' )
+                Counter++;
+            if ( *pPos == '}' )
+                Counter--;
+            if ( Counter == 0 )
+                break;
+        }
+    }
+    assert( *pPos == ')' || *pPos == '}' );
+    return pPos;
+}
+// trims spaces around the head
+static inline Scl_Pair_t Scl_LibertyUpdateHead( Scl_Tree_t * p, Scl_Pair_t Head )
+{
+    Scl_Pair_t Res;
+    char * pBeg = p->pContents + Head.Beg;
+    char * pEnd = p->pContents + Head.End;
+    char * pFirstNonSpace = NULL;
+    char * pLastNonSpace = NULL;
+    char * pChar;
+    for ( pChar = pBeg; pChar < pEnd; pChar++ )
+    {
+        if ( *pChar == '\n' )
+            p->nLines++;
+        if ( Scl_LibertyCharIsSpace(*pChar) )
+            continue;
+        pLastNonSpace = pChar;
+        if ( pFirstNonSpace == NULL )
+            pFirstNonSpace = pChar;
+    }
+    if ( pFirstNonSpace == NULL || pLastNonSpace == NULL )
+        return Head;
+    assert( pFirstNonSpace && pLastNonSpace );
+    Res.Beg = pFirstNonSpace - p->pContents;
+    Res.End = pLastNonSpace  - p->pContents + 1;
+    return Res;
+}
+// returns new item
+static inline Scl_Item_t * Scl_LibertyNewItem( Scl_Tree_t * p, int Type )
+{
+    p->pItems[p->nItems].iLine = p->nLines;
+    p->pItems[p->nItems].Type  = Type;
+    p->pItems[p->nItems].Child = -1;
+    p->pItems[p->nItems].Next  = -1;
+    return p->pItems + p->nItems++;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Gets the name to write.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Scl_LibertyReadString( Scl_Tree_t * p, Scl_Pair_t Pair )   
+{ 
+    static char Buffer[ABC_MAX_LIB_STR_LEN]; 
+    assert( Pair.End-Pair.Beg < ABC_MAX_LIB_STR_LEN );
+    strncpy( Buffer, p->pContents+Pair.Beg, Pair.End-Pair.Beg ); 
+    if ( Pair.Beg < Pair.End && Buffer[0] == '\"' )
+    {
+        assert( Buffer[Pair.End-Pair.Beg-1] == '\"' );
+        Buffer[Pair.End-Pair.Beg-1] = 0;
+        return Buffer + 1;
+    }
+    Buffer[Pair.End-Pair.Beg] = 0;
+    return Buffer;
+}
+int Scl_LibertyItemNum( Scl_Tree_t * p, Scl_Item_t * pRoot, char * pName )
+{
+    Scl_Item_t * pItem;
+    int Counter = 0;
+    Scl_ItemForEachChildName( p, pRoot, pItem, pName )
+        Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns free item.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_LibertyBuildItem( Scl_Tree_t * p, char ** ppPos, char * pEnd )
+{
+    Scl_Item_t * pItem;
+    Scl_Pair_t Key, Head, Body;
+    char * pNext, * pStop;
+    Key.End = 0;
+    if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
+        return -2;
+    Key.Beg = *ppPos - p->pContents;
+    if ( Scl_LibertySkipEntry( ppPos, pEnd ) )
+        goto exit;
+    Key.End = *ppPos - p->pContents;
+    if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
+        goto exit;
+    pNext = *ppPos;
+    if ( *pNext == ':' )
+    {
+        *ppPos = pNext + 1;
+        if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
+            goto exit;
+        Head.Beg = *ppPos - p->pContents;
+        if ( Scl_LibertySkipEntry( ppPos, pEnd ) )
+            goto exit;
+        Head.End = *ppPos - p->pContents;
+        if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 1 ) )
+            goto exit;
+        pNext = *ppPos;
+        if ( *pNext != ';' && *pNext != '\n' )
+            goto exit;
+        *ppPos = pNext + 1;
+        // end of equation
+        pItem = Scl_LibertyNewItem( p, SCL_LIBERTY_EQUA );
+        pItem->Key  = Key;
+        pItem->Head = Scl_LibertyUpdateHead( p, Head );
+        pItem->Next = Scl_LibertyBuildItem( p, ppPos, pEnd );
+        if ( pItem->Next == -1 )
+            goto exit;
+        return Scl_LibertyItemId( p, pItem );
+    }
+    if ( *pNext == '(' )
+    {
+        pStop = Scl_LibertyFindMatch( pNext, pEnd );
+        Head.Beg = pNext - p->pContents + 1;
+        Head.End = pStop - p->pContents;
+        *ppPos = pStop + 1;
+        if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
+        {
+            // end of list
+            pItem = Scl_LibertyNewItem( p, SCL_LIBERTY_LIST );
+            pItem->Key  = Key;
+            pItem->Head = Scl_LibertyUpdateHead( p, Head );
+            return Scl_LibertyItemId( p, pItem );
+        }
+        pNext = *ppPos;
+        if ( *pNext == '{' ) // beginning of body
+        {
+            pStop = Scl_LibertyFindMatch( pNext, pEnd );
+            Body.Beg = pNext - p->pContents + 1;
+            Body.End = pStop - p->pContents;
+            // end of body
+            pItem = Scl_LibertyNewItem( p, SCL_LIBERTY_PROC );
+            pItem->Key  = Key;
+            pItem->Head = Scl_LibertyUpdateHead( p, Head );
+            pItem->Body = Body;
+            *ppPos = pNext + 1;
+            pItem->Child = Scl_LibertyBuildItem( p, ppPos, pStop );
+            if ( pItem->Child == -1 )
+                goto exit;
+            *ppPos = pStop + 1;
+            pItem->Next = Scl_LibertyBuildItem( p, ppPos, pEnd );
+            if ( pItem->Next == -1 )
+                goto exit;
+            return Scl_LibertyItemId( p, pItem );
+        }
+        // end of list
+        if ( *pNext == ';' )
+            *ppPos = pNext + 1;
+        pItem = Scl_LibertyNewItem( p, SCL_LIBERTY_LIST );
+        pItem->Key  = Key;
+        pItem->Head = Scl_LibertyUpdateHead( p, Head );
+        pItem->Next = Scl_LibertyBuildItem( p, ppPos, pEnd );
+        if ( pItem->Next == -1 )
+            goto exit;
+        return Scl_LibertyItemId( p, pItem );
+    }
+exit:
+    if ( p->pError == NULL )
+    {
+        p->pError = ABC_ALLOC( char, 1000 );
+        sprintf( p->pError, "File \"%s\". Line %6d. Failed to parse entry \"%s\".\n", 
+            p->pFileName, p->nLines, Scl_LibertyReadString(p, Key) );
+    }
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [File management.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Scl_LibertyFixFileName( char * pFileName )
+{
+    char * pHead;
+    for ( pHead = pFileName; *pHead; pHead++ )
+        if ( *pHead == '>' )
+            *pHead = '\\';
+}
+int Scl_LibertyFileSize( char * pFileName )
+{
+    FILE * pFile;
+    int nFileSize;
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Scl_LibertyFileSize(): The input file is unavailable (absent or open).\n" );
+        return 0;
+    }
+    fseek( pFile, 0, SEEK_END );  
+    nFileSize = ftell( pFile ); 
+    fclose( pFile );
+    return nFileSize;
+}
+char * Scl_LibertyFileContents( char * pFileName, int nContents )
+{
+    FILE * pFile = fopen( pFileName, "rb" );
+    char * pContents = ABC_ALLOC( char, nContents+1 );
+    int RetValue;
+    RetValue = fread( pContents, nContents, 1, pFile );
+    fclose( pFile );
+    pContents[nContents] = 0;
+    return pContents;
+}
+void Scl_LibertyStringDump( char * pFileName, Vec_Str_t * vStr )
+{
+    FILE * pFile = fopen( pFileName, "wb" );
+    int RetValue;
+    if ( pFile == NULL )
+    {
+        printf( "Scl_LibertyStringDump(): The output file is unavailable.\n" );
+        return;
+    }
+    RetValue = fwrite( Vec_StrArray(vStr), 1, Vec_StrSize(vStr), pFile );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the parsing manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Scl_Tree_t * Scl_LibertyStart( char * pFileName )
+{
+    Scl_Tree_t * p;
+    int RetValue;
+    // read the file into the buffer
+    Scl_LibertyFixFileName( pFileName );
+    RetValue = Scl_LibertyFileSize( pFileName );
+    if ( RetValue == 0 )
+        return NULL;
+    // start the manager
+    p = ABC_ALLOC( Scl_Tree_t, 1 );
+    memset( p, 0, sizeof(Scl_Tree_t) );
+    p->clkStart  = Abc_Clock();
+    p->nContents = RetValue;
+    p->pContents = Scl_LibertyFileContents( pFileName, p->nContents );
+    // other 
+    p->pFileName = Abc_UtilStrsav( pFileName );
+    p->nItermAlloc = 10 + Scl_LibertyCountItems( p->pContents, p->pContents+p->nContents );
+    p->pItems = ABC_CALLOC( Scl_Item_t, p->nItermAlloc );
+    p->nItems = 0;
+    p->nLines = 1;
+    return p;
+}
+void Scl_LibertyStop( Scl_Tree_t * p, int fVerbose )
+{
+    if ( fVerbose )
+    {
+        printf( "Memory = %7.2f MB. ", 1.0 * (p->nContents + p->nItermAlloc * sizeof(Scl_Item_t))/(1<<20) );
+        ABC_PRT( "Time", Abc_Clock() - p->clkStart );
+    }
+    ABC_FREE( p->pFileName );
+    ABC_FREE( p->pContents );
+    ABC_FREE( p->pItems );
+    ABC_FREE( p->pError );
+    ABC_FREE( p );
+}
+Scl_Tree_t * Scl_LibertyParse( char * pFileName, int fVerbose )
+{
+    Scl_Tree_t * p;
+    char * pPos;
+    if ( (p = Scl_LibertyStart(pFileName)) == NULL )
+        return NULL;
+    pPos = p->pContents;
+    Scl_LibertyWipeOutComments( p->pContents, p->pContents+p->nContents );
+    if ( !Scl_LibertyBuildItem( p, &pPos, p->pContents + p->nContents ) == 0 )
+    {
+        if ( p->pError ) printf( "%s", p->pError );
+        printf( "Parsing failed.  " );
+        Abc_PrintTime( 1, "Parsing time", Abc_Clock() - p->clkStart );
+    }
+    else if ( fVerbose )
+    {
+        printf( "Parsing finished successfully.  " );
+        Abc_PrintTime( 1, "Parsing time", Abc_Clock() - p->clkStart );
+    }
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fetching attributes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Scl_LibertyReadCellIsFlop( Scl_Tree_t * p, Scl_Item_t * pCell )
+{
+    Scl_Item_t * pAttr;
+    Scl_ItemForEachChild( p, pCell, pAttr )
+        if ( !Scl_LibertyCompare(p, pAttr->Key, "ff") ||
+             !Scl_LibertyCompare(p, pAttr->Key, "latch") )
+            return 1;
+    return 0;
+}
+char * Scl_LibertyReadCellArea( Scl_Tree_t * p, Scl_Item_t * pCell )
+{
+    Scl_Item_t * pArea;
+    Scl_ItemForEachChildName( p, pCell, pArea, "area" )
+        return Scl_LibertyReadString(p, pArea->Head);
+    return 0;
+}
+char * Scl_LibertyReadPinFormula( Scl_Tree_t * p, Scl_Item_t * pPin )
+{
+    Scl_Item_t * pFunc;
+    Scl_ItemForEachChildName( p, pPin, pFunc, "function" )
+        return Scl_LibertyReadString(p, pFunc->Head);
+    return NULL;
+}
+int Scl_LibertyReadCellIsThreeState( Scl_Tree_t * p, Scl_Item_t * pCell )
+{
+    Scl_Item_t * pPin, * pItem;
+    Scl_ItemForEachChildName( p, pCell, pPin, "pin" )
+        Scl_ItemForEachChildName( p, pPin, pItem, "three_state" )
+            return 1;
+    return 0;
+}
+int Scl_LibertyReadCellOutputNum( Scl_Tree_t * p, Scl_Item_t * pCell )
+{
+    Scl_Item_t * pPin;
+    int Counter = 0;
+    Scl_ItemForEachChildName( p, pCell, pPin, "pin" )
+        if ( Scl_LibertyReadPinFormula(p, pPin) )
+            Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Parses the standard cell library in Liberty format.]
+
+  Description [Writes the resulting file in Genlib format.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Scl_LibertyReadGenlibStr( Scl_Tree_t * p, int fVerbose )
+{
+    Vec_Str_t * vStr;
+    Scl_Item_t * pCell, * pOutput, * pInput;
+    char * pFormula;
+    vStr = Vec_StrAlloc( 1000 );
+    Vec_StrPrintStr( vStr, "GATE          _const0_  0.000000  z=CONST0;\n" );
+    Vec_StrPrintStr( vStr, "GATE          _const1_  0.000000  z=CONST1;\n" );
+    Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pCell, "cell" )
+    {
+        if ( Scl_LibertyReadCellIsFlop(p, pCell) )
+        {
+            if ( fVerbose )  printf( "Scl_LibertyReadGenlib() skipped sequential cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) );
+            continue;
+        }
+        if ( Scl_LibertyReadCellIsThreeState(p, pCell) )
+        {
+            if ( fVerbose )  printf( "Scl_LibertyReadGenlib() skipped three-state cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) );
+            continue;
+        }
+        if ( Scl_LibertyReadCellOutputNum(p, pCell) == 0 )
+        {
+            if ( fVerbose )  printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" without logic function.\n", Scl_LibertyReadString(p, pCell->Head) );
+            continue;
+        }
+        // iterate through output pins
+        Scl_ItemForEachChildName( p, pCell, pOutput, "pin" )
+        {
+            if ( (pFormula = Scl_LibertyReadPinFormula(p, pOutput)) ) 
+                continue;
+            if ( !strcmp(pFormula, "0") || !strcmp(pFormula, "1") )
+            {
+                if ( fVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" with constant formula \"%s\".\n", Scl_LibertyReadString(p, pCell->Head), pFormula );
+                break;
+            }
+            Vec_StrPrintStr( vStr, "GATE " );
+            Vec_StrPrintStr( vStr, Scl_LibertyReadString(p, pCell->Head) );
+            Vec_StrPrintStr( vStr, " " );
+            Vec_StrPrintStr( vStr, Scl_LibertyReadCellArea(p, pCell) );
+            Vec_StrPrintStr( vStr, " " );
+            Vec_StrPrintStr( vStr, Scl_LibertyReadString(p, pOutput->Head) );
+            Vec_StrPrintStr( vStr, "=" );
+            Vec_StrPrintStr( vStr, pFormula );
+            Vec_StrPrintStr( vStr, ";\n" );
+            // iterate through input pins
+            Scl_ItemForEachChildName( p, pCell, pInput, "pin" )
+            {
+                if ( Scl_LibertyReadPinFormula(p, pInput) == NULL )
+                    continue;
+                Vec_StrPrintStr( vStr, "  PIN " );
+                Vec_StrPrintStr( vStr, Scl_LibertyReadString(p, pInput->Head) );
+                Vec_StrPrintStr( vStr, " UNKNOWN  1  999  1.00  0.00  1.00  0.00\n" );
+            }
+        }
+    }
+    Vec_StrPrintStr( vStr, "\n.end\n" );
+    Vec_StrPush( vStr, '\0' );
+//    printf( "%s", Vec_StrArray(vStr) );
+    return vStr;
+}
+Vec_Str_t * Scl_LibertyParseGenlibStr( char * pFileName, int fVerbose )
+{
+    Scl_Tree_t * p;
+    Vec_Str_t * vStr;
+    p = Scl_LibertyParse( pFileName, fVerbose );
+    if ( p == NULL )
+        return NULL;
+//    Scl_LibertyRead( p, "temp_.lib" );
+    vStr = Scl_LibertyReadGenlibStr( p, fVerbose );
+    Scl_LibertyStop( p, fVerbose );
+//    Scl_LibertyStringDump( "test_genlib.lib", vStr );
+    return vStr;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Enabling debug output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+//#define SCL_DEBUG
+#ifdef SCL_DEBUG
+static inline void Vec_StrPutI_( Vec_Str_t * vOut, int Val )     {  printf( "%d ",  Val );  Vec_StrPutI( vOut, Val );  }
+static inline void Vec_StrPutW_( Vec_Str_t * vOut, word Val )    {  printf( "%lu ", Val );  Vec_StrPutW( vOut, Val );  }
+static inline void Vec_StrPutF_( Vec_Str_t * vOut, float Val )   {  printf( "%f ",  Val );  Vec_StrPutF( vOut, Val );  }
+static inline void Vec_StrPutS_( Vec_Str_t * vOut, char * Val )  {  printf( "%s ",  Val );  Vec_StrPutS( vOut, Val );  }
+static inline void Vec_StrPut_( Vec_Str_t * vOut )               {  printf( "\n" ); }
+#else
+static inline void Vec_StrPutI_( Vec_Str_t * vOut, int Val )     { Vec_StrPutI( vOut, Val );  }
+static inline void Vec_StrPutW_( Vec_Str_t * vOut, word Val )    { Vec_StrPutW( vOut, Val );  }
+static inline void Vec_StrPutF_( Vec_Str_t * vOut, float Val )   { Vec_StrPutF( vOut, Val );  }
+static inline void Vec_StrPutS_( Vec_Str_t * vOut, char * Val )  { Vec_StrPutS( vOut, Val );  }
+static inline void Vec_StrPut_( Vec_Str_t * vOut )               { }
+#endif
+
+/**Function*************************************************************
+
+  Synopsis    [Parsing Liberty into internal data representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Scl_LibertyReadDefaultWireLoad( Scl_Tree_t * p )
+{
+    Scl_Item_t * pItem;
+    Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "default_wire_load" )
+        return Scl_LibertyReadString(p, pItem->Head);
+    return "";
+}
+char * Scl_LibertyReadDefaultWireLoadSel( Scl_Tree_t * p )
+{
+    Scl_Item_t * pItem;
+    Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "default_wire_load_selection" )
+        return Scl_LibertyReadString(p, pItem->Head);
+    return "";
+}
+float Scl_LibertyReadDefaultMaxTrans( Scl_Tree_t * p )
+{
+    Scl_Item_t * pItem;
+    Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "default_max_transition" )
+        return atof(Scl_LibertyReadString(p, pItem->Head));
+    return 0;
+}
+int Scl_LibertyReadTimeUnit( Scl_Tree_t * p )
+{
+    Scl_Item_t * pItem;
+    Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "time_unit" )
+    {
+        char * pUnit = Scl_LibertyReadString(p, pItem->Head);
+        // 9=1ns, 10=100ps, 11=10ps, 12=1ps
+        if ( !strcmp(pUnit, "1ns") )
+            return 9;
+        if ( !strcmp(pUnit, "100ps") )
+            return 10;
+        if ( !strcmp(pUnit, "10ps") )
+            return 11;
+        if ( !strcmp(pUnit, "1ps") )
+            return 12;
+        break;
+    }
+    printf( "Libery parser cannot read \"time_unit\".  Assuming   time_unit : \"1ns\".\n" );
+    return 9;
+}
+void Scl_LibertyReadLoadUnit( Scl_Tree_t * p, Vec_Str_t * vOut )
+{
+    Scl_Item_t * pItem;
+    Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "capacitive_load_unit" )
+    {
+        // expecting (1.00,ff) or (1, pf) ... 12 or 15 for 'pf' or 'ff'
+        char * pHead   = Scl_LibertyReadString(p, pItem->Head);
+        float First    = atof(strtok(pHead, " \t\n\r\\\","));
+        char * pSecond = strtok(NULL, " \t\n\r\\\",");
+        Vec_StrPutF_( vOut, First );
+        if ( pSecond && !strcmp(pSecond, "pf") )
+            Vec_StrPutI_( vOut, 12 );
+        else if ( pSecond && !strcmp(pSecond, "ff") )
+            Vec_StrPutI_( vOut, 15 );
+        else break;
+        return;
+    }
+    printf( "Libery parser cannot read \"capacitive_load_unit\". Assuming   capacitive_load_unit(1, pf).\n" );
+    Vec_StrPutF_( vOut, 1.0 );
+    Vec_StrPutI_( vOut, 12 );
+}
+void Scl_LibertyReadWireLoad( Scl_Tree_t * p, Vec_Str_t * vOut )
+{
+    Scl_Item_t * pItem, * pChild;
+    Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, Scl_LibertyRoot(p), "wire_load") );
+    Vec_StrPut_( vOut );
+    Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "wire_load" )
+    {
+        Vec_StrPutS_( vOut, Scl_LibertyReadString(p, pItem->Head) );
+        Scl_ItemForEachChildName( p, pItem, pChild, "capacitance" )
+            Vec_StrPutF_( vOut, atof(Scl_LibertyReadString(p, pChild->Head)) );
+        Scl_ItemForEachChildName( p, pItem, pChild, "slope" )
+            Vec_StrPutF_( vOut, atof(Scl_LibertyReadString(p, pChild->Head)) );
+        Vec_StrPut_( vOut );
+        Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, pItem, "fanout_length") );
+        Vec_StrPut_( vOut );
+        Scl_ItemForEachChildName( p, pItem, pChild, "fanout_length" )
+        {
+            char * pHead  = Scl_LibertyReadString(p, pChild->Head);
+            int    First  = atoi( strtok(pHead, " ,") );
+            float  Second = atof( strtok(NULL, " ") );
+            Vec_StrPutI_( vOut, First );
+            Vec_StrPutF_( vOut, Second );
+            Vec_StrPut_( vOut );
+        }
+        Vec_StrPut_( vOut );
+    }
+    Vec_StrPut_( vOut );
+}
+void Scl_LibertyReadWireLoadSelect( Scl_Tree_t * p, Vec_Str_t * vOut )
+{
+    Scl_Item_t * pItem, * pChild;
+    Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, Scl_LibertyRoot(p), "wire_load_selection") );
+    Vec_StrPut_( vOut );
+    Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "wire_load_selection" )
+    {
+        Vec_StrPutS_( vOut, Scl_LibertyReadString(p, pItem->Head) );
+        Vec_StrPut_( vOut );
+        Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, pItem, "wire_load_from_area") );
+        Vec_StrPut_( vOut );
+        Scl_ItemForEachChildName( p, pItem, pChild, "wire_load_from_area" )
+        {
+            char * pHead  = Scl_LibertyReadString(p, pChild->Head);
+            float  First  = atof( strtok(pHead, " ,") );
+            float  Second = atof( strtok(NULL, " ,") );
+            char * pThird = strtok(NULL, " ");
+            if ( pThird[0] == '\"' )
+                assert(pThird[strlen(pThird)-1] == '\"'), pThird[strlen(pThird)-1] = 0, pThird++;
+            Vec_StrPutF_( vOut, First );
+            Vec_StrPutF_( vOut, Second );
+            Vec_StrPutS_( vOut, pThird );
+            Vec_StrPut_( vOut );
+        }
+        Vec_StrPut_( vOut );
+    }
+    Vec_StrPut_( vOut );
+}
+int Scl_LibertyReadDeriveStrength( Scl_Tree_t * p, Scl_Item_t * pCell )
+{
+    Scl_Item_t * pItem;
+    Scl_ItemForEachChildName( p, pCell, pItem, "drive_strength" )
+        return atoi(Scl_LibertyReadString(p, pItem->Head));
+    return 0;
+}
+int Scl_LibertyReadPinDirection( Scl_Tree_t * p, Scl_Item_t * pPin )
+{
+    Scl_Item_t * pItem;
+    Scl_ItemForEachChildName( p, pPin, pItem, "direction" )
+    {
+        char * pToken = Scl_LibertyReadString(p, pItem->Head);
+        if ( !strcmp(pToken, "input") )
+            return 0;
+        if ( !strcmp(pToken, "output") )
+            return 1;
+        break;
+    }
+    return -1;
+}
+float Scl_LibertyReadPinCap( Scl_Tree_t * p, Scl_Item_t * pPin, char * pName )
+{
+    Scl_Item_t * pItem;
+    Scl_ItemForEachChildName( p, pPin, pItem, pName )
+        return atof(Scl_LibertyReadString(p, pItem->Head));
+    return 0;
+}
+Scl_Item_t * Scl_LibertyReadPinTiming( Scl_Tree_t * p, Scl_Item_t * pPinOut, char * pNameIn )
+{
+    Scl_Item_t * pTiming, * pPinIn;
+    Scl_ItemForEachChildName( p, pPinOut, pTiming, "timing" )
+        Scl_ItemForEachChildName( p, pTiming, pPinIn, "related_pin" )
+            if ( !strcmp(Scl_LibertyReadString(p, pPinIn->Head), pNameIn) )
+                return pTiming;
+    return NULL;
+}
+Vec_Ptr_t * Scl_LibertyReadPinTimingAll( Scl_Tree_t * p, Scl_Item_t * pPinOut, char * pNameIn )
+{
+    Vec_Ptr_t * vTimings;
+    Scl_Item_t * pTiming, * pPinIn;
+    vTimings = Vec_PtrAlloc( 16 );
+    Scl_ItemForEachChildName( p, pPinOut, pTiming, "timing" )
+        Scl_ItemForEachChildName( p, pTiming, pPinIn, "related_pin" )
+            if ( !strcmp(Scl_LibertyReadString(p, pPinIn->Head), pNameIn) )
+                Vec_PtrPush( vTimings, pTiming );
+    return vTimings;
+}
+int Scl_LibertyReadTimingSense( Scl_Tree_t * p, Scl_Item_t * pPin )
+{
+    Scl_Item_t * pItem;
+    Scl_ItemForEachChildName( p, pPin, pItem, "timing_sense" )
+    {
+        char * pToken = Scl_LibertyReadString(p, pItem->Head);
+        if ( !strcmp(pToken, "positive_unate") )
+            return sc_ts_Pos;
+        if ( !strcmp(pToken, "negative_unate") )
+            return sc_ts_Neg;
+        if ( !strcmp(pToken, "non_unate") )
+            return sc_ts_Non;
+        break;
+    }
+    return sc_ts_Non;
+}
+Vec_Flt_t * Scl_LibertyReadFloatVec( char * pName )
+{
+    char * pToken;
+    Vec_Flt_t * vValues = Vec_FltAlloc( 100 );
+    for ( pToken = strtok(pName, " \t\n\r\\\","); pToken; pToken = strtok(NULL, " \t\n\r\\\",") )
+        Vec_FltPush( vValues, atof(pToken) );
+    return vValues;
+}
+
+void Scl_LibertyDumpTables( Vec_Str_t * vOut, Vec_Flt_t * vInd1, Vec_Flt_t * vInd2, Vec_Flt_t * vValues )
+{
+    int i; float Entry;
+    // write entries
+    Vec_StrPutI_( vOut, Vec_FltSize(vInd1) );
+    Vec_FltForEachEntry( vInd1, Entry, i )
+        Vec_StrPutF_( vOut, Entry );
+    Vec_StrPut_( vOut );
+    // write entries
+    Vec_StrPutI_( vOut, Vec_FltSize(vInd2) );
+    Vec_FltForEachEntry( vInd2, Entry, i )
+        Vec_StrPutF_( vOut, Entry );
+    Vec_StrPut_( vOut );
+    Vec_StrPut_( vOut );
+    // write entries
+    assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) );
+    Vec_FltForEachEntry( vValues, Entry, i )
+    {
+        Vec_StrPutF_( vOut, Entry );
+        if ( i % Vec_FltSize(vInd2) == Vec_FltSize(vInd2)-1 )
+            Vec_StrPut_( vOut );
+    }
+    // dump approximations
+    Vec_StrPut_( vOut );
+    for ( i = 0; i < 3; i++ ) 
+        Vec_StrPutF_( vOut, 0 );
+    for ( i = 0; i < 4; i++ ) 
+        Vec_StrPutF_( vOut, 0 );
+    for ( i = 0; i < 6; i++ ) 
+        Vec_StrPutF_( vOut, 0 );
+    Vec_StrPut_( vOut );
+    Vec_StrPut_( vOut );
+}
+int Scl_LibertyScanTable( Scl_Tree_t * p, Vec_Ptr_t * vOut, Scl_Item_t * pTiming, char * pName, Vec_Ptr_t * vTemples )
+{
+    Vec_Flt_t * vIndex1 = NULL;
+    Vec_Flt_t * vIndex2 = NULL;
+    Vec_Flt_t * vValues = NULL;
+    Vec_Flt_t * vInd1, * vInd2;
+    Scl_Item_t * pItem, * pTable = NULL;
+    char * pThis, * pTempl = NULL;
+    int iPlace, i;
+    float Entry;
+    // find the table
+    Scl_ItemForEachChildName( p, pTiming, pTable, pName )
+        break;
+    if ( pTable == NULL )
+        return 0;
+    // find the template
+    pTempl = Scl_LibertyReadString(p, pTable->Head);
+    if ( pTempl == NULL || pTempl[0] == 0 )
+    {
+        // read the numbers
+        Scl_ItemForEachChild( p, pTable, pItem )
+        {
+            if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") )
+                assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+            else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") )
+                assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+            else if ( !Scl_LibertyCompare(p, pItem->Key, "values") )
+                assert(vValues == NULL), vValues = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+        }
+        if ( vIndex1 == NULL || vIndex2 == NULL || vValues == NULL )
+            { printf( "Incomplete table specification\n" ); return 0; }
+        // dump the table
+        vInd1 = vIndex1;
+        vInd2 = vIndex2;
+        // write entries
+        Vec_PtrPush( vOut, vInd1 );
+        Vec_PtrPush( vOut, vInd2 );
+        Vec_PtrPush( vOut, vValues );
+    }
+    else if ( !strcmp(pTempl, "scalar") )
+    {
+        Scl_ItemForEachChild( p, pTable, pItem )
+            if ( !Scl_LibertyCompare(p, pItem->Key, "values") )
+            {
+                assert(vValues == NULL);
+                vValues = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+                assert( Vec_FltSize(vValues) == 1 );
+                // write entries
+                Vec_PtrPush( vOut, Vec_IntStart(1) );
+                Vec_PtrPush( vOut, Vec_IntStart(1) );
+                Vec_PtrPush( vOut, vValues );
+                break;
+            }
+            else
+            { printf( "Cannot read \"scalar\" template\n" ); return 0; }
+    }
+    else
+    {
+        // fetch the template
+        iPlace = -1;
+        Vec_PtrForEachEntry( char *, vTemples, pThis, i )
+            if ( i % 4 == 0 && !strcmp(pTempl, pThis) )
+            {  
+                iPlace = i;
+                break;
+            }
+        if ( iPlace == -1 )
+            { printf( "Template cannot be found in the template library\n" ); return 0; }
+        // read the numbers
+        Scl_ItemForEachChild( p, pTable, pItem )
+        {
+            if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") )
+                assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+            else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") )
+                assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+            else if ( !Scl_LibertyCompare(p, pItem->Key, "values") )
+                assert(vValues == NULL), vValues = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+        }
+        // check the template style
+        vInd1 = (Vec_Flt_t *)Vec_PtrEntry( vTemples, iPlace + 2 ); // slew
+        vInd2 = (Vec_Flt_t *)Vec_PtrEntry( vTemples, iPlace + 3 ); // load
+        if ( Vec_PtrEntry(vTemples, iPlace + 1) == NULL ) // normal order (vIndex1 is slew; vIndex2 is load)
+        {
+            assert( !vIndex1 || Vec_FltSize(vIndex1) == Vec_FltSize(vInd1) );
+            assert( !vIndex2 || Vec_FltSize(vIndex2) == Vec_FltSize(vInd2) );
+            vInd1 = vIndex1 ? vIndex1 : vInd1;
+            vInd2 = vIndex2 ? vIndex2 : vInd2;
+            // write entries
+            Vec_PtrPush( vOut, Vec_FltDup(vInd1) );
+            Vec_PtrPush( vOut, Vec_FltDup(vInd2) );
+            Vec_PtrPush( vOut, Vec_FltDup(vValues) );
+        }
+        else  // reverse order (vIndex2 is slew; vIndex1 is load)
+        {
+            Vec_Flt_t * vValues2 = Vec_FltAlloc( Vec_FltSize(vValues) );
+            assert( !vIndex2 || Vec_FltSize(vIndex2) == Vec_FltSize(vInd1) );
+            assert( !vIndex1 || Vec_FltSize(vIndex1) == Vec_FltSize(vInd2) );
+            vInd1 = vIndex2 ? vIndex2 : vInd1;
+            vInd2 = vIndex1 ? vIndex1 : vInd2;
+            // write entries -- transpose
+            assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) );
+            Vec_FltForEachEntry( vValues, Entry, i )
+            {
+                int x = i % Vec_FltSize(vInd2);
+                int y = i / Vec_FltSize(vInd2);
+                Entry = Vec_FltEntry( vValues, x * Vec_FltSize(vInd1) + y );
+                Vec_FltPush( vValues2, Entry );
+            }
+            assert( Vec_FltSize(vValues) == Vec_FltSize(vValues2) );
+            // write entries
+            Vec_PtrPush( vOut, Vec_FltDup(vInd1) );
+            Vec_PtrPush( vOut, Vec_FltDup(vInd2) );
+            Vec_PtrPush( vOut, vValues2 );
+        }
+        Vec_FltFreeP( &vIndex1 );
+        Vec_FltFreeP( &vIndex2 );
+        Vec_FltFreeP( &vValues );
+    }
+    return 1;
+}
+int Scl_LibertyComputeWorstCase( Vec_Ptr_t * vTables, Vec_Flt_t ** pvInd0, Vec_Flt_t ** pvInd1, Vec_Flt_t ** pvValues )
+{
+    Vec_Flt_t * vInd0, * vInd1, * vValues;
+    Vec_Flt_t * vind0, * vind1, * vvalues;
+    int i, k, nTriples = Vec_PtrSize(vTables) / 3;
+    float Entry;
+    assert( Vec_PtrSize(vTables) > 0 && Vec_PtrSize(vTables) % 3 == 0 );
+    if ( nTriples == 1 )
+    {
+        *pvInd0   = (Vec_Flt_t *)Vec_PtrEntry(vTables, 0);
+        *pvInd1   = (Vec_Flt_t *)Vec_PtrEntry(vTables, 1);
+        *pvValues = (Vec_Flt_t *)Vec_PtrEntry(vTables, 2);
+        Vec_PtrShrink( vTables, 0 );
+        return 1;
+    }
+    vInd0   = Vec_FltDup( (Vec_Flt_t *)Vec_PtrEntry(vTables, 0) );
+    vInd1   = Vec_FltDup( (Vec_Flt_t *)Vec_PtrEntry(vTables, 1) );
+    vValues = Vec_FltDup( (Vec_Flt_t *)Vec_PtrEntry(vTables, 2) );
+    for ( i = 1; i < nTriples; i++ )
+    {
+        vind0   = (Vec_Flt_t *)Vec_PtrEntry(vTables, i*3+0);
+        vind1   = (Vec_Flt_t *)Vec_PtrEntry(vTables, i*3+1);
+        vvalues = (Vec_Flt_t *)Vec_PtrEntry(vTables, i*3+2);
+        // check equality of indexes
+        if ( !Vec_FltEqual(vind0, vInd0) )
+            continue;//return 0;
+        if ( !Vec_FltEqual(vind1, vInd1) )
+            continue;//return 0;
+//        Vec_FltForEachEntry( vvalues, Entry, k )
+//            Vec_FltAddToEntry( vValues, k, Entry );
+        Vec_FltForEachEntry( vvalues, Entry, k )
+            if ( Vec_FltEntry(vValues, k) < Entry )
+                Vec_FltWriteEntry( vValues, k, Entry );
+    }
+//    Vec_FltForEachEntry( vValues, Entry, k )
+//        Vec_FltWriteEntry( vValues, k, Entry/nTriples );
+    // return the result
+    *pvInd0 = vInd0;
+    *pvInd1 = vInd1;
+    *pvValues = vValues;
+    return 1;
+}
+
+int Scl_LibertyReadTable( Scl_Tree_t * p, Vec_Str_t * vOut, Scl_Item_t * pTiming, char * pName, Vec_Ptr_t * vTemples )
+{
+    Vec_Flt_t * vIndex1 = NULL;
+    Vec_Flt_t * vIndex2 = NULL;
+    Vec_Flt_t * vValues = NULL;
+    Vec_Flt_t * vInd1, * vInd2;
+    Scl_Item_t * pItem, * pTable = NULL;
+    char * pThis, * pTempl = NULL;
+    int iPlace, i;
+    float Entry;
+    // find the table
+    Scl_ItemForEachChildName( p, pTiming, pTable, pName )
+        break;
+    if ( pTable == NULL )
+        return 0;
+    // find the template
+    pTempl = Scl_LibertyReadString(p, pTable->Head);
+    if ( pTempl == NULL || pTempl[0] == 0 )
+    {
+        // read the numbers
+        Scl_ItemForEachChild( p, pTable, pItem )
+        {
+            if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") )
+                assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+            else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") )
+                assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+            else if ( !Scl_LibertyCompare(p, pItem->Key, "values") )
+                assert(vValues == NULL), vValues = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+        }
+        if ( vIndex1 == NULL || vIndex2 == NULL || vValues == NULL )
+            { printf( "Incomplete table specification\n" ); return 0; }
+        // dump the table
+        vInd1 = vIndex1;
+        vInd2 = vIndex2;
+        // write entries
+        Vec_StrPutI_( vOut, Vec_FltSize(vInd1) );
+        Vec_FltForEachEntry( vInd1, Entry, i )
+            Vec_StrPutF_( vOut, Entry );
+        Vec_StrPut_( vOut );
+        // write entries
+        Vec_StrPutI_( vOut, Vec_FltSize(vInd2) );
+        Vec_FltForEachEntry( vInd2, Entry, i )
+            Vec_StrPutF_( vOut, Entry );
+        Vec_StrPut_( vOut );
+        Vec_StrPut_( vOut );
+        // write entries
+        assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) );
+        Vec_FltForEachEntry( vValues, Entry, i )
+        {
+            Vec_StrPutF_( vOut, Entry );
+            if ( i % Vec_FltSize(vInd2) == Vec_FltSize(vInd2)-1 )
+                Vec_StrPut_( vOut );
+        }
+    }
+    else
+    {
+        // fetch the template
+        iPlace = -1;
+        Vec_PtrForEachEntry( char *, vTemples, pThis, i )
+            if ( i % 4 == 0 && !strcmp(pTempl, pThis) )
+            {  
+                iPlace = i;
+                break;
+            }
+        if ( iPlace == -1 )
+            { printf( "Template cannot be found in the template library\n" ); return 0; }
+        // read the numbers
+        Scl_ItemForEachChild( p, pTable, pItem )
+        {
+            if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") )
+                assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+            else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") )
+                assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+            else if ( !Scl_LibertyCompare(p, pItem->Key, "values") )
+                assert(vValues == NULL), vValues = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+        }
+        // check the template style
+        vInd1 = (Vec_Flt_t *)Vec_PtrEntry( vTemples, iPlace + 2 ); // slew
+        vInd2 = (Vec_Flt_t *)Vec_PtrEntry( vTemples, iPlace + 3 ); // load
+        if ( Vec_PtrEntry(vTemples, iPlace + 1) == NULL ) // normal order (vIndex1 is slew; vIndex2 is load)
+        {
+            assert( !vIndex1 || Vec_FltSize(vIndex1) == Vec_FltSize(vInd1) );
+            assert( !vIndex2 || Vec_FltSize(vIndex2) == Vec_FltSize(vInd2) );
+            vInd1 = vIndex1 ? vIndex1 : vInd1;
+            vInd2 = vIndex2 ? vIndex2 : vInd2;
+            // write entries
+            Vec_StrPutI_( vOut, Vec_FltSize(vInd1) );
+            Vec_FltForEachEntry( vInd1, Entry, i )
+                Vec_StrPutF_( vOut, Entry );
+            Vec_StrPut_( vOut );
+            // write entries
+            Vec_StrPutI_( vOut, Vec_FltSize(vInd2) );
+            Vec_FltForEachEntry( vInd2, Entry, i )
+                Vec_StrPutF_( vOut, Entry );
+            Vec_StrPut_( vOut );
+            Vec_StrPut_( vOut );
+            // write entries
+            assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) );
+            Vec_FltForEachEntry( vValues, Entry, i )
+            {
+                Vec_StrPutF_( vOut, Entry );
+                if ( i % Vec_FltSize(vInd2) == Vec_FltSize(vInd2)-1 )
+                    Vec_StrPut_( vOut );
+            }
+        }
+        else  // reverse order (vIndex2 is slew; vIndex1 is load)
+        {
+            assert( !vIndex2 || Vec_FltSize(vIndex2) == Vec_FltSize(vInd1) );
+            assert( !vIndex1 || Vec_FltSize(vIndex1) == Vec_FltSize(vInd2) );
+            vInd1 = vIndex2 ? vIndex2 : vInd1;
+            vInd2 = vIndex1 ? vIndex1 : vInd2;
+            // write entries
+            Vec_StrPutI_( vOut, Vec_FltSize(vInd1) );
+            Vec_FltForEachEntry( vInd1, Entry, i )
+                Vec_StrPutF_( vOut, Entry );
+            Vec_StrPut_( vOut );
+            // write entries
+            Vec_StrPutI_( vOut, Vec_FltSize(vInd2) );
+            Vec_FltForEachEntry( vInd2, Entry, i )
+                Vec_StrPutF_( vOut, Entry );
+            Vec_StrPut_( vOut );
+            Vec_StrPut_( vOut );
+            // write entries -- transpose
+            assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) );
+            Vec_FltForEachEntry( vValues, Entry, i )
+            {
+                int x = i % Vec_FltSize(vInd2);
+                int y = i / Vec_FltSize(vInd2);
+                Entry = Vec_FltEntry( vValues, x * Vec_FltSize(vInd1) + y );
+                Vec_StrPutF_( vOut, Entry );
+                if ( i % Vec_FltSize(vInd2) == Vec_FltSize(vInd2)-1 )
+                    Vec_StrPut_( vOut );
+            }
+        }
+    }
+    Vec_StrPut_( vOut );
+    for ( i = 0; i < 3; i++ ) 
+        Vec_StrPutF_( vOut, 0 );
+    for ( i = 0; i < 4; i++ ) 
+        Vec_StrPutF_( vOut, 0 );
+    for ( i = 0; i < 6; i++ ) 
+        Vec_StrPutF_( vOut, 0 );
+    Vec_FltFreeP( &vIndex1 );
+    Vec_FltFreeP( &vIndex2 );
+    Vec_FltFreeP( &vValues );
+    Vec_StrPut_( vOut );
+    Vec_StrPut_( vOut );
+    return 1;
+}
+void Scl_LibertyPrintTemplates( Vec_Ptr_t * vRes )
+{
+    Vec_Flt_t * vArray; int i;
+    assert( Vec_PtrSize(vRes) % 4 == 0 );
+    printf( "There are %d slew/load templates\n", Vec_PtrSize(vRes) % 4 );
+    Vec_PtrForEachEntry( Vec_Flt_t *, vRes, vArray, i )
+    {
+        if ( i % 4 == 0 )
+            printf( "%s\n", (char *)vArray );
+        else if ( i % 4 == 1 )
+            printf( "%d\n", (int)(vArray != NULL) );
+        else if ( i % 4 == 2 || i % 4 == 3 )
+            Vec_FltPrint( vArray );
+        if ( i % 4 == 3 )
+            printf( "\n" );
+    }
+}
+Vec_Ptr_t * Scl_LibertyReadTemplates( Scl_Tree_t * p )
+{
+    Vec_Ptr_t * vRes = NULL;
+    Vec_Flt_t * vIndex1, * vIndex2;
+    Scl_Item_t * pTempl, * pItem;
+    char * pVar1, * pVar2;
+    int fFlag0, fFlag1;
+    vRes = Vec_PtrAlloc( 100 );
+    Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pTempl, "lu_table_template" )
+    {
+        pVar1 = pVar2 = NULL;
+        vIndex1 = vIndex2 = NULL;
+        Scl_ItemForEachChild( p, pTempl, pItem )
+        {
+            if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") )
+                assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+            else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") )
+                assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+            else if ( !Scl_LibertyCompare(p, pItem->Key, "variable_1") )
+                assert(pVar1 == NULL), pVar1 = Abc_UtilStrsav( Scl_LibertyReadString(p, pItem->Head) );
+            else if ( !Scl_LibertyCompare(p, pItem->Key, "variable_2") )
+                assert(pVar2 == NULL), pVar2 = Abc_UtilStrsav( Scl_LibertyReadString(p, pItem->Head) );
+        }
+        if ( pVar1 == NULL || pVar2 == NULL )
+        {
+            ABC_FREE( pVar1 );  
+            ABC_FREE( pVar2 );
+            Vec_FltFreeP( &vIndex1 );
+            Vec_FltFreeP( &vIndex2 );
+            continue;
+        }
+        assert( pVar1 != NULL && pVar2 != NULL );
+        fFlag0 = (!strcmp(pVar1, "input_net_transition") && !strcmp(pVar2, "total_output_net_capacitance"));
+        fFlag1 = (!strcmp(pVar2, "input_net_transition") && !strcmp(pVar1, "total_output_net_capacitance"));
+        ABC_FREE( pVar1 );  
+        ABC_FREE( pVar2 );
+        if ( !fFlag0 && !fFlag1 )
+        {
+            Vec_FltFreeP( &vIndex1 );
+            Vec_FltFreeP( &vIndex2 );
+            continue;
+        }
+        Vec_PtrPush( vRes, Abc_UtilStrsav( Scl_LibertyReadString(p, pTempl->Head) ) );
+        Vec_PtrPush( vRes, fFlag0 ? NULL : (void *)(ABC_PTRINT_T)1 );
+        Vec_PtrPush( vRes, fFlag0 ? vIndex1 : vIndex2 );
+        Vec_PtrPush( vRes, fFlag0 ? vIndex2 : vIndex1 );
+    }
+    if ( Vec_PtrSize(vRes) == 0 )
+        Abc_Print( 0, "Templates are not defined.\n" );
+    // print templates
+//    printf( "Found %d templates\n", Vec_PtrSize(vRes)/4 );
+//    Scl_LibertyPrintTemplates( vRes );
+    return vRes;
+}
+Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbose )
+{
+    int fUseFirstTable = 0;
+    Vec_Str_t * vOut;
+    Vec_Ptr_t * vNameIns, * vTemples = NULL;
+    Scl_Item_t * pCell, * pPin, * pTiming;
+    Vec_Wrd_t * vTruth;
+    char * pFormula, * pName;
+    int i, k, Counter, nOutputs, nCells;
+    int nSkipped[3] = {0};
+
+    // read delay-table templates
+    vTemples = Scl_LibertyReadTemplates( p );
+
+    // start the library
+    vOut = Vec_StrAlloc( 10000 );
+    Vec_StrPutI_( vOut, ABC_SCL_CUR_VERSION );
+
+    // top level information
+    Vec_StrPut_( vOut );
+    Vec_StrPutS_( vOut, Scl_LibertyReadString(p, Scl_LibertyRoot(p)->Head) );
+    Vec_StrPutS_( vOut, Scl_LibertyReadDefaultWireLoad(p) );
+    Vec_StrPutS_( vOut, Scl_LibertyReadDefaultWireLoadSel(p) );
+    Vec_StrPutF_( vOut, Scl_LibertyReadDefaultMaxTrans(p) );
+    Vec_StrPutI_( vOut, Scl_LibertyReadTimeUnit(p) );
+    Scl_LibertyReadLoadUnit( p, vOut );
+    Vec_StrPut_( vOut );
+    Vec_StrPut_( vOut );
+
+    // read wire loads
+    Scl_LibertyReadWireLoad( p, vOut );
+    Scl_LibertyReadWireLoadSelect( p, vOut );
+
+    // count cells
+    nCells = 0;
+    Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pCell, "cell" )
+    {
+        if ( Scl_LibertyReadCellIsFlop(p, pCell) )
+        {
+            if ( fVeryVerbose )  printf( "Scl_LibertyReadGenlib() skipped sequential cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) );
+            nSkipped[0]++;
+            continue;
+        }
+        if ( Scl_LibertyReadCellIsThreeState(p, pCell) )
+        {
+            if ( fVeryVerbose )  printf( "Scl_LibertyReadGenlib() skipped three-state cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) );
+            nSkipped[1]++;
+            continue;
+        }
+        if ( (Counter = Scl_LibertyReadCellOutputNum(p, pCell)) == 0 )
+        {
+            if ( fVeryVerbose )  printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" without logic function.\n", Scl_LibertyReadString(p, pCell->Head) );
+            nSkipped[2]++;
+            continue;
+        }
+        nCells++;
+    }
+    // read cells
+    Vec_StrPutI_( vOut, nCells );
+    Vec_StrPut_( vOut );
+    Vec_StrPut_( vOut );
+    Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pCell, "cell" )
+    {
+        if ( Scl_LibertyReadCellIsFlop(p, pCell) )
+            continue;
+        if ( Scl_LibertyReadCellIsThreeState(p, pCell) )
+            continue;
+        if ( (Counter = Scl_LibertyReadCellOutputNum(p, pCell)) == 0 )
+            continue;
+        // top level information
+        Vec_StrPutS_( vOut, Scl_LibertyReadString(p, pCell->Head) );
+        pName = Scl_LibertyReadCellArea(p, pCell);
+        Vec_StrPutF_( vOut, pName ? atof(pName) : 1 );
+        Vec_StrPutI_( vOut, Scl_LibertyReadDeriveStrength(p, pCell) );
+        // pin count
+        nOutputs = Scl_LibertyReadCellOutputNum( p, pCell );
+        Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, pCell, "pin") - nOutputs );
+        Vec_StrPutI_( vOut, nOutputs );
+        Vec_StrPut_( vOut );
+        Vec_StrPut_( vOut );
+
+        // input pins
+        vNameIns = Vec_PtrAlloc( 16 );
+        Scl_ItemForEachChildName( p, pCell, pPin, "pin" )
+        {
+            float CapOne, CapRise, CapFall;
+            if ( Scl_LibertyReadPinFormula(p, pPin) != NULL ) // skip output pin
+                continue;
+            assert( Scl_LibertyReadPinDirection(p, pPin) == 0 );
+            pName = Scl_LibertyReadString(p, pPin->Head);
+            Vec_PtrPush( vNameIns, Abc_UtilStrsav(pName) );
+            Vec_StrPutS_( vOut, pName );
+            CapOne  = Scl_LibertyReadPinCap( p, pPin, "capacitance" );
+            CapRise = Scl_LibertyReadPinCap( p, pPin, "rise_capacitance" );
+            CapFall = Scl_LibertyReadPinCap( p, pPin, "fall_capacitance" );
+            if ( CapRise == 0 )
+                CapRise = CapOne;
+            if ( CapFall == 0 )
+                CapFall = CapOne;
+            Vec_StrPutF_( vOut, CapRise );
+            Vec_StrPutF_( vOut, CapFall );
+            Vec_StrPut_( vOut );
+        }
+        Vec_StrPut_( vOut );
+        // output pins
+        Scl_ItemForEachChildName( p, pCell, pPin, "pin" )
+        {
+            if ( !Scl_LibertyReadPinFormula(p, pPin) ) // skip input pin
+                continue;
+            assert( Scl_LibertyReadPinDirection(p, pPin) == 1 );
+            pName = Scl_LibertyReadString(p, pPin->Head);
+            Vec_StrPutS_( vOut, pName );
+            Vec_StrPutF_( vOut, Scl_LibertyReadPinCap( p, pPin, "max_capacitance" ) );
+            Vec_StrPutF_( vOut, Scl_LibertyReadPinCap( p, pPin, "max_transition" ) );
+            Vec_StrPutI_( vOut, Vec_PtrSize(vNameIns) );
+            pFormula = Scl_LibertyReadPinFormula(p, pPin);
+            Vec_StrPutS_( vOut, pFormula );
+            // write truth table
+            vTruth = Mio_ParseFormulaTruth( pFormula, (char **)Vec_PtrArray(vNameIns), Vec_PtrSize(vNameIns) );
+            for ( i = 0; i < Abc_Truth6WordNum(Vec_PtrSize(vNameIns)); i++ )
+                Vec_StrPutW_( vOut, Vec_WrdEntry(vTruth, i) );
+            Vec_WrdFree( vTruth );
+            Vec_StrPut_( vOut );
+            Vec_StrPut_( vOut );
+
+            // write the delay tables
+            if ( fUseFirstTable )
+            {
+                Vec_PtrForEachEntry( char *, vNameIns, pName, i )
+                {
+                    pTiming = Scl_LibertyReadPinTiming( p, pPin, pName );
+                    Vec_StrPutS_( vOut, pName );
+                    Vec_StrPutI_( vOut, (int)(pTiming != NULL) );
+                    if ( pTiming == NULL ) // output does not depend on input
+                        continue;
+                    Vec_StrPutI_( vOut, Scl_LibertyReadTimingSense(p, pTiming) );
+                    Vec_StrPut_( vOut );
+                    Vec_StrPut_( vOut );
+                    // some cells only have 'rise' or 'fall' but not both - here we work around this
+                    if ( !Scl_LibertyReadTable( p, vOut, pTiming, "cell_rise",           vTemples ) )
+                        if ( !Scl_LibertyReadTable( p, vOut, pTiming, "cell_fall",       vTemples ) )
+                                { printf( "Table cannot be found\n" ); return NULL; }                              
+                    if ( !Scl_LibertyReadTable( p, vOut, pTiming, "cell_fall",           vTemples ) )
+                        if ( !Scl_LibertyReadTable( p, vOut, pTiming, "cell_rise",       vTemples ) )
+                                { printf( "Table cannot be found\n" ); return NULL; }                              
+                    if ( !Scl_LibertyReadTable( p, vOut, pTiming, "rise_transition",     vTemples ) )
+                        if ( !Scl_LibertyReadTable( p, vOut, pTiming, "fall_transition", vTemples ) )
+                                { printf( "Table cannot be found\n" ); return NULL; }                              
+                    if ( !Scl_LibertyReadTable( p, vOut, pTiming, "fall_transition",     vTemples ) )
+                        if ( !Scl_LibertyReadTable( p, vOut, pTiming, "rise_transition", vTemples ) )
+                                { printf( "Table cannot be found\n" ); return NULL; }  
+                }
+                continue;
+            }
+
+            // write the timing tables
+            Vec_PtrForEachEntry( char *, vNameIns, pName, i )
+            {
+                Vec_Ptr_t * vTables[4];
+                Vec_Ptr_t * vTimings;
+                vTimings = Scl_LibertyReadPinTimingAll( p, pPin, pName );
+                Vec_StrPutS_( vOut, pName );
+                Vec_StrPutI_( vOut, (int)(Vec_PtrSize(vTimings) != 0) );
+                if ( Vec_PtrSize(vTimings) == 0 ) // output does not depend on input
+                {
+                    Vec_PtrFree( vTimings );
+                    continue;
+                }
+                Vec_StrPutI_( vOut, Scl_LibertyReadTimingSense(p, (Scl_Item_t *)Vec_PtrEntry(vTimings, 0)) );
+                Vec_StrPut_( vOut );
+                Vec_StrPut_( vOut );
+                // collect the timing tables
+                for ( k = 0; k < 4; k++ )
+                    vTables[k] = Vec_PtrAlloc( 16 );
+                Vec_PtrForEachEntry( Scl_Item_t *, vTimings, pTiming, k )
+                {
+                    // some cells only have 'rise' or 'fall' but not both - here we work around this
+                    if ( !Scl_LibertyScanTable( p, vTables[0], pTiming, "cell_rise",           vTemples ) )
+                        if ( !Scl_LibertyScanTable( p, vTables[0], pTiming, "cell_fall",       vTemples ) )
+                                { printf( "Table cannot be found\n" ); return NULL; }                              
+                    if ( !Scl_LibertyScanTable( p, vTables[1], pTiming, "cell_fall",           vTemples ) )
+                        if ( !Scl_LibertyScanTable( p, vTables[1], pTiming, "cell_rise",       vTemples ) )
+                                { printf( "Table cannot be found\n" ); return NULL; }                              
+                    if ( !Scl_LibertyScanTable( p, vTables[2], pTiming, "rise_transition",     vTemples ) )
+                        if ( !Scl_LibertyScanTable( p, vTables[2], pTiming, "fall_transition", vTemples ) )
+                                { printf( "Table cannot be found\n" ); return NULL; }                              
+                    if ( !Scl_LibertyScanTable( p, vTables[3], pTiming, "fall_transition",     vTemples ) )
+                        if ( !Scl_LibertyScanTable( p, vTables[3], pTiming, "rise_transition", vTemples ) )
+                                { printf( "Table cannot be found\n" ); return NULL; }  
+                }
+                Vec_PtrFree( vTimings );
+                // compute worse case of the tables
+                for ( k = 0; k < 4; k++ )
+                {
+                    Vec_Flt_t * vInd0, * vInd1, * vValues;
+                    if ( !Scl_LibertyComputeWorstCase( vTables[k], &vInd0, &vInd1, &vValues ) )
+                        { printf( "Table indexes have different values\n" ); return NULL; }  
+                    Vec_VecFree( (Vec_Vec_t *)vTables[k] );
+                    Scl_LibertyDumpTables( vOut, vInd0, vInd1, vValues );
+                    Vec_FltFree( vInd0 );
+                    Vec_FltFree( vInd1 );
+                    Vec_FltFree( vValues );
+                }
+            }
+        }
+        Vec_StrPut_( vOut );
+        Vec_PtrFreeFree( vNameIns );
+    }
+    // free templates
+    if ( vTemples )
+    {
+        Vec_Flt_t * vArray;
+        assert( Vec_PtrSize(vTemples) % 4 == 0 );
+        Vec_PtrForEachEntry( Vec_Flt_t *, vTemples, vArray, i )
+            if ( i % 4 == 0 )
+                ABC_FREE( vArray );
+            else if ( i % 4 == 2 || i % 4 == 3 )
+                Vec_FltFree( vArray );
+        Vec_PtrFree( vTemples );
+    }
+    if ( fVerbose )
+    {
+        printf( "Library \"%s\" from \"%s\" has %d cells ", 
+            Scl_LibertyReadString(p, Scl_LibertyRoot(p)->Head), p->pFileName, nCells );
+        printf( "(%d skipped: %d seq; %d tri-state; %d no func).  ", 
+            nSkipped[0]+nSkipped[1]+nSkipped[2], nSkipped[0], nSkipped[1], nSkipped[2] );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
+    }
+    return vOut;
+}
+SC_Lib * Abc_SclReadLiberty( char * pFileName, int fVerbose, int fVeryVerbose )
+{
+    SC_Lib * pLib;
+    Scl_Tree_t * p;
+    Vec_Str_t * vStr;
+    p = Scl_LibertyParse( pFileName, fVeryVerbose );
+    if ( p == NULL )
+        return NULL;
+//    Scl_LibertyParseDump( p, "temp_.lib" );
+    // collect relevant data
+    vStr = Scl_LibertyReadSclStr( p, fVerbose, fVeryVerbose );
+    Scl_LibertyStop( p, fVeryVerbose );
+    if ( vStr == NULL )
+        return NULL;
+    // construct SCL data-structure
+    pLib = Abc_SclReadFromStr( vStr );
+    if ( pLib == NULL )
+        return NULL;
+    pLib->pFileName = Abc_UtilStrsav( pFileName );
+    Abc_SclLibNormalize( pLib );
+    Vec_StrFree( vStr );
+//    printf( "Average slew = %.2f ps\n", Abc_SclComputeAverageSlew(pLib) );
+    return pLib;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Experiments with Liberty parsing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Scl_LibertyTest()
+{
+    char * pFileName = "bwrc.lib";
+    int fVerbose = 1;
+    int fVeryVerbose = 0;
+    Scl_Tree_t * p;
+    Vec_Str_t * vStr;
+//    return;
+    p = Scl_LibertyParse( pFileName, fVeryVerbose );
+    if ( p == NULL )
+        return;
+//    Scl_LibertyParseDump( p, "temp_.lib" );
+    vStr = Scl_LibertyReadSclStr( p, fVerbose, fVeryVerbose );
+    Scl_LibertyStringDump( "test_scl.lib", vStr );
+    Vec_StrFree( vStr );
+    Scl_LibertyStop( p, fVerbose );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/scl/sclLoad.c b/abc-build/src/map/scl/sclLoad.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/scl/sclLoad.c
@@ -0,0 +1,227 @@
+/**CFile****************************************************************
+
+  FileName    [sclLoad.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Standard-cell library representation.]
+
+  Synopsis    [Wire/gate load computations.]
+
+  Author      [Alan Mishchenko, Niklas Een]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 24, 2012.]
+
+  Revision    [$Id: sclLoad.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sclSize.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns estimated wire capacitances for each fanout count.]
+
+  Description []
+               
+  SideEffects []`
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Flt_t * Abc_SclFindWireCaps( SC_WireLoad * pWL, int nFanoutMax )
+{
+    Vec_Flt_t * vCaps = NULL;
+    float EntryPrev, EntryCur, Slope;
+    int i, iPrev, k, Entry, EntryMax;
+    assert( pWL != NULL );
+    // find the biggest fanout count
+    EntryMax = 0;
+    Vec_IntForEachEntry( pWL->vFanout, Entry, i )
+        EntryMax = Abc_MaxInt( EntryMax, Entry );
+    // create the array
+    vCaps = Vec_FltStart( Abc_MaxInt(nFanoutMax, EntryMax) + 1 );
+    Vec_IntForEachEntry( pWL->vFanout, Entry, i )
+        Vec_FltWriteEntry( vCaps, Entry, Vec_FltEntry(pWL->vLen, i) * pWL->cap );
+    // interpolate between the values
+    assert( Vec_FltEntry(vCaps, 1) != 0 );
+    iPrev = 1;
+    EntryPrev = Vec_FltEntry(vCaps, 1);
+    Vec_FltForEachEntryStart( vCaps, EntryCur, i, 2 )
+    {
+        if ( EntryCur == 0 )
+            continue;
+        Slope = (EntryCur - EntryPrev) / (i - iPrev);
+        for ( k = iPrev + 1; k < i; k++ )
+            Vec_FltWriteEntry( vCaps, k, EntryPrev + Slope * (k - iPrev) );
+        EntryPrev = EntryCur;
+        iPrev = i;
+    }
+    // extrapolate after the largest value
+    Slope = pWL->cap * pWL->slope;
+    for ( k = iPrev + 1; k < i; k++ )
+        Vec_FltWriteEntry( vCaps, k, EntryPrev + Slope * (k - iPrev) );
+    // show
+//    Vec_FltForEachEntry( vCaps, EntryCur, i )
+//        printf( "%3d : %f\n", i, EntryCur );
+    return vCaps;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes load for all nodes in the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Abc_SclFindWireLoad( Vec_Flt_t * vWireCaps, int nFans )
+{
+    if ( vWireCaps == NULL )
+        return 0;
+    return Vec_FltEntry( vWireCaps, Abc_MinInt(nFans, Vec_FltSize(vWireCaps)-1) );
+}
+void Abc_SclAddWireLoad( SC_Man * p, Abc_Obj_t * pObj, int fSubtr )
+{
+    float Load = Abc_SclFindWireLoad( p->vWireCaps, Abc_ObjFanoutNum(pObj) );
+    Abc_SclObjLoad(p, pObj)->rise += fSubtr ? -Load : Load;
+    Abc_SclObjLoad(p, pObj)->fall += fSubtr ? -Load : Load;
+}
+void Abc_SclComputeLoad( SC_Man * p )
+{
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k;
+    // clear load storage
+    Abc_NtkForEachObj( p->pNtk, pObj, i )
+    {
+        SC_Pair * pLoad = Abc_SclObjLoad( p, pObj );
+        if ( !Abc_ObjIsPo(pObj) )
+            pLoad->rise = pLoad->fall = 0.0;
+    }
+    // add cell load
+    Abc_NtkForEachNode1( p->pNtk, pObj, i )
+    {
+        SC_Cell * pCell = Abc_SclObjCell( pObj );
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+        {
+            SC_Pair * pLoad = Abc_SclObjLoad( p, pFanin );
+            SC_Pin * pPin = SC_CellPin( pCell, k );
+            pLoad->rise += pPin->rise_cap;
+            pLoad->fall += pPin->fall_cap;
+        }
+    }
+    // add PO load
+    Abc_NtkForEachCo( p->pNtk, pObj, i )
+    {
+        SC_Pair * pLoadPo = Abc_SclObjLoad( p, pObj );
+        SC_Pair * pLoad = Abc_SclObjLoad( p, Abc_ObjFanin0(pObj) );
+        pLoad->rise += pLoadPo->rise;
+        pLoad->fall += pLoadPo->fall;
+    }
+    // add wire load
+    if ( p->pWLoadUsed != NULL )
+    {
+        if ( p->vWireCaps == NULL )
+            p->vWireCaps = Abc_SclFindWireCaps( p->pWLoadUsed, Abc_NtkGetFanoutMax(p->pNtk) );
+        Abc_NtkForEachNode1( p->pNtk, pObj, i )
+            Abc_SclAddWireLoad( p, pObj, 0 );
+        Abc_NtkForEachPi( p->pNtk, pObj, i )
+            Abc_SclAddWireLoad( p, pObj, 0 );
+    }
+    // check input loads
+    if ( p->vInDrive != NULL )
+    {
+        Abc_NtkForEachPi( p->pNtk, pObj, i )
+        {
+            SC_Pair * pLoad = Abc_SclObjLoad( p, pObj );
+            if ( Abc_SclObjInDrive(p, pObj) != 0 && (pLoad->rise > Abc_SclObjInDrive(p, pObj) || pLoad->fall > Abc_SclObjInDrive(p, pObj)) )
+                printf( "Maximum input drive strength is exceeded at primary input %d.\n", i );
+        }
+    }
+    // calculate average load
+//    if ( p->EstLoadMax )
+    {
+        double TotalLoad = 0;
+        int nObjs = 0;
+        Abc_NtkForEachNode1( p->pNtk, pObj, i )
+        {
+            SC_Pair * pLoad = Abc_SclObjLoad( p, pObj );
+            TotalLoad += 0.5 * pLoad->fall + 0.5 * pLoad->rise;
+            nObjs++;
+        }
+        Abc_NtkForEachPi( p->pNtk, pObj, i )
+        {
+            SC_Pair * pLoad = Abc_SclObjLoad( p, pObj );
+            TotalLoad += 0.5 * pLoad->fall + 0.5 * pLoad->rise;
+            nObjs++;
+        }
+        p->EstLoadAve = (float)(TotalLoad / nObjs);
+//        printf( "Average load = %.2f\n", p->EstLoadAve );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates load of the node's fanins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclUpdateLoad( SC_Man * p, Abc_Obj_t * pObj, SC_Cell * pOld, SC_Cell * pNew )
+{
+    Abc_Obj_t * pFanin;
+    int k;
+    Abc_ObjForEachFanin( pObj, pFanin, k )
+    {
+        SC_Pair * pLoad = Abc_SclObjLoad( p, pFanin );
+        SC_Pin * pPinOld = SC_CellPin( pOld, k );
+        SC_Pin * pPinNew = SC_CellPin( pNew, k );
+        pLoad->rise += pPinNew->rise_cap - pPinOld->rise_cap;
+        pLoad->fall += pPinNew->fall_cap - pPinOld->fall_cap;
+    }
+}
+void Abc_SclUpdateLoadSplit( SC_Man * p, Abc_Obj_t * pBuffer, Abc_Obj_t * pFanout )
+{
+    SC_Pin * pPin;
+    SC_Pair * pLoad;
+    int iFanin = Abc_NodeFindFanin( pFanout, pBuffer );
+    assert( iFanin >= 0 );
+    assert( Abc_ObjFaninNum(pBuffer) == 1 );
+    pPin = SC_CellPin( Abc_SclObjCell(pFanout), iFanin );
+    // update load of the buffer
+    pLoad = Abc_SclObjLoad( p, pBuffer );
+    pLoad->rise -= pPin->rise_cap;
+    pLoad->fall -= pPin->fall_cap;
+    // update load of the fanin
+    pLoad = Abc_SclObjLoad( p, Abc_ObjFanin0(pBuffer) );
+    pLoad->rise += pPin->rise_cap;
+    pLoad->fall += pPin->fall_cap;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/scl/sclSize.c b/abc-build/src/map/scl/sclSize.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/scl/sclSize.c
@@ -0,0 +1,894 @@
+/**CFile****************************************************************
+
+  FileName    [sclSize.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Standard-cell library representation.]
+
+  Synopsis    [Core timing analysis used in gate-sizing.]
+
+  Author      [Alan Mishchenko, Niklas Een]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 24, 2012.]
+
+  Revision    [$Id: sclSize.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sclSize.h"
+#include "map/mio/mio.h"
+#include "misc/vec/vecWec.h"
+#include "base/main/main.h"
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Finding most critical objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_SclFindCriticalCo( SC_Man * p, int * pfRise )
+{
+    Abc_Obj_t * pObj, * pPivot = NULL;
+    float fMaxArr = 0;
+    int i;
+    assert( Abc_NtkPoNum(p->pNtk) > 0 );
+    Abc_NtkForEachCo( p->pNtk, pObj, i )
+    {
+        SC_Pair * pArr = Abc_SclObjTime( p, pObj );
+        if ( fMaxArr < pArr->rise )  fMaxArr = pArr->rise, *pfRise = 1, pPivot = pObj;
+        if ( fMaxArr < pArr->fall )  fMaxArr = pArr->fall, *pfRise = 0, pPivot = pObj;
+    }
+    if ( fMaxArr == 0 )
+        pPivot = Abc_NtkPo(p->pNtk, 0);
+    assert( pPivot != NULL );
+    return pPivot;
+}
+// assumes that slacks are not available (uses arrival times)
+Abc_Obj_t * Abc_SclFindMostCriticalFanin2( SC_Man * p, int * pfRise, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin, * pPivot = NULL;
+    float fMaxArr = 0;
+    int i;
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        SC_Pair * pArr = Abc_SclObjTime( p, pFanin );
+        if ( fMaxArr < pArr->rise )  fMaxArr = pArr->rise, *pfRise = 1, pPivot = pFanin;
+        if ( fMaxArr < pArr->fall )  fMaxArr = pArr->fall, *pfRise = 0, pPivot = pFanin;
+    }
+    return pPivot;
+}
+// assumes that slack are available
+Abc_Obj_t * Abc_SclFindMostCriticalFanin( SC_Man * p, int * pfRise, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin, * pPivot = NULL;
+    float fMinSlack = ABC_INFINITY;
+    SC_Pair * pArr;
+    int i;
+    *pfRise = 0;
+    // find min-slack node
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        if ( fMinSlack > Abc_SclObjGetSlack( p, pFanin, p->MaxDelay0 ) )
+        {
+            fMinSlack = Abc_SclObjGetSlack( p, pFanin, p->MaxDelay0 );
+            pPivot = pFanin;
+        }
+    if ( pPivot == NULL )
+        return NULL;
+    // find its leading phase
+    pArr = Abc_SclObjTime( p, pPivot );
+    *pfRise = (pArr->rise >= pArr->fall);
+    return pPivot;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Printing timing information for the node/network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_SclTimeNodePrint( SC_Man * p, Abc_Obj_t * pObj, int fRise, int Length, float maxDelay )
+{
+    SC_Cell * pCell = Abc_ObjIsNode(pObj) ? Abc_SclObjCell(pObj) : NULL;
+    printf( "%8d : ",           Abc_ObjId(pObj) );
+    printf( "%d ",              Abc_ObjFaninNum(pObj) );
+    printf( "%4d ",             Abc_ObjFanoutNum(pObj) );
+    printf( "%-*s ",            Length, pCell ? pCell->pName : "pi" );
+    printf( "A =%7.2f  ",       pCell ? pCell->area : 0.0 );
+    printf( "D%s =",            fRise ? "r" : "f" );
+    printf( "%6.1f",            Abc_SclObjTimeMax(p, pObj) );
+    printf( "%7.1f ps  ",       -Abc_AbsFloat(Abc_SclObjTimeOne(p, pObj, 0) - Abc_SclObjTimeOne(p, pObj, 1)) );
+    printf( "S =%6.1f ps  ",    Abc_SclObjSlewMax(p, pObj) );
+    printf( "Cin =%5.1f ff  ",  pCell ? SC_CellPinCapAve(pCell) : 0.0 );
+    printf( "Cout =%6.1f ff  ", Abc_SclObjLoadMax(p, pObj) );
+    printf( "Cmax =%6.1f ff  ", pCell ? SC_CellPin(pCell, pCell->n_inputs)->max_out_cap : 0.0 );
+    printf( "G =%5d  ",         pCell ? (int)(100.0 * Abc_SclObjLoadAve(p, pObj) / SC_CellPinCapAve(pCell)) : 0 );
+//    printf( "SL =%6.1f ps",     Abc_SclObjSlackMax(p, pObj, p->MaxDelay0) );
+    printf( "\n" );
+}
+void Abc_SclTimeNtkPrint( SC_Man * p, int fShowAll, int fPrintPath )
+{
+    int fReversePath = 1;
+    int i, nLength = 0, fRise = 0;
+    Abc_Obj_t * pObj, * pPivot = Abc_SclFindCriticalCo( p, &fRise ); 
+    float maxDelay = Abc_SclObjTimeOne( p, pPivot, fRise );
+    p->ReportDelay = maxDelay;
+
+#ifdef WIN32
+    printf( "WireLoad = \"%s\"  ", p->pWLoadUsed ? p->pWLoadUsed->pName : "none" );
+    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 14 ); // yellow
+    printf( "Gates =%7d ",         Abc_NtkNodeNum(p->pNtk) );
+    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 );  // normal
+    printf( "(%5.1f %%)   ",       100.0 * Abc_SclGetBufInvCount(p->pNtk) / Abc_NtkNodeNum(p->pNtk) );
+    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 10 ); // green
+    printf( "Cap =%5.1f ff ",      p->EstLoadAve );
+    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 );  // normal
+    printf( "(%5.1f %%)   ",       Abc_SclGetAverageSize(p->pNtk) );
+    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 11 ); // blue
+    printf( "Area =%12.2f ",       Abc_SclGetTotalArea(p->pNtk) );
+    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 );  // normal
+    printf( "(%5.1f %%)   ",       100.0 * Abc_SclCountMinSize(p->pLib, p->pNtk, 0) / Abc_NtkNodeNum(p->pNtk) );
+    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 13 ); // magenta
+    printf( "Delay =%9.2f ps  ",   maxDelay );
+    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 );  // normal
+    printf( "(%5.1f %%)   ",       100.0 * Abc_SclCountNearCriticalNodes(p) / Abc_NtkNodeNum(p->pNtk) );
+    printf( "            \n" );
+#else
+    Abc_Print( 1, "WireLoad = \"%s\"  ",   p->pWLoadUsed ? p->pWLoadUsed->pName : "none" );
+    Abc_Print( 1, "%sGates =%7d%s ",       "\033[1;33m", Abc_NtkNodeNum(p->pNtk),      "\033[0m" ); // yellow
+    Abc_Print( 1, "(%5.1f %%)   ",         100.0 * Abc_SclGetBufInvCount(p->pNtk) / Abc_NtkNodeNum(p->pNtk) );
+    Abc_Print( 1, "%sCap =%5.1f ff%s ",    "\033[1;32m", p->EstLoadAve,                "\033[0m" ); // green
+    Abc_Print( 1, "(%5.1f %%)   ",         Abc_SclGetAverageSize(p->pNtk) );
+    Abc_Print( 1, "%sArea =%12.2f%s ",     "\033[1;36m", Abc_SclGetTotalArea(p->pNtk), "\033[0m" ); // blue
+    Abc_Print( 1, "(%5.1f %%)   ",         100.0 * Abc_SclCountMinSize(p->pLib, p->pNtk, 0) / Abc_NtkNodeNum(p->pNtk) );
+    Abc_Print( 1, "%sDelay =%9.2f ps%s  ", "\033[1;35m", maxDelay,                     "\033[0m" ); // magenta
+    Abc_Print( 1, "(%5.1f %%)   ",         100.0 * Abc_SclCountNearCriticalNodes(p) / Abc_NtkNodeNum(p->pNtk) );
+    Abc_Print( 1, "            \n" );
+#endif
+
+    if ( fShowAll )
+    {
+//        printf( "Timing information for all nodes: \n" );
+        // find the longest cell name
+        Abc_NtkForEachNodeReverse( p->pNtk, pObj, i )
+            if ( Abc_ObjFaninNum(pObj) > 0 )
+                nLength = Abc_MaxInt( nLength, strlen(Abc_SclObjCell(pObj)->pName) );
+        // print timing
+        Abc_NtkForEachNodeReverse( p->pNtk, pObj, i )
+            if ( Abc_ObjFaninNum(pObj) > 0 )
+                Abc_SclTimeNodePrint( p, pObj, -1, nLength, maxDelay );
+    }
+    if ( fPrintPath )
+    {
+        Abc_Obj_t * pTemp, * pPrev = NULL;
+        int iStart = -1, iEnd = -1;
+        Vec_Ptr_t * vPath;
+//        printf( "Critical path: \n" );        
+        // find the longest cell name
+        pObj = Abc_ObjFanin0(pPivot);
+        i = 0;
+        while ( pObj && Abc_ObjIsNode(pObj) )
+        {
+            i++;
+            nLength = Abc_MaxInt( nLength, strlen(Abc_SclObjCell(pObj)->pName) );
+            pObj = Abc_SclFindMostCriticalFanin( p, &fRise, pObj );
+        }
+
+        // print timing
+        if ( !fReversePath )
+        {
+            // print timing
+            pObj = Abc_ObjFanin0(pPivot);
+            while ( pObj )//&& Abc_ObjIsNode(pObj) )
+            {
+                printf( "Path%3d --", i-- );
+                Abc_SclTimeNodePrint( p, pObj, fRise, nLength, maxDelay );
+                pPrev = pObj;
+                pObj = Abc_SclFindMostCriticalFanin( p, &fRise, pObj );
+            }
+        }
+        else
+        {
+            // collect path nodes
+            vPath = Vec_PtrAlloc( 100 );
+            Vec_PtrPush( vPath, pPivot );
+            pObj = Abc_ObjFanin0(pPivot);
+            while ( pObj )//&& Abc_ObjIsNode(pObj) )
+            {
+                Vec_PtrPush( vPath, pObj );
+                pPrev = pObj;
+                pObj = Abc_SclFindMostCriticalFanin( p, &fRise, pObj );
+            }
+            Vec_PtrForEachEntryReverse( Abc_Obj_t *, vPath, pObj, i )
+            {
+                printf( "Path%3d --", Vec_PtrSize(vPath)-1-i );
+                Abc_SclTimeNodePrint( p, pObj, fRise, nLength, maxDelay );
+                if ( i == 1 )
+                    break;
+            }
+            Vec_PtrFree( vPath );
+        }
+        // print start-point and end-point
+        Abc_NtkForEachPi( p->pNtk, pTemp, iStart )
+            if ( pTemp == pPrev )
+                break;
+        Abc_NtkForEachPo( p->pNtk, pTemp, iEnd )
+            if ( pTemp == pPivot )
+                break;
+        printf( "Start-point = pi%0*d.  End-point = po%0*d.\n", 
+            Abc_Base10Log( Abc_NtkPiNum(p->pNtk) ), iStart, 
+            Abc_Base10Log( Abc_NtkPoNum(p->pNtk) ), iEnd );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Timing computation for pin/gate/cone/network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_SclTimeFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin )
+{
+    SC_Pair * pArrIn   = Abc_SclObjTime( p, pFanin );
+    SC_Pair * pSlewIn  = Abc_SclObjSlew( p, pFanin );
+    SC_Pair * pLoad    = Abc_SclObjLoad( p, pObj );
+    SC_Pair * pArrOut  = Abc_SclObjTime( p, pObj );   // modified
+    SC_Pair * pSlewOut = Abc_SclObjSlew( p, pObj );   // modified
+    Scl_LibPinArrival( pTime, pArrIn, pSlewIn, pLoad, pArrOut, pSlewOut );
+}
+static inline void Abc_SclDeptFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin )
+{
+    SC_Pair * pDepIn   = Abc_SclObjDept( p, pFanin );   // modified
+    SC_Pair * pSlewIn  = Abc_SclObjSlew( p, pFanin );
+    SC_Pair * pLoad    = Abc_SclObjLoad( p, pObj );
+    SC_Pair * pDepOut  = Abc_SclObjDept( p, pObj );
+    Scl_LibPinDeparture( pTime, pDepIn, pSlewIn, pLoad, pDepOut );
+}
+static inline void Abc_SclDeptObj( SC_Man * p, Abc_Obj_t * pObj )
+{
+    SC_Timing * pTime;
+    Abc_Obj_t * pFanout;
+    int i;
+    SC_PairClean( Abc_SclObjDept(p, pObj) );
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+    {
+        if ( Abc_ObjIsCo(pFanout) || Abc_ObjIsLatch(pFanout) )
+            continue;
+        pTime = Scl_CellPinTime( Abc_SclObjCell(pFanout), Abc_NodeFindFanin(pFanout, pObj) );
+        Abc_SclDeptFanin( p, pTime, pFanout, pObj );
+    }
+}
+static inline float Abc_SclObjLoadValue( SC_Man * p, Abc_Obj_t * pObj )
+{
+//    float Value = Abc_MaxFloat(pLoad->fall, pLoad->rise) / (p->EstLoadAve * p->EstLoadMax);
+    return (0.5 * Abc_SclObjLoad(p, pObj)->fall + 0.5 * Abc_SclObjLoad(p, pObj)->rise) / (p->EstLoadAve * p->EstLoadMax);
+}
+static inline void Abc_SclTimeCi( SC_Man * p, Abc_Obj_t * pObj )
+{
+    if ( p->pPiDrive != NULL )
+    {
+        SC_Pair * pLoad = Abc_SclObjLoad( p, pObj );
+        SC_Pair * pTime = Abc_SclObjTime( p, pObj );
+        SC_Pair * pSlew = Abc_SclObjSlew( p, pObj );
+        Scl_LibHandleInputDriver( p->pPiDrive, pLoad, pTime, pSlew );
+    }
+}
+void Abc_SclTimeNode( SC_Man * p, Abc_Obj_t * pObj, int fDept )
+{
+    SC_Timing * pTime;
+    SC_Cell * pCell;
+    int k;
+    SC_Pair * pLoad = Abc_SclObjLoad( p, pObj );
+    float LoadRise = pLoad->rise;
+    float LoadFall = pLoad->fall;
+    float DeptRise = 0;
+    float DeptFall = 0;
+    float Value = p->EstLoadMax ? Abc_SclObjLoadValue( p, pObj ) : 0;
+    Abc_Obj_t * pFanin;
+    if ( Abc_ObjIsCi(pObj) )
+    {
+        assert( !fDept );
+        Abc_SclTimeCi( p, pObj );
+        return;
+    }
+    if ( Abc_ObjIsCo(pObj) )
+    {
+        if ( !fDept )
+        {
+            Abc_SclObjDupFanin( p, pObj );
+            Vec_FltWriteEntry( p->vTimesOut, pObj->iData, Abc_SclObjTimeMax(p, pObj) );
+            Vec_QueUpdate( p->vQue, pObj->iData );
+        }
+        return;
+    }
+    assert( Abc_ObjIsNode(pObj) );
+//    if ( !(Abc_ObjFaninNum(pObj) == 1 && Abc_ObjIsPi(Abc_ObjFanin0(pObj))) && p->EstLoadMax && Value > 1 )
+    if ( p->EstLoadMax && Value > 1 )
+    {
+        pLoad->rise = p->EstLoadAve * p->EstLoadMax;
+        pLoad->fall = p->EstLoadAve * p->EstLoadMax;
+        if ( fDept )
+        {
+            SC_Pair * pDepOut  = Abc_SclObjDept( p, pObj );
+            float EstDelta = p->EstLinear * log( Value );
+            DeptRise = pDepOut->rise;
+            DeptFall = pDepOut->fall;
+            pDepOut->rise += EstDelta;
+            pDepOut->fall += EstDelta;
+        }
+        p->nEstNodes++;
+    }
+    // get the library cell
+    pCell = Abc_SclObjCell( pObj );
+    // compute for each fanin
+    Abc_ObjForEachFanin( pObj, pFanin, k )
+    {
+        pTime = Scl_CellPinTime( pCell, k );
+        if ( fDept )
+            Abc_SclDeptFanin( p, pTime, pObj, pFanin );
+        else
+            Abc_SclTimeFanin( p, pTime, pObj, pFanin );
+    }
+    if ( p->EstLoadMax && Value > 1 )
+    {
+        pLoad->rise = LoadRise;
+        pLoad->fall = LoadFall;
+        if ( fDept )
+        {
+            SC_Pair * pDepOut  = Abc_SclObjDept( p, pObj );
+            pDepOut->rise = DeptRise;
+            pDepOut->fall = DeptFall;
+        }
+        else
+        {
+            SC_Pair * pArrOut  = Abc_SclObjTime( p, pObj );
+            float EstDelta = p->EstLinear * log( Value );
+            pArrOut->rise += EstDelta;
+            pArrOut->fall += EstDelta;
+        }
+    }
+}
+void Abc_SclTimeCone( SC_Man * p, Vec_Int_t * vCone )
+{
+    int fVerbose = 0;
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_SclConeClean( p, vCone );
+    Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i )
+    {
+        if ( fVerbose && Abc_ObjIsNode(pObj) )
+        printf( "  Updating node %d with gate %s\n", Abc_ObjId(pObj), Abc_SclObjCell(pObj)->pName );
+        if ( fVerbose && Abc_ObjIsNode(pObj) )
+        printf( "    before (%6.1f ps  %6.1f ps)   ", Abc_SclObjTimeOne(p, pObj, 1), Abc_SclObjTimeOne(p, pObj, 0) );
+        Abc_SclTimeNode( p, pObj, 0 );
+        if ( fVerbose && Abc_ObjIsNode(pObj) )
+        printf( "after (%6.1f ps  %6.1f ps)\n", Abc_SclObjTimeOne(p, pObj, 1), Abc_SclObjTimeOne(p, pObj, 0) );
+    }
+}
+void Abc_SclTimeNtkRecompute( SC_Man * p, float * pArea, float * pDelay, int fReverse, float DUser )
+{
+    Abc_Obj_t * pObj;
+    float D;
+    int i;
+    Abc_SclComputeLoad( p );
+    Abc_SclManCleanTime( p );
+    p->nEstNodes = 0;
+    Abc_NtkForEachCi( p->pNtk, pObj, i )
+        Abc_SclTimeNode( p, pObj, 0 );
+    Abc_NtkForEachNode1( p->pNtk, pObj, i )
+        Abc_SclTimeNode( p, pObj, 0 );
+    Abc_NtkForEachCo( p->pNtk, pObj, i )
+        Abc_SclTimeNode( p, pObj, 0 );
+    D = Abc_SclReadMaxDelay( p );
+    if ( fReverse && DUser > 0 && D < DUser )
+        D = DUser;
+    if ( pArea )
+        *pArea = Abc_SclGetTotalArea(p->pNtk);
+    if ( pDelay )
+        *pDelay = D;
+    if ( fReverse )
+    {
+        p->nEstNodes = 0;
+        Abc_NtkForEachNodeReverse1( p->pNtk, pObj, i )
+            Abc_SclTimeNode( p, pObj, 1 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Incremental timing update.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_SclTimeIncUpdateClean( SC_Man * p )
+{
+    Vec_Int_t * vLevel;
+    Abc_Obj_t * pObj;
+    int i, k;
+    Vec_WecForEachLevel( p->vLevels, vLevel, i )
+    {
+        Abc_NtkForEachObjVec( vLevel, p->pNtk, pObj, k )
+        {
+            assert( pObj->fMarkC == 1 );
+            pObj->fMarkC = 0;
+        }
+        Vec_IntClear( vLevel );
+    }
+}
+static inline void Abc_SclTimeIncAddNode( SC_Man * p, Abc_Obj_t * pObj )
+{
+    assert( !Abc_ObjIsLatch(pObj) );
+    assert( pObj->fMarkC == 0 );
+    pObj->fMarkC = 1;
+    Vec_IntPush( Vec_WecEntry(p->vLevels, Abc_ObjLevel(pObj)), Abc_ObjId(pObj) );
+    p->nIncUpdates++;
+}
+static inline void Abc_SclTimeIncAddFanins( SC_Man * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+//        if ( !pFanin->fMarkC && Abc_ObjIsNode(pFanin) )
+        if ( !pFanin->fMarkC && !Abc_ObjIsLatch(pFanin) )
+            Abc_SclTimeIncAddNode( p, pFanin );
+}
+static inline void Abc_SclTimeIncAddFanouts( SC_Man * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        if ( !pFanout->fMarkC && !Abc_ObjIsLatch(pFanout) )
+            Abc_SclTimeIncAddNode( p, pFanout );
+}
+static inline void Abc_SclTimeIncUpdateArrival( SC_Man * p )
+{
+    Vec_Int_t * vLevel;
+    SC_Pair ArrOut, SlewOut;
+    SC_Pair * pArrOut, *pSlewOut;
+    Abc_Obj_t * pObj;
+    float E = (float)0.1;
+    int i, k;
+    Vec_WecForEachLevel( p->vLevels, vLevel, i )
+    {
+        Abc_NtkForEachObjVec( vLevel, p->pNtk, pObj, k )
+        {
+            if ( Abc_ObjIsCo(pObj) )
+            {
+                Abc_SclObjDupFanin( p, pObj );
+                Vec_FltWriteEntry( p->vTimesOut, pObj->iData, Abc_SclObjTimeMax(p, pObj) );
+                Vec_QueUpdate( p->vQue, pObj->iData );
+                continue;
+            }
+            pArrOut  = Abc_SclObjTime( p, pObj );
+            pSlewOut = Abc_SclObjSlew( p, pObj );
+            SC_PairMove( &ArrOut,  pArrOut  );
+            SC_PairMove( &SlewOut, pSlewOut );
+            Abc_SclTimeNode( p, pObj, 0 );
+//            if ( !SC_PairEqual(&ArrOut, pArrOut) || !SC_PairEqual(&SlewOut, pSlewOut) )
+            if ( !SC_PairEqualE(&ArrOut, pArrOut, E) || !SC_PairEqualE(&SlewOut, pSlewOut, E) )
+                Abc_SclTimeIncAddFanouts( p, pObj );
+        }
+    }
+    p->MaxDelay = Abc_SclReadMaxDelay( p );
+}
+static inline void Abc_SclTimeIncUpdateDeparture( SC_Man * p )
+{
+    Vec_Int_t * vLevel;
+    SC_Pair DepOut, * pDepOut;
+    Abc_Obj_t * pObj;
+    float E = (float)0.1;
+    int i, k;
+    Vec_WecForEachLevelReverse( p->vLevels, vLevel, i )
+    {
+        Abc_NtkForEachObjVec( vLevel, p->pNtk, pObj, k )
+        {
+            pDepOut = Abc_SclObjDept( p, pObj );
+            SC_PairMove( &DepOut, pDepOut );
+            Abc_SclDeptObj( p, pObj );
+//            if ( !SC_PairEqual(&DepOut, pDepOut) )
+            if ( !SC_PairEqualE(&DepOut, pDepOut, E) )
+                Abc_SclTimeIncAddFanins( p, pObj );
+        }
+    } 
+    p->MaxDelay = Abc_SclReadMaxDelay( p );
+}
+void Abc_SclTimeIncCheckLevel( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( (int)pObj->Level != Abc_ObjLevelNew(pObj) )
+            printf( "Level of node %d is out of date!\n", i );
+}
+int Abc_SclTimeIncUpdate( SC_Man * p )
+{
+    Abc_Obj_t * pObj;
+    int i, RetValue;
+    if ( Vec_IntSize(p->vChanged) == 0 )
+        return 0;
+//    Abc_SclTimeIncCheckLevel( p->pNtk );
+    Abc_NtkForEachObjVec( p->vChanged, p->pNtk, pObj, i )
+    {
+        Abc_SclTimeIncAddFanins( p, pObj );
+        if ( pObj->fMarkC )
+            continue;
+        Abc_SclTimeIncAddNode( p, pObj );
+    }
+    Vec_IntClear( p->vChanged );
+    Abc_SclTimeIncUpdateArrival( p );
+    Abc_SclTimeIncUpdateDeparture( p );
+    Abc_SclTimeIncUpdateClean( p );
+    RetValue = p->nIncUpdates;
+    p->nIncUpdates = 0;
+    return RetValue;
+}
+void Abc_SclTimeIncInsert( SC_Man * p, Abc_Obj_t * pObj )
+{
+    Vec_IntPush( p->vChanged, Abc_ObjId(pObj) );
+}
+void Abc_SclTimeIncUpdateLevel_rec( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    int i, LevelNew = Abc_ObjLevelNew(pObj);
+    if ( LevelNew == (int)pObj->Level )
+        return;
+    pObj->Level = LevelNew;
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        Abc_SclTimeIncUpdateLevel_rec( pFanout );
+}
+void Abc_SclTimeIncUpdateLevel( Abc_Obj_t * pObj )
+{
+    Abc_SclTimeIncUpdateLevel_rec( pObj );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Read input slew and output load.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclManReadSlewAndLoad( SC_Man * p, Abc_Ntk_t * pNtk )
+{
+    if ( Abc_FrameReadMaxLoad() )
+    {
+        Abc_Obj_t * pObj;  int i;
+        float MaxLoad = Abc_FrameReadMaxLoad();
+//        printf( "Default output load is specified (%.2f ff).\n", MaxLoad );
+        Abc_NtkForEachPo( pNtk, pObj, i )
+        {
+            SC_Pair * pLoad = Abc_SclObjLoad( p, pObj );
+            pLoad->rise = pLoad->fall = MaxLoad;
+        }
+    }
+    if ( Abc_FrameReadDrivingCell() )
+    {
+        int iCell = Abc_SclCellFind( p->pLib, Abc_FrameReadDrivingCell() );
+        if ( iCell == -1 )
+            printf( "Cannot find the default PI driving cell (%s) in the library.\n", Abc_FrameReadDrivingCell() );
+        else
+        {
+//            printf( "Default PI driving cell is specified (%s).\n", Abc_FrameReadDrivingCell() );
+            p->pPiDrive = SC_LibCell( p->pLib, iCell );
+            assert( p->pPiDrive != NULL );
+            assert( p->pPiDrive->n_inputs == 1 );
+        }
+    }
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Prepare timing manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+SC_Man * Abc_SclManStart( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fUseWireLoads, int fDept, float DUser, int nTreeCRatio )
+{
+    SC_Man * p = Abc_SclManAlloc( pLib, pNtk );
+    if ( nTreeCRatio )
+    {
+        p->EstLoadMax = 0.01 * nTreeCRatio;  // max ratio of Cout/Cave when the estimation is used
+        p->EstLinear  = 100;                  // linear coefficient
+    }
+    Abc_SclMioGates2SclGates( pLib, pNtk );
+    Abc_SclManReadSlewAndLoad( p, pNtk );
+    if ( fUseWireLoads )
+    {
+        if ( pNtk->pWLoadUsed == NULL )
+        {            
+            p->pWLoadUsed = Abc_SclFindWireLoadModel( pLib, Abc_SclGetTotalArea(p->pNtk) );
+            if ( p->pWLoadUsed )
+            pNtk->pWLoadUsed = Abc_UtilStrsav( p->pWLoadUsed->pName );
+        }
+        else
+            p->pWLoadUsed = Abc_SclFetchWireLoadModel( pLib, pNtk->pWLoadUsed );
+    }
+    Abc_SclTimeNtkRecompute( p, &p->SumArea0, &p->MaxDelay0, fDept, DUser );
+    p->SumArea  = p->SumArea0;
+    p->MaxDelay = p->MaxDelay0;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Printing out timing information for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclTimePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nTreeCRatio, int fUseWireLoads, int fShowAll, int fPrintPath, int fDumpStats )
+{
+    SC_Man * p;
+    p = Abc_SclManStart( pLib, pNtk, fUseWireLoads, 1, 0, nTreeCRatio );
+    Abc_SclTimeNtkPrint( p, fShowAll, fPrintPath );
+    if ( fDumpStats )
+        Abc_SclDumpStats( p, "stats.txt", 0 );
+    Abc_SclManFree( p );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Printing out fanin information.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SclCheckCommonInputs( Abc_Obj_t * pObj, Abc_Obj_t * pFanin )
+{
+    Abc_Obj_t * pTemp;
+    int i;
+    Abc_ObjForEachFanin( pObj, pTemp, i )
+        if ( Abc_NodeFindFanin( pFanin, pTemp ) >= 0 )
+        {
+            printf( "Node %d and its fanin %d have common fanin %d.\n", Abc_ObjId(pObj), Abc_ObjId(pFanin), Abc_ObjId(pTemp) );
+
+            printf( "%-16s : ", Mio_GateReadName((Mio_Gate_t *)pObj->pData) ); 
+            Abc_ObjPrint( stdout, pObj );
+
+            printf( "%-16s : ", Mio_GateReadName((Mio_Gate_t *)pFanin->pData) ); 
+            Abc_ObjPrint( stdout, pFanin );
+
+            if ( pTemp->pData )
+            printf( "%-16s : ", Mio_GateReadName((Mio_Gate_t *)pTemp->pData) ); 
+            Abc_ObjPrint( stdout, pTemp );
+            return 1;
+        }
+    return 0;
+}
+void Abc_SclPrintFaninPairs( SC_Man * p, Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k;
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            if ( Abc_ObjIsNode(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+                Abc_SclCheckCommonInputs( pObj, pFanin );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Printing out buffer information.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_ObjIsBuffer( Abc_Obj_t * pObj ) { return Abc_ObjIsNode(pObj) && Abc_ObjFaninNum(pObj) == 1; }
+int Abc_SclHasBufferFanout( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        if ( Abc_ObjIsBuffer(pFanout) )
+            return 1;
+    return 0;
+}
+int Abc_SclCountBufferFanoutsInt( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    int i, Counter = 0;
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        if ( Abc_ObjIsBuffer(pFanout) )
+            Counter += Abc_SclCountBufferFanoutsInt( pFanout );
+    return Counter + Abc_ObjIsBuffer(pObj);
+}
+int Abc_SclCountBufferFanouts( Abc_Obj_t * pObj )
+{
+    return Abc_SclCountBufferFanoutsInt(pObj) - Abc_ObjIsBuffer(pObj);
+}
+int Abc_SclCountNonBufferFanoutsInt( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    int i, Counter = 0;
+    if ( !Abc_ObjIsBuffer(pObj) )
+        return 1;
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        Counter += Abc_SclCountNonBufferFanoutsInt( pFanout );
+    return Counter;
+}
+int Abc_SclCountNonBufferFanouts( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    int i, Counter = 0;
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        Counter += Abc_SclCountNonBufferFanoutsInt( pFanout );
+    return Counter;
+}
+float Abc_SclCountNonBufferDelayInt( SC_Man * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    float Delay = 0;
+    int i; 
+    if ( !Abc_ObjIsBuffer(pObj) )
+        return Abc_SclObjTimeMax(p, pObj);
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        Delay += Abc_SclCountNonBufferDelayInt( p, pFanout );
+    return Delay;
+}
+float Abc_SclCountNonBufferDelay( SC_Man * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    float Delay = 0;
+    int i; 
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        Delay += Abc_SclCountNonBufferDelayInt( p, pFanout );
+    return Delay;
+}
+float Abc_SclCountNonBufferLoadInt( SC_Man * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    float Load = 0;
+    int i; 
+    if ( !Abc_ObjIsBuffer(pObj) )
+        return 0;
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        Load += Abc_SclCountNonBufferLoadInt( p, pFanout );
+    Load += 0.5 * Abc_SclObjLoad(p, pObj)->rise + 0.5 * Abc_SclObjLoad(p, pObj)->fall;
+    Load -= 0.5 * SC_CellPin(Abc_SclObjCell(pObj), 0)->rise_cap + 0.5 * SC_CellPin(Abc_SclObjCell(pObj), 0)->fall_cap;
+    return Load;
+}
+float Abc_SclCountNonBufferLoad( SC_Man * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    float Load = 0;
+    int i; 
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        Load += Abc_SclCountNonBufferLoadInt( p, pFanout );
+    Load += 0.5 * Abc_SclObjLoad(p, pObj)->rise + 0.5 * Abc_SclObjLoad(p, pObj)->fall;
+    return Load;
+}
+void Abc_SclPrintBuffersOne( SC_Man * p, Abc_Obj_t * pObj, int nOffset )
+{
+    int i;
+    for ( i = 0; i < nOffset; i++ )
+        printf( "    " );
+    printf( "%6d: %-16s (%2d:%3d:%3d)  ", 
+        Abc_ObjId(pObj), 
+        Abc_ObjIsPi(pObj) ? "pi" : Mio_GateReadName((Mio_Gate_t *)pObj->pData), 
+        Abc_ObjFanoutNum(pObj), 
+        Abc_SclCountBufferFanouts(pObj), 
+        Abc_SclCountNonBufferFanouts(pObj) );
+    for ( ; i < 4; i++ )
+        printf( "    " );
+    printf( "a =%5.2f  ",      Abc_ObjIsPi(pObj) ? 0 : Abc_SclObjCell(pObj)->area );
+    printf( "d = (" );
+    printf( "%6.0f ps; ",      Abc_SclObjTimeOne(p, pObj, 1) );
+    printf( "%6.0f ps)  ",     Abc_SclObjTimeOne(p, pObj, 0) );
+    printf( "l =%5.0f ff  ",   Abc_SclObjLoadMax(p, pObj) );
+    printf( "s =%5.0f ps   ",  Abc_SclObjSlewMax(p, pObj) );
+    printf( "sl =%5.0f ps   ", Abc_SclObjSlackMax(p, pObj, p->MaxDelay0) );
+    if ( nOffset == 0 )
+    {
+    printf( "L =%5.0f ff   ",  Abc_SclCountNonBufferLoad(p, pObj) );
+    printf( "Lx =%5.0f ff  ",  100.0*Abc_SclCountNonBufferLoad(p, pObj)/p->EstLoadAve );
+    printf( "Dx =%5.0f ps  ",  Abc_SclCountNonBufferDelay(p, pObj)/Abc_SclCountNonBufferFanouts(pObj) - Abc_SclObjTimeOne(p, pObj, 1) );
+    printf( "Cx =%5.0f ps",    (Abc_SclCountNonBufferDelay(p, pObj)/Abc_SclCountNonBufferFanouts(pObj) - Abc_SclObjTimeOne(p, pObj, 1))/log(Abc_SclCountNonBufferLoad(p, pObj)/p->EstLoadAve) );
+    }
+    printf( "\n" );
+}
+void Abc_SclPrintBuffersInt( SC_Man * p, Abc_Obj_t * pObj, int nOffset )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    Abc_SclPrintBuffersOne( p, pObj, nOffset );
+    assert( Abc_ObjIsBuffer(pObj) );
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        if ( Abc_ObjIsBuffer(pFanout) )
+            Abc_SclPrintBuffersInt( p, pFanout, nOffset + 1 );
+}
+void Abc_SclPrintBufferTrees( SC_Man * p, Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj, * pFanout;
+    int i, k;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        if ( !Abc_ObjIsBuffer(pObj) && Abc_SclCountBufferFanouts(pObj) > 3 )
+        {           
+            Abc_SclPrintBuffersOne( p, pObj, 0 );
+            Abc_ObjForEachFanout( pObj, pFanout, k )
+                if ( Abc_ObjIsBuffer(pFanout) )
+                    Abc_SclPrintBuffersInt( p, pFanout, 1 );
+            printf( "\n" );
+        }
+    }
+}
+void Abc_SclPrintBuffers( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fVerbose )
+{
+    int fUseWireLoads = 0;
+    SC_Man * p;
+    assert( Abc_NtkIsMappedLogic(pNtk) );
+    p = Abc_SclManStart( pLib, pNtk, fUseWireLoads, 1, 0, 10000 ); 
+    Abc_SclPrintBufferTrees( p, pNtk ); 
+//    Abc_SclPrintFaninPairs( p, pNtk );
+    Abc_SclManFree( p );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/scl/sclSize.h b/abc-build/src/map/scl/sclSize.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/scl/sclSize.h
@@ -0,0 +1,590 @@
+/**CFile****************************************************************
+
+  FileName    [sclSize.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Standard-cell library representation.]
+
+  Synopsis    [Timing/gate-sizing manager.]
+
+  Author      [Alan Mishchenko, Niklas Een]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 24, 2012.]
+
+  Revision    [$Id: sclSize.h,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__map__scl__sclSize_h
+#define ABC__map__scl__sclSize_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "base/abc/abc.h"
+#include "misc/vec/vecQue.h"
+#include "misc/vec/vecWec.h"
+#include "sclLib.h"
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct SC_Man_          SC_Man;
+struct SC_Man_ 
+{
+    SC_Lib *       pLib;          // library
+    Abc_Ntk_t *    pNtk;          // network
+    int            nObjs;         // allocated size
+    // get assignment
+    Vec_Int_t *    vGatesBest;    // best gate sizes found so far
+    Vec_Int_t *    vUpdates;      // sizing updates in this round
+    Vec_Int_t *    vUpdates2;     // sizing updates in this round
+    // timing information
+    SC_WireLoad *  pWLoadUsed;    // name of the used WireLoad model
+    Vec_Flt_t *    vWireCaps;     // wire capacitances
+    SC_Pair *      pLoads;        // loads for each gate
+    SC_Pair *      pDepts;        // departures for each gate
+    SC_Pair *      pTimes;        // arrivals for each gate
+    SC_Pair *      pSlews;        // slews for each gate
+    Vec_Flt_t *    vInDrive;      // maximum input drive strength
+    Vec_Flt_t *    vTimesOut;     // output arrival times
+    Vec_Que_t *    vQue;          // outputs by their time
+    SC_Cell *      pPiDrive;      // cell driving primary inputs
+    // backup information
+    Vec_Flt_t *    vLoads2;       // backup storage for loads
+    Vec_Flt_t *    vLoads3;       // backup storage for loads
+    Vec_Flt_t *    vTimes2;       // backup storage for times
+    Vec_Flt_t *    vTimes3;       // backup storage for slews
+    // buffer trees
+    float          EstLoadMax;    // max ratio of Cout/Cin when this kicks in
+    float          EstLoadAve;    // average load of the gate
+    float          EstLinear;     // linear coefficient
+    int            nEstNodes;     // the number of estimations
+    // intermediate data
+    Vec_Que_t *    vNodeByGain;   // nodes by gain
+    Vec_Flt_t *    vNode2Gain;    // mapping node into its gain
+    Vec_Int_t *    vNode2Gate;    // mapping node into its best gate
+    Vec_Int_t *    vNodeIter;     // the last iteration the node was upsized
+    Vec_Int_t *    vBestFans;     // best fanouts
+    // incremental timing update
+    Vec_Wec_t *    vLevels;
+    Vec_Int_t *    vChanged; 
+    int            nIncUpdates;
+    // optimization parameters
+    float          SumArea;       // total area
+    float          MaxDelay;      // max delay
+    float          SumArea0;      // total area at the begining 
+    float          MaxDelay0;     // max delay at the begining
+    float          BestDelay;     // best delay in the middle
+    float          ReportDelay;   // delay to report
+    // runtime statistics
+    abctime        timeTotal;     // starting/total time
+    abctime        timeCone;      // critical path selection 
+    abctime        timeSize;      // incremental sizing
+    abctime        timeTime;      // timing update
+    abctime        timeOther;     // everything else
+};
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+static inline SC_Lib  * Abc_SclObjLib( Abc_Obj_t * p )                              { return (SC_Lib *)p->pNtk->pSCLib;    }
+static inline SC_Cell * Abc_SclObjCell( Abc_Obj_t * p )                             { return SC_LibCell( Abc_SclObjLib(p), Vec_IntEntry(p->pNtk->vGates, Abc_ObjId(p)) ); }
+static inline void      Abc_SclObjSetCell( Abc_Obj_t * p, SC_Cell * pCell )         { Vec_IntWriteEntry( p->pNtk->vGates, Abc_ObjId(p), pCell->Id );                      }
+
+static inline SC_Pair * Abc_SclObjLoad( SC_Man * p, Abc_Obj_t * pObj )              { return p->pLoads + Abc_ObjId(pObj);  }
+static inline SC_Pair * Abc_SclObjDept( SC_Man * p, Abc_Obj_t * pObj )              { return p->pDepts + Abc_ObjId(pObj);  }
+static inline SC_Pair * Abc_SclObjTime( SC_Man * p, Abc_Obj_t * pObj )              { return p->pTimes + Abc_ObjId(pObj);  }
+static inline SC_Pair * Abc_SclObjSlew( SC_Man * p, Abc_Obj_t * pObj )              { return p->pSlews + Abc_ObjId(pObj);  }
+
+static inline double    Abc_SclObjLoadMax( SC_Man * p, Abc_Obj_t * pObj )           { return Abc_MaxFloat(Abc_SclObjLoad(p, pObj)->rise, Abc_SclObjLoad(p, pObj)->fall);  }
+static inline float     Abc_SclObjLoadAve( SC_Man * p, Abc_Obj_t * pObj )           { return 0.5 * Abc_SclObjLoad(p, pObj)->rise + 0.5 * Abc_SclObjLoad(p, pObj)->fall;   }
+static inline double    Abc_SclObjTimeOne( SC_Man * p, Abc_Obj_t * pObj, int fRise ){ return fRise ? Abc_SclObjTime(p, pObj)->rise : Abc_SclObjTime(p, pObj)->fall;       }
+static inline float     Abc_SclObjTimeMax( SC_Man * p, Abc_Obj_t * pObj )           { return Abc_MaxFloat(Abc_SclObjTime(p, pObj)->rise, Abc_SclObjTime(p, pObj)->fall);  }
+static inline double    Abc_SclObjSlewMax( SC_Man * p, Abc_Obj_t * pObj )           { return Abc_MaxFloat(Abc_SclObjSlew(p, pObj)->rise, Abc_SclObjSlew(p, pObj)->fall);  }
+static inline float     Abc_SclObjGetSlackR( SC_Man * p, Abc_Obj_t * pObj, float D ){ return D - (Abc_SclObjTime(p, pObj)->rise + Abc_SclObjDept(p, pObj)->rise);         }
+static inline float     Abc_SclObjGetSlackF( SC_Man * p, Abc_Obj_t * pObj, float D ){ return D - (Abc_SclObjTime(p, pObj)->fall + Abc_SclObjDept(p, pObj)->fall);         }
+static inline float     Abc_SclObjGetSlack( SC_Man * p, Abc_Obj_t * pObj, float D ) { return D - Abc_MaxFloat(Abc_SclObjTime(p, pObj)->rise + Abc_SclObjDept(p, pObj)->rise, Abc_SclObjTime(p, pObj)->fall + Abc_SclObjDept(p, pObj)->fall);  }
+static inline double    Abc_SclObjSlackMax( SC_Man * p, Abc_Obj_t * pObj, float D ) { return Abc_SclObjGetSlack(p, pObj, D);                                              }
+static inline void      Abc_SclObjDupFanin( SC_Man * p, Abc_Obj_t * pObj )          { assert( Abc_ObjIsCo(pObj) ); *Abc_SclObjTime(p, pObj) = *Abc_SclObjTime(p, Abc_ObjFanin0(pObj));  }
+static inline float     Abc_SclObjInDrive( SC_Man * p, Abc_Obj_t * pObj )           { return Vec_FltEntry( p->vInDrive, pObj->iData );                                    }
+static inline void      Abc_SclObjSetInDrive( SC_Man * p, Abc_Obj_t * pObj, float c){ Vec_FltWriteEntry( p->vInDrive, pObj->iData, c );                                   }
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Constructor/destructor of STA manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline SC_Man * Abc_SclManAlloc( SC_Lib * pLib, Abc_Ntk_t * pNtk )
+{
+    SC_Man * p;
+    Abc_Obj_t * pObj;
+    int i;
+    assert( pLib->unit_time == 12 );
+    assert( pLib->unit_cap_snd == 15 );
+    assert( Abc_NtkHasMapping(pNtk) );
+    p = ABC_CALLOC( SC_Man, 1 );
+    p->pLib      = pLib;
+    p->pNtk      = pNtk;
+    p->nObjs     = Abc_NtkObjNumMax(pNtk);
+    p->pLoads    = ABC_CALLOC( SC_Pair, p->nObjs );
+    p->pDepts    = ABC_CALLOC( SC_Pair, p->nObjs );
+    p->pTimes    = ABC_CALLOC( SC_Pair, p->nObjs );
+    p->pSlews    = ABC_CALLOC( SC_Pair, p->nObjs );
+    p->vBestFans = Vec_IntStart( p->nObjs );
+    p->vTimesOut = Vec_FltStart( Abc_NtkCoNum(pNtk) );
+    p->vQue      = Vec_QueAlloc( Abc_NtkCoNum(pNtk) );
+    Vec_QueSetPriority( p->vQue, Vec_FltArrayP(p->vTimesOut) );
+    for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ )
+        Vec_QuePush( p->vQue, i );
+    p->vUpdates  = Vec_IntAlloc( 1000 );
+    p->vUpdates2 = Vec_IntAlloc( 1000 );
+    p->vLoads2   = Vec_FltAlloc( 1000 );
+    p->vLoads3   = Vec_FltAlloc( 1000 );
+    p->vTimes2   = Vec_FltAlloc( 1000 );
+    p->vTimes3   = Vec_FltAlloc( 1000 );
+    // intermediate data
+    p->vNode2Gain  = Vec_FltStart( p->nObjs );
+    p->vNode2Gate  = Vec_IntStart( p->nObjs );
+    p->vNodeByGain = Vec_QueAlloc( p->nObjs );
+    Vec_QueSetPriority( p->vNodeByGain, Vec_FltArrayP(p->vNode2Gain) );
+    p->vNodeIter   = Vec_IntStartFull( p->nObjs );
+    p->vLevels     = Vec_WecStart( 2 * Abc_NtkLevel(pNtk) + 1 );
+    p->vChanged    = Vec_IntAlloc( 100 );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        pObj->Level = Abc_ObjFanin0(pObj)->Level + 1;
+    // set CI/CO ids
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        pObj->iData = i;
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        pObj->iData = i;
+    return p;
+}
+static inline void Abc_SclManFree( SC_Man * p )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    // set CI/CO ids
+    Abc_NtkForEachCi( p->pNtk, pObj, i )
+        pObj->iData = 0;
+    Abc_NtkForEachCo( p->pNtk, pObj, i )
+        pObj->iData = 0;
+    // other
+    p->pNtk->pSCLib = NULL;
+    Vec_IntFreeP( &p->pNtk->vGates );
+    Vec_IntFreeP( &p->vNodeIter );
+    Vec_QueFreeP( &p->vNodeByGain );
+    Vec_FltFreeP( &p->vNode2Gain );
+    Vec_IntFreeP( &p->vNode2Gate );
+    // intermediate data
+    Vec_FltFreeP( &p->vLoads2 );
+    Vec_FltFreeP( &p->vLoads3 );
+    Vec_FltFreeP( &p->vTimes2 );
+    Vec_FltFreeP( &p->vTimes3 );
+    Vec_IntFreeP( &p->vUpdates );
+    Vec_IntFreeP( &p->vUpdates2 );
+    Vec_IntFreeP( &p->vGatesBest );
+    Vec_WecFreeP( &p->vLevels );
+    Vec_IntFreeP( &p->vChanged );
+//    Vec_QuePrint( p->vQue );
+    Vec_QueCheck( p->vQue );
+    Vec_QueFreeP( &p->vQue );
+    Vec_FltFreeP( &p->vTimesOut );
+    Vec_IntFreeP( &p->vBestFans );
+    Vec_FltFreeP( &p->vInDrive );
+    Vec_FltFreeP( &p->vWireCaps );
+    ABC_FREE( p->pLoads );
+    ABC_FREE( p->pDepts );
+    ABC_FREE( p->pTimes );
+    ABC_FREE( p->pSlews );
+    ABC_FREE( p );
+}
+/*
+static inline void Abc_SclManCleanTime( SC_Man * p )
+{
+    Vec_Flt_t * vSlews;
+    Abc_Obj_t * pObj;
+    int i;
+    vSlews = Vec_FltAlloc( 2 * Abc_NtkPiNum(p->pNtk) );
+    Abc_NtkForEachPi( p->pNtk, pObj, i )
+    {
+        SC_Pair * pSlew = Abc_SclObjSlew( p, pObj );
+        Vec_FltPush( vSlews, pSlew->rise );
+        Vec_FltPush( vSlews, pSlew->fall );
+    }
+    memset( p->pDepts, 0, sizeof(SC_Pair) * p->nObjs );
+    memset( p->pTimes, 0, sizeof(SC_Pair) * p->nObjs );
+    memset( p->pSlews, 0, sizeof(SC_Pair) * p->nObjs );
+    Abc_NtkForEachPi( p->pNtk, pObj, i )
+    {
+        SC_Pair * pSlew = Abc_SclObjSlew( p, pObj );
+        pSlew->rise = Vec_FltEntry( vSlews, 2 * i + 0 );
+        pSlew->fall = Vec_FltEntry( vSlews, 2 * i + 1 );
+    }
+    Vec_FltFree( vSlews );
+}
+*/
+static inline void Abc_SclManCleanTime( SC_Man * p )
+{
+    memset( p->pTimes, 0, sizeof(SC_Pair) * p->nObjs );
+    memset( p->pSlews, 0, sizeof(SC_Pair) * p->nObjs );
+    memset( p->pDepts, 0, sizeof(SC_Pair) * p->nObjs );
+/*
+    if ( p->pPiDrive != NULL )
+    {
+        SC_Pair * pSlew, * pTime, * pLoad;
+        Abc_Obj_t * pObj;
+        int i;
+        Abc_NtkForEachPi( p->pNtk, pObj, i )
+        {
+            pLoad = Abc_SclObjLoad( p, pObj );
+            pTime = Abc_SclObjTime( p, pObj );
+            pSlew = Abc_SclObjSlew( p, pObj );
+            Scl_LibHandleInputDriver( p->pPiDrive, pLoad, pTime, pSlew );
+        }
+    }
+*/
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Stores/retrivies information for the logic cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_SclLoadStore( SC_Man * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    Vec_FltClear( p->vLoads2 );
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+    {
+        Vec_FltPush( p->vLoads2, Abc_SclObjLoad(p, pFanin)->rise );
+        Vec_FltPush( p->vLoads2, Abc_SclObjLoad(p, pFanin)->fall );
+    }
+}
+static inline void Abc_SclLoadRestore( SC_Man * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin;
+    int i, k = 0;
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+    {
+        Abc_SclObjLoad(p, pFanin)->rise = Vec_FltEntry(p->vLoads2, k++);
+        Abc_SclObjLoad(p, pFanin)->fall = Vec_FltEntry(p->vLoads2, k++);
+    }
+    assert( Vec_FltSize(p->vLoads2) == k );
+}
+
+static inline void Abc_SclLoadStore3( SC_Man * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    Vec_FltClear( p->vLoads3 );
+    Vec_FltPush( p->vLoads3, Abc_SclObjLoad(p, pObj)->rise );
+    Vec_FltPush( p->vLoads3, Abc_SclObjLoad(p, pObj)->fall );
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+    {
+        Vec_FltPush( p->vLoads3, Abc_SclObjLoad(p, pFanin)->rise );
+        Vec_FltPush( p->vLoads3, Abc_SclObjLoad(p, pFanin)->fall );
+    }
+}
+static inline void Abc_SclLoadRestore3( SC_Man * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin;
+    int i, k = 0;
+    Abc_SclObjLoad(p, pObj)->rise = Vec_FltEntry(p->vLoads3, k++);
+    Abc_SclObjLoad(p, pObj)->fall = Vec_FltEntry(p->vLoads3, k++);
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+    {
+        Abc_SclObjLoad(p, pFanin)->rise = Vec_FltEntry(p->vLoads3, k++);
+        Abc_SclObjLoad(p, pFanin)->fall = Vec_FltEntry(p->vLoads3, k++);
+    }
+    assert( Vec_FltSize(p->vLoads3) == k );
+}
+static inline void Abc_SclConeStore( SC_Man * p, Vec_Int_t * vCone )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Vec_FltClear( p->vTimes2 );
+    Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i )
+    {
+        Vec_FltPush( p->vTimes2, Abc_SclObjTime(p, pObj)->rise );
+        Vec_FltPush( p->vTimes2, Abc_SclObjTime(p, pObj)->fall );
+        Vec_FltPush( p->vTimes2, Abc_SclObjSlew(p, pObj)->rise );
+        Vec_FltPush( p->vTimes2, Abc_SclObjSlew(p, pObj)->fall );
+    }
+}
+static inline void Abc_SclConeRestore( SC_Man * p, Vec_Int_t * vCone )
+{
+    Abc_Obj_t * pObj;
+    int i, k = 0;
+    Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i )
+    {
+        Abc_SclObjTime(p, pObj)->rise = Vec_FltEntry(p->vTimes2, k++);
+        Abc_SclObjTime(p, pObj)->fall = Vec_FltEntry(p->vTimes2, k++);
+        Abc_SclObjSlew(p, pObj)->rise = Vec_FltEntry(p->vTimes2, k++);
+        Abc_SclObjSlew(p, pObj)->fall = Vec_FltEntry(p->vTimes2, k++);
+    }
+    assert( Vec_FltSize(p->vTimes2) == k );
+}
+static inline void Abc_SclEvalStore( SC_Man * p, Vec_Int_t * vCone )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Vec_FltClear( p->vTimes3 );
+    Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i )
+    {
+        Vec_FltPush( p->vTimes3, Abc_SclObjTime(p, pObj)->rise );
+        Vec_FltPush( p->vTimes3, Abc_SclObjTime(p, pObj)->fall );
+    }
+}
+static inline float Abc_SclEvalPerform( SC_Man * p, Vec_Int_t * vCone )
+{
+    Abc_Obj_t * pObj;
+    float Diff, Multi = 1.5, Eval = 0;
+    int i, k = 0;
+    Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i )
+    {
+        Diff  = (Vec_FltEntry(p->vTimes3, k++) - Abc_SclObjTime(p, pObj)->rise);
+        Diff += (Vec_FltEntry(p->vTimes3, k++) - Abc_SclObjTime(p, pObj)->fall);
+        Eval += 0.5 * (Diff > 0 ? Diff : Multi * Diff);
+    }
+    assert( Vec_FltSize(p->vTimes3) == k );
+    return Eval / Vec_IntSize(vCone);
+}
+static inline float Abc_SclEvalPerformLegal( SC_Man * p, Vec_Int_t * vCone, float D )
+{
+    Abc_Obj_t * pObj;
+    float Rise, Fall, Multi = 1.0, Eval = 0;
+    int i, k = 0;
+    Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i )
+    {
+        Rise = Vec_FltEntry(p->vTimes3, k++) - Abc_SclObjTime(p, pObj)->rise;
+        Fall = Vec_FltEntry(p->vTimes3, k++) - Abc_SclObjTime(p, pObj)->fall;
+        if ( Rise + Multi * Abc_SclObjGetSlackR(p, pObj, D) < 0 || Fall + Multi * Abc_SclObjGetSlackF(p, pObj, D) < 0 )
+             return -1;
+        Eval += 0.5 * Rise + 0.5 * Fall;
+    }
+    assert( Vec_FltSize(p->vTimes3) == k );
+    return Eval / Vec_IntSize(vCone);
+}
+static inline void Abc_SclConeClean( SC_Man * p, Vec_Int_t * vCone )
+{
+    SC_Pair Zero = { 0.0, 0.0 };
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i )
+    {
+        *Abc_SclObjTime(p, pObj) = Zero;
+        *Abc_SclObjSlew(p, pObj) = Zero;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_SclGetBufInvCount( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i, Count = 0;
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        Count += (Abc_ObjFaninNum(pObj) == 1);
+    return Count;
+}
+static inline float Abc_SclGetAverageSize( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    double Total = 0;
+    int i, Count = 0;
+    Abc_NtkForEachNode1( pNtk, pObj, i )
+        Count++, Total += 100.0*Abc_SclObjCell(pObj)->Order/Abc_SclObjCell(pObj)->nGates;
+    return (float)(Total / Count);
+}
+static inline float Abc_SclGetTotalArea( Abc_Ntk_t * pNtk )
+{
+    double Area = 0;
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachNode1( pNtk, pObj, i )
+        Area += Abc_SclObjCell(pObj)->area;
+    return Area;
+}
+static inline float Abc_SclGetMaxDelay( SC_Man * p )
+{
+    float fMaxArr = 0;
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachCo( p->pNtk, pObj, i )
+        fMaxArr = Abc_MaxFloat( fMaxArr, Abc_SclObjTimeMax(p, pObj) );
+    return fMaxArr;
+}
+static inline float Abc_SclGetMaxDelayNodeFanins( SC_Man * p, Abc_Obj_t * pNode )
+{
+    float fMaxArr = 0;
+    Abc_Obj_t * pObj;
+    int i;
+    assert( Abc_ObjIsNode(pNode) );
+    Abc_ObjForEachFanin( pNode, pObj, i )
+        fMaxArr = Abc_MaxFloat( fMaxArr, Abc_SclObjTimeMax(p, pObj) );
+    return fMaxArr;
+}
+static inline float Abc_SclReadMaxDelay( SC_Man * p )
+{
+    return Abc_SclObjTimeMax( p, Abc_NtkCo(p->pNtk, Vec_QueTop(p->vQue)) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline SC_Cell * Abc_SclObjResiable( SC_Man * p, Abc_Obj_t * pObj, int fUpsize )
+{
+    SC_Cell * pOld = Abc_SclObjCell(pObj);
+    if ( fUpsize )
+        return pOld->pNext->Order > pOld->Order ? pOld->pNext : NULL;
+    else
+        return pOld->pPrev->Order < pOld->Order ? pOld->pPrev : NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dumps timing results into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_SclDumpStats( SC_Man * p, char * pFileName, abctime Time )
+{
+    static char FileNameOld[1000] = {0};
+    static int nNodesOld, nAreaOld, nDelayOld;
+    static abctime clk = 0;
+    FILE * pTable;
+    pTable = fopen( pFileName, "a+" );
+    if ( strcmp( FileNameOld, p->pNtk->pName ) )
+    {
+        sprintf( FileNameOld, "%s", p->pNtk->pName );
+        fprintf( pTable, "\n" );
+        fprintf( pTable, "%s ", Extra_FileNameWithoutPath(p->pNtk->pName) );
+        fprintf( pTable, "%d ", Abc_NtkPiNum(p->pNtk) );
+        fprintf( pTable, "%d ", Abc_NtkPoNum(p->pNtk) );
+        fprintf( pTable, "%d ", (nNodesOld = Abc_NtkNodeNum(p->pNtk)) );
+        fprintf( pTable, "%d ", (nAreaOld  = (int)p->SumArea)         );
+        fprintf( pTable, "%d ", (nDelayOld = (int)p->ReportDelay)     );
+        clk = Abc_Clock();
+    }
+    else
+    {
+        fprintf( pTable, " " );
+        fprintf( pTable, "%.1f ", 100.0 * Abc_NtkNodeNum(p->pNtk) / nNodesOld );
+        fprintf( pTable, "%.1f ", 100.0 * (int)p->SumArea         / nAreaOld  );
+        fprintf( pTable, "%.1f ", 100.0 * (int)p->ReportDelay     / nDelayOld );
+        fprintf( pTable, "%.2f",  1.0*(Abc_Clock() - clk)/CLOCKS_PER_SEC );
+    }
+    fclose( pTable );
+}
+
+/*=== sclBuffer.c ===============================================================*/
+extern Abc_Ntk_t *   Abc_SclBufferingPerform( Abc_Ntk_t * pNtk, SC_Lib * pLib, SC_BusPars * pPars );
+/*=== sclBufferOld.c ===============================================================*/
+extern int           Abc_SclIsInv( Abc_Obj_t * pObj );
+extern void          Abc_NodeInvUpdateFanPolarity( Abc_Obj_t * pObj );
+extern void          Abc_NodeInvUpdateObjFanoutPolarity( Abc_Obj_t * pObj, Abc_Obj_t * pFanout );
+extern void          Abc_SclReportDupFanins( Abc_Ntk_t * pNtk );
+extern Abc_Ntk_t *   Abc_SclUnBufferPerform( Abc_Ntk_t * pNtk, int fVerbose );
+extern Abc_Ntk_t *   Abc_SclUnBufferPhase( Abc_Ntk_t * pNtk, int fVerbose );
+extern Abc_Ntk_t *   Abc_SclBufferPhase( Abc_Ntk_t * pNtk, int fVerbose );
+extern int           Abc_SclCheckNtk( Abc_Ntk_t * p, int fVerbose );
+extern Abc_Ntk_t *   Abc_SclPerformBuffering( Abc_Ntk_t * p, int DegreeR, int Degree, int fUseInvs, int fVerbose );
+extern Abc_Ntk_t *   Abc_SclBufPerform( Abc_Ntk_t * pNtk, int FanMin, int FanMax, int fBufPis, int fSkipDup, int fVerbose );
+/*=== sclDnsize.c ===============================================================*/
+extern void          Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars );
+/*=== sclLoad.c ===============================================================*/
+extern Vec_Flt_t *   Abc_SclFindWireCaps( SC_WireLoad * pWL, int nFanoutMax );
+extern float         Abc_SclFindWireLoad( Vec_Flt_t * vWireCaps, int nFans );
+extern void          Abc_SclAddWireLoad( SC_Man * p, Abc_Obj_t * pObj, int fSubtr );
+extern void          Abc_SclComputeLoad( SC_Man * p );
+extern void          Abc_SclUpdateLoad( SC_Man * p, Abc_Obj_t * pObj, SC_Cell * pOld, SC_Cell * pNew );
+extern void          Abc_SclUpdateLoadSplit( SC_Man * p, Abc_Obj_t * pBuffer, Abc_Obj_t * pFanout );
+/*=== sclSize.c ===============================================================*/
+extern Abc_Obj_t *   Abc_SclFindCriticalCo( SC_Man * p, int * pfRise );
+extern Abc_Obj_t *   Abc_SclFindMostCriticalFanin( SC_Man * p, int * pfRise, Abc_Obj_t * pNode );
+extern void          Abc_SclTimeNtkPrint( SC_Man * p, int fShowAll, int fPrintPath );
+extern SC_Man *      Abc_SclManStart( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fUseWireLoads, int fDept, float DUser, int nTreeCRatio );
+extern void          Abc_SclTimeCone( SC_Man * p, Vec_Int_t * vCone );
+extern void          Abc_SclTimeNtkRecompute( SC_Man * p, float * pArea, float * pDelay, int fReverse, float DUser );
+extern int           Abc_SclTimeIncUpdate( SC_Man * p );
+extern void          Abc_SclTimeIncInsert( SC_Man * p, Abc_Obj_t * pObj );
+extern void          Abc_SclTimeIncUpdateLevel( Abc_Obj_t * pObj );
+extern void          Abc_SclTimePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nTreeCRatio, int fUseWireLoads, int fShowAll, int fPrintPath, int fDumpStats );
+extern void          Abc_SclPrintBuffers( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fVerbose );
+/*=== sclUpsize.c ===============================================================*/
+extern int           Abc_SclCountNearCriticalNodes( SC_Man * p );
+extern void          Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars );
+/*=== sclUtil.c ===============================================================*/
+extern void          Abc_SclMioGates2SclGates( SC_Lib * pLib, Abc_Ntk_t * p );
+extern void          Abc_SclSclGates2MioGates( SC_Lib * pLib, Abc_Ntk_t * p );
+extern void          Abc_SclPrintGateSizes( SC_Lib * pLib, Abc_Ntk_t * p );
+extern void          Abc_SclMinsizePerform( SC_Lib * pLib, Abc_Ntk_t * p, int fUseMax, int fVerbose );
+extern int           Abc_SclCountMinSize( SC_Lib * pLib, Abc_Ntk_t * p, int fUseMax );
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/map/scl/sclTime.h b/abc-build/src/map/scl/sclTime.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/scl/sclTime.h
@@ -0,0 +1,234 @@
+/**CFile****************************************************************
+
+  FileName    [sclTime.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Standard-cell library representation.]
+
+  Synopsis    [Timing/gate-sizing manager.]
+
+  Author      [Alan Mishchenko, Niklas Een]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 24, 2012.]
+
+  Revision    [$Id: sclTime.h,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__map__scl__sclTime_h
+#define ABC__map__scl__sclTime_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "misc/vec/vec.h"
+#include "sclLib.h"
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct SC_Time_           SC_Time;
+struct SC_Time_ 
+{
+    SC_Lib *       pLib;          // library
+    Vec_Int_t *    vCis;          // comb inputs
+    Vec_Int_t *    vCos;          // comb outputs 
+    int            nObjs;         // allocated size
+    // get assignment
+    Vec_Int_t *    vGates;        // mapping of objId into gateId
+    // timing information
+    SC_Pair *      pLoads;        // loads for each gate
+    SC_Pair *      pLoads2;       // loads for each gate
+    SC_Pair *      pDepts;        // departures for each gate
+    SC_Pair *      pTimes;        // arrivals for each gate
+    SC_Pair *      pSlews;        // slews for each gate
+    SC_Pair *      pTimes2;       // arrivals for each gate
+    SC_Pair *      pSlews2;       // slews for each gate
+    float *        pSlack;        // slacks for each gate
+    SC_WireLoad *  pWLoadUsed;    // name of the used WireLoad model
+    // optimization parameters
+    float          SumArea;       // total area
+    float          MaxDelay;      // max delay
+    float          SumArea0;      // total area at the begining 
+    float          MaxDelay0;     // max delay at the begining
+    float          BestDelay;     // best delay in the middle
+};
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+static inline SC_Cell * Scl_ObjCell( SC_Time * p, int i )                     { return SC_LibCell( p->pLib, Vec_IntEntry(p->vGates, i) );   }
+static inline void      Scl_ObjSetCell( SC_Time * p, int i, SC_Cell * pCell ) { Vec_IntWriteEntry( p->vGates, i, pCell->Id );               }
+
+static inline SC_Pair * Scl_ObjLoad( SC_Time * p, int i )                     { return p->pLoads + i;  }
+static inline SC_Pair * Scl_ObjLoad2( SC_Time * p, int i )                    { return p->pLoads2 + i; }
+static inline SC_Pair * Scl_ObjDept( SC_Time * p, int i )                     { return p->pDepts + i;  }
+static inline SC_Pair * Scl_ObjTime( SC_Time * p, int i )                     { return p->pTimes + i;  }
+static inline SC_Pair * Scl_ObjSlew( SC_Time * p, int i )                     { return p->pSlews + i;  }
+static inline SC_Pair * Scl_ObjTime2( SC_Time * p, int i )                    { return p->pTimes2 + i; }
+static inline SC_Pair * Scl_ObjSlew2( SC_Time * p, int i )                    { return p->pSlews2 + i; }
+
+static inline float     Scl_ObjTimeMax( SC_Time * p, int i )                  { return Abc_MaxFloat(Scl_ObjTime(p, i)->rise, Scl_ObjTime(p, i)->fall);  }
+static inline float     Scl_ObjDepthMax( SC_Time * p, int i )                 { return Abc_MaxFloat(Scl_ObjDept(p, i)->rise, Scl_ObjDept(p, i)->fall);  }
+static inline float     Scl_ObjGetSlack( SC_Time * p, int i, float D )        { return D - Abc_MaxFloat(Scl_ObjTime(p, i)->rise + Scl_ObjDept(p, i)->rise, Scl_ObjTime(p, i)->fall + Scl_ObjDept(p, i)->fall);  }
+static inline float     Scl_ObjGetSlackR( SC_Time * p, int i, float D )       { return D - (Scl_ObjTime(p, i)->rise + Scl_ObjDept(p, i)->rise);  }
+static inline float     Scl_ObjGetSlackF( SC_Time * p, int i, float D )       { return D - (Scl_ObjTime(p, i)->fall + Scl_ObjDept(p, i)->fall);  }
+static inline float     Scl_ObjSlack( SC_Time * p, int i )                    { return p->pSlack[i];   }
+
+static inline void      Scl_ObjDupFanin( SC_Time * p, int i, int iFanin )     { *Scl_ObjTime(p, i) = *Scl_ObjTime(p, iFanin);                    }
+static inline float     Scl_ObjGain( SC_Time * p, int i )                     { return 0.5*((Scl_ObjTime2(p, i)->rise - Scl_ObjTime(p, i)->rise) + (Scl_ObjTime2(p, i)->fall - Scl_ObjTime(p, i)->fall)); }
+static inline int       Scl_ObjLegal( SC_Time * p, int i, float D )           { return Scl_ObjTime(p, i)->rise <= Scl_ObjTime2(p, i)->rise + Scl_ObjGetSlackR(p, i, D) && Scl_ObjTime(p, i)->fall <= Scl_ObjTime2(p, i)->fall + Scl_ObjGetSlackF(p, i, D); }
+
+static inline double    Scl_ObjLoadFf( SC_Time * p, int i, int fRise )        { return fRise ? Scl_ObjLoad(p, i)->rise : Scl_ObjLoad(p, i)->fall; }
+static inline double    Scl_ObjTimePs( SC_Time * p, int i, int fRise )        { return fRise ? Scl_ObjTime(p, i)->rise : Scl_ObjTime(p, i)->fall; }
+static inline double    Scl_ObjSlewPs( SC_Time * p, int i, int fRise )        { return fRise ? Scl_ObjSlew(p, i)->rise : Scl_ObjSlew(p, i)->fall; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Constructor/destructor of STA manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline SC_Time * Scl_ManAlloc( SC_Lib * pLib, Vec_Int_t * vCis, Vec_Int_t * vCos, int nObjs )
+{
+    SC_Time * p;
+    p = ABC_CALLOC( SC_Time, 1 );
+    p->pLib      = pLib;
+    p->vCis      = vCis;
+    p->vCos      = vCos;
+    p->nObjs     = nObjs;
+    p->pLoads    = ABC_CALLOC( SC_Pair, p->nObjs );
+    p->pLoads2   = ABC_CALLOC( SC_Pair, p->nObjs );
+    p->pDepts    = ABC_CALLOC( SC_Pair, p->nObjs );
+    p->pTimes    = ABC_CALLOC( SC_Pair, p->nObjs );
+    p->pSlews    = ABC_CALLOC( SC_Pair, p->nObjs );
+    p->pTimes2   = ABC_CALLOC( SC_Pair, p->nObjs );
+    p->pSlews2   = ABC_CALLOC( SC_Pair, p->nObjs );
+    p->pSlack    = ABC_FALLOC( float, p->nObjs );
+    return p;
+}
+static inline void Scl_ManFree( SC_Time * p )
+{
+    Vec_IntFreeP( &p->vGates );
+    ABC_FREE( p->pLoads );
+    ABC_FREE( p->pLoads2 );
+    ABC_FREE( p->pDepts );
+    ABC_FREE( p->pTimes );
+    ABC_FREE( p->pSlews );
+    ABC_FREE( p->pTimes2 );
+    ABC_FREE( p->pSlews2 );
+    ABC_FREE( p->pSlack );
+    ABC_FREE( p );
+}
+static inline void Scl_ManCleanTime( SC_Time * p )
+{
+    memset( p->pDepts, 0, sizeof(SC_Pair) * p->nObjs );
+    memset( p->pTimes, 0, sizeof(SC_Pair) * p->nObjs );
+    memset( p->pSlews, 0, sizeof(SC_Pair) * p->nObjs );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Stores/retrieves timing information for the logic cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Scl_ConeStore( SC_Time * p, Vec_Int_t * vCone )
+{
+    int i, iObj;
+    Vec_IntForEachEntry( vCone, iObj, i )
+    {
+        *Scl_ObjTime2(p, iObj) = *Scl_ObjTime(p, iObj);
+        *Scl_ObjSlew2(p, iObj) = *Scl_ObjSlew(p, iObj);
+    }
+}
+static inline void Scl_ConeRestore( SC_Time * p, Vec_Int_t * vCone )
+{
+    int i, iObj;
+    Vec_IntForEachEntry( vCone, iObj, i )
+    {
+        *Scl_ObjTime(p, iObj) = *Scl_ObjTime2(p, iObj);
+        *Scl_ObjSlew(p, iObj) = *Scl_ObjSlew2(p, iObj);
+    }
+}
+static inline void Scl_ConeClear( SC_Time * p, Vec_Int_t * vCone )
+{
+    SC_Pair Zero = { 0.0, 0.0 };
+    int i, iObj;
+    Vec_IntForEachEntry( vCone, iObj, i )
+    {
+        *Scl_ObjTime(p, iObj) = Zero;
+        *Scl_ObjSlew(p, iObj) = Zero;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Timing computation for pin/gate/cone/network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Scl_PinTimeArrival( SC_Time * p, SC_Timing * pTime, int iObj, int iFanin )
+{
+    SC_Pair * pArrIn   = Scl_ObjTime( p, iFanin );
+    SC_Pair * pSlewIn  = Scl_ObjSlew( p, iFanin );
+    SC_Pair * pLoad    = Scl_ObjLoad( p, iObj );
+    SC_Pair * pArrOut  = Scl_ObjTime( p, iObj );   // modified
+    SC_Pair * pSlewOut = Scl_ObjSlew( p, iObj );   // modified
+    Scl_LibPinArrival( pTime, pArrIn, pSlewIn, pLoad, pArrOut, pSlewOut );
+}
+static inline void Scl_PinTimeDeparture( SC_Time * p, SC_Timing * pTime, int iObj, int iFanin )
+{
+    SC_Pair * pDepIn   = Scl_ObjDept( p, iFanin );   // modified
+    SC_Pair * pSlewIn  = Scl_ObjSlew( p, iFanin );
+    SC_Pair * pLoad    = Scl_ObjLoad( p, iObj );
+    SC_Pair * pDepOut  = Scl_ObjDept( p, iObj );
+    Scl_LibPinDeparture( pTime, pDepIn, pSlewIn, pLoad, pDepOut );
+}
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/map/scl/sclUpsize.c b/abc-build/src/map/scl/sclUpsize.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/scl/sclUpsize.c
@@ -0,0 +1,1022 @@
+/**CFile****************************************************************
+
+  FileName    [sclUpsize.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Standard-cell library representation.]
+
+  Synopsis    [Selective increase of gate sizes.]
+
+  Author      [Alan Mishchenko, Niklas Een]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 24, 2012.]
+
+  Revision    [$Id: sclUpsize.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sclSize.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Collect TFO of nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclFindTFO_rec( Abc_Obj_t * pObj, Vec_Int_t * vNodes, Vec_Int_t * vCos )
+{
+    Abc_Obj_t * pNext;
+    int i;
+    if ( Abc_NodeIsTravIdCurrent( pObj ) )
+        return;
+    Abc_NodeSetTravIdCurrent( pObj );
+    if ( Abc_ObjIsCo(pObj) )
+    {
+        Vec_IntPush( vCos, Abc_ObjId(pObj) );
+        return;
+    }
+    assert( Abc_ObjIsNode(pObj) );
+    Abc_ObjForEachFanout( pObj, pNext, i )
+        Abc_SclFindTFO_rec( pNext, vNodes, vCos );
+    if ( Abc_ObjFaninNum(pObj) > 0 )
+        Vec_IntPush( vNodes, Abc_ObjId(pObj) );
+}
+Vec_Int_t * Abc_SclFindTFO( Abc_Ntk_t * p, Vec_Int_t * vPath )
+{
+    Vec_Int_t * vNodes, * vCos;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k;
+    assert( Vec_IntSize(vPath) > 0 );
+    vCos = Vec_IntAlloc( 100 );
+    vNodes = Vec_IntAlloc( 100 );
+    // collect nodes in the TFO
+    Abc_NtkIncrementTravId( p ); 
+    Abc_NtkForEachObjVec( vPath, p, pObj, i )
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            if ( Abc_ObjIsNode(pFanin) )
+                Abc_SclFindTFO_rec( pFanin, vNodes, vCos );
+    // reverse order
+    Vec_IntReverseOrder( vNodes );
+//    Vec_IntSort( vNodes, 0 );
+//Vec_IntPrint( vNodes );
+//Vec_IntPrint( vCos );
+    Vec_IntAppend( vNodes, vCos );
+    Vec_IntFree( vCos );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect near-critical COs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_SclFindCriticalCoWindow( SC_Man * p, int Window )
+{
+    float fMaxArr = Abc_SclReadMaxDelay( p ) * (100.0 - Window) / 100.0;
+    Vec_Int_t * vPivots;
+    Abc_Obj_t * pObj;
+    int i;
+    vPivots = Vec_IntAlloc( 100 );
+    Abc_NtkForEachCo( p->pNtk, pObj, i )
+        if ( Abc_SclObjTimeMax(p, pObj) >= fMaxArr )
+            Vec_IntPush( vPivots, Abc_ObjId(pObj) );
+    assert( Vec_IntSize(vPivots) > 0 );
+    return vPivots;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect near-critical internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclFindCriticalNodeWindow_rec( SC_Man * p, Abc_Obj_t * pObj, Vec_Int_t * vPath, float fSlack, int fDept )
+{
+    Abc_Obj_t * pNext;
+    float fArrMax, fSlackFan;
+    int i;
+    if ( Abc_ObjIsCi(pObj) )
+        return;
+    if ( Abc_NodeIsTravIdCurrent( pObj ) )
+        return;
+    Abc_NodeSetTravIdCurrent( pObj );
+    assert( Abc_ObjIsNode(pObj) );
+    // compute the max arrival time of the fanins
+    if ( fDept )
+//        fArrMax = p->pSlack[Abc_ObjId(pObj)];
+        fArrMax = Abc_SclObjGetSlack(p, pObj, p->MaxDelay);
+    else
+        fArrMax = Abc_SclGetMaxDelayNodeFanins( p, pObj );
+//    assert( fArrMax >= -1 );
+    fArrMax = Abc_MaxFloat( fArrMax, 0 );
+    // traverse all fanins whose arrival times are within a window
+    Abc_ObjForEachFanin( pObj, pNext, i )
+    {
+        if ( Abc_ObjIsCi(pNext) || Abc_ObjFaninNum(pNext) == 0 )
+            continue;
+        assert( Abc_ObjIsNode(pNext) );
+        if ( fDept )
+//            fSlackFan = fSlack - (p->pSlack[Abc_ObjId(pNext)] - fArrMax);
+            fSlackFan = fSlack - (Abc_SclObjGetSlack(p, pNext, p->MaxDelay) - fArrMax);
+        else
+            fSlackFan = fSlack - (fArrMax - Abc_SclObjTimeMax(p, pNext));
+        if ( fSlackFan >= 0 )
+            Abc_SclFindCriticalNodeWindow_rec( p, pNext, vPath, fSlackFan, fDept );
+    }
+    if ( Abc_ObjFaninNum(pObj) > 0 )
+        Vec_IntPush( vPath, Abc_ObjId(pObj) );
+}
+Vec_Int_t * Abc_SclFindCriticalNodeWindow( SC_Man * p, Vec_Int_t * vPathCos, int Window, int fDept )
+{
+    float fMaxArr = Abc_SclReadMaxDelay( p );
+    float fSlackMax = fMaxArr * Window / 100.0;
+    Vec_Int_t * vPath = Vec_IntAlloc( 100 );
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkIncrementTravId( p->pNtk ); 
+    Abc_NtkForEachObjVec( vPathCos, p->pNtk, pObj, i )
+    {
+        float fSlackThis = fSlackMax - (fMaxArr - Abc_SclObjTimeMax(p, pObj));
+        if ( fSlackThis >= 0 )
+            Abc_SclFindCriticalNodeWindow_rec( p, Abc_ObjFanin0(pObj), vPath, fSlackThis, fDept );
+    }
+    // label critical nodes
+    Abc_NtkForEachObjVec( vPathCos, p->pNtk, pObj, i )
+        pObj->fMarkA = 1;
+    Abc_NtkForEachObjVec( vPath, p->pNtk, pObj, i )
+        pObj->fMarkA = 1;
+    return vPath;  
+}
+void Abc_SclUnmarkCriticalNodeWindow( SC_Man * p, Vec_Int_t * vPath )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObjVec( vPath, p->pNtk, pObj, i )
+        pObj->fMarkA = 0;
+}
+int Abc_SclCountNearCriticalNodes( SC_Man * p )
+{
+    int RetValue;
+    Vec_Int_t * vPathPos, * vPathNodes;
+    vPathPos   = Abc_SclFindCriticalCoWindow( p, 5 );
+    vPathNodes = Abc_SclFindCriticalNodeWindow( p, vPathPos, 5, 0 );
+    RetValue   = Vec_IntSize(vPathNodes);
+    Abc_SclUnmarkCriticalNodeWindow( p, vPathNodes );
+    Abc_SclUnmarkCriticalNodeWindow( p, vPathPos );
+    Vec_IntFree( vPathPos );
+    Vec_IntFree( vPathNodes );
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Find the array of nodes to be updated.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclFindNodesToUpdate( Abc_Obj_t * pPivot, Vec_Int_t ** pvNodes, Vec_Int_t ** pvEvals, Abc_Obj_t * pExtra )
+{
+    Abc_Ntk_t * p = Abc_ObjNtk(pPivot);
+    Abc_Obj_t * pObj, * pNext, * pNext2;
+    Vec_Int_t * vNodes = *pvNodes;
+    Vec_Int_t * vEvals = *pvEvals;
+    int i, k;
+    assert( Abc_ObjIsNode(pPivot) );
+    assert( pPivot->fMarkA );
+    // collect fanins, node, and fanouts
+    Vec_IntClear( vNodes );
+    Abc_ObjForEachFanin( pPivot, pNext, i )
+//        if ( Abc_ObjIsNode(pNext) && Abc_ObjFaninNum(pNext) > 0 )
+        if ( Abc_ObjIsCi(pNext) || Abc_ObjFaninNum(pNext) > 0 )
+            Vec_IntPush( vNodes, Abc_ObjId(pNext) );
+    Vec_IntPush( vNodes, Abc_ObjId(pPivot) );
+    if ( pExtra )
+        Vec_IntPush( vNodes, Abc_ObjId(pExtra) );
+    Abc_ObjForEachFanout( pPivot, pNext, i )
+        if ( Abc_ObjIsNode(pNext) && pNext->fMarkA )
+        {
+            Vec_IntPush( vNodes, Abc_ObjId(pNext) );
+            Abc_ObjForEachFanout( pNext, pNext2, k )
+                if ( Abc_ObjIsNode(pNext2) && pNext2->fMarkA )
+                    Vec_IntPush( vNodes, Abc_ObjId(pNext2) );
+        }
+    Vec_IntUniqify( vNodes );
+    // label nodes
+    Abc_NtkForEachObjVec( vNodes, p, pObj, i )
+    {
+        assert( pObj->fMarkB == 0 );
+        pObj->fMarkB = 1;
+    }
+    // collect nodes visible from the critical paths
+    Vec_IntClear( vEvals );
+    Abc_NtkForEachObjVec( vNodes, p, pObj, i )
+        Abc_ObjForEachFanout( pObj, pNext, k )
+            if ( pNext->fMarkA && !pNext->fMarkB )
+//            if ( !pNext->fMarkB )
+            {
+                assert( pObj->fMarkB );
+                Vec_IntPush( vEvals, Abc_ObjId(pObj) );
+                break;
+            }
+    assert( Vec_IntSize(vEvals) > 0 );
+    // label nodes
+    Abc_NtkForEachObjVec( vNodes, p, pObj, i )
+        pObj->fMarkB = 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SclFindBestCell( SC_Man * p, Abc_Obj_t * pObj, Vec_Int_t * vRecalcs, Vec_Int_t * vEvals, int Notches, int DelayGap, float * pGainBest )
+{
+    SC_Cell * pCellOld, * pCellNew;
+    float dGain, dGainBest;
+    int k, gateBest, NoChange = 0;
+    // save old gate, timing, fanin load
+    pCellOld = Abc_SclObjCell( pObj );
+    Abc_SclConeStore( p, vRecalcs );
+    Abc_SclEvalStore( p, vEvals );
+    Abc_SclLoadStore( p, pObj );
+    // try different gate sizes for this node
+    gateBest = -1;
+    dGainBest = -DelayGap;
+    SC_RingForEachCell( pCellOld, pCellNew, k )
+    {
+        if ( pCellNew == pCellOld )
+            continue;
+        if ( k > Notches )
+            break;
+        // set new cell
+        Abc_SclObjSetCell( pObj, pCellNew );
+        Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew );
+        // recompute timing
+        Abc_SclTimeCone( p, vRecalcs );
+        // set old cell
+        Abc_SclObjSetCell( pObj, pCellOld );
+        Abc_SclLoadRestore( p, pObj );
+        // save best gain
+        dGain = Abc_SclEvalPerform( p, vEvals );
+        if ( dGainBest < dGain )
+        {
+            dGainBest = dGain;
+            gateBest = pCellNew->Id;
+            NoChange = 1;
+        }
+        else if ( NoChange )
+            NoChange++;
+        if ( NoChange == 4 )
+            break;
+//        printf( "%.2f ", dGain );
+    }
+//    printf( "Best = %.2f   ", dGainBest );
+//    printf( "\n" );
+    // put back old cell and timing
+    Abc_SclObjSetCell( pObj, pCellOld );
+    Abc_SclConeRestore( p, vRecalcs );
+    *pGainBest = dGainBest;
+    return gateBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the set of gates to upsize.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SclFindBypasses( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notches, int iIter, int DelayGap, int fVeryVerbose )
+{
+    SC_Cell * pCellOld, * pCellNew;
+    Vec_Ptr_t * vFanouts;
+    Vec_Int_t * vRecalcs, * vEvals;
+    Abc_Obj_t * pBuf, * pFanin, * pFanout, * pExtra;
+    int i, j, iNode, gateBest, gateBest2, fanBest, Counter = 0;
+    float dGainBest, dGainBest2;
+
+    // compute savings due to bypassing buffers
+    vFanouts = Vec_PtrAlloc( 100 );
+    vRecalcs = Vec_IntAlloc( 100 );
+    vEvals = Vec_IntAlloc( 100 );
+    Vec_QueClear( p->vNodeByGain );
+    Abc_NtkForEachObjVec( vPathNodes, p->pNtk, pBuf, i )
+    {
+        assert( pBuf->fMarkB == 0 );
+        if ( Abc_ObjFaninNum(pBuf) != 1 )
+            continue;
+        pFanin = Abc_ObjFanin0(pBuf);
+        if ( !Abc_ObjIsNode(pFanin) )
+            continue;
+        pExtra = NULL;
+        if ( p->pNtk->vPhases == NULL )
+        {
+            if ( Abc_SclIsInv(pBuf) )
+            {
+                if ( !Abc_SclIsInv(pFanin) )
+                    continue;
+                pFanin = Abc_ObjFanin0(pFanin);
+                if ( !Abc_ObjIsNode(pFanin) )
+                    continue;
+                pExtra = pBuf;
+                // we make pBuf and pFanin are in the same phase and pFanin is a node
+            }
+        }
+        // here we have pBuf and its fanin pFanin, which is a logic node
+        // compute nodes to recalculate timing and nodes to evaluate afterwards
+        Abc_SclFindNodesToUpdate( pFanin, &vRecalcs, &vEvals, pExtra );
+        assert( Vec_IntSize(vEvals) > 0 );
+        // consider fanouts of this node
+        fanBest    = -1;
+        gateBest2  = -1;
+        dGainBest2 =  0;
+        Abc_NodeCollectFanouts( pBuf, vFanouts );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, j )
+        {
+            // skip COs
+            if ( Abc_ObjIsCo(pFanout) )
+                continue;
+            // skip non-critical fanouts
+            if ( !pFanout->fMarkA )
+                continue;
+            // skip if fanin already has fanout as a fanout
+            if ( Abc_NodeFindFanin(pFanout, pFanin) >= 0 )
+                continue;
+            // skip if fanin already has fanout as a fanout
+            if ( pExtra && Abc_NodeFindFanin(pFanout, pExtra) >= 0 )
+                continue;
+            // prepare
+            Abc_SclLoadStore3( p, pBuf );
+            Abc_SclUpdateLoadSplit( p, pBuf, pFanout );
+            Abc_ObjPatchFanin( pFanout, pBuf, pFanin );
+            // size the fanin
+            gateBest = Abc_SclFindBestCell( p, pFanin, vRecalcs, vEvals, Notches, DelayGap, &dGainBest );
+            // unprepare
+            Abc_SclLoadRestore3( p, pBuf );
+            Abc_ObjPatchFanin( pFanout, pFanin, pBuf );
+            if ( gateBest == -1 )
+                continue;
+            // compare gain
+            if ( dGainBest2 < dGainBest )
+            {
+                dGainBest2 = dGainBest;
+                gateBest2 = gateBest;
+                fanBest = Abc_ObjId(pFanout);
+            }
+        }
+        // remember savings
+        if ( gateBest2 >= 0 )
+        {
+            assert( dGainBest2 > 0.0 );
+            Vec_FltWriteEntry( p->vNode2Gain, Abc_ObjId(pBuf), dGainBest2 );
+            Vec_IntWriteEntry( p->vNode2Gate, Abc_ObjId(pBuf), gateBest2 );
+            Vec_QuePush( p->vNodeByGain, Abc_ObjId(pBuf) );
+            Vec_IntWriteEntry( p->vBestFans, Abc_ObjId(pBuf), fanBest );
+        }
+//        if ( ++Counter == 17 )
+//            break;
+    }
+    Vec_PtrFree( vFanouts );
+    Vec_IntFree( vRecalcs );
+    Vec_IntFree( vEvals );
+    if ( Vec_QueSize(p->vNodeByGain) == 0 )
+        return 0;
+    if ( fVeryVerbose ) 
+        printf( "\n" );
+
+    // accept changes for that are half above the average and do not overlap
+    Counter = 0;
+    dGainBest2 = -1;
+    vFanouts = Vec_PtrAlloc( 100 );
+    while ( Vec_QueSize(p->vNodeByGain) )
+    {
+        iNode   = Vec_QuePop(p->vNodeByGain);
+        pFanout = Abc_NtkObj( p->pNtk, Vec_IntEntry(p->vBestFans, iNode) );
+        pBuf    = Abc_NtkObj( p->pNtk, iNode );
+        pFanin  = Abc_ObjFanin0(pBuf);
+        if ( pFanout->fMarkB || pBuf->fMarkB )
+            continue;
+        if ( p->pNtk->vPhases == NULL )
+        {
+            // update fanin
+            if ( Abc_SclIsInv(pBuf) )
+            {
+                if ( !Abc_SclIsInv(pFanin) )
+                {
+                    assert( 0 );
+                    continue;
+                }
+                pFanin = Abc_ObjFanin0(pFanin);
+                if ( !Abc_ObjIsNode(pFanin) )
+                {
+                    assert( 0 );
+                    continue;
+                }
+            }
+        }
+        if ( pFanin->fMarkB )
+            continue;
+        pFanout->fMarkB = 1;
+        pBuf->fMarkB = 1;
+        pFanin->fMarkB = 1;
+        Vec_PtrPush( vFanouts, pFanout );
+        Vec_PtrPush( vFanouts, pBuf );
+        Vec_PtrPush( vFanouts, pFanin );
+        // remember gain
+        if ( dGainBest2 == -1 )
+            dGainBest2 = Vec_FltEntry(p->vNode2Gain, iNode);
+//        else if ( dGainBest2 > 2*Vec_FltEntry(p->vNode2Gain, iNode) )
+//            break;
+        // redirect
+        Abc_SclUpdateLoadSplit( p, pBuf, pFanout );
+        Abc_SclAddWireLoad( p, pBuf, 1 );
+        Abc_SclAddWireLoad( p, pFanin, 1 );
+        Abc_ObjPatchFanin( pFanout, pBuf, pFanin );
+        Abc_SclAddWireLoad( p, pBuf, 0 );
+        Abc_SclAddWireLoad( p, pFanin, 0 );
+        Abc_SclTimeIncUpdateLevel( pFanout );
+        // remember
+        Vec_IntPush( p->vUpdates2, Abc_ObjId(pFanout) );
+        Vec_IntPush( p->vUpdates2, Abc_ObjId(pFanin) );
+        Vec_IntPush( p->vUpdates2, Abc_ObjId(pBuf) );
+        // update cell
+        pCellOld = Abc_SclObjCell( pFanin );
+        pCellNew = SC_LibCell( p->pLib, Vec_IntEntry(p->vNode2Gate, iNode) );
+        p->SumArea += pCellNew->area - pCellOld->area;
+        Abc_SclObjSetCell( pFanin, pCellNew );
+        Abc_SclUpdateLoad( p, pFanin, pCellOld, pCellNew );
+        // record the update
+        Vec_IntPush( p->vUpdates, Abc_ObjId(pFanin) );
+        Vec_IntPush( p->vUpdates, pCellNew->Id );
+        Abc_SclTimeIncInsert( p, pFanout );
+        Abc_SclTimeIncInsert( p, pBuf );
+        Abc_SclTimeIncInsert( p, pFanin );
+        // remember when this node was upsized
+        Vec_IntWriteEntry( p->vNodeIter, Abc_ObjId(pFanout), -1 );
+        Vec_IntWriteEntry( p->vNodeIter, Abc_ObjId(pBuf), -1 );
+        Vec_IntWriteEntry( p->vNodeIter, Abc_ObjId(pFanin), -1 );
+        // update polarity
+        if ( p->pNtk->vPhases && Abc_SclIsInv(pBuf) )
+            Abc_NodeInvUpdateObjFanoutPolarity( pFanin, pFanout );
+        // report
+        if ( fVeryVerbose )
+        {
+            printf( "Node %6d  Redir fanout %6d to fanin %6d.  Gain = %7.1f ps. ", 
+                Abc_ObjId(pBuf), Abc_ObjId(pFanout), Abc_ObjId(pFanin), Vec_FltEntry(p->vNode2Gain, iNode) );
+            printf( "Gate %12s (%2d/%2d)  -> %12s (%2d/%2d) \n", 
+                pCellOld->pName, pCellOld->Order, pCellOld->nGates, 
+                pCellNew->pName, pCellNew->Order, pCellNew->nGates );
+        }
+/*
+        // check if the node became useless
+        if ( Abc_ObjFanoutNum(pBuf) == 0 )
+        {
+            pCellOld = Abc_SclObjCell( pBuf );
+            p->SumArea -= pCellOld->area;
+            Abc_NtkDeleteObj_rec( pBuf, 1 );
+            printf( "Removed node %d.\n", iNode );
+        }
+*/
+        Counter++;
+    }
+    Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, j )
+        pFanout->fMarkB = 0;
+    Vec_PtrFree( vFanouts );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check marked fanin/fanouts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+int Abc_SclObjCheckMarkedFanFans( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pNext;
+    int i;
+    if ( pObj->fMarkB )
+        return 1;
+    Abc_ObjForEachFanin( pObj, pNext, i )
+        if ( pNext->fMarkB )
+            return 1;
+    Abc_ObjForEachFanout( pObj, pNext, i )
+        if ( pNext->fMarkB )
+            return 1;
+    return 0;
+}
+void Abc_SclObjMarkFanFans( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+//    Abc_Obj_t * pNext;
+//    int i;
+    if ( pObj->fMarkB == 0 )
+    {
+        Vec_PtrPush( vNodes, pObj );
+        pObj->fMarkB = 1;
+    }
+/*
+    Abc_ObjForEachFanin( pObj, pNext, i )
+        if ( pNext->fMarkB == 0 )
+        {
+            Vec_PtrPush( vNodes, pNext );
+            pNext->fMarkB = 1;
+        }
+    Abc_ObjForEachFanout( pObj, pNext, i )
+        if ( pNext->fMarkB == 0 )
+        {
+            Vec_PtrPush( vNodes, pNext );
+            pNext->fMarkB = 1;
+        }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the set of gates to upsize.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SclFindUpsizes( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notches, int iIter, int DelayGap, int fMoreConserf )
+{
+    SC_Cell * pCellOld, * pCellNew;
+    Vec_Int_t * vRecalcs, * vEvals;
+    Vec_Ptr_t * vFanouts;
+    Abc_Obj_t * pObj;
+    float dGainBest, dGainBest2;
+    int i, gateBest, Limit, Counter, iIterLast;
+
+    // compute savings due to upsizing each node
+    vRecalcs = Vec_IntAlloc( 100 );
+    vEvals = Vec_IntAlloc( 100 );
+    Vec_QueClear( p->vNodeByGain );
+    Abc_NtkForEachObjVec( vPathNodes, p->pNtk, pObj, i )
+    {
+        assert( pObj->fMarkB == 0 );
+        iIterLast = Vec_IntEntry(p->vNodeIter, Abc_ObjId(pObj));
+        if ( iIterLast >= 0 && iIterLast + 5 > iIter )
+            continue;
+        // compute nodes to recalculate timing and nodes to evaluate afterwards
+        Abc_SclFindNodesToUpdate( pObj, &vRecalcs, &vEvals, NULL );
+        assert( Vec_IntSize(vEvals) > 0 );
+        //printf( "%d -> %d\n", Vec_IntSize(vRecalcs), Vec_IntSize(vEvals) );
+        gateBest = Abc_SclFindBestCell( p, pObj, vRecalcs, vEvals, Notches, DelayGap, &dGainBest );
+        // remember savings
+        if ( gateBest >= 0 )
+        {
+            assert( dGainBest > 0.0 );
+            Vec_FltWriteEntry( p->vNode2Gain, Abc_ObjId(pObj), dGainBest );
+            Vec_IntWriteEntry( p->vNode2Gate, Abc_ObjId(pObj), gateBest );
+            Vec_QuePush( p->vNodeByGain, Abc_ObjId(pObj) );
+        }
+    }
+    Vec_IntFree( vRecalcs );
+    Vec_IntFree( vEvals );
+    if ( Vec_QueSize(p->vNodeByGain) == 0 )
+        return 0;
+/*
+    Limit = Abc_MinInt( Vec_QueSize(p->vNodeByGain), Abc_MaxInt((int)(0.01 * Ratio * Vec_IntSize(vPathNodes)), 1) ); 
+    //printf( "\nSelecting %d out of %d\n", Limit, Vec_QueSize(p->vNodeByGain) );
+    for ( i = 0; i < Limit; i++ )
+    {
+        // get the object
+        pObj = Abc_NtkObj( p->pNtk, Vec_QuePop(p->vNodeByGain) );
+        assert( pObj->fMarkA );
+        // find old and new gates
+        pCellOld = Abc_SclObjCell( pObj );
+        pCellNew = SC_LibCell( p->pLib, Vec_IntEntry(p->vNode2Gate, Abc_ObjId(pObj)) );
+        assert( pCellNew != NULL );
+        //printf( "%6d  %20s -> %20s  ", Abc_ObjId(pObj), pCellOld->pName, pCellNew->pName );
+        //printf( "gain is %f\n", Vec_FltEntry(p->vNode2Gain, Abc_ObjId(pObj)) );
+        // update gate
+        Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew );
+        p->SumArea += pCellNew->area - pCellOld->area;
+        Abc_SclObjSetCell( pObj, pCellNew );
+        // record the update
+        Vec_IntPush( p->vUpdates, Abc_ObjId(pObj) );
+        Vec_IntPush( p->vUpdates, pCellNew->Id );
+        Abc_SclTimeIncInsert( p, pObj );
+        // remember when this node was upsized
+        Vec_IntWriteEntry( p->vNodeIter, Abc_ObjId(pObj), iIter );
+    }
+return Limit;
+*/
+
+    Limit = Abc_MinInt( Vec_QueSize(p->vNodeByGain), Abc_MaxInt((int)(0.01 * Ratio * Vec_IntSize(vPathNodes)), 1) ); 
+    dGainBest2 = -1;
+    Counter = 0;
+    vFanouts = Vec_PtrAlloc( 100 );
+    while ( Vec_QueSize(p->vNodeByGain) )
+    {
+        int iNode = Vec_QuePop(p->vNodeByGain);
+        Abc_Obj_t * pObj = Abc_NtkObj( p->pNtk, iNode );
+        assert( pObj->fMarkA );
+        if ( Abc_SclObjCheckMarkedFanFans( pObj ) )
+            continue;
+        Abc_SclObjMarkFanFans( pObj, vFanouts );
+        // remember gain
+        if ( dGainBest2 == -1 )
+            dGainBest2 = Vec_FltEntry(p->vNode2Gain, iNode);
+//        else if ( dGainBest2 > 3*Vec_FltEntry(p->vNode2Gain, iNode) )
+//            break;
+//        printf( "%.1f ", Vec_FltEntry(p->vNode2Gain, iNode) );
+
+        // find old and new gates
+        pCellOld = Abc_SclObjCell( pObj );
+        pCellNew = SC_LibCell( p->pLib, Vec_IntEntry(p->vNode2Gate, Abc_ObjId(pObj)) );
+        assert( pCellNew != NULL );
+        //printf( "%6d  %20s -> %20s  ", Abc_ObjId(pObj), pCellOld->pName, pCellNew->pName );
+        //printf( "gain is %f\n", Vec_FltEntry(p->vNode2Gain, Abc_ObjId(pObj)) );
+//        if ( pCellOld->Order > 0 )
+//            printf( "%.2f  %d -> %d(%d)   ", Vec_FltEntry(p->vNode2Gain, iNode), pCellOld->Order, pCellNew->Order, pCellNew->nGates );
+        // update gate
+        p->SumArea += pCellNew->area - pCellOld->area;
+        Abc_SclObjSetCell( pObj, pCellNew );
+        Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew );
+        // record the update
+        Vec_IntPush( p->vUpdates, Abc_ObjId(pObj) );
+        Vec_IntPush( p->vUpdates, pCellNew->Id );
+        Abc_SclTimeIncInsert( p, pObj );
+        // remember when this node was upsized
+        Vec_IntWriteEntry( p->vNodeIter, Abc_ObjId(pObj), iIter );
+        Counter++;
+        if ( Counter == Limit )
+            break;
+    }
+//    printf( "\n" );
+
+    Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pObj, i )
+        pObj->fMarkB = 0;
+    Vec_PtrFree( vFanouts );
+    return Counter;
+}
+void Abc_SclApplyUpdateToBest( Vec_Int_t * vGatesBest, Vec_Int_t * vGates, Vec_Int_t * vUpdate )
+{
+    int i, ObjId, GateId, GateId2; 
+    Vec_IntForEachEntryDouble( vUpdate, ObjId, GateId, i )
+        Vec_IntWriteEntry( vGatesBest, ObjId, GateId );
+    Vec_IntClear( vUpdate );
+    Vec_IntForEachEntryTwo( vGatesBest, vGates, GateId, GateId2, i )
+        assert( GateId == GateId2 );
+//    Vec_IntClear( vGatesBest );
+//    Vec_IntAppend( vGatesBest, vGates );
+}
+void Abc_SclUndoRecentChanges( Abc_Ntk_t * pNtk, Vec_Int_t * vTrans )
+{
+    int i;
+    assert( Vec_IntSize(vTrans) % 3 == 0 );
+    for ( i = Vec_IntSize(vTrans)/3 - 1; i >= 0; i-- )
+    {
+        Abc_Obj_t * pFanout = Abc_NtkObj( pNtk, Vec_IntEntry(vTrans, 3*i+0) );
+        Abc_Obj_t * pFanin  = Abc_NtkObj( pNtk, Vec_IntEntry(vTrans, 3*i+1) );
+        Abc_Obj_t * pObj    = Abc_NtkObj( pNtk, Vec_IntEntry(vTrans, 3*i+2) );
+        // we do not update load here because times will be recomputed
+        Abc_ObjPatchFanin( pFanout, pFanin, pObj );
+        Abc_SclTimeIncUpdateLevel( pFanout );
+//        printf( "Node %6d  Redir fanout %6d from fanin %6d. \n", 
+//            Abc_ObjId(pObj), Abc_ObjId(pFanout), Abc_ObjId(pFanin) );
+        // update polarity
+        if ( pNtk->vPhases && Abc_SclIsInv(pObj) )
+            Abc_NodeInvUpdateObjFanoutPolarity( pObj, pFanout );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclUpsizePrintDiffs( SC_Man * p, SC_Lib * pLib, Abc_Ntk_t * pNtk )
+{
+    float fDiff = (float)0.001;
+    int k;
+    Abc_Obj_t * pObj;
+
+    SC_Pair * pTimes = ABC_ALLOC( SC_Pair, p->nObjs );
+    SC_Pair * pSlews = ABC_ALLOC( SC_Pair, p->nObjs );
+    SC_Pair * pLoads = ABC_ALLOC( SC_Pair, p->nObjs );
+
+    memcpy( pTimes, p->pTimes, sizeof(SC_Pair) * p->nObjs );
+    memcpy( pSlews, p->pSlews, sizeof(SC_Pair) * p->nObjs );
+    memcpy( pLoads, p->pLoads, sizeof(SC_Pair) * p->nObjs );
+
+    Abc_SclTimeNtkRecompute( p, NULL, NULL, 0, 0 );
+
+    Abc_NtkForEachNode( pNtk, pObj, k )
+    {
+        if ( Abc_AbsFloat(p->pLoads[k].rise - pLoads[k].rise) > fDiff )
+            printf( "%6d : load rise differs %12.6f   %f %f\n", k, p->pLoads[k].rise-pLoads[k].rise, p->pLoads[k].rise, pLoads[k].rise );
+        if ( Abc_AbsFloat(p->pLoads[k].fall - pLoads[k].fall) > fDiff )
+            printf( "%6d : load fall differs %12.6f   %f %f\n", k, p->pLoads[k].fall-pLoads[k].fall, p->pLoads[k].fall, pLoads[k].fall );
+
+        if ( Abc_AbsFloat(p->pSlews[k].rise - pSlews[k].rise) > fDiff )
+            printf( "%6d : slew rise differs %12.6f   %f %f\n", k, p->pSlews[k].rise-pSlews[k].rise, p->pSlews[k].rise, pSlews[k].rise );
+        if ( Abc_AbsFloat(p->pSlews[k].fall - pSlews[k].fall) > fDiff )
+            printf( "%6d : slew fall differs %12.6f   %f %f\n", k, p->pSlews[k].fall-pSlews[k].fall, p->pSlews[k].fall, pSlews[k].fall );
+
+        if ( Abc_AbsFloat(p->pTimes[k].rise - pTimes[k].rise) > fDiff )
+            printf( "%6d : time rise differs %12.6f   %f %f\n", k, p->pTimes[k].rise-pTimes[k].rise, p->pTimes[k].rise, pTimes[k].rise );
+        if ( Abc_AbsFloat(p->pTimes[k].fall - pTimes[k].fall) > fDiff )
+            printf( "%6d : time fall differs %12.6f   %f %f\n", k, p->pTimes[k].fall-pTimes[k].fall, p->pTimes[k].fall, pTimes[k].fall );
+    }
+
+/*
+if ( memcmp( pTimes, p->pTimes, sizeof(SC_Pair) * p->nObjs ) )
+    printf( "Times differ!\n" );
+if ( memcmp( pSlews, p->pSlews, sizeof(SC_Pair) * p->nObjs ) )
+    printf( "Slews differ!\n" );
+if ( memcmp( pLoads, p->pLoads, sizeof(SC_Pair) * p->nObjs ) )
+    printf( "Loads differ!\n" );
+*/
+
+    ABC_FREE( pTimes );
+    ABC_FREE( pSlews );
+    ABC_FREE( pLoads );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print cumulative statistics.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclUpsizePrint( SC_Man * p, int Iter, int win, int nPathPos, int nPathNodes, int nUpsizes, int nTFOs, int fVerbose )
+{
+    printf( "%4d ",          Iter );
+    printf( "Win:%3d. ",     win );
+    printf( "PO:%6d. ",      nPathPos );
+    printf( "Path:%7d. ",    nPathNodes );
+    printf( "Gate:%5d. ",    nUpsizes );
+    printf( "TFO:%7d. ",     nTFOs );
+    printf( "A: " );
+    printf( "%.2f ",         p->SumArea );
+    printf( "(%+5.1f %%)  ", 100.0 * (p->SumArea - p->SumArea0)/ p->SumArea0 );
+    printf( "D: " );
+    printf( "%.2f ps ",      p->MaxDelay );
+    printf( "(%+5.1f %%)  ", 100.0 * (p->MaxDelay - p->MaxDelay0)/ p->MaxDelay0 );
+    printf( "B: " );
+    printf( "%.2f ps ",      p->BestDelay );
+    printf( "(%+5.1f %%)",   100.0 * (p->BestDelay - p->MaxDelay0)/ p->MaxDelay0 );
+    printf( "%8.2f sec    ", 1.0*(Abc_Clock() - p->timeTotal)/(CLOCKS_PER_SEC) );
+    printf( "%c", fVerbose ? '\n' : '\r' );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclUpsizeRemoveDangling( SC_Man * p, Abc_Ntk_t * pNtk )
+{
+    SC_Cell * pCell;
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        if ( Abc_ObjFanoutNum(pObj) == 0 )
+        {
+            pCell = Abc_SclObjCell( pObj );
+            p->SumArea -= pCell->area;
+            Abc_NtkDeleteObj_rec( pObj, 1 );
+//            printf( "Removed node %d.\n", i );
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars )
+{
+    SC_Man * p;
+    Vec_Int_t * vPathPos = NULL;    // critical POs
+    Vec_Int_t * vPathNodes = NULL;  // critical nodes and PIs
+    abctime clk, nRuntimeLimit = pPars->TimeOut ? pPars->TimeOut * CLOCKS_PER_SEC + Abc_Clock() : 0;
+    int i = 0, win, nUpsizes = -1, nFramesNoChange = 0, nConeSize = 0;
+    int nAllPos, nAllNodes, nAllTfos, nAllUpsizes;
+    if ( pPars->fVerbose )
+    {
+        printf( "Parameters: " );
+        printf( "Iters =%5d.  ",          pPars->nIters   );
+        printf( "Time win =%3d %%. ",     pPars->Window   );
+        printf( "Update ratio =%3d %%. ", pPars->Ratio    );
+        printf( "UseDept =%2d. ",         pPars->fUseDept );
+        printf( "UseWL =%2d. ",           pPars->fUseWireLoads );
+        printf( "Target =%5d ps. ",       pPars->DelayUser );
+        printf( "DelayGap =%3d ps. ",     pPars->DelayGap );
+        printf( "Timeout =%4d sec",       pPars->TimeOut  );
+        printf( "\n" );
+    }
+    // increase window for larger networks
+    if ( pPars->Window == 1 )
+        pPars->Window += (Abc_NtkNodeNum(pNtk) > 40000);
+    // prepare the manager; collect init stats
+    p = Abc_SclManStart( pLib, pNtk, pPars->fUseWireLoads, pPars->fUseDept, 0, pPars->BuffTreeEst );
+    p->timeTotal  = Abc_Clock();
+    assert( p->vGatesBest == NULL );
+    p->vGatesBest = Vec_IntDup( p->pNtk->vGates );
+    p->BestDelay  = p->MaxDelay0;
+    // perform upsizing
+    nAllPos = nAllNodes = nAllTfos = nAllUpsizes = 0;
+    if ( p->BestDelay <= pPars->DelayUser )
+        printf( "Current delay (%.2f ps) does not exceed the target delay (%.2f ps). Upsizing is not performed.\n", p->BestDelay, (float)pPars->DelayUser );
+    else
+    for ( i = 0; i < pPars->nIters; i++ )
+    {
+        for ( win = pPars->Window + ((i % 7) == 6); win <= 100;  win *= 2 )
+        {
+            // detect critical path
+            clk = Abc_Clock();
+            vPathPos   = Abc_SclFindCriticalCoWindow( p, win );
+            vPathNodes = Abc_SclFindCriticalNodeWindow( p, vPathPos, win, pPars->fUseDept );
+            p->timeCone += Abc_Clock() - clk;
+
+            // selectively upsize the nodes
+            clk = Abc_Clock();
+            if ( pPars->BypassFreq && i && (i % pPars->BypassFreq) == 0 )
+                nUpsizes = Abc_SclFindBypasses( p, vPathNodes, pPars->Ratio, pPars->Notches, i, pPars->DelayGap, pPars->fVeryVerbose );
+            else
+                nUpsizes = Abc_SclFindUpsizes( p, vPathNodes, pPars->Ratio, pPars->Notches, i, pPars->DelayGap, (pPars->BypassFreq > 0) );
+            p->timeSize += Abc_Clock() - clk;
+
+            // unmark critical path
+            clk = Abc_Clock();
+            Abc_SclUnmarkCriticalNodeWindow( p, vPathNodes );
+            Abc_SclUnmarkCriticalNodeWindow( p, vPathPos );
+            p->timeCone += Abc_Clock() - clk;
+            if ( nUpsizes > 0 )
+                break;
+            Vec_IntFree( vPathPos );
+            Vec_IntFree( vPathNodes );
+        }
+        if ( nUpsizes == 0 )
+            break;
+
+        // update timing information
+        clk = Abc_Clock();
+        if ( pPars->fUseDept )
+        {
+            if ( Vec_IntSize(p->vChanged) && !(pPars->BypassFreq && i && (i % pPars->BypassFreq) == 0) )
+                nConeSize = Abc_SclTimeIncUpdate( p );
+            else
+                Abc_SclTimeNtkRecompute( p, NULL, NULL, pPars->fUseDept, 0 );
+        }
+        else
+        {
+            Vec_Int_t * vTFO = Abc_SclFindTFO( p->pNtk, vPathNodes );
+            Abc_SclTimeCone( p, vTFO );
+            nConeSize = Vec_IntSize( vTFO );
+            Vec_IntFree( vTFO );
+        }
+        p->timeTime += Abc_Clock() - clk;
+//        Abc_SclUpsizePrintDiffs( p, pLib, pNtk );
+
+        // save the best network
+        p->MaxDelay = Abc_SclReadMaxDelay( p );
+        if ( p->BestDelay > p->MaxDelay )
+        {
+            p->BestDelay = p->MaxDelay;
+            Abc_SclApplyUpdateToBest( p->vGatesBest, p->pNtk->vGates, p->vUpdates );
+            Vec_IntClear( p->vUpdates2 );
+            nFramesNoChange = 0;
+        }
+        else
+            nFramesNoChange++;
+
+        // report and cleanup
+        Abc_SclUpsizePrint( p, i, win, Vec_IntSize(vPathPos), Vec_IntSize(vPathNodes), nUpsizes, nConeSize, pPars->fVeryVerbose || (pPars->fVerbose && nFramesNoChange == 0) ); //|| (i == nIters-1) );
+        nAllPos     += Vec_IntSize(vPathPos);
+        nAllNodes   += Vec_IntSize(vPathNodes);
+        nAllTfos    += nConeSize;
+        nAllUpsizes += nUpsizes;
+        Vec_IntFree( vPathPos );
+        Vec_IntFree( vPathNodes );
+        // check timeout
+        if ( nRuntimeLimit && Abc_Clock() > nRuntimeLimit )
+            break;
+        // check no change
+        if ( nFramesNoChange > pPars->nIterNoChange )
+            break;
+        // check best delay
+        if ( p->BestDelay <= pPars->DelayUser )
+            break;
+    }
+    // update for best gates and recompute timing
+    ABC_SWAP( Vec_Int_t *, p->vGatesBest, p->pNtk->vGates );
+    if ( pPars->BypassFreq != 0 )
+        Abc_SclUndoRecentChanges( p->pNtk, p->vUpdates2 );
+    if ( pPars->BypassFreq != 0 )
+        Abc_SclUpsizeRemoveDangling( p, pNtk );
+    Abc_SclTimeNtkRecompute( p, &p->SumArea, &p->MaxDelay, 0, 0 );
+    if ( pPars->fVerbose )
+        Abc_SclUpsizePrint( p, i, pPars->Window, nAllPos/(i?i:1), nAllNodes/(i?i:1), nAllUpsizes/(i?i:1), nAllTfos/(i?i:1), 1 );
+    else
+        printf( "                                                                                                                                                  \r" );
+    // report runtime
+    p->timeTotal = Abc_Clock() - p->timeTotal;
+    if ( pPars->fVerbose )
+    {
+        p->timeOther = p->timeTotal - p->timeCone - p->timeSize - p->timeTime;
+        ABC_PRTP( "Runtime: Critical path", p->timeCone,  p->timeTotal );
+        ABC_PRTP( "Runtime: Sizing eval  ", p->timeSize,  p->timeTotal );
+        ABC_PRTP( "Runtime: Timing update", p->timeTime,  p->timeTotal );
+        ABC_PRTP( "Runtime: Other        ", p->timeOther, p->timeTotal );
+        ABC_PRTP( "Runtime: TOTAL        ", p->timeTotal, p->timeTotal );
+    }
+    if ( pPars->fDumpStats )
+        Abc_SclDumpStats( p, "stats2.txt", p->timeTotal );
+    if ( nRuntimeLimit && Abc_Clock() > nRuntimeLimit )
+        printf( "Gate sizing timed out at %d seconds.\n", pPars->TimeOut );
+
+    // save the result and quit
+    Abc_SclSclGates2MioGates( pLib, pNtk ); // updates gate pointers
+    Abc_SclManFree( p );
+//    Abc_NtkCleanMarkAB( pNtk );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/scl/sclUtil.c b/abc-build/src/map/scl/sclUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/scl/sclUtil.c
@@ -0,0 +1,245 @@
+/**CFile****************************************************************
+
+  FileName    [sclUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Standard-cell library representation.]
+
+  Synopsis    [Various utilities.]
+
+  Author      [Alan Mishchenko, Niklas Een]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 24, 2012.]
+
+  Revision    [$Id: sclUtil.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sclSize.h"
+#include "map/mio/mio.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Converts pNode->pData gates into array of SC_Lit gate IDs and back.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclMioGates2SclGates( SC_Lib * pLib, Abc_Ntk_t * p )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    assert( p->vGates == NULL );
+    p->vGates = Vec_IntStartFull( Abc_NtkObjNumMax(p) );
+    Abc_NtkForEachNode1( p, pObj, i )
+    {
+        char * pName = Mio_GateReadName((Mio_Gate_t *)pObj->pData);
+        int gateId = Abc_SclCellFind( pLib, pName );
+        assert( gateId >= 0 );
+        Vec_IntWriteEntry( p->vGates, i, gateId );
+//printf( "Found gate %s\n", pName );
+    }
+    p->pSCLib = pLib;
+}
+void Abc_SclSclGates2MioGates( SC_Lib * pLib, Abc_Ntk_t * p )
+{
+    Abc_Obj_t * pObj;
+    int i, Counter = 0, CounterAll = 0;
+    assert( p->vGates != NULL );
+    Abc_NtkForEachNode1( p, pObj, i )
+    {
+        SC_Cell * pCell = Abc_SclObjCell(pObj);
+        assert( pCell->n_inputs == Abc_ObjFaninNum(pObj) );
+        pObj->pData = Mio_LibraryReadGateByName( (Mio_Library_t *)p->pManFunc, pCell->pName, NULL );
+        Counter += (pObj->pData == NULL);
+        assert( pObj->fMarkA == 0 && pObj->fMarkB == 0 );
+        CounterAll++;
+//printf( "Found gate %s\n", pCell->name );
+    }
+    if ( Counter )
+        printf( "Could not find %d (out of %d) gates in the current library.\n", Counter, CounterAll );
+    Vec_IntFreeP( &p->vGates );
+    p->pSCLib = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports percentage of gates of each size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+#define ABC_SCL_MAX_SIZE 64
+void Abc_SclManPrintGateSizes( SC_Lib * pLib, Abc_Ntk_t * p, Vec_Int_t * vGates )
+{
+    Abc_Obj_t * pObj;
+    int i, nGates = 0, Counters[ABC_SCL_MAX_SIZE] = {0};
+    double TotArea = 0, Areas[ABC_SCL_MAX_SIZE] = {0};
+    Abc_NtkForEachNode1( p, pObj, i )
+    {
+        SC_Cell * pCell = SC_LibCell( pLib, Vec_IntEntry(vGates, Abc_ObjId(pObj)) );
+        assert( pCell->Order < ABC_SCL_MAX_SIZE );
+        Counters[pCell->Order]++;
+        Areas[pCell->Order] += pCell->area;
+        TotArea += pCell->area;
+        nGates++;
+    }
+    printf( "Total gates = %d.  Total area = %.1f\n", nGates, TotArea );
+    for ( i = 0; i < ABC_SCL_MAX_SIZE; i++ )
+    {
+        if ( Counters[i] == 0 )
+            continue;
+        printf( "Cell size = %d.  ", i );
+        printf( "Count = %6d  ",     Counters[i] );
+        printf( "(%5.1f %%)   ",     100.0 * Counters[i] / nGates );
+        printf( "Area = %12.1f  ",   Areas[i] );
+        printf( "(%5.1f %%)  ",      100.0 * Areas[i] / TotArea );
+        printf( "\n" );
+    }
+}
+void Abc_SclPrintGateSizes( SC_Lib * pLib, Abc_Ntk_t * p )
+{
+    Abc_SclMioGates2SclGates( pLib, p );
+    Abc_SclManPrintGateSizes( pLib, p, p->vGates );
+    Vec_IntFreeP( &p->vGates );
+    p->pSCLib = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Downsizes each gate to its minimium size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+SC_Cell * Abc_SclFindMaxAreaCell( SC_Cell * pRepr )
+{
+    SC_Cell * pCell, * pBest = pRepr;
+    float AreaBest = pRepr->area;
+    int i;
+    SC_RingForEachCell( pRepr, pCell, i )
+        if ( AreaBest < pCell->area )
+        {
+            AreaBest = pCell->area;
+            pBest = pCell;
+        }
+    return pBest;
+}
+Vec_Int_t * Abc_SclFindMinAreas( SC_Lib * pLib, int fUseMax )
+{
+    Vec_Int_t * vMinCells;
+    SC_Cell * pCell, * pRepr = NULL, * pBest = NULL;
+    int i, k;
+    // map each gate in the library into its min/max-size prototype
+    vMinCells = Vec_IntStartFull( Vec_PtrSize(pLib->vCells) );
+    SC_LibForEachCellClass( pLib, pRepr, i )
+    {
+        pBest = fUseMax ? Abc_SclFindMaxAreaCell(pRepr) : pRepr;
+        SC_RingForEachCell( pRepr, pCell, k )
+            Vec_IntWriteEntry( vMinCells, pCell->Id, pBest->Id );
+    }
+    return vMinCells;
+}
+void Abc_SclMinsizePerform( SC_Lib * pLib, Abc_Ntk_t * p, int fUseMax, int fVerbose )
+{
+    Vec_Int_t * vMinCells;
+    Abc_Obj_t * pObj;
+    int i, gateId;
+    vMinCells = Abc_SclFindMinAreas( pLib, fUseMax );
+    Abc_SclMioGates2SclGates( pLib, p );
+    Abc_NtkForEachNode1( p, pObj, i )
+    {
+        gateId = Vec_IntEntry( p->vGates, i );
+        assert( gateId >= 0 && gateId < Vec_PtrSize(pLib->vCells) );
+        gateId = Vec_IntEntry( vMinCells, gateId );
+        assert( gateId >= 0 && gateId < Vec_PtrSize(pLib->vCells) );
+        Vec_IntWriteEntry( p->vGates, i, gateId );
+    }
+    Abc_SclSclGates2MioGates( pLib, p );
+    Vec_IntFree( vMinCells );
+}
+int Abc_SclCountMinSize( SC_Lib * pLib, Abc_Ntk_t * p, int fUseMax )
+{
+    Vec_Int_t * vMinCells;
+    Abc_Obj_t * pObj;
+    int i, gateId, Counter = 0;
+    vMinCells = Abc_SclFindMinAreas( pLib, fUseMax );
+    Abc_NtkForEachNode1( p, pObj, i )
+    {
+        gateId = Vec_IntEntry( p->vGates, i );
+        Counter += ( gateId == Vec_IntEntry(vMinCells, gateId) );
+    }
+    Vec_IntFree( vMinCells );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads timing constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SclReadTimingConstr( Abc_Frame_t * pAbc, char * pFileName, int fVerbose )
+{
+    char Buffer[1000], * pToken;
+    FILE * pFile = fopen( pFileName, "rb" );
+    while ( fgets( Buffer, 1000, pFile ) )
+    {
+        pToken = strtok( Buffer, " \t\r\n" );
+        if ( !strcmp(pToken, "set_driving_cell") )
+        {
+            Abc_FrameSetDrivingCell( Abc_UtilStrsav(strtok(NULL, " \t\r\n")) );
+            if ( fVerbose ) 
+                printf( "Setting driving cell to be \"%s\".\n", Abc_FrameReadDrivingCell() );
+        }
+        else if ( !strcmp(pToken, "set_load") )
+        {
+            Abc_FrameSetMaxLoad( atof(strtok(NULL, " \t\r\n")) );
+            if ( fVerbose ) 
+                printf( "Setting driving cell to be %f.\n", Abc_FrameReadMaxLoad() );
+        }
+        else 
+            printf( "Unrecognized token \"%s\".\n", pToken );
+    }
+    fclose( pFile );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/super/module.make b/abc-build/src/map/super/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/super/module.make
@@ -0,0 +1,3 @@
+SRC +=  src/map/super/super.c \
+	src/map/super/superAnd.c \
+	src/map/super/superGate.c
diff --git a/abc-build/src/map/super/super.c b/abc-build/src/map/super/super.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/super/super.c
@@ -0,0 +1,333 @@
+/**CFile****************************************************************
+
+  FileName    [super.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Pre-computation of supergates.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 18, 2003.]
+
+  Revision    [$Id: super.c,v 1.6 2004/10/30 20:51:11 satrajit Exp $]
+
+***********************************************************************/
+
+#include "superInt.h"
+#include "base/main/mainInt.h"
+#include "map/mio/mio.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Super_CommandSupergates   ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int Super_CommandSupergatesAnd( Abc_Frame_t * pAbc, int argc, char **argv );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Super_Init( Abc_Frame_t * pAbc )
+{
+    Cmd_CommandAdd( pAbc, "SC mapping",  "super",   Super_CommandSupergates,    0 ); 
+    Cmd_CommandAdd( pAbc, "SC mapping",  "super2",  Super_CommandSupergatesAnd, 0 ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Super_End( Abc_Frame_t * pAbc )
+{
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Super_CommandSupergatesAnd( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    FILE * pOut, * pErr;
+    int nVarsMax, nLevels;
+    int fVerbose;
+    int c;
+
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    // set the defaults
+    nVarsMax = 4;
+    nLevels  = 3;
+    fVerbose = 0;
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "ILvh")) != EOF ) 
+    {
+        switch (c) 
+        {
+            case 'I':
+                nVarsMax = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( nVarsMax < 0 ) 
+                    goto usage;
+                break;
+            case 'L':
+                nLevels = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( nLevels < 0 ) 
+                    goto usage;
+                break;
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+                break;
+            default:
+                goto usage;
+        }
+    }
+
+    Super2_Precompute( nVarsMax, nLevels, fVerbose );
+
+    return 0;
+
+usage:
+    fprintf( pErr, "usage: super2 [-IL num] [-vh]\n");
+    fprintf( pErr, "\t         precomputes the supergates composed of AND2s and INVs\n" );  
+    fprintf( pErr, "\t-I num : the max number of inputs to the supergate [default = %d]\n", nVarsMax );
+    fprintf( pErr, "\t-L num : the max number of logic levels of gates [default = %d]\n", nLevels );
+    fprintf( pErr, "\t-v     : enable verbose output\n");
+    fprintf( pErr, "\t-h     : print the help message\n");
+    return 1;       /* error exit */
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+    FILE * pFile;
+    FILE * pOut, * pErr;
+    Mio_Library_t * pLib;
+    char * FileName, * ExcludeFile;
+    float DelayLimit;
+    float AreaLimit;
+    int fSkipInvs;
+    int fWriteOldFormat; 
+    int nVarsMax, nLevels, nGatesMax, TimeLimit;
+    int fVerbose;
+    int c;
+
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    // set the defaults
+    nVarsMax   = 5;
+    nLevels    = 2;
+    DelayLimit = 0;
+    AreaLimit  = 0;
+    nGatesMax  = 0;
+    TimeLimit  = 0;
+    fSkipInvs  = 1;
+    fVerbose   = 0;
+    fWriteOldFormat = 0;
+    ExcludeFile = 0;
+
+    Extra_UtilGetoptReset();
+    while ( (c = Extra_UtilGetopt(argc, argv, "ILNTDAEsovh")) != EOF ) 
+    {
+        switch (c) 
+        {
+            case 'I':
+                nVarsMax = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( nVarsMax < 0 ) 
+                    goto usage;
+                break;
+            case 'L':
+                nLevels = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( nLevels < 0 ) 
+                    goto usage;
+                break;
+            case 'N':
+                nGatesMax = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( nGatesMax < 0 ) 
+                    goto usage;
+                break;
+            case 'T':
+                TimeLimit = atoi(argv[globalUtilOptind]);
+                globalUtilOptind++;
+                if ( TimeLimit < 0 ) 
+                    goto usage;
+                break;
+			case 'D':
+				DelayLimit = (float)atof(argv[globalUtilOptind]);
+				globalUtilOptind++;
+				if ( DelayLimit <= 0.0 ) 
+					goto usage;
+				break;
+			case 'A':
+				AreaLimit = (float)atof(argv[globalUtilOptind]);
+				globalUtilOptind++;
+				if ( AreaLimit <= 0.0 ) 
+					goto usage;
+				break;
+            case 'E':
+                ExcludeFile = argv[globalUtilOptind];
+                if ( ExcludeFile == 0 )
+                    goto usage;
+                globalUtilOptind++;
+                break;
+            case 's':
+                fSkipInvs ^= 1;
+                break;
+            case 'o':
+                fWriteOldFormat ^= 1;
+                break;
+            case 'v':
+                fVerbose ^= 1;
+                break;
+            case 'h':
+                goto usage;
+                break;
+            default:
+                goto usage;
+        }
+    }
+
+
+    if ( argc != globalUtilOptind + 1 )
+    {
+        fprintf( pErr, "The genlib library file should be given on the command line.\n" );
+        goto usage;
+    }
+
+    if ( nVarsMax < 2 || nVarsMax > 6 )
+    {
+        fprintf( pErr, "The max number of variables (%d) should be more than 1 and less than 7.\n", nVarsMax );
+        goto usage;
+    }
+
+    // get the input file name
+    FileName = argv[globalUtilOptind];
+    if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL )
+//    if ( (pFile = fopen( FileName, "r" )) == NULL )
+    {
+        fprintf( pErr, "Cannot open input file \"%s\". ", FileName );
+        if (( FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL ) ))
+            fprintf( pErr, "Did you mean \"%s\"?", FileName );
+        fprintf( pErr, "\n" );
+        return 1;
+    }
+    fclose( pFile );
+
+    // set the new network
+    pLib = Mio_LibraryRead( FileName, NULL, ExcludeFile, fVerbose );
+    if ( pLib == NULL )
+    {
+        fprintf( pErr, "Reading library has failed.\n" );
+        goto usage;
+    }
+
+    // compute the gates
+    FileName = Extra_FileNameGenericAppend(Mio_LibraryReadName(pLib), ".super");
+    Super_Precompute( pLib, nVarsMax, nLevels, nGatesMax, DelayLimit, AreaLimit, TimeLimit, fSkipInvs, fVerbose, FileName );
+
+    // delete the library
+    Mio_LibraryDelete( pLib );
+    return 0;
+
+usage:
+    fprintf( pErr, "usage: super [-ILNT num] [-DA float] [-E file] [-sovh] <genlib_file>\n");
+    fprintf( pErr, "\t         precomputes the supergates for the given genlib library\n" );  
+    fprintf( pErr, "\t-I num   : the max number of supergate inputs [default = %d]\n", nVarsMax );
+    fprintf( pErr, "\t-L num   : the max number of levels of gates [default = %d]\n", nLevels );
+    fprintf( pErr, "\t-N num   : the limit on the number of considered supergates [default = %d]\n", nGatesMax );
+    fprintf( pErr, "\t-T num   : the approximate runtime limit in seconds [default = %d]\n", TimeLimit );
+	fprintf( pErr, "\t-D float : the max delay of the supergates [default = %.2f]\n", DelayLimit );
+	fprintf( pErr, "\t-A float : the max area of the supergates [default = %.2f]\n", AreaLimit );
+    fprintf( pErr, "\t-E file  : file contains list of genlib gates to exclude\n" );
+    fprintf( pErr, "\t-s       : toggle the use of inverters at the inputs [default = %s]\n", (fSkipInvs? "no": "yes") );
+    fprintf( pErr, "\t-o       : toggle dumping the supergate library in old format [default = %s]\n", (fWriteOldFormat? "yes": "no") );
+    fprintf( pErr, "\t-v       : enable verbose output [default = %s]\n", (fVerbose? "yes" : "no") );
+    fprintf( pErr, "\t-h       : print the help message\n");
+    fprintf( pErr, "\n");
+    fprintf( pErr, "\tHere is a piece of advice on precomputing supergate libraries:\n");
+    fprintf( pErr, "\t\n");
+    fprintf( pErr, "\tStart with the number of inputs equal to 5 (-I 5), the number of \n");
+    fprintf( pErr, "\tlevels equal to 2 (-L 2), the delay equal to 2-3 delays of inverter, \n");
+    fprintf( pErr, "\tthe area equal to 2-3 areas of two input NAND, and runtime limit equal \n");
+    fprintf( pErr, "\tto 10 seconds (-T 10). Run precomputation and learn from the result.\n");
+    fprintf( pErr, "\tDetermine what parameter is most constraining and try to increase \n");
+    fprintf( pErr, "\tthe value of that parameter. The goal is to have a well-balanced\n");
+    fprintf( pErr, "\tset of constraints and the resulting supergate library containing\n");
+    fprintf( pErr, "\tapproximately 5K-20K supergates. Typically, it is better to increase\n");
+    fprintf( pErr, "\tdelay limit rather than area limit, because having large-area supergates\n");
+    fprintf( pErr, "\tmay result in a considerable increase in area.\n");
+    fprintf( pErr, "\t\n");
+    fprintf( pErr, "\tNote that a good supergate library for experiments typically can be \n");
+    fprintf( pErr, "\tprecomputed in 30 sec or less. Increasing runtime limit makes sense when\n");
+    fprintf( pErr, "\tother parameters are well-balanced and it is needed to enumerate more\n");
+    fprintf( pErr, "\tchoices to have a good result. In the end, to compute the final library\n");
+    fprintf( pErr, "\tthe runtime can be set to 300 sec to ensure the ultimate quality.\n");
+    fprintf( pErr, "\tIn some cases, the runtime has to be reduced if the supergate library\n");
+    fprintf( pErr, "\tcontains too many supergates (> 500K).\n");
+    fprintf( pErr, "\t\n");
+    fprintf( pErr, "\tWhen precomputing libraries of 6 inputs (-i 6), start with even more \n");
+    fprintf( pErr, "\trestricted parameters and gradually increase them until the goal is met.\n");
+    fprintf( pErr, "\t\n");
+    return 1;       /* error exit */
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/super/super.h b/abc-build/src/map/super/super.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/super/super.h
@@ -0,0 +1,62 @@
+/**CFile****************************************************************
+
+  FileName    [super.h]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Pre-computation of supergates (delay-limited gate combinations).]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: super.h,v 1.3 2004/06/28 14:20:25 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__map__super__super_h
+#define ABC__map__super__super_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== superAnd.c =============================================================*/
+extern void        Super2_Precompute( int nInputs, int nLevels, int fVerbose );
+/*=== superGate.c =============================================================*/
+extern Vec_Str_t * Super_PrecomputeStr( Mio_Library_t * pLibGen, int nVarsMax, int nLevels, int nGatesMax, float tDelayMax, float tAreaMax, int TimeLimit, int fSkipInv, int fVerbose );
+extern void        Super_Precompute( Mio_Library_t * pLibGen, int nVarsMax, int nLevels, int nGatesMax, float tDelayMax, float tAreaMax, int TimeLimit, int fSkipInv, int fVerbose, char * pFileName );
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/map/super/superAnd.c b/abc-build/src/map/super/superAnd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/super/superAnd.c
@@ -0,0 +1,701 @@
+/**CFile****************************************************************
+
+  FileName    [superAnd.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Pre-computation of supergates.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: superAnd.c,v 1.3 2004/06/28 14:20:25 alanmi Exp $]
+
+***********************************************************************/
+
+#include "superInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// the bit masks
+#define SUPER_MASK(n)     ((~((unsigned)0)) >> (32-n))
+#define SUPER_FULL         (~((unsigned)0))
+
+// data structure for AND2 subgraph precomputation
+typedef struct Super2_ManStruct_t_     Super2_Man_t;   // manager
+typedef struct Super2_LibStruct_t_     Super2_Lib_t;   // library
+typedef struct Super2_GateStruct_t_    Super2_Gate_t;  // supergate
+
+struct Super2_ManStruct_t_
+{
+    Extra_MmFixed_t *   pMem;         // memory manager for all supergates
+    stmm_table *        tTable;       // mapping of truth tables into gates
+    int                 nTried;       // the total number of tried
+};
+
+struct Super2_LibStruct_t_
+{
+    int                 i;            // used to iterate through the table
+    int                 k;            // used to iterate through the table
+    int                 nInputs;      // the number of inputs
+    int                 nMints;       // the number of minterms
+    int                 nLevels;      // the number of logic levels
+    int                 nGates;       // the number of gates in the library
+    int                 nGatesAlloc;  // the number of allocated places
+    Super2_Gate_t **    pGates;       // the gates themselves
+    unsigned            uMaskBit;     // the mask used to determine the compl bit
+};
+
+struct Super2_GateStruct_t_
+{
+    unsigned            uTruth;       // the truth table of this supergate
+    Super2_Gate_t *     pOne;         // the left wing
+    Super2_Gate_t *     pTwo;         // the right wing
+    Super2_Gate_t *     pNext;        // the next gate in the table
+};
+
+
+// manipulation of complemented attributes
+#define Super2_IsComplement(p)    (((int)((ABC_PTRUINT_T) (p) & 01)))
+#define Super2_Regular(p)         ((Super2_Gate_t *)((ABC_PTRUINT_T)(p) & ~01)) 
+#define Super2_Not(p)             ((Super2_Gate_t *)((ABC_PTRUINT_T)(p) ^ 01)) 
+#define Super2_NotCond(p,c)       ((Super2_Gate_t *)((ABC_PTRUINT_T)(p) ^ (c)))
+
+// iterating through the gates in the library
+#define Super2_LibForEachGate( Lib, Gate )                        \
+    for ( Lib->i = 0;                                             \
+          Lib->i < Lib->nGates && (Gate = Lib->pGates[Lib->i]);   \
+          Lib->i++ )
+#define Super2_LibForEachGate2( Lib, Gate2 )                      \
+    for ( Lib->k = 0;                                             \
+          Lib->k < Lib->i && (Gate2 = Lib->pGates[Lib->k]);       \
+          Lib->k++ )
+
+// static functions
+static Super2_Man_t * Super2_ManStart();
+static void           Super2_ManStop( Super2_Man_t * pMan );
+static Super2_Lib_t * Super2_LibStart();
+static Super2_Lib_t * Super2_LibDup( Super2_Lib_t * pLib );
+static void           Super2_LibStop( Super2_Lib_t * pLib );
+static void           Super2_LibAddGate( Super2_Lib_t * pLib, Super2_Gate_t * pGate );
+static Super2_Lib_t * Super2_LibFirst( Super2_Man_t * pMan, int nInputs );
+static Super2_Lib_t * Super2_LibCompute( Super2_Man_t * pMan, Super2_Lib_t * pLib );
+
+static void           Super2_LibWrite( Super2_Lib_t * pLib );
+static void           Super2_LibWriteGate( FILE * pFile, Super2_Lib_t * pLib, Super2_Gate_t * pGate );
+static char *         Super2_LibWriteGate_rec( Super2_Gate_t * pGate, int fInv, int Level );
+static int            Super2_LibWriteCompare( char * pStr1, char * pStr2 );
+static int            Super2_LibCompareGates( Super2_Gate_t ** ppG1, Super2_Gate_t ** ppG2 );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Precomputes the library of AND2 gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Super2_Precompute( int nInputs, int nLevels, int fVerbose )
+{
+    Super2_Man_t * pMan;
+    Super2_Lib_t * pLibCur, * pLibNext;
+    int Level;
+    abctime clk;
+
+    assert( nInputs < 6 );
+
+    // start the manager
+    pMan = Super2_ManStart();
+
+    // get the starting supergates
+    pLibCur = Super2_LibFirst( pMan, nInputs );
+
+    // perform the computation of supergates
+printf( "Computing supergates for %d inputs and %d levels:\n", nInputs, nLevels );
+    for ( Level = 1; Level <= nLevels; Level++ )
+    {
+clk = Abc_Clock();
+        pLibNext = Super2_LibCompute( pMan, pLibCur );
+        pLibNext->nLevels = Level;
+        Super2_LibStop( pLibCur );
+        pLibCur = pLibNext;
+printf( "Level %d:  Tried = %7d.  Computed = %7d.  ", Level, pMan->nTried, pLibCur->nGates );
+ABC_PRT( "Runtime", Abc_Clock() - clk );
+fflush( stdout );
+    }
+
+printf( "Writing the output file...\n" );
+fflush( stdout );
+    // write them into a file
+    Super2_LibWrite( pLibCur );
+    Super2_LibStop( pLibCur );
+
+    // stop the manager
+    Super2_ManStop( pMan );
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Super2_Man_t * Super2_ManStart()
+{
+    Super2_Man_t * pMan;
+    pMan = ABC_ALLOC( Super2_Man_t, 1 );
+    memset( pMan, 0, sizeof(Super2_Man_t) );
+    pMan->pMem   = Extra_MmFixedStart( sizeof(Super2_Gate_t) );
+    pMan->tTable = stmm_init_table( st__ptrcmp, st__ptrhash );
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Super2_ManStop( Super2_Man_t * pMan )
+{
+    Extra_MmFixedStop( pMan->pMem );
+    stmm_free_table( pMan->tTable );
+    ABC_FREE( pMan );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Super2_Lib_t * Super2_LibStart()
+{
+    Super2_Lib_t * pLib;
+    pLib = ABC_ALLOC( Super2_Lib_t, 1 );
+    memset( pLib, 0, sizeof(Super2_Lib_t) );
+    return pLib;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Super2_Lib_t * Super2_LibDup( Super2_Lib_t * pLib )
+{
+    Super2_Lib_t * pLibNew;
+    pLibNew = Super2_LibStart();
+    pLibNew->nInputs     = pLib->nInputs;
+    pLibNew->nMints      = pLib->nMints;
+    pLibNew->nLevels     = pLib->nLevels;
+    pLibNew->nGates      = pLib->nGates;
+    pLibNew->uMaskBit    = pLib->uMaskBit;
+    pLibNew->nGatesAlloc = 1000 + pLib->nGatesAlloc;
+    pLibNew->pGates      = ABC_ALLOC( Super2_Gate_t *, pLibNew->nGatesAlloc );
+    memcpy( pLibNew->pGates, pLib->pGates, pLibNew->nGates * sizeof(Super2_Gate_t *) );
+    return pLibNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add gate to the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Super2_LibAddGate( Super2_Lib_t * pLib, Super2_Gate_t * pGate )
+{
+    if ( pLib->nGates == pLib->nGatesAlloc )
+    {
+        pLib->pGates  = ABC_REALLOC( Super2_Gate_t *, pLib->pGates,  3 * pLib->nGatesAlloc );
+        pLib->nGatesAlloc *= 3;
+    }
+    pLib->pGates[ pLib->nGates++ ] = pGate;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Super2_LibStop( Super2_Lib_t * pLib )
+{
+    ABC_FREE( pLib->pGates );
+    ABC_FREE( pLib );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the starting supergates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Super2_Lib_t * Super2_LibFirst( Super2_Man_t * pMan, int nInputs )
+{
+    Super2_Lib_t * pLib;
+    int v, m;    
+
+    // start the library
+    pLib = Super2_LibStart();
+
+    // create the starting supergates
+    pLib->nInputs     = nInputs;
+    pLib->nMints      = (1 << nInputs);
+    pLib->nLevels     = 0;
+    pLib->nGates      = nInputs + 1;
+    pLib->nGatesAlloc = nInputs + 1;
+    pLib->uMaskBit    = (1 << (pLib->nMints-1));
+    pLib->pGates      = ABC_ALLOC( Super2_Gate_t *, nInputs + 1 );
+    // add the constant 0
+    pLib->pGates[0] = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem );
+    memset( pLib->pGates[0], 0, sizeof(Super2_Gate_t) );
+    // add the elementary gates
+    for ( v = 0; v < nInputs; v++ )
+    {
+        pLib->pGates[v+1] = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem );
+        memset( pLib->pGates[v+1], 0, sizeof(Super2_Gate_t) );
+        pLib->pGates[v+1]->pTwo = (Super2_Gate_t *)(ABC_PTRUINT_T)v;
+    }
+
+    // set up their truth tables
+    for ( m = 0; m < pLib->nMints; m++ )
+        for ( v = 0; v < nInputs; v++ )
+            if ( m & (1 << v) )
+                pLib->pGates[v+1]->uTruth |= (1 << m);
+    return pLib;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Precomputes one level of supergates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Super2_Lib_t * Super2_LibCompute( Super2_Man_t * pMan, Super2_Lib_t * pLib )
+{
+    Super2_Lib_t * pLibNew;
+    Super2_Gate_t * pGate1, * pGate2, * pGateNew;
+    Super2_Gate_t ** ppGate;
+    unsigned Mask = SUPER_MASK(pLib->nMints);
+    unsigned uTruth, uTruthR, uTruth1, uTruth2, uTruth1c, uTruth2c;
+
+    // start the new library
+    pLibNew = Super2_LibDup( pLib );
+
+    // reset the hash table
+    stmm_free_table( pMan->tTable );
+    pMan->tTable = stmm_init_table( st__ptrcmp, st__ptrhash );
+    // set the starting things into the hash table
+    Super2_LibForEachGate( pLibNew, pGate1 )
+    {
+        uTruthR = ((pGate1->uTruth & pLibNew->uMaskBit)? Mask & ~pGate1->uTruth : pGate1->uTruth);
+
+        if ( stmm_lookup( pMan->tTable, (char *)(ABC_PTRUINT_T)uTruthR, (char **)&pGate2 ) )
+        {
+            printf( "New gate:\n" );
+            Super2_LibWriteGate( stdout, pLibNew, pGate1 );
+            printf( "Gate in the table:\n" );
+            Super2_LibWriteGate( stdout, pLibNew, pGate2 );
+            assert( 0 );
+        }
+        stmm_insert( pMan->tTable, (char *)(ABC_PTRUINT_T)uTruthR, (char *)(ABC_PTRUINT_T)pGate1 );
+    }
+
+
+    // set the number of gates tried
+    pMan->nTried = pLibNew->nGates;
+
+    // go through the gate pairs
+    Super2_LibForEachGate( pLib, pGate1 )
+    {
+        if ( pLib->i && pLib->i % 300 == 0 )
+        {
+            printf( "Tried %5d first gates...\n", pLib->i );
+            fflush( stdout );
+        }
+
+        Super2_LibForEachGate2( pLib, pGate2 )
+        {
+            uTruth1  = pGate1->uTruth;
+            uTruth2  = pGate2->uTruth;
+            uTruth1c = Mask & ~uTruth1;
+            uTruth2c = Mask & ~uTruth2;
+
+            // none complemented
+            uTruth  = uTruth1  & uTruth2;
+            uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth);
+
+            if ( !stmm_find_or_add( pMan->tTable, (char *)(ABC_PTRUINT_T)uTruthR, (char ***)&ppGate ) )
+            {
+                pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem );
+                pGateNew->pOne  = pGate1;
+                pGateNew->pTwo  = pGate2;
+                pGateNew->uTruth = uTruth;
+                *ppGate = pGateNew;
+                Super2_LibAddGate( pLibNew, pGateNew );
+            }                
+
+            // one complemented
+            uTruth  = uTruth1c & uTruth2;
+            uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth);
+
+            if ( !stmm_find_or_add( pMan->tTable, (char *)(ABC_PTRUINT_T)uTruthR, (char ***)&ppGate ) )
+            {
+                pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem );
+                pGateNew->pOne  = Super2_Not(pGate1);
+                pGateNew->pTwo  = pGate2;
+                pGateNew->uTruth = uTruth;
+                *ppGate = pGateNew;
+                Super2_LibAddGate( pLibNew, pGateNew );
+            }                
+
+            // another complemented
+            uTruth  = uTruth1  & uTruth2c;
+            uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth);
+
+            if ( !stmm_find_or_add( pMan->tTable, (char *)(ABC_PTRUINT_T)uTruthR, (char ***)&ppGate ) )
+            {
+                pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem );
+                pGateNew->pOne  = pGate1;
+                pGateNew->pTwo  = Super2_Not(pGate2);
+                pGateNew->uTruth = uTruth;
+                *ppGate = pGateNew;
+                Super2_LibAddGate( pLibNew, pGateNew );
+            }                
+
+            // both complemented
+            uTruth  = uTruth1c & uTruth2c;
+            uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth);
+
+            if ( !stmm_find_or_add( pMan->tTable, (char *)(ABC_PTRUINT_T)uTruthR, (char ***)&ppGate ) )
+            {
+                pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem );
+                pGateNew->pOne  = Super2_Not(pGate1);
+                pGateNew->pTwo  = Super2_Not(pGate2);
+                pGateNew->uTruth = uTruth;
+                *ppGate = pGateNew;
+                Super2_LibAddGate( pLibNew, pGateNew );
+            }                
+
+            pMan->nTried += 4;
+        }
+    }
+    return pLibNew;
+}
+
+
+static unsigned s_uMaskBit;
+static unsigned s_uMaskAll;
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the library into the file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Super2_LibWrite( Super2_Lib_t * pLib )
+{
+    Super2_Gate_t * pGate;
+    FILE * pFile;
+    char FileName[100];
+    abctime clk;
+
+    if ( pLib->nLevels > 5 )
+    {
+        printf( "Cannot write file for %d levels.\n", pLib->nLevels );
+        return;
+    }
+
+clk = Abc_Clock();
+    // sort the supergates by truth table
+    s_uMaskBit = pLib->uMaskBit;
+    s_uMaskAll = SUPER_MASK(pLib->nMints);
+    qsort( (void *)pLib->pGates, pLib->nGates, sizeof(Super2_Gate_t *), 
+            (int (*)(const void *, const void *)) Super2_LibCompareGates );
+    assert( Super2_LibCompareGates( pLib->pGates, pLib->pGates + pLib->nGates - 1 ) < 0 );
+ABC_PRT( "Sorting", Abc_Clock() - clk );
+
+
+    // start the file
+    sprintf( FileName, "superI%dL%d", pLib->nInputs, pLib->nLevels );
+    pFile = fopen( FileName, "w" );
+    fprintf( pFile, "# AND2/INV supergates derived on %s.\n", Extra_TimeStamp() );
+    fprintf( pFile, "# Command line: \"super2 -i %d -l %d\".\n", pLib->nInputs, pLib->nLevels );
+    fprintf( pFile, "# The number of inputs     = %6d.\n", pLib->nInputs );
+    fprintf( pFile, "# The number of levels     = %6d.\n", pLib->nLevels );
+    fprintf( pFile, "# The number of supergates = %6d.\n", pLib->nGates  );
+    fprintf( pFile, "# The total functions      = %6d.\n", (1<<(pLib->nMints-1)) );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, "%6d\n", pLib->nGates );
+
+    // print the gates
+    Super2_LibForEachGate( pLib, pGate )
+        Super2_LibWriteGate( pFile, pLib, pGate );
+    fclose( pFile );
+
+    printf( "The supergates are written into file \"%s\" ", FileName );
+    printf( "(%0.2f MB).\n", ((double)Extra_FileSize(FileName))/(1<<20) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the gate into the file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Super2_LibCompareGates( Super2_Gate_t ** ppG1, Super2_Gate_t ** ppG2 )
+{
+    Super2_Gate_t * pG1  = *ppG1;
+    Super2_Gate_t * pG2  = *ppG2;
+    unsigned uTruth1, uTruth2;
+
+    uTruth1 = (pG1->uTruth & s_uMaskBit)? s_uMaskAll & ~pG1->uTruth : pG1->uTruth;
+    uTruth2 = (pG2->uTruth & s_uMaskBit)? s_uMaskAll & ~pG2->uTruth : pG2->uTruth;
+
+    if ( uTruth1 < uTruth2 )
+        return -1;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the gate into the file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Super2_LibWriteGate( FILE * pFile, Super2_Lib_t * pLib, Super2_Gate_t * pGate )
+{
+//    unsigned uTruthR;
+    unsigned uTruth;
+    int fInv;
+
+    // check whether the gate need complementation
+    fInv = (int)(pGate->uTruth & pLib->uMaskBit);
+    uTruth = (fInv? ~pGate->uTruth : pGate->uTruth);
+/*
+    // reverse the truth table
+    uTruthR = 0;
+    for ( m = 0; m < pLib->nMints; m++ )
+        if ( uTruth & (1 << m) )
+            uTruthR |= (1 << (pLib->nMints-1-m));
+*/
+    // write the truth table
+    Extra_PrintBinary( pFile, &uTruth, pLib->nMints );
+    fprintf( pFile, "   " );
+    // write the symbolic expression
+    fprintf( pFile, "%s", Super2_LibWriteGate_rec( pGate, fInv, pLib->nLevels ) );
+    fprintf( pFile, "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively writes the gate into the file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Super2_LibWriteGate_rec( Super2_Gate_t * pGate, int fInv, int Level )
+{
+    static char Buff01[  3], Buff02[  3];    // Max0              =  1
+    static char Buff11[  6], Buff12[  6];    // Max1 = 2*Max0 + 2 =  4
+    static char Buff21[ 12], Buff22[ 12];    // Max2 = 2*Max1 + 2 = 10
+    static char Buff31[ 25], Buff32[ 25];    // Max3 = 2*Max2 + 2 = 22
+    static char Buff41[ 50], Buff42[ 50];    // Max4 = 2*Max3 + 2 = 46
+    static char Buff51[100], Buff52[100];    // Max5 = 2*Max4 + 2 = 94
+    static char * pBuffs1[6] = { Buff01, Buff11, Buff21, Buff31, Buff41, Buff51 };
+    static char * pBuffs2[6] = { Buff02, Buff12, Buff22, Buff32, Buff42, Buff52 };
+    char * pBranch;
+    char * pBuffer1 = pBuffs1[Level];
+    char * pBuffer2 = pBuffs2[Level];
+    Super2_Gate_t * pGateNext1, * pGateNext2;
+    int fInvNext1, fInvNext2;
+    int RetValue;
+
+    // consider the last level
+    assert( Level >= 0 );
+    if ( pGate->pOne == NULL )
+    {
+        if ( pGate->uTruth == 0 )
+        {
+            pBuffer1[0] = (fInv? '1': '0');
+            pBuffer1[1] = '$';
+            pBuffer1[2] = 0;
+        }
+        else
+        {
+            pBuffer1[0] = (fInv? 'A' + ((int)(ABC_PTRUINT_T)pGate->pTwo): 'a' + ((int)(ABC_PTRUINT_T)pGate->pTwo));
+            pBuffer1[1] = 0;
+        }
+        return pBuffer1;
+    }
+    assert( Level > 0 );
+
+
+    // get the left branch
+    pGateNext1 = Super2_Regular(pGate->pOne);
+    fInvNext1  = Super2_IsComplement(pGate->pOne);
+    pBranch    = Super2_LibWriteGate_rec(pGateNext1, fInvNext1, Level - 1);
+    // copy into Buffer1
+    strcpy( pBuffer1, pBranch );
+
+    // get the right branch
+    pGateNext2 = Super2_Regular(pGate->pTwo);
+    fInvNext2  = Super2_IsComplement(pGate->pTwo);
+    pBranch    = Super2_LibWriteGate_rec(pGateNext2, fInvNext2, Level - 1);
+
+    // consider the case when comparison is not necessary
+    if ( fInvNext1 ^ fInvNext2 )
+    {
+        if ( fInvNext1 > fInvNext2 )
+            sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBuffer1, pBranch, (fInv? '>': ')') );
+        else
+            sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBranch, pBuffer1, (fInv? '>': ')') );
+    }
+    else
+    {
+        // compare the two branches
+        RetValue = Super2_LibWriteCompare( pBuffer1, pBranch );
+        if ( RetValue == 1 )
+            sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBuffer1, pBranch, (fInv? '>': ')') );
+        else // if ( RetValue == -1 )
+        {
+            sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBranch, pBuffer1, (fInv? '>': ')') );
+            if ( RetValue == 0 )
+                printf( "Strange!\n" );
+        }
+    }
+    return pBuffer2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the two branches of the tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Super2_LibWriteCompare( char * pStr1, char * pStr2 )
+{
+    while ( 1 )
+    {
+        // skip extra symbols
+        while ( *pStr1 && *pStr1 < 'A' )
+            pStr1++;
+        while ( *pStr2 && *pStr2 < 'A' )
+            pStr2++;
+
+        // check if any one is finished
+        if ( *pStr1 == 0 || *pStr2 == 0 )
+        {
+            if ( *pStr2 )
+                return 1;
+            return -1;
+        }
+
+        // compare
+        if ( *pStr1 == *pStr2 )
+        {
+            pStr1++;
+            pStr2++;
+        }
+        else
+        {
+            if ( *pStr1 < *pStr2 )
+                return 1;
+            return -1;
+        }
+    }
+    return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/super/superGENERIC.c b/abc-build/src/map/super/superGENERIC.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/super/superGENERIC.c
@@ -0,0 +1,51 @@
+/**CFile****************************************************************
+
+  FileName    [super__.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Pre-computation of supergates.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: super__.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "superInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/super/superGate.c b/abc-build/src/map/super/superGate.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/super/superGate.c
@@ -0,0 +1,1473 @@
+/**CFile****************************************************************
+
+  FileName    [superGate.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Pre-computation of supergates.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: superGate.c,v 1.7 2004/08/03 00:11:40 satrajit Exp $]
+
+***********************************************************************/
+
+#include <math.h>
+#include "superInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// the bit masks
+#define SUPER_MASK(n)     ((~((unsigned)0)) >> (32-(n)))
+#define SUPER_FULL         (~((unsigned)0))
+#define SUPER_NO_VAR         (-9999.0)
+#define SUPER_EPSILON        (0.001)
+
+// data structure for supergate precomputation
+typedef struct Super_ManStruct_t_     Super_Man_t;   // manager
+typedef struct Super_GateStruct_t_    Super_Gate_t;  // supergate
+
+struct Super_ManStruct_t_
+{
+    // parameters
+    char *              pName;        // the original genlib file name
+    int                 nVarsMax;     // the number of inputs
+    int                 nMints;       // the number of minterms
+    int                 nLevels;      // the number of logic levels
+    int                 nGatesMax;    // the number of gates computed
+    float               tDelayMax;    // the max delay of the supergates in the library
+    float               tAreaMax;     // the max area of the supergates in the library
+    int                 fSkipInv;     // the flag says about skipping inverters
+    int                 fWriteOldFormat; // in addition, writes the file in the old format
+    int                 fVerbose;
+
+    // supergates
+    Super_Gate_t *      pInputs[10];  // the input supergates
+    int                 nGates;       // the number of gates in the library
+    Super_Gate_t **     pGates;       // the gates themselves
+    stmm_table *        tTable;       // mapping of truth tables into gates
+
+    // memory managers
+    Extra_MmFixed_t *   pMem;         // memory manager for the supergates
+    Extra_MmFlex_t *    pMemFlex;     // memory manager for the fanin arrays
+
+    // statistics
+    int                 nTried;       // the total number of tried
+    int                 nAdded;       // the number of entries added
+    int                 nRemoved;     // the number of entries removed
+    int                 nClasses;     // the number of gate classes
+    int                 nUnique;      // the number of unique gates
+    int                 nLookups;     // the number of hash table lookups
+    int                 nAliases;     // the number of hash table lookups thrown away due to aliasing
+
+    // runtime
+    abctime             Time;         // the runtime of the generation procedure
+    int                 TimeLimit;    // the runtime limit (in seconds)
+    int                 TimeSec;      // the time passed (in seconds)
+    abctime             TimeStop;     // the time to stop computation (in miliseconds)
+    abctime             TimePrint;    // the time to print message
+};
+
+struct Super_GateStruct_t_
+{
+    Mio_Gate_t *        pRoot;        // the root gate for this supergate
+    unsigned            fVar :     1; // the flag signaling the elementary variable
+    unsigned            fSuper :   1; // the flag signaling the elementary variable
+    unsigned            nFanins :  6; // the number of fanin gates
+    unsigned            Number :  24; // the number assigned in the process
+    unsigned            uTruth[2];    // the truth table of this supergate
+    Super_Gate_t *      pFanins[6];   // the fanins of the gate
+    float               Area;         // the area of this gate
+    float               ptDelays[6];  // the pin-to-pin delays for all inputs
+    float               tDelayMax;    // the maximum delay
+    Super_Gate_t *      pNext;        // the next gate in the table
+};
+
+
+// iterating through the gates in the library
+#define Super_ManForEachGate( GateArray, Limit, Index, Gate )    \
+    for ( Index = 0;                                             \
+          Index < Limit && (Gate = GateArray[Index]);            \
+          Index++ )
+
+// static functions
+static Super_Man_t *  Super_ManStart();
+static void           Super_ManStop( Super_Man_t * pMan );
+
+static void           Super_AddGateToTable( Super_Man_t * pMan, Super_Gate_t * pGate );
+static void           Super_First( Super_Man_t * pMan, int nVarsMax );
+static Super_Man_t *  Super_Compute( Super_Man_t * pMan, Mio_Gate_t ** ppGates, int nGates, int nGatesMax, int fSkipInv );
+static Super_Gate_t * Super_CreateGateNew( Super_Man_t * pMan, Mio_Gate_t * pRoot, Super_Gate_t ** pSupers, int nSupers, unsigned uTruth[], float Area, float tPinDelaysRes[], float tDelayMax, int nPins );
+static int            Super_CompareGates( Super_Man_t * pMan, unsigned uTruth[], float Area, float tPinDelaysRes[], int nPins );
+static int            Super_DelayCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 );
+static int            Super_AreaCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 );
+static void           Super_TranferGatesToArray( Super_Man_t * pMan );
+static int            Super_CheckTimeout( ProgressBar * pPro, Super_Man_t * pMan );
+ 
+static Vec_Str_t *    Super_Write( Super_Man_t * pMan );
+static int            Super_WriteCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 );
+static void           Super_WriteFileHeader( Super_Man_t * pMan, FILE * pFile );
+
+static void           Super_WriteLibrary( Super_Man_t * pMan );
+
+static void           Super_WriteLibraryTreeFile( Super_Man_t * pMan );
+static Vec_Str_t *    Super_WriteLibraryTreeStr( Super_Man_t * pMan );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Precomputes the library of supergates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Super_Precompute( Mio_Library_t * pLibGen, int nVarsMax, int nLevels, int nGatesMax, float tDelayMax, float tAreaMax, int TimeLimit, int fSkipInv, int fVerbose, char * pFileName )
+{
+    Vec_Str_t * vStr;
+    FILE * pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {     
+        printf( "Cannot open output file \"%s\".\n", pFileName );
+        return;
+    }
+    vStr = Super_PrecomputeStr( pLibGen, nVarsMax, nLevels, nGatesMax, tDelayMax, tAreaMax, TimeLimit, fSkipInv, fVerbose );
+    fwrite( Vec_StrArray(vStr), 1, Vec_StrSize(vStr), pFile );
+    fclose( pFile );
+    Vec_StrFree( vStr );
+    // report the result of writing
+    if ( fVerbose )
+    {
+        printf( "The supergates are written using new format \"%s\" ", pFileName );
+        printf( "(%0.3f MB).\n", ((double)Extra_FileSize(pFileName))/(1<<20) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Precomputes the library of supergates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Super_PrecomputeStr( Mio_Library_t * pLibGen, int nVarsMax, int nLevels, int nGatesMax, float tDelayMax, float tAreaMax, int TimeLimit, int fSkipInv, int fVerbose )
+{
+    Vec_Str_t * vStr;
+    Super_Man_t * pMan;
+    Mio_Gate_t ** ppGates;
+    int nGates, Level;
+    abctime clk, clockStart;
+
+    assert( nVarsMax < 7 );
+    if ( nGatesMax && nGatesMax < nVarsMax )
+    {
+        fprintf( stderr, "Erro! The number of supergates requested (%d) in less than the number of variables (%d).\n", nGatesMax, nVarsMax );
+        fprintf( stderr, "The library cannot be computed.\n" );
+        return NULL;
+    }
+
+    // get the root gates
+    ppGates = Mio_CollectRoots( pLibGen, nVarsMax, tDelayMax, 0, &nGates, fVerbose );
+    if ( nGatesMax && nGates >= nGatesMax )
+    {
+        fprintf( stdout, "Warning! Genlib library contains more gates than can be computed.\n");
+        fprintf( stdout, "Only one-gate supergates are included in the supergate library.\n" );
+    }
+
+    // start the manager
+    pMan = Super_ManStart();
+    pMan->pName     = Mio_LibraryReadName(pLibGen);
+    pMan->nGatesMax = nGatesMax;
+    pMan->fSkipInv  = fSkipInv;
+    pMan->tDelayMax = tDelayMax;
+    pMan->tAreaMax  = tAreaMax;
+    pMan->TimeLimit = TimeLimit; // in seconds
+    pMan->TimeStop  = TimeLimit ? TimeLimit * CLOCKS_PER_SEC + Abc_Clock() : 0; // in CPU ticks
+    pMan->fVerbose  = fVerbose;
+
+    if ( nGates == 0 )
+    {
+        fprintf( stderr, "Error: No genlib gates satisfy the limits criteria. Stop.\n");
+        fprintf( stderr, "Limits: max delay =  %.2f, max area =  %.2f, time limit = %d sec.\n", 
+            pMan->tDelayMax, pMan->tAreaMax, pMan->TimeLimit );
+
+        // stop the manager
+        Super_ManStop( pMan );
+        ABC_FREE( ppGates );
+
+        return NULL;
+    }
+
+    // get the starting supergates
+    Super_First( pMan, nVarsMax );
+
+    // perform the computation of supergates
+    clockStart = Abc_Clock();
+if ( fVerbose )
+{
+    printf( "Computing supergates with %d inputs, %d levels, and %d max gates.\n", 
+        pMan->nVarsMax, nLevels, nGatesMax );
+    printf( "Limits: max delay =  %.2f, max area =  %.2f, time limit = %d sec.\n", 
+        pMan->tDelayMax, pMan->tAreaMax, pMan->TimeLimit );
+}
+
+    for ( Level = 1; Level <= nLevels; Level++ )
+    {
+        if ( pMan->TimeStop && Abc_Clock() > pMan->TimeStop )
+            break;
+clk = Abc_Clock();
+        Super_Compute( pMan, ppGates, nGates, nGatesMax, fSkipInv );
+        pMan->nLevels = Level;
+if ( fVerbose )
+{
+        printf( "Lev %d: Try =%12d. Add =%6d. Rem =%5d. Save =%6d. Lookups =%12d. Aliases =%12d. ",
+           Level, pMan->nTried, pMan->nAdded, pMan->nRemoved, pMan->nAdded - pMan->nRemoved, pMan->nLookups, pMan->nAliases );
+ABC_PRT( "Time", Abc_Clock() - clk );
+fflush( stdout );
+}
+    }
+    pMan->Time = Abc_Clock() - clockStart;
+
+if ( fVerbose )
+{
+printf( "Writing the output file...\n" );
+fflush( stdout );
+}
+    // write them into a file
+    vStr = Super_Write( pMan );
+
+    // stop the manager
+    Super_ManStop( pMan );
+    ABC_FREE( ppGates );
+    return vStr;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the starting supergates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Super_First( Super_Man_t * pMan, int nVarsMax )
+{
+    Super_Gate_t * pSuper;
+    int nMintLimit, nVarLimit;
+    int v, m;
+    // set the parameters
+    pMan->nVarsMax  = nVarsMax;
+    pMan->nMints    = (1 << nVarsMax);
+    pMan->nLevels   = 0;
+    // allocate room for the gates
+    pMan->nGates    = nVarsMax;  
+    pMan->pGates    = ABC_ALLOC( Super_Gate_t *, nVarsMax + 2 ); 
+    // create the gates corresponding to the elementary variables
+    for ( v = 0; v < nVarsMax; v++ )
+    {
+        // get a new gate
+        pSuper = (Super_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem );
+        memset( pSuper, 0, sizeof(Super_Gate_t) );
+        // assign the elementary variable, the truth table, and the delays
+        pSuper->fVar = 1;
+        pSuper->Number = v;
+        for ( m = 0; m < nVarsMax; m++ )
+            pSuper->ptDelays[m] = SUPER_NO_VAR;
+        pSuper->ptDelays[v] = 0.0;
+        // set the gate
+        pMan->pGates[v] = pSuper;
+        Super_AddGateToTable( pMan, pSuper );
+        pMan->pInputs[v] = pSuper;
+    }
+    // set up their truth tables
+    nVarLimit  = (nVarsMax >= 5)? 5 : nVarsMax;
+    nMintLimit = (1 << nVarLimit);
+    for ( m = 0; m < nMintLimit; m++ )
+        for ( v = 0; v < nVarLimit; v++ )
+            if ( m & (1 << v) )
+                pMan->pGates[v]->uTruth[0] |= (1 << m);
+    // make adjustments for the case of 6 variables
+    if ( nVarsMax == 6 )
+    {
+        for ( v = 0; v < 5; v++ )
+            pMan->pGates[v]->uTruth[1] = pMan->pGates[v]->uTruth[0];
+        pMan->pGates[5]->uTruth[0] = 0;
+        pMan->pGates[5]->uTruth[1] = ~((unsigned)0);
+    }
+    else
+    {
+        for ( v = 0; v < nVarsMax; v++ )
+            pMan->pGates[v]->uTruth[1] = 0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Precomputes one level of supergates.]
+
+  Description [This procedure computes the set of supergates that can be
+  derived from the given set of root gates (from genlib library) by composing
+  the root gates with the currently available supergates. This procedure is
+  smart in the sense that it tries to avoid useless emuration by imposing
+  tight bounds by area and delay. Only the supergates and are guaranteed to 
+  have smaller area and delay are enumereated. See comments below for details.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Super_Man_t * Super_Compute( Super_Man_t * pMan, Mio_Gate_t ** ppGates, int nGates, int nGatesMax, int fSkipInv )
+{
+    Super_Gate_t * pSupers[6], * pGate0, * pGate1, * pGate2, * pGate3, * pGate4, * pGate5, * pGateNew;
+    float tPinDelaysRes[6], * ptPinDelays[6], tPinDelayMax, tDelayMio;
+    float Area = 0.0; // Suppress "might be used uninitialized"
+    float Area0, Area1, Area2, Area3, Area4, AreaMio;
+    unsigned uTruth[2], uTruths[6][2];
+    int i0, i1, i2, i3, i4, i5; 
+    Super_Gate_t ** ppGatesLimit;
+    int nFanins, nGatesLimit, k, s, t;
+    ProgressBar * pProgress;
+    int fTimeOut;
+    int fPrune = 1;                     // Shall we prune?
+    int iPruneLimit = 3;                // Each of the gates plugged into the root gate will have 
+                                        // less than these many fanins
+    int iPruneLimitRoot = 4;            // The root gate may have only less than these many fanins
+
+    // put the gates from the unique table into the array
+    // the gates from the array will be used to compose other gates
+    // the gates in tbe table are used to check uniqueness of collected gates
+    Super_TranferGatesToArray( pMan );
+
+    // sort the gates in the increasing order of maximum delay
+    if ( pMan->nGates > 10000 )
+    {
+        printf( "Sorting array of %d supergates...\r", pMan->nGates );
+        fflush( stdout );
+    }
+    qsort( (void *)pMan->pGates, pMan->nGates, sizeof(Super_Gate_t *), 
+            (int (*)(const void *, const void *)) Super_DelayCompare );
+    assert( Super_DelayCompare( pMan->pGates, pMan->pGates + pMan->nGates - 1 ) <= 0 );
+    if ( pMan->nGates > 10000 )
+    {
+        printf( "                                       \r" );
+    }
+
+    pProgress = Extra_ProgressBarStart( stdout, pMan->TimeLimit );
+    pMan->TimePrint = Abc_Clock() + CLOCKS_PER_SEC;
+    ppGatesLimit = ABC_ALLOC( Super_Gate_t *, pMan->nGates );
+    // go through the root gates
+    // the root gates are sorted in the increasing gelay
+    fTimeOut = 0;
+    for ( k = 0; k < nGates; k++ )
+    {
+        if ( fTimeOut ) break;
+
+        if ( fPrune )
+        {
+            if ( pMan->nLevels >= 1 )  // First level gates have been computed
+            {
+                if ( Mio_GateReadPinNum(ppGates[k]) >= iPruneLimitRoot )
+                    continue;
+            }
+        }
+/*
+        if ( strcmp(Mio_GateReadName(ppGates[k]), "MUX2IX0") == 0 )
+        {
+            int s = 0;
+        }
+*/
+        // select the subset of gates to be considered with this root gate
+        // all the gates past this point will lead to delay larger than the limit
+        tDelayMio = (float)Mio_GateReadDelayMax(ppGates[k]);
+        for ( s = 0, t = 0; s < pMan->nGates; s++ )
+        {
+            if ( fPrune && ( pMan->nLevels >= 1 ) && ( ((int)pMan->pGates[s]->nFanins) >= iPruneLimit ))
+                continue;
+            
+            ppGatesLimit[t] = pMan->pGates[s];
+            if ( ppGatesLimit[t++]->tDelayMax + tDelayMio > pMan->tDelayMax && pMan->tDelayMax > 0.0 )
+                break;
+        }
+        nGatesLimit = t;
+
+        if ( pMan->fVerbose )
+        {
+            printf ("Trying %d choices for %d inputs\r", t, Mio_GateReadPinNum(ppGates[k]) );
+        }
+
+        // resort part of this range by area
+        // now we can prune the search by going up in the list until we reach the limit on area
+        // all the gates beyond this point can be skipped because their area can be only larger
+        if ( nGatesLimit > 10000 )
+            printf( "Sorting array of %d supergates...\r", nGatesLimit );
+        qsort( (void *)ppGatesLimit, nGatesLimit, sizeof(Super_Gate_t *), 
+                (int (*)(const void *, const void *)) Super_AreaCompare );
+        assert( Super_AreaCompare( ppGatesLimit, ppGatesLimit + nGatesLimit - 1 ) <= 0 );
+        if ( nGatesLimit > 10000 )
+            printf( "                                       \r" );
+
+        // consider the combinations of gates with the root gate on top
+        AreaMio = (float)Mio_GateReadArea(ppGates[k]);
+        nFanins = Mio_GateReadPinNum(ppGates[k]);
+        switch ( nFanins )
+        {
+        case 0: // should not happen
+            assert( 0 ); 
+            break;
+        case 1: // interter root
+            Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 )
+            {
+              if ( fTimeOut ) break;
+              fTimeOut = Super_CheckTimeout( pProgress, pMan );
+              // skip the inverter as the root gate before the elementary variable
+              // as a result, the supergates will not have inverters on the input side
+              // but inverters still may occur at the output of or inside complex supergates
+              if ( fSkipInv && pGate0->tDelayMax == 0 )
+                  continue;
+              // compute area
+              Area = AreaMio + pGate0->Area;
+              if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax )
+                  break;
+
+              pSupers[0] = pGate0;  uTruths[0][0] = pGate0->uTruth[0];  uTruths[0][1] = pGate0->uTruth[1];  ptPinDelays[0] = pGate0->ptDelays; 
+              Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax );
+              Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth );
+              if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) )
+                  continue;
+              // create a new gate
+              pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax );
+              Super_AddGateToTable( pMan, pGateNew );
+              if ( nGatesMax && pMan->nClasses > nGatesMax )
+                  goto done;
+            }
+            break;
+        case 2: // two-input root gate
+            Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 )
+            {
+              Area0 = AreaMio + pGate0->Area;
+              if ( pMan->tAreaMax > 0.0 && Area0 > pMan->tAreaMax )
+                  break;
+              pSupers[0] = pGate0;  uTruths[0][0] = pGate0->uTruth[0];  uTruths[0][1] = pGate0->uTruth[1];  ptPinDelays[0] = pGate0->ptDelays; 
+              Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 )
+              if ( i1 != i0 )
+              {
+                if ( fTimeOut ) goto done;
+                fTimeOut = Super_CheckTimeout( pProgress, pMan );
+                // compute area
+                Area = Area0 + pGate1->Area;
+                if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax )
+                    break;
+
+                pSupers[1] = pGate1;  uTruths[1][0] = pGate1->uTruth[0];  uTruths[1][1] = pGate1->uTruth[1];  ptPinDelays[1] = pGate1->ptDelays;
+                Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax );
+                Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth );
+                if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) )
+                    continue;
+                // create a new gate
+                pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax );
+                Super_AddGateToTable( pMan, pGateNew );
+                if ( nGatesMax && pMan->nClasses > nGatesMax )
+                    goto done;
+              }
+            }
+            break;
+        case 3: // three-input root gate
+            Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 )
+            {
+              Area0 = AreaMio + pGate0->Area;
+              if ( pMan->tAreaMax > 0.0 && Area0 > pMan->tAreaMax )
+                  break;
+              pSupers[0] = pGate0;  uTruths[0][0] = pGate0->uTruth[0];  uTruths[0][1] = pGate0->uTruth[1];  ptPinDelays[0] = pGate0->ptDelays; 
+
+              Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 )
+              if ( i1 != i0 )
+              {
+                Area1 = Area0 + pGate1->Area;
+                if ( pMan->tAreaMax > 0.0 && Area1 > pMan->tAreaMax )
+                    break;
+                pSupers[1] = pGate1;  uTruths[1][0] = pGate1->uTruth[0];  uTruths[1][1] = pGate1->uTruth[1];  ptPinDelays[1] = pGate1->ptDelays;
+
+                Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 )
+                if ( i2 != i0 && i2 != i1 )
+                {
+                  if ( fTimeOut ) goto done;
+                  fTimeOut = Super_CheckTimeout( pProgress, pMan );
+                  // compute area
+                  Area = Area1 + pGate2->Area;
+                  if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax )
+                      break;
+                  pSupers[2] = pGate2;  uTruths[2][0] = pGate2->uTruth[0];  uTruths[2][1] = pGate2->uTruth[1];   ptPinDelays[2] = pGate2->ptDelays;
+
+                  Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax );
+                  Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth );
+                  if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) )
+                      continue;
+                  // create a new gate
+                  pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax );
+                  Super_AddGateToTable( pMan, pGateNew );
+                  if ( nGatesMax && pMan->nClasses > nGatesMax )
+                      goto done;
+                }
+              }
+            }
+            break;
+        case 4: // four-input root gate
+            Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 )
+            {
+              Area0 = AreaMio + pGate0->Area;
+              if ( pMan->tAreaMax > 0.0 && Area0 > pMan->tAreaMax )
+                  break;
+              pSupers[0] = pGate0;  uTruths[0][0] = pGate0->uTruth[0];  uTruths[0][1] = pGate0->uTruth[1];  ptPinDelays[0] = pGate0->ptDelays; 
+
+              Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 )
+              if ( i1 != i0 )
+              {
+                Area1 = Area0 + pGate1->Area;
+                if ( pMan->tAreaMax > 0.0 && Area1 > pMan->tAreaMax )
+                    break;
+                pSupers[1] = pGate1;  uTruths[1][0] = pGate1->uTruth[0];  uTruths[1][1] = pGate1->uTruth[1];  ptPinDelays[1] = pGate1->ptDelays;
+
+                Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 )
+                if ( i2 != i0 && i2 != i1 )
+                {
+                  Area2 = Area1 + pGate2->Area;
+                  if ( pMan->tAreaMax > 0.0 && Area2 > pMan->tAreaMax )
+                      break;
+                  pSupers[2] = pGate2;  uTruths[2][0] = pGate2->uTruth[0];  uTruths[2][1] = pGate2->uTruth[1];   ptPinDelays[2] = pGate2->ptDelays;
+
+                  Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 )
+                  if ( i3 != i0 && i3 != i1 && i3 != i2 )
+                  {
+                    if ( fTimeOut ) goto done;
+                    fTimeOut = Super_CheckTimeout( pProgress, pMan );
+                    // compute area
+                    Area = Area2 + pGate3->Area;
+                    if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax )
+                        break;
+                    pSupers[3] = pGate3;   uTruths[3][0] = pGate3->uTruth[0];  uTruths[3][1] = pGate3->uTruth[1];   ptPinDelays[3] = pGate3->ptDelays;
+
+                    Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax );
+                    Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth );
+                    if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) )
+                        continue;
+                    // create a new gate
+                    pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax );
+                    Super_AddGateToTable( pMan, pGateNew );
+                    if ( nGatesMax && pMan->nClasses > nGatesMax )
+                        goto done;
+                  }
+                }
+              }
+            }
+            break;
+        case 5: // five-input root gate
+            Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 )
+            {
+              Area0 = AreaMio + pGate0->Area;
+              if ( pMan->tAreaMax > 0.0 && Area0 > pMan->tAreaMax )
+                  break;
+              pSupers[0] = pGate0;  uTruths[0][0] = pGate0->uTruth[0];  uTruths[0][1] = pGate0->uTruth[1];  ptPinDelays[0] = pGate0->ptDelays; 
+
+              Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 )
+              if ( i1 != i0 )
+              {
+                Area1 = Area0 + pGate1->Area;
+                if ( pMan->tAreaMax > 0.0 && Area1 > pMan->tAreaMax )
+                    break;
+                pSupers[1] = pGate1;  uTruths[1][0] = pGate1->uTruth[0];  uTruths[1][1] = pGate1->uTruth[1];  ptPinDelays[1] = pGate1->ptDelays;
+
+                Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 )
+                if ( i2 != i0 && i2 != i1 )
+                {
+                  Area2 = Area1 + pGate2->Area;
+                  if ( pMan->tAreaMax > 0.0 && Area2 > pMan->tAreaMax )
+                      break;
+                  pSupers[2] = pGate2;  uTruths[2][0] = pGate2->uTruth[0];  uTruths[2][1] = pGate2->uTruth[1];   ptPinDelays[2] = pGate2->ptDelays;
+
+                  Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 )
+                  if ( i3 != i0 && i3 != i1 && i3 != i2 )
+                  {
+                    Area3 = Area2 + pGate3->Area;
+                    if ( pMan->tAreaMax > 0.0 && Area3 > pMan->tAreaMax )
+                        break;
+                    pSupers[3] = pGate3;   uTruths[3][0] = pGate3->uTruth[0];  uTruths[3][1] = pGate3->uTruth[1];   ptPinDelays[3] = pGate3->ptDelays;
+
+                    Super_ManForEachGate( ppGatesLimit, nGatesLimit, i4, pGate4 )
+                    if ( i4 != i0 && i4 != i1 && i4 != i2 && i4 != i3 )
+                    {
+                      if ( fTimeOut ) goto done;
+                      fTimeOut = Super_CheckTimeout( pProgress, pMan );
+                      // compute area
+                      Area = Area3 + pGate4->Area;
+                      if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax )
+                          break;
+                      pSupers[4] = pGate4;   uTruths[4][0] = pGate4->uTruth[0];  uTruths[4][1] = pGate4->uTruth[1];  ptPinDelays[4] = pGate4->ptDelays;
+
+                      Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax );
+                      Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth );
+                      if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) )
+                          continue;
+                      // create a new gate
+                      pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax );
+                      Super_AddGateToTable( pMan, pGateNew );
+                      if ( nGatesMax && pMan->nClasses > nGatesMax )
+                          goto done;
+                    }
+                  }
+                }
+              }
+            }
+            break;
+        case 6: // six-input root gate
+            Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 )
+            {
+              Area0 = AreaMio + pGate0->Area;
+              if ( pMan->tAreaMax > 0.0 && Area0 > pMan->tAreaMax )
+                  break;
+              pSupers[0] = pGate0;  uTruths[0][0] = pGate0->uTruth[0];  uTruths[0][1] = pGate0->uTruth[1];  ptPinDelays[0] = pGate0->ptDelays; 
+
+              Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 )
+              if ( i1 != i0 )
+              {
+                Area1 = Area0 + pGate1->Area;
+                if ( pMan->tAreaMax > 0.0 && Area1 > pMan->tAreaMax )
+                    break;
+                pSupers[1] = pGate1;  uTruths[1][0] = pGate1->uTruth[0];  uTruths[1][1] = pGate1->uTruth[1];  ptPinDelays[1] = pGate1->ptDelays;
+
+                Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 )
+                if ( i2 != i0 && i2 != i1 )
+                {
+                  Area2 = Area1 + pGate2->Area;
+                  if ( pMan->tAreaMax > 0.0 && Area2 > pMan->tAreaMax )
+                      break;
+                  pSupers[2] = pGate2;  uTruths[2][0] = pGate2->uTruth[0];  uTruths[2][1] = pGate2->uTruth[1];   ptPinDelays[2] = pGate2->ptDelays;
+
+                  Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 )
+                  if ( i3 != i0 && i3 != i1 && i3 != i2 )
+                  {
+                    Area3 = Area2 + pGate3->Area;
+                    if ( pMan->tAreaMax > 0.0 && Area3 > pMan->tAreaMax )
+                        break;
+                    pSupers[3] = pGate3;   uTruths[3][0] = pGate3->uTruth[0];  uTruths[3][1] = pGate3->uTruth[1];   ptPinDelays[3] = pGate3->ptDelays;
+
+                    Super_ManForEachGate( ppGatesLimit, nGatesLimit, i4, pGate4 )
+                    if ( i4 != i0 && i4 != i1 && i4 != i2 && i4 != i3 )
+                    {
+                      if ( fTimeOut ) break;
+                      fTimeOut = Super_CheckTimeout( pProgress, pMan );
+                      // compute area
+                      Area4 = Area3 + pGate4->Area;
+                      if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax )
+                          break;
+                      pSupers[4] = pGate4;   uTruths[4][0] = pGate4->uTruth[0];  uTruths[4][1] = pGate4->uTruth[1];  ptPinDelays[4] = pGate4->ptDelays;
+
+                      Super_ManForEachGate( ppGatesLimit, nGatesLimit, i5, pGate5 )
+                      if ( i5 != i0 && i5 != i1 && i5 != i2 && i5 != i3 && i5 != i4 )
+                      {
+                        if ( fTimeOut ) goto done;
+                        fTimeOut = Super_CheckTimeout( pProgress, pMan );
+                        // compute area
+                        Area = Area4 + pGate5->Area;
+                        if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax )
+                            break;
+                        pSupers[5] = pGate5;   uTruths[5][0] = pGate5->uTruth[0];  uTruths[5][1] = pGate5->uTruth[1];  ptPinDelays[5] = pGate5->ptDelays;
+
+                        Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax );
+                        Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth );
+                        if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) )
+                            continue;
+                        // create a new gate
+                        pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax );
+                        Super_AddGateToTable( pMan, pGateNew );
+                        if ( nGatesMax && pMan->nClasses > nGatesMax )
+                            goto done;
+                      }
+                    }
+                  }
+                }
+              }
+            }
+            break;
+        default :
+            assert( 0 );
+            break;
+        }
+    }
+done: 
+    Extra_ProgressBarStop( pProgress );
+    ABC_FREE( ppGatesLimit );
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers gates from table into the array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Super_CheckTimeout( ProgressBar * pPro, Super_Man_t * pMan )
+{
+    abctime TimeNow = Abc_Clock();
+    if ( TimeNow > pMan->TimePrint )
+    {
+        Extra_ProgressBarUpdate( pPro, ++pMan->TimeSec, NULL );
+        pMan->TimePrint = Abc_Clock() + CLOCKS_PER_SEC;
+    }
+    if ( pMan->TimeStop && TimeNow > pMan->TimeStop )
+    {
+        printf ("Timeout!\n");
+        return 1;
+    }
+    pMan->nTried++;
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers gates from table into the array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Super_TranferGatesToArray( Super_Man_t * pMan )
+{
+    stmm_generator * gen;
+    Super_Gate_t * pGate, * pList;
+    ABC_PTRUINT_T Key;
+
+    // put the gates fron the table into the array
+    ABC_FREE( pMan->pGates );
+    pMan->pGates = ABC_ALLOC( Super_Gate_t *, pMan->nAdded );
+    pMan->nGates = 0;
+    stmm_foreach_item( pMan->tTable, gen, (char **)&Key, (char **)&pList )
+    {
+        for ( pGate = pList; pGate; pGate = pGate->pNext )
+            pMan->pGates[ pMan->nGates++ ] = pGate;
+    }
+//    assert( pMan->nGates == pMan->nAdded - pMan->nRemoved );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one supergate into the unique table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Super_AddGateToTable( Super_Man_t * pMan, Super_Gate_t * pGate )
+{
+    Super_Gate_t ** ppList;
+    ABC_PTRUINT_T Key;
+//    Key = pGate->uTruth[0] + 2003 * pGate->uTruth[1];
+    Key = pGate->uTruth[0] ^ pGate->uTruth[1];
+    if ( !stmm_find_or_add( pMan->tTable, (char *)Key, (char ***)&ppList ) )
+    {
+        *ppList = NULL;
+        pMan->nClasses++;
+    }
+    pGate->pNext = *ppList;
+    *ppList = pGate;
+    pMan->nAdded++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check the manager's unique table for comparable gates.]
+
+  Description [Returns 0 if the gate is dominated by others. Returns 1 
+  if the gate is new or is better than the available ones. In this case, 
+  cleans the table by removing the gates that are worse than the given one.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Super_CompareGates( Super_Man_t * pMan, unsigned uTruth[], float Area, float tPinDelaysRes[], int nPins )
+{
+    Super_Gate_t ** ppList, * pPrev, * pGate, * pGate2;
+    int i, fNewIsBetter, fGateIsBetter;
+    ABC_PTRUINT_T Key;
+
+    // skip constant functions
+    if ( pMan->nVarsMax < 6 )
+    {
+        if ( uTruth[0] == 0 || ~uTruth[0] == 0 )
+            return 0;
+    }
+    else
+    {
+        if ( ( uTruth[0] == 0 && uTruth[1] == 0 ) || ( ~uTruth[0] == 0 && ~uTruth[1] == 0 ) )
+            return 0;
+    }
+
+    // get hold of the place where the entry is stored
+//    Key = uTruth[0] + 2003 * uTruth[1];
+    Key = uTruth[0] ^ uTruth[1];
+    if ( !stmm_find( pMan->tTable, (char *)Key, (char ***)&ppList ) )
+        return 1; 
+    // the entry with this truth table is found
+    pPrev = NULL;
+    for ( pGate = *ppList, pGate2 = pGate? pGate->pNext: NULL; pGate; 
+        pGate = pGate2, pGate2 = pGate? pGate->pNext: NULL )
+    {
+        pMan->nLookups++;
+        if ( pGate->uTruth[0] != uTruth[0] || pGate->uTruth[1] != uTruth[1] )
+        {
+            pMan->nAliases++;
+            continue;
+        }
+        fGateIsBetter = 0;
+        fNewIsBetter  = 0;
+        if ( pGate->Area + SUPER_EPSILON < Area )
+            fGateIsBetter = 1;
+        else if ( pGate->Area > Area + SUPER_EPSILON )
+            fNewIsBetter = 1;
+        for ( i = 0; i < nPins; i++ )
+        {
+            if ( pGate->ptDelays[i] == SUPER_NO_VAR || tPinDelaysRes[i] == SUPER_NO_VAR )
+                continue;
+            if ( pGate->ptDelays[i] + SUPER_EPSILON < tPinDelaysRes[i] )
+                fGateIsBetter = 1;
+            else if ( pGate->ptDelays[i] > tPinDelaysRes[i] + SUPER_EPSILON )
+                fNewIsBetter = 1;
+            if ( fGateIsBetter && fNewIsBetter )
+                break;
+        }
+        // consider 4 cases
+        if ( fGateIsBetter && fNewIsBetter ) // Pareto points; save both
+            pPrev = pGate;
+        else if ( fNewIsBetter ) // gate is worse; remove the gate
+        {
+            if ( pPrev == NULL )
+                *ppList = pGate->pNext;
+            else
+                pPrev->pNext = pGate->pNext;
+            Extra_MmFixedEntryRecycle( pMan->pMem, (char *)pGate );
+            pMan->nRemoved++;
+        }
+        else if ( fGateIsBetter ) // new is worse, already dominated no need to see others
+            return 0;
+        else // if ( !fGateIsBetter && !fNewIsBetter ) // they are identical, no need to see others
+            return 0;
+    }
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Create a new supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Super_Gate_t * Super_CreateGateNew( Super_Man_t * pMan, Mio_Gate_t * pRoot, Super_Gate_t ** pSupers, int nSupers, 
+    unsigned uTruth[], float Area, float tPinDelaysRes[], float tDelayMax, int nPins )
+{
+    Super_Gate_t * pSuper;
+    pSuper = (Super_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem );
+    memset( pSuper, 0, sizeof(Super_Gate_t) );
+    pSuper->pRoot     = pRoot;
+    pSuper->uTruth[0] = uTruth[0];
+    pSuper->uTruth[1] = uTruth[1];
+    memcpy( pSuper->ptDelays, tPinDelaysRes, sizeof(float) * nPins );
+    pSuper->Area      = Area;
+    pSuper->nFanins   = nSupers;
+    memcpy( pSuper->pFanins, pSupers, sizeof(Super_Gate_t *) * nSupers );
+    pSuper->pNext     = NULL;
+    pSuper->tDelayMax = tDelayMax;
+    return pSuper;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Super_Man_t * Super_ManStart()
+{
+    Super_Man_t * pMan;
+    pMan = ABC_CALLOC( Super_Man_t, 1 );
+    pMan->pMem     = Extra_MmFixedStart( sizeof(Super_Gate_t) );
+    pMan->tTable   = stmm_init_table( st__ptrcmp, st__ptrhash );
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Super_ManStop( Super_Man_t * pMan )
+{
+    Extra_MmFixedStop( pMan->pMem );
+    if ( pMan->tTable ) stmm_free_table( pMan->tTable );
+    ABC_FREE( pMan->pGates );
+    ABC_FREE( pMan );
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the supergate library into the file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Super_Write( Super_Man_t * pMan )
+{
+    Vec_Str_t * vStr;
+    Super_Gate_t * pGateRoot, * pGate;
+    stmm_generator * gen;
+    int fZeroFound, v;
+    abctime clk;
+    ABC_PTRUINT_T Key;
+
+    if ( pMan->nGates < 1 )
+    {
+        printf( "The generated library is empty. No output file written.\n" );
+        return NULL;
+    }
+
+    // Filters the supergates by removing those that have fewer inputs than 
+    // the given limit, provided that the inputs are not consequtive. 
+    // For example, NAND2(a,c) is removed, but NAND2(a,b) is left, 
+    // because a and b are consequtive.
+    ABC_FREE( pMan->pGates );
+    pMan->pGates = ABC_ALLOC( Super_Gate_t *, pMan->nAdded );
+    pMan->nGates = 0;
+    stmm_foreach_item( pMan->tTable, gen, (char **)&Key, (char **)&pGateRoot )
+    {
+        for ( pGate = pGateRoot; pGate; pGate = pGate->pNext )
+        {
+            // skip the elementary variables
+            if ( pGate->pRoot == NULL )
+                continue;
+            // skip the non-consequtive gates
+            fZeroFound = 0;
+            for ( v = 0; v < pMan->nVarsMax; v++ )
+                if ( pGate->ptDelays[v] < SUPER_NO_VAR + SUPER_EPSILON )
+                    fZeroFound = 1;
+                else if ( fZeroFound )
+                    break;
+            if ( v < pMan->nVarsMax )
+                continue;
+            // save the unique gate
+            pMan->pGates[ pMan->nGates++ ] = pGate;
+        }
+    }
+
+clk = Abc_Clock();
+    // sort the supergates by truth table
+    qsort( (void *)pMan->pGates, pMan->nGates, sizeof(Super_Gate_t *), 
+            (int (*)(const void *, const void *)) Super_WriteCompare );
+    assert( Super_WriteCompare( pMan->pGates, pMan->pGates + pMan->nGates - 1 ) <= 0 );
+if ( pMan->fVerbose )
+{
+ABC_PRT( "Sorting", Abc_Clock() - clk );
+}
+
+
+    // write library in the old format
+clk = Abc_Clock();
+    if ( pMan->fWriteOldFormat )
+        Super_WriteLibrary( pMan );
+if ( pMan->fVerbose )
+{
+ABC_PRT( "Writing old format", Abc_Clock() - clk );
+}
+
+    // write the tree-like structure of supergates
+clk = Abc_Clock();
+    vStr = Super_WriteLibraryTreeStr( pMan );
+if ( pMan->fVerbose )
+{
+ABC_PRT( "Writing new format", Abc_Clock() - clk );
+}
+    return vStr;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the file header.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Super_WriteFileHeader( Super_Man_t * pMan, FILE * pFile )
+{
+    fprintf( pFile, "#\n" );
+    fprintf( pFile, "# Supergate library derived for \"%s\" on %s.\n", pMan->pName, Extra_TimeStamp() );
+    fprintf( pFile, "#\n" );
+    fprintf( pFile, "# Command line: \"super -I %d -L %d -N %d -T %d -D %.2f -A %.2f %s %s\".\n", 
+        pMan->nVarsMax, pMan->nLevels, pMan->nGatesMax, pMan->TimeLimit, pMan->tDelayMax, pMan->tAreaMax, (pMan->fSkipInv? "" : "-s"), pMan->pName );
+    fprintf( pFile, "#\n" );
+    fprintf( pFile, "# The number of inputs      = %10d.\n", pMan->nVarsMax );
+    fprintf( pFile, "# The number of levels      = %10d.\n", pMan->nLevels );
+    fprintf( pFile, "# The maximum delay         = %10.2f.\n", pMan->tDelayMax  );
+    fprintf( pFile, "# The maximum area          = %10.2f.\n", pMan->tAreaMax );
+    fprintf( pFile, "# The maximum runtime (sec) = %10d.\n", pMan->TimeLimit );
+    fprintf( pFile, "#\n" );
+    fprintf( pFile, "# The number of attempts    = %10d.\n", pMan->nTried  );
+    fprintf( pFile, "# The number of supergates  = %10d.\n", pMan->nGates  );
+    fprintf( pFile, "# The number of functions   = %10d.\n", pMan->nUnique );
+    fprintf( pFile, "# The total functions       = %.0f (2^%d).\n", pow((double)2,pMan->nMints), pMan->nMints );
+    fprintf( pFile, "#\n" );
+    fprintf( pFile, "# Generation time           = %10.2f sec.\n", (float)(pMan->Time)/(float)(CLOCKS_PER_SEC) );
+    fprintf( pFile, "#\n" );
+    fprintf( pFile, "%s\n", pMan->pName );
+    fprintf( pFile, "%d\n", pMan->nVarsMax );
+    fprintf( pFile, "%d\n", pMan->nGates );
+}
+void Super_WriteFileHeaderStr( Super_Man_t * pMan, Vec_Str_t * vStr )
+{
+    char pBuffer[1000];
+    sprintf( pBuffer, "#\n" );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "# Supergate library derived for \"%s\" on %s.\n", pMan->pName, Extra_TimeStamp() );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "#\n" );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "# Command line: \"super -I %d -L %d -N %d -T %d -D %.2f -A %.2f %s %s\".\n", 
+        pMan->nVarsMax, pMan->nLevels, pMan->nGatesMax, pMan->TimeLimit, pMan->tDelayMax, pMan->tAreaMax, (pMan->fSkipInv? "" : "-s"), pMan->pName );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "#\n" );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "# The number of inputs      = %10d.\n", pMan->nVarsMax );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "# The number of levels      = %10d.\n", pMan->nLevels );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "# The maximum delay         = %10.2f.\n", pMan->tDelayMax  );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "# The maximum area          = %10.2f.\n", pMan->tAreaMax );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "# The maximum runtime (sec) = %10d.\n", pMan->TimeLimit );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "#\n" );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "# The number of attempts    = %10d.\n", pMan->nTried  );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "# The number of supergates  = %10d.\n", pMan->nGates  );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "# The number of functions   = %10d.\n", pMan->nUnique );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "# The total functions       = %.0f (2^%d).\n", pow((double)2,pMan->nMints), pMan->nMints );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "#\n" );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "# Generation time           = %10.2f sec.\n", (float)(pMan->Time)/(float)(CLOCKS_PER_SEC) );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "#\n" );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "%s\n", pMan->pName );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "%d\n", pMan->nVarsMax );
+    Vec_StrPrintStr( vStr, pBuffer );
+    sprintf( pBuffer, "%d\n", pMan->nGates );
+    Vec_StrPrintStr( vStr, pBuffer );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares two gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Super_WriteCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 )
+{
+    unsigned * pTruth1 = (*ppG1)->uTruth;
+    unsigned * pTruth2 = (*ppG2)->uTruth;
+    if ( pTruth1[1] < pTruth2[1] )
+        return -1;
+    if ( pTruth1[1] > pTruth2[1] )
+        return 1;
+    if ( pTruth1[0] < pTruth2[0] )
+        return -1;
+    if ( pTruth1[0] > pTruth2[0] )
+        return 1;
+    return 0;
+}
+int Super_DelayCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 )
+{
+    if ( (*ppG1)->tDelayMax < (*ppG2)->tDelayMax )
+        return -1;
+    if ( (*ppG1)->tDelayMax > (*ppG2)->tDelayMax )
+        return 1;
+    return 0;
+}
+int Super_AreaCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 )
+{
+    if ( (*ppG1)->Area < (*ppG2)->Area )
+        return -1;
+    if ( (*ppG1)->Area > (*ppG2)->Area )
+        return 1;
+    return 0;
+}
+
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the gates into the file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Super_WriteLibraryGateName_rec( Super_Gate_t * pGate, char * pBuffer )
+{
+    char Buffer[10];
+    int i;
+
+    if ( pGate->pRoot == NULL )
+    {
+        sprintf( Buffer, "%c", 'a' + pGate->Number );
+        strcat( pBuffer, Buffer );
+        return;
+    }
+    strcat( pBuffer, Mio_GateReadName(pGate->pRoot) );
+    strcat( pBuffer, "(" );
+    for ( i = 0; i < (int)pGate->nFanins; i++ )
+    {
+        if ( i )
+            strcat( pBuffer, "," );
+        Super_WriteLibraryGateName_rec( pGate->pFanins[i], pBuffer );
+    }
+    strcat( pBuffer, ")" );
+}
+char * Super_WriteLibraryGateName( Super_Gate_t * pGate )
+{
+    static char Buffer[2000];
+    Buffer[0] = 0;
+    Super_WriteLibraryGateName_rec( pGate, Buffer );
+    return Buffer;
+}
+void Super_WriteLibraryGate( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pGate, int Num )
+{
+    int i;
+    fprintf( pFile, "%04d  ", Num );                         // the number
+    Extra_PrintBinary( pFile, pGate->uTruth, pMan->nMints ); // the truth table
+    fprintf( pFile, "   %5.2f", pGate->tDelayMax );          // the max delay
+    fprintf( pFile, "  " );                                  
+    for ( i = 0; i < pMan->nVarsMax; i++ )                   // the pin-to-pin delays
+        fprintf( pFile, " %5.2f", pGate->ptDelays[i]==SUPER_NO_VAR? 0.0 : pGate->ptDelays[i] );  
+    fprintf( pFile, "   %5.2f", pGate->Area );               // the area
+    fprintf( pFile, "   " );
+    fprintf( pFile, "%s", Super_WriteLibraryGateName(pGate) );      // the symbolic expression
+    fprintf( pFile, "\n" );
+}
+void Super_WriteLibrary( Super_Man_t * pMan )
+{
+    Super_Gate_t * pGate, * pGateNext;
+    FILE * pFile;
+    char * FileName;
+    char * pNameGeneric;
+    int i, Counter;
+
+    FileName = ABC_ALLOC( char, 10000 );
+
+    // get the file name
+    pNameGeneric = Extra_FileNameGeneric( pMan->pName );
+    sprintf( FileName, "%s.super_old", pNameGeneric );
+    ABC_FREE( pNameGeneric );
+
+    // count the number of unique functions
+    pMan->nUnique = 1;
+    Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pGate )
+    {
+        if ( i == pMan->nGates - 1 )
+            break;
+        // print the newline if this gate is different from the following one
+        pGateNext = pMan->pGates[i+1];
+        if ( pGateNext->uTruth[0] != pGate->uTruth[0] || pGateNext->uTruth[1] != pGate->uTruth[1] )
+            pMan->nUnique++;
+    }
+
+    // start the file
+    pFile = fopen( FileName, "w" );
+    Super_WriteFileHeader( pMan, pFile );
+
+    // print the gates
+    Counter = 0;
+    Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pGate )
+    {
+        Super_WriteLibraryGate( pFile, pMan, pGate, ++Counter );
+        if ( i == pMan->nGates - 1 )
+            break;
+        // print the newline if this gate is different from the following one
+        pGateNext = pMan->pGates[i+1];
+        if ( pGateNext->uTruth[0] != pGate->uTruth[0] || pGateNext->uTruth[1] != pGate->uTruth[1] )
+            fprintf( pFile, "\n" );
+    }
+    assert( Counter == pMan->nGates );
+    fclose( pFile );
+
+    if ( pMan->fVerbose )
+    {
+        printf( "The supergates are written using old format \"%s\" ", FileName );
+        printf( "(%0.3f MB).\n", ((double)Extra_FileSize(FileName))/(1<<20) );
+    }
+
+    ABC_FREE( FileName );
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively writes the gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Super_WriteLibraryTreeFile_rec( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pSuper, int * pCounter )
+{
+    int nFanins, i;
+    // skip an elementary variable and a gate that was already written
+    if ( pSuper->fVar || pSuper->Number > 0 )
+        return;
+    // write the fanins
+    nFanins = Mio_GateReadPinNum(pSuper->pRoot);
+    for ( i = 0; i < nFanins; i++ )
+        Super_WriteLibraryTreeFile_rec( pFile, pMan, pSuper->pFanins[i], pCounter );
+    // finally write the gate
+    pSuper->Number = (*pCounter)++;
+    fprintf( pFile, "%s", pSuper->fSuper? "* " : "" );
+    fprintf( pFile, "%s", Mio_GateReadName(pSuper->pRoot) );
+    for ( i = 0; i < nFanins; i++ )
+        fprintf( pFile, " %d", pSuper->pFanins[i]->Number );
+    // write the formula 
+    // this step is optional, the resulting library will work in any case
+    // however, it may be helpful to for debugging to compare the same library 
+    // written in the old format and written in the new format with formulas
+//    fprintf( pFile, "    # %s", Super_WriteLibraryGateName( pSuper ) );
+    fprintf( pFile, "\n" );
+}
+void Super_WriteLibraryTreeFile( Super_Man_t * pMan )
+{
+    Super_Gate_t * pSuper;
+    FILE * pFile;
+    char * FileName;
+    char * pNameGeneric;
+    int i, Counter;
+    int posStart;
+
+    FileName = ABC_ALLOC( char, 10000 );
+
+    // get the file name
+    pNameGeneric = Extra_FileNameGeneric( pMan->pName );
+    sprintf( FileName, "%s.super", pNameGeneric );
+    ABC_FREE( pNameGeneric );
+ 
+    // write the elementary variables
+    pFile = fopen( FileName, "wb" );
+    Super_WriteFileHeader( pMan, pFile );
+    // write the place holder for the number of lines
+    posStart = ftell( pFile );
+    fprintf( pFile, "         \n" );
+    // mark the real supergates
+    Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper )
+        pSuper->fSuper = 1;
+    // write the supergates
+    Counter = pMan->nVarsMax;
+    Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper )
+        Super_WriteLibraryTreeFile_rec( pFile, pMan, pSuper, &Counter );
+    fclose( pFile );
+    // write the number of lines
+    pFile = fopen( FileName, "rb+" );
+    fseek( pFile, posStart, SEEK_SET );
+    fprintf( pFile, "%d", Counter );
+    fclose( pFile );
+
+if ( pMan->fVerbose )
+{
+    printf( "The supergates are written using new format \"%s\" ", FileName );
+    printf( "(%0.3f MB).\n", ((double)Extra_FileSize(FileName))/(1<<20) );
+}
+
+    ABC_FREE( FileName );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively writes the gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Super_WriteLibraryTreeStr_rec( Vec_Str_t * vStr, Super_Man_t * pMan, Super_Gate_t * pSuper, int * pCounter )
+{
+    int nFanins, i;
+    // skip an elementary variable and a gate that was already written
+    if ( pSuper->fVar || pSuper->Number > 0 )
+        return;
+    // write the fanins
+    nFanins = Mio_GateReadPinNum(pSuper->pRoot);
+    for ( i = 0; i < nFanins; i++ )
+        Super_WriteLibraryTreeStr_rec( vStr, pMan, pSuper->pFanins[i], pCounter );
+    // finally write the gate
+    pSuper->Number = (*pCounter)++;
+//    fprintf( pFile, "%s", pSuper->fSuper? "* " : "" );
+//    fprintf( pFile, "%s", Mio_GateReadName(pSuper->pRoot) );
+//    for ( i = 0; i < nFanins; i++ )
+//        fprintf( pFile, " %d", pSuper->pFanins[i]->Number );
+    Vec_StrPrintStr( vStr, pSuper->fSuper? "* " : "" );
+    Vec_StrPrintStr( vStr, Mio_GateReadName(pSuper->pRoot) );
+    for ( i = 0; i < nFanins; i++ )
+    {
+        Vec_StrPrintStr( vStr, " " );
+        Vec_StrPrintNum( vStr, pSuper->pFanins[i]->Number );    
+    }
+    // write the formula 
+    // this step is optional, the resulting library will work in any case
+    // however, it may be helpful to for debugging to compare the same library 
+    // written in the old format and written in the new format with formulas
+//    fprintf( pFile, "    # %s", Super_WriteLibraryGateName( pSuper ) );
+//    fprintf( pFile, "\n" );
+    Vec_StrPrintStr( vStr, "\n" );
+}
+Vec_Str_t * Super_WriteLibraryTreeStr( Super_Man_t * pMan )
+{
+    char pInsert[16];
+    Vec_Str_t * vStr;
+    Super_Gate_t * pSuper;
+    int i, Counter;
+    int posStart;
+     // write the elementary variables
+    vStr = Vec_StrAlloc( 1000 );
+    Super_WriteFileHeaderStr( pMan, vStr );
+    // write the place holder for the number of lines
+    posStart = Vec_StrSize( vStr );
+    for ( i = 0; i < 9; i++ )
+        Vec_StrPush( vStr, ' ' );
+    Vec_StrPush( vStr, '\n' );
+    // mark the real supergates
+    Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper )
+        pSuper->fSuper = 1;
+    // write the supergates
+    Counter = pMan->nVarsMax;
+    Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper )
+        Super_WriteLibraryTreeStr_rec( vStr, pMan, pSuper, &Counter );
+    Vec_StrPush( vStr, 0 );
+    // write the number of lines
+    sprintf( pInsert, "%d", Counter );
+    for ( i = 0; i < (int)strlen(pInsert); i++ )
+        Vec_StrWriteEntry( vStr, posStart + i, pInsert[i] );
+    return vStr;
+}
+void Super_WriteLibraryTree( Super_Man_t * pMan )
+{
+    Vec_Str_t * vStr;
+    char * pFileName = Extra_FileNameGenericAppend( pMan->pName, ".super" );
+    FILE * pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {     
+        printf( "Cannot open output file \"%s\".\n", pFileName );
+        return;
+    }
+    vStr = Super_WriteLibraryTreeStr( pMan );
+    fwrite( Vec_StrArray(vStr), 1, Vec_StrSize(vStr), pFile );
+    fclose( pFile );
+    Vec_StrFree( vStr );
+    // report the result of writing
+    if ( pMan->fVerbose )
+    {
+        printf( "The supergates are written using new format \"%s\" ", pFileName );
+        printf( "(%0.3f MB).\n", ((double)Extra_FileSize(pFileName))/(1<<20) );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/map/super/superInt.h b/abc-build/src/map/super/superInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/super/superInt.h
@@ -0,0 +1,64 @@
+/**CFile****************************************************************
+
+  FileName    [superInt.h]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Pre-computation of supergates.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: superInt.h,v 1.4 2004/07/06 04:55:59 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__map__super__superInt_h
+#define ABC__map__super__superInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "base/abc/abc.h"
+#include "base/main/mainInt.h"
+#include "misc/mvc/mvc.h"
+#include "map/mio/mio.h"
+#include "misc/st/stmm.h"
+#include "super.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/map/super/superWrite.c b/abc-build/src/map/super/superWrite.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/map/super/superWrite.c
@@ -0,0 +1,81 @@
+/**CFile****************************************************************
+
+  FileName    [superWrite.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Pre-computation of supergates.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 8, 2003.]
+
+  Revision    [$Id: superWrite.c,v 1.1 2004/04/03 01:36:45 alanmi Exp $]
+
+***********************************************************************/
+
+#include "superInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+    One record in the supergate library file consists of:
+
+	<gate_number> <truth_table> <delay_max> <pin-to-pin-delays> <area> <gate_formula>
+
+	<gate_number>       is a zero-based integer
+	<truth_table>       is a string of 2^n bits representing the value of the function for each minterm
+	<delay_max>         is the maximum delay of the gate
+	<pin-to-pin-delays> is the array of n double values
+	<area>              is a floating point value
+	<gate_formula>      is the string representing the gate in the following format:
+		GATENAME1( GATENAME2( a, c ), GATENAME3( a, d ), ... )
+		The gate names (GATENAME1, etc) are the names as they appear in the .genlib library.
+		The primary inputs of the gates are denoted by lowercase chars 'a', 'b', etc.
+		The parantheses are mandatory for each gate, except for the wire. 
+		The wire name can be omitted, so that "a" can be used instead of "**wire**( a )".
+		The spaces are optional in any position of this string.
+
+
+    The supergates are generated exhaustively from all gate combinations that
+	have the max delay lower than the delay given by the user, or until the specified time
+	limit is reached.
+
+    The supergates are stored in supergate classes by their functionality. 
+	Among the gates with the equivalent functionaly only those are dropped, which are
+	dominated by at least one other gate in the class in terms of both delay and area.
+	For the definition of gate dominance see pliGenCheckDominance().
+*/
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/avl/avl.c b/abc-build/src/misc/avl/avl.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/avl/avl.c
@@ -0,0 +1,621 @@
+/*
+ * Revision Control Information
+ *
+ * $Source: /vol/opua/opua2/sis/sis-1.2/common/src/sis/avl/RCS/avl.c,v $
+ * $Author: sis $
+ * $Revision: 1.3 $
+ * $Date: 1994/07/15 23:00:40 $
+ *
+ */
+/* LINTLIBRARY */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "avl.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+
+#define HEIGHT(node) (node == NIL(avl_node) ? -1 : (node)->height)
+#define BALANCE(node) (HEIGHT((node)->right) - HEIGHT((node)->left))
+
+#define compute_height(node) {				\
+    int x=HEIGHT(node->left), y=HEIGHT(node->right);	\
+    (node)->height = MAX(x,y) + 1;			\
+}
+
+#define COMPARE(key, nodekey, compare)	 		\
+    ((compare == avl_numcmp) ? 				\
+	(int) key - (int) nodekey : 			\
+	(*compare)(key, nodekey))
+
+
+#define STACK_SIZE	50
+
+static avl_node *new_node ();
+static avl_node *find_rightmost ();
+static void do_rebalance ();
+static rotate_left ();
+static rotate_right ();
+static int do_check_tree ();
+
+avl_tree *
+avl_init_table (compar)
+ int (*compar) ();
+{
+	avl_tree *tree;
+
+	tree = ALLOC (avl_tree, 1);
+	tree->root = NIL (avl_node);
+	tree->compar = compar;
+	tree->num_entries = 0;
+	return tree;
+}
+
+
+
+avl_lookup (tree, key, value_p)
+ avl_tree *tree;
+ register char *key;
+ char **value_p;
+{
+	register avl_node *node;
+	register int (*compare) () = tree->compar, diff;
+
+	node = tree->root;
+	while (node != NIL (avl_node))
+	{
+		diff = COMPARE (key, node->key, compare);
+		if (diff == 0)
+		{
+			/* got a match */
+			if (value_p != NIL (char *))
+				 *value_p = node->value;
+			return 1;
+		}
+		node = (diff < 0) ? node->left : node->right;
+	}
+	return 0;
+}
+
+avl_first (tree, key_p, value_p)
+ avl_tree *tree;
+ char **key_p;
+ char **value_p;
+{
+	register avl_node *node;
+
+	if (tree->root == 0)
+	{
+		return 0;				/* no entries */
+	}
+	else
+	{
+		/* walk down the tree; stop at leftmost leaf */
+		for (node = tree->root; node->left != 0; node = node->left)
+		{
+		}
+		if (key_p != NIL (char *))
+			 *key_p = node->key;
+		if (value_p != NIL (char *))
+			 *value_p = node->value;
+		return 1;
+	}
+}
+
+
+avl_last (tree, key_p, value_p)
+ avl_tree *tree;
+ char **key_p;
+ char **value_p;
+{
+	register avl_node *node;
+
+	if (tree->root == 0)
+	{
+		return 0;				/* no entries */
+	}
+	else
+	{
+		/* walk down the tree; stop at rightmost leaf */
+		for (node = tree->root; node->right != 0; node = node->right)
+		{
+		}
+		if (key_p != NIL (char *))
+			 *key_p = node->key;
+		if (value_p != NIL (char *))
+			 *value_p = node->value;
+		return 1;
+	}
+}
+
+avl_insert (tree, key, value)
+ avl_tree *tree;
+ char *key;
+ char *value;
+{
+	register avl_node **node_p, *node;
+	register int stack_n = 0;
+	register int (*compare) () = tree->compar;
+	avl_node **stack_nodep[STACK_SIZE];
+	int diff, status;
+
+	node_p = &tree->root;
+
+	/* walk down the tree (saving the path); stop at insertion point */
+	status = 0;
+	while ((node = *node_p) != NIL (avl_node))
+	{
+		stack_nodep[stack_n++] = node_p;
+		diff = COMPARE (key, node->key, compare);
+		if (diff == 0)
+			status = 1;
+		node_p = (diff < 0) ? &node->left : &node->right;
+	}
+
+	/* insert the item and re-balance the tree */
+	*node_p = new_node (key, value);
+	do_rebalance (stack_nodep, stack_n);
+	tree->num_entries++;
+	tree->modified = 1;
+	return status;
+}
+
+
+
+avl_find_or_add (tree, key, slot_p)
+ avl_tree *tree;
+ char *key;
+ char ***slot_p;
+{
+	register avl_node **node_p, *node;
+	register int stack_n = 0;
+	register int (*compare) () = tree->compar;
+	avl_node **stack_nodep[STACK_SIZE];
+	int diff;
+
+	node_p = &tree->root;
+
+	/* walk down the tree (saving the path); stop at insertion point */
+	while ((node = *node_p) != NIL (avl_node))
+	{
+		stack_nodep[stack_n++] = node_p;
+		diff = COMPARE (key, node->key, compare);
+		if (diff == 0)
+		{
+			if (slot_p != 0)
+				*slot_p = &node->value;
+			return 1;			/* found */
+		}
+		node_p = (diff < 0) ? &node->left : &node->right;
+	}
+
+	/* insert the item and re-balance the tree */
+	*node_p = new_node (key, NIL (char));
+	if (slot_p != 0)
+		*slot_p = &(*node_p)->value;
+	do_rebalance (stack_nodep, stack_n);
+	tree->num_entries++;
+	tree->modified = 1;
+	return 0;					/* not already in tree */
+}
+
+avl_delete (tree, key_p, value_p)
+ avl_tree *tree;
+ char **key_p;
+ char **value_p;
+{
+	register avl_node **node_p, *node, *rightmost;
+	register int stack_n = 0;
+	char *key = *key_p;
+	int (*compare) () = tree->compar, diff;
+	avl_node **stack_nodep[STACK_SIZE];
+
+	node_p = &tree->root;
+
+	/* Walk down the tree saving the path; return if not found */
+	while ((node = *node_p) != NIL (avl_node))
+	{
+		diff = COMPARE (key, node->key, compare);
+		if (diff == 0)
+			goto delete_item;
+		stack_nodep[stack_n++] = node_p;
+		node_p = (diff < 0) ? &node->left : &node->right;
+	}
+	return 0;					/* not found */
+
+	/* prepare to delete node and replace it with rightmost of left tree */
+  delete_item:
+	*key_p = node->key;
+	if (value_p != 0)
+		*value_p = node->value;
+	if (node->left == NIL (avl_node))
+	{
+		*node_p = node->right;
+	}
+	else
+	{
+		rightmost = find_rightmost (&node->left);
+		rightmost->left = node->left;
+		rightmost->right = node->right;
+		rightmost->height = -2;	/* mark bogus height for do_rebal */
+		*node_p = rightmost;
+		stack_nodep[stack_n++] = node_p;
+	}
+	FREE (node);
+
+	/* work our way back up, re-balancing the tree */
+	do_rebalance (stack_nodep, stack_n);
+	tree->num_entries--;
+	tree->modified = 1;
+	return 1;
+}
+
+static void
+avl_record_gen_forward (node, gen)
+ avl_node *node;
+ avl_generator *gen;
+{
+	if (node != NIL (avl_node))
+	{
+		avl_record_gen_forward (node->left, gen);
+		gen->nodelist[gen->count++] = node;
+		avl_record_gen_forward (node->right, gen);
+	}
+}
+
+
+static void
+avl_record_gen_backward (node, gen)
+ avl_node *node;
+ avl_generator *gen;
+{
+	if (node != NIL (avl_node))
+	{
+		avl_record_gen_backward (node->right, gen);
+		gen->nodelist[gen->count++] = node;
+		avl_record_gen_backward (node->left, gen);
+	}
+}
+
+
+avl_generator *
+avl_init_gen (tree, dir)
+ avl_tree *tree;
+ int dir;
+{
+	avl_generator *gen;
+
+	/* what a hack */
+	gen = ALLOC (avl_generator, 1);
+	gen->tree = tree;
+	gen->nodelist = ALLOC (avl_node *, avl_count (tree));
+	gen->count = 0;
+	if (dir == AVL_FORWARD)
+	{
+		avl_record_gen_forward (tree->root, gen);
+	}
+	else
+	{
+		avl_record_gen_backward (tree->root, gen);
+	}
+	gen->count = 0;
+
+	/* catch any attempt to modify the tree while we generate */
+	tree->modified = 0;
+	return gen;
+}
+
+
+avl_gen (gen, key_p, value_p)
+ avl_generator *gen;
+ char **key_p;
+ char **value_p;
+{
+	avl_node *node;
+
+	if (gen->count == gen->tree->num_entries)
+	{
+		return 0;
+	}
+	else
+	{
+		node = gen->nodelist[gen->count++];
+		if (key_p != NIL (char *))
+			 *key_p = node->key;
+		if (value_p != NIL (char *))
+			 *value_p = node->value;
+		return 1;
+	}
+}
+
+
+void
+avl_free_gen (gen)
+ avl_generator *gen;
+{
+	FREE (gen->nodelist);
+	FREE (gen);
+}
+
+static avl_node *
+find_rightmost (node_p)
+ register avl_node **node_p;
+{
+	register avl_node *node;
+	register int stack_n = 0;
+	avl_node **stack_nodep[STACK_SIZE];
+
+	node = *node_p;
+	while (node->right != NIL (avl_node))
+	{
+		stack_nodep[stack_n++] = node_p;
+		node_p = &node->right;
+		node = *node_p;
+	}
+	*node_p = node->left;
+
+	do_rebalance (stack_nodep, stack_n);
+	return node;
+}
+
+
+static void
+do_rebalance (stack_nodep, stack_n)
+ register avl_node ***stack_nodep;
+ register int stack_n;
+{
+	register avl_node **node_p, *node;
+	register int hl, hr;
+	int height;
+
+	/* work our way back up, re-balancing the tree */
+	while (--stack_n >= 0)
+	{
+		node_p = stack_nodep[stack_n];
+		node = *node_p;
+		hl = HEIGHT (node->left);	/* watch for NIL */
+		hr = HEIGHT (node->right);	/* watch for NIL */
+		if ((hr - hl) < -1)
+		{
+			rotate_right (node_p);
+		}
+		else if ((hr - hl) > 1)
+		{
+			rotate_left (node_p);
+		}
+		else
+		{
+			height = MAX (hl, hr) + 1;
+			if (height == node->height)
+				break;
+			node->height = height;
+		}
+	}
+}
+
+static
+rotate_left (node_p)
+ register avl_node **node_p;
+{
+	register avl_node *old_root = *node_p, *new_root, *new_right;
+
+	if (BALANCE (old_root->right) >= 0)
+	{
+		*node_p = new_root = old_root->right;
+		old_root->right = new_root->left;
+		new_root->left = old_root;
+	}
+	else
+	{
+		new_right = old_root->right;
+		*node_p = new_root = new_right->left;
+		old_root->right = new_root->left;
+		new_right->left = new_root->right;
+		new_root->right = new_right;
+		new_root->left = old_root;
+		compute_height (new_right);
+	}
+	compute_height (old_root);
+	compute_height (new_root);
+}
+
+
+static
+rotate_right (node_p)
+ avl_node **node_p;
+{
+	register avl_node *old_root = *node_p, *new_root, *new_left;
+
+	if (BALANCE (old_root->left) <= 0)
+	{
+		*node_p = new_root = old_root->left;
+		old_root->left = new_root->right;
+		new_root->right = old_root;
+	}
+	else
+	{
+		new_left = old_root->left;
+		*node_p = new_root = new_left->right;
+		old_root->left = new_root->right;
+		new_left->right = new_root->left;
+		new_root->left = new_left;
+		new_root->right = old_root;
+		compute_height (new_left);
+	}
+	compute_height (old_root);
+	compute_height (new_root);
+}
+
+static void
+avl_walk_forward (node, func)
+ avl_node *node;
+ void (*func) ();
+{
+	if (node != NIL (avl_node))
+	{
+		avl_walk_forward (node->left, func);
+		(*func) (node->key, node->value);
+		avl_walk_forward (node->right, func);
+	}
+}
+
+
+static void
+avl_walk_backward (node, func)
+ avl_node *node;
+ void (*func) ();
+{
+	if (node != NIL (avl_node))
+	{
+		avl_walk_backward (node->right, func);
+		(*func) (node->key, node->value);
+		avl_walk_backward (node->left, func);
+	}
+}
+
+
+void
+avl_foreach (tree, func, direction)
+ avl_tree *tree;
+ void (*func) ();
+ int direction;
+{
+	if (direction == AVL_FORWARD)
+	{
+		avl_walk_forward (tree->root, func);
+	}
+	else
+	{
+		avl_walk_backward (tree->root, func);
+	}
+}
+
+
+static void
+free_entry (node, key_free, value_free)
+ avl_node *node;
+ void (*key_free) ();
+ void (*value_free) ();
+{
+	if (node != NIL (avl_node))
+	{
+		free_entry (node->left, key_free, value_free);
+		free_entry (node->right, key_free, value_free);
+		if (key_free != 0)
+			(*key_free) (node->key);
+		if (value_free != 0)
+			(*value_free) (node->value);
+		FREE (node);
+	}
+}
+
+
+void
+avl_free_table (tree, key_free, value_free)
+ avl_tree *tree;
+ void (*key_free) ();
+ void (*value_free) ();
+{
+	free_entry (tree->root, key_free, value_free);
+	FREE (tree);
+}
+
+
+int
+avl_count (tree)
+ avl_tree *tree;
+{
+	return tree->num_entries;
+}
+
+static avl_node *
+new_node (key, value)
+ char *key;
+ char *value;
+{
+	register avl_node *new;
+
+	new = ALLOC (avl_node, 1);
+	new->key = key;
+	new->value = value;
+	new->height = 0;
+	new->left = new->right = NIL (avl_node);
+	return new;
+}
+
+
+int
+avl_numcmp (x, y)
+ char *x, *y;
+{
+	return (int) x - (int) y;
+}
+
+int
+avl_check_tree (tree)
+ avl_tree *tree;
+{
+	int error = 0;
+	(void) do_check_tree (tree->root, tree->compar, &error);
+	return error;
+}
+
+
+static int
+do_check_tree (node, compar, error)
+ avl_node *node;
+ int (*compar) ();
+ int *error;
+{
+	int l_height, r_height, comp_height, bal;
+
+	if (node == NIL (avl_node))
+	{
+		return -1;
+	}
+
+	r_height = do_check_tree (node->right, compar, error);
+	l_height = do_check_tree (node->left, compar, error);
+
+	comp_height = MAX (l_height, r_height) + 1;
+	bal = r_height - l_height;
+
+	if (comp_height != node->height)
+	{
+		(void) printf ("Bad height for 0x%08x: computed=%d stored=%d\n",
+					   node, comp_height, node->height);
+		++*error;
+	}
+
+	if (bal > 1 || bal < -1)
+	{
+		(void) printf ("Out of balance at node 0x%08x, balance = %d\n",
+					   node, bal);
+		++*error;
+	}
+
+	if (node->left != NIL (avl_node) &&
+		(*compar) (node->left->key, node->key) > 0)
+	{
+		(void) printf ("Bad ordering between 0x%08x and 0x%08x",
+					   node, node->left);
+		++*error;
+	}
+
+	if (node->right != NIL (avl_node) &&
+		(*compar) (node->key, node->right->key) > 0)
+	{
+		(void) printf ("Bad ordering between 0x%08x and 0x%08x",
+					   node, node->right);
+		++*error;
+	}
+
+	return comp_height;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/avl/avl.doc b/abc-build/src/misc/avl/avl.doc
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/avl/avl.doc
@@ -0,0 +1,166 @@
+/*
+ * Revision Control Information
+ *
+ * /projects/hsis/CVS/utilities/avl/avl.doc,v
+ * rajeev
+ * 1.3
+ * 1995/08/08 22:36:22
+ *
+ */
+avl_tree *
+avl_init_table(compare)
+int (*compare)();
+	Initialize and return a new avl_tree.  Use the function `compare' to
+	compare items in the tree.  `compare' should be of the form:
+
+		int
+		compare(a,b)
+		char *a, *b;
+
+	and return a number < 0, == 0, > 0 depending on whether a < b,
+	a == b, or a > b, respectively.
+
+
+void
+avl_free_table(tree, key_delete_func, value_delete_func)
+avl_tree *tree;
+void (*key_delete_func)();
+void (*value_delete_func)();
+
+	Delete all storage associated with `tree'.  The functions 
+	key_delete_func and value_delete_func, if non-null, are called
+	to free each (key, value) pair.  They are declared as:
+
+		void
+		key_delete_func(key)
+		char *key;
+		{}
+
+		void
+		value_delete_func(value)
+		char *value;
+		{}
+
+	The C-library function free is often suitable as a free function.
+
+
+avl_first(tree, key_p, value_p)
+avl_tree *tree;
+char **key_p;
+char **value_p;
+	Retrieves the smallest element in the tree.  Returns 0 if there
+	are no elements in the tree.
+
+
+avl_last(tree, key_p, value_p)
+avl_tree *tree;
+char **key_p;
+char **value_p;
+	Retrieves the largest element in the tree.  Returns 0 if there
+	are no elements in the tree.
+
+
+avl_lookup(tree, key, value_p)
+avl_tree *tree;
+char *key;
+char **value_p;
+	Search for an entry matching `key'.  If found, set `value_p' to
+	the associated value field and return 1.  If not found, return
+	0 and leave `value_p' unchanged.
+
+
+avl_insert(tree, key, value);
+avl_tree *tree;
+char *key;
+char *value;
+	Insert the value `value' under the key `key'.  Multiple items
+	are allowed with the same value; all are inserted.
+
+
+avl_delete(tree, key_p, value_p)
+avl_tree *tree;
+char **key_p;
+char **value_p;
+	Search for the item with key `*key_p' in `tree'.  If found, set
+	`key_p' and `value_p' to point to the key and value of item,
+	delete the item and return 1.  Otherwise return 0 and leave
+	`key_p' and `value_p' unchanged.  WARNING: This interface is
+	buggy; in particular, if identical keys are in the table, it is
+	not possible to delete a particular (key, value) pair.  This
+	will be fixed either with 'handles' or a separate delete
+	function.
+
+
+avl_find_or_add(tree, key, slot_p)
+avl_tree *tree;
+char *key;
+char ***slot_p;
+	Search for an entry matching key; if not found, insert key and
+	return the address of the value slot for this entry.  If found,
+	do not insert key, and return the address of the value slot for
+	the existing entry.  slot_p can be used to associate a value with
+	the key.
+
+
+void
+avl_foreach(tree, func, direction)
+avl_tree *tree;
+int (*func)();
+int direction;
+
+	Apply `func' to each item in the tree `tree' in turn.  If
+	direction is AVL_FORWARD, the tree is traversed from smallest
+	to largest. Otherwise it is traversed from largest to smallest.
+
+	func should be of the form:
+
+	     void 
+	     func(key, value)
+	     char *key;
+	     char *value;
+
+	where `key' is the key the item was stored under, and `value'
+	the value of the item.
+
+
+avl_count(tree)
+avl_tree *tree;
+	Returns the number of entries in the avl tree.
+
+
+avl_generator *
+avl_init_gen(tree, direction)
+avl_tree *tree;
+int direction;
+	Start up a generator on an avl-tree.  direction is either 
+	AVL_FORWARD or AVL_BACKWARD indicating the direction of
+	generation.
+
+
+avl_gen(gen, key_p, value_p)
+avl_generator *gen;
+char **key_p;
+char **value_p;
+	Generate the next item from the avl-tree.  Returns 0 if there
+	are no more items in the tree.  Deletion of last generated item
+	(via avl_delete) is supported.  Insertion of items during
+	generation will result in these items never being generated
+	(until the next avl_init_gen()).  Excercise for the interested
+	student: how does one write an avl generator ? 
+
+
+void
+avl_free_gen(gen)
+avl_generator *gen;
+	Free a generator.
+
+
+avl_foreach_item(tree, gen, direction, key_p, value_p)
+avl_tree *tree;
+avl_generator *gen;
+int direction;
+char **key_p;
+char **value_p;
+	Generate over all items in an avl-tree.  This macro iterator
+	combines avl_init_gen(), avl_gen(), and avl_free_gen() into
+	a single statement iterator.
diff --git a/abc-build/src/misc/avl/avl.h b/abc-build/src/misc/avl/avl.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/avl/avl.h
@@ -0,0 +1,91 @@
+/*
+ * Revision Control Information
+ *
+ * $Source: /vol/opua/opua2/sis/sis-1.2/common/src/sis/avl/RCS/avl.h,v $
+ * $Author: sis $
+ * $Revision: 1.3 $
+ * $Date: 1994/07/15 23:00:40 $
+ *
+ */
+#ifndef ABC__misc__avl__avl_h
+#define ABC__misc__avl__avl_h
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+#define EXTERN
+
+#ifndef ARGS
+#define ARGS(protos) protos
+#endif
+
+#define MAX(a,b)	((a) > (b) ? (a) : (b))
+
+#define NIL(type)		\
+    ((type *) 0)
+#define ALLOC(type, num)	\
+    ((type *) malloc(sizeof(type) * (num)))
+#define REALLOC(type, obj, num)	\
+    ((type *) realloc((char *) obj, sizeof(type) * (num)))
+#define FREE(obj)		\
+    free((char *) (obj))
+
+
+
+typedef struct avl_node_struct avl_node;
+struct avl_node_struct {
+    avl_node *left, *right;
+    char *key;
+    char *value;
+    int height;
+};
+
+
+typedef struct avl_tree_struct avl_tree;
+struct avl_tree_struct {
+    avl_node *root;
+    int (*compar)();
+    int num_entries;
+    int modified;
+};
+
+
+typedef struct avl_generator_struct avl_generator;
+struct avl_generator_struct {
+    avl_tree *tree;
+    avl_node **nodelist;
+    int count;
+};
+
+
+#define AVL_FORWARD 	0
+#define AVL_BACKWARD 	1
+
+
+EXTERN avl_tree *avl_init_table ARGS((int (*)()));
+EXTERN int avl_delete ARGS((avl_tree *, char **, char **));
+EXTERN int avl_insert ARGS((avl_tree *, char *, char *));
+EXTERN int avl_lookup ARGS((avl_tree *, char *, char **));
+EXTERN int avl_first ARGS((avl_tree *, char **, char **));
+EXTERN int avl_last ARGS((avl_tree *, char **, char **));
+EXTERN int avl_find_or_add ARGS((avl_tree *, char *, char ***));
+EXTERN int avl_count ARGS((avl_tree *));
+EXTERN int avl_numcmp ARGS((char *, char *));
+EXTERN int avl_gen ARGS((avl_generator *, char **, char **));
+EXTERN void avl_foreach ARGS((avl_tree *, void (*)(), int));
+EXTERN void avl_free_table ARGS((avl_tree *, void (*)(), void (*)()));
+EXTERN void avl_free_gen ARGS((avl_generator *));
+EXTERN avl_generator *avl_init_gen ARGS((avl_tree *, int));
+
+#define avl_is_member(tree, key)	avl_lookup(tree, key, (char **) 0)
+
+#define avl_foreach_item(table, gen, dir, key_p, value_p) 	\
+    for(gen = avl_init_gen(table, dir); 			\
+	    avl_gen(gen, key_p, value_p) || (avl_free_gen(gen),0);)
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/misc/bar/bar.c b/abc-build/src/misc/bar/bar.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bar/bar.c
@@ -0,0 +1,193 @@
+/**CFile****************************************************************
+
+  FileName    [bar.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [extra]
+
+  Synopsis    [Progress bar.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bar.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "misc/util/abc_global.h"
+#include "base/main/main.h"
+#include "bar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+struct Bar_Progress_t_
+{
+    int              nItemsNext;   // the number of items for the next update of the progress bar
+    int              nItemsTotal;  // the total number of items
+    int              posTotal;     // the total number of positions
+    int              posCur;       // the current position
+    FILE *           pFile;        // the output stream 
+};
+
+static void Bar_ProgressShow( Bar_Progress_t * p, char * pString );
+static void Bar_ProgressClean( Bar_Progress_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the progress bar.]
+
+  Description [The first parameter is the output stream (pFile), where
+  the progress is printed. The current printing position should be the
+  first one on the given line. The second parameters is the total
+  number of items that correspond to 100% position of the progress bar.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bar_Progress_t * Bar_ProgressStart( FILE * pFile, int nItemsTotal )
+{
+    Bar_Progress_t * p;
+    Abc_Frame_t * pFrame;
+    pFrame = Abc_FrameReadGlobalFrame();
+    if ( pFrame == NULL )
+        return NULL;
+    if ( !Abc_FrameShowProgress(pFrame) ) return NULL;
+    p = ABC_ALLOC( Bar_Progress_t, 1 );
+    memset( p, 0, sizeof(Bar_Progress_t) );
+    p->pFile       = pFile;
+    p->nItemsTotal = nItemsTotal;
+    p->posTotal    = 78;
+    p->posCur      = 1;
+    p->nItemsNext  = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal);
+    Bar_ProgressShow( p, NULL );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the progress bar.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bar_ProgressUpdate_int( Bar_Progress_t * p, int nItemsCur, char * pString )
+{
+    if ( p == NULL ) return;
+    if ( nItemsCur < p->nItemsNext )
+        return;
+    if ( nItemsCur >= p->nItemsTotal )
+    {
+        p->posCur = 78;
+        p->nItemsNext = 0x7FFFFFFF;
+    }
+    else
+    {
+        p->posCur += 7;
+        p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal);
+    }
+    Bar_ProgressShow( p, pString );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the progress bar.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bar_ProgressStop( Bar_Progress_t * p )
+{
+    if ( p == NULL ) return;
+    Bar_ProgressClean( p );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the progress bar of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bar_ProgressShow( Bar_Progress_t * p, char * pString )
+{
+    int i;
+    if ( p == NULL ) 
+        return;
+    if ( Abc_FrameIsBatchMode() )
+        return;
+    if ( pString )
+        fprintf( p->pFile, "%s ", pString );
+    for ( i = (pString? strlen(pString) + 1 : 0); i < p->posCur; i++ )
+        fprintf( p->pFile, "-" );
+    if ( i == p->posCur )
+        fprintf( p->pFile, ">" );
+    for ( i++  ; i <= p->posTotal; i++ )
+        fprintf( p->pFile, " " );
+    fprintf( p->pFile, "\r" );
+    fflush( stdout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the progress bar before quitting.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bar_ProgressClean( Bar_Progress_t * p )
+{
+    int i;
+    if ( p == NULL ) 
+        return;
+    if ( Abc_FrameIsBatchMode() )
+        return;
+    for ( i = 0; i <= p->posTotal; i++ )
+        fprintf( p->pFile, " " );
+    fprintf( p->pFile, "\r" );
+    fflush( stdout );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/bar/bar.h b/abc-build/src/misc/bar/bar.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bar/bar.h
@@ -0,0 +1,78 @@
+/**CFile****************************************************************
+
+  FileName    [bar.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Progress bar.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bar.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__bar__bar_h
+#define ABC__aig__bar__bar_h
+
+
+#ifdef _WIN32
+#define inline __inline // compatible with MS VS 6.0
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+#define BAR_PROGRESS_USE   1
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+typedef struct Bar_Progress_t_ Bar_Progress_t;
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== bar.c ==========================================================*/
+extern Bar_Progress_t *  Bar_ProgressStart( FILE * pFile, int nItemsTotal );
+extern void              Bar_ProgressStop( Bar_Progress_t * p );
+extern void              Bar_ProgressUpdate_int( Bar_Progress_t * p, int nItemsCur, char * pString );
+
+static inline void       Bar_ProgressUpdate( Bar_Progress_t * p, int nItemsCur, char * pString ) {  
+    if ( BAR_PROGRESS_USE && p && (nItemsCur < *((int*)p)) ) return; Bar_ProgressUpdate_int(p, nItemsCur, pString); }
+
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/bar/module.make b/abc-build/src/misc/bar/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bar/module.make
@@ -0,0 +1,1 @@
+SRC +=	src/misc/bar/bar.c 
diff --git a/abc-build/src/misc/bbl/bblif.c b/abc-build/src/misc/bbl/bblif.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bbl/bblif.c
@@ -0,0 +1,1518 @@
+/**CFile****************************************************************
+
+  FileName    [bblif.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Binary BLIF representation for logic networks.]
+
+  Synopsis    [Main implementation module.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 28, 2009.]
+
+  Revision    [$Id: bblif.c,v 1.00 2009/02/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/util/abc_global.h"
+#include "bblif.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// vector of integers
+typedef struct Vec_Int_t_ Vec_Int_t;
+struct Vec_Int_t_ 
+{
+    int         nCap;
+    int         nSize;
+    int *       pArray;
+};
+
+// vector of characters
+typedef struct Vec_Str_t_ Vec_Str_t;
+struct Vec_Str_t_ 
+{
+    int         nCap;
+    int         nSize;
+    char *      pArray;
+};
+
+// network object
+struct Bbl_Obj_t_
+{
+    int         Id;              // user ID
+    int         Fnc;             // functionality
+    unsigned    fCi     :  1;    // combinational input
+    unsigned    fCo     :  1;    // combinational output
+    unsigned    fBox    :  1;    // subcircuit
+    unsigned    fMark   :  1;    // temporary mark
+    unsigned    nFanins : 28;    // fanin number
+    int         pFanins[0];      // fanin array
+};
+
+// object function
+typedef struct Bbl_Fnc_t_ Bbl_Fnc_t;
+struct Bbl_Fnc_t_
+{
+    int         nWords;          // word number
+    int         pWords[0];       // word array
+};
+
+// object function
+typedef struct Bbl_Ent_t_ Bbl_Ent_t;
+struct Bbl_Ent_t_
+{
+    int         iFunc;           // function handle
+    int         iNext;           // next entry handle
+};
+
+// data manager
+struct Bbl_Man_t_
+{
+    // data pool
+    Vec_Str_t * pName;           // design name
+    Vec_Str_t * pObjs;           // vector of objects
+    Vec_Str_t * pFncs;           // vector of functions
+    // construction
+    Vec_Int_t * vId2Obj;         // mapping user IDs into objects
+    Vec_Int_t * vObj2Id;         // mapping objects into user IDs
+    Vec_Int_t * vFaninNums;      // mapping user IDs into fanin number
+    // file contents
+    int         nFileSize;       // file size
+    char *      pFileData;       // file contents
+    // other data
+    Vec_Str_t * pEnts;           // vector of entries
+    int         SopMap[17][17];  // mapping vars x cubes into entry handles
+};
+
+static inline int         Bbl_ObjIsCi( Bbl_Obj_t * pObj )          { return pObj->fCi;                                        } 
+static inline int         Bbl_ObjIsCo( Bbl_Obj_t * pObj )          { return pObj->fCo;                                        } 
+static inline int         Bbl_ObjIsNode( Bbl_Obj_t * pObj )        { return!pObj->fCi && !pObj->fCo;                          } 
+
+static inline int         Bbl_ObjFaninNum( Bbl_Obj_t * pObj )      { return pObj->nFanins;                                    } 
+static inline Bbl_Obj_t * Bbl_ObjFanin( Bbl_Obj_t * pObj, int i )  { return (Bbl_Obj_t *)(((char *)pObj) - pObj->pFanins[i]); } 
+
+static inline int         Bbl_ObjSize( Bbl_Obj_t * pObj )          { return sizeof(Bbl_Obj_t) + sizeof(int) * pObj->nFanins;  } 
+static inline int         Bbl_FncSize( Bbl_Fnc_t * pFnc )          { return sizeof(Bbl_Fnc_t) + sizeof(int) * pFnc->nWords;   } 
+
+static inline Bbl_Obj_t * Bbl_VecObj( Vec_Str_t * p, int h )       { return (Bbl_Obj_t *)(p->pArray + h);                     } 
+static inline Bbl_Fnc_t * Bbl_VecFnc( Vec_Str_t * p, int h )       { return (Bbl_Fnc_t *)(p->pArray + h);                     } 
+static inline Bbl_Ent_t * Bbl_VecEnt( Vec_Str_t * p, int h )       { return (Bbl_Ent_t *)(p->pArray + h);                     } 
+
+static inline char *      Bbl_ManSop( Bbl_Man_t * p, int h )       { return (char *)Bbl_VecFnc(p->pFncs, h)->pWords;          } 
+static inline Bbl_Obj_t * Bbl_ManObj( Bbl_Man_t * p, int Id )      { return Bbl_VecObj(p->pObjs, p->vId2Obj->pArray[Id]);     } 
+
+#define Bbl_ManForEachObj_int( p, pObj, h )                \
+    for ( h = 0; (h < p->nSize) && (pObj = Bbl_VecObj(p,h)); h += Bbl_ObjSize(pObj) )
+#define Bbl_ManForEachFnc_int( p, pObj, h )                \
+    for ( h = 0; (h < p->nSize) && (pObj = Bbl_VecFnc(p,h)); h += Bbl_FncSize(pObj) )
+#define Bbl_ObjForEachFanin_int( pObj, pFanin, i )         \
+    for ( i = 0; (i < (int)pObj->nFanins) && (pFanin = Bbl_ObjFanin(pObj,i)); i++ )
+
+#define BBLIF_ALLOC(type, num)	 ((type *) malloc(sizeof(type) * (num)))
+#define BBLIF_CALLOC(type, num)	 ((type *) calloc((num), sizeof(type)))
+#define BBLIF_FALLOC(type, num)	 ((type *) memset(malloc(sizeof(type) * (num)), 0xff, sizeof(type) * (num)))
+#define BBLIF_FREE(obj)		     ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#define BBLIF_REALLOC(type, obj, num)	\
+        ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
+	     ((type *) malloc(sizeof(type) * (num))))
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntAlloc( int nCap )
+{
+    Vec_Int_t * p;
+    p = BBLIF_ALLOC( Vec_Int_t, 1 );
+    if ( nCap > 0 && nCap < 16 )
+        nCap = 16;
+    p->nSize  = 0;
+    p->nCap   = nCap;
+    p->pArray = p->nCap? BBLIF_ALLOC( int, p->nCap ) : NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given size and cleans it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntStart( int nSize )
+{
+    Vec_Int_t * p;
+    p = Vec_IntAlloc( nSize );
+    p->nSize = nSize;
+    memset( p->pArray, 0, sizeof(int) * nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given size and cleans it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntStartNatural( int nSize )
+{
+    Vec_Int_t * p;
+    int i;
+    p = Vec_IntAlloc( nSize );
+    p->nSize = nSize;
+    for ( i = 0; i < nSize; i++ )
+        p->pArray[i] = i;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the vector from an integer array of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntAllocArray( int * pArray, int nSize )
+{
+    Vec_Int_t * p;
+    p = BBLIF_ALLOC( Vec_Int_t, 1 );
+    p->nSize  = nSize;
+    p->nCap   = nSize;
+    p->pArray = pArray;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntFree( Vec_Int_t * p )
+{
+    BBLIF_FREE( p->pArray );
+    BBLIF_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntSize( Vec_Int_t * p )
+{
+    return p->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntEntry( Vec_Int_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntWriteEntry( Vec_Int_t * p, int i, int Entry )
+{
+    assert( i >= 0 && i < p->nSize );
+    p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntAddToEntry( Vec_Int_t * p, int i, int Addition )
+{
+    assert( i >= 0 && i < p->nSize );
+    p->pArray[i] += Addition;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntEntryLast( Vec_Int_t * p )
+{
+    assert( p->nSize > 0 );
+    return p->pArray[p->nSize-1];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the vector to the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntGrow( Vec_Int_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pArray = BBLIF_REALLOC( int, p->pArray, nCapMin ); 
+    assert( p->pArray );
+    p->nCap   = nCapMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fills the vector with given number of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntFill( Vec_Int_t * p, int nSize, int Fill )
+{
+    int i;
+    Vec_IntGrow( p, nSize );
+    for ( i = 0; i < nSize; i++ )
+        p->pArray[i] = Fill;
+    p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fills the vector with given number of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntFillExtra( Vec_Int_t * p, int nSize, int Fill )
+{
+    int i;
+    if ( p->nSize >= nSize )
+        return;
+    if ( nSize > 2 * p->nCap )
+        Vec_IntGrow( p, nSize );
+    else if ( nSize > p->nCap )
+        Vec_IntGrow( p, 2 * p->nCap );
+    for ( i = p->nSize; i < nSize; i++ )
+        p->pArray[i] = Fill;
+    p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the entry even if the place not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntGetEntry( Vec_Int_t * p, int i )
+{
+    Vec_IntFillExtra( p, i + 1, 0 );
+    return Vec_IntEntry( p, i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the entry even if the place does not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntSetEntry( Vec_Int_t * p, int i, int Entry )
+{
+    Vec_IntFillExtra( p, i + 1, 0 );
+    Vec_IntWriteEntry( p, i, Entry );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntShrink( Vec_Int_t * p, int nSizeNew )
+{
+    assert( p->nSize >= nSizeNew );
+    p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntClear( Vec_Int_t * p )
+{
+    p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntPush( Vec_Int_t * p, int Entry )
+{
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Vec_IntGrow( p, 16 );
+        else
+            Vec_IntGrow( p, 2 * p->nCap );
+    }
+    p->pArray[p->nSize++] = Entry;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Str_t * Vec_StrAlloc( int nCap )
+{
+    Vec_Str_t * p;
+    p = BBLIF_ALLOC( Vec_Str_t, 1 );
+    if ( nCap > 0 && nCap < 16 )
+        nCap = 16;
+    p->nSize  = 0;
+    p->nCap   = nCap;
+    p->pArray = p->nCap? BBLIF_ALLOC( char, p->nCap ) : NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the vector from an array of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Str_t * Vec_StrAllocArray( char * pArray, int nSize )
+{
+    Vec_Str_t * p;
+    p = BBLIF_ALLOC( Vec_Str_t, 1 );
+    p->nSize  = nSize;
+    p->nCap   = nSize;
+    p->pArray = pArray;
+    return p;
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Returns a piece of memory.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Vec_StrFetch( Vec_Str_t * p, int nBytes )
+{
+    while ( p->nSize + nBytes > p->nCap )
+    {
+        p->pArray = BBLIF_REALLOC( char, p->pArray, 3 * p->nCap );
+        p->nCap *= 3;
+    }
+    p->nSize += nBytes;
+    return p->pArray + p->nSize - nBytes;
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Write vector into file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Vec_StrWrite( FILE * pFile, Vec_Str_t * p )
+{
+    fwrite( &p->nSize, sizeof(int), 1, pFile );
+    fwrite( p->pArray, sizeof(char), p->nSize, pFile );
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Write vector into file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Vec_StrRead( char ** ppStr )
+{
+    Vec_Str_t * p;
+    char * pStr = *ppStr;
+    p = Vec_StrAlloc( 0 );
+    p->nSize = *(int *)pStr;
+    p->pArray = pStr + sizeof(int);
+    *ppStr = pStr + sizeof(int) + p->nSize * sizeof(char);
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_StrSize( Vec_Str_t * p )
+{
+    return p->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrFree( Vec_Str_t * p )
+{
+    BBLIF_FREE( p->pArray );
+    BBLIF_FREE( p );
+}
+
+
+
+
+
+/**Fnction*************************************************************
+
+  Synopsis    [Returns the file size.]
+
+  Description [The file should be closed.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bbl_ManFileSize( char * pFileName )
+{
+    FILE * pFile;
+    int nFileSize;
+    pFile = fopen( pFileName, "r" );
+    if ( pFile == NULL )
+    {
+        printf( "Bbl_ManFileSize(): The file is unavailable (absent or open).\n" );
+        return 0;
+    }
+    fseek( pFile, 0, SEEK_END );  
+    nFileSize = ftell( pFile ); 
+    fclose( pFile );
+    return nFileSize;
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Read data from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Bbl_ManFileRead( char * pFileName )
+{
+    FILE * pFile;
+    char * pContents;
+    int nFileSize;
+    int RetValue;
+    nFileSize = Bbl_ManFileSize( pFileName );
+    pFile = fopen( pFileName, "rb" );
+    pContents = BBLIF_ALLOC( char, nFileSize );
+    RetValue = fread( pContents, nFileSize, 1, pFile );
+    fclose( pFile );
+    return pContents;
+}
+
+
+
+/**Fnction*************************************************************
+
+  Synopsis    [Writes data into file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbl_ManDumpBinaryBlif( Bbl_Man_t * p, char * pFileName )
+{
+    FILE * pFile;
+    pFile = fopen( pFileName, "wb" );
+    Vec_StrWrite( pFile, p->pName );
+    Vec_StrWrite( pFile, p->pObjs );
+    Vec_StrWrite( pFile, p->pFncs );
+    fclose( pFile );
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Creates manager after reading.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bbl_Man_t * Bbl_ManReadBinaryBlif( char * pFileName )
+{
+    Bbl_Man_t * p;
+    Bbl_Obj_t * pObj;
+    char * pBuffer;
+    int h;
+    p = BBLIF_ALLOC( Bbl_Man_t, 1 );
+    memset( p, 0, sizeof(Bbl_Man_t) );
+    p->nFileSize = Bbl_ManFileSize( pFileName );
+    p->pFileData = Bbl_ManFileRead( pFileName );
+    // extract three managers
+    pBuffer = p->pFileData;
+    p->pName = Vec_StrRead( &pBuffer );
+    p->pObjs = Vec_StrRead( &pBuffer );
+    p->pFncs = Vec_StrRead( &pBuffer );
+    assert( pBuffer - p->pFileData == p->nFileSize );
+    // remember original IDs in the objects
+    p->vObj2Id = Vec_IntAlloc( 1000 );
+    Bbl_ManForEachObj_int( p->pObjs, pObj, h )
+    {
+        Vec_IntPush( p->vObj2Id, pObj->Id );
+        pObj->Id = Vec_IntSize(p->vObj2Id) - 1; 
+    }
+    return p;
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Prints stats of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbl_ManPrintStats( Bbl_Man_t * p )
+{
+    Bbl_Obj_t * pObj;
+    Bbl_Fnc_t * pFnc;
+    int h, nFuncs = 0, nNodes = 0, nObjs = 0;
+    Bbl_ManForEachObj_int( p->pObjs, pObj, h )
+        nObjs++, nNodes += Bbl_ObjIsNode(pObj);
+    Bbl_ManForEachFnc_int( p->pFncs, pFnc, h )
+        nFuncs++;
+    printf( "Total objects = %7d.  Total nodes = %7d. Unique functions = %7d.\n", nObjs, nNodes, nFuncs );
+    printf( "Name manager = %5.2f MB\n", 1.0*Vec_StrSize(p->pName)/(1 << 20) );
+    printf( "Objs manager = %5.2f MB\n", 1.0*Vec_StrSize(p->pObjs)/(1 << 20) );
+    printf( "Fncs manager = %5.2f MB\n", 1.0*Vec_StrSize(p->pFncs)/(1 << 20) );
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Deletes the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbl_ManStop( Bbl_Man_t * p )
+{
+    if ( p->vId2Obj )    Vec_IntFree( p->vId2Obj );
+    if ( p->vObj2Id )    Vec_IntFree( p->vObj2Id );
+    if ( p->vFaninNums ) Vec_IntFree( p->vFaninNums );
+    if ( p->pFileData )
+    {
+        BBLIF_FREE( p->pFileData );
+        p->pName->pArray = NULL;
+        p->pObjs->pArray = NULL;
+        p->pFncs->pArray = NULL;
+    }
+    if ( p->pEnts )
+    Vec_StrFree( p->pEnts );
+    Vec_StrFree( p->pName );
+    Vec_StrFree( p->pObjs );
+    Vec_StrFree( p->pFncs );
+    BBLIF_FREE( p );
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Creates manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bbl_Man_t * Bbl_ManStart( char * pName )
+{
+    Bbl_Man_t * p;
+    int nLength;
+    p = BBLIF_ALLOC( Bbl_Man_t, 1 );
+    memset( p, 0, sizeof(Bbl_Man_t) );
+    nLength = pName? 4 * ((strlen(pName) + 1) / 4 + 1) : 0;
+    p->pName  = Vec_StrAlloc( nLength );
+    p->pName->nSize = p->pName->nCap;
+    if ( pName )
+        strcpy( p->pName->pArray, pName );
+    p->pObjs = Vec_StrAlloc( 1 << 16 );
+    p->pFncs = Vec_StrAlloc( 1 << 16 );
+    p->pEnts = Vec_StrAlloc( 1 << 16 ); p->pEnts->nSize = 1;
+    p->vId2Obj = Vec_IntStart( 1 << 10 );
+    p->vFaninNums = Vec_IntStart( 1 << 10 );
+    return p;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs selection sort on the array of cubes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbl_ManSortCubes( char ** pCubes, int nCubes, int nVars )
+{
+    char * pTemp;
+    int i, j, best_i;
+    for ( i = 0; i < nCubes-1; i++ )
+    {
+        best_i = i;
+        for (j = i+1; j < nCubes; j++)
+            if ( memcmp( pCubes[j], pCubes[best_i], nVars ) < 0 )
+                best_i = j;
+        pTemp = pCubes[i]; pCubes[i] = pCubes[best_i]; pCubes[best_i] = pTemp;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts the cubes in the SOP to uniqify them to some extent.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Bbl_ManSortSop( char * pSop, int nVars )
+{
+    char ** pCubes, * pSopNew;
+    int c, Length, nCubes;
+    Length = strlen(pSop);
+    assert( Length % (nVars + 3) == 0 );
+    nCubes = Length / (nVars + 3);
+    if ( nCubes < 2 )
+    {
+        pSopNew = BBLIF_ALLOC( char, Length + 1 );
+        memcpy( pSopNew, pSop, Length + 1 );
+        return pSopNew;
+    }
+    pCubes = BBLIF_ALLOC( char *, nCubes );
+    for ( c = 0; c < nCubes; c++ )
+        pCubes[c] = pSop + c * (nVars + 3);
+    if ( nCubes < 300 )
+        Bbl_ManSortCubes( pCubes, nCubes, nVars );
+    pSopNew = BBLIF_ALLOC( char, Length + 1 );
+    for ( c = 0; c < nCubes; c++ )
+        memcpy( pSopNew + c * (nVars + 3), pCubes[c], nVars + 3 );
+    BBLIF_FREE( pCubes );
+    pSopNew[nCubes * (nVars + 3)] = 0;
+    return pSopNew;
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Saves one entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bbl_ManCreateEntry( Bbl_Man_t * p, int iFunc, int iNext )
+{
+    Bbl_Ent_t * pEnt;
+    pEnt = (Bbl_Ent_t *)Vec_StrFetch( p->pEnts, 2 * sizeof(int) );
+    pEnt->iFunc = iFunc;
+    pEnt->iNext = iNext;
+    return (char *)pEnt - p->pEnts->pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts the cubes in the SOP to uniqify them to some extent.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bbl_ManSopCheckUnique( Bbl_Man_t * p, char * pSop, int nVars, int nCubes, int iFunc )
+{
+    Bbl_Fnc_t * pFnc;
+    Bbl_Ent_t * pEnt;
+    int h, Length = strlen(pSop) + 1;
+    int nWords = (Length / 4 + (Length % 4 > 0));
+    if ( nVars > 16 )   nVars = 16;
+    if ( nCubes > 16 )  nCubes = 16;
+//    if ( nVars == 16 && nCubes == 16 )
+//        return iFunc;
+    for ( h = p->SopMap[nVars][nCubes]; h; h = pEnt->iNext )
+    {
+        pEnt = Bbl_VecEnt( p->pEnts, h );
+        pFnc = Bbl_VecFnc( p->pFncs, pEnt->iFunc );
+        assert( nVars == 16 || nCubes == 16 || pFnc->nWords == nWords );
+        if ( pFnc->nWords == nWords && memcmp( pFnc->pWords, pSop, Length ) == 0 )
+            return pEnt->iFunc;
+    }
+    p->SopMap[nVars][nCubes] = Bbl_ManCreateEntry( p, iFunc, p->SopMap[nVars][nCubes] );
+    return iFunc;
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Saves one SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bbl_ManSaveSop( Bbl_Man_t * p, char * pSop, int nVars )
+{
+    Bbl_Fnc_t * pFnc;
+    char * pSopNew;
+    int iFunc, Length = strlen(pSop) + 1;
+    int nWords = Length / 4 + (Length % 4 > 0);
+    // reorder cubes to semi-canicize SOPs
+    pSopNew = Bbl_ManSortSop( pSop, nVars );
+    // get the candidate location
+    iFunc = Bbl_ManSopCheckUnique( p, pSopNew, nVars, Length / (nVars + 3), Vec_StrSize(p->pFncs) );
+//    iFunc = Vec_StrSize(p->pFncs);
+    if ( iFunc == Vec_StrSize(p->pFncs) )
+    { // store this SOP
+        pFnc = (Bbl_Fnc_t *)Vec_StrFetch( p->pFncs, sizeof(Bbl_Fnc_t) + nWords * sizeof(int) );
+        pFnc->pWords[nWords-1] = 0;
+        pFnc->nWords = nWords;
+        strcpy( (char *)pFnc->pWords, pSopNew );
+        assert( iFunc == (char *)pFnc - p->pFncs->pArray );
+    }
+    BBLIF_FREE( pSopNew );
+    return iFunc;
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Adds one object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbl_ManCreateObject( Bbl_Man_t * p, Bbl_Type_t Type, int ObjId, int nFanins, char * pSop )
+{
+    Bbl_Obj_t * pObj;
+    if ( Type == BBL_OBJ_CI && nFanins != 0 )
+    {
+        printf( "Attempting to create a combinational input with %d fanins (should be 0).\n", nFanins );
+        return;
+    }
+    if ( Type == BBL_OBJ_CO && nFanins != 1 )
+    {
+        printf( "Attempting to create a combinational output with %d fanins (should be 1).\n", nFanins );
+        return;
+    }
+    pObj = (Bbl_Obj_t *)Vec_StrFetch( p->pObjs, sizeof(Bbl_Obj_t) + nFanins * sizeof(int) );
+    memset( pObj, 0, sizeof(Bbl_Obj_t) );
+    Vec_IntSetEntry( p->vId2Obj, ObjId, (char *)pObj - p->pObjs->pArray );
+    Vec_IntSetEntry( p->vFaninNums, ObjId, 0 );
+    pObj->fCi = (Type == BBL_OBJ_CI);
+    pObj->fCo = (Type == BBL_OBJ_CO);
+    pObj->Id  = ObjId;
+    pObj->Fnc = pSop? Bbl_ManSaveSop(p, pSop, nFanins) : -1;
+    pObj->nFanins = nFanins;
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Creates fanin/fanout relationship between two objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbl_ManAddFanin( Bbl_Man_t * p, int ObjId, int FaninId )
+{
+    Bbl_Obj_t * pObj, * pFanin;
+    int iFanin;
+    pObj   = Bbl_ManObj( p, ObjId );
+    if ( Bbl_ObjIsCi(pObj) )
+    {
+        printf( "Bbl_ManAddFanin(): Cannot add fanin of the combinational input (Id = %d).\n", ObjId );
+        return;
+    }
+    pFanin = Bbl_ManObj( p, FaninId );
+    if ( Bbl_ObjIsCo(pFanin) )
+    {
+        printf( "Bbl_ManAddFanin(): Cannot add fanout of the combinational output (Id = %d).\n", FaninId );
+        return;
+    }
+    iFanin = Vec_IntEntry( p->vFaninNums, ObjId );
+    if ( iFanin >= (int)pObj->nFanins )
+    {
+        printf( "Bbl_ManAddFanin(): Trying to add more fanins to object (Id = %d) than declared (%d).\n", ObjId, pObj->nFanins );
+        return;
+    }
+    assert( iFanin < (int)pObj->nFanins );
+    Vec_IntWriteEntry( p->vFaninNums, ObjId, iFanin+1 );
+    pObj->pFanins[iFanin] = (char *)pObj - (char *)pFanin;
+}
+
+
+/**Fnction*************************************************************
+
+  Synopsis    [Returns 1 if the manager was created correctly.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bbl_ManCheck( Bbl_Man_t * p )
+{
+    Bbl_Obj_t * pObj;
+    int h, RetValue = 1;
+    Bbl_ManForEachObj_int( p->pObjs, pObj, h )
+    {
+        if ( Bbl_ObjIsNode(pObj) && pObj->Fnc == -1 )
+            RetValue = 0, printf( "Bbl_ManCheck(): Node %d does not have function specified.\n", pObj->Id );
+        if ( Bbl_ObjIsCi(pObj) && pObj->Fnc != -1 )
+            RetValue = 0, printf( "Bbl_ManCheck(): CI with %d has function specified.\n", pObj->Id );
+        if ( Bbl_ObjIsCo(pObj) && pObj->Fnc != -1 )
+            RetValue = 0, printf( "Bbl_ManCheck(): CO with %d has function specified.\n", pObj->Id );
+        if ( Vec_IntEntry(p->vFaninNums, pObj->Id) != (int)pObj->nFanins )
+            RetValue = 0, printf( "Bbl_ManCheck(): Object %d has less fanins (%d) than declared (%d).\n", 
+                pObj->Id, Vec_IntEntry(p->vFaninNums, pObj->Id), pObj->nFanins );
+    }
+    return RetValue;
+}
+
+
+/**Fnction*************************************************************
+
+  Synopsis    [Misc APIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int         Bbl_ObjIsInput( Bbl_Obj_t * p )                      { return Bbl_ObjIsCi(p);                      }
+int         Bbl_ObjIsOutput( Bbl_Obj_t * p )                     { return Bbl_ObjIsCo(p);                      }
+int         Bbl_ObjIsLut( Bbl_Obj_t * p )                        { return Bbl_ObjIsNode(p);                    }
+int         Bbl_ObjId( Bbl_Obj_t * p )                           { return p->Id;                               }
+int         Bbl_ObjIdOriginal( Bbl_Man_t * pMan, Bbl_Obj_t * p ) { assert(0); return Vec_IntEntry(pMan->vObj2Id, p->Id);  }
+int         Bbl_ObjFaninNumber( Bbl_Obj_t * p )                  { return Bbl_ObjFaninNum(p);                  }
+char *      Bbl_ObjSop( Bbl_Man_t * pMan, Bbl_Obj_t * p )        { return Bbl_ManSop(pMan, p->Fnc);            }
+int         Bbl_ObjIsMarked( Bbl_Obj_t * p )                     { return p->fMark;                            }
+void        Bbl_ObjMark( Bbl_Obj_t * p )                         { p->fMark = 1;                               }
+int         Bbl_ObjFncHandle( Bbl_Obj_t * p )                    { return p->Fnc;                              }
+
+/**Fnction*************************************************************
+
+  Synopsis    [Returns the name of the design.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Bbl_ManName( Bbl_Man_t * p )
+{
+    return p->pName->pArray;
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Returns the maximum handle of the SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bbl_ManFncSize( Bbl_Man_t * p )
+{
+    return p->pFncs->nSize;
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Returns the first object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bbl_Obj_t * Bbl_ManObjFirst( Bbl_Man_t * p )
+{
+    return Bbl_VecObj( p->pObjs, 0 );
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Returns the next object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bbl_Obj_t * Bbl_ManObjNext( Bbl_Man_t * p, Bbl_Obj_t * pObj )
+{
+    char * pNext = (char *)pObj + Bbl_ObjSize(pObj);
+    char * pEdge = p->pObjs->pArray + p->pObjs->nSize;
+    return (Bbl_Obj_t *)(pNext < pEdge ? pNext : NULL);
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Returns the first fanin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bbl_Obj_t * Bbl_ObjFaninFirst( Bbl_Obj_t * p )
+{
+    return Bbl_ObjFaninNum(p) ? Bbl_ObjFanin( p, 0 ) : NULL;
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Returns the next fanin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bbl_Obj_t * Bbl_ObjFaninNext( Bbl_Obj_t * p, Bbl_Obj_t * pPrev )
+{
+    Bbl_Obj_t * pFanin;
+    int i;
+    Bbl_ObjForEachFanin_int( p, pFanin, i )
+        if ( pFanin == pPrev )
+            break;
+    return i < Bbl_ObjFaninNum(p) - 1 ? Bbl_ObjFanin( p, i+1 ) : NULL;
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Drives text BLIF file for debugging.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbl_ManDumpBlif( Bbl_Man_t * p, char * pFileName )
+{
+    FILE * pFile;
+    Bbl_Obj_t * pObj, * pFanin;
+    pFile = fopen( pFileName, "w" );
+    fprintf( pFile, "# Test file written by Bbl_ManDumpBlif() in ABC.\n" );
+    fprintf( pFile, ".model %s\n", Bbl_ManName(p) );
+    // write objects
+    Bbl_ManForEachObj( p, pObj )
+    {
+        if ( Bbl_ObjIsInput(pObj) )
+            fprintf( pFile, ".inputs %d\n", Bbl_ObjId(pObj) );
+        else if ( Bbl_ObjIsOutput(pObj) )
+            fprintf( pFile, ".outputs %d\n", Bbl_ObjId(pObj) );
+        else if ( Bbl_ObjIsLut(pObj) )
+        {
+            fprintf( pFile, ".names" );
+            Bbl_ObjForEachFanin( pObj, pFanin )
+                fprintf( pFile, " %d", Bbl_ObjId(pFanin) );
+            fprintf( pFile, " %d\n", Bbl_ObjId(pObj) );
+            fprintf( pFile, "%s", Bbl_ObjSop(p, pObj) );
+        }
+        else assert( 0 );
+    }
+    // write output drivers
+    Bbl_ManForEachObj( p, pObj )
+    {
+        if ( !Bbl_ObjIsOutput(pObj) )
+            continue;
+        fprintf( pFile, ".names" );
+        Bbl_ObjForEachFanin( pObj, pFanin )
+            fprintf( pFile, " %d", Bbl_ObjId(pFanin) );
+        fprintf( pFile, " %d\n", Bbl_ObjId(pObj) );
+        fprintf( pFile, "1 1\n" );
+    }
+    fprintf( pFile, ".end\n" );
+    fclose( pFile );
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Converting truth table into an SOP.]
+
+  Description [The truth table is given as a bit-string pTruth
+  composed of 2^nVars bits. The result is an SOP derived by
+  collecting minterms appearing in the truth table. The SOP is 
+  represented as a C-string, as documented in file "bblif.h".
+  It is recommended to limit the use of this procedure to Boolean 
+  functions up to 6 inputs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Bbl_ManTruthToSop( unsigned * pTruth, int nVars )
+{
+    char * pResult, * pTemp;
+    int nMints, nOnes, b, v;
+    assert( nVars >= 0 && nVars <= 16 );
+    nMints = (1 << nVars);
+    // count the number of ones
+    nOnes = 0;
+    for ( b = 0; b < nMints; b++ )
+        nOnes += ((pTruth[b>>5] >> (b&31)) & 1);
+    // handle constants
+    if ( nOnes == 0 || nOnes == nMints )
+    {
+        pResult = pTemp = BBLIF_ALLOC( char, nVars + 4 );        
+        for ( v = 0; v < nVars; v++ )
+            *pTemp++ = '-';
+        *pTemp++ = ' ';
+        *pTemp++ = nOnes? '1' : '0';
+        *pTemp++ = '\n';
+        *pTemp++ = 0;
+        assert( pTemp - pResult == nVars + 4 );
+        return pResult;
+    }
+    pResult = pTemp = BBLIF_ALLOC( char, nOnes * (nVars + 3) + 1 );        
+    for ( b = 0; b < nMints; b++ )
+    {
+        if ( ((pTruth[b>>5] >> (b&31)) & 1) == 0 )
+            continue;
+        for ( v = 0; v < nVars; v++ )
+            *pTemp++ = ((b >> v) & 1)? '1' : '0';
+        *pTemp++ = ' ';
+        *pTemp++ = '1';
+        *pTemp++ = '\n';
+    }
+    *pTemp++ = 0;
+    assert( pTemp - pResult == nOnes * (nVars + 3) + 1 );
+    return pResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the array of truth tables for the given number of vars.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Bbl_ManSopToTruthElem( int nVars, unsigned ** pVars )
+{
+    unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+    int i, k, nWords;
+    nWords = (nVars <= 5 ? 1 : (1 << (nVars - 5)));
+    for ( i = 0; i < nVars; i++ )
+    {
+        if ( i < 5 )
+        {
+            for ( k = 0; k < nWords; k++ )
+                pVars[i][k] = Masks[i];
+        }
+        else
+        {
+            for ( k = 0; k < nWords; k++ )
+                if ( k & (1 << (i-5)) )
+                    pVars[i][k] = ~(unsigned)0;
+                else
+                    pVars[i][k] = 0;
+        }
+    }
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [Converting SOP into a truth table.]
+
+  Description [The SOP is represented as a C-string, as documented in 
+  file "bblif.h". The truth table is returned as a bit-string composed 
+  of 2^nVars bits. For functions of less than 6 variables, the full
+  machine word is returned. (The truth table looks as if the function
+  had 5 variables.) The use of this procedure should be limited to 
+  Boolean functions with no more than 16 inputs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Bbl_ManSopToTruth( char * pSop, int nVars )
+{
+    unsigned * pTruth, * pCube, * pVars[16];
+    int nWords = nVars <= 5 ? 1 : (1 << (nVars - 5));
+    int v, c, w, nCubes, fCompl = 0;
+    if ( pSop == NULL )
+        return NULL;
+    if ( strlen(pSop) % (nVars + 3) != 0 )
+    {
+        printf( "Bbl_ManSopToTruth(): SOP is represented incorrectly.\n" );
+        return NULL;
+    }
+    // create storage for TTs of the result, elementary variables and the temp cube
+    pTruth   = BBLIF_ALLOC( unsigned, nWords );   
+    pVars[0] = BBLIF_ALLOC( unsigned, nWords * (nVars+1) );   
+    for ( v = 1; v < nVars; v++ )
+        pVars[v] = pVars[v-1] + nWords;
+    pCube = pVars[v-1] + nWords;
+    Bbl_ManSopToTruthElem( nVars, pVars );
+    // iterate through the cubes
+    memset( pTruth, 0, sizeof(unsigned) * nWords );
+    nCubes =  strlen(pSop) / (nVars + 3);
+    for ( c = 0; c < nCubes; c++ )
+    {
+        fCompl = (pSop[nVars+1] == '0');
+        memset( pCube, 0xff, sizeof(unsigned) * nWords );
+        // iterate through the literals of the cube
+        for ( v = 0; v < nVars; v++ )
+            if ( pSop[v] == '1' )
+                for ( w = 0; w < nWords; w++ )
+                    pCube[w] &= pVars[v][w];
+            else if ( pSop[v] == '0' )
+                for ( w = 0; w < nWords; w++ )
+                    pCube[w] &= ~pVars[v][w];
+        // add cube to storage
+        for ( w = 0; w < nWords; w++ )
+            pTruth[w] |= pCube[w];
+        // go to the next cube
+        pSop += (nVars + 3);
+    }
+    BBLIF_FREE( pVars[0] );
+    if ( fCompl )
+        for ( w = 0; w < nWords; w++ )
+            pTruth[w] = ~pTruth[w];
+    return pTruth;
+}
+
+
+/**Fnction*************************************************************
+
+  Synopsis    [Checks the truth table computation.]
+
+  Description [We construct the logic network for the half-adder represnted
+  using the BLIF file below]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbl_ManTestTruth( char * pSop, int nVars )
+{
+    unsigned * pTruth;
+    char * pSopNew;
+    pTruth = Bbl_ManSopToTruth( pSop, nVars );
+    pSopNew = Bbl_ManTruthToSop( pTruth, nVars );
+    printf( "Old SOP:\n%s\n", pSop );
+    printf( "New SOP:\n%s\n", pSopNew );
+    BBLIF_FREE( pSopNew );
+    BBLIF_FREE( pTruth );
+}
+
+/**Fnction*************************************************************
+
+  Synopsis    [This demo shows using the internal to construct a half-adder.]
+
+  Description [We construct the logic network for the half-adder represnted
+  using the BLIF file below]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbl_ManSimpleDemo()
+{
+/*
+    # There are contents of a BLIF file representing a half-adder:
+    .model hadder
+    .inputs a     // ID = 1
+    .inputs b     // ID = 2
+    .inputs cin   // ID = 3
+    .outputs s    // ID = 4
+    .outputs cout // ID = 5
+    .names a b cin s_driver   // ID = 6
+    100 1
+    010 1
+    001 1
+    111 1
+    .names a b cin cout_driver // ID = 7
+    -11 1
+    1-1 1
+    11- 1
+    .names s_driver s
+    1 1
+    .names cout_driver cout
+    1 1
+    .end
+*/
+    Bbl_Man_t * p;
+    // start the data manager
+    p = Bbl_ManStart( "hadder" );
+    // create CIs
+    Bbl_ManCreateObject( p, BBL_OBJ_CI, 1, 0, NULL ); // a
+    Bbl_ManCreateObject( p, BBL_OBJ_CI, 2, 0, NULL ); // b
+    Bbl_ManCreateObject( p, BBL_OBJ_CI, 3, 0, NULL ); // cin
+    // create COs
+    Bbl_ManCreateObject( p, BBL_OBJ_CO, 4, 1, NULL ); // s
+    Bbl_ManCreateObject( p, BBL_OBJ_CO, 5, 1, NULL ); // cout
+    // create internal nodes
+    Bbl_ManCreateObject( p, BBL_OBJ_NODE, 6, 3, "100 1\n010 1\n001 1\n111 1\n" ); // s_driver
+    Bbl_ManCreateObject( p, BBL_OBJ_NODE, 7, 3, "-11 1\n1-1 1\n11- 1\n" );        // cout_driver
+    // add fanins of node 6
+    Bbl_ManAddFanin( p, 6, 1 ); // s_driver <- a
+    Bbl_ManAddFanin( p, 6, 2 ); // s_driver <- b
+    Bbl_ManAddFanin( p, 6, 3 ); // s_driver <- cin
+    // add fanins of node 7
+    Bbl_ManAddFanin( p, 7, 1 ); // cout_driver <- a
+    Bbl_ManAddFanin( p, 7, 2 ); // cout_driver <- b
+    Bbl_ManAddFanin( p, 7, 3 ); // cout_driver <- cin
+    // add fanins of COs
+    Bbl_ManAddFanin( p, 4, 6 ); // s <- s_driver
+    Bbl_ManAddFanin( p, 5, 7 ); // cout <- cout_driver
+    // sanity check
+    Bbl_ManCheck( p );
+    // write BLIF file as a sanity check
+    Bbl_ManDumpBlif( p, "hadder.blif" );
+    // write binary BLIF file
+    Bbl_ManDumpBinaryBlif( p, "hadder.bblif" );
+    // remove the manager
+    Bbl_ManStop( p );
+
+
+//    Bbl_ManTestTruth( "100 1\n010 1\n001 1\n111 1\n", 3 );
+//    Bbl_ManTestTruth( "-11 0\n1-1 0\n11- 0\n", 3 );
+//    Bbl_ManTestTruth( "--- 1\n", 3 );
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/bbl/bblif.h b/abc-build/src/misc/bbl/bblif.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bbl/bblif.h
@@ -0,0 +1,285 @@
+/**CFile****************************************************************
+
+  FileName    [bblif.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Binary BLIF representation for logic networks.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 28, 2009.]
+
+  Revision    [$Id: bblif.h,v 1.00 2009/02/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__bbl__bblif_h
+#define ABC__aig__bbl__bblif_h
+
+
+/*
+    This file (taken together with "bblif.c") implements a stand-alone 
+    interface between ABC and an application that uses ABC. 
+    
+    The interface is designed to pass a combinational logic network 
+    from the calling application to ABC using a binary BLIF format (BBLIF) 
+    and return the network after synthesis/mapping/verification in ABC 
+    back to the caller.
+
+    The interface can do the following:
+    (1) accept a combinational logic network via a set of APIs
+    (2) write the logic network into a binary BLIF file readable by ABC
+    (3) read a binary BLIF file with a mapped network produced by ABC
+    (4) return the mapped network to the caller through a set of APIs
+
+    It should be noted that the BBLIF interface can be used to pass
+    the network from the calling application into ABC without writing it
+    into a file. In this case, ABC should be compiled as a library and
+    linked to the calling application. The BBLIF manager can be given
+    directly to the procedure Bbl_ManToAbc() to convert it into an AIG.
+    Similarly, the resulting mapped network can be converted into
+    BBLIF manager and passed back after the call to Bbl_ManFromAbc().
+
+    Here these steps are described in more detail:
+
+    (1) The BBLIF manager is allocated by calling Bbl_ManStart() and 
+        deallocated by calling Bbl_ManStop(). 
+    
+        The combinational network is composed of three types of objects:
+        (a) combinational inputs (CIs), (b) combinational outputs (COs), 
+        (c) internal logic nodes represented using Sum-of-Products (SOPs)
+        similar to the way logic nodes are represented in SIS. Sequential 
+        elements (flops) are currently not supported.   A CI has no fanins. 
+        A CO has exactly one fanin and no fanouts. Internal nodes can 
+        have any number of fanins and fanouts. Only an internal node can 
+        have a logic function.
+
+        Before constructing the BBLIF manager, each object should be 
+        assigned a unique non-negative (0-based) integer ID. The sequence
+        of ID numbers may have gaps in it (for example, 0, 1, 2, 5, 6, etc)
+        but care should be taken that the ID numbers do not grow too large
+        because internally they are used to index the objects. So if 
+        the largest given ID has value N, an array of 4*N bytes will be 
+        allocated internally by the BBLIF manager. Obviously if N = 1M, 
+        the array will use 4Mb, but if N = 100M, it will use 0.4Gb.
+
+        This object ID (called also "the original ID of the object") is 
+        given to Bbl_ManCreateObject(), which construct the BBLIF objects 
+        and to the procedure Bbl_ManAddFanin(), which creates fanin/fanout
+        relations between two objects.  The exact number of fanins of an
+        object should be declared when calling Bbl_ManCreateObject(). 
+        Later on, each node should be assigned as many fanins using 
+        Bbl_ManAddFanin(). The order/number of fanins corresponds to the 
+        order/number of variables in the SOP of the logic function of the 
+        node. The declared and actual number of fanins should be the same.
+        otherwise the interface will not function correctly. This is checked
+        by the procedure Bbl_ManCheck(), which should be called when 
+        constructing all objects and their fanins is finished.
+
+        The SOP representation of the logic function should be given to
+        every internal node. It is given as a C-string, showing the SOP
+        as it would appear in a BLIF or PLA file. Each cube is composed
+        of characters '0', '1', and '-', and ended by a seqence of three
+        characters: space ' ', followed by '0' or '1' (depending on whether 
+        on- or off-set is used), followed by the new line character '\n'. 
+        For example, a two-input OR has the following SOP representation: 
+        "1- 1\n-1 1\n", or equivalently, "00 0\n". The SOP for a constant 
+        function with no fanins is represented as " 0\n" (constant 0) and
+        " 1\n" (constant 1). SOP for a constant node with some fanins
+        may also be represented. For example, constant 0 node with three 
+        fanins will have SOP representation as follows: "--- 0\n".
+
+        The objects can be added to the BBLIF manager in any order, but 
+        by the time the fanin/fanout connections are created, corresponding 
+        objects should be already created.
+
+        The number of objects is limited by 2^31. The number of fanins
+        of one object is restricted to 2^28. The SOP representation can 
+        have arbitrary many products (cubes), as long as memory is enough
+        to represent them in the C-string form, as described above.
+
+    (2) To write the manager into a file, call procedure Bbl_ManDumpBinaryBlif().
+        It is recommended to use files with extension ".bblif" because it
+        will allow ABC to call the approapriate reader in command "read".
+
+    (3) To read the network from file, call procedure Bbl_ManReadBinaryBlif().
+
+    (4) It is assumed that ABC will return the network after mapping.
+        This network will arrive in a BBLIF file, from which the BBLIF 
+        manager is created by the call to Bbl_ManReadBinaryBlif(). The 
+        following APIs are useful to extract the mapped network from the manager:
+        
+        Iterator Bbl_ManForEachObj() iterates through the pointers to the
+        BBLIF objects, which are guaranteed to be in a topological order. 
+
+        For each object, the following APIs can be used:
+        Bbl_ObjIsInput() returns 1 if the object is a CI
+        Bbl_ObjIsOutput() returns 1 if the object is a CO
+        Bbl_ObjIsLut() returns 1 if the object is a logic node (lookup table)
+        Bbl_ObjFaninNumber() returns the number of fanins of the node
+        Bbl_ObjSop() returns the SOP representation of the node, as described above.
+
+        A special attention should be given to the representation of object IDs
+        after mapping. Recall that when the outgoing BBLIF network is constructed, 
+        the IDs of objects are assigned by the calling application and given to 
+        the BBLIF manager when procedure Bbl_ManCreateObject() is called.  
+        We refer to these object IDs as "original IDs of the objects". 
+        
+        When the network has been given to ABC, mapped, and returned to the 
+        calling application in the incoming BBLIF file, only CIs and COs are 
+        guaranteed to preserve their "original IDs". Other objects may be created 
+        during synthesis/mapping. The original IDs of these objects are set to -1. 
+
+        The following two APIs are used to return the IDs of objects after mapping:
+        Bbl_ObjId() returns the new ID (useful to construct network after mapping)
+        Bbl_ObjIdOriginal() returns the original ID (or -1 if this is a new object).
+
+        !!!***!!!
+        Note: The original ID currently cannot be returned by Bbl_ObjIdOriginal().
+        It is recommended to use the work-around described below.
+        !!!***!!!
+
+        The original ID is useful to map CIs/COs after mapping into CIs/COs before
+        mapping. However, the order of CIs/COs after mapping in the incoming network 
+        is the same as the order of their creation by the calling application 
+        in the outgoing network. This allows for a workaround that does not have 
+        the need for the original IDs.  We can simply iterate through the objects 
+        after mapping, and create CIs and COs in the order of their appearance, 
+        and this order is guaranteed to be the same as the order of their 
+        construction by the calling application.
+
+        It is also worth noting that currently the internal node names are not 
+        preserved by ABC during synthesis. This may change in the future. and then 
+        some of the internal nodes will preserve their IDs, which may allow the 
+        calling application to reconstruct the names of some of the nodes after 
+        synthesis/mapping in ABC using their original IDs whenever available.
+
+        Finally, iterator Bbl_ObjForEachFanin() can be used to iterate through 
+        the fanins of each mapped object. For CIs, there will be no fanins. 
+        For COs, there will be exactly one fanin. For the internal nodes (LUTs)
+        the number of fanins is the number of inputs of these nodes.
+
+    A demo of using this interface is included at the bottom of file "bblif.c" in 
+    procedure Bbl_ManSimpleDemo(). Additional examples can be found in the files
+    "abc\src\base\io\ioReadBblif.c" and "abc\src\base\io\ioWriteBblif.c". These
+    files illustrate how an ABC network is created from the BBLIF data manager 
+    and how the data manager is created from the ABC network. 
+    
+    Note that only the files "bblif.h" and "bblif.c" are needed for interfacing
+    the user's application with ABC, while other files should not be compiled 
+    as part of the application code.
+
+    Finally, a warning regarding endianness. The interface may not work 
+    if the BBLIF file is produced on a machine whose engianness is different 
+    from the machine, which is reading this file.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+#ifdef _WIN32
+#define inline __inline
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// object types
+typedef enum { 
+    BBL_OBJ_NONE,                // 0: non-existent object
+    BBL_OBJ_CI,                  // 1: primary input
+    BBL_OBJ_CO,                  // 2: primary output
+    BBL_OBJ_NODE,                // 3: buffer node
+    BBL_OBJ_VOID                 // 4: unused object
+} Bbl_Type_t;
+
+// data manager
+typedef struct Bbl_Man_t_ Bbl_Man_t;
+
+// data object
+typedef struct Bbl_Obj_t_ Bbl_Obj_t;
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+// (1) creating the data manager in the application code
+extern Bbl_Man_t * Bbl_ManStart( char * pName );
+extern void        Bbl_ManCreateObject( Bbl_Man_t * p, Bbl_Type_t Type, int ObjId, int nFanins, char * pSop );
+extern void        Bbl_ManAddFanin( Bbl_Man_t * p, int ObjId, int FaninId );
+extern int         Bbl_ManCheck( Bbl_Man_t * p );
+extern void        Bbl_ManPrintStats( Bbl_Man_t * p );
+extern void        Bbl_ManStop( Bbl_Man_t * p );
+
+// (2) writing the data manager into file
+extern void        Bbl_ManDumpBinaryBlif( Bbl_Man_t * p, char * pFileName );
+
+// (3) reading the data manager from file
+extern Bbl_Man_t * Bbl_ManReadBinaryBlif( char * pFileName );
+
+// (4) returning the mapped network after reading the data manaager from file
+extern char *      Bbl_ManName( Bbl_Man_t * p );
+extern int         Bbl_ObjIsInput( Bbl_Obj_t * p );
+extern int         Bbl_ObjIsOutput( Bbl_Obj_t * p );
+extern int         Bbl_ObjIsLut( Bbl_Obj_t * p );
+extern int         Bbl_ObjId( Bbl_Obj_t * p );
+extern int         Bbl_ObjIdOriginal( Bbl_Man_t * pMan, Bbl_Obj_t * p );
+extern int         Bbl_ObjFaninNumber( Bbl_Obj_t * p );
+extern char *      Bbl_ObjSop( Bbl_Man_t * pMan, Bbl_Obj_t * p );
+
+// for the use in iterators only
+extern Bbl_Obj_t * Bbl_ManObjFirst( Bbl_Man_t * p );
+extern Bbl_Obj_t * Bbl_ManObjNext( Bbl_Man_t * p, Bbl_Obj_t * pObj );
+extern Bbl_Obj_t * Bbl_ObjFaninFirst( Bbl_Obj_t * p );
+extern Bbl_Obj_t * Bbl_ObjFaninNext( Bbl_Obj_t * p, Bbl_Obj_t * pPrev );
+
+// iterator through the objects
+#define Bbl_ManForEachObj( p, pObj )                \
+    for ( pObj = Bbl_ManObjFirst(p); pObj; pObj = Bbl_ManObjNext(p, pObj) )
+// iterator through the fanins fo the an object
+#define Bbl_ObjForEachFanin( pObj, pFanin )         \
+    for ( pFanin = Bbl_ObjFaninFirst(pObj); pFanin; pFanin = Bbl_ObjFaninNext(pObj, pFanin) )
+
+// these additional procedures are provided to transform truth tables into SOPs, and vice versa
+extern char *      Bbl_ManTruthToSop( unsigned * pTruth, int nVars );
+extern unsigned *  Bbl_ManSopToTruth( char * pSop, int nVars );
+
+// write text BLIF file for debugging
+extern void        Bbl_ManDumpBlif( Bbl_Man_t * p, char * pFileName );
+
+// a simple demo procedure
+extern void        Bbl_ManSimpleDemo();
+
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/bbl/module.make b/abc-build/src/misc/bbl/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bbl/module.make
@@ -0,0 +1,1 @@
+SRC +=	src/misc/bbl/bblif.c 
diff --git a/abc-build/src/misc/bzlib/CHANGES b/abc-build/src/misc/bzlib/CHANGES
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bzlib/CHANGES
@@ -0,0 +1,319 @@
+ ------------------------------------------------------------------
+ This file is part of bzip2/libbzip2, a program and library for
+ lossless, block-sorting data compression.
+
+ bzip2/libbzip2 version 1.0.5 of 10 December 2007
+ Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+ Please read the WARNING, DISCLAIMER and PATENTS sections in the 
+ README file.
+
+ This program is released under the terms of the license contained
+ in the file LICENSE.
+ ------------------------------------------------------------------
+
+
+0.9.0
+~~~~~
+First version.
+
+
+0.9.0a
+~~~~~~
+Removed 'ranlib' from Makefile, since most modern Unix-es 
+don't need it, or even know about it.
+
+
+0.9.0b
+~~~~~~
+Fixed a problem with error reporting in bzip2.c.  This does not effect
+the library in any way.  Problem is: versions 0.9.0 and 0.9.0a (of the
+program proper) compress and decompress correctly, but give misleading
+error messages (internal panics) when an I/O error occurs, instead of
+reporting the problem correctly.  This shouldn't give any data loss
+(as far as I can see), but is confusing.
+
+Made the inline declarations disappear for non-GCC compilers.
+
+
+0.9.0c
+~~~~~~
+Fixed some problems in the library pertaining to some boundary cases.
+This makes the library behave more correctly in those situations.  The
+fixes apply only to features (calls and parameters) not used by
+bzip2.c, so the non-fixedness of them in previous versions has no
+effect on reliability of bzip2.c.
+
+In bzlib.c:
+   * made zero-length BZ_FLUSH work correctly in bzCompress().
+   * fixed bzWrite/bzRead to ignore zero-length requests.
+   * fixed bzread to correctly handle read requests after EOF.
+   * wrong parameter order in call to bzDecompressInit in
+     bzBuffToBuffDecompress.  Fixed.
+
+In compress.c:
+   * changed setting of nGroups in sendMTFValues() so as to 
+     do a bit better on small files.  This _does_ effect
+     bzip2.c.
+
+
+0.9.5a
+~~~~~~
+Major change: add a fallback sorting algorithm (blocksort.c)
+to give reasonable behaviour even for very repetitive inputs.
+Nuked --repetitive-best and --repetitive-fast since they are
+no longer useful.
+
+Minor changes: mostly a whole bunch of small changes/
+bugfixes in the driver (bzip2.c).  Changes pertaining to the
+user interface are:
+
+   allow decompression of symlink'd files to stdout
+   decompress/test files even without .bz2 extension
+   give more accurate error messages for I/O errors
+   when compressing/decompressing to stdout, don't catch control-C
+   read flags from BZIP2 and BZIP environment variables
+   decline to break hard links to a file unless forced with -f
+   allow -c flag even with no filenames
+   preserve file ownerships as far as possible
+   make -s -1 give the expected block size (100k)
+   add a flag -q --quiet to suppress nonessential warnings
+   stop decoding flags after --, so files beginning in - can be handled
+   resolved inconsistent naming: bzcat or bz2cat ?
+   bzip2 --help now returns 0
+
+Programming-level changes are:
+
+   fixed syntax error in GET_LL4 for Borland C++ 5.02
+   let bzBuffToBuffDecompress return BZ_DATA_ERROR{_MAGIC}
+   fix overshoot of mode-string end in bzopen_or_bzdopen
+   wrapped bzlib.h in #ifdef __cplusplus ... extern "C" { ... }
+   close file handles under all error conditions
+   added minor mods so it compiles with DJGPP out of the box
+   fixed Makefile so it doesn't give problems with BSD make
+   fix uninitialised memory reads in dlltest.c
+
+0.9.5b
+~~~~~~
+Open stdin/stdout in binary mode for DJGPP.
+
+0.9.5c
+~~~~~~
+Changed BZ_N_OVERSHOOT to be ... + 2 instead of ... + 1.  The + 1
+version could cause the sorted order to be wrong in some extremely
+obscure cases.  Also changed setting of quadrant in blocksort.c.
+
+0.9.5d
+~~~~~~
+The only functional change is to make bzlibVersion() in the library
+return the correct string.  This has no effect whatsoever on the
+functioning of the bzip2 program or library.  Added a couple of casts
+so the library compiles without warnings at level 3 in MS Visual
+Studio 6.0.  Included a Y2K statement in the file Y2K_INFO.  All other
+changes are minor documentation changes.
+
+1.0
+~~~
+Several minor bugfixes and enhancements:
+
+* Large file support.  The library uses 64-bit counters to
+  count the volume of data passing through it.  bzip2.c 
+  is now compiled with -D_FILE_OFFSET_BITS=64 to get large
+  file support from the C library.  -v correctly prints out
+  file sizes greater than 4 gigabytes.  All these changes have
+  been made without assuming a 64-bit platform or a C compiler
+  which supports 64-bit ints, so, except for the C library
+  aspect, they are fully portable.
+
+* Decompression robustness.  The library/program should be
+  robust to any corruption of compressed data, detecting and
+  handling _all_ corruption, instead of merely relying on
+  the CRCs.  What this means is that the program should 
+  never crash, given corrupted data, and the library should
+  always return BZ_DATA_ERROR.
+
+* Fixed an obscure race-condition bug only ever observed on
+  Solaris, in which, if you were very unlucky and issued
+  control-C at exactly the wrong time, both input and output
+  files would be deleted.
+
+* Don't run out of file handles on test/decompression when
+  large numbers of files have invalid magic numbers.
+
+* Avoid library namespace pollution.  Prefix all exported 
+  symbols with BZ2_.
+
+* Minor sorting enhancements from my DCC2000 paper.
+
+* Advance the version number to 1.0, so as to counteract the
+  (false-in-this-case) impression some people have that programs 
+  with version numbers less than 1.0 are in some way, experimental,
+  pre-release versions.
+
+* Create an initial Makefile-libbz2_so to build a shared library.
+  Yes, I know I should really use libtool et al ...
+
+* Make the program exit with 2 instead of 0 when decompression
+  fails due to a bad magic number (ie, an invalid bzip2 header).
+  Also exit with 1 (as the manual claims :-) whenever a diagnostic
+  message would have been printed AND the corresponding operation 
+  is aborted, for example
+     bzip2: Output file xx already exists.
+  When a diagnostic message is printed but the operation is not 
+  aborted, for example
+     bzip2: Can't guess original name for wurble -- using wurble.out
+  then the exit value 0 is returned, unless some other problem is
+  also detected.
+
+  I think it corresponds more closely to what the manual claims now.
+
+
+1.0.1
+~~~~~
+* Modified dlltest.c so it uses the new BZ2_ naming scheme.
+* Modified makefile-msc to fix minor build probs on Win2k.
+* Updated README.COMPILATION.PROBLEMS.
+
+There are no functionality changes or bug fixes relative to version
+1.0.0.  This is just a documentation update + a fix for minor Win32
+build problems.  For almost everyone, upgrading from 1.0.0 to 1.0.1 is
+utterly pointless.  Don't bother.
+
+
+1.0.2
+~~~~~
+A bug fix release, addressing various minor issues which have appeared
+in the 18 or so months since 1.0.1 was released.  Most of the fixes
+are to do with file-handling or documentation bugs.  To the best of my
+knowledge, there have been no data-loss-causing bugs reported in the
+compression/decompression engine of 1.0.0 or 1.0.1.
+
+Note that this release does not improve the rather crude build system
+for Unix platforms.  The general plan here is to autoconfiscate/
+libtoolise 1.0.2 soon after release, and release the result as 1.1.0
+or perhaps 1.2.0.  That, however, is still just a plan at this point.
+
+Here are the changes in 1.0.2.  Bug-reporters and/or patch-senders in
+parentheses.
+
+* Fix an infinite segfault loop in 1.0.1 when a directory is
+  encountered in -f (force) mode.
+     (Trond Eivind Glomsrod, Nicholas Nethercote, Volker Schmidt)
+
+* Avoid double fclose() of output file on certain I/O error paths.
+     (Solar Designer)
+
+* Don't fail with internal error 1007 when fed a long stream (> 48MB)
+  of byte 251.  Also print useful message suggesting that 1007s may be
+  caused by bad memory.
+     (noticed by Juan Pedro Vallejo, fixed by me)
+
+* Fix uninitialised variable silly bug in demo prog dlltest.c.
+     (Jorj Bauer)
+
+* Remove 512-MB limitation on recovered file size for bzip2recover
+  on selected platforms which support 64-bit ints.  At the moment
+  all GCC supported platforms, and Win32.
+     (me, Alson van der Meulen)
+
+* Hard-code header byte values, to give correct operation on platforms
+  using EBCDIC as their native character set (IBM's OS/390).
+     (Leland Lucius)
+
+* Copy file access times correctly.
+     (Marty Leisner)
+
+* Add distclean and check targets to Makefile.
+     (Michael Carmack)
+
+* Parameterise use of ar and ranlib in Makefile.  Also add $(LDFLAGS).
+     (Rich Ireland, Bo Thorsen)
+
+* Pass -p (create parent dirs as needed) to mkdir during make install.
+     (Jeremy Fusco)
+
+* Dereference symlinks when copying file permissions in -f mode.
+     (Volker Schmidt)
+
+* Majorly simplify implementation of uInt64_qrm10.
+     (Bo Lindbergh)
+
+* Check the input file still exists before deleting the output one,
+  when aborting in cleanUpAndFail().
+     (Joerg Prante, Robert Linden, Matthias Krings)
+
+Also a bunch of patches courtesy of Philippe Troin, the Debian maintainer
+of bzip2:
+
+* Wrapper scripts (with manpages): bzdiff, bzgrep, bzmore.
+
+* Spelling changes and minor enhancements in bzip2.1.
+
+* Avoid race condition between creating the output file and setting its
+  interim permissions safely, by using fopen_output_safely().
+  No changes to bzip2recover since there is no issue with file
+  permissions there.
+
+* do not print senseless report with -v when compressing an empty
+  file.
+
+* bzcat -f works on non-bzip2 files.
+
+* do not try to escape shell meta-characters on unix (the shell takes
+  care of these).
+
+* added --fast and --best aliases for -1 -9 for gzip compatibility.
+
+
+1.0.3 (15 Feb 05)
+~~~~~~~~~~~~~~~~~
+Fixes some minor bugs since the last version, 1.0.2.
+
+* Further robustification against corrupted compressed data.
+  There are currently no known bitstreams which can cause the
+  decompressor to crash, loop or access memory which does not
+  belong to it.  If you are using bzip2 or the library to 
+  decompress bitstreams from untrusted sources, an upgrade
+  to 1.0.3 is recommended.  This fixes CAN-2005-1260.
+
+* The documentation has been converted to XML, from which html
+  and pdf can be derived.
+
+* Various minor bugs in the documentation have been fixed.
+
+* Fixes for various compilation warnings with newer versions of
+  gcc, and on 64-bit platforms.
+
+* The BZ_NO_STDIO cpp symbol was not properly observed in 1.0.2.
+  This has been fixed.
+
+
+1.0.4 (20 Dec 06)
+~~~~~~~~~~~~~~~~~
+Fixes some minor bugs since the last version, 1.0.3.
+
+* Fix file permissions race problem (CAN-2005-0953).
+
+* Avoid possible segfault in BZ2_bzclose.  From Coverity's NetBSD
+  scan.
+
+* 'const'/prototype cleanups in the C code.
+
+* Change default install location to /usr/local, and handle multiple
+  'make install's without error.
+
+* Sanitise file names more carefully in bzgrep.  Fixes CAN-2005-0758
+  to the extent that applies to bzgrep.
+
+* Use 'mktemp' rather than 'tempfile' in bzdiff.
+
+* Tighten up a couple of assertions in blocksort.c following automated
+  analysis.
+
+* Fix minor doc/comment bugs.
+
+
+1.0.5 (10 Dec 07)
+~~~~~~~~~~~~~~~~~
+Security fix only.  Fixes CERT-FI 20469 as it applies to bzip2.
+
diff --git a/abc-build/src/misc/bzlib/LICENSE b/abc-build/src/misc/bzlib/LICENSE
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bzlib/LICENSE
@@ -0,0 +1,42 @@
+
+--------------------------------------------------------------------------
+
+This program, "bzip2", the associated library "libbzip2", and all
+documentation, are copyright (C) 1996-2007 Julian R Seward.  All
+rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. The origin of this software must not be misrepresented; you must 
+   not claim that you wrote the original software.  If you use this 
+   software in a product, an acknowledgment in the product 
+   documentation would be appreciated but is not required.
+
+3. Altered source versions must be plainly marked as such, and must
+   not be misrepresented as being the original software.
+
+4. The name of the author may not be used to endorse or promote 
+   products derived from this software without specific prior written 
+   permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+
+Julian Seward, jseward@bzip.org
+bzip2/libbzip2 version 1.0.5 of 10 December 2007
+
+--------------------------------------------------------------------------
diff --git a/abc-build/src/misc/bzlib/blocksort.c b/abc-build/src/misc/bzlib/blocksort.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bzlib/blocksort.c
@@ -0,0 +1,1098 @@
+
+/*-------------------------------------------------------------*/
+/*--- Block sorting machinery                               ---*/
+/*---                                           blocksort.c ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+   This file is part of bzip2/libbzip2, a program and library for
+   lossless, block-sorting data compression.
+
+   bzip2/libbzip2 version 1.0.5 of 10 December 2007
+   Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+   Please read the WARNING, DISCLAIMER and PATENTS sections in the 
+   README file.
+
+   This program is released under the terms of the license contained
+   in the file LICENSE.
+   ------------------------------------------------------------------ */
+
+
+#include "bzlib_private.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/*---------------------------------------------*/
+/*--- Fallback O(N log(N)^2) sorting        ---*/
+/*--- algorithm, for repetitive blocks      ---*/
+/*---------------------------------------------*/
+
+/*---------------------------------------------*/
+static 
+__inline__
+void fallbackSimpleSort ( UInt32* fmap, 
+                          UInt32* eclass, 
+                          Int32   lo, 
+                          Int32   hi )
+{
+   Int32 i, j, tmp;
+   UInt32 ec_tmp;
+
+   if (lo == hi) return;
+
+   if (hi - lo > 3) {
+      for ( i = hi-4; i >= lo; i-- ) {
+         tmp = fmap[i];
+         ec_tmp = eclass[tmp];
+         for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 )
+            fmap[j-4] = fmap[j];
+         fmap[j-4] = tmp;
+      }
+   }
+
+   for ( i = hi-1; i >= lo; i-- ) {
+      tmp = fmap[i];
+      ec_tmp = eclass[tmp];
+      for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ )
+         fmap[j-1] = fmap[j];
+      fmap[j-1] = tmp;
+   }
+}
+
+
+/*---------------------------------------------*/
+#define fswap(zz1, zz2) \
+   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
+
+#define fvswap(zzp1, zzp2, zzn)       \
+{                                     \
+   Int32 yyp1 = (zzp1);               \
+   Int32 yyp2 = (zzp2);               \
+   Int32 yyn  = (zzn);                \
+   while (yyn > 0) {                  \
+      fswap(fmap[yyp1], fmap[yyp2]);  \
+      yyp1++; yyp2++; yyn--;          \
+   }                                  \
+}
+
+
+#define fmin(a,b) ((a) < (b)) ? (a) : (b)
+
+#define fpush(lz,hz) { stackLo[sp] = lz; \
+                       stackHi[sp] = hz; \
+                       sp++; }
+
+#define fpop(lz,hz) { sp--;              \
+                      lz = stackLo[sp];  \
+                      hz = stackHi[sp]; }
+
+#define FALLBACK_QSORT_SMALL_THRESH 10
+#define FALLBACK_QSORT_STACK_SIZE   100
+
+
+static
+void fallbackQSort3 ( UInt32* fmap, 
+                      UInt32* eclass,
+                      Int32   loSt, 
+                      Int32   hiSt )
+{
+   Int32 unLo, unHi, ltLo, gtHi, n, m;
+   Int32 sp, lo, hi;
+   UInt32 med, r, r3;
+   Int32 stackLo[FALLBACK_QSORT_STACK_SIZE];
+   Int32 stackHi[FALLBACK_QSORT_STACK_SIZE];
+
+   r = 0;
+
+   sp = 0;
+   fpush ( loSt, hiSt );
+
+   while (sp > 0) {
+
+      AssertH ( sp < FALLBACK_QSORT_STACK_SIZE - 1, 1004 );
+
+      fpop ( lo, hi );
+      if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) {
+         fallbackSimpleSort ( fmap, eclass, lo, hi );
+         continue;
+      }
+
+      /* Random partitioning.  Median of 3 sometimes fails to
+         avoid bad cases.  Median of 9 seems to help but 
+         looks rather expensive.  This too seems to work but
+         is cheaper.  Guidance for the magic constants 
+         7621 and 32768 is taken from Sedgewick's algorithms
+         book, chapter 35.
+      */
+      r = ((r * 7621) + 1) % 32768;
+      r3 = r % 3;
+      if (r3 == 0) med = eclass[fmap[lo]]; else
+      if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else
+                   med = eclass[fmap[hi]];
+
+      unLo = ltLo = lo;
+      unHi = gtHi = hi;
+
+      while (1) {
+         while (1) {
+            if (unLo > unHi) break;
+            n = (Int32)eclass[fmap[unLo]] - (Int32)med;
+            if (n == 0) { 
+               fswap(fmap[unLo], fmap[ltLo]); 
+               ltLo++; unLo++; 
+               continue; 
+            };
+            if (n > 0) break;
+            unLo++;
+         }
+         while (1) {
+            if (unLo > unHi) break;
+            n = (Int32)eclass[fmap[unHi]] - (Int32)med;
+            if (n == 0) { 
+               fswap(fmap[unHi], fmap[gtHi]); 
+               gtHi--; unHi--; 
+               continue; 
+            };
+            if (n < 0) break;
+            unHi--;
+         }
+         if (unLo > unHi) break;
+         fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--;
+      }
+
+      AssertD ( unHi == unLo-1, "fallbackQSort3(2)" );
+
+      if (gtHi < ltLo) continue;
+
+      n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n);
+      m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m);
+
+      n = lo + unLo - ltLo - 1;
+      m = hi - (gtHi - unHi) + 1;
+
+      if (n - lo > hi - m) {
+         fpush ( lo, n );
+         fpush ( m, hi );
+      } else {
+         fpush ( m, hi );
+         fpush ( lo, n );
+      }
+   }
+}
+
+#undef fmin
+#undef fpush
+#undef fpop
+#undef fswap
+#undef fvswap
+#undef FALLBACK_QSORT_SMALL_THRESH
+#undef FALLBACK_QSORT_STACK_SIZE
+
+
+/*---------------------------------------------*/
+/* Pre:
+      nblock > 0
+      eclass exists for [0 .. nblock-1]
+      ((UChar*)eclass) [0 .. nblock-1] holds block
+      ptr exists for [0 .. nblock-1]
+
+   Post:
+      ((UChar*)eclass) [0 .. nblock-1] holds block
+      All other areas of eclass destroyed
+      fmap [0 .. nblock-1] holds sorted order
+      bhtab [ 0 .. 2+(nblock/32) ] destroyed
+*/
+
+#define       SET_BH(zz)  bhtab[(zz) >> 5] |= (1 << ((zz) & 31))
+#define     CLEAR_BH(zz)  bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31))
+#define     ISSET_BH(zz)  (bhtab[(zz) >> 5] & (1 << ((zz) & 31)))
+#define      WORD_BH(zz)  bhtab[(zz) >> 5]
+#define UNALIGNED_BH(zz)  ((zz) & 0x01f)
+
+static
+void fallbackSort ( UInt32* fmap, 
+                    UInt32* eclass, 
+                    UInt32* bhtab,
+                    Int32   nblock,
+                    Int32   verb )
+{
+   Int32 ftab[257];
+   Int32 ftabCopy[256];
+   Int32 H, i, j, k, l, r, cc, cc1;
+   Int32 nNotDone;
+   Int32 nBhtab;
+   UChar* eclass8 = (UChar*)eclass;
+
+   /*--
+      Initial 1-char radix sort to generate
+      initial fmap and initial BH bits.
+   --*/
+   if (verb >= 4)
+      VPrintf0 ( "        bucket sorting ...\n" );
+   for (i = 0; i < 257;    i++) ftab[i] = 0;
+   for (i = 0; i < nblock; i++) ftab[eclass8[i]]++;
+   for (i = 0; i < 256;    i++) ftabCopy[i] = ftab[i];
+   for (i = 1; i < 257;    i++) ftab[i] += ftab[i-1];
+
+   for (i = 0; i < nblock; i++) {
+      j = eclass8[i];
+      k = ftab[j] - 1;
+      ftab[j] = k;
+      fmap[k] = i;
+   }
+
+   nBhtab = 2 + (nblock / 32);
+   for (i = 0; i < nBhtab; i++) bhtab[i] = 0;
+   for (i = 0; i < 256; i++) SET_BH(ftab[i]);
+
+   /*--
+      Inductively refine the buckets.  Kind-of an
+      "exponential radix sort" (!), inspired by the
+      Manber-Myers suffix array construction algorithm.
+   --*/
+
+   /*-- set sentinel bits for block-end detection --*/
+   for (i = 0; i < 32; i++) { 
+      SET_BH(nblock + 2*i);
+      CLEAR_BH(nblock + 2*i + 1);
+   }
+
+   /*-- the log(N) loop --*/
+   H = 1;
+   while (1) {
+
+      if (verb >= 4) 
+         VPrintf1 ( "        depth %6d has ", H );
+
+      j = 0;
+      for (i = 0; i < nblock; i++) {
+         if (ISSET_BH(i)) j = i;
+         k = fmap[i] - H; if (k < 0) k += nblock;
+         eclass[k] = j;
+      }
+
+      nNotDone = 0;
+      r = -1;
+      while (1) {
+
+	 /*-- find the next non-singleton bucket --*/
+         k = r + 1;
+         while (ISSET_BH(k) && UNALIGNED_BH(k)) k++;
+         if (ISSET_BH(k)) {
+            while (WORD_BH(k) == 0xffffffff) k += 32;
+            while (ISSET_BH(k)) k++;
+         }
+         l = k - 1;
+         if (l >= nblock) break;
+         while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++;
+         if (!ISSET_BH(k)) {
+            while (WORD_BH(k) == 0x00000000) k += 32;
+            while (!ISSET_BH(k)) k++;
+         }
+         r = k - 1;
+         if (r >= nblock) break;
+
+         /*-- now [l, r] bracket current bucket --*/
+         if (r > l) {
+            nNotDone += (r - l + 1);
+            fallbackQSort3 ( fmap, eclass, l, r );
+
+            /*-- scan bucket and generate header bits-- */
+            cc = -1;
+            for (i = l; i <= r; i++) {
+               cc1 = eclass[fmap[i]];
+               if (cc != cc1) { SET_BH(i); cc = cc1; };
+            }
+         }
+      }
+
+      if (verb >= 4) 
+         VPrintf1 ( "%6d unresolved strings\n", nNotDone );
+
+      H *= 2;
+      if (H > nblock || nNotDone == 0) break;
+   }
+
+   /*-- 
+      Reconstruct the original block in
+      eclass8 [0 .. nblock-1], since the
+      previous phase destroyed it.
+   --*/
+   if (verb >= 4)
+      VPrintf0 ( "        reconstructing block ...\n" );
+   j = 0;
+   for (i = 0; i < nblock; i++) {
+      while (ftabCopy[j] == 0) j++;
+      ftabCopy[j]--;
+      eclass8[fmap[i]] = (UChar)j;
+   }
+   AssertH ( j < 256, 1005 );
+}
+
+#undef       SET_BH
+#undef     CLEAR_BH
+#undef     ISSET_BH
+#undef      WORD_BH
+#undef UNALIGNED_BH
+
+
+/*---------------------------------------------*/
+/*--- The main, O(N^2 log(N)) sorting       ---*/
+/*--- algorithm.  Faster for "normal"       ---*/
+/*--- non-repetitive blocks.                ---*/
+/*---------------------------------------------*/
+
+/*---------------------------------------------*/
+static
+__inline__
+Bool mainGtU ( UInt32  i1, 
+               UInt32  i2,
+               UChar*  block, 
+               UInt16* quadrant,
+               UInt32  nblock,
+               Int32*  budget )
+{
+   Int32  k;
+   UChar  c1, c2;
+   UInt16 s1, s2;
+
+   AssertD ( i1 != i2, "mainGtU" );
+   /* 1 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 2 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 3 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 4 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 5 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 6 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 7 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 8 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 9 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 10 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 11 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+   /* 12 */
+   c1 = block[i1]; c2 = block[i2];
+   if (c1 != c2) return (c1 > c2);
+   i1++; i2++;
+
+   k = nblock + 8;
+
+   do {
+      /* 1 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 2 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 3 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 4 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 5 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 6 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 7 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+      /* 8 */
+      c1 = block[i1]; c2 = block[i2];
+      if (c1 != c2) return (c1 > c2);
+      s1 = quadrant[i1]; s2 = quadrant[i2];
+      if (s1 != s2) return (s1 > s2);
+      i1++; i2++;
+
+      if (i1 >= nblock) i1 -= nblock;
+      if (i2 >= nblock) i2 -= nblock;
+
+      k -= 8;
+      (*budget)--;
+   }
+      while (k >= 0);
+
+   return False;
+}
+
+
+/*---------------------------------------------*/
+/*--
+   Knuth's increments seem to work better
+   than Incerpi-Sedgewick here.  Possibly
+   because the number of elems to sort is
+   usually small, typically <= 20.
+--*/
+static
+Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
+                   9841, 29524, 88573, 265720,
+                   797161, 2391484 };
+
+static
+void mainSimpleSort ( UInt32* ptr,
+                      UChar*  block,
+                      UInt16* quadrant,
+                      Int32   nblock,
+                      Int32   lo, 
+                      Int32   hi, 
+                      Int32   d,
+                      Int32*  budget )
+{
+   Int32 i, j, h, bigN, hp;
+   UInt32 v;
+
+   bigN = hi - lo + 1;
+   if (bigN < 2) return;
+
+   hp = 0;
+   while (incs[hp] < bigN) hp++;
+   hp--;
+
+   for (; hp >= 0; hp--) {
+      h = incs[hp];
+
+      i = lo + h;
+      while (True) {
+
+         /*-- copy 1 --*/
+         if (i > hi) break;
+         v = ptr[i];
+         j = i;
+         while ( mainGtU ( 
+                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
+                 ) ) {
+            ptr[j] = ptr[j-h];
+            j = j - h;
+            if (j <= (lo + h - 1)) break;
+         }
+         ptr[j] = v;
+         i++;
+
+         /*-- copy 2 --*/
+         if (i > hi) break;
+         v = ptr[i];
+         j = i;
+         while ( mainGtU ( 
+                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
+                 ) ) {
+            ptr[j] = ptr[j-h];
+            j = j - h;
+            if (j <= (lo + h - 1)) break;
+         }
+         ptr[j] = v;
+         i++;
+
+         /*-- copy 3 --*/
+         if (i > hi) break;
+         v = ptr[i];
+         j = i;
+         while ( mainGtU ( 
+                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
+                 ) ) {
+            ptr[j] = ptr[j-h];
+            j = j - h;
+            if (j <= (lo + h - 1)) break;
+         }
+         ptr[j] = v;
+         i++;
+
+         if (*budget < 0) return;
+      }
+   }
+}
+
+
+/*---------------------------------------------*/
+/*--
+   The following is an implementation of
+   an elegant 3-way quicksort for strings,
+   described in a paper "Fast Algorithms for
+   Sorting and Searching Strings", by Robert
+   Sedgewick and Jon L. Bentley.
+--*/
+
+#define mswap(zz1, zz2) \
+   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
+
+#define mvswap(zzp1, zzp2, zzn)       \
+{                                     \
+   Int32 yyp1 = (zzp1);               \
+   Int32 yyp2 = (zzp2);               \
+   Int32 yyn  = (zzn);                \
+   while (yyn > 0) {                  \
+      mswap(ptr[yyp1], ptr[yyp2]);    \
+      yyp1++; yyp2++; yyn--;          \
+   }                                  \
+}
+
+static 
+__inline__
+UChar mmed3 ( UChar a, UChar b, UChar c )
+{
+   UChar t;
+   if (a > b) { t = a; a = b; b = t; };
+   if (b > c) { 
+      b = c;
+      if (a > b) b = a;
+   }
+   return b;
+}
+
+#define mmin(a,b) ((a) < (b)) ? (a) : (b)
+
+#define mpush(lz,hz,dz) { stackLo[sp] = lz; \
+                          stackHi[sp] = hz; \
+                          stackD [sp] = dz; \
+                          sp++; }
+
+#define mpop(lz,hz,dz) { sp--;             \
+                         lz = stackLo[sp]; \
+                         hz = stackHi[sp]; \
+                         dz = stackD [sp]; }
+
+
+#define mnextsize(az) (nextHi[az]-nextLo[az])
+
+#define mnextswap(az,bz)                                        \
+   { Int32 tz;                                                  \
+     tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \
+     tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \
+     tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; }
+
+
+#define MAIN_QSORT_SMALL_THRESH 20
+#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT)
+#define MAIN_QSORT_STACK_SIZE 100
+
+static
+void mainQSort3 ( UInt32* ptr,
+                  UChar*  block,
+                  UInt16* quadrant,
+                  Int32   nblock,
+                  Int32   loSt, 
+                  Int32   hiSt, 
+                  Int32   dSt,
+                  Int32*  budget )
+{
+   Int32 unLo, unHi, ltLo, gtHi, n, m, med;
+   Int32 sp, lo, hi, d;
+
+   Int32 stackLo[MAIN_QSORT_STACK_SIZE];
+   Int32 stackHi[MAIN_QSORT_STACK_SIZE];
+   Int32 stackD [MAIN_QSORT_STACK_SIZE];
+
+   Int32 nextLo[3];
+   Int32 nextHi[3];
+   Int32 nextD [3];
+
+   sp = 0;
+   mpush ( loSt, hiSt, dSt );
+
+   while (sp > 0) {
+
+      AssertH ( sp < MAIN_QSORT_STACK_SIZE - 2, 1001 );
+
+      mpop ( lo, hi, d );
+      if (hi - lo < MAIN_QSORT_SMALL_THRESH || 
+          d > MAIN_QSORT_DEPTH_THRESH) {
+         mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget );
+         if (*budget < 0) return;
+         continue;
+      }
+
+      med = (Int32) 
+            mmed3 ( block[ptr[ lo         ]+d],
+                    block[ptr[ hi         ]+d],
+                    block[ptr[ (lo+hi)>>1 ]+d] );
+
+      unLo = ltLo = lo;
+      unHi = gtHi = hi;
+
+      while (True) {
+         while (True) {
+            if (unLo > unHi) break;
+            n = ((Int32)block[ptr[unLo]+d]) - med;
+            if (n == 0) { 
+               mswap(ptr[unLo], ptr[ltLo]); 
+               ltLo++; unLo++; continue; 
+            };
+            if (n >  0) break;
+            unLo++;
+         }
+         while (True) {
+            if (unLo > unHi) break;
+            n = ((Int32)block[ptr[unHi]+d]) - med;
+            if (n == 0) { 
+               mswap(ptr[unHi], ptr[gtHi]); 
+               gtHi--; unHi--; continue; 
+            };
+            if (n <  0) break;
+            unHi--;
+         }
+         if (unLo > unHi) break;
+         mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--;
+      }
+
+      AssertD ( unHi == unLo-1, "mainQSort3(2)" );
+
+      if (gtHi < ltLo) {
+         mpush(lo, hi, d+1 );
+         continue;
+      }
+
+      n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n);
+      m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m);
+
+      n = lo + unLo - ltLo - 1;
+      m = hi - (gtHi - unHi) + 1;
+
+      nextLo[0] = lo;  nextHi[0] = n;   nextD[0] = d;
+      nextLo[1] = m;   nextHi[1] = hi;  nextD[1] = d;
+      nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1;
+
+      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
+      if (mnextsize(1) < mnextsize(2)) mnextswap(1,2);
+      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
+
+      AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" );
+      AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" );
+
+      mpush (nextLo[0], nextHi[0], nextD[0]);
+      mpush (nextLo[1], nextHi[1], nextD[1]);
+      mpush (nextLo[2], nextHi[2], nextD[2]);
+   }
+}
+
+#undef mswap
+#undef mvswap
+#undef mpush
+#undef mpop
+#undef mmin
+#undef mnextsize
+#undef mnextswap
+#undef MAIN_QSORT_SMALL_THRESH
+#undef MAIN_QSORT_DEPTH_THRESH
+#undef MAIN_QSORT_STACK_SIZE
+
+
+/*---------------------------------------------*/
+/* Pre:
+      nblock > N_OVERSHOOT
+      block32 exists for [0 .. nblock-1 +N_OVERSHOOT]
+      ((UChar*)block32) [0 .. nblock-1] holds block
+      ptr exists for [0 .. nblock-1]
+
+   Post:
+      ((UChar*)block32) [0 .. nblock-1] holds block
+      All other areas of block32 destroyed
+      ftab [0 .. 65536 ] destroyed
+      ptr [0 .. nblock-1] holds sorted order
+      if (*budget < 0), sorting was abandoned
+*/
+
+#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8])
+#define SETMASK (1 << 21)
+#define CLEARMASK (~(SETMASK))
+
+static
+void mainSort ( UInt32* ptr, 
+                UChar*  block,
+                UInt16* quadrant, 
+                UInt32* ftab,
+                Int32   nblock,
+                Int32   verb,
+                Int32*  budget )
+{
+   Int32  i, j, k, ss, sb;
+   Int32  runningOrder[256];
+   Bool   bigDone[256];
+   Int32  copyStart[256];
+   Int32  copyEnd  [256];
+   UChar  c1;
+   Int32  numQSorted;
+   UInt16 s;
+   if (verb >= 4) VPrintf0 ( "        main sort initialise ...\n" );
+
+   /*-- set up the 2-byte frequency table --*/
+   for (i = 65536; i >= 0; i--) ftab[i] = 0;
+
+   j = block[0] << 8;
+   i = nblock-1;
+   for (; i >= 3; i -= 4) {
+      quadrant[i] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
+      ftab[j]++;
+      quadrant[i-1] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i-1]) << 8);
+      ftab[j]++;
+      quadrant[i-2] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i-2]) << 8);
+      ftab[j]++;
+      quadrant[i-3] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i-3]) << 8);
+      ftab[j]++;
+   }
+   for (; i >= 0; i--) {
+      quadrant[i] = 0;
+      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
+      ftab[j]++;
+   }
+
+   /*-- (emphasises close relationship of block & quadrant) --*/
+   for (i = 0; i < BZ_N_OVERSHOOT; i++) {
+      block   [nblock+i] = block[i];
+      quadrant[nblock+i] = 0;
+   }
+
+   if (verb >= 4) VPrintf0 ( "        bucket sorting ...\n" );
+
+   /*-- Complete the initial radix sort --*/
+   for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1];
+
+   s = block[0] << 8;
+   i = nblock-1;
+   for (; i >= 3; i -= 4) {
+      s = (s >> 8) | (block[i] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i;
+      s = (s >> 8) | (block[i-1] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i-1;
+      s = (s >> 8) | (block[i-2] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i-2;
+      s = (s >> 8) | (block[i-3] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i-3;
+   }
+   for (; i >= 0; i--) {
+      s = (s >> 8) | (block[i] << 8);
+      j = ftab[s] -1;
+      ftab[s] = j;
+      ptr[j] = i;
+   }
+
+   /*--
+      Now ftab contains the first loc of every small bucket.
+      Calculate the running order, from smallest to largest
+      big bucket.
+   --*/
+   for (i = 0; i <= 255; i++) {
+      bigDone     [i] = False;
+      runningOrder[i] = i;
+   }
+
+   {
+      Int32 vv;
+      Int32 h = 1;
+      do h = 3 * h + 1; while (h <= 256);
+      do {
+         h = h / 3;
+         for (i = h; i <= 255; i++) {
+            vv = runningOrder[i];
+            j = i;
+            while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) {
+               runningOrder[j] = runningOrder[j-h];
+               j = j - h;
+               if (j <= (h - 1)) goto zero;
+            }
+            zero:
+            runningOrder[j] = vv;
+         }
+      } while (h != 1);
+   }
+
+   /*--
+      The main sorting loop.
+   --*/
+
+   numQSorted = 0;
+
+   for (i = 0; i <= 255; i++) {
+
+      /*--
+         Process big buckets, starting with the least full.
+         Basically this is a 3-step process in which we call
+         mainQSort3 to sort the small buckets [ss, j], but
+         also make a big effort to avoid the calls if we can.
+      --*/
+      ss = runningOrder[i];
+
+      /*--
+         Step 1:
+         Complete the big bucket [ss] by quicksorting
+         any unsorted small buckets [ss, j], for j != ss.  
+         Hopefully previous pointer-scanning phases have already
+         completed many of the small buckets [ss, j], so
+         we don't have to sort them at all.
+      --*/
+      for (j = 0; j <= 255; j++) {
+         if (j != ss) {
+            sb = (ss << 8) + j;
+            if ( ! (ftab[sb] & SETMASK) ) {
+               Int32 lo = ftab[sb]   & CLEARMASK;
+               Int32 hi = (ftab[sb+1] & CLEARMASK) - 1;
+               if (hi > lo) {
+                  if (verb >= 4)
+                     VPrintf4 ( "        qsort [0x%x, 0x%x]   "
+                                "done %d   this %d\n",
+                                ss, j, numQSorted, hi - lo + 1 );
+                  mainQSort3 ( 
+                     ptr, block, quadrant, nblock, 
+                     lo, hi, BZ_N_RADIX, budget 
+                  );   
+                  numQSorted += (hi - lo + 1);
+                  if (*budget < 0) return;
+               }
+            }
+            ftab[sb] |= SETMASK;
+         }
+      }
+
+      AssertH ( !bigDone[ss], 1006 );
+
+      /*--
+         Step 2:
+         Now scan this big bucket [ss] so as to synthesise the
+         sorted order for small buckets [t, ss] for all t,
+         including, magically, the bucket [ss,ss] too.
+         This will avoid doing Real Work in subsequent Step 1's.
+      --*/
+      {
+         for (j = 0; j <= 255; j++) {
+            copyStart[j] =  ftab[(j << 8) + ss]     & CLEARMASK;
+            copyEnd  [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1;
+         }
+         for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) {
+            k = ptr[j]-1; if (k < 0) k += nblock;
+            c1 = block[k];
+            if (!bigDone[c1])
+               ptr[ copyStart[c1]++ ] = k;
+         }
+         for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) {
+            k = ptr[j]-1; if (k < 0) k += nblock;
+            c1 = block[k];
+            if (!bigDone[c1]) 
+               ptr[ copyEnd[c1]-- ] = k;
+         }
+      }
+
+      AssertH ( (copyStart[ss]-1 == copyEnd[ss])
+                || 
+                /* Extremely rare case missing in bzip2-1.0.0 and 1.0.1.
+                   Necessity for this case is demonstrated by compressing 
+                   a sequence of approximately 48.5 million of character 
+                   251; 1.0.0/1.0.1 will then die here. */
+                (copyStart[ss] == 0 && copyEnd[ss] == nblock-1),
+                1007 )
+
+      for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK;
+
+      /*--
+         Step 3:
+         The [ss] big bucket is now done.  Record this fact,
+         and update the quadrant descriptors.  Remember to
+         update quadrants in the overshoot area too, if
+         necessary.  The "if (i < 255)" test merely skips
+         this updating for the last bucket processed, since
+         updating for the last bucket is pointless.
+
+         The quadrant array provides a way to incrementally
+         cache sort orderings, as they appear, so as to 
+         make subsequent comparisons in fullGtU() complete
+         faster.  For repetitive blocks this makes a big
+         difference (but not big enough to be able to avoid
+         the fallback sorting mechanism, exponential radix sort).
+
+         The precise meaning is: at all times:
+
+            for 0 <= i < nblock and 0 <= j <= nblock
+
+            if block[i] != block[j], 
+
+               then the relative values of quadrant[i] and 
+                    quadrant[j] are meaningless.
+
+               else {
+                  if quadrant[i] < quadrant[j]
+                     then the string starting at i lexicographically
+                     precedes the string starting at j
+
+                  else if quadrant[i] > quadrant[j]
+                     then the string starting at j lexicographically
+                     precedes the string starting at i
+
+                  else
+                     the relative ordering of the strings starting
+                     at i and j has not yet been determined.
+               }
+      --*/
+      bigDone[ss] = True;
+
+      if (i < 255) {
+         Int32 bbStart  = ftab[ss << 8] & CLEARMASK;
+         Int32 bbSize   = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
+         Int32 shifts   = 0;
+
+         while ((bbSize >> shifts) > 65534) shifts++;
+
+         for (j = bbSize-1; j >= 0; j--) {
+            Int32 a2update     = ptr[bbStart + j];
+            UInt16 qVal        = (UInt16)(j >> shifts);
+            quadrant[a2update] = qVal;
+            if (a2update < BZ_N_OVERSHOOT)
+               quadrant[a2update + nblock] = qVal;
+         }
+         AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 );
+      }
+
+   }
+
+   if (verb >= 4)
+      VPrintf3 ( "        %d pointers, %d sorted, %d scanned\n",
+                 nblock, numQSorted, nblock - numQSorted );
+}
+
+#undef BIGFREQ
+#undef SETMASK
+#undef CLEARMASK
+
+
+/*---------------------------------------------*/
+/* Pre:
+      nblock > 0
+      arr2 exists for [0 .. nblock-1 +N_OVERSHOOT]
+      ((UChar*)arr2)  [0 .. nblock-1] holds block
+      arr1 exists for [0 .. nblock-1]
+
+   Post:
+      ((UChar*)arr2) [0 .. nblock-1] holds block
+      All other areas of block destroyed
+      ftab [ 0 .. 65536 ] destroyed
+      arr1 [0 .. nblock-1] holds sorted order
+*/
+void BZ2_blockSort ( EState* s )
+{
+   UInt32* ptr    = s->ptr; 
+   UChar*  block  = s->block;
+   UInt32* ftab   = s->ftab;
+   Int32   nblock = s->nblock;
+   Int32   verb   = s->verbosity;
+   Int32   wfact  = s->workFactor;
+   UInt16* quadrant;
+   Int32   budget;
+   Int32   budgetInit;
+   Int32   i;
+
+   if (nblock < 10000) {
+      fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
+   } else {
+      /* Calculate the location for quadrant, remembering to get
+         the alignment right.  Assumes that &(block[0]) is at least
+         2-byte aligned -- this should be ok since block is really
+         the first section of arr2.
+      */
+      i = nblock+BZ_N_OVERSHOOT;
+      if (i & 1) i++;
+      quadrant = (UInt16*)(&(block[i]));
+
+      /* (wfact-1) / 3 puts the default-factor-30
+         transition point at very roughly the same place as 
+         with v0.1 and v0.9.0.  
+         Not that it particularly matters any more, since the
+         resulting compressed stream is now the same regardless
+         of whether or not we use the main sort or fallback sort.
+      */
+      if (wfact < 1  ) wfact = 1;
+      if (wfact > 100) wfact = 100;
+      budgetInit = nblock * ((wfact-1) / 3);
+      budget = budgetInit;
+
+      mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget );
+      if (verb >= 3) 
+         VPrintf3 ( "      %d work, %d block, ratio %5.2f\n",
+                    budgetInit - budget,
+                    nblock, 
+                    (float)(budgetInit - budget) /
+                    (float)(nblock==0 ? 1 : nblock) ); 
+      if (budget < 0) {
+         if (verb >= 2) 
+            VPrintf0 ( "    too repetitive; using fallback"
+                       " sorting algorithm\n" );
+         fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
+      }
+   }
+
+   s->origPtr = -1;
+   for (i = 0; i < s->nblock; i++)
+      if (ptr[i] == 0)
+         { s->origPtr = i; break; };
+
+   AssertH( s->origPtr != -1, 1003 );
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                       blocksort.c ---*/
+/*-------------------------------------------------------------*/
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/misc/bzlib/bzip2.txt b/abc-build/src/misc/bzlib/bzip2.txt
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bzlib/bzip2.txt
@@ -0,0 +1,391 @@
+
+NAME
+       bzip2, bunzip2 - a block-sorting file compressor, v1.0.4
+       bzcat - decompresses files to stdout
+       bzip2recover - recovers data from damaged bzip2 files
+
+
+SYNOPSIS
+       bzip2 [ -cdfkqstvzVL123456789 ] [ filenames ...  ]
+       bunzip2 [ -fkvsVL ] [ filenames ...  ]
+       bzcat [ -s ] [ filenames ...  ]
+       bzip2recover filename
+
+
+DESCRIPTION
+       bzip2  compresses  files  using  the Burrows-Wheeler block
+       sorting text compression algorithm,  and  Huffman  coding.
+       Compression  is  generally  considerably  better than that
+       achieved by more conventional LZ77/LZ78-based compressors,
+       and  approaches  the performance of the PPM family of sta-
+       tistical compressors.
+
+       The command-line options are deliberately very similar  to
+       those of GNU gzip, but they are not identical.
+
+       bzip2  expects  a list of file names to accompany the com-
+       mand-line flags.  Each file is replaced  by  a  compressed
+       version  of  itself,  with  the  name "original_name.bz2".
+       Each compressed file has the same modification date,  per-
+       missions, and, when possible, ownership as the correspond-
+       ing original, so that these properties  can  be  correctly
+       restored  at  decompression  time.   File name handling is
+       naive in the sense that there is no mechanism for preserv-
+       ing  original file names, permissions, ownerships or dates
+       in filesystems which lack these concepts, or have  serious
+       file name length restrictions, such as MS-DOS.
+
+       bzip2  and  bunzip2 will by default not overwrite existing
+       files.  If you want this to happen, specify the -f flag.
+
+       If no file names  are  specified,  bzip2  compresses  from
+       standard  input  to  standard output.  In this case, bzip2
+       will decline to write compressed output to a terminal,  as
+       this  would  be  entirely  incomprehensible  and therefore
+       pointless.
+
+       bunzip2 (or bzip2 -d) decompresses  all  specified  files.
+       Files which were not created by bzip2 will be detected and
+       ignored, and a warning issued.  bzip2  attempts  to  guess
+       the  filename  for  the decompressed file from that of the
+       compressed file as follows:
+
+              filename.bz2    becomes   filename
+              filename.bz     becomes   filename
+              filename.tbz2   becomes   filename.tar
+              filename.tbz    becomes   filename.tar
+              anyothername    becomes   anyothername.out
+
+       If the file does not end in one of the recognised endings,
+       .bz2,  .bz,  .tbz2 or .tbz, bzip2 complains that it cannot
+       guess the name of the original file, and uses the original
+       name with .out appended.
+
+       As  with compression, supplying no filenames causes decom-
+       pression from standard input to standard output.
+
+       bunzip2 will correctly decompress a file which is the con-
+       catenation of two or more compressed files.  The result is
+       the concatenation of the corresponding uncompressed files.
+       Integrity testing (-t) of concatenated compressed files is
+       also supported.
+
+       You can also compress or decompress files to the  standard
+       output  by giving the -c flag.  Multiple files may be com-
+       pressed and decompressed like this.  The resulting outputs
+       are  fed  sequentially to stdout.  Compression of multiple
+       files in this manner generates a stream containing  multi-
+       ple compressed file representations.  Such a stream can be
+       decompressed correctly only  by  bzip2  version  0.9.0  or
+       later.   Earlier  versions of bzip2 will stop after decom-
+       pressing the first file in the stream.
+
+       bzcat (or bzip2 -dc) decompresses all specified  files  to
+       the standard output.
+
+       bzip2  will  read arguments from the environment variables
+       BZIP2 and BZIP, in  that  order,  and  will  process  them
+       before  any  arguments  read  from the command line.  This
+       gives a convenient way to supply default arguments.
+
+       Compression is always performed, even  if  the  compressed
+       file  is slightly larger than the original.  Files of less
+       than about one hundred bytes tend to get larger, since the
+       compression  mechanism  has  a  constant  overhead  in the
+       region of 50 bytes.  Random data (including the output  of
+       most  file  compressors)  is  coded at about 8.05 bits per
+       byte, giving an expansion of around 0.5%.
+
+       As a self-check for your  protection,  bzip2  uses  32-bit
+       CRCs  to make sure that the decompressed version of a file
+       is identical to the original.  This guards against corrup-
+       tion  of  the compressed data, and against undetected bugs
+       in bzip2 (hopefully very unlikely).  The chances  of  data
+       corruption  going  undetected  is  microscopic,  about one
+       chance in four billion for each file processed.  Be aware,
+       though,  that  the  check occurs upon decompression, so it
+       can only tell you that something is wrong.  It can't  help
+       you  recover  the original uncompressed data.  You can use
+       bzip2recover to try to recover data from damaged files.
+
+       Return values: 0 for a normal exit,  1  for  environmental
+       problems  (file not found, invalid flags, I/O errors, &c),
+       2 to indicate a corrupt compressed file, 3 for an internal
+       consistency error (eg, bug) which caused bzip2 to panic.
+
+
+OPTIONS
+       -c --stdout
+              Compress or decompress to standard output.
+
+       -d --decompress
+              Force  decompression.  bzip2, bunzip2 and bzcat are
+              really the same program,  and  the  decision  about
+              what  actions to take is done on the basis of which
+              name is used.  This flag overrides that  mechanism,
+              and forces bzip2 to decompress.
+
+       -z --compress
+              The   complement   to   -d:   forces   compression,
+              regardless of the invocation name.
+
+       -t --test
+              Check integrity of the specified file(s), but don't
+              decompress  them.   This  really  performs  a trial
+              decompression and throws away the result.
+
+       -f --force
+              Force overwrite of output files.   Normally,  bzip2
+              will  not  overwrite  existing  output files.  Also
+              forces bzip2 to break hard links to files, which it
+              otherwise wouldn't do.
+
+              bzip2  normally  declines to decompress files which
+              don't have the  correct  magic  header  bytes.   If
+              forced  (-f),  however,  it  will  pass  such files
+              through unmodified.  This is how GNU gzip  behaves.
+
+       -k --keep
+              Keep  (don't delete) input files during compression
+              or decompression.
+
+       -s --small
+              Reduce memory usage, for compression, decompression
+              and  testing.   Files  are  decompressed and tested
+              using a modified algorithm which only requires  2.5
+              bytes  per  block byte.  This means any file can be
+              decompressed in 2300k of memory,  albeit  at  about
+              half the normal speed.
+
+              During  compression,  -s  selects  a  block size of
+              200k, which limits memory use to  around  the  same
+              figure,  at  the expense of your compression ratio.
+              In short, if your  machine  is  low  on  memory  (8
+              megabytes  or  less),  use  -s for everything.  See
+              MEMORY MANAGEMENT below.
+
+       -q --quiet
+              Suppress non-essential warning messages.   Messages
+              pertaining  to I/O errors and other critical events
+              will not be suppressed.
+
+       -v --verbose
+              Verbose mode -- show the compression ratio for each
+              file  processed.   Further  -v's  increase the ver-
+              bosity level, spewing out lots of information which
+              is primarily of interest for diagnostic purposes.
+
+       -L --license -V --version
+              Display  the  software  version,  license terms and
+              conditions.
+
+       -1 (or --fast) to -9 (or --best)
+              Set the block size to 100 k, 200 k ..  900  k  when
+              compressing.   Has  no  effect  when decompressing.
+              See MEMORY MANAGEMENT below.  The --fast and --best
+              aliases  are  primarily for GNU gzip compatibility.
+              In particular, --fast doesn't make things  signifi-
+              cantly  faster.   And  --best  merely  selects  the
+              default behaviour.
+
+       --     Treats all subsequent arguments as file names, even
+              if they start with a dash.  This is so you can han-
+              dle files with names beginning  with  a  dash,  for
+              example: bzip2 -- -myfilename.
+
+       --repetitive-fast --repetitive-best
+              These  flags  are  redundant  in versions 0.9.5 and
+              above.  They provided some coarse control over  the
+              behaviour  of the sorting algorithm in earlier ver-
+              sions, which was sometimes useful.  0.9.5 and above
+              have  an  improved  algorithm  which  renders these
+              flags irrelevant.
+
+
+MEMORY MANAGEMENT
+       bzip2 compresses large files in blocks.   The  block  size
+       affects  both  the  compression  ratio  achieved,  and the
+       amount of memory needed for compression and decompression.
+       The  flags  -1  through  -9  specify  the block size to be
+       100,000 bytes through 900,000 bytes (the default)  respec-
+       tively.   At  decompression  time, the block size used for
+       compression is read from  the  header  of  the  compressed
+       file, and bunzip2 then allocates itself just enough memory
+       to decompress the file.  Since block sizes are  stored  in
+       compressed  files,  it follows that the flags -1 to -9 are
+       irrelevant to and so ignored during decompression.
+
+       Compression and decompression requirements, in bytes,  can
+       be estimated as:
+
+              Compression:   400k + ( 8 x block size )
+
+              Decompression: 100k + ( 4 x block size ), or
+                             100k + ( 2.5 x block size )
+
+       Larger  block  sizes  give  rapidly  diminishing  marginal
+       returns.  Most of the compression comes from the first two
+       or  three hundred k of block size, a fact worth bearing in
+       mind when using bzip2  on  small  machines.   It  is  also
+       important  to  appreciate  that  the  decompression memory
+       requirement is set at compression time by  the  choice  of
+       block size.
+
+       For  files  compressed  with  the default 900k block size,
+       bunzip2 will require about 3700 kbytes to decompress.   To
+       support decompression of any file on a 4 megabyte machine,
+       bunzip2 has an option to  decompress  using  approximately
+       half this amount of memory, about 2300 kbytes.  Decompres-
+       sion speed is also halved, so you should use  this  option
+       only where necessary.  The relevant flag is -s.
+
+       In general, try and use the largest block size memory con-
+       straints  allow,  since  that  maximises  the  compression
+       achieved.   Compression and decompression speed are virtu-
+       ally unaffected by block size.
+
+       Another significant point applies to files which fit in  a
+       single  block  --  that  means  most files you'd encounter
+       using a large block  size.   The  amount  of  real  memory
+       touched is proportional to the size of the file, since the
+       file is smaller than a block.  For example, compressing  a
+       file  20,000  bytes  long  with the flag -9 will cause the
+       compressor to allocate around 7600k of  memory,  but  only
+       touch 400k + 20000 * 8 = 560 kbytes of it.  Similarly, the
+       decompressor will allocate 3700k but  only  touch  100k  +
+       20000 * 4 = 180 kbytes.
+
+       Here  is a table which summarises the maximum memory usage
+       for different block sizes.  Also  recorded  is  the  total
+       compressed  size for 14 files of the Calgary Text Compres-
+       sion Corpus totalling 3,141,622 bytes.  This column  gives
+       some  feel  for  how  compression  varies with block size.
+       These figures tend to understate the advantage  of  larger
+       block  sizes  for  larger files, since the Corpus is domi-
+       nated by smaller files.
+
+                  Compress   Decompress   Decompress   Corpus
+           Flag     usage      usage       -s usage     Size
+
+            -1      1200k       500k         350k      914704
+            -2      2000k       900k         600k      877703
+            -3      2800k      1300k         850k      860338
+            -4      3600k      1700k        1100k      846899
+            -5      4400k      2100k        1350k      845160
+            -6      5200k      2500k        1600k      838626
+            -7      6100k      2900k        1850k      834096
+            -8      6800k      3300k        2100k      828642
+            -9      7600k      3700k        2350k      828642
+
+
+RECOVERING DATA FROM DAMAGED FILES
+       bzip2 compresses files in blocks, usually 900kbytes  long.
+       Each block is handled independently.  If a media or trans-
+       mission error causes a multi-block  .bz2  file  to  become
+       damaged,  it  may  be  possible  to  recover data from the
+       undamaged blocks in the file.
+
+       The compressed representation of each block  is  delimited
+       by  a  48-bit pattern, which makes it possible to find the
+       block boundaries with reasonable  certainty.   Each  block
+       also  carries its own 32-bit CRC, so damaged blocks can be
+       distinguished from undamaged ones.
+
+       bzip2recover is a  simple  program  whose  purpose  is  to
+       search  for blocks in .bz2 files, and write each block out
+       into its own .bz2 file.  You can then use bzip2 -t to test
+       the integrity of the resulting files, and decompress those
+       which are undamaged.
+
+       bzip2recover takes a single argument, the name of the dam-
+       aged    file,    and    writes    a    number   of   files
+       "rec00001file.bz2",  "rec00002file.bz2",  etc,  containing
+       the   extracted   blocks.   The   output   filenames   are
+       designed  so  that the use of wildcards in subsequent pro-
+       cessing  -- for example, "bzip2 -dc  rec*file.bz2 > recov-
+       ered_data" -- processes the files in the correct order.
+
+       bzip2recover should be of most use dealing with large .bz2
+       files,  as  these will contain many blocks.  It is clearly
+       futile to use it on damaged single-block  files,  since  a
+       damaged  block  cannot  be recovered.  If you wish to min-
+       imise any potential data loss through media  or  transmis-
+       sion errors, you might consider compressing with a smaller
+       block size.
+
+
+PERFORMANCE NOTES
+       The sorting phase of compression gathers together  similar
+       strings  in  the  file.  Because of this, files containing
+       very long runs of  repeated  symbols,  like  "aabaabaabaab
+       ..."   (repeated  several hundred times) may compress more
+       slowly than normal.  Versions 0.9.5 and  above  fare  much
+       better  than previous versions in this respect.  The ratio
+       between worst-case and average-case compression time is in
+       the  region  of  10:1.  For previous versions, this figure
+       was more like 100:1.  You can use the -vvvv option to mon-
+       itor progress in great detail, if you want.
+
+       Decompression speed is unaffected by these phenomena.
+
+       bzip2  usually  allocates  several  megabytes of memory to
+       operate in, and then charges all over it in a fairly  ran-
+       dom  fashion.   This means that performance, both for com-
+       pressing and decompressing, is largely determined  by  the
+       speed  at  which  your  machine  can service cache misses.
+       Because of this, small changes to the code to  reduce  the
+       miss  rate  have  been observed to give disproportionately
+       large performance improvements.  I imagine bzip2 will per-
+       form best on machines with very large caches.
+
+
+CAVEATS
+       I/O  error  messages  are not as helpful as they could be.
+       bzip2 tries hard to detect I/O errors  and  exit  cleanly,
+       but  the  details  of  what  the problem is sometimes seem
+       rather misleading.
+
+       This manual page pertains to version 1.0.4 of bzip2.  Com-
+       pressed  data created by this version is entirely forwards
+       and  backwards  compatible  with   the   previous   public
+       releases,  versions  0.1pl2,  0.9.0,  0.9.5, 1.0.0, 1.0.1,
+       1.0.2 and 1.0.3, but with the  following  exception: 0.9.0
+       and above can  correctly decompress  multiple concatenated
+       compressed files.  0.1pl2  cannot do this;  it  will  stop
+       after  decompressing just the first file in the stream.
+
+       bzip2recover  versions prior to 1.0.2 used 32-bit integers
+       to represent bit positions in compressed  files,  so  they
+       could  not handle compressed files more than 512 megabytes
+       long.  Versions 1.0.2 and above use 64-bit  ints  on  some
+       platforms  which  support them (GNU supported targets, and
+       Windows).  To establish whether or  not  bzip2recover  was
+       built  with  such  a limitation, run it without arguments.
+       In any event you can build yourself an  unlimited  version
+       if  you  can  recompile  it  with MaybeUInt64 set to be an
+       unsigned 64-bit integer.
+
+
+AUTHOR
+       Julian Seward, jsewardbzip.org.
+
+       http://www.bzip.org
+
+       The ideas embodied in bzip2 are due to (at least) the fol-
+       lowing  people: Michael Burrows and David Wheeler (for the
+       block sorting transformation), David Wheeler  (again,  for
+       the Huffman coder), Peter Fenwick (for the structured cod-
+       ing model in the original bzip, and many refinements), and
+       Alistair  Moffat,  Radford  Neal  and  Ian Witten (for the
+       arithmetic  coder  in  the  original  bzip).   I  am  much
+       indebted for their help, support and advice.  See the man-
+       ual in the source distribution for pointers to sources  of
+       documentation.  Christian von Roques encouraged me to look
+       for faster sorting algorithms, so as to speed up  compres-
+       sion.  Bela Lubkin encouraged me to improve the worst-case
+       compression performance.  Donna Robinson XMLised the docu-
+       mentation.   The bz* scripts are derived from those of GNU
+       gzip.  Many people sent patches, helped  with  portability
+       problems,  lent  machines,  gave advice and were generally
+       helpful.
+
diff --git a/abc-build/src/misc/bzlib/bzlib.c b/abc-build/src/misc/bzlib/bzlib.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bzlib/bzlib.c
@@ -0,0 +1,1588 @@
+
+/*-------------------------------------------------------------*/
+/*--- Library top-level functions.                          ---*/
+/*---                                               bzlib.c ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+   This file is part of bzip2/libbzip2, a program and library for
+   lossless, block-sorting data compression.
+
+   bzip2/libbzip2 version 1.0.5 of 10 December 2007
+   Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+   Please read the WARNING, DISCLAIMER and PATENTS sections in the 
+   README file.
+
+   This program is released under the terms of the license contained
+   in the file LICENSE.
+   ------------------------------------------------------------------ */
+
+/* CHANGES
+   0.9.0    -- original version.
+   0.9.0a/b -- no changes in this file.
+   0.9.0c   -- made zero-length BZ_FLUSH work correctly in bzCompress().
+     fixed bzWrite/bzRead to ignore zero-length requests.
+     fixed bzread to correctly handle read requests after EOF.
+     wrong parameter order in call to bzDecompressInit in
+     bzBuffToBuffDecompress.  Fixed.
+*/
+
+#include "bzlib_private.h"
+
+#ifdef WIN32
+#pragma warning(disable : 4996)
+#endif
+
+ABC_NAMESPACE_IMPL_START
+
+#ifdef _WIN32
+#define fileno   _fileno
+#define fdopen   _fdopen
+#define setmode  _setmode
+#endif
+ 
+/*---------------------------------------------------*/
+/*--- Compression stuff                           ---*/
+/*---------------------------------------------------*/
+
+
+/*---------------------------------------------------*/
+#ifndef BZ_NO_STDIO
+void BZ2_bz__AssertH__fail ( int errcode )
+{
+   fprintf(stderr, 
+      "\n\nbzip2/libbzip2: internal error number %d.\n"
+      "This is a bug in bzip2/libbzip2, %s.\n"
+      "Please report it to me at: jseward@bzip.org.  If this happened\n"
+      "when you were using some program which uses libbzip2 as a\n"
+      "component, you should also report this bug to the author(s)\n"
+      "of that program.  Please make an effort to report this bug;\n"
+      "timely and accurate bug reports eventually lead to higher\n"
+      "quality software.  Thanks.  Julian Seward, 10 December 2007.\n\n",
+      errcode,
+      BZ2_bzlibVersion()
+   );
+
+   if (errcode == 1007) {
+   fprintf(stderr,
+      "\n*** A special note about internal error number 1007 ***\n"
+      "\n"
+      "Experience suggests that a common cause of i.e. 1007\n"
+      "is unreliable memory or other hardware.  The 1007 assertion\n"
+      "just happens to cross-check the results of huge numbers of\n"
+      "memory reads/writes, and so acts (unintendedly) as a stress\n"
+      "test of your memory system.\n"
+      "\n"
+      "I suggest the following: try compressing the file again,\n"
+      "possibly monitoring progress in detail with the -vv flag.\n"
+      "\n"
+      "* If the error cannot be reproduced, and/or happens at different\n"
+      "  points in compression, you may have a flaky memory system.\n"
+      "  Try a memory-test program.  I have used Memtest86\n"
+      "  (www.memtest86.com).  At the time of writing it is free (GPLd).\n"
+      "  Memtest86 tests memory much more thorougly than your BIOSs\n"
+      "  power-on test, and may find failures that the BIOS doesn't.\n"
+      "\n"
+      "* If the error can be repeatably reproduced, this is a bug in\n"
+      "  bzip2, and I would very much like to hear about it.  Please\n"
+      "  let me know, and, ideally, save a copy of the file causing the\n"
+      "  problem -- without which I will be unable to investigate it.\n"
+      "\n"
+   );
+   }
+
+   exit(3);
+}
+#endif
+
+
+/*---------------------------------------------------*/
+static
+int bz_config_ok ( void )
+{
+   if (sizeof(int)   != 4) return 0;
+   if (sizeof(short) != 2) return 0;
+   if (sizeof(char)  != 1) return 0;
+   return 1;
+}
+
+
+/*---------------------------------------------------*/
+static
+void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
+{
+   void* v = malloc ( items * size );
+   return v;
+}
+
+static
+void default_bzfree ( void* opaque, void* addr )
+{
+   if (addr != NULL) free ( addr );
+}
+
+
+/*---------------------------------------------------*/
+static
+void prepare_new_block ( EState* s )
+{
+   Int32 i;
+   s->nblock = 0;
+   s->numZ = 0;
+   s->state_out_pos = 0;
+   BZ_INITIALISE_CRC ( s->blockCRC );
+   for (i = 0; i < 256; i++) s->inUse[i] = False;
+   s->blockNo++;
+}
+
+
+/*---------------------------------------------------*/
+static
+void init_RL ( EState* s )
+{
+   s->state_in_ch  = 256;
+   s->state_in_len = 0;
+}
+
+
+static
+Bool isempty_RL ( EState* s )
+{
+   if (s->state_in_ch < 256 && s->state_in_len > 0)
+      return False; else
+      return True;
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzCompressInit) 
+                    ( bz_stream* strm, 
+                     int        blockSize100k,
+                     int        verbosity,
+                     int        workFactor )
+{
+   Int32   n;
+   EState* s;
+
+   if (!bz_config_ok()) return BZ_CONFIG_ERROR;
+
+   if (strm == NULL || 
+       blockSize100k < 1 || blockSize100k > 9 ||
+       workFactor < 0 || workFactor > 250)
+     return BZ_PARAM_ERROR;
+
+   if (workFactor == 0) workFactor = 30;
+   if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
+   if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
+
+   s = (EState *)BZALLOC( sizeof(EState) );
+   if (s == NULL) return BZ_MEM_ERROR;
+   s->strm = strm;
+
+   s->arr1 = NULL;
+   s->arr2 = NULL;
+   s->ftab = NULL;
+
+   n       = 100000 * blockSize100k;
+   s->arr1 = (unsigned *)BZALLOC( n                  * sizeof(UInt32) );
+   s->arr2 = (unsigned *)BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
+   s->ftab = (unsigned *)BZALLOC( 65537              * sizeof(UInt32) );
+
+   if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
+      if (s->arr1 != NULL) BZFREE(s->arr1);
+      if (s->arr2 != NULL) BZFREE(s->arr2);
+      if (s->ftab != NULL) BZFREE(s->ftab);
+      if (s       != NULL) BZFREE(s);
+      return BZ_MEM_ERROR;
+   }
+
+   s->blockNo           = 0;
+   s->state             = BZ_S_INPUT;
+   s->mode              = BZ_M_RUNNING;
+   s->combinedCRC       = 0;
+   s->blockSize100k     = blockSize100k;
+   s->nblockMAX         = 100000 * blockSize100k - 19;
+   s->verbosity         = verbosity;
+   s->workFactor        = workFactor;
+
+   s->block             = (UChar*)s->arr2;
+   s->mtfv              = (UInt16*)s->arr1;
+   s->zbits             = NULL;
+   s->ptr               = (UInt32*)s->arr1;
+
+   strm->state          = s;
+   strm->total_in_lo32  = 0;
+   strm->total_in_hi32  = 0;
+   strm->total_out_lo32 = 0;
+   strm->total_out_hi32 = 0;
+   init_RL ( s );
+   prepare_new_block ( s );
+   return BZ_OK;
+}
+
+
+/*---------------------------------------------------*/
+static
+void add_pair_to_block ( EState* s )
+{
+   Int32 i;
+   UChar ch = (UChar)(s->state_in_ch);
+   for (i = 0; i < s->state_in_len; i++) {
+      BZ_UPDATE_CRC( s->blockCRC, ch );
+   }
+   s->inUse[s->state_in_ch] = True;
+   switch (s->state_in_len) {
+      case 1:
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         break;
+      case 2:
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         break;
+      case 3:
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         break;
+      default:
+         s->inUse[s->state_in_len-4] = True;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = (UChar)ch; s->nblock++;
+         s->block[s->nblock] = ((UChar)(s->state_in_len-4));
+         s->nblock++;
+         break;
+   }
+}
+
+
+/*---------------------------------------------------*/
+static
+void flush_RL ( EState* s )
+{
+   if (s->state_in_ch < 256) add_pair_to_block ( s );
+   init_RL ( s );
+}
+
+
+/*---------------------------------------------------*/
+#define ADD_CHAR_TO_BLOCK(zs,zchh0)               \
+{                                                 \
+   UInt32 zchh = (UInt32)(zchh0);                 \
+   /*-- fast track the common case --*/           \
+   if (zchh != zs->state_in_ch &&                 \
+       zs->state_in_len == 1) {                   \
+      UChar ch = (UChar)(zs->state_in_ch);        \
+      BZ_UPDATE_CRC( zs->blockCRC, ch );          \
+      zs->inUse[zs->state_in_ch] = True;          \
+      zs->block[zs->nblock] = (UChar)ch;          \
+      zs->nblock++;                               \
+      zs->state_in_ch = zchh;                     \
+   }                                              \
+   else                                           \
+   /*-- general, uncommon cases --*/              \
+   if (zchh != zs->state_in_ch ||                 \
+      zs->state_in_len == 255) {                  \
+      if (zs->state_in_ch < 256)                  \
+         add_pair_to_block ( zs );                \
+      zs->state_in_ch = zchh;                     \
+      zs->state_in_len = 1;                       \
+   } else {                                       \
+      zs->state_in_len++;                         \
+   }                                              \
+}
+
+
+/*---------------------------------------------------*/
+static
+Bool copy_input_until_stop ( EState* s )
+{
+   Bool progress_in = False;
+
+   if (s->mode == BZ_M_RUNNING) {
+
+      /*-- fast track the common case --*/
+      while (True) {
+         /*-- block full? --*/
+         if (s->nblock >= s->nblockMAX) break;
+         /*-- no input? --*/
+         if (s->strm->avail_in == 0) break;
+         progress_in = True;
+         ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 
+         s->strm->next_in++;
+         s->strm->avail_in--;
+         s->strm->total_in_lo32++;
+         if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
+      }
+
+   } else {
+
+      /*-- general, uncommon case --*/
+      while (True) {
+         /*-- block full? --*/
+         if (s->nblock >= s->nblockMAX) break;
+         /*-- no input? --*/
+         if (s->strm->avail_in == 0) break;
+         /*-- flush/finish end? --*/
+         if (s->avail_in_expect == 0) break;
+         progress_in = True;
+         ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 
+         s->strm->next_in++;
+         s->strm->avail_in--;
+         s->strm->total_in_lo32++;
+         if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
+         s->avail_in_expect--;
+      }
+   }
+   return progress_in;
+}
+
+
+/*---------------------------------------------------*/
+static
+Bool copy_output_until_stop ( EState* s )
+{
+   Bool progress_out = False;
+
+   while (True) {
+
+      /*-- no output space? --*/
+      if (s->strm->avail_out == 0) break;
+
+      /*-- block done? --*/
+      if (s->state_out_pos >= s->numZ) break;
+
+      progress_out = True;
+      *(s->strm->next_out) = s->zbits[s->state_out_pos];
+      s->state_out_pos++;
+      s->strm->avail_out--;
+      s->strm->next_out++;
+      s->strm->total_out_lo32++;
+      if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+   }
+
+   return progress_out;
+}
+
+
+/*---------------------------------------------------*/
+static
+Bool handle_compress ( bz_stream* strm )
+{
+   Bool progress_in  = False;
+   Bool progress_out = False;
+   EState* s = (EState *)strm->state;
+   
+   while (True) {
+
+      if (s->state == BZ_S_OUTPUT) {
+         progress_out |= copy_output_until_stop ( s );
+         if (s->state_out_pos < s->numZ) break;
+         if (s->mode == BZ_M_FINISHING && 
+             s->avail_in_expect == 0 &&
+             isempty_RL(s)) break;
+         prepare_new_block ( s );
+         s->state = BZ_S_INPUT;
+         if (s->mode == BZ_M_FLUSHING && 
+             s->avail_in_expect == 0 &&
+             isempty_RL(s)) break;
+      }
+
+      if (s->state == BZ_S_INPUT) {
+         progress_in |= copy_input_until_stop ( s );
+         if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
+            flush_RL ( s );
+            BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
+            s->state = BZ_S_OUTPUT;
+         }
+         else
+         if (s->nblock >= s->nblockMAX) {
+            BZ2_compressBlock ( s, False );
+            s->state = BZ_S_OUTPUT;
+         }
+         else
+         if (s->strm->avail_in == 0) {
+            break;
+         }
+      }
+
+   }
+
+   return progress_in || progress_out;
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
+{
+   Bool progress;
+   EState* s;
+   if (strm == NULL) return BZ_PARAM_ERROR;
+   s = (EState *)strm->state;
+   if (s == NULL) return BZ_PARAM_ERROR;
+   if (s->strm != strm) return BZ_PARAM_ERROR;
+
+   preswitch:
+   switch (s->mode) {
+
+      case BZ_M_IDLE:
+         return BZ_SEQUENCE_ERROR;
+
+      case BZ_M_RUNNING:
+         if (action == BZ_RUN) {
+            progress = handle_compress ( strm );
+            return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
+         } 
+         else
+	 if (action == BZ_FLUSH) {
+            s->avail_in_expect = strm->avail_in;
+            s->mode = BZ_M_FLUSHING;
+            goto preswitch;
+         }
+         else
+         if (action == BZ_FINISH) {
+            s->avail_in_expect = strm->avail_in;
+            s->mode = BZ_M_FINISHING;
+            goto preswitch;
+         }
+         else 
+            return BZ_PARAM_ERROR;
+
+      case BZ_M_FLUSHING:
+         if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
+         if (s->avail_in_expect != s->strm->avail_in) 
+            return BZ_SEQUENCE_ERROR;
+         progress = handle_compress ( strm );
+         if (s->avail_in_expect > 0 || !isempty_RL(s) ||
+             s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
+         s->mode = BZ_M_RUNNING;
+         return BZ_RUN_OK;
+
+      case BZ_M_FINISHING:
+         if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
+         if (s->avail_in_expect != s->strm->avail_in) 
+            return BZ_SEQUENCE_ERROR;
+         progress = handle_compress ( strm );
+         if (!progress) return BZ_SEQUENCE_ERROR;
+         if (s->avail_in_expect > 0 || !isempty_RL(s) ||
+             s->state_out_pos < s->numZ) return BZ_FINISH_OK;
+         s->mode = BZ_M_IDLE;
+         return BZ_STREAM_END;
+   }
+   return BZ_OK; /*--not reached--*/
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzCompressEnd)  ( bz_stream *strm )
+{
+   EState* s;
+   if (strm == NULL) return BZ_PARAM_ERROR;
+   s = (EState *)strm->state;
+   if (s == NULL) return BZ_PARAM_ERROR;
+   if (s->strm != strm) return BZ_PARAM_ERROR;
+
+   if (s->arr1 != NULL) BZFREE(s->arr1);
+   if (s->arr2 != NULL) BZFREE(s->arr2);
+   if (s->ftab != NULL) BZFREE(s->ftab);
+   BZFREE(strm->state);
+
+   strm->state = NULL;   
+
+   return BZ_OK;
+}
+
+
+/*---------------------------------------------------*/
+/*--- Decompression stuff                         ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzDecompressInit) 
+                     ( bz_stream* strm, 
+                       int        verbosity,
+                       int        small )
+{
+   DState* s;
+
+   if (!bz_config_ok()) return BZ_CONFIG_ERROR;
+
+   if (strm == NULL) return BZ_PARAM_ERROR;
+   if (small != 0 && small != 1) return BZ_PARAM_ERROR;
+   if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
+
+   if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
+   if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
+
+   s = (DState *)BZALLOC( sizeof(DState) );
+   if (s == NULL) return BZ_MEM_ERROR;
+   s->strm                  = strm;
+   strm->state              = s;
+   s->state                 = BZ_X_MAGIC_1;
+   s->bsLive                = 0;
+   s->bsBuff                = 0;
+   s->calculatedCombinedCRC = 0;
+   strm->total_in_lo32      = 0;
+   strm->total_in_hi32      = 0;
+   strm->total_out_lo32     = 0;
+   strm->total_out_hi32     = 0;
+   s->smallDecompress       = (Bool)small;
+   s->ll4                   = NULL;
+   s->ll16                  = NULL;
+   s->tt                    = NULL;
+   s->currBlockNo           = 0;
+   s->verbosity             = verbosity;
+
+   return BZ_OK;
+}
+
+
+/*---------------------------------------------------*/
+/* Return  True iff data corruption is discovered.
+   Returns False if there is no problem.
+*/
+static
+Bool unRLE_obuf_to_output_FAST ( DState* s )
+{
+   UChar k1;
+
+   if (s->blockRandomised) {
+
+      while (True) {
+         /* try to finish existing run */
+         while (True) {
+            if (s->strm->avail_out == 0) return False;
+            if (s->state_out_len == 0) break;
+            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
+            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
+            s->state_out_len--;
+            s->strm->next_out++;
+            s->strm->avail_out--;
+            s->strm->total_out_lo32++;
+            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+         }
+
+         /* can a new run be started? */
+         if (s->nblock_used == s->save_nblock+1) return False;
+               
+         /* Only caused by corrupt data stream? */
+         if (s->nblock_used > s->save_nblock+1)
+            return True;
+   
+         s->state_out_len = 1;
+         s->state_out_ch = s->k0;
+         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 2;
+         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 3;
+         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         s->state_out_len = ((Int32)k1) + 4;
+         BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; 
+         s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
+      }
+
+   } else {
+
+      /* restore */
+      UInt32        c_calculatedBlockCRC = s->calculatedBlockCRC;
+      UChar         c_state_out_ch       = s->state_out_ch;
+      Int32         c_state_out_len      = s->state_out_len;
+      Int32         c_nblock_used        = s->nblock_used;
+      Int32         c_k0                 = s->k0;
+      UInt32*       c_tt                 = s->tt;
+      UInt32        c_tPos               = s->tPos;
+      char*         cs_next_out          = s->strm->next_out;
+      unsigned int  cs_avail_out         = s->strm->avail_out;
+      Int32         ro_blockSize100k     = s->blockSize100k;
+      /* end restore */
+
+      UInt32       avail_out_INIT = cs_avail_out;
+      Int32        s_save_nblockPP = s->save_nblock+1;
+      unsigned int total_out_lo32_old;
+
+      while (True) {
+
+         /* try to finish existing run */
+         if (c_state_out_len > 0) {
+            while (True) {
+               if (cs_avail_out == 0) goto return_notr;
+               if (c_state_out_len == 1) break;
+               *( (UChar*)(cs_next_out) ) = c_state_out_ch;
+               BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
+               c_state_out_len--;
+               cs_next_out++;
+               cs_avail_out--;
+            }
+            s_state_out_len_eq_one:
+            {
+               if (cs_avail_out == 0) { 
+                  c_state_out_len = 1; goto return_notr;
+               };
+               *( (UChar*)(cs_next_out) ) = c_state_out_ch;
+               BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
+               cs_next_out++;
+               cs_avail_out--;
+            }
+         }   
+         /* Only caused by corrupt data stream? */
+         if (c_nblock_used > s_save_nblockPP)
+            return True;
+
+         /* can a new run be started? */
+         if (c_nblock_used == s_save_nblockPP) {
+            c_state_out_len = 0; goto return_notr;
+         };   
+         c_state_out_ch = c_k0;
+         BZ_GET_FAST_C(k1); c_nblock_used++;
+         if (k1 != c_k0) { 
+            c_k0 = k1; goto s_state_out_len_eq_one; 
+         };
+         if (c_nblock_used == s_save_nblockPP) 
+            goto s_state_out_len_eq_one;
+   
+         c_state_out_len = 2;
+         BZ_GET_FAST_C(k1); c_nblock_used++;
+         if (c_nblock_used == s_save_nblockPP) continue;
+         if (k1 != c_k0) { c_k0 = k1; continue; };
+   
+         c_state_out_len = 3;
+         BZ_GET_FAST_C(k1); c_nblock_used++;
+         if (c_nblock_used == s_save_nblockPP) continue;
+         if (k1 != c_k0) { c_k0 = k1; continue; };
+   
+         BZ_GET_FAST_C(k1); c_nblock_used++;
+         c_state_out_len = ((Int32)k1) + 4;
+         BZ_GET_FAST_C(c_k0); c_nblock_used++;
+      }
+
+      return_notr:
+      total_out_lo32_old = s->strm->total_out_lo32;
+      s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
+      if (s->strm->total_out_lo32 < total_out_lo32_old)
+         s->strm->total_out_hi32++;
+
+      /* save */
+      s->calculatedBlockCRC = c_calculatedBlockCRC;
+      s->state_out_ch       = c_state_out_ch;
+      s->state_out_len      = c_state_out_len;
+      s->nblock_used        = c_nblock_used;
+      s->k0                 = c_k0;
+      s->tt                 = c_tt;
+      s->tPos               = c_tPos;
+      s->strm->next_out     = cs_next_out;
+      s->strm->avail_out    = cs_avail_out;
+      /* end save */
+   }
+   return False;
+}
+
+
+
+/*---------------------------------------------------*/
+Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
+{
+   Int32 nb, na, mid;
+   nb = 0;
+   na = 256;
+   do {
+      mid = (nb + na) >> 1;
+      if (indx >= cftab[mid]) nb = mid; else na = mid;
+   }
+   while (na - nb != 1);
+   return nb;
+}
+
+
+/*---------------------------------------------------*/
+/* Return  True iff data corruption is discovered.
+   Returns False if there is no problem.
+*/
+static
+Bool unRLE_obuf_to_output_SMALL ( DState* s )
+{
+   UChar k1;
+
+   if (s->blockRandomised) {
+
+      while (True) {
+         /* try to finish existing run */
+         while (True) {
+            if (s->strm->avail_out == 0) return False;
+            if (s->state_out_len == 0) break;
+            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
+            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
+            s->state_out_len--;
+            s->strm->next_out++;
+            s->strm->avail_out--;
+            s->strm->total_out_lo32++;
+            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+         }
+   
+         /* can a new run be started? */
+         if (s->nblock_used == s->save_nblock+1) return False;
+
+         /* Only caused by corrupt data stream? */
+         if (s->nblock_used > s->save_nblock+1)
+            return True;
+   
+         s->state_out_len = 1;
+         s->state_out_ch = s->k0;
+         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 2;
+         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 3;
+         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
+         k1 ^= BZ_RAND_MASK; s->nblock_used++;
+         s->state_out_len = ((Int32)k1) + 4;
+         BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; 
+         s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
+      }
+
+   } else {
+
+      while (True) {
+         /* try to finish existing run */
+         while (True) {
+            if (s->strm->avail_out == 0) return False;
+            if (s->state_out_len == 0) break;
+            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
+            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
+            s->state_out_len--;
+            s->strm->next_out++;
+            s->strm->avail_out--;
+            s->strm->total_out_lo32++;
+            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
+         }
+   
+         /* can a new run be started? */
+         if (s->nblock_used == s->save_nblock+1) return False;
+
+         /* Only caused by corrupt data stream? */
+         if (s->nblock_used > s->save_nblock+1)
+            return True;
+   
+         s->state_out_len = 1;
+         s->state_out_ch = s->k0;
+         BZ_GET_SMALL(k1); s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 2;
+         BZ_GET_SMALL(k1); s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         s->state_out_len = 3;
+         BZ_GET_SMALL(k1); s->nblock_used++;
+         if (s->nblock_used == s->save_nblock+1) continue;
+         if (k1 != s->k0) { s->k0 = k1; continue; };
+   
+         BZ_GET_SMALL(k1); s->nblock_used++;
+         s->state_out_len = ((Int32)k1) + 4;
+         BZ_GET_SMALL(s->k0); s->nblock_used++;
+      }
+
+   }
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
+{
+   Bool    corrupt;
+   DState* s;
+   if (strm == NULL) return BZ_PARAM_ERROR;
+   s = (DState *)strm->state;
+   if (s == NULL) return BZ_PARAM_ERROR;
+   if (s->strm != strm) return BZ_PARAM_ERROR;
+
+   while (True) {
+      if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
+      if (s->state == BZ_X_OUTPUT) {
+         if (s->smallDecompress)
+            corrupt = unRLE_obuf_to_output_SMALL ( s ); else
+            corrupt = unRLE_obuf_to_output_FAST  ( s );
+         if (corrupt) return BZ_DATA_ERROR;
+         if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
+            BZ_FINALISE_CRC ( s->calculatedBlockCRC );
+            if (s->verbosity >= 3) 
+               VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC, 
+                          s->calculatedBlockCRC );
+            if (s->verbosity >= 2) VPrintf0 ( "]" );
+            if (s->calculatedBlockCRC != s->storedBlockCRC)
+               return BZ_DATA_ERROR;
+            s->calculatedCombinedCRC 
+               = (s->calculatedCombinedCRC << 1) | 
+                    (s->calculatedCombinedCRC >> 31);
+            s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
+            s->state = BZ_X_BLKHDR_1;
+         } else {
+            return BZ_OK;
+         }
+      }
+      if (s->state >= BZ_X_MAGIC_1) {
+         Int32 r = BZ2_decompress ( s );
+         if (r == BZ_STREAM_END) {
+            if (s->verbosity >= 3)
+               VPrintf2 ( "\n    combined CRCs: stored = 0x%08x, computed = 0x%08x", 
+                          s->storedCombinedCRC, s->calculatedCombinedCRC );
+            if (s->calculatedCombinedCRC != s->storedCombinedCRC)
+               return BZ_DATA_ERROR;
+            return r;
+         }
+         if (s->state != BZ_X_OUTPUT) return r;
+      }
+   }
+
+   AssertH ( 0, 6001 );
+
+   return 0;  /*NOTREACHED*/
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzDecompressEnd)  ( bz_stream *strm )
+{
+   DState* s;
+   if (strm == NULL) return BZ_PARAM_ERROR;
+   s = (DState *)strm->state;
+   if (s == NULL) return BZ_PARAM_ERROR;
+   if (s->strm != strm) return BZ_PARAM_ERROR;
+
+   if (s->tt   != NULL) BZFREE(s->tt);
+   if (s->ll16 != NULL) BZFREE(s->ll16);
+   if (s->ll4  != NULL) BZFREE(s->ll4);
+
+   BZFREE(strm->state);
+   strm->state = NULL;
+
+   return BZ_OK;
+}
+
+
+#ifndef BZ_NO_STDIO
+/*---------------------------------------------------*/
+/*--- File I/O stuff                              ---*/
+/*---------------------------------------------------*/
+
+#define BZ_SETERR(eee)                    \
+{                                         \
+   if (bzerror != NULL) *bzerror = eee;   \
+   if (bzf != NULL) bzf->lastErr = eee;   \
+}
+
+typedef 
+   struct {
+      FILE*     handle;
+      Char      buf[BZ_MAX_UNUSED];
+      Int32     bufN;
+      Bool      writing;
+      bz_stream strm;
+      Int32     lastErr;
+      Bool      initialisedOk;
+   }
+   bzFile;
+
+
+/*---------------------------------------------*/
+static Bool myfeof ( FILE* f )
+{
+   Int32 c = fgetc ( f );
+   if (c == EOF) return True;
+   ungetc ( c, f );
+   return False;
+}
+
+
+/*---------------------------------------------------*/
+BZFILE* BZ_API(BZ2_bzWriteOpen) 
+                    ( int*  bzerror,      
+                      FILE* f, 
+                      int   blockSize100k, 
+                      int   verbosity,
+                      int   workFactor )
+{
+   Int32   ret;
+   bzFile* bzf = NULL;
+
+   BZ_SETERR(BZ_OK);
+
+   if (f == NULL ||
+       (blockSize100k < 1 || blockSize100k > 9) ||
+       (workFactor < 0 || workFactor > 250) ||
+       (verbosity < 0 || verbosity > 4))
+      { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
+
+   if (ferror(f))
+      { BZ_SETERR(BZ_IO_ERROR); return NULL; };
+
+   bzf = (bzFile *)malloc ( sizeof(bzFile) );
+   if (bzf == NULL)
+      { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
+
+   BZ_SETERR(BZ_OK);
+   bzf->initialisedOk = False;
+   bzf->bufN          = 0;
+   bzf->handle        = f;
+   bzf->writing       = True;
+   bzf->strm.bzalloc  = NULL;
+   bzf->strm.bzfree   = NULL;
+   bzf->strm.opaque   = NULL;
+
+   if (workFactor == 0) workFactor = 30;
+   ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, 
+                              verbosity, workFactor );
+   if (ret != BZ_OK)
+      { BZ_SETERR(ret); free(bzf); return NULL; };
+
+   bzf->strm.avail_in = 0;
+   bzf->initialisedOk = True;
+   return bzf;   
+}
+
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzWrite)
+             ( int*    bzerror, 
+               BZFILE* b, 
+               void*   buf, 
+               int     len )
+{
+   Int32 n, n2, ret;
+   bzFile* bzf = (bzFile*)b;
+
+   BZ_SETERR(BZ_OK);
+   if (bzf == NULL || buf == NULL || len < 0)
+      { BZ_SETERR(BZ_PARAM_ERROR); return; };
+   if (!(bzf->writing))
+      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+   if (ferror(bzf->handle))
+      { BZ_SETERR(BZ_IO_ERROR); return; };
+
+   if (len == 0)
+      { BZ_SETERR(BZ_OK); return; };
+
+   bzf->strm.avail_in = len;
+   bzf->strm.next_in  = (char *)buf;
+
+   while (True) {
+      bzf->strm.avail_out = BZ_MAX_UNUSED;
+      bzf->strm.next_out = bzf->buf;
+      ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
+      if (ret != BZ_RUN_OK)
+         { BZ_SETERR(ret); return; };
+
+      if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
+         n = BZ_MAX_UNUSED - bzf->strm.avail_out;
+         n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 
+                       n, bzf->handle );
+         if (n != n2 || ferror(bzf->handle))
+            { BZ_SETERR(BZ_IO_ERROR); return; };
+      }
+
+      if (bzf->strm.avail_in == 0)
+         { BZ_SETERR(BZ_OK); return; };
+   }
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzWriteClose)
+                  ( int*          bzerror, 
+                    BZFILE*       b, 
+                    int           abandon,
+                    unsigned int* nbytes_in,
+                    unsigned int* nbytes_out )
+{
+   BZ2_bzWriteClose64 ( bzerror, b, abandon, 
+                        nbytes_in, NULL, nbytes_out, NULL );
+}
+
+
+void BZ_API(BZ2_bzWriteClose64)
+                  ( int*          bzerror, 
+                    BZFILE*       b, 
+                    int           abandon,
+                    unsigned int* nbytes_in_lo32,
+                    unsigned int* nbytes_in_hi32,
+                    unsigned int* nbytes_out_lo32,
+                    unsigned int* nbytes_out_hi32 )
+{
+   Int32   n, n2, ret;
+   bzFile* bzf = (bzFile*)b;
+
+   if (bzf == NULL)
+      { BZ_SETERR(BZ_OK); return; };
+   if (!(bzf->writing))
+      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+   if (ferror(bzf->handle))
+      { BZ_SETERR(BZ_IO_ERROR); return; };
+
+   if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
+   if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
+   if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
+   if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
+
+   if ((!abandon) && bzf->lastErr == BZ_OK) {
+      while (True) {
+         bzf->strm.avail_out = BZ_MAX_UNUSED;
+         bzf->strm.next_out = bzf->buf;
+         ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
+         if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
+            { BZ_SETERR(ret); return; };
+
+         if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
+            n = BZ_MAX_UNUSED - bzf->strm.avail_out;
+            n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 
+                          n, bzf->handle );
+            if (n != n2 || ferror(bzf->handle))
+               { BZ_SETERR(BZ_IO_ERROR); return; };
+         }
+
+         if (ret == BZ_STREAM_END) break;
+      }
+   }
+
+   if ( !abandon && !ferror ( bzf->handle ) ) {
+      fflush ( bzf->handle );
+      if (ferror(bzf->handle))
+         { BZ_SETERR(BZ_IO_ERROR); return; };
+   }
+
+   if (nbytes_in_lo32 != NULL)
+      *nbytes_in_lo32 = bzf->strm.total_in_lo32;
+   if (nbytes_in_hi32 != NULL)
+      *nbytes_in_hi32 = bzf->strm.total_in_hi32;
+   if (nbytes_out_lo32 != NULL)
+      *nbytes_out_lo32 = bzf->strm.total_out_lo32;
+   if (nbytes_out_hi32 != NULL)
+      *nbytes_out_hi32 = bzf->strm.total_out_hi32;
+
+   BZ_SETERR(BZ_OK);
+   BZ2_bzCompressEnd ( &(bzf->strm) );
+   free ( bzf );
+}
+
+
+/*---------------------------------------------------*/
+BZFILE* BZ_API(BZ2_bzReadOpen) 
+                   ( int*  bzerror, 
+                     FILE* f, 
+                     int   verbosity,
+                     int   small,
+                     void* unused,
+                     int   nUnused )
+{
+   bzFile* bzf = NULL;
+   int     ret;
+
+   BZ_SETERR(BZ_OK);
+
+   if (f == NULL || 
+       (small != 0 && small != 1) ||
+       (verbosity < 0 || verbosity > 4) ||
+       (unused == NULL && nUnused != 0) ||
+       (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
+      { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
+
+   if (ferror(f))
+      { BZ_SETERR(BZ_IO_ERROR); return NULL; };
+
+   bzf = (bzFile *)malloc ( sizeof(bzFile) );
+   if (bzf == NULL) 
+      { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
+
+   BZ_SETERR(BZ_OK);
+
+   bzf->initialisedOk = False;
+   bzf->handle        = f;
+   bzf->bufN          = 0;
+   bzf->writing       = False;
+   bzf->strm.bzalloc  = NULL;
+   bzf->strm.bzfree   = NULL;
+   bzf->strm.opaque   = NULL;
+   
+   while (nUnused > 0) {
+      bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
+      unused = ((void*)( 1 + ((UChar*)(unused))  ));
+      nUnused--;
+   }
+
+   ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
+   if (ret != BZ_OK)
+      { BZ_SETERR(ret); free(bzf); return NULL; };
+
+   bzf->strm.avail_in = bzf->bufN;
+   bzf->strm.next_in  = bzf->buf;
+
+   bzf->initialisedOk = True;
+   return bzf;   
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
+{
+   bzFile* bzf = (bzFile*)b;
+
+   BZ_SETERR(BZ_OK);
+   if (bzf == NULL)
+      { BZ_SETERR(BZ_OK); return; };
+
+   if (bzf->writing)
+      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+
+   if (bzf->initialisedOk)
+      (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
+   free ( bzf );
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzRead) 
+           ( int*    bzerror, 
+             BZFILE* b, 
+             void*   buf, 
+             int     len )
+{
+   Int32   n, ret;
+   bzFile* bzf = (bzFile*)b;
+
+   BZ_SETERR(BZ_OK);
+
+   if (bzf == NULL || buf == NULL || len < 0)
+      { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
+
+   if (bzf->writing)
+      { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
+
+   if (len == 0)
+      { BZ_SETERR(BZ_OK); return 0; };
+
+   bzf->strm.avail_out = len;
+   bzf->strm.next_out = (char *)buf;
+
+   while (True) {
+
+      if (ferror(bzf->handle)) 
+         { BZ_SETERR(BZ_IO_ERROR); return 0; };
+
+      if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
+         n = fread ( bzf->buf, sizeof(UChar), 
+                     BZ_MAX_UNUSED, bzf->handle );
+         if (ferror(bzf->handle))
+            { BZ_SETERR(BZ_IO_ERROR); return 0; };
+         bzf->bufN = n;
+         bzf->strm.avail_in = bzf->bufN;
+         bzf->strm.next_in = bzf->buf;
+      }
+
+      ret = BZ2_bzDecompress ( &(bzf->strm) );
+
+      if (ret != BZ_OK && ret != BZ_STREAM_END)
+         { BZ_SETERR(ret); return 0; };
+
+      if (ret == BZ_OK && myfeof(bzf->handle) && 
+          bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
+         { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
+
+      if (ret == BZ_STREAM_END)
+         { BZ_SETERR(BZ_STREAM_END);
+           return len - bzf->strm.avail_out; };
+      if (bzf->strm.avail_out == 0)
+         { BZ_SETERR(BZ_OK); return len; };
+      
+   }
+
+   return 0; /*not reached*/
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzReadGetUnused) 
+                     ( int*    bzerror, 
+                       BZFILE* b, 
+                       void**  unused, 
+                       int*    nUnused )
+{
+   bzFile* bzf = (bzFile*)b;
+   if (bzf == NULL)
+      { BZ_SETERR(BZ_PARAM_ERROR); return; };
+   if (bzf->lastErr != BZ_STREAM_END)
+      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
+   if (unused == NULL || nUnused == NULL)
+      { BZ_SETERR(BZ_PARAM_ERROR); return; };
+
+   BZ_SETERR(BZ_OK);
+   *nUnused = bzf->strm.avail_in;
+   *unused = bzf->strm.next_in;
+}
+#endif
+
+
+/*---------------------------------------------------*/
+/*--- Misc convenience stuff                      ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzBuffToBuffCompress) 
+                         ( char*         dest, 
+                           unsigned int* destLen,
+                           char*         source, 
+                           unsigned int  sourceLen,
+                           int           blockSize100k, 
+                           int           verbosity, 
+                           int           workFactor )
+{
+   bz_stream strm;
+   int ret;
+
+   if (dest == NULL || destLen == NULL || 
+       source == NULL ||
+       blockSize100k < 1 || blockSize100k > 9 ||
+       verbosity < 0 || verbosity > 4 ||
+       workFactor < 0 || workFactor > 250) 
+      return BZ_PARAM_ERROR;
+
+   if (workFactor == 0) workFactor = 30;
+   strm.bzalloc = NULL;
+   strm.bzfree = NULL;
+   strm.opaque = NULL;
+   ret = BZ2_bzCompressInit ( &strm, blockSize100k, 
+                              verbosity, workFactor );
+   if (ret != BZ_OK) return ret;
+
+   strm.next_in = source;
+   strm.next_out = dest;
+   strm.avail_in = sourceLen;
+   strm.avail_out = *destLen;
+
+   ret = BZ2_bzCompress ( &strm, BZ_FINISH );
+   if (ret == BZ_FINISH_OK) goto output_overflow;
+   if (ret != BZ_STREAM_END) goto errhandler;
+
+   /* normal termination */
+   *destLen -= strm.avail_out;   
+   BZ2_bzCompressEnd ( &strm );
+   return BZ_OK;
+
+   output_overflow:
+   BZ2_bzCompressEnd ( &strm );
+   return BZ_OUTBUFF_FULL;
+
+   errhandler:
+   BZ2_bzCompressEnd ( &strm );
+   return ret;
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzBuffToBuffDecompress) 
+                           ( char*         dest, 
+                             unsigned int* destLen,
+                             char*         source, 
+                             unsigned int  sourceLen,
+                             int           small,
+                             int           verbosity )
+{
+   bz_stream strm;
+   int ret;
+
+   if (dest == NULL || destLen == NULL || 
+       source == NULL ||
+       (small != 0 && small != 1) ||
+       verbosity < 0 || verbosity > 4) 
+          return BZ_PARAM_ERROR;
+
+   strm.bzalloc = NULL;
+   strm.bzfree = NULL;
+   strm.opaque = NULL;
+   ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
+   if (ret != BZ_OK) return ret;
+
+   strm.next_in = source;
+   strm.next_out = dest;
+   strm.avail_in = sourceLen;
+   strm.avail_out = *destLen;
+
+   ret = BZ2_bzDecompress ( &strm );
+   if (ret == BZ_OK) goto output_overflow_or_eof;
+   if (ret != BZ_STREAM_END) goto errhandler;
+
+   /* normal termination */
+   *destLen -= strm.avail_out;
+   BZ2_bzDecompressEnd ( &strm );
+   return BZ_OK;
+
+   output_overflow_or_eof:
+   if (strm.avail_out > 0) {
+      BZ2_bzDecompressEnd ( &strm );
+      return BZ_UNEXPECTED_EOF;
+   } else {
+      BZ2_bzDecompressEnd ( &strm );
+      return BZ_OUTBUFF_FULL;
+   };      
+
+   errhandler:
+   BZ2_bzDecompressEnd ( &strm );
+   return ret; 
+}
+
+
+/*---------------------------------------------------*/
+/*--
+   Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
+   to support better zlib compatibility.
+   This code is not _officially_ part of libbzip2 (yet);
+   I haven't tested it, documented it, or considered the
+   threading-safeness of it.
+   If this code breaks, please contact both Yoshioka and me.
+--*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+/*--
+   return version like "0.9.5d, 4-Sept-1999".
+--*/
+const char * BZ_API(BZ2_bzlibVersion)(void)
+{
+   return BZ_VERSION;
+}
+
+
+#ifndef BZ_NO_STDIO
+/*---------------------------------------------------*/
+
+#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
+#   include <fcntl.h>
+#   include <io.h>
+#   define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
+#else
+#   define SET_BINARY_MODE(file)
+#endif
+static
+BZFILE * bzopen_or_bzdopen
+               ( const char *path,   /* no use when bzdopen */
+                 int fd,             /* no use when bzdopen */
+                 const char *mode,
+                 int open_mode)      /* bzopen: 0, bzdopen:1 */
+{
+   int    bzerr;
+   char   unused[BZ_MAX_UNUSED];
+   int    blockSize100k = 9;
+   int    writing       = 0;
+   char   mode2[10]     = "";
+   FILE   *fp           = NULL;
+   BZFILE *bzfp         = NULL;
+   int    verbosity     = 0;
+   int    workFactor    = 30;
+   int    smallMode     = 0;
+   int    nUnused       = 0; 
+
+   if (mode == NULL) return NULL;
+   while (*mode) {
+      switch (*mode) {
+      case 'r':
+         writing = 0; break;
+      case 'w':
+         writing = 1; break;
+      case 's':
+         smallMode = 1; break;
+      default:
+         if (isdigit((int)(*mode))) {
+            blockSize100k = *mode-BZ_HDR_0;
+         }
+      }
+      mode++;
+   }
+   strcat(mode2, writing ? "w" : "r" );
+   strcat(mode2,"b");   /* binary mode */
+
+   if (open_mode==0) {
+      if (path==NULL || strcmp(path,"")==0) {
+        fp = (writing ? stdout : stdin);
+        SET_BINARY_MODE(fp);
+      } else {
+        fp = fopen(path,mode2);
+      }
+   } else {
+#ifdef BZ_STRICT_ANSI
+      fp = NULL;
+#else
+      fp = (FILE *)fdopen(fd,mode2);
+#endif
+   }
+   if (fp == NULL) return NULL;
+
+   if (writing) {
+      /* Guard against total chaos and anarchy -- JRS */
+      if (blockSize100k < 1) blockSize100k = 1;
+      if (blockSize100k > 9) blockSize100k = 9; 
+      bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
+                             verbosity,workFactor);
+   } else {
+      bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
+                            unused,nUnused);
+   }
+   if (bzfp == NULL) {
+      if (fp != stdin && fp != stdout) fclose(fp);
+      return NULL;
+   }
+   return bzfp;
+}
+
+
+/*---------------------------------------------------*/
+/*--
+   open file for read or write.
+      ex) bzopen("file","w9")
+      case path="" or NULL => use stdin or stdout.
+--*/
+BZFILE * BZ_API(BZ2_bzopen)
+               ( const char *path,
+                 const char *mode )
+{
+   return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
+}
+
+
+/*---------------------------------------------------*/
+BZFILE * BZ_API(BZ2_bzdopen)
+               ( int fd,
+                 const char *mode )
+{
+   return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
+{
+   int bzerr, nread;
+   if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
+   nread = BZ2_bzRead(&bzerr,b,buf,len);
+   if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
+      return nread;
+   } else {
+      return -1;
+   }
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
+{
+   int bzerr;
+
+   BZ2_bzWrite(&bzerr,b,buf,len);
+   if(bzerr == BZ_OK){
+      return len;
+   }else{
+      return -1;
+   }
+}
+
+
+/*---------------------------------------------------*/
+int BZ_API(BZ2_bzflush) (BZFILE *b)
+{
+   /* do nothing now... */
+   return 0;
+}
+
+
+/*---------------------------------------------------*/
+void BZ_API(BZ2_bzclose) (BZFILE* b)
+{
+   int bzerr;
+   FILE *fp;
+   
+   if (b==NULL) {return;}
+   fp = ((bzFile *)b)->handle;
+   if(((bzFile*)b)->writing){
+      BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
+      if(bzerr != BZ_OK){
+         BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
+      }
+   }else{
+      BZ2_bzReadClose(&bzerr,b);
+   }
+   if(fp!=stdin && fp!=stdout){
+      fclose(fp);
+   }
+}
+
+
+/*---------------------------------------------------*/
+/*--
+   return last error code 
+--*/
+static const char *bzerrorstrings[] = {
+       "OK"
+      ,"SEQUENCE_ERROR"
+      ,"PARAM_ERROR"
+      ,"MEM_ERROR"
+      ,"DATA_ERROR"
+      ,"DATA_ERROR_MAGIC"
+      ,"IO_ERROR"
+      ,"UNEXPECTED_EOF"
+      ,"OUTBUFF_FULL"
+      ,"CONFIG_ERROR"
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+      ,"???"   /* for future */
+};
+
+
+const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
+{
+   int err = ((bzFile *)b)->lastErr;
+
+   if(err>0) err = 0;
+   *errnum = err;
+   return bzerrorstrings[err*-1];
+}
+#endif
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                           bzlib.c ---*/
+/*-------------------------------------------------------------*/
+
+ABC_NAMESPACE_IMPL_END
+
+
+
diff --git a/abc-build/src/misc/bzlib/bzlib.h b/abc-build/src/misc/bzlib/bzlib.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bzlib/bzlib.h
@@ -0,0 +1,287 @@
+
+/*-------------------------------------------------------------*/
+/*--- Public header file for the library.                   ---*/
+/*---                                               bzlib.h ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+   This file is part of bzip2/libbzip2, a program and library for
+   lossless, block-sorting data compression.
+
+   bzip2/libbzip2 version 1.0.5 of 10 December 2007
+   Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+   Please read the WARNING, DISCLAIMER and PATENTS sections in the 
+   README file.
+
+   This program is released under the terms of the license contained
+   in the file LICENSE.
+   ------------------------------------------------------------------ */
+
+#ifdef _WIN32
+#ifdef __STDC__
+#undef __STDC__
+#endif
+#endif
+
+#ifndef ABC__misc__bzlib__bzlib_h
+#define ABC__misc__bzlib__bzlib_h
+
+#define BZ_RUN               0
+#define BZ_FLUSH             1
+#define BZ_FINISH            2
+
+#define BZ_OK                0
+#define BZ_RUN_OK            1
+#define BZ_FLUSH_OK          2
+#define BZ_FINISH_OK         3
+#define BZ_STREAM_END        4
+#define BZ_SEQUENCE_ERROR    (-1)
+#define BZ_PARAM_ERROR       (-2)
+#define BZ_MEM_ERROR         (-3)
+#define BZ_DATA_ERROR        (-4)
+#define BZ_DATA_ERROR_MAGIC  (-5)
+#define BZ_IO_ERROR          (-6)
+#define BZ_UNEXPECTED_EOF    (-7)
+#define BZ_OUTBUFF_FULL      (-8)
+#define BZ_CONFIG_ERROR      (-9)
+
+typedef 
+   struct {
+      char *next_in;
+      unsigned int avail_in;
+      unsigned int total_in_lo32;
+      unsigned int total_in_hi32;
+
+      char *next_out;
+      unsigned int avail_out;
+      unsigned int total_out_lo32;
+      unsigned int total_out_hi32;
+
+      void *state;
+
+      void *(*bzalloc)(void *,int,int);
+      void (*bzfree)(void *,void *);
+      void *opaque;
+   } 
+   bz_stream;
+
+
+#ifndef BZ_IMPORT
+#define BZ_EXPORT
+#endif
+
+#ifndef BZ_NO_STDIO
+/* Need a definitition for FILE */
+#include <stdio.h>
+#endif
+
+#ifdef _WIN32
+#   include <windows.h>
+#   ifdef small
+      /* windows.h define small to char */
+#      undef small
+#   endif
+#   ifdef BZ_EXPORT
+#   define BZ_API(func) WINAPI func
+#   define BZ_EXTERN extern
+#   else
+   /* import windows dll dynamically */
+#   define BZ_API(func) (WINAPI * func)
+#   define BZ_EXTERN
+#   endif
+#else
+#   define BZ_API(func) func
+#   define BZ_EXTERN extern
+#endif
+
+#include <stdio.h>
+#include "misc/util/abc_global.h"
+
+ABC_NAMESPACE_HEADER_START
+
+/*-- Core (low-level) library functions --*/
+
+BZ_EXTERN int BZ_API(BZ2_bzCompressInit) ( 
+      bz_stream* strm, 
+      int        blockSize100k, 
+      int        verbosity, 
+      int        workFactor 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzCompress) ( 
+      bz_stream* strm, 
+      int action 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) ( 
+      bz_stream* strm 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) ( 
+      bz_stream *strm, 
+      int       verbosity, 
+      int       small
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzDecompress) ( 
+      bz_stream* strm 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) ( 
+      bz_stream *strm 
+   );
+
+
+
+/*-- High(er) level library functions --*/
+
+#ifndef BZ_NO_STDIO
+#define BZ_MAX_UNUSED 5000
+
+typedef void BZFILE;
+
+BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) ( 
+      int*  bzerror,   
+      FILE* f, 
+      int   verbosity, 
+      int   small,
+      void* unused,    
+      int   nUnused 
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzReadClose) ( 
+      int*    bzerror, 
+      BZFILE* b 
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) ( 
+      int*    bzerror, 
+      BZFILE* b, 
+      void**  unused,  
+      int*    nUnused 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzRead) ( 
+      int*    bzerror, 
+      BZFILE* b, 
+      void*   buf, 
+      int     len 
+   );
+
+BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) ( 
+      int*  bzerror,      
+      FILE* f, 
+      int   blockSize100k, 
+      int   verbosity, 
+      int   workFactor 
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzWrite) ( 
+      int*    bzerror, 
+      BZFILE* b, 
+      void*   buf, 
+      int     len 
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzWriteClose) ( 
+      int*          bzerror, 
+      BZFILE*       b, 
+      int           abandon, 
+      unsigned int* nbytes_in, 
+      unsigned int* nbytes_out 
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) ( 
+      int*          bzerror, 
+      BZFILE*       b, 
+      int           abandon, 
+      unsigned int* nbytes_in_lo32, 
+      unsigned int* nbytes_in_hi32, 
+      unsigned int* nbytes_out_lo32, 
+      unsigned int* nbytes_out_hi32
+   );
+#endif
+
+
+/*-- Utility functions --*/
+
+BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) ( 
+      char*         dest, 
+      unsigned int* destLen,
+      char*         source, 
+      unsigned int  sourceLen,
+      int           blockSize100k, 
+      int           verbosity, 
+      int           workFactor 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) ( 
+      char*         dest, 
+      unsigned int* destLen,
+      char*         source, 
+      unsigned int  sourceLen,
+      int           small, 
+      int           verbosity 
+   );
+
+
+/*--
+   Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
+   to support better zlib compatibility.
+   This code is not _officially_ part of libbzip2 (yet);
+   I haven't tested it, documented it, or considered the
+   threading-safeness of it.
+   If this code breaks, please contact both Yoshioka and me.
+--*/
+
+BZ_EXTERN const char * BZ_API(BZ2_bzlibVersion) (
+      void
+   );
+
+#ifndef BZ_NO_STDIO
+BZ_EXTERN BZFILE * BZ_API(BZ2_bzopen) (
+      const char *path,
+      const char *mode
+   );
+
+BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) (
+      int        fd,
+      const char *mode
+   );
+         
+BZ_EXTERN int BZ_API(BZ2_bzread) (
+      BZFILE* b, 
+      void* buf, 
+      int len 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzwrite) (
+      BZFILE* b, 
+      void*   buf, 
+      int     len 
+   );
+
+BZ_EXTERN int BZ_API(BZ2_bzflush) (
+      BZFILE* b
+   );
+
+BZ_EXTERN void BZ_API(BZ2_bzclose) (
+      BZFILE* b
+   );
+
+BZ_EXTERN const char * BZ_API(BZ2_bzerror) (
+      BZFILE *b, 
+      int    *errnum
+   );
+#endif
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+#endif
+
+/*-------------------------------------------------------------*/
+/*--- end                                           bzlib.h ---*/
+/*-------------------------------------------------------------*/
diff --git a/abc-build/src/misc/bzlib/bzlib_private.h b/abc-build/src/misc/bzlib/bzlib_private.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bzlib/bzlib_private.h
@@ -0,0 +1,513 @@
+
+/*-------------------------------------------------------------*/
+/*--- Private header file for the library.                  ---*/
+/*---                                       bzlib_private.h ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+   This file is part of bzip2/libbzip2, a program and library for
+   lossless, block-sorting data compression.
+
+   bzip2/libbzip2 version 1.0.5 of 10 December 2007
+   Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+   Please read the WARNING, DISCLAIMER and PATENTS sections in the 
+   README file.
+
+   This program is released under the terms of the license contained
+   in the file LICENSE.
+   ------------------------------------------------------------------ */
+
+
+#ifndef ABC__misc__bzlib__bzlib_private_h
+#define ABC__misc__bzlib__bzlib_private_h
+
+
+#include <stdlib.h>
+
+#ifndef BZ_NO_STDIO
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#endif
+
+
+#include "bzlib.h"
+
+ABC_NAMESPACE_HEADER_START
+
+/*-- General stuff. --*/
+
+#define BZ_VERSION  "1.0.5, 10-Dec-2007"
+
+typedef char            Char;
+typedef unsigned char   Bool;
+typedef unsigned char   UChar;
+typedef int             Int32;
+typedef unsigned int    UInt32;
+typedef short           Int16;
+typedef unsigned short  UInt16;
+
+#define True  ((Bool)1)
+#define False ((Bool)0)
+
+#ifndef __GNUC__
+#define __inline__  /* */
+#endif 
+
+#ifndef BZ_NO_STDIO
+
+extern void BZ2_bz__AssertH__fail ( int errcode );
+#define AssertH(cond,errcode) \
+   { if (!(cond)) BZ2_bz__AssertH__fail ( errcode ); }
+
+#if BZ_DEBUG
+#define AssertD(cond,msg) \
+   { if (!(cond)) {       \
+      fprintf ( stderr,   \
+        "\n\nlibbzip2(debug build): internal error\n\t%s\n", msg );\
+      exit(1); \
+   }}
+#else
+#define AssertD(cond,msg) /* */
+#endif
+
+#define VPrintf0(zf) \
+   fprintf(stderr,zf)
+#define VPrintf1(zf,za1) \
+   fprintf(stderr,zf,za1)
+#define VPrintf2(zf,za1,za2) \
+   fprintf(stderr,zf,za1,za2)
+#define VPrintf3(zf,za1,za2,za3) \
+   fprintf(stderr,zf,za1,za2,za3)
+#define VPrintf4(zf,za1,za2,za3,za4) \
+   fprintf(stderr,zf,za1,za2,za3,za4)
+#define VPrintf5(zf,za1,za2,za3,za4,za5) \
+   fprintf(stderr,zf,za1,za2,za3,za4,za5)
+
+#else
+
+extern void bz_internal_error ( int errcode );
+#define AssertH(cond,errcode) \
+   { if (!(cond)) bz_internal_error ( errcode ); }
+#define AssertD(cond,msg)                do { } while (0)
+#define VPrintf0(zf)                     do { } while (0)
+#define VPrintf1(zf,za1)                 do { } while (0)
+#define VPrintf2(zf,za1,za2)             do { } while (0)
+#define VPrintf3(zf,za1,za2,za3)         do { } while (0)
+#define VPrintf4(zf,za1,za2,za3,za4)     do { } while (0)
+#define VPrintf5(zf,za1,za2,za3,za4,za5) do { } while (0)
+
+#endif
+
+
+#define BZALLOC(nnn) (strm->bzalloc)(strm->opaque,(nnn),1)
+#define BZFREE(ppp)  (strm->bzfree)(strm->opaque,(ppp))
+
+
+/*-- Header bytes. --*/
+
+#define BZ_HDR_B 0x42   /* 'B' */
+#define BZ_HDR_Z 0x5a   /* 'Z' */
+#define BZ_HDR_h 0x68   /* 'h' */
+#define BZ_HDR_0 0x30   /* '0' */
+  
+/*-- Constants for the back end. --*/
+
+#define BZ_MAX_ALPHA_SIZE 258
+#define BZ_MAX_CODE_LEN    23
+
+#define BZ_RUNA 0
+#define BZ_RUNB 1
+
+#define BZ_N_GROUPS 6
+#define BZ_G_SIZE   50
+#define BZ_N_ITERS  4
+
+#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE))
+
+
+
+/*-- Stuff for randomising repetitive blocks. --*/
+
+extern Int32 BZ2_rNums[512];
+
+#define BZ_RAND_DECLS                          \
+   Int32 rNToGo;                               \
+   Int32 rTPos                                 \
+
+#define BZ_RAND_INIT_MASK                      \
+   s->rNToGo = 0;                              \
+   s->rTPos  = 0                               \
+
+#define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0)
+
+#define BZ_RAND_UPD_MASK                       \
+   if (s->rNToGo == 0) {                       \
+      s->rNToGo = BZ2_rNums[s->rTPos];         \
+      s->rTPos++;                              \
+      if (s->rTPos == 512) s->rTPos = 0;       \
+   }                                           \
+   s->rNToGo--;
+
+
+
+/*-- Stuff for doing CRCs. --*/
+
+extern UInt32 BZ2_crc32Table[256];
+
+#define BZ_INITIALISE_CRC(crcVar)              \
+{                                              \
+   crcVar = 0xffffffffL;                       \
+}
+
+#define BZ_FINALISE_CRC(crcVar)                \
+{                                              \
+   crcVar = ~(crcVar);                         \
+}
+
+#define BZ_UPDATE_CRC(crcVar,cha)              \
+{                                              \
+   crcVar = (crcVar << 8) ^                    \
+            BZ2_crc32Table[(crcVar >> 24) ^    \
+                           ((UChar)cha)];      \
+}
+
+
+
+/*-- States and modes for compression. --*/
+
+#define BZ_M_IDLE      1
+#define BZ_M_RUNNING   2
+#define BZ_M_FLUSHING  3
+#define BZ_M_FINISHING 4
+
+#define BZ_S_OUTPUT    1
+#define BZ_S_INPUT     2
+
+#define BZ_N_RADIX 2
+#define BZ_N_QSORT 12
+#define BZ_N_SHELL 18
+#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2)
+
+
+
+
+/*-- Structure holding all the compression-side stuff. --*/
+
+typedef
+   struct {
+      /* pointer back to the struct bz_stream */
+      bz_stream* strm;
+
+      /* mode this stream is in, and whether inputting */
+      /* or outputting data */
+      Int32    mode;
+      Int32    state;
+
+      /* remembers avail_in when flush/finish requested */
+      UInt32   avail_in_expect;
+
+      /* for doing the block sorting */
+      UInt32*  arr1;
+      UInt32*  arr2;
+      UInt32*  ftab;
+      Int32    origPtr;
+
+      /* aliases for arr1 and arr2 */
+      UInt32*  ptr;
+      UChar*   block;
+      UInt16*  mtfv;
+      UChar*   zbits;
+
+      /* for deciding when to use the fallback sorting algorithm */
+      Int32    workFactor;
+
+      /* run-length-encoding of the input */
+      UInt32   state_in_ch;
+      Int32    state_in_len;
+      BZ_RAND_DECLS;
+
+      /* input and output limits and current posns */
+      Int32    nblock;
+      Int32    nblockMAX;
+      Int32    numZ;
+      Int32    state_out_pos;
+
+      /* map of bytes used in block */
+      Int32    nInUse;
+      Bool     inUse[256];
+      UChar    unseqToSeq[256];
+
+      /* the buffer for bit stream creation */
+      UInt32   bsBuff;
+      Int32    bsLive;
+
+      /* block and combined CRCs */
+      UInt32   blockCRC;
+      UInt32   combinedCRC;
+
+      /* misc administratium */
+      Int32    verbosity;
+      Int32    blockNo;
+      Int32    blockSize100k;
+
+      /* stuff for coding the MTF values */
+      Int32    nMTF;
+      Int32    mtfFreq    [BZ_MAX_ALPHA_SIZE];
+      UChar    selector   [BZ_MAX_SELECTORS];
+      UChar    selectorMtf[BZ_MAX_SELECTORS];
+
+      UChar    len     [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      Int32    code    [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      Int32    rfreq   [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      /* second dimension: only 3 needed; 4 makes index calculations faster */
+      UInt32   len_pack[BZ_MAX_ALPHA_SIZE][4];
+
+   }
+   EState;
+
+
+
+/*-- externs for compression. --*/
+
+extern void 
+BZ2_blockSort ( EState* );
+
+extern void 
+BZ2_compressBlock ( EState*, Bool );
+
+extern void 
+BZ2_bsInitWrite ( EState* );
+
+extern void 
+BZ2_hbAssignCodes ( Int32*, UChar*, Int32, Int32, Int32 );
+
+extern void 
+BZ2_hbMakeCodeLengths ( UChar*, Int32*, Int32, Int32 );
+
+
+
+/*-- states for decompression. --*/
+
+#define BZ_X_IDLE        1
+#define BZ_X_OUTPUT      2
+
+#define BZ_X_MAGIC_1     10
+#define BZ_X_MAGIC_2     11
+#define BZ_X_MAGIC_3     12
+#define BZ_X_MAGIC_4     13
+#define BZ_X_BLKHDR_1    14
+#define BZ_X_BLKHDR_2    15
+#define BZ_X_BLKHDR_3    16
+#define BZ_X_BLKHDR_4    17
+#define BZ_X_BLKHDR_5    18
+#define BZ_X_BLKHDR_6    19
+#define BZ_X_BCRC_1      20
+#define BZ_X_BCRC_2      21
+#define BZ_X_BCRC_3      22
+#define BZ_X_BCRC_4      23
+#define BZ_X_RANDBIT     24
+#define BZ_X_ORIGPTR_1   25
+#define BZ_X_ORIGPTR_2   26
+#define BZ_X_ORIGPTR_3   27
+#define BZ_X_MAPPING_1   28
+#define BZ_X_MAPPING_2   29
+#define BZ_X_SELECTOR_1  30
+#define BZ_X_SELECTOR_2  31
+#define BZ_X_SELECTOR_3  32
+#define BZ_X_CODING_1    33
+#define BZ_X_CODING_2    34
+#define BZ_X_CODING_3    35
+#define BZ_X_MTF_1       36
+#define BZ_X_MTF_2       37
+#define BZ_X_MTF_3       38
+#define BZ_X_MTF_4       39
+#define BZ_X_MTF_5       40
+#define BZ_X_MTF_6       41
+#define BZ_X_ENDHDR_2    42
+#define BZ_X_ENDHDR_3    43
+#define BZ_X_ENDHDR_4    44
+#define BZ_X_ENDHDR_5    45
+#define BZ_X_ENDHDR_6    46
+#define BZ_X_CCRC_1      47
+#define BZ_X_CCRC_2      48
+#define BZ_X_CCRC_3      49
+#define BZ_X_CCRC_4      50
+
+
+
+/*-- Constants for the fast MTF decoder. --*/
+
+#define MTFA_SIZE 4096
+#define MTFL_SIZE 16
+
+
+
+/*-- Structure holding all the decompression-side stuff. --*/
+
+typedef
+   struct {
+      /* pointer back to the struct bz_stream */
+      bz_stream* strm;
+
+      /* state indicator for this stream */
+      Int32    state;
+
+      /* for doing the final run-length decoding */
+      UChar    state_out_ch;
+      Int32    state_out_len;
+      Bool     blockRandomised;
+      BZ_RAND_DECLS;
+
+      /* the buffer for bit stream reading */
+      UInt32   bsBuff;
+      Int32    bsLive;
+
+      /* misc administratium */
+      Int32    blockSize100k;
+      Bool     smallDecompress;
+      Int32    currBlockNo;
+      Int32    verbosity;
+
+      /* for undoing the Burrows-Wheeler transform */
+      Int32    origPtr;
+      UInt32   tPos;
+      Int32    k0;
+      Int32    unzftab[256];
+      Int32    nblock_used;
+      Int32    cftab[257];
+      Int32    cftabCopy[257];
+
+      /* for undoing the Burrows-Wheeler transform (FAST) */
+      UInt32   *tt;
+
+      /* for undoing the Burrows-Wheeler transform (SMALL) */
+      UInt16   *ll16;
+      UChar    *ll4;
+
+      /* stored and calculated CRCs */
+      UInt32   storedBlockCRC;
+      UInt32   storedCombinedCRC;
+      UInt32   calculatedBlockCRC;
+      UInt32   calculatedCombinedCRC;
+
+      /* map of bytes used in block */
+      Int32    nInUse;
+      Bool     inUse[256];
+      Bool     inUse16[16];
+      UChar    seqToUnseq[256];
+
+      /* for decoding the MTF values */
+      UChar    mtfa   [MTFA_SIZE];
+      Int32    mtfbase[256 / MTFL_SIZE];
+      UChar    selector   [BZ_MAX_SELECTORS];
+      UChar    selectorMtf[BZ_MAX_SELECTORS];
+      UChar    len  [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+
+      Int32    limit  [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      Int32    base   [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      Int32    perm   [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+      Int32    minLens[BZ_N_GROUPS];
+
+      /* save area for scalars in the main decompress code */
+      Int32    save_i;
+      Int32    save_j;
+      Int32    save_t;
+      Int32    save_alphaSize;
+      Int32    save_nGroups;
+      Int32    save_nSelectors;
+      Int32    save_EOB;
+      Int32    save_groupNo;
+      Int32    save_groupPos;
+      Int32    save_nextSym;
+      Int32    save_nblockMAX;
+      Int32    save_nblock;
+      Int32    save_es;
+      Int32    save_N;
+      Int32    save_curr;
+      Int32    save_zt;
+      Int32    save_zn; 
+      Int32    save_zvec;
+      Int32    save_zj;
+      Int32    save_gSel;
+      Int32    save_gMinlen;
+      Int32*   save_gLimit;
+      Int32*   save_gBase;
+      Int32*   save_gPerm;
+
+   }
+   DState;
+
+
+
+/*-- Macros for decompression. --*/
+
+#define BZ_GET_FAST(cccc)                     \
+    /* c_tPos is unsigned, hence test < 0 is pointless. */ \
+    if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) return True; \
+    s->tPos = s->tt[s->tPos];                 \
+    cccc = (UChar)(s->tPos & 0xff);           \
+    s->tPos >>= 8;
+
+#define BZ_GET_FAST_C(cccc)                   \
+    /* c_tPos is unsigned, hence test < 0 is pointless. */ \
+    if (c_tPos >= (UInt32)100000 * (UInt32)ro_blockSize100k) return True; \
+    c_tPos = c_tt[c_tPos];                    \
+    cccc = (UChar)(c_tPos & 0xff);            \
+    c_tPos >>= 8;
+
+#define SET_LL4(i,n)                                          \
+   { if (((i) & 0x1) == 0)                                    \
+        s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); else    \
+        s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4);  \
+   }
+
+#define GET_LL4(i)                             \
+   ((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF)
+
+#define SET_LL(i,n)                          \
+   { s->ll16[i] = (UInt16)(n & 0x0000ffff);  \
+     SET_LL4(i, n >> 16);                    \
+   }
+
+#define GET_LL(i) \
+   (((UInt32)s->ll16[i]) | (GET_LL4(i) << 16))
+
+#define BZ_GET_SMALL(cccc)                            \
+    /* c_tPos is unsigned, hence test < 0 is pointless. */ \
+    if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) return True; \
+    cccc = BZ2_indexIntoF ( s->tPos, s->cftab );    \
+    s->tPos = GET_LL(s->tPos);
+
+
+/*-- externs for decompression. --*/
+
+Int32
+BZ2_indexIntoF ( Int32, Int32* );
+
+extern Int32 
+BZ2_decompress ( DState* );
+
+extern void 
+BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*,
+                           Int32,  Int32, Int32 );
+
+
+#endif
+
+
+/*-- BZ_NO_STDIO seems to make NULL disappear on some platforms. --*/
+
+#ifdef BZ_NO_STDIO
+#ifndef NULL
+#define NULL 0
+#endif
+
+#endif
+
+ABC_NAMESPACE_HEADER_END
+
+/*-------------------------------------------------------------*/
+/*--- end                                   bzlib_private.h ---*/
+/*-------------------------------------------------------------*/
diff --git a/abc-build/src/misc/bzlib/compress.c b/abc-build/src/misc/bzlib/compress.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bzlib/compress.c
@@ -0,0 +1,677 @@
+
+/*-------------------------------------------------------------*/
+/*--- Compression machinery (not incl block sorting)        ---*/
+/*---                                            compress.c ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+   This file is part of bzip2/libbzip2, a program and library for
+   lossless, block-sorting data compression.
+
+   bzip2/libbzip2 version 1.0.5 of 10 December 2007
+   Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+   Please read the WARNING, DISCLAIMER and PATENTS sections in the 
+   README file.
+
+   This program is released under the terms of the license contained
+   in the file LICENSE.
+   ------------------------------------------------------------------ */
+
+
+/* CHANGES
+    0.9.0    -- original version.
+    0.9.0a/b -- no changes in this file.
+    0.9.0c   -- changed setting of nGroups in sendMTFValues() 
+                so as to do a bit better on small files
+*/
+
+#include "bzlib_private.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------*/
+/*--- Bit stream I/O                              ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+void BZ2_bsInitWrite ( EState* s )
+{
+   s->bsLive = 0;
+   s->bsBuff = 0;
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsFinishWrite ( EState* s )
+{
+   while (s->bsLive > 0) {
+      s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
+      s->numZ++;
+      s->bsBuff <<= 8;
+      s->bsLive -= 8;
+   }
+}
+
+
+/*---------------------------------------------------*/
+#define bsNEEDW(nz)                           \
+{                                             \
+   while (s->bsLive >= 8) {                   \
+      s->zbits[s->numZ]                       \
+         = (UChar)(s->bsBuff >> 24);          \
+      s->numZ++;                              \
+      s->bsBuff <<= 8;                        \
+      s->bsLive -= 8;                         \
+   }                                          \
+}
+
+
+/*---------------------------------------------------*/
+static
+__inline__
+void bsW ( EState* s, Int32 n, UInt32 v )
+{
+   bsNEEDW ( n );
+   s->bsBuff |= (v << (32 - s->bsLive - n));
+   s->bsLive += n;
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsPutUInt32 ( EState* s, UInt32 u )
+{
+   bsW ( s, 8, (u >> 24) & 0xffL );
+   bsW ( s, 8, (u >> 16) & 0xffL );
+   bsW ( s, 8, (u >>  8) & 0xffL );
+   bsW ( s, 8,  u        & 0xffL );
+}
+
+
+/*---------------------------------------------------*/
+static
+void bsPutUChar ( EState* s, UChar c )
+{
+   bsW( s, 8, (UInt32)c );
+}
+
+
+/*---------------------------------------------------*/
+/*--- The back end proper                         ---*/
+/*---------------------------------------------------*/
+
+/*---------------------------------------------------*/
+static
+void makeMaps_e ( EState* s )
+{
+   Int32 i;
+   s->nInUse = 0;
+   for (i = 0; i < 256; i++)
+      if (s->inUse[i]) {
+         s->unseqToSeq[i] = s->nInUse;
+         s->nInUse++;
+      }
+}
+
+
+/*---------------------------------------------------*/
+static
+void generateMTFValues ( EState* s )
+{
+   UChar   yy[256];
+   Int32   i, j;
+   Int32   zPend;
+   Int32   wr;
+   Int32   EOB;
+
+   /* 
+      After sorting (eg, here),
+         s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
+         and
+         ((UChar*)s->arr2) [ 0 .. s->nblock-1 ] 
+         holds the original block data.
+
+      The first thing to do is generate the MTF values,
+      and put them in
+         ((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
+      Because there are strictly fewer or equal MTF values
+      than block values, ptr values in this area are overwritten
+      with MTF values only when they are no longer needed.
+
+      The final compressed bitstream is generated into the
+      area starting at
+         (UChar*) (&((UChar*)s->arr2)[s->nblock])
+
+      These storage aliases are set up in bzCompressInit(),
+      except for the last one, which is arranged in 
+      compressBlock().
+   */
+   UInt32* ptr   = s->ptr;
+   UChar* block  = s->block;
+   UInt16* mtfv  = s->mtfv;
+
+   makeMaps_e ( s );
+   EOB = s->nInUse+1;
+
+   for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0;
+
+   wr = 0;
+   zPend = 0;
+   for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i;
+
+   for (i = 0; i < s->nblock; i++) {
+      UChar ll_i;
+      AssertD ( wr <= i, "generateMTFValues(1)" );
+      j = ptr[i]-1; if (j < 0) j += s->nblock;
+      ll_i = s->unseqToSeq[block[j]];
+      AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" );
+
+      if (yy[0] == ll_i) { 
+         zPend++;
+      } else {
+
+         if (zPend > 0) {
+            zPend--;
+            while (True) {
+               if (zPend & 1) {
+                  mtfv[wr] = BZ_RUNB; wr++; 
+                  s->mtfFreq[BZ_RUNB]++; 
+               } else {
+                  mtfv[wr] = BZ_RUNA; wr++; 
+                  s->mtfFreq[BZ_RUNA]++; 
+               }
+               if (zPend < 2) break;
+               zPend = (zPend - 2) / 2;
+            };
+            zPend = 0;
+         }
+         {
+            register UChar  rtmp;
+            register UChar* ryy_j;
+            register UChar  rll_i;
+            rtmp  = yy[1];
+            yy[1] = yy[0];
+            ryy_j = &(yy[1]);
+            rll_i = ll_i;
+            while ( rll_i != rtmp ) {
+               register UChar rtmp2;
+               ryy_j++;
+               rtmp2  = rtmp;
+               rtmp   = *ryy_j;
+               *ryy_j = rtmp2;
+            };
+            yy[0] = rtmp;
+            j = ryy_j - &(yy[0]);
+            mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++;
+         }
+
+      }
+   }
+
+   if (zPend > 0) {
+      zPend--;
+      while (True) {
+         if (zPend & 1) {
+            mtfv[wr] = BZ_RUNB; wr++; 
+            s->mtfFreq[BZ_RUNB]++; 
+         } else {
+            mtfv[wr] = BZ_RUNA; wr++; 
+            s->mtfFreq[BZ_RUNA]++; 
+         }
+         if (zPend < 2) break;
+         zPend = (zPend - 2) / 2;
+      };
+      zPend = 0;
+   }
+
+   mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++;
+
+   s->nMTF = wr;
+}
+
+
+/*---------------------------------------------------*/
+#define BZ_LESSER_ICOST  0
+#define BZ_GREATER_ICOST 15
+
+static
+void sendMTFValues ( EState* s )
+{
+   Int32 v, t, i, j, gs, ge, totc, bt, bc, iter;
+   Int32 nSelectors, alphaSize, minLen, maxLen, selCtr;
+   Int32 nGroups, nBytes;
+
+   /*--
+   UChar  len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+   is a global since the decoder also needs it.
+
+   Int32  code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+   Int32  rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
+   are also globals only used in this proc.
+   Made global to keep stack frame size small.
+   --*/
+
+
+   UInt16 cost[BZ_N_GROUPS];
+   Int32  fave[BZ_N_GROUPS];
+
+   UInt16* mtfv = s->mtfv;
+
+   if (s->verbosity >= 3)
+      VPrintf3( "      %d in block, %d after MTF & 1-2 coding, "
+                "%d+2 syms in use\n", 
+                s->nblock, s->nMTF, s->nInUse );
+
+   alphaSize = s->nInUse+2;
+   for (t = 0; t < BZ_N_GROUPS; t++)
+      for (v = 0; v < alphaSize; v++)
+         s->len[t][v] = BZ_GREATER_ICOST;
+
+   /*--- Decide how many coding tables to use ---*/
+   AssertH ( s->nMTF > 0, 3001 );
+   if (s->nMTF < 200)  nGroups = 2; else
+   if (s->nMTF < 600)  nGroups = 3; else
+   if (s->nMTF < 1200) nGroups = 4; else
+   if (s->nMTF < 2400) nGroups = 5; else
+                       nGroups = 6;
+
+   /*--- Generate an initial set of coding tables ---*/
+   { 
+      Int32 nPart, remF, tFreq, aFreq;
+
+      nPart = nGroups;
+      remF  = s->nMTF;
+      gs = 0;
+      while (nPart > 0) {
+         tFreq = remF / nPart;
+         ge = gs-1;
+         aFreq = 0;
+         while (aFreq < tFreq && ge < alphaSize-1) {
+            ge++;
+            aFreq += s->mtfFreq[ge];
+         }
+
+         if (ge > gs 
+             && nPart != nGroups && nPart != 1 
+             && ((nGroups-nPart) % 2 == 1)) {
+            aFreq -= s->mtfFreq[ge];
+            ge--;
+         }
+
+         if (s->verbosity >= 3)
+            VPrintf5( "      initial group %d, [%d .. %d], "
+                      "has %d syms (%4.1f%%)\n",
+                      nPart, gs, ge, aFreq, 
+                      (100.0 * (float)aFreq) / (float)(s->nMTF) );
+ 
+         for (v = 0; v < alphaSize; v++)
+            if (v >= gs && v <= ge) 
+               s->len[nPart-1][v] = BZ_LESSER_ICOST; else
+               s->len[nPart-1][v] = BZ_GREATER_ICOST;
+ 
+         nPart--;
+         gs = ge+1;
+         remF -= aFreq;
+      }
+   }
+
+   /*--- 
+      Iterate up to BZ_N_ITERS times to improve the tables.
+   ---*/
+   for (iter = 0; iter < BZ_N_ITERS; iter++) {
+
+      for (t = 0; t < nGroups; t++) fave[t] = 0;
+
+      for (t = 0; t < nGroups; t++)
+         for (v = 0; v < alphaSize; v++)
+            s->rfreq[t][v] = 0;
+
+      /*---
+        Set up an auxiliary length table which is used to fast-track
+	the common case (nGroups == 6). 
+      ---*/
+      if (nGroups == 6) {
+         for (v = 0; v < alphaSize; v++) {
+            s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v];
+            s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v];
+            s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v];
+	 }
+      }
+
+      nSelectors = 0;
+      totc = 0;
+      gs = 0;
+      while (True) {
+
+         /*--- Set group start & end marks. --*/
+         if (gs >= s->nMTF) break;
+         ge = gs + BZ_G_SIZE - 1; 
+         if (ge >= s->nMTF) ge = s->nMTF-1;
+
+         /*-- 
+            Calculate the cost of this group as coded
+            by each of the coding tables.
+         --*/
+         for (t = 0; t < nGroups; t++) cost[t] = 0;
+
+         if (nGroups == 6 && 50 == ge-gs+1) {
+            /*--- fast track the common case ---*/
+            register UInt32 cost01, cost23, cost45;
+            register UInt16 icv;
+            cost01 = cost23 = cost45 = 0;
+
+#           define BZ_ITER(nn)                \
+               icv = mtfv[gs+(nn)];           \
+               cost01 += s->len_pack[icv][0]; \
+               cost23 += s->len_pack[icv][1]; \
+               cost45 += s->len_pack[icv][2]; \
+
+            BZ_ITER(0);  BZ_ITER(1);  BZ_ITER(2);  BZ_ITER(3);  BZ_ITER(4);
+            BZ_ITER(5);  BZ_ITER(6);  BZ_ITER(7);  BZ_ITER(8);  BZ_ITER(9);
+            BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14);
+            BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19);
+            BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24);
+            BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29);
+            BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34);
+            BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39);
+            BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44);
+            BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49);
+
+#           undef BZ_ITER
+
+            cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16;
+            cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16;
+            cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16;
+
+         } else {
+	    /*--- slow version which correctly handles all situations ---*/
+            for (i = gs; i <= ge; i++) { 
+               UInt16 icv = mtfv[i];
+               for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv];
+            }
+         }
+ 
+         /*-- 
+            Find the coding table which is best for this group,
+            and record its identity in the selector table.
+         --*/
+         bc = 999999999; bt = -1;
+         for (t = 0; t < nGroups; t++)
+            if (cost[t] < bc) { bc = cost[t]; bt = t; };
+         totc += bc;
+         fave[bt]++;
+         s->selector[nSelectors] = bt;
+         nSelectors++;
+
+         /*-- 
+            Increment the symbol frequencies for the selected table.
+          --*/
+         if (nGroups == 6 && 50 == ge-gs+1) {
+            /*--- fast track the common case ---*/
+
+#           define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++
+
+            BZ_ITUR(0);  BZ_ITUR(1);  BZ_ITUR(2);  BZ_ITUR(3);  BZ_ITUR(4);
+            BZ_ITUR(5);  BZ_ITUR(6);  BZ_ITUR(7);  BZ_ITUR(8);  BZ_ITUR(9);
+            BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14);
+            BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19);
+            BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24);
+            BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29);
+            BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34);
+            BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39);
+            BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44);
+            BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49);
+
+#           undef BZ_ITUR
+
+         } else {
+	    /*--- slow version which correctly handles all situations ---*/
+            for (i = gs; i <= ge; i++)
+               s->rfreq[bt][ mtfv[i] ]++;
+         }
+
+         gs = ge+1;
+      }
+      if (s->verbosity >= 3) {
+         VPrintf2 ( "      pass %d: size is %d, grp uses are ", 
+                   iter+1, totc/8 );
+         for (t = 0; t < nGroups; t++)
+            VPrintf1 ( "%d ", fave[t] );
+         VPrintf0 ( "\n" );
+      }
+
+      /*--
+        Recompute the tables based on the accumulated frequencies.
+      --*/
+      /* maxLen was changed from 20 to 17 in bzip2-1.0.3.  See 
+         comment in huffman.c for details. */
+      for (t = 0; t < nGroups; t++)
+         BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]), 
+                                 alphaSize, 17 /*20*/ );
+   }
+
+
+   AssertH( nGroups < 8, 3002 );
+   AssertH( nSelectors < 32768 &&
+            nSelectors <= (2 + (900000 / BZ_G_SIZE)),
+            3003 );
+
+
+   /*--- Compute MTF values for the selectors. ---*/
+   {
+      UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
+      for (i = 0; i < nGroups; i++) pos[i] = i;
+      for (i = 0; i < nSelectors; i++) {
+         ll_i = s->selector[i];
+         j = 0;
+         tmp = pos[j];
+         while ( ll_i != tmp ) {
+            j++;
+            tmp2 = tmp;
+            tmp = pos[j];
+            pos[j] = tmp2;
+         };
+         pos[0] = tmp;
+         s->selectorMtf[i] = j;
+      }
+   };
+
+   /*--- Assign actual codes for the tables. --*/
+   for (t = 0; t < nGroups; t++) {
+      minLen = 32;
+      maxLen = 0;
+      for (i = 0; i < alphaSize; i++) {
+         if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
+         if (s->len[t][i] < minLen) minLen = s->len[t][i];
+      }
+      AssertH ( !(maxLen > 17 /*20*/ ), 3004 );
+      AssertH ( !(minLen < 1),  3005 );
+      BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]), 
+                          minLen, maxLen, alphaSize );
+   }
+
+   /*--- Transmit the mapping table. ---*/
+   { 
+      Bool inUse16[16];
+      for (i = 0; i < 16; i++) {
+          inUse16[i] = False;
+          for (j = 0; j < 16; j++)
+             if (s->inUse[i * 16 + j]) inUse16[i] = True;
+      }
+     
+      nBytes = s->numZ;
+      for (i = 0; i < 16; i++)
+         if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0);
+
+      for (i = 0; i < 16; i++)
+         if (inUse16[i])
+            for (j = 0; j < 16; j++) {
+               if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0);
+            }
+
+      if (s->verbosity >= 3) 
+         VPrintf1( "      bytes: mapping %d, ", s->numZ-nBytes );
+   }
+
+   /*--- Now the selectors. ---*/
+   nBytes = s->numZ;
+   bsW ( s, 3, nGroups );
+   bsW ( s, 15, nSelectors );
+   for (i = 0; i < nSelectors; i++) { 
+      for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1);
+      bsW(s,1,0);
+   }
+   if (s->verbosity >= 3)
+      VPrintf1( "selectors %d, ", s->numZ-nBytes );
+
+   /*--- Now the coding tables. ---*/
+   nBytes = s->numZ;
+
+   for (t = 0; t < nGroups; t++) {
+      Int32 curr = s->len[t][0];
+      bsW ( s, 5, curr );
+      for (i = 0; i < alphaSize; i++) {
+         while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ };
+         while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ };
+         bsW ( s, 1, 0 );
+      }
+   }
+
+   if (s->verbosity >= 3)
+      VPrintf1 ( "code lengths %d, ", s->numZ-nBytes );
+
+   /*--- And finally, the block data proper ---*/
+   nBytes = s->numZ;
+   selCtr = 0;
+   gs = 0;
+   while (True) {
+      if (gs >= s->nMTF) break;
+      ge = gs + BZ_G_SIZE - 1; 
+      if (ge >= s->nMTF) ge = s->nMTF-1;
+      AssertH ( s->selector[selCtr] < nGroups, 3006 );
+
+      if (nGroups == 6 && 50 == ge-gs+1) {
+            /*--- fast track the common case ---*/
+            UInt16 mtfv_i;
+            UChar* s_len_sel_selCtr 
+               = &(s->len[s->selector[selCtr]][0]);
+            Int32* s_code_sel_selCtr
+               = &(s->code[s->selector[selCtr]][0]);
+
+#           define BZ_ITAH(nn)                      \
+               mtfv_i = mtfv[gs+(nn)];              \
+               bsW ( s,                             \
+                     s_len_sel_selCtr[mtfv_i],      \
+                     s_code_sel_selCtr[mtfv_i] )
+
+            BZ_ITAH(0);  BZ_ITAH(1);  BZ_ITAH(2);  BZ_ITAH(3);  BZ_ITAH(4);
+            BZ_ITAH(5);  BZ_ITAH(6);  BZ_ITAH(7);  BZ_ITAH(8);  BZ_ITAH(9);
+            BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14);
+            BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19);
+            BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24);
+            BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29);
+            BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34);
+            BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39);
+            BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44);
+            BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49);
+
+#           undef BZ_ITAH
+
+      } else {
+	 /*--- slow version which correctly handles all situations ---*/
+         for (i = gs; i <= ge; i++) {
+            bsW ( s, 
+                  s->len  [s->selector[selCtr]] [mtfv[i]],
+                  s->code [s->selector[selCtr]] [mtfv[i]] );
+         }
+      }
+
+
+      gs = ge+1;
+      selCtr++;
+   }
+   AssertH( selCtr == nSelectors, 3007 );
+
+   if (s->verbosity >= 3)
+      VPrintf1( "codes %d\n", s->numZ-nBytes );
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_compressBlock ( EState* s, Bool is_last_block )
+{
+   if (s->nblock > 0) {
+
+      BZ_FINALISE_CRC ( s->blockCRC );
+      s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
+      s->combinedCRC ^= s->blockCRC;
+      if (s->blockNo > 1) s->numZ = 0;
+
+      if (s->verbosity >= 2)
+         VPrintf4( "    block %d: crc = 0x%08x, "
+                   "combined CRC = 0x%08x, size = %d\n",
+                   s->blockNo, s->blockCRC, s->combinedCRC, s->nblock );
+
+      BZ2_blockSort ( s );
+   }
+
+   s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]);
+
+   /*-- If this is the first block, create the stream header. --*/
+   if (s->blockNo == 1) {
+      BZ2_bsInitWrite ( s );
+      bsPutUChar ( s, BZ_HDR_B );
+      bsPutUChar ( s, BZ_HDR_Z );
+      bsPutUChar ( s, BZ_HDR_h );
+      bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) );
+   }
+
+   if (s->nblock > 0) {
+
+      bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 );
+      bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 );
+      bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 );
+
+      /*-- Now the block's CRC, so it is in a known place. --*/
+      bsPutUInt32 ( s, s->blockCRC );
+
+      /*-- 
+         Now a single bit indicating (non-)randomisation. 
+         As of version 0.9.5, we use a better sorting algorithm
+         which makes randomisation unnecessary.  So always set
+         the randomised bit to 'no'.  Of course, the decoder
+         still needs to be able to handle randomised blocks
+         so as to maintain backwards compatibility with
+         older versions of bzip2.
+      --*/
+      bsW(s,1,0);
+
+      bsW ( s, 24, s->origPtr );
+      generateMTFValues ( s );
+      sendMTFValues ( s );
+   }
+
+
+   /*-- If this is the last block, add the stream trailer. --*/
+   if (is_last_block) {
+
+      bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 );
+      bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 );
+      bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 );
+      bsPutUInt32 ( s, s->combinedCRC );
+      if (s->verbosity >= 2)
+         VPrintf1( "    final combined CRC = 0x%08x\n   ", s->combinedCRC );
+      bsFinishWrite ( s );
+   }
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                        compress.c ---*/
+/*-------------------------------------------------------------*/
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/bzlib/crctable.c b/abc-build/src/misc/bzlib/crctable.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bzlib/crctable.c
@@ -0,0 +1,109 @@
+
+/*-------------------------------------------------------------*/
+/*--- Table for doing CRCs                                  ---*/
+/*---                                            crctable.c ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+   This file is part of bzip2/libbzip2, a program and library for
+   lossless, block-sorting data compression.
+
+   bzip2/libbzip2 version 1.0.5 of 10 December 2007
+   Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+   Please read the WARNING, DISCLAIMER and PATENTS sections in the 
+   README file.
+
+   This program is released under the terms of the license contained
+   in the file LICENSE.
+   ------------------------------------------------------------------ */
+
+
+#include "bzlib_private.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*--
+  I think this is an implementation of the AUTODIN-II,
+  Ethernet & FDDI 32-bit CRC standard.  Vaguely derived
+  from code by Rob Warnock, in Section 51 of the
+  comp.compression FAQ.
+--*/
+
+UInt32 BZ2_crc32Table[256] = {
+
+   /*-- Ugly, innit? --*/
+
+   0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L,
+   0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L,
+   0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L,
+   0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL,
+   0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L,
+   0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L,
+   0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L,
+   0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL,
+   0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L,
+   0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L,
+   0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L,
+   0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL,
+   0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L,
+   0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L,
+   0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L,
+   0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL,
+   0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL,
+   0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L,
+   0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L,
+   0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL,
+   0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL,
+   0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L,
+   0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L,
+   0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL,
+   0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL,
+   0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L,
+   0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L,
+   0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL,
+   0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL,
+   0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L,
+   0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L,
+   0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL,
+   0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L,
+   0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL,
+   0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL,
+   0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L,
+   0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L,
+   0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL,
+   0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL,
+   0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L,
+   0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L,
+   0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL,
+   0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL,
+   0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L,
+   0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L,
+   0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL,
+   0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL,
+   0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L,
+   0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L,
+   0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL,
+   0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L,
+   0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L,
+   0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L,
+   0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL,
+   0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L,
+   0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L,
+   0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L,
+   0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL,
+   0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L,
+   0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L,
+   0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L,
+   0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL,
+   0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L,
+   0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L
+};
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                        crctable.c ---*/
+/*-------------------------------------------------------------*/
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/bzlib/decompress.c b/abc-build/src/misc/bzlib/decompress.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bzlib/decompress.c
@@ -0,0 +1,631 @@
+
+/*-------------------------------------------------------------*/
+/*--- Decompression machinery                               ---*/
+/*---                                          decompress.c ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+   This file is part of bzip2/libbzip2, a program and library for
+   lossless, block-sorting data compression.
+
+   bzip2/libbzip2 version 1.0.5 of 10 December 2007
+   Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+   Please read the WARNING, DISCLAIMER and PATENTS sections in the 
+   README file.
+
+   This program is released under the terms of the license contained
+   in the file LICENSE.
+   ------------------------------------------------------------------ */
+
+
+#include "bzlib_private.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------------*/
+static
+void makeMaps_d ( DState* s )
+{
+   Int32 i;
+   s->nInUse = 0;
+   for (i = 0; i < 256; i++)
+      if (s->inUse[i]) {
+         s->seqToUnseq[s->nInUse] = i;
+         s->nInUse++;
+      }
+}
+
+
+/*---------------------------------------------------*/
+#define RETURN(rrr)                               \
+   { retVal = rrr; goto save_state_and_return; };
+
+#define GET_BITS(lll,vvv,nnn)                     \
+   case lll: s->state = lll;                      \
+   while (True) {                                 \
+      if (s->bsLive >= nnn) {                     \
+         UInt32 v;                                \
+         v = (s->bsBuff >>                        \
+             (s->bsLive-nnn)) & ((1 << nnn)-1);   \
+         s->bsLive -= nnn;                        \
+         vvv = v;                                 \
+         break;                                   \
+      }                                           \
+      if (s->strm->avail_in == 0) RETURN(BZ_OK);  \
+      s->bsBuff                                   \
+         = (s->bsBuff << 8) |                     \
+           ((UInt32)                              \
+              (*((UChar*)(s->strm->next_in))));   \
+      s->bsLive += 8;                             \
+      s->strm->next_in++;                         \
+      s->strm->avail_in--;                        \
+      s->strm->total_in_lo32++;                   \
+      if (s->strm->total_in_lo32 == 0)            \
+         s->strm->total_in_hi32++;                \
+   }
+
+#define GET_UCHAR(lll,uuu)                        \
+   GET_BITS(lll,uuu,8)
+
+#define GET_BIT(lll,uuu)                          \
+   GET_BITS(lll,uuu,1)
+
+/*---------------------------------------------------*/
+#define GET_MTF_VAL(label1,label2,lval)           \
+{                                                 \
+   if (groupPos == 0) {                           \
+      groupNo++;                                  \
+      if (groupNo >= nSelectors)                  \
+         RETURN(BZ_DATA_ERROR);                   \
+      groupPos = BZ_G_SIZE;                       \
+      gSel = s->selector[groupNo];                \
+      gMinlen = s->minLens[gSel];                 \
+      gLimit = &(s->limit[gSel][0]);              \
+      gPerm = &(s->perm[gSel][0]);                \
+      gBase = &(s->base[gSel][0]);                \
+   }                                              \
+   groupPos--;                                    \
+   zn = gMinlen;                                  \
+   GET_BITS(label1, zvec, zn);                    \
+   while (1) {                                    \
+      if (zn > 20 /* the longest code */)         \
+         RETURN(BZ_DATA_ERROR);                   \
+      if (zvec <= gLimit[zn]) break;              \
+      zn++;                                       \
+      GET_BIT(label2, zj);                        \
+      zvec = (zvec << 1) | zj;                    \
+   };                                             \
+   if (zvec - gBase[zn] < 0                       \
+       || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE)  \
+      RETURN(BZ_DATA_ERROR);                      \
+   lval = gPerm[zvec - gBase[zn]];                \
+}
+
+
+/*---------------------------------------------------*/
+Int32 BZ2_decompress ( DState* s )
+{
+   UChar      uc;
+   Int32      retVal;
+   Int32      minLen, maxLen;
+   bz_stream* strm = s->strm;
+
+   /* stuff that needs to be saved/restored */
+   Int32  i;
+   Int32  j;
+   Int32  t;
+   Int32  alphaSize;
+   Int32  nGroups;
+   Int32  nSelectors;
+   Int32  EOB;
+   Int32  groupNo;
+   Int32  groupPos;
+   Int32  nextSym;
+   Int32  nblockMAX;
+   Int32  nblock;
+   Int32  es;
+   Int32  N;
+   Int32  curr;
+   Int32  zt;
+   Int32  zn; 
+   Int32  zvec;
+   Int32  zj;
+   Int32  gSel;
+   Int32  gMinlen;
+   Int32* gLimit;
+   Int32* gBase;
+   Int32* gPerm;
+
+   if (s->state == BZ_X_MAGIC_1) {
+      /*initialise the save area*/
+      s->save_i           = 0;
+      s->save_j           = 0;
+      s->save_t           = 0;
+      s->save_alphaSize   = 0;
+      s->save_nGroups     = 0;
+      s->save_nSelectors  = 0;
+      s->save_EOB         = 0;
+      s->save_groupNo     = 0;
+      s->save_groupPos    = 0;
+      s->save_nextSym     = 0;
+      s->save_nblockMAX   = 0;
+      s->save_nblock      = 0;
+      s->save_es          = 0;
+      s->save_N           = 0;
+      s->save_curr        = 0;
+      s->save_zt          = 0;
+      s->save_zn          = 0;
+      s->save_zvec        = 0;
+      s->save_zj          = 0;
+      s->save_gSel        = 0;
+      s->save_gMinlen     = 0;
+      s->save_gLimit      = NULL;
+      s->save_gBase       = NULL;
+      s->save_gPerm       = NULL;
+   }
+
+   /*restore from the save area*/
+   i           = s->save_i;
+   j           = s->save_j;
+   t           = s->save_t;
+   alphaSize   = s->save_alphaSize;
+   nGroups     = s->save_nGroups;
+   nSelectors  = s->save_nSelectors;
+   EOB         = s->save_EOB;
+   groupNo     = s->save_groupNo;
+   groupPos    = s->save_groupPos;
+   nextSym     = s->save_nextSym;
+   nblockMAX   = s->save_nblockMAX;
+   nblock      = s->save_nblock;
+   es          = s->save_es;
+   N           = s->save_N;
+   curr        = s->save_curr;
+   zt          = s->save_zt;
+   zn          = s->save_zn; 
+   zvec        = s->save_zvec;
+   zj          = s->save_zj;
+   gSel        = s->save_gSel;
+   gMinlen     = s->save_gMinlen;
+   gLimit      = s->save_gLimit;
+   gBase       = s->save_gBase;
+   gPerm       = s->save_gPerm;
+
+   retVal = BZ_OK;
+
+   switch (s->state) {
+
+      GET_UCHAR(BZ_X_MAGIC_1, uc);
+      if (uc != BZ_HDR_B) RETURN(BZ_DATA_ERROR_MAGIC);
+
+      GET_UCHAR(BZ_X_MAGIC_2, uc);
+      if (uc != BZ_HDR_Z) RETURN(BZ_DATA_ERROR_MAGIC);
+
+      GET_UCHAR(BZ_X_MAGIC_3, uc)
+      if (uc != BZ_HDR_h) RETURN(BZ_DATA_ERROR_MAGIC);
+
+      GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
+      if (s->blockSize100k < (BZ_HDR_0 + 1) || 
+          s->blockSize100k > (BZ_HDR_0 + 9)) RETURN(BZ_DATA_ERROR_MAGIC);
+      s->blockSize100k -= BZ_HDR_0;
+
+      if (s->smallDecompress) {
+         s->ll16 = (unsigned short *)BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) );
+         s->ll4  = (unsigned char *)BZALLOC( 
+                      ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar) 
+                   );
+         if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR);
+      } else {
+         s->tt  = (unsigned *)BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) );
+         if (s->tt == NULL) RETURN(BZ_MEM_ERROR);
+      }
+
+      GET_UCHAR(BZ_X_BLKHDR_1, uc);
+
+      if (uc == 0x17) goto endhdr_2;
+      if (uc != 0x31) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_2, uc);
+      if (uc != 0x41) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_3, uc);
+      if (uc != 0x59) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_4, uc);
+      if (uc != 0x26) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_5, uc);
+      if (uc != 0x53) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_6, uc);
+      if (uc != 0x59) RETURN(BZ_DATA_ERROR);
+
+      s->currBlockNo++;
+      if (s->verbosity >= 2)
+         VPrintf1 ( "\n    [%d: huff+mtf ", s->currBlockNo );
+ 
+      s->storedBlockCRC = 0;
+      GET_UCHAR(BZ_X_BCRC_1, uc);
+      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_BCRC_2, uc);
+      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_BCRC_3, uc);
+      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_BCRC_4, uc);
+      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+
+      GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
+
+      s->origPtr = 0;
+      GET_UCHAR(BZ_X_ORIGPTR_1, uc);
+      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+      GET_UCHAR(BZ_X_ORIGPTR_2, uc);
+      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+      GET_UCHAR(BZ_X_ORIGPTR_3, uc);
+      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+
+      if (s->origPtr < 0)
+         RETURN(BZ_DATA_ERROR);
+      if (s->origPtr > 10 + 100000*s->blockSize100k) 
+         RETURN(BZ_DATA_ERROR);
+
+      /*--- Receive the mapping table ---*/
+      for (i = 0; i < 16; i++) {
+         GET_BIT(BZ_X_MAPPING_1, uc);
+         if (uc == 1) 
+            s->inUse16[i] = True; else 
+            s->inUse16[i] = False;
+      }
+
+      for (i = 0; i < 256; i++) s->inUse[i] = False;
+
+      for (i = 0; i < 16; i++)
+         if (s->inUse16[i])
+            for (j = 0; j < 16; j++) {
+               GET_BIT(BZ_X_MAPPING_2, uc);
+               if (uc == 1) s->inUse[i * 16 + j] = True;
+            }
+      makeMaps_d ( s );
+      if (s->nInUse == 0) RETURN(BZ_DATA_ERROR);
+      alphaSize = s->nInUse+2;
+
+      /*--- Now the selectors ---*/
+      GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
+      if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
+      GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
+      if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
+      for (i = 0; i < nSelectors; i++) {
+         j = 0;
+         while (True) {
+            GET_BIT(BZ_X_SELECTOR_3, uc);
+            if (uc == 0) break;
+            j++;
+            if (j >= nGroups) RETURN(BZ_DATA_ERROR);
+         }
+         s->selectorMtf[i] = j;
+      }
+
+      /*--- Undo the MTF values for the selectors. ---*/
+      {
+         UChar pos[BZ_N_GROUPS], tmp, v;
+         for (v = 0; v < nGroups; v++) pos[v] = v;
+   
+         for (i = 0; i < nSelectors; i++) {
+            v = s->selectorMtf[i];
+            tmp = pos[v];
+            while (v > 0) { pos[v] = pos[v-1]; v--; }
+            pos[0] = tmp;
+            s->selector[i] = tmp;
+         }
+      }
+
+      /*--- Now the coding tables ---*/
+      for (t = 0; t < nGroups; t++) {
+         GET_BITS(BZ_X_CODING_1, curr, 5);
+         for (i = 0; i < alphaSize; i++) {
+            while (True) {
+               if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR);
+               GET_BIT(BZ_X_CODING_2, uc);
+               if (uc == 0) break;
+               GET_BIT(BZ_X_CODING_3, uc);
+               if (uc == 0) curr++; else curr--;
+            }
+            s->len[t][i] = curr;
+         }
+      }
+
+      /*--- Create the Huffman decoding tables ---*/
+      for (t = 0; t < nGroups; t++) {
+         minLen = 32;
+         maxLen = 0;
+         for (i = 0; i < alphaSize; i++) {
+            if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
+            if (s->len[t][i] < minLen) minLen = s->len[t][i];
+         }
+         BZ2_hbCreateDecodeTables ( 
+            &(s->limit[t][0]), 
+            &(s->base[t][0]), 
+            &(s->perm[t][0]), 
+            &(s->len[t][0]),
+            minLen, maxLen, alphaSize
+         );
+         s->minLens[t] = minLen;
+      }
+
+      /*--- Now the MTF values ---*/
+
+      EOB      = s->nInUse+1;
+      nblockMAX = 100000 * s->blockSize100k;
+      groupNo  = -1;
+      groupPos = 0;
+
+      for (i = 0; i <= 255; i++) s->unzftab[i] = 0;
+
+      /*-- MTF init --*/
+      {
+         Int32 ii, jj, kk;
+         kk = MTFA_SIZE-1;
+         for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
+            for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
+               s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj);
+               kk--;
+            }
+            s->mtfbase[ii] = kk + 1;
+         }
+      }
+      /*-- end MTF init --*/
+
+      nblock = 0;
+      GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
+
+      while (True) {
+
+         if (nextSym == EOB) break;
+
+         if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
+
+            es = -1;
+            N = 1;
+            do {
+               if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
+               if (nextSym == BZ_RUNB) es = es + (1+1) * N;
+               N = N * 2;
+               GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
+            }
+               while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
+
+            es++;
+            uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
+            s->unzftab[uc] += es;
+
+            if (s->smallDecompress)
+               while (es > 0) {
+                  if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+                  s->ll16[nblock] = (UInt16)uc;
+                  nblock++;
+                  es--;
+               }
+            else
+               while (es > 0) {
+                  if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+                  s->tt[nblock] = (UInt32)uc;
+                  nblock++;
+                  es--;
+               };
+
+            continue;
+
+         } else {
+
+            if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+
+            /*-- uc = MTF ( nextSym-1 ) --*/
+            {
+               Int32 ii, jj, kk, pp, lno, off;
+               UInt32 nn;
+               nn = (UInt32)(nextSym - 1);
+
+               if (nn < MTFL_SIZE) {
+                  /* avoid general-case expense */
+                  pp = s->mtfbase[0];
+                  uc = s->mtfa[pp+nn];
+                  while (nn > 3) {
+                     Int32 z = pp+nn;
+                     s->mtfa[(z)  ] = s->mtfa[(z)-1];
+                     s->mtfa[(z)-1] = s->mtfa[(z)-2];
+                     s->mtfa[(z)-2] = s->mtfa[(z)-3];
+                     s->mtfa[(z)-3] = s->mtfa[(z)-4];
+                     nn -= 4;
+                  }
+                  while (nn > 0) { 
+                     s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--; 
+                  };
+                  s->mtfa[pp] = uc;
+               } else { 
+                  /* general case */
+                  lno = nn / MTFL_SIZE;
+                  off = nn % MTFL_SIZE;
+                  pp = s->mtfbase[lno] + off;
+                  uc = s->mtfa[pp];
+                  while (pp > s->mtfbase[lno]) { 
+                     s->mtfa[pp] = s->mtfa[pp-1]; pp--; 
+                  };
+                  s->mtfbase[lno]++;
+                  while (lno > 0) {
+                     s->mtfbase[lno]--;
+                     s->mtfa[s->mtfbase[lno]] 
+                        = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
+                     lno--;
+                  }
+                  s->mtfbase[0]--;
+                  s->mtfa[s->mtfbase[0]] = uc;
+                  if (s->mtfbase[0] == 0) {
+                     kk = MTFA_SIZE-1;
+                     for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
+                        for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
+                           s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
+                           kk--;
+                        }
+                        s->mtfbase[ii] = kk + 1;
+                     }
+                  }
+               }
+            }
+            /*-- end uc = MTF ( nextSym-1 ) --*/
+
+            s->unzftab[s->seqToUnseq[uc]]++;
+            if (s->smallDecompress)
+               s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else
+               s->tt[nblock]   = (UInt32)(s->seqToUnseq[uc]);
+            nblock++;
+
+            GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
+            continue;
+         }
+      }
+
+      /* Now we know what nblock is, we can do a better sanity
+         check on s->origPtr.
+      */
+      if (s->origPtr < 0 || s->origPtr >= nblock)
+         RETURN(BZ_DATA_ERROR);
+
+      /*-- Set up cftab to facilitate generation of T^(-1) --*/
+      s->cftab[0] = 0;
+      for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
+      for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
+      for (i = 0; i <= 256; i++) {
+         if (s->cftab[i] < 0 || s->cftab[i] > nblock) {
+            /* s->cftab[i] can legitimately be == nblock */
+            RETURN(BZ_DATA_ERROR);
+         }
+      }
+
+      s->state_out_len = 0;
+      s->state_out_ch  = 0;
+      BZ_INITIALISE_CRC ( s->calculatedBlockCRC );
+      s->state = BZ_X_OUTPUT;
+      if (s->verbosity >= 2) VPrintf0 ( "rt+rld" );
+
+      if (s->smallDecompress) {
+
+         /*-- Make a copy of cftab, used in generation of T --*/
+         for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i];
+
+         /*-- compute the T vector --*/
+         for (i = 0; i < nblock; i++) {
+            uc = (UChar)(s->ll16[i]);
+            SET_LL(i, s->cftabCopy[uc]);
+            s->cftabCopy[uc]++;
+         }
+
+         /*-- Compute T^(-1) by pointer reversal on T --*/
+         i = s->origPtr;
+         j = GET_LL(i);
+         do {
+            Int32 tmp = GET_LL(j);
+            SET_LL(j, i);
+            i = j;
+            j = tmp;
+         }
+            while (i != s->origPtr);
+
+         s->tPos = s->origPtr;
+         s->nblock_used = 0;
+         if (s->blockRandomised) {
+            BZ_RAND_INIT_MASK;
+            BZ_GET_SMALL(s->k0); s->nblock_used++;
+            BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; 
+         } else {
+            BZ_GET_SMALL(s->k0); s->nblock_used++;
+         }
+
+      } else {
+
+         /*-- compute the T^(-1) vector --*/
+         for (i = 0; i < nblock; i++) {
+            uc = (UChar)(s->tt[i] & 0xff);
+            s->tt[s->cftab[uc]] |= (i << 8);
+            s->cftab[uc]++;
+         }
+
+         s->tPos = s->tt[s->origPtr] >> 8;
+         s->nblock_used = 0;
+         if (s->blockRandomised) {
+            BZ_RAND_INIT_MASK;
+            BZ_GET_FAST(s->k0); s->nblock_used++;
+            BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; 
+         } else {
+            BZ_GET_FAST(s->k0); s->nblock_used++;
+         }
+
+      }
+
+      RETURN(BZ_OK);
+
+
+
+    endhdr_2:
+
+      GET_UCHAR(BZ_X_ENDHDR_2, uc);
+      if (uc != 0x72) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_ENDHDR_3, uc);
+      if (uc != 0x45) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_ENDHDR_4, uc);
+      if (uc != 0x38) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_ENDHDR_5, uc);
+      if (uc != 0x50) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_ENDHDR_6, uc);
+      if (uc != 0x90) RETURN(BZ_DATA_ERROR);
+
+      s->storedCombinedCRC = 0;
+      GET_UCHAR(BZ_X_CCRC_1, uc);
+      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_CCRC_2, uc);
+      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_CCRC_3, uc);
+      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_CCRC_4, uc);
+      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+
+      s->state = BZ_X_IDLE;
+      RETURN(BZ_STREAM_END);
+
+      default: AssertH ( False, 4001 );
+   }
+
+   AssertH ( False, 4002 );
+
+   save_state_and_return:
+
+   s->save_i           = i;
+   s->save_j           = j;
+   s->save_t           = t;
+   s->save_alphaSize   = alphaSize;
+   s->save_nGroups     = nGroups;
+   s->save_nSelectors  = nSelectors;
+   s->save_EOB         = EOB;
+   s->save_groupNo     = groupNo;
+   s->save_groupPos    = groupPos;
+   s->save_nextSym     = nextSym;
+   s->save_nblockMAX   = nblockMAX;
+   s->save_nblock      = nblock;
+   s->save_es          = es;
+   s->save_N           = N;
+   s->save_curr        = curr;
+   s->save_zt          = zt;
+   s->save_zn          = zn;
+   s->save_zvec        = zvec;
+   s->save_zj          = zj;
+   s->save_gSel        = gSel;
+   s->save_gMinlen     = gMinlen;
+   s->save_gLimit      = gLimit;
+   s->save_gBase       = gBase;
+   s->save_gPerm       = gPerm;
+
+   return retVal;   
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                      decompress.c ---*/
+/*-------------------------------------------------------------*/
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/bzlib/huffman.c b/abc-build/src/misc/bzlib/huffman.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bzlib/huffman.c
@@ -0,0 +1,210 @@
+
+/*-------------------------------------------------------------*/
+/*--- Huffman coding low-level stuff                        ---*/
+/*---                                             huffman.c ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+   This file is part of bzip2/libbzip2, a program and library for
+   lossless, block-sorting data compression.
+
+   bzip2/libbzip2 version 1.0.5 of 10 December 2007
+   Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+   Please read the WARNING, DISCLAIMER and PATENTS sections in the 
+   README file.
+
+   This program is released under the terms of the license contained
+   in the file LICENSE.
+   ------------------------------------------------------------------ */
+
+
+#include "bzlib_private.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*---------------------------------------------------*/
+#define WEIGHTOF(zz0)  ((zz0) & 0xffffff00)
+#define DEPTHOF(zz1)   ((zz1) & 0x000000ff)
+#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3))
+
+#define ADDWEIGHTS(zw1,zw2)                           \
+   (WEIGHTOF(zw1)+WEIGHTOF(zw2)) |                    \
+   (1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2)))
+
+#define UPHEAP(z)                                     \
+{                                                     \
+   Int32 zz, tmp;                                     \
+   zz = z; tmp = heap[zz];                            \
+   while (weight[tmp] < weight[heap[zz >> 1]]) {      \
+      heap[zz] = heap[zz >> 1];                       \
+      zz >>= 1;                                       \
+   }                                                  \
+   heap[zz] = tmp;                                    \
+}
+
+#define DOWNHEAP(z)                                   \
+{                                                     \
+   Int32 zz, yy, tmp;                                 \
+   zz = z; tmp = heap[zz];                            \
+   while (True) {                                     \
+      yy = zz << 1;                                   \
+      if (yy > nHeap) break;                          \
+      if (yy < nHeap &&                               \
+          weight[heap[yy+1]] < weight[heap[yy]])      \
+         yy++;                                        \
+      if (weight[tmp] < weight[heap[yy]]) break;      \
+      heap[zz] = heap[yy];                            \
+      zz = yy;                                        \
+   }                                                  \
+   heap[zz] = tmp;                                    \
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_hbMakeCodeLengths ( UChar *len, 
+                             Int32 *freq,
+                             Int32 alphaSize,
+                             Int32 maxLen )
+{
+   /*--
+      Nodes and heap entries run from 1.  Entry 0
+      for both the heap and nodes is a sentinel.
+   --*/
+   Int32 nNodes, nHeap, n1, n2, i, j, k;
+   Bool  tooLong;
+
+   Int32 heap   [ BZ_MAX_ALPHA_SIZE + 2 ];
+   Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ];
+   Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ]; 
+
+   for (i = 0; i < alphaSize; i++)
+      weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
+
+   while (True) {
+
+      nNodes = alphaSize;
+      nHeap = 0;
+
+      heap[0] = 0;
+      weight[0] = 0;
+      parent[0] = -2;
+
+      for (i = 1; i <= alphaSize; i++) {
+         parent[i] = -1;
+         nHeap++;
+         heap[nHeap] = i;
+         UPHEAP(nHeap);
+      }
+
+      AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 );
+   
+      while (nHeap > 1) {
+         n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
+         n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
+         nNodes++;
+         parent[n1] = parent[n2] = nNodes;
+         weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]);
+         parent[nNodes] = -1;
+         nHeap++;
+         heap[nHeap] = nNodes;
+         UPHEAP(nHeap);
+      }
+
+      AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 );
+
+      tooLong = False;
+      for (i = 1; i <= alphaSize; i++) {
+         j = 0;
+         k = i;
+         while (parent[k] >= 0) { k = parent[k]; j++; }
+         len[i-1] = j;
+         if (j > maxLen) tooLong = True;
+      }
+      
+      if (! tooLong) break;
+
+      /* 17 Oct 04: keep-going condition for the following loop used
+         to be 'i < alphaSize', which missed the last element,
+         theoretically leading to the possibility of the compressor
+         looping.  However, this count-scaling step is only needed if
+         one of the generated Huffman code words is longer than
+         maxLen, which up to and including version 1.0.2 was 20 bits,
+         which is extremely unlikely.  In version 1.0.3 maxLen was
+         changed to 17 bits, which has minimal effect on compression
+         ratio, but does mean this scaling step is used from time to
+         time, enough to verify that it works.
+
+         This means that bzip2-1.0.3 and later will only produce
+         Huffman codes with a maximum length of 17 bits.  However, in
+         order to preserve backwards compatibility with bitstreams
+         produced by versions pre-1.0.3, the decompressor must still
+         handle lengths of up to 20. */
+
+      for (i = 1; i <= alphaSize; i++) {
+         j = weight[i] >> 8;
+         j = 1 + (j / 2);
+         weight[i] = j << 8;
+      }
+   }
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_hbAssignCodes ( Int32 *code,
+                         UChar *length,
+                         Int32 minLen,
+                         Int32 maxLen,
+                         Int32 alphaSize )
+{
+   Int32 n, vec, i;
+
+   vec = 0;
+   for (n = minLen; n <= maxLen; n++) {
+      for (i = 0; i < alphaSize; i++)
+         if (length[i] == n) { code[i] = vec; vec++; };
+      vec <<= 1;
+   }
+}
+
+
+/*---------------------------------------------------*/
+void BZ2_hbCreateDecodeTables ( Int32 *limit,
+                                Int32 *base,
+                                Int32 *perm,
+                                UChar *length,
+                                Int32 minLen,
+                                Int32 maxLen,
+                                Int32 alphaSize )
+{
+   Int32 pp, i, j, vec;
+
+   pp = 0;
+   for (i = minLen; i <= maxLen; i++)
+      for (j = 0; j < alphaSize; j++)
+         if (length[j] == i) { perm[pp] = j; pp++; };
+
+   for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0;
+   for (i = 0; i < alphaSize; i++) base[length[i]+1]++;
+
+   for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1];
+
+   for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0;
+   vec = 0;
+
+   for (i = minLen; i <= maxLen; i++) {
+      vec += (base[i+1] - base[i]);
+      limit[i] = vec-1;
+      vec <<= 1;
+   }
+   for (i = minLen + 1; i <= maxLen; i++)
+      base[i] = ((limit[i-1] + 1) << 1) - base[i];
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                         huffman.c ---*/
+/*-------------------------------------------------------------*/
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/misc/bzlib/link.txt b/abc-build/src/misc/bzlib/link.txt
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bzlib/link.txt
@@ -0,0 +1,2 @@
+http://www.bzip.org
+http://gnuwin32.sourceforge.net/packages/bzip2.htm
diff --git a/abc-build/src/misc/bzlib/manual.html b/abc-build/src/misc/bzlib/manual.html
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bzlib/manual.html
@@ -0,0 +1,2540 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>bzip2 and libbzip2, version 1.0.5</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.69.1">
+<style type="text/css" media="screen">/* Colours:
+#74240f  dark brown      h1, h2, h3, h4
+#336699  medium blue     links
+#339999  turquoise       link hover colour
+#202020  almost black    general text
+#761596  purple          md5sum text
+#626262  dark gray       pre border
+#eeeeee  very light gray pre background
+#f2f2f9  very light blue nav table background
+#3366cc  medium blue     nav table border
+*/
+
+a, a:link, a:visited, a:active { color: #336699; }
+a:hover { color: #339999; }
+
+body { font: 80%/126% sans-serif; }
+h1, h2, h3, h4 { color: #74240f; }
+
+dt { color: #336699; font-weight: bold }
+dd { 
+ margin-left: 1.5em; 
+ padding-bottom: 0.8em;
+}
+
+/* -- ruler -- */
+div.hr_blue { 
+  height:  3px; 
+  background:#ffffff url("/images/hr_blue.png") repeat-x; }
+div.hr_blue hr { display:none; }
+
+/* release styles */
+#release p { margin-top: 0.4em; }
+#release .md5sum { color: #761596; }
+
+
+/* ------ styles for docs|manuals|howto ------ */
+/* -- lists -- */
+ul  { 
+ margin:     0px 4px 16px 16px;
+ padding:    0px;
+ list-style: url("/images/li-blue.png"); 
+}
+ul li { 
+ margin-bottom: 10px;
+}
+ul ul	{ 
+ list-style-type:  none; 
+ list-style-image: none; 
+ margin-left:      0px; 
+}
+
+/* header / footer nav tables */
+table.nav {
+ border:     solid 1px #3366cc;
+ background: #f2f2f9;
+ background-color: #f2f2f9;
+ margin-bottom: 0.5em;
+}
+/* don't have underlined links in chunked nav menus */
+table.nav a { text-decoration: none; }
+table.nav a:hover { text-decoration: underline; }
+table.nav td { font-size: 85%; }
+
+code, tt, pre { font-size: 120%; }
+code, tt { color: #761596; }
+
+div.literallayout, pre.programlisting, pre.screen {
+ color:      #000000;
+ padding:    0.5em;
+ background: #eeeeee;
+ border:     1px solid #626262;
+ background-color: #eeeeee;
+ margin: 4px 0px 4px 0px; 
+}
+</style>
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book" lang="en">
+<div class="titlepage">
+<div>
+<div><h1 class="title">
+<a name="userman"></a>bzip2 and libbzip2, version 1.0.5</h1></div>
+<div><h2 class="subtitle">A program and library for data compression</h2></div>
+<div><div class="authorgroup"><div class="author">
+<h3 class="author">
+<span class="firstname">Julian</span> <span class="surname">Seward</span>
+</h3>
+<div class="affiliation"><span class="orgname">http://www.bzip.org<br></span></div>
+</div></div></div>
+<div><p class="releaseinfo">Version 1.0.5 of 10 December 2007</p></div>
+<div><p class="copyright">Copyright © 1996-2007 Julian Seward</p></div>
+<div><div class="legalnotice">
+<a name="id2499833"></a><p>This program, <code class="computeroutput">bzip2</code>, the
+  associated library <code class="computeroutput">libbzip2</code>, and
+  all documentation, are copyright © 1996-2007 Julian Seward.
+  All rights reserved.</p>
+<p>Redistribution and use in source and binary forms, with
+  or without modification, are permitted provided that the
+  following conditions are met:</p>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p>Redistributions of source code must retain the
+   above copyright notice, this list of conditions and the
+   following disclaimer.</p></li>
+<li style="list-style-type: disc"><p>The origin of this software must not be
+   misrepresented; you must not claim that you wrote the original
+   software.  If you use this software in a product, an
+   acknowledgment in the product documentation would be
+   appreciated but is not required.</p></li>
+<li style="list-style-type: disc"><p>Altered source versions must be plainly marked
+   as such, and must not be misrepresented as being the original
+   software.</p></li>
+<li style="list-style-type: disc"><p>The name of the author may not be used to
+   endorse or promote products derived from this software without
+   specific prior written permission.</p></li>
+</ul></div>
+<p>THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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
+  AUTHOR 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.</p>
+<p>PATENTS: To the best of my knowledge,
+ <code class="computeroutput">bzip2</code> and
+ <code class="computeroutput">libbzip2</code> do not use any patented
+ algorithms.  However, I do not have the resources to carry
+ out a patent search.  Therefore I cannot give any guarantee of
+ the above statement.
+ </p>
+</div></div>
+</div>
+<hr>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="chapter"><a href="#intro">1. Introduction</a></span></dt>
+<dt><span class="chapter"><a href="#using">2. How to use bzip2</a></span></dt>
+<dd><dl>
+<dt><span class="sect1"><a href="#name">2.1. NAME</a></span></dt>
+<dt><span class="sect1"><a href="#synopsis">2.2. SYNOPSIS</a></span></dt>
+<dt><span class="sect1"><a href="#description">2.3. DESCRIPTION</a></span></dt>
+<dt><span class="sect1"><a href="#options">2.4. OPTIONS</a></span></dt>
+<dt><span class="sect1"><a href="#memory-management">2.5. MEMORY MANAGEMENT</a></span></dt>
+<dt><span class="sect1"><a href="#recovering">2.6. RECOVERING DATA FROM DAMAGED FILES</a></span></dt>
+<dt><span class="sect1"><a href="#performance">2.7. PERFORMANCE NOTES</a></span></dt>
+<dt><span class="sect1"><a href="#caveats">2.8. CAVEATS</a></span></dt>
+<dt><span class="sect1"><a href="#author">2.9. AUTHOR</a></span></dt>
+</dl></dd>
+<dt><span class="chapter"><a href="#libprog">3. 
+Programming with <code class="computeroutput">libbzip2</code>
+</a></span></dt>
+<dd><dl>
+<dt><span class="sect1"><a href="#top-level">3.1. Top-level structure</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#ll-summary">3.1.1. Low-level summary</a></span></dt>
+<dt><span class="sect2"><a href="#hl-summary">3.1.2. High-level summary</a></span></dt>
+<dt><span class="sect2"><a href="#util-fns-summary">3.1.3. Utility functions summary</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#err-handling">3.2. Error handling</a></span></dt>
+<dt><span class="sect1"><a href="#low-level">3.3. Low-level interface</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#bzcompress-init">3.3.1. <code class="computeroutput">BZ2_bzCompressInit</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzCompress">3.3.2. <code class="computeroutput">BZ2_bzCompress</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzCompress-end">3.3.3. <code class="computeroutput">BZ2_bzCompressEnd</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzDecompress-init">3.3.4. <code class="computeroutput">BZ2_bzDecompressInit</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzDecompress">3.3.5. <code class="computeroutput">BZ2_bzDecompress</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzDecompress-end">3.3.6. <code class="computeroutput">BZ2_bzDecompressEnd</code></a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#hl-interface">3.4. High-level interface</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#bzreadopen">3.4.1. <code class="computeroutput">BZ2_bzReadOpen</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzread">3.4.2. <code class="computeroutput">BZ2_bzRead</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzreadgetunused">3.4.3. <code class="computeroutput">BZ2_bzReadGetUnused</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzreadclose">3.4.4. <code class="computeroutput">BZ2_bzReadClose</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzwriteopen">3.4.5. <code class="computeroutput">BZ2_bzWriteOpen</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzwrite">3.4.6. <code class="computeroutput">BZ2_bzWrite</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzwriteclose">3.4.7. <code class="computeroutput">BZ2_bzWriteClose</code></a></span></dt>
+<dt><span class="sect2"><a href="#embed">3.4.8. Handling embedded compressed data streams</a></span></dt>
+<dt><span class="sect2"><a href="#std-rdwr">3.4.9. Standard file-reading/writing code</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#util-fns">3.5. Utility functions</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#bzbufftobuffcompress">3.5.1. <code class="computeroutput">BZ2_bzBuffToBuffCompress</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzbufftobuffdecompress">3.5.2. <code class="computeroutput">BZ2_bzBuffToBuffDecompress</code></a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#zlib-compat">3.6. <code class="computeroutput">zlib</code> compatibility functions</a></span></dt>
+<dt><span class="sect1"><a href="#stdio-free">3.7. Using the library in a <code class="computeroutput">stdio</code>-free environment</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#stdio-bye">3.7.1. Getting rid of <code class="computeroutput">stdio</code></a></span></dt>
+<dt><span class="sect2"><a href="#critical-error">3.7.2. Critical error handling</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#win-dll">3.8. Making a Windows DLL</a></span></dt>
+</dl></dd>
+<dt><span class="chapter"><a href="#misc">4. Miscellanea</a></span></dt>
+<dd><dl>
+<dt><span class="sect1"><a href="#limits">4.1. Limitations of the compressed file format</a></span></dt>
+<dt><span class="sect1"><a href="#port-issues">4.2. Portability issues</a></span></dt>
+<dt><span class="sect1"><a href="#bugs">4.3. Reporting bugs</a></span></dt>
+<dt><span class="sect1"><a href="#package">4.4. Did you get the right package?</a></span></dt>
+<dt><span class="sect1"><a href="#reading">4.5. Further Reading</a></span></dt>
+</dl></dd>
+</dl>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="intro"></a>1. Introduction</h2></div></div></div>
+<p><code class="computeroutput">bzip2</code> compresses files
+using the Burrows-Wheeler block-sorting text compression
+algorithm, and Huffman coding.  Compression is generally
+considerably better than that achieved by more conventional
+LZ77/LZ78-based compressors, and approaches the performance of
+the PPM family of statistical compressors.</p>
+<p><code class="computeroutput">bzip2</code> is built on top of
+<code class="computeroutput">libbzip2</code>, a flexible library for
+handling compressed data in the
+<code class="computeroutput">bzip2</code> format.  This manual
+describes both how to use the program and how to work with the
+library interface.  Most of the manual is devoted to this
+library, not the program, which is good news if your interest is
+only in the program.</p>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p><a href="#using">How to use bzip2</a> describes how to use
+ <code class="computeroutput">bzip2</code>; this is the only part
+ you need to read if you just want to know how to operate the
+ program.</p></li>
+<li style="list-style-type: disc"><p><a href="#libprog">Programming with libbzip2</a> describes the
+ programming interfaces in detail, and</p></li>
+<li style="list-style-type: disc"><p><a href="#misc">Miscellanea</a> records some
+ miscellaneous notes which I thought ought to be recorded
+ somewhere.</p></li>
+</ul></div>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="using"></a>2. How to use bzip2</h2></div></div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="sect1"><a href="#name">2.1. NAME</a></span></dt>
+<dt><span class="sect1"><a href="#synopsis">2.2. SYNOPSIS</a></span></dt>
+<dt><span class="sect1"><a href="#description">2.3. DESCRIPTION</a></span></dt>
+<dt><span class="sect1"><a href="#options">2.4. OPTIONS</a></span></dt>
+<dt><span class="sect1"><a href="#memory-management">2.5. MEMORY MANAGEMENT</a></span></dt>
+<dt><span class="sect1"><a href="#recovering">2.6. RECOVERING DATA FROM DAMAGED FILES</a></span></dt>
+<dt><span class="sect1"><a href="#performance">2.7. PERFORMANCE NOTES</a></span></dt>
+<dt><span class="sect1"><a href="#caveats">2.8. CAVEATS</a></span></dt>
+<dt><span class="sect1"><a href="#author">2.9. AUTHOR</a></span></dt>
+</dl>
+</div>
+<p>This chapter contains a copy of the
+<code class="computeroutput">bzip2</code> man page, and nothing
+else.</p>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="name"></a>2.1. NAME</h2></div></div></div>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p><code class="computeroutput">bzip2</code>,
+  <code class="computeroutput">bunzip2</code> - a block-sorting file
+  compressor, v1.0.4</p></li>
+<li style="list-style-type: disc"><p><code class="computeroutput">bzcat</code> -
+   decompresses files to stdout</p></li>
+<li style="list-style-type: disc"><p><code class="computeroutput">bzip2recover</code> -
+   recovers data from damaged bzip2 files</p></li>
+</ul></div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="synopsis"></a>2.2. SYNOPSIS</h2></div></div></div>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p><code class="computeroutput">bzip2</code> [
+  -cdfkqstvzVL123456789 ] [ filenames ...  ]</p></li>
+<li style="list-style-type: disc"><p><code class="computeroutput">bunzip2</code> [
+  -fkvsVL ] [ filenames ...  ]</p></li>
+<li style="list-style-type: disc"><p><code class="computeroutput">bzcat</code> [ -s ] [
+  filenames ...  ]</p></li>
+<li style="list-style-type: disc"><p><code class="computeroutput">bzip2recover</code>
+  filename</p></li>
+</ul></div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="description"></a>2.3. DESCRIPTION</h2></div></div></div>
+<p><code class="computeroutput">bzip2</code> compresses files
+using the Burrows-Wheeler block sorting text compression
+algorithm, and Huffman coding.  Compression is generally
+considerably better than that achieved by more conventional
+LZ77/LZ78-based compressors, and approaches the performance of
+the PPM family of statistical compressors.</p>
+<p>The command-line options are deliberately very similar to
+those of GNU <code class="computeroutput">gzip</code>, but they are
+not identical.</p>
+<p><code class="computeroutput">bzip2</code> expects a list of
+file names to accompany the command-line flags.  Each file is
+replaced by a compressed version of itself, with the name
+<code class="computeroutput">original_name.bz2</code>.  Each
+compressed file has the same modification date, permissions, and,
+when possible, ownership as the corresponding original, so that
+these properties can be correctly restored at decompression time.
+File name handling is naive in the sense that there is no
+mechanism for preserving original file names, permissions,
+ownerships or dates in filesystems which lack these concepts, or
+have serious file name length restrictions, such as
+MS-DOS.</p>
+<p><code class="computeroutput">bzip2</code> and
+<code class="computeroutput">bunzip2</code> will by default not
+overwrite existing files.  If you want this to happen, specify
+the <code class="computeroutput">-f</code> flag.</p>
+<p>If no file names are specified,
+<code class="computeroutput">bzip2</code> compresses from standard
+input to standard output.  In this case,
+<code class="computeroutput">bzip2</code> will decline to write
+compressed output to a terminal, as this would be entirely
+incomprehensible and therefore pointless.</p>
+<p><code class="computeroutput">bunzip2</code> (or
+<code class="computeroutput">bzip2 -d</code>) decompresses all
+specified files.  Files which were not created by
+<code class="computeroutput">bzip2</code> will be detected and
+ignored, and a warning issued.
+<code class="computeroutput">bzip2</code> attempts to guess the
+filename for the decompressed file from that of the compressed
+file as follows:</p>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p><code class="computeroutput">filename.bz2 </code>
+  becomes
+  <code class="computeroutput">filename</code></p></li>
+<li style="list-style-type: disc"><p><code class="computeroutput">filename.bz </code>
+  becomes
+  <code class="computeroutput">filename</code></p></li>
+<li style="list-style-type: disc"><p><code class="computeroutput">filename.tbz2</code>
+  becomes
+  <code class="computeroutput">filename.tar</code></p></li>
+<li style="list-style-type: disc"><p><code class="computeroutput">filename.tbz </code>
+  becomes
+  <code class="computeroutput">filename.tar</code></p></li>
+<li style="list-style-type: disc"><p><code class="computeroutput">anyothername </code>
+  becomes
+  <code class="computeroutput">anyothername.out</code></p></li>
+</ul></div>
+<p>If the file does not end in one of the recognised endings,
+<code class="computeroutput">.bz2</code>,
+<code class="computeroutput">.bz</code>,
+<code class="computeroutput">.tbz2</code> or
+<code class="computeroutput">.tbz</code>,
+<code class="computeroutput">bzip2</code> complains that it cannot
+guess the name of the original file, and uses the original name
+with <code class="computeroutput">.out</code> appended.</p>
+<p>As with compression, supplying no filenames causes
+decompression from standard input to standard output.</p>
+<p><code class="computeroutput">bunzip2</code> will correctly
+decompress a file which is the concatenation of two or more
+compressed files.  The result is the concatenation of the
+corresponding uncompressed files.  Integrity testing
+(<code class="computeroutput">-t</code>) of concatenated compressed
+files is also supported.</p>
+<p>You can also compress or decompress files to the standard
+output by giving the <code class="computeroutput">-c</code> flag.
+Multiple files may be compressed and decompressed like this.  The
+resulting outputs are fed sequentially to stdout.  Compression of
+multiple files in this manner generates a stream containing
+multiple compressed file representations.  Such a stream can be
+decompressed correctly only by
+<code class="computeroutput">bzip2</code> version 0.9.0 or later.
+Earlier versions of <code class="computeroutput">bzip2</code> will
+stop after decompressing the first file in the stream.</p>
+<p><code class="computeroutput">bzcat</code> (or
+<code class="computeroutput">bzip2 -dc</code>) decompresses all
+specified files to the standard output.</p>
+<p><code class="computeroutput">bzip2</code> will read arguments
+from the environment variables
+<code class="computeroutput">BZIP2</code> and
+<code class="computeroutput">BZIP</code>, in that order, and will
+process them before any arguments read from the command line.
+This gives a convenient way to supply default arguments.</p>
+<p>Compression is always performed, even if the compressed
+file is slightly larger than the original.  Files of less than
+about one hundred bytes tend to get larger, since the compression
+mechanism has a constant overhead in the region of 50 bytes.
+Random data (including the output of most file compressors) is
+coded at about 8.05 bits per byte, giving an expansion of around
+0.5%.</p>
+<p>As a self-check for your protection,
+<code class="computeroutput">bzip2</code> uses 32-bit CRCs to make
+sure that the decompressed version of a file is identical to the
+original.  This guards against corruption of the compressed data,
+and against undetected bugs in
+<code class="computeroutput">bzip2</code> (hopefully very unlikely).
+The chances of data corruption going undetected is microscopic,
+about one chance in four billion for each file processed.  Be
+aware, though, that the check occurs upon decompression, so it
+can only tell you that something is wrong.  It can't help you
+recover the original uncompressed data.  You can use
+<code class="computeroutput">bzip2recover</code> to try to recover
+data from damaged files.</p>
+<p>Return values: 0 for a normal exit, 1 for environmental
+problems (file not found, invalid flags, I/O errors, etc.), 2
+to indicate a corrupt compressed file, 3 for an internal
+consistency error (eg, bug) which caused
+<code class="computeroutput">bzip2</code> to panic.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="options"></a>2.4. OPTIONS</h2></div></div></div>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="computeroutput">-c --stdout</code></span></dt>
+<dd><p>Compress or decompress to standard
+  output.</p></dd>
+<dt><span class="term"><code class="computeroutput">-d --decompress</code></span></dt>
+<dd><p>Force decompression.
+  <code class="computeroutput">bzip2</code>,
+  <code class="computeroutput">bunzip2</code> and
+  <code class="computeroutput">bzcat</code> are really the same
+  program, and the decision about what actions to take is done on
+  the basis of which name is used.  This flag overrides that
+  mechanism, and forces bzip2 to decompress.</p></dd>
+<dt><span class="term"><code class="computeroutput">-z --compress</code></span></dt>
+<dd><p>The complement to
+  <code class="computeroutput">-d</code>: forces compression,
+  regardless of the invokation name.</p></dd>
+<dt><span class="term"><code class="computeroutput">-t --test</code></span></dt>
+<dd><p>Check integrity of the specified file(s), but
+  don't decompress them.  This really performs a trial
+  decompression and throws away the result.</p></dd>
+<dt><span class="term"><code class="computeroutput">-f --force</code></span></dt>
+<dd>
+<p>Force overwrite of output files.  Normally,
+  <code class="computeroutput">bzip2</code> will not overwrite
+  existing output files.  Also forces
+  <code class="computeroutput">bzip2</code> to break hard links to
+  files, which it otherwise wouldn't do.</p>
+<p><code class="computeroutput">bzip2</code> normally declines
+  to decompress files which don't have the correct magic header
+  bytes. If forced (<code class="computeroutput">-f</code>),
+  however, it will pass such files through unmodified. This is
+  how GNU <code class="computeroutput">gzip</code> behaves.</p>
+</dd>
+<dt><span class="term"><code class="computeroutput">-k --keep</code></span></dt>
+<dd><p>Keep (don't delete) input files during
+  compression or decompression.</p></dd>
+<dt><span class="term"><code class="computeroutput">-s --small</code></span></dt>
+<dd>
+<p>Reduce memory usage, for compression,
+  decompression and testing.  Files are decompressed and tested
+  using a modified algorithm which only requires 2.5 bytes per
+  block byte.  This means any file can be decompressed in 2300k
+  of memory, albeit at about half the normal speed.</p>
+<p>During compression, <code class="computeroutput">-s</code>
+  selects a block size of 200k, which limits memory use to around
+  the same figure, at the expense of your compression ratio.  In
+  short, if your machine is low on memory (8 megabytes or less),
+  use <code class="computeroutput">-s</code> for everything.  See
+  <a href="#memory-management">MEMORY MANAGEMENT</a> below.</p>
+</dd>
+<dt><span class="term"><code class="computeroutput">-q --quiet</code></span></dt>
+<dd><p>Suppress non-essential warning messages.
+  Messages pertaining to I/O errors and other critical events
+  will not be suppressed.</p></dd>
+<dt><span class="term"><code class="computeroutput">-v --verbose</code></span></dt>
+<dd><p>Verbose mode -- show the compression ratio for
+  each file processed.  Further
+  <code class="computeroutput">-v</code>'s increase the verbosity
+  level, spewing out lots of information which is primarily of
+  interest for diagnostic purposes.</p></dd>
+<dt><span class="term"><code class="computeroutput">-L --license -V --version</code></span></dt>
+<dd><p>Display the software version, license terms and
+  conditions.</p></dd>
+<dt><span class="term"><code class="computeroutput">-1</code> (or
+ <code class="computeroutput">--fast</code>) to
+ <code class="computeroutput">-9</code> (or
+ <code class="computeroutput">-best</code>)</span></dt>
+<dd><p>Set the block size to 100 k, 200 k ...  900 k
+  when compressing.  Has no effect when decompressing.  See <a href="#memory-management">MEMORY MANAGEMENT</a> below.  The
+  <code class="computeroutput">--fast</code> and
+  <code class="computeroutput">--best</code> aliases are primarily
+  for GNU <code class="computeroutput">gzip</code> compatibility.
+  In particular, <code class="computeroutput">--fast</code> doesn't
+  make things significantly faster.  And
+  <code class="computeroutput">--best</code> merely selects the
+  default behaviour.</p></dd>
+<dt><span class="term"><code class="computeroutput">--</code></span></dt>
+<dd><p>Treats all subsequent arguments as file names,
+  even if they start with a dash.  This is so you can handle
+  files with names beginning with a dash, for example:
+  <code class="computeroutput">bzip2 --
+  -myfilename</code>.</p></dd>
+<dt>
+<span class="term"><code class="computeroutput">--repetitive-fast</code>, </span><span class="term"><code class="computeroutput">--repetitive-best</code></span>
+</dt>
+<dd><p>These flags are redundant in versions 0.9.5 and
+  above.  They provided some coarse control over the behaviour of
+  the sorting algorithm in earlier versions, which was sometimes
+  useful.  0.9.5 and above have an improved algorithm which
+  renders these flags irrelevant.</p></dd>
+</dl></div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="memory-management"></a>2.5. MEMORY MANAGEMENT</h2></div></div></div>
+<p><code class="computeroutput">bzip2</code> compresses large
+files in blocks.  The block size affects both the compression
+ratio achieved, and the amount of memory needed for compression
+and decompression.  The flags <code class="computeroutput">-1</code>
+through <code class="computeroutput">-9</code> specify the block
+size to be 100,000 bytes through 900,000 bytes (the default)
+respectively.  At decompression time, the block size used for
+compression is read from the header of the compressed file, and
+<code class="computeroutput">bunzip2</code> then allocates itself
+just enough memory to decompress the file.  Since block sizes are
+stored in compressed files, it follows that the flags
+<code class="computeroutput">-1</code> to
+<code class="computeroutput">-9</code> are irrelevant to and so
+ignored during decompression.</p>
+<p>Compression and decompression requirements, in bytes, can be
+estimated as:</p>
+<pre class="programlisting">Compression:   400k + ( 8 x block size )
+
+Decompression: 100k + ( 4 x block size ), or
+               100k + ( 2.5 x block size )</pre>
+<p>Larger block sizes give rapidly diminishing marginal
+returns.  Most of the compression comes from the first two or
+three hundred k of block size, a fact worth bearing in mind when
+using <code class="computeroutput">bzip2</code> on small machines.
+It is also important to appreciate that the decompression memory
+requirement is set at compression time by the choice of block
+size.</p>
+<p>For files compressed with the default 900k block size,
+<code class="computeroutput">bunzip2</code> will require about 3700
+kbytes to decompress.  To support decompression of any file on a
+4 megabyte machine, <code class="computeroutput">bunzip2</code> has
+an option to decompress using approximately half this amount of
+memory, about 2300 kbytes.  Decompression speed is also halved,
+so you should use this option only where necessary.  The relevant
+flag is <code class="computeroutput">-s</code>.</p>
+<p>In general, try and use the largest block size memory
+constraints allow, since that maximises the compression achieved.
+Compression and decompression speed are virtually unaffected by
+block size.</p>
+<p>Another significant point applies to files which fit in a
+single block -- that means most files you'd encounter using a
+large block size.  The amount of real memory touched is
+proportional to the size of the file, since the file is smaller
+than a block.  For example, compressing a file 20,000 bytes long
+with the flag <code class="computeroutput">-9</code> will cause the
+compressor to allocate around 7600k of memory, but only touch
+400k + 20000 * 8 = 560 kbytes of it.  Similarly, the decompressor
+will allocate 3700k but only touch 100k + 20000 * 4 = 180
+kbytes.</p>
+<p>Here is a table which summarises the maximum memory usage
+for different block sizes.  Also recorded is the total compressed
+size for 14 files of the Calgary Text Compression Corpus
+totalling 3,141,622 bytes.  This column gives some feel for how
+compression varies with block size.  These figures tend to
+understate the advantage of larger block sizes for larger files,
+since the Corpus is dominated by smaller files.</p>
+<pre class="programlisting">        Compress   Decompress   Decompress   Corpus
+Flag     usage      usage       -s usage     Size
+
+ -1      1200k       500k         350k      914704
+ -2      2000k       900k         600k      877703
+ -3      2800k      1300k         850k      860338
+ -4      3600k      1700k        1100k      846899
+ -5      4400k      2100k        1350k      845160
+ -6      5200k      2500k        1600k      838626
+ -7      6100k      2900k        1850k      834096
+ -8      6800k      3300k        2100k      828642
+ -9      7600k      3700k        2350k      828642</pre>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="recovering"></a>2.6. RECOVERING DATA FROM DAMAGED FILES</h2></div></div></div>
+<p><code class="computeroutput">bzip2</code> compresses files in
+blocks, usually 900kbytes long.  Each block is handled
+independently.  If a media or transmission error causes a
+multi-block <code class="computeroutput">.bz2</code> file to become
+damaged, it may be possible to recover data from the undamaged
+blocks in the file.</p>
+<p>The compressed representation of each block is delimited by
+a 48-bit pattern, which makes it possible to find the block
+boundaries with reasonable certainty.  Each block also carries
+its own 32-bit CRC, so damaged blocks can be distinguished from
+undamaged ones.</p>
+<p><code class="computeroutput">bzip2recover</code> is a simple
+program whose purpose is to search for blocks in
+<code class="computeroutput">.bz2</code> files, and write each block
+out into its own <code class="computeroutput">.bz2</code> file.  You
+can then use <code class="computeroutput">bzip2 -t</code> to test
+the integrity of the resulting files, and decompress those which
+are undamaged.</p>
+<p><code class="computeroutput">bzip2recover</code> takes a
+single argument, the name of the damaged file, and writes a
+number of files <code class="computeroutput">rec0001file.bz2</code>,
+<code class="computeroutput">rec0002file.bz2</code>, etc, containing
+the extracted blocks.  The output filenames are designed so that
+the use of wildcards in subsequent processing -- for example,
+<code class="computeroutput">bzip2 -dc rec*file.bz2 &gt;
+recovered_data</code> -- lists the files in the correct
+order.</p>
+<p><code class="computeroutput">bzip2recover</code> should be of
+most use dealing with large <code class="computeroutput">.bz2</code>
+files, as these will contain many blocks.  It is clearly futile
+to use it on damaged single-block files, since a damaged block
+cannot be recovered.  If you wish to minimise any potential data
+loss through media or transmission errors, you might consider
+compressing with a smaller block size.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="performance"></a>2.7. PERFORMANCE NOTES</h2></div></div></div>
+<p>The sorting phase of compression gathers together similar
+strings in the file.  Because of this, files containing very long
+runs of repeated symbols, like "aabaabaabaab ..."  (repeated
+several hundred times) may compress more slowly than normal.
+Versions 0.9.5 and above fare much better than previous versions
+in this respect.  The ratio between worst-case and average-case
+compression time is in the region of 10:1.  For previous
+versions, this figure was more like 100:1.  You can use the
+<code class="computeroutput">-vvvv</code> option to monitor progress
+in great detail, if you want.</p>
+<p>Decompression speed is unaffected by these
+phenomena.</p>
+<p><code class="computeroutput">bzip2</code> usually allocates
+several megabytes of memory to operate in, and then charges all
+over it in a fairly random fashion.  This means that performance,
+both for compressing and decompressing, is largely determined by
+the speed at which your machine can service cache misses.
+Because of this, small changes to the code to reduce the miss
+rate have been observed to give disproportionately large
+performance improvements.  I imagine
+<code class="computeroutput">bzip2</code> will perform best on
+machines with very large caches.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="caveats"></a>2.8. CAVEATS</h2></div></div></div>
+<p>I/O error messages are not as helpful as they could be.
+<code class="computeroutput">bzip2</code> tries hard to detect I/O
+errors and exit cleanly, but the details of what the problem is
+sometimes seem rather misleading.</p>
+<p>This manual page pertains to version 1.0.5 of
+<code class="computeroutput">bzip2</code>.  Compressed data created by
+this version is entirely forwards and backwards compatible with the
+previous public releases, versions 0.1pl2, 0.9.0 and 0.9.5, 1.0.0,
+1.0.1, 1.0.2 and 1.0.3, but with the following exception: 0.9.0 and
+above can correctly decompress multiple concatenated compressed files.
+0.1pl2 cannot do this; it will stop after decompressing just the first
+file in the stream.</p>
+<p><code class="computeroutput">bzip2recover</code> versions
+prior to 1.0.2 used 32-bit integers to represent bit positions in
+compressed files, so it could not handle compressed files more
+than 512 megabytes long.  Versions 1.0.2 and above use 64-bit ints
+on some platforms which support them (GNU supported targets, and
+Windows). To establish whether or not
+<code class="computeroutput">bzip2recover</code> was built with such
+a limitation, run it without arguments. In any event you can
+build yourself an unlimited version if you can recompile it with
+<code class="computeroutput">MaybeUInt64</code> set to be an
+unsigned 64-bit integer.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="author"></a>2.9. AUTHOR</h2></div></div></div>
+<p>Julian Seward,
+<code class="computeroutput">jseward@bzip.org</code></p>
+<p>The ideas embodied in
+<code class="computeroutput">bzip2</code> are due to (at least) the
+following people: Michael Burrows and David Wheeler (for the
+block sorting transformation), David Wheeler (again, for the
+Huffman coder), Peter Fenwick (for the structured coding model in
+the original <code class="computeroutput">bzip</code>, and many
+refinements), and Alistair Moffat, Radford Neal and Ian Witten
+(for the arithmetic coder in the original
+<code class="computeroutput">bzip</code>).  I am much indebted for
+their help, support and advice.  See the manual in the source
+distribution for pointers to sources of documentation.  Christian
+von Roques encouraged me to look for faster sorting algorithms,
+so as to speed up compression.  Bela Lubkin encouraged me to
+improve the worst-case compression performance.  
+Donna Robinson XMLised the documentation.
+Many people sent
+patches, helped with portability problems, lent machines, gave
+advice and were generally helpful.</p>
+</div>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="libprog"></a>3. 
+Programming with <code class="computeroutput">libbzip2</code>
+</h2></div></div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="sect1"><a href="#top-level">3.1. Top-level structure</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#ll-summary">3.1.1. Low-level summary</a></span></dt>
+<dt><span class="sect2"><a href="#hl-summary">3.1.2. High-level summary</a></span></dt>
+<dt><span class="sect2"><a href="#util-fns-summary">3.1.3. Utility functions summary</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#err-handling">3.2. Error handling</a></span></dt>
+<dt><span class="sect1"><a href="#low-level">3.3. Low-level interface</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#bzcompress-init">3.3.1. <code class="computeroutput">BZ2_bzCompressInit</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzCompress">3.3.2. <code class="computeroutput">BZ2_bzCompress</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzCompress-end">3.3.3. <code class="computeroutput">BZ2_bzCompressEnd</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzDecompress-init">3.3.4. <code class="computeroutput">BZ2_bzDecompressInit</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzDecompress">3.3.5. <code class="computeroutput">BZ2_bzDecompress</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzDecompress-end">3.3.6. <code class="computeroutput">BZ2_bzDecompressEnd</code></a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#hl-interface">3.4. High-level interface</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#bzreadopen">3.4.1. <code class="computeroutput">BZ2_bzReadOpen</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzread">3.4.2. <code class="computeroutput">BZ2_bzRead</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzreadgetunused">3.4.3. <code class="computeroutput">BZ2_bzReadGetUnused</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzreadclose">3.4.4. <code class="computeroutput">BZ2_bzReadClose</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzwriteopen">3.4.5. <code class="computeroutput">BZ2_bzWriteOpen</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzwrite">3.4.6. <code class="computeroutput">BZ2_bzWrite</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzwriteclose">3.4.7. <code class="computeroutput">BZ2_bzWriteClose</code></a></span></dt>
+<dt><span class="sect2"><a href="#embed">3.4.8. Handling embedded compressed data streams</a></span></dt>
+<dt><span class="sect2"><a href="#std-rdwr">3.4.9. Standard file-reading/writing code</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#util-fns">3.5. Utility functions</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#bzbufftobuffcompress">3.5.1. <code class="computeroutput">BZ2_bzBuffToBuffCompress</code></a></span></dt>
+<dt><span class="sect2"><a href="#bzbufftobuffdecompress">3.5.2. <code class="computeroutput">BZ2_bzBuffToBuffDecompress</code></a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#zlib-compat">3.6. <code class="computeroutput">zlib</code> compatibility functions</a></span></dt>
+<dt><span class="sect1"><a href="#stdio-free">3.7. Using the library in a <code class="computeroutput">stdio</code>-free environment</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="#stdio-bye">3.7.1. Getting rid of <code class="computeroutput">stdio</code></a></span></dt>
+<dt><span class="sect2"><a href="#critical-error">3.7.2. Critical error handling</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="#win-dll">3.8. Making a Windows DLL</a></span></dt>
+</dl>
+</div>
+<p>This chapter describes the programming interface to
+<code class="computeroutput">libbzip2</code>.</p>
+<p>For general background information, particularly about
+memory use and performance aspects, you'd be well advised to read
+<a href="#using">How to use bzip2</a> as well.</p>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="top-level"></a>3.1. Top-level structure</h2></div></div></div>
+<p><code class="computeroutput">libbzip2</code> is a flexible
+library for compressing and decompressing data in the
+<code class="computeroutput">bzip2</code> data format.  Although
+packaged as a single entity, it helps to regard the library as
+three separate parts: the low level interface, and the high level
+interface, and some utility functions.</p>
+<p>The structure of
+<code class="computeroutput">libbzip2</code>'s interfaces is similar
+to that of Jean-loup Gailly's and Mark Adler's excellent
+<code class="computeroutput">zlib</code> library.</p>
+<p>All externally visible symbols have names beginning
+<code class="computeroutput">BZ2_</code>.  This is new in version
+1.0.  The intention is to minimise pollution of the namespaces of
+library clients.</p>
+<p>To use any part of the library, you need to
+<code class="computeroutput">#include &lt;bzlib.h&gt;</code>
+into your sources.</p>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="ll-summary"></a>3.1.1. Low-level summary</h3></div></div></div>
+<p>This interface provides services for compressing and
+decompressing data in memory.  There's no provision for dealing
+with files, streams or any other I/O mechanisms, just straight
+memory-to-memory work.  In fact, this part of the library can be
+compiled without inclusion of
+<code class="computeroutput">stdio.h</code>, which may be helpful
+for embedded applications.</p>
+<p>The low-level part of the library has no global variables
+and is therefore thread-safe.</p>
+<p>Six routines make up the low level interface:
+<code class="computeroutput">BZ2_bzCompressInit</code>,
+<code class="computeroutput">BZ2_bzCompress</code>, and
+<code class="computeroutput">BZ2_bzCompressEnd</code> for
+compression, and a corresponding trio
+<code class="computeroutput">BZ2_bzDecompressInit</code>,
+<code class="computeroutput">BZ2_bzDecompress</code> and
+<code class="computeroutput">BZ2_bzDecompressEnd</code> for
+decompression.  The <code class="computeroutput">*Init</code>
+functions allocate memory for compression/decompression and do
+other initialisations, whilst the
+<code class="computeroutput">*End</code> functions close down
+operations and release memory.</p>
+<p>The real work is done by
+<code class="computeroutput">BZ2_bzCompress</code> and
+<code class="computeroutput">BZ2_bzDecompress</code>.  These
+compress and decompress data from a user-supplied input buffer to
+a user-supplied output buffer.  These buffers can be any size;
+arbitrary quantities of data are handled by making repeated calls
+to these functions.  This is a flexible mechanism allowing a
+consumer-pull style of activity, or producer-push, or a mixture
+of both.</p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="hl-summary"></a>3.1.2. High-level summary</h3></div></div></div>
+<p>This interface provides some handy wrappers around the
+low-level interface to facilitate reading and writing
+<code class="computeroutput">bzip2</code> format files
+(<code class="computeroutput">.bz2</code> files).  The routines
+provide hooks to facilitate reading files in which the
+<code class="computeroutput">bzip2</code> data stream is embedded
+within some larger-scale file structure, or where there are
+multiple <code class="computeroutput">bzip2</code> data streams
+concatenated end-to-end.</p>
+<p>For reading files,
+<code class="computeroutput">BZ2_bzReadOpen</code>,
+<code class="computeroutput">BZ2_bzRead</code>,
+<code class="computeroutput">BZ2_bzReadClose</code> and 
+<code class="computeroutput">BZ2_bzReadGetUnused</code> are
+supplied.  For writing files,
+<code class="computeroutput">BZ2_bzWriteOpen</code>,
+<code class="computeroutput">BZ2_bzWrite</code> and
+<code class="computeroutput">BZ2_bzWriteFinish</code> are
+available.</p>
+<p>As with the low-level library, no global variables are used
+so the library is per se thread-safe.  However, if I/O errors
+occur whilst reading or writing the underlying compressed files,
+you may have to consult <code class="computeroutput">errno</code> to
+determine the cause of the error.  In that case, you'd need a C
+library which correctly supports
+<code class="computeroutput">errno</code> in a multithreaded
+environment.</p>
+<p>To make the library a little simpler and more portable,
+<code class="computeroutput">BZ2_bzReadOpen</code> and
+<code class="computeroutput">BZ2_bzWriteOpen</code> require you to
+pass them file handles (<code class="computeroutput">FILE*</code>s)
+which have previously been opened for reading or writing
+respectively.  That avoids portability problems associated with
+file operations and file attributes, whilst not being much of an
+imposition on the programmer.</p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="util-fns-summary"></a>3.1.3. Utility functions summary</h3></div></div></div>
+<p>For very simple needs,
+<code class="computeroutput">BZ2_bzBuffToBuffCompress</code> and
+<code class="computeroutput">BZ2_bzBuffToBuffDecompress</code> are
+provided.  These compress data in memory from one buffer to
+another buffer in a single function call.  You should assess
+whether these functions fulfill your memory-to-memory
+compression/decompression requirements before investing effort in
+understanding the more general but more complex low-level
+interface.</p>
+<p>Yoshioka Tsuneo
+(<code class="computeroutput">tsuneo@rr.iij4u.or.jp</code>) has
+contributed some functions to give better
+<code class="computeroutput">zlib</code> compatibility.  These
+functions are <code class="computeroutput">BZ2_bzopen</code>,
+<code class="computeroutput">BZ2_bzread</code>,
+<code class="computeroutput">BZ2_bzwrite</code>,
+<code class="computeroutput">BZ2_bzflush</code>,
+<code class="computeroutput">BZ2_bzclose</code>,
+<code class="computeroutput">BZ2_bzerror</code> and
+<code class="computeroutput">BZ2_bzlibVersion</code>.  You may find
+these functions more convenient for simple file reading and
+writing, than those in the high-level interface.  These functions
+are not (yet) officially part of the library, and are minimally
+documented here.  If they break, you get to keep all the pieces.
+I hope to document them properly when time permits.</p>
+<p>Yoshioka also contributed modifications to allow the
+library to be built as a Windows DLL.</p>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="err-handling"></a>3.2. Error handling</h2></div></div></div>
+<p>The library is designed to recover cleanly in all
+situations, including the worst-case situation of decompressing
+random data.  I'm not 100% sure that it can always do this, so
+you might want to add a signal handler to catch segmentation
+violations during decompression if you are feeling especially
+paranoid.  I would be interested in hearing more about the
+robustness of the library to corrupted compressed data.</p>
+<p>Version 1.0.3 more robust in this respect than any
+previous version.  Investigations with Valgrind (a tool for detecting
+problems with memory management) indicate
+that, at least for the few files I tested, all single-bit errors
+in the decompressed data are caught properly, with no
+segmentation faults, no uses of uninitialised data, no out of
+range reads or writes, and no infinite looping in the decompressor.
+So it's certainly pretty robust, although
+I wouldn't claim it to be totally bombproof.</p>
+<p>The file <code class="computeroutput">bzlib.h</code> contains
+all definitions needed to use the library.  In particular, you
+should definitely not include
+<code class="computeroutput">bzlib_private.h</code>.</p>
+<p>In <code class="computeroutput">bzlib.h</code>, the various
+return values are defined.  The following list is not intended as
+an exhaustive description of the circumstances in which a given
+value may be returned -- those descriptions are given later.
+Rather, it is intended to convey the rough meaning of each return
+value.  The first five actions are normal and not intended to
+denote an error situation.</p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="computeroutput">BZ_OK</code></span></dt>
+<dd><p>The requested action was completed
+   successfully.</p></dd>
+<dt><span class="term"><code class="computeroutput">BZ_RUN_OK, BZ_FLUSH_OK,
+    BZ_FINISH_OK</code></span></dt>
+<dd><p>In 
+   <code class="computeroutput">BZ2_bzCompress</code>, the requested
+   flush/finish/nothing-special action was completed
+   successfully.</p></dd>
+<dt><span class="term"><code class="computeroutput">BZ_STREAM_END</code></span></dt>
+<dd><p>Compression of data was completed, or the
+   logical stream end was detected during
+   decompression.</p></dd>
+</dl></div>
+<p>The following return values indicate an error of some
+kind.</p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="computeroutput">BZ_CONFIG_ERROR</code></span></dt>
+<dd><p>Indicates that the library has been improperly
+   compiled on your platform -- a major configuration error.
+   Specifically, it means that
+   <code class="computeroutput">sizeof(char)</code>,
+   <code class="computeroutput">sizeof(short)</code> and
+   <code class="computeroutput">sizeof(int)</code> are not 1, 2 and
+   4 respectively, as they should be.  Note that the library
+   should still work properly on 64-bit platforms which follow
+   the LP64 programming model -- that is, where
+   <code class="computeroutput">sizeof(long)</code> and
+   <code class="computeroutput">sizeof(void*)</code> are 8.  Under
+   LP64, <code class="computeroutput">sizeof(int)</code> is still 4,
+   so <code class="computeroutput">libbzip2</code>, which doesn't
+   use the <code class="computeroutput">long</code> type, is
+   OK.</p></dd>
+<dt><span class="term"><code class="computeroutput">BZ_SEQUENCE_ERROR</code></span></dt>
+<dd><p>When using the library, it is important to call
+   the functions in the correct sequence and with data structures
+   (buffers etc) in the correct states.
+   <code class="computeroutput">libbzip2</code> checks as much as it
+   can to ensure this is happening, and returns
+   <code class="computeroutput">BZ_SEQUENCE_ERROR</code> if not.
+   Code which complies precisely with the function semantics, as
+   detailed below, should never receive this value; such an event
+   denotes buggy code which you should
+   investigate.</p></dd>
+<dt><span class="term"><code class="computeroutput">BZ_PARAM_ERROR</code></span></dt>
+<dd><p>Returned when a parameter to a function call is
+   out of range or otherwise manifestly incorrect.  As with
+   <code class="computeroutput">BZ_SEQUENCE_ERROR</code>, this
+   denotes a bug in the client code.  The distinction between
+   <code class="computeroutput">BZ_PARAM_ERROR</code> and
+   <code class="computeroutput">BZ_SEQUENCE_ERROR</code> is a bit
+   hazy, but still worth making.</p></dd>
+<dt><span class="term"><code class="computeroutput">BZ_MEM_ERROR</code></span></dt>
+<dd><p>Returned when a request to allocate memory
+   failed.  Note that the quantity of memory needed to decompress
+   a stream cannot be determined until the stream's header has
+   been read.  So
+   <code class="computeroutput">BZ2_bzDecompress</code> and
+   <code class="computeroutput">BZ2_bzRead</code> may return
+   <code class="computeroutput">BZ_MEM_ERROR</code> even though some
+   of the compressed data has been read.  The same is not true
+   for compression; once
+   <code class="computeroutput">BZ2_bzCompressInit</code> or
+   <code class="computeroutput">BZ2_bzWriteOpen</code> have
+   successfully completed,
+   <code class="computeroutput">BZ_MEM_ERROR</code> cannot
+   occur.</p></dd>
+<dt><span class="term"><code class="computeroutput">BZ_DATA_ERROR</code></span></dt>
+<dd><p>Returned when a data integrity error is
+   detected during decompression.  Most importantly, this means
+   when stored and computed CRCs for the data do not match.  This
+   value is also returned upon detection of any other anomaly in
+   the compressed data.</p></dd>
+<dt><span class="term"><code class="computeroutput">BZ_DATA_ERROR_MAGIC</code></span></dt>
+<dd><p>As a special case of
+   <code class="computeroutput">BZ_DATA_ERROR</code>, it is
+   sometimes useful to know when the compressed stream does not
+   start with the correct magic bytes (<code class="computeroutput">'B' 'Z'
+   'h'</code>).</p></dd>
+<dt><span class="term"><code class="computeroutput">BZ_IO_ERROR</code></span></dt>
+<dd><p>Returned by
+   <code class="computeroutput">BZ2_bzRead</code> and
+   <code class="computeroutput">BZ2_bzWrite</code> when there is an
+   error reading or writing in the compressed file, and by
+   <code class="computeroutput">BZ2_bzReadOpen</code> and
+   <code class="computeroutput">BZ2_bzWriteOpen</code> for attempts
+   to use a file for which the error indicator (viz,
+   <code class="computeroutput">ferror(f)</code>) is set.  On
+   receipt of <code class="computeroutput">BZ_IO_ERROR</code>, the
+   caller should consult <code class="computeroutput">errno</code>
+   and/or <code class="computeroutput">perror</code> to acquire
+   operating-system specific information about the
+   problem.</p></dd>
+<dt><span class="term"><code class="computeroutput">BZ_UNEXPECTED_EOF</code></span></dt>
+<dd><p>Returned by
+   <code class="computeroutput">BZ2_bzRead</code> when the
+   compressed file finishes before the logical end of stream is
+   detected.</p></dd>
+<dt><span class="term"><code class="computeroutput">BZ_OUTBUFF_FULL</code></span></dt>
+<dd><p>Returned by
+   <code class="computeroutput">BZ2_bzBuffToBuffCompress</code> and
+   <code class="computeroutput">BZ2_bzBuffToBuffDecompress</code> to
+   indicate that the output data will not fit into the output
+   buffer provided.</p></dd>
+</dl></div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="low-level"></a>3.3. Low-level interface</h2></div></div></div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bzcompress-init"></a>3.3.1. <code class="computeroutput">BZ2_bzCompressInit</code></h3></div></div></div>
+<pre class="programlisting">typedef struct {
+  char *next_in;
+  unsigned int avail_in;
+  unsigned int total_in_lo32;
+  unsigned int total_in_hi32;
+
+  char *next_out;
+  unsigned int avail_out;
+  unsigned int total_out_lo32;
+  unsigned int total_out_hi32;
+
+  void *state;
+
+  void *(*bzalloc)(void *,int,int);
+  void (*bzfree)(void *,void *);
+  void *opaque;
+} bz_stream;
+
+int BZ2_bzCompressInit ( bz_stream *strm, 
+                         int blockSize100k, 
+                         int verbosity,
+                         int workFactor );</pre>
+<p>Prepares for compression.  The
+<code class="computeroutput">bz_stream</code> structure holds all
+data pertaining to the compression activity.  A
+<code class="computeroutput">bz_stream</code> structure should be
+allocated and initialised prior to the call.  The fields of
+<code class="computeroutput">bz_stream</code> comprise the entirety
+of the user-visible data.  <code class="computeroutput">state</code>
+is a pointer to the private data structures required for
+compression.</p>
+<p>Custom memory allocators are supported, via fields
+<code class="computeroutput">bzalloc</code>,
+<code class="computeroutput">bzfree</code>, and
+<code class="computeroutput">opaque</code>.  The value
+<code class="computeroutput">opaque</code> is passed to as the first
+argument to all calls to <code class="computeroutput">bzalloc</code>
+and <code class="computeroutput">bzfree</code>, but is otherwise
+ignored by the library.  The call <code class="computeroutput">bzalloc (
+opaque, n, m )</code> is expected to return a pointer
+<code class="computeroutput">p</code> to <code class="computeroutput">n *
+m</code> bytes of memory, and <code class="computeroutput">bzfree (
+opaque, p )</code> should free that memory.</p>
+<p>If you don't want to use a custom memory allocator, set
+<code class="computeroutput">bzalloc</code>,
+<code class="computeroutput">bzfree</code> and
+<code class="computeroutput">opaque</code> to
+<code class="computeroutput">NULL</code>, and the library will then
+use the standard <code class="computeroutput">malloc</code> /
+<code class="computeroutput">free</code> routines.</p>
+<p>Before calling
+<code class="computeroutput">BZ2_bzCompressInit</code>, fields
+<code class="computeroutput">bzalloc</code>,
+<code class="computeroutput">bzfree</code> and
+<code class="computeroutput">opaque</code> should be filled
+appropriately, as just described.  Upon return, the internal
+state will have been allocated and initialised, and
+<code class="computeroutput">total_in_lo32</code>,
+<code class="computeroutput">total_in_hi32</code>,
+<code class="computeroutput">total_out_lo32</code> and
+<code class="computeroutput">total_out_hi32</code> will have been
+set to zero.  These four fields are used by the library to inform
+the caller of the total amount of data passed into and out of the
+library, respectively.  You should not try to change them.  As of
+version 1.0, 64-bit counts are maintained, even on 32-bit
+platforms, using the <code class="computeroutput">_hi32</code>
+fields to store the upper 32 bits of the count.  So, for example,
+the total amount of data in is <code class="computeroutput">(total_in_hi32
+&lt;&lt; 32) + total_in_lo32</code>.</p>
+<p>Parameter <code class="computeroutput">blockSize100k</code>
+specifies the block size to be used for compression.  It should
+be a value between 1 and 9 inclusive, and the actual block size
+used is 100000 x this figure.  9 gives the best compression but
+takes most memory.</p>
+<p>Parameter <code class="computeroutput">verbosity</code> should
+be set to a number between 0 and 4 inclusive.  0 is silent, and
+greater numbers give increasingly verbose monitoring/debugging
+output.  If the library has been compiled with
+<code class="computeroutput">-DBZ_NO_STDIO</code>, no such output
+will appear for any verbosity setting.</p>
+<p>Parameter <code class="computeroutput">workFactor</code>
+controls how the compression phase behaves when presented with
+worst case, highly repetitive, input data.  If compression runs
+into difficulties caused by repetitive data, the library switches
+from the standard sorting algorithm to a fallback algorithm.  The
+fallback is slower than the standard algorithm by perhaps a
+factor of three, but always behaves reasonably, no matter how bad
+the input.</p>
+<p>Lower values of <code class="computeroutput">workFactor</code>
+reduce the amount of effort the standard algorithm will expend
+before resorting to the fallback.  You should set this parameter
+carefully; too low, and many inputs will be handled by the
+fallback algorithm and so compress rather slowly, too high, and
+your average-to-worst case compression times can become very
+large.  The default value of 30 gives reasonable behaviour over a
+wide range of circumstances.</p>
+<p>Allowable values range from 0 to 250 inclusive.  0 is a
+special case, equivalent to using the default value of 30.</p>
+<p>Note that the compressed output generated is the same
+regardless of whether or not the fallback algorithm is
+used.</p>
+<p>Be aware also that this parameter may disappear entirely in
+future versions of the library.  In principle it should be
+possible to devise a good way to automatically choose which
+algorithm to use.  Such a mechanism would render the parameter
+obsolete.</p>
+<p>Possible return values:</p>
+<pre class="programlisting">BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if strm is NULL 
+  or blockSize &lt; 1 or blockSize &gt; 9
+  or verbosity &lt; 0 or verbosity &gt; 4
+  or workFactor &lt; 0 or workFactor &gt; 250
+BZ_MEM_ERROR 
+  if not enough memory is available
+BZ_OK 
+  otherwise</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">BZ2_bzCompress
+  if BZ_OK is returned
+  no specific action needed in case of error</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bzCompress"></a>3.3.2. <code class="computeroutput">BZ2_bzCompress</code></h3></div></div></div>
+<pre class="programlisting">int BZ2_bzCompress ( bz_stream *strm, int action );</pre>
+<p>Provides more input and/or output buffer space for the
+library.  The caller maintains input and output buffers, and
+calls <code class="computeroutput">BZ2_bzCompress</code> to transfer
+data between them.</p>
+<p>Before each call to
+<code class="computeroutput">BZ2_bzCompress</code>,
+<code class="computeroutput">next_in</code> should point at the data
+to be compressed, and <code class="computeroutput">avail_in</code>
+should indicate how many bytes the library may read.
+<code class="computeroutput">BZ2_bzCompress</code> updates
+<code class="computeroutput">next_in</code>,
+<code class="computeroutput">avail_in</code> and
+<code class="computeroutput">total_in</code> to reflect the number
+of bytes it has read.</p>
+<p>Similarly, <code class="computeroutput">next_out</code> should
+point to a buffer in which the compressed data is to be placed,
+with <code class="computeroutput">avail_out</code> indicating how
+much output space is available.
+<code class="computeroutput">BZ2_bzCompress</code> updates
+<code class="computeroutput">next_out</code>,
+<code class="computeroutput">avail_out</code> and
+<code class="computeroutput">total_out</code> to reflect the number
+of bytes output.</p>
+<p>You may provide and remove as little or as much data as you
+like on each call of
+<code class="computeroutput">BZ2_bzCompress</code>.  In the limit,
+it is acceptable to supply and remove data one byte at a time,
+although this would be terribly inefficient.  You should always
+ensure that at least one byte of output space is available at
+each call.</p>
+<p>A second purpose of
+<code class="computeroutput">BZ2_bzCompress</code> is to request a
+change of mode of the compressed stream.</p>
+<p>Conceptually, a compressed stream can be in one of four
+states: IDLE, RUNNING, FLUSHING and FINISHING.  Before
+initialisation
+(<code class="computeroutput">BZ2_bzCompressInit</code>) and after
+termination (<code class="computeroutput">BZ2_bzCompressEnd</code>),
+a stream is regarded as IDLE.</p>
+<p>Upon initialisation
+(<code class="computeroutput">BZ2_bzCompressInit</code>), the stream
+is placed in the RUNNING state.  Subsequent calls to
+<code class="computeroutput">BZ2_bzCompress</code> should pass
+<code class="computeroutput">BZ_RUN</code> as the requested action;
+other actions are illegal and will result in
+<code class="computeroutput">BZ_SEQUENCE_ERROR</code>.</p>
+<p>At some point, the calling program will have provided all
+the input data it wants to.  It will then want to finish up -- in
+effect, asking the library to process any data it might have
+buffered internally.  In this state,
+<code class="computeroutput">BZ2_bzCompress</code> will no longer
+attempt to read data from
+<code class="computeroutput">next_in</code>, but it will want to
+write data to <code class="computeroutput">next_out</code>.  Because
+the output buffer supplied by the user can be arbitrarily small,
+the finishing-up operation cannot necessarily be done with a
+single call of
+<code class="computeroutput">BZ2_bzCompress</code>.</p>
+<p>Instead, the calling program passes
+<code class="computeroutput">BZ_FINISH</code> as an action to
+<code class="computeroutput">BZ2_bzCompress</code>.  This changes
+the stream's state to FINISHING.  Any remaining input (ie,
+<code class="computeroutput">next_in[0 .. avail_in-1]</code>) is
+compressed and transferred to the output buffer.  To do this,
+<code class="computeroutput">BZ2_bzCompress</code> must be called
+repeatedly until all the output has been consumed.  At that
+point, <code class="computeroutput">BZ2_bzCompress</code> returns
+<code class="computeroutput">BZ_STREAM_END</code>, and the stream's
+state is set back to IDLE.
+<code class="computeroutput">BZ2_bzCompressEnd</code> should then be
+called.</p>
+<p>Just to make sure the calling program does not cheat, the
+library makes a note of <code class="computeroutput">avail_in</code>
+at the time of the first call to
+<code class="computeroutput">BZ2_bzCompress</code> which has
+<code class="computeroutput">BZ_FINISH</code> as an action (ie, at
+the time the program has announced its intention to not supply
+any more input).  By comparing this value with that of
+<code class="computeroutput">avail_in</code> over subsequent calls
+to <code class="computeroutput">BZ2_bzCompress</code>, the library
+can detect any attempts to slip in more data to compress.  Any
+calls for which this is detected will return
+<code class="computeroutput">BZ_SEQUENCE_ERROR</code>.  This
+indicates a programming mistake which should be corrected.</p>
+<p>Instead of asking to finish, the calling program may ask
+<code class="computeroutput">BZ2_bzCompress</code> to take all the
+remaining input, compress it and terminate the current
+(Burrows-Wheeler) compression block.  This could be useful for
+error control purposes.  The mechanism is analogous to that for
+finishing: call <code class="computeroutput">BZ2_bzCompress</code>
+with an action of <code class="computeroutput">BZ_FLUSH</code>,
+remove output data, and persist with the
+<code class="computeroutput">BZ_FLUSH</code> action until the value
+<code class="computeroutput">BZ_RUN</code> is returned.  As with
+finishing, <code class="computeroutput">BZ2_bzCompress</code>
+detects any attempt to provide more input data once the flush has
+begun.</p>
+<p>Once the flush is complete, the stream returns to the
+normal RUNNING state.</p>
+<p>This all sounds pretty complex, but isn't really.  Here's a
+table which shows which actions are allowable in each state, what
+action will be taken, what the next state is, and what the
+non-error return values are.  Note that you can't explicitly ask
+what state the stream is in, but nor do you need to -- it can be
+inferred from the values returned by
+<code class="computeroutput">BZ2_bzCompress</code>.</p>
+<pre class="programlisting">IDLE/any
+  Illegal.  IDLE state only exists after BZ2_bzCompressEnd or
+  before BZ2_bzCompressInit.
+  Return value = BZ_SEQUENCE_ERROR
+
+RUNNING/BZ_RUN
+  Compress from next_in to next_out as much as possible.
+  Next state = RUNNING
+  Return value = BZ_RUN_OK
+
+RUNNING/BZ_FLUSH
+  Remember current value of next_in. Compress from next_in
+  to next_out as much as possible, but do not accept any more input.
+  Next state = FLUSHING
+  Return value = BZ_FLUSH_OK
+
+RUNNING/BZ_FINISH
+  Remember current value of next_in. Compress from next_in
+  to next_out as much as possible, but do not accept any more input.
+  Next state = FINISHING
+  Return value = BZ_FINISH_OK
+
+FLUSHING/BZ_FLUSH
+  Compress from next_in to next_out as much as possible, 
+  but do not accept any more input.
+  If all the existing input has been used up and all compressed
+  output has been removed
+    Next state = RUNNING; Return value = BZ_RUN_OK
+  else
+    Next state = FLUSHING; Return value = BZ_FLUSH_OK
+
+FLUSHING/other     
+  Illegal.
+  Return value = BZ_SEQUENCE_ERROR
+
+FINISHING/BZ_FINISH
+  Compress from next_in to next_out as much as possible,
+  but to not accept any more input.  
+  If all the existing input has been used up and all compressed
+  output has been removed
+    Next state = IDLE; Return value = BZ_STREAM_END
+  else
+    Next state = FINISHING; Return value = BZ_FINISH_OK
+
+FINISHING/other
+  Illegal.
+  Return value = BZ_SEQUENCE_ERROR</pre>
+<p>That still looks complicated?  Well, fair enough.  The
+usual sequence of calls for compressing a load of data is:</p>
+<div class="orderedlist"><ol type="1">
+<li><p>Get started with
+  <code class="computeroutput">BZ2_bzCompressInit</code>.</p></li>
+<li><p>Shovel data in and shlurp out its compressed form
+  using zero or more calls of
+  <code class="computeroutput">BZ2_bzCompress</code> with action =
+  <code class="computeroutput">BZ_RUN</code>.</p></li>
+<li><p>Finish up. Repeatedly call
+  <code class="computeroutput">BZ2_bzCompress</code> with action =
+  <code class="computeroutput">BZ_FINISH</code>, copying out the
+  compressed output, until
+  <code class="computeroutput">BZ_STREAM_END</code> is
+  returned.</p></li>
+<li><p>Close up and go home.  Call
+  <code class="computeroutput">BZ2_bzCompressEnd</code>.</p></li>
+</ol></div>
+<p>If the data you want to compress fits into your input
+buffer all at once, you can skip the calls of
+<code class="computeroutput">BZ2_bzCompress ( ..., BZ_RUN )</code>
+and just do the <code class="computeroutput">BZ2_bzCompress ( ..., BZ_FINISH
+)</code> calls.</p>
+<p>All required memory is allocated by
+<code class="computeroutput">BZ2_bzCompressInit</code>.  The
+compression library can accept any data at all (obviously).  So
+you shouldn't get any error return values from the
+<code class="computeroutput">BZ2_bzCompress</code> calls.  If you
+do, they will be
+<code class="computeroutput">BZ_SEQUENCE_ERROR</code>, and indicate
+a bug in your programming.</p>
+<p>Trivial other possible return values:</p>
+<pre class="programlisting">BZ_PARAM_ERROR
+  if strm is NULL, or strm-&gt;s is NULL</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bzCompress-end"></a>3.3.3. <code class="computeroutput">BZ2_bzCompressEnd</code></h3></div></div></div>
+<pre class="programlisting">int BZ2_bzCompressEnd ( bz_stream *strm );</pre>
+<p>Releases all memory associated with a compression
+stream.</p>
+<p>Possible return values:</p>
+<pre class="programlisting">BZ_PARAM_ERROR  if strm is NULL or strm-&gt;s is NULL
+BZ_OK           otherwise</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bzDecompress-init"></a>3.3.4. <code class="computeroutput">BZ2_bzDecompressInit</code></h3></div></div></div>
+<pre class="programlisting">int BZ2_bzDecompressInit ( bz_stream *strm, int verbosity, int small );</pre>
+<p>Prepares for decompression.  As with
+<code class="computeroutput">BZ2_bzCompressInit</code>, a
+<code class="computeroutput">bz_stream</code> record should be
+allocated and initialised before the call.  Fields
+<code class="computeroutput">bzalloc</code>,
+<code class="computeroutput">bzfree</code> and
+<code class="computeroutput">opaque</code> should be set if a custom
+memory allocator is required, or made
+<code class="computeroutput">NULL</code> for the normal
+<code class="computeroutput">malloc</code> /
+<code class="computeroutput">free</code> routines.  Upon return, the
+internal state will have been initialised, and
+<code class="computeroutput">total_in</code> and
+<code class="computeroutput">total_out</code> will be zero.</p>
+<p>For the meaning of parameter
+<code class="computeroutput">verbosity</code>, see
+<code class="computeroutput">BZ2_bzCompressInit</code>.</p>
+<p>If <code class="computeroutput">small</code> is nonzero, the
+library will use an alternative decompression algorithm which
+uses less memory but at the cost of decompressing more slowly
+(roughly speaking, half the speed, but the maximum memory
+requirement drops to around 2300k).  See <a href="#using">How to use bzip2</a>
+for more information on memory management.</p>
+<p>Note that the amount of memory needed to decompress a
+stream cannot be determined until the stream's header has been
+read, so even if
+<code class="computeroutput">BZ2_bzDecompressInit</code> succeeds, a
+subsequent <code class="computeroutput">BZ2_bzDecompress</code>
+could fail with
+<code class="computeroutput">BZ_MEM_ERROR</code>.</p>
+<p>Possible return values:</p>
+<pre class="programlisting">BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if ( small != 0 &amp;&amp; small != 1 )
+  or (verbosity &lt;; 0 || verbosity &gt; 4)
+BZ_MEM_ERROR
+  if insufficient memory is available</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">BZ2_bzDecompress
+  if BZ_OK was returned
+  no specific action required in case of error</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bzDecompress"></a>3.3.5. <code class="computeroutput">BZ2_bzDecompress</code></h3></div></div></div>
+<pre class="programlisting">int BZ2_bzDecompress ( bz_stream *strm );</pre>
+<p>Provides more input and/out output buffer space for the
+library.  The caller maintains input and output buffers, and uses
+<code class="computeroutput">BZ2_bzDecompress</code> to transfer
+data between them.</p>
+<p>Before each call to
+<code class="computeroutput">BZ2_bzDecompress</code>,
+<code class="computeroutput">next_in</code> should point at the
+compressed data, and <code class="computeroutput">avail_in</code>
+should indicate how many bytes the library may read.
+<code class="computeroutput">BZ2_bzDecompress</code> updates
+<code class="computeroutput">next_in</code>,
+<code class="computeroutput">avail_in</code> and
+<code class="computeroutput">total_in</code> to reflect the number
+of bytes it has read.</p>
+<p>Similarly, <code class="computeroutput">next_out</code> should
+point to a buffer in which the uncompressed output is to be
+placed, with <code class="computeroutput">avail_out</code>
+indicating how much output space is available.
+<code class="computeroutput">BZ2_bzCompress</code> updates
+<code class="computeroutput">next_out</code>,
+<code class="computeroutput">avail_out</code> and
+<code class="computeroutput">total_out</code> to reflect the number
+of bytes output.</p>
+<p>You may provide and remove as little or as much data as you
+like on each call of
+<code class="computeroutput">BZ2_bzDecompress</code>.  In the limit,
+it is acceptable to supply and remove data one byte at a time,
+although this would be terribly inefficient.  You should always
+ensure that at least one byte of output space is available at
+each call.</p>
+<p>Use of <code class="computeroutput">BZ2_bzDecompress</code> is
+simpler than
+<code class="computeroutput">BZ2_bzCompress</code>.</p>
+<p>You should provide input and remove output as described
+above, and repeatedly call
+<code class="computeroutput">BZ2_bzDecompress</code> until
+<code class="computeroutput">BZ_STREAM_END</code> is returned.
+Appearance of <code class="computeroutput">BZ_STREAM_END</code>
+denotes that <code class="computeroutput">BZ2_bzDecompress</code>
+has detected the logical end of the compressed stream.
+<code class="computeroutput">BZ2_bzDecompress</code> will not
+produce <code class="computeroutput">BZ_STREAM_END</code> until all
+output data has been placed into the output buffer, so once
+<code class="computeroutput">BZ_STREAM_END</code> appears, you are
+guaranteed to have available all the decompressed output, and
+<code class="computeroutput">BZ2_bzDecompressEnd</code> can safely
+be called.</p>
+<p>If case of an error return value, you should call
+<code class="computeroutput">BZ2_bzDecompressEnd</code> to clean up
+and release memory.</p>
+<p>Possible return values:</p>
+<pre class="programlisting">BZ_PARAM_ERROR
+  if strm is NULL or strm-&gt;s is NULL
+  or strm-&gt;avail_out &lt; 1
+BZ_DATA_ERROR
+  if a data integrity error is detected in the compressed stream
+BZ_DATA_ERROR_MAGIC
+  if the compressed stream doesn't begin with the right magic bytes
+BZ_MEM_ERROR
+  if there wasn't enough memory available
+BZ_STREAM_END
+  if the logical end of the data stream was detected and all
+  output in has been consumed, eg s--&gt;avail_out &gt; 0
+BZ_OK
+  otherwise</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">BZ2_bzDecompress
+  if BZ_OK was returned
+BZ2_bzDecompressEnd
+  otherwise</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bzDecompress-end"></a>3.3.6. <code class="computeroutput">BZ2_bzDecompressEnd</code></h3></div></div></div>
+<pre class="programlisting">int BZ2_bzDecompressEnd ( bz_stream *strm );</pre>
+<p>Releases all memory associated with a decompression
+stream.</p>
+<p>Possible return values:</p>
+<pre class="programlisting">BZ_PARAM_ERROR
+  if strm is NULL or strm-&gt;s is NULL
+BZ_OK
+  otherwise</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">  None.</pre>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="hl-interface"></a>3.4. High-level interface</h2></div></div></div>
+<p>This interface provides functions for reading and writing
+<code class="computeroutput">bzip2</code> format files.  First, some
+general points.</p>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p>All of the functions take an
+  <code class="computeroutput">int*</code> first argument,
+  <code class="computeroutput">bzerror</code>.  After each call,
+  <code class="computeroutput">bzerror</code> should be consulted
+  first to determine the outcome of the call.  If
+  <code class="computeroutput">bzerror</code> is
+  <code class="computeroutput">BZ_OK</code>, the call completed
+  successfully, and only then should the return value of the
+  function (if any) be consulted.  If
+  <code class="computeroutput">bzerror</code> is
+  <code class="computeroutput">BZ_IO_ERROR</code>, there was an
+  error reading/writing the underlying compressed file, and you
+  should then consult <code class="computeroutput">errno</code> /
+  <code class="computeroutput">perror</code> to determine the cause
+  of the difficulty.  <code class="computeroutput">bzerror</code>
+  may also be set to various other values; precise details are
+  given on a per-function basis below.</p></li>
+<li style="list-style-type: disc"><p>If <code class="computeroutput">bzerror</code> indicates
+  an error (ie, anything except
+  <code class="computeroutput">BZ_OK</code> and
+  <code class="computeroutput">BZ_STREAM_END</code>), you should
+  immediately call
+  <code class="computeroutput">BZ2_bzReadClose</code> (or
+  <code class="computeroutput">BZ2_bzWriteClose</code>, depending on
+  whether you are attempting to read or to write) to free up all
+  resources associated with the stream.  Once an error has been
+  indicated, behaviour of all calls except
+  <code class="computeroutput">BZ2_bzReadClose</code>
+  (<code class="computeroutput">BZ2_bzWriteClose</code>) is
+  undefined.  The implication is that (1)
+  <code class="computeroutput">bzerror</code> should be checked
+  after each call, and (2) if
+  <code class="computeroutput">bzerror</code> indicates an error,
+  <code class="computeroutput">BZ2_bzReadClose</code>
+  (<code class="computeroutput">BZ2_bzWriteClose</code>) should then
+  be called to clean up.</p></li>
+<li style="list-style-type: disc"><p>The <code class="computeroutput">FILE*</code> arguments
+  passed to <code class="computeroutput">BZ2_bzReadOpen</code> /
+  <code class="computeroutput">BZ2_bzWriteOpen</code> should be set
+  to binary mode.  Most Unix systems will do this by default, but
+  other platforms, including Windows and Mac, will not.  If you
+  omit this, you may encounter problems when moving code to new
+  platforms.</p></li>
+<li style="list-style-type: disc"><p>Memory allocation requests are handled by
+  <code class="computeroutput">malloc</code> /
+  <code class="computeroutput">free</code>.  At present there is no
+  facility for user-defined memory allocators in the file I/O
+  functions (could easily be added, though).</p></li>
+</ul></div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bzreadopen"></a>3.4.1. <code class="computeroutput">BZ2_bzReadOpen</code></h3></div></div></div>
+<pre class="programlisting">typedef void BZFILE;
+
+BZFILE *BZ2_bzReadOpen( int *bzerror, FILE *f, 
+                        int verbosity, int small,
+                        void *unused, int nUnused );</pre>
+<p>Prepare to read compressed data from file handle
+<code class="computeroutput">f</code>.
+<code class="computeroutput">f</code> should refer to a file which
+has been opened for reading, and for which the error indicator
+(<code class="computeroutput">ferror(f)</code>)is not set.  If
+<code class="computeroutput">small</code> is 1, the library will try
+to decompress using less memory, at the expense of speed.</p>
+<p>For reasons explained below,
+<code class="computeroutput">BZ2_bzRead</code> will decompress the
+<code class="computeroutput">nUnused</code> bytes starting at
+<code class="computeroutput">unused</code>, before starting to read
+from the file <code class="computeroutput">f</code>.  At most
+<code class="computeroutput">BZ_MAX_UNUSED</code> bytes may be
+supplied like this.  If this facility is not required, you should
+pass <code class="computeroutput">NULL</code> and
+<code class="computeroutput">0</code> for
+<code class="computeroutput">unused</code> and
+n<code class="computeroutput">Unused</code> respectively.</p>
+<p>For the meaning of parameters
+<code class="computeroutput">small</code> and
+<code class="computeroutput">verbosity</code>, see
+<code class="computeroutput">BZ2_bzDecompressInit</code>.</p>
+<p>The amount of memory needed to decompress a file cannot be
+determined until the file's header has been read.  So it is
+possible that <code class="computeroutput">BZ2_bzReadOpen</code>
+returns <code class="computeroutput">BZ_OK</code> but a subsequent
+call of <code class="computeroutput">BZ2_bzRead</code> will return
+<code class="computeroutput">BZ_MEM_ERROR</code>.</p>
+<p>Possible assignments to
+<code class="computeroutput">bzerror</code>:</p>
+<pre class="programlisting">BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if f is NULL
+  or small is neither 0 nor 1
+  or ( unused == NULL &amp;&amp; nUnused != 0 )
+  or ( unused != NULL &amp;&amp; !(0 &lt;= nUnused &lt;= BZ_MAX_UNUSED) )
+BZ_IO_ERROR
+  if ferror(f) is nonzero
+BZ_MEM_ERROR
+  if insufficient memory is available
+BZ_OK
+  otherwise.</pre>
+<p>Possible return values:</p>
+<pre class="programlisting">Pointer to an abstract BZFILE
+  if bzerror is BZ_OK
+NULL
+  otherwise</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">BZ2_bzRead
+  if bzerror is BZ_OK
+BZ2_bzClose
+  otherwise</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bzread"></a>3.4.2. <code class="computeroutput">BZ2_bzRead</code></h3></div></div></div>
+<pre class="programlisting">int BZ2_bzRead ( int *bzerror, BZFILE *b, void *buf, int len );</pre>
+<p>Reads up to <code class="computeroutput">len</code>
+(uncompressed) bytes from the compressed file
+<code class="computeroutput">b</code> into the buffer
+<code class="computeroutput">buf</code>.  If the read was
+successful, <code class="computeroutput">bzerror</code> is set to
+<code class="computeroutput">BZ_OK</code> and the number of bytes
+read is returned.  If the logical end-of-stream was detected,
+<code class="computeroutput">bzerror</code> will be set to
+<code class="computeroutput">BZ_STREAM_END</code>, and the number of
+bytes read is returned.  All other
+<code class="computeroutput">bzerror</code> values denote an
+error.</p>
+<p><code class="computeroutput">BZ2_bzRead</code> will supply
+<code class="computeroutput">len</code> bytes, unless the logical
+stream end is detected or an error occurs.  Because of this, it
+is possible to detect the stream end by observing when the number
+of bytes returned is less than the number requested.
+Nevertheless, this is regarded as inadvisable; you should instead
+check <code class="computeroutput">bzerror</code> after every call
+and watch out for
+<code class="computeroutput">BZ_STREAM_END</code>.</p>
+<p>Internally, <code class="computeroutput">BZ2_bzRead</code>
+copies data from the compressed file in chunks of size
+<code class="computeroutput">BZ_MAX_UNUSED</code> bytes before
+decompressing it.  If the file contains more bytes than strictly
+needed to reach the logical end-of-stream,
+<code class="computeroutput">BZ2_bzRead</code> will almost certainly
+read some of the trailing data before signalling
+<code class="computeroutput">BZ_SEQUENCE_END</code>.  To collect the
+read but unused data once
+<code class="computeroutput">BZ_SEQUENCE_END</code> has appeared,
+call <code class="computeroutput">BZ2_bzReadGetUnused</code>
+immediately before
+<code class="computeroutput">BZ2_bzReadClose</code>.</p>
+<p>Possible assignments to
+<code class="computeroutput">bzerror</code>:</p>
+<pre class="programlisting">BZ_PARAM_ERROR
+  if b is NULL or buf is NULL or len &lt; 0
+BZ_SEQUENCE_ERROR
+  if b was opened with BZ2_bzWriteOpen
+BZ_IO_ERROR
+  if there is an error reading from the compressed file
+BZ_UNEXPECTED_EOF
+  if the compressed file ended before 
+  the logical end-of-stream was detected
+BZ_DATA_ERROR
+  if a data integrity error was detected in the compressed stream
+BZ_DATA_ERROR_MAGIC
+  if the stream does not begin with the requisite header bytes 
+  (ie, is not a bzip2 data file).  This is really 
+  a special case of BZ_DATA_ERROR.
+BZ_MEM_ERROR
+  if insufficient memory was available
+BZ_STREAM_END
+  if the logical end of stream was detected.
+BZ_OK
+  otherwise.</pre>
+<p>Possible return values:</p>
+<pre class="programlisting">number of bytes read
+  if bzerror is BZ_OK or BZ_STREAM_END
+undefined
+  otherwise</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">collect data from buf, then BZ2_bzRead or BZ2_bzReadClose
+  if bzerror is BZ_OK
+collect data from buf, then BZ2_bzReadClose or BZ2_bzReadGetUnused
+  if bzerror is BZ_SEQUENCE_END
+BZ2_bzReadClose
+  otherwise</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bzreadgetunused"></a>3.4.3. <code class="computeroutput">BZ2_bzReadGetUnused</code></h3></div></div></div>
+<pre class="programlisting">void BZ2_bzReadGetUnused( int* bzerror, BZFILE *b, 
+                          void** unused, int* nUnused );</pre>
+<p>Returns data which was read from the compressed file but
+was not needed to get to the logical end-of-stream.
+<code class="computeroutput">*unused</code> is set to the address of
+the data, and <code class="computeroutput">*nUnused</code> to the
+number of bytes.  <code class="computeroutput">*nUnused</code> will
+be set to a value between <code class="computeroutput">0</code> and
+<code class="computeroutput">BZ_MAX_UNUSED</code> inclusive.</p>
+<p>This function may only be called once
+<code class="computeroutput">BZ2_bzRead</code> has signalled
+<code class="computeroutput">BZ_STREAM_END</code> but before
+<code class="computeroutput">BZ2_bzReadClose</code>.</p>
+<p>Possible assignments to
+<code class="computeroutput">bzerror</code>:</p>
+<pre class="programlisting">BZ_PARAM_ERROR
+  if b is NULL
+  or unused is NULL or nUnused is NULL
+BZ_SEQUENCE_ERROR
+  if BZ_STREAM_END has not been signalled
+  or if b was opened with BZ2_bzWriteOpen
+BZ_OK
+  otherwise</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">BZ2_bzReadClose</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bzreadclose"></a>3.4.4. <code class="computeroutput">BZ2_bzReadClose</code></h3></div></div></div>
+<pre class="programlisting">void BZ2_bzReadClose ( int *bzerror, BZFILE *b );</pre>
+<p>Releases all memory pertaining to the compressed file
+<code class="computeroutput">b</code>.
+<code class="computeroutput">BZ2_bzReadClose</code> does not call
+<code class="computeroutput">fclose</code> on the underlying file
+handle, so you should do that yourself if appropriate.
+<code class="computeroutput">BZ2_bzReadClose</code> should be called
+to clean up after all error situations.</p>
+<p>Possible assignments to
+<code class="computeroutput">bzerror</code>:</p>
+<pre class="programlisting">BZ_SEQUENCE_ERROR
+  if b was opened with BZ2_bzOpenWrite
+BZ_OK
+  otherwise</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">none</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bzwriteopen"></a>3.4.5. <code class="computeroutput">BZ2_bzWriteOpen</code></h3></div></div></div>
+<pre class="programlisting">BZFILE *BZ2_bzWriteOpen( int *bzerror, FILE *f, 
+                         int blockSize100k, int verbosity,
+                         int workFactor );</pre>
+<p>Prepare to write compressed data to file handle
+<code class="computeroutput">f</code>.
+<code class="computeroutput">f</code> should refer to a file which
+has been opened for writing, and for which the error indicator
+(<code class="computeroutput">ferror(f)</code>)is not set.</p>
+<p>For the meaning of parameters
+<code class="computeroutput">blockSize100k</code>,
+<code class="computeroutput">verbosity</code> and
+<code class="computeroutput">workFactor</code>, see
+<code class="computeroutput">BZ2_bzCompressInit</code>.</p>
+<p>All required memory is allocated at this stage, so if the
+call completes successfully,
+<code class="computeroutput">BZ_MEM_ERROR</code> cannot be signalled
+by a subsequent call to
+<code class="computeroutput">BZ2_bzWrite</code>.</p>
+<p>Possible assignments to
+<code class="computeroutput">bzerror</code>:</p>
+<pre class="programlisting">BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if f is NULL
+  or blockSize100k &lt; 1 or blockSize100k &gt; 9
+BZ_IO_ERROR
+  if ferror(f) is nonzero
+BZ_MEM_ERROR
+  if insufficient memory is available
+BZ_OK
+  otherwise</pre>
+<p>Possible return values:</p>
+<pre class="programlisting">Pointer to an abstract BZFILE
+  if bzerror is BZ_OK
+NULL
+  otherwise</pre>
+<p>Allowable next actions:</p>
+<pre class="programlisting">BZ2_bzWrite
+  if bzerror is BZ_OK
+  (you could go directly to BZ2_bzWriteClose, but this would be pretty pointless)
+BZ2_bzWriteClose
+  otherwise</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bzwrite"></a>3.4.6. <code class="computeroutput">BZ2_bzWrite</code></h3></div></div></div>
+<pre class="programlisting">void BZ2_bzWrite ( int *bzerror, BZFILE *b, void *buf, int len );</pre>
+<p>Absorbs <code class="computeroutput">len</code> bytes from the
+buffer <code class="computeroutput">buf</code>, eventually to be
+compressed and written to the file.</p>
+<p>Possible assignments to
+<code class="computeroutput">bzerror</code>:</p>
+<pre class="programlisting">BZ_PARAM_ERROR
+  if b is NULL or buf is NULL or len &lt; 0
+BZ_SEQUENCE_ERROR
+  if b was opened with BZ2_bzReadOpen
+BZ_IO_ERROR
+  if there is an error writing the compressed file.
+BZ_OK
+  otherwise</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bzwriteclose"></a>3.4.7. <code class="computeroutput">BZ2_bzWriteClose</code></h3></div></div></div>
+<pre class="programlisting">void BZ2_bzWriteClose( int *bzerror, BZFILE* f,
+                       int abandon,
+                       unsigned int* nbytes_in,
+                       unsigned int* nbytes_out );
+
+void BZ2_bzWriteClose64( int *bzerror, BZFILE* f,
+                         int abandon,
+                         unsigned int* nbytes_in_lo32,
+                         unsigned int* nbytes_in_hi32,
+                         unsigned int* nbytes_out_lo32,
+                         unsigned int* nbytes_out_hi32 );</pre>
+<p>Compresses and flushes to the compressed file all data so
+far supplied by <code class="computeroutput">BZ2_bzWrite</code>.
+The logical end-of-stream markers are also written, so subsequent
+calls to <code class="computeroutput">BZ2_bzWrite</code> are
+illegal.  All memory associated with the compressed file
+<code class="computeroutput">b</code> is released.
+<code class="computeroutput">fflush</code> is called on the
+compressed file, but it is not
+<code class="computeroutput">fclose</code>'d.</p>
+<p>If <code class="computeroutput">BZ2_bzWriteClose</code> is
+called to clean up after an error, the only action is to release
+the memory.  The library records the error codes issued by
+previous calls, so this situation will be detected automatically.
+There is no attempt to complete the compression operation, nor to
+<code class="computeroutput">fflush</code> the compressed file.  You
+can force this behaviour to happen even in the case of no error,
+by passing a nonzero value to
+<code class="computeroutput">abandon</code>.</p>
+<p>If <code class="computeroutput">nbytes_in</code> is non-null,
+<code class="computeroutput">*nbytes_in</code> will be set to be the
+total volume of uncompressed data handled.  Similarly,
+<code class="computeroutput">nbytes_out</code> will be set to the
+total volume of compressed data written.  For compatibility with
+older versions of the library,
+<code class="computeroutput">BZ2_bzWriteClose</code> only yields the
+lower 32 bits of these counts.  Use
+<code class="computeroutput">BZ2_bzWriteClose64</code> if you want
+the full 64 bit counts.  These two functions are otherwise
+absolutely identical.</p>
+<p>Possible assignments to
+<code class="computeroutput">bzerror</code>:</p>
+<pre class="programlisting">BZ_SEQUENCE_ERROR
+  if b was opened with BZ2_bzReadOpen
+BZ_IO_ERROR
+  if there is an error writing the compressed file
+BZ_OK
+  otherwise</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="embed"></a>3.4.8. Handling embedded compressed data streams</h3></div></div></div>
+<p>The high-level library facilitates use of
+<code class="computeroutput">bzip2</code> data streams which form
+some part of a surrounding, larger data stream.</p>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p>For writing, the library takes an open file handle,
+  writes compressed data to it,
+  <code class="computeroutput">fflush</code>es it but does not
+  <code class="computeroutput">fclose</code> it.  The calling
+  application can write its own data before and after the
+  compressed data stream, using that same file handle.</p></li>
+<li style="list-style-type: disc"><p>Reading is more complex, and the facilities are not as
+  general as they could be since generality is hard to reconcile
+  with efficiency.  <code class="computeroutput">BZ2_bzRead</code>
+  reads from the compressed file in blocks of size
+  <code class="computeroutput">BZ_MAX_UNUSED</code> bytes, and in
+  doing so probably will overshoot the logical end of compressed
+  stream.  To recover this data once decompression has ended,
+  call <code class="computeroutput">BZ2_bzReadGetUnused</code> after
+  the last call of <code class="computeroutput">BZ2_bzRead</code>
+  (the one returning
+  <code class="computeroutput">BZ_STREAM_END</code>) but before
+  calling
+  <code class="computeroutput">BZ2_bzReadClose</code>.</p></li>
+</ul></div>
+<p>This mechanism makes it easy to decompress multiple
+<code class="computeroutput">bzip2</code> streams placed end-to-end.
+As the end of one stream, when
+<code class="computeroutput">BZ2_bzRead</code> returns
+<code class="computeroutput">BZ_STREAM_END</code>, call
+<code class="computeroutput">BZ2_bzReadGetUnused</code> to collect
+the unused data (copy it into your own buffer somewhere).  That
+data forms the start of the next compressed stream.  To start
+uncompressing that next stream, call
+<code class="computeroutput">BZ2_bzReadOpen</code> again, feeding in
+the unused data via the <code class="computeroutput">unused</code> /
+<code class="computeroutput">nUnused</code> parameters.  Keep doing
+this until <code class="computeroutput">BZ_STREAM_END</code> return
+coincides with the physical end of file
+(<code class="computeroutput">feof(f)</code>).  In this situation
+<code class="computeroutput">BZ2_bzReadGetUnused</code> will of
+course return no data.</p>
+<p>This should give some feel for how the high-level interface
+can be used.  If you require extra flexibility, you'll have to
+bite the bullet and get to grips with the low-level
+interface.</p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="std-rdwr"></a>3.4.9. Standard file-reading/writing code</h3></div></div></div>
+<p>Here's how you'd write data to a compressed file:</p>
+<pre class="programlisting">FILE*   f;
+BZFILE* b;
+int     nBuf;
+char    buf[ /* whatever size you like */ ];
+int     bzerror;
+int     nWritten;
+
+f = fopen ( "myfile.bz2", "w" );
+if ( !f ) {
+ /* handle error */
+}
+b = BZ2_bzWriteOpen( &amp;bzerror, f, 9 );
+if (bzerror != BZ_OK) {
+ BZ2_bzWriteClose ( b );
+ /* handle error */
+}
+
+while ( /* condition */ ) {
+ /* get data to write into buf, and set nBuf appropriately */
+ nWritten = BZ2_bzWrite ( &amp;bzerror, b, buf, nBuf );
+ if (bzerror == BZ_IO_ERROR) { 
+   BZ2_bzWriteClose ( &amp;bzerror, b );
+   /* handle error */
+ }
+}
+
+BZ2_bzWriteClose( &amp;bzerror, b );
+if (bzerror == BZ_IO_ERROR) {
+ /* handle error */
+}</pre>
+<p>And to read from a compressed file:</p>
+<pre class="programlisting">FILE*   f;
+BZFILE* b;
+int     nBuf;
+char    buf[ /* whatever size you like */ ];
+int     bzerror;
+int     nWritten;
+
+f = fopen ( "myfile.bz2", "r" );
+if ( !f ) {
+  /* handle error */
+}
+b = BZ2_bzReadOpen ( &amp;bzerror, f, 0, NULL, 0 );
+if ( bzerror != BZ_OK ) {
+  BZ2_bzReadClose ( &amp;bzerror, b );
+  /* handle error */
+}
+
+bzerror = BZ_OK;
+while ( bzerror == BZ_OK &amp;&amp; /* arbitrary other conditions */) {
+  nBuf = BZ2_bzRead ( &amp;bzerror, b, buf, /* size of buf */ );
+  if ( bzerror == BZ_OK ) {
+    /* do something with buf[0 .. nBuf-1] */
+  }
+}
+if ( bzerror != BZ_STREAM_END ) {
+   BZ2_bzReadClose ( &amp;bzerror, b );
+   /* handle error */
+} else {
+   BZ2_bzReadClose ( &amp;bzerror, b );
+}</pre>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="util-fns"></a>3.5. Utility functions</h2></div></div></div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bzbufftobuffcompress"></a>3.5.1. <code class="computeroutput">BZ2_bzBuffToBuffCompress</code></h3></div></div></div>
+<pre class="programlisting">int BZ2_bzBuffToBuffCompress( char*         dest,
+                              unsigned int* destLen,
+                              char*         source,
+                              unsigned int  sourceLen,
+                              int           blockSize100k,
+                              int           verbosity,
+                              int           workFactor );</pre>
+<p>Attempts to compress the data in <code class="computeroutput">source[0
+.. sourceLen-1]</code> into the destination buffer,
+<code class="computeroutput">dest[0 .. *destLen-1]</code>.  If the
+destination buffer is big enough,
+<code class="computeroutput">*destLen</code> is set to the size of
+the compressed data, and <code class="computeroutput">BZ_OK</code>
+is returned.  If the compressed data won't fit,
+<code class="computeroutput">*destLen</code> is unchanged, and
+<code class="computeroutput">BZ_OUTBUFF_FULL</code> is
+returned.</p>
+<p>Compression in this manner is a one-shot event, done with a
+single call to this function.  The resulting compressed data is a
+complete <code class="computeroutput">bzip2</code> format data
+stream.  There is no mechanism for making additional calls to
+provide extra input data.  If you want that kind of mechanism,
+use the low-level interface.</p>
+<p>For the meaning of parameters
+<code class="computeroutput">blockSize100k</code>,
+<code class="computeroutput">verbosity</code> and
+<code class="computeroutput">workFactor</code>, see
+<code class="computeroutput">BZ2_bzCompressInit</code>.</p>
+<p>To guarantee that the compressed data will fit in its
+buffer, allocate an output buffer of size 1% larger than the
+uncompressed data, plus six hundred extra bytes.</p>
+<p><code class="computeroutput">BZ2_bzBuffToBuffDecompress</code>
+will not write data at or beyond
+<code class="computeroutput">dest[*destLen]</code>, even in case of
+buffer overflow.</p>
+<p>Possible return values:</p>
+<pre class="programlisting">BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if dest is NULL or destLen is NULL
+  or blockSize100k &lt; 1 or blockSize100k &gt; 9
+  or verbosity &lt; 0 or verbosity &gt; 4
+  or workFactor &lt; 0 or workFactor &gt; 250
+BZ_MEM_ERROR
+  if insufficient memory is available 
+BZ_OUTBUFF_FULL
+  if the size of the compressed data exceeds *destLen
+BZ_OK
+  otherwise</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bzbufftobuffdecompress"></a>3.5.2. <code class="computeroutput">BZ2_bzBuffToBuffDecompress</code></h3></div></div></div>
+<pre class="programlisting">int BZ2_bzBuffToBuffDecompress( char*         dest,
+                                unsigned int* destLen,
+                                char*         source,
+                                unsigned int  sourceLen,
+                                int           small,
+                                int           verbosity );</pre>
+<p>Attempts to decompress the data in <code class="computeroutput">source[0
+.. sourceLen-1]</code> into the destination buffer,
+<code class="computeroutput">dest[0 .. *destLen-1]</code>.  If the
+destination buffer is big enough,
+<code class="computeroutput">*destLen</code> is set to the size of
+the uncompressed data, and <code class="computeroutput">BZ_OK</code>
+is returned.  If the compressed data won't fit,
+<code class="computeroutput">*destLen</code> is unchanged, and
+<code class="computeroutput">BZ_OUTBUFF_FULL</code> is
+returned.</p>
+<p><code class="computeroutput">source</code> is assumed to hold
+a complete <code class="computeroutput">bzip2</code> format data
+stream.
+<code class="computeroutput">BZ2_bzBuffToBuffDecompress</code> tries
+to decompress the entirety of the stream into the output
+buffer.</p>
+<p>For the meaning of parameters
+<code class="computeroutput">small</code> and
+<code class="computeroutput">verbosity</code>, see
+<code class="computeroutput">BZ2_bzDecompressInit</code>.</p>
+<p>Because the compression ratio of the compressed data cannot
+be known in advance, there is no easy way to guarantee that the
+output buffer will be big enough.  You may of course make
+arrangements in your code to record the size of the uncompressed
+data, but such a mechanism is beyond the scope of this
+library.</p>
+<p><code class="computeroutput">BZ2_bzBuffToBuffDecompress</code>
+will not write data at or beyond
+<code class="computeroutput">dest[*destLen]</code>, even in case of
+buffer overflow.</p>
+<p>Possible return values:</p>
+<pre class="programlisting">BZ_CONFIG_ERROR
+  if the library has been mis-compiled
+BZ_PARAM_ERROR
+  if dest is NULL or destLen is NULL
+  or small != 0 &amp;&amp; small != 1
+  or verbosity &lt; 0 or verbosity &gt; 4
+BZ_MEM_ERROR
+  if insufficient memory is available 
+BZ_OUTBUFF_FULL
+  if the size of the compressed data exceeds *destLen
+BZ_DATA_ERROR
+  if a data integrity error was detected in the compressed data
+BZ_DATA_ERROR_MAGIC
+  if the compressed data doesn't begin with the right magic bytes
+BZ_UNEXPECTED_EOF
+  if the compressed data ends unexpectedly
+BZ_OK
+  otherwise</pre>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="zlib-compat"></a>3.6. <code class="computeroutput">zlib</code> compatibility functions</h2></div></div></div>
+<p>Yoshioka Tsuneo has contributed some functions to give
+better <code class="computeroutput">zlib</code> compatibility.
+These functions are <code class="computeroutput">BZ2_bzopen</code>,
+<code class="computeroutput">BZ2_bzread</code>,
+<code class="computeroutput">BZ2_bzwrite</code>,
+<code class="computeroutput">BZ2_bzflush</code>,
+<code class="computeroutput">BZ2_bzclose</code>,
+<code class="computeroutput">BZ2_bzerror</code> and
+<code class="computeroutput">BZ2_bzlibVersion</code>.  These
+functions are not (yet) officially part of the library.  If they
+break, you get to keep all the pieces.  Nevertheless, I think
+they work ok.</p>
+<pre class="programlisting">typedef void BZFILE;
+
+const char * BZ2_bzlibVersion ( void );</pre>
+<p>Returns a string indicating the library version.</p>
+<pre class="programlisting">BZFILE * BZ2_bzopen  ( const char *path, const char *mode );
+BZFILE * BZ2_bzdopen ( int        fd,    const char *mode );</pre>
+<p>Opens a <code class="computeroutput">.bz2</code> file for
+reading or writing, using either its name or a pre-existing file
+descriptor.  Analogous to <code class="computeroutput">fopen</code>
+and <code class="computeroutput">fdopen</code>.</p>
+<pre class="programlisting">int BZ2_bzread  ( BZFILE* b, void* buf, int len );
+int BZ2_bzwrite ( BZFILE* b, void* buf, int len );</pre>
+<p>Reads/writes data from/to a previously opened
+<code class="computeroutput">BZFILE</code>.  Analogous to
+<code class="computeroutput">fread</code> and
+<code class="computeroutput">fwrite</code>.</p>
+<pre class="programlisting">int  BZ2_bzflush ( BZFILE* b );
+void BZ2_bzclose ( BZFILE* b );</pre>
+<p>Flushes/closes a <code class="computeroutput">BZFILE</code>.
+<code class="computeroutput">BZ2_bzflush</code> doesn't actually do
+anything.  Analogous to <code class="computeroutput">fflush</code>
+and <code class="computeroutput">fclose</code>.</p>
+<pre class="programlisting">const char * BZ2_bzerror ( BZFILE *b, int *errnum )</pre>
+<p>Returns a string describing the more recent error status of
+<code class="computeroutput">b</code>, and also sets
+<code class="computeroutput">*errnum</code> to its numerical
+value.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="stdio-free"></a>3.7. Using the library in a <code class="computeroutput">stdio</code>-free environment</h2></div></div></div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="stdio-bye"></a>3.7.1. Getting rid of <code class="computeroutput">stdio</code></h3></div></div></div>
+<p>In a deeply embedded application, you might want to use
+just the memory-to-memory functions.  You can do this
+conveniently by compiling the library with preprocessor symbol
+<code class="computeroutput">BZ_NO_STDIO</code> defined.  Doing this
+gives you a library containing only the following eight
+functions:</p>
+<p><code class="computeroutput">BZ2_bzCompressInit</code>,
+<code class="computeroutput">BZ2_bzCompress</code>,
+<code class="computeroutput">BZ2_bzCompressEnd</code>
+<code class="computeroutput">BZ2_bzDecompressInit</code>,
+<code class="computeroutput">BZ2_bzDecompress</code>,
+<code class="computeroutput">BZ2_bzDecompressEnd</code>
+<code class="computeroutput">BZ2_bzBuffToBuffCompress</code>,
+<code class="computeroutput">BZ2_bzBuffToBuffDecompress</code></p>
+<p>When compiled like this, all functions will ignore
+<code class="computeroutput">verbosity</code> settings.</p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="critical-error"></a>3.7.2. Critical error handling</h3></div></div></div>
+<p><code class="computeroutput">libbzip2</code> contains a number
+of internal assertion checks which should, needless to say, never
+be activated.  Nevertheless, if an assertion should fail,
+behaviour depends on whether or not the library was compiled with
+<code class="computeroutput">BZ_NO_STDIO</code> set.</p>
+<p>For a normal compile, an assertion failure yields the
+message:</p>
+<div class="blockquote"><blockquote class="blockquote">
+<p>bzip2/libbzip2: internal error number N.</p>
+<p>This is a bug in bzip2/libbzip2, 1.0.5 of 10 December 2007.
+Please report it to me at: jseward@bzip.org.  If this happened
+when you were using some program which uses libbzip2 as a
+component, you should also report this bug to the author(s)
+of that program.  Please make an effort to report this bug;
+timely and accurate bug reports eventually lead to higher
+quality software.  Thanks.  Julian Seward, 10 December 2007.
+</p>
+</blockquote></div>
+<p>where <code class="computeroutput">N</code> is some error code
+number.  If <code class="computeroutput">N == 1007</code>, it also
+prints some extra text advising the reader that unreliable memory
+is often associated with internal error 1007. (This is a
+frequently-observed-phenomenon with versions 1.0.0/1.0.1).</p>
+<p><code class="computeroutput">exit(3)</code> is then
+called.</p>
+<p>For a <code class="computeroutput">stdio</code>-free library,
+assertion failures result in a call to a function declared
+as:</p>
+<pre class="programlisting">extern void bz_internal_error ( int errcode );</pre>
+<p>The relevant code is passed as a parameter.  You should
+supply such a function.</p>
+<p>In either case, once an assertion failure has occurred, any
+<code class="computeroutput">bz_stream</code> records involved can
+be regarded as invalid.  You should not attempt to resume normal
+operation with them.</p>
+<p>You may, of course, change critical error handling to suit
+your needs.  As I said above, critical errors indicate bugs in
+the library and should not occur.  All "normal" error situations
+are indicated via error return codes from functions, and can be
+recovered from.</p>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="win-dll"></a>3.8. Making a Windows DLL</h2></div></div></div>
+<p>Everything related to Windows has been contributed by
+Yoshioka Tsuneo
+(<code class="computeroutput">tsuneo@rr.iij4u.or.jp</code>), so
+you should send your queries to him (but perhaps Cc: me,
+<code class="computeroutput">jseward@bzip.org</code>).</p>
+<p>My vague understanding of what to do is: using Visual C++
+5.0, open the project file
+<code class="computeroutput">libbz2.dsp</code>, and build.  That's
+all.</p>
+<p>If you can't open the project file for some reason, make a
+new one, naming these files:
+<code class="computeroutput">blocksort.c</code>,
+<code class="computeroutput">bzlib.c</code>,
+<code class="computeroutput">compress.c</code>,
+<code class="computeroutput">crctable.c</code>,
+<code class="computeroutput">decompress.c</code>,
+<code class="computeroutput">huffman.c</code>,
+<code class="computeroutput">randtable.c</code> and
+<code class="computeroutput">libbz2.def</code>.  You will also need
+to name the header files <code class="computeroutput">bzlib.h</code>
+and <code class="computeroutput">bzlib_private.h</code>.</p>
+<p>If you don't use VC++, you may need to define the
+proprocessor symbol
+<code class="computeroutput">_WIN32</code>.</p>
+<p>Finally, <code class="computeroutput">dlltest.c</code> is a
+sample program using the DLL.  It has a project file,
+<code class="computeroutput">dlltest.dsp</code>.</p>
+<p>If you just want a makefile for Visual C, have a look at
+<code class="computeroutput">makefile.msc</code>.</p>
+<p>Be aware that if you compile
+<code class="computeroutput">bzip2</code> itself on Win32, you must
+set <code class="computeroutput">BZ_UNIX</code> to 0 and
+<code class="computeroutput">BZ_LCCWIN32</code> to 1, in the file
+<code class="computeroutput">bzip2.c</code>, before compiling.
+Otherwise the resulting binary won't work correctly.</p>
+<p>I haven't tried any of this stuff myself, but it all looks
+plausible.</p>
+</div>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="misc"></a>4. Miscellanea</h2></div></div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="sect1"><a href="#limits">4.1. Limitations of the compressed file format</a></span></dt>
+<dt><span class="sect1"><a href="#port-issues">4.2. Portability issues</a></span></dt>
+<dt><span class="sect1"><a href="#bugs">4.3. Reporting bugs</a></span></dt>
+<dt><span class="sect1"><a href="#package">4.4. Did you get the right package?</a></span></dt>
+<dt><span class="sect1"><a href="#reading">4.5. Further Reading</a></span></dt>
+</dl>
+</div>
+<p>These are just some random thoughts of mine.  Your mileage
+may vary.</p>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="limits"></a>4.1. Limitations of the compressed file format</h2></div></div></div>
+<p><code class="computeroutput">bzip2-1.0.X</code>,
+<code class="computeroutput">0.9.5</code> and
+<code class="computeroutput">0.9.0</code> use exactly the same file
+format as the original version,
+<code class="computeroutput">bzip2-0.1</code>.  This decision was
+made in the interests of stability.  Creating yet another
+incompatible compressed file format would create further
+confusion and disruption for users.</p>
+<p>Nevertheless, this is not a painless decision.  Development
+work since the release of
+<code class="computeroutput">bzip2-0.1</code> in August 1997 has
+shown complexities in the file format which slow down
+decompression and, in retrospect, are unnecessary.  These
+are:</p>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p>The run-length encoder, which is the first of the
+   compression transformations, is entirely irrelevant.  The
+   original purpose was to protect the sorting algorithm from the
+   very worst case input: a string of repeated symbols.  But
+   algorithm steps Q6a and Q6b in the original Burrows-Wheeler
+   technical report (SRC-124) show how repeats can be handled
+   without difficulty in block sorting.</p></li>
+<li style="list-style-type: disc">
+<p>The randomisation mechanism doesn't really need to be
+   there.  Udi Manber and Gene Myers published a suffix array
+   construction algorithm a few years back, which can be employed
+   to sort any block, no matter how repetitive, in O(N log N)
+   time.  Subsequent work by Kunihiko Sadakane has produced a
+   derivative O(N (log N)^2) algorithm which usually outperforms
+   the Manber-Myers algorithm.</p>
+<p>I could have changed to Sadakane's algorithm, but I find
+   it to be slower than <code class="computeroutput">bzip2</code>'s
+   existing algorithm for most inputs, and the randomisation
+   mechanism protects adequately against bad cases.  I didn't
+   think it was a good tradeoff to make.  Partly this is due to
+   the fact that I was not flooded with email complaints about
+   <code class="computeroutput">bzip2-0.1</code>'s performance on
+   repetitive data, so perhaps it isn't a problem for real
+   inputs.</p>
+<p>Probably the best long-term solution, and the one I have
+   incorporated into 0.9.5 and above, is to use the existing
+   sorting algorithm initially, and fall back to a O(N (log N)^2)
+   algorithm if the standard algorithm gets into
+   difficulties.</p>
+</li>
+<li style="list-style-type: disc"><p>The compressed file format was never designed to be
+   handled by a library, and I have had to jump though some hoops
+   to produce an efficient implementation of decompression.  It's
+   a bit hairy.  Try passing
+   <code class="computeroutput">decompress.c</code> through the C
+   preprocessor and you'll see what I mean.  Much of this
+   complexity could have been avoided if the compressed size of
+   each block of data was recorded in the data stream.</p></li>
+<li style="list-style-type: disc"><p>An Adler-32 checksum, rather than a CRC32 checksum,
+   would be faster to compute.</p></li>
+</ul></div>
+<p>It would be fair to say that the
+<code class="computeroutput">bzip2</code> format was frozen before I
+properly and fully understood the performance consequences of
+doing so.</p>
+<p>Improvements which I was able to incorporate into 0.9.0,
+despite using the same file format, are:</p>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc"><p>Single array implementation of the inverse BWT.  This
+  significantly speeds up decompression, presumably because it
+  reduces the number of cache misses.</p></li>
+<li style="list-style-type: disc"><p>Faster inverse MTF transform for large MTF values.
+  The new implementation is based on the notion of sliding blocks
+  of values.</p></li>
+<li style="list-style-type: disc"><p><code class="computeroutput">bzip2-0.9.0</code> now reads
+  and writes files with <code class="computeroutput">fread</code>
+  and <code class="computeroutput">fwrite</code>; version 0.1 used
+  <code class="computeroutput">putc</code> and
+  <code class="computeroutput">getc</code>.  Duh!  Well, you live
+  and learn.</p></li>
+</ul></div>
+<p>Further ahead, it would be nice to be able to do random
+access into files.  This will require some careful design of
+compressed file formats.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="port-issues"></a>4.2. Portability issues</h2></div></div></div>
+<p>After some consideration, I have decided not to use GNU
+<code class="computeroutput">autoconf</code> to configure 0.9.5 or
+1.0.</p>
+<p><code class="computeroutput">autoconf</code>, admirable and
+wonderful though it is, mainly assists with portability problems
+between Unix-like platforms.  But
+<code class="computeroutput">bzip2</code> doesn't have much in the
+way of portability problems on Unix; most of the difficulties
+appear when porting to the Mac, or to Microsoft's operating
+systems.  <code class="computeroutput">autoconf</code> doesn't help
+in those cases, and brings in a whole load of new
+complexity.</p>
+<p>Most people should be able to compile the library and
+program under Unix straight out-of-the-box, so to speak,
+especially if you have a version of GNU C available.</p>
+<p>There are a couple of
+<code class="computeroutput">__inline__</code> directives in the
+code.  GNU C (<code class="computeroutput">gcc</code>) should be
+able to handle them.  If you're not using GNU C, your C compiler
+shouldn't see them at all.  If your compiler does, for some
+reason, see them and doesn't like them, just
+<code class="computeroutput">#define</code>
+<code class="computeroutput">__inline__</code> to be
+<code class="computeroutput">/* */</code>.  One easy way to do this
+is to compile with the flag
+<code class="computeroutput">-D__inline__=</code>, which should be
+understood by most Unix compilers.</p>
+<p>If you still have difficulties, try compiling with the
+macro <code class="computeroutput">BZ_STRICT_ANSI</code> defined.
+This should enable you to build the library in a strictly ANSI
+compliant environment.  Building the program itself like this is
+dangerous and not supported, since you remove
+<code class="computeroutput">bzip2</code>'s checks against
+compressing directories, symbolic links, devices, and other
+not-really-a-file entities.  This could cause filesystem
+corruption!</p>
+<p>One other thing: if you create a
+<code class="computeroutput">bzip2</code> binary for public distribution,
+please consider linking it statically (<code class="computeroutput">gcc
+-static</code>).  This avoids all sorts of library-version
+issues that others may encounter later on.</p>
+<p>If you build <code class="computeroutput">bzip2</code> on
+Win32, you must set <code class="computeroutput">BZ_UNIX</code> to 0
+and <code class="computeroutput">BZ_LCCWIN32</code> to 1, in the
+file <code class="computeroutput">bzip2.c</code>, before compiling.
+Otherwise the resulting binary won't work correctly.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="bugs"></a>4.3. Reporting bugs</h2></div></div></div>
+<p>I tried pretty hard to make sure
+<code class="computeroutput">bzip2</code> is bug free, both by
+design and by testing.  Hopefully you'll never need to read this
+section for real.</p>
+<p>Nevertheless, if <code class="computeroutput">bzip2</code> dies
+with a segmentation fault, a bus error or an internal assertion
+failure, it will ask you to email me a bug report.  Experience from
+years of feedback of bzip2 users indicates that almost all these
+problems can be traced to either compiler bugs or hardware
+problems.</p>
+<div class="itemizedlist"><ul type="bullet">
+<li style="list-style-type: disc">
+<p>Recompile the program with no optimisation, and
+  see if it works.  And/or try a different compiler.  I heard all
+  sorts of stories about various flavours of GNU C (and other
+  compilers) generating bad code for
+  <code class="computeroutput">bzip2</code>, and I've run across two
+  such examples myself.</p>
+<p>2.7.X versions of GNU C are known to generate bad code
+  from time to time, at high optimisation levels.  If you get
+  problems, try using the flags
+  <code class="computeroutput">-O2</code>
+  <code class="computeroutput">-fomit-frame-pointer</code>
+  <code class="computeroutput">-fno-strength-reduce</code>.  You
+  should specifically <span class="emphasis"><em>not</em></span> use
+  <code class="computeroutput">-funroll-loops</code>.</p>
+<p>You may notice that the Makefile runs six tests as part
+  of the build process.  If the program passes all of these, it's
+  a pretty good (but not 100%) indication that the compiler has
+  done its job correctly.</p>
+</li>
+<li style="list-style-type: disc">
+<p>If <code class="computeroutput">bzip2</code>
+  crashes randomly, and the crashes are not repeatable, you may
+  have a flaky memory subsystem.
+  <code class="computeroutput">bzip2</code> really hammers your
+  memory hierarchy, and if it's a bit marginal, you may get these
+  problems.  Ditto if your disk or I/O subsystem is slowly
+  failing.  Yup, this really does happen.</p>
+<p>Try using a different machine of the same type, and see
+  if you can repeat the problem.</p>
+</li>
+<li style="list-style-type: disc"><p>This isn't really a bug, but ... If
+  <code class="computeroutput">bzip2</code> tells you your file is
+  corrupted on decompression, and you obtained the file via FTP,
+  there is a possibility that you forgot to tell FTP to do a
+  binary mode transfer.  That absolutely will cause the file to
+  be non-decompressible.  You'll have to transfer it
+  again.</p></li>
+</ul></div>
+<p>If you've incorporated
+<code class="computeroutput">libbzip2</code> into your own program
+and are getting problems, please, please, please, check that the
+parameters you are passing in calls to the library, are correct,
+and in accordance with what the documentation says is allowable.
+I have tried to make the library robust against such problems,
+but I'm sure I haven't succeeded.</p>
+<p>Finally, if the above comments don't help, you'll have to
+send me a bug report.  Now, it's just amazing how many people
+will send me a bug report saying something like:</p>
+<pre class="programlisting">bzip2 crashed with segmentation fault on my machine</pre>
+<p>and absolutely nothing else.  Needless to say, a such a
+report is <span class="emphasis"><em>totally, utterly, completely and
+comprehensively 100% useless; a waste of your time, my time, and
+net bandwidth</em></span>.  With no details at all, there's no way
+I can possibly begin to figure out what the problem is.</p>
+<p>The rules of the game are: facts, facts, facts.  Don't omit
+them because "oh, they won't be relevant".  At the bare
+minimum:</p>
+<pre class="programlisting">Machine type.  Operating system version.  
+Exact version of bzip2 (do bzip2 -V).  
+Exact version of the compiler used.  
+Flags passed to the compiler.</pre>
+<p>However, the most important single thing that will help me
+is the file that you were trying to compress or decompress at the
+time the problem happened.  Without that, my ability to do
+anything more than speculate about the cause, is limited.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="package"></a>4.4. Did you get the right package?</h2></div></div></div>
+<p><code class="computeroutput">bzip2</code> is a resource hog.
+It soaks up large amounts of CPU cycles and memory.  Also, it
+gives very large latencies.  In the worst case, you can feed many
+megabytes of uncompressed data into the library before getting
+any compressed output, so this probably rules out applications
+requiring interactive behaviour.</p>
+<p>These aren't faults of my implementation, I hope, but more
+an intrinsic property of the Burrows-Wheeler transform
+(unfortunately).  Maybe this isn't what you want.</p>
+<p>If you want a compressor and/or library which is faster,
+uses less memory but gets pretty good compression, and has
+minimal latency, consider Jean-loup Gailly's and Mark Adler's
+work, <code class="computeroutput">zlib-1.2.1</code> and
+<code class="computeroutput">gzip-1.2.4</code>.  Look for them at 
+<a href="http://www.zlib.org" target="_top">http://www.zlib.org</a> and 
+<a href="http://www.gzip.org" target="_top">http://www.gzip.org</a>
+respectively.</p>
+<p>For something faster and lighter still, you might try Markus F
+X J Oberhumer's <code class="computeroutput">LZO</code> real-time
+compression/decompression library, at 
+<a href="http://www.oberhumer.com/opensource" target="_top">http://www.oberhumer.com/opensource</a>.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="reading"></a>4.5. Further Reading</h2></div></div></div>
+<p><code class="computeroutput">bzip2</code> is not research
+work, in the sense that it doesn't present any new ideas.
+Rather, it's an engineering exercise based on existing
+ideas.</p>
+<p>Four documents describe essentially all the ideas behind
+<code class="computeroutput">bzip2</code>:</p>
+<div class="literallayout"><p>Michael Burrows and D. J. Wheeler:<br>
+  "A block-sorting lossless data compression algorithm"<br>
+   10th May 1994. <br>
+   Digital SRC Research Report 124.<br>
+   ftp://ftp.digital.com/pub/DEC/SRC/research-reports/SRC-124.ps.gz<br>
+   If you have trouble finding it, try searching at the<br>
+   New Zealand Digital Library, http://www.nzdl.org.<br>
+<br>
+Daniel S. Hirschberg and Debra A. LeLewer<br>
+  "Efficient Decoding of Prefix Codes"<br>
+   Communications of the ACM, April 1990, Vol 33, Number 4.<br>
+   You might be able to get an electronic copy of this<br>
+   from the ACM Digital Library.<br>
+<br>
+David J. Wheeler<br>
+   Program bred3.c and accompanying document bred3.ps.<br>
+   This contains the idea behind the multi-table Huffman coding scheme.<br>
+   ftp://ftp.cl.cam.ac.uk/users/djw3/<br>
+<br>
+Jon L. Bentley and Robert Sedgewick<br>
+  "Fast Algorithms for Sorting and Searching Strings"<br>
+   Available from Sedgewick's web page,<br>
+   www.cs.princeton.edu/~rs<br>
+</p></div>
+<p>The following paper gives valuable additional insights into
+the algorithm, but is not immediately the basis of any code used
+in bzip2.</p>
+<div class="literallayout"><p>Peter Fenwick:<br>
+   Block Sorting Text Compression<br>
+   Proceedings of the 19th Australasian Computer Science Conference,<br>
+     Melbourne, Australia.  Jan 31 - Feb 2, 1996.<br>
+   ftp://ftp.cs.auckland.ac.nz/pub/peter-f/ACSC96paper.ps</p></div>
+<p>Kunihiko Sadakane's sorting algorithm, mentioned above, is
+available from:</p>
+<div class="literallayout"><p>http://naomi.is.s.u-tokyo.ac.jp/~sada/papers/Sada98b.ps.gz<br>
+</p></div>
+<p>The Manber-Myers suffix array construction algorithm is
+described in a paper available from:</p>
+<div class="literallayout"><p>http://www.cs.arizona.edu/people/gene/PAPERS/suffix.ps<br>
+</p></div>
+<p>Finally, the following papers document some
+investigations I made into the performance of sorting
+and decompression algorithms:</p>
+<div class="literallayout"><p>Julian Seward<br>
+   On the Performance of BWT Sorting Algorithms<br>
+   Proceedings of the IEEE Data Compression Conference 2000<br>
+     Snowbird, Utah.  28-30 March 2000.<br>
+<br>
+Julian Seward<br>
+   Space-time Tradeoffs in the Inverse B-W Transform<br>
+   Proceedings of the IEEE Data Compression Conference 2001<br>
+     Snowbird, Utah.  27-29 March 2001.<br>
+</p></div>
+</div>
+</div>
+</div></body>
+</html>
diff --git a/abc-build/src/misc/bzlib/module.make b/abc-build/src/misc/bzlib/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bzlib/module.make
@@ -0,0 +1,7 @@
+SRC +=	src/misc/bzlib/blocksort.c \
+	src/misc/bzlib/bzlib.c \
+	src/misc/bzlib/compress.c \
+	src/misc/bzlib/crctable.c \
+	src/misc/bzlib/decompress.c \
+	src/misc/bzlib/huffman.c \
+	src/misc/bzlib/randtable.c
diff --git a/abc-build/src/misc/bzlib/randtable.c b/abc-build/src/misc/bzlib/randtable.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/bzlib/randtable.c
@@ -0,0 +1,89 @@
+
+/*-------------------------------------------------------------*/
+/*--- Table for randomising repetitive blocks               ---*/
+/*---                                           randtable.c ---*/
+/*-------------------------------------------------------------*/
+
+/* ------------------------------------------------------------------
+   This file is part of bzip2/libbzip2, a program and library for
+   lossless, block-sorting data compression.
+
+   bzip2/libbzip2 version 1.0.5 of 10 December 2007
+   Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
+
+   Please read the WARNING, DISCLAIMER and PATENTS sections in the 
+   README file.
+
+   This program is released under the terms of the license contained
+   in the file LICENSE.
+   ------------------------------------------------------------------ */
+
+
+#include "bzlib_private.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*---------------------------------------------*/
+Int32 BZ2_rNums[512] = { 
+   619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 
+   985, 724, 205, 454, 863, 491, 741, 242, 949, 214, 
+   733, 859, 335, 708, 621, 574, 73, 654, 730, 472, 
+   419, 436, 278, 496, 867, 210, 399, 680, 480, 51, 
+   878, 465, 811, 169, 869, 675, 611, 697, 867, 561, 
+   862, 687, 507, 283, 482, 129, 807, 591, 733, 623, 
+   150, 238, 59, 379, 684, 877, 625, 169, 643, 105, 
+   170, 607, 520, 932, 727, 476, 693, 425, 174, 647, 
+   73, 122, 335, 530, 442, 853, 695, 249, 445, 515, 
+   909, 545, 703, 919, 874, 474, 882, 500, 594, 612, 
+   641, 801, 220, 162, 819, 984, 589, 513, 495, 799, 
+   161, 604, 958, 533, 221, 400, 386, 867, 600, 782, 
+   382, 596, 414, 171, 516, 375, 682, 485, 911, 276, 
+   98, 553, 163, 354, 666, 933, 424, 341, 533, 870, 
+   227, 730, 475, 186, 263, 647, 537, 686, 600, 224, 
+   469, 68, 770, 919, 190, 373, 294, 822, 808, 206, 
+   184, 943, 795, 384, 383, 461, 404, 758, 839, 887, 
+   715, 67, 618, 276, 204, 918, 873, 777, 604, 560, 
+   951, 160, 578, 722, 79, 804, 96, 409, 713, 940, 
+   652, 934, 970, 447, 318, 353, 859, 672, 112, 785, 
+   645, 863, 803, 350, 139, 93, 354, 99, 820, 908, 
+   609, 772, 154, 274, 580, 184, 79, 626, 630, 742, 
+   653, 282, 762, 623, 680, 81, 927, 626, 789, 125, 
+   411, 521, 938, 300, 821, 78, 343, 175, 128, 250, 
+   170, 774, 972, 275, 999, 639, 495, 78, 352, 126, 
+   857, 956, 358, 619, 580, 124, 737, 594, 701, 612, 
+   669, 112, 134, 694, 363, 992, 809, 743, 168, 974, 
+   944, 375, 748, 52, 600, 747, 642, 182, 862, 81, 
+   344, 805, 988, 739, 511, 655, 814, 334, 249, 515, 
+   897, 955, 664, 981, 649, 113, 974, 459, 893, 228, 
+   433, 837, 553, 268, 926, 240, 102, 654, 459, 51, 
+   686, 754, 806, 760, 493, 403, 415, 394, 687, 700, 
+   946, 670, 656, 610, 738, 392, 760, 799, 887, 653, 
+   978, 321, 576, 617, 626, 502, 894, 679, 243, 440, 
+   680, 879, 194, 572, 640, 724, 926, 56, 204, 700, 
+   707, 151, 457, 449, 797, 195, 791, 558, 945, 679, 
+   297, 59, 87, 824, 713, 663, 412, 693, 342, 606, 
+   134, 108, 571, 364, 631, 212, 174, 643, 304, 329, 
+   343, 97, 430, 751, 497, 314, 983, 374, 822, 928, 
+   140, 206, 73, 263, 980, 736, 876, 478, 430, 305, 
+   170, 514, 364, 692, 829, 82, 855, 953, 676, 246, 
+   369, 970, 294, 750, 807, 827, 150, 790, 288, 923, 
+   804, 378, 215, 828, 592, 281, 565, 555, 710, 82, 
+   896, 831, 547, 261, 524, 462, 293, 465, 502, 56, 
+   661, 821, 976, 991, 658, 869, 905, 758, 745, 193, 
+   768, 550, 608, 933, 378, 286, 215, 979, 792, 961, 
+   61, 688, 793, 644, 986, 403, 106, 366, 905, 644, 
+   372, 567, 466, 434, 645, 210, 389, 550, 919, 135, 
+   780, 773, 635, 389, 707, 100, 626, 958, 165, 504, 
+   920, 176, 193, 713, 857, 265, 203, 50, 668, 108, 
+   645, 990, 626, 197, 510, 357, 358, 850, 858, 364, 
+   936, 638
+};
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                       randtable.c ---*/
+/*-------------------------------------------------------------*/
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/cofactor.c b/abc-build/src/misc/espresso/cofactor.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/cofactor.c
@@ -0,0 +1,389 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+    The cofactor of a cover against a cube "c" is a cover formed by the
+    cofactor of each cube in the cover against c.  The cofactor of two
+    cubes is null if they are distance 1 or more apart.  If they are
+    distance zero apart, the cofactor is the restriction of the cube
+    to the minterms of c.
+
+    The cube list contains the following information:
+
+	T[0] = pointer to a cube identifying the variables that have
+		been cofactored against
+	T[1] = pointer to just beyond the sentinel (i.e., T[n] in this case)
+	T[2]
+	  .
+	  .  = pointers to cubes
+	  .
+	T[n-2]
+	T[n-1] = NULL pointer (sentinel)
+
+
+    Cofactoring involves repeated application of "cdist0" to check if a
+    cube of the cover intersects the cofactored cube.  This can be
+    slow, especially for the recursive descent of the espresso
+    routines.  Therefore, a special cofactor routine "scofactor" is
+    provided which assumes the cofactor is only in a single variable.
+*/
+
+
+/* cofactor -- compute the cofactor of a cover with respect to a cube */
+pcube *cofactor(T, c)
+IN pcube *T;
+IN register pcube c;
+{
+    pcube temp = cube.temp[0], *Tc_save, *Tc, *T1;
+    register pcube p;
+    int listlen;
+
+    listlen = CUBELISTSIZE(T) + 5;
+
+    /* Allocate a new list of cube pointers (max size is previous size) */
+    Tc_save = Tc = ALLOC(pcube, listlen);
+
+    /* pass on which variables have been cofactored against */
+    *Tc++ = set_or(new_cube(), T[0], set_diff(temp, cube.fullset, c));
+    Tc++;
+
+    /* Loop for each cube in the list, determine suitability, and save */
+    for(T1 = T+2; (p = *T1++) != NULL; ) {
+	if (p != c) {
+
+#ifdef NO_INLINE
+	if (! cdist0(p, c)) goto false;
+#else
+    {register int w,last;register unsigned int x;if((last=cube.inword)!=-1)
+    {x=p[last]&c[last];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w<last;w++)
+    {x=p[w]&c[w];if(~(x|x>>1)&DISJOINT)goto false;}}}{register int w,var,last;
+    register pcube mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){
+    mask=cube.var_mask[var];last=cube.last_word[var];for(w=cube.first_word[var
+    ];w<=last;w++)if(p[w]&c[w]&mask[w])goto nextvar;goto false;nextvar:;}}
+#endif
+
+	    *Tc++ = p;
+	false: ;
+	}
+    }
+
+    *Tc++ = (pcube) NULL;                       /* sentinel */
+    Tc_save[1] = (pcube) Tc;                    /* save pointer to last */
+    return Tc_save;
+}
+
+/*
+    scofactor -- compute the cofactor of a cover with respect to a cube,
+    where the cube is "active" in only a single variable.
+
+    This routine has been optimized for speed.
+*/
+
+pcube *scofactor(T, c, var)
+IN pcube *T, c;
+IN int var;
+{
+    pcube *Tc, *Tc_save;
+    register pcube p, mask = cube.temp[1], *T1;
+    register int first = cube.first_word[var], last = cube.last_word[var];
+    int listlen;
+
+    listlen = CUBELISTSIZE(T) + 5;
+
+    /* Allocate a new list of cube pointers (max size is previous size) */
+    Tc_save = Tc = ALLOC(pcube, listlen);
+
+    /* pass on which variables have been cofactored against */
+    *Tc++ = set_or(new_cube(), T[0], set_diff(mask, cube.fullset, c));
+    Tc++;
+
+    /* Setup for the quick distance check */
+    (void) set_and(mask, cube.var_mask[var], c);
+
+    /* Loop for each cube in the list, determine suitability, and save */
+    for(T1 = T+2; (p = *T1++) != NULL; )
+	if (p != c) {
+	    register int i = first;
+	    do
+		if (p[i] & mask[i]) {
+		    *Tc++ = p;
+		    break;
+		}
+	    while (++i <= last);
+	}
+
+    *Tc++ = (pcube) NULL;                       /* sentinel */
+    Tc_save[1] = (pcube) Tc;                    /* save pointer to last */
+    return Tc_save;
+}
+
+void massive_count(T)
+IN pcube *T;
+{
+    int *count = cdata.part_zeros;
+    pcube *T1;
+
+    /* Clear the column counts (count of # zeros in each column) */
+ {  register int i;
+    for(i = cube.size - 1; i >= 0; i--)
+	count[i] = 0;
+ }
+
+    /* Count the number of zeros in each column */
+ {  register int i, *cnt;
+    register unsigned int val;
+    register pcube p, cof = T[0], full = cube.fullset;
+    for(T1 = T+2; (p = *T1++) != NULL; )
+	for(i = LOOP(p); i > 0; i--)
+	    if ((val = full[i] & ~ (p[i] | cof[i]))) {
+		cnt = count + ((i-1) << LOGBPI);
+#if BPI == 32
+	    if (val & 0xFF000000) {
+		if (val & 0x80000000) cnt[31]++;
+		if (val & 0x40000000) cnt[30]++;
+		if (val & 0x20000000) cnt[29]++;
+		if (val & 0x10000000) cnt[28]++;
+		if (val & 0x08000000) cnt[27]++;
+		if (val & 0x04000000) cnt[26]++;
+		if (val & 0x02000000) cnt[25]++;
+		if (val & 0x01000000) cnt[24]++;
+	    }
+	    if (val & 0x00FF0000) {
+		if (val & 0x00800000) cnt[23]++;
+		if (val & 0x00400000) cnt[22]++;
+		if (val & 0x00200000) cnt[21]++;
+		if (val & 0x00100000) cnt[20]++;
+		if (val & 0x00080000) cnt[19]++;
+		if (val & 0x00040000) cnt[18]++;
+		if (val & 0x00020000) cnt[17]++;
+		if (val & 0x00010000) cnt[16]++;
+	    }
+#endif
+	    if (val & 0xFF00) {
+		if (val & 0x8000) cnt[15]++;
+		if (val & 0x4000) cnt[14]++;
+		if (val & 0x2000) cnt[13]++;
+		if (val & 0x1000) cnt[12]++;
+		if (val & 0x0800) cnt[11]++;
+		if (val & 0x0400) cnt[10]++;
+		if (val & 0x0200) cnt[ 9]++;
+		if (val & 0x0100) cnt[ 8]++;
+	    }
+	    if (val & 0x00FF) {
+		if (val & 0x0080) cnt[ 7]++;
+		if (val & 0x0040) cnt[ 6]++;
+		if (val & 0x0020) cnt[ 5]++;
+		if (val & 0x0010) cnt[ 4]++;
+		if (val & 0x0008) cnt[ 3]++;
+		if (val & 0x0004) cnt[ 2]++;
+		if (val & 0x0002) cnt[ 1]++;
+		if (val & 0x0001) cnt[ 0]++;
+	    }
+	}
+ }
+
+    /*
+     * Perform counts for each variable:
+     *    cdata.var_zeros[var] = number of zeros in the variable
+     *    cdata.parts_active[var] = number of active parts for each variable
+     *    cdata.vars_active = number of variables which are active
+     *    cdata.vars_unate = number of variables which are active and unate
+     *
+     *    best -- the variable which is best for splitting based on:
+     *    mostactive -- most # active parts in any variable
+     *    mostzero -- most # zeros in any variable
+     *    mostbalanced -- minimum over the maximum # zeros / part / variable
+     */
+
+ {  register int var, i, lastbit, active, maxactive;
+    int best = -1, mostactive = 0, mostzero = 0, mostbalanced = 32000;
+    cdata.vars_unate = cdata.vars_active = 0;
+
+    for(var = 0; var < cube.num_vars; var++) {
+	if (var < cube.num_binary_vars) { /* special hack for binary vars */
+	    i = count[var*2];
+	    lastbit = count[var*2 + 1];
+	    active = (i > 0) + (lastbit > 0);
+	    cdata.var_zeros[var] = i + lastbit;
+	    maxactive = MAX(i, lastbit);
+	} else {
+	    maxactive = active = cdata.var_zeros[var] = 0;
+	    lastbit = cube.last_part[var];
+	    for(i = cube.first_part[var]; i <= lastbit; i++) {
+		cdata.var_zeros[var] += count[i];
+		active += (count[i] > 0);
+		if (active > maxactive) maxactive = active;
+	    }
+	}
+
+	/* first priority is to maximize the number of active parts */
+	/* for binary case, this will usually select the output first */
+	if (active > mostactive)
+	    best = var, mostactive = active, mostzero = cdata.var_zeros[best],
+	    mostbalanced = maxactive;
+	else if (active == mostactive)
+	{
+	    /* secondary condition is to maximize the number zeros */
+	    /* for binary variables, this is the same as minimum # of 2's */
+	    if (cdata.var_zeros[var] > mostzero)
+		best = var, mostzero = cdata.var_zeros[best],
+		mostbalanced = maxactive;
+	    else if (cdata.var_zeros[var] == mostzero)
+		/* third condition is to pick a balanced variable */
+		/* for binary vars, this means roughly equal # 0's and 1's */
+		if (maxactive < mostbalanced)
+		    best = var, mostbalanced = maxactive;
+	}
+
+	cdata.parts_active[var] = active;
+	cdata.is_unate[var] = (active == 1);
+	cdata.vars_active += (active > 0);
+	cdata.vars_unate += (active == 1);
+    }
+    cdata.best = best;
+ }
+}
+
+int binate_split_select(T, cleft, cright, debug_flag)
+IN pcube *T;
+IN register pcube cleft, cright;
+IN int debug_flag;
+{
+    int best = cdata.best;
+    register int i, lastbit = cube.last_part[best], halfbit = 0;
+    register pcube cof=T[0];
+
+    /* Create the cubes to cofactor against */
+    (void) set_diff(cleft, cube.fullset, cube.var_mask[best]);
+    (void) set_diff(cright, cube.fullset, cube.var_mask[best]);
+    for(i = cube.first_part[best]; i <= lastbit; i++)
+	if (! is_in_set(cof,i))
+	    halfbit++;
+    for(i = cube.first_part[best], halfbit = halfbit/2; halfbit > 0; i++)
+	if (! is_in_set(cof,i))
+	    halfbit--, set_insert(cleft, i);
+    for(; i <= lastbit; i++)
+	if (! is_in_set(cof,i))
+	    set_insert(cright, i);
+
+    if (debug & debug_flag) {
+	(void) printf("BINATE_SPLIT_SELECT: split against %d\n", best);
+	if (verbose_debug)
+	    (void) printf("cl=%s\ncr=%s\n", pc1(cleft), pc2(cright));
+    }
+    return best;
+}
+
+
+pcube *cube1list(A)
+pcover A;
+{
+    register pcube last, p, *plist, *list;
+
+    list = plist = ALLOC(pcube, A->count + 3);
+    *plist++ = new_cube();
+    plist++;
+    foreach_set(A, last, p) {
+	*plist++ = p;
+    }
+    *plist++ = NULL;                    /* sentinel */
+    list[1] = (pcube) plist;
+    return list;
+}
+
+
+pcube *cube2list(A, B)
+pcover A, B;
+{
+    register pcube last, p, *plist, *list;
+
+    list = plist = ALLOC(pcube, A->count + B->count + 3);
+    *plist++ = new_cube();
+    plist++;
+    foreach_set(A, last, p) {
+	*plist++ = p;
+    }
+    foreach_set(B, last, p) {
+	*plist++ = p;
+    }
+    *plist++ = NULL;
+    list[1] = (pcube) plist;
+    return list;
+}
+
+
+pcube *cube3list(A, B, C)
+pcover A, B, C;
+{
+    register pcube last, p, *plist, *list;
+
+    plist = ALLOC(pcube, A->count + B->count + C->count + 3);
+    list = plist;
+    *plist++ = new_cube();
+    plist++;
+    foreach_set(A, last, p) {
+	*plist++ = p;
+    }
+    foreach_set(B, last, p) {
+	*plist++ = p;
+    }
+    foreach_set(C, last, p) {
+	*plist++ = p;
+    }
+    *plist++ = NULL;
+    list[1] = (pcube) plist;
+    return list;
+}
+
+
+pcover cubeunlist(A1)
+pcube *A1;
+{
+    register int i;
+    register pcube p, pdest, cof = A1[0];
+    register pcover A;
+
+    A = new_cover(CUBELISTSIZE(A1));
+    for(i = 2; (p = A1[i]) != NULL; i++) {
+	pdest = GETSET(A, i-2);
+	INLINEset_or(pdest, p, cof);
+    }
+    A->count = CUBELISTSIZE(A1);
+    return A;
+}
+
+void simplify_cubelist(T)
+pcube *T;
+{
+    register pcube *Tdest;
+    register int i, ncubes;
+
+    (void) set_copy(cube.temp[0], T[0]);		/* retrieve cofactor */
+
+    ncubes = CUBELISTSIZE(T);
+    qsort((char *) (T+2), ncubes, sizeof(pset), (int (*)()) d1_order);
+
+    Tdest = T+2;
+    /*   *Tdest++ = T[2];   */
+    for(i = 3; i < ncubes; i++) {
+	if (d1_order(&T[i-1], &T[i]) != 0) {
+	    *Tdest++ = T[i];
+	}
+    }
+
+    *Tdest++ = NULL;				/* sentinel */
+    Tdest[1] = (pcube) Tdest;			/* save pointer to last */
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/cols.c b/abc-build/src/misc/espresso/cols.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/cols.c
@@ -0,0 +1,319 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+#include "sparse_int.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*
+ *  allocate a new col vector 
+ */
+sm_col *
+sm_col_alloc()
+{
+    register sm_col *pcol;
+
+#ifdef FAST_AND_LOOSE
+    if (sm_col_freelist == NIL(sm_col)) {
+	pcol = ALLOC(sm_col, 1);
+    } else {
+	pcol = sm_col_freelist;
+	sm_col_freelist = pcol->next_col;
+    }
+#else
+    pcol = ALLOC(sm_col, 1);
+#endif
+
+    pcol->col_num = 0;
+    pcol->length = 0;
+    pcol->first_row = pcol->last_row = NIL(sm_element);
+    pcol->next_col = pcol->prev_col = NIL(sm_col);
+    pcol->flag = 0;
+    pcol->user_word = NIL(char);		/* for our user ... */
+    return pcol;
+}
+
+
+/*
+ *  free a col vector -- for FAST_AND_LOOSE, this is real cheap for cols;
+ *  however, freeing a rowumn must still walk down the rowumn discarding
+ *  the elements one-by-one; that is the only use for the extra '-DCOLS'
+ *  compile flag ...
+ */
+void
+sm_col_free(pcol)
+register sm_col *pcol;
+{
+#if defined(FAST_AND_LOOSE) && ! defined(COLS)
+    if (pcol->first_row != NIL(sm_element)) {
+	/* Add the linked list of col items to the free list */
+	pcol->last_row->next_row = sm_element_freelist;
+	sm_element_freelist = pcol->first_row;
+    }
+
+    /* Add the col to the free list of cols */
+    pcol->next_col = sm_col_freelist;
+    sm_col_freelist = pcol;
+#else
+    register sm_element *p, *pnext;
+
+    for(p = pcol->first_row; p != 0; p = pnext) {
+	pnext = p->next_row;
+	sm_element_free(p);
+    }
+    FREE(pcol);
+#endif
+}
+
+
+/*
+ *  duplicate an existing col
+ */
+sm_col *
+sm_col_dup(pcol)
+register sm_col *pcol;
+{
+    register sm_col *pnew;
+    register sm_element *p;
+
+    pnew = sm_col_alloc();
+    for(p = pcol->first_row; p != 0; p = p->next_row) {
+	(void) sm_col_insert(pnew, p->row_num);
+    }
+    return pnew;
+}
+
+
+/*
+ *  insert an element into a col vector 
+ */
+sm_element *
+sm_col_insert(pcol, row)
+register sm_col *pcol;
+register int row;
+{
+    register sm_element *test, *element;
+
+    /* get a new item, save its address */
+    sm_element_alloc(element);
+    test = element;
+    sorted_insert(sm_element, pcol->first_row, pcol->last_row, pcol->length, 
+		    next_row, prev_row, row_num, row, test);
+
+    /* if item was not used, free it */
+    if (element != test) {
+	sm_element_free(element);
+    }
+
+    /* either way, return the current new value */
+    return test;
+}
+
+
+/*
+ *  remove an element from a col vector 
+ */
+void
+sm_col_remove(pcol, row)
+register sm_col *pcol;
+register int row;
+{
+    register sm_element *p;
+
+    for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row)
+	;
+    if (p != 0 && p->row_num == row) {
+	dll_unlink(p, pcol->first_row, pcol->last_row, 
+			    next_row, prev_row, pcol->length);
+	sm_element_free(p);
+    }
+}
+
+
+/*
+ *  find an element (if it is in the col vector)
+ */
+sm_element *
+sm_col_find(pcol, row)
+sm_col *pcol;
+int row;
+{
+    register sm_element *p;
+
+    for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row)
+	;
+    if (p != 0 && p->row_num == row) {
+	return p;
+    } else {
+	return NIL(sm_element);
+    }
+}
+
+/*
+ *  return 1 if col p2 contains col p1; 0 otherwise
+ */
+int 
+sm_col_contains(p1, p2)
+sm_col *p1, *p2;
+{
+    register sm_element *q1, *q2;
+
+    q1 = p1->first_row;
+    q2 = p2->first_row;
+    while (q1 != 0) {
+	if (q2 == 0 || q1->row_num < q2->row_num) {
+	    return 0;
+	} else if (q1->row_num == q2->row_num) {
+	    q1 = q1->next_row;
+	    q2 = q2->next_row;
+	} else {
+	    q2 = q2->next_row;
+	}
+    }
+    return 1;
+}
+
+
+/*
+ *  return 1 if col p1 and col p2 share an element in common
+ */
+int 
+sm_col_intersects(p1, p2)
+sm_col *p1, *p2;
+{
+    register sm_element *q1, *q2;
+
+    q1 = p1->first_row;
+    q2 = p2->first_row;
+    if (q1 == 0 || q2 == 0) return 0;
+    for(;;) {
+	if (q1->row_num < q2->row_num) {
+	    if ((q1 = q1->next_row) == 0) {
+		return 0;
+	    }
+	} else if (q1->row_num > q2->row_num) {
+	    if ((q2 = q2->next_row) == 0) {
+		return 0;
+	    }
+	} else {
+	    return 1;
+	}
+    }
+}
+
+
+/*
+ *  compare two cols, lexical ordering
+ */
+int 
+sm_col_compare(p1, p2)
+sm_col *p1, *p2;
+{
+    register sm_element *q1, *q2;
+
+    q1 = p1->first_row;
+    q2 = p2->first_row;
+    while(q1 != 0 && q2 != 0) {
+	if (q1->row_num != q2->row_num) {
+	    return q1->row_num - q2->row_num;
+	}
+	q1 = q1->next_row;
+	q2 = q2->next_row;
+    }
+
+    if (q1 != 0) {
+	return 1;
+    } else if (q2 != 0) {
+	return -1;
+    } else {
+	return 0;
+    }
+}
+
+
+/*
+ *  return the intersection
+ */
+sm_col *
+sm_col_and(p1, p2)
+sm_col *p1, *p2;
+{
+    register sm_element *q1, *q2;
+    register sm_col *result;
+
+    result = sm_col_alloc();
+    q1 = p1->first_row;
+    q2 = p2->first_row;
+    if (q1 == 0 || q2 == 0) return result;
+    for(;;) {
+	if (q1->row_num < q2->row_num) {
+	    if ((q1 = q1->next_row) == 0) {
+		return result;
+	    }
+	} else if (q1->row_num > q2->row_num) {
+	    if ((q2 = q2->next_row) == 0) {
+		return result;
+	    }
+	} else {
+	    (void) sm_col_insert(result, q1->row_num);
+	    if ((q1 = q1->next_row) == 0) {
+		return result;
+	    }
+	    if ((q2 = q2->next_row) == 0) {
+		return result;
+	    }
+	}
+    }
+}
+
+int 
+sm_col_hash(pcol, modulus)
+sm_col *pcol;
+int modulus;
+{
+    register int sum;
+    register sm_element *p;
+
+    sum = 0;
+    for(p = pcol->first_row; p != 0; p = p->next_row) {
+	sum = (sum*17 + p->row_num) % modulus;
+    }
+    return sum;
+}
+
+/*
+ *  remove an element from a col vector (given a pointer to the element) 
+ */
+void
+sm_col_remove_element(pcol, p)
+register sm_col *pcol;
+register sm_element *p;
+{
+    dll_unlink(p, pcol->first_row, pcol->last_row, 
+			next_row, prev_row, pcol->length);
+    sm_element_free(p);
+}
+
+
+void
+sm_col_print(fp, pcol)
+FILE *fp;
+sm_col *pcol;
+{
+    sm_element *p;
+
+    for(p = pcol->first_row; p != 0; p = p->next_row) {
+	(void) fprintf(fp, " %d", p->row_num);
+    }
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/compl.c b/abc-build/src/misc/espresso/compl.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/compl.c
@@ -0,0 +1,685 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ *  module: compl.c
+ *  purpose: compute the complement of a multiple-valued function
+ *
+ *  The "unate recursive paradigm" is used.  After a set of special
+ *  cases are examined, the function is split on the "most active
+ *  variable".  These two halves are complemented recursively, and then
+ *  the results are merged.
+ *
+ *  Changes (from Version 2.1 to Version 2.2)
+ *      1. Minor bug in compl_lifting -- cubes in the left half were
+ *      not marked as active, so that when merging a leaf from the left
+ *      hand side, the active flags were essentially random.  This led
+ *      to minor impredictability problem, but never affected the
+ *      accuracy of the results.
+ */
+
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+#define USE_COMPL_LIFT			0
+#define USE_COMPL_LIFT_ONSET		1
+#define USE_COMPL_LIFT_ONSET_COMPLEX	2
+#define NO_LIFTING			3
+
+static bool compl_special_cases();
+static pcover compl_merge();
+static void compl_d1merge();
+static pcover compl_cube();
+static void compl_lift();
+static void compl_lift_onset();
+static void compl_lift_onset_complex();
+static bool simp_comp_special_cases();
+static bool simplify_special_cases();
+
+
+/* complement -- compute the complement of T */
+pcover complement(T)
+pcube *T;			/* T will be disposed of */
+{
+    register pcube cl, cr;
+    register int best;
+    pcover Tbar, Tl, Tr;
+    int lifting;
+    static int compl_level = 0;
+
+    if (debug & COMPL)
+	debug_print(T, "COMPLEMENT", compl_level++);
+
+    if (compl_special_cases(T, &Tbar) == MAYBE) {
+
+	/* Allocate space for the partition cubes */
+	cl = new_cube();
+	cr = new_cube();
+	best = binate_split_select(T, cl, cr, COMPL);
+
+	/* Complement the left and right halves */
+	Tl = complement(scofactor(T, cl, best));
+	Tr = complement(scofactor(T, cr, best));
+
+	if (Tr->count*Tl->count > (Tr->count+Tl->count)*CUBELISTSIZE(T)) {
+	    lifting = USE_COMPL_LIFT_ONSET;
+	} else {
+	    lifting = USE_COMPL_LIFT;
+	}
+	Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
+
+	free_cube(cl);
+	free_cube(cr);
+	free_cubelist(T);
+    }
+
+    if (debug & COMPL)
+	debug1_print(Tbar, "exit COMPLEMENT", --compl_level);
+    return Tbar;
+}
+
+static bool compl_special_cases(T, Tbar)
+pcube *T;			/* will be disposed if answer is determined */
+pcover *Tbar;			/* returned only if answer determined */
+{
+    register pcube *T1, p, ceil, cof=T[0];
+    pcover A, ceil_compl;
+
+    /* Check for no cubes in the cover */
+    if (T[2] == NULL) {
+	*Tbar = sf_addset(new_cover(1), cube.fullset);
+	free_cubelist(T);
+	return TRUE;
+    }
+
+    /* Check for only a single cube in the cover */
+    if (T[3] == NULL) {
+	*Tbar = compl_cube(set_or(cof, cof, T[2]));
+	free_cubelist(T);
+	return TRUE;
+    }
+
+    /* Check for a row of all 1's (implies complement is null) */
+    for(T1 = T+2; (p = *T1++) != NULL; ) {
+	if (full_row(p, cof)) {
+	    *Tbar = new_cover(0);
+	    free_cubelist(T);
+	    return TRUE;
+	}
+    }
+
+    /* Check for a column of all 0's which can be factored out */
+    ceil = set_save(cof);
+    for(T1 = T+2; (p = *T1++) != NULL; ) {
+	INLINEset_or(ceil, ceil, p);
+    }
+    if (! setp_equal(ceil, cube.fullset)) {
+	ceil_compl = compl_cube(ceil);
+	(void) set_or(cof, cof, set_diff(ceil, cube.fullset, ceil));
+	set_free(ceil);
+	*Tbar = sf_append(complement(T), ceil_compl);
+	return TRUE;
+    }
+    set_free(ceil);
+
+    /* Collect column counts, determine unate variables, etc. */
+    massive_count(T);
+
+    /* If single active variable not factored out above, then tautology ! */
+    if (cdata.vars_active == 1) {
+	*Tbar = new_cover(0);
+	free_cubelist(T);
+	return TRUE;
+
+    /* Check for unate cover */
+    } else if (cdata.vars_unate == cdata.vars_active) {
+	A = map_cover_to_unate(T);
+	free_cubelist(T);
+	A = unate_compl(A);
+	*Tbar = map_unate_to_cover(A);
+	sf_free(A);
+	return TRUE;
+
+    /* Not much we can do about it */
+    } else {
+	return MAYBE;
+    }
+}
+
+/*
+ *  compl_merge -- merge the two cofactors around the splitting
+ *  variable
+ *
+ *  The merge operation involves intersecting each cube of the left
+ *  cofactor with cl, and intersecting each cube of the right cofactor
+ *  with cr.  The union of these two covers is the merged result.
+ *
+ *  In order to reduce the number of cubes, a distance-1 merge is
+ *  performed (note that two cubes can only combine distance-1 in the
+ *  splitting variable).  Also, a simple expand is performed in the
+ *  splitting variable (simple implies the covering check for the
+ *  expansion is not full containment, but single-cube containment).
+ */
+
+static pcover compl_merge(T1, L, R, cl, cr, var, lifting)
+pcube *T1;			/* Original ON-set */
+pcover L, R;			/* Complement from each recursion branch */
+register pcube cl, cr;		/* cubes used for cofactoring */
+int var;			/* splitting variable */
+int lifting;			/* whether to perform lifting or not */
+{
+    register pcube p, last, pt;
+    pcover T, Tbar;
+    pcube *L1, *R1;
+
+    if (debug & COMPL) {
+	(void) printf("compl_merge: left %d, right %d\n", L->count, R->count);
+	(void) printf("%s (cl)\n%s (cr)\nLeft is\n", pc1(cl), pc2(cr));
+	cprint(L);
+	(void) printf("Right is\n");
+	cprint(R);
+    }
+
+    /* Intersect each cube with the cofactored cube */
+    foreach_set(L, last, p) {
+	INLINEset_and(p, p, cl);
+	SET(p, ACTIVE);
+    }
+    foreach_set(R, last, p) {
+	INLINEset_and(p, p, cr);
+	SET(p, ACTIVE);
+    }
+
+    /* Sort the arrays for a distance-1 merge */
+    (void) set_copy(cube.temp[0], cube.var_mask[var]);
+    qsort((char *) (L1 = sf_list(L)), L->count, sizeof(pset), (int (*)()) d1_order);
+    qsort((char *) (R1 = sf_list(R)), R->count, sizeof(pset), (int (*)()) d1_order);
+
+    /* Perform distance-1 merge */
+    compl_d1merge(L1, R1);
+
+    /* Perform lifting */
+    switch(lifting) {
+	case USE_COMPL_LIFT_ONSET:
+	    T = cubeunlist(T1);
+	    compl_lift_onset(L1, T, cr, var);
+	    compl_lift_onset(R1, T, cl, var);
+	    free_cover(T);
+	    break;
+	case USE_COMPL_LIFT_ONSET_COMPLEX:
+	    T = cubeunlist(T1);
+	    compl_lift_onset_complex(L1, T, var);
+	    compl_lift_onset_complex(R1, T, var);
+	    free_cover(T);
+	    break;
+	case USE_COMPL_LIFT:
+	    compl_lift(L1, R1, cr, var);
+	    compl_lift(R1, L1, cl, var);
+	    break;
+	case NO_LIFTING:
+	    break;
+	default:
+	    ;
+    }
+    FREE(L1);
+    FREE(R1);
+
+    /* Re-create the merged cover */
+    Tbar = new_cover(L->count + R->count);
+    pt = Tbar->data;
+    foreach_set(L, last, p) {
+	INLINEset_copy(pt, p);
+	Tbar->count++;
+	pt += Tbar->wsize;
+    }
+    foreach_active_set(R, last, p) {
+	INLINEset_copy(pt, p);
+	Tbar->count++;
+	pt += Tbar->wsize;
+    }
+
+    if (debug & COMPL) {
+	(void) printf("Result %d\n", Tbar->count);
+	if (verbose_debug)
+	    cprint(Tbar);
+    }
+
+    free_cover(L);
+    free_cover(R);
+    return Tbar;
+}
+
+/*
+ *  compl_lift_simple -- expand in the splitting variable using single
+ *  cube containment against the other recursion branch to check
+ *  validity of the expansion, and expanding all (or none) of the
+ *  splitting variable.
+ */
+static void compl_lift(A1, B1, bcube, var)
+pcube *A1, *B1, bcube;
+int var;
+{
+    register pcube a, b, *B2, lift=cube.temp[4], liftor=cube.temp[5];
+    pcube mask = cube.var_mask[var];
+
+    (void) set_and(liftor, bcube, mask);
+
+    /* for each cube in the first array ... */
+    for(; (a = *A1++) != NULL; ) {
+	if (TESTP(a, ACTIVE)) {
+
+	    /* create a lift of this cube in the merging coord */
+	    (void) set_merge(lift, bcube, a, mask);
+
+	    /* for each cube in the second array */
+	    for(B2 = B1; (b = *B2++) != NULL; ) {
+		INLINEsetp_implies(lift, b, /* when_false => */ continue);
+		/* when_true => fall through to next statement */
+
+		/* cube of A1 was contained by some cube of B1, so raise */
+		INLINEset_or(a, a, liftor);
+		break;
+	    }
+	}
+    }
+}
+
+
+
+/*
+ *  compl_lift_onset -- expand in the splitting variable using a
+ *  distance-1 check against the original on-set; expand all (or
+ *  none) of the splitting variable.  Each cube of A1 is expanded
+ *  against the original on-set T.
+ */
+static void compl_lift_onset(A1, T, bcube, var)
+pcube *A1;
+pcover T;
+pcube bcube;
+int var;
+{
+    register pcube a, last, p, lift=cube.temp[4], mask=cube.var_mask[var];
+
+    /* for each active cube from one branch of the complement */
+    for(; (a = *A1++) != NULL; ) {
+	if (TESTP(a, ACTIVE)) {
+
+	    /* create a lift of this cube in the merging coord */
+	    INLINEset_and(lift, bcube, mask);	/* isolate parts to raise */
+	    INLINEset_or(lift, a, lift);	/* raise these parts in a */
+
+	    /* for each cube in the ON-set, check for intersection */
+	    foreach_set(T, last, p) {
+		if (cdist0(p, lift)) {
+		    goto nolift;
+		}
+	    }
+	    INLINEset_copy(a, lift);		/* save the raising */
+	    SET(a, ACTIVE);
+nolift : ;
+	}
+    }
+}
+
+/*
+ *  compl_lift_complex -- expand in the splitting variable, but expand all
+ *  parts which can possibly expand.
+ *  T is the original ON-set
+ *  A1 is either the left or right cofactor
+ */
+static void compl_lift_onset_complex(A1, T, var)
+pcube *A1;			/* array of pointers to new result */
+pcover T;			/* original ON-set */
+int var;			/* which variable we split on */
+{
+    register int dist;
+    register pcube last, p, a, xlower;
+
+    /* for each cube in the complement */
+    xlower = new_cube();
+    for(; (a = *A1++) != NULL; ) {
+
+	if (TESTP(a, ACTIVE)) {
+
+	    /* Find which parts of the splitting variable are forced low */
+	    INLINEset_clear(xlower, cube.size);
+	    foreach_set(T, last, p) {
+		if ((dist = cdist01(p, a)) < 2) {
+		    if (dist == 0) {
+			fatal("compl: ON-set and OFF-set are not orthogonal");
+		    } else {
+			(void) force_lower(xlower, p, a);
+		    }
+		}
+	    }
+
+	    (void) set_diff(xlower, cube.var_mask[var], xlower);
+	    (void) set_or(a, a, xlower);
+	    free_cube(xlower);
+	}
+    }
+}
+
+
+
+/*
+ *  compl_d1merge -- distance-1 merge in the splitting variable
+ */
+static void compl_d1merge(L1, R1)
+register pcube *L1, *R1;
+{
+    register pcube pl, pr;
+
+    /* Find equal cubes between the two cofactors */
+    for(pl = *L1, pr = *R1; (pl != NULL) && (pr != NULL); )
+	switch (d1_order(L1, R1)) {
+	    case 1:
+		pr = *(++R1); break;            /* advance right pointer */
+	    case -1:
+		pl = *(++L1); break;            /* advance left pointer */
+	    case 0:
+		RESET(pr, ACTIVE);
+		INLINEset_or(pl, pl, pr);
+		pr = *(++R1);
+	    default:
+		;
+	}
+}
+
+
+
+/* compl_cube -- return the complement of a single cube (De Morgan's law) */
+static pcover compl_cube(p)
+register pcube p;
+{
+    register pcube diff=cube.temp[7], pdest, mask, full=cube.fullset;
+    int var;
+    pcover R;
+
+    /* Allocate worst-case size cover (to avoid checking overflow) */
+    R = new_cover(cube.num_vars);
+
+    /* Compute bit-wise complement of the cube */
+    INLINEset_diff(diff, full, p);
+
+    for(var = 0; var < cube.num_vars; var++) {
+	mask = cube.var_mask[var];
+	/* If the bit-wise complement is not empty in var ... */
+	if (! setp_disjoint(diff, mask)) {
+	    pdest = GETSET(R, R->count++);
+	    INLINEset_merge(pdest, diff, full, mask);
+	}
+    }
+    return R;
+}
+
+/* simp_comp -- quick simplification of T */
+void simp_comp(T, Tnew, Tbar)
+pcube *T;			/* T will be disposed of */
+pcover *Tnew;
+pcover *Tbar;
+{
+    register pcube cl, cr;
+    register int best;
+    pcover Tl, Tr, Tlbar, Trbar;
+    int lifting;
+    static int simplify_level = 0;
+
+    if (debug & COMPL)
+	debug_print(T, "SIMPCOMP", simplify_level++);
+
+    if (simp_comp_special_cases(T, Tnew, Tbar) == MAYBE) {
+
+	/* Allocate space for the partition cubes */
+	cl = new_cube();
+	cr = new_cube();
+	best = binate_split_select(T, cl, cr, COMPL);
+
+	/* Complement the left and right halves */
+	simp_comp(scofactor(T, cl, best), &Tl, &Tlbar);
+	simp_comp(scofactor(T, cr, best), &Tr, &Trbar);
+
+	lifting = USE_COMPL_LIFT;
+	*Tnew = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
+
+	lifting = USE_COMPL_LIFT;
+	*Tbar = compl_merge(T, Tlbar, Trbar, cl, cr, best, lifting);
+
+	/* All of this work for nothing ? Let's hope not ... */
+	if ((*Tnew)->count > CUBELISTSIZE(T)) {
+	    sf_free(*Tnew);
+	    *Tnew = cubeunlist(T);
+	}
+
+	free_cube(cl);
+	free_cube(cr);
+	free_cubelist(T);
+    }
+
+    if (debug & COMPL) {
+	debug1_print(*Tnew, "exit SIMPCOMP (new)", simplify_level);
+	debug1_print(*Tbar, "exit SIMPCOMP (compl)", simplify_level);
+	simplify_level--;
+    }
+}
+
+static bool simp_comp_special_cases(T, Tnew, Tbar)
+pcube *T;			/* will be disposed if answer is determined */
+pcover *Tnew;			/* returned only if answer determined */
+pcover *Tbar;			/* returned only if answer determined */
+{
+    register pcube *T1, p, ceil, cof=T[0];
+    pcube last;
+    pcover A;
+
+    /* Check for no cubes in the cover (function is empty) */
+    if (T[2] == NULL) {
+	*Tnew = new_cover(1);
+	*Tbar = sf_addset(new_cover(1), cube.fullset);
+	free_cubelist(T);
+	return TRUE;
+    }
+
+    /* Check for only a single cube in the cover */
+    if (T[3] == NULL) {
+	(void) set_or(cof, cof, T[2]);
+	*Tnew = sf_addset(new_cover(1), cof);
+	*Tbar = compl_cube(cof);
+	free_cubelist(T);
+	return TRUE;
+    }
+
+    /* Check for a row of all 1's (function is a tautology) */
+    for(T1 = T+2; (p = *T1++) != NULL; ) {
+	if (full_row(p, cof)) {
+	    *Tnew = sf_addset(new_cover(1), cube.fullset);
+	    *Tbar = new_cover(1);
+	    free_cubelist(T);
+	    return TRUE;
+	}
+    }
+
+    /* Check for a column of all 0's which can be factored out */
+    ceil = set_save(cof);
+    for(T1 = T+2; (p = *T1++) != NULL; ) {
+	INLINEset_or(ceil, ceil, p);
+    }
+    if (! setp_equal(ceil, cube.fullset)) {
+	p = new_cube();
+	(void) set_diff(p, cube.fullset, ceil);
+	(void) set_or(cof, cof, p);
+	set_free(p);
+	simp_comp(T, Tnew, Tbar);
+
+	/* Adjust the ON-set */
+	A = *Tnew;
+	foreach_set(A, last, p) {
+	    INLINEset_and(p, p, ceil);
+	}
+
+	/* Compute the new complement */
+	*Tbar = sf_append(*Tbar, compl_cube(ceil));
+	set_free(ceil);
+	return TRUE;
+    }
+    set_free(ceil);
+
+    /* Collect column counts, determine unate variables, etc. */
+    massive_count(T);
+
+    /* If single active variable not factored out above, then tautology ! */
+    if (cdata.vars_active == 1) {
+	*Tnew = sf_addset(new_cover(1), cube.fullset);
+	*Tbar = new_cover(1);
+	free_cubelist(T);
+	return TRUE;
+
+    /* Check for unate cover */
+    } else if (cdata.vars_unate == cdata.vars_active) {
+	/* Make the cover minimum by single-cube containment */
+	A = cubeunlist(T);
+	*Tnew = sf_contain(A);
+
+	/* Now form a minimum representation of the complement */
+	A = map_cover_to_unate(T);
+	A = unate_compl(A);
+	*Tbar = map_unate_to_cover(A);
+	sf_free(A);
+	free_cubelist(T);
+	return TRUE;
+
+    /* Not much we can do about it */
+    } else {
+	return MAYBE;
+    }
+}
+
+/* simplify -- quick simplification of T */
+pcover simplify(T)
+pcube *T;			/* T will be disposed of */
+{
+    register pcube cl, cr;
+    register int best;
+    pcover Tbar, Tl, Tr;
+    int lifting;
+    static int simplify_level = 0;
+
+    if (debug & COMPL) {
+	debug_print(T, "SIMPLIFY", simplify_level++);
+    }
+
+    if (simplify_special_cases(T, &Tbar) == MAYBE) {
+
+	/* Allocate space for the partition cubes */
+	cl = new_cube();
+	cr = new_cube();
+
+	best = binate_split_select(T, cl, cr, COMPL);
+
+	/* Complement the left and right halves */
+	Tl = simplify(scofactor(T, cl, best));
+	Tr = simplify(scofactor(T, cr, best));
+
+	lifting = USE_COMPL_LIFT;
+	Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
+
+	/* All of this work for nothing ? Let's hope not ... */
+	if (Tbar->count > CUBELISTSIZE(T)) {
+	    sf_free(Tbar);
+	    Tbar = cubeunlist(T);
+	}
+
+	free_cube(cl);
+	free_cube(cr);
+	free_cubelist(T);
+    }
+
+    if (debug & COMPL) {
+	debug1_print(Tbar, "exit SIMPLIFY", --simplify_level);
+    }
+    return Tbar;
+}
+
+static bool simplify_special_cases(T, Tnew)
+pcube *T;			/* will be disposed if answer is determined */
+pcover *Tnew;			/* returned only if answer determined */
+{
+    register pcube *T1, p, ceil, cof=T[0];
+    pcube last;
+    pcover A;
+
+    /* Check for no cubes in the cover */
+    if (T[2] == NULL) {
+	*Tnew = new_cover(0);
+	free_cubelist(T);
+	return TRUE;
+    }
+
+    /* Check for only a single cube in the cover */
+    if (T[3] == NULL) {
+	*Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2]));
+	free_cubelist(T);
+	return TRUE;
+    }
+
+    /* Check for a row of all 1's (implies function is a tautology) */
+    for(T1 = T+2; (p = *T1++) != NULL; ) {
+	if (full_row(p, cof)) {
+	    *Tnew = sf_addset(new_cover(1), cube.fullset);
+	    free_cubelist(T);
+	    return TRUE;
+	}
+    }
+
+    /* Check for a column of all 0's which can be factored out */
+    ceil = set_save(cof);
+    for(T1 = T+2; (p = *T1++) != NULL; ) {
+	INLINEset_or(ceil, ceil, p);
+    }
+    if (! setp_equal(ceil, cube.fullset)) {
+	p = new_cube();
+	(void) set_diff(p, cube.fullset, ceil);
+	(void) set_or(cof, cof, p);
+	free_cube(p);
+
+	A = simplify(T);
+	foreach_set(A, last, p) {
+	    INLINEset_and(p, p, ceil);
+	}
+	*Tnew = A;
+	set_free(ceil);
+	return TRUE;
+    }
+    set_free(ceil);
+
+    /* Collect column counts, determine unate variables, etc. */
+    massive_count(T);
+
+    /* If single active variable not factored out above, then tautology ! */
+    if (cdata.vars_active == 1) {
+	*Tnew = sf_addset(new_cover(1), cube.fullset);
+	free_cubelist(T);
+	return TRUE;
+
+    /* Check for unate cover */
+    } else if (cdata.vars_unate == cdata.vars_active) {
+	A = cubeunlist(T);
+	*Tnew = sf_contain(A);
+	free_cubelist(T);
+	return TRUE;
+
+    /* Not much we can do about it */
+    } else {
+	return MAYBE;
+    }
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/contain.c b/abc-build/src/misc/espresso/contain.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/contain.c
@@ -0,0 +1,450 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+    contain.c -- set containment routines
+
+    These are complex routines for performing containment over a
+    family of sets, but they have the advantage of being much faster
+    than a straightforward n*n routine.
+
+    First the cubes are sorted by size, and as a secondary key they are
+    sorted so that if two cubes are equal they end up adjacent.  We can
+    than quickly remove equal cubes from further consideration by
+    comparing each cube to its neighbor.  Finally, because the cubes
+    are sorted by size, we need only check cubes which are larger (or
+    smaller) than a given cube for containment.
+*/
+
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*
+    sf_contain -- perform containment on a set family (delete sets which
+    are contained by some larger set in the family).  No assumptions are
+    made about A, and the result will be returned in decreasing order of
+    set size.
+*/
+pset_family sf_contain(A)
+INOUT pset_family A;            /* disposes of A */
+{
+    int cnt;
+    pset *A1;
+    pset_family R;
+
+    A1 = sf_sort(A, descend);           /* sort into descending order */
+    cnt = rm_equal(A1, descend);        /* remove duplicates */
+    cnt = rm_contain(A1);               /* remove contained sets */
+    R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */
+    sf_free(A);
+    return R;
+}
+
+
+/*
+    sf_rev_contain -- perform containment on a set family (delete sets which
+    contain some smaller set in the family).  No assumptions are made about
+    A, and the result will be returned in increasing order of set size
+*/
+pset_family sf_rev_contain(A)
+INOUT pset_family A;            /* disposes of A */
+{
+    int cnt;
+    pset *A1;
+    pset_family R;
+
+    A1 = sf_sort(A, ascend);            /* sort into ascending order */
+    cnt = rm_equal(A1, ascend);         /* remove duplicates */
+    cnt = rm_rev_contain(A1);           /* remove containing sets */
+    R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */
+    sf_free(A);
+    return R;
+}
+
+
+/*
+    sf_ind_contain -- perform containment on a set family (delete sets which
+    are contained by some larger set in the family).  No assumptions are
+    made about A, and the result will be returned in decreasing order of
+    set size.  Also maintains a set of row_indices to track which rows
+    disappear and how the rows end up permuted.
+*/
+pset_family sf_ind_contain(A, row_indices)
+INOUT pset_family A;            /* disposes of A */
+INOUT int *row_indices;         /* updated with the new values */
+{
+    int cnt;
+    pset *A1;
+    pset_family R;
+
+    A1 = sf_sort(A, descend);           /* sort into descending order */
+    cnt = rm_equal(A1, descend);        /* remove duplicates */
+    cnt = rm_contain(A1);               /* remove contained sets */
+    R = sf_ind_unlist(A1, cnt, A->sf_size, row_indices, A->data);
+    sf_free(A);
+    return R;
+}
+
+
+/* sf_dupl -- delete duplicate sets in a set family */
+pset_family sf_dupl(A)
+INOUT pset_family A;            /* disposes of A */
+{
+    register int cnt;
+    register pset *A1;
+    pset_family R;
+
+    A1 = sf_sort(A, descend);           /* sort the set family */
+    cnt = rm_equal(A1, descend);        /* remove duplicates */
+    R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */
+    sf_free(A);
+    return R;
+}
+
+
+/*
+    sf_union -- form the contained union of two set families (delete
+    sets which are contained by some larger set in the family).  A and
+    B are assumed already sorted in decreasing order of set size (and
+    the SIZE field is assumed to contain the set size), and the result
+    will be returned sorted likewise.
+*/
+pset_family sf_union(A, B)
+INOUT pset_family A, B;         /* disposes of A and B */
+{
+    int cnt;
+    pset_family R;
+    pset *A1 = sf_list(A), *B1 = sf_list(B), *E1;
+
+    E1 = ALLOC(pset, MAX(A->count, B->count) + 1);
+    cnt = rm2_equal(A1, B1, E1, descend);
+    cnt += rm2_contain(A1, B1) + rm2_contain(B1, A1);
+    R = sf_merge(A1, B1, E1, cnt, A->sf_size);
+    sf_free(A); sf_free(B);
+    return R;
+}
+
+
+/*
+    dist_merge -- consider all sets to be "or"-ed with "mask" and then
+    delete duplicates from the set family.
+*/
+pset_family dist_merge(A, mask)
+INOUT pset_family A;            /* disposes of A */
+IN pset mask;                   /* defines variables to mask out */
+{
+    pset *A1;
+    int cnt;
+    pset_family R;
+
+    (void) set_copy(cube.temp[0], mask);
+    A1 = sf_sort(A, d1_order);
+    cnt = d1_rm_equal(A1, d1_order);
+    R = sf_unlist(A1, cnt, A->sf_size);
+    sf_free(A);
+    return R;
+}
+
+
+/*
+    d1merge -- perform an efficient distance-1 merge of cubes of A
+*/
+pset_family d1merge(A, var)
+INOUT pset_family A;            /* disposes of A */
+IN int var;
+{
+    return dist_merge(A, cube.var_mask[var]);
+}
+
+
+
+/* d1_rm_equal -- distance-1 merge (merge cubes which are equal under a mask) */
+int d1_rm_equal(A1, compare)
+register pset *A1;				/* array of set pointers */
+int (*compare)();				/* comparison function */
+{
+    register int i, j, dest;
+
+    dest = 0;
+    if (A1[0] != (pcube) NULL) {
+	for(i = 0, j = 1; A1[j] != (pcube) NULL; j++)
+	    if ( (*compare)(&A1[i], &A1[j]) == 0) {
+		/* if sets are equal (under the mask) merge them */
+		(void) set_or(A1[i], A1[i], A1[j]);
+	    } else {
+		/* sets are unequal, so save the set i */
+		A1[dest++] = A1[i];
+		i = j;
+	    }
+	A1[dest++] = A1[i];
+    }
+    A1[dest] = (pcube) NULL;
+    return dest;
+}
+
+
+/* rm_equal -- scan a sorted array of set pointers for duplicate sets */
+int rm_equal(A1, compare)
+INOUT pset *A1;                 /* updated in place */
+IN int (*compare)();
+{
+    register pset *p, *pdest = A1;
+
+    if (*A1 != NULL) {                  /* If more than one set */
+	for(p = A1+1; *p != NULL; p++)
+	    if ((*compare)(p, p-1) != 0)
+		*pdest++ = *(p-1);
+	*pdest++ = *(p-1);
+	*pdest = NULL;
+    }
+    return pdest - A1;
+}
+
+
+/* rm_contain -- perform containment over a sorted array of set pointers */
+int rm_contain(A1)
+INOUT pset *A1;                 /* updated in place */
+{
+    register pset *pa, *pb;
+    register pset *pcheck = NULL; // Suppress "might be used uninitialized"
+    register pset a, b;
+    pset *pdest = A1;
+    int last_size = -1;
+
+    /* Loop for all cubes of A1 */
+    for(pa = A1; (a = *pa++) != NULL; ) {
+	/* Update the check pointer if the size has changed */
+	if (SIZE(a) != last_size)
+	    last_size = SIZE(a), pcheck = pdest;
+	for(pb = A1; pb != pcheck; ) {
+	    b = *pb++;
+	    INLINEsetp_implies(a, b, /* when_false => */ continue);
+	    goto lnext1;
+	}
+	/* set a was not contained by some larger set, so save it */
+	*pdest++ = a;
+    lnext1: ;
+    }
+
+    *pdest = NULL;
+    return pdest - A1;
+}
+
+
+/* rm_rev_contain -- perform rcontainment over a sorted array of set pointers */
+int rm_rev_contain(A1)
+INOUT pset *A1;                 /* updated in place */
+{
+    register pset *pa, *pb;
+    register pset *pcheck = NULL; // Suppress "might be used uninitialized"
+    register pset a, b;
+    pset *pdest = A1;
+    int last_size = -1;
+
+    /* Loop for all cubes of A1 */
+    for(pa = A1; (a = *pa++) != NULL; ) {
+	/* Update the check pointer if the size has changed */
+	if (SIZE(a) != last_size)
+	    last_size = SIZE(a), pcheck = pdest;
+	for(pb = A1; pb != pcheck; ) {
+	    b = *pb++;
+	    INLINEsetp_implies(b, a, /* when_false => */ continue);
+	    goto lnext1;
+	}
+	/* the set a did not contain some smaller set, so save it */
+	*pdest++ = a;
+    lnext1: ;
+    }
+
+    *pdest = NULL;
+    return pdest - A1;
+}
+
+
+/* rm2_equal -- check two sorted arrays of set pointers for equal cubes */
+int rm2_equal(A1, B1, E1, compare)
+INOUT register pset *A1, *B1;           /* updated in place */
+OUT pset *E1;
+IN int (*compare)();
+{
+    register pset *pda = A1, *pdb = B1, *pde = E1;
+
+    /* Walk through the arrays advancing pointer to larger cube */
+    for(; *A1 != NULL && *B1 != NULL; )
+	switch((*compare)(A1, B1)) {
+	    case -1:    /* "a" comes before "b" */
+		*pda++ = *A1++; break;
+	    case 0:     /* equal cubes */
+		*pde++ = *A1++; B1++; break;
+	    case 1:     /* "a" is to follow "b" */
+		*pdb++ = *B1++; break;
+	}
+
+    /* Finish moving down the pointers of A and B */
+    while (*A1 != NULL)
+	*pda++ = *A1++;
+    while (*B1 != NULL)
+	*pdb++ = *B1++;
+    *pda = *pdb = *pde = NULL;
+
+    return pde - E1;
+}
+
+
+/* rm2_contain -- perform containment between two arrays of set pointers */
+int rm2_contain(A1, B1)
+INOUT pset *A1;                 /* updated in place */
+IN pset *B1;                    /* unchanged */
+{
+    register pset *pa, *pb, a, b, *pdest = A1;
+
+    /* for each set in the first array ... */
+    for(pa = A1; (a = *pa++) != NULL; ) {
+	/* for each set in the second array which is larger ... */
+	for(pb = B1; (b = *pb++) != NULL && SIZE(b) > SIZE(a); ) {
+	    INLINEsetp_implies(a, b, /* when_false => */ continue);
+	    /* set was contained in some set of B, so don't save pointer */
+	    goto lnext1;
+	}
+	/* set wasn't contained in any set of B, so save the pointer */
+	*pdest++ = a;
+    lnext1: ;
+    }
+
+    *pdest = NULL;                      /* sentinel */
+    return pdest - A1;                  /* # elements in A1 */
+}
+
+
+
+/* sf_sort -- sort the sets of A */
+pset *sf_sort(A, compare)
+IN pset_family A;
+IN int (*compare)();
+{
+    register pset p, last, *pdest, *A1;
+
+    /* Create a single array pointing to each cube of A */
+    pdest = A1 = ALLOC(pset, A->count + 1);
+    foreach_set(A, last, p) {
+	PUTSIZE(p, set_ord(p));         /* compute the set size */
+	*pdest++ = p;                   /* save the pointer */
+    }
+    *pdest = NULL;                      /* Sentinel -- never seen by sort */
+
+    /* Sort cubes by size */
+    qsort((char *) A1, A->count, sizeof(pset), compare);
+    return A1;
+}
+
+
+/* sf_list -- make a list of pointers to the sets in a set family */
+pset *sf_list(A)
+IN register pset_family A;
+{
+    register pset p, last, *pdest, *A1;
+
+    /* Create a single array pointing to each cube of A */
+    pdest = A1 = ALLOC(pset, A->count + 1);
+    foreach_set(A, last, p)
+	*pdest++ = p;                   /* save the pointer */
+    *pdest = NULL;                      /* Sentinel */
+    return A1;
+}
+
+
+/* sf_unlist -- make a set family out of a list of pointers to sets */
+pset_family sf_unlist(A1, totcnt, size)
+IN pset *A1;
+IN int totcnt, size;
+{
+    register pset pr, p, *pa;
+    pset_family R = sf_new(totcnt, size);
+
+    R->count = totcnt;
+    for(pr = R->data, pa = A1; (p = *pa++) != NULL; pr += R->wsize)
+	INLINEset_copy(pr, p);
+    FREE(A1);
+    return R;
+}
+
+
+/* sf_ind_unlist -- make a set family out of a list of pointers to sets */
+pset_family sf_ind_unlist(A1, totcnt, size, row_indices, pfirst)
+IN pset *A1;
+IN int totcnt, size;
+INOUT int *row_indices;
+IN register pset pfirst;
+{
+    register pset pr, p, *pa;
+    register int i, *new_row_indices;
+    pset_family R = sf_new(totcnt, size);
+
+    R->count = totcnt;
+    new_row_indices = ALLOC(int, totcnt);
+    for(pr = R->data, pa = A1, i=0; (p = *pa++) != NULL; pr += R->wsize, i++) {
+	INLINEset_copy(pr, p);
+	new_row_indices[i] = row_indices[(p - pfirst)/R->wsize];
+    }
+    for(i = 0; i < totcnt; i++)
+	row_indices[i] = new_row_indices[i];
+    FREE(new_row_indices);
+    FREE(A1);
+    return R;
+}
+
+
+/* sf_merge -- merge three sorted lists of set pointers */
+pset_family sf_merge(A1, B1, E1, totcnt, size)
+INOUT pset *A1, *B1, *E1;               /* will be disposed of */
+IN int totcnt, size;
+{
+    register pset pr, ps, *pmin, *pmid, *pmax;
+    pset_family R;
+    pset *temp[3], *swap;
+    int i, j, n;
+
+    /* Allocate the result set_family */
+    R = sf_new(totcnt, size);
+    R->count = totcnt;
+    pr = R->data;
+
+    /* Quick bubble sort to order the top member of the three arrays */
+    n = 3;  temp[0] = A1;  temp[1] = B1;  temp[2] = E1;
+    for(i = 0; i < n-1; i++)
+	for(j = i+1; j < n; j++)
+	    if (desc1(*temp[i], *temp[j]) > 0) {
+		swap = temp[j];
+		temp[j] = temp[i];
+		temp[i] = swap;
+	    }
+    pmin = temp[0];  pmid = temp[1];  pmax = temp[2];
+
+    /* Save the minimum element, then update pmin, pmid, pmax */
+    while (*pmin != (pset) NULL) {
+	ps = *pmin++;
+	INLINEset_copy(pr, ps);
+	pr += R->wsize;
+	if (desc1(*pmin, *pmax) > 0) {
+	    swap = pmax; pmax = pmin; pmin = pmid; pmid = swap;
+	} else if (desc1(*pmin, *pmid) > 0) {
+	    swap = pmin; pmin = pmid; pmid = swap;
+	}
+    }
+
+    FREE(A1);
+    FREE(B1);
+    FREE(E1);
+    return R;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/cubehack.c b/abc-build/src/misc/espresso/cubehack.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/cubehack.c
@@ -0,0 +1,143 @@
+/*
+ * Revision Control Information
+ *
+ * $Source: /vol/opua/opua2/sis/sis-1.1/common/src/sis/node/RCS/cubehack.c,v $
+ * $Author: sis $
+ * $Revision: 1.2 $
+ * $Date: 1992/05/06 18:57:41 $
+ *
+ */
+/*
+#include "sis.h"
+#include "node_int.h"
+
+#ifdef lint
+struct cube_struct cube;
+bool summary;
+bool trace;
+bool remove_essential;
+bool force_irredundant;
+bool unwrap_onset;
+bool single_expand;
+bool pos;
+bool recompute_onset;
+bool use_super_gasp;
+bool use_random_order;
+#endif
+*/
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+void 
+cautious_define_cube_size(n)
+int n;
+{
+    if (cube.fullset != 0 && cube.num_binary_vars == n)
+	return;
+    if (cube.fullset != 0) {
+	setdown_cube();
+	FREE(cube.part_size);
+    }
+    cube.num_binary_vars = cube.num_vars = n;
+    cube.part_size = ALLOC(int, n);
+    cube_setup();
+}
+
+
+void
+define_cube_size(n)
+int n;
+{
+    register int q, i;
+    static int called_before = 0;
+
+    /* check if the cube is already just the right size */
+    if (cube.fullset != 0 && cube.num_binary_vars == n && cube.num_vars == n)
+	return;
+
+    /* We can't handle more than 100 inputs */
+    if (n > 100) {
+	cautious_define_cube_size(n);
+	called_before = 0;
+	return;
+    }
+
+    if (cube.fullset == 0 || ! called_before) {
+	cautious_define_cube_size(100);
+	called_before = 1;
+    }
+
+    cube.num_vars = n;
+    cube.num_binary_vars = n;
+    cube.num_mv_vars = 0;
+    cube.output = -1;
+    cube.size = n * 2;
+
+    /* first_part, last_part, first_word, last_word, part_size OKAY */
+    /* cube.sparse is OKAY */
+
+    /* need to completely re-make cube.fullset and cube.binary_mask */
+    (void) set_fill(cube.fullset, n*2);
+    (void) set_fill(cube.binary_mask, n*2);
+
+    /* need to resize each set in cube.var_mask and cube.temp */
+    q = cube.fullset[0];
+    for(i = 0; i < cube.num_vars; i++)
+	cube.var_mask[i][0] = q;
+    for(i = 0; i < CUBE_TEMP; i++)
+	cube.temp[i][0] = q;
+
+    /* need to resize cube.emptyset and cube.mv_mask */
+    cube.emptyset[0] = q;
+    cube.mv_mask[0] = q;
+
+    /* need to reset the inword and inmask */
+    if (cube.num_binary_vars != 0) {
+	cube.inword = cube.last_word[cube.num_binary_vars - 1];
+	cube.inmask = cube.binary_mask[cube.inword] & DISJOINT;
+    } else {
+	cube.inword = -1;
+	cube.inmask = 0;
+    }
+
+    /* cdata (entire structure) is OKAY */
+}
+
+
+void
+undefine_cube_size()
+{
+    if (cube.num_binary_vars > 100) {
+	if (cube.fullset != 0) {
+	    setdown_cube();
+	    FREE(cube.part_size);
+	}
+    } else {
+	cube.num_vars = cube.num_binary_vars = 100;
+	if (cube.fullset != 0) {
+	    setdown_cube();
+	    FREE(cube.part_size);
+	}
+    }
+}
+
+
+void
+set_espresso_flags()
+{
+    summary = FALSE;
+    trace = FALSE;
+    remove_essential = TRUE;
+    force_irredundant = TRUE;
+    unwrap_onset = TRUE;
+    single_expand = FALSE;
+    pos = FALSE;
+    recompute_onset = FALSE;
+    use_super_gasp = FALSE;
+    use_random_order = FALSE;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/cubestr.c b/abc-build/src/misc/espresso/cubestr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/cubestr.c
@@ -0,0 +1,157 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+    Module: cubestr.c -- routines for managing the global cube structure
+*/
+
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+    cube_setup -- assume that the fields "num_vars", "num_binary_vars", and
+    part_size[num_binary_vars .. num_vars-1] are setup, and initialize the
+    rest of cube and cdata.
+
+    If a part_size is < 0, then the field size is abs(part_size) and the
+    field read from the input is symbolic.
+*/
+void cube_setup()
+{
+    register int i, var;
+    register pcube p;
+
+    if (cube.num_binary_vars < 0 || cube.num_vars < cube.num_binary_vars)
+	fatal("cube size is silly, error in .i/.o or .mv");
+
+    cube.num_mv_vars = cube.num_vars - cube.num_binary_vars;
+    cube.output = cube.num_mv_vars > 0 ? cube.num_vars - 1 : -1;
+
+    cube.size = 0;
+    cube.first_part = ALLOC(int, cube.num_vars);
+    cube.last_part = ALLOC(int, cube.num_vars);
+    cube.first_word = ALLOC(int, cube.num_vars);
+    cube.last_word = ALLOC(int, cube.num_vars);
+    for(var = 0; var < cube.num_vars; var++) {
+	if (var < cube.num_binary_vars)
+	    cube.part_size[var] = 2;
+	cube.first_part[var] = cube.size;
+	cube.first_word[var] = WHICH_WORD(cube.size);
+	cube.size += ABS(cube.part_size[var]);
+	cube.last_part[var] = cube.size - 1;
+	cube.last_word[var] = WHICH_WORD(cube.size - 1);
+    }
+
+    cube.var_mask = ALLOC(pset, cube.num_vars);
+    cube.sparse = ALLOC(int, cube.num_vars);
+    cube.binary_mask = new_cube();
+    cube.mv_mask = new_cube();
+    for(var = 0; var < cube.num_vars; var++) {
+	p = cube.var_mask[var] = new_cube();
+	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++)
+	    set_insert(p, i);
+	if (var < cube.num_binary_vars) {
+	    INLINEset_or(cube.binary_mask, cube.binary_mask, p);
+	    cube.sparse[var] = 0;
+	} else {
+	    INLINEset_or(cube.mv_mask, cube.mv_mask, p);
+	    cube.sparse[var] = 1;
+	}
+    }
+    if (cube.num_binary_vars == 0)
+	cube.inword = -1;
+    else {
+	cube.inword = cube.last_word[cube.num_binary_vars - 1];
+	cube.inmask = cube.binary_mask[cube.inword] & DISJOINT;
+    }
+
+    cube.temp = ALLOC(pset, CUBE_TEMP);
+    for(i = 0; i < CUBE_TEMP; i++)
+	cube.temp[i] = new_cube();
+    cube.fullset = set_fill(new_cube(), cube.size);
+    cube.emptyset = new_cube();
+
+    cdata.part_zeros = ALLOC(int, cube.size);
+    cdata.var_zeros = ALLOC(int, cube.num_vars);
+    cdata.parts_active = ALLOC(int, cube.num_vars);
+    cdata.is_unate = ALLOC(int, cube.num_vars);
+}
+
+/*
+    setdown_cube -- free memory allocated for the cube/cdata structs
+    (free's all but the part_size array)
+
+    (I wanted to call this cube_setdown, but that violates the 8-character
+    external routine limit on the IBM !)
+*/
+void setdown_cube()
+{
+    register int i, var;
+
+    FREE(cube.first_part);
+    FREE(cube.last_part);
+    FREE(cube.first_word);
+    FREE(cube.last_word);
+    FREE(cube.sparse);
+
+    free_cube(cube.binary_mask);
+    free_cube(cube.mv_mask);
+    free_cube(cube.fullset);
+    free_cube(cube.emptyset);
+    for(var = 0; var < cube.num_vars; var++)
+	free_cube(cube.var_mask[var]);
+    FREE(cube.var_mask);
+
+    for(i = 0; i < CUBE_TEMP; i++)
+	free_cube(cube.temp[i]);
+    FREE(cube.temp);
+
+    FREE(cdata.part_zeros);
+    FREE(cdata.var_zeros);
+    FREE(cdata.parts_active);
+    FREE(cdata.is_unate);
+
+    cube.first_part = cube.last_part = (int *) NULL;
+    cube.first_word = cube.last_word = (int *) NULL;
+    cube.sparse = (int *) NULL;
+    cube.binary_mask = cube.mv_mask = (pcube) NULL;
+    cube.fullset = cube.emptyset = (pcube) NULL;
+    cube.var_mask = cube.temp = (pcube *) NULL;
+
+    cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL;
+    cdata.is_unate = (bool *) NULL;
+}
+
+
+void save_cube_struct()
+{
+    temp_cube_save = cube;              /* structure copy ! */
+    temp_cdata_save = cdata;            /*      ""          */
+
+    cube.first_part = cube.last_part = (int *) NULL;
+    cube.first_word = cube.last_word = (int *) NULL;
+    cube.part_size = (int *) NULL;
+    cube.binary_mask = cube.mv_mask = (pcube) NULL;
+    cube.fullset = cube.emptyset = (pcube) NULL;
+    cube.var_mask = cube.temp = (pcube *) NULL;
+
+    cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL;
+    cdata.is_unate = (bool *) NULL;
+}
+
+
+void restore_cube_struct()
+{
+    cube = temp_cube_save;              /* structure copy ! */
+    cdata = temp_cdata_save;            /*      ""          */
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/cvrin.c b/abc-build/src/misc/espresso/cvrin.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/cvrin.c
@@ -0,0 +1,816 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+    module: cvrin.c
+    purpose: cube and cover input routines
+*/
+
+#include <ctype.h>
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+static bool line_length_error;
+static int lineno;
+
+void skip_line(fpin, fpout, echo)
+register FILE *fpin, *fpout;
+register bool echo;
+{
+    register int ch;
+    while ((ch=getc(fpin)) != EOF && ch != '\n')
+	if (echo)
+	    putc(ch, fpout);
+    if (echo)
+	putc('\n', fpout);
+    lineno++;
+}
+
+char *get_word(fp, word)
+register FILE *fp;
+register char *word;
+{
+    register int ch, i = 0;
+    while ((ch = getc(fp)) != EOF && isspace(ch))
+	;
+    word[i++] = ch;
+    while ((ch = getc(fp)) != EOF && ! isspace(ch))
+	word[i++] = ch;
+    word[i++] = '\0';
+    return word;
+}
+
+/*
+ *  Yes, I know this routine is a mess
+ */
+void read_cube(fp, PLA)
+register FILE *fp;
+pPLA PLA;
+{
+    register int var, i;
+    pcube cf = cube.temp[0], cr = cube.temp[1], cd = cube.temp[2];
+    bool savef = FALSE, saved = FALSE, saver = FALSE;
+    char token[256]; 			/* for kiss read hack */
+    int varx, first, last, offset;	/* for kiss read hack */
+
+    set_clear(cf, cube.size);
+
+    /* Loop and read binary variables */
+    for(var = 0; var < cube.num_binary_vars; var++)
+	switch(getc(fp)) {
+	    case EOF:
+		goto bad_char;
+	    case '\n':
+		if (! line_length_error)
+		    (void) fprintf(stderr, "product term(s) %s\n",
+			"span more than one line (warning only)");
+		line_length_error = TRUE;
+		lineno++;
+		var--;
+		break;
+	    case ' ': case '|': case '\t':
+		var--;
+		break;
+	    case '2': case '-':
+		set_insert(cf, var*2+1);
+	    case '0':
+		set_insert(cf, var*2);
+		break;
+	    case '1':
+		set_insert(cf, var*2+1);
+		break;
+	    case '?':
+		break;
+	    default:
+		goto bad_char;
+	}
+
+
+    /* Loop for the all but one of the multiple-valued variables */	
+    for(var = cube.num_binary_vars; var < cube.num_vars-1; var++)
+
+	/* Read a symbolic multiple-valued variable */
+	if (cube.part_size[var] < 0) {
+	    (void) fscanf(fp, "%s", token);
+	    if (equal(token, "-") || equal(token, "ANY")) {
+		if (kiss && var == cube.num_vars - 2) {
+		    /* leave it empty */
+		} else {
+		    /* make it full */
+		    set_or(cf, cf, cube.var_mask[var]);
+		}
+	    } else if (equal(token, "~")) {
+		;
+		/* leave it empty ... (?) */
+	    } else {
+		if (kiss && var == cube.num_vars - 2)
+		    varx = var - 1, offset = ABS(cube.part_size[var-1]);
+		else
+		    varx = var, offset = 0;
+		/* Find the symbolic label in the label table */
+		first = cube.first_part[varx];
+		last = cube.last_part[varx];
+		for(i = first; i <= last; i++)
+		    if (PLA->label[i] == (char *) NULL) {
+			PLA->label[i] = util_strsav(token);	/* add new label */
+			set_insert(cf, i+offset);
+			break;
+		    } else if (equal(PLA->label[i], token)) {
+			set_insert(cf, i+offset);	/* use column i */
+			break;
+		    }
+		if (i > last) {
+		    (void) fprintf(stderr,
+"declared size of variable %d (counting from variable 0) is too small\n", var);
+		    exit(-1);
+		}
+	    }
+	
+	} else for(i = cube.first_part[var]; i <= cube.last_part[var]; i++)
+	    switch (getc(fp)) {
+		case EOF:
+		    goto bad_char;
+		case '\n':
+		    if (! line_length_error)
+			(void) fprintf(stderr, "product term(s) %s\n",
+			    "span more than one line (warning only)");
+		    line_length_error = TRUE;
+		    lineno++;
+		    i--;
+		    break;
+		case ' ': case '|': case '\t':
+		    i--;
+		    break;
+		case '1':
+		    set_insert(cf, i);
+		case '0':
+		    break;
+		default:
+		    goto bad_char;
+	    }
+
+    /* Loop for last multiple-valued variable */
+    if (kiss) {
+	saver = savef = TRUE;
+	(void) set_xor(cr, cf, cube.var_mask[cube.num_vars - 2]);
+    } else
+	set_copy(cr, cf);
+    set_copy(cd, cf);
+    for(i = cube.first_part[var]; i <= cube.last_part[var]; i++)
+	switch (getc(fp)) {
+	    case EOF:
+		goto bad_char;
+	    case '\n':
+		if (! line_length_error)
+		    (void) fprintf(stderr, "product term(s) %s\n",
+			"span more than one line (warning only)");
+		line_length_error = TRUE;
+		lineno++;
+		i--;
+		break;
+	    case ' ': case '|': case '\t':
+		i--;
+		break;
+	    case '4': case '1':
+		if (PLA->pla_type & F_type)
+		    set_insert(cf, i), savef = TRUE;
+		break;
+	    case '3': case '0':
+		if (PLA->pla_type & R_type)
+		    set_insert(cr, i), saver = TRUE;
+		break;
+	    case '2': case '-':
+		if (PLA->pla_type & D_type)
+		    set_insert(cd, i), saved = TRUE;
+	    case '~':
+		break;
+	    default:
+		goto bad_char;
+	}
+    if (savef) PLA->F = sf_addset(PLA->F, cf);
+    if (saved) PLA->D = sf_addset(PLA->D, cd);
+    if (saver) PLA->R = sf_addset(PLA->R, cr);
+    return;
+
+bad_char:
+    (void) fprintf(stderr, "(warning): input line #%d ignored\n", lineno);
+    skip_line(fp, stdout, TRUE);
+    return;
+}
+void parse_pla(fp, PLA)
+IN FILE *fp;
+INOUT pPLA PLA;
+{
+    int i, var, ch, np, last;
+    char word[256];
+
+    lineno = 1;
+    line_length_error = FALSE;
+
+loop:
+    switch(ch = getc(fp)) {
+	case EOF:
+	    return;
+
+	case '\n':
+	    lineno++;
+
+	case ' ': case '\t': case '\f': case '\r':
+	    break;
+
+	case '#':
+	    (void) ungetc(ch, fp);
+	    skip_line(fp, stdout, echo_comments);
+	    break;
+
+	case '.':
+	    /* .i gives the cube input size (binary-functions only) */
+	    if (equal(get_word(fp, word), "i")) {
+		if (cube.fullset != NULL) {
+		    (void) fprintf(stderr, "extra .i ignored\n");
+		    skip_line(fp, stdout, /* echo */ FALSE);
+		} else {
+		    if (fscanf(fp, "%d", &cube.num_binary_vars) != 1)
+			fatal("error reading .i");
+		    cube.num_vars = cube.num_binary_vars + 1;
+		    cube.part_size = ALLOC(int, cube.num_vars);
+		}
+
+	    /* .o gives the cube output size (binary-functions only) */
+	    } else if (equal(word, "o")) {
+		if (cube.fullset != NULL) {
+		    (void) fprintf(stderr, "extra .o ignored\n");
+		    skip_line(fp, stdout, /* echo */ FALSE);
+		} else {
+		    if (cube.part_size == NULL)
+			fatal(".o cannot appear before .i");
+		    if (fscanf(fp, "%d", &(cube.part_size[cube.num_vars-1]))!=1)
+			fatal("error reading .o");
+		    cube_setup();
+		    PLA_labels(PLA);
+		}
+
+	    /* .mv gives the cube size for a multiple-valued function */
+	    } else if (equal(word, "mv")) {
+		if (cube.fullset != NULL) {
+		    (void) fprintf(stderr, "extra .mv ignored\n");
+		    skip_line(fp, stdout, /* echo */ FALSE);
+		} else {
+		    if (cube.part_size != NULL)
+			fatal("cannot mix .i and .mv");
+		    if (fscanf(fp,"%d %d",
+			&cube.num_vars,&cube.num_binary_vars) != 2)
+			 fatal("error reading .mv");
+		    if (cube.num_binary_vars < 0)
+fatal("num_binary_vars (second field of .mv) cannot be negative");
+		    if (cube.num_vars < cube.num_binary_vars)
+			fatal(
+"num_vars (1st field of .mv) must exceed num_binary_vars (2nd field of .mv)");
+		    cube.part_size = ALLOC(int, cube.num_vars);
+		    for(var=cube.num_binary_vars; var < cube.num_vars; var++)
+			if (fscanf(fp, "%d", &(cube.part_size[var])) != 1)
+			    fatal("error reading .mv");
+		    cube_setup();
+		    PLA_labels(PLA);
+		}
+
+	    /* .p gives the number of product terms -- we ignore it */
+	    } else if (equal(word, "p"))
+		(void) fscanf(fp, "%d", &np);
+	    /* .e and .end specify the end of the file */
+	    else if (equal(word, "e") || equal(word,"end")) {
+		if (cube.fullset == NULL) {
+		    /* fatal("unknown PLA size, need .i/.o or .mv");*/
+                } else if (PLA->F == NULL) {
+                    PLA->F = new_cover(10);
+                    PLA->D = new_cover(10);
+                    PLA->R = new_cover(10);
+                }
+		return;
+	    }
+	    /* .kiss turns on the kiss-hack option */
+	    else if (equal(word, "kiss"))
+		kiss = TRUE;
+
+	    /* .type specifies a logical type for the PLA */
+	    else if (equal(word, "type")) {
+		(void) get_word(fp, word);
+		for(i = 0; pla_types[i].key != 0; i++)
+		    if (equal(pla_types[i].key + 1, word)) {
+			PLA->pla_type = pla_types[i].value;
+			break;
+		    }
+		if (pla_types[i].key == 0)
+		    fatal("unknown type in .type command");
+
+	    /* parse the labels */
+	    } else if (equal(word, "ilb")) {
+		if (cube.fullset == NULL)
+		    fatal("PLA size must be declared before .ilb or .ob");
+		if (PLA->label == NULL)
+		    PLA_labels(PLA);
+		for(var = 0; var < cube.num_binary_vars; var++) {
+		    (void) get_word(fp, word);
+		    i = cube.first_part[var];
+		    PLA->label[i+1] = util_strsav(word);
+		    PLA->label[i] = ALLOC(char, strlen(word) + 6);
+		    (void) sprintf(PLA->label[i], "%s.bar", word);
+		}
+	    } else if (equal(word, "ob")) {
+		if (cube.fullset == NULL)
+		    fatal("PLA size must be declared before .ilb or .ob");
+		if (PLA->label == NULL)
+		    PLA_labels(PLA);
+		var = cube.num_vars - 1;
+		for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+		    (void) get_word(fp, word);
+		    PLA->label[i] = util_strsav(word);
+		}
+	    /* .label assigns labels to multiple-valued variables */
+	    } else if (equal(word, "label")) {
+		if (cube.fullset == NULL)
+		    fatal("PLA size must be declared before .label");
+		if (PLA->label == NULL)
+		    PLA_labels(PLA);
+		if (fscanf(fp, "var=%d", &var) != 1)
+		    fatal("Error reading labels");
+		for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+		    (void) get_word(fp, word);
+		    PLA->label[i] = util_strsav(word);
+		}
+
+	    } else if (equal(word, "symbolic")) {
+		symbolic_t *newlist, *p1;
+		if (read_symbolic(fp, PLA, word, &newlist)) {
+		    if (PLA->symbolic == NIL(symbolic_t)) {
+			PLA->symbolic = newlist;
+		    } else {
+			for(p1=PLA->symbolic;p1->next!=NIL(symbolic_t);
+			    p1=p1->next){
+			}
+			p1->next = newlist;
+		    }
+		} else {
+		    fatal("error reading .symbolic");
+		}
+
+	    } else if (equal(word, "symbolic-output")) {
+		symbolic_t *newlist, *p1;
+		if (read_symbolic(fp, PLA, word, &newlist)) {
+		    if (PLA->symbolic_output == NIL(symbolic_t)) {
+			PLA->symbolic_output = newlist;
+		    } else {
+			for(p1=PLA->symbolic_output;p1->next!=NIL(symbolic_t);
+			    p1=p1->next){
+			}
+			p1->next = newlist;
+		    }
+		} else {
+		    fatal("error reading .symbolic-output");
+		}
+		
+	    /* .phase allows a choice of output phases */
+	    } else if (equal(word, "phase")) {
+		if (cube.fullset == NULL)
+		    fatal("PLA size must be declared before .phase");
+		if (PLA->phase != NULL) {
+		    (void) fprintf(stderr, "extra .phase ignored\n");
+		    skip_line(fp, stdout, /* echo */ FALSE);
+		} else {
+		    do ch = getc(fp); while (ch == ' ' || ch == '\t');
+		    (void) ungetc(ch, fp);
+		    PLA->phase = set_save(cube.fullset);
+		    last = cube.last_part[cube.num_vars - 1];
+		    for(i=cube.first_part[cube.num_vars - 1]; i <= last; i++)
+			if ((ch = getc(fp)) == '0')
+			    set_remove(PLA->phase, i);
+			else if (ch != '1')
+			    fatal("only 0 or 1 allowed in phase description");
+		}
+
+	    /* .pair allows for bit-pairing input variables */
+	    } else if (equal(word, "pair")) {
+		int j;
+		if (PLA->pair != NULL) {
+		    (void) fprintf(stderr, "extra .pair ignored\n");
+		} else {
+		    ppair pair;
+		    PLA->pair = pair = ALLOC(pair_t, 1);
+		    if (fscanf(fp, "%d", &(pair->cnt)) != 1)
+			fatal("syntax error in .pair");
+		    pair->var1 = ALLOC(int, pair->cnt);
+		    pair->var2 = ALLOC(int, pair->cnt);
+		    for(i = 0; i < pair->cnt; i++) {
+			(void) get_word(fp, word);
+			if (word[0] == '(') (void) strcpy(word, word+1);
+			if (label_index(PLA, word, &var, &j)) {
+			    pair->var1[i] = var+1;
+			} else {
+			    fatal("syntax error in .pair");
+			}
+
+			(void) get_word(fp, word);
+			if (word[strlen(word)-1] == ')') {
+			    word[strlen(word)-1]='\0';
+			}
+			if (label_index(PLA, word, &var, &j)) {
+			    pair->var2[i] = var+1;
+			} else {
+			    fatal("syntax error in .pair");
+			}
+		    }
+		}
+		
+	    } else {
+		if (echo_unknown_commands)
+		    printf("%c%s ", ch, word);
+		skip_line(fp, stdout, echo_unknown_commands);
+	    }
+	    break;
+	default:
+	    (void) ungetc(ch, fp);
+	    if (cube.fullset == NULL) {
+/*		fatal("unknown PLA size, need .i/.o or .mv");*/
+		if (echo_comments)
+		    putchar('#');
+		skip_line(fp, stdout, echo_comments);
+		break;
+	    }
+	    if (PLA->F == NULL) {
+		PLA->F = new_cover(10);
+		PLA->D = new_cover(10);
+		PLA->R = new_cover(10);
+	    }
+	    read_cube(fp, PLA);
+    }
+    goto loop;
+}
+/*
+    read_pla -- read a PLA from a file
+
+    Input stops when ".e" is encountered in the input file, or upon reaching
+    end of file.
+
+    Returns the PLA in the variable PLA after massaging the "symbolic"
+    representation into a positional cube notation of the ON-set, OFF-set,
+    and the DC-set.
+
+    needs_dcset and needs_offset control the computation of the OFF-set
+    and DC-set (i.e., if either needs to be computed, then it will be
+    computed via complement only if the corresponding option is TRUE.)
+    pla_type specifies the interpretation to be used when reading the
+    PLA.
+
+    The phase of the output functions is adjusted according to the
+    global option "pos" or according to an imbedded .phase option in
+    the input file.  Note that either phase option implies that the
+    OFF-set be computed regardless of whether the caller needs it
+    explicitly or not.
+
+    Bit pairing of the binary variables is performed according to an
+    imbedded .pair option in the input file.
+
+    The global cube structure also reflects the sizes of the PLA which
+    was just read.  If these fields have already been set, then any
+    subsequent PLA must conform to these sizes.
+
+    The global flags trace and summary control the output produced
+    during the read.
+
+    Returns a status code as a result:
+	EOF (-1) : End of file reached before any data was read
+	> 0	 : Operation successful
+*/
+
+int read_pla(fp, needs_dcset, needs_offset, pla_type, PLA_return)
+IN FILE *fp;
+IN bool needs_dcset, needs_offset;
+IN int pla_type;
+OUT pPLA *PLA_return;
+{
+    pPLA PLA;
+    int i, second, third;
+    long time;
+    cost_t cost;
+
+    /* Allocate and initialize the PLA structure */
+    PLA = *PLA_return = new_PLA();
+    PLA->pla_type = pla_type;
+
+    /* Read the pla */
+    time = ptime();
+    parse_pla(fp, PLA);
+
+    /* Check for nothing on the file -- implies reached EOF */
+    if (PLA->F == NULL) {
+	return EOF;
+    }
+
+    /* This hack merges the next-state field with the outputs */
+    for(i = 0; i < cube.num_vars; i++) {
+	cube.part_size[i] = ABS(cube.part_size[i]);
+    }
+    if (kiss) {
+	third = cube.num_vars - 3;
+	second = cube.num_vars - 2;
+	if (cube.part_size[third] != cube.part_size[second]) {
+	    (void) fprintf(stderr," with .kiss option, third to last and second\n");
+	    (void) fprintf(stderr, "to last variables must be the same size.\n");
+	    return EOF;
+	}
+	for(i = 0; i < cube.part_size[second]; i++) {
+	    PLA->label[i + cube.first_part[second]] =
+		util_strsav(PLA->label[i + cube.first_part[third]]);
+	}
+	cube.part_size[second] += cube.part_size[cube.num_vars-1];
+	cube.num_vars--;
+	setdown_cube();
+	cube_setup();
+    }
+
+    if (trace) {
+	totals(time, READ_TIME, PLA->F, &cost);
+    }
+
+    /* Decide how to break PLA into ON-set, OFF-set and DC-set */
+    time = ptime();
+    if (pos || PLA->phase != NULL || PLA->symbolic_output != NIL(symbolic_t)) {
+	needs_offset = TRUE;
+    }
+    if (needs_offset && (PLA->pla_type==F_type || PLA->pla_type==FD_type)) {
+	free_cover(PLA->R);
+	PLA->R = complement(cube2list(PLA->F, PLA->D));
+    } else if (needs_dcset && PLA->pla_type == FR_type) {
+	pcover X;
+	free_cover(PLA->D);
+	/* hack, why not? */
+	X = d1merge(sf_join(PLA->F, PLA->R), cube.num_vars - 1);
+	PLA->D = complement(cube1list(X));
+	free_cover(X);
+    } else if (PLA->pla_type == R_type || PLA->pla_type == DR_type) {
+	free_cover(PLA->F);
+	PLA->F = complement(cube2list(PLA->D, PLA->R));
+    }
+
+    if (trace) {
+	totals(time, COMPL_TIME, PLA->R, &cost);
+    }
+
+    /* Check for phase rearrangement of the functions */
+    if (pos) {
+	pcover onset = PLA->F;
+	PLA->F = PLA->R;
+	PLA->R = onset;
+	PLA->phase = new_cube();
+	set_diff(PLA->phase, cube.fullset, cube.var_mask[cube.num_vars-1]);
+    } else if (PLA->phase != NULL) {
+	(void) set_phase(PLA);
+    }
+
+    /* Setup minimization for two-bit decoders */
+    if (PLA->pair != (ppair) NULL) {
+	set_pair(PLA);
+    }
+
+    if (PLA->symbolic != NIL(symbolic_t)) {
+	EXEC(map_symbolic(PLA), "MAP-INPUT  ", PLA->F);
+    }
+    if (PLA->symbolic_output != NIL(symbolic_t)) {
+	EXEC(map_output_symbolic(PLA), "MAP-OUTPUT ", PLA->F);
+	if (needs_offset) {
+	    free_cover(PLA->R);
+EXECUTE(PLA->R=complement(cube2list(PLA->F,PLA->D)), COMPL_TIME, PLA->R, cost);
+	}
+    }
+
+    return 1;
+}
+
+void PLA_summary(PLA)
+pPLA PLA;
+{
+    int var, i;
+    symbolic_list_t *p2;
+    symbolic_t *p1;
+
+    printf("# PLA is %s", PLA->filename);
+    if (cube.num_binary_vars == cube.num_vars - 1)
+	printf(" with %d inputs and %d outputs\n",
+	    cube.num_binary_vars, cube.part_size[cube.num_vars - 1]);
+    else {
+	printf(" with %d variables (%d binary, mv sizes",
+	    cube.num_vars, cube.num_binary_vars);
+	for(var = cube.num_binary_vars; var < cube.num_vars; var++)
+	    printf(" %d", cube.part_size[var]);
+	printf(")\n");
+    }
+    printf("# ON-set cost is  %s\n", print_cost(PLA->F));
+    printf("# OFF-set cost is %s\n", print_cost(PLA->R));
+    printf("# DC-set cost is  %s\n", print_cost(PLA->D));
+    if (PLA->phase != NULL)
+	printf("# phase is %s\n", pc1(PLA->phase));
+    if (PLA->pair != NULL) {
+	printf("# two-bit decoders:");
+	for(i = 0; i < PLA->pair->cnt; i++)
+	    printf(" (%d %d)", PLA->pair->var1[i], PLA->pair->var2[i]);
+	printf("\n");
+    }
+    if (PLA->symbolic != NIL(symbolic_t)) {
+	for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+	    printf("# symbolic: ");
+	    for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+		printf(" %d", p2->variable);
+	    }
+	    printf("\n");
+	}
+    }
+    if (PLA->symbolic_output != NIL(symbolic_t)) {
+	for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1->next) {
+	    printf("# output symbolic: ");
+	    for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+		printf(" %d", p2->pos);
+	    }
+	    printf("\n");
+	}
+    }
+    (void) fflush(stdout);
+}
+
+
+pPLA new_PLA()
+{
+    pPLA PLA;
+
+    PLA = ALLOC(PLA_t, 1);
+    PLA->F = PLA->D = PLA->R = (pcover) NULL;
+    PLA->phase = (pcube) NULL;
+    PLA->pair = (ppair) NULL;
+    PLA->label = (char **) NULL;
+    PLA->filename = (char *) NULL;
+    PLA->pla_type = 0;
+    PLA->symbolic = NIL(symbolic_t);
+    PLA->symbolic_output = NIL(symbolic_t);
+    return PLA;
+}
+
+
+void PLA_labels(PLA)
+pPLA PLA;
+{
+    int i;
+
+    PLA->label = ALLOC(char *, cube.size);
+    for(i = 0; i < cube.size; i++)
+	PLA->label[i] = (char *) NULL;
+}
+
+
+void free_PLA(PLA)
+pPLA PLA;
+{
+    symbolic_list_t *p2, *p2next;
+    symbolic_t *p1, *p1next;
+    int i;
+
+    if (PLA->F != (pcover) NULL)
+	free_cover(PLA->F);
+    if (PLA->R != (pcover) NULL)
+	free_cover(PLA->R);
+    if (PLA->D != (pcover) NULL)
+	free_cover(PLA->D);
+    if (PLA->phase != (pcube) NULL)
+	free_cube(PLA->phase);
+    if (PLA->pair != (ppair) NULL) {
+	FREE(PLA->pair->var1);
+	FREE(PLA->pair->var2);
+	FREE(PLA->pair);
+    }
+    if (PLA->label != NULL) {
+	for(i = 0; i < cube.size; i++)
+	    if (PLA->label[i] != NULL)
+		FREE(PLA->label[i]);
+	FREE(PLA->label);
+    }
+    if (PLA->filename != NULL) {
+	FREE(PLA->filename);
+    }
+    for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1next) {
+	for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) {
+	    p2next = p2->next;
+	    FREE(p2);
+	}
+	p1next = p1->next;
+	FREE(p1);
+    }
+    PLA->symbolic = NIL(symbolic_t);
+    for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1next) {
+	for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) {
+	    p2next = p2->next;
+	    FREE(p2);
+	}
+	p1next = p1->next;
+	FREE(p1);
+    }
+    PLA->symbolic_output = NIL(symbolic_t);
+    FREE(PLA);
+}
+
+
+int read_symbolic(fp, PLA, word, retval)
+FILE *fp;
+pPLA PLA;
+char *word;		/* scratch string for words */
+symbolic_t **retval;
+{
+    symbolic_list_t *listp, *prev_listp;
+    symbolic_label_t *labelp, *prev_labelp;
+    symbolic_t *newlist;
+    int i, var;
+
+    newlist = ALLOC(symbolic_t, 1);
+    newlist->next = NIL(symbolic_t);
+    newlist->symbolic_list = NIL(symbolic_list_t);
+    newlist->symbolic_list_length = 0;
+    newlist->symbolic_label = NIL(symbolic_label_t);
+    newlist->symbolic_label_length = 0;
+    prev_listp = NIL(symbolic_list_t);
+    prev_labelp = NIL(symbolic_label_t);
+
+    for(;;) {
+	(void) get_word(fp, word);
+	if (equal(word, ";"))
+	    break;
+	if (label_index(PLA, word, &var, &i)) {
+	    listp = ALLOC(symbolic_list_t, 1);
+	    listp->variable = var;
+	    listp->pos = i;
+	    listp->next = NIL(symbolic_list_t);
+	    if (prev_listp == NIL(symbolic_list_t)) {
+		newlist->symbolic_list = listp;
+	    } else {
+		prev_listp->next = listp;
+	    }
+	    prev_listp = listp;
+	    newlist->symbolic_list_length++;
+	} else {
+	    return FALSE;
+	}
+    }
+
+    for(;;) {
+	(void) get_word(fp, word);
+	if (equal(word, ";"))
+	    break;
+	labelp = ALLOC(symbolic_label_t, 1);
+	labelp->label = util_strsav(word);
+	labelp->next = NIL(symbolic_label_t);
+	if (prev_labelp == NIL(symbolic_label_t)) {
+	    newlist->symbolic_label = labelp;
+	} else {
+	    prev_labelp->next = labelp;
+	}
+	prev_labelp = labelp;
+	newlist->symbolic_label_length++;
+    }
+
+    *retval = newlist;
+    return TRUE;
+}
+
+
+int label_index(PLA, word, varp, ip)
+pPLA PLA;
+char *word;
+int *varp;
+int *ip;
+{
+    int var, i;
+
+    if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char)) {
+	if (sscanf(word, "%d", varp) == 1) {
+	    *ip = *varp;
+	    return TRUE;
+	}
+    } else {
+	for(var = 0; var < cube.num_vars; var++) {
+	    for(i = 0; i < cube.part_size[var]; i++) {
+		if (equal(PLA->label[cube.first_part[var]+i], word)) {
+		    *varp = var;
+		    *ip = i;
+		    return TRUE;
+		}
+	    }
+	}
+    }
+    return FALSE;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/cvrm.c b/abc-build/src/misc/espresso/cvrm.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/cvrm.c
@@ -0,0 +1,544 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+    module: cvrm.c
+    Purpose: miscellaneous cover manipulation
+	a) verify two covers are equal, check consistency of a cover
+	b) unravel a multiple-valued cover into minterms
+	c) sort covers
+*/
+
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+static void cb_unravel(c, start, end, startbase, B1)
+IN register pcube c;
+IN int start, end;
+IN pcube startbase;
+INOUT pcover B1;
+{
+    pcube base = cube.temp[0], p, last;
+    int expansion, place, skip, var, size, offset;
+    register int i, j, k, n;
+
+    /* Determine how many cubes it will blow up into, and create a mask
+	for those parts that have only a single coordinate
+    */
+    expansion = 1;
+    (void) set_copy(base, startbase);
+    for(var = start; var <= end; var++) {
+	if ((size = set_dist(c, cube.var_mask[var])) < 2) {
+	    (void) set_or(base, base, cube.var_mask[var]);
+	} else {
+	    expansion *= size;
+	}
+    }
+    (void) set_and(base, c, base);
+
+    /* Add the unravelled sets starting at the last element of B1 */
+    offset = B1->count;
+    B1->count += expansion;
+    foreach_remaining_set(B1, last, GETSET(B1, offset-1), p) {
+	INLINEset_copy(p, base);
+    }
+
+    place = expansion;
+    for(var = start; var <= end; var++) {
+	if ((size = set_dist(c, cube.var_mask[var])) > 1) {
+	    skip = place;
+	    place = place / size;
+	    n = 0;
+	    for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+		if (is_in_set(c, i)) {
+		    for(j = n; j < expansion; j += skip) {
+			for(k = 0; k < place; k++) {
+			    p = GETSET(B1, j+k+offset);
+			    (void) set_insert(p, i);
+			}
+		    }
+		    n += place;
+		}
+	    }
+	}
+    }
+}
+
+
+pcover unravel_range(B, start, end)
+IN pcover B;
+IN int start, end;
+{
+    pcover B1;
+    int var, total_size, expansion, size;
+    register pcube p, last, startbase = cube.temp[1];
+
+    /* Create the starting base for those variables not being unravelled */
+    (void) set_copy(startbase, cube.emptyset);
+    for(var = 0; var < start; var++)
+	(void) set_or(startbase, startbase, cube.var_mask[var]);
+    for(var = end+1; var < cube.num_vars; var++)
+	(void) set_or(startbase, startbase, cube.var_mask[var]);
+
+    /* Determine how many cubes it will blow up into */
+    total_size = 0;
+    foreach_set(B, last, p) {
+	expansion = 1;
+	for(var = start; var <= end; var++)
+	    if ((size = set_dist(p, cube.var_mask[var])) >= 2)
+		if ((expansion *= size) > 1000000)
+		    fatal("unreasonable expansion in unravel");
+	total_size += expansion;
+    }
+
+    /* We can now allocate a cover of exactly the correct size */
+    B1 = new_cover(total_size);
+    foreach_set(B, last, p) {
+	cb_unravel(p, start, end, startbase, B1);
+    }
+    free_cover(B);
+    return B1;
+}
+
+
+pcover unravel(B, start)
+IN pcover B;
+IN int start;
+{
+    return unravel_range(B, start, cube.num_vars-1);
+}
+
+/* lex_sort -- sort cubes in a standard lexical fashion */
+pcover lex_sort(T)
+pcover T;
+{
+    pcover T1 = sf_unlist(sf_sort(T, lex_order), T->count, T->sf_size);
+    free_cover(T);
+    return T1;
+}
+
+
+/* size_sort -- sort cubes by their size */
+pcover size_sort(T)
+pcover T;
+{
+    pcover T1 = sf_unlist(sf_sort(T, descend), T->count, T->sf_size);
+    free_cover(T);
+    return T1;
+}
+
+
+/*  mini_sort -- sort cubes according to the heuristics of mini */
+pcover mini_sort(F, compare)
+pcover F;
+int (*compare)();
+{
+    register int *count, cnt, n = cube.size, i;
+    register pcube p, last;
+    pcover F_sorted;
+    pcube *F1;
+
+    /* Perform a column sum over the set family */
+    count = sf_count(F);
+
+    /* weight is "inner product of the cube and the column sums" */
+    foreach_set(F, last, p) {
+	cnt = 0;
+	for(i = 0; i < n; i++)
+	    if (is_in_set(p, i))
+		cnt += count[i];
+	PUTSIZE(p, cnt);
+    }
+    FREE(count);
+
+    /* use qsort to sort the array */
+    qsort((char *) (F1 = sf_list(F)), F->count, sizeof(pcube), compare);
+    F_sorted = sf_unlist(F1, F->count, F->sf_size);
+    free_cover(F);
+
+    return F_sorted;
+}
+
+
+/* sort_reduce -- Espresso strategy for ordering the cubes before reduction */
+pcover sort_reduce(T)
+IN pcover T;
+{
+    register pcube p, last, largest = NULL;
+    register int bestsize = -1, size, n = cube.num_vars;
+    pcover T_sorted;
+    pcube *T1;
+
+    if (T->count == 0)
+	return T;
+
+    /* find largest cube */
+    foreach_set(T, last, p)
+	if ((size = set_ord(p)) > bestsize)
+	    largest = p, bestsize = size;
+
+    foreach_set(T, last, p)
+	PUTSIZE(p, ((n - cdist(largest,p)) << 7) + MIN(set_ord(p),127));
+
+    qsort((char *) (T1 = sf_list(T)), T->count, sizeof(pcube), (int (*)()) descend);
+    T_sorted = sf_unlist(T1, T->count, T->sf_size);
+    free_cover(T);
+
+    return T_sorted;
+}
+
+pcover random_order(F)
+register pcover F;
+{
+    pset temp;
+    register int i, k;
+#ifdef RANDOM
+    long random();
+#endif
+
+    temp = set_new(F->sf_size);
+    for(i = F->count - 1; i > 0; i--) {
+	/* Choose a random number between 0 and i */
+#ifdef RANDOM
+	k = random() % i;
+#else
+	/* this is not meant to be really used; just provides an easy
+	   "out" if random() and srandom() aren't around
+	*/
+	k = (i*23 + 997) % i;
+#endif
+	/* swap sets i and k */
+	(void) set_copy(temp, GETSET(F, k));
+	(void) set_copy(GETSET(F, k), GETSET(F, i));
+	(void) set_copy(GETSET(F, i), temp);
+    }
+    set_free(temp);
+    return F;
+}
+
+/*
+ *  cubelist_partition -- take a cubelist T and see if it has any components;
+ *  if so, return cubelist's of the two partitions A and B; the return value
+ *  is the size of the partition; if not, A and B
+ *  are undefined and the return value is 0
+ */
+int cubelist_partition(T, A, B, comp_debug)
+pcube *T;			/* a list of cubes */
+pcube **A, **B;			/* cubelist of partition and remainder */
+unsigned int comp_debug;
+{
+    register pcube *T1, p, seed, cof;
+    pcube *A1, *B1;
+    bool change;
+    int count, numcube;
+
+    numcube = CUBELISTSIZE(T);
+
+    /* Mark all cubes -- covered cubes belong to the partition */
+    for(T1 = T+2; (p = *T1++) != NULL; ) {
+	RESET(p, COVERED);
+    }
+
+    /*
+     *  Extract a partition from the cubelist T; start with the first cube as a
+     *  seed, and then pull in all cubes which share a variable with the seed;
+     *  iterate until no new cubes are brought into the partition.
+     */
+    seed = set_save(T[2]);
+    cof = T[0];
+    SET(T[2], COVERED);
+    count = 1;
+
+    do {
+	change = FALSE;
+	for(T1 = T+2; (p = *T1++) != NULL; ) {
+	    if (! TESTP(p, COVERED) && ccommon(p, seed, cof)) {
+		INLINEset_and(seed, seed, p);
+		SET(p, COVERED);
+		change = TRUE;
+		count++;
+	    }
+	
+	}
+    } while (change);
+
+    set_free(seed);
+
+    if (comp_debug) {
+	(void) printf("COMPONENT_REDUCTION: split into %d %d\n",
+	    count, numcube - count);
+    }
+
+    if (count != numcube) {
+	/* Allocate and setup the cubelist's for the two partitions */
+	*A = A1 = ALLOC(pcube, numcube+3);
+	*B = B1 = ALLOC(pcube, numcube+3);
+	(*A)[0] = set_save(T[0]);
+	(*B)[0] = set_save(T[0]);
+	A1 = *A + 2;
+	B1 = *B + 2;
+
+	/* Loop over the cubes in T and distribute to A and B */
+	for(T1 = T+2; (p = *T1++) != NULL; ) {
+	    if (TESTP(p, COVERED)) {
+		*A1++ = p;
+	    } else {
+		*B1++ = p;
+	    }
+	}
+
+	/* Stuff needed at the end of the cubelist's */
+	*A1++ = NULL;
+	(*A)[1] = (pcube) A1;
+	*B1++ = NULL;
+	(*B)[1] = (pcube) B1;
+    }
+
+    return numcube - count;
+}
+
+/*
+ *  quick cofactor against a single output function
+ */
+pcover cof_output(T, i)
+pcover T;
+register int i;
+{
+    pcover T1;
+    register pcube p, last, pdest, mask;
+
+    mask = cube.var_mask[cube.output];
+    T1 = new_cover(T->count);
+    foreach_set(T, last, p) {
+	if (is_in_set(p, i)) {
+	    pdest = GETSET(T1, T1->count++);
+	    INLINEset_or(pdest, p, mask);
+	    RESET(pdest, PRIME);
+	}
+    }
+    return T1;
+}
+
+
+/*
+ *  quick intersection against a single output function
+ */
+pcover uncof_output(T, i)
+pcover T;
+int i;
+{
+    register pcube p, last, mask;
+
+    if (T == NULL) {
+	return T;
+    }
+
+    mask = cube.var_mask[cube.output];
+    foreach_set(T, last, p) {
+	INLINEset_diff(p, p, mask);
+	set_insert(p, i);
+    }
+    return T;
+}
+
+
+/*
+ *  A generic routine to perform an operation for each output function
+ *
+ *  func() is called with a PLA for each output function (with the output
+ *  part effectively removed).
+ *  func1() is called after reforming the equivalent output function
+ *
+ *  Each function returns TRUE if process is to continue
+ */
+void foreach_output_function(PLA, func, func1)
+pPLA PLA;
+int (*func)();
+int (*func1)();
+{
+    pPLA PLA1;
+    int i;
+
+    /* Loop for each output function */
+    for(i = 0; i < cube.part_size[cube.output]; i++) {
+
+	/* cofactor on the output part */
+	PLA1 = new_PLA();
+	PLA1->F = cof_output(PLA->F, i + cube.first_part[cube.output]);
+	PLA1->R = cof_output(PLA->R, i + cube.first_part[cube.output]);
+	PLA1->D = cof_output(PLA->D, i + cube.first_part[cube.output]);
+
+	/* Call a routine to do something with the cover */
+	if ((*func)(PLA1, i) == 0) {
+	    free_PLA(PLA1);
+	    return;
+	}
+
+	/* intersect with the particular output part again */
+	PLA1->F = uncof_output(PLA1->F, i + cube.first_part[cube.output]);
+	PLA1->R = uncof_output(PLA1->R, i + cube.first_part[cube.output]);
+	PLA1->D = uncof_output(PLA1->D, i + cube.first_part[cube.output]);
+
+	/* Call a routine to do something with the final result */
+	if ((*func1)(PLA1, i) == 0) {
+	    free_PLA(PLA1);
+	    return;
+	}
+
+	/* Cleanup for next go-around */
+	free_PLA(PLA1);
+	
+
+    }
+}
+
+static pcover Fmin;
+static pcube phase;
+
+/*
+ *  minimize each output function individually
+ */
+void so_espresso(PLA, strategy)
+pPLA PLA;
+int strategy;
+{
+    Fmin = new_cover(PLA->F->count);
+    if (strategy == 0) {
+	foreach_output_function(PLA, so_do_espresso, so_save);
+    } else {
+	foreach_output_function(PLA, so_do_exact, so_save);
+    }
+    sf_free(PLA->F);
+    PLA->F = Fmin;
+}
+
+
+/*
+ *  minimize each output function, choose function or complement based on the
+ *  one with the fewer number of terms
+ */
+void so_both_espresso(PLA, strategy)
+pPLA PLA;
+int strategy;
+{
+    phase = set_save(cube.fullset);
+    Fmin = new_cover(PLA->F->count);
+    if (strategy == 0) {
+	foreach_output_function(PLA, so_both_do_espresso, so_both_save);
+    } else {
+	foreach_output_function(PLA, so_both_do_exact, so_both_save);
+    }
+    sf_free(PLA->F);
+    PLA->F = Fmin;
+    PLA->phase = phase;
+}
+
+
+int so_do_espresso(PLA, i)
+pPLA PLA;
+int i;
+{
+    char word[32];
+
+    /* minimize the single-output function (on-set) */
+    skip_make_sparse = 1;
+    (void) sprintf(word, "ESPRESSO-POS(%d)", i);
+    EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F);
+    return 1;
+}
+
+
+int so_do_exact(PLA, i)
+pPLA PLA;
+int i;
+{
+    char word[32];
+
+    /* minimize the single-output function (on-set) */
+    skip_make_sparse = 1;
+    (void) sprintf(word, "EXACT-POS(%d)", i);
+    EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F);
+    return 1;
+}
+
+
+/*ARGSUSED*/
+int so_save(PLA, i)
+pPLA PLA;
+int i;
+{
+    Fmin = sf_append(Fmin, PLA->F);	/* disposes of PLA->F */
+    PLA->F = NULL;
+    return 1;
+}
+
+
+int so_both_do_espresso(PLA, i)
+pPLA PLA;
+int i;
+{
+    char word[32];
+
+    /* minimize the single-output function (on-set) */
+    (void) sprintf(word, "ESPRESSO-POS(%d)", i);
+    skip_make_sparse = 1;
+    EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F);
+
+    /* minimize the single-output function (off-set) */
+    (void) sprintf(word, "ESPRESSO-NEG(%d)", i);
+    skip_make_sparse = 1;
+    EXEC_S(PLA->R = espresso(PLA->R, PLA->D, PLA->F), word, PLA->R);
+
+    return 1;
+}
+
+
+int so_both_do_exact(PLA, i)
+pPLA PLA;
+int i;
+{
+    char word[32];
+
+    /* minimize the single-output function (on-set) */
+    (void) sprintf(word, "EXACT-POS(%d)", i);
+    skip_make_sparse = 1;
+    EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F);
+
+    /* minimize the single-output function (off-set) */
+    (void) sprintf(word, "EXACT-NEG(%d)", i);
+    skip_make_sparse = 1;
+    EXEC_S(PLA->R = minimize_exact(PLA->R, PLA->D, PLA->F, 1), word, PLA->R);
+
+    return 1;
+}
+
+
+int so_both_save(PLA, i)
+pPLA PLA;
+int i;
+{
+    if (PLA->F->count > PLA->R->count) {
+	sf_free(PLA->F);
+	PLA->F = PLA->R;
+	PLA->R = NULL;
+	i += cube.first_part[cube.output];
+	set_remove(phase, i);
+    } else {
+	sf_free(PLA->R);
+	PLA->R = NULL;
+    }
+    Fmin = sf_append(Fmin, PLA->F);
+    PLA->F = NULL;
+    return 1;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/cvrmisc.c b/abc-build/src/misc/espresso/cvrmisc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/cvrmisc.c
@@ -0,0 +1,147 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/* cost -- compute the cost of a cover */
+void cover_cost(F, cost)
+IN pcover F;
+INOUT pcost cost;
+{
+    register pcube p, last;
+    pcube *T;
+    int var;
+
+    /* use the routine used by cofactor to decide splitting variables */
+    massive_count(T = cube1list(F));
+    free_cubelist(T);
+
+    cost->cubes = F->count;
+    cost->total = cost->in = cost->out = cost->mv = cost->primes = 0;
+
+    /* Count transistors (zeros) for each binary variable (inputs) */
+    for(var = 0; var < cube.num_binary_vars; var++)
+	cost->in += cdata.var_zeros[var];
+
+    /* Count transistors for each mv variable based on sparse/dense */
+    for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++)
+	if (cube.sparse[var])
+	    cost->mv += F->count * cube.part_size[var] - cdata.var_zeros[var];
+	else
+	    cost->mv += cdata.var_zeros[var];
+
+    /* Count the transistors (ones) for the output variable */
+    if (cube.num_binary_vars != cube.num_vars) {
+	var = cube.num_vars - 1;
+	cost->out = F->count * cube.part_size[var] - cdata.var_zeros[var];
+    }
+
+    /* Count the number of nonprime cubes */
+    foreach_set(F, last, p)
+	cost->primes += TESTP(p, PRIME) != 0;
+
+    /* Count the total number of literals */
+    cost->total = cost->in + cost->out + cost->mv;
+}
+
+
+/* fmt_cost -- return a string which reports the "cost" of a cover */
+char *fmt_cost(cost)
+IN pcost cost;
+{
+    static char s[200];
+
+    if (cube.num_binary_vars == cube.num_vars - 1)
+	(void) sprintf(s, "c=%d(%d) in=%d out=%d tot=%d",
+	    cost->cubes, cost->cubes - cost->primes, cost->in,
+	    cost->out, cost->total);
+    else
+	(void) sprintf(s, "c=%d(%d) in=%d mv=%d out=%d",
+	   cost->cubes, cost->cubes - cost->primes, cost->in,
+	   cost->mv, cost->out);
+    return s;
+}
+
+
+char *print_cost(F)
+IN pcover F;
+{
+    cost_t cost;
+    cover_cost(F, &cost);
+    return fmt_cost(&cost);
+}
+
+
+/* copy_cost -- copy a cost function from s to d */
+void copy_cost(s, d)
+pcost s, d;
+{
+    d->cubes = s->cubes;
+    d->in = s->in;
+    d->out = s->out;
+    d->mv = s->mv;
+    d->total = s->total;
+    d->primes = s->primes;
+}
+
+
+/* size_stamp -- print single line giving the size of a cover */
+void size_stamp(T, name)
+IN pcover T;
+IN char *name;
+{
+    (void) printf("# %s\tCost is %s\n", name, print_cost(T));
+    (void) fflush(stdout);
+}
+
+
+/* print_trace -- print a line reporting size and time after a function */
+void print_trace(T, name, time)
+pcover T;
+char *name;
+long time;
+{
+    (void) printf("# %s\tTime was %s, cost is %s\n",
+	name, print_time(time), print_cost(T));
+    (void) fflush(stdout);
+}
+
+
+/* totals -- add time spent in the function into the totals */
+void totals(time, i, T, cost)
+long time;
+int i;
+pcover T;
+pcost cost;
+{
+    time = ptime() - time;
+    total_time[i] += time;
+    total_calls[i]++;
+    cover_cost(T, cost);
+    if (trace) {
+	(void) printf("# %s\tTime was %s, cost is %s\n",
+	    total_name[i], print_time(time), fmt_cost(cost));
+	(void) fflush(stdout);
+    }
+}
+
+
+/* fatal -- report fatal error message and take a dive */
+void fatal(s)
+char *s;
+{
+    (void) fprintf(stderr, "espresso: %s\n", s);
+    exit(1);
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/cvrout.c b/abc-build/src/misc/espresso/cvrout.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/cvrout.c
@@ -0,0 +1,614 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+    module: cvrout.c
+    purpose: cube and cover output routines
+*/
+
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+void fprint_pla(fp, PLA, output_type)
+INOUT FILE *fp;
+IN pPLA PLA;
+IN int output_type;
+{
+    int num;
+    register pcube last, p;
+
+    if ((output_type & CONSTRAINTS_type) != 0) {
+	output_symbolic_constraints(fp, PLA, 0);
+	output_type &= ~ CONSTRAINTS_type;
+	if (output_type == 0) {
+	    return;
+	}
+    }
+
+    if ((output_type & SYMBOLIC_CONSTRAINTS_type) != 0) {
+	output_symbolic_constraints(fp, PLA, 1);
+	output_type &= ~ SYMBOLIC_CONSTRAINTS_type;
+	if (output_type == 0) {
+	    return;
+	}
+    }
+
+    if (output_type == PLEASURE_type) {
+	pls_output(PLA);
+    } else if (output_type == EQNTOTT_type) {
+	eqn_output(PLA);
+    } else if (output_type == KISS_type) {
+	kiss_output(fp, PLA);
+    } else {
+	fpr_header(fp, PLA, output_type);
+
+	num = 0;
+	if (output_type & F_type) num += (PLA->F)->count;
+	if (output_type & D_type) num += (PLA->D)->count;
+	if (output_type & R_type) num += (PLA->R)->count;
+	(void) fprintf(fp, ".p %d\n", num);
+
+	/* quick patch 01/17/85 to support TPLA ! */
+	if (output_type == F_type) {
+	    foreach_set(PLA->F, last, p) {
+		print_cube(fp, p, "01");
+	    }
+	    (void) fprintf(fp, ".e\n");
+	} else {
+	    if (output_type & F_type) {
+		foreach_set(PLA->F, last, p) {
+		    print_cube(fp, p, "~1");
+		}
+	    }
+	    if (output_type & D_type) {
+		foreach_set(PLA->D, last, p) {
+		    print_cube(fp, p, "~2");
+		}
+	    }
+	    if (output_type & R_type) {
+		foreach_set(PLA->R, last, p) {
+		    print_cube(fp, p, "~0");
+		}
+	    }
+	    (void) fprintf(fp, ".end\n");
+	}
+    }
+}
+
+void fpr_header(fp, PLA, output_type)
+FILE *fp;
+pPLA PLA;
+int output_type;
+{
+    register int i, var;
+    int first, last;
+
+    /* .type keyword gives logical type */
+    if (output_type != F_type) {
+	(void) fprintf(fp, ".type ");
+	if (output_type & F_type) putc('f', fp);
+	if (output_type & D_type) putc('d', fp);
+	if (output_type & R_type) putc('r', fp);
+	putc('\n', fp);
+    }
+
+    /* Check for binary or multiple-valued labels */
+    if (cube.num_mv_vars <= 1) {
+	(void) fprintf(fp, ".i %d\n", cube.num_binary_vars);
+	if (cube.output != -1)
+	    (void) fprintf(fp, ".o %d\n", cube.part_size[cube.output]);
+    } else {
+	(void) fprintf(fp, ".mv %d %d", cube.num_vars, cube.num_binary_vars);
+	for(var = cube.num_binary_vars; var < cube.num_vars; var++)
+	    (void) fprintf(fp, " %d", cube.part_size[var]);
+	(void) fprintf(fp, "\n");
+    }
+
+    /* binary valued labels */
+    if (PLA->label != NIL(char *) && PLA->label[1] != NIL(char)
+	    && cube.num_binary_vars > 0) {
+	(void) fprintf(fp, ".ilb");
+	for(var = 0; var < cube.num_binary_vars; var++)
+	  /* see (NIL) OUTLABELS comment below */
+	  if(INLABEL(var) == NIL(char)){
+	    (void) fprintf(fp, " (null)");
+	  }
+	  else{
+	    (void) fprintf(fp, " %s", INLABEL(var));
+	  }
+	putc('\n', fp);
+    }
+
+    /* output-part (last multiple-valued variable) labels */
+    if (PLA->label != NIL(char *) &&
+	    PLA->label[cube.first_part[cube.output]] != NIL(char)
+		&& cube.output != -1) {
+	(void) fprintf(fp, ".ob");
+	for(i = 0; i < cube.part_size[cube.output]; i++)
+	  /* (NIL) OUTLABELS caused espresso to segfault under solaris */
+	  if(OUTLABEL(i) == NIL(char)){
+	    (void) fprintf(fp, " (null)");
+	  }
+	  else{
+	    (void) fprintf(fp, " %s", OUTLABEL(i));
+	  }
+	putc('\n', fp);
+    }
+
+    /* multiple-valued labels */
+    for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) {
+	first = cube.first_part[var];
+	last = cube.last_part[var];
+	if (PLA->label != NULL && PLA->label[first] != NULL) {
+	    (void) fprintf(fp, ".label var=%d", var);
+	    for(i = first; i <= last; i++) {
+		(void) fprintf(fp, " %s", PLA->label[i]);
+	    }
+	    putc('\n', fp);
+	}
+    }
+
+    if (PLA->phase != (pcube) NULL) {
+	first = cube.first_part[cube.output];
+	last = cube.last_part[cube.output];
+	(void) fprintf(fp, "#.phase ");
+	for(i = first; i <= last; i++)
+	    putc(is_in_set(PLA->phase,i) ? '1' : '0', fp);
+	(void) fprintf(fp, "\n");
+    }
+}
+
+void pls_output(PLA)
+IN pPLA PLA;
+{
+    register pcube last, p;
+
+    (void) printf(".option unmerged\n");
+    makeup_labels(PLA);
+    pls_label(PLA, stdout);
+    pls_group(PLA, stdout);
+    (void) printf(".p %d\n", PLA->F->count);
+    foreach_set(PLA->F, last, p) {
+	print_expanded_cube(stdout, p, PLA->phase);
+    }
+    (void) printf(".end\n");
+}
+
+
+void pls_group(PLA, fp)
+pPLA PLA;
+FILE *fp;
+{
+    int var, i, col, len;
+
+    (void) fprintf(fp, "\n.group");
+    col = 6;
+    for(var = 0; var < cube.num_vars-1; var++) {
+	(void) fprintf(fp, " ("), col += 2;
+	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+	    len = strlen(PLA->label[i]);
+	    if (col + len > 75)
+		(void) fprintf(fp, " \\\n"), col = 0;
+	    else if (i != 0)
+		putc(' ', fp), col += 1;
+	    (void) fprintf(fp, "%s", PLA->label[i]), col += len;
+	}
+	(void) fprintf(fp, ")"), col += 1;
+    }
+    (void) fprintf(fp, "\n");
+}
+
+
+void pls_label(PLA, fp)
+pPLA PLA;
+FILE *fp;
+{
+    int var, i, col, len;
+
+    (void) fprintf(fp, ".label");
+    col = 6;
+    for(var = 0; var < cube.num_vars; var++)
+	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+	    len = strlen(PLA->label[i]);
+	    if (col + len > 75)
+		(void) fprintf(fp, " \\\n"), col = 0;
+	    else
+		putc(' ', fp), col += 1;
+	    (void) fprintf(fp, "%s", PLA->label[i]), col += len;
+	}
+}
+
+
+
+/*
+    eqntott output mode -- output algebraic equations
+*/
+void eqn_output(PLA)
+pPLA PLA;
+{
+    register pcube p, last;
+    register int i, var, col, len;
+    int x;
+    bool firstand, firstor;
+
+    if (cube.output == -1)
+	fatal("Cannot have no-output function for EQNTOTT output mode");
+    if (cube.num_mv_vars != 1)
+	fatal("Must have binary-valued function for EQNTOTT output mode");
+    makeup_labels(PLA);
+
+    /* Write a single equation for each output */
+    for(i = 0; i < cube.part_size[cube.output]; i++) {
+	(void) printf("%s = ", OUTLABEL(i));
+	col = strlen(OUTLABEL(i)) + 3;
+	firstor = TRUE;
+
+	/* Write product terms for each cube in this output */
+	foreach_set(PLA->F, last, p)
+	    if (is_in_set(p, i + cube.first_part[cube.output])) {
+		if (firstor)
+		    (void) printf("("), col += 1;
+		else
+		    (void) printf(" | ("), col += 4;
+		firstor = FALSE;
+		firstand = TRUE;
+
+		/* print out a product term */
+		for(var = 0; var < cube.num_binary_vars; var++)
+		    if ((x=GETINPUT(p, var)) != DASH) {
+			len = strlen(INLABEL(var));
+			if (col+len > 72)
+			    (void) printf("\n    "), col = 4;
+			if (! firstand)
+			    (void) printf("&"), col += 1;
+			firstand = FALSE;
+			if (x == ZERO)
+			    (void) printf("!"), col += 1;
+			(void) printf("%s", INLABEL(var)), col += len;
+		    }
+		(void) printf(")"), col += 1;
+	    }
+	(void) printf(";\n\n");
+    }
+}
+
+
+char *fmt_cube(c, out_map, s)
+register pcube c;
+register char *out_map, *s;
+{
+    register int i, var, last, len = 0;
+
+    for(var = 0; var < cube.num_binary_vars; var++) {
+	s[len++] = "?01-" [GETINPUT(c, var)];
+    }
+    for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+	s[len++] = ' ';
+	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+	    s[len++] = "01" [is_in_set(c, i) != 0];
+	}
+    }
+    if (cube.output != -1) {
+	last = cube.last_part[cube.output];
+	s[len++] = ' ';
+	for(i = cube.first_part[cube.output]; i <= last; i++) {
+	    s[len++] = out_map [is_in_set(c, i) != 0];
+	}
+    }
+    s[len] = '\0';
+    return s;
+}
+
+
+void print_cube(fp, c, out_map)
+register FILE *fp;
+register pcube c;
+register char *out_map;
+{
+    register int i, var, ch;
+    int last;
+
+    for(var = 0; var < cube.num_binary_vars; var++) {
+	ch = "?01-" [GETINPUT(c, var)];
+	putc(ch, fp);
+    }
+    for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+	putc(' ', fp);
+	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+	    ch = "01" [is_in_set(c, i) != 0];
+	    putc(ch, fp);
+	}
+    }
+    if (cube.output != -1) {
+	last = cube.last_part[cube.output];
+	putc(' ', fp);
+	for(i = cube.first_part[cube.output]; i <= last; i++) {
+	    ch = out_map [is_in_set(c, i) != 0];
+	    putc(ch, fp);
+	}
+    }
+    putc('\n', fp);
+}
+
+
+void print_expanded_cube(fp, c, phase)
+register FILE *fp;
+register pcube c;
+pcube phase;
+{
+    register int i, var, ch;
+    char *out_map;
+
+    for(var = 0; var < cube.num_binary_vars; var++) {
+	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+	    ch = "~1" [is_in_set(c, i) != 0];
+	    putc(ch, fp);
+	}
+    }
+    for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+	    ch = "1~" [is_in_set(c, i) != 0];
+	    putc(ch, fp);
+	}
+    }
+    if (cube.output != -1) {
+	var = cube.num_vars - 1;
+	putc(' ', fp);
+	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+	    if (phase == (pcube) NULL || is_in_set(phase, i)) {
+		out_map = "~1";
+	    } else {
+		out_map = "~0";
+	    }
+	    ch = out_map[is_in_set(c, i) != 0];
+	    putc(ch, fp);
+	}
+    }
+    putc('\n', fp);
+}
+
+
+char *pc1(c) pcube c;
+{static char s1[256];return fmt_cube(c, "01", s1);}
+char *pc2(c) pcube c;
+{static char s2[256];return fmt_cube(c, "01", s2);}
+
+
+void debug_print(T, name, level)
+pcube *T;
+char *name;
+int level;
+{
+    register pcube *T1, p, temp;
+    register int cnt;
+
+    cnt = CUBELISTSIZE(T);
+    temp = new_cube();
+    if (verbose_debug && level == 0)
+	(void) printf("\n");
+    (void) printf("%s[%d]: ord(T)=%d\n", name, level, cnt);
+    if (verbose_debug) {
+	(void) printf("cofactor=%s\n", pc1(T[0]));
+	for(T1 = T+2, cnt = 1; (p = *T1++) != (pcube) NULL; cnt++)
+	    (void) printf("%4d. %s\n", cnt, pc1(set_or(temp, p, T[0])));
+    }
+    free_cube(temp);
+}
+
+
+void debug1_print(T, name, num)
+pcover T;
+char *name;
+int num;
+{
+    register int cnt = 1;
+    register pcube p, last;
+
+    if (verbose_debug && num == 0)
+	(void) printf("\n");
+    (void) printf("%s[%d]: ord(T)=%d\n", name, num, T->count);
+    if (verbose_debug)
+	foreach_set(T, last, p)
+	    (void) printf("%4d. %s\n", cnt++, pc1(p));
+}
+
+
+void cprint(T)
+pcover T;
+{
+    register pcube p, last;
+
+    foreach_set(T, last, p)
+	(void) printf("%s\n", pc1(p));
+}
+
+
+void makeup_labels(PLA)
+pPLA PLA;
+{
+    int var, i, ind;
+
+    if (PLA->label == (char **) NULL)
+	PLA_labels(PLA);
+
+    for(var = 0; var < cube.num_vars; var++)
+	for(i = 0; i < cube.part_size[var]; i++) {
+	    ind = cube.first_part[var] + i;
+	    if (PLA->label[ind] == (char *) NULL) {
+		PLA->label[ind] = ALLOC(char, 15);
+		if (var < cube.num_binary_vars)
+		    if ((i % 2) == 0)
+			(void) sprintf(PLA->label[ind], "v%d.bar", var);
+		    else
+			(void) sprintf(PLA->label[ind], "v%d", var);
+		else
+		    (void) sprintf(PLA->label[ind], "v%d.%d", var, i);
+	    }
+	}
+}
+
+
+void kiss_output(fp, PLA)
+FILE *fp;
+pPLA PLA;
+{
+    register pset last, p;
+
+    foreach_set(PLA->F, last, p) {
+	kiss_print_cube(fp, PLA, p, "~1");
+    }
+    foreach_set(PLA->D, last, p) {
+	kiss_print_cube(fp, PLA, p, "~2");
+    }
+}
+
+
+void kiss_print_cube(fp, PLA, p, out_string)
+FILE *fp;
+pPLA PLA;
+pcube p;
+char *out_string;
+{
+    register int i, var;
+    int part, x;
+
+    for(var = 0; var < cube.num_binary_vars; var++) {
+	x = "?01-" [GETINPUT(p, var)];
+	putc(x, fp);
+    }
+
+    for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+	putc(' ', fp);
+	if (setp_implies(cube.var_mask[var], p)) {
+	    putc('-', fp);
+	} else {
+	    part = -1;
+	    for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+		if (is_in_set(p, i)) {
+		    if (part != -1) {
+			fatal("more than 1 part in a symbolic variable\n");
+		    }
+		    part = i;
+		}
+	    }
+	    if (part == -1) {
+		putc('~', fp);	/* no parts, hope its an output ... */
+	    } else {
+		(void) fputs(PLA->label[part], fp);
+	    }
+	}
+    }
+
+    if ((var = cube.output) != -1) {
+	putc(' ', fp);
+	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+	    x = out_string [is_in_set(p, i) != 0];
+	    putc(x, fp);
+	}
+    }
+
+    putc('\n', fp);
+}
+
+void output_symbolic_constraints(fp, PLA, output_symbolic)
+FILE *fp;
+pPLA PLA;
+int output_symbolic;
+{
+    pset_family A;
+    register int i, j;
+    int size, var, npermute, *permute, *weight, noweight;
+
+    if ((cube.num_vars - cube.num_binary_vars) <= 1) {
+	return;
+    }
+    makeup_labels(PLA);
+
+    for(var=cube.num_binary_vars; var < cube.num_vars-1; var++) {
+
+	/* pull out the columns for variable "var" */
+	npermute = cube.part_size[var];
+	permute = ALLOC(int, npermute);
+	for(i=0; i < npermute; i++) {
+	    permute[i] = cube.first_part[var] + i;
+	}
+	A = sf_permute(sf_save(PLA->F), permute, npermute);
+	FREE(permute);
+
+
+	/* Delete the singletons and the full sets */
+	noweight = 0;
+	for(i = 0; i < A->count; i++) {
+	    size = set_ord(GETSET(A,i));
+	    if (size == 1 || size == A->sf_size) {
+		sf_delset(A, i--);
+		noweight++;
+	    }
+	}
+
+
+	/* Count how many times each is duplicated */
+	weight = ALLOC(int, A->count);
+	for(i = 0; i < A->count; i++) {
+	    RESET(GETSET(A, i), COVERED);
+	}
+	for(i = 0; i < A->count; i++) {
+	    weight[i] = 0;
+	    if (! TESTP(GETSET(A,i), COVERED)) {
+		weight[i] = 1;
+		for(j = i+1; j < A->count; j++) {
+		    if (setp_equal(GETSET(A,i), GETSET(A,j))) {
+			weight[i]++;
+			SET(GETSET(A,j), COVERED);
+		    }
+		}
+	    }
+	}
+
+
+	/* Print out the constraints */
+	if (! output_symbolic) {
+	    (void) fprintf(fp,
+	    "# Symbolic constraints for variable %d (Numeric form)\n", var);
+	    (void) fprintf(fp, "# unconstrained weight = %d\n", noweight);
+	    (void) fprintf(fp, "num_codes=%d\n", cube.part_size[var]);
+	    for(i = 0; i < A->count; i++) {
+		if (weight[i] > 0) {
+		    (void) fprintf(fp, "weight=%d: ", weight[i]);
+		    for(j = 0; j < A->sf_size; j++) {
+			if (is_in_set(GETSET(A,i), j)) {
+			    (void) fprintf(fp, " %d", j);
+			}
+		    }
+		    (void) fprintf(fp, "\n");
+		}
+	    }
+	} else {
+	    (void) fprintf(fp,
+	    "# Symbolic constraints for variable %d (Symbolic form)\n", var);
+	    for(i = 0; i < A->count; i++) {
+		if (weight[i] > 0) {
+		    (void) fprintf(fp, "#   w=%d: (", weight[i]);
+		    for(j = 0; j < A->sf_size; j++) {
+			if (is_in_set(GETSET(A,i), j)) {
+			    (void) fprintf(fp, " %s",
+				PLA->label[cube.first_part[var]+j]);
+			}
+		    }
+		    (void) fprintf(fp, " )\n");
+		}
+	    }
+	    FREE(weight);
+	}
+    }
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/dominate.c b/abc-build/src/misc/espresso/dominate.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/dominate.c
@@ -0,0 +1,103 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+int 
+sm_row_dominance(A)
+sm_matrix *A; 
+{
+    register sm_row *prow, *prow1;
+    register sm_col *pcol, *least_col;
+    register sm_element *p, *pnext;
+    int rowcnt;
+
+    rowcnt = A->nrows;
+
+    /* Check each row against all other rows */
+    for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+
+	/* Among all columns with a 1 in this row, choose smallest */
+	least_col = sm_get_col(A, prow->first_col->col_num);
+	for(p = prow->first_col->next_col; p != 0; p = p->next_col) {
+	    pcol = sm_get_col(A, p->col_num);
+	    if (pcol->length < least_col->length) {
+		least_col = pcol;
+	    }
+	}
+
+	/* Only check for containment against rows in this column */
+	for(p = least_col->first_row; p != 0; p = pnext) {
+	    pnext = p->next_row;
+
+	    prow1 = sm_get_row(A, p->row_num);
+	    if ((prow1->length > prow->length) ||
+	              (prow1->length == prow->length && 
+			      prow1->row_num > prow->row_num)) {
+		if (sm_row_contains(prow, prow1)) {
+		    sm_delrow(A, prow1->row_num);
+		}
+	    }
+	}
+    }
+
+    return rowcnt - A->nrows;
+}
+
+int 
+sm_col_dominance(A, weight)
+sm_matrix *A;
+int *weight;
+{
+    register sm_row *prow;
+    register sm_col *pcol, *pcol1;
+    register sm_element *p;
+    sm_row *least_row;
+    sm_col *next_col;
+    int colcnt;
+
+    colcnt = A->ncols;
+
+    /* Check each column against all other columns */
+    for(pcol = A->first_col; pcol != 0; pcol = next_col) {
+	next_col = pcol->next_col;
+
+	/* Check all rows to find the one with fewest elements */
+	least_row = sm_get_row(A, pcol->first_row->row_num);
+	for(p = pcol->first_row->next_row; p != 0; p = p->next_row) {
+	    prow = sm_get_row(A, p->row_num);
+	    if (prow->length < least_row->length) {
+		least_row = prow;
+	    }
+	}
+
+	/* Only check for containment against columns in this row */
+	for(p = least_row->first_col; p != 0; p = p->next_col) {
+	    pcol1 = sm_get_col(A, p->col_num);
+	    if (weight != 0 && weight[pcol1->col_num] > weight[pcol->col_num])
+		continue;
+	    if ((pcol1->length > pcol->length) ||
+	       (pcol1->length == pcol->length && 
+			       pcol1->col_num > pcol->col_num)) {
+		if (sm_col_contains(pcol, pcol1)) {
+		    sm_delcol(A, pcol->col_num);
+		    break;
+		}
+	    }
+	}
+    }
+
+    return colcnt - A->ncols;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/equiv.c b/abc-build/src/misc/espresso/equiv.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/equiv.c
@@ -0,0 +1,99 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+void find_equiv_outputs(PLA)
+pPLA PLA;
+{
+    int i, j, ipart, jpart, some_equiv;
+    pcover *R, *F;
+
+    some_equiv = FALSE;
+
+    makeup_labels(PLA);
+
+    F = ALLOC(pcover, cube.part_size[cube.output]);
+    R = ALLOC(pcover, cube.part_size[cube.output]);
+
+    for(i = 0; i < cube.part_size[cube.output]; i++) {
+	ipart = cube.first_part[cube.output] + i;
+	R[i] = cof_output(PLA->R, ipart);
+	F[i] = complement(cube1list(R[i]));
+    }
+	
+    for(i = 0; i < cube.part_size[cube.output]-1; i++) {
+	for(j = i+1; j < cube.part_size[cube.output]; j++) {
+	    ipart = cube.first_part[cube.output] + i;
+	    jpart = cube.first_part[cube.output] + j;
+
+	    if (check_equiv(F[i], F[j])) {
+		(void) printf("# Outputs %d and %d (%s and %s) are equivalent\n",
+		    i, j, PLA->label[ipart], PLA->label[jpart]);
+		some_equiv = TRUE;
+	    } else if (check_equiv(F[i], R[j])) {
+		(void) printf("# Outputs %d and NOT %d (%s and %s) are equivalent\n",
+		    i, j, PLA->label[ipart], PLA->label[jpart]);
+		some_equiv = TRUE;
+	    } else if (check_equiv(R[i], F[j])) {
+		(void) printf("# Outputs NOT %d and %d (%s and %s) are equivalent\n",
+		    i, j, PLA->label[ipart], PLA->label[jpart]);
+		some_equiv = TRUE;
+	    } else if (check_equiv(R[i], R[j])) {
+	    (void) printf("# Outputs NOT %d and NOT %d (%s and %s) are equivalent\n",
+		    i, j, PLA->label[ipart], PLA->label[jpart]);
+		some_equiv = TRUE;
+	    }
+	}
+    }
+
+    if (! some_equiv) {
+	(void) printf("# No outputs are equivalent\n");
+    }
+
+    for(i = 0; i < cube.part_size[cube.output]; i++) {
+	free_cover(F[i]);
+	free_cover(R[i]);
+    }
+    FREE(F);
+    FREE(R);
+}
+
+
+
+int check_equiv(f1, f2)
+pcover f1, f2;
+{
+    register pcube *f1list, *f2list;
+    register pcube p, last;
+
+    f1list = cube1list(f1);
+    foreach_set(f2, last, p) {
+	if (! cube_is_covered(f1list, p)) {
+	    return FALSE;
+	}
+    }
+    free_cubelist(f1list);
+
+    f2list = cube1list(f2);
+    foreach_set(f1, last, p) {
+	if (! cube_is_covered(f2list, p)) {
+	    return FALSE;
+	}
+    }
+    free_cubelist(f2list);
+
+    return TRUE;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/espresso.c b/abc-build/src/misc/espresso/espresso.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/espresso.c
@@ -0,0 +1,144 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ *  Module: espresso.c
+ *  Purpose: The main espresso algorithm
+ *
+ *  Returns a minimized version of the ON-set of a function
+ *
+ *  The following global variables affect the operation of Espresso:
+ *
+ *  MISCELLANEOUS:
+ *      trace
+ *          print trace information as the minimization progresses
+ *
+ *      remove_essential
+ *          remove essential primes
+ *
+ *      single_expand
+ *          if true, stop after first expand/irredundant
+ *
+ *  LAST_GASP or SUPER_GASP strategy:
+ *      use_super_gasp
+ *          uses the super_gasp strategy rather than last_gasp
+ *
+ *  SETUP strategy:
+ *      recompute_onset
+ *          recompute onset using the complement before starting
+ *
+ *      unwrap_onset
+ *          unwrap the function output part before first expand
+ *
+ *  MAKE_SPARSE strategy:
+ *      force_irredundant
+ *          iterates make_sparse to force a minimal solution (used
+ *          indirectly by make_sparse)
+ *
+ *      skip_make_sparse
+ *          skip the make_sparse step (used by opo only)
+ */
+
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+pcover espresso(F, D1, R)
+pcover F, D1, R;
+{
+    pcover E, D, Fsave;
+    pset last, p;
+    cost_t cost, best_cost;
+
+begin:
+    Fsave = sf_save(F);		/* save original function */
+    D = sf_save(D1);		/* make a scratch copy of D */
+
+    /* Setup has always been a problem */
+    if (recompute_onset) {
+	EXEC(E = simplify(cube1list(F)),     "SIMPLIFY   ", E);
+	free_cover(F);
+	F = E;
+    }
+    cover_cost(F, &cost);
+    if (unwrap_onset && (cube.part_size[cube.num_vars - 1] > 1)
+      && (cost.out != cost.cubes*cube.part_size[cube.num_vars-1])
+      && (cost.out < 5000))
+	EXEC(F = sf_contain(unravel(F, cube.num_vars - 1)), "SETUP      ", F);
+
+    /* Initial expand and irredundant */
+    foreach_set(F, last, p) {
+	RESET(p, PRIME);
+    }
+    EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost);
+    EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost);
+
+    if (! single_expand) {
+	if (remove_essential) {
+	    EXECUTE(E = essential(&F, &D), ESSEN_TIME, E, cost);
+	} else {
+	    E = new_cover(0);
+	}
+
+	cover_cost(F, &cost);
+	do {
+
+	    /* Repeat inner loop until solution becomes "stable" */
+	    do {
+		copy_cost(&cost, &best_cost);
+		EXECUTE(F = reduce(F, D), REDUCE_TIME, F, cost);
+		EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost);
+		EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost);
+	    } while (cost.cubes < best_cost.cubes);
+
+	    /* Perturb solution to see if we can continue to iterate */
+	    copy_cost(&cost, &best_cost);
+	    if (use_super_gasp) {
+		F = super_gasp(F, D, R, &cost);
+		if (cost.cubes >= best_cost.cubes)
+		    break;
+	    } else {
+		F = last_gasp(F, D, R, &cost);
+	    }
+
+	} while (cost.cubes < best_cost.cubes ||
+	    (cost.cubes == best_cost.cubes && cost.total < best_cost.total));
+
+	/* Append the essential cubes to F */
+	F = sf_append(F, E);                /* disposes of E */
+	if (trace) size_stamp(F, "ADJUST     ");
+    }
+
+    /* Free the D which we used */
+    free_cover(D);
+
+    /* Attempt to make the PLA matrix sparse */
+    if (! skip_make_sparse) {
+	F = make_sparse(F, D1, R);
+    }
+
+    /*
+     *  Check to make sure function is actually smaller !!
+     *  This can only happen because of the initial unravel.  If we fail,
+     *  then run the whole thing again without the unravel.
+     */
+    if (Fsave->count < F->count) {
+	free_cover(F);
+	F = Fsave;
+	unwrap_onset = FALSE;
+	goto begin;
+    } else {
+	free_cover(Fsave);
+    }
+
+    return F;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/espresso.h b/abc-build/src/misc/espresso/espresso.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/espresso.h
@@ -0,0 +1,786 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ *  espresso.h -- header file for Espresso-mv
+ */
+
+//#include "port.h"
+//#include "utility.h"
+#include "sparse.h"
+#include "mincov.h"
+
+#include "util_hack.h" // added
+
+#define ABC__misc__espresso__espresso_h
+#define print_time(t)	util_print_time(t)
+
+#ifdef IBM_WATC
+#define void int
+#include "short.h"
+#endif
+
+#ifdef IBMPC		/* set default options for IBM/PC */
+#define NO_INLINE
+#define BPI 16
+#endif
+
+/*-----THIS USED TO BE set.h----- */
+
+/*
+ *  set.h -- definitions for packed arrays of bits
+ *
+ *   This header file describes the data structures which comprise a
+ *   facility for efficiently implementing packed arrays of bits
+ *   (otherwise known as sets, cf. Pascal).
+ *
+ *   A set is a vector of bits and is implemented here as an array of
+ *   unsigned integers.  The low order bits of set[0] give the index of
+ *   the last word of set data.  The higher order bits of set[0] are
+ *   used to store data associated with the set.  The set data is
+ *   contained in elements set[1] ... set[LOOP(set)] as a packed bit
+ *   array.
+ *
+ *   A family of sets is a two-dimensional matrix of bits and is
+ *   implemented with the data type "set_family".
+ *
+ *   BPI == 32 and BPI == 16 have been tested and work.
+ */
+
+
+/* Define host machine characteristics of "unsigned int" */
+#ifndef ABC__misc__espresso__espresso_h
+#define BPI
+
+
+ABC_NAMESPACE_HEADER_START
+             32              /* # bits per integer */
+#endif
+
+#if BPI == 32
+#define LOGBPI          5               /* log(BPI)/log(2) */
+#else
+#define LOGBPI          4               /* log(BPI)/log(2) */
+#endif
+
+/* Define the set type */
+typedef unsigned int *pset;
+
+/* Define the set family type -- an array of sets */
+typedef struct set_family {
+    int wsize;                  /* Size of each set in 'ints' */
+    int sf_size;                /* User declared set size */
+    int capacity;               /* Number of sets allocated */
+    int count;                  /* The number of sets in the family */
+    int active_count;           /* Number of "active" sets */
+    pset data;                  /* Pointer to the set data */
+    struct set_family *next;    /* For garbage collection */
+} set_family_t, *pset_family;
+
+/* Macros to set and test single elements */
+#define WHICH_WORD(element)     (((element) >> LOGBPI) + 1)
+#define WHICH_BIT(element)      ((element) & (BPI-1))
+
+/* # of ints needed to allocate a set with "size" elements */
+#if BPI == 32
+#define SET_SIZE(size)          ((size) <= BPI ? 2 : (WHICH_WORD((size)-1) + 1))
+#else
+#define SET_SIZE(size)          ((size) <= BPI ? 3 : (WHICH_WORD((size)-1) + 2))
+#endif
+
+/*
+ *  Three fields are maintained in the first word of the set
+ *      LOOP is the index of the last word used for set data
+ *      LOOPCOPY is the index of the last word in the set
+ *      SIZE is available for general use (e.g., recording # elements in set)
+ *      NELEM retrieves the number of elements in the set
+ */
+#define LOOP(set)               (set[0] & 0x03ff)
+#define PUTLOOP(set, i)         (set[0] &= ~0x03ff, set[0] |= (i))
+#if BPI == 32
+#define LOOPCOPY(set)           LOOP(set)
+#define SIZE(set)               (set[0] >> 16)
+#define PUTSIZE(set, size)      (set[0] &= 0xffff, set[0] |= ((size) << 16))
+#else
+#define LOOPCOPY(set)           (LOOP(set) + 1)
+#define SIZE(set)               (set[LOOP(set)+1])
+#define PUTSIZE(set, size)      ((set[LOOP(set)+1]) = (size))
+#endif
+
+#define NELEM(set)		(BPI * LOOP(set))
+#define LOOPINIT(size)		((size <= BPI) ? 1 : WHICH_WORD((size)-1))
+
+/*
+ *      FLAGS store general information about the set
+ */
+#define SET(set, flag)          (set[0] |= (flag))
+#define RESET(set, flag)        (set[0] &= ~ (flag))
+#define TESTP(set, flag)        (set[0] & (flag))
+
+/* Flag definitions are ... */
+#define PRIME           0x8000          /* cube is prime */
+#define NONESSEN        0x4000          /* cube cannot be essential prime */
+#define ACTIVE          0x2000          /* cube is still active */
+#define REDUND          0x1000          /* cube is redundant(at this point) */
+#define COVERED         0x0800          /* cube has been covered */
+#define RELESSEN        0x0400          /* cube is relatively essential */
+
+/* Most efficient way to look at all members of a set family */
+#define foreach_set(R, last, p)\
+    for(p=R->data,last=p+R->count*R->wsize;p<last;p+=R->wsize)
+#define foreach_remaining_set(R, last, pfirst, p)\
+    for(p=pfirst+R->wsize,last=R->data+R->count*R->wsize;p<last;p+=R->wsize)
+#define foreach_active_set(R, last, p)\
+    foreach_set(R,last,p) if (TESTP(p, ACTIVE))
+
+/* Another way that also keeps the index of the current set member in i */
+#define foreachi_set(R, i, p)\
+    for(p=R->data,i=0;i<R->count;p+=R->wsize,i++)
+#define foreachi_active_set(R, i, p)\
+    foreachi_set(R,i,p) if (TESTP(p, ACTIVE))
+
+/* Looping over all elements in a set:
+ *      foreach_set_element(pset p, int i, unsigned val, int base) {
+ *		.
+ *		.
+ *		.
+ *      }
+ */
+#define foreach_set_element(p, i, val, base) 		\
+    for(i = LOOP(p); i > 0; )				\
+	for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1)  \
+	    if (val & 1)
+
+/* Return a pointer to a given member of a set family */
+#define GETSET(family, index)   ((family)->data + (family)->wsize * (index))
+
+/* Allocate and deallocate sets */
+#define set_new(size)	set_clear(ALLOC(unsigned int, SET_SIZE(size)), size)
+#define set_full(size)	set_fill(ALLOC(unsigned int, SET_SIZE(size)), size)
+#define set_save(r)	set_copy(ALLOC(unsigned int, SET_SIZE(NELEM(r))), r)
+#define set_free(r)	FREE(r)
+
+/* Check for set membership, remove set element and insert set element */
+#define is_in_set(set, e)       (set[WHICH_WORD(e)] & (1 << WHICH_BIT(e)))
+#define set_remove(set, e)      (set[WHICH_WORD(e)] &= ~ (1 << WHICH_BIT(e)))
+#define set_insert(set, e)      (set[WHICH_WORD(e)] |= 1 << WHICH_BIT(e))
+
+/* Inline code substitution for those places that REALLY need it on a VAX */
+#ifdef NO_INLINE
+#define INLINEset_copy(r, a)		(void) set_copy(r,a)
+#define INLINEset_clear(r, size)	(void) set_clear(r, size)
+#define INLINEset_fill(r, size)		(void) set_fill(r, size)
+#define INLINEset_and(r, a, b)		(void) set_and(r, a, b)
+#define INLINEset_or(r, a, b)		(void) set_or(r, a, b)
+#define INLINEset_diff(r, a, b)		(void) set_diff(r, a, b)
+#define INLINEset_ndiff(r, a, b, f)	(void) set_ndiff(r, a, b, f)
+#define INLINEset_xor(r, a, b)		(void) set_xor(r, a, b)
+#define INLINEset_xnor(r, a, b, f)	(void) set_xnor(r, a, b, f)
+#define INLINEset_merge(r, a, b, mask)	(void) set_merge(r, a, b, mask)
+#define INLINEsetp_implies(a, b, when_false)	\
+    if (! setp_implies(a,b)) when_false
+#define INLINEsetp_disjoint(a, b, when_false)	\
+    if (! setp_disjoint(a,b)) when_false
+#define INLINEsetp_equal(a, b, when_false)	\
+    if (! setp_equal(a,b)) when_false
+
+#else
+
+#define INLINEset_copy(r, a)\
+    {register int i_=LOOPCOPY(a); do r[i_]=a[i_]; while (--i_>=0);}
+#define INLINEset_clear(r, size)\
+    {register int i_=LOOPINIT(size); *r=i_; do r[i_] = 0; while (--i_ > 0);}
+#define INLINEset_fill(r, size)\
+    {register int i_=LOOPINIT(size); *r=i_; \
+    r[i_]=((unsigned int)(~0))>>(i_*BPI-size); while(--i_>0) r[i_]=~0;}
+#define INLINEset_and(r, a, b)\
+    {register int i_=LOOP(a); PUTLOOP(r,i_);\
+    do r[i_] = a[i_] & b[i_]; while (--i_>0);}
+#define INLINEset_or(r, a, b)\
+    {register int i_=LOOP(a); PUTLOOP(r,i_);\
+    do r[i_] = a[i_] | b[i_]; while (--i_>0);}
+#define INLINEset_diff(r, a, b)\
+    {register int i_=LOOP(a); PUTLOOP(r,i_);\
+    do r[i_] = a[i_] & ~ b[i_]; while (--i_>0);}
+#define INLINEset_ndiff(r, a, b, fullset)\
+    {register int i_=LOOP(a); PUTLOOP(r,i_);\
+    do r[i_] = fullset[i_] & (a[i_] | ~ b[i_]); while (--i_>0);}
+#ifdef IBM_WATC
+#define INLINEset_xor(r, a, b)		(void) set_xor(r, a, b)
+#define INLINEset_xnor(r, a, b, f)	(void) set_xnor(r, a, b, f)
+#else
+#define INLINEset_xor(r, a, b)\
+    {register int i_=LOOP(a); PUTLOOP(r,i_);\
+    do r[i_] = a[i_] ^ b[i_]; while (--i_>0);}
+#define INLINEset_xnor(r, a, b, fullset)\
+    {register int i_=LOOP(a); PUTLOOP(r,i_);\
+    do r[i_] = fullset[i_] & ~ (a[i_] ^ b[i_]); while (--i_>0);}
+#endif
+#define INLINEset_merge(r, a, b, mask)\
+    {register int i_=LOOP(a); PUTLOOP(r,i_);\
+    do r[i_] = (a[i_]&mask[i_]) | (b[i_]&~mask[i_]); while (--i_>0);}
+#define INLINEsetp_implies(a, b, when_false)\
+    {register int i_=LOOP(a); do if (a[i_]&~b[i_]) break; while (--i_>0);\
+    if (i_ != 0) when_false;}
+#define INLINEsetp_disjoint(a, b, when_false)\
+    {register int i_=LOOP(a); do if (a[i_]&b[i_]) break; while (--i_>0);\
+    if (i_ != 0) when_false;}
+#define INLINEsetp_equal(a, b, when_false)\
+    {register int i_=LOOP(a); do if (a[i_]!=b[i_]) break; while (--i_>0);\
+    if (i_ != 0) when_false;}
+
+#endif
+
+#if BPI == 32
+#define count_ones(v)\
+    (bit_count[v & 255] + bit_count[(v >> 8) & 255]\
+    + bit_count[(v >> 16) & 255] + bit_count[(v >> 24) & 255])
+#else
+#define count_ones(v)   (bit_count[v & 255] + bit_count[(v >> 8) & 255])
+#endif
+
+/* Table for efficient bit counting */
+extern int bit_count[256];
+/*----- END OF set.h ----- */
+
+
+/* Define a boolean type */
+#define bool	int
+#define FALSE	0
+#define TRUE 	1
+#define MAYBE	2
+#define print_bool(x) ((x) == 0 ? "FALSE" : ((x) == 1 ? "TRUE" : "MAYBE"))
+
+/* Map many cube/cover types/routines into equivalent set types/routines */
+#define pcube                   pset
+#define new_cube()              set_new(cube.size)
+#define free_cube(r)            set_free(r)
+#define pcover                  pset_family
+#define new_cover(i)            sf_new(i, cube.size)
+#define free_cover(r)           sf_free(r)
+#define free_cubelist(T)        FREE(T[0]); FREE(T);
+
+
+/* cost_t describes the cost of a cover */
+typedef struct cost_struct {
+    int cubes;			/* number of cubes in the cover */
+    int in;			/* transistor count, binary-valued variables */
+    int out;			/* transistor count, output part */
+    int mv;			/* transistor count, multiple-valued vars */
+    int total;			/* total number of transistors */
+    int primes;			/* number of prime cubes */
+} cost_t, *pcost;
+
+
+/* pair_t describes bit-paired variables */
+typedef struct pair_struct {
+    int cnt;
+    int *var1;
+    int *var2;
+} pair_t, *ppair;
+
+
+/* symbolic_list_t describes a single ".symbolic" line */
+typedef struct symbolic_list_struct {
+    int variable;
+    int pos;
+    struct symbolic_list_struct *next;
+} symbolic_list_t;
+
+
+/* symbolic_list_t describes a single ".symbolic" line */
+typedef struct symbolic_label_struct {
+    char *label;
+    struct symbolic_label_struct *next;
+} symbolic_label_t;
+
+
+/* symbolic_t describes a linked list of ".symbolic" lines */
+typedef struct symbolic_struct {
+    symbolic_list_t *symbolic_list;	/* linked list of items */
+    int symbolic_list_length;		/* length of symbolic_list list */
+    symbolic_label_t *symbolic_label;	/* linked list of new names */
+    int symbolic_label_length;		/* length of symbolic_label list */
+    struct symbolic_struct *next;
+} symbolic_t;
+
+
+/* PLA_t stores the logical representation of a PLA */
+typedef struct {
+    pcover F, D, R;		/* on-set, off-set and dc-set */
+    char *filename;             /* filename */
+    int pla_type;               /* logical PLA format */
+    pcube phase;                /* phase to split into on-set and off-set */
+    ppair pair;                 /* how to pair variables */
+    char **label;		/* labels for the columns */
+    symbolic_t *symbolic;	/* allow binary->symbolic mapping */
+    symbolic_t *symbolic_output;/* allow symbolic output mapping */
+} PLA_t, *pPLA;
+
+#define equal(a,b)      (strcmp(a,b) == 0)
+
+/* This is a hack which I wish I hadn't done, but too painful to change */
+#define CUBELISTSIZE(T)         (((pcube *) T[1] - T) - 3)
+
+/* For documentation purposes */
+#define IN
+#define OUT
+#define INOUT
+
+/* The pla_type field describes the input and output format of the PLA */
+#define F_type          1
+#define D_type          2
+#define R_type          4
+#define PLEASURE_type   8               /* output format */
+#define EQNTOTT_type    16              /* output format algebraic eqns */
+#define KISS_type	128		/* output format kiss */
+#define CONSTRAINTS_type	256	/* output the constraints (numeric) */
+#define SYMBOLIC_CONSTRAINTS_type 512	/* output the constraints (symbolic) */
+#define FD_type (F_type | D_type)
+#define FR_type (F_type | R_type)
+#define DR_type (D_type | R_type)
+#define FDR_type (F_type | D_type | R_type)
+
+/* Definitions for the debug variable */
+#define COMPL           0x0001
+#define ESSEN           0x0002
+#define EXPAND          0x0004
+#define EXPAND1         0x0008
+#define GASP            0x0010
+#define IRRED           0x0020
+#define REDUCE          0x0040
+#define REDUCE1         0x0080
+#define SPARSE          0x0100
+#define TAUT            0x0200
+#define EXACT           0x0400
+#define MINCOV          0x0800
+#define MINCOV1         0x1000
+#define SHARP           0x2000
+#define IRRED1		0x4000
+
+#define VERSION\
+    "UC Berkeley, Espresso Version #2.3, Release date 01/31/88"
+
+/* Define constants used for recording program statistics */
+#define TIME_COUNT      16
+#define READ_TIME       0
+#define COMPL_TIME      1
+#define ONSET_TIME	2
+#define ESSEN_TIME      3
+#define EXPAND_TIME     4
+#define IRRED_TIME      5
+#define REDUCE_TIME     6
+#define GEXPAND_TIME    7
+#define GIRRED_TIME     8
+#define GREDUCE_TIME    9
+#define PRIMES_TIME     10
+#define MINCOV_TIME	11
+#define MV_REDUCE_TIME  12
+#define RAISE_IN_TIME   13
+#define VERIFY_TIME     14
+#define WRITE_TIME	15
+
+
+/* For those who like to think about PLAs, macros to get at inputs/outputs */
+#define NUMINPUTS       cube.num_binary_vars
+#define NUMOUTPUTS      cube.part_size[cube.num_vars - 1]
+
+#define POSITIVE_PHASE(pos)\
+    (is_in_set(PLA->phase, cube.first_part[cube.output]+pos) != 0)
+
+#define INLABEL(var)    PLA->label[cube.first_part[var] + 1]
+#define OUTLABEL(pos)   PLA->label[cube.first_part[cube.output] + pos]
+
+#define GETINPUT(c, pos)\
+    ((c[WHICH_WORD(2*pos)] >> WHICH_BIT(2*pos)) & 3)
+#define GETOUTPUT(c, pos)\
+    (is_in_set(c, cube.first_part[cube.output] + pos) != 0)
+
+#define PUTINPUT(c, pos, value)\
+    c[WHICH_WORD(2*pos)] = (c[WHICH_WORD(2*pos)] & ~(3 << WHICH_BIT(2*pos)))\
+		| (value << WHICH_BIT(2*pos))
+#define PUTOUTPUT(c, pos, value)\
+    c[WHICH_WORD(pos)] = (c[WHICH_WORD(pos)] & ~(1 << WHICH_BIT(pos)))\
+		| (value << WHICH_BIT(pos))
+
+#define TWO     3
+#define DASH    3
+#define ONE     2
+#define ZERO    1
+
+
+#define EXEC(fct, name, S)\
+    {long t=ptime();fct;if(trace)print_trace(S,name,ptime()-t);}
+#define EXEC_S(fct, name, S)\
+    {long t=ptime();fct;if(summary)print_trace(S,name,ptime()-t);}
+#define EXECUTE(fct,i,S,cost)\
+    {long t=ptime();fct;totals(t,i,S,&(cost));}
+
+/*
+ *    Global Variable Declarations
+ */
+
+extern unsigned int debug;              /* debug parameter */
+extern bool verbose_debug;              /* -v:  whether to print a lot */
+extern char *total_name[TIME_COUNT];    /* basic function names */
+extern long total_time[TIME_COUNT];     /* time spent in basic fcts */
+extern int total_calls[TIME_COUNT];     /* # calls to each fct */
+
+extern bool echo_comments;		/* turned off by -eat option */
+extern bool echo_unknown_commands;	/* always true ?? */
+extern bool force_irredundant;          /* -nirr command line option */
+extern bool skip_make_sparse;
+extern bool kiss;                       /* -kiss command line option */
+extern bool pos;                        /* -pos command line option */
+extern bool print_solution;             /* -x command line option */
+extern bool recompute_onset;            /* -onset command line option */
+extern bool remove_essential;           /* -ness command line option */
+extern bool single_expand;              /* -fast command line option */
+extern bool summary;                    /* -s command line option */
+extern bool trace;                      /* -t command line option */
+extern bool unwrap_onset;               /* -nunwrap command line option */
+extern bool use_random_order;		/* -random command line option */
+extern bool use_super_gasp;		/* -strong command line option */
+extern char *filename;			/* filename PLA was read from */
+extern bool debug_exact_minimization;   /* dumps info for -do exact */
+
+
+/*
+ *  pla_types are the input and output types for reading/writing a PLA
+ */
+struct pla_types_struct {
+    char *key;
+    int value;
+};
+
+
+/*
+ *  The cube structure is a global structure which contains information
+ *  on how a set maps into a cube -- i.e., number of parts per variable,
+ *  number of variables, etc.  Also, many fields are pre-computed to
+ *  speed up various primitive operations.
+ */
+#define CUBE_TEMP       10
+
+struct cube_struct {
+    int size;                   /* set size of a cube */
+    int num_vars;               /* number of variables in a cube */
+    int num_binary_vars;        /* number of binary variables */
+    int *first_part;            /* first element of each variable */
+    int *last_part;             /* first element of each variable */
+    int *part_size;             /* number of elements in each variable */
+    int *first_word;            /* first word for each variable */
+    int *last_word;             /* last word for each variable */
+    pset binary_mask;           /* Mask to extract binary variables */
+    pset mv_mask;               /* mask to get mv parts */
+    pset *var_mask;             /* mask to extract a variable */
+    pset *temp;                 /* an array of temporary sets */
+    pset fullset;               /* a full cube */
+    pset emptyset;              /* an empty cube */
+    unsigned int inmask;        /* mask to get odd word of binary part */
+    int inword;                 /* which word number for above */
+    int *sparse;                /* should this variable be sparse? */
+    int num_mv_vars;            /* number of multiple-valued variables */
+    int output;                 /* which variable is "output" (-1 if none) */
+};
+
+struct cdata_struct {
+    int *part_zeros;            /* count of zeros for each element */
+    int *var_zeros;             /* count of zeros for each variable */
+    int *parts_active;          /* number of "active" parts for each var */
+    bool *is_unate;             /* indicates given var is unate */
+    int vars_active;            /* number of "active" variables */
+    int vars_unate;             /* number of unate variables */
+    int best;                   /* best "binate" variable */
+};
+
+
+extern struct pla_types_struct pla_types[];
+extern struct cube_struct cube, temp_cube_save;
+extern struct cdata_struct cdata, temp_cdata_save;
+
+#ifdef lint
+#define DISJOINT 0x5555
+#else
+#if BPI == 32
+#define DISJOINT 0x55555555
+#else
+#define DISJOINT 0x5555
+#endif
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+/* function declarations */
+
+/* cofactor.c */	extern int binate_split_select();
+/* cofactor.c */	extern pcover cubeunlist();
+/* cofactor.c */	extern pcube *cofactor();
+/* cofactor.c */	extern pcube *cube1list();
+/* cofactor.c */	extern pcube *cube2list();
+/* cofactor.c */	extern pcube *cube3list();
+/* cofactor.c */	extern pcube *scofactor();
+/* cofactor.c */	extern void massive_count();
+/* compl.c */	extern pcover complement();
+/* compl.c */	extern pcover simplify();
+/* compl.c */	extern void simp_comp();
+/* contain.c */	extern int d1_rm_equal();
+/* contain.c */	extern int rm2_contain();
+/* contain.c */	extern int rm2_equal();
+/* contain.c */	extern int rm_contain();
+/* contain.c */	extern int rm_equal();
+/* contain.c */	extern int rm_rev_contain();
+/* contain.c */	extern pset *sf_list();
+/* contain.c */	extern pset *sf_sort();
+/* contain.c */	extern pset_family d1merge();
+/* contain.c */	extern pset_family dist_merge();
+/* contain.c */	extern pset_family sf_contain();
+/* contain.c */	extern pset_family sf_dupl();
+/* contain.c */	extern pset_family sf_ind_contain();
+/* contain.c */	extern pset_family sf_ind_unlist();
+/* contain.c */	extern pset_family sf_merge();
+/* contain.c */	extern pset_family sf_rev_contain();
+/* contain.c */	extern pset_family sf_union();
+/* contain.c */	extern pset_family sf_unlist();
+/* cubestr.c */	extern void cube_setup();
+/* cubestr.c */	extern void restore_cube_struct();
+/* cubestr.c */	extern void save_cube_struct();
+/* cubestr.c */	extern void setdown_cube();
+/* cvrin.c */	extern void PLA_labels();
+/* cvrin.c */	extern char *get_word();
+/* cvrin.c */	extern int label_index();
+/* cvrin.c */	extern int read_pla();
+/* cvrin.c */	extern int read_symbolic();
+/* cvrin.c */	extern pPLA new_PLA();
+/* cvrin.c */	extern void PLA_summary();
+/* cvrin.c */	extern void free_PLA();
+/* cvrin.c */	extern void parse_pla();
+/* cvrin.c */	extern void read_cube();
+/* cvrin.c */	extern void skip_line();
+/* cvrm.c */	extern void foreach_output_function();
+/* cvrm.c */	extern int cubelist_partition();
+/* cvrm.c */	extern int so_both_do_espresso();
+/* cvrm.c */	extern int so_both_do_exact();
+/* cvrm.c */	extern int so_both_save();
+/* cvrm.c */	extern int so_do_espresso();
+/* cvrm.c */	extern int so_do_exact();
+/* cvrm.c */	extern int so_save();
+/* cvrm.c */	extern pcover cof_output();
+/* cvrm.c */	extern pcover lex_sort();
+/* cvrm.c */	extern pcover mini_sort();
+/* cvrm.c */	extern pcover random_order();
+/* cvrm.c */	extern pcover size_sort();
+/* cvrm.c */	extern pcover sort_reduce();
+/* cvrm.c */	extern pcover uncof_output();
+/* cvrm.c */	extern pcover unravel();
+/* cvrm.c */	extern pcover unravel_range();
+/* cvrm.c */	extern void so_both_espresso();
+/* cvrm.c */	extern void so_espresso();
+/* cvrmisc.c */	extern char *fmt_cost();
+/* cvrmisc.c */	extern char *print_cost();
+/* cvrmisc.c */	extern char *strsav();
+/* cvrmisc.c */	extern void copy_cost();
+/* cvrmisc.c */	extern void cover_cost();
+/* cvrmisc.c */	extern void fatal();
+/* cvrmisc.c */	extern void print_trace();
+/* cvrmisc.c */	extern void size_stamp();
+/* cvrmisc.c */	extern void totals();
+/* cvrout.c */	extern char *fmt_cube();
+/* cvrout.c */	extern char *fmt_expanded_cube();
+/* cvrout.c */	extern char *pc1();
+/* cvrout.c */	extern char *pc2();
+/* cvrout.c */	extern char *pc3();
+/* cvrout.c */	extern void makeup_labels();
+/* cvrout.c */	extern void kiss_output();
+/* cvrout.c */	extern void kiss_print_cube();
+/* cvrout.c */	extern void output_symbolic_constraints();
+/* cvrout.c */	extern void cprint();
+/* cvrout.c */	extern void debug1_print();
+/* cvrout.c */	extern void debug_print();
+/* cvrout.c */	extern void eqn_output();
+/* cvrout.c */	extern void fpr_header();
+/* cvrout.c */	extern void fprint_pla();
+/* cvrout.c */	extern void pls_group();
+/* cvrout.c */	extern void pls_label();
+/* cvrout.c */	extern void pls_output();
+/* cvrout.c */	extern void print_cube();
+/* cvrout.c */	extern void print_expanded_cube();
+/* cvrout.c */	extern void sf_debug_print();
+/* equiv.c */	extern void find_equiv_outputs();
+/* equiv.c */	extern int check_equiv();
+/* espresso.c */	extern pcover espresso();
+/* essen.c */	extern bool essen_cube();
+/* essen.c */	extern pcover cb_consensus();
+/* essen.c */	extern pcover cb_consensus_dist0();
+/* essen.c */	extern pcover essential();
+/* exact.c */	extern pcover minimize_exact();
+/* exact.c */	extern pcover minimize_exact_literals();
+/* expand.c */	extern bool feasibly_covered();
+/* expand.c */	extern int most_frequent();
+/* expand.c */	extern pcover all_primes();
+/* expand.c */	extern pcover expand();
+/* expand.c */	extern pcover find_all_primes();
+/* expand.c */	extern void elim_lowering();
+/* expand.c */	extern void essen_parts();
+/* expand.c */	extern void essen_raising();
+/* expand.c */	extern void expand1();
+/* expand.c */	extern void mincov();
+/* expand.c */	extern void select_feasible();
+/* expand.c */	extern void setup_BB_CC();
+/* gasp.c */	extern pcover expand_gasp();
+/* gasp.c */	extern pcover irred_gasp();
+/* gasp.c */	extern pcover last_gasp();
+/* gasp.c */	extern pcover super_gasp();
+/* gasp.c */	extern void expand1_gasp();
+/* getopt.c */	extern int util_getopt();
+/* hack.c */	extern void find_dc_inputs();
+/* hack.c */	extern void find_inputs();
+/* hack.c */	extern void form_bitvector();
+/* hack.c */	extern void map_dcset();
+/* hack.c */	extern void map_output_symbolic();
+/* hack.c */	extern void map_symbolic();
+/* hack.c */	extern pcover map_symbolic_cover();
+/* hack.c */	extern void symbolic_hack_labels();
+/* irred.c */	extern bool cube_is_covered();
+/* irred.c */	extern bool taut_special_cases();
+/* irred.c */	extern bool tautology();
+/* irred.c */	extern pcover irredundant();
+/* irred.c */	extern void mark_irredundant();
+/* irred.c */	extern void irred_split_cover();
+/* irred.c */	extern sm_matrix *irred_derive_table();
+/* map.c */	extern pset minterms();
+/* map.c */	extern void explode();
+/* map.c */	extern void map();
+/* opo.c */	extern void output_phase_setup();
+/* opo.c */	extern pPLA set_phase();
+/* opo.c */	extern pcover opo();
+/* opo.c */	extern pcube find_phase();
+/* opo.c */	extern pset_family find_covers();
+/* opo.c */	extern pset_family form_cover_table();
+/* opo.c */	extern pset_family opo_leaf();
+/* opo.c */	extern pset_family opo_recur();
+/* opo.c */	extern void opoall();
+/* opo.c */	extern void phase_assignment();
+/* opo.c */	extern void repeated_phase_assignment();
+/* pair.c */	extern void generate_all_pairs();
+/* pair.c */	extern int **find_pairing_cost();
+/* pair.c */	extern void find_best_cost();
+/* pair.c */	extern int greedy_best_cost();
+/* pair.c */	extern void minimize_pair();
+/* pair.c */	extern void pair_free();
+/* pair.c */	extern void pair_all();
+/* pair.c */	extern pcover delvar();
+/* pair.c */	extern pcover pairvar();
+/* pair.c */	extern ppair pair_best_cost();
+/* pair.c */	extern ppair pair_new();
+/* pair.c */	extern ppair pair_save();
+/* pair.c */	extern void print_pair();
+/* pair.c */	extern void find_optimal_pairing();
+/* pair.c */	extern void set_pair();
+/* pair.c */	extern void set_pair1();
+/* primes.c */	extern pcover primes_consensus();
+/* reduce.c */	extern bool sccc_special_cases();
+/* reduce.c */	extern pcover reduce();
+/* reduce.c */	extern pcube reduce_cube();
+/* reduce.c */	extern pcube sccc();
+/* reduce.c */	extern pcube sccc_cube();
+/* reduce.c */	extern pcube sccc_merge();
+/* set.c */	extern bool set_andp();
+/* set.c */	extern bool set_orp();
+/* set.c */	extern bool setp_disjoint();
+/* set.c */	extern bool setp_empty();
+/* set.c */	extern bool setp_equal();
+/* set.c */	extern bool setp_full();
+/* set.c */	extern bool setp_implies();
+/* set.c */	extern char *pbv1();
+/* set.c */	extern char *ps1();
+/* set.c */	extern int *sf_count();
+/* set.c */	extern int *sf_count_restricted();
+/* set.c */	extern int bit_index();
+/* set.c */	extern int set_dist();
+/* set.c */	extern int set_ord();
+/* set.c */	extern void set_adjcnt();
+/* set.c */	extern pset set_and();
+/* set.c */	extern pset set_clear();
+/* set.c */	extern pset set_copy();
+/* set.c */	extern pset set_diff();
+/* set.c */	extern pset set_fill();
+/* set.c */	extern pset set_merge();
+/* set.c */	extern pset set_or();
+/* set.c */	extern pset set_xor();
+/* set.c */	extern pset sf_and();
+/* set.c */	extern pset sf_or();
+/* set.c */	extern pset_family sf_active();
+/* set.c */	extern pset_family sf_addcol();
+/* set.c */	extern pset_family sf_addset();
+/* set.c */	extern pset_family sf_append();
+/* set.c */	extern pset_family sf_bm_read();
+/* set.c */	extern pset_family sf_compress();
+/* set.c */	extern pset_family sf_copy();
+/* set.c */	extern pset_family sf_copy_col();
+/* set.c */	extern pset_family sf_delc();
+/* set.c */	extern pset_family sf_delcol();
+/* set.c */	extern pset_family sf_inactive();
+/* set.c */	extern pset_family sf_join();
+/* set.c */	extern pset_family sf_new();
+/* set.c */	extern pset_family sf_permute();
+/* set.c */	extern pset_family sf_read();
+/* set.c */	extern pset_family sf_save();
+/* set.c */	extern pset_family sf_transpose();
+/* set.c */	extern void set_write();
+/* set.c */	extern void sf_bm_print();
+/* set.c */	extern void sf_cleanup();
+/* set.c */	extern void sf_delset();
+/* set.c */	extern void sf_free();
+/* set.c */	extern void sf_print();
+/* set.c */	extern void sf_write();
+/* setc.c */	extern bool ccommon();
+/* setc.c */	extern bool cdist0();
+/* setc.c */	extern bool full_row();
+/* setc.c */	extern int ascend();
+/* setc.c */	extern int cactive();
+/* setc.c */	extern int cdist();
+/* setc.c */	extern int cdist01();
+/* setc.c */	extern int cvolume();
+/* setc.c */	extern int d1_order();
+/* setc.c */	extern int d1_order_size();
+/* setc.c */	extern int desc1();
+/* setc.c */	extern int descend();
+/* setc.c */	extern int lex_order();
+/* setc.c */	extern int lex_order1();
+/* setc.c */	extern pset force_lower();
+/* setc.c */	extern void consensus();
+/* sharp.c */	extern pcover cb1_dsharp();
+/* sharp.c */	extern pcover cb_dsharp();
+/* sharp.c */	extern pcover cb_recur_dsharp();
+/* sharp.c */	extern pcover cb_recur_sharp();
+/* sharp.c */	extern pcover cb_sharp();
+/* sharp.c */	extern pcover cv_dsharp();
+/* sharp.c */	extern pcover cv_intersect();
+/* sharp.c */	extern pcover cv_sharp();
+/* sharp.c */	extern pcover dsharp();
+/* sharp.c */	extern pcover make_disjoint();
+/* sharp.c */	extern pcover sharp();
+/* sminterf.c */pset do_sm_minimum_cover();
+/* sparse.c */	extern pcover make_sparse();
+/* sparse.c */	extern pcover mv_reduce();
+/* unate.c */	extern pcover find_all_minimal_covers_petrick();
+/* unate.c */	extern pcover map_cover_to_unate();
+/* unate.c */	extern pcover map_unate_to_cover();
+/* unate.c */	extern pset_family exact_minimum_cover();
+/* unate.c */	extern pset_family gen_primes();
+/* unate.c */	extern pset_family unate_compl();
+/* unate.c */	extern pset_family unate_complement();
+/* unate.c */	extern pset_family unate_intersect();
+/* verify.c */	extern void PLA_permute();
+/* verify.c */	extern bool PLA_verify();
+/* verify.c */	extern bool check_consistency();
+/* verify.c */	extern bool verify();
diff --git a/abc-build/src/misc/espresso/essen.c b/abc-build/src/misc/espresso/essen.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/essen.c
@@ -0,0 +1,184 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+    module: essen.c
+    purpose: Find essential primes in a multiple-valued function
+*/
+
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+    essential -- return a cover consisting of the cubes of F which are
+    essential prime implicants (with respect to F u D); Further, remove
+    these cubes from the ON-set F, and add them to the OFF-set D.
+
+    Sometimes EXPAND can determine that a cube is not an essential prime.
+    If so, it will set the "NONESSEN" flag in the cube.
+
+    We count on IRREDUNDANT to have set the flag RELESSEN to indicate
+    that a prime was relatively essential (i.e., covers some minterm
+    not contained in any other prime in the current cover), or to have
+    reset the flag to indicate that a prime was relatively redundant
+    (i.e., all minterms covered by other primes in the current cover).
+    Of course, after executing irredundant, all of the primes in the
+    cover are relatively essential, but we can mark the primes which
+    were redundant at the start of irredundant and avoid an extra check
+    on these primes for essentiality.
+*/
+
+pcover essential(Fp, Dp)
+IN pcover *Fp, *Dp;
+{
+    register pcube last, p;
+    pcover E, F = *Fp, D = *Dp;
+
+    /* set all cubes in F active */
+    (void) sf_active(F);
+
+    /* Might as well start out with some cubes in E */
+    E = new_cover(10);
+
+    foreach_set(F, last, p) {
+	/* don't test a prime which EXPAND says is nonessential */
+	if (! TESTP(p, NONESSEN)) {
+	    /* only test a prime which was relatively essential */
+	    if (TESTP(p, RELESSEN)) {
+		/* Check essentiality */
+		if (essen_cube(F, D, p)) {
+		    if (debug & ESSEN)
+			printf("ESSENTIAL: %s\n", pc1(p));
+		    E = sf_addset(E, p);
+		    RESET(p, ACTIVE);
+		    F->active_count--;
+		}
+	    }
+	}
+    }
+
+    *Fp = sf_inactive(F);               /* delete the inactive cubes from F */
+    *Dp = sf_join(D, E);		/* add the essentials to D */
+    sf_free(D);
+    return E;
+}
+
+/*
+    essen_cube -- check if a single cube is essential or not
+
+    The prime c is essential iff
+
+	consensus((F u D) # c, c) u D
+
+    does not contain c.
+*/
+bool essen_cube(F, D, c)
+IN pcover F, D;
+IN pcube c;
+{
+    pcover H, FD;
+    pcube *H1;
+    bool essen;
+
+    /* Append F and D together, and take the sharp-consensus with c */
+    FD = sf_join(F, D);
+    H = cb_consensus(FD, c);
+    free_cover(FD);
+
+    /* Add the don't care set, and see if this covers c */
+    H1 = cube2list(H, D);
+    essen = ! cube_is_covered(H1, c);
+    free_cubelist(H1);
+
+    free_cover(H);
+    return essen;
+}
+
+
+/*
+ *  cb_consensus -- compute consensus(T # c, c)
+ */
+pcover cb_consensus(T, c)
+register pcover T;
+register pcube c;
+{
+    register pcube temp, last, p;
+    register pcover R;
+
+    R = new_cover(T->count*2);
+    temp = new_cube();
+    foreach_set(T, last, p) {
+	if (p != c) {
+	    switch (cdist01(p, c)) {
+		case 0:
+		    /* distance-0 needs special care */
+		    R = cb_consensus_dist0(R, p, c);
+		    break;
+
+		case 1:
+		    /* distance-1 is easy because no sharping required */
+		    consensus(temp, p, c);
+		    R = sf_addset(R, temp);
+		    break;
+	    }
+	}
+    }
+    set_free(temp);
+    return R;
+}
+
+
+/*
+ *  form the sharp-consensus for p and c when they intersect
+ *  What we are forming is consensus(p # c, c).
+ */
+pcover cb_consensus_dist0(R, p, c)
+pcover R;
+register pcube p, c;
+{
+    int var;
+    bool got_one;
+    register pcube temp, mask;
+    register pcube p_diff_c=cube.temp[0], p_and_c=cube.temp[1];
+
+    /* If c contains p, then this gives us no information for essential test */
+    if (setp_implies(p, c)) {
+	return R;
+    }
+
+    /* For the multiple-valued variables */
+    temp = new_cube();
+    got_one = FALSE;
+    INLINEset_diff(p_diff_c, p, c);
+    INLINEset_and(p_and_c, p, c);
+
+    for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+	/* Check if c(var) is contained in p(var) -- if so, no news */
+	mask = cube.var_mask[var];
+	if (! setp_disjoint(p_diff_c, mask)) {
+	    INLINEset_merge(temp, c, p_and_c, mask);
+	    R = sf_addset(R, temp);
+	    got_one = TRUE;
+	}
+    }
+
+    /* if no cube so far, add one for the intersection */
+    if (! got_one && cube.num_binary_vars > 0) {
+	/* Add a single cube for the intersection of p and c */
+	INLINEset_and(temp, p, c);
+	R = sf_addset(R, temp);
+    }
+
+    set_free(temp);
+    return R;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/exact.c b/abc-build/src/misc/espresso/exact.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/exact.c
@@ -0,0 +1,186 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+static void dump_irredundant();
+static pcover do_minimize();
+
+
+/*
+ *  minimize_exact -- main entry point for exact minimization
+ *
+ *  Global flags which affect this routine are:
+ *
+ *      debug
+ *      skip_make_sparse
+ */
+
+pcover
+minimize_exact(F, D, R, exact_cover)
+pcover F, D, R;
+int exact_cover;
+{
+    return do_minimize(F, D, R, exact_cover, /*weighted*/ 0);
+}
+
+
+pcover
+minimize_exact_literals(F, D, R, exact_cover)
+pcover F, D, R;
+int exact_cover;
+{
+    return do_minimize(F, D, R, exact_cover, /*weighted*/ 1);
+}
+
+
+
+static pcover
+do_minimize(F, D, R, exact_cover, weighted)
+pcover F, D, R;
+int exact_cover;
+int weighted;
+{
+    pcover newF, E, Rt, Rp;
+    pset p, last;
+    int heur, level, *weights, i;
+    sm_matrix *table;
+    sm_row *cover;
+    sm_element *pe;
+    int debug_save = debug;
+
+    if (debug & EXACT) {
+	debug |= (IRRED | MINCOV);
+    }
+#if defined(sun) || defined(bsd4_2)			/* hack ... */
+    if (debug & MINCOV) {
+	setlinebuf(stdout);
+    }
+#endif
+    level = (debug & MINCOV) ? 4 : 0;
+    heur = ! exact_cover;
+
+    /* Generate all prime implicants */
+    EXEC(F = primes_consensus(cube2list(F, D)), "PRIMES     ", F);
+
+    /* Setup the prime implicant table */
+    EXEC(irred_split_cover(F, D, &E, &Rt, &Rp), "ESSENTIALS ", E);
+    EXEC(table = irred_derive_table(D, E, Rp),  "PI-TABLE   ", Rp);
+
+    /* Solve either a weighted or nonweighted covering problem */
+    if (weighted) {
+	/* correct only for all 2-valued variables */
+	weights = ALLOC(int, F->count);
+	foreach_set(Rp, last, p) {
+	    weights[SIZE(p)] = cube.size - set_ord(p);
+	    /* We have added the 0's in the output part instead of the 1's.
+	       This loop corrects the literal count. */
+	    for (i = cube.first_part[cube.output];
+		 i <= cube.last_part[cube.output]; i++) {
+		is_in_set(p, i) ? weights[SIZE(p)]++ : weights[SIZE(p)]--;
+	    }
+	}
+    } else {
+	weights = NIL(int);
+    }
+    EXEC(cover=sm_minimum_cover(table,weights,heur,level), "MINCOV     ", F);
+    if (weights != 0) {
+	FREE(weights);
+    }
+
+    if (debug & EXACT) {
+	dump_irredundant(E, Rt, Rp, table);
+    }
+
+    /* Form the result cover */
+    newF = new_cover(100);
+    foreach_set(E, last, p) {
+	newF = sf_addset(newF, p);
+    }
+    sm_foreach_row_element(cover, pe) {
+	newF = sf_addset(newF, GETSET(F, pe->col_num));
+    }
+
+    free_cover(E);
+    free_cover(Rt);
+    free_cover(Rp);
+    sm_free(table);
+    sm_row_free(cover);
+    free_cover(F);
+
+    /* Attempt to make the results more sparse */
+    debug &= ~ (IRRED | SHARP | MINCOV);
+    if (! skip_make_sparse && R != 0) {
+	newF = make_sparse(newF, D, R);
+    }
+
+    debug = debug_save;
+    return newF;
+}
+
+static void
+dump_irredundant(E, Rt, Rp, table)
+pcover E, Rt, Rp;
+sm_matrix *table;
+{
+    FILE *fp_pi_table, *fp_primes;
+    pPLA PLA;
+    pset last, p;
+    char *file;
+
+    if (filename == 0 || strcmp(filename, "(stdin)") == 0) {
+	fp_pi_table = fp_primes = stdout;
+    } else {
+	file = ALLOC(char, strlen(filename)+20);
+	(void) sprintf(file, "%s.primes", filename);
+	if ((fp_primes = fopen(file, "w")) == NULL) {
+	    (void) fprintf(stderr, "espresso: Unable to open %s\n", file);
+	    fp_primes = stdout;
+	}
+	(void) sprintf(file, "%s.pi", filename);
+	if ((fp_pi_table = fopen(file, "w")) == NULL) {
+	    (void) fprintf(stderr, "espresso: Unable to open %s\n", file);
+	    fp_pi_table = stdout;
+	}
+	FREE(file);
+    }
+
+    PLA = new_PLA();
+    PLA_labels(PLA);
+
+    fpr_header(fp_primes, PLA, F_type);
+    free_PLA(PLA);
+
+    (void) fprintf(fp_primes, "# Essential primes are\n");
+    foreach_set(E, last, p) {
+	(void) fprintf(fp_primes, "%s\n", pc1(p));
+    }
+    (void) fprintf(fp_primes, "# Totally redundant primes are\n");
+    foreach_set(Rt, last, p) {
+	(void) fprintf(fp_primes, "%s\n", pc1(p));
+    }
+    (void) fprintf(fp_primes, "# Partially redundant primes are\n");
+    foreach_set(Rp, last, p) {
+	(void) fprintf(fp_primes, "%s\n", pc1(p));
+    }
+    if (fp_primes != stdout) {
+	(void) fclose(fp_primes);
+    }
+	
+    sm_write(fp_pi_table, table);
+    if (fp_pi_table != stdout) {
+	(void) fclose(fp_pi_table);
+    }
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/expand.c b/abc-build/src/misc/espresso/expand.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/expand.c
@@ -0,0 +1,700 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+    module: expand.c
+    purpose: Perform the Espresso-II Expansion Step
+
+    The idea is to take each nonprime cube of the on-set and expand it
+    into a prime implicant such that we can cover as many other cubes
+    of the on-set.  If no cube of the on-set can be covered, then we
+    expand each cube into a large prime implicant by transforming the
+    problem into a minimum covering problem which is solved by the
+    heuristics of minimum_cover.
+
+    These routines revolve around having a representation of the
+    OFF-set.  (In contrast to the Espresso-II manuscript, we do NOT
+    require an "unwrapped" version of the OFF-set).
+
+    Some conventions on variable names:
+
+	SUPER_CUBE is the supercube of all cubes which can be covered
+	by an expansion of the cube being expanded
+
+	OVEREXPANDED_CUBE is the cube which would result from expanding
+	all parts which can expand individually of the cube being expanded
+
+	RAISE is the current expansion of the current cube
+
+	FREESET is the set of parts which haven't been raised or lowered yet.
+
+	INIT_LOWER is a set of parts to be removed from the free parts before
+	starting the expansion
+*/
+
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+    expand -- expand each nonprime cube of F into a prime implicant
+
+    If nonsparse is true, only the non-sparse variables will be expanded;
+    this is done by forcing all of the sparse variables out of the free set.
+*/
+
+pcover expand(F, R, nonsparse)
+INOUT pcover F;
+IN pcover R;
+IN bool nonsparse;              /* expand non-sparse variables only */
+{
+    register pcube last, p;
+    pcube RAISE, FREESET, INIT_LOWER, SUPER_CUBE, OVEREXPANDED_CUBE;
+    int var, num_covered;
+    bool change;
+
+    /* Order the cubes according to "chewing-away from the edges" of mini */
+    if (use_random_order)
+	F = random_order(F);
+    else
+	F = mini_sort(F, ascend);
+
+    /* Allocate memory for variables needed by expand1() */
+    RAISE = new_cube();
+    FREESET = new_cube();
+    INIT_LOWER = new_cube();
+    SUPER_CUBE = new_cube();
+    OVEREXPANDED_CUBE = new_cube();
+
+    /* Setup the initial lowering set (differs only for nonsparse) */
+    if (nonsparse)
+	for(var = 0; var < cube.num_vars; var++)
+	    if (cube.sparse[var])
+		(void) set_or(INIT_LOWER, INIT_LOWER, cube.var_mask[var]);
+
+    /* Mark all cubes as not covered, and maybe essential */
+    foreach_set(F, last, p) {
+	RESET(p, COVERED);
+	RESET(p, NONESSEN);
+    }
+
+    /* Try to expand each nonprime and noncovered cube */
+    foreach_set(F, last, p) {
+	/* do not expand if PRIME or if covered by previous expansion */
+	if (! TESTP(p, PRIME) && ! TESTP(p, COVERED)) {
+
+	    /* expand the cube p, result is RAISE */
+	    expand1(R, F, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE,
+		INIT_LOWER, &num_covered, p);
+	    if (debug & EXPAND)
+		printf("EXPAND: %s (covered %d)\n", pc1(p), num_covered);
+	    (void) set_copy(p, RAISE);
+	    SET(p, PRIME);
+	    RESET(p, COVERED);		/* not really necessary */
+
+	    /* See if we generated an inessential prime */
+	    if (num_covered == 0 && ! setp_equal(p, OVEREXPANDED_CUBE)) {
+		SET(p, NONESSEN);
+	    }
+	}
+    }
+
+    /* Delete any cubes of F which became covered during the expansion */
+    F->active_count = 0;
+    change = FALSE;
+    foreach_set(F, last, p) {
+	if (TESTP(p, COVERED)) {
+	    RESET(p, ACTIVE);
+	    change = TRUE;
+	} else {
+	    SET(p, ACTIVE);
+	    F->active_count++;
+	}
+    }
+    if (change)
+	F = sf_inactive(F);
+
+    free_cube(RAISE);
+    free_cube(FREESET);
+    free_cube(INIT_LOWER);
+    free_cube(SUPER_CUBE);
+    free_cube(OVEREXPANDED_CUBE);
+    return F;
+}
+
+/*
+    expand1 -- Expand a single cube against the OFF-set
+*/
+void expand1(BB, CC, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE,
+		INIT_LOWER, num_covered, c)
+pcover BB;			/* Blocking matrix (OFF-set) */
+pcover CC;			/* Covering matrix (ON-set) */
+pcube RAISE;			/* The current parts which have been raised */
+pcube FREESET;			/* The current parts which are free */
+pcube OVEREXPANDED_CUBE;	/* Overexpanded cube of c */
+pcube SUPER_CUBE;		/* Supercube of all cubes of CC we cover */
+pcube INIT_LOWER;		/* Parts to initially remove from FREESET */
+int *num_covered;		/* Number of cubes of CC which are covered */
+pcube c;			/* The cube to be expanded */
+{
+    int bestindex;
+
+    if (debug & EXPAND1)
+	printf("\nEXPAND1:    \t%s\n", pc1(c));
+
+    /* initialize BB and CC */
+    SET(c, PRIME);		/* don't try to cover ourself */
+    setup_BB_CC(BB, CC);
+
+    /* initialize count of # cubes covered, and the supercube of them */
+    *num_covered = 0;
+    (void) set_copy(SUPER_CUBE, c);
+
+    /* Initialize the lowering, raising and unassigned sets */
+    (void) set_copy(RAISE, c);
+    (void) set_diff(FREESET, cube.fullset, RAISE);
+
+    /* If some parts are forced into lowering set, remove them */
+    if (! setp_empty(INIT_LOWER)) {
+	(void) set_diff(FREESET, FREESET, INIT_LOWER);
+	elim_lowering(BB, CC, RAISE, FREESET);
+    }
+
+    /* Determine what can be raised, and return the over-expanded cube */
+    essen_parts(BB, CC, RAISE, FREESET);
+    (void) set_or(OVEREXPANDED_CUBE, RAISE, FREESET);
+
+    /* While there are still cubes which can be covered, cover them ! */
+    if (CC->active_count > 0) {
+	select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered);
+    }
+
+    /* While there are still cubes covered by the overexpanded cube ... */
+    while (CC->active_count > 0) {
+	bestindex = most_frequent(CC, FREESET);
+	set_insert(RAISE, bestindex);
+	set_remove(FREESET, bestindex);
+	essen_parts(BB, CC, RAISE, FREESET);
+    }
+
+    /* Finally, when all else fails, choose the largest possible prime */
+    /* We will loop only if we decide unravelling OFF-set is too expensive */
+    while (BB->active_count > 0) {
+	mincov(BB, RAISE, FREESET);
+    }
+
+    /* Raise any remaining free coordinates */
+    (void) set_or(RAISE, RAISE, FREESET);
+}
+
+/*
+    essen_parts -- determine which parts are forced into the lowering
+    set to insure that the cube be orthognal to the OFF-set.
+
+    If any cube of the OFF-set is distance 1 from the raising cube,
+    then we must lower all parts of the conflicting variable.  (If the
+    cube is distance 0, we detect this error here.)
+
+    If there are essentially lowered parts, we can remove from consideration
+    any cubes of the OFF-set which are more than distance 1 from the
+    overexpanded cube of RAISE.
+*/
+
+void essen_parts(BB, CC, RAISE, FREESET)
+pcover BB, CC;
+pcube RAISE, FREESET;
+{
+    register pcube p, r = RAISE;
+    pcube lastp, xlower = cube.temp[0];
+    int dist;
+
+    (void) set_copy(xlower, cube.emptyset);
+
+    foreach_active_set(BB, lastp, p) {
+#ifdef NO_INLINE
+	if ((dist = cdist01(p, r)) > 1) goto exit_if;
+#else
+ {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1)
+{x=p[last]&r[last];if((x=~(x|x>>1)&cube.inmask))if((dist=count_ones(x))>1)goto
+exit_if;for(w=1;w<last;w++){x=p[w]&r[w];if((x=~(x|x>>1)&DISJOINT))if(dist==1||(
+dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube
+mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.var_mask[
+var];last=cube.last_word[var];for(w=cube.first_word[var];w<=last;w++)if(p[w]&r[
+w]&mask[w])goto nextvar;if(++dist>1)goto exit_if;nextvar:;}}
+#endif
+	if (dist == 0) {
+	    fatal("ON-set and OFF-set are not orthogonal");
+	} else {
+	    (void) force_lower(xlower, p, r);
+	    BB->active_count--;
+	    RESET(p, ACTIVE);
+	}
+exit_if: ;
+    }
+
+    if (! setp_empty(xlower)) {
+	(void) set_diff(FREESET, FREESET, xlower);/* remove from free set */
+	elim_lowering(BB, CC, RAISE, FREESET);
+    }
+
+    if (debug & EXPAND1)
+	printf("ESSEN_PARTS:\tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
+}
+
+/*
+    essen_raising -- determine which parts may always be added to
+    the raising set without restricting further expansions
+
+    General rule: if some part is not blocked by any cube of BB, then
+    this part can always be raised.
+*/
+
+void essen_raising(BB, RAISE, FREESET)
+register pcover BB;
+pcube RAISE, FREESET;
+{
+    register pcube last, p, xraise = cube.temp[0];
+
+    /* Form union of all cubes of BB, and then take complement wrt FREESET */
+    (void) set_copy(xraise, cube.emptyset);
+    foreach_active_set(BB, last, p)
+	INLINEset_or(xraise, xraise, p);
+    (void) set_diff(xraise, FREESET, xraise);
+
+    (void) set_or(RAISE, RAISE, xraise);         /* add to raising set */
+    (void) set_diff(FREESET, FREESET, xraise);       /* remove from free set */
+
+    if (debug & EXPAND1)
+	printf("ESSEN_RAISING:\tRAISE=%s FREESET=%s\n",
+	    pc1(RAISE), pc2(FREESET));
+}
+
+/*
+    elim_lowering -- after removing parts from FREESET, we can reduce the
+    size of both BB and CC.
+
+    We mark as inactive any cube of BB which does not intersect the
+    overexpanded cube (i.e., RAISE + FREESET).  Likewise, we remove
+    from CC any cube which is not covered by the overexpanded cube.
+*/
+
+void elim_lowering(BB, CC, RAISE, FREESET)
+pcover BB, CC;
+pcube RAISE, FREESET;
+{
+    register pcube p, r = set_or(cube.temp[0], RAISE, FREESET);
+    pcube last;
+
+    /*
+     *  Remove sets of BB which are orthogonal to future expansions
+     */
+    foreach_active_set(BB, last, p) {
+#ifdef NO_INLINE
+	if (! cdist0(p, r))
+#else
+ {register int w,lastw;register unsigned int x;if((lastw=cube.inword)!=-1){x=p[
+lastw]&r[lastw];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w<lastw;w++){x=p[w]
+&r[w];if(~(x|x>>1)&DISJOINT)goto false;}}}{register int w,var,lastw;register
+pcube mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.
+var_mask[var];lastw=cube.last_word[var];for(w=cube.first_word[var];w<=lastw;w++)
+if(p[w]&r[w]&mask[w])goto nextvar;goto false;nextvar:;}}continue;false:
+#endif
+	    BB->active_count--, RESET(p, ACTIVE);
+    }
+
+
+    /*
+     *  Remove sets of CC which cannot be covered by future expansions
+     */
+    if (CC != (pcover) NULL) {
+	foreach_active_set(CC, last, p) {
+#ifdef NO_INLINE
+	    if (! setp_implies(p, r))
+#else
+	    INLINEsetp_implies(p, r, /* when false => */ goto false1);
+	    /* when true => go to end of loop */ continue;
+	    false1:
+#endif
+		CC->active_count--, RESET(p, ACTIVE);
+	}
+    }
+}
+
+/*
+    most_frequent -- When all else fails, select a reasonable part to raise
+    The active cubes of CC are the cubes which are covered by the
+    overexpanded cube of the original cube (however, we know that none
+    of them can actually be covered by a feasible expansion of the
+    original cube).  We resort to the MINI strategy of selecting to
+    raise the part which will cover the same part in the most cubes of CC.
+*/
+int most_frequent(CC, FREESET)
+pcover CC;
+pcube FREESET;
+{
+    register int i, best_part, best_count, *count;
+    register pset p, last;
+
+    /* Count occurences of each variable */
+    count = ALLOC(int, cube.size);
+    for(i = 0; i < cube.size; i++)
+	count[i] = 0;
+    if (CC != (pcover) NULL)
+	foreach_active_set(CC, last, p)
+	    set_adjcnt(p, count, 1);
+
+    /* Now find which free part occurs most often */
+    best_count = best_part = -1;
+    for(i = 0; i < cube.size; i++)
+	if (is_in_set(FREESET,i) && count[i] > best_count) {
+	    best_part = i;
+	    best_count = count[i];
+	}
+    FREE(count);
+
+    if (debug & EXPAND1)
+	printf("MOST_FREQUENT:\tbest=%d FREESET=%s\n", best_part, pc2(FREESET));
+    return best_part;
+}
+
+/*
+    setup_BB_CC -- set up the blocking and covering set families;
+
+    Note that the blocking family is merely the set of cubes of R, and
+    that CC is the set of cubes of F which might possibly be covered
+    (i.e., nonprime cubes, and cubes not already covered)
+*/
+
+void setup_BB_CC(BB, CC)
+register pcover BB, CC;
+{
+    register pcube p, last;
+
+    /* Create the block and cover set families */
+    BB->active_count = BB->count;
+    foreach_set(BB, last, p)
+	SET(p, ACTIVE);
+
+    if (CC != (pcover) NULL) {
+	CC->active_count = CC->count;
+	foreach_set(CC, last, p)
+	    if (TESTP(p, COVERED) || TESTP(p, PRIME))
+		CC->active_count--, RESET(p, ACTIVE);
+	    else
+		SET(p, ACTIVE);
+    }
+}
+
+/*
+    select_feasible -- Determine if there are cubes which can be covered,
+    and if so, raise those parts necessary to cover as many as possible.
+
+    We really don't check to maximize the number that can be covered;
+    instead, we check, for each fcc, how many other fcc remain fcc
+    after expanding to cover the fcc.  (Essentially one-level lookahead).
+*/
+
+void select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered)
+pcover BB, CC;
+pcube RAISE, FREESET, SUPER_CUBE;
+int *num_covered;
+{
+    register pcube p, last;
+    register pcube bestfeas = NULL; // Suppress "might be used uninitialized"
+    register pcube *feas;
+    register int i, j;
+    pcube *feas_new_lower;
+    int bestcount, bestsize, count, size, numfeas, lastfeas;
+    pcover new_lower;
+
+    /*  Start out with all cubes covered by the over-expanded cube as
+     *  the "possibly" feasibly-covered cubes (pfcc)
+     */
+    feas = ALLOC(pcube, CC->active_count);
+    numfeas = 0;
+    foreach_active_set(CC, last, p)
+	feas[numfeas++] = p;
+
+    /* Setup extra cubes to record parts forced low after a covering */
+    feas_new_lower = ALLOC(pcube, CC->active_count);
+    new_lower = new_cover(numfeas);
+    for(i = 0; i < numfeas; i++)
+	feas_new_lower[i] = GETSET(new_lower, i);
+
+
+loop:
+    /* Find the essentially raised parts -- this might cover some cubes
+       for us, without having to find out if they are fcc or not
+    */
+    essen_raising(BB, RAISE, FREESET);
+
+    /* Now check all "possibly" feasibly covered cubes to check feasibility */
+    lastfeas = numfeas;
+    numfeas = 0;
+    for(i = 0; i < lastfeas; i++) {
+	p = feas[i];
+
+	/* Check active because essen_parts might have removed it */
+	if (TESTP(p, ACTIVE)) {
+
+	    /*  See if the cube is already covered by RAISE --
+	     *  this can happen because of essen_raising() or because of
+	     *  the previous "loop"
+	     */
+	    if (setp_implies(p, RAISE)) {
+		(*num_covered) += 1;
+		(void) set_or(SUPER_CUBE, SUPER_CUBE, p);
+		CC->active_count--;
+		RESET(p, ACTIVE);
+		SET(p, COVERED);
+	    /* otherwise, test if it is feasibly covered */
+	    } else if (feasibly_covered(BB,p,RAISE,feas_new_lower[numfeas])) {
+		feas[numfeas] = p;			/* save the fcc */
+		numfeas++;
+	    }
+	}
+    }
+    if (debug & EXPAND1)
+	printf("SELECT_FEASIBLE: started with %d pfcc, ended with %d fcc\n",
+	    lastfeas, numfeas);
+
+    /* Exit here if there are no feasibly covered cubes */
+    if (numfeas == 0) {
+	FREE(feas);
+	FREE(feas_new_lower);
+	free_cover(new_lower);
+	return;
+    }
+
+    /* Now find which is the best feasibly covered cube */
+    bestcount = 0;
+    bestsize = 9999;
+    for(i = 0; i < numfeas; i++) {
+	size = set_dist(feas[i], FREESET);	/* # of newly raised parts */
+	count = 0;	/* # of other cubes which remain fcc after raising */
+
+#define NEW
+#ifdef NEW
+	for(j = 0; j < numfeas; j++)
+	    if (setp_disjoint(feas_new_lower[i], feas[j]))
+		count++;
+#else
+	for(j = 0; j < numfeas; j++)
+	    if (setp_implies(feas[j], feas[i]))
+		count++;
+#endif
+	if (count > bestcount) {
+	    bestcount = count;
+	    bestfeas = feas[i];
+	    bestsize = size;
+	} else if (count == bestcount && size < bestsize) {
+	    bestfeas = feas[i];
+	    bestsize = size;
+	}
+    }
+
+    /* Add the necessary parts to the raising set */
+    (void) set_or(RAISE, RAISE, bestfeas);
+    (void) set_diff(FREESET, FREESET, RAISE);
+    if (debug & EXPAND1)
+	printf("FEASIBLE:  \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
+    essen_parts(BB, CC, RAISE, FREESET);
+    goto loop;
+/* NOTREACHED */
+}
+
+/*
+    feasibly_covered -- determine if the cube c is feasibly covered
+    (i.e., if it is possible to raise all of the necessary variables
+    while still insuring orthogonality with R).  Also, if c is feasibly
+    covered, then compute the new set of parts which are forced into
+    the lowering set.
+*/
+
+bool feasibly_covered(BB, c, RAISE, new_lower)
+pcover BB;
+pcube c, RAISE, new_lower;
+{
+    register pcube p, r = set_or(cube.temp[0], RAISE, c);
+    int dist;
+    pcube lastp;
+
+    set_copy(new_lower, cube.emptyset);
+    foreach_active_set(BB, lastp, p) {
+#ifdef NO_INLINE
+	if ((dist = cdist01(p, r)) > 1) goto exit_if;
+#else
+ {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1)
+{x=p[last]&r[last];if((x=~(x|x>>1)&cube.inmask))if((dist=count_ones(x))>1)goto
+exit_if;for(w=1;w<last;w++){x=p[w]&r[w];if((x=~(x|x>>1)&DISJOINT))if(dist==1||(
+dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube
+mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.var_mask[
+var];last=cube.last_word[var];for(w=cube.first_word[var];w<=last;w++)if(p[w]&r[
+w]&mask[w])goto nextvar;if(++dist>1)goto exit_if;nextvar:;}}
+#endif
+	if (dist == 0)
+	    return FALSE;
+	else
+	    (void) force_lower(new_lower, p, r);
+    exit_if: ;
+    }
+    return TRUE;
+}
+
+/*
+    mincov -- transform the problem of expanding a cube to a maximally-
+    large prime implicant into the problem of selecting a minimum
+    cardinality cover over a family of sets.
+
+    When we get to this point, we must unravel the remaining off-set.
+    This may be painful.
+*/
+
+void mincov(BB, RAISE, FREESET)
+pcover BB;
+pcube RAISE, FREESET;
+{
+    int expansion, nset, var, dist;
+    pset_family B;
+    register pcube xraise=cube.temp[0], xlower, p, last, plower;
+
+#ifdef RANDOM_MINCOV
+#if defined(_POSIX_SOURCE) || defined(__SVR4)
+    dist = rand() % set_ord(FREESET);
+#else
+    dist = random() % set_ord(FREESET);
+#endif
+    for(var = 0; var < cube.size && dist >= 0; var++) {
+	if (is_in_set(FREESET, var)) {
+	    dist--;
+	}
+    }
+
+    set_insert(RAISE, var);
+    set_remove(FREESET, var);
+    (void) essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET);
+#else
+
+    /* Create B which are those cubes which we must avoid intersecting */
+    B = new_cover(BB->active_count);
+    foreach_active_set(BB, last, p) {
+	plower = set_copy(GETSET(B, B->count++), cube.emptyset);
+	(void) force_lower(plower, p, RAISE);
+    }
+
+    /* Determine how many sets it will blow up into after the unravel */
+    nset = 0;
+    foreach_set(B, last, p) {
+	expansion = 1;
+	for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+	    if ((dist=set_dist(p, cube.var_mask[var])) > 1) {
+		expansion *= dist;
+		if (expansion > 500) goto heuristic_mincov;
+	    }
+	}
+	nset += expansion;
+	if (nset > 500) goto heuristic_mincov;
+    }
+
+    B = unravel(B, cube.num_binary_vars);
+    xlower = do_sm_minimum_cover(B);
+
+    /* Add any remaining free parts to the raising set */
+    (void) set_or(RAISE, RAISE, set_diff(xraise, FREESET, xlower));
+    (void) set_copy(FREESET, cube.emptyset);	/* free set is empty */
+    BB->active_count = 0;			/* BB satisfied */
+    if (debug & EXPAND1) {
+	printf("MINCOV:    \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
+    }
+    sf_free(B);
+    set_free(xlower);
+    return;
+
+heuristic_mincov:
+    sf_free(B);
+    /* most_frequent will pick first free part */
+    set_insert(RAISE, most_frequent(/*CC*/ (pcover) NULL, FREESET));
+    (void) set_diff(FREESET, FREESET, RAISE);
+    essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET);
+    return;
+#endif
+}
+
+/*
+    find_all_primes -- find all of the primes which cover the
+    currently reduced BB
+*/
+pcover find_all_primes(BB, RAISE, FREESET)
+pcover BB;
+register pcube RAISE, FREESET;
+{
+    register pset last, p, plower;
+    pset_family B, B1;
+
+    if (BB->active_count == 0) {
+	B1 = new_cover(1);
+	p = GETSET(B1, B1->count++);
+	(void) set_copy(p, RAISE);
+	SET(p, PRIME);
+    } else {
+	B = new_cover(BB->active_count);
+	foreach_active_set(BB, last, p) {
+	    plower = set_copy(GETSET(B, B->count++), cube.emptyset);
+	    (void) force_lower(plower, p, RAISE);
+	}
+	B = sf_rev_contain(unravel(B, cube.num_binary_vars));
+	B1 = exact_minimum_cover(B);
+	foreach_set(B1, last, p) {
+	    INLINEset_diff(p, FREESET, p);
+	    INLINEset_or(p, p, RAISE);
+	    SET(p, PRIME);
+	}
+	free_cover(B);
+    }
+    return B1;
+}
+
+/*
+    all_primes -- foreach cube in F, generate all of the primes
+    which cover the cube.
+*/
+
+pcover all_primes(F, R)
+pcover F, R;
+{
+    register pcube last, p, RAISE, FREESET;
+    pcover Fall_primes, B1;
+
+    FREESET = new_cube();
+    RAISE = new_cube();
+    Fall_primes = new_cover(F->count);
+
+    foreach_set(F, last, p) {
+	if (TESTP(p, PRIME)) {
+	    Fall_primes = sf_addset(Fall_primes, p);
+	} else {
+	    /* Setup for call to essential parts */
+	    (void) set_copy(RAISE, p);
+	    (void) set_diff(FREESET, cube.fullset, RAISE);
+	    setup_BB_CC(R, /* CC */ (pcover) NULL);
+	    essen_parts(R, /* CC */ (pcover) NULL, RAISE, FREESET);
+
+	    /* Find all of the primes, and add them to the prime set */
+	    B1 = find_all_primes(R, RAISE, FREESET);
+	    Fall_primes = sf_append(Fall_primes, B1);
+	}
+    }
+
+    set_free(RAISE);
+    set_free(FREESET);
+    return Fall_primes;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/gasp.c b/abc-build/src/misc/espresso/gasp.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/gasp.c
@@ -0,0 +1,233 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+    module: gasp.c
+
+    The "last_gasp" heuristic computes the reduction of each cube in
+    the cover (without replacement) and then performs an expansion of
+    these cubes.  The cubes which expand to cover some other cube are
+    added to the original cover and irredundant finds a minimal subset.
+
+    If one of the reduced cubes expands to cover some other reduced
+    cube, then the new prime thus generated is a candidate for reducing
+    the size of the cover.
+
+    super_gasp is a variation on this strategy which extracts a minimal
+    subset from the set of all prime implicants which cover all
+    maximally reduced cubes.
+*/
+
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*
+ *  reduce_gasp -- compute the maximal reduction of each cube of F
+ *
+ *  If a cube does not reduce, it remains prime; otherwise, it is marked
+ *  as nonprime.   If the cube is redundant (should NEVER happen here) we
+ *  just crap out ...
+ *
+ *  A cover with all of the cubes of F is returned.  Those that did
+ *  reduce are marked "NONPRIME"; those that reduced are marked "PRIME".
+ *  The cubes are in the same order as in F.
+ */
+static pcover reduce_gasp(F, D)
+pcover F, D;
+{
+    pcube p, last, cunder, *FD;
+    pcover G;
+
+    G = new_cover(F->count);
+    FD = cube2list(F, D);
+
+    /* Reduce cubes of F without replacement */
+    foreach_set(F, last, p) {
+	cunder = reduce_cube(FD, p);
+	if (setp_empty(cunder)) {
+	    fatal("empty reduction in reduce_gasp, shouldn't happen");
+	} else if (setp_equal(cunder, p)) {
+	    SET(cunder, PRIME);			/* just to make sure */
+	    G = sf_addset(G, p);		/* it did not reduce ... */
+	} else {
+	    RESET(cunder, PRIME);		/* it reduced ... */
+	    G = sf_addset(G, cunder);
+	}
+	if (debug & GASP) {
+	    printf("REDUCE_GASP: %s reduced to %s\n", pc1(p), pc2(cunder));
+	}
+	free_cube(cunder);
+    }
+
+    free_cubelist(FD);
+    return G;
+}
+
+/*
+ *  expand_gasp -- expand each nonprime cube of F into a prime implicant
+ *
+ *  The gasp strategy differs in that only those cubes which expand to
+ *  cover some other cube are saved; also, all cubes are expanded
+ *  regardless of whether they become covered or not.
+ */
+
+pcover expand_gasp(F, D, R, Foriginal)
+INOUT pcover F;
+IN pcover D;
+IN pcover R;
+IN pcover Foriginal;
+{
+    int c1index;
+    pcover G;
+
+    /* Try to expand each nonprime and noncovered cube */
+    G = new_cover(10);
+    for(c1index = 0; c1index < F->count; c1index++) {
+	expand1_gasp(F, D, R, Foriginal, c1index, &G);
+    }
+    G = sf_dupl(G);
+    G = expand(G, R, /*nonsparse*/ FALSE);	/* Make them prime ! */
+    return G;
+}
+
+
+
+/*
+ *  expand1 -- Expand a single cube against the OFF-set, using the gasp strategy
+ */
+void expand1_gasp(F, D, R, Foriginal, c1index, G)
+pcover F;		/* reduced cubes of ON-set */
+pcover D;		/* DC-set */
+pcover R;		/* OFF-set */
+pcover Foriginal;	/* ON-set before reduction (same order as F) */
+int c1index;		/* which index of F (or Freduced) to be checked */
+pcover *G;
+{
+    register int c2index;
+    register pcube p, last, c2under;
+    pcube RAISE, FREESET, temp, *FD, c2essential;
+    pcover F1;
+
+    if (debug & EXPAND1) {
+	printf("\nEXPAND1_GASP:    \t%s\n", pc1(GETSET(F, c1index)));
+    }
+
+    RAISE = new_cube();
+    FREESET = new_cube();
+    temp = new_cube();
+
+    /* Initialize the OFF-set */
+    R->active_count = R->count;
+    foreach_set(R, last, p) {
+	SET(p, ACTIVE);
+    }
+    /* Initialize the reduced ON-set, all nonprime cubes become active */
+    F->active_count = F->count;
+    foreachi_set(F, c2index, c2under) {
+	if (c1index == c2index || TESTP(c2under, PRIME)) {
+	    F->active_count--;
+	    RESET(c2under, ACTIVE);
+	} else {
+	    SET(c2under, ACTIVE);
+	}
+    }
+
+    /* Initialize the raising and unassigned sets */
+    (void) set_copy(RAISE, GETSET(F, c1index));
+    (void) set_diff(FREESET, cube.fullset, RAISE);
+
+    /* Determine parts which must be lowered */
+    essen_parts(R, F, RAISE, FREESET);
+
+    /* Determine parts which can always be raised */
+    essen_raising(R, RAISE, FREESET);
+
+    /* See which, if any, of the reduced cubes we can cover */
+    foreachi_set(F, c2index, c2under) {
+	if (TESTP(c2under, ACTIVE)) {
+	    /* See if this cube can be covered by an expansion */
+	    if (setp_implies(c2under, RAISE) ||
+	      feasibly_covered(R, c2under, RAISE, temp)) {
+		
+		/* See if c1under can expanded to cover c2 reduced against
+		 * (F - c1) u c1under; if so, c2 can definitely be removed !
+		 */
+
+		/* Copy F and replace c1 with c1under */
+		F1 = sf_save(Foriginal);
+		(void) set_copy(GETSET(F1, c1index), GETSET(F, c1index));
+
+		/* Reduce c2 against ((F - c1) u c1under) */
+		FD = cube2list(F1, D);
+		c2essential = reduce_cube(FD, GETSET(F1, c2index));
+		free_cubelist(FD);
+		sf_free(F1);
+
+		/* See if c2essential is covered by an expansion of c1under */
+		if (feasibly_covered(R, c2essential, RAISE, temp)) {
+		    (void) set_or(temp, RAISE, c2essential);
+		    RESET(temp, PRIME);		/* cube not prime */
+		    *G = sf_addset(*G, temp);
+		}
+		set_free(c2essential);
+	    }
+	}
+    }
+
+    free_cube(RAISE);
+    free_cube(FREESET);
+    free_cube(temp);
+}
+
+/* irred_gasp -- Add new primes to F and find an irredundant subset */
+pcover irred_gasp(F, D, G)
+pcover F, D, G;                 /* G is disposed of */
+{
+    if (G->count != 0)
+	F = irredundant(sf_append(F, G), D);
+    else
+	free_cover(G);
+    return F;
+}
+
+
+/* last_gasp */
+pcover last_gasp(F, D, R, cost)
+pcover F, D, R;
+cost_t *cost;
+{
+    pcover G, G1;
+
+    EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost);
+    EXECUTE(G1 = expand_gasp(G, D, R, F), GEXPAND_TIME, G1, *cost);
+    free_cover(G);
+    EXECUTE(F = irred_gasp(F, D, G1), GIRRED_TIME, F, *cost);
+    return F;
+}
+
+
+/* super_gasp */
+pcover super_gasp(F, D, R, cost)
+pcover F, D, R;
+cost_t *cost;
+{
+    pcover G, G1;
+
+    EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost);
+    EXECUTE(G1 = all_primes(G, R), GEXPAND_TIME, G1, *cost);
+    free_cover(G);
+    EXEC(G = sf_dupl(sf_append(F, G1)), "NEWPRIMES", G);
+    EXECUTE(F = irredundant(G, D), IRRED_TIME, F, *cost);
+    return F;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/gimpel.c b/abc-build/src/misc/espresso/gimpel.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/gimpel.c
@@ -0,0 +1,112 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*
+ *  check for:
+ *
+ *		c1	c2	rest
+ *		--      --      ---
+ *		 1	 1	0 0 0 0		<-- primary row
+ *		 1	 0	S1		<-- secondary row
+ *		 0       1	T1
+ *		 0       1	T2
+ *		 0       1	Tn
+ *		 0       0      R
+ */
+
+int
+gimpel_reduce(A, select, weight, lb, bound, depth, stats, best)
+sm_matrix *A;
+solution_t *select;
+int *weight;
+int lb;
+int bound;
+int depth;
+stats_t *stats;
+solution_t **best;
+{
+    register sm_row *prow, *save_sec;
+    register sm_col *c1 = NULL, *c2 = NULL; // Suppress "might be used uninitialized"
+    register sm_element *p, *p1;
+    int c1_col_num, c2_col_num;
+    int primary_row_num = -1, secondary_row_num = -1; // Suppress "might be used uninitialized"
+    int reduce_it; 
+
+    reduce_it = 0;
+    for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+	if (prow->length == 2) {
+	    c1 = sm_get_col(A, prow->first_col->col_num);
+	    c2 = sm_get_col(A, prow->last_col->col_num);
+	    if (c1->length == 2) {
+		reduce_it = 1;
+	    } else if (c2->length == 2) {
+		c1 = sm_get_col(A, prow->last_col->col_num);
+		c2 = sm_get_col(A, prow->first_col->col_num);
+		reduce_it = 1;
+	    }
+	    if (reduce_it) {
+		primary_row_num = prow->row_num;
+		secondary_row_num = c1->first_row->row_num;
+		if (secondary_row_num == primary_row_num) {
+		    secondary_row_num = c1->last_row->row_num;
+		}
+		break;
+	    }
+	}
+    }
+
+    if (reduce_it) {
+	c1_col_num = c1->col_num;
+	c2_col_num = c2->col_num;
+	save_sec = sm_row_dup(sm_get_row(A, secondary_row_num));
+	sm_row_remove(save_sec, c1_col_num);
+
+	for(p = c2->first_row; p != 0; p = p->next_row) {
+	    if (p->row_num != primary_row_num) {
+		/* merge rows S1 and T */
+		for(p1 = save_sec->first_col; p1 != 0; p1 = p1->next_col) {
+		    (void) sm_insert(A, p->row_num, p1->col_num);
+		}
+	    }
+	}
+
+	sm_delcol(A, c1_col_num);
+	sm_delcol(A, c2_col_num);
+	sm_delrow(A, primary_row_num);
+	sm_delrow(A, secondary_row_num);
+
+	stats->gimpel_count++;
+	stats->gimpel++;
+	*best = sm_mincov(A, select, weight, lb-1, bound-1, depth, stats);
+	stats->gimpel--;
+
+	if (*best != NIL(solution_t)) {
+	    /* is secondary row covered ? */
+	    if (sm_row_intersects(save_sec, (*best)->row)) {
+		/* yes, actually select c2 */
+		solution_add(*best, weight, c2_col_num);
+	    } else {
+		solution_add(*best, weight, c1_col_num);
+	    }
+	}
+
+	sm_row_free(save_sec);
+	return 1;
+    } else {
+	return 0;
+    }
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/globals.c b/abc-build/src/misc/espresso/globals.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/globals.c
@@ -0,0 +1,81 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+ *    Global Variable Declarations
+ */
+
+unsigned int debug;              /* debug parameter */
+bool verbose_debug;              /* -v:  whether to print a lot */
+char *total_name[TIME_COUNT];    /* basic function names */
+long total_time[TIME_COUNT];     /* time spent in basic fcts */
+int total_calls[TIME_COUNT];     /* # calls to each fct */
+
+bool echo_comments;		 /* turned off by -eat option */
+bool echo_unknown_commands;	 /* always true ?? */
+bool force_irredundant;          /* -nirr command line option */
+bool skip_make_sparse;
+bool kiss;                       /* -kiss command line option */
+bool pos;                        /* -pos command line option */
+bool print_solution;             /* -x command line option */
+bool recompute_onset;            /* -onset command line option */
+bool remove_essential;           /* -ness command line option */
+bool single_expand;              /* -fast command line option */
+bool summary;                    /* -s command line option */
+bool trace;                      /* -t command line option */
+bool unwrap_onset;               /* -nunwrap command line option */
+bool use_random_order;		 /* -random command line option */
+bool use_super_gasp;		 /* -strong command line option */
+char *filename;			 /* filename PLA was read from */
+
+struct pla_types_struct pla_types[] = {
+    {"-f", F_type},
+    {"-r", R_type},
+    {"-d", D_type},
+    {"-fd", FD_type},
+    {"-fr", FR_type},
+    {"-dr", DR_type},
+    {"-fdr", FDR_type},
+    {"-fc", F_type | CONSTRAINTS_type},
+    {"-rc", R_type | CONSTRAINTS_type},
+    {"-dc", D_type | CONSTRAINTS_type},
+    {"-fdc", FD_type | CONSTRAINTS_type},
+    {"-frc", FR_type | CONSTRAINTS_type},
+    {"-drc", DR_type | CONSTRAINTS_type},
+    {"-fdrc", FDR_type | CONSTRAINTS_type},
+    {"-pleasure", PLEASURE_type},
+    {"-eqn", EQNTOTT_type},
+    {"-eqntott", EQNTOTT_type},
+    {"-kiss", KISS_type},
+    {"-cons", CONSTRAINTS_type},
+    {"-scons", SYMBOLIC_CONSTRAINTS_type},
+    {0, 0}
+};
+
+
+struct cube_struct cube, temp_cube_save;
+struct cdata_struct cdata, temp_cdata_save;
+
+int bit_count[256] = {
+  0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+  1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+  1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+  2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+  1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+  2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+  2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+  3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/hack.c b/abc-build/src/misc/espresso/hack.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/hack.c
@@ -0,0 +1,646 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+void map_dcset(PLA)
+pPLA PLA;
+{
+    int var, i;
+    pcover Tplus, Tminus, Tplusbar, Tminusbar;
+    pcover newf, term1, term2, dcset, dcsetbar;
+    pcube cplus, cminus, last, p;
+
+    if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char))
+	return;
+
+    /* try to find a binary variable named "DONT_CARE" */
+    var = -1;
+    for(i = 0; i < cube.num_binary_vars * 2; i++) {
+	if (strncmp(PLA->label[i], "DONT_CARE", 9) == 0 ||
+	  strncmp(PLA->label[i], "DONTCARE", 8) == 0 ||
+	  strncmp(PLA->label[i], "dont_care", 9) == 0 ||
+	  strncmp(PLA->label[i], "dontcare", 8) == 0) {
+	    var = i/2;
+	    break;
+	}
+    }
+    if (var == -1) {
+	return;
+    }
+
+    /* form the cofactor cubes for the don't-care variable */
+    cplus = set_save(cube.fullset);
+    cminus = set_save(cube.fullset);
+    set_remove(cplus, var*2);
+    set_remove(cminus, var*2 + 1);
+
+    /* form the don't-care set */
+    EXEC(simp_comp(cofactor(cube1list(PLA->F), cplus), &Tplus, &Tplusbar),
+	"simpcomp+", Tplus);
+    EXEC(simp_comp(cofactor(cube1list(PLA->F), cminus), &Tminus, &Tminusbar),
+	"simpcomp-", Tminus);
+    EXEC(term1 = cv_intersect(Tplus, Tminusbar), "term1    ", term1);
+    EXEC(term2 = cv_intersect(Tminus, Tplusbar), "term2    ", term2);
+    EXEC(dcset = sf_union(term1, term2), "union     ", dcset);
+    EXEC(simp_comp(cube1list(dcset), &PLA->D, &dcsetbar), "simplify", PLA->D);
+    EXEC(newf = cv_intersect(PLA->F, dcsetbar), "separate  ", PLA->F);
+    free_cover(PLA->F);
+    PLA->F = newf;
+    free_cover(Tplus);
+    free_cover(Tminus);
+    free_cover(Tplusbar);
+    free_cover(Tminusbar);
+    free_cover(dcsetbar);
+
+    /* remove any cubes dependent on the DONT_CARE variable */
+    (void) sf_active(PLA->F);
+    foreach_set(PLA->F, last, p) {
+	if (! is_in_set(p, var*2) || ! is_in_set(p, var*2+1)) {
+	    RESET(p, ACTIVE);
+	}
+    }
+    PLA->F = sf_inactive(PLA->F);
+
+    /* resize the cube and delete the don't-care variable */
+    setdown_cube();
+    for(i = 2*var+2; i < cube.size; i++) {
+	PLA->label[i-2] = PLA->label[i];
+    }
+    for(i = var+1; i < cube.num_vars; i++) {
+	cube.part_size[i-1] = cube.part_size[i];
+    }
+    cube.num_binary_vars--;
+    cube.num_vars--;
+    cube_setup();
+    PLA->F = sf_delc(PLA->F, 2*var, 2*var+1);
+    PLA->D = sf_delc(PLA->D, 2*var, 2*var+1);
+}
+
+void map_output_symbolic(PLA)
+pPLA PLA;
+{
+    pset_family newF, newD;
+    pset compress;
+    symbolic_t *p1;
+    symbolic_list_t *p2;
+    int i, bit, tot_size, base, old_size;
+
+    /* Remove the DC-set from the ON-set (is this necessary ??) */
+    if (PLA->D->count > 0) {
+	sf_free(PLA->F);
+	PLA->F = complement(cube2list(PLA->D, PLA->R));
+    }
+
+    /* tot_size = width added for all symbolic variables */
+    tot_size = 0;
+    for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+	for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+	    if (p2->pos<0 || p2->pos>=cube.part_size[cube.output]) {
+		fatal("symbolic-output index out of range");
+/*	    } else if (p2->variable != cube.output) {
+		fatal("symbolic-output label must be an output");*/
+	    }
+	}
+	tot_size += 1 << p1->symbolic_list_length;
+    }
+
+    /* adjust the indices to skip over new outputs */
+    for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+	for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+	    p2->pos += tot_size;
+	}
+    }
+
+    /* resize the cube structure -- add enough for the one-hot outputs */
+    old_size = cube.size;
+    cube.part_size[cube.output] += tot_size;
+    setdown_cube();
+    cube_setup();
+
+    /* insert space in the output part for the one-hot output */
+    base = cube.first_part[cube.output];
+    PLA->F = sf_addcol(PLA->F, base, tot_size);
+    PLA->D = sf_addcol(PLA->D, base, tot_size);
+    PLA->R = sf_addcol(PLA->R, base, tot_size);
+
+    /* do the real work */
+    for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+	newF = new_cover(100);
+	newD = new_cover(100);
+	find_inputs(NIL(set_family_t), PLA, p1->symbolic_list, base, 0,
+			    &newF, &newD);
+/*
+ *  Not sure what this means
+	find_dc_inputs(PLA, p1->symbolic_list,
+			    base, 1 << p1->symbolic_list_length, &newF, &newD);
+ */
+	free_cover(PLA->F);
+	PLA->F = newF;
+/*
+ *  retain OLD DC-set -- but we've lost the don't-care arc information
+ *  (it defaults to branch to the zero state)
+	free_cover(PLA->D);
+	PLA->D = newD;
+ */
+	free_cover(newD);
+	base += 1 << p1->symbolic_list_length;
+    }
+
+    /* delete the old outputs, and resize the cube */
+    compress = set_full(newF->sf_size);
+    for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+	for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+	    bit = cube.first_part[cube.output] + p2->pos;
+	    set_remove(compress, bit);
+	}
+    }
+    cube.part_size[cube.output] -= newF->sf_size - set_ord(compress);
+    setdown_cube();
+    cube_setup();
+    PLA->F = sf_compress(PLA->F, compress);
+    PLA->D = sf_compress(PLA->D, compress);
+    if (cube.size != PLA->F->sf_size) fatal("error");
+
+    /* Quick minimization */
+    PLA->F = sf_contain(PLA->F);
+    PLA->D = sf_contain(PLA->D);
+    for(i = 0; i < cube.num_vars; i++) {
+	PLA->F = d1merge(PLA->F, i);
+	PLA->D = d1merge(PLA->D, i);
+    }
+    PLA->F = sf_contain(PLA->F);
+    PLA->D = sf_contain(PLA->D);
+
+    free_cover(PLA->R);
+    PLA->R = new_cover(0);
+
+    symbolic_hack_labels(PLA, PLA->symbolic_output,
+			    compress, cube.size, old_size, tot_size);
+    set_free(compress);
+}
+
+
+void find_inputs(A, PLA, list, base, value, newF, newD)
+pcover A;
+pPLA PLA;
+symbolic_list_t *list;
+int base, value;
+pcover *newF, *newD;
+{
+    pcover S, S1;
+    register pset last, p;
+
+    /*
+     *  A represents th 'input' values for which the outputs assume
+     *  the integer value 'value
+     */
+    if (list == NIL(symbolic_list_t)) {
+	/*
+	 *  Simulate these inputs against the on-set; then, insert into the
+	 *  new on-set a 1 in the proper position
+	 */
+	S = cv_intersect(A, PLA->F);
+	foreach_set(S, last, p) {
+	    set_insert(p, base + value);
+	}
+	*newF = sf_append(*newF, S);
+
+	/*
+	 *  'simulate' these inputs against the don't-care set
+	S = cv_intersect(A, PLA->D);
+	*newD = sf_append(*newD, S);
+	 */
+
+    } else {
+	/* intersect and recur with the OFF-set */
+	S = cof_output(PLA->R, cube.first_part[cube.output] + list->pos);
+	if (A != NIL(set_family_t)) {
+	    S1 = cv_intersect(A, S);
+	    free_cover(S);
+	    S = S1;
+	}
+	find_inputs(S, PLA, list->next, base, value*2, newF, newD);
+	free_cover(S);
+
+	/* intersect and recur with the ON-set */
+	S = cof_output(PLA->F, cube.first_part[cube.output] + list->pos);
+	if (A != NIL(set_family_t)) {
+	    S1 = cv_intersect(A, S);
+	    free_cover(S);
+	    S = S1;
+	}
+	find_inputs(S, PLA, list->next, base, value*2 + 1, newF, newD);
+	free_cover(S);
+    }
+}
+
+
+#if 0
+find_dc_inputs(PLA, list, base, maxval, newF, newD)
+pPLA PLA;
+symbolic_list_t *list;
+int base, maxval;
+pcover *newF, *newD;
+{
+    pcover A, S, S1;
+    symbolic_list_t *p2;
+    register pset p, last;
+    register int i;
+
+    /* painfully find the points for which the symbolic output is dc */
+    A = NIL(set_family_t);
+    for(p2=list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+	S = cof_output(PLA->D, cube.first_part[cube.output] + p2->pos);
+	if (A == NIL(set_family_t)) {
+	    A = S;
+	} else {
+	    S1 = cv_intersect(A, S);
+	    free_cover(S);
+	    free_cover(A);
+	    A = S1;
+	}
+    }
+
+    S = cv_intersect(A, PLA->F);
+    *newF = sf_append(*newF, S);
+
+    S = cv_intersect(A, PLA->D);
+    foreach_set(S, last, p) {
+	for(i = base; i < base + maxval; i++) {
+	    set_insert(p, i);
+	}
+    }
+    *newD = sf_append(*newD, S);
+    free_cover(A);
+}
+#endif
+
+void map_symbolic(PLA)
+pPLA PLA;
+{
+    symbolic_t *p1;
+    symbolic_list_t *p2;
+    int var, base, num_vars, num_binary_vars, *new_part_size;
+    int new_size, size_added, num_deleted_vars, num_added_vars, newvar;
+    pset compress;
+
+    /* Verify legal values are in the symbolic lists */
+    for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+	for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+	    if (p2->variable  < 0 || p2->variable >= cube.num_binary_vars) {
+		fatal(".symbolic requires binary variables");
+	    }
+	}
+    }
+
+    /*
+     *  size_added = width added for all symbolic variables
+     *  num_deleted_vars = # binary variables to be deleted
+     *  num_added_vars = # new mv variables
+     *  compress = a cube which will be used to compress the set families
+     */
+    size_added = 0;
+    num_added_vars = 0;
+    for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+	size_added += 1 << p1->symbolic_list_length;
+	num_added_vars++;
+    }
+    compress = set_full(PLA->F->sf_size + size_added);
+    for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+	for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+	    set_remove(compress, p2->variable*2);
+	    set_remove(compress, p2->variable*2+1);
+	}
+    }
+    num_deleted_vars = ((PLA->F->sf_size + size_added) - set_ord(compress))/2;
+
+    /* compute the new cube constants */
+    num_vars = cube.num_vars - num_deleted_vars + num_added_vars;
+    num_binary_vars = cube.num_binary_vars - num_deleted_vars;
+    new_size = cube.size - num_deleted_vars*2 + size_added;
+    new_part_size = ALLOC(int, num_vars);
+    new_part_size[num_vars-1] = cube.part_size[cube.num_vars-1];
+    for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) {
+	new_part_size[var-num_deleted_vars] = cube.part_size[var];
+    }
+
+    /* re-size the covers, opening room for the new mv variables */
+    base = cube.first_part[cube.output];
+    PLA->F = sf_addcol(PLA->F, base, size_added);
+    PLA->D = sf_addcol(PLA->D, base, size_added);
+    PLA->R = sf_addcol(PLA->R, base, size_added);
+
+    /* compute the values for the new mv variables */
+    newvar = (cube.num_vars - 1) - num_deleted_vars;
+    for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+	PLA->F = map_symbolic_cover(PLA->F, p1->symbolic_list, base);
+	PLA->D = map_symbolic_cover(PLA->D, p1->symbolic_list, base);
+	PLA->R = map_symbolic_cover(PLA->R, p1->symbolic_list, base);
+	base += 1 << p1->symbolic_list_length;
+	new_part_size[newvar++] = 1 << p1->symbolic_list_length;
+    }
+
+    /* delete the binary variables which disappear */
+    PLA->F = sf_compress(PLA->F, compress);
+    PLA->D = sf_compress(PLA->D, compress);
+    PLA->R = sf_compress(PLA->R, compress);
+
+    symbolic_hack_labels(PLA, PLA->symbolic, compress,
+		new_size, cube.size, size_added);
+    setdown_cube();
+    FREE(cube.part_size);
+    cube.num_vars = num_vars;
+    cube.num_binary_vars = num_binary_vars;
+    cube.part_size = new_part_size;
+    cube_setup();
+    set_free(compress);
+}
+
+
+pcover map_symbolic_cover(T, list, base)
+pcover T;
+symbolic_list_t *list;
+int base;
+{
+    pset last, p;
+    foreach_set(T, last, p) {
+	form_bitvector(p, base, 0, list);
+    }
+    return T;
+}
+
+
+void form_bitvector(p, base, value, list)
+pset p;			/* old cube, looking at binary variables */
+int base;		/* where in mv cube the new variable starts */
+int value;		/* current value for this recursion */
+symbolic_list_t *list;	/* current place in the symbolic list */
+{
+    if (list == NIL(symbolic_list_t)) {
+	set_insert(p, base + value);
+    } else {
+	switch(GETINPUT(p, list->variable)) {
+	    case ZERO:
+		form_bitvector(p, base, value*2, list->next);
+		break;
+	    case ONE:
+		form_bitvector(p, base, value*2+1, list->next);
+		break;
+	    case TWO:
+		form_bitvector(p, base, value*2, list->next);
+		form_bitvector(p, base, value*2+1, list->next);
+		break;
+	    default:
+		fatal("bad cube in form_bitvector");
+	}
+    }
+}
+
+
+void symbolic_hack_labels(PLA, list, compress, new_size, old_size, size_added)
+pPLA PLA;
+symbolic_t *list;
+pset compress;
+int new_size, old_size, size_added;
+{
+    int i, base;
+    char **oldlabel;
+    symbolic_t *p1;
+    symbolic_label_t *p3;
+
+    /* hack with the labels */
+    if ((oldlabel = PLA->label) == NIL(char *))
+	return;
+    PLA->label = ALLOC(char *, new_size);
+    for(i = 0; i < new_size; i++) {
+	PLA->label[i] = NIL(char);
+    }
+
+    /* copy the binary variable labels and unchanged mv variable labels */
+    base = 0;
+    for(i = 0; i < cube.first_part[cube.output]; i++) {
+	if (is_in_set(compress, i)) {
+	    PLA->label[base++] = oldlabel[i];
+	} else {
+	    if (oldlabel[i] != NIL(char)) {
+		FREE(oldlabel[i]);
+	    }
+	}
+    }
+
+    /* add the user-defined labels for the symbolic outputs */
+    for(p1 = list; p1 != NIL(symbolic_t); p1 = p1->next) {
+	p3 = p1->symbolic_label;
+	for(i = 0; i < (1 << p1->symbolic_list_length); i++) {
+	    if (p3 == NIL(symbolic_label_t)) {
+		PLA->label[base+i] = ALLOC(char, 10);
+		(void) sprintf(PLA->label[base+i], "X%d", i);
+	    } else {
+		PLA->label[base+i] = p3->label;
+		p3 = p3->next;
+	    }
+	}
+	base += 1 << p1->symbolic_list_length;
+    }
+
+    /* copy the labels for the binary outputs which remain */
+    for(i = cube.first_part[cube.output]; i < old_size; i++) {
+	if (is_in_set(compress, i + size_added)) {
+	    PLA->label[base++] = oldlabel[i];
+	} else {
+	    if (oldlabel[i] != NIL(char)) {
+		FREE(oldlabel[i]);
+	    }
+	}
+    }
+    FREE(oldlabel);
+}
+
+static pcover fsm_simplify(F)
+pcover F;
+{
+    pcover D, R;
+    D = new_cover(0);
+    R = complement(cube1list(F));
+    F = espresso(F, D, R);
+    free_cover(D);
+    free_cover(R);
+    return F;
+}
+
+
+void disassemble_fsm(PLA, verbose_mode)
+pPLA PLA;
+int verbose_mode;
+{
+    int nin, nstates, nout;
+    int before, after, present_state, next_state, i, j;
+    pcube next_state_mask, present_state_mask, state_mask, p, p1, last;
+    pcover go_nowhere, F, tF;
+
+    /* We make the DISGUSTING assumption that the first 'n' outputs have
+     *  been created by .symbolic-output, and represent a one-hot encoding
+     * of the next state.  'n' is the size of the second-to-last multiple-
+     * valued variable (i.e., before the outputs
+     */
+
+    if (cube.num_vars - cube.num_binary_vars != 2) {
+	(void) fprintf(stderr,
+	"use .symbolic and .symbolic-output to specify\n");
+	(void) fprintf(stderr,
+	"the present state and next state field information\n");
+	fatal("disassemble_pla: need two multiple-valued variables\n");
+    }
+
+    nin = cube.num_binary_vars;
+    nstates = cube.part_size[cube.num_binary_vars];
+    nout = cube.part_size[cube.num_vars - 1];
+    if (nout < nstates) {
+	(void) fprintf(stderr,
+	    "use .symbolic and .symbolic-output to specify\n");
+	(void) fprintf(stderr,
+	    "the present state and next state field information\n");
+	fatal("disassemble_pla: # outputs < # states\n");
+    }
+
+
+    present_state = cube.first_part[cube.num_binary_vars];
+    present_state_mask = new_cube();
+    for(i = 0; i < nstates; i++) {
+	set_insert(present_state_mask, i + present_state);
+    }
+
+    next_state = cube.first_part[cube.num_binary_vars+1];
+    next_state_mask = new_cube();
+    for(i = 0; i < nstates; i++) {
+	set_insert(next_state_mask, i + next_state);
+    }
+
+    state_mask = set_or(new_cube(), next_state_mask, present_state_mask);
+
+    F = new_cover(10);
+
+
+    /*
+     *  check for arcs which go from ANY state to state #i
+     */
+    for(i = 0; i < nstates; i++) {
+	tF = new_cover(10);
+	foreach_set(PLA->F, last, p) {
+	    if (setp_implies(present_state_mask, p)) { /* from any state ! */
+		if (is_in_set(p, next_state + i)) {
+		    tF = sf_addset(tF, p);
+		}
+	    }
+	}
+	before = tF->count;
+	if (before > 0) {
+	    tF = fsm_simplify(tF);
+	    /* don't allow the next state to disappear ... */
+	    foreach_set(tF, last, p) {
+		set_insert(p, next_state + i);
+	    }
+	    after = tF->count;
+	    F = sf_append(F, tF);
+	    if (verbose_mode) {
+		printf("# state EVERY to %d, before=%d after=%d\n",
+			i, before, after);
+	    }
+	}
+    }
+
+
+    /*
+     *  some 'arcs' may NOT have a next state -- handle these
+     *  we must unravel the present state part
+     */
+    go_nowhere = new_cover(10);
+    foreach_set(PLA->F, last, p) {
+	if (setp_disjoint(p, next_state_mask)) { /* no next state !! */
+	    go_nowhere = sf_addset(go_nowhere, p);
+	}
+    }
+    before = go_nowhere->count;
+    go_nowhere = unravel_range(go_nowhere,
+				cube.num_binary_vars, cube.num_binary_vars);
+    after = go_nowhere->count;
+    F = sf_append(F, go_nowhere);
+    if (verbose_mode) {
+	printf("# state ANY to NOWHERE, before=%d after=%d\n", before, after);
+    }
+
+
+    /*
+     *  minimize cover for all arcs from state #i to state #j
+     */
+    for(i = 0; i < nstates; i++) {
+	for(j = 0; j < nstates; j++) {
+	    tF = new_cover(10);
+	    foreach_set(PLA->F, last, p) {
+		/* not EVERY state */
+		if (! setp_implies(present_state_mask, p)) {
+		    if (is_in_set(p, present_state + i)) {
+			if (is_in_set(p, next_state + j)) {
+			    p1 = set_save(p);
+			    set_diff(p1, p1, state_mask);
+			    set_insert(p1, present_state + i);
+			    set_insert(p1, next_state + j);
+			    tF = sf_addset(tF, p1);
+			    set_free(p1);
+			}
+		    }
+		}
+	    }
+	    before = tF->count;
+	    if (before > 0) {
+		tF = fsm_simplify(tF);
+		/* don't allow the next state to disappear ... */
+		foreach_set(tF, last, p) {
+		    set_insert(p, next_state + j);
+		}
+		after = tF->count;
+		F = sf_append(F, tF);
+		if (verbose_mode) {
+		    printf("# state %d to %d, before=%d after=%d\n",
+			    i, j, before, after);
+		}
+	    }
+	}
+    }
+
+
+    free_cube(state_mask);
+    free_cube(present_state_mask);
+    free_cube(next_state_mask);
+
+    free_cover(PLA->F);
+    PLA->F = F;
+    free_cover(PLA->D);
+    PLA->D = new_cover(0);
+
+    setdown_cube();
+    FREE(cube.part_size);
+    cube.num_binary_vars = nin;
+    cube.num_vars = nin + 3;
+    cube.part_size = ALLOC(int, cube.num_vars);
+    cube.part_size[cube.num_binary_vars] = nstates;
+    cube.part_size[cube.num_binary_vars+1] = nstates;
+    cube.part_size[cube.num_binary_vars+2] = nout - nstates;
+    cube_setup();
+
+    foreach_set(PLA->F, last, p) {
+	kiss_print_cube(stdout, PLA, p, "~1");
+    }
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/indep.c b/abc-build/src/misc/espresso/indep.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/indep.c
@@ -0,0 +1,139 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+static sm_matrix *build_intersection_matrix();
+
+
+#if 0
+/*
+ *  verify that all rows in 'indep' are actually independent !
+ */
+static int 
+verify_indep_set(A, indep)
+sm_matrix *A;
+sm_row *indep;
+{
+    register sm_row *prow, *prow1;
+    register sm_element *p, *p1;
+
+    for(p = indep->first_col; p != 0; p = p->next_col) {
+	prow = sm_get_row(A, p->col_num);
+	for(p1 = p->next_col; p1 != 0; p1 = p1->next_col) {
+	    prow1 = sm_get_row(A, p1->col_num);
+	    if (sm_row_intersects(prow, prow1)) {
+		return 0;
+	    }
+	}
+    }
+    return 1;
+}
+#endif
+
+solution_t * 
+sm_maximal_independent_set(A, weight)
+sm_matrix *A;
+int *weight;
+{
+    register sm_row *best_row, *prow;
+    register sm_element *p;
+    int least_weight;
+    sm_row *save;
+    sm_matrix *B;
+    solution_t *indep;
+
+    indep = solution_alloc();
+    B = build_intersection_matrix(A);
+
+    while (B->nrows > 0) {
+	/*  Find the row which is disjoint from a maximum number of rows */
+	best_row = B->first_row;
+	for(prow = B->first_row->next_row; prow != 0; prow = prow->next_row) {
+	    if (prow->length < best_row->length) {
+		best_row = prow;
+	    }
+	}
+
+	/* Find which element in this row has least weight */
+	if (weight == NIL(int)) {
+	    least_weight = 1;
+	} else {
+	    prow = sm_get_row(A, best_row->row_num);
+	    least_weight = weight[prow->first_col->col_num];
+	    for(p = prow->first_col->next_col; p != 0; p = p->next_col) {
+		if (weight[p->col_num] < least_weight) {
+		    least_weight = weight[p->col_num];
+		}
+	    }
+	}
+	indep->cost += least_weight;
+	(void) sm_row_insert(indep->row, best_row->row_num);
+
+	/*  Discard the rows which intersect this row */
+	save = sm_row_dup(best_row);
+	for(p = save->first_col; p != 0; p = p->next_col) {
+	    sm_delrow(B, p->col_num);
+	    sm_delcol(B, p->col_num);
+	}
+	sm_row_free(save);
+    }
+
+    sm_free(B);
+
+/*
+    if (! verify_indep_set(A, indep->row)) {
+	fail("sm_maximal_independent_set: row set is not independent");
+    }
+*/
+    return indep;
+}
+
+static sm_matrix *
+build_intersection_matrix(A)
+sm_matrix *A;
+{
+    register sm_row *prow, *prow1;
+    register sm_element *p, *p1;
+    register sm_col *pcol;
+    sm_matrix *B;
+
+    /* Build row-intersection matrix */
+    B = sm_alloc();
+    for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+
+	/* Clear flags on all rows we can reach from row 'prow' */
+	for(p = prow->first_col; p != 0; p = p->next_col) {
+	    pcol = sm_get_col(A, p->col_num);
+	    for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) {
+		prow1 = sm_get_row(A, p1->row_num);
+		prow1->flag = 0;
+	    }
+	}
+
+	/* Now record which rows can be reached */
+	for(p = prow->first_col; p != 0; p = p->next_col) {
+	    pcol = sm_get_col(A, p->col_num);
+	    for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) {
+		prow1 = sm_get_row(A, p1->row_num);
+		if (! prow1->flag) {
+		    prow1->flag = 1;
+		    (void) sm_insert(B, prow->row_num, prow1->row_num);
+		}
+	    }
+	}
+    }
+
+    return B;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/irred.c b/abc-build/src/misc/espresso/irred.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/irred.c
@@ -0,0 +1,445 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+static void fcube_is_covered();
+static void ftautology();
+static bool ftaut_special_cases();
+
+
+static int Rp_current;
+
+/*
+ *   irredundant -- Return a minimal subset of F
+ */
+
+pcover
+irredundant(F, D)
+pcover F, D;
+{
+    mark_irredundant(F, D);
+    return sf_inactive(F);
+}
+
+
+/*
+ *   mark_irredundant -- find redundant cubes, and mark them "INACTIVE"
+ */
+
+void
+mark_irredundant(F, D)
+pcover F, D;
+{
+    pcover E, Rt, Rp;
+    pset p, p1, last;
+    sm_matrix *table;
+    sm_row *cover;
+    sm_element *pe;
+
+    /* extract a minimum cover */
+    irred_split_cover(F, D, &E, &Rt, &Rp);
+    table = irred_derive_table(D, E, Rp);
+    cover = sm_minimum_cover(table, NIL(int), /* heuristic */ 1, /* debug */ 0);
+
+    /* mark the cubes for the result */
+    foreach_set(F, last, p) {
+	RESET(p, ACTIVE);
+	RESET(p, RELESSEN);
+    }
+    foreach_set(E, last, p) {
+	p1 = GETSET(F, SIZE(p));
+	assert(setp_equal(p1, p));
+	SET(p1, ACTIVE);
+	SET(p1, RELESSEN);		/* for essen(), mark as rel. ess. */
+    }
+    sm_foreach_row_element(cover, pe) {
+	p1 = GETSET(F, pe->col_num);
+	SET(p1, ACTIVE);
+    }
+
+    if (debug & IRRED) {
+	printf("# IRRED: F=%d E=%d R=%d Rt=%d Rp=%d Rc=%d Final=%d Bound=%d\n",
+	    F->count, E->count, Rt->count+Rp->count, Rt->count, Rp->count,
+	    cover->length, E->count + cover->length, 0);
+    }
+
+    free_cover(E);
+    free_cover(Rt);
+    free_cover(Rp);
+    sm_free(table);
+    sm_row_free(cover);
+}
+
+/*
+ *  irred_split_cover -- find E, Rt, and Rp from the cover F, D
+ *
+ *	E  -- relatively essential cubes
+ *	Rt  -- totally redundant cubes
+ *	Rp  -- partially redundant cubes
+ */
+
+void
+irred_split_cover(F, D, E, Rt, Rp)
+pcover F, D;
+pcover *E, *Rt, *Rp;
+{
+    register pcube p, last;
+    register int index;
+    pcover R;
+    pcube *FD, *ED;
+
+    /* number the cubes of F -- these numbers track into E, Rp, Rt, etc. */
+    index = 0;
+    foreach_set(F, last, p) {
+	PUTSIZE(p, index);
+	index++;
+    }
+
+    *E = new_cover(10);
+    *Rt = new_cover(10);
+    *Rp = new_cover(10);
+    R = new_cover(10);
+
+    /* Split F into E and R */
+    FD = cube2list(F, D);
+    foreach_set(F, last, p) {
+	if (cube_is_covered(FD, p)) {
+	    R = sf_addset(R, p);
+	} else {
+	    *E = sf_addset(*E, p);
+	}
+	if (debug & IRRED1) {
+	    (void) printf("IRRED1: zr=%d ze=%d to-go=%d time=%s\n",
+		R->count, (*E)->count, F->count - (R->count + (*E)->count),
+		print_time(ptime()));
+	}
+    }
+    free_cubelist(FD);
+
+    /* Split R into Rt and Rp */
+    ED = cube2list(*E, D);
+    foreach_set(R, last, p) {
+	if (cube_is_covered(ED, p)) {
+	    *Rt = sf_addset(*Rt, p);
+	} else {
+	    *Rp = sf_addset(*Rp, p);
+	}
+	if (debug & IRRED1) {
+	    (void) printf("IRRED1: zr=%d zrt=%d to-go=%d time=%s\n",
+		(*Rp)->count, (*Rt)->count,
+		R->count - ((*Rp)->count +(*Rt)->count), print_time(ptime()));
+	}
+    }
+    free_cubelist(ED);
+
+    free_cover(R);
+}
+
+/*
+ *  irred_derive_table -- given the covers D, E and the set of
+ *  partially redundant primes Rp, build a covering table showing
+ *  possible selections of primes to cover Rp.
+ */
+
+sm_matrix *
+irred_derive_table(D, E, Rp)
+pcover D, E, Rp;
+{
+    register pcube last, p, *list;
+    sm_matrix *table;
+    int size_last_dominance, i;
+
+    /* Mark each cube in DE as not part of the redundant set */
+    foreach_set(D, last, p) {
+	RESET(p, REDUND);
+    }
+    foreach_set(E, last, p) {
+	RESET(p, REDUND);
+    }
+
+    /* Mark each cube in Rp as partially redundant */
+    foreach_set(Rp, last, p) {
+	SET(p, REDUND);             /* belongs to redundant set */
+    }
+
+    /* For each cube in Rp, find ways to cover its minterms */
+    list = cube3list(D, E, Rp);
+    table = sm_alloc();
+    size_last_dominance = 0;
+    i = 0;
+    foreach_set(Rp, last, p) {
+	Rp_current = SIZE(p);
+	fcube_is_covered(list, p, table);
+	RESET(p, REDUND);	/* can now consider this cube redundant */
+	if (debug & IRRED1) {
+	    (void) printf("IRRED1: %d of %d to-go=%d, table=%dx%d time=%s\n",
+		i, Rp->count, Rp->count - i,
+		table->nrows, table->ncols, print_time(ptime()));
+	}
+	/* try to keep memory limits down by reducing table as we go along */
+	if (table->nrows - size_last_dominance > 1000) {
+	    (void) sm_row_dominance(table);
+	    size_last_dominance = table->nrows;
+	    if (debug & IRRED1) {
+		(void) printf("IRRED1: delete redundant rows, now %dx%d\n",
+		    table->nrows, table->ncols);
+	    }
+	}
+	i++;
+    }
+    free_cubelist(list);
+
+    return table;
+}
+
+/* cube_is_covered -- determine if a cubelist "covers" a single cube */
+bool
+cube_is_covered(T, c)
+pcube *T, c;
+{
+    return tautology(cofactor(T,c));
+}
+
+
+
+/* tautology -- answer the tautology question for T */
+bool
+tautology(T)
+pcube *T;         /* T will be disposed of */
+{
+    register pcube cl, cr;
+    register int best, result;
+    static int taut_level = 0;
+
+    if (debug & TAUT) {
+	debug_print(T, "TAUTOLOGY", taut_level++);
+    }
+
+    if ((result = taut_special_cases(T)) == MAYBE) {
+	cl = new_cube();
+	cr = new_cube();
+	best = binate_split_select(T, cl, cr, TAUT);
+	result = tautology(scofactor(T, cl, best)) &&
+		 tautology(scofactor(T, cr, best));
+	free_cubelist(T);
+	free_cube(cl);
+	free_cube(cr);
+    }
+
+    if (debug & TAUT) {
+	printf("exit TAUTOLOGY[%d]: %s\n", --taut_level, print_bool(result));
+    }
+    return result;
+}
+
+/*
+ *  taut_special_cases -- check special cases for tautology
+ */
+
+bool
+taut_special_cases(T)
+pcube *T;			/* will be disposed if answer is determined */
+{
+    register pcube *T1, *Tsave, p, ceil=cube.temp[0], temp=cube.temp[1];
+    pcube *A, *B;
+    int var;
+
+    /* Check for a row of all 1's which implies tautology */
+    for(T1 = T+2; (p = *T1++) != NULL; ) {
+	if (full_row(p, T[0])) {
+	    free_cubelist(T);
+	    return TRUE;
+	}
+    }
+
+    /* Check for a column of all 0's which implies no tautology */
+start:
+    INLINEset_copy(ceil, T[0]);
+    for(T1 = T+2; (p = *T1++) != NULL; ) {
+	INLINEset_or(ceil, ceil, p);
+    }
+    if (! setp_equal(ceil, cube.fullset)) {
+	free_cubelist(T);
+	return FALSE;
+    }
+
+    /* Collect column counts, determine unate variables, etc. */
+    massive_count(T);
+
+    /* If function is unate (and no row of all 1's), then no tautology */
+    if (cdata.vars_unate == cdata.vars_active) {
+	free_cubelist(T);
+	return FALSE;
+
+    /* If active in a single variable (and no column of 0's) then tautology */
+    } else if (cdata.vars_active == 1) {
+	free_cubelist(T);
+	return TRUE;
+
+    /* Check for unate variables, and reduce cover if there are any */
+    } else if (cdata.vars_unate != 0) {
+	/* Form a cube "ceil" with full variables in the unate variables */
+	(void) set_copy(ceil, cube.emptyset);
+	for(var = 0; var < cube.num_vars; var++) {
+	    if (cdata.is_unate[var]) {
+		INLINEset_or(ceil, ceil, cube.var_mask[var]);
+	    }
+	}
+
+	/* Save only those cubes that are "full" in all unate variables */
+	for(Tsave = T1 = T+2; (p = *T1++) != 0; ) {
+	    if (setp_implies(ceil, set_or(temp, p, T[0]))) {
+		*Tsave++ = p;
+	    }
+	}
+	*Tsave++ = NULL;
+	T[1] = (pcube) Tsave;
+
+	if (debug & TAUT) {
+	    printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n",
+		(int)cdata.vars_unate, (int)CUBELISTSIZE(T));
+	}
+	goto start;
+
+    /* Check for component reduction */
+    } else if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T) / 2) {
+	if (cubelist_partition(T, &A, &B, debug & TAUT) == 0) {
+	    return MAYBE;
+	} else {
+	    free_cubelist(T);
+	    if (tautology(A)) {
+		free_cubelist(B);
+		return TRUE;
+	    } else {
+		return tautology(B);
+	    }
+	}
+    }
+
+    /* We tried as hard as we could, but must recurse from here on */
+    return MAYBE;
+}
+
+/* fcube_is_covered -- determine exactly how a cubelist "covers" a cube */
+static void
+fcube_is_covered(T, c, table)
+pcube *T, c;
+sm_matrix *table;
+{
+    ftautology(cofactor(T,c), table);
+}
+
+
+/* ftautology -- find ways to make a tautology */
+static void
+ftautology(T, table)
+pcube *T;         	/* T will be disposed of */
+sm_matrix *table;
+{
+    register pcube cl, cr;
+    register int best;
+    static int ftaut_level = 0;
+
+    if (debug & TAUT) {
+	debug_print(T, "FIND_TAUTOLOGY", ftaut_level++);
+    }
+
+    if (ftaut_special_cases(T, table) == MAYBE) {
+	cl = new_cube();
+	cr = new_cube();
+	best = binate_split_select(T, cl, cr, TAUT);
+
+	ftautology(scofactor(T, cl, best), table);
+	ftautology(scofactor(T, cr, best), table);
+
+	free_cubelist(T);
+	free_cube(cl);
+	free_cube(cr);
+    }
+
+    if (debug & TAUT) {
+	(void) printf("exit FIND_TAUTOLOGY[%d]: table is %d by %d\n",
+	    --ftaut_level, table->nrows, table->ncols);
+    }
+}
+
+static bool
+ftaut_special_cases(T, table)
+pcube *T;                 /* will be disposed if answer is determined */
+sm_matrix *table;
+{
+    register pcube *T1, *Tsave, p, temp = cube.temp[0], ceil = cube.temp[1];
+    int var, rownum;
+
+    /* Check for a row of all 1's in the essential cubes */
+    for(T1 = T+2; (p = *T1++) != 0; ) {
+	if (! TESTP(p, REDUND)) {
+	    if (full_row(p, T[0])) {
+		/* subspace is covered by essentials -- no new rows for table */
+		free_cubelist(T);
+		return TRUE;
+	    }
+	}
+    }
+
+    /* Collect column counts, determine unate variables, etc. */
+start:
+    massive_count(T);
+
+    /* If function is unate, find the rows of all 1's */
+    if (cdata.vars_unate == cdata.vars_active) {
+	/* find which nonessentials cover this subspace */
+	rownum = table->last_row ? table->last_row->row_num+1 : 0;
+	(void) sm_insert(table, rownum, Rp_current);
+	for(T1 = T+2; (p = *T1++) != 0; ) {
+	    if (TESTP(p, REDUND)) {
+		/* See if a redundant cube covers this leaf */
+		if (full_row(p, T[0])) {
+		    (void) sm_insert(table, rownum, (int) SIZE(p));
+		}
+	    }
+	}
+	free_cubelist(T);
+	return TRUE;
+
+    /* Perform unate reduction if there are any unate variables */
+    } else if (cdata.vars_unate != 0) {
+	/* Form a cube "ceil" with full variables in the unate variables */
+	(void) set_copy(ceil, cube.emptyset);
+	for(var = 0; var < cube.num_vars; var++) {
+	    if (cdata.is_unate[var]) {
+		INLINEset_or(ceil, ceil, cube.var_mask[var]);
+	    }
+	}
+
+	/* Save only those cubes that are "full" in all unate variables */
+	for(Tsave = T1 = T+2; (p = *T1++) != 0; ) {
+	    if (setp_implies(ceil, set_or(temp, p, T[0]))) {
+		*Tsave++ = p;
+	    }
+	}
+	*Tsave++ = 0;
+	T[1] = (pcube) Tsave;
+
+	if (debug & TAUT) {
+	    printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n",
+		(int)cdata.vars_unate, (int)CUBELISTSIZE(T));
+	}
+	goto start;
+    }
+
+    /* Not much we can do about it */
+    return MAYBE;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/main.c b/abc-build/src/misc/espresso/main.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/main.c
@@ -0,0 +1,751 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ *  Main driver for espresso
+ *
+ *  Old style -do xxx, -out xxx, etc. are still supported.
+ */
+
+#include "espresso.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+		/* table definitions for options */
+
+static FILE *last_fp;
+static int input_type = FD_type;
+
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+    int i, j, first, last, strategy, out_type, option;
+    pPLA PLA, PLA1;
+    pcover F, Fold, Dold;
+    pset last1, p;
+    cost_t cost;
+    bool error, exact_cover;
+    long start;
+    extern char *util_optarg;
+    extern int util_optind;
+
+    start = ptime();
+
+    error = FALSE;
+    init_runtime();
+#ifdef RANDOM
+    srandom(314973);
+#endif
+
+    option = 0;			/* default -D: ESPRESSO */
+    out_type = F_type;		/* default -o: default is ON-set only */
+    debug = 0;			/* default -d: no debugging info */
+    verbose_debug = FALSE;	/* default -v: not verbose */
+    print_solution = TRUE;	/* default -x: print the solution (!) */
+    summary = FALSE;		/* default -s: no summary */
+    trace = FALSE;		/* default -t: no trace information */
+    strategy = 0;		/* default -S: strategy number */
+    first = -1;			/* default -R: select range */
+    last = -1;
+    remove_essential = TRUE;	/* default -e: */
+    force_irredundant = TRUE;
+    unwrap_onset = TRUE;
+    single_expand = FALSE;
+    pos = FALSE;
+    recompute_onset = FALSE;
+    use_super_gasp = FALSE;
+    use_random_order = FALSE;
+    kiss = FALSE;
+    echo_comments = TRUE;
+    echo_unknown_commands = TRUE;
+    exact_cover = FALSE;	/* for -qm option, the default */
+
+    backward_compatibility_hack(&argc, argv, &option, &out_type);
+
+
+    /* parse command line options*/
+    while ((i = util_getopt(argc, argv, "D:S:de:o:r:stv:x")) != EOF) {
+	switch(i) {
+	    case 'D':		/* -Dcommand invokes a subcommand */
+		for(j = 0; option_table[j].name != 0; j++) {
+		    if (strcmp(util_optarg, option_table[j].name) == 0) {
+			option = j;
+			break;
+		    }
+		}
+		if (option_table[j].name == 0) {
+		    (void) fprintf(stderr, "%s: bad subcommand \"%s\"\n",
+			argv[0], util_optarg);
+		    exit(1);
+		}
+		break;
+
+	    case 'o':		/* -ooutput selects and output option */
+		for(j = 0; pla_types[j].key != 0; j++) {
+		    if (strcmp(util_optarg, pla_types[j].key+1) == 0) {
+			out_type = pla_types[j].value;
+			break;
+		    }
+		}
+		if (pla_types[j].key == 0) {
+		    (void) fprintf(stderr, "%s: bad output type \"%s\"\n",
+			argv[0], util_optarg);
+		    exit(1);
+		}
+		break;
+
+	    case 'e':		/* -eespresso selects an option for espresso */
+		for(j = 0; esp_opt_table[j].name != 0; j++) {
+		    if (strcmp(util_optarg, esp_opt_table[j].name) == 0) {
+			*(esp_opt_table[j].variable) = esp_opt_table[j].value;
+			break;
+		    }
+		}
+		if (esp_opt_table[j].name == 0) {
+		    (void) fprintf(stderr, "%s: bad espresso option \"%s\"\n",
+			argv[0], util_optarg);
+		    exit(1);
+		}
+		break;
+
+	    case 'd':		/* -d turns on (softly) all debug switches */
+		debug = debug_table[0].value;
+		trace = TRUE;
+		summary = TRUE;
+		break;
+
+	    case 'v':		/* -vdebug invokes a debug option */
+		verbose_debug = TRUE;
+		for(j = 0; debug_table[j].name != 0; j++) {
+		    if (strcmp(util_optarg, debug_table[j].name) == 0) {
+			debug |= debug_table[j].value;
+			break;
+		    }
+		}
+		if (debug_table[j].name == 0) {
+		    (void) fprintf(stderr, "%s: bad debug type \"%s\"\n",
+			argv[0], util_optarg);
+		    exit(1);
+		}
+		break;
+
+	    case 't':
+		trace = TRUE;
+		break;
+
+	    case 's':
+		summary = TRUE;
+		break;
+
+	    case 'x':		/* -x suppress printing of results */
+		print_solution = FALSE;
+		break;
+
+	    case 'S':		/* -S sets a strategy for several cmds */
+		strategy = atoi(util_optarg);
+		break;
+
+	    case 'r':		/* -r selects range (outputs or vars) */
+		if (sscanf(util_optarg, "%d-%d", &first, &last) < 2) {
+		    (void) fprintf(stderr, "%s: bad output range \"%s\"\n",
+			argv[0], util_optarg);
+		    exit(1);
+		}
+		break;
+
+	    default:
+		usage();
+		exit(1);
+	}
+    }
+
+    /* provide version information and summaries */
+    if (summary || trace) {
+	/* echo command line and arguments */
+	printf("#");
+	for(i = 0; i < argc; i++) {
+	    printf(" %s", argv[i]);
+	}
+	printf("\n");
+	printf("# %s\n", VERSION);
+    }
+
+    /* the remaining arguments are argv[util_optind ... argc-1] */
+    PLA = PLA1 = NIL(PLA_t);
+    switch(option_table[option].num_plas) {
+	case 2:
+	    if (util_optind+2 < argc) fatal("trailing arguments on command line");
+	    getPLA(util_optind++, argc, argv, option, &PLA, out_type);
+	    getPLA(util_optind++, argc, argv, option, &PLA1, out_type);
+	    break;
+	case 1:
+	    if (util_optind+1 < argc) fatal("trailing arguments on command line");
+	    getPLA(util_optind++, argc, argv, option, &PLA, out_type);
+	    break;
+    }
+    if (util_optind < argc) fatal("trailing arguments on command line");
+
+    if (summary || trace) {
+	if (PLA != NIL(PLA_t)) PLA_summary(PLA);
+	if (PLA1 != NIL(PLA_t)) PLA_summary(PLA1);
+    }
+
+/*
+ *  Now a case-statement to decide what to do
+ */
+
+    switch(option_table[option].key) {
+
+
+/******************** Espresso operations ********************/
+
+    case KEY_ESPRESSO:
+	Fold = sf_save(PLA->F);
+	PLA->F = espresso(PLA->F, PLA->D, PLA->R);
+	EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost);
+	if (error) {
+	    print_solution = FALSE;
+	    PLA->F = Fold;
+	    (void) check_consistency(PLA);
+	} else {
+	    free_cover(Fold);
+	}
+	break;
+
+    case KEY_MANY_ESPRESSO: {
+	int pla_type;
+	do {
+	    EXEC(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO   ",PLA->F);
+	    if (print_solution) {
+		fprint_pla(stdout, PLA, out_type);
+		(void) fflush(stdout);
+	    }
+	    pla_type = PLA->pla_type;
+	    free_PLA(PLA);
+	    setdown_cube();
+	    FREE(cube.part_size);
+	} while (read_pla(last_fp, TRUE, TRUE, pla_type, &PLA) != EOF);
+	exit(0);
+    }
+
+    case KEY_simplify:
+	EXEC(PLA->F = simplify(cube1list(PLA->F)), "SIMPLIFY  ", PLA->F);
+	break;
+
+    case KEY_so:	        /* minimize all functions as single-output */
+	if (strategy < 0 || strategy > 1) {
+	    strategy = 0;
+	}
+	so_espresso(PLA, strategy);
+	break;
+
+    case KEY_so_both:		/* minimize all functions as single-output */
+	if (strategy < 0 || strategy > 1) {
+	    strategy = 0;
+	}
+	so_both_espresso(PLA, strategy);
+	break;
+
+    case KEY_expand:            /* execute expand */
+	EXECUTE(PLA->F=expand(PLA->F,PLA->R,FALSE),EXPAND_TIME, PLA->F, cost);
+	break;
+
+    case KEY_irred:             /* extract minimal irredundant subset */
+	EXECUTE(PLA->F = irredundant(PLA->F, PLA->D), IRRED_TIME, PLA->F, cost);
+	break;
+
+    case KEY_reduce:            /* perform reduction */
+	EXECUTE(PLA->F = reduce(PLA->F, PLA->D), REDUCE_TIME, PLA->F, cost);
+	break;
+
+    case KEY_essen:             /* check for essential primes */
+	foreach_set(PLA->F, last1, p) {
+	    SET(p, RELESSEN);
+	    RESET(p, NONESSEN);
+	}
+	EXECUTE(F = essential(&(PLA->F), &(PLA->D)), ESSEN_TIME, PLA->F, cost);
+	free_cover(F);
+	break;
+
+    case KEY_super_gasp:
+	PLA->F = super_gasp(PLA->F, PLA->D, PLA->R, &cost);
+	break;
+
+    case KEY_gasp:
+	PLA->F = last_gasp(PLA->F, PLA->D, PLA->R, &cost);
+	break;
+
+    case KEY_make_sparse:       /* make_sparse step of Espresso */
+	PLA->F = make_sparse(PLA->F, PLA->D, PLA->R);
+	break;
+
+    case KEY_exact:
+	exact_cover = TRUE;
+
+    case KEY_qm:
+	Fold = sf_save(PLA->F);
+	PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, exact_cover);
+	EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost);
+	if (error) {
+	    print_solution = FALSE;
+	    PLA->F = Fold;
+	    (void) check_consistency(PLA);
+	}
+	free_cover(Fold);
+	break;
+
+    case KEY_primes:            /* generate all prime implicants */
+	EXEC(PLA->F = primes_consensus(cube2list(PLA->F, PLA->D)), 
+						    "PRIMES     ", PLA->F);
+	break;
+
+    case KEY_map:               /* print out a Karnaugh map of function */
+	map(PLA->F);
+	print_solution = FALSE;
+	break;
+
+
+
+/******************** Output phase and bit pairing ********************/
+
+    case KEY_opo:               /* sasao output phase assignment */
+	phase_assignment(PLA, strategy);
+	break;
+
+    case KEY_opoall:		/* try all phase assignments (!) */
+	if (first < 0 || first >= cube.part_size[cube.output]) {
+	    first = 0;
+	}
+	if (last < 0 || last >= cube.part_size[cube.output]) {
+	    last = cube.part_size[cube.output] - 1;
+	}
+	opoall(PLA, first, last, strategy);
+	break;
+
+    case KEY_pair:              /* find an optimal pairing */
+	find_optimal_pairing(PLA, strategy);
+	break;
+
+    case KEY_pairall:		/* try all pairings !! */
+	pair_all(PLA, strategy);
+	break;
+
+
+
+/******************** Simple cover operations ********************/
+
+    case KEY_echo:				/* echo the PLA */
+	break;
+
+    case KEY_taut:				/* tautology check */
+	printf("ON-set is%sa tautology\n",
+	    tautology(cube1list(PLA->F)) ? " " : " not ");
+	print_solution = FALSE;
+	break;
+
+    case KEY_contain:				/* single cube containment */
+	PLA->F = sf_contain(PLA->F);
+	break;
+
+    case KEY_intersect:				/* cover intersection */
+	PLA->F = cv_intersect(PLA->F, PLA1->F);
+	break;
+
+    case KEY_union:				/* cover union */
+	PLA->F = sf_union(PLA->F, PLA1->F);
+	break;
+
+    case KEY_disjoint:				/* make cover disjoint */
+	PLA->F = make_disjoint(PLA->F);
+	break;
+
+    case KEY_dsharp:				/* cover disjoint-sharp */
+	PLA->F = cv_dsharp(PLA->F, PLA1->F);
+	break;
+
+    case KEY_sharp:				/* cover sharp */
+	PLA->F = cv_sharp(PLA->F, PLA1->F);
+	break;
+
+    case KEY_lexsort:				/* lexical sort order */
+	PLA->F = lex_sort(PLA->F);
+	break;
+
+    case KEY_stats:				/* print info on size */
+	if (! summary) PLA_summary(PLA);
+	print_solution = FALSE;
+	break;
+
+    case KEY_minterms:				/* explode into minterms */
+	if (first < 0 || first >= cube.num_vars) {
+	    first = 0;
+	}
+	if (last < 0 || last >= cube.num_vars) {
+	    last = cube.num_vars - 1;
+	}
+	PLA->F = sf_dupl(unravel_range(PLA->F, first, last));
+	break;
+
+    case KEY_d1merge:				/* distance-1 merge */
+	if (first < 0 || first >= cube.num_vars) {
+	    first = 0;
+	}
+	if (last < 0 || last >= cube.num_vars) {
+	    last = cube.num_vars - 1;
+	}
+	for(i = first; i <= last; i++) {
+	    PLA->F = d1merge(PLA->F, i);
+	}
+	break;
+
+    case KEY_d1merge_in:		/* distance-1 merge inputs only */
+	for(i = 0; i < cube.num_binary_vars; i++) {
+	    PLA->F = d1merge(PLA->F, i);
+	}
+	break;
+
+    case KEY_PLA_verify:		/* check two PLAs for equivalence */
+	EXECUTE(error = PLA_verify(PLA, PLA1), VERIFY_TIME, PLA->F, cost);
+	if (error) {
+	    printf("PLA comparison failed; the PLA's are not equivalent\n");
+	    exit(1);
+	} else {
+	    printf("PLA's compared equal\n");
+	    exit(0);
+	}
+	break;	/* silly */
+
+    case KEY_verify:			/* check two covers for equivalence */
+	Fold = PLA->F;	Dold = PLA->D;	F = PLA1->F;
+	EXECUTE(error=verify(F, Fold, Dold), VERIFY_TIME, PLA->F, cost);
+	if (error) {
+	    printf("PLA comparison failed; the PLA's are not equivalent\n");
+	    exit(1);
+	} else {
+	    printf("PLA's compared equal\n");
+	    exit(0);
+	}	
+	break;	/* silly */
+
+    case KEY_check:			/* check consistency */
+	(void) check_consistency(PLA);
+	print_solution = FALSE;
+	break;
+
+    case KEY_mapdc:			/* compute don't care set */
+	map_dcset(PLA);
+	out_type = FD_type;
+	break;
+
+    case KEY_equiv:
+	find_equiv_outputs(PLA);
+	print_solution = FALSE;
+	break;
+
+    case KEY_separate:			/* remove PLA->D from PLA->F */
+	PLA->F = complement(cube2list(PLA->D, PLA->R));
+	break;
+
+    case KEY_xor: {
+	pcover T1 = cv_intersect(PLA->F, PLA1->R);
+	pcover T2 = cv_intersect(PLA1->F, PLA->R);
+	free_cover(PLA->F);
+	PLA->F = sf_contain(sf_join(T1, T2));
+	free_cover(T1);
+	free_cover(T2);
+	break;
+    }
+
+    case KEY_fsm: {
+	disassemble_fsm(PLA, summary);
+	print_solution = FALSE;
+	break;
+    }
+
+    case KEY_test: {
+	pcover T, E;
+	T = sf_join(PLA->D, PLA->R);
+	E = new_cover(10);
+	sf_free(PLA->F);
+	EXECUTE(PLA->F = complement(cube1list(T)), COMPL_TIME, PLA->F, cost);
+	EXECUTE(PLA->F = expand(PLA->F, T, FALSE), EXPAND_TIME, PLA->F, cost);
+	EXECUTE(PLA->F = irredundant(PLA->F, E), IRRED_TIME, PLA->F, cost);
+	sf_free(T);
+	T = sf_join(PLA->F, PLA->R);
+	EXECUTE(PLA->D = expand(PLA->D, T, FALSE), EXPAND_TIME, PLA->D, cost);
+	EXECUTE(PLA->D = irredundant(PLA->D, E), IRRED_TIME, PLA->D, cost);
+	sf_free(T);
+	sf_free(E);
+	break;
+    }
+
+
+    }
+
+    /* Print a runtime summary if trace mode enabled */
+    if (trace) {
+	runtime();
+    }
+
+    /* Print total runtime */
+    if (summary || trace) {
+	print_trace(PLA->F, option_table[option].name, ptime()-start);
+    }
+
+    /* Output the solution */
+    if (print_solution) {
+	EXECUTE(fprint_pla(stdout, PLA, out_type), WRITE_TIME, PLA->F, cost);
+    }
+
+    /* Crash and burn if there was a verify error */
+    if (error) {
+	fatal("cover verification failed");
+    }
+
+    /* cleanup all used memory */
+    free_PLA(PLA);
+    FREE(cube.part_size);
+    setdown_cube();             /* free the cube/cdata structure data */
+    sf_cleanup();               /* free unused set structures */
+    sm_cleanup();               /* sparse matrix cleanup */
+
+    exit(0);
+}
+
+
+getPLA(opt, argc, argv, option, PLA, out_type)
+int opt;
+int argc;
+char *argv[];
+int option;
+pPLA *PLA;
+int out_type;
+{
+    FILE *fp;
+    int needs_dcset, needs_offset;
+    char *fname;
+
+    if (opt >= argc) {
+	fp = stdin;
+	fname = "(stdin)";
+    } else {
+	fname = argv[opt];
+	if (strcmp(fname, "-") == 0) {
+	    fp = stdin;
+	} else if ((fp = fopen(argv[opt], "r")) == NULL) {
+	    (void) fprintf(stderr, "%s: Unable to open %s\n", argv[0], fname);
+	    exit(1);
+	}
+    }
+    if (option_table[option].key == KEY_echo) {
+	needs_dcset = (out_type & D_type) != 0;
+	needs_offset = (out_type & R_type) != 0;
+    } else {
+	needs_dcset = option_table[option].needs_dcset;
+	needs_offset = option_table[option].needs_offset;
+    }
+
+    if (read_pla(fp, needs_dcset, needs_offset, input_type, PLA) == EOF) {
+	(void) fprintf(stderr, "%s: Unable to find PLA on file %s\n", argv[0], fname);
+	exit(1);
+    }
+    (*PLA)->filename = util_strsav(fname);
+    filename = (*PLA)->filename;
+/*    (void) fclose(fp);*/
+/* hackto support -Dmany */
+    last_fp = fp;
+}
+
+
+runtime()
+{
+    int i;
+    long total = 1, temp;
+
+    for(i = 0; i < TIME_COUNT; i++) {
+	total += total_time[i];
+    }
+    for(i = 0; i < TIME_COUNT; i++) {
+	if (total_calls[i] != 0) {
+	    temp = 100 * total_time[i];
+	    printf("# %s\t%2d call(s) for %s (%2ld.%01ld%%)\n",
+		total_name[i], total_calls[i], print_time(total_time[i]),
+		    temp/total, (10 * (temp%total)) / total);
+	}
+    }
+}
+
+
+init_runtime()
+{
+    total_name[READ_TIME] =     "READ       ";
+    total_name[WRITE_TIME] =    "WRITE      ";
+    total_name[COMPL_TIME] =    "COMPL      ";
+    total_name[REDUCE_TIME] =   "REDUCE     ";
+    total_name[EXPAND_TIME] =   "EXPAND     ";
+    total_name[ESSEN_TIME] =    "ESSEN      ";
+    total_name[IRRED_TIME] =    "IRRED      ";
+    total_name[GREDUCE_TIME] =  "REDUCE_GASP";
+    total_name[GEXPAND_TIME] =  "EXPAND_GASP";
+    total_name[GIRRED_TIME] =   "IRRED_GASP ";
+    total_name[MV_REDUCE_TIME] ="MV_REDUCE  ";
+    total_name[RAISE_IN_TIME] = "RAISE_IN   ";
+    total_name[VERIFY_TIME] =   "VERIFY     ";
+    total_name[PRIMES_TIME] =   "PRIMES     ";
+    total_name[MINCOV_TIME] =   "MINCOV     ";
+}
+
+
+subcommands()
+{
+    int i, col;
+    printf("                ");
+    col = 16;
+    for(i = 0; option_table[i].name != 0; i++) {
+	if ((col + strlen(option_table[i].name) + 1) > 76) {
+	    printf(",\n                ");
+	    col = 16;
+	} else if (i != 0) {
+	    printf(", ");
+	}
+	printf("%s", option_table[i].name);
+	col += strlen(option_table[i].name) + 2;
+    }
+    printf("\n");
+}
+
+
+usage()
+{
+    printf("%s\n\n", VERSION);
+    printf("SYNOPSIS: espresso [options] [file]\n\n");
+    printf("  -d        Enable debugging\n");
+    printf("  -e[opt]   Select espresso option:\n");
+    printf("                fast, ness, nirr, nunwrap, onset, pos, strong,\n");
+    printf("                eat, eatdots, kiss, random\n");
+    printf("  -o[type]  Select output format:\n");
+    printf("                f, fd, fr, fdr, pleasure, eqntott, kiss, cons\n");
+    printf("  -rn-m     Select range for subcommands:\n");
+    printf("                d1merge: first and last variables (0 ... m-1)\n");
+    printf("                minterms: first and last variables (0 ... m-1)\n");
+    printf("                opoall: first and last outputs (0 ... m-1)\n");
+    printf("  -s        Provide short execution summary\n");
+    printf("  -t        Provide longer execution trace\n");
+    printf("  -x        Suppress printing of solution\n");
+    printf("  -v[type]  Verbose debugging detail (-v '' for all)\n");
+    printf("  -D[cmd]   Execute subcommand 'cmd':\n");
+    subcommands();
+    printf("  -Sn       Select strategy for subcommands:\n");
+    printf("                opo: bit2=exact bit1=repeated bit0=skip sparse\n");
+    printf("                opoall: 0=minimize, 1=exact\n");
+    printf("                pair: 0=algebraic, 1=strongd, 2=espresso, 3=exact\n");
+    printf("                pairall: 0=minimize, 1=exact, 2=opo\n");
+    printf("                so_espresso: 0=minimize, 1=exact\n");
+    printf("                so_both: 0=minimize, 1=exact\n");
+}
+
+/*
+ *  Hack for backward compatibility (ACK! )
+ */
+
+backward_compatibility_hack(argc, argv, option, out_type)
+int *argc;
+char **argv;
+int *option;
+int *out_type;
+{
+    int i, j;
+
+    /* Scan the argument list for something to do (default is ESPRESSO) */
+    *option = 0;
+    for(i = 1; i < (*argc)-1; i++) {
+	if (strcmp(argv[i], "-do") == 0) {
+	    for(j = 0; option_table[j].name != 0; j++)
+		if (strcmp(argv[i+1], option_table[j].name) == 0) {
+		    *option = j;
+		    delete_arg(argc, argv, i+1);
+		    delete_arg(argc, argv, i);
+		    break;
+		}
+	    if (option_table[j].name == 0) {
+		(void) fprintf(stderr,
+		 "espresso: bad keyword \"%s\" following -do\n",argv[i+1]);
+		exit(1);
+	    }
+	    break;
+	}
+    }
+
+    for(i = 1; i < (*argc)-1; i++) {
+	if (strcmp(argv[i], "-out") == 0) {
+	    for(j = 0; pla_types[j].key != 0; j++)
+		if (strcmp(pla_types[j].key+1, argv[i+1]) == 0) {
+		    *out_type = pla_types[j].value;
+		    delete_arg(argc, argv, i+1);
+		    delete_arg(argc, argv, i);
+		    break;
+		}
+	    if (pla_types[j].key == 0) {
+		(void) fprintf(stderr,
+		   "espresso: bad keyword \"%s\" following -out\n",argv[i+1]);
+		exit(1);
+	    }
+	    break;
+	}
+    }
+
+    for(i = 1; i < (*argc); i++) {
+	if (argv[i][0] == '-') {
+	    for(j = 0; esp_opt_table[j].name != 0; j++) {
+		if (strcmp(argv[i]+1, esp_opt_table[j].name) == 0) {
+		    delete_arg(argc, argv, i);
+		    *(esp_opt_table[j].variable) = esp_opt_table[j].value;
+		    break;
+		}
+	    }
+	}
+    }
+
+    if (check_arg(argc, argv, "-fdr")) input_type = FDR_type;
+    if (check_arg(argc, argv, "-fr")) input_type = FR_type;
+    if (check_arg(argc, argv, "-f")) input_type = F_type;
+}
+
+
+/* delete_arg -- delete an argument from the argument list */
+delete_arg(argc, argv, num)
+int *argc, num;
+register char *argv[];
+{
+    register int i;
+    (*argc)--;
+    for(i = num; i < *argc; i++) {
+	argv[i] = argv[i+1];
+    }
+}
+
+
+/* check_arg -- scan argv for an argument, and return TRUE if found */
+bool check_arg(argc, argv, s)
+int *argc;
+register char *argv[], *s;
+{
+    register int i;
+    for(i = 1; i < *argc; i++) {
+	if (strcmp(argv[i], s) == 0) {
+	    delete_arg(argc, argv, i);
+	    return TRUE;
+	}
+    }
+    return FALSE;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/main.h.bak b/abc-build/src/misc/espresso/main.h.bak
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/main.h.bak
@@ -0,0 +1,122 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+enum keys {
+    KEY_ESPRESSO, KEY_PLA_verify, KEY_check, KEY_contain, KEY_d1merge,
+    KEY_disjoint, KEY_dsharp, KEY_echo, KEY_essen, KEY_exact, KEY_expand,
+    KEY_gasp, KEY_intersect, KEY_irred, KEY_lexsort, KEY_make_sparse,
+    KEY_map, KEY_mapdc, KEY_minterms, KEY_opo, KEY_opoall,
+    KEY_pair, KEY_pairall, KEY_primes, KEY_qm, KEY_reduce, KEY_sharp,
+    KEY_simplify, KEY_so, KEY_so_both, KEY_stats, KEY_super_gasp, KEY_taut,
+    KEY_test, KEY_equiv, KEY_union, KEY_verify, KEY_MANY_ESPRESSO,
+    KEY_separate, KEY_xor, KEY_d1merge_in, KEY_fsm,
+    KEY_unknown
+};
+
+/* Lookup table for program options */
+struct {
+    char *name;
+    enum keys key;
+    int num_plas;
+    bool needs_offset;
+    bool needs_dcset;
+} option_table [] = {
+    /* ways to minimize functions */
+    "ESPRESSO", KEY_ESPRESSO, 1, TRUE, TRUE,    /* must be first */
+    "many", KEY_MANY_ESPRESSO, 1, TRUE, TRUE,
+    "exact", KEY_exact, 1, TRUE, TRUE,
+    "qm", KEY_qm, 1, TRUE, TRUE,
+    "single_output", KEY_so, 1, TRUE, TRUE,
+    "so", KEY_so, 1, TRUE, TRUE,
+    "so_both", KEY_so_both, 1, TRUE, TRUE,
+    "simplify", KEY_simplify, 1, FALSE, FALSE,
+    "echo", KEY_echo, 1, FALSE, FALSE,
+
+    /* output phase assignment and assignment of inputs to two-bit decoders */
+    "opo", KEY_opo, 1, TRUE, TRUE,
+    "opoall", KEY_opoall, 1, TRUE, TRUE,
+    "pair", KEY_pair, 1, TRUE, TRUE,
+    "pairall", KEY_pairall, 1, TRUE, TRUE,
+
+    /* Ways to check covers */
+    "check", KEY_check, 1, TRUE, TRUE,
+    "stats", KEY_stats, 1, FALSE, FALSE,
+    "verify", KEY_verify, 2, FALSE, TRUE,
+    "PLAverify", KEY_PLA_verify, 2, FALSE, TRUE,
+
+    /* hacks */
+    "equiv", KEY_equiv, 1, TRUE, TRUE,
+    "map", KEY_map, 1, FALSE, FALSE,
+    "mapdc", KEY_mapdc, 1, FALSE, FALSE,
+    "fsm", KEY_fsm, 1, FALSE, TRUE,
+
+    /* the basic boolean operations on covers */
+    "contain", KEY_contain, 1, FALSE, FALSE,
+    "d1merge", KEY_d1merge, 1, FALSE, FALSE,
+    "d1merge_in", KEY_d1merge_in, 1, FALSE, FALSE,
+    "disjoint", KEY_disjoint, 1, TRUE, FALSE,
+    "dsharp", KEY_dsharp, 2, FALSE, FALSE,
+    "intersect", KEY_intersect, 2, FALSE, FALSE,
+    "minterms", KEY_minterms, 1, FALSE, FALSE,
+    "primes", KEY_primes, 1, FALSE, TRUE,
+    "separate", KEY_separate, 1, TRUE, TRUE,
+    "sharp", KEY_sharp, 2, FALSE, FALSE,
+    "union", KEY_union, 2, FALSE, FALSE,
+    "xor", KEY_xor, 2, TRUE, TRUE,
+
+    /* debugging only -- call each step of the espresso algorithm */
+    "essen", KEY_essen, 1, FALSE, TRUE,
+    "expand", KEY_expand, 1, TRUE, FALSE,
+    "gasp", KEY_gasp, 1, TRUE, TRUE,
+    "irred", KEY_irred, 1, FALSE, TRUE,
+    "make_sparse", KEY_make_sparse, 1, TRUE, TRUE,
+    "reduce", KEY_reduce, 1, FALSE, TRUE,
+    "taut", KEY_taut, 1, FALSE, FALSE,
+    "super_gasp", KEY_super_gasp, 1, TRUE, TRUE,
+    "lexsort", KEY_lexsort, 1, FALSE, FALSE,
+    "test", KEY_test, 1, TRUE, TRUE,
+    0, KEY_unknown, 0, FALSE, FALSE             /* must be last */
+};
+
+
+struct {
+    char *name;
+    int value;
+} debug_table[] = {
+    "", EXPAND + ESSEN + IRRED + REDUCE + SPARSE + GASP + SHARP + MINCOV,
+    "compl",   COMPL,  "essen",       ESSEN,
+    "expand",  EXPAND, "expand1",     EXPAND1|EXPAND,
+    "irred",   IRRED,  "irred1",      IRRED1|IRRED,
+    "reduce",  REDUCE, "reduce1",     REDUCE1|REDUCE,
+    "mincov",  MINCOV, "mincov1",     MINCOV1|MINCOV,
+    "sparse",  SPARSE, "sharp",       SHARP,
+    "taut",    TAUT,   "gasp",        GASP,
+    "exact",   EXACT,
+    0,
+};
+
+
+struct {
+    char *name;
+    int *variable;
+    int value;
+} esp_opt_table[] = {
+    "eat", &echo_comments, FALSE,
+    "eatdots", &echo_unknown_commands, FALSE,
+    "fast", &single_expand, TRUE,
+    "kiss", &kiss, TRUE,
+    "ness", &remove_essential, FALSE,
+    "nirr", &force_irredundant, FALSE,
+    "nunwrap", &unwrap_onset, FALSE,
+    "onset", &recompute_onset, TRUE,
+    "pos", &pos, TRUE,
+    "random", &use_random_order, TRUE,
+    "strong", &use_super_gasp, TRUE,
+    0,
+};
diff --git a/abc-build/src/misc/espresso/map.c b/abc-build/src/misc/espresso/map.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/map.c
@@ -0,0 +1,122 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+static pcube Gcube;
+static pset Gminterm;
+
+pset minterms(T)
+pcover T;
+{
+    int size, var;
+    register pcube last;
+
+    size = 1;
+    for(var = 0; var < cube.num_vars; var++)
+	size *= cube.part_size[var];
+    Gminterm = set_new(size);
+
+    foreach_set(T, last, Gcube)
+	explode(cube.num_vars-1, 0);
+
+    return Gminterm;
+}
+
+
+void explode(var, z)
+int var, z;
+{
+    int i, last = cube.last_part[var];
+    for(i=cube.first_part[var], z *= cube.part_size[var]; i<=last; i++, z++)
+	if (is_in_set(Gcube, i))
+	{
+	    if (var == 0)
+		set_insert(Gminterm, z);
+	    else
+		explode(var-1, z);
+	}
+}
+
+
+static int mapindex[16][16] = {
+    {  0,  1,  3,  2,   16, 17, 19, 18,      80, 81, 83, 82,   64, 65, 67, 66},
+    {  4,  5,  7,  6,   20, 21, 23, 22,      84, 85, 87, 86,   68, 69, 71, 70},
+    { 12, 13, 15, 14,   28, 29, 31, 30,      92, 93, 95, 94,   76, 77, 79, 78},
+    {  8,  9, 11, 10,   24, 25, 27, 26,      88, 89, 91, 90,   72, 73, 75, 74},
+
+    { 32, 33, 35, 34,   48, 49, 51, 50,     112,113,115,114,   96, 97, 99, 98},
+    { 36, 37, 39, 38,   52, 53, 55, 54,     116,117,119,118,  100,101,103,102},
+    { 44, 45, 47, 46,   60, 61, 63, 62,     124,125,127,126,  108,109,111,110},
+    { 40, 41, 43, 42,   56, 57, 59, 58,     120,121,123,122,  104,105,107,106},
+
+
+    {160,161,163,162,  176,177,179,178,     240,241,243,242,  224,225,227,226},
+    {164,165,167,166,  180,181,183,182,     244,245,247,246,  228,229,231,230},
+    {172,173,175,174,  188,189,191,190,     252,253,255,254,  236,237,239,238},
+    {168,169,171,170,  184,185,187,186,     248,249,251,250,  232,233,235,234},
+
+    {128,129,131,130,  144,145,147,146,     208,209,211,210,  192,193,195,194},
+    {132,133,135,134,  148,149,151,150,     212,213,215,214,  196,197,199,198},
+    {140,141,143,142,  156,157,159,158,     220,221,223,222,  204,205,207,206},
+    {136,137,139,138,  152,153,155,154,     216,217,219,218,  200,201,203,202}
+};
+
+#define POWER2(n) (1 << n)
+void map(T)
+pcover T;
+{
+    int j, k, l, other_input_offset, output_offset, outnum, ind;
+    int largest_input_ind,  numout;
+    char c;
+    pset m;
+    bool some_output;
+
+    m = minterms(T);
+    largest_input_ind = POWER2(cube.num_binary_vars);
+    numout = cube.part_size[cube.num_vars-1];
+
+    for(outnum = 0; outnum < numout; outnum++) {
+	output_offset = outnum * largest_input_ind;
+	printf("\n\nOutput space # %d\n", outnum);
+	for(l = 0; l <= MAX(cube.num_binary_vars - 8, 0); l++) {
+	    other_input_offset = l * 256;
+	    for(k = 0; k < 16; k++) {
+		some_output = FALSE;
+		for(j = 0; j < 16; j++) {
+		    ind = mapindex[k][j] + other_input_offset;
+		    if (ind < largest_input_ind) {
+			c = is_in_set(m, ind+output_offset) ? '1' : '.';
+			putchar(c);
+			some_output = TRUE;
+		    }
+		    if ((j+1)%4 == 0)
+			putchar(' ');
+		    if ((j+1)%8 == 0)
+			printf("  ");
+		}
+		if (some_output)
+		    putchar('\n');
+		if ((k+1)%4 == 0) {
+		    if (k != 15 && mapindex[k+1][0] >= largest_input_ind)
+			break;
+		    putchar('\n');
+		}
+		if ((k+1)%8 == 0)
+		    putchar('\n');
+	    }
+	}
+    }
+    set_free(m);
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/matrix.c b/abc-build/src/misc/espresso/matrix.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/matrix.c
@@ -0,0 +1,579 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+#include "sparse_int.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+ *  free-lists are only used if 'FAST_AND_LOOSE' is set; this is because
+ *  we lose the debugging capability of libmm_t which trashes objects when
+ *  they are free'd.  However, FAST_AND_LOOSE is much faster if matrices
+ *  are created and freed frequently.
+ */
+
+#ifdef FAST_AND_LOOSE
+sm_element *sm_element_freelist;
+sm_row *sm_row_freelist;
+sm_col *sm_col_freelist;
+#endif
+
+
+sm_matrix *
+sm_alloc()
+{
+    register sm_matrix *A;
+
+    A = ALLOC(sm_matrix, 1);
+    A->rows = NIL(sm_row *);
+    A->cols = NIL(sm_col *);
+    A->nrows = A->ncols = 0;
+    A->rows_size = A->cols_size = 0;
+    A->first_row = A->last_row = NIL(sm_row);
+    A->first_col = A->last_col = NIL(sm_col);
+    A->user_word = NIL(char);		/* for our user ... */
+    return A;
+}
+
+
+sm_matrix *
+sm_alloc_size(row, col)
+int row, col;
+{
+    register sm_matrix *A;
+
+    A = sm_alloc();
+    sm_resize(A, row, col);
+    return A;
+}
+
+
+void
+sm_free(A)
+sm_matrix *A;
+{
+#ifdef FAST_AND_LOOSE
+    register sm_row *prow;
+
+    if (A->first_row != 0) {
+	for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+	    /* add the elements to the free list of elements */
+	    prow->last_col->next_col = sm_element_freelist;
+	    sm_element_freelist = prow->first_col;
+	}
+
+	/* Add the linked list of rows to the row-free-list */
+	A->last_row->next_row = sm_row_freelist;
+	sm_row_freelist = A->first_row;
+
+	/* Add the linked list of cols to the col-free-list */
+	A->last_col->next_col = sm_col_freelist;
+	sm_col_freelist = A->first_col;
+    }
+#else
+    register sm_row *prow, *pnext_row;
+    register sm_col *pcol, *pnext_col;
+
+    for(prow = A->first_row; prow != 0; prow = pnext_row) {
+	pnext_row = prow->next_row;
+	sm_row_free(prow);
+    }
+    for(pcol = A->first_col; pcol != 0; pcol = pnext_col) {
+	pnext_col = pcol->next_col;
+	pcol->first_row = pcol->last_row = NIL(sm_element);
+	sm_col_free(pcol);
+    }
+#endif
+
+    /* Free the arrays to map row/col numbers into pointers */
+    FREE(A->rows);
+    FREE(A->cols);
+    FREE(A);
+}
+
+
+sm_matrix *
+sm_dup(A)
+sm_matrix *A; 
+{
+    register sm_row *prow;
+    register sm_element *p;
+    register sm_matrix *B;
+
+    B = sm_alloc();
+    if (A->last_row != 0) {
+	sm_resize(B, A->last_row->row_num, A->last_col->col_num);
+	for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+	    for(p = prow->first_col; p != 0; p = p->next_col) {
+		(void) sm_insert(B, p->row_num, p->col_num);
+	    }
+	}
+    }
+    return B;
+}
+
+
+void 
+sm_resize(A, row, col)
+register sm_matrix *A;
+int row, col;
+{
+    register int i, new_size;
+
+    if (row >= A->rows_size) {
+	new_size = MAX(A->rows_size*2, row+1);
+	A->rows = REALLOC(sm_row *, A->rows, new_size);
+	for(i = A->rows_size; i < new_size; i++) {
+	    A->rows[i] = NIL(sm_row);
+	}
+	A->rows_size = new_size;
+    }
+
+    if (col >= A->cols_size) {
+	new_size = MAX(A->cols_size*2, col+1);
+	A->cols = REALLOC(sm_col *, A->cols, new_size);
+	for(i = A->cols_size; i < new_size; i++) {
+	    A->cols[i] = NIL(sm_col);
+	}
+	A->cols_size = new_size;
+    }
+}
+
+
+/*  
+ *  insert -- insert a value into the matrix
+ */
+sm_element *
+sm_insert(A, row, col)
+register sm_matrix *A;
+register int row, col;
+{
+    register sm_row *prow;
+    register sm_col *pcol;
+    register sm_element *element;
+    sm_element *save_element;
+
+    if (row >= A->rows_size || col >= A->cols_size) {
+	sm_resize(A, row, col);
+    }
+
+    prow = A->rows[row];
+    if (prow == NIL(sm_row)) {
+	prow = A->rows[row] = sm_row_alloc();
+	prow->row_num = row;
+	sorted_insert(sm_row, A->first_row, A->last_row, A->nrows, 
+			next_row, prev_row, row_num, row, prow);
+    }
+
+    pcol = A->cols[col];
+    if (pcol == NIL(sm_col)) {
+	pcol = A->cols[col] = sm_col_alloc();
+	pcol->col_num = col;
+	sorted_insert(sm_col, A->first_col, A->last_col, A->ncols, 
+			next_col, prev_col, col_num, col, pcol);
+    }
+
+    /* get a new item, save its address */
+    sm_element_alloc(element);
+    save_element = element;
+
+    /* insert it into the row list */
+    sorted_insert(sm_element, prow->first_col, prow->last_col, 
+		prow->length, next_col, prev_col, col_num, col, element);
+
+    /* if it was used, also insert it into the column list */
+    if (element == save_element) {
+	sorted_insert(sm_element, pcol->first_row, pcol->last_row, 
+		pcol->length, next_row, prev_row, row_num, row, element);
+    } else {
+	/* otherwise, it was already in matrix -- free element we allocated */
+	sm_element_free(save_element);
+    }
+    return element;
+}
+
+
+sm_element *
+sm_find(A, rownum, colnum)
+sm_matrix *A;
+int rownum, colnum;
+{
+    sm_row *prow;
+    sm_col *pcol;
+
+    prow = sm_get_row(A, rownum);
+    if (prow == NIL(sm_row)) {
+	return NIL(sm_element);
+    } else {
+	pcol = sm_get_col(A, colnum);
+	if (pcol == NIL(sm_col)) {
+	    return NIL(sm_element);
+	}
+	if (prow->length < pcol->length) {
+	    return sm_row_find(prow, colnum);
+	} else {
+	    return sm_col_find(pcol, rownum);
+	}
+    }
+}
+
+
+void
+sm_remove(A, rownum, colnum)
+sm_matrix *A;
+int rownum, colnum;
+{
+    sm_remove_element(A, sm_find(A, rownum, colnum));
+}
+
+
+
+void
+sm_remove_element(A, p)
+register sm_matrix *A; 
+register sm_element *p;
+{
+    register sm_row *prow;
+    register sm_col *pcol;
+
+    if (p == 0) return;
+
+    /* Unlink the element from its row */
+    prow = sm_get_row(A, p->row_num);
+    dll_unlink(p, prow->first_col, prow->last_col, 
+			next_col, prev_col, prow->length);
+
+    /* if no more elements in the row, discard the row header */
+    if (prow->first_col == NIL(sm_element)) {
+	sm_delrow(A, p->row_num);
+    }
+
+    /* Unlink the element from its column */
+    pcol = sm_get_col(A, p->col_num);
+    dll_unlink(p, pcol->first_row, pcol->last_row, 
+			next_row, prev_row, pcol->length);
+
+    /* if no more elements in the column, discard the column header */
+    if (pcol->first_row == NIL(sm_element)) {
+	sm_delcol(A, p->col_num);
+    }
+
+    sm_element_free(p);
+}
+
+void 
+sm_delrow(A, i)
+sm_matrix *A;
+int i;
+{
+    register sm_element *p, *pnext;
+    sm_col *pcol;
+    sm_row *prow;
+
+    prow = sm_get_row(A, i);
+    if (prow != NIL(sm_row)) {
+	/* walk across the row */
+	for(p = prow->first_col; p != 0; p = pnext) {
+	    pnext = p->next_col;
+
+	    /* unlink the item from the column (and delete it) */
+	    pcol = sm_get_col(A, p->col_num);
+	    sm_col_remove_element(pcol, p);
+
+	    /* discard the column if it is now empty */
+	    if (pcol->first_row == NIL(sm_element)) {
+		sm_delcol(A, pcol->col_num);
+	    }
+	}
+
+	/* discard the row -- we already threw away the elements */ 
+	A->rows[i] = NIL(sm_row);
+	dll_unlink(prow, A->first_row, A->last_row, 
+				next_row, prev_row, A->nrows);
+	prow->first_col = prow->last_col = NIL(sm_element);
+	sm_row_free(prow);
+    }
+}
+
+void 
+sm_delcol(A, i)
+sm_matrix *A;
+int i;
+{
+    register sm_element *p, *pnext;
+    sm_row *prow;
+    sm_col *pcol;
+
+    pcol = sm_get_col(A, i);
+    if (pcol != NIL(sm_col)) {
+	/* walk down the column */
+	for(p = pcol->first_row; p != 0; p = pnext) {
+	    pnext = p->next_row;
+
+	    /* unlink the element from the row (and delete it) */
+	    prow = sm_get_row(A, p->row_num);
+	    sm_row_remove_element(prow, p);
+
+	    /* discard the row if it is now empty */
+	    if (prow->first_col == NIL(sm_element)) {
+		sm_delrow(A, prow->row_num);
+	    }
+	}
+
+	/* discard the column -- we already threw away the elements */ 
+	A->cols[i] = NIL(sm_col);
+	dll_unlink(pcol, A->first_col, A->last_col, 
+			    next_col, prev_col, A->ncols);
+	pcol->first_row = pcol->last_row = NIL(sm_element);
+	sm_col_free(pcol);
+    }
+}
+
+void
+sm_copy_row(dest, dest_row, prow)
+register sm_matrix *dest;
+int dest_row;
+sm_row *prow;
+{
+    register sm_element *p;
+
+    for(p = prow->first_col; p != 0; p = p->next_col) {
+	(void) sm_insert(dest, dest_row, p->col_num);
+    }
+}
+
+
+void
+sm_copy_col(dest, dest_col, pcol)
+register sm_matrix *dest;
+int dest_col;
+sm_col *pcol;
+{
+    register sm_element *p;
+
+    for(p = pcol->first_row; p != 0; p = p->next_row) {
+	(void) sm_insert(dest, dest_col, p->row_num);
+    }
+}
+
+
+sm_row *
+sm_longest_row(A)
+sm_matrix *A;
+{
+    register sm_row *large_row, *prow;
+    register int max_length;
+
+    max_length = 0;
+    large_row = NIL(sm_row);
+    for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+	if (prow->length > max_length) {
+	    max_length = prow->length;
+	    large_row = prow;
+	}
+    }
+    return large_row;
+}
+
+
+sm_col *
+sm_longest_col(A)
+sm_matrix *A;
+{
+    register sm_col *large_col, *pcol;
+    register int max_length;
+
+    max_length = 0;
+    large_col = NIL(sm_col);
+    for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+	if (pcol->length > max_length) {
+	    max_length = pcol->length;
+	    large_col = pcol;
+	}
+    }
+    return large_col;
+}
+
+int
+sm_num_elements(A)
+sm_matrix *A;
+{
+    register sm_row *prow;
+    register int num;
+
+    num = 0;
+    sm_foreach_row(A, prow) {
+	num += prow->length;
+    }
+    return num;
+}
+
+int 
+sm_read(fp, A)
+FILE *fp;
+sm_matrix **A;
+{
+    int i, j, err;
+
+    *A = sm_alloc();
+    while (! feof(fp)) {
+	err = fscanf(fp, "%d %d", &i, &j);
+	if (err == EOF) {
+	    return 1;
+	} else if (err != 2) {
+	    return 0;
+	}
+	(void) sm_insert(*A, i, j);
+    }
+    return 1;
+}
+
+
+int 
+sm_read_compressed(fp, A)
+FILE *fp;
+sm_matrix **A;
+{
+    int i, j, k, nrows, ncols;
+    unsigned long x;
+
+    *A = sm_alloc();
+    if (fscanf(fp, "%d %d", &nrows, &ncols) != 2) {
+	return 0;
+    }
+    sm_resize(*A, nrows, ncols);
+
+    for(i = 0; i < nrows; i++) {
+	if (fscanf(fp, "%lx", &x) != 1) {
+	    return 0;
+	}
+	for(j = 0; j < ncols; j += 32) {
+	    if (fscanf(fp, "%lx", &x) != 1) {
+		return 0;
+	    }
+	    for(k = j; x != 0; x >>= 1, k++) {
+		if (x & 1) {
+		    (void) sm_insert(*A, i, k);
+		}
+	    }
+	}
+    }
+    return 1;
+}
+
+
+void 
+sm_write(fp, A)
+FILE *fp;
+sm_matrix *A;
+{
+    register sm_row *prow;
+    register sm_element *p;
+
+    for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+	for(p = prow->first_col; p != 0; p = p->next_col) {
+	    (void) fprintf(fp, "%d %d\n", p->row_num, p->col_num);
+	}
+    }
+}
+
+void 
+sm_print(fp, A)
+FILE *fp;
+sm_matrix *A;
+{
+    register sm_row *prow;
+    register sm_col *pcol;
+    int c;
+
+    if (A->last_col->col_num >= 100) {
+	(void) fprintf(fp, "    ");
+	for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+	    (void) fprintf(fp, "%d", (pcol->col_num / 100)%10);
+	}
+	putc('\n', fp);
+    }
+
+    if (A->last_col->col_num >= 10) {
+	(void) fprintf(fp, "    ");
+	for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+	    (void) fprintf(fp, "%d", (pcol->col_num / 10)%10);
+	}
+	putc('\n', fp);
+    }
+
+    (void) fprintf(fp, "    ");
+    for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+	(void) fprintf(fp, "%d", pcol->col_num % 10);
+    }
+    putc('\n', fp);
+
+    (void) fprintf(fp, "    ");
+    for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+	(void) fprintf(fp, "-");
+    }
+    putc('\n', fp);
+
+    for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+	(void) fprintf(fp, "%3d:", prow->row_num);
+
+	for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+	    c = sm_row_find(prow, pcol->col_num) ? '1' : '.';
+	    putc(c, fp);
+	}
+	putc('\n', fp);
+    }
+}
+
+
+void 
+sm_dump(A, s, max)
+sm_matrix *A;
+char *s;
+int max;
+{
+    FILE *fp = stdout;
+
+    (void) fprintf(fp, "%s %d rows by %d cols\n", s, A->nrows, A->ncols);
+    if (A->nrows < max) {
+	sm_print(fp, A);
+    }
+}
+
+void
+sm_cleanup()
+{
+#ifdef FAST_AND_LOOSE
+    register sm_element *p, *pnext;
+    register sm_row *prow, *pnextrow;
+    register sm_col *pcol, *pnextcol;
+
+    for(p = sm_element_freelist; p != 0; p = pnext) {
+	pnext = p->next_col;
+	FREE(p);
+    }
+    sm_element_freelist = 0;
+
+    for(prow = sm_row_freelist; prow != 0; prow = pnextrow) {
+	pnextrow = prow->next_row;
+	FREE(prow);
+    }
+    sm_row_freelist = 0;
+
+    for(pcol = sm_col_freelist; pcol != 0; pcol = pnextcol) {
+	pnextcol = pcol->next_col;
+	FREE(pcol);
+    }
+    sm_col_freelist = 0;
+#endif
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/mincov.c b/abc-build/src/misc/espresso/mincov.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/mincov.c
@@ -0,0 +1,383 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+ *  mincov.c
+ */
+
+#define USE_GIMPEL
+#define USE_INDEP_SET
+
+static int select_column();
+static void select_essential();
+static int verify_cover();
+
+#define fail(why) {\
+    (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\
+	__FILE__, __LINE__, why);\
+    (void) fflush(stdout);\
+    abort();\
+}
+
+sm_row *
+sm_minimum_cover(A, weight, heuristic, debug_level)
+sm_matrix *A;
+int *weight;
+int heuristic;		/* set to 1 for a heuristic covering */
+int debug_level;	/* how deep in the recursion to provide info */
+{
+    stats_t stats;
+    solution_t *best, *select;
+    sm_row *prow, *sol;
+    sm_col *pcol;
+    sm_matrix *dup_A;
+    int nelem, bound;
+    double sparsity;
+
+    /* Avoid sillyness */
+    if (A->nrows <= 0) {
+	return sm_row_alloc();		/* easy to cover */
+    }
+
+    /* Initialize debugging structure */
+    stats.start_time = util_cpu_time();
+    stats.debug = debug_level > 0;
+    stats.max_print_depth = debug_level;
+    stats.max_depth = -1;
+    stats.nodes = 0;
+    stats.component = stats.comp_count = 0;
+    stats.gimpel = stats.gimpel_count = 0;
+    stats.no_branching = heuristic != 0;
+    stats.lower_bound = -1;
+
+    /* Check the matrix sparsity */
+    nelem = 0;
+    sm_foreach_row(A, prow) {
+	nelem += prow->length;
+    }
+    sparsity = (double) nelem / (double) (A->nrows * A->ncols);
+
+    /* Determine an upper bound on the solution */
+    bound = 1;
+    sm_foreach_col(A, pcol) {
+	bound += WEIGHT(weight, pcol->col_num);
+    }
+
+    /* Perform the covering */
+    select = solution_alloc();
+    dup_A = sm_dup(A);
+    best = sm_mincov(dup_A, select, weight, 0, bound, 0, &stats);
+    sm_free(dup_A);
+    solution_free(select);
+
+    if (stats.debug) {
+	if (stats.no_branching) {
+	    (void) printf("**** heuristic covering ...\n");
+	    (void) printf("lower bound = %d\n", stats.lower_bound);
+	}
+	(void) printf("matrix     = %d by %d with %d elements (%4.3f%%)\n",
+		A->nrows, A->ncols, nelem, sparsity * 100.0);
+	(void) printf("cover size = %d elements\n", best->row->length);
+	(void) printf("cover cost = %d\n", best->cost);
+	(void) printf("time       = %s\n", 
+			util_print_time(util_cpu_time() - stats.start_time));
+	(void) printf("components = %d\n", stats.comp_count);
+	(void) printf("gimpel     = %d\n", stats.gimpel_count);
+	(void) printf("nodes      = %d\n", stats.nodes);
+	(void) printf("max_depth  = %d\n", stats.max_depth);
+    }
+
+    sol = sm_row_dup(best->row);
+    if (! verify_cover(A, sol)) {
+	fail("mincov: internal error -- cover verification failed\n");
+    }
+    solution_free(best);
+    return sol;
+}
+
+/*
+ *  Find the best cover for 'A' (given that 'select' already selected);
+ *
+ *    - abort search if a solution cannot be found which beats 'bound'
+ *
+ *    - if any solution meets 'lower_bound', then it is the optimum solution
+ *      and can be returned without further work.
+ */
+
+solution_t * 
+sm_mincov(A, select, weight, lb, bound, depth, stats)
+sm_matrix *A;
+solution_t *select;
+int *weight;
+int lb;
+int bound;
+int depth;
+stats_t *stats;
+{
+    sm_matrix *A1, *A2, *L, *R;
+    sm_element *p;
+    solution_t *select1, *select2, *best, *best1, *best2, *indep;
+    int pick, lb_new, debug;
+
+    /* Start out with some debugging information */
+    stats->nodes++;
+    if (depth > stats->max_depth) stats->max_depth = depth;
+    debug = stats->debug && (depth <= stats->max_print_depth);
+
+    /* Apply row dominance, column dominance, and select essentials */
+    select_essential(A, select, weight, bound);
+    if (select->cost >= bound) {
+	return NIL(solution_t);
+    }
+
+    /* See if gimpel's reduction technique applies ... */
+#ifdef USE_GIMPEL
+    if ( weight == NIL(int)) {	/* hack until we fix it */
+	if (gimpel_reduce(A, select, weight, lb, bound, depth, stats, &best)) {
+	    return best;
+	}
+    }
+#endif
+
+#ifdef USE_INDEP_SET
+    /* Determine bound from here to final solution using independent-set */
+    indep = sm_maximal_independent_set(A, weight);
+
+    /* make sure the lower bound is monotonically increasing */
+    lb_new = MAX(select->cost + indep->cost, lb);
+    pick = select_column(A, weight, indep);
+    solution_free(indep);
+#else
+    lb_new = select->cost + (A->nrows > 0);
+    pick = select_column(A, weight, NIL(solution_t));
+#endif
+
+    if (depth == 0) {
+	stats->lower_bound = lb_new + stats->gimpel;
+    }
+
+    if (debug) {
+        (void) printf("ABSMIN[%2d]%s", depth, stats->component ? "*" : " ");
+        (void) printf(" %3dx%3d sel=%3d bnd=%3d lb=%3d %12s ",
+            A->nrows, A->ncols, select->cost + stats->gimpel, 
+	    bound + stats->gimpel, lb_new + stats->gimpel, 
+	    util_print_time(util_cpu_time()-stats->start_time));
+    }
+
+    /* Check for bounding based on no better solution possible */
+    if (lb_new >= bound) {
+	if (debug) (void) printf("bounded\n");
+	best = NIL(solution_t);
+
+
+    /* Check for new best solution */
+    } else if (A->nrows == 0) {
+	best = solution_dup(select);
+	if (debug) (void) printf("BEST\n");
+	if (stats->debug && stats->component == 0) {
+            (void) printf("new 'best' solution %d at level %d (time is %s)\n", 
+		best->cost + stats->gimpel, depth, 
+		util_print_time(util_cpu_time() - stats->start_time));
+        }
+
+
+    /* Check for a partition of the problem */
+    } else if (sm_block_partition(A, &L, &R)) {
+	/* Make L the smaller problem */
+	if (L->ncols > R->ncols) {
+	    A1 = L;
+	    L = R;
+	    R = A1;
+	}
+	if (debug) (void) printf("comp %d %d\n", L->nrows, R->nrows);
+	stats->comp_count++;
+
+	/* Solve problem for L */
+	select1 = solution_alloc();
+	stats->component++;
+	best1 = sm_mincov(L, select1, weight, 0, 
+				    bound-select->cost, depth+1, stats);
+	stats->component--;
+	solution_free(select1);
+	sm_free(L);
+
+	/* Add best solution to the selected set */
+	if (best1 == NIL(solution_t)) {
+	    best = NIL(solution_t);
+	} else {
+	    for(p = best1->row->first_col; p != 0; p = p->next_col) {
+		solution_add(select, weight, p->col_num);
+	    }
+	    solution_free(best1);
+
+	    /* recur for the remaining block */
+	    best = sm_mincov(R, select, weight, lb_new, bound, depth+1, stats);
+	}
+	sm_free(R);
+
+    /* We've tried as hard as possible, but now we must split and recur */
+    } else {
+	if (debug) (void) printf("pick=%d\n", pick);
+
+        /* Assume we choose this column to be in the covering set */
+	A1 = sm_dup(A);
+	select1 = solution_dup(select);
+	solution_accept(select1, A1, weight, pick);
+        best1 = sm_mincov(A1, select1, weight, lb_new, bound, depth+1, stats);
+	solution_free(select1);
+	sm_free(A1);
+
+	/* Update the upper bound if we found a better solution */
+	if (best1 != NIL(solution_t) && bound > best1->cost) {
+	    bound = best1->cost;
+	}
+
+	/* See if this is a heuristic covering (no branching) */
+	if (stats->no_branching) {
+	    return best1;
+	}
+
+	/* Check for reaching lower bound -- if so, don't actually branch */
+	if (best1 != NIL(solution_t) && best1->cost == lb_new) {
+	    return best1;
+	}
+
+        /* Now assume we cannot have that column */
+	A2 = sm_dup(A);
+	select2 = solution_dup(select);
+	solution_reject(select2, A2, weight, pick);
+        best2 = sm_mincov(A2, select2, weight, lb_new, bound, depth+1, stats);
+	solution_free(select2);
+	sm_free(A2);
+
+	best = solution_choose_best(best1, best2);
+    }
+
+    return best;
+}
+
+static int 
+select_column(A, weight, indep)
+sm_matrix *A;
+int *weight;
+solution_t *indep;
+{
+    register sm_col *pcol;
+    register sm_row *prow, *indep_cols;
+    register sm_element *p, *p1;
+    double w, best;
+    int best_col;
+
+    indep_cols = sm_row_alloc();
+    if (indep != NIL(solution_t)) {
+	/* Find which columns are in the independent sets */
+	for(p = indep->row->first_col; p != 0; p = p->next_col) {
+	    prow = sm_get_row(A, p->col_num);
+	    for(p1 = prow->first_col; p1 != 0; p1 = p1->next_col) {
+		(void) sm_row_insert(indep_cols, p1->col_num);
+	    }
+	}
+    } else {
+	/* select out of all columns */
+	sm_foreach_col(A, pcol) {
+	    (void) sm_row_insert(indep_cols, pcol->col_num);
+	}
+    }
+
+    /* Find the best column */
+    best_col = -1;
+    best = -1;
+
+    /* Consider only columns which are in some independent row */
+    sm_foreach_row_element(indep_cols, p1) {
+	pcol = sm_get_col(A, p1->col_num);
+
+	/* Compute the total 'value' of all things covered by the column */
+	w = 0.0;
+	for(p = pcol->first_row; p != 0; p = p->next_row) {
+	    prow = sm_get_row(A, p->row_num);
+	    w += 1.0 / ((double) prow->length - 1.0);
+	}
+
+	/* divide this by the relative cost of choosing this column */
+	w = w / (double) WEIGHT(weight, pcol->col_num);
+
+	/* maximize this ratio */
+	if (w  > best) {
+	    best_col = pcol->col_num;
+	    best = w;
+	}
+    }
+
+    sm_row_free(indep_cols);
+    return best_col;
+}
+
+static void 
+select_essential(A, select, weight, bound)
+sm_matrix *A;
+solution_t *select;
+int *weight;
+int bound;			/* must beat this solution */
+{
+    register sm_element *p;
+    register sm_row *prow, *essen;
+    int delcols, delrows, essen_count;
+
+    do {
+	/*  Check for dominated columns  */
+	delcols = sm_col_dominance(A, weight);
+
+	/*  Find the rows with only 1 element (the essentials) */
+	essen = sm_row_alloc();
+	sm_foreach_row(A, prow) {
+	    if (prow->length == 1) {
+		(void) sm_row_insert(essen, prow->first_col->col_num);
+	    }
+	}
+
+	/* Select all of the elements */
+	sm_foreach_row_element(essen, p) {
+	    solution_accept(select, A, weight, p->col_num);
+	    /* Make sure solution still looks good */
+	    if (select->cost >= bound) {
+		sm_row_free(essen);
+		return;
+	    }
+	}
+	essen_count = essen->length;
+	sm_row_free(essen);
+
+	/*  Check for dominated rows  */
+	delrows = sm_row_dominance(A);
+
+    } while (delcols > 0 || delrows > 0 || essen_count > 0);
+}
+
+static int 
+verify_cover(A, cover)
+sm_matrix *A;
+sm_row *cover;
+{
+    sm_row *prow;
+
+    sm_foreach_row(A, prow) {
+	if (! sm_row_intersects(prow, cover)) {
+	    return 0;
+	}
+    }
+    return 1;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/mincov.h b/abc-build/src/misc/espresso/mincov.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/mincov.h
@@ -0,0 +1,11 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/* exported */
+extern sm_row *sm_minimum_cover();
diff --git a/abc-build/src/misc/espresso/mincov_int.h b/abc-build/src/misc/espresso/mincov_int.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/mincov_int.h
@@ -0,0 +1,55 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+//#include "utility.h"
+#include "sparse.h"
+#include "mincov.h"
+
+#include "util_hack.h" // added
+
+
+typedef struct stats_struct stats_t;
+struct stats_struct {
+    int debug;			/* 1 if debugging is enabled */
+    int max_print_depth;	/* dump stats for levels up to this level */
+    int max_depth;		/* deepest the recursion has gone */
+    int nodes;			/* total nodes visited */
+    int component;		/* currently solving a component */
+    int comp_count;		/* number of components detected */
+    int gimpel_count;		/* number of times Gimpel reduction applied */
+    int gimpel;			/* currently inside Gimpel reduction */
+    long start_time;		/* cpu time when the covering started */
+    int no_branching;
+    int lower_bound;
+};
+
+
+
+typedef struct solution_struct solution_t;
+struct solution_struct {
+    sm_row *row;
+    int cost;
+};
+
+
+extern solution_t *solution_alloc();
+extern void solution_free();
+extern solution_t *solution_dup();
+extern void solution_accept();
+extern void solution_reject();
+extern void solution_add();
+extern solution_t *solution_choose_best();
+
+extern solution_t *sm_maximal_independent_set();
+extern solution_t *sm_mincov();
+extern int gimpel_reduce();
+
+
+#define ABC__misc__espresso__mincov_int_h
diff --git a/abc-build/src/misc/espresso/module.make b/abc-build/src/misc/espresso/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/module.make
@@ -0,0 +1,39 @@
+SRC +=  src/misc/espresso/cofactor.c \
+	src/misc/espresso/cols.c \
+	src/misc/espresso/compl.c \
+	src/misc/espresso/contain.c \
+	src/misc/espresso/cubehack.c \
+	src/misc/espresso/cubestr.c \
+	src/misc/espresso/cvrin.c \
+	src/misc/espresso/cvrm.c \
+	src/misc/espresso/cvrmisc.c \
+	src/misc/espresso/cvrout.c \
+	src/misc/espresso/dominate.c \
+	src/misc/espresso/equiv.c \
+	src/misc/espresso/espresso.c \
+	src/misc/espresso/essen.c \
+	src/misc/espresso/exact.c \
+	src/misc/espresso/expand.c \
+	src/misc/espresso/gasp.c \
+	src/misc/espresso/gimpel.c \
+	src/misc/espresso/globals.c \
+	src/misc/espresso/hack.c \
+	src/misc/espresso/indep.c \
+	src/misc/espresso/irred.c \
+	src/misc/espresso/map.c \
+	src/misc/espresso/matrix.c \
+	src/misc/espresso/mincov.c \
+	src/misc/espresso/opo.c \
+	src/misc/espresso/pair.c \
+	src/misc/espresso/part.c \
+	src/misc/espresso/primes.c \
+	src/misc/espresso/reduce.c \
+	src/misc/espresso/rows.c \
+	src/misc/espresso/set.c \
+	src/misc/espresso/setc.c \
+	src/misc/espresso/sharp.c \
+	src/misc/espresso/sminterf.c \
+	src/misc/espresso/solution.c \
+	src/misc/espresso/sparse.c \
+	src/misc/espresso/unate.c \
+	src/misc/espresso/verify.c
diff --git a/abc-build/src/misc/espresso/opo.c b/abc-build/src/misc/espresso/opo.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/opo.c
@@ -0,0 +1,629 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+ *   Phase assignment technique (T. Sasao):
+ *
+ *      1. create a function with 2*m outputs which implements the
+ *      original function and its complement for each output
+ *
+ *      2. minimize this function
+ *
+ *      3. choose the minimum number of prime implicants from the
+ *      result of step 2 which are needed to realize either a function
+ *      or its complement for each output
+ *
+ *  Step 3 is performed in a rather crude way -- by simply multiplying
+ *  out a large expression of the form:
+ *
+ *      I = (ab + cdef)(acd + bgh) ...
+ *
+ *  which is a product of m expressions where each expression has two
+ *  product terms -- one representing which primes are needed for the
+ *  function, and one representing which primes are needed for the
+ *  complement.  The largest product term resulting shows which primes
+ *  to keep to implement one function or the other for each output.
+ *  For problems with many outputs, this may grind to a
+ *  halt.
+ *
+ *  Untried: form complement of I and use unate_complement ...
+ *
+ *  I have unsuccessfully tried several modifications to the basic
+ *  algorithm.  The first is quite simple: use Sasao's technique, but
+ *  only commit to a single output at a time (rather than all
+ *  outputs).  The goal would be that the later minimizations can "take
+ *  into account" the partial assignment at each step.  This is
+ *  expensive (m+1 minimizations rather than 2), and the results are
+ *  discouraging.
+ *
+ *  The second modification is rather complicated.  The result from the
+ *  minimization in step 2 is guaranteed to be minimal.  Hence, for
+ *  each output, the set of primes with a 1 in that output are both
+ *  necessary and sufficient to implement the function.  Espresso
+ *  achieves the minimality using the routine MAKE_SPARSE.  The
+ *  modification is to prevent MAKE_SPARSE from running.  Hence, there
+ *  are potentially many subsets of the set of primes with a 1 in a
+ *  column which can be used to implement that output.  We use
+ *  IRREDUNDANT to enumerate all possible subsets and then proceed as
+ *  before.
+ */
+
+static int opo_no_make_sparse;
+static int opo_repeated;
+static int opo_exact;
+static void minimize();
+
+void phase_assignment(PLA, opo_strategy)
+pPLA PLA;
+int opo_strategy;
+{
+    opo_no_make_sparse = opo_strategy % 2;
+    skip_make_sparse = opo_no_make_sparse;
+    opo_repeated = (opo_strategy / 2) % 2;
+    opo_exact = (opo_strategy / 4) % 2;
+
+    /* Determine a phase assignment */
+    if (PLA->phase != NULL) {
+	FREE(PLA->phase);
+    }
+
+    if (opo_repeated) {
+	PLA->phase = set_save(cube.fullset);
+	repeated_phase_assignment(PLA);
+    } else {
+	PLA->phase = find_phase(PLA, 0, (pcube) NULL);
+    }
+
+    /* Now minimize with this assignment */
+    skip_make_sparse = FALSE;
+    (void) set_phase(PLA);
+    minimize(PLA);
+}
+
+/*
+ *  repeated_phase_assignment -- an alternate strategy which commits
+ *  to a single phase assignment a step at a time.  Performs m + 1
+ *  minimizations !
+ */
+void repeated_phase_assignment(PLA)
+pPLA PLA;
+{
+    int i;
+    pcube phase;
+
+    for(i = 0; i < cube.part_size[cube.output]; i++) {
+
+	/* Find best assignment for all undecided outputs */
+	phase = find_phase(PLA, i, PLA->phase);
+
+	/* Commit for only a single output ... */
+	if (! is_in_set(phase, cube.first_part[cube.output] + i)) {
+	    set_remove(PLA->phase, cube.first_part[cube.output] + i);
+	}
+
+	if (trace || summary) {
+	    printf("\nOPO loop for output #%d\n", i);
+	    printf("PLA->phase is %s\n", pc1(PLA->phase));
+	    printf("phase      is %s\n", pc1(phase));
+	}
+	set_free(phase);
+    }
+}
+
+
+/*
+ *  find_phase -- find a phase assignment for the PLA for all outputs starting
+ *  with output number first_output.
+ */
+pcube find_phase(PLA, first_output, phase1)
+pPLA PLA;
+int first_output;
+pcube phase1;
+{
+    pcube phase;
+    pPLA PLA1;
+
+    phase = set_save(cube.fullset);
+
+    /* setup the double-phase characteristic function, resize the cube */
+    PLA1 = new_PLA();
+    PLA1->F = sf_save(PLA->F);
+    PLA1->R = sf_save(PLA->R);
+    PLA1->D = sf_save(PLA->D);
+    if (phase1 != NULL) {
+	PLA1->phase = set_save(phase1);
+	(void) set_phase(PLA1);
+    }
+    EXEC_S(output_phase_setup(PLA1, first_output), "OPO-SETUP ", PLA1->F);
+
+    /* minimize the double-phase function */
+    minimize(PLA1);
+
+    /* set the proper phases according to what gives a minimum solution */
+    EXEC_S(PLA1->F = opo(phase, PLA1->F, PLA1->D, PLA1->R, first_output),
+	    "OPO       ", PLA1->F);
+    free_PLA(PLA1);
+
+    /* set the cube structure to reflect the old size */
+    setdown_cube();
+    cube.part_size[cube.output] -=
+	(cube.part_size[cube.output] - first_output) / 2;
+    cube_setup();
+
+    return phase;
+}
+
+/*
+ *  opo -- multiply the expression out to determine a minimum subset of
+ *  primes.
+ */
+
+/*ARGSUSED*/
+pcover opo(phase, T, D, R, first_output)
+pcube phase;
+pcover T, D, R;
+int first_output;
+{
+    int offset, output, i, last_output, ind;
+    pset pdest, select, p, p1, last, last1, not_covered, tmp;
+    pset_family temp, T1, T2;
+
+    /* must select all primes for outputs [0 .. first_output-1] */
+    select = set_full(T->count);
+    for(output = 0; output < first_output; output++) {
+	ind = cube.first_part[cube.output] + output;
+	foreachi_set(T, i, p) {
+	    if (is_in_set(p, ind)) {
+		set_remove(select, i);
+	    }
+	}
+    }
+
+    /* Recursively perform the intersections */
+    offset = (cube.part_size[cube.output] - first_output) / 2;
+    last_output = first_output + offset - 1;
+    temp = opo_recur(T, D, select, offset, first_output, last_output);
+
+    /* largest set is on top -- select primes which are inferred from it */
+    pdest = temp->data;
+    T1 = new_cover(T->count);
+    foreachi_set(T, i, p) {
+	if (! is_in_set(pdest, i)) {
+	    T1 = sf_addset(T1, p);
+	}
+    }
+
+    set_free(select);
+    sf_free(temp);
+
+    /* finding phases is difficult -- see which functions are not covered */
+    T2 = complement(cube1list(T1));
+    not_covered = new_cube();
+    tmp = new_cube();
+    foreach_set(T, last, p) {
+	foreach_set(T2, last1, p1) {
+	    if (cdist0(p, p1)) {
+		(void) set_or(not_covered, not_covered, set_and(tmp, p, p1));
+	    }
+	}
+    }
+    free_cover(T);
+    free_cover(T2);
+    set_free(tmp);
+
+    /* Now reflect the phase choice in a single cube */
+    for(output = first_output; output <= last_output; output++) {
+	ind = cube.first_part[cube.output] + output;
+	if (is_in_set(not_covered, ind)) {
+	    if (is_in_set(not_covered, ind + offset)) {
+		fatal("error in output phase assignment");
+	    } else {
+		set_remove(phase, ind);
+	    }
+	}
+    }
+    set_free(not_covered);
+    return T1;
+}
+
+pset_family opo_recur(T, D, select, offset, first, last)
+pcover T, D;
+pcube select;
+int offset, first, last;
+{
+    static int level = 0;
+    int middle;
+    pset_family sl, sr, temp;
+
+    level++;
+    if (first == last) {
+#if 0
+	if (opo_no_make_sparse) {
+	    temp = form_cover_table(T, D, select, first, first + offset);
+	} else {
+	    temp = opo_leaf(T, select, first, first + offset);
+	}
+#else
+	temp = opo_leaf(T, select, first, first + offset);
+#endif
+    } else {
+	middle = (first + last) / 2;
+	sl = opo_recur(T, D, select, offset, first, middle);
+	sr = opo_recur(T, D, select, offset, middle+1, last);
+	temp = unate_intersect(sl, sr, level == 1);
+	if (trace) {
+	    printf("# OPO[%d]: %4d = %4d x %4d, time = %s\n", level - 1,
+		temp->count, sl->count, sr->count, print_time(ptime()));
+	    (void) fflush(stdout);
+	}
+	free_cover(sl);
+	free_cover(sr);
+    }
+    level--;
+    return temp;
+}
+
+
+pset_family opo_leaf(T, select, out1, out2)
+register pcover T;
+pset select;
+int out1, out2;
+{
+    register pset_family temp;
+    register pset p, pdest;
+    register int i;
+
+    out1 += cube.first_part[cube.output];
+    out2 += cube.first_part[cube.output];
+
+    /* Allocate space for the result */
+    temp = sf_new(2, T->count);
+
+    /* Find which primes are needed for the ON-set of this fct */
+    pdest = GETSET(temp, temp->count++);
+    (void) set_copy(pdest, select);
+    foreachi_set(T, i, p) {
+	if (is_in_set(p, out1)) {
+	    set_remove(pdest, i);
+	}
+    }
+
+    /* Find which primes are needed for the OFF-set of this fct */
+    pdest = GETSET(temp, temp->count++);
+    (void) set_copy(pdest, select);
+    foreachi_set(T, i, p) {
+	if (is_in_set(p, out2)) {
+	    set_remove(pdest, i);
+	}
+    }
+
+    return temp;
+}
+
+#if 0
+pset_family form_cover_table(F, D, select, f, fbar)
+pcover F, D;
+pset select;
+int f, fbar;		/* indices of f and fbar in the output part */
+{
+    register int i;
+    register pcube p;
+    pset_family f_table, fbar_table;
+
+    /* setup required for fcube_is_covered */
+    Rp_size = F->count;
+    Rp_start = set_new(Rp_size);
+    foreachi_set(F, i, p) {
+	PUTSIZE(p, i);
+    }
+    foreachi_set(D, i, p) {
+	RESET(p, REDUND);
+    }
+
+    f_table = find_covers(F, D, select, f);
+    fbar_table = find_covers(F, D, select, fbar);
+    f_table = sf_append(f_table, fbar_table);
+
+    set_free(Rp_start);
+    return f_table;
+}
+
+
+pset_family find_covers(F, D, select, n)
+pcover F, D;
+register pset select;
+int n;
+{
+    register pset p, last, new;
+    pcover F1;
+    pcube *Flist;
+    pset_family f_table, table;
+    int i;
+
+    n += cube.first_part[cube.output];
+
+    /* save cubes in this output, and remove the output variable */
+    F1 = new_cover(F->count);
+    foreach_set(F, last, p)
+	if (is_in_set(p, n)) {
+	    new = GETSET(F1, F1->count++);
+	    set_or(new, p, cube.var_mask[cube.output]);
+	    PUTSIZE(new, SIZE(p));
+	    SET(new, REDUND);
+	}
+
+    /* Find ways (sop form) to fail to cover output indexed by n */
+    Flist = cube2list(F1, D);
+    table = sf_new(10, Rp_size);
+    foreach_set(F1, last, p) {
+	set_fill(Rp_start, Rp_size);
+	set_remove(Rp_start, SIZE(p));
+	table = sf_append(table, fcube_is_covered(Flist, p));
+	RESET(p, REDUND);
+    }
+    set_fill(Rp_start, Rp_size);
+    foreach_set(table, last, p) {
+	set_diff(p, Rp_start, p);
+    }
+
+    /* complement this to get possible ways to cover the function */
+    for(i = 0; i < Rp_size; i++) {
+	if (! is_in_set(select, i)) {
+	    p = set_new(Rp_size);
+	    set_insert(p, i);
+	    table = sf_addset(table, p);
+	    set_free(p);
+	}
+    }
+    f_table = unate_compl(table);
+
+    /* what a pain, but we need bitwise complement of this */
+    set_fill(Rp_start, Rp_size);
+    foreach_set(f_table, last, p) {
+	set_diff(p, Rp_start, p);
+    }
+
+    free_cubelist(Flist);
+    sf_free(F1);
+    return f_table;
+}
+#endif
+
+/*
+ *  Take a PLA (ON-set, OFF-set and DC-set) and create the
+ *  "double-phase characteristic function" which is merely a new
+ *  function which has twice as many outputs and realizes both the
+ *  function and the complement.
+ *
+ *  The cube structure is assumed to represent the PLA upon entering.
+ *  It will be modified to represent the double-phase function upon
+ *  exit.
+ *
+ *  Only the outputs numbered starting with "first_output" are
+ *  duplicated in the output part
+ */
+
+void output_phase_setup(PLA, first_output)
+INOUT pPLA PLA;
+int first_output;
+{
+    pcover F, R, D;
+    pcube mask, mask1, last;
+    int first_part, offset;
+    bool save;
+    register pcube p, pr, pf;
+    register int i, last_part;
+
+    if (cube.output == -1)
+	fatal("output_phase_setup: must have an output");
+
+    F = PLA->F;
+    D = PLA->D;
+    R = PLA->R;
+    first_part = cube.first_part[cube.output] + first_output;
+    last_part = cube.last_part[cube.output];
+    offset = cube.part_size[cube.output] - first_output;
+
+    /* Change the output size, setup the cube structure */
+    setdown_cube();
+    cube.part_size[cube.output] += offset;
+    cube_setup();
+
+    /* Create a mask to select that part of the cube which isn't changing */
+    mask = set_save(cube.fullset);
+    for(i = first_part; i < cube.size; i++)
+	set_remove(mask, i);
+    mask1 = set_save(mask);
+    for(i = cube.first_part[cube.output]; i < first_part; i++) {
+	set_remove(mask1, i);
+    }
+
+    PLA->F = new_cover(F->count + R->count);
+    PLA->R = new_cover(F->count + R->count);
+    PLA->D = new_cover(D->count);
+
+    foreach_set(F, last, p) {
+	pf = GETSET(PLA->F, (PLA->F)->count++);
+	pr = GETSET(PLA->R, (PLA->R)->count++);
+	INLINEset_and(pf, mask, p);
+	INLINEset_and(pr, mask1, p);
+	for(i = first_part; i <= last_part; i++)
+	    if (is_in_set(p, i))
+		set_insert(pf, i);
+	save = FALSE;
+	for(i = first_part; i <= last_part; i++)
+	    if (is_in_set(p, i))
+		save = TRUE, set_insert(pr, i+offset);
+	if (! save) PLA->R->count--;
+    }
+
+    foreach_set(R, last, p) {
+	pf = GETSET(PLA->F, (PLA->F)->count++);
+	pr = GETSET(PLA->R, (PLA->R)->count++);
+	INLINEset_and(pf, mask1, p);
+	INLINEset_and(pr, mask, p);
+	save = FALSE;
+	for(i = first_part; i <= last_part; i++)
+	    if (is_in_set(p, i))
+		save = TRUE, set_insert(pf, i+offset);
+	if (! save) PLA->F->count--;
+	for(i = first_part; i <= last_part; i++)
+	    if (is_in_set(p, i))
+		set_insert(pr, i);
+    }
+
+    foreach_set(D, last, p) {
+	pf = GETSET(PLA->D, (PLA->D)->count++);
+	INLINEset_and(pf, mask, p);
+	for(i = first_part; i <= last_part; i++)
+	    if (is_in_set(p, i)) {
+		set_insert(pf, i);
+		set_insert(pf, i+offset);
+	    }
+    }
+
+    free_cover(F);
+    free_cover(D);
+    free_cover(R);
+    set_free(mask);
+    set_free(mask1);
+}
+
+/*
+ *  set_phase -- given a "cube" which describes which phases of the output
+ *  are to be implemented, compute the appropriate on-set and off-set
+ */
+pPLA set_phase(PLA)
+INOUT pPLA PLA;
+{
+    pcover F1, R1;
+    register pcube last, p, outmask;
+    register pcube temp=cube.temp[0], phase=PLA->phase, phase1=cube.temp[1];
+
+    outmask = cube.var_mask[cube.num_vars - 1];
+    set_diff(phase1, outmask, phase);
+    set_or(phase1, set_diff(temp, cube.fullset, outmask), phase1);
+    F1 = new_cover((PLA->F)->count + (PLA->R)->count);
+    R1 = new_cover((PLA->F)->count + (PLA->R)->count);
+
+    foreach_set(PLA->F, last, p) {
+	if (! setp_disjoint(set_and(temp, p, phase), outmask))
+	    set_copy(GETSET(F1, F1->count++), temp);
+	if (! setp_disjoint(set_and(temp, p, phase1), outmask))
+	    set_copy(GETSET(R1, R1->count++), temp);
+    }
+    foreach_set(PLA->R, last, p) {
+	if (! setp_disjoint(set_and(temp, p, phase), outmask))
+	    set_copy(GETSET(R1, R1->count++), temp);
+	if (! setp_disjoint(set_and(temp, p, phase1), outmask))
+	    set_copy(GETSET(F1, F1->count++), temp);
+    }
+    free_cover(PLA->F);
+    free_cover(PLA->R);
+    PLA->F = F1;
+    PLA->R = R1;
+    return PLA;
+}
+
+#define POW2(x)		(1 << (x))
+
+void opoall(PLA, first_output, last_output, opo_strategy)
+pPLA PLA;
+int first_output, last_output;
+int opo_strategy;
+{
+    pcover F, D, R, best_F, best_D, best_R;
+    int i, j, ind, num;
+    pcube bestphase;
+
+    opo_exact = opo_strategy;
+
+    if (PLA->phase != NULL) {
+	set_free(PLA->phase);
+    }
+
+    bestphase = set_save(cube.fullset);
+    best_F = sf_save(PLA->F);
+    best_D = sf_save(PLA->D);
+    best_R = sf_save(PLA->R);
+
+    for(i = 0; i < POW2(last_output - first_output + 1); i++) {
+
+	/* save the initial PLA covers */
+	F = sf_save(PLA->F);
+	D = sf_save(PLA->D);
+	R = sf_save(PLA->R);
+
+	/* compute the phase cube for this iteration */
+	PLA->phase = set_save(cube.fullset);
+	num = i;
+	for(j = last_output; j >= first_output; j--) {
+	    if (num % 2 == 0) {
+		ind = cube.first_part[cube.output] + j;
+		set_remove(PLA->phase, ind);
+	    }
+	    num /= 2;
+	}
+
+	/* set the phase and minimize */
+	(void) set_phase(PLA);
+	printf("# phase is %s\n", pc1(PLA->phase));
+	summary = TRUE;
+	minimize(PLA);
+
+	/* see if this is the best so far */
+	if (PLA->F->count < best_F->count) {
+	    /* save new best solution */
+	    set_copy(bestphase, PLA->phase);
+	    sf_free(best_F);
+	    sf_free(best_D);
+	    sf_free(best_R);
+	    best_F = PLA->F;
+	    best_D = PLA->D;
+	    best_R = PLA->R;
+	} else {
+	    /* throw away the solution */
+	    free_cover(PLA->F);
+	    free_cover(PLA->D);
+	    free_cover(PLA->R);
+	}
+	set_free(PLA->phase);
+
+	/* restore the initial PLA covers */
+	PLA->F = F;
+	PLA->D = D;
+	PLA->R = R;
+    }
+
+    /* one more minimization to restore the best answer */
+    PLA->phase = bestphase;
+    sf_free(PLA->F);
+    sf_free(PLA->D);
+    sf_free(PLA->R);
+    PLA->F = best_F;
+    PLA->D = best_D;
+    PLA->R = best_R;
+}
+
+static void minimize(PLA)
+pPLA PLA;
+{
+    if (opo_exact) {
+	EXEC_S(PLA->F = minimize_exact(PLA->F,PLA->D,PLA->R,1), "EXACT", PLA->F);
+    } else {
+	EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), "ESPRESSO  ",PLA->F);
+    }
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/pair.c b/abc-build/src/misc/espresso/pair.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/pair.c
@@ -0,0 +1,685 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+void set_pair(PLA)
+pPLA PLA;
+{
+    set_pair1(PLA, TRUE);
+}
+
+void set_pair1(PLA, adjust_labels)
+pPLA PLA;
+bool adjust_labels;
+{
+    int i, var, *paired, newvar;
+    int old_num_vars, old_num_binary_vars, old_size, old_mv_start;
+    int *new_part_size, new_num_vars, new_num_binary_vars, new_mv_start;
+    ppair pair = PLA->pair;
+    char scratch[1000], **oldlabel, *var1, *var1bar, *var2, *var2bar;
+
+    if (adjust_labels)
+	makeup_labels(PLA);
+
+    /* Check the pair structure for valid entries and see which binary
+	variables are left unpaired
+    */
+    paired = ALLOC(bool, cube.num_binary_vars);
+    for(var = 0; var < cube.num_binary_vars; var++)
+	paired[var] = FALSE;
+    for(i = 0; i < pair->cnt; i++)
+	if ((pair->var1[i] > 0 && pair->var1[i] <= cube.num_binary_vars) &&
+	     (pair->var2[i] > 0 && pair->var2[i] <= cube.num_binary_vars)) {
+	    paired[pair->var1[i]-1] = TRUE;
+	    paired[pair->var2[i]-1] = TRUE;
+	} else
+	    fatal("can only pair binary-valued variables");
+
+    PLA->F = delvar(pairvar(PLA->F, pair), paired);
+    PLA->R = delvar(pairvar(PLA->R, pair), paired);
+    PLA->D = delvar(pairvar(PLA->D, pair), paired);
+
+    /* Now painfully adjust the cube size */
+    old_size = cube.size;
+    old_num_vars = cube.num_vars;
+    old_num_binary_vars = cube.num_binary_vars;
+    old_mv_start = cube.first_part[cube.num_binary_vars];
+    /* Create the new cube.part_size vector and setup the cube structure */
+    new_num_binary_vars = 0;
+    for(var = 0; var < old_num_binary_vars; var++)
+	new_num_binary_vars += (paired[var] == FALSE);
+    new_num_vars = new_num_binary_vars + pair->cnt;
+    new_num_vars += old_num_vars - old_num_binary_vars;
+    new_part_size = ALLOC(int, new_num_vars);
+    for(var = 0; var < pair->cnt; var++)
+	new_part_size[new_num_binary_vars + var] = 4;
+    for(var = 0; var < old_num_vars - old_num_binary_vars; var++)
+	new_part_size[new_num_binary_vars + pair->cnt + var] =
+	    cube.part_size[old_num_binary_vars + var];
+    setdown_cube();
+    FREE(cube.part_size);
+    cube.num_vars = new_num_vars;
+    cube.num_binary_vars = new_num_binary_vars;
+    cube.part_size = new_part_size;
+    cube_setup();
+
+    /* hack with the labels to get them correct */
+    if (adjust_labels) {
+	oldlabel = PLA->label;
+	PLA->label = ALLOC(char *, cube.size);
+	for(var = 0; var < pair->cnt; var++) {
+	    newvar = cube.num_binary_vars*2 + var*4;
+	    var1 = oldlabel[ (pair->var1[var]-1) * 2 + 1];
+	    var2 = oldlabel[ (pair->var2[var]-1) * 2 + 1];
+	    var1bar = oldlabel[ (pair->var1[var]-1) * 2];
+	    var2bar = oldlabel[ (pair->var2[var]-1) * 2];
+	    (void) sprintf(scratch, "%s+%s", var1bar, var2bar);
+	    PLA->label[newvar] = util_strsav(scratch);
+	    (void) sprintf(scratch, "%s+%s", var1bar, var2);
+	    PLA->label[newvar+1] = util_strsav(scratch);
+	    (void) sprintf(scratch, "%s+%s", var1, var2bar);
+	    PLA->label[newvar+2] = util_strsav(scratch);
+	    (void) sprintf(scratch, "%s+%s", var1, var2);
+	    PLA->label[newvar+3] = util_strsav(scratch);
+	}
+	/* Copy the old labels for the unpaired binary vars */
+	i = 0;
+	for(var = 0; var < old_num_binary_vars; var++) {
+	    if (paired[var] == FALSE) {
+		PLA->label[2*i] = oldlabel[2*var];
+		PLA->label[2*i+1] = oldlabel[2*var+1];
+		oldlabel[2*var] = oldlabel[2*var+1] = (char *) NULL;
+		i++;
+	    }
+	}
+	/* Copy the old labels for the remaining unpaired vars */
+	new_mv_start = cube.num_binary_vars*2 + pair->cnt*4;
+	for(i = old_mv_start; i < old_size; i++) {
+	    PLA->label[new_mv_start + i - old_mv_start] = oldlabel[i];
+	    oldlabel[i] = (char *) NULL;
+	}
+	/* free remaining entries in oldlabel */
+	for(i = 0; i < old_size; i++)
+	    if (oldlabel[i] != (char *) NULL)
+		FREE(oldlabel[i]);
+	FREE(oldlabel);
+    }
+
+    /* the paired variables should not be sparse (cf. mv_reduce/raise_in)*/
+    for(var = 0; var < pair->cnt; var++)
+	cube.sparse[cube.num_binary_vars + var] = 0;
+    FREE(paired);
+}
+
+pcover pairvar(A, pair)
+pcover A;
+ppair pair;
+{
+    register pcube last, p;
+    register int val, p1, p2, b1, b0;
+    int insert_col, pairnum;
+
+    insert_col = cube.first_part[cube.num_vars - 1];
+
+    /* stretch the cover matrix to make room for the paired variables */
+    A = sf_delcol(A, insert_col, -4*pair->cnt);
+
+    /* compute the paired values */
+    foreach_set(A, last, p) {
+	for(pairnum = 0; pairnum < pair->cnt; pairnum++) {
+	    p1 = cube.first_part[pair->var1[pairnum] - 1];
+	    p2 = cube.first_part[pair->var2[pairnum] - 1];
+	    b1 = is_in_set(p, p2+1);
+	    b0 = is_in_set(p, p2);
+	    val = insert_col + pairnum * 4;
+	    if (/* a0 */ is_in_set(p, p1)) {
+		if (b0)
+		    set_insert(p, val + 3);
+		if (b1)
+		    set_insert(p, val + 2);
+	    }
+	    if (/* a1 */ is_in_set(p, p1+1)) {
+		if (b0)
+		    set_insert(p, val + 1);
+		if (b1)
+		    set_insert(p, val);
+	    }
+	}
+    }
+    return A;
+}
+
+
+/* delvar -- delete variables from A, minimize the number of column shifts */
+pcover delvar(A, paired)
+pcover A;
+bool paired[];
+{
+    bool run;
+    int first_run = 0; // Suppress "might be used uninitialized"
+    int run_length, var, offset = 0;
+
+    run = FALSE; run_length = 0;
+    for(var = 0; var < cube.num_binary_vars; var++)
+	if (paired[var])
+	    if (run)
+		run_length += cube.part_size[var];
+	    else {
+		run = TRUE;
+		first_run = cube.first_part[var];
+		run_length = cube.part_size[var];
+	    }
+	else
+	    if (run) {
+		A = sf_delcol(A, first_run-offset, run_length);
+		run = FALSE;
+		offset += run_length;
+	    }
+    if (run)
+	A = sf_delcol(A, first_run-offset, run_length);
+    return A;
+}
+
+/*
+    find_optimal_pairing -- find which binary variables should be paired
+    to maximally reduce the number of terms
+
+    This is essentially the technique outlined by T. Sasao in the
+    Trans. on Comp., Oct 1984.  We estimate the cost of pairing each
+    pair individually using 1 of 4 strategies: (1) algebraic division
+    of F by the pair (exactly T. Sasao technique); (2) strong division
+    of F by the paired variables (using REDUCE/EXPAND/ IRREDUNDANT from
+    espresso); (3) full minimization using espresso; (4) exact
+    minimization.  These are in order of both increasing accuracy and
+    increasing difficulty (!)
+
+    Once the n squared pairs have been evaluated, T. Sasao proposes a
+    graph covering of nodes by disjoint edges.  For now, I solve this
+    problem exhaustively (complexity = (n-1)*(n-3)*...*3*1 for n
+    variables when n is even).  Note that solving this problem exactly
+    is the same as evaluating the cost function for all possible
+    pairings.
+
+			       n       pairs
+
+			     1, 2           1
+			     3, 4           3
+			     5, 6          15
+			     7, 8         105
+			     9,10         945
+			    11,12      10,395
+			    13,14     135,135
+			    15,16   2,027,025
+			    17,18  34,459,425
+			    19,20 654,729,075
+*/
+void find_optimal_pairing(PLA, strategy)
+pPLA PLA;
+int strategy;
+{
+    int i, j, **cost_array;
+
+    cost_array = find_pairing_cost(PLA, strategy);
+
+    if (summary) {
+	printf("    ");
+	for(i = 0; i < cube.num_binary_vars; i++)
+	    printf("%3d ", i+1);
+	printf("\n");
+	for(i = 0; i < cube.num_binary_vars; i++) {
+	    printf("%3d ", i+1);
+	    for(j = 0; j < cube.num_binary_vars; j++)
+		printf("%3d ", cost_array[i][j]);
+	    printf("\n");
+	}
+    }
+
+    if (cube.num_binary_vars <= 14) {
+	PLA->pair = pair_best_cost(cost_array);
+    } else {
+	(void) greedy_best_cost(cost_array, &(PLA->pair));
+    }
+    printf("# ");
+    print_pair(PLA->pair);
+	
+    for(i = 0; i < cube.num_binary_vars; i++)
+	FREE(cost_array[i]);
+    FREE(cost_array);
+
+    set_pair(PLA);
+    EXEC_S(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO  ",PLA->F);
+}
+
+int **find_pairing_cost(PLA, strategy)
+pPLA PLA;
+int strategy;
+{
+    int var1, var2, **cost_array;
+    int i, j;
+    int xnum_binary_vars = 0, xnum_vars = 0, *xpart_size = NULL, cost = 0; // Suppress "might be used uninitialized"
+    pcover T;
+    pcover Fsave = NULL, Dsave = NULL, Rsave = NULL; // Suppress "might be used uninitialized"
+    pset mask;
+/*    char *s;*/
+
+    /* data is returned in the cost array */
+    cost_array = ALLOC(int *, cube.num_binary_vars);
+    for(i = 0; i < cube.num_binary_vars; i++)
+	cost_array[i] = ALLOC(int, cube.num_binary_vars);
+    for(i = 0; i < cube.num_binary_vars; i++)
+	for(j = 0; j < cube.num_binary_vars; j++)
+	    cost_array[i][j] = 0;
+
+    /* Setup the pair structure for pairing variables together */
+    PLA->pair = pair_new(1);
+    PLA->pair->cnt = 1;
+
+    for(var1 = 0; var1 < cube.num_binary_vars-1; var1++) {
+	for(var2 = var1+1; var2 < cube.num_binary_vars; var2++) {
+	    /* if anything but simple strategy, perform setup */
+	    if (strategy > 0) {
+		/* save the original covers */
+		Fsave = sf_save(PLA->F);
+		Dsave = sf_save(PLA->D);
+		Rsave = sf_save(PLA->R);
+
+		/* save the original cube structure */
+		xnum_binary_vars = cube.num_binary_vars;
+		xnum_vars = cube.num_vars;
+		xpart_size = ALLOC(int, cube.num_vars);
+		for(i = 0; i < cube.num_vars; i++)
+		    xpart_size[i] = cube.part_size[i];
+
+		/* pair two variables together */
+		PLA->pair->var1[0] = var1 + 1;
+		PLA->pair->var2[0] = var2 + 1;
+		set_pair1(PLA, /* adjust_labels */ FALSE);
+	    }
+
+
+	    /* decide how to best estimate worth of this pairing */
+	    switch(strategy) {
+		case 3:
+		    /*s = "exact minimization";*/
+		    PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1);
+		    cost = Fsave->count - PLA->F->count;
+		    break;
+		case 2:
+		    /*s = "full minimization";*/
+		    PLA->F = espresso(PLA->F, PLA->D, PLA->R);
+		    cost = Fsave->count - PLA->F->count;
+		    break;
+		case 1:
+		    /*s = "strong division";*/
+		    PLA->F = reduce(PLA->F, PLA->D);
+		    PLA->F = expand(PLA->F, PLA->R, FALSE);
+		    PLA->F = irredundant(PLA->F, PLA->D);
+		    cost = Fsave->count - PLA->F->count;
+		    break;
+		case 0:
+		    /*s = "weak division";*/
+		    mask = new_cube();
+		    set_or(mask, cube.var_mask[var1], cube.var_mask[var2]);
+		    T = dist_merge(sf_save(PLA->F), mask);
+		    cost = PLA->F->count - T->count;
+		    sf_free(T);
+		    set_free(mask);
+	    }
+
+	    cost_array[var1][var2] = cost;
+
+	    if (strategy > 0) {
+		/* restore the original cube structure -- free the new ones */
+		setdown_cube();
+		FREE(cube.part_size);
+		cube.num_binary_vars = xnum_binary_vars;
+		cube.num_vars = xnum_vars;
+		cube.part_size = xpart_size;
+		cube_setup();
+
+		/* restore the original cover(s) -- free the new ones */
+		sf_free(PLA->F);
+		sf_free(PLA->D);
+		sf_free(PLA->R);
+		PLA->F = Fsave;
+		PLA->D = Dsave;
+		PLA->R = Rsave;
+	    }
+	}
+    }
+
+    pair_free(PLA->pair);
+    PLA->pair = NULL;
+    return cost_array;
+}
+
+static int best_cost;
+static int **cost_array;
+static ppair best_pair;
+static pset best_phase;
+static pPLA global_PLA;
+static pcover best_F, best_D, best_R;
+static int pair_minim_strategy;
+
+
+void print_pair(pair)
+ppair pair;
+{
+    int i;
+
+    printf("pair is");
+    for(i = 0; i < pair->cnt; i++)
+	printf (" (%d %d)", pair->var1[i], pair->var2[i]);
+    printf("\n");
+}
+
+
+int greedy_best_cost(cost_array_local, pair_p)
+int **cost_array_local;
+ppair *pair_p;
+{
+    int i, j;
+    int besti = 0, bestj = 0;
+    int maxcost, total_cost;
+    pset cand;
+    ppair pair;
+
+    pair = pair_new(cube.num_binary_vars);
+    cand = set_full(cube.num_binary_vars);
+    total_cost = 0;
+
+    while (set_ord(cand) >= 2) {
+	maxcost = -1;
+	for(i = 0; i < cube.num_binary_vars; i++) {
+	    if (is_in_set(cand, i)) {
+		for(j = i+1; j < cube.num_binary_vars; j++) {
+		    if (is_in_set(cand, j)) {
+			if (cost_array_local[i][j] > maxcost) {
+			    maxcost = cost_array_local[i][j];
+			    besti = i;
+			    bestj = j;
+			}
+		    }
+		}
+	    }
+	}
+	pair->var1[pair->cnt] = besti+1;
+	pair->var2[pair->cnt] = bestj+1;
+	pair->cnt++;
+	set_remove(cand, besti);
+	set_remove(cand, bestj);
+	total_cost += maxcost;
+    }
+    set_free(cand);
+    *pair_p = pair;
+    return total_cost;
+}
+
+
+ppair pair_best_cost(cost_array_local)
+int **cost_array_local;
+{
+    ppair pair;
+    pset candidate;
+
+    best_cost = -1;
+    best_pair = NULL;
+    cost_array = cost_array_local;
+
+    pair = pair_new(cube.num_binary_vars);
+    candidate = set_full(cube.num_binary_vars);
+    generate_all_pairs(pair, cube.num_binary_vars, candidate, find_best_cost);
+    pair_free(pair);
+    set_free(candidate);
+    return best_pair;
+}
+
+
+void find_best_cost(pair)
+register ppair pair;
+{
+    register int i, cost;
+
+    cost = 0;
+    for(i = 0; i < pair->cnt; i++)
+	cost += cost_array[pair->var1[i]-1][pair->var2[i]-1];
+    if (cost > best_cost) {
+	best_cost = cost;
+	best_pair = pair_save(pair, pair->cnt);
+    }
+    if ((debug & MINCOV) && trace) {
+	printf("cost is %d ", cost);
+	print_pair(pair);
+    }
+}
+
+/*
+    pair_all: brute-force approach to try all possible pairings
+
+    pair_strategy is:
+	2) for espresso
+	3) for minimize_exact
+	4) for phase assignment
+*/
+
+void pair_all(PLA, pair_strategy)
+pPLA PLA;
+int pair_strategy;
+{
+    ppair pair;
+    pset candidate;
+
+    global_PLA = PLA;
+    pair_minim_strategy = pair_strategy;
+    best_cost = PLA->F->count + 1;
+    best_pair = NULL;
+    best_phase = NULL;
+    best_F = best_D = best_R = NULL;
+    pair = pair_new(cube.num_binary_vars);
+    candidate = set_fill(set_new(cube.num_binary_vars), cube.num_binary_vars);
+
+    generate_all_pairs(pair, cube.num_binary_vars, candidate, minimize_pair);
+
+    pair_free(pair);
+    set_free(candidate);
+
+    PLA->pair = best_pair;
+    PLA->phase = best_phase;
+/* not really necessary
+    if (phase != NULL)
+	(void) set_phase(PLA->phase);
+*/
+    set_pair(PLA);
+    printf("# ");
+    print_pair(PLA->pair);
+
+    sf_free(PLA->F);
+    sf_free(PLA->D);
+    sf_free(PLA->R);
+    PLA->F = best_F;
+    PLA->D = best_D;
+    PLA->R = best_R;
+}
+
+
+/*
+ *  minimize_pair -- called as each pair is generated
+ */
+void minimize_pair(pair)
+ppair pair;
+{
+    pcover Fsave, Dsave, Rsave;
+    int i, xnum_binary_vars, xnum_vars, *xpart_size;
+
+    /* save the original covers */
+    Fsave = sf_save(global_PLA->F);
+    Dsave = sf_save(global_PLA->D);
+    Rsave = sf_save(global_PLA->R);
+
+    /* save the original cube structure */
+    xnum_binary_vars = cube.num_binary_vars;
+    xnum_vars = cube.num_vars;
+    xpart_size = ALLOC(int, cube.num_vars);
+    for(i = 0; i < cube.num_vars; i++)
+	xpart_size[i] = cube.part_size[i];
+
+    /* setup the paired variables */
+    global_PLA->pair = pair;
+    set_pair1(global_PLA, /* adjust_labels */ FALSE);
+
+    /* call the minimizer */
+    if (summary)
+	print_pair(pair);
+    switch(pair_minim_strategy) {
+	case 2:
+	    EXEC_S(phase_assignment(global_PLA,0), "OPO       ", global_PLA->F);
+	    if (summary)
+		printf("# phase is %s\n", pc1(global_PLA->phase));
+	    break;
+	case 1:
+	    EXEC_S(global_PLA->F = minimize_exact(global_PLA->F, global_PLA->D,
+		global_PLA->R, 1), "EXACT     ", global_PLA->F);
+	    break;
+	case 0:
+	    EXEC_S(global_PLA->F = espresso(global_PLA->F, global_PLA->D,
+		global_PLA->R), "ESPRESSO  ", global_PLA->F);
+	    break;
+	default:
+	    break;
+    }
+
+    /* see if we have a new best solution */
+    if (global_PLA->F->count < best_cost) {
+	best_cost = global_PLA->F->count;
+	best_pair = pair_save(pair, pair->cnt);
+	best_phase = global_PLA->phase!=NULL?set_save(global_PLA->phase):NULL;
+	if (best_F != NULL) sf_free(best_F);
+	if (best_D != NULL) sf_free(best_D);
+	if (best_R != NULL) sf_free(best_R);
+	best_F = sf_save(global_PLA->F);
+	best_D = sf_save(global_PLA->D);
+	best_R = sf_save(global_PLA->R);
+    }
+
+    /* restore the original cube structure -- free the new ones */
+    setdown_cube();
+    FREE(cube.part_size);
+    cube.num_binary_vars = xnum_binary_vars;
+    cube.num_vars = xnum_vars;
+    cube.part_size = xpart_size;
+    cube_setup();
+
+    /* restore the original cover(s) -- free the new ones */
+    sf_free(global_PLA->F);
+    sf_free(global_PLA->D);
+    sf_free(global_PLA->R);
+    global_PLA->F = Fsave;
+    global_PLA->D = Dsave;
+    global_PLA->R = Rsave;
+    global_PLA->pair = NULL;
+    global_PLA->phase = NULL;
+}
+
+void generate_all_pairs(pair, n, candidate, action)
+ppair pair;
+int n;
+pset candidate;
+int (*action)();
+{
+    int i, j;
+    pset recur_candidate;
+    ppair recur_pair;
+
+    if (set_ord(candidate) < 2) {
+	(*action)(pair);
+	return;
+    }
+
+    recur_pair = pair_save(pair, n);
+    recur_candidate = set_save(candidate);
+
+    /* Find first variable still in the candidate set */
+    for(i = 0; i < n; i++)
+	if (is_in_set(candidate, i))
+	    break;
+
+    /* Try all pairs of i with other variables */
+    for(j = i+1; j < n; j++)
+	if (is_in_set(candidate, j)) {
+	    /* pair (i j) -- remove from candidate set for future pairings */
+	    set_remove(recur_candidate, i);
+	    set_remove(recur_candidate, j);
+
+	    /* add to the pair array */
+	    recur_pair->var1[recur_pair->cnt] = i+1;
+	    recur_pair->var2[recur_pair->cnt] = j+1;
+	    recur_pair->cnt++;
+
+	    /* recur looking for the end ... */
+	    generate_all_pairs(recur_pair, n, recur_candidate, action);
+
+	    /* now break this pair, and restore candidate set */
+	    recur_pair->cnt--;
+	    set_insert(recur_candidate, i);
+	    set_insert(recur_candidate, j);
+	}
+
+    /* if odd, generate all pairs which do NOT include i */
+    if ((set_ord(candidate) % 2) == 1) {
+	set_remove(recur_candidate, i);
+	generate_all_pairs(recur_pair, n, recur_candidate, action);
+    }
+
+    pair_free(recur_pair);
+    set_free(recur_candidate);
+}
+
+ppair pair_new(n)
+register int n;
+{
+    register ppair pair1;
+
+    pair1 = ALLOC(pair_t, 1);
+    pair1->cnt = 0;
+    pair1->var1 = ALLOC(int, n);
+    pair1->var2 = ALLOC(int, n);
+    return pair1;
+}
+
+
+ppair pair_save(pair, n)
+register ppair pair;
+register int n;
+{
+    register int k;
+    register ppair pair1;
+
+    pair1 = pair_new(n);
+    pair1->cnt = pair->cnt;
+    for(k = 0; k < pair->cnt; k++) {
+	pair1->var1[k] = pair->var1[k];
+	pair1->var2[k] = pair->var2[k];
+    }
+    return pair1;
+}
+
+
+void pair_free(pair)
+register ppair pair;
+{
+    FREE(pair->var1);
+    FREE(pair->var2);
+    FREE(pair);
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/part.c b/abc-build/src/misc/espresso/part.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/part.c
@@ -0,0 +1,127 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+static int visit_col();
+
+static void
+copy_row(A, prow)
+register sm_matrix *A;
+register sm_row *prow;
+{
+    register sm_element *p;
+
+    for(p = prow->first_col; p != 0; p = p->next_col) {
+	(void) sm_insert(A, p->row_num, p->col_num);
+    }
+}
+
+
+static int
+visit_row(A, prow, rows_visited, cols_visited)
+sm_matrix *A;
+sm_row *prow;
+int *rows_visited;
+int *cols_visited;
+{
+    sm_element *p;
+    sm_col *pcol;
+
+    if (! prow->flag) {
+	prow->flag = 1;
+	(*rows_visited)++;
+	if (*rows_visited == A->nrows) {
+	    return 1;
+	}
+	for(p = prow->first_col; p != 0; p = p->next_col) {
+	    pcol = sm_get_col(A, p->col_num);
+	    if (! pcol->flag) {
+		if (visit_col(A, pcol, rows_visited, cols_visited)) {
+		    return 1;
+		}
+	    }
+	}
+    }
+    return 0;
+}
+
+
+static int
+visit_col(A, pcol, rows_visited, cols_visited)
+sm_matrix *A;
+sm_col *pcol;
+int *rows_visited;
+int *cols_visited;
+{
+    sm_element *p;
+    sm_row *prow;
+
+    if (! pcol->flag) {
+	pcol->flag = 1;
+	(*cols_visited)++;
+	if (*cols_visited == A->ncols) {
+	    return 1;
+	}
+	for(p = pcol->first_row; p != 0; p = p->next_row) {
+	    prow = sm_get_row(A, p->row_num);
+	    if (! prow->flag) {
+		if (visit_row(A, prow, rows_visited, cols_visited)) {
+		    return 1;
+		}
+	    }
+	}
+    }
+    return 0;
+}
+
+int
+sm_block_partition(A, L, R)
+sm_matrix *A;
+sm_matrix **L, **R;
+{
+    int cols_visited, rows_visited;
+    register sm_row *prow;
+    register sm_col *pcol;
+
+    /* Avoid the trivial case */
+    if (A->nrows == 0) {
+	return 0;
+    }
+
+    /* Reset the visited flags for each row and column */
+    for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+	prow->flag = 0;
+    }
+    for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+	pcol->flag = 0;
+    }
+
+    cols_visited = rows_visited = 0;
+    if (visit_row(A, A->first_row, &rows_visited, &cols_visited)) {
+	/* we found all of the rows */
+	return 0;
+    } else {
+	*L = sm_alloc();
+	*R = sm_alloc();
+	for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+	    if (prow->flag) {
+		copy_row(*L, prow);
+	    } else {
+		copy_row(*R, prow);
+	    }
+	}
+	return 1;
+    }
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/primes.c b/abc-build/src/misc/espresso/primes.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/primes.c
@@ -0,0 +1,175 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+static bool primes_consensus_special_cases();
+static pcover primes_consensus_merge();
+static pcover and_with_cofactor(); 
+
+
+/* primes_consensus -- generate primes using consensus */
+pcover primes_consensus(T)
+pcube *T;			/* T will be disposed of */
+{
+    register pcube cl, cr;
+    register int best;
+    pcover Tnew, Tl, Tr;
+
+    if (primes_consensus_special_cases(T, &Tnew) == MAYBE) {
+	cl = new_cube();
+	cr = new_cube();
+	best = binate_split_select(T, cl, cr, COMPL);
+
+	Tl = primes_consensus(scofactor(T, cl, best));
+	Tr = primes_consensus(scofactor(T, cr, best));
+	Tnew = primes_consensus_merge(Tl, Tr, cl, cr);
+
+	free_cube(cl);
+	free_cube(cr);
+	free_cubelist(T);
+    }
+
+    return Tnew;
+}
+
+static bool 
+primes_consensus_special_cases(T, Tnew)
+pcube *T;			/* will be disposed if answer is determined */
+pcover *Tnew;			/* returned only if answer determined */
+{
+    register pcube *T1, p, ceil, cof=T[0];
+    pcube last;
+    pcover A;
+
+    /* Check for no cubes in the cover */
+    if (T[2] == NULL) {
+	*Tnew = new_cover(0);
+	free_cubelist(T);
+	return TRUE;
+    }
+
+    /* Check for only a single cube in the cover */
+    if (T[3] == NULL) {
+	*Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2]));
+	free_cubelist(T);
+	return TRUE;
+    }
+
+    /* Check for a row of all 1's (implies function is a tautology) */
+    for(T1 = T+2; (p = *T1++) != NULL; ) {
+	if (full_row(p, cof)) {
+	    *Tnew = sf_addset(new_cover(1), cube.fullset);
+	    free_cubelist(T);
+	    return TRUE;
+	}
+    }
+
+    /* Check for a column of all 0's which can be factored out */
+    ceil = set_save(cof);
+    for(T1 = T+2; (p = *T1++) != NULL; ) {
+	INLINEset_or(ceil, ceil, p);
+    }
+    if (! setp_equal(ceil, cube.fullset)) {
+	p = new_cube();
+	(void) set_diff(p, cube.fullset, ceil);
+	(void) set_or(cof, cof, p);
+	free_cube(p);
+
+	A = primes_consensus(T);
+	foreach_set(A, last, p) {
+	    INLINEset_and(p, p, ceil);
+	}
+	*Tnew = A;
+	set_free(ceil);
+	return TRUE;
+    }
+    set_free(ceil);
+
+    /* Collect column counts, determine unate variables, etc. */
+    massive_count(T);
+
+    /* If single active variable not factored out above, then tautology ! */
+    if (cdata.vars_active == 1) {
+	*Tnew = sf_addset(new_cover(1), cube.fullset);
+	free_cubelist(T);
+	return TRUE;
+
+    /* Check for unate cover */
+    } else if (cdata.vars_unate == cdata.vars_active) {
+	A = cubeunlist(T);
+	*Tnew = sf_contain(A);
+	free_cubelist(T);
+	return TRUE;
+
+    /* Not much we can do about it */
+    } else {
+	return MAYBE;
+    }
+}
+
+static pcover 
+primes_consensus_merge(Tl, Tr, cl, cr)
+pcover Tl, Tr;
+pcube cl, cr;
+{
+    register pcube pl, pr, lastl, lastr, pt;
+    pcover T, Tsave;
+
+    Tl = and_with_cofactor(Tl, cl);
+    Tr = and_with_cofactor(Tr, cr);
+
+    T = sf_new(500, Tl->sf_size);
+    pt = T->data;
+    Tsave = sf_contain(sf_join(Tl, Tr));
+
+    foreach_set(Tl, lastl, pl) {
+	foreach_set(Tr, lastr, pr) {
+	    if (cdist01(pl, pr) == 1) {
+		consensus(pt, pl, pr);
+		if (++T->count >= T->capacity) {
+		    Tsave = sf_union(Tsave, sf_contain(T));
+		    T = sf_new(500, Tl->sf_size);
+		    pt = T->data;
+		} else {
+		    pt += T->wsize;
+		}
+	    }
+	}
+    }
+    free_cover(Tl);
+    free_cover(Tr);
+
+    Tsave = sf_union(Tsave, sf_contain(T));
+    return Tsave;
+}
+
+
+static pcover
+and_with_cofactor(A, cof)
+pset_family A;
+register pset cof;
+{
+    register pset last, p;
+
+    foreach_set(A, last, p) {
+	INLINEset_and(p, p, cof);
+	if (cdist(p, cube.fullset) > 0) {
+	    RESET(p, ACTIVE);
+	} else {
+	    SET(p, ACTIVE);
+	}
+    }
+    return sf_inactive(A);
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/reduce.c b/abc-build/src/misc/espresso/reduce.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/reduce.c
@@ -0,0 +1,263 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+    module: reduce.c
+    purpose: Perform the Espresso-II reduction step
+
+    Reduction is a technique used to explore larger regions of the
+    optimization space.  We replace each cube of F with a smaller
+    cube while still maintaining a cover of the same logic function.
+*/
+
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+static bool toggle = TRUE;
+
+
+/*
+    reduce -- replace each cube in F with its reduction
+
+    The reduction of a cube is the smallest cube contained in the cube
+    which can replace the cube in the original cover without changing
+    the cover.  This is equivalent to the super cube of all of the
+    essential points in the cube.  This can be computed directly.
+
+    The problem is that the order in which the cubes are reduced can
+    greatly affect the final result.  We alternate between two ordering
+    strategies:
+
+	(1) Order the cubes in ascending order of distance from the
+	largest cube breaking ties by ordering cubes of equal distance
+	in descending order of size (sort_reduce)
+
+	(2) Order the cubes in descending order of the inner-product of
+	the cube and the column sums (mini_sort)
+
+    The real workhorse of this section is the routine SCCC which is
+    used to find the Smallest Cube Containing the Complement of a cover.
+    Reduction as proposed by Espresso-II takes a cube and computes its
+    maximal reduction as the intersection between the cube and the
+    smallest cube containing the complement of (F u D - {c}) cofactored
+    against c.
+
+    As usual, the unate-recursive paradigm is used to compute SCCC.
+    The SCCC of a unate cover is trivial to compute, and thus we perform
+    Shannon Cofactor expansion attempting to drive the cover to be unate
+    as fast as possible.
+*/
+
+pcover reduce(F, D)
+INOUT pcover F;
+IN pcover D;
+{
+    register pcube last, p, cunder, *FD;
+
+    /* Order the cubes */
+    if (use_random_order)
+	F = random_order(F);
+    else {
+	F = toggle ? sort_reduce(F) : mini_sort(F, descend);
+	toggle = ! toggle;
+    }
+
+    /* Try to reduce each cube */
+    FD = cube2list(F, D);
+    foreach_set(F, last, p) {
+	cunder = reduce_cube(FD, p);		/* reduce the cube */
+	if (setp_equal(cunder, p)) {            /* see if it actually did */
+	    SET(p, ACTIVE);	/* cube remains active */
+	    SET(p, PRIME);	/* cube remains prime ? */
+	} else {
+	    if (debug & REDUCE) {
+		printf("REDUCE: %s to %s %s\n",
+		    pc1(p), pc2(cunder), print_time(ptime()));
+	    }
+	    set_copy(p, cunder);                /* save reduced version */
+	    RESET(p, PRIME);                    /* cube is no longer prime */
+	    if (setp_empty(cunder))
+		RESET(p, ACTIVE);               /* if null, kill the cube */
+	    else
+		SET(p, ACTIVE);                 /* cube is active */
+	}
+	free_cube(cunder);
+    }
+    free_cubelist(FD);
+
+    /* Delete any cubes of F which reduced to the empty cube */
+    return sf_inactive(F);
+}
+
+/* reduce_cube -- find the maximal reduction of a cube */
+pcube reduce_cube(FD, p)
+IN pcube *FD, p;
+{
+    pcube cunder;
+
+    cunder = sccc(cofactor(FD, p));
+    return set_and(cunder, cunder, p);
+}
+
+
+/* sccc -- find Smallest Cube Containing the Complement of a cover */
+pcube sccc(T)
+INOUT pcube *T;         /* T will be disposed of */
+{
+    pcube r;
+    register pcube cl, cr;
+    register int best;
+    static int sccc_level = 0;
+
+    if (debug & REDUCE1) {
+	debug_print(T, "SCCC", sccc_level++);
+    }
+
+    if (sccc_special_cases(T, &r) == MAYBE) {
+	cl = new_cube();
+	cr = new_cube();
+	best = binate_split_select(T, cl, cr, REDUCE1);
+	r = sccc_merge(sccc(scofactor(T, cl, best)),
+		       sccc(scofactor(T, cr, best)), cl, cr);
+	free_cubelist(T);
+    }
+
+    if (debug & REDUCE1)
+	printf("SCCC[%d]: result is %s\n", --sccc_level, pc1(r));
+    return r;
+}
+
+
+pcube sccc_merge(left, right, cl, cr)
+INOUT register pcube left, right;       /* will be disposed of ... */
+INOUT register pcube cl, cr;            /* will be disposed of ... */
+{
+    INLINEset_and(left, left, cl);
+    INLINEset_and(right, right, cr);
+    INLINEset_or(left, left, right);
+    free_cube(right);
+    free_cube(cl);
+    free_cube(cr);
+    return left;
+}
+
+
+/*
+    sccc_cube -- find the smallest cube containing the complement of a cube
+
+    By DeMorgan's law and the fact that the smallest cube containing a
+    cover is the "or" of the positional cubes, it is simple to see that
+    the SCCC is the universe if the cube has more than two active
+    variables.  If there is only a single active variable, then the
+    SCCC is merely the bitwise complement of the cube in that
+    variable.  A last special case is no active variables, in which
+    case the SCCC is empty.
+
+    This is "anded" with the incoming cube result.
+*/
+pcube sccc_cube(result, p)
+register pcube result, p;
+{
+    register pcube temp=cube.temp[0], mask;
+    int var;
+
+    if ((var = cactive(p)) >= 0) {
+	mask = cube.var_mask[var];
+	INLINEset_xor(temp, p, mask);
+	INLINEset_and(result, result, temp);
+    }
+    return result;
+}
+
+/*
+ *   sccc_special_cases -- check the special cases for sccc
+ */
+
+bool sccc_special_cases(T, result)
+INOUT pcube *T;                 /* will be disposed if answer is determined */
+OUT pcube *result;              /* returned only if answer determined */
+{
+    register pcube *T1, p, temp = cube.temp[1], ceil, cof = T[0];
+    pcube *A, *B;
+
+    /* empty cover => complement is universe => SCCC is universe */
+    if (T[2] == NULL) {
+	*result = set_save(cube.fullset);
+	free_cubelist(T);
+	return TRUE;
+    }
+
+    /* row of 1's => complement is empty => SCCC is empty */
+    for(T1 = T+2; (p = *T1++) != NULL; ) {
+	if (full_row(p, cof)) {
+	    *result = new_cube();
+	    free_cubelist(T);
+	    return TRUE;
+	}
+    }
+
+    /* Collect column counts, determine unate variables, etc. */
+    massive_count(T);
+
+    /* If cover is unate (or single cube), apply simple rules to find SCCCU */
+    if (cdata.vars_unate == cdata.vars_active || T[3] == NULL) {
+	*result = set_save(cube.fullset);
+	for(T1 = T+2; (p = *T1++) != NULL; ) {
+	    (void) sccc_cube(*result, set_or(temp, p, cof));
+	}
+	free_cubelist(T);
+	return TRUE;
+    }
+
+    /* Check for column of 0's (which can be easily factored( */
+    ceil = set_save(cof);
+    for(T1 = T+2; (p = *T1++) != NULL; ) {
+	INLINEset_or(ceil, ceil, p);
+    }
+    if (! setp_equal(ceil, cube.fullset)) {
+	*result = sccc_cube(set_save(cube.fullset), ceil);
+	if (setp_equal(*result, cube.fullset)) {
+	    free_cube(ceil);
+	} else {
+	    *result = sccc_merge(sccc(cofactor(T,ceil)),
+			 set_save(cube.fullset), ceil, *result);
+	}
+	free_cubelist(T);
+	return TRUE;
+    }
+    free_cube(ceil);
+
+    /* Single active column at this point => tautology => SCCC is empty */
+    if (cdata.vars_active == 1) {
+	*result = new_cube();
+	free_cubelist(T);
+	return TRUE;
+    }
+
+    /* Check for components */
+    if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T)/2) {
+	if (cubelist_partition(T, &A, &B, debug & REDUCE1) == 0) {
+	    return MAYBE;
+	} else {
+	    free_cubelist(T);
+	    *result = sccc(A);
+	    ceil = sccc(B);
+	    (void) set_and(*result, *result, ceil);
+	    set_free(ceil);
+	    return TRUE;
+	}
+    }
+
+    /* Not much we can do about it */
+    return MAYBE;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/rows.c b/abc-build/src/misc/espresso/rows.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/rows.c
@@ -0,0 +1,319 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+#include "sparse_int.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+/*
+ *  allocate a new row vector 
+ */
+sm_row *
+sm_row_alloc()
+{
+    register sm_row *prow;
+
+#ifdef FAST_AND_LOOSE
+    if (sm_row_freelist == NIL(sm_row)) {
+	prow = ALLOC(sm_row, 1);
+    } else {
+	prow = sm_row_freelist;
+	sm_row_freelist = prow->next_row;
+    }
+#else
+    prow = ALLOC(sm_row, 1);
+#endif
+
+    prow->row_num = 0;
+    prow->length = 0;
+    prow->first_col = prow->last_col = NIL(sm_element);
+    prow->next_row = prow->prev_row = NIL(sm_row);
+    prow->flag = 0;
+    prow->user_word = NIL(char);		/* for our user ... */
+    return prow;
+}
+
+
+/*
+ *  free a row vector -- for FAST_AND_LOOSE, this is real cheap for rows;
+ *  however, freeing a column must still walk down the column discarding
+ *  the elements one-by-one; that is the only use for the extra '-DCOLS'
+ *  compile flag ...
+ */
+void
+sm_row_free(prow)
+register sm_row *prow;
+{
+#if defined(FAST_AND_LOOSE) && ! defined(COLS)
+    if (prow->first_col != NIL(sm_element)) {
+	/* Add the linked list of row items to the free list */
+	prow->last_col->next_col = sm_element_freelist;
+	sm_element_freelist = prow->first_col;
+    }
+
+    /* Add the row to the free list of rows */
+    prow->next_row = sm_row_freelist;
+    sm_row_freelist = prow;
+#else
+    register sm_element *p, *pnext;
+
+    for(p = prow->first_col; p != 0; p = pnext) {
+	pnext = p->next_col;
+	sm_element_free(p);
+    }
+    FREE(prow);
+#endif
+}
+
+
+/*
+ *  duplicate an existing row
+ */
+sm_row *
+sm_row_dup(prow)
+register sm_row *prow;
+{
+    register sm_row *pnew;
+    register sm_element *p;
+
+    pnew = sm_row_alloc();
+    for(p = prow->first_col; p != 0; p = p->next_col) {
+	(void) sm_row_insert(pnew, p->col_num);
+    }
+    return pnew;
+}
+
+
+/*
+ *  insert an element into a row vector 
+ */
+sm_element *
+sm_row_insert(prow, col)
+register sm_row *prow;
+register int col;
+{
+    register sm_element *test, *element;
+
+    /* get a new item, save its address */
+    sm_element_alloc(element);
+    test = element;
+    sorted_insert(sm_element, prow->first_col, prow->last_col, prow->length, 
+		    next_col, prev_col, col_num, col, test);
+
+    /* if item was not used, free it */
+    if (element != test) {
+	sm_element_free(element);
+    }
+
+    /* either way, return the current new value */
+    return test;
+}
+
+
+/*
+ *  remove an element from a row vector 
+ */
+void
+sm_row_remove(prow, col)
+register sm_row *prow;
+register int col;
+{
+    register sm_element *p;
+
+    for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col)
+	;
+    if (p != 0 && p->col_num == col) {
+	dll_unlink(p, prow->first_col, prow->last_col, 
+			    next_col, prev_col, prow->length);
+	sm_element_free(p);
+    }
+}
+
+
+/*
+ *  find an element (if it is in the row vector)
+ */
+sm_element *
+sm_row_find(prow, col)
+sm_row *prow;
+int col;
+{
+    register sm_element *p;
+
+    for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col)
+	;
+    if (p != 0 && p->col_num == col) {
+	return p;
+    } else {
+	return NIL(sm_element);
+    }
+}
+
+/*
+ *  return 1 if row p2 contains row p1; 0 otherwise
+ */
+int 
+sm_row_contains(p1, p2)
+sm_row *p1, *p2;
+{
+    register sm_element *q1, *q2;
+
+    q1 = p1->first_col;
+    q2 = p2->first_col;
+    while (q1 != 0) {
+	if (q2 == 0 || q1->col_num < q2->col_num) {
+	    return 0;
+	} else if (q1->col_num == q2->col_num) {
+	    q1 = q1->next_col;
+	    q2 = q2->next_col;
+	} else {
+	    q2 = q2->next_col;
+	}
+    }
+    return 1;
+}
+
+
+/*
+ *  return 1 if row p1 and row p2 share an element in common
+ */
+int 
+sm_row_intersects(p1, p2)
+sm_row *p1, *p2;
+{
+    register sm_element *q1, *q2;
+
+    q1 = p1->first_col;
+    q2 = p2->first_col;
+    if (q1 == 0 || q2 == 0) return 0;
+    for(;;) {
+	if (q1->col_num < q2->col_num) {
+	    if ((q1 = q1->next_col) == 0) {
+		return 0;
+	    }
+	} else if (q1->col_num > q2->col_num) {
+	    if ((q2 = q2->next_col) == 0) {
+		return 0;
+	    }
+	} else {
+	    return 1;
+	}
+    }
+}
+
+
+/*
+ *  compare two rows, lexical ordering
+ */
+int 
+sm_row_compare(p1, p2)
+sm_row *p1, *p2;
+{
+    register sm_element *q1, *q2;
+
+    q1 = p1->first_col;
+    q2 = p2->first_col;
+    while(q1 != 0 && q2 != 0) {
+	if (q1->col_num != q2->col_num) {
+	    return q1->col_num - q2->col_num;
+	}
+	q1 = q1->next_col;
+	q2 = q2->next_col;
+    }
+
+    if (q1 != 0) {
+	return 1;
+    } else if (q2 != 0) {
+	return -1;
+    } else {
+	return 0;
+    }
+}
+
+
+/*
+ *  return the intersection
+ */
+sm_row *
+sm_row_and(p1, p2)
+sm_row *p1, *p2;
+{
+    register sm_element *q1, *q2;
+    register sm_row *result;
+
+    result = sm_row_alloc();
+    q1 = p1->first_col;
+    q2 = p2->first_col;
+    if (q1 == 0 || q2 == 0) return result;
+    for(;;) {
+	if (q1->col_num < q2->col_num) {
+	    if ((q1 = q1->next_col) == 0) {
+		return result;
+	    }
+	} else if (q1->col_num > q2->col_num) {
+	    if ((q2 = q2->next_col) == 0) {
+		return result;
+	    }
+	} else {
+	    (void) sm_row_insert(result, q1->col_num);
+	    if ((q1 = q1->next_col) == 0) {
+		return result;
+	    }
+	    if ((q2 = q2->next_col) == 0) {
+		return result;
+	    }
+	}
+    }
+}
+
+int 
+sm_row_hash(prow, modulus)
+sm_row *prow;
+int modulus;
+{
+    register int sum;
+    register sm_element *p;
+
+    sum = 0;
+    for(p = prow->first_col; p != 0; p = p->next_col) {
+	sum = (sum*17 + p->col_num) % modulus;
+    }
+    return sum;
+}
+
+/*
+ *  remove an element from a row vector (given a pointer to the element) 
+ */
+void
+sm_row_remove_element(prow, p)
+register sm_row *prow;
+register sm_element *p;
+{
+    dll_unlink(p, prow->first_col, prow->last_col, 
+			next_col, prev_col, prow->length);
+    sm_element_free(p);
+}
+
+
+void
+sm_row_print(fp, prow)
+FILE *fp;
+sm_row *prow;
+{
+    sm_element *p;
+
+    for(p = prow->first_col; p != 0; p = p->next_col) {
+	(void) fprintf(fp, " %d", p->col_num);
+    }
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/set.c b/abc-build/src/misc/espresso/set.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/set.c
@@ -0,0 +1,825 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ *   set.c -- routines for maniuplating sets and set families
+ */
+
+/* LINTLIBRARY */
+
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+static pset_family set_family_garbage = NULL;
+
+static void intcpy(d, s, n)
+register unsigned int *d, *s;
+register long n;
+{
+    register int i;
+    for(i = 0; i < n; i++) {
+	*d++ = *s++;
+    }
+}
+
+
+/* bit_index -- find first bit (from LSB) in a word (MSB=bit n, LSB=bit 0) */
+int bit_index(a)
+register unsigned int a;
+{
+    register int i;
+    if (a == 0)
+	return -1;
+    for(i = 0; (a & 1) == 0; a >>= 1, i++)
+	;
+    return i;
+}
+
+
+/* set_ord -- count number of elements in a set */
+int set_ord(a)
+register pset a;
+{
+    register int i, sum = 0;
+    register unsigned int val;
+    for(i = LOOP(a); i > 0; i--)
+	if ((val = a[i]) != 0)
+	    sum += count_ones(val);
+    return sum;
+}
+
+/* set_dist -- distance between two sets (# elements in common) */
+int set_dist(a, b)
+register pset a, b;
+{
+    register int i, sum = 0;
+    register unsigned int val;
+    for(i = LOOP(a); i > 0; i--)
+	if ((val = a[i] & b[i]) != 0)
+	    sum += count_ones(val);
+    return sum;
+}
+
+/* set_clear -- make "r" the empty set of "size" elements */
+pset set_clear(r, size)
+register pset r;
+int size;
+{
+    register int i = LOOPINIT(size);
+    *r = i; do r[i] = 0; while (--i > 0);
+    return r;
+}
+
+/* set_fill -- make "r" the universal set of "size" elements */
+pset set_fill(r, size)
+register pset r;
+register int size;
+{
+    register int i = LOOPINIT(size);
+    *r = i;
+    r[i] = ~ (unsigned) 0;
+    r[i] >>= i * BPI - size;
+    while (--i > 0)
+	r[i] = ~ (unsigned) 0;
+    return r;
+}
+
+/* set_copy -- copy set a into set r */
+pset set_copy(r, a)
+register pset r, a;
+{
+    register int i = LOOPCOPY(a);
+    do r[i] = a[i]; while (--i >= 0);
+    return r;
+}
+
+/* set_and -- compute intersection of sets "a" and "b" */
+pset set_and(r, a, b)
+register pset r, a, b;
+{
+    register int i = LOOP(a);
+    PUTLOOP(r,i); do r[i] = a[i] & b[i]; while (--i > 0);
+    return r;
+}
+
+/* set_or -- compute union of sets "a" and "b" */
+pset set_or(r, a, b)
+register pset r, a, b;
+{
+    register int i = LOOP(a);
+    PUTLOOP(r,i); do r[i] = a[i] | b[i]; while (--i > 0);
+    return r;
+}
+
+/* set_diff -- compute difference of sets "a" and "b" */
+pset set_diff(r, a, b)
+register pset r, a, b;
+{
+    register int i = LOOP(a);
+    PUTLOOP(r,i); do r[i] = a[i] & ~b[i]; while (--i > 0);
+    return r;
+}
+
+/* set_xor -- compute exclusive-or of sets "a" and "b" */
+pset set_xor(r, a, b)
+register pset r, a, b;
+{
+    register int i = LOOP(a);
+#ifdef IBM_WATC
+    PUTLOOP(r,i); do r[i] = (a[i]&~b[i]) | (~a[i]&b[i]); while (--i > 0);
+#else
+    PUTLOOP(r,i); do r[i] = a[i] ^ b[i]; while (--i > 0);
+#endif
+    return r;
+}
+
+/* set_merge -- compute "a" & "mask" | "b" & ~ "mask" */
+pset set_merge(r, a, b, mask)
+register pset r, a, b, mask;
+{
+    register int i = LOOP(a);
+    PUTLOOP(r,i); do r[i] = (a[i]&mask[i]) | (b[i]&~mask[i]); while (--i > 0);
+    return r;
+}
+
+/* set_andp -- compute intersection of sets "a" and "b" , TRUE if nonempty */
+bool set_andp(r, a, b)
+register pset r, a, b;
+{
+    register int i = LOOP(a);
+    register unsigned int x = 0;
+    PUTLOOP(r,i); do {r[i] = a[i] & b[i]; x |= r[i];} while (--i > 0);
+    return x != 0;
+}
+
+/* set_orp -- compute union of sets "a" and "b" , TRUE if nonempty */
+bool set_orp(r, a, b)
+register pset r, a, b;
+{
+    register int i = LOOP(a);
+    register unsigned int x = 0;
+    PUTLOOP(r,i); do {r[i] = a[i] | b[i]; x |= r[i];} while (--i > 0);
+    return x != 0;
+}
+
+/* setp_empty -- check if the set "a" is empty */
+bool setp_empty(a)
+register pset a;
+{
+    register int i = LOOP(a);
+    do if (a[i]) return FALSE; while (--i > 0);
+    return TRUE;
+}
+
+/* setp_full -- check if the set "a" is the full set of "size" elements */
+bool setp_full(a, size)
+register pset a;
+register int size;
+{
+    register int i = LOOP(a);
+    register unsigned int test;
+    test = ~ (unsigned) 0;
+    test >>= i * BPI - size;
+    if (a[i] != test)
+	return FALSE;
+    while (--i > 0)
+	if (a[i] != (~(unsigned) 0))
+	    return FALSE;
+    return TRUE;
+}
+
+/* setp_equal -- check if the set "a" equals set "b" */
+bool setp_equal(a, b)
+register pset a, b;
+{
+    register int i = LOOP(a);
+    do if (a[i] != b[i]) return FALSE; while (--i > 0);
+    return TRUE;
+}
+
+/* setp_disjoint -- check if intersection of "a" and "b" is empty */
+bool setp_disjoint(a, b)
+register pset a, b;
+{
+    register int i = LOOP(a);
+    do if (a[i] & b[i]) return FALSE; while (--i > 0);
+    return TRUE;
+}
+
+/* setp_implies -- check if "a" implies "b" ("b" contains "a") */
+bool setp_implies(a, b)
+register pset a, b;
+{
+    register int i = LOOP(a);
+    do if (a[i] & ~b[i]) return FALSE; while (--i > 0);
+    return TRUE;
+}
+
+/* sf_or -- form the "or" of all sets in a set family */
+pset sf_or(A)
+pset_family A;
+{
+    register pset or, last, p;
+
+    or = set_new(A->sf_size);
+    foreach_set(A, last, p)
+	INLINEset_or(or, or, p);
+    return or;
+}
+
+/* sf_and -- form the "and" of all sets in a set family */
+pset sf_and(A)
+pset_family A;
+{
+    register pset and, last, p;
+
+    and = set_fill(set_new(A->sf_size), A->sf_size);
+    foreach_set(A, last, p)
+	INLINEset_and(and, and, p);
+    return and;
+}
+
+/* sf_active -- make all members of the set family active */
+pset_family sf_active(A)
+pset_family A;
+{
+    register pset p, last;
+    foreach_set(A, last, p) {
+	SET(p, ACTIVE);
+    }
+    A->active_count = A->count;
+    return A;
+}
+
+
+/* sf_inactive -- remove all inactive cubes in a set family */
+pset_family sf_inactive(A)
+pset_family A;
+{
+    register pset p, last, pdest;
+
+    pdest = A->data;
+    foreach_set(A, last, p) {
+	if (TESTP(p, ACTIVE)) {
+	    if (pdest != p) {
+		INLINEset_copy(pdest, p);
+	    }
+	    pdest += A->wsize;
+	} else {
+	    A->count--;
+	}
+    }
+    return A;
+}
+
+
+/* sf_copy -- copy a set family */
+pset_family sf_copy(R, A)
+pset_family R, A;
+{
+    R->sf_size = A->sf_size;
+    R->wsize = A->wsize;
+/*R->capacity = A->count;*/
+/*R->data = REALLOC(unsigned int, R->data, (long) R->capacity * R->wsize);*/
+    R->count = A->count;
+    R->active_count = A->active_count;
+    intcpy(R->data, A->data, (long) A->wsize * A->count);
+    return R;
+}
+
+
+/* sf_join -- join A and B into a single set_family */
+pset_family sf_join(A, B)
+pset_family A, B;
+{
+    pset_family R;
+    long asize = A->count * A->wsize;
+    long bsize = B->count * B->wsize;
+
+    if (A->sf_size != B->sf_size) fatal("sf_join: sf_size mismatch");
+    R = sf_new(A->count + B->count, A->sf_size);
+    R->count = A->count + B->count;
+    R->active_count = A->active_count + B->active_count;
+    intcpy(R->data, A->data, asize);
+    intcpy(R->data + asize, B->data, bsize);
+    return R;
+}
+
+
+/* sf_append -- append the sets of B to the end of A, and dispose of B */
+pset_family sf_append(A, B)
+pset_family A, B;
+{
+    long asize = A->count * A->wsize;
+    long bsize = B->count * B->wsize;
+
+    if (A->sf_size != B->sf_size) fatal("sf_append: sf_size mismatch");
+    A->capacity = A->count + B->count;
+    A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize);
+    intcpy(A->data + asize, B->data, bsize);
+    A->count += B->count;
+    A->active_count += B->active_count;
+    sf_free(B);
+    return A;
+}
+
+
+/* sf_new -- allocate "num" sets of "size" elements each */
+pset_family sf_new(num, size)
+int num, size;
+{
+    pset_family A;
+    if (set_family_garbage == NULL) {
+	A = ALLOC(set_family_t, 1);
+    } else {
+	A = set_family_garbage;
+	set_family_garbage = A->next;
+    }
+    A->sf_size = size;
+    A->wsize = SET_SIZE(size);
+    A->capacity = num;
+    A->data = ALLOC(unsigned int, (long) A->capacity * A->wsize);
+    A->count = 0;
+    A->active_count = 0;
+    return A;
+}
+
+
+/* sf_save -- create a duplicate copy of a set family */
+pset_family sf_save(A)
+register pset_family A;
+{
+    return sf_copy(sf_new(A->count, A->sf_size), A);
+}
+
+
+/* sf_free -- free the storage allocated for a set family */
+void sf_free(A)
+pset_family A;
+{
+    FREE(A->data);
+    A->next = set_family_garbage;
+    set_family_garbage = A;
+}
+
+
+/* sf_cleanup -- free all of the set families from the garbage list */
+void sf_cleanup()
+{
+    register pset_family p, pnext;
+    for(p = set_family_garbage; p != (pset_family) NULL; p = pnext) {
+	pnext = p->next;
+	FREE(p);
+    }
+    set_family_garbage = (pset_family) NULL;
+}
+
+
+/* sf_addset -- add a set to the end of a set family */
+pset_family sf_addset(A, s)
+pset_family A;
+pset s;
+{
+    register pset p;
+
+    if (A->count >= A->capacity) {
+	A->capacity = A->capacity + A->capacity/2 + 1;
+	A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize);
+    }
+    p = GETSET(A, A->count++);
+    INLINEset_copy(p, s);
+    return A;
+}
+
+/* sf_delset -- delete a set from a set family */
+void sf_delset(A, i)
+pset_family A;
+int i;
+{   (void) set_copy(GETSET(A,i), GETSET(A, --A->count));}
+
+/* sf_print -- print a set_family as a set (list the element numbers) */
+void sf_print(A)
+pset_family A;
+{
+    char *ps1();
+    register pset p;
+    register int i;
+    foreachi_set(A, i, p)
+	printf("A[%d] = %s\n", i, ps1(p));
+}
+
+/* sf_bm_print -- print a set_family as a bit-matrix */
+void sf_bm_print(A)
+pset_family A;
+{
+    char *pbv1();
+    register pset p;
+    register int i;
+    foreachi_set(A, i, p)
+	printf("[%4d] %s\n", i, pbv1(p, A->sf_size));
+}
+
+
+/* sf_write -- output a set family in an unintelligable manner */
+void sf_write(fp, A)
+FILE *fp;
+pset_family A;
+{
+    register pset p, last;
+    (void) fprintf(fp, "%d %d\n", A->count, A->sf_size);
+    foreach_set(A, last, p)
+	set_write(fp, p);
+    (void) fflush(fp);
+}
+
+
+/* sf_read -- read a set family written by sf_write */
+pset_family sf_read(fp)
+FILE *fp;
+{
+    int i, j;
+    register pset p, last;
+    pset_family A;
+
+    (void) fscanf(fp, "%d %d\n", &i, &j);
+    A = sf_new(i, j);
+    A->count = i;
+    foreach_set(A, last, p) {
+	(void) fscanf(fp, "%x", p);
+	for(j = 1; j <= LOOP(p); j++)
+	    (void) fscanf(fp, "%x", p+j);
+    }
+    return A;
+}
+
+
+/* set_write -- output a set in an unintelligable manner */
+void set_write(fp, a)
+register FILE *fp;
+register pset a;
+{
+    register int n = LOOP(a), j;
+
+    for(j = 0; j <= n; j++) {
+	(void) fprintf(fp, "%x ", a[j]);
+	if ((j+1) % 8 == 0 && j != n)
+	    (void) fprintf(fp, "\n\t");
+    }
+    (void) fprintf(fp, "\n");
+}
+
+
+/* sf_bm_read -- read a set family written by sf_bm_print (almost) */
+pset_family sf_bm_read(fp)
+FILE *fp;
+{
+    int i, j, rows, cols;
+    register pset pdest;
+    pset_family A;
+
+    (void) fscanf(fp, "%d %d\n", &rows, &cols);
+    A = sf_new(rows, cols);
+    for(i = 0; i < rows; i++) {
+	pdest = GETSET(A, A->count++);
+	(void) set_clear(pdest, A->sf_size);
+	for(j = 0; j < cols; j++) {
+	    switch(getc(fp)) {
+		case '0':
+		    break;
+		case '1':
+		    set_insert(pdest, j);
+		    break;
+		default:
+		    fatal("Error reading set family");
+	    }
+	}
+	if (getc(fp) != '\n') {
+	    fatal("Error reading set family (at end of line)");
+	}
+    }
+    return A;
+}
+
+
+
+/* ps1 -- convert a set into a printable string */
+#define largest_string 120
+static char s1[largest_string];
+char *ps1(a)
+register pset a;
+{
+    register int i, num, l, len = 0, n = NELEM(a);
+    char temp[20];
+    bool first = TRUE;
+
+    s1[len++] = '[';
+    for(i = 0; i < n; i++)
+	if (is_in_set(a,i)) {
+	    if (! first)
+		s1[len++] = ',';
+	    first = FALSE; num = i;
+	    /* Generate digits (reverse order) */
+	    l = 0; do temp[l++] = num % 10 + '0'; while ((num /= 10) > 0);
+	    /* Copy them back in correct order */
+	    do s1[len++] = temp[--l]; while (l > 0);
+	    if (len > largest_string-15) {
+		s1[len++] = '.'; s1[len++] = '.'; s1[len++] = '.';
+		break;
+	    }
+	}
+
+    s1[len++] = ']';
+    s1[len++] = '\0';
+    return s1;
+}
+
+/* pbv1 -- print bit-vector */
+char *pbv1(s, n)
+pset s;
+int n;
+{
+    register int i;
+    for(i = 0; i < n; i++)
+	s1[i] = is_in_set(s,i) ? '1' : '0';
+    s1[n] = '\0';
+    return s1;
+}
+
+
+/* set_adjcnt -- adjust the counts for a set by "weight" */
+void
+set_adjcnt(a, count, weight)
+register pset a;
+register int *count, weight;
+{
+    register int i, base;
+    register unsigned int val;
+
+    for(i = LOOP(a); i > 0; ) {
+	for(val = a[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) {
+	    if (val & 1) {
+		count[base] += weight;
+	    }
+	}
+    }
+}
+
+
+
+/* sf_count -- perform a column sum over a set family */
+int *sf_count(A)
+pset_family A;
+{
+    register pset p, last;
+    register int i, base, *count;
+    register unsigned int val;
+
+    count = ALLOC(int, A->sf_size);
+    for(i = A->sf_size - 1; i >= 0; i--) {
+	count[i] = 0;
+    }
+
+    foreach_set(A, last, p) {
+	for(i = LOOP(p); i > 0; ) {
+	    for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) {
+		if (val & 1) {
+		    count[base]++;
+		}
+	    }
+	}
+    }
+    return count;
+}
+
+
+/* sf_count_restricted -- perform a column sum over a set family, restricting
+ * to only the columns which are in r; also, the columns are weighted by the
+ * number of elements which are in each row
+ */
+int *sf_count_restricted(A, r)
+pset_family A;
+register pset r;
+{
+    register pset p;
+    register int i, base, *count;
+    register unsigned int val;
+    int weight;
+    pset last;
+
+    count = ALLOC(int, A->sf_size);
+    for(i = A->sf_size - 1; i >= 0; i--) {
+	count[i] = 0;
+    }
+
+    /* Loop for each set */
+    foreach_set(A, last, p) {
+	weight = 1024 / (set_ord(p) - 1);
+	for(i = LOOP(p); i > 0; ) {
+	    for(val=p[i]&r[i], base= --i<<LOGBPI; val!=0; base++, val >>= 1) {
+		if (val & 1) {
+		    count[base] += weight;
+		}
+	    }
+	}
+    }
+    return count;
+}
+
+
+/*
+ *  sf_delc -- delete columns first ... last of A
+ */
+pset_family sf_delc(A, first, last)
+pset_family A;
+int first, last;
+{
+    return sf_delcol(A, first, last-first + 1);
+}
+
+
+/*
+ *  sf_addcol -- add columns to a set family; includes a quick check to see
+ *  if there is already enough room (and hence, can avoid copying)
+ */
+pset_family sf_addcol(A, firstcol, n)
+pset_family A;
+int firstcol, n;
+{
+    int maxsize;
+
+    /* Check if adding columns at the end ... */
+    if (firstcol == A->sf_size) {
+	/* If so, check if there is already enough room */
+	maxsize = BPI * LOOPINIT(A->sf_size);
+	if ((A->sf_size + n) <= maxsize) {
+	    A->sf_size += n;
+	    return A;
+	}
+    }
+    return sf_delcol(A, firstcol, -n);
+}
+
+/*
+ * sf_delcol -- add/delete columns to/from a set family
+ *
+ *  if n > 0 then n columns starting from firstcol are deleted if n < 0
+ *  then n blank columns are inserted starting at firstcol
+ *      (i.e., the first new column number is firstcol)
+ *
+ *  This is done by copying columns in the array which is a relatively
+ *  slow operation.
+ */
+pset_family sf_delcol(A, firstcol, n)
+pset_family A;
+register int firstcol, n;
+{
+    register pset p, last, pdest;
+    register int i;
+    pset_family B;
+
+    B = sf_new(A->count, A->sf_size - n);
+    foreach_set(A, last, p) {
+	pdest = GETSET(B, B->count++);
+	INLINEset_clear(pdest, B->sf_size);
+	for(i = 0; i < firstcol; i++)
+	    if (is_in_set(p, i))
+		set_insert(pdest, i);
+	for(i = n > 0 ? firstcol + n : firstcol; i < A->sf_size; i++)
+	    if (is_in_set(p, i))
+		set_insert(pdest, i - n);
+    }
+    sf_free(A);
+    return B;
+}
+
+
+/*
+ *  sf_copy_col -- copy column "srccol" from "src" to column "dstcol" of "dst"
+ */
+pset_family sf_copy_col(dst, dstcol, src, srccol)
+pset_family dst, src;
+int dstcol, srccol;
+{
+    register pset last, p, pdest;
+    register int word_test, word_set;
+    unsigned int bit_set, bit_test;
+
+    /* CHEAT! form these constants outside the loop */
+    word_test = WHICH_WORD(srccol);
+    bit_test = 1 << WHICH_BIT(srccol);
+    word_set = WHICH_WORD(dstcol);
+    bit_set = 1 << WHICH_BIT(dstcol);
+
+    pdest = dst->data;
+    foreach_set(src, last, p) {
+	if ((p[word_test] & bit_test) != 0)
+	    pdest[word_set] |= bit_set;
+/*
+ *  equivalent code for this is ...
+ *	if (is_in_set(p, srccol)) set_insert(pdest, destcol);
+ */
+	pdest += dst->wsize;
+    }
+    return dst;
+}
+
+
+
+/*
+ *  sf_compress -- delete columns from a matrix
+ */
+pset_family sf_compress(A, c)
+pset_family A;			/* will be freed */
+register pset c;
+{
+    register pset p;
+    register int i, bcol;
+    pset_family B;
+
+    /* create a clean set family for the result */
+    B = sf_new(A->count, set_ord(c));
+    for(i = 0; i < A->count; i++) {
+	p = GETSET(B, B->count++);
+	INLINEset_clear(p, B->sf_size);
+    }
+
+    /* copy each column of A which has a 1 in c */
+    bcol = 0;
+    for(i = 0; i < A->sf_size; i++) {
+	if (is_in_set(c, i)) {
+	    (void) sf_copy_col(B, bcol++, A, i);
+	}
+    }
+    sf_free(A);
+    return B;
+}
+
+
+
+/*
+ *  sf_transpose -- transpose a bit matrix
+ *
+ *  There are trickier ways of doing this, but this works.
+ */
+pset_family sf_transpose(A)
+pset_family A;
+{
+    pset_family B;
+    register pset p;
+    register int i, j;
+
+    B = sf_new(A->sf_size, A->count);
+    B->count = A->sf_size;
+    foreachi_set(B, i, p) {
+	INLINEset_clear(p, B->sf_size);
+    }
+    foreachi_set(A, i, p) {
+	for(j = 0; j < A->sf_size; j++) {
+	    if (is_in_set(p, j)) {
+		set_insert(GETSET(B, j), i);
+	    }
+	}
+    }
+    sf_free(A);
+    return B;
+}
+
+
+/*
+ *   sf_permute -- permute the columns of a set_family
+ *
+ *   permute is an array of integers containing column numbers of A which
+ *   are to be retained.
+ */
+pset_family sf_permute(A, permute, npermute)
+pset_family A;
+register int *permute, npermute;
+{
+    pset_family B;
+    register pset p, last, pdest;
+    register int j;
+
+    B = sf_new(A->count, npermute);
+    B->count = A->count;
+    foreach_set(B, last, p)
+	INLINEset_clear(p, npermute);
+
+    pdest = B->data;
+    foreach_set(A, last, p) {
+	for(j = 0; j < npermute; j++)
+	    if (is_in_set(p, permute[j]))
+		set_insert(pdest, j);
+	pdest += B->wsize;
+    }
+    sf_free(A);
+    return B;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/setc.c b/abc-build/src/misc/espresso/setc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/setc.c
@@ -0,0 +1,488 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+    setc.c -- massive bit-hacking for performing special "cube"-type
+    operations on a set
+
+    The basic trick used for binary valued variables is the following:
+
+    If a[w] and b[w] contain a full word of binary variables, then:
+
+     1) to get the full word of their intersection, we use
+
+	    x = a[w] & b[w];
+
+
+     2) to see if the intersection is null in any variables, we examine
+
+	    x = ~(x | x >> 1) & DISJOINT;
+
+	this will have a single 1 in each binary variable for which
+	the intersection is null.  In particular, if this is zero,
+	then there are no disjoint variables; or, if this is nonzero,
+	then there is at least one disjoint variable.  A "count_ones"
+	over x will tell in how many variables they have an null
+	intersection.
+
+
+     3) to get a mask which selects the disjoint variables, we use
+
+	    (x | x << 1)
+
+	this provides a selector which can be used to see where
+	they have an null intersection
+
+
+    cdist       return distance between two cubes
+    cdist0      return true if two cubes are distance 0 apart
+    cdist01     return distance, or 2 if distance exceeds 1
+    consensus   compute consensus of two cubes distance 1 apart
+    force_lower expand hack (for now), related to consensus
+*/
+
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/* see if the cube has a full row of 1's (with respect to cof) */
+bool full_row(p, cof)
+IN register pcube p, cof;
+{
+    register int i = LOOP(p);
+    do if ((p[i] | cof[i]) != cube.fullset[i]) return FALSE; while (--i > 0);
+    return TRUE;
+}
+
+/*
+    cdist0 -- return TRUE if a and b are distance 0 apart
+*/
+
+bool cdist0(a, b)
+register pcube a, b;
+{
+ {  /* Check binary variables */
+    register int w, last; register unsigned int x;
+    if ((last = cube.inword) != -1) {
+
+	/* Check the partial word of binary variables */
+	x = a[last] & b[last];
+	if (~(x | x >> 1) & cube.inmask)
+	    return FALSE;               /* disjoint in some variable */
+
+	/* Check the full words of binary variables */
+	for(w = 1; w < last; w++) {
+	    x = a[w] & b[w];
+	    if (~(x | x >> 1) & DISJOINT)
+		return FALSE;           /* disjoint in some variable */
+	}
+    }
+ }
+
+ {  /* Check the multiple-valued variables */
+    register int w, var, last; register pcube mask;
+    for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+	mask = cube.var_mask[var]; last = cube.last_word[var];
+	for(w = cube.first_word[var]; w <= last; w++)
+	    if (a[w] & b[w] & mask[w])
+		goto nextvar;
+	return FALSE;           /* disjoint in this variable */
+    nextvar: ;
+    }
+ }
+    return TRUE;
+}
+
+/*
+    cdist01 -- return the "distance" between two cubes (defined as the
+    number of null variables in their intersection).  If the distance
+    exceeds 1, the value 2 is returned.
+*/
+
+int cdist01(a, b)
+register pset a, b;
+{
+    int dist = 0;
+
+ {  /* Check binary variables */
+    register int w, last; register unsigned int x;
+    if ((last = cube.inword) != -1) {
+
+	/* Check the partial word of binary variables */
+	x = a[last] & b[last];
+	if ((x = ~ (x | x >> 1) & cube.inmask))
+	    if ((dist = count_ones(x)) > 1)
+		return 2;
+
+	/* Check the full words of binary variables */
+	for(w = 1; w < last; w++) {
+	    x = a[w] & b[w];
+	    if ((x = ~ (x | x >> 1) & DISJOINT))
+		if (dist == 1 || (dist += count_ones(x)) > 1)
+		    return 2;
+	}
+    }
+ }
+
+ {  /* Check the multiple-valued variables */
+    register int w, var, last; register pcube mask;
+    for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+	mask = cube.var_mask[var]; last = cube.last_word[var];
+	for(w = cube.first_word[var]; w <= last; w++)
+	    if (a[w] & b[w] & mask[w])
+		goto nextvar;
+	if (++dist > 1)
+	    return 2;
+    nextvar: ;
+    }
+ }
+    return dist;
+}
+
+/*
+    cdist -- return the "distance" between two cubes (defined as the
+    number of null variables in their intersection).
+*/
+
+int cdist(a, b)
+register pset a, b;
+{
+    int dist = 0;
+
+ {  /* Check binary variables */
+    register int w, last; register unsigned int x;
+    if ((last = cube.inword) != -1) {
+
+	/* Check the partial word of binary variables */
+	x = a[last] & b[last];
+	if ((x = ~ (x | x >> 1) & cube.inmask))
+	    dist = count_ones(x);
+
+	/* Check the full words of binary variables */
+	for(w = 1; w < last; w++) {
+	    x = a[w] & b[w];
+	    if ((x = ~ (x | x >> 1) & DISJOINT))
+		dist += count_ones(x);
+	}
+    }
+ }
+
+ {  /* Check the multiple-valued variables */
+    register int w, var, last; register pcube mask;
+    for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+	mask = cube.var_mask[var]; last = cube.last_word[var];
+	for(w = cube.first_word[var]; w <= last; w++)
+	    if (a[w] & b[w] & mask[w])
+		goto nextvar;
+	dist++;
+    nextvar: ;
+    }
+ }
+    return dist;
+}
+
+/*
+    force_lower -- Determine which variables of a do not intersect b.
+*/
+
+pset force_lower(xlower, a, b)
+INOUT pset xlower;
+IN register pset a, b;
+{
+
+ {  /* Check binary variables (if any) */
+    register int w, last; register unsigned int x;
+    if ((last = cube.inword) != -1) {
+
+	/* Check the partial word of binary variables */
+	x = a[last] & b[last];
+	if ((x = ~(x | x >> 1) & cube.inmask))
+	    xlower[last] |= (x | (x << 1)) & a[last];
+
+	/* Check the full words of binary variables */
+	for(w = 1; w < last; w++) {
+	    x = a[w] & b[w];
+	    if ((x = ~(x | x >> 1) & DISJOINT))
+		xlower[w] |= (x | (x << 1)) & a[w];
+	}
+    }
+ }
+
+ {  /* Check the multiple-valued variables */
+    register int w, var, last; register pcube mask;
+    for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+	mask = cube.var_mask[var]; last = cube.last_word[var];
+	for(w = cube.first_word[var]; w <= last; w++)
+	    if (a[w] & b[w] & mask[w])
+		goto nextvar;
+	for(w = cube.first_word[var]; w <= last; w++)
+	    xlower[w] |= a[w] & mask[w];
+    nextvar: ;
+    }
+ }
+    return xlower;
+}
+
+/*
+    consensus -- multiple-valued consensus
+
+    Although this looks very messy, the idea is to compute for r the
+    "and" of the cubes a and b for each variable, unless the "and" is
+    null in a variable, in which case the "or" of a and b is computed
+    for this variable.
+
+    Because we don't check how many variables are null in the
+    intersection of a and b, the returned value for r really only
+    represents the consensus when a and b are distance 1 apart.
+*/
+
+void consensus(r, a, b)
+INOUT pcube r;
+IN register pcube a, b;
+{
+    INLINEset_clear(r, cube.size);
+
+ {  /* Check binary variables (if any) */
+    register int w, last; register unsigned int x;
+    if ((last = cube.inword) != -1) {
+
+	/* Check the partial word of binary variables */
+	r[last] = x = a[last] & b[last];
+	if ((x = ~(x | x >> 1) & cube.inmask))
+	    r[last] |= (x | (x << 1)) & (a[last] | b[last]);
+
+	/* Check the full words of binary variables */
+	for(w = 1; w < last; w++) {
+	    r[w] = x = a[w] & b[w];
+	    if ((x = ~(x | x >> 1) & DISJOINT))
+		r[w] |= (x | (x << 1)) & (a[w] | b[w]);
+	}
+    }
+ }
+
+
+ {  /* Check the multiple-valued variables */
+    bool empty; int var; unsigned int x;
+    register int w, last; register pcube mask;
+    for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+	mask = cube.var_mask[var];
+	last = cube.last_word[var];
+	empty = TRUE;
+	for(w = cube.first_word[var]; w <= last; w++)
+	    if ((x = a[w] & b[w] & mask[w]))
+		empty = FALSE, r[w] |= x;
+	if (empty)
+	    for(w = cube.first_word[var]; w <= last; w++)
+		r[w] |= mask[w] & (a[w] | b[w]);
+    }
+ }
+}
+
+/*
+    cactive -- return the index of the single active variable in
+    the cube, or return -1 if there are none or more than 2.
+*/
+
+int cactive(a)
+register pcube a;
+{
+    int active = -1, dist = 0, bit_index();
+
+ {  /* Check binary variables */
+    register int w, last;
+    register unsigned int x;
+    if ((last = cube.inword) != -1) {
+
+	/* Check the partial word of binary variables */
+	x = a[last];
+	if ((x = ~ (x & x >> 1) & cube.inmask)) {
+	    if ((dist = count_ones(x)) > 1)
+		return -1;		/* more than 2 active variables */
+	    active = (last-1)*(BPI/2) + bit_index(x) / 2;
+	}
+
+	/* Check the full words of binary variables */
+	for(w = 1; w < last; w++) {
+	    x = a[w];
+	    if ((x = ~ (x & x >> 1) & DISJOINT)) {
+		if ((dist += count_ones(x)) > 1)
+		    return -1;		/* more than 2 active variables */
+		active = (w-1)*(BPI/2) + bit_index(x) / 2;
+	    }
+	}
+    }
+ }
+
+ {  /* Check the multiple-valued variables */
+    register int w, var, last;
+    register pcube mask;
+    for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+	mask = cube.var_mask[var];
+	last = cube.last_word[var];
+	for(w = cube.first_word[var]; w <= last; w++)
+	    if (mask[w] & ~ a[w]) {
+		if (++dist > 1)
+		    return -1;
+		active = var;
+		break;
+	    }
+    }
+ }
+ return active;
+}
+
+/*
+    ccommon -- return TRUE if a and b are share "active" variables
+    active variables include variables that are empty;
+*/
+
+bool ccommon(a, b, cof)
+register pcube a, b, cof;
+{
+ {  /* Check binary variables */
+    int last;
+    register int w;
+    register unsigned int x, y;
+    if ((last = cube.inword) != -1) {
+
+	/* Check the partial word of binary variables */
+	x = a[last] | cof[last];
+	y = b[last] | cof[last];
+	if (~(x & x>>1) & ~(y & y>>1) & cube.inmask)
+	    return TRUE;
+
+	/* Check the full words of binary variables */
+	for(w = 1; w < last; w++) {
+	    x = a[w] | cof[w];
+	    y = b[w] | cof[w];
+	    if (~(x & x>>1) & ~(y & y>>1) & DISJOINT)
+		return TRUE;
+	}
+    }
+ }
+
+ {  /* Check the multiple-valued variables */
+    int var;
+    register int w, last;
+    register pcube mask;
+    for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+	mask = cube.var_mask[var]; last = cube.last_word[var];
+	/* Check for some part missing from a */
+	for(w = cube.first_word[var]; w <= last; w++)
+	    if (mask[w] & ~a[w] & ~cof[w]) {
+
+		/* If so, check for some part missing from b */
+		for(w = cube.first_word[var]; w <= last; w++)
+		    if (mask[w] & ~b[w] & ~cof[w])
+			return TRUE;            /* both active */
+		break;
+	    }
+    }
+ }
+    return FALSE;
+}
+
+/*
+    These routines compare two sets (cubes) for the qsort() routine and
+    return:
+
+	-1 if set a is to precede set b
+	 0 if set a and set b are equal
+	 1 if set a is to follow set b
+
+    Usually the SIZE field of the set is assumed to contain the size
+    of the set (which will save recomputing the set size during the
+    sort).  For distance-1 merging, the global variable cube.temp[0] is
+    a mask which mask's-out the merging variable.
+*/
+
+/* descend -- comparison for descending sort on set size */
+int descend(a, b)
+pset *a, *b;
+{
+    register pset a1 = *a, b1 = *b;
+    if (SIZE(a1) > SIZE(b1)) return -1;
+    else if (SIZE(a1) < SIZE(b1)) return 1;
+    else {
+	register int i = LOOP(a1);
+	do
+	    if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1;
+	while (--i > 0);
+    }
+    return 0;
+}
+
+/* ascend -- comparison for ascending sort on set size */
+int ascend(a, b)
+pset *a, *b;
+{
+    register pset a1 = *a, b1 = *b;
+    if (SIZE(a1) > SIZE(b1)) return 1;
+    else if (SIZE(a1) < SIZE(b1)) return -1;
+    else {
+	register int i = LOOP(a1);
+	do
+	    if (a1[i] > b1[i]) return 1; else if (a1[i] < b1[i]) return -1;
+	while (--i > 0);
+    }
+    return 0;
+}
+
+
+/* lex_order -- comparison for "lexical" ordering of cubes */
+int lex_order(a, b)
+pset *a, *b;
+{
+    register pset a1 = *a, b1 = *b;
+    register int i = LOOP(a1);
+    do
+	if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1;
+    while (--i > 0);
+    return 0;
+}
+
+
+/* d1_order -- comparison for distance-1 merge routine */
+int d1_order(a, b)
+pset *a, *b;
+{
+    register pset a1 = *a, b1 = *b, c1 = cube.temp[0];
+    register int i = LOOP(a1);
+    register unsigned int x1, x2;
+    do
+	if ((x1 = a1[i] | c1[i]) > (x2 = b1[i] | c1[i])) return -1;
+	else if (x1 < x2) return 1;
+    while (--i > 0);
+    return 0;
+}
+
+
+/* desc1 -- comparison (without indirection) for descending sort */
+/* also has effect of handling NULL pointers,and a NULL pointer has smallest
+order */
+int desc1(a, b)
+register pset a, b;
+{
+    if (a == (pset) NULL)
+	return (b == (pset) NULL) ? 0 : 1;
+    else if (b == (pset) NULL)
+	return -1;
+    if (SIZE(a) > SIZE(b)) return -1;
+    else if (SIZE(a) < SIZE(b)) return 1;
+    else {
+	register int i = LOOP(a);
+	do
+	    if (a[i] > b[i]) return -1; else if (a[i] < b[i]) return 1;
+	while (--i > 0);
+    }
+    return 0;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/sharp.c b/abc-build/src/misc/espresso/sharp.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/sharp.c
@@ -0,0 +1,252 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+    sharp.c -- perform sharp, disjoint sharp, and intersection
+*/
+
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+long start_time;
+
+
+/* cv_sharp -- form the sharp product between two covers */
+pcover cv_sharp(A, B)
+pcover A, B;
+{
+    pcube last, p;
+    pcover T;
+
+    T = new_cover(0);
+    foreach_set(A, last, p)
+	T = sf_union(T, cb_sharp(p, B));
+    return T;
+}
+
+
+/* cb_sharp -- form the sharp product between a cube and a cover */
+pcover cb_sharp(c, T)
+pcube c;
+pcover T;
+{
+    if (T->count == 0) {
+	T = sf_addset(new_cover(1), c);
+    } else {
+	start_time = ptime();
+	T = cb_recur_sharp(c, T, 0, T->count-1, 0);
+    }
+    return T;
+}
+
+
+/* recursive formulation to provide balanced merging */
+pcover cb_recur_sharp(c, T, first, last, level)
+pcube c;
+pcover T;
+int first, last, level;
+{
+    pcover temp, left, right;
+    int middle;
+
+    if (first == last) {
+	temp = sharp(c, GETSET(T, first));
+    } else {
+	middle = (first + last) / 2;
+	left = cb_recur_sharp(c, T, first, middle, level+1);
+	right = cb_recur_sharp(c, T, middle+1, last, level+1);
+	temp = cv_intersect(left, right);
+	if ((debug & SHARP) && level < 4) {
+	    printf("# SHARP[%d]: %4d = %4d x %4d, time = %s\n",
+		level, temp->count, left->count, right->count,
+		print_time(ptime() - start_time));
+	    (void) fflush(stdout);
+	}
+	free_cover(left);
+	free_cover(right);
+    }
+    return temp;
+}
+
+
+/* sharp -- form the sharp product between two cubes */
+pcover sharp(a, b)
+pcube a, b;
+{
+    register int var;
+    register pcube d=cube.temp[0], temp=cube.temp[1], temp1=cube.temp[2];
+    pcover r = new_cover(cube.num_vars);
+
+    if (cdist0(a, b)) {
+	set_diff(d, a, b);
+	for(var = 0; var < cube.num_vars; var++) {
+	    if (! setp_empty(set_and(temp, d, cube.var_mask[var]))) {
+		set_diff(temp1, a, cube.var_mask[var]);
+		set_or(GETSET(r, r->count++), temp, temp1);
+	    }
+	}
+    } else {
+	r = sf_addset(r, a);
+    }
+    return r;
+}
+
+pcover make_disjoint(A)
+pcover A;
+{
+    pcover R, new;
+    register pset last, p;
+
+    R = new_cover(0);
+    foreach_set(A, last, p) {
+	new = cb_dsharp(p, R);
+	R = sf_append(R, new);
+    }
+    return R;
+}
+
+
+/* cv_dsharp -- disjoint-sharp product between two covers */
+pcover cv_dsharp(A, B)
+pcover A, B;
+{
+    register pcube last, p;
+    pcover T;
+
+    T = new_cover(0);
+    foreach_set(A, last, p) {
+	T = sf_union(T, cb_dsharp(p, B));
+    }
+    return T;
+}
+
+
+/* cb1_dsharp -- disjoint-sharp product between a cover and a cube */
+pcover cb1_dsharp(T, c)
+pcover T;
+pcube c;
+{
+    pcube last, p;
+    pcover R;
+
+    R = new_cover(T->count);
+    foreach_set(T, last, p) {
+	R = sf_union(R, dsharp(p, c));
+    }
+    return R;
+}
+
+
+/* cb_dsharp -- disjoint-sharp product between a cube and a cover */
+pcover cb_dsharp(c, T)
+pcube c;
+pcover T;
+{
+    pcube last, p;
+    pcover Y, Y1;
+
+    if (T->count == 0) {
+	Y = sf_addset(new_cover(1), c);
+    } else {
+	Y = new_cover(T->count);
+	set_copy(GETSET(Y,Y->count++), c);
+	foreach_set(T, last, p) {
+	    Y1 = cb1_dsharp(Y, p);
+	    free_cover(Y);
+	    Y = Y1;
+	}
+    }
+    return Y;
+}
+
+
+/* dsharp -- form the disjoint-sharp product between two cubes */
+pcover dsharp(a, b)
+pcube a, b;
+{
+    register pcube mask, diff, and, temp, temp1 = cube.temp[0];
+    int var;
+    pcover r;
+
+    r = new_cover(cube.num_vars);
+
+    if (cdist0(a, b)) {
+	diff = set_diff(new_cube(), a, b);
+	and = set_and(new_cube(), a, b);
+	mask = new_cube();
+	for(var = 0; var < cube.num_vars; var++) {
+	    /* check if position var of "a and not b" is not empty */
+	    if (! setp_disjoint(diff, cube.var_mask[var])) {
+
+		/* coordinate var equals the difference between a and b */
+		temp = GETSET(r, r->count++);
+		(void) set_and(temp, diff, cube.var_mask[var]);
+
+		/* coordinates 0 ... var-1 equal the intersection */
+		INLINEset_and(temp1, and, mask);
+		INLINEset_or(temp, temp, temp1);
+
+		/* coordinates var+1 .. cube.num_vars equal a */
+		set_or(mask, mask, cube.var_mask[var]);
+		INLINEset_diff(temp1, a, mask);
+		INLINEset_or(temp, temp, temp1);
+	    }
+	}
+	free_cube(diff);
+	free_cube(and);
+	free_cube(mask);
+    } else {
+	r = sf_addset(r, a);
+    }
+    return r;
+}
+
+/* cv_intersect -- form the intersection of two covers */
+
+#define MAGIC 500               /* save 500 cubes before containment */
+
+pcover cv_intersect(A, B)
+pcover A, B;
+{
+    register pcube pi, pj, lasti, lastj, pt;
+    pcover T, Tsave = NULL;
+
+    /* How large should each temporary result cover be ? */
+    T = new_cover(MAGIC);
+    pt = T->data;
+
+    /* Form pairwise intersection of each cube of A with each cube of B */
+    foreach_set(A, lasti, pi) {
+	foreach_set(B, lastj, pj) {
+	    if (cdist0(pi, pj)) {
+		(void) set_and(pt, pi, pj);
+		if (++T->count >= T->capacity) {
+		    if (Tsave == NULL)
+			Tsave = sf_contain(T);
+		    else
+			Tsave = sf_union(Tsave, sf_contain(T));
+		    T = new_cover(MAGIC);
+		    pt = T->data;
+		} else
+		    pt += T->wsize;
+	    }
+	}
+    }
+
+
+    if (Tsave == NULL)
+	Tsave = sf_contain(T);
+    else
+	Tsave = sf_union(Tsave, sf_contain(T));
+    return Tsave;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/sminterf.c b/abc-build/src/misc/espresso/sminterf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/sminterf.c
@@ -0,0 +1,49 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+pset
+do_sm_minimum_cover(A)
+pset_family A;
+{
+    sm_matrix *M;
+    sm_row *sparse_cover;
+    sm_element *pe;
+    pset cover;
+    register int i, base, rownum;
+    register unsigned val;
+    register pset last, p;
+
+    M = sm_alloc();
+    rownum = 0;
+    foreach_set(A, last, p) {
+	foreach_set_element(p, i, val, base) {
+	    (void) sm_insert(M, rownum, base);
+	}
+	rownum++;
+    }
+
+    sparse_cover = sm_minimum_cover(M, NIL(int), 1, 0);
+    sm_free(M);
+
+    cover = set_new(A->sf_size);
+    sm_foreach_row_element(sparse_cover, pe) {
+	set_insert(cover, pe->col_num);
+    }
+    sm_row_free(sparse_cover);
+
+    return cover;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/solution.c b/abc-build/src/misc/espresso/solution.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/solution.c
@@ -0,0 +1,119 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+solution_t *
+solution_alloc()
+{
+    solution_t *sol;
+
+    sol = ALLOC(solution_t, 1);
+    sol->cost = 0;
+    sol->row = sm_row_alloc();
+    return sol;
+}
+
+
+void
+solution_free(sol)
+solution_t *sol;
+{
+    sm_row_free(sol->row);
+    FREE(sol);
+}
+
+
+solution_t *
+solution_dup(sol)
+solution_t *sol;
+{
+    solution_t *new_sol;
+
+    new_sol = ALLOC(solution_t, 1);
+    new_sol->cost = sol->cost;
+    new_sol->row = sm_row_dup(sol->row);
+    return new_sol;
+}
+
+
+void 
+solution_add(sol, weight, col)
+solution_t *sol;
+int *weight;
+int col;
+{
+    (void) sm_row_insert(sol->row, col);
+    sol->cost += WEIGHT(weight, col);
+}
+
+
+void 
+solution_accept(sol, A, weight, col)
+solution_t *sol;
+sm_matrix *A;
+int *weight;
+int col;
+{
+    register sm_element *p, *pnext;
+    sm_col *pcol;
+
+    solution_add(sol, weight, col);
+
+    /* delete rows covered by this column */
+    pcol = sm_get_col(A, col);
+    for(p = pcol->first_row; p != 0; p = pnext) {
+	pnext = p->next_row;		/* grab it before it disappears */
+	sm_delrow(A, p->row_num);
+    }
+}
+
+
+/* ARGSUSED */
+void 
+solution_reject(sol, A, weight, col)
+solution_t *sol;
+sm_matrix *A;
+int *weight;
+int col;
+{
+    sm_delcol(A, col);
+}
+
+
+solution_t *
+solution_choose_best(best1, best2)
+solution_t *best1, *best2;
+{
+    if (best1 != NIL(solution_t)) {
+	if (best2 != NIL(solution_t)) {
+	    if (best1->cost <= best2->cost) {
+		solution_free(best2);
+		return best1;
+	    } else {
+		solution_free(best1);
+		return best2;
+	    }
+	} else {
+	    return best1;
+	}
+    } else {
+	if (best2 != NIL(solution_t)) {
+	    return best2;
+	} else {
+	    return NIL(solution_t);
+	}
+    }
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/sparse.c b/abc-build/src/misc/espresso/sparse.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/sparse.c
@@ -0,0 +1,151 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+    module: sparse.c
+
+    make_sparse is a last-step cleanup to reduce the total number
+    of literals in the cover.
+
+    This is done by reducing the "sparse" variables (using a modified
+    version of irredundant rather than reduce), followed by expanding
+    the "dense" variables (using modified version of expand).
+*/
+
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+pcover make_sparse(F, D, R)
+pcover F, D, R;
+{
+    cost_t cost, best_cost;
+
+    cover_cost(F, &best_cost);
+
+    do {
+	EXECUTE(F = mv_reduce(F, D), MV_REDUCE_TIME, F, cost);
+	if (cost.total == best_cost.total)
+	    break;
+	copy_cost(&cost, &best_cost);
+
+	EXECUTE(F = expand(F, R, TRUE), RAISE_IN_TIME, F, cost);
+	if (cost.total == best_cost.total)
+	    break;
+	copy_cost(&cost, &best_cost);
+    } while (force_irredundant);
+
+    return F;
+}
+
+/*
+    mv_reduce -- perform an "optimal" reduction of the variables which
+    we desire to be sparse
+
+    This could be done using "reduce" and then saving just the desired
+    part of the reduction.  Instead, this version uses IRRED to find
+    which cubes of an output are redundant.  Note that this gets around
+    the cube-ordering problem.
+
+    In normal use, it is expected that the cover is irredundant and
+    hence no cubes will be reduced to the empty cube (however, this is
+    checked for and such cubes will be deleted)
+*/
+
+pcover
+mv_reduce(F, D)
+pcover F, D;
+{
+    register int i, var;
+    register pcube p, p1, last;
+    int index;
+    pcover F1, D1;
+    pcube *F_cube_table;
+
+    /* loop for each multiple-valued variable */
+    for(var = 0; var < cube.num_vars; var++) {
+
+	if (cube.sparse[var]) {
+
+	    /* loop for each part of the variable */
+	    for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+
+		/* remember mapping of F1 cubes back to F cubes */
+		F_cube_table = ALLOC(pcube, F->count);
+
+		/* 'cofactor' against part #i of variable #var */
+		F1 = new_cover(F->count);
+		foreach_set(F, last, p) {
+		    if (is_in_set(p, i)) {
+			F_cube_table[F1->count] = p;
+			p1 = GETSET(F1, F1->count++);
+			(void) set_diff(p1, p, cube.var_mask[var]);
+			set_insert(p1, i);
+		    }
+		}
+
+		/* 'cofactor' against part #i of variable #var */
+		/* not really necessary -- just more efficient ? */
+		D1 = new_cover(D->count);
+		foreach_set(D, last, p) {
+		    if (is_in_set(p, i)) {
+			p1 = GETSET(D1, D1->count++);
+			(void) set_diff(p1, p, cube.var_mask[var]);
+			set_insert(p1, i);
+		    }
+		}
+
+		mark_irredundant(F1, D1);
+
+		/* now remove part i from cubes which are redundant */
+		index = 0;
+		foreach_set(F1, last, p1) {
+		    if (! TESTP(p1, ACTIVE)) {
+			p = F_cube_table[index];
+
+			/*   don't reduce a variable which is full
+			 *   (unless it is the output variable)
+			 */
+			if (var == cube.num_vars-1 ||
+			     ! setp_implies(cube.var_mask[var], p)) {
+			    set_remove(p, i);
+			}
+			RESET(p, PRIME);
+		    }
+		    index++;
+		}
+
+		free_cover(F1);
+		free_cover(D1);
+		FREE(F_cube_table);
+	    }
+	}
+    }
+
+    /* Check if any cubes disappeared */
+    (void) sf_active(F);
+    for(var = 0; var < cube.num_vars; var++) {
+	if (cube.sparse[var]) {
+	    foreach_active_set(F, last, p) {
+		if (setp_disjoint(p, cube.var_mask[var])) {
+		    RESET(p, ACTIVE);
+		    F->active_count--;
+		}
+	    }
+	}
+    }
+
+    if (F->count != F->active_count) {
+	F = sf_inactive(F);
+    }
+    return F;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/sparse.h b/abc-build/src/misc/espresso/sparse.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/sparse.h
@@ -0,0 +1,143 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#ifndef ABC__misc__espresso__sparse_h
+#define ABC__misc__espresso__sparse_h
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+/*
+ *  sparse.h -- sparse matrix package header file
+ */
+
+typedef struct sm_element_struct sm_element;
+typedef struct sm_row_struct sm_row;
+typedef struct sm_col_struct sm_col;
+typedef struct sm_matrix_struct sm_matrix;
+
+
+/*
+ *  sparse matrix element
+ */
+struct sm_element_struct {
+    int row_num;		/* row number of this element */
+    int col_num;		/* column number of this element */
+    sm_element *next_row;	/* next row in this column */
+    sm_element *prev_row;	/* previous row in this column */
+    sm_element *next_col;	/* next column in this row */
+    sm_element *prev_col;	/* previous column in this row */
+    char *user_word;		/* user-defined word */
+};
+
+
+/*
+ *  row header
+ */
+struct sm_row_struct {
+    int row_num;		/* the row number */
+    int length;			/* number of elements in this row */
+    int flag;			/* user-defined word */
+    sm_element *first_col;	/* first element in this row */
+    sm_element *last_col;	/* last element in this row */
+    sm_row *next_row;		/* next row (in sm_matrix linked list) */
+    sm_row *prev_row;		/* previous row (in sm_matrix linked list) */
+    char *user_word;		/* user-defined word */
+};
+
+
+/*
+ *  column header
+ */
+struct sm_col_struct {
+    int col_num;		/* the column number */
+    int length;			/* number of elements in this column */
+    int flag;			/* user-defined word */
+    sm_element *first_row;	/* first element in this column */
+    sm_element *last_row;	/* last element in this column */
+    sm_col *next_col;		/* next column (in sm_matrix linked list) */
+    sm_col *prev_col;		/* prev column (in sm_matrix linked list) */
+    char *user_word;		/* user-defined word */
+};
+
+
+/*
+ *  A sparse matrix
+ */
+struct sm_matrix_struct {
+    sm_row **rows;		/* pointer to row headers (by row #) */
+    int rows_size;		/* alloc'ed size of above array */
+    sm_col **cols;		/* pointer to column headers (by col #) */
+    int cols_size;		/* alloc'ed size of above array */
+    sm_row *first_row;		/* first row (linked list of all rows) */
+    sm_row *last_row;		/* last row (linked list of all rows) */
+    int nrows;			/* number of rows */
+    sm_col *first_col;		/* first column (linked list of columns) */
+    sm_col *last_col;		/* last column (linked list of columns) */
+    int ncols;			/* number of columns */
+    char *user_word;		/* user-defined word */
+};
+
+
+#define sm_get_col(A, colnum)	\
+    (((colnum) >= 0 && (colnum) < (A)->cols_size) ? \
+	(A)->cols[colnum] : (sm_col *) 0)
+
+#define sm_get_row(A, rownum)	\
+    (((rownum) >= 0 && (rownum) < (A)->rows_size) ? \
+	(A)->rows[rownum] : (sm_row *) 0)
+
+#define sm_foreach_row(A, prow)	\
+	for(prow = A->first_row; prow != 0; prow = prow->next_row)
+
+#define sm_foreach_col(A, pcol)	\
+	for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col)
+
+#define sm_foreach_row_element(prow, p)	\
+	for(p = prow->first_col; p != 0; p = p->next_col)
+
+#define sm_foreach_col_element(pcol, p)	\
+	for(p = pcol->first_row; p != 0; p = p->next_row)
+
+#define sm_put(x, val) \
+	(x->user_word = (char *) val)
+
+#define sm_get(type, x) \
+	((type) (x->user_word))
+
+extern sm_matrix *sm_alloc(), *sm_alloc_size(), *sm_dup();
+extern void sm_free(), sm_delrow(), sm_delcol(), sm_resize();
+extern void sm_write(), sm_print(), sm_dump(), sm_cleanup();
+extern void sm_copy_row(), sm_copy_col();
+extern void sm_remove(), sm_remove_element();
+extern sm_element *sm_insert(), *sm_find();
+extern sm_row *sm_longest_row();
+extern sm_col *sm_longest_col();
+extern int sm_read(), sm_read_compressed();
+
+extern sm_row *sm_row_alloc(), *sm_row_dup(), *sm_row_and();
+extern void sm_row_free(), sm_row_remove(), sm_row_print();
+extern sm_element *sm_row_insert(), *sm_row_find();
+extern int sm_row_contains(), sm_row_intersects();
+extern int sm_row_compare(), sm_row_hash();
+
+extern sm_col *sm_col_alloc(), *sm_col_dup(), *sm_col_and();
+extern void sm_col_free(), sm_col_remove(), sm_col_print();
+extern sm_element *sm_col_insert(), *sm_col_find();
+extern int sm_col_contains(), sm_col_intersects();
+extern int sm_col_compare(), sm_col_hash();
+
+extern int sm_row_dominance(), sm_col_dominance(), sm_block_partition();
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/misc/espresso/sparse_int.h b/abc-build/src/misc/espresso/sparse_int.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/sparse_int.h
@@ -0,0 +1,121 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+//#include "utility.h"
+#include "sparse.h"
+
+#include "util_hack.h" // added
+
+
+
+/*
+ *  sorted, double-linked list insertion
+ *
+ *  type: object type
+ *
+ *  first, last: fields (in header) to head and tail of the list
+ *  count: field (in header) of length of the list
+ *
+ *  next, prev: fields (in object) to link next and previous objects
+ *  value: field (in object) which controls the order
+ *
+ *  newval: value field for new object
+ *  e: an object to use if insertion needed (set to actual value used)
+ */
+
+#define ABC__misc__espresso__sparse_int_h
+    if (last == 0) { \
+	e->value = newval; \
+	first = e; \
+	last = e; \
+	e->next = 0; \
+	e->prev = 0; \
+	count++; \
+    } else if (last->value < newval) { \
+	e->value = newval; \
+	last->next = e; \
+	e->prev = last; \
+	last = e; \
+	e->next = 0; \
+	count++; \
+    } else if (first->value > newval) { \
+	e->value = newval; \
+	first->prev = e; \
+	e->next = first; \
+	first = e; \
+	e->prev = 0; \
+	count++; \
+    } else { \
+	type *p; \
+	for(p = first; p->value < newval; p = p->next) \
+	    ; \
+	if (p->value > newval) { \
+	    e->value = newval; \
+	    p = p->prev; \
+	    p->next->prev = e; \
+	    e->next = p->next; \
+	    p->next = e; \
+	    e->prev = p; \
+	    count++; \
+	} else { \
+	    e = p; \
+	} \
+    }
+
+
+/*
+ *  double linked-list deletion
+ */
+#define dll_unlink(p, first, last, next, prev, count) { \
+    if (p->prev == 0) { \
+	first = p->next; \
+    } else { \
+	p->prev->next = p->next; \
+    } \
+    if (p->next == 0) { \
+	last = p->prev; \
+    } else { \
+	p->next->prev = p->prev; \
+    } \
+    count--; \
+}
+
+
+#ifdef FAST_AND_LOOSE
+extern sm_element *sm_element_freelist;
+extern sm_row *sm_row_freelist;
+extern sm_col *sm_col_freelist;
+
+#define sm_element_alloc(newobj) \
+    if (sm_element_freelist == NIL(sm_element)) { \
+	newobj = ALLOC(sm_element, 1); \
+    } else { \
+	newobj = sm_element_freelist; \
+	sm_element_freelist = sm_element_freelist->next_col; \
+    } \
+    newobj->user_word = NIL(char); \
+
+#define sm_element_free(e) \
+    (e->next_col = sm_element_freelist, sm_element_freelist = e)
+
+#else
+
+#define sm_element_alloc(newobj)	\
+    newobj = ALLOC(sm_element, 1);	\
+    newobj->user_word = NIL(char);
+#define sm_element_free(e)		\
+    FREE(e)
+#endif
+
+
+extern void sm_row_remove_element();
+extern void sm_col_remove_element();
+
+/* LINTLIBRARY */
diff --git a/abc-build/src/misc/espresso/unate.c b/abc-build/src/misc/espresso/unate.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/unate.c
@@ -0,0 +1,446 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ *  unate.c -- routines for dealing with unate functions
+ */
+
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+static pset_family abs_covered();
+static pset_family abs_covered_many();
+static int abs_select_restricted();
+
+pcover map_cover_to_unate(T)
+pcube *T;
+{
+    register unsigned int word_test, word_set, bit_test, bit_set;
+    register pcube p, pA;
+    pset_family A;
+    pcube *T1;
+    int ncol, i;
+
+    A = sf_new(CUBELISTSIZE(T), cdata.vars_unate);
+    A->count = CUBELISTSIZE(T);
+    foreachi_set(A, i, p) {
+	(void) set_clear(p, A->sf_size);
+    }
+    ncol = 0;
+
+    for(i = 0; i < cube.size; i++) {
+	if (cdata.part_zeros[i] > 0) {
+	    assert(ncol <= cdata.vars_unate);
+
+	    /* Copy a column from T to A */
+	    word_test = WHICH_WORD(i);
+	    bit_test = 1 << WHICH_BIT(i);
+	    word_set = WHICH_WORD(ncol);
+	    bit_set = 1 << WHICH_BIT(ncol);
+
+	    pA = A->data;
+	    for(T1 = T+2; (p = *T1++) != 0; ) {
+		if ((p[word_test] & bit_test) == 0) {
+		    pA[word_set] |= bit_set;
+		}
+		pA += A->wsize;
+	    }
+
+	    ncol++;
+	}
+    }
+
+    return A;
+}
+
+pcover map_unate_to_cover(A)
+pset_family A;
+{
+    register int i, ncol, lp;
+    register pcube p, pB;
+    int var, nunate, *unate;
+    pcube last;
+    pset_family B;
+
+    B = sf_new(A->count, cube.size);
+    B->count = A->count;
+
+    /* Find the unate variables */
+    unate = ALLOC(int, cube.num_vars);
+    nunate = 0;
+    for(var = 0; var < cube.num_vars; var++) {
+	if (cdata.is_unate[var]) {
+	    unate[nunate++] = var;
+	}
+    }
+
+    /* Loop for each set of A */
+    pB = B->data;
+    foreach_set(A, last, p) {
+
+	/* Initialize this set of B */
+	INLINEset_fill(pB, cube.size);
+
+	/* Now loop for the unate variables; if the part is in A,
+	 * then this variable of B should be a single 1 in the unate
+	 * part.
+	 */
+	for(ncol = 0; ncol < nunate; ncol++) {
+	    if (is_in_set(p, ncol)) {
+		lp = cube.last_part[unate[ncol]];
+		for(i = cube.first_part[unate[ncol]]; i <= lp; i++) {
+		    if (cdata.part_zeros[i] == 0) {
+			set_remove(pB, i);
+		    }
+		}
+	    }
+	}
+	pB += B->wsize;
+    }
+
+    FREE(unate);
+    return B;
+}
+
+/*
+ *  unate_compl
+ */
+
+pset_family unate_compl(A)
+pset_family A;
+{
+    register pset p, last;
+
+    /* Make sure A is single-cube containment minimal */
+/*    A = sf_rev_contain(A);*/
+
+    foreach_set(A, last, p) {
+	PUTSIZE(p, set_ord(p));
+    }
+
+    /* Recursively find the complement */
+    A = unate_complement(A);
+
+    /* Now, we can guarantee a minimal result by containing the result */
+    A = sf_rev_contain(A);
+    return A;
+}
+
+
+/*
+ *  Assume SIZE(p) records the size of each set
+ */
+pset_family unate_complement(A)
+pset_family A;			/* disposes of A */
+{
+    pset_family Abar;
+    register pset p, p1, restrict;
+    register int i;
+    int max_i, min_set_ord, j;
+
+    /* Check for no sets in the matrix -- complement is the universe */
+    if (A->count == 0) {
+	sf_free(A);
+	Abar = sf_new(1, A->sf_size);
+	(void) set_clear(GETSET(Abar, Abar->count++), A->sf_size);
+
+    /* Check for a single set in the maxtrix -- compute de Morgan complement */
+    } else if (A->count == 1) {
+	p = A->data;
+	Abar = sf_new(A->sf_size, A->sf_size);
+	for(i = 0; i < A->sf_size; i++) {
+	    if (is_in_set(p, i)) {
+		p1 = set_clear(GETSET(Abar, Abar->count++), A->sf_size);
+		set_insert(p1, i);
+	    }
+	}
+	sf_free(A);
+
+    } else {
+
+	/* Select splitting variable as the variable which belongs to a set
+	 * of the smallest size, and which has greatest column count
+	 */
+	restrict = set_new(A->sf_size);
+	min_set_ord = A->sf_size + 1;
+	foreachi_set(A, i, p) {
+	    if (SIZE(p) < min_set_ord) {
+		set_copy(restrict, p);
+		min_set_ord = SIZE(p);
+	    } else if (SIZE(p) == min_set_ord) {
+		set_or(restrict, restrict, p);
+	    }
+	}
+
+	/* Check for no data (shouldn't happen ?) */
+	if (min_set_ord == 0) {
+	    A->count = 0;
+	    Abar = A;
+
+	/* Check for "essential" columns */
+	} else if (min_set_ord == 1) {
+	    Abar = unate_complement(abs_covered_many(A, restrict));
+	    sf_free(A);
+	    foreachi_set(Abar, i, p) {
+		set_or(p, p, restrict);
+	    }
+
+	/* else, recur as usual */
+	} else {
+	    max_i = abs_select_restricted(A, restrict);
+
+	    /* Select those rows of A which are not covered by max_i,
+	     * recursively find all minimal covers of these rows, and
+	     * then add back in max_i
+	     */
+	    Abar = unate_complement(abs_covered(A, max_i));
+	    foreachi_set(Abar, i, p) {
+		set_insert(p, max_i);
+	    }
+
+	    /* Now recur on A with all zero's on column max_i */
+	    foreachi_set(A, i, p) {
+		if (is_in_set(p, max_i)) {
+		    set_remove(p, max_i);
+		    j = SIZE(p) - 1;
+		    PUTSIZE(p, j);
+		}
+	    }
+
+	    Abar = sf_append(Abar, unate_complement(A));
+	}
+	set_free(restrict);
+    }
+
+    return Abar;
+}
+
+pset_family exact_minimum_cover(T)
+IN pset_family T;
+{
+    register pset p, last, p1;
+    register int i, n;
+    int lev, lvl;
+    pset nlast;
+    pset_family temp;
+    long start = ptime();
+    struct {
+	pset_family sf;
+	int level;
+    } stack[32];                /* 32 suffices for 2 ** 32 cubes ! */
+
+    if (T->count <= 0)
+	return sf_new(1, T->sf_size);
+    for(n = T->count, lev = 0; n != 0; n >>= 1, lev++)   ;
+
+    /* A simple heuristic ordering */
+    T = lex_sort(sf_save(T));
+
+    /* Push a full set on the stack to get things started */
+    n = 1;
+    stack[0].sf = sf_new(1, T->sf_size);
+    stack[0].level = lev;
+    set_fill(GETSET(stack[0].sf, stack[0].sf->count++), T->sf_size);
+
+    nlast = GETSET(T, T->count - 1);
+    foreach_set(T, last, p) {
+
+	/* "unstack" the set into a family */
+	temp = sf_new(set_ord(p), T->sf_size);
+	for(i = 0; i < T->sf_size; i++)
+	    if (is_in_set(p, i)) {
+		p1 = set_fill(GETSET(temp, temp->count++), T->sf_size);
+		set_remove(p1, i);
+	    }
+	stack[n].sf = temp;
+	stack[n++].level = lev;
+
+	/* Pop the stack and perform (leveled) intersections */
+	while (n > 1 && (stack[n-1].level==stack[n-2].level || p == nlast)) {
+	    temp = unate_intersect(stack[n-1].sf, stack[n-2].sf, FALSE);
+	    lvl = MIN(stack[n-1].level, stack[n-2].level) - 1;
+	    if (debug & MINCOV && lvl < 10) {
+		printf("# EXACT_MINCOV[%d]: %4d = %4d x %4d, time = %s\n",
+		    lvl, temp->count, stack[n-1].sf->count,
+		    stack[n-2].sf->count, print_time(ptime() - start));
+		(void) fflush(stdout);
+	    }
+	    sf_free(stack[n-2].sf);
+	    sf_free(stack[n-1].sf);
+	    stack[n-2].sf = temp;
+	    stack[n-2].level = lvl;
+	    n--;
+	}
+    }
+
+    temp = stack[0].sf;
+    p1 = set_fill(set_new(T->sf_size), T->sf_size);
+    foreach_set(temp, last, p)
+	INLINEset_diff(p, p1, p);
+    set_free(p1);
+    if (debug & MINCOV1) {
+	printf("MINCOV: family of all minimal coverings is\n");
+	sf_print(temp);
+    }
+    sf_free(T);         /* this is the copy of T we made ... */
+    return temp;
+}
+
+/*
+ *  unate_intersect -- intersect two unate covers
+ *
+ *  If largest_only is TRUE, then only the largest cube(s) are returned
+ */
+
+#define MAGIC 500               /* save 500 cubes before containment */
+
+pset_family unate_intersect(A, B, largest_only)
+pset_family A, B;
+bool largest_only;
+{
+    register pset pi, pj, lasti, lastj, pt;
+    pset_family T, Tsave;
+    bool save;
+    int maxord, ord;
+
+    /* How large should each temporary result cover be ? */
+    T = sf_new(MAGIC, A->sf_size);
+    Tsave = NULL;
+    maxord = 0;
+    pt = T->data;
+
+    /* Form pairwise intersection of each set of A with each cube of B */
+    foreach_set(A, lasti, pi) {
+
+	foreach_set(B, lastj, pj) {
+
+	    save = set_andp(pt, pi, pj);
+
+	    /* Check if we want the largest only */
+	    if (save && largest_only) {
+		if ((ord = set_ord(pt)) > maxord) {
+		    /* discard Tsave and T */
+		    if (Tsave != NULL) {
+			sf_free(Tsave);
+			Tsave = NULL;
+		    }
+		    pt = T->data;
+		    T->count = 0;
+		    /* Re-create pt (which was just thrown away) */
+		    (void) set_and(pt, pi, pj);
+		    maxord = ord;
+		} else if (ord < maxord) {
+		    save = FALSE;
+		}
+	    }
+
+	    if (save) {
+		if (++T->count >= T->capacity) {
+		    T = sf_contain(T);
+		    Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T);
+		    T = sf_new(MAGIC, A->sf_size);
+		    pt = T->data;
+		} else {
+		    pt += T->wsize;
+		}
+	    }
+	}
+    }
+
+
+    /* Contain the final result and merge it into Tsave */
+    T = sf_contain(T);
+    Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T);
+
+    return Tsave;
+}
+
+/*
+ *  abs_covered -- after selecting a new column for the selected set,
+ *  create a new matrix which is only those rows which are still uncovered
+ */
+static pset_family
+abs_covered(A, pick)
+pset_family A;
+register int pick;
+{
+    register pset last, p, pdest;
+    register pset_family Aprime;
+
+    Aprime = sf_new(A->count, A->sf_size);
+    pdest = Aprime->data;
+    foreach_set(A, last, p)
+	if (! is_in_set(p, pick)) {
+	    INLINEset_copy(pdest, p);
+	    Aprime->count++;
+	    pdest += Aprime->wsize;
+	}
+    return Aprime;
+}
+
+
+/*
+ *  abs_covered_many -- after selecting many columns for ther selected set,
+ *  create a new matrix which is only those rows which are still uncovered
+ */
+static pset_family
+abs_covered_many(A, pick_set)
+pset_family A;
+register pset pick_set;
+{
+    register pset last, p, pdest;
+    register pset_family Aprime;
+
+    Aprime = sf_new(A->count, A->sf_size);
+    pdest = Aprime->data;
+    foreach_set(A, last, p)
+	if (setp_disjoint(p, pick_set)) {
+	    INLINEset_copy(pdest, p);
+	    Aprime->count++;
+	    pdest += Aprime->wsize;
+	}
+    return Aprime;
+}
+
+
+/*
+ *  abs_select_restricted -- select the column of maximum column count which
+ *  also belongs to the set "restrict"; weight each column of a set as
+ *  1 / (set_ord(p) - 1).
+ */
+static int
+abs_select_restricted(A, restrict)
+pset_family A;
+pset restrict;
+{
+    register int i, best_var, best_count, *count;
+
+    /* Sum the elements in these columns */
+    count = sf_count_restricted(A, restrict);
+
+    /* Find which variable has maximum weight */
+    best_var = -1;
+    best_count = 0;
+    for(i = 0; i < A->sf_size; i++) {
+	if (count[i] > best_count) {
+	    best_var = i;
+	    best_count = count[i];
+	}
+    }
+    FREE(count);
+
+    if (best_var == -1)
+	fatal("abs_select_restricted: should not have best_var == -1");
+
+    return best_var;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/espresso/util_old.h b/abc-build/src/misc/espresso/util_old.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/util_old.h
@@ -0,0 +1,309 @@
+/*
+ * Revision Control Information
+ *
+ * $Source: /vol/opua/opua2/sis/sis-1.2/common/src/sis/util/RCS/util.h,v $
+ * $Author: sis $
+ * $Revision: 1.9 $
+ * $Date: 1993/06/07 21:04:07 $
+ *
+ */
+#ifndef ABC__misc__espresso__util_old_h
+#define ABC__misc__espresso__util_old_h
+
+#if defined(_IBMR2)
+#ifndef _POSIX_SOURCE
+#define _POSIX_SOURCE           /* Argh!  IBM strikes again */
+#endif
+#ifndef _ALL_SOURCE
+#define _ALL_SOURCE             /* Argh!  IBM strikes again */
+#endif
+#ifndef _ANSI_C_SOURCE
+#define _ANSI_C_SOURCE          /* Argh!  IBM strikes again */
+#endif
+#endif
+
+#if defined(__STDC__) || defined(sprite) || defined(_IBMR2) || defined(__osf__)
+#include <unistd.h>
+#endif
+
+#if defined(_IBMR2) && !defined(__STDC__)
+#define _BSD
+#endif
+
+#include "ansi.h"	/* since some files don't include sis.h */
+
+/* This was taken out and defined at compile time in the SIS Makefile
+   that uses the OctTools.  When the OctTools are used, USE_MM is defined,
+   because the OctTools contain libmm.a.  Otherwise, USE_MM is not defined,
+   since the mm package is not distributed with SIS, only with Oct. */
+
+/* #define USE_MM */		/* choose libmm.a as the memory allocator */
+
+#define NIL(type)		((type *) 0)
+
+#ifdef USE_MM
+/*
+ *  assumes the memory manager is libmm.a
+ *	- allows malloc(0) or realloc(obj, 0)
+ *	- catches out of memory (and calls MMout_of_memory())
+ *	- catch free(0) and realloc(0, size) in the macros
+ */
+#define ALLOC(type, num)	\
+    ((type *) malloc(sizeof(type) * (num)))
+#define REALLOC(type, obj, num)	\
+    (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \
+	    ((type *) malloc(sizeof(type) * (num)))
+#define FREE(obj)		\
+    ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#else
+/*
+ *  enforce strict semantics on the memory allocator
+ *	- when in doubt, delete the '#define USE_MM' above
+ */
+#define ALLOC(type, num)	\
+    ((type *) MMalloc((long) sizeof(type) * (long) (num)))
+#define REALLOC(type, obj, num)	\
+    ((type *) MMrealloc((char *) (obj), (long) sizeof(type) * (long) (num)))
+#define FREE(obj)		\
+    ((obj) ? (free((void *) (obj)), (obj) = 0) : 0)
+#endif
+
+
+/* Ultrix (and SABER) have 'fixed' certain functions which used to be int */
+#if defined(ultrix) || defined(SABER) || defined(aiws) || defined(__hpux) || defined(__STDC__) || defined(apollo)
+#define VOID_HACK void
+#else
+#define VOID_HACK int
+#endif
+
+
+/* No machines seem to have much of a problem with these */
+#include <stdio.h>
+#include <ctype.h>
+
+
+/* Some machines fail to define some functions in stdio.h */
+#if !defined(__STDC__) && !defined(sprite) && !defined(_IBMR2) && !defined(__osf__)
+extern FILE *popen(), *tmpfile();
+extern int pclose();
+#ifndef clearerr		/* is a macro on many machines, but not all */
+extern VOID_HACK clearerr();
+#endif
+#ifndef rewind
+extern VOID_HACK rewind();
+#endif
+#endif
+
+#ifndef PORT_H
+#include <sys/types.h>
+#include <signal.h>
+#if defined(ultrix)
+#if defined(_SIZE_T_)
+#define ultrix4
+#else
+#if defined(SIGLOST)
+#define ultrix3
+#else
+#define ultrix2
+#endif
+#endif
+#endif
+#endif
+
+/* most machines don't give us a header file for these */
+#if defined(__STDC__) || defined(sprite) || defined(_IBMR2) || defined(__osf__) || defined(sunos4) || defined(__hpux)
+#include <stdlib.h>
+#if defined(__hpux)
+#include <errno.h>    /* For perror() defininition */
+#endif /* __hpux */
+#else
+extern VOID_HACK abort(), free(), exit(), perror();
+extern char *getenv();
+#ifdef ultrix4
+extern void *malloc(), *realloc(), *calloc();
+#else
+extern char *malloc(), *realloc(), *calloc();
+#endif
+#if defined(aiws) 
+extern int sprintf();
+#else
+#ifndef _IBMR2
+extern char *sprintf();
+#endif
+#endif
+extern int system();
+extern double atof();
+#endif
+
+#ifndef PORT_H
+#if defined(ultrix3) || defined(sunos4) || defined(_IBMR2) || defined(__STDC__)
+#define SIGNAL_FN       void
+#else
+/* sequent, ultrix2, 4.3BSD (vax, hp), sunos3 */
+#define SIGNAL_FN       int
+#endif
+#endif
+
+/* some call it strings.h, some call it string.h; others, also have memory.h */
+#if defined(__STDC__) || defined(sprite)
+#include <string.h>
+#else
+#if defined(ultrix4) || defined(__hpux)
+#include <strings.h>
+#else
+#if defined(_IBMR2) || defined(__osf__)
+#include<string.h>
+#include<strings.h>
+#else
+/* ANSI C string.h -- 1/11/88 Draft Standard */
+/* ugly, awful hack */
+#ifndef PORT_H
+extern char *strcpy(), *strncpy(), *strcat(), *strncat(), *strerror();
+extern char *strpbrk(), *strtok(), *strchr(), *strrchr(), *strstr();
+extern int strcoll(), strxfrm(), strncmp(), strlen(), strspn(), strcspn();
+extern char *memmove(), *memccpy(), *memchr(), *memcpy(), *memset();
+extern int memcmp(), strcmp();
+#endif
+#endif
+#endif
+#endif
+
+/* a few extras */
+#if defined(__hpux)
+#define random() lrand48()
+#define srandom(a) srand48(a)
+#define bzero(a,b) memset(a, 0, b)
+#else
+#if !defined(__osf__) && !defined(linux)
+/* these are defined as macros in stdlib.h */
+extern VOID_HACK srandom();
+extern long random();
+#endif
+#endif
+
+/* code from sis-1.3 commented out below
+#if defined(__STDC__) || defined(sprite)
+#include <assert.h>
+#else
+#ifndef NDEBUG
+#define assert(ex) {\
+    if (! (ex)) {\
+	(void) fprintf(stderr,\
+	    "Assertion failed: file %s, line %d\n\"%s\"\n",\
+	    __FILE__, __LINE__, "ex");\
+	(void) fflush(stdout);\
+	abort();\
+    }\
+}
+#else
+#define assert(ex) {ex;}
+#endif
+#endif
+*/
+
+   /* Sunil 5/3/97:
+   sis-1.4: dont let the assert call go to the OS, since
+   much of the code in SIS has actual computation done in
+   the assert function. %$#$@@#! The OS version of assert
+   will do nothing if NDEBUG is set. We cant let that happen...
+   */
+#  ifdef NDEBUG
+#    define assert(ex) {ex;}
+#  else
+#    define assert(ex) {\
+    if (! (ex)) {\
+	(void) fprintf(stderr,\
+	    "Assertion failed: file %s, line %d\n\"%s\"\n",\
+	    __FILE__, __LINE__, "ex");\
+	(void) fflush(stdout);\
+	abort();\
+    }\
+}
+#  endif
+
+
+#define fail(why) {\
+    (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\
+	__FILE__, __LINE__, why);\
+    (void) fflush(stdout);\
+    abort();\
+}
+
+
+#ifdef lint
+#undef putc			/* correct lint '_flsbuf' bug */
+#undef ALLOC			/* allow for lint -h flag */
+#undef REALLOC
+#define ALLOC(type, num)	(((type *) 0) + (num))
+#define REALLOC(type, obj, num)	((obj) + (num))
+#endif
+
+/*
+#if !defined(__osf__)
+#define MAXPATHLEN
+ 1024
+#endif
+*/
+
+/* These arguably do NOT belong in util.h */
+#ifndef ABS
+#define ABS(a)			((a) < 0 ? -(a) : (a))
+#endif
+#ifndef MAX
+#define MAX(a,b)		((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b)		((a) < (b) ? (a) : (b))
+#endif
+
+
+#ifndef USE_MM
+EXTERN void MMout_of_memory ARGS((long));
+EXTERN char *MMalloc ARGS((long));
+EXTERN char *MMrealloc ARGS((char *, long));
+EXTERN void MMfree ARGS((char *));
+#endif
+
+EXTERN void util_print_cpu_stats ARGS((FILE *));
+EXTERN long util_cpu_time ARGS((void));
+EXTERN void util_getopt_reset ARGS((void));
+EXTERN int util_getopt ARGS((int, char **, char *));
+EXTERN char *util_path_search ARGS((char *));
+EXTERN char *util_file_search ARGS((char *, char *, char *));
+EXTERN int util_pipefork ARGS((char **, FILE **, FILE **, int *));
+EXTERN char *util_print_time ARGS((long));
+EXTERN int util_save_image ARGS((char *, char *));
+EXTERN char *util_strsav ARGS((char *));
+EXTERN int util_do_nothing ARGS((void));
+EXTERN char *util_tilde_expand ARGS((char *));
+EXTERN char *util_tempnam ARGS((char *, char *));
+EXTERN FILE *util_tmpfile ARGS((void));
+EXTERN long getSoftDataLimit();
+
+#define ptime()         util_cpu_time()
+#define print_time(t)   util_print_time(t)
+
+/* util_getopt() global variables (ack !) */
+extern int util_optind;
+extern char *util_optarg;
+
+#include <math.h>
+#ifndef HUGE_VAL
+#ifndef HUGE
+#define HUGE  8.9884656743115790e+307
+#endif
+#define HUGE_VAL HUGE
+#endif
+#ifndef MAXINT
+#define MAXINT (1 << 30)
+#endif
+
+#include <varargs.h>
+
+ABC_NAMESPACE_HEADER_START
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/misc/espresso/verify.c b/abc-build/src/misc/espresso/verify.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/espresso/verify.c
@@ -0,0 +1,198 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ */
+
+#include "espresso.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+ *  verify -- check that all minterms of F are contained in (Fold u Dold)
+ *  and that all minterms of Fold are contained in (F u Dold).
+ */
+bool verify(F, Fold, Dold)
+pcover F, Fold, Dold;
+{
+    pcube p, last, *FD;
+    bool verify_error = FALSE;
+
+    /* Make sure the function didn't grow too large */
+    FD = cube2list(Fold, Dold);
+    foreach_set(F, last, p)
+	if (! cube_is_covered(FD, p)) {
+	    printf("some minterm in F is not covered by Fold u Dold\n");
+	    verify_error = TRUE;
+	    if (verbose_debug) printf("%s\n", pc1(p)); else break;
+	}
+    free_cubelist(FD);
+
+    /* Make sure minimized function covers the original function */
+    FD = cube2list(F, Dold);
+    foreach_set(Fold, last, p)
+	if (! cube_is_covered(FD, p)) {
+	    printf("some minterm in Fold is not covered by F u Dold\n");
+	    verify_error = TRUE;
+	    if (verbose_debug) printf("%s\n", pc1(p)); else break;
+	}
+    free_cubelist(FD);
+
+    return verify_error;
+}
+
+
+
+/*
+ *  PLA_verify -- verify that two PLA's are identical
+ *
+ *  If names are given, row and column permutations are done to make
+ *  the comparison meaningful.
+ *
+ */
+bool PLA_verify(PLA1, PLA2)
+pPLA PLA1, PLA2;
+{
+    /* Check if both have names given; if so, attempt to permute to
+     * match the names
+     */
+    if (PLA1->label != NULL && PLA1->label[0] != NULL &&
+	   PLA2->label != NULL && PLA2->label[0] != NULL) {
+	PLA_permute(PLA1, PLA2);
+    } else {
+	(void) fprintf(stderr, "Warning: cannot permute columns without names\n");
+	return TRUE;
+    }
+
+    if (PLA1->F->sf_size != PLA2->F->sf_size) {
+	(void) fprintf(stderr, "PLA_verify: PLA's are not the same size\n");
+	return TRUE;
+    }
+
+    return verify(PLA2->F, PLA1->F, PLA1->D);
+}
+
+
+
+/*
+ *  Permute the columns of PLA1 so that they match the order of PLA2
+ *  Discard any columns of PLA1 which are not in PLA2
+ *  Association is strictly by the names of the columns of the cover.
+ */
+void PLA_permute(PLA1, PLA2)
+pPLA PLA1, PLA2;
+{
+    register int i, j, *permute, npermute;
+    register char *labi;
+    char **label;
+
+    /* determine which columns of PLA1 to save, and place these in the list
+     * "permute"; the order in this list is the final output order
+     */
+    npermute = 0;
+    permute = ALLOC(int, PLA2->F->sf_size);
+    for(i = 0; i < PLA2->F->sf_size; i++) {
+	labi = PLA2->label[i];
+	for(j = 0; j < PLA1->F->sf_size; j++) {
+	    if (strcmp(labi, PLA1->label[j]) == 0) {
+		permute[npermute++] = j;
+		break;
+	    }
+	}
+    }
+
+    /* permute columns */
+    if (PLA1->F != NULL) {
+	PLA1->F = sf_permute(PLA1->F, permute, npermute);
+    }
+    if (PLA1->R != NULL) {
+	PLA1->R = sf_permute(PLA1->R, permute, npermute);
+    }
+    if (PLA1->D != NULL) {
+	PLA1->D = sf_permute(PLA1->D, permute, npermute);
+    }
+
+    /* permute the labels */
+    label = ALLOC(char *, cube.size);
+    for(i = 0; i < npermute; i++) {
+	label[i] = PLA1->label[permute[i]];
+    }
+    for(i = npermute; i < cube.size; i++) {
+	label[i] = NULL;
+    }
+    FREE(PLA1->label);
+    PLA1->label = label;
+
+    FREE(permute);
+}
+
+
+
+/*
+ *  check_consistency -- test that the ON-set, OFF-set and DC-set form
+ *  a partition of the boolean space.
+ */
+bool check_consistency(PLA)
+pPLA PLA;
+{
+    bool verify_error = FALSE;
+    pcover T;
+
+    T = cv_intersect(PLA->F, PLA->D);
+    if (T->count == 0)
+	printf("ON-SET and DC-SET are disjoint\n");
+    else {
+	printf("Some minterm(s) belong to both the ON-SET and DC-SET !\n");
+	if (verbose_debug)
+	    cprint(T);
+	verify_error = TRUE;
+    }
+    (void) fflush(stdout);
+    free_cover(T);
+
+    T = cv_intersect(PLA->F, PLA->R);
+    if (T->count == 0)
+	printf("ON-SET and OFF-SET are disjoint\n");
+    else {
+	printf("Some minterm(s) belong to both the ON-SET and OFF-SET !\n");
+	if (verbose_debug)
+	    cprint(T);
+	verify_error = TRUE;
+    }
+    (void) fflush(stdout);
+    free_cover(T);
+
+    T = cv_intersect(PLA->D, PLA->R);
+    if (T->count == 0)
+	printf("DC-SET and OFF-SET are disjoint\n");
+    else {
+	printf("Some minterm(s) belong to both the OFF-SET and DC-SET !\n");
+	if (verbose_debug)
+	    cprint(T);
+	verify_error = TRUE;
+    }
+    (void) fflush(stdout);
+    free_cover(T);
+
+    if (tautology(cube3list(PLA->F, PLA->D, PLA->R)))
+	printf("Union of ON-SET, OFF-SET and DC-SET is the universe\n");
+    else {
+	T = complement(cube3list(PLA->F, PLA->D, PLA->R));
+	printf("There are minterms left unspecified !\n");
+	if (verbose_debug)
+	    cprint(T);
+	verify_error = TRUE;
+	free_cover(T);
+    }
+    (void) fflush(stdout);
+    return verify_error;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/ext/ext.h b/abc-build/src/misc/ext/ext.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/ext/ext.h
@@ -0,0 +1,57 @@
+/**CFile****************************************************************
+
+  FileName    [ext.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName []
+
+  Synopsis    [plugin for external functionality]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ext.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__misc__ext__ext_h
+#define ABC__misc__ext__ext_h
+
+#define EXT_ABC_FRAME
+#define EXT_ABC_INIT(pAbc)
+#define EXT_ABC_END(pAbc)
+    
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/ext/module.make b/abc-build/src/misc/ext/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/ext/module.make
diff --git a/abc-build/src/misc/extra/extra.h b/abc-build/src/misc/extra/extra.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extra.h
@@ -0,0 +1,414 @@
+/**CFile****************************************************************
+
+  FileName    [extra.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [extra]
+
+  Synopsis    [Various reusable software utilities.]
+
+  Description [This library contains a number of operators and 
+  traversal routines developed to extend the functionality of 
+  CUDD v.2.3.x, by Fabio Somenzi (http://vlsi.colorado.edu/~fabio/)
+  To compile your code with the library, #include "extra.h" 
+  in your source files and link your project to CUDD and this 
+  library. Use the library at your own risk and with caution. 
+  Note that debugging of some operators still continues.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: extra.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__misc__extra__extra_h
+#define ABC__misc__extra__extra_h
+
+
+#ifdef _WIN32
+#define inline __inline // compatible with MS VS 6.0
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/st/st.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+typedef unsigned char      uint8;
+typedef unsigned short     uint16;
+typedef unsigned int       uint32;
+
+/*===========================================================================*/
+/*     Various Utilities                                                     */
+/*===========================================================================*/
+
+/*=== extraUtilBitMatrix.c ================================================================*/
+
+typedef struct Extra_BitMat_t_ Extra_BitMat_t;
+extern Extra_BitMat_t * Extra_BitMatrixStart( int nSize );
+extern void         Extra_BitMatrixClean( Extra_BitMat_t * p );
+extern void         Extra_BitMatrixStop( Extra_BitMat_t * p );
+extern void         Extra_BitMatrixPrint( Extra_BitMat_t * p );
+extern int          Extra_BitMatrixReadSize( Extra_BitMat_t * p );
+extern void         Extra_BitMatrixInsert1( Extra_BitMat_t * p, int i, int k );
+extern int          Extra_BitMatrixLookup1( Extra_BitMat_t * p, int i, int k );
+extern void         Extra_BitMatrixDelete1( Extra_BitMat_t * p, int i, int k );
+extern void         Extra_BitMatrixInsert2( Extra_BitMat_t * p, int i, int k );
+extern int          Extra_BitMatrixLookup2( Extra_BitMat_t * p, int i, int k );
+extern void         Extra_BitMatrixDelete2( Extra_BitMat_t * p, int i, int k );
+extern void         Extra_BitMatrixOr( Extra_BitMat_t * p, int i, unsigned * pInfo );
+extern void         Extra_BitMatrixOrTwo( Extra_BitMat_t * p, int i, int j );
+extern int          Extra_BitMatrixCountOnesUpper( Extra_BitMat_t * p );
+extern int          Extra_BitMatrixIsDisjoint( Extra_BitMat_t * p1, Extra_BitMat_t * p2 );
+extern int          Extra_BitMatrixIsClique( Extra_BitMat_t * p );
+
+/*=== extraUtilFile.c ========================================================*/
+
+extern char *       Extra_FileGetSimilarName( char * pFileNameWrong, char * pS1, char * pS2, char * pS3, char * pS4, char * pS5 );
+extern char *       Extra_FileNameExtension( char * FileName );
+extern char *       Extra_FileNameAppend( char * pBase, char * pSuffix );
+extern char *       Extra_FileNameGeneric( char * FileName );
+extern char *       Extra_FileNameGenericAppend( char * pBase, char * pSuffix );
+extern char *       Extra_FileNameWithoutPath( char * FileName );
+extern int          Extra_FileCheck( char * pFileName );
+extern int          Extra_FileSize( char * pFileName );
+extern char *       Extra_FileRead( FILE * pFile );
+extern char *       Extra_FileRead2( FILE * pFile, FILE * pFile2 );
+extern char *       Extra_FileReadContents( char * pFileName );
+extern char *       Extra_FileReadContents2( char * pFileName, char * pFileName2 );
+extern int          Extra_FileIsType( char * pFileName, char * pS1, char * pS2, char * pS3 );
+extern char *       Extra_TimeStamp();
+extern char *       Extra_StringAppend( char * pStrGiven, char * pStrAdd );
+extern void         Extra_StringClean( char * pStrGiven, char * pCharKeep );
+extern unsigned     Extra_ReadBinary( char * Buffer );
+extern void         Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits );
+extern int          Extra_ReadHex( unsigned Sign[], char * pString, int nDigits );
+extern int          Extra_ReadHexadecimal( unsigned Sign[], char * pString, int nVars );
+extern void         Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars );
+extern void         Extra_PrintHexadecimalString( char * pString, unsigned Sign[], int nVars );
+extern void         Extra_PrintHex( FILE * pFile, unsigned * pTruth, int nVars );
+extern void         Extra_PrintHexReverse( FILE * pFile, unsigned * pTruth, int nVars );
+extern void         Extra_PrintSymbols( FILE * pFile, char Char, int nTimes, int fPrintNewLine );
+
+/*=== extraUtilReader.c ========================================================*/
+
+typedef struct Extra_FileReader_t_ Extra_FileReader_t;
+extern Extra_FileReader_t * Extra_FileReaderAlloc( char * pFileName, 
+    char * pCharsComment, char * pCharsStop, char * pCharsClean );
+extern void         Extra_FileReaderFree( Extra_FileReader_t * p );
+extern char *       Extra_FileReaderGetFileName( Extra_FileReader_t * p );
+extern int          Extra_FileReaderGetFileSize( Extra_FileReader_t * p );
+extern int          Extra_FileReaderGetCurPosition( Extra_FileReader_t * p );
+extern void *       Extra_FileReaderGetTokens( Extra_FileReader_t * p );
+extern int          Extra_FileReaderGetLineNumber( Extra_FileReader_t * p, int iToken );
+
+/*=== extraUtilMemory.c ========================================================*/
+
+typedef struct Extra_MmFixed_t_    Extra_MmFixed_t;    
+typedef struct Extra_MmFlex_t_     Extra_MmFlex_t;     
+typedef struct Extra_MmStep_t_     Extra_MmStep_t;     
+
+// fixed-size-block memory manager
+extern Extra_MmFixed_t *  Extra_MmFixedStart( int nEntrySize );
+extern void        Extra_MmFixedStop( Extra_MmFixed_t * p );
+extern char *      Extra_MmFixedEntryFetch( Extra_MmFixed_t * p );
+extern void        Extra_MmFixedEntryRecycle( Extra_MmFixed_t * p, char * pEntry );
+extern void        Extra_MmFixedRestart( Extra_MmFixed_t * p );
+extern int         Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p );
+extern int         Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p );
+// flexible-size-block memory manager
+extern Extra_MmFlex_t * Extra_MmFlexStart();
+extern void        Extra_MmFlexStop( Extra_MmFlex_t * p );
+extern void        Extra_MmFlexPrint( Extra_MmFlex_t * p );
+extern char *      Extra_MmFlexEntryFetch( Extra_MmFlex_t * p, int nBytes );
+extern int         Extra_MmFlexReadMemUsage( Extra_MmFlex_t * p );
+// hierarchical memory manager
+extern Extra_MmStep_t * Extra_MmStepStart( int nSteps );
+extern void        Extra_MmStepStop( Extra_MmStep_t * p );
+extern char *      Extra_MmStepEntryFetch( Extra_MmStep_t * p, int nBytes );
+extern void        Extra_MmStepEntryRecycle( Extra_MmStep_t * p, char * pEntry, int nBytes );
+extern int         Extra_MmStepReadMemUsage( Extra_MmStep_t * p );
+
+/*=== extraUtilMisc.c ========================================================*/
+
+/* finds the smallest integer larger or equal than the logarithm */
+extern int         Extra_Base2LogDouble( double Num );
+/* returns the power of two as a double */
+extern double      Extra_Power2( int Num );
+extern int         Extra_Power3( int Num );
+/* the number of combinations of k elements out of n */
+extern int         Extra_NumCombinations( int k, int n  );
+extern int *       Extra_DeriveRadixCode( int Number, int Radix, int nDigits );
+/* counts the number of 1s in the bitstring */
+extern int         Extra_CountOnes( unsigned char * pBytes, int nBytes );
+/* the factorial of number */
+extern int         Extra_Factorial( int n );
+/* the permutation of the given number of elements */
+extern char **     Extra_Permutations( int n );
+/* permutation and complementation of a truth table */
+unsigned           Extra_TruthPermute( unsigned Truth, char * pPerms, int nVars, int fReverse );
+unsigned           Extra_TruthPolarize( unsigned uTruth, int Polarity, int nVars );
+/* canonical forms of a truth table */
+extern unsigned    Extra_TruthCanonN( unsigned uTruth, int nVars );
+extern unsigned    Extra_TruthCanonNN( unsigned uTruth, int nVars );
+extern unsigned    Extra_TruthCanonP( unsigned uTruth, int nVars );
+extern unsigned    Extra_TruthCanonNP( unsigned uTruth, int nVars );
+extern unsigned    Extra_TruthCanonNPN( unsigned uTruth, int nVars );
+/* canonical forms of 4-variable functions */
+extern void        Extra_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap );
+extern void        Extra_Truth4VarN( unsigned short ** puCanons, char *** puPhases, char ** ppCounters, int nPhasesMax );
+/* permutation mapping */
+extern unsigned short Extra_TruthPerm4One( unsigned uTruth, int Phase );
+extern unsigned    Extra_TruthPerm5One( unsigned uTruth, int Phase );
+extern void        Extra_TruthPerm6One( unsigned * uTruth, int Phase, unsigned * uTruthRes );
+extern void        Extra_TruthExpand( int nVars, int nWords, unsigned * puTruth, unsigned uPhase, unsigned * puTruthR );
+/* precomputing tables for permutation mapping */
+extern void **     Extra_ArrayAlloc( int nCols, int nRows, int Size );
+extern unsigned short ** Extra_TruthPerm43();
+extern unsigned ** Extra_TruthPerm53();
+extern unsigned ** Extra_TruthPerm54();
+/* bubble sort for small number of entries */
+extern void        Extra_BubbleSort( int Order[], int Costs[], int nSize, int fIncreasing );
+/* complementation/permutation generation */
+extern int *       Extra_GreyCodeSchedule( int n );
+extern int *       Extra_PermSchedule( int n );
+extern word        Extra_Truth6MinimumExact( word t, int * pComp, int * pPerm );
+extern word        Extra_Truth6MinimumHeuristic( word t );
+
+/*=== extraUtilCanon.c ========================================================*/
+
+/* fast computation of N-canoninical form up to 6 inputs */
+extern int         Extra_TruthCanonFastN( int nVarsMax, int nVarsReal, unsigned * pt, unsigned ** pptRes, char ** ppfRes );
+
+/*=== extraUtilDsd.c ========================================================*/
+
+typedef struct Sdm_Man_t_ Sdm_Man_t; 
+extern int         Sdm_ManCanRead();
+extern Sdm_Man_t * Sdm_ManRead();
+extern void        Sdm_ManQuit();
+extern int         Sdm_ManComputeFunc( Sdm_Man_t * p, int iDsdLit0, int iDsdLit1, int * pCut, int uMask, int fXor );
+extern void        Sdm_ManPrintDsdStats( Sdm_Man_t * p, int fVerbose );
+extern int         Sdm_ManReadDsdVarNum( Sdm_Man_t * p, int iDsd );
+extern int         Sdm_ManReadDsdAndNum( Sdm_Man_t * p, int iDsd );
+extern int         Sdm_ManReadDsdClauseNum( Sdm_Man_t * p, int iDsd );
+extern word        Sdm_ManReadDsdTruth( Sdm_Man_t * p, int iDsd );
+extern char *      Sdm_ManReadDsdStr( Sdm_Man_t * p, int iDsd );
+extern void        Sdm_ManReadCnfCosts( Sdm_Man_t * p, int * pCosts, int nCosts );
+
+/*=== extraUtilProgress.c ================================================================*/
+
+typedef struct ProgressBarStruct ProgressBar;
+
+extern ProgressBar * Extra_ProgressBarStart( FILE * pFile, int nItemsTotal );
+extern void        Extra_ProgressBarStop( ProgressBar * p );
+extern void        Extra_ProgressBarUpdate_int( ProgressBar * p, int nItemsCur, char * pString );
+
+static inline void Extra_ProgressBarUpdate( ProgressBar * p, int nItemsCur, char * pString ) 
+{  if ( p && nItemsCur < *((int*)p) ) return; Extra_ProgressBarUpdate_int(p, nItemsCur, pString); }
+
+/*=== extraUtilTruth.c ================================================================*/
+
+static inline int   Extra_BitWordNum( int nBits )    { return nBits/(8*sizeof(unsigned)) + ((nBits%(8*sizeof(unsigned))) > 0);  }
+static inline int   Extra_TruthWordNum( int nVars )  { return nVars <= 5 ? 1 : (1 << (nVars - 5)); }
+
+static inline void  Extra_TruthSetBit( unsigned * p, int Bit )   { p[Bit>>5] |= (1<<(Bit & 31));               }
+static inline void  Extra_TruthXorBit( unsigned * p, int Bit )   { p[Bit>>5] ^= (1<<(Bit & 31));               }
+static inline int   Extra_TruthHasBit( unsigned * p, int Bit )   { return (p[Bit>>5] & (1<<(Bit & 31))) > 0;   }
+
+static inline int Extra_WordCountOnes( unsigned uWord )
+{
+    uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555);
+    uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333);
+    uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F);
+    uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF);
+    return  (uWord & 0x0000FFFF) + (uWord>>16);
+}
+static inline int Extra_TruthCountOnes( unsigned * pIn, int nVars )
+{
+    int w, Counter = 0;
+    for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+        Counter += Extra_WordCountOnes(pIn[w]);
+    return Counter;
+}
+static inline int Extra_TruthIsEqual( unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+    int w;
+    for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+        if ( pIn0[w] != pIn1[w] )
+            return 0;
+    return 1;
+}
+static inline int Extra_TruthIsConst0( unsigned * pIn, int nVars )
+{
+    int w;
+    for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+        if ( pIn[w] )
+            return 0;
+    return 1;
+}
+static inline int Extra_TruthIsConst1( unsigned * pIn, int nVars )
+{
+    int w;
+    for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+        if ( pIn[w] != ~(unsigned)0 )
+            return 0;
+    return 1;
+}
+static inline int Extra_TruthIsImply( unsigned * pIn1, unsigned * pIn2, int nVars )
+{
+    int w;
+    for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+        if ( pIn1[w] & ~pIn2[w] )
+            return 0;
+    return 1;
+}
+static inline void Extra_TruthCopy( unsigned * pOut, unsigned * pIn, int nVars )
+{
+    int w;
+    for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = pIn[w];
+}
+static inline void Extra_TruthClear( unsigned * pOut, int nVars )
+{
+    int w;
+    for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = 0;
+}
+static inline void Extra_TruthFill( unsigned * pOut, int nVars )
+{
+    int w;
+    for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = ~(unsigned)0;
+}
+static inline void Extra_TruthNot( unsigned * pOut, unsigned * pIn, int nVars )
+{
+    int w;
+    for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = ~pIn[w];
+}
+static inline void Extra_TruthAnd( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+    int w;
+    for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = pIn0[w] & pIn1[w];
+}
+static inline void Extra_TruthOr( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+    int w;
+    for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = pIn0[w] | pIn1[w];
+}
+static inline void Extra_TruthSharp( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+    int w;
+    for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = pIn0[w] & ~pIn1[w];
+}
+static inline void Extra_TruthNand( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+    int w;
+    for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = ~(pIn0[w] & pIn1[w]);
+}
+static inline void Extra_TruthAndPhase( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars, int fCompl0, int fCompl1 )
+{
+    int w;
+    if ( fCompl0 && fCompl1 )
+    {
+        for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+            pOut[w] = ~(pIn0[w] | pIn1[w]);
+    }
+    else if ( fCompl0 && !fCompl1 )
+    {
+        for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+            pOut[w] = ~pIn0[w] & pIn1[w];
+    }
+    else if ( !fCompl0 && fCompl1 )
+    {
+        for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+            pOut[w] = pIn0[w] & ~pIn1[w];
+    }
+    else // if ( !fCompl0 && !fCompl1 )
+    {
+        for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+            pOut[w] = pIn0[w] & pIn1[w];
+    }
+}
+
+extern unsigned ** Extra_TruthElementary( int nVars );
+extern void        Extra_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int Start );
+extern void        Extra_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase );
+extern void        Extra_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase );
+extern int         Extra_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar );
+extern int         Extra_TruthSupportSize( unsigned * pTruth, int nVars );
+extern int         Extra_TruthSupport( unsigned * pTruth, int nVars );
+extern void        Extra_TruthCofactor0( unsigned * pTruth, int nVars, int iVar );
+extern void        Extra_TruthCofactor1( unsigned * pTruth, int nVars, int iVar );
+extern void        Extra_TruthExist( unsigned * pTruth, int nVars, int iVar );
+extern void        Extra_TruthForall( unsigned * pTruth, int nVars, int iVar );
+extern void        Extra_TruthMux( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar );
+extern void        Extra_TruthChangePhase( unsigned * pTruth, int nVars, int iVar );
+extern int         Extra_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin );
+extern void        Extra_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore );
+extern unsigned    Extra_TruthHash( unsigned * pIn, int nWords );
+extern unsigned    Extra_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore );
+
+/*=== extraUtilUtil.c ================================================================*/
+
+extern abctime       Extra_CpuTime();
+extern double        Extra_CpuTimeDouble();
+extern int           Extra_GetSoftDataLimit();
+extern ABC_DLL void  Extra_UtilGetoptReset();
+extern int           Extra_UtilGetopt( int argc, char *argv[], const char *optstring );
+extern char *        Extra_UtilPrintTime( long t );
+extern char *        Extra_UtilStrsav( const char *s );
+extern char *        Extra_UtilTildeExpand( char *fname );
+extern char *        Extra_UtilFileSearch( char *file, char *path, char *mode );
+extern void          (*Extra_UtilMMoutOfMemory)( long size );
+
+extern const char *  globalUtilOptarg;
+extern int           globalUtilOptind;
+
+/**AutomaticEnd***************************************************************/
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif /* __EXTRA_H__ */
diff --git a/abc-build/src/misc/extra/extraBdd.h b/abc-build/src/misc/extra/extraBdd.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraBdd.h
@@ -0,0 +1,315 @@
+/**CFile****************************************************************
+
+  FileName    [extraBdd.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [extra]
+
+  Synopsis    [Various reusable software utilities.]
+
+  Description [This library contains a number of operators and 
+  traversal routines developed to extend the functionality of 
+  CUDD v.2.3.x, by Fabio Somenzi (http://vlsi.colorado.edu/~fabio/)
+  To compile your code with the library, #include "extra.h" 
+  in your source files and link your project to CUDD and this 
+  library. Use the library at your own risk and with caution. 
+  Note that debugging of some operators still continues.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: extraBdd.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__misc__extra__extra_bdd_h
+#define ABC__misc__extra__extra_bdd_h
+
+
+#ifdef _WIN32
+#define inline __inline // compatible with MS VS 6.0
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/st/st.h"
+#include "bdd/cudd/cuddInt.h"
+#include "misc/extra/extra.h"
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/* constants of the manager */
+#define     b0     Cudd_Not((dd)->one)
+#define     b1              (dd)->one
+#define     z0              (dd)->zero
+#define     z1              (dd)->one
+#define     a0              (dd)->zero
+#define     a1              (dd)->one
+
+// hash key macros
+#define hashKey1(a,TSIZE) \
+((ABC_PTRUINT_T)(a) % TSIZE)
+
+#define hashKey2(a,b,TSIZE) \
+(((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b) * DD_P1) % TSIZE)
+
+#define hashKey3(a,b,c,TSIZE) \
+(((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 ) % TSIZE)
+
+#define hashKey4(a,b,c,d,TSIZE) \
+((((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 + \
+   (ABC_PTRUINT_T)(d)) * DD_P3) % TSIZE)
+
+#define hashKey5(a,b,c,d,e,TSIZE) \
+(((((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 + \
+   (ABC_PTRUINT_T)(d)) * DD_P3 + (ABC_PTRUINT_T)(e)) * DD_P1) % TSIZE)
+
+/*===========================================================================*/
+/*     Various Utilities                                                     */
+/*===========================================================================*/
+
+/*=== extraBddAuto.c ========================================================*/
+
+extern DdNode *     Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc );
+extern DdNode *     Extra_bddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG );
+extern DdNode *      extraBddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG );
+extern DdNode *     Extra_bddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc );
+extern DdNode *      extraBddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc );
+extern DdNode *     Extra_bddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc );
+extern DdNode *      extraBddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc );
+
+extern DdNode *     Extra_bddSpaceCanonVars( DdManager * dd, DdNode * bSpace );
+extern DdNode *      extraBddSpaceCanonVars( DdManager * dd, DdNode * bSpace );
+
+extern DdNode *     Extra_bddSpaceEquations( DdManager * dd, DdNode * bSpace );
+extern DdNode *     Extra_bddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace );
+extern DdNode *      extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace );
+extern DdNode *     Extra_bddSpaceEquationsPos( DdManager * dd, DdNode * bSpace );
+extern DdNode *      extraBddSpaceEquationsPos( DdManager * dd, DdNode * bSpace );
+
+extern DdNode *     Extra_bddSpaceFromMatrixPos( DdManager * dd, DdNode * zA );
+extern DdNode *      extraBddSpaceFromMatrixPos( DdManager * dd, DdNode * zA );
+extern DdNode *     Extra_bddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA );
+extern DdNode *      extraBddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA );
+
+extern DdNode *     Extra_bddSpaceReduce( DdManager * dd, DdNode * bFunc, DdNode * bCanonVars );
+extern DdNode **    Extra_bddSpaceExorGates( DdManager * dd, DdNode * bFuncRed, DdNode * zEquations );
+
+/*=== extraBddCas.c =============================================================*/
+
+/* performs the binary encoding of the set of function using the given vars */
+extern DdNode *     Extra_bddEncodingBinary( DdManager * dd, DdNode ** pbFuncs, int nFuncs, DdNode ** pbVars, int nVars );
+/* solves the column encoding problem using a sophisticated method */
+extern DdNode *     Extra_bddEncodingNonStrict( DdManager * dd, DdNode ** pbColumns, int nColumns, DdNode * bVarsCol, DdNode ** pCVars, int nMulti, int * pSimple );
+/* collects the nodes under the cut and, for each node, computes the sum of paths leading to it from the root */
+extern st__table *   Extra_bddNodePathsUnderCut( DdManager * dd, DdNode * bFunc, int CutLevel );
+/* collects the nodes under the cut starting from the given set of ADD nodes */
+extern int          Extra_bddNodePathsUnderCutArray( DdManager * dd, DdNode ** paNodes, DdNode ** pbCubes, int nNodes, DdNode ** paNodesRes, DdNode ** pbCubesRes, int CutLevel );
+/* find the profile of a DD (the number of edges crossing each level) */
+extern int          Extra_ProfileWidth( DdManager * dd, DdNode * F, int * Profile, int CutLevel );
+
+/*=== extraBddImage.c ================================================================*/
+
+typedef struct Extra_ImageTree_t_  Extra_ImageTree_t;
+extern Extra_ImageTree_t * Extra_bddImageStart( 
+    DdManager * dd, DdNode * bCare,
+    int nParts, DdNode ** pbParts,
+    int nVars, DdNode ** pbVars, int fVerbose );
+extern DdNode *    Extra_bddImageCompute( Extra_ImageTree_t * pTree, DdNode * bCare );
+extern void        Extra_bddImageTreeDelete( Extra_ImageTree_t * pTree );
+extern DdNode *    Extra_bddImageRead( Extra_ImageTree_t * pTree );
+
+typedef struct Extra_ImageTree2_t_  Extra_ImageTree2_t;
+extern Extra_ImageTree2_t * Extra_bddImageStart2( 
+    DdManager * dd, DdNode * bCare,
+    int nParts, DdNode ** pbParts,
+    int nVars, DdNode ** pbVars, int fVerbose );
+extern DdNode *    Extra_bddImageCompute2( Extra_ImageTree2_t * pTree, DdNode * bCare );
+extern void        Extra_bddImageTreeDelete2( Extra_ImageTree2_t * pTree );
+extern DdNode *    Extra_bddImageRead2( Extra_ImageTree2_t * pTree );
+
+/*=== extraBddMisc.c ========================================================*/
+
+extern DdNode *     Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute );
+extern DdNode *     Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f );
+extern DdNode *     Extra_bddRemapUp( DdManager * dd, DdNode * bF );
+extern DdNode *     Extra_bddMove( DdManager * dd, DdNode * bF, int nVars );
+extern DdNode *     extraBddMove( DdManager * dd, DdNode * bF, DdNode * bFlag );
+extern void         Extra_StopManager( DdManager * dd );
+extern void         Extra_bddPrint( DdManager * dd, DdNode * F );
+extern void         Extra_bddPrintSupport( DdManager * dd, DdNode * F );
+extern void         extraDecomposeCover( DdManager* dd, DdNode*  zC, DdNode** zC0, DdNode** zC1, DdNode** zC2 );
+extern int          Extra_bddSuppSize( DdManager * dd, DdNode * bSupp );
+extern int          Extra_bddSuppContainVar( DdManager * dd, DdNode * bS, DdNode * bVar );
+extern int          Extra_bddSuppOverlapping( DdManager * dd, DdNode * S1, DdNode * S2 );
+extern int          Extra_bddSuppDifferentVars( DdManager * dd, DdNode * S1, DdNode * S2, int DiffMax );
+extern int          Extra_bddSuppCheckContainment( DdManager * dd, DdNode * bL, DdNode * bH, DdNode ** bLarge, DdNode ** bSmall );
+extern int *        Extra_SupportArray( DdManager * dd, DdNode * F, int * support );
+extern int *        Extra_VectorSupportArray( DdManager * dd, DdNode ** F, int n, int * support );
+extern DdNode *     Extra_bddFindOneCube( DdManager * dd, DdNode * bF );
+extern DdNode *     Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc );
+extern DdNode *     Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop );
+extern DdNode *     Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst );
+extern DdNode *     Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f );
+extern int          Extra_bddIsVar( DdNode * bFunc );
+extern DdNode *     Extra_bddCreateAnd( DdManager * dd, int nVars );
+extern DdNode *     Extra_bddCreateOr( DdManager * dd, int nVars );
+extern DdNode *     Extra_bddCreateExor( DdManager * dd, int nVars );
+extern DdNode *     Extra_zddPrimes( DdManager * dd, DdNode * F );
+extern void         Extra_bddPermuteArray( DdManager * dd, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut );
+extern DdNode *     Extra_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars );
+extern DdNode *     Extra_bddChangePolarity( DdManager * dd, DdNode * bFunc, DdNode * bVars );
+extern DdNode *     extraBddChangePolarity( DdManager * dd, DdNode * bFunc, DdNode * bVars );
+extern int          Extra_bddVarIsInCube( DdNode * bCube, int iVar );
+extern DdNode *     Extra_bddAndPermute( DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute );
+
+#ifndef ABC_PRB
+#define ABC_PRB(dd,f)       printf("%s = ", #f); Extra_bddPrint(dd,f); printf("\n")
+#endif
+
+/*=== extraBddKmap.c ================================================================*/
+
+/* displays the Karnaugh Map of a function */
+extern void        Extra_PrintKMap( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nVars, DdNode ** XVars, int fSuppType, char ** pVarNames );
+/* displays the Karnaugh Map of a relation */
+extern void        Extra_PrintKMapRelation( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nXVars, int nYVars, DdNode ** XVars, DdNode ** YVars );
+
+/*=== extraBddSymm.c =================================================================*/
+
+typedef struct Extra_SymmInfo_t_  Extra_SymmInfo_t;
+struct Extra_SymmInfo_t_ {
+    int nVars;      // the number of variables in the support
+    int nVarsMax;   // the number of variables in the DD manager
+    int nSymms;     // the number of pair-wise symmetries
+    int nNodes;     // the number of nodes in a ZDD (if applicable)
+    int * pVars;    // the list of all variables present in the support
+    char ** pSymms; // the symmetry information
+};
+
+/* computes the classical symmetry information for the function - recursive */
+extern Extra_SymmInfo_t *  Extra_SymmPairsCompute( DdManager * dd, DdNode * bFunc );
+/* computes the classical symmetry information for the function - using naive approach */
+extern Extra_SymmInfo_t *  Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc );
+extern int         Extra_bddCheckVarsSymmetricNaive( DdManager * dd, DdNode * bF, int iVar1, int iVar2 );
+
+/* allocates the data structure */
+extern Extra_SymmInfo_t *  Extra_SymmPairsAllocate( int nVars );
+/* deallocates the data structure */
+extern void        Extra_SymmPairsDissolve( Extra_SymmInfo_t * );
+/* print the contents the data structure */
+extern void        Extra_SymmPairsPrint( Extra_SymmInfo_t * );
+/* converts the ZDD into the Extra_SymmInfo_t structure */
+extern Extra_SymmInfo_t *  Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bVars );
+
+/* computes the classical symmetry information as a ZDD */
+extern DdNode *    Extra_zddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars );
+extern DdNode *     extraZddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars );
+/* returns a singleton-set ZDD containing all variables that are symmetric with the given one */
+extern DdNode *    Extra_zddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars );
+extern DdNode *     extraZddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars );
+/* converts a set of variables into a set of singleton subsets */
+extern DdNode *    Extra_zddGetSingletons( DdManager * dd, DdNode * bVars );
+extern DdNode *     extraZddGetSingletons( DdManager * dd, DdNode * bVars );
+/* filters the set of variables using the support of the function */
+extern DdNode *    Extra_bddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF );
+extern DdNode *     extraBddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF );
+
+/* checks the possibility that the two vars are symmetric */
+extern int         Extra_bddCheckVarsSymmetric( DdManager * dd, DdNode * bF, int iVar1, int iVar2 );
+extern DdNode *     extraBddCheckVarsSymmetric( DdManager * dd, DdNode * bF, DdNode * bVars );
+
+/* build the set of all tuples of K variables out of N from the BDD cube */
+extern DdNode *    Extra_zddTuplesFromBdd( DdManager * dd, int K, DdNode * bVarsN );
+extern DdNode *     extraZddTuplesFromBdd( DdManager * dd, DdNode * bVarsK, DdNode * bVarsN );
+/* selects one subset from a ZDD representing the set of subsets */
+extern DdNode *    Extra_zddSelectOneSubset( DdManager * dd, DdNode * zS );
+extern DdNode *     extraZddSelectOneSubset( DdManager * dd, DdNode * zS );
+
+/*=== extraBddUnate.c =================================================================*/
+
+extern DdNode *    Extra_bddAndTime( DdManager * dd, DdNode * f, DdNode * g, int TimeOut );
+extern DdNode *    Extra_bddAndAbstractTime( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube, int TimeOut );
+extern DdNode *    Extra_TransferPermuteTime( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute, int TimeOut );
+
+/*=== extraBddUnate.c =================================================================*/
+
+typedef struct Extra_UnateVar_t_  Extra_UnateVar_t;
+struct Extra_UnateVar_t_ {
+    unsigned    iVar : 30;  // index of the variable
+    unsigned    Pos  :  1;  // 1 if positive unate
+    unsigned    Neg  :  1;  // 1 if negative unate
+};
+
+typedef struct Extra_UnateInfo_t_  Extra_UnateInfo_t;
+struct Extra_UnateInfo_t_ {
+    int nVars;      // the number of variables in the support
+    int nVarsMax;   // the number of variables in the DD manager
+    int nUnate;     // the number of unate variables
+    Extra_UnateVar_t * pVars;    // the array of variables present in the support
+};
+
+/* allocates the data structure */
+extern Extra_UnateInfo_t *  Extra_UnateInfoAllocate( int nVars );
+/* deallocates the data structure */
+extern void        Extra_UnateInfoDissolve( Extra_UnateInfo_t * );
+/* print the contents the data structure */
+extern void        Extra_UnateInfoPrint( Extra_UnateInfo_t * );
+/* converts the ZDD into the Extra_SymmInfo_t structure */
+extern Extra_UnateInfo_t *  Extra_UnateInfoCreateFromZdd( DdManager * dd, DdNode * zUnate, DdNode * bVars );
+/* naive check of unateness of one variable */
+extern int         Extra_bddCheckUnateNaive( DdManager * dd, DdNode * bF, int iVar );
+
+/* computes the unateness information for the function */
+extern Extra_UnateInfo_t *  Extra_UnateComputeFast( DdManager * dd, DdNode * bFunc );
+extern Extra_UnateInfo_t *  Extra_UnateComputeSlow( DdManager * dd, DdNode * bFunc );
+
+/* computes the classical symmetry information as a ZDD */
+extern DdNode *    Extra_zddUnateInfoCompute( DdManager * dd, DdNode * bF, DdNode * bVars );
+extern DdNode *     extraZddUnateInfoCompute( DdManager * dd, DdNode * bF, DdNode * bVars );
+
+/* converts a set of variables into a set of singleton subsets */
+extern DdNode *    Extra_zddGetSingletonsBoth( DdManager * dd, DdNode * bVars );
+extern DdNode *     extraZddGetSingletonsBoth( DdManager * dd, DdNode * bVars );
+
+/**AutomaticEnd***************************************************************/
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif /* __EXTRA_H__ */
diff --git a/abc-build/src/misc/extra/extraBddAuto.c b/abc-build/src/misc/extra/extraBddAuto.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraBddAuto.c
@@ -0,0 +1,1563 @@
+/**CFile****************************************************************
+
+  FileName    [extraBddAuto.c]
+
+  PackageName [extra]
+
+  Synopsis    [Computation of autosymmetries.]
+
+  Author      [Alan Mishchenko]
+
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - September 1, 2003.]
+
+  Revision    [$Id: extraBddAuto.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+
+/*
+    LinearSpace(f) = Space(f,f)
+
+    Space(f,g)
+	{
+		if ( f = const )
+		{ 
+		    if ( f = g )  return 1;
+			else          return 0;
+		}
+		if ( g = const )  return 0;
+		return x' * Space(fx',gx') * Space(fx,gx) + x * Space(fx',gx) * Space(fx,gx');
+	}
+
+	Equations(s) = Pos(s) + Neg(s);
+
+	Pos(s)
+	{
+		if ( s  = 0 )   return 1;
+		if ( s  = 1 )   return 0;
+		if ( sx'= 0 )   return Pos(sx) + x;
+		if ( sx = 0 )   return Pos(sx');
+		return 1 * [Pos(sx') & Pos(sx)] + x * [Pos(sx') & Neg(sx)];
+	}
+
+	Neg(s)
+	{
+		if ( s  = 0 )   return 1;
+		if ( s  = 1 )   return 0;
+		if ( sx'= 0 )   return Neg(sx);
+		if ( sx = 0 )   return Neg(sx') + x;
+		return 1 * [Neg(sx') & Neg(sx)] + x * [Neg(sx') & Pos(sx)];
+	}
+
+
+    SpaceP(A)
+	{
+		if ( A = 0 )    return 1;
+		if ( A = 1 )    return 1;
+		return x' * SpaceP(Ax') * SpaceP(Ax) + x * SpaceP(Ax') * SpaceN(Ax);
+	}
+
+    SpaceN(A)
+	{
+		if ( A = 0 )    return 1;
+		if ( A = 1 )    return 0;
+		return x' * SpaceN(Ax') * SpaceN(Ax) + x * SpaceN(Ax') * SpaceP(Ax);
+	}
+
+
+    LinInd(A)
+	{
+		if ( A = const )     return 1;
+		if ( !LinInd(Ax') )  return 0;
+		if ( !LinInd(Ax)  )  return 0;
+		if (  LinSumOdd(Ax')  & LinSumEven(Ax) != 0 )  return 0;
+		if (  LinSumEven(Ax') & LinSumEven(Ax) != 0 )  return 0;
+		return 1;
+	}
+
+	LinSumOdd(A)
+	{
+		if ( A = 0 )    return 0;                 // Odd0  ---e-- Odd1
+		if ( A = 1 )    return 1;                 //       \   o
+		Odd0  = LinSumOdd(Ax');  // x is absent   //         \ 
+		Even0 = LinSumEven(Ax'); // x is absent   //       /   o  
+		Odd1  = LinSumOdd(Ax);   // x is present  // Even0 ---e-- Even1 
+		Even1 = LinSumEven(Ax);  // x is absent
+		return 1 * [Odd0 + ExorP(Odd0, Even1)] + x * [Odd1 + ExorP(Odd1, Even0)];
+	}
+
+	LinSumEven(A)
+	{
+		if ( A = 0 )    return 0;
+		if ( A = 1 )    return 0;
+		Odd0  = LinSumOdd(Ax');  // x is absent
+		Even0 = LinSumEven(Ax'); // x is absent
+		Odd1  = LinSumOdd(Ax);   // x is present
+		Even1 = LinSumEven(Ax);  // x is absent
+		return 1 * [Even0 + Even1 + ExorP(Even0, Even1)] + x * [ExorP(Odd0, Odd1)];
+	}
+	
+*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc )
+{
+	int * pSupport;
+	int * pPermute;
+	int * pPermuteBack;
+	DdNode ** pCompose;
+	DdNode * bCube, * bTemp;
+	DdNode * bSpace, * bFunc1, * bFunc2, * bSpaceShift;
+	int nSupp, Counter;
+	int i, lev;
+
+	// get the support
+	pSupport = ABC_ALLOC( int, ddMax(dd->size,dd->sizeZ) );
+	Extra_SupportArray( dd, bFunc, pSupport );
+	nSupp = 0;
+	for ( i = 0; i < dd->size; i++ )
+		if ( pSupport[i] )
+			nSupp++;
+
+	// make sure the manager has enough variables
+	if ( 2*nSupp > dd->size )
+	{
+		printf( "Cannot derive linear space, because DD manager does not have enough variables.\n" );
+		fflush( stdout );
+		ABC_FREE( pSupport );
+		return NULL;
+	}
+
+	// create the permutation arrays
+	pPermute     = ABC_ALLOC( int, dd->size );
+	pPermuteBack = ABC_ALLOC( int, dd->size );
+	pCompose     = ABC_ALLOC( DdNode *, dd->size );
+	for ( i = 0; i < dd->size; i++ )
+	{
+		pPermute[i]     = i;
+		pPermuteBack[i] = i;
+		pCompose[i]     = dd->vars[i];   Cudd_Ref( pCompose[i] );
+	}
+
+	// remap the function in such a way that the variables are interleaved
+	Counter = 0;
+	bCube = b1;  Cudd_Ref( bCube );
+	for ( lev = 0; lev < dd->size; lev++ )
+		if ( pSupport[ dd->invperm[lev] ] )
+		{   // var "dd->invperm[lev]" on level "lev" should go to level 2*Counter;
+			pPermute[ dd->invperm[lev] ] = dd->invperm[2*Counter];
+			// var from level 2*Counter+1 should go back to the place of this var
+			pPermuteBack[ dd->invperm[2*Counter+1] ] = dd->invperm[lev];
+			// the permutation should be defined in such a way that variable
+			// on level 2*Counter is replaced by an EXOR of itself and var on the next level
+			Cudd_Deref( pCompose[ dd->invperm[2*Counter] ] );
+			pCompose[ dd->invperm[2*Counter] ] = 
+				Cudd_bddXor( dd, dd->vars[ dd->invperm[2*Counter] ], dd->vars[ dd->invperm[2*Counter+1] ] );  
+			Cudd_Ref( pCompose[ dd->invperm[2*Counter] ] );
+			// add this variable to the cube
+			bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[ dd->invperm[2*Counter] ] );  Cudd_Ref( bCube );
+			Cudd_RecursiveDeref( dd, bTemp );
+			// increment the counter
+			Counter ++;
+		}
+
+	// permute the functions
+	bFunc1 = Cudd_bddPermute( dd, bFunc, pPermute );         Cudd_Ref( bFunc1 );
+	// compose to gate the function depending on both vars
+	bFunc2 = Cudd_bddVectorCompose( dd, bFunc1, pCompose );  Cudd_Ref( bFunc2 );
+	// gate the vector space
+	// L(a) = ForAll x [ F(x) = F(x+a) ] = Not( Exist x [ F(x) (+) F(x+a) ] )
+	bSpaceShift = Cudd_bddXorExistAbstract( dd, bFunc1, bFunc2, bCube );  Cudd_Ref( bSpaceShift );
+	bSpaceShift = Cudd_Not( bSpaceShift );
+	// permute the space back into the original mapping
+	bSpace = Cudd_bddPermute( dd, bSpaceShift, pPermuteBack ); Cudd_Ref( bSpace );
+	Cudd_RecursiveDeref( dd, bFunc1 );
+	Cudd_RecursiveDeref( dd, bFunc2 );
+	Cudd_RecursiveDeref( dd, bSpaceShift );
+	Cudd_RecursiveDeref( dd, bCube );
+
+	for ( i = 0; i < dd->size; i++ )
+		Cudd_RecursiveDeref( dd, pCompose[i] );
+	ABC_FREE( pPermute );
+	ABC_FREE( pPermuteBack );
+	ABC_FREE( pCompose );
+    ABC_FREE( pSupport );
+
+	Cudd_Deref( bSpace );
+	return bSpace;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG )
+{
+    DdNode * bRes;
+    do {
+		dd->reordered = 0;
+		bRes = extraBddSpaceFromFunction( dd, bF, bG );
+    } while (dd->reordered == 1);
+    return bRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc )
+{
+    DdNode * bRes;
+    do {
+		dd->reordered = 0;
+		bRes = extraBddSpaceFromFunctionPos( dd, bFunc );
+    } while (dd->reordered == 1);
+    return bRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc )
+{
+    DdNode * bRes;
+    do {
+		dd->reordered = 0;
+		bRes = extraBddSpaceFromFunctionNeg( dd, bFunc );
+    } while (dd->reordered == 1);
+    return bRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceCanonVars( DdManager * dd, DdNode * bSpace )
+{
+    DdNode * bRes;
+    do {
+		dd->reordered = 0;
+		bRes = extraBddSpaceCanonVars( dd, bSpace );
+    } while (dd->reordered == 1);
+    return bRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceReduce( DdManager * dd, DdNode * bFunc, DdNode * bCanonVars )
+{
+	DdNode * bNegCube;
+	DdNode * bResult;
+	bNegCube = Extra_bddSupportNegativeCube( dd, bCanonVars );  Cudd_Ref( bNegCube );
+	bResult  = Cudd_Cofactor( dd, bFunc, bNegCube );            Cudd_Ref( bResult );
+	Cudd_RecursiveDeref( dd, bNegCube );
+	Cudd_Deref( bResult );
+	return bResult;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceEquations( DdManager * dd, DdNode * bSpace )
+{
+    DdNode * zRes;
+	DdNode * zEquPos;
+	DdNode * zEquNeg;
+	zEquPos = Extra_bddSpaceEquationsPos( dd, bSpace );  Cudd_Ref( zEquPos );
+	zEquNeg = Extra_bddSpaceEquationsNeg( dd, bSpace );  Cudd_Ref( zEquNeg );
+	zRes    = Cudd_zddUnion( dd, zEquPos, zEquNeg );     Cudd_Ref( zRes );
+	Cudd_RecursiveDerefZdd( dd, zEquPos );
+	Cudd_RecursiveDerefZdd( dd, zEquNeg );
+	Cudd_Deref( zRes );
+    return zRes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceEquationsPos( DdManager * dd, DdNode * bSpace )
+{
+    DdNode * zRes;
+    do {
+		dd->reordered = 0;
+		zRes = extraBddSpaceEquationsPos( dd, bSpace );
+    } while (dd->reordered == 1);
+    return zRes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace )
+{
+    DdNode * zRes;
+    do {
+		dd->reordered = 0;
+		zRes = extraBddSpaceEquationsNeg( dd, bSpace );
+    } while (dd->reordered == 1);
+    return zRes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromMatrixPos( DdManager * dd, DdNode * zA )
+{
+    DdNode * bRes;
+    do {
+		dd->reordered = 0;
+		bRes = extraBddSpaceFromMatrixPos( dd, zA );
+    } while (dd->reordered == 1);
+    return bRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA )
+{
+    DdNode * bRes;
+    do {
+		dd->reordered = 0;
+		bRes = extraBddSpaceFromMatrixNeg( dd, zA );
+    } while (dd->reordered == 1);
+    return bRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of literals in one combination.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_zddLitCountComb( DdManager * dd, DdNode * zComb )
+{
+	int Counter;
+	if ( zComb == z0 )
+		return 0;
+	Counter = 0;
+	for ( ; zComb != z1; zComb = cuddT(zComb) )
+		Counter++;
+	return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description [Returns the array of ZDDs with the number equal to the number of 
+  vars in the DD manager. If the given var is non-canonical, this array contains
+  the referenced ZDD representing literals in the corresponding EXOR equation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode ** Extra_bddSpaceExorGates( DdManager * dd, DdNode * bFuncRed, DdNode * zEquations )
+{
+	DdNode ** pzRes;
+	int * pVarsNonCan;
+	DdNode * zEquRem;
+	int iVarNonCan;
+	DdNode * zExor, * zTemp;
+
+	// get the set of non-canonical variables
+	pVarsNonCan = ABC_ALLOC( int, ddMax(dd->size,dd->sizeZ) );
+	Extra_SupportArray( dd, bFuncRed, pVarsNonCan );
+
+	// allocate storage for the EXOR sets
+	pzRes = ABC_ALLOC( DdNode *, dd->size );
+	memset( pzRes, 0, sizeof(DdNode *) * dd->size );
+
+	// go through all the equations
+	zEquRem = zEquations;  Cudd_Ref( zEquRem );
+	while ( zEquRem != z0 )
+	{
+		// extract one product
+		zExor = Extra_zddSelectOneSubset( dd, zEquRem );   Cudd_Ref( zExor );
+		// remove it from the set
+		zEquRem = Cudd_zddDiff( dd, zTemp = zEquRem, zExor );  Cudd_Ref( zEquRem );
+		Cudd_RecursiveDerefZdd( dd, zTemp );
+
+		// locate the non-canonical variable
+		iVarNonCan = -1;
+		for ( zTemp = zExor; zTemp != z1; zTemp = cuddT(zTemp) )
+		{
+			if ( pVarsNonCan[zTemp->index/2] == 1 )
+			{
+				assert( iVarNonCan == -1 );
+				iVarNonCan = zTemp->index/2;
+			}
+		}
+		assert( iVarNonCan != -1 );
+
+		if ( Extra_zddLitCountComb( dd, zExor ) > 1 )
+			pzRes[ iVarNonCan ] = zExor; // takes ref
+		else
+			Cudd_RecursiveDerefZdd( dd, zExor );
+	}
+	Cudd_RecursiveDerefZdd( dd, zEquRem );
+
+	ABC_FREE( pVarsNonCan );
+	return pzRes;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive steps of Extra_bddSpaceFromFunction.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * extraBddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG )
+{
+	DdNode * bRes;
+	DdNode * bFR, * bGR;
+
+	bFR = Cudd_Regular( bF ); 
+	bGR = Cudd_Regular( bG ); 
+	if ( cuddIsConstant(bFR) )
+	{
+		if ( bF == bG )
+			return b1;
+		else 
+			return b0;
+	}
+	if ( cuddIsConstant(bGR) )
+		return b0;
+	// both bFunc and bCore are not constants
+
+	// the operation is commutative - normalize the problem
+	if ( (unsigned)(ABC_PTRUINT_T)bF > (unsigned)(ABC_PTRUINT_T)bG )
+		return extraBddSpaceFromFunction(dd, bG, bF);
+
+
+    if ( (bRes = cuddCacheLookup2(dd, extraBddSpaceFromFunction, bF, bG)) )
+    	return bRes;
+	else
+	{
+		DdNode * bF0, * bF1;
+		DdNode * bG0, * bG1;
+		DdNode * bTemp1, * bTemp2;
+		DdNode * bRes0, * bRes1;
+		int LevelF, LevelG;
+		int index;
+
+		LevelF = dd->perm[bFR->index];
+		LevelG = dd->perm[bGR->index];
+		if ( LevelF <= LevelG )
+		{
+			index = dd->invperm[LevelF];
+			if ( bFR != bF )
+			{
+				bF0 = Cudd_Not( cuddE(bFR) );
+				bF1 = Cudd_Not( cuddT(bFR) );
+			}
+			else
+			{
+				bF0 = cuddE(bFR);
+				bF1 = cuddT(bFR);
+			}
+		}
+		else
+		{
+			index = dd->invperm[LevelG];
+			bF0 = bF1 = bF;
+		}
+
+		if ( LevelG <= LevelF )
+		{
+			if ( bGR != bG )
+			{
+				bG0 = Cudd_Not( cuddE(bGR) );
+				bG1 = Cudd_Not( cuddT(bGR) );
+			}
+			else
+			{
+				bG0 = cuddE(bGR);
+				bG1 = cuddT(bGR);
+			}
+		}
+		else
+			bG0 = bG1 = bG;
+
+		bTemp1 = extraBddSpaceFromFunction( dd, bF0, bG0 );
+		if ( bTemp1 == NULL ) 
+			return NULL;
+		cuddRef( bTemp1 );
+
+		bTemp2 = extraBddSpaceFromFunction( dd, bF1, bG1 );
+		if ( bTemp2 == NULL ) 
+		{
+			Cudd_RecursiveDeref( dd, bTemp1 );
+			return NULL;
+		}
+		cuddRef( bTemp2 );
+
+
+		bRes0  = cuddBddAndRecur( dd, bTemp1, bTemp2 );
+		if ( bRes0 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bTemp1 );
+			Cudd_RecursiveDeref( dd, bTemp2 );
+			return NULL;
+		}
+		cuddRef( bRes0 );
+		Cudd_RecursiveDeref( dd, bTemp1 );
+		Cudd_RecursiveDeref( dd, bTemp2 );
+
+
+		bTemp1  = extraBddSpaceFromFunction( dd, bF0, bG1 );
+		if ( bTemp1 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bRes0 );
+			return NULL;
+		}
+		cuddRef( bTemp1 );
+
+		bTemp2  = extraBddSpaceFromFunction( dd, bF1, bG0 );
+		if ( bTemp2 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bRes0 );
+			Cudd_RecursiveDeref( dd, bTemp1 );
+			return NULL;
+		}
+		cuddRef( bTemp2 );
+
+		bRes1  = cuddBddAndRecur( dd, bTemp1, bTemp2 );
+		if ( bRes1 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bRes0 );
+			Cudd_RecursiveDeref( dd, bTemp1 );
+			Cudd_RecursiveDeref( dd, bTemp2 );
+			return NULL;
+		}
+		cuddRef( bRes1 );
+		Cudd_RecursiveDeref( dd, bTemp1 );
+		Cudd_RecursiveDeref( dd, bTemp2 );
+
+
+
+		// consider the case when Res0 and Res1 are the same node 
+		if ( bRes0 == bRes1 )
+			bRes = bRes1;
+		// consider the case when Res1 is complemented 
+		else if ( Cudd_IsComplement(bRes1) ) 
+		{
+			bRes = cuddUniqueInter(dd, index, Cudd_Not(bRes1), Cudd_Not(bRes0));
+			if ( bRes == NULL ) 
+			{
+				Cudd_RecursiveDeref(dd,bRes0);
+				Cudd_RecursiveDeref(dd,bRes1);
+				return NULL;
+			}
+			bRes = Cudd_Not(bRes);
+		} 
+		else 
+		{
+			bRes = cuddUniqueInter( dd, index, bRes1, bRes0 );
+			if ( bRes == NULL ) 
+			{
+				Cudd_RecursiveDeref(dd,bRes0);
+				Cudd_RecursiveDeref(dd,bRes1);
+				return NULL;
+			}
+		}
+		cuddDeref( bRes0 );
+		cuddDeref( bRes1 );
+			
+		// insert the result into cache 
+		cuddCacheInsert2(dd, extraBddSpaceFromFunction, bF, bG, bRes);
+		return bRes;
+	}
+}  /* end of extraBddSpaceFromFunction */
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs the recursive step of Extra_bddSpaceFromFunctionPos().]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * extraBddSpaceFromFunctionPos( DdManager * dd, DdNode * bF )
+{
+	DdNode * bRes, * bFR;
+	statLine( dd );
+
+	bFR = Cudd_Regular(bF);
+	if ( cuddIsConstant(bFR) )
+		return b1;
+
+    if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromFunctionPos, bF)) )
+    	return bRes;
+	else
+	{
+		DdNode * bF0,   * bF1;
+		DdNode * bPos0, * bPos1;
+		DdNode * bNeg0, * bNeg1;
+		DdNode * bRes0, * bRes1; 
+
+		if ( bFR != bF ) // bF is complemented 
+		{
+			bF0 = Cudd_Not( cuddE(bFR) );
+			bF1 = Cudd_Not( cuddT(bFR) );
+		}
+		else
+		{
+			bF0 = cuddE(bFR);
+			bF1 = cuddT(bFR);
+		}
+
+
+		bPos0  = extraBddSpaceFromFunctionPos( dd, bF0 );
+		if ( bPos0 == NULL )
+			return NULL;
+		cuddRef( bPos0 );
+
+		bPos1  = extraBddSpaceFromFunctionPos( dd, bF1 );
+		if ( bPos1 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bPos0 );
+			return NULL;
+		}
+		cuddRef( bPos1 );
+
+		bRes0  = cuddBddAndRecur( dd, bPos0, bPos1 );
+		if ( bRes0 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bPos0 );
+			Cudd_RecursiveDeref( dd, bPos1 );
+			return NULL;
+		}
+		cuddRef( bRes0 );
+		Cudd_RecursiveDeref( dd, bPos0 );
+		Cudd_RecursiveDeref( dd, bPos1 );
+
+
+		bNeg0  = extraBddSpaceFromFunctionNeg( dd, bF0 );
+		if ( bNeg0 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bRes0 );
+			return NULL;
+		}
+		cuddRef( bNeg0 );
+
+		bNeg1  = extraBddSpaceFromFunctionNeg( dd, bF1 );
+		if ( bNeg1 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bRes0 );
+			Cudd_RecursiveDeref( dd, bNeg0 );
+			return NULL;
+		}
+		cuddRef( bNeg1 );
+
+		bRes1  = cuddBddAndRecur( dd, bNeg0, bNeg1 );
+		if ( bRes1 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bRes0 );
+			Cudd_RecursiveDeref( dd, bNeg0 );
+			Cudd_RecursiveDeref( dd, bNeg1 );
+			return NULL;
+		}
+		cuddRef( bRes1 );
+		Cudd_RecursiveDeref( dd, bNeg0 );
+		Cudd_RecursiveDeref( dd, bNeg1 );
+
+
+		// consider the case when Res0 and Res1 are the same node 
+		if ( bRes0 == bRes1 )
+			bRes = bRes1;
+		// consider the case when Res1 is complemented 
+		else if ( Cudd_IsComplement(bRes1) ) 
+		{
+			bRes = cuddUniqueInter( dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0) );
+			if ( bRes == NULL ) 
+			{
+				Cudd_RecursiveDeref(dd,bRes0);
+				Cudd_RecursiveDeref(dd,bRes1);
+				return NULL;
+			}
+			bRes = Cudd_Not(bRes);
+		} 
+		else 
+		{
+			bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 );
+			if ( bRes == NULL ) 
+			{
+				Cudd_RecursiveDeref(dd,bRes0);
+				Cudd_RecursiveDeref(dd,bRes1);
+				return NULL;
+			}
+		}
+		cuddDeref( bRes0 );
+		cuddDeref( bRes1 );
+
+		cuddCacheInsert1( dd, extraBddSpaceFromFunctionPos, bF, bRes );
+		return bRes;
+	}
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs the recursive step of Extra_bddSpaceFromFunctionPos().]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * extraBddSpaceFromFunctionNeg( DdManager * dd, DdNode * bF )
+{
+	DdNode * bRes, * bFR;
+	statLine( dd );
+
+	bFR = Cudd_Regular(bF);
+	if ( cuddIsConstant(bFR) )
+		return b0;
+
+    if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromFunctionNeg, bF)) )
+    	return bRes;
+	else
+	{
+		DdNode * bF0,   * bF1;
+		DdNode * bPos0, * bPos1;
+		DdNode * bNeg0, * bNeg1;
+		DdNode * bRes0, * bRes1; 
+
+		if ( bFR != bF ) // bF is complemented 
+		{
+			bF0 = Cudd_Not( cuddE(bFR) );
+			bF1 = Cudd_Not( cuddT(bFR) );
+		}
+		else
+		{
+			bF0 = cuddE(bFR);
+			bF1 = cuddT(bFR);
+		}
+
+
+		bPos0  = extraBddSpaceFromFunctionNeg( dd, bF0 );
+		if ( bPos0 == NULL )
+			return NULL;
+		cuddRef( bPos0 );
+
+		bPos1  = extraBddSpaceFromFunctionNeg( dd, bF1 );
+		if ( bPos1 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bPos0 );
+			return NULL;
+		}
+		cuddRef( bPos1 );
+
+		bRes0  = cuddBddAndRecur( dd, bPos0, bPos1 );
+		if ( bRes0 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bPos0 );
+			Cudd_RecursiveDeref( dd, bPos1 );
+			return NULL;
+		}
+		cuddRef( bRes0 );
+		Cudd_RecursiveDeref( dd, bPos0 );
+		Cudd_RecursiveDeref( dd, bPos1 );
+
+
+		bNeg0  = extraBddSpaceFromFunctionPos( dd, bF0 );
+		if ( bNeg0 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bRes0 );
+			return NULL;
+		}
+		cuddRef( bNeg0 );
+
+		bNeg1  = extraBddSpaceFromFunctionPos( dd, bF1 );
+		if ( bNeg1 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bRes0 );
+			Cudd_RecursiveDeref( dd, bNeg0 );
+			return NULL;
+		}
+		cuddRef( bNeg1 );
+
+		bRes1  = cuddBddAndRecur( dd, bNeg0, bNeg1 );
+		if ( bRes1 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bRes0 );
+			Cudd_RecursiveDeref( dd, bNeg0 );
+			Cudd_RecursiveDeref( dd, bNeg1 );
+			return NULL;
+		}
+		cuddRef( bRes1 );
+		Cudd_RecursiveDeref( dd, bNeg0 );
+		Cudd_RecursiveDeref( dd, bNeg1 );
+
+
+		// consider the case when Res0 and Res1 are the same node 
+		if ( bRes0 == bRes1 )
+			bRes = bRes1;
+		// consider the case when Res1 is complemented 
+		else if ( Cudd_IsComplement(bRes1) ) 
+		{
+			bRes = cuddUniqueInter( dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0) );
+			if ( bRes == NULL ) 
+			{
+				Cudd_RecursiveDeref(dd,bRes0);
+				Cudd_RecursiveDeref(dd,bRes1);
+				return NULL;
+			}
+			bRes = Cudd_Not(bRes);
+		} 
+		else 
+		{
+			bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 );
+			if ( bRes == NULL ) 
+			{
+				Cudd_RecursiveDeref(dd,bRes0);
+				Cudd_RecursiveDeref(dd,bRes1);
+				return NULL;
+			}
+		}
+		cuddDeref( bRes0 );
+		cuddDeref( bRes1 );
+
+		cuddCacheInsert1( dd, extraBddSpaceFromFunctionNeg, bF, bRes );
+		return bRes;
+	}
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs the recursive step of Extra_bddSpaceCanonVars().]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * extraBddSpaceCanonVars( DdManager * dd, DdNode * bF )
+{
+	DdNode * bRes, * bFR;
+	statLine( dd );
+
+	bFR = Cudd_Regular(bF);
+	if ( cuddIsConstant(bFR) )
+		return bF;
+
+    if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceCanonVars, bF)) )
+    	return bRes;
+	else
+	{
+		DdNode * bF0,  * bF1;
+		DdNode * bRes, * bRes0; 
+
+		if ( bFR != bF ) // bF is complemented 
+		{
+			bF0 = Cudd_Not( cuddE(bFR) );
+			bF1 = Cudd_Not( cuddT(bFR) );
+		}
+		else
+		{
+			bF0 = cuddE(bFR);
+			bF1 = cuddT(bFR);
+		}
+
+		if ( bF0 == b0 )
+		{
+			bRes = extraBddSpaceCanonVars( dd, bF1 );
+			if ( bRes == NULL )
+				return NULL;
+		}
+		else if ( bF1 == b0 )
+		{
+			bRes = extraBddSpaceCanonVars( dd, bF0 );
+			if ( bRes == NULL )
+				return NULL;
+		}
+		else
+		{
+			bRes0 = extraBddSpaceCanonVars( dd, bF0 );
+			if ( bRes0 == NULL )
+				return NULL;
+			cuddRef( bRes0 );
+
+			bRes = cuddUniqueInter( dd, bFR->index, bRes0, b0 );
+			if ( bRes == NULL ) 
+			{
+				Cudd_RecursiveDeref( dd,bRes0 );
+				return NULL;
+			}
+			cuddDeref( bRes0 );
+		}
+
+		cuddCacheInsert1( dd, extraBddSpaceCanonVars, bF, bRes );
+		return bRes;
+	}
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs the recursive step of Extra_bddSpaceEquationsPos().]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * extraBddSpaceEquationsPos( DdManager * dd, DdNode * bF )
+{
+	DdNode * zRes;
+	statLine( dd );
+
+	if ( bF == b0 )
+		return z1;
+	if ( bF == b1 )
+		return z0;
+	
+    if ( (zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsPos, bF)) )
+    	return zRes;
+	else
+	{
+		DdNode * bFR, * bF0,  * bF1;
+		DdNode * zPos0, * zPos1, * zNeg1; 
+		DdNode * zRes, * zRes0, * zRes1;
+
+		bFR = Cudd_Regular(bF);
+		if ( bFR != bF ) // bF is complemented 
+		{
+			bF0 = Cudd_Not( cuddE(bFR) );
+			bF1 = Cudd_Not( cuddT(bFR) );
+		}
+		else
+		{
+			bF0 = cuddE(bFR);
+			bF1 = cuddT(bFR);
+		}
+
+		if ( bF0 == b0 )
+		{
+			zRes1 = extraBddSpaceEquationsPos( dd, bF1 );
+			if ( zRes1 == NULL )
+				return NULL;
+			cuddRef( zRes1 );
+
+			// add the current element to the set
+			zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes1 );
+			if ( zRes == NULL ) 
+			{
+				Cudd_RecursiveDerefZdd(dd, zRes1);
+				return NULL;
+			}
+			cuddDeref( zRes1 );
+		}
+		else if ( bF1 == b0 )
+		{
+			zRes = extraBddSpaceEquationsPos( dd, bF0 );
+			if ( zRes == NULL )
+				return NULL;
+		}
+		else
+		{
+			zPos0 = extraBddSpaceEquationsPos( dd, bF0 );
+			if ( zPos0 == NULL )
+				return NULL;
+			cuddRef( zPos0 );
+
+			zPos1 = extraBddSpaceEquationsPos( dd, bF1 );
+			if ( zPos1 == NULL )
+			{
+				Cudd_RecursiveDerefZdd(dd, zPos0);
+				return NULL;
+			}
+			cuddRef( zPos1 );
+
+			zNeg1 = extraBddSpaceEquationsNeg( dd, bF1 );
+			if ( zNeg1 == NULL )
+			{
+				Cudd_RecursiveDerefZdd(dd, zPos0);
+				Cudd_RecursiveDerefZdd(dd, zPos1);
+				return NULL;
+			}
+			cuddRef( zNeg1 );
+
+
+			zRes0 = cuddZddIntersect( dd, zPos0, zPos1 );
+			if ( zRes0 == NULL )
+			{
+				Cudd_RecursiveDerefZdd(dd, zNeg1);
+				Cudd_RecursiveDerefZdd(dd, zPos0);
+				Cudd_RecursiveDerefZdd(dd, zPos1);
+				return NULL;
+			}
+			cuddRef( zRes0 );
+
+			zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 );
+			if ( zRes1 == NULL )
+			{
+				Cudd_RecursiveDerefZdd(dd, zRes0);
+				Cudd_RecursiveDerefZdd(dd, zNeg1);
+				Cudd_RecursiveDerefZdd(dd, zPos0);
+				Cudd_RecursiveDerefZdd(dd, zPos1);
+				return NULL;
+			}
+			cuddRef( zRes1 );
+			Cudd_RecursiveDerefZdd(dd, zNeg1);
+			Cudd_RecursiveDerefZdd(dd, zPos0);
+			Cudd_RecursiveDerefZdd(dd, zPos1);
+			// only zRes0 and zRes1 are refed at this point
+
+			zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 );
+			if ( zRes == NULL ) 
+			{
+				Cudd_RecursiveDerefZdd(dd, zRes0);
+				Cudd_RecursiveDerefZdd(dd, zRes1);
+				return NULL;
+			}
+			cuddDeref( zRes0 );
+			cuddDeref( zRes1 );
+		}
+
+		cuddCacheInsert1( dd, extraBddSpaceEquationsPos, bF, zRes );
+		return zRes;
+	}
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs the recursive step of Extra_bddSpaceEquationsNev().]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bF )
+{
+	DdNode * zRes;
+	statLine( dd );
+
+	if ( bF == b0 )
+		return z1;
+	if ( bF == b1 )
+		return z0;
+	
+    if ( (zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsNeg, bF)) )
+    	return zRes;
+	else
+	{
+		DdNode * bFR, * bF0,  * bF1;
+		DdNode * zPos0, * zPos1, * zNeg1; 
+		DdNode * zRes, * zRes0, * zRes1;
+
+		bFR = Cudd_Regular(bF);
+		if ( bFR != bF ) // bF is complemented 
+		{
+			bF0 = Cudd_Not( cuddE(bFR) );
+			bF1 = Cudd_Not( cuddT(bFR) );
+		}
+		else
+		{
+			bF0 = cuddE(bFR);
+			bF1 = cuddT(bFR);
+		}
+
+		if ( bF0 == b0 )
+		{
+			zRes = extraBddSpaceEquationsNeg( dd, bF1 );
+			if ( zRes == NULL )
+				return NULL;
+		}
+		else if ( bF1 == b0 )
+		{
+			zRes0 = extraBddSpaceEquationsNeg( dd, bF0 );
+			if ( zRes0 == NULL )
+				return NULL;
+			cuddRef( zRes0 );
+
+			// add the current element to the set
+			zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes0 );
+			if ( zRes == NULL ) 
+			{
+				Cudd_RecursiveDerefZdd(dd, zRes0);
+				return NULL;
+			}
+			cuddDeref( zRes0 );
+		}
+		else
+		{
+			zPos0 = extraBddSpaceEquationsNeg( dd, bF0 );
+			if ( zPos0 == NULL )
+				return NULL;
+			cuddRef( zPos0 );
+
+			zPos1 = extraBddSpaceEquationsNeg( dd, bF1 );
+			if ( zPos1 == NULL )
+			{
+				Cudd_RecursiveDerefZdd(dd, zPos0);
+				return NULL;
+			}
+			cuddRef( zPos1 );
+
+			zNeg1 = extraBddSpaceEquationsPos( dd, bF1 );
+			if ( zNeg1 == NULL )
+			{
+				Cudd_RecursiveDerefZdd(dd, zPos0);
+				Cudd_RecursiveDerefZdd(dd, zPos1);
+				return NULL;
+			}
+			cuddRef( zNeg1 );
+
+
+			zRes0 = cuddZddIntersect( dd, zPos0, zPos1 );
+			if ( zRes0 == NULL )
+			{
+				Cudd_RecursiveDerefZdd(dd, zNeg1);
+				Cudd_RecursiveDerefZdd(dd, zPos0);
+				Cudd_RecursiveDerefZdd(dd, zPos1);
+				return NULL;
+			}
+			cuddRef( zRes0 );
+
+			zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 );
+			if ( zRes1 == NULL )
+			{
+				Cudd_RecursiveDerefZdd(dd, zRes0);
+				Cudd_RecursiveDerefZdd(dd, zNeg1);
+				Cudd_RecursiveDerefZdd(dd, zPos0);
+				Cudd_RecursiveDerefZdd(dd, zPos1);
+				return NULL;
+			}
+			cuddRef( zRes1 );
+			Cudd_RecursiveDerefZdd(dd, zNeg1);
+			Cudd_RecursiveDerefZdd(dd, zPos0);
+			Cudd_RecursiveDerefZdd(dd, zPos1);
+			// only zRes0 and zRes1 are refed at this point
+
+			zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 );
+			if ( zRes == NULL ) 
+			{
+				Cudd_RecursiveDerefZdd(dd, zRes0);
+				Cudd_RecursiveDerefZdd(dd, zRes1);
+				return NULL;
+			}
+			cuddDeref( zRes0 );
+			cuddDeref( zRes1 );
+		}
+
+		cuddCacheInsert1( dd, extraBddSpaceEquationsNeg, bF, zRes );
+		return zRes;
+	}
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs the recursive step of Extra_bddSpaceFromFunctionPos().]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * extraBddSpaceFromMatrixPos( DdManager * dd, DdNode * zA )
+{
+	DdNode * bRes;
+	statLine( dd );
+
+	if ( zA == z0 )
+		return b1;
+	if ( zA == z1 )
+		return b1;
+
+    if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromMatrixPos, zA)) )
+    	return bRes;
+	else
+	{
+		DdNode * bP0, * bP1;
+		DdNode * bN0, * bN1;
+		DdNode * bRes0, * bRes1; 
+
+		bP0  = extraBddSpaceFromMatrixPos( dd, cuddE(zA) );
+		if ( bP0 == NULL )
+			return NULL;
+		cuddRef( bP0 );
+
+		bP1  = extraBddSpaceFromMatrixPos( dd, cuddT(zA) );
+		if ( bP1 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bP0 );
+			return NULL;
+		}
+		cuddRef( bP1 );
+
+		bRes0  = cuddBddAndRecur( dd, bP0, bP1 );
+		if ( bRes0 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bP0 );
+			Cudd_RecursiveDeref( dd, bP1 );
+			return NULL;
+		}
+		cuddRef( bRes0 );
+		Cudd_RecursiveDeref( dd, bP0 );
+		Cudd_RecursiveDeref( dd, bP1 );
+
+
+		bN0  = extraBddSpaceFromMatrixPos( dd, cuddE(zA) );
+		if ( bN0 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bRes0 );
+			return NULL;
+		}
+		cuddRef( bN0 );
+
+		bN1  = extraBddSpaceFromMatrixNeg( dd, cuddT(zA) );
+		if ( bN1 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bRes0 );
+			Cudd_RecursiveDeref( dd, bN0 );
+			return NULL;
+		}
+		cuddRef( bN1 );
+
+		bRes1  = cuddBddAndRecur( dd, bN0, bN1 );
+		if ( bRes1 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bRes0 );
+			Cudd_RecursiveDeref( dd, bN0 );
+			Cudd_RecursiveDeref( dd, bN1 );
+			return NULL;
+		}
+		cuddRef( bRes1 );
+		Cudd_RecursiveDeref( dd, bN0 );
+		Cudd_RecursiveDeref( dd, bN1 );
+
+
+		// consider the case when Res0 and Res1 are the same node 
+		if ( bRes0 == bRes1 )
+			bRes = bRes1;
+		// consider the case when Res1 is complemented 
+		else if ( Cudd_IsComplement(bRes1) ) 
+		{
+			bRes = cuddUniqueInter( dd, zA->index/2, Cudd_Not(bRes1), Cudd_Not(bRes0) );
+			if ( bRes == NULL ) 
+			{
+				Cudd_RecursiveDeref(dd,bRes0);
+				Cudd_RecursiveDeref(dd,bRes1);
+				return NULL;
+			}
+			bRes = Cudd_Not(bRes);
+		} 
+		else 
+		{
+			bRes = cuddUniqueInter( dd, zA->index/2, bRes1, bRes0 );
+			if ( bRes == NULL ) 
+			{
+				Cudd_RecursiveDeref(dd,bRes0);
+				Cudd_RecursiveDeref(dd,bRes1);
+				return NULL;
+			}
+		}
+		cuddDeref( bRes0 );
+		cuddDeref( bRes1 );
+
+		cuddCacheInsert1( dd, extraBddSpaceFromMatrixPos, zA, bRes );
+		return bRes;
+	}
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs the recursive step of Extra_bddSpaceFromFunctionPos().]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * extraBddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA )
+{
+	DdNode * bRes;
+	statLine( dd );
+
+	if ( zA == z0 )
+		return b1;
+	if ( zA == z1 )
+		return b0;
+
+    if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromMatrixNeg, zA)) )
+    	return bRes;
+	else
+	{
+		DdNode * bP0, * bP1;
+		DdNode * bN0, * bN1;
+		DdNode * bRes0, * bRes1; 
+
+		bP0  = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) );
+		if ( bP0 == NULL )
+			return NULL;
+		cuddRef( bP0 );
+
+		bP1  = extraBddSpaceFromMatrixNeg( dd, cuddT(zA) );
+		if ( bP1 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bP0 );
+			return NULL;
+		}
+		cuddRef( bP1 );
+
+		bRes0  = cuddBddAndRecur( dd, bP0, bP1 );
+		if ( bRes0 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bP0 );
+			Cudd_RecursiveDeref( dd, bP1 );
+			return NULL;
+		}
+		cuddRef( bRes0 );
+		Cudd_RecursiveDeref( dd, bP0 );
+		Cudd_RecursiveDeref( dd, bP1 );
+
+
+		bN0  = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) );
+		if ( bN0 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bRes0 );
+			return NULL;
+		}
+		cuddRef( bN0 );
+
+		bN1  = extraBddSpaceFromMatrixPos( dd, cuddT(zA) );
+		if ( bN1 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bRes0 );
+			Cudd_RecursiveDeref( dd, bN0 );
+			return NULL;
+		}
+		cuddRef( bN1 );
+
+		bRes1  = cuddBddAndRecur( dd, bN0, bN1 );
+		if ( bRes1 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bRes0 );
+			Cudd_RecursiveDeref( dd, bN0 );
+			Cudd_RecursiveDeref( dd, bN1 );
+			return NULL;
+		}
+		cuddRef( bRes1 );
+		Cudd_RecursiveDeref( dd, bN0 );
+		Cudd_RecursiveDeref( dd, bN1 );
+
+
+		// consider the case when Res0 and Res1 are the same node 
+		if ( bRes0 == bRes1 )
+			bRes = bRes1;
+		// consider the case when Res1 is complemented 
+		else if ( Cudd_IsComplement(bRes1) ) 
+		{
+			bRes = cuddUniqueInter( dd, zA->index/2, Cudd_Not(bRes1), Cudd_Not(bRes0) );
+			if ( bRes == NULL ) 
+			{
+				Cudd_RecursiveDeref(dd,bRes0);
+				Cudd_RecursiveDeref(dd,bRes1);
+				return NULL;
+			}
+			bRes = Cudd_Not(bRes);
+		} 
+		else 
+		{
+			bRes = cuddUniqueInter( dd, zA->index/2, bRes1, bRes0 );
+			if ( bRes == NULL ) 
+			{
+				Cudd_RecursiveDeref(dd,bRes0);
+				Cudd_RecursiveDeref(dd,bRes1);
+				return NULL;
+			}
+		}
+		cuddDeref( bRes0 );
+		cuddDeref( bRes1 );
+
+		cuddCacheInsert1( dd, extraBddSpaceFromMatrixNeg, zA, bRes );
+		return bRes;
+	}
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraBddCas.c b/abc-build/src/misc/extra/extraBddCas.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraBddCas.c
@@ -0,0 +1,1235 @@
+/**CFile****************************************************************
+
+  FileName    [extraBddCas.c]
+
+  PackageName [extra]
+
+  Synopsis    [Procedures related to LUT cascade synthesis.]
+
+  Author      [Alan Mishchenko]
+
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - September 1, 2003.]
+
+  Revision    [$Id: extraBddCas.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+// the table to store cofactor operations
+#define _TABLESIZE_COF  51113
+typedef struct 
+{
+    unsigned Sign;  
+    DdNode * Arg1;  
+} _HashEntry_cof;
+_HashEntry_cof HHTable1[_TABLESIZE_COF];
+
+// the table to store the result of computation of the number of minterms
+#define _TABLESIZE_MINT  15113
+typedef struct 
+{
+    DdNode * Arg1;  
+    unsigned Arg2;  
+    unsigned Res;  
+} _HashEntry_mint;
+_HashEntry_mint HHTable2[_TABLESIZE_MINT];
+
+typedef struct 
+{
+    int      nEdges;  // the number of in-coming edges of the node
+    DdNode * bSum;    // the sum of paths of the incoming edges
+} traventry;
+
+// the signature used for hashing
+static unsigned s_Signature = 1;
+
+static int s_CutLevel = 0;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+// because the proposed solution to the optimal encoding problem has exponential complexity
+// we limit the depth of the branch and bound procedure to 5 levels
+static int s_MaxDepth = 5;      
+
+static int s_nVarsBest;          // the number of vars in the best ordering
+static int s_VarOrderBest[32];   // storing the best ordering of vars in the "simple encoding"
+static int s_VarOrderCur[32];    // storing the current ordering of vars
+ 
+// the place to store the supports of the encoded function
+static DdNode * s_Field[8][256]; // the size should be K, 2^K, where K is no less than MaxDepth
+static DdNode * s_Encoded;       // this is the original function
+static DdNode * s_VarAll;        // the set of all column variables
+static int s_MultiStart;         // the total number of encoding variables used
+// the array field now stores the supports
+
+static DdNode ** s_pbTemp;       // the temporary storage for the columns
+
+static int s_BackTracks;
+static int s_BackTrackLimit = 100;
+
+static DdNode * s_Terminal;      // the terminal value for counting minterms
+
+
+static int s_EncodingVarsLevel;
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars );
+static void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level );
+// functions called from EvaluateEncodings_rec()
+static DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost );
+static DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost );
+unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll );
+static unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max );
+
+static void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st__table * Visited );
+static void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st__table * Visited, st__table * CutNodes );
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the binary encoding of the set of function using the given vars.]
+
+  Description [Performs a straight binary encoding of the set of functions using 
+  the variable cubes formed from the given set of variables. ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * 
+Extra_bddEncodingBinary( 
+  DdManager * dd, 
+  DdNode ** pbFuncs,    // pbFuncs is the array of columns to be encoded
+  int nFuncs,           // nFuncs is the number of columns in the array
+  DdNode ** pbVars,     // pbVars is the array of variables to use for the codes
+  int nVars )           // nVars is the column multiplicity, [log2(nFuncs)]
+{
+    int i;
+    DdNode * bResult;
+    DdNode * bCube, * bTemp, * bProd;
+
+    assert( nVars >= Abc_Base2Log(nFuncs) );
+
+    bResult = b0;   Cudd_Ref( bResult );
+    for ( i = 0; i < nFuncs; i++ )
+    {
+        bCube   = Extra_bddBitsToCube( dd, i, nVars, pbVars, 1 );   Cudd_Ref( bCube );
+        bProd   = Cudd_bddAnd( dd, bCube, pbFuncs[i] );         Cudd_Ref( bProd );
+        Cudd_RecursiveDeref( dd, bCube );
+
+        bResult = Cudd_bddOr( dd, bProd, bTemp = bResult );     Cudd_Ref( bResult );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bProd );
+    }
+
+    Cudd_Deref( bResult );
+    return bResult;
+} /* end of Extra_bddEncodingBinary */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Solves the column encoding problem using a sophisticated method.]
+
+  Description [The encoding is based on the idea of deriving functions which 
+  depend on only one variable, which corresponds to the case of non-disjoint 
+  decompostion. It is assumed that the variables pCVars are ordered below the variables
+  representing the solumns, and the first variable pCVars[0] is the topmost one.]
+
+  SideEffects []
+
+  SeeAlso     [Extra_bddEncodingBinary]
+
+******************************************************************************/
+
+DdNode * 
+Extra_bddEncodingNonStrict( 
+  DdManager * dd, 
+  DdNode ** pbColumns,   // pbColumns is the array of columns to be encoded;
+  int nColumns,          // nColumns is the number of columns in the array
+  DdNode * bVarsCol,     // bVarsCol is the cube of variables on which the columns depend
+  DdNode ** pCVars,      // pCVars is the array of variables to use for the codes
+  int nMulti,            // nMulti is the column multiplicity, [log2(nColumns)]
+  int * pSimple )        // pSimple gets the number of code variables taken from the input varibles without change
+{
+    DdNode * bEncoded, * bResult;
+    int nVarsCol = Cudd_SupportSize(dd,bVarsCol);
+    abctime clk;
+
+    // cannot work with more that 32-bit codes
+    assert( nMulti < 32 );
+
+    // perform the preliminary encoding using the straight binary code
+    bEncoded = Extra_bddEncodingBinary( dd, pbColumns, nColumns, pCVars, nMulti );   Cudd_Ref( bEncoded );
+    //printf( "Node count = %d", Cudd_DagSize(bEncoded) );
+
+    // set the backgroup value for counting minterms
+    s_Terminal = b0;
+    // set the level of the encoding variables
+    s_EncodingVarsLevel = dd->invperm[pCVars[0]->index];
+
+    // the current number of backtracks
+    s_BackTracks = 0;
+    // the variables that are cofactored on the topmost level where everything starts (no vars)
+    s_Field[0][0] = b1;   
+    // the size of the best set of "simple" encoding variables found so far
+    s_nVarsBest   = 0;
+
+    // set the relation to be accessible to traversal procedures
+    s_Encoded = bEncoded;
+    // the set of all vars to be accessible to traversal procedures
+    s_VarAll  = bVarsCol;
+    // the column multiplicity
+    s_MultiStart  = nMulti;
+
+
+    clk = Abc_Clock();
+    // find the simplest encoding
+    if ( nColumns > 2 )
+    EvaluateEncodings_rec( dd, bVarsCol, nVarsCol, nMulti, 1 );
+//  printf( "The number of backtracks = %d\n", s_BackTracks );
+//  s_EncSearchTime += Abc_Clock() - clk;
+
+    // allocate the temporary storage for the columns
+    s_pbTemp = (DdNode **)ABC_ALLOC( char, nColumns * sizeof(DdNode *) );
+
+//  clk = Abc_Clock();
+    bResult = CreateTheCodes_rec( dd, bEncoded, 0, pCVars );   Cudd_Ref( bResult );
+//  s_EncComputeTime += Abc_Clock() - clk;
+    
+    // delocate the preliminarily encoded set
+    Cudd_RecursiveDeref( dd, bEncoded );
+//  Cudd_RecursiveDeref( dd, aEncoded );
+
+    ABC_FREE( s_pbTemp );
+
+    *pSimple = s_nVarsBest;
+    Cudd_Deref( bResult );
+    return bResult;
+}
+ 
+/**Function********************************************************************
+
+  Synopsis    [Collects the nodes under the cut and, for each node, computes the sum of paths leading to it from the root.]
+
+  Description [The table returned contains the set of BDD nodes pointed to under the cut
+  and, for each node, the BDD of the sum of paths leading to this node from the root
+  The sums of paths in the table are referenced. CutLevel is the first DD level 
+  considered to be under the cut.]
+
+  SideEffects []
+
+  SeeAlso     [Extra_bddNodePaths]
+
+******************************************************************************/
+ st__table * Extra_bddNodePathsUnderCut( DdManager * dd, DdNode * bFunc, int CutLevel )
+{
+    st__table * Visited;  // temporary table to remember the visited nodes
+    st__table * CutNodes; // the result goes here
+    st__table * Result; // the result goes here
+    DdNode * aFunc;
+
+    s_CutLevel = CutLevel;
+
+    Result  = st__init_table( st__ptrcmp, st__ptrhash);;
+    // the terminal cases
+    if ( Cudd_IsConstant( bFunc ) )
+    {
+        if ( bFunc == b1 )
+        {
+            st__insert( Result, (char*)b1, (char*)b1 );
+            Cudd_Ref( b1 );
+            Cudd_Ref( b1 );
+        }
+        else
+        {
+            st__insert( Result, (char*)b0, (char*)b0 );
+            Cudd_Ref( b0 );
+            Cudd_Ref( b0 );
+        }
+        return Result;
+    }
+
+    // create the ADD to simplify processing (no complemented edges)
+    aFunc = Cudd_BddToAdd( dd, bFunc );   Cudd_Ref( aFunc );
+
+    // Step 1: Start the tables and collect information about the nodes above the cut 
+    // this information tells how many edges point to each node
+    Visited  = st__init_table( st__ptrcmp, st__ptrhash);;
+    CutNodes = st__init_table( st__ptrcmp, st__ptrhash);;
+
+    CountNodeVisits_rec( dd, aFunc, Visited );
+
+    // Step 2: Traverse the BDD using the visited table and compute the sum of paths
+    CollectNodesAndComputePaths_rec( dd, aFunc, b1, Visited, CutNodes );
+
+    // at this point the table of cut nodes is ready and the table of visited is useless
+    {
+        st__generator * gen;
+        DdNode * aNode;
+        traventry * p;
+        st__foreach_item( Visited, gen, (const char**)&aNode, (char**)&p )
+        {
+            Cudd_RecursiveDeref( dd, p->bSum );
+            ABC_FREE( p );
+        }
+        st__free_table( Visited );
+    }
+
+    // go through the table CutNodes and create the BDD and the path to be returned
+    {
+        st__generator * gen;
+        DdNode * aNode, * bNode, * bSum;
+        st__foreach_item( CutNodes, gen, (const char**)&aNode, (char**)&bSum)
+        {
+            // aNode is not referenced, because aFunc is holding it
+            bNode = Cudd_addBddPattern( dd, aNode );  Cudd_Ref( bNode ); 
+            st__insert( Result, (char*)bNode, (char*)bSum );
+            // the new table takes both refs
+        }
+        st__free_table( CutNodes );
+    }
+
+    // dereference the ADD
+    Cudd_RecursiveDeref( dd, aFunc );
+
+    // return the table
+    return Result;
+
+} /* end of Extra_bddNodePathsUnderCut */
+
+/**Function********************************************************************
+
+  Synopsis    [Collects the nodes under the cut in the ADD starting from the given set of ADD nodes.]
+
+  Description [Takes the array, paNodes, of ADD nodes to start the traversal,
+  the array, pbCubes, of BDD cubes to start the traversal with in each node, 
+  and the number, nNodes, of ADD nodes and BDD cubes in paNodes and pbCubes. 
+  Returns the number of columns found. Fills in paNodesRes (pbCubesRes) 
+  with the set of ADD columns (BDD paths). These arrays should be allocated 
+  by the user.]
+
+  SideEffects []
+
+  SeeAlso     [Extra_bddNodePaths]
+
+******************************************************************************/
+int Extra_bddNodePathsUnderCutArray( DdManager * dd, DdNode ** paNodes, DdNode ** pbCubes, int nNodes, DdNode ** paNodesRes, DdNode ** pbCubesRes, int CutLevel )
+{
+    st__table * Visited;  // temporary table to remember the visited nodes
+    st__table * CutNodes; // the nodes under the cut go here
+    int i, Counter;
+
+    s_CutLevel = CutLevel;
+
+    // there should be some nodes
+    assert( nNodes > 0 );
+    if ( nNodes == 1 && Cudd_IsConstant( paNodes[0] ) )
+    {
+        if ( paNodes[0] == a1 )
+        {
+            paNodesRes[0] = a1;          Cudd_Ref( a1 );
+            pbCubesRes[0] = pbCubes[0];  Cudd_Ref( pbCubes[0] );
+        }
+        else
+        {
+            paNodesRes[0] = a0;          Cudd_Ref( a0 );
+            pbCubesRes[0] = pbCubes[0];  Cudd_Ref( pbCubes[0] );
+        }
+        return 1;
+    }
+
+    // Step 1: Start the table and collect information about the nodes above the cut 
+    // this information tells how many edges point to each node
+    CutNodes = st__init_table( st__ptrcmp, st__ptrhash);;
+    Visited  = st__init_table( st__ptrcmp, st__ptrhash);;
+
+    for ( i = 0; i < nNodes; i++ )
+        CountNodeVisits_rec( dd, paNodes[i], Visited );
+
+    // Step 2: Traverse the BDD using the visited table and compute the sum of paths
+    for ( i = 0; i < nNodes; i++ )
+        CollectNodesAndComputePaths_rec( dd, paNodes[i], pbCubes[i], Visited, CutNodes );
+
+    // at this point, the table of cut nodes is ready and the table of visited is useless
+    {
+        st__generator * gen;
+        DdNode * aNode;
+        traventry * p;
+        st__foreach_item( Visited, gen, (const char**)&aNode, (char**)&p )
+        {
+            Cudd_RecursiveDeref( dd, p->bSum );
+            ABC_FREE( p );
+        }
+        st__free_table( Visited );
+    }
+
+    // go through the table CutNodes and create the BDD and the path to be returned
+    {
+        st__generator * gen;
+        DdNode * aNode, * bSum;
+        Counter = 0;
+        st__foreach_item( CutNodes, gen, (const char**)&aNode, (char**)&bSum)
+        {
+            paNodesRes[Counter] = aNode;   Cudd_Ref( aNode ); 
+            pbCubesRes[Counter] = bSum;
+            Counter++;
+        }
+        st__free_table( CutNodes );
+    }
+
+    // return the number of cofactors found
+    return Counter;
+
+} /* end of Extra_bddNodePathsUnderCutArray */
+
+/**Function*************************************************************
+
+  Synopsis    [Collects all the BDD nodes into the table.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void extraCollectNodes( DdNode * Func, st__table * tNodes )
+{
+    DdNode * FuncR;
+    FuncR = Cudd_Regular(Func);
+    if ( st__find_or_add( tNodes, (char*)FuncR, NULL ) )
+        return;
+    if ( cuddIsConstant(FuncR) )
+        return;
+    extraCollectNodes( cuddE(FuncR), tNodes );
+    extraCollectNodes( cuddT(FuncR), tNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects all the nodes of one DD into the table.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+ st__table * Extra_CollectNodes( DdNode * Func )
+{
+    st__table * tNodes;
+    tNodes = st__init_table( st__ptrcmp, st__ptrhash );
+    extraCollectNodes( Func, tNodes );
+    return tNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the topmost level from which the given node is referenced.]
+
+  Description [Takes the table which maps each BDD nodes (including the constants)
+  into the topmost level on which this node counts as a cofactor. Takes the topmost
+  level, on which this node counts as a cofactor (see Extra_ProfileWidthFast(). 
+  Takes the node, for which the table entry should be updated.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void extraProfileUpdateTopLevel( st__table * tNodeTopRef, int TopLevelNew, DdNode * node )
+{
+    int * pTopLevel;
+
+    if ( st__find_or_add( tNodeTopRef, (char*)node, (char***)&pTopLevel ) )
+    { // the node is already referenced
+        // the current top level should be updated if it is larger than the new level
+        if ( *pTopLevel > TopLevelNew ) 
+             *pTopLevel = TopLevelNew;
+    }
+    else
+    { // the node is not referenced
+        // its level should be set to the current new level
+        *pTopLevel = TopLevelNew;
+    }
+}
+/**Function*************************************************************
+
+  Synopsis    [Fast computation of the BDD profile.]
+
+  Description [The array to store the profile is given by the user and should
+  contain at least as many entries as there is the maximum of the BDD/ZDD
+  size of the manager PLUS ONE.
+  When we say that the widths of the DD on level L is W, we mean the following.
+  Let us create the cut between the level L-1 and the level L and count the number
+  of different DD nodes pointed to across the cut. This number is the width W.
+  From this it follows the on level 0, the width is equal to the number of external
+  pointers to the considered DDs. If there is only one DD, then the profile on 
+  level 0 is always 1. If this DD is rooted in the topmost variable, then the width
+  on level 1 is always 2, etc. The width at the level equal to dd->size is the
+  number of terminal nodes in the DD. (Because we consider the first level #0
+  and the last level #dd->size, the profile array should contain dd->size+1 entries.)
+  ]
+
+  SideEffects [This procedure will not work for BDDs w/ complement edges, only for ADDs and ZDDs]
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_ProfileWidth( DdManager * dd, DdNode * Func, int * pProfile, int CutLevel )
+{
+    st__generator * gen;
+    st__table * tNodeTopRef; // this table stores the top level from which this node is pointed to
+    st__table * tNodes;
+    DdNode * node;
+    DdNode * nodeR;
+    int LevelStart, Limit;
+    int i, size;
+    int WidthMax;
+  
+    // start the mapping table
+    tNodeTopRef = st__init_table( st__ptrcmp, st__ptrhash);;
+    // add the topmost node to the profile
+    extraProfileUpdateTopLevel( tNodeTopRef, 0, Func );
+
+    // collect all nodes
+    tNodes = Extra_CollectNodes( Func );
+    // go though all the nodes and set the top level the cofactors are pointed from
+//  Cudd_ForeachNode( dd, Func, genDD, node )
+    st__foreach_item( tNodes, gen, (const char**)&node, NULL )
+    {
+//      assert( Cudd_Regular(node) );  // this procedure works only with ADD/ZDD (not BDD w/ compl.edges)
+        nodeR = Cudd_Regular(node);
+        if ( cuddIsConstant(nodeR) )
+            continue;
+        // this node is not a constant - consider its cofactors
+        extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddE(nodeR) );
+        extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddT(nodeR) );
+    }
+    st__free_table( tNodes );
+
+    // clean the profile
+    size = ddMax(dd->size, dd->sizeZ) + 1;
+    for ( i = 0; i < size; i++ ) 
+        pProfile[i] = 0;
+
+    // create the profile
+    st__foreach_item( tNodeTopRef, gen, (const char**)&node, (char**)&LevelStart )
+    {
+        nodeR = Cudd_Regular(node);
+        Limit = (cuddIsConstant(nodeR))? dd->size: dd->perm[nodeR->index];
+        for ( i = LevelStart; i <= Limit; i++ )
+            pProfile[i]++;
+    }
+
+    if ( CutLevel != -1 && CutLevel != 0  )
+        size = CutLevel;
+
+    // get the max width
+    WidthMax = 0;
+    for ( i = 0; i < size; i++ ) 
+        if ( WidthMax < pProfile[i] )
+            WidthMax = pProfile[i];
+
+    // deref the table
+    st__free_table( tNodeTopRef );
+
+    return WidthMax;
+} /* end of Extra_ProfileWidth */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the non-strict codes when evaluation is finished.]
+
+  Description [The information about the best code is stored in s_VarOrderBest,
+  which has s_nVarsBest entries.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars )
+// bEncoded is the preliminarily encoded set of columns
+// Level is the current level in the recursion
+// pCVars are the variables to be used for encoding
+{
+    DdNode * bRes;
+    if ( Level == s_nVarsBest )
+    { // the terminal case, when we need to remap the encoded function 
+        // from the preliminary encoded variables to the new ones
+        st__table * CutNodes;
+        int nCols;
+//      double nMints;
+/*
+#ifdef _DEBUG
+
+        {
+        DdNode * bTemp;
+        // make sure that the given number of variables is enough
+        bTemp  = Cudd_bddExistAbstract( dd, bEncoded, s_VarAll );           Cudd_Ref( bTemp );
+//      nMints = Cudd_CountMinterm( dd, bTemp, s_MultiStart );
+        nMints = Extra_CountMintermsSimple( bTemp, (1<<s_MultiStart) );
+        if ( nMints > Extra_Power2( s_MultiStart-Level ) ) 
+        {  // the number of minterms is too large to encode the columns 
+           // using the given minimum number of encoding variables
+            assert( 0 );
+        }
+        Cudd_RecursiveDeref( dd, bTemp );
+        }
+#endif
+*/
+        // get the columns to be re-encoded
+        CutNodes = Extra_bddNodePathsUnderCut( dd, bEncoded, s_EncodingVarsLevel );
+        // LUT size is the cut level because because the temporary encoding variables 
+        // are above the functional variables - this is not true!!!
+        // the temporary variables are below!
+
+        // put the entries from the table into the temporary array
+        { 
+            st__generator * gen;
+            DdNode * bColumn, * bCode;
+            nCols = 0;
+            st__foreach_item( CutNodes, gen, (const char**)&bCode, (char**)&bColumn )
+            {
+                if ( bCode == b0 )
+                { // the unused part of the columns
+                    Cudd_RecursiveDeref( dd, bColumn );
+                    Cudd_RecursiveDeref( dd, bCode );
+                    continue;
+                }
+                else
+                {
+                    s_pbTemp[ nCols ] = bColumn; // takes ref
+                    Cudd_RecursiveDeref( dd, bCode );
+                    nCols++;
+                }
+            }
+            st__free_table( CutNodes );
+//          assert( nCols == (int)nMints );
+        }
+
+        // encode the columns
+        if ( s_MultiStart-Level == 0 ) // we reached the bottom level of recursion
+        {
+            assert( nCols       == 1 );
+//          assert( (int)nMints == 1 );
+            bRes = s_pbTemp[0];     Cudd_Ref( bRes );
+        }
+        else
+        {
+            bRes = Extra_bddEncodingBinary( dd, s_pbTemp, nCols, pCVars+Level, s_MultiStart-Level ); Cudd_Ref( bRes );
+        }
+
+        // deref the columns
+        {
+            int i;
+            for ( i = 0; i < nCols; i++ )
+                Cudd_RecursiveDeref( dd, s_pbTemp[i] );
+        }
+    }
+    else
+    {
+        // cofactor the problem as specified in the best solution
+        DdNode * bCof0,  * bCof1;
+        DdNode * bRes0,  * bRes1;
+        DdNode * bProd0, * bProd1;
+        DdNode * bTemp;
+        DdNode * bVarNext = dd->vars[ s_VarOrderBest[Level] ];
+
+        bCof0  = Cudd_Cofactor( dd, bEncoded,  Cudd_Not( bVarNext ) );   Cudd_Ref( bCof0 );
+        bCof1  = Cudd_Cofactor( dd, bEncoded,            bVarNext   );   Cudd_Ref( bCof1 );
+
+        // call recursively
+        bRes0 = CreateTheCodes_rec( dd, bCof0, Level+1, pCVars );  Cudd_Ref( bRes0 );
+        bRes1 = CreateTheCodes_rec( dd, bCof1, Level+1, pCVars );  Cudd_Ref( bRes1 );
+
+        Cudd_RecursiveDeref( dd, bCof0 );
+        Cudd_RecursiveDeref( dd, bCof1 );
+
+        // compose the result using the identity (bVarNext <=> pCVars[Level])  - this is wrong!
+        // compose the result as follows: x'y'F0 + xyF1
+        bProd0 = Cudd_bddAnd( dd, Cudd_Not(bVarNext), Cudd_Not(pCVars[Level]) );   Cudd_Ref( bProd0 );
+        bProd1 = Cudd_bddAnd( dd,          bVarNext ,          pCVars[Level]  );   Cudd_Ref( bProd1 );
+
+        bProd0 = Cudd_bddAnd( dd, bTemp = bProd0, bRes0 );   Cudd_Ref( bProd0 );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bRes0 );
+
+        bProd1 = Cudd_bddAnd( dd, bTemp = bProd1, bRes1 );   Cudd_Ref( bProd1 );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bRes1 );
+
+        bRes = Cudd_bddOr( dd, bProd0, bProd1 );             Cudd_Ref( bRes );
+
+        Cudd_RecursiveDeref( dd, bProd0 );
+        Cudd_RecursiveDeref( dd, bProd1 );
+    }
+    Cudd_Deref( bRes );
+    return bRes;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the current set of variables and counts the number of minterms.]
+
+  Description [Old implementation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level )
+// bVarsCol is the set of remaining variables
+// nVarsCol is the number of remaining variables
+// nMulti is the number of encoding variables to be used
+// Level is the level of recursion, from which this function is called
+// if we successfully finish this procedure, Level also stands for how many encoding variabled we saved
+{
+    int i, k;
+    int nEntries = (1<<(Level-1)); // the number of entries in the field of the previous level
+    DdNode * bVars0, * bVars1; // the cofactors
+    unsigned nMint0, nMint1;   // the number of minterms
+    DdNode * bTempV;
+    DdNode * bVarTop;
+    int fBreak;
+
+
+    // there is no need to search above this level
+    if ( Level > s_MaxDepth )
+        return;
+
+    // if there are no variables left, quit the research
+    if ( bVarsCol == b1 )
+        return;
+
+    if ( s_BackTracks > s_BackTrackLimit )
+        return;
+
+    s_BackTracks++;
+
+    // otherwise, go through the remaining variables
+    for ( bTempV = bVarsCol; bTempV != b1; bTempV = cuddT(bTempV) )
+    {
+        // the currently tested variable
+        bVarTop = dd->vars[bTempV->index];
+
+        // put it into the array
+        s_VarOrderCur[Level-1] = bTempV->index;
+
+        // go through the entries and fill them out by cofactoring
+        fBreak = 0;
+        for ( i = 0; i < nEntries; i++ )
+        {
+            bVars0 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], Cudd_Not(bVarTop), &nMint0 );
+            Cudd_Ref( bVars0 );
+
+            if ( nMint0 > Extra_Power2( nMulti-1 ) ) 
+            {
+                // there is no way to encode - dereference and return
+                Cudd_RecursiveDeref( dd, bVars0 );
+                fBreak = 1;
+                break;
+            }
+
+            bVars1 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], bVarTop, &nMint1 );
+            Cudd_Ref( bVars1 );
+
+            if ( nMint1 > Extra_Power2( nMulti-1 ) ) 
+            {
+                // there is no way to encode - dereference and return
+                Cudd_RecursiveDeref( dd, bVars0 );
+                Cudd_RecursiveDeref( dd, bVars1 );
+                fBreak = 1;
+                break;
+            }
+
+            // otherwise, add these two cofactors
+            s_Field[Level][2*i + 0] = bVars0; // takes ref
+            s_Field[Level][2*i + 1] = bVars1; // takes ref
+        } 
+
+        if ( !fBreak )
+        {
+            DdNode * bVarsRem;
+            // if we ended up here, it means that the cofactors w.r.t. variable bVarTop satisfy the condition
+            // save this situation
+            if ( s_nVarsBest < Level )
+            {
+                s_nVarsBest = Level;
+                // copy the variable assignment
+                for ( k = 0; k < Level; k++ )
+                    s_VarOrderBest[k] = s_VarOrderCur[k];
+            }
+
+            // call recursively
+            // get the new variable set
+            if ( nMulti-1 > 0 )
+            {
+                bVarsRem = Cudd_bddExistAbstract( dd, bVarsCol, bVarTop );   Cudd_Ref( bVarsRem );
+                EvaluateEncodings_rec( dd, bVarsRem, nVarsCol-1, nMulti-1, Level+1 );
+                Cudd_RecursiveDeref( dd, bVarsRem );
+            }
+        }
+
+        // deref the contents of the array
+        for ( k = 0; k < i; k++ )
+        {
+            Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 0] );
+            Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 1] );
+        }
+
+        // if the solution is found, there is no need to continue
+        if ( s_nVarsBest == s_MaxDepth )
+            return;
+
+        // if the solution is found, there is no need to continue
+        if ( s_nVarsBest == s_MultiStart )
+            return;
+    }
+    // at this point, we have tried all possible directions in the space of variables
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the current set of variables and counts the number of minterms.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost )
+// takes bVars - the variables cofactored so far (some of them may be in negative polarity)
+// bVarTop - the topmost variable w.r.t. which to cofactor (may be in negative polarity)
+// returns the cost and the new set of variables (bVars & bVarTop)
+{
+    DdNode * bVarsRes;
+
+    // get the resulting set of variables
+    bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop );  Cudd_Ref( bVarsRes );
+
+    // increment signature before calling Cudd_CountCofactorMinterms()
+    s_Signature++;
+    *Cost = Extra_CountCofactorMinterms( dd, s_Encoded, bVarsRes, s_VarAll );
+
+    Cudd_Deref( bVarsRes );
+//  s_CountCalls++;
+    return bVarsRes;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the current set of variables and counts the number of minterms.]
+
+  Description [The old implementation, which is approximately 4 times slower.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost )
+{
+    DdNode * bVarsRes;
+    DdNode * bCof, * bFun;
+
+    bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop );             Cudd_Ref( bVarsRes );
+
+    bCof  = Cudd_Cofactor( dd, s_Encoded,  bVarsRes );        Cudd_Ref( bCof );
+    bFun  = Cudd_bddExistAbstract( dd, bCof, s_VarAll );      Cudd_Ref( bFun );
+    *Cost = (unsigned)Cudd_CountMinterm( dd, bFun, s_MultiStart );
+    Cudd_RecursiveDeref( dd, bFun );
+    Cudd_RecursiveDeref( dd, bCof );
+
+    Cudd_Deref( bVarsRes );
+//  s_CountCalls++;
+    return bVarsRes;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of encoding minterms pointed to by the cofactor of the function.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll )
+// this function computes how many minterms depending on the encoding variables
+// are there in the cofactor of bFunc w.r.t. variables bVarsCof
+// bFunc is assumed to depend on variables s_VarsAll
+// the variables s_VarsAll should be ordered above the encoding variables
+{
+    unsigned HKey;
+    DdNode * bFuncR;
+
+    // if the function is zero, there are no minterms
+//  if ( bFunc == b0 )
+//      return 0;
+
+//  if ( st__lookup(Visited, (char*)bFunc, NULL) )
+//      return 0;
+
+//  HKey = hashKey2c( s_Signature, bFuncR );
+//  if ( HHTable1[HKey].Sign == s_Signature && HHTable1[HKey].Arg1 == bFuncR ) // this node is visited
+//      return 0;
+
+
+    // check the hash-table 
+    bFuncR = Cudd_Regular(bFunc);
+//  HKey = hashKey2( s_Signature, bFuncR, _TABLESIZE_COF );
+    HKey = hashKey2( s_Signature, bFunc, _TABLESIZE_COF );
+    for ( ;  HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF )
+//      if ( HHTable1[HKey].Arg1 == bFuncR ) // this node is visited
+        if ( HHTable1[HKey].Arg1 == bFunc ) // this node is visited
+            return 0;
+
+
+    // if the function is already the code
+    if ( dd->perm[bFuncR->index] >= s_EncodingVarsLevel )
+    {
+//      st__insert(Visited, (char*)bFunc, NULL);
+
+//      HHTable1[HKey].Sign = s_Signature;
+//      HHTable1[HKey].Arg1 = bFuncR;
+
+        assert( HHTable1[HKey].Sign != s_Signature );
+        HHTable1[HKey].Sign = s_Signature;
+//      HHTable1[HKey].Arg1 = bFuncR;
+        HHTable1[HKey].Arg1 = bFunc;
+
+        return Extra_CountMintermsSimple( bFunc, (1<<s_MultiStart) );
+    }
+    else
+    {
+        DdNode * bFunc0,    * bFunc1;
+        DdNode * bVarsCof0, * bVarsCof1;
+        DdNode * bVarsCofR = Cudd_Regular(bVarsCof);
+        unsigned Res;
+
+        // get the levels
+        int LevelF = dd->perm[bFuncR->index];
+        int LevelC = cuddI(dd,bVarsCofR->index);
+        int LevelA = dd->perm[bVarsAll->index];
+
+        int LevelTop = LevelF;
+
+        if ( LevelTop > LevelC )
+             LevelTop = LevelC;
+
+        if ( LevelTop > LevelA )
+             LevelTop = LevelA;
+
+        // the top var in the function or in cofactoring vars always belongs to the set of all vars
+        assert( !( LevelTop == LevelF || LevelTop == LevelC ) || LevelTop == LevelA );
+
+        // cofactor the function
+        if ( LevelTop == LevelF )
+        {
+            if ( bFuncR != bFunc ) // bFunc is complemented 
+            {
+                bFunc0 = Cudd_Not( cuddE(bFuncR) );
+                bFunc1 = Cudd_Not( cuddT(bFuncR) );
+            }
+            else
+            {
+                bFunc0 = cuddE(bFuncR);
+                bFunc1 = cuddT(bFuncR);
+            }
+        }
+        else // bVars is higher in the variable order 
+            bFunc0 = bFunc1 = bFunc;
+
+        // cofactor the cube
+        if ( LevelTop == LevelC )
+        {
+            if ( bVarsCofR != bVarsCof ) // bFunc is complemented 
+            {
+                bVarsCof0 = Cudd_Not( cuddE(bVarsCofR) );
+                bVarsCof1 = Cudd_Not( cuddT(bVarsCofR) );
+            }
+            else
+            {
+                bVarsCof0 = cuddE(bVarsCofR);
+                bVarsCof1 = cuddT(bVarsCofR);
+            }
+        }
+        else // bVars is higher in the variable order 
+            bVarsCof0 = bVarsCof1 = bVarsCof;
+
+        // there are two cases: 
+        // (1) the top variable belongs to the cofactoring variables
+        // (2) the top variable does not belong to the cofactoring variables
+
+        // (1) the top variable belongs to the cofactoring variables
+        Res = 0;
+        if ( LevelTop == LevelC )
+        {
+            if ( bVarsCof1 == b0 ) // this is a negative cofactor
+            {
+                if ( bFunc0 != b0 )
+                Res = Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) );
+            }
+            else                        // this is a positive cofactor
+            {
+                if ( bFunc1 != b0 )
+                Res = Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) );
+            }
+        }
+        else
+        {
+            if ( bFunc0 != b0 )
+            Res += Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) );
+            
+            if ( bFunc1 != b0 )
+            Res += Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) );
+        }
+
+//      st__insert(Visited, (char*)bFunc, NULL);
+
+//      HHTable1[HKey].Sign = s_Signature;
+//      HHTable1[HKey].Arg1 = bFuncR;
+
+        // skip through the entries with the same signatures 
+        // (these might have been created at the time of recursive calls)
+        for ( ; HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF );
+        assert( HHTable1[HKey].Sign != s_Signature );
+        HHTable1[HKey].Sign = s_Signature;
+//      HHTable1[HKey].Arg1 = bFuncR;
+        HHTable1[HKey].Arg1 = bFunc;
+
+        return Res;
+    }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of minterms.]
+
+  Description [This function counts minterms for functions up to 32 variables
+  using a local cache. The terminal value (s_Termina) should be adjusted for
+  BDDs and ADDs.]
+
+  SideEffects [None]
+
+******************************************************************************/
+unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max )
+{
+    unsigned HKey;
+
+    // normalize
+    if ( Cudd_IsComplement(bFunc) )
+        return max - Extra_CountMintermsSimple( Cudd_Not(bFunc), max );
+
+    // now it is known that the function is not complemented
+    if ( cuddIsConstant(bFunc) )
+        return ((bFunc==s_Terminal)? 0: max);
+
+    // check cache
+    HKey = hashKey2( bFunc, max, _TABLESIZE_MINT );
+    if ( HHTable2[HKey].Arg1 == bFunc && HHTable2[HKey].Arg2 == max )
+        return HHTable2[HKey].Res;
+    else
+    {
+        // min = min0/2 + min1/2;
+        unsigned min = (Extra_CountMintermsSimple( cuddE(bFunc), max ) >> 1) +
+                       (Extra_CountMintermsSimple( cuddT(bFunc), max ) >> 1);
+
+        HHTable2[HKey].Arg1 = bFunc;
+        HHTable2[HKey].Arg2 = max;
+        HHTable2[HKey].Res  = min;
+
+        return min;
+    }
+}   /* end of Extra_CountMintermsSimple */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Visits the nodes.]
+
+  Description [Visits the nodes above the cut and the nodes pointed to below the cut;
+  collects the visited nodes, counts how many times each node is visited, and sets 
+  the path-sum to be the constant zero BDD.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st__table * Visited )
+
+{
+    traventry * p;
+    char **slot;
+    if ( st__find_or_add(Visited, (char*)aFunc, &slot) )
+    { // the entry already exists
+        p = (traventry*) *slot;
+        // increment the counter of incoming edges
+        p->nEdges++;
+        return; 
+    }
+    // this node has not been visited
+    assert( !Cudd_IsComplement(aFunc) );
+
+    // create the new traversal entry
+    p = (traventry *) ABC_ALLOC( char, sizeof(traventry) );
+    // set the initial sum of edges to zero BDD
+    p->bSum = b0;   Cudd_Ref( b0 );
+    // set the starting number of incoming edges
+    p->nEdges = 1;
+    // set this entry into the slot
+    *slot = (char*)p;
+
+    // recur if the node is above the cut
+    if ( cuddI(dd,aFunc->index) < s_CutLevel )
+    {
+        CountNodeVisits_rec( dd, cuddE(aFunc), Visited );
+        CountNodeVisits_rec( dd, cuddT(aFunc), Visited );
+    }
+} /* end of CountNodeVisits_rec */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Revisits the nodes and computes the paths.]
+
+  Description [This function visits the nodes above the cut having the goal of 
+  summing all the incomming BDD edges; when this function comes across the node 
+  below the cut, it saves this node in the CutNode table.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st__table * Visited, st__table * CutNodes )
+{   
+    // find the node in the visited table
+    DdNode * bTemp;
+    traventry * p;
+    char **slot;
+    if ( st__find_or_add(Visited, (char*)aFunc, &slot) )
+    { // the node is found
+        // get the pointer to the traversal entry
+        p = (traventry*) *slot;
+
+        // make sure that the counter of incoming edges is positive
+        assert( p->nEdges > 0 );
+
+        // add the cube to the currently accumulated cubes
+        p->bSum = Cudd_bddOr( dd, bTemp = p->bSum, bCube );  Cudd_Ref( p->bSum );
+        Cudd_RecursiveDeref( dd, bTemp );
+
+        // decrement the number of visits
+        p->nEdges--;
+
+        // if more visits to this node are expected, return
+        if ( p->nEdges ) 
+            return;
+        else // if ( p->nEdges == 0 )
+        { // this is the last visit - propagate the cube
+
+            // check where this node is
+            if ( cuddI(dd,aFunc->index) < s_CutLevel )
+            { // the node is above the cut
+                DdNode * bCube0, * bCube1;
+
+                // get the top-most variable
+                DdNode * bVarTop = dd->vars[aFunc->index];
+
+                // compute the propagated cubes
+                bCube0 = Cudd_bddAnd( dd, p->bSum, Cudd_Not( bVarTop ) );   Cudd_Ref( bCube0 );
+                bCube1 = Cudd_bddAnd( dd, p->bSum,           bVarTop   );   Cudd_Ref( bCube1 );
+
+                // call recursively
+                CollectNodesAndComputePaths_rec( dd, cuddE(aFunc), bCube0, Visited, CutNodes );
+                CollectNodesAndComputePaths_rec( dd, cuddT(aFunc), bCube1, Visited, CutNodes );
+
+                // dereference the cubes
+                Cudd_RecursiveDeref( dd, bCube0 );
+                Cudd_RecursiveDeref( dd, bCube1 );
+                return;
+            }
+            else
+            { // the node is below the cut
+                // add this node to the cut node table, if it is not yet there
+
+//              DdNode * bNode;
+//              bNode = Cudd_addBddPattern( dd, aFunc );  Cudd_Ref( bNode );
+                if ( st__find_or_add(CutNodes, (char*)aFunc, &slot) )
+                { // the node exists - should never happen
+                    assert( 0 );
+                }
+                *slot = (char*) p->bSum;   Cudd_Ref( p->bSum );
+                // the table takes the reference of bNode
+                return;
+            }
+        }
+    }
+
+    // the node does not exist in the visited table - should never happen
+    assert(0);
+
+} /* end of CollectNodesAndComputePaths_rec */
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                           END OF FILE                            ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraBddImage.c b/abc-build/src/misc/extra/extraBddImage.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraBddImage.c
@@ -0,0 +1,1162 @@
+/**CFile****************************************************************
+
+  FileName    [extraBddImage.c]
+
+  PackageName [extra]
+
+  Synopsis    [Various reusable software utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2003.]
+
+  Revision    [$Id: extraBddImage.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/* 
+    The ideas implemented in this file are inspired by the paper:
+    Pankaj Chauhan, Edmund Clarke, Somesh Jha, Jim Kukula, Tom Shiple, 
+    Helmut Veith, Dong Wang. Non-linear Quantification Scheduling in 
+    Image Computation. ICCAD, 2001.
+*/
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+typedef struct Extra_ImageNode_t_  Extra_ImageNode_t;
+typedef struct Extra_ImagePart_t_  Extra_ImagePart_t;
+typedef struct Extra_ImageVar_t_   Extra_ImageVar_t;
+
+struct Extra_ImageTree_t_
+{
+    Extra_ImageNode_t * pRoot;      // the root of quantification tree
+    Extra_ImageNode_t * pCare;      // the leaf node with the care set
+    DdNode *            bCareSupp;  // the cube to quantify from the care
+    int                 fVerbose;   // the verbosity flag
+    int                 nNodesMax;  // the max number of nodes in one iter
+    int                 nNodesMaxT; // the overall max number of nodes
+    int                 nIter;      // the number of iterations with this tree
+};
+
+struct Extra_ImageNode_t_
+{
+    DdManager *         dd;         // the manager 
+    DdNode *            bCube;      // the cube to quantify
+    DdNode *            bImage;     // the partial image
+    Extra_ImageNode_t * pNode1;     // the first branch
+    Extra_ImageNode_t * pNode2;     // the second branch
+    Extra_ImagePart_t * pPart;      // the partition (temporary)
+};
+
+struct Extra_ImagePart_t_
+{
+    DdNode *            bFunc;      // the partition
+    DdNode *            bSupp;      // the support of this partition
+    int                 nNodes;     // the number of BDD nodes
+    short               nSupp;      // the number of support variables
+    short               iPart;      // the number of this partition
+};
+
+struct Extra_ImageVar_t_
+{
+    int                 iNum;       // the BDD index of this variable
+    DdNode *            bParts;     // the partition numbers
+    int                 nParts;     // the number of partitions
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static Extra_ImagePart_t ** Extra_CreateParts( DdManager * dd,
+    int nParts, DdNode ** pbParts, DdNode * bCare );
+static Extra_ImageVar_t ** Extra_CreateVars( DdManager * dd,
+    int nParts, Extra_ImagePart_t ** pParts,
+    int nVars, DdNode ** pbVarsNs );
+static Extra_ImageNode_t ** Extra_CreateNodes( DdManager * dd, 
+    int nParts, Extra_ImagePart_t ** pParts, 
+    int nVars,  Extra_ImageVar_t ** pVars );
+static void Extra_DeleteParts_rec( Extra_ImageNode_t * pNode );
+static int Extra_BuildTreeNode( DdManager * dd, 
+    int nNodes, Extra_ImageNode_t ** pNodes, 
+    int nVars,  Extra_ImageVar_t ** pVars );
+static Extra_ImageNode_t * Extra_MergeTopNodes( DdManager * dd, 
+    int nNodes, Extra_ImageNode_t ** pNodes );
+static void Extra_bddImageTreeDelete_rec( Extra_ImageNode_t * pNode );
+static void Extra_bddImageCompute_rec( Extra_ImageTree_t * pTree, Extra_ImageNode_t * pNode );
+static int Extra_FindBestVariable( DdManager * dd,
+    int nNodes, Extra_ImageNode_t ** pNodes, 
+    int nVars,  Extra_ImageVar_t ** pVars );
+static void Extra_FindBestPartitions( DdManager * dd, DdNode * bParts, 
+    int nNodes, Extra_ImageNode_t ** pNodes, 
+    int * piNode1, int * piNode2 );
+static Extra_ImageNode_t * Extra_CombineTwoNodes( DdManager * dd, DdNode * bCube,
+    Extra_ImageNode_t * pNode1, Extra_ImageNode_t * pNode2 );
+
+static void Extra_bddImagePrintLatchDependency( DdManager * dd, DdNode * bCare,
+    int nParts, DdNode ** pbParts,
+    int nVars, DdNode ** pbVars );
+static void Extra_bddImagePrintLatchDependencyOne( DdManager * dd, DdNode * bFunc, 
+    DdNode * bVarsCs, DdNode * bVarsNs, int iPart );
+
+static void Extra_bddImagePrintTree( Extra_ImageTree_t * pTree );
+static void Extra_bddImagePrintTree_rec( Extra_ImageNode_t * pNode, int nOffset );
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the image computation using tree-based scheduling.]
+
+  Description [This procedure starts the image computation. It uses
+  the given care set to test-run the image computation and creates the 
+  quantification tree by scheduling variable quantifications. The tree can 
+  be used to compute images for other care sets without rescheduling.
+  In this case, Extra_bddImageCompute() should be called.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Extra_ImageTree_t * Extra_bddImageStart( 
+    DdManager * dd, DdNode * bCare, // the care set
+    int nParts, DdNode ** pbParts,  // the partitions for image computation
+    int nVars, DdNode ** pbVars, int fVerbose )   // the NS and parameter variables (not quantified!)
+{
+    Extra_ImageTree_t * pTree;
+    Extra_ImagePart_t ** pParts;
+    Extra_ImageVar_t ** pVars;
+    Extra_ImageNode_t ** pNodes;
+    int v;
+
+    if ( fVerbose && dd->size <= 80 )
+        Extra_bddImagePrintLatchDependency( dd, bCare, nParts, pbParts, nVars, pbVars );
+
+    // create variables, partitions and leaf nodes
+    pParts = Extra_CreateParts( dd, nParts, pbParts, bCare );
+    pVars  = Extra_CreateVars( dd, nParts + 1, pParts, nVars, pbVars );
+    pNodes = Extra_CreateNodes( dd, nParts + 1, pParts, dd->size, pVars );
+    
+    // create the tree
+    pTree = ABC_ALLOC( Extra_ImageTree_t, 1 );
+    memset( pTree, 0, sizeof(Extra_ImageTree_t) );
+    pTree->pCare = pNodes[nParts];
+    pTree->fVerbose = fVerbose;
+
+    // process the nodes
+    while ( Extra_BuildTreeNode( dd, nParts + 1, pNodes, dd->size, pVars ) );
+
+    // make sure the variables are gone
+    for ( v = 0; v < dd->size; v++ )
+        assert( pVars[v] == NULL );
+    ABC_FREE( pVars );
+
+    // merge the topmost nodes
+    while ( (pTree->pRoot = Extra_MergeTopNodes( dd, nParts + 1, pNodes )) == NULL );
+
+    // make sure the nodes are gone
+    for ( v = 0; v < nParts + 1; v++ )
+        assert( pNodes[v] == NULL );
+    ABC_FREE( pNodes );
+
+//    if ( fVerbose )
+//        Extra_bddImagePrintTree( pTree );
+
+    // set the support of the care set
+    pTree->bCareSupp = Cudd_Support( dd, bCare );  Cudd_Ref( pTree->bCareSupp );
+
+    // clean the partitions
+    Extra_DeleteParts_rec( pTree->pRoot );
+    ABC_FREE( pParts );
+    return pTree;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the image.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_bddImageCompute( Extra_ImageTree_t * pTree, DdNode * bCare )
+{
+    DdManager * dd = pTree->pCare->dd;
+    DdNode * bSupp, * bRem;
+
+    pTree->nIter++;
+
+    // make sure the supports are okay
+    bSupp = Cudd_Support( dd, bCare );        Cudd_Ref( bSupp );
+    if ( bSupp != pTree->bCareSupp )
+    {
+        bRem = Cudd_bddExistAbstract( dd, bSupp, pTree->bCareSupp );  Cudd_Ref( bRem );
+        if ( bRem != b1 )
+        {
+printf( "Original care set support: " );
+ABC_PRB( dd, pTree->bCareSupp );
+printf( "Current care set support: " );
+ABC_PRB( dd, bSupp );
+            Cudd_RecursiveDeref( dd, bSupp );
+            Cudd_RecursiveDeref( dd, bRem );
+            printf( "The care set depends on some vars that were not in the care set during scheduling.\n" );
+            return NULL;
+        }
+        Cudd_RecursiveDeref( dd, bRem );
+    }
+    Cudd_RecursiveDeref( dd, bSupp );
+
+    // remove the previous image
+    Cudd_RecursiveDeref( dd, pTree->pCare->bImage );
+    pTree->pCare->bImage = bCare;   Cudd_Ref( bCare );
+
+    // compute the image
+    pTree->nNodesMax = 0;
+    Extra_bddImageCompute_rec( pTree, pTree->pRoot );
+    if ( pTree->nNodesMaxT < pTree->nNodesMax )
+        pTree->nNodesMaxT = pTree->nNodesMax;
+
+//    if ( pTree->fVerbose )
+//        printf( "Iter %2d : Max nodes = %5d.\n", pTree->nIter, pTree->nNodesMax );
+    return pTree->pRoot->bImage;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Delete the tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_bddImageTreeDelete( Extra_ImageTree_t * pTree )
+{
+    if ( pTree->bCareSupp )
+        Cudd_RecursiveDeref( pTree->pRoot->dd, pTree->bCareSupp );
+    Extra_bddImageTreeDelete_rec( pTree->pRoot );
+    ABC_FREE( pTree );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the image from the tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_bddImageRead( Extra_ImageTree_t * pTree )
+{
+    return pTree->pRoot->bImage;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static Functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+  Synopsis    [Creates partitions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Extra_ImagePart_t ** Extra_CreateParts( DdManager * dd,
+    int nParts, DdNode ** pbParts, DdNode * bCare )
+{
+    Extra_ImagePart_t ** pParts;
+    int i;
+
+    // start the partitions
+    pParts = ABC_ALLOC( Extra_ImagePart_t *, nParts + 1 );
+    // create structures for each variable
+    for ( i = 0; i < nParts; i++ )
+    {
+        pParts[i] = ABC_ALLOC( Extra_ImagePart_t, 1 );
+        pParts[i]->bFunc  = pbParts[i];                           Cudd_Ref( pParts[i]->bFunc );
+        pParts[i]->bSupp  = Cudd_Support( dd, pParts[i]->bFunc ); Cudd_Ref( pParts[i]->bSupp );
+        pParts[i]->nSupp  = Extra_bddSuppSize( dd, pParts[i]->bSupp );
+        pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc );
+        pParts[i]->iPart  = i;
+    }
+    // add the care set as the last partition
+    pParts[nParts] = ABC_ALLOC( Extra_ImagePart_t, 1 );
+    pParts[nParts]->bFunc = bCare;                                     Cudd_Ref( pParts[nParts]->bFunc );
+    pParts[nParts]->bSupp = Cudd_Support( dd, pParts[nParts]->bFunc ); Cudd_Ref( pParts[nParts]->bSupp );
+    pParts[nParts]->nSupp = Extra_bddSuppSize( dd, pParts[nParts]->bSupp );
+    pParts[nParts]->nNodes = Cudd_DagSize( pParts[nParts]->bFunc );
+    pParts[nParts]->iPart  = nParts;
+    return pParts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Extra_ImageVar_t ** Extra_CreateVars( DdManager * dd,
+    int nParts, Extra_ImagePart_t ** pParts,
+    int nVars, DdNode ** pbVars )
+{
+    Extra_ImageVar_t ** pVars;
+    DdNode ** pbFuncs;
+    DdNode * bCubeNs, * bSupp, * bParts, * bTemp, * bSuppTemp;
+    int nVarsTotal, iVar, p, Counter;
+
+    // put all the functions into one array
+    pbFuncs = ABC_ALLOC( DdNode *, nParts );
+    for ( p = 0; p < nParts; p++ )
+        pbFuncs[p] = pParts[p]->bSupp;
+    bSupp = Cudd_VectorSupport( dd, pbFuncs, nParts );  Cudd_Ref( bSupp );
+    ABC_FREE( pbFuncs );
+
+    // remove the NS vars
+    bCubeNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars );        Cudd_Ref( bCubeNs );
+    bSupp = Cudd_bddExistAbstract( dd, bTemp = bSupp, bCubeNs );     Cudd_Ref( bSupp );
+    Cudd_RecursiveDeref( dd, bTemp );
+    Cudd_RecursiveDeref( dd, bCubeNs );
+
+    // get the number of I and CS variables to be quantified
+    nVarsTotal = Extra_bddSuppSize( dd, bSupp );
+
+    // start the variables
+    pVars = ABC_ALLOC( Extra_ImageVar_t *, dd->size );
+    memset( pVars, 0, sizeof(Extra_ImageVar_t *) * dd->size );
+    // create structures for each variable
+    for ( bSuppTemp = bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) )
+    {
+        iVar = bSuppTemp->index;
+        pVars[iVar] = ABC_ALLOC( Extra_ImageVar_t, 1 );
+        pVars[iVar]->iNum = iVar;
+        // collect all the parts this var belongs to
+        Counter = 0;
+        bParts = b1; Cudd_Ref( bParts );
+        for ( p = 0; p < nParts; p++ )
+            if ( Cudd_bddLeq( dd, pParts[p]->bSupp, dd->vars[bSuppTemp->index] ) )
+            {
+                bParts = Cudd_bddAnd( dd, bTemp = bParts, dd->vars[p] );  Cudd_Ref( bParts );
+                Cudd_RecursiveDeref( dd, bTemp );
+                Counter++;
+            }
+        pVars[iVar]->bParts = bParts; // takes ref
+        pVars[iVar]->nParts = Counter;
+    }
+    Cudd_RecursiveDeref( dd, bSupp );
+    return pVars;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Extra_ImageNode_t ** Extra_CreateNodes( DdManager * dd, 
+    int nParts, Extra_ImagePart_t ** pParts, 
+    int nVars,  Extra_ImageVar_t ** pVars )
+{
+    Extra_ImageNode_t ** pNodes;
+    Extra_ImageNode_t * pNode;
+    DdNode * bTemp;
+    int i, v, iPart;
+/*
+    DdManager *         dd;       // the manager 
+    DdNode *            bCube;    // the cube to quantify
+    DdNode *            bImage;   // the partial image
+    Extra_ImageNode_t * pNode1;   // the first branch
+    Extra_ImageNode_t * pNode2;   // the second branch
+    Extra_ImagePart_t * pPart;    // the partition (temporary)
+*/
+    // start the partitions
+    pNodes = ABC_ALLOC( Extra_ImageNode_t *, nParts );
+    // create structures for each leaf nodes
+    for ( i = 0; i < nParts; i++ )
+    {
+        pNodes[i] = ABC_ALLOC( Extra_ImageNode_t, 1 );
+        memset( pNodes[i], 0, sizeof(Extra_ImageNode_t) );
+        pNodes[i]->dd    = dd;
+        pNodes[i]->pPart = pParts[i];
+    }
+    // find the quantification cubes for each leaf node
+    for ( v = 0; v < nVars; v++ )
+    {
+        if ( pVars[v] == NULL )
+            continue;
+        assert( pVars[v]->nParts > 0 );
+        if ( pVars[v]->nParts > 1 )
+            continue;
+        iPart = pVars[v]->bParts->index;
+        if ( pNodes[iPart]->bCube == NULL )
+        {
+            pNodes[iPart]->bCube = dd->vars[v];   
+            Cudd_Ref( dd->vars[v] );
+        }
+        else
+        {
+            pNodes[iPart]->bCube = Cudd_bddAnd( dd, bTemp = pNodes[iPart]->bCube, dd->vars[v] );  
+            Cudd_Ref( pNodes[iPart]->bCube );
+            Cudd_RecursiveDeref( dd, bTemp );
+        }
+        // remove these  variables
+        Cudd_RecursiveDeref( dd, pVars[v]->bParts );
+        ABC_FREE( pVars[v] );
+    }
+
+    // assign the leaf node images
+    for ( i = 0; i < nParts; i++ )
+    {
+        pNode = pNodes[i];
+        if ( pNode->bCube )
+        {
+            // update the partition
+            pParts[i]->bFunc = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bFunc, pNode->bCube );
+            Cudd_Ref( pParts[i]->bFunc );
+            Cudd_RecursiveDeref( dd, bTemp );
+            // update the support the partition
+            pParts[i]->bSupp = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bSupp, pNode->bCube ); 
+            Cudd_Ref( pParts[i]->bSupp );
+            Cudd_RecursiveDeref( dd, bTemp );
+            // update the numbers
+            pParts[i]->nSupp  = Extra_bddSuppSize( dd, pParts[i]->bSupp );
+            pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc );
+            // get rid of the cube
+            // save the last (care set) quantification cube
+            if ( i < nParts - 1 )
+            {
+                Cudd_RecursiveDeref( dd, pNode->bCube );
+                pNode->bCube = NULL;
+            }
+        }
+        // copy the function
+        pNode->bImage = pParts[i]->bFunc;   Cudd_Ref( pNode->bImage );
+    }
+/*
+    for ( i = 0; i < nParts; i++ )
+    {
+        pNode = pNodes[i];
+ABC_PRB( dd, pNode->bCube );
+ABC_PRB( dd, pNode->pPart->bFunc );
+ABC_PRB( dd, pNode->pPart->bSupp );
+printf( "\n" );
+    }
+*/
+    return pNodes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Delete the partitions from the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_DeleteParts_rec( Extra_ImageNode_t * pNode )
+{
+    Extra_ImagePart_t * pPart;
+    if ( pNode->pNode1 )
+        Extra_DeleteParts_rec( pNode->pNode1 );
+    if ( pNode->pNode2 )
+        Extra_DeleteParts_rec( pNode->pNode2 );
+    pPart = pNode->pPart;
+    Cudd_RecursiveDeref( pNode->dd, pPart->bFunc );
+    Cudd_RecursiveDeref( pNode->dd, pPart->bSupp );
+    ABC_FREE( pNode->pPart );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Delete the partitions from the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_bddImageTreeDelete_rec( Extra_ImageNode_t * pNode )
+{
+    if ( pNode->pNode1 )
+        Extra_bddImageTreeDelete_rec( pNode->pNode1 );
+    if ( pNode->pNode2 )
+        Extra_bddImageTreeDelete_rec( pNode->pNode2 );
+    if ( pNode->bCube )
+        Cudd_RecursiveDeref( pNode->dd, pNode->bCube );
+    if ( pNode->bImage )
+        Cudd_RecursiveDeref( pNode->dd, pNode->bImage );
+    assert( pNode->pPart == NULL );
+    ABC_FREE( pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recompute the image.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_bddImageCompute_rec( Extra_ImageTree_t * pTree, Extra_ImageNode_t * pNode )
+{
+    DdManager * dd = pNode->dd;
+    DdNode * bTemp;
+    int nNodes;
+
+    // trivial case
+    if ( pNode->pNode1 == NULL )
+    {
+        if ( pNode->bCube )
+        {
+            pNode->bImage = Cudd_bddExistAbstract( dd, bTemp = pNode->bImage, pNode->bCube ); 
+            Cudd_Ref( pNode->bImage );
+            Cudd_RecursiveDeref( dd, bTemp );
+        }
+        return;
+    }
+
+    // compute the children
+    if ( pNode->pNode1 )
+        Extra_bddImageCompute_rec( pTree, pNode->pNode1 );
+    if ( pNode->pNode2 )
+        Extra_bddImageCompute_rec( pTree, pNode->pNode2 );
+
+    // clean the old image
+    if ( pNode->bImage )
+        Cudd_RecursiveDeref( dd, pNode->bImage );
+    pNode->bImage = NULL;
+
+    // compute the new image
+    if ( pNode->bCube )
+        pNode->bImage = Cudd_bddAndAbstract( dd, 
+            pNode->pNode1->bImage, pNode->pNode2->bImage, pNode->bCube );
+    else
+        pNode->bImage = Cudd_bddAnd( dd, pNode->pNode1->bImage, pNode->pNode2->bImage );
+    Cudd_Ref( pNode->bImage );
+
+    if ( pTree->fVerbose )
+    {
+        nNodes = Cudd_DagSize( pNode->bImage );
+        if ( pTree->nNodesMax < nNodes )
+            pTree->nNodesMax = nNodes;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Builds the tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_BuildTreeNode( DdManager * dd, 
+    int nNodes, Extra_ImageNode_t ** pNodes, 
+    int nVars,  Extra_ImageVar_t ** pVars )
+{
+    Extra_ImageNode_t * pNode1, * pNode2;
+    Extra_ImageVar_t * pVar;
+    Extra_ImageNode_t * pNode;
+    DdNode * bCube, * bTemp, * bSuppTemp, * bParts;
+    int iNode1, iNode2;
+    int iVarBest, nSupp, v;
+
+    // find the best variable
+    iVarBest = Extra_FindBestVariable( dd, nNodes, pNodes, nVars, pVars );
+    if ( iVarBest == -1 )
+        return 0;
+
+    pVar = pVars[iVarBest];
+
+    // this var cannot appear in one partition only
+    nSupp = Extra_bddSuppSize( dd, pVar->bParts );
+    assert( nSupp == pVar->nParts );
+    assert( nSupp != 1 );
+
+    // if it appears in only two partitions, quantify it
+    if ( pVar->nParts == 2 )
+    {
+        // get the nodes
+        iNode1 = pVar->bParts->index;
+        iNode2 = cuddT(pVar->bParts)->index;
+        pNode1 = pNodes[iNode1];
+        pNode2 = pNodes[iNode2];
+
+        // get the quantification cube
+        bCube = dd->vars[pVar->iNum];    Cudd_Ref( bCube );
+        // add the variables that appear only in these partitions
+        for ( v = 0; v < nVars; v++ )
+            if ( pVars[v] && v != iVarBest && pVars[v]->bParts == pVars[iVarBest]->bParts )
+            {
+                // add this var
+                bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[pVars[v]->iNum] );   Cudd_Ref( bCube );
+                Cudd_RecursiveDeref( dd, bTemp );
+                // clean this var
+                Cudd_RecursiveDeref( dd, pVars[v]->bParts );
+                ABC_FREE( pVars[v] );
+            }
+        // clean the best var
+        Cudd_RecursiveDeref( dd, pVars[iVarBest]->bParts );
+        ABC_FREE( pVars[iVarBest] );
+
+        // combines two nodes
+        pNode = Extra_CombineTwoNodes( dd, bCube, pNode1, pNode2 );
+        Cudd_RecursiveDeref( dd, bCube );
+    }
+    else // if ( pVar->nParts > 2 )
+    {
+        // find two smallest BDDs that have this var
+        Extra_FindBestPartitions( dd, pVar->bParts, nNodes, pNodes, &iNode1, &iNode2 );
+        pNode1 = pNodes[iNode1];
+        pNode2 = pNodes[iNode2];
+
+        // it is not possible that a var appears only in these two
+        // otherwise, it would have a different cost
+        bParts = Cudd_bddAnd( dd, dd->vars[iNode1], dd->vars[iNode2] ); Cudd_Ref( bParts );
+        for ( v = 0; v < nVars; v++ )
+            if ( pVars[v] && pVars[v]->bParts == bParts )
+                assert( 0 );
+        Cudd_RecursiveDeref( dd, bParts );
+
+        // combines two nodes
+        pNode = Extra_CombineTwoNodes( dd, b1, pNode1, pNode2 );
+    }
+
+    // clean the old nodes
+    pNodes[iNode1] = pNode;
+    pNodes[iNode2] = NULL;
+    
+    // update the variables that appear in pNode[iNode2]
+    for ( bSuppTemp = pNode2->pPart->bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) )
+    {
+        pVar = pVars[bSuppTemp->index];
+        if ( pVar == NULL ) // this variable is not be quantified
+            continue;
+        // quantify this var
+        assert( Cudd_bddLeq( dd, pVar->bParts, dd->vars[iNode2] ) );
+        pVar->bParts = Cudd_bddExistAbstract( dd, bTemp = pVar->bParts, dd->vars[iNode2] ); Cudd_Ref( pVar->bParts );
+        Cudd_RecursiveDeref( dd, bTemp );
+        // add the new var
+        pVar->bParts = Cudd_bddAnd( dd, bTemp = pVar->bParts, dd->vars[iNode1] ); Cudd_Ref( pVar->bParts );
+        Cudd_RecursiveDeref( dd, bTemp );
+        // update the score
+        pVar->nParts = Extra_bddSuppSize( dd, pVar->bParts );
+    }
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Merges the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Extra_ImageNode_t * Extra_MergeTopNodes(
+    DdManager * dd, int nNodes, Extra_ImageNode_t ** pNodes )
+{
+    Extra_ImageNode_t * pNode;
+    int n1 = -1, n2 = -1, n;
+
+    // find the first and the second non-empty spots
+    for ( n = 0; n < nNodes; n++ )
+        if ( pNodes[n] )
+        {
+            if ( n1 == -1 )
+                n1 = n;
+            else if ( n2 == -1 )
+            {
+                n2 = n;
+                break;
+            }
+        }
+    assert( n1 != -1 );
+    // check the situation when only one such node is detected
+    if ( n2 == -1 )
+    {
+        // save the node
+        pNode = pNodes[n1];
+        // clean the node
+        pNodes[n1] = NULL;
+        return pNode;
+    }
+  
+    // combines two nodes
+    pNode = Extra_CombineTwoNodes( dd, b1, pNodes[n1], pNodes[n2] );
+
+    // clean the old nodes
+    pNodes[n1] = pNode;
+    pNodes[n2] = NULL;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Extra_ImageNode_t * Extra_CombineTwoNodes( DdManager * dd, DdNode * bCube,
+    Extra_ImageNode_t * pNode1, Extra_ImageNode_t * pNode2 )
+{
+    Extra_ImageNode_t * pNode;
+    Extra_ImagePart_t * pPart;
+
+    // create a new partition
+    pPart = ABC_ALLOC( Extra_ImagePart_t, 1 );
+    memset( pPart, 0, sizeof(Extra_ImagePart_t) );
+    // create the function
+    pPart->bFunc = Cudd_bddAndAbstract( dd, pNode1->pPart->bFunc, pNode2->pPart->bFunc, bCube );
+    Cudd_Ref( pPart->bFunc );
+    // update the support the partition
+    pPart->bSupp = Cudd_bddAndAbstract( dd, pNode1->pPart->bSupp, pNode2->pPart->bSupp, bCube );
+    Cudd_Ref( pPart->bSupp );
+    // update the numbers
+    pPart->nSupp  = Extra_bddSuppSize( dd, pPart->bSupp );
+    pPart->nNodes = Cudd_DagSize( pPart->bFunc );
+    pPart->iPart = -1;
+/*
+ABC_PRB( dd, pNode1->pPart->bSupp );
+ABC_PRB( dd, pNode2->pPart->bSupp );
+ABC_PRB( dd, pPart->bSupp );
+*/
+    // create a new node
+    pNode = ABC_ALLOC( Extra_ImageNode_t, 1 );
+    memset( pNode, 0, sizeof(Extra_ImageNode_t) );
+    pNode->dd     = dd;
+    pNode->pPart  = pPart;
+    pNode->pNode1 = pNode1;
+    pNode->pNode2 = pNode2;
+    // compute the image
+    pNode->bImage = Cudd_bddAndAbstract( dd, pNode1->bImage, pNode2->bImage, bCube ); 
+    Cudd_Ref( pNode->bImage );
+    // save the cube
+    if ( bCube != b1 )
+    {
+        pNode->bCube = bCube;   Cudd_Ref( bCube );
+    }
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the best variable.]
+
+  Description [The variables is the best if the sum of squares of the
+  BDD sizes of the partitions, in which it participates, is the minimum.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_FindBestVariable( DdManager * dd,
+    int nNodes, Extra_ImageNode_t ** pNodes, 
+    int nVars,  Extra_ImageVar_t ** pVars )
+{
+    DdNode * bTemp;
+    int iVarBest, v;
+    double CostBest, CostCur;
+
+    CostBest = 100000000000000.0;
+    iVarBest = -1;
+    for ( v = 0; v < nVars; v++ )
+        if ( pVars[v] )
+        {
+            CostCur = 0;
+            for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) )
+                CostCur += pNodes[bTemp->index]->pPart->nNodes * 
+                           pNodes[bTemp->index]->pPart->nNodes;
+            if ( CostBest > CostCur )
+            {
+                CostBest = CostCur;
+                iVarBest = v;
+            }
+        }
+    return iVarBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes two smallest partions that have this var.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_FindBestPartitions( DdManager * dd, DdNode * bParts, 
+    int nNodes, Extra_ImageNode_t ** pNodes, 
+    int * piNode1, int * piNode2 )
+{
+    DdNode * bTemp;
+    int iPart1, iPart2;
+    int CostMin1, CostMin2, Cost;
+
+    // go through the partitions
+    iPart1 = iPart2 = -1;
+    CostMin1 = CostMin2 = 1000000;
+    for ( bTemp = bParts; bTemp != b1; bTemp = cuddT(bTemp) )
+    {
+        Cost = pNodes[bTemp->index]->pPart->nNodes;
+        if ( CostMin1 > Cost )
+        {
+            CostMin2 = CostMin1;    iPart2 = iPart1;
+            CostMin1 = Cost;        iPart1 = bTemp->index;
+        }
+        else if ( CostMin2 > Cost )
+        {
+            CostMin2 = Cost;        iPart2 = bTemp->index;
+        }
+    }
+
+    *piNode1 = iPart1;
+    *piNode2 = iPart2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the latch dependency matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_bddImagePrintLatchDependency( 
+    DdManager * dd, DdNode * bCare, // the care set
+    int nParts, DdNode ** pbParts,  // the partitions for image computation
+    int nVars, DdNode ** pbVars )   // the NS and parameter variables (not quantified!)
+{
+    int i;
+    DdNode * bVarsCs, * bVarsNs;
+
+    bVarsCs = Cudd_Support( dd, bCare );                       Cudd_Ref( bVarsCs );
+    bVarsNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars );  Cudd_Ref( bVarsNs );
+
+    printf( "The latch dependency matrix:\n" );
+    printf( "Partitions = %d   Variables: total = %d  non-quantifiable = %d\n",
+        nParts, dd->size, nVars );
+    printf( "     : " );
+    for ( i = 0; i < dd->size; i++ )
+        printf( "%d", i % 10 );
+    printf( "\n" );
+
+    for ( i = 0; i < nParts; i++ )
+        Extra_bddImagePrintLatchDependencyOne( dd, pbParts[i], bVarsCs, bVarsNs, i );
+    Extra_bddImagePrintLatchDependencyOne( dd, bCare, bVarsCs, bVarsNs, nParts );
+
+    Cudd_RecursiveDeref( dd, bVarsCs );
+    Cudd_RecursiveDeref( dd, bVarsNs );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints one row of the latch dependency matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_bddImagePrintLatchDependencyOne(
+    DdManager * dd, DdNode * bFunc,      // the function
+    DdNode * bVarsCs, DdNode * bVarsNs,  // the current/next state vars
+    int iPart )
+{
+    DdNode * bSupport;
+    int v;
+    bSupport = Cudd_Support( dd, bFunc );  Cudd_Ref( bSupport );
+    printf( " %3d : ", iPart );
+    for ( v = 0; v < dd->size; v++ )
+    {
+        if ( Cudd_bddLeq( dd, bSupport, dd->vars[v] ) )
+        {
+            if ( Cudd_bddLeq( dd, bVarsCs, dd->vars[v] ) )
+                printf( "c" );
+            else if ( Cudd_bddLeq( dd, bVarsNs, dd->vars[v] ) ) 
+                printf( "n" );
+            else
+                printf( "i" );
+        }
+        else
+            printf( "." );
+    }
+    printf( "\n" );
+    Cudd_RecursiveDeref( dd, bSupport );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the tree for quenstification scheduling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_bddImagePrintTree( Extra_ImageTree_t * pTree )
+{
+    printf( "The quantification scheduling tree:\n" );
+    Extra_bddImagePrintTree_rec( pTree->pRoot, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the tree for quenstification scheduling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_bddImagePrintTree_rec( Extra_ImageNode_t * pNode, int Offset )
+{
+    DdNode * Cube;
+    int i;
+
+    Cube = pNode->bCube;
+
+    if ( pNode->pNode1 == NULL )
+    {
+        printf( "<%d> ", pNode->pPart->iPart );
+        if ( Cube != NULL )
+        {
+            ABC_PRB( pNode->dd, Cube );
+        }
+        else
+            printf( "\n" );
+        return;
+    }
+
+    printf( "<*> " );
+    if ( Cube != NULL )
+    {
+        ABC_PRB( pNode->dd, Cube );
+    }
+    else
+        printf( "\n" );
+
+    for ( i = 0; i < Offset; i++ )
+        printf( "    " );
+    Extra_bddImagePrintTree_rec( pNode->pNode1, Offset + 1 );
+
+    for ( i = 0; i < Offset; i++ )
+        printf( "    " );
+    Extra_bddImagePrintTree_rec( pNode->pNode2, Offset + 1 );
+}
+
+
+
+
+
+struct Extra_ImageTree2_t_
+{
+    DdManager * dd;
+    DdNode *    bRel;
+    DdNode *    bCube;
+    DdNode *    bImage;
+};
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the monolithic image computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Extra_ImageTree2_t * Extra_bddImageStart2( 
+    DdManager * dd, DdNode * bCare,
+    int nParts, DdNode ** pbParts,
+    int nVars, DdNode ** pbVars, int fVerbose )
+{
+    Extra_ImageTree2_t * pTree;
+    DdNode * bCubeAll, * bCubeNot, * bTemp;
+    int i;
+
+    pTree = ABC_ALLOC( Extra_ImageTree2_t, 1 );
+    pTree->dd = dd;
+    pTree->bImage = NULL;
+
+    bCubeAll = Extra_bddComputeCube( dd, dd->vars, dd->size );      Cudd_Ref( bCubeAll );
+    bCubeNot = Extra_bddComputeCube( dd, pbVars,   nVars );         Cudd_Ref( bCubeNot );
+    pTree->bCube = Cudd_bddExistAbstract( dd, bCubeAll, bCubeNot ); Cudd_Ref( pTree->bCube );
+    Cudd_RecursiveDeref( dd, bCubeAll );
+    Cudd_RecursiveDeref( dd, bCubeNot );
+
+    // derive the monolithic relation
+    pTree->bRel = b1;   Cudd_Ref( pTree->bRel );
+    for ( i = 0; i < nParts; i++ )
+    {
+        pTree->bRel = Cudd_bddAnd( dd, bTemp = pTree->bRel, pbParts[i] ); Cudd_Ref( pTree->bRel );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    Extra_bddImageCompute2( pTree, bCare );
+    return pTree;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_bddImageCompute2( Extra_ImageTree2_t * pTree, DdNode * bCare )
+{
+    if ( pTree->bImage )
+        Cudd_RecursiveDeref( pTree->dd, pTree->bImage );
+    pTree->bImage = Cudd_bddAndAbstract( pTree->dd, pTree->bRel, bCare, pTree->bCube ); 
+    Cudd_Ref( pTree->bImage );
+    return pTree->bImage;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_bddImageTreeDelete2( Extra_ImageTree2_t * pTree )
+{
+    if ( pTree->bRel )
+        Cudd_RecursiveDeref( pTree->dd, pTree->bRel );
+    if ( pTree->bCube )
+        Cudd_RecursiveDeref( pTree->dd, pTree->bCube );
+    if ( pTree->bImage )
+        Cudd_RecursiveDeref( pTree->dd, pTree->bImage );
+    ABC_FREE( pTree );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the previously computed image.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_bddImageRead2( Extra_ImageTree2_t * pTree )
+{
+    return pTree->bImage;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraBddKmap.c b/abc-build/src/misc/extra/extraBddKmap.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraBddKmap.c
@@ -0,0 +1,874 @@
+/**CFile****************************************************************
+
+  FileName    [extraBddKmap.c]
+
+  PackageName [extra]
+
+  Synopsis    [Visualizing the K-map.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - September 1, 2003.]
+
+  Revision    [$Id: extraBddKmap.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $]
+
+***********************************************************************/
+
+///      K-map visualization using pseudo graphics      ///
+///       Version 1.0. Started - August 20, 2000        ///
+///     Version 2.0. Added to EXTRA - July 17, 2001     ///
+
+#include "extraBdd.h"
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+// the maximum number of variables in the Karnaugh Map
+#define MAXVARS 20
+
+/*
+// single line
+#define SINGLE_VERTICAL     (char)179
+#define SINGLE_HORIZONTAL   (char)196
+#define SINGLE_TOP_LEFT     (char)218
+#define SINGLE_TOP_RIGHT    (char)191
+#define SINGLE_BOT_LEFT     (char)192
+#define SINGLE_BOT_RIGHT    (char)217
+
+// double line
+#define DOUBLE_VERTICAL     (char)186
+#define DOUBLE_HORIZONTAL   (char)205
+#define DOUBLE_TOP_LEFT     (char)201
+#define DOUBLE_TOP_RIGHT    (char)187
+#define DOUBLE_BOT_LEFT     (char)200
+#define DOUBLE_BOT_RIGHT    (char)188
+
+// line intersections
+#define SINGLES_CROSS       (char)197
+#define DOUBLES_CROSS       (char)206
+#define S_HOR_CROSS_D_VER   (char)215
+#define S_VER_CROSS_D_HOR   (char)216
+
+// single line joining
+#define S_JOINS_S_VER_LEFT  (char)180
+#define S_JOINS_S_VER_RIGHT (char)195
+#define S_JOINS_S_HOR_TOP   (char)193
+#define S_JOINS_S_HOR_BOT   (char)194
+
+// double line joining
+#define D_JOINS_D_VER_LEFT  (char)185
+#define D_JOINS_D_VER_RIGHT (char)204
+#define D_JOINS_D_HOR_TOP   (char)202
+#define D_JOINS_D_HOR_BOT   (char)203
+
+// single line joining double line
+#define S_JOINS_D_VER_LEFT  (char)182
+#define S_JOINS_D_VER_RIGHT (char)199
+#define S_JOINS_D_HOR_TOP   (char)207
+#define S_JOINS_D_HOR_BOT   (char)209
+*/
+
+// single line
+#define SINGLE_VERTICAL     (char)'|'
+#define SINGLE_HORIZONTAL   (char)'-'
+#define SINGLE_TOP_LEFT     (char)'+'
+#define SINGLE_TOP_RIGHT    (char)'+'
+#define SINGLE_BOT_LEFT     (char)'+'
+#define SINGLE_BOT_RIGHT    (char)'+'
+
+// double line
+#define DOUBLE_VERTICAL     (char)'|'
+#define DOUBLE_HORIZONTAL   (char)'-'
+#define DOUBLE_TOP_LEFT     (char)'+'
+#define DOUBLE_TOP_RIGHT    (char)'+'
+#define DOUBLE_BOT_LEFT     (char)'+'
+#define DOUBLE_BOT_RIGHT    (char)'+'
+
+// line intersections
+#define SINGLES_CROSS       (char)'+'
+#define DOUBLES_CROSS       (char)'+'
+#define S_HOR_CROSS_D_VER   (char)'+'
+#define S_VER_CROSS_D_HOR   (char)'+'
+
+// single line joining
+#define S_JOINS_S_VER_LEFT  (char)'+'
+#define S_JOINS_S_VER_RIGHT (char)'+'
+#define S_JOINS_S_HOR_TOP   (char)'+'
+#define S_JOINS_S_HOR_BOT   (char)'+'
+
+// double line joining
+#define D_JOINS_D_VER_LEFT  (char)'+'
+#define D_JOINS_D_VER_RIGHT (char)'+'
+#define D_JOINS_D_HOR_TOP   (char)'+'
+#define D_JOINS_D_HOR_BOT   (char)'+'
+
+// single line joining double line
+#define S_JOINS_D_VER_LEFT  (char)'+'
+#define S_JOINS_D_VER_RIGHT (char)'+'
+#define S_JOINS_D_HOR_TOP   (char)'+'
+#define S_JOINS_D_HOR_BOT   (char)'+'
+
+
+// other symbols
+#define UNDERSCORE          (char)95
+//#define SYMBOL_ZERO       (char)248   // degree sign
+//#define SYMBOL_ZERO         (char)'o'
+#ifdef WIN32
+#define SYMBOL_ZERO         (char)'0'
+#else
+#define SYMBOL_ZERO         (char)' '
+#endif
+#define SYMBOL_ONE          (char)'1'
+#define SYMBOL_DC           (char)'-'
+#define SYMBOL_OVERLAP      (char)'?'
+
+// full cells and half cells
+#define CELL_FREE           (char)32
+#define CELL_FULL           (char)219
+#define HALF_UPPER          (char)223
+#define HALF_LOWER          (char)220
+#define HALF_LEFT           (char)221
+#define HALF_RIGHT          (char)222
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+// the array of BDD variables used internally
+static DdNode * s_XVars[MAXVARS];
+
+// flag which determines where the horizontal variable names are printed
+static int fHorizontalVarNamesPrintedAbove = 1;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+// Oleg's way of generating the gray code
+static int GrayCode( int BinCode );
+static int BinCode ( int GrayCode );
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the K-map of the function.]
+
+  Description [If the pointer to the array of variables XVars is NULL,
+               fSuppType determines how the support will be determined.
+               fSuppType == 0 -- takes the first nVars of the manager
+               fSuppType == 1 -- takes the topmost nVars of the manager
+               fSuppType == 2 -- determines support from the on-set and the offset
+               ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Extra_PrintKMap( 
+  FILE * Output,  /* the output stream */
+  DdManager * dd, 
+  DdNode * OnSet, 
+  DdNode * OffSet, 
+  int nVars, 
+  DdNode ** XVars, 
+  int fSuppType, /* the flag which determines how support is computed */
+  char ** pVarNames )
+{
+    int fPrintTruth = 1;
+    int d, p, n, s, v, h, w;
+    int nVarsVer;
+    int nVarsHor;
+    int nCellsVer;
+    int nCellsHor;
+    int nSkipSpaces;
+
+    // make sure that on-set and off-set do not overlap
+    if ( !Cudd_bddLeq( dd, OnSet, Cudd_Not(OffSet) ) )
+    {
+        fprintf( Output, "PrintKMap(): The on-set and the off-set overlap\n" );
+        return;
+    }
+
+    // print truth table for debugging
+    if ( fPrintTruth )
+    {
+        DdNode * bCube, * bPart;
+        printf( "Truth table: " );
+        if ( nVars == 0 )
+            printf( "Constant" );
+        else if ( nVars == 1 )
+            printf( "1-var function" );
+        else
+        {
+//            printf( "0x" );
+            for ( d = (1<<(nVars-2)) - 1; d >= 0; d-- )
+            {
+                int Value = 0;
+                for ( s = 0; s < 4; s++ )
+                {
+                    bCube = Extra_bddBitsToCube( dd, 4*d+s, nVars, dd->vars, 0 );   Cudd_Ref( bCube );
+                    bPart = Cudd_Cofactor( dd, OnSet, bCube );                      Cudd_Ref( bPart );
+                    Value |= ((int)(bPart == b1) << s);
+                    Cudd_RecursiveDeref( dd, bPart );
+                    Cudd_RecursiveDeref( dd, bCube );
+                }
+                if ( Value < 10 )
+                    fprintf( stdout, "%d", Value );
+                else
+                    fprintf( stdout, "%c", 'a' + Value-10 );
+            }
+        }
+        printf( "\n" );
+    }
+
+
+/*
+    if ( OnSet == b1 )
+    {
+        fprintf( Output, "PrintKMap(): Constant 1\n" );
+        return;
+    }
+    if ( OffSet == b1 )
+    {
+        fprintf( Output, "PrintKMap(): Constant 0\n" );
+        return;
+    }
+*/
+    if ( nVars < 0 || nVars > MAXVARS )
+    {
+        fprintf( Output, "PrintKMap(): The number of variables is less than zero or more than %d\n", MAXVARS );
+        return;
+    }
+
+    // determine the support if it is not given
+    if ( XVars == NULL )
+    {
+        if ( fSuppType == 0 )
+        {   // assume that the support includes the first nVars of the manager
+            assert( nVars );
+            for ( v = 0; v < nVars; v++ )
+                s_XVars[v] = Cudd_bddIthVar( dd, v );
+        }
+        else if ( fSuppType == 1 )
+        {   // assume that the support includes the topmost nVars of the manager
+            assert( nVars );
+            for ( v = 0; v < nVars; v++ )
+                s_XVars[v] = Cudd_bddIthVar( dd, dd->invperm[v] );
+        }
+        else // determine the support
+        {
+            DdNode * SuppOn, * SuppOff, * Supp;
+            int cVars = 0;
+            DdNode * TempSupp;
+
+            // determine support
+            SuppOn = Cudd_Support( dd, OnSet );         Cudd_Ref( SuppOn );
+            SuppOff = Cudd_Support( dd, OffSet );       Cudd_Ref( SuppOff );
+            Supp = Cudd_bddAnd( dd, SuppOn, SuppOff );  Cudd_Ref( Supp );
+            Cudd_RecursiveDeref( dd, SuppOn );
+            Cudd_RecursiveDeref( dd, SuppOff );
+
+            nVars = Cudd_SupportSize( dd, Supp );
+            if ( nVars > MAXVARS )
+            {
+                fprintf( Output, "PrintKMap(): The number of variables is more than %d\n", MAXVARS );
+                Cudd_RecursiveDeref( dd, Supp );
+                return;
+            }
+
+            // assign variables
+            for ( TempSupp = Supp; TempSupp != dd->one; TempSupp = Cudd_T(TempSupp), cVars++ )
+                s_XVars[cVars] = Cudd_bddIthVar( dd, TempSupp->index );
+
+            Cudd_RecursiveDeref( dd, TempSupp );
+        }
+    }
+    else
+    {
+        // copy variables
+        assert( XVars );
+        for ( v = 0; v < nVars; v++ )
+            s_XVars[v] = XVars[v];
+    }
+
+    ////////////////////////////////////////////////////////////////////
+    // determine the Karnaugh map parameters
+    nVarsVer = nVars/2;
+    nVarsHor = nVars - nVarsVer;
+
+    nCellsVer = (1<<nVarsVer);
+    nCellsHor = (1<<nVarsHor);
+    nSkipSpaces = nVarsVer + 1;
+
+    ////////////////////////////////////////////////////////////////////
+    // print variable names
+    fprintf( Output, "\n" );
+    for ( w = 0; w < nVarsVer; w++ )
+        if ( pVarNames == NULL )
+            fprintf( Output, "%c", 'a'+nVarsHor+w );
+        else
+            fprintf( Output, " %s", pVarNames[nVarsHor+w] );
+
+    if ( fHorizontalVarNamesPrintedAbove )
+    {
+        fprintf( Output, " \\ " );
+        for ( w = 0; w < nVarsHor; w++ )
+            if ( pVarNames == NULL )
+                fprintf( Output, "%c", 'a'+w );
+            else
+                fprintf( Output, "%s ", pVarNames[w] );
+    }
+    fprintf( Output, "\n" );
+
+    if ( fHorizontalVarNamesPrintedAbove )
+    {
+        ////////////////////////////////////////////////////////////////////
+        // print horizontal digits
+        for ( d = 0; d < nVarsHor; d++ )
+        {
+            for ( p = 0; p < nSkipSpaces + 2; p++, fprintf( Output, " " ) );
+            for ( n = 0; n < nCellsHor; n++ )
+                if ( GrayCode(n) & (1<<(nVarsHor-1-d)) )
+                    fprintf( Output, "1   " );
+                else
+                    fprintf( Output, "0   " );
+            fprintf( Output, "\n" );
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////////
+    // print the upper line
+    for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+    fprintf( Output, "%c", DOUBLE_TOP_LEFT );
+    for ( s = 0; s < nCellsHor; s++ )
+    {
+        fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+        fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+        fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+        if ( s != nCellsHor-1 )
+        {
+            if ( s&1 )
+                fprintf( Output, "%c", D_JOINS_D_HOR_BOT );
+            else
+                fprintf( Output, "%c", S_JOINS_D_HOR_BOT );
+        }
+    }
+    fprintf( Output, "%c", DOUBLE_TOP_RIGHT );
+    fprintf( Output, "\n" );
+
+    ////////////////////////////////////////////////////////////////////
+    // print the map
+    for ( v = 0; v < nCellsVer; v++ )
+    {
+        DdNode * CubeVerBDD;
+
+        // print horizontal digits
+//      for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+        for ( n = 0; n < nVarsVer; n++ )
+            if ( GrayCode(v) & (1<<(nVarsVer-1-n)) )
+                fprintf( Output, "1" );
+            else
+                fprintf( Output, "0" );
+        fprintf( Output, " " );
+
+        // find vertical cube
+        CubeVerBDD = Extra_bddBitsToCube( dd, GrayCode(v), nVarsVer, s_XVars+nVarsHor, 1 );    Cudd_Ref( CubeVerBDD );
+
+        // print text line
+        fprintf( Output, "%c", DOUBLE_VERTICAL );
+        for ( h = 0; h < nCellsHor; h++ )
+        {
+            DdNode * CubeHorBDD, * Prod, * ValueOnSet, * ValueOffSet;
+
+            fprintf( Output, " " );
+//          fprintf( Output, "x" );
+            ///////////////////////////////////////////////////////////////
+            // determine what should be printed
+            CubeHorBDD  = Extra_bddBitsToCube( dd, GrayCode(h), nVarsHor, s_XVars, 1 );    Cudd_Ref( CubeHorBDD );
+            Prod = Cudd_bddAnd( dd, CubeHorBDD, CubeVerBDD );                   Cudd_Ref( Prod );
+            Cudd_RecursiveDeref( dd, CubeHorBDD );
+
+            ValueOnSet  = Cudd_Cofactor( dd, OnSet, Prod );                     Cudd_Ref( ValueOnSet );
+            ValueOffSet = Cudd_Cofactor( dd, OffSet, Prod );                    Cudd_Ref( ValueOffSet );
+            Cudd_RecursiveDeref( dd, Prod );
+
+#ifdef WIN32
+            {
+            HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+            char Symb = 0, Color = 0;
+            if ( ValueOnSet == b1 && ValueOffSet == b0 )
+                Symb = SYMBOL_ONE,     Color = 14;  // yellow
+            else if ( ValueOnSet == b0 && ValueOffSet == b1 )
+                Symb = SYMBOL_ZERO,    Color = 11;  // blue
+            else if ( ValueOnSet == b0 && ValueOffSet == b0 ) 
+                Symb = SYMBOL_DC,      Color = 10;  // green
+            else if ( ValueOnSet == b1 && ValueOffSet == b1 ) 
+                Symb = SYMBOL_OVERLAP, Color = 12;  // red
+            else
+                assert(0);
+            SetConsoleTextAttribute( hConsole, Color );
+            fprintf( Output, "%c", Symb );
+            SetConsoleTextAttribute( hConsole, 7 );
+            }
+#else
+            {
+            if ( ValueOnSet == b1 && ValueOffSet == b0 )
+                fprintf( Output, "%c", SYMBOL_ONE );
+            else if ( ValueOnSet == b0 && ValueOffSet == b1 )
+                fprintf( Output, "%c", SYMBOL_ZERO );
+            else if ( ValueOnSet == b0 && ValueOffSet == b0 ) 
+                fprintf( Output, "%c", SYMBOL_DC );
+            else if ( ValueOnSet == b1 && ValueOffSet == b1 ) 
+                fprintf( Output, "%c", SYMBOL_OVERLAP );
+            else
+                assert(0);
+            }
+#endif
+
+            Cudd_RecursiveDeref( dd, ValueOnSet );
+            Cudd_RecursiveDeref( dd, ValueOffSet );
+            ///////////////////////////////////////////////////////////////
+            fprintf( Output, " " );
+
+            if ( h != nCellsHor-1 )
+            {
+                if ( h&1 )
+                    fprintf( Output, "%c", DOUBLE_VERTICAL );
+                else
+                    fprintf( Output, "%c", SINGLE_VERTICAL );
+            }
+        }
+        fprintf( Output, "%c", DOUBLE_VERTICAL );
+        fprintf( Output, "\n" );
+
+        Cudd_RecursiveDeref( dd, CubeVerBDD );
+
+        if ( v != nCellsVer-1 )
+        // print separator line
+        {
+            for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+            if ( v&1 )
+            {
+                fprintf( Output, "%c", D_JOINS_D_VER_RIGHT );
+                for ( s = 0; s < nCellsHor; s++ )
+                {
+                    fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+                    fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+                    fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+                    if ( s != nCellsHor-1 )
+                    {
+                        if ( s&1 )
+                            fprintf( Output, "%c", DOUBLES_CROSS );
+                        else
+                            fprintf( Output, "%c", S_VER_CROSS_D_HOR );
+                    }
+                }
+                fprintf( Output, "%c", D_JOINS_D_VER_LEFT );
+            }
+            else
+            {
+                fprintf( Output, "%c", S_JOINS_D_VER_RIGHT );
+                for ( s = 0; s < nCellsHor; s++ )
+                {
+                    fprintf( Output, "%c", SINGLE_HORIZONTAL );
+                    fprintf( Output, "%c", SINGLE_HORIZONTAL );
+                    fprintf( Output, "%c", SINGLE_HORIZONTAL );
+                    if ( s != nCellsHor-1 )
+                    {
+                        if ( s&1 )
+                            fprintf( Output, "%c", S_HOR_CROSS_D_VER );
+                        else
+                            fprintf( Output, "%c", SINGLES_CROSS );
+                    }
+                }
+                fprintf( Output, "%c", S_JOINS_D_VER_LEFT );
+            }
+            fprintf( Output, "\n" );
+        }
+    }
+    
+    ////////////////////////////////////////////////////////////////////
+    // print the lower line
+    for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+    fprintf( Output, "%c", DOUBLE_BOT_LEFT );
+    for ( s = 0; s < nCellsHor; s++ )
+    {
+        fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+        fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+        fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+        if ( s != nCellsHor-1 )
+        {
+            if ( s&1 )
+                fprintf( Output, "%c", D_JOINS_D_HOR_TOP );
+            else
+                fprintf( Output, "%c", S_JOINS_D_HOR_TOP );
+        }
+    }
+    fprintf( Output, "%c", DOUBLE_BOT_RIGHT );
+    fprintf( Output, "\n" );
+
+    if ( !fHorizontalVarNamesPrintedAbove )
+    {
+        ////////////////////////////////////////////////////////////////////
+        // print horizontal digits
+        for ( d = 0; d < nVarsHor; d++ )
+        {
+            for ( p = 0; p < nSkipSpaces + 2; p++, fprintf( Output, " " ) );
+            for ( n = 0; n < nCellsHor; n++ )
+                if ( GrayCode(n) & (1<<(nVarsHor-1-d)) )
+                    fprintf( Output, "1   " );
+                else
+                    fprintf( Output, "0   " );
+
+            /////////////////////////////////
+            fprintf( Output, "%c", (char)('a'+d) );
+            /////////////////////////////////
+            fprintf( Output, "\n" );
+        }
+    }
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the K-map of the relation.]
+
+  Description [Assumes that the relation depends the first nXVars of XVars and 
+  the first nYVars of YVars. Draws X and Y vars and vertical and horizontal vars.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Extra_PrintKMapRelation( 
+  FILE * Output,  /* the output stream */
+  DdManager * dd, 
+  DdNode * OnSet, 
+  DdNode * OffSet, 
+  int nXVars, 
+  int nYVars, 
+  DdNode ** XVars, 
+  DdNode ** YVars ) /* the flag which determines how support is computed */
+{
+    int d, p, n, s, v, h, w;
+    int nVars;
+    int nVarsVer;
+    int nVarsHor;
+    int nCellsVer;
+    int nCellsHor;
+    int nSkipSpaces;
+
+    // make sure that on-set and off-set do not overlap
+    if ( !Cudd_bddLeq( dd, OnSet, Cudd_Not(OffSet) ) )
+    {
+        fprintf( Output, "PrintKMap(): The on-set and the off-set overlap\n" );
+        return;
+    }
+
+    if ( OnSet == b1 )
+    {
+        fprintf( Output, "PrintKMap(): Constant 1\n" );
+        return;
+    }
+    if ( OffSet == b1 )
+    {
+        fprintf( Output, "PrintKMap(): Constant 0\n" );
+        return;
+    }
+
+    nVars = nXVars + nYVars;
+    if ( nVars < 0 || nVars > MAXVARS )
+    {
+        fprintf( Output, "PrintKMap(): The number of variables is less than zero or more than %d\n", MAXVARS );
+        return;
+    }
+
+
+    ////////////////////////////////////////////////////////////////////
+    // determine the Karnaugh map parameters
+    nVarsVer = nXVars;
+    nVarsHor = nYVars;
+    nCellsVer = (1<<nVarsVer);
+    nCellsHor = (1<<nVarsHor);
+    nSkipSpaces = nVarsVer + 1;
+
+    ////////////////////////////////////////////////////////////////////
+    // print variable names
+    fprintf( Output, "\n" );
+    for ( w = 0; w < nVarsVer; w++ )
+        fprintf( Output, "%c", 'a'+nVarsHor+w );
+    if ( fHorizontalVarNamesPrintedAbove )
+    {
+        fprintf( Output, " \\ " );
+        for ( w = 0; w < nVarsHor; w++ )
+            fprintf( Output, "%c", 'a'+w );
+    }
+    fprintf( Output, "\n" );
+
+    if ( fHorizontalVarNamesPrintedAbove )
+    {
+        ////////////////////////////////////////////////////////////////////
+        // print horizontal digits
+        for ( d = 0; d < nVarsHor; d++ )
+        {
+            for ( p = 0; p < nSkipSpaces + 2; p++, fprintf( Output, " " ) );
+            for ( n = 0; n < nCellsHor; n++ )
+                if ( GrayCode(n) & (1<<(nVarsHor-1-d)) )
+                    fprintf( Output, "1   " );
+                else
+                    fprintf( Output, "0   " );
+            fprintf( Output, "\n" );
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////////
+    // print the upper line
+    for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+    fprintf( Output, "%c", DOUBLE_TOP_LEFT );
+    for ( s = 0; s < nCellsHor; s++ )
+    {
+        fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+        fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+        fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+        if ( s != nCellsHor-1 )
+        {
+            if ( s&1 )
+                fprintf( Output, "%c", D_JOINS_D_HOR_BOT );
+            else
+                fprintf( Output, "%c", S_JOINS_D_HOR_BOT );
+        }
+    }
+    fprintf( Output, "%c", DOUBLE_TOP_RIGHT );
+    fprintf( Output, "\n" );
+
+    ////////////////////////////////////////////////////////////////////
+    // print the map
+    for ( v = 0; v < nCellsVer; v++ )
+    {
+        DdNode * CubeVerBDD;
+
+        // print horizontal digits
+//      for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+        for ( n = 0; n < nVarsVer; n++ )
+            if ( GrayCode(v) & (1<<(nVarsVer-1-n)) )
+                fprintf( Output, "1" );
+            else
+                fprintf( Output, "0" );
+        fprintf( Output, " " );
+
+        // find vertical cube
+//      CubeVerBDD = Extra_bddBitsToCube( dd, GrayCode(v), nVarsVer, s_XVars+nVarsHor );    Cudd_Ref( CubeVerBDD );
+        CubeVerBDD = Extra_bddBitsToCube( dd, GrayCode(v), nXVars, XVars, 1 );                 Cudd_Ref( CubeVerBDD );
+
+        // print text line
+        fprintf( Output, "%c", DOUBLE_VERTICAL );
+        for ( h = 0; h < nCellsHor; h++ )
+        {
+            DdNode * CubeHorBDD, * Prod, * ValueOnSet, * ValueOffSet;
+
+            fprintf( Output, " " );
+//          fprintf( Output, "x" );
+            ///////////////////////////////////////////////////////////////
+            // determine what should be printed
+//          CubeHorBDD  = Extra_bddBitsToCube( dd, GrayCode(h), nVarsHor, s_XVars );    Cudd_Ref( CubeHorBDD );
+            CubeHorBDD  = Extra_bddBitsToCube( dd, GrayCode(h), nYVars, YVars, 1 );        Cudd_Ref( CubeHorBDD );
+            Prod = Cudd_bddAnd( dd, CubeHorBDD, CubeVerBDD );                           Cudd_Ref( Prod );
+            Cudd_RecursiveDeref( dd, CubeHorBDD );
+
+            ValueOnSet  = Cudd_Cofactor( dd, OnSet, Prod );                     Cudd_Ref( ValueOnSet );
+            ValueOffSet = Cudd_Cofactor( dd, OffSet, Prod );                    Cudd_Ref( ValueOffSet );
+            Cudd_RecursiveDeref( dd, Prod );
+
+            if ( ValueOnSet == b1 && ValueOffSet == b0 )
+                fprintf( Output, "%c", SYMBOL_ONE );
+            else if ( ValueOnSet == b0 && ValueOffSet == b1 )
+                fprintf( Output, "%c", SYMBOL_ZERO );
+            else if ( ValueOnSet == b0 && ValueOffSet == b0 ) 
+                fprintf( Output, "%c", SYMBOL_DC );
+            else if ( ValueOnSet == b1 && ValueOffSet == b1 ) 
+                fprintf( Output, "%c", SYMBOL_OVERLAP );
+            else
+                assert(0);
+
+            Cudd_RecursiveDeref( dd, ValueOnSet );
+            Cudd_RecursiveDeref( dd, ValueOffSet );
+            ///////////////////////////////////////////////////////////////
+            fprintf( Output, " " );
+
+            if ( h != nCellsHor-1 )
+            {
+                if ( h&1 )
+                    fprintf( Output, "%c", DOUBLE_VERTICAL );
+                else
+                    fprintf( Output, "%c", SINGLE_VERTICAL );
+            }
+        }
+        fprintf( Output, "%c", DOUBLE_VERTICAL );
+        fprintf( Output, "\n" );
+
+        Cudd_RecursiveDeref( dd, CubeVerBDD );
+
+        if ( v != nCellsVer-1 )
+        // print separator line
+        {
+            for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+            if ( v&1 )
+            {
+                fprintf( Output, "%c", D_JOINS_D_VER_RIGHT );
+                for ( s = 0; s < nCellsHor; s++ )
+                {
+                    fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+                    fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+                    fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+                    if ( s != nCellsHor-1 )
+                    {
+                        if ( s&1 )
+                            fprintf( Output, "%c", DOUBLES_CROSS );
+                        else
+                            fprintf( Output, "%c", S_VER_CROSS_D_HOR );
+                    }
+                }
+                fprintf( Output, "%c", D_JOINS_D_VER_LEFT );
+            }
+            else
+            {
+                fprintf( Output, "%c", S_JOINS_D_VER_RIGHT );
+                for ( s = 0; s < nCellsHor; s++ )
+                {
+                    fprintf( Output, "%c", SINGLE_HORIZONTAL );
+                    fprintf( Output, "%c", SINGLE_HORIZONTAL );
+                    fprintf( Output, "%c", SINGLE_HORIZONTAL );
+                    if ( s != nCellsHor-1 )
+                    {
+                        if ( s&1 )
+                            fprintf( Output, "%c", S_HOR_CROSS_D_VER );
+                        else
+                            fprintf( Output, "%c", SINGLES_CROSS );
+                    }
+                }
+                fprintf( Output, "%c", S_JOINS_D_VER_LEFT );
+            }
+            fprintf( Output, "\n" );
+        }
+    }
+    
+    ////////////////////////////////////////////////////////////////////
+    // print the lower line
+    for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+    fprintf( Output, "%c", DOUBLE_BOT_LEFT );
+    for ( s = 0; s < nCellsHor; s++ )
+    {
+        fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+        fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+        fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+        if ( s != nCellsHor-1 )
+        {
+            if ( s&1 )
+                fprintf( Output, "%c", D_JOINS_D_HOR_TOP );
+            else
+                fprintf( Output, "%c", S_JOINS_D_HOR_TOP );
+        }
+    }
+    fprintf( Output, "%c", DOUBLE_BOT_RIGHT );
+    fprintf( Output, "\n" );
+
+    if ( !fHorizontalVarNamesPrintedAbove )
+    {
+        ////////////////////////////////////////////////////////////////////
+        // print horizontal digits
+        for ( d = 0; d < nVarsHor; d++ )
+        {
+            for ( p = 0; p < nSkipSpaces + 2; p++, fprintf( Output, " " ) );
+            for ( n = 0; n < nCellsHor; n++ )
+                if ( GrayCode(n) & (1<<(nVarsHor-1-d)) )
+                    fprintf( Output, "1   " );
+                else
+                    fprintf( Output, "0   " );
+
+            /////////////////////////////////
+            fprintf( Output, "%c", (char)('a'+d) );
+            /////////////////////////////////
+            fprintf( Output, "\n" );
+        }
+    }
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int GrayCode ( int BinCode )
+{
+  return BinCode ^ ( BinCode >> 1 );
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int BinCode ( int GrayCode )
+{
+  int bc = GrayCode;
+  while( GrayCode >>= 1 ) bc ^= GrayCode;
+  return bc;
+}
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraBddMisc.c b/abc-build/src/misc/extra/extraBddMisc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraBddMisc.c
@@ -0,0 +1,2034 @@
+/**CFile****************************************************************
+
+  FileName    [extraBddMisc.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [extra]
+
+  Synopsis    [DD-based utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: extraBddMisc.c,v 1.4 2005/10/04 00:19:54 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+// file "extraDdTransfer.c"
+static DdNode * extraTransferPermuteRecur( DdManager * ddS, DdManager * ddD, DdNode * f, st__table * table, int * Permute );
+static DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute );
+static DdNode * cuddBddPermuteRecur ARGS( ( DdManager * manager, DdHashTable * table, DdNode * node, int *permut ) );
+
+static DdNode * extraBddAndPermute( DdHashTable * table, DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute );
+
+// file "cuddUtils.c"
+static void ddSupportStep(DdNode *f, int *support);
+static void ddClearFlag(DdNode *f);
+
+static DdNode* extraZddPrimes( DdManager *dd, DdNode* F );
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Convert a {A,B}DD from a manager to another with variable remapping.]
+
+  Description [Convert a {A,B}DD from a manager to another one. The orders of the
+  variables in the two managers may be different. Returns a
+  pointer to the {A,B}DD in the destination manager if successful; NULL
+  otherwise. The i-th entry in the array Permute tells what is the index
+  of the i-th variable from the old manager in the new manager.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute )
+{
+    DdNode * bRes;
+    do
+    {
+        ddDestination->reordered = 0;
+        bRes = extraTransferPermute( ddSource, ddDestination, f, Permute );
+    }
+    while ( ddDestination->reordered == 1 );
+    return ( bRes );
+
+}                               /* end of Extra_TransferPermute */
+
+/**Function********************************************************************
+
+  Synopsis    [Transfers the BDD from one manager into another level by level.]
+
+  Description [Transfers the BDD from one manager into another while
+  preserving the correspondence between variables level by level.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f )
+{
+    DdNode * bRes;
+    int * pPermute;
+    int nMin, nMax, i;
+
+    nMin = ddMin(ddSource->size, ddDestination->size);
+    nMax = ddMax(ddSource->size, ddDestination->size);
+    pPermute = ABC_ALLOC( int, nMax );
+    // set up the variable permutation
+    for ( i = 0; i < nMin; i++ )
+        pPermute[ ddSource->invperm[i] ] = ddDestination->invperm[i];
+    if ( ddSource->size > ddDestination->size )
+    {
+        for (      ; i < nMax; i++ )
+            pPermute[ ddSource->invperm[i] ] = -1;
+    }
+    bRes = Extra_TransferPermute( ddSource, ddDestination, f, pPermute );
+    ABC_FREE( pPermute );
+    return bRes;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Remaps the function to depend on the topmost variables on the manager.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_bddRemapUp(
+  DdManager * dd,
+  DdNode * bF )
+{
+    int * pPermute;
+    DdNode * bSupp, * bTemp, * bRes;
+    int Counter;
+
+    pPermute = ABC_ALLOC( int, dd->size );
+
+    // get support
+    bSupp = Cudd_Support( dd, bF );    Cudd_Ref( bSupp );
+
+    // create the variable map
+    // to remap the DD into the upper part of the manager
+    Counter = 0;
+    for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) )
+        pPermute[bTemp->index] = dd->invperm[Counter++];
+
+    // transfer the BDD and remap it
+    bRes = Cudd_bddPermute( dd, bF, pPermute );  Cudd_Ref( bRes );
+
+    // remove support
+    Cudd_RecursiveDeref( dd, bSupp );
+
+    // return
+    Cudd_Deref( bRes );
+    ABC_FREE( pPermute );
+    return bRes;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Moves the BDD by the given number of variables up or down.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     [Extra_bddShift]
+
+******************************************************************************/
+DdNode * Extra_bddMove( 
+  DdManager * dd,   /* the DD manager */
+  DdNode * bF,
+  int nVars) 
+{
+    DdNode * res;
+    DdNode * bVars;
+    if ( nVars == 0 )
+        return bF;
+    if ( Cudd_IsConstant(bF) )
+        return bF;
+    assert( nVars <= dd->size );
+    if ( nVars > 0 )
+        bVars = dd->vars[nVars];
+    else
+        bVars = Cudd_Not(dd->vars[-nVars]);
+
+    do {
+        dd->reordered = 0;
+        res = extraBddMove( dd, bF, bVars );
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Extra_bddMove */
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_StopManager( DdManager * dd )
+{
+    int RetValue;
+    // check for remaining references in the package
+    RetValue = Cudd_CheckZeroRef( dd );
+    if ( RetValue > 10 )
+//    if ( RetValue )
+        printf( "\nThe number of referenced nodes = %d\n\n", RetValue );
+//  Cudd_PrintInfo( dd, stdout );
+    Cudd_Quit( dd );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Outputs the BDD in a readable format.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void Extra_bddPrint( DdManager * dd, DdNode * F )
+{
+    DdGen * Gen;
+    int * Cube;
+    CUDD_VALUE_TYPE Value;
+    int nVars = dd->size;
+    int fFirstCube = 1;
+    int i;
+
+    if ( F == NULL )
+    {
+        printf("NULL");
+        return;
+    }
+    if ( F == b0 )
+    {
+        printf("Constant 0");
+        return;
+    }
+    if ( F == b1 )
+    {
+        printf("Constant 1");
+        return;
+    }
+
+    Cudd_ForeachCube( dd, F, Gen, Cube, Value )
+    {
+        if ( fFirstCube )
+            fFirstCube = 0;
+        else
+//          Output << " + ";
+            printf( " + " );
+
+        for ( i = 0; i < nVars; i++ )
+            if ( Cube[i] == 0 )
+                printf( "[%d]'", i );
+//              printf( "%c'", (char)('a'+i) );
+            else if ( Cube[i] == 1 )
+                printf( "[%d]", i );
+//              printf( "%c", (char)('a'+i) );
+    }
+
+//  printf("\n");
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Outputs the BDD in a readable format.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void Extra_bddPrintSupport( DdManager * dd, DdNode * F )
+{
+    DdNode * bSupp;
+    bSupp = Cudd_Support( dd, F );   Cudd_Ref( bSupp );
+    Extra_bddPrint( dd, bSupp );
+    Cudd_RecursiveDeref( dd, bSupp );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the size of the support.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Extra_bddSuppSize( DdManager * dd, DdNode * bSupp )
+{
+    int Counter = 0;
+    while ( bSupp != b1 )
+    {
+        assert( !Cudd_IsComplement(bSupp) );
+        assert( cuddE(bSupp) == b0 );
+
+        bSupp = cuddT(bSupp);
+        Counter++;
+    }
+    return Counter;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if the support contains the given BDD variable.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Extra_bddSuppContainVar( DdManager * dd, DdNode * bS, DdNode * bVar )   
+{ 
+    for( ; bS != b1; bS = cuddT(bS) )
+        if ( bS->index == bVar->index )
+            return 1;
+    return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if two supports represented as BDD cubes are overlapping.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Extra_bddSuppOverlapping( DdManager * dd, DdNode * S1, DdNode * S2 )
+{
+    while ( S1->index != CUDD_CONST_INDEX && S2->index != CUDD_CONST_INDEX )
+    {
+        // if the top vars are the same, they intersect
+        if ( S1->index == S2->index )
+            return 1;
+        // if the top vars are different, skip the one, which is higher
+        if ( dd->perm[S1->index] < dd->perm[S2->index] )
+            S1 = cuddT(S1);
+        else
+            S2 = cuddT(S2);
+    }
+    return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of different vars in two supports.]
+
+  Description [Counts the number of variables that appear in one support and 
+  does not appear in other support. If the number exceeds DiffMax, returns DiffMax.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Extra_bddSuppDifferentVars( DdManager * dd, DdNode * S1, DdNode * S2, int DiffMax )
+{
+    int Result = 0;
+    while ( S1->index != CUDD_CONST_INDEX && S2->index != CUDD_CONST_INDEX )
+    {
+        // if the top vars are the same, this var is the same
+        if ( S1->index == S2->index )
+        {
+            S1 = cuddT(S1);
+            S2 = cuddT(S2);
+            continue;
+        }
+        // the top var is different
+        Result++;
+
+        if ( Result >= DiffMax )
+            return DiffMax;
+
+        // if the top vars are different, skip the one, which is higher
+        if ( dd->perm[S1->index] < dd->perm[S2->index] )
+            S1 = cuddT(S1);
+        else
+            S2 = cuddT(S2);
+    }
+
+    // consider the remaining variables
+    if ( S1->index != CUDD_CONST_INDEX )
+        Result += Extra_bddSuppSize(dd,S1);
+    else if ( S2->index != CUDD_CONST_INDEX )
+        Result += Extra_bddSuppSize(dd,S2);
+
+    if ( Result >= DiffMax )
+        return DiffMax;
+    return Result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the support containment.]
+
+  Description [This function returns 1 if one support is contained in another.
+  In this case, bLarge (bSmall) is assigned to point to the larger (smaller) support.
+  If the supports are identical, return 0 and does not assign the supports!]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Extra_bddSuppCheckContainment( DdManager * dd, DdNode * bL, DdNode * bH, DdNode ** bLarge, DdNode ** bSmall )
+{
+    DdNode * bSL = bL;
+    DdNode * bSH = bH;
+    int fLcontainsH = 1;
+    int fHcontainsL = 1;
+    int TopVar;
+    
+    if ( bSL == bSH )
+        return 0;
+
+    while ( bSL != b1 || bSH != b1 )
+    {
+        if ( bSL == b1 )
+        { // Low component has no vars; High components has some vars
+            fLcontainsH = 0;
+            if ( fHcontainsL == 0 )
+                return 0;
+            else
+                break;
+        }
+
+        if ( bSH == b1 )
+        { // similarly
+            fHcontainsL = 0;
+            if ( fLcontainsH == 0 )
+                return 0;
+            else
+                break;
+        }
+
+        // determine the topmost var of the supports by comparing their levels
+        if ( dd->perm[bSL->index] < dd->perm[bSH->index] )
+            TopVar = bSL->index;
+        else
+            TopVar = bSH->index;
+
+        if ( TopVar == bSL->index && TopVar == bSH->index ) 
+        { // they are on the same level
+            // it does not tell us anything about their containment
+            // skip this var
+            bSL = cuddT(bSL);
+            bSH = cuddT(bSH);
+        }
+        else if ( TopVar == bSL->index ) // and TopVar != bSH->index
+        { // Low components is higher and contains more vars
+            // it is not possible that High component contains Low
+            fHcontainsL = 0;
+            // skip this var
+            bSL = cuddT(bSL);
+        }
+        else // if ( TopVar == bSH->index ) // and TopVar != bSL->index
+        { // similarly
+            fLcontainsH = 0;
+            // skip this var
+            bSH = cuddT(bSH);
+        }
+
+        // check the stopping condition
+        if ( !fHcontainsL && !fLcontainsH )
+            return 0;
+    }
+    // only one of them can be true at the same time
+    assert( !fHcontainsL || !fLcontainsH );
+    if ( fHcontainsL )
+    {
+        *bLarge = bH;
+        *bSmall = bL;
+    }
+    else // fLcontainsH
+    {
+        *bLarge = bL;
+        *bSmall = bH;
+    }
+    return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds variables on which the DD depends and returns them as am array.]
+
+  Description [Finds the variables on which the DD depends. Returns an array 
+  with entries set to 1 for those variables that belong to the support; 
+  NULL otherwise. The array is allocated by the user and should have at least
+  as many entries as the maximum number of variables in BDD and ZDD parts of 
+  the manager.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Support Cudd_VectorSupport Cudd_ClassifySupport]
+
+******************************************************************************/
+int * 
+Extra_SupportArray(
+  DdManager * dd, /* manager */
+  DdNode * f,     /* DD whose support is sought */
+  int * support ) /* array allocated by the user */
+{
+    int i, size;
+
+    /* Initialize support array for ddSupportStep. */
+    size = ddMax(dd->size, dd->sizeZ);
+    for (i = 0; i < size; i++) 
+        support[i] = 0;
+    
+    /* Compute support and clean up markers. */
+    ddSupportStep(Cudd_Regular(f),support);
+    ddClearFlag(Cudd_Regular(f));
+
+    return(support);
+
+} /* end of Extra_SupportArray */
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the variables on which a set of DDs depends.]
+
+  Description [Finds the variables on which a set of DDs depends.
+  The set must contain either BDDs and ADDs, or ZDDs.
+  Returns a BDD consisting of the product of the variables if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Support Cudd_ClassifySupport]
+
+******************************************************************************/
+int *
+Extra_VectorSupportArray( 
+  DdManager * dd, /* manager */ 
+  DdNode ** F, /* array of DDs whose support is sought */ 
+  int n, /* size of the array */  
+  int * support ) /* array allocated by the user */
+{
+    int i, size;
+
+    /* Allocate and initialize support array for ddSupportStep. */
+    size = ddMax( dd->size, dd->sizeZ );
+    for ( i = 0; i < size; i++ )
+        support[i] = 0;
+
+    /* Compute support and clean up markers. */
+    for ( i = 0; i < n; i++ )
+        ddSupportStep( Cudd_Regular(F[i]), support );
+    for ( i = 0; i < n; i++ )
+        ddClearFlag( Cudd_Regular(F[i]) );
+
+    return support;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Find any cube belonging to the on-set of the function.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *  Extra_bddFindOneCube( DdManager * dd, DdNode * bF )
+{
+    char * s_Temp;
+    DdNode * bCube, * bTemp;
+    int v;
+
+    // get the vector of variables in the cube
+    s_Temp = ABC_ALLOC( char, dd->size );
+    Cudd_bddPickOneCube( dd, bF, s_Temp );
+
+    // start the cube
+    bCube = b1; Cudd_Ref( bCube );
+    for ( v = 0; v < dd->size; v++ )
+        if ( s_Temp[v] == 0 )
+        {
+//          Cube &= !s_XVars[v];
+            bCube = Cudd_bddAnd( dd, bTemp = bCube, Cudd_Not(dd->vars[v]) ); Cudd_Ref( bCube );
+            Cudd_RecursiveDeref( dd, bTemp );
+        }
+        else if ( s_Temp[v] == 1 )
+        {
+//          Cube &=  s_XVars[v];
+            bCube = Cudd_bddAnd( dd, bTemp = bCube,          dd->vars[v]  ); Cudd_Ref( bCube );
+            Cudd_RecursiveDeref( dd, bTemp );
+        }
+    Cudd_Deref(bCube);
+    ABC_FREE( s_Temp );
+    return bCube;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns one cube contained in the given BDD.]
+
+  Description [This function returns the cube with the smallest 
+  bits-to-integer value.]
+
+  SideEffects []
+
+******************************************************************************/
+DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc )
+{
+    DdNode * bFuncR, * bFunc0, * bFunc1;
+    DdNode * bRes0,  * bRes1,  * bRes;
+
+    bFuncR = Cudd_Regular(bFunc);
+    if ( cuddIsConstant(bFuncR) )
+        return bFunc;
+
+    // cofactor
+    if ( Cudd_IsComplement(bFunc) )
+    {
+        bFunc0 = Cudd_Not( cuddE(bFuncR) );
+        bFunc1 = Cudd_Not( cuddT(bFuncR) );
+    }
+    else
+    {
+        bFunc0 = cuddE(bFuncR);
+        bFunc1 = cuddT(bFuncR);
+    }
+
+    // try to find the cube with the negative literal
+    bRes0 = Extra_bddGetOneCube( dd, bFunc0 );  Cudd_Ref( bRes0 );
+
+    if ( bRes0 != b0 )
+    {
+        bRes = Cudd_bddAnd( dd, bRes0, Cudd_Not(dd->vars[bFuncR->index]) ); Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( dd, bRes0 );
+    }
+    else
+    {
+        Cudd_RecursiveDeref( dd, bRes0 );
+        // try to find the cube with the positive literal
+        bRes1 = Extra_bddGetOneCube( dd, bFunc1 );  Cudd_Ref( bRes1 );
+        assert( bRes1 != b0 );
+        bRes = Cudd_bddAnd( dd, bRes1, dd->vars[bFuncR->index] ); Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( dd, bRes1 );
+    }
+
+    Cudd_Deref( bRes );
+    return bRes;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the reordering-sensitive step of Extra_bddMove().]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop )
+{
+    DdNode * bTemp, * bProd;
+    int i;
+    assert( iStart <= iStop );
+    assert( iStart >= 0 && iStart <= dd->size );
+    assert( iStop >= 0  && iStop  <= dd->size );
+    bProd = b1;         Cudd_Ref( bProd );
+    for ( i = iStart; i < iStop; i++ )
+    {
+        bProd = Cudd_bddAnd( dd, bTemp = bProd, dd->vars[i] );      Cudd_Ref( bProd );
+        Cudd_RecursiveDeref( dd, bTemp ); 
+    }
+    Cudd_Deref( bProd );
+    return bProd;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the cube of BDD variables corresponding to bits it the bit-code]
+
+  Description [Returns a bdd composed of elementary bdds found in array BddVars[] such 
+  that the bdd vars encode the number Value of bit length CodeWidth (if fMsbFirst is 1, 
+  the most significant bit is encoded with the first bdd variable). If the variables 
+  BddVars are not specified, takes the first CodeWidth variables of the manager]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst )
+{
+    int z;
+    DdNode * bTemp, * bVar, * bVarBdd, * bResult;
+
+    bResult = b1;   Cudd_Ref( bResult );
+    for ( z = 0; z < CodeWidth; z++ )
+    {
+        bVarBdd = (pbVars)? pbVars[z]: dd->vars[z];
+        if ( fMsbFirst )
+            bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (CodeWidth-1-z)))==0 );
+        else
+            bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (z)))==0 );
+        bResult = Cudd_bddAnd( dd, bTemp = bResult, bVar );     Cudd_Ref( bResult );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    Cudd_Deref( bResult );
+
+    return bResult;
+}  /* end of Extra_bddBitsToCube */
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the support as a negative polarity cube.]
+
+  Description [Finds the variables on which a DD depends. Returns a BDD 
+  consisting of the product of the variables in the negative polarity 
+  if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_VectorSupport Cudd_Support]
+
+******************************************************************************/
+DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f )
+{
+	int *support;
+	DdNode *res, *tmp, *var;
+	int i, j;
+	int size;
+
+	/* Allocate and initialize support array for ddSupportStep. */
+	size = ddMax( dd->size, dd->sizeZ );
+	support = ABC_ALLOC( int, size );
+	if ( support == NULL )
+	{
+		dd->errorCode = CUDD_MEMORY_OUT;
+		return ( NULL );
+	}
+	for ( i = 0; i < size; i++ )
+	{
+		support[i] = 0;
+	}
+
+	/* Compute support and clean up markers. */
+	ddSupportStep( Cudd_Regular( f ), support );
+	ddClearFlag( Cudd_Regular( f ) );
+
+	/* Transform support from array to cube. */
+	do
+	{
+		dd->reordered = 0;
+		res = DD_ONE( dd );
+		cuddRef( res );
+		for ( j = size - 1; j >= 0; j-- )
+		{						/* for each level bottom-up */
+			i = ( j >= dd->size ) ? j : dd->invperm[j];
+			if ( support[i] == 1 )
+			{
+				var = cuddUniqueInter( dd, i, dd->one, Cudd_Not( dd->one ) );
+				//////////////////////////////////////////////////////////////////
+				var = Cudd_Not(var);
+				//////////////////////////////////////////////////////////////////
+				cuddRef( var );
+				tmp = cuddBddAndRecur( dd, res, var );
+				if ( tmp == NULL )
+				{
+					Cudd_RecursiveDeref( dd, res );
+					Cudd_RecursiveDeref( dd, var );
+					res = NULL;
+					break;
+				}
+				cuddRef( tmp );
+				Cudd_RecursiveDeref( dd, res );
+				Cudd_RecursiveDeref( dd, var );
+				res = tmp;
+			}
+		}
+	}
+	while ( dd->reordered == 1 );
+
+	ABC_FREE( support );
+	if ( res != NULL )
+		cuddDeref( res );
+	return ( res );
+
+}								/* end of Extra_SupportNeg */
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if the BDD is the BDD of elementary variable.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Extra_bddIsVar( DdNode * bFunc )
+{
+    bFunc = Cudd_Regular( bFunc );
+    if ( cuddIsConstant(bFunc) )
+        return 0;
+    return cuddIsConstant( cuddT(bFunc) ) && cuddIsConstant( Cudd_Regular(cuddE(bFunc)) );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates AND composed of the first nVars of the manager.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars )
+{
+    DdNode * bFunc, * bTemp;
+    int i;
+    bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc );
+    for ( i = 0; i < nVars; i++ )
+    {
+        bFunc = Cudd_bddAnd( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) );  Cudd_Ref( bFunc );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    Cudd_Deref( bFunc );
+    return bFunc;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates OR composed of the first nVars of the manager.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_bddCreateOr( DdManager * dd, int nVars )
+{
+    DdNode * bFunc, * bTemp;
+    int i;
+    bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc );
+    for ( i = 0; i < nVars; i++ )
+    {
+        bFunc = Cudd_bddOr( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) );  Cudd_Ref( bFunc );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    Cudd_Deref( bFunc );
+    return bFunc;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates EXOR composed of the first nVars of the manager.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_bddCreateExor( DdManager * dd, int nVars )
+{
+    DdNode * bFunc, * bTemp;
+    int i;
+    bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc );
+    for ( i = 0; i < nVars; i++ )
+    {
+        bFunc = Cudd_bddXor( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) );  Cudd_Ref( bFunc );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    Cudd_Deref( bFunc );
+    return bFunc;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the set of primes as a ZDD.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F )
+{
+    DdNode	*res;
+    do {
+		dd->reordered = 0;
+		res = extraZddPrimes(dd, F);
+		if ( dd->reordered == 1 )
+			printf("\nReordering in Extra_zddPrimes()\n");
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Extra_zddPrimes */
+
+/**Function********************************************************************
+
+  Synopsis    [Permutes the variables of the array of BDDs.]
+
+  Description [Given a permutation in array permut, creates a new BDD
+  with permuted variables. There should be an entry in array permut
+  for each variable in the manager. The i-th entry of permut holds the
+  index of the variable that is to substitute the i-th variable.
+  The DDs in the resulting array are already referenced.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addPermute Cudd_bddSwapVariables]
+
+******************************************************************************/
+void Extra_bddPermuteArray( DdManager * manager, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut )
+{
+	DdHashTable *table;
+	int i, k;
+	do
+	{
+		manager->reordered = 0;
+		table = cuddHashTableInit( manager, 1, 2 );
+
+		/* permute the output functions one-by-one */
+		for ( i = 0; i < nNodes; i++ )
+		{
+			bNodesOut[i] = cuddBddPermuteRecur( manager, table, bNodesIn[i], permut );
+			if ( bNodesOut[i] == NULL )
+			{
+				/* deref the array of the already computed outputs */
+				for ( k = 0; k < i; k++ )
+					Cudd_RecursiveDeref( manager, bNodesOut[k] );
+				break;
+			}
+			cuddRef( bNodesOut[i] );
+		}
+		/* Dispose of local cache. */
+		cuddHashTableQuit( table );
+	}
+	while ( manager->reordered == 1 );
+}	/* end of Extra_bddPermuteArray */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the positive polarty cube composed of the first vars in the array.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars )
+{
+    DdNode * bRes;
+    DdNode * bTemp;
+    int i;
+
+    bRes = b1; Cudd_Ref( bRes );
+    for ( i = 0; i < nVars; i++ )
+    {
+        bRes = Cudd_bddAnd( dd, bTemp = bRes, bXVars[i] );  Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+
+    Cudd_Deref( bRes );
+    return bRes;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Changes the polarity of vars listed in the cube.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_bddChangePolarity( 
+  DdManager * dd,   /* the DD manager */
+  DdNode * bFunc,
+  DdNode * bVars) 
+{
+    DdNode  *res;
+    do {
+        dd->reordered = 0;
+        res = extraBddChangePolarity( dd, bFunc, bVars );
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Extra_bddChangePolarity */
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the given variable belongs to the cube.]
+
+  Description [Return -1 if the var does not appear in the cube.
+  Otherwise, returns polarity (0 or 1) of the var in the cube.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_bddVarIsInCube( DdNode * bCube, int iVar )
+{
+    DdNode * bCube0, * bCube1;
+    while ( Cudd_Regular(bCube)->index != CUDD_CONST_INDEX )
+    {
+        bCube0 = Cudd_NotCond( cuddE(Cudd_Regular(bCube)), Cudd_IsComplement(bCube) );
+        bCube1 = Cudd_NotCond( cuddT(Cudd_Regular(bCube)), Cudd_IsComplement(bCube) );
+        // make sure it is a cube
+        assert( (Cudd_IsComplement(bCube0) && Cudd_Regular(bCube0)->index == CUDD_CONST_INDEX) || // bCube0 == 0
+                (Cudd_IsComplement(bCube1) && Cudd_Regular(bCube1)->index == CUDD_CONST_INDEX) ); // bCube1 == 0
+        // quit if it is the last one
+        if ( Cudd_Regular(bCube)->index == iVar )
+            return (int)(Cudd_IsComplement(bCube0) && Cudd_Regular(bCube0)->index == CUDD_CONST_INDEX);
+        // get the next cube
+        if ( (Cudd_IsComplement(bCube0) && Cudd_Regular(bCube0)->index == CUDD_CONST_INDEX) )
+            bCube = bCube1;
+        else
+            bCube = bCube0;
+    }
+    return -1;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Computes the AND of two BDD with different orders.]
+
+  Description [Derives the result of Boolean AND of bF and bG in ddF.
+  The array pPermute gives the mapping of variables of ddG into that of ddF.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_bddAndPermute( DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute )
+{
+    DdHashTable * table;
+    DdNode * bRes;
+    do
+    {
+        ddF->reordered = 0;
+        table = cuddHashTableInit( ddF, 2, 256 );
+        if (table == NULL) return NULL;
+        bRes = extraBddAndPermute( table, ddF, bF, ddG, bG, pPermute );  
+        if ( bRes ) cuddRef( bRes );
+        cuddHashTableQuit( table );
+        if ( bRes ) cuddDeref( bRes );
+//if ( ddF->reordered == 1 )
+//printf( "Reordering happened\n" );
+    }
+    while ( ddF->reordered == 1 );
+//printf( "|F| =%6d  |G| =%6d  |H| =%6d  |F|*|G| =%9d\n", 
+//       Cudd_DagSize(bF), Cudd_DagSize(bG), Cudd_DagSize(bRes), 
+//       Cudd_DagSize(bF) * Cudd_DagSize(bG) );
+    return ( bRes );
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the reordering-sensitive step of Extra_bddMove().]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * extraBddMove( 
+  DdManager * dd,    /* the DD manager */
+  DdNode * bF,
+  DdNode * bDist) 
+{
+    DdNode * bRes;
+
+    if ( Cudd_IsConstant(bF) )
+        return bF;
+
+    if ( (bRes = cuddCacheLookup2(dd, extraBddMove, bF, bDist)) )
+        return bRes;
+    else
+    {
+        DdNode * bRes0, * bRes1;             
+        DdNode * bF0, * bF1;             
+        DdNode * bFR = Cudd_Regular(bF); 
+        int VarNew;
+        
+        if ( Cudd_IsComplement(bDist) )
+            VarNew = bFR->index - Cudd_Not(bDist)->index;
+        else
+            VarNew = bFR->index + bDist->index;
+        assert( VarNew < dd->size );
+
+        // cofactor the functions
+        if ( bFR != bF ) // bFunc is complemented 
+        {
+            bF0 = Cudd_Not( cuddE(bFR) );
+            bF1 = Cudd_Not( cuddT(bFR) );
+        }
+        else
+        {
+            bF0 = cuddE(bFR);
+            bF1 = cuddT(bFR);
+        }
+
+        bRes0 = extraBddMove( dd, bF0, bDist );
+        if ( bRes0 == NULL ) 
+            return NULL;
+        cuddRef( bRes0 );
+
+        bRes1 = extraBddMove( dd, bF1, bDist );
+        if ( bRes1 == NULL ) 
+        {
+            Cudd_RecursiveDeref( dd, bRes0 );
+            return NULL;
+        }
+        cuddRef( bRes1 );
+
+        /* only bRes0 and bRes1 are referenced at this point */
+        bRes = cuddBddIteRecur( dd, dd->vars[VarNew], bRes1, bRes0 );
+        if ( bRes == NULL ) 
+        {
+            Cudd_RecursiveDeref( dd, bRes0 );
+            Cudd_RecursiveDeref( dd, bRes1 );
+            return NULL;
+        }
+        cuddRef( bRes );
+        Cudd_RecursiveDeref( dd, bRes0 );
+        Cudd_RecursiveDeref( dd, bRes1 );
+
+        /* insert the result into cache */
+        cuddCacheInsert2( dd, extraBddMove, bF, bDist, bRes );
+        cuddDeref( bRes );
+        return bRes;
+    }
+} /* end of extraBddMove */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds three cofactors of the cover w.r.t. to the topmost variable.]
+
+  Description [Finds three cofactors of the cover w.r.t. to the topmost variable.
+  Does not check the cover for being a constant. Assumes that ZDD variables encoding 
+  positive and negative polarities are adjacent in the variable order. Is different 
+  from cuddZddGetCofactors3() in that it does not compute the cofactors w.r.t. the 
+  given variable but takes the cofactors with respent to the topmost variable. 
+  This function is more efficient when used in recursive procedures because it does 
+  not require referencing of the resulting cofactors (compare cuddZddProduct() 
+  and extraZddPrimeProduct()).]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddZddGetCofactors3]
+
+******************************************************************************/
+void 
+extraDecomposeCover( 
+  DdManager* dd,    /* the manager */
+  DdNode*  zC,      /* the cover */
+  DdNode** zC0,     /* the pointer to the negative var cofactor */ 
+  DdNode** zC1,     /* the pointer to the positive var cofactor */ 
+  DdNode** zC2 )    /* the pointer to the cofactor without var */ 
+{
+    if ( (zC->index & 1) == 0 ) 
+    { /* the top variable is present in positive polarity and maybe in negative */
+
+        DdNode *Temp = cuddE( zC );
+        *zC1  = cuddT( zC );
+        if ( cuddIZ(dd,Temp->index) == cuddIZ(dd,zC->index) + 1 )
+        {   /* Temp is not a terminal node 
+             * top var is present in negative polarity */
+            *zC2 = cuddE( Temp );
+            *zC0 = cuddT( Temp );
+        }
+        else
+        {   /* top var is not present in negative polarity */
+            *zC2 = Temp;
+            *zC0 = dd->zero;
+        }
+    }
+    else 
+    { /* the top variable is present only in negative */
+        *zC1 = dd->zero;
+        *zC2 = cuddE( zC );
+        *zC0 = cuddT( zC );
+    }
+} /* extraDecomposeCover */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static Functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Convert a BDD from a manager to another one.]
+
+  Description [Convert a BDD from a manager to another one. Returns a
+  pointer to the BDD in the destination manager if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Extra_TransferPermute]
+
+******************************************************************************/
+DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute )
+{
+    DdNode *res;
+    st__table *table = NULL;
+    st__generator *gen = NULL;
+    DdNode *key, *value;
+
+    table = st__init_table( st__ptrcmp, st__ptrhash );
+    if ( table == NULL )
+        goto failure;
+    res = extraTransferPermuteRecur( ddS, ddD, f, table, Permute );
+    if ( res != NULL )
+        cuddRef( res );
+
+    /* Dereference all elements in the table and dispose of the table.
+       ** This must be done also if res is NULL to avoid leaks in case of
+       ** reordering. */
+    gen = st__init_gen( table );
+    if ( gen == NULL )
+        goto failure;
+    while ( st__gen( gen, ( const char ** ) &key, ( char ** ) &value ) )
+    {
+        Cudd_RecursiveDeref( ddD, value );
+    }
+    st__free_gen( gen );
+    gen = NULL;
+    st__free_table( table );
+    table = NULL;
+
+    if ( res != NULL )
+        cuddDeref( res );
+    return ( res );
+
+  failure:
+    if ( table != NULL )
+        st__free_table( table );
+    if ( gen != NULL )
+        st__free_gen( gen );
+    return ( NULL );
+
+}                               /* end of extraTransferPermute */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Extra_TransferPermute.]
+
+  Description [Performs the recursive step of Extra_TransferPermute.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [extraTransferPermute]
+
+******************************************************************************/
+static DdNode * 
+extraTransferPermuteRecur( 
+  DdManager * ddS, 
+  DdManager * ddD, 
+  DdNode * f, 
+  st__table * table, 
+  int * Permute )
+{
+    DdNode *ft, *fe, *t, *e, *var, *res;
+    DdNode *one, *zero;
+    int index;
+    int comple = 0;
+
+    statLine( ddD );
+    one = DD_ONE( ddD );
+    comple = Cudd_IsComplement( f );
+
+    /* Trivial cases. */
+    if ( Cudd_IsConstant( f ) )
+        return ( Cudd_NotCond( one, comple ) );
+
+
+    /* Make canonical to increase the utilization of the cache. */
+    f = Cudd_NotCond( f, comple );
+    /* Now f is a regular pointer to a non-constant node. */
+
+    /* Check the cache. */
+    if ( st__lookup( table, ( char * ) f, ( char ** ) &res ) )
+        return ( Cudd_NotCond( res, comple ) );
+
+    if ( ddS->TimeStop && Abc_Clock() > ddS->TimeStop )
+        return NULL;
+    if ( ddD->TimeStop && Abc_Clock() > ddD->TimeStop )
+        return NULL;
+
+    /* Recursive step. */
+    if ( Permute )
+        index = Permute[f->index];
+    else
+        index = f->index;
+
+    ft = cuddT( f );
+    fe = cuddE( f );
+
+    t = extraTransferPermuteRecur( ddS, ddD, ft, table, Permute );
+    if ( t == NULL )
+    {
+        return ( NULL );
+    }
+    cuddRef( t );
+
+    e = extraTransferPermuteRecur( ddS, ddD, fe, table, Permute );
+    if ( e == NULL )
+    {
+        Cudd_RecursiveDeref( ddD, t );
+        return ( NULL );
+    }
+    cuddRef( e );
+
+    zero = Cudd_Not(ddD->one);
+    var = cuddUniqueInter( ddD, index, one, zero );
+    if ( var == NULL )
+    {
+        Cudd_RecursiveDeref( ddD, t );
+        Cudd_RecursiveDeref( ddD, e );
+        return ( NULL );
+    }
+    res = cuddBddIteRecur( ddD, var, t, e );
+
+    if ( res == NULL )
+    {
+        Cudd_RecursiveDeref( ddD, t );
+        Cudd_RecursiveDeref( ddD, e );
+        return ( NULL );
+    }
+    cuddRef( res );
+    Cudd_RecursiveDeref( ddD, t );
+    Cudd_RecursiveDeref( ddD, e );
+
+    if ( st__add_direct( table, ( char * ) f, ( char * ) res ) ==
+         st__OUT_OF_MEM )
+    {
+        Cudd_RecursiveDeref( ddD, res );
+        return ( NULL );
+    }
+    return ( Cudd_NotCond( res, comple ) );
+
+}                               /* end of extraTransferPermuteRecur */
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_Support.]
+
+  Description [Performs the recursive step of Cudd_Support. Performs a
+  DFS from f. The support is accumulated in supp as a side effect. Uses
+  the LSB of the then pointer as visited flag.]
+
+  SideEffects [None]
+
+  SeeAlso     [ddClearFlag]
+
+******************************************************************************/
+static void
+ddSupportStep(
+  DdNode * f,
+  int * support)
+{
+    if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) {
+	return;
+    }
+
+    support[f->index] = 1;
+    ddSupportStep(cuddT(f),support);
+    ddSupportStep(Cudd_Regular(cuddE(f)),support);
+    /* Mark as visited. */
+    f->next = Cudd_Not(f->next);
+    return;
+
+} /* end of ddSupportStep */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs a DFS from f, clearing the LSB of the next
+  pointers.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [ddSupportStep ddDagInt]
+
+******************************************************************************/
+static void
+ddClearFlag(
+  DdNode * f)
+{
+    if (!Cudd_IsComplement(f->next)) {
+	return;
+    }
+    /* Clear visited flag. */
+    f->next = Cudd_Regular(f->next);
+    if (cuddIsConstant(f)) {
+	return;
+    }
+    ddClearFlag(cuddT(f));
+    ddClearFlag(Cudd_Regular(cuddE(f)));
+    return;
+
+} /* end of ddClearFlag */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Composed three subcovers into one ZDD.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+extraComposeCover( 
+  DdManager* dd,    /* the manager */
+  DdNode* zC0,     /* the pointer to the negative var cofactor */ 
+  DdNode* zC1,     /* the pointer to the positive var cofactor */ 
+  DdNode* zC2,     /* the pointer to the cofactor without var */ 
+  int TopVar)    /* the index of the positive ZDD var */
+{
+    DdNode * zRes, * zTemp;
+    /* compose with-neg-var and without-var using the neg ZDD var */
+    zTemp = cuddZddGetNode( dd, 2*TopVar + 1, zC0, zC2 );
+    if ( zTemp == NULL ) 
+    {
+        Cudd_RecursiveDerefZdd(dd, zC0);
+        Cudd_RecursiveDerefZdd(dd, zC1);
+        Cudd_RecursiveDerefZdd(dd, zC2);
+        return NULL;
+    }
+    cuddRef( zTemp );
+    cuddDeref( zC0 );
+    cuddDeref( zC2 );
+
+    /* compose with-pos-var and previous result using the pos ZDD var */
+    zRes = cuddZddGetNode( dd, 2*TopVar, zC1, zTemp );
+    if ( zRes == NULL ) 
+    {
+        Cudd_RecursiveDerefZdd(dd, zC1);
+        Cudd_RecursiveDerefZdd(dd, zTemp);
+        return NULL;
+    }
+    cuddDeref( zC1 );
+    cuddDeref( zTemp );
+    return zRes;
+} /* extraComposeCover */
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of prime computation.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode* extraZddPrimes( DdManager *dd, DdNode* F )
+{
+	DdNode *zRes;
+
+	if ( F == Cudd_Not( dd->one ) )
+		return dd->zero;
+	if ( F == dd->one )
+		return dd->one;
+
+    /* check cache */
+    zRes = cuddCacheLookup1Zdd(dd, extraZddPrimes, F);
+    if (zRes)
+    	return(zRes);
+	{
+		/* temporary variables */
+		DdNode *bF01, *zP0, *zP1;
+		/* three components of the prime set */
+		DdNode *zResE, *zResP, *zResN;
+		int fIsComp = Cudd_IsComplement( F );
+
+		/* find cofactors of F */
+		DdNode * bF0 = Cudd_NotCond( Cudd_E( F ), fIsComp );
+		DdNode * bF1 = Cudd_NotCond( Cudd_T( F ), fIsComp );
+
+		/* find the intersection of cofactors */
+		bF01 = cuddBddAndRecur( dd, bF0, bF1 );
+		if ( bF01 == NULL ) return NULL;
+		cuddRef( bF01 );
+
+		/* solve the problems for cofactors */
+		zP0 = extraZddPrimes( dd, bF0 );
+		if ( zP0 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bF01 );
+			return NULL;
+		}
+		cuddRef( zP0 );
+
+		zP1 = extraZddPrimes( dd, bF1 );
+		if ( zP1 == NULL )
+		{
+			Cudd_RecursiveDeref( dd, bF01 );
+			Cudd_RecursiveDerefZdd( dd, zP0 );
+			return NULL;
+		}
+		cuddRef( zP1 );
+
+		/* check for local unateness */
+		if ( bF01 == bF0 )       /* unate increasing */
+		{
+			/* intersection is useless */
+			cuddDeref( bF01 );
+			/* the primes of intersection are the primes of F0 */
+			zResE = zP0;
+			/* there are no primes with negative var */
+			zResN = dd->zero;
+			cuddRef( zResN );
+			/* primes with positive var are primes of F1 that are not primes of F01 */
+			zResP = cuddZddDiff( dd, zP1, zP0 );
+			if ( zResP == NULL )  
+			{
+				Cudd_RecursiveDerefZdd( dd, zResE );
+				Cudd_RecursiveDerefZdd( dd, zResN );
+				Cudd_RecursiveDerefZdd( dd, zP1 );
+				return NULL;
+			}
+			cuddRef( zResP );
+			Cudd_RecursiveDerefZdd( dd, zP1 );
+		}
+		else if ( bF01 == bF1 ) /* unate decreasing */
+		{
+			/* intersection is useless */
+			cuddDeref( bF01 );
+			/* the primes of intersection are the primes of F1 */
+			zResE = zP1;
+			/* there are no primes with positive var */
+			zResP = dd->zero;
+			cuddRef( zResP );
+			/* primes with negative var are primes of F0 that are not primes of F01 */
+			zResN = cuddZddDiff( dd, zP0, zP1 );
+			if ( zResN == NULL )  
+			{
+				Cudd_RecursiveDerefZdd( dd, zResE );
+				Cudd_RecursiveDerefZdd( dd, zResP );
+				Cudd_RecursiveDerefZdd( dd, zP0 );
+				return NULL;
+			}
+			cuddRef( zResN );
+			Cudd_RecursiveDerefZdd( dd, zP0 );
+		}
+		else /* not unate */
+		{
+			/* primes without the top var are primes of F10 */
+			zResE = extraZddPrimes( dd, bF01 );
+			if ( zResE == NULL )  
+			{
+				Cudd_RecursiveDerefZdd( dd, bF01 );
+				Cudd_RecursiveDerefZdd( dd, zP0 );
+				Cudd_RecursiveDerefZdd( dd, zP1 );
+				return NULL;
+			}
+			cuddRef( zResE );
+			Cudd_RecursiveDeref( dd, bF01 );
+
+			/* primes with the negative top var are those of P0 that are not in F10 */
+			zResN = cuddZddDiff( dd, zP0, zResE );
+			if ( zResN == NULL )  
+			{
+				Cudd_RecursiveDerefZdd( dd, zResE );
+				Cudd_RecursiveDerefZdd( dd, zP0 );
+				Cudd_RecursiveDerefZdd( dd, zP1 );
+				return NULL;
+			}
+			cuddRef( zResN );
+			Cudd_RecursiveDerefZdd( dd, zP0 );
+
+			/* primes with the positive top var are those of P1 that are not in F10 */
+			zResP = cuddZddDiff( dd, zP1, zResE );
+			if ( zResP == NULL )  
+			{
+				Cudd_RecursiveDerefZdd( dd, zResE );
+				Cudd_RecursiveDerefZdd( dd, zResN );
+				Cudd_RecursiveDerefZdd( dd, zP1 );
+				return NULL;
+			}
+			cuddRef( zResP );
+			Cudd_RecursiveDerefZdd( dd, zP1 );
+		}
+
+		zRes = extraComposeCover( dd, zResN, zResP, zResE, Cudd_Regular(F)->index );
+		if ( zRes == NULL ) return NULL;
+
+		/* insert the result into cache */
+		cuddCacheInsert1(dd, extraZddPrimes, F, zRes);
+		return zRes;
+	}
+} /* end of extraZddPrimes */
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_bddPermute.]
+
+  Description [ Recursively puts the BDD in the order given in the array permut.
+  Checks for trivial cases to terminate recursion, then splits on the
+  children of this node.  Once the solutions for the children are
+  obtained, it puts into the current position the node from the rest of
+  the BDD that should be here. Then returns this BDD.
+  The key here is that the node being visited is NOT put in its proper
+  place by this instance, but rather is switched when its proper position
+  is reached in the recursion tree.<p>
+  The DdNode * that is returned is the same BDD as passed in as node,
+  but in the new order.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPermute cuddAddPermuteRecur]
+
+******************************************************************************/
+static DdNode *
+cuddBddPermuteRecur( DdManager * manager /* DD manager */ ,
+					 DdHashTable * table /* computed table */ ,
+					 DdNode * node /* BDD to be reordered */ ,
+					 int *permut /* permutation array */  )
+{
+	DdNode *N, *T, *E;
+	DdNode *res;
+	int index;
+
+	statLine( manager );
+	N = Cudd_Regular( node );
+
+	/* Check for terminal case of constant node. */
+	if ( cuddIsConstant( N ) )
+	{
+		return ( node );
+	}
+
+	/* If problem already solved, look up answer and return. */
+	if ( N->ref != 1 && ( res = cuddHashTableLookup1( table, N ) ) != NULL )
+	{
+		return ( Cudd_NotCond( res, N != node ) );
+	}
+
+	/* Split and recur on children of this node. */
+	T = cuddBddPermuteRecur( manager, table, cuddT( N ), permut );
+	if ( T == NULL )
+		return ( NULL );
+	cuddRef( T );
+	E = cuddBddPermuteRecur( manager, table, cuddE( N ), permut );
+	if ( E == NULL )
+	{
+		Cudd_IterDerefBdd( manager, T );
+		return ( NULL );
+	}
+	cuddRef( E );
+
+	/* Move variable that should be in this position to this position
+	   ** by retrieving the single var BDD for that variable, and calling
+	   ** cuddBddIteRecur with the T and E we just created.
+	 */
+	index = permut[N->index];
+	res = cuddBddIteRecur( manager, manager->vars[index], T, E );
+	if ( res == NULL )
+	{
+		Cudd_IterDerefBdd( manager, T );
+		Cudd_IterDerefBdd( manager, E );
+		return ( NULL );
+	}
+	cuddRef( res );
+	Cudd_IterDerefBdd( manager, T );
+	Cudd_IterDerefBdd( manager, E );
+
+	/* Do not keep the result if the reference count is only 1, since
+	   ** it will not be visited again.
+	 */
+	if ( N->ref != 1 )
+	{
+		ptrint fanout = ( ptrint ) N->ref;
+		cuddSatDec( fanout );
+		if ( !cuddHashTableInsert1( table, N, res, fanout ) )
+		{
+			Cudd_IterDerefBdd( manager, res );
+			return ( NULL );
+		}
+	}
+	cuddDeref( res );
+	return ( Cudd_NotCond( res, N != node ) );
+
+}								/* end of cuddBddPermuteRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the reordering-sensitive step of Extra_bddChangePolarity().]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * extraBddChangePolarity( 
+  DdManager * dd,    /* the DD manager */
+  DdNode * bFunc, 
+  DdNode * bVars) 
+{
+    DdNode * bRes;
+
+    if ( bVars == b1 )
+        return bFunc;
+    if ( Cudd_IsConstant(bFunc) )
+        return bFunc;
+
+    if ( (bRes = cuddCacheLookup2(dd, extraBddChangePolarity, bFunc, bVars)) )
+        return bRes;
+    else
+    {
+        DdNode * bFR = Cudd_Regular(bFunc); 
+        int LevelF   = dd->perm[bFR->index];
+        int LevelV   = dd->perm[bVars->index];
+
+        if ( LevelV < LevelF )
+            bRes = extraBddChangePolarity( dd, bFunc, cuddT(bVars) );
+        else // if ( LevelF <= LevelV )
+        {
+            DdNode * bRes0, * bRes1;             
+            DdNode * bF0, * bF1;             
+            DdNode * bVarsNext;
+
+            // cofactor the functions
+            if ( bFR != bFunc ) // bFunc is complemented 
+            {
+                bF0 = Cudd_Not( cuddE(bFR) );
+                bF1 = Cudd_Not( cuddT(bFR) );
+            }
+            else
+            {
+                bF0 = cuddE(bFR);
+                bF1 = cuddT(bFR);
+            }
+
+            if ( LevelF == LevelV )
+                bVarsNext = cuddT(bVars);
+            else
+                bVarsNext = bVars;
+
+            bRes0 = extraBddChangePolarity( dd, bF0, bVarsNext );
+            if ( bRes0 == NULL ) 
+                return NULL;
+            cuddRef( bRes0 );
+
+            bRes1 = extraBddChangePolarity( dd, bF1, bVarsNext );
+            if ( bRes1 == NULL ) 
+            {
+                Cudd_RecursiveDeref( dd, bRes0 );
+                return NULL;
+            }
+            cuddRef( bRes1 );
+
+            if ( LevelF == LevelV )
+            { // swap the cofactors
+                DdNode * bTemp;
+                bTemp = bRes0;
+                bRes0 = bRes1;
+                bRes1 = bTemp;
+            }
+
+            /* only aRes0 and aRes1 are referenced at this point */
+
+            /* consider the case when Res0 and Res1 are the same node */
+            if ( bRes0 == bRes1 )
+                bRes = bRes1;
+            /* consider the case when Res1 is complemented */
+            else if ( Cudd_IsComplement(bRes1) ) 
+            {
+                bRes = cuddUniqueInter(dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0));
+                if ( bRes == NULL ) 
+                {
+                    Cudd_RecursiveDeref(dd,bRes0);
+                    Cudd_RecursiveDeref(dd,bRes1);
+                    return NULL;
+                }
+                bRes = Cudd_Not(bRes);
+            } 
+            else 
+            {
+                bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 );
+                if ( bRes == NULL ) 
+                {
+                    Cudd_RecursiveDeref(dd,bRes0);
+                    Cudd_RecursiveDeref(dd,bRes1);
+                    return NULL;
+                }
+            }
+            cuddDeref( bRes0 );
+            cuddDeref( bRes1 );
+        }
+            
+        /* insert the result into cache */
+        cuddCacheInsert2(dd, extraBddChangePolarity, bFunc, bVars, bRes);
+        return bRes;
+    }
+} /* end of extraBddChangePolarity */
+
+
+
+static int Counter = 0;
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the AND of two BDD with different orders.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * extraBddAndPermute( DdHashTable * table, DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute )
+{
+    DdNode * bF0, * bF1, * bG0, * bG1, * bRes0, * bRes1, * bRes, * bVar;
+    int LevF, LevG, Lev;
+
+    // if F == 0, return 0 
+    if ( bF == Cudd_Not(ddF->one) )
+        return Cudd_Not(ddF->one);
+    // if G == 0, return 0 
+    if ( bG == Cudd_Not(ddG->one) )
+        return Cudd_Not(ddF->one);
+    // if G == 1, return F
+    if ( bG == ddG->one )
+        return bF;
+    // cannot use F == 1, because the var order of G has to be changed
+
+    // check cache
+    if ( //(Cudd_Regular(bF)->ref != 1 || Cudd_Regular(bG)->ref != 1) && 
+         (bRes = cuddHashTableLookup2(table, bF, bG)) )
+        return bRes;
+    Counter++;
+
+    if ( ddF->TimeStop && Abc_Clock() > ddF->TimeStop )
+        return NULL;
+    if ( ddG->TimeStop && Abc_Clock() > ddG->TimeStop )
+        return NULL;
+
+    // find the topmost variable in F and G using var order of F
+    LevF = cuddI( ddF, Cudd_Regular(bF)->index );
+    LevG = cuddI( ddF, pPermute ? pPermute[Cudd_Regular(bG)->index] : Cudd_Regular(bG)->index );
+    Lev  = Abc_MinInt( LevF, LevG );
+    assert( Lev < ddF->size );
+    bVar = ddF->vars[ddF->invperm[Lev]];
+
+    // cofactor
+    bF0 = (Lev < LevF) ? bF : Cudd_NotCond( cuddE(Cudd_Regular(bF)), Cudd_IsComplement(bF) );
+    bF1 = (Lev < LevF) ? bF : Cudd_NotCond( cuddT(Cudd_Regular(bF)), Cudd_IsComplement(bF) );
+    bG0 = (Lev < LevG) ? bG : Cudd_NotCond( cuddE(Cudd_Regular(bG)), Cudd_IsComplement(bG) );
+    bG1 = (Lev < LevG) ? bG : Cudd_NotCond( cuddT(Cudd_Regular(bG)), Cudd_IsComplement(bG) );
+
+    // call for cofactors
+    bRes0 = extraBddAndPermute( table, ddF, bF0, ddG, bG0, pPermute );
+    if ( bRes0 == NULL ) 
+        return NULL;
+    cuddRef( bRes0 );
+    // call for cofactors
+    bRes1 = extraBddAndPermute( table, ddF, bF1, ddG, bG1, pPermute );
+    if ( bRes1 == NULL ) 
+    {
+        Cudd_IterDerefBdd( ddF, bRes0 );
+        return NULL;
+    }
+    cuddRef( bRes1 );
+
+    // compose the result
+    bRes = cuddBddIteRecur( ddF, bVar, bRes1, bRes0 );
+    if ( bRes == NULL )
+    {
+        Cudd_IterDerefBdd( ddF, bRes0 );
+        Cudd_IterDerefBdd( ddF, bRes1 );
+        return NULL;
+    }
+    cuddRef( bRes );
+    Cudd_IterDerefBdd( ddF, bRes0 );
+    Cudd_IterDerefBdd( ddF, bRes1 );
+
+    // cache the result
+//    if ( Cudd_Regular(bF)->ref != 1 || Cudd_Regular(bG)->ref != 1 )
+    {
+        ptrint fanout = (ptrint)Cudd_Regular(bF)->ref * Cudd_Regular(bG)->ref;
+        cuddSatDec(fanout);
+        cuddHashTableInsert2( table, bF, bG, bRes, fanout );
+    }
+    cuddDeref( bRes );
+    return bRes;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Testbench.]
+
+  Description [This procedure takes BDD manager ddF and two BDDs
+  in this manager (bF and bG).  It creates a new manager ddG,
+  transfers bG into it and then reorders it, resulting in bG2.
+  Then it tries to compute the product of bF and bG2 in ddF.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_TestAndPerm( DdManager * ddF, DdNode * bF, DdNode * bG )
+{
+    DdManager * ddG;
+    DdNode * bG2, * bRes1, * bRes2;
+    abctime clk;
+    // disable variable ordering in ddF
+    Cudd_AutodynDisable( ddF );
+
+    // create new BDD manager
+    ddG = Cudd_Init( ddF->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    // transfer BDD into it
+    Cudd_ShuffleHeap( ddG, ddF->invperm );
+    bG2 = Extra_TransferLevelByLevel( ddF, ddG, bG );   Cudd_Ref( bG2 );
+    // reorder the new manager
+    Cudd_ReduceHeap( ddG, CUDD_REORDER_SYMM_SIFT, 1 );
+
+    // compute the result
+clk = Abc_Clock();
+    bRes1 = Cudd_bddAnd( ddF, bF, bG );                 Cudd_Ref( bRes1 );
+Abc_PrintTime( 1, "Runtime of Cudd_bddAnd  ", Abc_Clock() - clk );
+
+    // compute the result
+Counter = 0;
+clk = Abc_Clock();
+    bRes2 = Extra_bddAndPermute( ddF, bF, ddG, bG2, NULL );      Cudd_Ref( bRes2 );
+Abc_PrintTime( 1, "Runtime of new procedure", Abc_Clock() - clk );
+printf( "Recursive calls = %d\n", Counter );
+printf( "|F| =%6d  |G| =%6d  |H| =%6d  |F|*|G| =%9d  ", 
+       Cudd_DagSize(bF), Cudd_DagSize(bG), Cudd_DagSize(bRes2), 
+       Cudd_DagSize(bF) * Cudd_DagSize(bG) );
+
+    if ( bRes1 == bRes2 )
+        printf( "Result verified.\n\n" );
+    else
+        printf( "Result is incorrect.\n\n" );
+
+    Cudd_RecursiveDeref( ddF, bRes1 );
+    Cudd_RecursiveDeref( ddF, bRes2 );
+    // quit the new manager
+    Cudd_RecursiveDeref( ddG, bG2 );
+    Extra_StopManager( ddG );
+
+    // re-enable variable ordering in ddF
+    Cudd_AutodynEnable( ddF, CUDD_REORDER_SYMM_SIFT );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraBddSymm.c b/abc-build/src/misc/extra/extraBddSymm.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraBddSymm.c
@@ -0,0 +1,1474 @@
+/**CFile****************************************************************
+
+  FileName    [extraBddSymm.c]
+
+  PackageName [extra]
+
+  Synopsis    [Efficient methods to compute the information about
+  symmetric variables using the algorithm presented in the paper:
+  A. Mishchenko. Fast Computation of Symmetries in Boolean Functions. 
+  Transactions on CAD, Nov. 2003.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - September 1, 2003.]
+
+  Revision    [$Id: extraBddSymm.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#define DD_GET_SYMM_VARS_TAG          0x0a /* former DD_BDD_XOR_EXIST_ABSTRACT_TAG */
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the classical symmetry information for the function.]
+
+  Description [Returns the symmetry information in the form of Extra_SymmInfo_t structure.]
+
+  SideEffects [If the ZDD variables are not derived from BDD variables with
+  multiplicity 2, this function may derive them in a wrong way.]
+
+  SeeAlso     []
+
+******************************************************************************/
+Extra_SymmInfo_t * Extra_SymmPairsCompute( 
+  DdManager * dd,   /* the manager */
+  DdNode * bFunc)   /* the function whose symmetries are computed */
+{
+    DdNode * bSupp;
+    DdNode * zRes;
+    Extra_SymmInfo_t * p;
+
+    bSupp = Cudd_Support( dd, bFunc );                      Cudd_Ref( bSupp );
+    zRes  = Extra_zddSymmPairsCompute( dd, bFunc, bSupp );  Cudd_Ref( zRes );
+
+    p = Extra_SymmPairsCreateFromZdd( dd, zRes, bSupp );
+
+    Cudd_RecursiveDeref( dd, bSupp );
+    Cudd_RecursiveDerefZdd( dd, zRes );
+
+    return p;
+
+} /* end of Extra_SymmPairsCompute */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the classical symmetry information as a ZDD.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_zddSymmPairsCompute( 
+  DdManager * dd,   /* the DD manager */
+  DdNode * bF,
+  DdNode * bVars) 
+{
+    DdNode * res;
+    do {
+        dd->reordered = 0;
+        res = extraZddSymmPairsCompute( dd, bF, bVars );
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Extra_zddSymmPairsCompute */
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a singleton-set ZDD containing all variables that are symmetric with the given one.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_zddGetSymmetricVars( 
+  DdManager * dd,    /* the DD manager */
+  DdNode * bF,       /* the first function  - originally, the positive cofactor */
+  DdNode * bG,       /* the second fucntion - originally, the negative cofactor */
+  DdNode * bVars)    /* the set of variables, on which F and G depend */
+{
+    DdNode * res;
+    do {
+        dd->reordered = 0;
+        res = extraZddGetSymmetricVars( dd, bF, bG, bVars );
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Extra_zddGetSymmetricVars */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a set of variables into a set of singleton subsets.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_zddGetSingletons( 
+  DdManager * dd,    /* the DD manager */
+  DdNode * bVars)    /* the set of variables */
+{
+    DdNode * res;
+    do {
+        dd->reordered = 0;
+        res = extraZddGetSingletons( dd, bVars );
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Extra_zddGetSingletons */
+
+/**Function********************************************************************
+
+  Synopsis    [Filters the set of variables using the support of the function.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_bddReduceVarSet( 
+  DdManager * dd,    /* the DD manager */
+  DdNode * bVars,    /* the set of variables to be reduced */
+  DdNode * bF)       /* the function whose support is used for reduction */
+{
+    DdNode * res;
+    do {
+        dd->reordered = 0;
+        res = extraBddReduceVarSet( dd, bVars, bF );
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Extra_bddReduceVarSet */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates symmetry information structure.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars )
+{
+    int i;
+    Extra_SymmInfo_t * p;
+
+    // allocate and clean the storage for symmetry info
+    p = ABC_ALLOC( Extra_SymmInfo_t, 1 );
+    memset( p, 0, sizeof(Extra_SymmInfo_t) );
+    p->nVars     = nVars;
+    p->pVars     = ABC_ALLOC( int, nVars );  
+    p->pSymms    = ABC_ALLOC( char *, nVars );  
+    p->pSymms[0] = ABC_ALLOC( char  , nVars * nVars );
+    memset( p->pSymms[0], 0, nVars * nVars * sizeof(char) );
+
+    for ( i = 1; i < nVars; i++ )
+        p->pSymms[i] = p->pSymms[i-1] + nVars;
+
+    return p;
+} /* end of Extra_SymmPairsAllocate */
+
+/**Function********************************************************************
+
+  Synopsis    [Deallocates symmetry information structure.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Extra_SymmPairsDissolve( Extra_SymmInfo_t * p )
+{
+    ABC_FREE( p->pVars );
+    ABC_FREE( p->pSymms[0] );
+    ABC_FREE( p->pSymms    );
+    ABC_FREE( p );
+} /* end of Extra_SymmPairsDissolve */
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates symmetry information structure.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Extra_SymmPairsPrint( Extra_SymmInfo_t * p )
+{
+    int i, k;
+    printf( "\n" );
+    for ( i = 0; i < p->nVars; i++ )
+    {
+        for ( k = 0; k <= i; k++ )
+            printf( " " );
+        for ( k = i+1; k < p->nVars; k++ )
+            if ( p->pSymms[i][k] )
+                printf( "1" );
+            else
+                printf( "." );
+        printf( "\n" );
+    }
+} /* end of Extra_SymmPairsPrint */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates the symmetry information structure from ZDD.]
+
+  Description [ZDD representation of symmetries is the set of cubes, each
+  of which has two variables in the positive polarity. These variables correspond
+  to the symmetric variable pair.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bSupp )
+{
+    int i;
+    int nSuppSize;
+    Extra_SymmInfo_t * p;
+    int * pMapVars2Nums;
+    DdNode * bTemp;
+    DdNode * zSet, * zCube, * zTemp;
+    int iVar1, iVar2;
+
+    nSuppSize = Extra_bddSuppSize( dd, bSupp );
+
+    // allocate and clean the storage for symmetry info
+    p = Extra_SymmPairsAllocate( nSuppSize );
+
+    // allocate the storage for the temporary map
+    pMapVars2Nums = ABC_ALLOC( int, dd->size );
+    memset( pMapVars2Nums, 0, dd->size * sizeof(int) );
+
+    // assign the variables
+    p->nVarsMax = dd->size;
+//  p->nNodes   = Cudd_DagSize( zPairs );
+    p->nNodes   = 0;
+    for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ )
+    {
+        p->pVars[i] = bTemp->index;
+        pMapVars2Nums[bTemp->index] = i;
+    }
+
+    // write the symmetry info into the structure
+    zSet = zPairs;   Cudd_Ref( zSet );
+    while ( zSet != z0 )
+    {
+        // get the next cube
+        zCube  = Extra_zddSelectOneSubset( dd, zSet );    Cudd_Ref( zCube );
+
+        // add these two variables to the data structure
+        assert( cuddT( cuddT(zCube) ) == z1 );
+        iVar1 = zCube->index/2;
+        iVar2 = cuddT(zCube)->index/2;
+        if ( pMapVars2Nums[iVar1] < pMapVars2Nums[iVar2] )
+            p->pSymms[ pMapVars2Nums[iVar1] ][ pMapVars2Nums[iVar2] ] = 1;
+        else
+            p->pSymms[ pMapVars2Nums[iVar2] ][ pMapVars2Nums[iVar1] ] = 1;
+        // count the symmetric pairs
+        p->nSymms ++;
+
+        // update the cuver and deref the cube
+        zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube );     Cudd_Ref( zSet );
+        Cudd_RecursiveDerefZdd( dd, zTemp );
+        Cudd_RecursiveDerefZdd( dd, zCube );
+
+    } // for each cube 
+    Cudd_RecursiveDerefZdd( dd, zSet );
+
+    ABC_FREE( pMapVars2Nums );
+    return p;
+
+} /* end of Extra_SymmPairsCreateFromZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the possibility of two variables being symmetric.]
+
+  Description [Returns 0 if vars are not symmetric. Return 1 if vars can be symmetric.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Extra_bddCheckVarsSymmetric( 
+  DdManager * dd,   /* the DD manager */
+  DdNode * bF,
+  int iVar1,
+  int iVar2) 
+{
+    DdNode * bVars;
+    int Res;
+
+//  return 1;
+
+    assert( iVar1 != iVar2 );
+    assert( iVar1 < dd->size );
+    assert( iVar2 < dd->size );
+
+    bVars = Cudd_bddAnd( dd, dd->vars[iVar1], dd->vars[iVar2] );   Cudd_Ref( bVars );
+
+    Res = (int)( extraBddCheckVarsSymmetric( dd, bF, bVars ) == b1 );
+
+    Cudd_RecursiveDeref( dd, bVars );
+
+    return Res;
+} /* end of Extra_bddCheckVarsSymmetric */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the classical symmetry information for the function.]
+
+  Description [Uses the naive way of comparing cofactors.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc )
+{
+    DdNode * bSupp, * bTemp;
+    int nSuppSize;
+    Extra_SymmInfo_t * p;
+    int i, k;
+
+    // compute the support
+    bSupp = Cudd_Support( dd, bFunc );   Cudd_Ref( bSupp );
+    nSuppSize = Extra_bddSuppSize( dd, bSupp );
+//printf( "Support = %d. ", nSuppSize );
+//Extra_bddPrint( dd, bSupp );
+//printf( "%d ", nSuppSize );
+
+    // allocate the storage for symmetry info
+    p = Extra_SymmPairsAllocate( nSuppSize );
+
+    // assign the variables
+    p->nVarsMax = dd->size;
+    for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ )
+        p->pVars[i] = bTemp->index;
+
+    // go through the candidate pairs and check using Idea1
+    for ( i = 0; i < nSuppSize; i++ )
+    for ( k = i+1; k < nSuppSize; k++ )
+    {
+        p->pSymms[k][i] = p->pSymms[i][k] = Extra_bddCheckVarsSymmetricNaive( dd, bFunc, p->pVars[i], p->pVars[k] );
+        if ( p->pSymms[i][k] )
+             p->nSymms++;
+    }
+
+    Cudd_RecursiveDeref( dd, bSupp );
+    return p;
+
+} /* end of Extra_SymmPairsComputeNaive */
+
+/**Function********************************************************************
+
+  Synopsis    [Checks if the two variables are symmetric.]
+
+  Description [Returns 0 if vars are not symmetric. Return 1 if vars are symmetric.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Extra_bddCheckVarsSymmetricNaive( 
+  DdManager * dd,   /* the DD manager */
+  DdNode * bF,
+  int iVar1,
+  int iVar2) 
+{
+    DdNode * bCube1, * bCube2;
+    DdNode * bCof01, * bCof10;
+    int Res;
+
+    assert( iVar1 != iVar2 );
+    assert( iVar1 < dd->size );
+    assert( iVar2 < dd->size );
+
+    bCube1 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar1] ), dd->vars[iVar2] );   Cudd_Ref( bCube1 );
+    bCube2 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar2] ), dd->vars[iVar1] );   Cudd_Ref( bCube2 );
+
+    bCof01 = Cudd_Cofactor( dd, bF, bCube1 );  Cudd_Ref( bCof01 );
+    bCof10 = Cudd_Cofactor( dd, bF, bCube2 );  Cudd_Ref( bCof10 );
+
+    Res = (int)( bCof10 == bCof01 );
+
+    Cudd_RecursiveDeref( dd, bCof01 );
+    Cudd_RecursiveDeref( dd, bCof10 );
+    Cudd_RecursiveDeref( dd, bCube1 );
+    Cudd_RecursiveDeref( dd, bCube2 );
+
+    return Res;
+} /* end of Extra_bddCheckVarsSymmetricNaive */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds ZDD representing the set of fixed-size variable tuples.]
+
+  Description [Creates ZDD of all combinations of variables in Support that
+  is represented by a BDD.]
+
+  SideEffects [New ZDD variables are created if indices of the variables
+               present in the combination are larger than the currently
+               allocated number of ZDD variables.]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode* Extra_zddTuplesFromBdd( 
+  DdManager * dd,   /* the DD manager */
+  int K,            /* the number of variables in tuples */
+  DdNode * bVarsN)   /* the set of all variables represented as a BDD */
+{
+    DdNode  *zRes;
+    int     autoDynZ;
+
+    autoDynZ = dd->autoDynZ;
+    dd->autoDynZ = 0;
+
+    do {
+        /* transform the numeric arguments (K) into a DdNode* argument;
+         * this allows us to use the standard internal CUDD cache */
+        DdNode *bVarSet = bVarsN, *bVarsK = bVarsN;
+        int     nVars = 0, i;
+
+        /* determine the number of variables in VarSet */
+        while ( bVarSet != b1 )
+        {
+            nVars++;
+            /* make sure that the VarSet is a cube */
+            if ( cuddE( bVarSet ) != b0 )
+                return NULL;
+            bVarSet = cuddT( bVarSet );
+        }
+        /* make sure that the number of variables in VarSet is less or equal 
+           that the number of variables that should be present in the tuples
+        */
+        if ( K > nVars )
+            return NULL;
+
+        /* the second argument in the recursive call stannds for <n>;
+         * reate the first argument, which stands for <k>
+         * as when we are talking about the tuple of <k> out of <n> */
+        for ( i = 0; i < nVars-K; i++ )
+            bVarsK = cuddT( bVarsK );
+
+        dd->reordered = 0;
+        zRes = extraZddTuplesFromBdd(dd, bVarsK, bVarsN );
+
+    } while (dd->reordered == 1);
+    dd->autoDynZ = autoDynZ;
+    return zRes;
+
+} /* end of Extra_zddTuplesFromBdd */
+
+/**Function********************************************************************
+
+  Synopsis    [Selects one subset from the set of subsets represented by a ZDD.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode* Extra_zddSelectOneSubset( 
+  DdManager * dd,   /* the DD manager */
+  DdNode * zS)      /* the ZDD */
+{
+    DdNode  *res;
+    do {
+        dd->reordered = 0;
+        res = extraZddSelectOneSubset(dd, zS);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Extra_zddSelectOneSubset */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Performs a recursive step of Extra_SymmPairsCompute.]
+
+  Description [Returns the set of symmetric variable pairs represented as a set 
+  of two-literal ZDD cubes. Both variables always appear in the positive polarity
+  in the cubes. This function works without building new BDD nodes. Some relatively 
+  small number of ZDD nodes may be built to ensure proper bookkeeping of the 
+  symmetry information.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * 
+extraZddSymmPairsCompute( 
+  DdManager * dd,   /* the manager */
+  DdNode * bFunc,   /* the function whose symmetries are computed */
+  DdNode * bVars )  /* the set of variables on which this function depends */
+{
+    DdNode * zRes;
+    DdNode * bFR = Cudd_Regular(bFunc); 
+
+    if ( cuddIsConstant(bFR) )
+    {
+        int nVars, i;
+
+        // determine how many vars are in the bVars
+        nVars = Extra_bddSuppSize( dd, bVars );
+        if ( nVars < 2 )
+            return z0;
+        else
+        {
+            DdNode * bVarsK;
+
+            // create the BDD bVarsK corresponding to K = 2;
+            bVarsK = bVars;
+            for ( i = 0; i < nVars-2; i++ )
+                bVarsK = cuddT( bVarsK );
+            return extraZddTuplesFromBdd( dd, bVarsK, bVars );
+        }
+    }
+    assert( bVars != b1 );
+
+    if ( (zRes = cuddCacheLookup2Zdd(dd, extraZddSymmPairsCompute, bFunc, bVars)) )
+        return zRes;
+    else
+    {
+        DdNode * zRes0, * zRes1;
+        DdNode * zTemp, * zPlus, * zSymmVars;             
+        DdNode * bF0, * bF1;             
+        DdNode * bVarsNew;
+        int nVarsExtra;
+        int LevelF;
+
+        // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV
+        // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F
+        // count how many extra vars are there in bVars
+        nVarsExtra = 0;
+        LevelF = dd->perm[bFR->index];
+        for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) )
+            nVarsExtra++; 
+        // the indexes (level) of variables should be synchronized now
+        assert( bFR->index == bVarsNew->index );
+
+        // cofactor the function
+        if ( bFR != bFunc ) // bFunc is complemented 
+        {
+            bF0 = Cudd_Not( cuddE(bFR) );
+            bF1 = Cudd_Not( cuddT(bFR) );
+        }
+        else
+        {
+            bF0 = cuddE(bFR);
+            bF1 = cuddT(bFR);
+        }
+
+        // solve subproblems
+        zRes0 = extraZddSymmPairsCompute( dd, bF0, cuddT(bVarsNew) );
+        if ( zRes0 == NULL )
+            return NULL;
+        cuddRef( zRes0 );
+
+        // if there is no symmetries in the negative cofactor
+        // there is no need to test the positive cofactor
+        if ( zRes0 == z0 )
+            zRes = zRes0;  // zRes takes reference
+        else
+        {
+            zRes1 = extraZddSymmPairsCompute( dd, bF1, cuddT(bVarsNew) );
+            if ( zRes1 == NULL )
+            {
+                Cudd_RecursiveDerefZdd( dd, zRes0 );
+                return NULL;
+            }
+            cuddRef( zRes1 );
+
+            // only those variables are pair-wise symmetric 
+            // that are pair-wise symmetric in both cofactors
+            // therefore, intersect the solutions
+            zRes = cuddZddIntersect( dd, zRes0, zRes1 );
+            if ( zRes == NULL )
+            {
+                Cudd_RecursiveDerefZdd( dd, zRes0 );
+                Cudd_RecursiveDerefZdd( dd, zRes1 );
+                return NULL;
+            }
+            cuddRef( zRes );
+            Cudd_RecursiveDerefZdd( dd, zRes0 );
+            Cudd_RecursiveDerefZdd( dd, zRes1 );
+        }
+
+        // consider the current top-most variable and find all the vars
+        // that are pairwise symmetric with it
+        // these variables are returned as a set of ZDD singletons
+        zSymmVars = extraZddGetSymmetricVars( dd, bF1, bF0, cuddT(bVarsNew) );
+        if ( zSymmVars == NULL )
+        {
+            Cudd_RecursiveDerefZdd( dd, zRes );
+            return NULL;
+        }
+        cuddRef( zSymmVars );
+
+        // attach the topmost variable to the set, to get the variable pairs
+        // use the positive polarity ZDD variable for the purpose
+
+        // there is no need to do so, if zSymmVars is empty
+        if ( zSymmVars == z0 )
+            Cudd_RecursiveDerefZdd( dd, zSymmVars );
+        else
+        {
+            zPlus = cuddZddGetNode( dd, 2*bFR->index, zSymmVars, z0 );
+            if ( zPlus == NULL ) 
+            {
+                Cudd_RecursiveDerefZdd( dd, zRes );
+                Cudd_RecursiveDerefZdd( dd, zSymmVars );
+                return NULL;
+            }
+            cuddRef( zPlus );
+            cuddDeref( zSymmVars );
+
+            // add these variable pairs to the result
+            zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+            if ( zRes == NULL )
+            {
+                Cudd_RecursiveDerefZdd( dd, zTemp );
+                Cudd_RecursiveDerefZdd( dd, zPlus );
+                return NULL;
+            }
+            cuddRef( zRes );
+            Cudd_RecursiveDerefZdd( dd, zTemp );
+            Cudd_RecursiveDerefZdd( dd, zPlus );
+        }
+
+        // only zRes is referenced at this point
+
+        // if we skipped some variables, these variables cannot be symmetric with
+        // any variables that are currently in the support of bF, but they can be 
+        // symmetric with the variables that are in bVars but not in the support of bF
+        if ( nVarsExtra )
+        {
+            // it is possible to improve this step:
+            // (1) there is no need to enter here, if nVarsExtra < 2
+
+            // create the set of topmost nVarsExtra in bVars
+            DdNode * bVarsExtra;
+            int nVars;
+
+            // remove from bVars all the variable that are in the support of bFunc
+            bVarsExtra = extraBddReduceVarSet( dd, bVars, bFunc );  
+            if ( bVarsExtra == NULL )
+            {
+                Cudd_RecursiveDerefZdd( dd, zRes );
+                return NULL;
+            }
+            cuddRef( bVarsExtra );
+
+            // determine how many vars are in the bVarsExtra
+            nVars = Extra_bddSuppSize( dd, bVarsExtra );
+            if ( nVars < 2 )
+            {
+                Cudd_RecursiveDeref( dd, bVarsExtra );
+            }
+            else
+            {
+                int i;
+                DdNode * bVarsK;
+
+                // create the BDD bVarsK corresponding to K = 2;
+                bVarsK = bVarsExtra;
+                for ( i = 0; i < nVars-2; i++ )
+                    bVarsK = cuddT( bVarsK );
+
+                // create the 2 variable tuples
+                zPlus = extraZddTuplesFromBdd( dd, bVarsK, bVarsExtra );
+                if ( zPlus == NULL )
+                {
+                    Cudd_RecursiveDeref( dd, bVarsExtra );
+                    Cudd_RecursiveDerefZdd( dd, zRes );
+                    return NULL;
+                }
+                cuddRef( zPlus );
+                Cudd_RecursiveDeref( dd, bVarsExtra );
+
+                // add these to the result
+                zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+                if ( zRes == NULL )
+                {
+                    Cudd_RecursiveDerefZdd( dd, zTemp );
+                    Cudd_RecursiveDerefZdd( dd, zPlus );
+                    return NULL;
+                }
+                cuddRef( zRes );
+                Cudd_RecursiveDerefZdd( dd, zTemp );
+                Cudd_RecursiveDerefZdd( dd, zPlus );
+            }
+        }
+        cuddDeref( zRes );
+
+
+        /* insert the result into cache */
+        cuddCacheInsert2(dd, extraZddSymmPairsCompute, bFunc, bVars, zRes);
+        return zRes;
+    }
+} /* end of extraZddSymmPairsCompute */
+
+/**Function********************************************************************
+
+  Synopsis    [Performs a recursive step of Extra_zddGetSymmetricVars.]
+
+  Description [Returns the set of ZDD singletons, containing those positive
+  ZDD variables that correspond to BDD variables x, for which it is true 
+  that bF(x=0) == bG(x=1).]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * extraZddGetSymmetricVars( 
+  DdManager * dd,    /* the DD manager */
+  DdNode * bF,       /* the first function  - originally, the positive cofactor */
+  DdNode * bG,       /* the second function - originally, the negative cofactor */
+  DdNode * bVars)    /* the set of variables, on which F and G depend */
+{
+    DdNode * zRes;
+    DdNode * bFR = Cudd_Regular(bF); 
+    DdNode * bGR = Cudd_Regular(bG); 
+
+    if ( cuddIsConstant(bFR) && cuddIsConstant(bGR) )
+    {
+        if ( bF == bG )
+            return extraZddGetSingletons( dd, bVars );
+        else 
+            return z0;
+    }
+    assert( bVars != b1 );
+
+    if ( (zRes = cuddCacheLookupZdd(dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars)) )
+        return zRes;
+    else
+    {
+        DdNode * zRes0, * zRes1;             
+        DdNode * zPlus, * zTemp;
+        DdNode * bF0, * bF1;             
+        DdNode * bG0, * bG1;             
+        DdNode * bVarsNew;
+    
+        int LevelF = cuddI(dd,bFR->index);
+        int LevelG = cuddI(dd,bGR->index);
+        int LevelFG;
+
+        if ( LevelF < LevelG )
+            LevelFG = LevelF;
+        else
+            LevelFG = LevelG;
+
+        // at least one of the arguments is not a constant
+        assert( LevelFG < dd->size );
+
+        // every variable in bF and bG should be also in bVars, therefore LevelFG cannot be above LevelV
+        // if LevelFG is below LevelV, scroll through the vars in bVars to the same level as LevelFG
+        for ( bVarsNew = bVars; LevelFG > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) );
+        assert( LevelFG == dd->perm[bVarsNew->index] );
+
+        // cofactor the functions
+        if ( LevelF == LevelFG )
+        {
+            if ( bFR != bF ) // bF is complemented 
+            {
+                bF0 = Cudd_Not( cuddE(bFR) );
+                bF1 = Cudd_Not( cuddT(bFR) );
+            }
+            else
+            {
+                bF0 = cuddE(bFR);
+                bF1 = cuddT(bFR);
+            }
+        }
+        else 
+            bF0 = bF1 = bF;
+
+        if ( LevelG == LevelFG )
+        {
+            if ( bGR != bG ) // bG is complemented 
+            {
+                bG0 = Cudd_Not( cuddE(bGR) );
+                bG1 = Cudd_Not( cuddT(bGR) );
+            }
+            else
+            {
+                bG0 = cuddE(bGR);
+                bG1 = cuddT(bGR);
+            }
+        }
+        else 
+            bG0 = bG1 = bG;
+
+        // solve subproblems
+        zRes0 = extraZddGetSymmetricVars( dd, bF0, bG0, cuddT(bVarsNew) );
+        if ( zRes0 == NULL ) 
+            return NULL;
+        cuddRef( zRes0 );
+
+        // if there is not symmetries in the negative cofactor
+        // there is no need to test the positive cofactor
+        if ( zRes0 == z0 )
+            zRes = zRes0;  // zRes takes reference
+        else
+        {
+            zRes1 = extraZddGetSymmetricVars( dd, bF1, bG1, cuddT(bVarsNew) );
+            if ( zRes1 == NULL ) 
+            {
+                Cudd_RecursiveDerefZdd( dd, zRes0 );
+                return NULL;
+            }
+            cuddRef( zRes1 );
+
+            // only those variables should belong to the resulting set 
+            // for which the property is true for both cofactors
+            zRes = cuddZddIntersect( dd, zRes0, zRes1 );
+            if ( zRes == NULL )
+            {
+                Cudd_RecursiveDerefZdd( dd, zRes0 );
+                Cudd_RecursiveDerefZdd( dd, zRes1 );
+                return NULL;
+            }
+            cuddRef( zRes );
+            Cudd_RecursiveDerefZdd( dd, zRes0 );
+            Cudd_RecursiveDerefZdd( dd, zRes1 );
+        }
+
+        // add one more singleton if the property is true for this variable
+        if ( bF0 == bG1 )
+        {
+            zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 );
+            if ( zPlus == NULL ) 
+            {
+                Cudd_RecursiveDerefZdd( dd, zRes );
+                return NULL;
+            }
+            cuddRef( zPlus );
+
+            // add these variable pairs to the result
+            zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+            if ( zRes == NULL )
+            {
+                Cudd_RecursiveDerefZdd( dd, zTemp );
+                Cudd_RecursiveDerefZdd( dd, zPlus );
+                return NULL;
+            }
+            cuddRef( zRes );
+            Cudd_RecursiveDerefZdd( dd, zTemp );
+            Cudd_RecursiveDerefZdd( dd, zPlus );
+        }
+
+        if ( bF == bG && bVars != bVarsNew )
+        { 
+            // if the functions are equal, so are their cofactors
+            // add those variables from V that are above F and G 
+
+            DdNode * bVarsExtra;
+
+            assert( LevelFG > dd->perm[bVars->index] );
+
+            // create the BDD of the extra variables
+            bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsNew );
+            if ( bVarsExtra == NULL )
+            {
+                Cudd_RecursiveDerefZdd( dd, zRes );
+                return NULL;
+            }
+            cuddRef( bVarsExtra );
+
+            zPlus = extraZddGetSingletons( dd, bVarsExtra );
+            if ( zPlus == NULL )
+            {
+                Cudd_RecursiveDeref( dd, bVarsExtra );
+                Cudd_RecursiveDerefZdd( dd, zRes );
+                return NULL;
+            }
+            cuddRef( zPlus );
+            Cudd_RecursiveDeref( dd, bVarsExtra );
+
+            // add these to the result
+            zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+            if ( zRes == NULL )
+            {
+                Cudd_RecursiveDerefZdd( dd, zTemp );
+                Cudd_RecursiveDerefZdd( dd, zPlus );
+                return NULL;
+            }
+            cuddRef( zRes );
+            Cudd_RecursiveDerefZdd( dd, zTemp );
+            Cudd_RecursiveDerefZdd( dd, zPlus );
+        }
+        cuddDeref( zRes );
+
+        cuddCacheInsert( dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars, zRes );
+        return zRes;
+    }
+}   /* end of extraZddGetSymmetricVars */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs a recursive step of Extra_zddGetSingletons.]
+
+  Description [Returns the set of ZDD singletons, containing those positive 
+  polarity ZDD variables that correspond to the BDD variables in bVars.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * extraZddGetSingletons( 
+  DdManager * dd,    /* the DD manager */
+  DdNode * bVars)    /* the set of variables */
+{
+    DdNode * zRes;
+
+    if ( bVars == b1 )
+//    if ( bVars == b0 )  // bug fixed by Jin Zhang, Jan 23, 2004
+        return z1;
+
+    if ( (zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletons, bVars)) )
+        return zRes;
+    else
+    {
+        DdNode * zTemp, * zPlus;          
+
+        // solve subproblem
+        zRes = extraZddGetSingletons( dd, cuddT(bVars) );
+        if ( zRes == NULL ) 
+            return NULL;
+        cuddRef( zRes );
+        
+        zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 );
+        if ( zPlus == NULL ) 
+        {
+            Cudd_RecursiveDerefZdd( dd, zRes );
+            return NULL;
+        }
+        cuddRef( zPlus );
+
+        // add these to the result
+        zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+        if ( zRes == NULL )
+        {
+            Cudd_RecursiveDerefZdd( dd, zTemp );
+            Cudd_RecursiveDerefZdd( dd, zPlus );
+            return NULL;
+        }
+        cuddRef( zRes );
+        Cudd_RecursiveDerefZdd( dd, zTemp );
+        Cudd_RecursiveDerefZdd( dd, zPlus );
+        cuddDeref( zRes );
+
+        cuddCacheInsert1( dd, extraZddGetSingletons, bVars, zRes );
+        return zRes;
+    }
+}   /* end of extraZddGetSingletons */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs a recursive step of Extra_bddReduceVarSet.]
+
+  Description [Returns the set of all variables in the given set that are not in the 
+  support of the given function.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * extraBddReduceVarSet( 
+  DdManager * dd,    /* the DD manager */
+  DdNode * bVars,    /* the set of variables to be reduced */
+  DdNode * bF)       /* the function whose support is used for reduction */
+{
+    DdNode * bRes;
+    DdNode * bFR = Cudd_Regular(bF);
+
+    if ( cuddIsConstant(bFR) || bVars == b1 )
+        return bVars;
+
+    if ( (bRes = cuddCacheLookup2(dd, extraBddReduceVarSet, bVars, bF)) )
+        return bRes;
+    else
+    {
+        DdNode * bF0, * bF1;             
+        DdNode * bVarsThis, * bVarsLower, * bTemp;
+        int LevelF;
+
+        // if LevelF is below LevelV, scroll through the vars in bVars 
+        LevelF = dd->perm[bFR->index];
+        for ( bVarsThis = bVars; LevelF > cuddI(dd,bVarsThis->index); bVarsThis = cuddT(bVarsThis) );
+        // scroll also through the current var, because it should be not be added
+        if ( LevelF == cuddI(dd,bVarsThis->index) )
+            bVarsLower = cuddT(bVarsThis);
+        else
+            bVarsLower = bVarsThis;
+
+        // cofactor the function
+        if ( bFR != bF ) // bFunc is complemented 
+        {
+            bF0 = Cudd_Not( cuddE(bFR) );
+            bF1 = Cudd_Not( cuddT(bFR) );
+        }
+        else
+        {
+            bF0 = cuddE(bFR);
+            bF1 = cuddT(bFR);
+        }
+
+        // solve subproblems
+        bRes = extraBddReduceVarSet( dd, bVarsLower, bF0 );
+        if ( bRes == NULL ) 
+            return NULL;
+        cuddRef( bRes );
+
+        bRes = extraBddReduceVarSet( dd, bTemp = bRes, bF1 );
+        if ( bRes == NULL ) 
+        {
+            Cudd_RecursiveDeref( dd, bTemp );
+            return NULL;
+        }
+        cuddRef( bRes );
+        Cudd_RecursiveDeref( dd, bTemp );
+
+        // the current var should not be added
+        // add the skipped vars
+        if ( bVarsThis != bVars )
+        {
+            DdNode * bVarsExtra;
+
+            // extract the skipped variables
+            bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsThis );
+            if ( bVarsExtra == NULL )
+            {
+                Cudd_RecursiveDeref( dd, bRes );
+                return NULL;
+            }
+            cuddRef( bVarsExtra );
+
+            // add these variables
+            bRes = cuddBddAndRecur( dd, bTemp = bRes, bVarsExtra );
+            if ( bRes == NULL ) 
+            {
+                Cudd_RecursiveDeref( dd, bTemp );
+                Cudd_RecursiveDeref( dd, bVarsExtra );
+                return NULL;
+            }
+            cuddRef( bRes );
+            Cudd_RecursiveDeref( dd, bTemp );
+            Cudd_RecursiveDeref( dd, bVarsExtra );
+        }
+        cuddDeref( bRes );
+
+        cuddCacheInsert2( dd, extraBddReduceVarSet, bVars, bF, bRes );
+        return bRes;
+    }
+}   /* end of extraBddReduceVarSet */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Extra_bddCheckVarsSymmetric().]
+
+  Description [Returns b0 if the variables are not symmetric. Returns b1 if the
+  variables can be symmetric. The variables are represented in the form of a 
+  two-variable cube. In case the cube contains one variable (below Var1 level),
+  the cube's pointer is complemented if the variable Var1 occurred on the 
+  current path; otherwise, the cube's pointer is regular. Uses additional 
+  complemented bit (Hash_Not) to mark the result if in the BDD rooted that this
+  node there is a branch passing though the node labeled with Var2.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * extraBddCheckVarsSymmetric( 
+  DdManager * dd,    /* the DD manager */
+  DdNode * bF,
+  DdNode * bVars) 
+{
+    DdNode * bRes;
+
+    if ( bF == b0 )
+        return b1;
+
+    assert( bVars != b1 );
+    
+    if ( (bRes = cuddCacheLookup2(dd, extraBddCheckVarsSymmetric, bF, bVars)) )
+        return bRes;
+    else
+    {
+        DdNode * bRes0, * bRes1;
+        DdNode * bF0, * bF1;             
+        DdNode * bFR = Cudd_Regular(bF);
+        int LevelF = cuddI(dd,bFR->index);
+
+        DdNode * bVarsR = Cudd_Regular(bVars);
+        int fVar1Pres;
+        int iLev1;
+        int iLev2;
+
+        if ( bVarsR != bVars ) // cube's pointer is complemented
+        {
+            assert( cuddT(bVarsR) == b1 );
+            fVar1Pres = 1;                    // the first var is present on the path
+            iLev1 = -1;                       // we are already below the first var level
+            iLev2 = dd->perm[bVarsR->index];  // the level of the second var
+        }
+        else  // cube's pointer is NOT complemented
+        {
+            fVar1Pres = 0;                    // the first var is absent on the path
+            if ( cuddT(bVars) == b1 )
+            {
+                iLev1 = -1;                             // we are already below the first var level 
+                iLev2 = dd->perm[bVars->index];         // the level of the second var
+            }
+            else
+            {
+                assert( cuddT(cuddT(bVars)) == b1 );
+                iLev1 = dd->perm[bVars->index];         // the level of the first var 
+                iLev2 = dd->perm[cuddT(bVars)->index];  // the level of the second var
+            }
+        }
+
+        // cofactor the function
+        // the cofactors are needed only if we are above the second level
+        if ( LevelF < iLev2 )
+        {
+            if ( bFR != bF ) // bFunc is complemented 
+            {
+                bF0 = Cudd_Not( cuddE(bFR) );
+                bF1 = Cudd_Not( cuddT(bFR) );
+            }
+            else
+            {
+                bF0 = cuddE(bFR);
+                bF1 = cuddT(bFR);
+            }
+        }
+        else
+            bF0 = bF1 = NULL;
+
+        // consider five cases:
+        // (1) F is above iLev1
+        // (2) F is on the level iLev1
+        // (3) F is between iLev1 and iLev2
+        // (4) F is on the level iLev2
+        // (5) F is below iLev2
+
+        // (1) F is above iLev1
+        if ( LevelF < iLev1 )
+        {
+            // the returned result cannot have the hash attribute
+            // because we still did not reach the level of Var1;
+            // the attribute never travels above the level of Var1
+            bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars );
+//          assert( !Hash_IsComplement( bRes0 ) );
+            assert( bRes0 != z0 );
+            if ( bRes0 == b0 )
+                bRes = b0;
+            else
+                bRes = extraBddCheckVarsSymmetric( dd, bF1, bVars );
+//          assert( !Hash_IsComplement( bRes ) );
+            assert( bRes != z0 );
+        }
+        // (2) F is on the level iLev1
+        else if ( LevelF == iLev1 )
+        {
+            bRes0 = extraBddCheckVarsSymmetric( dd, bF0, Cudd_Not( cuddT(bVars) ) );
+            if ( bRes0 == b0 )
+                bRes = b0;
+            else
+            {
+                bRes1 = extraBddCheckVarsSymmetric( dd, bF1, Cudd_Not( cuddT(bVars) ) );
+                if ( bRes1 == b0 )
+                    bRes = b0;
+                else
+                {
+//                  if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) )
+                    if ( bRes0 == z0 || bRes1 == z0 )
+                        bRes = b1;
+                    else
+                        bRes = b0;
+                }
+            }
+        }
+        // (3) F is between iLev1 and iLev2
+        else if ( LevelF < iLev2 )
+        {
+            bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars );
+            if ( bRes0 == b0 )
+                bRes = b0;
+            else
+            {
+                bRes1 = extraBddCheckVarsSymmetric( dd, bF1, bVars );
+                if ( bRes1 == b0 )
+                    bRes = b0;
+                else
+                {
+//                  if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) )
+//                      bRes = Hash_Not( b1 );
+                    if ( bRes0 == z0 || bRes1 == z0 )
+                        bRes = z0;
+                    else
+                        bRes = b1;
+                }
+            }
+        }
+        // (4) F is on the level iLev2
+        else if ( LevelF == iLev2 )
+        {
+            // this is the only place where the hash attribute (Hash_Not) can be added 
+            // to the result; it can be added only if the path came through the node
+            // lebeled with Var1; therefore, the hash attribute cannot be returned
+            // to the caller function
+            if ( fVar1Pres )
+//              bRes = Hash_Not( b1 );
+                bRes = z0;
+            else 
+                bRes = b0;
+        }
+        // (5) F is below iLev2
+        else // if ( LevelF > iLev2 )
+        {
+            // it is possible that the path goes through the node labeled by Var1
+            // and still everything is okay; we do not label with Hash_Not here
+            // because the path does not go through node labeled by Var2
+            bRes = b1;
+        }
+
+        cuddCacheInsert2(dd, extraBddCheckVarsSymmetric, bF, bVars, bRes);
+        return bRes;
+    }
+} /* end of extraBddCheckVarsSymmetric */
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the reordering-sensitive step of Extra_zddTupleFromBdd().]
+
+  Description [Generates in a bottom-up fashion ZDD for all combinations
+               composed of k variables out of variables belonging to Support.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode* extraZddTuplesFromBdd( 
+  DdManager * dd,   /* the DD manager */
+  DdNode * bVarsK,   /* the number of variables in tuples */
+  DdNode * bVarsN)   /* the set of all variables */
+{
+    DdNode *zRes, *zRes0, *zRes1;
+    statLine(dd); 
+
+    /* terminal cases */
+/*  if ( k < 0 || k > n )
+ *      return dd->zero;
+ *  if ( n == 0 )
+ *      return dd->one; 
+ */
+    if ( cuddI( dd, bVarsK->index ) < cuddI( dd, bVarsN->index ) )
+        return z0;
+    if ( bVarsN == b1 )
+        return z1;
+
+    /* check cache */
+    zRes = cuddCacheLookup2Zdd(dd, extraZddTuplesFromBdd, bVarsK, bVarsN);
+    if (zRes)
+        return(zRes);
+
+    /* ZDD in which this variable is 0 */
+/*  zRes0 = extraZddTuplesFromBdd( dd, k,     n-1 ); */
+    zRes0 = extraZddTuplesFromBdd( dd, bVarsK, cuddT(bVarsN) );
+    if ( zRes0 == NULL ) 
+        return NULL;
+    cuddRef( zRes0 );
+
+    /* ZDD in which this variable is 1 */
+/*  zRes1 = extraZddTuplesFromBdd( dd, k-1,          n-1 ); */
+    if ( bVarsK == b1 )
+    {
+        zRes1 = z0;
+        cuddRef( zRes1 );
+    }
+    else
+    {
+        zRes1 = extraZddTuplesFromBdd( dd, cuddT(bVarsK), cuddT(bVarsN) );
+        if ( zRes1 == NULL ) 
+        {
+            Cudd_RecursiveDerefZdd( dd, zRes0 );
+            return NULL;
+        }
+        cuddRef( zRes1 );
+    }
+
+    /* compose Res0 and Res1 with the given ZDD variable */
+    zRes = cuddZddGetNode( dd, 2*bVarsN->index, zRes1, zRes0 );
+    if ( zRes == NULL ) 
+    {
+        Cudd_RecursiveDerefZdd( dd, zRes0 );
+        Cudd_RecursiveDerefZdd( dd, zRes1 );
+        return NULL;
+    }
+    cuddDeref( zRes0 );
+    cuddDeref( zRes1 );
+
+    /* insert the result into cache */
+    cuddCacheInsert2(dd, extraZddTuplesFromBdd, bVarsK, bVarsN, zRes);
+    return zRes;
+
+} /* end of extraZddTuplesFromBdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Extra_zddSelectOneSubset.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * extraZddSelectOneSubset( 
+  DdManager * dd, 
+  DdNode * zS )
+// selects one subset from the ZDD zS
+// returns z0 if and only if zS is an empty set of cubes
+{
+    DdNode * zRes;
+
+    if ( zS == z0 )    return z0;
+    if ( zS == z1 )    return z1;
+    
+    // check cache
+    if ( (zRes = cuddCacheLookup1Zdd( dd, extraZddSelectOneSubset, zS )) )
+        return zRes;
+    else
+    {
+        DdNode * zS0, * zS1, * zTemp; 
+
+        zS0 = cuddE(zS);
+        zS1 = cuddT(zS);
+
+        if ( zS0 != z0 )
+        {
+            zRes = extraZddSelectOneSubset( dd, zS0 );
+            if ( zRes == NULL )
+                return NULL;
+        }
+        else // if ( zS0 == z0 )
+        {
+            assert( zS1 != z0 );
+            zRes = extraZddSelectOneSubset( dd, zS1 );
+            if ( zRes == NULL )
+                return NULL;
+            cuddRef( zRes );
+
+            zRes = cuddZddGetNode( dd, zS->index, zTemp = zRes, z0 );
+            if ( zRes == NULL ) 
+            {
+                Cudd_RecursiveDerefZdd( dd, zTemp );
+                return NULL;
+            }
+            cuddDeref( zTemp );
+        }
+
+        // insert the result into cache
+        cuddCacheInsert1( dd, extraZddSelectOneSubset, zS, zRes );
+        return zRes;
+    }       
+} /* end of extraZddSelectOneSubset */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static Functions                                            */
+/*---------------------------------------------------------------------------*/
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraBddTime.c b/abc-build/src/misc/extra/extraBddTime.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraBddTime.c
@@ -0,0 +1,660 @@
+/**CFile****************************************************************
+
+  FileName    [extraBddTime.c]
+
+  PackageName [extra]
+
+  Synopsis    [Procedures to control runtime in BDD operators.]
+
+  Author      [Alan Mishchenko]
+
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - September 1, 2003.]
+
+  Revision    [$Id: extraBddTime.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define CHECK_FACTOR 10
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * cuddBddAndRecurTime( DdManager * manager, DdNode * f, DdNode * g, int * pRecCalls, int TimeOut );
+static DdNode * cuddBddAndAbstractRecurTime( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube, int * pRecCalls, int TimeOut );
+static DdNode * extraTransferPermuteTime( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute, int TimeOut );
+static DdNode * extraTransferPermuteRecurTime( DdManager * ddS, DdManager * ddD, DdNode * f, st__table * table, int * Permute, int TimeOut );
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the conjunction of two BDDs f and g.]
+
+  Description [Computes the conjunction of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAndAbstract Cudd_bddIntersect
+  Cudd_bddOr Cudd_bddNand Cudd_bddNor Cudd_bddXor Cudd_bddXnor]
+
+******************************************************************************/
+DdNode *
+Extra_bddAndTime(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  int TimeOut)
+{
+    DdNode *res;
+    int Counter = 0;
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddAndRecurTime(dd,f,g, &Counter, TimeOut);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Extra_bddAndTime */
+
+/**Function********************************************************************
+
+  Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
+  variables in cube.]
+
+  Description [Takes the AND of two BDDs and simultaneously abstracts
+  the variables in cube. The variables are existentially abstracted.
+  Returns a pointer to the result is successful; NULL otherwise.
+  Cudd_bddAndAbstract implements the semiring matrix multiplication
+  algorithm for the boolean semiring.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addMatrixMultiply Cudd_addTriangle Cudd_bddAnd]
+
+******************************************************************************/
+DdNode *
+Extra_bddAndAbstractTime(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  DdNode * cube,
+  int TimeOut)
+{
+    DdNode *res;
+    int Counter = 0;
+
+    do {
+	manager->reordered = 0;
+	res = cuddBddAndAbstractRecurTime(manager, f, g, cube, &Counter, TimeOut);
+    } while (manager->reordered == 1);
+    return(res);
+
+} /* end of Extra_bddAndAbstractTime */
+
+/**Function********************************************************************
+
+  Synopsis    [Convert a {A,B}DD from a manager to another with variable remapping.]
+
+  Description [Convert a {A,B}DD from a manager to another one. The orders of the
+  variables in the two managers may be different. Returns a
+  pointer to the {A,B}DD in the destination manager if successful; NULL
+  otherwise. The i-th entry in the array Permute tells what is the index
+  of the i-th variable from the old manager in the new manager.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_TransferPermuteTime( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute, int TimeOut )
+{
+    DdNode * bRes;
+    do
+    {
+        ddDestination->reordered = 0;
+        bRes = extraTransferPermuteTime( ddSource, ddDestination, f, Permute, TimeOut );
+    }
+    while ( ddDestination->reordered == 1 );
+    return ( bRes );
+
+} /* end of Extra_TransferPermuteTime */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Implements the recursive step of Cudd_bddAnd.]
+
+  Description [Implements the recursive step of Cudd_bddAnd by taking
+  the conjunction of two BDDs.  Returns a pointer to the result is
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddAnd]
+
+******************************************************************************/
+DdNode *
+cuddBddAndRecurTime(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  int * pRecCalls,
+  int TimeOut)
+{
+    DdNode *F, *fv, *fnv, *G, *gv, *gnv;
+    DdNode *one, *r, *t, *e;
+    unsigned int topf, topg, index;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+
+    /* Terminal cases. */
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    if (F == G) {
+	if (f == g) return(f);
+	else return(Cudd_Not(one));
+    }
+    if (F == one) {
+	if (f == one) return(g);
+	else return(f);
+    }
+    if (G == one) {
+	if (g == one) return(f);
+	else return(g);
+    }
+
+    /* At this point f and g are not constant. */
+    if (f > g) { /* Try to increase cache efficiency. */
+	DdNode *tmp = f;
+	f = g;
+	g = tmp;
+	F = Cudd_Regular(f);
+	G = Cudd_Regular(g);
+    }
+
+    /* Check cache. */
+    if (F->ref != 1 || G->ref != 1) {
+	r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g);
+	if (r != NULL) return(r);
+    }
+
+//    if ( TimeOut && ((*pRecCalls)++ % CHECK_FACTOR) == 0 && TimeOut < Abc_Clock() )
+    if ( TimeOut && Abc_Clock() > TimeOut )
+        return NULL;
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    topf = manager->perm[F->index];
+    topg = manager->perm[G->index];
+
+    /* Compute cofactors. */
+    if (topf <= topg) {
+	index = F->index;
+	fv = cuddT(F);
+	fnv = cuddE(F);
+	if (Cudd_IsComplement(f)) {
+	    fv = Cudd_Not(fv);
+	    fnv = Cudd_Not(fnv);
+	}
+    } else {
+	index = G->index;
+	fv = fnv = f;
+    }
+
+    if (topg <= topf) {
+	gv = cuddT(G);
+	gnv = cuddE(G);
+	if (Cudd_IsComplement(g)) {
+	    gv = Cudd_Not(gv);
+	    gnv = Cudd_Not(gnv);
+	}
+    } else {
+	gv = gnv = g;
+    }
+
+    t = cuddBddAndRecurTime(manager, fv, gv, pRecCalls, TimeOut);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+
+    e = cuddBddAndRecurTime(manager, fnv, gnv, pRecCalls, TimeOut);
+    if (e == NULL) {
+	Cudd_IterDerefBdd(manager, t);
+	return(NULL);
+    }
+    cuddRef(e);
+
+    if (t == e) {
+	r = t;
+    } else {
+	if (Cudd_IsComplement(t)) {
+	    r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(manager, t);
+		Cudd_IterDerefBdd(manager, e);
+		return(NULL);
+	    }
+	    r = Cudd_Not(r);
+	} else {
+	    r = cuddUniqueInter(manager,(int)index,t,e);
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(manager, t);
+		Cudd_IterDerefBdd(manager, e);
+		return(NULL);
+	    }
+	}
+    }
+    cuddDeref(e);
+    cuddDeref(t);
+    if (F->ref != 1 || G->ref != 1)
+	cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r);
+    return(r);
+
+} /* end of cuddBddAndRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
+  variables in cube.]
+
+  Description [Takes the AND of two BDDs and simultaneously abstracts
+  the variables in cube. The variables are existentially abstracted.
+  Returns a pointer to the result is successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddAndAbstract]
+
+******************************************************************************/
+DdNode *
+cuddBddAndAbstractRecurTime(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  DdNode * cube,
+  int * pRecCalls,
+  int TimeOut)
+{
+    DdNode *F, *ft, *fe, *G, *gt, *ge;
+    DdNode *one, *zero, *r, *t, *e;
+    unsigned int topf, topg, topcube, top, index;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    /* Terminal cases. */
+    if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
+    if (f == one && g == one)	return(one);
+
+    if (cube == one) {
+	return(cuddBddAndRecurTime(manager, f, g, pRecCalls, TimeOut));
+    }
+    if (f == one || f == g) {
+	return(cuddBddExistAbstractRecur(manager, g, cube));
+    }
+    if (g == one) {
+	return(cuddBddExistAbstractRecur(manager, f, cube));
+    }
+    /* At this point f, g, and cube are not constant. */
+
+    if (f > g) { /* Try to increase cache efficiency. */
+	DdNode *tmp = f;
+	f = g;
+	g = tmp;
+    }
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    topf = manager->perm[F->index];
+    topg = manager->perm[G->index];
+    top = ddMin(topf, topg);
+    topcube = manager->perm[cube->index];
+
+    while (topcube < top) {
+	cube = cuddT(cube);
+	if (cube == one) {
+	    return(cuddBddAndRecurTime(manager, f, g, pRecCalls, TimeOut));
+	}
+	topcube = manager->perm[cube->index];
+    }
+    /* Now, topcube >= top. */
+
+    /* Check cache. */
+    if (F->ref != 1 || G->ref != 1) {
+	r = cuddCacheLookup(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube);
+	if (r != NULL) {
+	    return(r);
+	}
+    }
+
+//    if ( TimeOut && ((*pRecCalls)++ % CHECK_FACTOR) == 0 && TimeOut < Abc_Clock() )
+    if ( TimeOut && Abc_Clock() > TimeOut )
+        return NULL;
+
+    if (topf == top) {
+	index = F->index;
+	ft = cuddT(F);
+	fe = cuddE(F);
+	if (Cudd_IsComplement(f)) {
+	    ft = Cudd_Not(ft);
+	    fe = Cudd_Not(fe);
+	}
+    } else {
+	index = G->index;
+	ft = fe = f;
+    }
+
+    if (topg == top) {
+	gt = cuddT(G);
+	ge = cuddE(G);
+	if (Cudd_IsComplement(g)) {
+	    gt = Cudd_Not(gt);
+	    ge = Cudd_Not(ge);
+	}
+    } else {
+	gt = ge = g;
+    }
+
+    if (topcube == top) {	/* quantify */
+	DdNode *Cube = cuddT(cube);
+	t = cuddBddAndAbstractRecurTime(manager, ft, gt, Cube, pRecCalls, TimeOut);
+	if (t == NULL) return(NULL);
+	/* Special case: 1 OR anything = 1. Hence, no need to compute
+	** the else branch if t is 1. Likewise t + t * anything == t.
+	** Notice that t == fe implies that fe does not depend on the
+	** variables in Cube. Likewise for t == ge.
+	*/
+	if (t == one || t == fe || t == ge) {
+	    if (F->ref != 1 || G->ref != 1)
+		cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG,
+				f, g, cube, t);
+	    return(t);
+	}
+	cuddRef(t);
+	/* Special case: t + !t * anything == t + anything. */
+	if (t == Cudd_Not(fe)) {
+	    e = cuddBddExistAbstractRecur(manager, ge, Cube);
+	} else if (t == Cudd_Not(ge)) {
+	    e = cuddBddExistAbstractRecur(manager, fe, Cube);
+	} else {
+	    e = cuddBddAndAbstractRecurTime(manager, fe, ge, Cube, pRecCalls, TimeOut);
+	}
+	if (e == NULL) {
+	    Cudd_IterDerefBdd(manager, t);
+	    return(NULL);
+	}
+	if (t == e) {
+	    r = t;
+	    cuddDeref(t);
+	} else {
+	    cuddRef(e);
+	    r = cuddBddAndRecurTime(manager, Cudd_Not(t), Cudd_Not(e), pRecCalls, TimeOut);
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(manager, t);
+		Cudd_IterDerefBdd(manager, e);
+		return(NULL);
+	    }
+	    r = Cudd_Not(r);
+	    cuddRef(r);
+	    Cudd_DelayedDerefBdd(manager, t);
+	    Cudd_DelayedDerefBdd(manager, e);
+	    cuddDeref(r);
+	}
+    } else {
+	t = cuddBddAndAbstractRecurTime(manager, ft, gt, cube, pRecCalls, TimeOut);
+	if (t == NULL) return(NULL);
+	cuddRef(t);
+	e = cuddBddAndAbstractRecurTime(manager, fe, ge, cube, pRecCalls, TimeOut);
+	if (e == NULL) {
+	    Cudd_IterDerefBdd(manager, t);
+	    return(NULL);
+	}
+	if (t == e) {
+	    r = t;
+	    cuddDeref(t);
+	} else {
+	    cuddRef(e);
+	    if (Cudd_IsComplement(t)) {
+		r = cuddUniqueInter(manager, (int) index,
+				    Cudd_Not(t), Cudd_Not(e));
+		if (r == NULL) {
+		    Cudd_IterDerefBdd(manager, t);
+		    Cudd_IterDerefBdd(manager, e);
+		    return(NULL);
+		}
+		r = Cudd_Not(r);
+	    } else {
+		r = cuddUniqueInter(manager,(int)index,t,e);
+		if (r == NULL) {
+		    Cudd_IterDerefBdd(manager, t);
+		    Cudd_IterDerefBdd(manager, e);
+		    return(NULL);
+		}
+	    }
+	    cuddDeref(e);
+	    cuddDeref(t);
+	}
+    }
+
+    if (F->ref != 1 || G->ref != 1)
+	cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, r);
+    return (r);
+
+} /* end of cuddBddAndAbstractRecur */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Convert a BDD from a manager to another one.]
+
+  Description [Convert a BDD from a manager to another one. Returns a
+  pointer to the BDD in the destination manager if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Extra_TransferPermute]
+
+******************************************************************************/
+DdNode * extraTransferPermuteTime( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute, int TimeOut )
+{
+    DdNode *res;
+    st__table *table = NULL;
+    st__generator *gen = NULL;
+    DdNode *key, *value;
+
+    table = st__init_table( st__ptrcmp, st__ptrhash );
+    if ( table == NULL )
+        goto failure;
+    res = extraTransferPermuteRecurTime( ddS, ddD, f, table, Permute, TimeOut );
+    if ( res != NULL )
+        cuddRef( res );
+
+    /* Dereference all elements in the table and dispose of the table.
+       ** This must be done also if res is NULL to avoid leaks in case of
+       ** reordering. */
+    gen = st__init_gen( table );
+    if ( gen == NULL )
+        goto failure;
+    while ( st__gen( gen, ( const char ** ) &key, ( char ** ) &value ) )
+    {
+        Cudd_RecursiveDeref( ddD, value );
+    }
+    st__free_gen( gen );
+    gen = NULL;
+    st__free_table( table );
+    table = NULL;
+
+    if ( res != NULL )
+        cuddDeref( res );
+    return ( res );
+
+  failure:
+    if ( table != NULL )
+        st__free_table( table );
+    if ( gen != NULL )
+        st__free_gen( gen );
+    return ( NULL );
+
+} /* end of extraTransferPermuteTime */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Extra_TransferPermute.]
+
+  Description [Performs the recursive step of Extra_TransferPermute.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [extraTransferPermuteTime]
+
+******************************************************************************/
+static DdNode * 
+extraTransferPermuteRecurTime( 
+  DdManager * ddS, 
+  DdManager * ddD, 
+  DdNode * f, 
+  st__table * table, 
+  int * Permute,
+  int TimeOut )
+{
+    DdNode *ft, *fe, *t, *e, *var, *res;
+    DdNode *one, *zero;
+    int index;
+    int comple = 0;
+
+    statLine( ddD );
+    one = DD_ONE( ddD );
+    comple = Cudd_IsComplement( f );
+
+    /* Trivial cases. */
+    if ( Cudd_IsConstant( f ) )
+        return ( Cudd_NotCond( one, comple ) );
+
+
+    /* Make canonical to increase the utilization of the cache. */
+    f = Cudd_NotCond( f, comple );
+    /* Now f is a regular pointer to a non-constant node. */
+
+    /* Check the cache. */
+    if ( st__lookup( table, ( char * ) f, ( char ** ) &res ) )
+        return ( Cudd_NotCond( res, comple ) );
+
+    if ( TimeOut && Abc_Clock() > TimeOut )
+        return NULL;
+
+    /* Recursive step. */
+    if ( Permute )
+        index = Permute[f->index];
+    else
+        index = f->index;
+
+    ft = cuddT( f );
+    fe = cuddE( f );
+
+    t = extraTransferPermuteRecurTime( ddS, ddD, ft, table, Permute, TimeOut );
+    if ( t == NULL )
+    {
+        return ( NULL );
+    }
+    cuddRef( t );
+
+    e = extraTransferPermuteRecurTime( ddS, ddD, fe, table, Permute, TimeOut );
+    if ( e == NULL )
+    {
+        Cudd_RecursiveDeref( ddD, t );
+        return ( NULL );
+    }
+    cuddRef( e );
+
+    zero = Cudd_Not(ddD->one);
+    var = cuddUniqueInter( ddD, index, one, zero );
+    if ( var == NULL )
+    {
+        Cudd_RecursiveDeref( ddD, t );
+        Cudd_RecursiveDeref( ddD, e );
+        return ( NULL );
+    }
+    res = cuddBddIteRecur( ddD, var, t, e );
+
+    if ( res == NULL )
+    {
+        Cudd_RecursiveDeref( ddD, t );
+        Cudd_RecursiveDeref( ddD, e );
+        return ( NULL );
+    }
+    cuddRef( res );
+    Cudd_RecursiveDeref( ddD, t );
+    Cudd_RecursiveDeref( ddD, e );
+
+    if ( st__add_direct( table, ( char * ) f, ( char * ) res ) ==
+         st__OUT_OF_MEM )
+    {
+        Cudd_RecursiveDeref( ddD, res );
+        return ( NULL );
+    }
+    return ( Cudd_NotCond( res, comple ) );
+
+}  /* end of extraTransferPermuteRecurTime */
+
+////////////////////////////////////////////////////////////////////////
+///                           END OF FILE                            ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraBddUnate.c b/abc-build/src/misc/extra/extraBddUnate.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraBddUnate.c
@@ -0,0 +1,646 @@
+/**CFile****************************************************************
+
+  FileName    [extraBddUnate.c]
+
+  PackageName [extra]
+
+  Synopsis    [Efficient methods to compute the information about
+  unate variables using an algorithm that is conceptually similar to
+  the algorithm for two-variable symmetry computation presented in:
+  A. Mishchenko. Fast Computation of Symmetries in Boolean Functions. 
+  Transactions on CAD, Nov. 2003.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - September 1, 2003.]
+
+  Revision    [$Id: extraBddUnate.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extraBdd.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the classical symmetry information for the function.]
+
+  Description [Returns the symmetry information in the form of Extra_UnateInfo_t structure.]
+
+  SideEffects [If the ZDD variables are not derived from BDD variables with
+  multiplicity 2, this function may derive them in a wrong way.]
+
+  SeeAlso     []
+
+******************************************************************************/
+Extra_UnateInfo_t * Extra_UnateComputeFast( 
+  DdManager * dd,   /* the manager */
+  DdNode * bFunc)   /* the function whose symmetries are computed */
+{
+    DdNode * bSupp;
+    DdNode * zRes;
+    Extra_UnateInfo_t * p;
+
+    bSupp = Cudd_Support( dd, bFunc );                      Cudd_Ref( bSupp );
+    zRes  = Extra_zddUnateInfoCompute( dd, bFunc, bSupp );  Cudd_Ref( zRes );
+
+    p = Extra_UnateInfoCreateFromZdd( dd, zRes, bSupp );
+
+    Cudd_RecursiveDeref( dd, bSupp );
+    Cudd_RecursiveDerefZdd( dd, zRes );
+
+    return p;
+
+} /* end of Extra_UnateInfoCompute */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the classical symmetry information as a ZDD.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_zddUnateInfoCompute( 
+  DdManager * dd,   /* the DD manager */
+  DdNode * bF,
+  DdNode * bVars) 
+{
+    DdNode * res;
+    do {
+        dd->reordered = 0;
+        res = extraZddUnateInfoCompute( dd, bF, bVars );
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Extra_zddUnateInfoCompute */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a set of variables into a set of singleton subsets.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_zddGetSingletonsBoth( 
+  DdManager * dd,    /* the DD manager */
+  DdNode * bVars)    /* the set of variables */
+{
+    DdNode * res;
+    do {
+        dd->reordered = 0;
+        res = extraZddGetSingletonsBoth( dd, bVars );
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Extra_zddGetSingletonsBoth */
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates unateness information structure.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Extra_UnateInfo_t *  Extra_UnateInfoAllocate( int nVars )
+{
+    Extra_UnateInfo_t * p;
+    // allocate and clean the storage for unateness info
+    p = ABC_ALLOC( Extra_UnateInfo_t, 1 );
+    memset( p, 0, sizeof(Extra_UnateInfo_t) );
+    p->nVars     = nVars;
+    p->pVars     = ABC_ALLOC( Extra_UnateVar_t, nVars );  
+    memset( p->pVars, 0, nVars * sizeof(Extra_UnateVar_t) );
+    return p;
+} /* end of Extra_UnateInfoAllocate */
+
+/**Function********************************************************************
+
+  Synopsis    [Deallocates symmetry information structure.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Extra_UnateInfoDissolve( Extra_UnateInfo_t * p )
+{
+    ABC_FREE( p->pVars );
+    ABC_FREE( p );
+} /* end of Extra_UnateInfoDissolve */
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates symmetry information structure.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Extra_UnateInfoPrint( Extra_UnateInfo_t * p )
+{
+    char * pBuffer;
+    int i;
+    pBuffer = ABC_ALLOC( char, p->nVarsMax+1 );
+    memset( pBuffer, ' ', p->nVarsMax );
+    pBuffer[p->nVarsMax] = 0;
+    for ( i = 0; i < p->nVars; i++ )
+        if ( p->pVars[i].Neg )
+            pBuffer[ p->pVars[i].iVar ] = 'n';
+        else if ( p->pVars[i].Pos )
+            pBuffer[ p->pVars[i].iVar ] = 'p';
+        else
+            pBuffer[ p->pVars[i].iVar ] = '.';
+    printf( "%s\n", pBuffer );
+    ABC_FREE( pBuffer );
+} /* end of Extra_UnateInfoPrint */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates the symmetry information structure from ZDD.]
+
+  Description [ZDD representation of symmetries is the set of cubes, each
+  of which has two variables in the positive polarity. These variables correspond
+  to the symmetric variable pair.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Extra_UnateInfo_t * Extra_UnateInfoCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bSupp )
+{
+    Extra_UnateInfo_t * p;
+    DdNode * bTemp, * zSet, * zCube, * zTemp;
+    int * pMapVars2Nums;
+    int i, nSuppSize;
+
+    nSuppSize = Extra_bddSuppSize( dd, bSupp );
+
+    // allocate and clean the storage for symmetry info
+    p = Extra_UnateInfoAllocate( nSuppSize );
+
+    // allocate the storage for the temporary map
+    pMapVars2Nums = ABC_ALLOC( int, dd->size );
+    memset( pMapVars2Nums, 0, dd->size * sizeof(int) );
+
+    // assign the variables
+    p->nVarsMax = dd->size;
+    for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ )
+    {
+        p->pVars[i].iVar = bTemp->index;
+        pMapVars2Nums[bTemp->index] = i;
+    }
+
+    // write the symmetry info into the structure
+    zSet = zPairs;   Cudd_Ref( zSet );
+//    Cudd_zddPrintCover( dd, zPairs );    printf( "\n" );
+    while ( zSet != z0 )
+    {
+        // get the next cube
+        zCube  = Extra_zddSelectOneSubset( dd, zSet );    Cudd_Ref( zCube );
+
+        // add this var to the data structure
+        assert( cuddT(zCube) == z1 && cuddE(zCube) == z0 );
+        if ( zCube->index & 1 ) // neg
+            p->pVars[ pMapVars2Nums[zCube->index/2] ].Neg = 1;
+        else
+            p->pVars[ pMapVars2Nums[zCube->index/2] ].Pos = 1;
+        // count the unate vars
+        p->nUnate++;
+
+        // update the cuver and deref the cube
+        zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube );     Cudd_Ref( zSet );
+        Cudd_RecursiveDerefZdd( dd, zTemp );
+        Cudd_RecursiveDerefZdd( dd, zCube );
+
+    } // for each cube 
+    Cudd_RecursiveDerefZdd( dd, zSet );
+    ABC_FREE( pMapVars2Nums );
+    return p;
+
+} /* end of Extra_UnateInfoCreateFromZdd */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the classical unateness information for the function.]
+
+  Description [Uses the naive way of comparing cofactors.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Extra_UnateInfo_t * Extra_UnateComputeSlow( DdManager * dd, DdNode * bFunc )
+{
+    int nSuppSize;
+    DdNode * bSupp, * bTemp;
+    Extra_UnateInfo_t * p;
+    int i, Res;
+
+    // compute the support
+    bSupp = Cudd_Support( dd, bFunc );   Cudd_Ref( bSupp );
+    nSuppSize = Extra_bddSuppSize( dd, bSupp );
+//printf( "Support = %d. ", nSuppSize );
+//Extra_bddPrint( dd, bSupp );
+//printf( "%d ", nSuppSize );
+
+    // allocate the storage for symmetry info
+    p = Extra_UnateInfoAllocate( nSuppSize );
+
+    // assign the variables
+    p->nVarsMax = dd->size;
+    for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ )
+    {
+        Res = Extra_bddCheckUnateNaive( dd, bFunc, bTemp->index );
+        p->pVars[i].iVar = bTemp->index;
+        if ( Res == -1 )
+            p->pVars[i].Neg = 1;
+        else if ( Res == 1 )
+            p->pVars[i].Pos = 1;
+        p->nUnate += (Res != 0);
+    }
+    Cudd_RecursiveDeref( dd, bSupp );
+    return p;
+
+} /* end of Extra_UnateComputeSlow */
+
+/**Function********************************************************************
+
+  Synopsis    [Checks if the two variables are symmetric.]
+
+  Description [Returns 0 if vars are not unate. Return -1/+1 if the var is neg/pos unate.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Extra_bddCheckUnateNaive( 
+  DdManager * dd,   /* the DD manager */
+  DdNode * bF,
+  int iVar) 
+{
+    DdNode * bCof0, * bCof1;
+    int Res;
+
+    assert( iVar < dd->size );
+
+    bCof0 = Cudd_Cofactor( dd, bF, Cudd_Not(Cudd_bddIthVar(dd,iVar)) );  Cudd_Ref( bCof0 );
+    bCof1 = Cudd_Cofactor( dd, bF, Cudd_bddIthVar(dd,iVar) );            Cudd_Ref( bCof1 );
+
+    if ( Cudd_bddLeq( dd, bCof0, bCof1 ) )
+        Res = 1;
+    else if ( Cudd_bddLeq( dd, bCof1, bCof0 ) )
+        Res =-1;
+    else
+        Res = 0;
+
+    Cudd_RecursiveDeref( dd, bCof0 );
+    Cudd_RecursiveDeref( dd, bCof1 );
+    return Res;
+} /* end of Extra_bddCheckUnateNaive */
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Performs a recursive step of Extra_UnateInfoCompute.]
+
+  Description [Returns the set of symmetric variable pairs represented as a set 
+  of two-literal ZDD cubes. Both variables always appear in the positive polarity
+  in the cubes. This function works without building new BDD nodes. Some relatively 
+  small number of ZDD nodes may be built to ensure proper bookkeeping of the 
+  symmetry information.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * 
+extraZddUnateInfoCompute( 
+  DdManager * dd,   /* the manager */
+  DdNode * bFunc,   /* the function whose symmetries are computed */
+  DdNode * bVars )  /* the set of variables on which this function depends */
+{
+    DdNode * zRes;
+    DdNode * bFR = Cudd_Regular(bFunc); 
+
+    if ( cuddIsConstant(bFR) )
+    {
+        if ( cuddIsConstant(bVars) )
+            return z0;
+        return extraZddGetSingletonsBoth( dd, bVars );
+    }
+    assert( bVars != b1 );
+
+    if ( (zRes = cuddCacheLookup2Zdd(dd, extraZddUnateInfoCompute, bFunc, bVars)) )
+        return zRes;
+    else
+    {
+        DdNode * zRes0, * zRes1;
+        DdNode * zTemp, * zPlus;             
+        DdNode * bF0, * bF1;             
+        DdNode * bVarsNew;
+        int nVarsExtra;
+        int LevelF;
+        int AddVar;
+
+        // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV
+        // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F
+        // count how many extra vars are there in bVars
+        nVarsExtra = 0;
+        LevelF = dd->perm[bFR->index];
+        for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) )
+            nVarsExtra++; 
+        // the indexes (level) of variables should be synchronized now
+        assert( bFR->index == bVarsNew->index );
+
+        // cofactor the function
+        if ( bFR != bFunc ) // bFunc is complemented 
+        {
+            bF0 = Cudd_Not( cuddE(bFR) );
+            bF1 = Cudd_Not( cuddT(bFR) );
+        }
+        else
+        {
+            bF0 = cuddE(bFR);
+            bF1 = cuddT(bFR);
+        }
+
+        // solve subproblems
+        zRes0 = extraZddUnateInfoCompute( dd, bF0, cuddT(bVarsNew) );
+        if ( zRes0 == NULL )
+            return NULL;
+        cuddRef( zRes0 );
+
+        // if there is no symmetries in the negative cofactor
+        // there is no need to test the positive cofactor
+        if ( zRes0 == z0 )
+            zRes = zRes0;  // zRes takes reference
+        else
+        {
+            zRes1 = extraZddUnateInfoCompute( dd, bF1, cuddT(bVarsNew) );
+            if ( zRes1 == NULL )
+            {
+                Cudd_RecursiveDerefZdd( dd, zRes0 );
+                return NULL;
+            }
+            cuddRef( zRes1 );
+
+            // only those variables are pair-wise symmetric 
+            // that are pair-wise symmetric in both cofactors
+            // therefore, intersect the solutions
+            zRes = cuddZddIntersect( dd, zRes0, zRes1 );
+            if ( zRes == NULL )
+            {
+                Cudd_RecursiveDerefZdd( dd, zRes0 );
+                Cudd_RecursiveDerefZdd( dd, zRes1 );
+                return NULL;
+            }
+            cuddRef( zRes );
+            Cudd_RecursiveDerefZdd( dd, zRes0 );
+            Cudd_RecursiveDerefZdd( dd, zRes1 );
+        }
+
+        // consider the current top-most variable
+        AddVar = -1;
+        if ( Cudd_bddLeq( dd, bF0, bF1 ) ) // pos
+            AddVar = 0;
+        else if ( Cudd_bddLeq( dd, bF1, bF0 ) ) // neg
+            AddVar = 1;
+        if ( AddVar >= 0 )
+        {
+            // create the singleton
+            zPlus = cuddZddGetNode( dd, 2*bFR->index + AddVar, z1, z0 );
+            if ( zPlus == NULL ) 
+            {
+                Cudd_RecursiveDerefZdd( dd, zRes );
+                return NULL;
+            }
+            cuddRef( zPlus );
+
+            // add these to the result
+            zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+            if ( zRes == NULL )
+            {
+                Cudd_RecursiveDerefZdd( dd, zTemp );
+                Cudd_RecursiveDerefZdd( dd, zPlus );
+                return NULL;
+            }
+            cuddRef( zRes );
+            Cudd_RecursiveDerefZdd( dd, zTemp );
+            Cudd_RecursiveDerefZdd( dd, zPlus );
+        }
+        // only zRes is referenced at this point
+
+        // if we skipped some variables, these variables cannot be symmetric with
+        // any variables that are currently in the support of bF, but they can be 
+        // symmetric with the variables that are in bVars but not in the support of bF
+        for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) )
+        {
+            // create the negative singleton
+            zPlus = cuddZddGetNode( dd, 2*bVarsNew->index+1, z1, z0 );
+            if ( zPlus == NULL ) 
+            {
+                Cudd_RecursiveDerefZdd( dd, zRes );
+                return NULL;
+            }
+            cuddRef( zPlus );
+
+            // add these to the result
+            zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+            if ( zRes == NULL )
+            {
+                Cudd_RecursiveDerefZdd( dd, zTemp );
+                Cudd_RecursiveDerefZdd( dd, zPlus );
+                return NULL;
+            }
+            cuddRef( zRes );
+            Cudd_RecursiveDerefZdd( dd, zTemp );
+            Cudd_RecursiveDerefZdd( dd, zPlus );
+        
+
+            // create the positive singleton
+            zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 );
+            if ( zPlus == NULL ) 
+            {
+                Cudd_RecursiveDerefZdd( dd, zRes );
+                return NULL;
+            }
+            cuddRef( zPlus );
+
+            // add these to the result
+            zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+            if ( zRes == NULL )
+            {
+                Cudd_RecursiveDerefZdd( dd, zTemp );
+                Cudd_RecursiveDerefZdd( dd, zPlus );
+                return NULL;
+            }
+            cuddRef( zRes );
+            Cudd_RecursiveDerefZdd( dd, zTemp );
+            Cudd_RecursiveDerefZdd( dd, zPlus );
+        }
+        cuddDeref( zRes );
+
+        /* insert the result into cache */
+        cuddCacheInsert2(dd, extraZddUnateInfoCompute, bFunc, bVars, zRes);
+        return zRes;
+    }
+} /* end of extraZddUnateInfoCompute */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs a recursive step of Extra_zddGetSingletons.]
+
+  Description [Returns the set of ZDD singletons, containing those pos/neg 
+  polarity ZDD variables that correspond to the BDD variables in bVars.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * extraZddGetSingletonsBoth( 
+  DdManager * dd,    /* the DD manager */
+  DdNode * bVars)    /* the set of variables */
+{
+    DdNode * zRes;
+
+    if ( bVars == b1 )
+        return z1;
+
+    if ( (zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletonsBoth, bVars)) )
+        return zRes;
+    else
+    {
+        DdNode * zTemp, * zPlus;          
+
+        // solve subproblem
+        zRes = extraZddGetSingletonsBoth( dd, cuddT(bVars) );
+        if ( zRes == NULL ) 
+            return NULL;
+        cuddRef( zRes );
+
+        
+        // create the negative singleton
+        zPlus = cuddZddGetNode( dd, 2*bVars->index+1, z1, z0 );
+        if ( zPlus == NULL ) 
+        {
+            Cudd_RecursiveDerefZdd( dd, zRes );
+            return NULL;
+        }
+        cuddRef( zPlus );
+
+        // add these to the result
+        zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+        if ( zRes == NULL )
+        {
+            Cudd_RecursiveDerefZdd( dd, zTemp );
+            Cudd_RecursiveDerefZdd( dd, zPlus );
+            return NULL;
+        }
+        cuddRef( zRes );
+        Cudd_RecursiveDerefZdd( dd, zTemp );
+        Cudd_RecursiveDerefZdd( dd, zPlus );
+        
+
+        // create the positive singleton
+        zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 );
+        if ( zPlus == NULL ) 
+        {
+            Cudd_RecursiveDerefZdd( dd, zRes );
+            return NULL;
+        }
+        cuddRef( zPlus );
+
+        // add these to the result
+        zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+        if ( zRes == NULL )
+        {
+            Cudd_RecursiveDerefZdd( dd, zTemp );
+            Cudd_RecursiveDerefZdd( dd, zPlus );
+            return NULL;
+        }
+        cuddRef( zRes );
+        Cudd_RecursiveDerefZdd( dd, zTemp );
+        Cudd_RecursiveDerefZdd( dd, zPlus );
+
+        cuddDeref( zRes );
+        cuddCacheInsert1( dd, extraZddGetSingletonsBoth, bVars, zRes );
+        return zRes;
+    }
+}   /* end of extraZddGetSingletonsBoth */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static Functions                                            */
+/*---------------------------------------------------------------------------*/
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraUtilBitMatrix.c b/abc-build/src/misc/extra/extraUtilBitMatrix.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraUtilBitMatrix.c
@@ -0,0 +1,420 @@
+/**CFile****************************************************************
+
+  FileName    [extraUtilBitMatrix.c]
+
+  PackageName [extra]
+
+  Synopsis    [Various reusable software utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2003.]
+
+  Revision    [$Id: extraUtilBitMatrix.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+struct Extra_BitMat_t_
+{
+    unsigned ** ppData;      // bit data
+    int         nSize;       // the number of bits in one dimension
+    int         nWords;      // the number of words in one dimension
+    int         nBitShift;   // the number of bits to shift to get words
+    unsigned    uMask;       // the mask to get the number of bits in the word
+    int         nLookups;    // the number of lookups  
+    int         nInserts;    // the number of inserts
+    int         nDeletes;    // the number of deletions
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the bit matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Extra_BitMat_t * Extra_BitMatrixStart( int nSize )
+{
+    Extra_BitMat_t * p;
+    int i;
+    p = ABC_ALLOC( Extra_BitMat_t, 1 );
+    memset( p, 0, sizeof(Extra_BitMat_t) );
+    p->nSize     = nSize;
+    p->nBitShift = (sizeof(unsigned) == 4) ?  5:  6;
+    p->uMask     = (sizeof(unsigned) == 4) ? 31: 63;
+    p->nWords    = nSize / (8 * sizeof(unsigned)) + ((nSize % (8 * sizeof(unsigned))) > 0);
+    p->ppData    = ABC_ALLOC( unsigned *, nSize );
+    p->ppData[0] = ABC_ALLOC( unsigned, nSize * p->nWords );
+    memset( p->ppData[0], 0, sizeof(unsigned) * nSize * p->nWords );
+    for ( i = 1; i < nSize; i++ )
+        p->ppData[i] = p->ppData[i-1] + p->nWords;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the bit matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_BitMatrixClean( Extra_BitMat_t * p )
+{
+    memset( p->ppData[0], 0, sizeof(unsigned) * p->nSize * p->nWords );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the bit matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_BitMatrixStop( Extra_BitMat_t * p )
+{
+    ABC_FREE( p->ppData[0] );
+    ABC_FREE( p->ppData );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the bit-matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_BitMatrixPrint( Extra_BitMat_t * pMat )
+{
+    int i, k, nVars;
+    printf( "\n" );
+    nVars = Extra_BitMatrixReadSize( pMat );
+    for ( i = 0; i < nVars; i++ )
+    {
+        for ( k = 0; k <= i; k++ )
+            printf( " " );
+        for ( k = i+1; k < nVars; k++ )
+            if ( Extra_BitMatrixLookup1( pMat, i, k ) )
+                printf( "1" );
+            else
+                printf( "." );
+        printf( "\n" );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the matrix size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_BitMatrixReadSize( Extra_BitMat_t * p )
+{
+    return p->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the element into the upper part.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_BitMatrixInsert1( Extra_BitMat_t * p, int i, int k )
+{
+    p->nInserts++;
+    if ( i < k )
+        p->ppData[i][k>>p->nBitShift] |= (1<<(k & p->uMask));
+    else
+        p->ppData[k][i>>p->nBitShift] |= (1<<(i & p->uMask));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the element into the upper part.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_BitMatrixLookup1( Extra_BitMat_t * p, int i, int k )
+{
+    p->nLookups++;
+    if ( i < k )
+        return ((p->ppData[i][k>>p->nBitShift] & (1<<(k & p->uMask))) > 0);
+    else
+        return ((p->ppData[k][i>>p->nBitShift] & (1<<(i & p->uMask))) > 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the element into the upper part.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_BitMatrixDelete1( Extra_BitMat_t * p, int i, int k )
+{
+    p->nDeletes++;
+    if ( i < k )
+        p->ppData[i][k>>p->nBitShift] &= ~(1<<(k & p->uMask));
+    else
+        p->ppData[k][i>>p->nBitShift] &= ~(1<<(i & p->uMask));
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the element into the upper part.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_BitMatrixInsert2( Extra_BitMat_t * p, int i, int k )
+{
+    p->nInserts++;
+    if ( i > k )
+        p->ppData[i][k>>p->nBitShift] |= (1<<(k & p->uMask));
+    else
+        p->ppData[k][i>>p->nBitShift] |= (1<<(i & p->uMask));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the element into the upper part.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_BitMatrixLookup2( Extra_BitMat_t * p, int i, int k )
+{
+    p->nLookups++;
+    if ( i > k )
+        return ((p->ppData[i][k>>p->nBitShift] & (1<<(k & p->uMask))) > 0);
+    else
+        return ((p->ppData[k][i>>p->nBitShift] & (1<<(i & p->uMask))) > 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the element into the upper part.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_BitMatrixDelete2( Extra_BitMat_t * p, int i, int k )
+{
+    p->nDeletes++;
+    if ( i > k )
+        p->ppData[i][k>>p->nBitShift] &= ~(1<<(k & p->uMask));
+    else
+        p->ppData[k][i>>p->nBitShift] &= ~(1<<(i & p->uMask));
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the element into the upper part.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_BitMatrixOr( Extra_BitMat_t * p, int i, unsigned * pInfo )
+{
+    int w;
+    for ( w = 0; w < p->nWords; w++ )
+        p->ppData[i][w] |= pInfo[w];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the element into the upper part.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_BitMatrixOrTwo( Extra_BitMat_t * p, int i, int j )
+{
+    int w;
+    for ( w = 0; w < p->nWords; w++ )
+        p->ppData[i][w] = p->ppData[j][w] = (p->ppData[i][w] | p->ppData[j][w]);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of 1's in the upper rectangle.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_BitMatrixCountOnesUpper( Extra_BitMat_t * p )
+{
+    int i, k, nTotal = 0;
+    for ( i = 0; i < p->nSize; i++ )
+        for ( k = i + 1; k < p->nSize; k++ )
+            nTotal += ( (p->ppData[i][k>>5] & (1 << (k&31))) > 0 );
+    return nTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the matrices have no entries in common.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_BitMatrixIsDisjoint( Extra_BitMat_t * p1, Extra_BitMat_t * p2 )
+{
+    int i, w;
+    assert( p1->nSize == p2->nSize );
+    for ( i = 0; i < p1->nSize; i++ )
+        for ( w = 0; w < p1->nWords; w++ )
+            if ( p1->ppData[i][w] & p2->ppData[i][w] )
+                return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the matrix is a set of cliques.]
+
+  Description [For example pairwise symmetry info should satisfy this property.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_BitMatrixIsClique( Extra_BitMat_t * pMat )
+{
+    int v, u, i;
+    for ( v = 0; v < pMat->nSize; v++ )
+    for ( u = v+1; u < pMat->nSize; u++ )
+    {
+        if ( !Extra_BitMatrixLookup1( pMat, v, u ) )
+            continue;
+        // v and u are symmetric
+        for ( i = 0; i < pMat->nSize; i++ )
+        {
+            if ( i == v || i == u )
+                continue;
+            // i is neither v nor u
+            // the symmetry status of i is the same w.r.t. to v and u
+            if ( Extra_BitMatrixLookup1( pMat, i, v ) != Extra_BitMatrixLookup1( pMat, i, u ) )
+                return 0;
+        }
+    }
+    return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraUtilCanon.c b/abc-build/src/misc/extra/extraUtilCanon.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraUtilCanon.c
@@ -0,0 +1,691 @@
+/**CFile****************************************************************
+
+  FileName    [extraUtilMisc.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [extra]
+
+  Synopsis    [Computing canonical forms of Boolean functions using truth tables.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: extraUtilMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+static unsigned s_Truths3[256] = 
+{
+    0x00000000, 0x01010101, 0x01010101, 0x03030303, 0x01010101, 0x05050505, 0x06060606, 0x07070707,
+    0x01010101, 0x06060606, 0x05050505, 0x07070707, 0x03030303, 0x07070707, 0x07070707, 0x0f0f0f0f,
+    0x01010101, 0x11111111, 0x12121212, 0x13131313, 0x14141414, 0x15151515, 0x16161616, 0x17171717,
+    0x18181818, 0x19191919, 0x1a1a1a1a, 0x1b1b1b1b, 0x1c1c1c1c, 0x1d1d1d1d, 0x1e1e1e1e, 0x1f1f1f1f,
+    0x01010101, 0x12121212, 0x11111111, 0x13131313, 0x18181818, 0x1a1a1a1a, 0x19191919, 0x1b1b1b1b,
+    0x14141414, 0x16161616, 0x15151515, 0x17171717, 0x1c1c1c1c, 0x1e1e1e1e, 0x1d1d1d1d, 0x1f1f1f1f,
+    0x03030303, 0x13131313, 0x13131313, 0x33333333, 0x1c1c1c1c, 0x35353535, 0x36363636, 0x37373737,
+    0x1c1c1c1c, 0x36363636, 0x35353535, 0x37373737, 0x3c3c3c3c, 0x3d3d3d3d, 0x3d3d3d3d, 0x3f3f3f3f,
+    0x01010101, 0x14141414, 0x18181818, 0x1c1c1c1c, 0x11111111, 0x15151515, 0x19191919, 0x1d1d1d1d,
+    0x12121212, 0x16161616, 0x1a1a1a1a, 0x1e1e1e1e, 0x13131313, 0x17171717, 0x1b1b1b1b, 0x1f1f1f1f,
+    0x05050505, 0x15151515, 0x1a1a1a1a, 0x35353535, 0x15151515, 0x55555555, 0x56565656, 0x57575757,
+    0x1a1a1a1a, 0x56565656, 0x5a5a5a5a, 0x5b5b5b5b, 0x35353535, 0x57575757, 0x5b5b5b5b, 0x5f5f5f5f,
+    0x06060606, 0x16161616, 0x19191919, 0x36363636, 0x19191919, 0x56565656, 0x66666666, 0x67676767,
+    0x16161616, 0x69696969, 0x56565656, 0x6b6b6b6b, 0x36363636, 0x6b6b6b6b, 0x67676767, 0x6f6f6f6f,
+    0x07070707, 0x17171717, 0x1b1b1b1b, 0x37373737, 0x1d1d1d1d, 0x57575757, 0x67676767, 0x77777777,
+    0x1e1e1e1e, 0x6b6b6b6b, 0x5b5b5b5b, 0x7b7b7b7b, 0x3d3d3d3d, 0x7d7d7d7d, 0x7e7e7e7e, 0x7f7f7f7f,
+    0x01010101, 0x18181818, 0x14141414, 0x1c1c1c1c, 0x12121212, 0x1a1a1a1a, 0x16161616, 0x1e1e1e1e,
+    0x11111111, 0x19191919, 0x15151515, 0x1d1d1d1d, 0x13131313, 0x1b1b1b1b, 0x17171717, 0x1f1f1f1f,
+    0x06060606, 0x19191919, 0x16161616, 0x36363636, 0x16161616, 0x56565656, 0x69696969, 0x6b6b6b6b,
+    0x19191919, 0x66666666, 0x56565656, 0x67676767, 0x36363636, 0x67676767, 0x6b6b6b6b, 0x6f6f6f6f,
+    0x05050505, 0x1a1a1a1a, 0x15151515, 0x35353535, 0x1a1a1a1a, 0x5a5a5a5a, 0x56565656, 0x5b5b5b5b,
+    0x15151515, 0x56565656, 0x55555555, 0x57575757, 0x35353535, 0x5b5b5b5b, 0x57575757, 0x5f5f5f5f,
+    0x07070707, 0x1b1b1b1b, 0x17171717, 0x37373737, 0x1e1e1e1e, 0x5b5b5b5b, 0x6b6b6b6b, 0x7b7b7b7b,
+    0x1d1d1d1d, 0x67676767, 0x57575757, 0x77777777, 0x3d3d3d3d, 0x7e7e7e7e, 0x7d7d7d7d, 0x7f7f7f7f,
+    0x03030303, 0x1c1c1c1c, 0x1c1c1c1c, 0x3c3c3c3c, 0x13131313, 0x35353535, 0x36363636, 0x3d3d3d3d,
+    0x13131313, 0x36363636, 0x35353535, 0x3d3d3d3d, 0x33333333, 0x37373737, 0x37373737, 0x3f3f3f3f,
+    0x07070707, 0x1d1d1d1d, 0x1e1e1e1e, 0x3d3d3d3d, 0x17171717, 0x57575757, 0x6b6b6b6b, 0x7d7d7d7d,
+    0x1b1b1b1b, 0x67676767, 0x5b5b5b5b, 0x7e7e7e7e, 0x37373737, 0x77777777, 0x7b7b7b7b, 0x7f7f7f7f,
+    0x07070707, 0x1e1e1e1e, 0x1d1d1d1d, 0x3d3d3d3d, 0x1b1b1b1b, 0x5b5b5b5b, 0x67676767, 0x7e7e7e7e,
+    0x17171717, 0x6b6b6b6b, 0x57575757, 0x7d7d7d7d, 0x37373737, 0x7b7b7b7b, 0x77777777, 0x7f7f7f7f,
+    0x0f0f0f0f, 0x1f1f1f1f, 0x1f1f1f1f, 0x3f3f3f3f, 0x1f1f1f1f, 0x5f5f5f5f, 0x6f6f6f6f, 0x7f7f7f7f,
+    0x1f1f1f1f, 0x6f6f6f6f, 0x5f5f5f5f, 0x7f7f7f7f, 0x3f3f3f3f, 0x7f7f7f7f, 0x7f7f7f7f, 0xffffffff
+};
+
+static char s_Phases3[256][9] = 
+{
+/*   0 */  {  8,   0, 1, 2, 3, 4, 5, 6, 7 }, 
+/*   1 */  {  1,   0 }, 
+/*   2 */  {  1,   1 }, 
+/*   3 */  {  2,   0, 1 }, 
+/*   4 */  {  1,   2 }, 
+/*   5 */  {  2,   0, 2 }, 
+/*   6 */  {  2,   0, 3 }, 
+/*   7 */  {  1,   0 }, 
+/*   8 */  {  1,   3 }, 
+/*   9 */  {  2,   1, 2 }, 
+/*  10 */  {  2,   1, 3 }, 
+/*  11 */  {  1,   1 }, 
+/*  12 */  {  2,   2, 3 }, 
+/*  13 */  {  1,   2 }, 
+/*  14 */  {  1,   3 }, 
+/*  15 */  {  4,   0, 1, 2, 3 }, 
+/*  16 */  {  1,   4 }, 
+/*  17 */  {  2,   0, 4 }, 
+/*  18 */  {  2,   0, 5 }, 
+/*  19 */  {  1,   0 }, 
+/*  20 */  {  2,   0, 6 }, 
+/*  21 */  {  1,   0 }, 
+/*  22 */  {  1,   0 }, 
+/*  23 */  {  1,   0 }, 
+/*  24 */  {  2,   0, 7 }, 
+/*  25 */  {  1,   0 }, 
+/*  26 */  {  1,   0 }, 
+/*  27 */  {  1,   0 }, 
+/*  28 */  {  1,   0 }, 
+/*  29 */  {  1,   0 }, 
+/*  30 */  {  1,   0 }, 
+/*  31 */  {  1,   0 }, 
+/*  32 */  {  1,   5 }, 
+/*  33 */  {  2,   1, 4 }, 
+/*  34 */  {  2,   1, 5 }, 
+/*  35 */  {  1,   1 }, 
+/*  36 */  {  2,   1, 6 }, 
+/*  37 */  {  1,   1 }, 
+/*  38 */  {  1,   1 }, 
+/*  39 */  {  1,   1 }, 
+/*  40 */  {  2,   1, 7 }, 
+/*  41 */  {  1,   1 }, 
+/*  42 */  {  1,   1 }, 
+/*  43 */  {  1,   1 }, 
+/*  44 */  {  1,   1 }, 
+/*  45 */  {  1,   1 }, 
+/*  46 */  {  1,   1 }, 
+/*  47 */  {  1,   1 }, 
+/*  48 */  {  2,   4, 5 }, 
+/*  49 */  {  1,   4 }, 
+/*  50 */  {  1,   5 }, 
+/*  51 */  {  4,   0, 1, 4, 5 }, 
+/*  52 */  {  1,   6 }, 
+/*  53 */  {  1,   0 }, 
+/*  54 */  {  1,   0 }, 
+/*  55 */  {  1,   0 }, 
+/*  56 */  {  1,   7 }, 
+/*  57 */  {  1,   1 }, 
+/*  58 */  {  1,   1 }, 
+/*  59 */  {  1,   1 }, 
+/*  60 */  {  4,   0, 1, 6, 7 }, 
+/*  61 */  {  1,   0 }, 
+/*  62 */  {  1,   1 }, 
+/*  63 */  {  2,   0, 1 }, 
+/*  64 */  {  1,   6 }, 
+/*  65 */  {  2,   2, 4 }, 
+/*  66 */  {  2,   2, 5 }, 
+/*  67 */  {  1,   2 }, 
+/*  68 */  {  2,   2, 6 }, 
+/*  69 */  {  1,   2 }, 
+/*  70 */  {  1,   2 }, 
+/*  71 */  {  1,   2 }, 
+/*  72 */  {  2,   2, 7 }, 
+/*  73 */  {  1,   2 }, 
+/*  74 */  {  1,   2 }, 
+/*  75 */  {  1,   2 }, 
+/*  76 */  {  1,   2 }, 
+/*  77 */  {  1,   2 }, 
+/*  78 */  {  1,   2 }, 
+/*  79 */  {  1,   2 }, 
+/*  80 */  {  2,   4, 6 }, 
+/*  81 */  {  1,   4 }, 
+/*  82 */  {  1,   5 }, 
+/*  83 */  {  1,   4 }, 
+/*  84 */  {  1,   6 }, 
+/*  85 */  {  4,   0, 2, 4, 6 }, 
+/*  86 */  {  1,   0 }, 
+/*  87 */  {  1,   0 }, 
+/*  88 */  {  1,   7 }, 
+/*  89 */  {  1,   2 }, 
+/*  90 */  {  4,   0, 2, 5, 7 }, 
+/*  91 */  {  1,   0 }, 
+/*  92 */  {  1,   6 }, 
+/*  93 */  {  1,   2 }, 
+/*  94 */  {  1,   2 }, 
+/*  95 */  {  2,   0, 2 }, 
+/*  96 */  {  2,   4, 7 }, 
+/*  97 */  {  1,   4 }, 
+/*  98 */  {  1,   5 }, 
+/*  99 */  {  1,   4 }, 
+/* 100 */  {  1,   6 }, 
+/* 101 */  {  1,   4 }, 
+/* 102 */  {  4,   0, 3, 4, 7 }, 
+/* 103 */  {  1,   0 }, 
+/* 104 */  {  1,   7 }, 
+/* 105 */  {  4,   0, 3, 5, 6 }, 
+/* 106 */  {  1,   7 }, 
+/* 107 */  {  1,   0 }, 
+/* 108 */  {  1,   7 }, 
+/* 109 */  {  1,   3 }, 
+/* 110 */  {  1,   3 }, 
+/* 111 */  {  2,   0, 3 }, 
+/* 112 */  {  1,   4 }, 
+/* 113 */  {  1,   4 }, 
+/* 114 */  {  1,   5 }, 
+/* 115 */  {  1,   4 }, 
+/* 116 */  {  1,   6 }, 
+/* 117 */  {  1,   4 }, 
+/* 118 */  {  1,   4 }, 
+/* 119 */  {  2,   0, 4 }, 
+/* 120 */  {  1,   7 }, 
+/* 121 */  {  1,   5 }, 
+/* 122 */  {  1,   5 }, 
+/* 123 */  {  2,   0, 5 }, 
+/* 124 */  {  1,   6 }, 
+/* 125 */  {  2,   0, 6 }, 
+/* 126 */  {  2,   0, 7 }, 
+/* 127 */  {  1,   0 }, 
+/* 128 */  {  1,   7 }, 
+/* 129 */  {  2,   3, 4 }, 
+/* 130 */  {  2,   3, 5 }, 
+/* 131 */  {  1,   3 }, 
+/* 132 */  {  2,   3, 6 }, 
+/* 133 */  {  1,   3 }, 
+/* 134 */  {  1,   3 }, 
+/* 135 */  {  1,   3 }, 
+/* 136 */  {  2,   3, 7 }, 
+/* 137 */  {  1,   3 }, 
+/* 138 */  {  1,   3 }, 
+/* 139 */  {  1,   3 }, 
+/* 140 */  {  1,   3 }, 
+/* 141 */  {  1,   3 }, 
+/* 142 */  {  1,   3 }, 
+/* 143 */  {  1,   3 }, 
+/* 144 */  {  2,   5, 6 }, 
+/* 145 */  {  1,   4 }, 
+/* 146 */  {  1,   5 }, 
+/* 147 */  {  1,   5 }, 
+/* 148 */  {  1,   6 }, 
+/* 149 */  {  1,   6 }, 
+/* 150 */  {  4,   1, 2, 4, 7 }, 
+/* 151 */  {  1,   1 }, 
+/* 152 */  {  1,   7 }, 
+/* 153 */  {  4,   1, 2, 5, 6 }, 
+/* 154 */  {  1,   5 }, 
+/* 155 */  {  1,   1 }, 
+/* 156 */  {  1,   6 }, 
+/* 157 */  {  1,   2 }, 
+/* 158 */  {  1,   2 }, 
+/* 159 */  {  2,   1, 2 }, 
+/* 160 */  {  2,   5, 7 }, 
+/* 161 */  {  1,   4 }, 
+/* 162 */  {  1,   5 }, 
+/* 163 */  {  1,   5 }, 
+/* 164 */  {  1,   6 }, 
+/* 165 */  {  4,   1, 3, 4, 6 }, 
+/* 166 */  {  1,   3 }, 
+/* 167 */  {  1,   1 }, 
+/* 168 */  {  1,   7 }, 
+/* 169 */  {  1,   1 }, 
+/* 170 */  {  4,   1, 3, 5, 7 }, 
+/* 171 */  {  1,   1 }, 
+/* 172 */  {  1,   7 }, 
+/* 173 */  {  1,   3 }, 
+/* 174 */  {  1,   3 }, 
+/* 175 */  {  2,   1, 3 }, 
+/* 176 */  {  1,   5 }, 
+/* 177 */  {  1,   4 }, 
+/* 178 */  {  1,   5 }, 
+/* 179 */  {  1,   5 }, 
+/* 180 */  {  1,   6 }, 
+/* 181 */  {  1,   4 }, 
+/* 182 */  {  1,   4 }, 
+/* 183 */  {  2,   1, 4 }, 
+/* 184 */  {  1,   7 }, 
+/* 185 */  {  1,   5 }, 
+/* 186 */  {  1,   5 }, 
+/* 187 */  {  2,   1, 5 }, 
+/* 188 */  {  1,   7 }, 
+/* 189 */  {  2,   1, 6 }, 
+/* 190 */  {  2,   1, 7 }, 
+/* 191 */  {  1,   1 }, 
+/* 192 */  {  2,   6, 7 }, 
+/* 193 */  {  1,   4 }, 
+/* 194 */  {  1,   5 }, 
+/* 195 */  {  4,   2, 3, 4, 5 }, 
+/* 196 */  {  1,   6 }, 
+/* 197 */  {  1,   2 }, 
+/* 198 */  {  1,   3 }, 
+/* 199 */  {  1,   2 }, 
+/* 200 */  {  1,   7 }, 
+/* 201 */  {  1,   2 }, 
+/* 202 */  {  1,   3 }, 
+/* 203 */  {  1,   3 }, 
+/* 204 */  {  4,   2, 3, 6, 7 }, 
+/* 205 */  {  1,   2 }, 
+/* 206 */  {  1,   3 }, 
+/* 207 */  {  2,   2, 3 }, 
+/* 208 */  {  1,   6 }, 
+/* 209 */  {  1,   4 }, 
+/* 210 */  {  1,   5 }, 
+/* 211 */  {  1,   4 }, 
+/* 212 */  {  1,   6 }, 
+/* 213 */  {  1,   6 }, 
+/* 214 */  {  1,   7 }, 
+/* 215 */  {  2,   2, 4 }, 
+/* 216 */  {  1,   7 }, 
+/* 217 */  {  1,   6 }, 
+/* 218 */  {  1,   7 }, 
+/* 219 */  {  2,   2, 5 }, 
+/* 220 */  {  1,   6 }, 
+/* 221 */  {  2,   2, 6 }, 
+/* 222 */  {  2,   2, 7 }, 
+/* 223 */  {  1,   2 }, 
+/* 224 */  {  1,   7 }, 
+/* 225 */  {  1,   4 }, 
+/* 226 */  {  1,   5 }, 
+/* 227 */  {  1,   5 }, 
+/* 228 */  {  1,   6 }, 
+/* 229 */  {  1,   6 }, 
+/* 230 */  {  1,   7 }, 
+/* 231 */  {  2,   3, 4 }, 
+/* 232 */  {  1,   7 }, 
+/* 233 */  {  1,   6 }, 
+/* 234 */  {  1,   7 }, 
+/* 235 */  {  2,   3, 5 }, 
+/* 236 */  {  1,   7 }, 
+/* 237 */  {  2,   3, 6 }, 
+/* 238 */  {  2,   3, 7 }, 
+/* 239 */  {  1,   3 }, 
+/* 240 */  {  4,   4, 5, 6, 7 }, 
+/* 241 */  {  1,   4 }, 
+/* 242 */  {  1,   5 }, 
+/* 243 */  {  2,   4, 5 }, 
+/* 244 */  {  1,   6 }, 
+/* 245 */  {  2,   4, 6 }, 
+/* 246 */  {  2,   4, 7 }, 
+/* 247 */  {  1,   4 }, 
+/* 248 */  {  1,   7 }, 
+/* 249 */  {  2,   5, 6 }, 
+/* 250 */  {  2,   5, 7 }, 
+/* 251 */  {  1,   5 }, 
+/* 252 */  {  2,   6, 7 }, 
+/* 253 */  {  1,   6 }, 
+/* 254 */  {  1,   7 }, 
+/* 255 */  {  8,   0, 1, 2, 3, 4, 5, 6, 7 }
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int Extra_TruthCanonN_rec( int nVars, unsigned char * pt, unsigned ** pptRes, char ** ppfRes, int Flag );
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the N-canonical form of the Boolean function up to 6 inputs.]
+
+  Description [The N-canonical form is defined as the truth table with 
+  the minimum integer value. This function exhaustively enumerates 
+  through the complete set of 2^N phase assignments.
+  Returns pointers to the static storage to the truth table and phases. 
+  This data should be used before the function is called again.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Extra_TruthCanonFastN( int nVarsMax, int nVarsReal, unsigned * pt, unsigned ** pptRes, char ** ppfRes )
+{
+    static unsigned uTruthStore6[2];
+    int RetValue;
+    assert( nVarsMax <= 6 );
+    assert( nVarsReal <= nVarsMax );
+    RetValue = Extra_TruthCanonN_rec( nVarsReal <= 3? 3: nVarsReal, (unsigned char *)pt, pptRes, ppfRes, 0 );
+    if ( nVarsMax == 6 && nVarsReal < nVarsMax )
+    {
+        uTruthStore6[0] = **pptRes;
+        uTruthStore6[1] = **pptRes;
+        *pptRes = uTruthStore6;
+    }
+    return RetValue;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+  Synopsis    [Recursive implementation of the above.]
+
+  Description []
+               
+  SideEffects [This procedure has a bug, which shows on Solaris.
+  Most likely has something to do with the casts, i.g *((unsigned *)pt0)]
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_TruthCanonN_rec( int nVars, unsigned char * pt, unsigned ** pptRes, char ** ppfRes, int Flag )
+{
+    static unsigned uTruthStore[7][2][2];
+    static char uPhaseStore[7][2][64];
+
+    unsigned char * pt0, * pt1;
+    unsigned * ptRes0, * ptRes1, * ptRes;
+    unsigned uInit0, uInit1, uTruth0, uTruth1, uTemp;
+    char * pfRes0, * pfRes1, * pfRes;
+    int nf0, nf1, nfRes, i, nVarsN;
+
+    // table lookup for three vars
+    if ( nVars == 3 )
+    {
+        *pptRes = &s_Truths3[*pt];
+        *ppfRes = s_Phases3[*pt]+1;
+        return s_Phases3[*pt][0];
+    }
+
+    // number of vars for the next call
+    nVarsN = nVars-1;
+    // truth table for the next call
+    pt0 = pt;
+    pt1 = pt + (1 << nVarsN) / 8;
+    // 5-var truth tables for this call
+//    uInit0 = *((unsigned *)pt0);
+//    uInit1 = *((unsigned *)pt1);
+    if ( nVarsN == 3 )
+    {
+        uInit0 = (pt0[0] << 24) | (pt0[0] << 16) | (pt0[0] << 8) | pt0[0];
+        uInit1 = (pt1[0] << 24) | (pt1[0] << 16) | (pt1[0] << 8) | pt1[0];
+    }
+    else if ( nVarsN == 4 )
+    {
+        uInit0 = (pt0[1] << 24) | (pt0[0] << 16) | (pt0[1] << 8) | pt0[0];
+        uInit1 = (pt1[1] << 24) | (pt1[0] << 16) | (pt1[1] << 8) | pt1[0];
+    }
+    else
+    {
+        uInit0 = (pt0[3] << 24) | (pt0[2] << 16) | (pt0[1] << 8) | pt0[0];
+        uInit1 = (pt1[3] << 24) | (pt1[2] << 16) | (pt1[1] << 8) | pt1[0];
+    }
+
+    // storage for truth tables and phases
+    ptRes  = uTruthStore[nVars][Flag];
+    pfRes  = uPhaseStore[nVars][Flag];
+
+    // solve trivial cases
+    if ( uInit1 == 0 )
+    {
+        nf0 = Extra_TruthCanonN_rec( nVarsN, pt0, &ptRes0, &pfRes0, 0 );
+        uTruth1 = uInit1;
+        uTruth0 = *ptRes0;
+        nfRes   = 0;
+        for ( i = 0; i < nf0; i++ )
+            pfRes[nfRes++] = pfRes0[i];
+        goto finish;
+    }
+    if ( uInit0 == 0 )
+    {
+        nf1 = Extra_TruthCanonN_rec( nVarsN, pt1, &ptRes1, &pfRes1, 1 );
+        uTruth1 = uInit0;
+        uTruth0 = *ptRes1;
+        nfRes   = 0;
+        for ( i = 0; i < nf1; i++ )
+            pfRes[nfRes++] = pfRes1[i] | (1<<nVarsN);
+        goto finish;
+    }
+
+    if ( uInit1 == 0xFFFFFFFF )
+    {
+        nf0 = Extra_TruthCanonN_rec( nVarsN, pt0, &ptRes0, &pfRes0, 0 );
+        uTruth1 = *ptRes0;
+        uTruth0 = uInit1;
+        nfRes   = 0;
+        for ( i = 0; i < nf0; i++ )
+            pfRes[nfRes++] = pfRes0[i] | (1<<nVarsN);
+        goto finish;
+    }
+    if ( uInit0 == 0xFFFFFFFF )
+    {
+        nf1 = Extra_TruthCanonN_rec( nVarsN, pt1, &ptRes1, &pfRes1, 1 );
+        uTruth1 = *ptRes1;
+        uTruth0 = uInit0;
+        nfRes   = 0;
+        for ( i = 0; i < nf1; i++ )
+            pfRes[nfRes++] = pfRes1[i];
+        goto finish;
+    }
+
+    // solve the problem for cofactors
+    nf0 = Extra_TruthCanonN_rec( nVarsN, pt0, &ptRes0, &pfRes0, 0 );
+    nf1 = Extra_TruthCanonN_rec( nVarsN, pt1, &ptRes1, &pfRes1, 1 );
+
+    // combine the result
+    if ( *ptRes1 < *ptRes0 )
+    {
+        uTruth0 = 0xFFFFFFFF;
+        nfRes   = 0;
+        for ( i = 0; i < nf1; i++ )
+        {
+            uTemp = Extra_TruthPolarize( uInit0, pfRes1[i], nVarsN );
+            if ( uTruth0 > uTemp )
+            {
+                nfRes          = 0;
+                uTruth0        = uTemp;
+                pfRes[nfRes++] = pfRes1[i];
+            }
+            else if ( uTruth0 == uTemp ) 
+                pfRes[nfRes++] = pfRes1[i];
+        }
+        uTruth1 = *ptRes1;
+    }
+    else if ( *ptRes1 > *ptRes0 )
+    {
+        uTruth0 = 0xFFFFFFFF;
+        nfRes   = 0;
+        for ( i = 0; i < nf0; i++ )
+        {
+            uTemp = Extra_TruthPolarize( uInit1, pfRes0[i], nVarsN );
+            if ( uTruth0 > uTemp )
+            {
+                nfRes          = 0;
+                uTruth0        = uTemp;
+                pfRes[nfRes++] = pfRes0[i] | (1<<nVarsN);
+            }
+            else if ( uTruth0 == uTemp ) 
+                pfRes[nfRes++] = pfRes0[i] | (1<<nVarsN);
+        }
+        uTruth1 = *ptRes0;
+    }
+    else 
+    {
+        assert( nf0 == nf1 );
+        nfRes = 0; 
+        for ( i = 0; i < nf1; i++ )
+            pfRes[nfRes++] = pfRes1[i];
+        for ( i = 0; i < nf0; i++ )
+            pfRes[nfRes++] = pfRes0[i] | (1<<nVarsN);
+        uTruth0 = Extra_TruthPolarize( uInit0, pfRes1[0], nVarsN );
+        uTruth1 = *ptRes0;
+    }
+
+finish :
+    if ( nVarsN == 3 )
+    {
+        uTruth0 &= 0xFF;
+        uTruth1 &= 0xFF;
+        uTemp = (uTruth1 << 8) | uTruth0;
+        *ptRes = (uTemp << 16) | uTemp;
+    }
+    else if ( nVarsN == 4 )
+    {
+        uTruth0 &= 0xFFFF;
+        uTruth1 &= 0xFFFF;
+        *ptRes = (uTruth1 << 16) | uTruth0;
+    }
+    else if ( nVarsN == 5 )
+    {
+        *(ptRes+0) = uTruth0;
+        *(ptRes+1) = uTruth1;
+    }
+
+    *pptRes = ptRes;
+    *ppfRes = pfRes;
+    return nfRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_Var3Print()
+{
+    extern void Extra_Truth3VarN( unsigned ** puCanons, char *** puPhases, char ** ppCounters );
+
+    unsigned * uCanons;
+    char ** uPhases;
+    char * pCounters;
+    int i, k;
+
+    Extra_Truth3VarN( &uCanons, &uPhases, &pCounters );
+
+    for ( i = 0; i < 256; i++ )
+    {
+        if ( i % 8 == 0 )
+            printf( "\n" );
+        Extra_PrintHex( stdout, uCanons + i, 5 ); 
+        printf( ", " );
+    }
+    printf( "\n" );
+
+    for ( i = 0; i < 256; i++ )
+    {
+        printf( "%3d */  { %2d,   ", i, pCounters[i] );
+        for ( k = 0; k < pCounters[i]; k++ )            
+            printf( "%s%d", k? ", ":"", uPhases[i][k] );
+        printf( " }\n" );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_Var3Test()
+{
+    extern void Extra_Truth3VarN( unsigned ** puCanons, char *** puPhases, char ** ppCounters );
+
+    unsigned * uCanons;
+    char ** uPhases;
+    char * pCounters;
+    int i;
+    unsigned * ptRes;
+    char * pfRes;
+    unsigned uTruth;
+    int Count;
+
+    Extra_Truth3VarN( &uCanons, &uPhases, &pCounters );
+
+    for ( i = 0; i < 256; i++ )
+    {
+        uTruth = i;
+        Count =  Extra_TruthCanonFastN( 5, 3, &uTruth, &ptRes, &pfRes );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Map_Var4Test()
+{
+    extern void Extra_Truth4VarN( unsigned short ** puCanons, char *** puPhases, char ** ppCounters, int PhaseMax );
+
+    unsigned short * uCanons;
+    char ** uPhases;
+    char * pCounters;
+    int i;
+    unsigned * ptRes;
+    char * pfRes;
+    unsigned uTruth;
+    int Count;
+
+    Extra_Truth4VarN( &uCanons, &uPhases, &pCounters, 16 );
+
+    for ( i = 0; i < 256*256; i++ )
+    {
+        uTruth = i;
+        Count =  Extra_TruthCanonFastN( 5, 4, &uTruth, &ptRes, &pfRes );
+    }
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static Functions                                            */
+/*---------------------------------------------------------------------------*/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraUtilCube.c b/abc-build/src/misc/extra/extraUtilCube.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraUtilCube.c
@@ -0,0 +1,279 @@
+/**CFile****************************************************************
+
+  FileName    [extraUtilCube.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [extra]
+
+  Synopsis    [Permutation computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: extraUtilCube.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "misc/vec/vec.h"
+#include "misc/vec/vecHsh.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline void Abc_StatePush( Vec_Int_t * vData, char * pState, int k )  { int i; for ( i = 0; i < 6; i++ ) Vec_IntWriteEntry(vData, 6*k+i, ((int*)pState)[i]);  }
+static inline void Abc_StatePerm( char * pState, char * pPerm, char * pRes ) { int i; for ( i = 0; i < 24; i++ ) pRes[i] = pState[(int)pPerm[i]];                    }
+static inline void Abc_StatePrint( char * pState )                           { int i; for ( i = 0; i < 24; i++ ) printf(" %2d", pState[i]); printf( "\n" );          }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_EnumerateCubeStates2()
+{
+    int pXYZ[3][9][2] = {
+        { {3, 5}, {3,17}, {3,15}, {1, 6}, {1,16}, {1,14}, {2, 4}, {2,18}, {2,13} },
+        { {2,14}, {2,24}, {2,12}, {3,13}, {3,23}, {3,10}, {1,15}, {1,22}, {1,11} },
+        { {1,10}, {1, 7}, {1, 4}, {3,12}, {3, 9}, {3, 6}, {2,11}, {2, 8}, {2, 5} }  };
+
+    Vec_Int_t * vData = Vec_IntStart( 6 * (1 << 22) );            // 96 MB
+    Hsh_IntMan_t * vHash = Hsh_IntManStart( vData, 6, 1 << 22 );  // 32 MB
+    int i, k, v, RetValue, Beg, End, Counter = 0;
+    char pStart[24], pFirst[9][24];
+    abctime clk = Abc_Clock();
+    printf( "Enumerating states of 2x2x2 cube.\n" );
+    // init state
+    for ( v = 0; v < 24; v++ )
+        pStart[v] = v;
+    Abc_StatePush( vData, pStart, Counter );
+    RetValue = Hsh_IntManAdd( vHash, Counter );
+    assert( RetValue == Counter );
+    Counter++;
+    // first nine states
+    for ( i = 0; i < 3; i++ )
+    {
+        memcpy( pFirst[i], pStart, 24 );
+        for ( v = 0; v < 9; v++ )
+            ABC_SWAP( char, pFirst[i][pXYZ[i][v][0]-1], pFirst[i][pXYZ[i][v][1]-1] );
+        Abc_StatePush( vData, pFirst[i], Counter );
+        RetValue = Hsh_IntManAdd( vHash, Counter );
+        assert( RetValue == Counter );
+        Counter++;
+        //Abc_StatePrint( pFirst[i] );
+
+        memcpy( pFirst[3+i], pFirst[i], 24 );
+        for ( v = 0; v < 9; v++ )
+            ABC_SWAP( char, pFirst[3+i][pXYZ[i][v][0]-1], pFirst[3+i][pXYZ[i][v][1]-1] );
+        Abc_StatePush( vData, pFirst[3+i], Counter );
+        RetValue = Hsh_IntManAdd( vHash, Counter );
+        assert( RetValue == Counter );
+        Counter++;
+        //Abc_StatePrint( pFirst[3+i] );
+
+        memcpy( pFirst[6+i], pFirst[3+i], 24 );
+        for ( v = 0; v < 9; v++ )
+            ABC_SWAP( char, pFirst[6+i][pXYZ[i][v][0]-1], pFirst[6+i][pXYZ[i][v][1]-1] );
+        Abc_StatePush( vData, pFirst[6+i], Counter );
+        RetValue = Hsh_IntManAdd( vHash, Counter );
+        assert( RetValue == Counter );
+        Counter++;
+        //Abc_StatePrint( pFirst[6+i] );
+    }
+    printf( "Iter %2d -> %8d   ", 0, 1 );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    printf( "Iter %2d -> %8d   ", 1, Counter );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    Beg = 1;  End = 10;
+    for ( i = 2; i <= 100; i++ )
+    {
+        if ( Beg == End )
+            break;
+        for ( k = Beg; k < End; k++ )
+            for ( v = 0; v < 9; v++ )
+            {
+                Abc_StatePerm( (char *)Vec_IntEntryP(vData, 6*k), pFirst[v], (char *)Vec_IntEntryP(vData, 6*Counter) );
+                RetValue = Hsh_IntManAdd( vHash, Counter );
+                if ( RetValue == Counter )
+                    Counter++;
+                if ( Counter == (1<<22) )
+                {
+                    printf( "Did not converge.  " );
+                    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+                    return;
+                }
+            }
+        Beg = End;  End = Counter;
+        printf( "Iter %2d -> %8d   ", i, Counter );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    Hsh_IntManStop( vHash );
+    Vec_IntFree( vData );
+}
+
+/*
+Enumerating states of 2x2x2 cube.
+Iter  0 ->        1   Time =     0.00 sec
+Iter  1 ->       10   Time =     0.00 sec
+Iter  2 ->       64   Time =     0.00 sec
+Iter  3 ->      385   Time =     0.00 sec
+Iter  4 ->     2232   Time =     0.00 sec
+Iter  5 ->    12224   Time =     0.00 sec
+Iter  6 ->    62360   Time =     0.02 sec
+Iter  7 ->   289896   Time =     0.09 sec
+Iter  8 ->  1159968   Time =     0.90 sec
+Iter  9 ->  3047716   Time =    11.62 sec
+Iter 10 ->  3671516   Time =    52.00 sec
+Iter 11 ->  3674160   Time =    70.38 sec
+Iter 12 ->  3674160   Time =    70.48 sec 
+*/
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int  Abc_DataHasBit( word * p, word i )  { return (p[(i)>>6] & (1<<((i) & 63))) > 0; }
+static inline void Abc_DataXorBit( word * p, word i )  { p[(i)>>6] ^= (1<<((i) & 63));             }
+static inline int  Abc_DataGetCube( word w, int i )         { return (w >> (5*i)) & 31;            }
+static inline word Abc_DataXorCube( word w, int i, int c )  { return w ^ (((word)c) << (5*i));     }
+static inline word Abc_CubeGenerateSign( char * pState )
+{
+    static int Var2Cor[24] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, -1, -1, -1, 6, 6, 6 };
+    static int Var2Per[24] = { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, -1, -1, -1, 0, 1, 2 };
+    word Res = 0; 
+    Res = Abc_DataXorCube( Res, 0, (Var2Cor[(int)pState[ 0]] << 2) | Var2Per[(int)pState[ 0]] );
+    Res = Abc_DataXorCube( Res, 1, (Var2Cor[(int)pState[ 3]] << 2) | Var2Per[(int)pState[ 3]] );
+    Res = Abc_DataXorCube( Res, 2, (Var2Cor[(int)pState[ 6]] << 2) | Var2Per[(int)pState[ 6]] );
+    Res = Abc_DataXorCube( Res, 3, (Var2Cor[(int)pState[ 9]] << 2) | Var2Per[(int)pState[ 9]] );
+    Res = Abc_DataXorCube( Res, 4, (Var2Cor[(int)pState[12]] << 2) | Var2Per[(int)pState[12]] );
+    Res = Abc_DataXorCube( Res, 5, (Var2Cor[(int)pState[15]] << 2) | Var2Per[(int)pState[15]] );
+    Res = Abc_DataXorCube( Res, 6, (Var2Cor[(int)pState[21]] << 2) | Var2Per[(int)pState[21]] );
+    return Res;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_EnumerateCubeStates()
+{
+    int pXYZ[3][9][2] = {
+        { {3, 5}, {3,17}, {3,15}, {1, 6}, {1,16}, {1,14}, {2, 4}, {2,18}, {2,13} },
+        { {2,14}, {2,24}, {2,12}, {3,13}, {3,23}, {3,10}, {1,15}, {1,22}, {1,11} },
+        { {1,10}, {1, 7}, {1, 4}, {3,12}, {3, 9}, {3, 6}, {2,11}, {2, 8}, {2, 5} }  };
+
+    Vec_Int_t * vData = Vec_IntStart( 6 * (1 << 22) );  // 96 MB
+    word State, * pHash = ABC_CALLOC( word, 1 << 29 );  //  4 GB
+    int i, k, v, Beg, End, Counter = 0;
+    char * pPrev, * pState, pStart[24], pFirst[9][24];
+    abctime clk = Abc_Clock();
+    printf( "Enumerating states of 2x2x2 cube.\n" );
+    // init state
+    for ( v = 0; v < 24; v++ )
+        pStart[v] = v;
+    Abc_StatePush( vData, pStart, Counter );
+    Abc_DataXorBit( pHash, Abc_CubeGenerateSign(pStart) );
+    Counter++;
+    // first nine states
+    for ( i = 0; i < 3; i++ )
+    {
+        memcpy( pFirst[i], pStart, 24 );
+        for ( v = 0; v < 9; v++ )
+            ABC_SWAP( char, pFirst[i][pXYZ[i][v][0]-1], pFirst[i][pXYZ[i][v][1]-1] );
+        Abc_StatePush( vData, pFirst[i], Counter );
+        Abc_DataXorBit( pHash, Abc_CubeGenerateSign(pFirst[i]) );
+        Counter++;
+        //Abc_StatePrint( pFirst[i] );
+
+        memcpy( pFirst[3+i], pFirst[i], 24 );
+        for ( v = 0; v < 9; v++ )
+            ABC_SWAP( char, pFirst[3+i][pXYZ[i][v][0]-1], pFirst[3+i][pXYZ[i][v][1]-1] );
+        Abc_StatePush( vData, pFirst[3+i], Counter );
+        Abc_DataXorBit( pHash, Abc_CubeGenerateSign(pFirst[3+i]) );
+        Counter++;
+        //Abc_StatePrint( pFirst[3+i] );
+
+        memcpy( pFirst[6+i], pFirst[3+i], 24 );
+        for ( v = 0; v < 9; v++ )
+            ABC_SWAP( char, pFirst[6+i][pXYZ[i][v][0]-1], pFirst[6+i][pXYZ[i][v][1]-1] );
+        Abc_StatePush( vData, pFirst[6+i], Counter );
+        Abc_DataXorBit( pHash, Abc_CubeGenerateSign(pFirst[6+i]) );
+        Counter++;
+        //Abc_StatePrint( pFirst[6+i] );
+    }
+    printf( "Iter %2d -> %8d   ", 0, 1 );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    printf( "Iter %2d -> %8d   ", 1, Counter );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    Beg = 1;  End = 10;
+    for ( i = 2; i <= 100; i++ )
+    {
+        if ( Beg == End )
+            break;
+        for ( k = Beg; k < End; k++ )
+        {
+            pPrev = (char *)Vec_IntEntryP(vData, 6*k);
+            for ( v = 0; v < 9; v++ )
+            {
+                pState = (char *)Vec_IntEntryP(vData, 6*Counter);
+                Abc_StatePerm( pPrev, pFirst[v], pState );
+                State = Abc_CubeGenerateSign( pState );
+                if ( !Abc_DataHasBit(pHash, State) )
+                    Abc_DataXorBit(pHash, State), Counter++;
+                if ( Counter == (1<<22) )
+                {
+                    printf( "Did not converge.  " );
+                    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+                    return;
+                }
+            }
+        }
+        Beg = End;  End = Counter;
+        printf( "Iter %2d -> %8d   ", i, Counter );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    Vec_IntFree( vData );
+    ABC_FREE( pHash );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraUtilDsd.c b/abc-build/src/misc/extra/extraUtilDsd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraUtilDsd.c
@@ -0,0 +1,1271 @@
+/**CFile****************************************************************
+
+  FileName    [extraUtilDsd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [extra]
+
+  Synopsis    [File management utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: extraUtilDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "extra.h"
+#include "misc/vec/vec.h"
+#include "misc/vec/vecHsh.h"
+#include "misc/util/utilTruth.h"
+#include "bool/rsb/rsb.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Sdm_Dsd_t_ Sdm_Dsd_t;
+struct Sdm_Dsd_t_
+{
+    int              nVars;                    // support size
+    int              nAnds;                    // the number of AND gates
+    int              nClauses;                 // the number of CNF clauses
+    word             uTruth;                   // truth table
+    char *           pStr;                     // description 
+};
+
+#define DSD_CLASS_NUM 595
+
+static Sdm_Dsd_t s_DsdClass6[DSD_CLASS_NUM] = { 
+    { 0,  0,  1, ABC_CONST(0x0000000000000000), "0" },   //    0
+    { 1,  0,  2, ABC_CONST(0xAAAAAAAAAAAAAAAA), "a" },   //    1
+    { 2,  1,  3, ABC_CONST(0x8888888888888888), "(ab)" },   //    2
+    { 2,  3,  4, ABC_CONST(0x6666666666666666), "[ab]" },   //    3
+    { 3,  2,  4, ABC_CONST(0x8080808080808080), "(abc)" },   //    4
+    { 3,  2,  4, ABC_CONST(0x7070707070707070), "(!(ab)c)" },   //    5
+    { 3,  4,  6, ABC_CONST(0x7878787878787878), "[(ab)c]" },   //    6
+    { 3,  4,  5, ABC_CONST(0x6060606060606060), "([ab]c)" },   //    7
+    { 3,  6,  8, ABC_CONST(0x9696969696969696), "[abc]" },   //    8
+    { 3,  3,  4, ABC_CONST(0xCACACACACACACACA), "<abc>" },   //    9
+    { 4,  3,  5, ABC_CONST(0x8000800080008000), "(abcd)" },   //   10
+    { 4,  3,  5, ABC_CONST(0x7F007F007F007F00), "(!(abc)d)" },   //   11
+    { 4,  5,  8, ABC_CONST(0x7F807F807F807F80), "[(abc)d]" },   //   12
+    { 4,  3,  5, ABC_CONST(0x7000700070007000), "(!(ab)cd)" },   //   13
+    { 4,  3,  5, ABC_CONST(0x8F008F008F008F00), "(!(!(ab)c)d)" },   //   14
+    { 4,  5,  8, ABC_CONST(0x8F708F708F708F70), "[(!(ab)c)d]" },   //   15
+    { 4,  5,  7, ABC_CONST(0x7800780078007800), "([(ab)c]d)" },   //   16
+    { 4,  7, 12, ABC_CONST(0x8778877887788778), "[(ab)cd]" },   //   17
+    { 4,  5,  6, ABC_CONST(0x6000600060006000), "([ab]cd)" },   //   18
+    { 4,  5,  6, ABC_CONST(0x9F009F009F009F00), "(!([ab]c)d)" },   //   19
+    { 4,  7, 10, ABC_CONST(0x9F609F609F609F60), "[([ab]c)d]" },   //   20
+    { 4,  7,  9, ABC_CONST(0x9600960096009600), "([abc]d)" },   //   21
+    { 4,  9, 16, ABC_CONST(0x6996699669966996), "[abcd]" },   //   22
+    { 4,  4,  5, ABC_CONST(0xCA00CA00CA00CA00), "(<abc>d)" },   //   23
+    { 4,  6,  8, ABC_CONST(0x35CA35CA35CA35CA), "[<abc>d]" },   //   24
+    { 4,  3,  6, ABC_CONST(0x0777077707770777), "(!(ab)!(cd))" },   //   25
+    { 4,  5,  9, ABC_CONST(0x7888788878887888), "[(ab)(cd)]" },   //   26
+    { 4,  5,  7, ABC_CONST(0x0666066606660666), "([ab]!(cd))" },   //   27
+    { 4,  7,  8, ABC_CONST(0x0660066006600660), "([ab][cd])" },   //   28
+    { 4,  4,  6, ABC_CONST(0xCAAACAAACAAACAAA), "<ab(cd)>" },   //   29
+    { 4,  6,  8, ABC_CONST(0xACCAACCAACCAACCA), "<ab[cd]>" },   //   30
+    { 4,  4,  5, ABC_CONST(0xF088F088F088F088), "<(ab)cd>" },   //   31
+    { 4,  6,  6, ABC_CONST(0xF066F066F066F066), "<[ab]cd>" },   //   32
+    { 5,  4,  6, ABC_CONST(0x8000000080000000), "(abcde)" },   //   33
+    { 5,  4,  6, ABC_CONST(0x7FFF00007FFF0000), "(!(abcd)e)" },   //   34
+    { 5,  6, 10, ABC_CONST(0x7FFF80007FFF8000), "[(abcd)e]" },   //   35
+    { 5,  4,  6, ABC_CONST(0x7F0000007F000000), "(!(abc)de)" },   //   36
+    { 5,  4,  6, ABC_CONST(0x80FF000080FF0000), "(!(!(abc)d)e)" },   //   37
+    { 5,  6, 10, ABC_CONST(0x80FF7F0080FF7F00), "[(!(abc)d)e]" },   //   38
+    { 5,  6,  9, ABC_CONST(0x7F8000007F800000), "([(abc)d]e)" },   //   39
+    { 5,  8, 16, ABC_CONST(0x807F7F80807F7F80), "[(abc)de]" },   //   40
+    { 5,  4,  6, ABC_CONST(0x7000000070000000), "(!(ab)cde)" },   //   41
+    { 5,  4,  6, ABC_CONST(0x8FFF00008FFF0000), "(!(!(ab)cd)e)" },   //   42
+    { 5,  6, 10, ABC_CONST(0x8FFF70008FFF7000), "[(!(ab)cd)e]" },   //   43
+    { 5,  4,  6, ABC_CONST(0x8F0000008F000000), "(!(!(ab)c)de)" },   //   44
+    { 5,  4,  6, ABC_CONST(0x70FF000070FF0000), "(!(!(!(ab)c)d)e)" },   //   45
+    { 5,  6, 10, ABC_CONST(0x70FF8F0070FF8F00), "[(!(!(ab)c)d)e]" },   //   46
+    { 5,  6,  9, ABC_CONST(0x8F7000008F700000), "([(!(ab)c)d]e)" },   //   47
+    { 5,  8, 16, ABC_CONST(0x708F8F70708F8F70), "[(!(ab)c)de]" },   //   48
+    { 5,  6,  8, ABC_CONST(0x7800000078000000), "([(ab)c]de)" },   //   49
+    { 5,  6,  8, ABC_CONST(0x87FF000087FF0000), "(!([(ab)c]d)e)" },   //   50
+    { 5,  8, 14, ABC_CONST(0x87FF780087FF7800), "[([(ab)c]d)e]" },   //   51
+    { 5,  8, 13, ABC_CONST(0x8778000087780000), "([(ab)cd]e)" },   //   52
+    { 5, 10, 24, ABC_CONST(0x7887877878878778), "[(ab)cde]" },   //   53
+    { 5,  6,  7, ABC_CONST(0x6000000060000000), "([ab]cde)" },   //   54
+    { 5,  6,  7, ABC_CONST(0x9FFF00009FFF0000), "(!([ab]cd)e)" },   //   55
+    { 5,  8, 12, ABC_CONST(0x9FFF60009FFF6000), "[([ab]cd)e]" },   //   56
+    { 5,  6,  7, ABC_CONST(0x9F0000009F000000), "(!([ab]c)de)" },   //   57
+    { 5,  6,  7, ABC_CONST(0x60FF000060FF0000), "(!(!([ab]c)d)e)" },   //   58
+    { 5,  8, 12, ABC_CONST(0x60FF9F0060FF9F00), "[(!([ab]c)d)e]" },   //   59
+    { 5,  8, 11, ABC_CONST(0x9F6000009F600000), "([([ab]c)d]e)" },   //   60
+    { 5, 10, 20, ABC_CONST(0x609F9F60609F9F60), "[([ab]c)de]" },   //   61
+    { 5,  8, 10, ABC_CONST(0x9600000096000000), "([abc]de)" },   //   62
+    { 5,  8, 10, ABC_CONST(0x69FF000069FF0000), "(!([abc]d)e)" },   //   63
+    { 5, 10, 18, ABC_CONST(0x69FF960069FF9600), "[([abc]d)e]" },   //   64
+    { 5, 10, 17, ABC_CONST(0x6996000069960000), "([abcd]e)" },   //   65
+    { 5, 12, 32, ABC_CONST(0x9669699696696996), "[abcde]" },   //   66
+    { 5,  5,  6, ABC_CONST(0xCA000000CA000000), "(<abc>de)" },   //   67
+    { 5,  5,  6, ABC_CONST(0x35FF000035FF0000), "(!(<abc>d)e)" },   //   68
+    { 5,  7, 10, ABC_CONST(0x35FFCA0035FFCA00), "[(<abc>d)e]" },   //   69
+    { 5,  7,  9, ABC_CONST(0x35CA000035CA0000), "([<abc>d]e)" },   //   70
+    { 5,  9, 16, ABC_CONST(0xCA3535CACA3535CA), "[<abc>de]" },   //   71
+    { 5,  4,  7, ABC_CONST(0x0777000007770000), "(!(ab)!(cd)e)" },   //   72
+    { 5,  4,  7, ABC_CONST(0xF8880000F8880000), "(!(!(ab)!(cd))e)" },   //   73
+    { 5,  6, 12, ABC_CONST(0xF8880777F8880777), "[(!(ab)!(cd))e]" },   //   74
+    { 5,  6, 10, ABC_CONST(0x7888000078880000), "([(ab)(cd)]e)" },   //   75
+    { 5,  6, 10, ABC_CONST(0x8777000087770000), "(![(ab)(cd)]e)" },   //   76
+    { 5,  8, 18, ABC_CONST(0x8777788887777888), "[(ab)(cd)e]" },   //   77
+    { 5,  6,  8, ABC_CONST(0x0666000006660000), "([ab]!(cd)e)" },   //   78
+    { 5,  6,  8, ABC_CONST(0xF9990000F9990000), "(!([ab]!(cd))e)" },   //   79
+    { 5,  8, 14, ABC_CONST(0xF9990666F9990666), "[([ab]!(cd))e]" },   //   80
+    { 5,  8,  9, ABC_CONST(0x0660000006600000), "([ab][cd]e)" },   //   81
+    { 5,  8,  9, ABC_CONST(0xF99F0000F99F0000), "(!([ab][cd])e)" },   //   82
+    { 5, 10, 16, ABC_CONST(0xF99F0660F99F0660), "[([ab][cd])e]" },   //   83
+    { 5,  5,  7, ABC_CONST(0xCAAA0000CAAA0000), "(<ab(cd)>e)" },   //   84
+    { 5,  7, 12, ABC_CONST(0x3555CAAA3555CAAA), "[<ab(cd)>e]" },   //   85
+    { 5,  7,  9, ABC_CONST(0xACCA0000ACCA0000), "(<ab[cd]>e)" },   //   86
+    { 5,  9, 16, ABC_CONST(0x5335ACCA5335ACCA), "[<ab[cd]>e]" },   //   87
+    { 5,  5,  6, ABC_CONST(0xF0880000F0880000), "(<(ab)cd>e)" },   //   88
+    { 5,  5,  6, ABC_CONST(0x0F7700000F770000), "(!<(ab)cd>e)" },   //   89
+    { 5,  7, 10, ABC_CONST(0x0F77F0880F77F088), "[<(ab)cd>e]" },   //   90
+    { 5,  7,  7, ABC_CONST(0xF0660000F0660000), "(<[ab]cd>e)" },   //   91
+    { 5,  9, 12, ABC_CONST(0x0F99F0660F99F066), "[<[ab]cd>e]" },   //   92
+    { 5,  4,  8, ABC_CONST(0x007F7F7F007F7F7F), "(!(abc)!(de))" },   //   93
+    { 5,  6, 12, ABC_CONST(0x7F8080807F808080), "[(abc)(de)]" },   //   94
+    { 5,  4,  7, ABC_CONST(0x008F8F8F008F8F8F), "(!(!(ab)c)!(de))" },   //   95
+    { 5,  6, 12, ABC_CONST(0x8F7070708F707070), "[(!(ab)c)(de)]" },   //   96
+    { 5,  6, 10, ABC_CONST(0x0078787800787878), "([(ab)c]!(de))" },   //   97
+    { 5,  6,  9, ABC_CONST(0x009F9F9F009F9F9F), "(!([ab]c)!(de))" },   //   98
+    { 5,  8, 15, ABC_CONST(0x9F6060609F606060), "[([ab]c)(de)]" },   //   99
+    { 5,  8, 13, ABC_CONST(0x0096969600969696), "([abc]!(de))" },   //  100
+    { 5,  5,  7, ABC_CONST(0x00CACACA00CACACA), "(<abc>!(de))" },   //  101
+    { 5,  7, 12, ABC_CONST(0x35CACACA35CACACA), "[<abc>(de)]" },   //  102
+    { 5,  6,  9, ABC_CONST(0x007F7F00007F7F00), "(!(abc)[de])" },   //  103
+    { 5,  6,  8, ABC_CONST(0x008F8F00008F8F00), "(!(!(ab)c)[de])" },   //  104
+    { 5,  8, 11, ABC_CONST(0x0078780000787800), "([(ab)c][de])" },   //  105
+    { 5,  8, 10, ABC_CONST(0x009F9F00009F9F00), "(!([ab]c)[de])" },   //  106
+    { 5, 10, 14, ABC_CONST(0x0096960000969600), "([abc][de])" },   //  107
+    { 5,  7,  8, ABC_CONST(0x00CACA0000CACA00), "(<abc>[de])" },   //  108
+    { 5,  5,  8, ABC_CONST(0xCAAAAAAACAAAAAAA), "<ab(cde)>" },   //  109
+    { 5,  5,  8, ABC_CONST(0xACCCAAAAACCCAAAA), "<ab(!(cd)e)>" },   //  110
+    { 5,  7, 12, ABC_CONST(0xACCCCAAAACCCCAAA), "<ab[(cd)e]>" },   //  111
+    { 5,  7, 10, ABC_CONST(0xACCAAAAAACCAAAAA), "<ab([cd]e)>" },   //  112
+    { 5,  9, 16, ABC_CONST(0xCAACACCACAACACCA), "<ab[cde]>" },   //  113
+    { 5,  6,  8, ABC_CONST(0xCCAACACACCAACACA), "<ab<cde>>" },   //  114
+    { 5,  5,  7, ABC_CONST(0xC0AAAAAAC0AAAAAA), "<a(bc)(de)>" },   //  115
+    { 5,  7,  8, ABC_CONST(0x3CAAAAAA3CAAAAAA), "<a[bc](de)>" },   //  116
+    { 5,  5,  8, ABC_CONST(0xF0888888F0888888), "<(ab)c(de)>" },   //  117
+    { 5,  7, 10, ABC_CONST(0x88F0F08888F0F088), "<(ab)c[de]>" },   //  118
+    { 5,  7, 10, ABC_CONST(0xF0666666F0666666), "<[ab]c(de)>" },   //  119
+    { 5,  9, 12, ABC_CONST(0x66F0F06666F0F066), "<[ab]c[de]>" },   //  120
+    { 5,  5,  6, ABC_CONST(0xF0008888F0008888), "<(ab)(cd)e>" },   //  121
+    { 5,  5,  6, ABC_CONST(0xF0007777F0007777), "<!(ab)(cd)e>" },   //  122
+    { 5,  7,  7, ABC_CONST(0xF0006666F0006666), "<[ab](cd)e>" },   //  123
+    { 5,  9,  8, ABC_CONST(0x0FF066660FF06666), "<[ab][cd]e>" },   //  124
+    { 5,  5,  6, ABC_CONST(0xFF008080FF008080), "<(abc)de>" },   //  125
+    { 5,  5,  6, ABC_CONST(0xFF007070FF007070), "<(!(ab)c)de>" },   //  126
+    { 5,  7,  8, ABC_CONST(0xFF007878FF007878), "<[(ab)c]de>" },   //  127
+    { 5,  7,  7, ABC_CONST(0xFF006060FF006060), "<([ab]c)de>" },   //  128
+    { 5,  9, 10, ABC_CONST(0xFF009696FF009696), "<[abc]de>" },   //  129
+    { 5,  6,  6, ABC_CONST(0xFF00CACAFF00CACA), "<<abc>de>" },   //  130
+    { 6,  5,  7, ABC_CONST(0x8000000000000000), "(abcdef)" },   //  131
+    { 6,  5,  7, ABC_CONST(0x7FFFFFFF00000000), "(!(abcde)f)" },   //  132
+    { 6,  7, 12, ABC_CONST(0x7FFFFFFF80000000), "[(abcde)f]" },   //  133
+    { 6,  5,  7, ABC_CONST(0x7FFF000000000000), "(!(abcd)ef)" },   //  134
+    { 6,  5,  7, ABC_CONST(0x8000FFFF00000000), "(!(!(abcd)e)f)" },   //  135
+    { 6,  7, 12, ABC_CONST(0x8000FFFF7FFF0000), "[(!(abcd)e)f]" },   //  136
+    { 6,  7, 11, ABC_CONST(0x7FFF800000000000), "([(abcd)e]f)" },   //  137
+    { 6,  9, 20, ABC_CONST(0x80007FFF7FFF8000), "[(abcd)ef]" },   //  138
+    { 6,  5,  7, ABC_CONST(0x7F00000000000000), "(!(abc)def)" },   //  139
+    { 6,  5,  7, ABC_CONST(0x80FFFFFF00000000), "(!(!(abc)de)f)" },   //  140
+    { 6,  7, 12, ABC_CONST(0x80FFFFFF7F000000), "[(!(abc)de)f]" },   //  141
+    { 6,  5,  7, ABC_CONST(0x80FF000000000000), "(!(!(abc)d)ef)" },   //  142
+    { 6,  5,  7, ABC_CONST(0x7F00FFFF00000000), "(!(!(!(abc)d)e)f)" },   //  143
+    { 6,  7, 12, ABC_CONST(0x7F00FFFF80FF0000), "[(!(!(abc)d)e)f]" },   //  144
+    { 6,  7, 11, ABC_CONST(0x80FF7F0000000000), "([(!(abc)d)e]f)" },   //  145
+    { 6,  9, 20, ABC_CONST(0x7F0080FF80FF7F00), "[(!(abc)d)ef]" },   //  146
+    { 6,  7, 10, ABC_CONST(0x7F80000000000000), "([(abc)d]ef)" },   //  147
+    { 6,  7, 10, ABC_CONST(0x807FFFFF00000000), "(!([(abc)d]e)f)" },   //  148
+    { 6,  9, 18, ABC_CONST(0x807FFFFF7F800000), "[([(abc)d]e)f]" },   //  149
+    { 6,  9, 17, ABC_CONST(0x807F7F8000000000), "([(abc)de]f)" },   //  150
+    { 6, 11, 32, ABC_CONST(0x7F80807F807F7F80), "[(abc)def]" },   //  151
+    { 6,  5,  7, ABC_CONST(0x7000000000000000), "(!(ab)cdef)" },   //  152
+    { 6,  5,  7, ABC_CONST(0x8FFFFFFF00000000), "(!(!(ab)cde)f)" },   //  153
+    { 6,  7, 12, ABC_CONST(0x8FFFFFFF70000000), "[(!(ab)cde)f]" },   //  154
+    { 6,  5,  7, ABC_CONST(0x8FFF000000000000), "(!(!(ab)cd)ef)" },   //  155
+    { 6,  5,  7, ABC_CONST(0x7000FFFF00000000), "(!(!(!(ab)cd)e)f)" },   //  156
+    { 6,  7, 12, ABC_CONST(0x7000FFFF8FFF0000), "[(!(!(ab)cd)e)f]" },   //  157
+    { 6,  7, 11, ABC_CONST(0x8FFF700000000000), "([(!(ab)cd)e]f)" },   //  158
+    { 6,  9, 20, ABC_CONST(0x70008FFF8FFF7000), "[(!(ab)cd)ef]" },   //  159
+    { 6,  5,  7, ABC_CONST(0x8F00000000000000), "(!(!(ab)c)def)" },   //  160
+    { 6,  5,  7, ABC_CONST(0x70FFFFFF00000000), "(!(!(!(ab)c)de)f)" },   //  161
+    { 6,  7, 12, ABC_CONST(0x70FFFFFF8F000000), "[(!(!(ab)c)de)f]" },   //  162
+    { 6,  5,  7, ABC_CONST(0x70FF000000000000), "(!(!(!(ab)c)d)ef)" },   //  163
+    { 6,  5,  7, ABC_CONST(0x8F00FFFF00000000), "(!(!(!(!(ab)c)d)e)f)" },   //  164
+    { 6,  7, 12, ABC_CONST(0x8F00FFFF70FF0000), "[(!(!(!(ab)c)d)e)f]" },   //  165
+    { 6,  7, 11, ABC_CONST(0x70FF8F0000000000), "([(!(!(ab)c)d)e]f)" },   //  166
+    { 6,  9, 20, ABC_CONST(0x8F0070FF70FF8F00), "[(!(!(ab)c)d)ef]" },   //  167
+    { 6,  7, 10, ABC_CONST(0x8F70000000000000), "([(!(ab)c)d]ef)" },   //  168
+    { 6,  7, 10, ABC_CONST(0x708FFFFF00000000), "(!([(!(ab)c)d]e)f)" },   //  169
+    { 6,  9, 18, ABC_CONST(0x708FFFFF8F700000), "[([(!(ab)c)d]e)f]" },   //  170
+    { 6,  9, 17, ABC_CONST(0x708F8F7000000000), "([(!(ab)c)de]f)" },   //  171
+    { 6, 11, 32, ABC_CONST(0x8F70708F708F8F70), "[(!(ab)c)def]" },   //  172
+    { 6,  7,  9, ABC_CONST(0x7800000000000000), "([(ab)c]def)" },   //  173
+    { 6,  7,  9, ABC_CONST(0x87FFFFFF00000000), "(!([(ab)c]de)f)" },   //  174
+    { 6,  9, 16, ABC_CONST(0x87FFFFFF78000000), "[([(ab)c]de)f]" },   //  175
+    { 6,  7,  9, ABC_CONST(0x87FF000000000000), "(!([(ab)c]d)ef)" },   //  176
+    { 6,  7,  9, ABC_CONST(0x7800FFFF00000000), "(!(!([(ab)c]d)e)f)" },   //  177
+    { 6,  9, 16, ABC_CONST(0x7800FFFF87FF0000), "[(!([(ab)c]d)e)f]" },   //  178
+    { 6,  9, 15, ABC_CONST(0x87FF780000000000), "([([(ab)c]d)e]f)" },   //  179
+    { 6, 11, 28, ABC_CONST(0x780087FF87FF7800), "[([(ab)c]d)ef]" },   //  180
+    { 6,  9, 14, ABC_CONST(0x8778000000000000), "([(ab)cd]ef)" },   //  181
+    { 6,  9, 14, ABC_CONST(0x7887FFFF00000000), "(!([(ab)cd]e)f)" },   //  182
+    { 6, 11, 26, ABC_CONST(0x7887FFFF87780000), "[([(ab)cd]e)f]" },   //  183
+    { 6, 11, 25, ABC_CONST(0x7887877800000000), "([(ab)cde]f)" },   //  184
+    { 6, 13, 48, ABC_CONST(0x8778788778878778), "[(ab)cdef]" },   //  185
+    { 6,  7,  8, ABC_CONST(0x6000000000000000), "([ab]cdef)" },   //  186
+    { 6,  7,  8, ABC_CONST(0x9FFFFFFF00000000), "(!([ab]cde)f)" },   //  187
+    { 6,  9, 14, ABC_CONST(0x9FFFFFFF60000000), "[([ab]cde)f]" },   //  188
+    { 6,  7,  8, ABC_CONST(0x9FFF000000000000), "(!([ab]cd)ef)" },   //  189
+    { 6,  7,  8, ABC_CONST(0x6000FFFF00000000), "(!(!([ab]cd)e)f)" },   //  190
+    { 6,  9, 14, ABC_CONST(0x6000FFFF9FFF0000), "[(!([ab]cd)e)f]" },   //  191
+    { 6,  9, 13, ABC_CONST(0x9FFF600000000000), "([([ab]cd)e]f)" },   //  192
+    { 6, 11, 24, ABC_CONST(0x60009FFF9FFF6000), "[([ab]cd)ef]" },   //  193
+    { 6,  7,  8, ABC_CONST(0x9F00000000000000), "(!([ab]c)def)" },   //  194
+    { 6,  7,  8, ABC_CONST(0x60FFFFFF00000000), "(!(!([ab]c)de)f)" },   //  195
+    { 6,  9, 14, ABC_CONST(0x60FFFFFF9F000000), "[(!([ab]c)de)f]" },   //  196
+    { 6,  7,  8, ABC_CONST(0x60FF000000000000), "(!(!([ab]c)d)ef)" },   //  197
+    { 6,  7,  8, ABC_CONST(0x9F00FFFF00000000), "(!(!(!([ab]c)d)e)f)" },   //  198
+    { 6,  9, 14, ABC_CONST(0x9F00FFFF60FF0000), "[(!(!([ab]c)d)e)f]" },   //  199
+    { 6,  9, 13, ABC_CONST(0x60FF9F0000000000), "([(!([ab]c)d)e]f)" },   //  200
+    { 6, 11, 24, ABC_CONST(0x9F0060FF60FF9F00), "[(!([ab]c)d)ef]" },   //  201
+    { 6,  9, 12, ABC_CONST(0x9F60000000000000), "([([ab]c)d]ef)" },   //  202
+    { 6,  9, 12, ABC_CONST(0x609FFFFF00000000), "(!([([ab]c)d]e)f)" },   //  203
+    { 6, 11, 22, ABC_CONST(0x609FFFFF9F600000), "[([([ab]c)d]e)f]" },   //  204
+    { 6, 11, 21, ABC_CONST(0x609F9F6000000000), "([([ab]c)de]f)" },   //  205
+    { 6, 13, 40, ABC_CONST(0x9F60609F609F9F60), "[([ab]c)def]" },   //  206
+    { 6,  9, 11, ABC_CONST(0x9600000000000000), "([abc]def)" },   //  207
+    { 6,  9, 11, ABC_CONST(0x69FFFFFF00000000), "(!([abc]de)f)" },   //  208
+    { 6, 11, 20, ABC_CONST(0x69FFFFFF96000000), "[([abc]de)f]" },   //  209
+    { 6,  9, 11, ABC_CONST(0x69FF000000000000), "(!([abc]d)ef)" },   //  210
+    { 6,  9, 11, ABC_CONST(0x9600FFFF00000000), "(!(!([abc]d)e)f)" },   //  211
+    { 6, 11, 20, ABC_CONST(0x9600FFFF69FF0000), "[(!([abc]d)e)f]" },   //  212
+    { 6, 11, 19, ABC_CONST(0x69FF960000000000), "([([abc]d)e]f)" },   //  213
+    { 6, 13, 36, ABC_CONST(0x960069FF69FF9600), "[([abc]d)ef]" },   //  214
+    { 6, 11, 18, ABC_CONST(0x6996000000000000), "([abcd]ef)" },   //  215
+    { 6, 11, 18, ABC_CONST(0x9669FFFF00000000), "(!([abcd]e)f)" },   //  216
+    { 6, 13, 34, ABC_CONST(0x9669FFFF69960000), "[([abcd]e)f]" },   //  217
+    { 6, 13, 33, ABC_CONST(0x9669699600000000), "([abcde]f)" },   //  218
+    { 6, 15, 64, ABC_CONST(0x6996966996696996), "[abcdef]" },   //  219
+    { 6,  6,  7, ABC_CONST(0xCA00000000000000), "(<abc>def)" },   //  220
+    { 6,  6,  7, ABC_CONST(0x35FFFFFF00000000), "(!(<abc>de)f)" },   //  221
+    { 6,  8, 12, ABC_CONST(0x35FFFFFFCA000000), "[(<abc>de)f]" },   //  222
+    { 6,  6,  7, ABC_CONST(0x35FF000000000000), "(!(<abc>d)ef)" },   //  223
+    { 6,  6,  7, ABC_CONST(0xCA00FFFF00000000), "(!(!(<abc>d)e)f)" },   //  224
+    { 6,  8, 12, ABC_CONST(0xCA00FFFF35FF0000), "[(!(<abc>d)e)f]" },   //  225
+    { 6,  8, 11, ABC_CONST(0x35FFCA0000000000), "([(<abc>d)e]f)" },   //  226
+    { 6, 10, 20, ABC_CONST(0xCA0035FF35FFCA00), "[(<abc>d)ef]" },   //  227
+    { 6,  8, 10, ABC_CONST(0x35CA000000000000), "([<abc>d]ef)" },   //  228
+    { 6,  8, 10, ABC_CONST(0xCA35FFFF00000000), "(!([<abc>d]e)f)" },   //  229
+    { 6, 10, 18, ABC_CONST(0xCA35FFFF35CA0000), "[([<abc>d]e)f]" },   //  230
+    { 6, 10, 17, ABC_CONST(0xCA3535CA00000000), "([<abc>de]f)" },   //  231
+    { 6, 12, 32, ABC_CONST(0x35CACA35CA3535CA), "[<abc>def]" },   //  232
+    { 6,  5,  8, ABC_CONST(0x0777000000000000), "(!(ab)!(cd)ef)" },   //  233
+    { 6,  5,  8, ABC_CONST(0xF888FFFF00000000), "(!(!(ab)!(cd)e)f)" },   //  234
+    { 6,  7, 14, ABC_CONST(0xF888FFFF07770000), "[(!(ab)!(cd)e)f]" },   //  235
+    { 6,  5,  8, ABC_CONST(0xF888000000000000), "(!(!(ab)!(cd))ef)" },   //  236
+    { 6,  5,  8, ABC_CONST(0x0777FFFF00000000), "(!(!(!(ab)!(cd))e)f)" },   //  237
+    { 6,  7, 14, ABC_CONST(0x0777FFFFF8880000), "[(!(!(ab)!(cd))e)f]" },   //  238
+    { 6,  7, 13, ABC_CONST(0xF888077700000000), "([(!(ab)!(cd))e]f)" },   //  239
+    { 6,  9, 24, ABC_CONST(0x0777F888F8880777), "[(!(ab)!(cd))ef]" },   //  240
+    { 6,  7, 11, ABC_CONST(0x7888000000000000), "([(ab)(cd)]ef)" },   //  241
+    { 6,  7, 11, ABC_CONST(0x8777FFFF00000000), "(!([(ab)(cd)]e)f)" },   //  242
+    { 6,  9, 20, ABC_CONST(0x8777FFFF78880000), "[([(ab)(cd)]e)f]" },   //  243
+    { 6,  7, 11, ABC_CONST(0x8777000000000000), "(![(ab)(cd)]ef)" },   //  244
+    { 6,  7, 11, ABC_CONST(0x7888FFFF00000000), "(!(![(ab)(cd)]e)f)" },   //  245
+    { 6,  9, 20, ABC_CONST(0x7888FFFF87770000), "[(![(ab)(cd)]e)f]" },   //  246
+    { 6,  9, 19, ABC_CONST(0x8777788800000000), "([(ab)(cd)e]f)" },   //  247
+    { 6, 11, 36, ABC_CONST(0x7888877787777888), "[(ab)(cd)ef]" },   //  248
+    { 6,  7,  9, ABC_CONST(0x0666000000000000), "([ab]!(cd)ef)" },   //  249
+    { 6,  7,  9, ABC_CONST(0xF999FFFF00000000), "(!([ab]!(cd)e)f)" },   //  250
+    { 6,  9, 16, ABC_CONST(0xF999FFFF06660000), "[([ab]!(cd)e)f]" },   //  251
+    { 6,  7,  9, ABC_CONST(0xF999000000000000), "(!([ab]!(cd))ef)" },   //  252
+    { 6,  7,  9, ABC_CONST(0x0666FFFF00000000), "(!(!([ab]!(cd))e)f)" },   //  253
+    { 6,  9, 16, ABC_CONST(0x0666FFFFF9990000), "[(!([ab]!(cd))e)f]" },   //  254
+    { 6,  9, 15, ABC_CONST(0xF999066600000000), "([([ab]!(cd))e]f)" },   //  255
+    { 6, 11, 28, ABC_CONST(0x0666F999F9990666), "[([ab]!(cd))ef]" },   //  256
+    { 6,  9, 10, ABC_CONST(0x0660000000000000), "([ab][cd]ef)" },   //  257
+    { 6,  9, 10, ABC_CONST(0xF99FFFFF00000000), "(!([ab][cd]e)f)" },   //  258
+    { 6, 11, 18, ABC_CONST(0xF99FFFFF06600000), "[([ab][cd]e)f]" },   //  259
+    { 6,  9, 10, ABC_CONST(0xF99F000000000000), "(!([ab][cd])ef)" },   //  260
+    { 6,  9, 10, ABC_CONST(0x0660FFFF00000000), "(!(!([ab][cd])e)f)" },   //  261
+    { 6, 11, 18, ABC_CONST(0x0660FFFFF99F0000), "[(!([ab][cd])e)f]" },   //  262
+    { 6, 11, 17, ABC_CONST(0xF99F066000000000), "([([ab][cd])e]f)" },   //  263
+    { 6, 13, 32, ABC_CONST(0x0660F99FF99F0660), "[([ab][cd])ef]" },   //  264
+    { 6,  6,  8, ABC_CONST(0xCAAA000000000000), "(<ab(cd)>ef)" },   //  265
+    { 6,  6,  8, ABC_CONST(0x3555FFFF00000000), "(!(<ab(cd)>e)f)" },   //  266
+    { 6,  8, 14, ABC_CONST(0x3555FFFFCAAA0000), "[(<ab(cd)>e)f]" },   //  267
+    { 6,  8, 13, ABC_CONST(0x3555CAAA00000000), "([<ab(cd)>e]f)" },   //  268
+    { 6, 10, 24, ABC_CONST(0xCAAA35553555CAAA), "[<ab(cd)>ef]" },   //  269
+    { 6,  8, 10, ABC_CONST(0xACCA000000000000), "(<ab[cd]>ef)" },   //  270
+    { 6,  8, 10, ABC_CONST(0x5335FFFF00000000), "(!(<ab[cd]>e)f)" },   //  271
+    { 6, 10, 18, ABC_CONST(0x5335FFFFACCA0000), "[(<ab[cd]>e)f]" },   //  272
+    { 6, 10, 17, ABC_CONST(0x5335ACCA00000000), "([<ab[cd]>e]f)" },   //  273
+    { 6, 12, 32, ABC_CONST(0xACCA53355335ACCA), "[<ab[cd]>ef]" },   //  274
+    { 6,  6,  7, ABC_CONST(0xF088000000000000), "(<(ab)cd>ef)" },   //  275
+    { 6,  6,  7, ABC_CONST(0x0F77FFFF00000000), "(!(<(ab)cd>e)f)" },   //  276
+    { 6,  8, 12, ABC_CONST(0x0F77FFFFF0880000), "[(<(ab)cd>e)f]" },   //  277
+    { 6,  6,  7, ABC_CONST(0x0F77000000000000), "(!<(ab)cd>ef)" },   //  278
+    { 6,  6,  7, ABC_CONST(0xF088FFFF00000000), "(!(!<(ab)cd>e)f)" },   //  279
+    { 6,  8, 12, ABC_CONST(0xF088FFFF0F770000), "[(!<(ab)cd>e)f]" },   //  280
+    { 6,  8, 11, ABC_CONST(0x0F77F08800000000), "([<(ab)cd>e]f)" },   //  281
+    { 6, 10, 20, ABC_CONST(0xF0880F770F77F088), "[<(ab)cd>ef]" },   //  282
+    { 6,  8,  8, ABC_CONST(0xF066000000000000), "(<[ab]cd>ef)" },   //  283
+    { 6,  8,  8, ABC_CONST(0x0F99FFFF00000000), "(!(<[ab]cd>e)f)" },   //  284
+    { 6, 10, 14, ABC_CONST(0x0F99FFFFF0660000), "[(<[ab]cd>e)f]" },   //  285
+    { 6, 10, 13, ABC_CONST(0x0F99F06600000000), "([<[ab]cd>e]f)" },   //  286
+    { 6, 12, 24, ABC_CONST(0xF0660F990F99F066), "[<[ab]cd>ef]" },   //  287
+    { 6,  5,  9, ABC_CONST(0x007F7F7F00000000), "(!(abc)!(de)f)" },   //  288
+    { 6,  5,  9, ABC_CONST(0xFF80808000000000), "(!(!(abc)!(de))f)" },   //  289
+    { 6,  7, 16, ABC_CONST(0xFF808080007F7F7F), "[(!(abc)!(de))f]" },   //  290
+    { 6,  7, 13, ABC_CONST(0x7F80808000000000), "([(abc)(de)]f)" },   //  291
+    { 6,  7, 13, ABC_CONST(0x807F7F7F00000000), "(![(abc)(de)]f)" },   //  292
+    { 6,  9, 24, ABC_CONST(0x807F7F7F7F808080), "[(abc)(de)f]" },   //  293
+    { 6,  5,  8, ABC_CONST(0x008F8F8F00000000), "(!(!(ab)c)!(de)f)" },   //  294
+    { 6,  5,  8, ABC_CONST(0xFF70707000000000), "(!(!(!(ab)c)!(de))f)" },   //  295
+    { 6,  7, 14, ABC_CONST(0xFF707070008F8F8F), "[(!(!(ab)c)!(de))f]" },   //  296
+    { 6,  7, 13, ABC_CONST(0x8F70707000000000), "([(!(ab)c)(de)]f)" },   //  297
+    { 6,  7, 13, ABC_CONST(0x708F8F8F00000000), "(![(!(ab)c)(de)]f)" },   //  298
+    { 6,  9, 24, ABC_CONST(0x708F8F8F8F707070), "[(!(ab)c)(de)f]" },   //  299
+    { 6,  7, 11, ABC_CONST(0x0078787800000000), "([(ab)c]!(de)f)" },   //  300
+    { 6,  7, 11, ABC_CONST(0xFF87878700000000), "(!([(ab)c]!(de))f)" },   //  301
+    { 6,  9, 20, ABC_CONST(0xFF87878700787878), "[([(ab)c]!(de))f]" },   //  302
+    { 6,  7, 10, ABC_CONST(0x009F9F9F00000000), "(!([ab]c)!(de)f)" },   //  303
+    { 6,  7, 10, ABC_CONST(0xFF60606000000000), "(!(!([ab]c)!(de))f)" },   //  304
+    { 6,  9, 18, ABC_CONST(0xFF606060009F9F9F), "[(!([ab]c)!(de))f]" },   //  305
+    { 6,  9, 16, ABC_CONST(0x9F60606000000000), "([([ab]c)(de)]f)" },   //  306
+    { 6,  9, 16, ABC_CONST(0x609F9F9F00000000), "(![([ab]c)(de)]f)" },   //  307
+    { 6, 11, 30, ABC_CONST(0x609F9F9F9F606060), "[([ab]c)(de)f]" },   //  308
+    { 6,  9, 14, ABC_CONST(0x0096969600000000), "([abc]!(de)f)" },   //  309
+    { 6,  9, 14, ABC_CONST(0xFF69696900000000), "(!([abc]!(de))f)" },   //  310
+    { 6, 11, 26, ABC_CONST(0xFF69696900969696), "[([abc]!(de))f]" },   //  311
+    { 6,  6,  8, ABC_CONST(0x00CACACA00000000), "(<abc>!(de)f)" },   //  312
+    { 6,  6,  8, ABC_CONST(0xFF35353500000000), "(!(<abc>!(de))f)" },   //  313
+    { 6,  8, 14, ABC_CONST(0xFF35353500CACACA), "[(<abc>!(de))f]" },   //  314
+    { 6,  8, 13, ABC_CONST(0x35CACACA00000000), "([<abc>(de)]f)" },   //  315
+    { 6, 10, 24, ABC_CONST(0xCA35353535CACACA), "[<abc>(de)f]" },   //  316
+    { 6,  7, 10, ABC_CONST(0x007F7F0000000000), "(!(abc)[de]f)" },   //  317
+    { 6,  7, 10, ABC_CONST(0xFF8080FF00000000), "(!(!(abc)[de])f)" },   //  318
+    { 6,  9, 18, ABC_CONST(0xFF8080FF007F7F00), "[(!(abc)[de])f]" },   //  319
+    { 6,  7,  9, ABC_CONST(0x008F8F0000000000), "(!(!(ab)c)[de]f)" },   //  320
+    { 6,  7,  9, ABC_CONST(0xFF7070FF00000000), "(!(!(!(ab)c)[de])f)" },   //  321
+    { 6,  9, 16, ABC_CONST(0xFF7070FF008F8F00), "[(!(!(ab)c)[de])f]" },   //  322
+    { 6,  9, 12, ABC_CONST(0x0078780000000000), "([(ab)c][de]f)" },   //  323
+    { 6,  9, 12, ABC_CONST(0xFF8787FF00000000), "(!([(ab)c][de])f)" },   //  324
+    { 6, 11, 22, ABC_CONST(0xFF8787FF00787800), "[([(ab)c][de])f]" },   //  325
+    { 6,  9, 11, ABC_CONST(0x009F9F0000000000), "(!([ab]c)[de]f)" },   //  326
+    { 6,  9, 11, ABC_CONST(0xFF6060FF00000000), "(!(!([ab]c)[de])f)" },   //  327
+    { 6, 11, 20, ABC_CONST(0xFF6060FF009F9F00), "[(!([ab]c)[de])f]" },   //  328
+    { 6, 11, 15, ABC_CONST(0x0096960000000000), "([abc][de]f)" },   //  329
+    { 6, 11, 15, ABC_CONST(0xFF6969FF00000000), "(!([abc][de])f)" },   //  330
+    { 6, 13, 28, ABC_CONST(0xFF6969FF00969600), "[([abc][de])f]" },   //  331
+    { 6,  8,  9, ABC_CONST(0x00CACA0000000000), "(<abc>[de]f)" },   //  332
+    { 6,  8,  9, ABC_CONST(0xFF3535FF00000000), "(!(<abc>[de])f)" },   //  333
+    { 6, 10, 16, ABC_CONST(0xFF3535FF00CACA00), "[(<abc>[de])f]" },   //  334
+    { 6,  6,  9, ABC_CONST(0xCAAAAAAA00000000), "(<ab(cde)>f)" },   //  335
+    { 6,  8, 16, ABC_CONST(0x35555555CAAAAAAA), "[<ab(cde)>f]" },   //  336
+    { 6,  6,  9, ABC_CONST(0xACCCAAAA00000000), "(<ab(!(cd)e)>f)" },   //  337
+    { 6,  8, 16, ABC_CONST(0x53335555ACCCAAAA), "[<ab(!(cd)e)>f]" },   //  338
+    { 6,  8, 13, ABC_CONST(0xACCCCAAA00000000), "(<ab[(cd)e]>f)" },   //  339
+    { 6, 10, 24, ABC_CONST(0x53333555ACCCCAAA), "[<ab[(cd)e]>f]" },   //  340
+    { 6,  8, 11, ABC_CONST(0xACCAAAAA00000000), "(<ab([cd]e)>f)" },   //  341
+    { 6, 10, 20, ABC_CONST(0x53355555ACCAAAAA), "[<ab([cd]e)>f]" },   //  342
+    { 6, 10, 17, ABC_CONST(0xCAACACCA00000000), "(<ab[cde]>f)" },   //  343
+    { 6, 12, 32, ABC_CONST(0x35535335CAACACCA), "[<ab[cde]>f]" },   //  344
+    { 6,  7,  9, ABC_CONST(0xCCAACACA00000000), "(<ab<cde>>f)" },   //  345
+    { 6,  9, 16, ABC_CONST(0x33553535CCAACACA), "[<ab<cde>>f]" },   //  346
+    { 6,  6,  8, ABC_CONST(0xC0AAAAAA00000000), "(<a(bc)(de)>f)" },   //  347
+    { 6,  6,  8, ABC_CONST(0x3F55555500000000), "(!<a(bc)(de)>f)" },   //  348
+    { 6,  8, 14, ABC_CONST(0x3F555555C0AAAAAA), "[<a(bc)(de)>f]" },   //  349
+    { 6,  8,  9, ABC_CONST(0x3CAAAAAA00000000), "(<a[bc](de)>f)" },   //  350
+    { 6, 10, 16, ABC_CONST(0xC35555553CAAAAAA), "[<a[bc](de)>f]" },   //  351
+    { 6,  6,  9, ABC_CONST(0xF088888800000000), "(<(ab)c(de)>f)" },   //  352
+    { 6,  6,  9, ABC_CONST(0x0F77777700000000), "(!<(ab)c(de)>f)" },   //  353
+    { 6,  8, 16, ABC_CONST(0x0F777777F0888888), "[<(ab)c(de)>f]" },   //  354
+    { 6,  8, 11, ABC_CONST(0x88F0F08800000000), "(<(ab)c[de]>f)" },   //  355
+    { 6,  8, 11, ABC_CONST(0x770F0F7700000000), "(!<(ab)c[de]>f)" },   //  356
+    { 6, 10, 20, ABC_CONST(0x770F0F7788F0F088), "[<(ab)c[de]>f]" },   //  357
+    { 6,  8, 11, ABC_CONST(0xF066666600000000), "(<[ab]c(de)>f)" },   //  358
+    { 6, 10, 20, ABC_CONST(0x0F999999F0666666), "[<[ab]c(de)>f]" },   //  359
+    { 6, 10, 13, ABC_CONST(0x66F0F06600000000), "(<[ab]c[de]>f)" },   //  360
+    { 6, 12, 24, ABC_CONST(0x990F0F9966F0F066), "[<[ab]c[de]>f]" },   //  361
+    { 6,  6,  7, ABC_CONST(0xF000888800000000), "(<(ab)(cd)e>f)" },   //  362
+    { 6,  6,  7, ABC_CONST(0x0FFF777700000000), "(!<(ab)(cd)e>f)" },   //  363
+    { 6,  8, 12, ABC_CONST(0x0FFF7777F0008888), "[<(ab)(cd)e>f]" },   //  364
+    { 6,  6,  7, ABC_CONST(0xF000777700000000), "(<!(ab)(cd)e>f)" },   //  365
+    { 6,  8, 12, ABC_CONST(0x0FFF8888F0007777), "[<!(ab)(cd)e>f]" },   //  366
+    { 6,  8,  8, ABC_CONST(0xF000666600000000), "(<[ab](cd)e>f)" },   //  367
+    { 6,  8,  8, ABC_CONST(0x0FFF999900000000), "(!<[ab](cd)e>f)" },   //  368
+    { 6, 10, 14, ABC_CONST(0x0FFF9999F0006666), "[<[ab](cd)e>f]" },   //  369
+    { 6, 10,  9, ABC_CONST(0x0FF0666600000000), "(<[ab][cd]e>f)" },   //  370
+    { 6, 12, 16, ABC_CONST(0xF00F99990FF06666), "[<[ab][cd]e>f]" },   //  371
+    { 6,  6,  7, ABC_CONST(0xFF00808000000000), "(<(abc)de>f)" },   //  372
+    { 6,  6,  7, ABC_CONST(0x00FF7F7F00000000), "(!<(abc)de>f)" },   //  373
+    { 6,  8, 12, ABC_CONST(0x00FF7F7FFF008080), "[<(abc)de>f]" },   //  374
+    { 6,  6,  7, ABC_CONST(0xFF00707000000000), "(<(!(ab)c)de>f)" },   //  375
+    { 6,  6,  7, ABC_CONST(0x00FF8F8F00000000), "(!<(!(ab)c)de>f)" },   //  376
+    { 6,  8, 12, ABC_CONST(0x00FF8F8FFF007070), "[<(!(ab)c)de>f]" },   //  377
+    { 6,  8,  9, ABC_CONST(0xFF00787800000000), "(<[(ab)c]de>f)" },   //  378
+    { 6, 10, 16, ABC_CONST(0x00FF8787FF007878), "[<[(ab)c]de>f]" },   //  379
+    { 6,  8,  8, ABC_CONST(0xFF00606000000000), "(<([ab]c)de>f)" },   //  380
+    { 6,  8,  8, ABC_CONST(0x00FF9F9F00000000), "(!<([ab]c)de>f)" },   //  381
+    { 6, 10, 14, ABC_CONST(0x00FF9F9FFF006060), "[<([ab]c)de>f]" },   //  382
+    { 6, 10, 11, ABC_CONST(0xFF00969600000000), "(<[abc]de>f)" },   //  383
+    { 6, 12, 20, ABC_CONST(0x00FF6969FF009696), "[<[abc]de>f]" },   //  384
+    { 6,  7,  7, ABC_CONST(0xFF00CACA00000000), "(<<abc>de>f)" },   //  385
+    { 6,  9, 12, ABC_CONST(0x00FF3535FF00CACA), "[<<abc>de>f]" },   //  386
+    { 6,  5, 10, ABC_CONST(0x00007FFF7FFF7FFF), "(!(abcd)!(ef))" },   //  387
+    { 6,  7, 15, ABC_CONST(0x7FFF800080008000), "[(abcd)(ef)]" },   //  388
+    { 6,  5,  8, ABC_CONST(0x000080FF80FF80FF), "(!(!(abc)d)!(ef))" },   //  389
+    { 6,  7, 15, ABC_CONST(0x80FF7F007F007F00), "[(!(abc)d)(ef)]" },   //  390
+    { 6,  7, 13, ABC_CONST(0x00007F807F807F80), "([(abc)d]!(ef))" },   //  391
+    { 6,  5,  9, ABC_CONST(0x00008FFF8FFF8FFF), "(!(!(ab)cd)!(ef))" },   //  392
+    { 6,  7, 15, ABC_CONST(0x8FFF700070007000), "[(!(ab)cd)(ef)]" },   //  393
+    { 6,  5,  9, ABC_CONST(0x000070FF70FF70FF), "(!(!(!(ab)c)d)!(ef))" },   //  394
+    { 6,  7, 15, ABC_CONST(0x70FF8F008F008F00), "[(!(!(ab)c)d)(ef)]" },   //  395
+    { 6,  7, 13, ABC_CONST(0x00008F708F708F70), "([(!(ab)c)d]!(ef))" },   //  396
+    { 6,  7, 12, ABC_CONST(0x000087FF87FF87FF), "(!([(ab)c]d)!(ef))" },   //  397
+    { 6,  9, 21, ABC_CONST(0x87FF780078007800), "[([(ab)c]d)(ef)]" },   //  398
+    { 6,  9, 19, ABC_CONST(0x0000877887788778), "([(ab)cd]!(ef))" },   //  399
+    { 6,  7, 11, ABC_CONST(0x00009FFF9FFF9FFF), "(!([ab]cd)!(ef))" },   //  400
+    { 6,  9, 18, ABC_CONST(0x9FFF600060006000), "[([ab]cd)(ef)]" },   //  401
+    { 6,  7, 10, ABC_CONST(0x000060FF60FF60FF), "(!(!([ab]c)d)!(ef))" },   //  402
+    { 6,  9, 18, ABC_CONST(0x60FF9F009F009F00), "[(!([ab]c)d)(ef)]" },   //  403
+    { 6,  9, 16, ABC_CONST(0x00009F609F609F60), "([([ab]c)d]!(ef))" },   //  404
+    { 6,  9, 15, ABC_CONST(0x000069FF69FF69FF), "(!([abc]d)!(ef))" },   //  405
+    { 6, 11, 27, ABC_CONST(0x69FF960096009600), "[([abc]d)(ef)]" },   //  406
+    { 6, 11, 25, ABC_CONST(0x0000699669966996), "([abcd]!(ef))" },   //  407
+    { 6,  6,  9, ABC_CONST(0x000035FF35FF35FF), "(!(<abc>d)!(ef))" },   //  408
+    { 6,  8, 15, ABC_CONST(0x35FFCA00CA00CA00), "[(<abc>d)(ef)]" },   //  409
+    { 6,  8, 13, ABC_CONST(0x000035CA35CA35CA), "([<abc>d]!(ef))" },   //  410
+    { 6,  5, 11, ABC_CONST(0x0000077707770777), "(!(ab)!(cd)!(ef))" },   //  411
+    { 6,  5,  9, ABC_CONST(0x0000F888F888F888), "(!(!(ab)!(cd))!(ef))" },   //  412
+    { 6,  7, 18, ABC_CONST(0xF888077707770777), "[(!(ab)!(cd))(ef)]" },   //  413
+    { 6,  7, 14, ABC_CONST(0x0000788878887888), "([(ab)(cd)]!(ef))" },   //  414
+    { 6,  7, 15, ABC_CONST(0x0000877787778777), "(![(ab)(cd)]!(ef))" },   //  415
+    { 6,  9, 27, ABC_CONST(0x8777788878887888), "[(ab)(cd)(ef)]" },   //  416
+    { 6,  7, 12, ABC_CONST(0x0000066606660666), "([ab]!(cd)!(ef))" },   //  417
+    { 6,  7, 11, ABC_CONST(0x0000F999F999F999), "(!([ab]!(cd))!(ef))" },   //  418
+    { 6,  9, 21, ABC_CONST(0xF999066606660666), "[([ab]!(cd))(ef)]" },   //  419
+    { 6,  9, 13, ABC_CONST(0x0000066006600660), "([ab][cd]!(ef))" },   //  420
+    { 6,  9, 13, ABC_CONST(0x0000F99FF99FF99F), "(!([ab][cd])!(ef))" },   //  421
+    { 6, 11, 24, ABC_CONST(0xF99F066006600660), "[([ab][cd])(ef)]" },   //  422
+    { 6,  6, 10, ABC_CONST(0x0000CAAACAAACAAA), "(<ab(cd)>!(ef))" },   //  423
+    { 6,  8, 18, ABC_CONST(0x3555CAAACAAACAAA), "[<ab(cd)>(ef)]" },   //  424
+    { 6,  8, 13, ABC_CONST(0x0000ACCAACCAACCA), "(<ab[cd]>!(ef))" },   //  425
+    { 6, 10, 24, ABC_CONST(0x5335ACCAACCAACCA), "[<ab[cd]>(ef)]" },   //  426
+    { 6,  6,  8, ABC_CONST(0x0000F088F088F088), "(<(ab)cd>!(ef))" },   //  427
+    { 6,  6,  9, ABC_CONST(0x00000F770F770F77), "(!<(ab)cd>!(ef))" },   //  428
+    { 6,  8, 15, ABC_CONST(0x0F77F088F088F088), "[<(ab)cd>(ef)]" },   //  429
+    { 6,  8, 10, ABC_CONST(0x0000F066F066F066), "(<[ab]cd>!(ef))" },   //  430
+    { 6, 10, 18, ABC_CONST(0x0F99F066F066F066), "[<[ab]cd>(ef)]" },   //  431
+    { 6,  7, 11, ABC_CONST(0x00007FFF7FFF0000), "(!(abcd)[ef])" },   //  432
+    { 6,  7,  9, ABC_CONST(0x000080FF80FF0000), "(!(!(abc)d)[ef])" },   //  433
+    { 6,  9, 14, ABC_CONST(0x00007F807F800000), "([(abc)d][ef])" },   //  434
+    { 6,  7, 10, ABC_CONST(0x00008FFF8FFF0000), "(!(!(ab)cd)[ef])" },   //  435
+    { 6,  7, 10, ABC_CONST(0x000070FF70FF0000), "(!(!(!(ab)c)d)[ef])" },   //  436
+    { 6,  9, 14, ABC_CONST(0x00008F708F700000), "([(!(ab)c)d][ef])" },   //  437
+    { 6,  9, 13, ABC_CONST(0x000087FF87FF0000), "(!([(ab)c]d)[ef])" },   //  438
+    { 6, 11, 20, ABC_CONST(0x0000877887780000), "([(ab)cd][ef])" },   //  439
+    { 6,  9, 12, ABC_CONST(0x00009FFF9FFF0000), "(!([ab]cd)[ef])" },   //  440
+    { 6,  9, 11, ABC_CONST(0x000060FF60FF0000), "(!(!([ab]c)d)[ef])" },   //  441
+    { 6, 11, 17, ABC_CONST(0x00009F609F600000), "([([ab]c)d][ef])" },   //  442
+    { 6, 11, 16, ABC_CONST(0x000069FF69FF0000), "(!([abc]d)[ef])" },   //  443
+    { 6, 13, 26, ABC_CONST(0x0000699669960000), "([abcd][ef])" },   //  444
+    { 6,  8, 10, ABC_CONST(0x000035FF35FF0000), "(!(<abc>d)[ef])" },   //  445
+    { 6, 10, 14, ABC_CONST(0x000035CA35CA0000), "([<abc>d][ef])" },   //  446
+    { 6,  7, 10, ABC_CONST(0x0000F888F8880000), "(!(!(ab)!(cd))[ef])" },   //  447
+    { 6,  9, 15, ABC_CONST(0x0000788878880000), "([(ab)(cd)][ef])" },   //  448
+    { 6,  9, 16, ABC_CONST(0x0000877787770000), "(![(ab)(cd)][ef])" },   //  449
+    { 6,  9, 12, ABC_CONST(0x0000F999F9990000), "(!([ab]!(cd))[ef])" },   //  450
+    { 6, 11, 14, ABC_CONST(0x0000066006600000), "([ab][cd][ef])" },   //  451
+    { 6, 11, 14, ABC_CONST(0x0000F99FF99F0000), "(!([ab][cd])[ef])" },   //  452
+    { 6,  8, 11, ABC_CONST(0x0000CAAACAAA0000), "(<ab(cd)>[ef])" },   //  453
+    { 6, 10, 14, ABC_CONST(0x0000ACCAACCA0000), "(<ab[cd]>[ef])" },   //  454
+    { 6,  8,  9, ABC_CONST(0x0000F088F0880000), "(<(ab)cd>[ef])" },   //  455
+    { 6,  8, 10, ABC_CONST(0x00000F770F770000), "(!<(ab)cd>[ef])" },   //  456
+    { 6, 10, 11, ABC_CONST(0x0000F066F0660000), "(<[ab]cd>[ef])" },   //  457
+    { 6,  5, 11, ABC_CONST(0x007F7F7F7F7F7F7F), "(!(abc)!(def))" },   //  458
+    { 6,  7, 16, ABC_CONST(0x7F80808080808080), "[(abc)(def)]" },   //  459
+    { 6,  5,  9, ABC_CONST(0x008F8F8F8F8F8F8F), "(!(!(ab)c)!(def))" },   //  460
+    { 6,  7, 16, ABC_CONST(0x8F70707070707070), "[(!(ab)c)(def)]" },   //  461
+    { 6,  7, 13, ABC_CONST(0x0078787878787878), "([(ab)c]!(def))" },   //  462
+    { 6,  7, 12, ABC_CONST(0x009F9F9F9F9F9F9F), "(!([ab]c)!(def))" },   //  463
+    { 6,  9, 20, ABC_CONST(0x9F60606060606060), "[([ab]c)(def)]" },   //  464
+    { 6,  9, 17, ABC_CONST(0x0096969696969696), "([abc]!(def))" },   //  465
+    { 6,  6,  9, ABC_CONST(0x00CACACACACACACA), "(<abc>!(def))" },   //  466
+    { 6,  8, 16, ABC_CONST(0x35CACACACACACACA), "[<abc>(def)]" },   //  467
+    { 6,  5,  8, ABC_CONST(0x8F0000008F8F8F8F), "(!(!(ab)c)!(!(de)f))" },   //  468
+    { 6,  7, 16, ABC_CONST(0x708F8F8F70707070), "[(!(ab)c)(!(de)f)]" },   //  469
+    { 6,  7, 11, ABC_CONST(0x7800000078787878), "([(ab)c]!(!(de)f))" },   //  470
+    { 6,  7, 10, ABC_CONST(0x9F0000009F9F9F9F), "(!([ab]c)!(!(de)f))" },   //  471
+    { 6,  9, 20, ABC_CONST(0x609F9F9F60606060), "[([ab]c)(!(de)f)]" },   //  472
+    { 6,  9, 14, ABC_CONST(0x9600000096969696), "([abc]!(!(de)f))" },   //  473
+    { 6,  6,  8, ABC_CONST(0xCA000000CACACACA), "(<abc>!(!(de)f))" },   //  474
+    { 6,  8, 16, ABC_CONST(0xCA353535CACACACA), "[<abc>(!(de)f)]" },   //  475
+    { 6,  9, 15, ABC_CONST(0x0078787878000000), "([(ab)c][(de)f])" },   //  476
+    { 6,  9, 14, ABC_CONST(0x009F9F9F9F000000), "(!([ab]c)[(de)f])" },   //  477
+    { 6, 11, 19, ABC_CONST(0x0096969696000000), "([abc][(de)f])" },   //  478
+    { 6,  8, 11, ABC_CONST(0x00CACACACA000000), "(<abc>[(de)f])" },   //  479
+    { 6,  9, 13, ABC_CONST(0x9F00009F9F9F9F9F), "(!([ab]c)!([de]f))" },   //  480
+    { 6, 11, 25, ABC_CONST(0x609F9F6060606060), "[([ab]c)([de]f)]" },   //  481
+    { 6, 11, 18, ABC_CONST(0x9600009696969696), "([abc]!([de]f))" },   //  482
+    { 6,  8, 10, ABC_CONST(0xCA0000CACACACACA), "(<abc>!([de]f))" },   //  483
+    { 6, 10, 20, ABC_CONST(0xCA3535CACACACACA), "[<abc>([de]f)]" },   //  484
+    { 6, 13, 24, ABC_CONST(0x9600009600969600), "([abc][def])" },   //  485
+    { 6, 10, 14, ABC_CONST(0xCA0000CA00CACA00), "(<abc>[def])" },   //  486
+    { 6,  7,  8, ABC_CONST(0xCACA0000CA00CA00), "(<abc><def>)" },   //  487
+    { 6,  9, 16, ABC_CONST(0x3535CACA35CA35CA), "[<abc><def>]" },   //  488
+    { 6,  6, 10, ABC_CONST(0xCAAAAAAAAAAAAAAA), "<ab(cdef)>" },   //  489
+    { 6,  6, 10, ABC_CONST(0xACCCCCCCAAAAAAAA), "<ab(!(cde)f)>" },   //  490
+    { 6,  8, 16, ABC_CONST(0xACCCCCCCCAAAAAAA), "<ab[(cde)f]>" },   //  491
+    { 6,  6, 10, ABC_CONST(0xACCCAAAAAAAAAAAA), "<ab(!(cd)ef)>" },   //  492
+    { 6,  6, 10, ABC_CONST(0xCAAACCCCAAAAAAAA), "<ab(!(!(cd)e)f)>" },   //  493
+    { 6,  8, 16, ABC_CONST(0xCAAACCCCACCCAAAA), "<ab[(!(cd)e)f]>" },   //  494
+    { 6,  8, 14, ABC_CONST(0xACCCCAAAAAAAAAAA), "<ab([(cd)e]f)>" },   //  495
+    { 6, 10, 24, ABC_CONST(0xCAAAACCCACCCCAAA), "<ab[(cd)ef]>" },   //  496
+    { 6,  8, 12, ABC_CONST(0xACCAAAAAAAAAAAAA), "<ab([cd]ef)>" },   //  497
+    { 6,  8, 12, ABC_CONST(0xCAACCCCCAAAAAAAA), "<ab(!([cd]e)f)>" },   //  498
+    { 6, 10, 20, ABC_CONST(0xCAACCCCCACCAAAAA), "<ab[([cd]e)f]>" },   //  499
+    { 6, 10, 18, ABC_CONST(0xCAACACCAAAAAAAAA), "<ab([cde]f)>" },   //  500
+    { 6, 12, 32, ABC_CONST(0xACCACAACCAACACCA), "<ab[cdef]>" },   //  501
+    { 6,  7, 10, ABC_CONST(0xCCAACACAAAAAAAAA), "<ab(<cde>f)>" },   //  502
+    { 6,  9, 16, ABC_CONST(0xAACCACACCCAACACA), "<ab[<cde>f]>" },   //  503
+    { 6,  6, 12, ABC_CONST(0xAAAAACCCACCCACCC), "<ab(!(cd)!(ef))>" },   //  504
+    { 6,  8, 18, ABC_CONST(0xACCCCAAACAAACAAA), "<ab[(cd)(ef)]>" },   //  505
+    { 6,  8, 14, ABC_CONST(0xAAAAACCAACCAACCA), "<ab([cd]!(ef))>" },   //  506
+    { 6, 10, 16, ABC_CONST(0xAAAAACCAACCAAAAA), "<ab([cd][ef])>" },   //  507
+    { 6,  7, 12, ABC_CONST(0xCCAACACACACACACA), "<ab<cd(ef)>>" },   //  508
+    { 6,  9, 16, ABC_CONST(0xCACACCAACCAACACA), "<ab<cd[ef]>>" },   //  509
+    { 6,  7, 10, ABC_CONST(0xCCCCAAAACAAACAAA), "<ab<(cd)ef>>" },   //  510
+    { 6,  9, 12, ABC_CONST(0xCCCCAAAAACCAACCA), "<ab<[cd]ef>>" },   //  511
+    { 6,  6,  9, ABC_CONST(0xC0AAAAAAAAAAAAAA), "<a(bc)(def)>" },   //  512
+    { 6,  6, 10, ABC_CONST(0xAAC0C0C0AAAAAAAA), "<a(bc)(!(de)f)>" },   //  513
+    { 6,  8, 12, ABC_CONST(0xAAC0C0AAAAAAAAAA), "<a(bc)([de]f)>" },   //  514
+    { 6,  8, 10, ABC_CONST(0x3CAAAAAAAAAAAAAA), "<a[bc](def)>" },   //  515
+    { 6,  8, 12, ABC_CONST(0xAA3C3C3CAAAAAAAA), "<a[bc](!(de)f)>" },   //  516
+    { 6, 10, 14, ABC_CONST(0xAA3C3CAAAAAAAAAA), "<a[bc]([de]f)>" },   //  517
+    { 6,  6,  8, ABC_CONST(0xC000AAAAAAAAAAAA), "<a(bcd)(ef)>" },   //  518
+    { 6,  6,  8, ABC_CONST(0x3F00AAAAAAAAAAAA), "<a(!(bc)d)(ef)>" },   //  519
+    { 6,  8, 10, ABC_CONST(0x3FC0AAAAAAAAAAAA), "<a[(bc)d](ef)>" },   //  520
+    { 6,  8,  9, ABC_CONST(0x3C00AAAAAAAAAAAA), "<a([bc]d)(ef)>" },   //  521
+    { 6, 10, 12, ABC_CONST(0xC33CAAAAAAAAAAAA), "<a[bcd](ef)>" },   //  522
+    { 6,  7,  8, ABC_CONST(0xF0CCAAAAAAAAAAAA), "<a<bcd>(ef)>" },   //  523
+    { 6,  6, 11, ABC_CONST(0xF088888888888888), "<(ab)c(def)>" },   //  524
+    { 6,  6, 10, ABC_CONST(0x88F0F0F088888888), "<(ab)c(!(de)f)>" },   //  525
+    { 6,  8, 15, ABC_CONST(0x88F0F0F0F0888888), "<(ab)c[(de)f]>" },   //  526
+    { 6,  8, 13, ABC_CONST(0x88F0F08888888888), "<(ab)c([de]f)>" },   //  527
+    { 6, 10, 20, ABC_CONST(0xF08888F088F0F088), "<(ab)c[def]>" },   //  528
+    { 6,  7, 10, ABC_CONST(0xF0F08888F088F088), "<(ab)c<def>>" },   //  529
+    { 6,  8, 14, ABC_CONST(0xF066666666666666), "<[ab]c(def)>" },   //  530
+    { 6,  8, 12, ABC_CONST(0x66F0F0F066666666), "<[ab]c(!(de)f)>" },   //  531
+    { 6, 10, 18, ABC_CONST(0x66F0F0F0F0666666), "<[ab]c[(de)f]>" },   //  532
+    { 6, 10, 16, ABC_CONST(0x66F0F06666666666), "<[ab]c([de]f)>" },   //  533
+    { 6, 12, 24, ABC_CONST(0xF06666F066F0F066), "<[ab]c[def]>" },   //  534
+    { 6,  9, 12, ABC_CONST(0xF0F06666F066F066), "<[ab]c<def>>" },   //  535
+    { 6,  6,  9, ABC_CONST(0xF000888888888888), "<(ab)(cd)(ef)>" },   //  536
+    { 6,  6,  9, ABC_CONST(0xF000777777777777), "<!(ab)(cd)(ef)>" },   //  537
+    { 6,  8, 12, ABC_CONST(0x8888F000F0008888), "<(ab)(cd)[ef]>" },   //  538
+    { 6,  8, 12, ABC_CONST(0x7777F000F0007777), "<!(ab)(cd)[ef]>" },   //  539
+    { 6,  8, 10, ABC_CONST(0x0FF0888888888888), "<(ab)[cd](ef)>" },   //  540
+    { 6,  8, 11, ABC_CONST(0xF000666666666666), "<[ab](cd)(ef)>" },   //  541
+    { 6, 10, 14, ABC_CONST(0x6666F000F0006666), "<[ab](cd)[ef]>" },   //  542
+    { 6, 10, 12, ABC_CONST(0x0FF0666666666666), "<[ab][cd](ef)>" },   //  543
+    { 6, 12, 16, ABC_CONST(0x66660FF00FF06666), "<[ab][cd][ef]>" },   //  544
+    { 6,  6, 10, ABC_CONST(0xFF00808080808080), "<(abc)d(ef)>" },   //  545
+    { 6,  8, 12, ABC_CONST(0x8080FF00FF008080), "<(abc)d[ef]>" },   //  546
+    { 6,  6, 10, ABC_CONST(0xFF00707070707070), "<(!(ab)c)d(ef)>" },   //  547
+    { 6,  8, 12, ABC_CONST(0x7070FF00FF007070), "<(!(ab)c)d[ef]>" },   //  548
+    { 6,  8, 14, ABC_CONST(0xFF00787878787878), "<[(ab)c]d(ef)>" },   //  549
+    { 6, 10, 16, ABC_CONST(0x7878FF00FF007878), "<[(ab)c]d[ef]>" },   //  550
+    { 6,  8, 12, ABC_CONST(0xFF00606060606060), "<([ab]c)d(ef)>" },   //  551
+    { 6, 10, 14, ABC_CONST(0x6060FF00FF006060), "<([ab]c)d[ef]>" },   //  552
+    { 6, 10, 18, ABC_CONST(0xFF00969696969696), "<[abc]d(ef)>" },   //  553
+    { 6, 12, 20, ABC_CONST(0x9696FF00FF009696), "<[abc]d[ef]>" },   //  554
+    { 6,  7, 10, ABC_CONST(0xFF00CACACACACACA), "<<abc>d(ef)>" },   //  555
+    { 6,  9, 12, ABC_CONST(0xCACAFF00FF00CACA), "<<abc>d[ef]>" },   //  556
+    { 6,  6,  7, ABC_CONST(0xFF00000080808080), "<(abc)(de)f>" },   //  557
+    { 6,  6,  7, ABC_CONST(0xFF0000007F7F7F7F), "<!(abc)(de)f>" },   //  558
+    { 6,  8,  8, ABC_CONST(0x00FFFF0080808080), "<(abc)[de]f>" },   //  559
+    { 6,  6,  7, ABC_CONST(0xFF00000070707070), "<(!(ab)c)(de)f>" },   //  560
+    { 6,  6,  7, ABC_CONST(0xFF0000008F8F8F8F), "<!(!(ab)c)(de)f>" },   //  561
+    { 6,  8,  8, ABC_CONST(0x00FFFF0070707070), "<(!(ab)c)[de]f>" },   //  562
+    { 6,  8,  9, ABC_CONST(0xFF00000078787878), "<[(ab)c](de)f>" },   //  563
+    { 6, 10, 10, ABC_CONST(0x00FFFF0078787878), "<[(ab)c][de]f>" },   //  564
+    { 6,  8,  8, ABC_CONST(0xFF00000060606060), "<([ab]c)(de)f>" },   //  565
+    { 6,  8,  8, ABC_CONST(0xFF0000009F9F9F9F), "<!([ab]c)(de)f>" },   //  566
+    { 6, 10,  9, ABC_CONST(0x00FFFF0060606060), "<([ab]c)[de]f>" },   //  567
+    { 6, 10, 11, ABC_CONST(0xFF00000096969696), "<[abc](de)f>" },   //  568
+    { 6, 12, 12, ABC_CONST(0x00FFFF0096969696), "<[abc][de]f>" },   //  569
+    { 6,  7,  7, ABC_CONST(0xFF000000CACACACA), "<<abc>(de)f>" },   //  570
+    { 6,  9,  8, ABC_CONST(0x00FFFF00CACACACA), "<<abc>[de]f>" },   //  571
+    { 6,  6,  7, ABC_CONST(0xFFFF000080008000), "<(abcd)ef>" },   //  572
+    { 6,  6,  7, ABC_CONST(0xFFFF00007F007F00), "<(!(abc)d)ef>" },   //  573
+    { 6,  8, 10, ABC_CONST(0xFFFF00007F807F80), "<[(abc)d]ef>" },   //  574
+    { 6,  6,  7, ABC_CONST(0xFFFF000070007000), "<(!(ab)cd)ef>" },   //  575
+    { 6,  6,  7, ABC_CONST(0xFFFF00008F008F00), "<(!(!(ab)c)d)ef>" },   //  576
+    { 6,  8, 10, ABC_CONST(0xFFFF00008F708F70), "<[(!(ab)c)d]ef>" },   //  577
+    { 6,  8,  9, ABC_CONST(0xFFFF000078007800), "<([(ab)c]d)ef>" },   //  578
+    { 6, 10, 14, ABC_CONST(0xFFFF000087788778), "<[(ab)cd]ef>" },   //  579
+    { 6,  8,  8, ABC_CONST(0xFFFF000060006000), "<([ab]cd)ef>" },   //  580
+    { 6,  8,  8, ABC_CONST(0xFFFF00009F009F00), "<(!([ab]c)d)ef>" },   //  581
+    { 6, 10, 12, ABC_CONST(0xFFFF00009F609F60), "<[([ab]c)d]ef>" },   //  582
+    { 6, 10, 11, ABC_CONST(0xFFFF000096009600), "<([abc]d)ef>" },   //  583
+    { 6, 12, 18, ABC_CONST(0xFFFF000069966996), "<[abcd]ef>" },   //  584
+    { 6,  7,  7, ABC_CONST(0xFFFF0000CA00CA00), "<(<abc>d)ef>" },   //  585
+    { 6,  9, 10, ABC_CONST(0xFFFF000035CA35CA), "<[<abc>d]ef>" },   //  586
+    { 6,  6,  8, ABC_CONST(0xFFFF000007770777), "<(!(ab)!(cd))ef>" },   //  587
+    { 6,  8, 11, ABC_CONST(0xFFFF000078887888), "<[(ab)(cd)]ef>" },   //  588
+    { 6,  8,  9, ABC_CONST(0xFFFF000006660666), "<([ab]!(cd))ef>" },   //  589
+    { 6, 10, 10, ABC_CONST(0xFFFF000006600660), "<([ab][cd])ef>" },   //  590
+    { 6,  7,  8, ABC_CONST(0xFFFF0000CAAACAAA), "<<ab(cd)>ef>" },   //  591
+    { 6,  9, 10, ABC_CONST(0xFFFF0000ACCAACCA), "<<ab[cd]>ef>" },   //  592
+    { 6,  7,  7, ABC_CONST(0xFFFF0000F088F088), "<<(ab)cd>ef>" },   //  593
+    { 6,  9,  8, ABC_CONST(0xFFFF0000F066F066), "<<[ab]cd>ef>" }    //  594
+};
+
+struct Sdm_Man_t_
+{
+    Sdm_Dsd_t *      pDsd6;                    // NPN class information
+    Hsh_IntMan_t *   pHash;                    // maps DSD functions into NPN classes
+    Vec_Int_t *      vConfgRes;                // configurations
+    Vec_Wrd_t *      vPerm6;                   // permutations of DSD classes
+    Vec_Int_t *      vMap2Perm;                // maps number into its permutation
+    char             Perm6[720][6];            // permutations
+    int              nCountDsd[DSD_CLASS_NUM];
+    int              nNonDsd;
+    int              nAllDsd;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sdm_ManPrintDsdStats( Sdm_Man_t * p, int fVerbose )
+{
+    int i, Absent = 0;
+    for ( i = 0; i < DSD_CLASS_NUM; i++ )
+    {
+        if ( p->nCountDsd[i] == 0 )
+        {
+            Absent++;
+            continue;
+        }
+        if ( fVerbose )
+        {
+            printf( "%5d  :  ", i );
+            printf( "%-20s   ", p->pDsd6[i].pStr );
+            printf( "%8d ",     p->nCountDsd[i] );
+            printf( "\n" );
+        }
+    }
+    printf( "Unused classes = %d (%.2f %%).  ", Absent, 100.0 * Absent / DSD_CLASS_NUM );
+    printf( "Non-DSD cuts = %d (%.2f %%).  ",   p->nNonDsd, 100.0 * p->nNonDsd / Abc_MaxInt(1, p->nAllDsd) );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hsh_IntMan_t * Sdm_ManBuildHashTable( Vec_Int_t ** pvConfgRes ) 
+{
+    FILE * pFile;
+    char * pFileName = "dsdfuncs6.dat";
+    int RetValue, size = Extra_FileSize( pFileName ) / 12;  // 2866420
+    Vec_Wrd_t * vTruthRes = Vec_WrdAlloc( size );
+    Vec_Int_t * vConfgRes = Vec_IntAlloc( size );
+    Hsh_IntMan_t * pHash;
+
+    pFile = fopen( pFileName, "rb" );
+    RetValue = fread( Vec_WrdArray(vTruthRes), sizeof(word), size, pFile );
+    RetValue = fread( Vec_IntArray(vConfgRes), sizeof(int), size, pFile );
+    vTruthRes->nSize = size;
+    vConfgRes->nSize = size;
+    // create hash table
+    pHash = Hsh_WrdManHashArrayStart( vTruthRes, 1 );
+    // cleanup
+    if ( pvConfgRes )
+        *pvConfgRes = vConfgRes;
+    else
+        Vec_IntFree( vConfgRes );
+    Vec_WrdFree( vTruthRes );
+//    Hsh_IntManStop( pHash );
+    return pHash;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sdm_ManPrecomputePerms( Sdm_Man_t * p )
+{
+    int nVars = 6;
+    // 0(1:1) 1(2:1) 2(4:2) 3(10:6) 4(33:23) 5(131:98) 6(595:464)
+    int nClasses[7] = { 1, 2, 4, 10, 33, 131, 595 };
+    int nPerms = Extra_Factorial( nVars );
+//    int nSwaps = (1 << nVars);
+    int * pComp, * pPerm;
+    int i, k, x, One, OneCopy, Num;
+    Vec_Int_t * vVars;
+    abctime clk = Abc_Clock();
+    assert( p->pDsd6 == NULL );
+    p->pDsd6 = s_DsdClass6;
+    // precompute schedules
+    pComp = Extra_GreyCodeSchedule( nVars );
+    pPerm = Extra_PermSchedule( nVars );
+    // map numbers into perms
+    p->vMap2Perm = Vec_IntStartFull( (1<<(3*nVars)) );
+    // store permutations
+    One = 0;
+    for ( x = 0; x < nVars; x++ )
+    {
+        p->Perm6[0][x] = (char)x;
+        One |= (x << (3*x));
+    }
+//    Vec_IntWriteEntry( p->vMap2Perm, One, 0 );
+    OneCopy = One;
+    for ( k = 0; k < nPerms; k++ )
+    {
+        if ( k > 0 )
+        for ( x = 0; x < nVars; x++ )
+            p->Perm6[k][x] = p->Perm6[k-1][x];
+        ABC_SWAP( char, p->Perm6[k][pPerm[k]], p->Perm6[k][pPerm[k]+1] );
+
+        Num = ( (One >> (3*(pPerm[k]  ))) ^ (One >> (3*(pPerm[k]+1))) ) & 7;
+        One ^=  (Num << (3*(pPerm[k]  )));
+        One ^=  (Num << (3*(pPerm[k]+1)));
+
+        Vec_IntWriteEntry( p->vMap2Perm, One, k );
+        
+//        Sdm_ManPrintPerm( One );
+//        for ( x = 0; x < nVars; x++ )
+//            printf( "%d ", p->Perm6[k][x] );
+//        printf( "\n" );
+    }
+    assert( OneCopy == One );
+    // fill in the gaps
+    vVars = Vec_IntAlloc( 6 );
+    Vec_IntForEachEntry( p->vMap2Perm, Num, i )
+    {
+        // mark used variables
+        int Count = 0;
+        One = i;
+        Vec_IntFill( vVars, 6, 0 );
+        for ( k = 0; k < nVars; k++ )
+        {
+            int iVar = ((One >> (3*k)) & 7);
+            if ( iVar >= nVars && iVar < 7 )
+                break;
+            if ( iVar != 7 )
+            {
+                if ( Vec_IntEntry( vVars, iVar ) == 1 )
+                    break;
+                Vec_IntWriteEntry( vVars, iVar, 1 );
+                Count++;
+            }
+        }
+        // skip ones with dups and complete
+        if ( k < nVars || Count == nVars )
+            continue;
+        // find unused variables
+        for ( x = k = 0; k < 6; k++ )
+            if ( Vec_IntEntry(vVars, k) == 0 )
+                Vec_IntWriteEntry( vVars, x++, k );
+        Vec_IntShrink( vVars, x );
+        // fill in used variables
+        x = 0;
+        for ( k = 0; k < nVars; k++ )
+        {
+            int iVar = ((One >> (3*k)) & 7);
+            if ( iVar == 7 )
+                One ^= ((Vec_IntEntry(vVars, x++) ^ 7) << (3*k));
+        }
+        assert( x == Vec_IntSize(vVars) );
+        // save this one
+        assert( Vec_IntEntry( p->vMap2Perm, One ) != -1 );
+        Vec_IntWriteEntry( p->vMap2Perm, i, Vec_IntEntry(p->vMap2Perm, One) );
+/*
+        // mapping
+        Sdm_ManPrintPerm( i );
+        printf( "->  " );
+        Sdm_ManPrintPerm( One );
+        printf( "\n" );
+*/
+    }
+    Vec_IntFree( vVars );
+
+    // store permuted truth tables
+    assert( p->vPerm6 == NULL );
+    p->vPerm6 = Vec_WrdAlloc( nPerms * DSD_CLASS_NUM );
+    for ( i = 0; i < nClasses[nVars]; i++ )
+    {
+        word uTruth = s_DsdClass6[i].uTruth;
+        for ( k = 0; k < nPerms; k++ )
+        {
+            uTruth = Abc_Tt6SwapAdjacent( uTruth, pPerm[k] );
+            Vec_WrdPush( p->vPerm6, uTruth );
+        }
+        assert( uTruth == s_DsdClass6[i].uTruth );
+    }
+    ABC_FREE( pPerm );
+    ABC_FREE( pComp );
+    // build hash table
+    p->pHash = Sdm_ManBuildHashTable( &p->vConfgRes );
+    Abc_PrintTime( 1, "Setting up DSD information", Abc_Clock() - clk );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sdm_ManPrintPerm( unsigned s )
+{
+    int i;
+    for ( i = 0; i < 6; i++ )
+        printf( "%d ", (s >> (3*i)) & 7 );
+    printf( "  " );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks hash table for DSD class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sdm_ManCheckDsd6( Sdm_Man_t * p, word t )
+{
+    int fCompl, Entry, Config;
+    if ( (fCompl = (t & 1)) )
+        t = ~t;
+    Entry = *Hsh_IntManLookup( p->pHash, (unsigned *)&t );
+    if ( Entry == -1 )
+        return -1;
+    Config = Vec_IntEntry( p->vConfgRes, Entry );
+    if ( fCompl )
+        Config ^= (1 << 16);
+    return Config;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sdm_ManComputeFunc( Sdm_Man_t * p, int iDsdLit0, int iDsdLit1, int * pCut, int uMask, int fXor )
+{
+//    int fVerbose = 0;
+    int i, Config, iClass, fCompl, Res;
+    int PermMask = uMask & 0x3FFFF;
+    int ComplMask = uMask >> 18;
+    word Truth0, Truth1p, t0, t1, t;
+    p->nAllDsd++;
+
+    assert( uMask > 1 );
+    assert( iDsdLit0 < DSD_CLASS_NUM * 2 );
+    assert( iDsdLit1 < DSD_CLASS_NUM * 2 );
+    Truth0  = p->pDsd6[Abc_Lit2Var(iDsdLit0)].uTruth;
+    Truth1p = Vec_WrdEntry( p->vPerm6, Abc_Lit2Var(iDsdLit1) * 720 + Vec_IntEntry(p->vMap2Perm, PermMask ) );
+    if ( ComplMask )
+        for ( i = 0; i < 6; i++ )
+            if ( (ComplMask >> i) & 1 )
+                Truth1p = Abc_Tt6Flip( Truth1p, i );            
+    t0 = Abc_LitIsCompl(iDsdLit0) ? ~Truth0  : Truth0;
+    t1 = Abc_LitIsCompl(iDsdLit1) ? ~Truth1p : Truth1p;
+    t = fXor ? t0 ^ t1 : t0 & t1;
+/*
+if ( fVerbose )
+{
+Sdm_ManPrintPerm( PermMask );                      printf( "\n" );
+Extra_PrintBinary( stdout, &ComplMask, 6 );        printf( "\n" );
+Kit_DsdPrintFromTruth( (unsigned *)&Truth0, 6 );   printf( "\n" );
+Kit_DsdPrintFromTruth( (unsigned *)&Truth1p, 6 );  printf( "\n" );
+Kit_DsdPrintFromTruth( (unsigned *)&t, 6 );        printf( "\n" );
+}
+*/
+    // find configuration
+    Config = Sdm_ManCheckDsd6( p, t );
+    if ( Config == -1 )
+    {
+        p->nNonDsd++;
+        return -1;
+    }
+
+    // get the class
+    iClass = Config >> 17;
+    fCompl = (Config >> 16) & 1;
+    Config &= 0xFFFF;
+
+    // set the function
+    Res = Abc_Var2Lit( iClass, fCompl );
+
+    // update cut
+    assert( (Config >> 6) < 720 );
+    if ( pCut )
+    {
+        int pLeavesNew[6] = { -1, -1, -1, -1, -1, -1 };
+        assert( pCut[0] <= 6 );
+        for ( i = 0; i < pCut[0]; i++ )
+            pLeavesNew[(int)(p->Perm6[Config >> 6][i])] = Abc_LitNotCond( pCut[i+1], (Config >> i) & 1 );
+        pCut[0] = p->pDsd6[iClass].nVars;
+        for ( i = 0; i < pCut[0]; i++ )
+            assert( pLeavesNew[i] != -1 );
+        for ( i = 0; i < pCut[0]; i++ )
+            pCut[i+1] = pLeavesNew[i];
+    }
+    assert( iClass < DSD_CLASS_NUM );
+    p->nCountDsd[iClass]++;
+    return Res;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sdm_ManReadDsdVarNum( Sdm_Man_t * p, int iDsd )
+{
+    return p->pDsd6[iDsd].nVars;
+}
+int Sdm_ManReadDsdAndNum( Sdm_Man_t * p, int iDsd )
+{
+    return p->pDsd6[iDsd].nAnds;
+}
+int Sdm_ManReadDsdClauseNum( Sdm_Man_t * p, int iDsd )
+{
+    return p->pDsd6[iDsd].nClauses;
+}
+word Sdm_ManReadDsdTruth( Sdm_Man_t * p, int iDsd )
+{
+    return p->pDsd6[iDsd].uTruth;
+}
+char * Sdm_ManReadDsdStr( Sdm_Man_t * p, int iDsd )
+{
+    return p->pDsd6[iDsd].pStr;
+}
+void Sdm_ManReadCnfCosts( Sdm_Man_t * p, int * pCosts, int nCosts )
+{
+    int i;
+    assert( nCosts == DSD_CLASS_NUM );
+    pCosts[0] = pCosts[1] = 0;
+    for ( i = 2; i < DSD_CLASS_NUM; i++ )
+        pCosts[i] = Sdm_ManReadDsdClauseNum( p, i );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Manager manipulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Sdm_Man_t * Sdm_ManAlloc()
+{
+    Sdm_Man_t * p;
+    p = ABC_CALLOC( Sdm_Man_t, 1 );
+    Sdm_ManPrecomputePerms( p );
+    return p;
+}
+void Sdm_ManFree( Sdm_Man_t * p )
+{
+    Vec_WrdFree( p->vPerm6 );
+    Vec_IntFree( p->vMap2Perm );
+    Vec_IntFree( p->vConfgRes );
+    Vec_IntFree( p->pHash->vData );
+    Hsh_IntManStop( p->pHash );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Sdm_Man_t * s_SdmMan = NULL;
+Sdm_Man_t * Sdm_ManRead()
+{
+    if ( s_SdmMan == NULL )
+        s_SdmMan = Sdm_ManAlloc();
+    memset( s_SdmMan->nCountDsd, 0, sizeof(int) * DSD_CLASS_NUM );
+    return s_SdmMan;
+}
+void Sdm_ManQuit()
+{
+    if ( s_SdmMan != NULL )
+        Sdm_ManFree( s_SdmMan );
+    s_SdmMan = NULL;
+}
+int Sdm_ManCanRead()
+{
+    char * pFileName = "dsdfuncs6.dat";
+    FILE * pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+        return 0;
+    fclose( pFile );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sdm_ManTest()
+{
+    Sdm_Man_t * p;
+    int iDsd0 = 4;
+    int iDsd1 = 6;
+    int iDsd;
+    int uMask = 0x3FFFF ^ ((7 ^ 0) << 6) ^ ((7 ^ 1) << 9);
+    int pCut[7] = { 4, 10, 20, 30, 40 };
+//    Sdm_ManPrintPerm( uMask );
+    p = Sdm_ManAlloc();
+    iDsd = Sdm_ManComputeFunc( p, iDsd0, iDsd1, pCut, uMask, 0 );
+    Sdm_ManFree( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+void Sdm_ManCompareCnfSizes()
+{
+    Vec_Int_t * vMemory;
+    word uTruth;
+    int i, nSop0, nSop1, nVars, nCla, RetValue;
+    vMemory = Vec_IntAlloc( 1 << 16 );
+    for ( i = 1; i < DSD_CLASS_NUM; i++ )
+    {
+        uTruth = Sdm_ManReadDsdTruth( s_SdmMan, i );
+        nVars = Sdm_ManReadDsdVarNum( s_SdmMan, i );
+        nCla = Sdm_ManReadDsdClauseNum( s_SdmMan, i );
+
+        RetValue = Kit_TruthIsop( &uTruth, nVars, vMemory, 0 );
+        nSop0 = Vec_IntSize(vMemory);
+
+        uTruth = ~uTruth;
+        RetValue = Kit_TruthIsop( &uTruth, nVars, vMemory, 0 );
+        nSop1 = Vec_IntSize(vMemory);
+
+        if ( nSop0 + nSop1 != nCla )
+            printf( "Class %4d : %d + %d != %d\n", i, nSop0, nSop1, nCla );
+        else
+            printf( "Class %4d : %d + %d == %d\n", i, nSop0, nSop1, nCla );
+    }
+    Vec_IntFree( vMemory );
+}
+*/
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collect DSD divisors of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sdm_ManDivCollect_rec( word t, Vec_Wrd_t ** pvDivs )
+{
+    int i, Config, Counter = 0;
+    // check if function is decomposable
+    Config = Sdm_ManCheckDsd6( s_SdmMan, t );
+    if ( Config != -1 && (Config >> 17) < 2 )
+        return;
+    for ( i = 0; i < 6; i++ )
+    {
+        if ( !Abc_Tt6HasVar( t, i ) )
+            continue;
+        Sdm_ManDivCollect_rec( Abc_Tt6Cofactor0(t, i), pvDivs );
+        Sdm_ManDivCollect_rec( Abc_Tt6Cofactor1(t, i), pvDivs );
+        Counter++;
+    }
+    if ( Config != -1 && Counter >= 2 && Counter <= 4 )
+    {
+        Vec_WrdPush( pvDivs[Counter], (t & 1) ? ~t : t );
+//        Kit_DsdPrintFromTruth( (unsigned *)&t, 6 ); printf( "\n" );
+    }
+}
+void Sdm_ManDivTest()
+{
+//    word u, t0, t1, t = ABC_CONST(0xB0F0BBFFB0F0BAFE);
+//    word u, t0, t1, t = ABC_CONST(0x3F1F3F13FFDFFFD3);
+    word u, t0, t1, t = ABC_CONST(0x3F3FFFFF37003700);
+    Rsb_Man_t * pManRsb = Rsb_ManAlloc( 6, 200, 3, 1 );
+    Vec_Wrd_t * pvDivs[7] = { NULL };
+    Vec_Wrd_t * vDivs = Vec_WrdAlloc( 100 );
+    int i, RetValue;
+
+    // collect divisors
+    for ( i = 2; i <= 4; i++ )
+        pvDivs[i] = Vec_WrdAlloc( 100 );
+    Sdm_ManDivCollect_rec( t, pvDivs );
+    for ( i = 2; i <= 4; i++ )
+        Vec_WrdUniqify( pvDivs[i] );
+
+    // prepare the set
+    vDivs = Vec_WrdAlloc( 100 );
+    for ( i = 0; i < 6; i++ )
+        Vec_WrdPush( vDivs, s_Truths6[i] );
+    for ( i = 2; i <= 4; i++ )
+        Vec_WrdAppend( vDivs, pvDivs[i] );
+    for ( i = 2; i <= 4; i++ )
+        Vec_WrdFree( pvDivs[i] );
+
+    Vec_WrdForEachEntry( vDivs, u, i )
+    {
+        printf( "%2d : ", i );
+//        Kit_DsdPrintFromTruth( (unsigned *)&u, 6 ); 
+        printf( "\n" );
+    }
+
+    RetValue = Rsb_ManPerformResub6( pManRsb, 6, t, vDivs, &t0, &t1, 1 );
+    if ( RetValue )
+    {
+//        Kit_DsdPrintFromTruth( (unsigned *)&t0, 6 ); printf( "\n" );
+//        Kit_DsdPrintFromTruth( (unsigned *)&t1, 6 ); printf( "\n" );
+        printf( "Decomposition exits.\n" );
+    }
+
+
+    Vec_WrdFree( vDivs );
+    Rsb_ManFree( pManRsb );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Generation of node test.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+#include "bool/kit/kit.h"
+void Sdm_ManNodeGenTest()
+{
+    extern Kit_Graph_t * Kit_TruthToGraph( unsigned * pTruth, int nVars, Vec_Int_t * vMemory );
+    Sdm_Man_t * p = s_SdmMan;
+    Vec_Int_t * vCover;
+    Kit_Graph_t * pGraph;
+    int i;
+    vCover = Vec_IntAlloc( 1 << 16 );
+    for ( i = 2; i < DSD_CLASS_NUM; i++ )
+    {
+        pGraph = Kit_TruthToGraph( (unsigned *)&p->pDsd6[i].uTruth, p->pDsd6[i].nVars, vCover );
+        printf( "%d %s %d %d   ", i, p->pDsd6[i].pStr, Kit_GraphNodeNum(pGraph), p->pDsd6[i].nAnds );
+    }
+    printf( "\n" );
+}
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraUtilEnum.c b/abc-build/src/misc/extra/extraUtilEnum.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraUtilEnum.c
@@ -0,0 +1,680 @@
+/**CFile****************************************************************
+
+  FileName    [extraUtilEnum.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [extra]
+
+  Synopsis    [Function enumeration.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: extraUtilEnum.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "misc/vec/vec.h"
+#include "misc/vec/vecHsh.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_GetFirst( int * pnVars, int * pnMints, int * pnFuncs, unsigned * pVars, unsigned * pMints, unsigned * pFuncs )
+{
+    int nVars  = 8;
+    int nMints = 16;
+    int nFuncs = 8;
+    char * pMintStrs[16] = { 
+        "1-1-1-1-",
+        "1-1--11-",
+        "1-1-1--1",
+        "1-1--1-1",
+
+        "-11-1-1-",
+        "-11--11-",
+        "-11-1--1",
+        "-11--1-1",
+
+        "1--11-1-",
+        "1--1-11-",
+        "1--11--1",
+        "1--1-1-1",
+
+        "-1-11-1-",
+        "-1-1-11-",
+        "-1-11--1",
+        "-1-1-1-1"
+    };
+    char * pFuncStrs[8] = { 
+        "1111101011111010",
+        "0000010100000101",
+        "1111110010101001",
+        "0000001101010110",
+        "1111111111001101",
+        "0000000000110010",
+        "1111111111111110",
+        "0000000000000001",
+    };
+    int i, k;
+    *pnVars  = nVars;
+    *pnMints = nMints;
+    *pnFuncs = nFuncs;
+    // extract mints
+    for ( i = 0; i < nMints; i++ )
+        for ( k = 0; k < nVars; k++ )
+            if ( pMintStrs[i][k] == '1' )
+                pMints[i] |= (1 << k), pVars[k] |= (1 << i);
+    // extract funcs
+    for ( i = 0; i < nFuncs; i++ )
+        for ( k = 0; k < nMints; k++ )
+            if ( pFuncStrs[i][k] == '1' )
+                pFuncs[i] |= (1 << k);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_GetSecond( int * pnVars, int * pnMints, int * pnFuncs, unsigned * pVars, unsigned * pMints, unsigned * pFuncs )
+{
+    int nVars  = 10;
+    int nMints = 32;
+    int nFuncs = 7;
+    char * pMintStrs[32] = { 
+        "1-1---1---",
+        "1-1----1--",
+        "1-1-----1-",
+        "1-1------1",
+
+        "1--1--1---",
+        "1--1---1--",
+        "1--1----1-",
+        "1--1-----1",
+
+        "1---1-1---",
+        "1---1--1--",
+        "1---1---1-",
+        "1---1----1",
+
+        "1----11---",
+        "1----1-1--",
+        "1----1--1-",
+        "1----1---1",
+
+
+        "-11---1---",
+        "-11----1--",
+        "-11-----1-",
+        "-11------1",
+
+        "-1-1--1---",
+        "-1-1---1--",
+        "-1-1----1-",
+        "-1-1-----1",
+
+        "-1--1-1---",
+        "-1--1--1--",
+        "-1--1---1-",
+        "-1--1----1",
+
+        "-1---11---",
+        "-1---1-1--",
+        "-1---1--1-",
+        "-1---1---1"
+    };
+    char * pFuncStrs[7] = { 
+        "11111110110010001110110010000000",
+        "00000001001101110001001101111111",
+        "10000001001001000001001001001000",
+        "01001000000100101000000100100100",
+        "00100100100000010100100000010010",
+        "00010010010010000010010010000001",
+        "11111111111111111111000000000000"
+    };
+    int i, k;
+    *pnVars  = nVars;
+    *pnMints = nMints;
+    *pnFuncs = nFuncs;
+    // extract mints
+    for ( i = 0; i < nMints; i++ )
+        for ( k = 0; k < nVars; k++ )
+            if ( pMintStrs[i][k] == '1' )
+                pMints[i] |= (1 << k), pVars[k] |= (1 << i);
+    // extract funcs
+    for ( i = 0; i < nFuncs; i++ )
+        for ( k = 0; k < nMints; k++ )
+            if ( pFuncStrs[i][k] == '1' )
+                pFuncs[i] |= (1 << k);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_GetThird( int * pnVars, int * pnMints, int * pnFuncs, unsigned * pVars, unsigned * pMints, unsigned * pFuncs )
+{
+    int nVars  = 8;
+    int nMints = 16;
+    int nFuncs = 7;
+    char * pMintStrs[16] = { 
+        "1---1---",
+        "1----1--",
+        "1-----1-",
+        "1------1",
+
+        "-1--1---",
+        "-1---1--",
+        "-1----1-",
+        "-1-----1",
+
+        "--1-1---",
+        "--1--1--",
+        "--1---1-",
+        "--1----1",
+
+        "---11---",
+        "---1-1--",
+        "---1--1-",
+        "---1---1"
+    };
+    char * pFuncStrs[7] = { 
+        "1111111011001000",
+        "0000000100110111",
+        "1000000100100100",
+        "0100100000010010",
+        "0010010010000001",
+        "0001001001001000",
+        "1111111111111111"
+    };
+    int i, k;
+    *pnVars  = nVars;
+    *pnMints = nMints;
+    *pnFuncs = nFuncs;
+    // extract mints
+    for ( i = 0; i < nMints; i++ )
+        for ( k = 0; k < nVars; k++ )
+            if ( pMintStrs[i][k] == '1' )
+                pMints[i] |= (1 << k), pVars[k] |= (1 << i);
+    // extract funcs
+    for ( i = 0; i < nFuncs; i++ )
+        for ( k = 0; k < nMints; k++ )
+            if ( pFuncStrs[i][k] == '1' )
+                pFuncs[i] |= (1 << k);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_EnumPrint_rec( Vec_Int_t * vGates, int i, int nVars )
+{
+    int Fan0 = Vec_IntEntry(vGates, 2*i);
+    int Fan1 = Vec_IntEntry(vGates, 2*i+1);
+    char * pOper = Fan0 < Fan1 ? "" : "+";
+    if ( Fan0 > Fan1 )
+        ABC_SWAP( int, Fan0, Fan1 );
+    if ( Fan0 < nVars )
+        printf( "%c", 'a'+Fan0 );
+    else
+    {
+        printf( "(" );
+        Abc_EnumPrint_rec( vGates, Fan0, nVars );
+        printf( ")" );
+    }
+    printf( "%s", pOper );
+    if ( Fan1 < nVars )
+        printf( "%c", 'a'+Fan1 );
+    else
+    {
+        printf( "(" );
+        Abc_EnumPrint_rec( vGates, Fan1, nVars );
+        printf( ")" );
+    }
+}
+void Abc_EnumPrint( Vec_Int_t * vGates, int i, int nVars )
+{
+    assert( 2*i < Vec_IntSize(vGates) );
+    Abc_EnumPrint_rec( vGates, i, nVars );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int  Abc_DataHasBit( word * p, word i )  { return (p[(i)>>6] & (1<<((i) & 63))) > 0; }
+static inline void Abc_DataXorBit( word * p, word i )  { p[(i)>>6] ^= (1<<((i) & 63));             }
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_EnumerateFunctions( int nDecMax )
+{
+    int nVars;
+    int nMints;
+    int nFuncs;
+    unsigned pVars[100] = {0};
+    unsigned pMints[100] = {0};
+    unsigned pFuncs[100] = {0};
+    unsigned Truth;
+    int FuncDone[100] = {0}, nFuncDone = 0;
+    int GateCount[100] = {0};
+    int i, k, n, a, b, v;
+    abctime clk = Abc_Clock();
+    Vec_Int_t * vGates = Vec_IntAlloc( 100000 );
+    Vec_Int_t * vTruths = Vec_IntAlloc( 100000 );
+//    Vec_Int_t * vHash = Vec_IntStartFull( 1 << 16 );
+    word * pHash;
+
+    // extract data
+//    Abc_GetFirst( &nVars, &nMints, &nFuncs, pVars, pMints, pFuncs );
+    Abc_GetSecond( &nVars, &nMints, &nFuncs, pVars, pMints, pFuncs );
+//    Abc_GetThird( &nVars, &nMints, &nFuncs, pVars, pMints, pFuncs );
+
+    // create hash table
+    assert( nMints == 16 || nMints == 32 );
+    pHash = (word *)ABC_CALLOC( char, 1 << (nMints-3) );
+
+    // create elementary gates
+    for ( k = 0; k < nVars; k++ )
+    {
+//        Vec_IntWriteEntry( vHash, pVars[k], k );
+        Abc_DataXorBit( pHash, pVars[k] );
+        Vec_IntPush( vTruths, pVars[k] );
+        Vec_IntPush( vGates, -1 );
+        Vec_IntPush( vGates, -1 );
+    }
+
+    // go through different number of variables
+    GateCount[0] = 0;
+    GateCount[1] = nVars;
+    assert( Vec_IntSize(vTruths) == nVars );
+    for ( n = 0; n < nDecMax && nFuncDone < nFuncs; n++ )
+    {
+        for ( a = 0; a <= n; a++ )
+        for ( b = a; b <= n; b++ )
+        if ( a + b == n )
+        {
+            printf( "Trying %d + %d + 1 = %d\n", a, b, n+1 );
+            for ( i = GateCount[a]; i < GateCount[a+1]; i++ )
+            for ( k = GateCount[b]; k < GateCount[b+1]; k++ )
+            if ( i < k )
+            {
+                Truth = Vec_IntEntry(vTruths, i) & Vec_IntEntry(vTruths, k);
+//                if ( Vec_IntEntry(vHash, Truth) == -1 )
+                if ( !Abc_DataHasBit(pHash, Truth) )
+                {
+//                    Vec_IntWriteEntry( vHash, Truth, Vec_IntSize(vTruths) );
+                    Abc_DataXorBit( pHash, Truth );
+                    Vec_IntPush( vTruths, Truth );
+                    Vec_IntPush( vGates, i );
+                    Vec_IntPush( vGates, k );
+
+                    for ( v = 0; v < nFuncs; v++ )
+                    if ( !FuncDone[v] && Truth == pFuncs[v] )
+                    {
+                        printf( "Found function %d with %d gates: ", v, n+1 );
+                        Abc_EnumPrint( vGates, Vec_IntSize(vTruths)-1, nVars );
+                        FuncDone[v] = 1;
+                        nFuncDone++;
+                    }
+                }
+                Truth = Vec_IntEntry(vTruths, i) | Vec_IntEntry(vTruths, k);
+//                if ( Vec_IntEntry(vHash, Truth) == -1 )
+                if ( !Abc_DataHasBit(pHash, Truth) )
+                {
+//                    Vec_IntWriteEntry( vHash, Truth, Vec_IntSize(vTruths) );
+                    Abc_DataXorBit( pHash, Truth );
+                    Vec_IntPush( vTruths, Truth );
+                    Vec_IntPush( vGates, k );
+                    Vec_IntPush( vGates, i );
+
+                    for ( v = 0; v < nFuncs; v++ )
+                    if ( !FuncDone[v] && Truth == pFuncs[v] )
+                    {
+                        printf( "Found function %d with %d gates: ", v, n+1 );
+                        Abc_EnumPrint( vGates, Vec_IntSize(vTruths)-1, nVars );
+                        FuncDone[v] = 1;
+                        nFuncDone++;
+                    }
+                }
+            }
+        }
+        GateCount[n+2] = Vec_IntSize(vTruths);
+        printf( "Finished %d gates.  Truths = %10d.  ", n+1, Vec_IntSize(vTruths) );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    ABC_FREE( pHash );
+//    Vec_IntFree( vHash );
+    Vec_IntFree( vGates );
+    Vec_IntFree( vTruths );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+#define ABC_ENUM_MAX 16
+static word s_Truths6[6] = {
+    ABC_CONST(0xAAAAAAAAAAAAAAAA),
+    ABC_CONST(0xCCCCCCCCCCCCCCCC),
+    ABC_CONST(0xF0F0F0F0F0F0F0F0),
+    ABC_CONST(0xFF00FF00FF00FF00),
+    ABC_CONST(0xFFFF0000FFFF0000),
+    ABC_CONST(0xFFFFFFFF00000000)
+};
+typedef struct Abc_EnuMan_t_ Abc_EnuMan_t;
+struct Abc_EnuMan_t_
+{
+    int              nVars;        // support size
+    int              nVarsFree;    // number of PIs used
+    int              fVerbose;     // verbose flag
+    int              fUseXor;      // using XOR gate
+    int              nNodeMax;     // the max number of nodes
+    int              nNodes;       // current number of gates
+    int              nTops;        // the number of fanoutless gates
+    int              pFans0[ABC_ENUM_MAX];   // fanins
+    int              pFans1[ABC_ENUM_MAX];   // fanins 
+    int              fCompl0[ABC_ENUM_MAX];  // complements
+    int              fCompl1[ABC_ENUM_MAX];  // complements
+    int              Polar[ABC_ENUM_MAX];    // polarity
+    int              pRefs[ABC_ENUM_MAX];    // references
+    int              pLevel[ABC_ENUM_MAX];   // level 
+    word             pTruths[ABC_ENUM_MAX];  // truth tables
+    word             nTries;       // attempts to build a gate
+    word             nBuilds;      // actually built gates
+    word             nFinished;    // finished structures
+};
+static inline void Abc_EnumRef( Abc_EnuMan_t * p, int i )
+{
+    assert( p->pRefs[i] >= 0 );
+    if ( p->pRefs[i]++ == 0 )
+        p->nTops--;
+}
+static inline void Abc_EnumDeref( Abc_EnuMan_t * p, int i )
+{
+    if ( --p->pRefs[i] == 0 )
+        p->nTops++;
+    assert( p->pRefs[i] >= 0 );
+}
+static inline void Abc_EnumRefNode( Abc_EnuMan_t * p, int i )
+{
+    Abc_EnumRef( p, p->pFans0[i] );
+    Abc_EnumRef( p, p->pFans1[i] );
+    p->nTops++;
+    p->nNodes++; 
+    assert( i < p->nNodes );
+}
+static inline void Abc_EnumDerefNode( Abc_EnuMan_t * p, int i )
+{
+    assert( i < p->nNodes );
+    Abc_EnumDeref( p, p->pFans0[i] );
+    Abc_EnumDeref( p, p->pFans1[i] );
+    p->nTops--;
+    p->nNodes--; 
+}
+static inline void Abc_EnumPrintOne( Abc_EnuMan_t * p )
+{
+    int i;
+    Kit_DsdPrintFromTruth( (unsigned *)(p->pTruths + p->nNodes - 1), p->nVars ); 
+    for ( i = p->nVars; i < p->nNodes; i++ )
+        if ( p->Polar[i] == 4 )
+            printf( "  %c=%c+%c", 'a'+i, 'a'+p->pFans0[i], 'a'+p->pFans1[i] );
+        else
+            printf( "  %c=%s%c%s%c", 'a'+i, p->fCompl0[i]?"!":"", 'a'+p->pFans0[i], p->fCompl1[i]?"!":"", 'a'+p->pFans1[i] );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_EnumEquiv( word a, word b )
+{
+    return a == b || a == ~b;
+}
+static inline int Abc_EnumerateFilter( Abc_EnuMan_t * p )
+{
+    int fUseFull = 1;
+    int n = p->nNodes;
+    int i = p->pFans0[n];
+    int k = p->pFans1[n], t;
+    word * pTruths = p->pTruths;
+    word uTruth = pTruths[n];
+    assert( i < k );
+    // skip constants
+    if ( Abc_EnumEquiv(uTruth, 0) )
+        return 1;
+    // skip equal ones
+    for ( t = 0; t < n; t++ )
+        if ( Abc_EnumEquiv(uTruth, pTruths[t]) )
+            return 1;
+    if ( fUseFull )
+    {
+        // skip those that can be derived by any pair
+        int a, b; 
+        for ( a = 0; a <= i; a++ )
+        for ( b = a + 1; b <= k; b++ )
+        {
+            if ( a == i && b == k )
+                continue;
+            if ( Abc_EnumEquiv(uTruth,  pTruths[a] &  pTruths[b]) )
+                return 1;
+            if ( Abc_EnumEquiv(uTruth,  pTruths[a] & ~pTruths[b]) )
+                return 1;
+            if ( Abc_EnumEquiv(uTruth, ~pTruths[a] &  pTruths[b]) )
+                return 1;
+            if ( Abc_EnumEquiv(uTruth, ~pTruths[a] & ~pTruths[b]) )
+                return 1;
+            if ( p->fUseXor && Abc_EnumEquiv(uTruth,  pTruths[a] ^ pTruths[b]) )
+                return 1;
+        }
+    }
+    else
+    {
+        // skip those that can be derived by fanin and any other one in the cone
+        int uTruthI = p->fCompl0[n] ? ~pTruths[i] : pTruths[i];
+        int uTruthK = p->fCompl1[n] ? ~pTruths[k] : pTruths[k];
+        assert( p->fUseXor == 0 );
+        for ( t = 0; t < k; t++ )
+            if ( Abc_EnumEquiv(uTruth, pTruths[t] & uTruthI) || Abc_EnumEquiv(uTruth, ~pTruths[t] & uTruthI) )
+                return 1;
+        for ( t = 0; t < i; t++ )
+            if ( Abc_EnumEquiv(uTruth, pTruths[t] & uTruthK) || Abc_EnumEquiv(uTruth, ~pTruths[t] & uTruthK) )
+                return 1;
+    }
+    return 0;
+}
+void Abc_EnumerateFuncs_rec( Abc_EnuMan_t * p, int fNew, int iNode1st ) // the first node on the last level
+{
+    if ( p->nNodes == p->nNodeMax )
+    {
+        assert( p->nTops == 1 );
+        if ( p->fVerbose )
+            Abc_EnumPrintOne( p );
+        p->nFinished++;
+        return;
+    }
+    {
+    int i, k, c, cLim = 4 + p->fUseXor, n = p->nNodes;
+    int nRefedFans = p->nNodeMax - n + 1 - p->nTops;
+    int high0 = fNew ? iNode1st : p->pFans1[n-1];
+    int high1 = fNew ? n        : iNode1st;
+    int low0  = fNew ? 0        : p->pFans0[n-1];
+    int c0    = fNew ? 0        : p->Polar[n-1];
+    int Level = p->pLevel[high0];
+    assert( p->nTops > 0 && p->nTops <= p->nNodeMax - n + 1 );
+    // go through nodes 
+    for ( k = high0; k < high1; k++ )
+    {
+        if ( nRefedFans == 0 && p->pRefs[k] > 0 )
+            continue;
+        if ( p->pRefs[k] > 0 )
+            nRefedFans--;
+        assert( nRefedFans >= 0 );
+        // try second fanin
+        for ( i = (k == high0) ? low0 : 0; i < k; i++ )
+        {
+            if ( nRefedFans == 0 && p->pRefs[i] > 0 )
+                continue;
+            if ( Level == 0 && p->pRefs[i] == 0 && p->pRefs[k] == 0 && (i+1 != k || (i > 0 && p->pRefs[i-1] == 0)) ) // NPN
+                continue;
+            if ( p->pLevel[k] == 0 && p->pRefs[k] == 0 && p->pRefs[i] != 0 && k > 0 && p->pRefs[k-1] == 0 ) // NPN
+                continue;
+//            if ( p->pLevel[i] == 0 && p->pRefs[i] == 0 && p->pRefs[k] != 0 && i > 0 && p->pRefs[i-1] == 0 ) // NPN
+//                continue;
+            // try four polarities
+            for ( c = (k == high0 && i == low0 && !fNew) ? c0 + 1 : 0; c < cLim; c++ )
+            {
+                if ( p->pLevel[i] == 0 && p->pRefs[i] == 0 && (c & 1) == 1 ) // NPN
+                    continue;
+                if ( p->pLevel[k] == 0 && p->pRefs[k] == 0 && (c & 2) == 2 ) // NPN
+                    continue;
+                p->nTries++;
+                // create node
+                assert( i < k );
+                p->pFans0[n]  = i;
+                p->pFans1[n]  = k;
+                p->fCompl0[n] = c & 1;
+                p->fCompl1[n] = (c >> 1) & 1;
+                p->Polar[n]   = c;
+                if ( c == 4 )
+                    p->pTruths[n] = p->pTruths[i] ^ p->pTruths[k];
+                else
+                    p->pTruths[n] = ((c & 1) ? ~p->pTruths[i] : p->pTruths[i]) & ((c & 2) ? ~p->pTruths[k] : p->pTruths[k]);
+                if ( Abc_EnumerateFilter(p) )
+                    continue;
+                p->nBuilds++;
+                assert( Level == Abc_MaxInt(p->pLevel[i], p->pLevel[k]) );
+                p->pLevel[n]  = Level + 1;
+                Abc_EnumRefNode( p, n );
+                Abc_EnumerateFuncs_rec( p, 0, fNew ? n : iNode1st );
+                Abc_EnumDerefNode( p, n );
+                assert( n == p->nNodes );
+            }
+        }
+        if ( p->pRefs[k] > 0 )
+            nRefedFans++;
+    }
+    if ( fNew )
+        return;
+    // start a new level
+    Abc_EnumerateFuncs_rec( p, 1, iNode1st );
+    }
+}
+void Abc_EnumerateFuncs( int nVars, int nGates, int fVerbose )
+{
+    abctime clk = Abc_Clock();
+    Abc_EnuMan_t P, * p = &P; 
+    int i;
+    if ( nVars > nGates + 1 )
+    {
+        printf( "The gate count %d is not enough to have functions with %d inputs.\n", nGates, nVars );
+        return;
+    }
+    assert( nVars >= 2 && nVars <= 6 );
+    assert( nGates > 0 && nVars + nGates < ABC_ENUM_MAX );
+    memset( p, 0, sizeof(Abc_EnuMan_t) );
+    p->fVerbose  = fVerbose;
+    p->fUseXor   = 0;
+    p->nVars     = nVars;
+    p->nNodeMax  = nVars + nGates;
+    p->nNodes    = nVars;
+    p->nTops     = nVars;
+    for ( i = 0; i < nVars; i++ )
+        p->pTruths[i] = s_Truths6[i];
+    Abc_EnumerateFuncs_rec( p, 1, 0 );
+    assert( p->nNodes == nVars );
+    assert( p->nTops == nVars );
+    // report statistics
+    printf( "Vars = %d.  Gates = %d.  Tries = %u. Builds = %u.  Finished = %d. ", 
+        nVars, nGates, (unsigned)p->nTries, (unsigned)p->nBuilds, (unsigned)p->nFinished );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraUtilFile.c b/abc-build/src/misc/extra/extraUtilFile.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraUtilFile.c
@@ -0,0 +1,830 @@
+/**CFile****************************************************************
+
+  FileName    [extraUtilFile.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [extra]
+
+  Synopsis    [File management utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: extraUtilFile.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+  Synopsis    [Tries to find a file name with a different extension.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_FileGetSimilarName( char * pFileNameWrong, char * pS1, char * pS2, char * pS3, char * pS4, char * pS5 )
+{
+    FILE * pFile;
+    char * pFileNameOther;
+    char * pFileGen;
+
+    if ( pS1 == NULL )
+        return NULL;
+
+    // get the generic file name
+    pFileGen = Extra_FileNameGeneric( pFileNameWrong );
+    pFileNameOther = Extra_FileNameAppend( pFileGen, pS1 );
+    pFile = fopen( pFileNameOther, "r" );
+    if ( pFile == NULL && pS2 )
+    { // try one more
+        pFileNameOther = Extra_FileNameAppend( pFileGen, pS2 );
+        pFile = fopen( pFileNameOther, "r" );
+        if ( pFile == NULL && pS3 )
+        { // try one more
+            pFileNameOther = Extra_FileNameAppend( pFileGen, pS3 );
+            pFile = fopen( pFileNameOther, "r" );
+            if ( pFile == NULL && pS4 )
+            { // try one more
+                pFileNameOther = Extra_FileNameAppend( pFileGen, pS4 );
+                pFile = fopen( pFileNameOther, "r" );
+                if ( pFile == NULL && pS5 )
+                { // try one more
+                    pFileNameOther = Extra_FileNameAppend( pFileGen, pS5 );
+                    pFile = fopen( pFileNameOther, "r" );
+                }
+            }
+        }
+    }
+    ABC_FREE( pFileGen );
+    if ( pFile )
+    {
+        fclose( pFile );
+        return pFileNameOther;
+    }
+    // did not find :(
+    return NULL;            
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the pointer to the file extension.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_FileNameExtension( char * FileName )
+{
+    char * pDot;
+    // find the last "dot" in the file name, if it is present
+    for ( pDot = FileName + strlen(FileName)-1; pDot >= FileName; pDot-- )
+        if ( *pDot == '.' )
+            return pDot + 1;
+   return FileName;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the composite name of the file.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_FileNameAppend( char * pBase, char * pSuffix )
+{
+    static char Buffer[500];
+    assert( strlen(pBase) + strlen(pSuffix) < 500 );
+    sprintf( Buffer, "%s%s", pBase, pSuffix );
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_FileNameGeneric( char * FileName )
+{
+    char * pDot, * pRes;
+    pRes = Extra_UtilStrsav( FileName );
+    if ( (pDot = strrchr( pRes, '.' )) )
+        *pDot = 0;
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the composite name of the file.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_FileNameGenericAppend( char * pBase, char * pSuffix )
+{
+    static char Buffer[1000];
+    char * pDot;
+    assert( strlen(pBase) + strlen(pSuffix) < 1000 );
+    strcpy( Buffer, pBase );
+    if ( (pDot = strrchr( Buffer, '.' )) )
+        *pDot = 0;
+    strcat( Buffer, pSuffix );
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_FileNameWithoutPath( char * FileName )
+{
+    char * pRes;
+    for ( pRes = FileName + strlen(FileName) - 1; pRes >= FileName; pRes-- )
+        if ( *pRes == '\\' || *pRes == '/' )
+            return pRes + 1;
+    return FileName;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the file size.]
+
+  Description [The file should be closed.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_FileCheck( char * pFileName )
+{
+    FILE * pFile;
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Extra_FileCheck():  File \"%s\" does not exist.\n", pFileName );
+        return 0;
+    }
+    fseek( pFile, 0, SEEK_END );
+    if ( ftell( pFile ) == 0 )
+        printf( "Extra_FileCheck():  File \"%s\" is empty.\n", pFileName );
+    fclose( pFile );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the file size.]
+
+  Description [The file should be closed.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_FileSize( char * pFileName )
+{
+    FILE * pFile;
+    int nFileSize;
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Extra_FileSize(): The file is unavailable (absent or open).\n" );
+        return 0;
+    }
+    fseek( pFile, 0, SEEK_END );  
+    nFileSize = ftell( pFile ); 
+    fclose( pFile );
+    return nFileSize;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Read the file into the internal buffer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_FileRead( FILE * pFile )
+{
+    int nFileSize;
+    char * pBuffer;
+    int RetValue;
+    // get the file size, in bytes
+    fseek( pFile, 0, SEEK_END );  
+    nFileSize = ftell( pFile );  
+    // move the file current reading position to the beginning
+    rewind( pFile ); 
+    // load the contents of the file into memory
+    pBuffer = ABC_ALLOC( char, nFileSize + 3 );
+    RetValue = fread( pBuffer, nFileSize, 1, pFile );
+    // terminate the string with '\0'
+    pBuffer[ nFileSize + 0] = '\n';
+    pBuffer[ nFileSize + 1] = '\0';
+    return pBuffer;
+}
+char * Extra_FileRead2( FILE * pFile, FILE * pFile2 )
+{
+    char * pBuffer;
+    int nSize, nSize2;
+    int RetValue;
+    // get the file size, in bytes
+    fseek( pFile, 0, SEEK_END );  
+    nSize = ftell( pFile );  
+    rewind( pFile ); 
+    // get the file size, in bytes
+    fseek( pFile2, 0, SEEK_END );  
+    nSize2 = ftell( pFile2 );  
+    rewind( pFile2 ); 
+    // load the contents of the file into memory
+    pBuffer = ABC_ALLOC( char, nSize + nSize2 + 3 );
+    RetValue = fread( pBuffer,         nSize,  1, pFile );
+    RetValue = fread( pBuffer + nSize, nSize2, 1, pFile2 );
+    // terminate the string with '\0'
+    pBuffer[ nSize + nSize2 + 0] = '\n';
+    pBuffer[ nSize + nSize2 + 1] = '\0';
+    return pBuffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read the file into the internal buffer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_FileReadContents( char * pFileName )
+{
+    FILE * pFile;
+    char * pBuffer;
+    pFile = fopen( pFileName, "rb" );
+    pBuffer = pFile ? Extra_FileRead( pFile ) : NULL;
+    if ( pFile )  fclose( pFile );
+    return pBuffer;
+}
+char * Extra_FileReadContents2( char * pFileName, char * pFileName2 )
+{
+    FILE * pFile, * pFile2;
+    char * pBuffer;
+    pFile  = fopen( pFileName, "rb" );
+    pFile2 = fopen( pFileName2, "rb" );
+    pBuffer = (pFile && pFile2) ? Extra_FileRead2( pFile, pFile2 ) : NULL;
+    if ( pFile )  fclose( pFile );
+    if ( pFile2 ) fclose( pFile2 );
+    return pBuffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns one if the file has a given extension.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_FileIsType( char * pFileName, char * pS1, char * pS2, char * pS3 )
+{
+    int lenS, lenF = strlen(pFileName);
+    lenS = pS1 ? strlen(pS1) : 0;
+    if ( lenS && lenF > lenS && !strncmp( pFileName+lenF-lenS, pS1, lenS ) )
+        return 1;
+    lenS = pS2 ? strlen(pS2) : 0;
+    if ( lenS && lenF > lenS && !strncmp( pFileName+lenF-lenS, pS2, lenS ) )
+        return 1;
+    lenS = pS3 ? strlen(pS3) : 0;
+    if ( lenS && lenF > lenS && !strncmp( pFileName+lenF-lenS, pS3, lenS ) )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the time stamp.]
+
+  Description [The file should be closed.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_TimeStamp()
+{
+    static char Buffer[100];
+	char * TimeStamp;
+	time_t ltime;
+    // get the current time
+	time( &ltime );
+	TimeStamp = asctime( localtime( &ltime ) );
+	TimeStamp[ strlen(TimeStamp) - 1 ] = 0;
+    strcpy( Buffer, TimeStamp );
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Extra_ReadBinary( char * Buffer )
+{
+    unsigned Result;
+    int i;
+
+    Result = 0;
+    for ( i = 0; Buffer[i]; i++ )
+        if ( Buffer[i] == '0' || Buffer[i] == '1' )
+            Result = Result * 2 + Buffer[i] - '0';
+        else
+        {
+            assert( 0 );
+        }
+    return Result;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the bit string.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits )
+{
+    int Remainder, nWords;
+    int w, i;
+
+    Remainder = (nBits%(sizeof(unsigned)*8));
+    nWords    = (nBits/(sizeof(unsigned)*8)) + (Remainder>0);
+
+    for ( w = nWords-1; w >= 0; w-- )
+        for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- )
+            fprintf( pFile, "%c", '0' + (int)((Sign[w] & (1<<i)) > 0) );
+
+//  fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the hex unsigned into the bit-string.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_ReadHex( unsigned Sign[], char * pString, int nDigits )
+{
+    int Digit, k, c;
+    for ( k = 0; k < nDigits; k++ )
+    {
+        c = nDigits-1-k;
+        if ( pString[c] >= '0' && pString[c] <= '9' )
+            Digit = pString[c] - '0';
+        else if ( pString[c] >= 'A' && pString[c] <= 'F' )
+            Digit = pString[c] - 'A' + 10;
+        else if ( pString[c] >= 'a' && pString[c] <= 'f' )
+            Digit = pString[c] - 'a' + 10;
+        else { assert( 0 ); return 0; }
+        Sign[k/8] |= ( (Digit & 15) << ((k%8) * 4) );
+    }
+    return 1;
+}
+int Extra_ReadHexadecimal( unsigned Sign[], char * pString, int nVars )
+{
+    int nWords, nDigits, k;
+    nWords = Extra_TruthWordNum( nVars );
+    for ( k = 0; k < nWords; k++ )
+        Sign[k] = 0;
+    // read the number from the string
+    nDigits = (1 << nVars) / 4;
+    if ( nDigits == 0 )
+        nDigits = 1;
+    Extra_ReadHex( Sign, pString, nDigits );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the hex unsigned into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars )
+{
+    int nDigits, Digit, k;
+    // write the number into the file
+    nDigits = (1 << nVars) / 4;
+    for ( k = nDigits - 1; k >= 0; k-- )
+    {
+        Digit = ((Sign[k/8] >> ((k%8) * 4)) & 15);
+        if ( Digit < 10 )
+            fprintf( pFile, "%d", Digit );
+        else
+            fprintf( pFile, "%c", 'a' + Digit-10 );
+    }
+//    fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the hex unsigned into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_PrintHexadecimalString( char * pString, unsigned Sign[], int nVars )
+{
+    int nDigits, Digit, k;
+    // write the number into the file
+    nDigits = (1 << nVars) / 4;
+    for ( k = nDigits - 1; k >= 0; k-- )
+    {
+        Digit = ((Sign[k/8] >> ((k%8) * 4)) & 15);
+        if ( Digit < 10 )
+            *pString++ = '0' + Digit;
+        else
+            *pString++ = 'a' + Digit-10;
+    }
+//    fprintf( pFile, "\n" );
+    *pString = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the hex unsigned into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_PrintHex( FILE * pFile, unsigned * pTruth, int nVars )
+{
+    int nMints, nDigits, Digit, k;
+
+    // write the number into the file
+    fprintf( pFile, "0x" );
+    nMints  = (1 << nVars);
+    nDigits = nMints / 4 + ((nMints % 4) > 0);
+    for ( k = nDigits - 1; k >= 0; k-- )
+    {
+        Digit = ((pTruth[k/8] >> (k * 4)) & 15);
+        if ( Digit < 10 )
+            fprintf( pFile, "%d", Digit );
+        else
+            fprintf( pFile, "%c", 'A' + Digit-10 );
+    }
+//    fprintf( pFile, "\n" );
+}
+void Extra_PrintHexReverse( FILE * pFile, unsigned * pTruth, int nVars )
+{
+    int nMints, nDigits, Digit, k;
+
+    // write the number into the file
+    fprintf( pFile, "0x" );
+    nMints  = (1 << nVars);
+    nDigits = nMints / 4 + ((nMints % 4) > 0);
+    for ( k = 0; k < nDigits; k++ )
+    {
+        Digit = ((pTruth[k/8] >> (k * 4)) & 15);
+        if ( Digit < 10 )
+            fprintf( pFile, "%d", Digit );
+        else
+            fprintf( pFile, "%c", 'A' + Digit-10 );
+    }
+//    fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the composite name of the file.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_PrintSymbols( FILE * pFile, char Char, int nTimes, int fPrintNewLine )
+{
+    int i;
+    for ( i = 0; i < nTimes; i++ )
+        printf( "%c", Char );
+    if ( fPrintNewLine )
+        printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Appends the string.]
+
+  Description [Assumes that the given string (pStrGiven) has been allocated
+  before using malloc(). The additional string has not been allocated.
+  Allocs more root, appends the additional part, frees the old given string.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_StringAppend( char * pStrGiven, char * pStrAdd )
+{
+    char * pTemp;
+    if ( pStrGiven )
+    {
+        pTemp = ABC_ALLOC( char, strlen(pStrGiven) + strlen(pStrAdd) + 2 );
+        sprintf( pTemp, "%s%s", pStrGiven, pStrAdd );
+        ABC_FREE( pStrGiven );
+    }
+    else
+        pTemp = Extra_UtilStrsav( pStrAdd );
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Only keep characters belonging to the second string.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_StringClean( char * pStrGiven, char * pCharKeep )
+{
+    char * pTemp, * pChar, * pSave = pStrGiven;
+    for ( pTemp = pStrGiven; *pTemp; pTemp++ )
+    {
+        for ( pChar = pCharKeep; *pChar; pChar++ )
+            if ( *pTemp == *pChar )
+                break;
+        if ( *pChar == 0 )
+            continue;
+        *pSave++ = *pTemp;
+    }
+    *pSave = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [String comparison procedure.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_StringCompare( const char * pp1, const char * pp2 )
+{
+    return strcmp(*(char **)pp1, *(char **)pp2);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts lines in the file alphabetically.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_FileSort( char * pFileName, char * pFileNameOut )
+{
+    FILE * pFile;
+    char * pContents;
+    char ** pLines;
+    int i, nLines, Begin;
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Extra_FileSort(): Cannot open file \"%s\".\n", pFileName );
+        return;
+    }
+    pContents = Extra_FileRead( pFile );
+    fclose( pFile );
+    if ( pContents == NULL )
+    {
+        printf( "Extra_FileSort(): Cannot read contents of file \"%s\".\n", pFileName );
+        return;
+    }
+    // count end of lines
+    for ( nLines = 0, i = 0; pContents[i]; i++ )
+        nLines += (pContents[i] == '\n');
+    // break the file into lines
+    pLines = (char **)malloc( sizeof(char *) * nLines );
+    Begin = 0;
+    for ( nLines = 0, i = 0; pContents[i]; i++ )
+        if ( pContents[i] == '\n' )
+        {
+            pContents[i] = 0;
+            pLines[nLines++] = pContents + Begin;
+            Begin = i + 1;
+        }
+    // sort the lines
+    qsort( pLines, nLines, sizeof(char *), (int(*)(const void *,const void *))Extra_StringCompare );
+    // write a new file
+    pFile = fopen( pFileNameOut, "wb" );
+    for ( i = 0; i < nLines; i++ )
+        if ( pLines[i][0] )
+            fprintf( pFile, "%s\n", pLines[i] );
+    fclose( pFile );
+    // cleanup
+    free( pLines );
+    free( pContents );
+    // report the result
+    printf( "The file after sorting is \"%s\".\n", pFileNameOut );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Appends line number in the end.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_FileLineNumAdd( char * pFileName, char * pFileNameOut )
+{
+    char Buffer[1000];
+    FILE * pFile;
+    FILE * pFile2;
+    int iLine;
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Extra_FileLineNumAdd(): Cannot open file \"%s\".\n", pFileName );
+        return;
+    }
+    pFile2 = fopen( pFileNameOut, "wb" );
+    if ( pFile2 == NULL )
+    {
+        fclose( pFile );
+        printf( "Extra_FileLineNumAdd(): Cannot open file \"%s\".\n", pFileNameOut );
+        return;
+    }
+    for ( iLine = 0; fgets( Buffer, 1000, pFile ); iLine++ )
+    {
+        sprintf( Buffer + strlen(Buffer) - 2, "%03d\n%c", iLine, 0 );
+        fputs( Buffer, pFile2 );
+    }
+    fclose( pFile );
+    fclose( pFile2 );
+    // report the result
+    printf( "The resulting file is \"%s\".\n", pFileNameOut );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+int main( int argc, char ** argv )
+{
+    if ( argc == 2 )
+        Extra_FileSort( argv[1], Extra_FileNameAppend(argv[1], "_sorted") );
+    else
+        printf( "%s: Wrong number of command line arguments.\n", argv[0] );
+    return 1;
+}
+*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static Functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraUtilMemory.c b/abc-build/src/misc/extra/extraUtilMemory.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraUtilMemory.c
@@ -0,0 +1,628 @@
+/**CFile****************************************************************
+
+  FileName    [extraUtilMemory.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [extra]
+
+  Synopsis    [Memory managers.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: extraUtilMemory.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+struct Extra_MmFixed_t_
+{
+    // information about individual entries
+    int           nEntrySize;    // the size of one entry
+    int           nEntriesAlloc; // the total number of entries allocated
+    int           nEntriesUsed;  // the number of entries in use
+    int           nEntriesMax;   // the max number of entries in use
+    char *        pEntriesFree;  // the linked list of free entries
+
+    // this is where the memory is stored
+    int           nChunkSize;    // the size of one chunk
+    int           nChunksAlloc;  // the maximum number of memory chunks 
+    int           nChunks;       // the current number of memory chunks 
+    char **       pChunks;       // the allocated memory
+
+    // statistics
+    int           nMemoryUsed;   // memory used in the allocated entries
+    int           nMemoryAlloc;  // memory allocated
+};
+
+struct Extra_MmFlex_t_
+{
+    // information about individual entries
+    int           nEntriesUsed;  // the number of entries allocated
+    char *        pCurrent;      // the current pointer to free memory
+    char *        pEnd;          // the first entry outside the free memory
+
+    // this is where the memory is stored
+    int           nChunkSize;    // the size of one chunk
+    int           nChunksAlloc;  // the maximum number of memory chunks 
+    int           nChunks;       // the current number of memory chunks 
+    char **       pChunks;       // the allocated memory
+
+    // statistics
+    int           nMemoryUsed;   // memory used in the allocated entries
+    int           nMemoryAlloc;  // memory allocated
+};
+
+
+struct Extra_MmStep_t_
+{
+    int                nMems;    // the number of fixed memory managers employed
+    Extra_MmFixed_t ** pMems;    // memory managers: 2^1 words, 2^2 words, etc
+    int                nMapSize; // the size of the memory array
+    Extra_MmFixed_t ** pMap;     // maps the number of bytes into its memory manager
+    int                nLargeChunksAlloc;  // the maximum number of large memory chunks 
+    int                nLargeChunks;       // the current number of large memory chunks 
+    void **            pLargeChunks;       // the allocated large memory chunks
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates memory pieces of fixed size.]
+
+  Description [The size of the chunk is computed as the minimum of
+  1024 entries and 64K. Can only work with entry size at least 4 byte long.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Extra_MmFixed_t * Extra_MmFixedStart( int nEntrySize )
+{
+    Extra_MmFixed_t * p;
+
+    p = ABC_ALLOC( Extra_MmFixed_t, 1 );
+    memset( p, 0, sizeof(Extra_MmFixed_t) );
+
+    p->nEntrySize    = nEntrySize;
+    p->nEntriesAlloc = 0;
+    p->nEntriesUsed  = 0;
+    p->pEntriesFree  = NULL;
+
+    if ( nEntrySize * (1 << 10) < (1<<16) )
+        p->nChunkSize = (1 << 10);
+    else
+        p->nChunkSize = (1<<16) / nEntrySize;
+    if ( p->nChunkSize < 8 )
+        p->nChunkSize = 8;
+
+    p->nChunksAlloc  = 64;
+    p->nChunks       = 0;
+    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
+
+    p->nMemoryUsed   = 0;
+    p->nMemoryAlloc  = 0;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_MmFixedPrint( Extra_MmFixed_t * p )
+{
+    printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n",
+        p->nEntrySize, p->nChunkSize, p->nChunks );
+    printf( "   Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n",
+        p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_MmFixedStop( Extra_MmFixed_t * p )
+{
+    int i;
+    if ( p == NULL )
+        return;
+    for ( i = 0; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    ABC_FREE( p->pChunks );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_MmFixedEntryFetch( Extra_MmFixed_t * p )
+{
+    char * pTemp;
+    int i;
+
+    // check if there are still free entries
+    if ( p->nEntriesUsed == p->nEntriesAlloc )
+    { // need to allocate more entries
+        assert( p->pEntriesFree == NULL );
+        if ( p->nChunks == p->nChunksAlloc )
+        {
+            p->nChunksAlloc *= 2;
+            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
+        }
+        p->pEntriesFree = ABC_ALLOC( char, p->nEntrySize * p->nChunkSize );
+        p->nMemoryAlloc += p->nEntrySize * p->nChunkSize;
+        // transform these entries into a linked list
+        pTemp = p->pEntriesFree;
+        for ( i = 1; i < p->nChunkSize; i++ )
+        {
+            *((char **)pTemp) = pTemp + p->nEntrySize;
+            pTemp += p->nEntrySize;
+        }
+        // set the last link
+        *((char **)pTemp) = NULL;
+        // add the chunk to the chunk storage
+        p->pChunks[ p->nChunks++ ] = p->pEntriesFree;
+        // add to the number of entries allocated
+        p->nEntriesAlloc += p->nChunkSize;
+    }
+    // incrememt the counter of used entries
+    p->nEntriesUsed++;
+    if ( p->nEntriesMax < p->nEntriesUsed )
+        p->nEntriesMax = p->nEntriesUsed;
+    // return the first entry in the free entry list
+    pTemp = p->pEntriesFree;
+    p->pEntriesFree = *((char **)pTemp);
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_MmFixedEntryRecycle( Extra_MmFixed_t * p, char * pEntry )
+{
+    // decrement the counter of used entries
+    p->nEntriesUsed--;
+    // add the entry to the linked list of free entries
+    *((char **)pEntry) = p->pEntriesFree;
+    p->pEntriesFree = pEntry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description [Relocates all the memory except the first chunk.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_MmFixedRestart( Extra_MmFixed_t * p )
+{
+    int i;
+    char * pTemp;
+
+    // deallocate all chunks except the first one
+    for ( i = 1; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    p->nChunks = 1;
+    // transform these entries into a linked list
+    pTemp = p->pChunks[0];
+    for ( i = 1; i < p->nChunkSize; i++ )
+    {
+        *((char **)pTemp) = pTemp + p->nEntrySize;
+        pTemp += p->nEntrySize;
+    }
+    // set the last link
+    *((char **)pTemp) = NULL;
+    // set the free entry list
+    p->pEntriesFree  = p->pChunks[0];
+    // set the correct statistics
+    p->nMemoryAlloc  = p->nEntrySize * p->nChunkSize;
+    p->nMemoryUsed   = 0;
+    p->nEntriesAlloc = p->nChunkSize;
+    p->nEntriesUsed  = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p )
+{
+    return p->nMemoryAlloc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p )
+{
+    return p->nEntriesMax;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates entries of flexible size.]
+
+  Description [Can only work with entry size at least 4 byte long.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Extra_MmFlex_t * Extra_MmFlexStart()
+{ 
+    Extra_MmFlex_t * p;
+//printf( "allocing flex\n" );
+    p = ABC_ALLOC( Extra_MmFlex_t, 1 );
+    memset( p, 0, sizeof(Extra_MmFlex_t) );
+
+    p->nEntriesUsed  = 0;
+    p->pCurrent      = NULL;
+    p->pEnd          = NULL;
+
+    p->nChunkSize    = (1 << 12);
+    p->nChunksAlloc  = 64;
+    p->nChunks       = 0;
+    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
+
+    p->nMemoryUsed   = 0;
+    p->nMemoryAlloc  = 0;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_MmFlexPrint( Extra_MmFlex_t * p )
+{
+    printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n",
+        p->nChunkSize, p->nChunks );
+    printf( "   Entries used = %d. Memory used = %d. Memory alloc = %d.\n",
+        p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_MmFlexStop( Extra_MmFlex_t * p )
+{
+    int i;
+    if ( p == NULL )
+        return;
+//printf( "deleting flex\n" );
+    for ( i = 0; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    ABC_FREE( p->pChunks );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_MmFlexEntryFetch( Extra_MmFlex_t * p, int nBytes )
+{
+    char * pTemp;
+    // check if there are still free entries
+    if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd )
+    { // need to allocate more entries
+        if ( p->nChunks == p->nChunksAlloc )
+        {
+            p->nChunksAlloc *= 2;
+            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
+        }
+        if ( nBytes > p->nChunkSize )
+        {
+            // resize the chunk size if more memory is requested than it can give
+            // (ideally, this should never happen)
+            p->nChunkSize = 2 * nBytes;
+        }
+        p->pCurrent = ABC_ALLOC( char, p->nChunkSize );
+        p->pEnd     = p->pCurrent + p->nChunkSize;
+        p->nMemoryAlloc += p->nChunkSize;
+        // add the chunk to the chunk storage
+        p->pChunks[ p->nChunks++ ] = p->pCurrent;
+    }
+    assert( p->pCurrent + nBytes <= p->pEnd );
+    // increment the counter of used entries
+    p->nEntriesUsed++;
+    // keep track of the memory used
+    p->nMemoryUsed += nBytes;
+    // return the next entry
+    pTemp = p->pCurrent;
+    p->pCurrent += nBytes;
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_MmFlexReadMemUsage( Extra_MmFlex_t * p )
+{
+    return p->nMemoryAlloc;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the hierarchical memory manager.]
+
+  Description [This manager can allocate entries of any size.
+  Iternally they are mapped into the entries with the number of bytes
+  equal to the power of 2. The smallest entry size is 8 bytes. The
+  next one is 16 bytes etc. So, if the user requests 6 bytes, he gets 
+  8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc.
+  The input parameters "nSteps" says how many fixed memory managers
+  are employed internally. Calling this procedure with nSteps equal
+  to 10 results in 10 hierarchically arranged internal memory managers, 
+  which can allocate up to 4096 (1Kb) entries. Requests for larger 
+  entries are handed over to malloc() and then ABC_FREE()ed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Extra_MmStep_t * Extra_MmStepStart( int nSteps )
+{
+    Extra_MmStep_t * p;
+    int i, k;
+    p = ABC_ALLOC( Extra_MmStep_t, 1 );
+    memset( p, 0, sizeof(Extra_MmStep_t) );
+    p->nMems = nSteps;
+    // start the fixed memory managers
+    p->pMems = ABC_ALLOC( Extra_MmFixed_t *, p->nMems );
+    for ( i = 0; i < p->nMems; i++ )
+        p->pMems[i] = Extra_MmFixedStart( (8<<i) );
+    // set up the mapping of the required memory size into the corresponding manager
+    p->nMapSize = (4<<p->nMems);
+    p->pMap = ABC_ALLOC( Extra_MmFixed_t *, p->nMapSize+1 );
+    p->pMap[0] = NULL;
+    for ( k = 1; k <= 4; k++ )
+        p->pMap[k] = p->pMems[0];
+    for ( i = 0; i < p->nMems; i++ )
+        for ( k = (4<<i)+1; k <= (8<<i); k++ )
+            p->pMap[k] = p->pMems[i];
+//for ( i = 1; i < 100; i ++ )
+//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_MmStepStop( Extra_MmStep_t * p )
+{
+    int i;
+    for ( i = 0; i < p->nMems; i++ )
+        Extra_MmFixedStop( p->pMems[i] );
+    if ( p->pLargeChunks ) 
+    {
+      for ( i = 0; i < p->nLargeChunks; i++ )
+          ABC_FREE( p->pLargeChunks[i] );
+      ABC_FREE( p->pLargeChunks );
+    }
+    ABC_FREE( p->pMems );
+    ABC_FREE( p->pMap );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_MmStepEntryFetch( Extra_MmStep_t * p, int nBytes )
+{
+    if ( nBytes == 0 )
+        return NULL;
+    if ( nBytes > p->nMapSize )
+    {
+//        printf( "Allocating %d bytes.\n", nBytes );
+//        return ABC_ALLOC( char, nBytes );
+        if ( p->nLargeChunks == p->nLargeChunksAlloc )
+        {
+            if ( p->nLargeChunksAlloc == 0 )
+                p->nLargeChunksAlloc = 32;
+            p->nLargeChunksAlloc *= 2;
+            p->pLargeChunks = ABC_REALLOC( void *, p->pLargeChunks, p->nLargeChunksAlloc );
+        }
+        p->pLargeChunks[ p->nLargeChunks++ ] = ABC_ALLOC( char, nBytes );
+        return (char *)p->pLargeChunks[ p->nLargeChunks - 1 ];
+    }
+    return Extra_MmFixedEntryFetch( p->pMap[nBytes] );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_MmStepEntryRecycle( Extra_MmStep_t * p, char * pEntry, int nBytes )
+{
+    if ( nBytes == 0 )
+        return;
+    if ( nBytes > p->nMapSize )
+    {
+//        ABC_FREE( pEntry );
+        return;
+    }
+    Extra_MmFixedEntryRecycle( p->pMap[nBytes], pEntry );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_MmStepReadMemUsage( Extra_MmStep_t * p )
+{
+    int i, nMemTotal = 0;
+    for ( i = 0; i < p->nMems; i++ )
+        nMemTotal += p->pMems[i]->nMemoryAlloc;
+    return nMemTotal;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraUtilMisc.c b/abc-build/src/misc/extra/extraUtilMisc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraUtilMisc.c
@@ -0,0 +1,2541 @@
+/**CFile****************************************************************
+
+  FileName    [extraUtilMisc.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [extra]
+
+  Synopsis    [Misc procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: extraUtilMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <math.h>
+
+#include "extra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+static void Extra_Permutations_rec( char ** pRes, int nFact, int n, char Array[] );
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the smallest integer larger of equal than the logarithm.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Extra_Base2LogDouble( double Num )
+{
+    double Res;
+    int ResInt;
+
+    Res    = log(Num)/log(2.0);
+    ResInt = (int)Res;
+    if ( ResInt == Res )
+        return ResInt;
+    else 
+        return ResInt+1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the power of two as a double.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+double Extra_Power2( int Degree )
+{
+    double Res;
+    assert( Degree >= 0 );
+    if ( Degree < 32 )
+        return (double)(01<<Degree); 
+    for ( Res = 1.0; Degree; Res *= 2.0, Degree-- );
+    return Res;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_Power3( int Num )
+{
+    int i;
+    int Res;
+    Res = 1;
+    for ( i = 0; i < Num; i++ )
+        Res *= 3;
+    return Res;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the number of combinations of k elements out of n.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Extra_NumCombinations( int k, int n )
+{
+    int i, Res = 1;
+    for ( i = 1; i <= k; i++ )
+            Res = Res * (n-i+1) / i;
+    return Res;
+} /* end of Extra_NumCombinations */
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Extra_DeriveRadixCode( int Number, int Radix, int nDigits )
+{
+    static int Code[100];
+    int i;
+    assert( nDigits < 100 );
+    for ( i = 0; i < nDigits; i++ )
+    {
+        Code[i] = Number % Radix;
+        Number  = Number / Radix;
+    }
+    assert( Number == 0 );
+    return Code;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of ones in the bitstring.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_CountOnes( unsigned char * pBytes, int nBytes )
+{
+    static int bit_count[256] = {
+      0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+      3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+    };
+
+    int i, Counter;
+    Counter = 0;
+    for ( i = 0; i < nBytes; i++ )
+        Counter += bit_count[ *(pBytes+i) ];
+    return Counter;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the factorial.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Extra_Factorial( int n )
+{
+    int i, Res = 1;
+    for ( i = 1; i <= n; i++ )
+        Res *= i;
+    return Res;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the set of all permutations.]
+
+  Description [The number of permutations in the array is n!. The number of
+  entries in each permutation is n. Therefore, the resulting array is a 
+  two-dimentional array of the size: n! x n. To free the resulting array,
+  call ABC_FREE() on the pointer returned by this procedure.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+char ** Extra_Permutations( int n )
+{
+    char Array[50];
+    char ** pRes;
+    int nFact, i;
+    // allocate memory
+    nFact = Extra_Factorial( n );
+    pRes  = (char **)Extra_ArrayAlloc( nFact, n, sizeof(char) );
+    // fill in the permutations
+    for ( i = 0; i < n; i++ )
+        Array[i] = i;
+    Extra_Permutations_rec( pRes, nFact, n, Array );
+    // print the permutations
+/*
+    {
+    int i, k;
+    for ( i = 0; i < nFact; i++ )
+    {
+        printf( "{" );
+        for ( k = 0; k < n; k++ )
+            printf( " %d", pRes[i][k] );
+        printf( " }\n" );
+    }
+    }
+*/
+    return pRes;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Fills in the array of permutations.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Extra_Permutations_rec( char ** pRes, int nFact, int n, char Array[] )
+{
+    char ** pNext;
+    int nFactNext;
+    int iTemp, iCur, iLast, k;
+
+    if ( n == 1 )
+    {
+        pRes[0][0] = Array[0];
+        return;
+    }
+
+    // get the next factorial
+    nFactNext = nFact / n;
+    // get the last entry
+    iLast = n - 1;
+
+    for ( iCur = 0; iCur < n; iCur++ )
+    {
+        // swap Cur and Last
+        iTemp        = Array[iCur];
+        Array[iCur]  = Array[iLast];
+        Array[iLast] = iTemp;
+
+        // get the pointer to the current section
+        pNext = pRes + (n - 1 - iCur) * nFactNext;
+
+        // set the last entry 
+        for ( k = 0; k < nFactNext; k++ )
+            pNext[k][iLast] = Array[iLast];
+
+        // call recursively for this part
+        Extra_Permutations_rec( pNext, nFactNext, n - 1, Array );
+
+        // swap them back
+        iTemp        = Array[iCur];
+        Array[iCur]  = Array[iLast];
+        Array[iLast] = iTemp;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Permutes the given vector of minterms.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_TruthPermute_int( int * pMints, int nMints, char * pPerm, int nVars, int * pMintsP )
+{
+    int m, v;
+    // clean the storage for minterms
+    memset( pMintsP, 0, sizeof(int) * nMints );
+    // go through minterms and add the variables
+    for ( m = 0; m < nMints; m++ )
+        for ( v = 0; v < nVars; v++ )
+            if ( pMints[m] & (1 << v) )
+                pMintsP[m] |= (1 << pPerm[v]);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Permutes the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Extra_TruthPermute( unsigned Truth, char * pPerms, int nVars, int fReverse )
+{
+    unsigned Result;
+    int * pMints;
+    int * pMintsP;
+    int nMints;
+    int i, m;
+
+    assert( nVars < 6 );
+    nMints  = (1 << nVars);
+    pMints  = ABC_ALLOC( int, nMints );
+    pMintsP = ABC_ALLOC( int, nMints );
+    for ( i = 0; i < nMints; i++ )
+        pMints[i] = i;
+
+    Extra_TruthPermute_int( pMints, nMints, pPerms, nVars, pMintsP );
+
+    Result = 0;
+    if ( fReverse )
+    {
+        for ( m = 0; m < nMints; m++ )
+            if ( Truth & (1 << pMintsP[m]) )
+                Result |= (1 << m);
+    }
+    else
+    {
+        for ( m = 0; m < nMints; m++ )
+            if ( Truth & (1 << m) )
+                Result |= (1 << pMintsP[m]);
+    }
+
+    ABC_FREE( pMints );
+    ABC_FREE( pMintsP );
+
+    return Result;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Changes the phase of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Extra_TruthPolarize( unsigned uTruth, int Polarity, int nVars )
+{
+    // elementary truth tables
+    static unsigned Signs[5] = {
+        0xAAAAAAAA,    // 1010 1010 1010 1010 1010 1010 1010 1010
+        0xCCCCCCCC,    // 1010 1010 1010 1010 1010 1010 1010 1010
+        0xF0F0F0F0,    // 1111 0000 1111 0000 1111 0000 1111 0000
+        0xFF00FF00,    // 1111 1111 0000 0000 1111 1111 0000 0000
+        0xFFFF0000     // 1111 1111 1111 1111 0000 0000 0000 0000
+    };
+    unsigned uTruthRes, uCof0, uCof1;
+    int nMints, Shift, v;
+    assert( nVars < 6 );
+    nMints = (1 << nVars);
+    uTruthRes = uTruth;
+    for ( v = 0; v < nVars; v++ )
+        if ( Polarity & (1 << v) )
+        {
+            uCof0  = uTruth & ~Signs[v];
+            uCof1  = uTruth &  Signs[v];
+            Shift  = (1 << v);
+            uCof0 <<= Shift;
+            uCof1 >>= Shift;
+            uTruth = uCof0 | uCof1;
+        }
+    return uTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes N-canonical form using brute-force methods.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Extra_TruthCanonN( unsigned uTruth, int nVars )
+{
+    unsigned uTruthMin, uPhase;
+    int nMints, i;
+    nMints    = (1 << nVars);
+    uTruthMin = 0xFFFFFFFF;
+    for ( i = 0; i < nMints; i++ )
+    {
+        uPhase = Extra_TruthPolarize( uTruth, i, nVars ); 
+        if ( uTruthMin > uPhase )
+            uTruthMin = uPhase;
+    }
+    return uTruthMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes NN-canonical form using brute-force methods.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Extra_TruthCanonNN( unsigned uTruth, int nVars )
+{
+    unsigned uTruthMin, uTruthC, uPhase;
+    int nMints, i;
+    nMints    = (1 << nVars);
+    uTruthC   = (unsigned)( (~uTruth) & ((~((unsigned)0)) >> (32-nMints)) );
+    uTruthMin = 0xFFFFFFFF;
+    for ( i = 0; i < nMints; i++ )
+    {
+        uPhase = Extra_TruthPolarize( uTruth, i, nVars ); 
+        if ( uTruthMin > uPhase )
+            uTruthMin = uPhase;
+        uPhase = Extra_TruthPolarize( uTruthC, i, nVars ); 
+        if ( uTruthMin > uPhase )
+            uTruthMin = uPhase;
+    }
+    return uTruthMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes P-canonical form using brute-force methods.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Extra_TruthCanonP( unsigned uTruth, int nVars )
+{
+    static int nVarsOld, nPerms;
+    static char ** pPerms = NULL;
+
+    unsigned uTruthMin, uPerm;
+    int k;
+
+    if ( pPerms == NULL )
+    {
+        nPerms = Extra_Factorial( nVars );   
+        pPerms = Extra_Permutations( nVars );
+        nVarsOld = nVars;
+    }
+    else if ( nVarsOld != nVars )
+    {
+        ABC_FREE( pPerms );
+        nPerms = Extra_Factorial( nVars );   
+        pPerms = Extra_Permutations( nVars );
+        nVarsOld = nVars;
+    }
+
+    uTruthMin = 0xFFFFFFFF;
+    for ( k = 0; k < nPerms; k++ )
+    {
+        uPerm = Extra_TruthPermute( uTruth, pPerms[k], nVars, 0 );
+        if ( uTruthMin > uPerm )
+            uTruthMin = uPerm;
+    }
+    return uTruthMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes NP-canonical form using brute-force methods.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Extra_TruthCanonNP( unsigned uTruth, int nVars )
+{
+    static int nVarsOld, nPerms;
+    static char ** pPerms = NULL;
+
+    unsigned uTruthMin, uPhase, uPerm;
+    int nMints, k, i;
+
+    if ( pPerms == NULL )
+    {
+        nPerms = Extra_Factorial( nVars );   
+        pPerms = Extra_Permutations( nVars );
+        nVarsOld = nVars;
+    }
+    else if ( nVarsOld != nVars )
+    {
+        ABC_FREE( pPerms );
+        nPerms = Extra_Factorial( nVars );   
+        pPerms = Extra_Permutations( nVars );
+        nVarsOld = nVars;
+    }
+
+    nMints    = (1 << nVars);
+    uTruthMin = 0xFFFFFFFF;
+    for ( i = 0; i < nMints; i++ )
+    {
+        uPhase = Extra_TruthPolarize( uTruth, i, nVars ); 
+        for ( k = 0; k < nPerms; k++ )
+        {
+            uPerm = Extra_TruthPermute( uPhase, pPerms[k], nVars, 0 );
+            if ( uTruthMin > uPerm )
+                uTruthMin = uPerm;
+        }
+    }
+    return uTruthMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes NPN-canonical form using brute-force methods.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Extra_TruthCanonNPN( unsigned uTruth, int nVars )
+{
+    static int nVarsOld, nPerms;
+    static char ** pPerms = NULL;
+
+    unsigned uTruthMin, uTruthC, uPhase, uPerm;
+    int nMints, k, i;
+
+    if ( pPerms == NULL )
+    {
+        nPerms = Extra_Factorial( nVars );   
+        pPerms = Extra_Permutations( nVars );
+        nVarsOld = nVars;
+    }
+    else if ( nVarsOld != nVars )
+    {
+        ABC_FREE( pPerms );
+        nPerms = Extra_Factorial( nVars );   
+        pPerms = Extra_Permutations( nVars );
+        nVarsOld = nVars;
+    }
+
+    nMints    = (1 << nVars);
+    uTruthC   = (unsigned)( (~uTruth) & ((~((unsigned)0)) >> (32-nMints)) );
+    uTruthMin = 0xFFFFFFFF;
+    for ( i = 0; i < nMints; i++ )
+    {
+        uPhase = Extra_TruthPolarize( uTruth, i, nVars ); 
+        for ( k = 0; k < nPerms; k++ )
+        {
+            uPerm = Extra_TruthPermute( uPhase, pPerms[k], nVars, 0 );
+            if ( uTruthMin > uPerm )
+                uTruthMin = uPerm;
+        }
+        uPhase = Extra_TruthPolarize( uTruthC, i, nVars ); 
+        for ( k = 0; k < nPerms; k++ )
+        {
+            uPerm = Extra_TruthPermute( uPhase, pPerms[k], nVars, 0 );
+            if ( uTruthMin > uPerm )
+                uTruthMin = uPerm;
+        }
+    }
+    return uTruthMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes NPN canonical forms for 4-variable functions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap )
+{
+    unsigned short * uCanons;
+    unsigned char * uMap;
+    unsigned uTruth, uPhase, uPerm;
+    char ** pPerms4, * uPhases, * uPerms;
+    int nFuncs, nClasses;
+    int i, k;
+
+    nFuncs  = (1 << 16);
+    uCanons = ABC_ALLOC( unsigned short, nFuncs );
+    uPhases = ABC_ALLOC( char, nFuncs );
+    uPerms  = ABC_ALLOC( char, nFuncs );
+    uMap    = ABC_ALLOC( unsigned char, nFuncs );
+    memset( uCanons, 0, sizeof(unsigned short) * nFuncs );
+    memset( uPhases, 0, sizeof(char) * nFuncs );
+    memset( uPerms,  0, sizeof(char) * nFuncs );
+    memset( uMap,    0, sizeof(unsigned char) * nFuncs );
+    pPerms4 = Extra_Permutations( 4 );
+
+    nClasses = 1;
+    nFuncs = (1 << 15);
+    for ( uTruth = 1; uTruth < (unsigned)nFuncs; uTruth++ )
+    {
+        // skip already assigned
+        if ( uCanons[uTruth] )
+        {
+            assert( uTruth > uCanons[uTruth] );
+            uMap[~uTruth & 0xFFFF] = uMap[uTruth] = uMap[uCanons[uTruth]];
+            continue;
+        }
+        uMap[uTruth] = nClasses++;
+        for ( i = 0; i < 16; i++ )
+        {
+            uPhase = Extra_TruthPolarize( uTruth, i, 4 );
+            for ( k = 0; k < 24; k++ )
+            {
+                uPerm = Extra_TruthPermute( uPhase, pPerms4[k], 4, 0 );
+                if ( uCanons[uPerm] == 0 )
+                {
+                    uCanons[uPerm] = uTruth;
+                    uPhases[uPerm] = i;
+                    uPerms[uPerm]  = k;
+
+                    uPerm = ~uPerm & 0xFFFF;
+                    uCanons[uPerm] = uTruth;
+                    uPhases[uPerm] = i | 16;
+                    uPerms[uPerm]  = k;
+                }
+                else
+                    assert( uCanons[uPerm] == uTruth );
+            }
+            uPhase = Extra_TruthPolarize( ~uTruth & 0xFFFF, i, 4 ); 
+            for ( k = 0; k < 24; k++ )
+            {
+                uPerm = Extra_TruthPermute( uPhase, pPerms4[k], 4, 0 );
+                if ( uCanons[uPerm] == 0 )
+                {
+                    uCanons[uPerm] = uTruth;
+                    uPhases[uPerm] = i;
+                    uPerms[uPerm]  = k;
+
+                    uPerm = ~uPerm & 0xFFFF;
+                    uCanons[uPerm] = uTruth;
+                    uPhases[uPerm] = i | 16;
+                    uPerms[uPerm]  = k;
+                }
+                else
+                    assert( uCanons[uPerm] == uTruth );
+            }
+        }
+    }
+    uPhases[(1<<16)-1] = 16;
+    assert( nClasses == 222 );
+    ABC_FREE( pPerms4 );
+    if ( puCanons ) 
+        *puCanons = uCanons;
+    else
+        ABC_FREE( uCanons );
+    if ( puPhases ) 
+        *puPhases = uPhases;
+    else
+        ABC_FREE( uPhases );
+    if ( puPerms ) 
+        *puPerms = uPerms;
+    else
+        ABC_FREE( uPerms );
+    if ( puMap ) 
+        *puMap = uMap;
+    else
+        ABC_FREE( uMap );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes NPN canonical forms for 4-variable functions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_Truth3VarN( unsigned ** puCanons, char *** puPhases, char ** ppCounters )
+{
+    int nPhasesMax = 8;
+    unsigned * uCanons;
+    unsigned uTruth, uPhase, uTruth32;
+    char ** uPhases, * pCounters;
+    int nFuncs, nClasses, i;
+
+    nFuncs  = (1 << 8);
+    uCanons = ABC_ALLOC( unsigned, nFuncs );
+    memset( uCanons, 0, sizeof(unsigned) * nFuncs );
+    pCounters = ABC_ALLOC( char, nFuncs );
+    memset( pCounters, 0, sizeof(char) * nFuncs );
+    uPhases = (char **)Extra_ArrayAlloc( nFuncs, nPhasesMax, sizeof(char) );
+    nClasses = 0;
+    for ( uTruth = 0; uTruth < (unsigned)nFuncs; uTruth++ )
+    {
+        // skip already assigned
+        uTruth32 = ((uTruth << 24) | (uTruth << 16) | (uTruth << 8) | uTruth);
+        if ( uCanons[uTruth] )
+        {
+            assert( uTruth32 > uCanons[uTruth] );
+            continue;
+        }
+        nClasses++;
+        for ( i = 0; i < 8; i++ )
+        {
+            uPhase = Extra_TruthPolarize( uTruth, i, 3 );
+            if ( uCanons[uPhase] == 0 && (uTruth || i==0) )
+            {
+                uCanons[uPhase]    = uTruth32;
+                uPhases[uPhase][0] = i;
+                pCounters[uPhase]  = 1;
+            }
+            else
+            {
+                assert( uCanons[uPhase] == uTruth32 );
+                if ( pCounters[uPhase] < nPhasesMax )
+                    uPhases[uPhase][ (int)pCounters[uPhase]++ ] = i;
+            }
+        }
+    }
+    if ( puCanons ) 
+        *puCanons = uCanons;
+    else
+        ABC_FREE( uCanons );
+    if ( puPhases ) 
+        *puPhases = uPhases;
+    else
+        ABC_FREE( uPhases );
+    if ( ppCounters ) 
+        *ppCounters = pCounters;
+    else
+        ABC_FREE( pCounters );
+//    printf( "The number of 3N-classes = %d.\n", nClasses );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes NPN canonical forms for 4-variable functions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_Truth4VarN( unsigned short ** puCanons, char *** puPhases, char ** ppCounters, int nPhasesMax )
+{
+    unsigned short * uCanons;
+    unsigned uTruth, uPhase;
+    char ** uPhases, * pCounters;
+    int nFuncs, nClasses, i;
+
+    nFuncs  = (1 << 16);
+    uCanons = ABC_ALLOC( unsigned short, nFuncs );
+    memset( uCanons, 0, sizeof(unsigned short) * nFuncs );
+    pCounters = ABC_ALLOC( char, nFuncs );
+    memset( pCounters, 0, sizeof(char) * nFuncs );
+    uPhases = (char **)Extra_ArrayAlloc( nFuncs, nPhasesMax, sizeof(char) );
+    nClasses = 0;
+    for ( uTruth = 0; uTruth < (unsigned)nFuncs; uTruth++ )
+    {
+        // skip already assigned
+        if ( uCanons[uTruth] )
+        {
+            assert( uTruth > uCanons[uTruth] );
+            continue;
+        }
+        nClasses++;
+        for ( i = 0; i < 16; i++ )
+        {
+            uPhase = Extra_TruthPolarize( uTruth, i, 4 );
+            if ( uCanons[uPhase] == 0 && (uTruth || i==0) )
+            {
+                uCanons[uPhase]    = uTruth;
+                uPhases[uPhase][0] = i;
+                pCounters[uPhase]  = 1;
+            }
+            else
+            {
+                assert( uCanons[uPhase] == uTruth );
+                if ( pCounters[uPhase] < nPhasesMax )
+                    uPhases[uPhase][ (int)pCounters[uPhase]++ ] = i;
+            }
+        }
+    }
+    if ( puCanons ) 
+        *puCanons = uCanons;
+    else
+        ABC_FREE( uCanons );
+    if ( puPhases ) 
+        *puPhases = uPhases;
+    else
+        ABC_FREE( uPhases );
+    if ( ppCounters ) 
+        *ppCounters = pCounters;
+    else
+        ABC_FREE( pCounters );
+//    printf( "The number of 4N-classes = %d.\n", nClasses );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocated one-memory-chunk array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void ** Extra_ArrayAlloc( int nCols, int nRows, int Size )
+{
+    void ** pRes;
+    char * pBuffer;
+    int i;
+    assert( nCols > 0 && nRows > 0 && Size > 0 );
+    pBuffer = ABC_ALLOC( char, nCols * (sizeof(void *) + nRows * Size) );
+    pRes = (void **)pBuffer;
+    pRes[0] = pBuffer + nCols * sizeof(void *);
+    for ( i = 1; i < nCols; i++ )
+        pRes[i] = (void *)((char *)pRes[0] + i * nRows * Size);
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes a phase of the 3-var function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned short Extra_TruthPerm4One( unsigned uTruth, int Phase )
+{
+    // cases
+    static unsigned short Cases[16] = {
+        0,      // 0000  - skip
+        0,      // 0001  - skip
+        0xCCCC, // 0010  - single var
+        0,      // 0011  - skip
+        0xF0F0, // 0100  - single var
+        1,      // 0101
+        1,      // 0110
+        0,      // 0111  - skip
+        0xFF00, // 1000  - single var
+        1,      // 1001
+        1,      // 1010
+        1,      // 1011
+        1,      // 1100
+        1,      // 1101
+        1,      // 1110
+        0       // 1111  - skip
+    };
+    // permutations
+    static int Perms[16][4] = {
+        { 0, 0, 0, 0 }, // 0000  - skip
+        { 0, 0, 0, 0 }, // 0001  - skip
+        { 0, 0, 0, 0 }, // 0010  - single var
+        { 0, 0, 0, 0 }, // 0011  - skip
+        { 0, 0, 0, 0 }, // 0100  - single var
+        { 0, 2, 1, 3 }, // 0101
+        { 2, 0, 1, 3 }, // 0110
+        { 0, 0, 0, 0 }, // 0111  - skip
+        { 0, 0, 0, 0 }, // 1000  - single var
+        { 0, 2, 3, 1 }, // 1001
+        { 2, 0, 3, 1 }, // 1010
+        { 0, 1, 3, 2 }, // 1011
+        { 2, 3, 0, 1 }, // 1100
+        { 0, 3, 1, 2 }, // 1101
+        { 3, 0, 1, 2 }, // 1110
+        { 0, 0, 0, 0 }  // 1111  - skip
+    };
+    int i, k, iRes;
+    unsigned uTruthRes;
+    assert( Phase >= 0 && Phase < 16 );
+    if ( Cases[Phase] == 0 )
+        return uTruth;
+    if ( Cases[Phase] > 1 )
+        return Cases[Phase];
+    uTruthRes = 0;
+    for ( i = 0; i < 16; i++ )
+        if ( uTruth & (1 << i) )
+        {
+            for ( iRes = 0, k = 0; k < 4; k++ )
+                if ( i & (1 << Perms[Phase][k]) )
+                    iRes |= (1 << k);
+            uTruthRes |= (1 << iRes);
+        }
+    return uTruthRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes a phase of the 3-var function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Extra_TruthPerm5One( unsigned uTruth, int Phase )
+{
+    // cases
+    static unsigned Cases[32] = {
+        0,          // 00000  - skip
+        0,          // 00001  - skip
+        0xCCCCCCCC, // 00010  - single var
+        0,          // 00011  - skip
+        0xF0F0F0F0, // 00100  - single var
+        1,          // 00101
+        1,          // 00110
+        0,          // 00111  - skip
+        0xFF00FF00, // 01000  - single var
+        1,          // 01001
+        1,          // 01010
+        1,          // 01011
+        1,          // 01100
+        1,          // 01101
+        1,          // 01110
+        0,          // 01111  - skip
+        0xFFFF0000, // 10000  - skip
+        1,          // 10001
+        1,          // 10010
+        1,          // 10011
+        1,          // 10100
+        1,          // 10101
+        1,          // 10110
+        1,          // 10111  - four var
+        1,          // 11000
+        1,          // 11001
+        1,          // 11010
+        1,          // 11011  - four var
+        1,          // 11100
+        1,          // 11101  - four var
+        1,          // 11110  - four var
+        0           // 11111  - skip
+    };
+    // permutations
+    static int Perms[32][5] = {
+        { 0, 0, 0, 0, 0 }, // 00000  - skip
+        { 0, 0, 0, 0, 0 }, // 00001  - skip
+        { 0, 0, 0, 0, 0 }, // 00010  - single var
+        { 0, 0, 0, 0, 0 }, // 00011  - skip
+        { 0, 0, 0, 0, 0 }, // 00100  - single var
+        { 0, 2, 1, 3, 4 }, // 00101
+        { 2, 0, 1, 3, 4 }, // 00110
+        { 0, 0, 0, 0, 0 }, // 00111  - skip
+        { 0, 0, 0, 0, 0 }, // 01000  - single var
+        { 0, 2, 3, 1, 4 }, // 01001
+        { 2, 0, 3, 1, 4 }, // 01010
+        { 0, 1, 3, 2, 4 }, // 01011
+        { 2, 3, 0, 1, 4 }, // 01100
+        { 0, 3, 1, 2, 4 }, // 01101
+        { 3, 0, 1, 2, 4 }, // 01110
+        { 0, 0, 0, 0, 0 }, // 01111  - skip
+        { 0, 0, 0, 0, 0 }, // 10000  - single var
+        { 0, 4, 2, 3, 1 }, // 10001
+        { 4, 0, 2, 3, 1 }, // 10010
+        { 0, 1, 3, 4, 2 }, // 10011
+        { 2, 3, 0, 4, 1 }, // 10100
+        { 0, 3, 1, 4, 2 }, // 10101
+        { 3, 0, 1, 4, 2 }, // 10110
+        { 0, 1, 2, 4, 3 }, // 10111  - four var
+        { 2, 3, 4, 0, 1 }, // 11000
+        { 0, 3, 4, 1, 2 }, // 11001
+        { 3, 0, 4, 1, 2 }, // 11010
+        { 0, 1, 4, 2, 3 }, // 11011  - four var
+        { 3, 4, 0, 1, 2 }, // 11100
+        { 0, 4, 1, 2, 3 }, // 11101  - four var
+        { 4, 0, 1, 2, 3 }, // 11110  - four var
+        { 0, 0, 0, 0, 0 }  // 11111  - skip
+    };
+    int i, k, iRes;
+    unsigned uTruthRes;
+    assert( Phase >= 0 && Phase < 32 );
+    if ( Cases[Phase] == 0 )
+        return uTruth;
+    if ( Cases[Phase] > 1 )
+        return Cases[Phase];
+    uTruthRes = 0;
+    for ( i = 0; i < 32; i++ )
+        if ( uTruth & (1 << i) )
+        {
+            for ( iRes = 0, k = 0; k < 5; k++ )
+                if ( i & (1 << Perms[Phase][k]) )
+                    iRes |= (1 << k);
+            uTruthRes |= (1 << iRes);
+        }
+    return uTruthRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes a phase of the 3-var function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_TruthPerm6One( unsigned * uTruth, int Phase, unsigned * uTruthRes )
+{
+    // cases
+    static unsigned Cases[64] = {
+        0,          // 000000  - skip
+        0,          // 000001  - skip
+        0xCCCCCCCC, // 000010  - single var
+        0,          // 000011  - skip
+        0xF0F0F0F0, // 000100  - single var
+        1,          // 000101
+        1,          // 000110
+        0,          // 000111  - skip
+        0xFF00FF00, // 001000  - single var
+        1,          // 001001
+        1,          // 001010
+        1,          // 001011
+        1,          // 001100
+        1,          // 001101
+        1,          // 001110
+        0,          // 001111  - skip
+        0xFFFF0000, // 010000  - skip
+        1,          // 010001
+        1,          // 010010
+        1,          // 010011
+        1,          // 010100
+        1,          // 010101
+        1,          // 010110
+        1,          // 010111  - four var
+        1,          // 011000
+        1,          // 011001
+        1,          // 011010
+        1,          // 011011  - four var
+        1,          // 011100
+        1,          // 011101  - four var
+        1,          // 011110  - four var
+        0,          // 011111  - skip
+        0xFFFFFFFF, // 100000  - single var
+        1,          // 100001 
+        1,          // 100010  
+        1,          // 100011  
+        1,          // 100100  
+        1,          // 100101
+        1,          // 100110
+        1,          // 100111  
+        1,          // 101000  
+        1,          // 101001
+        1,          // 101010
+        1,          // 101011
+        1,          // 101100
+        1,          // 101101
+        1,          // 101110
+        1,          // 101111  
+        1,          // 110000  
+        1,          // 110001
+        1,          // 110010
+        1,          // 110011
+        1,          // 110100
+        1,          // 110101
+        1,          // 110110
+        1,          // 110111  
+        1,          // 111000
+        1,          // 111001
+        1,          // 111010
+        1,          // 111011  
+        1,          // 111100
+        1,          // 111101  
+        1,          // 111110  
+        0           // 111111  - skip
+    };
+    // permutations
+    static int Perms[64][6] = {
+        { 0, 0, 0, 0, 0, 0 }, // 000000  - skip
+        { 0, 0, 0, 0, 0, 0 }, // 000001  - skip
+        { 0, 0, 0, 0, 0, 0 }, // 000010  - single var
+        { 0, 0, 0, 0, 0, 0 }, // 000011  - skip
+        { 0, 0, 0, 0, 0, 0 }, // 000100  - single var
+        { 0, 2, 1, 3, 4, 5 }, // 000101
+        { 2, 0, 1, 3, 4, 5 }, // 000110
+        { 0, 0, 0, 0, 0, 0 }, // 000111  - skip
+        { 0, 0, 0, 0, 0, 0 }, // 001000  - single var
+        { 0, 2, 3, 1, 4, 5 }, // 001001
+        { 2, 0, 3, 1, 4, 5 }, // 001010
+        { 0, 1, 3, 2, 4, 5 }, // 001011
+        { 2, 3, 0, 1, 4, 5 }, // 001100
+        { 0, 3, 1, 2, 4, 5 }, // 001101
+        { 3, 0, 1, 2, 4, 5 }, // 001110
+        { 0, 0, 0, 0, 0, 0 }, // 001111  - skip
+        { 0, 0, 0, 0, 0, 0 }, // 010000  - skip
+        { 0, 4, 2, 3, 1, 5 }, // 010001
+        { 4, 0, 2, 3, 1, 5 }, // 010010
+        { 0, 1, 3, 4, 2, 5 }, // 010011
+        { 2, 3, 0, 4, 1, 5 }, // 010100
+        { 0, 3, 1, 4, 2, 5 }, // 010101
+        { 3, 0, 1, 4, 2, 5 }, // 010110
+        { 0, 1, 2, 4, 3, 5 }, // 010111  - four var
+        { 2, 3, 4, 0, 1, 5 }, // 011000
+        { 0, 3, 4, 1, 2, 5 }, // 011001
+        { 3, 0, 4, 1, 2, 5 }, // 011010
+        { 0, 1, 4, 2, 3, 5 }, // 011011  - four var
+        { 3, 4, 0, 1, 2, 5 }, // 011100
+        { 0, 4, 1, 2, 3, 5 }, // 011101  - four var
+        { 4, 0, 1, 2, 3, 5 }, // 011110  - four var
+        { 0, 0, 0, 0, 0, 0 }, // 011111  - skip
+        { 0, 0, 0, 0, 0, 0 }, // 100000  - single var
+        { 0, 2, 3, 4, 5, 1 }, // 100001 
+        { 2, 0, 3, 4, 5, 1 }, // 100010  
+        { 0, 1, 3, 4, 5, 2 }, // 100011  
+        { 2, 3, 0, 4, 5, 1 }, // 100100  
+        { 0, 3, 1, 4, 5, 2 }, // 100101
+        { 3, 0, 1, 4, 5, 2 }, // 100110
+        { 0, 1, 2, 4, 5, 3 }, // 100111  
+        { 2, 3, 4, 0, 5, 1 }, // 101000  
+        { 0, 3, 4, 1, 5, 2 }, // 101001
+        { 3, 0, 4, 1, 5, 2 }, // 101010
+        { 0, 1, 4, 2, 5, 3 }, // 101011
+        { 3, 4, 0, 1, 5, 2 }, // 101100
+        { 0, 4, 1, 2, 5, 3 }, // 101101
+        { 4, 0, 1, 2, 5, 3 }, // 101110
+        { 0, 1, 2, 3, 5, 4 }, // 101111  
+        { 2, 3, 4, 5, 0, 1 }, // 110000  
+        { 0, 3, 4, 5, 1, 2 }, // 110001
+        { 3, 0, 4, 5, 1, 2 }, // 110010
+        { 0, 1, 4, 5, 2, 3 }, // 110011
+        { 3, 4, 0, 5, 1, 2 }, // 110100
+        { 0, 4, 1, 5, 2, 3 }, // 110101
+        { 4, 0, 1, 5, 2, 3 }, // 110110
+        { 0, 1, 2, 5, 3, 4 }, // 110111  
+        { 3, 4, 5, 0, 1, 2 }, // 111000
+        { 0, 4, 5, 1, 2, 3 }, // 111001
+        { 4, 0, 5, 1, 2, 3 }, // 111010
+        { 0, 1, 5, 2, 3, 4 }, // 111011  
+        { 4, 5, 0, 1, 2, 3 }, // 111100
+        { 0, 5, 1, 2, 3, 4 }, // 111101  
+        { 5, 0, 1, 2, 3, 4 }, // 111110  
+        { 0, 0, 0, 0, 0, 0 }  // 111111  - skip
+    };
+    int i, k, iRes;
+    assert( Phase >= 0 && Phase < 64 );
+    if ( Cases[Phase] == 0 )
+    {
+        uTruthRes[0] = uTruth[0];
+        uTruthRes[1] = uTruth[1];
+        return;
+    }
+    if ( Cases[Phase] > 1 )
+    {
+        if ( Phase == 32 )
+        {
+            uTruthRes[0] = 0x00000000;
+            uTruthRes[1] = 0xFFFFFFFF;
+        }
+        else
+        {
+            uTruthRes[0] = Cases[Phase];
+            uTruthRes[1] = Cases[Phase];
+        }
+        return;
+    }
+    uTruthRes[0] = 0;
+    uTruthRes[1] = 0;
+    for ( i = 0; i < 64; i++ )
+    {
+        if ( i < 32 )
+        {
+            if ( uTruth[0] & (1 << i) )
+            {
+                for ( iRes = 0, k = 0; k < 6; k++ )
+                    if ( i & (1 << Perms[Phase][k]) )
+                        iRes |= (1 << k);
+                if ( iRes < 32 )
+                    uTruthRes[0] |= (1 << iRes);
+                else
+                    uTruthRes[1] |= (1 << (iRes-32));
+            }
+        }
+        else
+        {
+            if ( uTruth[1] & (1 << (i-32)) )
+            {
+                for ( iRes = 0, k = 0; k < 6; k++ )
+                    if ( i & (1 << Perms[Phase][k]) )
+                        iRes |= (1 << k);
+                if ( iRes < 32 )
+                    uTruthRes[0] |= (1 << iRes);
+                else
+                    uTruthRes[1] |= (1 << (iRes-32));
+            }
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes a phase of the 8-var function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_TruthExpand( int nVars, int nWords, unsigned * puTruth, unsigned uPhase, unsigned * puTruthR )
+{
+    // elementary truth tables
+    static unsigned uTruths[8][8] = {
+        { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA },
+        { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC },
+        { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 },
+        { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 },
+        { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, 
+        { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, 
+        { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, 
+        { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } 
+    };
+    static char Cases[256] = {
+         0, // 00000000
+         0, // 00000001
+         1, // 00000010
+         0, // 00000011
+         2, // 00000100
+        -1, // 00000101
+        -1, // 00000110
+         0, // 00000111
+         3, // 00001000
+        -1, // 00001001
+        -1, // 00001010
+        -1, // 00001011
+        -1, // 00001100
+        -1, // 00001101
+        -1, // 00001110
+         0, // 00001111
+         4, // 00010000
+        -1, // 00010001
+        -1, // 00010010
+        -1, // 00010011
+        -1, // 00010100
+        -1, // 00010101
+        -1, // 00010110
+        -1, // 00010111
+        -1, // 00011000
+        -1, // 00011001
+        -1, // 00011010
+        -1, // 00011011
+        -1, // 00011100
+        -1, // 00011101
+        -1, // 00011110
+         0, // 00011111
+         5, // 00100000
+        -1, // 00100001
+        -1, // 00100010
+        -1, // 00100011
+        -1, // 00100100
+        -1, // 00100101
+        -1, // 00100110
+        -1, // 00100111
+        -1, // 00101000
+        -1, // 00101001
+        -1, // 00101010
+        -1, // 00101011
+        -1, // 00101100
+        -1, // 00101101
+        -1, // 00101110
+        -1, // 00101111
+        -1, // 00110000
+        -1, // 00110001
+        -1, // 00110010
+        -1, // 00110011
+        -1, // 00110100
+        -1, // 00110101
+        -1, // 00110110
+        -1, // 00110111
+        -1, // 00111000
+        -1, // 00111001
+        -1, // 00111010
+        -1, // 00111011
+        -1, // 00111100
+        -1, // 00111101
+        -1, // 00111110
+         0, // 00111111
+         6, // 01000000
+        -1, // 01000001
+        -1, // 01000010
+        -1, // 01000011
+        -1, // 01000100
+        -1, // 01000101
+        -1, // 01000110
+        -1, // 01000111
+        -1, // 01001000
+        -1, // 01001001
+        -1, // 01001010
+        -1, // 01001011
+        -1, // 01001100
+        -1, // 01001101
+        -1, // 01001110
+        -1, // 01001111
+        -1, // 01010000
+        -1, // 01010001
+        -1, // 01010010
+        -1, // 01010011
+        -1, // 01010100
+        -1, // 01010101
+        -1, // 01010110
+        -1, // 01010111
+        -1, // 01011000
+        -1, // 01011001
+        -1, // 01011010
+        -1, // 01011011
+        -1, // 01011100
+        -1, // 01011101
+        -1, // 01011110
+        -1, // 01011111
+        -1, // 01100000
+        -1, // 01100001
+        -1, // 01100010
+        -1, // 01100011
+        -1, // 01100100
+        -1, // 01100101
+        -1, // 01100110
+        -1, // 01100111
+        -1, // 01101000
+        -1, // 01101001
+        -1, // 01101010
+        -1, // 01101011
+        -1, // 01101100
+        -1, // 01101101
+        -1, // 01101110
+        -1, // 01101111
+        -1, // 01110000
+        -1, // 01110001
+        -1, // 01110010
+        -1, // 01110011
+        -1, // 01110100
+        -1, // 01110101
+        -1, // 01110110
+        -1, // 01110111
+        -1, // 01111000
+        -1, // 01111001
+        -1, // 01111010
+        -1, // 01111011
+        -1, // 01111100
+        -1, // 01111101
+        -1, // 01111110
+         0, // 01111111
+         7, // 10000000
+        -1, // 10000001
+        -1, // 10000010
+        -1, // 10000011
+        -1, // 10000100
+        -1, // 10000101
+        -1, // 10000110
+        -1, // 10000111
+        -1, // 10001000
+        -1, // 10001001
+        -1, // 10001010
+        -1, // 10001011
+        -1, // 10001100
+        -1, // 10001101
+        -1, // 10001110
+        -1, // 10001111
+        -1, // 10010000
+        -1, // 10010001
+        -1, // 10010010
+        -1, // 10010011
+        -1, // 10010100
+        -1, // 10010101
+        -1, // 10010110
+        -1, // 10010111
+        -1, // 10011000
+        -1, // 10011001
+        -1, // 10011010
+        -1, // 10011011
+        -1, // 10011100
+        -1, // 10011101
+        -1, // 10011110
+        -1, // 10011111
+        -1, // 10100000
+        -1, // 10100001
+        -1, // 10100010
+        -1, // 10100011
+        -1, // 10100100
+        -1, // 10100101
+        -1, // 10100110
+        -1, // 10100111
+        -1, // 10101000
+        -1, // 10101001
+        -1, // 10101010
+        -1, // 10101011
+        -1, // 10101100
+        -1, // 10101101
+        -1, // 10101110
+        -1, // 10101111
+        -1, // 10110000
+        -1, // 10110001
+        -1, // 10110010
+        -1, // 10110011
+        -1, // 10110100
+        -1, // 10110101
+        -1, // 10110110
+        -1, // 10110111
+        -1, // 10111000
+        -1, // 10111001
+        -1, // 10111010
+        -1, // 10111011
+        -1, // 10111100
+        -1, // 10111101
+        -1, // 10111110
+        -1, // 10111111
+        -1, // 11000000
+        -1, // 11000001
+        -1, // 11000010
+        -1, // 11000011
+        -1, // 11000100
+        -1, // 11000101
+        -1, // 11000110
+        -1, // 11000111
+        -1, // 11001000
+        -1, // 11001001
+        -1, // 11001010
+        -1, // 11001011
+        -1, // 11001100
+        -1, // 11001101
+        -1, // 11001110
+        -1, // 11001111
+        -1, // 11010000
+        -1, // 11010001
+        -1, // 11010010
+        -1, // 11010011
+        -1, // 11010100
+        -1, // 11010101
+        -1, // 11010110
+        -1, // 11010111
+        -1, // 11011000
+        -1, // 11011001
+        -1, // 11011010
+        -1, // 11011011
+        -1, // 11011100
+        -1, // 11011101
+        -1, // 11011110
+        -1, // 11011111
+        -1, // 11100000
+        -1, // 11100001
+        -1, // 11100010
+        -1, // 11100011
+        -1, // 11100100
+        -1, // 11100101
+        -1, // 11100110
+        -1, // 11100111
+        -1, // 11101000
+        -1, // 11101001
+        -1, // 11101010
+        -1, // 11101011
+        -1, // 11101100
+        -1, // 11101101
+        -1, // 11101110
+        -1, // 11101111
+        -1, // 11110000
+        -1, // 11110001
+        -1, // 11110010
+        -1, // 11110011
+        -1, // 11110100
+        -1, // 11110101
+        -1, // 11110110
+        -1, // 11110111
+        -1, // 11111000
+        -1, // 11111001
+        -1, // 11111010
+        -1, // 11111011
+        -1, // 11111100
+        -1, // 11111101
+        -1, // 11111110
+         0  // 11111111
+    };
+    static char Perms[256][8] = {
+        { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000000
+        { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000001
+        { 1, 0, 2, 3, 4, 5, 6, 7 }, // 00000010
+        { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000011
+        { 1, 2, 0, 3, 4, 5, 6, 7 }, // 00000100
+        { 0, 2, 1, 3, 4, 5, 6, 7 }, // 00000101
+        { 2, 0, 1, 3, 4, 5, 6, 7 }, // 00000110
+        { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000111
+        { 1, 2, 3, 0, 4, 5, 6, 7 }, // 00001000
+        { 0, 2, 3, 1, 4, 5, 6, 7 }, // 00001001
+        { 2, 0, 3, 1, 4, 5, 6, 7 }, // 00001010
+        { 0, 1, 3, 2, 4, 5, 6, 7 }, // 00001011
+        { 2, 3, 0, 1, 4, 5, 6, 7 }, // 00001100
+        { 0, 3, 1, 2, 4, 5, 6, 7 }, // 00001101
+        { 3, 0, 1, 2, 4, 5, 6, 7 }, // 00001110
+        { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00001111
+        { 1, 2, 3, 4, 0, 5, 6, 7 }, // 00010000
+        { 0, 2, 3, 4, 1, 5, 6, 7 }, // 00010001
+        { 2, 0, 3, 4, 1, 5, 6, 7 }, // 00010010
+        { 0, 1, 3, 4, 2, 5, 6, 7 }, // 00010011
+        { 2, 3, 0, 4, 1, 5, 6, 7 }, // 00010100
+        { 0, 3, 1, 4, 2, 5, 6, 7 }, // 00010101
+        { 3, 0, 1, 4, 2, 5, 6, 7 }, // 00010110
+        { 0, 1, 2, 4, 3, 5, 6, 7 }, // 00010111
+        { 2, 3, 4, 0, 1, 5, 6, 7 }, // 00011000
+        { 0, 3, 4, 1, 2, 5, 6, 7 }, // 00011001
+        { 3, 0, 4, 1, 2, 5, 6, 7 }, // 00011010
+        { 0, 1, 4, 2, 3, 5, 6, 7 }, // 00011011
+        { 3, 4, 0, 1, 2, 5, 6, 7 }, // 00011100
+        { 0, 4, 1, 2, 3, 5, 6, 7 }, // 00011101
+        { 4, 0, 1, 2, 3, 5, 6, 7 }, // 00011110
+        { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00011111
+        { 1, 2, 3, 4, 5, 0, 6, 7 }, // 00100000
+        { 0, 2, 3, 4, 5, 1, 6, 7 }, // 00100001
+        { 2, 0, 3, 4, 5, 1, 6, 7 }, // 00100010
+        { 0, 1, 3, 4, 5, 2, 6, 7 }, // 00100011
+        { 2, 3, 0, 4, 5, 1, 6, 7 }, // 00100100
+        { 0, 3, 1, 4, 5, 2, 6, 7 }, // 00100101
+        { 3, 0, 1, 4, 5, 2, 6, 7 }, // 00100110
+        { 0, 1, 2, 4, 5, 3, 6, 7 }, // 00100111
+        { 2, 3, 4, 0, 5, 1, 6, 7 }, // 00101000
+        { 0, 3, 4, 1, 5, 2, 6, 7 }, // 00101001
+        { 3, 0, 4, 1, 5, 2, 6, 7 }, // 00101010
+        { 0, 1, 4, 2, 5, 3, 6, 7 }, // 00101011
+        { 3, 4, 0, 1, 5, 2, 6, 7 }, // 00101100
+        { 0, 4, 1, 2, 5, 3, 6, 7 }, // 00101101
+        { 4, 0, 1, 2, 5, 3, 6, 7 }, // 00101110
+        { 0, 1, 2, 3, 5, 4, 6, 7 }, // 00101111
+        { 2, 3, 4, 5, 0, 1, 6, 7 }, // 00110000
+        { 0, 3, 4, 5, 1, 2, 6, 7 }, // 00110001
+        { 3, 0, 4, 5, 1, 2, 6, 7 }, // 00110010
+        { 0, 1, 4, 5, 2, 3, 6, 7 }, // 00110011
+        { 3, 4, 0, 5, 1, 2, 6, 7 }, // 00110100
+        { 0, 4, 1, 5, 2, 3, 6, 7 }, // 00110101
+        { 4, 0, 1, 5, 2, 3, 6, 7 }, // 00110110
+        { 0, 1, 2, 5, 3, 4, 6, 7 }, // 00110111
+        { 3, 4, 5, 0, 1, 2, 6, 7 }, // 00111000
+        { 0, 4, 5, 1, 2, 3, 6, 7 }, // 00111001
+        { 4, 0, 5, 1, 2, 3, 6, 7 }, // 00111010
+        { 0, 1, 5, 2, 3, 4, 6, 7 }, // 00111011
+        { 4, 5, 0, 1, 2, 3, 6, 7 }, // 00111100
+        { 0, 5, 1, 2, 3, 4, 6, 7 }, // 00111101
+        { 5, 0, 1, 2, 3, 4, 6, 7 }, // 00111110
+        { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00111111
+        { 1, 2, 3, 4, 5, 6, 0, 7 }, // 01000000
+        { 0, 2, 3, 4, 5, 6, 1, 7 }, // 01000001
+        { 2, 0, 3, 4, 5, 6, 1, 7 }, // 01000010
+        { 0, 1, 3, 4, 5, 6, 2, 7 }, // 01000011
+        { 2, 3, 0, 4, 5, 6, 1, 7 }, // 01000100
+        { 0, 3, 1, 4, 5, 6, 2, 7 }, // 01000101
+        { 3, 0, 1, 4, 5, 6, 2, 7 }, // 01000110
+        { 0, 1, 2, 4, 5, 6, 3, 7 }, // 01000111
+        { 2, 3, 4, 0, 5, 6, 1, 7 }, // 01001000
+        { 0, 3, 4, 1, 5, 6, 2, 7 }, // 01001001
+        { 3, 0, 4, 1, 5, 6, 2, 7 }, // 01001010
+        { 0, 1, 4, 2, 5, 6, 3, 7 }, // 01001011
+        { 3, 4, 0, 1, 5, 6, 2, 7 }, // 01001100
+        { 0, 4, 1, 2, 5, 6, 3, 7 }, // 01001101
+        { 4, 0, 1, 2, 5, 6, 3, 7 }, // 01001110
+        { 0, 1, 2, 3, 5, 6, 4, 7 }, // 01001111
+        { 2, 3, 4, 5, 0, 6, 1, 7 }, // 01010000
+        { 0, 3, 4, 5, 1, 6, 2, 7 }, // 01010001
+        { 3, 0, 4, 5, 1, 6, 2, 7 }, // 01010010
+        { 0, 1, 4, 5, 2, 6, 3, 7 }, // 01010011
+        { 3, 4, 0, 5, 1, 6, 2, 7 }, // 01010100
+        { 0, 4, 1, 5, 2, 6, 3, 7 }, // 01010101
+        { 4, 0, 1, 5, 2, 6, 3, 7 }, // 01010110
+        { 0, 1, 2, 5, 3, 6, 4, 7 }, // 01010111
+        { 3, 4, 5, 0, 1, 6, 2, 7 }, // 01011000
+        { 0, 4, 5, 1, 2, 6, 3, 7 }, // 01011001
+        { 4, 0, 5, 1, 2, 6, 3, 7 }, // 01011010
+        { 0, 1, 5, 2, 3, 6, 4, 7 }, // 01011011
+        { 4, 5, 0, 1, 2, 6, 3, 7 }, // 01011100
+        { 0, 5, 1, 2, 3, 6, 4, 7 }, // 01011101
+        { 5, 0, 1, 2, 3, 6, 4, 7 }, // 01011110
+        { 0, 1, 2, 3, 4, 6, 5, 7 }, // 01011111
+        { 2, 3, 4, 5, 6, 0, 1, 7 }, // 01100000
+        { 0, 3, 4, 5, 6, 1, 2, 7 }, // 01100001
+        { 3, 0, 4, 5, 6, 1, 2, 7 }, // 01100010
+        { 0, 1, 4, 5, 6, 2, 3, 7 }, // 01100011
+        { 3, 4, 0, 5, 6, 1, 2, 7 }, // 01100100
+        { 0, 4, 1, 5, 6, 2, 3, 7 }, // 01100101
+        { 4, 0, 1, 5, 6, 2, 3, 7 }, // 01100110
+        { 0, 1, 2, 5, 6, 3, 4, 7 }, // 01100111
+        { 3, 4, 5, 0, 6, 1, 2, 7 }, // 01101000
+        { 0, 4, 5, 1, 6, 2, 3, 7 }, // 01101001
+        { 4, 0, 5, 1, 6, 2, 3, 7 }, // 01101010
+        { 0, 1, 5, 2, 6, 3, 4, 7 }, // 01101011
+        { 4, 5, 0, 1, 6, 2, 3, 7 }, // 01101100
+        { 0, 5, 1, 2, 6, 3, 4, 7 }, // 01101101
+        { 5, 0, 1, 2, 6, 3, 4, 7 }, // 01101110
+        { 0, 1, 2, 3, 6, 4, 5, 7 }, // 01101111
+        { 3, 4, 5, 6, 0, 1, 2, 7 }, // 01110000
+        { 0, 4, 5, 6, 1, 2, 3, 7 }, // 01110001
+        { 4, 0, 5, 6, 1, 2, 3, 7 }, // 01110010
+        { 0, 1, 5, 6, 2, 3, 4, 7 }, // 01110011
+        { 4, 5, 0, 6, 1, 2, 3, 7 }, // 01110100
+        { 0, 5, 1, 6, 2, 3, 4, 7 }, // 01110101
+        { 5, 0, 1, 6, 2, 3, 4, 7 }, // 01110110
+        { 0, 1, 2, 6, 3, 4, 5, 7 }, // 01110111
+        { 4, 5, 6, 0, 1, 2, 3, 7 }, // 01111000
+        { 0, 5, 6, 1, 2, 3, 4, 7 }, // 01111001
+        { 5, 0, 6, 1, 2, 3, 4, 7 }, // 01111010
+        { 0, 1, 6, 2, 3, 4, 5, 7 }, // 01111011
+        { 5, 6, 0, 1, 2, 3, 4, 7 }, // 01111100
+        { 0, 6, 1, 2, 3, 4, 5, 7 }, // 01111101
+        { 6, 0, 1, 2, 3, 4, 5, 7 }, // 01111110
+        { 0, 1, 2, 3, 4, 5, 6, 7 }, // 01111111
+        { 1, 2, 3, 4, 5, 6, 7, 0 }, // 10000000
+        { 0, 2, 3, 4, 5, 6, 7, 1 }, // 10000001
+        { 2, 0, 3, 4, 5, 6, 7, 1 }, // 10000010
+        { 0, 1, 3, 4, 5, 6, 7, 2 }, // 10000011
+        { 2, 3, 0, 4, 5, 6, 7, 1 }, // 10000100
+        { 0, 3, 1, 4, 5, 6, 7, 2 }, // 10000101
+        { 3, 0, 1, 4, 5, 6, 7, 2 }, // 10000110
+        { 0, 1, 2, 4, 5, 6, 7, 3 }, // 10000111
+        { 2, 3, 4, 0, 5, 6, 7, 1 }, // 10001000
+        { 0, 3, 4, 1, 5, 6, 7, 2 }, // 10001001
+        { 3, 0, 4, 1, 5, 6, 7, 2 }, // 10001010
+        { 0, 1, 4, 2, 5, 6, 7, 3 }, // 10001011
+        { 3, 4, 0, 1, 5, 6, 7, 2 }, // 10001100
+        { 0, 4, 1, 2, 5, 6, 7, 3 }, // 10001101
+        { 4, 0, 1, 2, 5, 6, 7, 3 }, // 10001110
+        { 0, 1, 2, 3, 5, 6, 7, 4 }, // 10001111
+        { 2, 3, 4, 5, 0, 6, 7, 1 }, // 10010000
+        { 0, 3, 4, 5, 1, 6, 7, 2 }, // 10010001
+        { 3, 0, 4, 5, 1, 6, 7, 2 }, // 10010010
+        { 0, 1, 4, 5, 2, 6, 7, 3 }, // 10010011
+        { 3, 4, 0, 5, 1, 6, 7, 2 }, // 10010100
+        { 0, 4, 1, 5, 2, 6, 7, 3 }, // 10010101
+        { 4, 0, 1, 5, 2, 6, 7, 3 }, // 10010110
+        { 0, 1, 2, 5, 3, 6, 7, 4 }, // 10010111
+        { 3, 4, 5, 0, 1, 6, 7, 2 }, // 10011000
+        { 0, 4, 5, 1, 2, 6, 7, 3 }, // 10011001
+        { 4, 0, 5, 1, 2, 6, 7, 3 }, // 10011010
+        { 0, 1, 5, 2, 3, 6, 7, 4 }, // 10011011
+        { 4, 5, 0, 1, 2, 6, 7, 3 }, // 10011100
+        { 0, 5, 1, 2, 3, 6, 7, 4 }, // 10011101
+        { 5, 0, 1, 2, 3, 6, 7, 4 }, // 10011110
+        { 0, 1, 2, 3, 4, 6, 7, 5 }, // 10011111
+        { 2, 3, 4, 5, 6, 0, 7, 1 }, // 10100000
+        { 0, 3, 4, 5, 6, 1, 7, 2 }, // 10100001
+        { 3, 0, 4, 5, 6, 1, 7, 2 }, // 10100010
+        { 0, 1, 4, 5, 6, 2, 7, 3 }, // 10100011
+        { 3, 4, 0, 5, 6, 1, 7, 2 }, // 10100100
+        { 0, 4, 1, 5, 6, 2, 7, 3 }, // 10100101
+        { 4, 0, 1, 5, 6, 2, 7, 3 }, // 10100110
+        { 0, 1, 2, 5, 6, 3, 7, 4 }, // 10100111
+        { 3, 4, 5, 0, 6, 1, 7, 2 }, // 10101000
+        { 0, 4, 5, 1, 6, 2, 7, 3 }, // 10101001
+        { 4, 0, 5, 1, 6, 2, 7, 3 }, // 10101010
+        { 0, 1, 5, 2, 6, 3, 7, 4 }, // 10101011
+        { 4, 5, 0, 1, 6, 2, 7, 3 }, // 10101100
+        { 0, 5, 1, 2, 6, 3, 7, 4 }, // 10101101
+        { 5, 0, 1, 2, 6, 3, 7, 4 }, // 10101110
+        { 0, 1, 2, 3, 6, 4, 7, 5 }, // 10101111
+        { 3, 4, 5, 6, 0, 1, 7, 2 }, // 10110000
+        { 0, 4, 5, 6, 1, 2, 7, 3 }, // 10110001
+        { 4, 0, 5, 6, 1, 2, 7, 3 }, // 10110010
+        { 0, 1, 5, 6, 2, 3, 7, 4 }, // 10110011
+        { 4, 5, 0, 6, 1, 2, 7, 3 }, // 10110100
+        { 0, 5, 1, 6, 2, 3, 7, 4 }, // 10110101
+        { 5, 0, 1, 6, 2, 3, 7, 4 }, // 10110110
+        { 0, 1, 2, 6, 3, 4, 7, 5 }, // 10110111
+        { 4, 5, 6, 0, 1, 2, 7, 3 }, // 10111000
+        { 0, 5, 6, 1, 2, 3, 7, 4 }, // 10111001
+        { 5, 0, 6, 1, 2, 3, 7, 4 }, // 10111010
+        { 0, 1, 6, 2, 3, 4, 7, 5 }, // 10111011
+        { 5, 6, 0, 1, 2, 3, 7, 4 }, // 10111100
+        { 0, 6, 1, 2, 3, 4, 7, 5 }, // 10111101
+        { 6, 0, 1, 2, 3, 4, 7, 5 }, // 10111110
+        { 0, 1, 2, 3, 4, 5, 7, 6 }, // 10111111
+        { 2, 3, 4, 5, 6, 7, 0, 1 }, // 11000000
+        { 0, 3, 4, 5, 6, 7, 1, 2 }, // 11000001
+        { 3, 0, 4, 5, 6, 7, 1, 2 }, // 11000010
+        { 0, 1, 4, 5, 6, 7, 2, 3 }, // 11000011
+        { 3, 4, 0, 5, 6, 7, 1, 2 }, // 11000100
+        { 0, 4, 1, 5, 6, 7, 2, 3 }, // 11000101
+        { 4, 0, 1, 5, 6, 7, 2, 3 }, // 11000110
+        { 0, 1, 2, 5, 6, 7, 3, 4 }, // 11000111
+        { 3, 4, 5, 0, 6, 7, 1, 2 }, // 11001000
+        { 0, 4, 5, 1, 6, 7, 2, 3 }, // 11001001
+        { 4, 0, 5, 1, 6, 7, 2, 3 }, // 11001010
+        { 0, 1, 5, 2, 6, 7, 3, 4 }, // 11001011
+        { 4, 5, 0, 1, 6, 7, 2, 3 }, // 11001100
+        { 0, 5, 1, 2, 6, 7, 3, 4 }, // 11001101
+        { 5, 0, 1, 2, 6, 7, 3, 4 }, // 11001110
+        { 0, 1, 2, 3, 6, 7, 4, 5 }, // 11001111
+        { 3, 4, 5, 6, 0, 7, 1, 2 }, // 11010000
+        { 0, 4, 5, 6, 1, 7, 2, 3 }, // 11010001
+        { 4, 0, 5, 6, 1, 7, 2, 3 }, // 11010010
+        { 0, 1, 5, 6, 2, 7, 3, 4 }, // 11010011
+        { 4, 5, 0, 6, 1, 7, 2, 3 }, // 11010100
+        { 0, 5, 1, 6, 2, 7, 3, 4 }, // 11010101
+        { 5, 0, 1, 6, 2, 7, 3, 4 }, // 11010110
+        { 0, 1, 2, 6, 3, 7, 4, 5 }, // 11010111
+        { 4, 5, 6, 0, 1, 7, 2, 3 }, // 11011000
+        { 0, 5, 6, 1, 2, 7, 3, 4 }, // 11011001
+        { 5, 0, 6, 1, 2, 7, 3, 4 }, // 11011010
+        { 0, 1, 6, 2, 3, 7, 4, 5 }, // 11011011
+        { 5, 6, 0, 1, 2, 7, 3, 4 }, // 11011100
+        { 0, 6, 1, 2, 3, 7, 4, 5 }, // 11011101
+        { 6, 0, 1, 2, 3, 7, 4, 5 }, // 11011110
+        { 0, 1, 2, 3, 4, 7, 5, 6 }, // 11011111
+        { 3, 4, 5, 6, 7, 0, 1, 2 }, // 11100000
+        { 0, 4, 5, 6, 7, 1, 2, 3 }, // 11100001
+        { 4, 0, 5, 6, 7, 1, 2, 3 }, // 11100010
+        { 0, 1, 5, 6, 7, 2, 3, 4 }, // 11100011
+        { 4, 5, 0, 6, 7, 1, 2, 3 }, // 11100100
+        { 0, 5, 1, 6, 7, 2, 3, 4 }, // 11100101
+        { 5, 0, 1, 6, 7, 2, 3, 4 }, // 11100110
+        { 0, 1, 2, 6, 7, 3, 4, 5 }, // 11100111
+        { 4, 5, 6, 0, 7, 1, 2, 3 }, // 11101000
+        { 0, 5, 6, 1, 7, 2, 3, 4 }, // 11101001
+        { 5, 0, 6, 1, 7, 2, 3, 4 }, // 11101010
+        { 0, 1, 6, 2, 7, 3, 4, 5 }, // 11101011
+        { 5, 6, 0, 1, 7, 2, 3, 4 }, // 11101100
+        { 0, 6, 1, 2, 7, 3, 4, 5 }, // 11101101
+        { 6, 0, 1, 2, 7, 3, 4, 5 }, // 11101110
+        { 0, 1, 2, 3, 7, 4, 5, 6 }, // 11101111
+        { 4, 5, 6, 7, 0, 1, 2, 3 }, // 11110000
+        { 0, 5, 6, 7, 1, 2, 3, 4 }, // 11110001
+        { 5, 0, 6, 7, 1, 2, 3, 4 }, // 11110010
+        { 0, 1, 6, 7, 2, 3, 4, 5 }, // 11110011
+        { 5, 6, 0, 7, 1, 2, 3, 4 }, // 11110100
+        { 0, 6, 1, 7, 2, 3, 4, 5 }, // 11110101
+        { 6, 0, 1, 7, 2, 3, 4, 5 }, // 11110110
+        { 0, 1, 2, 7, 3, 4, 5, 6 }, // 11110111
+        { 5, 6, 7, 0, 1, 2, 3, 4 }, // 11111000
+        { 0, 6, 7, 1, 2, 3, 4, 5 }, // 11111001
+        { 6, 0, 7, 1, 2, 3, 4, 5 }, // 11111010
+        { 0, 1, 7, 2, 3, 4, 5, 6 }, // 11111011
+        { 6, 7, 0, 1, 2, 3, 4, 5 }, // 11111100
+        { 0, 7, 1, 2, 3, 4, 5, 6 }, // 11111101
+        { 7, 0, 1, 2, 3, 4, 5, 6 }, // 11111110
+        { 0, 1, 2, 3, 4, 5, 6, 7 }  // 11111111
+    };
+
+    assert( uPhase > 0 && uPhase < (unsigned)(1 << nVars) );
+
+    // the same function
+    if ( Cases[uPhase] == 0 )
+    {
+        int i;
+        for ( i = 0; i < nWords; i++ )
+            puTruthR[i] = puTruth[i];
+        return;
+    }
+
+    // an elementary variable
+    if ( Cases[uPhase] > 0 )
+    {
+        int i;
+        for ( i = 0; i < nWords; i++ )
+            puTruthR[i] = uTruths[(int)Cases[uPhase]][i];
+        return;
+    }
+
+    // truth table takes one word
+    if ( nWords == 1 )
+    {
+        int i, k, nMints, iRes;
+        char * pPerm = Perms[uPhase];
+        puTruthR[0] = 0;
+        nMints = (1 << nVars);
+        for ( i = 0; i < nMints; i++ )
+            if ( puTruth[0] & (1 << i) )
+            {
+                for ( iRes = 0, k = 0; k < nVars; k++ )
+                    if ( i & (1 << pPerm[k]) )
+                        iRes |= (1 << k);
+                puTruthR[0] |= (1 << iRes);
+            }
+        return;
+    }
+    else if ( nWords == 2 )
+    {
+        int i, k, iRes;
+        char * pPerm = Perms[uPhase];
+        puTruthR[0] = puTruthR[1] = 0;
+        for ( i = 0; i < 32; i++ )
+        {
+            if ( puTruth[0] & (1 << i) )
+            {
+                for ( iRes = 0, k = 0; k < 6; k++ )
+                    if ( i & (1 << pPerm[k]) )
+                        iRes |= (1 << k);
+                if ( iRes < 32 )
+                    puTruthR[0] |= (1 << iRes);
+                else
+                    puTruthR[1] |= (1 << (iRes-32));
+            }
+        }
+        for ( ; i < 64; i++ )
+        {
+            if ( puTruth[1] & (1 << (i-32)) )
+            {
+                for ( iRes = 0, k = 0; k < 6; k++ )
+                    if ( i & (1 << pPerm[k]) )
+                        iRes |= (1 << k);
+                if ( iRes < 32 )
+                    puTruthR[0] |= (1 << iRes);
+                else
+                    puTruthR[1] |= (1 << (iRes-32));
+            }
+        }
+    }
+    // truth table takes more than one word
+    else
+    {
+        int i, k, nMints, iRes;
+        char * pPerm = Perms[uPhase];
+        for ( i = 0; i < nWords; i++ )
+            puTruthR[i] = 0;
+        nMints = (1 << nVars);
+        for ( i = 0; i < nMints; i++ )
+            if ( puTruth[i>>5] & (1 << (i&31)) )
+            {
+                for ( iRes = 0, k = 0; k < 5; k++ )
+                    if ( i & (1 << pPerm[k]) )
+                        iRes |= (1 << k);
+                puTruthR[iRes>>5] |= (1 << (iRes&31));
+            }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocated lookup table for truth table permutation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned short ** Extra_TruthPerm43()
+{
+    unsigned short ** pTable;
+    unsigned uTruth;
+    int i, k;
+    pTable = (unsigned short **)Extra_ArrayAlloc( 256, 16, 2 );
+    for ( i = 0; i < 256; i++ )
+    {
+        uTruth = (i << 8) | i;
+        for ( k = 0; k < 16; k++ )
+            pTable[i][k] = Extra_TruthPerm4One( uTruth, k );
+    }
+    return pTable;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocated lookup table for truth table permutation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned ** Extra_TruthPerm53()
+{
+    unsigned ** pTable;
+    unsigned uTruth;
+    int i, k;
+    pTable = (unsigned **)Extra_ArrayAlloc( 256, 32, 4 );
+    for ( i = 0; i < 256; i++ )
+    {
+        uTruth = (i << 24) | (i << 16) | (i << 8) | i;
+        for ( k = 0; k < 32; k++ )
+            pTable[i][k] = Extra_TruthPerm5One( uTruth, k );
+    }
+    return pTable;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocated lookup table for truth table permutation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned ** Extra_TruthPerm54()
+{
+    unsigned ** pTable;
+    unsigned uTruth;
+    int i;
+    pTable = (unsigned **)Extra_ArrayAlloc( 256*256, 4, 4 );
+    for ( i = 0; i < 256*256; i++ )
+    {
+        uTruth = (i << 16) | i;
+        pTable[i][0] = Extra_TruthPerm5One( uTruth, 31-8 );
+        pTable[i][1] = Extra_TruthPerm5One( uTruth, 31-4 );
+        pTable[i][2] = Extra_TruthPerm5One( uTruth, 31-2 );
+        pTable[i][3] = Extra_TruthPerm5One( uTruth, 31-1 );
+    }
+    return pTable;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocated lookup table for truth table permutation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned ** Extra_TruthPerm63()
+{
+    unsigned ** pTable;
+    unsigned uTruth[2];
+    int i, k;
+    pTable = (unsigned **)Extra_ArrayAlloc( 256, 64, 8 );
+    for ( i = 0; i < 256; i++ )
+    {
+        uTruth[0] = (i << 24) | (i << 16) | (i << 8) | i;
+        uTruth[1] = uTruth[0];
+        for ( k = 0; k < 64; k++ )
+            Extra_TruthPerm6One( uTruth, k, &pTable[i][k] );
+    }
+    return pTable;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the pointer to the elementary truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned ** Extra_Truths8()
+{
+    static unsigned uTruths[8][8] = {
+        { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA },
+        { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC },
+        { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 },
+        { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 },
+        { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, 
+        { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, 
+        { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, 
+        { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } 
+    };
+    static unsigned * puResult[8] = {
+        uTruths[0], uTruths[1], uTruths[2], uTruths[3], uTruths[4], uTruths[5], uTruths[6], uTruths[7] 
+    };
+    return (unsigned **)puResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Bubble-sorts components by scores in increasing order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_BubbleSort( int Order[], int Costs[], int nSize, int fIncreasing )
+{
+    int i, Temp, fChanges;
+    assert( nSize < 1000 );
+    for ( i = 0; i < nSize; i++ )
+        Order[i] = i;
+    if ( fIncreasing )
+    {
+        do {
+            fChanges = 0;
+            for ( i = 0; i < nSize - 1; i++ )
+            {
+                if ( Costs[Order[i]] <= Costs[Order[i+1]] )
+                    continue;
+                Temp = Order[i];
+                Order[i] = Order[i+1];
+                Order[i+1] = Temp;
+                fChanges = 1;
+            }
+        } while ( fChanges );
+    }
+    else
+    {
+        do {
+            fChanges = 0;
+            for ( i = 0; i < nSize - 1; i++ )
+            {
+                if ( Costs[Order[i]] >= Costs[Order[i+1]] )
+                    continue;
+                Temp = Order[i];
+                Order[i] = Order[i+1];
+                Order[i+1] = Temp;
+                fChanges = 1;
+            }
+        } while ( fChanges );
+    }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static Functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the permutation table for 8 variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_TruthExpandGeneratePermTable()
+{
+    int i, k, nOnes, Last1, First0;
+    int iOne, iZero;
+
+    printf( "\nstatic char Cases[256] = {\n" );
+    for ( i = 0; i < 256; i++ )
+    {
+        nOnes = 0;
+        Last1 = First0 = -1;
+        for ( k = 0; k < 8; k++ )
+        {
+            if ( i & (1 << k) )
+            {
+                nOnes++;
+                Last1 = k;
+            }
+            else if ( First0 == -1 )
+                First0 = k;
+        }
+        if ( Last1 + 1 == First0 || i == 255 )
+            printf( "     %d%s", 0, (i==255? " ":",") );
+        else if ( nOnes == 1 )
+            printf( "     %d,", Last1 );
+        else
+            printf( "    -%d,", 1 );
+        printf( " // " );
+        Extra_PrintBinary( stdout, (unsigned*)&i, 8 );
+        printf( "\n" );
+    }
+    printf( "};\n" );
+
+    printf( "\nstatic char Perms[256][8] = {\n" );
+    for ( i = 0; i < 256; i++ )
+    {
+        printf( "    {" );
+        nOnes = 0;
+        for ( k = 0; k < 8; k++ )
+            if ( i & (1 << k) )
+                nOnes++;
+        iOne = 0;
+        iZero = nOnes;
+        for ( k = 0; k < 8; k++ )
+            if ( i & (1 << k) )
+                printf( "%s %d", (k==0? "":","), iOne++ );
+            else
+                printf( "%s %d", (k==0? "":","), iZero++ );
+        assert( iOne + iZero == 8 );
+        printf( " }%s // ", (i==255? " ":",") );
+        Extra_PrintBinary( stdout, (unsigned*)&i, 8 );
+        printf( "\n" );
+    }
+    printf( "};\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes complementation schedule for 2^n Grey codes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Extra_GreyCodeSchedule( int n )
+{
+    int * pRes = ABC_ALLOC( int, (1<<n) );
+    int i, k, b = 0;
+//    pRes[b++] = -1;
+    for ( k = 0; k < n; k++ )
+        for ( pRes[b++] = k, i = 1; i < (1<<k); i++ )
+            pRes[b++] = pRes[i-1]; // pRes[i];
+    pRes[b++] = n-1;
+    assert( b == (1<<n) );
+
+    if ( 0 )
+    {
+        unsigned uSign = 0;
+        for ( b = 0; b < (1<<n); b++ )
+        {
+            uSign ^= (1 << pRes[b]);
+            printf( "%3d %3d  ", b, pRes[b] );
+            Extra_PrintBinary( stdout, &uSign, n );
+            printf( "\n" );
+        }
+    }
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes permutation schedule for n! permutations.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Extra_PermSchedule( int n )
+{
+    int nFact   = Extra_Factorial(n);
+    int nGroups = nFact / n / 2;
+    int * pRes = ABC_ALLOC( int, nFact );
+    int * pRes0, i, k, b = 0;
+    assert( n > 1 );
+    if ( n == 2 )
+    {
+        pRes[0] = pRes[1] = 0;
+        return pRes;
+    }
+    pRes0 = Extra_PermSchedule( n-1 );
+    for ( k = 0; k < nGroups; k++ )
+    {
+        for ( i = n-1; i > 0; i-- )
+            pRes[b++] = i-1;
+        pRes[b++] = pRes0[2*k]+1;
+        for ( i = 0; i < n-1; i++ )
+            pRes[b++] = i;
+        pRes[b++] = pRes0[2*k+1];
+    }
+    ABC_FREE( pRes0 );
+    assert( b == nFact );
+
+    if ( 0 )
+    {
+        int Perm[16];
+        for ( i = 0; i < n; i++ )
+            Perm[i] = i;
+        for ( b = 0; b < nFact; b++ )
+        {
+            ABC_SWAP( int, Perm[pRes[b]], Perm[pRes[b]+1] );
+            printf( "%3d %3d    ", b, pRes[b] );
+            for ( i = 0; i < n; i++ )
+                printf( "%d", Perm[i] );
+            printf( "\n" );
+        }
+    }
+    return pRes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds minimum form of a 6-input function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Extra_Truth6SwapAdjacent( word t, int v )
+{
+    // variable swapping code
+    static word PMasks[5][3] = {
+        { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) },
+        { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) },
+        { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) },
+        { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) },
+        { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) }
+    };
+    assert( v < 5 );
+    return (t & PMasks[v][0]) | ((t & PMasks[v][1]) << (1 << v)) | ((t & PMasks[v][2]) >> (1 << v));
+}
+static inline word Extra_Truth6ChangePhase( word t, int v )
+{
+    // elementary truth tables
+    static word Truth6[6] = {
+        ABC_CONST(0xAAAAAAAAAAAAAAAA),
+        ABC_CONST(0xCCCCCCCCCCCCCCCC),
+        ABC_CONST(0xF0F0F0F0F0F0F0F0),
+        ABC_CONST(0xFF00FF00FF00FF00),
+        ABC_CONST(0xFFFF0000FFFF0000),
+        ABC_CONST(0xFFFFFFFF00000000)
+    };
+    assert( v < 6 );
+    return ((t & ~Truth6[v]) << (1 << v)) | ((t & Truth6[v]) >> (1 << v));
+}
+word Extra_Truth6MinimumExact( word t, int * pComp, int * pPerm )
+{
+    word tMin = ~(word)0;
+    word tCur, tTemp1, tTemp2;
+    int i, p, c;
+    for ( i = 0; i < 2; i++ )
+    {
+        tCur = i ? ~t : t;
+        tTemp1 = tCur;
+        for ( p = 0; p < 720; p++ )
+        {
+//            printf( "Trying perm %d:\n", p );
+//            Kit_DsdPrintFromTruth( &tCur, 6 ), printf( "\n" );;
+            tTemp2 = tCur;
+            for ( c = 0; c < 64; c++ )
+            {
+                tMin = Abc_MinWord( tMin, tCur );
+                tCur = Extra_Truth6ChangePhase( tCur, pComp[c] );
+            }
+            assert( tTemp2 == tCur );
+            tCur = Extra_Truth6SwapAdjacent( tCur, pPerm[p] );
+        }
+        assert( tTemp1 == tCur );
+    }
+    return tMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform heuristic TT minimization.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Extra_Truth6Ones( word t )
+{
+    t =    (t & ABC_CONST(0x5555555555555555)) + ((t>> 1) & ABC_CONST(0x5555555555555555));
+    t =    (t & ABC_CONST(0x3333333333333333)) + ((t>> 2) & ABC_CONST(0x3333333333333333));
+    t =    (t & ABC_CONST(0x0F0F0F0F0F0F0F0F)) + ((t>> 4) & ABC_CONST(0x0F0F0F0F0F0F0F0F));
+    t =    (t & ABC_CONST(0x00FF00FF00FF00FF)) + ((t>> 8) & ABC_CONST(0x00FF00FF00FF00FF));
+    t =    (t & ABC_CONST(0x0000FFFF0000FFFF)) + ((t>>16) & ABC_CONST(0x0000FFFF0000FFFF));
+    return (t & ABC_CONST(0x00000000FFFFFFFF)) +  (t>>32);
+}
+static inline word Extra_Truth6MinimumRoundOne( word t, int v )
+{
+    word tCur, tMin = t; // ab 
+    assert( v >= 0 && v < 5 );
+
+    tCur = Extra_Truth6ChangePhase( t, v );    // !ab
+    tMin = Abc_MinWord( tMin, tCur );
+    tCur = Extra_Truth6ChangePhase( t, v+1 );  // a!b
+    tMin = Abc_MinWord( tMin, tCur );
+    tCur = Extra_Truth6ChangePhase( tCur, v ); // !a!b
+    tMin = Abc_MinWord( tMin, tCur );
+
+    t    = Extra_Truth6SwapAdjacent( t, v );   // ba
+    tMin = Abc_MinWord( tMin, t );
+
+    tCur = Extra_Truth6ChangePhase( t, v );    // !ba
+    tMin = Abc_MinWord( tMin, tCur );
+    tCur = Extra_Truth6ChangePhase( t, v+1 );  // b!a
+    tMin = Abc_MinWord( tMin, tCur );
+    tCur = Extra_Truth6ChangePhase( tCur, v ); // !b!a
+    tMin = Abc_MinWord( tMin, tCur );
+
+    return tMin;
+}
+static inline word Extra_Truth6MinimumRoundMany( word t )
+{
+    int i, k, Limit = 10;
+    word tCur, tMin = t;
+    for ( i = 0; i < Limit; i++ )
+    {
+        word tMin0 = tMin;
+        for ( k = 4; k >= 0; k-- )
+        {
+            tCur = Extra_Truth6MinimumRoundOne( tMin, k );
+            tMin = Abc_MinWord( tMin, tCur );
+        }
+        if ( tMin0 == tMin )
+            break;
+    }
+    return tMin;
+}
+word Extra_Truth6MinimumHeuristic( word t )
+{
+    word tMin1, tMin2;
+    int nOnes = Extra_Truth6Ones( t );
+    if ( nOnes < 32 )
+        return Extra_Truth6MinimumRoundMany( t );
+    if ( nOnes > 32 )
+        return Extra_Truth6MinimumRoundMany( ~t );
+    tMin1 = Extra_Truth6MinimumRoundMany(  t );
+    tMin2 = Extra_Truth6MinimumRoundMany( ~t );
+    return Abc_MinWord( tMin1, tMin2 );
+}
+void Extra_Truth6MinimumHeuristicTest()
+{
+    word t = ABC_CONST(0x5555555555555555) & ~(ABC_CONST(0x3333333333333333) & ABC_CONST(0x0F0F0F0F0F0F0F0F));
+    Extra_Truth6MinimumRoundMany( t );
+    t = 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reads functions from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word * Extra_NpnRead( char * pFileName, int nFuncs )
+{
+    FILE * pFile;
+    word * pFuncs;
+    char pBuffer[100];
+    int i = 0;
+    pFuncs = ABC_CALLOC( word, nFuncs );
+    pFile = fopen( pFileName, "rb" );
+    while ( fgets( pBuffer, 100, pFile ) )
+        Extra_ReadHex( (unsigned *)(pFuncs + i++), (pBuffer[1] == 'x' ? pBuffer+2 : pBuffer), 16 );
+    fclose( pFile );
+    assert( i == nFuncs );
+    for ( i = 0; i < Abc_MinInt(nFuncs, 10); i++ )
+    {
+        printf( "Line %d : ", i );
+        Extra_PrintHex( stdout, (unsigned *)(pFuncs + i), 6 ), printf( "\n" );
+    }
+    return pFuncs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison for words.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int CompareWords( void * p1, void * p2 )
+{
+    word Word1 = *(word *)p1;
+    word Word2 = *(word *)p2;
+    if ( Word1 < Word2 )
+        return -1;
+    if ( Word1 > Word2 )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the permutation table for 8 variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_NpnTest1()
+{
+    int * pComp;
+    pComp = Extra_PermSchedule( 5 );
+//    pComp = Extra_GreyCodeSchedule( 5 );
+    ABC_FREE( pComp );
+}
+void Extra_NpnTest2()
+{
+    int * pComp, * pPerm;
+    word tMin, t = ABC_CONST(0xa2222aaa08888000);
+    pComp = Extra_GreyCodeSchedule( 6 );
+    pPerm = Extra_PermSchedule( 6 );
+    tMin  = Extra_Truth6MinimumExact( t, pComp, pPerm );
+    ABC_FREE( pPerm );
+    ABC_FREE( pComp );
+
+    Extra_PrintHex( stdout, (unsigned *)&t,    6 ), printf( "\n" );
+    Extra_PrintHex( stdout, (unsigned *)&tMin, 6 ), printf( "\n" );
+}
+void Extra_NpnTest()
+{
+//    int nFuncs = 5687661; 
+//    int nFuncs = 400777;
+    int nFuncs = 10;
+    abctime clk = Abc_Clock();
+    word * pFuncs;
+    int * pComp, * pPerm;
+    int i;//, k, nUnique = 0;
+/*
+    // read functions
+    pFuncs = Extra_NpnRead( "C:\\_projects\\abc\\_TEST\\allan\\lib6var5M.txt", nFuncs );
+//    pFuncs = Extra_NpnRead( "C:\\_projects\\abc\\_TEST\\allan\\lib6var5M_out_Total_minimal.txt", nFuncs );
+    qsort( (void *)pFuncs, nFuncs, sizeof(word), (int(*)(const void *,const void *))CompareWords );
+
+    // count unique
+    k = 1;
+    for ( i = 1; i < nFuncs; i++ )
+        if ( pFuncs[i] != pFuncs[i-1] )
+            pFuncs[k++] = pFuncs[i];
+    nFuncs = k;
+    printf( "Total number of unique functions = %d\n", nFuncs );
+*/
+//    pFuncs = Extra_NpnRead( "C:\\_projects\\abc\\_TEST\\allan\\lib6var5M_out_Total_minimal.txt", nFuncs );
+    pFuncs = Extra_NpnRead( "C:\\_projects\\abc\\_TEST\\allan\\test.txt", nFuncs );
+    pComp = Extra_GreyCodeSchedule( 6 );
+    pPerm = Extra_PermSchedule( 6 );
+    // compute minimum forms
+    for ( i = 0; i < nFuncs; i++ )
+    {
+        pFuncs[i] = Extra_Truth6MinimumExact( pFuncs[i], pComp, pPerm );
+        if ( i % 10000 == 0 )
+            printf( "%d\n", i );
+    }
+    printf( "Finished deriving minimum form\n" );
+/*
+    // sort them by value
+    qsort( (void *)pFuncs, nFuncs, sizeof(word), (int(*)(const void *,const void *))CompareWords );
+    // count unique
+    nUnique = nFuncs;
+    for ( i = 1; i < nFuncs; i++ )
+        if ( pFuncs[i] == pFuncs[i-1] )
+            nUnique--;
+    printf( "Total number of unique ones = %d\n", nUnique );
+*/
+    for ( i = 0; i < Abc_MinInt(nFuncs, 10); i++ )
+    {
+        printf( "Line %d : ", i );
+        Extra_PrintHex( stdout, (unsigned *)(pFuncs + i), 6 ), printf( "\n" );
+    }
+    ABC_FREE( pPerm );
+    ABC_FREE( pComp );
+    ABC_FREE( pFuncs );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraUtilPerm.c b/abc-build/src/misc/extra/extraUtilPerm.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraUtilPerm.c
@@ -0,0 +1,933 @@
+/**CFile****************************************************************
+
+  FileName    [extraUtilPerm.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [extra]
+
+  Synopsis    [Permutation computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: extraUtilPerm.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "misc/vec/vec.h"
+#include "aig/gia/gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef enum  
+{
+    ABC_ZDD_OPER_NONE,
+    ABC_ZDD_OPER_DIFF,
+    ABC_ZDD_OPER_UNION,
+    ABC_ZDD_OPER_MIN_UNION,
+    ABC_ZDD_OPER_INTER,
+    ABC_ZDD_OPER_PERM,
+    ABC_ZDD_OPER_PERM_PROD,
+    ABC_ZDD_OPER_COF0,
+    ABC_ZDD_OPER_COF1,
+    ABC_ZDD_OPER_THRESH,
+    ABC_ZDD_OPER_DOT_PROD,
+    ABC_ZDD_OPER_DOT_PROD_6,
+    ABC_ZDD_OPER_INSERT,
+    ABC_ZDD_OPER_PATHS,
+    ABC_ZDD_OPER_NODES,
+    ABC_ZDD_OPER_ITE
+} Abc_ZddOper;
+
+typedef struct Abc_ZddObj_ Abc_ZddObj;
+struct Abc_ZddObj_ 
+{
+    unsigned     Var  : 31;
+    unsigned     Mark :  1;
+    unsigned     True;
+    unsigned     False;
+};  
+
+typedef struct Abc_ZddEnt_ Abc_ZddEnt;
+struct Abc_ZddEnt_ 
+{
+    int          Arg0;
+    int          Arg1;
+    int          Arg2;
+    int          Res;
+};
+
+typedef struct Abc_ZddMan_ Abc_ZddMan;
+struct Abc_ZddMan_ 
+{
+    int          nVars;
+    int          nObjs;
+    int          nObjsAlloc;
+    int          nPermSize;
+    unsigned     nUniqueMask;
+    unsigned     nCacheMask;
+    int *        pUnique;
+    int *        pNexts;
+    Abc_ZddEnt * pCache;
+    Abc_ZddObj * pObjs;
+    int          nCacheLookups;
+    int          nCacheMisses;
+    word         nMemory;
+    int *        pV2TI;
+    int *        pV2TJ;
+    int *        pT2V;
+};
+
+static inline int          Abc_ZddIthVar( int i )                                  { return i + 2;                                            }
+static inline unsigned     Abc_ZddHash( int Arg0, int Arg1, int Arg2 )             { return 12582917 * Arg0 + 4256249 * Arg1 + 741457 * Arg2; }
+
+static inline Abc_ZddObj * Abc_ZddNode( Abc_ZddMan * p, int i )                    { return p->pObjs + i;                                     }
+static inline int          Abc_ZddObjId( Abc_ZddMan * p, Abc_ZddObj * pObj )       { return pObj - p->pObjs;                                  }
+static inline int          Abc_ZddObjVar( Abc_ZddMan * p, int i )                  { return Abc_ZddNode(p, i)->Var;                           }
+
+static inline void         Abc_ZddSetVarIJ( Abc_ZddMan * p, int i, int j, int v )  { assert( i < j ); p->pT2V[i * p->nPermSize + j] = v;      }
+static inline int          Abc_ZddVarIJ( Abc_ZddMan * p, int i, int j )            { assert( i < j ); return p->pT2V[i * p->nPermSize + j];   }
+static inline int          Abc_ZddVarsClash( Abc_ZddMan * p, int v0, int v1 )      { return p->pV2TI[v0] == p->pV2TI[v1] || p->pV2TJ[v0] == p->pV2TJ[v1] || p->pV2TI[v0] == p->pV2TJ[v1] || p->pV2TJ[v0] == p->pV2TI[v1];  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_ZddCacheLookup( Abc_ZddMan * p, int Arg0, int Arg1, int Arg2 )
+{
+    Abc_ZddEnt * pEnt = p->pCache + (Abc_ZddHash(Arg0, Arg1, Arg2) & p->nCacheMask);
+    p->nCacheLookups++;
+    return (pEnt->Arg0 == Arg0 && pEnt->Arg1 == Arg1 && pEnt->Arg2 == Arg2) ? pEnt->Res : -1;
+}
+static inline int Abc_ZddCacheInsert( Abc_ZddMan * p, int Arg0, int Arg1, int Arg2, int Res )
+{
+    Abc_ZddEnt * pEnt = p->pCache + (Abc_ZddHash(Arg0, Arg1, Arg2) & p->nCacheMask);
+    pEnt->Arg0 = Arg0;  pEnt->Arg1 = Arg1;  pEnt->Arg2 = Arg2;  pEnt->Res = Res;
+    p->nCacheMisses++;
+    assert( Res >= 0 );
+    return Res;
+}
+static inline int Abc_ZddUniqueLookup( Abc_ZddMan * p, int Var, int True, int False )
+{
+    int *q = p->pUnique + (Abc_ZddHash(Var, True, False) & p->nUniqueMask);
+    for ( ; *q; q = p->pNexts + *q )
+        if ( p->pObjs[*q].Var == (unsigned)Var && p->pObjs[*q].True == (unsigned)True && p->pObjs[*q].False == (unsigned)False )
+            return *q;
+    return 0;
+}
+static inline int Abc_ZddUniqueCreate( Abc_ZddMan * p, int Var, int True, int False )
+{
+    assert( Var >= 0 && Var < p->nVars );
+    assert( Var < Abc_ZddObjVar(p, True) );
+    assert( Var < Abc_ZddObjVar(p, False) );
+    if ( True == 0 )
+        return False;
+    {
+        int *q = p->pUnique + (Abc_ZddHash(Var, True, False) & p->nUniqueMask);
+        for ( ; *q; q = p->pNexts + *q )
+            if ( p->pObjs[*q].Var == (unsigned)Var && p->pObjs[*q].True == (unsigned)True && p->pObjs[*q].False == (unsigned)False )
+                return *q;
+        if ( p->nObjs == p->nObjsAlloc )
+            printf( "Aborting because the number of nodes exceeded %d.\n", p->nObjsAlloc ), fflush(stdout);
+        assert( p->nObjs < p->nObjsAlloc );     
+        *q = p->nObjs++;
+        p->pObjs[*q].Var = Var;
+        p->pObjs[*q].True = True;
+        p->pObjs[*q].False = False;
+//        printf( "Added node %3d: Var = %3d.  True = %3d.  False = %3d\n", *q, Var, True, False );
+        return *q;
+    }
+}
+int Abc_ZddBuildSet( Abc_ZddMan * p, int * pSet, int Size )
+{
+    int i, Res = 1;
+    Vec_IntSelectSort( pSet, Size );
+    for ( i = Size - 1; i >= 0; i-- )
+        Res = Abc_ZddUniqueCreate( p, pSet[i], Res, 0 );
+    return Res;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_ZddMan * Abc_ZddManAlloc( int nVars, int nObjs )
+{
+    Abc_ZddMan * p; int i;
+    p = ABC_CALLOC( Abc_ZddMan, 1 );
+    p->nVars       = nVars;
+    p->nObjsAlloc  = nObjs;
+    p->nUniqueMask = (1 << Abc_Base2Log(nObjs)) - 1;
+    p->nCacheMask  = (1 << Abc_Base2Log(nObjs)) - 1;
+    p->pUnique     = ABC_CALLOC( int, p->nUniqueMask + 1 );
+    p->pNexts      = ABC_CALLOC( int, p->nObjsAlloc );
+    p->pCache      = ABC_CALLOC( Abc_ZddEnt, p->nCacheMask + 1 );
+    p->pObjs       = ABC_CALLOC( Abc_ZddObj, p->nObjsAlloc );
+    p->nObjs       = 2;
+    memset( p->pObjs, 0xff, sizeof(Abc_ZddObj) * 2 );
+    p->pObjs[0].Var = nVars;
+    p->pObjs[1].Var = nVars;
+    for ( i = 0; i < nVars; i++ )
+        Abc_ZddUniqueCreate( p, i, 1, 0 );
+    assert( p->nObjs == nVars + 2 );
+    p->nMemory = sizeof(Abc_ZddMan)/4 + 
+        p->nUniqueMask + 1 + p->nObjsAlloc + 
+        (p->nCacheMask + 1) * sizeof(Abc_ZddEnt)/4 + 
+        p->nObjsAlloc * sizeof(Abc_ZddObj)/4;
+    return p;
+}
+void Abc_ZddManCreatePerms( Abc_ZddMan * p, int nPermSize )
+{
+    int i, j, v = 0;
+    assert( 2 * p->nVars == nPermSize * (nPermSize - 1) );
+    assert( p->nPermSize == 0 );
+    p->nPermSize = nPermSize;
+    p->pV2TI = ABC_FALLOC( int, p->nVars );
+    p->pV2TJ = ABC_FALLOC( int, p->nVars );
+    p->pT2V  = ABC_FALLOC( int, p->nPermSize * p->nPermSize );
+    for ( i = 0; i < nPermSize; i++ )
+        for ( j = i + 1; j < nPermSize; j++ )
+        {
+            p->pV2TI[v] = i;
+            p->pV2TJ[v] = j;
+            Abc_ZddSetVarIJ( p, i, j, v++ );
+        }
+    assert( v == p->nVars );
+}
+void Abc_ZddManFree( Abc_ZddMan * p )
+{
+    printf( "ZDD stats: Var = %d  Obj = %d  Alloc = %d  Hit = %d  Miss = %d  ", 
+        p->nVars, p->nObjs, p->nObjsAlloc, p->nCacheLookups-p->nCacheMisses, p->nCacheMisses );
+    printf( "Mem = %.2f MB\n", 4.0*(int)(p->nMemory/(1<<20)) );
+    ABC_FREE( p->pT2V );
+    ABC_FREE( p->pV2TI );
+    ABC_FREE( p->pV2TJ );
+    ABC_FREE( p->pUnique );
+    ABC_FREE( p->pNexts );
+    ABC_FREE( p->pCache );
+    ABC_FREE( p->pObjs );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ZddDiff( Abc_ZddMan * p, int a, int b )
+{
+    Abc_ZddObj * A, * B; 
+    int r0, r1, r;
+    if ( a == 0 ) return 0;
+    if ( b == 0 ) return a;
+    if ( a == b ) return 0;
+    if ( (r = Abc_ZddCacheLookup(p, a, b, ABC_ZDD_OPER_DIFF)) >= 0 )
+        return r;
+    A = Abc_ZddNode( p, a );
+    B = Abc_ZddNode( p, b );
+    if ( A->Var < B->Var )
+        r0 = Abc_ZddDiff( p, A->False, b ), 
+        r = Abc_ZddUniqueCreate( p, A->Var, A->True, r0 );
+    else if ( A->Var > B->Var )
+        r = Abc_ZddDiff( p, a, B->False );
+    else
+        r0 = Abc_ZddDiff( p, A->False, B->False ), 
+        r1 = Abc_ZddDiff( p, A->True, B->True ),
+        r = Abc_ZddUniqueCreate( p, A->Var, A->True, r0 );
+    return Abc_ZddCacheInsert( p, a, b, ABC_ZDD_OPER_DIFF, r );
+}
+int Abc_ZddUnion( Abc_ZddMan * p, int a, int b )
+{
+    Abc_ZddObj * A, * B; 
+    int r0, r1, r;
+    if ( a == 0 ) return b;
+    if ( b == 0 ) return a;
+    if ( a == b ) return a;
+    if ( a > b )  return Abc_ZddUnion( p, b, a );
+    if ( (r = Abc_ZddCacheLookup(p, a, b, ABC_ZDD_OPER_UNION)) >= 0 )
+        return r;
+    A = Abc_ZddNode( p, a );
+    B = Abc_ZddNode( p, b );
+    if ( A->Var < B->Var )
+        r0 = Abc_ZddUnion( p, A->False, b ), 
+        r1 = A->True;
+    else if ( A->Var > B->Var )
+        r0 = Abc_ZddUnion( p, a, B->False ), 
+        r1 = B->True;
+    else
+        r0 = Abc_ZddUnion( p, A->False, B->False ), 
+        r1 = Abc_ZddUnion( p, A->True, B->True );
+    r = Abc_ZddUniqueCreate( p, Abc_MinInt(A->Var, B->Var), r1, r0 );
+    return Abc_ZddCacheInsert( p, a, b, ABC_ZDD_OPER_UNION, r );
+}
+int Abc_ZddMinUnion( Abc_ZddMan * p, int a, int b )
+{
+    Abc_ZddObj * A, * B; 
+    int r0, r1, r;
+    if ( a == 0 ) return b;
+    if ( b == 0 ) return a;
+    if ( a == b ) return a;
+    if ( a > b )  return Abc_ZddMinUnion( p, b, a );
+    if ( (r = Abc_ZddCacheLookup(p, a, b, ABC_ZDD_OPER_MIN_UNION)) >= 0 )
+        return r;
+    A = Abc_ZddNode( p, a );
+    B = Abc_ZddNode( p, b );
+    if ( A->Var < B->Var )
+        r0 = Abc_ZddMinUnion( p, A->False, b ), 
+        r1 = A->True;
+    else if ( A->Var > B->Var )
+        r0 = Abc_ZddMinUnion( p, a, B->False ), 
+        r1 = B->True;
+    else
+        r0 = Abc_ZddMinUnion( p, A->False, B->False ), 
+        r1 = Abc_ZddMinUnion( p, A->True, B->True );
+    r1 = Abc_ZddDiff( p, r1, r0 ); // assume args are minimal
+    r = Abc_ZddUniqueCreate( p, Abc_MinInt(A->Var, B->Var), r1, r0 );
+    return Abc_ZddCacheInsert( p, a, b, ABC_ZDD_OPER_MIN_UNION, r );
+}
+int Abc_ZddIntersect( Abc_ZddMan * p, int a, int b )
+{
+    Abc_ZddObj * A, * B; 
+    int r0, r1, r;
+    if ( a == 0 ) return 0;
+    if ( b == 0 ) return 0;
+    if ( a == b ) return a;
+    if ( a > b )  return Abc_ZddIntersect( p, b, a );
+    if ( (r = Abc_ZddCacheLookup(p, a, b, ABC_ZDD_OPER_INTER)) >= 0 )
+        return r;
+    A = Abc_ZddNode( p, a );
+    B = Abc_ZddNode( p, b );
+    if ( A->Var < B->Var )
+        r0 = Abc_ZddIntersect( p, A->False, b ), 
+        r1 = A->True;
+    else if ( A->Var > B->Var )
+        r0 = Abc_ZddIntersect( p, a, B->False ), 
+        r1 = B->True;
+    else
+        r0 = Abc_ZddIntersect( p, A->False, B->False ), 
+        r1 = Abc_ZddIntersect( p, A->True, B->True );
+    r = Abc_ZddUniqueCreate( p, Abc_MinInt(A->Var, B->Var), r1, r0 );
+    return Abc_ZddCacheInsert( p, a, b, ABC_ZDD_OPER_INTER, r );
+}
+int Abc_ZddCof0( Abc_ZddMan * p, int a, int Var )
+{
+    Abc_ZddObj * A; 
+    int r0, r1, r;
+    if ( a < 2 ) return a;
+    A = Abc_ZddNode( p, a );
+    if ( (int)A->Var > Var )
+        return a;
+    if ( (r = Abc_ZddCacheLookup(p, a, Var, ABC_ZDD_OPER_COF0)) >= 0 )
+        return r;
+    if ( (int)A->Var < Var )
+        r0 = Abc_ZddCof0( p, A->False, Var ),
+        r1 = Abc_ZddCof0( p, A->True, Var ),
+        r  = Abc_ZddUniqueCreate( p, A->Var, r1, r0 );
+    else
+        r = Abc_ZddCof0( p, A->False, Var );
+    return Abc_ZddCacheInsert( p, a, Var, ABC_ZDD_OPER_COF0, r );
+}
+int Abc_ZddCof1( Abc_ZddMan * p, int a, int Var )
+{
+    Abc_ZddObj * A; 
+    int r0, r1, r;
+    if ( a < 2 ) return a;
+    A = Abc_ZddNode( p, a );
+    if ( (int)A->Var > Var )
+        return a;
+    if ( (r = Abc_ZddCacheLookup(p, a, Var, ABC_ZDD_OPER_COF1)) >= 0 )
+        return r;
+    if ( (int)A->Var < Var )
+        r0 = Abc_ZddCof1( p, A->False, Var ),
+        r1 = Abc_ZddCof1( p, A->True, Var );
+    else
+        r0 = 0,
+        r1 = Abc_ZddCof1( p, A->True, Var );
+    r = Abc_ZddUniqueCreate( p, A->Var, r1, r0 );
+    return Abc_ZddCacheInsert( p, a, Var, ABC_ZDD_OPER_COF1, r );
+}
+int Abc_ZddCountPaths( Abc_ZddMan * p, int a )
+{
+    Abc_ZddObj * A;  
+    int r;
+    if ( a < 2 ) return a;
+    if ( (r = Abc_ZddCacheLookup(p, a, 0, ABC_ZDD_OPER_PATHS)) >= 0 )
+        return r;
+    A = Abc_ZddNode( p, a );
+    r = Abc_ZddCountPaths( p, A->False ) + Abc_ZddCountPaths( p, A->True );
+    return Abc_ZddCacheInsert( p, a, 0, ABC_ZDD_OPER_PATHS, r );
+}
+/*
+int Abc_ZddCountNodes( Abc_ZddMan * p, int a )
+{
+    Abc_ZddObj * A;  
+    int r;
+    if ( a < 2 ) return 0;
+    if ( (r = Abc_ZddCacheLookup(p, a, 0, ABC_ZDD_OPER_NODES)) >= 0 )
+        return r;
+    A = Abc_ZddNode( p, a );
+    r = 1 + Abc_ZddCountNodes( p, A->False ) + Abc_ZddCountNodes( p, A->True );
+    return Abc_ZddCacheInsert( p, a, 0, ABC_ZDD_OPER_NODES, r );
+}
+*/
+int Abc_ZddCount_rec( Abc_ZddMan * p, int i )
+{
+    Abc_ZddObj * A;
+    if ( i < 2 )
+        return 0;
+    A = Abc_ZddNode( p, i );
+    if ( A->Mark )
+        return 0;
+    A->Mark = 1;
+    return 1 + Abc_ZddCount_rec(p, A->False) + Abc_ZddCount_rec(p, A->True);
+}
+void Abc_ZddUnmark_rec( Abc_ZddMan * p, int i )
+{
+    Abc_ZddObj * A;
+    if ( i < 2 )
+        return;
+    A = Abc_ZddNode( p, i );
+    if ( !A->Mark )
+        return;
+    A->Mark = 0;
+    Abc_ZddUnmark_rec( p, A->False );
+    Abc_ZddUnmark_rec( p, A->True );
+}
+int Abc_ZddCountNodes( Abc_ZddMan * p, int i )
+{
+    int Count = Abc_ZddCount_rec( p, i );
+    Abc_ZddUnmark_rec( p, i );
+    return Count;
+}
+int Abc_ZddCountNodesArray( Abc_ZddMan * p, Vec_Int_t * vNodes )
+{
+    int i, Id, Count = 0;
+    Vec_IntForEachEntry( vNodes, Id, i )
+        Count += Abc_ZddCount_rec( p, Id );
+    Vec_IntForEachEntry( vNodes, Id, i )
+        Abc_ZddUnmark_rec( p, Id );
+    return Count;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ZddThresh( Abc_ZddMan * p, int a, int b )
+{
+    Abc_ZddObj * A; 
+    int r0, r1, r;
+    if ( a < 2 )  return a;
+    if ( b == 0 ) return 0;
+    if ( (r = Abc_ZddCacheLookup(p, a, b, ABC_ZDD_OPER_THRESH)) >= 0 )
+        return r;
+    A  = Abc_ZddNode( p, a );
+    r0 = Abc_ZddThresh( p, A->False, b ),
+    r1 = Abc_ZddThresh( p, A->True, b-1 );
+    r  = Abc_ZddUniqueCreate( p, A->Var, r1, r0 );
+    return Abc_ZddCacheInsert( p, a, b, ABC_ZDD_OPER_THRESH, r );
+}
+int Abc_ZddDotProduct( Abc_ZddMan * p, int a, int b )
+{
+    Abc_ZddObj * A, * B; 
+    int r0, r1, b2, t1, t2, r;
+    if ( a == 0 ) return 0;
+    if ( b == 0 ) return 0;
+    if ( a == 1 ) return b;
+    if ( b == 1 ) return a;
+    if ( a > b )  return Abc_ZddDotProduct( p, b, a );
+    if ( (r = Abc_ZddCacheLookup(p, a, b, ABC_ZDD_OPER_DOT_PROD)) >= 0 )
+        return r;
+    A = Abc_ZddNode( p, a );
+    B = Abc_ZddNode( p, b );
+    if ( A->Var < B->Var )
+        r0 = Abc_ZddDotProduct( p, A->False, b ), 
+        r1 = Abc_ZddDotProduct( p, A->True, b );
+    else if ( A->Var > B->Var )
+        r0 = Abc_ZddDotProduct( p, a, B->False ), 
+        r1 = Abc_ZddDotProduct( p, a, B->True ); 
+    else
+        r0 = Abc_ZddDotProduct( p, A->False, B->False ),
+        b2 = Abc_ZddUnion( p, B->False, B->True ), 
+        t1 = Abc_ZddDotProduct( p, A->True, b2 ), 
+        t2 = Abc_ZddDotProduct( p, A->False, B->True ), 
+        r1 = Abc_ZddUnion( p, t1, t2 );
+    r = Abc_ZddUniqueCreate( p, Abc_MinInt(A->Var, B->Var), r1, r0 );
+    return Abc_ZddCacheInsert( p, a, b, ABC_ZDD_OPER_DOT_PROD, r );
+}
+int Abc_ZddDotMinProduct6( Abc_ZddMan * p, int a, int b )
+{
+    Abc_ZddObj * A, * B; 
+    int r0, r1, b2, t1, t2, r;
+    if ( a == 0 ) return 0;
+    if ( b == 0 ) return 0;
+    if ( a == 1 ) return b;
+    if ( b == 1 ) return a;
+    if ( a > b )  return Abc_ZddDotMinProduct6( p, b, a );
+    if ( (r = Abc_ZddCacheLookup(p, a, b, ABC_ZDD_OPER_DOT_PROD_6)) >= 0 )
+        return r;
+    A = Abc_ZddNode( p, a );
+    B = Abc_ZddNode( p, b );
+    if ( A->Var < B->Var )
+        r0 = Abc_ZddDotMinProduct6( p, A->False, b ), 
+        r1 = Abc_ZddDotMinProduct6( p, A->True, b );
+    else if ( A->Var > B->Var )
+        r0 = Abc_ZddDotMinProduct6( p, a, B->False ), 
+        r1 = Abc_ZddDotMinProduct6( p, a, B->True ); 
+    else
+        r0 = Abc_ZddDotMinProduct6( p, A->False, B->False ),
+        b2 = Abc_ZddMinUnion( p, B->False, B->True ), 
+        t1 = Abc_ZddDotMinProduct6( p, A->True, b2 ), 
+        t2 = Abc_ZddDotMinProduct6( p, A->False, B->True ), 
+        r1 = Abc_ZddMinUnion( p, t1, t2 );
+    r1 = Abc_ZddThresh( p, r1, 5 ),
+    r1 = Abc_ZddDiff( p, r1, r0 ); 
+    r = Abc_ZddUniqueCreate( p, Abc_MinInt(A->Var, B->Var), r1, r0 );
+    return Abc_ZddCacheInsert( p, a, b, ABC_ZDD_OPER_DOT_PROD_6, r );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ZddPerm( Abc_ZddMan * p, int a, int Var )
+{
+    Abc_ZddObj * A; 
+    int r0, r1, r;
+    assert( Var < p->nVars );
+    if ( a == 0 )  return 0;
+    if ( a == 1 )  return Abc_ZddIthVar(Var);
+    if ( (r = Abc_ZddCacheLookup(p, a, Var, ABC_ZDD_OPER_PERM)) >= 0 )
+        return r;
+    A = Abc_ZddNode( p, a );
+    if ( p->pV2TI[A->Var] > p->pV2TI[Var] ) // Ai > Bi
+        r = Abc_ZddUniqueCreate( p, Var, a, 0 );
+    else if ( (int)A->Var == Var ) // Ai == Bi && Aj == Bj
+        r0 = Abc_ZddPerm( p, A->False, Var ), 
+        r  = Abc_ZddUnion( p, r0, A->True );
+    else 
+    {
+        int VarPerm, VarTop;
+        int Ai = p->pV2TI[A->Var];
+        int Aj = p->pV2TJ[A->Var];
+        int Bi = p->pV2TI[Var];
+        int Bj = p->pV2TJ[Var];
+        assert( Ai < Aj && Bi < Bj && Ai <= Bi );
+        if ( Aj == Bi )
+            VarPerm = Var,
+            VarTop  = Abc_ZddVarIJ(p, Ai, Bj);
+        else if ( Aj == Bj )
+            VarPerm = Var,
+            VarTop  = Abc_ZddVarIJ(p, Ai, Bi);
+        else if ( Ai == Bi )
+            VarPerm = Abc_ZddVarIJ(p, Abc_MinInt(Aj, Bj), Abc_MaxInt(Aj, Bj)),
+            VarTop  = A->Var;
+        else // no clash
+            VarPerm = Var, 
+            VarTop  = A->Var;
+        assert( p->pV2TI[VarPerm] > p->pV2TI[VarTop] );
+        r0 = Abc_ZddPerm( p, A->False, Var ); 
+        r1 = Abc_ZddPerm( p, A->True, VarPerm );
+        assert( Abc_ZddObjVar(p, r1) > VarTop );
+        if ( Abc_ZddObjVar(p, r0) > VarTop )
+            r = Abc_ZddUniqueCreate( p, VarTop, r1, r0 );
+        else
+            r1 = Abc_ZddUniqueCreate( p, VarTop, r1, 0 ),
+            r = Abc_ZddUnion( p, r0, r1 );
+    }
+    return Abc_ZddCacheInsert( p, a, Var, ABC_ZDD_OPER_PERM, r );
+}
+int Abc_ZddPermProduct( Abc_ZddMan * p, int a, int b )
+{
+    Abc_ZddObj * B; 
+    int r0, r1, r;
+    if ( a == 0 ) return 0;
+    if ( a == 1 ) return b;
+    if ( b == 0 ) return 0;
+    if ( b == 1 ) return a;
+    if ( (r = Abc_ZddCacheLookup(p, a, b, ABC_ZDD_OPER_PERM_PROD)) >= 0 )
+        return r;
+    B  = Abc_ZddNode( p, b );
+    r0 = Abc_ZddPermProduct( p, a, B->False ); 
+    r1 = Abc_ZddPermProduct( p, a, B->True ); 
+    r1 = Abc_ZddPerm( p, r1, B->Var );
+    r  = Abc_ZddUnion( p, r0, r1 );
+    return Abc_ZddCacheInsert( p, a, b, ABC_ZDD_OPER_PERM_PROD, r );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Printing permutations and transpositions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ZddPermPrint( int * pPerm, int Size )
+{
+    int i;
+    printf( "{" );
+    for ( i = 0; i < Size; i++ )
+        printf( " %2d", pPerm[i] );
+    printf( " }\n" );
+}
+void Abc_ZddCombPrint( int * pComb, int nTrans )
+{
+    int i;
+    if ( nTrans == 0 )
+        printf( "Empty set" );
+    for ( i = 0; i < nTrans; i++ )
+        printf( "(%d %d)", pComb[i] >> 16, pComb[i] & 0xffff );
+    printf( "\n" );
+}
+int Abc_ZddPerm2Comb( int * pPerm, int Size, int * pComb )
+{
+    int i, j, nTrans = 0;
+    for ( i = 0; i < Size; i++ )
+        if ( i != pPerm[i] )
+        {
+            for ( j = i+1; j < Size; j++ )
+                if ( i == pPerm[j] )
+                    break;
+            pComb[nTrans++] = (i << 16) | j;
+            ABC_SWAP( int, pPerm[i], pPerm[j] );
+            assert( i == pPerm[i] );
+        }
+    return nTrans;
+}
+void Abc_ZddComb2Perm( int * pComb, int nTrans, int * pPerm, int Size )
+{
+    int v;
+    for ( v = 0; v < Size; v++ )
+        pPerm[v] = v;
+    for ( v = nTrans-1; v >= 0; v-- )
+        ABC_SWAP( int, pPerm[pComb[v] >> 16], pPerm[pComb[v] & 0xffff] );
+}
+void Abc_ZddPermCombTest()
+{
+    int Size = 10;
+    int pPerm[10] = { 6, 5, 7, 0, 3, 2, 1, 8, 9, 4 };
+    int pComb[10], nTrans;
+    Abc_ZddPermPrint( pPerm, Size );
+    nTrans = Abc_ZddPerm2Comb( pPerm, Size, pComb );
+    Abc_ZddCombPrint( pComb, nTrans );
+    Abc_ZddComb2Perm( pComb, nTrans, pPerm, Size );
+    Abc_ZddPermPrint( pPerm, Size );
+    Size = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Printing ZDDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ZddPrint_rec( Abc_ZddMan * p, int a, int * pPath, int Size )
+{
+    Abc_ZddObj * A;  
+    if ( a == 0 ) return;
+//    if ( a == 1 ) { Abc_ZddPermPrint( pPath, Size ); return; }
+    if ( a == 1 )
+    { 
+        int pPerm[24], pComb[24], i;
+        assert( p->nPermSize <= 24 );
+        for ( i = 0; i < Size; i++ )
+            pComb[i] = (p->pV2TI[pPath[i]] << 16) | p->pV2TJ[pPath[i]];
+        Abc_ZddCombPrint( pComb, Size ); 
+        Abc_ZddComb2Perm( pComb, Size, pPerm, p->nPermSize );
+        Abc_ZddPermPrint( pPerm, p->nPermSize );
+        return; 
+    }
+    A = Abc_ZddNode( p, a );
+    Abc_ZddPrint_rec( p, A->False, pPath, Size );
+    pPath[Size] = A->Var;
+    Abc_ZddPrint_rec( p, A->True, pPath, Size + 1 );
+}
+void Abc_ZddPrint( Abc_ZddMan * p, int a )
+{
+    int * pPath = ABC_CALLOC( int, p->nVars );
+    Abc_ZddPrint_rec( p, a, pPath, 0 );
+    ABC_FREE( pPath );
+}
+void Abc_ZddPrintTest( Abc_ZddMan * p )
+{
+//    int nSets = 2;
+//    int Size = 2;
+//    int pSets[2][2] = { {5, 0}, {3, 11} };
+    int nSets = 3;
+    int Size = 5;
+    int pSets[3][5] = { {5, 0, 2, 10, 7}, {3, 11, 10, 7, 2}, {0, 2, 5, 10, 7} };
+    int i, Set, Union = 0;
+    for ( i = 0; i < nSets; i++ )
+    {
+        Abc_ZddPermPrint( pSets[i], Size );
+        Set = Abc_ZddBuildSet( p, pSets[i], Size );
+        Union = Abc_ZddUnion( p, Union, Set );
+    }
+    printf( "Resulting set:\n" );
+    Abc_ZddPrint( p, Union );
+    printf( "\n" );
+    printf( "Nodes = %d.   Path = %d.\n", Abc_ZddCountNodes(p, Union), Abc_ZddCountPaths(p, Union) );
+    Size = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ZddGiaTest( Gia_Man_t * pGia )
+{
+    Abc_ZddMan * p;
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vNodes;
+    int i, r, Paths = 0;
+    p = Abc_ZddManAlloc( Gia_ManObjNum(pGia), 1 << 24 ); // 576 MB  (36 B/node)
+    Gia_ManFillValue( pGia );
+    Gia_ManForEachCi( pGia, pObj, i )
+        pObj->Value = Abc_ZddIthVar( Gia_ObjId(pGia, pObj) );
+    vNodes = Vec_IntAlloc( Gia_ManAndNum(pGia) );
+    Gia_ManForEachAnd( pGia, pObj, i )
+    {
+        r = Abc_ZddDotMinProduct6( p, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value );
+        r = Abc_ZddUnion( p, r, Abc_ZddIthVar(i) );
+        pObj->Value = r;
+        Vec_IntPush( vNodes, r );
+        // print
+//        printf( "Node %d:\n", i );
+//        Abc_ZddPrint( p, r );
+//        printf( "Node %d   ZddNodes = %d\n", i, Abc_ZddCountNodes(p, r) );
+    }
+    Gia_ManForEachAnd( pGia, pObj, i )
+        Paths += Abc_ZddCountPaths(p, pObj->Value);
+    printf( "Paths = %d.  Shared nodes = %d.\n", Paths, Abc_ZddCountNodesArray(p, vNodes) );
+    Vec_IntFree( vNodes );
+    Abc_ZddManFree( p );
+}
+/*
+    abc 01> &r pj1.aig; &ps; &test
+    pj1      : i/o =   1769/   1063  and =   16285  lev =  156 (12.91)  mem = 0.23 MB
+    Paths = 839934.  Shared nodes = 770999.
+    ZDD stats: Var = 19118  Obj = 11578174  All = 16777216  Hits = 25617277  Miss = 40231476  Mem = 576.00 MB
+*/
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ZddPermTestInt( Abc_ZddMan * p )
+{
+    int nPerms = 3;
+    int Size = 5;
+    int pPerms[3][5] = { {1, 0, 2, 4, 3}, {1, 2, 4, 0, 3}, {0, 3, 2, 1, 4} };
+    int pComb[5], nTrans;
+    int i, k, Set, Union = 0, iPivot;
+    for ( i = 0; i < nPerms; i++ )
+        Abc_ZddPermPrint( pPerms[i], Size );
+    for ( i = 0; i < nPerms; i++ )
+    {
+        printf( "Perm %d:\n", i );
+        Abc_ZddPermPrint( pPerms[i], Size );
+        nTrans = Abc_ZddPerm2Comb( pPerms[i], Size, pComb );
+        Abc_ZddCombPrint( pComb, nTrans );
+        for ( k = 0; k < nTrans; k++ )
+            pComb[k] = Abc_ZddVarIJ( p, pComb[k] >> 16, pComb[k] & 0xFFFF );
+        Abc_ZddPermPrint( pComb, nTrans );
+        // add to ZDD
+        Set = Abc_ZddBuildSet( p, pComb, nTrans );
+        Union = Abc_ZddUnion( p, Union, Set );
+    }
+    printf( "\nResulting set of permutations:\n" );
+    Abc_ZddPrint( p, Union );
+    printf( "Nodes = %d.   Path = %d.\n", Abc_ZddCountNodes(p, Union), Abc_ZddCountPaths(p, Union) );
+
+    iPivot = Abc_ZddVarIJ( p, 3, 4 );
+    Union = Abc_ZddPerm( p, Union, iPivot );
+
+    printf( "\nResulting set of permutations:\n" );
+    Abc_ZddPrint( p, Union );
+    printf( "Nodes = %d.   Path = %d.\n", Abc_ZddCountNodes(p, Union), Abc_ZddCountPaths(p, Union) );
+    printf( "\n" );
+}
+
+void Abc_ZddPermTest()
+{
+    Abc_ZddMan * p;
+    p = Abc_ZddManAlloc( 10, 1 << 20 );
+    Abc_ZddManCreatePerms( p, 5 );
+    Abc_ZddPermTestInt( p );
+    Abc_ZddManFree( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_EnumerateCubeStatesZdd()
+{
+    int pXYZ[3][9][2] = {
+        { {3, 5}, {3,17}, {3,15}, {1, 6}, {1,16}, {1,14}, {2, 4}, {2,18}, {2,13} },
+        { {2,14}, {2,24}, {2,12}, {3,13}, {3,23}, {3,10}, {1,15}, {1,22}, {1,11} },
+        { {1,10}, {1, 7}, {1, 4}, {3,12}, {3, 9}, {3, 6}, {2,11}, {2, 8}, {2, 5} }  };
+#ifdef WIN32
+    int LogObj = 24;
+#else
+    int LogObj = 27;
+#endif
+    Abc_ZddMan * p;
+    int i, k, pComb[9], pPerm[24], nSize;
+    int ZddTurn1, ZddTurn2, ZddTurn3, ZddTurns, ZddAll;
+    abctime clk = Abc_Clock();
+    printf( "Enumerating states of 2x2x2 cube.\n" );
+    p = Abc_ZddManAlloc( 24 * 23 / 2, 1 << LogObj ); // finished with 2^27 (4 GB)
+    Abc_ZddManCreatePerms( p, 24 );
+    // init state
+    printf( "Iter %2d -> %8d  Nodes = %7d  Used = %10d  ", 0, 1, 0, 2 );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    // first 9 states
+    ZddTurns = 1;
+    for ( i = 0; i < 3; i++ )
+    {
+        for ( k = 0; k < 24; k++ )
+            pPerm[k] = k;
+        for ( k = 0; k < 9; k++ )
+            ABC_SWAP( int, pPerm[pXYZ[i][k][0]-1], pPerm[pXYZ[i][k][1]-1] );
+        nSize = Abc_ZddPerm2Comb( pPerm, 24, pComb );
+        assert( nSize == 9 );
+        for ( k = 0; k < 9; k++ )
+            pComb[k] = Abc_ZddVarIJ( p, pComb[k] >> 16, pComb[k] & 0xffff );
+        // add first turn
+        ZddTurn1  = Abc_ZddBuildSet( p, pComb, 9 );
+        ZddTurns = Abc_ZddUnion( p, ZddTurns, ZddTurn1 );
+        //Abc_ZddPrint( p, ZddTurn1 );
+        // add second turn
+        ZddTurn2 = Abc_ZddPermProduct( p, ZddTurn1, ZddTurn1 );
+        ZddTurns = Abc_ZddUnion( p, ZddTurns, ZddTurn2 );
+        //Abc_ZddPrint( p, ZddTurn2 );
+        // add third turn
+        ZddTurn3 = Abc_ZddPermProduct( p, ZddTurn2, ZddTurn1 );
+        ZddTurns = Abc_ZddUnion( p, ZddTurns, ZddTurn3 );
+        //Abc_ZddPrint( p, ZddTurn3 );
+        //printf( "\n" );
+    }
+    //Abc_ZddPrint( p, ZddTurns );
+    printf( "Iter %2d -> %8d  Nodes = %7d  Used = %10d  ", 1, Abc_ZddCountPaths(p, ZddTurns), Abc_ZddCountNodes(p, ZddTurns), p->nObjs );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    // other states
+    ZddAll = ZddTurns;
+    for ( i = 2; i <= 100; i++ )
+    {
+        int ZddAllPrev = ZddAll;
+        ZddAll = Abc_ZddPermProduct( p, ZddAll, ZddTurns );
+        printf( "Iter %2d -> %8d  Nodes = %7d  Used = %10d  ", i, Abc_ZddCountPaths(p, ZddAll), Abc_ZddCountNodes(p, ZddAll), p->nObjs );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+        if ( ZddAllPrev == ZddAll )
+            break;
+    }
+    Abc_ZddManFree( p );
+}
+
+/*
+Enumerating states of 2x2x2 cube.
+Iter  0 ->        1  Nodes =       0  Used =          2  Time =     0.00 sec
+Iter  1 ->       10  Nodes =      63  Used =        577  Time =     0.00 sec
+Iter  2 ->       64  Nodes =     443  Used =       4349  Time =     0.03 sec
+Iter  3 ->      385  Nodes =    2018  Used =      26654  Time =     0.14 sec
+Iter  4 ->     2232  Nodes =    7451  Used =     119442  Time =     0.45 sec
+Iter  5 ->    12224  Nodes =   25178  Used =     490038  Time =     1.10 sec
+Iter  6 ->    62360  Nodes =   83955  Used =    1919750  Time =     1.79 sec
+Iter  7 ->   289896  Nodes =  290863  Used =    7182932  Time =     3.15 sec
+Iter  8 ->  1159968  Nodes =  614845  Used =   25301123  Time =     8.03 sec
+Iter  9 ->  3047716  Nodes =  585664  Used =   66228369  Time =    20.22 sec
+Iter 10 ->  3671516  Nodes =   19430  Used =  102292452  Time =    33.41 sec
+Iter 11 ->  3674160  Nodes =     511  Used =  103545878  Time =    33.92 sec
+Iter 12 ->  3674160  Nodes =     511  Used =  103566266  Time =    33.93 sec
+ZDD stats: Var = 276  Obj = 103566266  Alloc = 134217728  Hit = 63996630  Miss = 141768893  Mem = 4608.00 MB
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraUtilProgress.c b/abc-build/src/misc/extra/extraUtilProgress.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraUtilProgress.c
@@ -0,0 +1,185 @@
+/**CFile****************************************************************
+
+  FileName    [extraUtilProgress.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [extra]
+
+  Synopsis    [Progress bar.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: extraUtilProgress.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include "extra.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+struct ProgressBarStruct
+{
+    int              nItemsNext;   // the number of items for the next update of the progress bar
+    int              nItemsTotal;  // the total number of items
+    int              posTotal;     // the total number of positions
+    int              posCur;       // the current position
+    FILE *           pFile;        // the output stream 
+};
+
+static void Extra_ProgressBarShow( ProgressBar * p, char * pString );
+static void Extra_ProgressBarClean( ProgressBar * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the progress bar.]
+
+  Description [The first parameter is the output stream (pFile), where
+  the progress is printed. The current printing position should be the
+  first one on the given line. The second parameters is the total
+  number of items that correspond to 100% position of the progress bar.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+ProgressBar * Extra_ProgressBarStart( FILE * pFile, int nItemsTotal )
+{
+    ProgressBar * p;
+    if ( !Abc_FrameShowProgress(Abc_FrameGetGlobalFrame()) ) return NULL;
+    p = ABC_ALLOC( ProgressBar, 1 );
+    memset( p, 0, sizeof(ProgressBar) );
+    p->pFile       = pFile;
+    p->nItemsTotal = nItemsTotal;
+    p->posTotal    = 78;
+    p->posCur      = 1;
+    p->nItemsNext  = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal);
+    Extra_ProgressBarShow( p, NULL );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the progress bar.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_ProgressBarUpdate_int( ProgressBar * p, int nItemsCur, char * pString )
+{
+    if ( p == NULL ) return;
+    if ( nItemsCur < p->nItemsNext )
+        return;
+    if ( nItemsCur >= p->nItemsTotal )
+    {
+        p->posCur = 78;
+        p->nItemsNext = 0x7FFFFFFF;
+    }
+    else
+    {
+        p->posCur += 7;
+        p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal);
+    }
+    Extra_ProgressBarShow( p, pString );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the progress bar.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_ProgressBarStop( ProgressBar * p )
+{
+    if ( p == NULL ) return;
+    Extra_ProgressBarClean( p );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the progress bar of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_ProgressBarShow( ProgressBar * p, char * pString )
+{
+    int i;
+    if ( p == NULL ) 
+        return;
+    if ( Abc_FrameIsBatchMode() )
+        return;
+    if ( pString )
+        fprintf( p->pFile, "%s ", pString );
+    for ( i = (pString? strlen(pString) + 1 : 0); i < p->posCur; i++ )
+        fprintf( p->pFile, "-" );
+    if ( i == p->posCur )
+        fprintf( p->pFile, ">" );
+    for ( i++  ; i <= p->posTotal; i++ )
+        fprintf( p->pFile, " " );
+    fprintf( p->pFile, "\r" );
+    fflush( stdout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the progress bar before quitting.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_ProgressBarClean( ProgressBar * p )
+{
+    int i;
+    if ( p == NULL ) 
+        return;
+    if ( Abc_FrameIsBatchMode() )
+        return;
+    for ( i = 0; i <= p->posTotal; i++ )
+        fprintf( p->pFile, " " );
+    fprintf( p->pFile, "\r" );
+    fflush( stdout );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraUtilReader.c b/abc-build/src/misc/extra/extraUtilReader.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraUtilReader.c
@@ -0,0 +1,390 @@
+/**CFile****************************************************************
+
+  FileName    [extraUtilReader.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [extra]
+
+  Synopsis    [File reading utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: extraUtilReader.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include "extra.h"
+#include "misc/vec/vec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define EXTRA_BUFFER_SIZE        4*1048576    // 1M   - size of the data chunk stored in memory
+#define EXTRA_OFFSET_SIZE           4096    // 4K   - load new data when less than this is left
+
+#define EXTRA_MINIMUM(a,b)       (((a) < (b))? (a) : (b))
+
+struct Extra_FileReader_t_
+{
+    // the input file
+    char *           pFileName;     // the input file name
+    FILE *           pFile;         // the input file pointer
+    int              nFileSize;     // the total number of bytes in the file
+    int              nFileRead;     // the number of bytes currently read from file
+    // info about processing different types of input chars
+    char             pCharMap[256]; // the character map
+    // temporary storage for data 
+    char *           pBuffer;       // the buffer
+    int              nBufferSize;   // the size of the buffer
+    char *           pBufferCur;    // the current reading position
+    char *           pBufferEnd;    // the first position not used by currently loaded data
+    char *           pBufferStop;   // the position where loading new data will be done
+    // tokens given to the user
+    Vec_Ptr_t *      vTokens;       // the vector of tokens returned to the user
+    Vec_Int_t *      vLines;        // the vector of line numbers for each token
+    int              nLineCounter;  // the counter of lines processed
+    // status of the parser
+    int              fStop;         // this flag goes high when the end of file is reached
+};
+
+// character types
+typedef enum { 
+    EXTRA_CHAR_COMMENT,  // a character that begins the comment
+    EXTRA_CHAR_NORMAL,   // a regular character
+    EXTRA_CHAR_STOP,     // a character that delimits a series of tokens
+    EXTRA_CHAR_CLEAN     // a character that should be cleaned
+} Extra_CharType_t;
+
+// the static functions
+static void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p );
+static void Extra_FileReaderReload( Extra_FileReader_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the file reader.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Extra_FileReader_t * Extra_FileReaderAlloc( char * pFileName, 
+    char * pCharsComment, char * pCharsStop, char * pCharsClean )
+{
+    Extra_FileReader_t * p;
+    FILE * pFile;
+    char * pChar;
+    int nCharsToRead;
+    int RetValue;
+    // check if the file can be opened
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Extra_FileReaderAlloc(): Cannot open input file \"%s\".\n", pFileName );
+        return NULL;
+    }
+    // start the file reader    
+    p = ABC_ALLOC( Extra_FileReader_t, 1 );
+    memset( p, 0, sizeof(Extra_FileReader_t) );
+    p->pFileName   = pFileName;
+    p->pFile       = pFile;
+    // set the character map
+    memset( p->pCharMap, EXTRA_CHAR_NORMAL, 256 );
+    for ( pChar = pCharsComment; *pChar; pChar++ )
+        p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_COMMENT;
+    for ( pChar = pCharsStop; *pChar; pChar++ )
+        p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_STOP;
+    for ( pChar = pCharsClean; *pChar; pChar++ )
+        p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_CLEAN;
+    // get the file size, in bytes
+    fseek( pFile, 0, SEEK_END );  
+    p->nFileSize = ftell( pFile );  
+    rewind( pFile ); 
+    // allocate the buffer
+    p->pBuffer = ABC_ALLOC( char, EXTRA_BUFFER_SIZE+1 );
+    p->nBufferSize = EXTRA_BUFFER_SIZE;
+    p->pBufferCur  = p->pBuffer;
+    // determine how many chars to read
+    nCharsToRead = EXTRA_MINIMUM(p->nFileSize, EXTRA_BUFFER_SIZE);
+    // load the first part into the buffer
+    RetValue = fread( p->pBuffer, nCharsToRead, 1, p->pFile );
+    p->nFileRead = nCharsToRead;
+    // set the ponters to the end and the stopping point
+    p->pBufferEnd  = p->pBuffer + nCharsToRead;
+    p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + EXTRA_BUFFER_SIZE - EXTRA_OFFSET_SIZE;
+    // start the arrays
+    p->vTokens = Vec_PtrAlloc( 100 );
+    p->vLines = Vec_IntAlloc( 100 );
+    p->nLineCounter = 1; // 1-based line counting
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the file reader.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_FileReaderFree( Extra_FileReader_t * p )
+{
+    if ( p->pFile )
+        fclose( p->pFile );
+    ABC_FREE( p->pBuffer );
+    Vec_PtrFree( p->vTokens );
+    Vec_IntFree( p->vLines );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the file size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_FileReaderGetFileName( Extra_FileReader_t * p )
+{
+    return p->pFileName;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the file size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_FileReaderGetFileSize( Extra_FileReader_t * p )
+{
+    return p->nFileSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the current reading position.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_FileReaderGetCurPosition( Extra_FileReader_t * p )
+{
+    return p->nFileRead - (p->pBufferEnd - p->pBufferCur);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the line number for the given token.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_FileReaderGetLineNumber( Extra_FileReader_t * p, int iToken )
+{
+    assert( iToken >= 0 && iToken < p->vTokens->nSize );
+    return p->vLines->pArray[iToken];
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the next set of tokens.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Extra_FileReaderGetTokens( Extra_FileReader_t * p )
+{
+    Vec_Ptr_t * vTokens;
+    while ( (vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens_int( p )) )
+        if ( vTokens->nSize > 0 )
+            break;
+    return vTokens;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the next set of tokens.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p )
+{
+    char * pChar;
+    int fTokenStarted, MapValue;
+    if ( p->fStop )
+        return NULL;
+    // reset the token info
+    p->vTokens->nSize = 0;
+    p->vLines->nSize = 0;
+    fTokenStarted = 0;
+    // check if the new data should to be loaded
+    if ( p->pBufferCur > p->pBufferStop )
+        Extra_FileReaderReload( p );
+
+//    printf( "%d\n", p->pBufferEnd - p->pBufferCur );
+
+    // process the string starting from the current position
+    for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ )
+    {
+        // count the lines
+        if ( *pChar == '\n' )
+            p->nLineCounter++;
+        // switch depending on the character
+        MapValue = p->pCharMap[(int)*pChar];
+
+//        printf( "Char value = %d. Map value = %d.\n", *pChar, MapValue );
+
+
+        switch ( MapValue )
+        {
+            case EXTRA_CHAR_COMMENT:
+                if ( *pChar != '/' || *(pChar+1) == '/' ) 
+                { // dealing with the need to have // as a comment
+                    // if the token was being written, stop it
+                    if ( fTokenStarted )
+                        fTokenStarted = 0;
+                    // eraze the comment till the end of line
+                    while ( *pChar != '\n' )
+                    {
+                        *pChar++ = 0;
+                        if ( pChar == p->pBufferEnd )
+                        {   // this failure is due to the fact the comment continued 
+                            // through EXTRA_OFFSET_SIZE chars till the end of the buffer
+                            printf( "Extra_FileReader failed to parse the file \"%s\".\n", p->pFileName );
+                            return NULL;
+                        }
+                    }
+                    pChar--;
+                    break;
+                }
+                // otherwise it is a normal character
+            case EXTRA_CHAR_NORMAL:
+                if ( !fTokenStarted )
+                {
+                    Vec_PtrPush( p->vTokens, pChar );
+                    Vec_IntPush( p->vLines, p->nLineCounter );
+                    fTokenStarted = 1;
+                }
+                break;
+            case EXTRA_CHAR_STOP:
+                if ( fTokenStarted )
+                    fTokenStarted = 0;
+                *pChar = 0;
+                // prepare before leaving
+                p->pBufferCur = pChar + 1;
+                return p->vTokens;
+            case EXTRA_CHAR_CLEAN:
+                if ( fTokenStarted )
+                    fTokenStarted = 0;
+                *pChar = 0;
+                break;
+            default:
+                assert( 0 );
+        }
+    }
+    // the file is finished or the last part continued 
+    // through EXTRA_OFFSET_SIZE chars till the end of the buffer
+    if ( p->pBufferStop == p->pBufferEnd ) // end of file
+    {
+        *pChar = 0;
+        p->fStop = 1;
+        return p->vTokens;
+    }
+    printf( "Extra_FileReader failed to parse the file \"%s\".\n", p->pFileName );
+/*
+    {
+        int i;
+        for ( i = 0; i < p->vTokens->nSize; i++ )
+            printf( "%s ", p->vTokens->pArray[i] );
+        printf( "\n" );
+    }
+*/
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Loads new data into the file reader.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_FileReaderReload( Extra_FileReader_t * p )
+{
+    int nCharsUsed, nCharsToRead;
+    int RetValue;
+    assert( !p->fStop );
+    assert( p->pBufferCur > p->pBufferStop );
+    assert( p->pBufferCur < p->pBufferEnd );
+    // figure out how many chars are still not processed
+    nCharsUsed = p->pBufferEnd - p->pBufferCur;
+    // move the remaining data to the beginning of the buffer
+    memmove( p->pBuffer, p->pBufferCur, nCharsUsed );
+    p->pBufferCur = p->pBuffer;
+    // determine how many chars we will read
+    nCharsToRead = EXTRA_MINIMUM( p->nBufferSize - nCharsUsed, p->nFileSize - p->nFileRead );
+    // read the chars
+    RetValue = fread( p->pBuffer + nCharsUsed, nCharsToRead, 1, p->pFile );
+    p->nFileRead += nCharsToRead;
+    // set the ponters to the end and the stopping point
+    p->pBufferEnd  = p->pBuffer + nCharsUsed + nCharsToRead;
+    p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + EXTRA_BUFFER_SIZE - EXTRA_OFFSET_SIZE;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraUtilSupp.c b/abc-build/src/misc/extra/extraUtilSupp.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraUtilSupp.c
@@ -0,0 +1,532 @@
+/**CFile****************************************************************
+
+  FileName    [extraUtilSupp.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [extra]
+
+  Synopsis    [Support minimization.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: extraUtilSupp.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "misc/vec/vec.h"
+#include "misc/vec/vecWec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern void         Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits );
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Generate m-out-of-n vectors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_SuppCountOnes( unsigned i )
+{
+    i = i - ((i >> 1) & 0x55555555);
+    i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
+    i = ((i + (i >> 4)) & 0x0F0F0F0F);
+    return (i*(0x01010101))>>24;
+}
+Vec_Wrd_t * Abc_SuppGen( int m, int n )
+{
+    Vec_Wrd_t * vRes = Vec_WrdAlloc( 1000 );
+    int i, Size = (1 << n);
+    for ( i = 0; i < Size; i++ )
+        if ( Abc_SuppCountOnes(i) == m )
+            Vec_WrdPush( vRes, i );
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform verification.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SuppVerify( Vec_Wrd_t * p, word * pMatrix, int nVars, int nVarsMin )
+{
+    Vec_Wrd_t * pNew;
+    word * pLimit, * pEntry1, * pEntry2;
+    word Entry, EntryNew;
+    int i, k, v, Value, Counter = 0;
+    pNew = Vec_WrdAlloc( Vec_WrdSize(p) );
+    Vec_WrdForEachEntry( p, Entry, i )
+    {
+        EntryNew = 0;
+        for ( v = 0; v < nVarsMin; v++ )
+        {
+            Value = 0;
+            for ( k = 0; k < nVars; k++ )
+                if ( ((pMatrix[v] >> k) & 1) && ((Entry >> k) & 1) )
+                    Value ^= 1;
+            if ( Value )
+                EntryNew |= (((word)1) << v);            
+        }
+        Vec_WrdPush( pNew, EntryNew );
+    }
+    // check that they are disjoint
+    pLimit  = Vec_WrdLimit(pNew);
+    pEntry1 = Vec_WrdArray(pNew);
+    for ( ; pEntry1 < pLimit; pEntry1++ )
+    for ( pEntry2 = pEntry1 + 1; pEntry2 < pLimit; pEntry2++ )
+        if ( *pEntry1 == *pEntry2 )
+            Counter++;
+    if ( Counter )
+        printf( "The total of %d pairs fail verification.\n", Counter );
+    else
+        printf( "Verification successful.\n" );
+    Vec_WrdFree( pNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generate pairs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Wrd_t * Abc_SuppGenPairs( Vec_Wrd_t * p, int nBits )
+{
+    Vec_Wrd_t * vRes = Vec_WrdAlloc( 1000 );
+    unsigned * pMap = ABC_CALLOC( unsigned, 1 << Abc_MaxInt(0,nBits-5) ); 
+    word * pLimit = Vec_WrdLimit(p);
+    word * pEntry1 = Vec_WrdArray(p);
+    word * pEntry2, Value;
+    for ( ; pEntry1 < pLimit; pEntry1++ )
+    for ( pEntry2 = pEntry1 + 1; pEntry2 < pLimit; pEntry2++ )
+    {
+        Value = *pEntry1 ^ *pEntry2;
+        if ( Abc_InfoHasBit(pMap, (int)Value) )
+            continue;
+        Abc_InfoXorBit( pMap, (int)Value );
+        Vec_WrdPush( vRes, Value );
+    }
+    ABC_FREE( pMap );
+    return vRes;
+}
+Vec_Wrd_t * Abc_SuppGenPairs2( int nOnes, int nBits )
+{
+    Vec_Wrd_t * vRes = Vec_WrdAlloc( 1000 );
+    int i, k, Size = (1 << nBits), Value;
+    for ( i = 0; i < Size; i++ )
+    {
+        Value = Abc_SuppCountOnes(i);
+        for ( k = 1; k <= nOnes; k++ )
+            if ( Value == 2*k )
+                break;
+        if ( k <= nOnes )
+            Vec_WrdPush( vRes, i );
+    }
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Select variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SuppPrintMask( word uMask, int nBits )
+{
+    int i;
+    for ( i = 0; i < nBits; i++ )
+        printf( "%d", (int)((uMask >> i) & 1) );
+    printf( "\n" );
+}
+void Abc_SuppGenProfile( Vec_Wrd_t * p, int nBits, int * pCounts )
+{
+    word Ent;
+    int i, k, b;
+    Vec_WrdForEachEntry( p, Ent, i )
+        for ( b = ((Ent >> nBits) & 1), k = 0; k < nBits; k++ )
+            pCounts[k] += ((Ent >> k) & 1) ^ b;
+}
+void Abc_SuppPrintProfile( Vec_Wrd_t * p, int nBits )
+{
+    int k, Counts[64] = {0};
+    Abc_SuppGenProfile( p, nBits, Counts );
+    for ( k = 0; k < nBits; k++ )
+        printf( "%2d : %6d  %6.2f %%\n", k, Counts[k], 100.0 * Counts[k] / Vec_WrdSize(p) );
+}
+int Abc_SuppGenFindBest( Vec_Wrd_t * p, int nBits, int * pMerit )
+{
+    int k, kBest = 0, Counts[64] = {0};
+    Abc_SuppGenProfile( p, nBits, Counts );
+    for ( k = 1; k < nBits; k++ )
+        if ( Counts[kBest] < Counts[k] )
+            kBest = k;
+    *pMerit = Counts[kBest];
+    return kBest;
+}
+void Abc_SuppGenSelectVar( Vec_Wrd_t * p, int nBits, int iVar )
+{
+    word * pEntry = Vec_WrdArray(p);
+    word * pLimit = Vec_WrdLimit(p);
+    for ( ; pEntry < pLimit; pEntry++ )
+        if ( (*pEntry >> iVar) & 1 )
+            *pEntry ^= (((word)1) << nBits);
+}
+void Abc_SuppGenFilter( Vec_Wrd_t * p, int nBits )
+{
+    word Ent;
+    int i, k = 0;
+    Vec_WrdForEachEntry( p, Ent, i )
+        if ( ((Ent >> nBits) & 1) == 0 )
+            Vec_WrdWriteEntry( p, k++, Ent );
+    Vec_WrdShrink( p, k );
+}
+word Abc_SuppFindOne( Vec_Wrd_t * p, int nBits )
+{
+    word uMask = 0;
+    int Prev = -1, This, Var;
+    while ( 1 )
+    {
+        Var = Abc_SuppGenFindBest( p, nBits, &This );
+        if ( Prev >= This )
+            break;
+        Prev = This;
+        Abc_SuppGenSelectVar( p, nBits, Var );
+        uMask |= (((word)1) << Var);
+    }
+    return uMask;
+}
+int Abc_SuppMinimize( word * pMatrix, Vec_Wrd_t * p, int nBits, int fVerbose )
+{
+    int i;
+    for ( i = 0; Vec_WrdSize(p) > 0; i++ )
+    {
+//        Abc_SuppPrintProfile( p, nBits );
+        pMatrix[i] = Abc_SuppFindOne( p, nBits );
+        Abc_SuppGenFilter( p, nBits );   
+        if ( !fVerbose )
+            continue;
+        // print stats
+        printf( "%2d : ", i );
+        printf( "%6d  ", Vec_WrdSize(p) );
+        Abc_SuppPrintMask( pMatrix[i], nBits );
+//        printf( "\n" );
+    }
+    return i;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SuppTest( int nOnes, int nVars, int fUseSimple, int fCheck, int fVerbose )
+{
+    int nVarsMin;
+    word Matrix[64];
+    abctime clk = Abc_Clock();
+    // create the problem
+    Vec_Wrd_t * vRes = Abc_SuppGen( nOnes, nVars );
+    Vec_Wrd_t * vPairs = fUseSimple ? Abc_SuppGenPairs2( nOnes, nVars ) : Abc_SuppGenPairs( vRes, nVars );
+    assert( nVars < 100 );
+    printf( "M = %2d  N = %2d : ", nOnes, nVars );
+    printf( "K = %6d   ",  Vec_WrdSize(vRes) );
+    printf( "Total = %12.0f  ", 0.5 * Vec_WrdSize(vRes) * (Vec_WrdSize(vRes) - 1) );
+    printf( "Distinct = %8d  ",  Vec_WrdSize(vPairs) );
+    Abc_PrintTime( 1, "Reduction time", Abc_Clock() - clk );
+    // solve the problem
+    clk = Abc_Clock();
+    nVarsMin = Abc_SuppMinimize( Matrix, vPairs, nVars, fVerbose );
+    printf( "Solution with %d variables found.  ", nVarsMin );
+    Abc_PrintTime( 1, "Covering time", Abc_Clock() - clk );
+    if ( fCheck )
+        Abc_SuppVerify( vRes, Matrix, nVars, nVarsMin );
+    Vec_WrdFree( vPairs );
+    Vec_WrdFree( vRes );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the input part of the cubes specified in MIN format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Wrd_t * Abc_SuppReadMin( char * pFileName, int * pnVars )
+{
+    extern char * Extra_FileReadContents( char * pFileName );
+    Vec_Wrd_t * vRes; word uCube;
+    int nCubes = 0, nVars = -1, iVar;
+    char * pCur, * pToken, * pStart = "INPUT F-COVER";
+    char * pStr = Extra_FileReadContents( pFileName );
+    if ( pStr == NULL )
+        { printf( "Cannot open input file (%s).\n", pFileName ); return NULL; }
+    pCur = strstr( pStr, pStart );
+    if ( pCur == NULL )
+        { printf( "Cannot find beginning of cube cover (%s).\n", pStart ); return NULL; }
+    pToken = strtok( pCur + strlen(pStart), " \t\r\n," );
+    nCubes = atoi( pToken );
+    if ( nCubes < 1 || nCubes > 1000000 )
+        { printf( "The number of cubes in not in the range [1; 1000000].\n" ); return NULL; }
+    vRes = Vec_WrdAlloc( 1000 );
+    uCube = 0; iVar = 0;
+    while ( (pToken = strtok(NULL, " \t\r\n,")) != NULL )
+    {
+        if ( strlen(pToken) > 2 )
+        {
+            if ( !strncmp(pToken, "INPUT", strlen("INPUT")) )
+                break;
+            if ( iVar > 64 )
+                { printf( "The number of inputs (%d) is too high.\n", iVar ); Vec_WrdFree(vRes); return NULL; }
+            if ( nVars == -1 )
+                nVars = iVar;
+            else if ( nVars != iVar )
+                { printf( "The number of inputs (%d) does not match declaration (%d).\n", nVars, iVar ); Vec_WrdFree(vRes); return NULL; }
+            Vec_WrdPush( vRes, uCube );
+            uCube = 0; iVar = 0;
+            continue;
+        }
+        if ( pToken[1] == '0' && pToken[0] == '1' ) // value 1
+            uCube |= (((word)1) << iVar);
+        else if ( pToken[1] != '1' || pToken[0] != '0' ) // value 0
+            { printf( "Strange literal representation (%s) of cube %d.\n", pToken, nCubes ); Vec_WrdFree(vRes); return NULL; }
+        iVar++;
+    }
+    ABC_FREE( pStr );
+    if ( Vec_WrdSize(vRes) != nCubes )
+        { printf( "The number of cubes (%d) does not match declaration (%d).\n", Vec_WrdSize(vRes), nCubes ); Vec_WrdFree(vRes); return NULL; }
+    else
+        printf( "Successfully parsed function with %d inputs and %d cubes.\n", nVars, nCubes );
+    *pnVars = nVars;
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Wrd_t * Abc_SuppDiffMatrix( Vec_Wrd_t * vCubes )
+{
+    abctime clk = Abc_Clock();
+    word * pEnt2, * pEnt = Vec_WrdArray( vCubes );
+    word * pLimit = Vec_WrdLimit( vCubes );
+    Vec_Wrd_t * vRes, * vPairs = Vec_WrdAlloc( Vec_WrdSize(vCubes) * (Vec_WrdSize(vCubes) - 1) / 2 );
+    word * pStore = Vec_WrdArray( vPairs );
+    for ( ; pEnt < pLimit; pEnt++ )
+    for ( pEnt2 = pEnt+1; pEnt2 < pLimit; pEnt2++ )
+        *pStore++ = *pEnt ^ *pEnt2;
+    vPairs->nSize = Vec_WrdCap(vPairs);
+    assert( pStore == Vec_WrdLimit(vPairs) );
+//    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+//    vRes = Vec_WrdUniqifyHash( vPairs, 1 );
+    vRes = Vec_WrdDup( vPairs );
+    printf( "Successfully generated diff matrix with %10d rows (%6.2f %%).  ", 
+        Vec_WrdSize(vRes), 100.0 * Vec_WrdSize(vRes) / Vec_WrdSize(vPairs) );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    Vec_WrdFree( vPairs );
+    return vRes;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Solve difference matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_SuppCountOnes64( word i )
+{
+    i = i - ((i >> 1) & 0x5555555555555555);
+    i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333);
+    i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F);
+    return (i*(0x0101010101010101))>>56;
+}
+int Abc_SuppFindVar( Vec_Wec_t * pS, Vec_Wec_t * pD, int nVars )
+{
+    int v, vBest = -1, dBest;
+    for ( v = 0; v < nVars; v++ )
+    {
+        if ( Vec_WecLevelSize(pS, v) )
+            continue;
+        if ( vBest == -1 || dBest > Vec_WecLevelSize(pD, v) )
+            vBest = v, dBest = Vec_WecLevelSize(pD, v);
+    }
+    return vBest;
+}
+void Abc_SuppRemove( Vec_Wrd_t * p, int * pCounts, Vec_Wec_t * pS, Vec_Wec_t * pD, int iVar, int nVars )
+{
+    word Entry; int i, v;
+    assert( Vec_WecLevelSize(pS, iVar) == 0 );
+    Vec_IntClear( Vec_WecEntry(pD, iVar) );
+    Vec_WrdForEachEntry( p, Entry, i )
+    {
+        if ( ((Entry >> iVar) & 1) == 0 )
+            continue;
+        pCounts[i]--;
+        if ( pCounts[i] == 1 )
+        {
+            for ( v = 0; v < nVars; v++ )
+                if ( (Entry >> v) & 1 )
+                {
+                    Vec_IntRemove( Vec_WecEntry(pD, v), i );
+                    Vec_WecPush( pS, v, i );
+                }
+        }
+        else if ( pCounts[i] == 2 )
+        {
+            for ( v = 0; v < nVars; v++ )
+                if ( (Entry >> v) & 1 )
+                    Vec_WecPush( pD, v, i );
+        }        
+    }
+}
+void Abc_SuppProfile( Vec_Wec_t * pS, Vec_Wec_t * pD, int nVars )
+{
+    int v;
+    for ( v = 0; v < nVars; v++ )
+        printf( "%2d : S = %3d  D = %3d\n", v, Vec_WecLevelSize(pS, v), Vec_WecLevelSize(pD, v) );
+}
+int Abc_SuppSolve( Vec_Wrd_t * p, int nVars )
+{
+    abctime clk = Abc_Clock();
+    Vec_Wrd_t * pNew = Vec_WrdDup( p );
+    Vec_Wec_t * vSingles = Vec_WecStart( 64 );
+    Vec_Wec_t * vDoubles = Vec_WecStart( 64 );
+    word Entry; int i, v, iVar, nVarsNew = nVars;
+    int * pCounts = ABC_ALLOC( int, Vec_WrdSize(p) );
+    Vec_WrdForEachEntry( p, Entry, i )
+    {
+        pCounts[i] = Abc_SuppCountOnes64( Entry );
+        if ( pCounts[i] == 1 )
+        {
+            for ( v = 0; v < nVars; v++ )
+                if ( (Entry >> v) & 1 )
+                    Vec_WecPush( vSingles, v, i );
+        }
+        else if ( pCounts[i] == 2 )
+        {
+            for ( v = 0; v < nVars; v++ )
+                if ( (Entry >> v) & 1 )
+                    Vec_WecPush( vDoubles, v, i );
+        }
+    }
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+//    Abc_SuppProfile( vSingles, vDoubles, nVars );
+    // find variable in 0 singles and the smallest doubles
+    while ( 1 )
+    {
+        iVar = Abc_SuppFindVar( vSingles, vDoubles, nVars );
+        if ( iVar == -1 )
+            break;
+//        printf( "Selected variable %d.\n", iVar );
+        Abc_SuppRemove( pNew, pCounts, vSingles, vDoubles, iVar, nVars );
+//        Abc_SuppProfile( vSingles, vDoubles, nVars );
+        nVarsNew--;
+    }
+//    printf( "Result = %d (out of %d)\n", nVarsNew, nVars );
+    Vec_WecFree( vSingles );
+    Vec_WecFree( vDoubles );
+    Vec_WrdFree( pNew );
+    ABC_FREE( pCounts );
+    return nVarsNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SuppReadMinTest( char * pFileName )
+{
+//    int fVerbose = 0;
+    abctime clk = Abc_Clock();
+//    word Matrix[64];
+    int nVars, nVarsMin;
+    Vec_Wrd_t * vPairs, * vCubes;
+    vCubes = Abc_SuppReadMin( pFileName, &nVars );
+    if ( vCubes == NULL )
+        return;
+    vPairs = Abc_SuppDiffMatrix( vCubes );
+    Vec_WrdFreeP( &vCubes );
+    // solve the problem
+    clk = Abc_Clock();
+//    nVarsMin = Abc_SuppMinimize( Matrix, vPairs, nVars, fVerbose );
+    nVarsMin = Abc_SuppSolve( vPairs, nVars );
+    printf( "Solution with %d variables found.  ", nVarsMin );
+    Abc_PrintTime( 1, "Covering time", Abc_Clock() - clk );
+
+    Vec_WrdFreeP( &vPairs );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraUtilTruth.c b/abc-build/src/misc/extra/extraUtilTruth.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraUtilTruth.c
@@ -0,0 +1,1153 @@
+/**CFile****************************************************************
+
+  FileName    [extraUtilMisc.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [extra]
+
+  Synopsis    [Various procedures for truth table manipulation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: extraUtilMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static unsigned s_VarMasks[5][2] = {
+    { 0x33333333, 0xAAAAAAAA },
+    { 0x55555555, 0xCCCCCCCC },
+    { 0x0F0F0F0F, 0xF0F0F0F0 },
+    { 0x00FF00FF, 0xFF00FF00 },
+    { 0x0000FFFF, 0xFFFF0000 }
+};
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+  Synopsis    [Derive elementary truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned ** Extra_TruthElementary( int nVars )
+{
+    unsigned ** pRes;
+    int i, k, nWords;
+    nWords = Extra_TruthWordNum(nVars);
+    pRes = (unsigned **)Extra_ArrayAlloc( nVars, nWords, 4 );
+    for ( i = 0; i < nVars; i++ )
+    {
+        if ( i < 5 )
+        {
+            for ( k = 0; k < nWords; k++ )
+                pRes[i][k] = s_VarMasks[i][1];
+        }
+        else
+        {
+            for ( k = 0; k < nWords; k++ )
+                if ( k & (1 << (i-5)) )
+                    pRes[i][k] = ~(unsigned)0;
+                else
+                    pRes[i][k] = 0;
+        }
+    }
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Swaps two adjacent variables in the truth table.]
+
+  Description [Swaps var number Start and var number Start+1 (0-based numbers).
+  The input truth table is pIn. The output truth table is pOut.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int iVar )
+{
+    static unsigned PMasks[4][3] = {
+        { 0x99999999, 0x22222222, 0x44444444 },
+        { 0xC3C3C3C3, 0x0C0C0C0C, 0x30303030 },
+        { 0xF00FF00F, 0x00F000F0, 0x0F000F00 },
+        { 0xFF0000FF, 0x0000FF00, 0x00FF0000 }
+    };
+    int nWords = Extra_TruthWordNum( nVars );
+    int i, k, Step, Shift;
+
+    assert( iVar < nVars - 1 );
+    if ( iVar < 4 )
+    {
+        Shift = (1 << iVar);
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift);
+    }
+    else if ( iVar > 4 )
+    {
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 4*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                pOut[i] = pIn[i];
+            for ( i = 0; i < Step; i++ )
+                pOut[Step+i] = pIn[2*Step+i];
+            for ( i = 0; i < Step; i++ )
+                pOut[2*Step+i] = pIn[Step+i];
+            for ( i = 0; i < Step; i++ )
+                pOut[3*Step+i] = pIn[3*Step+i];
+            pIn  += 4*Step;
+            pOut += 4*Step;
+        }
+    }
+    else // if ( iVar == 4 )
+    {
+        for ( i = 0; i < nWords; i += 2 )
+        {
+            pOut[i]   = (pIn[i]   & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16);
+            pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i]   & 0xFFFF0000) >> 16);
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Swaps two adjacent variables in the truth table.]
+
+  Description [Swaps var number Start and var number Start+1 (0-based numbers).
+  The input truth table is pIn. The output truth table is pOut.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_TruthSwapAdjacentVars2( unsigned * pIn, unsigned * pOut, int nVars, int Start )
+{
+    int nWords = (nVars <= 5)? 1 : (1 << (nVars-5));
+    int i, k, Step;
+
+    assert( Start < nVars - 1 );
+    switch ( Start )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0x99999999) | ((pIn[i] & 0x22222222) << 1) | ((pIn[i] & 0x44444444) >> 1);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0xC3C3C3C3) | ((pIn[i] & 0x0C0C0C0C) << 2) | ((pIn[i] & 0x30303030) >> 2);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0xF00FF00F) | ((pIn[i] & 0x00F000F0) << 4) | ((pIn[i] & 0x0F000F00) >> 4);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pIn[i] & 0xFF0000FF) | ((pIn[i] & 0x0000FF00) << 8) | ((pIn[i] & 0x00FF0000) >> 8);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i += 2 )
+        {
+            pOut[i]   = (pIn[i]   & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16);
+            pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i]   & 0xFFFF0000) >> 16);
+        }
+        return;
+    default:
+        Step = (1 << (Start - 5));
+        for ( k = 0; k < nWords; k += 4*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                pOut[i] = pIn[i];
+            for ( i = 0; i < Step; i++ )
+                pOut[Step+i] = pIn[2*Step+i];
+            for ( i = 0; i < Step; i++ )
+                pOut[2*Step+i] = pIn[Step+i];
+            for ( i = 0; i < Step; i++ )
+                pOut[3*Step+i] = pIn[3*Step+i];
+            pIn  += 4*Step;
+            pOut += 4*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Expands the truth table according to the phase.]
+
+  Description [The input and output truth tables are in pIn/pOut. The current number
+  of variables is nVars. The total number of variables in nVarsAll. The last argument
+  (Phase) contains shows where the variables should go.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase )
+{
+    unsigned * pTemp;
+    int i, k, Var = nVars - 1, Counter = 0;
+    for ( i = nVarsAll - 1; i >= 0; i-- )
+        if ( Phase & (1 << i) )
+        {
+            for ( k = Var; k < i; k++ )
+            {
+                Extra_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k );
+                pTemp = pIn; pIn = pOut; pOut = pTemp;
+                Counter++;
+            }
+            Var--;
+        }
+    assert( Var == -1 );
+    // swap if it was moved an even number of times
+    if ( !(Counter & 1) )
+        Extra_TruthCopy( pOut, pIn, nVarsAll );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Shrinks the truth table according to the phase.]
+
+  Description [The input and output truth tables are in pIn/pOut. The current number
+  of variables is nVars. The total number of variables in nVarsAll. The last argument
+  (Phase) contains shows what variables should remain.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase )
+{
+    unsigned * pTemp;
+    int i, k, Var = 0, Counter = 0;
+    for ( i = 0; i < nVarsAll; i++ )
+        if ( Phase & (1 << i) )
+        {
+            for ( k = i-1; k >= Var; k-- )
+            {
+                Extra_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k );
+                pTemp = pIn; pIn = pOut; pOut = pTemp;
+                Counter++;
+            }
+            Var++;
+        }
+    assert( Var == nVars );
+    // swap if it was moved an even number of times
+    if ( !(Counter & 1) )
+        Extra_TruthCopy( pOut, pIn, nVarsAll );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if TT depends on the given variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar )
+{
+    int nWords = Extra_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            if ( (pTruth[i] & 0x55555555) != ((pTruth[i] & 0xAAAAAAAA) >> 1) )
+                return 1;
+        return 0;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            if ( (pTruth[i] & 0x33333333) != ((pTruth[i] & 0xCCCCCCCC) >> 2) )
+                return 1;
+        return 0;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            if ( (pTruth[i] & 0x0F0F0F0F) != ((pTruth[i] & 0xF0F0F0F0) >> 4) )
+                return 1;
+        return 0;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            if ( (pTruth[i] & 0x00FF00FF) != ((pTruth[i] & 0xFF00FF00) >> 8) )
+                return 1;
+        return 0;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            if ( (pTruth[i] & 0x0000FFFF) != ((pTruth[i] & 0xFFFF0000) >> 16) )
+                return 1;
+        return 0;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                if ( pTruth[i] != pTruth[Step+i] )
+                    return 1;
+            pTruth += 2*Step;
+        }
+        return 0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of support vars.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_TruthSupportSize( unsigned * pTruth, int nVars )
+{
+    int i, Counter = 0;
+    for ( i = 0; i < nVars; i++ )
+        Counter += Extra_TruthVarInSupport( pTruth, nVars, i );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns support of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_TruthSupport( unsigned * pTruth, int nVars )
+{
+    int i, Support = 0;
+    for ( i = 0; i < nVars; i++ )
+        if ( Extra_TruthVarInSupport( pTruth, nVars, i ) )
+            Support |= (1 << i);
+    return Support;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes positive cofactor of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_TruthCofactor1( unsigned * pTruth, int nVars, int iVar )
+{
+    int nWords = Extra_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0xAAAAAAAA) | ((pTruth[i] & 0xAAAAAAAA) >> 1);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0xCCCCCCCC) | ((pTruth[i] & 0xCCCCCCCC) >> 2);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0xF0F0F0F0) | ((pTruth[i] & 0xF0F0F0F0) >> 4);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0xFF00FF00) | ((pTruth[i] & 0xFF00FF00) >> 8);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0xFFFF0000) | ((pTruth[i] & 0xFFFF0000) >> 16);
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                pTruth[i] = pTruth[Step+i];
+            pTruth += 2*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes negative cofactor of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_TruthCofactor0( unsigned * pTruth, int nVars, int iVar )
+{
+    int nWords = Extra_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0x55555555) | ((pTruth[i] & 0x55555555) << 1);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0x33333333) | ((pTruth[i] & 0x33333333) << 2);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0x0F0F0F0F) | ((pTruth[i] & 0x0F0F0F0F) << 4);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0x00FF00FF) | ((pTruth[i] & 0x00FF00FF) << 8);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & 0x0000FFFF) | ((pTruth[i] & 0x0000FFFF) << 16);
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+                pTruth[Step+i] = pTruth[i];
+            pTruth += 2*Step;
+        }
+        return;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Existentially quantifies the variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_TruthExist( unsigned * pTruth, int nVars, int iVar )
+{
+    int nWords = Extra_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] |=  ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] |=  ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] |=  ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] |=  ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] |=  ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16);
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+            {
+                pTruth[i]     |= pTruth[Step+i];
+                pTruth[Step+i] = pTruth[i];
+            }
+            pTruth += 2*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Existentially quantifies the variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_TruthForall( unsigned * pTruth, int nVars, int iVar )
+{
+    int nWords = Extra_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] &=  ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] &=  ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] &=  ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] &=  ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] &=  ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16);
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+            {
+                pTruth[i]     &= pTruth[Step+i];
+                pTruth[Step+i] = pTruth[i];
+            }
+            pTruth += 2*Step;
+        }
+        return;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes negative cofactor of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_TruthMux( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar )
+{
+    int nWords = Extra_TruthWordNum( nVars );
+    int i, k, Step;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pCof0[i] & 0x55555555) | (pCof1[i] & 0xAAAAAAAA);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pCof0[i] & 0x33333333) | (pCof1[i] & 0xCCCCCCCC);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pCof0[i] & 0x0F0F0F0F) | (pCof1[i] & 0xF0F0F0F0);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pCof0[i] & 0x00FF00FF) | (pCof1[i] & 0xFF00FF00);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (pCof0[i] & 0x0000FFFF) | (pCof1[i] & 0xFFFF0000);
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+            {
+                pOut[i]      = pCof0[i];
+                pOut[Step+i] = pCof1[Step+i];
+            }
+            pOut += 2*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks symmetry of two variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 )
+{
+    static unsigned uTemp0[16], uTemp1[16];
+    assert( nVars <= 9 );
+    // compute Cof01
+    Extra_TruthCopy( uTemp0, pTruth, nVars );
+    Extra_TruthCofactor0( uTemp0, nVars, iVar0 );
+    Extra_TruthCofactor1( uTemp0, nVars, iVar1 );
+    // compute Cof10
+    Extra_TruthCopy( uTemp1, pTruth, nVars );
+    Extra_TruthCofactor1( uTemp1, nVars, iVar0 );
+    Extra_TruthCofactor0( uTemp1, nVars, iVar1 );
+    // compare
+    return Extra_TruthIsEqual( uTemp0, uTemp1, nVars );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks antisymmetry of two variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_TruthVarsAntiSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 )
+{
+    static unsigned uTemp0[16], uTemp1[16];
+    assert( nVars <= 9 );
+    // compute Cof00
+    Extra_TruthCopy( uTemp0, pTruth, nVars );
+    Extra_TruthCofactor0( uTemp0, nVars, iVar0 );
+    Extra_TruthCofactor0( uTemp0, nVars, iVar1 );
+    // compute Cof11
+    Extra_TruthCopy( uTemp1, pTruth, nVars );
+    Extra_TruthCofactor1( uTemp1, nVars, iVar0 );
+    Extra_TruthCofactor1( uTemp1, nVars, iVar1 );
+    // compare
+    return Extra_TruthIsEqual( uTemp0, uTemp1, nVars );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Changes phase of the function w.r.t. one variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_TruthChangePhase( unsigned * pTruth, int nVars, int iVar )
+{
+    int nWords = Extra_TruthWordNum( nVars );
+    int i, k, Step;
+    unsigned Temp;
+
+    assert( iVar < nVars );
+    switch ( iVar )
+    {
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ((pTruth[i] & 0x55555555) << 1) | ((pTruth[i] & 0xAAAAAAAA) >> 1);
+        return;
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ((pTruth[i] & 0x33333333) << 2) | ((pTruth[i] & 0xCCCCCCCC) >> 2);
+        return;
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ((pTruth[i] & 0x0F0F0F0F) << 4) | ((pTruth[i] & 0xF0F0F0F0) >> 4);
+        return;
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ((pTruth[i] & 0x00FF00FF) << 8) | ((pTruth[i] & 0xFF00FF00) >> 8);
+        return;
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = ((pTruth[i] & 0x0000FFFF) << 16) | ((pTruth[i] & 0xFFFF0000) >> 16);
+        return;
+    default:
+        Step = (1 << (iVar - 5));
+        for ( k = 0; k < nWords; k += 2*Step )
+        {
+            for ( i = 0; i < Step; i++ )
+            {
+                Temp = pTruth[i];
+                pTruth[i] = pTruth[Step+i];
+                pTruth[Step+i] = Temp;
+            }
+            pTruth += 2*Step;
+        }
+        return;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes minimum overlap in supports of cofactors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin )
+{
+    static unsigned uCofactor[16];
+    int i, ValueCur, ValueMin, VarMin;
+    unsigned uSupp0, uSupp1;
+    int nVars0, nVars1;
+    assert( nVars <= 9 );
+    ValueMin = 32;
+    VarMin   = -1;
+    for ( i = 0; i < nVars; i++ )
+    {
+        // get negative cofactor
+        Extra_TruthCopy( uCofactor, pTruth, nVars );
+        Extra_TruthCofactor0( uCofactor, nVars, i );
+        uSupp0 = Extra_TruthSupport( uCofactor, nVars );
+        nVars0 = Extra_WordCountOnes( uSupp0 );
+//Extra_PrintBinary( stdout, &uSupp0, 8 ); printf( "\n" );
+        // get positive cofactor
+        Extra_TruthCopy( uCofactor, pTruth, nVars );
+        Extra_TruthCofactor1( uCofactor, nVars, i );
+        uSupp1 = Extra_TruthSupport( uCofactor, nVars );
+        nVars1 = Extra_WordCountOnes( uSupp1 );
+//Extra_PrintBinary( stdout, &uSupp1, 8 ); printf( "\n" );
+        // get the number of common vars
+        ValueCur = Extra_WordCountOnes( uSupp0 & uSupp1 );
+        if ( ValueMin > ValueCur && nVars0 <= 5 && nVars1 <= 5 )
+        {
+            ValueMin = ValueCur;
+            VarMin = i;
+        }
+        if ( ValueMin == 0 )
+            break;
+    }
+    if ( pVarMin )
+        *pVarMin = VarMin;
+    return ValueMin;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of 1's in each cofactor.]
+
+  Description [The resulting numbers are stored in the array of shorts, 
+  whose length is 2*nVars. The number of 1's is counted in a different
+  space than the original function. For example, if the function depends 
+  on k variables, the cofactors are assumed to depend on k-1 variables.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore )
+{
+    int nWords = Extra_TruthWordNum( nVars );
+    int i, k, Counter;
+    memset( pStore, 0, sizeof(short) * 2 * nVars );
+    if ( nVars <= 5 )
+    {
+        if ( nVars > 0 )
+        {
+            pStore[2*0+0] = Extra_WordCountOnes( pTruth[0] & 0x55555555 );
+            pStore[2*0+1] = Extra_WordCountOnes( pTruth[0] & 0xAAAAAAAA );
+        }
+        if ( nVars > 1 )
+        {
+            pStore[2*1+0] = Extra_WordCountOnes( pTruth[0] & 0x33333333 );
+            pStore[2*1+1] = Extra_WordCountOnes( pTruth[0] & 0xCCCCCCCC );
+        }
+        if ( nVars > 2 )
+        {
+            pStore[2*2+0] = Extra_WordCountOnes( pTruth[0] & 0x0F0F0F0F );
+            pStore[2*2+1] = Extra_WordCountOnes( pTruth[0] & 0xF0F0F0F0 );
+        }
+        if ( nVars > 3 )
+        {
+            pStore[2*3+0] = Extra_WordCountOnes( pTruth[0] & 0x00FF00FF );
+            pStore[2*3+1] = Extra_WordCountOnes( pTruth[0] & 0xFF00FF00 );
+        }
+        if ( nVars > 4 )
+        {
+            pStore[2*4+0] = Extra_WordCountOnes( pTruth[0] & 0x0000FFFF );
+            pStore[2*4+1] = Extra_WordCountOnes( pTruth[0] & 0xFFFF0000 );
+        }
+        return;
+    }
+    // nVars >= 6
+    // count 1's for all other variables
+    for ( k = 0; k < nWords; k++ )
+    {
+        Counter = Extra_WordCountOnes( pTruth[k] );
+        for ( i = 5; i < nVars; i++ )
+            if ( k & (1 << (i-5)) )
+                pStore[2*i+1] += Counter;
+            else
+                pStore[2*i+0] += Counter;
+    }
+    // count 1's for the first five variables
+    for ( k = 0; k < nWords/2; k++ )
+    {
+        pStore[2*0+0] += Extra_WordCountOnes( (pTruth[0] & 0x55555555) | ((pTruth[1] & 0x55555555) <<  1) );
+        pStore[2*0+1] += Extra_WordCountOnes( (pTruth[0] & 0xAAAAAAAA) | ((pTruth[1] & 0xAAAAAAAA) >>  1) );
+        pStore[2*1+0] += Extra_WordCountOnes( (pTruth[0] & 0x33333333) | ((pTruth[1] & 0x33333333) <<  2) );
+        pStore[2*1+1] += Extra_WordCountOnes( (pTruth[0] & 0xCCCCCCCC) | ((pTruth[1] & 0xCCCCCCCC) >>  2) );
+        pStore[2*2+0] += Extra_WordCountOnes( (pTruth[0] & 0x0F0F0F0F) | ((pTruth[1] & 0x0F0F0F0F) <<  4) );
+        pStore[2*2+1] += Extra_WordCountOnes( (pTruth[0] & 0xF0F0F0F0) | ((pTruth[1] & 0xF0F0F0F0) >>  4) );
+        pStore[2*3+0] += Extra_WordCountOnes( (pTruth[0] & 0x00FF00FF) | ((pTruth[1] & 0x00FF00FF) <<  8) );
+        pStore[2*3+1] += Extra_WordCountOnes( (pTruth[0] & 0xFF00FF00) | ((pTruth[1] & 0xFF00FF00) >>  8) );
+        pStore[2*4+0] += Extra_WordCountOnes( (pTruth[0] & 0x0000FFFF) | ((pTruth[1] & 0x0000FFFF) << 16) );
+        pStore[2*4+1] += Extra_WordCountOnes( (pTruth[0] & 0xFFFF0000) | ((pTruth[1] & 0xFFFF0000) >> 16) );
+        pTruth += 2;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Canonicize the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Extra_TruthHash( unsigned * pIn, int nWords )
+{
+    // The 1,024 smallest prime numbers used to compute the hash value
+    // http://www.math.utah.edu/~alfeld/math/primelist.html
+    static int HashPrimes[1024] = { 2, 3, 5, 
+    7, 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, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 
+    641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 
+    757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 
+    881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 
+    1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 
+    1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 
+    1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 
+    1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 
+    1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 
+    1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 
+    1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 
+    1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 
+    1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 
+    1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 
+    2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 
+    2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 
+    2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 
+    2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 
+    2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 
+    2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 
+    2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 
+    2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 
+    2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 
+    3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 
+    3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 
+    3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 
+    3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 
+    3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 
+    3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 
+    3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 
+    3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 
+    3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 
+    4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 
+    4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 
+    4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 
+    4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 
+    4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 
+    4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 
+    4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 
+    4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 
+    5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 
+    5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 
+    5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 
+    5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 
+    5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 
+    5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 
+    5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 
+    5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 
+    6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 
+    6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 
+    6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 
+    6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 
+    6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 
+    6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 
+    6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 
+    6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 
+    6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 
+    7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 
+    7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 
+    7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 
+    7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 
+    7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 
+    7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 
+    7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 
+    8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, 
+    8147, 8161 };
+    int i;
+    unsigned uHashKey;
+    assert( nWords <= 1024 );
+    uHashKey = 0;
+    for ( i = 0; i < nWords; i++ )
+        uHashKey ^= HashPrimes[i] * pIn[i];
+    return uHashKey;
+}
+
+ 
+/**Function*************************************************************
+
+  Synopsis    [Canonicize the truth table.]
+
+  Description [Returns the phase. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Extra_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore )
+{
+    unsigned * pIn = pInOut, * pOut = pAux, * pTemp;
+    int nWords = Extra_TruthWordNum( nVars );
+    int i, Temp, fChange, Counter, nOnes;//, k, j, w, Limit;
+    unsigned uCanonPhase;
+
+    // canonicize output
+    uCanonPhase = 0;
+    nOnes = Extra_TruthCountOnes(pIn, nVars);
+    if ( (nOnes > nWords * 16) || ((nOnes == nWords * 16) && (pIn[0] & 1)) )
+    {
+        uCanonPhase |= (1 << nVars);
+        Extra_TruthNot( pIn, pIn, nVars );
+    }
+
+    // collect the minterm counts
+    Extra_TruthCountOnesInCofs( pIn, nVars, pStore );
+
+    // canonicize phase
+    for ( i = 0; i < nVars; i++ )
+    {
+        if ( pStore[2*i+0] <= pStore[2*i+1] )
+            continue;
+        uCanonPhase |= (1 << i);
+        Temp = pStore[2*i+0];
+        pStore[2*i+0] = pStore[2*i+1];
+        pStore[2*i+1] = Temp;
+        Extra_TruthChangePhase( pIn, nVars, i );
+    }
+
+//    Extra_PrintHexadecimal( stdout, pIn, nVars );
+//    printf( "\n" );
+
+    // permute
+    Counter = 0;
+    do {
+        fChange = 0;
+        for ( i = 0; i < nVars-1; i++ )
+        {
+            if ( pStore[2*i] <= pStore[2*(i+1)] )
+                continue;
+            Counter++;
+            fChange = 1;
+
+            Temp = pCanonPerm[i];
+            pCanonPerm[i] = pCanonPerm[i+1];
+            pCanonPerm[i+1] = Temp;
+
+            Temp = pStore[2*i];
+            pStore[2*i] = pStore[2*(i+1)];
+            pStore[2*(i+1)] = Temp;
+
+            Temp = pStore[2*i+1];
+            pStore[2*i+1] = pStore[2*(i+1)+1];
+            pStore[2*(i+1)+1] = Temp;
+
+            Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, i );
+            pTemp = pIn; pIn = pOut; pOut = pTemp;
+        }
+    } while ( fChange );
+
+/*
+    Extra_PrintBinary( stdout, &uCanonPhase, nVars+1 ); printf( " : " );
+    for ( i = 0; i < nVars; i++ )
+        printf( "%d=%d/%d  ", pCanonPerm[i], pStore[2*i], pStore[2*i+1] );
+    printf( "  C = %d\n", Counter );
+    Extra_PrintHexadecimal( stdout, pIn, nVars );
+    printf( "\n" );
+*/
+
+/*
+    // process symmetric variable groups
+    uSymms = 0;
+    for ( i = 0; i < nVars-1; i++ )
+    {
+        if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric
+            continue;
+        if ( pStore[2*i] != pStore[2*i+1] )
+            continue;
+        if ( Extra_TruthVarsSymm( pIn, nVars, i, i+1 ) )
+            continue;
+        if ( Extra_TruthVarsAntiSymm( pIn, nVars, i, i+1 ) )
+            Extra_TruthChangePhase( pIn, nVars, i+1 );
+    }
+*/
+
+/*
+    // process symmetric variable groups
+    uSymms = 0;
+    for ( i = 0; i < nVars-1; i++ )
+    {
+        if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric
+            continue;
+        // i and i+1 can be symmetric
+        // find the end of this group
+        for ( k = i+1; k < nVars; k++ )
+            if ( pStore[2*i] != pStore[2*k] ) 
+                break;
+        Limit = k;
+        assert( i < Limit-1 );
+        // go through the variables in this group
+        for ( j = i + 1; j < Limit; j++ )
+        {
+            // check symmetry
+            if ( Extra_TruthVarsSymm( pIn, nVars, i, j ) )
+            {
+                uSymms |= (1 << j);
+                continue;
+            }
+            // they are phase-unknown
+            if ( pStore[2*i] == pStore[2*i+1] ) 
+            {
+                if ( Extra_TruthVarsAntiSymm( pIn, nVars, i, j ) )
+                {
+                    Extra_TruthChangePhase( pIn, nVars, j );
+                    uCanonPhase ^= (1 << j);
+                    uSymms |= (1 << j);
+                    continue;
+                }
+            }
+
+            // they are not symmetric - move j as far as it goes in the group
+            for ( k = j; k < Limit-1; k++ )
+            {
+                Counter++;
+
+                Temp = pCanonPerm[k];
+                pCanonPerm[k] = pCanonPerm[k+1];
+                pCanonPerm[k+1] = Temp;
+
+                assert( pStore[2*k] == pStore[2*(k+1)] );
+                Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, k );
+                pTemp = pIn; pIn = pOut; pOut = pTemp;
+            }
+            Limit--;
+            j--;
+        }
+        i = Limit - 1;
+    }
+*/
+
+    // swap if it was moved an even number of times
+    if ( Counter & 1 )
+        Extra_TruthCopy( pOut, pIn, nVars );
+    return uCanonPhase;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraUtilUtil.c b/abc-build/src/misc/extra/extraUtilUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraUtilUtil.c
@@ -0,0 +1,411 @@
+/**CFile****************************************************************
+
+  FileName    [extraUtilUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [extra]
+
+  Synopsis    [Old SIS utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: extraUtilUtil.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include "extra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define EXTRA_RLIMIT_DATA_DEFAULT 67108864  // assume 64MB by default 
+
+/*  File   : getopt.c
+ *  Author : Henry Spencer, University of Toronto
+ *  Updated: 28 April 1984
+ *
+ *  Changes: (R Rudell)
+ *  changed index() to strchr();
+ *  added getopt_reset() to reset the getopt argument parsing
+ *
+ *  Purpose: get option letter from argv.
+ */
+
+const char * globalUtilOptarg;        // Global argument pointer (util_optarg)
+int    globalUtilOptind = 0;    // Global argv index (util_optind)
+
+static const char *pScanStr;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [getSoftDataLimit()]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_GetSoftDataLimit()
+{
+    return EXTRA_RLIMIT_DATA_DEFAULT;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [util_getopt_reset()]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_UtilGetoptReset()
+{
+    globalUtilOptarg = 0;
+    globalUtilOptind = 0;
+    pScanStr = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [util_getopt()]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_UtilGetopt( int argc, char *argv[], const char *optstring )
+{
+    register int c;
+    register const char *place;
+
+    globalUtilOptarg = NULL;
+
+    if (pScanStr == NULL || *pScanStr == '\0') {
+    if (globalUtilOptind == 0) globalUtilOptind++;
+    if (globalUtilOptind >= argc) return EOF;
+    place = argv[globalUtilOptind];
+    if (place[0] != '-' || place[1] == '\0') return EOF;
+    globalUtilOptind++;
+    if (place[1] == '-' && place[2] == '\0') return EOF;
+    pScanStr = place+1;
+    }
+
+    c = *pScanStr++;
+    place = strchr(optstring, c);
+    if (place == NULL || c == ':') {
+    (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
+    return '?';
+    }
+    if (*++place == ':') {
+    if (*pScanStr != '\0') {
+        globalUtilOptarg = pScanStr;
+        pScanStr = NULL;
+    } else {
+        if (globalUtilOptind >= argc) {
+        (void) fprintf(stderr, "%s: %c requires an argument\n", 
+            argv[0], c);
+        return '?';
+        }
+        globalUtilOptarg = argv[globalUtilOptind];
+        globalUtilOptind++;
+    }
+    }
+    return c;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [util_print_time()]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_UtilPrintTime( long t )
+{
+    static char s[40];
+
+    (void) sprintf(s, "%ld.%02ld sec", t/1000, (t%1000)/10);
+    return s;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Extra_UtilStrsav()]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_UtilStrsav( const char *s )
+{
+    if(s == NULL) {  /* added 7/95, for robustness */
+       return NULL;
+    }
+    else {
+       return strcpy(ABC_ALLOC(char, strlen(s)+1), s);
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [util_tilde_expand()]
+
+  Description [The code contributed by Niklas Sorensson.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_UtilTildeExpand( char *fname )
+{
+    return Extra_UtilStrsav( fname );
+/*
+    int         n_tildes = 0;
+    const char* home;
+    char*       expanded;
+    int         length;
+    int         i, j, k;
+
+    for (i = 0; i < (int)strlen(fname); i++)
+        if (fname[i] == '~') n_tildes++;
+
+    home     = getenv("HOME");
+    length   = n_tildes * strlen(home) + strlen(fname);
+    expanded = ABC_ALLOC(char, length + 1);
+
+    j = 0;
+    for (i = 0; i < (int)strlen(fname); i++){
+        if (fname[i] == '~'){
+            for (k = 0; k < (int)strlen(home); k++)
+                expanded[j++] = home[k];
+        }else
+            expanded[j++] = fname[i];
+    }
+
+    expanded[j] = '\0';
+    return expanded; 
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [check_file()]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_UtilCheckFile(char *filename, const char *mode)
+{
+    FILE *fp;
+    int got_file;
+
+    if (strcmp(mode, "x") == 0) {
+	mode = "r";
+    }
+    fp = fopen(filename, mode);
+    got_file = (fp != 0);
+    if (fp != 0) {
+	(void) fclose(fp);
+    }
+    return got_file;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [util_file_search()]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Extra_UtilFileSearch(char *file, char *path, char *mode)
+//char *file;			// file we're looking for 
+//char *path;			// search path, colon separated 
+//char *mode;			// "r", "w", or "x" 
+{
+    int quit;
+    char *buffer, *filename, *save_path, *cp;
+
+    if (path == 0 || strcmp(path, "") == 0) {
+	path = ".";		/* just look in the current directory */
+    }
+
+    save_path = path = Extra_UtilStrsav(path);
+    quit = 0;
+    do {
+	cp = strchr(path, ':');
+	if (cp != 0) {
+	    *cp = '\0';
+	} else {
+	    quit = 1;
+	}
+
+	/* cons up the filename out of the path and file name */
+	if (strcmp(path, ".") == 0) {
+	    buffer = Extra_UtilStrsav(file);
+	} else {
+	    buffer = ABC_ALLOC(char, strlen(path) + strlen(file) + 4);
+	    (void) sprintf(buffer, "%s/%s", path, file);
+	}
+	filename = Extra_UtilTildeExpand(buffer);
+	ABC_FREE(buffer);
+
+	/* see if we can access it */
+	if (Extra_UtilCheckFile(filename, mode)) {
+	    ABC_FREE(save_path);
+	    return filename;
+	}
+	ABC_FREE(filename);
+	path = ++cp;
+    } while (! quit); 
+
+    ABC_FREE(save_path);
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [MMout_of_memory()]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/* MMout_of_memory -- out of memory for lazy people, flush and exit */
+void Extra_UtilMMout_Of_Memory( long size ) 
+{
+    (void) fflush(stdout);
+    (void) fprintf(stderr, "\nout of memory allocating %u bytes\n",
+		   (unsigned) size);
+	assert( 0 );
+    exit(1);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [MMoutOfMemory()]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void (*Extra_UtilMMoutOfMemory)( long size ) = (void (*)( long size ))Extra_UtilMMout_Of_Memory;
+
+
+/**Function*************************************************************
+
+  Synopsis    [util_cpu_time()]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+abctime Extra_CpuTime()
+{
+    return Abc_Clock();
+}
+
+/**Function*************************************************************
+
+  Synopsis    [util_cpu_time()]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+#if defined(NT) || defined(NT64) || defined(WIN32)
+double Extra_CpuTimeDouble()
+{
+    return 1.0*Abc_Clock()/CLOCKS_PER_SEC;
+}
+#else
+
+ABC_NAMESPACE_IMPL_END
+
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <unistd.h>
+
+ABC_NAMESPACE_IMPL_START
+
+double Extra_CpuTimeDouble()
+{
+    struct rusage ru;
+    getrusage(RUSAGE_SELF, &ru);
+    return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; 
+}
+#endif
+
+/**Function*************************************************************
+
+  Synopsis    [Testing memory leaks.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_MemTest()
+{
+//    ABC_ALLOC( char, 1002 );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/extraZddTrunc.c b/abc-build/src/misc/extra/extraZddTrunc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/extraZddTrunc.c
@@ -0,0 +1,338 @@
+/**CFile****************************************************************
+
+  FileName    [extraZddTrunc.c]
+
+  PackageName [extra]
+
+  Synopsis    [Procedure to truncate a ZDD using variable probabilities.]
+
+  Author      [Alan Mishchenko]
+
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - September 1, 2003.]
+
+  Revision    [$Id: extraZddTrunc.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/st/st.h"
+#include "bdd/cudd/cuddInt.h"
+
+#ifdef _WIN32
+#define inline __inline // compatible with MS VS 6.0
+#endif
+
+ABC_NAMESPACE_IMPL_START
+
+
+#define TEST_VAR_MAX 10
+#define TEST_SET_MAX 10
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+// dynamic vector of intergers
+typedef struct Vec_Int_t_       Vec_Int_t;
+struct Vec_Int_t_ 
+{
+    int              nCap;
+    int              nSize;
+    int *            pArray;
+};
+static inline Vec_Int_t * Vec_IntAlloc( int nCap )
+{
+    Vec_Int_t * p;
+    p = ABC_ALLOC( Vec_Int_t, 1 );
+    if ( nCap > 0 && nCap < 16 )
+        nCap = 16;
+    p->nSize  = 0;
+    p->nCap   = nCap;
+    p->pArray = p->nCap? ABC_ALLOC( int, p->nCap ) : NULL;
+    return p;
+}
+static inline void Vec_IntFree( Vec_Int_t * p )
+{
+    ABC_FREE( p->pArray );
+    ABC_FREE( p );
+}
+static inline int * Vec_IntReleaseArray( Vec_Int_t * p )
+{
+    int * pArray = p->pArray;
+    p->nCap = 0;
+    p->nSize = 0;
+    p->pArray = NULL;
+    return pArray;
+}
+static inline int Vec_IntAddToEntry( Vec_Int_t * p, int i, int Addition )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray[i] += Addition;
+}
+static inline void Vec_IntGrow( Vec_Int_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pArray = ABC_REALLOC( int, p->pArray, nCapMin ); 
+    assert( p->pArray );
+    p->nCap   = nCapMin;
+}
+static inline int Vec_IntPop( Vec_Int_t * p )
+{
+    assert( p->nSize > 0 );
+    return p->pArray[--p->nSize];
+}
+static inline void Vec_IntPush( Vec_Int_t * p, int Entry )
+{
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Vec_IntGrow( p, 16 );
+        else
+            Vec_IntGrow( p, 2 * p->nCap );
+    }
+    p->pArray[p->nSize++] = Entry;
+}
+static inline void Vec_IntAppend( Vec_Int_t * vVec1, Vec_Int_t * vVec2 )
+{
+    int i;
+    for ( i = 0; i < vVec2->nSize; i++ )
+        Vec_IntPush( vVec1, vVec2->pArray[i] );
+}
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Compute the set of subsets whose probability is more than ProbLimit.]
+
+  Description [The resulting array has the following form:  The first integer entry 
+  is the number of resulting subsets.  The following integer entries in the array
+  contain as many subsets. Each subset is an array of integers followed by -1. 
+  See how subsets are printed in the included test procedure below.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Extra_zddTruncate_rec(
+  DdManager * dd, 
+  DdNode * zFunc,       // zFunc is the ZDD to be truncated
+  double * pVarProbs,    // pVarProbs is probabilities of each variable (should have at least dd->sizeZ entries)
+  double ProbLimit,      // ProbLimit is the limit on the probabilities (only those more than this will be collected)
+  double ProbThis,       // current path probability
+  Vec_Int_t * vSubset,  // current subset under construction
+  Vec_Int_t * vResult ) // resulting subsets to be returned to the user
+{
+    // quit if probability of the path is less then the limit
+    if ( ProbThis < ProbLimit )
+        return;
+    // quit if there is no subsets
+	if ( zFunc == Cudd_ReadZero(dd) ) 
+		return;
+    // quit and save a new subset if there is one
+	if ( zFunc == Cudd_ReadOne(dd) ) 
+    {
+        Vec_IntAddToEntry( vResult, 0, 1 );
+        Vec_IntAppend( vResult, vSubset );
+        Vec_IntPush( vResult, -1 );
+		return;
+    }
+    // call recursively for the set without the given variable
+    Extra_zddTruncate_rec( dd, cuddE(zFunc), pVarProbs, ProbLimit, ProbThis, vSubset, vResult );
+    // call recursively for the set with the given variable
+    Vec_IntPush( vSubset, Cudd_NodeReadIndex(zFunc) );
+    Extra_zddTruncate_rec( dd, cuddT(zFunc), pVarProbs, ProbLimit, ProbThis * pVarProbs[Cudd_NodeReadIndex(zFunc)], vSubset, vResult );
+    Vec_IntPop( vSubset );
+}
+int * Extra_zddTruncate( 
+  DdManager * dd, 
+  DdNode * zFunc,       // zFunc is the ZDD to be truncated
+  double * pVarProbs,    // pVarProbs is probabilities of each variable (should have at least dd->sizeZ entries)
+  double ProbLimit )     // ProbLimit is the limit on the probabilities (only those more than this will be collected)
+{
+    Vec_Int_t * vSubset, * vResult;
+    int i, sizeZ = Cudd_ReadZddSize(dd);
+    int * pResult;
+    // check that probabilities are reasonable
+    assert( ProbLimit > 0 && ProbLimit <= 1 );
+    for ( i = 0; i < sizeZ; i++ )
+        assert( pVarProbs[i] > 0 && pVarProbs[i] <= 1 );
+    // enumerate assignments satisfying the probability limit
+    vSubset = Vec_IntAlloc( sizeZ );
+    vResult = Vec_IntAlloc( 10 * sizeZ );
+    Vec_IntPush( vResult, 0 );
+    Extra_zddTruncate_rec( dd, zFunc, pVarProbs, ProbLimit, 1, vSubset, vResult );
+    Vec_IntFree( vSubset );
+    pResult = Vec_IntReleaseArray( vResult );
+    Vec_IntFree( vResult );
+    return pResult;
+} // end of Extra_zddTruncate 
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the combination composed of a single ZDD variable.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Extra_zddVariable( DdManager * dd, int iVar )
+{
+    DdNode * zRes;
+    do {
+        dd->reordered = 0;
+        zRes = cuddZddGetNode( dd, iVar, Cudd_ReadOne(dd), Cudd_ReadZero(dd) ); 
+    } while (dd->reordered == 1);
+    return zRes;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates ZDD representing a given set of subsets.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Extra_zddCreateSubsets(
+  DdManager * dd,
+  int pSubsets[][TEST_VAR_MAX+1],
+  int nSubsets )
+{
+    int i, k;
+    DdNode * zOne, * zVar, * zRes, * zTemp;
+    zRes = Cudd_ReadZero(dd); Cudd_Ref( zRes );
+    for ( i = 0; i < nSubsets; i++ )
+    {
+        zOne = Cudd_ReadOne(dd); Cudd_Ref( zOne );
+        for ( k = 0; pSubsets[i][k] != -1; k++ )
+        {
+            assert( pSubsets[i][k] < TEST_VAR_MAX );
+            zVar = Extra_zddVariable( dd, pSubsets[i][k] );
+            zOne = Cudd_zddUnateProduct( dd, zTemp = zOne, zVar ); Cudd_Ref( zOne );
+            Cudd_RecursiveDerefZdd( dd, zTemp );
+        }
+        zRes = Cudd_zddUnion( dd, zRes, zOne ); Cudd_Ref( zRes );
+        Cudd_RecursiveDerefZdd( dd, zOne );
+    }
+    Cudd_Deref( zRes );
+    return zRes;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a set of subsets represented using as an array.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Extra_zddPrintSubsets( int * pSubsets )
+{
+    int i, k, Counter = 0;
+    printf( "The set contains %d subsets:\n", pSubsets[0] );
+    for ( i = k = 0; i < pSubsets[0]; i++ )
+    {
+        printf( "Subset %3d : {", Counter );
+        for ( k++; pSubsets[k] != -1; k++ )
+            printf( " %d", pSubsets[k] );
+        printf( " }\n" );
+        Counter++;
+    }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Testbench for the above truncation procedure.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Extra_zddTruncateTest()
+{
+    // input data
+    int nSubsets = 5;
+    int pSubsets[TEST_SET_MAX][TEST_VAR_MAX+1] = { {0, 3, 5, -1}, {1, 2, 3, 6, 9, -1}, {1, 5, 7, 8, -1}, {2, 4, -1}, {0, 5, 6, 9, -1} };
+    // varible probabilities
+    double pVarProbs[TEST_VAR_MAX] = { 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 };
+    double ProbLimit = 0.001;
+    // output data
+    int * pOutput;
+    // start the manager and create ZDD representing the input subsets
+    DdManager * dd = Cudd_Init( 0, TEST_VAR_MAX, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS , 0 );
+    DdNode * zFunc = Extra_zddCreateSubsets( dd, pSubsets, nSubsets );  Cudd_Ref( zFunc );
+    assert( nSubsets <= TEST_SET_MAX );
+    // print the input ZDD
+    printf( "The initial ZDD representing %d subsets:\n", nSubsets );
+    Cudd_zddPrintMinterm( dd, zFunc );
+    // compute the result of truncation
+    pOutput = Extra_zddTruncate( dd, zFunc, pVarProbs, ProbLimit );
+    // print the resulting ZDD
+    printf( "The resulting ZDD representing %d subsets:\n", pOutput[0] );
+    // print the resulting subsets
+    Extra_zddPrintSubsets( pOutput );
+    // cleanup
+    ABC_FREE( pOutput );
+    Cudd_RecursiveDerefZdd( dd, zFunc );
+    Cudd_Quit( dd );
+} 
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                           END OF FILE                            ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/extra/module.make b/abc-build/src/misc/extra/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/extra/module.make
@@ -0,0 +1,22 @@
+SRC +=	src/misc/extra/extraBddAuto.c \
+	src/misc/extra/extraBddCas.c \
+	src/misc/extra/extraBddImage.c \
+	src/misc/extra/extraBddKmap.c \
+	src/misc/extra/extraBddMisc.c \
+	src/misc/extra/extraBddSymm.c \
+	src/misc/extra/extraBddTime.c \
+	src/misc/extra/extraBddUnate.c \
+	src/misc/extra/extraUtilBitMatrix.c \
+	src/misc/extra/extraUtilCanon.c \
+	src/misc/extra/extraUtilCube.c \
+	src/misc/extra/extraUtilDsd.c \
+	src/misc/extra/extraUtilEnum.c \
+	src/misc/extra/extraUtilFile.c \
+	src/misc/extra/extraUtilMemory.c \
+	src/misc/extra/extraUtilMisc.c \
+	src/misc/extra/extraUtilPerm.c \
+	src/misc/extra/extraUtilProgress.c \
+	src/misc/extra/extraUtilReader.c \
+	src/misc/extra/extraUtilSupp.c \
+	src/misc/extra/extraUtilTruth.c \
+	src/misc/extra/extraUtilUtil.c
diff --git a/abc-build/src/misc/hash/hash.h b/abc-build/src/misc/hash/hash.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/hash/hash.h
@@ -0,0 +1,70 @@
+/**CFile****************************************************************
+
+  FileName    [hash.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Hash map.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Aaron P. Hurst]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 16, 2005.]
+
+  Revision    [$Id: vec.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__hash__hash_h
+#define ABC__misc__hash__hash_h
+
+
+#ifdef _WIN32
+#define inline __inline // compatible with MS VS 6.0
+#endif
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "misc/util/abc_global.h"
+
+#include "hashInt.h"
+#include "hashFlt.h"
+#include "hashPtr.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+int Hash_DefaultHashFunc(int key, int nBins) {
+  return Abc_AbsInt( ( (key+11)*(key)*7+3 ) % nBins );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
diff --git a/abc-build/src/misc/hash/hashFlt.h b/abc-build/src/misc/hash/hashFlt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/hash/hashFlt.h
@@ -0,0 +1,339 @@
+/**CFile****************************************************************
+
+  FileName    [hashFlt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Hash maps.]
+
+  Synopsis    [Hash maps.]
+
+  Author      [Aaron P. Hurst]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 16, 2006.]
+
+  Revision    [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__hash__hashFlt_h
+#define ABC__misc__hash__hashFlt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "misc/extra/extra.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+extern int Hash_DefaultHashFunc(int key, int nBins);
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Hash_Flt_t_       Hash_Flt_t;
+typedef struct Hash_Flt_Entry_t_ Hash_Flt_Entry_t;
+
+struct Hash_Flt_Entry_t_
+{
+  int                              key;
+  float                            data;
+  struct Hash_Flt_Entry_t_ *       pNext;
+};
+
+struct Hash_Flt_t_ 
+{
+  int                             nSize;
+  int                             nBins;
+  int (* fHash)(int key, int nBins);
+  Hash_Flt_Entry_t **             pArray;
+};
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define Hash_FltForEachEntry( pHash, pEntry, bin)   \
+  for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \
+    if (pEntry)
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a hash map with the given number of bins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Hash_Flt_t * Hash_FltAlloc( int nBins )
+{
+  Hash_Flt_t * p;
+  int i;
+  assert(nBins > 0);
+  p = ABC_ALLOC( Hash_Flt_t, 1);
+  p->nBins = nBins;
+  p->fHash = Hash_DefaultHashFunc;
+  p->nSize  = 0;
+  p->pArray = ABC_ALLOC( Hash_Flt_Entry_t *, nBins );
+  for(i=0; i<nBins; i++)
+    p->pArray[i] = NULL;
+
+  return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if a key already exists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Hash_FltExists( Hash_Flt_t *p, int key )
+{
+  int bin;
+  Hash_Flt_Entry_t *pEntry, **pLast;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pLast = &(p->pArray[bin]);
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if (pEntry->key == key) {
+      return 1;
+    }
+    pLast = &(pEntry->pNext);
+    pEntry = pEntry->pNext;
+  }
+
+  return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds or creates an entry with a key and writes value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Hash_FltWriteEntry( Hash_Flt_t *p, int key, float data )
+{
+  int bin;
+  Hash_Flt_Entry_t *pEntry, **pLast;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pLast = &(p->pArray[bin]);
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if (pEntry->key == key) {
+      pEntry->data = data;
+      return;
+    }
+    pLast = &(pEntry->pNext);
+    pEntry = pEntry->pNext;
+  }
+
+  // this key does not currently exist
+  // create a new entry and add to bin
+  p->nSize++;
+  (*pLast) = pEntry = ABC_ALLOC( Hash_Flt_Entry_t, 1 );
+  pEntry->pNext = NULL;
+  pEntry->key = key;
+  pEntry->data = data;
+
+  return;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds or creates an entry with a key.]
+
+  Description [fCreate specifies whether new entries should be created.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline float Hash_FltEntry( Hash_Flt_t *p, int key, int fCreate )
+{
+  int bin;
+  Hash_Flt_Entry_t *pEntry, **pLast;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pLast = &(p->pArray[bin]);
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if (pEntry->key == key)
+      return pEntry->data;
+    pLast = &(pEntry->pNext);
+    pEntry = pEntry->pNext;
+  }
+
+  // this key does not currently exist
+  if (fCreate) {
+    // create a new entry and add to bin
+    p->nSize++;
+    (*pLast) = pEntry = ABC_ALLOC( Hash_Flt_Entry_t, 1 );
+    pEntry->pNext = NULL;
+    pEntry->key = key;
+    pEntry->data = 0.0;
+    return pEntry->data;
+  }
+
+  return 0.0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds or creates an entry with a key and returns the pointer to it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline float* Hash_FltEntryPtr( Hash_Flt_t *p, int key )
+{
+  int bin;
+  Hash_Flt_Entry_t *pEntry, **pLast;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pLast = &(p->pArray[bin]);
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if (pEntry->key == key)
+      return &(pEntry->data);
+    pLast = &(pEntry->pNext);
+    pEntry = pEntry->pNext;
+  }
+
+  // this key does not currently exist
+  // create a new entry and add to bin
+  p->nSize++;
+  (*pLast) = pEntry = ABC_ALLOC( Hash_Flt_Entry_t, 1 );
+  pEntry->pNext = NULL;
+  pEntry->key = key;
+  pEntry->data = 0.0;
+
+  return &(pEntry->data);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes an entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Hash_FltRemove( Hash_Flt_t *p, int key )
+{
+  int    bin;
+  Hash_Flt_Entry_t *pEntry, **pLast;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pLast = &(p->pArray[bin]);
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if (pEntry->key == key) {
+      p->nSize--;
+      *pLast = pEntry->pNext;
+      ABC_FREE( pEntry );
+      return;
+    }
+    pLast = &(pEntry->pNext);
+    pEntry = pEntry->pNext;
+  }
+    
+  // could not find key
+  return;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the hash.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Hash_FltFree( Hash_Flt_t *p ) {
+  int bin;
+  Hash_Flt_Entry_t *pEntry, *pTemp;
+
+  // free bins
+  for(bin = 0; bin < p->nBins; bin++) {
+    pEntry = p->pArray[bin];
+    while(pEntry) {
+      pTemp = pEntry;
+      pEntry = pEntry->pNext;
+      ABC_FREE( pTemp );
+    }
+  }
+ 
+  // free hash
+  ABC_FREE( p->pArray );
+  ABC_FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/misc/hash/hashGen.h b/abc-build/src/misc/hash/hashGen.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/hash/hashGen.h
@@ -0,0 +1,367 @@
+/**CFile****************************************************************
+
+  FileName    [vecGen.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Hash maps.]
+
+  Synopsis    [Hash maps.]
+
+  Author      [Aaron P. Hurst, Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Jan 26, 2011.]
+
+  Revision    [$Id: vecGen.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__hash__hashGen_h
+#define ABC__misc__hash__hashGen_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "misc/extra/extra.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Hash_Gen_t_       Hash_Gen_t;
+typedef struct Hash_Gen_Entry_t_ Hash_Gen_Entry_t;
+
+struct Hash_Gen_Entry_t_
+{
+  char *                          key;
+  void *                          data;
+  struct Hash_Gen_Entry_t_ *     pNext;
+};
+
+typedef int (*Hash_GenHashFunction_t)(void* key, int nBins);
+typedef int (*Hash_GenCompFunction_t)(void* key, void* data);
+
+struct Hash_Gen_t_ 
+{
+  int                             nSize;
+  int                             nBins;
+  Hash_GenHashFunction_t          fHash;
+  Hash_GenCompFunction_t          fComp;
+  int                             fFreeKey;
+  Hash_Gen_Entry_t **             pArray;
+};
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define Hash_GenForEachEntry( pHash, pEntry, bin )   \
+  for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \
+    if (pEntry)
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Default hash function for strings.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Hash_DefaultHashFuncStr( void * key, int nBins )
+{
+    const char* p = (const char*)key;
+    int h=0;
+
+    for( ; *p ; ++p )
+        h += h*5 + *p;
+  
+    return (unsigned)h % nBins; 
+}
+
+static int Hash_DefaultCmpFuncStr( void * key1, void * key2 )
+{
+    return strcmp((const char*)key1, (const char*) key2);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Default hash function for (long) integers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Hash_DefaultHashFuncInt( void * key, int nBins )
+{
+    return (long)key % nBins;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Default comparison function for (long) integers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Hash_DefaultCmpFuncInt( void * key1, void* key2 )
+{
+    return (long)key1 - (long)key2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a hash map with the given number of bins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Hash_Gen_t * Hash_GenAlloc( 
+  int nBins, 
+  int (*Hash_FuncHash)(void *, int),
+  int (*Hash_FuncComp)(void *, void *),
+  int fFreeKey)
+{
+  Hash_Gen_t * p;
+  assert(nBins > 0);
+  p = ABC_CALLOC( Hash_Gen_t, 1 );
+  p->nBins  = nBins;
+  p->fHash  = Hash_FuncHash? Hash_FuncHash : (int (*)(void *, int))Hash_DefaultHashFuncStr;
+  p->fComp  = Hash_FuncComp? Hash_FuncComp : (int (*)(void *, void *))Hash_DefaultCmpFuncStr;
+  p->fFreeKey = fFreeKey;
+  p->nSize  = 0;
+  p->pArray = ABC_CALLOC( Hash_Gen_Entry_t *, nBins );
+  return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if a key already exists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Hash_GenExists( Hash_Gen_t *p, void * key )
+{
+  int bin;
+  Hash_Gen_Entry_t *pEntry;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if ( !p->fComp(pEntry->key,key) ) {
+      return 1;
+    }
+    pEntry = pEntry->pNext;
+  }
+
+  return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds or creates an entry with a key and writes value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Hash_GenWriteEntry( Hash_Gen_t *p, void * key, void * data )
+{
+  int bin;
+  Hash_Gen_Entry_t *pEntry, **pLast;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pLast = &(p->pArray[bin]);
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if ( !p->fComp(pEntry->key,key) ) {
+      pEntry->data = data;
+      return;
+    }
+    pLast = &(pEntry->pNext);
+    pEntry = pEntry->pNext;
+  }
+
+  // this key does not currently exist
+  // create a new entry and add to bin
+  p->nSize++;
+  (*pLast) = pEntry = ABC_ALLOC( Hash_Gen_Entry_t, 1 );
+  pEntry->pNext = NULL;
+  pEntry->key  = (char *)key;
+  pEntry->data = data;
+
+  return;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds or creates an entry with a key.]
+
+  Description [fCreate specifies whether a new entry should be created.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Hash_Gen_Entry_t * Hash_GenEntry( Hash_Gen_t *p, void * key, int fCreate )
+{
+  int bin;
+  Hash_Gen_Entry_t *pEntry, **pLast;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pLast = &(p->pArray[bin]);
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if ( !p->fComp(pEntry->key,key) )
+      return pEntry;
+    pLast = &(pEntry->pNext);
+    pEntry = pEntry->pNext;
+  }
+
+  // this key does not currently exist
+  if (fCreate) {
+    // create a new entry and add to bin
+    p->nSize++;
+    (*pLast) = pEntry = ABC_ALLOC( Hash_Gen_Entry_t, 1 );
+    pEntry->pNext = NULL;
+    pEntry->key  = (char *)key;
+    pEntry->data = NULL;
+    return pEntry;
+  }
+
+  return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes an entry.]
+
+  Description [Returns data, if there was any.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void* Hash_GenRemove( Hash_Gen_t *p, void * key )
+{
+  int    bin;
+  void * data;
+  Hash_Gen_Entry_t *pEntry, **pLast;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pLast = &(p->pArray[bin]);
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if ( !p->fComp(pEntry->key,key) ) {
+      p->nSize--;
+      data = pEntry->data;
+      *pLast = pEntry->pNext;
+      if (p->fFreeKey)
+        ABC_FREE(pEntry->key);
+      ABC_FREE(pEntry);
+      return data;
+    }
+    pLast = &(pEntry->pNext);
+    pEntry = pEntry->pNext;
+  }
+    
+  // could not find key
+  return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the hash.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Hash_GenFree( Hash_Gen_t *p ) 
+{
+  int bin;
+  Hash_Gen_Entry_t *pEntry, *pTemp;
+
+  // free bins
+  for(bin = 0; bin < p->nBins; bin++) {
+    pEntry = p->pArray[bin];
+    while(pEntry) {
+      pTemp = pEntry;
+      if( p->fFreeKey )
+        ABC_FREE(pTemp->key);
+      pEntry = pEntry->pNext;
+      ABC_FREE( pTemp );
+    }
+  }
+ 
+  // free hash
+  ABC_FREE( p->pArray );
+  ABC_FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/misc/hash/hashInt.h b/abc-build/src/misc/hash/hashInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/hash/hashInt.h
@@ -0,0 +1,302 @@
+/**CFile****************************************************************
+
+  FileName    [hashInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Hash maps.]
+
+  Synopsis    [Hash maps.]
+
+  Author      [Aaron P. Hurst]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 16, 2006.]
+
+  Revision    [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__hash__hashInt_h
+#define ABC__misc__hash__hashInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "misc/extra/extra.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+extern int Hash_DefaultHashFunc(int key, int nBins);
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Hash_Int_t_       Hash_Int_t;
+typedef struct Hash_Int_Entry_t_ Hash_Int_Entry_t;
+
+struct Hash_Int_Entry_t_
+{
+  int                              key;
+  int                            data;
+  struct Hash_Int_Entry_t_ *       pNext;
+};
+
+struct Hash_Int_t_ 
+{
+  int                             nSize;
+  int                             nBins;
+  int (* fHash)(int key, int nBins);
+  Hash_Int_Entry_t **             pArray;
+};
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define Hash_IntForEachEntry( pHash, pEntry, bin)   \
+  for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \
+    if (pEntry)
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a hash map with the given number of bins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Hash_Int_t * Hash_IntAlloc( int nBins )
+{
+  Hash_Int_t * p;
+  int i;
+  assert(nBins > 0);
+  p = ABC_ALLOC( Hash_Int_t, 1);
+  p->nBins = nBins;
+  p->fHash = Hash_DefaultHashFunc;
+  p->nSize  = 0;
+  p->pArray = ABC_ALLOC( Hash_Int_Entry_t *, nBins+1 );
+  for(i=0; i<nBins; i++)
+    p->pArray[i] = NULL;
+
+  return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if a key already exists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Hash_IntExists( Hash_Int_t *p, int key)
+{
+  int bin;
+  Hash_Int_Entry_t *pEntry, **pLast;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pLast = &(p->pArray[bin]);
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if (pEntry->key == key) {
+      return 1;
+    }
+    pLast = &(pEntry->pNext);
+    pEntry = pEntry->pNext;
+  }
+
+  return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds or creates an entry with a key and writes value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Hash_IntWriteEntry( Hash_Int_t *p, int key, int data )
+{
+  int bin;
+  Hash_Int_Entry_t *pEntry, **pLast;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pLast = &(p->pArray[bin]);
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if (pEntry->key == key) {
+      pEntry->data = data;
+      return;
+    }
+    pLast = &(pEntry->pNext);
+    pEntry = pEntry->pNext;
+  }
+
+  // this key does not currently exist
+  // create a new entry and add to bin
+  p->nSize++;
+  (*pLast) = pEntry = ABC_ALLOC( Hash_Int_Entry_t, 1 );
+  pEntry->pNext = NULL;
+  pEntry->key = key;
+  pEntry->data = data;
+
+  return;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds or creates an entry with a key.]
+
+  Description [fCreate specifies whether new entries will be created.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Hash_IntEntry( Hash_Int_t *p, int key, int fCreate )
+{
+  int bin;
+  Hash_Int_Entry_t *pEntry, **pLast;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pLast = &(p->pArray[bin]);
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if (pEntry->key == key)
+      return pEntry->data;
+    pLast = &(pEntry->pNext);
+    pEntry = pEntry->pNext;
+  }
+
+  // this key does not currently exist
+  if (fCreate) {
+    // create a new entry and add to bin
+    p->nSize++;
+    (*pLast) = pEntry = ABC_ALLOC( Hash_Int_Entry_t, 1 );
+    pEntry->pNext = NULL;
+    pEntry->key = key;
+    pEntry->data = 0;
+    return pEntry->data;
+  }
+
+  return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds or creates an entry with a key and returns the pointer to it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int* Hash_IntEntryPtr( Hash_Int_t *p, int key )
+{
+  int bin;
+  Hash_Int_Entry_t *pEntry, **pLast;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pLast = &(p->pArray[bin]);
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if (pEntry->key == key)
+      return &(pEntry->data);
+    pLast = &(pEntry->pNext);
+    pEntry = pEntry->pNext;
+  }
+
+  // this key does not currently exist
+  // create a new entry and add to bin
+  p->nSize++;
+  (*pLast) = pEntry = ABC_ALLOC( Hash_Int_Entry_t, 1 );
+  pEntry->pNext = NULL;
+  pEntry->key = key;
+  pEntry->data = 0;
+
+  return &(pEntry->data);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the hash.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Hash_IntFree( Hash_Int_t *p ) {
+  int bin;
+  Hash_Int_Entry_t *pEntry, *pTemp;
+
+  // free bins
+  for(bin = 0; bin < p->nBins; bin++) {
+    pEntry = p->pArray[bin];
+    while(pEntry) {
+      pTemp = pEntry;
+      pEntry = pEntry->pNext;
+      ABC_FREE( pTemp );
+    }
+  }
+
+  // free hash
+  ABC_FREE( p->pArray );
+  ABC_FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/misc/hash/hashPtr.h b/abc-build/src/misc/hash/hashPtr.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/hash/hashPtr.h
@@ -0,0 +1,339 @@
+/**CFile****************************************************************
+
+  FileName    [hashFlt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Hash maps.]
+
+  Synopsis    [Hash maps.]
+
+  Author      [Aaron P. Hurst]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 16, 2006.]
+
+  Revision    [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__hash__hashPtr_h
+#define ABC__misc__hash__hashPtr_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "misc/extra/extra.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+extern int Hash_DefaultHashFunc(int key, int nBins);
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Hash_Ptr_t_       Hash_Ptr_t;
+typedef struct Hash_Ptr_Entry_t_ Hash_Ptr_Entry_t;
+
+struct Hash_Ptr_Entry_t_
+{
+  int                              key;
+  void *                           data;
+  struct Hash_Ptr_Entry_t_ *       pNext;
+};
+
+struct Hash_Ptr_t_ 
+{
+  int                             nSize;
+  int                             nBins;
+  int (* fHash)(int key, int nBins);
+  Hash_Ptr_Entry_t **             pArray;
+};
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define Hash_PtrForEachEntry( pHash, pEntry, bin )   \
+  for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \
+    if (pEntry)
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a hash map with the given number of bins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Hash_Ptr_t * Hash_PtrAlloc( int nBins )
+{
+  Hash_Ptr_t * p;
+  int i;
+  assert(nBins > 0);
+  p = ABC_ALLOC( Hash_Ptr_t, 1);
+  p->nBins = nBins;
+  p->fHash = Hash_DefaultHashFunc;
+  p->nSize  = 0;
+  p->pArray = ABC_ALLOC( Hash_Ptr_Entry_t *, nBins );
+  for(i=0; i<nBins; i++)
+    p->pArray[i] = NULL;
+
+  return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if a key already exists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Hash_PtrExists( Hash_Ptr_t *p, int key )
+{
+  int bin;
+  Hash_Ptr_Entry_t *pEntry;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if (pEntry->key == key) {
+      return 1;
+    }
+    pEntry = pEntry->pNext;
+  }
+
+  return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds or creates an entry with a key and writes value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Hash_PtrWriteEntry( Hash_Ptr_t *p, int key, void * data )
+{
+  int bin;
+  Hash_Ptr_Entry_t *pEntry, **pLast;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pLast = &(p->pArray[bin]);
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if (pEntry->key == key) {
+      pEntry->data = data;
+      return;
+    }
+    pLast = &(pEntry->pNext);
+    pEntry = pEntry->pNext;
+  }
+
+  // this key does not currently exist
+  // create a new entry and add to bin
+  p->nSize++;
+  (*pLast) = pEntry = ABC_ALLOC( Hash_Ptr_Entry_t, 1 );
+  pEntry->pNext = NULL;
+  pEntry->key = key;
+  pEntry->data = data;
+
+  return;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds or creates an entry with a key.]
+
+  Description [fCreate specifies whether a new entry should be created.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void * Hash_PtrEntry( Hash_Ptr_t *p, int key, int fCreate )
+{
+  int bin;
+  Hash_Ptr_Entry_t *pEntry, **pLast;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pLast = &(p->pArray[bin]);
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if (pEntry->key == key)
+      return pEntry->data;
+    pLast = &(pEntry->pNext);
+    pEntry = pEntry->pNext;
+  }
+
+  // this key does not currently exist
+  if (fCreate) {
+    // create a new entry and add to bin
+    p->nSize++;
+    (*pLast) = pEntry = ABC_ALLOC( Hash_Ptr_Entry_t, 1 );
+    pEntry->pNext = NULL;
+    pEntry->key = key;
+    pEntry->data = NULL;
+    return pEntry->data;
+  }
+
+  return NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds or creates an entry with a key and returns the pointer to it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void** Hash_PtrEntryPtr( Hash_Ptr_t *p, int key )
+{
+  int bin;
+  Hash_Ptr_Entry_t *pEntry, **pLast;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pLast = &(p->pArray[bin]);
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if (pEntry->key == key)
+      return &(pEntry->data);
+    pLast = &(pEntry->pNext);
+    pEntry = pEntry->pNext;
+  }
+
+  // this key does not currently exist
+  // create a new entry and add to bin
+  p->nSize++;
+  (*pLast) = pEntry = ABC_ALLOC( Hash_Ptr_Entry_t, 1 );
+  pEntry->pNext = NULL;
+  pEntry->key = key;
+  pEntry->data = NULL;
+
+  return &(pEntry->data);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes an entry.]
+
+  Description [Returns data, if there was any.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void* Hash_PtrRemove( Hash_Ptr_t *p, int key )
+{
+  int    bin;
+  void * data;
+  Hash_Ptr_Entry_t *pEntry, **pLast;
+
+  // find the bin where this key would live
+  bin = (*(p->fHash))(key, p->nBins);
+
+  // search for key
+  pLast = &(p->pArray[bin]);
+  pEntry = p->pArray[bin];
+  while(pEntry) {
+    if (pEntry->key == key) {
+      p->nSize--;
+      data = pEntry->data;
+      *pLast = pEntry->pNext;
+      return data;
+    }
+    pLast = &(pEntry->pNext);
+    pEntry = pEntry->pNext;
+  }
+    
+  // could not find key
+  return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the hash.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Hash_PtrFree( Hash_Ptr_t *p ) 
+{
+  int bin;
+  Hash_Ptr_Entry_t *pEntry, *pTemp;
+
+  // free bins
+  for(bin = 0; bin < p->nBins; bin++) {
+    pEntry = p->pArray[bin];
+    while(pEntry) {
+      pTemp = pEntry;
+      pEntry = pEntry->pNext;
+      ABC_FREE( pTemp );
+    }
+  }
+ 
+  // free hash
+  ABC_FREE( p->pArray );
+  ABC_FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/misc/hash/module.make b/abc-build/src/misc/hash/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/hash/module.make
@@ -0,0 +1,1 @@
+SRC += 
diff --git a/abc-build/src/misc/mem/mem.c b/abc-build/src/misc/mem/mem.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mem/mem.c
@@ -0,0 +1,605 @@
+/**CFile****************************************************************
+
+  FileName    [esopMem.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Cover manipulation package.]
+
+  Synopsis    [Memory managers.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: esopMem.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "mem.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+struct Mem_Fixed_t_
+{
+    // information about individual entries
+    int           nEntrySize;    // the size of one entry
+    int           nEntriesAlloc; // the total number of entries allocated
+    int           nEntriesUsed;  // the number of entries in use
+    int           nEntriesMax;   // the max number of entries in use
+    char *        pEntriesFree;  // the linked list of free entries
+
+    // this is where the memory is stored
+    int           nChunkSize;    // the size of one chunk
+    int           nChunksAlloc;  // the maximum number of memory chunks 
+    int           nChunks;       // the current number of memory chunks 
+    char **       pChunks;       // the allocated memory
+
+    // statistics
+    int           nMemoryUsed;   // memory used in the allocated entries
+    int           nMemoryAlloc;  // memory allocated
+};
+
+struct Mem_Flex_t_
+{
+    // information about individual entries
+    int           nEntriesUsed;  // the number of entries allocated
+    char *        pCurrent;      // the current pointer to free memory
+    char *        pEnd;          // the first entry outside the free memory
+
+    // this is where the memory is stored
+    int           nChunkSize;    // the size of one chunk
+    int           nChunksAlloc;  // the maximum number of memory chunks 
+    int           nChunks;       // the current number of memory chunks 
+    char **       pChunks;       // the allocated memory
+
+    // statistics
+    int           nMemoryUsed;   // memory used in the allocated entries
+    int           nMemoryAlloc;  // memory allocated
+};
+
+struct Mem_Step_t_
+{
+    int             nMems;              // the number of fixed memory managers employed
+    Mem_Fixed_t **  pMems;              // memory managers: 2^1 words, 2^2 words, etc
+    int             nMapSize;           // the size of the memory array
+    Mem_Fixed_t **  pMap;               // maps the number of bytes into its memory manager
+    int             nLargeChunksAlloc;  // the maximum number of large memory chunks
+    int             nLargeChunks;       // the current number of large memory chunks
+    void **         pLargeChunks;       // the allocated large memory chunks
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates memory pieces of fixed size.]
+
+  Description [The size of the chunk is computed as the minimum of
+  1024 entries and 64K. Can only work with entry size at least 4 byte long.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mem_Fixed_t * Mem_FixedStart( int nEntrySize )
+{
+    Mem_Fixed_t * p;
+
+    p = ABC_ALLOC( Mem_Fixed_t, 1 );
+    memset( p, 0, sizeof(Mem_Fixed_t) );
+
+    p->nEntrySize    = nEntrySize;
+    p->nEntriesAlloc = 0;
+    p->nEntriesUsed  = 0;
+    p->pEntriesFree  = NULL;
+
+    if ( nEntrySize * (1 << 10) < (1<<16) )
+        p->nChunkSize = (1 << 10);
+    else
+        p->nChunkSize = (1<<16) / nEntrySize;
+    if ( p->nChunkSize < 8 )
+        p->nChunkSize = 8;
+
+    p->nChunksAlloc  = 64;
+    p->nChunks       = 0;
+    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
+
+    p->nMemoryUsed   = 0;
+    p->nMemoryAlloc  = 0;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose )
+{
+    int i;
+    if ( p == NULL )
+        return;
+    if ( fVerbose )
+    {
+        printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n",
+            p->nEntrySize, p->nChunkSize, p->nChunks );
+        printf( "   Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n",
+            p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc );
+    }
+    for ( i = 0; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    ABC_FREE( p->pChunks );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Mem_FixedEntryFetch( Mem_Fixed_t * p )
+{
+    char * pTemp;
+    int i;
+
+    // check if there are still free entries
+    if ( p->nEntriesUsed == p->nEntriesAlloc )
+    { // need to allocate more entries
+        assert( p->pEntriesFree == NULL );
+        if ( p->nChunks == p->nChunksAlloc )
+        {
+            p->nChunksAlloc *= 2;
+            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
+        }
+        p->pEntriesFree = ABC_ALLOC( char, p->nEntrySize * p->nChunkSize );
+        p->nMemoryAlloc += p->nEntrySize * p->nChunkSize;
+        // transform these entries into a linked list
+        pTemp = p->pEntriesFree;
+        for ( i = 1; i < p->nChunkSize; i++ )
+        {
+            *((char **)pTemp) = pTemp + p->nEntrySize;
+            pTemp += p->nEntrySize;
+        }
+        // set the last link
+        *((char **)pTemp) = NULL;
+        // add the chunk to the chunk storage
+        p->pChunks[ p->nChunks++ ] = p->pEntriesFree;
+        // add to the number of entries allocated
+        p->nEntriesAlloc += p->nChunkSize;
+    }
+    // incrememt the counter of used entries
+    p->nEntriesUsed++;
+    if ( p->nEntriesMax < p->nEntriesUsed )
+        p->nEntriesMax = p->nEntriesUsed;
+    // return the first entry in the free entry list
+    pTemp = p->pEntriesFree;
+    p->pEntriesFree = *((char **)pTemp);
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry )
+{
+    // decrement the counter of used entries
+    p->nEntriesUsed--;
+    // add the entry to the linked list of free entries
+    *((char **)pEntry) = p->pEntriesFree;
+    p->pEntriesFree = pEntry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description [Relocates all the memory except the first chunk.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mem_FixedRestart( Mem_Fixed_t * p )
+{
+    int i;
+    char * pTemp;
+
+    // deallocate all chunks except the first one
+    for ( i = 1; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    p->nChunks = 1;
+    // transform these entries into a linked list
+    pTemp = p->pChunks[0];
+    for ( i = 1; i < p->nChunkSize; i++ )
+    {
+        *((char **)pTemp) = pTemp + p->nEntrySize;
+        pTemp += p->nEntrySize;
+    }
+    // set the last link
+    *((char **)pTemp) = NULL;
+    // set the free entry list
+    p->pEntriesFree  = p->pChunks[0];
+    // set the correct statistics
+    p->nMemoryAlloc  = p->nEntrySize * p->nChunkSize;
+    p->nMemoryUsed   = 0;
+    p->nEntriesAlloc = p->nChunkSize;
+    p->nEntriesUsed  = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mem_FixedReadMemUsage( Mem_Fixed_t * p )
+{
+    return p->nMemoryAlloc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mem_FixedReadMaxEntriesUsed( Mem_Fixed_t * p )
+{
+    return p->nEntriesMax;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates entries of flexible size.]
+
+  Description [Can only work with entry size at least 4 byte long.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mem_Flex_t * Mem_FlexStart()
+{
+    Mem_Flex_t * p;
+
+    p = ABC_ALLOC( Mem_Flex_t, 1 );
+    memset( p, 0, sizeof(Mem_Flex_t) );
+
+    p->nEntriesUsed  = 0;
+    p->pCurrent      = NULL;
+    p->pEnd          = NULL;
+
+    p->nChunkSize    = (1 << 12);
+    p->nChunksAlloc  = 64;
+    p->nChunks       = 0;
+    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
+
+    p->nMemoryUsed   = 0;
+    p->nMemoryAlloc  = 0;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mem_FlexStop( Mem_Flex_t * p, int fVerbose )
+{
+    int i;
+    if ( p == NULL )
+        return;
+    if ( fVerbose )
+    {
+        printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n",
+            p->nChunkSize, p->nChunks );
+        printf( "   Entries used = %d. Memory used = %d. Memory alloc = %d.\n",
+            p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc );
+    }
+    for ( i = 0; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    ABC_FREE( p->pChunks );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes )
+{
+    char * pTemp;
+    // check if there are still free entries
+    if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd )
+    { // need to allocate more entries
+        if ( p->nChunks == p->nChunksAlloc )
+        {
+            p->nChunksAlloc *= 2;
+            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
+        }
+        if ( nBytes > p->nChunkSize )
+        {
+            // resize the chunk size if more memory is requested than it can give
+            // (ideally, this should never happen)
+            p->nChunkSize = 2 * nBytes;
+        }
+        p->pCurrent = ABC_ALLOC( char, p->nChunkSize );
+        p->pEnd     = p->pCurrent + p->nChunkSize;
+        p->nMemoryAlloc += p->nChunkSize;
+        // add the chunk to the chunk storage
+        p->pChunks[ p->nChunks++ ] = p->pCurrent;
+    }
+    assert( p->pCurrent + nBytes <= p->pEnd );
+    // increment the counter of used entries
+    p->nEntriesUsed++;
+    // keep track of the memory used
+    p->nMemoryUsed += nBytes;
+    // return the next entry
+    pTemp = p->pCurrent;
+    p->pCurrent += nBytes;
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description [Relocates all the memory except the first chunk.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mem_FlexRestart( Mem_Flex_t * p )
+{
+    int i;
+    if ( p->nChunks == 0 )
+        return;
+    // deallocate all chunks except the first one
+    for ( i = 1; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    p->nChunks  = 1;
+    p->nMemoryAlloc = p->nChunkSize;
+    // transform these entries into a linked list
+    p->pCurrent = p->pChunks[0];
+    p->pEnd     = p->pCurrent + p->nChunkSize;
+    p->nEntriesUsed = 0;
+    p->nMemoryUsed = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mem_FlexReadMemUsage( Mem_Flex_t * p )
+{
+    return p->nMemoryUsed;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the hierarchical memory manager.]
+
+  Description [This manager can allocate entries of any size.
+  Iternally they are mapped into the entries with the number of bytes
+  equal to the power of 2. The smallest entry size is 8 bytes. The
+  next one is 16 bytes etc. So, if the user requests 6 bytes, he gets 
+  8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc.
+  The input parameters "nSteps" says how many fixed memory managers
+  are employed internally. Calling this procedure with nSteps equal
+  to 10 results in 10 hierarchically arranged internal memory managers, 
+  which can allocate up to 4096 (1Kb) entries. Requests for larger 
+  entries are handed over to malloc() and then ABC_FREE()ed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mem_Step_t * Mem_StepStart( int nSteps )
+{
+    Mem_Step_t * p;
+    int i, k;
+    p = ABC_ALLOC( Mem_Step_t, 1 );
+    memset( p, 0, sizeof(Mem_Step_t) );
+    p->nMems = nSteps;
+    // start the fixed memory managers
+    p->pMems = ABC_ALLOC( Mem_Fixed_t *, p->nMems );
+    for ( i = 0; i < p->nMems; i++ )
+        p->pMems[i] = Mem_FixedStart( (8<<i) );
+    // set up the mapping of the required memory size into the corresponding manager
+    p->nMapSize = (4<<p->nMems);
+    p->pMap = ABC_ALLOC( Mem_Fixed_t *, p->nMapSize+1 );
+    p->pMap[0] = NULL;
+    for ( k = 1; k <= 4; k++ )
+        p->pMap[k] = p->pMems[0];
+    for ( i = 0; i < p->nMems; i++ )
+        for ( k = (4<<i)+1; k <= (8<<i); k++ )
+            p->pMap[k] = p->pMems[i];
+//for ( i = 1; i < 100; i ++ )
+//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mem_StepStop( Mem_Step_t * p, int fVerbose )
+{
+    int i;
+    for ( i = 0; i < p->nMems; i++ )
+        Mem_FixedStop( p->pMems[i], fVerbose );
+    if ( p->pLargeChunks ) 
+    {
+        for ( i = 0; i < p->nLargeChunks; i++ )
+            ABC_FREE( p->pLargeChunks[i] );
+        ABC_FREE( p->pLargeChunks );
+    }
+    ABC_FREE( p->pMems );
+    ABC_FREE( p->pMap );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Mem_StepEntryFetch( Mem_Step_t * p, int nBytes )
+{
+    if ( nBytes == 0 )
+        return NULL;
+    if ( nBytes > p->nMapSize )
+    {
+//        printf( "Allocating %d bytes.\n", nBytes );
+//        return ABC_ALLOC( char, nBytes );
+        if ( p->nLargeChunks == p->nLargeChunksAlloc )
+        {
+            if ( p->nLargeChunksAlloc == 0 )
+                p->nLargeChunksAlloc = 32;
+            p->nLargeChunksAlloc *= 2;
+            p->pLargeChunks = (void **)ABC_REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc ); 
+        }
+        p->pLargeChunks[ p->nLargeChunks++ ] = ABC_ALLOC( char, nBytes );
+        return (char *)p->pLargeChunks[ p->nLargeChunks - 1 ];
+    }
+    return Mem_FixedEntryFetch( p->pMap[nBytes] );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes )
+{
+    if ( nBytes == 0 )
+        return;
+    if ( nBytes > p->nMapSize )
+    {
+//        ABC_FREE( pEntry );
+        return;
+    }
+    Mem_FixedEntryRecycle( p->pMap[nBytes], pEntry );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mem_StepReadMemUsage( Mem_Step_t * p )
+{
+    int i, nMemTotal = 0;
+    for ( i = 0; i < p->nMems; i++ )
+        nMemTotal += p->pMems[i]->nMemoryAlloc;
+    return nMemTotal;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/mem/mem.h b/abc-build/src/misc/mem/mem.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mem/mem.h
@@ -0,0 +1,75 @@
+/**CFile****************************************************************
+
+  FileName    [mem.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Memory management.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mem.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__mem__mem_h
+#define ABC__aig__mem__mem_h
+
+#include "misc/util/abc_global.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Mem_Fixed_t_    Mem_Fixed_t;    
+typedef struct Mem_Flex_t_     Mem_Flex_t;     
+typedef struct Mem_Step_t_     Mem_Step_t;     
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/*=== mem.c ===========================================================*/
+// fixed-size-block memory manager
+extern Mem_Fixed_t * Mem_FixedStart( int nEntrySize );
+extern void          Mem_FixedStop( Mem_Fixed_t * p, int fVerbose );
+extern char *        Mem_FixedEntryFetch( Mem_Fixed_t * p );
+extern void          Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry );
+extern void          Mem_FixedRestart( Mem_Fixed_t * p );
+extern int           Mem_FixedReadMemUsage( Mem_Fixed_t * p );
+extern int           Mem_FixedReadMaxEntriesUsed( Mem_Fixed_t * p );
+// flexible-size-block memory manager
+extern Mem_Flex_t *  Mem_FlexStart();
+extern void          Mem_FlexStop( Mem_Flex_t * p, int fVerbose );
+extern char *        Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes );
+extern void          Mem_FlexRestart( Mem_Flex_t * p );
+extern int           Mem_FlexReadMemUsage( Mem_Flex_t * p );
+// hierarchical memory manager
+extern Mem_Step_t *  Mem_StepStart( int nSteps );
+extern void          Mem_StepStop( Mem_Step_t * p, int fVerbose );
+extern char *        Mem_StepEntryFetch( Mem_Step_t * p, int nBytes );
+extern void          Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes );
+extern int           Mem_StepReadMemUsage( Mem_Step_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/abc-build/src/misc/mem/mem2.h b/abc-build/src/misc/mem/mem2.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mem/mem2.h
@@ -0,0 +1,271 @@
+/**CFile****************************************************************
+
+  FileName    [mem2.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Memory management.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mem2.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__mem__mem2_h
+#define ABC__aig__mem__mem2_h
+
+#include "misc/vec/vec.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Mmr_Flex_t_     Mmr_Flex_t;     
+typedef struct Mmr_Fixed_t_    Mmr_Fixed_t;    
+typedef struct Mmr_Step_t_     Mmr_Step_t;     
+
+struct Mmr_Flex_t_
+{
+    int           nPageBase;     // log2 page size in words
+    int           PageMask;      // page mask
+    int           nEntries;      // entries allocated
+    int           nEntriesMax;   // max number of enries used
+    int           iNext;         // next word to be used
+    Vec_Ptr_t     vPages;        // memory pages
+};
+
+struct Mmr_Fixed_t_
+{
+    int           nPageBase;     // log2 page size in words
+    int           PageMask;      // page mask
+    int           nEntryWords;   // entry size in words
+    int           nEntries;      // entries allocated
+    int           nEntriesMax;   // max number of enries used
+    Vec_Ptr_t     vPages;        // memory pages
+    Vec_Int_t     vFrees;        // free entries
+};
+
+struct Mmr_Step_t_
+{
+    int           nBits;         // the number of bits
+    int           uMask;         // the number of managers minus 1
+    int           nEntries;      // the number of entries
+    int           nEntriesMax;   // the max number of entries
+    int           nEntriesAll;   // the total number of entries
+    Mmr_Fixed_t   pMems[0];      // memory managers: 2^0 words, 2^1 words, etc
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Mmr_Flex_t * Mmr_FlexStart( int nPageBase )
+{
+    Mmr_Flex_t * p;
+    p = ABC_CALLOC( Mmr_Flex_t, 1 );
+    p->nPageBase = nPageBase;
+    p->PageMask  = (1 << nPageBase) - 1;
+    p->iNext     = (1 << nPageBase);
+    return p;
+}
+static inline void Mmr_FlexStop( Mmr_Flex_t * p )
+{
+    word * pPage;
+    int i;
+    if ( 0 && Vec_PtrSize(&p->vPages) )
+        printf( "Using %3d pages of %6d words each with %6d entries (max = %6d). Total memory = %5.2f MB.\n", 
+            Vec_PtrSize(&p->vPages), p->nPageBase ? 1 << p->nPageBase : 0, p->nEntries, p->nEntriesMax, 
+            1.0 * Vec_PtrSize(&p->vPages) * (1 << p->nPageBase) * 8 / (1 << 20) );
+    Vec_PtrForEachEntry( word *, &p->vPages, pPage, i )
+        ABC_FREE( pPage );
+    ABC_FREE( p->vPages.pArray );
+    ABC_FREE( p );
+}
+static inline word * Mmr_FlexEntry( Mmr_Flex_t * p, int h )
+{
+    assert( h > 0 && h < p->iNext );
+    return (word *)Vec_PtrEntry(&p->vPages, (h >> p->nPageBase)) + (h & p->PageMask);
+}
+static inline int Mmr_FlexFetch( Mmr_Flex_t * p, int nWords )
+{
+    int hEntry;
+    assert( nWords > 0 && nWords < p->PageMask );
+    if ( p->iNext + nWords >= p->PageMask )
+    {
+        Vec_PtrPush( &p->vPages, ABC_FALLOC( word, p->PageMask + 1 ) );
+        p->iNext = 1;
+    }
+    hEntry = ((Vec_PtrSize(&p->vPages) - 1) << p->nPageBase) | p->iNext;
+    p->iNext += nWords;
+    p->nEntries++;
+    p->nEntriesMax = Abc_MaxInt( p->nEntriesMax, p->nEntries );
+    return hEntry;
+}
+static inline void Mmr_FlexRelease( Mmr_Flex_t * p, int h )
+{
+    assert( h > 0 && h < p->iNext );
+    if ( (h >> p->nPageBase) && Vec_PtrEntry(&p->vPages, (h >> p->nPageBase) - 1) )
+    {
+        word * pPage = (word *)Vec_PtrEntry(&p->vPages, (h >> p->nPageBase) - 1);
+        Vec_PtrWriteEntry( &p->vPages, (h >> p->nPageBase) - 1, NULL );
+        ABC_FREE( pPage );
+    }
+}
+
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Mmr_FixedCreate( Mmr_Fixed_t * p, int nPageBase, int nEntryWords )
+{
+    assert( nEntryWords > 0 && nEntryWords < (1 << nPageBase) );
+    p->nPageBase   = nPageBase;
+    p->PageMask    = (1 << nPageBase) - 1;
+    p->nEntryWords = nEntryWords;
+}
+static inline Mmr_Fixed_t * Mmr_FixedStart( int nPageBase, int nEntryWords )
+{
+    Mmr_Fixed_t * p = ABC_CALLOC( Mmr_Fixed_t, 1 );
+    Mmr_FixedCreate( p, nPageBase, nEntryWords );
+    return p;
+}
+static inline void Mmr_FixedStop( Mmr_Fixed_t * p, int fFreeLast )
+{
+    word * pPage;
+    int i;
+    if ( 0 && Vec_PtrSize(&p->vPages) )
+        printf( "Using %3d pages of %6d words each with %6d entries (max = %6d) of size %d. Total memory = %5.2f MB.\n", 
+            Vec_PtrSize(&p->vPages), p->nPageBase ? 1 << p->nPageBase : 0, p->nEntries, p->nEntriesMax, p->nEntryWords,
+            1.0 * Vec_PtrSize(&p->vPages) * (1 << p->nPageBase) * 8 / (1 << 20) );
+    Vec_PtrForEachEntry( word *, &p->vPages, pPage, i )
+        ABC_FREE( pPage );
+    ABC_FREE( p->vPages.pArray );
+    ABC_FREE( p->vFrees.pArray );
+    if ( fFreeLast )
+        ABC_FREE( p );
+}
+static inline word * Mmr_FixedEntry( Mmr_Fixed_t * p, int h )
+{
+    assert( h > 0 && h < (Vec_PtrSize(&p->vPages) << p->nPageBase) );
+    return (word *)Vec_PtrEntry(&p->vPages, (h >> p->nPageBase)) + (h & p->PageMask);
+}
+static inline int Mmr_FixedFetch( Mmr_Fixed_t * p )
+{
+    if ( Vec_IntSize(&p->vFrees) == 0 )
+    {
+        int i, hEntry = Vec_PtrSize(&p->vPages) << p->nPageBase;
+        Vec_PtrPush( &p->vPages, ABC_FALLOC( word, p->PageMask + 1 ) );
+        for ( i = 1; i + p->nEntryWords <= p->PageMask; i += p->nEntryWords )
+            Vec_IntPush( &p->vFrees, hEntry | i );
+        Vec_IntReverseOrder( &p->vFrees );
+    }
+    p->nEntries++;
+    p->nEntriesMax = Abc_MaxInt( p->nEntriesMax, p->nEntries );
+    return Vec_IntPop( &p->vFrees );
+}
+static inline void Mmr_FixedRecycle( Mmr_Fixed_t * p, int h )
+{
+    p->nEntries--;
+    memset( Mmr_FixedEntry(p, h), 0xFF, sizeof(word) * p->nEntryWords );
+    Vec_IntPush( &p->vFrees, h );
+}
+static inline int Mmr_FixedMemory( Mmr_Fixed_t * p )
+{
+    return Vec_PtrSize(&p->vPages) * (p->PageMask + 1);
+}
+
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Mmr_Step_t * Mmr_StepStart( int nPageBase, int nWordBase )
+{
+    char * pMemory = ABC_CALLOC( char, sizeof(Mmr_Step_t) + sizeof(Mmr_Fixed_t) * (1 << nWordBase) );
+    Mmr_Step_t * p = (Mmr_Step_t *)pMemory;
+    int i;
+    p->nBits = nWordBase;
+    p->uMask = (1 << nWordBase) - 1;
+    for ( i = 1; i <= p->uMask; i++ )
+        Mmr_FixedCreate( p->pMems + i, nPageBase, i );
+    return p;
+}
+static inline void Mmr_StepStop( Mmr_Step_t * p )
+{
+    int i;
+    for ( i = 0; i <= p->uMask; i++ )
+        Mmr_FixedStop( p->pMems + i, 0 );
+    ABC_FREE( p );
+}
+static inline word * Mmr_StepEntry( Mmr_Step_t * p, int h )
+{
+    assert( (h & p->uMask) > 0 );
+    return Mmr_FixedEntry( p->pMems + (h & p->uMask), (h >> p->nBits) );
+}
+static inline int Mmr_StepFetch( Mmr_Step_t * p, int nWords )
+{
+    assert( nWords > 0 && nWords <= p->uMask );
+    p->nEntries++;
+    p->nEntriesAll++;
+    p->nEntriesMax = Abc_MaxInt( p->nEntriesMax, p->nEntries );
+    return (Mmr_FixedFetch(p->pMems + nWords) << p->nBits) | nWords;
+}
+static inline void Mmr_StepRecycle( Mmr_Step_t * p, int h )
+{
+    p->nEntries--;
+    Mmr_FixedRecycle( p->pMems + (h & p->uMask), (h >> p->nBits) );
+}
+static inline int Mmr_StepMemory( Mmr_Step_t * p )
+{
+    int i, Mem = 0;
+    for ( i = 1; i <= p->uMask; i++ )
+        Mem += Mmr_FixedMemory( p->pMems + i );
+    return Mem;
+}
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/abc-build/src/misc/mem/module.make b/abc-build/src/misc/mem/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mem/module.make
@@ -0,0 +1,1 @@
+SRC +=	src/misc/mem/mem.c 
diff --git a/abc-build/src/misc/mvc/module.make b/abc-build/src/misc/mvc/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/module.make
@@ -0,0 +1,15 @@
+SRC +=  src/misc/mvc/mvcApi.c \
+	src/misc/mvc/mvcCompare.c \
+	src/misc/mvc/mvcContain.c \
+	src/misc/mvc/mvcCover.c \
+	src/misc/mvc/mvcCube.c \
+	src/misc/mvc/mvcDivide.c \
+	src/misc/mvc/mvcDivisor.c \
+	src/misc/mvc/mvcList.c \
+	src/misc/mvc/mvcLits.c \
+	src/misc/mvc/mvcMan.c \
+	src/misc/mvc/mvcOpAlg.c \
+	src/misc/mvc/mvcOpBool.c \
+	src/misc/mvc/mvcPrint.c \
+	src/misc/mvc/mvcSort.c \
+	src/misc/mvc/mvcUtils.c
diff --git a/abc-build/src/misc/mvc/mvc.c b/abc-build/src/misc/mvc/mvc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/mvc.c
@@ -0,0 +1,51 @@
+/**CFile****************************************************************
+
+  FileName    [mvc.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    []
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: mvc.c,v 1.3 2003/03/19 19:50:26 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/mvc/mvc.h b/abc-build/src/misc/mvc/mvc.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/mvc.h
@@ -0,0 +1,739 @@
+/**CFile****************************************************************
+
+  FileName    [mvc.h]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Data structure for MV cube/cover manipulation.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: mvc.h,v 1.10 2003/05/02 23:23:59 wjiang Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__misc__mvc__mvc_h
+#define ABC__misc__mvc__mvc_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "misc/extra/extra.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+// this is the only part of Mvc package, which should be modified
+// when compiling the package for other platforms
+
+// these parameters can be computed but setting them manually makes it faster
+#define BITS_PER_WORD         32                      // sizeof(Mvc_CubeWord_t) * 8 
+#define BITS_PER_WORD_MINUS   31                      // the same minus 1
+#define BITS_PER_WORD_LOG     5                       // log2(sizeof(Mvc_CubeWord_t) * 8)
+#define BITS_DISJOINT         ((Mvc_CubeWord_t)0x55555555)  // the mask of the type "01010101"
+#define BITS_FULL             ((Mvc_CubeWord_t)0xffffffff)  // the mask of the type "11111111"
+
+// uncomment this macro to switch to standard memory management
+//#define USE_SYSTEM_MEMORY_MANAGEMENT 
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+// cube/list/cover/data
+typedef unsigned int               Mvc_CubeWord_t;
+typedef struct MvcCubeStruct       Mvc_Cube_t;
+typedef struct MvcListStruct       Mvc_List_t;
+typedef struct MvcCoverStruct      Mvc_Cover_t;
+typedef struct MvcDataStruct       Mvc_Data_t;
+typedef struct MvcManagerStruct    Mvc_Manager_t;
+
+// the cube data structure
+struct MvcCubeStruct
+{
+    Mvc_Cube_t *    pNext;        // the next cube in the linked list
+    unsigned        iLast   : 24; // the index of the last word
+    unsigned        nUnused :  6; // the number of unused bits in the last word
+    unsigned        fPrime  :  1; // marks the prime cube
+    unsigned        fEssen  :  1; // marks the essential cube
+    unsigned        nOnes;        // the number of 1's in the bit data
+    Mvc_CubeWord_t  pData[1];     // the first Mvc_CubeWord_t filled with bit data
+};
+
+// the single-linked list of cubes in the cover
+struct MvcListStruct
+{
+    Mvc_Cube_t *    pHead;        // the first cube in the list
+    Mvc_Cube_t *    pTail;        // the last cube in the list
+    int             nItems;       // the number of cubes in the list
+};
+
+// the cover data structure
+struct MvcCoverStruct
+{
+    int             nWords;       // the number of machine words
+    int             nUnused;      // the number of unused bits in the last word
+    int             nBits;        // the number of used data bits in the cube
+    Mvc_List_t      lCubes;       // the single-linked list of cubes
+    Mvc_Cube_t **   pCubes;       // the array of cubes (for sorting)
+    int             nCubesAlloc;  // the size of allocated storage
+    int *           pLits;        // the counter of lit occurrances in cubes
+    Mvc_Cube_t *    pMask;        // the multipurpose mask
+    Mvc_Manager_t * pMem;         // the memory manager
+};
+
+// data structure to store information about MV variables
+struct MvcDataStruct
+{
+    Mvc_Manager_t * pMan;         // the memory manager
+//    Vm_VarMap_t *   pVm;          // the MV variable data
+    int             nBinVars;     // the number of binary variables
+    Mvc_Cube_t *    pMaskBin;     // the mask to select the binary bits only
+    Mvc_Cube_t **   ppMasks;      // the mask to select each MV variable
+    Mvc_Cube_t *    ppTemp[3];    // the temporary cubes
+};
+
+// the manager of covers and cubes (as of today, only managing memory)
+struct MvcManagerStruct
+{
+    Extra_MmFixed_t * pManC;        // the manager for covers
+    Extra_MmFixed_t * pMan1;        // the manager for 1-word cubes
+    Extra_MmFixed_t * pMan2;        // the manager for 2-word cubes
+    Extra_MmFixed_t * pMan4;        // the manager for 3-word cubes
+};
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+// reading data from the header of the cube
+#define Mvc_CubeReadNext(Cube)       ((Cube)->pNext)
+#define Mvc_CubeReadNextP(Cube)      (&(Cube)->pNext)
+#define Mvc_CubeReadLast(Cube)       ((Cube)->iLast)
+#define Mvc_CubeReadSize(Cube)       ((Cube)->nOnes)
+// setting data to the header of the cube
+#define Mvc_CubeSetNext(Cube,Next)   ((Cube)->pNext = (Next))
+#define Mvc_CubeSetLast(Cube,Last)   ((Cube)->iLast = (Last))
+#define Mvc_CubeSetSize(Cube,Size)   ((Cube)->nOnes = (Size))
+// checking the number of words
+
+#define Mvc_Cube1Words(Cube)         ((Cube)->iLast == 0) 
+#define Mvc_Cube2Words(Cube)         ((Cube)->iLast == 1) 
+#define Mvc_CubeNWords(Cube)         ((Cube)->iLast >  1) 
+// getting one data bit
+#define Mvc_CubeWhichWord(Bit)       ((Bit) >> BITS_PER_WORD_LOG)
+#define Mvc_CubeWhichBit(Bit)        ((Bit) &  BITS_PER_WORD_MINUS)
+// accessing individual bits
+#define Mvc_CubeBitValue(Cube, Bit) (((Cube)->pData[Mvc_CubeWhichWord(Bit)] &   (((Mvc_CubeWord_t)1)<<(Mvc_CubeWhichBit(Bit)))) > 0)
+#define Mvc_CubeBitInsert(Cube, Bit) ((Cube)->pData[Mvc_CubeWhichWord(Bit)] |=  (((Mvc_CubeWord_t)1)<<(Mvc_CubeWhichBit(Bit))))
+#define Mvc_CubeBitRemove(Cube, Bit) ((Cube)->pData[Mvc_CubeWhichWord(Bit)] &= ~(((Mvc_CubeWord_t)1)<<(Mvc_CubeWhichBit(Bit))))
+// accessing values of the binary variables
+#define Mvc_CubeVarValue(Cube, Var) (((Cube)->pData[Mvc_CubeWhichWord(2*(Var))] >> (Mvc_CubeWhichBit(2*(Var)))) & ((Mvc_CubeWord_t)3))
+
+// various macros
+
+// cleaning the data bits of the cube
+#define Mvc_Cube1BitClean( Cube )\
+          ((Cube)->pData[0] = 0)
+#define Mvc_Cube2BitClean( Cube )\
+         (((Cube)->pData[0] = 0),\
+          ((Cube)->pData[1] = 0))
+#define Mvc_CubeNBitClean( Cube  )\
+{\
+    int _i_;\
+    for( _i_ = (Cube)->iLast; _i_ >= 0; _i_--)\
+           (Cube)->pData[_i_] = 0;\
+}
+
+// cleaning the unused part of the lat word
+#define Mvc_CubeBitCleanUnused( Cube )\
+    ((Cube)->pData[(Cube)->iLast] &= (BITS_FULL >> (Cube)->nUnused))
+
+// filling the used data bits with 1's
+#define Mvc_Cube1BitFill( Cube )\
+           (Cube)->pData[0] = (BITS_FULL >> (Cube)->nUnused);
+#define Mvc_Cube2BitFill( Cube )\
+         (((Cube)->pData[0] =  BITS_FULL),\
+          ((Cube)->pData[1] = (BITS_FULL >> (Cube)->nUnused))) 
+#define Mvc_CubeNBitFill( Cube )\
+{\
+    int _i_;\
+    (Cube)->pData[(Cube)->iLast] = (BITS_FULL >> (Cube)->nUnused);\
+    for( _i_ = (Cube)->iLast - 1; _i_ >= 0; _i_-- )\
+        (Cube)->pData[_i_] =  BITS_FULL;\
+}
+
+// complementing the data bits
+#define Mvc_Cube1BitNot( Cube )\
+          ((Cube)->pData[0] ^= (BITS_FULL >> (Cube)->nUnused))
+#define Mvc_Cube2BitNot( Cube )\
+         (((Cube)->pData[0] ^=  BITS_FULL),\
+          ((Cube)->pData[1] ^= (BITS_FULL >> (Cube)->nUnused)))
+#define Mvc_CubeNBitNot( Cube )\
+{\
+    int _i_;\
+    (Cube)->pData[(Cube)->iLast] ^= (BITS_FULL >> (Cube)->nUnused);\
+    for( _i_ = (Cube)->iLast - 1; _i_ >= 0; _i_-- )\
+        (Cube)->pData[_i_] ^=  BITS_FULL;\
+}
+
+#define Mvc_Cube1BitCopy( Cube1, Cube2 )\
+         (((Cube1)->pData[0]) = ((Cube2)->pData[0]))
+#define Mvc_Cube2BitCopy( Cube1, Cube2 )\
+        ((((Cube1)->pData[0]) = ((Cube2)->pData[0])),\
+         (((Cube1)->pData[1])=  ((Cube2)->pData[1])))
+#define Mvc_CubeNBitCopy( Cube1, Cube2 )\
+{\
+    int _i_;\
+    for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+        ((Cube1)->pData[_i_]) = ((Cube2)->pData[_i_]);\
+}
+
+#define Mvc_Cube1BitOr( CubeR, Cube1, Cube2 )\
+         (((CubeR)->pData[0]) = ((Cube1)->pData[0] | (Cube2)->pData[0]))
+#define Mvc_Cube2BitOr( CubeR, Cube1, Cube2 )\
+        ((((CubeR)->pData[0]) = ((Cube1)->pData[0] | (Cube2)->pData[0])),\
+         (((CubeR)->pData[1]) = ((Cube1)->pData[1] | (Cube2)->pData[1])))
+#define Mvc_CubeNBitOr( CubeR, Cube1, Cube2 )\
+{\
+    int _i_;\
+    for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+        (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] | (Cube2)->pData[_i_]));\
+}
+
+#define Mvc_Cube1BitExor( CubeR, Cube1, Cube2 )\
+         (((CubeR)->pData[0]) = ((Cube1)->pData[0] ^ (Cube2)->pData[0]))
+#define Mvc_Cube2BitExor( CubeR, Cube1, Cube2 )\
+        ((((CubeR)->pData[0]) = ((Cube1)->pData[0] ^ (Cube2)->pData[0])),\
+         (((CubeR)->pData[1]) = ((Cube1)->pData[1] ^ (Cube2)->pData[1])))
+#define Mvc_CubeNBitExor( CubeR, Cube1, Cube2 )\
+{\
+    int _i_;\
+    for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+        (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] ^ (Cube2)->pData[_i_]));\
+}
+
+#define Mvc_Cube1BitAnd( CubeR, Cube1, Cube2 )\
+         (((CubeR)->pData[0]) = ((Cube1)->pData[0] & (Cube2)->pData[0]))
+#define Mvc_Cube2BitAnd( CubeR, Cube1, Cube2 )\
+        ((((CubeR)->pData[0]) = ((Cube1)->pData[0] & (Cube2)->pData[0])),\
+         (((CubeR)->pData[1]) = ((Cube1)->pData[1] & (Cube2)->pData[1])))
+#define Mvc_CubeNBitAnd( CubeR, Cube1, Cube2 )\
+{\
+    int _i_;\
+    for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+        (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] & (Cube2)->pData[_i_]));\
+} 
+
+#define Mvc_Cube1BitSharp( CubeR, Cube1, Cube2 )\
+         (((CubeR)->pData[0]) = ((Cube1)->pData[0] & ~((Cube2)->pData[0])))
+#define Mvc_Cube2BitSharp( CubeR, Cube1, Cube2 )\
+        ((((CubeR)->pData[0]) = ((Cube1)->pData[0] & ~((Cube2)->pData[0]))),\
+         (((CubeR)->pData[1]) = ((Cube1)->pData[1] & ~((Cube2)->pData[1]))))
+#define Mvc_CubeNBitSharp( CubeR, Cube1, Cube2 )\
+{\
+    int _i_;\
+    for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+        (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] & ~(Cube2)->pData[_i_]));\
+}  
+
+#define Mvc_Cube1BitEmpty( Res, Cube )\
+  (Res = ((Cube)->pData[0] == 0))
+#define Mvc_Cube2BitEmpty( Res, Cube )\
+  (Res = ((Cube)->pData[0] == 0 && (Cube)->pData[1] == 0))
+#define Mvc_CubeNBitEmpty( Res, Cube )\
+{\
+    int _i_; Res = 1;\
+    for (_i_ = (Cube)->iLast; _i_ >= 0; _i_--)\
+        if ( (Cube)->pData[_i_] )\
+           { Res = 0; break; }\
+}
+
+#define Mvc_Cube1BitEqual( Res, Cube1, Cube2 )\
+  (Res = (((Cube1)->pData[0]) == ((Cube2)->pData[0])))
+#define Mvc_Cube2BitEqual( Res, Cube1, Cube2 )\
+ (Res = ((((Cube1)->pData[0]) == ((Cube2)->pData[0])) &&\
+         (((Cube1)->pData[1]) == ((Cube2)->pData[1]))))
+#define Mvc_CubeNBitEqual( Res, Cube1, Cube2 )\
+{\
+    int _i_; Res = 1;\
+    for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+         if (((Cube1)->pData[_i_]) != ((Cube2)->pData[_i_]))\
+              { Res = 0; break; }\
+}
+
+#define Mvc_Cube1BitLess( Res, Cube1, Cube2 )\
+  (Res = (((Cube1)->pData[0]) <  ((Cube2)->pData[0])))
+#define Mvc_Cube2BitLess( Res, Cube1, Cube2 )\
+ (Res = ((((Cube1)->pData[0]) <  ((Cube2)->pData[0])) ||\
+        ((((Cube1)->pData[0]) == ((Cube2)->pData[0])) && (((Cube1)->pData[1]) <  ((Cube2)->pData[1])))))
+#define Mvc_CubeNBitLess( Res, Cube1, Cube2 )\
+{\
+    int _i_; Res = 1;\
+    for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+         if (((Cube1)->pData[_i_]) >= ((Cube2)->pData[_i_]))\
+             { Res = 0; break; }\
+}        
+
+#define Mvc_Cube1BitMore( Res, Cube1, Cube2 )\
+  (Res = (((Cube1)->pData[0]) >  ((Cube2)->pData[0])))
+#define Mvc_Cube2BitMore( Res, Cube1, Cube2 )\
+ (Res = ((((Cube1)->pData[0]) >  ((Cube2)->pData[0])) ||\
+        ((((Cube1)->pData[0]) == ((Cube2)->pData[0])) && (((Cube1)->pData[1]) >  ((Cube2)->pData[1])))))
+#define Mvc_CubeNBitMore( Res, Cube1, Cube2 )\
+{\
+    int _i_; Res = 1;\
+    for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+        if (((Cube1)->pData[_i_]) <= ((Cube2)->pData[_i_]))\
+             { Res = 0; break; }\
+}         
+
+#define Mvc_Cube1BitNotImpl( Res, Cube1, Cube2 )\
+  (Res = (((Cube1)->pData[0])  & ~((Cube2)->pData[0])))
+#define Mvc_Cube2BitNotImpl( Res, Cube1, Cube2 )\
+ (Res = ((((Cube1)->pData[0]) & ~((Cube2)->pData[0])) ||\
+         (((Cube1)->pData[1]) & ~((Cube2)->pData[1]))))
+#define Mvc_CubeNBitNotImpl( Res, Cube1, Cube2 )\
+{\
+    int _i_; Res = 0;\
+    for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+        if (((Cube1)->pData[_i_]) & ~((Cube2)->pData[_i_]))\
+            { Res = 1; break; }\
+}         
+
+#define Mvc_Cube1BitDisjoint( Res, Cube1, Cube2 )\
+  (Res = ((((Cube1)->pData[0]) &  ((Cube2)->pData[0])) == 0 ))
+#define Mvc_Cube2BitDisjoint( Res, Cube1, Cube2 )\
+ (Res = (((((Cube1)->pData[0]) &  ((Cube2)->pData[0])) == 0 ) &&\
+         ((((Cube1)->pData[1]) &  ((Cube2)->pData[1])) == 0 )))
+#define Mvc_CubeNBitDisjoint( Res, Cube1, Cube2 )\
+{\
+    int _i_; Res = 1;\
+    for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+        if (((Cube1)->pData[_i_]) & ((Cube2)->pData[_i_]))\
+             { Res = 0; break; }\
+}             
+
+#define Mvc_Cube1BitEqualUnderMask( Res, Cube1, Cube2, Mask )\
+  (Res = ((((Cube1)->pData[0]) & ((Mask)->pData[0])) == (((Cube2)->pData[0]) & ((Mask)->pData[0]))))
+#define Mvc_Cube2BitEqualUnderMask( Res, Cube1, Cube2, Mask )\
+ (Res = (((((Cube1)->pData[0]) & ((Mask)->pData[0])) == (((Cube2)->pData[0]) & ((Mask)->pData[0])))  &&\
+         ((((Cube1)->pData[1]) & ((Mask)->pData[1])) == (((Cube2)->pData[1]) & ((Mask)->pData[1])))))
+#define Mvc_CubeNBitEqualUnderMask( Res, Cube1, Cube2, Mask )\
+{\
+    int _i_; Res = 1;\
+    for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+        if ((((Cube1)->pData[_i_]) & ((Mask)->pData[_i_])) != (((Cube2)->pData[_i_]) & ((Mask)->pData[_i_])))\
+            { Res = 0; break; }\
+}               
+
+#define Mvc_Cube1BitEqualOutsideMask( Res, Cube1, Cube2, Mask )\
+  (Res = ((((Cube1)->pData[0]) | ((Mask)->pData[0])) == (((Cube2)->pData[0]) | ((Mask)->pData[0]))))
+#define Mvc_Cube2BitEqualOutsideMask( Res, Cube1, Cube2, Mask )\
+ (Res = (((((Cube1)->pData[0]) | ((Mask)->pData[0])) == (((Cube2)->pData[0]) | ((Mask)->pData[0])))  &&\
+         ((((Cube1)->pData[1]) | ((Mask)->pData[1])) == (((Cube2)->pData[1]) | ((Mask)->pData[1])))))
+#define Mvc_CubeNBitEqualOutsideMask( Res, Cube1, Cube2, Mask )\
+{\
+    int _i_; Res = 1;\
+    for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+        if ((((Cube1)->pData[_i_]) | ((Mask)->pData[_i_])) != (((Cube2)->pData[_i_]) | ((Mask)->pData[_i_])))\
+            { Res = 0; break; }\
+}              
+
+#define Mvc_Cube1BitIntersectUnderMask( Res, Cube1, Cube2, Mask)\
+  (Res = ((((Cube1)->pData[0]) & ((Cube2)->pData[0]) & ((Mask)->pData[0])) > 0))
+#define Mvc_Cube2BitIntersectUnderMask( Res, Cube1, Cube2, Mask)\
+ (Res = (((((Cube1)->pData[0]) & ((Cube2)->pData[0]) & ((Mask)->pData[0])) > 0) ||\
+         ((((Cube1)->pData[1]) & ((Cube2)->pData[1]) & ((Mask)->pData[1])) > 0)))
+#define Mvc_CubeNBitIntersectUnderMask( Res, Cube1, Cube2, Mask)\
+{\
+    int _i_; Res = 0;\
+    for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+        if (((Cube1)->pData[_i_]) & ((Cube2)->pData[_i_]) & ((Mask)->pData[_i_]))\
+           { Res = 1; break; }\
+}       
+
+#define Mvc_Cube1BitNotImplUnderMask( Res, Cube1, Cube2, Mask )\
+  (Res = (((Mask)->pData[0]) & ((Cube1)->pData[0])  & ~((Cube2)->pData[0])))
+#define Mvc_Cube2BitNotImplUnderMask( Res, Cube1, Cube2, Mask )\
+ (Res = ((((Mask)->pData[0]) & ((Cube1)->pData[0]) & ~((Cube2)->pData[0])) ||\
+         (((Mask)->pData[1]) & ((Cube1)->pData[1]) & ~((Cube2)->pData[1]))))
+#define Mvc_CubeNBitNotImplUnderMask( Res, Cube1, Cube2, Mask )\
+{\
+    int _i_; Res = 0;\
+    for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+        if (((Mask)->pData[_i_]) & ((Cube1)->pData[_i_]) & ~((Cube2)->pData[_i_]))\
+            { Res = 1; break; }\
+}         
+
+// the following macros make no assumption about the cube's bitset size
+#define Mvc_CubeBitClean( Cube )\
+    if ( Mvc_Cube1Words(Cube) )      { Mvc_Cube1BitClean( Cube ); }\
+    else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitClean( Cube ); }\
+    else                             { Mvc_CubeNBitClean( Cube ); }
+#define Mvc_CubeBitFill( Cube )\
+    if ( Mvc_Cube1Words(Cube) )      { Mvc_Cube1BitFill( Cube ); }\
+    else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitFill( Cube ); }\
+    else                             { Mvc_CubeNBitFill( Cube ); }
+#define Mvc_CubeBitNot( Cube )\
+    if ( Mvc_Cube1Words(Cube) )      { Mvc_Cube1BitNot( Cube ); }\
+    else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitNot( Cube ); }\
+    else                             { Mvc_CubeNBitNot( Cube ); }
+#define Mvc_CubeBitCopy( Cube1, Cube2 )\
+    if ( Mvc_Cube1Words(Cube1) )     { Mvc_Cube1BitCopy( Cube1, Cube2 ); }\
+    else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitCopy( Cube1, Cube2 ); }\
+    else                             { Mvc_CubeNBitCopy( Cube1, Cube2 ); }
+#define Mvc_CubeBitOr( CubeR, Cube1, Cube2 )\
+    if ( Mvc_Cube1Words(Cube1) )     { Mvc_Cube1BitOr( CubeR, Cube1, Cube2 ); }\
+    else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitOr( CubeR, Cube1, Cube2 ); }\
+    else                             { Mvc_CubeNBitOr( CubeR, Cube1, Cube2 ); }
+#define Mvc_CubeBitExor( CubeR, Cube1, Cube2 )\
+    if ( Mvc_Cube1Words(Cube1) )     { Mvc_Cube1BitExor( CubeR, Cube1, Cube2 ); }\
+    else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitExor( CubeR, Cube1, Cube2 ); }\
+    else                             { Mvc_CubeNBitExor( CubeR, Cube1, Cube2 ); }
+#define Mvc_CubeBitAnd( CubeR, Cube1, Cube2 )\
+    if ( Mvc_Cube1Words(Cube1) )     { Mvc_Cube1BitAnd( CubeR, Cube1, Cube2 ); }\
+    else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitAnd( CubeR, Cube1, Cube2 ); }\
+    else                             { Mvc_CubeNBitAnd( CubeR, Cube1, Cube2 ); }
+#define Mvc_CubeBitSharp( CubeR, Cube1, Cube2 )\
+    if ( Mvc_Cube1Words(Cube1) )     { Mvc_Cube1BitSharp( CubeR, Cube1, Cube2 ); }\
+    else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitSharp( CubeR, Cube1, Cube2 ); }\
+    else                             { Mvc_CubeNBitSharp( CubeR, Cube1, Cube2 ); }
+#define Mvc_CubeBitEmpty( Res, Cube )\
+    if ( Mvc_Cube1Words(Cube) )      { Mvc_Cube1BitEmpty( Res, Cube ); }\
+    else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitEmpty( Res, Cube ); }\
+    else                             { Mvc_CubeNBitEmpty( Res, Cube ); }
+#define Mvc_CubeBitEqual( Res, Cube1, Cube2 )\
+    if ( Mvc_Cube1Words(Cube1) )     { Mvc_Cube1BitEqual( Res, Cube1, Cube2 ); }\
+    else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitEqual( Res, Cube1, Cube2 ); }\
+    else                             { Mvc_CubeNBitEqual( Res, Cube1, Cube2 ); }
+#define Mvc_CubeBitLess( Res, Cube1, Cube2 )\
+    if ( Mvc_Cube1Words(Cube1) )     { Mvc_Cube1BitLess( Res, Cube1, Cube2 ); }\
+    else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitLess( Res, Cube1, Cube2 ); }\
+    else                             { Mvc_CubeNBitLess( Res, Cube1, Cube2 ); }
+#define Mvc_CubeBitMore( Res, Cube1, Cube2 )\
+    if ( Mvc_Cube1Words(Cube1) )     { Mvc_Cube1BitMore( Res, Cube1, Cube2 ); }\
+    else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitMore( Res, Cube1, Cube2 ); }\
+    else                             { Mvc_CubeNBitMore( Res, Cube1, Cube2 ); }
+#define Mvc_CubeBitNotImpl( Res, Cube1, Cube2 )\
+    if ( Mvc_Cube1Words(Cube1) )     { Mvc_Cube1BitNotImpl( Res, Cube1, Cube2 ); }\
+    else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitNotImpl( Res, Cube1, Cube2 ); }\
+    else                             { Mvc_CubeNBitNotImpl( Res, Cube1, Cube2 ); }
+#define Mvc_CubeBitDisjoint( Res, Cube1, Cube2 )\
+    if ( Mvc_Cube1Words(Cube1) )     { Mvc_Cube1BitDisjoint( Res, Cube1, Cube2 ); }\
+    else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitDisjoint( Res, Cube1, Cube2 ); }\
+    else                             { Mvc_CubeNBitDisjoint( Res, Cube1, Cube2 ); }
+#define Mvc_CubeBitEqualUnderMask( Res, Cube1, Cube2, Mask )\
+    if ( Mvc_Cube1Words(Cube1) )     { Mvc_Cube1BitEqualUnderMask( Res, Cube1, Cube2, Mask ); }\
+    else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitEqualUnderMask( Res, Cube1, Cube2, Mask ); }\
+    else                             { Mvc_CubeNBitEqualUnderMask( Res, Cube1, Cube2, Mask ); }
+#define Mvc_CubeBitEqualOutsideMask( Res, Cube1, Cube2, Mask )\
+    if ( Mvc_Cube1Words(Cube1) )     { Mvc_Cube1BitEqualOutsideMask( Res, Cube1, Cube2, Mask ); }\
+    else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitEqualOutsideMask( Res, Cube1, Cube2, Mask ); }\
+    else                             { Mvc_CubeNBitEqualOutsideMask( Res, Cube1, Cube2, Mask ); }
+#define Mvc_CubeBitIntersectUnderMask( Res, Cube1, Cube2, Mask )\
+    if ( Mvc_Cube1Words(Cube1) )     { Mvc_Cube1BitIntersectUnderMask( Res, Cube1, Cube2, Mask ); }\
+    else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitIntersectUnderMask( Res, Cube1, Cube2, Mask ); }\
+    else                             { Mvc_CubeNBitIntersectUnderMask( Res, Cube1, Cube2, Mask ); }
+#define Mvc_CubeBitNotImplUnderMask( Res, Cube1, Cube2, Mask )\
+    if ( Mvc_Cube1Words(Cube1) )     { Mvc_Cube1BitNotImplUnderMask( Res, Cube1, Cube2, Mask ); }\
+    else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitNotImplUnderMask( Res, Cube1, Cube2, Mask ); }\
+    else                             { Mvc_CubeNBitNotImplUnderMask( Res, Cube1, Cube2, Mask ); }
+
+
+// managing linked lists
+#define Mvc_ListAddCubeHead( pList, pCube )\
+    {\
+        if ( pList->pHead == NULL )\
+        {\
+            Mvc_CubeSetNext( pCube, NULL );\
+            pList->pHead = pCube;\
+            pList->pTail = pCube;\
+        }\
+        else\
+        {\
+            Mvc_CubeSetNext( pCube, pList->pHead );\
+            pList->pHead = pCube;\
+        }\
+        pList->nItems++;\
+    }
+#define Mvc_ListAddCubeTail( pList, pCube )\
+    {\
+        if ( pList->pHead == NULL )\
+            pList->pHead = pCube;\
+        else\
+            Mvc_CubeSetNext( pList->pTail, pCube );\
+        pList->pTail    = pCube;\
+        Mvc_CubeSetNext( pCube, NULL );\
+        pList->nItems++;\
+    }
+#define Mvc_ListDeleteCube( pList, pPrev, pCube )\
+{\
+    if ( pPrev == NULL )\
+        pList->pHead = pCube->pNext;\
+    else\
+        pPrev->pNext = pCube->pNext;\
+    if ( pList->pTail == pCube )\
+    {\
+        assert( pCube->pNext == NULL );\
+        pList->pTail = pPrev;\
+    }\
+    pList->nItems--;\
+}
+
+// managing linked lists inside the cover
+#define Mvc_CoverAddCubeHead( pCover, pCube )\
+{\
+    Mvc_List_t * pList = &pCover->lCubes;\
+    Mvc_ListAddCubeHead( pList, pCube );\
+}
+#define Mvc_CoverAddCubeTail( pCover, pCube )\
+{\
+    Mvc_List_t * pList = &pCover->lCubes;\
+    Mvc_ListAddCubeTail( pList, pCube );\
+}
+#define Mvc_CoverDeleteCube( pCover, pPrev, pCube )\
+{\
+    Mvc_List_t * pList = &pCover->lCubes;\
+    Mvc_ListDeleteCube( pList, pPrev, pCube );\
+}
+
+
+
+
+
+
+// iterator through the cubes in the cube list
+#define Mvc_ListForEachCube( List, Cube )\
+    for ( Cube = List->pHead;\
+          Cube;\
+          Cube = Cube->pNext )
+#define Mvc_ListForEachCubeSafe( List, Cube, Cube2 )\
+    for ( Cube = List->pHead, Cube2 = (Cube? Cube->pNext: NULL);\
+          Cube;\
+          Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) )
+
+// iterator through cubes in the cover
+#define Mvc_CoverForEachCube( Cover, Cube )\
+    for ( Cube = (Cover)->lCubes.pHead;\
+          Cube;\
+          Cube = Cube->pNext )
+#define Mvc_CoverForEachCubeWithIndex( Cover, Cube, Index )\
+    for ( Index = 0, Cube = (Cover)->lCubes.pHead;\
+          Cube;\
+          Index++, Cube = Cube->pNext )
+#define Mvc_CoverForEachCubeSafe( Cover, Cube, Cube2 )\
+    for ( Cube = (Cover)->lCubes.pHead, Cube2 = (Cube? Cube->pNext: NULL);\
+          Cube;\
+          Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) )
+
+// iterator which starts from the given cube
+#define Mvc_CoverForEachCubeStart( Start, Cube )\
+    for ( Cube = Start;\
+          Cube;\
+          Cube = Cube->pNext )
+#define Mvc_CoverForEachCubeStartSafe( Start, Cube, Cube2 )\
+    for ( Cube = Start, Cube2 = (Cube? Cube->pNext: NULL);\
+          Cube;\
+          Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) )
+
+
+// iterator through literals of the cube
+#define Mvc_CubeForEachBit( Cover, Cube, iBit, Value )\
+    for ( iBit = 0;\
+          iBit < Cover->nBits && ((Value = Mvc_CubeBitValue(Cube,iBit))>=0);\
+          iBit++ )
+// iterator through values of binary variables
+#define Mvc_CubeForEachVarValue( Cover, Cube, iVar, Value )\
+    for ( iVar = 0;\
+          iVar < Cover->nBits/2 && (Value = Mvc_CubeVarValue(Cube,iVar));\
+          iVar++ )
+
+
+// macros which work with memory
+// MEM_ALLOC: allocate the given number (Size) of items of type (Type)
+// MEM_FREE:  deallocate the pointer (Pointer) to the given number (Size) of items of type (Type)
+#define MEM_ALLOC( Manager, Type, Size )          ((Type *)ABC_ALLOC( char, (Size) * sizeof(Type) ))
+#define MEM_FREE( Manager, Type, Size, Pointer )  if ( Pointer ) { ABC_FREE(Pointer); Pointer = NULL; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== mvcApi.c ====================================================*/
+extern int              Mvc_CoverReadWordNum( Mvc_Cover_t * pCover );
+extern int              Mvc_CoverReadBitNum( Mvc_Cover_t * pCover );
+extern int              Mvc_CoverReadCubeNum( Mvc_Cover_t * pCover );
+extern Mvc_Cube_t *     Mvc_CoverReadCubeHead( Mvc_Cover_t * pCover );
+extern Mvc_Cube_t *     Mvc_CoverReadCubeTail( Mvc_Cover_t * pCover );
+extern Mvc_List_t *     Mvc_CoverReadCubeList( Mvc_Cover_t * pCover );
+extern int              Mvc_ListReadCubeNum( Mvc_List_t * pList );
+extern Mvc_Cube_t *     Mvc_ListReadCubeHead( Mvc_List_t * pList );
+extern Mvc_Cube_t *     Mvc_ListReadCubeTail( Mvc_List_t * pList );
+extern void             Mvc_CoverSetCubeNum( Mvc_Cover_t * pCover,int nItems );
+extern void             Mvc_CoverSetCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void             Mvc_CoverSetCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void             Mvc_CoverSetCubeList( Mvc_Cover_t * pCover, Mvc_List_t * pList );
+extern int              Mvc_CoverIsEmpty( Mvc_Cover_t * pCover );
+extern int              Mvc_CoverIsTautology( Mvc_Cover_t * pCover );
+extern int              Mvc_CoverIsBinaryBuffer( Mvc_Cover_t * pCover );
+extern void             Mvc_CoverMakeEmpty( Mvc_Cover_t * pCover );
+extern void             Mvc_CoverMakeTautology( Mvc_Cover_t * pCover );
+extern Mvc_Cover_t *    Mvc_CoverCreateEmpty( Mvc_Cover_t * pCover );
+extern Mvc_Cover_t *    Mvc_CoverCreateTautology( Mvc_Cover_t * pCover );
+/*=== mvcCover.c ====================================================*/
+extern Mvc_Cover_t *    Mvc_CoverAlloc( Mvc_Manager_t * pMem, int nBits );
+extern Mvc_Cover_t *    Mvc_CoverCreateConst( Mvc_Manager_t * pMem, int nBits, int  Phase );
+extern Mvc_Cover_t *    Mvc_CoverClone( Mvc_Cover_t * pCover );
+extern Mvc_Cover_t *    Mvc_CoverDup( Mvc_Cover_t * pCover );
+extern void             Mvc_CoverFree( Mvc_Cover_t * pCover );
+extern void             Mvc_CoverAllocateMask( Mvc_Cover_t * pCover );
+extern void             Mvc_CoverAllocateArrayLits( Mvc_Cover_t * pCover );
+extern void             Mvc_CoverAllocateArrayCubes( Mvc_Cover_t * pCover );
+extern void             Mvc_CoverDeallocateMask( Mvc_Cover_t * pCover );
+extern void             Mvc_CoverDeallocateArrayLits( Mvc_Cover_t * pCover );
+/*=== mvcCube.c ====================================================*/
+extern Mvc_Cube_t *     Mvc_CubeAlloc( Mvc_Cover_t * pCover );
+extern Mvc_Cube_t *     Mvc_CubeDup( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void             Mvc_CubeFree( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void             Mvc_CubeBitRemoveDcs( Mvc_Cube_t * pCube );
+/*=== mvcCompare.c ====================================================*/
+extern int              Mvc_CubeCompareInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask );
+extern int              Mvc_CubeCompareSizeAndInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask );
+extern int              Mvc_CubeCompareIntUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask );
+extern int              Mvc_CubeCompareIntOutsideMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask );
+extern int              Mvc_CubeCompareIntOutsideAndUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask );
+/*=== mvcDd.c ====================================================*/
+/*
+extern DdNode *         Mvc_CoverConvertToBdd( DdManager * dd, Mvc_Cover_t * pCover );
+extern DdNode *         Mvc_CoverConvertToZdd( DdManager * dd, Mvc_Cover_t * pCover );
+extern DdNode *         Mvc_CoverConvertToZdd2( DdManager * dd, Mvc_Cover_t * pCover );
+extern DdNode *         Mvc_CubeConvertToBdd( DdManager * dd, Mvc_Cube_t * pCube );
+extern DdNode *         Mvc_CubeConvertToZdd( DdManager * dd, Mvc_Cube_t * pCube );
+extern DdNode *         Mvc_CubeConvertToZdd2( DdManager * dd, Mvc_Cube_t * pCube );
+*/
+/*=== mvcDivisor.c ====================================================*/
+extern Mvc_Cover_t *    Mvc_CoverDivisor( Mvc_Cover_t * pCover );
+/*=== mvcDivide.c ====================================================*/
+extern void             Mvc_CoverDivide( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem );
+extern void             Mvc_CoverDivideInternal( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem );
+extern void             Mvc_CoverDivideByLiteral( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem );
+extern void             Mvc_CoverDivideByCube( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem );
+extern void             Mvc_CoverDivideByLiteralQuo( Mvc_Cover_t * pCover, int iLit );
+/*=== mvcList.c ====================================================*/
+// these functions are available as macros
+extern void             Mvc_ListAddCubeHead_( Mvc_List_t * pList, Mvc_Cube_t * pCube );
+extern void             Mvc_ListAddCubeTail_( Mvc_List_t * pList, Mvc_Cube_t * pCube );
+extern void             Mvc_ListDeleteCube_( Mvc_List_t * pList, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube );
+extern void             Mvc_CoverAddCubeHead_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void             Mvc_CoverAddCubeTail_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void             Mvc_CoverDeleteCube_( Mvc_Cover_t * pCover, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube );
+extern void             Mvc_CoverAddDupCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void             Mvc_CoverAddDupCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+// other functions
+extern void             Mvc_CoverAddLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void             Mvc_CoverDeleteLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void             Mvc_CoverList2Array( Mvc_Cover_t * pCover );
+extern void             Mvc_CoverArray2List( Mvc_Cover_t * pCover );
+extern Mvc_Cube_t *     Mvc_ListGetTailFromHead( Mvc_Cube_t * pHead );
+/*=== mvcPrint.c ====================================================*/
+extern void             Mvc_CoverPrint( Mvc_Cover_t * pCover );
+extern void             Mvc_CubePrint( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void             Mvc_CoverPrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover );
+extern void             Mvc_CubePrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+/*=== mvcSort.c ====================================================*/
+extern void             Mvc_CoverSort( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) );
+/*=== mvcUtils.c ====================================================*/
+extern void             Mvc_CoverSupport( Mvc_Cover_t * pCover, Mvc_Cube_t * pSupp );
+extern int              Mvc_CoverSupportSizeBinary( Mvc_Cover_t * pCover );
+extern int              Mvc_CoverSupportVarBelongs( Mvc_Cover_t * pCover, int iVar );
+extern void             Mvc_CoverCommonCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pComCube );
+extern int              Mvc_CoverIsCubeFree( Mvc_Cover_t * pCover );
+extern void             Mvc_CoverMakeCubeFree( Mvc_Cover_t * pCover );
+extern Mvc_Cover_t *    Mvc_CoverCommonCubeCover( Mvc_Cover_t * pCover );
+extern int              Mvc_CoverCheckSuppContainment( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 );
+extern int              Mvc_CoverSetCubeSizes( Mvc_Cover_t * pCover );
+extern int              Mvc_CoverGetCubeSize( Mvc_Cube_t * pCube );
+extern int              Mvc_CoverCountCubePairDiffs( Mvc_Cover_t * pCover, unsigned char pDiffs[] );
+extern Mvc_Cover_t *    Mvc_CoverRemap( Mvc_Cover_t * pCover, int * pVarsRem, int nVarsRem );
+extern void             Mvc_CoverInverse( Mvc_Cover_t * pCover );
+extern Mvc_Cover_t *    Mvc_CoverRemoveDontCareLits( Mvc_Cover_t * pCover );
+extern Mvc_Cover_t *    Mvc_CoverCofactor( Mvc_Cover_t * pCover, int iValue, int iValueOther );
+extern Mvc_Cover_t *    Mvc_CoverFlipVar( Mvc_Cover_t * pCover, int iValue0, int iValue1 );
+extern Mvc_Cover_t *    Mvc_CoverUnivQuantify( Mvc_Cover_t * p, int iValueA0, int iValueA1, int iValueB0, int iValueB1 );
+extern Mvc_Cover_t **   Mvc_CoverCofactors( Mvc_Data_t * pData, Mvc_Cover_t * pCover, int iVar );
+extern int              Mvr_CoverCountLitsWithValue( Mvc_Data_t * pData, Mvc_Cover_t * pCover, int iVar, int iValue );
+//extern Mvc_Cover_t *    Mvc_CoverCreateExpanded( Mvc_Cover_t * pCover, Vm_VarMap_t * pVmNew );
+extern Mvc_Cover_t *    Mvc_CoverTranspose( Mvc_Cover_t * pCover );
+extern int              Mvc_UtilsCheckUnusedZeros( Mvc_Cover_t * pCover );
+/*=== mvcLits.c ====================================================*/
+extern int              Mvc_CoverAnyLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask );
+extern int              Mvc_CoverBestLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask );
+extern int              Mvc_CoverWorstLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask );
+extern Mvc_Cover_t *    Mvc_CoverBestLiteralCover( Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple );
+extern int              Mvc_CoverFirstCubeFirstLit( Mvc_Cover_t * pCover );
+extern int              Mvc_CoverCountLiterals( Mvc_Cover_t * pCover );
+extern int              Mvc_CoverIsOneLiteral( Mvc_Cover_t * pCover );
+/*=== mvcOpAlg.c ====================================================*/
+extern Mvc_Cover_t *    Mvc_CoverAlgebraicMultiply( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 );
+extern Mvc_Cover_t *    Mvc_CoverAlgebraicSubtract( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 );
+extern int              Mvc_CoverAlgebraicEqual( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 );
+/*=== mvcOpBool.c ====================================================*/
+extern Mvc_Cover_t *    Mvc_CoverBooleanOr( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 );
+extern Mvc_Cover_t *    Mvc_CoverBooleanAnd( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 );
+extern int              Mvc_CoverBooleanEqual( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 );
+
+/*=== mvcContain.c ====================================================*/
+extern int              Mvc_CoverContain( Mvc_Cover_t * pCover );
+/*=== mvcTau.c ====================================================*/
+extern int              Mvc_CoverTautology( Mvc_Data_t * p, Mvc_Cover_t * pCover );
+/*=== mvcCompl.c ====================================================*/
+extern Mvc_Cover_t *    Mvc_CoverComplement( Mvc_Data_t * p, Mvc_Cover_t * pCover );
+/*=== mvcSharp.c ====================================================*/
+extern Mvc_Cover_t *    Mvc_CoverSharp( Mvc_Data_t * p, Mvc_Cover_t * pA, Mvc_Cover_t * pB );
+extern int              Mvc_CoverDist0Cubes( Mvc_Data_t * pData, Mvc_Cube_t * pA, Mvc_Cube_t * pB );
+extern void             Mvc_CoverIntersectCubes( Mvc_Data_t * pData, Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 );
+extern int              Mvc_CoverIsIntersecting( Mvc_Data_t * pData, Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 );
+extern void             Mvc_CoverAppendCubes( Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 );
+extern void             Mvc_CoverCopyAndAppendCubes( Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 );
+extern void             Mvc_CoverRemoveCubes( Mvc_Cover_t * pC );
+
+/*=== mvcReshape.c ====================================================*/
+extern void             Mvc_CoverMinimizeByReshape( Mvc_Data_t * pData, Mvc_Cover_t * pCover );
+
+/*=== mvcMerge.c ====================================================*/
+extern void             Mvc_CoverDist1Merge( Mvc_Data_t * p, Mvc_Cover_t * pCover );
+
+/*=== mvcData.c ====================================================*/
+//extern Mvc_Data_t *     Mvc_CoverDataAlloc( Vm_VarMap_t * pVm, Mvc_Cover_t * pCover );
+//extern void             Mvc_CoverDataFree( Mvc_Data_t * p, Mvc_Cover_t * pCover );
+
+/*=== mvcMan.c ====================================================*/
+extern void             Mvc_ManagerFree( Mvc_Manager_t * p );
+extern Mvc_Manager_t *  Mvc_ManagerStart();
+extern Mvc_Manager_t *  Mvc_ManagerAllocCover();
+extern Mvc_Manager_t *  Mvc_ManagerAllocCube( int nWords );
+extern Mvc_Manager_t *  Mvc_ManagerFreeCover( Mvc_Cover_t * pCover );
+extern Mvc_Manager_t *  Mvc_ManagerFreeCube( Mvc_Cover_t * pCube, int nWords );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/mvc/mvcApi.c b/abc-build/src/misc/mvc/mvcApi.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/mvcApi.c
@@ -0,0 +1,238 @@
+/**CFile****************************************************************
+
+  FileName    [mvcApi.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    []
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: mvcApi.c,v 1.4 2003/04/03 06:31:48 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int          Mvc_CoverReadWordNum( Mvc_Cover_t * pCover )   { return pCover->nWords;         }
+int          Mvc_CoverReadBitNum( Mvc_Cover_t * pCover )    { return pCover->nBits;          }
+int          Mvc_CoverReadCubeNum( Mvc_Cover_t * pCover )   { return pCover->lCubes.nItems; }
+Mvc_Cube_t * Mvc_CoverReadCubeHead( Mvc_Cover_t * pCover )  { return pCover->lCubes.pHead;  }
+Mvc_Cube_t * Mvc_CoverReadCubeTail( Mvc_Cover_t * pCover )  { return pCover->lCubes.pTail;  }
+Mvc_List_t * Mvc_CoverReadCubeList( Mvc_Cover_t * pCover )  { return &pCover->lCubes;        }
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int          Mvc_ListReadCubeNum( Mvc_List_t * pList )   { return pList->nItems; }
+Mvc_Cube_t * Mvc_ListReadCubeHead( Mvc_List_t * pList )  { return pList->pHead;  }
+Mvc_Cube_t * Mvc_ListReadCubeTail( Mvc_List_t * pList )  { return pList->pTail;  }
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void         Mvc_CoverSetCubeNum( Mvc_Cover_t * pCover,int nItems )           { pCover->lCubes.nItems = nItems; }
+void         Mvc_CoverSetCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { pCover->lCubes.pHead = pCube;   }
+void         Mvc_CoverSetCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { pCover->lCubes.pTail = pCube;   }
+void         Mvc_CoverSetCubeList( Mvc_Cover_t * pCover, Mvc_List_t * pList ) { pCover->lCubes = *pList;        }
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverIsEmpty( Mvc_Cover_t * pCover )
+{
+    return Mvc_CoverReadCubeNum(pCover) == 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverIsTautology( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCube;
+    int iBit, Value;
+
+    if ( Mvc_CoverReadCubeNum(pCover) != 1 )
+        return 0;
+
+    pCube = Mvc_CoverReadCubeHead( pCover );
+    Mvc_CubeForEachBit( pCover, pCube, iBit, Value )
+        if ( Value == 0 )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the cover is a binary buffer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverIsBinaryBuffer( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCube;
+    if ( pCover->nBits != 2 )
+        return 0;
+    if ( Mvc_CoverReadCubeNum(pCover) != 1 )
+        return 0;
+    pCube = pCover->lCubes.pHead;
+    if ( Mvc_CubeBitValue(pCube, 0) == 0 && Mvc_CubeBitValue(pCube, 1) == 1 )
+        return 1;
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverMakeEmpty( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCube, * pCube2;
+    Mvc_CoverForEachCubeSafe( pCover, pCube, pCube2 )
+        Mvc_CubeFree( pCover, pCube );
+    pCover->lCubes.nItems = 0;
+    pCover->lCubes.pHead = NULL;
+    pCover->lCubes.pTail = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverMakeTautology( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCubeNew;
+    Mvc_CoverMakeEmpty( pCover );
+    pCubeNew = Mvc_CubeAlloc( pCover );
+    Mvc_CubeBitFill( pCubeNew );
+    Mvc_CoverAddCubeTail( pCover, pCubeNew );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverCreateEmpty( Mvc_Cover_t * pCover )
+{
+    Mvc_Cover_t * pCoverNew;
+    pCoverNew = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
+    return pCoverNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverCreateTautology( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCubeNew;
+    Mvc_Cover_t * pCoverNew;
+    pCoverNew = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
+    pCubeNew = Mvc_CubeAlloc( pCoverNew );
+    Mvc_CubeBitFill( pCubeNew );
+    Mvc_CoverAddCubeTail( pCoverNew, pCubeNew );
+    return pCoverNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/mvc/mvcCompare.c b/abc-build/src/misc/mvc/mvcCompare.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/mvcCompare.c
@@ -0,0 +1,374 @@
+/**CFile****************************************************************
+
+  FileName    [mvcCompare.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Various cube comparison functions.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: mvcCompare.c,v 1.5 2003/04/03 23:25:41 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Compares two cubes according to their integer value.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CubeCompareInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask )
+{
+    if ( Mvc_Cube1Words(pC1) )
+    {
+        if ( pC1->pData[0] < pC2->pData[0] )
+            return -1;
+        if ( pC1->pData[0] > pC2->pData[0] )
+            return 1;
+        return 0;
+    }
+    else if ( Mvc_Cube2Words(pC1) )
+    {
+        if ( pC1->pData[1] < pC2->pData[1] )
+            return -1;
+        if ( pC1->pData[1] > pC2->pData[1] )
+            return 1;
+        if ( pC1->pData[0] < pC2->pData[0] )
+            return -1;
+        if ( pC1->pData[0] > pC2->pData[0] )
+            return 1;
+        return 0;
+    }
+    else                            
+    {
+        int i = Mvc_CubeReadLast(pC1);
+        for(; i >= 0; i--)
+        {
+            if ( pC1->pData[i] < pC2->pData[i] )
+                return -1;
+            if ( pC1->pData[i] > pC2->pData[i] )
+                return 1;
+        }
+        return 0;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the cubes (1) by size, (2) by integer value.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CubeCompareSizeAndInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask )
+{
+    // compare the cubes by size
+    if ( Mvc_CubeReadSize( pC1 ) < Mvc_CubeReadSize( pC2 ) )
+        return 1;
+    if ( Mvc_CubeReadSize( pC1 ) > Mvc_CubeReadSize( pC2 ) )
+        return -1;
+    // the cubes have the same size
+
+    // compare the cubes as integers
+    if ( Mvc_Cube1Words( pC1 ) )
+    {
+        if ( pC1->pData[0] < pC2->pData[0] )
+            return -1;
+        if ( pC1->pData[0] > pC2->pData[0] )
+            return 1;
+        return 0;
+    }
+    else if ( Mvc_Cube2Words( pC1 ) )
+    {
+        if ( pC1->pData[1] < pC2->pData[1] )
+            return -1;
+        if ( pC1->pData[1] > pC2->pData[1] )
+            return 1;
+        if ( pC1->pData[0] < pC2->pData[0] )
+            return -1;
+        if ( pC1->pData[0] > pC2->pData[0] )
+            return 1;
+        return 0;
+    }
+    else                            
+    {
+        int i = Mvc_CubeReadLast( pC1 );
+        for(; i >= 0; i--)
+        {
+            if ( pC1->pData[i] < pC2->pData[i] )
+                return -1;
+            if ( pC1->pData[i] > pC2->pData[i] )
+                return 1;
+        }
+        return 0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares two cubes under the mask.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CubeCompareIntUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask )
+{
+    unsigned uBits1, uBits2;
+
+    // compare the cubes under the mask
+    if ( Mvc_Cube1Words(pC1) )
+    {
+        uBits1 = pC1->pData[0] & pMask->pData[0];
+        uBits2 = pC2->pData[0] & pMask->pData[0];
+        if ( uBits1 < uBits2 )
+            return -1;
+        if ( uBits1 > uBits2 )
+            return 1;
+        // cubes are equal
+        return 0;
+    }
+    else if ( Mvc_Cube2Words(pC1) )
+    {
+        uBits1 = pC1->pData[1] & pMask->pData[1];
+        uBits2 = pC2->pData[1] & pMask->pData[1];
+        if ( uBits1 < uBits2 )
+            return -1;
+        if ( uBits1 > uBits2 )
+            return 1;
+        uBits1 = pC1->pData[0] & pMask->pData[0];
+        uBits2 = pC2->pData[0] & pMask->pData[0];
+        if ( uBits1 < uBits2 )
+            return -1;
+        if ( uBits1 > uBits2 )
+            return 1;
+        return 0;
+    }
+    else                            
+    {
+        int i = Mvc_CubeReadLast(pC1);
+        for(; i >= 0; i--)
+        {
+            uBits1 = pC1->pData[i] & pMask->pData[i];
+            uBits2 = pC2->pData[i] & pMask->pData[i];
+            if ( uBits1 < uBits2 )
+                return -1;
+            if ( uBits1 > uBits2 )
+                return 1;
+        }
+        return 0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares two cubes under the mask.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CubeCompareIntOutsideMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask )
+{
+    unsigned uBits1, uBits2;
+
+    // compare the cubes under the mask
+    if ( Mvc_Cube1Words(pC1) )
+    {
+        uBits1 = pC1->pData[0] | pMask->pData[0];
+        uBits2 = pC2->pData[0] | pMask->pData[0];
+        if ( uBits1 < uBits2 )
+            return -1;
+        if ( uBits1 > uBits2 )
+            return 1;
+        // cubes are equal
+        return 0;
+    }
+    else if ( Mvc_Cube2Words(pC1) )
+    {
+        uBits1 = pC1->pData[1] | pMask->pData[1];
+        uBits2 = pC2->pData[1] | pMask->pData[1];
+        if ( uBits1 < uBits2 )
+            return -1;
+        if ( uBits1 > uBits2 )
+            return 1;
+        uBits1 = pC1->pData[0] | pMask->pData[0];
+        uBits2 = pC2->pData[0] | pMask->pData[0];
+        if ( uBits1 < uBits2 )
+            return -1;
+        if ( uBits1 > uBits2 )
+            return 1;
+        return 0;
+    }
+    else                            
+    {
+        int i = Mvc_CubeReadLast(pC1);
+        for(; i >= 0; i--)
+        {
+            uBits1 = pC1->pData[i] | pMask->pData[i];
+            uBits2 = pC2->pData[i] | pMask->pData[i];
+            if ( uBits1 < uBits2 )
+                return -1;
+            if ( uBits1 > uBits2 )
+                return 1;
+        }
+        return 0;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the cubes (1) outside the mask, (2) under the mask.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CubeCompareIntOutsideAndUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask )
+{
+    unsigned uBits1, uBits2;
+
+    if ( Mvc_Cube1Words(pC1) )
+    {
+        // compare the cubes outside the mask
+        uBits1 = pC1->pData[0] & ~(pMask->pData[0]);
+        uBits2 = pC2->pData[0] & ~(pMask->pData[0]);
+        if ( uBits1 < uBits2 )
+            return -1;
+        if ( uBits1 > uBits2 )
+            return 1;
+
+        // compare the cubes under the mask
+        uBits1 = pC1->pData[0] & pMask->pData[0];
+        uBits2 = pC2->pData[0] & pMask->pData[0];
+        if ( uBits1 < uBits2 )
+            return -1;
+        if ( uBits1 > uBits2 )
+            return 1;
+        // cubes are equal
+        // should never happen
+        assert( 0 );
+        return 0;
+    }
+    else if ( Mvc_Cube2Words(pC1) )
+    {
+        // compare the cubes outside the mask
+        uBits1 = pC1->pData[1] & ~(pMask->pData[1]);
+        uBits2 = pC2->pData[1] & ~(pMask->pData[1]);
+        if ( uBits1 < uBits2 )
+            return -1;
+        if ( uBits1 > uBits2 )
+            return 1;
+
+        uBits1 = pC1->pData[0] & ~(pMask->pData[0]);
+        uBits2 = pC2->pData[0] & ~(pMask->pData[0]);
+        if ( uBits1 < uBits2 )
+            return -1;
+        if ( uBits1 > uBits2 )
+            return 1;
+
+        // compare the cubes under the mask
+        uBits1 = pC1->pData[1] & pMask->pData[1];
+        uBits2 = pC2->pData[1] & pMask->pData[1];
+        if ( uBits1 < uBits2 )
+            return -1;
+        if ( uBits1 > uBits2 )
+            return 1;
+
+        uBits1 = pC1->pData[0] & pMask->pData[0];
+        uBits2 = pC2->pData[0] & pMask->pData[0];
+        if ( uBits1 < uBits2 )
+            return -1;
+        if ( uBits1 > uBits2 )
+            return 1;
+
+        // cubes are equal
+        // should never happen
+        assert( 0 );
+        return 0;
+    }
+    else                            
+    {
+        int i;
+
+        // compare the cubes outside the mask
+        for( i = Mvc_CubeReadLast(pC1); i >= 0; i-- )
+        {
+            uBits1 = pC1->pData[i] & ~(pMask->pData[i]);
+            uBits2 = pC2->pData[i] & ~(pMask->pData[i]);
+            if ( uBits1 < uBits2 )
+                return -1;
+            if ( uBits1 > uBits2 )
+                return 1;
+        }
+        // compare the cubes under the mask
+        for( i = Mvc_CubeReadLast(pC1); i >= 0; i-- )
+        {
+            uBits1 = pC1->pData[i] & pMask->pData[i];
+            uBits2 = pC2->pData[i] & pMask->pData[i];
+            if ( uBits1 < uBits2 )
+                return -1;
+            if ( uBits1 > uBits2 )
+                return 1;
+        }
+/*
+        {
+            Mvc_Cover_t * pCover;
+            pCover = Mvc_CoverAlloc( NULL, 96 );
+            Mvc_CubePrint( pCover, pC1 );
+            Mvc_CubePrint( pCover, pC2 );
+            Mvc_CubePrint( pCover, pMask );
+        }
+*/
+        // cubes are equal
+        // should never happen
+        assert( 0 );
+        return 0;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/mvc/mvcContain.c b/abc-build/src/misc/mvc/mvcContain.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/mvcContain.c
@@ -0,0 +1,178 @@
+/**CFile****************************************************************
+
+  FileName    [mvcContain.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Making the cover single-cube containment ABC_FREE.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: mvcContain.c,v 1.4 2003/04/03 23:25:42 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Mvc_CoverRemoveDuplicates( Mvc_Cover_t * pCover );
+static void Mvc_CoverRemoveContained( Mvc_Cover_t * pCover );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    [Removes the contained cubes.]
+
+  Description [Returns 1 if the cover has been changed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int  Mvc_CoverContain( Mvc_Cover_t * pCover )
+{
+    int nCubes;
+    nCubes = Mvc_CoverReadCubeNum( pCover );
+    if ( nCubes < 2 )
+        return 0;
+    Mvc_CoverSetCubeSizes(pCover);
+    Mvc_CoverSort( pCover, NULL, Mvc_CubeCompareSizeAndInt );
+    Mvc_CoverRemoveDuplicates( pCover );
+    if ( nCubes > 1 )
+        Mvc_CoverRemoveContained( pCover );
+    return (nCubes != Mvc_CoverReadCubeNum(pCover));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes adjacent duplicated cubes from the cube list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverRemoveDuplicates( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pPrev, * pCube, * pCube2;
+    int  fEqual;
+
+    // set the first cube of the cover
+    pPrev = Mvc_CoverReadCubeHead(pCover);
+    // go through all the cubes after this one
+    Mvc_CoverForEachCubeStartSafe( Mvc_CubeReadNext(pPrev), pCube, pCube2 )
+    {
+        // compare the current cube with the prev cube
+        Mvc_CubeBitEqual( fEqual, pPrev, pCube );
+        if ( fEqual )
+        { // they are equal - remove the current cube
+            Mvc_CoverDeleteCube( pCover, pPrev, pCube );
+            Mvc_CubeFree( pCover, pCube );
+            // don't change the previous cube cube
+        }
+        else
+        { // they are not equal - update the previous cube
+            pPrev = pCube;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes contained cubes from the sorted cube list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverRemoveContained( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCubeBeg, * pCubeEnd, * pCubeLarge;
+    Mvc_Cube_t * pCube, * pCube2, * pPrev;
+    unsigned sizeCur;
+    int  Result;
+
+    // since the cubes are sorted by size, it is sufficient 
+    // to compare each cube with other cubes that have larger sizes
+    // if the given cube implies a larger cube, the larger cube is removed
+    pCubeBeg = Mvc_CoverReadCubeHead(pCover);
+    do
+    {
+        // get the current cube size
+        sizeCur = Mvc_CubeReadSize(pCubeBeg);
+
+        // initialize the end of the given size group
+        pCubeEnd = pCubeBeg;
+        // find the beginning of the next size group
+        Mvc_CoverForEachCubeStart( Mvc_CubeReadNext(pCubeBeg), pCube )
+        {
+            if ( sizeCur == Mvc_CubeReadSize(pCube) ) 
+                pCubeEnd = pCube;
+            else // pCube is the first cube in the new size group
+                break;
+        }
+        // if we could not find the next size group
+        // the containment check is finished
+        if ( pCube == NULL )
+            break;
+        // otherwise, pCubeBeg/pCubeEnd are the first/last cubes of the group
+
+        // go through all the cubes between pCubeBeg and pCubeEnd, inclusive,
+        // and for each of them, try removing cubes after pCubeEnd
+        Mvc_CoverForEachCubeStart( pCubeBeg, pCubeLarge )
+        {
+            pPrev = pCubeEnd;
+            Mvc_CoverForEachCubeStartSafe( Mvc_CubeReadNext(pCubeEnd), pCube, pCube2 )
+            {
+                // check containment
+                Mvc_CubeBitNotImpl( Result, pCube, pCubeLarge );
+                if ( !Result )
+                { // pCubeLarge implies pCube - remove pCube
+                    Mvc_CoverDeleteCube( pCover, pPrev, pCube );
+                    Mvc_CubeFree( pCover, pCube );
+                    // don't update the previous cube
+                }
+                else
+                {   // update the previous cube
+                    pPrev = pCube;
+                }
+            }
+            // quit, if the main cube was the last one of this size
+            if ( pCubeLarge == pCubeEnd )
+                break;
+        }
+
+        // set the beginning of the next group
+        pCubeBeg = Mvc_CubeReadNext(pCubeEnd);
+    }
+    while ( pCubeBeg );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/mvc/mvcCover.c b/abc-build/src/misc/mvc/mvcCover.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/mvcCover.c
@@ -0,0 +1,256 @@
+/**CFile****************************************************************
+
+  FileName    [mvcCover.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Basic procedures to manipulate unate cube covers.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: mvcCover.c,v 1.5 2003/04/09 18:02:05 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverAlloc( Mvc_Manager_t * pMem, int nBits )
+{
+    Mvc_Cover_t * p;
+    int nBitsInUnsigned;
+
+    nBitsInUnsigned  = 8 * sizeof(Mvc_CubeWord_t);
+#ifdef USE_SYSTEM_MEMORY_MANAGEMENT
+    p                = (Mvc_Cover_t *)ABC_ALLOC( char, sizeof(Mvc_Cover_t) );
+#else
+    p                = (Mvc_Cover_t *)Extra_MmFixedEntryFetch( pMem->pManC );
+#endif
+    p->pMem          = pMem;
+    p->nBits         = nBits;
+    p->nWords        = nBits / nBitsInUnsigned + (int)(nBits % nBitsInUnsigned > 0);
+    p->nUnused       = p->nWords * nBitsInUnsigned - p->nBits;
+    p->lCubes.nItems = 0;
+    p->lCubes.pHead  = NULL;
+    p->lCubes.pTail  = NULL;
+    p->nCubesAlloc   = 0;
+    p->pCubes        = NULL;
+    p->pMask         = NULL;
+    p->pLits         = NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverClone( Mvc_Cover_t * p )
+{
+    Mvc_Cover_t * pCover;
+#ifdef USE_SYSTEM_MEMORY_MANAGEMENT
+    pCover                = (Mvc_Cover_t *)ABC_ALLOC( char, sizeof(Mvc_Cover_t) );
+#else
+    pCover                = (Mvc_Cover_t *)Extra_MmFixedEntryFetch( p->pMem->pManC );
+#endif
+    pCover->pMem          = p->pMem;
+    pCover->nBits         = p->nBits;
+    pCover->nWords        = p->nWords;
+    pCover->nUnused       = p->nUnused;
+    pCover->lCubes.nItems = 0;
+    pCover->lCubes.pHead  = NULL;
+    pCover->lCubes.pTail  = NULL;
+    pCover->nCubesAlloc   = 0;
+    pCover->pCubes        = NULL;
+    pCover->pMask         = NULL;
+    pCover->pLits         = NULL;
+    return pCover;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverDup( Mvc_Cover_t * p )
+{
+    Mvc_Cover_t * pCover;
+    Mvc_Cube_t * pCube, * pCubeCopy;
+    // clone the cover
+    pCover = Mvc_CoverClone( p );
+    // copy the cube list
+    Mvc_CoverForEachCube( p, pCube )
+    {
+        pCubeCopy = Mvc_CubeDup( p, pCube );
+        Mvc_CoverAddCubeTail( pCover, pCubeCopy );
+    }
+    return pCover;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverFree( Mvc_Cover_t * p )
+{
+    Mvc_Cube_t * pCube, * pCube2;
+    // recycle cube list
+    Mvc_CoverForEachCubeSafe( p, pCube, pCube2 )
+        Mvc_CubeFree( p, pCube );
+    // recycle other pointers
+    Mvc_CubeFree( p, p->pMask );
+    MEM_FREE( p->pMem, Mvc_Cube_t *, p->nCubesAlloc, p->pCubes );
+    MEM_FREE( p->pMem, int,          p->nBits,       p->pLits  );
+
+#ifdef USE_SYSTEM_MEMORY_MANAGEMENT
+    ABC_FREE( p );
+#else
+    Extra_MmFixedEntryRecycle( p->pMem->pManC, (char *)p );
+#endif
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverAllocateMask( Mvc_Cover_t * pCover ) 
+{ 
+    if ( pCover->pMask == NULL )
+        pCover->pMask = Mvc_CubeAlloc( pCover );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverAllocateArrayLits( Mvc_Cover_t * pCover ) 
+{ 
+    if ( pCover->pLits == NULL )
+        pCover->pLits = MEM_ALLOC( pCover->pMem, int, pCover->nBits );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverAllocateArrayCubes( Mvc_Cover_t * pCover ) 
+{ 
+    if ( pCover->nCubesAlloc < pCover->lCubes.nItems )
+    {
+        if ( pCover->nCubesAlloc > 0 )
+            MEM_FREE( pCover->pMem, Mvc_Cube_t *, pCover->nCubesAlloc, pCover->pCubes );
+        pCover->nCubesAlloc = pCover->lCubes.nItems;
+        pCover->pCubes = MEM_ALLOC( pCover->pMem, Mvc_Cube_t *, pCover->nCubesAlloc );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverDeallocateMask( Mvc_Cover_t * pCover ) 
+{ 
+    Mvc_CubeFree( pCover, pCover->pMask );
+    pCover->pMask = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverDeallocateArrayLits( Mvc_Cover_t * pCover ) 
+{ 
+    if ( pCover->pLits )
+    {
+        MEM_FREE( pCover->pMem, int, pCover->nBits, pCover->pLits );
+        pCover->pLits = NULL;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/mvc/mvcCube.c b/abc-build/src/misc/mvc/mvcCube.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/mvcCube.c
@@ -0,0 +1,180 @@
+/**CFile****************************************************************
+
+  FileName    [mvcCube.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Manipulating unate cubes.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: mvcCube.c,v 1.4 2003/04/03 06:31:49 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cube_t * Mvc_CubeAlloc( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCube;
+
+    assert( pCover->nWords >= 0 );
+    // allocate the cube
+#ifdef USE_SYSTEM_MEMORY_MANAGEMENT
+    if ( pCover->nWords == 0 )
+        pCube = (Mvc_Cube_t *)ABC_ALLOC( char, sizeof(Mvc_Cube_t) );
+    else
+        pCube = (Mvc_Cube_t *)ABC_ALLOC( char,  sizeof(Mvc_Cube_t) + sizeof(Mvc_CubeWord_t) * (pCover->nWords - 1) );
+#else
+    switch( pCover->nWords )
+    {
+    case 0:
+    case 1:
+        pCube = (Mvc_Cube_t *)Extra_MmFixedEntryFetch( pCover->pMem->pMan1 );
+        break;
+    case 2:
+        pCube = (Mvc_Cube_t *)Extra_MmFixedEntryFetch( pCover->pMem->pMan2 );
+        break;
+    case 3:
+    case 4:
+        pCube = (Mvc_Cube_t *)Extra_MmFixedEntryFetch( pCover->pMem->pMan4 );
+        break;
+    default:
+        pCube = (Mvc_Cube_t *)ABC_ALLOC( char, sizeof(Mvc_Cube_t) + sizeof(Mvc_CubeWord_t) * (pCover->nWords - 1) );
+        break;
+    }
+#endif
+    // set the parameters charactering this cube
+    if ( pCover->nWords == 0 )
+        pCube->iLast   = pCover->nWords;
+    else
+        pCube->iLast   = pCover->nWords - 1;
+    pCube->nUnused = pCover->nUnused;
+    return pCube;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cube_t * Mvc_CubeDup( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+    Mvc_Cube_t * pCubeCopy;
+    pCubeCopy = Mvc_CubeAlloc( pCover );
+    Mvc_CubeBitCopy( pCubeCopy, pCube );
+    return pCubeCopy;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CubeFree( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+    if ( pCube == NULL )
+        return;
+
+    // verify the parameters charactering this cube
+    assert( pCube->iLast == 0 || ((int)pCube->iLast) == pCover->nWords - 1 );
+    assert( ((int)pCube->nUnused) == pCover->nUnused );
+
+    // deallocate the cube
+#ifdef USE_SYSTEM_MEMORY_MANAGEMENT
+    ABC_FREE( pCube );
+#else
+    switch( pCover->nWords )
+    {
+    case 0:
+    case 1:
+        Extra_MmFixedEntryRecycle( pCover->pMem->pMan1, (char *)pCube );
+        break;
+    case 2:
+        Extra_MmFixedEntryRecycle( pCover->pMem->pMan2, (char *)pCube );
+        break;
+    case 3:
+    case 4:
+        Extra_MmFixedEntryRecycle( pCover->pMem->pMan4, (char *)pCube );
+        break;
+    default:
+        ABC_FREE( pCube );
+        break;
+    }
+#endif
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Removes the don't-care variable from the cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CubeBitRemoveDcs( Mvc_Cube_t * pCube )
+{
+    unsigned Mask;
+    int i;
+    for ( i = Mvc_CubeReadLast(pCube); i >= 0; i-- )
+    {
+        // detect those variables that are different (not DCs)
+        Mask = (pCube->pData[i] ^ (pCube->pData[i] >> 1)) & BITS_DISJOINT; 
+        // create the mask of all that are different
+        Mask |= (Mask << 1);
+        // remove other bits from the set
+        pCube->pData[i] &= Mask;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/mvc/mvcDivide.c b/abc-build/src/misc/mvc/mvcDivide.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/mvcDivide.c
@@ -0,0 +1,442 @@
+/**CFile****************************************************************
+
+  FileName    [mvcDivide.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Procedures for algebraic division.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: mvcDivide.c,v 1.5 2003/04/26 20:41:36 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Mvc_CoverVerifyDivision( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t * pQuo, Mvc_Cover_t * pRem );
+
+int s_fVerbose = 0;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverDivide( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem )
+{
+    // check the number of cubes
+    if ( Mvc_CoverReadCubeNum( pCover ) < Mvc_CoverReadCubeNum( pDiv ) )
+    {
+        *ppQuo = NULL;
+        *ppRem = NULL;
+        return;
+    }
+
+    // make sure that support of pCover contains that of pDiv
+    if ( !Mvc_CoverCheckSuppContainment( pCover, pDiv ) )
+    {
+        *ppQuo = NULL;
+        *ppRem = NULL;
+        return;
+    }
+
+    // perform the general division
+    Mvc_CoverDivideInternal( pCover, pDiv, ppQuo, ppRem );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Merge the cubes inside the groups.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverDivideInternal( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem )
+{
+    Mvc_Cover_t * pQuo, * pRem;
+    Mvc_Cube_t * pCubeC, * pCubeD, * pCubeCopy;
+    Mvc_Cube_t * pCube1, * pCube2;
+    int * pGroups, nGroups;    // the cube groups
+    int nCubesC, nCubesD, nMerges, iCubeC, iCubeD;
+    int iMerge = -1; // Suppress "might be used uninitialized"
+    int fSkipG, GroupSize, g, c, RetValue;
+    int nCubes;
+
+    // get cover sizes
+    nCubesD = Mvc_CoverReadCubeNum( pDiv );
+    nCubesC = Mvc_CoverReadCubeNum( pCover );
+
+    // check trivial cases
+    if ( nCubesD == 1 )
+    {
+        if ( Mvc_CoverIsOneLiteral( pDiv ) )
+            Mvc_CoverDivideByLiteral( pCover, pDiv, ppQuo, ppRem );
+        else
+            Mvc_CoverDivideByCube( pCover, pDiv, ppQuo, ppRem );
+        return;
+    }
+
+    // create the divisor and the remainder 
+    pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
+    pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
+
+    // get the support of the divisor
+    Mvc_CoverAllocateMask( pDiv );
+    Mvc_CoverSupport( pDiv, pDiv->pMask );
+
+    // sort the cubes of the divisor
+    Mvc_CoverSort( pDiv, NULL, Mvc_CubeCompareInt );
+    // sort the cubes of the cover
+    Mvc_CoverSort( pCover, pDiv->pMask, Mvc_CubeCompareIntOutsideAndUnderMask );
+
+    // allocate storage for cube groups
+    pGroups = MEM_ALLOC( pCover->pMem, int, nCubesC + 1 );
+
+    // mask contains variables in the support of Div
+    // split the cubes into groups using the mask
+    Mvc_CoverList2Array( pCover );
+    Mvc_CoverList2Array( pDiv );
+    pGroups[0] = 0;
+    nGroups    = 1;
+    for ( c = 1; c < nCubesC; c++ )
+    {
+        // get the cubes
+        pCube1 = pCover->pCubes[c-1];
+        pCube2 = pCover->pCubes[c  ];
+        // compare the cubes
+        Mvc_CubeBitEqualOutsideMask( RetValue, pCube1, pCube2, pDiv->pMask );
+        if ( !RetValue )
+            pGroups[nGroups++] = c;
+    }
+    // finish off the last group
+    pGroups[nGroups] = nCubesC;
+
+    // consider each group separately and decide
+    // whether it can produce a quotient cube
+    nCubes = 0;
+    for ( g = 0; g < nGroups; g++ )
+    {
+        // if the group has less than nCubesD cubes, 
+        // there is no way it can produce the quotient cube
+        // copy the cubes to the remainder
+        GroupSize = pGroups[g+1] - pGroups[g];
+        if ( GroupSize < nCubesD )
+        {
+            for ( c = pGroups[g]; c < pGroups[g+1]; c++ )
+            {
+                pCubeCopy = Mvc_CubeDup( pRem, pCover->pCubes[c] );
+                Mvc_CoverAddCubeTail( pRem, pCubeCopy );
+                nCubes++;
+            }
+            continue;
+        }
+
+        // mark the cubes as those that should be added to the remainder
+        for ( c = pGroups[g]; c < pGroups[g+1]; c++ )
+            Mvc_CubeSetSize( pCover->pCubes[c], 1 );
+
+        // go through the cubes in the group and at the same time
+        // go through the cubes in the divisor
+        iCubeD  = 0;
+        iCubeC  = 0;
+        pCubeD  = pDiv->pCubes[iCubeD++];
+        pCubeC  = pCover->pCubes[pGroups[g]+iCubeC++];
+        fSkipG  = 0;
+        nMerges = 0;
+
+        while ( 1 )
+        {
+            // compare the topmost cubes in F and in D
+            RetValue = Mvc_CubeCompareIntUnderMask( pCubeC, pCubeD, pDiv->pMask );
+            // cube are ordered in increasing order of their int value
+            if ( RetValue == -1 ) // pCubeC is above pCubeD
+            {  // cube in C should be added to the remainder
+                // check that there is enough cubes in the group
+                if ( GroupSize - iCubeC < nCubesD - nMerges )
+                {
+                    fSkipG = 1;
+                    break;
+                }
+                // get the next cube in the cover
+                pCubeC = pCover->pCubes[pGroups[g]+iCubeC++];
+                continue;
+            }
+            if ( RetValue == 1 ) // pCubeD is above pCubeC
+            { // given cube in D does not have a corresponding cube in the cover
+                fSkipG = 1;
+                break;
+            }
+            // mark the cube as the one that should NOT be added to the remainder
+            Mvc_CubeSetSize( pCubeC, 0 );
+            // remember this merged cube
+            iMerge = iCubeC-1;
+            nMerges++;
+
+            // stop if we considered the last cube of the group
+            if ( iCubeD == nCubesD )
+                break;
+
+            // advance the cube of the divisor
+            assert( iCubeD < nCubesD );
+            pCubeD = pDiv->pCubes[iCubeD++];
+
+            // advance the cube of the group
+            assert( pGroups[g]+iCubeC < nCubesC );
+            pCubeC = pCover->pCubes[pGroups[g]+iCubeC++];
+        }
+
+        if ( fSkipG )
+        { 
+            // the group has failed, add all the cubes to the remainder
+            for ( c = pGroups[g]; c < pGroups[g+1]; c++ )
+            {
+                pCubeCopy = Mvc_CubeDup( pRem, pCover->pCubes[c] );
+                Mvc_CoverAddCubeTail( pRem, pCubeCopy );
+                nCubes++;
+            }
+            continue;
+        }
+
+        // the group has worked, add left-over cubes to the remainder
+        for ( c = pGroups[g]; c < pGroups[g+1]; c++ )
+        {
+            pCubeC = pCover->pCubes[c];
+            if ( Mvc_CubeReadSize(pCubeC) )
+            {
+                pCubeCopy = Mvc_CubeDup( pRem, pCubeC );
+                Mvc_CoverAddCubeTail( pRem, pCubeCopy );
+                nCubes++;
+            }
+        }
+
+        // create the quotient cube
+        pCube1 = Mvc_CubeAlloc( pQuo );
+        Mvc_CubeBitSharp( pCube1, pCover->pCubes[pGroups[g]+iMerge], pDiv->pMask );
+        // add the cube to the quotient
+        Mvc_CoverAddCubeTail( pQuo, pCube1 );
+        nCubes += nCubesD;
+    }
+    assert( nCubes == nCubesC );
+
+    // deallocate the memory
+    MEM_FREE( pCover->pMem, int, nCubesC + 1, pGroups );
+
+    // return the results
+    *ppRem = pRem;
+    *ppQuo = pQuo;
+//    Mvc_CoverVerifyDivision( pCover, pDiv, pQuo, pRem );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Divides the cover by a cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverDivideByCube( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem )
+{
+    Mvc_Cover_t * pQuo, * pRem;
+    Mvc_Cube_t * pCubeC, * pCubeD, * pCubeCopy;
+    int CompResult;
+
+    // get the only cube of D
+    assert( Mvc_CoverReadCubeNum(pDiv) == 1 );
+
+    // start the quotient and the remainder
+    pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
+    pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
+
+    // get the first and only cube of the divisor
+    pCubeD = Mvc_CoverReadCubeHead( pDiv );
+
+    // iterate through the cubes in the cover
+    Mvc_CoverForEachCube( pCover, pCubeC )
+    {
+        // check the containment of literals from pCubeD in pCube
+        Mvc_Cube2BitNotImpl( CompResult, pCubeD, pCubeC );
+        if ( !CompResult )
+        { // this cube belongs to the quotient
+            // alloc the cube
+            pCubeCopy = Mvc_CubeAlloc( pQuo );
+            // clean the support of D
+            Mvc_CubeBitSharp( pCubeCopy, pCubeC, pCubeD );
+            // add the cube to the quotient
+            Mvc_CoverAddCubeTail( pQuo, pCubeCopy );
+        }
+        else
+        { 
+            // copy the cube
+            pCubeCopy = Mvc_CubeDup( pRem, pCubeC );
+            // add the cube to the remainder
+            Mvc_CoverAddCubeTail( pRem, pCubeCopy );
+        }
+    }
+    // return the results
+    *ppRem = pRem;
+    *ppQuo = pQuo;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Divides the cover by a literal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverDivideByLiteral( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem )
+{
+    Mvc_Cover_t * pQuo, * pRem;
+    Mvc_Cube_t * pCubeC, * pCubeCopy;
+    int iLit;
+
+    // get the only cube of D
+    assert( Mvc_CoverReadCubeNum(pDiv) == 1 );
+
+    // start the quotient and the remainder
+    pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
+    pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
+
+    // get the first and only literal in the divisor cube
+    iLit = Mvc_CoverFirstCubeFirstLit( pDiv );
+
+    // iterate through the cubes in the cover
+    Mvc_CoverForEachCube( pCover, pCubeC )
+    {
+        // copy the cube
+        pCubeCopy = Mvc_CubeDup( pCover, pCubeC );
+        // add the cube to the quotient or to the remainder depending on the literal
+        if ( Mvc_CubeBitValue( pCubeCopy, iLit ) )
+        {   // remove the literal
+            Mvc_CubeBitRemove( pCubeCopy, iLit );
+            // add the cube ot the quotient
+            Mvc_CoverAddCubeTail( pQuo, pCubeCopy );
+        }
+        else
+        {   // add the cube ot the remainder
+            Mvc_CoverAddCubeTail( pRem, pCubeCopy );
+        }
+    }
+    // return the results
+    *ppRem = pRem;
+    *ppQuo = pQuo;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the quotient of division by literal.]
+
+  Description [Reduces the cover to be the equal to the result of
+  division of the given cover by the literal.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverDivideByLiteralQuo( Mvc_Cover_t * pCover, int iLit )
+{
+    Mvc_Cube_t * pCube, * pCube2, * pPrev;
+    // delete those cubes that do not have this literal
+    // remove this literal from other cubes
+    pPrev = NULL;
+    Mvc_CoverForEachCubeSafe( pCover, pCube, pCube2 )
+    {
+        if ( Mvc_CubeBitValue( pCube, iLit ) == 0 )
+        { // delete the cube from the cover
+            Mvc_CoverDeleteCube( pCover, pPrev, pCube );
+            Mvc_CubeFree( pCover, pCube );
+            // don't update the previous cube
+        }
+        else
+        { // delete this literal from the cube
+            Mvc_CubeBitRemove( pCube, iLit );
+            // update the previous cube
+            pPrev = pCube;
+        }
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies that the result of algebraic division is correct.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverVerifyDivision( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t * pQuo, Mvc_Cover_t * pRem )
+{   
+    Mvc_Cover_t * pProd;
+    Mvc_Cover_t * pDiff;
+
+    pProd = Mvc_CoverAlgebraicMultiply( pDiv, pQuo );
+    pDiff = Mvc_CoverAlgebraicSubtract( pCover, pProd );
+
+    if ( Mvc_CoverAlgebraicEqual( pDiff, pRem ) )
+        printf( "Verification OKAY!\n" );
+    else
+    {
+        printf( "Verification FAILED!\n" );
+        printf( "pCover:\n" );
+        Mvc_CoverPrint( pCover );
+        printf( "pDiv:\n" );
+        Mvc_CoverPrint( pDiv );
+        printf( "pRem:\n" );
+        Mvc_CoverPrint( pRem );
+        printf( "pQuo:\n" );
+        Mvc_CoverPrint( pQuo );
+    }
+
+    Mvc_CoverFree( pProd );
+    Mvc_CoverFree( pDiff );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/mvc/mvcDivisor.c b/abc-build/src/misc/mvc/mvcDivisor.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/mvcDivisor.c
@@ -0,0 +1,95 @@
+/**CFile****************************************************************
+
+  FileName    [mvcDivisor.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Procedures for compute the quick divisor.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: mvcDivisor.c,v 1.1 2003/04/03 15:34:08 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void  Mvc_CoverDivisorZeroKernel( Mvc_Cover_t * pCover );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the quick divisor of the cover.]
+
+  Description [Returns NULL, if there is not divisor other than
+  trivial.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverDivisor( Mvc_Cover_t * pCover )
+{
+    Mvc_Cover_t * pKernel;
+    if ( Mvc_CoverReadCubeNum(pCover) <= 1 )
+        return NULL;
+    // allocate the literal array and count literals
+    if ( Mvc_CoverAnyLiteral( pCover, NULL ) == -1 )
+        return NULL;
+    // duplicate the cover
+    pKernel = Mvc_CoverDup(pCover);
+    // perform the kerneling
+    Mvc_CoverDivisorZeroKernel( pKernel );
+    assert( Mvc_CoverReadCubeNum(pKernel) );
+    return pKernel;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes a level-zero kernel.]
+
+  Description [Modifies the cover to contain one level-zero kernel.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverDivisorZeroKernel( Mvc_Cover_t * pCover )
+{
+    int iLit;
+    // find any literal that occurs at least two times
+//    iLit = Mvc_CoverAnyLiteral( pCover, NULL );
+    iLit = Mvc_CoverWorstLiteral( pCover, NULL );
+//    iLit = Mvc_CoverBestLiteral( pCover, NULL );
+    if ( iLit == -1 )
+        return;
+    // derive the cube-free quotient
+    Mvc_CoverDivideByLiteralQuo( pCover, iLit ); // the same cover
+    Mvc_CoverMakeCubeFree( pCover );             // the same cover
+    // call recursively
+    Mvc_CoverDivisorZeroKernel( pCover );              // the same cover
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/mvc/mvcList.c b/abc-build/src/misc/mvc/mvcList.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/mvcList.c
@@ -0,0 +1,367 @@
+/**CFile****************************************************************
+
+  FileName    [mvcList.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Manipulating list of cubes in the cover.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: mvcList.c,v 1.4 2003/04/03 06:31:50 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_ListAddCubeHead_( Mvc_List_t * pList, Mvc_Cube_t * pCube )
+{
+    if ( pList->pHead == NULL )
+    {
+        Mvc_CubeSetNext( pCube, NULL );
+        pList->pHead = pCube;
+        pList->pTail = pCube;
+    }
+    else
+    {
+        Mvc_CubeSetNext( pCube, pList->pHead );
+        pList->pHead = pCube;
+    }
+    pList->nItems++;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_ListAddCubeTail_( Mvc_List_t * pList, Mvc_Cube_t * pCube )
+{
+    if ( pList->pHead == NULL )
+        pList->pHead = pCube;
+    else
+        Mvc_CubeSetNext( pList->pTail, pCube );
+    pList->pTail    = pCube;
+    Mvc_CubeSetNext( pCube, NULL );
+    pList->nItems++;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_ListDeleteCube_( Mvc_List_t * pList, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube )
+{
+    if ( pPrev == NULL ) // deleting the head cube
+        pList->pHead = Mvc_CubeReadNext(pCube);
+    else
+        pPrev->pNext = pCube->pNext;
+    if ( pList->pTail == pCube ) // deleting the tail cube
+    {
+        assert( Mvc_CubeReadNext(pCube) == NULL );
+        pList->pTail = pPrev;
+    }
+    pList->nItems--;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverAddCubeHead_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+    Mvc_List_t * pList = &pCover->lCubes;
+    if ( pList->pHead == NULL )
+    {
+        Mvc_CubeSetNext( pCube, NULL );
+        pList->pHead = pCube;
+        pList->pTail = pCube;
+    }
+    else
+    {
+        Mvc_CubeSetNext( pCube, pList->pHead );
+        pList->pHead = pCube;
+    }
+    pList->nItems++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverAddCubeTail_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+    Mvc_List_t * pList = &pCover->lCubes;
+
+    if ( pList->pHead == NULL )
+        pList->pHead = pCube;
+    else
+        Mvc_CubeSetNext( pList->pTail, pCube );
+    pList->pTail    = pCube;
+    Mvc_CubeSetNext( pCube, NULL );
+    pList->nItems++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverDeleteCube_( Mvc_Cover_t * pCover, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube )
+{
+    Mvc_List_t * pList = &pCover->lCubes;
+ 
+    if ( pPrev == NULL ) // deleting the head cube
+        pList->pHead = Mvc_CubeReadNext(pCube);
+    else
+        pPrev->pNext = pCube->pNext;
+    if ( pList->pTail == pCube ) // deleting the tail cube
+    {
+        assert( Mvc_CubeReadNext(pCube) == NULL );
+        pList->pTail = pPrev;
+    }
+    pList->nItems--;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverAddDupCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+    Mvc_Cube_t * pCubeNew;
+    pCubeNew = Mvc_CubeAlloc( pCover );
+    Mvc_CubeBitCopy( pCubeNew, pCube );
+    Mvc_CoverAddCubeHead( pCover, pCubeNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverAddDupCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+    Mvc_Cube_t * pCubeNew;
+    // copy the cube as part of this cover
+    pCubeNew = Mvc_CubeAlloc( pCover );
+    Mvc_CubeBitCopy( pCubeNew, pCube );
+    // clean the last bits of the new cube
+//    pCubeNew->pData[pCubeNew->iLast] &= (BITS_FULL >> pCubeNew->nUnused);
+    // add the cube at the end
+    Mvc_CoverAddCubeTail( pCover, pCubeNew );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverAddLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+//    int iBit, Value;
+//    assert( pCover->pLits );
+//    Mvc_CubeForEachBit( pCover, pCube, iBit, Value )
+//        if ( Value )
+//            pCover->pLits[iBit] += Value;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverDeleteLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+//    int iBit, Value;
+//    assert( pCover->pLits );
+//    Mvc_CubeForEachBit( pCover, pCube, iBit, Value )
+//        if ( Value )
+//            pCover->pLits[iBit] -= Value;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the cubes from the list into the array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverList2Array( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCube;
+    int Counter;
+    // resize storage if necessary
+    Mvc_CoverAllocateArrayCubes( pCover );
+    // iterate through the cubes
+    Counter = 0;
+    Mvc_CoverForEachCube( pCover, pCube )
+        pCover->pCubes[ Counter++ ] = pCube;
+    assert( Counter == Mvc_CoverReadCubeNum(pCover) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the cubes from the array into list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverArray2List( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCube;
+    int nCubes, i;
+
+    assert( pCover->pCubes );
+
+    nCubes = Mvc_CoverReadCubeNum(pCover);
+    if ( nCubes == 0 )
+        return;
+    if ( nCubes == 1 )
+    {
+        pCube    = pCover->pCubes[0];
+        pCube->pNext = NULL;
+        pCover->lCubes.pHead = pCover->lCubes.pTail = pCube;
+        return;
+    }
+    // set up the first cube
+    pCube = pCover->pCubes[0];
+    pCover->lCubes.pHead = pCube;
+    // set up the last cube
+    pCube = pCover->pCubes[nCubes-1];
+    pCube->pNext = NULL;
+    pCover->lCubes.pTail = pCube;
+
+    // link all cubes starting from the first one
+    for ( i = 0; i < nCubes - 1; i++ )
+        pCover->pCubes[i]->pNext = pCover->pCubes[i+1];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the tail of the linked list given by the head.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cube_t * Mvc_ListGetTailFromHead( Mvc_Cube_t * pHead )
+{
+    Mvc_Cube_t * pCube, * pTail;
+    for ( pTail = pCube = pHead; 
+          pCube; 
+          pTail = pCube, pCube = Mvc_CubeReadNext(pCube) );
+    return pTail;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/mvc/mvcLits.c b/abc-build/src/misc/mvc/mvcLits.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/mvcLits.c
@@ -0,0 +1,350 @@
+/**CFile****************************************************************
+
+  FileName    [mvcLits.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Literal counting/updating procedures.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: mvcLits.c,v 1.4 2003/04/03 06:31:50 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Find the any literal that occurs more than once.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverAnyLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask )
+{
+    Mvc_Cube_t * pCube;
+    int nWord, nBit, i;
+    int nLitsCur;
+    int fUseFirst = 0;
+
+    // go through each literal
+    if ( fUseFirst )
+    {
+        for ( i = 0; i < pCover->nBits; i++ )
+            if ( !pMask || Mvc_CubeBitValue(pMask,i) )
+            {
+                // get the word and bit of this literal
+                nWord = Mvc_CubeWhichWord(i);
+                nBit  = Mvc_CubeWhichBit(i);
+                // go through all the cubes
+                nLitsCur = 0;
+                Mvc_CoverForEachCube( pCover, pCube )
+                    if ( pCube->pData[nWord] & (1<<nBit) )
+                    {
+                        nLitsCur++;
+                        if ( nLitsCur > 1 )
+                            return i;
+                    }
+            }
+    }
+    else
+    {
+        for ( i = pCover->nBits - 1; i >=0; i-- )
+            if ( !pMask || Mvc_CubeBitValue(pMask,i) )
+            {
+                // get the word and bit of this literal
+                nWord = Mvc_CubeWhichWord(i);
+                nBit  = Mvc_CubeWhichBit(i);
+                // go through all the cubes
+                nLitsCur = 0;
+                Mvc_CoverForEachCube( pCover, pCube )
+                    if ( pCube->pData[nWord] & (1<<nBit) )
+                    {
+                        nLitsCur++;
+                        if ( nLitsCur > 1 )
+                            return i;
+                    }
+            }
+    }
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the most often occurring literal.]
+
+  Description [Find the most often occurring literal among those
+  that occur more than once.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverBestLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask )
+{
+    Mvc_Cube_t * pCube;
+    int nWord, nBit;
+    int i, iMax, nLitsMax, nLitsCur;
+    int fUseFirst = 1;
+
+    // go through each literal
+    iMax = -1;
+    nLitsMax = -1;
+    for ( i = 0; i < pCover->nBits; i++ )
+        if ( !pMask || Mvc_CubeBitValue(pMask,i) )
+        {
+            // get the word and bit of this literal
+            nWord = Mvc_CubeWhichWord(i);
+            nBit  = Mvc_CubeWhichBit(i);
+            // go through all the cubes
+            nLitsCur = 0;
+            Mvc_CoverForEachCube( pCover, pCube )
+                if ( pCube->pData[nWord] & (1<<nBit) )
+                    nLitsCur++;
+
+            // check if this is the best literal
+            if ( fUseFirst )
+            {
+                if ( nLitsMax < nLitsCur )
+                {
+                    nLitsMax = nLitsCur;
+                    iMax = i;
+                }
+            }
+            else
+            {
+                if ( nLitsMax <= nLitsCur )
+                {
+                    nLitsMax = nLitsCur;
+                    iMax = i;
+                }
+            }
+        }
+
+    if ( nLitsMax > 1 )
+        return iMax;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the most often occurring literal.]
+
+  Description [Find the most often occurring literal among those
+  that occur more than once.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverWorstLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask )
+{
+    Mvc_Cube_t * pCube;
+    int nWord, nBit;
+    int i, iMin, nLitsMin, nLitsCur;
+    int fUseFirst = 1;
+
+    // go through each literal
+    iMin = -1;
+    nLitsMin = 1000000;
+    for ( i = 0; i < pCover->nBits; i++ )
+        if ( !pMask || Mvc_CubeBitValue(pMask,i) )
+        {
+            // get the word and bit of this literal
+            nWord = Mvc_CubeWhichWord(i);
+            nBit  = Mvc_CubeWhichBit(i);
+            // go through all the cubes
+            nLitsCur = 0;
+            Mvc_CoverForEachCube( pCover, pCube )
+                if ( pCube->pData[nWord] & (1<<nBit) )
+                    nLitsCur++;
+
+            // skip the literal that does not occur or occurs once
+            if ( nLitsCur < 2 )
+                continue;
+
+            // check if this is the best literal
+            if ( fUseFirst )
+            {
+                if ( nLitsMin > nLitsCur )
+                {
+                    nLitsMin = nLitsCur;
+                    iMin = i;
+                }
+            }
+            else
+            {
+                if ( nLitsMin >= nLitsCur )
+                {
+                    nLitsMin = nLitsCur;
+                    iMin = i;
+                }
+            }
+        }
+
+    if ( nLitsMin < 1000000 )
+        return iMin;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverBestLiteralCover( Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple )
+{
+    Mvc_Cover_t * pCoverNew;
+    Mvc_Cube_t * pCubeNew;
+    Mvc_Cube_t * pCubeS;
+    int iLitBest;
+
+    // create the new cover
+    pCoverNew = Mvc_CoverClone( pCover );
+    // get the new cube
+    pCubeNew = Mvc_CubeAlloc( pCoverNew );
+    // clean the cube
+    Mvc_CubeBitClean( pCubeNew );
+
+    // get the first cube of pSimple
+    assert( Mvc_CoverReadCubeNum(pSimple) == 1 );
+    pCubeS = Mvc_CoverReadCubeHead( pSimple );
+    // find the best literal among those of pCubeS
+    iLitBest = Mvc_CoverBestLiteral( pCover, pCubeS );
+
+    // insert this literal into the cube
+    Mvc_CubeBitInsert( pCubeNew, iLitBest );
+    // add the cube to the cover
+    Mvc_CoverAddCubeTail( pCoverNew, pCubeNew );
+    return pCoverNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverFirstCubeFirstLit( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCube;
+    int iBit, Value;
+
+    // get the first cube
+    pCube = Mvc_CoverReadCubeHead( pCover );
+    // get the first literal
+    Mvc_CubeForEachBit( pCover, pCube, iBit, Value )
+        if ( Value )
+            return iBit;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of literals in the cover.]
+
+  Description [Allocates storage for literal counters and fills it up
+  using the current information.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverCountLiterals( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCube;
+    int nWord, nBit;
+    int i, CounterTot, CounterCur;
+
+    // allocate/clean the storage for literals
+//    Mvc_CoverAllocateArrayLits( pCover );
+//    memset( pCover->pLits, 0, pCover->nBits * sizeof(int) );
+    // go through each literal
+    CounterTot = 0;
+    for ( i = 0; i < pCover->nBits; i++ )
+    {
+        // get the word and bit of this literal
+        nWord = Mvc_CubeWhichWord(i);
+        nBit  = Mvc_CubeWhichBit(i);
+        // go through all the cubes
+        CounterCur = 0;
+        Mvc_CoverForEachCube( pCover, pCube )
+            if ( pCube->pData[nWord] & (1<<nBit) )
+                CounterCur++;
+        CounterTot += CounterCur;
+    }
+    return CounterTot;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of literals in the cover.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverIsOneLiteral( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCube;
+    int iBit, Counter, Value;
+    if ( Mvc_CoverReadCubeNum(pCover) != 1 )
+        return 0;
+    pCube = Mvc_CoverReadCubeHead(pCover);
+    // count literals
+    Counter = 0;
+    Mvc_CubeForEachBit( pCover, pCube, iBit, Value )
+    {
+        if ( Value )
+        {
+            if ( Counter++ )
+                return 0;
+        }
+    }
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/mvc/mvcMan.c b/abc-build/src/misc/mvc/mvcMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/mvcMan.c
@@ -0,0 +1,82 @@
+/**CFile****************************************************************
+
+  FileName    [mvcMan.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Procedures working with the MVC memory manager.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: mvcMan.c,v 1.3 2003/03/19 19:50:26 alanmi Exp $]
+
+***********************************************************************/
+
+#include <string.h>
+#include "mvc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Manager_t * Mvc_ManagerStart()
+{
+    Mvc_Manager_t * p;
+    p = ABC_ALLOC( Mvc_Manager_t, 1 );
+    memset( p, 0, sizeof(Mvc_Manager_t) );
+    p->pMan1 = Extra_MmFixedStart( sizeof(Mvc_Cube_t)                              );
+    p->pMan2 = Extra_MmFixedStart( sizeof(Mvc_Cube_t) +     sizeof(Mvc_CubeWord_t) );
+    p->pMan4 = Extra_MmFixedStart( sizeof(Mvc_Cube_t) + 3 * sizeof(Mvc_CubeWord_t) );
+    p->pManC = Extra_MmFixedStart( sizeof(Mvc_Cover_t) );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_ManagerFree( Mvc_Manager_t * p )
+{
+    Extra_MmFixedStop( p->pMan1 );
+    Extra_MmFixedStop( p->pMan2 );
+    Extra_MmFixedStop( p->pMan4 );
+    Extra_MmFixedStop( p->pManC );
+    ABC_FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/mvc/mvcOpAlg.c b/abc-build/src/misc/mvc/mvcOpAlg.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/mvcOpAlg.c
@@ -0,0 +1,168 @@
+/**CFile****************************************************************
+
+  FileName    [mvcOperAlg.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Miscellaneous operations on covers.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: mvcOpAlg.c,v 1.4 2003/04/26 20:41:36 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Multiplies two disjoint-support covers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverAlgebraicMultiply( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 )
+{
+    Mvc_Cover_t * pCover;
+    Mvc_Cube_t * pCube1, * pCube2, * pCube;
+    int CompResult;
+
+    // covers should be the same base
+    assert( pCover1->nBits == pCover2->nBits );
+    // make sure that supports do not overlap
+    Mvc_CoverAllocateMask( pCover1 );
+    Mvc_CoverAllocateMask( pCover2 );
+    Mvc_CoverSupport( pCover1, pCover1->pMask );
+    Mvc_CoverSupport( pCover2, pCover2->pMask );
+    // check if the cubes are bit-wise disjoint
+    Mvc_CubeBitDisjoint( CompResult, pCover1->pMask, pCover2->pMask );
+    if ( !CompResult )
+        printf( "Mvc_CoverMultiply(): Cover supports are not disjoint!\n" );
+
+    // iterate through the cubes
+    pCover = Mvc_CoverClone( pCover1 );
+    Mvc_CoverForEachCube( pCover1, pCube1 )
+        Mvc_CoverForEachCube( pCover2, pCube2 )
+        { 
+            // create the product cube
+            pCube = Mvc_CubeAlloc( pCover );
+            // set the product cube equal to the product of the two cubes
+            Mvc_CubeBitOr( pCube, pCube1, pCube2 );
+            // add the cube to the cover
+            Mvc_CoverAddCubeTail( pCover, pCube );
+        }
+    return pCover;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Subtracts the second cover from the first.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverAlgebraicSubtract( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 )
+{
+    Mvc_Cover_t * pCover;
+    Mvc_Cube_t * pCube1, * pCube2, * pCube;
+    int fFound;
+    int CompResult;
+
+    // covers should be the same base
+    assert( pCover1->nBits == pCover2->nBits );
+
+    // iterate through the cubes
+    pCover = Mvc_CoverClone( pCover1 );
+    Mvc_CoverForEachCube( pCover1, pCube1 )
+    {
+        fFound = 0;
+        Mvc_CoverForEachCube( pCover2, pCube2 )
+        {
+            Mvc_CubeBitEqual( CompResult, pCube1, pCube2 );
+            if ( CompResult )
+            {
+                fFound = 1;
+                break;
+            }
+        }
+        if ( !fFound )
+        { 
+            // create the copy of the cube
+            pCube = Mvc_CubeDup( pCover, pCube1 );
+            // add the cube copy to the cover
+            Mvc_CoverAddCubeTail( pCover, pCube );
+        }
+    }
+    return pCover;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverAlgebraicEqual( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 )
+{
+    Mvc_Cube_t * pCube1, * pCube2;
+    int fFound;
+    int CompResult;
+
+    // covers should be the same base
+    assert( pCover1->nBits == pCover2->nBits );
+    // iterate through the cubes
+    Mvc_CoverForEachCube( pCover1, pCube1 )
+    {
+        fFound = 0;
+        Mvc_CoverForEachCube( pCover2, pCube2 )
+        {
+            Mvc_CubeBitEqual( CompResult, pCube1, pCube2 );
+            if ( CompResult )
+            {
+                fFound = 1;
+                break;
+            }
+        }
+        if ( !fFound )
+            return 0;
+    }
+    return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/mvc/mvcOpBool.c b/abc-build/src/misc/mvc/mvcOpBool.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/mvcOpBool.c
@@ -0,0 +1,156 @@
+/**CFile****************************************************************
+
+  FileName    [mvcProc.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Various boolean procedures working with covers.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: mvcOpBool.c,v 1.4 2003/04/16 01:55:37 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverBooleanOr( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 )
+{
+    Mvc_Cover_t * pCover;
+    Mvc_Cube_t * pCube, * pCubeCopy;
+    // make sure the covers are compatible
+    assert( pCover1->nBits == pCover2->nBits );
+    // clone the cover
+    pCover = Mvc_CoverClone( pCover1 );
+    // create the cubes by making pair-wise products
+    // of cubes in pCover1 and pCover2
+    Mvc_CoverForEachCube( pCover1, pCube )
+    {
+        pCubeCopy = Mvc_CubeDup( pCover, pCube );
+        Mvc_CoverAddCubeTail( pCover, pCubeCopy );
+    }
+    Mvc_CoverForEachCube( pCover2, pCube )
+    {
+        pCubeCopy = Mvc_CubeDup( pCover, pCube );
+        Mvc_CoverAddCubeTail( pCover, pCubeCopy );
+    }
+    return pCover;
+}
+
+#if 0
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverBooleanAnd( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 )
+{
+    Mvc_Cover_t * pCover;
+    Mvc_Cube_t * pCube1, * pCube2, * pCubeCopy;
+    // make sure the covers are compatible
+    assert( pCover1->nBits == pCover2->nBits );
+    // clone the cover
+    pCover = Mvc_CoverClone( pCover1 );
+    // create the cubes by making pair-wise products
+    // of cubes in pCover1 and pCover2
+    Mvc_CoverForEachCube( pCover1, pCube1 )
+    {
+        Mvc_CoverForEachCube( pCover2, pCube2 )
+        {
+            if ( Mvc_CoverDist0Cubes( p, pCube1, pCube2 ) )
+            {
+                pCubeCopy = Mvc_CubeAlloc( pCover );
+                Mvc_CubeBitAnd( pCubeCopy, pCube1, pCube2 );
+                Mvc_CoverAddCubeTail( pCover, pCubeCopy );
+            }
+        }
+        // if the number of cubes in the new cover is too large
+        // try compressing them
+        if ( Mvc_CoverReadCubeNum( pCover ) > 500 )
+            Mvc_CoverContain( pCover );
+    }
+    return pCover;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the two covers are equal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverBooleanEqual( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 )
+{
+    Mvc_Cover_t * pSharp;
+
+    pSharp = Mvc_CoverSharp( p, pCover1, pCover2 );
+    if ( Mvc_CoverReadCubeNum( pSharp ) )
+    {
+Mvc_CoverContain( pSharp );
+printf( "Sharp \n" );
+Mvc_CoverPrint( pSharp );
+        Mvc_CoverFree( pSharp );
+        return 0;
+    }
+    Mvc_CoverFree( pSharp );
+
+    pSharp = Mvc_CoverSharp( p, pCover2, pCover1 );
+    if ( Mvc_CoverReadCubeNum( pSharp ) )
+    {
+Mvc_CoverContain( pSharp );
+printf( "Sharp \n" );
+Mvc_CoverPrint( pSharp );
+        Mvc_CoverFree( pSharp );
+        return 0;
+    }
+    Mvc_CoverFree( pSharp );
+
+    return 1;
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/mvc/mvcPrint.c b/abc-build/src/misc/mvc/mvcPrint.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/mvcPrint.c
@@ -0,0 +1,225 @@
+/**CFile****************************************************************
+
+  FileName    [mvcPrint.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Printing cubes and covers.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: mvcPrint.c,v 1.6 2003/04/09 18:02:06 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+//#include "vm.h"
+//#include "vmInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Mvc_CubePrintBinary( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverPrint( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCube;
+    int i;
+    // print general statistics
+    printf( "The cover contains %d cubes (%d bits and %d words)\n", 
+        pCover->lCubes.nItems, pCover->nBits, pCover->nWords );
+    // iterate through the cubes
+    Mvc_CoverForEachCube( pCover, pCube )
+        Mvc_CubePrint( pCover, pCube );
+
+    if ( pCover->pLits )
+    {
+        for ( i = 0; i < pCover->nBits; i++ )
+            printf( " %d", pCover->pLits[i] );
+        printf( "\n" ); 
+    }
+    printf( "End of cover printout\n" ); 
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CubePrint( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+    int iBit, Value;
+    // iterate through the literals
+//    printf( "Size = %2d   ", Mvc_CubeReadSize(pCube) );
+    Mvc_CubeForEachBit( pCover, pCube, iBit, Value )
+        printf( "%c", '0' + Value );
+    printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverPrintBinary( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCube;
+    int i;
+    // print general statistics
+    printf( "The cover contains %d cubes (%d bits and %d words)\n", 
+        pCover->lCubes.nItems, pCover->nBits, pCover->nWords );
+    // iterate through the cubes
+    Mvc_CoverForEachCube( pCover, pCube )
+        Mvc_CubePrintBinary( pCover, pCube );
+
+    if ( pCover->pLits )
+    {
+        for ( i = 0; i < pCover->nBits; i++ )
+            printf( " %d", pCover->pLits[i] );
+        printf( "\n" ); 
+    }
+    printf( "End of cover printout\n" ); 
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CubePrintBinary( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+    int iVar, Value;
+    // iterate through the literals
+//    printf( "Size = %2d   ", Mvc_CubeReadSize(pCube) );
+    Mvc_CubeForEachVarValue( pCover, pCube, iVar, Value )
+    {
+        assert( Value != 0 );
+        if ( Value == 3 )
+            printf( "-" );
+        else if ( Value == 1 )
+            printf( "0" );
+        else 
+            printf( "1" );
+    }
+    printf( "\n" );
+}
+
+#if 0
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverPrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCube;
+    int i;
+    // print general statistics
+    printf( "The cover contains %d cubes (%d bits and %d words)\n", 
+        pCover->lCubes.nItems, pCover->nBits, pCover->nWords );
+    // iterate through the cubes
+    Mvc_CoverForEachCube( pCover, pCube )
+        Mvc_CubePrintMv( pData, pCover, pCube );
+
+    if ( pCover->pLits )
+    {
+        for ( i = 0; i < pCover->nBits; i++ )
+            printf( " %d", pCover->pLits[i] );
+        printf( "\n" ); 
+    }
+    printf( "End of cover printout\n" ); 
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CubePrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+    int iLit, iVar;
+    // iterate through the literals
+    printf( "Size = %2d   ", Mvc_CubeReadSize(pCube) );
+    iVar = 0;
+    for ( iLit = 0; iLit < pData->pVm->nValuesIn; iLit++ )
+    {
+        if ( iLit == pData->pVm->pValuesFirst[iVar+1] )
+        {
+            printf( " " );
+            iVar++;
+        }
+        if ( Mvc_CubeBitValue( pCube, iLit ) )
+            printf( "%c", '0' + iLit - pData->pVm->pValuesFirst[iVar] );
+        else
+            printf( "-" );
+    }
+    printf( "\n" );
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/mvc/mvcSort.c b/abc-build/src/misc/mvc/mvcSort.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/mvcSort.c
@@ -0,0 +1,146 @@
+/**CFile****************************************************************
+
+  FileName    [mvcSort.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Sorting cubes in the cover with the mask.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [uC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: mvcSort.c,v 1.5 2003/04/27 01:03:45 wjiang Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+
+Mvc_Cube_t * Mvc_CoverSort_rec( Mvc_Cube_t * pList, int nItems, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) );
+Mvc_Cube_t * Mvc_CoverSortMerge( Mvc_Cube_t * pList1, Mvc_Cube_t * pList2, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) );
+
+////////////////////////////////////////////////////////////////////////
+///                     FuNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts cubes using the given cost function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverSort( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) )
+{
+    Mvc_Cube_t * pHead;
+    int nCubes;
+    // one cube does not need sorting
+    nCubes = Mvc_CoverReadCubeNum(pCover);
+    if ( nCubes <= 1 )
+        return;
+    // sort the cubes 
+    pHead = Mvc_CoverSort_rec( Mvc_CoverReadCubeHead(pCover), nCubes, pMask, pCompareFunc ); 
+    // insert the sorted list into the cover
+    Mvc_CoverSetCubeHead( pCover, pHead );
+    Mvc_CoverSetCubeTail( pCover, Mvc_ListGetTailFromHead(pHead) );
+    // make sure that the list is sorted in the increasing order
+    assert( pCompareFunc( Mvc_CoverReadCubeHead(pCover), Mvc_CoverReadCubeTail(pCover), pMask ) <= 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursive part of Mvc_CoverSort()]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cube_t * Mvc_CoverSort_rec( Mvc_Cube_t * pList, int nItems, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) )
+{
+    Mvc_Cube_t * pList1, * pList2;
+    int nItems1, nItems2, i;
+
+    // trivial case
+    if ( nItems == 1 )
+    {
+        Mvc_CubeSetNext( pList, NULL );
+        return pList;
+    }
+
+    // select the new sizes
+    nItems1 = nItems/2;
+    nItems2 = nItems - nItems1;
+
+    // set the new beginnings
+    pList1 = pList2 = pList;
+    for ( i = 0; i < nItems1; i++ )
+        pList2 = Mvc_CubeReadNext( pList2 );
+
+    // solve recursively
+    pList1 = Mvc_CoverSort_rec( pList1, nItems1, pMask, pCompareFunc );
+    pList2 = Mvc_CoverSort_rec( pList2, nItems2, pMask, pCompareFunc );
+
+    // merge
+    return Mvc_CoverSortMerge( pList1, pList2, pMask, pCompareFunc );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two NULL-terminated linked lists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cube_t * Mvc_CoverSortMerge( Mvc_Cube_t * pList1, Mvc_Cube_t * pList2, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) )
+{
+    Mvc_Cube_t * pList = NULL, ** ppTail = &pList;
+    Mvc_Cube_t * pCube;
+    while ( pList1 && pList2 )
+    {
+        if ( pCompareFunc( pList1, pList2, pMask ) < 0 )
+        {
+            pCube = pList1;
+            pList1 = Mvc_CubeReadNext(pList1);
+        }
+        else
+        {
+            pCube = pList2;
+            pList2 = Mvc_CubeReadNext(pList2);
+        }
+        *ppTail = pCube;
+        ppTail = Mvc_CubeReadNextP(pCube);
+    }
+    *ppTail = pList1? pList1: pList2;
+    return pList;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/mvc/mvcUtils.c b/abc-build/src/misc/mvc/mvcUtils.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/mvc/mvcUtils.c
@@ -0,0 +1,873 @@
+/**CFile****************************************************************
+
+  FileName    [mvcUtils.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Various cover handling utilities.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: mvcUtils.c,v 1.7 2003/04/26 20:41:36 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int bit_count[256] = {
+  0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+  1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+  1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+  2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+  1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+  2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+  2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+  3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
+
+
+static void Mvc_CoverCopyColumn( Mvc_Cover_t * pCoverOld, Mvc_Cover_t * pCoverNew, int iColOld, int iColNew );
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverSupport( Mvc_Cover_t * pCover, Mvc_Cube_t * pSupp )
+{
+    Mvc_Cube_t * pCube;
+    // clean the support
+    Mvc_CubeBitClean( pSupp );
+    // collect the support
+    Mvc_CoverForEachCube( pCover, pCube )
+        Mvc_CubeBitOr( pSupp, pSupp, pCube );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverSupportAnd( Mvc_Cover_t * pCover, Mvc_Cube_t * pSupp )
+{
+    Mvc_Cube_t * pCube;
+    // clean the support
+    Mvc_CubeBitFill( pSupp );
+    // collect the support
+    Mvc_CoverForEachCube( pCover, pCube )
+        Mvc_CubeBitAnd( pSupp, pSupp, pCube );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverSupportSizeBinary( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pSupp;
+    int Counter, i, v0, v1;
+    // compute the support
+    pSupp = Mvc_CubeAlloc( pCover );
+    Mvc_CoverSupportAnd( pCover, pSupp );
+    Counter = pCover->nBits/2;
+    for ( i = 0; i < pCover->nBits/2; i++ )
+    {
+        v0 = Mvc_CubeBitValue( pSupp, 2*i   );
+        v1 = Mvc_CubeBitValue( pSupp, 2*i+1 );
+        if ( v0 && v1 )
+            Counter--;
+    }
+    Mvc_CubeFree( pCover, pSupp );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverSupportVarBelongs( Mvc_Cover_t * pCover, int iVar )
+{
+    Mvc_Cube_t * pSupp;
+    int RetValue, v0, v1;
+    // compute the support
+    pSupp = Mvc_CubeAlloc( pCover );
+    Mvc_CoverSupportAnd( pCover, pSupp );
+    v0 = Mvc_CubeBitValue( pSupp, 2*iVar   );
+    v1 = Mvc_CubeBitValue( pSupp, 2*iVar+1 );
+    RetValue = (int)( !v0 || !v1 );
+    Mvc_CubeFree( pCover, pSupp );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverCommonCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pComCube )
+{
+    Mvc_Cube_t * pCube;
+    // clean the support
+    Mvc_CubeBitFill( pComCube );
+    // collect the support
+    Mvc_CoverForEachCube( pCover, pCube )
+        Mvc_CubeBitAnd( pComCube, pComCube, pCube );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverIsCubeFree( Mvc_Cover_t * pCover )
+{
+    int Result;
+    // get the common cube
+    Mvc_CoverAllocateMask( pCover );
+    Mvc_CoverCommonCube( pCover, pCover->pMask );
+    // check whether the common cube is empty
+    Mvc_CubeBitEmpty( Result, pCover->pMask );
+    return Result;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverMakeCubeFree( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCube;
+    // get the common cube
+    Mvc_CoverAllocateMask( pCover );
+    Mvc_CoverCommonCube( pCover, pCover->pMask );
+    // remove this cube from the cubes in the cover
+    Mvc_CoverForEachCube( pCover, pCube )
+        Mvc_CubeBitSharp( pCube, pCube, pCover->pMask );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverCommonCubeCover( Mvc_Cover_t * pCover )
+{
+    Mvc_Cover_t * pRes;
+    Mvc_Cube_t * pCube;
+    // create the new cover
+    pRes = Mvc_CoverClone( pCover );
+    // get the new cube
+    pCube = Mvc_CubeAlloc( pRes );
+    // get the common cube
+    Mvc_CoverCommonCube( pCover, pCube );
+    // add the cube to the cover
+    Mvc_CoverAddCubeTail( pRes, pCube );
+    return pRes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the support of cover2 is contained in the support of cover1.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverCheckSuppContainment( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 )
+{
+    int Result;
+    assert( pCover1->nBits == pCover2->nBits );
+    // set the supports
+    Mvc_CoverAllocateMask( pCover1 );
+    Mvc_CoverSupport( pCover1, pCover1->pMask );
+    Mvc_CoverAllocateMask( pCover2 );
+    Mvc_CoverSupport( pCover2, pCover2->pMask );
+    // check the containment
+    Mvc_CubeBitNotImpl( Result, pCover2->pMask, pCover1->pMask );
+    return !Result;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the cube sizes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverSetCubeSizes( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCube;
+    unsigned char * pByte, * pByteStart, * pByteStop;
+    int nBytes, nOnes;
+
+    // get the number of unsigned chars in the cube's bit strings
+    nBytes = pCover->nBits / (8 * sizeof(unsigned char)) + (int)(pCover->nBits % (8 * sizeof(unsigned char)) > 0);
+    // iterate through the cubes
+    Mvc_CoverForEachCube( pCover, pCube )
+    {
+        // clean the counter of ones
+        nOnes = 0;
+        // set the starting and stopping positions
+        pByteStart = (unsigned char *)pCube->pData;
+        pByteStop  = pByteStart + nBytes;
+        // iterate through the positions
+        for ( pByte = pByteStart; pByte < pByteStop; pByte++ )
+            nOnes += bit_count[*pByte];
+        // set the nOnes
+        Mvc_CubeSetSize( pCube, nOnes );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the cube sizes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverGetCubeSize( Mvc_Cube_t * pCube )
+{
+    unsigned char * pByte, * pByteStart, * pByteStop;
+    int nOnes, nBytes, nBits;
+    // get the number of unsigned chars in the cube's bit strings
+    nBits = (pCube->iLast + 1) * sizeof(Mvc_CubeWord_t) * 8 - pCube->nUnused;
+    nBytes = nBits / (8 * sizeof(unsigned char)) + (int)(nBits % (8 * sizeof(unsigned char)) > 0);
+    // clean the counter of ones
+    nOnes = 0;
+    // set the starting and stopping positions
+    pByteStart = (unsigned char *)pCube->pData;
+    pByteStop  = pByteStart + nBytes;
+    // iterate through the positions
+    for ( pByte = pByteStart; pByte < pByteStop; pByte++ )
+        nOnes += bit_count[*pByte];
+    return nOnes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the differences in each cube pair in the cover.]
+
+  Description [Takes the cover (pCover) and the array where the
+  diff counters go (pDiffs). The array pDiffs should have as many
+  entries as there are different pairs of cubes in the cover: n(n-1)/2.
+  Fills out the array pDiffs with the following info: For each cube
+  pair, included in the array is the number of literals in both cubes
+  after they are made cube ABC_FREE.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_CoverCountCubePairDiffs( Mvc_Cover_t * pCover, unsigned char pDiffs[] )
+{
+    Mvc_Cube_t * pCube1;
+    Mvc_Cube_t * pCube2;
+    Mvc_Cube_t * pMask;
+    unsigned char * pByte, * pByteStart, * pByteStop;
+    int nBytes, nOnes;
+    int nCubePairs;
+
+    // allocate a temporary mask
+    pMask = Mvc_CubeAlloc( pCover );
+    // get the number of unsigned chars in the cube's bit strings
+    nBytes = pCover->nBits / (8 * sizeof(unsigned char)) + (int)(pCover->nBits % (8 * sizeof(unsigned char)) > 0);
+    // iterate through the cubes
+    nCubePairs = 0;
+    Mvc_CoverForEachCube( pCover, pCube1 )
+    {
+        Mvc_CoverForEachCubeStart( Mvc_CubeReadNext(pCube1), pCube2 )
+        {
+            // find the bit-wise exor of cubes
+            Mvc_CubeBitExor( pMask, pCube1, pCube2 );
+            // set the starting and stopping positions
+            pByteStart = (unsigned char *)pMask->pData;
+            pByteStop  = pByteStart + nBytes;
+            // clean the counter of ones
+            nOnes = 0;
+            // iterate through the positions
+            for ( pByte = pByteStart; pByte < pByteStop; pByte++ )
+                nOnes += bit_count[*pByte];
+            // set the nOnes
+            pDiffs[nCubePairs++] = nOnes;
+        }
+    }
+    // deallocate the mask
+    Mvc_CubeFree( pCover, pMask );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new cover containing some literals of the old cover.]
+
+  Description [Creates the new cover containing the given number (nVarsRem)
+  literals of the old cover. All the bits of the new cover are initialized
+  to "1". The selected bits from the old cover are copied on top. The numbers
+  of the selected bits to copy are given in the array pVarsRem. The i-set
+  entry in this array is the index of the bit in the old cover which goes
+  to the i-th place in the new cover. If the i-th entry in pVarsRem is -1, 
+  it means that the i-th bit does not change (remains composed of all 1's).
+  This is a useful feature to speed up remapping covers, which are known
+  to depend only on a subset of input variables.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverRemap( Mvc_Cover_t * p, int * pVarsRem, int nVarsRem )
+{
+    Mvc_Cover_t * pCover;
+    Mvc_Cube_t * pCube, * pCubeCopy;
+    int i;
+    // clone the cover
+    pCover = Mvc_CoverAlloc( p->pMem, nVarsRem );
+    // copy the cube list
+    Mvc_CoverForEachCube( p, pCube )
+    {
+        pCubeCopy = Mvc_CubeAlloc( pCover );
+        //Mvc_CubeBitClean( pCubeCopy );   //changed by wjiang
+        Mvc_CubeBitFill( pCubeCopy );      //changed by wjiang
+        Mvc_CoverAddCubeTail( pCover, pCubeCopy );
+    }
+    // copy the corresponding columns
+    for ( i = 0; i < nVarsRem; i++ )
+    {
+        if (pVarsRem[i] < 0) 
+            continue;     //added by wjiang
+        assert( pVarsRem[i] >= 0 && pVarsRem[i] < p->nBits );
+        Mvc_CoverCopyColumn( p, pCover, pVarsRem[i], i );
+    }
+    return pCover;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Copies a column from the old cover to the new cover.]
+
+  Description [Copies the column (iColOld) of the old cover (pCoverOld)
+  into the column (iColNew) of the new cover (pCoverNew). Assumes that 
+  the number of cubes is the same in both covers. Makes no assuptions 
+  about the current contents of the column in the new cover.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverCopyColumn( Mvc_Cover_t * pCoverOld, Mvc_Cover_t * pCoverNew, 
+                         int iColOld, int iColNew )
+{
+    Mvc_Cube_t * pCubeOld, * pCubeNew;
+    int iWordOld, iWordNew, iBitOld, iBitNew;
+
+    assert( Mvc_CoverReadCubeNum(pCoverOld) == Mvc_CoverReadCubeNum(pCoverNew) );
+
+    // get the place of the old and new columns
+    iWordOld = Mvc_CubeWhichWord(iColOld);
+    iBitOld  = Mvc_CubeWhichBit(iColOld);
+    iWordNew = Mvc_CubeWhichWord(iColNew);
+    iBitNew  = Mvc_CubeWhichBit(iColNew);
+
+    // go through the cubes of both covers
+    pCubeNew = Mvc_CoverReadCubeHead(pCoverNew);
+    Mvc_CoverForEachCube( pCoverOld, pCubeOld )
+    {
+        if ( pCubeOld->pData[iWordOld] & (1<<iBitOld) )
+            pCubeNew->pData[iWordNew] |= (1<<iBitNew);
+        else
+            pCubeNew->pData[iWordNew] &= ~(1<<iBitNew);  // added by wjiang
+        pCubeNew = Mvc_CubeReadNext( pCubeNew );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mvc_CoverInverse( Mvc_Cover_t * pCover )
+{
+    Mvc_Cube_t * pCube;
+    // complement the cubes
+    Mvc_CoverForEachCube( pCover, pCube )
+        Mvc_CubeBitNot( pCube );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This function dups the cover and removes DC literals from cubes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverRemoveDontCareLits( Mvc_Cover_t * pCover )
+{
+    Mvc_Cover_t * pCoverNew;
+    Mvc_Cube_t * pCube;
+
+    pCoverNew = Mvc_CoverDup( pCover );
+    Mvc_CoverForEachCube( pCoverNew, pCube )
+        Mvc_CubeBitRemoveDcs( pCube );
+    return pCoverNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the cofactor w.r.t. to a binary var.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverCofactor( Mvc_Cover_t * p, int iValue, int iValueOther )
+{
+    Mvc_Cover_t * pCover;
+    Mvc_Cube_t * pCube, * pCubeCopy;
+    // clone the cover
+    pCover = Mvc_CoverClone( p );
+    // copy the cube list
+    Mvc_CoverForEachCube( p, pCube )
+        if ( Mvc_CubeBitValue( pCube, iValue ) )
+        {
+            pCubeCopy = Mvc_CubeDup( pCover, pCube );
+            Mvc_CoverAddCubeTail( pCover, pCubeCopy );
+            Mvc_CubeBitInsert( pCubeCopy, iValueOther );
+        }
+    return pCover;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the cover, in which the binary var is complemented.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverFlipVar( Mvc_Cover_t * p, int iValue0, int iValue1 )
+{
+    Mvc_Cover_t * pCover;
+    Mvc_Cube_t * pCube, * pCubeCopy;
+    int Value0, Value1, Temp;
+
+    assert( iValue0 + 1 == iValue1 ); // should be adjacent
+
+    // clone the cover
+    pCover = Mvc_CoverClone( p );
+    // copy the cube list
+    Mvc_CoverForEachCube( p, pCube )
+    {
+        pCubeCopy = Mvc_CubeDup( pCover, pCube );
+        Mvc_CoverAddCubeTail( pCover, pCubeCopy );
+
+        // get the bits
+        Value0 = Mvc_CubeBitValue( pCubeCopy, iValue0 );
+        Value1 = Mvc_CubeBitValue( pCubeCopy, iValue1 );
+
+        // if both bits are one, nothing to swap
+        if ( Value0 && Value1 )
+            continue;
+        // cannot be both zero because they belong to the same var
+        assert( Value0 || Value1 ); 
+
+        // swap the bits
+        Temp   = Value0;
+        Value0 = Value1;
+        Value1 = Temp;
+
+        // set the bits after the swap
+        if ( Value0 )
+            Mvc_CubeBitInsert( pCubeCopy, iValue0 );
+        else
+            Mvc_CubeBitRemove( pCubeCopy, iValue0 );
+
+        if ( Value1 )
+            Mvc_CubeBitInsert( pCubeCopy, iValue1 );
+        else
+            Mvc_CubeBitRemove( pCubeCopy, iValue1 );
+    }
+    return pCover;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the cover derived by universal quantification.]
+
+  Description [Returns the cover computed by universal quantification
+  as follows: CoverNew = Univ(B) [Cover & (A==B)]. Removes the second 
+  binary var from the support (given by values iValueB0 and iValueB1). 
+  Leaves the first binary variable (given by values iValueA0 and iValueA1) 
+  in the support.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverUnivQuantify( Mvc_Cover_t * p, 
+    int iValueA0, int iValueA1, int iValueB0, int iValueB1 )
+{
+    Mvc_Cover_t * pCover;
+    Mvc_Cube_t * pCube, * pCubeCopy;
+    int ValueA0, ValueA1, ValueB0, ValueB1;
+
+    // clone the cover
+    pCover = Mvc_CoverClone( p );
+    // copy the cube list
+    Mvc_CoverForEachCube( p, pCube )
+    {
+        // get the bits
+        ValueA0 = Mvc_CubeBitValue( pCube, iValueA0 );
+        ValueA1 = Mvc_CubeBitValue( pCube, iValueA1 );
+        ValueB0 = Mvc_CubeBitValue( pCube, iValueB0 );
+        ValueB1 = Mvc_CubeBitValue( pCube, iValueB1 );
+
+        // cannot be both zero because they belong to the same var
+        assert( ValueA0 || ValueA1 ); 
+        assert( ValueB0 || ValueB1 ); 
+
+        // if the values of this var are different, do not add the cube
+        if ( ValueA0 != ValueB0 && ValueA1 != ValueB1 )
+            continue;
+
+        // create the cube
+        pCubeCopy = Mvc_CubeDup( pCover, pCube );
+        Mvc_CoverAddCubeTail( pCover, pCubeCopy );
+
+        // insert 1's into for the first var, if both have this value
+        if ( ValueA0 && ValueB0 )
+            Mvc_CubeBitInsert( pCubeCopy, iValueA0 );
+        else
+            Mvc_CubeBitRemove( pCubeCopy, iValueA0 );
+
+        if ( ValueA1 && ValueB1 )
+            Mvc_CubeBitInsert( pCubeCopy, iValueA1 );
+        else
+            Mvc_CubeBitRemove( pCubeCopy, iValueA1 );
+            
+        // insert 1's into for the second var (the cover does not depend on it)
+        Mvc_CubeBitInsert( pCubeCopy, iValueB0 );
+        Mvc_CubeBitInsert( pCubeCopy, iValueB1 );
+    }
+    return pCover;
+}
+
+#if 0
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the cofactors of the cover.]
+
+  Description [Derives the cofactors w.r.t. a variable and also cubes
+  that do not depend on this variable.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t ** Mvc_CoverCofactors( Mvc_Data_t * pData, Mvc_Cover_t * pCover, int iVar )
+{
+    Mvc_Cover_t ** ppCofs;
+    Mvc_Cube_t * pCube, * pCubeNew;
+    int i, nValues, iValueFirst, Res;
+
+    // start the covers for cofactors
+    iValueFirst = Vm_VarMapReadValuesFirst(pData->pVm, iVar);
+    nValues = Vm_VarMapReadValues(pData->pVm, iVar);
+    ppCofs = ABC_ALLOC( Mvc_Cover_t *, nValues + 1 );
+    for ( i = 0; i <= nValues; i++ )
+        ppCofs[i] = Mvc_CoverClone( pCover );
+
+    // go through the cubes
+    Mvc_CoverForEachCube( pCover, pCube )
+    {
+        // if the literal if a full literal, add it to last "cofactor"
+        Mvc_CubeBitEqualUnderMask( Res, pCube, pData->ppMasks[iVar], pData->ppMasks[iVar] );
+        if ( Res )
+        {
+            pCubeNew = Mvc_CubeDup(pCover, pCube);
+            Mvc_CoverAddCubeTail( ppCofs[nValues], pCubeNew );
+            continue;
+        }
+
+        // otherwise, add it to separate values
+        for ( i = 0; i < nValues; i++ )
+            if ( Mvc_CubeBitValue( pCube, iValueFirst + i ) )
+            {
+                pCubeNew = Mvc_CubeDup(pCover, pCube);
+                Mvc_CubeBitOr( pCubeNew, pCubeNew, pData->ppMasks[iVar] );
+                Mvc_CoverAddCubeTail( ppCofs[i], pCubeNew );
+            }
+    }
+    return ppCofs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the cubes with non-trivial literals with the given value.]
+
+  Description [The data and the cover are given (pData, pCover). Also given 
+  are the variable number and the number of a value of this variable.
+  This procedure returns the number of cubes having a non-trivial literal
+  of this variable that have the given value present.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvr_CoverCountLitsWithValue( Mvc_Data_t * pData, Mvc_Cover_t * pCover, int iVar, int iValue )
+{
+    Mvc_Cube_t * pCube;
+    int iValueFirst, Res, Counter;
+
+    Counter = 0;
+    iValueFirst = Vm_VarMapReadValuesFirst( pData->pVm, iVar );
+    Mvc_CoverForEachCube( pCover, pCube )
+    {
+        // check if the given literal is the full literal
+        Mvc_CubeBitEqualUnderMask( Res, pCube, pData->ppMasks[iVar], pData->ppMasks[iVar] );
+        if ( Res )
+            continue;
+        // this literal is not a full literal; check if it has this value
+        Counter += Mvc_CubeBitValue( pCube, iValueFirst + iValue );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the expanded cover.]
+
+  Description [The original cover is expanded by adding some variables.
+  These variables are the additional variables in pVmNew, compared to
+  pCvr->pVm. The resulting cover is the same as the original one, except
+  that it contains the additional variables present as full literals
+  in every cube.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverCreateExpanded( Mvc_Cover_t * pCover, Vm_VarMap_t * pVmNew )
+{
+    Mvc_Cover_t * pCoverNew;
+    Mvc_Cube_t * pCube, * pCubeNew;
+    int i, iLast, iLastNew;
+
+    // create the new cover
+    pCoverNew = Mvc_CoverAlloc( pCover->pMem, Vm_VarMapReadValuesInNum(pVmNew) );
+
+    // get the cube composed of extra bits
+    Mvc_CoverAllocateMask( pCoverNew );
+    Mvc_CubeBitClean( pCoverNew->pMask );
+    for ( i = pCover->nBits; i < pCoverNew->nBits; i++ )
+        Mvc_CubeBitInsert( pCoverNew->pMask, i );
+
+    // get the indexes of the last words in both covers
+    iLast    = pCover->nWords?    pCover->nWords - 1: 0;
+    iLastNew = pCoverNew->nWords? pCoverNew->nWords - 1: 0;
+
+    // create the cubes of the new cover
+    Mvc_CoverForEachCube( pCover, pCube )
+    {
+        pCubeNew = Mvc_CubeAlloc( pCoverNew );
+        Mvc_CubeBitClean( pCubeNew );
+        // copy the bits (cannot immediately use Mvc_CubeBitCopy, 
+        // because covers have different numbers of bits)
+        Mvc_CubeSetLast( pCubeNew, iLast );
+        Mvc_CubeBitCopy( pCubeNew, pCube );
+        Mvc_CubeSetLast( pCubeNew, iLastNew );
+        // add the extra bits
+        Mvc_CubeBitOr( pCubeNew, pCubeNew, pCoverNew->pMask );
+        // add the cube to the new cover
+        Mvc_CoverAddCubeTail( pCoverNew, pCubeNew );
+    }
+    return pCoverNew;
+}
+
+#endif
+
+/**Function*************************************************************
+
+  Synopsis    [Transposes the cube cover.]
+
+  Description [Returns the cube cover that looks like a transposed
+  matrix, compared to the matrix derived from the original cover.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverTranspose( Mvc_Cover_t * pCover )
+{
+    Mvc_Cover_t * pRes;
+    Mvc_Cube_t * pCubeRes, * pCube;
+    int nWord, nBit, i, iCube;
+
+    pRes = Mvc_CoverAlloc( pCover->pMem, Mvc_CoverReadCubeNum(pCover) );
+    for ( i = 0; i < pCover->nBits; i++ )
+    {
+        // get the word and bit of this literal
+        nWord = Mvc_CubeWhichWord(i);
+        nBit  = Mvc_CubeWhichBit(i);
+        // get the transposed cube
+        pCubeRes = Mvc_CubeAlloc( pRes );
+        Mvc_CubeBitClean( pCubeRes );
+        iCube = 0;
+        Mvc_CoverForEachCube( pCover, pCube )
+        {
+            if ( pCube->pData[nWord] & (1<<nBit) )
+                Mvc_CubeBitInsert( pCubeRes, iCube );
+            iCube++;
+        }
+        Mvc_CoverAddCubeTail( pRes, pCubeRes ); 
+    }
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks that the cubes of the cover have 0's in unused bits.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mvc_UtilsCheckUnusedZeros( Mvc_Cover_t * pCover )
+{
+    unsigned Unsigned;
+    Mvc_Cube_t * pCube;
+    int nCubes;
+
+    nCubes = 0;
+    Mvc_CoverForEachCube( pCover, pCube )
+    {
+        if ( pCube->nUnused == 0 )
+            continue;
+
+        Unsigned = ( pCube->pData[pCube->iLast] & 
+                    (BITS_FULL << (32-pCube->nUnused)) );
+        if( Unsigned )
+        {
+            printf( "Cube %2d out of %2d contains dirty bits.\n", nCubes, 
+                Mvc_CoverReadCubeNum(pCover) );
+        }
+        nCubes++;
+    }
+    return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/nm/module.make b/abc-build/src/misc/nm/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/nm/module.make
@@ -0,0 +1,2 @@
+SRC +=  src/misc/nm/nmApi.c \
+	src/misc/nm/nmTable.c
diff --git a/abc-build/src/misc/nm/nm.h b/abc-build/src/misc/nm/nm.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/nm/nm.h
@@ -0,0 +1,96 @@
+/**CFilextern e****************************************************************
+
+  FileName    [nm.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Name manager.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nm.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__nm__nm_h
+#define ABC__misc__nm__nm_h
+
+
+/*
+    This manager is designed to store ID-to-name and name-to-ID mapping
+    for Boolean networks and And-Inverter Graphs.
+    
+    In a netlist, net names are unique. In this case, there is a one-to-one
+    mapping between IDs and names.
+
+    In a logic network, which do not have nets, several objects may have
+    the same name. For example, a latch output and a primary output.
+    Another example, a primary input and an input to a black box.
+    In this case, for each ID on an object there is only one name, 
+    but for each name may be several IDs of objects having this name.
+
+    The name manager maps ID-to-name uniquely but it allows one name to 
+    be mapped into several IDs. When a query to find an ID of the object
+    by its name is submitted, it is possible to specify the object type, 
+    which will help select one of several IDs. If the type is -1, and 
+    there is more than one object with the given name, any object with 
+    the given name is returned.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Nm_Man_t_ Nm_Man_t;
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== nmApi.c ==========================================================*/
+extern Nm_Man_t *   Nm_ManCreate( int nSize );
+extern void         Nm_ManFree( Nm_Man_t * p );
+extern int          Nm_ManNumEntries( Nm_Man_t * p );
+extern char *       Nm_ManStoreIdName( Nm_Man_t * p, int ObjId, int Type, char * pName, char * pSuffix );
+extern void         Nm_ManDeleteIdName( Nm_Man_t * p, int ObjId );
+extern char *       Nm_ManCreateUniqueName( Nm_Man_t * p, int ObjId );
+extern char *       Nm_ManFindNameById( Nm_Man_t * p, int ObjId );
+extern int          Nm_ManFindIdByName( Nm_Man_t * p, char * pName, int Type );
+extern int          Nm_ManFindIdByNameTwoTypes( Nm_Man_t * p, char * pName, int Type1, int Type2 );
+extern Vec_Int_t *  Nm_ManReturnNameIds( Nm_Man_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/nm/nmApi.c b/abc-build/src/misc/nm/nmApi.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/nm/nmApi.c
@@ -0,0 +1,278 @@
+/**CFile****************************************************************
+
+  FileName    [nmApi.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Name manager.]
+
+  Synopsis    [APIs of the name manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nmApi.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nmInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the name manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Nm_Man_t * Nm_ManCreate( int nSize )
+{
+    Nm_Man_t * p;
+    // allocate the table
+    p = ABC_ALLOC( Nm_Man_t, 1 );
+    memset( p, 0, sizeof(Nm_Man_t) );
+    // set the parameters
+    p->nSizeFactor   = 2; // determined the limit on the grow of data before the table resizes
+    p->nGrowthFactor = 3; // determined how much the table grows after resizing
+    // allocate and clean the bins
+    p->nBins = Abc_PrimeCudd(nSize);
+    p->pBinsI2N = ABC_ALLOC( Nm_Entry_t *, p->nBins );
+    p->pBinsN2I = ABC_ALLOC( Nm_Entry_t *, p->nBins );
+    memset( p->pBinsI2N, 0, sizeof(Nm_Entry_t *) * p->nBins );
+    memset( p->pBinsN2I, 0, sizeof(Nm_Entry_t *) * p->nBins );
+    // start the memory manager
+    p->pMem = Extra_MmFlexStart();
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the name manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nm_ManFree( Nm_Man_t * p )
+{
+    Extra_MmFlexStop( p->pMem );
+    ABC_FREE( p->pBinsI2N );
+    ABC_FREE( p->pBinsN2I );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of objects with names.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nm_ManNumEntries( Nm_Man_t * p )
+{
+    return p->nEntries;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new entry in the name manager.]
+
+  Description [Returns 1 if the entry with the given object ID
+  already exists in the name manager.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Nm_ManStoreIdName( Nm_Man_t * p, int ObjId, int Type, char * pName, char * pSuffix )
+{
+    Nm_Entry_t * pEntry;
+    int RetValue, nEntrySize;
+    // check if the object with this ID is already stored
+    if ( (pEntry = Nm_ManTableLookupId(p, ObjId)) )
+    {
+        printf( "Nm_ManStoreIdName(): Entry with the same ID already exists.\n" );
+        return NULL;
+    }
+    // create a new entry
+    nEntrySize = sizeof(Nm_Entry_t) + strlen(pName) + (pSuffix?strlen(pSuffix):0) + 1;
+//    nEntrySize = (nEntrySize / 4 + ((nEntrySize % 4) > 0)) * 4;
+    nEntrySize = (nEntrySize / sizeof(char*) + ((nEntrySize % sizeof(char*)) > 0)) * sizeof(char*); // added by Saurabh on Sep 3, 2009
+    pEntry = (Nm_Entry_t *)Extra_MmFlexEntryFetch( p->pMem, nEntrySize );
+    pEntry->pNextI2N = pEntry->pNextN2I = pEntry->pNameSake = NULL;
+    pEntry->ObjId = ObjId;
+    pEntry->Type = Type;
+    sprintf( pEntry->Name, "%s%s", pName, pSuffix? pSuffix : "" );
+    // add the entry to the hash table
+    RetValue = Nm_ManTableAdd( p, pEntry );
+    assert( RetValue == 1 );
+    return pEntry->Name;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new entry in the name manager.]
+
+  Description [Returns 1 if the entry with the given object ID
+  already exists in the name manager.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nm_ManDeleteIdName( Nm_Man_t * p, int ObjId )
+{
+    Nm_Entry_t * pEntry;
+    pEntry = Nm_ManTableLookupId(p, ObjId);
+    if ( pEntry == NULL )
+    {
+        printf( "Nm_ManDeleteIdName(): This entry is not in the table.\n" );
+        return;
+    }
+    // remove entry from the table
+    Nm_ManTableDelete( p, ObjId );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds a unique name for the node.]
+
+  Description [If the name exists, tries appending numbers to it until 
+  it becomes unique. The name is not added to the table.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Nm_ManCreateUniqueName( Nm_Man_t * p, int ObjId )
+{
+    static char NameStr[1000];
+    Nm_Entry_t * pEntry;
+    int i;
+    if ( (pEntry = Nm_ManTableLookupId(p, ObjId)) )
+        return pEntry->Name;
+    sprintf( NameStr, "n%d", ObjId );
+    for ( i = 1; Nm_ManTableLookupName(p, NameStr, -1); i++ )
+        sprintf( NameStr, "n%d_%d", ObjId, i );
+    return NameStr;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns name of the object if the ID is known.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Nm_ManFindNameById( Nm_Man_t * p, int ObjId )
+{
+    Nm_Entry_t * pEntry;
+    if ( (pEntry = Nm_ManTableLookupId(p, ObjId)) )
+        return pEntry->Name;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns ID of the object if its name is known.]
+
+  Description [This procedure may return two IDs because POs and latches 
+  may have the same name (the only allowed case of name duplication).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nm_ManFindIdByName( Nm_Man_t * p, char * pName, int Type )
+{
+    Nm_Entry_t * pEntry;
+    if ( (pEntry = Nm_ManTableLookupName(p, pName, Type)) )
+        return pEntry->ObjId;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns ID of the object if its name is known.]
+
+  Description [This procedure may return two IDs because POs and latches 
+  may have the same name (the only allowed case of name duplication).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nm_ManFindIdByNameTwoTypes( Nm_Man_t * p, char * pName, int Type1, int Type2 )
+{
+    int iNodeId;
+    iNodeId = Nm_ManFindIdByName( p, pName, Type1 );
+    if ( iNodeId == -1 )
+        iNodeId = Nm_ManFindIdByName( p, pName, Type2 );
+    if ( iNodeId == -1 )
+        return -1;
+    return iNodeId;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Return the IDs of objects with names.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Nm_ManReturnNameIds( Nm_Man_t * p )
+{
+    Vec_Int_t * vNameIds;
+    int i;
+    vNameIds = Vec_IntAlloc( p->nEntries );
+    for ( i = 0; i < p->nBins; i++ )
+        if ( p->pBinsI2N[i] )
+            Vec_IntPush( vNameIds, p->pBinsI2N[i]->ObjId );
+    return vNameIds;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/nm/nmInt.h b/abc-build/src/misc/nm/nmInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/nm/nmInt.h
@@ -0,0 +1,94 @@
+/**CFile****************************************************************
+
+  FileName    [nmInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Name manager.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nmInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__nm__nmInt_h
+#define ABC__misc__nm__nmInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "misc/extra/extra.h"
+#include "misc/vec/vec.h"
+#include "nm.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Nm_Entry_t_ Nm_Entry_t;
+struct Nm_Entry_t_
+{
+    unsigned         Type;          // object type
+    unsigned         ObjId;         // object ID
+    Nm_Entry_t *     pNextI2N;      // the next entry in the ID hash table
+    Nm_Entry_t *     pNextN2I;      // the next entry in the name hash table
+    Nm_Entry_t *     pNameSake;     // the next entry with the same name
+    char             Name[0];       // name of the object
+};
+
+struct Nm_Man_t_
+{
+    Nm_Entry_t **    pBinsI2N;      // mapping IDs into names
+    Nm_Entry_t **    pBinsN2I;      // mapping names into IDs 
+    int              nBins;         // the number of bins in tables
+    int              nEntries;      // the number of entries
+    int              nSizeFactor;   // determined how much larger the table should be
+    int              nGrowthFactor; // determined how much the table grows after resizing
+    Extra_MmFlex_t * pMem;          // memory manager for entries (and names)
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== nmTable.c ==========================================================*/
+extern int              Nm_ManTableAdd( Nm_Man_t * p, Nm_Entry_t * pEntry );
+extern int              Nm_ManTableDelete( Nm_Man_t * p, int ObjId );
+extern Nm_Entry_t *     Nm_ManTableLookupId( Nm_Man_t * p, int ObjId );
+extern Nm_Entry_t *     Nm_ManTableLookupName( Nm_Man_t * p, char * pName, int Type );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/abc-build/src/misc/nm/nmTable.c b/abc-build/src/misc/nm/nmTable.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/nm/nmTable.c
@@ -0,0 +1,310 @@
+/**CFile****************************************************************
+
+  FileName    [nmTable.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Name manager.]
+
+  Synopsis    [Hash table for the name manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nmTable.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nmInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// hashing for integers
+static unsigned Nm_HashNumber( int Num, int TableSize ) 
+{
+    unsigned Key = 0;
+    Key ^= ( Num        & 0xFF) * 7937;
+    Key ^= ((Num >>  8) & 0xFF) * 2971;
+    Key ^= ((Num >> 16) & 0xFF) * 911;
+    Key ^= ((Num >> 24) & 0xFF) * 353;
+    return Key % TableSize;
+}
+
+// hashing for strings
+static unsigned Nm_HashString( char * pName, int TableSize ) 
+{
+    static int s_Primes[10] = { 
+        1291, 1699, 2357, 4177, 5147, 
+        5647, 6343, 7103, 7873, 8147
+    };
+    unsigned i, Key = 0;
+    for ( i = 0; pName[i] != '\0'; i++ )
+        Key ^= s_Primes[i%10]*pName[i]*pName[i];
+    return Key % TableSize;
+}
+
+static void Nm_ManResize( Nm_Man_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Adds an entry to two hash tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nm_ManTableAdd( Nm_Man_t * p, Nm_Entry_t * pEntry )
+{
+    Nm_Entry_t ** ppSpot, * pOther;
+    // resize the tables if needed
+    if ( p->nEntries > p->nBins * p->nSizeFactor )
+        Nm_ManResize( p );
+    // add the entry to the table Id->Name
+    assert( Nm_ManTableLookupId(p, pEntry->ObjId) == NULL );
+    ppSpot = p->pBinsI2N + Nm_HashNumber(pEntry->ObjId, p->nBins);
+    pEntry->pNextI2N = *ppSpot;
+    *ppSpot = pEntry;
+    // check if an entry with the same name already exists
+    if ( (pOther = Nm_ManTableLookupName(p, pEntry->Name, -1)) )
+    {
+        // entry with the same name already exists - add it to the ring
+        pEntry->pNameSake = pOther->pNameSake? pOther->pNameSake : pOther;
+        pOther->pNameSake = pEntry;
+    }
+    else
+    {
+        // entry with the same name does not exist - add it to the table
+        ppSpot = p->pBinsN2I + Nm_HashString(pEntry->Name, p->nBins);
+        pEntry->pNextN2I = *ppSpot;
+        *ppSpot = pEntry;
+    }
+    // report successfully added entry
+    p->nEntries++;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the entry from two hash tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nm_ManTableDelete( Nm_Man_t * p, int ObjId )
+{
+    Nm_Entry_t ** ppSpot, * pEntry, * pPrev;
+    int fRemoved;
+    p->nEntries--;
+    // remove the entry from the table Id->Name
+    assert( Nm_ManTableLookupId(p, ObjId) != NULL );
+    ppSpot = p->pBinsI2N + Nm_HashNumber(ObjId, p->nBins);
+    while ( (*ppSpot)->ObjId != (unsigned)ObjId )
+        ppSpot = &(*ppSpot)->pNextI2N;
+    pEntry = *ppSpot; 
+    *ppSpot = (*ppSpot)->pNextI2N;
+    // remove the entry from the table Name->Id
+    ppSpot = p->pBinsN2I + Nm_HashString(pEntry->Name, p->nBins);
+    while ( *ppSpot && *ppSpot != pEntry )
+        ppSpot = &(*ppSpot)->pNextN2I;
+    // remember if we found this one in the list
+    fRemoved = (*ppSpot != NULL);
+    if ( *ppSpot )
+    {
+        assert( *ppSpot == pEntry );
+        *ppSpot = (*ppSpot)->pNextN2I;
+    }
+    // quit if this entry has no namesakes
+    if ( pEntry->pNameSake == NULL )
+    {
+        assert( fRemoved );
+        return 1;
+    }
+    // remove entry from the ring of namesakes
+    assert( pEntry->pNameSake != pEntry );
+    for ( pPrev = pEntry; pPrev->pNameSake != pEntry; pPrev = pPrev->pNameSake );
+    assert( !strcmp(pPrev->Name, pEntry->Name) );
+    assert( pPrev->pNameSake == pEntry );
+    if ( pEntry->pNameSake == pPrev ) // two entries in the ring
+        pPrev->pNameSake = NULL;
+    else
+        pPrev->pNameSake = pEntry->pNameSake;
+    // reinsert the ring back if we removed its connection with the list in the table
+    if ( fRemoved )
+    {
+        assert( pPrev->pNextN2I == NULL );
+        pPrev->pNextN2I = *ppSpot;
+        *ppSpot = pPrev;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Looks up the entry by ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Nm_Entry_t * Nm_ManTableLookupId( Nm_Man_t * p, int ObjId )
+{
+    Nm_Entry_t * pEntry;
+    for ( pEntry = p->pBinsI2N[ Nm_HashNumber(ObjId, p->nBins) ]; pEntry; pEntry = pEntry->pNextI2N )
+        if ( pEntry->ObjId == (unsigned)ObjId )
+            return pEntry;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Looks up the entry by name and type.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Nm_Entry_t * Nm_ManTableLookupName( Nm_Man_t * p, char * pName, int Type )
+{
+    Nm_Entry_t * pEntry, * pTemp;
+    for ( pEntry = p->pBinsN2I[ Nm_HashString(pName, p->nBins) ]; pEntry; pEntry = pEntry->pNextN2I )
+    {
+        // check the entry itself
+        if ( !strcmp(pEntry->Name, pName) && (Type == -1 || pEntry->Type == (unsigned)Type) )
+            return pEntry;
+        // if there is no namesakes, continue
+        if ( pEntry->pNameSake == NULL )
+            continue;
+        // check the list of namesakes
+        for ( pTemp = pEntry->pNameSake; pTemp != pEntry; pTemp = pTemp->pNameSake )
+            if ( !strcmp(pTemp->Name, pName) && (Type == -1 || pTemp->Type == (unsigned)Type) )
+                return pTemp;
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Profiles hash tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nm_ManProfile( Nm_Man_t * p )
+{
+    Nm_Entry_t * pEntry;
+    int Counter, e;
+    printf( "I2N table: " );
+    for ( e = 0; e < p->nBins; e++ )
+    {
+        Counter = 0;
+        for ( pEntry = p->pBinsI2N[e]; pEntry; pEntry = pEntry->pNextI2N )
+            Counter++;
+        printf( "%d ", Counter );
+    }
+    printf( "\n" );
+    printf( "N2I table: " );
+    for ( e = 0; e < p->nBins; e++ )
+    {
+        Counter = 0;
+        for ( pEntry = p->pBinsN2I[e]; pEntry; pEntry = pEntry->pNextN2I )
+            Counter++;
+        printf( "%d ", Counter );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nm_ManResize( Nm_Man_t * p )
+{
+    Nm_Entry_t ** pBinsNewI2N, ** pBinsNewN2I, * pEntry, * pEntry2, ** ppSpot;
+    int nBinsNew, Counter, e;
+    abctime clk;
+
+clk = Abc_Clock();
+    // get the new table size
+    nBinsNew = Abc_PrimeCudd( p->nGrowthFactor * p->nBins ); 
+    // allocate a new array
+    pBinsNewI2N = ABC_ALLOC( Nm_Entry_t *, nBinsNew );
+    pBinsNewN2I = ABC_ALLOC( Nm_Entry_t *, nBinsNew );
+    memset( pBinsNewI2N, 0, sizeof(Nm_Entry_t *) * nBinsNew );
+    memset( pBinsNewN2I, 0, sizeof(Nm_Entry_t *) * nBinsNew );
+    // rehash entries in Id->Name table
+    Counter = 0;
+    for ( e = 0; e < p->nBins; e++ )
+        for ( pEntry = p->pBinsI2N[e], pEntry2 = pEntry? pEntry->pNextI2N : NULL; 
+              pEntry; pEntry = pEntry2, pEntry2 = pEntry? pEntry->pNextI2N : NULL )
+            {
+                ppSpot = pBinsNewI2N + Nm_HashNumber(pEntry->ObjId, nBinsNew);
+                pEntry->pNextI2N = *ppSpot;
+                *ppSpot = pEntry;
+                Counter++;
+            }
+    // rehash entries in Name->Id table
+    for ( e = 0; e < p->nBins; e++ )
+        for ( pEntry = p->pBinsN2I[e], pEntry2 = pEntry? pEntry->pNextN2I : NULL; 
+              pEntry; pEntry = pEntry2, pEntry2 = pEntry? pEntry->pNextN2I : NULL )
+            {
+                ppSpot = pBinsNewN2I + Nm_HashString(pEntry->Name, nBinsNew);
+                pEntry->pNextN2I = *ppSpot;
+                *ppSpot = pEntry;
+            }
+    assert( Counter == p->nEntries );
+//    printf( "Increasing the structural table size from %6d to %6d. ", p->nBins, nBinsNew );
+//    ABC_PRT( "Time", Abc_Clock() - clk );
+    // replace the table and the parameters
+    ABC_FREE( p->pBinsI2N );
+    ABC_FREE( p->pBinsN2I );
+    p->pBinsI2N = pBinsNewI2N;
+    p->pBinsN2I = pBinsNewN2I;
+    p->nBins = nBinsNew;
+//    Nm_ManProfile( p );
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/st/module.make b/abc-build/src/misc/st/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/st/module.make
@@ -0,0 +1,2 @@
+SRC +=  src/misc/st/st.c \
+	src/misc/st/stmm.c
diff --git a/abc-build/src/misc/st/st.c b/abc-build/src/misc/st/st.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/st/st.c
@@ -0,0 +1,562 @@
+/*
+ * Revision Control Information
+ *
+ * /projects/hsis/CVS/utilities/st/st.c,v
+ * serdar
+ * 1.1
+ * 1993/07/29 01:00:13
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "st.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+#define st__NUMCMP(x,y) ((x) != (y))
+#define st__NUMHASH(x,size) (Abc_AbsInt((long)x)%(size))
+//#define st__PTRHASH(x,size) ((int)((ABC_PTRUINT_T)(x)>>2)%size)  // 64-bit bug fix 9/17/2007
+#define st__PTRHASH(x,size) ((int)(((ABC_PTRUINT_T)(x)>>2)%size))
+#define EQUAL(func, x, y) \
+    ((((func) == st__numcmp) || ((func) == st__ptrcmp)) ?\
+      (st__NUMCMP((x),(y)) == 0) : ((*func)((x), (y)) == 0))
+
+
+#define do_hash(key, table)\
+    ((table->hash == st__ptrhash) ? st__PTRHASH((key),(table)->num_bins) :\
+     (table->hash == st__numhash) ? st__NUMHASH((key), (table)->num_bins) :\
+     (*table->hash)((key), (table)->num_bins))
+
+static int rehash( st__table *table);
+
+int st__numhash(const char*, int);
+int st__ptrhash(const char*, int);
+int st__numcmp(const char*, const char*);
+int st__ptrcmp(const char*, const char*);
+
+ st__table *
+ st__init_table_with_params( st__compare_func_type compare, st__hash_func_type hash, int size, int density, double grow_factor, int reorder_flag)
+{
+    int i;
+    st__table *newTable;
+
+    newTable = ABC_ALLOC( st__table, 1);
+    if (newTable == NULL) {
+    return NULL;
+    }
+    newTable->compare = compare;
+    newTable->hash = hash;
+    newTable->num_entries = 0;
+    newTable->max_density = density;
+    newTable->grow_factor = grow_factor;
+    newTable->reorder_flag = reorder_flag;
+    if (size <= 0) {
+    size = 1;
+    }
+    newTable->num_bins = size;
+    newTable->bins = ABC_ALLOC( st__table_entry *, size);
+    if (newTable->bins == NULL) {
+    ABC_FREE(newTable);
+    return NULL;
+    }
+    for(i = 0; i < size; i++) {
+    newTable->bins[i] = 0;
+    }
+    return newTable;
+}
+
+ st__table *
+ st__init_table( st__compare_func_type compare, st__hash_func_type hash)
+{
+    return st__init_table_with_params(compare, hash, st__DEFAULT_INIT_TABLE_SIZE,
+                     st__DEFAULT_MAX_DENSITY,
+                     st__DEFAULT_GROW_FACTOR,
+                     st__DEFAULT_REORDER_FLAG);
+}
+                
+void
+ st__free_table( st__table *table)
+{
+    st__table_entry *ptr, *next;
+    int i;
+
+    for(i = 0; i < table->num_bins ; i++) {
+    ptr = table->bins[i];
+    while (ptr != NULL) {
+        next = ptr->next;
+        ABC_FREE(ptr);
+        ptr = next;
+    }
+    }
+    ABC_FREE(table->bins);
+    ABC_FREE(table);
+}
+
+#define PTR_NOT_EQUAL(table, ptr, user_key)\
+(ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key))
+
+#define FIND_ENTRY(table, hash_val, key, ptr, last) \
+    (last) = &(table)->bins[hash_val];\
+    (ptr) = *(last);\
+    while (PTR_NOT_EQUAL((table), (ptr), (key))) {\
+    (last) = &(ptr)->next; (ptr) = *(last);\
+    }\
+    if ((ptr) != NULL && (table)->reorder_flag) {\
+    *(last) = (ptr)->next;\
+    (ptr)->next = (table)->bins[hash_val];\
+    (table)->bins[hash_val] = (ptr);\
+    }
+
+int
+ st__lookup( st__table *table, const char *key, char **value)
+{
+    int hash_val;
+    st__table_entry *ptr, **last;
+
+    hash_val = do_hash(key, table);
+
+    FIND_ENTRY(table, hash_val, key, ptr, last);
+    
+    if (ptr == NULL) {
+    return 0;
+    } else {
+    if (value != NULL) {
+        *value = ptr->record; 
+    }
+    return 1;
+    }
+}
+
+int
+ st__lookup_int( st__table *table, char *key, int *value)
+{
+    int hash_val;
+    st__table_entry *ptr, **last;
+
+    hash_val = do_hash(key, table);
+
+    FIND_ENTRY(table, hash_val, key, ptr, last);
+    
+    if (ptr == NULL) {
+    return 0;
+    } else {
+    if (value != 0) {
+        *value = (long) ptr->record;
+    }
+    return 1;
+    }
+}
+
+/* This macro does not check if memory allocation fails. Use at you own risk */
+#define ADD_DIRECT(table, key, value, hash_val, new)\
+{\
+    if (table->num_entries/table->num_bins >= table->max_density) {\
+    rehash(table);\
+    hash_val = do_hash(key,table);\
+    }\
+    \
+    new = ABC_ALLOC( st__table_entry, 1);\
+    \
+    new->key = key;\
+    new->record = value;\
+    new->next = table->bins[hash_val];\
+    table->bins[hash_val] = new;\
+    table->num_entries++;\
+}
+
+int
+ st__insert( st__table *table, const char *key, char *value)
+{
+    int hash_val;
+    st__table_entry *newEntry;
+    st__table_entry *ptr, **last;
+
+    hash_val = do_hash(key, table);
+
+    FIND_ENTRY(table, hash_val, key, ptr, last);
+
+    if (ptr == NULL) {
+    if (table->num_entries/table->num_bins >= table->max_density) {
+        if (rehash(table) == st__OUT_OF_MEM) {
+        return st__OUT_OF_MEM;
+        }
+        hash_val = do_hash(key, table);
+    }
+    newEntry = ABC_ALLOC( st__table_entry, 1);
+    if (newEntry == NULL) {
+        return st__OUT_OF_MEM;
+    }
+    newEntry->key = (char *)key;
+    newEntry->record = value;
+    newEntry->next = table->bins[hash_val];
+    table->bins[hash_val] = newEntry;
+    table->num_entries++;
+    return 0;
+    } else {
+    ptr->record = value;
+    return 1;
+    }
+}
+
+int
+ st__add_direct( st__table *table, char *key, char *value)
+{
+    int hash_val;
+    st__table_entry *newEntry;
+    
+    hash_val = do_hash(key, table);
+    if (table->num_entries / table->num_bins >= table->max_density) {
+    if (rehash(table) == st__OUT_OF_MEM) {
+        return st__OUT_OF_MEM;
+    }
+    }
+    hash_val = do_hash(key, table);
+    newEntry = ABC_ALLOC( st__table_entry, 1);
+    if (newEntry == NULL) {
+    return st__OUT_OF_MEM;
+    }
+    newEntry->key = key;
+    newEntry->record = value;
+    newEntry->next = table->bins[hash_val];
+    table->bins[hash_val] = newEntry;
+    table->num_entries++;
+    return 1;
+}
+
+int
+ st__find_or_add( st__table *table, char *key, char ***slot)
+{
+    int hash_val;
+    st__table_entry *newEntry, *ptr, **last;
+
+    hash_val = do_hash(key, table);
+
+    FIND_ENTRY(table, hash_val, key, ptr, last);
+
+    if (ptr == NULL) {
+    if (table->num_entries / table->num_bins >= table->max_density) {
+        if (rehash(table) == st__OUT_OF_MEM) {
+        return st__OUT_OF_MEM;
+        }
+        hash_val = do_hash(key, table);
+    }
+    newEntry = ABC_ALLOC( st__table_entry, 1);
+    if (newEntry == NULL) {
+        return st__OUT_OF_MEM;
+    }
+    newEntry->key = key;
+    newEntry->record = (char *) 0;
+    newEntry->next = table->bins[hash_val];
+    table->bins[hash_val] = newEntry;
+    table->num_entries++;
+    if (slot != NULL) *slot = &newEntry->record;
+    return 0;
+    } else {
+    if (slot != NULL) *slot = &ptr->record;
+    return 1;
+    }
+}
+
+int
+ st__find( st__table *table, char *key, char ***slot)
+{
+    int hash_val;
+    st__table_entry *ptr, **last;
+
+    hash_val = do_hash(key, table);
+
+    FIND_ENTRY(table, hash_val, key, ptr, last);
+
+    if (ptr == NULL) {
+    return 0;
+    } else {
+    if (slot != NULL) {
+        *slot = &ptr->record;
+    }
+    return 1;
+    }
+}
+
+static int
+rehash( st__table *table)
+{
+    st__table_entry *ptr, *next, **old_bins;
+    int             i, old_num_bins, hash_val, old_num_entries;
+
+    /* save old values */
+    old_bins = table->bins;
+    old_num_bins = table->num_bins;
+    old_num_entries = table->num_entries;
+
+    /* rehash */
+    table->num_bins = (int)(table->grow_factor * old_num_bins);
+    if (table->num_bins % 2 == 0) {
+    table->num_bins += 1;
+    }
+    table->num_entries = 0;
+    table->bins = ABC_ALLOC( st__table_entry *, table->num_bins);
+    if (table->bins == NULL) {
+    table->bins = old_bins;
+    table->num_bins = old_num_bins;
+    table->num_entries = old_num_entries;
+    return st__OUT_OF_MEM;
+    }
+    /* initialize */
+    for (i = 0; i < table->num_bins; i++) {
+    table->bins[i] = 0;
+    }
+
+    /* copy data over */
+    for (i = 0; i < old_num_bins; i++) {
+    ptr = old_bins[i];
+    while (ptr != NULL) {
+        next = ptr->next;
+        hash_val = do_hash(ptr->key, table);
+        ptr->next = table->bins[hash_val];
+        table->bins[hash_val] = ptr;
+        table->num_entries++;
+        ptr = next;
+    }
+    }
+    ABC_FREE(old_bins);
+
+    return 1;
+}
+
+ st__table *
+ st__copy( st__table *old_table)
+{
+    st__table *newEntry_table;
+    st__table_entry *ptr, *newEntryptr, *next, *newEntry;
+    int i, j, num_bins = old_table->num_bins;
+
+    newEntry_table = ABC_ALLOC( st__table, 1);
+    if (newEntry_table == NULL) {
+    return NULL;
+    }
+    
+    *newEntry_table = *old_table;
+    newEntry_table->bins = ABC_ALLOC( st__table_entry *, num_bins);
+    if (newEntry_table->bins == NULL) {
+    ABC_FREE(newEntry_table);
+    return NULL;
+    }
+    for(i = 0; i < num_bins ; i++) {
+    newEntry_table->bins[i] = NULL;
+    ptr = old_table->bins[i];
+    while (ptr != NULL) {
+        newEntry = ABC_ALLOC( st__table_entry, 1);
+        if (newEntry == NULL) {
+        for (j = 0; j <= i; j++) {
+            newEntryptr = newEntry_table->bins[j];
+            while (newEntryptr != NULL) {
+            next = newEntryptr->next;
+            ABC_FREE(newEntryptr);
+            newEntryptr = next;
+            }
+        }
+        ABC_FREE(newEntry_table->bins);
+        ABC_FREE(newEntry_table);
+        return NULL;
+        }
+        *newEntry = *ptr;
+        newEntry->next = newEntry_table->bins[i];
+        newEntry_table->bins[i] = newEntry;
+        ptr = ptr->next;
+    }
+    }
+    return newEntry_table;
+}
+
+int
+ st__delete( st__table *table, const char **keyp, char **value)
+{
+    int hash_val;
+    const char *key = *keyp;
+    st__table_entry *ptr, **last;
+
+    hash_val = do_hash(key, table);
+
+    FIND_ENTRY(table, hash_val, key, ptr ,last);
+    
+    if (ptr == NULL) {
+    return 0;
+    }
+
+    *last = ptr->next;
+    if (value != NULL) *value = ptr->record;
+    *keyp = ptr->key;
+    ABC_FREE(ptr);
+    table->num_entries--;
+    return 1;
+}
+
+int
+ st__delete_int( st__table *table, long *keyp, char **value)
+{
+    int hash_val;
+    char *key = (char *) *keyp;
+    st__table_entry *ptr, **last;
+
+    hash_val = do_hash(key, table);
+
+    FIND_ENTRY(table, hash_val, key, ptr ,last);
+
+    if (ptr == NULL) {
+        return 0;
+    }
+
+    *last = ptr->next;
+    if (value != NULL) *value = ptr->record;
+    *keyp = (long) ptr->key;
+    ABC_FREE(ptr);
+    table->num_entries--;
+    return 1;
+}
+
+int
+ st__foreach( st__table *table, enum st__retval (*func)(char *, char *, char *), char *arg)
+{
+    st__table_entry *ptr, **last;
+    enum st__retval retval;
+    int i;
+
+    for(i = 0; i < table->num_bins; i++) {
+    last = &table->bins[i]; ptr = *last;
+    while (ptr != NULL) {
+        retval = (*func)(ptr->key, ptr->record, arg);
+        switch (retval) {
+        case st__CONTINUE:
+        last = &ptr->next; ptr = *last;
+        break;
+        case st__STOP:
+        return 0;
+        case st__DELETE:
+        *last = ptr->next;
+        table->num_entries--;   /* cstevens@ic */
+        ABC_FREE(ptr);
+        ptr = *last;
+        }
+    }
+    }
+    return 1;
+}
+
+int
+ st__strhash(const char *string, int modulus)
+{
+    int val = 0;
+    int c;
+    
+    while ((c = *string++) != '\0') {
+    val = val*997 + c;
+    }
+
+    return ((val < 0) ? -val : val)%modulus;
+}
+
+int
+ st__numhash(const char *x, int size)
+{
+    return st__NUMHASH(x, size);
+}
+
+int
+ st__ptrhash(const char *x, int size)
+{
+    return st__PTRHASH(x, size);
+}
+
+int
+ st__numcmp(const char *x, const char *y)
+{
+    return st__NUMCMP(x, y);
+}
+
+int
+ st__ptrcmp(const char *x, const char *y)
+{
+    return st__NUMCMP(x, y);
+}
+
+ st__generator *
+ st__init_gen( st__table *table)
+{
+    st__generator *gen;
+
+    gen = ABC_ALLOC( st__generator, 1);
+    if (gen == NULL) {
+    return NULL;
+    }
+    gen->table = table;
+    gen->entry = NULL;
+    gen->index = 0;
+    return gen;
+}
+
+
+int 
+ st__gen( st__generator *gen, const char **key_p, char **value_p)
+{
+    int i;
+
+    if (gen->entry == NULL) {
+    /* try to find next entry */
+    for(i = gen->index; i < gen->table->num_bins; i++) {
+        if (gen->table->bins[i] != NULL) {
+        gen->index = i+1;
+        gen->entry = gen->table->bins[i];
+        break;
+        }
+    }
+    if (gen->entry == NULL) {
+        return 0;       /* that's all folks ! */
+    }
+    }
+    *key_p = gen->entry->key;
+    if (value_p != 0) {
+    *value_p = gen->entry->record;
+    }
+    gen->entry = gen->entry->next;
+    return 1;
+}
+
+
+int 
+ st__gen_int( st__generator *gen, const char **key_p, long *value_p)
+{
+    int i;
+
+    if (gen->entry == NULL) {
+    /* try to find next entry */
+    for(i = gen->index; i < gen->table->num_bins; i++) {
+        if (gen->table->bins[i] != NULL) {
+        gen->index = i+1;
+        gen->entry = gen->table->bins[i];
+        break;
+        }
+    }
+    if (gen->entry == NULL) {
+        return 0;       /* that's all folks ! */
+    }
+    }
+    *key_p = gen->entry->key;
+    if (value_p != 0) {
+    *value_p = (long) gen->entry->record;
+    }
+    gen->entry = gen->entry->next;
+    return 1;
+}
+
+
+void
+ st__free_gen( st__generator *gen)
+{
+    ABC_FREE(gen);
+}
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/st/st.h b/abc-build/src/misc/st/st.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/st/st.h
@@ -0,0 +1,121 @@
+/*
+ * Revision Control Information
+ *
+ * /projects/hsis/CVS/utilities/st/st.h,v
+ * serdar
+ * 1.1
+ * 1993/07/29 01:00:21
+ *
+ */
+/* LINTLIBRARY */
+
+/* /projects/hsis/CVS/utilities/st/st.h,v 1.1 1993/07/29 01:00:21 serdar Exp */
+
+#ifndef ABC__misc__st__st_h
+#define ABC__misc__st__st_h
+#define st__INCLUDED
+
+#include "misc/util/abc_global.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+/* These are potential duplicates. */
+#ifndef EXTERN
+#   ifdef __cplusplus
+#       ifdef ABC_NAMESPACE
+#           define EXTERN extern
+#       else
+#           define EXTERN extern "C"
+#       endif
+#   else
+#       define EXTERN extern
+#   endif
+#endif
+
+#ifndef ARGS
+#define ARGS(protos) protos
+#endif
+
+
+typedef int (* st__compare_func_type)(const char*, const char*);
+typedef int (* st__hash_func_type)(const char*, int);
+
+typedef struct st__table_entry st__table_entry;
+struct st__table_entry {
+    char *key;
+    char *record;
+    st__table_entry *next;
+};
+
+typedef struct st__table st__table;
+struct st__table {
+    st__compare_func_type compare;
+    st__hash_func_type hash;
+    int num_bins;
+    int num_entries;
+    int max_density;
+    int reorder_flag;
+    double grow_factor;
+    st__table_entry **bins;
+};
+
+typedef struct st__generator st__generator;
+struct st__generator {
+    st__table *table;
+    st__table_entry *entry;
+    int index;
+};
+
+#define st__is_member(table,key) st__lookup(table,key,(char **) 0)
+#define st__count(table) ((table)->num_entries)
+
+enum st__retval { st__CONTINUE, st__STOP, st__DELETE};
+
+typedef enum st__retval (* st__PFSR)(char *, char *, char *);
+typedef int (* st__PFI)();
+
+extern st__table * st__init_table_with_params ( st__compare_func_type compare, st__hash_func_type hash, int size, int density, double grow_factor, int reorder_flag);
+extern st__table * st__init_table ( st__compare_func_type, st__hash_func_type);
+extern void st__free_table ( st__table *);
+extern int st__lookup ( st__table *, const char *, char **);
+extern int st__lookup_int ( st__table *, char *, int *);
+extern int st__insert ( st__table *, const char *, char *);
+extern int st__add_direct ( st__table *, char *, char *);
+extern int st__find_or_add ( st__table *, char *, char ***);
+extern int st__find ( st__table *, char *, char ***);
+extern st__table * st__copy ( st__table *);
+extern int st__delete ( st__table *, const char **, char **);
+extern int st__delete_int ( st__table *, long *, char **);
+extern int st__foreach ( st__table *, st__PFSR, char *);
+extern int st__strhash (const char *, int);
+extern int st__numhash (const char *, int);
+extern int st__ptrhash (const char *, int);
+extern int st__numcmp (const char *, const char *);
+extern int st__ptrcmp (const char *, const char *);
+extern st__generator * st__init_gen ( st__table *);
+extern int st__gen ( st__generator *, const char **, char **);
+extern int st__gen_int ( st__generator *, const char **, long *);
+extern void st__free_gen ( st__generator *);
+
+
+#define st__DEFAULT_MAX_DENSITY 5
+#define st__DEFAULT_INIT_TABLE_SIZE 11
+#define st__DEFAULT_GROW_FACTOR 2.0
+#define st__DEFAULT_REORDER_FLAG 0
+
+#define st__foreach_item(table, gen, key, value) \
+    for(gen= st__init_gen(table); st__gen(gen,key,value) || ( st__free_gen(gen),0);)
+
+#define st__foreach_item_int(table, gen, key, value) \
+    for(gen= st__init_gen(table); st__gen_int(gen,key,value) || ( st__free_gen(gen),0);)
+
+#define st__OUT_OF_MEM -10000
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif /* st__INCLUDED */
diff --git a/abc-build/src/misc/st/stmm.c b/abc-build/src/misc/st/stmm.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/st/stmm.c
@@ -0,0 +1,627 @@
+/*
+ * Revision Control Information
+ *
+ * /projects/hsis/CVS/utilities/st/st.c,v
+ * serdar
+ * 1.1
+ * 1993/07/29 01:00:13
+ *
+ */
+#include <stdio.h>
+#include "misc/extra/extra.h"
+#include "stmm.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+#define STMM_NUMCMP(x,y) ((x) != (y))
+#define STMM_NUMHASH(x,size) (Abc_AbsInt((long)x)%(size))
+//#define STMM_PTRHASH(x,size) ((int)((ABC_PTRUINT_T)(x)>>2)%size) //  64-bit bug fix 9/17/2007
+#define STMM_PTRHASH(x,size) ((int)(((ABC_PTRUINT_T)(x)>>2)%size))
+#define EQUAL(func, x, y) \
+    ((((func) == stmm_numcmp) || ((func) == stmm_ptrcmp)) ?\
+      (STMM_NUMCMP((x),(y)) == 0) : ((*func)((x), (y)) == 0))
+
+
+#define do_hash(key, table)\
+    ((table->hash == stmm_ptrhash) ? STMM_PTRHASH((key),(table)->num_bins) :\
+     (table->hash == stmm_numhash) ? STMM_NUMHASH((key), (table)->num_bins) :\
+     (*table->hash)((key), (table)->num_bins))
+
+static int rehash (stmm_table *table);
+//int stmm_numhash (), stmm_ptrhash (), stmm_numcmp (), stmm_ptrcmp ();
+
+stmm_table *
+stmm_init_table_with_params (stmm_compare_func_type compare, stmm_hash_func_type hash, int size, int density, double grow_factor, int reorder_flag)
+{
+    int i;
+    stmm_table *newTable;
+
+    newTable = ABC_ALLOC(stmm_table, 1);
+    if (newTable == NULL) {
+    return NULL;
+    }
+    newTable->compare = compare;
+    newTable->hash = hash;
+    newTable->num_entries = 0;
+    newTable->max_density = density;
+    newTable->grow_factor = grow_factor;
+    newTable->reorder_flag = reorder_flag;
+    if (size <= 0) {
+    size = 1;
+    }
+    newTable->num_bins = size;
+    newTable->bins = ABC_ALLOC(stmm_table_entry *, size);
+    if (newTable->bins == NULL) {
+    ABC_FREE(newTable);
+    return NULL;
+    }
+    for (i = 0; i < size; i++) {
+    newTable->bins[i] = 0;
+    }
+
+    // added by alanmi
+    newTable->pMemMan = Extra_MmFixedStart(sizeof (stmm_table_entry));
+    return newTable;
+}
+
+stmm_table *
+stmm_init_table (stmm_compare_func_type compare, stmm_hash_func_type hash)
+{
+    return stmm_init_table_with_params (compare, hash,
+                    STMM_DEFAULT_INIT_TABLE_SIZE,
+                    STMM_DEFAULT_MAX_DENSITY,
+                    STMM_DEFAULT_GROW_FACTOR,
+                    STMM_DEFAULT_REORDER_FLAG);
+}
+
+void
+stmm_free_table (stmm_table *table)
+{
+/*
+    stmm_table_entry *ptr, *next;
+    int i;
+    for ( i = 0; i < table->num_bins; i++ )
+    {
+        ptr = table->bins[i];
+        while ( ptr != NULL )
+        {
+            next = ptr->next;
+            ABC_FREE( ptr );
+            ptr = next;
+        }
+    }
+*/
+    // no need to deallocate entries because they are in the memory manager now
+    // added by alanmi
+    if ( table->pMemMan )
+        Extra_MmFixedStop ((Extra_MmFixed_t *)table->pMemMan);
+    ABC_FREE(table->bins);
+    ABC_FREE(table);
+}
+
+// this function recycles all the bins
+void
+stmm_clean (stmm_table *table)
+{
+    int i;
+    // clean the bins
+    for (i = 0; i < table->num_bins; i++)
+        table->bins[i] = NULL;
+    // reset the parameters
+    table->num_entries = 0;
+    // restart the memory manager
+    Extra_MmFixedRestart ((Extra_MmFixed_t *)table->pMemMan);
+}
+
+
+#define PTR_NOT_EQUAL(table, ptr, user_key)\
+(ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key))
+
+#define FIND_ENTRY(table, hash_val, key, ptr, last) \
+    (last) = &(table)->bins[hash_val];\
+    (ptr) = *(last);\
+    while (PTR_NOT_EQUAL((table), (ptr), (key))) {\
+    (last) = &(ptr)->next; (ptr) = *(last);\
+    }\
+    if ((ptr) != NULL && (table)->reorder_flag) {\
+    *(last) = (ptr)->next;\
+    (ptr)->next = (table)->bins[hash_val];\
+    (table)->bins[hash_val] = (ptr);\
+    }
+
+int
+stmm_lookup (stmm_table *table, char *key, char **value)
+{
+    int hash_val;
+    stmm_table_entry *ptr, **last;
+
+    hash_val = do_hash (key, table);
+
+    FIND_ENTRY (table, hash_val, key, ptr, last);
+
+    if (ptr == NULL) {
+    return 0;
+    }
+    else {
+    if (value != NULL)
+    {
+        *value = ptr->record;
+    }
+    return 1;
+    }
+}
+
+int
+stmm_lookup_int (stmm_table *table, char *key, int *value)
+{
+    int hash_val;
+    stmm_table_entry *ptr, **last;
+
+    hash_val = do_hash (key, table);
+
+    FIND_ENTRY (table, hash_val, key, ptr, last);
+
+    if (ptr == NULL) {
+    return 0;
+    }
+    else {
+    if (value != 0)
+    {
+        *value = (long) ptr->record;
+    }
+    return 1;
+    }
+}
+
+// This macro contained a line
+//    new = ABC_ALLOC(stmm_table_entry, 1);
+// which was modified by alanmi
+
+
+/* This macro does not check if memory allocation fails. Use at you own risk */
+#define ADD_DIRECT(table, key, value, hash_val, new)\
+{\
+    if (table->num_entries/table->num_bins >= table->max_density) {\
+    rehash(table);\
+    hash_val = do_hash(key,table);\
+    }\
+    \
+    new = (stmm_table_entry *)Extra_MmFixedEntryFetch( (Extra_MmFixed_t *)table->pMemMan );\
+    \
+    new->key = key;\
+    new->record = value;\
+    new->next = table->bins[hash_val];\
+    table->bins[hash_val] = new;\
+    table->num_entries++;\
+}
+
+int
+stmm_insert (stmm_table *table, char *key, char *value)
+{
+    int hash_val;
+    stmm_table_entry *newEntry;
+    stmm_table_entry *ptr, **last;
+
+    hash_val = do_hash (key, table);
+
+    FIND_ENTRY (table, hash_val, key, ptr, last);
+
+    if (ptr == NULL) {
+    if (table->num_entries / table->num_bins >= table->max_density) {
+        if (rehash (table) == STMM_OUT_OF_MEM) {
+        return STMM_OUT_OF_MEM;
+        }
+        hash_val = do_hash (key, table);
+    }
+
+//              newEntry = ABC_ALLOC( stmm_table_entry, 1 );
+    newEntry = (stmm_table_entry *) Extra_MmFixedEntryFetch ((Extra_MmFixed_t *)table->pMemMan);
+    if (newEntry == NULL) {
+        return STMM_OUT_OF_MEM;
+    }
+
+    newEntry->key = key;
+    newEntry->record = value;
+    newEntry->next = table->bins[hash_val];
+    table->bins[hash_val] = newEntry;
+    table->num_entries++;
+    return 0;
+    }
+    else {
+    ptr->record = value;
+    return 1;
+    }
+}
+
+int
+stmm_add_direct (stmm_table *table, char *key, char *value)
+{
+    int hash_val;
+    stmm_table_entry *newEntry;
+
+    hash_val = do_hash (key, table);
+    if (table->num_entries / table->num_bins >= table->max_density) {
+    if (rehash (table) == STMM_OUT_OF_MEM) {
+        return STMM_OUT_OF_MEM;
+    }
+    }
+    hash_val = do_hash (key, table);
+
+//      newEntry = ABC_ALLOC( stmm_table_entry, 1 );
+    newEntry = (stmm_table_entry *) Extra_MmFixedEntryFetch ((Extra_MmFixed_t *)table->pMemMan);
+    if (newEntry == NULL) {
+    return STMM_OUT_OF_MEM;
+    }
+
+    newEntry->key = key;
+    newEntry->record = value;
+    newEntry->next = table->bins[hash_val];
+    table->bins[hash_val] = newEntry;
+    table->num_entries++;
+    return 1;
+}
+
+int
+stmm_find_or_add (stmm_table *table, char *key, char ***slot)
+{
+    int hash_val;
+    stmm_table_entry *newEntry, *ptr, **last;
+
+    hash_val = do_hash (key, table);
+
+    FIND_ENTRY (table, hash_val, key, ptr, last);
+
+    if (ptr == NULL) {
+    if (table->num_entries / table->num_bins >= table->max_density) {
+        if (rehash (table) == STMM_OUT_OF_MEM) {
+        return STMM_OUT_OF_MEM;
+        }
+        hash_val = do_hash (key, table);
+    }
+
+    // newEntry = ABC_ALLOC( stmm_table_entry, 1 );
+    newEntry = (stmm_table_entry *) Extra_MmFixedEntryFetch ((Extra_MmFixed_t *)table->pMemMan);
+    if (newEntry == NULL) {
+        return STMM_OUT_OF_MEM;
+    }
+
+    newEntry->key = key;
+    newEntry->record = (char *) 0;
+    newEntry->next = table->bins[hash_val];
+    table->bins[hash_val] = newEntry;
+    table->num_entries++;
+    if (slot != NULL)
+         *slot = &newEntry->record;
+    return 0;
+    }
+    else {
+    if (slot != NULL)
+         *slot = &ptr->record;
+    return 1;
+    }
+}
+
+int
+stmm_find (stmm_table *table, char *key, char ***slot)
+{
+    int hash_val;
+    stmm_table_entry *ptr, **last;
+
+    hash_val = do_hash (key, table);
+
+    FIND_ENTRY (table, hash_val, key, ptr, last);
+
+    if (ptr == NULL) {
+    return 0;
+    }
+    else {
+    if (slot != NULL)
+    {
+        *slot = &ptr->record;
+    }
+    return 1;
+    }
+}
+
+static int
+rehash (stmm_table *table)
+{
+    stmm_table_entry *ptr, *next, **old_bins;
+    int i, old_num_bins, hash_val, old_num_entries;
+
+    /* save old values */
+    old_bins = table->bins;
+    old_num_bins = table->num_bins;
+    old_num_entries = table->num_entries;
+
+    /* rehash */
+    table->num_bins = (int) (table->grow_factor * old_num_bins);
+    if (table->num_bins % 2 == 0) {
+    table->num_bins += 1;
+    }
+    table->num_entries = 0;
+    table->bins = ABC_ALLOC(stmm_table_entry *, table->num_bins);
+    if (table->bins == NULL) {
+    table->bins = old_bins;
+    table->num_bins = old_num_bins;
+    table->num_entries = old_num_entries;
+    return STMM_OUT_OF_MEM;
+    }
+    /* initialize */
+    for (i = 0; i < table->num_bins; i++) {
+    table->bins[i] = 0;
+    }
+
+    /* copy data over */
+    for (i = 0; i < old_num_bins; i++) {
+    ptr = old_bins[i];
+    while (ptr != NULL) {
+        next = ptr->next;
+        hash_val = do_hash (ptr->key, table);
+        ptr->next = table->bins[hash_val];
+        table->bins[hash_val] = ptr;
+        table->num_entries++;
+        ptr = next;
+    }
+    }
+    ABC_FREE(old_bins);
+
+    return 1;
+}
+
+stmm_table *
+stmm_copy (stmm_table *old_table)
+{
+    stmm_table *newEntry_table;
+    stmm_table_entry *ptr, /* *newEntryptr, *next, */ *newEntry;
+    int i, /*j, */ num_bins = old_table->num_bins;
+
+    newEntry_table = ABC_ALLOC(stmm_table, 1);
+    if (newEntry_table == NULL) {
+    return NULL;
+    }
+
+    *newEntry_table = *old_table;
+    newEntry_table->bins = ABC_ALLOC(stmm_table_entry *, num_bins);
+    if (newEntry_table->bins == NULL) {
+    ABC_FREE(newEntry_table);
+    return NULL;
+    }
+
+    // allocate the memory manager for the newEntry table
+    newEntry_table->pMemMan = Extra_MmFixedStart (sizeof (stmm_table_entry));
+
+    for (i = 0; i < num_bins; i++) {
+    newEntry_table->bins[i] = NULL;
+    ptr = old_table->bins[i];
+    while (ptr != NULL) {
+//                      newEntry = ABC_ALLOC( stmm_table_entry, 1 );
+        newEntry = (stmm_table_entry *)Extra_MmFixedEntryFetch ((Extra_MmFixed_t *)newEntry_table->pMemMan);
+        if (newEntry == NULL) {
+/*
+                for ( j = 0; j <= i; j++ )
+                {
+                    newEntryptr = newEntry_table->bins[j];
+                    while ( newEntryptr != NULL )
+                    {
+                        next = newEntryptr->next;
+                        ABC_FREE( newEntryptr );
+                        newEntryptr = next;
+                    }
+                }
+*/
+        Extra_MmFixedStop ((Extra_MmFixed_t *)newEntry_table->pMemMan);
+
+        ABC_FREE(newEntry_table->bins);
+        ABC_FREE(newEntry_table);
+        return NULL;
+        }
+        *newEntry = *ptr;
+        newEntry->next = newEntry_table->bins[i];
+        newEntry_table->bins[i] = newEntry;
+        ptr = ptr->next;
+    }
+    }
+    return newEntry_table;
+}
+
+int
+stmm_delete (stmm_table *table, char **keyp, char **value)
+{
+    int hash_val;
+    char *key = *keyp;
+    stmm_table_entry *ptr, **last;
+
+    hash_val = do_hash (key, table);
+
+    FIND_ENTRY (table, hash_val, key, ptr, last);
+
+    if (ptr == NULL) {
+    return 0;
+    }
+
+    *last = ptr->next;
+    if (value != NULL)
+     *value = ptr->record;
+    *keyp = ptr->key;
+//      ABC_FREE( ptr );
+    Extra_MmFixedEntryRecycle ((Extra_MmFixed_t *)table->pMemMan, (char *) ptr);
+
+    table->num_entries--;
+    return 1;
+}
+
+int
+stmm_delete_int (stmm_table *table, long *keyp, char **value)
+{
+    int hash_val;
+    char *key = (char *) *keyp;
+    stmm_table_entry *ptr, **last;
+
+    hash_val = do_hash (key, table);
+
+    FIND_ENTRY (table, hash_val, key, ptr, last);
+
+    if (ptr == NULL) {
+    return 0;
+    }
+
+    *last = ptr->next;
+    if (value != NULL)
+     *value = ptr->record;
+    *keyp = (long) ptr->key;
+//      ABC_FREE( ptr );
+    Extra_MmFixedEntryRecycle ((Extra_MmFixed_t *)table->pMemMan, (char *) ptr);
+
+    table->num_entries--;
+    return 1;
+}
+
+int
+stmm_foreach (stmm_table *table, enum stmm_retval (*func) (char *, char *, char *), char *arg)
+{
+    stmm_table_entry *ptr, **last;
+    enum stmm_retval retval;
+    int i;
+
+    for (i = 0; i < table->num_bins; i++) {
+    last = &table->bins[i];
+    ptr = *last;
+    while (ptr != NULL) {
+        retval = (*func) (ptr->key, ptr->record, arg);
+        switch (retval) {
+        case STMM_CONTINUE:
+        last = &ptr->next;
+        ptr = *last;
+        break;
+        case STMM_STOP:
+        return 0;
+        case STMM_DELETE:
+        *last = ptr->next;
+        table->num_entries--;   /* cstevens@ic */
+//                              ABC_FREE( ptr );
+        Extra_MmFixedEntryRecycle ((Extra_MmFixed_t *)table->pMemMan, (char *) ptr);
+
+        ptr = *last;
+        }
+    }
+    }
+    return 1;
+}
+
+int
+stmm_strhash (const char *string, int modulus)
+{
+    int val = 0;
+    int c;
+
+    while ((c = *string++) != '\0') {
+    val = val * 997 + c;
+    }
+
+    return ((val < 0) ? -val : val) % modulus;
+}
+
+int
+stmm_numhash (const char *x, int size)
+{
+    return STMM_NUMHASH (x, size);
+}
+
+int
+stmm_ptrhash (const char *x, int size)
+{
+    return STMM_PTRHASH (x, size);
+}
+
+int
+stmm_numcmp (const char *x, const char *y)
+{
+    return STMM_NUMCMP (x, y);
+}
+
+int
+stmm_ptrcmp (const char *x, const char *y)
+{
+    return STMM_NUMCMP (x, y);
+}
+
+stmm_generator *
+stmm_init_gen (stmm_table *table)
+{
+    stmm_generator *gen;
+
+    gen = ABC_ALLOC(stmm_generator, 1);
+    if (gen == NULL) {
+    return NULL;
+    }
+    gen->table = table;
+    gen->entry = NULL;
+    gen->index = 0;
+    return gen;
+}
+
+
+int
+stmm_gen (stmm_generator *gen, char **key_p, char **value_p)
+{
+    int i;
+
+    if (gen->entry == NULL) {
+    /* try to find next entry */
+    for (i = gen->index; i < gen->table->num_bins; i++) {
+        if (gen->table->bins[i] != NULL) {
+        gen->index = i + 1;
+        gen->entry = gen->table->bins[i];
+        break;
+        }
+    }
+    if (gen->entry == NULL) {
+        return 0;       /* that's all folks ! */
+    }
+    }
+    *key_p = gen->entry->key;
+    if (value_p != 0) {
+    *value_p = gen->entry->record;
+    }
+    gen->entry = gen->entry->next;
+    return 1;
+}
+
+
+int
+stmm_gen_int (stmm_generator *gen, char **key_p, long *value_p)
+{
+    int i;
+
+    if (gen->entry == NULL) {
+    /* try to find next entry */
+    for (i = gen->index; i < gen->table->num_bins; i++) {
+        if (gen->table->bins[i] != NULL) {
+        gen->index = i + 1;
+        gen->entry = gen->table->bins[i];
+        break;
+        }
+    }
+    if (gen->entry == NULL) {
+        return 0;       /* that's all folks ! */
+    }
+    }
+    *key_p = gen->entry->key;
+    if (value_p != 0)
+    {
+    *value_p = (long) gen->entry->record;
+    }
+    gen->entry = gen->entry->next;
+    return 1;
+}
+
+
+void
+stmm_free_gen (stmm_generator *gen)
+{
+    ABC_FREE(gen);
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/st/stmm.h b/abc-build/src/misc/st/stmm.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/st/stmm.h
@@ -0,0 +1,147 @@
+/*
+ * Revision Control Information
+ *
+ * /projects/hsis/CVS/utilities/st/st.h,v
+ * serdar
+ * 1.1
+ * 1993/07/29 01:00:21
+ *
+ */
+/* LINTLIBRARY */
+
+/* /projects/hsis/CVS/utilities/st/st.h,v 1.1 1993/07/29 01:00:21 serdar Exp */
+
+#ifndef ABC__misc__st__stmm_h
+#define ABC__misc__st__stmm_h
+
+#include "misc/util/abc_global.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+/* These are potential duplicates. */
+#ifndef EXTERN
+#   ifdef __cplusplus
+#       ifdef ABC_NAMESPACE
+#           define EXTERN extern
+#       else
+#           define EXTERN extern "C"
+#       endif
+#   else
+#       define EXTERN extern
+#   endif
+#endif
+
+#ifndef ARGS
+#define ARGS(protos) protos
+#endif
+
+typedef int (*stmm_compare_func_type)(const char*, const char*);
+typedef int (*stmm_hash_func_type)(const char*, int);
+
+typedef struct stmm_table_entry stmm_table_entry;
+typedef struct stmm_table stmm_table;
+typedef struct stmm_generator stmm_generator;
+
+struct stmm_table_entry
+{
+    char *key;
+    char *record;
+    stmm_table_entry *next;
+};
+
+struct stmm_table
+{
+    stmm_compare_func_type compare;
+    stmm_hash_func_type hash;
+    int num_bins;
+    int num_entries;
+    int max_density;
+    int reorder_flag;
+    double grow_factor;
+    stmm_table_entry **bins;
+    // memory manager to improve runtime and prevent memory fragmentation
+    // added by alanmi - January 16, 2003
+    void * pMemMan;
+};
+
+struct stmm_generator
+{
+    stmm_table *table;
+    stmm_table_entry *entry;
+    int index;
+};
+
+#define stmm_is_member(table,key) stmm_lookup(table,key,(char **) 0)
+#define stmm_count(table) ((table)->num_entries)
+
+enum stmm_retval
+{ STMM_CONTINUE, STMM_STOP, STMM_DELETE };
+
+typedef enum stmm_retval (*STMM_PFSR) (char *, char *, char *);
+
+EXTERN stmm_table *stmm_init_table_with_params
+ARGS ((stmm_compare_func_type compare, stmm_hash_func_type hash, int size, int density, double grow_factor, int reorder_flag));
+EXTERN stmm_table *stmm_init_table ARGS ((stmm_compare_func_type, stmm_hash_func_type));
+EXTERN void stmm_free_table ARGS ((stmm_table *));
+EXTERN int stmm_lookup ARGS ((stmm_table *, char *, char **));
+EXTERN int stmm_lookup_int ARGS ((stmm_table *, char *, int *));
+EXTERN int stmm_insert ARGS ((stmm_table *, char *, char *));
+EXTERN int stmm_add_direct ARGS ((stmm_table *, char *, char *));
+EXTERN int stmm_find_or_add ARGS ((stmm_table *, char *, char ***));
+EXTERN int stmm_find ARGS ((stmm_table *, char *, char ***));
+EXTERN stmm_table *stmm_copy ARGS ((stmm_table *));
+EXTERN int stmm_delete ARGS ((stmm_table *, char **, char **));
+EXTERN int stmm_delete_int ARGS ((stmm_table *, long *, char **));
+EXTERN int stmm_foreach ARGS ((stmm_table *, STMM_PFSR, char *));
+EXTERN int stmm_strhash ARGS ((const char *, int));
+EXTERN int stmm_numhash ARGS ((const char *, int));
+EXTERN int stmm_ptrhash ARGS ((const char *, int));
+EXTERN int stmm_numcmp ARGS ((const char *, const char *));
+EXTERN int stmm_ptrcmp ARGS ((const char *, const char *));
+EXTERN stmm_generator *stmm_init_gen ARGS ((stmm_table *));
+EXTERN int stmm_gen ARGS ((stmm_generator *, char **, char **));
+EXTERN int stmm_gen_int ARGS ((stmm_generator *, char **, long *));
+EXTERN void stmm_free_gen ARGS ((stmm_generator *));
+// additional functions
+EXTERN void stmm_clean ARGS ((stmm_table *));
+
+
+
+#define STMM_DEFAULT_MAX_DENSITY        5
+#define STMM_DEFAULT_INIT_TABLE_SIZE   11
+#define STMM_DEFAULT_GROW_FACTOR      2.0
+#define STMM_DEFAULT_REORDER_FLAG       0
+
+// added by Zhihong: no need for memory allocation
+#define stmm_foreach_item2(tb, /* stmm_generator */gen, key, value) \
+    for(gen.table=(tb), gen.entry=NULL, gen.index=0; \
+        stmm_gen(&(gen),key,value);)
+
+#define stmm_foreach_item(table, gen, key, value) \
+    for(gen=stmm_init_gen(table); stmm_gen(gen,key,value) || (stmm_free_gen(gen),0);)
+
+#define stmm_foreach_item_int(table, gen, key, value) \
+    for(gen=stmm_init_gen(table); stmm_gen_int(gen,key,value) || (stmm_free_gen(gen),0);)
+
+#define STMM_OUT_OF_MEM -10000
+
+/*
+
+// consider adding these other other similar definitions
+#define st__table       stmm_table
+#define st__insert      stmm_insert
+#define st__delete      stmm_delete
+#define st__lookup      stmm_lookup
+#define st__init_table  stmm_init_table
+#define st__free_table  stmm_free_table
+
+*/
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif /* STMM_INCLUDED */
diff --git a/abc-build/src/misc/tim/module.make b/abc-build/src/misc/tim/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/tim/module.make
@@ -0,0 +1,5 @@
+SRC +=	src/misc/tim/timBox.c \
+	src/misc/tim/timDump.c \
+	src/misc/tim/timMan.c \
+	src/misc/tim/timTime.c \
+	src/misc/tim/timTrav.c
diff --git a/abc-build/src/misc/tim/tim.c b/abc-build/src/misc/tim/tim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/tim/tim.c
@@ -0,0 +1,39 @@
+/**CFile****************************************************************
+
+  FileName    [tim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Hierarchy/timing manager.]
+
+  Synopsis    [Representation of timing information.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: tim.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "timInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/tim/tim.h b/abc-build/src/misc/tim/tim.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/tim/tim.h
@@ -0,0 +1,180 @@
+/**CFile****************************************************************
+
+  FileName    [tim.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Hierarchy/timing manager.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: tim.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__tim__tim_h
+#define ABC__aig__tim__tim_h
+
+/*
+    The data-structure Tim_Man_t implemented in this package stores two types 
+    of information:
+    (1) hierarchical information about the connectivity of a combinational 
+    logic network with combinational logic node and combinational white boxes
+    (2) timing information about input-to-output delays of each combinational 
+    white box.
+
+    This data-structure is closely coupled with the AIG manager extracted from 
+    the same combinational logic network. The AIG manager represents combinational
+    logic surrounding white boxes, and contains additional PIs/POs corresponding
+    to the outputs/inputs of the white boxes.
+
+    The manager Tim_Man_t is created by a call to Tim_ManStart(). The arguments 
+    of this call are the total number of all combinational inputs/output in 
+    the extracted AIG. (Note that this number is different from the number of 
+    inputs/outputs of the combinational logic network, because the extracted AIG 
+    will have additional inputs/output due to white boxes.)
+
+    The extracted AIG and the corresponding Tim_Man_t may be created at the same 
+    time or at separate times. The following guideline assumes concurrent creation.
+
+    First, PIs of the AIG are created in 1-to-1 correspondence with the PIs 
+    of the original network.
+    Next, all nodes (logic nodes and white boxes) of the network are traversed 
+    in a topologic order.
+    When a white box is encountered, the TFI cone of box inputs are tranversed 
+    and all new logic nodes encoutered added to the AIG.
+    Then, the white box is created by the call to Tim_ManCreateBox().
+    Then, new POs of the AIG are created in 1-to-1 correspondence with box inputs. 
+    Then, new PIs of the AIG are created in 1-to-1 correspondence with box outputs.
+    Finally, the TFO cone of the POs is traversed and all new logic nodes 
+    encountered added to the AIG.
+    In the end, the POs of the AIG is constructed in 1-to-1 correspondence with 
+    the PIs of the original combinational logic network.
+
+    Delay tables representing input-to-output delays of each type of white
+    box should be computed in advance and given to the timing manager in one array
+    through the API Tim_ManSetDelayTables().  When each box is constructed, the delay
+    table ID of this box (which is the index of the table in the above array) is given 
+    as the last argument 'iDelayTable' in Tim_ManCreateBox().
+
+    A delay table is a one-dimensional array of floats whose size is: 3 + nInputs * nOutputs.
+    The first entry is the delay table ID used by the boxes to refer to the table.
+    The second and third entries are nInputs and nOutputs.
+    The following 'nInputs * nOutputs' entries are delay numbers for each output, 
+    that is, the first set of nInputs entries give delay of the first output.
+    the second set of nInputs entries give delay of the second output, etc.
+
+    The Tim_Man_t is typically associated with the AIG manager (pGia) using 
+    pointer (pGia->pManTime). It is automatically deallocated when the host 
+    AIG manager is deleted.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Tim_Man_t_  Tim_Man_t;
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define TIM_ETERNITY 1000000000
+
+////////////////////////////////////////////////////////////////////////
+///                             ITERATORS                            ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     SEQUENTIAL ITERATORS                         ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== timBox.c ===========================================================*/
+extern void            Tim_ManCreateBox( Tim_Man_t * p, int firstIn, int nIns, int firstOut, int nOuts, int iDelayTable );
+extern int             Tim_ManBoxForCi( Tim_Man_t * p, int iCo );
+extern int             Tim_ManBoxForCo( Tim_Man_t * p, int iCi );
+extern int             Tim_ManBoxInputFirst( Tim_Man_t * p, int iBox );
+extern int             Tim_ManBoxOutputFirst( Tim_Man_t * p, int iBox );
+extern int             Tim_ManBoxInputNum( Tim_Man_t * p, int iBox );
+extern int             Tim_ManBoxOutputNum( Tim_Man_t * p, int iBox );
+extern int             Tim_ManBoxDelayTableId( Tim_Man_t * p, int iBox );
+extern float *         Tim_ManBoxDelayTable( Tim_Man_t * p, int iBox );
+extern int             Tim_ManBoxIsBlack( Tim_Man_t * p, int iBox );
+extern int             Tim_ManBoxCopy( Tim_Man_t * p, int iBox );
+extern void            Tim_ManBoxSetCopy( Tim_Man_t * p, int iBox, int iCopy );
+extern int             Tim_ManBoxFindFromCiNum( Tim_Man_t * p, int iCiNum );
+/*=== timDump.c ===========================================================*/
+extern Vec_Str_t *     Tim_ManSave( Tim_Man_t * p, int fHieOnly );
+extern Tim_Man_t *     Tim_ManLoad( Vec_Str_t * p, int fHieOnly );
+/*=== timMan.c ===========================================================*/
+extern Tim_Man_t *     Tim_ManStart( int nCis, int nCos );
+extern Tim_Man_t *     Tim_ManDup( Tim_Man_t * p, int fUnitDelay );
+extern Tim_Man_t *     Tim_ManTrim( Tim_Man_t * p, Vec_Int_t * vBoxPres );
+extern Vec_Int_t *     Tim_ManAlignTwo( Tim_Man_t * pSpec, Tim_Man_t * pImpl );
+extern void            Tim_ManCreate( Tim_Man_t * p, void * pLib, Vec_Flt_t * vInArrs, Vec_Flt_t * vOutReqs );
+extern float *         Tim_ManGetArrTimes( Tim_Man_t * p );
+extern float *         Tim_ManGetReqTimes( Tim_Man_t * p );
+extern void            Tim_ManStop( Tim_Man_t * p );
+extern void            Tim_ManStopP( Tim_Man_t ** p );
+extern void            Tim_ManPrint( Tim_Man_t * p );
+extern void            Tim_ManPrintStats( Tim_Man_t * p, int nAnd2Delay );
+extern int             Tim_ManCiNum( Tim_Man_t * p );
+extern int             Tim_ManCoNum( Tim_Man_t * p );
+extern int             Tim_ManPiNum( Tim_Man_t * p );
+extern int             Tim_ManPoNum( Tim_Man_t * p );
+extern int             Tim_ManBoxNum( Tim_Man_t * p );
+extern int             Tim_ManBlackBoxNum( Tim_Man_t * p );
+extern int             Tim_ManDelayTableNum( Tim_Man_t * p );
+extern void            Tim_ManSetDelayTables( Tim_Man_t * p, Vec_Ptr_t * vDelayTables );
+extern void            Tim_ManTravIdDisable( Tim_Man_t * p );
+extern void            Tim_ManTravIdEnable( Tim_Man_t * p );
+/*=== timTime.c ===========================================================*/
+extern void            Tim_ManInitPiArrival( Tim_Man_t * p, int iPi, float Delay );
+extern void            Tim_ManInitPoRequired( Tim_Man_t * p, int iPo, float Delay );
+extern void            Tim_ManInitPiArrivalAll( Tim_Man_t * p, float Delay );
+extern void            Tim_ManInitPoRequiredAll( Tim_Man_t * p, float Delay );
+extern void            Tim_ManSetCoArrival( Tim_Man_t * p, int iCo, float Delay );
+extern void            Tim_ManSetCiRequired( Tim_Man_t * p, int iCi, float Delay );
+extern void            Tim_ManSetCoRequired( Tim_Man_t * p, int iCo, float Delay );
+extern float           Tim_ManGetCiArrival( Tim_Man_t * p, int iCi );
+extern float           Tim_ManGetCoRequired( Tim_Man_t * p, int iCo );
+/*=== timTrav.c ===========================================================*/
+extern void            Tim_ManIncrementTravId( Tim_Man_t * p );
+extern void            Tim_ManSetCurrentTravIdBoxInputs( Tim_Man_t * p, int iBox );
+extern void            Tim_ManSetCurrentTravIdBoxOutputs( Tim_Man_t * p, int iBox );
+extern void            Tim_ManSetPreviousTravIdBoxInputs( Tim_Man_t * p, int iBox );
+extern void            Tim_ManSetPreviousTravIdBoxOutputs( Tim_Man_t * p, int iBox );
+extern int             Tim_ManIsCiTravIdCurrent( Tim_Man_t * p, int iCi );
+extern int             Tim_ManIsCoTravIdCurrent( Tim_Man_t * p, int iCo );
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/tim/timBox.c b/abc-build/src/misc/tim/timBox.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/tim/timBox.c
@@ -0,0 +1,293 @@
+/**CFile****************************************************************
+
+  FileName    [timBox.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Hierarchy/timing manager.]
+
+  Synopsis    [Manipulation of timing boxes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: timBox.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "timInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the new timing box.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManCreateBox( Tim_Man_t * p, int firstIn, int nIns, int firstOut, int nOuts, int iDelayTable )
+{
+    Tim_Box_t * pBox;
+    int i;
+    if ( p->vBoxes == NULL )
+        p->vBoxes = Vec_PtrAlloc( 100 );
+    pBox = (Tim_Box_t *)Mem_FlexEntryFetch( p->pMemObj, sizeof(Tim_Box_t) + sizeof(int) * (nIns+nOuts) );
+    memset( pBox, 0, sizeof(Tim_Box_t) );
+    pBox->iBox = Vec_PtrSize( p->vBoxes );
+    Vec_PtrPush( p->vBoxes, pBox );
+    pBox->iDelayTable = iDelayTable;
+    pBox->nInputs  = nIns;
+    pBox->nOutputs = nOuts;
+    for ( i = 0; i < nIns; i++ )
+    {
+        assert( firstIn+i < p->nCos );
+        pBox->Inouts[i] = firstIn+i;
+        p->pCos[firstIn+i].iObj2Box = pBox->iBox;
+        p->pCos[firstIn+i].iObj2Num = i;
+    }
+    for ( i = 0; i < nOuts; i++ )
+    {
+        assert( firstOut+i < p->nCis );
+        pBox->Inouts[nIns+i] = firstOut+i;
+        p->pCis[firstOut+i].iObj2Box = pBox->iBox;
+        p->pCis[firstOut+i].iObj2Num = i;
+    }
+//    if ( pBox->iBox < 20 )
+//        printf( "%4d  %4d  %4d  %4d  \n", firstIn, nIns, firstOut, nOuts );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the box number for the given input.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tim_ManBoxForCi( Tim_Man_t * p, int iCi )
+{
+    if ( iCi >= p->nCis )
+        return -1;
+    return p->pCis[iCi].iObj2Box;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the box number for the given output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tim_ManBoxForCo( Tim_Man_t * p, int iCo )
+{
+    if ( iCo >= p->nCos )
+        return -1;
+    return p->pCos[iCo].iObj2Box;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the first input of the box.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tim_ManBoxInputFirst( Tim_Man_t * p, int iBox )
+{
+    return Tim_ManBox(p, iBox)->Inouts[0];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the first output of the box.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tim_ManBoxOutputFirst( Tim_Man_t * p, int iBox )
+{
+    return Tim_ManBox(p, iBox)->Inouts[Tim_ManBox(p, iBox)->nInputs];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of box inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tim_ManBoxInputNum( Tim_Man_t * p, int iBox )
+{
+    return Tim_ManBox(p, iBox)->nInputs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of box outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tim_ManBoxOutputNum( Tim_Man_t * p, int iBox )
+{
+    return Tim_ManBox(p, iBox)->nOutputs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Return the delay table id.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tim_ManBoxDelayTableId( Tim_Man_t * p, int iBox )
+{
+    return Tim_ManBox(p, iBox)->iDelayTable;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Return the delay table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float * Tim_ManBoxDelayTable( Tim_Man_t * p, int iBox )
+{
+    float * pTable;
+    Tim_Box_t * pBox = Tim_ManBox(p, iBox);
+    if ( pBox->iDelayTable < 0 )
+        return NULL;
+    pTable = (float *)Vec_PtrEntry( p->vDelayTables, pBox->iDelayTable );
+    assert( (int)pTable[1] == pBox->nInputs );
+    assert( (int)pTable[2] == pBox->nOutputs );
+    return pTable;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Return 1 if the box is black.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tim_ManBoxIsBlack( Tim_Man_t * p, int iBox )
+{
+    return Tim_ManBox(p, iBox)->fBlack;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the copy of the box.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tim_ManBoxCopy( Tim_Man_t * p, int iBox )
+{
+    return Tim_ManBox(p, iBox)->iCopy;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the copy of the box.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManBoxSetCopy( Tim_Man_t * p, int iBox, int iCopy )
+{
+    Tim_ManBox(p, iBox)->iCopy = iCopy;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tim_ManBoxFindFromCiNum( Tim_Man_t * p, int iCiNum )
+{
+    Tim_Box_t * pBox;
+    int i;
+    assert( iCiNum >= 0 && iCiNum < Tim_ManCiNum(p) );
+    if ( iCiNum < Tim_ManPiNum(p) )
+        return -1;
+    Tim_ManForEachBox( p, pBox, i )
+        if ( iCiNum < Tim_ManBoxOutputFirst(p, i) )
+            return i - 1;
+    return -2;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/tim/timDump.c b/abc-build/src/misc/tim/timDump.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/tim/timDump.c
@@ -0,0 +1,199 @@
+/**CFile****************************************************************
+
+  FileName    [timDump.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Hierarchy/timing manager.]
+
+  Synopsis    [Saving and loading the hierarchy timing manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: timDump.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "timInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define TIM_DUMP_VER_NUM 1
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Transform the timing manager into the char stream.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Tim_ManSave( Tim_Man_t * p, int fHieOnly )
+{
+    Tim_Box_t * pBox;
+    Tim_Obj_t * pObj;
+    Vec_Str_t * vStr;
+    float * pDelayTable;
+    int i, k, TableSize;
+    // create output stream
+    vStr = Vec_StrAlloc( 10000 );
+    // dump version number
+    Vec_StrPutI_ne( vStr, TIM_DUMP_VER_NUM );
+    // save CI/CO counts
+    Vec_StrPutI_ne( vStr, Tim_ManCiNum(p) );
+    Vec_StrPutI_ne( vStr, Tim_ManCoNum(p) );
+    // save PI/PO counts
+    Vec_StrPutI_ne( vStr, Tim_ManPiNum(p) );
+    Vec_StrPutI_ne( vStr, Tim_ManPoNum(p) );
+    // save number of boxes
+    Vec_StrPutI_ne( vStr, Tim_ManBoxNum(p) );
+    // for each box, save num_inputs, num_outputs, delay table ID, and copy field
+    if ( Tim_ManBoxNum(p) > 0 )
+    Tim_ManForEachBox( p, pBox, i )
+    {
+        Vec_StrPutI_ne( vStr, Tim_ManBoxInputNum(p, pBox->iBox) );
+        Vec_StrPutI_ne( vStr, Tim_ManBoxOutputNum(p, pBox->iBox) );
+        Vec_StrPutI_ne( vStr, Tim_ManBoxDelayTableId(p, pBox->iBox) ); // can be -1 if delay table is not given
+        Vec_StrPutI_ne( vStr, Tim_ManBoxCopy(p, pBox->iBox) );         // can be -1 if the copy is node defined
+    }
+    if ( fHieOnly )
+        return vStr;
+    // save the number of delay tables
+    Vec_StrPutI_ne( vStr, Tim_ManDelayTableNum(p) );
+    // save the delay tables
+    if ( Tim_ManDelayTableNum(p) > 0 )
+    Tim_ManForEachTable( p, pDelayTable, i )
+    {
+        assert( (int)pDelayTable[0] == i );
+        // save table ID and dimensions (inputs x outputs)
+        Vec_StrPutI_ne( vStr, (int)pDelayTable[0] );
+        Vec_StrPutI_ne( vStr, (int)pDelayTable[1] );
+        Vec_StrPutI_ne( vStr, (int)pDelayTable[2] );
+        // save table contents
+        TableSize = (int)pDelayTable[1] * (int)pDelayTable[2];
+        for ( k = 0; k < TableSize; k++ )
+            Vec_StrPutF( vStr, pDelayTable[k+3] );
+    }
+    // save PI arrival times
+    Tim_ManForEachPi( p, pObj, i )
+        Vec_StrPutF( vStr, Tim_ManGetCiArrival(p, pObj->Id) );
+    // save PO required times
+    Tim_ManForEachPo( p, pObj, i )
+        Vec_StrPutF( vStr, Tim_ManGetCoRequired(p, pObj->Id) );
+    return vStr;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Restores the timing manager from the char stream.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Tim_Man_t * Tim_ManLoad( Vec_Str_t * p, int fHieOnly )
+{
+    Tim_Man_t * pMan;
+    Tim_Obj_t * pObj;
+    int VerNum, nCis, nCos, nPis, nPos;
+    int nBoxes, nBoxIns, nBoxOuts, CopyBox;
+    int TableId, nTables, TableSize, TableX, TableY;
+    int i, k, curPi, curPo, iStr = 0;
+    float * pDelayTable;
+    // get version number 
+    VerNum = Vec_StrGetI_ne( p, &iStr );
+    assert( VerNum == TIM_DUMP_VER_NUM );
+    // get the number of CIs/COs
+    nCis = Vec_StrGetI_ne( p, &iStr );
+    nCos = Vec_StrGetI_ne( p, &iStr );
+    // get the number of PIs/POs
+    nPis = Vec_StrGetI_ne( p, &iStr );
+    nPos = Vec_StrGetI_ne( p, &iStr );
+    // start the timing manager
+    pMan = Tim_ManStart( nCis, nCos );
+    // start boxes
+    nBoxes = Vec_StrGetI_ne( p, &iStr );
+    assert( pMan->vBoxes == NULL );
+    if ( nBoxes > 0 )
+        pMan->vBoxes = Vec_PtrAlloc( nBoxes );
+    // create boxes
+    curPi = nPis;
+    curPo = 0;
+    for ( i = 0; i < nBoxes; i++ )
+    {
+        nBoxIns  = Vec_StrGetI_ne( p, &iStr );
+        nBoxOuts = Vec_StrGetI_ne( p, &iStr );
+        TableId  = Vec_StrGetI_ne( p, &iStr );
+        CopyBox  = Vec_StrGetI_ne( p, &iStr );
+        Tim_ManCreateBox( pMan, curPo, nBoxIns, curPi, nBoxOuts, TableId );
+        Tim_ManBoxSetCopy( pMan, i, CopyBox );
+        curPi += nBoxOuts;
+        curPo += nBoxIns;
+    }
+    curPo += nPos;
+    assert( curPi == nCis );
+    assert( curPo == nCos );
+    if ( fHieOnly )
+        return pMan;
+    // create delay tables
+    nTables = Vec_StrGetI_ne( p, &iStr );
+    assert( pMan->vDelayTables == NULL );
+    if ( nTables > 0 )
+        pMan->vDelayTables = Vec_PtrAlloc( nTables );
+    // read delay tables
+    for ( i = 0; i < nTables; i++ )
+    {
+        // read table ID and dimensions
+        TableId = Vec_StrGetI_ne( p, &iStr );
+        TableX  = Vec_StrGetI_ne( p, &iStr );
+        TableY  = Vec_StrGetI_ne( p, &iStr );
+        assert( TableId == i );
+        // create new table
+        TableSize = TableX * TableY;
+        pDelayTable = ABC_ALLOC( float, TableSize + 3 );
+        pDelayTable[0] = TableId;
+        pDelayTable[1] = TableX;
+        pDelayTable[2] = TableY;
+        // read table contents
+        for ( k = 0; k < TableSize; k++ )
+            pDelayTable[k+3] = Vec_StrGetF( p, &iStr );
+        assert( Vec_PtrSize(pMan->vDelayTables) == TableId );
+        Vec_PtrPush( pMan->vDelayTables, pDelayTable );
+    }
+    assert( Tim_ManDelayTableNum(pMan) == nTables );
+    // read PI arrival times
+    Tim_ManForEachPi( pMan, pObj, i )
+        Tim_ManInitPiArrival( pMan, i, Vec_StrGetF(p, &iStr) );
+    // read PO required times
+    Tim_ManForEachPo( pMan, pObj, i )
+        Tim_ManInitPoRequired( pMan, i, Vec_StrGetF(p, &iStr) );
+    assert( Vec_StrSize(p) == iStr );
+//    Tim_ManPrint( pMan );
+    return pMan;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/tim/timInt.h b/abc-build/src/misc/tim/timInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/tim/timInt.h
@@ -0,0 +1,148 @@
+/**CFile****************************************************************
+
+  FileName    [timInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Hierarchy/timing manager.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: timInt.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__tim__timInt_h
+#define ABC__aig__tim__timInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+#include "misc/mem/mem.h"
+#include "tim.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Tim_Box_t_           Tim_Box_t;
+typedef struct Tim_Obj_t_           Tim_Obj_t;
+
+// timing manager
+struct Tim_Man_t_
+{
+    Vec_Ptr_t *      vBoxes;         // the timing boxes
+    Vec_Ptr_t *      vDelayTables;   // pointers to the delay tables
+    Mem_Flex_t *     pMemObj;        // memory manager for boxes
+    int              nTravIds;       // traversal ID of the manager
+    int              fUseTravId;     // enables the use of traversal ID
+    int              nCis;           // the number of PIs
+    int              nCos;           // the number of POs
+    Tim_Obj_t *      pCis;           // timing info for the PIs
+    Tim_Obj_t *      pCos;           // timing info for the POs
+};
+
+// timing box
+struct Tim_Box_t_
+{
+    int              iBox;           // the unique ID of this box
+    int              TravId;         // traversal ID of this box
+    int              nInputs;        // the number of box inputs (POs)
+    int              nOutputs;       // the number of box outputs (PIs)
+    int              iDelayTable;    // index of the delay table
+    int              iCopy;          // copy of this box
+    int              fBlack;         // this is black box
+    int              Inouts[0];      // the int numbers of PIs and POs
+};
+
+// timing object
+struct Tim_Obj_t_
+{
+    int              Id;             // the ID of this object
+    int              TravId;         // traversal ID of this object
+    int              iObj2Box;       // mapping of the object into its box
+    int              iObj2Num;       // mapping of the object into its number in the box
+    float            timeArr;        // arrival time of the object
+    float            timeReq;        // required time of the object
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline Tim_Obj_t * Tim_ManCi( Tim_Man_t * p, int i )                           { assert( i < p->nCis ); return p->pCis + i;      }
+static inline Tim_Obj_t * Tim_ManCo( Tim_Man_t * p, int i )                           { assert( i < p->nCos ); return p->pCos + i;      }
+static inline Tim_Box_t * Tim_ManBox( Tim_Man_t * p, int i )                          { return (Tim_Box_t *)Vec_PtrEntry(p->vBoxes, i); }
+
+static inline Tim_Box_t * Tim_ManCiBox( Tim_Man_t * p, int i )                        { return Tim_ManCi(p,i)->iObj2Box < 0 ? NULL : (Tim_Box_t *)Vec_PtrEntry( p->vBoxes, Tim_ManCi(p,i)->iObj2Box ); }
+static inline Tim_Box_t * Tim_ManCoBox( Tim_Man_t * p, int i )                        { return Tim_ManCo(p,i)->iObj2Box < 0 ? NULL : (Tim_Box_t *)Vec_PtrEntry( p->vBoxes, Tim_ManCo(p,i)->iObj2Box ); }
+
+static inline Tim_Obj_t * Tim_ManBoxInput( Tim_Man_t * p, Tim_Box_t * pBox, int i )   { assert( i < pBox->nInputs  ); return p->pCos + pBox->Inouts[i];               }
+static inline Tim_Obj_t * Tim_ManBoxOutput( Tim_Man_t * p, Tim_Box_t * pBox, int i )  { assert( i < pBox->nOutputs ); return p->pCis + pBox->Inouts[pBox->nInputs+i]; }
+
+////////////////////////////////////////////////////////////////////////
+///                             ITERATORS                            ///
+////////////////////////////////////////////////////////////////////////
+
+#define Tim_ManForEachCi( p, pObj, i )                                  \
+    for ( i = 0; (i < (p)->nCis) && ((pObj) = (p)->pCis + i); i++ )
+#define Tim_ManForEachCo( p, pObj, i )                                  \
+    for ( i = 0; (i < (p)->nCos) && ((pObj) = (p)->pCos + i); i++ )
+
+#define Tim_ManForEachPi( p, pObj, i )                                  \
+    Tim_ManForEachCi( p, pObj, i ) if ( pObj->iObj2Box >= 0 ) {} else 
+#define Tim_ManForEachPo( p, pObj, i )                                  \
+    Tim_ManForEachCo( p, pObj, i ) if ( pObj->iObj2Box >= 0 ) {} else 
+
+#define Tim_ManForEachBox( p, pBox, i )                                 \
+    Vec_PtrForEachEntry( Tim_Box_t *, p->vBoxes, pBox, i )
+
+#define Tim_ManBoxForEachInput( p, pBox, pObj, i )                      \
+    for ( i = 0; (i < (pBox)->nInputs) && ((pObj) = Tim_ManBoxInput(p, pBox, i)); i++ )
+#define Tim_ManBoxForEachOutput( p, pBox, pObj, i )                     \
+    for ( i = 0; (i < (pBox)->nOutputs) && ((pObj) = Tim_ManBoxOutput(p, pBox, i)); i++ )
+
+#define Tim_ManForEachTable( p, pTable, i )                             \
+    Vec_PtrForEachEntry( float *, p->vDelayTables, pTable, i )
+
+////////////////////////////////////////////////////////////////////////
+///                     SEQUENTIAL ITERATORS                         ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== time.c ===========================================================*/
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/tim/timMan.c b/abc-build/src/misc/tim/timMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/tim/timMan.c
@@ -0,0 +1,679 @@
+/**CFile****************************************************************
+
+  FileName    [timMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Hierarchy/timing manager.]
+
+  Synopsis    [Manipulation of manager data-structure.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: timMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "timInt.h"
+#include "map/if/if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the timing manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Tim_Man_t * Tim_ManStart( int nCis, int nCos )
+{
+    Tim_Man_t * p;
+    Tim_Obj_t * pObj;
+    int i;
+    p = ABC_ALLOC( Tim_Man_t, 1 );
+    memset( p, 0, sizeof(Tim_Man_t) );
+    p->pMemObj = Mem_FlexStart();
+    p->nCis = nCis;
+    p->nCos = nCos;
+    p->pCis = ABC_ALLOC( Tim_Obj_t, nCis );
+    memset( p->pCis, 0, sizeof(Tim_Obj_t) * nCis );
+    p->pCos = ABC_ALLOC( Tim_Obj_t, nCos );
+    memset( p->pCos, 0, sizeof(Tim_Obj_t) * nCos );
+    Tim_ManForEachCi( p, pObj, i )
+    {
+        pObj->Id = i;
+        pObj->iObj2Box = pObj->iObj2Num = -1;
+        pObj->timeReq = TIM_ETERNITY;
+    }
+    Tim_ManForEachCo( p, pObj, i )
+    {
+        pObj->Id = i;
+        pObj->iObj2Box = pObj->iObj2Num = -1;
+        pObj->timeReq = TIM_ETERNITY;
+    }
+    p->fUseTravId = 1;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the timing manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Tim_Man_t * Tim_ManDup( Tim_Man_t * p, int fUnitDelay )
+{
+    Tim_Man_t * pNew;
+    Tim_Box_t * pBox;
+    Tim_Obj_t * pObj;
+    float * pDelayTable, * pDelayTableNew;
+    int i, k, nInputs, nOutputs;
+    // clear traversal IDs
+    Tim_ManForEachCi( p, pObj, i ) 
+        pObj->TravId = 0;          
+    Tim_ManForEachCo( p, pObj, i ) 
+        pObj->TravId = 0;          
+    // create new manager
+    pNew = Tim_ManStart( p->nCis, p->nCos );
+    // copy box connectivity information
+    memcpy( pNew->pCis, p->pCis, sizeof(Tim_Obj_t) * p->nCis ); 
+    memcpy( pNew->pCos, p->pCos, sizeof(Tim_Obj_t) * p->nCos ); 
+    if ( fUnitDelay )
+    {
+        // discretize PI arrival times
+//        Tim_ManForEachPi( pNew, pObj, k )
+//          pObj->timeArr = (int)pObj->timeArr;
+        // discretize PO required times
+//        Tim_ManForEachPo( pNew, pObj, k )
+//          pObj->timeReq = 1 + (int)pObj->timeReq;
+        // clear PI arrival and PO required
+        Tim_ManInitPiArrivalAll( p, 0.0 );
+        Tim_ManInitPoRequiredAll( p, (float)TIM_ETERNITY );
+    }
+    // duplicate delay tables
+    if ( Tim_ManDelayTableNum(p) > 0 )
+    {
+        pNew->vDelayTables = Vec_PtrStart( Vec_PtrSize(p->vDelayTables) );
+        Tim_ManForEachTable( p, pDelayTable, i )
+        {
+            if ( pDelayTable == NULL )
+                continue;
+            assert( i == (int)pDelayTable[0] );
+            nInputs   = (int)pDelayTable[1];
+            nOutputs  = (int)pDelayTable[2];
+            pDelayTableNew = ABC_ALLOC( float, 3 + nInputs * nOutputs );
+            pDelayTableNew[0] = (int)pDelayTable[0];
+            pDelayTableNew[1] = (int)pDelayTable[1];
+            pDelayTableNew[2] = (int)pDelayTable[2];
+            for ( k = 0; k < nInputs * nOutputs; k++ )
+                pDelayTableNew[3+k] = fUnitDelay ? 1.0 : pDelayTable[3+k];
+//            assert( (int)pDelayTableNew[0] == Vec_PtrSize(pNew->vDelayTables) );
+            assert( Vec_PtrEntry(pNew->vDelayTables, i) == NULL );
+            Vec_PtrWriteEntry( pNew->vDelayTables, i, pDelayTableNew );
+//printf( "Finished duplicating delay table %d.\n", i );
+        }
+    }
+    // duplicate boxes
+    if ( Tim_ManBoxNum(p) > 0 )
+    {
+        pNew->vBoxes = Vec_PtrAlloc( Tim_ManBoxNum(p) );
+        Tim_ManForEachBox( p, pBox, i )
+           Tim_ManCreateBox( pNew, pBox->Inouts[0], pBox->nInputs, 
+                pBox->Inouts[pBox->nInputs], pBox->nOutputs, pBox->iDelayTable );
+    }
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Trims the timing manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Tim_Man_t * Tim_ManTrim( Tim_Man_t * p, Vec_Int_t * vBoxPres )
+{
+    Tim_Man_t * pNew;
+    Tim_Box_t * pBox;
+    Tim_Obj_t * pObj;
+    float * pDelayTable, * pDelayTableNew;
+    int i, k, nNewCis, nNewCos, nInputs, nOutputs;
+    assert( Vec_IntSize(vBoxPres) == Tim_ManBoxNum(p) );
+    // count the number of CIs and COs in the trimmed manager
+    nNewCis = Tim_ManPiNum(p);
+    nNewCos = Tim_ManPoNum(p);
+    if ( Tim_ManBoxNum(p) )
+        Tim_ManForEachBox( p, pBox, i )
+            if ( Vec_IntEntry(vBoxPres, i) )
+            {
+                nNewCis += pBox->nOutputs;
+                nNewCos += pBox->nInputs;
+            }
+    if ( nNewCis == Tim_ManCiNum(p) && nNewCos == Tim_ManCoNum(p) )
+        return Tim_ManDup( p, 0 );
+    assert( nNewCis < Tim_ManCiNum(p) );
+    assert( nNewCos < Tim_ManCoNum(p) );
+    // clear traversal IDs
+    Tim_ManForEachCi( p, pObj, i ) 
+        pObj->TravId = 0;          
+    Tim_ManForEachCo( p, pObj, i ) 
+        pObj->TravId = 0;          
+    // create new manager
+    pNew = Tim_ManStart( nNewCis, nNewCos );
+    // copy box connectivity information
+    memcpy( pNew->pCis, p->pCis, sizeof(Tim_Obj_t) * Tim_ManPiNum(p) );
+    memcpy( pNew->pCos + nNewCos - Tim_ManPoNum(p), 
+            p->pCos + Tim_ManCoNum(p) - Tim_ManPoNum(p), 
+            sizeof(Tim_Obj_t) * Tim_ManPoNum(p) );
+    // duplicate delay tables
+    if ( Tim_ManDelayTableNum(p) > 0 )
+    {
+        pNew->vDelayTables = Vec_PtrStart( Vec_PtrSize(p->vDelayTables) );
+        Tim_ManForEachTable( p, pDelayTable, i )
+        {
+            if ( pDelayTable == NULL )
+                continue;
+            assert( i == (int)pDelayTable[0] );
+            nInputs   = (int)pDelayTable[1];
+            nOutputs  = (int)pDelayTable[2];
+            pDelayTableNew = ABC_ALLOC( float, 3 + nInputs * nOutputs );
+            pDelayTableNew[0] = (int)pDelayTable[0];
+            pDelayTableNew[1] = (int)pDelayTable[1];
+            pDelayTableNew[2] = (int)pDelayTable[2];
+            for ( k = 0; k < nInputs * nOutputs; k++ )
+                pDelayTableNew[3+k] = pDelayTable[3+k];
+//            assert( (int)pDelayTableNew[0] == Vec_PtrSize(pNew->vDelayTables) );
+            assert( Vec_PtrEntry(pNew->vDelayTables, i) == NULL );
+            Vec_PtrWriteEntry( pNew->vDelayTables, i, pDelayTableNew );
+        }
+    }
+    // duplicate boxes
+    if ( Tim_ManBoxNum(p) > 0 )
+    {
+        int curPi = Tim_ManPiNum(p);
+        int curPo = 0;
+        pNew->vBoxes = Vec_PtrAlloc( Tim_ManBoxNum(p) );
+        Tim_ManForEachBox( p, pBox, i )
+            if ( Vec_IntEntry(vBoxPres, i) )
+            {
+                Tim_ManCreateBox( pNew, curPo, pBox->nInputs, curPi, pBox->nOutputs, pBox->iDelayTable );
+                Tim_ManBoxSetCopy( pNew, Tim_ManBoxNum(pNew) - 1, i );
+                curPi += pBox->nOutputs;
+                curPo += pBox->nInputs;
+            }
+        curPo += Tim_ManPoNum(p);
+        assert( curPi == Tim_ManCiNum(pNew) );
+        assert( curPo == Tim_ManCoNum(pNew) );
+    }
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Aligns two sets of boxes using the copy field.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Tim_ManAlignTwo( Tim_Man_t * pSpec, Tim_Man_t * pImpl )
+{
+    Vec_Int_t * vBoxPres;
+    Tim_Box_t * pBox;
+    int i;
+    assert( Tim_ManBoxNum(pSpec) > Tim_ManBoxNum(pImpl) );
+    // check if boxes of pImpl can be aligned
+    Tim_ManForEachBox( pImpl, pBox, i )
+        if ( pBox->iCopy < 0 || pBox->iCopy >= Tim_ManBoxNum(pSpec) ) 
+            return NULL;
+    // map dropped boxes into 1, others into 0
+    vBoxPres = Vec_IntStart( Tim_ManBoxNum(pSpec) );
+    Tim_ManForEachBox( pImpl, pBox, i )
+    {
+        assert( !Vec_IntEntry(vBoxPres, pBox->iCopy) );
+        Vec_IntWriteEntry( vBoxPres, pBox->iCopy, 1 );
+    }
+    return vBoxPres;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the timing manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManStop( Tim_Man_t * p )
+{
+    Vec_PtrFreeFree( p->vDelayTables );
+    Vec_PtrFreeP( &p->vBoxes );
+    Mem_FlexStop( p->pMemObj, 0 );
+    ABC_FREE( p->pCis );
+    ABC_FREE( p->pCos );
+    ABC_FREE( p );
+}
+void Tim_ManStopP( Tim_Man_t ** p )
+{
+    if ( *p == NULL )
+        return;
+    Tim_ManStop( *p );
+    *p = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates manager using hierarchy / box library / delay info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManCreate( Tim_Man_t * p, void * pLib, Vec_Flt_t * vInArrs, Vec_Flt_t * vOutReqs )
+{
+    If_LibBox_t * pLibBox = (If_LibBox_t *)pLib;
+    If_Box_t * pIfBox;
+    Tim_Box_t * pBox;
+    Tim_Obj_t * pObj;
+    float * pTable;
+    int i, k;
+    assert( p->vDelayTables == NULL );
+    p->vDelayTables = Vec_PtrStart( Vec_PtrSize(pLibBox->vBoxes) );
+    if ( p->vBoxes )
+    Tim_ManForEachBox( p, pBox, i )
+    {
+        if ( pBox->iDelayTable == -1 )
+        {
+            // create table with constants
+            pTable = ABC_ALLOC( float, 3 + pBox->nInputs * pBox->nOutputs );
+            pTable[0] = pBox->iDelayTable;
+            pTable[1] = pBox->nInputs;
+            pTable[2] = pBox->nOutputs;
+            for ( k = 0; k < pBox->nInputs * pBox->nOutputs; k++ )
+                pTable[3 + k] = 1.0;
+            // save table
+            pBox->iDelayTable = Vec_PtrSize(p->vDelayTables);
+            Vec_PtrPush( p->vDelayTables, pTable );
+            continue;
+        }
+        assert( pBox->iDelayTable >= 0 && pBox->iDelayTable < Vec_PtrSize(pLibBox->vBoxes) );
+        pIfBox = (If_Box_t *)Vec_PtrEntry( pLibBox->vBoxes, pBox->iDelayTable );
+        assert( pIfBox != NULL );
+        assert( pIfBox->nPis == pBox->nInputs );
+        assert( pIfBox->nPos == pBox->nOutputs );
+        pBox->fBlack = pIfBox->fBlack;
+        if ( Vec_PtrEntry( p->vDelayTables, pBox->iDelayTable ) != NULL )
+            continue;
+        // create table of boxes
+        pTable = ABC_ALLOC( float, 3 + pBox->nInputs * pBox->nOutputs );
+        pTable[0] = pBox->iDelayTable;
+        pTable[1] = pBox->nInputs;
+        pTable[2] = pBox->nOutputs;
+        for ( k = 0; k < pBox->nInputs * pBox->nOutputs; k++ )
+            pTable[3 + k] = pIfBox->pDelays[k];
+        // save table
+        Vec_PtrWriteEntry( p->vDelayTables, pBox->iDelayTable, pTable );
+    }
+    // create arrival times
+    if ( vInArrs )
+    {
+        assert( Vec_FltSize(vInArrs) == Tim_ManPiNum(p) );
+        Tim_ManForEachPi( p, pObj, i )
+            pObj->timeArr = Vec_FltEntry(vInArrs, i);
+
+    }
+    // create required times
+    if ( vOutReqs )
+    {
+        k = 0;
+        assert( Vec_FltSize(vOutReqs) == Tim_ManPoNum(p) );
+        Tim_ManForEachPo( p, pObj, i )
+            pObj->timeReq = Vec_FltEntry(vOutReqs, k++);
+        assert( k == Tim_ManPoNum(p) );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Get arrival and required times if they are non-trivial.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float * Tim_ManGetArrTimes( Tim_Man_t * p )
+{
+    float * pTimes;
+    Tim_Obj_t * pObj;
+    int i;
+    Tim_ManForEachPi( p, pObj, i )
+        if ( pObj->timeArr != 0.0 )
+            break;
+    if ( i == Tim_ManPiNum(p) )
+        return NULL;
+    pTimes  = ABC_FALLOC( float, Tim_ManCiNum(p) );
+    Tim_ManForEachPi( p, pObj, i )
+        pTimes[i] = pObj->timeArr;
+    return pTimes;
+}
+float * Tim_ManGetReqTimes( Tim_Man_t * p )
+{
+    float * pTimes;
+    Tim_Obj_t * pObj;
+    int i, k = 0;
+    Tim_ManForEachPo( p, pObj, i )
+        if ( pObj->timeReq != TIM_ETERNITY )
+            break;
+    if ( i == Tim_ManPoNum(p) )
+        return NULL;
+    pTimes  = ABC_FALLOC( float, Tim_ManCoNum(p) );
+    Tim_ManForEachPo( p, pObj, i )
+        pTimes[k++] = pObj->timeArr;
+    assert( k == Tim_ManPoNum(p) );
+    return pTimes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the timing manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManPrint( Tim_Man_t * p )
+{
+    Tim_Box_t * pBox;
+    Tim_Obj_t * pObj, * pPrev;
+    float * pTable;
+    int i, j, k, TableX, TableY;
+    if ( p == NULL )
+        return;
+    printf( "TIMING MANAGER:\n" );
+    printf( "PI = %d. CI = %d. PO = %d. CO = %d. Box = %d.\n", 
+        Tim_ManPiNum(p), Tim_ManCiNum(p), Tim_ManPoNum(p), Tim_ManCoNum(p), Tim_ManBoxNum(p) );
+
+    // print CI info
+    pPrev = p->pCis;
+    Tim_ManForEachPi( p, pObj, i )
+        if ( pPrev->timeArr != pObj->timeArr || pPrev->timeReq != pObj->timeReq )
+            break;
+    if ( i == Tim_ManCiNum(p) )
+        printf( "All PIs :  arr = %5.3f  req = %5.3f\n", pPrev->timeArr, pPrev->timeReq );
+    else
+        Tim_ManForEachPi( p, pObj, i )
+            printf( "PI%5d :  arr = %5.3f  req = %5.3f\n", i, pObj->timeArr, pObj->timeReq );
+
+    // print CO info
+    pPrev = p->pCos;
+    Tim_ManForEachPo( p, pObj, i )
+        if ( pPrev->timeArr != pObj->timeArr || pPrev->timeReq != pObj->timeReq )
+            break;
+    if ( i == Tim_ManCoNum(p) )
+        printf( "All POs :  arr = %5.3f  req = %5.3f\n", pPrev->timeArr, pPrev->timeReq );
+    else
+    {
+        int k = 0;
+        Tim_ManForEachPo( p, pObj, i )
+            printf( "PO%5d :  arr = %5.3f  req = %5.3f\n", k++, pObj->timeArr, pObj->timeReq );
+    }
+
+    // print box info
+    if ( Tim_ManBoxNum(p) > 0 )
+    Tim_ManForEachBox( p, pBox, i )
+    {
+        printf( "*** Box %5d :  I =%4d. O =%4d. I1 =%6d. O1 =%6d. Table =%4d\n", 
+            i, pBox->nInputs, pBox->nOutputs, 
+            Tim_ManBoxInputFirst(p, i), Tim_ManBoxOutputFirst(p, i), 
+            pBox->iDelayTable );
+
+        // print box inputs
+        pPrev = Tim_ManBoxInput( p, pBox, 0 );
+        Tim_ManBoxForEachInput( p, pBox, pObj, k )
+            if ( pPrev->timeArr != pObj->timeArr || pPrev->timeReq != pObj->timeReq )
+                break;
+        if ( k == Tim_ManBoxInputNum(p, pBox->iBox) )
+            printf( "Box inputs  :  arr = %5.3f  req = %5.3f\n", pPrev->timeArr, pPrev->timeReq );
+        else
+            Tim_ManBoxForEachInput( p, pBox, pObj, k )
+                printf( "box-in%4d :  arr = %5.3f  req = %5.3f\n", k, pObj->timeArr, pObj->timeReq );
+
+        // print box outputs
+        pPrev = Tim_ManBoxOutput( p, pBox, 0 );
+        Tim_ManBoxForEachOutput( p, pBox, pObj, k )
+            if ( pPrev->timeArr != pObj->timeArr || pPrev->timeReq != pObj->timeReq )
+                break;
+        if ( k == Tim_ManBoxOutputNum(p, pBox->iBox) )
+            printf( "Box outputs :  arr = %5.3f  req = %5.3f\n", pPrev->timeArr, pPrev->timeReq );
+        else
+            Tim_ManBoxForEachOutput( p, pBox, pObj, k )
+                printf( "box-out%3d :  arr = %5.3f  req = %5.3f\n", k, pObj->timeArr, pObj->timeReq );
+
+        if ( i > 2 )
+            break;
+    }
+
+    // print delay tables
+    if ( Tim_ManDelayTableNum(p) > 0 )
+    Tim_ManForEachTable( p, pTable, i )
+    {
+        if ( pTable == NULL )
+            continue;
+        printf( "Delay table %d:\n", i );
+        assert( i == (int)pTable[0] );
+        TableX = (int)pTable[1];
+        TableY = (int)pTable[2];
+        for ( j = 0; j < TableY; j++, printf( "\n" ) )
+            for ( k = 0; k < TableX; k++ )
+                if ( pTable[3+j*TableX+k] == -ABC_INFINITY )
+                    printf( "%5s", "-" );
+                else
+                    printf( "%5.0f", pTable[3+j*TableX+k] );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints statistics of the timing manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManPrintStats( Tim_Man_t * p, int nAnd2Delay )
+{
+    Tim_Box_t * pBox;
+    Vec_Int_t * vCounts;
+    Vec_Ptr_t * vBoxes;
+    int i, Count, IdMax;
+    if ( p == NULL )
+        return;
+    Abc_Print( 1, "Hierarchy      :  " );
+    printf( "PI/CI = %d/%d   PO/CO = %d/%d   Box = %d   ", 
+        Tim_ManPiNum(p), Tim_ManCiNum(p), 
+        Tim_ManPoNum(p), Tim_ManCoNum(p), 
+        Tim_ManBoxNum(p) );
+    if ( nAnd2Delay )
+        printf( "delay(AND2) = %d", nAnd2Delay );
+    printf( "\n" );
+    if ( Tim_ManBoxNum(p) == 0 )
+        return;
+    IdMax = 0;
+    Tim_ManForEachBox( p, pBox, i )
+        IdMax = Abc_MaxInt( IdMax, pBox->iDelayTable );
+    vCounts = Vec_IntStart( IdMax+1 );
+    vBoxes  = Vec_PtrStart( IdMax+1 );
+    Tim_ManForEachBox( p, pBox, i )
+    {
+        Vec_IntAddToEntry( vCounts, pBox->iDelayTable, 1 );
+        Vec_PtrWriteEntry( vBoxes, pBox->iDelayTable, pBox );
+    }
+    // print statistics about boxes
+    Vec_IntForEachEntry( vCounts, Count, i )
+    {
+        if ( Count == 0 ) continue;
+        pBox = (Tim_Box_t *)Vec_PtrEntry( vBoxes, i );
+        printf( "    Box %4d      ", i );
+        printf( "Num = %4d   ", Count );
+        printf( "Ins = %4d   ", pBox->nInputs );
+        printf( "Outs = %4d",   pBox->nOutputs );
+        printf( "\n" );
+    }
+    Vec_IntFree( vCounts );
+    Vec_PtrFree( vBoxes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Read parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tim_ManCiNum( Tim_Man_t * p )
+{
+    return p->nCis;
+}
+int Tim_ManCoNum( Tim_Man_t * p )
+{
+    return p->nCos;
+}
+int Tim_ManPiNum( Tim_Man_t * p )
+{
+    if ( Tim_ManBoxNum(p) == 0 )
+        return Tim_ManCiNum(p);
+    return Tim_ManBoxOutputFirst(p, 0);
+}
+int Tim_ManPoNum( Tim_Man_t * p )
+{
+    int iLastBoxId;
+    if ( Tim_ManBoxNum(p) == 0 )
+        return Tim_ManCoNum(p);
+    iLastBoxId = Tim_ManBoxNum(p) - 1;
+    return Tim_ManCoNum(p) - (Tim_ManBoxInputFirst(p, iLastBoxId) + Tim_ManBoxInputNum(p, iLastBoxId));
+}
+int Tim_ManBoxNum( Tim_Man_t * p )
+{
+    return p->vBoxes ? Vec_PtrSize(p->vBoxes) : 0;
+}
+int Tim_ManBlackBoxNum( Tim_Man_t * p )
+{
+    Tim_Box_t * pBox;
+    int i, Counter = 0;
+    if ( Tim_ManBoxNum(p) )
+        Tim_ManForEachBox( p, pBox, i )
+            Counter += pBox->fBlack;
+    return Counter;
+}
+int Tim_ManDelayTableNum( Tim_Man_t * p )
+{
+    return p->vDelayTables ? Vec_PtrSize(p->vDelayTables) : 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the vector of timing tables associated with the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManSetDelayTables( Tim_Man_t * p, Vec_Ptr_t * vDelayTables )
+{
+    assert( p->vDelayTables == NULL );
+    p->vDelayTables = vDelayTables;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Disables the use of the traversal ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManTravIdDisable( Tim_Man_t * p )
+{
+    p->fUseTravId = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Enables the use of the traversal ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManTravIdEnable( Tim_Man_t * p )
+{
+    p->fUseTravId = 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/tim/timTime.c b/abc-build/src/misc/tim/timTime.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/tim/timTime.c
@@ -0,0 +1,265 @@
+/**CFile****************************************************************
+
+  FileName    [timTime.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Hierarchy/timing manager.]
+
+  Synopsis    [Setting and resetting timing information of the boxes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: timTime.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "timInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Initializes arrival time of the PI.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManInitPiArrival( Tim_Man_t * p, int iPi, float Delay )
+{
+    assert( iPi < p->nCis );
+    p->pCis[iPi].timeArr = Delay;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Initializes required time of the PO.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManInitPoRequired( Tim_Man_t * p, int iPo, float Delay )
+{
+    assert( iPo < p->nCos );
+    p->pCos[iPo].timeReq = Delay;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets arrival times of all PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManInitPiArrivalAll( Tim_Man_t * p, float Delay )
+{
+    Tim_Obj_t * pObj;
+    int i;
+    Tim_ManForEachPi( p, pObj, i )
+        Tim_ManInitPiArrival( p, i, Delay );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets required times of all POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManInitPoRequiredAll( Tim_Man_t * p, float Delay )
+{
+    Tim_Obj_t * pObj;
+    int i;
+    Tim_ManForEachPo( p, pObj, i )
+        Tim_ManSetCoRequired( p, i, Delay );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates arrival time of the CO.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManSetCoArrival( Tim_Man_t * p, int iCo, float Delay )
+{
+    assert( iCo < p->nCos );
+    assert( !p->fUseTravId || p->pCos[iCo].TravId != p->nTravIds );
+    p->pCos[iCo].timeArr = Delay;
+    p->pCos[iCo].TravId = p->nTravIds;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates required time of the CI.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManSetCiRequired( Tim_Man_t * p, int iCi, float Delay )
+{
+    assert( iCi < p->nCis );
+    assert( !p->fUseTravId || p->pCis[iCi].TravId != p->nTravIds );
+    p->pCis[iCi].timeReq = Delay;
+    p->pCis[iCi].TravId = p->nTravIds;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates required time of the CO.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManSetCoRequired( Tim_Man_t * p, int iCo, float Delay )
+{
+    assert( iCo < p->nCos );
+    assert( !p->fUseTravId || p->pCos[iCo].TravId != p->nTravIds );
+    p->pCos[iCo].timeReq = Delay;
+    p->pCos[iCo].TravId = p->nTravIds;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns CO arrival time.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Tim_ManGetCiArrival( Tim_Man_t * p, int iCi )
+{
+    Tim_Box_t * pBox;
+    Tim_Obj_t * pObjThis, * pObj, * pObjRes;
+    float * pTable, * pDelays, DelayBest;
+    int i, k;
+    // consider the already processed PI
+    pObjThis = Tim_ManCi( p, iCi );
+    if ( p->fUseTravId && pObjThis->TravId == p->nTravIds )
+        return pObjThis->timeArr;
+    pObjThis->TravId = p->nTravIds;
+    // consider the main PI
+    pBox = Tim_ManCiBox( p, iCi );
+    if ( pBox == NULL )
+        return pObjThis->timeArr;
+    // update box timing
+    pBox->TravId = p->nTravIds;
+    // get the arrival times of the inputs of the box (POs)
+    if ( p->fUseTravId )
+    Tim_ManBoxForEachInput( p, pBox, pObj, i )
+        if ( pObj->TravId != p->nTravIds )
+            printf( "Tim_ManGetCiArrival(): Input arrival times of the box are not up to date!\n" );
+    // compute the arrival times for each output of the box (PIs)
+    pTable = Tim_ManBoxDelayTable( p, pBox->iBox );
+    Tim_ManBoxForEachOutput( p, pBox, pObjRes, i )
+    {
+        pDelays = pTable + 3 + i * pBox->nInputs;
+        DelayBest = -TIM_ETERNITY;
+        Tim_ManBoxForEachInput( p, pBox, pObj, k )
+            DelayBest = Abc_MaxInt( DelayBest, pObj->timeArr + pDelays[k] );
+        pObjRes->timeArr = DelayBest;
+        pObjRes->TravId = p->nTravIds;
+    }
+    return pObjThis->timeArr;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns CO required time.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Tim_ManGetCoRequired( Tim_Man_t * p, int iCo )
+{
+    Tim_Box_t * pBox;
+    Tim_Obj_t * pObjThis, * pObj, * pObjRes;
+    float * pTable, * pDelays, DelayBest;
+    int i, k;
+    // consider the already processed PO
+    pObjThis = Tim_ManCo( p, iCo );
+    if ( p->fUseTravId && pObjThis->TravId == p->nTravIds )
+        return pObjThis->timeReq;
+    pObjThis->TravId = p->nTravIds;
+    // consider the main PO
+    pBox = Tim_ManCoBox( p, iCo );
+    if ( pBox == NULL )
+        return pObjThis->timeReq;
+    // update box timing
+    pBox->TravId = p->nTravIds;
+    // get the required times of the outputs of the box (PIs)
+    if ( p->fUseTravId )
+    Tim_ManBoxForEachOutput( p, pBox, pObj, i )
+        if ( pObj->TravId != p->nTravIds )
+            printf( "Tim_ManGetCoRequired(): Output required times of output %d the box %d are not up to date!\n", i, pBox->iBox );
+    // compute the required times for each input of the box (POs)
+    pTable = Tim_ManBoxDelayTable( p, pBox->iBox );
+    Tim_ManBoxForEachInput( p, pBox, pObjRes, i )
+    {
+        DelayBest = TIM_ETERNITY;
+        Tim_ManBoxForEachOutput( p, pBox, pObj, k )
+        {
+            pDelays = pTable + 3 + k * pBox->nInputs;
+            DelayBest = Abc_MinFloat( DelayBest, pObj->timeReq - pDelays[i] );
+        }
+        pObjRes->timeReq = DelayBest;
+        pObjRes->TravId = p->nTravIds;
+    }
+    return pObjThis->timeReq;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/tim/timTrav.c b/abc-build/src/misc/tim/timTrav.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/tim/timTrav.c
@@ -0,0 +1,185 @@
+/**CFile****************************************************************
+
+  FileName    [timTrav.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Hierarchy/timing manager.]
+
+  Synopsis    [Manipulation of traversal IDs.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: timTrav.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "timInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Increments the trav ID of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManIncrementTravId( Tim_Man_t * p )
+{
+    int i;
+    if ( p->nTravIds >= (1<<30)-1 )
+    {
+        p->nTravIds = 0;
+        for ( i = 0; i < p->nCis; i++ )
+            p->pCis[i].TravId = 0;
+        for ( i = 0; i < p->nCos; i++ )
+            p->pCos[i].TravId = 0;
+    }
+    assert( p->nTravIds < (1<<30)-1 );
+    p->nTravIds++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Label box inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManSetCurrentTravIdBoxInputs( Tim_Man_t * p, int iBox )
+{
+    Tim_Box_t * pBox;
+    Tim_Obj_t * pObj;
+    int i;
+    pBox = Tim_ManBox( p, iBox );
+    Tim_ManBoxForEachInput( p, pBox, pObj, i )
+        pObj->TravId = p->nTravIds;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Label box outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManSetCurrentTravIdBoxOutputs( Tim_Man_t * p, int iBox )
+{
+    Tim_Box_t * pBox;
+    Tim_Obj_t * pObj;
+    int i;
+    pBox = Tim_ManBox( p, iBox );
+    Tim_ManBoxForEachOutput( p, pBox, pObj, i )
+        pObj->TravId = p->nTravIds;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Label box inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManSetPreviousTravIdBoxInputs( Tim_Man_t * p, int iBox )
+{
+    Tim_Box_t * pBox;
+    Tim_Obj_t * pObj;
+    int i;
+    pBox = Tim_ManBox( p, iBox );
+    Tim_ManBoxForEachInput( p, pBox, pObj, i )
+        pObj->TravId = p->nTravIds - 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Label box outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tim_ManSetPreviousTravIdBoxOutputs( Tim_Man_t * p, int iBox )
+{
+    Tim_Box_t * pBox;
+    Tim_Obj_t * pObj;
+    int i;
+    pBox = Tim_ManBox( p, iBox );
+    Tim_ManBoxForEachOutput( p, pBox, pObj, i )
+        pObj->TravId = p->nTravIds - 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates required time of the CI.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tim_ManIsCiTravIdCurrent( Tim_Man_t * p, int iCi )
+{
+    assert( iCi < p->nCis );
+    assert( p->fUseTravId );
+    return p->pCis[iCi].TravId == p->nTravIds;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates required time of the CO.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tim_ManIsCoTravIdCurrent( Tim_Man_t * p, int iCo )
+{
+    assert( iCo < p->nCos );
+    assert( p->fUseTravId );
+    return p->pCos[iCo].TravId == p->nTravIds;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/util/abc_global.h b/abc-build/src/misc/util/abc_global.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/util/abc_global.h
@@ -0,0 +1,424 @@
+/**CFile****************************************************************
+
+  FileName    [abc_global.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Global declarations.]
+
+  Synopsis    [Global declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Jan 30, 2009.]
+
+  Revision    [$Id: abc_global.h,v 1.00 2009/01/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__misc__util__abc_global_h
+#define ABC__misc__util__abc_global_h
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#ifdef _WIN32
+#ifndef __MINGW32__
+#define inline __inline // compatible with MS VS 6.0
+#pragma warning(disable : 4152) // warning C4152: nonstandard extension, function/data pointer conversion in expression
+#pragma warning(disable : 4200) // warning C4200: nonstandard extension used : zero-sized array in struct/union
+#pragma warning(disable : 4244) // warning C4244: '+=' : conversion from 'int ' to 'unsigned short ', possible loss of data
+#pragma warning(disable : 4514) // warning C4514: 'Vec_StrPop' : unreferenced inline function has been removed
+#pragma warning(disable : 4710) // warning C4710: function 'Vec_PtrGrow' not inlined
+//#pragma warning( disable : 4273 )
+#endif
+#endif
+
+#ifdef WIN32
+  #ifdef WIN32_NO_DLL
+    #define ABC_DLLEXPORT
+    #define ABC_DLLIMPORT
+  #else
+    #define ABC_DLLEXPORT __declspec(dllexport)
+    #define ABC_DLLIMPORT __declspec(dllimport)
+  #endif
+#else  /* defined(WIN32) */
+#define ABC_DLLIMPORT
+#endif /* defined(WIN32) */
+
+#ifndef ABC_DLL
+#define ABC_DLL ABC_DLLIMPORT
+#endif
+
+// catch memory leaks in Visual Studio
+#ifdef WIN32
+  #ifdef _DEBUG
+    #define _CRTDBG_MAP_ALLOC
+    #include <crtdbg.h>
+  #endif
+#endif
+
+#if !defined(___unused)
+#if defined(__GNUC__)
+#define ___unused __attribute__ ((__unused__))
+#else
+#define ___unused
+#endif
+#endif
+
+/*
+#ifdef __cplusplus
+#error "C++ code"
+#else
+#error "C code"
+#endif
+*/
+
+#include <time.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+////////////////////////////////////////////////////////////////////////
+///                         NAMESPACES                               ///
+////////////////////////////////////////////////////////////////////////
+
+//#define ABC_NAMESPACE xxx
+
+#ifdef __cplusplus
+#  ifdef ABC_NAMESPACE
+#    define ABC_NAMESPACE_HEADER_START namespace ABC_NAMESPACE {
+#    define ABC_NAMESPACE_HEADER_END }
+#    define ABC_NAMESPACE_IMPL_START namespace ABC_NAMESPACE {
+#    define ABC_NAMESPACE_IMPL_END }
+#    define ABC_NAMESPACE_PREFIX ABC_NAMESPACE::
+#  else
+#    define ABC_NAMESPACE_HEADER_START extern "C" {
+#    define ABC_NAMESPACE_HEADER_END }
+#    define ABC_NAMESPACE_IMPL_START
+#    define ABC_NAMESPACE_IMPL_END
+#    define ABC_NAMESPACE_PREFIX
+#  endif // #ifdef ABC_NAMESPACE
+#else
+#  define ABC_NAMESPACE_HEADER_START
+#  define ABC_NAMESPACE_HEADER_END
+#  define ABC_NAMESPACE_IMPL_START
+#  define ABC_NAMESPACE_IMPL_END
+#  define ABC_NAMESPACE_PREFIX
+#endif // #ifdef __cplusplus
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+/**
+ * Pointer difference type; replacement for ptrdiff_t.
+ * This is a signed integral type that is the same size as a pointer.
+ * NOTE: This type may be different sizes on different platforms.
+ */
+#if       defined(__ccdoc__)
+typedef platform_dependent_type ABC_PTRDIFF_T;
+#elif     defined(LIN64)
+typedef long ABC_PTRDIFF_T;
+#elif     defined(NT64)
+typedef long long ABC_PTRDIFF_T;
+#elif     defined(NT) || defined(LIN) || defined(WIN32)
+typedef int ABC_PTRDIFF_T;
+#else
+   #error unknown platform
+#endif /* defined(PLATFORM) */
+
+/**
+ * Unsigned integral type that can contain a pointer.
+ * This is an unsigned integral type that is the same size as a pointer.
+ * NOTE: This type may be different sizes on different platforms.
+ */
+#if       defined(__ccdoc__)
+typedef platform_dependent_type ABC_PTRUINT_T;
+#elif     defined(LIN64)
+typedef unsigned long ABC_PTRUINT_T;
+#elif     defined(NT64)
+typedef unsigned long long ABC_PTRUINT_T;
+#elif     defined(NT) || defined(LIN) || defined(WIN32)
+typedef unsigned int ABC_PTRUINT_T;
+#else
+   #error unknown platform
+#endif /* defined(PLATFORM) */
+
+/**
+ * Signed integral type that can contain a pointer.
+ * This is a signed integral type that is the same size as a pointer.
+ * NOTE: This type may be different sizes on different platforms.
+ */
+#if       defined(__ccdoc__)
+typedef platform_dependent_type ABC_PTRINT_T;
+#elif     defined(LIN64)
+typedef long ABC_PTRINT_T;
+#elif     defined(NT64)
+typedef long long ABC_PTRINT_T;
+#elif     defined(NT) || defined(LIN) || defined(WIN32)
+typedef int ABC_PTRINT_T;
+#else
+   #error unknown platform
+#endif /* defined(PLATFORM) */
+
+/**
+ * 64-bit signed integral type.
+ */
+#if       defined(__ccdoc__)
+typedef platform_dependent_type ABC_INT64_T;
+#elif     defined(LIN64)
+typedef long ABC_INT64_T;
+#elif     defined(NT64) || defined(LIN)
+typedef long long ABC_INT64_T;
+#elif     defined(WIN32) || defined(NT)
+typedef signed __int64 ABC_INT64_T;
+#else
+   #error unknown platform
+#endif /* defined(PLATFORM) */
+
+/**
+ * 64-bit unsigned integral type.
+ */
+#if       defined(__ccdoc__)
+typedef platform_dependent_type ABC_UINT64_T;
+#elif     defined(LIN64)
+typedef unsigned long ABC_UINT64_T;
+#elif     defined(NT64) || defined(LIN)
+typedef unsigned long long ABC_UINT64_T;
+#elif     defined(WIN32) || defined(NT)
+typedef unsigned __int64 ABC_UINT64_T;
+#else
+   #error unknown platform
+#endif /* defined(PLATFORM) */
+
+#ifdef LIN
+  #define ABC_CONST(number) number ## ULL 
+#else // LIN64 and windows
+  #define ABC_CONST(number) number
+#endif
+
+typedef ABC_UINT64_T word;
+typedef ABC_INT64_T iword;
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define ABC_INFINITY    (100000000)
+
+#define ABC_SWAP(Type, a, b)  { Type t = a; a = b; b = t; }
+
+#define ABC_PRT(a,t)    (Abc_Print(1, "%s =", (a)), Abc_Print(1, "%9.2f sec\n", 1.0*(t)/(CLOCKS_PER_SEC)))
+#define ABC_PRTr(a,t)   (Abc_Print(1, "%s =", (a)), Abc_Print(1, "%9.2f sec\r", 1.0*(t)/(CLOCKS_PER_SEC)))
+#define ABC_PRTn(a,t)   (Abc_Print(1, "%s =", (a)), Abc_Print(1, "%9.2f sec  ", 1.0*(t)/(CLOCKS_PER_SEC)))
+#define ABC_PRTP(a,t,T) (Abc_Print(1, "%s =", (a)), Abc_Print(1, "%9.2f sec (%6.2f %%)\n", 1.0*(t)/(CLOCKS_PER_SEC), (T)? 100.0*(t)/(T) : 0.0))
+#define ABC_PRM(a,f)    (Abc_Print(1, "%s =", (a)), Abc_Print(1, "%10.3f MB\n",    1.0*(f)/(1<<20)))
+#define ABC_PRMr(a,f)   (Abc_Print(1, "%s =", (a)), Abc_Print(1, "%10.3f MB\r",    1.0*(f)/(1<<20)))
+#define ABC_PRMn(a,f)   (Abc_Print(1, "%s =", (a)), Abc_Print(1, "%10.3f MB  ",    1.0*(f)/(1<<20)))
+#define ABC_PRMP(a,f,F) (Abc_Print(1, "%s =", (a)), Abc_Print(1, "%10.3f MB (%6.2f %%)\n",  (1.0*(f)/(1<<20)), ((F)? 100.0*(f)/(F) : 0.0) ) )
+
+#define ABC_ALLOC(type, num)     ((type *) malloc(sizeof(type) * (num)))
+#define ABC_CALLOC(type, num)    ((type *) calloc((num), sizeof(type)))
+#define ABC_FALLOC(type, num)    ((type *) memset(malloc(sizeof(type) * (num)), 0xff, sizeof(type) * (num)))
+#define ABC_FREE(obj)            ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#define ABC_REALLOC(type, obj, num) \
+        ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
+         ((type *) malloc(sizeof(type) * (num))))
+
+static inline int      Abc_AbsInt( int a        )             { return a < 0 ? -a : a; }
+static inline int      Abc_MaxInt( int a, int b )             { return a > b ?  a : b; }
+static inline int      Abc_MinInt( int a, int b )             { return a < b ?  a : b; }
+static inline word     Abc_MaxWord( word a, word b )          { return a > b ?  a : b; }
+static inline word     Abc_MinWord( word a, word b )          { return a < b ?  a : b; }
+static inline float    Abc_AbsFloat( float a          )       { return a < 0 ? -a : a; }
+static inline float    Abc_MaxFloat( float a, float b )       { return a > b ?  a : b; }
+static inline float    Abc_MinFloat( float a, float b )       { return a < b ?  a : b; }
+static inline double   Abc_AbsDouble( double a           )    { return a < 0 ? -a : a; }
+static inline double   Abc_MaxDouble( double a, double b )    { return a > b ?  a : b; }
+static inline double   Abc_MinDouble( double a, double b )    { return a < b ?  a : b; }
+
+static inline int      Abc_Float2Int( float Val )             { union { int x; float y; } v; v.y = Val; return v.x;         }
+static inline float    Abc_Int2Float( int Num )               { union { int x; float y; } v; v.x = Num; return v.y;         }
+static inline int      Abc_Base2Log( unsigned n )             { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n >>= 1, r++ ) {}; return r; }
+static inline int      Abc_Base10Log( unsigned n )            { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n /= 10, r++ ) {}; return r; }
+static inline int      Abc_Base16Log( unsigned n )            { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n /= 16, r++ ) {}; return r; }
+static inline char *   Abc_UtilStrsav( char * s )             { return s ? strcpy(ABC_ALLOC(char, strlen(s)+1), s) : NULL;  }
+static inline int      Abc_BitWordNum( int nBits )            { return (nBits>>5) + ((nBits&31) > 0);                       }
+static inline int      Abc_TruthWordNum( int nVars )          { return nVars <= 5 ? 1 : (1 << (nVars - 5));                 }
+static inline int      Abc_Truth6WordNum( int nVars )         { return nVars <= 6 ? 1 : (1 << (nVars - 6));                 }
+static inline int      Abc_InfoHasBit( unsigned * p, int i )  { return (p[(i)>>5] & (1<<((i) & 31))) > 0;                   }
+static inline void     Abc_InfoSetBit( unsigned * p, int i )  { p[(i)>>5] |= (1<<((i) & 31));                               }
+static inline void     Abc_InfoXorBit( unsigned * p, int i )  { p[(i)>>5] ^= (1<<((i) & 31));                               }
+static inline unsigned Abc_InfoMask( int nVar )               { return (~(unsigned)0) >> (32-nVar);                         }
+
+static inline int      Abc_Var2Lit( int Var, int fCompl )     { return Var + Var + fCompl; }
+static inline int      Abc_Lit2Var( int Lit )                 { return Lit >> 1;           }
+static inline int      Abc_LitIsCompl( int Lit )              { return Lit & 1;            }
+static inline int      Abc_LitNot( int Lit )                  { return Lit ^ 1;            }
+static inline int      Abc_LitNotCond( int Lit, int c )       { return Lit ^ (int)(c > 0); }
+static inline int      Abc_LitRegular( int Lit )              { return Lit & ~01;          }
+static inline int      Abc_Lit2LitV( int * pMap, int Lit )    { return Abc_Var2Lit( pMap[Abc_Lit2Var(Lit)], Abc_LitIsCompl(Lit) );   }
+static inline int      Abc_Lit2LitL( int * pMap, int Lit )    { return Abc_LitNotCond( pMap[Abc_Lit2Var(Lit)], Abc_LitIsCompl(Lit) );   }
+
+
+// time counting
+typedef ABC_INT64_T abctime;
+static inline abctime Abc_Clock()
+{
+#if (defined(LIN) || defined(LIN64)) && !(__APPLE__ & __MACH__) && !defined(__MINGW32__)
+    struct timespec ts;
+    if ( clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) < 0 ) 
+        return (abctime)-1;
+    abctime res = ((abctime) ts.tv_sec) * CLOCKS_PER_SEC;
+    res += (((abctime) ts.tv_nsec) * CLOCKS_PER_SEC) / 1000000000;
+    return res;
+#else
+    return (abctime) clock();
+#endif
+}
+
+// bridge communication
+#define BRIDGE_NETLIST           106
+#define BRIDGE_ABS_NETLIST       107
+extern int Gia_ManToBridgeText( FILE * pFile, int Size, unsigned char * pBuffer );
+extern int Gia_ManToBridgeAbsNetlist( FILE * pFile, void * p, int pkg_type );
+
+// string printing
+extern char * vnsprintf(const char* format, va_list args);
+extern char * nsprintf(const char* format, ...);
+
+
+// misc printing procedures
+enum Abc_VerbLevel
+{
+    ABC_PROMPT   = -2,
+    ABC_ERROR    = -1,
+    ABC_WARNING  =  0,
+    ABC_STANDARD =  1,
+    ABC_VERBOSE  =  2
+};
+static inline void Abc_Print( int level, const char * format, ... )
+{
+#ifndef ABC_LIB
+    extern ABC_DLL int Abc_FrameIsBridgeMode();
+    va_list args;
+
+    if ( ! Abc_FrameIsBridgeMode() ){
+        if ( level == ABC_ERROR )
+            printf( "Error: " );
+        else if ( level == ABC_WARNING )
+            printf( "Warning: " );
+    }else{
+        if ( level == ABC_ERROR )
+            Gia_ManToBridgeText( stdout, strlen("Error: "), (unsigned char*)"Error: " );
+        else if ( level == ABC_WARNING )
+            Gia_ManToBridgeText( stdout, strlen("Warning: "), (unsigned char*)"Warning: " );
+    }
+
+    va_start( args, format );
+    if ( Abc_FrameIsBridgeMode() )
+    {
+        char * tmp = vnsprintf( format, args );
+        Gia_ManToBridgeText( stdout, strlen(tmp), (unsigned char*)tmp );
+        free( tmp );
+    }
+    else
+        vprintf( format, args );
+    va_end( args );
+#endif
+}
+
+static inline void Abc_PrintInt( int i )
+{
+    double v3 = (double)i/1000;
+    double v6 = (double)i/1000000;
+
+    Abc_Print( 1,  "  " );
+
+    if ( i > -1000 && i < 1000 )
+        Abc_Print( 1, " %4d", i );
+
+    else if ( v3 > -9.995 && v3 < 9.995 )
+        Abc_Print( 1, "%4.2fk", v3 );
+    else if ( v3 > -99.95 && v3 < 99.95 )
+        Abc_Print( 1, "%4.1fk", v3 );
+    else if ( v3 > -999.5 && v3 < 999.5 )
+        Abc_Print( 1, "%4.0fk", v3 );
+
+    else if ( v6 > -9.995 && v6 < 9.995 )
+        Abc_Print( 1, "%4.2fm", v6 );
+    else if ( v6 > -99.95 && v6 < 99.95 )
+        Abc_Print( 1, "%4.1fm", v6 );
+    else if ( v6 > -999.5 && v6 < 999.5 )
+        Abc_Print( 1, "%4.0fm", v6 );
+}
+
+static inline void Abc_PrintTime( int level, const char * pStr, abctime time )
+{
+    ABC_PRT( pStr, time );
+}
+
+static inline void Abc_PrintTimeP( int level, const char * pStr, abctime time, abctime Time )
+{
+    ABC_PRTP( pStr, time, Time );
+}
+
+static inline void Abc_PrintMemoryP( int level, const char * pStr, int mem, int Mem )
+{
+    ABC_PRMP( pStr, mem, Mem );
+}
+
+// Returns the next prime >= p
+static inline int Abc_PrimeCudd( unsigned int p )
+{
+    int i,pn;
+    p--;
+    do {
+        p++;
+        if (p&1)
+        {
+            pn = 1;
+            i = 3;
+            while ((unsigned) (i * i) <= p)
+            {
+                if (p % i == 0) {
+                    pn = 0;
+                    break;
+                }
+                i += 2;
+            }
+        }
+        else
+            pn = 0;
+    } while (!pn);
+    return(p);
+
+} // end of Cudd_Prime 
+
+
+// sorting
+extern void   Abc_MergeSort( int * pInput, int nSize );
+extern int *  Abc_MergeSortCost( int * pCosts, int nSize );
+extern void   Abc_QuickSort1( word * pData, int nSize, int fDecrease );
+extern void   Abc_QuickSort2( word * pData, int nSize, int fDecrease );
+extern void   Abc_QuickSort3( word * pData, int nSize, int fDecrease );
+extern void   Abc_QuickSortCostData( int * pCosts, int nSize, int fDecrease, word * pData, int * pResult );
+extern int *  Abc_QuickSortCost( int * pCosts, int nSize, int fDecrease );
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/misc/util/module.make b/abc-build/src/misc/util/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/util/module.make
@@ -0,0 +1,7 @@
+SRC +=  src/misc/util/utilBridge.c \
+	src/misc/util/utilCex.c \
+	src/misc/util/utilColor.c \
+	src/misc/util/utilFile.c \
+	src/misc/util/utilNam.c \
+	src/misc/util/utilSignal.c \
+	src/misc/util/utilSort.c
diff --git a/abc-build/src/misc/util/utilBridge.c b/abc-build/src/misc/util/utilBridge.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/util/utilBridge.c
@@ -0,0 +1,553 @@
+/**CFile****************************************************************
+
+  FileName    [utilBridge.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName []
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: utilBridge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#if defined(LIN) || defined(LIN64)
+#include <unistd.h>
+#endif
+
+#include "aig/gia/gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define BRIDGE_TEXT_MESSAGE 999996
+
+#define BRIDGE_ABORT        5
+#define BRIDGE_PROGRESS     3
+#define BRIDGE_RESULTS      101
+#define BRIDGE_BAD_ABS      105
+//#define BRIDGE_NETLIST      106
+//#define BRIDGE_ABS_NETLIST  107
+
+#define BRIDGE_VALUE_X 0
+#define BRIDGE_VALUE_0 2
+#define BRIDGE_VALUE_1 3
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Gia_ManToBridgeVec( Gia_Man_t * p )
+{
+    Vec_Str_t * vStr;
+    Gia_Obj_t * pObj;
+    int i, uLit0, uLit1, nNodes;
+    assert( Gia_ManPoNum(p) > 0 );
+
+    // start with const1 node (number 1)
+    nNodes = 1;
+    // assign literals(!!!) to the value field
+    Gia_ManConst0(p)->Value = Abc_Var2Lit( nNodes++, 1 );
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Abc_Var2Lit( nNodes++, 0 );
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Abc_Var2Lit( nNodes++, 0 );
+
+    // write header
+    vStr = Vec_StrAlloc( 1000 );
+    Gia_AigerWriteUnsigned( vStr, Gia_ManPiNum(p) );
+    Gia_AigerWriteUnsigned( vStr, Gia_ManRegNum(p) );
+    Gia_AigerWriteUnsigned( vStr, Gia_ManAndNum(p) );
+
+    // write the nodes 
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        uLit0 = Gia_ObjFanin0Copy( pObj );
+        uLit1 = Gia_ObjFanin1Copy( pObj );
+        assert( uLit0 != uLit1 );
+        Gia_AigerWriteUnsigned( vStr, uLit0 << 1 );
+        Gia_AigerWriteUnsigned( vStr, uLit1 );
+    }
+
+    // write latch drivers
+    Gia_ManForEachRi( p, pObj, i )
+    {
+        uLit0 = Gia_ObjFanin0Copy( pObj );
+        Gia_AigerWriteUnsigned( vStr, (uLit0 << 2) | BRIDGE_VALUE_0 );
+    }
+
+    // write PO drivers
+    Gia_AigerWriteUnsigned( vStr, Gia_ManPoNum(p) );
+    Gia_ManForEachPo( p, pObj, i )
+    {
+        uLit0 = Gia_ObjFanin0Copy( pObj );
+        // complement property output!!!
+        Gia_AigerWriteUnsigned( vStr, Abc_LitNot(uLit0) );
+    }
+    return vStr;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_CreateHeader( FILE * pFile, int Type, int Size, unsigned char * pBuffer )
+{
+    fprintf( pFile, "%.6d", Type );
+    fprintf( pFile, " " );
+    fprintf( pFile, "%.16d", Size );
+    fprintf( pFile, " " );
+#if !defined(LIN) && !defined(LIN64)
+    {
+    int RetValue;
+    RetValue = fwrite( pBuffer, Size, 1, pFile );
+    assert( RetValue == 1 || Size == 0);
+    fflush( pFile );
+    }
+#else
+    fflush(pFile);
+    int fd = fileno(pFile);
+
+    ssize_t bytes_written = 0;
+    while (bytes_written < Size){
+        ssize_t n = write(fd, &pBuffer[bytes_written], Size - bytes_written);
+        if (n < 0){
+            fprintf(stderr, "BridgeMode: failed to send package; aborting\n"); fflush(stderr);
+            _exit(255);
+        }
+        bytes_written += n;
+    }
+#endif
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManToBridgeText( FILE * pFile, int Size, unsigned char * pBuffer )
+{
+    Gia_CreateHeader( pFile, BRIDGE_TEXT_MESSAGE, Size, pBuffer );
+    return 1;
+}
+
+
+int Gia_ManToBridgeAbort( FILE * pFile, int Size, unsigned char * pBuffer )
+{
+    Gia_CreateHeader( pFile, BRIDGE_ABORT, Size, pBuffer );
+    return 1;
+}
+
+
+int Gia_ManToBridgeProgress( FILE * pFile, int Size, unsigned char * pBuffer )
+{
+    Gia_CreateHeader( pFile, BRIDGE_PROGRESS, Size, pBuffer );
+    return 1;
+}
+
+
+int Gia_ManToBridgeAbsNetlist( FILE * pFile, void * p, int pkg_type )
+{
+    Vec_Str_t * vBuffer;
+    vBuffer = Gia_ManToBridgeVec( (Gia_Man_t *)p );
+    Gia_CreateHeader( pFile, pkg_type, Vec_StrSize(vBuffer), (unsigned char *)Vec_StrArray(vBuffer) );
+    Vec_StrFree( vBuffer );
+    return 1;
+}
+
+
+int Gia_ManToBridgeBadAbs( FILE * pFile )
+{
+    Gia_CreateHeader( pFile, BRIDGE_BAD_ABS, 0, NULL );
+    return 1;
+}
+
+
+static int aigerNumSize( unsigned x )
+{
+    int sz = 1;
+    while (x & ~0x7f)
+    {
+        sz++;
+        x >>= 7;
+    }
+    return sz;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFromBridgeHolds( FILE * pFile, int iPoProved )
+{
+    fprintf( pFile, "%.6d", 101 /*message type = Result*/);
+    fprintf( pFile, " " );
+    fprintf( pFile, "%.16d", 3 + aigerNumSize(iPoProved) /*size in bytes*/);
+    fprintf( pFile, " " );
+
+    fputc( (char)BRIDGE_VALUE_1, pFile ); // true
+    fputc( (char)1, pFile ); // size of vector (Armin's encoding)
+    Gia_AigerWriteUnsignedFile( pFile, iPoProved ); // number of the property (Armin's encoding)
+    fputc( (char)0, pFile ); // no invariant
+    fflush(pFile);
+}
+void Gia_ManFromBridgeUnknown( FILE * pFile, int iPoUnknown )
+{
+    fprintf( pFile, "%.6d", 101 /*message type = Result*/);
+    fprintf( pFile, " " );
+    fprintf( pFile, "%.16d", 2 + aigerNumSize(iPoUnknown) /*size in bytes*/);
+    fprintf( pFile, " " );
+
+    fputc( (char)BRIDGE_VALUE_X, pFile ); // undef
+    fputc( (char)1, pFile ); // size of vector (Armin's encoding)
+    Gia_AigerWriteUnsignedFile( pFile, iPoUnknown ); // number of the property (Armin's encoding)
+    fflush(pFile);
+}
+void Gia_ManFromBridgeCex( FILE * pFile, Abc_Cex_t * pCex )
+{
+    int i, f, iBit;//, RetValue;
+    Vec_Str_t * vStr = Vec_StrAlloc( 1000 );
+    Vec_StrPush( vStr, (char)BRIDGE_VALUE_0 ); // false
+    Vec_StrPush( vStr, (char)1 ); // size of vector (Armin's encoding)
+    Gia_AigerWriteUnsigned( vStr, pCex->iPo ); // number of the property (Armin's encoding)
+    Vec_StrPush( vStr, (char)1 ); // size of vector (Armin's encoding)
+    Gia_AigerWriteUnsigned( vStr, pCex->iFrame ); // depth
+
+    Gia_AigerWriteUnsigned( vStr, 1 ); // concrete
+    Gia_AigerWriteUnsigned( vStr, pCex->iFrame + 1 ); // number of frames (1 more than depth)
+    iBit = pCex->nRegs;
+    for ( f = 0; f <= pCex->iFrame; f++ )
+    {
+        Gia_AigerWriteUnsigned( vStr, pCex->nPis ); // num of inputs
+        for ( i = 0; i < pCex->nPis; i++, iBit++ )
+            Vec_StrPush( vStr, (char)(Abc_InfoHasBit(pCex->pData, iBit) ? BRIDGE_VALUE_1:BRIDGE_VALUE_0) ); // value
+    }
+    assert( iBit == pCex->nBits );
+    Vec_StrPush( vStr, (char)1 ); // the number of frames (for a concrete counter-example)
+    Gia_AigerWriteUnsigned( vStr, pCex->nRegs ); // num of flops
+    for ( i = 0; i < pCex->nRegs; i++ )
+        Vec_StrPush( vStr, (char)BRIDGE_VALUE_0 ); // always zero!!!
+//    RetValue = fwrite( Vec_StrArray(vStr), Vec_StrSize(vStr), 1, pFile );
+    Gia_CreateHeader(pFile, 101/*type=Result*/, Vec_StrSize(vStr), (unsigned char*)Vec_StrArray(vStr));
+
+    Vec_StrFree( vStr );
+    fflush(pFile);
+}
+int Gia_ManToBridgeResult( FILE * pFile, int Result, Abc_Cex_t * pCex, int iPoProved )
+{
+    if ( Result == 0 ) // sat
+        Gia_ManFromBridgeCex( pFile, pCex );
+    else if ( Result == 1 ) // unsat
+        Gia_ManFromBridgeHolds( pFile, iPoProved );
+    else if ( Result == -1 ) // undef
+        Gia_ManFromBridgeUnknown( pFile, iPoProved );
+    else assert( 0 );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t *  Gia_ManFromBridgeReadBody( int Size, unsigned char * pBuffer, Vec_Int_t ** pvInits )
+{
+    int fHash = 0;
+    Vec_Int_t * vLits, * vInits;
+    Gia_Man_t * p = NULL;
+    unsigned char * pBufferPivot, * pBufferEnd = pBuffer + Size;
+    int i, nInputs, nFlops, nGates, nProps;
+    unsigned iFan0, iFan1;
+
+    nInputs = Gia_AigerReadUnsigned( &pBuffer );
+    nFlops  = Gia_AigerReadUnsigned( &pBuffer );
+    nGates  = Gia_AigerReadUnsigned( &pBuffer );
+
+    vLits = Vec_IntAlloc( 1000 );
+    Vec_IntPush( vLits, -999 );
+    Vec_IntPush( vLits,  1 );
+
+    // start the AIG package
+    p = Gia_ManStart( nInputs + nFlops * 2 + nGates + 1 + 1 ); // PI+FO+FI+AND+PO+1
+    p->pName = Abc_UtilStrsav( "temp" );
+
+    // create PIs
+    for ( i = 0; i < nInputs; i++ )
+        Vec_IntPush( vLits, Gia_ManAppendCi( p ) );
+
+    // create flop outputs
+    for ( i = 0; i < nFlops; i++ )
+        Vec_IntPush( vLits, Gia_ManAppendCi( p ) );
+
+    // create nodes
+    if ( fHash )
+        Gia_ManHashAlloc( p );
+    for ( i = 0; i < nGates; i++ )
+    {
+        iFan0 = Gia_AigerReadUnsigned( &pBuffer );
+        iFan1 = Gia_AigerReadUnsigned( &pBuffer );
+        assert( !(iFan0 & 1) );
+        iFan0 >>= 1;
+        iFan0 = Abc_LitNotCond( Vec_IntEntry(vLits, iFan0 >> 1), iFan0 & 1 );
+        iFan1 = Abc_LitNotCond( Vec_IntEntry(vLits, iFan1 >> 1), iFan1 & 1 );
+        if ( fHash )
+            Vec_IntPush( vLits, Gia_ManHashAnd(p, iFan0, iFan1) );
+        else
+            Vec_IntPush( vLits, Gia_ManAppendAnd(p, iFan0, iFan1) );
+
+    }
+    if ( fHash )
+        Gia_ManHashStop( p );
+
+    // remember where flops begin
+    pBufferPivot = pBuffer;
+    // scroll through flops
+    for ( i = 0; i < nFlops; i++ )
+        Gia_AigerReadUnsigned( &pBuffer );
+
+    // create POs
+    nProps = Gia_AigerReadUnsigned( &pBuffer );
+//    assert( nProps == 1 );
+    for ( i = 0; i < nProps; i++ )
+    {
+        iFan0 = Gia_AigerReadUnsigned( &pBuffer );
+        iFan0 = Abc_LitNotCond( Vec_IntEntry(vLits, iFan0 >> 1), iFan0 & 1 );
+        // complement property output!!!
+        Gia_ManAppendCo( p, Abc_LitNot(iFan0) );
+    }
+    // make sure the end of buffer is reached
+    assert( pBufferEnd == pBuffer );
+
+    // resetting to flops
+    pBuffer = pBufferPivot;
+    vInits = Vec_IntAlloc( nFlops );
+    for ( i = 0; i < nFlops; i++ )
+    {
+        iFan0 = Gia_AigerReadUnsigned( &pBuffer );
+        assert( (iFan0 & 3) == BRIDGE_VALUE_0 );
+        Vec_IntPush( vInits, iFan0 & 3 ); // 0 = X value; 1 = not used; 2 = false; 3 = true
+        iFan0 >>= 2;
+        iFan0 = Abc_LitNotCond( Vec_IntEntry(vLits, iFan0 >> 1), iFan0 & 1 );
+        Gia_ManAppendCo( p, iFan0 );
+    }
+    Gia_ManSetRegNum( p, nFlops );
+    Vec_IntFree( vLits );
+
+    // remove wholes in the node list
+    if ( fHash )
+    {
+        Gia_Man_t * pTemp;
+        p = Gia_ManCleanup( pTemp = p );
+        Gia_ManStop( pTemp );
+    }
+
+    // return
+    if ( pvInits )
+        *pvInits = vInits;
+    else
+        Vec_IntFree( vInits );
+    return p;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManFromBridgeReadPackage( FILE * pFile, int * pType, int * pSize, unsigned char ** ppBuffer )
+{
+    char Temp[24];
+    int RetValue;
+    RetValue = fread( Temp, 24, 1, pFile );
+    if ( RetValue != 1 )
+    {
+        printf( "Gia_ManFromBridgeReadPackage();  Error 1: Something is wrong!\n" );
+        return 0;
+    }
+    Temp[6] = 0;
+    Temp[23]= 0;
+
+    *pType = atoi( Temp );
+    *pSize = atoi( Temp + 7 );
+
+    *ppBuffer = ABC_ALLOC( unsigned char, *pSize );
+    RetValue = fread( *ppBuffer, *pSize, 1, pFile );
+    if ( RetValue != 1 && *pSize != 0 )
+    {
+        ABC_FREE( *ppBuffer );
+        printf( "Gia_ManFromBridgeReadPackage();  Error 2: Something is wrong!\n" );
+        return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFromBridge( FILE * pFile, Vec_Int_t ** pvInit )
+{
+    unsigned char * pBuffer;
+    int Type, Size, RetValue;
+    Gia_Man_t * p = NULL;
+
+    RetValue = Gia_ManFromBridgeReadPackage( pFile, &Type, &Size, &pBuffer );
+    ABC_FREE( pBuffer );
+    if ( !RetValue )
+        return NULL;
+
+    RetValue = Gia_ManFromBridgeReadPackage( pFile, &Type, &Size, &pBuffer );
+    if ( !RetValue )
+        return NULL;
+
+    p = Gia_ManFromBridgeReadBody( Size, pBuffer, pvInit );
+    ABC_FREE( pBuffer );
+    if ( p == NULL )
+        return NULL;
+
+    RetValue = Gia_ManFromBridgeReadPackage( pFile, &Type, &Size, &pBuffer );
+    ABC_FREE( pBuffer );
+    if ( !RetValue )
+        return NULL;
+
+    return p;
+}
+
+/*
+    {
+        extern void Gia_ManFromBridgeTest( char * pFileName );
+        Gia_ManFromBridgeTest( "C:\\_projects\\abc\\_TEST\\bug\\65\\par.dump" );
+    }
+*/
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManToBridgeAbsNetlistTest( char * pFileName, Gia_Man_t * p, int msg_type )
+{
+    FILE * pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open output file \"%s\".\n", pFileName );
+        return;
+    }
+    Gia_ManToBridgeAbsNetlist( pFile, p, msg_type );
+    fclose ( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFromBridgeTest( char * pFileName )
+{
+    Gia_Man_t * p;
+    FILE * pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open input file \"%s\".\n", pFileName );
+        return;
+    }
+
+    p = Gia_ManFromBridge( pFile, NULL );
+    fclose ( pFile );
+
+    Gia_ManPrintStats( p, NULL );
+    Gia_AigerWrite( p, "temp.aig", 0, 0 );
+
+    Gia_ManToBridgeAbsNetlistTest( "par_.dump", p, BRIDGE_ABS_NETLIST );
+    Gia_ManStop( p );
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/misc/util/utilCex.c b/abc-build/src/misc/util/utilCex.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/util/utilCex.c
@@ -0,0 +1,563 @@
+/**CFile****************************************************************
+
+  FileName    [utilCex.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Handling counter-examples.]
+
+  Synopsis    [Handling counter-examples.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Feburary 13, 2011.]
+
+  Revision    [$Id: utilCex.c,v 1.00 2011/02/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+#include "utilCex.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Abc_CexAlloc( int nRegs, int nRealPis, int nFrames )
+{
+    Abc_Cex_t * pCex;
+    int nWords = Abc_BitWordNum( nRegs + nRealPis * nFrames );
+    pCex = (Abc_Cex_t *)ABC_ALLOC( char, sizeof(Abc_Cex_t) + sizeof(unsigned) * nWords );
+    memset( pCex, 0, sizeof(Abc_Cex_t) + sizeof(unsigned) * nWords );
+    pCex->nRegs  = nRegs;
+    pCex->nPis   = nRealPis;
+    pCex->nBits  = nRegs + nRealPis * nFrames;
+    return pCex;
+}
+Abc_Cex_t * Abc_CexAllocFull( int nRegs, int nRealPis, int nFrames )
+{
+    Abc_Cex_t * pCex;
+    int nWords = Abc_BitWordNum( nRegs + nRealPis * nFrames );
+    pCex = (Abc_Cex_t *)ABC_ALLOC( char, sizeof(Abc_Cex_t) + sizeof(unsigned) * nWords );
+    memset( pCex, 0xFF, sizeof(Abc_Cex_t) + sizeof(unsigned) * nWords );
+    pCex->nRegs  = nRegs;
+    pCex->nPis   = nRealPis;
+    pCex->nBits  = nRegs + nRealPis * nFrames;
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Make the trivial counter-example for the trivially asserted output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Abc_CexMakeTriv( int nRegs, int nTruePis, int nTruePos, int iFrameOut )
+{
+    Abc_Cex_t * pCex;
+    int iPo, iFrame;
+    assert( nRegs > 0 );
+    iPo    = iFrameOut % nTruePos;
+    iFrame = iFrameOut / nTruePos;
+    // allocate the counter example
+    pCex = Abc_CexAlloc( nRegs, nTruePis, iFrame + 1 );
+    pCex->iPo    = iPo;
+    pCex->iFrame = iFrame;
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Abc_CexCreate( int nRegs, int nPis, int * pArray, int iFrame, int iPo, int fSkipRegs )
+{
+    Abc_Cex_t * pCex;
+    int i;
+    pCex = Abc_CexAlloc( nRegs, nPis, iFrame+1 );
+    pCex->iPo    = iPo;
+    pCex->iFrame = iFrame;
+    if ( pArray == NULL )
+        return pCex;
+    if ( fSkipRegs )
+    {
+        for ( i = nRegs; i < pCex->nBits; i++ )
+            if ( pArray[i-nRegs] )
+                Abc_InfoSetBit( pCex->pData, i );
+    }
+    else
+    {
+        for ( i = 0; i < pCex->nBits; i++ )
+            if ( pArray[i] )
+                Abc_InfoSetBit( pCex->pData, i );
+    }
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Make the trivial counter-example for the trivially asserted output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Abc_CexDup( Abc_Cex_t * p, int nRegsNew )
+{
+    Abc_Cex_t * pCex;
+    int i;
+    if ( p == (Abc_Cex_t *)(ABC_PTRINT_T)1 )
+        return p;
+    if ( nRegsNew == -1 )
+        nRegsNew = p->nRegs;
+    pCex = Abc_CexAlloc( nRegsNew, p->nPis, p->iFrame+1 );
+    pCex->iPo    = p->iPo;
+    pCex->iFrame = p->iFrame;
+    for ( i = p->nRegs; i < p->nBits; i++ )
+        if ( Abc_InfoHasBit(p->pData, i) )
+            Abc_InfoSetBit( pCex->pData, pCex->nRegs + i - p->nRegs );
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CEX from comb model.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Abc_CexDeriveFromCombModel( int * pModel, int nPis, int nRegs, int iPo )
+{
+    Abc_Cex_t * pCex;
+    int i;
+    pCex = Abc_CexAlloc( nRegs, nPis, 1 );
+    pCex->iPo = iPo;
+    pCex->iFrame = 0;
+    for ( i = 0; i < nPis; i++ )
+        if ( pModel[i] )
+            pCex->pData[i>>5] |= (1<<(i & 31));     
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CEX from comb model.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Abc_CexMerge( Abc_Cex_t * pCex, Abc_Cex_t * pPart, int iFrBeg, int iFrEnd )
+{
+    Abc_Cex_t * pNew;
+    int nFramesGain;
+    int i, f, iBit;
+
+    if ( iFrBeg < 0 )
+        { printf( "Starting frame is less than 0.\n" ); return NULL; }
+    if ( iFrEnd < 0 )
+        { printf( "Stopping frame is less than 0.\n" ); return NULL; }
+    if ( iFrBeg > pCex->iFrame )
+        { printf( "Starting frame is more than the last frame of CEX (%d).\n", pCex->iFrame ); return NULL; }
+    if ( iFrEnd > pCex->iFrame )
+        { printf( "Stopping frame is more than the last frame of CEX (%d).\n", pCex->iFrame ); return NULL; }
+    if ( iFrBeg > iFrEnd )
+        { printf( "Starting frame (%d) should be less than stopping frame (%d).\n", iFrBeg, iFrEnd ); return NULL; }
+    assert( iFrBeg >= 0 && iFrBeg <= pCex->iFrame );
+    assert( iFrEnd >= 0 && iFrEnd <= pCex->iFrame );
+    assert( iFrBeg <= iFrEnd );
+
+    assert( pCex->nPis == pPart->nPis );
+    assert( iFrEnd - iFrBeg + pPart->iPo >= pPart->iFrame );
+
+    nFramesGain = iFrEnd - iFrBeg + pPart->iPo - pPart->iFrame;
+    pNew = Abc_CexAlloc( pCex->nRegs, pCex->nPis, pCex->iFrame + 1 - nFramesGain );
+    pNew->iPo    = pCex->iPo;
+    pNew->iFrame = pCex->iFrame - nFramesGain;
+
+    for ( iBit = 0; iBit < pCex->nRegs; iBit++ )
+        if ( Abc_InfoHasBit(pCex->pData, iBit) )
+            Abc_InfoSetBit( pNew->pData, iBit );
+    for ( f = 0; f < iFrBeg; f++ )
+        for ( i = 0; i < pCex->nPis; i++, iBit++ )
+            if ( Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i) )
+                Abc_InfoSetBit( pNew->pData, iBit );
+    for ( f = 0; f < pPart->iFrame; f++ )
+        for ( i = 0; i < pCex->nPis; i++, iBit++ )
+            if ( Abc_InfoHasBit(pPart->pData, pPart->nRegs + pCex->nPis * f + i) )
+                Abc_InfoSetBit( pNew->pData, iBit );
+    for ( f = iFrEnd; f <= pCex->iFrame; f++ )
+        for ( i = 0; i < pCex->nPis; i++, iBit++ )
+            if ( Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i) )
+                Abc_InfoSetBit( pNew->pData, iBit );
+    assert( iBit == pNew->nBits );
+
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints out the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_CexPrintStats( Abc_Cex_t * p )
+{
+    int k, Counter = 0;
+    if ( p == NULL )
+    {
+        printf( "The counter example is NULL.\n" );
+        return;
+    }
+    if ( p == (Abc_Cex_t *)(ABC_PTRINT_T)1 )
+    {
+        printf( "The counter example is present but not available (pointer has value \"1\").\n" );
+        return;
+    }
+    for ( k = 0; k < p->nBits; k++ )
+        Counter += Abc_InfoHasBit(p->pData, k);
+    printf( "CEX: Po =%4d  Frame =%4d  FF = %d  PI = %d  Bit =%8d  1s =%8d (%5.2f %%)\n", 
+        p->iPo, p->iFrame, p->nRegs, p->nPis, p->nBits, 
+        Counter, 100.0 * Counter / (p->nBits - p->nRegs) );
+}
+void Abc_CexPrintStatsInputs( Abc_Cex_t * p, int nInputs )
+{
+    int k, Counter = 0, Counter2 = 0;
+    if ( p == NULL )
+    {
+        printf( "The counter example is NULL.\n" );
+        return;
+    }
+    if ( p == (Abc_Cex_t *)(ABC_PTRINT_T)1 )
+    {
+        printf( "The counter example is present but not available (pointer has value \"1\").\n" );
+        return;
+    }
+    for ( k = 0; k < p->nBits; k++ )
+    {
+        Counter += Abc_InfoHasBit(p->pData, k);
+        if ( (k - p->nRegs) % p->nPis < nInputs )
+            Counter2 += Abc_InfoHasBit(p->pData, k);
+    }
+    printf( "CEX: Po =%4d  Frame =%4d  FF = %d  PI = %d  Bit =%8d  1s =%8d (%5.2f %%) 1sIn =%8d (%5.2f %%)\n", 
+        p->iPo, p->iFrame, p->nRegs, p->nPis, p->nBits, 
+        Counter,  100.0 * Counter  / (p->nBits - p->nRegs), 
+        Counter2, 100.0 * Counter2 / (p->nBits - p->nRegs - (p->iFrame + 1) * (p->nPis - nInputs)) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints out the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_CexPrint( Abc_Cex_t * p )
+{
+    int i, f, k;
+    if ( p == NULL )
+    {
+        printf( "The counter example is NULL.\n" );
+        return;
+    }
+    if ( p == (Abc_Cex_t *)(ABC_PTRINT_T)1 )
+    {
+        printf( "The counter example is present but not available (pointer has value \"1\").\n" );
+        return;
+    }
+    Abc_CexPrintStats( p );
+    printf( "State    : " );
+    for ( k = 0; k < p->nRegs; k++ )
+        printf( "%d", Abc_InfoHasBit(p->pData, k) );
+    printf( "\n" );
+    for ( f = 0; f <= p->iFrame; f++ )
+    {
+        printf( "Frame %3d : ", f );
+        for ( i = 0; i < p->nPis; i++ )
+            printf( "%d", Abc_InfoHasBit(p->pData, k++) );
+        printf( "\n" );
+    }
+    assert( k == p->nBits );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_CexFreeP( Abc_Cex_t ** p )
+{
+    if ( *p == NULL )
+        return;
+    if ( *p == (Abc_Cex_t *)(ABC_PTRINT_T)1 )
+        *p = NULL;
+    else
+        ABC_FREE( *p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_CexFree( Abc_Cex_t * p )
+{
+    if ( p == (Abc_Cex_t *)(ABC_PTRINT_T)1 )
+        return;
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transform CEX after phase abstraction with nFrames frames.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Abc_CexTransformPhase( Abc_Cex_t * p, int nPisOld, int nPosOld, int nRegsOld )
+{
+    Abc_Cex_t * pCex;
+    int nFrames = p->nPis / nPisOld;
+    int nPosNew = nPosOld * nFrames;
+    assert( p->nPis % nPisOld == 0 );
+    assert( p->iPo < nPosNew );
+    pCex = Abc_CexDup( p, nRegsOld );
+    pCex->nPis   = nPisOld;
+    pCex->iPo    = -1;
+    pCex->iFrame = (p->iFrame + 1) * nFrames - 1;
+    pCex->nBits  = p->nBits;
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transform CEX after phase temporal decomposition with nFrames frames.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Abc_CexTransformTempor( Abc_Cex_t * p, int nPisOld, int nPosOld, int nRegsOld )
+{
+    Abc_Cex_t * pCex;
+    int i, k, iBit = nRegsOld, nFrames = p->nPis / nPisOld - 1;
+    assert( p->iFrame > 0 ); // otherwise tempor did not properly check for failures in the prefix
+    assert( p->nPis % nPisOld == 0 );
+    pCex = Abc_CexAlloc( nRegsOld, nPisOld, nFrames + p->iFrame + 1 );
+    pCex->iPo    = p->iPo;
+    pCex->iFrame = nFrames + p->iFrame;
+    for ( i = 0; i < nFrames; i++ )
+        for ( k = 0; k < nPisOld; k++, iBit++ )
+            if ( Abc_InfoHasBit(p->pData, p->nRegs + (i+1)*nPisOld + k) )
+                Abc_InfoSetBit( pCex->pData, iBit );
+    for ( i = 0; i <= p->iFrame; i++ )
+        for ( k = 0; k < nPisOld; k++, iBit++ )
+            if ( Abc_InfoHasBit(p->pData, p->nRegs + i*p->nPis + k) )
+                Abc_InfoSetBit( pCex->pData, iBit );
+    assert( iBit == pCex->nBits );
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transform CEX after "logic; undc; st; zero".]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Abc_CexTransformUndc( Abc_Cex_t * p, char * pInit )
+{
+    Abc_Cex_t * pCex;
+    int nFlops = strlen(pInit);
+    int i, f, iBit, iAddPi = 0, nAddPis = 0;
+    // count how many flops got a new PI
+    for ( i = 0; i < nFlops; i++ )
+        nAddPis += (int)(pInit[i] == 'x');
+    // create new CEX
+    pCex = Abc_CexAlloc( nFlops, p->nPis - nAddPis, p->iFrame + 1 );
+    pCex->iPo    = p->iPo;
+    pCex->iFrame = p->iFrame;
+    for ( iBit = 0; iBit < nFlops; iBit++ )
+    {
+        if ( pInit[iBit] == '1' || (pInit[iBit] == 'x' && Abc_InfoHasBit(p->pData, p->nRegs + p->nPis - nAddPis + iAddPi)) )
+            Abc_InfoSetBit( pCex->pData, iBit );
+        iAddPi += (int)(pInit[iBit] == 'x');
+    }
+    assert( iAddPi == nAddPis );
+    // add timeframes
+    for ( f = 0; f <= p->iFrame; f++ )
+        for ( i = 0; i < pCex->nPis; i++, iBit++ )
+            if ( Abc_InfoHasBit(p->pData, p->nRegs + p->nPis * f + i) )
+                Abc_InfoSetBit( pCex->pData, iBit );
+    assert( iBit == pCex->nBits );
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives permuted CEX using permutation of its inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Abc_CexPermute( Abc_Cex_t * p, Vec_Int_t * vMapOld2New )
+{
+    Abc_Cex_t * pCex;
+    int i, iNew;
+    assert( Vec_IntSize(vMapOld2New) == p->nPis );
+    pCex = Abc_CexAlloc( p->nRegs, p->nPis, p->iFrame+1 );
+    pCex->iPo    = p->iPo;
+    pCex->iFrame = p->iFrame;
+    for ( i = p->nRegs; i < p->nBits; i++ )
+        if ( Abc_InfoHasBit(p->pData, i) )
+        {
+            iNew = p->nRegs + p->nPis * ((i - p->nRegs) / p->nPis) + Vec_IntEntry( vMapOld2New, (i - p->nRegs) % p->nPis );
+            Abc_InfoSetBit( pCex->pData, iNew );
+        }
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives permuted CEX using two canonical permutations.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Abc_CexPermuteTwo( Abc_Cex_t * p, Vec_Int_t * vPermOld, Vec_Int_t * vPermNew )
+{
+    Abc_Cex_t * pCex;
+    Vec_Int_t * vPerm;
+    int i, eOld, eNew;
+    assert( Vec_IntSize(vPermOld) == p->nPis );
+    assert( Vec_IntSize(vPermNew) == p->nPis );
+    vPerm = Vec_IntStartFull( p->nPis );
+    Vec_IntForEachEntryTwo( vPermOld, vPermNew, eOld, eNew, i )
+        Vec_IntWriteEntry( vPerm, eOld, eNew );
+    pCex = Abc_CexPermute( p, vPerm );
+    Vec_IntFree( vPerm );
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of 1s in the CEX.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_CexOnes32( unsigned i )
+{
+    i = i - ((i >> 1) & 0x55555555);
+    i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
+    i = ((i + (i >> 4)) & 0x0F0F0F0F);
+    return (i*(0x01010101))>>24;
+}
+int Abc_CexCountOnes( Abc_Cex_t * p )
+{
+    int nWords = Abc_BitWordNum( p->nBits );
+    int i, Count = 0;
+    for ( i = 0; i < nWords; i++ )
+        Count += Abc_CexOnes32( p->pData[i] );
+    return Count;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/util/utilCex.h b/abc-build/src/misc/util/utilCex.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/util/utilCex.h
@@ -0,0 +1,84 @@
+/**CFile****************************************************************
+
+  FileName    [utilCex.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Handling sequential counter-examples.]
+
+  Synopsis    [Handling sequential counter-examples.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Feburary 13, 2011.]
+
+  Revision    [$Id: utilCex.h,v 1.00 2011/02/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__util__utilCex_h
+#define ABC__misc__util__utilCex_h
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// sequential counter-example
+typedef struct Abc_Cex_t_ Abc_Cex_t;
+struct Abc_Cex_t_
+{
+    int              iPo;       // the zero-based number of PO, for which verification failed
+    int              iFrame;    // the zero-based number of the time-frame, for which verificaiton failed
+    int              nRegs;     // the number of registers in the miter 
+    int              nPis;      // the number of primary inputs in the miter
+    int              nBits;     // the number of words of bit data used
+    unsigned         pData[0];  // the cex bit data (the number of bits: nRegs + (iFrame+1) * nPis)
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== utilCex.c ===========================================================*/
+extern Abc_Cex_t *   Abc_CexAlloc( int nRegs, int nTruePis, int nFrames );
+extern Abc_Cex_t *   Abc_CexAllocFull( int nRegs, int nTruePis, int nFrames );
+extern Abc_Cex_t *   Abc_CexMakeTriv( int nRegs, int nTruePis, int nTruePos, int iFrameOut );
+extern Abc_Cex_t *   Abc_CexCreate( int nRegs, int nTruePis, int * pArray, int iFrame, int iPo, int fSkipRegs );
+extern Abc_Cex_t *   Abc_CexDup( Abc_Cex_t * p, int nRegsNew );
+extern Abc_Cex_t *   Abc_CexDeriveFromCombModel( int * pModel, int nPis, int nRegs, int iPo );
+extern Abc_Cex_t *   Abc_CexMerge( Abc_Cex_t * pCex, Abc_Cex_t * pPart, int iFrBeg, int iFrEnd );
+extern void          Abc_CexPrintStats( Abc_Cex_t * p );
+extern void          Abc_CexPrintStatsInputs( Abc_Cex_t * p, int nInputs );
+extern void          Abc_CexPrint( Abc_Cex_t * p );
+extern void          Abc_CexFreeP( Abc_Cex_t ** p );
+extern void          Abc_CexFree( Abc_Cex_t * p );
+extern Abc_Cex_t *   Abc_CexTransformPhase( Abc_Cex_t * p, int nPisOld, int nPosOld, int nRegsOld );
+extern Abc_Cex_t *   Abc_CexTransformTempor( Abc_Cex_t * p, int nPisOld, int nPosOld, int nRegsOld );
+extern Abc_Cex_t *   Abc_CexTransformUndc( Abc_Cex_t * p, char * pInit );
+extern Abc_Cex_t *   Abc_CexPermute( Abc_Cex_t * p, Vec_Int_t * vMapOld2New );
+extern Abc_Cex_t *   Abc_CexPermuteTwo( Abc_Cex_t * p, Vec_Int_t * vPermOld, Vec_Int_t * vPermNew );
+extern int           Abc_CexCountOnes( Abc_Cex_t * p );
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/misc/util/utilColor.c b/abc-build/src/misc/util/utilColor.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/util/utilColor.c
@@ -0,0 +1,124 @@
+/**CFile****************************************************************
+
+  FileName    [utilColor.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Handling counter-examples.]
+
+  Synopsis    [Handling counter-examples.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Feburary 13, 2011.]
+
+  Revision    [$Id: utilColor.c,v 1.00 2011/02/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc/util/abc_global.h"
+
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_ColorTest()
+{
+#ifdef WIN32
+    int x, y;
+    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+    printf( "Background     00   01   02   03   04   05   06   07   08   09   10   11   12   13   14   15\n" );
+    for ( y = 0; y < 16; y++ )
+    {
+        printf( "Foreground %02d", y );
+        for ( x = 0; x < 16; x++ )
+        {
+            printf( " " );
+            SetConsoleTextAttribute( hConsole, (WORD)(16 * x + y) );
+            printf( " Hi " );
+            SetConsoleTextAttribute( hConsole, 7 );
+        }
+        printf( "\n" );
+    }
+#else
+/*
+  fg[Default]   = '[0m';    fg[DefaultBold] = '[1m'
+
+  fg[Black]     = '[0;30m'; fg[DarkGray]    = '[1;30m'
+  fg[Blue]      = '[0;34m'; fg[LightBlue]   = '[1;34m'
+  fg[Green]     = '[0;32m'; fg[LightGreen]  = '[1;32m'
+  fg[Cyan]      = '[0;36m'; fg[LightCyan]   = '[1;36m'
+  fg[Red]       = '[0;31m'; fg[LightRed]    = '[1;31m'
+  fg[Purple]    = '[0;35m'; fg[LightPurple] = '[1;35m'
+  fg[Brown]     = '[0;33m'; fg[Yellow]      = '[1;33m'
+  fg[LightGray] = '[0;37m'; fg[White]       = '[1;37m'
+
+  bg[Black]     = '[0;40m'; hi[Underlined]  = '[4m'
+  bg[Blue]      = '[0;44m'; hi[Blinking]    = '[5m'
+  bg[Green]     = '[0;42m'; hi[Inverted]    = '[7m'
+  bg[Cyan]      = '[0;46m'; hi[Concealed]   = '[8m'
+  bg[Red]       = '[0;41m'
+  bg[Purple]    = '[0;45m'
+  bg[Brown]     = '[0;43m'
+  bg[LightGray] = '[0;47m'
+*/
+    int x, y;
+    printf( "Background       " );
+    for ( x = 0; x < 8; x++ )
+        printf( "  [1;4%dm", x );
+    printf( "\n" );
+    for ( y = 0; y < 2; y++ )
+    {
+        printf( "Foreground [%dm   ", y );
+        for ( x = 0; x < 8; x++ )
+            printf( "  \033[%d;3%dm\033[%dm  Hi  \033[0m", y&1, y>>1, x );
+        printf( "\n" );
+    }
+    for ( y = 0; y < 16; y++ )
+    {
+        printf( "Foreground [%d;3%dm", y&1, y>>1 );
+        for ( x = 0; x < 8; x++ )
+            printf( "  \033[%d;3%dm\033[1;4%dm  Hi  \033[0m", y&1, y>>1, x );
+        printf( "\n" );
+    }
+    printf( "\033[4mUnderlined\033[0m\n" );
+    printf( "\033[5mBlinking  \033[0m\n" );
+    printf( "\033[7mInverted  \033[0m\n" );
+    printf( "\033[8mConcealed \033[0m\n" );
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/util/utilFile.c b/abc-build/src/misc/util/utilFile.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/util/utilFile.c
@@ -0,0 +1,221 @@
+/**CFile****************************************************************
+
+  FileName    [utilFile.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Temporary file utilities.]
+
+  Synopsis    [Temporary file utilities.]
+
+  Author      [Niklas Een]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 29, 2010.]
+
+  Revision    [$Id: utilFile.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#if defined(_MSC_VER) || defined(__MINGW32__)
+#include <Windows.h>
+#include <process.h>
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "abc_global.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static ABC_UINT64_T realTimeAbs()  // -- absolute time in nano-seconds
+{
+#if defined(_MSC_VER)
+    LARGE_INTEGER f, t;
+    double realTime_freq;
+    int ok;
+
+    ok = QueryPerformanceFrequency(&f); assert(ok);
+    realTime_freq = 1.0 / (__int64)(((ABC_UINT64_T)f.LowPart) | ((ABC_UINT64_T)f.HighPart << 32));
+
+    ok = QueryPerformanceCounter(&t); assert(ok);
+    return (ABC_UINT64_T)(__int64)(((__int64)(((ABC_UINT64_T)t.LowPart | ((ABC_UINT64_T)t.HighPart << 32))) * realTime_freq * 1000000000));
+#else
+    return 0;
+#endif
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Opens a temporary file.]
+
+  Description [Opens a temporary file with given prefix and returns file 
+  descriptor (-1 on failure) and a string containing the name of the file 
+  (to be freed by caller).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int tmpFile(const char* prefix, const char* suffix, char** out_name)
+{
+#if defined(_MSC_VER) || defined(__MINGW32__)
+    int i, fd;
+    *out_name = (char*)malloc(strlen(prefix) + strlen(suffix) + 27);
+    for (i = 0; i < 10; i++){
+        sprintf(*out_name, "%s%I64X%d%s", prefix, realTimeAbs(), _getpid(), suffix);
+        fd = _open(*out_name, O_CREAT | O_EXCL | O_BINARY | O_RDWR, _S_IREAD | _S_IWRITE);
+        if (fd == -1){
+            free(*out_name);
+            *out_name = NULL;
+        }
+        return fd;
+    }
+    assert(0);  // -- could not open temporary file
+    return 0;
+#else
+    int fd;
+    *out_name = (char*)malloc(strlen(prefix) + strlen(suffix) + 7);
+    assert(*out_name != NULL);
+    sprintf(*out_name, "%sXXXXXX", prefix);
+    fd = mkstemp(*out_name);
+    if (fd == -1){
+        free(*out_name);
+        *out_name = NULL;
+    }else{
+        // Kludge:
+        close(fd);
+        unlink(*out_name);
+        strcat(*out_name, suffix);
+        fd = open(*out_name, O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE);
+        if (fd == -1){
+            free(*out_name);
+            *out_name = NULL;
+        }
+    }
+    return fd;
+#endif
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+int main(int argc, char** argv)
+{
+    char* tmp_filename;
+    int   fd = tmpFile("__abctmp_", &tmp_filename);
+    FILE* out = fdopen(fd, "wb");
+
+    fprintf(out, "This file contains important information.\n");
+    fclose(out);
+
+    printf("Created: %s\n", tmp_filename);
+    free(tmp_filename);
+
+    return 0;
+}
+*/
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char* vnsprintf(const char* format, va_list args)
+{
+    unsigned n;
+    char*    ret;
+    va_list  args_copy;
+
+    static FILE* dummy_file = NULL;
+    if (!dummy_file)
+    {
+#if !defined(_MSC_VER) && !defined(__MINGW32)
+        dummy_file = fopen("/dev/null", "wb");
+#else
+        dummy_file = fopen("NUL", "wb");
+#endif
+    }
+
+#if defined(__va_copy)
+    __va_copy(args_copy, args);
+#else
+  #if defined(va_copy)
+    va_copy(args_copy, args);
+  #else
+    args_copy = args;
+  #endif
+#endif
+    n = vfprintf(dummy_file, format, args);
+    ret = ABC_ALLOC( char, n + 1 );
+    ret[n] = (char)255;
+    args = args_copy;
+    vsprintf(ret, format, args);
+#if !defined(__va_copy) && defined(va_copy)
+    va_end(args_copy);
+#endif
+    assert(ret[n] == 0);
+    return ret;
+}
+
+char* nsprintf(const char* format, ...)
+{
+    char* ret;
+    va_list args;
+    va_start(args, format);
+    ret = vnsprintf(format, args);
+    va_end(args);
+    return ret;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/util/utilMem.c b/abc-build/src/misc/util/utilMem.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/util/utilMem.c
@@ -0,0 +1,341 @@
+/**CFile****************************************************************
+
+  FileName    [utilMem.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Memory recycling utilities.]
+
+  Synopsis    [Memory recycling utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: utilMem.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "abc_global.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+
+typedef struct Vec_Mem_t_       Vec_Mem_t;
+struct Vec_Mem_t_ 
+{
+    int              nCap;
+    int              nSize;
+    void **          pArray;
+};
+
+void * s_vAllocs = NULL;
+void * s_vFrees  = NULL;
+int    s_fInterrupt = 0;
+
+#define ABC_MEM_ALLOC(type, num)	 ((type *) malloc(sizeof(type) * (num)))
+#define ABC_MEM_CALLOC(type, num)	 ((type *) calloc((num), sizeof(type)))
+#define ABC_MEM_FALLOC(type, num)	 ((type *) memset(malloc(sizeof(type) * (num)), 0xff, sizeof(type) * (num)))
+#define ABC_MEM_FREE(obj)		     ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#define ABC_MEM_REALLOC(type, obj, num)	\
+        ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
+	     ((type *) malloc(sizeof(type) * (num))))
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Mem_t * Vec_MemAlloc( int nCap )
+{
+    Vec_Mem_t * p;
+    p = ABC_MEM_ALLOC( Vec_Mem_t, 1 );
+    if ( nCap > 0 && nCap < 8 )
+        nCap = 8;
+    p->nSize  = 0;
+    p->nCap   = nCap;
+    p->pArray = p->nCap? ABC_MEM_ALLOC( void *, p->nCap ) : NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_MemFree( Vec_Mem_t * p )
+{
+    ABC_MEM_FREE( p->pArray );
+    ABC_MEM_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the vector to the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_MemGrow( Vec_Mem_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pArray = ABC_MEM_REALLOC( void *, p->pArray, nCapMin ); 
+    p->nCap   = nCapMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_MemPush( Vec_Mem_t * p, void * Entry )
+{
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Vec_MemGrow( p, 16 );
+        else
+            Vec_MemGrow( p, 2 * p->nCap );
+    }
+    p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting the entries by their integer value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Vec_MemSort( Vec_Mem_t * p, int (*Vec_MemSortCompare)() )
+{
+    if ( p->nSize < 2 )
+        return;
+    qsort( (void *)p->pArray, p->nSize, sizeof(void *), 
+            (int (*)(const void *, const void *)) Vec_MemSortCompare );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Remembers an allocated pointer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Util_MemRecAlloc( void * pMem )
+{
+    if ( s_vAllocs )
+        Vec_MemPush( (Vec_Mem_t *)s_vAllocs, pMem );
+    return pMem;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Remembers a deallocated pointer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Util_MemRecFree( void * pMem )
+{
+    if ( s_vFrees )
+        Vec_MemPush( (Vec_Mem_t *)s_vFrees, pMem );
+    return pMem;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure used for sorting the nodes in decreasing order of levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Util_ComparePointers( void ** pp1, void ** pp2 )
+{
+    if ( *pp1 < *pp2 )
+        return -1;
+    if ( *pp1 > *pp2 ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds entries that do not appear in both lists.]
+
+  Description [Assumes that the vectors are sorted in the increasing order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Mem_t * Vec_MemTwoMerge( Vec_Mem_t * vArr1, Vec_Mem_t * vArr2 )
+{
+    Vec_Mem_t * vArr = Vec_MemAlloc( vArr1->nSize + vArr2->nSize ); 
+    void ** pBeg  = vArr->pArray;
+    void ** pBeg1 = vArr1->pArray;
+    void ** pBeg2 = vArr2->pArray;
+    void ** pEnd1 = vArr1->pArray + vArr1->nSize;
+    void ** pEnd2 = vArr2->pArray + vArr2->nSize;
+    while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+    {
+        if ( *pBeg1 == *pBeg2 )
+            pBeg1++, pBeg2++;
+        else if ( *pBeg1 < *pBeg2 )
+        {
+            free( *pBeg1 );
+            *pBeg++ = *pBeg1++;
+        }
+        else 
+            assert( 0 );
+//            *pBeg++ = *pBeg2++;
+    }
+    while ( pBeg1 < pEnd1 )
+        *pBeg++ = *pBeg1++;
+//    while ( pBeg2 < pEnd2 )
+//        *pBeg++ = *pBeg2++;
+    assert( pBeg2 >= pEnd2 );
+    vArr->nSize = pBeg - vArr->pArray;
+    assert( vArr->nSize <= vArr->nCap );
+    assert( vArr->nSize >= vArr1->nSize );
+    assert( vArr->nSize >= vArr2->nSize );
+    return vArr;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the accumulated memory.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Util_MemRecRecycle()
+{
+    Vec_Mem_t * vMerge;
+    assert( s_vAllocs == NULL );
+    assert( s_vFrees == NULL );
+    Vec_MemSort( (Vec_Mem_t *)s_vAllocs, (int (*)())Util_ComparePointers );
+    Vec_MemSort( (Vec_Mem_t *)s_vFrees, (int (*)())Util_ComparePointers );
+    vMerge = (Vec_Mem_t *)Vec_MemTwoMerge( (Vec_Mem_t *)s_vAllocs, (Vec_Mem_t *)s_vFrees );
+    Vec_MemFree( vMerge );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts memory structures.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Util_MemRecStart()
+{
+    assert( s_vAllocs == NULL && s_vFrees == NULL );
+    s_vAllocs = Vec_MemAlloc( 1000 );
+    s_vFrees = Vec_MemAlloc( 1000 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Quits memory structures.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Util_MemRecQuit()
+{
+    assert( s_vAllocs != NULL && s_vFrees != NULL );
+    Vec_MemFree( (Vec_Mem_t *)s_vAllocs );
+    Vec_MemFree( (Vec_Mem_t *)s_vFrees );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts memory structures.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Util_MemRecIsSet()
+{
+    return s_vAllocs != NULL && s_vFrees != NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/util/utilMem.h b/abc-build/src/misc/util/utilMem.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/util/utilMem.h
@@ -0,0 +1,73 @@
+/**CFile****************************************************************
+
+  FileName    [utilInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Memory recycling utilities.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: utilInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__util__utilMem_h
+#define ABC__misc__util__utilMem_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+extern void * s_vAllocs;   // storage of allocated pointers
+extern void * s_vFrees;    // storage of deallocated pointers
+extern int s_fInterrupt;   // set to 1 when it is time to backout
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== utilMem.c ==========================================================*/
+extern void *       Util_MemRecAlloc( void * pMem );
+extern void *       Util_MemRecFree( void * pMem );
+extern void         Util_MemStart();
+extern void         Util_MemQuit();
+extern void         Util_MemRecycle();
+extern int          Util_MemRecIsSet();
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/util/utilNam.c b/abc-build/src/misc/util/utilNam.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/util/utilNam.c
@@ -0,0 +1,500 @@
+/**CFile****************************************************************
+
+  FileName    [utilNam.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Manager for character strings.]
+
+  Synopsis    [Manager for character strings.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: utilNam.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "abc_global.h"
+#include "misc/vec/vec.h"
+#include "utilNam.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// this package maps non-empty character strings into natural numbers and back
+
+// name manager
+struct Abc_Nam_t_
+{
+    // info storage for names
+    int              nStore;       // the size of allocated storage
+    int              iHandle;      // the current free handle
+    char *           pStore;       // storage for name objects
+    // internal number mappings
+    Vec_Int_t *      vInt2Handle;  // mapping integers into handles
+    Vec_Int_t *      vInt2Next;    // mapping integers into nexts
+    // hash table for names
+    int *            pBins;        // the hash table bins 
+    int              nBins;        // the number of bins 
+    // manager recycling
+    int              nRefs;        // reference counter for the manager
+};
+
+static inline char * Abc_NamHandleToStr( Abc_Nam_t * p, int h )        { return (char *)(p->pStore + h);                         }
+static inline int    Abc_NamIntToHandle( Abc_Nam_t * p, int i )        { return Vec_IntEntry(p->vInt2Handle, i);                 }
+static inline char * Abc_NamIntToStr( Abc_Nam_t * p, int i )           { return Abc_NamHandleToStr(p, Abc_NamIntToHandle(p,i));  }
+static inline int    Abc_NamIntToNext( Abc_Nam_t * p, int i )          { return Vec_IntEntry(p->vInt2Next, i);                   }
+static inline int *  Abc_NamIntToNextP( Abc_Nam_t * p, int i )         { return Vec_IntEntryP(p->vInt2Next, i);                  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Nam_t * Abc_NamStart( int nObjs, int nAveSize )
+{
+    Abc_Nam_t * p;
+    if ( nObjs == 0 )
+        nObjs = 16;
+    p = ABC_CALLOC( Abc_Nam_t, 1 );
+    p->nStore      = ((nObjs * (nAveSize + 1) + 16) / 4) * 4;
+    p->pStore      = ABC_ALLOC( char, p->nStore );
+    p->nBins       = Abc_PrimeCudd( nObjs );
+    p->pBins       = ABC_CALLOC( int, p->nBins );
+    // 0th object is unused
+    p->vInt2Handle = Vec_IntAlloc( nObjs );  Vec_IntPush( p->vInt2Handle, -1 );
+    p->vInt2Next   = Vec_IntAlloc( nObjs );  Vec_IntPush( p->vInt2Next,   -1 );
+    p->iHandle     = 4;
+    memset( p->pStore, 0, 4 );
+//Abc_Print( 1, "Starting nam with %d bins.\n", p->nBins );
+    // start reference counting
+    p->nRefs       = 1;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NamStop( Abc_Nam_t * p )
+{
+//Abc_Print( 1, "Starting nam with %d bins.\n", p->nBins );
+    Vec_IntFree( p->vInt2Handle );
+    Vec_IntFree( p->vInt2Next );
+    ABC_FREE( p->pStore );
+    ABC_FREE( p->pBins );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NamPrint( Abc_Nam_t * p )
+{
+    int h, i;
+    Vec_IntForEachEntryStart( p->vInt2Handle, h, i, 1 )
+        Abc_Print( 1, "%d=\n%s\n", i, Abc_NamHandleToStr(p, h) );
+//    Abc_Print( 1, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [References the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Nam_t * Abc_NamRef( Abc_Nam_t * p )
+{
+    p->nRefs++;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NamDeref( Abc_Nam_t * p )
+{
+    if ( p == NULL )
+        return;
+    if ( --p->nRefs == 0 )
+        Abc_NamStop( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of used entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NamObjNumMax( Abc_Nam_t * p )
+{
+    return Vec_IntSize(p->vInt2Handle);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports memory usage of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NamMemUsed( Abc_Nam_t * p )
+{
+    if ( p == NULL )
+        return 0;
+    return sizeof(Abc_Nam_t) + p->iHandle + sizeof(int) * p->nBins + 
+        sizeof(int) * (p->vInt2Handle->nSize + p->vInt2Next->nSize);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports memory usage of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NamMemAlloc( Abc_Nam_t * p )
+{
+    if ( p == NULL )
+        return 0;
+    return sizeof(Abc_Nam_t) + p->nStore + sizeof(int) * p->nBins + 
+        sizeof(int) * (p->vInt2Handle->nCap + p->vInt2Next->nCap);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash value of the C-string.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NamStrHash( const char * pStr, int nTableSize )
+{
+    static int s_FPrimes[128] = { 
+        1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 
+        1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 
+        2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 
+        2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 
+        3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 
+        3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 
+        4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 
+        4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 
+        5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 
+        6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 
+        6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 
+        7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 
+        8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+    };
+    unsigned i, uHash;
+    for ( uHash = 0, i = 0; pStr[i]; i++ )
+        if ( i & 1 ) 
+            uHash *= pStr[i] * s_FPrimes[i & 0x7F];
+        else
+            uHash ^= pStr[i] * s_FPrimes[i & 0x7F];
+    return uHash % nTableSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns place where this string is, or should be.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int * Abc_NamStrHashFind( Abc_Nam_t * p, const char * pStr )
+{
+    char * pThis;
+    int * pPlace = (int *)(p->pBins + Abc_NamStrHash( pStr, p->nBins ));
+    assert( *pStr );
+    for ( pThis = (*pPlace)? Abc_NamIntToStr(p, *pPlace) : NULL; 
+          pThis;    pPlace = Abc_NamIntToNextP(p, *pPlace), 
+          pThis = (*pPlace)? Abc_NamIntToStr(p, *pPlace) : NULL )
+              if ( !strcmp( pStr, pThis ) )
+                  break;
+    return pPlace;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NamStrHashResize( Abc_Nam_t * p )
+{
+    Vec_Int_t * vInt2HandleOld;
+    char * pThis;
+    int * piPlace, * pBinsOld, iHandleOld, i;//, clk = Abc_Clock();
+    assert( p->pBins != NULL );
+//    Abc_Print( 1, "Resizing names manager hash table from %6d to %6d. ", p->nBins, Abc_PrimeCudd( 3 * p->nBins ) );
+    // replace the table
+    pBinsOld = p->pBins;
+    p->nBins = Abc_PrimeCudd( 3 * p->nBins ); 
+    p->pBins = ABC_CALLOC( int, p->nBins );
+    // replace the handles array
+    vInt2HandleOld = p->vInt2Handle;
+    p->vInt2Handle = Vec_IntAlloc( 2 * Vec_IntSize(vInt2HandleOld) ); 
+    Vec_IntPush( p->vInt2Handle, -1 );
+    Vec_IntClear( p->vInt2Next );    Vec_IntPush( p->vInt2Next, -1 );
+    // rehash the entries from the old table
+    Vec_IntForEachEntryStart( vInt2HandleOld, iHandleOld, i, 1 )
+    {
+        pThis   = Abc_NamHandleToStr( p, iHandleOld );
+        piPlace = Abc_NamStrHashFind( p, pThis );
+        assert( *piPlace == 0 );
+        *piPlace = Vec_IntSize( p->vInt2Handle );
+        assert( Vec_IntSize( p->vInt2Handle ) == i );
+        Vec_IntPush( p->vInt2Handle, iHandleOld );
+        Vec_IntPush( p->vInt2Next,   0 );
+    }
+    Vec_IntFree( vInt2HandleOld );
+    ABC_FREE( pBinsOld );
+//    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the index of the string in the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NamStrFind( Abc_Nam_t * p, char * pStr )
+{
+    return *Abc_NamStrHashFind( p, pStr );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds or adds the given name to storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NamStrFindOrAdd( Abc_Nam_t * p, char * pStr, int * pfFound )
+{
+    int i, iHandleNew;
+    int *piPlace;
+    if ( !(pStr[0] != '\\' || pStr[strlen(pStr)-1] == ' ') )
+    {
+        for ( i = strlen(pStr) - 1; i >= 0; i-- )
+            if ( *pStr == ' ' )
+                break;
+        assert( i < (int)strlen(pStr) );
+    }
+    piPlace = Abc_NamStrHashFind( p, pStr );
+    if ( *piPlace )
+    {
+        if ( pfFound )
+            *pfFound = 1;
+        return *piPlace;
+    }
+    if ( pfFound )
+        *pfFound = 0;
+    iHandleNew = p->iHandle + strlen(pStr) + 1;
+    while ( p->nStore < iHandleNew )
+    {
+        p->nStore *= 3;
+        p->nStore /= 2;
+        p->pStore  = ABC_REALLOC( char, p->pStore, p->nStore );
+    }
+    assert( p->nStore >= iHandleNew );
+    // create new handle
+    *piPlace = Vec_IntSize( p->vInt2Handle );
+    strcpy( Abc_NamHandleToStr( p, p->iHandle ), pStr );
+    Vec_IntPush( p->vInt2Handle, p->iHandle );
+    Vec_IntPush( p->vInt2Next, 0 );
+    p->iHandle = iHandleNew;
+    // extend the hash table
+    if ( Vec_IntSize(p->vInt2Handle) > 2 * p->nBins )
+        Abc_NamStrHashResize( p );
+    return Vec_IntSize(p->vInt2Handle) - 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns name from name ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_NamStr( Abc_Nam_t * p, int NameId )
+{
+    return NameId? Abc_NamIntToStr(p, NameId) : NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [For each ID of the first manager, gives ID of the second one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NamComputeIdMap( Abc_Nam_t * p1, Abc_Nam_t * p2 )
+{
+    Vec_Int_t * vMap;
+    char * pThis;
+    int * piPlace, iHandle1, i;
+    if ( p1 == p2 )
+        return Vec_IntStartNatural( Abc_NamObjNumMax(p1) );
+    vMap = Vec_IntStart( Abc_NamObjNumMax(p1) );
+    Vec_IntForEachEntryStart( p1->vInt2Handle, iHandle1, i, 1 )
+    {
+        pThis = Abc_NamHandleToStr( p1, iHandle1 );
+        piPlace = Abc_NamStrHashFind( p2, pThis );
+        Vec_IntWriteEntry( vMap, i, *piPlace );
+//        Abc_Print( 1, "%d->%d  ", i, *piPlace );
+    }
+    return vMap;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of common names in the array.]
+
+  Description [The array contains name IDs in the first manager.
+  The procedure returns the number of entries that correspond to names
+  in the first manager that appear in the second manager.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NamReportCommon( Vec_Int_t * vNameIds1, Abc_Nam_t * p1, Abc_Nam_t * p2 )
+{
+    int i, Entry, Counter = 0;
+    Vec_IntForEachEntry( vNameIds1, Entry, i )
+    {
+        assert( Entry > 0 && Entry < Abc_NamObjNumMax(p1) );
+        Counter += (Abc_NamStrFind(p2, Abc_NamStr(p1, Entry)) > 0);
+//        if ( Abc_NamStrFind(p2, Abc_NamStr(p1, Entry)) == 0 )
+//            Abc_Print( 1, "unique name <%s>\n", Abc_NamStr(p1, Entry) );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the name that appears in p1 does not appear in p2.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_NamReportUnique( Vec_Int_t * vNameIds1, Abc_Nam_t * p1, Abc_Nam_t * p2 )
+{
+    int i, Entry;
+    Vec_IntForEachEntry( vNameIds1, Entry, i )
+    {
+        assert( Entry > 0 && Entry < Abc_NamObjNumMax(p1) );
+        if ( Abc_NamStrFind(p2, Abc_NamStr(p1, Entry)) == 0 )
+            return Abc_NamStr(p1, Entry);
+    }
+    return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/util/utilNam.h b/abc-build/src/misc/util/utilNam.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/util/utilNam.h
@@ -0,0 +1,76 @@
+/**CFile****************************************************************
+
+  FileName    [utilNam.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Memory recycling utilities.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: utilNam.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__util__utilNam_h
+#define ABC__misc__util__utilNam_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Abc_Nam_t_           Abc_Nam_t;
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define Abc_NamManForEachObj( p, pStr, i )  \
+    for ( i = 1; (i < Abc_NamObjNumMax(p)) && ((pStr) = Abc_NamStr(p, i)); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== utilNam.c ===============================================================*/
+extern Abc_Nam_t *     Abc_NamStart( int nObjs, int nAveSize );
+extern void            Abc_NamStop( Abc_Nam_t * p );
+extern void            Abc_NamPrint( Abc_Nam_t * p );
+extern Abc_Nam_t *     Abc_NamRef( Abc_Nam_t * p );
+extern void            Abc_NamDeref( Abc_Nam_t * p );
+extern int             Abc_NamObjNumMax( Abc_Nam_t * p );
+extern int             Abc_NamMemUsed( Abc_Nam_t * p );
+extern int             Abc_NamMemAlloc( Abc_Nam_t * p );
+extern int             Abc_NamStrFind( Abc_Nam_t * p, char * pStr );
+extern int             Abc_NamStrFindOrAdd( Abc_Nam_t * p, char * pStr, int * pfFound );
+extern char *          Abc_NamStr( Abc_Nam_t * p, int id );
+extern Vec_Int_t *     Abc_NamComputeIdMap( Abc_Nam_t * p1, Abc_Nam_t * p2 );
+extern int             Abc_NamReportCommon( Vec_Int_t * vNameIds1, Abc_Nam_t * p1, Abc_Nam_t * p2 );
+extern char *          Abc_NamReportUnique( Vec_Int_t * vNameIds1, Abc_Nam_t * p1, Abc_Nam_t * p2 );
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/util/utilSignal.c b/abc-build/src/misc/util/utilSignal.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/util/utilSignal.c
@@ -0,0 +1,72 @@
+/**CFile****************************************************************
+
+  FileName    [utilSignal.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName []
+
+  Synopsis    []
+
+  Author      [Baruch Sterin]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2011.]
+
+  Revision    [$Id: utilSignal.c,v 1.00 2011/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "abc_global.h"
+#include "utilSignal.h"
+
+#ifdef _MSC_VER
+#define unlink _unlink
+#else
+#include <unistd.h>
+#endif
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+#ifndef ABC_PYTHON_EMBED
+
+int Util_SignalSystem(const char* cmd)
+{
+    return system(cmd);
+}
+
+int tmpFile(const char* prefix, const char* suffix, char** out_name);
+
+int Util_SignalTmpFile(const char* prefix, const char* suffix, char** out_name)
+{
+    return tmpFile(prefix, suffix, out_name);
+}
+
+void Util_SignalTmpFileRemove(const char* fname, int fLeave)
+{
+    if (! fLeave)
+    {
+        unlink(fname);
+    }
+}
+
+#endif /* ABC_PYTHON_EMBED */
+
+ABC_NAMESPACE_IMPL_END
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/misc/util/utilSignal.h b/abc-build/src/misc/util/utilSignal.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/util/utilSignal.h
@@ -0,0 +1,58 @@
+/**CFile****************************************************************
+
+  FileName    [utilSignal.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Signal handling utilities.]
+
+  Synopsis    [Signal handling utilities.]
+
+  Author      [Baruch Sterin]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2011.]
+
+  Revision    [$Id: utilSignal.h,v 1.00 2011/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__util__utilSignal_h
+#define ABC__misc__util__utilSignal_h
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== utilSignal.c ==========================================================*/
+
+extern int       Util_SignalTmpFile(const char* prefix, const char* suffix, char** out_name);
+extern void      Util_SignalTmpFileRemove(const char* fname, int fLeave);
+extern int       Util_SignalSystem(const char* cmd);
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/misc/util/utilSort.c b/abc-build/src/misc/util/utilSort.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/util/utilSort.c
@@ -0,0 +1,789 @@
+/**CFile****************************************************************
+
+  FileName    [utilSort.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Merge sort with user-specified cost.]
+
+  Synopsis    [Merge sort with user-specified cost.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Feburary 13, 2011.]
+
+  Revision    [$Id: utilSort.c,v 1.00 2011/02/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "abc_global.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Merging two lists of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SortMerge( int * p1Beg, int * p1End, int * p2Beg, int * p2End, int * pOut )
+{
+    int nEntries = (p1End - p1Beg) + (p2End - p2Beg);
+    int * pOutBeg = pOut;
+    while ( p1Beg < p1End && p2Beg < p2End )
+    {
+        if ( *p1Beg == *p2Beg )
+            *pOut++ = *p1Beg++, *pOut++ = *p2Beg++; 
+        else if ( *p1Beg < *p2Beg )
+            *pOut++ = *p1Beg++; 
+        else // if ( *p1Beg > *p2Beg )
+            *pOut++ = *p2Beg++; 
+    }
+    while ( p1Beg < p1End )
+        *pOut++ = *p1Beg++; 
+    while ( p2Beg < p2End )
+        *pOut++ = *p2Beg++;
+    assert( pOut - pOutBeg == nEntries );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursive sorting.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_Sort_rec( int * pInBeg, int * pInEnd, int * pOutBeg )
+{
+    int nSize = pInEnd - pInBeg;
+    assert( nSize > 0 );
+    if ( nSize == 1 )
+        return;
+    if ( nSize == 2 )
+    {
+         if ( pInBeg[0] > pInBeg[1] )
+         {
+             pInBeg[0] ^= pInBeg[1];
+             pInBeg[1] ^= pInBeg[0];
+             pInBeg[0] ^= pInBeg[1];
+         }
+    }
+    else if ( nSize < 8 )
+    {
+        int temp, i, j, best_i;
+        for ( i = 0; i < nSize-1; i++ )
+        {
+            best_i = i;
+            for ( j = i+1; j < nSize; j++ )
+                if ( pInBeg[j] < pInBeg[best_i] )
+                    best_i = j;
+            temp = pInBeg[i]; 
+            pInBeg[i] = pInBeg[best_i]; 
+            pInBeg[best_i] = temp;
+        }
+    }
+    else
+    {
+        Abc_Sort_rec( pInBeg, pInBeg + nSize/2, pOutBeg );
+        Abc_Sort_rec( pInBeg + nSize/2, pInEnd, pOutBeg + nSize/2 );
+        Abc_SortMerge( pInBeg, pInBeg + nSize/2, pInBeg + nSize/2, pInEnd, pOutBeg );
+        memcpy( pInBeg, pOutBeg, sizeof(int) * nSize );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the sorted array of integers.]
+
+  Description [This procedure is about 10% faster than qsort().]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MergeSort( int * pInput, int nSize )
+{
+    int * pOutput;
+    if ( nSize < 2 )
+        return;
+    pOutput = (int *) malloc( sizeof(int) * nSize );
+    Abc_Sort_rec( pInput, pInput + nSize, pOutput );
+    free( pOutput );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Merging two lists of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MergeSortCostMerge( int * p1Beg, int * p1End, int * p2Beg, int * p2End, int * pOut )
+{
+    int nEntries = (p1End - p1Beg) + (p2End - p2Beg);
+    int * pOutBeg = pOut;
+    while ( p1Beg < p1End && p2Beg < p2End )
+    {
+        if ( p1Beg[1] == p2Beg[1] )
+            *pOut++ = *p1Beg++, *pOut++ = *p1Beg++, *pOut++ = *p2Beg++, *pOut++ = *p2Beg++; 
+        else if ( p1Beg[1] < p2Beg[1] )
+            *pOut++ = *p1Beg++, *pOut++ = *p1Beg++; 
+        else // if ( p1Beg[1] > p2Beg[1] )
+            *pOut++ = *p2Beg++, *pOut++ = *p2Beg++; 
+    }
+    while ( p1Beg < p1End )
+        *pOut++ = *p1Beg++, *pOut++ = *p1Beg++; 
+    while ( p2Beg < p2End )
+        *pOut++ = *p2Beg++, *pOut++ = *p2Beg++;
+    assert( pOut - pOutBeg == nEntries );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursive sorting.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MergeSortCost_rec( int * pInBeg, int * pInEnd, int * pOutBeg )
+{
+    int nSize = (pInEnd - pInBeg)/2;
+    assert( nSize > 0 );
+    if ( nSize == 1 )
+        return;
+    if ( nSize == 2 )
+    {
+         if ( pInBeg[1] > pInBeg[3] )
+         {
+             pInBeg[1] ^= pInBeg[3];
+             pInBeg[3] ^= pInBeg[1];
+             pInBeg[1] ^= pInBeg[3];
+             pInBeg[0] ^= pInBeg[2];
+             pInBeg[2] ^= pInBeg[0];
+             pInBeg[0] ^= pInBeg[2];
+         }
+    }
+    else if ( nSize < 8 )
+    {
+        int temp, i, j, best_i;
+        for ( i = 0; i < nSize-1; i++ )
+        {
+            best_i = i;
+            for ( j = i+1; j < nSize; j++ )
+                if ( pInBeg[2*j+1] < pInBeg[2*best_i+1] )
+                    best_i = j;
+            temp = pInBeg[2*i]; 
+            pInBeg[2*i] = pInBeg[2*best_i]; 
+            pInBeg[2*best_i] = temp;
+            temp = pInBeg[2*i+1]; 
+            pInBeg[2*i+1] = pInBeg[2*best_i+1]; 
+            pInBeg[2*best_i+1] = temp;
+        }
+    }
+    else
+    {
+        Abc_MergeSortCost_rec( pInBeg, pInBeg + 2*(nSize/2), pOutBeg );
+        Abc_MergeSortCost_rec( pInBeg + 2*(nSize/2), pInEnd, pOutBeg + 2*(nSize/2) );
+        Abc_MergeSortCostMerge( pInBeg, pInBeg + 2*(nSize/2), pInBeg + 2*(nSize/2), pInEnd, pOutBeg );
+        memcpy( pInBeg, pOutBeg, sizeof(int) * 2 * nSize );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting procedure.]
+
+  Description [Returns permutation for the non-decreasing order of costs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Abc_MergeSortCost( int * pCosts, int nSize )
+{
+    int i, * pResult, * pInput, * pOutput;
+    pResult = (int *) calloc( sizeof(int), nSize );
+    if ( nSize < 2 )
+        return pResult;
+    pInput  = (int *) malloc( sizeof(int) * 2 * nSize );
+    pOutput = (int *) malloc( sizeof(int) * 2 * nSize );
+    for ( i = 0; i < nSize; i++ )
+        pInput[2*i] = i, pInput[2*i+1] = pCosts[i];
+    Abc_MergeSortCost_rec( pInput, pInput + 2*nSize, pOutput );
+    for ( i = 0; i < nSize; i++ )
+        pResult[i] = pInput[2*i];
+    free( pOutput );
+    free( pInput );
+    return pResult;
+}
+
+
+// this implementation uses 3x less memory but is 30% slower due to cache misses
+
+#if 0  
+
+/**Function*************************************************************
+
+  Synopsis    [Merging two lists of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MergeSortCostMerge( int * p1Beg, int * p1End, int * p2Beg, int * p2End, int * pOut, int * pCost )
+{
+    int nEntries = (p1End - p1Beg) + (p2End - p2Beg);
+    int * pOutBeg = pOut;
+    while ( p1Beg < p1End && p2Beg < p2End )
+    {
+        if ( pCost[*p1Beg] == pCost[*p2Beg] )
+            *pOut++ = *p1Beg++, *pOut++ = *p2Beg++; 
+        else if ( pCost[*p1Beg] < pCost[*p2Beg] )
+            *pOut++ = *p1Beg++; 
+        else // if ( pCost[*p1Beg] > pCost[*p2Beg] )
+            *pOut++ = *p2Beg++; 
+    }
+    while ( p1Beg < p1End )
+        *pOut++ = *p1Beg++; 
+    while ( p2Beg < p2End )
+        *pOut++ = *p2Beg++;
+    assert( pOut - pOutBeg == nEntries );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursive sorting.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MergeSortCost_rec( int * pInBeg, int * pInEnd, int * pOutBeg, int * pCost )
+{
+    int nSize = pInEnd - pInBeg;
+    assert( nSize > 0 );
+    if ( nSize == 1 )
+        return;
+    if ( nSize == 2 )
+    {
+         if ( pCost[pInBeg[0]] > pCost[pInBeg[1]] )
+         {
+             pInBeg[0] ^= pInBeg[1];
+             pInBeg[1] ^= pInBeg[0];
+             pInBeg[0] ^= pInBeg[1];
+         }
+    }
+    else if ( nSize < 8 )
+    {
+        int temp, i, j, best_i;
+        for ( i = 0; i < nSize-1; i++ )
+        {
+            best_i = i;
+            for ( j = i+1; j < nSize; j++ )
+                if ( pCost[pInBeg[j]] < pCost[pInBeg[best_i]] )
+                    best_i = j;
+            temp = pInBeg[i]; 
+            pInBeg[i] = pInBeg[best_i]; 
+            pInBeg[best_i] = temp;
+        }
+    }
+    else
+    {
+        Abc_MergeSortCost_rec( pInBeg, pInBeg + nSize/2, pOutBeg, pCost );
+        Abc_MergeSortCost_rec( pInBeg + nSize/2, pInEnd, pOutBeg + nSize/2, pCost );
+        Abc_MergeSortCostMerge( pInBeg, pInBeg + nSize/2, pInBeg + nSize/2, pInEnd, pOutBeg, pCost );
+        memcpy( pInBeg, pOutBeg, sizeof(int) * nSize );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting procedure.]
+
+  Description [Returns permutation for the non-decreasing order of costs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Abc_MergeSortCost( int * pCosts, int nSize )
+{
+    int i, * pInput, * pOutput;
+    pInput = (int *) malloc( sizeof(int) * nSize );
+    for ( i = 0; i < nSize; i++ )
+        pInput[i] = i;
+    if ( nSize < 2 )
+        return pInput;
+    pOutput = (int *) malloc( sizeof(int) * nSize );
+    Abc_MergeSortCost_rec( pInput, pInput + nSize, pOutput, pCosts );
+    free( pOutput );
+    return pInput;
+}
+
+#endif
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_SortNumCompare( int * pNum1, int * pNum2 )
+{
+    return *pNum1 - *pNum2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Testing the sorting procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_SortTest()
+{
+    int fUseNew = 0;
+    int i, nSize = 50000000;
+    int * pArray = (int *)malloc( sizeof(int) * nSize );
+    int * pPerm;
+    abctime clk;
+    // generate numbers
+    srand( 1000 );
+    for ( i = 0; i < nSize; i++ )
+        pArray[i] = rand();
+
+    // try sorting
+    if ( fUseNew )
+    {
+        int fUseCost = 1;
+        if ( fUseCost )
+        {
+            clk = Abc_Clock();
+            pPerm = Abc_MergeSortCost( pArray, nSize );
+            Abc_PrintTime( 1, "New sort", Abc_Clock() - clk );
+            // check
+            for ( i = 1; i < nSize; i++ )
+                assert( pArray[pPerm[i-1]] <= pArray[pPerm[i]] );
+            free( pPerm );
+        }
+        else
+        {
+            clk = Abc_Clock();
+            Abc_MergeSort( pArray, nSize );
+            Abc_PrintTime( 1, "New sort", Abc_Clock() - clk );
+            // check
+            for ( i = 1; i < nSize; i++ )
+                assert( pArray[i-1] <= pArray[i] );
+        }
+    }
+    else
+    {
+        clk = Abc_Clock();
+        qsort( (void *)pArray, nSize, sizeof(int), (int (*)(const void *, const void *)) Abc_SortNumCompare );
+        Abc_PrintTime( 1, "Old sort", Abc_Clock() - clk );
+        // check
+        for ( i = 1; i < nSize; i++ )
+            assert( pArray[i-1] <= pArray[i] );
+    }
+
+    free( pArray );
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [QuickSort algorithm as implemented by qsort().]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_QuickSort1CompareInc( word * p1, word * p2 )
+{
+    if ( (unsigned)(*p1) < (unsigned)(*p2) )
+        return -1;
+    if ( (unsigned)(*p1) > (unsigned)(*p2) )
+        return 1;
+    return 0;
+}
+int Abc_QuickSort1CompareDec( word * p1, word * p2 )
+{
+    if ( (unsigned)(*p1) > (unsigned)(*p2) )
+        return -1;
+    if ( (unsigned)(*p1) < (unsigned)(*p2) )
+        return 1;
+    return 0;
+}
+void Abc_QuickSort1( word * pData, int nSize, int fDecrease )
+{
+    int i, fVerify = 0;
+    if ( fDecrease )
+    {
+        qsort( (void *)pData, nSize, sizeof(word), (int (*)(const void *, const void *))Abc_QuickSort1CompareDec );
+        if ( fVerify )
+            for ( i = 1; i < nSize; i++ )
+                assert( (unsigned)pData[i-1] >= (unsigned)pData[i] );
+    }
+    else
+    {
+        qsort( (void *)pData, nSize, sizeof(word), (int (*)(const void *, const void *))Abc_QuickSort1CompareInc );
+        if ( fVerify )
+            for ( i = 1; i < nSize; i++ )
+                assert( (unsigned)pData[i-1] <= (unsigned)pData[i] );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [QuickSort algorithm based on 2/3-way partitioning.]
+
+  Description [This code is based on the online presentation 
+  "QuickSort is Optimal" by Robert Sedgewick and Jon Bentley.
+  http://www.sorting-algorithms.com/static/QuicksortIsOptimal.pdf 
+
+  The first 32-bits of the input data contain values to be compared. 
+  The last 32-bits contain the user's data. When sorting is finished, 
+  the 64-bit words are ordered in the increasing order of their value ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_SelectSortInc( word * pData, int nSize )
+{
+    int i, j, best_i;
+    for ( i = 0; i < nSize-1; i++ )
+    {
+        best_i = i;
+        for ( j = i+1; j < nSize; j++ )
+            if ( (unsigned)pData[j] < (unsigned)pData[best_i] )
+                best_i = j;
+        ABC_SWAP( word, pData[i], pData[best_i] );
+    }
+}
+static inline void Abc_SelectSortDec( word * pData, int nSize )
+{
+    int i, j, best_i;
+    for ( i = 0; i < nSize-1; i++ )
+    {
+        best_i = i;
+        for ( j = i+1; j < nSize; j++ )
+            if ( (unsigned)pData[j] > (unsigned)pData[best_i] )
+                best_i = j;
+        ABC_SWAP( word, pData[i], pData[best_i] );
+    }
+}
+
+void Abc_QuickSort2Inc_rec( word * pData, int l, int r )
+{
+    word v = pData[r];
+    int i = l-1, j = r;
+    if ( l >= r )
+        return;
+    assert( l < r );
+    if ( r - l < 10 )
+    {
+        Abc_SelectSortInc( pData + l, r - l + 1 );
+        return;
+    }
+    while ( 1 )
+    {
+        while ( (unsigned)pData[++i] < (unsigned)v );
+        while ( (unsigned)v < (unsigned)pData[--j] )
+            if ( j == l )
+                break;
+        if ( i >= j )
+            break;
+        ABC_SWAP( word, pData[i], pData[j] );
+    }
+    ABC_SWAP( word, pData[i], pData[r] ); 
+    Abc_QuickSort2Inc_rec( pData, l, i-1 );
+    Abc_QuickSort2Inc_rec( pData, i+1, r );
+}
+void Abc_QuickSort2Dec_rec( word * pData, int l, int r )
+{
+    word v = pData[r];
+    int i = l-1, j = r;
+    if ( l >= r )
+        return;
+    assert( l < r );
+    if ( r - l < 10 )
+    {
+        Abc_SelectSortDec( pData + l, r - l + 1 );
+        return;
+    }
+    while ( 1 )
+    {
+        while ( (unsigned)pData[++i] > (unsigned)v );
+        while ( (unsigned)v > (unsigned)pData[--j] )
+            if ( j == l )
+                break;
+        if ( i >= j )
+            break;
+        ABC_SWAP( word, pData[i], pData[j] );
+    }
+    ABC_SWAP( word, pData[i], pData[r] ); 
+    Abc_QuickSort2Dec_rec( pData, l, i-1 );
+    Abc_QuickSort2Dec_rec( pData, i+1, r );
+}
+
+void Abc_QuickSort3Inc_rec( word * pData, int l, int r )
+{
+    word v = pData[r];
+    int k, i = l-1, j = r, p = l-1, q = r;
+    if ( l >= r )
+        return;
+    assert( l < r );
+    if ( r - l < 10 )
+    {
+        Abc_SelectSortInc( pData + l, r - l + 1 );
+        return;
+    }
+    while ( 1 )
+    {
+        while ( (unsigned)pData[++i] < (unsigned)v );
+        while ( (unsigned)v < (unsigned)pData[--j] )
+            if ( j == l )
+                break;
+        if ( i >= j )
+            break;
+        ABC_SWAP( word, pData[i], pData[j] );
+        if ( (unsigned)pData[i] == (unsigned)v ) 
+            { p++; ABC_SWAP( word, pData[p], pData[i] ); }
+        if ( (unsigned)v == (unsigned)pData[j] ) 
+            { q--; ABC_SWAP( word, pData[j], pData[q] ); }
+    }
+    ABC_SWAP( word, pData[i], pData[r] ); 
+    j = i-1; i = i+1;
+    for ( k = l; k < p; k++, j-- ) 
+        ABC_SWAP( word, pData[k], pData[j] );
+    for ( k = r-1; k > q; k--, i++ ) 
+        ABC_SWAP( word, pData[i], pData[k] );
+    Abc_QuickSort3Inc_rec( pData, l, j );
+    Abc_QuickSort3Inc_rec( pData, i, r );
+}
+void Abc_QuickSort3Dec_rec( word * pData, int l, int r )
+{
+    word v = pData[r];
+    int k, i = l-1, j = r, p = l-1, q = r;
+    if ( l >= r )
+        return;
+    assert( l < r );
+    if ( r - l < 10 )
+    {
+        Abc_SelectSortDec( pData + l, r - l + 1 );
+        return;
+    }
+    while ( 1 )
+    {
+        while ( (unsigned)pData[++i] > (unsigned)v );
+        while ( (unsigned)v > (unsigned)pData[--j] )
+            if ( j == l )
+                break;
+        if ( i >= j )
+            break;
+        ABC_SWAP( word, pData[i], pData[j] );
+        if ( (unsigned)pData[i] == (unsigned)v ) 
+            { p++; ABC_SWAP( word, pData[p], pData[i] ); }
+        if ( (unsigned)v == (unsigned)pData[j] ) 
+            { q--; ABC_SWAP( word, pData[j], pData[q] ); }
+    }
+    ABC_SWAP( word, pData[i], pData[r] ); 
+    j = i-1; i = i+1;
+    for ( k = l; k < p; k++, j-- ) 
+        ABC_SWAP( word, pData[k], pData[j] );
+    for ( k = r-1; k > q; k--, i++ ) 
+        ABC_SWAP( word, pData[i], pData[k] );
+    Abc_QuickSort3Dec_rec( pData, l, j );
+    Abc_QuickSort3Dec_rec( pData, i, r );
+}
+
+void Abc_QuickSort2( word * pData, int nSize, int fDecrease )
+{
+    int i, fVerify = 0;
+    if ( fDecrease )
+    {
+        Abc_QuickSort2Dec_rec( pData, 0, nSize - 1 );
+        if ( fVerify )
+            for ( i = 1; i < nSize; i++ )
+                assert( (unsigned)pData[i-1] >= (unsigned)pData[i] );
+    }
+    else
+    {
+        Abc_QuickSort2Inc_rec( pData, 0, nSize - 1 );
+        if ( fVerify )
+            for ( i = 1; i < nSize; i++ )
+                assert( (unsigned)pData[i-1] <= (unsigned)pData[i] );
+    }
+}
+void Abc_QuickSort3( word * pData, int nSize, int fDecrease )
+{
+    int i, fVerify = 1;
+    if ( fDecrease )
+    {
+        Abc_QuickSort2Dec_rec( pData, 0, nSize - 1 );
+        if ( fVerify )
+            for ( i = 1; i < nSize; i++ )
+                assert( (unsigned)pData[i-1] >= (unsigned)pData[i] );
+    }
+    else
+    {
+        Abc_QuickSort2Inc_rec( pData, 0, nSize - 1 );
+        if ( fVerify )
+            for ( i = 1; i < nSize; i++ )
+                assert( (unsigned)pData[i-1] <= (unsigned)pData[i] );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Wrapper around QuickSort to sort entries based on cost.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_QuickSortCostData( int * pCosts, int nSize, int fDecrease, word * pData, int * pResult )
+{
+    int i;
+    for ( i = 0; i < nSize; i++ )
+        pData[i] = ((word)i << 32) | pCosts[i];
+    Abc_QuickSort3( pData, nSize, fDecrease );
+    for ( i = 0; i < nSize; i++ )
+        pResult[i] = (int)(pData[i] >> 32);
+}
+int * Abc_QuickSortCost( int * pCosts, int nSize, int fDecrease )
+{
+    word * pData = ABC_ALLOC( word, nSize );
+    int * pResult = ABC_ALLOC( int, nSize );
+    Abc_QuickSortCostData( pCosts, nSize, fDecrease, pData, pResult );
+    ABC_FREE( pData );
+    return pResult;
+}
+
+//        extern void Abc_QuickSortTest();
+//        Abc_QuickSortTest();
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_QuickSortTest()
+{
+    int nSize = 1000000;
+    int fVerbose = 0;
+    word * pData1, * pData2;
+    int i;
+    abctime clk = Abc_Clock();
+    // generate numbers
+    pData1 = ABC_ALLOC( word, nSize );
+    pData2 = ABC_ALLOC( word, nSize );
+    srand( 1111 );
+    for ( i = 0; i < nSize; i++ )
+        pData2[i] = pData1[i] = ((word)i << 32) | rand();
+    Abc_PrintTime( 1, "Prepare ", Abc_Clock() - clk );
+    // perform sorting
+    clk = Abc_Clock();
+    Abc_QuickSort3( pData1, nSize, 1 );
+    Abc_PrintTime( 1, "Sort new", Abc_Clock() - clk );
+    // print the result
+    if ( fVerbose )
+    {
+        for ( i = 0; i < nSize; i++ )
+            printf( "(%d,%d) ", (int)(pData1[i] >> 32), (int)pData1[i] );
+        printf( "\n" );
+    }
+    // create new numbers
+    clk = Abc_Clock();
+    Abc_QuickSort1( pData2, nSize, 1 );
+    Abc_PrintTime( 1, "Sort old", Abc_Clock() - clk );
+    // print the result
+    if ( fVerbose )
+    {
+        for ( i = 0; i < nSize; i++ )
+            printf( "(%d,%d) ", (int)(pData2[i] >> 32), (int)pData2[i] );
+        printf( "\n" );
+    }
+    ABC_FREE( pData1 );
+    ABC_FREE( pData2 );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/util/utilTruth.h b/abc-build/src/misc/util/utilTruth.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/util/utilTruth.h
@@ -0,0 +1,1934 @@
+/**CFile****************************************************************
+
+  FileName    [utilTruth.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Truth table manipulation.]
+
+  Synopsis    [Truth table manipulation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 28, 2012.]
+
+  Revision    [$Id: utilTruth.h,v 1.00 2012/10/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__util__utilTruth_h
+#define ABC__misc__util__utilTruth_h
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+static word s_Truths6[6] = {
+    ABC_CONST(0xAAAAAAAAAAAAAAAA),
+    ABC_CONST(0xCCCCCCCCCCCCCCCC),
+    ABC_CONST(0xF0F0F0F0F0F0F0F0),
+    ABC_CONST(0xFF00FF00FF00FF00),
+    ABC_CONST(0xFFFF0000FFFF0000),
+    ABC_CONST(0xFFFFFFFF00000000)
+};
+
+static word s_Truths6Neg[6] = {
+    ABC_CONST(0x5555555555555555),
+    ABC_CONST(0x3333333333333333),
+    ABC_CONST(0x0F0F0F0F0F0F0F0F),
+    ABC_CONST(0x00FF00FF00FF00FF),
+    ABC_CONST(0x0000FFFF0000FFFF),
+    ABC_CONST(0x00000000FFFFFFFF)
+};
+
+static word s_PMasks[5][3] = {
+    { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) },
+    { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) },
+    { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) },
+    { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) },
+    { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) }
+};
+
+static word Ps_PMasks[5][6][3] = {
+	{ 
+        { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 0 0  
+        { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) }, // 0 1  
+        { ABC_CONST(0xA5A5A5A5A5A5A5A5), ABC_CONST(0x0A0A0A0A0A0A0A0A), ABC_CONST(0x5050505050505050) }, // 0 2 
+        { ABC_CONST(0xAA55AA55AA55AA55), ABC_CONST(0x00AA00AA00AA00AA), ABC_CONST(0x5500550055005500) }, // 0 3 
+        { ABC_CONST(0xAAAA5555AAAA5555), ABC_CONST(0x0000AAAA0000AAAA), ABC_CONST(0x5555000055550000) }, // 0 4 
+        { ABC_CONST(0xAAAAAAAA55555555), ABC_CONST(0x00000000AAAAAAAA), ABC_CONST(0x5555555500000000) }  // 0 5 
+    },
+	{ 
+        { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 1 0  
+        { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 1 1  
+        { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) }, // 1 2 
+        { ABC_CONST(0xCC33CC33CC33CC33), ABC_CONST(0x00CC00CC00CC00CC), ABC_CONST(0x3300330033003300) }, // 1 3 
+        { ABC_CONST(0xCCCC3333CCCC3333), ABC_CONST(0x0000CCCC0000CCCC), ABC_CONST(0x3333000033330000) }, // 1 4 
+        { ABC_CONST(0xCCCCCCCC33333333), ABC_CONST(0x00000000CCCCCCCC), ABC_CONST(0x3333333300000000) }  // 1 5 
+    },
+	{ 
+        { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 2 0  
+        { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 2 1  
+        { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 2 2 
+        { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) }, // 2 3 
+        { ABC_CONST(0xF0F00F0FF0F00F0F), ABC_CONST(0x0000F0F00000F0F0), ABC_CONST(0x0F0F00000F0F0000) }, // 2 4 
+        { ABC_CONST(0xF0F0F0F00F0F0F0F), ABC_CONST(0x00000000F0F0F0F0), ABC_CONST(0x0F0F0F0F00000000) }  // 2 5 
+    },
+	{ 
+        { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 3 0  
+        { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 3 1  
+        { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 3 2 
+        { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 3 3 
+        { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) }, // 3 4 
+        { ABC_CONST(0xFF00FF0000FF00FF), ABC_CONST(0x00000000FF00FF00), ABC_CONST(0x00FF00FF00000000) }  // 3 5 
+    },
+	{ 
+        { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 4 0  
+        { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 4 1  
+        { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 4 2 
+        { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 4 3 
+        { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 4 4 
+        { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) }  // 4 5 
+    }
+};
+
+// the bit count for the first 256 integer numbers
+static int Abc_TtBitCount8[256] = {
+    0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
+static inline int Abc_TtBitCount16( int i ) { return Abc_TtBitCount8[i & 0xFF] + Abc_TtBitCount8[i >> 8]; }
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+// read/write/flip i-th bit of a bit string table:
+static inline int     Abc_TtGetBit( word * p, int i )         { return (int)(p[i>>6] >> (i & 63)) & 1;        }
+static inline void    Abc_TtSetBit( word * p, int i )         { p[i>>6] |= (((word)1)<<(i & 63));             }
+static inline void    Abc_TtXorBit( word * p, int i )         { p[i>>6] ^= (((word)1)<<(i & 63));             }
+
+// read/write k-th digit d of a hexadecimal number:
+static inline int     Abc_TtGetHex( word * p, int k )         { return (int)(p[k>>4] >> ((k<<2) & 63)) & 15;  }
+static inline void    Abc_TtSetHex( word * p, int k, int d )  { p[k>>4] |= (((word)d)<<((k<<2) & 63));        }
+static inline void    Abc_TtXorHex( word * p, int k, int d )  { p[k>>4] ^= (((word)d)<<((k<<2) & 63));        }
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int  Abc_TtWordNum( int nVars )     { return nVars <= 6 ? 1 : 1 << (nVars-6); }
+static inline int  Abc_TtByteNum( int nVars )     { return nVars <= 3 ? 1 : 1 << (nVars-3); }
+static inline int  Abc_TtHexDigitNum( int nVars ) { return nVars <= 2 ? 1 : 1 << (nVars-2); }
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_TtClear( word * pOut, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        pOut[w] = 0;
+}
+static inline void Abc_TtFill( word * pOut, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        pOut[w] = ~(word)0;
+}
+static inline void Abc_TtUnit( word * pOut, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        pOut[w] = s_Truths6[0];
+}
+static inline void Abc_TtNot( word * pOut, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        pOut[w] = ~pOut[w];
+}
+static inline void Abc_TtCopy( word * pOut, word * pIn, int nWords, int fCompl )
+{
+    int w;
+    if ( fCompl )
+        for ( w = 0; w < nWords; w++ )
+            pOut[w] = ~pIn[w];
+    else
+        for ( w = 0; w < nWords; w++ )
+            pOut[w] = pIn[w];
+}
+static inline void Abc_TtAnd( word * pOut, word * pIn1, word * pIn2, int nWords, int fCompl )
+{
+    int w;
+    if ( fCompl )
+        for ( w = 0; w < nWords; w++ )
+            pOut[w] = ~(pIn1[w] & pIn2[w]);
+    else
+        for ( w = 0; w < nWords; w++ )
+            pOut[w] = pIn1[w] & pIn2[w];
+}
+static inline void Abc_TtSharp( word * pOut, word * pIn1, word * pIn2, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        pOut[w] = pIn1[w] & ~pIn2[w];
+}
+static inline void Abc_TtOr( word * pOut, word * pIn1, word * pIn2, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        pOut[w] = pIn1[w] | pIn2[w];
+}
+static inline void Abc_TtXor( word * pOut, word * pIn1, word * pIn2, int nWords, int fCompl )
+{
+    int w;
+    if ( fCompl )
+        for ( w = 0; w < nWords; w++ )
+            pOut[w] = pIn1[w] ^ ~pIn2[w];
+    else
+        for ( w = 0; w < nWords; w++ )
+            pOut[w] = pIn1[w] ^ pIn2[w];
+}
+static inline void Abc_TtMux( word * pOut, word * pCtrl, word * pIn1, word * pIn0, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        pOut[w] = (pCtrl[w] & pIn1[w]) | (~pCtrl[w] & pIn0[w]);
+}
+static inline int Abc_TtEqual( word * pIn1, word * pIn2, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        if ( pIn1[w] != pIn2[w] )
+            return 0;
+    return 1;
+}
+static inline int Abc_TtCompare( word * pIn1, word * pIn2, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        if ( pIn1[w] != pIn2[w] )
+            return (pIn1[w] < pIn2[w]) ? -1 : 1;
+    return 0;
+}
+static inline int Abc_TtCompareRev( word * pIn1, word * pIn2, int nWords )
+{
+    int w;
+    for ( w = nWords - 1; w >= 0; w-- )
+        if ( pIn1[w] != pIn2[w] )
+            return (pIn1[w] < pIn2[w]) ? -1 : 1;
+    return 0;
+}
+static inline int Abc_TtIsConst0( word * pIn1, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        if ( pIn1[w] )
+            return 0;
+    return 1;
+}
+static inline int Abc_TtIsConst1( word * pIn1, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        if ( ~pIn1[w] )
+            return 0;
+    return 1;
+}
+static inline void Abc_TtConst0( word * pIn1, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        pIn1[w] = 0;
+}
+static inline void Abc_TtConst1( word * pIn1, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        pIn1[w] = ~(word)0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute elementary truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_TtElemInit( word ** pTtElems, int nVars )
+{
+    int i, k, nWords = Abc_TtWordNum( nVars );
+    for ( i = 0; i < nVars; i++ )
+        if ( i < 6 )
+            for ( k = 0; k < nWords; k++ )
+                pTtElems[i][k] = s_Truths6[i];
+        else
+            for ( k = 0; k < nWords; k++ )
+                pTtElems[i][k] = (k & (1 << (i-6))) ? ~(word)0 : 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Abc_Tt6Cofactor0( word t, int iVar )
+{
+    assert( iVar >= 0 && iVar < 6 );
+    return (t &s_Truths6Neg[iVar]) | ((t &s_Truths6Neg[iVar]) << (1<<iVar));
+}
+static inline word Abc_Tt6Cofactor1( word t, int iVar )
+{
+    assert( iVar >= 0 && iVar < 6 );
+    return (t & s_Truths6[iVar]) | ((t & s_Truths6[iVar]) >> (1<<iVar));
+}
+
+static inline void Abc_TtCofactor0p( word * pOut, word * pIn, int nWords, int iVar )
+{
+    if ( nWords == 1 )
+        pOut[0] = ((pIn[0] & s_Truths6Neg[iVar]) << (1 << iVar)) | (pIn[0] & s_Truths6Neg[iVar]);
+	else if ( iVar <= 5 )
+	{
+		int w, shift = (1 << iVar);
+		for ( w = 0; w < nWords; w++ )
+            pOut[w] = ((pIn[w] & s_Truths6Neg[iVar]) << shift) | (pIn[w] & s_Truths6Neg[iVar]);
+	}
+	else // if ( iVar > 5 )
+	{
+        word * pLimit = pIn + nWords;
+		int i, iStep = Abc_TtWordNum(iVar);
+		for ( ; pIn < pLimit; pIn += 2*iStep, pOut += 2*iStep )
+			for ( i = 0; i < iStep; i++ )
+            {
+                pOut[i]         = pIn[i];
+                pOut[i + iStep] = pIn[i];
+            }
+	}	
+}
+static inline void Abc_TtCofactor1p( word * pOut, word * pIn, int nWords, int iVar )
+{
+    if ( nWords == 1 )
+        pOut[0] = (pIn[0] & s_Truths6[iVar]) | ((pIn[0] & s_Truths6[iVar]) >> (1 << iVar));
+	else if ( iVar <= 5 )
+	{
+		int w, shift = (1 << iVar);
+		for ( w = 0; w < nWords; w++ )
+            pOut[w] = (pIn[w] & s_Truths6[iVar]) | ((pIn[w] & s_Truths6[iVar]) >> shift);
+	}
+	else // if ( iVar > 5 )
+	{
+        word * pLimit = pIn + nWords;
+		int i, iStep = Abc_TtWordNum(iVar);
+		for ( ; pIn < pLimit; pIn += 2*iStep, pOut += 2*iStep )
+			for ( i = 0; i < iStep; i++ )
+            {
+                pOut[i]         = pIn[i + iStep];
+                pOut[i + iStep] = pIn[i + iStep];
+            }
+	}	
+}
+static inline void Abc_TtCofactor0( word * pTruth, int nWords, int iVar )
+{
+    if ( nWords == 1 )
+        pTruth[0] = ((pTruth[0] & s_Truths6Neg[iVar]) << (1 << iVar)) | (pTruth[0] & s_Truths6Neg[iVar]);
+    else if ( iVar <= 5 )
+    {
+        int w, shift = (1 << iVar);
+        for ( w = 0; w < nWords; w++ )
+            pTruth[w] = ((pTruth[w] & s_Truths6Neg[iVar]) << shift) | (pTruth[w] & s_Truths6Neg[iVar]);
+    }
+    else // if ( iVar > 5 )
+    {
+        word * pLimit = pTruth + nWords;
+        int i, iStep = Abc_TtWordNum(iVar);
+        for ( ; pTruth < pLimit; pTruth += 2*iStep )
+            for ( i = 0; i < iStep; i++ )
+                pTruth[i + iStep] = pTruth[i];
+    }
+}
+static inline void Abc_TtCofactor1( word * pTruth, int nWords, int iVar )
+{
+    if ( nWords == 1 )
+        pTruth[0] = (pTruth[0] & s_Truths6[iVar]) | ((pTruth[0] & s_Truths6[iVar]) >> (1 << iVar));
+    else if ( iVar <= 5 )
+    {
+        int w, shift = (1 << iVar);
+        for ( w = 0; w < nWords; w++ )
+            pTruth[w] = (pTruth[w] & s_Truths6[iVar]) | ((pTruth[w] & s_Truths6[iVar]) >> shift);
+    }
+    else // if ( iVar > 5 )
+    {
+        word * pLimit = pTruth + nWords;
+        int i, iStep = Abc_TtWordNum(iVar);
+        for ( ; pTruth < pLimit; pTruth += 2*iStep )
+            for ( i = 0; i < iStep; i++ )
+                pTruth[i] = pTruth[i + iStep];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks pairs of cofactors w.r.t. two variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_TtCheckEqualCofs( word * pTruth, int nWords, int iVar, int jVar, int Num1, int Num2 )
+{
+    assert( Num1 < Num2 && Num2 < 4 );
+    assert( iVar < jVar );
+    if ( nWords == 1 )
+    {
+        word Mask = s_Truths6Neg[jVar] & s_Truths6Neg[iVar];
+        int shift1 = (Num1 >> 1) * (1 << jVar) + (Num1 & 1) * (1 << iVar);
+        int shift2 = (Num2 >> 1) * (1 << jVar) + (Num2 & 1) * (1 << iVar);
+        return ((pTruth[0] >> shift1) & Mask) == ((pTruth[0] >> shift2) & Mask);
+    }
+	if ( jVar <= 5 )
+	{
+        word Mask = s_Truths6Neg[jVar] & s_Truths6Neg[iVar];
+        int shift1 = (Num1 >> 1) * (1 << jVar) + (Num1 & 1) * (1 << iVar);
+        int shift2 = (Num2 >> 1) * (1 << jVar) + (Num2 & 1) * (1 << iVar);
+		int w;
+		for ( w = 0; w < nWords; w++ )
+            if ( ((pTruth[w] >> shift1) & Mask) != ((pTruth[w] >> shift2) & Mask) )
+                return 0;
+        return 1;
+	}
+	if ( iVar <= 5 && jVar > 5 )
+	{
+        word * pLimit = pTruth + nWords;
+        int j, jStep = Abc_TtWordNum(jVar);
+		int shift1 = (Num1 & 1) * (1 << iVar);
+		int shift2 = (Num2 & 1) * (1 << iVar);
+        int Offset1 = (Num1 >> 1) * jStep;
+        int Offset2 = (Num2 >> 1) * jStep;
+		for ( ; pTruth < pLimit; pTruth += 2*jStep )
+			for ( j = 0; j < jStep; j++ )
+                if ( ((pTruth[j + Offset1] >> shift1) & s_Truths6Neg[iVar]) != ((pTruth[j + Offset2] >> shift2) & s_Truths6Neg[iVar]) )
+                    return 0;
+        return 1;
+	}
+	{
+        word * pLimit = pTruth + nWords;
+		int j, jStep = Abc_TtWordNum(jVar);
+		int i, iStep = Abc_TtWordNum(iVar);
+        int Offset1 = (Num1 >> 1) * jStep + (Num1 & 1) * iStep;
+        int Offset2 = (Num2 >> 1) * jStep + (Num2 & 1) * iStep;
+		for ( ; pTruth < pLimit; pTruth += 2*jStep )
+			for ( i = 0; i < jStep; i += 2*iStep )
+				for ( j = 0; j < iStep; j++ )
+                    if ( pTruth[Offset1 + i + j] != pTruth[Offset2 + i + j] )
+                        return 0;
+        return 1;
+	}	
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_Tt6Cof0IsConst0( word t, int iVar ) { return (t & s_Truths6Neg[iVar]) == 0;                                          }
+static inline int Abc_Tt6Cof0IsConst1( word t, int iVar ) { return (t & s_Truths6Neg[iVar]) == s_Truths6Neg[iVar];                         }
+static inline int Abc_Tt6Cof1IsConst0( word t, int iVar ) { return (t & s_Truths6[iVar]) == 0;                                             }
+static inline int Abc_Tt6Cof1IsConst1( word t, int iVar ) { return (t & s_Truths6[iVar]) == s_Truths6[iVar];                               }
+static inline int Abc_Tt6CofsOpposite( word t, int iVar ) { return (~t & s_Truths6Neg[iVar]) == ((t >> (1 << iVar)) & s_Truths6Neg[iVar]); } 
+static inline int Abc_Tt6Cof0EqualCof1( word t1, word t2, int iVar ) { return (t1 & s_Truths6Neg[iVar]) == ((t2 >> (1 << iVar)) & s_Truths6Neg[iVar]); } 
+static inline int Abc_Tt6Cof0EqualCof0( word t1, word t2, int iVar ) { return (t1 & s_Truths6Neg[iVar]) == (t2 & s_Truths6Neg[iVar]); } 
+static inline int Abc_Tt6Cof1EqualCof1( word t1, word t2, int iVar ) { return (t1 & s_Truths6[iVar])    == (t2 & s_Truths6[iVar]); } 
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_TtTruthIsConst0( word * p, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( p[w] != 0        ) return 0; return 1; }
+static inline int Abc_TtTruthIsConst1( word * p, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( p[w] != ~(word)0 ) return 0; return 1; }
+
+static inline int Abc_TtCof0IsConst0( word * t, int nWords, int iVar ) 
+{ 
+    if ( iVar < 6 )
+    {
+        int i;
+        for ( i = 0; i < nWords; i++ )
+            if ( t[i] & s_Truths6Neg[iVar] )
+                return 0;
+        return 1;
+    }
+    else
+    {
+        int i, Step = (1 << (iVar - 6));
+        word * tLimit = t + nWords;
+        for ( ; t < tLimit; t += 2*Step )
+            for ( i = 0; i < Step; i++ )
+                if ( t[i] )
+                    return 0;
+        return 1;
+    }
+}
+static inline int Abc_TtCof0IsConst1( word * t, int nWords, int iVar ) 
+{ 
+    if ( iVar < 6 )
+    {
+        int i;
+        for ( i = 0; i < nWords; i++ )
+            if ( (t[i] & s_Truths6Neg[iVar]) != s_Truths6Neg[iVar] )
+                return 0;
+        return 1;
+    }
+    else
+    {
+        int i, Step = (1 << (iVar - 6));
+        word * tLimit = t + nWords;
+        for ( ; t < tLimit; t += 2*Step )
+            for ( i = 0; i < Step; i++ )
+                if ( ~t[i] )
+                    return 0;
+        return 1;
+    }
+}
+static inline int Abc_TtCof1IsConst0( word * t, int nWords, int iVar ) 
+{ 
+    if ( iVar < 6 )
+    {
+        int i;
+        for ( i = 0; i < nWords; i++ )
+            if ( t[i] & s_Truths6[iVar] )
+                return 0;
+        return 1;
+    }
+    else
+    {
+        int i, Step = (1 << (iVar - 6));
+        word * tLimit = t + nWords;
+        for ( ; t < tLimit; t += 2*Step )
+            for ( i = 0; i < Step; i++ )
+                if ( t[i+Step] )
+                    return 0;
+        return 1;
+    }
+}
+static inline int Abc_TtCof1IsConst1( word * t, int nWords, int iVar ) 
+{ 
+    if ( iVar < 6 )
+    {
+        int i;
+        for ( i = 0; i < nWords; i++ )
+            if ( (t[i] & s_Truths6[iVar]) != s_Truths6[iVar] )
+                return 0;
+        return 1;
+    }
+    else
+    {
+        int i, Step = (1 << (iVar - 6));
+        word * tLimit = t + nWords;
+        for ( ; t < tLimit; t += 2*Step )
+            for ( i = 0; i < Step; i++ )
+                if ( ~t[i+Step] )
+                    return 0;
+        return 1;
+    }
+}
+static inline int Abc_TtCofsOpposite( word * t, int nWords, int iVar ) 
+{ 
+    if ( iVar < 6 )
+    {
+        int i, Shift = (1 << iVar);
+        for ( i = 0; i < nWords; i++ )
+            if ( ((t[i] << Shift) & s_Truths6[iVar]) != (~t[i] & s_Truths6[iVar]) )
+                return 0;
+        return 1;
+    }
+    else
+    {
+        int i, Step = (1 << (iVar - 6));
+        word * tLimit = t + nWords;
+        for ( ; t < tLimit; t += 2*Step )
+            for ( i = 0; i < Step; i++ )
+                if ( t[i] != ~t[i+Step] )
+                    return 0;
+        return 1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stretch truthtable to have more input variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_TtStretch5( unsigned * pInOut, int nVarS, int nVarB )
+{
+    int w, i, step, nWords;
+    if ( nVarS == nVarB )
+        return;
+    assert( nVarS < nVarB );
+    step = Abc_TruthWordNum(nVarS);
+    nWords = Abc_TruthWordNum(nVarB);
+    if ( step == nWords )
+        return;
+    assert( step < nWords );
+    for ( w = 0; w < nWords; w += step )
+        for ( i = 0; i < step; i++ )
+            pInOut[w + i] = pInOut[i];              
+}
+static inline void Abc_TtStretch6( word * pInOut, int nVarS, int nVarB )
+{
+    int w, i, step, nWords;
+    if ( nVarS == nVarB )
+        return;
+    assert( nVarS < nVarB );
+    step = Abc_Truth6WordNum(nVarS);
+    nWords = Abc_Truth6WordNum(nVarB);
+    if ( step == nWords )
+        return;
+    assert( step < nWords );
+    for ( w = 0; w < nWords; w += step )
+        for ( i = 0; i < step; i++ )
+            pInOut[w + i] = pInOut[i];              
+}
+static inline word Abc_Tt6Stretch( word t, int nVars )
+{
+    assert( nVars >= 0 );
+    if ( nVars == 0 )
+        nVars++, t = (t & 0x1) | ((t & 0x1) << 1);
+    if ( nVars == 1 )
+        nVars++, t = (t & 0x3) | ((t & 0x3) << 2);
+    if ( nVars == 2 )
+        nVars++, t = (t & 0xF) | ((t & 0xF) << 4);
+    if ( nVars == 3 )
+        nVars++, t = (t & 0xFF) | ((t & 0xFF) << 8);
+    if ( nVars == 4 )
+        nVars++, t = (t & 0xFFFF) | ((t & 0xFFFF) << 16);
+    if ( nVars == 5 )
+        nVars++, t = (t & 0xFFFFFFFF) | ((t & 0xFFFFFFFF) << 32);
+    assert( nVars == 6 );
+    return t;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_TtIsHexDigit( char HexChar )
+{
+    return (HexChar >= '0' && HexChar <= '9') || (HexChar >= 'A' && HexChar <= 'F') || (HexChar >= 'a' && HexChar <= 'f');
+}
+static inline char Abc_TtPrintDigit( int Digit )
+{
+    assert( Digit >= 0 && Digit < 16 );
+    if ( Digit < 10 )
+        return '0' + Digit;
+    return 'A' + Digit-10;
+}
+static inline int Abc_TtReadHexDigit( char HexChar )
+{
+    if ( HexChar >= '0' && HexChar <= '9' )
+        return HexChar - '0';
+    if ( HexChar >= 'A' && HexChar <= 'F' )
+        return HexChar - 'A' + 10;
+    if ( HexChar >= 'a' && HexChar <= 'f' )
+        return HexChar - 'a' + 10;
+    assert( 0 ); // not a hexadecimal symbol
+    return -1; // return value which makes no sense
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_TtPrintHex( word * pTruth, int nVars )
+{
+    word * pThis, * pLimit = pTruth + Abc_TtWordNum(nVars);
+    int k;
+    assert( nVars >= 2 );
+    for ( pThis = pTruth; pThis < pLimit; pThis++ )
+        for ( k = 0; k < 16; k++ )
+            printf( "%c", Abc_TtPrintDigit((int)(pThis[0] >> (k << 2)) & 15) );
+    printf( "\n" );
+}
+static inline void Abc_TtPrintHexRev( FILE * pFile, word * pTruth, int nVars )
+{
+    word * pThis;
+    int k, StartK = nVars >= 6 ? 16 : (1 << (nVars - 2));
+    assert( nVars >= 2 );
+    for ( pThis = pTruth + Abc_TtWordNum(nVars) - 1; pThis >= pTruth; pThis-- )
+        for ( k = StartK - 1; k >= 0; k-- )
+            fprintf( pFile, "%c", Abc_TtPrintDigit((int)(pThis[0] >> (k << 2)) & 15) );
+//    printf( "\n" );
+}
+static inline void Abc_TtPrintHexSpecial( word * pTruth, int nVars )
+{
+    word * pThis;
+    int k;
+    assert( nVars >= 2 );
+    for ( pThis = pTruth + Abc_TtWordNum(nVars) - 1; pThis >= pTruth; pThis-- )
+        for ( k = 0; k < 16; k++ )
+            printf( "%c", Abc_TtPrintDigit((int)(pThis[0] >> (k << 2)) & 15) );
+    printf( "\n" );
+}
+static inline int Abc_TtWriteHexRev( char * pStr, word * pTruth, int nVars )
+{
+    word * pThis;
+    char * pStrInit = pStr;
+    int k, StartK = nVars >= 6 ? 16 : (1 << (nVars - 2));
+    assert( nVars >= 2 );
+    for ( pThis = pTruth + Abc_TtWordNum(nVars) - 1; pThis >= pTruth; pThis-- )
+        for ( k = StartK - 1; k >= 0; k-- )
+            *pStr++ = Abc_TtPrintDigit( (int)(pThis[0] >> (k << 2)) & 15 );
+    return pStr - pStrInit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads hex truth table from a string.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_TtReadHex( word * pTruth, char * pString )
+{
+    int k, nVars, Digit, nDigits;
+    // skip the first 2 symbols if they are "0x"
+    if ( pString[0] == '0' && pString[1] == 'x' )
+        pString += 2;
+    // count the number of hex digits
+    nDigits = 0;
+    for ( k = 0; Abc_TtIsHexDigit(pString[k]); k++ )
+        nDigits++;
+    if ( nDigits == 1 )
+    {
+        if ( pString[0] == '0' || pString[0] == 'F' )
+        {
+            pTruth[0] = (pString[0] == '0') ? 0 : ~(word)0;
+            return 0;
+        }
+        if ( pString[0] == '5' || pString[0] == 'A' )
+        {
+            pTruth[0] = (pString[0] == '5') ? s_Truths6Neg[0] : s_Truths6[0];
+            return 1;
+        }
+    }
+    // determine the number of variables
+    nVars = 2 + Abc_Base2Log( nDigits );
+    // clean storage
+    for ( k = Abc_TtWordNum(nVars) - 1; k >= 0; k-- )
+        pTruth[k] = 0;
+    // read hexadecimal digits in the reverse order
+    // (the last symbol in the string is the least significant digit)
+    for ( k = 0; k < nDigits; k++ )
+    {
+        Digit = Abc_TtReadHexDigit( pString[nDigits - 1 - k] );
+        assert( Digit >= 0 && Digit < 16 );
+        Abc_TtSetHex( pTruth, k, Digit );
+    }
+    if ( nVars < 6 )
+        pTruth[0] = Abc_Tt6Stretch( pTruth[0], nVars );
+    return nVars;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_TtPrintBinary( word * pTruth, int nVars )
+{
+    word * pThis, * pLimit = pTruth + Abc_TtWordNum(nVars);
+    int k, Limit = Abc_MinInt( 64, (1 << nVars) );
+    assert( nVars >= 2 );
+    for ( pThis = pTruth; pThis < pLimit; pThis++ )
+        for ( k = 0; k < Limit; k++ )
+            printf( "%d", Abc_InfoHasBit( (unsigned *)pThis, k ) );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_TtSuppFindFirst( int Supp )
+{
+    int i;
+    assert( Supp > 0 );
+    for ( i = 0; i < 32; i++ )
+        if ( Supp & (1 << i) )
+            return i;
+    return -1;
+}
+static inline int Abc_TtSuppOnlyOne( int Supp )
+{
+    if ( Supp == 0 )
+        return 0;
+    return (Supp & (Supp-1)) == 0;
+}
+static inline int Abc_TtSuppIsMinBase( int Supp )
+{
+    assert( Supp > 0 );
+    return (Supp & (Supp+1)) == 0;
+}
+static inline int Abc_Tt6HasVar( word t, int iVar )
+{
+    return ((t >> (1<<iVar)) & s_Truths6Neg[iVar]) != (t & s_Truths6Neg[iVar]);
+}
+static inline int Abc_TtHasVar( word * t, int nVars, int iVar )
+{
+    assert( iVar < nVars );
+    if ( nVars <= 6 )
+        return Abc_Tt6HasVar( t[0], iVar );
+    if ( iVar < 6 )
+    {
+        int i, Shift = (1 << iVar);
+        int nWords = Abc_TtWordNum( nVars );
+        for ( i = 0; i < nWords; i++ )
+            if ( ((t[i] >> Shift) & s_Truths6Neg[iVar]) != (t[i] & s_Truths6Neg[iVar]) )
+                return 1;
+        return 0;
+    }
+    else
+    {
+        int i, Step = (1 << (iVar - 6));
+        word * tLimit = t + Abc_TtWordNum( nVars );
+        for ( ; t < tLimit; t += 2*Step )
+            for ( i = 0; i < Step; i++ )
+                if ( t[i] != t[Step+i] )
+                    return 1;
+        return 0;
+    }
+}
+static inline int Abc_TtSupport( word * t, int nVars )
+{
+    int v, Supp = 0;
+    for ( v = 0; v < nVars; v++ )
+        if ( Abc_TtHasVar( t, nVars, v ) )
+            Supp |= (1 << v);
+    return Supp;
+}
+static inline int Abc_TtSupportSize( word * t, int nVars )
+{
+    int v, SuppSize = 0;
+    for ( v = 0; v < nVars; v++ )
+        if ( Abc_TtHasVar( t, nVars, v ) )
+            SuppSize++;
+    return SuppSize;
+}
+static inline int Abc_TtSupportAndSize( word * t, int nVars, int * pSuppSize )
+{
+    int v, Supp = 0;
+    *pSuppSize = 0;
+    for ( v = 0; v < nVars; v++ )
+        if ( Abc_TtHasVar( t, nVars, v ) )
+            Supp |= (1 << v), (*pSuppSize)++;
+    return Supp;
+}
+static inline int Abc_Tt6SupportAndSize( word t, int nVars, int * pSuppSize )
+{
+    int v, Supp = 0;
+    *pSuppSize = 0;
+    assert( nVars <= 6 );
+    for ( v = 0; v < nVars; v++ )
+        if ( Abc_Tt6HasVar( t, v ) )
+            Supp |= (1 << v), (*pSuppSize)++;
+    return Supp;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Abc_Tt6Flip( word Truth, int iVar )
+{
+    return Truth = ((Truth << (1 << iVar)) & s_Truths6[iVar]) | ((Truth & s_Truths6[iVar]) >> (1 << iVar));
+}
+static inline void Abc_TtFlip( word * pTruth, int nWords, int iVar )
+{
+    if ( nWords == 1 )
+        pTruth[0] = ((pTruth[0] << (1 << iVar)) & s_Truths6[iVar]) | ((pTruth[0] & s_Truths6[iVar]) >> (1 << iVar));
+	else if ( iVar <= 5 )
+	{
+		int w, shift = (1 << iVar);
+		for ( w = 0; w < nWords; w++ )
+            pTruth[w] = ((pTruth[w] << shift) & s_Truths6[iVar]) | ((pTruth[w] & s_Truths6[iVar]) >> shift);
+	}
+	else // if ( iVar > 5 )
+	{
+        word * pLimit = pTruth + nWords;
+		int i, iStep = Abc_TtWordNum(iVar);
+		for ( ; pTruth < pLimit; pTruth += 2*iStep )
+			for ( i = 0; i < iStep; i++ )
+                ABC_SWAP( word, pTruth[i], pTruth[i + iStep] );
+	}	
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Abc_Tt6Permute_rec( word t, int * pPerm, int nVars )
+{
+    word uRes0, uRes1; int Var;
+    if (  t == 0 ) return 0;
+    if ( ~t == 0 ) return ~(word)0;
+    for ( Var = nVars-1; Var >= 0; Var-- )
+        if ( Abc_Tt6HasVar( t, Var ) )
+             break;
+    assert( Var >= 0 );
+    uRes0 = Abc_Tt6Permute_rec( Abc_Tt6Cofactor0(t, Var), pPerm, Var );
+    uRes1 = Abc_Tt6Permute_rec( Abc_Tt6Cofactor1(t, Var), pPerm, Var );
+    return (uRes0 & s_Truths6Neg[pPerm[Var]]) | (uRes1 & s_Truths6[pPerm[Var]]);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Abc_Tt6SwapAdjacent( word Truth, int iVar )
+{
+    return (Truth & s_PMasks[iVar][0]) | ((Truth & s_PMasks[iVar][1]) << (1 << iVar)) | ((Truth & s_PMasks[iVar][2]) >> (1 << iVar));
+}
+static inline void Abc_TtSwapAdjacent( word * pTruth, int nWords, int iVar )
+{
+    static word s_PMasks[5][3] = {
+        { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) },
+        { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) },
+        { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) },
+        { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) },
+        { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) }
+    };
+    if ( iVar < 5 )
+    {
+        int i, Shift = (1 << iVar);
+        for ( i = 0; i < nWords; i++ )
+            pTruth[i] = (pTruth[i] & s_PMasks[iVar][0]) | ((pTruth[i] & s_PMasks[iVar][1]) << Shift) | ((pTruth[i] & s_PMasks[iVar][2]) >> Shift);
+    }
+    else if ( iVar == 5 )
+    {
+        unsigned * pTruthU = (unsigned *)pTruth;
+        unsigned * pLimitU = (unsigned *)(pTruth + nWords);
+		for ( ; pTruthU < pLimitU; pTruthU += 4 )
+            ABC_SWAP( unsigned, pTruthU[1], pTruthU[2] );
+    }
+    else // if ( iVar > 5 )
+    {
+        word * pLimit = pTruth + nWords;
+		int i, iStep = Abc_TtWordNum(iVar);
+		for ( ; pTruth < pLimit; pTruth += 4*iStep )
+			for ( i = 0; i < iStep; i++ )
+                ABC_SWAP( word, pTruth[i + iStep], pTruth[i + 2*iStep] );
+    }
+}
+static inline word Abc_Tt6SwapVars( word t, int iVar, int jVar )
+{
+    word * s_PMasks = Ps_PMasks[iVar][jVar];
+    int shift = (1 << jVar) - (1 << iVar);
+    assert( iVar < jVar );
+    return (t & s_PMasks[0]) | ((t & s_PMasks[1]) << shift) | ((t & s_PMasks[2]) >> shift);
+}
+static inline void Abc_TtSwapVars( word * pTruth, int nVars, int iVar, int jVar )
+{
+	if ( iVar == jVar )
+		return;
+	if ( jVar < iVar )
+        ABC_SWAP( int, iVar, jVar );
+    assert( iVar < jVar && jVar < nVars );
+    if ( nVars <= 6 )
+    {
+        pTruth[0] = Abc_Tt6SwapVars( pTruth[0], iVar, jVar );
+        return;
+    }
+	if ( jVar <= 5 )
+    {
+        word * s_PMasks = Ps_PMasks[iVar][jVar];
+	    int nWords = Abc_TtWordNum(nVars);
+		int w, shift = (1 << jVar) - (1 << iVar);
+		for ( w = 0; w < nWords; w++ )
+            pTruth[w] = (pTruth[w] & s_PMasks[0]) | ((pTruth[w] & s_PMasks[1]) << shift) | ((pTruth[w] & s_PMasks[2]) >> shift);
+        return;
+	}
+	if ( iVar <= 5 && jVar > 5 )
+	{
+	    word low2High, high2Low;
+        word * pLimit = pTruth + Abc_TtWordNum(nVars);
+        int j, jStep = Abc_TtWordNum(jVar);
+		int shift = 1 << iVar;
+		for ( ; pTruth < pLimit; pTruth += 2*jStep )
+			for ( j = 0; j < jStep; j++ )
+			{
+                low2High = (pTruth[j] & s_Truths6[iVar]) >> shift;
+                high2Low = (pTruth[j+jStep] << shift) & s_Truths6[iVar];
+                pTruth[j] = (pTruth[j] & ~s_Truths6[iVar]) | high2Low;
+                pTruth[j+jStep] = (pTruth[j+jStep] & s_Truths6[iVar]) | low2High;
+			}
+        return;
+	}
+	{
+        word * pLimit = pTruth + Abc_TtWordNum(nVars);
+		int i, iStep = Abc_TtWordNum(iVar);
+		int j, jStep = Abc_TtWordNum(jVar);
+		for ( ; pTruth < pLimit; pTruth += 2*jStep )
+			for ( i = 0; i < jStep; i += 2*iStep )
+				for ( j = 0; j < iStep; j++ )
+                    ABC_SWAP( word, pTruth[iStep + i + j], pTruth[jStep + i + j] );
+        return;
+	}	
+}
+// moves one var (v) to the given position (p)
+static inline void Abc_TtMoveVar( word * pF, int nVars, int * V2P, int * P2V, int v, int p )
+{
+    int iVar = V2P[v], jVar = p;
+    if ( iVar == jVar )
+        return;
+    Abc_TtSwapVars( pF, nVars, iVar, jVar );
+    V2P[P2V[iVar]] = jVar;
+    V2P[P2V[jVar]] = iVar;
+    P2V[iVar] ^= P2V[jVar];
+    P2V[jVar] ^= P2V[iVar];
+    P2V[iVar] ^= P2V[jVar];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Support minimization.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_TtShrink( word * pF, int nVars, int nVarsAll, unsigned Phase )
+{
+    int i, k, Var = 0;
+    assert( nVarsAll <= 16 );
+    for ( i = 0; i < nVarsAll; i++ )
+        if ( Phase & (1 << i) )
+        {
+            for ( k = i-1; k >= Var; k-- )
+                Abc_TtSwapAdjacent( pF, Abc_TtWordNum(nVarsAll), k );
+            Var++;
+        }
+    assert( Var == nVars );
+}
+static inline int Abc_TtMinimumBase( word * t, int * pSupp, int nVarsAll, int * pnVars )
+{
+    int v, iVar = 0, uSupp = 0;
+    assert( nVarsAll <= 16 );
+    for ( v = 0; v < nVarsAll; v++ )
+        if ( Abc_TtHasVar( t, nVarsAll, v ) )
+        {
+            uSupp |= (1 << v);
+            if ( pSupp )
+                pSupp[iVar] = pSupp[v];
+            iVar++;
+        }
+    if ( pnVars )
+        *pnVars = iVar;
+    if ( uSupp == 0 || Abc_TtSuppIsMinBase( uSupp ) )
+        return 0;
+    Abc_TtShrink( t, iVar, nVarsAll, uSupp );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cut minimization.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Abc_Tt6Expand( word t, int * pCut0, int nCutSize0, int * pCut, int nCutSize )
+{
+    int i, k;
+    for ( i = nCutSize - 1, k = nCutSize0 - 1; i >= 0 && k >= 0; i-- )
+    {
+        if ( pCut[i] > pCut0[k] )
+            continue;
+        assert( pCut[i] == pCut0[k] );
+        if ( k < i )
+            t = Abc_Tt6SwapVars( t, k, i );
+        k--;
+    }
+    assert( k == -1 );
+    return t;
+}
+static inline void Abc_TtExpand( word * pTruth0, int nVars, int * pCut0, int nCutSize0, int * pCut, int nCutSize )
+{
+    int i, k;
+    for ( i = nCutSize - 1, k = nCutSize0 - 1; i >= 0 && k >= 0; i-- )
+    {
+        if ( pCut[i] > pCut0[k] )
+            continue;
+        assert( pCut[i] == pCut0[k] );
+        if ( k < i )
+            Abc_TtSwapVars( pTruth0, nVars, k, i );
+        k--;
+    }
+    assert( k == -1 );
+}
+static inline int Abc_Tt6MinBase( word * pTruth, int * pVars, int nVars ) 
+{
+    word t = *pTruth;
+    int i, k;
+    for ( i = k = 0; i < nVars; i++ )
+    {
+        if ( !Abc_Tt6HasVar( t, i ) )
+            continue;
+        if ( k < i )
+        {
+            if ( pVars ) pVars[k] = pVars[i];
+            t = Abc_Tt6SwapVars( t, k, i );
+        }
+        k++;
+    }
+    if ( k == nVars )
+        return k;
+    assert( k < nVars );
+    *pTruth = t;
+    return k;
+}
+static inline int Abc_TtMinBase( word * pTruth, int * pVars, int nVars, int nVarsAll ) 
+{
+    int i, k;
+    assert( nVars <= nVarsAll );
+    for ( i = k = 0; i < nVars; i++ )
+    {
+        if ( !Abc_TtHasVar( pTruth, nVarsAll, i ) )
+            continue;
+        if ( k < i )
+        {
+            if ( pVars ) pVars[k] = pVars[i];
+            Abc_TtSwapVars( pTruth, nVarsAll, k, i );
+        }
+        k++;
+    }
+    if ( k == nVars )
+        return k;
+    assert( k < nVars );
+//    assert( k == Abc_TtSupportSize(pTruth, nVars) );
+    return k;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implemeting given NPN config.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_TtImplementNpnConfig( word * pTruth, int nVars, char * pCanonPerm, unsigned uCanonPhase )
+{
+    int i, k, nWords = Abc_TtWordNum( nVars );
+    if ( (uCanonPhase >> nVars) & 1 )
+        Abc_TtNot( pTruth, nWords );
+    for ( i = 0; i < nVars; i++ )
+        if ( (uCanonPhase >> i) & 1 )
+            Abc_TtFlip( pTruth, nWords, i );
+    if ( pCanonPerm )
+    for ( i = 0; i < nVars; i++ )
+    {
+        for ( k = i; k < nVars; k++ )
+            if ( pCanonPerm[k] == i )
+                break;
+        assert( k < nVars );
+        if ( i == k )
+            continue;
+        Abc_TtSwapVars( pTruth, nVars, i, k );
+        ABC_SWAP( int, pCanonPerm[i], pCanonPerm[k] );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_TtCountOnesSlow( word t )
+{
+    t =    (t & ABC_CONST(0x5555555555555555)) + ((t>> 1) & ABC_CONST(0x5555555555555555));
+    t =    (t & ABC_CONST(0x3333333333333333)) + ((t>> 2) & ABC_CONST(0x3333333333333333));
+    t =    (t & ABC_CONST(0x0F0F0F0F0F0F0F0F)) + ((t>> 4) & ABC_CONST(0x0F0F0F0F0F0F0F0F));
+    t =    (t & ABC_CONST(0x00FF00FF00FF00FF)) + ((t>> 8) & ABC_CONST(0x00FF00FF00FF00FF));
+    t =    (t & ABC_CONST(0x0000FFFF0000FFFF)) + ((t>>16) & ABC_CONST(0x0000FFFF0000FFFF));
+    return (t & ABC_CONST(0x00000000FFFFFFFF)) +  (t>>32);
+}
+static inline int Abc_TtCountOnes( word x )
+{
+    x = x - ((x >> 1) & ABC_CONST(0x5555555555555555));   
+    x = (x & ABC_CONST(0x3333333333333333)) + ((x >> 2) & ABC_CONST(0x3333333333333333));    
+    x = (x + (x >> 4)) & ABC_CONST(0x0F0F0F0F0F0F0F0F);    
+    x = x + (x >> 8);
+    x = x + (x >> 16);
+    x = x + (x >> 32); 
+    return (int)(x & 0xFF);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_Tt6FirstBit( word t )
+{
+    int n = 0;
+    if ( t == 0 ) return -1;
+    if ( (t & ABC_CONST(0x00000000FFFFFFFF)) == 0 ) { n += 32; t >>= 32; }
+    if ( (t & ABC_CONST(0x000000000000FFFF)) == 0 ) { n += 16; t >>= 16; }
+    if ( (t & ABC_CONST(0x00000000000000FF)) == 0 ) { n +=  8; t >>=  8; }
+    if ( (t & ABC_CONST(0x000000000000000F)) == 0 ) { n +=  4; t >>=  4; }
+    if ( (t & ABC_CONST(0x0000000000000003)) == 0 ) { n +=  2; t >>=  2; }
+    if ( (t & ABC_CONST(0x0000000000000001)) == 0 ) { n++; }
+    return n;
+}
+static inline int Abc_Tt6LastBit( word t )
+{
+    int n = 0;
+    if ( t == 0 ) return -1;
+    if ( (t & ABC_CONST(0xFFFFFFFF00000000)) == 0 ) { n += 32; t <<= 32; }
+    if ( (t & ABC_CONST(0xFFFF000000000000)) == 0 ) { n += 16; t <<= 16; }
+    if ( (t & ABC_CONST(0xFF00000000000000)) == 0 ) { n +=  8; t <<=  8; }
+    if ( (t & ABC_CONST(0xF000000000000000)) == 0 ) { n +=  4; t <<=  4; }
+    if ( (t & ABC_CONST(0xC000000000000000)) == 0 ) { n +=  2; t <<=  2; }
+    if ( (t & ABC_CONST(0x8000000000000000)) == 0 ) { n++; }
+    return 63-n;
+}
+static inline int Abc_TtFindFirstBit( word * pIn, int nVars )
+{
+    int w, nWords = Abc_TtWordNum(nVars);
+    for ( w = 0; w < nWords; w++ )
+        if ( pIn[w] )
+            return 64*w + Abc_Tt6FirstBit(pIn[w]);
+    return -1;
+}
+static inline int Abc_TtFindFirstZero( word * pIn, int nVars )
+{
+    int w, nWords = Abc_TtWordNum(nVars);
+    for ( w = 0; w < nWords; w++ )
+        if ( ~pIn[w] )
+            return 64*w + Abc_Tt6FirstBit(~pIn[w]);
+    return -1;
+}
+static inline int Abc_TtFindLastBit( word * pIn, int nVars )
+{
+    int w, nWords = Abc_TtWordNum(nVars);
+    for ( w = nWords - 1; w >= 0; w-- )
+        if ( pIn[w] )
+            return 64*w + Abc_Tt6LastBit(pIn[w]);
+    return -1;
+}
+static inline int Abc_TtFindLastZero( word * pIn, int nVars )
+{
+    int w, nWords = Abc_TtWordNum(nVars);
+    for ( w = nWords - 1; w >= 0; w-- )
+        if ( ~pIn[w] )
+            return 64*w + Abc_Tt6LastBit(~pIn[w]);
+    return -1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_TtReverseVars( word * pTruth, int nVars )
+{
+    int k;
+    for ( k = 0; k < nVars/2 ; k++ )
+        Abc_TtSwapVars( pTruth, nVars, k, nVars - 1 - k );
+}
+static inline void Abc_TtReverseBits( word * pTruth, int nVars )
+{
+    static unsigned char pMirror[256] = {
+          0, 128,  64, 192,  32, 160,  96, 224,  16, 144,  80, 208,  48, 176, 112, 240,
+          8, 136,  72, 200,  40, 168, 104, 232,  24, 152,  88, 216,  56, 184, 120, 248,
+          4, 132,  68, 196,  36, 164, 100, 228,  20, 148,  84, 212,  52, 180, 116, 244,
+         12, 140,  76, 204,  44, 172, 108, 236,  28, 156,  92, 220,  60, 188, 124, 252,
+          2, 130,  66, 194,  34, 162,  98, 226,  18, 146,  82, 210,  50, 178, 114, 242,
+         10, 138,  74, 202,  42, 170, 106, 234,  26, 154,  90, 218,  58, 186, 122, 250,
+          6, 134,  70, 198,  38, 166, 102, 230,  22, 150,  86, 214,  54, 182, 118, 246,
+         14, 142,  78, 206,  46, 174, 110, 238,  30, 158,  94, 222,  62, 190, 126, 254,
+          1, 129,  65, 193,  33, 161,  97, 225,  17, 145,  81, 209,  49, 177, 113, 241,
+          9, 137,  73, 201,  41, 169, 105, 233,  25, 153,  89, 217,  57, 185, 121, 249,
+          5, 133,  69, 197,  37, 165, 101, 229,  21, 149,  85, 213,  53, 181, 117, 245,
+         13, 141,  77, 205,  45, 173, 109, 237,  29, 157,  93, 221,  61, 189, 125, 253,
+          3, 131,  67, 195,  35, 163,  99, 227,  19, 147,  83, 211,  51, 179, 115, 243,
+         11, 139,  75, 203,  43, 171, 107, 235,  27, 155,  91, 219,  59, 187, 123, 251,
+          7, 135,  71, 199,  39, 167, 103, 231,  23, 151,  87, 215,  55, 183, 119, 247,
+         15, 143,  79, 207,  47, 175, 111, 239,  31, 159,  95, 223,  63, 191, 127, 255
+    };
+    unsigned char Temp, * pTruthC = (unsigned char *)pTruth;
+    int i, nBytes = (nVars > 6) ? (1 << (nVars - 3)) : 8;
+    for ( i = 0; i < nBytes/2; i++ )
+    {
+        Temp = pMirror[pTruthC[i]];
+        pTruthC[i] = pMirror[pTruthC[nBytes-1-i]];
+        pTruthC[nBytes-1-i] = Temp;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes ISOP for 6 variables or less.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Abc_Tt6Isop( word uOn, word uOnDc, int nVars, int * pnCubes )
+{
+    word uOn0, uOn1, uOnDc0, uOnDc1, uRes0, uRes1, uRes2;
+    int Var;
+    assert( nVars <= 6 );
+    assert( (uOn & ~uOnDc) == 0 );
+    if ( uOn == 0 )
+        return 0;
+    if ( uOnDc == ~(word)0 )
+    {
+        (*pnCubes)++;
+        return ~(word)0;
+    }
+    assert( nVars > 0 );
+    // find the topmost var
+    for ( Var = nVars-1; Var >= 0; Var-- )
+        if ( Abc_Tt6HasVar( uOn, Var ) || Abc_Tt6HasVar( uOnDc, Var ) )
+             break;
+    assert( Var >= 0 );
+    // cofactor
+    uOn0   = Abc_Tt6Cofactor0( uOn,   Var );
+    uOn1   = Abc_Tt6Cofactor1( uOn  , Var );
+    uOnDc0 = Abc_Tt6Cofactor0( uOnDc, Var );
+    uOnDc1 = Abc_Tt6Cofactor1( uOnDc, Var );
+    // solve for cofactors
+    uRes0 = Abc_Tt6Isop( uOn0 & ~uOnDc1, uOnDc0, Var, pnCubes );
+    uRes1 = Abc_Tt6Isop( uOn1 & ~uOnDc0, uOnDc1, Var, pnCubes );
+    uRes2 = Abc_Tt6Isop( (uOn0 & ~uRes0) | (uOn1 & ~uRes1), uOnDc0 & uOnDc1, Var, pnCubes );
+    // derive the final truth table
+    uRes2 |= (uRes0 & s_Truths6Neg[Var]) | (uRes1 & s_Truths6[Var]);
+    assert( (uOn & ~uRes2) == 0 );
+    assert( (uRes2 & ~uOnDc) == 0 );
+    return uRes2;
+}
+static inline int Abc_Tt7Isop( word uOn[2], word uOnDc[2], int nVars, word uRes[2] )
+{
+    int nCubes = 0;
+    if ( nVars <= 6 || (uOn[0] == uOn[1] && uOnDc[0] == uOnDc[1]) )
+        uRes[0] = uRes[1] = Abc_Tt6Isop( uOn[0], uOnDc[0], Abc_MinInt(nVars, 6), &nCubes );
+    else
+    {
+        word uRes0, uRes1, uRes2;
+        assert( nVars == 7 );
+        // solve for cofactors
+        uRes0 = Abc_Tt6Isop( uOn[0] & ~uOnDc[1], uOnDc[0], 6, &nCubes );
+        uRes1 = Abc_Tt6Isop( uOn[1] & ~uOnDc[0], uOnDc[1], 6, &nCubes );
+        uRes2 = Abc_Tt6Isop( (uOn[0] & ~uRes0) | (uOn[1] & ~uRes1), uOnDc[0] & uOnDc[1], 6, &nCubes );
+        // derive the final truth table
+        uRes[0] = uRes2 | uRes0;
+        uRes[1] = uRes2 | uRes1;
+        assert( (uOn[0] & ~uRes[0]) == 0 && (uOn[1] & ~uRes[1]) == 0 );
+        assert( (uRes[0] & ~uOnDc[0])==0 && (uRes[1] & ~uOnDc[1])==0 );
+    }
+    return nCubes;
+}
+static inline int Abc_Tt8Isop( word uOn[4], word uOnDc[4], int nVars, word uRes[4] )
+{
+    int nCubes = 0;
+    if ( nVars <= 6 )
+        uRes[0] = uRes[1] = uRes[2] = uRes[3] = Abc_Tt6Isop( uOn[0], uOnDc[0], nVars, &nCubes );
+    else if ( nVars == 7 || (uOn[0] == uOn[2] && uOn[1] == uOn[3] && uOnDc[0] == uOnDc[2] && uOnDc[1] == uOnDc[3]) )
+    {
+        nCubes = Abc_Tt7Isop( uOn, uOnDc, 7, uRes );
+        uRes[2] = uRes[0];
+        uRes[3] = uRes[1];
+    }
+    else 
+    {
+        word uOn0[2], uOn1[2], uOn2[2], uOnDc2[2], uRes0[2], uRes1[2], uRes2[2];
+        assert( nVars == 8 );
+        // cofactor
+        uOn0[0] = uOn[0] & ~uOnDc[2];
+        uOn0[1] = uOn[1] & ~uOnDc[3];
+        uOn1[0] = uOn[2] & ~uOnDc[0];
+        uOn1[1] = uOn[3] & ~uOnDc[1];
+        uOnDc2[0] = uOnDc[0] & uOnDc[2];
+        uOnDc2[1] = uOnDc[1] & uOnDc[3];
+        // solve for cofactors
+        nCubes += Abc_Tt7Isop( uOn0, uOnDc+0, 7, uRes0 );
+        nCubes += Abc_Tt7Isop( uOn1, uOnDc+2, 7, uRes1 );
+        uOn2[0] = (uOn[0] & ~uRes0[0]) | (uOn[2] & ~uRes1[0]);
+        uOn2[1] = (uOn[1] & ~uRes0[1]) | (uOn[3] & ~uRes1[1]);
+        nCubes += Abc_Tt7Isop( uOn2, uOnDc2, 7, uRes2 );
+        // derive the final truth table
+        uRes[0] = uRes2[0] | uRes0[0];
+        uRes[1] = uRes2[1] | uRes0[1];
+        uRes[2] = uRes2[0] | uRes1[0];
+        uRes[3] = uRes2[1] | uRes1[1];
+        assert( (uOn[0] & ~uRes[0]) == 0 && (uOn[1] & ~uRes[1]) == 0 && (uOn[2] & ~uRes[2]) == 0 && (uOn[3] & ~uRes[3]) == 0 );
+        assert( (uRes[0] & ~uOnDc[0])==0 && (uRes[1] & ~uOnDc[1])==0 && (uRes[2] & ~uOnDc[2])==0 && (uRes[3] & ~uOnDc[3])==0 );
+    }
+    return nCubes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes CNF size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_Tt6CnfSize( word t, int nVars )
+{
+    int nCubes = 0;
+    Abc_Tt6Isop(  t,  t, nVars, &nCubes );
+    Abc_Tt6Isop( ~t, ~t, nVars, &nCubes );
+    assert( nCubes <= 64 );
+    return nCubes;
+}
+static inline int Abc_Tt8CnfSize( word t[4], int nVars )
+{
+    word uRes[4], tc[4] = {~t[0], ~t[1], ~t[2], ~t[3]};
+    int nCubes = 0;
+    nCubes += Abc_Tt8Isop( t,  t,  nVars, uRes );
+    nCubes += Abc_Tt8Isop( tc, tc, nVars, uRes );
+    assert( nCubes <= 256 );
+    return nCubes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives ISOP cover for the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Abc_Tt6IsopCover( word uOn, word uOnDc, int nVars, int * pCover, int * pnCubes )
+{
+    word uOn0, uOn1, uOnDc0, uOnDc1, uRes0, uRes1, uRes2;
+    int c, Var, nBeg0, nEnd0, nEnd1;
+    assert( nVars <= 6 );
+    assert( (uOn & ~uOnDc) == 0 );
+    if ( uOn == 0 )
+        return 0;
+    if ( uOnDc == ~(word)0 )
+    {
+        pCover[(*pnCubes)++] = 0;
+        return ~(word)0;
+    }
+    assert( nVars > 0 );
+    // find the topmost var
+    for ( Var = nVars-1; Var >= 0; Var-- )
+        if ( Abc_Tt6HasVar( uOn, Var ) || Abc_Tt6HasVar( uOnDc, Var ) )
+             break;
+    assert( Var >= 0 );
+    // cofactor
+    uOn0   = Abc_Tt6Cofactor0( uOn,   Var );
+    uOn1   = Abc_Tt6Cofactor1( uOn  , Var );
+    uOnDc0 = Abc_Tt6Cofactor0( uOnDc, Var );
+    uOnDc1 = Abc_Tt6Cofactor1( uOnDc, Var );
+    // solve for cofactors
+    nBeg0 = *pnCubes; 
+    uRes0 = Abc_Tt6IsopCover( uOn0 & ~uOnDc1, uOnDc0, Var, pCover, pnCubes );
+    nEnd0 = *pnCubes;
+    uRes1 = Abc_Tt6IsopCover( uOn1 & ~uOnDc0, uOnDc1, Var, pCover, pnCubes );
+    nEnd1 = *pnCubes;
+    uRes2 = Abc_Tt6IsopCover( (uOn0 & ~uRes0) | (uOn1 & ~uRes1), uOnDc0 & uOnDc1, Var, pCover, pnCubes );
+    // derive the final truth table
+    uRes2 |= (uRes0 & s_Truths6Neg[Var]) | (uRes1 & s_Truths6[Var]);
+    for ( c = nBeg0; c < nEnd0; c++ )
+        pCover[c] |= (1 << (2*Var+0));
+    for ( c = nEnd0; c < nEnd1; c++ )
+        pCover[c] |= (1 << (2*Var+1));
+    assert( (uOn & ~uRes2) == 0 );
+    assert( (uRes2 & ~uOnDc) == 0 );
+    return uRes2;
+}
+static inline void Abc_Tt7IsopCover( word uOn[2], word uOnDc[2], int nVars, word uRes[2], int * pCover, int * pnCubes )
+{
+    if ( nVars <= 6 || (uOn[0] == uOn[1] && uOnDc[0] == uOnDc[1]) )
+        uRes[0] = uRes[1] = Abc_Tt6IsopCover( uOn[0], uOnDc[0], Abc_MinInt(nVars, 6), pCover, pnCubes );
+    else
+    {
+        word uRes0, uRes1, uRes2;
+        int c, nBeg0, nEnd0, nEnd1;
+        assert( nVars == 7 );
+        // solve for cofactors
+        nBeg0 = *pnCubes; 
+        uRes0 = Abc_Tt6IsopCover( uOn[0] & ~uOnDc[1], uOnDc[0], 6, pCover, pnCubes );   
+        nEnd0 = *pnCubes;
+        uRes1 = Abc_Tt6IsopCover( uOn[1] & ~uOnDc[0], uOnDc[1], 6, pCover, pnCubes );   
+        nEnd1 = *pnCubes;
+        uRes2 = Abc_Tt6IsopCover( (uOn[0] & ~uRes0) | (uOn[1] & ~uRes1), uOnDc[0] & uOnDc[1], 6, pCover, pnCubes );
+        // derive the final truth table
+        uRes[0] = uRes2 | uRes0;
+        uRes[1] = uRes2 | uRes1;
+        for ( c = nBeg0; c < nEnd0; c++ )
+            pCover[c] |= (1 << (2*6+0));
+        for ( c = nEnd0; c < nEnd1; c++ )
+            pCover[c] |= (1 << (2*6+1));
+        assert( (uOn[0] & ~uRes[0]) == 0 && (uOn[1] & ~uRes[1]) == 0 );
+        assert( (uRes[0] & ~uOnDc[0])==0 && (uRes[1] & ~uOnDc[1])==0 );
+    }
+}
+static inline void Abc_Tt8IsopCover( word uOn[4], word uOnDc[4], int nVars, word uRes[4], int * pCover, int * pnCubes )
+{
+    if ( nVars <= 6 )
+        uRes[0] = uRes[1] = uRes[2] = uRes[3] = Abc_Tt6IsopCover( uOn[0], uOnDc[0], nVars, pCover, pnCubes );
+    else if ( nVars == 7 || (uOn[0] == uOn[2] && uOn[1] == uOn[3] && uOnDc[0] == uOnDc[2] && uOnDc[1] == uOnDc[3]) )
+    {
+        Abc_Tt7IsopCover( uOn, uOnDc, 7, uRes, pCover, pnCubes );
+        uRes[2] = uRes[0];
+        uRes[3] = uRes[1];
+    }
+    else 
+    {
+        word uOn0[2], uOn1[2], uOn2[2], uOnDc2[2], uRes0[2], uRes1[2], uRes2[2];
+        int c, nBeg0, nEnd0, nEnd1;
+        assert( nVars == 8 );
+        // cofactor
+        uOn0[0] = uOn[0] & ~uOnDc[2];
+        uOn0[1] = uOn[1] & ~uOnDc[3];
+        uOn1[0] = uOn[2] & ~uOnDc[0];
+        uOn1[1] = uOn[3] & ~uOnDc[1];
+        uOnDc2[0] = uOnDc[0] & uOnDc[2];
+        uOnDc2[1] = uOnDc[1] & uOnDc[3];
+        // solve for cofactors
+        nBeg0 = *pnCubes; 
+        Abc_Tt7IsopCover( uOn0, uOnDc+0, 7, uRes0, pCover, pnCubes );
+        nEnd0 = *pnCubes;
+        Abc_Tt7IsopCover( uOn1, uOnDc+2, 7, uRes1, pCover, pnCubes );
+        nEnd1 = *pnCubes;
+        uOn2[0] = (uOn[0] & ~uRes0[0]) | (uOn[2] & ~uRes1[0]);
+        uOn2[1] = (uOn[1] & ~uRes0[1]) | (uOn[3] & ~uRes1[1]);
+        Abc_Tt7IsopCover( uOn2, uOnDc2, 7, uRes2, pCover, pnCubes );
+        // derive the final truth table
+        uRes[0] = uRes2[0] | uRes0[0];
+        uRes[1] = uRes2[1] | uRes0[1];
+        uRes[2] = uRes2[0] | uRes1[0];
+        uRes[3] = uRes2[1] | uRes1[1];
+        for ( c = nBeg0; c < nEnd0; c++ )
+            pCover[c] |= (1 << (2*7+0));
+        for ( c = nEnd0; c < nEnd1; c++ )
+            pCover[c] |= (1 << (2*7+1));
+        assert( (uOn[0] & ~uRes[0]) == 0 && (uOn[1] & ~uRes[1]) == 0 && (uOn[2] & ~uRes[2]) == 0 && (uOn[3] & ~uRes[3]) == 0 );
+        assert( (uRes[0] & ~uOnDc[0])==0 && (uRes[1] & ~uOnDc[1])==0 && (uRes[2] & ~uOnDc[2])==0 && (uRes[3] & ~uOnDc[3])==0 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes CNF for the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_Tt6Cnf( word t, int nVars, int * pCover )
+{
+    int c, nCubes = 0;
+    Abc_Tt6IsopCover( t, t, nVars, pCover, &nCubes );
+    for ( c = 0; c < nCubes; c++ )
+        pCover[c] |= (1 << (2*nVars+0));
+    Abc_Tt6IsopCover( ~t, ~t, nVars, pCover, &nCubes );
+    for ( ; c < nCubes; c++ )
+        pCover[c] |= (1 << (2*nVars+1));
+    assert( nCubes <= 64 );
+    return nCubes;
+}
+static inline int Abc_Tt8Cnf( word t[4], int nVars, int * pCover )
+{
+    word uRes[4], tc[4] = {~t[0], ~t[1], ~t[2], ~t[3]};
+    int c, nCubes = 0;
+    Abc_Tt8IsopCover( t,  t,  nVars, uRes, pCover, &nCubes );
+    for ( c = 0; c < nCubes; c++ )
+        pCover[c] |= (1 << (2*nVars+0));
+    Abc_Tt8IsopCover( tc, tc, nVars, uRes, pCover, &nCubes );
+    for ( ; c < nCubes; c++ )
+        pCover[c] |= (1 << (2*nVars+1));
+    assert( nCubes <= 256 );
+    return nCubes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Check if the function is decomposable with the given pair.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_TtCheckDsdAnd( word t, int i, int j, word * pOut )
+{
+    word c0 = Abc_Tt6Cofactor0( t, i );
+    word c1 = Abc_Tt6Cofactor1( t, i );
+    word c00 = Abc_Tt6Cofactor0( c0, j );
+    word c01 = Abc_Tt6Cofactor1( c0, j );
+    word c10 = Abc_Tt6Cofactor0( c1, j );
+    word c11 = Abc_Tt6Cofactor1( c1, j );
+    if ( c00 == c01 && c00 == c10 ) //  i *  j
+    {
+        if ( pOut ) *pOut = (~s_Truths6[i] & c00) | (s_Truths6[i] & c11);
+        return 0;
+    }
+    if ( c11 == c00 && c11 == c10 ) //  i * !j
+    {
+        if ( pOut ) *pOut = (~s_Truths6[i] & c11) | (s_Truths6[i] & c01);
+        return 1;
+    }
+    if ( c11 == c00 && c11 == c01 ) // !i *  j
+    {
+        if ( pOut ) *pOut = (~s_Truths6[i] & c11) | (s_Truths6[i] & c10);
+        return 2;
+    }
+    if ( c11 == c01 && c11 == c10 ) // !i * !j
+    {
+        if ( pOut ) *pOut = (~s_Truths6[i] & c11) | (s_Truths6[i] & c00);
+        return 3;
+    }
+    if ( c00 == c11 && c01 == c10 )
+    {
+        if ( pOut ) *pOut = (~s_Truths6[i] & c11) | (s_Truths6[i] & c10);
+        return 4;
+    }
+    return -1;
+}
+static inline int Abc_TtCheckDsdMux( word t, int i, word * pOut )
+{
+    word c0 = Abc_Tt6Cofactor0( t, i );
+    word c1 = Abc_Tt6Cofactor1( t, i );
+    word c00, c01, c10, c11;
+    int k, fPres0, fPres1, iVar0 = -1, iVar1 = -1;
+    for ( k = 0; k < 6; k++ )
+    {
+        if ( k == i ) continue;
+        fPres0 = Abc_Tt6HasVar( c0, k );
+        fPres1 = Abc_Tt6HasVar( c1, k );
+        if ( fPres0 && !fPres1 )
+        {
+            if ( iVar0 >= 0 )
+                return -1;
+            iVar0 = k;
+        }
+        if ( !fPres0 && fPres1 )
+        {
+            if ( iVar1 >= 0 )
+                return -1;
+            iVar1 = k;
+        }
+    }
+    if ( iVar0 == -1 || iVar1 == -1 )
+        return -1;
+    c00 = Abc_Tt6Cofactor0( c0, iVar0 );
+    c01 = Abc_Tt6Cofactor1( c0, iVar0 );
+    c10 = Abc_Tt6Cofactor0( c1, iVar1 );
+    c11 = Abc_Tt6Cofactor1( c1, iVar1 );
+    if ( c00 ==  c10 && c01 ==  c11 ) //  ITE(i,  iVar1,  iVar0)
+    {
+        if ( pOut ) *pOut = (~s_Truths6[i] & c10) | (s_Truths6[i] & c11);
+        return (Abc_Var2Lit(iVar1, 0) << 16) | Abc_Var2Lit(iVar0, 0);
+    }
+    if ( c00 == ~c10 && c01 == ~c11 ) //  ITE(i,  iVar1, !iVar0)
+    {
+        if ( pOut ) *pOut = (~s_Truths6[i] & c10) | (s_Truths6[i] & c11);
+        return (Abc_Var2Lit(iVar1, 0) << 16) | Abc_Var2Lit(iVar0, 1);
+    }
+    return -1;
+}
+static inline void Unm_ManCheckTest2()
+{
+    word t, t1, Out, Var0, Var1, Var0_, Var1_;
+    int iVar0, iVar1, i, Res;
+    for ( iVar0 = 0; iVar0 < 6; iVar0++ )
+    for ( iVar1 = 0; iVar1 < 6; iVar1++ )
+    {
+        if ( iVar0 == iVar1 )
+            continue;
+        Var0 = s_Truths6[iVar0];
+        Var1 = s_Truths6[iVar1];
+        for ( i = 0; i < 5; i++ )
+        {
+            Var0_ = ((i >> 0) & 1) ? ~Var0 : Var0;
+            Var1_ = ((i >> 1) & 1) ? ~Var1 : Var1;
+
+            t = Var0_ & Var1_;
+            if ( i == 4 )
+                t = ~(Var0_ ^ Var1_);
+
+//            Kit_DsdPrintFromTruth( (unsigned *)&t, 6 ), printf( "\n" );
+
+            Res = Abc_TtCheckDsdAnd( t, iVar0, iVar1, &Out );
+            if ( Res == -1 )
+            {
+                printf( "No decomposition\n" );
+                continue;
+            }
+
+            Var0_ = s_Truths6[iVar0];
+            Var0_ = ((Res >> 0) & 1) ? ~Var0_ : Var0_;
+
+            Var1_ = s_Truths6[iVar1];
+            Var1_ = ((Res >> 1) & 1) ? ~Var1_ : Var1_;
+
+            t1 = Var0_ & Var1_;
+            if ( Res == 4 )
+                t1 = Var0_ ^ Var1_;
+
+            t1 = (~t1 & Abc_Tt6Cofactor0(Out, iVar0)) | (t1 & Abc_Tt6Cofactor1(Out, iVar0));
+
+//            Kit_DsdPrintFromTruth( (unsigned *)&t1, 6 ), printf( "\n" );
+
+            if ( t1 != t )
+                printf( "Verification failed.\n" );
+            else
+                printf( "Verification succeeded.\n" );
+        }
+    }
+}
+static inline void Unm_ManCheckTest()
+{
+    word t, t1, Out, Ctrl, Var0, Var1, Ctrl_, Var0_, Var1_;
+    int iVar0, iVar1, iCtrl, i, Res;
+    for ( iCtrl = 0; iCtrl < 6; iCtrl++ )
+    for ( iVar0 = 0; iVar0 < 6; iVar0++ )
+    for ( iVar1 = 0; iVar1 < 6; iVar1++ )
+    {
+        if ( iCtrl == iVar0 || iCtrl == iVar1 || iVar0 == iVar1 )
+            continue;
+        Ctrl = s_Truths6[iCtrl];
+        Var0 = s_Truths6[iVar0];
+        Var1 = s_Truths6[iVar1];
+        for ( i = 0; i < 8; i++ )
+        {
+            Ctrl_ = ((i >> 0) & 1) ? ~Ctrl : Ctrl;
+            Var0_ = ((i >> 1) & 1) ? ~Var0 : Var0;
+            Var1_ = ((i >> 2) & 1) ? ~Var1 : Var1;
+
+            t = (~Ctrl_ & Var0_) | (Ctrl_ & Var1_);
+
+//            Kit_DsdPrintFromTruth( (unsigned *)&t, 6 ), printf( "\n" );
+
+            Res = Abc_TtCheckDsdMux( t, iCtrl, &Out );
+            if ( Res == -1 )
+            {
+                printf( "No decomposition\n" );
+                continue;
+            }
+
+//            Kit_DsdPrintFromTruth( (unsigned *)&Out, 6 ), printf( "\n" );
+
+            Ctrl_ = s_Truths6[iCtrl];
+            Var0_ = s_Truths6[Abc_Lit2Var(Res & 0xFFFF)];
+            Var0_ = Abc_LitIsCompl(Res & 0xFFFF) ? ~Var0_ : Var0_;
+
+            Res >>= 16;
+            Var1_ = s_Truths6[Abc_Lit2Var(Res & 0xFFFF)];
+            Var1_ = Abc_LitIsCompl(Res & 0xFFFF) ? ~Var1_ : Var1_;
+
+            t1 = (~Ctrl_ & Var0_) | (Ctrl_ & Var1_);
+
+//            Kit_DsdPrintFromTruth( (unsigned *)&t1, 6 ), printf( "\n" );
+//            Kit_DsdPrintFromTruth( (unsigned *)&Out, 6 ), printf( "\n" );
+
+            t1 = (~t1 & Abc_Tt6Cofactor0(Out, iCtrl)) | (t1 & Abc_Tt6Cofactor1(Out, iCtrl));
+
+//            Kit_DsdPrintFromTruth( (unsigned *)&t1, 6 ), printf( "\n" );
+
+            if ( t1 != t )
+                printf( "Verification failed.\n" );
+            else
+                printf( "Verification succeeded.\n" );
+        }
+    }
+}
+
+
+/*=== utilTruth.c ===========================================================*/
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/misc/util/util_hack.h b/abc-build/src/misc/util/util_hack.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/util/util_hack.h
@@ -0,0 +1,46 @@
+/**CFile****************************************************************
+
+  FileName    [util_hack.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [This file is used to simulate the presence of "util.h".]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: util_hack.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__misc__util__util_hack_h
+#define ABC__misc__util__util_hack_h
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <math.h>
+
+#include "abc_global.h"
+
+ABC_NAMESPACE_HEADER_START
+
+#define NIL(type)           ((type *) 0)
+
+#define util_cpu_time       Extra_CpuTime            
+#define getSoftDataLimit    Extra_GetSoftDataLimit   
+#define MMoutOfMemory       Extra_UtilMMoutOfMemory      
+
+extern abctime              Extra_CpuTime();
+extern int                  Extra_GetSoftDataLimit();
+extern void               (*Extra_UtilMMoutOfMemory)( long size );
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/misc/vec/module.make b/abc-build/src/misc/vec/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/vec/module.make
@@ -0,0 +1,1 @@
+SRC += 
diff --git a/abc-build/src/misc/vec/vec.h b/abc-build/src/misc/vec/vec.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/vec/vec.h
@@ -0,0 +1,72 @@
+/**CFile****************************************************************
+
+  FileName    [vec.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resizable arrays.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: vec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__vec__vec_h
+#define ABC__misc__vec__vec_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "misc/util/abc_global.h"
+
+#include "vecInt.h"
+#include "vecFlt.h"
+#include "vecStr.h"
+#include "vecPtr.h"
+#include "vecVec.h"
+#include "vecAtt.h"
+#include "vecWrd.h"
+#include "vecBit.h"
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/vec/vecAtt.h b/abc-build/src/misc/vec/vecAtt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/vec/vecAtt.h
@@ -0,0 +1,298 @@
+/**CFile****************************************************************
+
+  FileName    [vecAtt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resizable arrays.]
+
+  Synopsis    [Array of user-specified attiributes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: vecAtt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__vec__vecAtt_h
+#define ABC__misc__vec__vecAtt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+// various attributes
+typedef enum { 
+    VEC_ATTR_NONE = 0,     // 0
+    VEC_ATTR_COPY,         // 1
+    VEC_ATTR_LOCAL_AIG,    // 2
+    VEC_ATTR_LOCAL_SOP,    // 3
+    VEC_ATTR_LOCAL_BDD,    // 4
+    VEC_ATTR_GLOBAL_AIG,   // 5
+    VEC_ATTR_GLOBAL_SOP,   // 6
+    VEC_ATTR_GLOBAL_BDD,   // 7
+    VEC_ATTR_LEVEL,        // 8
+    VEC_ATTR_LEVEL_REV,    // 9
+    VEC_ATTR_RETIME_LAG,   // 10
+    VEC_ATTR_FRAIG,        // 11
+    VEC_ATTR_MVVAR,        // 12
+    VEC_ATTR_DATA1,        // 13
+    VEC_ATTR_DATA2,        // 14
+    VEC_ATTR_TOTAL_NUM     // 15
+} Vec_AttrType_t;
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vec_Att_t_  Vec_Att_t;
+struct Vec_Att_t_ 
+{
+    // storage for attributes
+    int              nCap;                 // the size of array allocated
+    // Removed pArrayInt as it's not 64-bit safe, it generates compiler
+    // warnings, and it's unused.
+    void **          pArrayPtr;            // the pointer attribute array
+    // attribute specific info
+    void *           pMan;                 // the manager for this attribute
+    void (*pFuncFreeMan) (void *);         // the procedure to free the manager
+    void*(*pFuncStartObj)(void *);         // the procedure to start one attribute
+    void (*pFuncFreeObj) (void *, void *); // the procedure to free one attribute
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Att_t * Vec_AttAlloc( 
+    int nSize, void * pMan,
+    void (*pFuncFreeMan) (void *), 
+    void*(*pFuncStartObj)(void *), 
+    void (*pFuncFreeObj) (void *, void *)  )
+{
+    Vec_Att_t * p;
+    p = ABC_ALLOC( Vec_Att_t, 1 );
+    memset( p, 0, sizeof(Vec_Att_t) );
+    p->pMan          = pMan;
+    p->pFuncFreeMan  = pFuncFreeMan;
+    p->pFuncStartObj = pFuncStartObj;
+    p->pFuncFreeObj  = pFuncFreeObj;
+    p->nCap = nSize? nSize : 16;
+    p->pArrayPtr = ABC_ALLOC( void *, p->nCap );
+    memset( p->pArrayPtr, 0, sizeof(void *) * p->nCap );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void * Vec_AttFree( Vec_Att_t * p, int fFreeMan )
+{
+    void * pMan;
+    if ( p == NULL )
+        return NULL;
+    // free the attributes of objects
+    if ( p->pFuncFreeObj )
+    {
+        int i;
+        for ( i = 0; i < p->nCap; i++ )
+            if ( p->pArrayPtr[i] )
+                p->pFuncFreeObj( p->pMan, p->pArrayPtr[i] );
+    }
+    // free the memory manager
+    pMan = fFreeMan? NULL : p->pMan;
+    if ( p->pMan && fFreeMan )  
+        p->pFuncFreeMan( p->pMan );
+    ABC_FREE( p->pArrayPtr );
+    ABC_FREE( p );
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Clears the vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_AttClear( Vec_Att_t * p )
+{
+    // free the attributes of objects
+    if ( p->pFuncFreeObj )
+    {
+        int i;
+        if ( p->pFuncFreeObj )
+            for ( i = 0; i < p->nCap; i++ )
+                if ( p->pArrayPtr[i] )
+                    p->pFuncFreeObj( p->pMan, p->pArrayPtr[i] );
+    }
+    memset( p->pArrayPtr, 0, sizeof(void *) * p->nCap );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes one entry from the attribute manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_AttFreeEntry( Vec_Att_t * p, int i )
+{
+    if ( i >= p->nCap )
+        return;
+    if ( p->pMan )
+    {
+        if ( p->pArrayPtr[i] && p->pFuncFreeObj )
+            p->pFuncFreeObj( p->pMan, (void *)p->pArrayPtr[i] );
+    }
+    p->pArrayPtr[i] = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the vector to the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_AttGrow( Vec_Att_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pArrayPtr = ABC_REALLOC( void *, p->pArrayPtr, nCapMin );
+    memset( p->pArrayPtr + p->nCap, 0, sizeof(void *) * (nCapMin - p->nCap) );
+    p->nCap = nCapMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the entry into its place.]
+
+  Description [Only works if the manager is not defined.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_AttWriteEntry( Vec_Att_t * p, int i, void * pEntry )
+{
+    assert( p->pArrayPtr );
+    assert( p->pFuncStartObj == NULL );
+    if ( i >= p->nCap )
+        Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i + 10 );
+    p->pArrayPtr[i] = pEntry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void * Vec_AttEntry( Vec_Att_t * p, int i )
+{
+    assert( p->pArrayPtr );
+    if ( i >= p->nCap )
+        Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i + 10 );
+    if ( p->pArrayPtr[i] == NULL && p->pFuncStartObj )
+        p->pArrayPtr[i] = p->pFuncStartObj( p->pMan );
+    return p->pArrayPtr[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void * Vec_AttMan( Vec_Att_t * p )
+{
+    return p->pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of attributes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void ** Vec_AttArray( Vec_Att_t * p )
+{
+    return p->pArrayPtr;
+}
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/vec/vecBit.h b/abc-build/src/misc/vec/vecBit.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/vec/vecBit.h
@@ -0,0 +1,611 @@
+/**CFile****************************************************************
+
+  FileName    [vecBit.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resizable arrays.]
+
+  Synopsis    [Resizable arrays of bits.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: vecBit.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__vec__vecBit_h
+#define ABC__misc__vec__vecBit_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vec_Bit_t_       Vec_Bit_t;
+struct Vec_Bit_t_ 
+{
+    int              nCap;
+    int              nSize;
+    int *            pArray;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define Vec_BitForEachEntry( vVec, Entry, i )                                               \
+    for ( i = 0; (i < Vec_BitSize(vVec)) && (((Entry) = Vec_BitEntry(vVec, i)), 1); i++ )
+#define Vec_BitForEachEntryStart( vVec, Entry, i, Start )                                   \
+    for ( i = Start; (i < Vec_BitSize(vVec)) && (((Entry) = Vec_BitEntry(vVec, i)), 1); i++ )
+#define Vec_BitForEachEntryStop( vVec, Entry, i, Stop )                                   \
+    for ( i = 0; (i < Stop) && (((Entry) = Vec_BitEntry(vVec, i)), 1); i++ )
+#define Vec_BitForEachEntryStartStop( vVec, Entry, i, Start, Stop )                         \
+    for ( i = Start; (i < Stop) && (((Entry) = Vec_BitEntry(vVec, i)), 1); i++ )
+#define Vec_BitForEachEntryReverse( vVec, pEntry, i )                                       \
+    for ( i = Vec_BitSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_BitEntry(vVec, i)), 1); i-- )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Bit_t * Vec_BitAlloc( int nCap )
+{
+    Vec_Bit_t * p;
+    nCap = (nCap >> 5) + ((nCap & 31) > 0);
+    p = ABC_ALLOC( Vec_Bit_t, 1 );
+    p->nSize  = 0;
+    p->nCap   = nCap * 32;
+    p->pArray = nCap? ABC_ALLOC( int, nCap ) : NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given size and cleans it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Bit_t * Vec_BitStart( int nSize )
+{
+    Vec_Bit_t * p;
+    nSize = (nSize >> 5) + ((nSize & 31) > 0);
+    p = Vec_BitAlloc( nSize * 32 );
+    p->nSize = nSize * 32;
+    memset( p->pArray, 0, sizeof(int) * nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given size and cleans it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Bit_t * Vec_BitStartFull( int nSize )
+{
+    Vec_Bit_t * p;
+    nSize = (nSize >> 5) + ((nSize & 31) > 0);
+    p = Vec_BitAlloc( nSize );
+    p->nSize = nSize * 32;
+    memset( p->pArray, 0xff, sizeof(int) * nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the integer array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Bit_t * Vec_BitDup( Vec_Bit_t * pVec )
+{
+    Vec_Bit_t * p;
+    assert( (pVec->nSize & 31) == 0 );
+    p = ABC_ALLOC( Vec_Bit_t, 1 );
+    p->nSize  = pVec->nSize;
+    p->nCap   = pVec->nSize;
+    p->pArray = p->nCap? ABC_ALLOC( int, p->nCap >> 5 ) : NULL;
+    memcpy( p->pArray, pVec->pArray, sizeof(int) * (p->nCap >> 5) );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_BitFree( Vec_Bit_t * p )
+{
+    ABC_FREE( p->pArray );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_BitFreeP( Vec_Bit_t ** p )
+{
+    if ( *p == NULL )
+        return;
+    ABC_FREE( (*p)->pArray );
+    ABC_FREE( (*p) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int * Vec_BitReleaseArray( Vec_Bit_t * p )
+{
+    int * pArray = p->pArray;
+    p->nCap = 0;
+    p->nSize = 0;
+    p->pArray = NULL;
+    return pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int * Vec_BitArray( Vec_Bit_t * p )
+{
+    return p->pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_BitSize( Vec_Bit_t * p )
+{
+    return p->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_BitCap( Vec_Bit_t * p )
+{
+    return p->nCap;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline double Vec_BitMemory( Vec_Bit_t * p )
+{
+    return !p ? 0.0 : 1.0 * sizeof(int) * p->nCap + sizeof(Vec_Bit_t);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_BitEntry( Vec_Bit_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return (p->pArray[i >> 5] >> (i & 31)) & 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_BitWriteEntry( Vec_Bit_t * p, int i, int Entry )
+{
+    assert( i >= 0 && i < p->nSize );
+    if ( Entry == 1 )
+        p->pArray[i >> 5] |=  (1 << (i & 31));
+    else if ( Entry == 0 )
+        p->pArray[i >> 5] &= ~(1 << (i & 31));
+    else assert(0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_BitEntryLast( Vec_Bit_t * p )
+{
+    assert( p->nSize > 0 );
+    return Vec_BitEntry( p, p->nSize-1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the vector to the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_BitGrow( Vec_Bit_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    nCapMin = (nCapMin >> 5) + ((nCapMin & 31) > 0);
+    p->pArray = ABC_REALLOC( int, p->pArray, nCapMin ); 
+    assert( p->pArray );
+    p->nCap   = nCapMin * 32;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fills the vector with given number of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_BitFill( Vec_Bit_t * p, int nSize, int Fill )
+{
+    int i;
+    Vec_BitGrow( p, nSize );
+    nSize = (nSize >> 5) + ((nSize & 31) > 0);
+    if ( Fill == 0 )
+    {
+        for ( i = 0; i < nSize; i++ )
+            p->pArray[i] = 0;
+    }
+    else if ( Fill == 1 )
+    {
+        for ( i = 0; i < nSize; i++ )
+            p->pArray[i] = ~0;
+    }
+    else assert( 0 );
+    p->nSize = nSize * 32;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fills the vector with given number of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_BitFillExtra( Vec_Bit_t * p, int nSize, int Fill )
+{
+    int i;
+    if ( nSize <= p->nSize )
+        return;
+    if ( nSize > 2 * p->nCap )
+        Vec_BitGrow( p, nSize );
+    else if ( nSize > p->nCap )
+        Vec_BitGrow( p, 2 * p->nCap );
+
+    assert( p->nSize < nSize );
+    if ( (p->nSize >> 5) == (nSize >> 5) )
+    {
+        unsigned Mask = (~(~0 << (nSize-p->nSize)) << p->nSize);
+        if ( Fill == 1 )
+            p->pArray[nSize >> 5] |= Mask;
+        else if ( Fill == 0 )
+            p->pArray[nSize >> 5] &= ~Mask;
+        else assert( 0 );
+    }
+    else
+    {
+        unsigned Mask1 = (p->nSize & 31) ? ~0 << (p->nSize & 31) : 0;
+        unsigned Mask2 = (nSize & 31)    ? ~(~0 << (nSize & 31)) : 0;
+        int w1 = (p->nSize >> 5);
+        int w2 = (nSize >> 5);
+        if ( Fill == 1 )
+        {
+            p->pArray[w1] |= Mask1;
+            p->pArray[w2] |= Mask2;
+            for ( i = w1 + 1; i < w2; i++ )
+                p->pArray[i] = ~0;
+        }
+        else if ( Fill == 0 )
+        {
+            p->pArray[w1] &= ~Mask1;
+            p->pArray[w2] &= ~Mask2;
+            for ( i = w1 + 1; i < w2; i++ )
+                p->pArray[i] = 0;
+        }
+        else assert( 0 );
+    }
+    p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the entry even if the place not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_BitGetEntry( Vec_Bit_t * p, int i )
+{
+    Vec_BitFillExtra( p, i + 1, 0 );
+    return Vec_BitEntry( p, i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the entry even if the place does not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_BitSetEntry( Vec_Bit_t * p, int i, int Entry )
+{
+    Vec_BitFillExtra( p, i + 1, 0 );
+    Vec_BitWriteEntry( p, i, Entry );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_BitShrink( Vec_Bit_t * p, int nSizeNew )
+{
+    assert( p->nSize >= nSizeNew );
+    p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_BitClear( Vec_Bit_t * p )
+{
+    p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_BitPush( Vec_Bit_t * p, int Entry )
+{
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Vec_BitGrow( p, 16 );
+        else
+            Vec_BitGrow( p, 2 * p->nCap );
+    }
+    if ( Entry == 1 )
+        p->pArray[p->nSize >> 5] |=  (1 << (p->nSize & 31));
+    else if ( Entry == 0 )
+        p->pArray[p->nSize >> 5] &= ~(1 << (p->nSize & 31));
+    else assert( 0 );
+    p->nSize++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the last entry and removes it from the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_BitPop( Vec_Bit_t * p )
+{
+    int Entry;
+    assert( p->nSize > 0 );
+    Entry = Vec_BitEntryLast( p );
+    p->nSize--;
+    return Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_BitCountWord( unsigned uWord )
+{
+    uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555);
+    uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333);
+    uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F);
+    uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF);
+    return  (uWord & 0x0000FFFF) + (uWord>>16);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_BitCount( Vec_Bit_t * p ) 
+{
+    unsigned * pArray = (unsigned *)p->pArray;
+    int nWords = (p->nSize >> 5) + ((p->nSize & 31) > 0);
+    int i, Counter = 0;
+    if ( p->nSize & 31 )
+    {
+        assert( nWords > 0 );
+        for ( i = 0; i < nWords-1; i++ )
+            Counter += Vec_BitCountWord( pArray[i] );
+        Counter += Vec_BitCountWord( pArray[i] & ~(~0 << (p->nSize & 31)) );
+    }
+    else
+    {
+        for ( i = 0; i < nWords; i++ )
+            Counter += Vec_BitCountWord( pArray[i] );
+    }
+    return Counter;
+}
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/vec/vecFlt.h b/abc-build/src/misc/vec/vecFlt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/vec/vecFlt.h
@@ -0,0 +1,804 @@
+/**CFile****************************************************************
+
+  FileName    [vecFlt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resizable arrays.]
+
+  Synopsis    [Resizable arrays of floats.]
+
+  Author      [Aaron P. Hurst]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__vec__vecFlt_h
+#define ABC__misc__vec__vecFlt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vec_Flt_t_       Vec_Flt_t;
+struct Vec_Flt_t_ 
+{
+    int              nCap;
+    int              nSize;
+    float *          pArray;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define Vec_FltForEachEntry( vVec, Entry, i )                                               \
+    for ( i = 0; (i < Vec_FltSize(vVec)) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ )
+#define Vec_FltForEachEntryStart( vVec, Entry, i, Start )                                   \
+    for ( i = Start; (i < Vec_FltSize(vVec)) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ )
+#define Vec_FltForEachEntryStartStop( vVec, Entry, i, Start, Stop )                         \
+    for ( i = Start; (i < Stop) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ )
+#define Vec_FltForEachEntryReverse( vVec, pEntry, i )                                       \
+    for ( i = Vec_FltSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_FltEntry(vVec, i)), 1); i-- )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Flt_t * Vec_FltAlloc( int nCap )
+{
+    Vec_Flt_t * p;
+    p = ABC_ALLOC( Vec_Flt_t, 1 );
+    if ( nCap > 0 && nCap < 16 )
+        nCap = 16;
+    p->nSize  = 0;
+    p->nCap   = nCap;
+    p->pArray = p->nCap? ABC_ALLOC( float, p->nCap ) : NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given size and cleans it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Flt_t * Vec_FltStart( int nSize )
+{
+    Vec_Flt_t * p;
+    p = Vec_FltAlloc( nSize );
+    p->nSize = nSize;
+    memset( p->pArray, 0, sizeof(float) * nSize );
+    return p;
+}
+static inline Vec_Flt_t * Vec_FltStartFull( int nSize )
+{
+    Vec_Flt_t * p;
+    p = Vec_FltAlloc( nSize );
+    p->nSize = nSize;
+    memset( p->pArray, 0xFF, sizeof(float) * nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the vector from a float array of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Flt_t * Vec_FltAllocArray( float * pArray, int nSize )
+{
+    Vec_Flt_t * p;
+    p = ABC_ALLOC( Vec_Flt_t, 1 );
+    p->nSize  = nSize;
+    p->nCap   = nSize;
+    p->pArray = pArray;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the vector from a float array of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Flt_t * Vec_FltAllocArrayCopy( float * pArray, int nSize )
+{
+    Vec_Flt_t * p;
+    p = ABC_ALLOC( Vec_Flt_t, 1 );
+    p->nSize  = nSize;
+    p->nCap   = nSize;
+    p->pArray = ABC_ALLOC( float, nSize );
+    memcpy( p->pArray, pArray, sizeof(float) * nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the float array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Flt_t * Vec_FltDup( Vec_Flt_t * pVec )
+{
+    Vec_Flt_t * p;
+    p = ABC_ALLOC( Vec_Flt_t, 1 );
+    p->nSize  = pVec->nSize;
+    p->nCap   = pVec->nCap;
+    p->pArray = p->nCap? ABC_ALLOC( float, p->nCap ) : NULL;
+    memcpy( p->pArray, pVec->pArray, sizeof(float) * pVec->nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the array into another vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Flt_t * Vec_FltDupArray( Vec_Flt_t * pVec )
+{
+    Vec_Flt_t * p;
+    p = ABC_ALLOC( Vec_Flt_t, 1 );
+    p->nSize  = pVec->nSize;
+    p->nCap   = pVec->nCap;
+    p->pArray = pVec->pArray;
+    pVec->nSize  = 0;
+    pVec->nCap   = 0;
+    pVec->pArray = NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_FltFree( Vec_Flt_t * p )
+{
+    ABC_FREE( p->pArray );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_FltFreeP( Vec_Flt_t ** p )
+{
+    if ( *p == NULL )
+        return;
+    ABC_FREE( (*p)->pArray );
+    ABC_FREE( (*p) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline float * Vec_FltReleaseArray( Vec_Flt_t * p )
+{
+    float * pArray = p->pArray;
+    p->nCap = 0;
+    p->nSize = 0;
+    p->pArray = NULL;
+    return pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline float * Vec_FltArray( Vec_Flt_t * p )
+{
+    return p->pArray;
+}
+static inline float ** Vec_FltArrayP( Vec_Flt_t * p )
+{
+    return &p->pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_FltSize( Vec_Flt_t * p )
+{
+    return p->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_FltCap( Vec_Flt_t * p )
+{
+    return p->nCap;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline double Vec_FltMemory( Vec_Flt_t * p )
+{
+    return !p ? 0.0 : 1.0 * sizeof(float) * p->nCap + sizeof(Vec_Flt_t);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline float Vec_FltEntry( Vec_Flt_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray[i];
+}
+static inline float * Vec_FltEntryP( Vec_Flt_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray + i;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_FltWriteEntry( Vec_Flt_t * p, int i, float Entry )
+{
+    assert( i >= 0 && i < p->nSize );
+    p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_FltAddToEntry( Vec_Flt_t * p, int i, float Addition )
+{
+    assert( i >= 0 && i < p->nSize );
+    p->pArray[i] += Addition;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_FltUpdateEntry( Vec_Flt_t * p, int i, float Value )
+{
+    if ( Vec_FltEntry( p, i ) < Value )
+        Vec_FltWriteEntry( p, i, Value );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline float Vec_FltEntryLast( Vec_Flt_t * p )
+{
+    return p->pArray[p->nSize-1];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the vector to the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_FltGrow( Vec_Flt_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pArray = ABC_REALLOC( float, p->pArray, nCapMin ); 
+    p->nCap   = nCapMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fills the vector with given number of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_FltFill( Vec_Flt_t * p, int nSize, float Entry )
+{
+    int i;
+    Vec_FltGrow( p, nSize );
+    for ( i = 0; i < nSize; i++ )
+        p->pArray[i] = Entry;
+    p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fills the vector with given number of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_FltFillExtra( Vec_Flt_t * p, int nSize, float Fill )
+{
+    int i;
+    if ( nSize <= p->nSize )
+        return;
+    if ( nSize > 2 * p->nCap )
+        Vec_FltGrow( p, nSize );
+    else if ( nSize > p->nCap )
+        Vec_FltGrow( p, 2 * p->nCap );
+    for ( i = p->nSize; i < nSize; i++ )
+        p->pArray[i] = Fill;
+    p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_FltShrink( Vec_Flt_t * p, int nSizeNew )
+{
+    assert( p->nSize >= nSizeNew );
+    p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_FltClear( Vec_Flt_t * p )
+{
+    p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_FltPush( Vec_Flt_t * p, float Entry )
+{
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Vec_FltGrow( p, 16 );
+        else
+            Vec_FltGrow( p, 2 * p->nCap );
+    }
+    p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_FltPushOrder( Vec_Flt_t * p, float Entry )
+{
+    int i;
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Vec_FltGrow( p, 16 );
+        else
+            Vec_FltGrow( p, 2 * p->nCap );
+    }
+    p->nSize++;
+    for ( i = p->nSize-2; i >= 0; i-- )
+        if ( p->pArray[i] > Entry )
+            p->pArray[i+1] = p->pArray[i];
+        else
+            break;
+    p->pArray[i+1] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_FltPushUnique( Vec_Flt_t * p, float Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            return 1;
+    Vec_FltPush( p, Entry );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the last entry and removes it from the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline float Vec_FltPop( Vec_Flt_t * p )
+{
+    assert( p->nSize > 0 );
+    return p->pArray[--p->nSize];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_FltFind( Vec_Flt_t * p, float Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            return i;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_FltRemove( Vec_Flt_t * p, float Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            break;
+    if ( i == p->nSize )
+        return 0;
+    assert( i < p->nSize );
+    for ( i++; i < p->nSize; i++ )
+        p->pArray[i-1] = p->pArray[i];
+    p->nSize--;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline float Vec_FltFindMax( Vec_Flt_t * p )
+{
+    int i;
+    float Best;
+    if ( p->nSize == 0 )
+        return 0;
+    Best = p->pArray[0];
+    for ( i = 1; i < p->nSize; i++ )
+        if ( Best < p->pArray[i] )
+            Best = p->pArray[i];
+    return Best;
+}
+static inline float Vec_FltFindMin( Vec_Flt_t * p )
+{
+    int i;
+    float Best;
+    if ( p->nSize == 0 )
+        return 0;
+    Best = p->pArray[0];
+    for ( i = 1; i < p->nSize; i++ )
+        if ( Best > p->pArray[i] )
+            Best = p->pArray[i];
+    return Best;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if two vectors are equal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_FltEqual( Vec_Flt_t * p1, Vec_Flt_t * p2 ) 
+{
+    int i;
+    if ( p1->nSize != p2->nSize )
+        return 0;
+    for ( i = 0; i < p1->nSize; i++ )
+        if ( p1->pArray[i] != p2->pArray[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_FltPrint( Vec_Flt_t * vVec )
+{
+    int i; float Entry;
+    printf( "Vector has %d entries: {", Vec_FltSize(vVec) );
+    Vec_FltForEachEntry( vVec, Entry, i )
+        printf( " %f", Entry );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two floats.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Vec_FltSortCompare1( float * pp1, float * pp2 )
+{
+    // for some reason commenting out lines (as shown) led to crashing of the release version
+    if ( *pp1 < *pp2 )
+        return -1;
+    if ( *pp1 > *pp2 ) //
+        return 1;
+    return 0; //
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two floats.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Vec_FltSortCompare2( float * pp1, float * pp2 )
+{
+    // for some reason commenting out lines (as shown) led to crashing of the release version
+    if ( *pp1 > *pp2 )
+        return -1;
+    if ( *pp1 < *pp2 ) //
+        return 1;
+    return 0; //
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting the entries by their value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_FltSort( Vec_Flt_t * p, int fReverse )
+{
+    if ( fReverse ) 
+        qsort( (void *)p->pArray, p->nSize, sizeof(float), 
+                (int (*)(const void *, const void *)) Vec_FltSortCompare2 );
+    else
+        qsort( (void *)p->pArray, p->nSize, sizeof(float), 
+                (int (*)(const void *, const void *)) Vec_FltSortCompare1 );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
diff --git a/abc-build/src/misc/vec/vecHash.h b/abc-build/src/misc/vec/vecHash.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/vec/vecHash.h
@@ -0,0 +1,266 @@
+/**CFile****************************************************************
+
+  FileName    [vecHash.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resizable arrays.]
+
+  Synopsis    [Hashing integer pairs/triples into an integer.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: vecHash.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__vec__vecHash_h
+#define ABC__misc__vec__vecHash_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Hash_IntObj_t_ Hash_IntObj_t;
+struct Hash_IntObj_t_
+{
+    int          iData0;
+    int          iData1;
+    int          iData2;
+    int          iNext;
+};
+
+typedef struct Hash_IntMan_t_ Hash_IntMan_t;
+struct Hash_IntMan_t_
+{
+    Vec_Int_t *  vTable;      // hash table
+    Vec_Int_t *  vObjs;       // hash objects
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline Hash_IntObj_t * Hash_IntObj( Hash_IntMan_t * p, int i )           { return i ? (Hash_IntObj_t *)Vec_IntEntryP(p->vObjs, 4*i) : NULL;  }
+static inline int             Hash_IntObjData0( Hash_IntMan_t * p, int i )      { return Hash_IntObj(p, i)->iData0;                                 }
+static inline int             Hash_IntObjData1( Hash_IntMan_t * p, int i )      { return Hash_IntObj(p, i)->iData1;                                 }
+static inline int             Hash_IntObjData2( Hash_IntMan_t * p, int i )      { return Hash_IntObj(p, i)->iData2;                                 }
+
+static inline int             Hash_Int2ObjInc( Hash_IntMan_t * p, int i )             { return Hash_IntObj(p, i)->iData2++;                         }
+static inline int             Hash_Int2ObjDec( Hash_IntMan_t * p, int i )             { return --Hash_IntObj(p, i)->iData2;                         }
+static inline void            Hash_Int2ObjSetData2( Hash_IntMan_t * p, int i, int d ) { Hash_IntObj(p, i)->iData2 = d;                              }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Hashing data entries composed of nSize integers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Hash_IntMan_t * Hash_IntManStart( int nSize )
+{
+    Hash_IntMan_t * p;  nSize += 100;
+    p = ABC_CALLOC( Hash_IntMan_t, 1 );
+    p->vTable = Vec_IntStart( Abc_PrimeCudd(nSize) );
+    p->vObjs  = Vec_IntAlloc( 4*nSize );
+    Vec_IntFill( p->vObjs, 4, 0 );
+    return p;
+}
+static inline void Hash_IntManStop( Hash_IntMan_t * p )
+{
+    Vec_IntFree( p->vObjs );
+    Vec_IntFree( p->vTable );
+    ABC_FREE( p );
+}
+static inline int Hash_IntManEntryNum( Hash_IntMan_t * p )
+{
+    return Vec_IntSize(p->vObjs)/4 - 1;
+}
+static inline void Hash_IntManProfile( Hash_IntMan_t * p )
+{
+    Hash_IntObj_t * pObj;
+    int i, Count, Entry;
+    Vec_IntForEachEntry( p->vTable, Entry, i )
+    {
+        Count = 0;
+        for ( pObj = Hash_IntObj( p, Entry ); pObj; pObj = Hash_IntObj( p, pObj->iNext ) )
+            Count++;
+        printf( "%d ", Count );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Hash_Int2ManHash( int iData0, int iData1, int nTableSize )
+{
+    return (4177 * (unsigned)iData0 + 7873 * (unsigned)iData1) % (unsigned)nTableSize;
+}
+static inline int * Hash_Int2ManLookup( Hash_IntMan_t * p, int iData0, int iData1 )
+{
+    Hash_IntObj_t * pObj;
+    int * pPlace = Vec_IntEntryP( p->vTable, Hash_Int2ManHash(iData0, iData1, Vec_IntSize(p->vTable)) );
+    for ( ; (pObj = Hash_IntObj(p, *pPlace)); pPlace = &pObj->iNext )
+        if ( pObj->iData0 == iData0 && pObj->iData1 == iData1 )
+            return pPlace;
+    assert( *pPlace == 0 );
+    return pPlace;
+}
+static inline int Hash_Int2ManInsert( Hash_IntMan_t * p, int iData0, int iData1, int iData2 )
+{
+    Hash_IntObj_t * pObj;
+    int i, nObjs, * pPlace;
+    nObjs = Vec_IntSize(p->vObjs)/4;
+    if ( nObjs > Vec_IntSize(p->vTable) )
+    {
+//        printf( "Resizing...\n" );
+        Vec_IntFill( p->vTable, Abc_PrimeCudd(2*Vec_IntSize(p->vTable)), 0 );
+        for ( i = 1; i < nObjs; i++ )
+        {
+            pObj = Hash_IntObj( p, i );
+            pObj->iNext = 0;
+            pPlace = Hash_Int2ManLookup( p, pObj->iData0, pObj->iData1 );
+            assert( *pPlace == 0 );
+            *pPlace = i;
+        }
+    }
+    pPlace = Hash_Int2ManLookup( p, iData0, iData1 );
+    if ( *pPlace )
+        return *pPlace;
+    *pPlace = nObjs;
+    Vec_IntPush( p->vObjs, iData0 );
+    Vec_IntPush( p->vObjs, iData1 );
+    Vec_IntPush( p->vObjs, iData2 );
+    Vec_IntPush( p->vObjs, 0 );
+    return nObjs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Hsh_Int3ManHash( int iData0, int iData1, int iData2, int nTableSize )
+{
+    return (4177 * (unsigned)iData0 + 7873 * (unsigned)iData1 + 1699 * (unsigned)iData2) % (unsigned)nTableSize;
+}
+static inline int * Hsh_Int3ManLookup( Hash_IntMan_t * p, int iData0, int iData1, int iData2 )
+{
+    Hash_IntObj_t * pObj;
+    int * pPlace = Vec_IntEntryP( p->vTable, Hsh_Int3ManHash(iData0, iData1, iData2, Vec_IntSize(p->vTable)) );
+    for ( ; (pObj = Hash_IntObj(p, *pPlace)); pPlace = &pObj->iNext )
+        if ( pObj->iData0 == iData0 && pObj->iData1 == iData1 && pObj->iData2 == iData2 )
+            return pPlace;
+    assert( *pPlace == 0 );
+    return pPlace;
+}
+static inline int Hsh_Int3ManInsert( Hash_IntMan_t * p, int iData0, int iData1, int iData2 )
+{
+    Hash_IntObj_t * pObj;
+    int i, nObjs, * pPlace;
+    nObjs = Vec_IntSize(p->vObjs)/4;
+    if ( nObjs > Vec_IntSize(p->vTable) )
+    {
+//        printf( "Resizing...\n" );
+        Vec_IntFill( p->vTable, Abc_PrimeCudd(2*Vec_IntSize(p->vTable)), 0 );
+        for ( i = 1; i < nObjs; i++ )
+        {
+            pObj = Hash_IntObj( p, i );
+            pObj->iNext = 0;
+            pPlace = Hsh_Int3ManLookup( p, pObj->iData0, pObj->iData1, pObj->iData2 );
+            assert( *pPlace == 0 );
+            *pPlace = i;
+        }
+    }
+    pPlace = Hsh_Int3ManLookup( p, iData0, iData1, iData2 );
+    if ( *pPlace )
+        return *pPlace;
+    *pPlace = nObjs;
+    Vec_IntPush( p->vObjs, iData0 );
+    Vec_IntPush( p->vObjs, iData1 );
+    Vec_IntPush( p->vObjs, iData2 );
+    Vec_IntPush( p->vObjs, 0 );
+    return nObjs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Test procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Hash_IntManHashArrayTest()
+{
+    Hash_IntMan_t * p;
+    int RetValue;
+
+    p = Hash_IntManStart( 10 );
+
+    RetValue = Hash_Int2ManInsert( p, 10, 11, 12 );
+    assert( RetValue );
+
+    RetValue = Hash_Int2ManInsert( p, 20, 21, 22 );
+    assert( RetValue );
+
+    RetValue = Hash_Int2ManInsert( p, 10, 11, 12 );
+    assert( !RetValue );
+ 
+    Hash_IntManStop( p );
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
diff --git a/abc-build/src/misc/vec/vecHsh.h b/abc-build/src/misc/vec/vecHsh.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/vec/vecHsh.h
@@ -0,0 +1,407 @@
+/**CFile****************************************************************
+
+  FileName    [vecHsh.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resizable arrays.]
+
+  Synopsis    [Hashing vector entries.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: vecHsh.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__vec__vecHsh_h
+#define ABC__misc__vec__vecHsh_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Hsh_IntObj_t_ Hsh_IntObj_t;
+struct Hsh_IntObj_t_
+{
+    int          iData;
+    int          iNext;
+};
+
+typedef struct Hsh_IntMan_t_ Hsh_IntMan_t;
+struct Hsh_IntMan_t_
+{
+    int          nSize;       // data size
+    Vec_Int_t *  vData;       // data storage
+    Vec_Int_t *  vTable;      // hash table
+    Vec_Wrd_t *  vObjs;       // hash objects
+};
+
+
+
+typedef struct Hsh_VecObj_t_ Hsh_VecObj_t;
+struct Hsh_VecObj_t_
+{
+    int          nSize;
+    int          iNext;
+    int          pArray[0];
+};
+
+typedef struct Hsh_VecMan_t_ Hsh_VecMan_t;
+struct Hsh_VecMan_t_
+{
+    Vec_Int_t *  vTable;      // hash table
+    Vec_Int_t *  vData;       // data storage
+    Vec_Int_t *  vMap;        // mapping entries into data;
+    Vec_Int_t    vTemp;       // temporary array
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline unsigned *      Hsh_IntData( Hsh_IntMan_t * p, int iData )  { return (unsigned *)Vec_IntEntryP( p->vData, p->nSize * iData );             }
+static inline Hsh_IntObj_t *  Hsh_IntObj( Hsh_IntMan_t * p, int iObj )    { return iObj == -1 ? NULL : (Hsh_IntObj_t *)Vec_WrdEntryP( p->vObjs, iObj ); }
+static inline word            Hsh_IntWord( int iData, int iNext )         { Hsh_IntObj_t Obj = {iData, iNext}; return *((word *)&Obj);                  }
+
+static inline Hsh_VecObj_t *  Hsh_VecObj( Hsh_VecMan_t * p, int i )  { return i == -1 ? NULL : (Hsh_VecObj_t *)Vec_IntEntryP(p->vData, Vec_IntEntry(p->vMap, i));  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Hashing data entries composed of nSize integers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Hsh_IntMan_t * Hsh_IntManStart( Vec_Int_t * vData, int nSize, int nEntries )
+{
+    Hsh_IntMan_t * p;
+    p = ABC_CALLOC( Hsh_IntMan_t, 1 );
+    p->nSize  = nSize;
+    p->vData  = vData;
+    p->vTable = Vec_IntStartFull( Abc_PrimeCudd(nEntries) );
+    p->vObjs  = Vec_WrdAlloc( nEntries );
+    return p;
+}
+static inline void Hsh_IntManStop( Hsh_IntMan_t * p )
+{
+    Vec_IntFree( p->vTable );
+    Vec_WrdFree( p->vObjs );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Hsh_IntManHash( unsigned * pData, int nSize, int nTableSize )
+{
+    static int s_Primes[7] = { 4177, 5147, 5647, 6343, 7103, 7873, 8147 };
+    unsigned char * pDataC = (unsigned char *)pData;
+    int c, nChars = nSize * 4;
+    unsigned Key = 0;
+    for ( c = 0; c < nChars; c++ )
+        Key += pDataC[c] * s_Primes[c % 7];
+    return (int)(Key % nTableSize);
+}
+static inline int * Hsh_IntManLookup( Hsh_IntMan_t * p, unsigned * pData )
+{
+    Hsh_IntObj_t * pObj;
+    int * pPlace = Vec_IntEntryP( p->vTable, Hsh_IntManHash(pData, p->nSize, Vec_IntSize(p->vTable)) );
+    for ( ; (pObj = Hsh_IntObj(p, *pPlace)); pPlace = &pObj->iNext )
+        if ( !memcmp( pData, Hsh_IntData(p, pObj->iData), sizeof(int) * p->nSize ) )
+            return pPlace;
+    assert( *pPlace == -1 );
+    return pPlace;
+}
+static inline int Hsh_IntManAdd( Hsh_IntMan_t * p, int iData )
+{
+    int i, * pPlace;
+    if ( Vec_WrdSize(p->vObjs) > Vec_IntSize(p->vTable) )
+    {
+        Vec_IntFill( p->vTable, Abc_PrimeCudd(2*Vec_IntSize(p->vTable)), -1 );
+        for ( i = 0; i < Vec_WrdSize(p->vObjs); i++ )
+        {
+            pPlace = Vec_IntEntryP( p->vTable, Hsh_IntManHash(Hsh_IntData(p, i), p->nSize, Vec_IntSize(p->vTable)) );
+            Hsh_IntObj(p, i)->iNext = *pPlace;  *pPlace = i;
+        }
+    }
+    pPlace = Hsh_IntManLookup( p, Hsh_IntData(p, iData) );
+    if ( *pPlace == -1 )
+    {
+        *pPlace = Vec_WrdSize(p->vObjs);
+        Vec_WrdPush( p->vObjs, Hsh_IntWord(iData, -1) );
+        return Vec_WrdSize(p->vObjs) - 1;
+    }
+    return (word *)Hsh_IntObj(p, *pPlace) - Vec_WrdArray(p->vObjs);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Hashes data by value.]
+
+  Description [Array vData contains data entries, each of 'nSize' integers.
+  The resulting array contains the indexes of unique data entries.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Hsh_IntManHashArray( Vec_Int_t * vData, int nSize )
+{
+    Hsh_IntMan_t * p;
+    Vec_Int_t * vRes = Vec_IntAlloc( 100 );
+    int i, nEntries = Vec_IntSize(vData) / nSize;
+    assert( Vec_IntSize(vData) % nSize == 0 );
+    p = Hsh_IntManStart( vData, nSize, nEntries );
+    for ( i = 0; i < nEntries; i++ )
+        Vec_IntPush( vRes, Hsh_IntManAdd(p, i) );
+    Hsh_IntManStop( p );
+    return vRes;
+}
+static inline Vec_Int_t * Hsh_WrdManHashArray( Vec_Wrd_t * vDataW, int nSize )
+{
+    Hsh_IntMan_t * p;
+    Vec_Int_t Data = { 2*Vec_WrdCap(vDataW), 2*Vec_WrdSize(vDataW), (int *)Vec_WrdArray(vDataW) };
+    Vec_Int_t * vData = &Data;
+    Vec_Int_t * vRes = Vec_IntAlloc( 100 );
+    int i, nEntries = Vec_IntSize(vData) / (2*nSize);
+    assert( Vec_IntSize(vData) % (2*nSize) == 0 );
+    p = Hsh_IntManStart( vData, (2*nSize), nEntries );
+    for ( i = 0; i < nEntries; i++ )
+        Vec_IntPush( vRes, Hsh_IntManAdd(p, i) );
+    Hsh_IntManStop( p );
+    return vRes;
+}
+static inline Hsh_IntMan_t * Hsh_WrdManHashArrayStart( Vec_Wrd_t * vDataW, int nSize )
+{
+    Hsh_IntMan_t * p;
+    int i, nEntries = Vec_WrdSize(vDataW) / nSize;
+    Vec_Int_t * vData = Vec_IntAlloc( 2*Vec_WrdSize(vDataW) );
+    memcpy( Vec_IntArray(vData), Vec_WrdArray(vDataW), sizeof(word)*Vec_WrdSize(vDataW) );
+    vData->nSize = 2*Vec_WrdSize(vDataW);
+/*
+    for ( i = 0; i < 30; i++ )
+    {
+        extern void Extra_PrintHex( FILE * pFile, unsigned * pTruth, int nVars );
+        Extra_PrintHex( stdout, (unsigned *) Vec_WrdEntryP(vDataW, i), 6 );  printf( "  " );
+        Kit_DsdPrintFromTruth( (unsigned *) Vec_WrdEntryP(vDataW, i), 6 );   printf( "\n" );
+    }
+*/
+    assert( Vec_IntSize(vData) % (2*nSize) == 0 );
+    p = Hsh_IntManStart( vData, (2*nSize), nEntries );
+    for ( i = 0; i < nEntries; i++ )
+        Hsh_IntManAdd( p, i );
+    assert( Vec_WrdSize(p->vObjs) == nEntries );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Test procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Hsh_IntManHashArrayTest()
+{
+    Vec_Int_t * vData = Vec_IntAlloc( 10 );
+    Vec_Int_t * vRes;
+    Vec_IntPush( vData, 12 );
+    Vec_IntPush( vData, 17 );
+    Vec_IntPush( vData, 13 );
+    Vec_IntPush( vData, 12 );
+    Vec_IntPush( vData, 15 );
+    Vec_IntPush( vData, 3 );
+    Vec_IntPush( vData, 16 );
+    Vec_IntPush( vData, 16 );
+    Vec_IntPush( vData, 12 );
+    Vec_IntPush( vData, 17 );
+    Vec_IntPush( vData, 12 );
+    Vec_IntPush( vData, 12 );
+
+    vRes = Hsh_IntManHashArray( vData, 2 );
+
+    Vec_IntPrint( vData );
+    Vec_IntPrint( vRes );
+
+    Vec_IntFree( vData );
+    Vec_IntFree( vRes );
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Hashing integer arrays.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Hsh_VecMan_t * Hsh_VecManStart( int nEntries )
+{
+    Hsh_VecMan_t * p;
+    p = ABC_CALLOC( Hsh_VecMan_t, 1 );
+    p->vTable = Vec_IntStartFull( Abc_PrimeCudd(nEntries) );
+    p->vData  = Vec_IntAlloc( nEntries * 4 );
+    p->vMap   = Vec_IntAlloc( nEntries );
+    return p;
+}
+static inline void Hsh_VecManStop( Hsh_VecMan_t * p )
+{
+    Vec_IntFree( p->vTable );
+    Vec_IntFree( p->vData );
+    Vec_IntFree( p->vMap );
+    ABC_FREE( p );
+}
+static inline Vec_Int_t * Hsh_VecReadEntry( Hsh_VecMan_t * p, int i )
+{
+    Hsh_VecObj_t * pObj = Hsh_VecObj( p, i );
+    p->vTemp.nSize = p->vTemp.nCap = pObj->nSize;
+    p->vTemp.pArray = (int*)pObj + 2;
+    return &p->vTemp;
+}
+static inline int Hsh_VecSize( Hsh_VecMan_t * p )
+{
+    return Vec_IntSize(p->vMap);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Hsh_VecManHash( Vec_Int_t * vVec, int nTableSize )
+{
+    static unsigned s_Primes[7] = {4177, 5147, 5647, 6343, 7103, 7873, 8147};
+    unsigned Key = 0;
+    int i, Entry;
+    Vec_IntForEachEntry( vVec, Entry, i )
+        Key += (unsigned)Entry * s_Primes[i % 7];
+    return (int)(Key % nTableSize);
+}
+static inline int Hsh_VecManAdd( Hsh_VecMan_t * p, Vec_Int_t * vVec )
+{
+    Hsh_VecObj_t * pObj;
+    int i, Ent, * pPlace;
+    if ( Vec_IntSize(p->vMap) > Vec_IntSize(p->vTable) )
+    {
+        Vec_IntFill( p->vTable, Abc_PrimeCudd(2*Vec_IntSize(p->vTable)), -1 );
+        for ( i = 0; i < Vec_IntSize(p->vMap); i++ )
+        {
+            pPlace = Vec_IntEntryP( p->vTable, Hsh_VecManHash(Hsh_VecReadEntry(p, i), Vec_IntSize(p->vTable)) );
+            Hsh_VecObj(p, i)->iNext = *pPlace; *pPlace = i;
+        }
+    }
+    pPlace = Vec_IntEntryP( p->vTable, Hsh_VecManHash(vVec, Vec_IntSize(p->vTable)) );
+    for ( ; (pObj = Hsh_VecObj(p, *pPlace)); pPlace = &pObj->iNext )
+        if ( pObj->nSize == Vec_IntSize(vVec) && !memcmp( pObj->pArray, Vec_IntArray(vVec), sizeof(int) * pObj->nSize ) )
+            return *pPlace;
+    *pPlace = Vec_IntSize(p->vMap);
+    assert( Vec_IntSize(p->vData) % 2 == 0 );
+    Vec_IntPush( p->vMap, Vec_IntSize(p->vData) );
+    Vec_IntPush( p->vData, Vec_IntSize(vVec) );
+    Vec_IntPush( p->vData, -1 );
+    Vec_IntForEachEntry( vVec, Ent, i )
+        Vec_IntPush( p->vData, Ent );
+    if ( Vec_IntSize(vVec) & 1 )
+        Vec_IntPush( p->vData, -1 );
+    return Vec_IntSize(p->vMap) - 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Test procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Hsh_VecManHashTest()
+{
+    Hsh_VecMan_t * p;
+    Vec_Int_t * vTemp;
+    Vec_Int_t * vRes = Vec_IntAlloc( 1000 );
+    int i;
+    
+    p = Hsh_VecManStart( 5 );
+    for ( i = 0; i < 20; i++ )
+    {
+        vTemp = Vec_IntStartNatural( i );
+        Vec_IntPush( vRes, Hsh_VecManAdd( p, vTemp ) );
+        Vec_IntFree( vTemp );
+    }
+    for ( ; i > 0; i-- )
+    {
+        vTemp = Vec_IntStartNatural( i );
+        Vec_IntPush( vRes, Hsh_VecManAdd( p, vTemp ) );
+        Vec_IntFree( vTemp );
+    }
+    Vec_IntPrint( vRes );
+    Vec_IntFree( vRes );
+
+    Hsh_VecManStop( p );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
diff --git a/abc-build/src/misc/vec/vecInt.h b/abc-build/src/misc/vec/vecInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/vec/vecInt.h
@@ -0,0 +1,1808 @@
+/**CFile****************************************************************
+
+  FileName    [vecInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resizable arrays.]
+
+  Synopsis    [Resizable arrays of integers.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__vec__vecInt_h
+#define ABC__misc__vec__vecInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vec_Int_t_       Vec_Int_t;
+struct Vec_Int_t_ 
+{
+    int              nCap;
+    int              nSize;
+    int *            pArray;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define Vec_IntForEachEntry( vVec, Entry, i )                                               \
+    for ( i = 0; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ )
+#define Vec_IntForEachEntryStart( vVec, Entry, i, Start )                                   \
+    for ( i = Start; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ )
+#define Vec_IntForEachEntryStop( vVec, Entry, i, Stop )                                     \
+    for ( i = 0; (i < Stop) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ )
+#define Vec_IntForEachEntryStartStop( vVec, Entry, i, Start, Stop )                         \
+    for ( i = Start; (i < Stop) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ )
+#define Vec_IntForEachEntryReverse( vVec, pEntry, i )                                       \
+    for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_IntEntry(vVec, i)), 1); i-- )
+#define Vec_IntForEachEntryTwo( vVec1, vVec2, Entry1, Entry2, i )                           \
+    for ( i = 0; (i < Vec_IntSize(vVec1)) && (((Entry1) = Vec_IntEntry(vVec1, i)), 1) && (((Entry2) = Vec_IntEntry(vVec2, i)), 1); i++ )
+#define Vec_IntForEachEntryDouble( vVec, Entry1, Entry2, i )                                \
+    for ( i = 0; (i+1 < Vec_IntSize(vVec)) && (((Entry1) = Vec_IntEntry(vVec, i)), 1) && (((Entry2) = Vec_IntEntry(vVec, i+1)), 1); i += 2 )
+#define Vec_IntForEachEntryThisNext( vVec, This, Next, i )                                  \
+    for ( i = 0, (This) = (Next) = (Vec_IntSize(vVec) ? Vec_IntEntry(vVec, 0) : -1); (i+1 < Vec_IntSize(vVec)) && (((Next) = Vec_IntEntry(vVec, i+1)), 1); i += 2, (This) = (Next) )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntAlloc( int nCap )
+{
+    Vec_Int_t * p;
+    p = ABC_ALLOC( Vec_Int_t, 1 );
+    if ( nCap > 0 && nCap < 16 )
+        nCap = 16;
+    p->nSize  = 0;
+    p->nCap   = nCap;
+    p->pArray = p->nCap? ABC_ALLOC( int, p->nCap ) : NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given size and cleans it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntStart( int nSize )
+{
+    Vec_Int_t * p;
+    p = Vec_IntAlloc( nSize );
+    p->nSize = nSize;
+    memset( p->pArray, 0, sizeof(int) * nSize );
+    return p;
+}
+static inline Vec_Int_t * Vec_IntStartFull( int nSize )
+{
+    Vec_Int_t * p;
+    p = Vec_IntAlloc( nSize );
+    p->nSize = nSize;
+    memset( p->pArray, 0xff, sizeof(int) * nSize );
+    return p;
+}
+static inline Vec_Int_t * Vec_IntStartRange( int First, int Range )
+{
+    Vec_Int_t * p;
+    int i;
+    p = Vec_IntAlloc( Range );
+    p->nSize = Range;
+    for ( i = 0; i < Range; i++ )
+        p->pArray[i] = First + i;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given size and cleans it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntStartNatural( int nSize )
+{
+    Vec_Int_t * p;
+    int i;
+    p = Vec_IntAlloc( nSize );
+    p->nSize = nSize;
+    for ( i = 0; i < nSize; i++ )
+        p->pArray[i] = i;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the vector from an integer array of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntAllocArray( int * pArray, int nSize )
+{
+    Vec_Int_t * p;
+    p = ABC_ALLOC( Vec_Int_t, 1 );
+    p->nSize  = nSize;
+    p->nCap   = nSize;
+    p->pArray = pArray;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the vector from an integer array of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntAllocArrayCopy( int * pArray, int nSize )
+{
+    Vec_Int_t * p;
+    p = ABC_ALLOC( Vec_Int_t, 1 );
+    p->nSize  = nSize;
+    p->nCap   = nSize;
+    p->pArray = ABC_ALLOC( int, nSize );
+    memcpy( p->pArray, pArray, sizeof(int) * nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the integer array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntDup( Vec_Int_t * pVec )
+{
+    Vec_Int_t * p;
+    p = ABC_ALLOC( Vec_Int_t, 1 );
+    p->nSize  = pVec->nSize;
+    p->nCap   = pVec->nSize;
+    p->pArray = p->nCap? ABC_ALLOC( int, p->nCap ) : NULL;
+    memcpy( p->pArray, pVec->pArray, sizeof(int) * pVec->nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the array into another vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntDupArray( Vec_Int_t * pVec )
+{
+    Vec_Int_t * p;
+    p = ABC_ALLOC( Vec_Int_t, 1 );
+    p->nSize  = pVec->nSize;
+    p->nCap   = pVec->nCap;
+    p->pArray = pVec->pArray;
+    pVec->nSize  = 0;
+    pVec->nCap   = 0;
+    pVec->pArray = NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntZero( Vec_Int_t * p )
+{
+    p->pArray = NULL;
+    p->nSize = 0;
+    p->nCap = 0;
+}
+static inline void Vec_IntErase( Vec_Int_t * p )
+{
+    ABC_FREE( p->pArray );
+    p->nSize = 0;
+    p->nCap = 0;
+}
+static inline void Vec_IntFree( Vec_Int_t * p )
+{
+    ABC_FREE( p->pArray );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntFreeP( Vec_Int_t ** p )
+{
+    if ( *p == NULL )
+        return;
+    ABC_FREE( (*p)->pArray );
+    ABC_FREE( (*p) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int * Vec_IntReleaseArray( Vec_Int_t * p )
+{
+    int * pArray = p->pArray;
+    p->nCap = 0;
+    p->nSize = 0;
+    p->pArray = NULL;
+    return pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int * Vec_IntArray( Vec_Int_t * p )
+{
+    return p->pArray;
+}
+static inline int ** Vec_IntArrayP( Vec_Int_t * p )
+{
+    return &p->pArray;
+}
+static inline int * Vec_IntLimit( Vec_Int_t * p )
+{
+    return p->pArray + p->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntSize( Vec_Int_t * p )
+{
+    return p->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntCap( Vec_Int_t * p )
+{
+    return p->nCap;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline double Vec_IntMemory( Vec_Int_t * p )
+{
+    return !p ? 0.0 : 1.0 * sizeof(int) * p->nCap + sizeof(Vec_Int_t) ;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntEntry( Vec_Int_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int * Vec_IntEntryP( Vec_Int_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray + i;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntWriteEntry( Vec_Int_t * p, int i, int Entry )
+{
+    assert( i >= 0 && i < p->nSize );
+    p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntAddToEntry( Vec_Int_t * p, int i, int Addition )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray[i] += Addition;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntUpdateEntry( Vec_Int_t * p, int i, int Value )
+{
+    if ( Vec_IntEntry( p, i ) < Value )
+        Vec_IntWriteEntry( p, i, Value );
+}
+static inline void Vec_IntDowndateEntry( Vec_Int_t * p, int i, int Value )
+{
+    if ( Vec_IntEntry( p, i ) > Value )
+        Vec_IntWriteEntry( p, i, Value );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntEntryLast( Vec_Int_t * p )
+{
+    assert( p->nSize > 0 );
+    return p->pArray[p->nSize-1];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the vector to the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntGrow( Vec_Int_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pArray = ABC_REALLOC( int, p->pArray, nCapMin ); 
+    assert( p->pArray );
+    p->nCap   = nCapMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the vector to the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntGrowResize( Vec_Int_t * p, int nCapMin )
+{
+    p->nSize  = nCapMin;
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pArray = ABC_REALLOC( int, p->pArray, nCapMin ); 
+    assert( p->pArray );
+    p->nCap   = nCapMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fills the vector with given number of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntFill( Vec_Int_t * p, int nSize, int Fill )
+{
+    int i;
+    Vec_IntGrow( p, nSize );
+    for ( i = 0; i < nSize; i++ )
+        p->pArray[i] = Fill;
+    p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fills the vector with given number of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntFillExtra( Vec_Int_t * p, int nSize, int Fill )
+{
+    int i;
+    if ( nSize <= p->nSize )
+        return;
+    if ( nSize > 2 * p->nCap )
+        Vec_IntGrow( p, nSize );
+    else if ( nSize > p->nCap )
+        Vec_IntGrow( p, 2 * p->nCap );
+    for ( i = p->nSize; i < nSize; i++ )
+        p->pArray[i] = Fill;
+    p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the entry even if the place not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntGetEntry( Vec_Int_t * p, int i )
+{
+    Vec_IntFillExtra( p, i + 1, 0 );
+    return Vec_IntEntry( p, i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the entry even if the place not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int * Vec_IntGetEntryP( Vec_Int_t * p, int i )
+{
+    Vec_IntFillExtra( p, i + 1, 0 );
+    return Vec_IntEntryP( p, i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the entry even if the place does not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntSetEntry( Vec_Int_t * p, int i, int Entry )
+{
+    Vec_IntFillExtra( p, i + 1, 0 );
+    Vec_IntWriteEntry( p, i, Entry );
+}
+static inline void Vec_IntSetEntryFull( Vec_Int_t * p, int i, int Entry )
+{
+    Vec_IntFillExtra( p, i + 1, -1 );
+    Vec_IntWriteEntry( p, i, Entry );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntShrink( Vec_Int_t * p, int nSizeNew )
+{
+    assert( p->nSize >= nSizeNew );
+    p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntClear( Vec_Int_t * p )
+{
+    p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntPush( Vec_Int_t * p, int Entry )
+{
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Vec_IntGrow( p, 16 );
+        else
+            Vec_IntGrow( p, 2 * p->nCap );
+    }
+    p->pArray[p->nSize++] = Entry;
+}
+static inline void Vec_IntPushArray( Vec_Int_t * p, int * pEntries, int nEntries )
+{
+    int i;
+    for ( i = 0; i < nEntries; i++ )
+        Vec_IntPush( p, pEntries[i] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntPushFirst( Vec_Int_t * p, int Entry )
+{
+    int i;
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Vec_IntGrow( p, 16 );
+        else
+            Vec_IntGrow( p, 2 * p->nCap );
+    }
+    p->nSize++;
+    for ( i = p->nSize - 1; i >= 1; i-- )
+        p->pArray[i] = p->pArray[i-1];
+    p->pArray[0] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the entry while preserving the increasing order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntPushOrder( Vec_Int_t * p, int Entry )
+{
+    int i;
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Vec_IntGrow( p, 16 );
+        else
+            Vec_IntGrow( p, 2 * p->nCap );
+    }
+    p->nSize++;
+    for ( i = p->nSize-2; i >= 0; i-- )
+        if ( p->pArray[i] > Entry )
+            p->pArray[i+1] = p->pArray[i];
+        else
+            break;
+    p->pArray[i+1] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the entry while preserving the increasing order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntPushOrderReverse( Vec_Int_t * p, int Entry )
+{
+    int i;
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Vec_IntGrow( p, 16 );
+        else
+            Vec_IntGrow( p, 2 * p->nCap );
+    }
+    p->nSize++;
+    for ( i = p->nSize-2; i >= 0; i-- )
+        if ( p->pArray[i] < Entry )
+            p->pArray[i+1] = p->pArray[i];
+        else
+            break;
+    p->pArray[i+1] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the entry while preserving the increasing order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntPushUniqueOrder( Vec_Int_t * p, int Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            return 1;
+    Vec_IntPushOrder( p, Entry );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntPushUnique( Vec_Int_t * p, int Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            return 1;
+    Vec_IntPush( p, Entry );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the pointer to the next nWords entries in the vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned * Vec_IntFetch( Vec_Int_t * p, int nWords )
+{
+    if ( nWords == 0 )
+        return NULL;
+    assert( nWords > 0 );
+    p->nSize += nWords;
+    if ( p->nSize > p->nCap )
+    {
+//         Vec_IntGrow( p, 2 * p->nSize );
+        return NULL;
+    }
+    return ((unsigned *)p->pArray) + p->nSize - nWords;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the last entry and removes it from the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntPop( Vec_Int_t * p )
+{
+    assert( p->nSize > 0 );
+    return p->pArray[--p->nSize];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntFind( Vec_Int_t * p, int Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            return i;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntRemove( Vec_Int_t * p, int Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            break;
+    if ( i == p->nSize )
+        return 0;
+    assert( i < p->nSize );
+    for ( i++; i < p->nSize; i++ )
+        p->pArray[i-1] = p->pArray[i];
+    p->nSize--;
+    return 1;
+}
+static inline int Vec_IntRemove1( Vec_Int_t * p, int Entry )
+{
+    int i;
+    for ( i = 1; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            break;
+    if ( i >= p->nSize )
+        return 0;
+    assert( i < p->nSize );
+    for ( i++; i < p->nSize; i++ )
+        p->pArray[i-1] = p->pArray[i];
+    p->nSize--;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntDrop( Vec_Int_t * p, int i )
+{
+    int k;
+    assert( i >= 0 && i < Vec_IntSize(p) );
+    p->nSize--;
+    for ( k = i; k < p->nSize; k++ )
+        p->pArray[k] = p->pArray[k+1];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Interts entry at the index iHere. Shifts other entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntInsert( Vec_Int_t * p, int iHere, int Entry )
+{
+    int i;
+    assert( iHere >= 0 && iHere < p->nSize );
+    Vec_IntPush( p, 0 );
+    for ( i = p->nSize - 1; i > iHere; i-- )
+        p->pArray[i] = p->pArray[i-1];
+    p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntFindMax( Vec_Int_t * p )
+{
+    int i, Best;
+    if ( p->nSize == 0 )
+        return 0;
+    Best = p->pArray[0];
+    for ( i = 1; i < p->nSize; i++ )
+        if ( Best < p->pArray[i] )
+            Best = p->pArray[i];
+    return Best;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntFindMin( Vec_Int_t * p )
+{
+    int i, Best;
+    if ( p->nSize == 0 )
+        return 0;
+    Best = p->pArray[0];
+    for ( i = 1; i < p->nSize; i++ )
+        if ( Best > p->pArray[i] )
+            Best = p->pArray[i];
+    return Best;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reverses the order of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntReverseOrder( Vec_Int_t * p )
+{
+    int i, Temp;
+    for ( i = 0; i < p->nSize/2; i++ )
+    {
+        Temp = p->pArray[i];
+        p->pArray[i] = p->pArray[p->nSize-1-i];
+        p->pArray[p->nSize-1-i] = Temp;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntInvert( Vec_Int_t * p, int Fill ) 
+{
+    int Entry, i;
+    Vec_Int_t * vRes = Vec_IntAlloc( 0 );
+    if ( Vec_IntSize(p) == 0 )
+        return vRes;
+    Vec_IntFill( vRes, Vec_IntFindMax(p) + 1, Fill );
+    Vec_IntForEachEntry( p, Entry, i )
+        if ( Entry != Fill )
+            Vec_IntWriteEntry( vRes, Entry, i );
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntCondense( Vec_Int_t * p, int Fill ) 
+{
+    int Entry, i;
+    Vec_Int_t * vRes = Vec_IntAlloc( Vec_IntSize(p) );
+    Vec_IntForEachEntry( p, Entry, i )
+        if ( Entry != Fill )
+            Vec_IntPush( vRes, Entry );
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntSum( Vec_Int_t * p ) 
+{
+    int i, Counter = 0;
+    for ( i = 0; i < p->nSize; i++ )
+        Counter += p->pArray[i];
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntCountEntry( Vec_Int_t * p, int Entry ) 
+{
+    int i, Counter = 0;
+    for ( i = 0; i < p->nSize; i++ )
+        Counter += (p->pArray[i] == Entry);
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntCountPositive( Vec_Int_t * p ) 
+{
+    int i, Counter = 0;
+    for ( i = 0; i < p->nSize; i++ )
+        Counter += (p->pArray[i] > 0);
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if two vectors are equal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntEqual( Vec_Int_t * p1, Vec_Int_t * p2 ) 
+{
+    int i;
+    if ( p1->nSize != p2->nSize )
+        return 0;
+    for ( i = 0; i < p1->nSize; i++ )
+        if ( p1->pArray[i] != p2->pArray[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of common entries.]
+
+  Description [Assumes that the entries are non-negative integers that
+  are not very large, so inversion of the array can be performed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntCountCommon( Vec_Int_t * p1, Vec_Int_t * p2 ) 
+{
+    Vec_Int_t * vTemp;
+    int Entry, i, Counter = 0;
+    if ( Vec_IntSize(p1) < Vec_IntSize(p2) )
+        vTemp = p1, p1 = p2, p2 = vTemp;
+    assert( Vec_IntSize(p1) >= Vec_IntSize(p2) );
+    vTemp = Vec_IntInvert( p2, -1 );
+    Vec_IntFillExtra( vTemp, Vec_IntFindMax(p1) + 1, -1 );
+    Vec_IntForEachEntry( p1, Entry, i )
+        if ( Vec_IntEntry(vTemp, Entry) >= 0 )
+            Counter++;
+    Vec_IntFree( vTemp );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two integers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Vec_IntSortCompare1( int * pp1, int * pp2 )
+{
+    // for some reason commenting out lines (as shown) led to crashing of the release version
+    if ( *pp1 < *pp2 )
+        return -1;
+    if ( *pp1 > *pp2 ) //
+        return 1;
+    return 0; //
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two integers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Vec_IntSortCompare2( int * pp1, int * pp2 )
+{
+    // for some reason commenting out lines (as shown) led to crashing of the release version
+    if ( *pp1 > *pp2 )
+        return -1;
+    if ( *pp1 < *pp2 ) //
+        return 1;
+    return 0; //
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting the entries by their integer value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntSort( Vec_Int_t * p, int fReverse )
+{
+    if ( fReverse ) 
+        qsort( (void *)p->pArray, p->nSize, sizeof(int), 
+                (int (*)(const void *, const void *)) Vec_IntSortCompare2 );
+    else
+        qsort( (void *)p->pArray, p->nSize, sizeof(int), 
+                (int (*)(const void *, const void *)) Vec_IntSortCompare1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Leaves only unique entries.]
+
+  Description [Returns the number of duplicated entried found.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntUniqify( Vec_Int_t * p )
+{
+    int i, k, RetValue;
+    if ( p->nSize < 2 )
+        return 0;
+    Vec_IntSort( p, 0 );
+    for ( i = k = 1; i < p->nSize; i++ )
+        if ( p->pArray[i] != p->pArray[i-1] )
+            p->pArray[k++] = p->pArray[i];
+    RetValue = p->nSize - k;
+    p->nSize = k;
+    return RetValue;
+}
+static inline int Vec_IntCountDuplicates( Vec_Int_t * p )
+{
+    int RetValue;
+    Vec_Int_t * pDup = Vec_IntDup( p );
+    Vec_IntUniqify( pDup );
+    RetValue = Vec_IntSize(p) - Vec_IntSize(pDup);
+    Vec_IntFree( pDup );
+    return RetValue;
+}
+static inline int Vec_IntCheckUniqueSmall( Vec_Int_t * p )
+{
+    int i, k;
+    for ( i = 0; i < p->nSize; i++ )
+        for ( k = i+1; k < p->nSize; k++ )
+            if ( p->pArray[i] == p->pArray[k] )
+                return 0;
+    return 1;
+}
+static inline int Vec_IntCountUnique( Vec_Int_t * p )
+{
+    int i, Count = 0, Max = Vec_IntFindMax(p);
+    unsigned char * pPres = ABC_CALLOC( unsigned char, Max+1 );
+    for ( i = 0; i < p->nSize; i++ )
+        if ( pPres[p->pArray[i]] == 0 )
+            pPres[p->pArray[i]] = 1, Count++;
+    ABC_FREE( pPres );
+    return Count;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of unique entries.]
+
+  Description []
+               
+  SideEffects [] 
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Vec_IntUniqueHashKeyDebug( unsigned char * pStr, int nChars, int TableMask )
+{
+    static unsigned s_BigPrimes[4] = {12582917, 25165843, 50331653, 100663319};
+    unsigned Key = 0; int c;
+    for ( c = 0; c < nChars; c++ )
+    {
+        Key += (unsigned)pStr[c] * s_BigPrimes[c & 3];
+        printf( "%d : ", c );
+        printf( "%3d  ", pStr[c] );
+        printf( "%12u ", Key );
+        printf( "%12u ", Key&TableMask );
+        printf( "\n" );
+    }
+    return Key;
+}
+static inline void Vec_IntUniqueProfile( Vec_Int_t * vData, int * pTable, int * pNexts, int TableMask, int nIntSize )
+{
+    int i, Key, Counter;
+    for ( i = 0; i <= TableMask; i++ )
+    {
+        Counter = 0;
+        for ( Key = pTable[i]; Key != -1; Key = pNexts[Key] )
+            Counter++;
+        if ( Counter < 7 )
+            continue;
+        printf( "%d\n", Counter );
+        for ( Key = pTable[i]; Key != -1; Key = pNexts[Key] )
+        {
+//            Extra_PrintBinary( stdout, (unsigned *)Vec_IntEntryP(vData, Key*nIntSize), 40 ), printf( "\n" );
+//            Vec_IntUniqueHashKeyDebug( (unsigned char *)Vec_IntEntryP(vData, Key*nIntSize), 4*nIntSize, TableMask );
+        }
+    }
+    printf( "\n" );
+}
+
+static inline unsigned Vec_IntUniqueHashKey2( unsigned char * pStr, int nChars )
+{
+    static unsigned s_BigPrimes[4] = {12582917, 25165843, 50331653, 100663319};
+    unsigned Key = 0; int c;
+    for ( c = 0; c < nChars; c++ )
+        Key += (unsigned)pStr[c] * s_BigPrimes[c & 3];
+    return Key;
+}
+
+static inline unsigned Vec_IntUniqueHashKey( unsigned char * pStr, int nChars )
+{
+    static unsigned s_BigPrimes[16] = 
+    {
+        0x984b6ad9,0x18a6eed3,0x950353e2,0x6222f6eb,0xdfbedd47,0xef0f9023,0xac932a26,0x590eaf55,
+        0x97d0a034,0xdc36cd2e,0x22736b37,0xdc9066b0,0x2eb2f98b,0x5d9c7baf,0x85747c9e,0x8aca1055
+    };
+    static unsigned s_BigPrimes2[16] = 
+    {
+        0x8d8a5ebe,0x1e6a15dc,0x197d49db,0x5bab9c89,0x4b55dea7,0x55dede49,0x9a6a8080,0xe5e51035,
+        0xe148d658,0x8a17eb3b,0xe22e4b38,0xe5be2a9a,0xbe938cbb,0x3b981069,0x7f9c0c8e,0xf756df10
+    };
+    unsigned Key = 0; int c;
+    for ( c = 0; c < nChars; c++ )
+        Key += s_BigPrimes2[(2*c)&15]   * s_BigPrimes[(unsigned)pStr[c] & 15] +
+               s_BigPrimes2[(2*c+1)&15] * s_BigPrimes[(unsigned)pStr[c] >> 4];
+    return Key;
+}
+static inline int * Vec_IntUniqueLookup( Vec_Int_t * vData, int i, int nIntSize, int * pNexts, int * pStart )
+{
+    int * pData = Vec_IntEntryP( vData, i*nIntSize );
+    for ( ; *pStart != -1; pStart = pNexts + *pStart )
+        if ( !memcmp( pData, Vec_IntEntryP(vData, *pStart*nIntSize), sizeof(int) * nIntSize ) )
+            return pStart;
+    return pStart;
+}
+static inline int Vec_IntUniqueCount( Vec_Int_t * vData, int nIntSize, Vec_Int_t ** pvMap )
+{
+    int nEntries  = Vec_IntSize(vData) / nIntSize;
+    int TableMask = (1 << Abc_Base2Log(nEntries)) - 1;
+    int * pTable  = ABC_FALLOC( int, TableMask+1 );
+    int * pNexts  = ABC_FALLOC( int, TableMask+1 );
+    int * pClass  = ABC_ALLOC( int, nEntries );
+    int i, Key, * pEnt, nUnique = 0;
+    assert( nEntries * nIntSize == Vec_IntSize(vData) );
+    for ( i = 0; i < nEntries; i++ )
+    {
+        pEnt = Vec_IntEntryP( vData, i*nIntSize );
+        Key  = TableMask & Vec_IntUniqueHashKey( (unsigned char *)pEnt, 4*nIntSize );
+        pEnt = Vec_IntUniqueLookup( vData, i, nIntSize, pNexts, pTable+Key );
+        if ( *pEnt == -1 )
+            *pEnt = i, nUnique++;
+        pClass[i] = *pEnt;
+    }
+//    Vec_IntUniqueProfile( vData, pTable, pNexts, TableMask, nIntSize );
+    ABC_FREE( pTable );
+    ABC_FREE( pNexts );
+    if ( pvMap )
+        *pvMap = Vec_IntAllocArray( pClass, nEntries );
+    else
+        ABC_FREE( pClass );
+    return nUnique;
+}
+static inline Vec_Int_t * Vec_IntUniqifyHash( Vec_Int_t * vData, int nIntSize )
+{
+    Vec_Int_t * vMap, * vUnique;
+    int i, Ent, nUnique = Vec_IntUniqueCount( vData, nIntSize, &vMap );
+    vUnique = Vec_IntAlloc( nUnique * nIntSize );
+    Vec_IntForEachEntry( vMap, Ent, i )
+    {
+        if ( Ent < i ) continue;
+        assert( Ent == i );
+        Vec_IntPushArray( vUnique, Vec_IntEntryP(vData, i*nIntSize), nIntSize );
+    }
+    assert( Vec_IntSize(vUnique) == nUnique * nIntSize );
+    Vec_IntFree( vMap );
+    return vUnique;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two integers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntSortCompareUnsigned( unsigned * pp1, unsigned * pp2 )
+{
+    if ( *pp1 < *pp2 )
+        return -1;
+    if ( *pp1 > *pp2 )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting the entries by their integer value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntSortUnsigned( Vec_Int_t * p )
+{
+    qsort( (void *)p->pArray, p->nSize, sizeof(int), 
+            (int (*)(const void *, const void *)) Vec_IntSortCompareUnsigned );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of common entries.]
+
+  Description [Assumes that the vectors are sorted in the increasing order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntTwoCountCommon( Vec_Int_t * vArr1, Vec_Int_t * vArr2 )
+{
+    int * pBeg1 = vArr1->pArray;
+    int * pBeg2 = vArr2->pArray;
+    int * pEnd1 = vArr1->pArray + vArr1->nSize;
+    int * pEnd2 = vArr2->pArray + vArr2->nSize;
+    int Counter = 0;
+    while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+    {
+        if ( *pBeg1 == *pBeg2 )
+            pBeg1++, pBeg2++, Counter++;
+        else if ( *pBeg1 < *pBeg2 )
+            pBeg1++;
+        else 
+            pBeg2++;
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects common entries.]
+
+  Description [Assumes that the vectors are sorted in the increasing order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntTwoFindCommon( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vArr )
+{
+    int * pBeg1 = vArr1->pArray;
+    int * pBeg2 = vArr2->pArray;
+    int * pEnd1 = vArr1->pArray + vArr1->nSize;
+    int * pEnd2 = vArr2->pArray + vArr2->nSize;
+    Vec_IntClear( vArr );
+    while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+    {
+        if ( *pBeg1 == *pBeg2 )
+            Vec_IntPush( vArr, *pBeg1 ), pBeg1++, pBeg2++;
+        else if ( *pBeg1 < *pBeg2 )
+            pBeg1++;
+        else 
+            pBeg2++;
+    }
+    return Vec_IntSize(vArr);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects and removes common entries]
+
+  Description [Assumes that the vectors are sorted in the increasing order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntTwoRemoveCommon( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vArr )
+{
+    int * pBeg1 = vArr1->pArray;
+    int * pBeg2 = vArr2->pArray;
+    int * pEnd1 = vArr1->pArray + vArr1->nSize;
+    int * pEnd2 = vArr2->pArray + vArr2->nSize;
+    int * pBeg1New = vArr1->pArray;
+    int * pBeg2New = vArr2->pArray;
+    Vec_IntClear( vArr );
+    while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+    {
+        if ( *pBeg1 == *pBeg2 )
+            Vec_IntPush( vArr, *pBeg1 ), pBeg1++, pBeg2++;
+        else if ( *pBeg1 < *pBeg2 )
+            *pBeg1New++ = *pBeg1++;
+        else 
+            *pBeg2New++ = *pBeg2++;
+    }
+    while ( pBeg1 < pEnd1 )
+        *pBeg1New++ = *pBeg1++;
+    while ( pBeg2 < pEnd2 )
+        *pBeg2New++ = *pBeg2++;
+    Vec_IntShrink( vArr1, pBeg1New - vArr1->pArray );
+    Vec_IntShrink( vArr2, pBeg2New - vArr2->pArray );
+    return Vec_IntSize(vArr);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes entries of the second one from the first one.]
+
+  Description [Assumes that the vectors are sorted in the increasing order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntTwoRemove( Vec_Int_t * vArr1, Vec_Int_t * vArr2 )
+{
+    int * pBeg1 = vArr1->pArray;
+    int * pBeg2 = vArr2->pArray;
+    int * pEnd1 = vArr1->pArray + vArr1->nSize;
+    int * pEnd2 = vArr2->pArray + vArr2->nSize;
+    int * pBeg1New = vArr1->pArray;
+    while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+    {
+        if ( *pBeg1 == *pBeg2 )
+            pBeg1++, pBeg2++;
+        else if ( *pBeg1 < *pBeg2 )
+            *pBeg1New++ = *pBeg1++;
+        else 
+            pBeg2++;
+    }
+    while ( pBeg1 < pEnd1 )
+        *pBeg1New++ = *pBeg1++;
+    Vec_IntShrink( vArr1, pBeg1New - vArr1->pArray );
+    return Vec_IntSize(vArr1);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the result of merging the two vectors.]
+
+  Description [Assumes that the vectors are sorted in the increasing order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntTwoMerge2Int( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vArr )
+{
+    int * pBeg  = vArr->pArray;
+    int * pBeg1 = vArr1->pArray;
+    int * pBeg2 = vArr2->pArray;
+    int * pEnd1 = vArr1->pArray + vArr1->nSize;
+    int * pEnd2 = vArr2->pArray + vArr2->nSize;
+    while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+    {
+        if ( *pBeg1 == *pBeg2 )
+            *pBeg++ = *pBeg1++, pBeg2++;
+        else if ( *pBeg1 < *pBeg2 )
+            *pBeg++ = *pBeg1++;
+        else 
+            *pBeg++ = *pBeg2++;
+    }
+    while ( pBeg1 < pEnd1 )
+        *pBeg++ = *pBeg1++;
+    while ( pBeg2 < pEnd2 )
+        *pBeg++ = *pBeg2++;
+    vArr->nSize = pBeg - vArr->pArray;
+    assert( vArr->nSize <= vArr->nCap );
+    assert( vArr->nSize >= vArr1->nSize );
+    assert( vArr->nSize >= vArr2->nSize );
+}
+static inline Vec_Int_t * Vec_IntTwoMerge( Vec_Int_t * vArr1, Vec_Int_t * vArr2 )
+{
+    Vec_Int_t * vArr = Vec_IntAlloc( vArr1->nSize + vArr2->nSize ); 
+    Vec_IntTwoMerge2Int( vArr1, vArr2, vArr );
+    return vArr;
+}
+static inline void Vec_IntTwoMerge2( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vArr )
+{
+    Vec_IntGrow( vArr, Vec_IntSize(vArr1) + Vec_IntSize(vArr2) );
+    Vec_IntTwoMerge2Int( vArr1, vArr2, vArr );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the result of splitting of the two vectors.]
+
+  Description [Assumes that the vectors are sorted in the increasing order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntTwoSplit( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vArr, Vec_Int_t * vArr1n, Vec_Int_t * vArr2n )
+{
+    int * pBeg1 = vArr1->pArray;
+    int * pBeg2 = vArr2->pArray;
+    int * pEnd1 = vArr1->pArray + vArr1->nSize;
+    int * pEnd2 = vArr2->pArray + vArr2->nSize;
+    while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+    {
+        if ( *pBeg1 == *pBeg2 )
+            Vec_IntPush( vArr, *pBeg1++ ), pBeg2++;
+        else if ( *pBeg1 < *pBeg2 )
+            Vec_IntPush( vArr1n, *pBeg1++ );
+        else 
+            Vec_IntPush( vArr2n, *pBeg2++ );
+    }
+    while ( pBeg1 < pEnd1 )
+        Vec_IntPush( vArr1n, *pBeg1++ );
+    while ( pBeg2 < pEnd2 )
+        Vec_IntPush( vArr2n, *pBeg2++ );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntSelectSort( int * pArray, int nSize )
+{
+    int temp, i, j, best_i;
+    for ( i = 0; i < nSize-1; i++ )
+    {
+        best_i = i;
+        for ( j = i+1; j < nSize; j++ )
+            if ( pArray[j] < pArray[best_i] )
+                best_i = j;
+        temp = pArray[i]; 
+        pArray[i] = pArray[best_i]; 
+        pArray[best_i] = temp;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntSelectSortCost( int * pArray, int nSize, Vec_Int_t * vCosts )
+{
+    int i, j, best_i;
+    for ( i = 0; i < nSize-1; i++ )
+    {
+        best_i = i;
+        for ( j = i+1; j < nSize; j++ )
+            if ( Vec_IntEntry(vCosts, pArray[j]) < Vec_IntEntry(vCosts, pArray[best_i]) )
+                best_i = j;
+        ABC_SWAP( int, pArray[i], pArray[best_i] );
+    }
+}
+static inline void Vec_IntSelectSortCost2( int * pArray, int nSize, int * pCosts )
+{
+    int i, j, best_i;
+    for ( i = 0; i < nSize-1; i++ )
+    {
+        best_i = i;
+        for ( j = i+1; j < nSize; j++ )
+            if ( pCosts[j] < pCosts[best_i] )
+                best_i = j;
+        ABC_SWAP( int, pArray[i], pArray[best_i] );
+        ABC_SWAP( int, pCosts[i], pCosts[best_i] );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntPrint( Vec_Int_t * vVec )
+{
+    int i, Entry;
+    printf( "Vector has %d entries: {", Vec_IntSize(vVec) );
+    Vec_IntForEachEntry( vVec, Entry, i )
+        printf( " %d", Entry );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_IntCompareVec( Vec_Int_t * p1, Vec_Int_t * p2 )
+{
+    if ( p1 == NULL || p2 == NULL )
+        return (p1 != NULL) - (p2 != NULL);
+    if ( Vec_IntSize(p1) != Vec_IntSize(p2) )
+        return Vec_IntSize(p1) - Vec_IntSize(p2);
+    return memcmp( Vec_IntArray(p1), Vec_IntArray(p2), sizeof(int)*Vec_IntSize(p1) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Appends the contents of the second vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntAppend( Vec_Int_t * vVec1, Vec_Int_t * vVec2 )
+{
+    int Entry, i;
+    Vec_IntForEachEntry( vVec2, Entry, i )
+        Vec_IntPush( vVec1, Entry );
+}
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/vec/vecMem.h b/abc-build/src/misc/vec/vecMem.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/vec/vecMem.h
@@ -0,0 +1,423 @@
+/**CFile****************************************************************
+
+  FileName    [vecMem.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resizable arrays.]
+
+  Synopsis    [Resizable array of memory pieces.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - July 20, 2012.]
+
+  Revision    [$Id: vecMem.h,v 1.00 2012/07/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__vec__vecMem_h
+#define ABC__misc__vec__vecMem_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+ABC_NAMESPACE_HEADER_START
+
+/* 
+   This vector stores pieces of memory of the given size.
+   It is useful for representing truth tables and any other objects
+   of the fixed size.  It is better that Extra_MmFixed because the
+   entry IDs can be used as handles to retrieve memory pieces without 
+   the need for an array of pointers from entry IDs into memory pieces
+   (this can save 8(4) bytes per object on a 64(32)-bit platform).
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vec_Mem_t_       Vec_Mem_t;
+struct Vec_Mem_t_ 
+{
+    int              nEntrySize;  // entry size (in terms of 8-byte words)
+    int              nEntries;    // number of entries currently used
+    int              LogPageSze;  // log2 of page size (in terms of entries)
+    int              PageMask;    // page mask
+    int              nPageAlloc;  // number of pages currently allocated
+    int              iPage;       // the number of a page currently used   
+    word **          ppPages;     // memory pages
+    Vec_Int_t *      vTable;      // hash table
+    Vec_Int_t *      vNexts;      // next pointers
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define Vec_MemForEachEntry( p, pEntry, i )                                              \
+    for ( i = 0; (i < Vec_MemEntryNum(p)) && ((pEntry) = Vec_MemReadEntry(p, i)); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a memory vector.]
+
+  Description [Entry size is in terms of 8-byte words. Page size is log2
+  of the number of entries on one page.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Mem_t * Vec_MemAlloc( int nEntrySize, int LogPageSze )
+{
+    Vec_Mem_t * p;
+    p = ABC_CALLOC( Vec_Mem_t, 1 );
+    p->nEntrySize = nEntrySize;
+    p->LogPageSze = LogPageSze;
+    p->PageMask   = (1 << p->LogPageSze) - 1;
+    p->iPage      = -1;
+    return p;
+}
+static inline void Vec_MemFree( Vec_Mem_t * p )
+{
+    int i;
+    for ( i = 0; i <= p->iPage; i++ )
+        ABC_FREE( p->ppPages[i] );
+    ABC_FREE( p->ppPages );
+    ABC_FREE( p );
+}
+static inline void Vec_MemFreeP( Vec_Mem_t ** p )
+{
+    if ( *p == NULL )
+        return;
+    Vec_MemFree( *p );
+    *p = NULL;
+}
+static inline Vec_Mem_t * Vec_MemDup( Vec_Mem_t * pVec )
+{
+    Vec_Mem_t * p = NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the integer array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_MemFill( Vec_Mem_t * pVec, int nEntries )
+{
+}
+static inline void Vec_MemClean( Vec_Mem_t * pVec, int nEntries )
+{
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_MemEntrySize( Vec_Mem_t * p )
+{
+    return p->nEntrySize;
+}
+static inline int Vec_MemEntryNum( Vec_Mem_t * p )
+{
+    return p->nEntries;
+}
+static inline int Vec_MemPageSize( Vec_Mem_t * p )
+{
+    return p->LogPageSze;
+}
+static inline int Vec_MemPageNum( Vec_Mem_t * p )
+{
+    return p->iPage+1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline double Vec_MemMemory( Vec_Mem_t * p )
+{
+    return (double)sizeof(word) * p->nEntrySize * (1 << p->LogPageSze) * (p->iPage + 1) + (double)sizeof(word *) * p->nPageAlloc + (double)sizeof(Vec_Mem_t);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word * Vec_MemReadEntry( Vec_Mem_t * p, int i )
+{
+    assert( i >= 0 && i < p->nEntries );
+    return p->ppPages[i >> p->LogPageSze] + p->nEntrySize * (i & p->PageMask);
+}
+static inline word * Vec_MemReadEntryLast( Vec_Mem_t * p )
+{
+    assert( p->nEntries > 0 );
+    return Vec_MemReadEntry( p, p->nEntries-1 );
+}
+static inline void Vec_MemWriteEntry( Vec_Mem_t * p, int i, word * pEntry )
+{
+    word * pPlace = Vec_MemReadEntry( p, i );
+    memmove( pPlace, pEntry, sizeof(word) * p->nEntrySize );
+}
+static inline word * Vec_MemGetEntry( Vec_Mem_t * p, int i )
+{
+    assert( i >= 0 );
+    if ( i >= p->nEntries )
+    {
+        int k, iPageNew = (i >> p->LogPageSze);
+        if ( p->iPage < iPageNew )
+        {
+            // realloc page pointers if needed
+            if ( iPageNew >= p->nPageAlloc )
+                p->ppPages = ABC_REALLOC( word *, p->ppPages, (p->nPageAlloc = p->nPageAlloc ? 2 * p->nPageAlloc : iPageNew + 32) );
+            // allocate new pages if needed
+            for ( k = p->iPage + 1; k <= iPageNew; k++ )
+                p->ppPages[k] = ABC_ALLOC( word, p->nEntrySize * (1 << p->LogPageSze) );
+            // update page counter
+            p->iPage = iPageNew;
+        }
+        // update entry counter
+        p->nEntries = i + 1;
+    }
+    return Vec_MemReadEntry( p, i );
+}
+static inline void Vec_MemSetEntry( Vec_Mem_t * p, int i, word * pEntry )
+{
+    word * pPlace = Vec_MemGetEntry( p, i );
+    memmove( pPlace, pEntry, sizeof(word) * p->nEntrySize );
+}
+static inline void Vec_MemPush( Vec_Mem_t * p, word * pEntry )
+{
+    word * pPlace = Vec_MemGetEntry( p, p->nEntries );
+    memmove( pPlace, pEntry, sizeof(word) * p->nEntrySize );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_MemShrink( Vec_Mem_t * p, int nEntriesNew )
+{
+    int i, iPageOld = p->iPage;
+    assert( nEntriesNew <= p->nEntries );
+    p->nEntries = nEntriesNew;
+    p->iPage = (nEntriesNew >> p->LogPageSze);
+    for ( i = p->iPage + 1; i <= iPageOld; i++ )
+        ABC_FREE( p->ppPages[i] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_MemDumpDigit( FILE * pFile, int HexDigit )
+{
+    assert( HexDigit >= 0 && HexDigit < 16 );
+    if ( HexDigit < 10 )
+        fprintf( pFile, "%d", HexDigit );
+    else
+        fprintf( pFile, "%c", 'A' + HexDigit-10 );
+}
+static inline void Vec_MemDump( FILE * pFile, Vec_Mem_t * pVec )
+{
+    word * pEntry;
+    int i, w, d;
+    if ( pFile == stdout )
+        printf( "Memory vector has %d entries: \n", Vec_MemEntryNum(pVec) );
+    Vec_MemForEachEntry( pVec, pEntry, i )
+    {
+        for ( w = pVec->nEntrySize - 1; w >= 0; w-- )
+            for ( d = 15; d >= 0; d-- )
+                Vec_MemDumpDigit( pFile, (int)(pEntry[w] >> (d<<2)) & 15 );
+        fprintf( pFile, "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Hashing entries in the memory vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_MemHashAlloc( Vec_Mem_t * p, int nTableSize )
+{
+    assert( p->vTable == NULL && p->vNexts == NULL );
+    p->vTable = Vec_IntStartFull( Abc_PrimeCudd(nTableSize) );
+    p->vNexts = Vec_IntAlloc( nTableSize );
+}
+static inline void Vec_MemHashFree( Vec_Mem_t * p )
+{
+    if ( p == NULL )
+        return;
+    Vec_IntFreeP( &p->vTable );
+    Vec_IntFreeP( &p->vNexts );
+}
+static inline unsigned Vec_MemHashKey( Vec_Mem_t * p, word * pEntry )
+{
+    static int s_Primes[8] = { 1699, 4177, 5147, 5647, 6343, 7103, 7873, 8147 };
+    int i, nData = 2 * p->nEntrySize;
+    unsigned * pData = (unsigned *)pEntry;
+    unsigned uHash = 0;
+    for ( i = 0; i < nData; i++ )
+        uHash += pData[i] * s_Primes[i & 0x7];
+    return uHash % Vec_IntSize(p->vTable);
+}
+static int * Vec_MemHashLookup( Vec_Mem_t * p, word * pEntry )
+{
+    int * pSpot = Vec_IntEntryP( p->vTable, Vec_MemHashKey(p, pEntry) );
+    for ( ; *pSpot != -1; pSpot = Vec_IntEntryP(p->vNexts, *pSpot) )
+        if ( !memcmp( Vec_MemReadEntry(p, *pSpot), pEntry, sizeof(word) * p->nEntrySize ) ) // equal
+            return pSpot;
+    return pSpot;
+}
+static void Vec_MemHashResize( Vec_Mem_t * p )
+{
+    word * pEntry;
+    int i, * pSpot;
+    Vec_IntFill( p->vTable, Abc_PrimeCudd(2 * Vec_IntSize(p->vTable)), -1 );
+    Vec_IntClear( p->vNexts );
+    Vec_MemForEachEntry( p, pEntry, i )
+    {
+        pSpot = Vec_MemHashLookup( p, pEntry );
+        assert( *pSpot == -1 );
+        *pSpot = Vec_IntSize(p->vNexts);
+        Vec_IntPush( p->vNexts, -1 );
+    }
+    assert( p->nEntries == Vec_IntSize(p->vNexts) );
+}
+static int Vec_MemHashInsert( Vec_Mem_t * p, word * pEntry )
+{
+    int * pSpot;
+    if ( p->nEntries > Vec_IntSize(p->vTable) )
+        Vec_MemHashResize( p );
+    pSpot = Vec_MemHashLookup( p, pEntry );
+    if ( *pSpot != -1 )
+        return *pSpot;
+    *pSpot = Vec_IntSize(p->vNexts);
+    Vec_IntPush( p->vNexts, -1 );
+    Vec_MemPush( p, pEntry );
+    assert( p->nEntries == Vec_IntSize(p->vNexts) );
+    return Vec_IntSize(p->vNexts) - 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates memory vector for storing truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Mem_t * Vec_MemAllocForTT( int nVars, int fCompl )
+{
+    int Value, nWords = (nVars <= 6 ? 1 : (1 << (nVars - 6)));
+    word * uTruth = ABC_ALLOC( word, nWords ); 
+    Vec_Mem_t * vTtMem = Vec_MemAlloc( nWords, 12 );
+    Vec_MemHashAlloc( vTtMem, 10000 );
+    memset( uTruth, 0x00, sizeof(word) * nWords );
+    Value = Vec_MemHashInsert( vTtMem, uTruth ); assert( Value == 0 );
+    if ( fCompl )
+        memset( uTruth, 0x55, sizeof(word) * nWords );
+    else
+        memset( uTruth, 0xAA, sizeof(word) * nWords );
+    Value = Vec_MemHashInsert( vTtMem, uTruth ); assert( Value == 1 );
+    ABC_FREE( uTruth );
+    return vTtMem;
+}
+static inline void Vec_MemAddMuxTT( Vec_Mem_t * p, int nVars )
+{
+    int Value, nWords = (nVars <= 6 ? 1 : (1 << (nVars - 6)));
+    word * uTruth = ABC_ALLOC( word, nWords ); 
+    memset( uTruth, 0xCA, sizeof(word) * nWords );
+    Value = Vec_MemHashInsert( p, uTruth ); assert( Value == 2 );
+    ABC_FREE( uTruth );
+}
+static inline void Vec_MemDumpTruthTables( Vec_Mem_t * p, char * pName, int nLutSize )
+{
+    FILE * pFile;
+    char pFileName[1000];
+    sprintf( pFileName, "tt_%s_%02d.txt", pName ? pName : NULL, nLutSize );
+    pFile = pName ? fopen( pFileName, "wb" ) : stdout;
+    Vec_MemDump( pFile, p );
+    if ( pFile != stdout )
+        fclose( pFile );
+    printf( "Dumped %d %d-var truth tables into file \"%s\" (%.2f MB).\n", 
+        Vec_MemEntryNum(p), nLutSize, pName ? pFileName : "stdout",
+        8.0 * Vec_MemEntryNum(p) * Vec_MemEntrySize(p) / (1 << 20) );
+}
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/vec/vecPtr.h b/abc-build/src/misc/vec/vecPtr.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/vec/vecPtr.h
@@ -0,0 +1,1102 @@
+/**CFile****************************************************************
+
+  FileName    [vecPtr.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resizable arrays.]
+
+  Synopsis    [Resizable arrays of generic pointers.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: vecPtr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__vec__vecPtr_h
+#define ABC__misc__vec__vecPtr_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vec_Ptr_t_       Vec_Ptr_t;
+struct Vec_Ptr_t_ 
+{
+    int              nCap;
+    int              nSize;
+    void **          pArray;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+// iterators through entries
+#define Vec_PtrForEachEntry( Type, vVec, pEntry, i )                                               \
+    for ( i = 0; (i < Vec_PtrSize(vVec)) && (((pEntry) = (Type)Vec_PtrEntry(vVec, i)), 1); i++ )
+#define Vec_PtrForEachEntryStart( Type, vVec, pEntry, i, Start )                                   \
+    for ( i = Start; (i < Vec_PtrSize(vVec)) && (((pEntry) = (Type)Vec_PtrEntry(vVec, i)), 1); i++ )
+#define Vec_PtrForEachEntryStop( Type, vVec, pEntry, i, Stop )                                     \
+    for ( i = 0; (i < Stop) && (((pEntry) = (Type)Vec_PtrEntry(vVec, i)), 1); i++ )
+#define Vec_PtrForEachEntryStartStop( Type, vVec, pEntry, i, Start, Stop )                         \
+    for ( i = Start; (i < Stop) && (((pEntry) = (Type)Vec_PtrEntry(vVec, i)), 1); i++ )
+#define Vec_PtrForEachEntryReverse( Type, vVec, pEntry, i )                                        \
+    for ( i = Vec_PtrSize(vVec) - 1; (i >= 0) && (((pEntry) = (Type)Vec_PtrEntry(vVec, i)), 1); i-- )
+#define Vec_PtrForEachEntryTwo( Type1, vVec1, Type2, vVec2, pEntry1, pEntry2, i )                  \
+    for ( i = 0; (i < Vec_PtrSize(vVec1)) && (((pEntry1) = (Type1)Vec_PtrEntry(vVec1, i)), 1) && (((pEntry2) = (Type2)Vec_PtrEntry(vVec2, i)), 1); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrAlloc( int nCap )
+{
+    Vec_Ptr_t * p;
+    p = ABC_ALLOC( Vec_Ptr_t, 1 );
+    if ( nCap > 0 && nCap < 8 )
+        nCap = 8;
+    p->nSize  = 0;
+    p->nCap   = nCap;
+    p->pArray = p->nCap? ABC_ALLOC( void *, p->nCap ) : NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given size and cleans it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrStart( int nSize )
+{
+    Vec_Ptr_t * p;
+    p = Vec_PtrAlloc( nSize );
+    p->nSize = nSize;
+    memset( p->pArray, 0, sizeof(void *) * nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the vector from an integer array of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrAllocArray( void ** pArray, int nSize )
+{
+    Vec_Ptr_t * p;
+    p = ABC_ALLOC( Vec_Ptr_t, 1 );
+    p->nSize  = nSize;
+    p->nCap   = nSize;
+    p->pArray = pArray;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the vector from an integer array of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrAllocArrayCopy( void ** pArray, int nSize )
+{
+    Vec_Ptr_t * p;
+    p = ABC_ALLOC( Vec_Ptr_t, 1 );
+    p->nSize  = nSize;
+    p->nCap   = nSize;
+    p->pArray = ABC_ALLOC( void *, nSize );
+    memcpy( p->pArray, pArray, sizeof(void *) * nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the integer array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrDup( Vec_Ptr_t * pVec )
+{
+    Vec_Ptr_t * p;
+    p = ABC_ALLOC( Vec_Ptr_t, 1 );
+    p->nSize  = pVec->nSize;
+    p->nCap   = pVec->nCap;
+    p->pArray = p->nCap? ABC_ALLOC( void *, p->nCap ) : NULL;
+    memcpy( p->pArray, pVec->pArray, sizeof(void *) * pVec->nSize );
+    return p;
+}
+static inline Vec_Ptr_t * Vec_PtrDupStr( Vec_Ptr_t * pVec )
+{
+    int i;
+    Vec_Ptr_t * p = Vec_PtrDup( pVec );
+    for ( i = 0; i < p->nSize; i++ )
+        p->pArray[i] = Abc_UtilStrsav( (char *)p->pArray[i] );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the array into another vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrDupArray( Vec_Ptr_t * pVec )
+{
+    Vec_Ptr_t * p;
+    p = ABC_ALLOC( Vec_Ptr_t, 1 );
+    p->nSize  = pVec->nSize;
+    p->nCap   = pVec->nCap;
+    p->pArray = pVec->pArray;
+    pVec->nSize  = 0;
+    pVec->nCap   = 0;
+    pVec->pArray = NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrFree( Vec_Ptr_t * p )
+{
+    ABC_FREE( p->pArray );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrFreeP( Vec_Ptr_t ** p )
+{
+    if ( *p == NULL )
+        return;
+    ABC_FREE( (*p)->pArray );
+    ABC_FREE( (*p) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void ** Vec_PtrReleaseArray( Vec_Ptr_t * p )
+{
+    void ** pArray = p->pArray;
+    p->nCap = 0;
+    p->nSize = 0;
+    p->pArray = NULL;
+    return pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void ** Vec_PtrArray( Vec_Ptr_t * p )
+{
+    return p->pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_PtrSize( Vec_Ptr_t * p )
+{
+    return p->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_PtrCap( Vec_Ptr_t * p )
+{
+    return p->nCap;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline double Vec_PtrMemory( Vec_Ptr_t * p )
+{
+    return !p ? 0.0 : 1.0 * sizeof(void *) * p->nCap + sizeof(Vec_Ptr_t);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_PtrCountZero( Vec_Ptr_t * p ) 
+{
+    int i, Counter = 0;
+    for ( i = 0; i < p->nSize; i++ )
+        Counter += (p->pArray[i] == NULL);
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void * Vec_PtrEntry( Vec_Ptr_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void ** Vec_PtrEntryP( Vec_Ptr_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray + i;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrWriteEntry( Vec_Ptr_t * p, int i, void * Entry )
+{
+    assert( i >= 0 && i < p->nSize );
+    p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void * Vec_PtrEntryLast( Vec_Ptr_t * p )
+{
+    assert( p->nSize > 0 );
+    return p->pArray[p->nSize-1];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the vector to the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrGrow( Vec_Ptr_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pArray = ABC_REALLOC( void *, p->pArray, nCapMin ); 
+    p->nCap   = nCapMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fills the vector with given number of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrFill( Vec_Ptr_t * p, int nSize, void * Entry )
+{
+    int i;
+    Vec_PtrGrow( p, nSize );
+    for ( i = 0; i < nSize; i++ )
+        p->pArray[i] = Entry;
+    p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fills the vector with given number of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrFillExtra( Vec_Ptr_t * p, int nSize, void * Fill )
+{
+    int i;
+    if ( nSize <= p->nSize )
+        return;
+    if ( nSize > 2 * p->nCap )
+        Vec_PtrGrow( p, nSize );
+    else if ( nSize > p->nCap )
+        Vec_PtrGrow( p, 2 * p->nCap );
+    for ( i = p->nSize; i < nSize; i++ )
+        p->pArray[i] = Fill;
+    p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the entry even if the place not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void * Vec_PtrGetEntry( Vec_Ptr_t * p, int i )
+{
+    Vec_PtrFillExtra( p, i + 1, NULL );
+    return Vec_PtrEntry( p, i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the entry even if the place does not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrSetEntry( Vec_Ptr_t * p, int i, void * Entry )
+{
+    Vec_PtrFillExtra( p, i + 1, NULL );
+    Vec_PtrWriteEntry( p, i, Entry );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrShrink( Vec_Ptr_t * p, int nSizeNew )
+{
+    assert( p->nSize >= nSizeNew );
+    p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrClear( Vec_Ptr_t * p )
+{
+    p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates array of memory pointers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrFreeData( Vec_Ptr_t * p )
+{
+    void * pTemp; int i;
+    if ( p == NULL ) return;
+    Vec_PtrForEachEntry( void *, p, pTemp, i )
+        if ( pTemp != (void *)(ABC_PTRINT_T)1 && pTemp != (void *)(ABC_PTRINT_T)2 )
+            ABC_FREE( pTemp );
+}
+static inline void Vec_PtrFreeFree( Vec_Ptr_t * p )
+{
+    if ( p == NULL ) return;
+    Vec_PtrFreeData( p );
+    Vec_PtrFree( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Copies the interger array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrCopy( Vec_Ptr_t * pDest, Vec_Ptr_t * pSour )
+{
+    pDest->nSize = 0;
+    Vec_PtrGrow( pDest, pSour->nSize );
+    memcpy( pDest->pArray, pSour->pArray, sizeof(void *) * pSour->nSize );
+    pDest->nSize = pSour->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrPush( Vec_Ptr_t * p, void * Entry )
+{
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Vec_PtrGrow( p, 16 );
+        else
+            Vec_PtrGrow( p, 2 * p->nCap );
+    }
+    p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrPushFirst( Vec_Ptr_t * p, void * Entry )
+{
+    int i;
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Vec_PtrGrow( p, 16 );
+        else
+            Vec_PtrGrow( p, 2 * p->nCap );
+    }
+    p->nSize++;
+    for ( i = p->nSize - 1; i >= 1; i-- )
+        p->pArray[i] = p->pArray[i-1];
+    p->pArray[0] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_PtrPushUnique( Vec_Ptr_t * p, void * Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            return 1;
+    Vec_PtrPush( p, Entry );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the last entry and removes it from the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void * Vec_PtrPop( Vec_Ptr_t * p )
+{
+    assert( p->nSize > 0 );
+    return p->pArray[--p->nSize];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_PtrFind( Vec_Ptr_t * p, void * Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            return i;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrRemove( Vec_Ptr_t * p, void * Entry )
+{
+    int i;
+    // delete assuming that it is closer to the end
+    for ( i = p->nSize - 1; i >= 0; i-- )
+        if ( p->pArray[i] == Entry )
+            break;
+    assert( i >= 0 );
+/*
+    // delete assuming that it is closer to the beginning
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            break;
+    assert( i < p->nSize );
+*/
+    for ( i++; i < p->nSize; i++ )
+        p->pArray[i-1] = p->pArray[i];
+    p->nSize--;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Interts entry at the index iHere. Shifts other entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrInsert( Vec_Ptr_t * p, int iHere, void * Entry )
+{
+    int i;
+    assert( iHere >= 0 && iHere < p->nSize );
+    Vec_PtrPush( p, 0 );
+    for ( i = p->nSize - 1; i > iHere; i-- )
+        p->pArray[i] = p->pArray[i-1];
+    p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Moves the first nItems to the end.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrReorder( Vec_Ptr_t * p, int nItems )
+{
+    assert( nItems < p->nSize );
+    Vec_PtrGrow( p, nItems + p->nSize );
+    memmove( (char **)p->pArray + p->nSize, p->pArray, nItems * sizeof(void*) );
+    memmove( p->pArray, (char **)p->pArray + nItems, p->nSize * sizeof(void*) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reverses the order of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrReverseOrder( Vec_Ptr_t * p )
+{
+    void * Temp;
+    int i;
+    for ( i = 0; i < p->nSize/2; i++ )
+    {
+        Temp = p->pArray[i];
+        p->pArray[i] = p->pArray[p->nSize-1-i];
+        p->pArray[p->nSize-1-i] = Temp;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if two vectors are equal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_PtrEqual( Vec_Ptr_t * p1, Vec_Ptr_t * p2 ) 
+{
+    int i;
+    if ( p1->nSize != p2->nSize )
+        return 0;
+    for ( i = 0; i < p1->nSize; i++ )
+        if ( p1->pArray[i] != p2->pArray[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two integers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Vec_PtrSortComparePtr( void ** pp1, void ** pp2 )
+{
+    if ( *pp1 < *pp2 )
+        return -1;
+    if ( *pp1 > *pp2 ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting the entries by their integer value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Vec_PtrSort( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() ) ___unused;
+static void Vec_PtrSort( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() )
+{
+    if ( p->nSize < 2 )
+        return;
+    if ( Vec_PtrSortCompare == NULL )
+        qsort( (void *)p->pArray, p->nSize, sizeof(void *), 
+                (int (*)(const void *, const void *)) Vec_PtrSortComparePtr );
+    else
+        qsort( (void *)p->pArray, p->nSize, sizeof(void *), 
+                (int (*)(const void *, const void *)) Vec_PtrSortCompare );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting the entries by their integer value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Vec_PtrUniqify( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() ) ___unused;
+static void Vec_PtrUniqify( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() )
+{
+    int i, k;
+    if ( p->nSize < 2 )
+        return;
+    Vec_PtrSort( p, Vec_PtrSortCompare );
+    for ( i = k = 1; i < p->nSize; i++ )
+        if ( p->pArray[i] != p->pArray[i-1] )
+            p->pArray[k++] = p->pArray[i];
+    p->nSize = k;
+}
+static void Vec_PtrUniqify2( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)(), void (*Vec_PtrObjFree)(), Vec_Int_t * vCounts )
+{
+    int i, k;
+    if ( vCounts )
+        Vec_IntFill( vCounts, 1, 1 );
+    if ( p->nSize < 2 )
+        return;
+    Vec_PtrSort( p, Vec_PtrSortCompare );
+    for ( i = k = 1; i < p->nSize; i++ )
+        if ( Vec_PtrSortCompare(p->pArray+i, p->pArray+k-1) != 0 )
+        {
+            p->pArray[k++] = p->pArray[i];
+            if ( vCounts )
+                Vec_IntPush( vCounts, 1 );
+        }
+        else 
+        {
+            if ( Vec_PtrObjFree )
+                Vec_PtrObjFree( p->pArray[i] );
+            if ( vCounts )
+                Vec_IntAddToEntry( vCounts, Vec_IntSize(vCounts)-1, 1 );
+        }
+    p->nSize = k;
+    assert( vCounts == NULL || Vec_IntSize(vCounts) == Vec_PtrSize(p) );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the array of simulation info.]
+
+  Description [Allocates the array containing given number of entries, 
+  each of which contains given number of unsigned words of simulation data.
+  The resulting array can be freed using regular procedure Vec_PtrFree().
+  It is the responsibility of the user to ensure this array is never grown.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrAllocSimInfo( int nEntries, int nWords )
+{
+    void ** pMemory;
+    unsigned * pInfo;
+    int i;
+    pMemory = (void **)ABC_ALLOC( char, (sizeof(void *) + sizeof(unsigned) * nWords) * nEntries );
+    pInfo = (unsigned *)(pMemory + nEntries);
+    for ( i = 0; i < nEntries; i++ )
+        pMemory[i] = pInfo + i * nWords;
+    return Vec_PtrAllocArray( pMemory, nEntries );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans simulation info of each entry beginning with iWord.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_PtrReadWordsSimInfo( Vec_Ptr_t * p )
+{
+    return (unsigned *)Vec_PtrEntry(p,1) - (unsigned *)Vec_PtrEntry(p,0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans simulation info of each entry beginning with iWord.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrCleanSimInfo( Vec_Ptr_t * vInfo, int iWord, int nWords )
+{
+    int i;
+    for ( i = 0; i < vInfo->nSize; i++ )
+        memset( (char*)Vec_PtrEntry(vInfo,i) + 4*iWord, 0, 4*(nWords-iWord) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans simulation info of each entry beginning with iWord.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrFillSimInfo( Vec_Ptr_t * vInfo, int iWord, int nWords )
+{
+    int i;
+    for ( i = 0; i < vInfo->nSize; i++ )
+        memset( (char*)Vec_PtrEntry(vInfo,i) + 4*iWord, 0xFF, 4*(nWords-iWord) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the array of simulation info.]
+
+  Description [Doubles the number of objects for which siminfo is allocated.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrDoubleSimInfo( Vec_Ptr_t * vInfo )
+{
+    Vec_Ptr_t * vInfoNew;
+    int nWords;
+    assert( Vec_PtrSize(vInfo) > 1 );
+    // get the new array
+    nWords = (unsigned *)Vec_PtrEntry(vInfo,1) - (unsigned *)Vec_PtrEntry(vInfo,0);
+    vInfoNew = Vec_PtrAllocSimInfo( 2*Vec_PtrSize(vInfo), nWords );
+    // copy the simulation info
+    memcpy( Vec_PtrEntry(vInfoNew,0), Vec_PtrEntry(vInfo,0), Vec_PtrSize(vInfo) * nWords * 4 );
+    // replace the array
+    ABC_FREE( vInfo->pArray );
+    vInfo->pArray = vInfoNew->pArray;
+    vInfo->nSize *= 2;
+    vInfo->nCap *= 2;
+    // free the old array
+    vInfoNew->pArray = NULL;
+    ABC_FREE( vInfoNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the array of simulation info.]
+
+  Description [Doubles the number of simulation patterns stored for each object.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_PtrReallocSimInfo( Vec_Ptr_t * vInfo )
+{
+    Vec_Ptr_t * vInfoNew;
+    int nWords, i;
+    assert( Vec_PtrSize(vInfo) > 1 );
+    // get the new array
+    nWords = (unsigned *)Vec_PtrEntry(vInfo,1) - (unsigned *)Vec_PtrEntry(vInfo,0);
+    vInfoNew = Vec_PtrAllocSimInfo( Vec_PtrSize(vInfo), 2*nWords );
+    // copy the simulation info
+    for ( i = 0; i < vInfo->nSize; i++ )
+        memcpy( Vec_PtrEntry(vInfoNew,i), Vec_PtrEntry(vInfo,i), nWords * 4 );
+    // replace the array
+    ABC_FREE( vInfo->pArray );
+    vInfo->pArray = vInfoNew->pArray;
+    // free the old array
+    vInfoNew->pArray = NULL;
+    ABC_FREE( vInfoNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the array of truth tables for the given number of vars.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrAllocTruthTables( int nVars )
+{
+    Vec_Ptr_t * p;
+    unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+    unsigned * pTruth;
+    int i, k, nWords;
+    nWords = (nVars <= 5 ? 1 : (1 << (nVars - 5)));
+    p = Vec_PtrAllocSimInfo( nVars, nWords );
+    for ( i = 0; i < nVars; i++ )
+    {
+        pTruth = (unsigned *)p->pArray[i];
+        if ( i < 5 )
+        {
+            for ( k = 0; k < nWords; k++ )
+                pTruth[k] = Masks[i];
+        }
+        else
+        {
+            for ( k = 0; k < nWords; k++ )
+                if ( k & (1 << (i-5)) )
+                    pTruth[k] = ~(unsigned)0;
+                else
+                    pTruth[k] = 0;
+        }
+    }
+    return p;
+}
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/vec/vecQue.h b/abc-build/src/misc/vec/vecQue.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/vec/vecQue.h
@@ -0,0 +1,374 @@
+/**CFile****************************************************************
+
+  FileName    [vecQue.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resizable arrays.]
+
+  Synopsis    [Priority queue.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: vecQue.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__vec__Queue_h
+#define ABC__misc__vec__Queue_h
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vec_Que_t_  Vec_Que_t;
+struct Vec_Que_t_ 
+{
+    int             nCap;
+    int             nSize;
+    int *           pHeap;
+    int *           pOrder;
+    float **        pCostsFlt;  // owned by the caller
+};
+
+static inline float Vec_QuePrio( Vec_Que_t * p, int v ) { return *p->pCostsFlt ? (*p->pCostsFlt)[v] : v; }
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Que_t * Vec_QueAlloc( int nCap )
+{
+    Vec_Que_t * p;
+    p = ABC_CALLOC( Vec_Que_t, 1 );
+    if ( nCap < 16 )
+        nCap = 16;
+    p->nSize  = 1;
+    p->nCap   = nCap + 1;
+    p->pHeap  = ABC_FALLOC( int, p->nCap );
+    p->pOrder = ABC_FALLOC( int, p->nCap );
+    return p;
+}
+static inline void Vec_QueFree( Vec_Que_t * p )
+{
+    ABC_FREE( p->pOrder );
+    ABC_FREE( p->pHeap );
+    ABC_FREE( p );
+}
+static inline void Vec_QueFreeP( Vec_Que_t ** p )
+{
+    if ( *p )
+        Vec_QueFree( *p );
+    *p = NULL;
+}
+static inline void Vec_QueSetPriority( Vec_Que_t * p, float ** pCosts )
+{
+    assert( p->pCostsFlt == NULL );
+    p->pCostsFlt = pCosts;
+}
+static inline void Vec_QueGrow( Vec_Que_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pHeap  = ABC_REALLOC( int, p->pHeap,  nCapMin );
+    p->pOrder = ABC_REALLOC( int, p->pOrder, nCapMin ); 
+    memset( p->pHeap  + p->nCap, 0xff, (nCapMin - p->nCap) * sizeof(int) );
+    memset( p->pOrder + p->nCap, 0xff, (nCapMin - p->nCap) * sizeof(int) );
+    p->nCap   = nCapMin;
+}
+static inline void Vec_QueClear( Vec_Que_t * p )
+{
+    int i;
+    assert( p->pHeap[0] == -1 );
+    for ( i = 1; i < p->nSize; i++ )
+    {
+        assert( p->pHeap[i] >= 0 && p->pOrder[p->pHeap[i]] == i );
+        p->pOrder[p->pHeap[i]] = -1;
+        p->pHeap[i] = -1;
+    }
+    p->nSize = 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_QueSize( Vec_Que_t * p )
+{
+    assert( p->nSize > 0 );
+    return p->nSize - 1;
+}
+static inline int Vec_QueTop( Vec_Que_t * p )
+{
+    return Vec_QueSize(p) > 0 ? p->pHeap[1] : -1;
+}
+static inline float Vec_QueTopPriority( Vec_Que_t * p )
+{
+    return Vec_QueSize(p) > 0 ? Vec_QuePrio(p, p->pHeap[1]) : -ABC_INFINITY;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_QueMoveUp( Vec_Que_t * p, int v )
+{
+    float Cost = Vec_QuePrio(p, v);
+    int i      = p->pOrder[v];
+    int parent = i >> 1;
+    int fMoved = 0;
+    assert( p->pOrder[v] != -1 );
+    assert( p->pHeap[i] == v );
+    while ( i > 1 && Cost > Vec_QuePrio(p, p->pHeap[parent]) )
+    {
+        p->pHeap[i]            = p->pHeap[parent];
+        p->pOrder[p->pHeap[i]] = i;
+        i                      = parent;
+        parent                 = i >> 1;
+        fMoved                 = 1;
+    }
+    p->pHeap[i]  = v;
+    p->pOrder[v] = i;
+    return fMoved;
+}
+static inline void Vec_QueMoveDown( Vec_Que_t * p, int v )
+{
+    float Cost = Vec_QuePrio(p, v);
+    int i      = p->pOrder[v];
+    int child  = i << 1;
+    while ( child < p->nSize )
+    {
+        if ( child + 1 < p->nSize && Vec_QuePrio(p, p->pHeap[child]) < Vec_QuePrio(p, p->pHeap[child+1]) )
+            child++;
+        assert( child < p->nSize );
+        if ( Cost >= Vec_QuePrio(p, p->pHeap[child]))
+            break;
+        p->pHeap[i]            = p->pHeap[child];
+        p->pOrder[p->pHeap[i]] = i;
+        i                      = child;
+        child                  = child << 1;
+    }
+    p->pHeap[i]  = v;
+    p->pOrder[v] = i;
+}
+static inline void Vec_QueUpdate( Vec_Que_t * p, int v )
+{
+    if ( !Vec_QueMoveUp( p, v ) )
+        Vec_QueMoveDown( p, v );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_QueIsMember( Vec_Que_t * p, int v )
+{
+    assert( v >= 0 );
+    return (int)( v < p->nCap && p->pOrder[v] >= 0 );
+}
+static inline void Vec_QuePush( Vec_Que_t * p, int v )
+{
+    if ( p->nSize >= p->nCap )
+        Vec_QueGrow( p, Abc_MaxInt(p->nSize+1, 2*p->nCap) );
+    if ( v >= p->nCap )
+        Vec_QueGrow( p, Abc_MaxInt(v+1, 2*p->nCap) );
+    assert( p->nSize < p->nCap );
+    assert( p->pOrder[v] == -1 );
+    assert( p->pHeap[p->nSize] == -1 );
+    p->pOrder[v] = p->nSize;
+    p->pHeap[p->nSize++] = v;
+    Vec_QueMoveUp( p, v );
+}
+static inline int Vec_QuePop( Vec_Que_t * p )
+{
+    int v, Res;
+    assert( p->nSize > 1 );
+    Res = p->pHeap[1];      p->pOrder[Res] = -1;
+    if ( --p->nSize == 1 )
+    {
+        p->pHeap[1] = -1;
+        return Res;
+    }
+    v = p->pHeap[p->nSize]; p->pHeap[p->nSize] = -1;
+    p->pHeap[1] = v;        p->pOrder[v] = 1;
+    Vec_QueMoveDown( p, v );
+    return Res;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_QuePrint( Vec_Que_t * p )
+{
+    int i, k, m;
+    for ( i = k = 1; i < p->nSize; i += k, k *= 2 )
+    {
+        for ( m = 0; m < k; m++ )
+            if ( i+m < p->nSize )
+                printf( "%-5d", p->pHeap[i+m] );
+        printf( "\n" );
+        for ( m = 0; m < k; m++ )
+            if ( i+m < p->nSize )
+                printf( "%-5.0f", Vec_QuePrio(p, p->pHeap[i+m]) );
+        printf( "\n" );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_QueCheck( Vec_Que_t * p )
+{
+    int i, child;
+    assert( p->nSize > 0 );
+    assert( p->nSize <= p->nCap );
+    // check mapping
+    for ( i = 0; i < p->nSize-1; i++ )
+        assert( p->pOrder[i] > 0 );
+    for ( ; i < p->nCap; i++ )
+        assert( p->pOrder[i] == -1 );
+    // check heap
+    assert( p->pHeap[0] == -1 );
+    for ( i = 0; i < p->nSize-1; i++ )
+        assert( p->pHeap[p->pOrder[i]] == i );
+    for ( i++; i < p->nCap; i++ )
+        assert( p->pHeap[i] == -1 );
+    // check heap property
+    for ( i = 1; i < p->nSize; i++ )
+    {
+        child = i << 1;
+        if ( child < p->nSize )
+            assert( Vec_QuePrio(p, p->pHeap[i]) >= Vec_QuePrio(p, p->pHeap[child]) );
+        child++;
+        if ( child < p->nSize )
+            assert( Vec_QuePrio(p, p->pHeap[i]) >= Vec_QuePrio(p, p->pHeap[child]) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_QueTest( Vec_Flt_t * vCosts )
+{
+    Vec_Int_t * vTop;
+    Vec_Que_t * p;
+    int i, Entry;
+
+    // start the queue
+    p = Vec_QueAlloc( Vec_FltSize(vCosts) );
+    Vec_QueSetPriority( p, Vec_FltArrayP(vCosts) );
+    for ( i = 0; i < Vec_FltSize(vCosts); i++ )
+        Vec_QuePush( p, i );
+//    Vec_QuePrint( p );
+    Vec_QueCheck( p );
+
+    // find the topmost 10%
+    vTop = Vec_IntAlloc( Vec_FltSize(vCosts) / 10 );
+    while ( Vec_IntSize(vTop) < Vec_FltSize(vCosts) / 10 )
+        Vec_IntPush( vTop, Vec_QuePop(p) );
+//    Vec_IntPrint( vTop );
+//    Vec_QueCheck( p ); // queque is not ready at this point!!!
+
+    // put them back
+    Vec_IntForEachEntry( vTop, Entry, i )
+        Vec_QuePush( p, Entry );
+    Vec_IntFree( vTop );
+    Vec_QueCheck( p );
+
+    Vec_QueFree( p );
+}
+
+/*
+    {
+        extern void Vec_QueTest( Vec_Flt_t * p );
+        Vec_QueTest( p->vTimesOut );
+    }
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
diff --git a/abc-build/src/misc/vec/vecSet.h b/abc-build/src/misc/vec/vecSet.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/vec/vecSet.h
@@ -0,0 +1,285 @@
+/**CFile****************************************************************
+
+  FileName    [vecSet.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT solvers.]
+
+  Synopsis    [Multi-page dynamic array.]
+
+  Author      [Alan Mishchenko]
+
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: vecSet.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__sat__bsat__vecSet_h
+#define ABC__sat__bsat__vecSet_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// data-structure for logging entries
+// memory is allocated in 2^nPageSize word-sized pages
+// the first two 'words' of each page are used for bookkeeping
+// the first 'word' of bookkeeping data stores the word limit
+// the second 'word' of bookkeeping data stores the shadow word limit
+// (the shadow word limit is only used during garbage collection)
+
+typedef struct Vec_Set_t_ Vec_Set_t;
+struct Vec_Set_t_
+{
+    int               nPageSize;    // page size
+    unsigned          uPageMask;    // page mask
+    int               nEntries;     // entry count
+    int               iPage;        // current page
+    int               iPageS;       // shadow page
+    int               nPagesAlloc;  // page count allocated
+    word **           pPages;       // page pointers
+}; 
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int     Vec_SetHandPage( Vec_Set_t * p, int h )    { return h >> p->nPageSize;      }
+static inline int     Vec_SetHandShift( Vec_Set_t * p, int h )   { return h & p->uPageMask;       }
+static inline int     Vec_SetWordNum( int nSize )                { return (nSize + 1) >> 1;       }
+
+//static inline word *  Vec_SetEntry( Vec_Set_t * p, int h )       { assert(Vec_SetHandPage(p, h) >= 0 && Vec_SetHandPage(p, h) <= p->iPage); assert(Vec_SetHandShift(p, h) >= 2 && Vec_SetHandShift(p, h) < (1 << p->nPageSize)); return p->pPages[Vec_SetHandPage(p, h)] + Vec_SetHandShift(p, h);     }
+static inline word *  Vec_SetEntry( Vec_Set_t * p, int h )       { return p->pPages[Vec_SetHandPage(p, h)] + Vec_SetHandShift(p, h);                     }
+static inline int     Vec_SetEntryNum( Vec_Set_t * p )           { return p->nEntries;            }
+static inline void    Vec_SetWriteEntryNum( Vec_Set_t * p, int i){ p->nEntries = i;               }
+
+static inline int     Vec_SetLimit( word * p )                   { return p[0];                   }
+static inline int     Vec_SetLimitS( word * p )                  { return p[1];                   }
+
+static inline int     Vec_SetIncLimit( word * p, int nWords )    { return p[0] += nWords;         }
+static inline int     Vec_SetIncLimitS( word * p, int nWords )   { return p[1] += nWords;         }
+
+static inline void    Vec_SetWriteLimit( word * p, int nWords )  { p[0] = nWords;                 }
+static inline void    Vec_SetWriteLimitS( word * p, int nWords ) { p[1] = nWords;                 }
+
+static inline int     Vec_SetHandCurrent( Vec_Set_t * p )        { return (p->iPage << p->nPageSize)  + Vec_SetLimit(p->pPages[p->iPage]);               }
+static inline int     Vec_SetHandCurrentS( Vec_Set_t * p )       { return (p->iPageS << p->nPageSize) + Vec_SetLimitS(p->pPages[p->iPageS]);             }
+
+static inline int     Vec_SetHandMemory( Vec_Set_t * p, int h )  { return Vec_SetHandPage(p, h) * (1 << (p->nPageSize+3)) + Vec_SetHandShift(p, h) * 8;  }
+static inline int     Vec_SetMemory( Vec_Set_t * p )             { return Vec_SetHandMemory(p, Vec_SetHandCurrent(p));                                   }
+static inline int     Vec_SetMemoryS( Vec_Set_t * p )            { return Vec_SetHandMemory(p, Vec_SetHandCurrentS(p));                                  }
+static inline int     Vec_SetMemoryAll( Vec_Set_t * p )          { return (p->iPage+1) * (1 << (p->nPageSize+3));                                        }
+
+// Type is the Set type
+// pVec is vector of set
+// nSize should be given by the user
+// pSet is the pointer to the set
+// p (page) and s (shift) are variables used here
+#define Vec_SetForEachEntry( Type, pVec, nSize, pSet, p, s )   \
+    for ( p = 0; p <= pVec->iPage; p++ )                       \
+        for ( s = 2; s < Vec_SetLimit(pVec->pPages[p]) && ((pSet) = (Type)(pVec->pPages[p] + (s))); s += nSize )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocating vector.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_SetAlloc_( Vec_Set_t * p, int nPageSize )
+{
+    assert( nPageSize > 8 );
+    memset( p, 0, sizeof(Vec_Set_t) );
+    p->nPageSize    = nPageSize;
+    p->uPageMask    = (unsigned)((1 << nPageSize) - 1);
+    p->nPagesAlloc  = 256;
+    p->pPages       = ABC_CALLOC( word *, p->nPagesAlloc );
+    p->pPages[0]    = ABC_ALLOC( word, (1 << p->nPageSize) );
+    p->pPages[0][0] = ~0;
+    p->pPages[0][1] = ~0;
+    Vec_SetWriteLimit( p->pPages[0], 2 );
+}
+static inline Vec_Set_t * Vec_SetAlloc( int nPageSize )
+{
+    Vec_Set_t * p;
+    p = ABC_CALLOC( Vec_Set_t, 1 );
+    Vec_SetAlloc_( p, nPageSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resetting vector.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_SetRestart( Vec_Set_t * p )
+{
+    p->nEntries     = 0;
+    p->iPage        = 0;
+    p->iPageS       = 0;
+    p->pPages[0][0] = ~0;
+    p->pPages[0][1] = ~0;
+    Vec_SetWriteLimit( p->pPages[0], 2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Freeing vector.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_SetFree_( Vec_Set_t * p )
+{
+    int i;
+    if ( p == NULL ) return;
+    for ( i = 0; i < p->nPagesAlloc; i++ )
+        ABC_FREE( p->pPages[i] );
+    ABC_FREE( p->pPages );
+}
+static inline void Vec_SetFree( Vec_Set_t * p )
+{
+    if ( p == NULL ) return;
+    Vec_SetFree_( p );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns memory in bytes occupied by the vector.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline double Vec_ReportMemory( Vec_Set_t * p )
+{
+    double Mem = sizeof(Vec_Set_t);
+    Mem += p->nPagesAlloc * sizeof(void *);
+    Mem += sizeof(word) * (1 << p->nPageSize) * (1 + p->iPage);
+    return Mem;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Appending entries to vector.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_SetAppend( Vec_Set_t * p, int * pArray, int nSize )
+{
+    int nWords = Vec_SetWordNum( nSize );
+    assert( nWords < (1 << p->nPageSize) );
+    p->nEntries++;
+    if ( Vec_SetLimit( p->pPages[p->iPage] ) + nWords >= (1 << p->nPageSize) )
+    {
+        if ( ++p->iPage == p->nPagesAlloc )
+        {
+            p->pPages = ABC_REALLOC( word *, p->pPages, p->nPagesAlloc * 2 );
+            memset( p->pPages + p->nPagesAlloc, 0, sizeof(word *) * p->nPagesAlloc );
+            p->nPagesAlloc *= 2;
+        }
+        if ( p->pPages[p->iPage] == NULL )
+            p->pPages[p->iPage] = ABC_ALLOC( word, (1 << p->nPageSize) );
+        Vec_SetWriteLimit( p->pPages[p->iPage], 2 );
+        p->pPages[p->iPage][1] = ~0;
+    }
+    if ( pArray )
+        memcpy( p->pPages[p->iPage] + Vec_SetLimit(p->pPages[p->iPage]), pArray, sizeof(int) * nSize );
+    Vec_SetIncLimit( p->pPages[p->iPage], nWords );
+    return Vec_SetHandCurrent(p) - nWords;
+}
+static inline int Vec_SetAppendS( Vec_Set_t * p, int nSize )
+{
+    int nWords = Vec_SetWordNum( nSize );
+    assert( nWords < (1 << p->nPageSize) );
+    if ( Vec_SetLimitS( p->pPages[p->iPageS] ) + nWords >= (1 << p->nPageSize) )
+        Vec_SetWriteLimitS( p->pPages[++p->iPageS], 2 );
+    Vec_SetIncLimitS( p->pPages[p->iPageS], nWords );
+    return Vec_SetHandCurrentS(p) - nWords;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Shrinking vector size.]
+
+  Description []
+
+  SideEffects [This procedure does not update the number of entries.]
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_SetShrink( Vec_Set_t * p, int h )
+{
+    assert( h <= Vec_SetHandCurrent(p) );
+    p->iPage = Vec_SetHandPage(p, h);
+    Vec_SetWriteLimit( p->pPages[p->iPage], Vec_SetHandShift(p, h) );
+}
+static inline void Vec_SetShrinkS( Vec_Set_t * p, int h )
+{
+    assert( h <= Vec_SetHandCurrent(p) );
+    p->iPageS = Vec_SetHandPage(p, h);
+    Vec_SetWriteLimitS( p->pPages[p->iPageS], Vec_SetHandShift(p, h) );
+}
+
+static inline void Vec_SetShrinkLimits( Vec_Set_t * p )
+{
+    int i;
+    for ( i = 0; i <= p->iPage; i++ )
+        Vec_SetWriteLimit( p->pPages[i], Vec_SetLimitS(p->pPages[i]) );
+}
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/vec/vecStr.h b/abc-build/src/misc/vec/vecStr.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/vec/vecStr.h
@@ -0,0 +1,910 @@
+/**CFile****************************************************************
+
+  FileName    [vecStr.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resizable arrays.]
+
+  Synopsis    [Resizable arrays of characters.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: vecStr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__vec__vecStr_h
+#define ABC__misc__vec__vecStr_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vec_Str_t_       Vec_Str_t;
+struct Vec_Str_t_ 
+{
+    int              nCap;
+    int              nSize;
+    char *           pArray;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define Vec_StrForEachEntry( vVec, Entry, i )                                               \
+    for ( i = 0; (i < Vec_StrSize(vVec)) && (((Entry) = Vec_StrEntry(vVec, i)), 1); i++ )   
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Str_t * Vec_StrAlloc( int nCap )
+{
+    Vec_Str_t * p;
+    p = ABC_ALLOC( Vec_Str_t, 1 );
+    if ( nCap > 0 && nCap < 16 )
+        nCap = 16;
+    p->nSize  = 0;
+    p->nCap   = nCap;
+    p->pArray = p->nCap? ABC_ALLOC( char, p->nCap ) : NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given size and cleans it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Str_t * Vec_StrStart( int nSize )
+{
+    Vec_Str_t * p;
+    p = Vec_StrAlloc( nSize );
+    p->nSize = nSize;
+    memset( p->pArray, 0, sizeof(char) * nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the vector from an integer array of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Str_t * Vec_StrAllocArray( char * pArray, int nSize )
+{
+    Vec_Str_t * p;
+    p = ABC_ALLOC( Vec_Str_t, 1 );
+    p->nSize  = nSize;
+    p->nCap   = nSize;
+    p->pArray = pArray;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the vector from an integer array of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Str_t * Vec_StrAllocArrayCopy( char * pArray, int nSize )
+{
+    Vec_Str_t * p;
+    p = ABC_ALLOC( Vec_Str_t, 1 );
+    p->nSize  = nSize;
+    p->nCap   = nSize;
+    p->pArray = ABC_ALLOC( char, nSize );
+    memcpy( p->pArray, pArray, sizeof(char) * nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the integer array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Str_t * Vec_StrDup( Vec_Str_t * pVec )
+{
+    Vec_Str_t * p;
+    p = ABC_ALLOC( Vec_Str_t, 1 );
+    p->nSize  = pVec->nSize;
+    p->nCap   = pVec->nCap;
+    p->pArray = p->nCap? ABC_ALLOC( char, p->nCap ) : NULL;
+    memcpy( p->pArray, pVec->pArray, sizeof(char) * pVec->nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the array into another vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Str_t * Vec_StrDupArray( Vec_Str_t * pVec )
+{
+    Vec_Str_t * p;
+    p = ABC_ALLOC( Vec_Str_t, 1 );
+    p->nSize  = pVec->nSize;
+    p->nCap   = pVec->nCap;
+    p->pArray = pVec->pArray;
+    pVec->nSize  = 0;
+    pVec->nCap   = 0;
+    pVec->pArray = NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrFree( Vec_Str_t * p )
+{
+    ABC_FREE( p->pArray );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrFreeP( Vec_Str_t ** p )
+{
+    if ( *p == NULL )
+        return;
+    ABC_FREE( (*p)->pArray );
+    ABC_FREE( (*p) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline char * Vec_StrReleaseArray( Vec_Str_t * p )
+{
+    char * pArray = p->pArray;
+    p->nCap = 0;
+    p->nSize = 0;
+    p->pArray = NULL;
+    return pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline char * Vec_StrArray( Vec_Str_t * p )
+{
+    return p->pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_StrSize( Vec_Str_t * p )
+{
+    return p->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_StrCap( Vec_Str_t * p )
+{
+    return p->nCap;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline double Vec_StrMemory( Vec_Str_t * p )
+{
+    return !p ? 0.0 : 1.0 * sizeof(char) * p->nCap + sizeof(Vec_Str_t);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline char Vec_StrEntry( Vec_Str_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline char * Vec_StrEntryP( Vec_Str_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray + i;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrWriteEntry( Vec_Str_t * p, int i, char Entry )
+{
+    assert( i >= 0 && i < p->nSize );
+    p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline char Vec_StrEntryLast( Vec_Str_t * p )
+{
+    assert( p->nSize > 0 );
+    return p->pArray[p->nSize-1];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the vector to the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrGrow( Vec_Str_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pArray = ABC_REALLOC( char, p->pArray, nCapMin ); 
+    p->nCap   = nCapMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fills the vector with given number of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrFill( Vec_Str_t * p, int nSize, char Fill )
+{
+    int i;
+    Vec_StrGrow( p, nSize );
+    p->nSize = nSize;
+    for ( i = 0; i < p->nSize; i++ )
+        p->pArray[i] = Fill;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fills the vector with given number of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrFillExtra( Vec_Str_t * p, int nSize, char Fill )
+{
+    int i;
+    if ( nSize <= p->nSize )
+        return;
+    if ( nSize > 2 * p->nCap )
+        Vec_StrGrow( p, nSize );
+    else if ( nSize > p->nCap )
+        Vec_StrGrow( p, 2 * p->nCap );
+    for ( i = p->nSize; i < nSize; i++ )
+        p->pArray[i] = Fill;
+    p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the entry even if the place not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline char Vec_StrGetEntry( Vec_Str_t * p, int i )
+{
+    Vec_StrFillExtra( p, i + 1, 0 );
+    return Vec_StrEntry( p, i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the entry even if the place does not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrSetEntry( Vec_Str_t * p, int i, char Entry )
+{
+    Vec_StrFillExtra( p, i + 1, 0 );
+    Vec_StrWriteEntry( p, i, Entry );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrShrink( Vec_Str_t * p, int nSizeNew )
+{
+    assert( p->nSize >= nSizeNew );
+    p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrClear( Vec_Str_t * p )
+{
+    p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrPush( Vec_Str_t * p, char Entry )
+{
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Vec_StrGrow( p, 16 );
+        else
+            Vec_StrGrow( p, 2 * p->nCap );
+    }
+    p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the last entry and removes it from the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline char Vec_StrPop( Vec_Str_t * p )
+{
+    assert( p->nSize > 0 );
+    return p->pArray[--p->nSize];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrPrintNum( Vec_Str_t * p, int Num )
+{
+    int i;
+    char Digits[16];
+    if ( Num == 0 )
+    {
+        Vec_StrPush( p, '0' );
+        return;
+    }
+    if ( Num < 0 )
+    {
+        Vec_StrPush( p, '-' );
+        Num = -Num;
+    }
+    for ( i = 0; Num; Num /= 10,  i++ )
+        Digits[i] = Num % 10;
+    for ( i--; i >= 0; i-- )
+        Vec_StrPush( p, (char)('0' + Digits[i]) );
+}
+static inline void Vec_StrPrintNumStar( Vec_Str_t * p, int Num, int nDigits )
+{
+    int i;
+    char Digits[16] = {0};
+    if ( Num == 0 )
+    {
+        for ( i = 0; i < nDigits; i++ )
+            Vec_StrPush( p, '0' );
+        return;
+    }
+    if ( Num < 0 )
+    {
+        Vec_StrPush( p, '-' );
+        Num = -Num;
+        nDigits--;
+    }
+    for ( i = 0; Num; Num /= 10,  i++ )
+        Digits[i] = Num % 10;
+    for ( i = Abc_MaxInt(i, nDigits)-1; i >= 0; i-- )
+        Vec_StrPush( p, (char)('0' + Digits[i]) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrPrintStr( Vec_Str_t * p, const char * pStr )
+{
+    int i, Length = strlen(pStr);
+    for ( i = 0; i < Length; i++ )
+        Vec_StrPush( p, pStr[i] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Appends the string to the char vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrAppend( Vec_Str_t * p, const char * pString )
+{
+    Vec_StrPrintStr( p, pString );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reverses the order of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrReverseOrder( Vec_Str_t * p )
+{
+    int i, Temp;
+    for ( i = 0; i < p->nSize/2; i++ )
+    {
+        Temp = p->pArray[i];
+        p->pArray[i] = p->pArray[p->nSize-1-i];
+        p->pArray[p->nSize-1-i] = Temp;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_StrSum( Vec_Str_t * p ) 
+{
+    int i, Counter = 0;
+    for ( i = 0; i < p->nSize; i++ )
+        Counter += (int)p->pArray[i];
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares two strings.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_StrEqual( Vec_Str_t * p1, Vec_Str_t * p2 ) 
+{
+    int i;
+    if ( p1->nSize != p2->nSize )
+        return 0;
+    for ( i = 0; i < p1->nSize; i++ )
+        if ( p1->pArray[i] != p2->pArray[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Vec_StrSortCompare1( char * pp1, char * pp2 )
+{
+    // for some reason commenting out lines (as shown) led to crashing of the release version
+    if ( *pp1 < *pp2 )
+        return -1;
+    if ( *pp1 > *pp2 ) //
+        return 1;
+    return 0; //
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Vec_StrSortCompare2( char * pp1, char * pp2 )
+{
+    // for some reason commenting out lines (as shown) led to crashing of the release version
+    if ( *pp1 > *pp2 )
+        return -1;
+    if ( *pp1 < *pp2 ) //
+        return 1;
+    return 0; //
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting the entries by their integer value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrSort( Vec_Str_t * p, int fReverse )
+{
+    if ( fReverse ) 
+        qsort( (void *)p->pArray, p->nSize, sizeof(char), 
+                (int (*)(const void *, const void *)) Vec_StrSortCompare2 );
+    else
+        qsort( (void *)p->pArray, p->nSize, sizeof(char), 
+                (int (*)(const void *, const void *)) Vec_StrSortCompare1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_StrCompareVec( Vec_Str_t * p1, Vec_Str_t * p2 )
+{
+    if ( p1 == NULL || p2 == NULL )
+        return (p1 != NULL) - (p2 != NULL);
+    if ( Vec_StrSize(p1) != Vec_StrSize(p2) )
+        return Vec_StrSize(p1) - Vec_StrSize(p2);
+    return memcmp( Vec_StrArray(p1), Vec_StrArray(p2), Vec_StrSize(p1) );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Binary I/O for numbers (int/float/etc) and strings (char *).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrPutI_ne( Vec_Str_t * vOut, int Val )
+{
+    int i;
+//    for ( i = 0; i < 4; i++ )
+    for ( i = 3; i >= 0; i-- )
+        Vec_StrPush( vOut, (char)(Val >> (8*i)) );
+}
+static inline int Vec_StrGetI_ne( Vec_Str_t * vOut, int * pPos )
+{
+    int i;
+    int Val = 0;
+//    for ( i = 0; i < 4; i++ )
+    for ( i = 3; i >= 0; i-- )
+        Val |= ((int)(unsigned char)Vec_StrEntry(vOut, (*pPos)++) << (8*i));
+    return Val;
+}
+
+static inline void Vec_StrPutI( Vec_Str_t * vOut, int Val )
+{
+    for ( ; Val >= 0x80; Val >>= 7 )
+        Vec_StrPush( vOut, (unsigned char)(Val | 0x80) );
+    Vec_StrPush( vOut, (unsigned char)Val );
+}
+static inline int Vec_StrGetI( Vec_Str_t * vOut, int * pPos )
+{
+    unsigned char ch;
+    int i = 0, Val = 0;
+    while ( (ch = Vec_StrEntry(vOut, (*pPos)++)) & 0x80 )
+        Val |= ((ch & 0x7f) << (7 * i++));
+    return Val | (ch << (7 * i));
+}
+
+static inline void Vec_StrPutW( Vec_Str_t * vOut, word Val )
+{
+    int i;
+    for ( i = 0; i < 8; i++ )
+        Vec_StrPush( vOut, (char)(Val >> (8*i)) );
+}
+static inline word Vec_StrGetW( Vec_Str_t * vOut, int * pPos )
+{
+    int i;
+    word Val = 0;
+    for ( i = 0; i < 8; i++ )
+        Val |= ((word)(unsigned char)Vec_StrEntry(vOut, (*pPos)++) << (8*i));
+    return Val;
+}
+
+static inline void Vec_StrPutF( Vec_Str_t * vOut, float Val )
+{
+    union { float num; unsigned char data[4]; } tmp;
+    tmp.num = Val;
+    Vec_StrPush( vOut, tmp.data[0] );
+    Vec_StrPush( vOut, tmp.data[1] );
+    Vec_StrPush( vOut, tmp.data[2] );
+    Vec_StrPush( vOut, tmp.data[3] );
+}
+static inline float Vec_StrGetF( Vec_Str_t * vOut, int * pPos )
+{
+    union { float num; unsigned char data[4]; } tmp;
+    tmp.data[0] = Vec_StrEntry( vOut, (*pPos)++ );
+    tmp.data[1] = Vec_StrEntry( vOut, (*pPos)++ );
+    tmp.data[2] = Vec_StrEntry( vOut, (*pPos)++ );
+    tmp.data[3] = Vec_StrEntry( vOut, (*pPos)++ );
+    return tmp.num;
+}
+
+static inline void Vec_StrPutD( Vec_Str_t * vOut, double Val )
+{
+    union { double num; unsigned char data[8]; } tmp;
+    int i, Lim = sizeof(double);
+    tmp.num = Val;
+    for ( i = 0; i < Lim; i++ )
+        Vec_StrPush( vOut, tmp.data[i] );
+}
+static inline double Vec_StrGetD( Vec_Str_t * vOut, int * pPos )
+{
+    union { double num; unsigned char data[8]; } tmp;
+    int i, Lim = sizeof(double);
+    for ( i = 0; i < Lim; i++ )
+        tmp.data[i] = Vec_StrEntry( vOut, (*pPos)++ );
+    return tmp.num;
+}
+
+static inline void Vec_StrPutS( Vec_Str_t * vOut, char * pStr )
+{
+    while ( *pStr )
+        Vec_StrPush( vOut, *pStr++ );
+    Vec_StrPush( vOut, (char)0 );
+}
+static inline char * Vec_StrGetS( Vec_Str_t * vOut, int * pPos )
+{
+    char * pStr = Vec_StrEntryP( vOut, *pPos );
+    while ( Vec_StrEntry(vOut, (*pPos)++) );
+    return Abc_UtilStrsav(pStr);
+}
+
+static inline void Vec_StrPutC( Vec_Str_t * vOut, char c )
+{
+    Vec_StrPush( vOut, c );
+}
+static inline char Vec_StrGetC( Vec_Str_t * vOut, int * pPos )
+{
+    return Vec_StrEntry(vOut, (*pPos)++);
+}
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/vec/vecVec.h b/abc-build/src/misc/vec/vecVec.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/vec/vecVec.h
@@ -0,0 +1,638 @@
+/**CFile****************************************************************
+
+  FileName    [vecVec.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resizable arrays.]
+
+  Synopsis    [Resizable vector of resizable vectors.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: vecVec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__vec__vecVec_h
+#define ABC__misc__vec__vecVec_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vec_Vec_t_       Vec_Vec_t;
+struct Vec_Vec_t_ 
+{
+    int              nCap;
+    int              nSize;
+    void **          pArray;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+// iterators through levels 
+#define Vec_VecForEachLevel( vGlob, vVec, i )                                                 \
+    for ( i = 0; (i < Vec_VecSize(vGlob)) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ )
+#define Vec_VecForEachLevelStart( vGlob, vVec, i, LevelStart )                                \
+    for ( i = LevelStart; (i < Vec_VecSize(vGlob)) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ )
+#define Vec_VecForEachLevelStop( vGlob, vVec, i, LevelStop )                                  \
+    for ( i = 0; (i < LevelStop) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ )
+#define Vec_VecForEachLevelStartStop( vGlob, vVec, i, LevelStart, LevelStop )                 \
+    for ( i = LevelStart; (i < LevelStop) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ )
+#define Vec_VecForEachLevelReverse( vGlob, vVec, i )                                          \
+    for ( i = Vec_VecSize(vGlob)-1; (i >= 0) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i-- )
+#define Vec_VecForEachLevelReverseStartStop( vGlob, vVec, i, LevelStart, LevelStop )          \
+    for ( i = LevelStart-1; (i >= LevelStop) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i-- )
+#define Vec_VecForEachLevelTwo( vGlob1, vGlob2, vVec1, vVec2, i )                                                 \
+    for ( i = 0; (i < Vec_VecSize(vGlob1)) && (((vVec1) = Vec_VecEntry(vGlob1, i)), 1) && (((vVec2) = Vec_VecEntry(vGlob2, i)), 1); i++ )
+
+// iterators through levels 
+#define Vec_VecForEachLevelInt( vGlob, vVec, i )                                              \
+    for ( i = 0; (i < Vec_VecSize(vGlob)) && (((vVec) = Vec_VecEntryInt(vGlob, i)), 1); i++ )
+#define Vec_VecForEachLevelIntStart( vGlob, vVec, i, LevelStart )                             \
+    for ( i = LevelStart; (i < Vec_VecSize(vGlob)) && (((vVec) = Vec_VecEntryInt(vGlob, i)), 1); i++ )
+#define Vec_VecForEachLevelIntStop( vGlob, vVec, i, LevelStop )                               \
+    for ( i = 0; (i < LevelStop) && (((vVec) = Vec_VecEntryInt(vGlob, i)), 1); i++ )
+#define Vec_VecForEachLevelIntStartStop( vGlob, vVec, i, LevelStart, LevelStop )              \
+    for ( i = LevelStart; (i < LevelStop) && (((vVec) = Vec_VecEntryInt(vGlob, i)), 1); i++ )
+#define Vec_VecForEachLevelIntReverse( vGlob, vVec, i )                                       \
+    for ( i = Vec_VecSize(vGlob)-1; (i >= 0) && (((vVec) = Vec_VecEntryInt(vGlob, i)), 1); i-- )
+#define Vec_VecForEachLevelIntReverseStartStop( vGlob, vVec, i, LevelStart, LevelStop )       \
+    for ( i = LevelStart-1; (i >= LevelStop) && (((vVec) = Vec_VecEntryInt(vGlob, i)), 1); i-- )
+#define Vec_VecForEachLevelIntTwo( vGlob1, vGlob2, vVec1, vVec2, i )                          \
+    for ( i = 0; (i < Vec_VecSize(vGlob1)) && (((vVec1) = Vec_VecEntryInt(vGlob1, i)), 1) && (((vVec2) = Vec_VecEntryInt(vGlob2, i)), 1); i++ )
+
+// iteratores through entries
+#define Vec_VecForEachEntry( Type, vGlob, pEntry, i, k )                                      \
+    for ( i = 0; i < Vec_VecSize(vGlob); i++ )                                                \
+        Vec_PtrForEachEntry( Type, Vec_VecEntry(vGlob, i), pEntry, k ) 
+#define Vec_VecForEachEntryLevel( Type, vGlob, pEntry, i, Level )                             \
+        Vec_PtrForEachEntry( Type, Vec_VecEntry(vGlob, Level), pEntry, i ) 
+#define Vec_VecForEachEntryStart( Type, vGlob, pEntry, i, k, LevelStart )                     \
+    for ( i = LevelStart; i < Vec_VecSize(vGlob); i++ )                                       \
+        Vec_PtrForEachEntry( Type, Vec_VecEntry(vGlob, i), pEntry, k ) 
+#define Vec_VecForEachEntryStartStop( Type, vGlob, pEntry, i, k, LevelStart, LevelStop )      \
+    for ( i = LevelStart; i < LevelStop; i++ )                                                \
+        Vec_PtrForEachEntry( Type, Vec_VecEntry(vGlob, i), pEntry, k ) 
+#define Vec_VecForEachEntryReverse( Type, vGlob, pEntry, i, k )                               \
+    for ( i = 0; i < Vec_VecSize(vGlob); i++ )                                                \
+        Vec_PtrForEachEntryReverse( Type, Vec_VecEntry(vGlob, i), pEntry, k ) 
+#define Vec_VecForEachEntryReverseReverse( Type, vGlob, pEntry, i, k )                        \
+    for ( i = Vec_VecSize(vGlob) - 1; i >= 0; i-- )                                           \
+        Vec_PtrForEachEntryReverse( Type, Vec_VecEntry(vGlob, i), pEntry, k ) 
+#define Vec_VecForEachEntryReverseStart( Type, vGlob, pEntry, i, k, LevelStart )              \
+    for ( i = LevelStart-1; i >= 0; i-- )                                                     \
+        Vec_PtrForEachEntry( Type, Vec_VecEntry(vGlob, i), pEntry, k ) 
+
+// iteratores through entries
+#define Vec_VecForEachEntryInt( vGlob, Entry, i, k )                                          \
+    for ( i = 0; i < Vec_VecSize(vGlob); i++ )                                                \
+        Vec_IntForEachEntry( Vec_VecEntryInt(vGlob, i), Entry, k ) 
+#define Vec_VecForEachEntryIntLevel( vGlob, Entry, i, Level )                                 \
+        Vec_IntForEachEntry( Vec_VecEntryInt(vGlob, Level), Entry, i ) 
+#define Vec_VecForEachEntryIntStart( vGlob, Entry, i, k, LevelStart )                         \
+    for ( i = LevelStart; i < Vec_VecSize(vGlob); i++ )                                       \
+        Vec_IntForEachEntry( Vec_VecEntryInt(vGlob, i), Entry, k ) 
+#define Vec_VecForEachEntryIntStartStop( vGlob, Entry, i, k, LevelStart, LevelStop )          \
+    for ( i = LevelStart; i < LevelStop; i++ )                                                \
+        Vec_IntForEachEntry( Vec_VecEntryInt(vGlob, i), Entry, k ) 
+#define Vec_VecForEachEntryIntReverse( vGlob, Entry, i, k )                                   \
+    for ( i = 0; i < Vec_VecSize(vGlob); i++ )                                                \
+        Vec_IntForEachEntryReverse( Vec_VecEntryInt(vGlob, i), Entry, k ) 
+#define Vec_VecForEachEntryIntReverseReverse( vGlob, Entry, i, k )                            \
+    for ( i = Vec_VecSize(vGlob) - 1; i >= 0; i-- )                                           \
+        Vec_IntForEachEntryReverse( Vec_VecEntryInt(vGlob, i), Entry, k ) 
+#define Vec_VecForEachEntryIntReverseStart( vGlob, Entry, i, k, LevelStart )                  \
+    for ( i = LevelStart-1; i >= 0; i-- )                                                     \
+        Vec_IntForEachEntry( Vec_VecEntryInt(vGlob, i), Entry, k ) 
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Vec_t * Vec_VecAlloc( int nCap )
+{
+    Vec_Vec_t * p;
+    p = ABC_ALLOC( Vec_Vec_t, 1 );
+    if ( nCap > 0 && nCap < 8 )
+        nCap = 8;
+    p->nSize  = 0;
+    p->nCap   = nCap;
+    p->pArray = p->nCap? ABC_ALLOC( void *, p->nCap ) : NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Vec_t * Vec_VecStart( int nSize )
+{
+    Vec_Vec_t * p;
+    int i;
+    p = Vec_VecAlloc( nSize );
+    for ( i = 0; i < nSize; i++ )
+        p->pArray[i] = Vec_PtrAlloc( 0 );
+    p->nSize = nSize;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_VecExpand( Vec_Vec_t * p, int Level )
+{
+    int i;
+    if ( p->nSize >= Level + 1 )
+        return;
+    Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 );
+    for ( i = p->nSize; i <= Level; i++ )
+        p->pArray[i] = Vec_PtrAlloc( 0 );
+    p->nSize = Level + 1;
+}
+static inline void Vec_VecExpandInt( Vec_Vec_t * p, int Level )
+{
+    int i;
+    if ( p->nSize >= Level + 1 )
+        return;
+    Vec_IntGrow( (Vec_Int_t *)p, Level + 1 );
+    for ( i = p->nSize; i <= Level; i++ )
+        p->pArray[i] = Vec_PtrAlloc( 0 );
+    p->nSize = Level + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_VecSize( Vec_Vec_t * p )
+{
+    return p->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_VecCap( Vec_Vec_t * p )
+{
+    return p->nCap;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_VecLevelSize( Vec_Vec_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return Vec_PtrSize( (Vec_Ptr_t *)p->pArray[i] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_VecEntry( Vec_Vec_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return (Vec_Ptr_t *)p->pArray[i];
+}
+static inline Vec_Int_t * Vec_VecEntryInt( Vec_Vec_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return (Vec_Int_t *)p->pArray[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline double Vec_VecMemory( Vec_Vec_t * p )
+{
+    int i;
+    double Mem;
+    if ( p == NULL )  return 0.0;
+    Mem = Vec_PtrMemory( (Vec_Ptr_t *)p );
+    for ( i = 0; i < p->nSize; i++ )
+        if ( Vec_VecEntry(p, i) )
+            Mem += Vec_PtrMemory( Vec_VecEntry(p, i) );
+    return Mem;
+}
+static inline double Vec_VecMemoryInt( Vec_Vec_t * p )
+{
+    int i;
+    double Mem;
+    if ( p == NULL )  return 0.0;
+    Mem = Vec_PtrMemory( (Vec_Ptr_t *)p );
+    for ( i = 0; i < p->nSize; i++ )
+        if ( Vec_VecEntry(p, i) )
+            Mem += Vec_IntMemory( Vec_VecEntryInt(p, i) );
+    return Mem;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void * Vec_VecEntryEntry( Vec_Vec_t * p, int i, int k )
+{
+    return Vec_PtrEntry( Vec_VecEntry(p, i), k );
+}
+static inline int Vec_VecEntryEntryInt( Vec_Vec_t * p, int i, int k )
+{
+    return Vec_IntEntry( Vec_VecEntryInt(p, i), k );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_VecFree( Vec_Vec_t * p )
+{
+    Vec_Ptr_t * vVec;
+    int i;
+    Vec_VecForEachLevel( p, vVec, i )
+        if ( vVec ) Vec_PtrFree( vVec );
+    Vec_PtrFree( (Vec_Ptr_t *)p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_VecFreeP( Vec_Vec_t ** p )
+{
+    if ( *p == NULL )
+        return;
+    Vec_VecFree( *p );
+    *p = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Vec_t * Vec_VecDup( Vec_Vec_t * p )
+{
+    Vec_Ptr_t * vNew, * vVec;
+    int i;
+    vNew = Vec_PtrAlloc( Vec_VecSize(p) );
+    Vec_VecForEachLevel( p, vVec, i )
+        Vec_PtrPush( vNew, Vec_PtrDup(vVec) );
+    return (Vec_Vec_t *)vNew;
+}
+static inline Vec_Vec_t * Vec_VecDupInt( Vec_Vec_t * p )
+{
+    Vec_Ptr_t * vNew;
+    Vec_Int_t * vVec;
+    int i;
+    vNew = Vec_PtrAlloc( Vec_VecSize(p) );
+    Vec_VecForEachLevelInt( p, vVec, i )
+        Vec_PtrPush( vNew, Vec_IntDup(vVec) );
+    return (Vec_Vec_t *)vNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the vector of vectors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_VecSizeSize( Vec_Vec_t * p )
+{
+    Vec_Ptr_t * vVec;
+    int i, Counter = 0;
+    Vec_VecForEachLevel( p, vVec, i )
+        Counter += vVec->nSize;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_VecClear( Vec_Vec_t * p )
+{
+    Vec_Ptr_t * vVec;
+    int i;
+    Vec_VecForEachLevel( p, vVec, i )
+        Vec_PtrClear( vVec );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_VecPush( Vec_Vec_t * p, int Level, void * Entry )
+{
+    if ( p->nSize < Level + 1 )
+    {
+        int i;
+        Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 );
+        for ( i = p->nSize; i < Level + 1; i++ )
+            p->pArray[i] = Vec_PtrAlloc( 0 );
+        p->nSize = Level + 1;
+    }
+    Vec_PtrPush( Vec_VecEntry(p, Level), Entry );
+}
+static inline void Vec_VecPushInt( Vec_Vec_t * p, int Level, int Entry )
+{
+    if ( p->nSize < Level + 1 )
+    {
+        int i;
+        Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 );
+        for ( i = p->nSize; i < Level + 1; i++ )
+            p->pArray[i] = Vec_IntAlloc( 0 );
+        p->nSize = Level + 1;
+    }
+    Vec_IntPush( Vec_VecEntryInt(p, Level), Entry );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_VecPushUnique( Vec_Vec_t * p, int Level, void * Entry )
+{
+    if ( p->nSize < Level + 1 )
+        Vec_VecPush( p, Level, Entry );
+    else
+        Vec_PtrPushUnique( Vec_VecEntry(p, Level), Entry );
+}
+static inline void Vec_VecPushUniqueInt( Vec_Vec_t * p, int Level, int Entry )
+{
+    if ( p->nSize < Level + 1 )
+        Vec_VecPushInt( p, Level, Entry );
+    else
+        Vec_IntPushUnique( Vec_VecEntryInt(p, Level), Entry );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two arrays.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Vec_VecSortCompare1( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 )
+{
+    if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) )
+        return -1;
+    if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) ) 
+        return 1;
+    return 0; 
+}
+static int Vec_VecSortCompare2( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 )
+{
+    if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) )
+        return -1;
+    if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting the entries by their integer value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_VecSort( Vec_Vec_t * p, int fReverse )
+{
+    if ( fReverse ) 
+        qsort( (void *)p->pArray, p->nSize, sizeof(void *), 
+                (int (*)(const void *, const void *)) Vec_VecSortCompare2 );
+    else
+        qsort( (void *)p->pArray, p->nSize, sizeof(void *), 
+                (int (*)(const void *, const void *)) Vec_VecSortCompare1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two integers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Vec_VecSortCompare3( Vec_Int_t ** pp1, Vec_Int_t ** pp2 )
+{
+    if ( Vec_IntEntry(*pp1,0) < Vec_IntEntry(*pp2,0) )
+        return -1;
+    if ( Vec_IntEntry(*pp1,0) > Vec_IntEntry(*pp2,0) ) 
+        return 1;
+    return 0; 
+}
+static int Vec_VecSortCompare4( Vec_Int_t ** pp1, Vec_Int_t ** pp2 )
+{
+    if ( Vec_IntEntry(*pp1,0) > Vec_IntEntry(*pp2,0) )
+        return -1;
+    if ( Vec_IntEntry(*pp1,0) < Vec_IntEntry(*pp2,0) ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting the entries by their integer value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_VecSortByFirstInt( Vec_Vec_t * p, int fReverse )
+{
+    if ( fReverse ) 
+        qsort( (void *)p->pArray, p->nSize, sizeof(void *), 
+                (int (*)(const void *, const void *)) Vec_VecSortCompare4 );
+    else
+        qsort( (void *)p->pArray, p->nSize, sizeof(void *), 
+                (int (*)(const void *, const void *)) Vec_VecSortCompare3 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_VecPrintInt( Vec_Vec_t * p, int fSkipSingles )
+{
+    int i, k, Entry;
+    Vec_VecForEachEntryInt( p, Entry, i, k )
+    {
+        if ( fSkipSingles && Vec_VecLevelSize(p, i) == 1 )
+            break;
+        if ( k == 0 )
+            printf( " %4d : {", i );
+        printf( " %d", Entry );
+        if ( k == Vec_VecLevelSize(p, i) - 1 )
+            printf( " }\n" );
+    }
+}
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/vec/vecWec.h b/abc-build/src/misc/vec/vecWec.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/vec/vecWec.h
@@ -0,0 +1,699 @@
+/**CFile****************************************************************
+
+  FileName    [vecWec.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resizable arrays.]
+
+  Synopsis    [Resizable vector of resizable vectors.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: vecWec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__vec__vecWec_h
+#define ABC__misc__vec__vecWec_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vec_Wec_t_       Vec_Wec_t;
+struct Vec_Wec_t_ 
+{
+    int              nCap;
+    int              nSize;
+    Vec_Int_t *      pArray;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+// iterators through levels 
+#define Vec_WecForEachLevel( vGlob, vVec, i )                                              \
+    for ( i = 0; (i < Vec_WecSize(vGlob)) && (((vVec) = Vec_WecEntry(vGlob, i)), 1); i++ )
+#define Vec_WecForEachLevelVec( vLevels, vGlob, vVec, i )                                  \
+    for ( i = 0; (i < Vec_IntSize(vLevels)) && (((vVec) = Vec_WecEntry(vGlob, Vec_IntEntry(vLevels, i))), 1); i++ )
+#define Vec_WecForEachLevelStart( vGlob, vVec, i, LevelStart )                             \
+    for ( i = LevelStart; (i < Vec_WecSize(vGlob)) && (((vVec) = Vec_WecEntry(vGlob, i)), 1); i++ )
+#define Vec_WecForEachLevelStop( vGlob, vVec, i, LevelStop )                               \
+    for ( i = 0; (i < LevelStop) && (((vVec) = Vec_WecEntry(vGlob, i)), 1); i++ )
+#define Vec_WecForEachLevelStartStop( vGlob, vVec, i, LevelStart, LevelStop )              \
+    for ( i = LevelStart; (i < LevelStop) && (((vVec) = Vec_WecEntry(vGlob, i)), 1); i++ )
+#define Vec_WecForEachLevelReverse( vGlob, vVec, i )                                       \
+    for ( i = Vec_WecSize(vGlob)-1; (i >= 0) && (((vVec) = Vec_WecEntry(vGlob, i)), 1); i-- )
+#define Vec_WecForEachLevelReverseStartStop( vGlob, vVec, i, LevelStart, LevelStop )       \
+    for ( i = LevelStart-1; (i >= LevelStop) && (((vVec) = Vec_WecEntry(vGlob, i)), 1); i-- )
+#define Vec_WecForEachLevelTwo( vGlob1, vGlob2, vVec1, vVec2, i )                          \
+    for ( i = 0; (i < Vec_WecSize(vGlob1)) && (((vVec1) = Vec_WecEntry(vGlob1, i)), 1) && (((vVec2) = Vec_WecEntry(vGlob2, i)), 1); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Wec_t * Vec_WecAlloc( int nCap )
+{
+    Vec_Wec_t * p;
+    p = ABC_ALLOC( Vec_Wec_t, 1 );
+    if ( nCap > 0 && nCap < 8 )
+        nCap = 8;
+    p->nSize  = 0;
+    p->nCap   = nCap;
+    p->pArray = p->nCap? ABC_CALLOC( Vec_Int_t, p->nCap ) : NULL;
+    return p;
+}
+static inline Vec_Wec_t * Vec_WecStart( int nSize )
+{
+    Vec_Wec_t * p;
+    p = Vec_WecAlloc( nSize );
+    p->nSize = nSize;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the vector to the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WecGrow( Vec_Wec_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pArray = ABC_REALLOC( Vec_Int_t, p->pArray, nCapMin ); 
+    memset( p->pArray + p->nCap, 0, sizeof(Vec_Int_t) * (nCapMin - p->nCap) );
+    p->nCap   = nCapMin;
+}
+static inline void Vec_WecInit( Vec_Wec_t * p, int nSize )
+{
+    Vec_WecGrow( p, nSize );
+    p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_WecEntry( Vec_Wec_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray + i;
+}
+static inline Vec_Int_t * Vec_WecEntryLast( Vec_Wec_t * p )
+{
+    assert( p->nSize > 0 );
+    return p->pArray + p->nSize - 1;
+}
+static inline int Vec_WecEntryEntry( Vec_Wec_t * p, int i, int k )
+{
+    return Vec_IntEntry( Vec_WecEntry(p, i), k );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_WecArray( Vec_Wec_t * p )
+{
+    return p->pArray;
+}
+static inline int Vec_WecLevelId( Vec_Wec_t * p, Vec_Int_t * vLevel )
+{
+    assert( p->pArray <= vLevel && vLevel < p->pArray + p->nSize );
+    return vLevel - p->pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_WecCap( Vec_Wec_t * p )
+{
+    return p->nCap;
+}
+static inline int Vec_WecSize( Vec_Wec_t * p )
+{
+    return p->nSize;
+}
+static inline int Vec_WecLevelSize( Vec_Wec_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return Vec_IntSize( p->pArray + i );
+}
+static inline int Vec_WecSizeSize( Vec_Wec_t * p )
+{
+    Vec_Int_t * vVec;
+    int i, Counter = 0;
+    Vec_WecForEachLevel( p, vVec, i )
+        Counter += Vec_IntSize(vVec);
+    return Counter;
+}
+static inline int Vec_WecSizeUsed( Vec_Wec_t * p )
+{
+    Vec_Int_t * vVec;
+    int i, Counter = 0;
+    Vec_WecForEachLevel( p, vVec, i )
+        Counter += (int)(Vec_IntSize(vVec) > 0);
+    return Counter;
+}
+static inline int Vec_WecSizeUsedLimits( Vec_Wec_t * p, int iStart, int iStop )
+{
+    Vec_Int_t * vVec;
+    int i, Counter = 0;
+    Vec_WecForEachLevelStartStop( p, vVec, i, iStart, iStop )
+        Counter += (int)(Vec_IntSize(vVec) > 0);
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WecShrink( Vec_Wec_t * p, int nSizeNew )
+{
+    assert( p->nSize >= nSizeNew );
+    p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WecClear( Vec_Wec_t * p )
+{
+    Vec_Int_t * vVec;
+    int i;
+    Vec_WecForEachLevel( p, vVec, i )
+        Vec_IntClear( vVec );
+    p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WecPush( Vec_Wec_t * p, int Level, int Entry )
+{
+    if ( p->nSize < Level + 1 )
+    {
+        Vec_WecGrow( p, Abc_MaxInt(2*p->nCap, Level + 1) );
+        p->nSize = Level + 1;
+    }
+    Vec_IntPush( Vec_WecEntry(p, Level), Entry );
+}
+static inline Vec_Int_t * Vec_WecPushLevel( Vec_Wec_t * p )
+{
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Vec_WecGrow( p, 16 );
+        else
+            Vec_WecGrow( p, 2 * p->nCap );
+    }
+    ++p->nSize;
+    return Vec_WecEntryLast( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline double Vec_WecMemory( Vec_Wec_t * p )
+{
+    int i;
+    double Mem;
+    if ( p == NULL )  return 0.0;
+    Mem = sizeof(Vec_Int_t) * Vec_WecCap(p);
+    for ( i = 0; i < p->nSize; i++ )
+        Mem += sizeof(int) * Vec_IntCap( Vec_WecEntry(p, i) );
+    return Mem;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WecZero( Vec_Wec_t * p )
+{
+    p->pArray = NULL;
+    p->nSize = 0;
+    p->nCap = 0;
+}
+static inline void Vec_WecErase( Vec_Wec_t * p )
+{
+    int i;
+    for ( i = 0; i < p->nCap; i++ )
+        ABC_FREE( p->pArray[i].pArray );
+    ABC_FREE( p->pArray );
+    p->nSize = 0;
+    p->nCap = 0;
+}
+static inline void Vec_WecFree( Vec_Wec_t * p )
+{
+    Vec_WecErase( p );
+    ABC_FREE( p );
+}
+static inline void Vec_WecFreeP( Vec_Wec_t ** p )
+{
+    if ( *p == NULL )
+        return;
+    Vec_WecFree( *p );
+    *p = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WecPushUnique( Vec_Wec_t * p, int Level, int Entry )
+{
+    if ( p->nSize < Level + 1 )
+        Vec_WecPush( p, Level, Entry );
+    else
+        Vec_IntPushUnique( Vec_WecEntry(p, Level), Entry );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Wec_t * Vec_WecDup( Vec_Wec_t * p )
+{
+    Vec_Wec_t * vNew;
+    Vec_Int_t * vVec;
+    int i, k, Entry;
+    vNew = Vec_WecAlloc( Vec_WecSize(p) );
+    Vec_WecForEachLevel( p, vVec, i )
+        Vec_IntForEachEntry( vVec, Entry, k )
+            Vec_WecPush( vNew, i, Entry );
+    return vNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting by array size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Vec_WecSortCompare1( Vec_Int_t * p1, Vec_Int_t * p2 )
+{
+    if ( Vec_IntSize(p1) < Vec_IntSize(p2) )
+        return -1;
+    if ( Vec_IntSize(p1) > Vec_IntSize(p2) ) 
+        return 1;
+    return 0; 
+}
+static int Vec_WecSortCompare2( Vec_Int_t * p1, Vec_Int_t * p2 )
+{
+    if ( Vec_IntSize(p1) > Vec_IntSize(p2) )
+        return -1;
+    if ( Vec_IntSize(p1) < Vec_IntSize(p2) ) 
+        return 1;
+    return 0; 
+}
+static inline void Vec_WecSort( Vec_Wec_t * p, int fReverse )
+{
+    if ( fReverse ) 
+        qsort( (void *)p->pArray, p->nSize, sizeof(Vec_Int_t), 
+                (int (*)(const void *, const void *)) Vec_WecSortCompare2 );
+    else
+        qsort( (void *)p->pArray, p->nSize, sizeof(Vec_Int_t), 
+                (int (*)(const void *, const void *)) Vec_WecSortCompare1 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting by the first entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Vec_WecSortCompare3( Vec_Int_t * p1, Vec_Int_t * p2 )
+{
+    if ( Vec_IntEntry(p1,0) < Vec_IntEntry(p2,0) )
+        return -1;
+    if ( Vec_IntEntry(p1,0) > Vec_IntEntry(p2,0) ) 
+        return 1;
+    return 0; 
+}
+static int Vec_WecSortCompare4( Vec_Int_t * p1, Vec_Int_t * p2 )
+{
+    if ( Vec_IntEntry(p1,0) > Vec_IntEntry(p2,0) )
+        return -1;
+    if ( Vec_IntEntry(p1,0) < Vec_IntEntry(p2,0) ) 
+        return 1;
+    return 0; 
+}
+static inline void Vec_WecSortByFirstInt( Vec_Wec_t * p, int fReverse )
+{
+    if ( fReverse ) 
+        qsort( (void *)p->pArray, p->nSize, sizeof(Vec_Int_t), 
+                (int (*)(const void *, const void *)) Vec_WecSortCompare4 );
+    else
+        qsort( (void *)p->pArray, p->nSize, sizeof(Vec_Int_t), 
+                (int (*)(const void *, const void *)) Vec_WecSortCompare3 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting by the last entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Vec_WecSortCompare5( Vec_Int_t * p1, Vec_Int_t * p2 )
+{
+    if ( Vec_IntEntryLast(p1) < Vec_IntEntryLast(p2) )
+        return -1;
+    if ( Vec_IntEntryLast(p1) > Vec_IntEntryLast(p2) ) 
+        return 1;
+    return 0; 
+}
+static int Vec_WecSortCompare6( Vec_Int_t * p1, Vec_Int_t * p2 )
+{
+    if ( Vec_IntEntryLast(p1) > Vec_IntEntryLast(p2) )
+        return -1;
+    if ( Vec_IntEntryLast(p1) < Vec_IntEntryLast(p2) ) 
+        return 1;
+    return 0; 
+}
+static inline void Vec_WecSortByLastInt( Vec_Wec_t * p, int fReverse )
+{
+    if ( fReverse ) 
+        qsort( (void *)p->pArray, p->nSize, sizeof(Vec_Int_t), 
+                (int (*)(const void *, const void *)) Vec_WecSortCompare6 );
+    else
+        qsort( (void *)p->pArray, p->nSize, sizeof(Vec_Int_t), 
+                (int (*)(const void *, const void *)) Vec_WecSortCompare5 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WecPrint( Vec_Wec_t * p, int fSkipSingles )
+{
+    Vec_Int_t * vVec;
+    int i, k, Entry;
+    Vec_WecForEachLevel( p, vVec, i )
+    {
+        if ( fSkipSingles && Vec_IntSize(vVec) == 1 )
+            continue;
+        printf( " %4d : {", i );
+        Vec_IntForEachEntry( vVec, Entry, k )
+            printf( " %d", Entry );
+        printf( " }\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the set of equivalence classes.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Wec_t * Vec_WecCreateClasses( Vec_Int_t * vMap )
+{
+    Vec_Wec_t * vClasses;
+    int i, Entry;
+    vClasses = Vec_WecStart( Vec_IntFindMax(vMap) + 1 );
+    Vec_IntForEachEntry( vMap, Entry, i )
+        Vec_WecPush( vClasses, Entry, i );
+    return vClasses;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_WecCountNonTrivial( Vec_Wec_t * p, int * pnUsed )
+{
+    Vec_Int_t * vClass;
+    int i, nClasses = 0;
+    *pnUsed = 0;
+    Vec_WecForEachLevel( p, vClass, i )
+    {
+        if ( Vec_IntSize(vClass) < 2 )
+            continue;
+        nClasses++;
+        (*pnUsed) += Vec_IntSize(vClass);
+    }
+    return nClasses;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_WecCollectFirsts( Vec_Wec_t * p )
+{
+    Vec_Int_t * vFirsts, * vLevel;
+    int i;
+    vFirsts = Vec_IntAlloc( Vec_WecSize(p) );
+    Vec_WecForEachLevel( p, vLevel, i )
+        if ( Vec_IntSize(vLevel) > 0 )
+            Vec_IntPush( vFirsts, Vec_IntEntry(vLevel, 0) );
+    return vFirsts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_WecConvertToVecPtr( Vec_Wec_t * p )
+{
+    Vec_Ptr_t * vCopy;
+    Vec_Int_t * vLevel;
+    int i;
+    vCopy = Vec_PtrAlloc( Vec_WecSize(p) );
+    Vec_WecForEachLevel( p, vLevel, i )
+        Vec_PtrPush( vCopy, Vec_IntDup(vLevel) );
+    return vCopy;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Temporary vector marking.]
+
+  Description [The vector should be static when the marking is used.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int  Vec_WecIntHasMark( Vec_Int_t * vVec ) { return (vVec->nCap >> 30) & 1; }
+static inline void Vec_WecIntSetMark( Vec_Int_t * vVec ) { vVec->nCap |= (1<<30);         }
+static inline void Vec_WecIntXorMark( Vec_Int_t * vVec ) { vVec->nCap ^= (1<<30);         }
+static inline void Vec_WecMarkLevels( Vec_Wec_t * vCubes, Vec_Int_t * vLevels )
+{
+    Vec_Int_t * vCube;
+    int i;
+    Vec_WecForEachLevelVec( vLevels, vCubes, vCube, i )
+    {
+        assert( !Vec_WecIntHasMark( vCube ) );
+        Vec_WecIntXorMark( vCube );
+    }
+}
+static inline void Vec_WecUnmarkLevels( Vec_Wec_t * vCubes, Vec_Int_t * vLevels )
+{
+    Vec_Int_t * vCube;
+    int i;
+    Vec_WecForEachLevelVec( vLevels, vCubes, vCube, i )
+    {
+        assert( Vec_WecIntHasMark( vCube ) );
+        Vec_WecIntXorMark( vCube );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes 0-size vectors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WecRemoveEmpty( Vec_Wec_t * vCubes )
+{
+    Vec_Int_t * vCube;
+    int i, k = 0;
+    Vec_WecForEachLevel( vCubes, vCube, i )
+        if ( Vec_IntSize(vCube) > 0 )
+            vCubes->pArray[k++] = *vCube;
+        else
+            ABC_FREE( vCube->pArray );
+    for ( i = k; i < Vec_WecSize(vCubes); i++ )
+        Vec_IntZero( Vec_WecEntry(vCubes, i) );
+    Vec_WecShrink( vCubes, k );
+//    Vec_WecSortByFirstInt( vCubes, 0 );
+}
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/vec/vecWrd.h b/abc-build/src/misc/vec/vecWrd.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/vec/vecWrd.h
@@ -0,0 +1,1165 @@
+/**CFile****************************************************************
+
+  FileName    [vecWrd.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resizable arrays.]
+
+  Synopsis    [Resizable arrays of long unsigned integers.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: vecWrd.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__misc__vec__vecWrd_h
+#define ABC__misc__vec__vecWrd_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vec_Wrd_t_       Vec_Wrd_t;
+struct Vec_Wrd_t_ 
+{
+    int              nCap;
+    int              nSize;
+    word *           pArray;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define Vec_WrdForEachEntry( vVec, Entry, i )                                               \
+    for ( i = 0; (i < Vec_WrdSize(vVec)) && (((Entry) = Vec_WrdEntry(vVec, i)), 1); i++ )
+#define Vec_WrdForEachEntryStart( vVec, Entry, i, Start )                                   \
+    for ( i = Start; (i < Vec_WrdSize(vVec)) && (((Entry) = Vec_WrdEntry(vVec, i)), 1); i++ )
+#define Vec_WrdForEachEntryStop( vVec, Entry, i, Stop )                                   \
+    for ( i = 0; (i < Stop) && (((Entry) = Vec_WrdEntry(vVec, i)), 1); i++ )
+#define Vec_WrdForEachEntryStartStop( vVec, Entry, i, Start, Stop )                         \
+    for ( i = Start; (i < Stop) && (((Entry) = Vec_WrdEntry(vVec, i)), 1); i++ )
+#define Vec_WrdForEachEntryReverse( vVec, pEntry, i )                                       \
+    for ( i = Vec_WrdSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_WrdEntry(vVec, i)), 1); i-- )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Wrd_t * Vec_WrdAlloc( int nCap )
+{
+    Vec_Wrd_t * p;
+    p = ABC_ALLOC( Vec_Wrd_t, 1 );
+    if ( nCap > 0 && nCap < 16 )
+        nCap = 16;
+    p->nSize  = 0;
+    p->nCap   = nCap;
+    p->pArray = p->nCap? ABC_ALLOC( word, p->nCap ) : NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given size and cleans it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Wrd_t * Vec_WrdStart( int nSize )
+{
+    Vec_Wrd_t * p;
+    p = Vec_WrdAlloc( nSize );
+    p->nSize = nSize;
+    memset( p->pArray, 0, sizeof(word) * nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given size and cleans it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Wrd_t * Vec_WrdStartFull( int nSize )
+{
+    Vec_Wrd_t * p;
+    p = Vec_WrdAlloc( nSize );
+    p->nSize = nSize;
+    memset( p->pArray, 0xff, sizeof(word) * nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given size and cleans it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Wrd_t * Vec_WrdStartNatural( int nSize )
+{
+    Vec_Wrd_t * p;
+    int i;
+    p = Vec_WrdAlloc( nSize );
+    p->nSize = nSize;
+    for ( i = 0; i < nSize; i++ )
+        p->pArray[i] = i;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the vector from an integer array of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Wrd_t * Vec_WrdAllocArray( word * pArray, int nSize )
+{
+    Vec_Wrd_t * p;
+    p = ABC_ALLOC( Vec_Wrd_t, 1 );
+    p->nSize  = nSize;
+    p->nCap   = nSize;
+    p->pArray = pArray;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the vector from an integer array of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Wrd_t * Vec_WrdAllocArrayCopy( word * pArray, int nSize )
+{
+    Vec_Wrd_t * p;
+    p = ABC_ALLOC( Vec_Wrd_t, 1 );
+    p->nSize  = nSize;
+    p->nCap   = nSize;
+    p->pArray = ABC_ALLOC( word, nSize );
+    memcpy( p->pArray, pArray, sizeof(word) * nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the integer array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Wrd_t * Vec_WrdDup( Vec_Wrd_t * pVec )
+{
+    Vec_Wrd_t * p;
+    p = ABC_ALLOC( Vec_Wrd_t, 1 );
+    p->nSize  = pVec->nSize;
+    p->nCap   = pVec->nSize;
+    p->pArray = p->nCap? ABC_ALLOC( word, p->nCap ) : NULL;
+    memcpy( p->pArray, pVec->pArray, sizeof(word) * pVec->nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the array into another vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Wrd_t * Vec_WrdDupArray( Vec_Wrd_t * pVec )
+{
+    Vec_Wrd_t * p;
+    p = ABC_ALLOC( Vec_Wrd_t, 1 );
+    p->nSize  = pVec->nSize;
+    p->nCap   = pVec->nCap;
+    p->pArray = pVec->pArray;
+    pVec->nSize  = 0;
+    pVec->nCap   = 0;
+    pVec->pArray = NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdErase( Vec_Wrd_t * p )
+{
+    ABC_FREE( p->pArray );
+    p->nSize = 0;
+    p->nCap = 0;
+}
+static inline void Vec_WrdFree( Vec_Wrd_t * p )
+{
+    ABC_FREE( p->pArray );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdFreeP( Vec_Wrd_t ** p )
+{
+    if ( *p == NULL )
+        return;
+    ABC_FREE( (*p)->pArray );
+    ABC_FREE( (*p) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word * Vec_WrdReleaseArray( Vec_Wrd_t * p )
+{
+    word * pArray = p->pArray;
+    p->nCap = 0;
+    p->nSize = 0;
+    p->pArray = NULL;
+    return pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word * Vec_WrdArray( Vec_Wrd_t * p )
+{
+    return p->pArray;
+}
+static inline word * Vec_WrdLimit( Vec_Wrd_t * p )
+{
+    return p->pArray + p->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_WrdSize( Vec_Wrd_t * p )
+{
+    return p->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_WrdCap( Vec_Wrd_t * p )
+{
+    return p->nCap;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline double Vec_WrdMemory( Vec_Wrd_t * p )
+{
+    return !p ? 0.0 : 1.0 * sizeof(word) * p->nCap + sizeof(Vec_Wrd_t);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Vec_WrdEntry( Vec_Wrd_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word * Vec_WrdEntryP( Vec_Wrd_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray + i;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdWriteEntry( Vec_Wrd_t * p, int i, word Entry )
+{
+    assert( i >= 0 && i < p->nSize );
+    p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Vec_WrdAddToEntry( Vec_Wrd_t * p, int i, word Addition )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray[i] += Addition;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Vec_WrdEntryLast( Vec_Wrd_t * p )
+{
+    assert( p->nSize > 0 );
+    return p->pArray[p->nSize-1];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the vector to the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdGrow( Vec_Wrd_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pArray = ABC_REALLOC( word, p->pArray, nCapMin ); 
+    assert( p->pArray );
+    p->nCap   = nCapMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fills the vector with given number of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdFill( Vec_Wrd_t * p, int nSize, word Fill )
+{
+    int i;
+    Vec_WrdGrow( p, nSize );
+    for ( i = 0; i < nSize; i++ )
+        p->pArray[i] = Fill;
+    p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fills the vector with given number of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdFillExtra( Vec_Wrd_t * p, int nSize, word Fill )
+{
+    int i;
+    if ( nSize <= p->nSize )
+        return;
+    if ( nSize > 2 * p->nCap )
+        Vec_WrdGrow( p, nSize );
+    else if ( nSize > p->nCap )
+        Vec_WrdGrow( p, 2 * p->nCap );
+    for ( i = p->nSize; i < nSize; i++ )
+        p->pArray[i] = Fill;
+    p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the entry even if the place not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Vec_WrdGetEntry( Vec_Wrd_t * p, int i )
+{
+    Vec_WrdFillExtra( p, i + 1, 0 );
+    return Vec_WrdEntry( p, i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the entry even if the place not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word * Vec_WrdGetEntryP( Vec_Wrd_t * p, int i )
+{
+    Vec_WrdFillExtra( p, i + 1, 0 );
+    return Vec_WrdEntryP( p, i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the entry even if the place does not exist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdSetEntry( Vec_Wrd_t * p, int i, word Entry )
+{
+    Vec_WrdFillExtra( p, i + 1, 0 );
+    Vec_WrdWriteEntry( p, i, Entry );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdShrink( Vec_Wrd_t * p, int nSizeNew )
+{
+    assert( p->nSize >= nSizeNew );
+    p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdClear( Vec_Wrd_t * p )
+{
+    p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdPush( Vec_Wrd_t * p, word Entry )
+{
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Vec_WrdGrow( p, 16 );
+        else
+            Vec_WrdGrow( p, 2 * p->nCap );
+    }
+    p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdPushFirst( Vec_Wrd_t * p, word Entry )
+{
+    int i;
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Vec_WrdGrow( p, 16 );
+        else
+            Vec_WrdGrow( p, 2 * p->nCap );
+    }
+    p->nSize++;
+    for ( i = p->nSize - 1; i >= 1; i-- )
+        p->pArray[i] = p->pArray[i-1];
+    p->pArray[0] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the entry while preserving the increasing order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdPushOrder( Vec_Wrd_t * p, word Entry )
+{
+    int i;
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Vec_WrdGrow( p, 16 );
+        else
+            Vec_WrdGrow( p, 2 * p->nCap );
+    }
+    p->nSize++;
+    for ( i = p->nSize-2; i >= 0; i-- )
+        if ( p->pArray[i] > Entry )
+            p->pArray[i+1] = p->pArray[i];
+        else
+            break;
+    p->pArray[i+1] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the entry while preserving the increasing order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_WrdPushUniqueOrder( Vec_Wrd_t * p, word Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            return 1;
+    Vec_WrdPushOrder( p, Entry );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_WrdPushUnique( Vec_Wrd_t * p, word Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            return 1;
+    Vec_WrdPush( p, Entry );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the pointer to the next nWords entries in the vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word * Vec_WrdFetch( Vec_Wrd_t * p, int nWords )
+{
+    if ( nWords == 0 )
+        return NULL;
+    assert( nWords > 0 );
+    p->nSize += nWords;
+    if ( p->nSize > p->nCap )
+    {
+//         Vec_WrdGrow( p, 2 * p->nSize );
+        return NULL;
+    }
+    return p->pArray + p->nSize - nWords;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the last entry and removes it from the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Vec_WrdPop( Vec_Wrd_t * p )
+{
+    assert( p->nSize > 0 );
+    return p->pArray[--p->nSize];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_WrdFind( Vec_Wrd_t * p, word Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            return i;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_WrdRemove( Vec_Wrd_t * p, word Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            break;
+    if ( i == p->nSize )
+        return 0;
+    assert( i < p->nSize );
+    for ( i++; i < p->nSize; i++ )
+        p->pArray[i-1] = p->pArray[i];
+    p->nSize--;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Interts entry at the index iHere. Shifts other entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdInsert( Vec_Wrd_t * p, int iHere, word Entry )
+{
+    int i;
+    assert( iHere >= 0 && iHere < p->nSize );
+    Vec_WrdPush( p, 0 );
+    for ( i = p->nSize - 1; i > iHere; i-- )
+        p->pArray[i] = p->pArray[i-1];
+    p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Vec_WrdFindMax( Vec_Wrd_t * p )
+{
+    word Best;
+    int i;
+    if ( p->nSize == 0 )
+        return 0;
+    Best = p->pArray[0];
+    for ( i = 1; i < p->nSize; i++ )
+        if ( Best < p->pArray[i] )
+            Best = p->pArray[i];
+    return Best;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Vec_WrdFindMin( Vec_Wrd_t * p )
+{
+    word Best;
+    int i;
+    if ( p->nSize == 0 )
+        return 0;
+    Best = p->pArray[0];
+    for ( i = 1; i < p->nSize; i++ )
+        if ( Best > p->pArray[i] )
+            Best = p->pArray[i];
+    return Best;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reverses the order of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdReverseOrder( Vec_Wrd_t * p )
+{
+    word Temp;
+    int i;
+    for ( i = 0; i < p->nSize/2; i++ )
+    {
+        Temp = p->pArray[i];
+        p->pArray[i] = p->pArray[p->nSize-1-i];
+        p->pArray[p->nSize-1-i] = Temp;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Wrd_t * Vec_WrdInvert( Vec_Wrd_t * p, word Fill ) 
+{
+    int i;
+    word Entry;
+    Vec_Wrd_t * vRes = Vec_WrdAlloc( 0 );
+    Vec_WrdFill( vRes, Vec_WrdFindMax(p) + 1, Fill );
+    Vec_WrdForEachEntry( p, Entry, i )
+        if ( Entry != Fill )
+            Vec_WrdWriteEntry( vRes, Entry, i );
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Vec_WrdSum( Vec_Wrd_t * p ) 
+{
+    word Counter = 0;
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        Counter += p->pArray[i];
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if two vectors are equal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_WrdEqual( Vec_Wrd_t * p1, Vec_Wrd_t * p2 ) 
+{
+    int i;
+    if ( p1->nSize != p2->nSize )
+        return 0;
+    for ( i = 0; i < p1->nSize; i++ )
+        if ( p1->pArray[i] != p2->pArray[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of common entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vec_WrdCountCommon( Vec_Wrd_t * p1, Vec_Wrd_t * p2 ) 
+{
+    Vec_Wrd_t * vTemp;
+    word Entry;
+    int i, Counter = 0;
+    if ( Vec_WrdSize(p1) < Vec_WrdSize(p2) )
+        vTemp = p1, p1 = p2, p2 = vTemp;
+    assert( Vec_WrdSize(p1) >= Vec_WrdSize(p2) );
+    vTemp = Vec_WrdInvert( p2, -1 );
+    Vec_WrdFillExtra( vTemp, Vec_WrdFindMax(p1) + 1, ~((word)0) );
+    Vec_WrdForEachEntry( p1, Entry, i )
+        if ( Vec_WrdEntry(vTemp, Entry) != ~((word)0) )
+            Counter++;
+    Vec_WrdFree( vTemp );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two integers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Vec_WrdSortCompare1( word * pp1, word * pp2 )
+{
+    // for some reason commenting out lines (as shown) led to crashing of the release version
+    if ( *pp1 < *pp2 )
+        return -1;
+    if ( *pp1 > *pp2 ) //
+        return 1;
+    return 0; //
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two integers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Vec_WrdSortCompare2( word * pp1, word * pp2 )
+{
+    // for some reason commenting out lines (as shown) led to crashing of the release version
+    if ( *pp1 > *pp2 )
+        return -1;
+    if ( *pp1 < *pp2 ) //
+        return 1;
+    return 0; //
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting the entries by their integer value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdSort( Vec_Wrd_t * p, int fReverse )
+{
+    if ( fReverse ) 
+        qsort( (void *)p->pArray, p->nSize, sizeof(word), 
+                (int (*)(const void *, const void *)) Vec_WrdSortCompare2 );
+    else
+        qsort( (void *)p->pArray, p->nSize, sizeof(word), 
+                (int (*)(const void *, const void *)) Vec_WrdSortCompare1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Leaves only unique entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdUniqify( Vec_Wrd_t * p )
+{
+    int i, k;
+    if ( p->nSize < 2 )
+        return;
+    Vec_WrdSort( p, 0 );
+    for ( i = k = 1; i < p->nSize; i++ )
+        if ( p->pArray[i] != p->pArray[i-1] )
+            p->pArray[k++] = p->pArray[i];
+    p->nSize = k;
+}
+static inline Vec_Wrd_t * Vec_WrdUniqifyHash( Vec_Wrd_t * vData, int nWordSize )
+{
+    Vec_Int_t * vResInt;
+    Vec_Int_t * vDataInt = (Vec_Int_t *)vData;
+    vDataInt->nSize *= 2;
+    vDataInt->nCap *= 2;
+    vResInt = Vec_IntUniqifyHash( vDataInt, 2 * nWordSize );
+    vDataInt->nSize /= 2;
+    vDataInt->nCap /= 2;
+    vResInt->nSize /= 2;
+    vResInt->nCap /= 2;
+    return (Vec_Wrd_t *)vResInt;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two integers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Vec_WrdSortCompareUnsigned( word * pp1, word * pp2 )
+{
+    if ( *pp1 < *pp2 )
+        return -1;
+    if ( *pp1 > *pp2 )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting the entries by their integer value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdSortUnsigned( Vec_Wrd_t * p )
+{
+    qsort( (void *)p->pArray, p->nSize, sizeof(word), 
+            (int (*)(const void *, const void *)) Vec_WrdSortCompareUnsigned );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Appends the contents of the second vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_WrdAppend( Vec_Wrd_t * vVec1, Vec_Wrd_t * vVec2 )
+{
+    word Entry; int i;
+    Vec_WrdForEachEntry( vVec2, Entry, i )
+        Vec_WrdPush( vVec1, Entry );
+}
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/misc/zlib/README b/abc-build/src/misc/zlib/README
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/README
@@ -0,0 +1,115 @@
+ZLIB DATA COMPRESSION LIBRARY
+
+zlib 1.2.5 is a general purpose data compression library.  All the code is
+thread safe.  The data format used by the zlib library is described by RFCs
+(Request for Comments) 1950 to 1952 in the files
+http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
+and rfc1952.txt (gzip format).
+
+All functions of the compression library are documented in the file zlib.h
+(volunteer to write man pages welcome, contact zlib@gzip.org).  A usage example
+of the library is given in the file example.c which also tests that the library
+is working correctly.  Another example is given in the file minigzip.c.  The
+compression library itself is composed of all source files except example.c and
+minigzip.c.
+
+To compile all files and run the test program, follow the instructions given at
+the top of Makefile.in.  In short "./configure; make test", and if that goes
+well, "make install" should work for most flavors of Unix.  For Windows, use one
+of the special makefiles in win32/ or contrib/vstudio/ .  For VMS, use
+make_vms.com.
+
+Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
+<info@winimage.com> for the Windows DLL version.  The zlib home page is
+http://zlib.net/ .  Before reporting a problem, please check this site to
+verify that you have the latest version of zlib; otherwise get the latest
+version and check whether the problem still exists or not.
+
+PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help.
+
+Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan.  1997
+issue of Dr.  Dobb's Journal; a copy of the article is available at
+http://marknelson.us/1997/01/01/zlib-engine/ .
+
+The changes made in version 1.2.5 are documented in the file ChangeLog.
+
+Unsupported third party contributions are provided in directory contrib/ .
+
+zlib is available in Java using the java.util.zip package, documented at
+http://java.sun.com/developer/technicalArticles/Programming/compression/ .
+
+A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is available
+at CPAN (Comprehensive Perl Archive Network) sites, including
+http://search.cpan.org/~pmqs/IO-Compress-Zlib/ .
+
+A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
+available in Python 1.5 and later versions, see
+http://www.python.org/doc/lib/module-zlib.html .
+
+zlib is built into tcl: http://wiki.tcl.tk/4610 .
+
+An experimental package to read and write files in .zip format, written on top
+of zlib by Gilles Vollant <info@winimage.com>, is available in the
+contrib/minizip directory of zlib.
+
+
+Notes for some targets:
+
+- For Windows DLL versions, please see win32/DLL_FAQ.txt
+
+- For 64-bit Irix, deflate.c must be compiled without any optimization. With
+  -O, one libpng test fails. The test works in 32 bit mode (with the -n32
+  compiler flag). The compiler bug has been reported to SGI.
+
+- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
+  when compiled with cc.
+
+- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
+  necessary to get gzprintf working correctly. This is done by configure.
+
+- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
+  other compilers. Use "make test" to check your compiler.
+
+- gzdopen is not supported on RISCOS or BEOS.
+
+- For PalmOs, see http://palmzlib.sourceforge.net/
+
+
+Acknowledgments:
+
+  The deflate format used by zlib was defined by Phil Katz.  The deflate and
+  zlib specifications were written by L.  Peter Deutsch.  Thanks to all the
+  people who reported problems and suggested various improvements in zlib; they
+  are too numerous to cite here.
+
+Copyright notice:
+
+ (C) 1995-2010 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not* receiving
+lengthy legal documents to sign.  The sources are provided for free but without
+warranty of any kind.  The library has been entirely written by Jean-loup
+Gailly and Mark Adler; it does not include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include in
+the file ChangeLog history information documenting your changes.  Please read
+the FAQ for more information on the distribution of modified source versions.
diff --git a/abc-build/src/misc/zlib/adler32.c b/abc-build/src/misc/zlib/adler32.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/adler32.c
@@ -0,0 +1,168 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2007 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc/util/abc_global.h"
+
+#include "zutil.h"
+
+ABC_NAMESPACE_IMPL_START
+
+#define local static
+
+local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2);
+
+#define BASE 65521UL    /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);
+
+/* use NO_DIVIDE if your processor does not do division in hardware */
+#ifdef NO_DIVIDE
+#  define MOD(a) \
+    do { \
+        if (a >= (BASE << 16)) a -= (BASE << 16); \
+        if (a >= (BASE << 15)) a -= (BASE << 15); \
+        if (a >= (BASE << 14)) a -= (BASE << 14); \
+        if (a >= (BASE << 13)) a -= (BASE << 13); \
+        if (a >= (BASE << 12)) a -= (BASE << 12); \
+        if (a >= (BASE << 11)) a -= (BASE << 11); \
+        if (a >= (BASE << 10)) a -= (BASE << 10); \
+        if (a >= (BASE << 9)) a -= (BASE << 9); \
+        if (a >= (BASE << 8)) a -= (BASE << 8); \
+        if (a >= (BASE << 7)) a -= (BASE << 7); \
+        if (a >= (BASE << 6)) a -= (BASE << 6); \
+        if (a >= (BASE << 5)) a -= (BASE << 5); \
+        if (a >= (BASE << 4)) a -= (BASE << 4); \
+        if (a >= (BASE << 3)) a -= (BASE << 3); \
+        if (a >= (BASE << 2)) a -= (BASE << 2); \
+        if (a >= (BASE << 1)) a -= (BASE << 1); \
+        if (a >= BASE) a -= BASE; \
+    } while (0)
+#  define MOD4(a) \
+    do { \
+        if (a >= (BASE << 4)) a -= (BASE << 4); \
+        if (a >= (BASE << 3)) a -= (BASE << 3); \
+        if (a >= (BASE << 2)) a -= (BASE << 2); \
+        if (a >= (BASE << 1)) a -= (BASE << 1); \
+        if (a >= BASE) a -= BASE; \
+    } while (0)
+#else
+#  define MOD(a) a %= BASE
+#  define MOD4(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len)
+{
+    unsigned long sum2;
+    unsigned n;
+
+    /* split Adler-32 into component sums */
+    sum2 = (adler >> 16) & 0xffff;
+    adler &= 0xffff;
+
+    /* in case user likes doing a byte at a time, keep it fast */
+    if (len == 1) {
+        adler += buf[0];
+        if (adler >= BASE)
+            adler -= BASE;
+        sum2 += adler;
+        if (sum2 >= BASE)
+            sum2 -= BASE;
+        return adler | (sum2 << 16);
+    }
+
+    /* initial Adler-32 value (deferred check for len == 1 speed) */
+    if (buf == Z_NULL)
+        return 1L;
+
+    /* in case short lengths are provided, keep it somewhat fast */
+    if (len < 16) {
+        while (len--) {
+            adler += *buf++;
+            sum2 += adler;
+        }
+        if (adler >= BASE)
+            adler -= BASE;
+        MOD4(sum2);             /* only added so many BASE's */
+        return adler | (sum2 << 16);
+    }
+
+    /* do length NMAX blocks -- requires just one modulo operation */
+    while (len >= NMAX) {
+        len -= NMAX;
+        n = NMAX / 16;          /* NMAX is divisible by 16 */
+        do {
+            DO16(buf);          /* 16 sums unrolled */
+            buf += 16;
+        } while (--n);
+        MOD(adler);
+        MOD(sum2);
+    }
+
+    /* do remaining bytes (less than NMAX, still just one modulo) */
+    if (len) {                  /* avoid modulos if none remaining */
+        while (len >= 16) {
+            len -= 16;
+            DO16(buf);
+            buf += 16;
+        }
+        while (len--) {
+            adler += *buf++;
+            sum2 += adler;
+        }
+        MOD(adler);
+        MOD(sum2);
+    }
+
+    /* return recombined sums */
+    return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2)
+{
+    unsigned long sum1;
+    unsigned long sum2;
+    unsigned rem;
+
+    /* the derivation of this formula is left as an exercise for the reader */
+    rem = (unsigned)(len2 % BASE);
+    sum1 = adler1 & 0xffff;
+    sum2 = rem * sum1;
+    MOD(sum2);
+    sum1 += (adler2 & 0xffff) + BASE - 1;
+    sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
+    if (sum1 >= BASE) sum1 -= BASE;
+    if (sum1 >= BASE) sum1 -= BASE;
+    if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
+    if (sum2 >= BASE) sum2 -= BASE;
+    return sum1 | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2)
+{
+    return adler32_combine_(adler1, adler2, len2);
+}
+
+uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2)
+{
+    return adler32_combine_(adler1, adler2, len2);
+}
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/zlib/algorithm.txt b/abc-build/src/misc/zlib/algorithm.txt
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/algorithm.txt
@@ -0,0 +1,209 @@
+1. Compression algorithm (deflate)
+
+The deflation algorithm used by gzip (also zip and zlib) is a variation of
+LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
+the input data.  The second occurrence of a string is replaced by a
+pointer to the previous string, in the form of a pair (distance,
+length).  Distances are limited to 32K bytes, and lengths are limited
+to 258 bytes. When a string does not occur anywhere in the previous
+32K bytes, it is emitted as a sequence of literal bytes.  (In this
+description, `string' must be taken as an arbitrary sequence of bytes,
+and is not restricted to printable characters.)
+
+Literals or match lengths are compressed with one Huffman tree, and
+match distances are compressed with another tree. The trees are stored
+in a compact form at the start of each block. The blocks can have any
+size (except that the compressed data for one block must fit in
+available memory). A block is terminated when deflate() determines that
+it would be useful to start another block with fresh trees. (This is
+somewhat similar to the behavior of LZW-based _compress_.)
+
+Duplicated strings are found using a hash table. All input strings of
+length 3 are inserted in the hash table. A hash index is computed for
+the next 3 bytes. If the hash chain for this index is not empty, all
+strings in the chain are compared with the current input string, and
+the longest match is selected.
+
+The hash chains are searched starting with the most recent strings, to
+favor small distances and thus take advantage of the Huffman encoding.
+The hash chains are singly linked. There are no deletions from the
+hash chains, the algorithm simply discards matches that are too old.
+
+To avoid a worst-case situation, very long hash chains are arbitrarily
+truncated at a certain length, determined by a runtime option (level
+parameter of deflateInit). So deflate() does not always find the longest
+possible match but generally finds a match which is long enough.
+
+deflate() also defers the selection of matches with a lazy evaluation
+mechanism. After a match of length N has been found, deflate() searches for
+a longer match at the next input byte. If a longer match is found, the
+previous match is truncated to a length of one (thus producing a single
+literal byte) and the process of lazy evaluation begins again. Otherwise,
+the original match is kept, and the next match search is attempted only N
+steps later.
+
+The lazy match evaluation is also subject to a runtime parameter. If
+the current match is long enough, deflate() reduces the search for a longer
+match, thus speeding up the whole process. If compression ratio is more
+important than speed, deflate() attempts a complete second search even if
+the first match is already long enough.
+
+The lazy match evaluation is not performed for the fastest compression
+modes (level parameter 1 to 3). For these fast modes, new strings
+are inserted in the hash table only when no match was found, or
+when the match is not too long. This degrades the compression ratio
+but saves time since there are both fewer insertions and fewer searches.
+
+
+2. Decompression algorithm (inflate)
+
+2.1 Introduction
+
+The key question is how to represent a Huffman code (or any prefix code) so
+that you can decode fast.  The most important characteristic is that shorter
+codes are much more common than longer codes, so pay attention to decoding the
+short codes fast, and let the long codes take longer to decode.
+
+inflate() sets up a first level table that covers some number of bits of
+input less than the length of longest code.  It gets that many bits from the
+stream, and looks it up in the table.  The table will tell if the next
+code is that many bits or less and how many, and if it is, it will tell
+the value, else it will point to the next level table for which inflate()
+grabs more bits and tries to decode a longer code.
+
+How many bits to make the first lookup is a tradeoff between the time it
+takes to decode and the time it takes to build the table.  If building the
+table took no time (and if you had infinite memory), then there would only
+be a first level table to cover all the way to the longest code.  However,
+building the table ends up taking a lot longer for more bits since short
+codes are replicated many times in such a table.  What inflate() does is
+simply to make the number of bits in the first table a variable, and  then
+to set that variable for the maximum speed.
+
+For inflate, which has 286 possible codes for the literal/length tree, the size
+of the first table is nine bits.  Also the distance trees have 30 possible
+values, and the size of the first table is six bits.  Note that for each of
+those cases, the table ended up one bit longer than the ``average'' code
+length, i.e. the code length of an approximately flat code which would be a
+little more than eight bits for 286 symbols and a little less than five bits
+for 30 symbols.
+
+
+2.2 More details on the inflate table lookup
+
+Ok, you want to know what this cleverly obfuscated inflate tree actually
+looks like.  You are correct that it's not a Huffman tree.  It is simply a
+lookup table for the first, let's say, nine bits of a Huffman symbol.  The
+symbol could be as short as one bit or as long as 15 bits.  If a particular
+symbol is shorter than nine bits, then that symbol's translation is duplicated
+in all those entries that start with that symbol's bits.  For example, if the
+symbol is four bits, then it's duplicated 32 times in a nine-bit table.  If a
+symbol is nine bits long, it appears in the table once.
+
+If the symbol is longer than nine bits, then that entry in the table points
+to another similar table for the remaining bits.  Again, there are duplicated
+entries as needed.  The idea is that most of the time the symbol will be short
+and there will only be one table look up.  (That's whole idea behind data
+compression in the first place.)  For the less frequent long symbols, there
+will be two lookups.  If you had a compression method with really long
+symbols, you could have as many levels of lookups as is efficient.  For
+inflate, two is enough.
+
+So a table entry either points to another table (in which case nine bits in
+the above example are gobbled), or it contains the translation for the symbol
+and the number of bits to gobble.  Then you start again with the next
+ungobbled bit.
+
+You may wonder: why not just have one lookup table for how ever many bits the
+longest symbol is?  The reason is that if you do that, you end up spending
+more time filling in duplicate symbol entries than you do actually decoding.
+At least for deflate's output that generates new trees every several 10's of
+kbytes.  You can imagine that filling in a 2^15 entry table for a 15-bit code
+would take too long if you're only decoding several thousand symbols.  At the
+other extreme, you could make a new table for every bit in the code.  In fact,
+that's essentially a Huffman tree.  But then you spend two much time
+traversing the tree while decoding, even for short symbols.
+
+So the number of bits for the first lookup table is a trade of the time to
+fill out the table vs. the time spent looking at the second level and above of
+the table.
+
+Here is an example, scaled down:
+
+The code being decoded, with 10 symbols, from 1 to 6 bits long:
+
+A: 0
+B: 10
+C: 1100
+D: 11010
+E: 11011
+F: 11100
+G: 11101
+H: 11110
+I: 111110
+J: 111111
+
+Let's make the first table three bits long (eight entries):
+
+000: A,1
+001: A,1
+010: A,1
+011: A,1
+100: B,2
+101: B,2
+110: -> table X (gobble 3 bits)
+111: -> table Y (gobble 3 bits)
+
+Each entry is what the bits decode as and how many bits that is, i.e. how
+many bits to gobble.  Or the entry points to another table, with the number of
+bits to gobble implicit in the size of the table.
+
+Table X is two bits long since the longest code starting with 110 is five bits
+long:
+
+00: C,1
+01: C,1
+10: D,2
+11: E,2
+
+Table Y is three bits long since the longest code starting with 111 is six
+bits long:
+
+000: F,2
+001: F,2
+010: G,2
+011: G,2
+100: H,2
+101: H,2
+110: I,3
+111: J,3
+
+So what we have here are three tables with a total of 20 entries that had to
+be constructed.  That's compared to 64 entries for a single table.  Or
+compared to 16 entries for a Huffman tree (six two entry tables and one four
+entry table).  Assuming that the code ideally represents the probability of
+the symbols, it takes on the average 1.25 lookups per symbol.  That's compared
+to one lookup for the single table, or 1.66 lookups per symbol for the
+Huffman tree.
+
+There, I think that gives you a picture of what's going on.  For inflate, the
+meaning of a particular symbol is often more than just a letter.  It can be a
+byte (a "literal"), or it can be either a length or a distance which
+indicates a base value and a number of bits to fetch after the code that is
+added to the base value.  Or it might be the special end-of-block code.  The
+data structures created in inftrees.c try to encode all that information
+compactly in the tables.
+
+
+Jean-loup Gailly        Mark Adler
+jloup@gzip.org          madler@alumni.caltech.edu
+
+
+References:
+
+[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
+Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
+pp. 337-343.
+
+``DEFLATE Compressed Data Format Specification'' available in
+http://www.ietf.org/rfc/rfc1951.txt
diff --git a/abc-build/src/misc/zlib/compress_.c b/abc-build/src/misc/zlib/compress_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/compress_.c
@@ -0,0 +1,76 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/* ===========================================================================
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least 0.1% larger than sourceLen plus
+   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+int ZEXPORT compress2 (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level)
+{
+    z_stream stream;
+    int err;
+
+    stream.next_in = (Bytef*)source;
+    stream.avail_in = (uInt)sourceLen;
+#ifdef MAXSEG_64K
+    /* Check for source > 64K on 16-bit machine: */
+    if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+#endif
+    stream.next_out = dest;
+    stream.avail_out = (uInt)*destLen;
+    if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+    stream.zalloc = (alloc_func)0;
+    stream.zfree = (free_func)0;
+    stream.opaque = (voidpf)0;
+
+    err = deflateInit(&stream, level);
+    if (err != Z_OK) return err;
+
+    err = deflate(&stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        deflateEnd(&stream);
+        return err == Z_OK ? Z_BUF_ERROR : err;
+    }
+    *destLen = stream.total_out;
+
+    err = deflateEnd(&stream);
+    return err;
+}
+
+/* ===========================================================================
+ */
+int ZEXPORT compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
+{
+    return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
+}
+
+/* ===========================================================================
+     If the default memLevel or windowBits for deflateInit() is changed, then
+   this function needs to be updated.
+ */
+uLong ZEXPORT compressBound (uLong sourceLen)
+{
+    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
+           (sourceLen >> 25) + 13;
+}
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/zlib/crc32.c b/abc-build/src/misc/zlib/crc32.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/crc32.c
@@ -0,0 +1,433 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-2006, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
+ * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
+ * tables for updating the shift register in one step with three exclusive-ors
+ * instead of four steps with four exclusive-ors.  This results in about a
+ * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
+ */
+
+/* @(#) $Id$ */
+
+/*
+  Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
+  protection on the static variables used to control the first-use generation
+  of the crc tables.  Therefore, if you #define DYNAMIC_CRC_TABLE, you should
+  first call get_crc_table() to initialize the tables before allowing more than
+  one thread to use crc32().
+ */
+
+#ifdef MAKECRCH
+#  include <stdio.h>
+#  ifndef DYNAMIC_CRC_TABLE
+#    define DYNAMIC_CRC_TABLE
+#  endif /* !DYNAMIC_CRC_TABLE */
+#endif /* MAKECRCH */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc/util/abc_global.h"
+
+#include "zutil.h"      /* for STDC and FAR definitions */
+
+ABC_NAMESPACE_IMPL_START
+
+#define local static
+
+/* Find a four-byte integer type for crc32_little() and crc32_big(). */
+#ifndef NOBYFOUR
+#  ifdef STDC           /* need ANSI C limits.h to determine sizes */
+ABC_NAMESPACE_IMPL_END
+#    include <limits.h>
+ABC_NAMESPACE_IMPL_START
+#    define BYFOUR
+#    if (UINT_MAX == 0xffffffffUL)
+       typedef unsigned int u4;
+#    else
+#      if (ULONG_MAX == 0xffffffffUL)
+         typedef unsigned long u4;
+#      else
+#        if (USHRT_MAX == 0xffffffffUL)
+           typedef unsigned short u4;
+#        else
+#          undef BYFOUR     /* can't find a four-byte integer type! */
+#        endif
+#      endif
+#    endif
+#  endif /* STDC */
+#endif /* !NOBYFOUR */
+
+/* Definitions for doing the crc four data bytes at a time. */
+#ifdef BYFOUR
+#  define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \
+                (((w)&0xff00)<<8)+(((w)&0xff)<<24))
+   local unsigned long crc32_little OF((unsigned long,
+                        const unsigned char FAR *, unsigned));
+   local unsigned long crc32_big OF((unsigned long,
+                        const unsigned char FAR *, unsigned));
+#  define TBLS 8
+#else
+#  define TBLS 1
+#endif /* BYFOUR */
+
+/* Local functions for crc concatenation */
+local unsigned long gf2_matrix_times OF((unsigned long *mat,
+                                         unsigned long vec));
+local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
+local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2);
+
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local volatile int crc_table_empty = 1;
+local unsigned long FAR crc_table[TBLS][256];
+local void make_crc_table OF((void));
+#ifdef MAKECRCH
+   local void write_table OF((FILE *, const unsigned long FAR *));
+#endif /* MAKECRCH */
+/*
+  Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
+  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+  Polynomials over GF(2) are represented in binary, one bit per coefficient,
+  with the lowest powers in the most significant bit.  Then adding polynomials
+  is just exclusive-or, and multiplying a polynomial by x is a right shift by
+  one.  If we call the above polynomial p, and represent a byte as the
+  polynomial q, also with the lowest power in the most significant bit (so the
+  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+  where a mod b means the remainder after dividing a by b.
+
+  This calculation is done using the shift-register method of multiplying and
+  taking the remainder.  The register is initialized to zero, and for each
+  incoming bit, x^32 is added mod p to the register if the bit is a one (where
+  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+  x (which is shifting right by one and adding x^32 mod p if the bit shifted
+  out is a one).  We start with the highest power (least significant bit) of
+  q and repeat for all eight bits of q.
+
+  The first table is simply the CRC of all possible eight bit values.  This is
+  all the information needed to generate CRCs on data a byte at a time for all
+  combinations of CRC register values and incoming bytes.  The remaining tables
+  allow for word-at-a-time CRC calculation for both big-endian and little-
+  endian machines, where a word is four bytes.
+*/
+local void make_crc_table()
+{
+    unsigned long c;
+    int n, k;
+    unsigned long poly;                 /* polynomial exclusive-or pattern */
+    /* terms of polynomial defining this crc (except x^32): */
+    static volatile int first = 1;      /* flag to limit concurrent making */
+    static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+    /* See if another task is already doing this (not thread-safe, but better
+       than nothing -- significantly reduces duration of vulnerability in
+       case the advice about DYNAMIC_CRC_TABLE is ignored) */
+    if (first) {
+        first = 0;
+
+        /* make exclusive-or pattern from polynomial (0xedb88320UL) */
+        poly = 0UL;
+        for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
+            poly |= 1UL << (31 - p[n]);
+
+        /* generate a crc for every 8-bit value */
+        for (n = 0; n < 256; n++) {
+            c = (unsigned long)n;
+            for (k = 0; k < 8; k++)
+                c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+            crc_table[0][n] = c;
+        }
+
+#ifdef BYFOUR
+        /* generate crc for each value followed by one, two, and three zeros,
+           and then the byte reversal of those as well as the first table */
+        for (n = 0; n < 256; n++) {
+            c = crc_table[0][n];
+            crc_table[4][n] = REV(c);
+            for (k = 1; k < 4; k++) {
+                c = crc_table[0][c & 0xff] ^ (c >> 8);
+                crc_table[k][n] = c;
+                crc_table[k + 4][n] = REV(c);
+            }
+        }
+#endif /* BYFOUR */
+
+        crc_table_empty = 0;
+    }
+    else {      /* not first */
+        /* wait for the other guy to finish (not efficient, but rare) */
+        while (crc_table_empty)
+            ;
+    }
+
+#ifdef MAKECRCH
+    /* write out CRC tables to crc32.h */
+    {
+        FILE *out;
+
+        out = fopen("crc32.h", "w");
+        if (out == NULL) return;
+        fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
+        fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
+        fprintf(out, "local const unsigned long FAR ");
+        fprintf(out, "crc_table[TBLS][256] =\n{\n  {\n");
+        write_table(out, crc_table[0]);
+#  ifdef BYFOUR
+        fprintf(out, "#ifdef BYFOUR\n");
+        for (k = 1; k < 8; k++) {
+            fprintf(out, "  },\n  {\n");
+            write_table(out, crc_table[k]);
+        }
+        fprintf(out, "#endif\n");
+#  endif /* BYFOUR */
+        fprintf(out, "  }\n};\n");
+        fclose(out);
+    }
+#endif /* MAKECRCH */
+}
+
+#ifdef MAKECRCH
+local void write_table(FILE *out, const unsigned long FAR *table)
+{
+    int n;
+
+    for (n = 0; n < 256; n++)
+        fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : "    ", table[n],
+                n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
+}
+#endif /* MAKECRCH */
+
+#else /* !DYNAMIC_CRC_TABLE */
+/* ========================================================================
+ * Tables of CRC-32s of all single-byte values, made by make_crc_table().
+ */
+ABC_NAMESPACE_IMPL_END
+#include "crc32.h"
+ABC_NAMESPACE_IMPL_START
+#endif /* DYNAMIC_CRC_TABLE */
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+const unsigned long FAR * ZEXPORT get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+    if (crc_table_empty)
+        make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+    return (const unsigned long FAR *)crc_table;
+}
+
+/* ========================================================================= */
+#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
+#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, uInt len)
+{
+    if (buf == Z_NULL) return 0UL;
+
+#ifdef DYNAMIC_CRC_TABLE
+    if (crc_table_empty)
+        make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+
+#ifdef BYFOUR
+    if (sizeof(void *) == sizeof(ptrdiff_t)) {
+        u4 endian;
+
+        endian = 1;
+        if (*((unsigned char *)(&endian)))
+            return crc32_little(crc, buf, len);
+        else
+            return crc32_big(crc, buf, len);
+    }
+#endif /* BYFOUR */
+    crc = crc ^ 0xffffffffUL;
+    while (len >= 8) {
+        DO8;
+        len -= 8;
+    }
+    if (len) do {
+        DO1;
+    } while (--len);
+    return crc ^ 0xffffffffUL;
+}
+
+#ifdef BYFOUR
+
+/* ========================================================================= */
+#define DOLIT4 c ^= *buf4++; \
+        c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
+            crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
+#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
+
+/* ========================================================================= */
+local unsigned long crc32_little(unsigned long crc, const unsigned char FAR *buf, unsigned len)
+{
+    register u4 c;
+    register const u4 FAR *buf4;
+
+    c = (u4)crc;
+    c = ~c;
+    while (len && ((ptrdiff_t)buf & 3)) {
+        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+        len--;
+    }
+
+    buf4 = (const u4 FAR *)(const void FAR *)buf;
+    while (len >= 32) {
+        DOLIT32;
+        len -= 32;
+    }
+    while (len >= 4) {
+        DOLIT4;
+        len -= 4;
+    }
+    buf = (const unsigned char FAR *)buf4;
+
+    if (len) do {
+        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+    } while (--len);
+    c = ~c;
+    return (unsigned long)c;
+}
+
+/* ========================================================================= */
+#define DOBIG4 c ^= *++buf4; \
+        c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
+            crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
+#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
+
+/* ========================================================================= */
+local unsigned long crc32_big(unsigned long crc, const unsigned char FAR *buf, unsigned len)
+{
+    register u4 c;
+    register const u4 FAR *buf4;
+
+    c = REV((u4)crc);
+    c = ~c;
+    while (len && ((ptrdiff_t)buf & 3)) {
+        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+        len--;
+    }
+
+    buf4 = (const u4 FAR *)(const void FAR *)buf;
+    buf4--;
+    while (len >= 32) {
+        DOBIG32;
+        len -= 32;
+    }
+    while (len >= 4) {
+        DOBIG4;
+        len -= 4;
+    }
+    buf4++;
+    buf = (const unsigned char FAR *)buf4;
+
+    if (len) do {
+        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+    } while (--len);
+    c = ~c;
+    return (unsigned long)(REV(c));
+}
+
+#endif /* BYFOUR */
+
+#define GF2_DIM 32      /* dimension of GF(2) vectors (length of CRC) */
+
+/* ========================================================================= */
+local unsigned long gf2_matrix_times(unsigned long *mat, unsigned long vec)
+{
+    unsigned long sum;
+
+    sum = 0;
+    while (vec) {
+        if (vec & 1)
+            sum ^= *mat;
+        vec >>= 1;
+        mat++;
+    }
+    return sum;
+}
+
+/* ========================================================================= */
+local void gf2_matrix_square(unsigned long *square, unsigned long *mat)
+{
+    int n;
+
+    for (n = 0; n < GF2_DIM; n++)
+        square[n] = gf2_matrix_times(mat, mat[n]);
+}
+
+/* ========================================================================= */
+local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2)
+{
+    int n;
+    unsigned long row;
+    unsigned long even[GF2_DIM];    /* even-power-of-two zeros operator */
+    unsigned long odd[GF2_DIM];     /* odd-power-of-two zeros operator */
+
+    /* degenerate case (also disallow negative lengths) */
+    if (len2 <= 0)
+        return crc1;
+
+    /* put operator for one zero bit in odd */
+    odd[0] = 0xedb88320UL;          /* CRC-32 polynomial */
+    row = 1;
+    for (n = 1; n < GF2_DIM; n++) {
+        odd[n] = row;
+        row <<= 1;
+    }
+
+    /* put operator for two zero bits in even */
+    gf2_matrix_square(even, odd);
+
+    /* put operator for four zero bits in odd */
+    gf2_matrix_square(odd, even);
+
+    /* apply len2 zeros to crc1 (first square will put the operator for one
+       zero byte, eight zero bits, in even) */
+    do {
+        /* apply zeros operator for this bit of len2 */
+        gf2_matrix_square(even, odd);
+        if (len2 & 1)
+            crc1 = gf2_matrix_times(even, crc1);
+        len2 >>= 1;
+
+        /* if no more bits set, then done */
+        if (len2 == 0)
+            break;
+
+        /* another iteration of the loop with odd and even swapped */
+        gf2_matrix_square(odd, even);
+        if (len2 & 1)
+            crc1 = gf2_matrix_times(odd, crc1);
+        len2 >>= 1;
+
+        /* if no more bits set, then done */
+    } while (len2 != 0);
+
+    /* return combined crc */
+    crc1 ^= crc2;
+    return crc1;
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2)
+{
+    return crc32_combine_(crc1, crc2, len2);
+}
+
+uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2)
+{
+    return crc32_combine_(crc1, crc2, len2);
+}
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/zlib/crc32.h b/abc-build/src/misc/zlib/crc32.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/crc32.h
@@ -0,0 +1,445 @@
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+ABC_NAMESPACE_HEADER_START
+
+local const unsigned long FAR crc_table[TBLS][256] =
+{
+  {
+    0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
+    0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
+    0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
+    0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
+    0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
+    0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
+    0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
+    0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
+    0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
+    0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
+    0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
+    0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
+    0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
+    0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
+    0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
+    0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
+    0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
+    0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
+    0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
+    0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
+    0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
+    0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
+    0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
+    0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
+    0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
+    0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
+    0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
+    0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
+    0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
+    0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
+    0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
+    0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
+    0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
+    0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
+    0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
+    0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
+    0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
+    0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
+    0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
+    0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
+    0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
+    0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
+    0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
+    0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
+    0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
+    0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
+    0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
+    0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
+    0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
+    0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
+    0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
+    0x2d02ef8dUL
+#ifdef BYFOUR
+  },
+  {
+    0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
+    0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
+    0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
+    0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
+    0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
+    0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
+    0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
+    0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
+    0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
+    0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
+    0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
+    0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
+    0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
+    0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
+    0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
+    0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
+    0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
+    0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
+    0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
+    0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
+    0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
+    0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
+    0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
+    0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
+    0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
+    0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
+    0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
+    0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
+    0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
+    0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
+    0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
+    0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
+    0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
+    0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
+    0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
+    0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
+    0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
+    0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
+    0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
+    0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
+    0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
+    0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
+    0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
+    0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
+    0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
+    0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
+    0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
+    0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
+    0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
+    0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
+    0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
+    0x9324fd72UL
+  },
+  {
+    0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
+    0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
+    0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
+    0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
+    0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
+    0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
+    0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
+    0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
+    0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
+    0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
+    0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
+    0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
+    0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
+    0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
+    0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
+    0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
+    0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
+    0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
+    0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
+    0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
+    0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
+    0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
+    0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
+    0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
+    0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
+    0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
+    0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
+    0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
+    0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
+    0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
+    0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
+    0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
+    0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
+    0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
+    0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
+    0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
+    0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
+    0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
+    0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
+    0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
+    0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
+    0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
+    0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
+    0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
+    0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
+    0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
+    0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
+    0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
+    0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
+    0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
+    0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
+    0xbe9834edUL
+  },
+  {
+    0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
+    0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
+    0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
+    0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
+    0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
+    0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
+    0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
+    0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
+    0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
+    0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
+    0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
+    0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
+    0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
+    0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
+    0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
+    0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
+    0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
+    0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
+    0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
+    0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
+    0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
+    0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
+    0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
+    0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
+    0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
+    0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
+    0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
+    0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
+    0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
+    0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
+    0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
+    0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
+    0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
+    0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
+    0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
+    0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
+    0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
+    0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
+    0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
+    0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
+    0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
+    0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
+    0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
+    0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
+    0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
+    0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
+    0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
+    0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
+    0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
+    0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
+    0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
+    0xde0506f1UL
+  },
+  {
+    0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
+    0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
+    0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
+    0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
+    0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
+    0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
+    0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
+    0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
+    0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
+    0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
+    0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
+    0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
+    0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
+    0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
+    0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
+    0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
+    0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
+    0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
+    0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
+    0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
+    0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
+    0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
+    0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
+    0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
+    0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
+    0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
+    0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
+    0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
+    0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
+    0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
+    0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
+    0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
+    0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
+    0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
+    0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
+    0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
+    0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
+    0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
+    0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
+    0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
+    0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
+    0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
+    0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
+    0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
+    0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
+    0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
+    0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
+    0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
+    0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
+    0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
+    0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
+    0x8def022dUL
+  },
+  {
+    0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
+    0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
+    0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
+    0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
+    0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
+    0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
+    0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
+    0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
+    0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
+    0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
+    0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
+    0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
+    0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
+    0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
+    0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
+    0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
+    0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
+    0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
+    0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
+    0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
+    0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
+    0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
+    0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
+    0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
+    0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
+    0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
+    0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
+    0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
+    0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
+    0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
+    0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
+    0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
+    0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
+    0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
+    0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
+    0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
+    0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
+    0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
+    0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
+    0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
+    0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
+    0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
+    0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
+    0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
+    0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
+    0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
+    0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
+    0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
+    0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
+    0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
+    0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
+    0x72fd2493UL
+  },
+  {
+    0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
+    0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
+    0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
+    0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
+    0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
+    0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
+    0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
+    0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
+    0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
+    0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
+    0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
+    0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
+    0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
+    0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
+    0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
+    0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
+    0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
+    0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
+    0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
+    0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
+    0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
+    0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
+    0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
+    0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
+    0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
+    0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
+    0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
+    0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
+    0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
+    0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
+    0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
+    0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
+    0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
+    0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
+    0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
+    0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
+    0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
+    0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
+    0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
+    0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
+    0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
+    0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
+    0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
+    0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
+    0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
+    0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
+    0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
+    0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
+    0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
+    0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
+    0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
+    0xed3498beUL
+  },
+  {
+    0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
+    0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
+    0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
+    0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
+    0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
+    0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
+    0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
+    0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
+    0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
+    0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
+    0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
+    0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
+    0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
+    0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
+    0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
+    0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
+    0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
+    0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
+    0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
+    0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
+    0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
+    0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
+    0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
+    0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
+    0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
+    0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
+    0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
+    0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
+    0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
+    0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
+    0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
+    0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
+    0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
+    0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
+    0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
+    0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
+    0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
+    0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
+    0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
+    0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
+    0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
+    0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
+    0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
+    0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
+    0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
+    0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
+    0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
+    0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
+    0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
+    0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
+    0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
+    0xf10605deUL
+#endif
+  }
+};
+
+ABC_NAMESPACE_HEADER_END
diff --git a/abc-build/src/misc/zlib/deflate.c b/abc-build/src/misc/zlib/deflate.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/deflate.c
@@ -0,0 +1,1784 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ *  ALGORITHM
+ *
+ *      The "deflation" process depends on being able to identify portions
+ *      of the input text which are identical to earlier input (within a
+ *      sliding window trailing behind the input currently being processed).
+ *
+ *      The most straightforward technique turns out to be the fastest for
+ *      most input files: try all possible matches and select the longest.
+ *      The key feature of this algorithm is that insertions into the string
+ *      dictionary are very simple and thus fast, and deletions are avoided
+ *      completely. Insertions are performed at each input character, whereas
+ *      string matches are performed only when the previous match ends. So it
+ *      is preferable to spend more time in matches to allow very fast string
+ *      insertions and avoid deletions. The matching algorithm for small
+ *      strings is inspired from that of Rabin & Karp. A brute force approach
+ *      is used to find longer strings when a small match has been found.
+ *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ *      (by Leonid Broukhis).
+ *         A previous version of this file used a more sophisticated algorithm
+ *      (by Fiala and Greene) which is guaranteed to run in linear amortized
+ *      time, but has a larger average cost, uses more memory and is patented.
+ *      However the F&G algorithm may be faster for some highly redundant
+ *      files if the parameter max_chain_length (described below) is too large.
+ *
+ *  ACKNOWLEDGEMENTS
+ *
+ *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ *      I found it in 'freeze' written by Leonid Broukhis.
+ *      Thanks to many people for bug reports and testing.
+ *
+ *  REFERENCES
+ *
+ *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ *      Available in http://www.ietf.org/rfc/rfc1951.txt
+ *
+ *      A description of the Rabin and Karp algorithm is given in the book
+ *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ *      Fiala,E.R., and Greene,D.H.
+ *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id$ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc/util/abc_global.h"
+
+#include "deflate.h"
+
+ABC_NAMESPACE_IMPL_START
+
+const char deflate_copyright[] =
+   " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ *  Function prototypes.
+ */
+typedef enum {
+    need_more,      /* block not completed, need more input or more output */
+    block_done,     /* block flush performed */
+    finish_started, /* finish started, need only more output at next deflate */
+    finish_done     /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local void fill_window    OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast   OF((deflate_state *s, int flush));
+#ifndef FASTEST
+local block_state deflate_slow   OF((deflate_state *s, int flush));
+#endif
+local block_state deflate_rle    OF((deflate_state *s, int flush));
+local block_state deflate_huff   OF((deflate_state *s, int flush));
+local void lm_init        OF((deflate_state *s));
+local void putShortMSB    OF((deflate_state *s, uInt b));
+local void flush_pending  OF((z_streamp strm));
+local int read_buf        OF((z_streamp strm, Bytef *buf, unsigned size));
+#ifdef ASMV
+      void match_init OF((void)); /* asm code initialization */
+      uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#else
+local uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#endif
+
+#ifdef DEBUG
+local  void check_match OF((deflate_state *s, IPos start, IPos match,
+                            int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+#  define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+   ush good_length; /* reduce lazy search above this match length */
+   ush max_lazy;    /* do not perform lazy search above this match length */
+   ush nice_length; /* quit search above this match length */
+   ush max_chain;
+   compress_func func;
+} config;
+
+#ifdef FASTEST
+local const config configuration_table[2] = {
+/*      good lazy nice chain */
+/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
+/* 1 */ {4,    4,  8,    4, deflate_fast}}; /* max speed, no lazy matches */
+#else
+local const config configuration_table[10] = {
+/*      good lazy nice chain */
+/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
+/* 1 */ {4,    4,  8,    4, deflate_fast}, /* max speed, no lazy matches */
+/* 2 */ {4,    5, 16,    8, deflate_fast},
+/* 3 */ {4,    6, 32,   32, deflate_fast},
+
+/* 4 */ {4,    4, 16,   16, deflate_slow},  /* lazy matches */
+/* 5 */ {8,   16, 32,   32, deflate_slow},
+/* 6 */ {8,   16, 128, 128, deflate_slow},
+/* 7 */ {8,   32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
+#endif
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+#ifndef NO_DUMMY_DECL
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+#endif
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN  assertion: all calls to to UPDATE_HASH are made with consecutive
+ *    input characters, so that a running hash key can be computed from the
+ *    previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN  assertion: all calls to to INSERT_STRING are made with consecutive
+ *    input characters and the first MIN_MATCH bytes of str are valid
+ *    (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    match_head = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+    s->head[s->hash_size-1] = NIL; \
+    zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, int stream_size)
+{
+    return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+                         Z_DEFAULT_STRATEGY, version, stream_size);
+    /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(z_streamp strm, int  level, int  method, int  windowBits, int  memLevel, int  strategy,
+                  const char *version, int stream_size)
+{
+    deflate_state *s;
+    int wrap = 1;
+    static const char my_version[] = ZLIB_VERSION;
+
+    ushf *overlay;
+    /* We overlay pending_buf and d_buf+l_buf. This works since the average
+     * output size for (length,distance) codes is <= 24 bits.
+     */
+
+    if (version == Z_NULL || version[0] != my_version[0] ||
+        stream_size != sizeof(z_stream)) {
+        return Z_VERSION_ERROR;
+    }
+    if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+    strm->msg = Z_NULL;
+    if (strm->zalloc == (alloc_func)0) {
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+    }
+    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+
+#ifdef FASTEST
+    if (level != 0) level = 1;
+#else
+    if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+
+    if (windowBits < 0) { /* suppress zlib wrapper */
+        wrap = 0;
+        windowBits = -windowBits;
+    }
+#ifdef GZIP
+    else if (windowBits > 15) {
+        wrap = 2;       /* write gzip wrapper instead */
+        windowBits -= 16;
+    }
+#endif
+    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+        windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+        strategy < 0 || strategy > Z_FIXED) {
+        return Z_STREAM_ERROR;
+    }
+    if (windowBits == 8) windowBits = 9;  /* until 256-byte window bug fixed */
+    s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+    if (s == Z_NULL) return Z_MEM_ERROR;
+    strm->state = (struct internal_state FAR *)s;
+    s->strm = strm;
+
+    s->wrap = wrap;
+    s->gzhead = Z_NULL;
+    s->w_bits = windowBits;
+    s->w_size = 1 << s->w_bits;
+    s->w_mask = s->w_size - 1;
+
+    s->hash_bits = memLevel + 7;
+    s->hash_size = 1 << s->hash_bits;
+    s->hash_mask = s->hash_size - 1;
+    s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+    s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
+    s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+    s->high_water = 0;      /* nothing written to s->window yet */
+
+    s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+    overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+    s->pending_buf = (uchf *) overlay;
+    s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+
+    if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+        s->pending_buf == Z_NULL) {
+        s->status = FINISH_STATE;
+        strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+        deflateEnd (strm);
+        return Z_MEM_ERROR;
+    }
+    s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+    s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+    s->level = level;
+    s->strategy = strategy;
+    s->method = (Byte)method;
+
+    return deflateReset(strm);
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary (z_streamp strm, const Bytef *dictionary, uInt  dictLength)
+{
+    deflate_state *s;
+    uInt length = dictLength;
+    uInt n;
+    IPos hash_head = 0;
+
+    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
+        strm->state->wrap == 2 ||
+        (strm->state->wrap == 1 && strm->state->status != INIT_STATE))
+        return Z_STREAM_ERROR;
+
+    s = strm->state;
+    if (s->wrap)
+        strm->adler = adler32(strm->adler, dictionary, dictLength);
+
+    if (length < MIN_MATCH) return Z_OK;
+    if (length > s->w_size) {
+        length = s->w_size;
+        dictionary += dictLength - length; /* use the tail of the dictionary */
+    }
+    zmemcpy(s->window, dictionary, length);
+    s->strstart = length;
+    s->block_start = (long)length;
+
+    /* Insert all strings in the hash table (except for the last two bytes).
+     * s->lookahead stays null, so s->ins_h will be recomputed at the next
+     * call of fill_window.
+     */
+    s->ins_h = s->window[0];
+    UPDATE_HASH(s, s->ins_h, s->window[1]);
+    for (n = 0; n <= length - MIN_MATCH; n++) {
+        INSERT_STRING(s, n, hash_head);
+    }
+    if (hash_head) hash_head = 0;  /* to make compiler happy */
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset (z_streamp strm)
+{
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL ||
+        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) {
+        return Z_STREAM_ERROR;
+    }
+
+    strm->total_in = strm->total_out = 0;
+    strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+    strm->data_type = Z_UNKNOWN;
+
+    s = (deflate_state *)strm->state;
+    s->pending = 0;
+    s->pending_out = s->pending_buf;
+
+    if (s->wrap < 0) {
+        s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
+    }
+    s->status = s->wrap ? INIT_STATE : BUSY_STATE;
+    strm->adler =
+#ifdef GZIP
+        s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
+#endif
+        adler32(0L, Z_NULL, 0);
+    s->last_flush = Z_NO_FLUSH;
+
+    _tr_init(s);
+    lm_init(s);
+
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetHeader (z_streamp strm, gz_headerp head)
+{
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    if (strm->state->wrap != 2) return Z_STREAM_ERROR;
+    strm->state->gzhead = head;
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePrime (z_streamp strm, int bits, int value)
+{
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    strm->state->bi_valid = bits;
+    strm->state->bi_buf = (ush)(value & ((1 << bits) - 1));
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(z_streamp strm, int level, int strategy)
+{
+    deflate_state *s;
+    compress_func func;
+    int err = Z_OK;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    s = strm->state;
+
+#ifdef FASTEST
+    if (level != 0) level = 1;
+#else
+    if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
+        return Z_STREAM_ERROR;
+    }
+    func = configuration_table[s->level].func;
+
+    if ((strategy != s->strategy || func != configuration_table[level].func) &&
+        strm->total_in != 0) {
+        /* Flush the last buffer: */
+        err = deflate(strm, Z_BLOCK);
+    }
+    if (s->level != level) {
+        s->level = level;
+        s->max_lazy_match   = configuration_table[level].max_lazy;
+        s->good_match       = configuration_table[level].good_length;
+        s->nice_match       = configuration_table[level].nice_length;
+        s->max_chain_length = configuration_table[level].max_chain;
+    }
+    s->strategy = strategy;
+    return err;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain)
+{
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    s = strm->state;
+    s->good_match = good_length;
+    s->max_lazy_match = max_lazy;
+    s->nice_match = nice_length;
+    s->max_chain_length = max_chain;
+    return Z_OK;
+}
+
+/* =========================================================================
+ * For the default windowBits of 15 and memLevel of 8, this function returns
+ * a close to exact, as well as small, upper bound on the compressed size.
+ * They are coded as constants here for a reason--if the #define's are
+ * changed, then this function needs to be changed as well.  The return
+ * value for 15 and 8 only works for those exact settings.
+ *
+ * For any setting other than those defaults for windowBits and memLevel,
+ * the value returned is a conservative worst case for the maximum expansion
+ * resulting from using fixed blocks instead of stored blocks, which deflate
+ * can emit on compressed data for some combinations of the parameters.
+ *
+ * This function could be more sophisticated to provide closer upper bounds for
+ * every combination of windowBits and memLevel.  But even the conservative
+ * upper bound of about 14% expansion does not seem onerous for output buffer
+ * allocation.
+ */
+uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen)
+{
+    deflate_state *s;
+    uLong complen, wraplen;
+    Bytef *str;
+
+    /* conservative upper bound for compressed data */
+    complen = sourceLen +
+              ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;
+
+    /* if can't get parameters, return conservative bound plus zlib wrapper */
+    if (strm == Z_NULL || strm->state == Z_NULL)
+        return complen + 6;
+
+    /* compute wrapper length */
+    s = strm->state;
+    switch (s->wrap) {
+    case 0:                                 /* raw deflate */
+        wraplen = 0;
+        break;
+    case 1:                                 /* zlib wrapper */
+        wraplen = 6 + (s->strstart ? 4 : 0);
+        break;
+    case 2:                                 /* gzip wrapper */
+        wraplen = 18;
+        if (s->gzhead != Z_NULL) {          /* user-supplied gzip header */
+            if (s->gzhead->extra != Z_NULL)
+                wraplen += 2 + s->gzhead->extra_len;
+            str = s->gzhead->name;
+            if (str != Z_NULL)
+                do {
+                    wraplen++;
+                } while (*str++);
+            str = s->gzhead->comment;
+            if (str != Z_NULL)
+                do {
+                    wraplen++;
+                } while (*str++);
+            if (s->gzhead->hcrc)
+                wraplen += 2;
+        }
+        break;
+    default:                                /* for compiler happiness */
+        wraplen = 6;
+    }
+
+    /* if not default parameters, return conservative bound */
+    if (s->w_bits != 15 || s->hash_bits != 8 + 7)
+        return complen + wraplen;
+
+    /* default settings: return tight bound for that case */
+    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
+           (sourceLen >> 25) + 13 - 6 + wraplen;
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (deflate_state *s, uInt b)
+{
+    put_byte(s, (Byte)(b >> 8));
+    put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+local void flush_pending(z_streamp strm)
+{
+    unsigned len = strm->state->pending;
+
+    if (len > strm->avail_out) len = strm->avail_out;
+    if (len == 0) return;
+
+    zmemcpy(strm->next_out, strm->state->pending_out, len);
+    strm->next_out  += len;
+    strm->state->pending_out  += len;
+    strm->total_out += len;
+    strm->avail_out  -= len;
+    strm->state->pending -= len;
+    if (strm->state->pending == 0) {
+        strm->state->pending_out = strm->state->pending_buf;
+    }
+}
+
+/* ========================================================================= */
+int ZEXPORT deflate (z_streamp strm, int flush)
+{
+    int old_flush; /* value of flush param for previous deflate call */
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL ||
+        flush > Z_BLOCK || flush < 0) {
+        return Z_STREAM_ERROR;
+    }
+    s = strm->state;
+
+    if (strm->next_out == Z_NULL ||
+        (strm->next_in == Z_NULL && strm->avail_in != 0) ||
+        (s->status == FINISH_STATE && flush != Z_FINISH)) {
+        ERR_RETURN(strm, Z_STREAM_ERROR);
+    }
+    if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+    s->strm = strm; /* just in case */
+    old_flush = s->last_flush;
+    s->last_flush = flush;
+
+    /* Write the header */
+    if (s->status == INIT_STATE) {
+#ifdef GZIP
+        if (s->wrap == 2) {
+            strm->adler = crc32(0L, Z_NULL, 0);
+            put_byte(s, 31);
+            put_byte(s, 139);
+            put_byte(s, 8);
+            if (s->gzhead == Z_NULL) {
+                put_byte(s, 0);
+                put_byte(s, 0);
+                put_byte(s, 0);
+                put_byte(s, 0);
+                put_byte(s, 0);
+                put_byte(s, s->level == 9 ? 2 :
+                            (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+                             4 : 0));
+                put_byte(s, OS_CODE);
+                s->status = BUSY_STATE;
+            }
+            else {
+                put_byte(s, (s->gzhead->text ? 1 : 0) +
+                            (s->gzhead->hcrc ? 2 : 0) +
+                            (s->gzhead->extra == Z_NULL ? 0 : 4) +
+                            (s->gzhead->name == Z_NULL ? 0 : 8) +
+                            (s->gzhead->comment == Z_NULL ? 0 : 16)
+                        );
+                put_byte(s, (Byte)(s->gzhead->time & 0xff));
+                put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
+                put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
+                put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
+                put_byte(s, s->level == 9 ? 2 :
+                            (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+                             4 : 0));
+                put_byte(s, s->gzhead->os & 0xff);
+                if (s->gzhead->extra != Z_NULL) {
+                    put_byte(s, s->gzhead->extra_len & 0xff);
+                    put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
+                }
+                if (s->gzhead->hcrc)
+                    strm->adler = crc32(strm->adler, s->pending_buf,
+                                        s->pending);
+                s->gzindex = 0;
+                s->status = EXTRA_STATE;
+            }
+        }
+        else
+#endif
+        {
+            uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+            uInt level_flags;
+
+            if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
+                level_flags = 0;
+            else if (s->level < 6)
+                level_flags = 1;
+            else if (s->level == 6)
+                level_flags = 2;
+            else
+                level_flags = 3;
+            header |= (level_flags << 6);
+            if (s->strstart != 0) header |= PRESET_DICT;
+            header += 31 - (header % 31);
+
+            s->status = BUSY_STATE;
+            putShortMSB(s, header);
+
+            /* Save the adler32 of the preset dictionary: */
+            if (s->strstart != 0) {
+                putShortMSB(s, (uInt)(strm->adler >> 16));
+                putShortMSB(s, (uInt)(strm->adler & 0xffff));
+            }
+            strm->adler = adler32(0L, Z_NULL, 0);
+        }
+    }
+#ifdef GZIP
+    if (s->status == EXTRA_STATE) {
+        if (s->gzhead->extra != Z_NULL) {
+            uInt beg = s->pending;  /* start of bytes to update crc */
+
+            while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
+                if (s->pending == s->pending_buf_size) {
+                    if (s->gzhead->hcrc && s->pending > beg)
+                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                            s->pending - beg);
+                    flush_pending(strm);
+                    beg = s->pending;
+                    if (s->pending == s->pending_buf_size)
+                        break;
+                }
+                put_byte(s, s->gzhead->extra[s->gzindex]);
+                s->gzindex++;
+            }
+            if (s->gzhead->hcrc && s->pending > beg)
+                strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                    s->pending - beg);
+            if (s->gzindex == s->gzhead->extra_len) {
+                s->gzindex = 0;
+                s->status = NAME_STATE;
+            }
+        }
+        else
+            s->status = NAME_STATE;
+    }
+    if (s->status == NAME_STATE) {
+        if (s->gzhead->name != Z_NULL) {
+            uInt beg = s->pending;  /* start of bytes to update crc */
+            int val;
+
+            do {
+                if (s->pending == s->pending_buf_size) {
+                    if (s->gzhead->hcrc && s->pending > beg)
+                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                            s->pending - beg);
+                    flush_pending(strm);
+                    beg = s->pending;
+                    if (s->pending == s->pending_buf_size) {
+                        val = 1;
+                        break;
+                    }
+                }
+                val = s->gzhead->name[s->gzindex++];
+                put_byte(s, val);
+            } while (val != 0);
+            if (s->gzhead->hcrc && s->pending > beg)
+                strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                    s->pending - beg);
+            if (val == 0) {
+                s->gzindex = 0;
+                s->status = COMMENT_STATE;
+            }
+        }
+        else
+            s->status = COMMENT_STATE;
+    }
+    if (s->status == COMMENT_STATE) {
+        if (s->gzhead->comment != Z_NULL) {
+            uInt beg = s->pending;  /* start of bytes to update crc */
+            int val;
+
+            do {
+                if (s->pending == s->pending_buf_size) {
+                    if (s->gzhead->hcrc && s->pending > beg)
+                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                            s->pending - beg);
+                    flush_pending(strm);
+                    beg = s->pending;
+                    if (s->pending == s->pending_buf_size) {
+                        val = 1;
+                        break;
+                    }
+                }
+                val = s->gzhead->comment[s->gzindex++];
+                put_byte(s, val);
+            } while (val != 0);
+            if (s->gzhead->hcrc && s->pending > beg)
+                strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                    s->pending - beg);
+            if (val == 0)
+                s->status = HCRC_STATE;
+        }
+        else
+            s->status = HCRC_STATE;
+    }
+    if (s->status == HCRC_STATE) {
+        if (s->gzhead->hcrc) {
+            if (s->pending + 2 > s->pending_buf_size)
+                flush_pending(strm);
+            if (s->pending + 2 <= s->pending_buf_size) {
+                put_byte(s, (Byte)(strm->adler & 0xff));
+                put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+                strm->adler = crc32(0L, Z_NULL, 0);
+                s->status = BUSY_STATE;
+            }
+        }
+        else
+            s->status = BUSY_STATE;
+    }
+#endif
+
+    /* Flush as much pending output as possible */
+    if (s->pending != 0) {
+        flush_pending(strm);
+        if (strm->avail_out == 0) {
+            /* Since avail_out is 0, deflate will be called again with
+             * more output space, but possibly with both pending and
+             * avail_in equal to zero. There won't be anything to do,
+             * but this is not an error situation so make sure we
+             * return OK instead of BUF_ERROR at next call of deflate:
+             */
+            s->last_flush = -1;
+            return Z_OK;
+        }
+
+    /* Make sure there is something to do and avoid duplicate consecutive
+     * flushes. For repeated and useless calls with Z_FINISH, we keep
+     * returning Z_STREAM_END instead of Z_BUF_ERROR.
+     */
+    } else if (strm->avail_in == 0 && flush <= old_flush &&
+               flush != Z_FINISH) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* User must not provide more input after the first FINISH: */
+    if (s->status == FINISH_STATE && strm->avail_in != 0) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* Start a new block or continue the current one.
+     */
+    if (strm->avail_in != 0 || s->lookahead != 0 ||
+        (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+        block_state bstate;
+
+        bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
+                    (s->strategy == Z_RLE ? deflate_rle(s, flush) :
+                        (*(configuration_table[s->level].func))(s, flush));
+
+        if (bstate == finish_started || bstate == finish_done) {
+            s->status = FINISH_STATE;
+        }
+        if (bstate == need_more || bstate == finish_started) {
+            if (strm->avail_out == 0) {
+                s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+            }
+            return Z_OK;
+            /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+             * of deflate should use the same flush parameter to make sure
+             * that the flush is complete. So we don't have to output an
+             * empty block here, this will be done at next call. This also
+             * ensures that for a very small output buffer, we emit at most
+             * one empty block.
+             */
+        }
+        if (bstate == block_done) {
+            if (flush == Z_PARTIAL_FLUSH) {
+                _tr_align(s);
+            } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
+                _tr_stored_block(s, (char*)0, 0L, 0);
+                /* For a full flush, this empty block will be recognized
+                 * as a special marker by inflate_sync().
+                 */
+                if (flush == Z_FULL_FLUSH) {
+                    CLEAR_HASH(s);             /* forget history */
+                    if (s->lookahead == 0) {
+                        s->strstart = 0;
+                        s->block_start = 0L;
+                    }
+                }
+            }
+            flush_pending(strm);
+            if (strm->avail_out == 0) {
+              s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+              return Z_OK;
+            }
+        }
+    }
+    Assert(strm->avail_out > 0, "bug2");
+
+    if (flush != Z_FINISH) return Z_OK;
+    if (s->wrap <= 0) return Z_STREAM_END;
+
+    /* Write the trailer */
+#ifdef GZIP
+    if (s->wrap == 2) {
+        put_byte(s, (Byte)(strm->adler & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
+        put_byte(s, (Byte)(strm->total_in & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
+    }
+    else
+#endif
+    {
+        putShortMSB(s, (uInt)(strm->adler >> 16));
+        putShortMSB(s, (uInt)(strm->adler & 0xffff));
+    }
+    flush_pending(strm);
+    /* If avail_out is zero, the application will call deflate again
+     * to flush the rest.
+     */
+    if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
+    return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd (z_streamp strm)
+{
+    int status;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+
+    status = strm->state->status;
+    if (status != INIT_STATE &&
+        status != EXTRA_STATE &&
+        status != NAME_STATE &&
+        status != COMMENT_STATE &&
+        status != HCRC_STATE &&
+        status != BUSY_STATE &&
+        status != FINISH_STATE) {
+      return Z_STREAM_ERROR;
+    }
+
+    /* Deallocate in reverse order of allocations: */
+    TRY_FREE(strm, strm->state->pending_buf);
+    TRY_FREE(strm, strm->state->head);
+    TRY_FREE(strm, strm->state->prev);
+    TRY_FREE(strm, strm->state->window);
+
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+
+    return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy (z_streamp dest, z_streamp source)
+{
+#ifdef MAXSEG_64K
+    return Z_STREAM_ERROR;
+#else
+    deflate_state *ds;
+    deflate_state *ss;
+    ushf *overlay;
+
+
+    if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
+        return Z_STREAM_ERROR;
+    }
+
+    ss = source->state;
+
+    zmemcpy(dest, source, sizeof(z_stream));
+
+    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+    if (ds == Z_NULL) return Z_MEM_ERROR;
+    dest->state = (struct internal_state FAR *) ds;
+    zmemcpy(ds, ss, sizeof(deflate_state));
+    ds->strm = dest;
+
+    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+    ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));
+    ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));
+    overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
+    ds->pending_buf = (uchf *) overlay;
+
+    if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+        ds->pending_buf == Z_NULL) {
+        deflateEnd (dest);
+        return Z_MEM_ERROR;
+    }
+    /* following zmemcpy do not work for 16-bit MSDOS */
+    zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+    zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
+    zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
+    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+    ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
+    ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+
+    ds->l_desc.dyn_tree = ds->dyn_ltree;
+    ds->d_desc.dyn_tree = ds->dyn_dtree;
+    ds->bl_desc.dyn_tree = ds->bl_tree;
+
+    return Z_OK;
+#endif /* MAXSEG_64K */
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read.  All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local int read_buf(z_streamp strm, Bytef *buf, unsigned size)
+{
+    unsigned len = strm->avail_in;
+
+    if (len > size) len = size;
+    if (len == 0) return 0;
+
+    strm->avail_in  -= len;
+
+    if (strm->state->wrap == 1) {
+        strm->adler = adler32(strm->adler, strm->next_in, len);
+    }
+#ifdef GZIP
+    else if (strm->state->wrap == 2) {
+        strm->adler = crc32(strm->adler, strm->next_in, len);
+    }
+#endif
+    zmemcpy(buf, strm->next_in, len);
+    strm->next_in  += len;
+    strm->total_in += len;
+
+    return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (deflate_state *s)
+{
+    s->window_size = (ulg)2L*s->w_size;
+
+    CLEAR_HASH(s);
+
+    /* Set the default configuration parameters:
+     */
+    s->max_lazy_match   = configuration_table[s->level].max_lazy;
+    s->good_match       = configuration_table[s->level].good_length;
+    s->nice_match       = configuration_table[s->level].nice_length;
+    s->max_chain_length = configuration_table[s->level].max_chain;
+
+    s->strstart = 0;
+    s->block_start = 0L;
+    s->lookahead = 0;
+    s->match_length = s->prev_length = MIN_MATCH-1;
+    s->match_available = 0;
+    s->ins_h = 0;
+#ifndef FASTEST
+#ifdef ASMV
+    match_init(); /* initialize the asm code */
+#endif
+#endif
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+local uInt longest_match(deflate_state *s, IPos cur_match)
+{
+    unsigned chain_length = s->max_chain_length;/* max hash chain length */
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                       /* matched string */
+    register int len;                           /* length of current match */
+    int best_len = s->prev_length;              /* best match length so far */
+    int nice_match = s->nice_match;             /* stop if match long enough */
+    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+        s->strstart - (IPos)MAX_DIST(s) : NIL;
+    /* Stop when cur_match becomes <= limit. To simplify the code,
+     * we prevent matches with the string of window index 0.
+     */
+    Posf *prev = s->prev;
+    uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+    /* Compare two bytes at a time. Note: this is not always beneficial.
+     * Try with and without -DUNALIGNED_OK to check.
+     */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+    register ush scan_start = *(ushf*)scan;
+    register ush scan_end   = *(ushf*)(scan+best_len-1);
+#else
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+    register Byte scan_end1  = scan[best_len-1];
+    register Byte scan_end   = scan[best_len];
+#endif
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    /* Do not waste too much time if we already have a good match: */
+    if (s->prev_length >= s->good_match) {
+        chain_length >>= 2;
+    }
+    /* Do not look for matches beyond the end of the input. This is necessary
+     * to make deflate deterministic.
+     */
+    if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    do {
+        Assert(cur_match < s->strstart, "no future");
+        match = s->window + cur_match;
+
+        /* Skip to next match if the match length cannot increase
+         * or if the match length is less than 2.  Note that the checks below
+         * for insufficient lookahead only occur occasionally for performance
+         * reasons.  Therefore uninitialized memory will be accessed, and
+         * conditional jumps will be made that depend on those values.
+         * However the length of the match is limited to the lookahead, so
+         * the output of deflate is not affected by the uninitialized values.
+         */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+        /* This code assumes sizeof(unsigned short) == 2. Do not use
+         * UNALIGNED_OK if your compiler uses a different size.
+         */
+        if (*(ushf*)(match+best_len-1) != scan_end ||
+            *(ushf*)match != scan_start) continue;
+
+        /* It is not necessary to compare scan[2] and match[2] since they are
+         * always equal when the other bytes match, given that the hash keys
+         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+         * strstart+3, +5, ... up to strstart+257. We check for insufficient
+         * lookahead only every 4th comparison; the 128th check will be made
+         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+         * necessary to put more guard bytes at the end of the window, or
+         * to check more often for insufficient lookahead.
+         */
+        Assert(scan[2] == match[2], "scan[2]?");
+        scan++, match++;
+        do {
+        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 scan < strend);
+        /* The funny "do {}" generates better code on most compilers */
+
+        /* Here, scan <= window+strstart+257 */
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+        if (*scan == *match) scan++;
+
+        len = (MAX_MATCH - 1) - (int)(strend-scan);
+        scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+        if (match[best_len]   != scan_end  ||
+            match[best_len-1] != scan_end1 ||
+            *match            != *scan     ||
+            *++match          != scan[1])      continue;
+
+        /* The check at best_len-1 can be removed because it will be made
+         * again later. (This heuristic is not always a win.)
+         * It is not necessary to compare scan[2] and match[2] since they
+         * are always equal when the other bytes match, given that
+         * the hash keys are equal and that HASH_BITS >= 8.
+         */
+        scan += 2, match++;
+        Assert(*scan == *match, "match[2]?");
+
+        /* We check for insufficient lookahead only every 8th comparison;
+         * the 256th check will be made at strstart+258.
+         */
+        do {
+        } while (*++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 scan < strend);
+
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+        len = MAX_MATCH - (int)(strend - scan);
+        scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+        if (len > best_len) {
+            s->match_start = cur_match;
+            best_len = len;
+            if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+            scan_end = *(ushf*)(scan+best_len-1);
+#else
+            scan_end1  = scan[best_len-1];
+            scan_end   = scan[best_len];
+#endif
+        }
+    } while ((cur_match = prev[cur_match & wmask]) > limit
+             && --chain_length != 0);
+
+    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+    return s->lookahead;
+}
+#endif /* ASMV */
+
+#else /* FASTEST */
+
+/* ---------------------------------------------------------------------------
+ * Optimized version for FASTEST only
+ */
+local uInt longest_match(deflate_state *s, IPos cur_match)
+{
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                       /* matched string */
+    register int len;                           /* length of current match */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    Assert(cur_match < s->strstart, "no future");
+
+    match = s->window + cur_match;
+
+    /* Return failure if the match length is less than 2:
+     */
+    if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+    /* The check at best_len-1 can be removed because it will be made
+     * again later. (This heuristic is not always a win.)
+     * It is not necessary to compare scan[2] and match[2] since they
+     * are always equal when the other bytes match, given that
+     * the hash keys are equal and that HASH_BITS >= 8.
+     */
+    scan += 2, match += 2;
+    Assert(*scan == *match, "match[2]?");
+
+    /* We check for insufficient lookahead only every 8th comparison;
+     * the 256th check will be made at strstart+258.
+     */
+    do {
+    } while (*++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             scan < strend);
+
+    Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+    len = MAX_MATCH - (int)(strend - scan);
+
+    if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+    s->match_start = cur_match;
+    return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
+}
+
+#endif /* FASTEST */
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(deflate_state *s, IPos start, IPos match, int length)
+{
+    /* check that the match is indeed a match */
+    if (zmemcmp(s->window + match,
+                s->window + start, length) != EQUAL) {
+        fprintf(stderr, " start %u, match %u, length %d\n",
+                start, match, length);
+        do {
+            fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+        } while (--length != 0);
+        z_error("invalid match");
+    }
+    if (z_verbose > 1) {
+        fprintf(stderr,"\\[%d,%d]", start-match, length);
+        do { putc(s->window[start++], stderr); } while (--length != 0);
+    }
+}
+#else
+#  define check_match(s, start, match, length)
+#endif /* DEBUG */
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ *    At least one byte has been read, or avail_in == 0; reads are
+ *    performed for at least two bytes (required for the zip translate_eol
+ *    option -- not supported here).
+ */
+local void fill_window(deflate_state *s)
+{
+    register unsigned n, m;
+    register Posf *p;
+    unsigned more;    /* Amount of free space at the end of the window. */
+    uInt wsize = s->w_size;
+
+    do {
+        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+        /* Deal with !@#$% 64K limit: */
+        if (sizeof(int) <= 2) {
+            if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+                more = wsize;
+
+            } else if (more == (unsigned)(-1)) {
+                /* Very unlikely, but possible on 16 bit machine if
+                 * strstart == 0 && lookahead == 1 (input done a byte at time)
+                 */
+                more--;
+            }
+        }
+
+        /* If the window is almost full and there is insufficient lookahead,
+         * move the upper half to the lower one to make room in the upper half.
+         */
+        if (s->strstart >= wsize+MAX_DIST(s)) {
+
+            zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
+            s->match_start -= wsize;
+            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */
+            s->block_start -= (long) wsize;
+
+            /* Slide the hash table (could be avoided with 32 bit values
+               at the expense of memory usage). We slide even when level == 0
+               to keep the hash table consistent if we switch back to level > 0
+               later. (Using level 0 permanently is not an optimal usage of
+               zlib, so we don't care about this pathological case.)
+             */
+            n = s->hash_size;
+            p = &s->head[n];
+            do {
+                m = *--p;
+                *p = (Pos)(m >= wsize ? m-wsize : NIL);
+            } while (--n);
+
+            n = wsize;
+#ifndef FASTEST
+            p = &s->prev[n];
+            do {
+                m = *--p;
+                *p = (Pos)(m >= wsize ? m-wsize : NIL);
+                /* If n is not on any hash chain, prev[n] is garbage but
+                 * its value will never be used.
+                 */
+            } while (--n);
+#endif
+            more += wsize;
+        }
+        if (s->strm->avail_in == 0) return;
+
+        /* If there was no sliding:
+         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+         *    more == window_size - lookahead - strstart
+         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+         * => more >= window_size - 2*WSIZE + 2
+         * In the BIG_MEM or MMAP case (not yet supported),
+         *   window_size == input_size + MIN_LOOKAHEAD  &&
+         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+         * Otherwise, window_size == 2*WSIZE so more >= 2.
+         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+         */
+        Assert(more >= 2, "more < 2");
+
+        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+        s->lookahead += n;
+
+        /* Initialize the hash value now that we have some input: */
+        if (s->lookahead >= MIN_MATCH) {
+            s->ins_h = s->window[s->strstart];
+            UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+            Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+        }
+        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+         * but this is not important since only literal bytes will be emitted.
+         */
+
+    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+
+    /* If the WIN_INIT bytes after the end of the current data have never been
+     * written, then zero those bytes in order to avoid memory check reports of
+     * the use of uninitialized (or uninitialised as Julian writes) bytes by
+     * the longest match routines.  Update the high water mark for the next
+     * time through here.  WIN_INIT is set to MAX_MATCH since the longest match
+     * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
+     */
+    if (s->high_water < s->window_size) {
+        ulg curr = s->strstart + (ulg)(s->lookahead);
+        ulg init;
+
+        if (s->high_water < curr) {
+            /* Previous high water mark below current data -- zero WIN_INIT
+             * bytes or up to end of window, whichever is less.
+             */
+            init = s->window_size - curr;
+            if (init > WIN_INIT)
+                init = WIN_INIT;
+            zmemzero(s->window + curr, (unsigned)init);
+            s->high_water = curr + init;
+        }
+        else if (s->high_water < (ulg)curr + WIN_INIT) {
+            /* High water mark at or above current data, but below current data
+             * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
+             * to end of window, whichever is less.
+             */
+            init = (ulg)curr + WIN_INIT - s->high_water;
+            if (init > s->window_size - s->high_water)
+                init = s->window_size - s->high_water;
+            zmemzero(s->window + s->high_water, (unsigned)init);
+            s->high_water += init;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, last) { \
+   _tr_flush_block(s, (s->block_start >= 0L ? \
+                   (charf *)&s->window[(unsigned)s->block_start] : \
+                   (charf *)Z_NULL), \
+                (ulg)((long)s->strstart - s->block_start), \
+                (last)); \
+   s->block_start = s->strstart; \
+   flush_pending(s->strm); \
+   Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, last) { \
+   FLUSH_BLOCK_ONLY(s, last); \
+   if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+local block_state deflate_stored(deflate_state *s, int flush)
+{
+    /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+     * to pending_buf_size, and each stored block has a 5 byte header:
+     */
+    ulg max_block_size = 0xffff;
+    ulg max_start;
+
+    if (max_block_size > s->pending_buf_size - 5) {
+        max_block_size = s->pending_buf_size - 5;
+    }
+
+    /* Copy as much as possible from input to output: */
+    for (;;) {
+        /* Fill the window as much as possible: */
+        if (s->lookahead <= 1) {
+
+            Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+                   s->block_start >= (long)s->w_size, "slide too late");
+
+            fill_window(s);
+            if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+        Assert(s->block_start >= 0L, "block gone");
+
+        s->strstart += s->lookahead;
+        s->lookahead = 0;
+
+        /* Emit a stored block if pending_buf will be full: */
+        max_start = s->block_start + max_block_size;
+        if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
+            /* strstart == 0 is possible when wraparound on 16-bit machine */
+            s->lookahead = (uInt)(s->strstart - max_start);
+            s->strstart = (uInt)max_start;
+            FLUSH_BLOCK(s, 0);
+        }
+        /* Flush if we may have to slide, otherwise block_start may become
+         * negative and the data will be gone:
+         */
+        if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+            FLUSH_BLOCK(s, 0);
+        }
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(deflate_state *s, int flush)
+{
+    IPos hash_head;       /* head of the hash chain */
+    int bflush;           /* set if current block must be flushed */
+
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        hash_head = NIL;
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         * At this point we have always match_length < MIN_MATCH
+         */
+        if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+            s->match_length = longest_match (s, hash_head);
+            /* longest_match() sets match_start */
+        }
+        if (s->match_length >= MIN_MATCH) {
+            check_match(s, s->strstart, s->match_start, s->match_length);
+
+            _tr_tally_dist(s, s->strstart - s->match_start,
+                           s->match_length - MIN_MATCH, bflush);
+
+            s->lookahead -= s->match_length;
+
+            /* Insert new strings in the hash table only if the match length
+             * is not too large. This saves time but degrades compression.
+             */
+#ifndef FASTEST
+            if (s->match_length <= s->max_insert_length &&
+                s->lookahead >= MIN_MATCH) {
+                s->match_length--; /* string at strstart already in table */
+                do {
+                    s->strstart++;
+                    INSERT_STRING(s, s->strstart, hash_head);
+                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+                     * always MIN_MATCH bytes ahead.
+                     */
+                } while (--s->match_length != 0);
+                s->strstart++;
+            } else
+#endif
+            {
+                s->strstart += s->match_length;
+                s->match_length = 0;
+                s->ins_h = s->window[s->strstart];
+                UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+                Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+                /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+                 * matter since it will be recomputed at next deflate call.
+                 */
+            }
+        } else {
+            /* No match, output a literal byte */
+            Tracevv((stderr,"%c", s->window[s->strstart]));
+            _tr_tally_lit (s, s->window[s->strstart], bflush);
+            s->lookahead--;
+            s->strstart++;
+        }
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(deflate_state *s, int flush)
+{
+    IPos hash_head;          /* head of hash chain */
+    int bflush;              /* set if current block must be flushed */
+
+    /* Process the input block. */
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        hash_head = NIL;
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         */
+        s->prev_length = s->match_length, s->prev_match = s->match_start;
+        s->match_length = MIN_MATCH-1;
+
+        if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+            s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+            s->match_length = longest_match (s, hash_head);
+            /* longest_match() sets match_start */
+
+            if (s->match_length <= 5 && (s->strategy == Z_FILTERED
+#if TOO_FAR <= 32767
+                || (s->match_length == MIN_MATCH &&
+                    s->strstart - s->match_start > TOO_FAR)
+#endif
+                )) {
+
+                /* If prev_match is also MIN_MATCH, match_start is garbage
+                 * but we will ignore the current match anyway.
+                 */
+                s->match_length = MIN_MATCH-1;
+            }
+        }
+        /* If there was a match at the previous step and the current
+         * match is not better, output the previous match:
+         */
+        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+            /* Do not insert strings in hash table beyond this. */
+
+            check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+            _tr_tally_dist(s, s->strstart -1 - s->prev_match,
+                           s->prev_length - MIN_MATCH, bflush);
+
+            /* Insert in hash table all strings up to the end of the match.
+             * strstart-1 and strstart are already inserted. If there is not
+             * enough lookahead, the last two strings are not inserted in
+             * the hash table.
+             */
+            s->lookahead -= s->prev_length-1;
+            s->prev_length -= 2;
+            do {
+                if (++s->strstart <= max_insert) {
+                    INSERT_STRING(s, s->strstart, hash_head);
+                }
+            } while (--s->prev_length != 0);
+            s->match_available = 0;
+            s->match_length = MIN_MATCH-1;
+            s->strstart++;
+
+            if (bflush) FLUSH_BLOCK(s, 0);
+
+        } else if (s->match_available) {
+            /* If there was no match at the previous position, output a
+             * single literal. If there was a match but the current match
+             * is longer, truncate the previous match to a single literal.
+             */
+            Tracevv((stderr,"%c", s->window[s->strstart-1]));
+            _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+            if (bflush) {
+                FLUSH_BLOCK_ONLY(s, 0);
+            }
+            s->strstart++;
+            s->lookahead--;
+            if (s->strm->avail_out == 0) return need_more;
+        } else {
+            /* There is no previous match to compare with, wait for
+             * the next step to decide.
+             */
+            s->match_available = 1;
+            s->strstart++;
+            s->lookahead--;
+        }
+    }
+    Assert (flush != Z_NO_FLUSH, "no flush?");
+    if (s->match_available) {
+        Tracevv((stderr,"%c", s->window[s->strstart-1]));
+        _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+        s->match_available = 0;
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif /* FASTEST */
+
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one.  Do not maintain a hash table.  (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+local block_state deflate_rle(deflate_state *s, int flush)
+{
+    int bflush;             /* set if current block must be flushed */
+    uInt prev;              /* byte at distance one to match */
+    Bytef *scan, *strend;   /* scan goes up to strend for length of run */
+
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the longest encodable run.
+         */
+        if (s->lookahead < MAX_MATCH) {
+            fill_window(s);
+            if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* See how many times the previous byte repeats */
+        s->match_length = 0;
+        if (s->lookahead >= MIN_MATCH && s->strstart > 0) {
+            scan = s->window + s->strstart - 1;
+            prev = *scan;
+            if (prev == *++scan && prev == *++scan && prev == *++scan) {
+                strend = s->window + s->strstart + MAX_MATCH;
+                do {
+                } while (prev == *++scan && prev == *++scan &&
+                         prev == *++scan && prev == *++scan &&
+                         prev == *++scan && prev == *++scan &&
+                         prev == *++scan && prev == *++scan &&
+                         scan < strend);
+                s->match_length = MAX_MATCH - (int)(strend - scan);
+                if (s->match_length > s->lookahead)
+                    s->match_length = s->lookahead;
+            }
+        }
+
+        /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+        if (s->match_length >= MIN_MATCH) {
+            check_match(s, s->strstart, s->strstart - 1, s->match_length);
+
+            _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);
+
+            s->lookahead -= s->match_length;
+            s->strstart += s->match_length;
+            s->match_length = 0;
+        } else {
+            /* No match, output a literal byte */
+            Tracevv((stderr,"%c", s->window[s->strstart]));
+            _tr_tally_lit (s, s->window[s->strstart], bflush);
+            s->lookahead--;
+            s->strstart++;
+        }
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.
+ * (It will be regenerated if this run of deflate switches away from Huffman.)
+ */
+local block_state deflate_huff(deflate_state *s, int flush)
+{
+    int bflush;             /* set if current block must be flushed */
+
+    for (;;) {
+        /* Make sure that we have a literal to write. */
+        if (s->lookahead == 0) {
+            fill_window(s);
+            if (s->lookahead == 0) {
+                if (flush == Z_NO_FLUSH)
+                    return need_more;
+                break;      /* flush the current block */
+            }
+        }
+
+        /* Output a literal byte */
+        s->match_length = 0;
+        Tracevv((stderr,"%c", s->window[s->strstart]));
+        _tr_tally_lit (s, s->window[s->strstart], bflush);
+        s->lookahead--;
+        s->strstart++;
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/zlib/deflate.h b/abc-build/src/misc/zlib/deflate.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/deflate.h
@@ -0,0 +1,346 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-2010 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef DEFLATE_H
+#define DEFLATE_H
+
+#include "zutil.h"
+
+ABC_NAMESPACE_HEADER_START
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+   trailer creation by deflate().  NO_GZIP would be used to avoid linking in
+   the crc code when it is not needed.  For shared libraries, gzip encoding
+   should be left enabled. */
+#ifndef NO_GZIP
+#  define GZIP
+#endif
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS  256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES   30
+/* number of distance codes */
+
+#define BL_CODES  19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE    42
+#define EXTRA_STATE   69
+#define NAME_STATE    73
+#define COMMENT_STATE 91
+#define HCRC_STATE   103
+#define BUSY_STATE   113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+    union {
+        ush  freq;       /* frequency count */
+        ush  code;       /* bit string */
+    } fc;
+    union {
+        ush  dad;        /* father node in Huffman tree */
+        ush  len;        /* length of bit string */
+    } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad  dl.dad
+#define Len  dl.len
+
+typedef struct static_tree_desc_s  static_tree_desc;
+
+typedef struct tree_desc_s {
+    ct_data *dyn_tree;           /* the dynamic tree */
+    int     max_code;            /* largest code with non zero frequency */
+    static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+    z_streamp strm;      /* pointer back to this zlib stream */
+    int   status;        /* as the name implies */
+    Bytef *pending_buf;  /* output still pending */
+    ulg   pending_buf_size; /* size of pending_buf */
+    Bytef *pending_out;  /* next pending byte to output to the stream */
+    uInt   pending;      /* nb of bytes in the pending buffer */
+    int   wrap;          /* bit 0 true for zlib, bit 1 true for gzip */
+    gz_headerp  gzhead;  /* gzip header information to write */
+    uInt   gzindex;      /* where in extra, name, or comment */
+    Byte  method;        /* STORED (for zip only) or DEFLATED */
+    int   last_flush;    /* value of flush param for previous deflate call */
+
+                /* used by deflate.c: */
+
+    uInt  w_size;        /* LZ77 window size (32K by default) */
+    uInt  w_bits;        /* log2(w_size)  (8..16) */
+    uInt  w_mask;        /* w_size - 1 */
+
+    Bytef *window;
+    /* Sliding window. Input bytes are read into the second half of the window,
+     * and move to the first half later to keep a dictionary of at least wSize
+     * bytes. With this organization, matches are limited to a distance of
+     * wSize-MAX_MATCH bytes, but this ensures that IO is always
+     * performed with a length multiple of the block size. Also, it limits
+     * the window size to 64K, which is quite useful on MSDOS.
+     * To do: use the user input buffer as sliding window.
+     */
+
+    ulg window_size;
+    /* Actual size of window: 2*wSize, except when the user input buffer
+     * is directly used as sliding window.
+     */
+
+    Posf *prev;
+    /* Link to older string with same hash index. To limit the size of this
+     * array to 64K, this link is maintained only for the last 32K strings.
+     * An index in this array is thus a window index modulo 32K.
+     */
+
+    Posf *head; /* Heads of the hash chains or NIL. */
+
+    uInt  ins_h;          /* hash index of string to be inserted */
+    uInt  hash_size;      /* number of elements in hash table */
+    uInt  hash_bits;      /* log2(hash_size) */
+    uInt  hash_mask;      /* hash_size-1 */
+
+    uInt  hash_shift;
+    /* Number of bits by which ins_h must be shifted at each input
+     * step. It must be such that after MIN_MATCH steps, the oldest
+     * byte no longer takes part in the hash key, that is:
+     *   hash_shift * MIN_MATCH >= hash_bits
+     */
+
+    long block_start;
+    /* Window position at the beginning of the current output block. Gets
+     * negative when the window is moved backwards.
+     */
+
+    uInt match_length;           /* length of best match */
+    IPos prev_match;             /* previous match */
+    int match_available;         /* set if previous match exists */
+    uInt strstart;               /* start of string to insert */
+    uInt match_start;            /* start of matching string */
+    uInt lookahead;              /* number of valid bytes ahead in window */
+
+    uInt prev_length;
+    /* Length of the best match at previous step. Matches not greater than this
+     * are discarded. This is used in the lazy match evaluation.
+     */
+
+    uInt max_chain_length;
+    /* To speed up deflation, hash chains are never searched beyond this
+     * length.  A higher limit improves compression ratio but degrades the
+     * speed.
+     */
+
+    uInt max_lazy_match;
+    /* Attempt to find a better match only when the current match is strictly
+     * smaller than this value. This mechanism is used only for compression
+     * levels >= 4.
+     */
+#   define max_insert_length  max_lazy_match
+    /* Insert new strings in the hash table only if the match length is not
+     * greater than this length. This saves time but degrades compression.
+     * max_insert_length is used only for compression levels <= 3.
+     */
+
+    int level;    /* compression level (1..9) */
+    int strategy; /* favor or force Huffman coding*/
+
+    uInt good_match;
+    /* Use a faster search when the previous match is longer than this */
+
+    int nice_match; /* Stop searching when current match exceeds this */
+
+                /* used by trees.c: */
+    /* Didn't use ct_data typedef below to supress compiler warning */
+    struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
+    struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+    struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
+
+    struct tree_desc_s l_desc;               /* desc. for literal tree */
+    struct tree_desc_s d_desc;               /* desc. for distance tree */
+    struct tree_desc_s bl_desc;              /* desc. for bit length tree */
+
+    ush bl_count[MAX_BITS+1];
+    /* number of codes at each bit length for an optimal tree */
+
+    int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
+    int heap_len;               /* number of elements in the heap */
+    int heap_max;               /* element of largest frequency */
+    /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+     * The same heap array is used to build all trees.
+     */
+
+    uch depth[2*L_CODES+1];
+    /* Depth of each subtree used as tie breaker for trees of equal frequency
+     */
+
+    uchf *l_buf;          /* buffer for literals or lengths */
+
+    uInt  lit_bufsize;
+    /* Size of match buffer for literals/lengths.  There are 4 reasons for
+     * limiting lit_bufsize to 64K:
+     *   - frequencies can be kept in 16 bit counters
+     *   - if compression is not successful for the first block, all input
+     *     data is still in the window so we can still emit a stored block even
+     *     when input comes from standard input.  (This can also be done for
+     *     all blocks if lit_bufsize is not greater than 32K.)
+     *   - if compression is not successful for a file smaller than 64K, we can
+     *     even emit a stored file instead of a stored block (saving 5 bytes).
+     *     This is applicable only for zip (not gzip or zlib).
+     *   - creating new Huffman trees less frequently may not provide fast
+     *     adaptation to changes in the input data statistics. (Take for
+     *     example a binary file with poorly compressible code followed by
+     *     a highly compressible string table.) Smaller buffer sizes give
+     *     fast adaptation but have of course the overhead of transmitting
+     *     trees more frequently.
+     *   - I can't count above 4
+     */
+
+    uInt last_lit;      /* running index in l_buf */
+
+    ushf *d_buf;
+    /* Buffer for distances. To simplify the code, d_buf and l_buf have
+     * the same number of elements. To use different lengths, an extra flag
+     * array would be necessary.
+     */
+
+    ulg opt_len;        /* bit length of current block with optimal trees */
+    ulg static_len;     /* bit length of current block with static trees */
+    uInt matches;       /* number of string matches in current block */
+    int last_eob_len;   /* bit length of EOB code for last block */
+
+#ifdef DEBUG
+    ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+    ulg bits_sent;      /* bit length of compressed data sent mod 2^32 */
+#endif
+
+    ush bi_buf;
+    /* Output buffer. bits are inserted starting at the bottom (least
+     * significant bits).
+     */
+    int bi_valid;
+    /* Number of valid bits in bi_buf.  All bits above the last valid bit
+     * are always zero.
+     */
+
+    ulg high_water;
+    /* High water mark offset in window for initialized bytes -- bytes above
+     * this are set to zero in order to avoid memory check warnings when
+     * longest match routines access bytes past the input.  This is then
+     * updated to the new high water mark.
+     */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s)  ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+#define WIN_INIT MAX_MATCH
+/* Number of bytes after end of data in window to initialize in order to avoid
+   memory checker errors from longest match routines */
+
+        /* in trees.c */
+void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
+int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
+void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
+                        ulg stored_len, int last));
+void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
+void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
+                        ulg stored_len, int last));
+
+#define d_code(dist) \
+   ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+  extern uch ZLIB_INTERNAL _length_code[];
+  extern uch ZLIB_INTERNAL _dist_code[];
+#else
+  extern const uch ZLIB_INTERNAL _length_code[];
+  extern const uch ZLIB_INTERNAL _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+  { uch cc = (c); \
+    s->d_buf[s->last_lit] = 0; \
+    s->l_buf[s->last_lit++] = cc; \
+    s->dyn_ltree[cc].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+   }
+# define _tr_tally_dist(s, distance, length, flush) \
+  { uch len = (length); \
+    ush dist = (distance); \
+    s->d_buf[s->last_lit] = dist; \
+    s->l_buf[s->last_lit++] = len; \
+    dist--; \
+    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+    s->dyn_dtree[d_code(dist)].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+  }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+              flush = _tr_tally(s, distance, length)
+#endif
+
+ABC_NAMESPACE_HEADER_END
+
+#endif /* DEFLATE_H */
diff --git a/abc-build/src/misc/zlib/gzclose.c b/abc-build/src/misc/zlib/gzclose.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/gzclose.c
@@ -0,0 +1,33 @@
+/* gzclose.c -- zlib gzclose() function
+ * Copyright (C) 2004, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc/util/abc_global.h"
+
+#include "gzguts.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/* gzclose() is in a separate file so that it is linked in only if it is used.
+   That way the other gzclose functions can be used instead to avoid linking in
+   unneeded compression or decompression routines. */
+int ZEXPORT gzclose(gzFile file)
+{
+#ifndef NO_GZCOMPRESS
+    gz_statep state;
+
+    if (file == NULL)
+        return Z_STREAM_ERROR;
+    state = (gz_statep)file;
+
+    return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file);
+#else
+    return gzclose_r(file);
+#endif
+}
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/misc/zlib/gzguts.h b/abc-build/src/misc/zlib/gzguts.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/gzguts.h
@@ -0,0 +1,147 @@
+/* gzguts.h -- zlib internal header definitions for gz* operations
+ * Copyright (C) 2004, 2005, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#ifdef _LARGEFILE64_SOURCE
+#  ifndef _LARGEFILE_SOURCE
+#    define _LARGEFILE_SOURCE 1
+#  endif
+#  ifdef _FILE_OFFSET_BITS
+#    undef _FILE_OFFSET_BITS
+#  endif
+#endif
+
+#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ)
+#  define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+#else
+#  define ZLIB_INTERNAL
+#endif
+
+#include <stdio.h>
+#include "zlib.h"
+#ifdef STDC
+#  include <string.h>
+#  include <stdlib.h>
+#  include <limits.h>
+#endif
+#include <fcntl.h>
+
+#ifdef NO_DEFLATE       /* for compatibility with old definition */
+#  define NO_GZCOMPRESS
+#endif
+
+#ifdef _MSC_VER
+#  include <io.h>
+#  define vsnprintf _vsnprintf
+#endif
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+/* gz* functions always use library allocation functions */
+#ifndef STDC
+  extern voidp  malloc OF((uInt size));
+  extern void   free   OF((voidpf ptr));
+#endif
+
+/* get errno and strerror definition */
+#if defined UNDER_CE
+#  include <windows.h>
+#  define zstrerror() gz_strwinerror((DWORD)GetLastError())
+#else
+#  ifdef STDC
+#    include <errno.h>
+#    define zstrerror() strerror(errno)
+#  else
+#    define zstrerror() "stdio error (consult errno)"
+#  endif
+#endif
+
+#include <stdio.h>
+#include "misc/util/abc_global.h"
+
+ABC_NAMESPACE_HEADER_START
+
+#ifdef _WIN32
+#define open  _open
+#define close _close
+#define lseek _lseek
+#define read  _read
+#define write _write
+#endif
+
+/* provide prototypes for these when building zlib without LFS */
+#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
+    ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+    ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
+    ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
+    ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+#endif
+
+/* default i/o buffer size -- double this for output when reading */
+#define GZBUFSIZE 8192
+
+/* gzip modes, also provide a little integrity check on the passed structure */
+#define GZ_NONE 0
+#define GZ_READ 7247
+#define GZ_WRITE 31153
+#define GZ_APPEND 1     /* mode set to GZ_WRITE after the file is opened */
+
+/* values for gz_state how */
+#define LOOK 0      /* look for a gzip header */
+#define COPY 1      /* copy input directly */
+#define GZIP 2      /* decompress a gzip stream */
+
+/* internal gzip file state data structure */
+typedef struct {
+        /* used for both reading and writing */
+    int mode;               /* see gzip modes above */
+    int fd;                 /* file descriptor */
+    char *path;             /* path or fd for error messages */
+    z_off64_t pos;          /* current position in uncompressed data */
+    unsigned size;          /* buffer size, zero if not allocated yet */
+    unsigned want;          /* requested buffer size, default is GZBUFSIZE */
+    unsigned char *in;      /* input buffer */
+    unsigned char *out;     /* output buffer (double-sized when reading) */
+    unsigned char *next;    /* next output data to deliver or write */
+        /* just for reading */
+    unsigned have;          /* amount of output data unused at next */
+    int eof;                /* true if end of input file reached */
+    z_off64_t start;        /* where the gzip data started, for rewinding */
+    z_off64_t raw;          /* where the raw data started, for seeking */
+    int how;                /* 0: get header, 1: copy, 2: decompress */
+    int direct;             /* true if last read direct, false if gzip */
+        /* just for writing */
+    int level;              /* compression level */
+    int strategy;           /* compression strategy */
+        /* seek request */
+    z_off64_t skip;         /* amount to skip (already rewound if backwards) */
+    int seek;               /* true if seek request pending */
+        /* error information */
+    int err;                /* error code */
+    char *msg;              /* error message */
+        /* zlib inflate or deflate stream */
+    z_stream strm;          /* stream structure in-place (not a pointer) */
+} gz_state;
+typedef gz_state FAR *gz_statep;
+
+/* shared functions */
+void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
+#if defined UNDER_CE
+char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
+#endif
+
+/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
+   value -- needed when comparing unsigned to z_off64_t, which is signed
+   (possible z_off64_t types off_t, off64_t, and long are all signed) */
+#ifdef INT_MAX
+#  define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
+#else
+unsigned ZLIB_INTERNAL gz_intmax OF((void));
+#  define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
+#endif
+
+ABC_NAMESPACE_HEADER_END
diff --git a/abc-build/src/misc/zlib/gzlib.c b/abc-build/src/misc/zlib/gzlib.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/gzlib.c
@@ -0,0 +1,517 @@
+/* gzlib.c -- zlib functions common to reading and writing gzip files
+ * Copyright (C) 2004, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc/util/abc_global.h"
+
+#include "gzguts.h"
+
+ABC_NAMESPACE_IMPL_START
+
+#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
+#  define LSEEK lseek64
+#else
+#  define LSEEK lseek
+#endif
+
+/* Local functions */
+local void gz_reset OF((gz_statep));
+local gzFile gz_open OF((const char *, int, const char *));
+
+#if defined UNDER_CE
+
+/* Map the Windows error number in ERROR to a locale-dependent error message
+   string and return a pointer to it.  Typically, the values for ERROR come
+   from GetLastError.
+
+   The string pointed to shall not be modified by the application, but may be
+   overwritten by a subsequent call to gz_strwinerror
+
+   The gz_strwinerror function does not change the current setting of
+   GetLastError. */
+char ZLIB_INTERNAL *gz_strwinerror (DWORD error)
+{
+    static char buf[1024];
+
+    wchar_t *msgbuf;
+    DWORD lasterr = GetLastError();
+    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
+        | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+        NULL,
+        error,
+        0, /* Default language */
+        (LPVOID)&msgbuf,
+        0,
+        NULL);
+    if (chars != 0) {
+        /* If there is an \r\n appended, zap it.  */
+        if (chars >= 2
+            && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
+            chars -= 2;
+            msgbuf[chars] = 0;
+        }
+
+        if (chars > sizeof (buf) - 1) {
+            chars = sizeof (buf) - 1;
+            msgbuf[chars] = 0;
+        }
+
+        wcstombs(buf, msgbuf, chars + 1);
+        LocalFree(msgbuf);
+    }
+    else {
+        sprintf(buf, "unknown win32 error (%ld)", error);
+    }
+
+    SetLastError(lasterr);
+    return buf;
+}
+
+#endif /* UNDER_CE */
+
+/* Reset gzip file state */
+local void gz_reset(gz_statep state)
+{
+    if (state->mode == GZ_READ) {   /* for reading ... */
+        state->have = 0;            /* no output data available */
+        state->eof = 0;             /* not at end of file */
+        state->how = LOOK;          /* look for gzip header */
+        state->direct = 1;          /* default for empty file */
+    }
+    state->seek = 0;                /* no seek request pending */
+    gz_error(state, Z_OK, NULL);    /* clear error */
+    state->pos = 0;                 /* no uncompressed data yet */
+    state->strm.avail_in = 0;       /* no input data yet */
+}
+
+/* Open a gzip file either by name or file descriptor. */
+local gzFile gz_open(const char *path, int fd, const char *mode)
+{
+    gz_statep state;
+
+    /* allocate gzFile structure to return */
+    state = (gz_statep)malloc(sizeof(gz_state));
+    if (state == NULL)
+        return NULL;
+    state->size = 0;            /* no buffers allocated yet */
+    state->want = GZBUFSIZE;    /* requested buffer size */
+    state->msg = NULL;          /* no error message yet */
+
+    /* interpret mode */
+    state->mode = GZ_NONE;
+    state->level = Z_DEFAULT_COMPRESSION;
+    state->strategy = Z_DEFAULT_STRATEGY;
+    while (*mode) {
+        if (*mode >= '0' && *mode <= '9')
+            state->level = *mode - '0';
+        else
+            switch (*mode) {
+            case 'r':
+                state->mode = GZ_READ;
+                break;
+#ifndef NO_GZCOMPRESS
+            case 'w':
+                state->mode = GZ_WRITE;
+                break;
+            case 'a':
+                state->mode = GZ_APPEND;
+                break;
+#endif
+            case '+':       /* can't read and write at the same time */
+                free(state);
+                return NULL;
+            case 'b':       /* ignore -- will request binary anyway */
+                break;
+            case 'f':
+                state->strategy = Z_FILTERED;
+                break;
+            case 'h':
+                state->strategy = Z_HUFFMAN_ONLY;
+                break;
+            case 'R':
+                state->strategy = Z_RLE;
+                break;
+            case 'F':
+                state->strategy = Z_FIXED;
+            default:        /* could consider as an error, but just ignore */
+                ;
+            }
+        mode++;
+    }
+
+    /* must provide an "r", "w", or "a" */
+    if (state->mode == GZ_NONE) {
+        free(state);
+        return NULL;
+    }
+
+    /* save the path name for error messages */
+    state->path = (char *)malloc(strlen(path) + 1);
+    if (state->path == NULL) {
+        free(state);
+        return NULL;
+    }
+    strcpy(state->path, path);
+
+    /* open the file with the appropriate mode (or just use fd) */
+    state->fd = fd != -1 ? fd :
+        open(path,
+#ifdef O_LARGEFILE
+            O_LARGEFILE |
+#endif
+#ifdef O_BINARY
+            O_BINARY |
+#endif
+            (state->mode == GZ_READ ?
+                O_RDONLY :
+                (O_WRONLY | O_CREAT | (
+                    state->mode == GZ_WRITE ?
+                        O_TRUNC :
+                        O_APPEND))),
+            0666);
+    if (state->fd == -1) {
+        free(state->path);
+        free(state);
+        return NULL;
+    }
+    if (state->mode == GZ_APPEND)
+        state->mode = GZ_WRITE;         /* simplify later checks */
+
+    /* save the current position for rewinding (only if reading) */
+    if (state->mode == GZ_READ) {
+        state->start = LSEEK(state->fd, 0, SEEK_CUR);
+        if (state->start == -1) state->start = 0;
+    }
+
+    /* initialize stream */
+    gz_reset(state);
+
+    /* return stream */
+    return (gzFile)state;
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzopen(const char *path, const char *mode)
+{
+    return gz_open(path, -1, mode);
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzopen64(const char *path, const char *mode)
+{
+    return gz_open(path, -1, mode);
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzdopen(int fd, const char *mode)
+{
+    char *path;         /* identifier for error messages */
+    gzFile gz;
+
+    if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
+        return NULL;
+    sprintf(path, "<fd:%d>", fd);   /* for debugging */
+    gz = gz_open(path, fd, mode);
+    free(path);
+    return gz;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzbuffer(gzFile file, unsigned size)
+{
+    gz_statep state;
+
+    /* get internal structure and check integrity */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+        return -1;
+
+    /* make sure we haven't already allocated memory */
+    if (state->size != 0)
+        return -1;
+
+    /* check and set requested size */
+    if (size == 0)
+        return -1;
+    state->want = size;
+    return 0;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzrewind(gzFile file)
+{
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+
+    /* check that we're reading and that there's no error */
+    if (state->mode != GZ_READ || state->err != Z_OK)
+        return -1;
+
+    /* back up and start over */
+    if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
+        return -1;
+    gz_reset(state);
+    return 0;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence)
+{
+    unsigned n;
+    z_off64_t ret;
+    gz_statep state;
+
+    /* get internal structure and check integrity */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+        return -1;
+
+    /* check that there's no error */
+    if (state->err != Z_OK)
+        return -1;
+
+    /* can only seek from start or relative to current position */
+    if (whence != SEEK_SET && whence != SEEK_CUR)
+        return -1;
+
+    /* normalize offset to a SEEK_CUR specification */
+    if (whence == SEEK_SET)
+        offset -= state->pos;
+    else if (state->seek)
+        offset += state->skip;
+    state->seek = 0;
+
+    /* if within raw area while reading, just go there */
+    if (state->mode == GZ_READ && state->how == COPY &&
+        state->pos + offset >= state->raw) {
+        ret = LSEEK(state->fd, offset - state->have, SEEK_CUR);
+        if (ret == -1)
+            return -1;
+        state->have = 0;
+        state->eof = 0;
+        state->seek = 0;
+        gz_error(state, Z_OK, NULL);
+        state->strm.avail_in = 0;
+        state->pos += offset;
+        return state->pos;
+    }
+
+    /* calculate skip amount, rewinding if needed for back seek when reading */
+    if (offset < 0) {
+        if (state->mode != GZ_READ)         /* writing -- can't go backwards */
+            return -1;
+        offset += state->pos;
+        if (offset < 0)                     /* before start of file! */
+            return -1;
+        if (gzrewind(file) == -1)           /* rewind, then skip to offset */
+            return -1;
+    }
+
+    /* if reading, skip what's in output buffer (one less gzgetc() check) */
+    if (state->mode == GZ_READ) {
+        n = GT_OFF(state->have) || (z_off64_t)state->have > offset ?
+            (unsigned)offset : state->have;
+        state->have -= n;
+        state->next += n;
+        state->pos += n;
+        offset -= n;
+    }
+
+    /* request skip (if not zero) */
+    if (offset) {
+        state->seek = 1;
+        state->skip = offset;
+    }
+    return state->pos + offset;
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence)
+{
+    z_off64_t ret;
+
+    ret = gzseek64(file, (z_off64_t)offset, whence);
+    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gztell64(gzFile file)
+{
+    gz_statep state;
+
+    /* get internal structure and check integrity */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+        return -1;
+
+    /* return position */
+    return state->pos + (state->seek ? state->skip : 0);
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gztell(gzFile file)
+{
+    z_off64_t ret;
+
+    ret = gztell64(file);
+    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gzoffset64(gzFile file)
+{
+    z_off64_t offset;
+    gz_statep state;
+
+    /* get internal structure and check integrity */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+        return -1;
+
+    /* compute and return effective offset in file */
+    offset = LSEEK(state->fd, 0, SEEK_CUR);
+    if (offset == -1)
+        return -1;
+    if (state->mode == GZ_READ)             /* reading */
+        offset -= state->strm.avail_in;     /* don't count buffered input */
+    return offset;
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gzoffset(gzFile file)
+{
+    z_off64_t ret;
+
+    ret = gzoffset64(file);
+    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzeof(gzFile file)
+{
+    gz_statep state;
+
+    /* get internal structure and check integrity */
+    if (file == NULL)
+        return 0;
+    state = (gz_statep)file;
+    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+        return 0;
+
+    /* return end-of-file state */
+    return state->mode == GZ_READ ?
+        (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0;
+}
+
+/* -- see zlib.h -- */
+const char * ZEXPORT gzerror(gzFile file, int *errnum)
+{
+    gz_statep state;
+
+    /* get internal structure and check integrity */
+    if (file == NULL)
+        return NULL;
+    state = (gz_statep)file;
+    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+        return NULL;
+
+    /* return error information */
+    if (errnum != NULL)
+        *errnum = state->err;
+    return state->msg == NULL ? "" : state->msg;
+}
+
+/* -- see zlib.h -- */
+void ZEXPORT gzclearerr(gzFile file)
+{
+    gz_statep state;
+
+    /* get internal structure and check integrity */
+    if (file == NULL)
+        return;
+    state = (gz_statep)file;
+    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+        return;
+
+    /* clear error and end-of-file */
+    if (state->mode == GZ_READ)
+        state->eof = 0;
+    gz_error(state, Z_OK, NULL);
+}
+
+/* Create an error message in allocated memory and set state->err and
+   state->msg accordingly.  Free any previous error message already there.  Do
+   not try to free or allocate space if the error is Z_MEM_ERROR (out of
+   memory).  Simply save the error message as a static string.  If there is an
+   allocation failure constructing the error message, then convert the error to
+   out of memory. */
+void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg)
+{
+    /* free previously allocated message and clear */
+    if (state->msg != NULL) {
+        if (state->err != Z_MEM_ERROR)
+            free(state->msg);
+        state->msg = NULL;
+    }
+
+    /* set error code, and if no message, then done */
+    state->err = err;
+    if (msg == NULL)
+        return;
+
+    /* for an out of memory error, save as static string */
+    if (err == Z_MEM_ERROR) {
+        state->msg = (char *)msg;
+        return;
+    }
+
+    /* construct error message with path */
+    if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
+        state->err = Z_MEM_ERROR;
+        state->msg = (char *)"out of memory";
+        return;
+    }
+    strcpy(state->msg, state->path);
+    strcat(state->msg, ": ");
+    strcat(state->msg, msg);
+    return;
+}
+
+#ifndef INT_MAX
+/* portably return maximum value for an int (when limits.h presumed not
+   available) -- we need to do this to cover cases where 2's complement not
+   used, since C standard permits 1's complement and sign-bit representations,
+   otherwise we could just use ((unsigned)-1) >> 1 */
+unsigned ZLIB_INTERNAL gz_intmax()
+{
+    unsigned p, q;
+
+    p = 1;
+    do {
+        q = p;
+        p <<= 1;
+        p++;
+    } while (p > q);
+    return q >> 1;
+}
+#endif
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/zlib/gzread.c b/abc-build/src/misc/zlib/gzread.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/gzread.c
@@ -0,0 +1,641 @@
+/* gzread.c -- zlib functions for reading gzip files
+ * Copyright (C) 2004, 2005, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc/util/abc_global.h"
+
+#include "gzguts.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/* Local functions */
+local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
+local int gz_avail OF((gz_statep));
+local int gz_next4 OF((gz_statep, unsigned long *));
+local int gz_head OF((gz_statep));
+local int gz_decomp OF((gz_statep));
+local int gz_make OF((gz_statep));
+local int gz_skip OF((gz_statep, z_off64_t));
+
+/* Use read() to load a buffer -- return -1 on error, otherwise 0.  Read from
+   state->fd, and update state->eof, state->err, and state->msg as appropriate.
+   This function needs to loop on read(), since read() is not guaranteed to
+   read the number of bytes requested, depending on the type of descriptor. */
+local int gz_load(gz_statep state, unsigned char *buf, unsigned len, unsigned *have)
+{
+    int ret;
+
+    *have = 0;
+    do {
+        ret = read(state->fd, buf + *have, len - *have);
+        if (ret <= 0)
+            break;
+        *have += ret;
+    } while (*have < len);
+    if (ret < 0) {
+        gz_error(state, Z_ERRNO, zstrerror());
+        return -1;
+    }
+    if (ret == 0)
+        state->eof = 1;
+    return 0;
+}
+
+/* Load up input buffer and set eof flag if last data loaded -- return -1 on
+   error, 0 otherwise.  Note that the eof flag is set when the end of the input
+   file is reached, even though there may be unused data in the buffer.  Once
+   that data has been used, no more attempts will be made to read the file.
+   gz_avail() assumes that strm->avail_in == 0. */
+local int gz_avail(gz_statep state)
+{
+    z_streamp strm = &(state->strm);
+
+    if (state->err != Z_OK)
+        return -1;
+    if (state->eof == 0) {
+        if (gz_load(state, state->in, state->size,
+                (unsigned *)&(strm->avail_in)) == -1)
+            return -1;
+        strm->next_in = state->in;
+    }
+    return 0;
+}
+
+/* Get next byte from input, or -1 if end or error. */
+#define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \
+                (strm->avail_in == 0 ? -1 : \
+                 (strm->avail_in--, *(strm->next_in)++)))
+
+/* Get a four-byte little-endian integer and return 0 on success and the value
+   in *ret.  Otherwise -1 is returned and *ret is not modified. */
+local int gz_next4(gz_statep state, unsigned long *ret)
+{
+    int ch;
+    unsigned long val;
+    z_streamp strm = &(state->strm);
+
+    val = NEXT();
+    val += (unsigned)NEXT() << 8;
+    val += (unsigned long)NEXT() << 16;
+    ch = NEXT();
+    if (ch == -1)
+        return -1;
+    val += (unsigned long)ch << 24;
+    *ret = val;
+    return 0;
+}
+
+/* Look for gzip header, set up for inflate or copy.  state->have must be zero.
+   If this is the first time in, allocate required memory.  state->how will be
+   left unchanged if there is no more input data available, will be set to COPY
+   if there is no gzip header and direct copying will be performed, or it will
+   be set to GZIP for decompression, and the gzip header will be skipped so
+   that the next available input data is the raw deflate stream.  If direct
+   copying, then leftover input data from the input buffer will be copied to
+   the output buffer.  In that case, all further file reads will be directly to
+   either the output buffer or a user buffer.  If decompressing, the inflate
+   state and the check value will be initialized.  gz_head() will return 0 on
+   success or -1 on failure.  Failures may include read errors or gzip header
+   errors.  */
+local int gz_head(gz_statep state)
+{
+    z_streamp strm = &(state->strm);
+    int flags;
+    unsigned len;
+
+    /* allocate read buffers and inflate memory */
+    if (state->size == 0) {
+        /* allocate buffers */
+        state->in = (unsigned char *)malloc(state->want);
+        state->out = (unsigned char *)malloc(state->want << 1);
+        if (state->in == NULL || state->out == NULL) {
+            if (state->out != NULL)
+                free(state->out);
+            if (state->in != NULL)
+                free(state->in);
+            gz_error(state, Z_MEM_ERROR, "out of memory");
+            return -1;
+        }
+        state->size = state->want;
+
+        /* allocate inflate memory */
+        state->strm.zalloc = Z_NULL;
+        state->strm.zfree = Z_NULL;
+        state->strm.opaque = Z_NULL;
+        state->strm.avail_in = 0;
+        state->strm.next_in = Z_NULL;
+        if (inflateInit2(&(state->strm), -15) != Z_OK) {    /* raw inflate */
+            free(state->out);
+            free(state->in);
+            state->size = 0;
+            gz_error(state, Z_MEM_ERROR, "out of memory");
+            return -1;
+        }
+    }
+
+    /* get some data in the input buffer */
+    if (strm->avail_in == 0) {
+        if (gz_avail(state) == -1)
+            return -1;
+        if (strm->avail_in == 0)
+            return 0;
+    }
+
+    /* look for the gzip magic header bytes 31 and 139 */
+    if (strm->next_in[0] == 31) {
+        strm->avail_in--;
+        strm->next_in++;
+        if (strm->avail_in == 0 && gz_avail(state) == -1)
+            return -1;
+        if (strm->avail_in && strm->next_in[0] == 139) {
+            /* we have a gzip header, woo hoo! */
+            strm->avail_in--;
+            strm->next_in++;
+
+            /* skip rest of header */
+            if (NEXT() != 8) {      /* compression method */
+                gz_error(state, Z_DATA_ERROR, "unknown compression method");
+                return -1;
+            }
+            flags = NEXT();
+            if (flags & 0xe0) {     /* reserved flag bits */
+                gz_error(state, Z_DATA_ERROR, "unknown header flags set");
+                return -1;
+            }
+            NEXT();                 /* modification time */
+            NEXT();
+            NEXT();
+            NEXT();
+            NEXT();                 /* extra flags */
+            NEXT();                 /* operating system */
+            if (flags & 4) {        /* extra field */
+                len = (unsigned)NEXT();
+                len += (unsigned)NEXT() << 8;
+                while (len--)
+                    if (NEXT() < 0)
+                        break;
+            }
+            if (flags & 8)          /* file name */
+                while (NEXT() > 0)
+                    ;
+            if (flags & 16)         /* comment */
+                while (NEXT() > 0)
+                    ;
+            if (flags & 2) {        /* header crc */
+                NEXT();
+                NEXT();
+            }
+            /* an unexpected end of file is not checked for here -- it will be
+               noticed on the first request for uncompressed data */
+
+            /* set up for decompression */
+            inflateReset(strm);
+            strm->adler = crc32(0L, Z_NULL, 0);
+            state->how = GZIP;
+            state->direct = 0;
+            return 0;
+        }
+        else {
+            /* not a gzip file -- save first byte (31) and fall to raw i/o */
+            state->out[0] = 31;
+            state->have = 1;
+        }
+    }
+
+    /* doing raw i/o, save start of raw data for seeking, copy any leftover
+       input to output -- this assumes that the output buffer is larger than
+       the input buffer, which also assures space for gzungetc() */
+    state->raw = state->pos;
+    state->next = state->out;
+    if (strm->avail_in) {
+        memcpy(state->next + state->have, strm->next_in, strm->avail_in);
+        state->have += strm->avail_in;
+        strm->avail_in = 0;
+    }
+    state->how = COPY;
+    state->direct = 1;
+    return 0;
+}
+
+/* Decompress from input to the provided next_out and avail_out in the state.
+   If the end of the compressed data is reached, then verify the gzip trailer
+   check value and length (modulo 2^32).  state->have and state->next are set
+   to point to the just decompressed data, and the crc is updated.  If the
+   trailer is verified, state->how is reset to LOOK to look for the next gzip
+   stream or raw data, once state->have is depleted.  Returns 0 on success, -1
+   on failure.  Failures may include invalid compressed data or a failed gzip
+   trailer verification. */
+local int gz_decomp(gz_statep state)
+{
+    int ret;
+    unsigned had;
+    unsigned long crc, len;
+    z_streamp strm = &(state->strm);
+
+    /* fill output buffer up to end of deflate stream */
+    had = strm->avail_out;
+    do {
+        /* get more input for inflate() */
+        if (strm->avail_in == 0 && gz_avail(state) == -1)
+            return -1;
+        if (strm->avail_in == 0) {
+            gz_error(state, Z_DATA_ERROR, "unexpected end of file");
+            return -1;
+        }
+
+        /* decompress and handle errors */
+        ret = inflate(strm, Z_NO_FLUSH);
+        if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
+            gz_error(state, Z_STREAM_ERROR,
+                      "internal error: inflate stream corrupt");
+            return -1;
+        }
+        if (ret == Z_MEM_ERROR) {
+            gz_error(state, Z_MEM_ERROR, "out of memory");
+            return -1;
+        }
+        if (ret == Z_DATA_ERROR) {              /* deflate stream invalid */
+            gz_error(state, Z_DATA_ERROR,
+                      strm->msg == NULL ? "compressed data error" : strm->msg);
+            return -1;
+        }
+    } while (strm->avail_out && ret != Z_STREAM_END);
+
+    /* update available output and crc check value */
+    state->have = had - strm->avail_out;
+    state->next = strm->next_out - state->have;
+    strm->adler = crc32(strm->adler, state->next, state->have);
+
+    /* check gzip trailer if at end of deflate stream */
+    if (ret == Z_STREAM_END) {
+        if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) {
+            gz_error(state, Z_DATA_ERROR, "unexpected end of file");
+            return -1;
+        }
+        if (crc != strm->adler) {
+            gz_error(state, Z_DATA_ERROR, "incorrect data check");
+            return -1;
+        }
+        if (len != (strm->total_out & 0xffffffffL)) {
+            gz_error(state, Z_DATA_ERROR, "incorrect length check");
+            return -1;
+        }
+        state->how = LOOK;      /* ready for next stream, once have is 0 (leave
+                                   state->direct unchanged to remember how) */
+    }
+
+    /* good decompression */
+    return 0;
+}
+
+/* Make data and put in the output buffer.  Assumes that state->have == 0.
+   Data is either copied from the input file or decompressed from the input
+   file depending on state->how.  If state->how is LOOK, then a gzip header is
+   looked for (and skipped if found) to determine wither to copy or decompress.
+   Returns -1 on error, otherwise 0.  gz_make() will leave state->have as COPY
+   or GZIP unless the end of the input file has been reached and all data has
+   been processed.  */
+local int gz_make(gz_statep state)
+{
+    z_streamp strm = &(state->strm);
+
+    if (state->how == LOOK) {           /* look for gzip header */
+        if (gz_head(state) == -1)
+            return -1;
+        if (state->have)                /* got some data from gz_head() */
+            return 0;
+    }
+    if (state->how == COPY) {           /* straight copy */
+        if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1)
+            return -1;
+        state->next = state->out;
+    }
+    else if (state->how == GZIP) {      /* decompress */
+        strm->avail_out = state->size << 1;
+        strm->next_out = state->out;
+        if (gz_decomp(state) == -1)
+            return -1;
+    }
+    return 0;
+}
+
+/* Skip len uncompressed bytes of output.  Return -1 on error, 0 on success. */
+local int gz_skip(gz_statep state, z_off64_t len)
+{
+    unsigned n;
+
+    /* skip over len bytes or reach end-of-file, whichever comes first */
+    while (len)
+        /* skip over whatever is in output buffer */
+        if (state->have) {
+            n = GT_OFF(state->have) || (z_off64_t)state->have > len ?
+                (unsigned)len : state->have;
+            state->have -= n;
+            state->next += n;
+            state->pos += n;
+            len -= n;
+        }
+
+        /* output buffer empty -- return if we're at the end of the input */
+        else if (state->eof && state->strm.avail_in == 0)
+            break;
+
+        /* need more data to skip -- load up output buffer */
+        else {
+            /* get more output, looking for header if required */
+            if (gz_make(state) == -1)
+                return -1;
+        }
+    return 0;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzread(gzFile file, voidp buf, unsigned len)
+{
+    unsigned got, n;
+    gz_statep state;
+    z_streamp strm;
+
+    /* get internal structure */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+    strm = &(state->strm);
+
+    /* check that we're reading and that there's no error */
+    if (state->mode != GZ_READ || state->err != Z_OK)
+        return -1;
+
+    /* since an int is returned, make sure len fits in one, otherwise return
+       with an error (this avoids the flaw in the interface) */
+    if ((int)len < 0) {
+        gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
+        return -1;
+    }
+
+    /* if len is zero, avoid unnecessary operations */
+    if (len == 0)
+        return 0;
+
+    /* process a skip request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_skip(state, state->skip) == -1)
+            return -1;
+    }
+
+    /* get len bytes to buf, or less than len if at the end */
+    got = 0;
+    do {
+        /* first just try copying data from the output buffer */
+        if (state->have) {
+            n = state->have > len ? len : state->have;
+            memcpy(buf, state->next, n);
+            state->next += n;
+            state->have -= n;
+        }
+
+        /* output buffer empty -- return if we're at the end of the input */
+        else if (state->eof && strm->avail_in == 0)
+            break;
+
+        /* need output data -- for small len or new stream load up our output
+           buffer */
+        else if (state->how == LOOK || len < (state->size << 1)) {
+            /* get more output, looking for header if required */
+            if (gz_make(state) == -1)
+                return -1;
+            continue;       /* no progress yet -- go back to memcpy() above */
+            /* the copy above assures that we will leave with space in the
+               output buffer, allowing at least one gzungetc() to succeed */
+        }
+
+        /* large len -- read directly into user buffer */
+        else if (state->how == COPY) {      /* read directly */
+            if (gz_load(state, (unsigned char *)buf, len, &n) == -1)
+                return -1;
+        }
+
+        /* large len -- decompress directly into user buffer */
+        else {  /* state->how == GZIP */
+            strm->avail_out = len;
+            strm->next_out = (unsigned char *)buf;
+            if (gz_decomp(state) == -1)
+                return -1;
+            n = state->have;
+            state->have = 0;
+        }
+
+        /* update progress */
+        len -= n;
+        buf = (char *)buf + n;
+        got += n;
+        state->pos += n;
+    } while (len);
+
+    /* return number of bytes read into user buffer (will fit in int) */
+    return (int)got;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzgetc(gzFile file)
+{
+    int ret;
+    unsigned char buf[1];
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+
+    /* check that we're reading and that there's no error */
+    if (state->mode != GZ_READ || state->err != Z_OK)
+        return -1;
+
+    /* try output buffer (no need to check for skip request) */
+    if (state->have) {
+        state->have--;
+        state->pos++;
+        return *(state->next)++;
+    }
+
+    /* nothing there -- try gzread() */
+    ret = gzread(file, buf, 1);
+    return ret < 1 ? -1 : buf[0];
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzungetc(int c, gzFile file)
+{
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+
+    /* check that we're reading and that there's no error */
+    if (state->mode != GZ_READ || state->err != Z_OK)
+        return -1;
+
+    /* process a skip request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_skip(state, state->skip) == -1)
+            return -1;
+    }
+
+    /* can't push EOF */
+    if (c < 0)
+        return -1;
+
+    /* if output buffer empty, put byte at end (allows more pushing) */
+    if (state->have == 0) {
+        state->have = 1;
+        state->next = state->out + (state->size << 1) - 1;
+        state->next[0] = c;
+        state->pos--;
+        return c;
+    }
+
+    /* if no room, give up (must have already done a gzungetc()) */
+    if (state->have == (state->size << 1)) {
+        gz_error(state, Z_BUF_ERROR, "out of room to push characters");
+        return -1;
+    }
+
+    /* slide output data if needed and insert byte before existing data */
+    if (state->next == state->out) {
+        unsigned char *src = state->out + state->have;
+        unsigned char *dest = state->out + (state->size << 1);
+        while (src > state->out)
+            *--dest = *--src;
+        state->next = dest;
+    }
+    state->have++;
+    state->next--;
+    state->next[0] = c;
+    state->pos--;
+    return c;
+}
+
+/* -- see zlib.h -- */
+char * ZEXPORT gzgets(gzFile file, char *buf, int len)
+{
+    unsigned left, n;
+    char *str;
+    unsigned char *eol;
+    gz_statep state;
+
+    /* check parameters and get internal structure */
+    if (file == NULL || buf == NULL || len < 1)
+        return NULL;
+    state = (gz_statep)file;
+
+    /* check that we're reading and that there's no error */
+    if (state->mode != GZ_READ || state->err != Z_OK)
+        return NULL;
+
+    /* process a skip request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_skip(state, state->skip) == -1)
+            return NULL;
+    }
+
+    /* copy output bytes up to new line or len - 1, whichever comes first --
+       append a terminating zero to the string (we don't check for a zero in
+       the contents, let the user worry about that) */
+    str = buf;
+    left = (unsigned)len - 1;
+    if (left) do {
+        /* assure that something is in the output buffer */
+        if (state->have == 0) {
+            if (gz_make(state) == -1)
+                return NULL;            /* error */
+            if (state->have == 0) {     /* end of file */
+                if (buf == str)         /* got bupkus */
+                    return NULL;
+                break;                  /* got something -- return it */
+            }
+        }
+
+        /* look for end-of-line in current output buffer */
+        n = state->have > left ? left : state->have;
+        eol = (unsigned char *)memchr(state->next, '\n', n);
+        if (eol != NULL)
+            n = (unsigned)(eol - state->next) + 1;
+
+        /* copy through end-of-line, or remainder if not found */
+        memcpy(buf, state->next, n);
+        state->have -= n;
+        state->next += n;
+        state->pos += n;
+        left -= n;
+        buf += n;
+    } while (left && eol == NULL);
+
+    /* found end-of-line or out of space -- terminate string and return it */
+    buf[0] = 0;
+    return str;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzdirect(gzFile file)
+{
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return 0;
+    state = (gz_statep)file;
+
+    /* check that we're reading */
+    if (state->mode != GZ_READ)
+        return 0;
+
+    /* if the state is not known, but we can find out, then do so (this is
+       mainly for right after a gzopen() or gzdopen()) */
+    if (state->how == LOOK && state->have == 0)
+        (void)gz_head(state);
+
+    /* return 1 if reading direct, 0 if decompressing a gzip stream */
+    return state->direct;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzclose_r(gzFile file)
+{
+    int ret;
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return Z_STREAM_ERROR;
+    state = (gz_statep)file;
+
+    /* check that we're reading */
+    if (state->mode != GZ_READ)
+        return Z_STREAM_ERROR;
+
+    /* free memory and close file */
+    if (state->size) {
+        inflateEnd(&(state->strm));
+        free(state->out);
+        free(state->in);
+    }
+    gz_error(state, Z_OK, NULL);
+    free(state->path);
+    ret = close(state->fd);
+    free(state);
+    return ret ? Z_ERRNO : Z_OK;
+}
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/zlib/gzwrite.c b/abc-build/src/misc/zlib/gzwrite.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/gzwrite.c
@@ -0,0 +1,520 @@
+/* gzwrite.c -- zlib functions for writing gzip files
+ * Copyright (C) 2004, 2005, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc/util/abc_global.h"
+
+#include "gzguts.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/* Local functions */
+local int gz_init OF((gz_statep));
+local int gz_comp OF((gz_statep, int));
+local int gz_zero OF((gz_statep, z_off64_t));
+
+/* Initialize state for writing a gzip file.  Mark initialization by setting
+   state->size to non-zero.  Return -1 on failure or 0 on success. */
+local int gz_init(gz_statep state)
+{
+    int ret;
+    z_streamp strm = &(state->strm);
+
+    /* allocate input and output buffers */
+    state->in = (unsigned char *)malloc(state->want);
+    state->out = (unsigned char *)malloc(state->want);
+    if (state->in == NULL || state->out == NULL) {
+        if (state->out != NULL)
+            free(state->out);
+        if (state->in != NULL)
+            free(state->in);
+        gz_error(state, Z_MEM_ERROR, "out of memory");
+        return -1;
+    }
+
+    /* allocate deflate memory, set up for gzip compression */
+    strm->zalloc = Z_NULL;
+    strm->zfree = Z_NULL;
+    strm->opaque = Z_NULL;
+    ret = deflateInit2(strm, state->level, Z_DEFLATED,
+                       15 + 16, 8, state->strategy);
+    if (ret != Z_OK) {
+        free(state->in);
+        gz_error(state, Z_MEM_ERROR, "out of memory");
+        return -1;
+    }
+
+    /* mark state as initialized */
+    state->size = state->want;
+
+    /* initialize write buffer */
+    strm->avail_out = state->size;
+    strm->next_out = state->out;
+    state->next = strm->next_out;
+    return 0;
+}
+
+/* Compress whatever is at avail_in and next_in and write to the output file.
+   Return -1 if there is an error writing to the output file, otherwise 0.
+   flush is assumed to be a valid deflate() flush value.  If flush is Z_FINISH,
+   then the deflate() state is reset to start a new gzip stream. */
+local int gz_comp(gz_statep state, int flush)
+{
+    int ret, got;
+    unsigned have;
+    z_streamp strm = &(state->strm);
+
+    /* allocate memory if this is the first time through */
+    if (state->size == 0 && gz_init(state) == -1)
+        return -1;
+
+    /* run deflate() on provided input until it produces no more output */
+    ret = Z_OK;
+    do {
+        /* write out current buffer contents if full, or if flushing, but if
+           doing Z_FINISH then don't write until we get to Z_STREAM_END */
+        if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
+            (flush != Z_FINISH || ret == Z_STREAM_END))) {
+            have = (unsigned)(strm->next_out - state->next);
+            if (have && ((got = write(state->fd, state->next, have)) < 0 ||
+                         (unsigned)got != have)) {
+                gz_error(state, Z_ERRNO, zstrerror());
+                return -1;
+            }
+            if (strm->avail_out == 0) {
+                strm->avail_out = state->size;
+                strm->next_out = state->out;
+            }
+            state->next = strm->next_out;
+        }
+
+        /* compress */
+        have = strm->avail_out;
+        ret = deflate(strm, flush);
+        if (ret == Z_STREAM_ERROR) {
+            gz_error(state, Z_STREAM_ERROR,
+                      "internal error: deflate stream corrupt");
+            return -1;
+        }
+        have -= strm->avail_out;
+    } while (have);
+
+    /* if that completed a deflate stream, allow another to start */
+    if (flush == Z_FINISH)
+        deflateReset(strm);
+
+    /* all done, no errors */
+    return 0;
+}
+
+/* Compress len zeros to output.  Return -1 on error, 0 on success. */
+local int gz_zero(gz_statep state, z_off64_t len)
+{
+    int first;
+    unsigned n;
+    z_streamp strm = &(state->strm);
+
+    /* consume whatever's left in the input buffer */
+    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
+        return -1;
+
+    /* compress len zeros (len guaranteed > 0) */
+    first = 1;
+    while (len) {
+        n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
+            (unsigned)len : state->size;
+        if (first) {
+            memset(state->in, 0, n);
+            first = 0;
+        }
+        strm->avail_in = n;
+        strm->next_in = state->in;
+        state->pos += n;
+        if (gz_comp(state, Z_NO_FLUSH) == -1)
+            return -1;
+        len -= n;
+    }
+    return 0;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len)
+{
+    unsigned put = len;
+    unsigned n;
+    gz_statep state;
+    z_streamp strm;
+
+    /* get internal structure */
+    if (file == NULL)
+        return 0;
+    state = (gz_statep)file;
+    strm = &(state->strm);
+
+    /* check that we're writing and that there's no error */
+    if (state->mode != GZ_WRITE || state->err != Z_OK)
+        return 0;
+
+    /* since an int is returned, make sure len fits in one, otherwise return
+       with an error (this avoids the flaw in the interface) */
+    if ((int)len < 0) {
+        gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
+        return 0;
+    }
+
+    /* if len is zero, avoid unnecessary operations */
+    if (len == 0)
+        return 0;
+
+    /* allocate memory if this is the first time through */
+    if (state->size == 0 && gz_init(state) == -1)
+        return 0;
+
+    /* check for seek request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_zero(state, state->skip) == -1)
+            return 0;
+    }
+
+    /* for small len, copy to input buffer, otherwise compress directly */
+    if (len < state->size) {
+        /* copy to input buffer, compress when full */
+        do {
+            if (strm->avail_in == 0)
+                strm->next_in = state->in;
+            n = state->size - strm->avail_in;
+            if (n > len)
+                n = len;
+            memcpy(strm->next_in + strm->avail_in, buf, n);
+            strm->avail_in += n;
+            state->pos += n;
+            buf = (char *)buf + n;
+            len -= n;
+            if (len && gz_comp(state, Z_NO_FLUSH) == -1)
+                return 0;
+        } while (len);
+    }
+    else {
+        /* consume whatever's left in the input buffer */
+        if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
+            return 0;
+
+        /* directly compress user buffer to file */
+        strm->avail_in = len;
+        strm->next_in = (unsigned char *)(voidp)buf;
+        state->pos += len;
+        if (gz_comp(state, Z_NO_FLUSH) == -1)
+            return 0;
+    }
+
+    /* input was all buffered or compressed (put will fit in int) */
+    return (int)put;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzputc(gzFile file, int c)
+{
+    unsigned char buf[1];
+    gz_statep state;
+    z_streamp strm;
+
+    /* get internal structure */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+    strm = &(state->strm);
+
+    /* check that we're writing and that there's no error */
+    if (state->mode != GZ_WRITE || state->err != Z_OK)
+        return -1;
+
+    /* check for seek request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_zero(state, state->skip) == -1)
+            return -1;
+    }
+
+    /* try writing to input buffer for speed (state->size == 0 if buffer not
+       initialized) */
+    if (strm->avail_in < state->size) {
+        if (strm->avail_in == 0)
+            strm->next_in = state->in;
+        strm->next_in[strm->avail_in++] = c;
+        state->pos++;
+        return c;
+    }
+
+    /* no room in buffer or not initialized, use gz_write() */
+    buf[0] = c;
+    if (gzwrite(file, buf, 1) != 1)
+        return -1;
+    return c;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzputs(gzFile file, const char *str)
+{
+    int ret;
+    unsigned len;
+
+    /* write string */
+    len = (unsigned)strlen(str);
+    ret = gzwrite(file, str, len);
+    return ret == 0 && len != 0 ? -1 : ret;
+}
+
+#ifdef STDC
+#include <stdarg.h>
+
+/* -- see zlib.h -- */
+int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
+{
+    int size, len;
+    gz_statep state;
+    z_streamp strm;
+    va_list va;
+
+    /* get internal structure */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+    strm = &(state->strm);
+
+    /* check that we're writing and that there's no error */
+    if (state->mode != GZ_WRITE || state->err != Z_OK)
+        return 0;
+
+    /* make sure we have some buffer space */
+    if (state->size == 0 && gz_init(state) == -1)
+        return 0;
+
+    /* check for seek request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_zero(state, state->skip) == -1)
+            return 0;
+    }
+
+    /* consume whatever's left in the input buffer */
+    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
+        return 0;
+
+    /* do the printf() into the input buffer, put length in len */
+    size = (int)(state->size);
+    state->in[size - 1] = 0;
+    va_start(va, format);
+#ifdef NO_vsnprintf
+#  ifdef HAS_vsprintf_void
+    (void)vsprintf(state->in, format, va);
+    va_end(va);
+    for (len = 0; len < size; len++)
+        if (state->in[len] == 0) break;
+#  else
+    len = vsprintf(state->in, format, va);
+    va_end(va);
+#  endif
+#else
+#  ifdef HAS_vsnprintf_void
+    (void)vsnprintf(state->in, size, format, va);
+    va_end(va);
+    len = strlen(state->in);
+#  else
+    len = vsnprintf((char *)(state->in), size, format, va);
+    va_end(va);
+#  endif
+#endif
+
+    /* check that printf() results fit in buffer */
+    if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
+        return 0;
+
+    /* update buffer and position, defer compression until needed */
+    strm->avail_in = (unsigned)len;
+    strm->next_in = state->in;
+    state->pos += len;
+    return len;
+}
+
+#else /* !STDC */
+
+/* -- see zlib.h -- */
+int ZEXPORTVA gzprintf (gzFile file, const char *format, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10,
+                       int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20)
+{
+    int size, len;
+    gz_statep state;
+    z_streamp strm;
+
+    /* get internal structure */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+    strm = &(state->strm);
+
+    /* check that we're writing and that there's no error */
+    if (state->mode != GZ_WRITE || state->err != Z_OK)
+        return 0;
+
+    /* make sure we have some buffer space */
+    if (state->size == 0 && gz_init(state) == -1)
+        return 0;
+
+    /* check for seek request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_zero(state, state->skip) == -1)
+            return 0;
+    }
+
+    /* consume whatever's left in the input buffer */
+    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
+        return 0;
+
+    /* do the printf() into the input buffer, put length in len */
+    size = (int)(state->size);
+    state->in[size - 1] = 0;
+#ifdef NO_snprintf
+#  ifdef HAS_sprintf_void
+    sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
+            a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+    for (len = 0; len < size; len++)
+        if (state->in[len] == 0) break;
+#  else
+    len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
+                a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+#  endif
+#else
+#  ifdef HAS_snprintf_void
+    snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
+             a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+    len = strlen(state->in);
+#  else
+    len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
+                 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+#  endif
+#endif
+
+    /* check that printf() results fit in buffer */
+    if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
+        return 0;
+
+    /* update buffer and position, defer compression until needed */
+    strm->avail_in = (unsigned)len;
+    strm->next_in = state->in;
+    state->pos += len;
+    return len;
+}
+
+#endif
+
+/* -- see zlib.h -- */
+int ZEXPORT gzflush(gzFile file, int flush)
+{
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return -1;
+    state = (gz_statep)file;
+
+    /* check that we're writing and that there's no error */
+    if (state->mode != GZ_WRITE || state->err != Z_OK)
+        return Z_STREAM_ERROR;
+
+    /* check flush parameter */
+    if (flush < 0 || flush > Z_FINISH)
+        return Z_STREAM_ERROR;
+
+    /* check for seek request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_zero(state, state->skip) == -1)
+            return -1;
+    }
+
+    /* compress remaining data with requested flush */
+    gz_comp(state, flush);
+    return state->err;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzsetparams(gzFile file, int level, int strategy)
+{
+    gz_statep state;
+    z_streamp strm;
+
+    /* get internal structure */
+    if (file == NULL)
+        return Z_STREAM_ERROR;
+    state = (gz_statep)file;
+    strm = &(state->strm);
+
+    /* check that we're writing and that there's no error */
+    if (state->mode != GZ_WRITE || state->err != Z_OK)
+        return Z_STREAM_ERROR;
+
+    /* if no change is requested, then do nothing */
+    if (level == state->level && strategy == state->strategy)
+        return Z_OK;
+
+    /* check for seek request */
+    if (state->seek) {
+        state->seek = 0;
+        if (gz_zero(state, state->skip) == -1)
+            return -1;
+    }
+
+    /* change compression parameters for subsequent input */
+    if (state->size) {
+        /* flush previous input with previous parameters before changing */
+        if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
+            return state->err;
+        deflateParams(strm, level, strategy);
+    }
+    state->level = level;
+    state->strategy = strategy;
+    return Z_OK;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzclose_w(gzFile file)
+{
+    int ret = 0;
+    gz_statep state;
+
+    /* get internal structure */
+    if (file == NULL)
+        return Z_STREAM_ERROR;
+    state = (gz_statep)file;
+
+    /* check that we're writing */
+    if (state->mode != GZ_WRITE)
+        return Z_STREAM_ERROR;
+
+    /* check for seek request */
+    if (state->seek) {
+        state->seek = 0;
+        ret += gz_zero(state, state->skip);
+    }
+
+    /* flush, free memory, and close file */
+    ret += gz_comp(state, Z_FINISH);
+    (void)deflateEnd(&(state->strm));
+    free(state->out);
+    free(state->in);
+    gz_error(state, Z_OK, NULL);
+    free(state->path);
+    ret += close(state->fd);
+    free(state);
+    return ret ? Z_ERRNO : Z_OK;
+}
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/zlib/infback.c b/abc-build/src/misc/zlib/infback.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/infback.c
@@ -0,0 +1,631 @@
+/* infback.c -- inflate using a call-back interface
+ * Copyright (C) 1995-2009 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+   This code is largely copied from inflate.c.  Normally either infback.o or
+   inflate.o would be linked into an application--not both.  The interface
+   with inffast.c is retained so that optimized assembler-coded versions of
+   inflate_fast() can be used with either inflate.c or infback.c.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc/util/abc_global.h"
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+
+/*
+   strm provides memory allocation functions in zalloc and zfree, or
+   Z_NULL to use the library memory allocation functions.
+
+   windowBits is in the range 8..15, and window is a user-supplied
+   window and output buffer that is 2**windowBits bytes.
+ */
+int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size)
+{
+    struct inflate_state FAR *state;
+
+    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+        stream_size != (int)(sizeof(z_stream)))
+        return Z_VERSION_ERROR;
+    if (strm == Z_NULL || window == Z_NULL ||
+        windowBits < 8 || windowBits > 15)
+        return Z_STREAM_ERROR;
+    strm->msg = Z_NULL;                 /* in case we return an error */
+    if (strm->zalloc == (alloc_func)0) {
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+    }
+    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+    state = (struct inflate_state FAR *)ZALLOC(strm, 1,
+                                               sizeof(struct inflate_state));
+    if (state == Z_NULL) return Z_MEM_ERROR;
+    Tracev((stderr, "inflate: allocated\n"));
+    strm->state = (struct internal_state FAR *)state;
+    state->dmax = 32768U;
+    state->wbits = windowBits;
+    state->wsize = 1U << windowBits;
+    state->window = window;
+    state->wnext = 0;
+    state->whave = 0;
+    return Z_OK;
+}
+
+/*
+   Return state with length and distance decoding tables and index sizes set to
+   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
+   If BUILDFIXED is defined, then instead this routine builds the tables the
+   first time it's called, and returns those tables the first time and
+   thereafter.  This reduces the size of the code by about 2K bytes, in
+   exchange for a little execution time.  However, BUILDFIXED should not be
+   used for threaded applications, since the rewriting of the tables and virgin
+   may not be thread-safe.
+ */
+local void fixedtables(struct inflate_state FAR *state)
+{
+#ifdef BUILDFIXED
+    static int virgin = 1;
+    static code *lenfix, *distfix;
+    static code fixed[544];
+
+    /* build fixed huffman tables if first call (may not be thread safe) */
+    if (virgin) {
+        unsigned sym, bits;
+        static code *next;
+
+        /* literal/length table */
+        sym = 0;
+        while (sym < 144) state->lens[sym++] = 8;
+        while (sym < 256) state->lens[sym++] = 9;
+        while (sym < 280) state->lens[sym++] = 7;
+        while (sym < 288) state->lens[sym++] = 8;
+        next = fixed;
+        lenfix = next;
+        bits = 9;
+        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+        /* distance table */
+        sym = 0;
+        while (sym < 32) state->lens[sym++] = 5;
+        distfix = next;
+        bits = 5;
+        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+        /* do this just once */
+        virgin = 0;
+    }
+#else /* !BUILDFIXED */
+#   include "inffixed.h"
+#endif /* BUILDFIXED */
+    state->lencode = lenfix;
+    state->lenbits = 9;
+    state->distcode = distfix;
+    state->distbits = 5;
+}
+
+/* Macros for inflateBack(): */
+
+/* Load returned state from inflate_fast() */
+#define LOAD() \
+    do { \
+        put = strm->next_out; \
+        left = strm->avail_out; \
+        next = strm->next_in; \
+        have = strm->avail_in; \
+        hold = state->hold; \
+        bits = state->bits; \
+    } while (0)
+
+/* Set state from registers for inflate_fast() */
+#define RESTORE() \
+    do { \
+        strm->next_out = put; \
+        strm->avail_out = left; \
+        strm->next_in = next; \
+        strm->avail_in = have; \
+        state->hold = hold; \
+        state->bits = bits; \
+    } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+    do { \
+        hold = 0; \
+        bits = 0; \
+    } while (0)
+
+/* Assure that some input is available.  If input is requested, but denied,
+   then return a Z_BUF_ERROR from inflateBack(). */
+#define PULL() \
+    do { \
+        if (have == 0) { \
+            have = in(in_desc, &next); \
+            if (have == 0) { \
+                next = Z_NULL; \
+                ret = Z_BUF_ERROR; \
+                goto inf_leave; \
+            } \
+        } \
+    } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflateBack()
+   with an error if there is no input available. */
+#define PULLBYTE() \
+    do { \
+        PULL(); \
+        have--; \
+        hold += (unsigned long)(*next++) << bits; \
+        bits += 8; \
+    } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator.  If there is
+   not enough available input to do that, then return from inflateBack() with
+   an error. */
+#define NEEDBITS(n) \
+    do { \
+        while (bits < (unsigned)(n)) \
+            PULLBYTE(); \
+    } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+    ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+    do { \
+        hold >>= (n); \
+        bits -= (unsigned)(n); \
+    } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+    do { \
+        hold >>= bits & 7; \
+        bits -= bits & 7; \
+    } while (0)
+
+/* Assure that some output space is available, by writing out the window
+   if it's full.  If the write fails, return from inflateBack() with a
+   Z_BUF_ERROR. */
+#define ROOM() \
+    do { \
+        if (left == 0) { \
+            put = state->window; \
+            left = state->wsize; \
+            state->whave = left; \
+            if (out(out_desc, put, left)) { \
+                ret = Z_BUF_ERROR; \
+                goto inf_leave; \
+            } \
+        } \
+    } while (0)
+
+/*
+   strm provides the memory allocation functions and window buffer on input,
+   and provides information on the unused input on return.  For Z_DATA_ERROR
+   returns, strm will also provide an error message.
+
+   in() and out() are the call-back input and output functions.  When
+   inflateBack() needs more input, it calls in().  When inflateBack() has
+   filled the window with output, or when it completes with data in the
+   window, it calls out() to write out the data.  The application must not
+   change the provided input until in() is called again or inflateBack()
+   returns.  The application must not change the window/output buffer until
+   inflateBack() returns.
+
+   in() and out() are called with a descriptor parameter provided in the
+   inflateBack() call.  This parameter can be a structure that provides the
+   information required to do the read or write, as well as accumulated
+   information on the input and output such as totals and check values.
+
+   in() should return zero on failure.  out() should return non-zero on
+   failure.  If either in() or out() fails, than inflateBack() returns a
+   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
+   was in() or out() that caused in the error.  Otherwise,  inflateBack()
+   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
+   error, or Z_MEM_ERROR if it could not allocate memory for the state.
+   inflateBack() can also return Z_STREAM_ERROR if the input parameters
+   are not correct, i.e. strm is Z_NULL or the state was not initialized.
+ */
+int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc)
+{
+    struct inflate_state FAR *state;
+    unsigned char FAR *next;    /* next input */
+    unsigned char FAR *put;     /* next output */
+    unsigned have, left;        /* available input and output */
+    unsigned long hold;         /* bit buffer */
+    unsigned bits;              /* bits in bit buffer */
+    unsigned copy;              /* number of stored or match bytes to copy */
+    unsigned char FAR *from;    /* where to copy match bytes from */
+    code here;                  /* current decoding table entry */
+    code last;                  /* parent table entry */
+    unsigned len;               /* length to copy for repeats, bits to drop */
+    int ret;                    /* return code */
+    static const unsigned short order[19] = /* permutation of code lengths */
+        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+    /* Check that the strm exists and that the state was initialized */
+    if (strm == Z_NULL || strm->state == Z_NULL)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* Reset the state */
+    strm->msg = Z_NULL;
+    state->mode = TYPE;
+    state->last = 0;
+    state->whave = 0;
+    next = strm->next_in;
+    have = next != Z_NULL ? strm->avail_in : 0;
+    hold = 0;
+    bits = 0;
+    put = state->window;
+    left = state->wsize;
+
+    /* Inflate until end of block marked as last */
+    for (;;)
+        switch (state->mode) {
+        case TYPE:
+            /* determine and dispatch block type */
+            if (state->last) {
+                BYTEBITS();
+                state->mode = DONE;
+                break;
+            }
+            NEEDBITS(3);
+            state->last = BITS(1);
+            DROPBITS(1);
+            switch (BITS(2)) {
+            case 0:                             /* stored block */
+                Tracev((stderr, "inflate:     stored block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = STORED;
+                break;
+            case 1:                             /* fixed block */
+                fixedtables(state);
+                Tracev((stderr, "inflate:     fixed codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = LEN;              /* decode codes */
+                break;
+            case 2:                             /* dynamic block */
+                Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = TABLE;
+                break;
+            case 3:
+                strm->msg = (char *)"invalid block type";
+                state->mode = BAD;
+            }
+            DROPBITS(2);
+            break;
+
+        case STORED:
+            /* get and verify stored block length */
+            BYTEBITS();                         /* go to byte boundary */
+            NEEDBITS(32);
+            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+                strm->msg = (char *)"invalid stored block lengths";
+                state->mode = BAD;
+                break;
+            }
+            state->length = (unsigned)hold & 0xffff;
+            Tracev((stderr, "inflate:       stored length %u\n",
+                    state->length));
+            INITBITS();
+
+            /* copy stored block from input to output */
+            while (state->length != 0) {
+                copy = state->length;
+                PULL();
+                ROOM();
+                if (copy > have) copy = have;
+                if (copy > left) copy = left;
+                zmemcpy(put, next, copy);
+                have -= copy;
+                next += copy;
+                left -= copy;
+                put += copy;
+                state->length -= copy;
+            }
+            Tracev((stderr, "inflate:       stored end\n"));
+            state->mode = TYPE;
+            break;
+
+        case TABLE:
+            /* get dynamic table entries descriptor */
+            NEEDBITS(14);
+            state->nlen = BITS(5) + 257;
+            DROPBITS(5);
+            state->ndist = BITS(5) + 1;
+            DROPBITS(5);
+            state->ncode = BITS(4) + 4;
+            DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+            if (state->nlen > 286 || state->ndist > 30) {
+                strm->msg = (char *)"too many length or distance symbols";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracev((stderr, "inflate:       table sizes ok\n"));
+
+            /* get code length code lengths (not a typo) */
+            state->have = 0;
+            while (state->have < state->ncode) {
+                NEEDBITS(3);
+                state->lens[order[state->have++]] = (unsigned short)BITS(3);
+                DROPBITS(3);
+            }
+            while (state->have < 19)
+                state->lens[order[state->have++]] = 0;
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 7;
+            ret = inflate_table(CODES, state->lens, 19, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid code lengths set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       code lengths ok\n"));
+
+            /* get length and distance code code lengths */
+            state->have = 0;
+            while (state->have < state->nlen + state->ndist) {
+                for (;;) {
+                    here = state->lencode[BITS(state->lenbits)];
+                    if ((unsigned)(here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                if (here.val < 16) {
+                    NEEDBITS(here.bits);
+                    DROPBITS(here.bits);
+                    state->lens[state->have++] = here.val;
+                }
+                else {
+                    if (here.val == 16) {
+                        NEEDBITS(here.bits + 2);
+                        DROPBITS(here.bits);
+                        if (state->have == 0) {
+                            strm->msg = (char *)"invalid bit length repeat";
+                            state->mode = BAD;
+                            break;
+                        }
+                        len = (unsigned)(state->lens[state->have - 1]);
+                        copy = 3 + BITS(2);
+                        DROPBITS(2);
+                    }
+                    else if (here.val == 17) {
+                        NEEDBITS(here.bits + 3);
+                        DROPBITS(here.bits);
+                        len = 0;
+                        copy = 3 + BITS(3);
+                        DROPBITS(3);
+                    }
+                    else {
+                        NEEDBITS(here.bits + 7);
+                        DROPBITS(here.bits);
+                        len = 0;
+                        copy = 11 + BITS(7);
+                        DROPBITS(7);
+                    }
+                    if (state->have + copy > state->nlen + state->ndist) {
+                        strm->msg = (char *)"invalid bit length repeat";
+                        state->mode = BAD;
+                        break;
+                    }
+                    while (copy--)
+                        state->lens[state->have++] = (unsigned short)len;
+                }
+            }
+
+            /* handle error breaks in while */
+            if (state->mode == BAD) break;
+
+            /* check for end-of-block code (better have one) */
+            if (state->lens[256] == 0) {
+                strm->msg = (char *)"invalid code -- missing end-of-block";
+                state->mode = BAD;
+                break;
+            }
+
+            /* build code tables -- note: do not change the lenbits or distbits
+               values here (9 and 6) without reading the comments in inftrees.h
+               concerning the ENOUGH constants, which depend on those values */
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 9;
+            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid literal/lengths set";
+                state->mode = BAD;
+                break;
+            }
+            state->distcode = (code const FAR *)(state->next);
+            state->distbits = 6;
+            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+                            &(state->next), &(state->distbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid distances set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       codes ok\n"));
+            state->mode = LEN;
+
+        case LEN:
+            /* use inflate_fast() if we have enough input and output */
+            if (have >= 6 && left >= 258) {
+                RESTORE();
+                if (state->whave < state->wsize)
+                    state->whave = state->wsize - left;
+                inflate_fast(strm, state->wsize);
+                LOAD();
+                break;
+            }
+
+            /* get a literal, length, or end-of-block code */
+            for (;;) {
+                here = state->lencode[BITS(state->lenbits)];
+                if ((unsigned)(here.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if (here.op && (here.op & 0xf0) == 0) {
+                last = here;
+                for (;;) {
+                    here = state->lencode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(here.bits);
+            state->length = (unsigned)here.val;
+
+            /* process literal */
+            if (here.op == 0) {
+                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+                        "inflate:         literal '%c'\n" :
+                        "inflate:         literal 0x%02x\n", here.val));
+                ROOM();
+                *put++ = (unsigned char)(state->length);
+                left--;
+                state->mode = LEN;
+                break;
+            }
+
+            /* process end of block */
+            if (here.op & 32) {
+                Tracevv((stderr, "inflate:         end of block\n"));
+                state->mode = TYPE;
+                break;
+            }
+
+            /* invalid code */
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid literal/length code";
+                state->mode = BAD;
+                break;
+            }
+
+            /* length code -- get extra bits, if any */
+            state->extra = (unsigned)(here.op) & 15;
+            if (state->extra != 0) {
+                NEEDBITS(state->extra);
+                state->length += BITS(state->extra);
+                DROPBITS(state->extra);
+            }
+            Tracevv((stderr, "inflate:         length %u\n", state->length));
+
+            /* get distance code */
+            for (;;) {
+                here = state->distcode[BITS(state->distbits)];
+                if ((unsigned)(here.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if ((here.op & 0xf0) == 0) {
+                last = here;
+                for (;;) {
+                    here = state->distcode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(here.bits);
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+            state->offset = (unsigned)here.val;
+
+            /* get distance extra bits, if any */
+            state->extra = (unsigned)(here.op) & 15;
+            if (state->extra != 0) {
+                NEEDBITS(state->extra);
+                state->offset += BITS(state->extra);
+                DROPBITS(state->extra);
+            }
+            if (state->offset > state->wsize - (state->whave < state->wsize ?
+                                                left : 0)) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
+
+            /* copy match from window to output */
+            do {
+                ROOM();
+                copy = state->wsize - state->offset;
+                if (copy < left) {
+                    from = put + copy;
+                    copy = left - copy;
+                }
+                else {
+                    from = put - state->offset;
+                    copy = left;
+                }
+                if (copy > state->length) copy = state->length;
+                state->length -= copy;
+                left -= copy;
+                do {
+                    *put++ = *from++;
+                } while (--copy);
+            } while (state->length != 0);
+            break;
+
+        case DONE:
+            /* inflate stream terminated properly -- write leftover output */
+            ret = Z_STREAM_END;
+            if (left < state->wsize) {
+                if (out(out_desc, state->window, state->wsize - left))
+                    ret = Z_BUF_ERROR;
+            }
+            goto inf_leave;
+
+        case BAD:
+            ret = Z_DATA_ERROR;
+            goto inf_leave;
+
+        default:                /* can't happen, but makes compilers happy */
+            ret = Z_STREAM_ERROR;
+            goto inf_leave;
+        }
+
+    /* Return unused input */
+  inf_leave:
+    strm->next_in = next;
+    strm->avail_in = have;
+    return ret;
+}
+
+int ZEXPORT inflateBackEnd(z_streamp strm)
+{
+    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+        return Z_STREAM_ERROR;
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+    Tracev((stderr, "inflate: end\n"));
+    return Z_OK;
+}
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/zlib/inffast.c b/abc-build/src/misc/zlib/inffast.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/inffast.c
@@ -0,0 +1,351 @@
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2008, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc/util/abc_global.h"
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+ABC_NAMESPACE_IMPL_START
+
+#ifndef ASMINF
+
+/* Allow machine dependent optimization for post-increment or pre-increment.
+   Based on testing to date,
+   Pre-increment preferred for:
+   - PowerPC G3 (Adler)
+   - MIPS R5000 (Randers-Pehrson)
+   Post-increment preferred for:
+   - none
+   No measurable difference:
+   - Pentium III (Anderson)
+   - M68060 (Nikl)
+ */
+#ifdef POSTINC
+#  define OFF 0
+#  define PUP(a) *(a)++
+#else
+#  define OFF 1
+#  define PUP(a) *++(a)
+#endif
+
+/*
+   Decode literal, length, and distance codes and write out the resulting
+   literal and match bytes until either not enough input or output is
+   available, an end-of-block is encountered, or a data error is encountered.
+   When large enough input and output buffers are supplied to inflate(), for
+   example, a 16K input buffer and a 64K output buffer, more than 95% of the
+   inflate execution time is spent in this routine.
+
+   Entry assumptions:
+
+        state->mode == LEN
+        strm->avail_in >= 6
+        strm->avail_out >= 258
+        start >= strm->avail_out
+        state->bits < 8
+
+   On return, state->mode is one of:
+
+        LEN -- ran out of enough output space or enough available input
+        TYPE -- reached end of block code, inflate() to interpret next block
+        BAD -- error in block data
+
+   Notes:
+
+    - The maximum input bits used by a length/distance pair is 15 bits for the
+      length code, 5 bits for the length extra, 15 bits for the distance code,
+      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
+      Therefore if strm->avail_in >= 6, then there is enough input to avoid
+      checking for available input while decoding.
+
+    - The maximum bytes that a single length/distance pair can output is 258
+      bytes, which is the maximum length that can be coded.  inflate_fast()
+      requires strm->avail_out >= 258 for each loop to avoid checking for
+      output space.
+ */
+void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start)  /* inflate()'s starting value for strm->avail_out */
+{
+    struct inflate_state FAR *state;
+    unsigned char FAR *in;      /* local strm->next_in */
+    unsigned char FAR *last;    /* while in < last, enough input available */
+    unsigned char FAR *out;     /* local strm->next_out */
+    unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
+    unsigned char FAR *end;     /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+    unsigned dmax;              /* maximum distance from zlib header */
+#endif
+    unsigned wsize;             /* window size or zero if not using window */
+    unsigned whave;             /* valid bytes in the window */
+    unsigned wnext;             /* window write index */
+    unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
+    unsigned long hold;         /* local strm->hold */
+    unsigned bits;              /* local strm->bits */
+    code const FAR *lcode;      /* local strm->lencode */
+    code const FAR *dcode;      /* local strm->distcode */
+    unsigned lmask;             /* mask for first level of length codes */
+    unsigned dmask;             /* mask for first level of distance codes */
+    code here;                  /* retrieved table entry */
+    unsigned op;                /* code bits, operation, extra bits, or */
+                                /*  window position, window bytes to copy */
+    unsigned len;               /* match length, unused bytes */
+    unsigned dist;              /* match distance */
+    unsigned char FAR *from;    /* where to copy match from */
+
+    /* copy state to local variables */
+    state = (struct inflate_state FAR *)strm->state;
+    in = strm->next_in - OFF;
+    last = in + (strm->avail_in - 5);
+    out = strm->next_out - OFF;
+    beg = out - (start - strm->avail_out);
+    end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+    dmax = state->dmax;
+#endif
+    wsize = state->wsize;
+    whave = state->whave;
+    wnext = state->wnext;
+    window = state->window;
+    hold = state->hold;
+    bits = state->bits;
+    lcode = state->lencode;
+    dcode = state->distcode;
+    lmask = (1U << state->lenbits) - 1;
+    dmask = (1U << state->distbits) - 1;
+
+    /* decode literals and length/distances until end-of-block or not enough
+       input data or output space */
+    do {
+        if (bits < 15) {
+            hold += (unsigned long)(PUP(in)) << bits;
+            bits += 8;
+            hold += (unsigned long)(PUP(in)) << bits;
+            bits += 8;
+        }
+        here = lcode[hold & lmask];
+      dolen:
+        op = (unsigned)(here.bits);
+        hold >>= op;
+        bits -= op;
+        op = (unsigned)(here.op);
+        if (op == 0) {                          /* literal */
+            Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+                    "inflate:         literal '%c'\n" :
+                    "inflate:         literal 0x%02x\n", here.val));
+            PUP(out) = (unsigned char)(here.val);
+        }
+        else if (op & 16) {                     /* length base */
+            len = (unsigned)(here.val);
+            op &= 15;                           /* number of extra bits */
+            if (op) {
+                if (bits < op) {
+                    hold += (unsigned long)(PUP(in)) << bits;
+                    bits += 8;
+                }
+                len += (unsigned)hold & ((1U << op) - 1);
+                hold >>= op;
+                bits -= op;
+            }
+            Tracevv((stderr, "inflate:         length %u\n", len));
+            if (bits < 15) {
+                hold += (unsigned long)(PUP(in)) << bits;
+                bits += 8;
+                hold += (unsigned long)(PUP(in)) << bits;
+                bits += 8;
+            }
+            here = dcode[hold & dmask];
+          dodist:
+            op = (unsigned)(here.bits);
+            hold >>= op;
+            bits -= op;
+            op = (unsigned)(here.op);
+            if (op & 16) {                      /* distance base */
+                dist = (unsigned)(here.val);
+                op &= 15;                       /* number of extra bits */
+                if (bits < op) {
+                    hold += (unsigned long)(PUP(in)) << bits;
+                    bits += 8;
+                    if (bits < op) {
+                        hold += (unsigned long)(PUP(in)) << bits;
+                        bits += 8;
+                    }
+                }
+                dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+                if (dist > dmax) {
+                    strm->msg = (char *)"invalid distance too far back";
+                    state->mode = BAD;
+                    break;
+                }
+#endif
+                hold >>= op;
+                bits -= op;
+                Tracevv((stderr, "inflate:         distance %u\n", dist));
+                op = (unsigned)(out - beg);     /* max distance in output */
+                if (dist > op) {                /* see if copy from window */
+                    op = dist - op;             /* distance back in window */
+                    if (op > whave) {
+                        if (state->sane) {
+                            strm->msg =
+                                (char *)"invalid distance too far back";
+                            state->mode = BAD;
+                            break;
+                        }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+                        if (len <= op - whave) {
+                            do {
+                                PUP(out) = 0;
+                            } while (--len);
+                            continue;
+                        }
+                        len -= op - whave;
+                        do {
+                            PUP(out) = 0;
+                        } while (--op > whave);
+                        if (op == 0) {
+                            from = out - dist;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--len);
+                            continue;
+                        }
+#endif
+                    }
+                    from = window - OFF;
+                    if (wnext == 0) {           /* very common case */
+                        from += wsize - op;
+                        if (op < len) {         /* some from window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = out - dist;  /* rest from output */
+                        }
+                    }
+                    else if (wnext < op) {      /* wrap around window */
+                        from += wsize + wnext - op;
+                        op -= wnext;
+                        if (op < len) {         /* some from end of window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = window - OFF;
+                            if (wnext < len) {  /* some from start of window */
+                                op = wnext;
+                                len -= op;
+                                do {
+                                    PUP(out) = PUP(from);
+                                } while (--op);
+                                from = out - dist;      /* rest from output */
+                            }
+                        }
+                    }
+                    else {                      /* contiguous in window */
+                        from += wnext - op;
+                        if (op < len) {         /* some from window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = out - dist;  /* rest from output */
+                        }
+                    }
+                    while (len > 2) {
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        len -= 3;
+                    }
+                    if (len) {
+                        PUP(out) = PUP(from);
+                        if (len > 1)
+                            PUP(out) = PUP(from);
+                    }
+                }
+                else {
+                    from = out - dist;          /* copy direct from output */
+                    do {                        /* minimum length is three */
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        len -= 3;
+                    } while (len > 2);
+                    if (len) {
+                        PUP(out) = PUP(from);
+                        if (len > 1)
+                            PUP(out) = PUP(from);
+                    }
+                }
+            }
+            else if ((op & 64) == 0) {          /* 2nd level distance code */
+                here = dcode[here.val + (hold & ((1U << op) - 1))];
+                goto dodist;
+            }
+            else {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+        }
+        else if ((op & 64) == 0) {              /* 2nd level length code */
+            here = lcode[here.val + (hold & ((1U << op) - 1))];
+            goto dolen;
+        }
+        else if (op & 32) {                     /* end-of-block */
+            Tracevv((stderr, "inflate:         end of block\n"));
+            state->mode = TYPE;
+            break;
+        }
+        else {
+            strm->msg = (char *)"invalid literal/length code";
+            state->mode = BAD;
+            break;
+        }
+    } while (in < last && out < end);
+
+    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+    len = bits >> 3;
+    in -= len;
+    bits -= len << 3;
+    hold &= (1U << bits) - 1;
+
+    /* update state and return */
+    strm->next_in = in + OFF;
+    strm->next_out = out + OFF;
+    strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+    strm->avail_out = (unsigned)(out < end ?
+                                 257 + (end - out) : 257 - (out - end));
+    state->hold = hold;
+    state->bits = bits;
+    return;
+}
+
+/*
+   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+   - Using bit fields for code structure
+   - Different op definition to avoid & for extra bits (do & for table bits)
+   - Three separate decoding do-loops for direct, window, and wnext == 0
+   - Special case for distance > 1 copies to do overlapped load and store copy
+   - Explicit branch predictions (based on measured branch probabilities)
+   - Deferring match copy and interspersed it with decoding subsequent codes
+   - Swapping literal/length else
+   - Swapping window/direct else
+   - Larger unrolled copy loops (three is about right)
+   - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
+
+ 
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/misc/zlib/inffast.h b/abc-build/src/misc/zlib/inffast.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/inffast.h
@@ -0,0 +1,15 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-2003, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+ABC_NAMESPACE_HEADER_START
+
+void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
+
+ABC_NAMESPACE_HEADER_END
diff --git a/abc-build/src/misc/zlib/inffixed.h b/abc-build/src/misc/zlib/inffixed.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/inffixed.h
@@ -0,0 +1,98 @@
+    /* inffixed.h -- table for decoding fixed codes
+     * Generated automatically by makefixed().
+     */
+
+    /* WARNING: this file should *not* be used by applications. It
+       is part of the implementation of the compression library and
+       is subject to change. Applications should only use zlib.h.
+     */
+
+//ABC_NAMESPACE_HEADER_START
+
+    static const code lenfix[512] = {
+        {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+        {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+        {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+        {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+        {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+        {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+        {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+        {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+        {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+        {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+        {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+        {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+        {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+        {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+        {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+        {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+        {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+        {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+        {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+        {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+        {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+        {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+        {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+        {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+        {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+        {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+        {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+        {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+        {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+        {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+        {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+        {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+        {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+        {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+        {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+        {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+        {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+        {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+        {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+        {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+        {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+        {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+        {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+        {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+        {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+        {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+        {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+        {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+        {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+        {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+        {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+        {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+        {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+        {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+        {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+        {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+        {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+        {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+        {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+        {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+        {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+        {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+        {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+        {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+        {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+        {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+        {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+        {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+        {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+        {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+        {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+        {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+        {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+        {0,9,255}
+    };
+
+    static const code distfix[32] = {
+        {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+        {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+        {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+        {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+        {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+        {22,5,193},{64,5,0}
+    };
+
+//ABC_NAMESPACE_HEADER_END
diff --git a/abc-build/src/misc/zlib/inflate.c b/abc-build/src/misc/zlib/inflate.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/inflate.c
@@ -0,0 +1,1457 @@
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * Change history:
+ *
+ * 1.2.beta0    24 Nov 2002
+ * - First version -- complete rewrite of inflate to simplify code, avoid
+ *   creation of window when not needed, minimize use of window when it is
+ *   needed, make inffast.c even faster, implement gzip decoding, and to
+ *   improve code readability and style over the previous zlib inflate code
+ *
+ * 1.2.beta1    25 Nov 2002
+ * - Use pointers for available input and output checking in inffast.c
+ * - Remove input and output counters in inffast.c
+ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
+ * - Remove unnecessary second byte pull from length extra in inffast.c
+ * - Unroll direct copy to three copies per loop in inffast.c
+ *
+ * 1.2.beta2    4 Dec 2002
+ * - Change external routine names to reduce potential conflicts
+ * - Correct filename to inffixed.h for fixed tables in inflate.c
+ * - Make hbuf[] unsigned char to match parameter type in inflate.c
+ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
+ *   to avoid negation problem on Alphas (64 bit) in inflate.c
+ *
+ * 1.2.beta3    22 Dec 2002
+ * - Add comments on state->bits assertion in inffast.c
+ * - Add comments on op field in inftrees.h
+ * - Fix bug in reuse of allocated window after inflateReset()
+ * - Remove bit fields--back to byte structure for speed
+ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
+ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
+ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
+ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
+ * - Use local copies of stream next and avail values, as well as local bit
+ *   buffer and bit count in inflate()--for speed when inflate_fast() not used
+ *
+ * 1.2.beta4    1 Jan 2003
+ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
+ * - Move a comment on output buffer sizes from inffast.c to inflate.c
+ * - Add comments in inffast.c to introduce the inflate_fast() routine
+ * - Rearrange window copies in inflate_fast() for speed and simplification
+ * - Unroll last copy for window match in inflate_fast()
+ * - Use local copies of window variables in inflate_fast() for speed
+ * - Pull out common wnext == 0 case for speed in inflate_fast()
+ * - Make op and len in inflate_fast() unsigned for consistency
+ * - Add FAR to lcode and dcode declarations in inflate_fast()
+ * - Simplified bad distance check in inflate_fast()
+ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
+ *   source file infback.c to provide a call-back interface to inflate for
+ *   programs like gzip and unzip -- uses window as output buffer to avoid
+ *   window copying
+ *
+ * 1.2.beta5    1 Jan 2003
+ * - Improved inflateBack() interface to allow the caller to provide initial
+ *   input in strm.
+ * - Fixed stored blocks bug in inflateBack()
+ *
+ * 1.2.beta6    4 Jan 2003
+ * - Added comments in inffast.c on effectiveness of POSTINC
+ * - Typecasting all around to reduce compiler warnings
+ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
+ *   make compilers happy
+ * - Changed type of window in inflateBackInit() to unsigned char *
+ *
+ * 1.2.beta7    27 Jan 2003
+ * - Changed many types to unsigned or unsigned short to avoid warnings
+ * - Added inflateCopy() function
+ *
+ * 1.2.0        9 Mar 2003
+ * - Changed inflateBack() interface to provide separate opaque descriptors
+ *   for the in() and out() functions
+ * - Changed inflateBack() argument and in_func typedef to swap the length
+ *   and buffer address return values for the input function
+ * - Check next_in and next_out for Z_NULL on entry to inflate()
+ *
+ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc/util/abc_global.h"
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+ABC_NAMESPACE_IMPL_START
+
+#ifdef MAKEFIXED
+#  ifndef BUILDFIXED
+#    define BUILDFIXED
+#  endif
+#endif
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, unsigned out));
+#ifdef BUILDFIXED
+   void makefixed OF((void));
+#endif
+local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
+                              unsigned len));
+
+int ZEXPORT inflateReset(z_streamp strm)
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    strm->total_in = strm->total_out = state->total = 0;
+    strm->msg = Z_NULL;
+    strm->adler = 1;        /* to support ill-conceived Java test suite */
+    state->mode = HEAD;
+    state->last = 0;
+    state->havedict = 0;
+    state->dmax = 32768U;
+    state->head = Z_NULL;
+    state->wsize = 0;
+    state->whave = 0;
+    state->wnext = 0;
+    state->hold = 0;
+    state->bits = 0;
+    state->lencode = state->distcode = state->next = state->codes;
+    state->sane = 1;
+    state->back = -1;
+    Tracev((stderr, "inflate: reset\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateReset2(z_streamp strm, int windowBits)
+{
+    int wrap;
+    struct inflate_state FAR *state;
+
+    /* get the state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* extract wrap request from windowBits parameter */
+    if (windowBits < 0) {
+        wrap = 0;
+        windowBits = -windowBits;
+    }
+    else {
+        wrap = (windowBits >> 4) + 1;
+#ifdef GUNZIP
+        if (windowBits < 48)
+            windowBits &= 15;
+#endif
+    }
+
+    /* set number of window bits, free window if different */
+    if (windowBits && (windowBits < 8 || windowBits > 15))
+        return Z_STREAM_ERROR;
+    if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
+        ZFREE(strm, state->window);
+        state->window = Z_NULL;
+    }
+
+    /* update state and reset the rest of it */
+    state->wrap = wrap;
+    state->wbits = (unsigned)windowBits;
+    return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size)
+{
+    int ret;
+    struct inflate_state FAR *state;
+
+    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+        stream_size != (int)(sizeof(z_stream)))
+        return Z_VERSION_ERROR;
+    if (strm == Z_NULL) return Z_STREAM_ERROR;
+    strm->msg = Z_NULL;                 /* in case we return an error */
+    if (strm->zalloc == (alloc_func)0) {
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+    }
+    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+    state = (struct inflate_state FAR *)
+            ZALLOC(strm, 1, sizeof(struct inflate_state));
+    if (state == Z_NULL) return Z_MEM_ERROR;
+    Tracev((stderr, "inflate: allocated\n"));
+    strm->state = (struct internal_state FAR *)state;
+    state->window = Z_NULL;
+    ret = inflateReset2(strm, windowBits);
+    if (ret != Z_OK) {
+        ZFREE(strm, state);
+        strm->state = Z_NULL;
+    }
+    return ret;
+}
+
+int ZEXPORT inflateInit_(z_streamp strm, const char *version, int stream_size)
+{
+    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+int ZEXPORT inflatePrime(z_streamp strm, int bits, int value)
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (bits < 0) {
+        state->hold = 0;
+        state->bits = 0;
+        return Z_OK;
+    }
+    if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
+    value &= (1L << bits) - 1;
+    state->hold += value << state->bits;
+    state->bits += bits;
+    return Z_OK;
+}
+
+/*
+   Return state with length and distance decoding tables and index sizes set to
+   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
+   If BUILDFIXED is defined, then instead this routine builds the tables the
+   first time it's called, and returns those tables the first time and
+   thereafter.  This reduces the size of the code by about 2K bytes, in
+   exchange for a little execution time.  However, BUILDFIXED should not be
+   used for threaded applications, since the rewriting of the tables and virgin
+   may not be thread-safe.
+ */
+local void fixedtables(struct inflate_state FAR *state)
+{
+#ifdef BUILDFIXED
+    static int virgin = 1;
+    static code *lenfix, *distfix;
+    static code fixed[544];
+
+    /* build fixed huffman tables if first call (may not be thread safe) */
+    if (virgin) {
+        unsigned sym, bits;
+        static code *next;
+
+        /* literal/length table */
+        sym = 0;
+        while (sym < 144) state->lens[sym++] = 8;
+        while (sym < 256) state->lens[sym++] = 9;
+        while (sym < 280) state->lens[sym++] = 7;
+        while (sym < 288) state->lens[sym++] = 8;
+        next = fixed;
+        lenfix = next;
+        bits = 9;
+        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+        /* distance table */
+        sym = 0;
+        while (sym < 32) state->lens[sym++] = 5;
+        distfix = next;
+        bits = 5;
+        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+        /* do this just once */
+        virgin = 0;
+    }
+#else /* !BUILDFIXED */
+#   include "inffixed.h"
+#endif /* BUILDFIXED */
+    state->lencode = lenfix;
+    state->lenbits = 9;
+    state->distcode = distfix;
+    state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include <stdio.h>
+
+/*
+   Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also
+   defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes
+   those tables to stdout, which would be piped to inffixed.h.  A small program
+   can simply call makefixed to do this:
+
+    void makefixed(void);
+
+    int main(void)
+    {
+        makefixed();
+        return 0;
+    }
+
+   Then that can be linked with zlib built with MAKEFIXED defined and run:
+
+    a.out > inffixed.h
+ */
+void makefixed()
+{
+    unsigned low, size;
+    struct inflate_state state;
+
+    fixedtables(&state);
+    puts("    /* inffixed.h -- table for decoding fixed codes");
+    puts("     * Generated automatically by makefixed().");
+    puts("     */");
+    puts("");
+    puts("    /* WARNING: this file should *not* be used by applications.");
+    puts("       It is part of the implementation of this library and is");
+    puts("       subject to change. Applications should only use zlib.h.");
+    puts("     */");
+    puts("");
+    size = 1U << 9;
+    printf("    static const code lenfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 7) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits,
+               state.lencode[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+    size = 1U << 5;
+    printf("\n    static const code distfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 6) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+               state.distcode[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+}
+#endif /* MAKEFIXED */
+
+/*
+   Update the window with the last wsize (normally 32K) bytes written before
+   returning.  If window does not exist yet, create it.  This is only called
+   when a window is already in use, or when output has been written during this
+   inflate call, but the end of the deflate stream has not been reached yet.
+   It is also called to create a window for dictionary data when a dictionary
+   is loaded.
+
+   Providing output buffers larger than 32K to inflate() should provide a speed
+   advantage, since only the last 32K of output is copied to the sliding window
+   upon return from inflate(), and since all distances after the first 32K of
+   output will fall in the output data, making match copies simpler and faster.
+   The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(z_streamp strm, unsigned out)
+{
+    struct inflate_state FAR *state;
+    unsigned copy, dist;
+
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* if it hasn't been done already, allocate space for the window */
+    if (state->window == Z_NULL) {
+        state->window = (unsigned char FAR *)
+                        ZALLOC(strm, 1U << state->wbits,
+                               sizeof(unsigned char));
+        if (state->window == Z_NULL) return 1;
+    }
+
+    /* if window not in use yet, initialize */
+    if (state->wsize == 0) {
+        state->wsize = 1U << state->wbits;
+        state->wnext = 0;
+        state->whave = 0;
+    }
+
+    /* copy state->wsize or less output bytes into the circular window */
+    copy = out - strm->avail_out;
+    if (copy >= state->wsize) {
+        zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
+        state->wnext = 0;
+        state->whave = state->wsize;
+    }
+    else {
+        dist = state->wsize - state->wnext;
+        if (dist > copy) dist = copy;
+        zmemcpy(state->window + state->wnext, strm->next_out - copy, dist);
+        copy -= dist;
+        if (copy) {
+            zmemcpy(state->window, strm->next_out - copy, copy);
+            state->wnext = copy;
+            state->whave = state->wsize;
+        }
+        else {
+            state->wnext += dist;
+            if (state->wnext == state->wsize) state->wnext = 0;
+            if (state->whave < state->wsize) state->whave += dist;
+        }
+    }
+    return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+#  define UPDATE(check, buf, len) \
+    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+#  define UPDATE(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+#  define CRC2(check, word) \
+    do { \
+        hbuf[0] = (unsigned char)(word); \
+        hbuf[1] = (unsigned char)((word) >> 8); \
+        check = crc32(check, hbuf, 2); \
+    } while (0)
+
+#  define CRC4(check, word) \
+    do { \
+        hbuf[0] = (unsigned char)(word); \
+        hbuf[1] = (unsigned char)((word) >> 8); \
+        hbuf[2] = (unsigned char)((word) >> 16); \
+        hbuf[3] = (unsigned char)((word) >> 24); \
+        check = crc32(check, hbuf, 4); \
+    } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+    do { \
+        put = strm->next_out; \
+        left = strm->avail_out; \
+        next = strm->next_in; \
+        have = strm->avail_in; \
+        hold = state->hold; \
+        bits = state->bits; \
+    } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+    do { \
+        strm->next_out = put; \
+        strm->avail_out = left; \
+        strm->next_in = next; \
+        strm->avail_in = have; \
+        state->hold = hold; \
+        state->bits = bits; \
+    } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+    do { \
+        hold = 0; \
+        bits = 0; \
+    } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+   if there is no input available. */
+#define PULLBYTE() \
+    do { \
+        if (have == 0) goto inf_leave; \
+        have--; \
+        hold += (unsigned long)(*next++) << bits; \
+        bits += 8; \
+    } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator.  If there is
+   not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+    do { \
+        while (bits < (unsigned)(n)) \
+            PULLBYTE(); \
+    } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+    ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+    do { \
+        hold >>= (n); \
+        bits -= (unsigned)(n); \
+    } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+    do { \
+        hold >>= bits & 7; \
+        bits -= bits & 7; \
+    } while (0)
+
+/* Reverse the bytes in a 32-bit value */
+#define REVERSE(q) \
+    ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+     (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+/*
+   inflate() uses a state machine to process as much input data and generate as
+   much output data as possible before returning.  The state machine is
+   structured roughly as follows:
+
+    for (;;) switch (state) {
+    ...
+    case STATEn:
+        if (not enough input data or output space to make progress)
+            return;
+        ... make progress ...
+        state = STATEm;
+        break;
+    ...
+    }
+
+   so when inflate() is called again, the same case is attempted again, and
+   if the appropriate resources are provided, the machine proceeds to the
+   next state.  The NEEDBITS() macro is usually the way the state evaluates
+   whether it can proceed or should return.  NEEDBITS() does the return if
+   the requested bits are not available.  The typical use of the BITS macros
+   is:
+
+        NEEDBITS(n);
+        ... do something with BITS(n) ...
+        DROPBITS(n);
+
+   where NEEDBITS(n) either returns from inflate() if there isn't enough
+   input left to load n bits into the accumulator, or it continues.  BITS(n)
+   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
+   the low n bits off the accumulator.  INITBITS() clears the accumulator
+   and sets the number of available bits to zero.  BYTEBITS() discards just
+   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
+   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+   if there is no input available.  The decoding of variable length codes uses
+   PULLBYTE() directly in order to pull just enough bytes to decode the next
+   code, and no more.
+
+   Some states loop until they get enough input, making sure that enough
+   state information is maintained to continue the loop where it left off
+   if NEEDBITS() returns in the loop.  For example, want, need, and keep
+   would all have to actually be part of the saved state in case NEEDBITS()
+   returns:
+
+    case STATEw:
+        while (want < need) {
+            NEEDBITS(n);
+            keep[want++] = BITS(n);
+            DROPBITS(n);
+        }
+        state = STATEx;
+    case STATEx:
+
+   As shown above, if the next state is also the next case, then the break
+   is omitted.
+
+   A state may also return if there is not enough output space available to
+   complete that state.  Those states are copying stored data, writing a
+   literal byte, and copying a matching string.
+
+   When returning, a "goto inf_leave" is used to update the total counters,
+   update the check value, and determine whether any progress has been made
+   during that inflate() call in order to return the proper return code.
+   Progress is defined as a change in either strm->avail_in or strm->avail_out.
+   When there is a window, goto inf_leave will update the window with the last
+   output written.  If a goto inf_leave occurs in the middle of decompression
+   and there is no window currently, goto inf_leave will create one and copy
+   output to the window for the next call of inflate().
+
+   In this implementation, the flush parameter of inflate() only affects the
+   return code (per zlib.h).  inflate() always writes as much as possible to
+   strm->next_out, given the space available and the provided input--the effect
+   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
+   the allocation of and copying into a sliding window until necessary, which
+   provides the effect documented in zlib.h for Z_FINISH when the entire input
+   stream available.  So the only thing the flush parameter actually does is:
+   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
+   will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(z_streamp strm, int flush)
+{
+    struct inflate_state FAR *state;
+    unsigned char FAR *next;    /* next input */
+    unsigned char FAR *put;     /* next output */
+    unsigned have, left;        /* available input and output */
+    unsigned long hold;         /* bit buffer */
+    unsigned bits;              /* bits in bit buffer */
+    unsigned in, out;           /* save starting available input and output */
+    unsigned copy;              /* number of stored or match bytes to copy */
+    unsigned char FAR *from;    /* where to copy match bytes from */
+    code here;                  /* current decoding table entry */
+    code last;                  /* parent table entry */
+    unsigned len;               /* length to copy for repeats, bits to drop */
+    int ret;                    /* return code */
+#ifdef GUNZIP
+    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
+#endif
+    static const unsigned short order[19] = /* permutation of code lengths */
+        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+    if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
+        (strm->next_in == Z_NULL && strm->avail_in != 0))
+        return Z_STREAM_ERROR;
+
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
+    LOAD();
+    in = have;
+    out = left;
+    ret = Z_OK;
+    for (;;)
+        switch (state->mode) {
+        case HEAD:
+            if (state->wrap == 0) {
+                state->mode = TYPEDO;
+                break;
+            }
+            NEEDBITS(16);
+#ifdef GUNZIP
+            if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */
+                state->check = crc32(0L, Z_NULL, 0);
+                CRC2(state->check, hold);
+                INITBITS();
+                state->mode = FLAGS;
+                break;
+            }
+            state->flags = 0;           /* expect zlib header */
+            if (state->head != Z_NULL)
+                state->head->done = -1;
+            if (!(state->wrap & 1) ||   /* check if zlib header allowed */
+#else
+            if (
+#endif
+                ((BITS(8) << 8) + (hold >> 8)) % 31) {
+                strm->msg = (char *)"incorrect header check";
+                state->mode = BAD;
+                break;
+            }
+            if (BITS(4) != Z_DEFLATED) {
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
+                break;
+            }
+            DROPBITS(4);
+            len = BITS(4) + 8;
+            if (state->wbits == 0)
+                state->wbits = len;
+            else if (len > state->wbits) {
+                strm->msg = (char *)"invalid window size";
+                state->mode = BAD;
+                break;
+            }
+            state->dmax = 1U << len;
+            Tracev((stderr, "inflate:   zlib header ok\n"));
+            strm->adler = state->check = adler32(0L, Z_NULL, 0);
+            state->mode = hold & 0x200 ? DICTID : TYPE;
+            INITBITS();
+            break;
+#ifdef GUNZIP
+        case FLAGS:
+            NEEDBITS(16);
+            state->flags = (int)(hold);
+            if ((state->flags & 0xff) != Z_DEFLATED) {
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
+                break;
+            }
+            if (state->flags & 0xe000) {
+                strm->msg = (char *)"unknown header flags set";
+                state->mode = BAD;
+                break;
+            }
+            if (state->head != Z_NULL)
+                state->head->text = (int)((hold >> 8) & 1);
+            if (state->flags & 0x0200) CRC2(state->check, hold);
+            INITBITS();
+            state->mode = TIME;
+        case TIME:
+            NEEDBITS(32);
+            if (state->head != Z_NULL)
+                state->head->time = hold;
+            if (state->flags & 0x0200) CRC4(state->check, hold);
+            INITBITS();
+            state->mode = OS;
+        case OS:
+            NEEDBITS(16);
+            if (state->head != Z_NULL) {
+                state->head->xflags = (int)(hold & 0xff);
+                state->head->os = (int)(hold >> 8);
+            }
+            if (state->flags & 0x0200) CRC2(state->check, hold);
+            INITBITS();
+            state->mode = EXLEN;
+        case EXLEN:
+            if (state->flags & 0x0400) {
+                NEEDBITS(16);
+                state->length = (unsigned)(hold);
+                if (state->head != Z_NULL)
+                    state->head->extra_len = (unsigned)hold;
+                if (state->flags & 0x0200) CRC2(state->check, hold);
+                INITBITS();
+            }
+            else if (state->head != Z_NULL)
+                state->head->extra = Z_NULL;
+            state->mode = EXTRA;
+        case EXTRA:
+            if (state->flags & 0x0400) {
+                copy = state->length;
+                if (copy > have) copy = have;
+                if (copy) {
+                    if (state->head != Z_NULL &&
+                        state->head->extra != Z_NULL) {
+                        len = state->head->extra_len - state->length;
+                        zmemcpy(state->head->extra + len, next,
+                                len + copy > state->head->extra_max ?
+                                state->head->extra_max - len : copy);
+                    }
+                    if (state->flags & 0x0200)
+                        state->check = crc32(state->check, next, copy);
+                    have -= copy;
+                    next += copy;
+                    state->length -= copy;
+                }
+                if (state->length) goto inf_leave;
+            }
+            state->length = 0;
+            state->mode = NAME;
+        case NAME:
+            if (state->flags & 0x0800) {
+                if (have == 0) goto inf_leave;
+                copy = 0;
+                do {
+                    len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->name != Z_NULL &&
+                            state->length < state->head->name_max)
+                        state->head->name[state->length++] = len;
+                } while (len && copy < have);
+                if (state->flags & 0x0200)
+                    state->check = crc32(state->check, next, copy);
+                have -= copy;
+                next += copy;
+                if (len) goto inf_leave;
+            }
+            else if (state->head != Z_NULL)
+                state->head->name = Z_NULL;
+            state->length = 0;
+            state->mode = COMMENT;
+        case COMMENT:
+            if (state->flags & 0x1000) {
+                if (have == 0) goto inf_leave;
+                copy = 0;
+                do {
+                    len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->comment != Z_NULL &&
+                            state->length < state->head->comm_max)
+                        state->head->comment[state->length++] = len;
+                } while (len && copy < have);
+                if (state->flags & 0x0200)
+                    state->check = crc32(state->check, next, copy);
+                have -= copy;
+                next += copy;
+                if (len) goto inf_leave;
+            }
+            else if (state->head != Z_NULL)
+                state->head->comment = Z_NULL;
+            state->mode = HCRC;
+        case HCRC:
+            if (state->flags & 0x0200) {
+                NEEDBITS(16);
+                if (hold != (state->check & 0xffff)) {
+                    strm->msg = (char *)"header crc mismatch";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+            }
+            if (state->head != Z_NULL) {
+                state->head->hcrc = (int)((state->flags >> 9) & 1);
+                state->head->done = 1;
+            }
+            strm->adler = state->check = crc32(0L, Z_NULL, 0);
+            state->mode = TYPE;
+            break;
+#endif
+        case DICTID:
+            NEEDBITS(32);
+            strm->adler = state->check = REVERSE(hold);
+            INITBITS();
+            state->mode = DICT;
+        case DICT:
+            if (state->havedict == 0) {
+                RESTORE();
+                return Z_NEED_DICT;
+            }
+            strm->adler = state->check = adler32(0L, Z_NULL, 0);
+            state->mode = TYPE;
+        case TYPE:
+            if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
+        case TYPEDO:
+            if (state->last) {
+                BYTEBITS();
+                state->mode = CHECK;
+                break;
+            }
+            NEEDBITS(3);
+            state->last = BITS(1);
+            DROPBITS(1);
+            switch (BITS(2)) {
+            case 0:                             /* stored block */
+                Tracev((stderr, "inflate:     stored block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = STORED;
+                break;
+            case 1:                             /* fixed block */
+                fixedtables(state);
+                Tracev((stderr, "inflate:     fixed codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = LEN_;             /* decode codes */
+                if (flush == Z_TREES) {
+                    DROPBITS(2);
+                    goto inf_leave;
+                }
+                break;
+            case 2:                             /* dynamic block */
+                Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = TABLE;
+                break;
+            case 3:
+                strm->msg = (char *)"invalid block type";
+                state->mode = BAD;
+            }
+            DROPBITS(2);
+            break;
+        case STORED:
+            BYTEBITS();                         /* go to byte boundary */
+            NEEDBITS(32);
+            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+                strm->msg = (char *)"invalid stored block lengths";
+                state->mode = BAD;
+                break;
+            }
+            state->length = (unsigned)hold & 0xffff;
+            Tracev((stderr, "inflate:       stored length %u\n",
+                    state->length));
+            INITBITS();
+            state->mode = COPY_;
+            if (flush == Z_TREES) goto inf_leave;
+        case COPY_:
+            state->mode = COPY;
+        case COPY:
+            copy = state->length;
+            if (copy) {
+                if (copy > have) copy = have;
+                if (copy > left) copy = left;
+                if (copy == 0) goto inf_leave;
+                zmemcpy(put, next, copy);
+                have -= copy;
+                next += copy;
+                left -= copy;
+                put += copy;
+                state->length -= copy;
+                break;
+            }
+            Tracev((stderr, "inflate:       stored end\n"));
+            state->mode = TYPE;
+            break;
+        case TABLE:
+            NEEDBITS(14);
+            state->nlen = BITS(5) + 257;
+            DROPBITS(5);
+            state->ndist = BITS(5) + 1;
+            DROPBITS(5);
+            state->ncode = BITS(4) + 4;
+            DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+            if (state->nlen > 286 || state->ndist > 30) {
+                strm->msg = (char *)"too many length or distance symbols";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracev((stderr, "inflate:       table sizes ok\n"));
+            state->have = 0;
+            state->mode = LENLENS;
+        case LENLENS:
+            while (state->have < state->ncode) {
+                NEEDBITS(3);
+                state->lens[order[state->have++]] = (unsigned short)BITS(3);
+                DROPBITS(3);
+            }
+            while (state->have < 19)
+                state->lens[order[state->have++]] = 0;
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 7;
+            ret = inflate_table(CODES, state->lens, 19, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid code lengths set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       code lengths ok\n"));
+            state->have = 0;
+            state->mode = CODELENS;
+        case CODELENS:
+            while (state->have < state->nlen + state->ndist) {
+                for (;;) {
+                    here = state->lencode[BITS(state->lenbits)];
+                    if ((unsigned)(here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                if (here.val < 16) {
+                    NEEDBITS(here.bits);
+                    DROPBITS(here.bits);
+                    state->lens[state->have++] = here.val;
+                }
+                else {
+                    if (here.val == 16) {
+                        NEEDBITS(here.bits + 2);
+                        DROPBITS(here.bits);
+                        if (state->have == 0) {
+                            strm->msg = (char *)"invalid bit length repeat";
+                            state->mode = BAD;
+                            break;
+                        }
+                        len = state->lens[state->have - 1];
+                        copy = 3 + BITS(2);
+                        DROPBITS(2);
+                    }
+                    else if (here.val == 17) {
+                        NEEDBITS(here.bits + 3);
+                        DROPBITS(here.bits);
+                        len = 0;
+                        copy = 3 + BITS(3);
+                        DROPBITS(3);
+                    }
+                    else {
+                        NEEDBITS(here.bits + 7);
+                        DROPBITS(here.bits);
+                        len = 0;
+                        copy = 11 + BITS(7);
+                        DROPBITS(7);
+                    }
+                    if (state->have + copy > state->nlen + state->ndist) {
+                        strm->msg = (char *)"invalid bit length repeat";
+                        state->mode = BAD;
+                        break;
+                    }
+                    while (copy--)
+                        state->lens[state->have++] = (unsigned short)len;
+                }
+            }
+
+            /* handle error breaks in while */
+            if (state->mode == BAD) break;
+
+            /* check for end-of-block code (better have one) */
+            if (state->lens[256] == 0) {
+                strm->msg = (char *)"invalid code -- missing end-of-block";
+                state->mode = BAD;
+                break;
+            }
+
+            /* build code tables -- note: do not change the lenbits or distbits
+               values here (9 and 6) without reading the comments in inftrees.h
+               concerning the ENOUGH constants, which depend on those values */
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 9;
+            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid literal/lengths set";
+                state->mode = BAD;
+                break;
+            }
+            state->distcode = (code const FAR *)(state->next);
+            state->distbits = 6;
+            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+                            &(state->next), &(state->distbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid distances set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       codes ok\n"));
+            state->mode = LEN_;
+            if (flush == Z_TREES) goto inf_leave;
+        case LEN_:
+            state->mode = LEN;
+        case LEN:
+            if (have >= 6 && left >= 258) {
+                RESTORE();
+                inflate_fast(strm, out);
+                LOAD();
+                if (state->mode == TYPE)
+                    state->back = -1;
+                break;
+            }
+            state->back = 0;
+            for (;;) {
+                here = state->lencode[BITS(state->lenbits)];
+                if ((unsigned)(here.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if (here.op && (here.op & 0xf0) == 0) {
+                last = here;
+                for (;;) {
+                    here = state->lencode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+                state->back += last.bits;
+            }
+            DROPBITS(here.bits);
+            state->back += here.bits;
+            state->length = (unsigned)here.val;
+            if ((int)(here.op) == 0) {
+                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+                        "inflate:         literal '%c'\n" :
+                        "inflate:         literal 0x%02x\n", here.val));
+                state->mode = LIT;
+                break;
+            }
+            if (here.op & 32) {
+                Tracevv((stderr, "inflate:         end of block\n"));
+                state->back = -1;
+                state->mode = TYPE;
+                break;
+            }
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid literal/length code";
+                state->mode = BAD;
+                break;
+            }
+            state->extra = (unsigned)(here.op) & 15;
+            state->mode = LENEXT;
+        case LENEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->length += BITS(state->extra);
+                DROPBITS(state->extra);
+                state->back += state->extra;
+            }
+            Tracevv((stderr, "inflate:         length %u\n", state->length));
+            state->was = state->length;
+            state->mode = DIST;
+        case DIST:
+            for (;;) {
+                here = state->distcode[BITS(state->distbits)];
+                if ((unsigned)(here.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if ((here.op & 0xf0) == 0) {
+                last = here;
+                for (;;) {
+                    here = state->distcode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+                state->back += last.bits;
+            }
+            DROPBITS(here.bits);
+            state->back += here.bits;
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+            state->offset = (unsigned)here.val;
+            state->extra = (unsigned)(here.op) & 15;
+            state->mode = DISTEXT;
+        case DISTEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->offset += BITS(state->extra);
+                DROPBITS(state->extra);
+                state->back += state->extra;
+            }
+#ifdef INFLATE_STRICT
+            if (state->offset > state->dmax) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
+            state->mode = MATCH;
+        case MATCH:
+            if (left == 0) goto inf_leave;
+            copy = out - left;
+            if (state->offset > copy) {         /* copy from window */
+                copy = state->offset - copy;
+                if (copy > state->whave) {
+                    if (state->sane) {
+                        strm->msg = (char *)"invalid distance too far back";
+                        state->mode = BAD;
+                        break;
+                    }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+                    Trace((stderr, "inflate.c too far\n"));
+                    copy -= state->whave;
+                    if (copy > state->length) copy = state->length;
+                    if (copy > left) copy = left;
+                    left -= copy;
+                    state->length -= copy;
+                    do {
+                        *put++ = 0;
+                    } while (--copy);
+                    if (state->length == 0) state->mode = LEN;
+                    break;
+#endif
+                }
+                if (copy > state->wnext) {
+                    copy -= state->wnext;
+                    from = state->window + (state->wsize - copy);
+                }
+                else
+                    from = state->window + (state->wnext - copy);
+                if (copy > state->length) copy = state->length;
+            }
+            else {                              /* copy from output */
+                from = put - state->offset;
+                copy = state->length;
+            }
+            if (copy > left) copy = left;
+            left -= copy;
+            state->length -= copy;
+            do {
+                *put++ = *from++;
+            } while (--copy);
+            if (state->length == 0) state->mode = LEN;
+            break;
+        case LIT:
+            if (left == 0) goto inf_leave;
+            *put++ = (unsigned char)(state->length);
+            left--;
+            state->mode = LEN;
+            break;
+        case CHECK:
+            if (state->wrap) {
+                NEEDBITS(32);
+                out -= left;
+                strm->total_out += out;
+                state->total += out;
+                if (out)
+                    strm->adler = state->check =
+                        UPDATE(state->check, put - out, out);
+                out = left;
+                if ((
+#ifdef GUNZIP
+                     state->flags ? hold :
+#endif
+                     REVERSE(hold)) != state->check) {
+                    strm->msg = (char *)"incorrect data check";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+                Tracev((stderr, "inflate:   check matches trailer\n"));
+            }
+#ifdef GUNZIP
+            state->mode = LENGTH;
+        case LENGTH:
+            if (state->wrap && state->flags) {
+                NEEDBITS(32);
+                if (hold != (state->total & 0xffffffffUL)) {
+                    strm->msg = (char *)"incorrect length check";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+                Tracev((stderr, "inflate:   length matches trailer\n"));
+            }
+#endif
+            state->mode = DONE;
+        case DONE:
+            ret = Z_STREAM_END;
+            goto inf_leave;
+        case BAD:
+            ret = Z_DATA_ERROR;
+            goto inf_leave;
+        case MEM:
+            return Z_MEM_ERROR;
+        case SYNC:
+        default:
+            return Z_STREAM_ERROR;
+        }
+
+    /*
+       Return from inflate(), updating the total counts and the check value.
+       If there was no progress during the inflate() call, return a buffer
+       error.  Call updatewindow() to create and/or update the window state.
+       Note: a memory error from inflate() is non-recoverable.
+     */
+  inf_leave:
+    RESTORE();
+    if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
+        if (updatewindow(strm, out)) {
+            state->mode = MEM;
+            return Z_MEM_ERROR;
+        }
+    in -= strm->avail_in;
+    out -= strm->avail_out;
+    strm->total_in += in;
+    strm->total_out += out;
+    state->total += out;
+    if (state->wrap && out)
+        strm->adler = state->check =
+            UPDATE(state->check, strm->next_out - out, out);
+    strm->data_type = state->bits + (state->last ? 64 : 0) +
+                      (state->mode == TYPE ? 128 : 0) +
+                      (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
+    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+        ret = Z_BUF_ERROR;
+    return ret;
+}
+
+int ZEXPORT inflateEnd(z_streamp strm)
+{
+    struct inflate_state FAR *state;
+    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->window != Z_NULL) ZFREE(strm, state->window);
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+    Tracev((stderr, "inflate: end\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength)
+{
+    struct inflate_state FAR *state;
+    unsigned long id;
+
+    /* check state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->wrap != 0 && state->mode != DICT)
+        return Z_STREAM_ERROR;
+
+    /* check for correct dictionary id */
+    if (state->mode == DICT) {
+        id = adler32(0L, Z_NULL, 0);
+        id = adler32(id, dictionary, dictLength);
+        if (id != state->check)
+            return Z_DATA_ERROR;
+    }
+
+    /* copy dictionary to window */
+    if (updatewindow(strm, strm->avail_out)) {
+        state->mode = MEM;
+        return Z_MEM_ERROR;
+    }
+    if (dictLength > state->wsize) {
+        zmemcpy(state->window, dictionary + dictLength - state->wsize,
+                state->wsize);
+        state->whave = state->wsize;
+    }
+    else {
+        zmemcpy(state->window + state->wsize - dictLength, dictionary,
+                dictLength);
+        state->whave = dictLength;
+    }
+    state->havedict = 1;
+    Tracev((stderr, "inflate:   dictionary set\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head)
+{
+    struct inflate_state FAR *state;
+
+    /* check state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+    /* save header structure */
+    state->head = head;
+    head->done = 0;
+    return Z_OK;
+}
+
+/*
+   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
+   or when out of input.  When called, *have is the number of pattern bytes
+   found in order so far, in 0..3.  On return *have is updated to the new
+   state.  If on return *have equals four, then the pattern was found and the
+   return value is how many bytes were read including the last byte of the
+   pattern.  If *have is less than four, then the pattern has not been found
+   yet and the return value is len.  In the latter case, syncsearch() can be
+   called again with more data and the *have state.  *have is initialized to
+   zero for the first call.
+ */
+local unsigned syncsearch(unsigned FAR *have, unsigned char FAR *buf, unsigned len)
+{
+    unsigned got;
+    unsigned next;
+
+    got = *have;
+    next = 0;
+    while (next < len && got < 4) {
+        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+            got++;
+        else if (buf[next])
+            got = 0;
+        else
+            got = 4 - got;
+        next++;
+    }
+    *have = got;
+    return next;
+}
+
+int ZEXPORT inflateSync(z_streamp strm)
+{
+    unsigned len;               /* number of bytes to look at or looked at */
+    unsigned long in, out;      /* temporary to save total_in and total_out */
+    unsigned char buf[4];       /* to restore bit buffer to byte string */
+    struct inflate_state FAR *state;
+
+    /* check parameters */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+    /* if first time, start search in bit buffer */
+    if (state->mode != SYNC) {
+        state->mode = SYNC;
+        state->hold <<= state->bits & 7;
+        state->bits -= state->bits & 7;
+        len = 0;
+        while (state->bits >= 8) {
+            buf[len++] = (unsigned char)(state->hold);
+            state->hold >>= 8;
+            state->bits -= 8;
+        }
+        state->have = 0;
+        syncsearch(&(state->have), buf, len);
+    }
+
+    /* search available input */
+    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+    strm->avail_in -= len;
+    strm->next_in += len;
+    strm->total_in += len;
+
+    /* return no joy or set up to restart inflate() on a new block */
+    if (state->have != 4) return Z_DATA_ERROR;
+    in = strm->total_in;  out = strm->total_out;
+    inflateReset(strm);
+    strm->total_in = in;  strm->total_out = out;
+    state->mode = TYPE;
+    return Z_OK;
+}
+
+/*
+   Returns true if inflate is currently at the end of a block generated by
+   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+   implementation to provide an additional safety check. PPP uses
+   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+   block. When decompressing, PPP checks that at the end of input packet,
+   inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(z_streamp strm)
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(z_streamp dest, z_streamp source)
+{
+    struct inflate_state FAR *state;
+    struct inflate_state FAR *copy;
+    unsigned char FAR *window;
+    unsigned wsize;
+
+    /* check input */
+    if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
+        source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)source->state;
+
+    /* allocate space */
+    copy = (struct inflate_state FAR *)
+           ZALLOC(source, 1, sizeof(struct inflate_state));
+    if (copy == Z_NULL) return Z_MEM_ERROR;
+    window = Z_NULL;
+    if (state->window != Z_NULL) {
+        window = (unsigned char FAR *)
+                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+        if (window == Z_NULL) {
+            ZFREE(source, copy);
+            return Z_MEM_ERROR;
+        }
+    }
+
+    /* copy state */
+    zmemcpy(dest, source, sizeof(z_stream));
+    zmemcpy(copy, state, sizeof(struct inflate_state));
+    if (state->lencode >= state->codes &&
+        state->lencode <= state->codes + ENOUGH - 1) {
+        copy->lencode = copy->codes + (state->lencode - state->codes);
+        copy->distcode = copy->codes + (state->distcode - state->codes);
+    }
+    copy->next = copy->codes + (state->next - state->codes);
+    if (window != Z_NULL) {
+        wsize = 1U << state->wbits;
+        zmemcpy(window, state->window, wsize);
+    }
+    copy->window = window;
+    dest->state = (struct internal_state FAR *)copy;
+    return Z_OK;
+}
+
+int ZEXPORT inflateUndermine(z_streamp strm, int subvert)
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    state->sane = !subvert;
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+    return Z_OK;
+#else
+    state->sane = 1;
+    return Z_DATA_ERROR;
+#endif
+}
+
+long ZEXPORT inflateMark(z_streamp strm)
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16;
+    state = (struct inflate_state FAR *)strm->state;
+    return ((long)(state->back) << 16) +
+        (state->mode == COPY ? state->length :
+            (state->mode == MATCH ? state->was - state->length : 0));
+}
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/zlib/inflate.h b/abc-build/src/misc/zlib/inflate.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/inflate.h
@@ -0,0 +1,126 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2009 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+ABC_NAMESPACE_HEADER_START
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+   trailer decoding by inflate().  NO_GZIP would be used to avoid linking in
+   the crc code when it is not needed.  For shared libraries, gzip decoding
+   should be left enabled. */
+#ifndef NO_GZIP
+#  define GUNZIP
+#endif
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+    HEAD,       /* i: waiting for magic header */
+    FLAGS,      /* i: waiting for method and flags (gzip) */
+    TIME,       /* i: waiting for modification time (gzip) */
+    OS,         /* i: waiting for extra flags and operating system (gzip) */
+    EXLEN,      /* i: waiting for extra length (gzip) */
+    EXTRA,      /* i: waiting for extra bytes (gzip) */
+    NAME,       /* i: waiting for end of file name (gzip) */
+    COMMENT,    /* i: waiting for end of comment (gzip) */
+    HCRC,       /* i: waiting for header crc (gzip) */
+    DICTID,     /* i: waiting for dictionary check value */
+    DICT,       /* waiting for inflateSetDictionary() call */
+        TYPE,       /* i: waiting for type bits, including last-flag bit */
+        TYPEDO,     /* i: same, but skip check to exit inflate on new block */
+        STORED,     /* i: waiting for stored size (length and complement) */
+        COPY_,      /* i/o: same as COPY below, but only first time in */
+        COPY,       /* i/o: waiting for input or output to copy stored block */
+        TABLE,      /* i: waiting for dynamic block table lengths */
+        LENLENS,    /* i: waiting for code length code lengths */
+        CODELENS,   /* i: waiting for length/lit and distance code lengths */
+            LEN_,       /* i: same as LEN below, but only first time in */
+            LEN,        /* i: waiting for length/lit/eob code */
+            LENEXT,     /* i: waiting for length extra bits */
+            DIST,       /* i: waiting for distance code */
+            DISTEXT,    /* i: waiting for distance extra bits */
+            MATCH,      /* o: waiting for output space to copy string */
+            LIT,        /* o: waiting for output space to write literal */
+    CHECK,      /* i: waiting for 32-bit check value */
+    LENGTH,     /* i: waiting for 32-bit length (gzip) */
+    DONE,       /* finished check, done -- remain here until reset */
+    BAD,        /* got a data error -- remain here until reset */
+    MEM,        /* got an inflate() memory error -- remain here until reset */
+    SYNC        /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+    State transitions between above modes -
+
+    (most modes can go to BAD or MEM on error -- not shown for clarity)
+
+    Process header:
+        HEAD -> (gzip) or (zlib) or (raw)
+        (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
+                  HCRC -> TYPE
+        (zlib) -> DICTID or TYPE
+        DICTID -> DICT -> TYPE
+        (raw) -> TYPEDO
+    Read deflate blocks:
+            TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
+            STORED -> COPY_ -> COPY -> TYPE
+            TABLE -> LENLENS -> CODELENS -> LEN_
+            LEN_ -> LEN
+    Read deflate codes in fixed or dynamic block:
+                LEN -> LENEXT or LIT or TYPE
+                LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+                LIT -> LEN
+    Process trailer:
+        CHECK -> LENGTH -> DONE
+ */
+
+/* state maintained between inflate() calls.  Approximately 10K bytes. */
+struct inflate_state {
+    inflate_mode mode;          /* current inflate mode */
+    int last;                   /* true if processing last block */
+    int wrap;                   /* bit 0 true for zlib, bit 1 true for gzip */
+    int havedict;               /* true if dictionary provided */
+    int flags;                  /* gzip header method and flags (0 if zlib) */
+    unsigned dmax;              /* zlib header max distance (INFLATE_STRICT) */
+    unsigned long check;        /* protected copy of check value */
+    unsigned long total;        /* protected copy of output count */
+    gz_headerp head;            /* where to save gzip header information */
+        /* sliding window */
+    unsigned wbits;             /* log base 2 of requested window size */
+    unsigned wsize;             /* window size or zero if not using window */
+    unsigned whave;             /* valid bytes in the window */
+    unsigned wnext;             /* window write index */
+    unsigned char FAR *window;  /* allocated sliding window, if needed */
+        /* bit accumulator */
+    unsigned long hold;         /* input bit accumulator */
+    unsigned bits;              /* number of bits in "in" */
+        /* for string and stored block copying */
+    unsigned length;            /* literal or length of data to copy */
+    unsigned offset;            /* distance back to copy string from */
+        /* for table and code decoding */
+    unsigned extra;             /* extra bits needed */
+        /* fixed and dynamic code tables */
+    code const FAR *lencode;    /* starting table for length/literal codes */
+    code const FAR *distcode;   /* starting table for distance codes */
+    unsigned lenbits;           /* index bits for lencode */
+    unsigned distbits;          /* index bits for distcode */
+        /* dynamic table building */
+    unsigned ncode;             /* number of code length code lengths */
+    unsigned nlen;              /* number of length code lengths */
+    unsigned ndist;             /* number of distance code lengths */
+    unsigned have;              /* number of code lengths in lens[] */
+    code FAR *next;             /* next available space in codes[] */
+    unsigned short lens[320];   /* temporary storage for code lengths */
+    unsigned short work[288];   /* work area for code table building */
+    code codes[ENOUGH];         /* space for code tables */
+    int sane;                   /* if false, allow invalid distance too far */
+    int back;                   /* bits back of last unprocessed length/lit */
+    unsigned was;               /* initial length of match */
+};
+
+ABC_NAMESPACE_HEADER_END
diff --git a/abc-build/src/misc/zlib/inftrees.c b/abc-build/src/misc/zlib/inftrees.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/inftrees.c
@@ -0,0 +1,337 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc/util/abc_global.h"
+
+#include "zutil.h"
+#include "inftrees.h"
+
+ABC_NAMESPACE_IMPL_START
+
+#define MAXBITS 15
+
+const char inflate_copyright[] =
+   " inflate 1.2.5 Copyright 1995-2010 Mark Adler ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/*
+   Build a set of tables to decode the provided canonical Huffman code.
+   The code lengths are lens[0..codes-1].  The result starts at *table,
+   whose indices are 0..2^bits-1.  work is a writable array of at least
+   lens shorts, which is used as a work area.  type is the type of code
+   to be generated, CODES, LENS, or DISTS.  On return, zero is success,
+   -1 is an invalid code, and +1 means that ENOUGH isn't enough.  table
+   on return points to the next available entry's address.  bits is the
+   requested root table index bits, and on return it is the actual root
+   table index bits.  It will differ if the request is greater than the
+   longest code or if it is less than the shortest code.
+ */
+int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, unsigned codes, code FAR * FAR *table, unsigned FAR *bits, unsigned short FAR *work)
+{
+    unsigned len;               /* a code's length in bits */
+    unsigned sym;               /* index of code symbols */
+    unsigned min, max;          /* minimum and maximum code lengths */
+    unsigned root;              /* number of index bits for root table */
+    unsigned curr;              /* number of index bits for current table */
+    unsigned drop;              /* code bits to drop for sub-table */
+    int left;                   /* number of prefix codes available */
+    unsigned used;              /* code entries in table used */
+    unsigned huff;              /* Huffman code */
+    unsigned incr;              /* for incrementing code, index */
+    unsigned fill;              /* index for replicating entries */
+    unsigned low;               /* low bits for current root entry */
+    unsigned mask;              /* mask for low root bits */
+    code here;                  /* table entry for duplication */
+    code FAR *next;             /* next available space in table */
+    const unsigned short FAR *base;     /* base value table to use */
+    const unsigned short FAR *extra;    /* extra bits table to use */
+    int end;                    /* use base and extra for symbol > end */
+    unsigned short count[MAXBITS+1];    /* number of codes of each length */
+    unsigned short offs[MAXBITS+1];     /* offsets in table for each length */
+    static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+    static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+        16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195};
+    static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577, 0, 0};
+    static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+        16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+        23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+        28, 28, 29, 29, 64, 64};
+
+    /*
+       Process a set of code lengths to create a canonical Huffman code.  The
+       code lengths are lens[0..codes-1].  Each length corresponds to the
+       symbols 0..codes-1.  The Huffman code is generated by first sorting the
+       symbols by length from short to long, and retaining the symbol order
+       for codes with equal lengths.  Then the code starts with all zero bits
+       for the first code of the shortest length, and the codes are integer
+       increments for the same length, and zeros are appended as the length
+       increases.  For the deflate format, these bits are stored backwards
+       from their more natural integer increment ordering, and so when the
+       decoding tables are built in the large loop below, the integer codes
+       are incremented backwards.
+
+       This routine assumes, but does not check, that all of the entries in
+       lens[] are in the range 0..MAXBITS.  The caller must assure this.
+       1..MAXBITS is interpreted as that code length.  zero means that that
+       symbol does not occur in this code.
+
+       The codes are sorted by computing a count of codes for each length,
+       creating from that a table of starting indices for each length in the
+       sorted table, and then entering the symbols in order in the sorted
+       table.  The sorted table is work[], with that space being provided by
+       the caller.
+
+       The length counts are used for other purposes as well, i.e. finding
+       the minimum and maximum length codes, determining if there are any
+       codes at all, checking for a valid set of lengths, and looking ahead
+       at length counts to determine sub-table sizes when building the
+       decoding tables.
+     */
+
+    /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+    for (len = 0; len <= MAXBITS; len++)
+        count[len] = 0;
+    for (sym = 0; sym < codes; sym++)
+        count[lens[sym]]++;
+
+    /* bound code lengths, force root to be within code lengths */
+    root = *bits;
+    for (max = MAXBITS; max >= 1; max--)
+        if (count[max] != 0) break;
+    if (root > max) root = max;
+    if (max == 0) {                     /* no symbols to code at all */
+        here.op = (unsigned char)64;    /* invalid code marker */
+        here.bits = (unsigned char)1;
+        here.val = (unsigned short)0;
+        *(*table)++ = here;             /* make a table to force an error */
+        *(*table)++ = here;
+        *bits = 1;
+        return 0;     /* no symbols, but wait for decoding to report error */
+    }
+    for (min = 1; min < max; min++)
+        if (count[min] != 0) break;
+    if (root < min) root = min;
+
+    /* check for an over-subscribed or incomplete set of lengths */
+    left = 1;
+    for (len = 1; len <= MAXBITS; len++) {
+        left <<= 1;
+        left -= count[len];
+        if (left < 0) return -1;        /* over-subscribed */
+    }
+    if (left > 0 && (type == CODES || max != 1))
+        return -1;                      /* incomplete set */
+
+    /* generate offsets into symbol table for each length for sorting */
+    offs[1] = 0;
+    for (len = 1; len < MAXBITS; len++)
+        offs[len + 1] = offs[len] + count[len];
+
+    /* sort symbols by length, by symbol order within each length */
+    for (sym = 0; sym < codes; sym++)
+        if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+    /*
+       Create and fill in decoding tables.  In this loop, the table being
+       filled is at next and has curr index bits.  The code being used is huff
+       with length len.  That code is converted to an index by dropping drop
+       bits off of the bottom.  For codes where len is less than drop + curr,
+       those top drop + curr - len bits are incremented through all values to
+       fill the table with replicated entries.
+
+       root is the number of index bits for the root table.  When len exceeds
+       root, sub-tables are created pointed to by the root entry with an index
+       of the low root bits of huff.  This is saved in low to check for when a
+       new sub-table should be started.  drop is zero when the root table is
+       being filled, and drop is root when sub-tables are being filled.
+
+       When a new sub-table is needed, it is necessary to look ahead in the
+       code lengths to determine what size sub-table is needed.  The length
+       counts are used for this, and so count[] is decremented as codes are
+       entered in the tables.
+
+       used keeps track of how many table entries have been allocated from the
+       provided *table space.  It is checked for LENS and DIST tables against
+       the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
+       the initial root table size constants.  See the comments in inftrees.h
+       for more information.
+
+       sym increments through all symbols, and the loop terminates when
+       all codes of length max, i.e. all codes, have been processed.  This
+       routine permits incomplete codes, so another loop after this one fills
+       in the rest of the decoding tables with invalid code markers.
+     */
+
+    /* set up for code type */
+    switch (type) {
+    case CODES:
+        base = extra = work;    /* dummy value--not used */
+        end = 19;
+        break;
+    case LENS:
+        base = lbase;
+        base -= 257;
+        extra = lext;
+        extra -= 257;
+        end = 256;
+        break;
+    default:            /* DISTS */
+        base = dbase;
+        extra = dext;
+        end = -1;
+    }
+
+    /* initialize state for loop */
+    huff = 0;                   /* starting code */
+    sym = 0;                    /* starting code symbol */
+    len = min;                  /* starting code length */
+    next = *table;              /* current table to fill in */
+    curr = root;                /* current table index bits */
+    drop = 0;                   /* current bits to drop from code for index */
+    low = (unsigned)(-1);       /* trigger new sub-table when len > root */
+    used = 1U << root;          /* use root table entries */
+    mask = used - 1;            /* mask for comparing low */
+
+    /* check available table space */
+    if ((type == LENS && used >= ENOUGH_LENS) ||
+        (type == DISTS && used >= ENOUGH_DISTS))
+        return 1;
+
+    /* process all codes and make table entries */
+    for (;;) {
+        /* create table entry */
+        here.bits = (unsigned char)(len - drop);
+        if ((int)(work[sym]) < end) {
+            here.op = (unsigned char)0;
+            here.val = work[sym];
+        }
+        else if ((int)(work[sym]) > end) {
+            here.op = (unsigned char)(extra[work[sym]]);
+            here.val = base[work[sym]];
+        }
+        else {
+            here.op = (unsigned char)(32 + 64);         /* end of block */
+            here.val = 0;
+        }
+
+        /* replicate for those indices with low len bits equal to huff */
+        incr = 1U << (len - drop);
+        fill = 1U << curr;
+        min = fill;                 /* save offset to next table */
+        do {
+            fill -= incr;
+            next[(huff >> drop) + fill] = here;
+        } while (fill != 0);
+
+        /* backwards increment the len-bit code huff */
+        incr = 1U << (len - 1);
+        while (huff & incr)
+            incr >>= 1;
+        if (incr != 0) {
+            huff &= incr - 1;
+            huff += incr;
+        }
+        else
+            huff = 0;
+
+        /* go to next symbol, update count, len */
+        sym++;
+        if (--(count[len]) == 0) {
+            if (len == max) break;
+            len = lens[work[sym]];
+        }
+
+        /* create new sub-table if needed */
+        if (len > root && (huff & mask) != low) {
+            /* if first time, transition to sub-tables */
+            if (drop == 0)
+                drop = root;
+
+            /* increment past last table */
+            next += min;            /* here min is 1 << curr */
+
+            /* determine length of next table */
+            curr = len - drop;
+            left = (int)(1 << curr);
+            while (curr + drop < max) {
+                left -= count[curr + drop];
+                if (left <= 0) break;
+                curr++;
+                left <<= 1;
+            }
+
+            /* check for enough space */
+            used += 1U << curr;
+            if ((type == LENS && used >= ENOUGH_LENS) ||
+                (type == DISTS && used >= ENOUGH_DISTS))
+                return 1;
+
+            /* point entry in root table to sub-table */
+            low = huff & mask;
+            (*table)[low].op = (unsigned char)curr;
+            (*table)[low].bits = (unsigned char)root;
+            (*table)[low].val = (unsigned short)(next - *table);
+        }
+    }
+
+    /*
+       Fill in rest of table for incomplete codes.  This loop is similar to the
+       loop above in incrementing huff for table indices.  It is assumed that
+       len is equal to curr + drop, so there is no loop needed to increment
+       through high index bits.  When the current sub-table is filled, the loop
+       drops back to the root table to fill in any remaining entries there.
+     */
+    here.op = (unsigned char)64;                /* invalid code marker */
+    here.bits = (unsigned char)(len - drop);
+    here.val = (unsigned short)0;
+    while (huff != 0) {
+        /* when done with sub-table, drop back to root table */
+        if (drop != 0 && (huff & mask) != low) {
+            drop = 0;
+            len = root;
+            next = *table;
+            here.bits = (unsigned char)len;
+        }
+
+        /* put invalid code marker in table */
+        next[huff >> drop] = here;
+
+        /* backwards increment the len-bit code huff */
+        incr = 1U << (len - 1);
+        while (huff & incr)
+            incr >>= 1;
+        if (incr != 0) {
+            huff &= incr - 1;
+            huff += incr;
+        }
+        else
+            huff = 0;
+    }
+
+    /* set return parameters */
+    *table += used;
+    *bits = root;
+    return 0;
+}
+
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/misc/zlib/inftrees.h b/abc-build/src/misc/zlib/inftrees.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/inftrees.h
@@ -0,0 +1,66 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2005, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+ABC_NAMESPACE_HEADER_START
+
+/* Structure for decoding tables.  Each entry provides either the
+   information needed to do the operation requested by the code that
+   indexed that table entry, or it provides a pointer to another
+   table that indexes more bits of the code.  op indicates whether
+   the entry is a pointer to another table, a literal, a length or
+   distance, an end-of-block, or an invalid code.  For a table
+   pointer, the low four bits of op is the number of index bits of
+   that table.  For a length or distance, the low four bits of op
+   is the number of extra bits to get after the code.  bits is
+   the number of bits in this code or part of the code to drop off
+   of the bit buffer.  val is the actual byte to output in the case
+   of a literal, the base length or distance, or the offset from
+   the current table to the next table.  Each entry is four bytes. */
+typedef struct {
+    unsigned char op;           /* operation, extra bits, table bits */
+    unsigned char bits;         /* bits in this part of the code */
+    unsigned short val;         /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+    00000000 - literal
+    0000tttt - table link, tttt != 0 is the number of table index bits
+    0001eeee - length or distance, eeee is the number of extra bits
+    01100000 - end of block
+    01000000 - invalid code
+ */
+
+/* Maximum size of the dynamic table.  The maximum number of code structures is
+   1444, which is the sum of 852 for literal/length codes and 592 for distance
+   codes.  These values were found by exhaustive searches using the program
+   examples/enough.c found in the zlib distribtution.  The arguments to that
+   program are the number of symbols, the initial root table size, and the
+   maximum bit length of a code.  "enough 286 9 15" for literal/length codes
+   returns returns 852, and "enough 30 6 15" for distance codes returns 592.
+   The initial root table size (9 or 6) is found in the fifth argument of the
+   inflate_table() calls in inflate.c and infback.c.  If the root table size is
+   changed, then these maximum sizes would be need to be recalculated and
+   updated. */
+#define ENOUGH_LENS 852
+#define ENOUGH_DISTS 592
+#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
+
+/* Type of code to build for inflate_table() */
+typedef enum {
+    CODES,
+    LENS,
+    DISTS
+} codetype;
+
+int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
+                             unsigned codes, code FAR * FAR *table,
+                             unsigned FAR *bits, unsigned short FAR *work));
+
+ABC_NAMESPACE_HEADER_END
diff --git a/abc-build/src/misc/zlib/license b/abc-build/src/misc/zlib/license
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/license
@@ -0,0 +1,31 @@
+Copyright notice:
+
+ (C) 1995-2010 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not* receiving
+lengthy legal documents to sign.  The sources are provided for free but without
+warranty of any kind.  The library has been entirely written by Jean-loup
+Gailly and Mark Adler; it does not include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include in
+the file ChangeLog history information documenting your changes.  Please read
+the FAQ for more information on the distribution of modified source versions.
diff --git a/abc-build/src/misc/zlib/link.txt b/abc-build/src/misc/zlib/link.txt
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/link.txt
@@ -0,0 +1,1 @@
+http://www.zlib.net/
diff --git a/abc-build/src/misc/zlib/module.make b/abc-build/src/misc/zlib/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/module.make
@@ -0,0 +1,15 @@
+SRC +=	src/misc/zlib/adler32.c \
+	src/misc/zlib/compress_.c \
+	src/misc/zlib/crc32.c \
+	src/misc/zlib/deflate.c \
+	src/misc/zlib/gzclose.c \
+	src/misc/zlib/gzlib.c \
+	src/misc/zlib/gzread.c \
+	src/misc/zlib/gzwrite.c \
+	src/misc/zlib/infback.c \
+	src/misc/zlib/inffast.c \
+	src/misc/zlib/inflate.c \
+	src/misc/zlib/inftrees.c \
+	src/misc/zlib/trees.c \
+	src/misc/zlib/uncompr.c \
+	src/misc/zlib/zutil.c
diff --git a/abc-build/src/misc/zlib/trees.c b/abc-build/src/misc/zlib/trees.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/trees.c
@@ -0,0 +1,1216 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-2010 Jean-loup Gailly
+ * detect_data_type() function provided freely by Cosmin Truta, 2006
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ *  ALGORITHM
+ *
+ *      The "deflation" process uses several Huffman trees. The more
+ *      common source values are represented by shorter bit sequences.
+ *
+ *      Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values).  The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ *  REFERENCES
+ *
+ *      Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ *      Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ *      Storer, James A.
+ *          Data Compression:  Methods and Theory, pp. 49-50.
+ *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.
+ *
+ *      Sedgewick, R.
+ *          Algorithms, p290.
+ *          Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* @(#) $Id$ */
+
+/* #define GEN_TREES_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc/util/abc_global.h"
+
+#include "deflate.h"
+
+#ifdef DEBUG
+#  include <ctype.h>
+#endif
+
+ABC_NAMESPACE_IMPL_START
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6      16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10    17
+/* repeat a zero length 3-10 times  (3 bits of repeat count) */
+
+#define REPZ_11_138  18
+/* repeat a zero length 11-138 times  (7 bits of repeat count) */
+
+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+   = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local const int extra_dbits[D_CODES] /* extra bits for each distance code */
+   = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local const uch bl_order[BL_CODES]
+   = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+#define DIST_CODE_LEN  512 /* see definition of array dist_code below */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+/* non ANSI compilers may not accept trees.h */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+uch _dist_code[DIST_CODE_LEN];
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+uch _length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#else
+ABC_NAMESPACE_IMPL_END
+#  include "trees.h"
+ABC_NAMESPACE_IMPL_START
+#endif /* GEN_TREES_H */
+
+struct static_tree_desc_s {
+    const ct_data *static_tree;  /* static tree or NULL */
+    const intf *extra_bits;      /* extra bits for each code or NULL */
+    int     extra_base;          /* base index for extra_bits */
+    int     elems;               /* max number of elements in the tree */
+    int     max_length;          /* max bit length for the codes */
+};
+
+local static_tree_desc  static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local static_tree_desc  static_d_desc =
+{static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS};
+
+local static_tree_desc  static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0,   BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void tr_static_init OF((void));
+local void init_block     OF((deflate_state *s));
+local void pqdownheap     OF((deflate_state *s, ct_data *tree, int k));
+local void gen_bitlen     OF((deflate_state *s, tree_desc *desc));
+local void gen_codes      OF((ct_data *tree, int max_code, ushf *bl_count));
+local void build_tree     OF((deflate_state *s, tree_desc *desc));
+local void scan_tree      OF((deflate_state *s, ct_data *tree, int max_code));
+local void send_tree      OF((deflate_state *s, ct_data *tree, int max_code));
+local int  build_bl_tree  OF((deflate_state *s));
+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
+                              int blcodes));
+local void compress_block OF((deflate_state *s, ct_data *ltree,
+                              ct_data *dtree));
+local int  detect_data_type OF((deflate_state *s));
+local unsigned bi_reverse OF((unsigned value, int length));
+local void bi_windup      OF((deflate_state *s));
+local void bi_flush       OF((deflate_state *s));
+local void copy_block     OF((deflate_state *s, charf *buf, unsigned len,
+                              int header));
+
+#ifdef GEN_TREES_H
+local void gen_trees_header OF((void));
+#endif
+
+#ifndef DEBUG
+#  define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+   /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+#  define send_code(s, c, tree) \
+     { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+       send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+    put_byte(s, (uch)((w) & 0xff)); \
+    put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef DEBUG
+local void send_bits      OF((deflate_state *s, int value, int length));
+
+local void send_bits(deflate_state *s, int value, int length)
+{
+    Tracevv((stderr," l %2d v %4x ", length, value));
+    Assert(length > 0 && length <= 15, "invalid length");
+    s->bits_sent += (ulg)length;
+
+    /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+     * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+     * unused bits in value.
+     */
+    if (s->bi_valid > (int)Buf_size - length) {
+        s->bi_buf |= (ush)value << s->bi_valid;
+        put_short(s, s->bi_buf);
+        s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+        s->bi_valid += length - Buf_size;
+    } else {
+        s->bi_buf |= (ush)value << s->bi_valid;
+        s->bi_valid += length;
+    }
+}
+#else /* !DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+  if (s->bi_valid > (int)Buf_size - len) {\
+    int val = value;\
+    s->bi_buf |= (ush)val << s->bi_valid;\
+    put_short(s, s->bi_buf);\
+    s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+    s->bi_valid += len - Buf_size;\
+  } else {\
+    s->bi_buf |= (ush)(value) << s->bi_valid;\
+    s->bi_valid += len;\
+  }\
+}
+#endif /* DEBUG */
+
+
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+local void tr_static_init()
+{
+#if defined(GEN_TREES_H) || !defined(STDC)
+    static int static_init_done = 0;
+    int n;        /* iterates over tree elements */
+    int bits;     /* bit counter */
+    int length;   /* length value */
+    int code;     /* code value */
+    int dist;     /* distance index */
+    ush bl_count[MAX_BITS+1];
+    /* number of codes at each bit length for an optimal tree */
+
+    if (static_init_done) return;
+
+    /* For some embedded targets, global variables are not initialized: */
+#ifdef NO_INIT_GLOBAL_POINTERS
+    static_l_desc.static_tree = static_ltree;
+    static_l_desc.extra_bits = extra_lbits;
+    static_d_desc.static_tree = static_dtree;
+    static_d_desc.extra_bits = extra_dbits;
+    static_bl_desc.extra_bits = extra_blbits;
+#endif
+
+    /* Initialize the mapping length (0..255) -> length code (0..28) */
+    length = 0;
+    for (code = 0; code < LENGTH_CODES-1; code++) {
+        base_length[code] = length;
+        for (n = 0; n < (1<<extra_lbits[code]); n++) {
+            _length_code[length++] = (uch)code;
+        }
+    }
+    Assert (length == 256, "tr_static_init: length != 256");
+    /* Note that the length 255 (match length 258) can be represented
+     * in two different ways: code 284 + 5 bits or code 285, so we
+     * overwrite length_code[255] to use the best encoding:
+     */
+    _length_code[length-1] = (uch)code;
+
+    /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+    dist = 0;
+    for (code = 0 ; code < 16; code++) {
+        base_dist[code] = dist;
+        for (n = 0; n < (1<<extra_dbits[code]); n++) {
+            _dist_code[dist++] = (uch)code;
+        }
+    }
+    Assert (dist == 256, "tr_static_init: dist != 256");
+    dist >>= 7; /* from now on, all distances are divided by 128 */
+    for ( ; code < D_CODES; code++) {
+        base_dist[code] = dist << 7;
+        for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+            _dist_code[256 + dist++] = (uch)code;
+        }
+    }
+    Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+    /* Construct the codes of the static literal tree */
+    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+    n = 0;
+    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+    while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+    /* Codes 286 and 287 do not exist, but we must include them in the
+     * tree construction to get a canonical Huffman tree (longest code
+     * all ones)
+     */
+    gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+    /* The static distance tree is trivial: */
+    for (n = 0; n < D_CODES; n++) {
+        static_dtree[n].Len = 5;
+        static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+    }
+    static_init_done = 1;
+
+#  ifdef GEN_TREES_H
+    gen_trees_header();
+#  endif
+#endif /* defined(GEN_TREES_H) || !defined(STDC) */
+}
+
+/* ===========================================================================
+ * Genererate the file trees.h describing the static trees.
+ */
+#ifdef GEN_TREES_H
+#  ifndef DEBUG
+ABC_NAMESPACE_IMPL_END
+#    include <stdio.h>
+ABC_NAMESPACE_IMPL_START
+#  endif
+
+#  define SEPARATOR(i, last, width) \
+      ((i) == (last)? "\n};\n\n" :    \
+       ((i) % (width) == (width)-1 ? ",\n" : ", "))
+
+void gen_trees_header()
+{
+    FILE *header = fopen("trees.h", "w");
+    int i;
+
+    Assert (header != NULL, "Can't open trees.h");
+    fprintf(header,
+            "/* header created automatically with -DGEN_TREES_H */\n\n");
+
+    fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
+    for (i = 0; i < L_CODES+2; i++) {
+        fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
+                static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
+    }
+
+    fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
+    for (i = 0; i < D_CODES; i++) {
+        fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+                static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
+    }
+
+    fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n");
+    for (i = 0; i < DIST_CODE_LEN; i++) {
+        fprintf(header, "%2u%s", _dist_code[i],
+                SEPARATOR(i, DIST_CODE_LEN-1, 20));
+    }
+
+    fprintf(header,
+        "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+    for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
+        fprintf(header, "%2u%s", _length_code[i],
+                SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
+    }
+
+    fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
+    for (i = 0; i < LENGTH_CODES; i++) {
+        fprintf(header, "%1u%s", base_length[i],
+                SEPARATOR(i, LENGTH_CODES-1, 20));
+    }
+
+    fprintf(header, "local const int base_dist[D_CODES] = {\n");
+    for (i = 0; i < D_CODES; i++) {
+        fprintf(header, "%5u%s", base_dist[i],
+                SEPARATOR(i, D_CODES-1, 10));
+    }
+
+    fclose(header);
+}
+#endif /* GEN_TREES_H */
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void ZLIB_INTERNAL _tr_init(deflate_state *s)
+{
+    tr_static_init();
+
+    s->l_desc.dyn_tree = s->dyn_ltree;
+    s->l_desc.stat_desc = &static_l_desc;
+
+    s->d_desc.dyn_tree = s->dyn_dtree;
+    s->d_desc.stat_desc = &static_d_desc;
+
+    s->bl_desc.dyn_tree = s->bl_tree;
+    s->bl_desc.stat_desc = &static_bl_desc;
+
+    s->bi_buf = 0;
+    s->bi_valid = 0;
+    s->last_eob_len = 8; /* enough lookahead for inflate */
+#ifdef DEBUG
+    s->compressed_len = 0L;
+    s->bits_sent = 0L;
+#endif
+
+    /* Initialize the first block of the first file: */
+    init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(deflate_state *s)
+{
+    int n; /* iterates over tree elements */
+
+    /* Initialize the trees. */
+    for (n = 0; n < L_CODES;  n++) s->dyn_ltree[n].Freq = 0;
+    for (n = 0; n < D_CODES;  n++) s->dyn_dtree[n].Freq = 0;
+    for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+    s->dyn_ltree[END_BLOCK].Freq = 1;
+    s->opt_len = s->static_len = 0L;
+    s->last_lit = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+    top = s->heap[SMALLEST]; \
+    s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+    pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+   (tree[n].Freq < tree[m].Freq || \
+   (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(deflate_state *s, ct_data *tree, int k)
+{
+    int v = s->heap[k];
+    int j = k << 1;  /* left son of k */
+    while (j <= s->heap_len) {
+        /* Set j to the smallest of the two sons: */
+        if (j < s->heap_len &&
+            smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+            j++;
+        }
+        /* Exit if v is smaller than both sons */
+        if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+        /* Exchange v with the smallest son */
+        s->heap[k] = s->heap[j];  k = j;
+
+        /* And continue down the tree, setting j to the left son of k */
+        j <<= 1;
+    }
+    s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ *    above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ *     array bl_count contains the frequencies for each bit length.
+ *     The length opt_len is updated; static_len is also updated if stree is
+ *     not null.
+ */
+local void gen_bitlen(deflate_state *s, tree_desc *desc)
+{
+    ct_data *tree        = desc->dyn_tree;
+    int max_code         = desc->max_code;
+    const ct_data *stree = desc->stat_desc->static_tree;
+    const intf *extra    = desc->stat_desc->extra_bits;
+    int base             = desc->stat_desc->extra_base;
+    int max_length       = desc->stat_desc->max_length;
+    int h;              /* heap index */
+    int n, m;           /* iterate over the tree elements */
+    int bits;           /* bit length */
+    int xbits;          /* extra bits */
+    ush f;              /* frequency */
+    int overflow = 0;   /* number of elements with bit length too large */
+
+    for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+    /* In a first pass, compute the optimal bit lengths (which may
+     * overflow in the case of the bit length tree).
+     */
+    tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+    for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+        n = s->heap[h];
+        bits = tree[tree[n].Dad].Len + 1;
+        if (bits > max_length) bits = max_length, overflow++;
+        tree[n].Len = (ush)bits;
+        /* We overwrite tree[n].Dad which is no longer needed */
+
+        if (n > max_code) continue; /* not a leaf node */
+
+        s->bl_count[bits]++;
+        xbits = 0;
+        if (n >= base) xbits = extra[n-base];
+        f = tree[n].Freq;
+        s->opt_len += (ulg)f * (bits + xbits);
+        if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
+    }
+    if (overflow == 0) return;
+
+    Trace((stderr,"\nbit length overflow\n"));
+    /* This happens for example on obj2 and pic of the Calgary corpus */
+
+    /* Find the first bit length which could increase: */
+    do {
+        bits = max_length-1;
+        while (s->bl_count[bits] == 0) bits--;
+        s->bl_count[bits]--;      /* move one leaf down the tree */
+        s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+        s->bl_count[max_length]--;
+        /* The brother of the overflow item also moves one step up,
+         * but this does not affect bl_count[max_length]
+         */
+        overflow -= 2;
+    } while (overflow > 0);
+
+    /* Now recompute all bit lengths, scanning in increasing frequency.
+     * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+     * lengths instead of fixing only the wrong ones. This idea is taken
+     * from 'ar' written by Haruhiko Okumura.)
+     */
+    for (bits = max_length; bits != 0; bits--) {
+        n = s->bl_count[bits];
+        while (n != 0) {
+            m = s->heap[--h];
+            if (m > max_code) continue;
+            if ((unsigned) tree[m].Len != (unsigned) bits) {
+                Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+                s->opt_len += ((long)bits - (long)tree[m].Len)
+                              *(long)tree[m].Freq;
+                tree[m].Len = (ush)bits;
+            }
+            n--;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ *     zero code length.
+ */
+local void gen_codes (ct_data *tree, int max_code, ushf *bl_count)
+                /* the tree to decorate */
+                /* largest code with non zero frequency */
+                /* number of codes at each bit length */
+{
+    ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+    ush code = 0;              /* running code value */
+    int bits;                  /* bit index */
+    int n;                     /* code index */
+
+    /* The distribution counts are first used to generate the code values
+     * without bit reversal.
+     */
+    for (bits = 1; bits <= MAX_BITS; bits++) {
+        next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+    }
+    /* Check that the bit counts in bl_count are consistent. The last code
+     * must be all ones.
+     */
+    Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+            "inconsistent bit counts");
+    Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+    for (n = 0;  n <= max_code; n++) {
+        int len = tree[n].Len;
+        if (len == 0) continue;
+        /* Now reverse the bits */
+        tree[n].Code = bi_reverse(next_code[len]++, len);
+
+        Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+             n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+    }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ *     and corresponding code. The length opt_len is updated; static_len is
+ *     also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(deflate_state *s, tree_desc *desc)
+{
+    ct_data *tree         = desc->dyn_tree;
+    const ct_data *stree  = desc->stat_desc->static_tree;
+    int elems             = desc->stat_desc->elems;
+    int n, m;          /* iterate over heap elements */
+    int max_code = -1; /* largest code with non zero frequency */
+    int node;          /* new node being created */
+
+    /* Construct the initial heap, with least frequent element in
+     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+     * heap[0] is not used.
+     */
+    s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+    for (n = 0; n < elems; n++) {
+        if (tree[n].Freq != 0) {
+            s->heap[++(s->heap_len)] = max_code = n;
+            s->depth[n] = 0;
+        } else {
+            tree[n].Len = 0;
+        }
+    }
+
+    /* The pkzip format requires that at least one distance code exists,
+     * and that at least one bit should be sent even if there is only one
+     * possible code. So to avoid special checks later on we force at least
+     * two codes of non zero frequency.
+     */
+    while (s->heap_len < 2) {
+        node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+        tree[node].Freq = 1;
+        s->depth[node] = 0;
+        s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+        /* node is 0 or 1 so it does not have extra bits */
+    }
+    desc->max_code = max_code;
+
+    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+     * establish sub-heaps of increasing lengths:
+     */
+    for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+    /* Construct the Huffman tree by repeatedly combining the least two
+     * frequent nodes.
+     */
+    node = elems;              /* next internal node of the tree */
+    do {
+        pqremove(s, tree, n);  /* n = node of least frequency */
+        m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+        s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+        s->heap[--(s->heap_max)] = m;
+
+        /* Create a new node father of n and m */
+        tree[node].Freq = tree[n].Freq + tree[m].Freq;
+        s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
+                                s->depth[n] : s->depth[m]) + 1);
+        tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+        if (tree == s->bl_tree) {
+            fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+        }
+#endif
+        /* and insert the new node in the heap */
+        s->heap[SMALLEST] = node++;
+        pqdownheap(s, tree, SMALLEST);
+
+    } while (s->heap_len >= 2);
+
+    s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+    /* At this point, the fields freq and dad are set. We can now
+     * generate the bit lengths.
+     */
+    gen_bitlen(s, (tree_desc *)desc);
+
+    /* The field len is now set, we can generate the bit codes */
+    gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree (deflate_state *s, ct_data *tree, int max_code)
+{
+    int n;                     /* iterates over all tree elements */
+    int prevlen = -1;          /* last emitted length */
+    int curlen;                /* length of current code */
+    int nextlen = tree[0].Len; /* length of next code */
+    int count = 0;             /* repeat count of the current code */
+    int max_count = 7;         /* max repeat count */
+    int min_count = 4;         /* min repeat count */
+
+    if (nextlen == 0) max_count = 138, min_count = 3;
+    tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+    for (n = 0; n <= max_code; n++) {
+        curlen = nextlen; nextlen = tree[n+1].Len;
+        if (++count < max_count && curlen == nextlen) {
+            continue;
+        } else if (count < min_count) {
+            s->bl_tree[curlen].Freq += count;
+        } else if (curlen != 0) {
+            if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+            s->bl_tree[REP_3_6].Freq++;
+        } else if (count <= 10) {
+            s->bl_tree[REPZ_3_10].Freq++;
+        } else {
+            s->bl_tree[REPZ_11_138].Freq++;
+        }
+        count = 0; prevlen = curlen;
+        if (nextlen == 0) {
+            max_count = 138, min_count = 3;
+        } else if (curlen == nextlen) {
+            max_count = 6, min_count = 3;
+        } else {
+            max_count = 7, min_count = 4;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (deflate_state *s, ct_data *tree, int max_code)
+{
+    int n;                     /* iterates over all tree elements */
+    int prevlen = -1;          /* last emitted length */
+    int curlen;                /* length of current code */
+    int nextlen = tree[0].Len; /* length of next code */
+    int count = 0;             /* repeat count of the current code */
+    int max_count = 7;         /* max repeat count */
+    int min_count = 4;         /* min repeat count */
+
+    /* tree[max_code+1].Len = -1; */  /* guard already set */
+    if (nextlen == 0) max_count = 138, min_count = 3;
+
+    for (n = 0; n <= max_code; n++) {
+        curlen = nextlen; nextlen = tree[n+1].Len;
+        if (++count < max_count && curlen == nextlen) {
+            continue;
+        } else if (count < min_count) {
+            do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+        } else if (curlen != 0) {
+            if (curlen != prevlen) {
+                send_code(s, curlen, s->bl_tree); count--;
+            }
+            Assert(count >= 3 && count <= 6, " 3_6?");
+            send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+
+        } else if (count <= 10) {
+            send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+
+        } else {
+            send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+        }
+        count = 0; prevlen = curlen;
+        if (nextlen == 0) {
+            max_count = 138, min_count = 3;
+        } else if (curlen == nextlen) {
+            max_count = 6, min_count = 3;
+        } else {
+            max_count = 7, min_count = 4;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(deflate_state *s)
+{
+    int max_blindex;  /* index of last bit length code of non zero freq */
+
+    /* Determine the bit length frequencies for literal and distance trees */
+    scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+    scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+    /* Build the bit length tree: */
+    build_tree(s, (tree_desc *)(&(s->bl_desc)));
+    /* opt_len now includes the length of the tree representations, except
+     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+     */
+
+    /* Determine the number of bit length codes to send. The pkzip format
+     * requires that at least 4 bit length codes be sent. (appnote.txt says
+     * 3 but the actual value used is 4.)
+     */
+    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+        if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+    }
+    /* Update opt_len to include the bit length tree and counts */
+    s->opt_len += 3*(max_blindex+1) + 5+5+4;
+    Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+            s->opt_len, s->static_len));
+
+    return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(deflate_state *s, int lcodes, int dcodes, int blcodes)
+{
+    int rank;                    /* index in bl_order */
+
+    Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+    Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+            "too many codes");
+    Tracev((stderr, "\nbl counts: "));
+    send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+    send_bits(s, dcodes-1,   5);
+    send_bits(s, blcodes-4,  4); /* not -3 as stated in appnote.txt */
+    for (rank = 0; rank < blcodes; rank++) {
+        Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+        send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+    }
+    Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+    send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+    Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+    send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+    Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf, ulg stored_len, int last)
+{
+    send_bits(s, (STORED_BLOCK<<1)+last, 3);    /* send block type */
+#ifdef DEBUG
+    s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+    s->compressed_len += (stored_len + 4) << 3;
+#endif
+    copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ * The current inflate code requires 9 bits of lookahead. If the
+ * last two codes for the previous block (real code plus EOB) were coded
+ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ * the last real code. In this case we send two empty static blocks instead
+ * of one. (There are no problems if the previous block is stored or fixed.)
+ * To simplify the code, we assume the worst case of last real code encoded
+ * on one bit only.
+ */
+void ZLIB_INTERNAL _tr_align(deflate_state *s)
+{
+    send_bits(s, STATIC_TREES<<1, 3);
+    send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+    s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+#endif
+    bi_flush(s);
+    /* Of the 10 bits for the empty block, we have already sent
+     * (10 - bi_valid) bits. The lookahead for the last real code (before
+     * the EOB of the previous block) was thus at least one plus the length
+     * of the EOB plus what we have just sent of the empty static block.
+     */
+    if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
+        send_bits(s, STATIC_TREES<<1, 3);
+        send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+        s->compressed_len += 10L;
+#endif
+        bi_flush(s);
+    }
+    s->last_eob_len = 7;
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file.
+ */
+void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int last)
+{
+    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+    int max_blindex = 0;  /* index of last bit length code of non zero freq */
+
+    /* Build the Huffman trees unless a stored block is forced */
+    if (s->level > 0) {
+
+        /* Check if the file is binary or text */
+        if (s->strm->data_type == Z_UNKNOWN)
+            s->strm->data_type = detect_data_type(s);
+
+        /* Construct the literal and distance trees */
+        build_tree(s, (tree_desc *)(&(s->l_desc)));
+        Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+                s->static_len));
+
+        build_tree(s, (tree_desc *)(&(s->d_desc)));
+        Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+                s->static_len));
+        /* At this point, opt_len and static_len are the total bit lengths of
+         * the compressed block data, excluding the tree representations.
+         */
+
+        /* Build the bit length tree for the above two trees, and get the index
+         * in bl_order of the last bit length code to send.
+         */
+        max_blindex = build_bl_tree(s);
+
+        /* Determine the best encoding. Compute the block lengths in bytes. */
+        opt_lenb = (s->opt_len+3+7)>>3;
+        static_lenb = (s->static_len+3+7)>>3;
+
+        Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+                opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+                s->last_lit));
+
+        if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+    } else {
+        Assert(buf != (char*)0, "lost buf");
+        opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+    }
+
+#ifdef FORCE_STORED
+    if (buf != (char*)0) { /* force stored block */
+#else
+    if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+                       /* 4: two words for the lengths */
+#endif
+        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+         * Otherwise we can't have processed more than WSIZE input bytes since
+         * the last block flush, because compression would have been
+         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+         * transform a block into a stored block.
+         */
+        _tr_stored_block(s, buf, stored_len, last);
+
+#ifdef FORCE_STATIC
+    } else if (static_lenb >= 0) { /* force static trees */
+#else
+    } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
+#endif
+        send_bits(s, (STATIC_TREES<<1)+last, 3);
+        compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+#ifdef DEBUG
+        s->compressed_len += 3 + s->static_len;
+#endif
+    } else {
+        send_bits(s, (DYN_TREES<<1)+last, 3);
+        send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
+                       max_blindex+1);
+        compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+#ifdef DEBUG
+        s->compressed_len += 3 + s->opt_len;
+#endif
+    }
+    Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+    /* The above check is made mod 2^32, for files larger than 512 MB
+     * and uLong implemented on 32 bits.
+     */
+    init_block(s);
+
+    if (last) {
+        bi_windup(s);
+#ifdef DEBUG
+        s->compressed_len += 7;  /* align on byte boundary */
+#endif
+    }
+    Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+           s->compressed_len-7*last));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int ZLIB_INTERNAL _tr_tally (deflate_state *s, unsigned dist, unsigned lc)
+{
+    s->d_buf[s->last_lit] = (ush)dist;
+    s->l_buf[s->last_lit++] = (uch)lc;
+    if (dist == 0) {
+        /* lc is the unmatched char */
+        s->dyn_ltree[lc].Freq++;
+    } else {
+        s->matches++;
+        /* Here, lc is the match length - MIN_MATCH */
+        dist--;             /* dist = match distance - 1 */
+        Assert((ush)dist < (ush)MAX_DIST(s) &&
+               (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+               (ush)d_code(dist) < (ush)D_CODES,  "_tr_tally: bad match");
+
+        s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
+        s->dyn_dtree[d_code(dist)].Freq++;
+    }
+
+#ifdef TRUNCATE_BLOCK
+    /* Try to guess if it is profitable to stop the current block here */
+    if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
+        /* Compute an upper bound for the compressed length */
+        ulg out_length = (ulg)s->last_lit*8L;
+        ulg in_length = (ulg)((long)s->strstart - s->block_start);
+        int dcode;
+        for (dcode = 0; dcode < D_CODES; dcode++) {
+            out_length += (ulg)s->dyn_dtree[dcode].Freq *
+                (5L+extra_dbits[dcode]);
+        }
+        out_length >>= 3;
+        Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+               s->last_lit, in_length, out_length,
+               100L - out_length*100L/in_length));
+        if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
+    }
+#endif
+    return (s->last_lit == s->lit_bufsize-1);
+    /* We avoid equality with lit_bufsize because of wraparound at 64K
+     * on 16 bit machines and because stored blocks are restricted to
+     * 64K-1 bytes.
+     */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(deflate_state *s, ct_data *ltree, ct_data *dtree)
+{
+    unsigned dist;      /* distance of matched string */
+    int lc;             /* match length or unmatched char (if dist == 0) */
+    unsigned lx = 0;    /* running index in l_buf */
+    unsigned code;      /* the code to send */
+    int extra;          /* number of extra bits to send */
+
+    if (s->last_lit != 0) do {
+        dist = s->d_buf[lx];
+        lc = s->l_buf[lx++];
+        if (dist == 0) {
+            send_code(s, lc, ltree); /* send a literal byte */
+            Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+        } else {
+            /* Here, lc is the match length - MIN_MATCH */
+            code = _length_code[lc];
+            send_code(s, code+LITERALS+1, ltree); /* send the length code */
+            extra = extra_lbits[code];
+            if (extra != 0) {
+                lc -= base_length[code];
+                send_bits(s, lc, extra);       /* send the extra length bits */
+            }
+            dist--; /* dist is now the match distance - 1 */
+            code = d_code(dist);
+            Assert (code < D_CODES, "bad d_code");
+
+            send_code(s, code, dtree);       /* send the distance code */
+            extra = extra_dbits[code];
+            if (extra != 0) {
+                dist -= base_dist[code];
+                send_bits(s, dist, extra);   /* send the extra distance bits */
+            }
+        } /* literal or match pair ? */
+
+        /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+        Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
+               "pendingBuf overflow");
+
+    } while (lx < s->last_lit);
+
+    send_code(s, END_BLOCK, ltree);
+    s->last_eob_len = ltree[END_BLOCK].Len;
+}
+
+/* ===========================================================================
+ * Check if the data type is TEXT or BINARY, using the following algorithm:
+ * - TEXT if the two conditions below are satisfied:
+ *    a) There are no non-portable control characters belonging to the
+ *       "black list" (0..6, 14..25, 28..31).
+ *    b) There is at least one printable character belonging to the
+ *       "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
+ * - BINARY otherwise.
+ * - The following partially-portable control characters form a
+ *   "gray list" that is ignored in this detection algorithm:
+ *   (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
+ * IN assertion: the fields Freq of dyn_ltree are set.
+ */
+local int detect_data_type(deflate_state *s)
+{
+    /* black_mask is the bit mask of black-listed bytes
+     * set bits 0..6, 14..25, and 28..31
+     * 0xf3ffc07f = binary 11110011111111111100000001111111
+     */
+    unsigned long black_mask = 0xf3ffc07fUL;
+    int n;
+
+    /* Check for non-textual ("black-listed") bytes. */
+    for (n = 0; n <= 31; n++, black_mask >>= 1)
+        if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))
+            return Z_BINARY;
+
+    /* Check for textual ("white-listed") bytes. */
+    if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
+            || s->dyn_ltree[13].Freq != 0)
+        return Z_TEXT;
+    for (n = 32; n < LITERALS; n++)
+        if (s->dyn_ltree[n].Freq != 0)
+            return Z_TEXT;
+
+    /* There are no "black-listed" or "white-listed" bytes:
+     * this stream either is empty or has tolerated ("gray-listed") bytes only.
+     */
+    return Z_BINARY;
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(unsigned code, int len)
+{
+    register unsigned res = 0;
+    do {
+        res |= code & 1;
+        code >>= 1, res <<= 1;
+    } while (--len > 0);
+    return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(deflate_state *s)
+{
+    if (s->bi_valid == 16) {
+        put_short(s, s->bi_buf);
+        s->bi_buf = 0;
+        s->bi_valid = 0;
+    } else if (s->bi_valid >= 8) {
+        put_byte(s, (Byte)s->bi_buf);
+        s->bi_buf >>= 8;
+        s->bi_valid -= 8;
+    }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(deflate_state *s)
+{
+    if (s->bi_valid > 8) {
+        put_short(s, s->bi_buf);
+    } else if (s->bi_valid > 0) {
+        put_byte(s, (Byte)s->bi_buf);
+    }
+    s->bi_buf = 0;
+    s->bi_valid = 0;
+#ifdef DEBUG
+    s->bits_sent = (s->bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+local void copy_block(deflate_state *s, charf    *buf, unsigned len, int      header)
+{
+    bi_windup(s);        /* align on byte boundary */
+    s->last_eob_len = 8; /* enough lookahead for inflate */
+
+    if (header) {
+        put_short(s, (ush)len);
+        put_short(s, (ush)~len);
+#ifdef DEBUG
+        s->bits_sent += 2*16;
+#endif
+    }
+#ifdef DEBUG
+    s->bits_sent += (ulg)len<<3;
+#endif
+    while (len--) {
+        put_byte(s, *buf++);
+    }
+}
+
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/misc/zlib/trees.h b/abc-build/src/misc/zlib/trees.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/trees.h
@@ -0,0 +1,132 @@
+/* header created automatically with -DGEN_TREES_H */
+
+ABC_NAMESPACE_HEADER_START
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{  8}}, {{140},{  8}}, {{ 76},{  8}}, {{204},{  8}}, {{ 44},{  8}},
+{{172},{  8}}, {{108},{  8}}, {{236},{  8}}, {{ 28},{  8}}, {{156},{  8}},
+{{ 92},{  8}}, {{220},{  8}}, {{ 60},{  8}}, {{188},{  8}}, {{124},{  8}},
+{{252},{  8}}, {{  2},{  8}}, {{130},{  8}}, {{ 66},{  8}}, {{194},{  8}},
+{{ 34},{  8}}, {{162},{  8}}, {{ 98},{  8}}, {{226},{  8}}, {{ 18},{  8}},
+{{146},{  8}}, {{ 82},{  8}}, {{210},{  8}}, {{ 50},{  8}}, {{178},{  8}},
+{{114},{  8}}, {{242},{  8}}, {{ 10},{  8}}, {{138},{  8}}, {{ 74},{  8}},
+{{202},{  8}}, {{ 42},{  8}}, {{170},{  8}}, {{106},{  8}}, {{234},{  8}},
+{{ 26},{  8}}, {{154},{  8}}, {{ 90},{  8}}, {{218},{  8}}, {{ 58},{  8}},
+{{186},{  8}}, {{122},{  8}}, {{250},{  8}}, {{  6},{  8}}, {{134},{  8}},
+{{ 70},{  8}}, {{198},{  8}}, {{ 38},{  8}}, {{166},{  8}}, {{102},{  8}},
+{{230},{  8}}, {{ 22},{  8}}, {{150},{  8}}, {{ 86},{  8}}, {{214},{  8}},
+{{ 54},{  8}}, {{182},{  8}}, {{118},{  8}}, {{246},{  8}}, {{ 14},{  8}},
+{{142},{  8}}, {{ 78},{  8}}, {{206},{  8}}, {{ 46},{  8}}, {{174},{  8}},
+{{110},{  8}}, {{238},{  8}}, {{ 30},{  8}}, {{158},{  8}}, {{ 94},{  8}},
+{{222},{  8}}, {{ 62},{  8}}, {{190},{  8}}, {{126},{  8}}, {{254},{  8}},
+{{  1},{  8}}, {{129},{  8}}, {{ 65},{  8}}, {{193},{  8}}, {{ 33},{  8}},
+{{161},{  8}}, {{ 97},{  8}}, {{225},{  8}}, {{ 17},{  8}}, {{145},{  8}},
+{{ 81},{  8}}, {{209},{  8}}, {{ 49},{  8}}, {{177},{  8}}, {{113},{  8}},
+{{241},{  8}}, {{  9},{  8}}, {{137},{  8}}, {{ 73},{  8}}, {{201},{  8}},
+{{ 41},{  8}}, {{169},{  8}}, {{105},{  8}}, {{233},{  8}}, {{ 25},{  8}},
+{{153},{  8}}, {{ 89},{  8}}, {{217},{  8}}, {{ 57},{  8}}, {{185},{  8}},
+{{121},{  8}}, {{249},{  8}}, {{  5},{  8}}, {{133},{  8}}, {{ 69},{  8}},
+{{197},{  8}}, {{ 37},{  8}}, {{165},{  8}}, {{101},{  8}}, {{229},{  8}},
+{{ 21},{  8}}, {{149},{  8}}, {{ 85},{  8}}, {{213},{  8}}, {{ 53},{  8}},
+{{181},{  8}}, {{117},{  8}}, {{245},{  8}}, {{ 13},{  8}}, {{141},{  8}},
+{{ 77},{  8}}, {{205},{  8}}, {{ 45},{  8}}, {{173},{  8}}, {{109},{  8}},
+{{237},{  8}}, {{ 29},{  8}}, {{157},{  8}}, {{ 93},{  8}}, {{221},{  8}},
+{{ 61},{  8}}, {{189},{  8}}, {{125},{  8}}, {{253},{  8}}, {{ 19},{  9}},
+{{275},{  9}}, {{147},{  9}}, {{403},{  9}}, {{ 83},{  9}}, {{339},{  9}},
+{{211},{  9}}, {{467},{  9}}, {{ 51},{  9}}, {{307},{  9}}, {{179},{  9}},
+{{435},{  9}}, {{115},{  9}}, {{371},{  9}}, {{243},{  9}}, {{499},{  9}},
+{{ 11},{  9}}, {{267},{  9}}, {{139},{  9}}, {{395},{  9}}, {{ 75},{  9}},
+{{331},{  9}}, {{203},{  9}}, {{459},{  9}}, {{ 43},{  9}}, {{299},{  9}},
+{{171},{  9}}, {{427},{  9}}, {{107},{  9}}, {{363},{  9}}, {{235},{  9}},
+{{491},{  9}}, {{ 27},{  9}}, {{283},{  9}}, {{155},{  9}}, {{411},{  9}},
+{{ 91},{  9}}, {{347},{  9}}, {{219},{  9}}, {{475},{  9}}, {{ 59},{  9}},
+{{315},{  9}}, {{187},{  9}}, {{443},{  9}}, {{123},{  9}}, {{379},{  9}},
+{{251},{  9}}, {{507},{  9}}, {{  7},{  9}}, {{263},{  9}}, {{135},{  9}},
+{{391},{  9}}, {{ 71},{  9}}, {{327},{  9}}, {{199},{  9}}, {{455},{  9}},
+{{ 39},{  9}}, {{295},{  9}}, {{167},{  9}}, {{423},{  9}}, {{103},{  9}},
+{{359},{  9}}, {{231},{  9}}, {{487},{  9}}, {{ 23},{  9}}, {{279},{  9}},
+{{151},{  9}}, {{407},{  9}}, {{ 87},{  9}}, {{343},{  9}}, {{215},{  9}},
+{{471},{  9}}, {{ 55},{  9}}, {{311},{  9}}, {{183},{  9}}, {{439},{  9}},
+{{119},{  9}}, {{375},{  9}}, {{247},{  9}}, {{503},{  9}}, {{ 15},{  9}},
+{{271},{  9}}, {{143},{  9}}, {{399},{  9}}, {{ 79},{  9}}, {{335},{  9}},
+{{207},{  9}}, {{463},{  9}}, {{ 47},{  9}}, {{303},{  9}}, {{175},{  9}},
+{{431},{  9}}, {{111},{  9}}, {{367},{  9}}, {{239},{  9}}, {{495},{  9}},
+{{ 31},{  9}}, {{287},{  9}}, {{159},{  9}}, {{415},{  9}}, {{ 95},{  9}},
+{{351},{  9}}, {{223},{  9}}, {{479},{  9}}, {{ 63},{  9}}, {{319},{  9}},
+{{191},{  9}}, {{447},{  9}}, {{127},{  9}}, {{383},{  9}}, {{255},{  9}},
+{{511},{  9}}, {{  0},{  7}}, {{ 64},{  7}}, {{ 32},{  7}}, {{ 96},{  7}},
+{{ 16},{  7}}, {{ 80},{  7}}, {{ 48},{  7}}, {{112},{  7}}, {{  8},{  7}},
+{{ 72},{  7}}, {{ 40},{  7}}, {{104},{  7}}, {{ 24},{  7}}, {{ 88},{  7}},
+{{ 56},{  7}}, {{120},{  7}}, {{  4},{  7}}, {{ 68},{  7}}, {{ 36},{  7}},
+{{100},{  7}}, {{ 20},{  7}}, {{ 84},{  7}}, {{ 52},{  7}}, {{116},{  7}},
+{{  3},{  8}}, {{131},{  8}}, {{ 67},{  8}}, {{195},{  8}}, {{ 35},{  8}},
+{{163},{  8}}, {{ 99},{  8}}, {{227},{  8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
+ 0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,
+ 8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  0,  0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+    0,     1,     2,     3,     4,     6,     8,    12,    16,    24,
+   32,    48,    64,    96,   128,   192,   256,   384,   512,   768,
+ 1024,  1536,  2048,  3072,  4096,  6144,  8192, 12288, 16384, 24576
+};
+
+ABC_NAMESPACE_HEADER_END
+
diff --git a/abc-build/src/misc/zlib/uncompr.c b/abc-build/src/misc/zlib/uncompr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/uncompr.c
@@ -0,0 +1,67 @@
+/* uncompr.c -- decompress a memory buffer
+ * Copyright (C) 1995-2003, 2010 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc/util/abc_global.h"
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/* ===========================================================================
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be large enough to hold the
+   entire uncompressed data. (The size of the uncompressed data must have
+   been saved previously by the compressor and transmitted to the decompressor
+   by some mechanism outside the scope of this compression library.)
+   Upon exit, destLen is the actual size of the compressed buffer.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+int ZEXPORT uncompress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
+{
+    z_stream stream;
+    int err;
+
+    stream.next_in = (Bytef*)source;
+    stream.avail_in = (uInt)sourceLen;
+    /* Check for source > 64K on 16-bit machine: */
+    if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+
+    stream.next_out = dest;
+    stream.avail_out = (uInt)*destLen;
+    if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+    stream.zalloc = (alloc_func)0;
+    stream.zfree = (free_func)0;
+
+    err = inflateInit(&stream);
+    if (err != Z_OK) return err;
+
+    err = inflate(&stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        inflateEnd(&stream);
+        if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
+            return Z_DATA_ERROR;
+        return err;
+    }
+    *destLen = stream.total_out;
+
+    err = inflateEnd(&stream);
+    return err;
+}
+
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/zlib/zconf.h b/abc-build/src/misc/zlib/zconf.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/zconf.h
@@ -0,0 +1,432 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2010 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
+ */
+#ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */
+
+/* all linked symbols */
+#  define _dist_code            z__dist_code
+#  define _length_code          z__length_code
+#  define _tr_align             z__tr_align
+#  define _tr_flush_block       z__tr_flush_block
+#  define _tr_init              z__tr_init
+#  define _tr_stored_block      z__tr_stored_block
+#  define _tr_tally             z__tr_tally
+#  define adler32               z_adler32
+#  define adler32_combine       z_adler32_combine
+#  define adler32_combine64     z_adler32_combine64
+#  define compress              z_compress
+#  define compress2             z_compress2
+#  define compressBound         z_compressBound
+#  define crc32                 z_crc32
+#  define crc32_combine         z_crc32_combine
+#  define crc32_combine64       z_crc32_combine64
+#  define deflate               z_deflate
+#  define deflateBound          z_deflateBound
+#  define deflateCopy           z_deflateCopy
+#  define deflateEnd            z_deflateEnd
+#  define deflateInit2_         z_deflateInit2_
+#  define deflateInit_          z_deflateInit_
+#  define deflateParams         z_deflateParams
+#  define deflatePrime          z_deflatePrime
+#  define deflateReset          z_deflateReset
+#  define deflateSetDictionary  z_deflateSetDictionary
+#  define deflateSetHeader      z_deflateSetHeader
+#  define deflateTune           z_deflateTune
+#  define deflate_copyright     z_deflate_copyright
+#  define get_crc_table         z_get_crc_table
+#  define gz_error              z_gz_error
+#  define gz_intmax             z_gz_intmax
+#  define gz_strwinerror        z_gz_strwinerror
+#  define gzbuffer              z_gzbuffer
+#  define gzclearerr            z_gzclearerr
+#  define gzclose               z_gzclose
+#  define gzclose_r             z_gzclose_r
+#  define gzclose_w             z_gzclose_w
+#  define gzdirect              z_gzdirect
+#  define gzdopen               z_gzdopen
+#  define gzeof                 z_gzeof
+#  define gzerror               z_gzerror
+#  define gzflush               z_gzflush
+#  define gzgetc                z_gzgetc
+#  define gzgets                z_gzgets
+#  define gzoffset              z_gzoffset
+#  define gzoffset64            z_gzoffset64
+#  define gzopen                z_gzopen
+#  define gzopen64              z_gzopen64
+#  define gzprintf              z_gzprintf
+#  define gzputc                z_gzputc
+#  define gzputs                z_gzputs
+#  define gzread                z_gzread
+#  define gzrewind              z_gzrewind
+#  define gzseek                z_gzseek
+#  define gzseek64              z_gzseek64
+#  define gzsetparams           z_gzsetparams
+#  define gztell                z_gztell
+#  define gztell64              z_gztell64
+#  define gzungetc              z_gzungetc
+#  define gzwrite               z_gzwrite
+#  define inflate               z_inflate
+#  define inflateBack           z_inflateBack
+#  define inflateBackEnd        z_inflateBackEnd
+#  define inflateBackInit_      z_inflateBackInit_
+#  define inflateCopy           z_inflateCopy
+#  define inflateEnd            z_inflateEnd
+#  define inflateGetHeader      z_inflateGetHeader
+#  define inflateInit2_         z_inflateInit2_
+#  define inflateInit_          z_inflateInit_
+#  define inflateMark           z_inflateMark
+#  define inflatePrime          z_inflatePrime
+#  define inflateReset          z_inflateReset
+#  define inflateReset2         z_inflateReset2
+#  define inflateSetDictionary  z_inflateSetDictionary
+#  define inflateSync           z_inflateSync
+#  define inflateSyncPoint      z_inflateSyncPoint
+#  define inflateUndermine      z_inflateUndermine
+#  define inflate_copyright     z_inflate_copyright
+#  define inflate_fast          z_inflate_fast
+#  define inflate_table         z_inflate_table
+#  define uncompress            z_uncompress
+#  define zError                z_zError
+#  define zcalloc               z_zcalloc
+#  define zcfree                z_zcfree
+#  define zlibCompileFlags      z_zlibCompileFlags
+#  define zlibVersion           z_zlibVersion
+
+/* all zlib typedefs in zlib.h and zconf.h */
+#  define Byte                  z_Byte
+#  define Bytef                 z_Bytef
+#  define alloc_func            z_alloc_func
+#  define charf                 z_charf
+#  define free_func             z_free_func
+#  define gzFile                z_gzFile
+#  define gz_header             z_gz_header
+#  define gz_headerp            z_gz_headerp
+#  define in_func               z_in_func
+#  define intf                  z_intf
+#  define out_func              z_out_func
+#  define uInt                  z_uInt
+#  define uIntf                 z_uIntf
+#  define uLong                 z_uLong
+#  define uLongf                z_uLongf
+#  define voidp                 z_voidp
+#  define voidpc                z_voidpc
+#  define voidpf                z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+#  define gz_header_s           z_gz_header_s
+#  define internal_state        z_internal_state
+
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+#  define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+#  define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+#  ifndef WIN32
+#    define WIN32
+#  endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+#    ifndef SYS16BIT
+#      define SYS16BIT
+#    endif
+#  endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+#  ifndef STDC
+#    define STDC
+#  endif
+#  if __STDC_VERSION__ >= 199901L
+#    ifndef STDC99
+#      define STDC99
+#    endif
+#  endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+#  define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
+#  define STDC
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const       /* note: need a more gentle solution here */
+#  endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+#  define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+#  if defined(M_I86SM) || defined(M_I86MM)
+     /* MSC small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef _MSC_VER
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#  if (defined(__SMALL__) || defined(__MEDIUM__))
+     /* Turbo C small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef __BORLANDC__
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+   /* If building or using zlib as a DLL, define ZLIB_DLL.
+    * This is not mandatory, but it offers a little performance increase.
+    */
+#  ifdef ZLIB_DLL
+#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+#      ifdef ZLIB_INTERNAL
+#        define ZEXTERN extern __declspec(dllexport)
+#      else
+#        define ZEXTERN extern __declspec(dllimport)
+#      endif
+#    endif
+#  endif  /* ZLIB_DLL */
+   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+    * define ZLIB_WINAPI.
+    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+    */
+#  ifdef ZLIB_WINAPI
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+     /* No need for _export, use ZLIB.DEF instead. */
+     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+#    define ZEXPORT WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA WINAPIV
+#    else
+#      define ZEXPORTVA FAR CDECL
+#    endif
+#  endif
+#endif
+
+#if defined (__BEOS__)
+#  ifdef ZLIB_DLL
+#    ifdef ZLIB_INTERNAL
+#      define ZEXPORT   __declspec(dllexport)
+#      define ZEXPORTVA __declspec(dllexport)
+#    else
+#      define ZEXPORT   __declspec(dllimport)
+#      define ZEXPORTVA __declspec(dllimport)
+#    endif
+#  endif
+#endif
+
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+
+#ifndef FAR
+#  define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void const *voidpc;
+   typedef void FAR   *voidpf;
+   typedef void       *voidp;
+#else
+   typedef Byte const *voidpc;
+   typedef Byte FAR   *voidpf;
+   typedef Byte       *voidp;
+#endif
+
+#ifdef HAVE_UNISTD_H    /* may be set to #if 1 by ./configure */
+#  define Z_HAVE_UNISTD_H
+#endif
+
+#ifdef STDC
+#  include <sys/types.h>    /* for off_t */
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if -_LARGEFILE64_SOURCE - -1 == 1
+#  undef _LARGEFILE64_SOURCE
+#endif
+
+#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
+#  include <unistd.h>       /* for SEEK_* and off_t */
+#  ifdef VMS
+#    include <unixio.h>     /* for off_t */
+#  endif
+#  ifndef z_off_t
+#    define z_off_t off_t
+#  endif
+#endif
+
+ABC_NAMESPACE_HEADER_START
+
+#ifndef SEEK_SET
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+
+#ifndef z_off_t
+#  define z_off_t long
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
+#  define z_off64_t off64_t
+#else
+#  define z_off64_t z_off_t
+#endif
+
+#if defined(__OS400__)
+#  define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+#  define NO_vsnprintf
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+  #pragma map(deflateInit_,"DEIN")
+  #pragma map(deflateInit2_,"DEIN2")
+  #pragma map(deflateEnd,"DEEND")
+  #pragma map(deflateBound,"DEBND")
+  #pragma map(inflateInit_,"ININ")
+  #pragma map(inflateInit2_,"ININ2")
+  #pragma map(inflateEnd,"INEND")
+  #pragma map(inflateSync,"INSY")
+  #pragma map(inflateSetDictionary,"INSEDI")
+  #pragma map(compressBound,"CMBND")
+  #pragma map(inflate_table,"INTABL")
+  #pragma map(inflate_fast,"INFA")
+  #pragma map(inflate_copyright,"INCOPY")
+#endif
+
+ABC_NAMESPACE_HEADER_END
+
+#endif /* ZCONF_H */
diff --git a/abc-build/src/misc/zlib/zlib.h b/abc-build/src/misc/zlib/zlib.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/zlib.h
@@ -0,0 +1,1619 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.2.5, April 19th, 2010
+
+  Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
+  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+#include "misc/util/abc_global.h"
+
+#include "zconf.h"
+
+ABC_NAMESPACE_HEADER_START
+
+#define ZLIB_VERSION "1.2.5"
+#define ZLIB_VERNUM 0x1250
+#define ZLIB_VER_MAJOR 1
+#define ZLIB_VER_MINOR 2
+#define ZLIB_VER_REVISION 5
+#define ZLIB_VER_SUBREVISION 0
+
+/*
+    The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed data.
+  This version of the library supports only one compression method (deflation)
+  but other algorithms will be added later and will have the same stream
+  interface.
+
+    Compression can be done in a single step if the buffers are large enough,
+  or can be done by repeated calls of the compression function.  In the latter
+  case, the application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+    The compressed data format used by default by the in-memory functions is
+  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+  around a deflate stream, which is itself documented in RFC 1951.
+
+    The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio using the functions that start
+  with "gz".  The gzip format is different from the zlib format.  gzip is a
+  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+    This library can optionally read and write gzip streams in memory as well.
+
+    The zlib format was designed to be compact and fast for use in memory
+  and on communications channels.  The gzip format was designed for single-
+  file compression on file systems, has a larger header than zlib to maintain
+  directory information, and uses a different, slower check method than zlib.
+
+    The library does not install any signal handler.  The decoder checks
+  the consistency of the compressed data, so the library should never crash
+  even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    Bytef    *next_in;  /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total nb of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total nb of bytes output so far */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: binary or text */
+    uLong   adler;      /* adler32 value of the uncompressed data */
+    uLong   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+     gzip header information passed to and from zlib routines.  See RFC 1952
+  for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+    int     text;       /* true if compressed data believed to be text */
+    uLong   time;       /* modification time */
+    int     xflags;     /* extra flags (not used when writing a gzip file) */
+    int     os;         /* operating system */
+    Bytef   *extra;     /* pointer to extra field or Z_NULL if none */
+    uInt    extra_len;  /* extra field length (valid if extra != Z_NULL) */
+    uInt    extra_max;  /* space at extra (only when reading header) */
+    Bytef   *name;      /* pointer to zero-terminated file name or Z_NULL */
+    uInt    name_max;   /* space at name (only when reading header) */
+    Bytef   *comment;   /* pointer to zero-terminated comment or Z_NULL */
+    uInt    comm_max;   /* space at comment (only when reading header) */
+    int     hcrc;       /* true if there was or will be a header crc */
+    int     done;       /* true when done reading gzip header (not used
+                           when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+     The application must update next_in and avail_in when avail_in has dropped
+   to zero.  It must update next_out and avail_out when avail_out has dropped
+   to zero.  The application must initialize zalloc, zfree and opaque before
+   calling the init function.  All other fields are set by the compression
+   library and must not be updated by the application.
+
+     The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree.  This can be useful for custom
+   memory management.  The compression library attaches no meaning to the
+   opaque value.
+
+     zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.
+
+     On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this if
+   the symbol MAXSEG_64K is defined (see zconf.h).  WARNING: On MSDOS, pointers
+   returned by zalloc for objects of exactly 65536 bytes *must* have their
+   offset normalized to zero.  The default allocation function provided by this
+   library ensures this (see zutil.c).  To reduce memory requirements and avoid
+   any allocation of 64K objects, at the expense of compression ratio, compile
+   the library with -DMAX_WBITS=14 (see zconf.h).
+
+     The fields total_in and total_out can be used for statistics or progress
+   reports.  After compression, total_in holds the total size of the
+   uncompressed data and may be saved for use in the decompressor (particularly
+   if the decompressor wants to decompress everything in a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+#define Z_BLOCK         5
+#define Z_TREES         6
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_RLE                 3
+#define Z_FIXED               4
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_TEXT     1
+#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+
+                        /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is not
+   compatible with the zlib.h header file used by the application.  This check
+   is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+     Initializes the internal stream state for compression.  The fields
+   zalloc, zfree and opaque must be initialized before by the caller.  If
+   zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
+   allocation functions.
+
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at all
+   (the input data is simply copied a block at a time).  Z_DEFAULT_COMPRESSION
+   requests a default compromise between speed and compression (currently
+   equivalent to level 6).
+
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if level is not a valid compression level, or
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).  msg is set to null
+   if there is no error message.  deflateInit does not perform any compression:
+   this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+    deflate compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full.  It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+    The detailed semantics are as follows.  deflate performs one or both of the
+  following actions:
+
+  - Compress more input starting at next_in and update next_in and avail_in
+    accordingly.  If not all input can be processed (because there is not
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary (in interactive applications).  Some
+    output may be provided even if flush is not set.
+
+    Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming more
+  output, and updating avail_in or avail_out accordingly; avail_out should
+  never be zero before the call.  The application can consume the compressed
+  output when it wants, for example when the output buffer is full (avail_out
+  == 0), or after each call of deflate().  If deflate returns Z_OK and with
+  zero avail_out, it must be called again after making room in the output
+  buffer because there might be more output pending.
+
+    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+  decide how much data to accumulate before producing output, in order to
+  maximize compression.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far.  (In
+  particular avail_in is zero after the call if enough output space has been
+  provided before the call.) Flushing may degrade compression for some
+  compression algorithms and so it should be used only when necessary.  This
+  completes the current deflate block and follows it with an empty stored block
+  that is three bits plus filler bits to the next byte, followed by four bytes
+  (00 00 ff ff).
+
+    If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
+  output buffer, but the output is not aligned to a byte boundary.  All of the
+  input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
+  This completes the current deflate block and follows it with an empty fixed
+  codes block that is 10 bits long.  This assures that enough bytes are output
+  in order for the decompressor to finish the block before the empty fixed code
+  block.
+
+    If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
+  for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
+  seven bits of the current block are held to be written as the next byte after
+  the next deflate block is completed.  In this case, the decompressor may not
+  be provided enough bits at this point in order to complete decompression of
+  the data provided so far to the compressor.  It may need to wait for the next
+  block to be emitted.  This is for advanced applications that need to control
+  the emission of deflate blocks.
+
+    If flush is set to Z_FULL_FLUSH, all output is flushed as with
+  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired.  Using Z_FULL_FLUSH too often can seriously degrade
+  compression.
+
+    If deflate returns with avail_out == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  avail_out), until the flush is complete (deflate returns with non-zero
+  avail_out).  In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+  avail_out is greater than six to avoid repeated flush markers due to
+  avail_out == 0 on return.
+
+    If the parameter flush is set to Z_FINISH, pending input is processed,
+  pending output is flushed and deflate returns with Z_STREAM_END if there was
+  enough output space; if deflate returns with Z_OK, this function must be
+  called again with Z_FINISH and more output space (updated avail_out) but no
+  more input data, until it returns with Z_STREAM_END or an error.  After
+  deflate has returned Z_STREAM_END, the only possible operations on the stream
+  are deflateReset or deflateEnd.
+
+    Z_FINISH can be used immediately after deflateInit if all the compression
+  is to be done in a single step.  In this case, avail_out must be at least the
+  value returned by deflateBound (see below).  If deflate does not return
+  Z_STREAM_END, then it must be called again as described above.
+
+    deflate() sets strm->adler to the adler32 checksum of all input read
+  so far (that is, total_in bytes).
+
+    deflate() may update strm->data_type if it can make a good guess about
+  the input data type (Z_BINARY or Z_TEXT).  In doubt, the data is considered
+  binary.  This field is only for information purposes and does not affect the
+  compression algorithm in any manner.
+
+    deflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if all input has been
+  consumed and all output has been produced (only when flush is set to
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+  if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible
+  (for example avail_in or avail_out was zero).  Note that Z_BUF_ERROR is not
+  fatal, and deflate() can be called again with more input and more output
+  space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any pending
+   output.
+
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+   prematurely (some input or output was discarded).  In the error case, msg
+   may be set but then points to a static string (which must not be
+   deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+     Initializes the internal stream state for decompression.  The fields
+   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+   the caller.  If next_in is not Z_NULL and avail_in is large enough (the
+   exact value depends on the compression method), inflateInit determines the
+   compression method from the zlib header and allocates all data structures
+   accordingly; otherwise the allocation will be deferred to the first call of
+   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+   use default allocation functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+   invalid, such as a null pointer to the structure.  msg is set to null if
+   there is no error message.  inflateInit does not perform any decompression
+   apart from possibly reading the zlib header if present: actual decompression
+   will be done by inflate().  (So next_in and avail_in may be modified, but
+   next_out and avail_out are unused and unchanged.) The current implementation
+   of inflateInit() does not process any header information -- that is deferred
+   until inflate() is called.
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+    inflate decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full.  It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+  The detailed semantics are as follows.  inflate performs one or both of the
+  following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly.  If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing will
+    resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() provides as much output as possible, until there is
+    no more input data or no more space in the output buffer (see below about
+    the flush parameter).
+
+    Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming more
+  output, and updating the next_* and avail_* values accordingly.  The
+  application can consume the uncompressed output when it wants, for example
+  when the output buffer is full (avail_out == 0), or after each call of
+  inflate().  If inflate returns Z_OK and with zero avail_out, it must be
+  called again after making room in the output buffer because there might be
+  more output pending.
+
+    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
+  Z_BLOCK, or Z_TREES.  Z_SYNC_FLUSH requests that inflate() flush as much
+  output as possible to the output buffer.  Z_BLOCK requests that inflate()
+  stop if and when it gets to the next deflate block boundary.  When decoding
+  the zlib or gzip format, this will cause inflate() to return immediately
+  after the header and before the first block.  When doing a raw inflate,
+  inflate() will go ahead and process the first block, and will return when it
+  gets to the end of that block, or when it runs out of data.
+
+    The Z_BLOCK option assists in appending to or combining deflate streams.
+  Also to assist in this, on return inflate() will set strm->data_type to the
+  number of unused bits in the last byte taken from strm->next_in, plus 64 if
+  inflate() is currently decoding the last block in the deflate stream, plus
+  128 if inflate() returned immediately after decoding an end-of-block code or
+  decoding the complete header up to just before the first byte of the deflate
+  stream.  The end-of-block will not be indicated until all of the uncompressed
+  data from that block has been written to strm->next_out.  The number of
+  unused bits may in general be greater than seven, except when bit 7 of
+  data_type is set, in which case the number of unused bits will be less than
+  eight.  data_type is set as noted here every time inflate() returns for all
+  flush options, and so can be used to determine the amount of currently
+  consumed input in bits.
+
+    The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
+  end of each deflate block header is reached, before any actual data in that
+  block is decoded.  This allows the caller to determine the length of the
+  deflate block header for later use in random access within a deflate block.
+  256 is added to the value of strm->data_type when inflate() returns
+  immediately after reaching the end of the deflate block header.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error.  However if all decompression is to be performed in a single step (a
+  single call of inflate), the parameter flush should be set to Z_FINISH.  In
+  this case all pending input is processed and all pending output is flushed;
+  avail_out must be large enough to hold all the uncompressed data.  (The size
+  of the uncompressed data may have been saved by the compressor for this
+  purpose.) The next operation on this stream must be inflateEnd to deallocate
+  the decompression state.  The use of Z_FINISH is never required, but can be
+  used to inform inflate that a faster approach may be used for the single
+  inflate() call.
+
+     In this implementation, inflate() always flushes as much output as
+  possible to the output buffer, and always uses the faster approach on the
+  first call.  So the only effect of the flush parameter in this implementation
+  is on the return value of inflate(), as noted below, or when it returns early
+  because Z_BLOCK or Z_TREES is used.
+
+     If a preset dictionary is needed after this call (see inflateSetDictionary
+  below), inflate sets strm->adler to the adler32 checksum of the dictionary
+  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+  strm->adler to the adler32 checksum of all output produced so far (that is,
+  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+  below.  At the end of the stream, inflate() checks that its computed adler32
+  checksum is equal to that saved by the compressor and returns Z_STREAM_END
+  only if the checksum is correct.
+
+    inflate() can decompress and check either zlib-wrapped or gzip-wrapped
+  deflate data.  The header type is detected automatically, if requested when
+  initializing with inflateInit2().  Any information contained in the gzip
+  header is not retained, so applications that need that information should
+  instead use raw inflate, see inflateInit2() below, or inflateBack() and
+  perform their own processing of the gzip header and trailer.
+
+    inflate() returns Z_OK if some progress has been made (more input processed
+  or more output produced), Z_STREAM_END if the end of the compressed data has
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect check
+  value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+  next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory,
+  Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+  output buffer when Z_FINISH is used.  Note that Z_BUF_ERROR is not fatal, and
+  inflate() can be called again with more input and more output space to
+  continue decompressing.  If Z_DATA_ERROR is returned, the application may
+  then call inflateSync() to look for a good compression block if a partial
+  recovery of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any pending
+   output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent.  In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+
+                        /* Advanced functions */
+
+/*
+    The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+                                     int  level,
+                                     int  method,
+                                     int  windowBits,
+                                     int  memLevel,
+                                     int  strategy));
+
+     This is another version of deflateInit with more compression options.  The
+   fields next_in, zalloc, zfree and opaque must be initialized before by the
+   caller.
+
+     The method parameter is the compression method.  It must be Z_DEFLATED in
+   this version of the library.
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer).  It should be in the range 8..15 for this
+   version of the library.  Larger values of this parameter result in better
+   compression at the expense of memory usage.  The default value is 15 if
+   deflateInit is used instead.
+
+     windowBits can also be -8..-15 for raw deflate.  In this case, -windowBits
+   determines the window size.  deflate() will then generate raw deflate data
+   with no zlib header or trailer, and will not compute an adler32 check value.
+
+     windowBits can also be greater than 15 for optional gzip encoding.  Add
+   16 to windowBits to write a simple gzip header and trailer around the
+   compressed data instead of a zlib wrapper.  The gzip header will have no
+   file name, no extra data, no comment, no modification time (set to zero), no
+   header crc, and the operating system will be set to 255 (unknown).  If a
+   gzip stream is being written, strm->adler is a crc32 instead of an adler32.
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression state.  memLevel=1 uses minimum memory but is
+   slow and reduces compression ratio; memLevel=9 uses maximum memory for
+   optimal speed.  The default value is 8.  See zconf.h for total memory usage
+   as a function of windowBits and memLevel.
+
+     The strategy parameter is used to tune the compression algorithm.  Use the
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+   string match), or Z_RLE to limit match distances to one (run-length
+   encoding).  Filtered data consists mostly of small values with a somewhat
+   random distribution.  In this case, the compression algorithm is tuned to
+   compress them better.  The effect of Z_FILTERED is to force more Huffman
+   coding and less string matching; it is somewhat intermediate between
+   Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY.  Z_RLE is designed to be almost as
+   fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data.  The
+   strategy parameter only affects the compression ratio but not the
+   correctness of the compressed output even if it is not set appropriately.
+   Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
+   decoder for special applications.
+
+     deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
+   method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
+   incompatible with the version assumed by the caller (ZLIB_VERSION).  msg is
+   set to null if there is no error message.  deflateInit2 does not perform any
+   compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output.  This function must be called
+   immediately after deflateInit, deflateInit2 or deflateReset, before any call
+   of deflate.  The compressor and decompressor must use exactly the same
+   dictionary (see inflateSetDictionary).
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary.  Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy; the data can then be compressed better than
+   with the default empty dictionary.
+
+     Depending on the size of the compression data structures selected by
+   deflateInit or deflateInit2, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size
+   provided in deflateInit or deflateInit2.  Thus the strings most likely to be
+   useful should be put at the end of the dictionary, not at the front.  In
+   addition, the current implementation of deflate will use at most the window
+   size minus 262 bytes of the provided dictionary.
+
+     Upon return of this function, strm->adler is set to the adler32 value
+   of the dictionary; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor.  (The adler32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.) If a raw deflate was requested, then the
+   adler32 value is not computed and strm->adler is not set.
+
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
+   inconsistent (for example if deflate has already been called for this stream
+   or if the compression method is bsort).  deflateSetDictionary does not
+   perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter.  The streams that will be discarded should then be freed
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal
+   compression state which can be quite large, so this strategy is slow and can
+   consume lots of memory.
+
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to deflateEnd followed by deflateInit,
+   but does not free and reallocate all the internal compression state.  The
+   stream will keep the same compression level and any other attributes that
+   may have been set by deflateInit2.
+
+     deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+                                      int level,
+                                      int strategy));
+/*
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in deflateInit2.  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different strategy.
+   If the compression level is changed, the input available so far is
+   compressed with the old level (and may be flushed); the new level will take
+   effect only at the next call of deflate().
+
+     Before the call of deflateParams, the stream state must be set as for
+   a call of deflate(), since the currently available input may have to be
+   compressed and flushed.  In particular, strm->avail_out must be non-zero.
+
+     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if
+   strm->avail_out was zero.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+                                    int good_length,
+                                    int max_lazy,
+                                    int nice_length,
+                                    int max_chain));
+/*
+     Fine tune deflate's internal compression parameters.  This should only be
+   used by someone who understands the algorithm used by zlib's deflate for
+   searching for the best matching string, and even then only by the most
+   fanatic optimizer trying to squeeze out the last compressed bit for their
+   specific input data.  Read the deflate.c source code for the meaning of the
+   max_lazy, good_length, nice_length, and max_chain parameters.
+
+     deflateTune() can be called after deflateInit() or deflateInit2(), and
+   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+                                       uLong sourceLen));
+/*
+     deflateBound() returns an upper bound on the compressed size after
+   deflation of sourceLen bytes.  It must be called after deflateInit() or
+   deflateInit2(), and after deflateSetHeader(), if used.  This would be used
+   to allocate an output buffer for deflation in a single pass, and so would be
+   called before deflate().
+*/
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     deflatePrime() inserts bits in the deflate output stream.  The intent
+   is that this function is used to start off the deflate output with the bits
+   leftover from a previous deflate stream when appending to it.  As such, this
+   function can only be used for raw deflate, and must be used before the first
+   deflate() call after a deflateInit2() or deflateReset().  bits must be less
+   than or equal to 16, and that many of the least significant bits of value
+   will be inserted in the output.
+
+     deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+     deflateSetHeader() provides gzip header information for when a gzip
+   stream is requested by deflateInit2().  deflateSetHeader() may be called
+   after deflateInit2() or deflateReset() and before the first call of
+   deflate().  The text, time, os, extra field, name, and comment information
+   in the provided gz_header structure are written to the gzip header (xflag is
+   ignored -- the extra flags are set according to the compression level).  The
+   caller must assure that, if not Z_NULL, name and comment are terminated with
+   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+   available there.  If hcrc is true, a gzip header crc is included.  Note that
+   the current versions of the command-line version of gzip (up through version
+   1.3.x) do not support header crc's, and will report that it is a "multi-part
+   gzip file" and give up.
+
+     If deflateSetHeader is not used, the default gzip header has text false,
+   the time set to zero, and os set to 255, with no extra, name, or comment
+   fields.  The gzip header is returned to the default state by deflateReset().
+
+     deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+                                     int  windowBits));
+
+     This is another version of inflateInit with an extra parameter.  The
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+   before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library.  The default value is 15 if inflateInit is used
+   instead.  windowBits must be greater than or equal to the windowBits value
+   provided to deflateInit2() while compressing, or it must be equal to 15 if
+   deflateInit2() was not used.  If a compressed stream with a larger window
+   size is given as input, inflate() will return with the error code
+   Z_DATA_ERROR instead of trying to allocate a larger window.
+
+     windowBits can also be zero to request that inflate use the window size in
+   the zlib header of the compressed stream.
+
+     windowBits can also be -8..-15 for raw inflate.  In this case, -windowBits
+   determines the window size.  inflate() will then process raw deflate data,
+   not looking for a zlib or gzip header, not generating a check value, and not
+   looking for any check values for comparison at the end of the stream.  This
+   is for use with other formats that use the deflate compressed data format
+   such as zip.  Those formats provide their own check values.  If a custom
+   format is developed using the raw deflate format for compressed data, it is
+   recommended that a check value such as an adler32 or a crc32 be applied to
+   the uncompressed data as is done in the zlib, gzip, and zip formats.  For
+   most applications, the zlib format should be used as is.  Note that comments
+   above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+     windowBits can also be greater than 15 for optional gzip decoding.  Add
+   32 to windowBits to enable zlib and gzip decoding with automatic header
+   detection, or add 16 to decode only the gzip format (the zlib format will
+   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is a
+   crc32 instead of an adler32.
+
+     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+   invalid, such as a null pointer to the structure.  msg is set to null if
+   there is no error message.  inflateInit2 does not perform any decompression
+   apart from possibly reading the zlib header if present: actual decompression
+   will be done by inflate().  (So next_in and avail_in may be modified, but
+   next_out and avail_out are unused and unchanged.) The current implementation
+   of inflateInit2() does not process any header information -- that is
+   deferred until inflate() is called.
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence.  This function must be called immediately after a call of inflate,
+   if that call returned Z_NEED_DICT.  The dictionary chosen by the compressor
+   can be determined from the adler32 value returned by that call of inflate.
+   The compressor and decompressor must use exactly the same dictionary (see
+   deflateSetDictionary).  For raw inflate, this function can be called
+   immediately after inflateInit2() or inflateReset() and before any call of
+   inflate() to set the dictionary.  The application must insure that the
+   dictionary that was used for compression is provided.
+
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+   expected one (incorrect adler32 value).  inflateSetDictionary does not
+   perform any decompression: this will be done by subsequent calls of
+   inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+     Skips invalid compressed data until a full flush point (see above the
+   description of deflate with Z_FULL_FLUSH) can be found, or until all
+   available input is skipped.  No output is provided.
+
+     inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+   if no more input was provided, Z_DATA_ERROR if no flush point has been
+   found, or Z_STREAM_ERROR if the stream structure was inconsistent.  In the
+   success case, the application may save the current current value of total_in
+   which indicates where valid compressed data was found.  In the error case,
+   the application may repeatedly call inflateSync, providing more input each
+   time, until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when randomly accessing a large stream.  The
+   first pass through the stream can periodically record the inflate state,
+   allowing restarting inflate at those points when randomly accessing the
+   stream.
+
+     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.  The
+   stream will keep attributes that may have been set by inflateInit2.
+
+     inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
+                                      int windowBits));
+/*
+     This function is the same as inflateReset, but it also permits changing
+   the wrap and window size requests.  The windowBits parameter is interpreted
+   the same as it is for inflateInit2.
+
+     inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL), or if
+   the windowBits parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     This function inserts bits in the inflate input stream.  The intent is
+   that this function is used to start inflating at a bit position in the
+   middle of a byte.  The provided bits will be used before any bytes are used
+   from next_in.  This function should only be used with raw inflate, and
+   should be used before the first inflate() call after inflateInit2() or
+   inflateReset().  bits must be less than or equal to 16, and that many of the
+   least significant bits of value will be inserted in the input.
+
+     If bits is negative, then the input stream bit buffer is emptied.  Then
+   inflatePrime() can be called again to put bits in the buffer.  This is used
+   to clear out bits leftover after feeding inflate a block description prior
+   to feeding inflate codes.
+
+     inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
+/*
+     This function returns two values, one in the lower 16 bits of the return
+   value, and the other in the remaining upper bits, obtained by shifting the
+   return value down 16 bits.  If the upper value is -1 and the lower value is
+   zero, then inflate() is currently decoding information outside of a block.
+   If the upper value is -1 and the lower value is non-zero, then inflate is in
+   the middle of a stored block, with the lower value equaling the number of
+   bytes from the input remaining to copy.  If the upper value is not -1, then
+   it is the number of bits back from the current bit position in the input of
+   the code (literal or length/distance pair) currently being processed.  In
+   that case the lower value is the number of bytes already emitted for that
+   code.
+
+     A code is being processed if inflate is waiting for more input to complete
+   decoding of the code, or if it has completed decoding but is waiting for
+   more output space to write the literal or match data.
+
+     inflateMark() is used to mark locations in the input data for random
+   access, which may be at bit positions, and to note those cases where the
+   output of a code may span boundaries of random access blocks.  The current
+   location in the input stream can be determined from avail_in and data_type
+   as noted in the description for the Z_BLOCK flush parameter for inflate.
+
+     inflateMark returns the value noted above or -1 << 16 if the provided
+   source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+     inflateGetHeader() requests that gzip header information be stored in the
+   provided gz_header structure.  inflateGetHeader() may be called after
+   inflateInit2() or inflateReset(), and before the first call of inflate().
+   As inflate() processes the gzip stream, head->done is zero until the header
+   is completed, at which time head->done is set to one.  If a zlib stream is
+   being decoded, then head->done is set to -1 to indicate that there will be
+   no gzip header information forthcoming.  Note that Z_BLOCK or Z_TREES can be
+   used to force inflate() to return immediately after header processing is
+   complete and before any actual data is decompressed.
+
+     The text, time, xflags, and os fields are filled in with the gzip header
+   contents.  hcrc is set to true if there is a header CRC.  (The header CRC
+   was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+   contains the maximum number of bytes to write to extra.  Once done is true,
+   extra_len contains the actual extra field length, and extra contains the
+   extra field, or that field truncated if extra_max is less than extra_len.
+   If name is not Z_NULL, then up to name_max characters are written there,
+   terminated with a zero unless the length is greater than name_max.  If
+   comment is not Z_NULL, then up to comm_max characters are written there,
+   terminated with a zero unless the length is greater than comm_max.  When any
+   of extra, name, or comment are not Z_NULL and the respective field is not
+   present in the header, then that field is set to Z_NULL to signal its
+   absence.  This allows the use of deflateSetHeader() with the returned
+   structure to duplicate the header.  However if those fields are set to
+   allocated memory, then the application will need to save those pointers
+   elsewhere so that they can be eventually freed.
+
+     If inflateGetHeader is not used, then the header information is simply
+   discarded.  The header is always checked for validity, including the header
+   CRC if present.  inflateReset() will reset the process to discard the header
+   information.  The application would need to call inflateGetHeader() again to
+   retrieve the header from the next gzip stream.
+
+     inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+                                        unsigned char FAR *window));
+
+     Initialize the internal stream state for decompression using inflateBack()
+   calls.  The fields zalloc, zfree and opaque in strm must be initialized
+   before the call.  If zalloc and zfree are Z_NULL, then the default library-
+   derived memory allocation routines are used.  windowBits is the base two
+   logarithm of the window size, in the range 8..15.  window is a caller
+   supplied buffer of that size.  Except for special applications where it is
+   assured that deflate was used with small window sizes, windowBits must be 15
+   and a 32K byte window must be supplied to be able to decompress general
+   deflate streams.
+
+     See inflateBack() for the usage of these routines.
+
+     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+   the paramaters are invalid, Z_MEM_ERROR if the internal state could not be
+   allocated, or Z_VERSION_ERROR if the version of the library does not match
+   the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+                                    in_func in, void FAR *in_desc,
+                                    out_func out, void FAR *out_desc));
+/*
+     inflateBack() does a raw inflate with a single call using a call-back
+   interface for input and output.  This is more efficient than inflate() for
+   file i/o applications in that it avoids copying between the output and the
+   sliding window by simply making the window itself the output buffer.  This
+   function trusts the application to not change the output buffer passed by
+   the output function, at least until inflateBack() returns.
+
+     inflateBackInit() must be called first to allocate the internal state
+   and to initialize the state with the user-provided window buffer.
+   inflateBack() may then be used multiple times to inflate a complete, raw
+   deflate stream with each call.  inflateBackEnd() is then called to free the
+   allocated state.
+
+     A raw deflate stream is one with no zlib or gzip header or trailer.
+   This routine would normally be used in a utility that reads zip or gzip
+   files and writes out uncompressed files.  The utility would decode the
+   header and process the trailer on its own, hence this routine expects only
+   the raw deflate stream to decompress.  This is different from the normal
+   behavior of inflate(), which expects either a zlib or gzip header and
+   trailer around the deflate stream.
+
+     inflateBack() uses two subroutines supplied by the caller that are then
+   called by inflateBack() for input and output.  inflateBack() calls those
+   routines until it reads a complete deflate stream and writes out all of the
+   uncompressed data, or until it encounters an error.  The function's
+   parameters and return types are defined above in the in_func and out_func
+   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the
+   number of bytes of provided input, and a pointer to that input in buf.  If
+   there is no input available, in() must return zero--buf is ignored in that
+   case--and inflateBack() will return a buffer error.  inflateBack() will call
+   out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].  out()
+   should return zero on success, or non-zero on failure.  If out() returns
+   non-zero, inflateBack() will return with an error.  Neither in() nor out()
+   are permitted to change the contents of the window provided to
+   inflateBackInit(), which is also the buffer that out() uses to write from.
+   The length written by out() will be at most the window size.  Any non-zero
+   amount of input may be provided by in().
+
+     For convenience, inflateBack() can be provided input on the first call by
+   setting strm->next_in and strm->avail_in.  If that input is exhausted, then
+   in() will be called.  Therefore strm->next_in must be initialized before
+   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called
+   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in
+   must also be initialized, and then if strm->avail_in is not zero, input will
+   initially be taken from strm->next_in[0 ..  strm->avail_in - 1].
+
+     The in_desc and out_desc parameters of inflateBack() is passed as the
+   first parameter of in() and out() respectively when they are called.  These
+   descriptors can be optionally used to pass any information that the caller-
+   supplied in() and out() functions need to do their job.
+
+     On return, inflateBack() will set strm->next_in and strm->avail_in to
+   pass back any unused input that was provided by the last in() call.  The
+   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+   if in() or out() returned an error, Z_DATA_ERROR if there was a format error
+   in the deflate stream (in which case strm->msg is set to indicate the nature
+   of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
+   In the case of Z_BUF_ERROR, an input or output error can be distinguished
+   using strm->next_in which will be Z_NULL only if in() returned an error.  If
+   strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
+   non-zero.  (in() will always be called before out(), so strm->next_in is
+   assured to be defined if out() returns non-zero.) Note that inflateBack()
+   cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+     All memory allocated by inflateBackInit() is freed.
+
+     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+   state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+     1.0: size of uInt
+     3.2: size of uLong
+     5.4: size of voidpf (pointer)
+     7.6: size of z_off_t
+
+    Compiler, assembler, and debug options:
+     8: DEBUG
+     9: ASMV or ASMINF -- use ASM code
+     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+     11: 0 (reserved)
+
+    One-time table building (smaller code, but not thread-safe if true):
+     12: BUILDFIXED -- build static block decoding tables when needed
+     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+     14,15: 0 (reserved)
+
+    Library content (indicates missing functionality):
+     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+                          deflate code when not needed)
+     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+                    and decode gzip streams (to avoid linking crc code)
+     18-19: 0 (reserved)
+
+    Operation variations (changes in library functionality):
+     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+     21: FASTEST -- deflate algorithm with only one, lowest compression level
+     22,23: 0 (reserved)
+
+    The sprintf variant used by gzprintf (zero is best):
+     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+     26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+    Remainder:
+     27-31: 0 (reserved)
+ */
+
+
+                        /* utility functions */
+
+/*
+     The following utility functions are implemented on top of the basic
+   stream-oriented functions.  To simplify the interface, some default options
+   are assumed (compression level and memory usage, standard memory allocation
+   functions).  The source code of these utility functions can be modified if
+   you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
+                                 const Bytef *source, uLong sourceLen));
+/*
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer.  Upon entry, destLen is the total size
+   of the destination buffer, which must be at least the value returned by
+   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
+   compressed buffer.
+
+     compress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
+                                  const Bytef *source, uLong sourceLen,
+                                  int level));
+/*
+     Compresses the source buffer into the destination buffer.  The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer.  Upon entry, destLen is the total size of the
+   destination buffer, which must be at least the value returned by
+   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
+   compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+     compressBound() returns an upper bound on the compressed size after
+   compress() or compress2() on sourceLen bytes.  It would be used before a
+   compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
+                                   const Bytef *source, uLong sourceLen));
+/*
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer.  Upon entry, destLen is the total size
+   of the destination buffer, which must be large enough to hold the entire
+   uncompressed data.  (The size of the uncompressed data must have been saved
+   previously by the compressor and transmitted to the decompressor by some
+   mechanism outside the scope of this compression library.) Upon exit, destLen
+   is the actual size of the uncompressed buffer.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
+*/
+
+
+                        /* gzip file access functions */
+
+/*
+     This library supports reading and writing files in gzip (.gz) format with
+   an interface similar to that of stdio, using the functions that start with
+   "gz".  The gzip format is different from the zlib format.  gzip is a gzip
+   wrapper, documented in RFC 1952, wrapped around a deflate stream.
+*/
+
+typedef voidp gzFile;       /* opaque gzip file descriptor */
+
+/*
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+
+     Opens a gzip (.gz) file for reading or writing.  The mode parameter is as
+   in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
+   a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
+   compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
+   for fixed code compression as in "wb9F".  (See the description of
+   deflateInit2 for more information about the strategy parameter.) Also "a"
+   can be used instead of "w" to request that the gzip stream that will be
+   written be appended to the file.  "+" will result in an error, since reading
+   and writing to the same gzip file is not supported.
+
+     gzopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.
+
+     gzopen returns NULL if the file could not be opened, if there was
+   insufficient memory to allocate the gzFile state, or if an invalid mode was
+   specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
+   errno can be checked to determine if the reason gzopen failed was that the
+   file could not be opened.
+*/
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+     gzdopen associates a gzFile with the file descriptor fd.  File descriptors
+   are obtained from calls like open, dup, creat, pipe or fileno (if the file
+   has been previously opened with fopen).  The mode parameter is as in gzopen.
+
+     The next call of gzclose on the returned gzFile will also close the file
+   descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
+   fd.  If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
+   mode);.  The duplicated descriptor should be saved to avoid a leak, since
+   gzdopen does not close fd if it fails.
+
+     gzdopen returns NULL if there was insufficient memory to allocate the
+   gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
+   provided, or '+' was provided), or if fd is -1.  The file descriptor is not
+   used until the next gz* read, write, seek, or close operation, so gzdopen
+   will not detect if fd is invalid (unless fd is -1).
+*/
+
+ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
+/*
+     Set the internal buffer size used by this library's functions.  The
+   default buffer size is 8192 bytes.  This function must be called after
+   gzopen() or gzdopen(), and before any other calls that read or write the
+   file.  The buffer memory allocation is always deferred to the first read or
+   write.  Two buffers are allocated, either both of the specified size when
+   writing, or one of the specified size and the other twice that size when
+   reading.  A larger buffer size of, for example, 64K or 128K bytes will
+   noticeably increase the speed of decompression (reading).
+
+     The new buffer size also affects the maximum length for gzprintf().
+
+     gzbuffer() returns 0 on success, or -1 on failure, such as being called
+   too late.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+     Dynamically update the compression level or strategy.  See the description
+   of deflateInit2 for the meaning of these parameters.
+
+     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+   opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+     Reads the given number of uncompressed bytes from the compressed file.  If
+   the input file was not in gzip format, gzread copies the given number of
+   bytes into the buffer.
+
+     After reaching the end of a gzip stream in the input, gzread will continue
+   to read, looking for another gzip stream, or failing that, reading the rest
+   of the input file directly without decompression.  The entire input file
+   will be read if gzread is called until it returns less than the requested
+   len.
+
+     gzread returns the number of uncompressed bytes actually read, less than
+   len for end of file, or -1 for error.
+*/
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+                                voidpc buf, unsigned len));
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of uncompressed bytes written or 0 in case of
+   error.
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
+/*
+     Converts, formats, and writes the arguments to the compressed file under
+   control of the format string, as in fprintf.  gzprintf returns the number of
+   uncompressed bytes actually written, or 0 in case of error.  The number of
+   uncompressed bytes written is limited to 8191, or one less than the buffer
+   size given to gzbuffer().  The caller should assure that this limit is not
+   exceeded.  If it is exceeded, then gzprintf() will return an error (0) with
+   nothing written.  In this case, there may also be a buffer overflow with
+   unpredictable consequences, which is possible only if zlib was compiled with
+   the insecure functions sprintf() or vsprintf() because the secure snprintf()
+   or vsnprintf() functions were not available.  This can be determined using
+   zlibCompileFlags().
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+     Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+
+     gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+     Reads bytes from the compressed file until len-1 characters are read, or a
+   newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  If any characters are read or if len == 1, the
+   string is terminated with a null character.  If no characters are read due
+   to an end-of-file or len < 1, then the buffer is left untouched.
+
+     gzgets returns buf which is a null-terminated string, or it returns NULL
+   for end-of-file or in case of error.  If there was an error, the contents at
+   buf are indeterminate.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+     Writes c, converted to an unsigned char, into the compressed file.  gzputc
+   returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+     Reads one byte from the compressed file.  gzgetc returns this byte or -1
+   in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+     Push one character back onto the stream to be read as the first character
+   on the next read.  At least one character of push-back is allowed.
+   gzungetc() returns the character pushed, or -1 on failure.  gzungetc() will
+   fail if c is -1, and may fail if a character has been pushed but not read
+   yet.  If gzungetc is used immediately after gzopen or gzdopen, at least the
+   output buffer size of pushed characters is allowed.  (See gzbuffer above.)
+   The pushed character will be discarded if the stream is repositioned with
+   gzseek() or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+     Flushes all pending output into the compressed file.  The parameter flush
+   is as in the deflate() function.  The return value is the zlib error number
+   (see function gzerror below).  gzflush is only permitted when writing.
+
+     If the flush parameter is Z_FINISH, the remaining data is written and the
+   gzip stream is completed in the output.  If gzwrite() is called again, a new
+   gzip stream will be started in the output.  gzread() is able to read such
+   concatented gzip streams.
+
+     gzflush should be called only when strictly necessary because it will
+   degrade compression if called too often.
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+                                   z_off_t offset, int whence));
+
+     Sets the starting position for the next gzread or gzwrite on the given
+   compressed file.  The offset represents a number of bytes in the
+   uncompressed data stream.  The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow.  If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+     gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
+
+     Returns the starting position for the next gzread or gzwrite on the given
+   compressed file.  This position represents a number of bytes in the
+   uncompressed data stream, and is zero when starting, even if appending or
+   reading a gzip stream from the middle of a file using gzdopen().
+
+     gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
+
+     Returns the current offset in the file being read or written.  This offset
+   includes the count of bytes that precede the gzip stream, for example when
+   appending or when using gzdopen() for reading.  When reading, the offset
+   does not include as yet unused buffered input.  This information can be used
+   for a progress indicator.  On error, gzoffset() returns -1.
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+     Returns true (1) if the end-of-file indicator has been set while reading,
+   false (0) otherwise.  Note that the end-of-file indicator is set only if the
+   read tried to go past the end of the input, but came up short.  Therefore,
+   just like feof(), gzeof() may return false even if there is no more data to
+   read, in the event that the last read request was for the exact number of
+   bytes remaining in the input file.  This will happen if the input file size
+   is an exact multiple of the buffer size.
+
+     If gzeof() returns true, then the read functions will return no more data,
+   unless the end-of-file indicator is reset by gzclearerr() and the input file
+   has grown since the previous end of file was detected.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+     Returns true (1) if file is being copied directly while reading, or false
+   (0) if file is a gzip stream being decompressed.  This state can change from
+   false to true while reading the input file if the end of a gzip stream is
+   reached, but is followed by data that is not another gzip stream.
+
+     If the input file is empty, gzdirect() will return true, since the input
+   does not contain a gzip stream.
+
+     If gzdirect() is used immediately after gzopen() or gzdopen() it will
+   cause buffers to be allocated to allow reading the file to determine if it
+   is a gzip file.  Therefore if gzbuffer() is used, it should be called before
+   gzdirect().
+*/
+
+ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
+/*
+     Flushes all pending output if necessary, closes the compressed file and
+   deallocates the (de)compression state.  Note that once file is closed, you
+   cannot call gzerror with file, since its structures have been deallocated.
+   gzclose must not be called more than once on the same file, just as free
+   must not be called more than once on the same allocation.
+
+     gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
+   file operation error, or Z_OK on success.
+*/
+
+ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
+ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
+/*
+     Same as gzclose(), but gzclose_r() is only for use when reading, and
+   gzclose_w() is only for use when writing or appending.  The advantage to
+   using these instead of gzclose() is that they avoid linking in zlib
+   compression or decompression code that is not used when only reading or only
+   writing respectively.  If gzclose() is used, then both compression and
+   decompression code will be included the application when linking to a static
+   zlib library.
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+     Returns the error message for the last error which occurred on the given
+   compressed file.  errnum is set to zlib error number.  If an error occurred
+   in the file system and not in the compression library, errnum is set to
+   Z_ERRNO and the application may consult errno to get the exact error code.
+
+     The application must not modify the returned string.  Future calls to
+   this function may invalidate the previously returned string.  If file is
+   closed, then the string previously returned by gzerror will no longer be
+   available.
+
+     gzerror() should be used to distinguish errors from end-of-file for those
+   functions above that do not distinguish those cases in their return values.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+     Clears the error and end-of-file flags for file.  This is analogous to the
+   clearerr() function in stdio.  This is useful for continuing to read a gzip
+   file that is being written concurrently.
+*/
+
+
+                        /* checksum functions */
+
+/*
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the compression
+   library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum.  If buf is Z_NULL, this function returns the
+   required initial value for the checksum.
+
+     An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster.
+
+   Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+/*
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+                                          z_off_t len2));
+
+     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1
+   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of
+   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
+*/
+
+ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
+/*
+     Update a running CRC-32 with the bytes buf[0..len-1] and return the
+   updated CRC-32.  If buf is Z_NULL, this function returns the required
+   initial value for the for the crc.  Pre- and post-conditioning (one's
+   complement) is performed within this function so it shouldn't be done by the
+   application.
+
+   Usage example:
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+     Combine two CRC-32 check values into one.  For two sequences of bytes,
+   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32
+   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+   len2.
+*/
+
+
+                        /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
+                                      int windowBits, int memLevel,
+                                      int strategy, const char *version,
+                                      int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
+                                      const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+                                         unsigned char FAR *window,
+                                         const char *version,
+                                         int stream_size));
+#define deflateInit(strm, level) \
+        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+        inflateBackInit_((strm), (windowBits), (window), \
+                                            ZLIB_VERSION, sizeof(z_stream))
+
+/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
+ * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
+ * both are true, the application gets the *64 functions, and the regular
+ * functions are changed to 64 bits) -- in case these are set on systems
+ * without large file support, _LFS64_LARGEFILE must also be true
+ */
+#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
+   ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+   ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
+   ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
+   ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+   ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
+   ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
+#endif
+
+#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0
+#  define gzopen gzopen64
+#  define gzseek gzseek64
+#  define gztell gztell64
+#  define gzoffset gzoffset64
+#  define adler32_combine adler32_combine64
+#  define crc32_combine crc32_combine64
+#  ifdef _LARGEFILE64_SOURCE
+     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
+     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
+     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
+     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+#  endif
+#else
+   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
+   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
+   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
+   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
+   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+#endif
+
+/* hack for buggy compilers */
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+    struct internal_state {int dummy;};
+#endif
+
+/* undocumented functions */
+ZEXTERN const char   * ZEXPORT zError           OF((int));
+ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));
+ZEXTERN const uLongf * ZEXPORT get_crc_table    OF((void));
+ZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));
+
+ABC_NAMESPACE_HEADER_END
+
+#endif /* ZLIB_H */
diff --git a/abc-build/src/misc/zlib/zutil.c b/abc-build/src/misc/zlib/zutil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/zutil.c
@@ -0,0 +1,318 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2005, 2010 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc/util/abc_global.h"
+
+#include "zutil.h"
+
+
+ABC_NAMESPACE_IMPL_START
+
+
+#ifndef NO_DUMMY_DECL
+struct internal_state      {int dummy;}; /* for buggy compilers */
+#endif
+
+const char * const z_errmsg[10] = {
+"need dictionary",     /* Z_NEED_DICT       2  */
+"stream end",          /* Z_STREAM_END      1  */
+"",                    /* Z_OK              0  */
+"file error",          /* Z_ERRNO         (-1) */
+"stream error",        /* Z_STREAM_ERROR  (-2) */
+"data error",          /* Z_DATA_ERROR    (-3) */
+"insufficient memory", /* Z_MEM_ERROR     (-4) */
+"buffer error",        /* Z_BUF_ERROR     (-5) */
+"incompatible version",/* Z_VERSION_ERROR (-6) */
+""};
+
+
+const char * ZEXPORT zlibVersion()
+{
+    return ZLIB_VERSION;
+}
+
+uLong ZEXPORT zlibCompileFlags()
+{
+    uLong flags;
+
+    flags = 0;
+    switch ((int)(sizeof(uInt))) {
+    case 2:     break;
+    case 4:     flags += 1;     break;
+    case 8:     flags += 2;     break;
+    default:    flags += 3;
+    }
+    switch ((int)(sizeof(uLong))) {
+    case 2:     break;
+    case 4:     flags += 1 << 2;        break;
+    case 8:     flags += 2 << 2;        break;
+    default:    flags += 3 << 2;
+    }
+    switch ((int)(sizeof(voidpf))) {
+    case 2:     break;
+    case 4:     flags += 1 << 4;        break;
+    case 8:     flags += 2 << 4;        break;
+    default:    flags += 3 << 4;
+    }
+    switch ((int)(sizeof(z_off_t))) {
+    case 2:     break;
+    case 4:     flags += 1 << 6;        break;
+    case 8:     flags += 2 << 6;        break;
+    default:    flags += 3 << 6;
+    }
+#ifdef DEBUG
+    flags += 1 << 8;
+#endif
+#if defined(ASMV) || defined(ASMINF)
+    flags += 1 << 9;
+#endif
+#ifdef ZLIB_WINAPI
+    flags += 1 << 10;
+#endif
+#ifdef BUILDFIXED
+    flags += 1 << 12;
+#endif
+#ifdef DYNAMIC_CRC_TABLE
+    flags += 1 << 13;
+#endif
+#ifdef NO_GZCOMPRESS
+    flags += 1L << 16;
+#endif
+#ifdef NO_GZIP
+    flags += 1L << 17;
+#endif
+#ifdef PKZIP_BUG_WORKAROUND
+    flags += 1L << 20;
+#endif
+#ifdef FASTEST
+    flags += 1L << 21;
+#endif
+#ifdef STDC
+#  ifdef NO_vsnprintf
+        flags += 1L << 25;
+#    ifdef HAS_vsprintf_void
+        flags += 1L << 26;
+#    endif
+#  else
+#    ifdef HAS_vsnprintf_void
+        flags += 1L << 26;
+#    endif
+#  endif
+#else
+        flags += 1L << 24;
+#  ifdef NO_snprintf
+        flags += 1L << 25;
+#    ifdef HAS_sprintf_void
+        flags += 1L << 26;
+#    endif
+#  else
+#    ifdef HAS_snprintf_void
+        flags += 1L << 26;
+#    endif
+#  endif
+#endif
+    return flags;
+}
+
+#ifdef DEBUG
+
+#  ifndef verbose
+#    define verbose 0
+#  endif
+int ZLIB_INTERNAL z_verbose = verbose;
+
+void ZLIB_INTERNAL z_error (m)
+    char *m;
+{
+    fprintf(stderr, "%s\n", m);
+    exit(1);
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(int err)
+{
+    return ERR_MSG(err);
+}
+
+#if defined(_WIN32_WCE)
+    /* The Microsoft C Run-Time Library for Windows CE doesn't have
+     * errno.  We define it as a global variable to simplify porting.
+     * Its value is always 0 and should not be used.
+     */
+    int errno = 0;
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt  len)
+{
+    if (len == 0) return;
+    do {
+        *dest++ = *source++; /* ??? to be unrolled */
+    } while (--len != 0);
+}
+
+int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt  len)
+{
+    uInt j;
+
+    for (j = 0; j < len; j++) {
+        if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+    }
+    return 0;
+}
+
+void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt  len)
+{
+    if (len == 0) return;
+    do {
+        *dest++ = 0;  /* ??? to be unrolled */
+    } while (--len != 0);
+}
+#endif
+
+
+#ifdef SYS16BIT
+
+#ifdef __TURBOC__
+/* Turbo C in 16-bit mode */
+
+#  define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+    voidpf org_ptr;
+    voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+    voidpf buf = opaque; /* just to make some compilers happy */
+    ulg bsize = (ulg)items*size;
+
+    /* If we allocate less than 65520 bytes, we assume that farmalloc
+     * will return a usable pointer which doesn't have to be normalized.
+     */
+    if (bsize < 65520L) {
+        buf = farmalloc(bsize);
+        if (*(ush*)&buf != 0) return buf;
+    } else {
+        buf = farmalloc(bsize + 16L);
+    }
+    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+    table[next_ptr].org_ptr = buf;
+
+    /* Normalize the pointer to seg:0 */
+    *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+    *(ush*)&buf = 0;
+    table[next_ptr++].new_ptr = buf;
+    return buf;
+}
+
+void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
+{
+    int n;
+    if (*(ush*)&ptr != 0) { /* object < 64K */
+        farfree(ptr);
+        return;
+    }
+    /* Find the original pointer */
+    for (n = 0; n < next_ptr; n++) {
+        if (ptr != table[n].new_ptr) continue;
+
+        farfree(table[n].org_ptr);
+        while (++n < next_ptr) {
+            table[n-1] = table[n];
+        }
+        next_ptr--;
+        return;
+    }
+    ptr = opaque; /* just to make some compilers happy */
+    Assert(0, "zcfree: ptr not found");
+}
+
+#endif /* __TURBOC__ */
+
+
+#ifdef M_I86
+/* Microsoft C in 16-bit mode */
+
+#  define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+#  define _halloc  halloc
+#  define _hfree   hfree
+#endif
+
+voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size)
+{
+    if (opaque) opaque = 0; /* to make compiler happy */
+    return _halloc((long)items, size);
+}
+
+void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
+{
+    if (opaque) opaque = 0; /* to make compiler happy */
+    _hfree(ptr);
+}
+
+#endif /* M_I86 */
+
+#endif /* SYS16BIT */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp  malloc OF((uInt size));
+extern voidp  calloc OF((uInt items, uInt size));
+extern void   free   OF((voidpf ptr));
+#endif
+
+voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+    if (opaque) items += size - size; /* make compiler happy */
+    return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+                              (voidpf)calloc(items, size);
+}
+
+void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
+{
+    free(ptr);
+    if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
+
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/misc/zlib/zutil.h b/abc-build/src/misc/zlib/zutil.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/misc/zlib/zutil.h
@@ -0,0 +1,288 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2010 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZUTIL_H
+#define ZUTIL_H
+
+#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ)
+#  define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+#else
+#  define ZLIB_INTERNAL
+#endif
+
+#include "zlib.h"
+
+#ifdef STDC
+#  if !(defined(_WIN32_WCE) && defined(_MSC_VER))
+#    include <stddef.h>
+#  endif
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+
+ABC_NAMESPACE_HEADER_START
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char  uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long  ulg;
+
+extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+  return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+        /* common constants */
+
+#ifndef DEF_WBITS
+#  define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+/* The three kinds of block type */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+        /* target dependencies */
+
+#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
+#  define OS_CODE  0x00
+#  if defined(__TURBOC__) || defined(__BORLANDC__)
+#    if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+       /* Allow compilation with ANSI keywords only enabled */
+       void _Cdecl farfree( void *block );
+       void *_Cdecl farmalloc( unsigned long nbytes );
+#    else
+ABC_NAMESPACE_HEADER_END
+#      include <alloc.h>
+ABC_NAMESPACE_HEADER_START
+#    endif
+#  else /* MSC or DJGPP */
+ABC_NAMESPACE_HEADER_END
+#    include <malloc.h>
+ABC_NAMESPACE_HEADER_START
+#  endif
+#endif
+
+#ifdef AMIGA
+#  define OS_CODE  0x01
+#endif
+
+#if defined(VAXC) || defined(VMS)
+#  define OS_CODE  0x02
+#  define F_OPEN(name, mode) \
+     fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#if defined(ATARI) || defined(atarist)
+#  define OS_CODE  0x05
+#endif
+
+#ifdef OS2
+#  define OS_CODE  0x06
+#  ifdef M_I86
+ABC_NAMESPACE_HEADER_END
+#    include <malloc.h>
+ABC_NAMESPACE_HEADER_START
+#  endif
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+#  define OS_CODE  0x07
+#  if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+ABC_NAMESPACE_HEADER_END
+#    include <unix.h> /* for fdopen */
+ABC_NAMESPACE_HEADER_START
+#  else
+#    ifndef fdopen
+#      define fdopen(fd,mode) NULL /* No fdopen() */
+#    endif
+#  endif
+#endif
+
+#ifdef TOPS20
+#  define OS_CODE  0x0a
+#endif
+
+#ifdef WIN32
+#  ifndef __CYGWIN__  /* Cygwin is Unix, not Win32 */
+#    define OS_CODE  0x0b
+#  endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+#  define OS_CODE  0x0f
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+#  define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
+#  if defined(_WIN32_WCE)
+#    define fdopen(fd,mode) NULL /* No fdopen() */
+#    ifndef _PTRDIFF_T_DEFINED
+       typedef int ptrdiff_t;
+#      define _PTRDIFF_T_DEFINED
+#    endif
+#  else
+#    define fdopen(fd,type)  _fdopen(fd,type)
+#  endif
+#endif
+
+#if defined(__BORLANDC__)
+  #pragma warn -8004
+  #pragma warn -8008
+  #pragma warn -8066
+#endif
+
+/* provide prototypes for these when building zlib without LFS */
+#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
+    ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+    ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+#endif
+
+        /* common defaults */
+
+#ifndef OS_CODE
+#  define OS_CODE  0x03  /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+#  define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+         /* functions */
+
+#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
+#  ifndef HAVE_VSNPRINTF
+#    define HAVE_VSNPRINTF
+#  endif
+#endif
+#if defined(__CYGWIN__)
+#  ifndef HAVE_VSNPRINTF
+#    define HAVE_VSNPRINTF
+#  endif
+#endif
+#ifndef HAVE_VSNPRINTF
+#  ifdef MSDOS
+     /* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+        but for now we just assume it doesn't. */
+#    define NO_vsnprintf
+#  endif
+#  ifdef __TURBOC__
+#    define NO_vsnprintf
+#  endif
+#  ifdef WIN32
+     /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+#    if !defined(vsnprintf) && !defined(NO_vsnprintf)
+#      if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
+#         define vsnprintf _vsnprintf
+#      endif
+#    endif
+#  endif
+#  ifdef __SASC
+#    define NO_vsnprintf
+#  endif
+#endif
+#ifdef VMS
+#  define NO_vsnprintf
+#endif
+
+#if defined(pyr)
+#  define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+  * You may have to use the same strategy for Borland C (untested).
+  * The __SC__ check is for Symantec.
+  */
+#  define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+#  define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+#  ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+#    define zmemcpy _fmemcpy
+#    define zmemcmp _fmemcmp
+#    define zmemzero(dest, len) _fmemset(dest, 0, len)
+#  else
+#    define zmemcpy memcpy
+#    define zmemcmp memcmp
+#    define zmemzero(dest, len) memset(dest, 0, len)
+#  endif
+#else
+   void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+   int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
+   void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef DEBUG
+   ABC_NAMESPACE_HEADER_END
+#  include <stdio.h>
+ABC_NAMESPACE_HEADER_START
+   extern int ZLIB_INTERNAL z_verbose;
+   extern void ZLIB_INTERNAL z_error OF((char *m));
+#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+#  define Trace(x) {if (z_verbose>=0) fprintf x ;}
+#  define Tracev(x) {if (z_verbose>0) fprintf x ;}
+#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+
+voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
+                        unsigned size));
+void ZLIB_INTERNAL zcfree  OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+           (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+ABC_NAMESPACE_HEADER_END
+
+#endif /* ZUTIL_H */
diff --git a/abc-build/src/opt/cgt/cgt.h b/abc-build/src/opt/cgt/cgt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cgt/cgt.h
@@ -0,0 +1,87 @@
+/**CFile****************************************************************
+
+  FileName    [cgt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Clock gating package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cgt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__cgt__cgt_h
+#define ABC__aig__cgt__cgt_h
+
+
+/* 
+    The algorithm implemented in this package is based on the paper:
+    A. Hurst. "Automatic synthesis of clock gating logic with controlled 
+    netlist perturbation", DAC 2008.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Cgt_Par_t_ Cgt_Par_t;
+struct Cgt_Par_t_
+{
+    int          nLevelMax;      // the max number of levels to look for clock-gates
+    int          nCandMax;       // the max number of candidates at each node
+    int          nOdcMax;        // the max number of ODC levels to consider
+    int          nConfMax;       // the max number of conflicts at a node
+    int          nVarsMin;       // the min number of variables to recycle the SAT solver
+    int          nFlopsMin;      // the min number of flops needed to recycle the SAT solver
+    int          fAreaOnly;      // derive clock gating to minimize area
+    int          fVerbose;       // verbosity flag
+    int          fVeryVerbose;   // verbosity flag
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== cgtCore.c ==========================================================*/
+extern void            Cgt_SetDefaultParams( Cgt_Par_t * p );
+extern Vec_Vec_t *     Cgt_ClockGatingCandidates( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars, Vec_Int_t * vUseful );
+extern Vec_Vec_t *     Cgt_ClockGatingInt( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars, Vec_Int_t * vUseful );
+extern Aig_Man_t *     Cgt_ClockGating( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/cgt/cgtAig.c b/abc-build/src/opt/cgt/cgtAig.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cgt/cgtAig.c
@@ -0,0 +1,601 @@
+/**CFile****************************************************************
+
+  FileName    [cgtAig.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Clock gating package.]
+
+  Synopsis    [Creates AIG to compute clock-gating.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cgtAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cgtInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes transitive fanout cone of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cgt_ManDetectCandidates_rec( Aig_Man_t * pAig, Vec_Int_t * vUseful, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands )
+{
+    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(pAig, pObj);
+    if ( Aig_ObjIsNode(pObj) )
+    {
+        Cgt_ManDetectCandidates_rec( pAig, vUseful, Aig_ObjFanin0(pObj), nLevelMax, vCands );
+        Cgt_ManDetectCandidates_rec( pAig, vUseful, Aig_ObjFanin1(pObj), nLevelMax, vCands );
+    }
+    if ( Aig_ObjLevel(pObj) <= nLevelMax && (vUseful == NULL || Vec_IntEntry(vUseful, Aig_ObjId(pObj))) )
+        Vec_PtrPush( vCands, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes transitive fanout cone of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cgt_ManDetectCandidates( Aig_Man_t * pAig, Vec_Int_t * vUseful, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands )
+{
+    Vec_PtrClear( vCands );
+    if ( !Aig_ObjIsNode(pObj) )
+        return;
+    Aig_ManIncrementTravId( pAig );
+    Cgt_ManDetectCandidates_rec( pAig, vUseful, pObj, nLevelMax, vCands );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes transitive fanout cone of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cgt_ManDetectFanout_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_Ptr_t * vFanout )
+{
+    Aig_Obj_t * pFanout;
+    int f, iFanout = -1;
+    if ( Aig_ObjIsCo(pObj) || Aig_ObjLevel(pObj) > nOdcMax )
+        return;
+    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(pAig, pObj);
+    Vec_PtrPush( vFanout, pObj );
+    Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f )
+        Cgt_ManDetectFanout_rec( pAig, pFanout, nOdcMax, vFanout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes transitive fanout cone of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cgt_ManDetectFanout( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_Ptr_t * vFanout )
+{
+    Aig_Obj_t * pFanout;
+    int i, k, f, iFanout = -1;
+    // collect visited nodes
+    Vec_PtrClear( vFanout );
+    Aig_ManIncrementTravId( pAig );
+    Cgt_ManDetectFanout_rec( pAig, pObj, nOdcMax, vFanout );
+    // remove those nodes whose fanout is included
+    k = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i )
+    {
+        // go through the fanouts of this node
+        Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f )
+            if ( !Aig_ObjIsTravIdCurrent(pAig, pFanout) )
+                break;
+        if ( f == Aig_ObjRefs(pObj) ) // all fanouts are included
+            continue;
+        Vec_PtrWriteEntry( vFanout, k++, pObj );
+    }
+    Vec_PtrShrink( vFanout, k );
+    Vec_PtrSort( vFanout, (int (*)(void))Aig_ObjCompareIdIncrease );
+    assert( Vec_PtrSize(vFanout) > 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes visited nodes in the topological order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cgt_ManCollectVisited_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vVisited )
+{
+    if ( Aig_ObjIsCi(pObj) )
+        return;
+    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(pAig, pObj);
+    assert( Aig_ObjIsNode(pObj) );
+    Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin0(pObj), vVisited );
+    Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin1(pObj), vVisited );
+    Vec_PtrPush( vVisited, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes visited nodes in the topological order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cgt_ManCollectVisited( Aig_Man_t * pAig, Vec_Ptr_t * vFanout, Vec_Ptr_t * vVisited )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Vec_PtrClear( vVisited );
+    Aig_ManIncrementTravId( pAig );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i )
+        Cgt_ManCollectVisited_rec( pAig, pObj, vVisited );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Aig_Obj_t *  Aig_ObjChild0CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj )  
+{ return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId0(pObj)), Aig_ObjFaninC0(pObj));  }
+static inline Aig_Obj_t *  Aig_ObjChild1CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj )  
+{ return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId1(pObj)), Aig_ObjFaninC1(pObj));  }
+
+/**Function*************************************************************
+
+  Synopsis    [Derives miter for clock-gating.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Cgt_ManConstructCareCondition( Cgt_Man_t * p, Aig_Man_t * pNew, Aig_Obj_t * pObjLo, Vec_Ptr_t * vCopy0, Vec_Ptr_t * vCopy1 )
+{
+    Aig_Obj_t * pMiter, * pObj, * pTemp;
+    int i;
+    assert( Aig_ObjIsCi(pObjLo) );
+    // detect nodes and their cone
+    Cgt_ManDetectFanout( p->pAig, pObjLo, p->pPars->nOdcMax, p->vFanout );
+    Cgt_ManCollectVisited( p->pAig, p->vFanout, p->vVisited );
+    // add new variables if the observability condition depends on PI variables
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vVisited, pObj, i )
+    {
+        assert( Aig_ObjIsNode(pObj) );
+        if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin0(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId0(pObj)) == NULL )
+        {
+            pTemp = Aig_ObjCreateCi( pNew );
+            Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId0(pObj), pTemp );
+            Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId0(pObj), pTemp );
+        }
+        if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin1(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId1(pObj)) == NULL )
+        {
+            pTemp = Aig_ObjCreateCi( pNew );
+            Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId1(pObj), pTemp );
+            Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId1(pObj), pTemp );
+        }
+    }
+    // construct AIGs for the nodes
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vVisited, pObj, i )
+    {
+        pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy0, pObj), Aig_ObjChild1CopyVec(vCopy0, pObj) );
+        Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObj), pTemp );
+        pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy1, pObj), Aig_ObjChild1CopyVec(vCopy1, pObj) );
+        Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObj), pTemp );
+    }
+    // construct the care miter
+    pMiter = Aig_ManConst0( pNew );
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanout, pObj, i )
+    {
+        pTemp = Aig_Exor( pNew, (Aig_Obj_t *)Vec_PtrEntry(vCopy0, Aig_ObjId(pObj)), (Aig_Obj_t *)Vec_PtrEntry(vCopy1, Aig_ObjId(pObj)) );
+        pMiter = Aig_Or( pNew, pMiter, pTemp );
+    }
+    return pMiter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives AIG for clock-gating.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pCare, * pMiter;
+    Vec_Ptr_t * vCopy0, * vCopy1;
+    int i;
+    assert( Aig_ManRegNum(p->pAig) );
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p->pAig) );
+    pNew->pName = Abc_UtilStrsav( "CG_miter" );
+    // build the first frame
+    Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p->pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    Aig_ManForEachNode( p->pAig, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+//    Saig_ManForEachPo( p->pAig, pObj, i )
+//        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    if ( p->pPars->nOdcMax > 0 )
+    {
+        // create storage for observability conditions
+        vCopy0 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) );
+        vCopy1 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) );
+        // initialize register outputs
+        Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+        {
+            Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) );
+            Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) );
+        }
+        // compute observability condition for each latch output
+        Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+        {
+            // set the constants
+            Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ManConst0(pNew) );
+            Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ManConst1(pNew) );
+            // compute condition
+            pCare = Cgt_ManConstructCareCondition( p, pNew, pObjLo, vCopy0, vCopy1 );
+            // restore the values
+            Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) );
+            Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) );
+            // compute the miter
+            pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) );
+            pMiter = Aig_And( pNew, pMiter, pCare );
+            pObjLi->pData = Aig_ObjCreateCo( pNew, pMiter );
+        }
+        Vec_PtrFree( vCopy0 );
+        Vec_PtrFree( vCopy1 );
+    }
+    else
+    {
+        // construct clock-gating miters for each register input
+        Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+        {
+            pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) );
+            pObjLi->pData = Aig_ObjCreateCo( pNew, pMiter );
+        }
+    }
+    Aig_ManCleanup( pNew );
+    Aig_ManSetCioIds( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds relevant constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Cgt_ManConstructCare_rec( Aig_Man_t * pCare, Aig_Obj_t * pObj, Aig_Man_t * pNew )
+{
+    Aig_Obj_t * pObj0, * pObj1;
+    if ( Aig_ObjIsTravIdCurrent( pCare, pObj ) )
+        return (Aig_Obj_t *)pObj->pData;
+    Aig_ObjSetTravIdCurrent( pCare, pObj );
+    if ( Aig_ObjIsCi(pObj) )
+        return (Aig_Obj_t *)(pObj->pData = NULL);
+    pObj0 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pObj), pNew );
+    if ( pObj0 == NULL )
+        return (Aig_Obj_t *)(pObj->pData = NULL);
+    pObj1 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin1(pObj), pNew );
+    if ( pObj1 == NULL )
+        return (Aig_Obj_t *)(pObj->pData = NULL);
+    pObj0 = Aig_NotCond( pObj0, Aig_ObjFaninC0(pObj) );
+    pObj1 = Aig_NotCond( pObj1, Aig_ObjFaninC1(pObj) );
+    return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, pObj0, pObj1 ));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Builds constraints belonging to the given partition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cgt_ManConstructCare( Aig_Man_t * pNew, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, Vec_Ptr_t * vLeaves )
+{
+    Vec_Int_t * vOuts;
+    Aig_Obj_t * pLeaf, * pPi, * pPo, * pObjAig;
+    int i, k, iOut;
+    // go through the PIs of the partition
+    // label the corresponding PIs of the care set
+    Aig_ManIncrementTravId( pCare );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, i )
+    {
+        pPi = Aig_ManCi( pCare, Aig_ObjCioId(pLeaf) );
+        Aig_ObjSetTravIdCurrent( pCare, pPi );
+        pPi->pData = pLeaf->pData;
+    }
+    // construct the constraints
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, i )
+    {
+        vOuts = Vec_VecEntryInt( vSuppsInv, Aig_ObjCioId(pLeaf) );
+        Vec_IntForEachEntry( vOuts, iOut, k )
+        {
+            pPo = Aig_ManCo( pCare, iOut );
+            if ( Aig_ObjIsTravIdCurrent( pCare, pPo ) )
+                continue;
+            Aig_ObjSetTravIdCurrent( pCare, pPo );
+            if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(pCare) )
+                continue;
+            pObjAig = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pPo), pNew );
+            if ( pObjAig == NULL )
+                continue;
+            pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) );
+            Aig_ObjCreateCo( pNew, pObjAig );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG recursively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Cgt_ManDupPartition_rec( Aig_Man_t * pNew, Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vLeaves )
+{
+    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+        return (Aig_Obj_t *)pObj->pData;
+    Aig_ObjSetTravIdCurrent(pAig, pObj);
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        pObj->pData = Aig_ObjCreateCi( pNew );
+        Vec_PtrPush( vLeaves, pObj );
+        return (Aig_Obj_t *)pObj->pData;
+    }
+    Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin0(pObj), vLeaves );
+    Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin1(pObj), vLeaves );
+    return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates register outputs starting from the given one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pFrame, int nVarsMin, int nFlopsMin, int iStart, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, int * pnOutputs )
+{
+    Vec_Ptr_t * vRoots, * vLeaves, * vPos;
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( Aig_ManRegNum(pFrame) == 0 );
+    vRoots = Vec_PtrAlloc( 100 );
+    vLeaves = Vec_PtrAlloc( 100 ); 
+    vPos = Vec_PtrAlloc( 100 );
+    pNew = Aig_ManStart( nVarsMin );
+    pNew->pName = Abc_UtilStrsav( "partition" );
+    Aig_ManIncrementTravId( pFrame );
+    Aig_ManConst1(pFrame)->pData = Aig_ManConst1(pNew);
+    Aig_ObjSetTravIdCurrent( pFrame, Aig_ManConst1(pFrame) );
+    for ( i = iStart; i < iStart + nFlopsMin && i < Aig_ManCoNum(pFrame); i++ )
+    {
+        pObj = Aig_ManCo( pFrame, i );
+        Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves );
+        Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) );
+        Vec_PtrPush( vPos, pObj );
+    }
+    for ( ; Aig_ManObjNum(pNew) < nVarsMin && i < Aig_ManCoNum(pFrame); i++ )
+    {
+        pObj = Aig_ManCo( pFrame, i );
+        Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves );
+        Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) );
+        Vec_PtrPush( vPos, pObj );
+    }
+    assert( nFlopsMin >= Vec_PtrSize(vRoots) || Vec_PtrSize(vRoots) >= nFlopsMin );
+    // create constaints
+    if ( pCare )
+        Cgt_ManConstructCare( pNew, pCare, vSuppsInv, vLeaves );
+    // create POs
+    Vec_PtrForEachEntry( Aig_Obj_t *, vPos, pObj, i )
+        pObj->pData = (Aig_Obj_t *)Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vRoots, i) );
+    if ( pnOutputs != NULL )
+        *pnOutputs = Vec_PtrSize( vPos );
+    Vec_PtrFree( vRoots );
+    Vec_PtrFree( vLeaves );
+    Vec_PtrFree( vPos );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements one clock-gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Cgt_ManBuildClockGate( Aig_Man_t * pNew, Vec_Ptr_t * vGates )
+{
+    Aig_Obj_t * pGate, * pTotal;
+    int i;
+    assert( Vec_PtrSize(vGates) > 0 );
+    pTotal = Aig_ManConst0(pNew);
+    Vec_PtrForEachEntry( Aig_Obj_t *, vGates, pGate, i )
+    {
+        if ( Aig_Regular(pGate)->pNext )
+            pGate = Aig_NotCond( Aig_Regular(pGate)->pNext, Aig_IsComplement(pGate) );
+        else
+            pGate = Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) );
+        pTotal = Aig_Or( pNew, pTotal, pGate );
+    }
+    return pTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives AIG after clock-gating.]
+
+  Description [The array contains, for each flop, its gate if present.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Vec_t * vGates, int fReduce, int * pnUsedNodes )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo, * pGateNew;
+    Vec_Ptr_t * vOne;
+    int i, k;
+    Aig_ManCleanNext( pAig );
+    // label nodes
+    Vec_VecForEachEntry( Aig_Obj_t *, vGates, pObj, i, k )
+    {
+        if ( Aig_IsComplement(pObj) )
+            Aig_Regular(pObj)->fMarkB = 1;
+        else
+            Aig_Regular(pObj)->fMarkA = 1;
+    }
+    // construct AIG
+    assert( Aig_ManRegNum(pAig) );
+    pNew = Aig_ManStart( Aig_ManObjNumMax(pAig) );
+    pNew->pName = Abc_UtilStrsav( pAig->pName );
+    pNew->pSpec = Abc_UtilStrsav( pAig->pSpec );
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    if ( fReduce )
+    {
+        Aig_ManForEachNode( pAig, pObj, i )
+        {
+            assert( !(pObj->fMarkA && pObj->fMarkB) );
+            pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+            if ( pObj->fMarkA )
+            {
+                pObj->pNext = (Aig_Obj_t *)pObj->pData;
+                pObj->pData = Aig_ManConst0(pNew);
+            }
+            else if ( pObj->fMarkB )
+            {
+                pObj->pNext = (Aig_Obj_t *)pObj->pData;
+                pObj->pData = Aig_ManConst1(pNew);
+            }
+        }
+    }
+    else
+    {
+        Aig_ManForEachNode( pAig, pObj, i )
+            pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    }
+    if ( pnUsedNodes != NULL )
+        *pnUsedNodes = Aig_ManNodeNum(pNew);
+    Saig_ManForEachPo( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+    {
+        vOne = Vec_VecEntry( vGates, i );
+        if ( Vec_PtrSize(vOne) == 0 )
+            pObjNew = Aig_ObjChild0Copy(pObjLi);
+        else
+        {
+//            pGateNew = Aig_NotCond( Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) );
+            pGateNew = Cgt_ManBuildClockGate( pNew, vOne );
+            pObjNew = Aig_Mux( pNew, pGateNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) );
+        }
+        pObjLi->pData = Aig_ObjCreateCo( pNew, pObjNew );
+    }
+    Aig_ManCleanup( pNew );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) );
+    // unlabel nodes
+    Aig_ManCleanMarkAB( pAig );
+    Aig_ManCleanNext( pAig );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/cgt/cgtCore.c b/abc-build/src/opt/cgt/cgtCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cgt/cgtCore.c
@@ -0,0 +1,328 @@
+/**CFile****************************************************************
+
+  FileName    [cgtCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Clock gating package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cgtCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cgtInt.h"
+#include "misc/bar/bar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cgt_SetDefaultParams( Cgt_Par_t * p )
+{
+    memset( p, 0, sizeof(Cgt_Par_t) );
+    p->nLevelMax  =    25;   // the max number of levels to look for clock-gates
+    p->nCandMax   =  1000;   // the max number of candidates at each node
+    p->nOdcMax    =     0;   // the max number of ODC levels to consider
+    p->nConfMax   =    10;   // the max number of conflicts at a node
+    p->nVarsMin   =  1000;   // the min number of vars to recycle the SAT solver
+    p->nFlopsMin  =    10;   // the min number of flops to recycle the SAT solver
+    p->fAreaOnly  =     0;   // derive clock-gating to minimize area
+    p->fVerbose   =     0;   // verbosity flag
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation does not filter out this candidate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cgt_SimulationFilter( Cgt_Man_t * p, Aig_Obj_t * pCandPart, Aig_Obj_t * pMiterPart )
+{
+    unsigned * pInfoCand, * pInfoMiter;
+    int w, nWords = Abc_BitWordNum( p->nPatts );  
+    pInfoCand  = (unsigned *)Vec_PtrEntry( p->vPatts, Aig_ObjId(Aig_Regular(pCandPart)) );
+    pInfoMiter = (unsigned *)Vec_PtrEntry( p->vPatts, Aig_ObjId(pMiterPart) );
+    // C => !M -- true   is the same as    C & M -- false
+    if ( !Aig_IsComplement(pCandPart) )
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( pInfoCand[w] & pInfoMiter[w] )
+                return 0;
+    }
+    else
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( ~pInfoCand[w] & pInfoMiter[w] )
+                return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Saves one simulation pattern.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cgt_SimulationRecord( Cgt_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachObj( p->pPart, pObj, i )
+        if ( sat_solver_var_value( p->pSat, p->pCnf->pVarNums[i] ) )
+            Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(p->vPatts, i), p->nPatts );
+    p->nPatts++;
+    if ( p->nPatts == 32 * p->nPattWords )
+    {
+        Vec_PtrReallocSimInfo( p->vPatts );
+        Vec_PtrCleanSimInfo( p->vPatts, p->nPattWords, 2 * p->nPattWords );
+        p->nPattWords *= 2;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs clock-gating for the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cgt_ClockGatingRangeCheck( Cgt_Man_t * p, int iStart, int nOutputs )
+{
+    Vec_Ptr_t * vNodes = p->vFanout;
+    Aig_Obj_t * pMiter, * pCand, * pMiterFrame, * pCandFrame, * pMiterPart, * pCandPart;
+    int i, k, RetValue, nCalls;
+    assert( Vec_VecSize(p->vGatesAll) == Aig_ManCoNum(p->pFrame) );
+    // go through all the registers inputs of this range
+    for ( i = iStart; i < iStart + nOutputs; i++ )
+    {
+        nCalls = p->nCalls;
+        pMiter = Saig_ManLi( p->pAig, i );
+        Cgt_ManDetectCandidates( p->pAig, p->vUseful, Aig_ObjFanin0(pMiter), p->pPars->nLevelMax, vNodes );
+        // go through the candidates of this PO
+        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pCand, k )
+        {
+            // get the corresponding nodes from the frames
+            pCandFrame  = (Aig_Obj_t *)pCand->pData;
+            pMiterFrame = (Aig_Obj_t *)pMiter->pData;
+            // get the corresponding nodes from the part
+            pCandPart   = (Aig_Obj_t *)pCandFrame->pData;
+            pMiterPart  = (Aig_Obj_t *)pMiterFrame->pData;
+            // try direct polarity
+            if ( Cgt_SimulationFilter( p, pCandPart, pMiterPart ) )
+            {
+                RetValue = Cgt_CheckImplication( p, pCandPart, pMiterPart );
+                if ( RetValue == 1 )
+                {
+                    Vec_VecPush( p->vGatesAll, i, pCand );
+                    continue;
+                }
+                if ( RetValue == 0 )
+                    Cgt_SimulationRecord( p );
+            }
+            else
+                p->nCallsFiltered++;
+            // try reverse polarity
+            if ( Cgt_SimulationFilter( p, Aig_Not(pCandPart), pMiterPart ) )
+            {
+                RetValue = Cgt_CheckImplication( p, Aig_Not(pCandPart), pMiterPart );
+                if ( RetValue == 1 )
+                {
+                    Vec_VecPush( p->vGatesAll, i, Aig_Not(pCand) );
+                    continue;
+                }
+                if ( RetValue == 0 )
+                    Cgt_SimulationRecord( p );
+            }
+            else
+                p->nCallsFiltered++;
+        }
+
+        if ( p->pPars->fVerbose )
+        {
+//            printf( "Flop %3d : Cand = %4d. Gate = %4d. SAT calls = %3d.\n", 
+//                i, Vec_PtrSize(vNodes), Vec_PtrSize(Vec_VecEntry(p->vGatesAll, i)), p->nCalls-nCalls );
+        }
+
+    }
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Performs clock-gating for the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cgt_ClockGatingRange( Cgt_Man_t * p, int iStart )
+{
+    int nOutputs, iStop;
+    abctime clk, clkTotal = Abc_Clock();
+    int nCallsUnsat    = p->nCallsUnsat;
+    int nCallsSat      = p->nCallsSat;
+    int nCallsUndec    = p->nCallsUndec;
+    int nCallsFiltered = p->nCallsFiltered;
+clk = Abc_Clock();
+    p->pPart = Cgt_ManDupPartition( p->pFrame, p->pPars->nVarsMin, p->pPars->nFlopsMin, iStart, p->pCare, p->vSuppsInv, &nOutputs );
+    p->pCnf  = Cnf_DeriveSimple( p->pPart, nOutputs );
+    p->pSat  = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 );
+    sat_solver_compress( p->pSat );
+    p->vPatts = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p->pPart), p->nPattWords );
+    Vec_PtrCleanSimInfo( p->vPatts, 0, p->nPattWords );
+p->timePrepare += Abc_Clock() - clk;
+    Cgt_ClockGatingRangeCheck( p, iStart, nOutputs );
+    iStop = iStart + nOutputs;
+    if ( p->pPars->fVeryVerbose )
+    {
+        printf( "%5d : D =%4d. C =%5d. Var =%6d. Pr =%5d. Cex =%5d. F =%4d. Saved =%6d. ",
+            iStart, iStop-iStart, Aig_ManCoNum(p->pPart)-nOutputs, p->pSat->size, 
+            p->nCallsUnsat-nCallsUnsat, 
+            p->nCallsSat  -nCallsSat, 
+            p->nCallsUndec-nCallsUndec,
+            p->nCallsFiltered-nCallsFiltered );
+        ABC_PRT( "Time", Abc_Clock() - clkTotal );
+    }
+    Cgt_ManClean( p );
+    p->nRecycles++;
+    return iStop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs clock-gating for the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Cgt_ClockGatingCandidates( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars, Vec_Int_t * vUseful )
+{
+    Bar_Progress_t * pProgress = NULL;
+    Cgt_Par_t Pars; 
+    Cgt_Man_t * p;
+    Vec_Vec_t * vGatesAll;
+    int iStart;
+    abctime clk = Abc_Clock(), clkTotal = Abc_Clock();
+    // reset random numbers
+    Aig_ManRandom( 1 );
+    if ( pPars == NULL )
+        Cgt_SetDefaultParams( pPars = &Pars );    
+    p = Cgt_ManCreate( pAig, pCare, pPars );
+    p->vUseful = vUseful;
+    p->pFrame = Cgt_ManDeriveAigForGating( p );
+p->timeAig += Abc_Clock() - clk;
+    assert( Aig_ManCoNum(p->pFrame) == Saig_ManRegNum(p->pAig) );
+    pProgress = Bar_ProgressStart( stdout, Aig_ManCoNum(p->pFrame) );
+    for ( iStart = 0; iStart < Aig_ManCoNum(p->pFrame); )
+    {
+        Bar_ProgressUpdate( pProgress, iStart, NULL );
+        iStart = Cgt_ClockGatingRange( p, iStart );
+    }
+    Bar_ProgressStop( pProgress );
+    vGatesAll = p->vGatesAll;
+    p->vGatesAll = NULL;
+p->timeTotal = Abc_Clock() - clkTotal;
+    Cgt_ManStop( p );
+    return vGatesAll;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs clock-gating for the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Cgt_ClockGatingInt( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars, Vec_Int_t * vUseful )
+{
+    Vec_Vec_t * vGatesAll, * vGates;
+    vGatesAll = Cgt_ClockGatingCandidates( pAig, pCare, pPars, vUseful );
+    if ( pPars->fAreaOnly )
+        vGates = Cgt_ManDecideArea( pAig, vGatesAll, pPars->nOdcMax, pPars->fVerbose );
+    else
+        vGates = Cgt_ManDecideSimple( pAig, vGatesAll, pPars->nOdcMax, pPars->fVerbose );
+    Vec_VecFree( vGatesAll );
+    return vGates;
+}
+Aig_Man_t * Cgt_ClockGating( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars )
+{
+    Aig_Man_t * pGated;
+    Vec_Vec_t * vGates = Cgt_ClockGatingInt( pAig, pCare, pPars, NULL );
+    int nNodesUsed;
+    if ( pPars->fVerbose )
+    {
+//        printf( "Before CG: " );
+//        Aig_ManPrintStats( pAig );
+    }
+    pGated = Cgt_ManDeriveGatedAig( pAig, vGates, pPars->fAreaOnly, &nNodesUsed );
+    if ( pPars->fVerbose )
+    {
+//        printf( "After  CG: " );
+//        Aig_ManPrintStats( pGated );
+        printf( "Nodes: Before CG = %6d. After CG = %6d. (%6.2f %%).  Total after CG = %6d.\n", 
+            Aig_ManNodeNum(pAig), nNodesUsed, 
+            100.0*nNodesUsed/Aig_ManNodeNum(pAig), 
+            Aig_ManNodeNum(pGated) );
+    }
+    Vec_VecFree( vGates );
+    return pGated;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/cgt/cgtDecide.c b/abc-build/src/opt/cgt/cgtDecide.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cgt/cgtDecide.c
@@ -0,0 +1,300 @@
+/**CFile****************************************************************
+
+  FileName    [cgtMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Clock gating package.]
+
+  Synopsis    [Decide what gate to use for what flop.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cgtMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cgtInt.h"
+#include "proof/ssw/sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand );
+extern int Ssw_SmlCountXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand );
+extern int Ssw_SmlCountEqual( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo );
+extern int Ssw_SmlNodeCountOnesReal( Ssw_Sml_t * p, Aig_Obj_t * pObj );
+extern int Ssw_SmlNodeCountOnesRealVec( Ssw_Sml_t * p, Vec_Ptr_t * vObjs );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Collects POs in the transitive fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cgt_ManCollectFanoutPos_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vFanout )
+{
+    Aig_Obj_t * pFanout;
+    int f, iFanout = -1;
+    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(pAig, pObj);
+    if ( Aig_ObjIsCo(pObj) )
+    {
+        Vec_PtrPush( vFanout, pObj );
+        return;
+    }
+    Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f )
+        Cgt_ManCollectFanoutPos_rec( pAig, pFanout, vFanout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects POs in the transitive fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cgt_ManCollectFanoutPos( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vFanout )
+{
+    Vec_PtrClear( vFanout );
+    Aig_ManIncrementTravId( pAig );
+    Cgt_ManCollectFanoutPos_rec( pAig, pObj, vFanout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if all PO fanouts can be gated by this node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cgt_ManCheckGateComplete( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, Aig_Obj_t * pGate, Vec_Ptr_t * vFanout )
+{
+    Vec_Ptr_t * vGates;
+    Aig_Obj_t * pObj;
+    int i;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i )
+    {
+        if ( Saig_ObjIsPo(pAig, pObj) )
+            return 0;
+        vGates = Vec_VecEntry( vGatesAll, Aig_ObjCioId(pObj) - Saig_ManPoNum(pAig) );
+        if ( Vec_PtrFind( vGates, pGate ) == -1 )
+            return 0;            
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the set of complete clock gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Cgt_ManCompleteGates( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose )
+{
+    Vec_Ptr_t * vFanout, * vGatesFull;
+    Aig_Obj_t * pGate, * pGateR;
+    int i, k;
+    vFanout    = Vec_PtrAlloc( 100 );
+    vGatesFull = Vec_PtrAlloc( 100 );
+    Vec_VecForEachEntry( Aig_Obj_t *, vGatesAll, pGate, i, k )
+    {
+        pGateR = Aig_Regular(pGate);
+        if ( pGateR->fMarkA )
+            continue;
+        pGateR->fMarkA = 1;
+        Cgt_ManCollectFanoutPos( pAig, pGateR, vFanout );
+        if ( Cgt_ManCheckGateComplete( pAig, vGatesAll, pGate, vFanout ) )
+            Vec_PtrPush( vGatesFull, pGate );
+    }
+    Vec_PtrFree( vFanout );
+    Vec_VecForEachEntry( Aig_Obj_t *, vGatesAll, pGate, i, k )
+        Aig_Regular(pGate)->fMarkA = 0;
+    return vGatesFull;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Calculates coverage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Cgt_ManComputeCoverage( Aig_Man_t * pAig, Vec_Vec_t * vGates )
+{
+    int nFrames = 32;
+    int nWords  =  1;
+    Ssw_Sml_t * pSml;
+    Vec_Ptr_t * vOne;
+    int i, nTransSaved = 0;
+    pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords );
+    Vec_VecForEachLevel( vGates, vOne, i )
+        nTransSaved += Ssw_SmlNodeCountOnesRealVec( pSml, vOne );
+    Ssw_SmlStop( pSml );
+    return (float)100.0*nTransSaved/32/nFrames/nWords/Vec_VecSize(vGates);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Chooses what clock-gate to use for this register.]
+
+  Description [Currently uses the naive approach: For each register, 
+  choose the clock gate, which covers most of the transitions.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose )
+{
+    int nFrames = 32;
+    int nWords  =  1;
+    Ssw_Sml_t * pSml;
+    Vec_Vec_t * vGates;
+    Vec_Ptr_t * vCands;
+    Aig_Obj_t * pObjLi, * pObjLo, * pCand, * pCandBest;
+    int i, k, nHitsCur, nHitsMax, Counter = 0;
+    abctime clk = Abc_Clock();
+    int nTransTotal = 0, nTransSaved = 0;
+    vGates = Vec_VecStart( Saig_ManRegNum(pAig) );
+    pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords );
+    Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+    {
+        nHitsMax = 0;
+        pCandBest = NULL;
+        vCands = Vec_VecEntry( vGatesAll, i );
+        Vec_PtrForEachEntry( Aig_Obj_t *, vCands, pCand, k )
+        {
+            // check if this is indeed a clock-gate
+            if ( nOdcMax == 0 && !Ssw_SmlCheckXorImplication( pSml, pObjLi, pObjLo, pCand ) )
+                printf( "Clock gate candidate is invalid!\n" );
+            // find its characteristic number
+            nHitsCur = Ssw_SmlNodeCountOnesReal( pSml, pCand );
+            if ( nHitsMax < nHitsCur )
+            {
+                nHitsMax = nHitsCur;
+                pCandBest = pCand;
+            }
+        }
+        if ( pCandBest != NULL )
+        {
+            Vec_VecPush( vGates, i, pCandBest );
+            Counter++;
+            nTransSaved += nHitsMax;
+        }
+        nTransTotal += 32 * nFrames * nWords;
+    }
+    Ssw_SmlStop( pSml );
+    if ( fVerbose )
+    {
+        printf( "Gating signals = %6d. Gated flops = %6d. (Total flops = %6d.)\n", 
+            Vec_VecSizeSize(vGatesAll), Counter, Saig_ManRegNum(pAig) );
+//        printf( "Gated transitions = %5.2f %%. (%5.2f %%.) ", 
+//            100.0*nTransSaved/nTransTotal, Cgt_ManComputeCoverage(pAig, vGates) );
+        printf( "Gated transitions = %5.2f %%. ", Cgt_ManComputeCoverage(pAig, vGates) );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+/*
+    {
+        Vec_Ptr_t * vCompletes;
+        vCompletes = Cgt_ManCompleteGates( pAig, vGatesAll, nOdcMax, fVerbose );
+        printf( "Complete gates = %d. \n", Vec_PtrSize(vCompletes) );
+        Vec_PtrFree( vCompletes );
+    }
+*/
+    return vGates;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the set of complete clock gates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Cgt_ManDecideArea( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose )
+{
+    Vec_Vec_t * vGates;
+    Vec_Ptr_t * vCompletes, * vOne;
+    Aig_Obj_t * pGate;
+    int i, k, Counter = 0;
+    abctime clk = Abc_Clock();
+    // derive and label complete gates
+    vCompletes = Cgt_ManCompleteGates( pAig, vGatesAll, nOdcMax, fVerbose );
+    // label complete gates
+    Vec_PtrForEachEntry( Aig_Obj_t *, vCompletes, pGate, i )
+        Aig_Regular(pGate)->fMarkA = 1;
+    // select only complete gates
+    vGates = Vec_VecStart( Saig_ManRegNum(pAig) );
+    Vec_VecForEachEntry( Aig_Obj_t *, vGatesAll, pGate, i, k )
+        if ( Aig_Regular(pGate)->fMarkA )
+            Vec_VecPush( vGates, i, pGate );
+    // unlabel complete gates
+    Vec_PtrForEachEntry( Aig_Obj_t *, vCompletes, pGate, i )
+        Aig_Regular(pGate)->fMarkA = 0;
+    // count the number of gated flops
+    Vec_VecForEachLevel( vGates, vOne, i )
+    {
+        Counter += (int)(Vec_PtrSize(vOne) > 0);
+//        printf( "%d ", Vec_PtrSize(vOne) );
+    }
+//    printf( "\n" );
+    if ( fVerbose )
+    {
+        printf( "Gating signals = %6d. Gated flops = %6d. (Total flops = %6d.)\n", 
+            Vec_VecSizeSize(vGatesAll), Counter, Saig_ManRegNum(pAig) );
+        printf( "Complete gates = %6d. Gated transitions = %5.2f %%. ", 
+            Vec_PtrSize(vCompletes), Cgt_ManComputeCoverage(pAig, vGates) );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    Vec_PtrFree( vCompletes );
+    return vGates;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/cgt/cgtInt.h b/abc-build/src/opt/cgt/cgtInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cgt/cgtInt.h
@@ -0,0 +1,123 @@
+/**CFile****************************************************************
+
+  FileName    [cgtInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Clock gating package.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cgtInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__cgt__cgtInt_h
+#define ABC__aig__cgt__cgtInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "aig/saig/saig.h"
+#include "sat/bsat/satSolver.h"
+#include "sat/cnf/cnf.h"
+#include "cgt.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Cgt_Man_t_ Cgt_Man_t;
+struct Cgt_Man_t_
+{
+    // user's data
+    Cgt_Par_t *  pPars;          // user's parameters
+    Aig_Man_t *  pAig;           // user's AIG manager
+    Vec_Int_t *  vUseful;        // user's candidate nodes
+    // user's constraints
+    Aig_Man_t *  pCare;          // constraint cones
+    Vec_Vec_t *  vSuppsInv;      // inverse support of the constraints
+    // result of clock-gating
+    Vec_Vec_t *  vGatesAll;      // the computed clock-gates
+    Vec_Ptr_t *  vGates;         // the selected clock-gates
+    // internal data
+    Aig_Man_t *  pFrame;         // clock gate AIG manager
+    Vec_Ptr_t *  vFanout;        // temporary storage for fanouts
+    Vec_Ptr_t *  vVisited;       // temporary storage for visited nodes
+    // SAT solving
+    Aig_Man_t *  pPart;          // partition
+    Cnf_Dat_t *  pCnf;           // CNF of the partition
+    sat_solver * pSat;           // SAT solver 
+    Vec_Ptr_t *  vPatts;         // simulation patterns
+    int          nPatts;         // the number of patterns accumulated
+    int          nPattWords;     // the number of pattern words
+    // statistics
+    int          nRecycles;      // recycles 
+    int          nCalls;         // total calls
+    int          nCallsSat;      // satisfiable calls
+    int          nCallsUnsat;    // unsatisfiable calls  
+    int          nCallsUndec;    // undecided calls
+    int          nCallsFiltered; // filtered out calls
+    abctime      timeAig;        // constructing AIG
+    abctime      timePrepare;    // partitioning and SAT solving
+    abctime      timeSat;        // total runtime
+    abctime      timeSatSat;     // satisfiable runtime 
+    abctime      timeSatUnsat;   // unsatisfiable runtime 
+    abctime      timeSatUndec;   // undecided runtime
+    abctime      timeDecision;   // making decision about what gates to use
+    abctime      timeOther;      // other runtime
+    abctime      timeTotal;      // total runtime
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== cgtAig.c ==========================================================*/
+extern void             Cgt_ManDetectCandidates( Aig_Man_t * pAig, Vec_Int_t * vUseful, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands );
+extern Aig_Man_t *      Cgt_ManDeriveAigForGating( Cgt_Man_t * p );
+extern Aig_Man_t *      Cgt_ManDupPartition( Aig_Man_t * pAig, int nVarsMin, int nFlopsMin, int iStart, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, int * pnOutputs );
+extern Aig_Man_t *      Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Vec_t * vGates, int fReduce, int * pnUsedNodes );
+/*=== cgtDecide.c ==========================================================*/
+extern Vec_Vec_t *      Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose );
+extern Vec_Vec_t *      Cgt_ManDecideArea( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose );
+/*=== cgtMan.c ==========================================================*/
+extern Cgt_Man_t *      Cgt_ManCreate( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars );
+extern void             Cgt_ManClean( Cgt_Man_t * p );
+extern void             Cgt_ManStop( Cgt_Man_t * p );
+/*=== cgtSat.c ==========================================================*/
+extern int              Cgt_CheckImplication( Cgt_Man_t * p, Aig_Obj_t * pGate, Aig_Obj_t * pFlop );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/cgt/cgtMan.c b/abc-build/src/opt/cgt/cgtMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cgt/cgtMan.c
@@ -0,0 +1,179 @@
+/**CFile****************************************************************
+
+  FileName    [cgtMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Clock gating package.]
+
+  Synopsis    [Manipulation of clock gating manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cgtMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cgtInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cgt_Man_t * Cgt_ManCreate( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars )
+{
+    Cgt_Man_t * p;
+    // prepare the sequential AIG
+    assert( Saig_ManRegNum(pAig) > 0 );
+    Aig_ManFanoutStart( pAig );
+    Aig_ManSetCioIds( pAig );
+    // create interpolation manager
+    p = ABC_ALLOC( Cgt_Man_t, 1 ); 
+    memset( p, 0, sizeof(Cgt_Man_t) );
+    p->pPars      = pPars;
+    p->pAig       = pAig;
+    p->vGatesAll  = Vec_VecStart( Saig_ManRegNum(pAig) );
+    p->vFanout    = Vec_PtrAlloc( 1000 );
+    p->vVisited   = Vec_PtrAlloc( 1000 );
+    p->nPattWords = 16;
+    if ( pCare == NULL )
+        return p;
+    // check out the constraints
+    if ( Aig_ManCiNum(pCare) != Aig_ManCiNum(pAig) )
+    {
+        printf( "The PI count of care (%d) and AIG (%d) differ. Careset is not used.\n", 
+            Aig_ManCiNum(pCare), Aig_ManCiNum(pAig) );
+        return p;
+    }
+    p->pCare = pCare;
+    p->vSuppsInv = (Vec_Vec_t *)Aig_ManSupportsInverse( p->pCare );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cgt_ManClean( Cgt_Man_t * p )
+{
+    if ( p->pPart )
+    {
+        Aig_ManStop( p->pPart );
+        p->pPart = NULL;
+    }
+    if ( p->pCnf )
+    {
+        Cnf_DataFree( p->pCnf );
+        p->pCnf = NULL;
+    }
+    if ( p->pSat )
+    {
+        sat_solver_delete( p->pSat );
+        p->pSat = NULL;
+    }
+    if ( p->vPatts )
+    {
+        Vec_PtrFree( p->vPatts );
+        p->vPatts = NULL;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cgt_ManPrintStats( Cgt_Man_t * p )
+{
+    printf( "Params: LevMax = %d. CandMax = %d. OdcMax = %d. ConfMax = %d. VarMin = %d. FlopMin = %d.\n", 
+        p->pPars->nLevelMax, p->pPars->nCandMax, p->pPars->nOdcMax, 
+        p->pPars->nConfMax, p->pPars->nVarsMin, p->pPars->nFlopsMin );
+    printf( "SAT   : Calls = %d. Unsat = %d. Sat = %d. Fails = %d.  Recycles = %d.  ", 
+        p->nCalls, p->nCallsUnsat, p->nCallsSat, p->nCallsUndec, p->nRecycles );
+    ABC_PRT( "Time", p->timeTotal );
+/*
+    p->timeOther = p->timeTotal-p->timeAig-p->timePrepare-p->timeSat-p->timeDecision;
+    ABC_PRTP( "AIG        ", p->timeAig,       p->timeTotal );
+    ABC_PRTP( "Prepare    ", p->timePrepare,   p->timeTotal );
+    ABC_PRTP( "SAT solving", p->timeSat,       p->timeTotal );
+    ABC_PRTP( "  unsat    ", p->timeSatUnsat,  p->timeTotal );
+    ABC_PRTP( "  sat      ", p->timeSatSat,    p->timeTotal );
+    ABC_PRTP( "  undecided", p->timeSatUndec,  p->timeTotal );
+    ABC_PRTP( "Other      ", p->timeOther,     p->timeTotal );
+    ABC_PRTP( "TOTAL      ", p->timeTotal,     p->timeTotal );
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cgt_ManStop( Cgt_Man_t * p )
+{
+    if ( p->pPars->fVerbose )
+        Cgt_ManPrintStats( p );
+    if ( p->pFrame )
+        Aig_ManStop( p->pFrame );
+    Cgt_ManClean( p );
+    Vec_PtrFree( p->vFanout );
+    Vec_PtrFree( p->vVisited );
+    if ( p->vGates )
+        Vec_PtrFree( p->vGates );
+    if ( p->vGatesAll )
+        Vec_VecFree( p->vGatesAll );
+    if ( p->vSuppsInv )
+        Vec_VecFree( p->vSuppsInv );
+    ABC_FREE( p );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/cgt/cgtSat.c b/abc-build/src/opt/cgt/cgtSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cgt/cgtSat.c
@@ -0,0 +1,98 @@
+/**CFile****************************************************************
+
+  FileName    [cgtSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Clock gating package.]
+
+  Synopsis    [Checking implications using SAT.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cgtSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cgtInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    [Runs equivalence test for the two nodes.]
+
+  Description [Both nodes should be regular and different from each other.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cgt_CheckImplication( Cgt_Man_t * p, Aig_Obj_t * pGate, Aig_Obj_t * pMiter )
+{
+    int nBTLimit = p->pPars->nConfMax;
+    int pLits[2], RetValue;
+    abctime clk;
+    p->nCalls++;
+
+    // sanity checks
+    assert( p->pSat && p->pCnf );
+    assert( !Aig_IsComplement(pMiter) );
+    assert( Aig_Regular(pGate) != pMiter );
+
+    // solve under assumptions
+    // G => !M -- true     G & M -- false
+    pLits[0] = toLitCond( p->pCnf->pVarNums[Aig_Regular(pGate)->Id], Aig_IsComplement(pGate) );
+    pLits[1] = toLitCond( p->pCnf->pVarNums[pMiter->Id], 0 );
+
+clk = Abc_Clock();
+    RetValue = sat_solver_solve( p->pSat, pLits, pLits + 2, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+p->timeSat += Abc_Clock() - clk;
+    if ( RetValue == l_False )
+    {
+p->timeSatUnsat += Abc_Clock() - clk;
+        pLits[0] = lit_neg( pLits[0] );
+        pLits[1] = lit_neg( pLits[1] );
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+        sat_solver_compress( p->pSat );
+        p->nCallsUnsat++;
+        return 1;
+    }
+    else if ( RetValue == l_True )
+    {
+p->timeSatSat += Abc_Clock() - clk;
+        p->nCallsSat++;
+        return 0;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+p->timeSatUndec += Abc_Clock() - clk;
+        p->nCallsUndec++;
+        return -1;
+    }
+    return -2;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/cgt/module.make b/abc-build/src/opt/cgt/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cgt/module.make
@@ -0,0 +1,5 @@
+SRC +=	src/opt/cgt/cgtAig.c \
+	src/opt/cgt/cgtCore.c \
+	src/opt/cgt/cgtDecide.c \
+	src/opt/cgt/cgtMan.c \
+	src/opt/cgt/cgtSat.c
diff --git a/abc-build/src/opt/csw/csw.h b/abc-build/src/opt/csw/csw.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/csw/csw.h
@@ -0,0 +1,69 @@
+/**CFile****************************************************************
+
+  FileName    [csw.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Cut sweeping.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - July 11, 2007.]
+
+  Revision    [$Id: csw.h,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__csw__csw_h
+#define ABC__aig__csw__csw_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                           ITERATORS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== cnfCore.c ========================================================*/
+extern Aig_Man_t *     Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/csw/cswCore.c b/abc-build/src/opt/csw/cswCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/csw/cswCore.c
@@ -0,0 +1,100 @@
+/**CFile****************************************************************
+
+  FileName    [cswCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Cut sweeping.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - July 11, 2007.]
+
+  Revision    [$Id: cswCore.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose )
+{
+    Csw_Man_t * p;
+    Aig_Man_t * pRes;
+    Aig_Obj_t * pObj, * pObjNew, * pObjRes;
+    int i;
+    abctime clk;
+clk = Abc_Clock();
+    // start the manager
+    p = Csw_ManStart( pAig, nCutsMax, nLeafMax, fVerbose );
+    // set elementary cuts at the PIs
+    Aig_ManForEachCi( p->pManRes, pObj, i )
+    {
+        Csw_ObjPrepareCuts( p, pObj, 1 );
+        Csw_ObjAddRefs( p, pObj, Aig_ManCi(p->pManAig,i)->nRefs );
+    }
+    // process the nodes
+    Aig_ManForEachNode( pAig, pObj, i )
+    {
+        // create the new node
+        pObjNew = Aig_And( p->pManRes, Csw_ObjChild0Equiv(p, pObj), Csw_ObjChild1Equiv(p, pObj) );
+        // check if this node can be represented using another node
+//        pObjRes = Csw_ObjSweep( p, Aig_Regular(pObjNew), pObj->nRefs > 1 );
+//        pObjRes = Aig_NotCond( pObjRes, Aig_IsComplement(pObjNew) );
+        // try recursively if resubsitution is used
+        do {
+            pObjRes = Csw_ObjSweep( p, Aig_Regular(pObjNew), pObj->nRefs > 1 );
+            pObjRes = Aig_NotCond( pObjRes, Aig_IsComplement(pObjNew) );        
+            pObjNew = pObjRes;
+        } while ( Csw_ObjCuts(p, Aig_Regular(pObjNew)) == NULL && !Aig_ObjIsConst1(Aig_Regular(pObjNew)) );
+        // save the resulting node
+        Csw_ObjSetEquiv( p, pObj, pObjRes );
+        // add to the reference counter
+        Csw_ObjAddRefs( p, Aig_Regular(pObjRes), pObj->nRefs );
+    }
+    // add the POs
+    Aig_ManForEachCo( pAig, pObj, i )
+        Aig_ObjCreateCo( p->pManRes, Csw_ObjChild0Equiv(p, pObj) );
+    // remove dangling nodes 
+    Aig_ManCleanup( p->pManRes );
+    // return the resulting manager
+p->timeTotal = Abc_Clock() - clk;
+p->timeOther = p->timeTotal - p->timeCuts - p->timeHash;
+    pRes = p->pManRes;
+    Csw_ManStop( p );
+    return pRes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/csw/cswCut.c b/abc-build/src/opt/csw/cswCut.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/csw/cswCut.c
@@ -0,0 +1,608 @@
+/**CFile****************************************************************
+
+  FileName    [cswCut.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Cut sweeping.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - July 11, 2007.]
+
+  Revision    [$Id: cswCut.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the cost of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Csw_CutFindCost( Csw_Man_t * p, Csw_Cut_t * pCut )
+{
+    Aig_Obj_t * pLeaf;
+    int i, Cost = 0;
+    assert( pCut->nFanins > 0 );
+    Csw_CutForEachLeaf( p->pManRes, pCut, pLeaf, i )
+    {
+//        Cost += pLeaf->nRefs;
+        Cost += Csw_ObjRefs( p, pLeaf );
+//        printf( "%d ", pLeaf->nRefs );
+    }
+//printf( "\n" );
+    return Cost * 100 / pCut->nFanins;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the cost of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline float Csw_CutFindCost2( Csw_Man_t * p, Csw_Cut_t * pCut )
+{
+    Aig_Obj_t * pLeaf;
+    float Cost = 0.0;
+    int i;
+    assert( pCut->nFanins > 0 );
+    Csw_CutForEachLeaf( p->pManRes, pCut, pLeaf, i )
+        Cost += (float)1.0/pLeaf->nRefs;
+    return 1/Cost;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the next free cut to use.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Csw_Cut_t * Csw_CutFindFree( Csw_Man_t * p, Aig_Obj_t * pObj )
+{
+    Csw_Cut_t * pCut, * pCutMax;
+    int i;
+    pCutMax = NULL;
+    Csw_ObjForEachCut( p, pObj, pCut, i )
+    {
+        if ( pCut->nFanins == 0 )
+            return pCut;
+        if ( pCutMax == NULL || pCutMax->Cost < pCut->Cost )
+            pCutMax = pCut;
+    }
+    assert( pCutMax != NULL );
+    pCutMax->nFanins = 0;
+    return pCutMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the stretching phase of the cut w.r.t. the merged cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Cut_TruthPhase( Csw_Cut_t * pCut, Csw_Cut_t * pCut1 )
+{
+    unsigned uPhase = 0;
+    int i, k;
+    for ( i = k = 0; i < pCut->nFanins; i++ )
+    {
+        if ( k == pCut1->nFanins )
+            break;
+        if ( pCut->pFanins[i] < pCut1->pFanins[k] )
+            continue;
+        assert( pCut->pFanins[i] == pCut1->pFanins[k] );
+        uPhase |= (1 << i);
+        k++;
+    }
+    return uPhase;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs truth table computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Csw_CutComputeTruth( Csw_Man_t * p, Csw_Cut_t * pCut, Csw_Cut_t * pCut0, Csw_Cut_t * pCut1, int fCompl0, int fCompl1 )
+{
+    // permute the first table
+    if ( fCompl0 ) 
+        Kit_TruthNot( p->puTemp[0], Csw_CutTruth(pCut0), p->nLeafMax );
+    else
+        Kit_TruthCopy( p->puTemp[0], Csw_CutTruth(pCut0), p->nLeafMax );
+    Kit_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nFanins, p->nLeafMax, Cut_TruthPhase(pCut, pCut0), 0 );
+    // permute the second table
+    if ( fCompl1 ) 
+        Kit_TruthNot( p->puTemp[1], Csw_CutTruth(pCut1), p->nLeafMax );
+    else
+        Kit_TruthCopy( p->puTemp[1], Csw_CutTruth(pCut1), p->nLeafMax );
+    Kit_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nFanins, p->nLeafMax, Cut_TruthPhase(pCut, pCut1), 0 );
+    // produce the resulting table
+    Kit_TruthAnd( Csw_CutTruth(pCut), p->puTemp[2], p->puTemp[3], p->nLeafMax );
+//    assert( pCut->nFanins >= Kit_TruthSupportSize( Csw_CutTruth(pCut), p->nLeafMax ) );
+    return Csw_CutTruth(pCut);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs support minimization for the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Csw_CutSupportMinimize( Csw_Man_t * p, Csw_Cut_t * pCut )
+{
+    unsigned * pTruth;
+    int uSupp, nFansNew, i, k;
+    // get truth table
+    pTruth = Csw_CutTruth( pCut );
+    // get support 
+    uSupp = Kit_TruthSupport( pTruth, p->nLeafMax );
+    // get the new support size
+    nFansNew = Kit_WordCountOnes( uSupp );
+    // check if there are redundant variables
+    if ( nFansNew == pCut->nFanins )
+        return nFansNew;
+    assert( nFansNew < pCut->nFanins );
+    // minimize support
+    Kit_TruthShrink( p->puTemp[0], pTruth, nFansNew, p->nLeafMax, uSupp, 1 );
+    for ( i = k = 0; i < pCut->nFanins; i++ )
+        if ( uSupp & (1 << i) )
+            pCut->pFanins[k++] = pCut->pFanins[i];
+    assert( k == nFansNew );
+    pCut->nFanins = nFansNew;
+//    assert( nFansNew == Kit_TruthSupportSize( pTruth, p->nLeafMax ) );
+//Extra_PrintBinary( stdout, pTruth, (1<<p->nLeafMax) ); printf( "\n" );
+    return nFansNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pDom is contained in pCut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Csw_CutCheckDominance( Csw_Cut_t * pDom, Csw_Cut_t * pCut )
+{
+    int i, k;
+    for ( i = 0; i < (int)pDom->nFanins; i++ )
+    {
+        for ( k = 0; k < (int)pCut->nFanins; k++ )
+            if ( pDom->pFanins[i] == pCut->pFanins[k] )
+                break;
+        if ( k == (int)pCut->nFanins ) // node i in pDom is not contained in pCut
+            return 0;
+    }
+    // every node in pDom is contained in pCut
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the cut is contained.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Csw_CutFilter( Csw_Man_t * p, Aig_Obj_t * pObj, Csw_Cut_t * pCut )
+{ 
+    Csw_Cut_t * pTemp;
+    int i;
+    // go through the cuts of the node
+    Csw_ObjForEachCut( p, pObj, pTemp, i )
+    {
+        if ( pTemp->nFanins < 2 )
+            continue;
+        if ( pTemp == pCut )
+            continue;
+        if ( pTemp->nFanins > pCut->nFanins )
+        {
+            // skip the non-contained cuts
+            if ( (pTemp->uSign & pCut->uSign) != pCut->uSign )
+                continue;
+            // check containment seriously
+            if ( Csw_CutCheckDominance( pCut, pTemp ) )
+            {
+                // remove contained cut
+                pTemp->nFanins = 0;
+            }
+         }
+        else
+        {
+            // skip the non-contained cuts
+            if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign )
+                continue;
+            // check containment seriously
+            if ( Csw_CutCheckDominance( pTemp, pCut ) )
+            {
+                // remove the given
+                pCut->nFanins = 0;
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Csw_CutMergeOrdered( Csw_Man_t * p, Csw_Cut_t * pC0, Csw_Cut_t * pC1, Csw_Cut_t * pC )
+{ 
+    int i, k, c;
+    assert( pC0->nFanins >= pC1->nFanins );
+    // the case of the largest cut sizes
+    if ( pC0->nFanins == p->nLeafMax && pC1->nFanins == p->nLeafMax )
+    {
+        for ( i = 0; i < pC0->nFanins; i++ )
+            if ( pC0->pFanins[i] != pC1->pFanins[i] )
+                return 0;
+        for ( i = 0; i < pC0->nFanins; i++ )
+            pC->pFanins[i] = pC0->pFanins[i];
+        pC->nFanins = pC0->nFanins;
+        return 1;
+    }
+    // the case when one of the cuts is the largest
+    if ( pC0->nFanins == p->nLeafMax )
+    {
+        for ( i = 0; i < pC1->nFanins; i++ )
+        {
+            for ( k = pC0->nFanins - 1; k >= 0; k-- )
+                if ( pC0->pFanins[k] == pC1->pFanins[i] )
+                    break;
+            if ( k == -1 ) // did not find
+                return 0;
+        }
+        for ( i = 0; i < pC0->nFanins; i++ )
+            pC->pFanins[i] = pC0->pFanins[i];
+        pC->nFanins = pC0->nFanins;
+        return 1;
+    }
+
+    // compare two cuts with different numbers
+    i = k = 0;
+    for ( c = 0; c < p->nLeafMax; c++ )
+    {
+        if ( k == pC1->nFanins )
+        {
+            if ( i == pC0->nFanins )
+            {
+                pC->nFanins = c;
+                return 1;
+            }
+            pC->pFanins[c] = pC0->pFanins[i++];
+            continue;
+        }
+        if ( i == pC0->nFanins )
+        {
+            if ( k == pC1->nFanins )
+            {
+                pC->nFanins = c;
+                return 1;
+            }
+            pC->pFanins[c] = pC1->pFanins[k++];
+            continue;
+        }
+        if ( pC0->pFanins[i] < pC1->pFanins[k] )
+        {
+            pC->pFanins[c] = pC0->pFanins[i++];
+            continue;
+        }
+        if ( pC0->pFanins[i] > pC1->pFanins[k] )
+        {
+            pC->pFanins[c] = pC1->pFanins[k++];
+            continue;
+        }
+        pC->pFanins[c] = pC0->pFanins[i++]; 
+        k++;
+    }
+    if ( i < pC0->nFanins || k < pC1->nFanins )
+        return 0;
+    pC->nFanins = c;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the object for FPGA mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Csw_CutMerge( Csw_Man_t * p, Csw_Cut_t * pCut0, Csw_Cut_t * pCut1, Csw_Cut_t * pCut )
+{ 
+    assert( p->nLeafMax > 0 );
+    // merge the nodes
+    if ( pCut0->nFanins < pCut1->nFanins )
+    {
+        if ( !Csw_CutMergeOrdered( p, pCut1, pCut0, pCut ) )
+            return 0;
+    }
+    else
+    {
+        if ( !Csw_CutMergeOrdered( p, pCut0, pCut1, pCut ) )
+            return 0;
+    }
+    pCut->uSign = pCut0->uSign | pCut1->uSign;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Consider cut with more than 2 fanins having 2 true variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Csw_ObjTwoVarCut( Csw_Man_t * p, Csw_Cut_t * pCut )
+{
+    Aig_Obj_t * pRes, * pIn0, * pIn1;
+    int nVars, uTruth, fCompl = 0;
+    assert( pCut->nFanins > 2 );
+    // minimize support of this cut
+    nVars = Csw_CutSupportMinimize( p, pCut );
+    assert( nVars == 2 );
+    // get the fanins
+    pIn0 = Aig_ManObj( p->pManRes, pCut->pFanins[0] );
+    pIn1 = Aig_ManObj( p->pManRes, pCut->pFanins[1] );
+    // derive the truth table
+    uTruth = 0xF & *Csw_CutTruth(pCut);
+    if ( uTruth == 14 || uTruth == 13 || uTruth == 11 || uTruth == 7 )
+    {
+        uTruth = 0xF & ~uTruth;
+        fCompl = 1;
+    }
+    // compute the result
+    pRes = NULL;
+    if ( uTruth == 1  )  // 0001  // 1110  14
+        pRes = Aig_And( p->pManRes, Aig_Not(pIn0), Aig_Not(pIn1) );
+    if ( uTruth == 2  )  // 0010  // 1101  13 
+        pRes = Aig_And( p->pManRes,         pIn0 , Aig_Not(pIn1) );
+    if ( uTruth == 4  )  // 0100  // 1011  11
+        pRes = Aig_And( p->pManRes, Aig_Not(pIn0),         pIn1  );
+    if ( uTruth == 8  )  // 1000  // 0111   7
+        pRes = Aig_And( p->pManRes,         pIn0 ,         pIn1  );
+    if ( pRes )
+        pRes = Aig_NotCond( pRes, fCompl );
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Csw_Cut_t * Csw_ObjPrepareCuts( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv )
+{
+    Csw_Cut_t * pCutSet, * pCut;
+    int i;
+    // create the cutset of the node
+    pCutSet = (Csw_Cut_t *)Aig_MmFixedEntryFetch( p->pMemCuts );
+    Csw_ObjSetCuts( p, pObj, pCutSet );
+    Csw_ObjForEachCut( p, pObj, pCut, i )
+    {
+        pCut->nFanins = 0;
+        pCut->iNode = pObj->Id;
+        pCut->nCutSize = p->nCutSize;
+        pCut->nLeafMax = p->nLeafMax;
+    }
+    // add unit cut if needed
+    if ( fTriv )
+    {
+        pCut = pCutSet;
+        pCut->Cost = 0;
+        pCut->iNode = pObj->Id;
+        pCut->nFanins = 1;
+        pCut->pFanins[0] = pObj->Id;
+        pCut->uSign = Aig_ObjCutSign( pObj->Id );
+        memset( Csw_CutTruth(pCut), 0xAA, sizeof(unsigned) * p->nTruthWords );
+    }
+    return pCutSet;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives cuts for one node and sweeps this node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Csw_ObjSweep( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv )
+{
+    int fUseResub = 1;
+    Csw_Cut_t * pCut0, * pCut1, * pCut, * pCutSet;
+    Aig_Obj_t * pFanin0 = Aig_ObjFanin0(pObj);
+    Aig_Obj_t * pFanin1 = Aig_ObjFanin1(pObj);
+    Aig_Obj_t * pObjNew;
+    unsigned * pTruth;
+    int i, k, nVars, nFanins, iVar;
+    abctime clk;
+
+    assert( !Aig_IsComplement(pObj) );
+    if ( !Aig_ObjIsNode(pObj) )
+        return pObj;
+    if ( Csw_ObjCuts(p, pObj) )
+        return pObj;
+    // the node is not processed yet
+    assert( Csw_ObjCuts(p, pObj) == NULL );
+    assert( Aig_ObjIsNode(pObj) );
+
+    // set up the first cut
+    pCutSet = Csw_ObjPrepareCuts( p, pObj, fTriv );
+
+    // compute pair-wise cut combinations while checking table
+    Csw_ObjForEachCut( p, pFanin0, pCut0, i )
+    if ( pCut0->nFanins > 0 )
+    Csw_ObjForEachCut( p, pFanin1, pCut1, k )
+    if ( pCut1->nFanins > 0 )
+    {
+        // make sure K-feasible cut exists
+        if ( Kit_WordCountOnes(pCut0->uSign | pCut1->uSign) > p->nLeafMax )
+            continue;
+        // get the next cut of this node
+        pCut = Csw_CutFindFree( p, pObj );
+clk = Abc_Clock();
+        // assemble the new cut
+        if ( !Csw_CutMerge( p, pCut0, pCut1, pCut ) )
+        {
+            assert( pCut->nFanins == 0 );
+            continue;
+        }
+        // check containment
+        if ( Csw_CutFilter( p, pObj, pCut ) )
+        {
+            assert( pCut->nFanins == 0 );
+            continue;
+        }
+        // create its truth table
+        pTruth = Csw_CutComputeTruth( p, pCut, pCut0, pCut1, Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) );
+        // support minimize the truth table
+        nFanins = pCut->nFanins;
+//        nVars = Csw_CutSupportMinimize( p, pCut ); // leads to quality degradation
+        nVars = Kit_TruthSupportSize( pTruth, p->nLeafMax );
+p->timeCuts += Abc_Clock() - clk;
+
+        // check for trivial truth tables
+        if ( nVars == 0 )
+        {
+            p->nNodesTriv0++;
+            return Aig_NotCond( Aig_ManConst1(p->pManRes), !(pTruth[0] & 1) );
+        }
+        if ( nVars == 1 )
+        {
+            p->nNodesTriv1++;
+            iVar = Kit_WordFindFirstBit( Kit_TruthSupport(pTruth, p->nLeafMax) );
+            assert( iVar < pCut->nFanins );
+            return Aig_NotCond( Aig_ManObj(p->pManRes, pCut->pFanins[iVar]), (pTruth[0] & 1) );
+        }
+        if ( nVars == 2 && nFanins > 2 && fUseResub )
+        {
+            if ( (pObjNew = Csw_ObjTwoVarCut( p, pCut )) )
+            {
+                p->nNodesTriv2++;
+                return pObjNew;
+            }
+        }
+
+        // check if an equivalent node with the same cut exists
+clk = Abc_Clock();
+        pObjNew = pCut->nFanins > 2 ? Csw_TableCutLookup( p, pCut ) : NULL;
+p->timeHash += Abc_Clock() - clk;
+        if ( pObjNew )
+        {
+            p->nNodesCuts++;
+            return pObjNew;
+        }
+
+        // assign the cost
+        pCut->Cost = Csw_CutFindCost( p, pCut );
+        assert( pCut->nFanins > 0 );
+        assert( pCut->Cost > 0 );
+    }
+    p->nNodesTried++;
+
+    // load the resulting cuts into the table
+clk = Abc_Clock();
+    Csw_ObjForEachCut( p, pObj, pCut, i )
+    {
+        if ( pCut->nFanins > 2 )
+        {
+            assert( pCut->Cost > 0 );
+            Csw_TableCutInsert( p, pCut );
+        }
+    }
+p->timeHash += Abc_Clock() - clk;
+
+    // return the node if could not replace it
+    return pObj;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/csw/cswInt.h b/abc-build/src/opt/csw/cswInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/csw/cswInt.h
@@ -0,0 +1,160 @@
+/**CFile****************************************************************
+
+  FileName    [cswInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Cut sweeping.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - July 11, 2007.]
+
+  Revision    [$Id: cswInt.h,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__csw__cswInt_h
+#define ABC__aig__csw__cswInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "aig/aig/aig.h"
+#include "opt/dar/dar.h"
+#include "bool/kit/kit.h"
+#include "csw.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Csw_Man_t_            Csw_Man_t;
+typedef struct Csw_Cut_t_            Csw_Cut_t;
+
+// the cut used to represent node in the AIG
+struct Csw_Cut_t_
+{
+    Csw_Cut_t *     pNext;           // the next cut in the table 
+    int             Cost;            // the cost of the cut
+//    float           Cost;            // the cost of the cut
+    unsigned        uSign;           // cut signature
+    int             iNode;           // the node, for which it is the cut
+    short           nCutSize;        // the number of bytes in the cut
+    char            nLeafMax;        // the maximum number of fanins
+    char            nFanins;         // the current number of fanins
+    int             pFanins[0];      // the fanins (followed by the truth table)
+};
+
+// the CNF computation manager
+struct Csw_Man_t_
+{
+    // AIG manager
+    Aig_Man_t *     pManAig;         // the input AIG manager
+    Aig_Man_t *     pManRes;         // the output AIG manager
+    Aig_Obj_t **    pEquiv;          // the equivalent nodes in the resulting manager
+    Csw_Cut_t **    pCuts;           // the cuts for each node in the output manager
+    int *           pnRefs;          // the number of references of each new node
+    // hash table for cuts
+    Csw_Cut_t **    pTable;          // the table composed of cuts 
+    int             nTableSize;      // the size of hash table
+    // parameters
+    int             nCutsMax;        // the max number of cuts at the node
+    int             nLeafMax;        // the max number of leaves of a cut
+    int             fVerbose;        // enables verbose output
+    // internal variables
+    int             nCutSize;        // the number of bytes needed to store one cut
+    int             nTruthWords;     // the number of truth table words
+    Aig_MmFixed_t * pMemCuts;        // memory manager for cuts
+    unsigned *      puTemp[4];       // used for the truth table computation
+    // statistics
+    int             nNodesTriv0;     // the number of trivial nodes
+    int             nNodesTriv1;     // the number of trivial nodes
+    int             nNodesTriv2;     // the number of trivial nodes
+    int             nNodesCuts;      // the number of rewritten nodes
+    int             nNodesTried;     // the number of nodes tried
+    abctime         timeCuts;        // time to compute the cut and its truth table
+    abctime         timeHash;        // time for hashing cuts
+    abctime         timeOther;       // other time
+    abctime         timeTotal;       // total time
+};
+
+static inline int          Csw_CutLeaveNum( Csw_Cut_t * pCut )          { return pCut->nFanins;                                   }
+static inline int *        Csw_CutLeaves( Csw_Cut_t * pCut )            { return pCut->pFanins;                                   }
+static inline unsigned *   Csw_CutTruth( Csw_Cut_t * pCut )             { return (unsigned *)(pCut->pFanins + pCut->nLeafMax);    }
+static inline Csw_Cut_t *  Csw_CutNext( Csw_Cut_t * pCut )              { return (Csw_Cut_t *)(((char *)pCut) + pCut->nCutSize);  }
+
+static inline int          Csw_ObjRefs( Csw_Man_t * p, Aig_Obj_t * pObj )                         { return p->pnRefs[pObj->Id];   }
+static inline void         Csw_ObjAddRefs( Csw_Man_t * p, Aig_Obj_t * pObj, int nRefs )           { p->pnRefs[pObj->Id] += nRefs; }
+
+static inline Csw_Cut_t *  Csw_ObjCuts( Csw_Man_t * p, Aig_Obj_t * pObj )                         { return p->pCuts[pObj->Id];    }
+static inline void         Csw_ObjSetCuts( Csw_Man_t * p, Aig_Obj_t * pObj, Csw_Cut_t * pCuts )   { p->pCuts[pObj->Id] = pCuts;   }
+
+static inline Aig_Obj_t *  Csw_ObjEquiv( Csw_Man_t * p, Aig_Obj_t * pObj )                        { return p->pEquiv[pObj->Id];   }
+static inline void         Csw_ObjSetEquiv( Csw_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pEquiv ) { p->pEquiv[pObj->Id] = pEquiv; }
+
+static inline Aig_Obj_t *  Csw_ObjChild0Equiv( Csw_Man_t * p, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Csw_ObjEquiv(p, Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj)) : NULL;  }
+static inline Aig_Obj_t *  Csw_ObjChild1Equiv( Csw_Man_t * p, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Csw_ObjEquiv(p, Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj)) : NULL;  }
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                           ITERATORS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// iterator over cuts of the node
+#define Csw_ObjForEachCut( p, pObj, pCut, i )                           \
+    for ( i = 0, pCut = Csw_ObjCuts(p, pObj); i < p->nCutsMax; i++, pCut = Csw_CutNext(pCut) ) 
+// iterator over leaves of the cut
+#define Csw_CutForEachLeaf( p, pCut, pLeaf, i )                         \
+    for ( i = 0; (i < (int)(pCut)->nFanins) && ((pLeaf) = Aig_ManObj(p, (pCut)->pFanins[i])); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== cnfCut.c ========================================================*/
+extern Csw_Cut_t *    Csw_ObjPrepareCuts( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv );
+extern Aig_Obj_t *    Csw_ObjSweep( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv );
+/*=== cnfMan.c ========================================================*/
+extern Csw_Man_t *    Csw_ManStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, int fVerbose );
+extern void           Csw_ManStop( Csw_Man_t * p );
+/*=== cnfTable.c ========================================================*/
+extern int            Csw_TableCountCuts( Csw_Man_t * p );
+extern void           Csw_TableCutInsert( Csw_Man_t * p, Csw_Cut_t * pCut );
+extern Aig_Obj_t *    Csw_TableCutLookup( Csw_Man_t * p, Csw_Cut_t * pCut );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/csw/cswMan.c b/abc-build/src/opt/csw/cswMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/csw/cswMan.c
@@ -0,0 +1,130 @@
+/**CFile****************************************************************
+
+  FileName    [cswMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Cut sweeping.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - July 11, 2007.]
+
+  Revision    [$Id: cswMan.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the cut sweeping manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Csw_Man_t * Csw_ManStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, int fVerbose )
+{
+    Csw_Man_t * p;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( nCutsMax >= 2  );
+    assert( nLeafMax <= 16 );
+    // allocate the fraiging manager
+    p = ABC_ALLOC( Csw_Man_t, 1 );
+    memset( p, 0, sizeof(Csw_Man_t) );
+    p->nCutsMax = nCutsMax;
+    p->nLeafMax = nLeafMax;
+    p->fVerbose = fVerbose;
+    p->pManAig  = pMan;
+    // create the new manager
+    p->pManRes  = Aig_ManStartFrom( pMan );
+    assert( Aig_ManCiNum(p->pManAig) == Aig_ManCiNum(p->pManRes) );
+    // allocate room for cuts and equivalent nodes
+    p->pnRefs   = ABC_ALLOC( int, Aig_ManObjNumMax(pMan) );
+    p->pEquiv   = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pMan) );
+    p->pCuts    = ABC_ALLOC( Csw_Cut_t *, Aig_ManObjNumMax(pMan) );
+    memset( p->pCuts, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pMan) );
+    memset( p->pnRefs, 0, sizeof(int) * Aig_ManObjNumMax(pMan) );
+    // allocate memory manager
+    p->nTruthWords = Abc_TruthWordNum(nLeafMax);
+    p->nCutSize = sizeof(Csw_Cut_t) + sizeof(int) * nLeafMax + sizeof(unsigned) * p->nTruthWords;
+    p->pMemCuts = Aig_MmFixedStart( p->nCutSize * p->nCutsMax, 512 );
+    // allocate hash table for cuts
+    p->nTableSize = Abc_PrimeCudd( Aig_ManNodeNum(pMan) * p->nCutsMax / 2 );
+    p->pTable = ABC_ALLOC( Csw_Cut_t *, p->nTableSize );
+    memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize );
+    // set the pointers to the available fraig nodes
+    Csw_ObjSetEquiv( p, Aig_ManConst1(p->pManAig), Aig_ManConst1(p->pManRes) );
+    Aig_ManForEachCi( p->pManAig, pObj, i )
+        Csw_ObjSetEquiv( p, pObj, Aig_ManCi(p->pManRes, i) );
+    // room for temporary truth tables
+    p->puTemp[0] = ABC_ALLOC( unsigned, 4 * p->nTruthWords );
+    p->puTemp[1] = p->puTemp[0] + p->nTruthWords;
+    p->puTemp[2] = p->puTemp[1] + p->nTruthWords;
+    p->puTemp[3] = p->puTemp[2] + p->nTruthWords;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the fraiging manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Csw_ManStop( Csw_Man_t * p )
+{
+    if ( p->fVerbose )
+    {
+        int nNodesBeg = Aig_ManNodeNum(p->pManAig);
+        int nNodesEnd = Aig_ManNodeNum(p->pManRes);
+        printf( "Beg = %7d.  End = %7d.  (%6.2f %%)  Try = %7d.  Cuts = %8d.\n", 
+            nNodesBeg, nNodesEnd, 100.0*(nNodesBeg-nNodesEnd)/nNodesBeg,
+            p->nNodesTried, Csw_TableCountCuts( p ) );
+        printf( "Triv0 = %6d.  Triv1 = %6d.  Triv2 = %6d.  Cut-replace = %6d.\n", 
+            p->nNodesTriv0, p->nNodesTriv1, p->nNodesTriv2, p->nNodesCuts );
+        ABC_PRTP( "Cuts    ", p->timeCuts,     p->timeTotal );
+        ABC_PRTP( "Hashing ", p->timeHash,     p->timeTotal );
+        ABC_PRTP( "Other   ", p->timeOther,    p->timeTotal );
+        ABC_PRTP( "TOTAL   ", p->timeTotal,    p->timeTotal );
+    }
+    ABC_FREE( p->puTemp[0] );
+    Aig_MmFixedStop( p->pMemCuts, 0 );
+    ABC_FREE( p->pnRefs );
+    ABC_FREE( p->pEquiv );
+    ABC_FREE( p->pCuts );
+    ABC_FREE( p->pTable );
+    ABC_FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/csw/cswTable.c b/abc-build/src/opt/csw/cswTable.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/csw/cswTable.c
@@ -0,0 +1,166 @@
+/**CFile****************************************************************
+
+  FileName    [cswTable.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Cut sweeping.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - July 11, 2007.]
+
+  Revision    [$Id: cswTable.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash value of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Csw_CutHash( Csw_Cut_t * pCut )
+{
+    static int s_FPrimes[128] = { 
+        1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 
+        1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 
+        2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 
+        2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 
+        3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 
+        3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 
+        4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 
+        4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 
+        5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 
+        6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 
+        6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 
+        7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 
+        8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+    };
+    unsigned uHash;
+    int i;
+    assert( pCut->nFanins <= 16 );
+    uHash = 0;
+    for ( i = 0; i < pCut->nFanins; i++ )
+        uHash ^= pCut->pFanins[i] * s_FPrimes[i];
+    return uHash;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the total number of cuts in the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Csw_TableCountCuts( Csw_Man_t * p )
+{
+    Csw_Cut_t * pEnt;
+    int i, Counter = 0;
+    for ( i = 0; i < p->nTableSize; i++ )
+        for ( pEnt = p->pTable[i]; pEnt; pEnt = pEnt->pNext )
+            Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the cut to the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Csw_TableCutInsert( Csw_Man_t * p, Csw_Cut_t * pCut )
+{
+    int iEntry = Csw_CutHash(pCut) % p->nTableSize;
+    pCut->pNext = p->pTable[iEntry];
+    p->pTable[iEntry] = pCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns an equivalent node if it exists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Csw_TableCutLookup( Csw_Man_t * p, Csw_Cut_t * pCut )
+{
+    Aig_Obj_t * pRes = NULL;
+    Csw_Cut_t * pEnt;
+    unsigned * pTruthNew, * pTruthOld;
+    int iEntry = Csw_CutHash(pCut) % p->nTableSize;
+    for ( pEnt = p->pTable[iEntry]; pEnt; pEnt = pEnt->pNext )
+    {
+        if ( pEnt->nFanins != pCut->nFanins )
+            continue;
+        if ( pEnt->uSign != pCut->uSign )
+            continue;
+        if ( memcmp( pEnt->pFanins, pCut->pFanins, sizeof(int) * pCut->nFanins ) )
+            continue;
+        pTruthOld = Csw_CutTruth(pEnt);
+        pTruthNew = Csw_CutTruth(pCut);
+        if ( (pTruthOld[0] & 1) == (pTruthNew[0] & 1) )
+        {
+            if ( Kit_TruthIsEqual( pTruthOld, pTruthNew, pCut->nFanins ) )
+            {
+                pRes = Aig_ManObj( p->pManRes, pEnt->iNode );
+                assert( pRes->fPhase == Aig_ManObj( p->pManRes, pCut->iNode )->fPhase );
+                break;
+            }
+        }
+        else
+        {
+            if ( Kit_TruthIsOpposite( pTruthOld, pTruthNew, pCut->nFanins ) )
+            {
+                pRes = Aig_Not( Aig_ManObj( p->pManRes, pEnt->iNode ) );
+                assert( Aig_Regular(pRes)->fPhase != Aig_ManObj( p->pManRes, pCut->iNode )->fPhase );
+                break;
+            }
+        }
+    }
+    return pRes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/csw/csw_.c b/abc-build/src/opt/csw/csw_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/csw/csw_.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+  FileName    [csw_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Cut sweeping.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - July 11, 2007.]
+
+  Revision    [$Id: csw_.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/csw/module.make b/abc-build/src/opt/csw/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/csw/module.make
@@ -0,0 +1,4 @@
+SRC +=	src/opt/csw/cswCore.c \
+	src/opt/csw/cswCut.c \
+	src/opt/csw/cswMan.c \
+	src/opt/csw/cswTable.c 
diff --git a/abc-build/src/opt/cut/abcCut.c b/abc-build/src/opt/cut/abcCut.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cut/abcCut.c
@@ -0,0 +1,498 @@
+/**CFile****************************************************************
+
+  FileName    [abcCut.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Interface to cut computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "cut.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq );
+static void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq );
+
+
+extern int nTotal, nGood, nEqual;
+
+// temporary
+//Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ) { return NULL; }
+Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ) 
+{
+    Vec_Int_t * vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
+    int i;
+    Abc_Obj_t * pObj;
+
+//    Abc_NtkForEachCi( pNtk, pObj, i )
+//        Vec_IntWriteEntry( vAttrs, pObj->Id, 1 );
+
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+//        if ( Abc_ObjIsNode(pObj) && (rand() % 4 == 0) )
+        if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) && (rand() % 3 == 0) )
+            Vec_IntWriteEntry( vAttrs, pObj->Id, 1 );
+    }
+    return vAttrs; 
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
+{
+    ProgressBar * pProgress;
+    Cut_Man_t *  p;
+    Abc_Obj_t * pObj, * pNode;
+    Vec_Ptr_t * vNodes;
+    Vec_Int_t * vChoices;
+    int i;
+    clock_t clk = clock();
+
+    extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk );
+    extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk );
+
+    nTotal = nGood = nEqual = 0;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    // start the manager
+    pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
+    p = Cut_ManStart( pParams );
+    // compute node attributes if local or global cuts are requested
+    if ( pParams->fGlobal || pParams->fLocal )
+    {
+        extern Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk );
+        Cut_ManSetNodeAttrs( p, Abc_NtkGetNodeAttributes(pNtk) );
+    }
+    // prepare for cut dropping
+    if ( pParams->fDrop )
+        Cut_ManSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) );
+    // set cuts for PIs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        if ( Abc_ObjFanoutNum(pObj) > 0 )
+            Cut_NodeSetTriv( p, pObj->Id );
+    // compute cuts for internal nodes
+    vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs
+    vChoices = Vec_IntAlloc( 100 );
+    pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        // when we reached a CO, it is time to deallocate the cuts
+        if ( Abc_ObjIsCo(pObj) )
+        {
+            if ( pParams->fDrop )
+                Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+            continue;
+        }
+        // skip constant node, it has no cuts
+//        if ( Abc_NodeIsConst(pObj) )
+//            continue;
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        // compute the cuts to the internal node
+        Abc_NodeGetCuts( p, pObj, pParams->fDag, pParams->fTree );  
+        // consider dropping the fanins cuts
+        if ( pParams->fDrop )
+        {
+            Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+            Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId1(pObj) );
+        }
+        // add cuts due to choices
+        if ( Abc_AigNodeIsChoice(pObj) )
+        {
+            Vec_IntClear( vChoices );
+            for ( pNode = pObj; pNode; pNode = pNode->pData )
+                Vec_IntPush( vChoices, pNode->Id );
+            Cut_NodeUnionCuts( p, vChoices );
+        }
+    }
+    Extra_ProgressBarStop( pProgress );
+    Vec_PtrFree( vNodes );
+    Vec_IntFree( vChoices );
+PRT( "Total", clock() - clk );
+//Abc_NtkPrintCuts( p, pNtk, 0 );
+//    Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk );
+
+    // temporary printout of stats
+    if ( nTotal )
+    printf( "Total cuts = %d. Good cuts = %d.  Ratio = %5.2f\n", nTotal, nGood, ((double)nGood)/nTotal );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cut computation using the oracle.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p )
+{
+    Abc_Obj_t * pObj;
+    Vec_Ptr_t * vNodes;
+    int i;
+    clock_t clk = clock();
+    int fDrop = Cut_OracleReadDrop(p);
+
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    // prepare cut droppping
+    if ( fDrop )
+        Cut_OracleSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) );
+
+    // set cuts for PIs
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        if ( Abc_ObjFanoutNum(pObj) > 0 )
+            Cut_OracleNodeSetTriv( p, pObj->Id );
+
+    // compute cuts for internal nodes
+    vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        // when we reached a CO, it is time to deallocate the cuts
+        if ( Abc_ObjIsCo(pObj) )
+        {
+            if ( fDrop )
+                Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+            continue;
+        }
+        // skip constant node, it has no cuts
+//        if ( Abc_NodeIsConst(pObj) )
+//            continue;
+        // compute the cuts to the internal node
+        Cut_OracleComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),  
+                Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+        // consider dropping the fanins cuts
+        if ( fDrop )
+        {
+            Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+            Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId1(pObj) );
+        }
+    }
+    Vec_PtrFree( vNodes );
+//PRT( "Total", clock() - clk );
+//Abc_NtkPrintCuts_( p, pNtk, 0 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
+{
+/*
+    Cut_Man_t *  p;
+    Abc_Obj_t * pObj, * pNode;
+    int i, nIters, fStatus;
+    Vec_Int_t * vChoices;
+    clock_t clk = clock();
+
+    assert( Abc_NtkIsSeq(pNtk) );
+    assert( pParams->fSeq );
+//    assert( Abc_NtkIsDfsOrdered(pNtk) );
+
+    // start the manager
+    pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
+    pParams->nCutSet = Abc_NtkCutSetNodeNum( pNtk );
+    p = Cut_ManStart( pParams );
+
+    // set cuts for the constant node and the PIs
+    pObj = Abc_AigConst1(pNtk);
+    if ( Abc_ObjFanoutNum(pObj) > 0 )
+        Cut_NodeSetTriv( p, pObj->Id );
+    Abc_NtkForEachPi( pNtk, pObj, i )
+    {
+//printf( "Setting trivial cut %d.\n", pObj->Id );
+        Cut_NodeSetTriv( p, pObj->Id );
+    }
+    // label the cutset nodes and set their number in the array
+    // assign the elementary cuts to the cutset nodes
+    Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+    {
+        assert( pObj->fMarkC == 0 );
+        pObj->fMarkC = 1;
+        pObj->pCopy = (Abc_Obj_t *)i;
+        Cut_NodeSetTriv( p, pObj->Id );
+//printf( "Setting trivial cut %d.\n", pObj->Id );
+    }
+
+    // process the nodes
+    vChoices = Vec_IntAlloc( 100 );
+    for ( nIters = 0; nIters < 10; nIters++ )
+    {
+//printf( "ITERATION %d:\n", nIters );
+        // compute the cuts for the internal nodes
+        Abc_AigForEachAnd( pNtk, pObj, i )
+        {
+            Abc_NodeGetCutsSeq( p, pObj, nIters==0 );
+            // add cuts due to choices
+            if ( Abc_AigNodeIsChoice(pObj) )
+            {
+                Vec_IntClear( vChoices );
+                for ( pNode = pObj; pNode; pNode = pNode->pData )
+                    Vec_IntPush( vChoices, pNode->Id );
+                Cut_NodeUnionCutsSeq( p, vChoices, (pObj->fMarkC ? (int)pObj->pCopy : -1), nIters==0 );
+            }
+        }
+        // merge the new cuts with the old cuts
+        Abc_NtkForEachPi( pNtk, pObj, i )
+            Cut_NodeNewMergeWithOld( p, pObj->Id );
+        Abc_AigForEachAnd( pNtk, pObj, i )
+            Cut_NodeNewMergeWithOld( p, pObj->Id );
+        // for the cutset, transfer temp cuts to new cuts
+        fStatus = 0;
+        Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+            fStatus |= Cut_NodeTempTransferToNew( p, pObj->Id, i );
+        if ( fStatus == 0 )
+            break;
+    }
+    Vec_IntFree( vChoices );
+
+    // if the status is not finished, transfer new to old for the cutset
+    Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+        Cut_NodeNewMergeWithOld( p, pObj->Id );
+
+    // transfer the old cuts to the new positions
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        Cut_NodeOldTransferToNew( p, pObj->Id );
+
+    // unlabel the cutset nodes
+    Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+        pObj->fMarkC = 0;
+if ( pParams->fVerbose )
+{
+PRT( "Total", clock() - clk );
+printf( "Converged after %d iterations.\n", nIters );
+}
+//Abc_NtkPrintCuts( p, pNtk, 1 );
+    return p;
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree )
+{
+    void * pList;
+    if ( pList = Abc_NodeReadCuts( p, pObj ) )
+        return pList;
+    Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fDag, fTree );
+    Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fDag, fTree );
+    return Abc_NodeGetCuts( p, pObj, fDag, fTree );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree )
+{
+    Abc_Obj_t * pFanin;
+    int fDagNode, fTriv, TreeCode = 0;
+//    assert( Abc_NtkIsStrash(pObj->pNtk) );
+    assert( Abc_ObjFaninNum(pObj) == 2 );
+
+
+    // check if the node is a DAG node
+    fDagNode = (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj));
+    // increment the counter of DAG nodes
+    if ( fDagNode ) Cut_ManIncrementDagNodes( p );
+    // add the trivial cut if the node is a DAG node, or if we compute all cuts
+    fTriv = fDagNode || !fDag;
+    // check if fanins are DAG nodes
+    if ( fTree )
+    {
+        pFanin = Abc_ObjFanin0(pObj);
+        TreeCode |=  (Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin));
+        pFanin = Abc_ObjFanin1(pObj);
+        TreeCode |= ((Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)) << 1);
+    }
+
+
+    // changes due to the global/local cut computation
+    {
+        Cut_Params_t * pParams = Cut_ManReadParams(p);
+        if ( pParams->fLocal )
+        {
+            Vec_Int_t * vNodeAttrs = Cut_ManReadNodeAttrs(p);
+            fDagNode = Vec_IntEntry( vNodeAttrs, pObj->Id );
+            if ( fDagNode ) Cut_ManIncrementDagNodes( p );
+//            fTriv = fDagNode || !pParams->fGlobal;
+            fTriv = !Vec_IntEntry( vNodeAttrs, pObj->Id );
+            TreeCode = 0;
+            pFanin = Abc_ObjFanin0(pObj);
+            TreeCode |=  Vec_IntEntry( vNodeAttrs, pFanin->Id );
+            pFanin = Abc_ObjFanin1(pObj);
+            TreeCode |= (Vec_IntEntry( vNodeAttrs, pFanin->Id ) << 1);
+        }
+    }
+    return Cut_NodeComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),  
+        Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), fTriv, TreeCode );  
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fTriv )
+{
+    int CutSetNum;
+    assert( Abc_NtkIsSeq(pObj->pNtk) );
+    assert( Abc_ObjFaninNum(pObj) == 2 );
+    fTriv     = pObj->fMarkC ? 0 : fTriv;
+    CutSetNum = pObj->fMarkC ? (int)pObj->pCopy : -1;
+    Cut_NodeComputeCutsSeq( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),  
+        Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj), fTriv, CutSetNum );  
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj )
+{
+    return Cut_NodeReadCutsNew( p, pObj->Id );  
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj )
+{
+    Cut_NodeFreeCuts( p, pObj->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq )
+{
+    Cut_Man_t * pMan = p;
+    Cut_Cut_t * pList;
+    Abc_Obj_t * pObj;
+    int i;
+    printf( "Cuts of the network:\n" );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        pList = Abc_NodeReadCuts( p, pObj );
+        printf( "Node %s:\n", Abc_ObjName(pObj) );
+        Cut_CutPrintList( pList, fSeq );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq )
+{
+    Cut_Man_t * pMan = p;
+    Cut_Cut_t * pList;
+    Abc_Obj_t * pObj;
+    pObj = Abc_NtkObj( pNtk, 2 * Abc_NtkObjNum(pNtk) / 3 );
+    pList = Abc_NodeReadCuts( p, pObj );
+    printf( "Node %s:\n", Abc_ObjName(pObj) );
+    Cut_CutPrintList( pList, fSeq );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/cut/cut.h b/abc-build/src/opt/cut/cut.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cut/cut.h
@@ -0,0 +1,172 @@
+/**CFile****************************************************************
+
+  FileName    [cut.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [K-feasible cut computation package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: .h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__opt__cut__cut_h
+#define ABC__opt__cut__cut_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+#define CUT_SIZE_MIN    3      // the min K of the K-feasible cut computation
+#define CUT_SIZE_MAX   12      // the max K of the K-feasible cut computation
+
+#define CUT_SHIFT       8      // the number of bits for storing latch number in the cut leaves
+#define CUT_MASK        0xFF   // the mask to get the stored latch number
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Cut_ManStruct_t_         Cut_Man_t;
+typedef struct Cut_OracleStruct_t_      Cut_Oracle_t;
+typedef struct Cut_CutStruct_t_         Cut_Cut_t;
+typedef struct Cut_ParamsStruct_t_      Cut_Params_t;
+
+struct Cut_ParamsStruct_t_
+{
+    int                nVarsMax;          // the max cut size ("k" of the k-feasible cuts)
+    int                nKeepMax;          // the max number of cuts kept at a node
+    int                nIdsMax;           // the max number of IDs of cut objects
+    int                nBitShift;         // the number of bits used for the latch counter of an edge
+    int                nCutSet;           // the number of nodes in the cut set
+    int                fTruth;            // compute truth tables
+    int                fFilter;           // filter dominated cuts
+    int                fSeq;              // compute sequential cuts
+    int                fDrop;             // drop cuts on the fly
+    int                fDag;              // compute only DAG cuts
+    int                fTree;             // compute only tree cuts
+    int                fGlobal;           // compute only global cuts
+    int                fLocal;            // compute only local cuts
+    int                fRecord;           // record the cut computation flow
+    int                fRecordAig;        // record the cut functions
+    int                fFancy;            // perform fancy computations
+    int                fMap;              // computes delay of FPGA mapping with cuts
+    int                fAdjust;           // removed useless fanouts of XORs/MUXes
+    int                fNpnSave;          // enables dumping 6-input truth tables
+    int                fVerbose;          // the verbosiness flag
+};
+
+struct Cut_CutStruct_t_
+{
+    unsigned           Num0       : 11;   // temporary number
+    unsigned           Num1       : 11;   // temporary number
+    unsigned           fSimul     :  1;   // the value of cut's output at 000.. pattern
+    unsigned           fCompl     :  1;   // the cut is complemented
+    unsigned           nVarsMax   :  4;   // the max number of vars [4-6]
+    unsigned           nLeaves    :  4;   // the number of leaves [4-6]
+    unsigned           uSign;             // the signature
+    unsigned           uCanon0;           // the canonical form 
+    unsigned           uCanon1;           // the canonical form 
+    Cut_Cut_t *        pNext;             // the next cut in the list
+    int                pLeaves[0];        // the array of leaves
+};
+
+static inline int        Cut_CutReadLeaveNum( Cut_Cut_t * p )  {  return p->nLeaves;   }
+static inline int *      Cut_CutReadLeaves( Cut_Cut_t * p )    {  return p->pLeaves;   }
+static inline unsigned * Cut_CutReadTruth( Cut_Cut_t * p )     {  return (unsigned *)(p->pLeaves + p->nVarsMax); }
+static inline void       Cut_CutWriteTruth( Cut_Cut_t * p, unsigned * puTruth )  { 
+    int i;
+    for ( i = (p->nVarsMax <= 5) ? 0 : ((1 << (p->nVarsMax - 5)) - 1); i >= 0; i-- )
+        p->pLeaves[p->nVarsMax + i] = (int)puTruth[i];
+}
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== cutApi.c ==========================================================*/
+extern Cut_Cut_t *      Cut_NodeReadCutsNew( Cut_Man_t * p, int Node );
+extern Cut_Cut_t *      Cut_NodeReadCutsOld( Cut_Man_t * p, int Node );
+extern Cut_Cut_t *      Cut_NodeReadCutsTemp( Cut_Man_t * p, int Node );
+extern void             Cut_NodeWriteCutsNew( Cut_Man_t * p, int Node, Cut_Cut_t * pList );
+extern void             Cut_NodeWriteCutsOld( Cut_Man_t * p, int Node, Cut_Cut_t * pList );
+extern void             Cut_NodeWriteCutsTemp( Cut_Man_t * p, int Node, Cut_Cut_t * pList );
+extern void             Cut_NodeSetTriv( Cut_Man_t * p, int Node );
+extern void             Cut_NodeTryDroppingCuts( Cut_Man_t * p, int Node );
+extern void             Cut_NodeFreeCuts( Cut_Man_t * p, int Node );
+/*=== cutCut.c ==========================================================*/
+extern void             Cut_CutPrint( Cut_Cut_t * pCut, int fSeq );
+extern void             Cut_CutPrintList( Cut_Cut_t * pList, int fSeq );
+extern int              Cut_CutCountList( Cut_Cut_t * pList );
+/*=== cutMan.c ==========================================================*/
+extern Cut_Man_t *      Cut_ManStart( Cut_Params_t * pParams );
+extern void             Cut_ManStop( Cut_Man_t * p );
+extern void             Cut_ManPrintStats( Cut_Man_t * p );
+extern void             Cut_ManPrintStatsToFile( Cut_Man_t * p, char * pFileName, abctime TimeTotal );
+extern void             Cut_ManSetFanoutCounts( Cut_Man_t * p, Vec_Int_t * vFanCounts );
+extern void             Cut_ManSetNodeAttrs( Cut_Man_t * p, Vec_Int_t * vFanCounts );
+extern int              Cut_ManReadVarsMax( Cut_Man_t * p );
+extern Cut_Params_t *   Cut_ManReadParams( Cut_Man_t * p );
+extern Vec_Int_t *      Cut_ManReadNodeAttrs( Cut_Man_t * p );
+extern void             Cut_ManIncrementDagNodes( Cut_Man_t * p );
+/*=== cutNode.c ==========================================================*/
+extern Cut_Cut_t *      Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv, int TreeCode ); 
+extern Cut_Cut_t *      Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes );
+extern Cut_Cut_t *      Cut_NodeUnionCutsSeq( Cut_Man_t * p, Vec_Int_t * vNodes, int CutSetNum, int fFirst );
+extern int              Cut_ManMappingArea_rec( Cut_Man_t * p, int Node );
+/*=== cutSeq.c ==========================================================*/
+extern void             Cut_NodeComputeCutsSeq( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int nLat0, int nLat1, int fTriv, int CutSetNum );
+extern void             Cut_NodeNewMergeWithOld( Cut_Man_t * p, int Node );
+extern int              Cut_NodeTempTransferToNew( Cut_Man_t * p, int Node, int CutSetNum );
+extern void             Cut_NodeOldTransferToNew( Cut_Man_t * p, int Node );
+/*=== cutOracle.c ==========================================================*/
+extern Cut_Oracle_t *   Cut_OracleStart( Cut_Man_t * pMan );
+extern void             Cut_OracleStop( Cut_Oracle_t * p );
+extern void             Cut_OracleSetFanoutCounts( Cut_Oracle_t * p, Vec_Int_t * vFanCounts );
+extern int              Cut_OracleReadDrop( Cut_Oracle_t * p );
+extern void             Cut_OracleNodeSetTriv( Cut_Oracle_t * p, int Node );
+extern Cut_Cut_t *      Cut_OracleComputeCuts( Cut_Oracle_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 );
+extern void             Cut_OracleTryDroppingCuts( Cut_Oracle_t * p, int Node );
+/*=== cutTruth.c ==========================================================*/
+extern void             Cut_TruthNCanonicize( Cut_Cut_t * pCut );
+/*=== cutPre22.c ==========================================================*/
+extern void             Cut_CellPrecompute();
+extern void             Cut_CellLoad();
+extern int              Cut_CellIsRunning();
+extern void             Cut_CellDumpToFile();
+extern int              Cut_CellTruthLookup( unsigned * pTruth, int nVars );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/cut/cutApi.c b/abc-build/src/opt/cut/cutApi.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cut/cutApi.c
@@ -0,0 +1,202 @@
+/**CFile****************************************************************
+
+  FileName    [cutNode.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [K-feasible cut computation package.]
+
+  Synopsis    [Procedures to compute cuts for a node.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cutNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the pointer to the linked list of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_NodeReadCutsNew( Cut_Man_t * p, int Node )
+{
+    if ( Node >= p->vCutsNew->nSize )
+        return NULL;
+    return (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the pointer to the linked list of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_NodeReadCutsOld( Cut_Man_t * p, int Node )
+{
+    assert( Node < p->vCutsOld->nSize );
+    return (Cut_Cut_t *)Vec_PtrEntry( p->vCutsOld, Node );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the pointer to the linked list of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_NodeReadCutsTemp( Cut_Man_t * p, int Node )
+{
+    assert( Node < p->vCutsTemp->nSize );
+    return (Cut_Cut_t *)Vec_PtrEntry( p->vCutsTemp, Node );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the pointer to the linked list of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_NodeWriteCutsNew( Cut_Man_t * p, int Node, Cut_Cut_t * pList )
+{
+    Vec_PtrWriteEntry( p->vCutsNew, Node, pList );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the pointer to the linked list of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_NodeWriteCutsOld( Cut_Man_t * p, int Node, Cut_Cut_t * pList )
+{
+    Vec_PtrWriteEntry( p->vCutsOld, Node, pList );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the pointer to the linked list of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_NodeWriteCutsTemp( Cut_Man_t * p, int Node, Cut_Cut_t * pList )
+{
+    Vec_PtrWriteEntry( p->vCutsTemp, Node, pList );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the trivial cut for the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_NodeSetTriv( Cut_Man_t * p, int Node )
+{
+    assert( Cut_NodeReadCutsNew(p, Node) == NULL );
+    Cut_NodeWriteCutsNew( p, Node, Cut_CutCreateTriv(p, Node) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Consider dropping cuts if they are useless by now.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_NodeTryDroppingCuts( Cut_Man_t * p, int Node )
+{
+    int nFanouts;
+    assert( p->vFanCounts );
+    nFanouts = Vec_IntEntry( p->vFanCounts, Node );
+    assert( nFanouts > 0 );
+    if ( --nFanouts == 0 )
+        Cut_NodeFreeCuts( p, Node );
+    Vec_IntWriteEntry( p->vFanCounts, Node, nFanouts );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the cuts at the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_NodeFreeCuts( Cut_Man_t * p, int Node )
+{
+    Cut_Cut_t * pList, * pCut, * pCut2;
+    pList = Cut_NodeReadCutsNew( p, Node );
+    if ( pList == NULL )
+        return;
+    Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+        Cut_CutRecycle( p, pCut );
+    Cut_NodeWriteCutsNew( p, Node, NULL );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/cut/cutCut.c b/abc-build/src/opt/cut/cutCut.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cut/cutCut.c
@@ -0,0 +1,364 @@
+/**CFile****************************************************************
+
+  FileName    [cutNode.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [K-feasible cut computation package.]
+
+  Synopsis    [Procedures to compute cuts for a node.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cutNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutAlloc( Cut_Man_t * p )
+{
+    Cut_Cut_t * pCut;
+    // cut allocation
+    pCut = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts );
+    memset( pCut, 0, sizeof(Cut_Cut_t) );
+    pCut->nVarsMax   = p->pParams->nVarsMax;
+    pCut->fSimul     = p->fSimul;
+    // statistics
+    p->nCutsAlloc++;
+    p->nCutsCur++;
+    if ( p->nCutsPeak < p->nCutsAlloc - p->nCutsDealloc )
+        p->nCutsPeak = p->nCutsAlloc - p->nCutsDealloc;
+    return pCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recybles the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut )
+{
+    p->nCutsDealloc++;
+    p->nCutsCur--;
+    if ( pCut->nLeaves == 1 )
+        p->nCutsTriv--;
+    Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares two cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 )
+{
+    int i;
+    if ( pCut1->nLeaves < pCut2->nLeaves )
+        return -1;
+    if ( pCut1->nLeaves > pCut2->nLeaves )
+        return 1;
+    for ( i = 0; i < (int)pCut1->nLeaves; i++ )
+    {
+        if ( pCut1->pLeaves[i] < pCut2->pLeaves[i] )
+            return -1;
+        if ( pCut1->pLeaves[i] > pCut2->pLeaves[i] )
+            return 1;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutDupList( Cut_Man_t * p, Cut_Cut_t * pList )
+{
+    Cut_Cut_t * pHead = NULL, ** ppTail = &pHead;
+    Cut_Cut_t * pTemp, * pCopy;
+    if ( pList == NULL )
+        return NULL;
+    Cut_ListForEachCut( pList, pTemp )
+    {
+        pCopy = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts );
+        memcpy( pCopy, pTemp, p->EntrySize );
+        *ppTail = pCopy;
+        ppTail = &pCopy->pNext;
+    }
+    *ppTail = NULL;
+    return pHead;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_CutRecycleList( Cut_Man_t * p, Cut_Cut_t * pList )
+{
+    Cut_Cut_t * pCut, * pCut2;
+    Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+        Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of cuts in the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cut_CutCountList( Cut_Cut_t * pList )
+{
+    int Counter = 0;
+    Cut_ListForEachCut( pList, pList )
+        Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two NULL-terminated linked lists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutMergeLists( Cut_Cut_t * pList1, Cut_Cut_t * pList2 )
+{
+    Cut_Cut_t * pList = NULL, ** ppTail = &pList;
+    Cut_Cut_t * pCut;
+    while ( pList1 && pList2 )
+    {
+        if ( Cut_CutCompare(pList1, pList2) < 0 )
+        {
+            pCut = pList1;
+            pList1 = pList1->pNext;
+        }
+        else
+        {
+            pCut = pList2;
+            pList2 = pList2->pNext;
+        }
+        *ppTail = pCut;
+        ppTail = &pCut->pNext;
+    }
+    *ppTail = pList1? pList1: pList2;
+    return pList;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the number of the cuts in the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_CutNumberList( Cut_Cut_t * pList )
+{
+    Cut_Cut_t * pCut;
+    int i = 0;
+    Cut_ListForEachCut( pList, pCut )
+        pCut->Num0 = i++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the trivial cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node )
+{
+    Cut_Cut_t * pCut;
+    if ( p->pParams->fSeq )
+        Node <<= CUT_SHIFT;
+    pCut = Cut_CutAlloc( p );
+    pCut->nLeaves    = 1;
+    pCut->pLeaves[0] = Node;
+    pCut->uSign      = Cut_NodeSign( Node );
+    if ( p->pParams->fTruth )
+    {
+/*
+        if ( pCut->nVarsMax == 4 )
+            Cut_CutWriteTruth( pCut, p->uTruthVars[0] );
+        else
+            Extra_BitCopy( pCut->nLeaves, p->uTruths[0], (uint8*)Cut_CutReadTruth(pCut) );
+*/
+        unsigned * pTruth = Cut_CutReadTruth(pCut);
+        int i;
+        for ( i = 0; i < p->nTruthWords; i++ )
+            pTruth[i] = 0xAAAAAAAA;
+    }
+    p->nCutsTriv++;
+    return pCut;
+} 
+
+
+/**Function*************************************************************
+
+  Synopsis    [Print the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_CutPrint( Cut_Cut_t * pCut, int fSeq )
+{
+    int i;
+    assert( pCut->nLeaves > 0 );
+    printf( "%d : {", pCut->nLeaves );
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+    {
+        if ( fSeq )
+        {
+            printf( " %d", pCut->pLeaves[i] >> CUT_SHIFT );
+            if ( pCut->pLeaves[i] & CUT_MASK )
+                printf( "(%d)", pCut->pLeaves[i] & CUT_MASK );
+        }
+        else
+            printf( " %d", pCut->pLeaves[i] );
+    }
+    printf( " }" );
+//    printf( "\nSign = " );
+//    Extra_PrintBinary( stdout, &pCut->uSign, 32 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Print the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_CutPrintList( Cut_Cut_t * pList, int fSeq )
+{
+    Cut_Cut_t * pCut;
+    for ( pCut = pList; pCut; pCut = pCut->pNext )
+        Cut_CutPrint( pCut, fSeq ), printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Consider dropping cuts if they are useless by now.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+{
+    printf( "\n" );
+    printf( "%d : %5d %5d %5d %5d %5d\n", 
+        pCut0->nLeaves, 
+        pCut0->nLeaves > 0 ? pCut0->pLeaves[0] : -1, 
+        pCut0->nLeaves > 1 ? pCut0->pLeaves[1] : -1, 
+        pCut0->nLeaves > 2 ? pCut0->pLeaves[2] : -1, 
+        pCut0->nLeaves > 3 ? pCut0->pLeaves[3] : -1, 
+        pCut0->nLeaves > 4 ? pCut0->pLeaves[4] : -1
+        );
+    printf( "%d : %5d %5d %5d %5d %5d\n", 
+        pCut1->nLeaves, 
+        pCut1->nLeaves > 0 ? pCut1->pLeaves[0] : -1, 
+        pCut1->nLeaves > 1 ? pCut1->pLeaves[1] : -1, 
+        pCut1->nLeaves > 2 ? pCut1->pLeaves[2] : -1, 
+        pCut1->nLeaves > 3 ? pCut1->pLeaves[3] : -1, 
+        pCut1->nLeaves > 4 ? pCut1->pLeaves[4] : -1
+        );
+    if ( pCut == NULL )
+        printf( "Cannot merge\n" );
+    else
+        printf( "%d : %5d %5d %5d %5d %5d\n", 
+            pCut->nLeaves, 
+            pCut->nLeaves > 0 ? pCut->pLeaves[0] : -1, 
+            pCut->nLeaves > 1 ? pCut->pLeaves[1] : -1, 
+            pCut->nLeaves > 2 ? pCut->pLeaves[2] : -1, 
+            pCut->nLeaves > 3 ? pCut->pLeaves[3] : -1, 
+            pCut->nLeaves > 4 ? pCut->pLeaves[4] : -1
+            );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/cut/cutExpand.c b/abc-build/src/opt/cut/cutExpand.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cut/cutExpand.c
@@ -0,0 +1,189 @@
+/**CFile****************************************************************
+
+  FileName    [cutExpand.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [K-feasible cut computation package.]
+
+  Synopsis    [Computes the truth table of the cut after expansion.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cutExpand.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define CUT_CELL_MVAR  9
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the stretching phase of the cut w.r.t. the merged cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Cut_TruthPhase( Cut_Cut_t * pCut, Cut_Cut_t * pCut1 )
+{
+    unsigned uPhase = 0;
+    int i, k;
+    for ( i = k = 0; i < (int)pCut->nLeaves; i++ )
+    {
+        if ( k == (int)pCut1->nLeaves )
+            break;
+        if ( pCut->pLeaves[i] < pCut1->pLeaves[k] )
+            continue;
+        assert( pCut->pLeaves[i] == pCut1->pLeaves[k] );
+        uPhase |= (1 << i);
+        k++;
+    }
+    return uPhase;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the truth table of the composition of cuts.]
+
+  Description [Inputs are: 
+  - a factor cut (truth table is stored inside)
+  - a node in the factor cut
+  - a tree cut to be substituted (truth table is stored inside)
+  - the resulting cut (truth table will be filled in).
+  Note that all cuts, including the resulting one, should be already 
+  computed and the nodes should be stored in the ascending order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_TruthCompose( Cut_Cut_t * pCutF, int Node, Cut_Cut_t * pCutT, Cut_Cut_t * pCutRes )
+{
+    static unsigned uCof0[1<<(CUT_CELL_MVAR-5)];
+    static unsigned uCof1[1<<(CUT_CELL_MVAR-5)];
+    static unsigned uTemp[1<<(CUT_CELL_MVAR-5)];
+    unsigned * pIn, * pOut, * pTemp;
+    unsigned uPhase;
+    int NodeIndex, i, k;
+
+    // sanity checks
+    assert( pCutF->nVarsMax == pCutT->nVarsMax );
+    assert( pCutF->nVarsMax == pCutRes->nVarsMax );
+    assert( pCutF->nVarsMax <= CUT_CELL_MVAR );
+    // the factor cut (pCutF) should have its nodes sorted in the ascending order
+    assert( pCutF->nLeaves <= pCutF->nVarsMax );
+    for ( i = 0; i < (int)pCutF->nLeaves - 1; i++ )
+        assert( pCutF->pLeaves[i] < pCutF->pLeaves[i+1] );
+    // the tree cut (pCutT) should have its nodes sorted in the ascending order
+    assert( pCutT->nLeaves <= pCutT->nVarsMax );
+    for ( i = 0; i < (int)pCutT->nLeaves - 1; i++ )
+        assert( pCutT->pLeaves[i] < pCutT->pLeaves[i+1] );
+    // the resulting cut (pCutRes) should have its nodes sorted in the ascending order
+    assert( pCutRes->nLeaves <= pCutRes->nVarsMax );
+    for ( i = 0; i < (int)pCutRes->nLeaves - 1; i++ )
+        assert( pCutRes->pLeaves[i] < pCutRes->pLeaves[i+1] );
+    // make sure that every node in pCutF (except Node) appears in pCutRes
+    for ( i = 0; i < (int)pCutF->nLeaves; i++ )
+    {
+        if ( pCutF->pLeaves[i] == Node )
+            continue;
+        for ( k = 0; k < (int)pCutRes->nLeaves; k++ )
+            if ( pCutF->pLeaves[i] == pCutRes->pLeaves[k] )
+                break;
+        assert( k < (int)pCutRes->nLeaves ); // node i from pCutF is not found in pCutRes!!!
+    }
+    // make sure that every node in pCutT appears in pCutRes
+    for ( i = 0; i < (int)pCutT->nLeaves; i++ )
+    {
+        for ( k = 0; k < (int)pCutRes->nLeaves; k++ )
+            if ( pCutT->pLeaves[i] == pCutRes->pLeaves[k] )
+                break;
+        assert( k < (int)pCutRes->nLeaves ); // node i from pCutT is not found in pCutRes!!!
+    }
+
+
+    // find the index of the given node in the factor cut
+    NodeIndex = -1;
+    for ( NodeIndex = 0; NodeIndex < (int)pCutF->nLeaves; NodeIndex++ )
+        if ( pCutF->pLeaves[NodeIndex] == Node )
+            break;
+    assert( NodeIndex >= 0 );  // Node should be in pCutF
+
+    // copy the truth table
+    Extra_TruthCopy( uTemp, Cut_CutReadTruth(pCutF), pCutF->nLeaves );
+
+    // bubble-move the NodeIndex variable to be the last one (the most significant one)
+    pIn = uTemp; pOut = uCof0; // uCof0 is used for temporary storage here
+    for ( i = NodeIndex; i < (int)pCutF->nLeaves - 1; i++ )
+    {
+        Extra_TruthSwapAdjacentVars( pOut, pIn, pCutF->nLeaves, i );
+        pTemp = pIn; pIn = pOut; pOut = pTemp;
+    }
+    if ( (pCutF->nLeaves - 1 - NodeIndex) & 1 )
+        Extra_TruthCopy( pOut, pIn, pCutF->nLeaves );
+    // the result of stretching is in uTemp
+
+    // cofactor the factor cut with respect to the node
+    Extra_TruthCopy( uCof0, uTemp, pCutF->nLeaves );
+    Extra_TruthCofactor0( uCof0, pCutF->nLeaves, pCutF->nLeaves-1 );
+    Extra_TruthCopy( uCof1, uTemp, pCutF->nLeaves );
+    Extra_TruthCofactor1( uCof1, pCutF->nLeaves, pCutF->nLeaves-1 );
+
+    // temporarily shrink the factor cut's variables by removing Node 
+    for ( i = NodeIndex; i < (int)pCutF->nLeaves - 1; i++ )
+        pCutF->pLeaves[i] = pCutF->pLeaves[i+1];
+    pCutF->nLeaves--;
+
+    // spread out the cofactors' truth tables to the same var order as the resulting cut
+    uPhase = Cut_TruthPhase(pCutRes, pCutF);
+    assert( Extra_WordCountOnes(uPhase) == (int)pCutF->nLeaves );
+    Extra_TruthStretch( uTemp, uCof0, pCutF->nLeaves, pCutF->nVarsMax, uPhase );
+    Extra_TruthCopy( uCof0, uTemp, pCutF->nVarsMax );
+    Extra_TruthStretch( uTemp, uCof1, pCutF->nLeaves, pCutF->nVarsMax, uPhase );
+    Extra_TruthCopy( uCof1, uTemp, pCutF->nVarsMax );
+
+    // spread out the tree cut's truth table to the same var order as the resulting cut
+    uPhase = Cut_TruthPhase(pCutRes, pCutT); 
+    assert( Extra_WordCountOnes(uPhase) == (int)pCutT->nLeaves );
+    Extra_TruthStretch( uTemp, Cut_CutReadTruth(pCutT), pCutT->nLeaves, pCutT->nVarsMax, uPhase );
+
+    // create the resulting truth table
+    pTemp = Cut_CutReadTruth(pCutRes);
+    for ( i = Extra_TruthWordNum(pCutRes->nLeaves)-1; i >= 0; i-- )
+        pTemp[i] = (uCof0[i] & ~uTemp[i]) | (uCof1[i] & uTemp[i]);
+
+    // undo the removal of the node from the cut
+    for ( i = (int)pCutF->nLeaves - 1; i >= NodeIndex; --i )
+        pCutF->pLeaves[i+1] = pCutF->pLeaves[i];
+    pCutF->pLeaves[NodeIndex] = Node;
+    pCutF->nLeaves++;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/cut/cutInt.h b/abc-build/src/opt/cut/cutInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cut/cutInt.h
@@ -0,0 +1,165 @@
+/**CFile****************************************************************
+
+  FileName    [cutInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [K-feasible cut computation package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cutInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__opt__cut__cutInt_h
+#define ABC__opt__cut__cutInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "misc/extra/extra.h"
+#include "misc/vec/vec.h"
+#include "cut.h"
+#include "cutList.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Cut_HashTableStruct_t_ Cut_HashTable_t;
+
+struct Cut_ManStruct_t_
+{ 
+    // user preferences
+    Cut_Params_t *     pParams;          // computation parameters
+    Vec_Int_t *        vFanCounts;       // the array of fanout counters
+    Vec_Int_t *        vNodeAttrs;       // node attributes (1 = global; 0 = local)
+    // storage for cuts
+    Vec_Ptr_t *        vCutsNew;         // new cuts by node ID
+    Vec_Ptr_t *        vCutsOld;         // old cuts by node ID
+    Vec_Ptr_t *        vCutsTemp;        // temp cuts for cutset nodes by cutset node number
+    // memory management
+    Extra_MmFixed_t *  pMmCuts;
+    int                EntrySize;
+    int                nTruthWords;
+    // temporary variables
+    Cut_Cut_t *        pReady;
+    Vec_Ptr_t *        vTemp;
+    int                fCompl0;
+    int                fCompl1;
+    int                fSimul;
+    int                nNodeCuts;
+    Cut_Cut_t *        pStore0[2];
+    Cut_Cut_t *        pStore1[2];
+    Cut_Cut_t *        pCompareOld;
+    Cut_Cut_t *        pCompareNew;
+    unsigned *         puTemp[4];
+    // record of the cut computation
+    Vec_Int_t *        vNodeCuts;        // the number of cuts for each node
+    Vec_Int_t *        vNodeStarts;      // the number of the starting cut of each node
+    Vec_Int_t *        vCutPairs;        // the pairs of parent cuts for each cut
+    // minimum delay mapping with the given cuts
+    Vec_Ptr_t *        vCutsMax;
+    Vec_Int_t *        vDelays;
+    Vec_Int_t *        vDelays2;
+    int                nDelayMin;
+    // statistics
+    int                nCutsCur;
+    int                nCutsAlloc;
+    int                nCutsDealloc;
+    int                nCutsPeak;
+    int                nCutsTriv;
+    int                nCutsFilter;
+    int                nCutsLimit;
+    int                nNodes;
+    int                nNodesDag;
+    int                nNodesNoCuts;
+    // runtime
+    abctime            timeMerge;
+    abctime            timeUnion;
+    abctime            timeTruth;
+    abctime            timeFilter;
+    abctime            timeHash;
+    abctime            timeMap;
+};
+
+// iterator through all the cuts of the list
+#define Cut_ListForEachCut( pList, pCut )                 \
+    for ( pCut = pList;                                   \
+          pCut;                                           \
+          pCut = pCut->pNext )
+#define Cut_ListForEachCutStop( pList, pCut, pStop )      \
+    for ( pCut = pList;                                   \
+          pCut != pStop;                                  \
+          pCut = pCut->pNext )
+#define Cut_ListForEachCutSafe( pList, pCut, pCut2 )      \
+    for ( pCut = pList,                                   \
+          pCut2 = pCut? pCut->pNext: NULL;                \
+          pCut;                                           \
+          pCut = pCut2,                                   \
+          pCut2 = pCut? pCut->pNext: NULL )
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+// computes signature of the node
+static inline unsigned Cut_NodeSign( int Node )        { return (1 << (Node % 31));                        }
+static inline int      Cut_TruthWords( int nVarsMax )  { return nVarsMax <= 5 ? 1 : (1 << (nVarsMax - 5)); }
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== cutCut.c ==========================================================*/
+extern Cut_Cut_t *         Cut_CutAlloc( Cut_Man_t * p );
+extern void                Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut );
+extern int                 Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 );
+extern Cut_Cut_t *         Cut_CutDupList( Cut_Man_t * p, Cut_Cut_t * pList );
+extern void                Cut_CutRecycleList( Cut_Man_t * p, Cut_Cut_t * pList );
+extern Cut_Cut_t *         Cut_CutMergeLists( Cut_Cut_t * pList1, Cut_Cut_t * pList2 ); 
+extern void                Cut_CutNumberList( Cut_Cut_t * pList );
+extern Cut_Cut_t *         Cut_CutCreateTriv( Cut_Man_t * p, int Node );
+extern void                Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
+/*=== cutMerge.c ==========================================================*/
+extern Cut_Cut_t *         Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
+/*=== cutNode.c ==========================================================*/
+extern void                Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fCompl0, int fCompl1, Cut_Cut_t * pList0, Cut_Cut_t * pList1, int fTriv, int TreeCode ); 
+extern int                 Cut_CutListVerify( Cut_Cut_t * pList );
+/*=== cutTable.c ==========================================================*/
+extern Cut_HashTable_t *   Cut_TableStart( int Size );
+extern void                Cut_TableStop( Cut_HashTable_t * pTable );
+extern int                 Cut_TableLookup( Cut_HashTable_t * pTable, Cut_Cut_t * pCut, int fStore );
+extern void                Cut_TableClear( Cut_HashTable_t * pTable );
+extern int                 Cut_TableReadTime( Cut_HashTable_t * pTable );
+/*=== cutTruth.c ==========================================================*/
+extern void                Cut_TruthComputeOld( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 );
+extern void                Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/cut/cutList.h b/abc-build/src/opt/cut/cutList.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cut/cutList.h
@@ -0,0 +1,215 @@
+/**CFile****************************************************************
+
+  FileName    [cutList.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Implementation of layered listed list of cuts.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cutList.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__opt__cut__cutList_h
+#define ABC__opt__cut__cutList_h
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Cut_ListStruct_t_         Cut_List_t;
+struct Cut_ListStruct_t_
+{
+    Cut_Cut_t *  pHead[CUT_SIZE_MAX+1];
+    Cut_Cut_t ** ppTail[CUT_SIZE_MAX+1];
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Start the cut list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cut_ListStart( Cut_List_t * p )
+{
+    int i;
+    for ( i = 1; i <= CUT_SIZE_MAX; i++ )
+    {
+        p->pHead[i] = 0;
+        p->ppTail[i] = &p->pHead[i];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one cut to the cut list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cut_ListAdd( Cut_List_t * p, Cut_Cut_t * pCut )
+{
+    assert( pCut->nLeaves > 0 && pCut->nLeaves <= CUT_SIZE_MAX );
+    *p->ppTail[pCut->nLeaves] = pCut;
+    p->ppTail[pCut->nLeaves] = &pCut->pNext;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one cut to the cut list while preserving order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cut_ListAdd2( Cut_List_t * p, Cut_Cut_t * pCut )
+{
+    extern int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 );
+    Cut_Cut_t * pTemp, ** ppSpot;
+    assert( pCut->nLeaves > 0 && pCut->nLeaves <= CUT_SIZE_MAX );
+    if ( p->pHead[pCut->nLeaves] != NULL )
+    {
+        ppSpot = &p->pHead[pCut->nLeaves];
+        for ( pTemp = p->pHead[pCut->nLeaves]; pTemp; pTemp = pTemp->pNext )
+        {
+            if ( Cut_CutCompare(pCut, pTemp) < 0 )
+            {
+                *ppSpot = pCut;
+                pCut->pNext = pTemp;
+                return;
+            }
+            else
+                ppSpot = &pTemp->pNext;
+        }
+    }
+    *p->ppTail[pCut->nLeaves] = pCut;
+    p->ppTail[pCut->nLeaves] = &pCut->pNext;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive the super list from the linked list of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cut_ListDerive( Cut_List_t * p, Cut_Cut_t * pList )
+{
+    Cut_Cut_t * pPrev;
+    int nLeaves;
+    Cut_ListStart( p );
+    while ( pList != NULL )
+    {
+        nLeaves = pList->nLeaves;
+        p->pHead[nLeaves] = pList;
+        for ( pPrev = pList, pList = pList->pNext; pList; pPrev = pList, pList = pList->pNext )
+            if ( nLeaves < (int)pList->nLeaves )
+                break;
+        p->ppTail[nLeaves] = &pPrev->pNext;
+        pPrev->pNext = NULL;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the second list to the first list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cut_ListAddList( Cut_List_t * pOld, Cut_List_t * pNew )
+{
+    int i;
+    for ( i = 1; i <= CUT_SIZE_MAX; i++ )
+    {
+        if ( pNew->pHead[i] == NULL )
+            continue;
+        *pOld->ppTail[i] = pNew->pHead[i];
+        pOld->ppTail[i] = pNew->ppTail[i];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the cut list linked into one sequence of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Cut_Cut_t * Cut_ListFinish( Cut_List_t * p )
+{
+    Cut_Cut_t * pHead = NULL, ** ppTail = &pHead;
+    int i;
+    for ( i = 1; i <= CUT_SIZE_MAX; i++ )
+    {
+        if ( p->pHead[i] == NULL )
+            continue;
+        *ppTail = p->pHead[i];
+        ppTail = p->ppTail[i];
+    }
+    *ppTail = NULL;
+    return pHead;
+}
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/cut/cutMan.c b/abc-build/src/opt/cut/cutMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cut/cutMan.c
@@ -0,0 +1,320 @@
+/**CFile****************************************************************
+
+  FileName    [cutMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [K-feasible cut computation package.]
+
+  Synopsis    [Cut manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cutMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern void Npn_StartTruth8( uint8 uTruths[][32] );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the cut manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Man_t * Cut_ManStart( Cut_Params_t * pParams )
+{
+    Cut_Man_t * p;
+//    extern int nTruthDsd;
+//    nTruthDsd = 0;
+    assert( pParams->nVarsMax >= 3 && pParams->nVarsMax <= CUT_SIZE_MAX );
+    p = ABC_ALLOC( Cut_Man_t, 1 );
+    memset( p, 0, sizeof(Cut_Man_t) );
+    // set and correct parameters
+    p->pParams = pParams;
+    // prepare storage for cuts
+    p->vCutsNew = Vec_PtrAlloc( pParams->nIdsMax );
+    Vec_PtrFill( p->vCutsNew, pParams->nIdsMax, NULL );
+    // prepare storage for sequential cuts
+    if ( pParams->fSeq )
+    {
+        p->pParams->fFilter = 1;
+        p->vCutsOld = Vec_PtrAlloc( pParams->nIdsMax );
+        Vec_PtrFill( p->vCutsOld, pParams->nIdsMax, NULL );
+        p->vCutsTemp = Vec_PtrAlloc( pParams->nCutSet );
+        Vec_PtrFill( p->vCutsTemp, pParams->nCutSet, NULL );
+        if ( pParams->fTruth && pParams->nVarsMax > 5 )
+        {
+            pParams->fTruth = 0;
+            printf( "Skipping computation of truth tables for sequential cuts with more than 5 inputs.\n" );
+        }
+    }
+    // entry size
+    p->EntrySize = sizeof(Cut_Cut_t) + pParams->nVarsMax * sizeof(int);
+    if ( pParams->fTruth )
+    {
+        if ( pParams->nVarsMax > 14 )
+        {
+            pParams->fTruth = 0;
+            printf( "Skipping computation of truth table for more than %d inputs.\n", 14 );
+        }
+        else
+        {
+            p->nTruthWords = Cut_TruthWords( pParams->nVarsMax );
+            p->EntrySize += p->nTruthWords * sizeof(unsigned);
+        }
+        p->puTemp[0] = ABC_ALLOC( unsigned, 4 * p->nTruthWords );
+        p->puTemp[1] = p->puTemp[0] + p->nTruthWords;
+        p->puTemp[2] = p->puTemp[1] + p->nTruthWords;
+        p->puTemp[3] = p->puTemp[2] + p->nTruthWords;
+    }
+    // enable cut computation recording
+    if ( pParams->fRecord )
+    {
+        p->vNodeCuts   = Vec_IntStart( pParams->nIdsMax );
+        p->vNodeStarts = Vec_IntStart( pParams->nIdsMax );
+        p->vCutPairs   = Vec_IntAlloc( 0 );
+    }
+    // allocate storage for delays
+    if ( pParams->fMap && !p->pParams->fSeq )
+    {
+        p->vDelays = Vec_IntStart( pParams->nIdsMax );
+        p->vDelays2 = Vec_IntStart( pParams->nIdsMax );
+        p->vCutsMax = Vec_PtrStart( pParams->nIdsMax );
+    }
+    // memory for cuts
+    p->pMmCuts = Extra_MmFixedStart( p->EntrySize );
+    p->vTemp = Vec_PtrAlloc( 100 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the cut manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_ManStop( Cut_Man_t * p )
+{
+    if ( p->vCutsNew )    Vec_PtrFree( p->vCutsNew );
+    if ( p->vCutsOld )    Vec_PtrFree( p->vCutsOld );
+    if ( p->vCutsTemp )   Vec_PtrFree( p->vCutsTemp );
+    if ( p->vFanCounts )  Vec_IntFree( p->vFanCounts );
+    if ( p->vTemp )       Vec_PtrFree( p->vTemp );
+
+    if ( p->vCutsMax )    Vec_PtrFree( p->vCutsMax );
+    if ( p->vDelays )     Vec_IntFree( p->vDelays );
+    if ( p->vDelays2 )    Vec_IntFree( p->vDelays2 );
+    if ( p->vNodeCuts )   Vec_IntFree( p->vNodeCuts );
+    if ( p->vNodeStarts ) Vec_IntFree( p->vNodeStarts );
+    if ( p->vCutPairs )   Vec_IntFree( p->vCutPairs );
+    if ( p->puTemp[0] )   ABC_FREE( p->puTemp[0] );
+
+    Extra_MmFixedStop( p->pMmCuts );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_ManPrintStats( Cut_Man_t * p )
+{
+    if ( p->pReady )
+    {
+        Cut_CutRecycle( p, p->pReady );
+        p->pReady = NULL;
+    }
+    printf( "Cut computation statistics:\n" );
+    printf( "Current cuts      = %8d. (Trivial = %d.)\n", p->nCutsCur-p->nCutsTriv, p->nCutsTriv );
+    printf( "Peak cuts         = %8d.\n", p->nCutsPeak );
+    printf( "Total allocated   = %8d.\n", p->nCutsAlloc );
+    printf( "Total deallocated = %8d.\n", p->nCutsDealloc );
+    printf( "Cuts filtered     = %8d.\n", p->nCutsFilter );
+    printf( "Nodes saturated   = %8d. (Max cuts = %d.)\n", p->nCutsLimit, p->pParams->nKeepMax );
+    printf( "Cuts per node     = %8.1f\n", ((float)(p->nCutsCur-p->nCutsTriv))/p->nNodes );
+    printf( "The cut size      = %8d bytes.\n", p->EntrySize );
+    printf( "Peak memory       = %8.2f MB.\n", (float)p->nCutsPeak * p->EntrySize / (1<<20) );
+    printf( "Total nodes       = %8d.\n", p->nNodes );
+    if ( p->pParams->fDag || p->pParams->fTree )
+    {
+    printf( "DAG nodes         = %8d.\n", p->nNodesDag );
+    printf( "Tree nodes        = %8d.\n", p->nNodes - p->nNodesDag );
+    }
+    printf( "Nodes w/o cuts    = %8d.\n", p->nNodesNoCuts );
+    if ( p->pParams->fMap && !p->pParams->fSeq )
+    printf( "Mapping delay     = %8d.\n", p->nDelayMin );
+
+    ABC_PRT( "Merge ", p->timeMerge );
+    ABC_PRT( "Union ", p->timeUnion );
+    ABC_PRT( "Filter", p->timeFilter );
+    ABC_PRT( "Truth ", p->timeTruth );
+    ABC_PRT( "Map   ", p->timeMap );
+//    printf( "Nodes = %d. Multi = %d.  Cuts = %d. Multi = %d.\n", 
+//        p->nNodes, p->nNodesMulti, p->nCutsCur-p->nCutsTriv, p->nCutsMulti );
+//    printf( "Count0 = %d. Count1 = %d. Count2 = %d.\n\n", p->Count0, p->Count1, p->Count2 );
+}
+
+    
+/**Function*************************************************************
+
+  Synopsis    [Prints some interesting stats.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_ManPrintStatsToFile( Cut_Man_t * p, char * pFileName, abctime TimeTotal )
+{
+    FILE * pTable;
+    pTable = fopen( "cut_stats.txt", "a+" );
+    fprintf( pTable, "%-20s ", pFileName );
+    fprintf( pTable, "%8d ", p->nNodes );
+    fprintf( pTable, "%6.1f ", ((float)(p->nCutsCur))/p->nNodes );
+    fprintf( pTable, "%6.2f ", ((float)(100.0 * p->nCutsLimit))/p->nNodes );
+    fprintf( pTable, "%6.2f ", (float)p->nCutsPeak * p->EntrySize / (1<<20) );
+    fprintf( pTable, "%6.2f ", (float)(TimeTotal)/(float)(CLOCKS_PER_SEC) );
+    fprintf( pTable, "\n" );
+    fclose( pTable );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_ManSetFanoutCounts( Cut_Man_t * p, Vec_Int_t * vFanCounts )
+{
+    p->vFanCounts = vFanCounts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_ManSetNodeAttrs( Cut_Man_t * p, Vec_Int_t * vNodeAttrs )
+{
+    p->vNodeAttrs = vNodeAttrs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cut_ManReadVarsMax( Cut_Man_t * p )
+{
+    return p->pParams->nVarsMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Params_t * Cut_ManReadParams( Cut_Man_t * p )
+{
+    return p->pParams;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Cut_ManReadNodeAttrs( Cut_Man_t * p )
+{
+    return p->vNodeAttrs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_ManIncrementDagNodes( Cut_Man_t * p )
+{
+    p->nNodesDag++;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/cut/cutMerge.c b/abc-build/src/opt/cut/cutMerge.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cut/cutMerge.c
@@ -0,0 +1,662 @@
+/**CFile****************************************************************
+
+  FileName    [cutMerge.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [K-feasible cut computation package.]
+
+  Synopsis    [Procedure to merge two cuts.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cutMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two cuts.]
+
+  Description [This procedure works.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutMergeTwo2( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+{ 
+    static int M[7][3] = {{0},{0},{0},{0},{0},{0},{0}};
+    Cut_Cut_t * pRes;
+    int * pRow;
+    int nLeaves0, nLeaves1, Limit;
+    int i, k, Count, nNodes;
+
+    assert( pCut0->nLeaves >= pCut1->nLeaves );
+
+    // the case of the largest cut sizes
+    Limit = p->pParams->nVarsMax;
+    nLeaves0 = pCut0->nLeaves;
+    nLeaves1 = pCut1->nLeaves;
+    if ( nLeaves0 == Limit && nLeaves1 == Limit )
+    {
+        for ( i = 0; i < nLeaves0; i++ )
+            if ( pCut0->pLeaves[i] != pCut1->pLeaves[i] )
+                return NULL;
+        pRes = Cut_CutAlloc( p );
+        for ( i = 0; i < nLeaves0; i++ )
+            pRes->pLeaves[i] = pCut0->pLeaves[i];
+        pRes->nLeaves = nLeaves0;
+        return pRes;
+    }
+    // the case when one of the cuts is the largest
+    if ( nLeaves0 == Limit )
+    {
+        for ( i = 0; i < nLeaves1; i++ )
+        {
+            for ( k = nLeaves0 - 1; k >= 0; k-- )
+                if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] )
+                    break;
+            if ( k == -1 ) // did not find
+                return NULL;
+        }
+        pRes = Cut_CutAlloc( p );
+        for ( i = 0; i < nLeaves0; i++ )
+            pRes->pLeaves[i] = pCut0->pLeaves[i];
+        pRes->nLeaves = nLeaves0;
+        return pRes;
+    }
+    // other cases
+    nNodes = nLeaves0;
+    for ( i = 0; i < nLeaves1; i++ )
+    {
+        for ( k = nLeaves0 - 1; k >= 0; k-- )
+        {
+            if ( pCut0->pLeaves[k] > pCut1->pLeaves[i] )
+                continue;
+            if ( pCut0->pLeaves[k] < pCut1->pLeaves[i] )
+            {
+                pRow = M[k+1];
+                if ( pRow[0] == 0 )
+                    pRow[0] = pCut1->pLeaves[i], pRow[1] = 0;
+                else if ( pRow[1] == 0 )
+                    pRow[1] = pCut1->pLeaves[i], pRow[2] = 0;
+                else if ( pRow[2] == 0 )
+                    pRow[2] = pCut1->pLeaves[i];
+                else 
+                    assert( 0 );
+                if ( ++nNodes > Limit )
+                {
+                    for ( i = 0; i <= nLeaves0; i++ )
+                        M[i][0] = 0;
+                    return NULL;
+                }
+            }
+            break;
+        }
+        if ( k == -1 )
+        {
+            pRow = M[0];
+            if ( pRow[0] == 0 )
+                pRow[0] = pCut1->pLeaves[i], pRow[1] = 0;
+            else if ( pRow[1] == 0 )
+                pRow[1] = pCut1->pLeaves[i], pRow[2] = 0;
+            else if ( pRow[2] == 0 )
+                pRow[2] = pCut1->pLeaves[i];
+            else 
+                assert( 0 );
+            if ( ++nNodes > Limit )
+            {
+                for ( i = 0; i <= nLeaves0; i++ )
+                    M[i][0] = 0;
+                return NULL;
+            }
+            continue;
+        }
+    }
+
+    pRes = Cut_CutAlloc( p );
+    for ( Count = 0, i = 0; i <= nLeaves0; i++ )
+    {
+        if ( i > 0 )
+            pRes->pLeaves[Count++] = pCut0->pLeaves[i-1];
+        pRow = M[i];
+        if ( pRow[0] )
+        {
+            pRes->pLeaves[Count++] = pRow[0];
+            if ( pRow[1] )
+            {
+                pRes->pLeaves[Count++] = pRow[1];
+                if ( pRow[2] )
+                    pRes->pLeaves[Count++] = pRow[2];
+            }
+            pRow[0] = 0;
+        }
+    }
+    assert( Count == nNodes );
+    pRes->nLeaves = nNodes;
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+{ 
+    Cut_Cut_t * pRes;
+    int * pLeaves;
+    int Limit, nLeaves0, nLeaves1;
+    int i, k, c;
+
+    assert( pCut0->nLeaves >= pCut1->nLeaves );
+
+    // consider two cuts
+    nLeaves0 = pCut0->nLeaves;
+    nLeaves1 = pCut1->nLeaves;
+
+    // the case of the largest cut sizes
+    Limit = p->pParams->nVarsMax;
+    if ( nLeaves0 == Limit && nLeaves1 == Limit )
+    {
+        for ( i = 0; i < nLeaves0; i++ )
+            if ( pCut0->pLeaves[i] != pCut1->pLeaves[i] )
+                return NULL;
+        pRes = Cut_CutAlloc( p );
+        for ( i = 0; i < nLeaves0; i++ )
+            pRes->pLeaves[i] = pCut0->pLeaves[i];
+        pRes->nLeaves = pCut0->nLeaves;
+        return pRes;
+    }
+    // the case when one of the cuts is the largest
+    if ( nLeaves0 == Limit )
+    {
+        for ( i = 0; i < nLeaves1; i++ )
+        {
+            for ( k = nLeaves0 - 1; k >= 0; k-- )
+                if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] )
+                    break;
+            if ( k == -1 ) // did not find
+                return NULL;
+        }
+        pRes = Cut_CutAlloc( p );
+        for ( i = 0; i < nLeaves0; i++ )
+            pRes->pLeaves[i] = pCut0->pLeaves[i];
+        pRes->nLeaves = pCut0->nLeaves;
+        return pRes;
+    }
+
+    // prepare the cut
+    if ( p->pReady == NULL )
+        p->pReady = Cut_CutAlloc( p );
+    pLeaves = p->pReady->pLeaves;
+
+    // compare two cuts with different numbers
+    i = k = 0;
+    for ( c = 0; c < Limit; c++ )
+    {
+        if ( k == nLeaves1 )
+        {
+            if ( i == nLeaves0 )
+            {
+                p->pReady->nLeaves = c;
+                pRes = p->pReady;  p->pReady = NULL;
+                return pRes;
+            }
+            pLeaves[c] = pCut0->pLeaves[i++];
+            continue;
+        }
+        if ( i == nLeaves0 )
+        {
+            if ( k == nLeaves1 )
+            {
+                p->pReady->nLeaves = c;
+                pRes = p->pReady;  p->pReady = NULL;
+                return pRes;
+            }
+            pLeaves[c] = pCut1->pLeaves[k++];
+            continue;
+        }
+        if ( pCut0->pLeaves[i] < pCut1->pLeaves[k] )
+        {
+            pLeaves[c] = pCut0->pLeaves[i++];
+            continue;
+        }
+        if ( pCut0->pLeaves[i] > pCut1->pLeaves[k] )
+        {
+            pLeaves[c] = pCut1->pLeaves[k++];
+            continue;
+        }
+        pLeaves[c] = pCut0->pLeaves[i++]; 
+        k++;
+    }
+    if ( i < nLeaves0 || k < nLeaves1 )
+        return NULL;
+    p->pReady->nLeaves = c;
+    pRes = p->pReady;  p->pReady = NULL;
+    return pRes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutMergeTwo3( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+{ 
+    Cut_Cut_t * pRes;
+    int * pLeaves;
+    int Limit, nLeaves0, nLeaves1;
+    int i, k, c;
+
+    assert( pCut0->nLeaves >= pCut1->nLeaves );
+
+    // prepare the cut
+    if ( p->pReady == NULL )
+        p->pReady = Cut_CutAlloc( p );
+    pLeaves = p->pReady->pLeaves;
+
+    // consider two cuts
+    Limit = p->pParams->nVarsMax;
+    nLeaves0 = pCut0->nLeaves;
+    nLeaves1 = pCut1->nLeaves;
+    if ( nLeaves0 == Limit )
+    { // the case when one of the cuts is the largest
+        if ( nLeaves1 == Limit )
+        { // the case when both cuts are the largest
+            for ( i = 0; i < nLeaves0; i++ )
+            {
+                pLeaves[i] = pCut0->pLeaves[i];
+                if ( pLeaves[i] != pCut1->pLeaves[i] )
+                    return NULL;
+            }
+        }
+        else
+        {
+            for ( i = k = 0; i < nLeaves0; i++ )
+            {
+                pLeaves[i] = pCut0->pLeaves[i];
+                if ( k == (int)nLeaves1 )
+                    continue;
+                if ( pLeaves[i] < pCut1->pLeaves[k] )
+                    continue;
+                if ( pLeaves[i] == pCut1->pLeaves[k++] )
+                    continue;
+                return NULL;
+            }
+            if ( k < nLeaves1 )
+                return NULL;
+        }
+        p->pReady->nLeaves = nLeaves0;
+        pRes = p->pReady;  p->pReady = NULL;
+        return pRes;
+    }
+
+    // compare two cuts with different numbers
+    i = k = 0;
+    for ( c = 0; c < Limit; c++ )
+    {
+        if ( k == nLeaves1 )
+        {
+            if ( i == nLeaves0 )
+            {
+                p->pReady->nLeaves = c;
+                pRes = p->pReady;  p->pReady = NULL;
+                return pRes;
+            }
+            pLeaves[c] = pCut0->pLeaves[i++];
+            continue;
+        }
+        if ( i == nLeaves0 )
+        {
+            if ( k == nLeaves1 )
+            {
+                p->pReady->nLeaves = c;
+                pRes = p->pReady;  p->pReady = NULL;
+                return pRes;
+            }
+            pLeaves[c] = pCut1->pLeaves[k++];
+            continue;
+        }
+        if ( pCut0->pLeaves[i] < pCut1->pLeaves[k] )
+        {
+            pLeaves[c] = pCut0->pLeaves[i++];
+            continue;
+        }
+        if ( pCut0->pLeaves[i] > pCut1->pLeaves[k] )
+        {
+            pLeaves[c] = pCut1->pLeaves[k++];
+            continue;
+        }
+        pLeaves[c] = pCut0->pLeaves[i++]; 
+        k++;
+    }
+    if ( i < nLeaves0 || k < nLeaves1 )
+        return NULL;
+    p->pReady->nLeaves = c;
+    pRes = p->pReady;  p->pReady = NULL;
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutMergeTwo4( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+{ 
+    Cut_Cut_t * pRes;
+    int * pLeaves;
+    int i, k, min, NodeTemp, Limit, nTotal;
+
+    assert( pCut0->nLeaves >= pCut1->nLeaves );
+
+    // prepare the cut
+    if ( p->pReady == NULL )
+        p->pReady = Cut_CutAlloc( p );
+    pLeaves = p->pReady->pLeaves;
+
+    // consider two cuts
+    Limit = p->pParams->nVarsMax;
+    if ( pCut0->nLeaves == (unsigned)Limit )
+    { // the case when one of the cuts is the largest
+        if ( pCut1->nLeaves == (unsigned)Limit )
+        { // the case when both cuts are the largest
+            for ( i = 0; i < (int)pCut0->nLeaves; i++ )
+            {
+                pLeaves[i] = pCut0->pLeaves[i];
+                if ( pLeaves[i] != pCut1->pLeaves[i] )
+                    return NULL;
+            }
+        }
+        else
+        {
+            for ( i = k = 0; i < (int)pCut0->nLeaves; i++ )
+            {
+                pLeaves[i] = pCut0->pLeaves[i];
+                if ( k == (int)pCut1->nLeaves )
+                    continue;
+                if ( pLeaves[i] < pCut1->pLeaves[k] )
+                    continue;
+                if ( pLeaves[i] == pCut1->pLeaves[k++] )
+                    continue;
+                return NULL;
+            }
+            if ( k < (int)pCut1->nLeaves )
+                return NULL;
+        }
+        p->pReady->nLeaves = pCut0->nLeaves;
+        pRes = p->pReady;  p->pReady = NULL;
+        return pRes;
+    }
+
+    // count the number of unique entries in pCut1
+    nTotal = pCut0->nLeaves;
+    for ( i = 0; i < (int)pCut1->nLeaves; i++ )
+    {
+        // try to find this entry among the leaves of pCut0
+        for ( k = 0; k < (int)pCut0->nLeaves; k++ )
+            if ( pCut1->pLeaves[i] == pCut0->pLeaves[k] )
+                break;
+        if ( k < (int)pCut0->nLeaves ) // found
+            continue;
+        // we found a new entry to add
+        if ( nTotal == Limit )
+            return NULL;
+        pLeaves[nTotal++] = pCut1->pLeaves[i];
+    }
+    // we know that the feasible cut exists
+
+    // add the starting entries
+    for ( k = 0; k < (int)pCut0->nLeaves; k++ )
+        pLeaves[k] = pCut0->pLeaves[k];
+
+    // selection-sort the entries
+    for ( i = 0; i < nTotal - 1; i++ )
+    {
+        min = i;
+        for ( k = i+1; k < nTotal; k++ )
+            if ( pLeaves[k] < pLeaves[min] )
+                min = k;
+        NodeTemp     = pLeaves[i];
+        pLeaves[i]   = pLeaves[min];
+        pLeaves[min] = NodeTemp;
+    }
+    p->pReady->nLeaves = nTotal;
+    pRes = p->pReady;  p->pReady = NULL;
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two cuts.]
+
+  Description [This procedure works.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutMergeTwo5( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+{ 
+    static int M[7][3] = {{0},{0},{0},{0},{0},{0},{0}};
+    Cut_Cut_t * pRes;
+    int * pRow;
+    unsigned uSign0, uSign1;
+    int i, k, nNodes, Count;
+    unsigned Limit = p->pParams->nVarsMax;
+
+    assert( pCut0->nLeaves >= pCut1->nLeaves );
+
+    // the case of the largest cut sizes
+    if ( pCut0->nLeaves == Limit && pCut1->nLeaves == Limit )
+    {
+        for ( i = 0; i < (int)pCut0->nLeaves; i++ )
+            if ( pCut0->pLeaves[i] != pCut1->pLeaves[i] )
+                return NULL;
+        pRes = Cut_CutAlloc( p );
+        for ( i = 0; i < (int)pCut0->nLeaves; i++ )
+            pRes->pLeaves[i] = pCut0->pLeaves[i];
+        pRes->nLeaves = pCut0->nLeaves;
+        return pRes;
+    }
+    // the case when one of the cuts is the largest
+    if ( pCut0->nLeaves == Limit )
+    {
+        if ( !p->pParams->fTruth )
+        {
+            for ( i = 0; i < (int)pCut1->nLeaves; i++ )
+            {
+                for ( k = pCut0->nLeaves - 1; k >= 0; k-- )
+                    if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] )
+                        break;
+                if ( k == -1 ) // did not find
+                    return NULL;
+            }
+            pRes = Cut_CutAlloc( p );
+        }
+        else
+        {
+            uSign1 = 0;
+            for ( i = 0; i < (int)pCut1->nLeaves; i++ )
+            {
+                for ( k = pCut0->nLeaves - 1; k >= 0; k-- )
+                    if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] )
+                    {
+                        uSign1 |= (1 << i);
+                        break;
+                    }
+                if ( k == -1 ) // did not find
+                    return NULL;
+            }
+            pRes = Cut_CutAlloc( p );
+            pRes->Num1 = uSign1;
+        }
+        for ( i = 0; i < (int)pCut0->nLeaves; i++ )
+            pRes->pLeaves[i] = pCut0->pLeaves[i];
+        pRes->nLeaves = pCut0->nLeaves;
+        return pRes;
+    }
+    // other cases
+    nNodes = pCut0->nLeaves;
+    for ( i = 0; i < (int)pCut1->nLeaves; i++ )
+    {
+        for ( k = pCut0->nLeaves - 1; k >= 0; k-- )
+        {
+            if ( pCut0->pLeaves[k] > pCut1->pLeaves[i] )
+                continue;
+            if ( pCut0->pLeaves[k] < pCut1->pLeaves[i] )
+            {
+                pRow = M[k+1];
+                if ( pRow[0] == 0 )
+                    pRow[0] = pCut1->pLeaves[i], pRow[1] = 0;
+                else if ( pRow[1] == 0 )
+                    pRow[1] = pCut1->pLeaves[i], pRow[2] = 0;
+                else if ( pRow[2] == 0 )
+                    pRow[2] = pCut1->pLeaves[i];
+                else 
+                    assert( 0 );
+                if ( ++nNodes > (int)Limit )
+                {
+                    for ( i = 0; i <= (int)pCut0->nLeaves; i++ )
+                        M[i][0] = 0;
+                    return NULL;
+                }
+            }
+            break;
+        }
+        if ( k == -1 )
+        {
+            pRow = M[0];
+            if ( pRow[0] == 0 )
+                pRow[0] = pCut1->pLeaves[i], pRow[1] = 0;
+            else if ( pRow[1] == 0 )
+                pRow[1] = pCut1->pLeaves[i], pRow[2] = 0;
+            else if ( pRow[2] == 0 )
+                pRow[2] = pCut1->pLeaves[i];
+            else 
+                assert( 0 );
+            if ( ++nNodes > (int)Limit )
+            {
+                for ( i = 0; i <= (int)pCut0->nLeaves; i++ )
+                    M[i][0] = 0;
+                return NULL;
+            }
+            continue;
+        }
+    }
+
+    pRes = Cut_CutAlloc( p );
+    if ( !p->pParams->fTruth )
+    {
+        for ( Count = 0, i = 0; i <= (int)pCut0->nLeaves; i++ )
+        {
+            if ( i > 0 )
+                pRes->pLeaves[Count++] = pCut0->pLeaves[i-1];
+            pRow = M[i];
+            if ( pRow[0] )
+            {
+                pRes->pLeaves[Count++] = pRow[0];
+                if ( pRow[1] )
+                {
+                    pRes->pLeaves[Count++] = pRow[1];
+                    if ( pRow[2] )
+                        pRes->pLeaves[Count++] = pRow[2];
+                }
+                pRow[0] = 0;
+            }
+        }
+        assert( Count == nNodes );
+        pRes->nLeaves = nNodes;
+/*
+    // make sure that the cut is correct
+    {
+        for ( i = 1; i < (int)pRes->nLeaves; i++ )
+            if ( pRes->pLeaves[i-1] >= pRes->pLeaves[i] )
+            {
+                int v = 0;
+            }
+    }
+*/
+        return pRes;
+    }
+
+    uSign0 = uSign1 = 0;
+    for ( Count = 0, i = 0; i <= (int)pCut0->nLeaves; i++ )
+    {
+        if ( i > 0 )
+        {
+            uSign0 |= (1 << Count);
+            pRes->pLeaves[Count++] = pCut1->pLeaves[i-1];
+        }
+        pRow = M[i];
+        if ( pRow[0] )
+        {
+            uSign1 |= (1 << Count);
+            pRes->pLeaves[Count++] = pRow[0];
+            if ( pRow[1] )
+            {
+                uSign1 |= (1 << Count);
+                pRes->pLeaves[Count++] = pRow[1];
+                if ( pRow[2] )
+                {
+                    uSign1 |= (1 << Count);
+                    pRes->pLeaves[Count++] = pRow[2];
+                }
+            }
+            pRow[0] = 0;
+        }
+    }
+    assert( Count == nNodes );
+    pRes->nLeaves = nNodes;
+    pRes->Num1 = uSign1;
+    pRes->Num0 = uSign0;
+    return pRes;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/cut/cutNode.c b/abc-build/src/opt/cut/cutNode.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cut/cutNode.c
@@ -0,0 +1,1004 @@
+/**CFile****************************************************************
+
+  FileName    [cutNode.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [K-feasible cut computation package.]
+
+  Synopsis    [Procedures to compute cuts for a node.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cutNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Cut_NodeMapping( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 );
+static int Cut_NodeMapping2( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pDom is contained in pCut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cut_CutCheckDominance( Cut_Cut_t * pDom, Cut_Cut_t * pCut )
+{
+    int i, k;
+    for ( i = 0; i < (int)pDom->nLeaves; i++ )
+    {
+        for ( k = 0; k < (int)pCut->nLeaves; k++ )
+            if ( pDom->pLeaves[i] == pCut->pLeaves[k] )
+                break;
+        if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut
+            return 0;
+    }
+    // every node in pDom is contained in pCut
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Filters cuts using dominance.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cut_CutFilter( Cut_Man_t * p, Cut_Cut_t * pList )
+{ 
+    Cut_Cut_t * pListR, ** ppListR = &pListR;
+    Cut_Cut_t * pCut, * pCut2, * pDom, * pPrev;
+    // save the first cut
+    *ppListR = pList, ppListR = &pList->pNext;
+    // try to filter out other cuts
+    pPrev = pList;
+    Cut_ListForEachCutSafe( pList->pNext, pCut, pCut2 )
+    {
+        assert( pCut->nLeaves > 1 );
+        // go through all the previous cuts up to pCut
+        Cut_ListForEachCutStop( pList->pNext, pDom, pCut )
+        {
+            if ( pDom->nLeaves > pCut->nLeaves )
+                continue;
+            if ( (pDom->uSign & pCut->uSign) != pDom->uSign )
+                continue;
+            if ( Cut_CutCheckDominance( pDom, pCut ) )
+                break;
+        }
+        if ( pDom != pCut ) // pDom is contained in pCut - recycle pCut
+        {
+            // make sure cuts are connected after removing
+            pPrev->pNext = pCut->pNext;
+            // recycle the cut
+            Cut_CutRecycle( p, pCut );
+        }
+        else // pDom is NOT contained in pCut - save pCut
+        {
+            *ppListR = pCut, ppListR = &pCut->pNext;
+            pPrev = pCut;
+        }
+    }
+    *ppListR = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks equality of one cut.]
+
+  Description [Returns 1 if the cut is removed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cut_CutFilterOneEqual( Cut_Man_t * p, Cut_List_t * pSuperList, Cut_Cut_t * pCut )
+{
+    Cut_Cut_t * pTemp;
+    Cut_ListForEachCut( pSuperList->pHead[pCut->nLeaves], pTemp )
+    {
+        // skip the non-contained cuts
+        if ( pCut->uSign != pTemp->uSign )
+            continue;
+        // check containment seriously
+        if ( Cut_CutCheckDominance( pTemp, pCut ) )
+        {
+            p->nCutsFilter++;
+            Cut_CutRecycle( p, pCut );
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks containment for one cut.]
+
+  Description [Returns 1 if the cut is removed.]
+               
+  SideEffects [May remove other cuts in the set.]
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cut_CutFilterOne( Cut_Man_t * p, Cut_List_t * pSuperList, Cut_Cut_t * pCut )
+{
+    Cut_Cut_t * pTemp, * pTemp2, ** ppTail;
+    int a;
+
+    // check if this cut is filtered out by smaller cuts
+    for ( a = 2; a <= (int)pCut->nLeaves; a++ )
+    {
+        Cut_ListForEachCut( pSuperList->pHead[a], pTemp )
+        {
+            // skip the non-contained cuts
+            if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign )
+                continue;
+            // check containment seriously
+            if ( Cut_CutCheckDominance( pTemp, pCut ) )
+            {
+                p->nCutsFilter++;
+                Cut_CutRecycle( p, pCut );
+                return 1;
+            }
+        }
+    }
+
+    // filter out other cuts using this one
+    for ( a = pCut->nLeaves + 1; a <= (int)pCut->nVarsMax; a++ )
+    {
+        ppTail = pSuperList->pHead + a;
+        Cut_ListForEachCutSafe( pSuperList->pHead[a], pTemp, pTemp2 )
+        {
+            // skip the non-contained cuts
+            if ( (pTemp->uSign & pCut->uSign) != pCut->uSign )
+            {
+                ppTail = &pTemp->pNext;
+                continue;
+            }
+            // check containment seriously
+            if ( Cut_CutCheckDominance( pCut, pTemp ) )
+            {
+                p->nCutsFilter++;
+                p->nNodeCuts--;
+                // move the head
+                if ( pSuperList->pHead[a] == pTemp )
+                    pSuperList->pHead[a] = pTemp->pNext;
+                // move the tail
+                if ( pSuperList->ppTail[a] == &pTemp->pNext )
+                    pSuperList->ppTail[a] = ppTail;
+                // skip the given cut in the list
+                *ppTail = pTemp->pNext;
+                // recycle pTemp
+                Cut_CutRecycle( p, pTemp );
+            }
+            else
+                ppTail = &pTemp->pNext;
+        }
+        assert( ppTail == pSuperList->ppTail[a] );
+        assert( *ppTail == NULL );
+    }
+
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the cut is local and can be removed.]
+
+  Description [Returns 1 if the cut is removed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cut_CutFilterGlobal( Cut_Man_t * p, Cut_Cut_t * pCut )
+{
+    int a;
+    if ( pCut->nLeaves == 1 )
+        return 0;
+    for ( a = 0; a < (int)pCut->nLeaves; a++ )
+        if ( Vec_IntEntry( p->vNodeAttrs, pCut->pLeaves[a] ) ) // global
+            return 0;
+    // there is no global nodes, the cut should be removed
+    p->nCutsFilter++;
+    Cut_CutRecycle( p, pCut );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks containment for one cut.]
+
+  Description [Returns 1 if the cut is removed.]
+               
+  SideEffects [May remove other cuts in the set.]
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cut_CutFilterOld( Cut_Man_t * p, Cut_Cut_t * pList, Cut_Cut_t * pCut )
+{
+    Cut_Cut_t * pPrev, * pTemp, * pTemp2, ** ppTail;
+
+    // check if this cut is filtered out by smaller cuts
+    pPrev = NULL;
+    Cut_ListForEachCut( pList, pTemp )
+    {
+        if ( pTemp->nLeaves > pCut->nLeaves )
+            break;
+        pPrev = pTemp;
+        // skip the non-contained cuts
+        if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign )
+            continue;
+        // check containment seriously
+        if ( Cut_CutCheckDominance( pTemp, pCut ) )
+        {
+            p->nCutsFilter++;
+            Cut_CutRecycle( p, pCut );
+            return 1;
+        }
+    }
+    assert( pPrev->pNext == pTemp );
+
+    // filter out other cuts using this one
+    ppTail = &pPrev->pNext;
+    Cut_ListForEachCutSafe( pTemp, pTemp, pTemp2 )
+    {
+        // skip the non-contained cuts
+        if ( (pTemp->uSign & pCut->uSign) != pCut->uSign )
+        {
+            ppTail = &pTemp->pNext;
+            continue;
+        }
+        // check containment seriously
+        if ( Cut_CutCheckDominance( pCut, pTemp ) )
+        {
+            p->nCutsFilter++;
+            p->nNodeCuts--;
+            // skip the given cut in the list
+            *ppTail = pTemp->pNext;
+            // recycle pTemp
+            Cut_CutRecycle( p, pTemp );
+        }
+        else
+            ppTail = &pTemp->pNext;
+    }
+    assert( *ppTail == NULL );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Processes two cuts.]
+
+  Description [Returns 1 if the limit has been reached.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cut_CutProcessTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, Cut_List_t * pSuperList )
+{
+    Cut_Cut_t * pCut;
+    // merge the cuts
+    if ( pCut0->nLeaves >= pCut1->nLeaves )
+        pCut = Cut_CutMergeTwo( p, pCut0, pCut1 );
+    else
+        pCut = Cut_CutMergeTwo( p, pCut1, pCut0 );
+    if ( pCut == NULL )
+        return 0;
+    assert( p->pParams->fSeq || pCut->nLeaves > 1 );
+    // set the signature
+    pCut->uSign = pCut0->uSign | pCut1->uSign;
+    if ( p->pParams->fRecord )
+        pCut->Num0 = pCut0->Num0, pCut->Num1 = pCut1->Num0;
+    // check containment
+    if ( p->pParams->fFilter )
+    {
+        if ( Cut_CutFilterOne(p, pSuperList, pCut) )
+//        if ( Cut_CutFilterOneEqual(p, pSuperList, pCut) )
+            return 0;
+        if ( p->pParams->fSeq )
+        {
+            if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) )
+                return 0;
+            if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) )
+                return 0;
+        }
+    }
+
+    if ( p->pParams->fGlobal )
+    {
+        assert( p->vNodeAttrs != NULL );
+        if ( Cut_CutFilterGlobal( p, pCut ) )
+            return 0;
+    }
+
+    // compute the truth table
+    if ( p->pParams->fTruth )
+        Cut_TruthCompute( p, pCut, pCut0, pCut1, p->fCompl0, p->fCompl1 );
+    // add to the list
+    Cut_ListAdd( pSuperList, pCut );
+    // return status (0 if okay; 1 if exceeded the limit)
+    return ++p->nNodeCuts == p->pParams->nKeepMax;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts by merging cuts at two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv, int TreeCode )
+{
+    Cut_List_t Super, * pSuper = &Super;
+    Cut_Cut_t * pList, * pCut;
+    abctime clk;
+    // start the number of cuts at the node
+    p->nNodes++;
+    p->nNodeCuts = 0;
+    // prepare information for recording
+    if ( p->pParams->fRecord )
+    {
+        Cut_CutNumberList( Cut_NodeReadCutsNew(p, Node0) );
+        Cut_CutNumberList( Cut_NodeReadCutsNew(p, Node1) );
+    }
+    // compute the cuts
+clk = Abc_Clock();
+    Cut_ListStart( pSuper );
+    Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, Cut_NodeReadCutsNew(p, Node0), Cut_NodeReadCutsNew(p, Node1), fTriv, TreeCode );
+    pList = Cut_ListFinish( pSuper );
+p->timeMerge += Abc_Clock() - clk;
+    // verify the result of cut computation
+//    Cut_CutListVerify( pList );
+    // performing the recording
+    if ( p->pParams->fRecord )
+    {
+        Vec_IntWriteEntry( p->vNodeStarts, Node, Vec_IntSize(p->vCutPairs) );
+        Cut_ListForEachCut( pList, pCut )
+            Vec_IntPush( p->vCutPairs, ((pCut->Num1 << 16) | pCut->Num0) );
+        Vec_IntWriteEntry( p->vNodeCuts, Node, Vec_IntSize(p->vCutPairs) - Vec_IntEntry(p->vNodeStarts, Node) );
+    }
+    if ( p->pParams->fRecordAig )
+    {
+        extern void Aig_RManRecord( unsigned * pTruth, int nVarsInit );
+        Cut_ListForEachCut( pList, pCut )
+            if ( Cut_CutReadLeaveNum(pCut) > 4 )
+                Aig_RManRecord( Cut_CutReadTruth(pCut), Cut_CutReadLeaveNum(pCut) );
+    }
+    // check if the node is over the list
+    if ( p->nNodeCuts == p->pParams->nKeepMax )
+        p->nCutsLimit++;
+    // set the list at the node
+    Vec_PtrFillExtra( p->vCutsNew, Node + 1, NULL );
+    assert( Cut_NodeReadCutsNew(p, Node) == NULL );
+    /////
+//    pList->pNext = NULL;
+    /////
+    Cut_NodeWriteCutsNew( p, Node, pList );
+    // filter the cuts
+//clk = Abc_Clock();
+//    if ( p->pParams->fFilter )
+//        Cut_CutFilter( p, pList0 );
+//p->timeFilter += Abc_Clock() - clk;
+    // perform mapping of this node with these cuts
+clk = Abc_Clock();
+    if ( p->pParams->fMap && !p->pParams->fSeq )
+    {
+//        int Delay1, Delay2;
+//        Delay1 = Cut_NodeMapping( p, pList, Node, Node0, Node1 );    
+//        Delay2 = Cut_NodeMapping2( p, pList, Node, Node0, Node1 );   
+//        assert( Delay1 >= Delay2 );
+        Cut_NodeMapping( p, pList, Node, Node0, Node1 );
+    }
+p->timeMap += Abc_Clock() - clk;
+    return pList;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns optimum delay mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cut_NodeMapping2( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 )
+{
+    Cut_Cut_t * pCut;
+    int DelayMin, DelayCur, i;
+    if ( pCuts == NULL )
+        p->nDelayMin = -1;
+    if ( p->nDelayMin == -1 )
+        return -1;
+    DelayMin = 1000000;
+    Cut_ListForEachCut( pCuts, pCut )
+    {
+        if ( pCut->nLeaves == 1 )
+            continue;
+        DelayCur = 0;
+        for ( i = 0; i < (int)pCut->nLeaves; i++ )
+            if ( DelayCur < Vec_IntEntry(p->vDelays, pCut->pLeaves[i]) )
+                DelayCur = Vec_IntEntry(p->vDelays, pCut->pLeaves[i]);
+        if ( DelayMin > DelayCur )
+            DelayMin = DelayCur;
+    }
+    if ( DelayMin == 1000000 )
+    {
+         p->nDelayMin = -1;
+         return -1;
+    }
+    DelayMin++;
+    Vec_IntWriteEntry( p->vDelays, Node, DelayMin );
+    if ( p->nDelayMin < DelayMin )
+        p->nDelayMin = DelayMin;
+    return DelayMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns optimum delay mapping using the largest cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cut_NodeMapping( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 )
+{
+    Cut_Cut_t * pCut0, * pCut1, * pCut;
+    int Delay0, Delay1, Delay;
+    // get the fanin cuts
+    Delay0 = Vec_IntEntry( p->vDelays2, Node0 );
+    Delay1 = Vec_IntEntry( p->vDelays2, Node1 );
+    pCut0 = (Delay0 == 0) ? (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node0 ) : (Cut_Cut_t *)Vec_PtrEntry( p->vCutsMax, Node0 );
+    pCut1 = (Delay1 == 0) ? (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node1 ) : (Cut_Cut_t *)Vec_PtrEntry( p->vCutsMax, Node1 );
+    if ( Delay0 == Delay1 )
+        Delay = (Delay0 == 0) ? Delay0 + 1: Delay0;
+    else if ( Delay0 > Delay1 )
+    {
+        Delay = Delay0;
+        pCut1 = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node1 );
+        assert( pCut1->nLeaves == 1 );
+    }
+    else // if ( Delay0 < Delay1 )
+    {
+        Delay = Delay1;
+        pCut0 = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node0 );
+        assert( pCut0->nLeaves == 1 );
+    }
+    // merge the cuts
+    if ( pCut0->nLeaves < pCut1->nLeaves )
+        pCut  = Cut_CutMergeTwo( p, pCut1, pCut0 );
+    else
+        pCut  = Cut_CutMergeTwo( p, pCut0, pCut1 );
+    if ( pCut == NULL )
+    {
+        Delay++;
+        pCut = Cut_CutAlloc( p );
+        pCut->nLeaves = 2;
+        pCut->pLeaves[0] = Node0 < Node1 ? Node0 : Node1;
+        pCut->pLeaves[1] = Node0 < Node1 ? Node1 : Node0;
+    }
+    assert( Delay > 0 );
+    Vec_IntWriteEntry( p->vDelays2, Node, Delay );
+    Vec_PtrWriteEntry( p->vCutsMax, Node, pCut );
+    if ( p->nDelayMin < Delay )
+        p->nDelayMin = Delay;
+    return Delay;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area after mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cut_ManMappingArea_rec( Cut_Man_t * p, int Node )
+{
+    Cut_Cut_t * pCut;
+    int i, Counter;
+    if ( p->vCutsMax == NULL )
+        return 0;
+    pCut = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsMax, Node );
+    if ( pCut == NULL || pCut->nLeaves == 1 )
+        return 0;
+    Counter = 0;
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        Counter += Cut_ManMappingArea_rec( p, pCut->pLeaves[i] );
+    Vec_PtrWriteEntry( p->vCutsMax, Node, NULL );
+    return 1 + Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts by merging cuts at two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fCompl0, int fCompl1, Cut_Cut_t * pList0, Cut_Cut_t * pList1, int fTriv, int TreeCode )
+{
+    Cut_Cut_t * pStop0, * pStop1, * pTemp0, * pTemp1;
+    Cut_Cut_t * pStore0 = NULL, * pStore1 = NULL; // Suppress "might be used uninitialized"
+    int i, nCutsOld, Limit;
+    // start with the elementary cut
+    if ( fTriv ) 
+    {
+//        printf( "Creating trivial cut %d.\n", Node );
+        pTemp0 = Cut_CutCreateTriv( p, Node );
+        Cut_ListAdd( pSuper, pTemp0 );
+        p->nNodeCuts++;
+    }
+    // get the cut lists of children
+    if ( pList0 == NULL || pList1 == NULL || (p->pParams->fLocal && TreeCode)  )
+        return;
+
+    // remember the old number of cuts
+    nCutsOld = p->nCutsCur;
+    Limit = p->pParams->nVarsMax;
+    // get the simultation bit of the node
+    p->fSimul = (fCompl0 ^ pList0->fSimul) & (fCompl1 ^ pList1->fSimul);
+    // set temporary variables
+    p->fCompl0 = fCompl0;
+    p->fCompl1 = fCompl1;
+    // if tree cuts are computed, make sure only the unit cuts propagate over the DAG nodes
+    if ( TreeCode & 1 )
+    {
+        assert( pList0->nLeaves == 1 );
+        pStore0 = pList0->pNext;
+        pList0->pNext = NULL;
+    }
+    if ( TreeCode & 2 )
+    {
+        assert( pList1->nLeaves == 1 );
+        pStore1 = pList1->pNext;
+        pList1->pNext = NULL;
+    }
+    // find the point in the list where the max-var cuts begin
+    Cut_ListForEachCut( pList0, pStop0 )
+        if ( pStop0->nLeaves == (unsigned)Limit )
+            break;
+    Cut_ListForEachCut( pList1, pStop1 )
+        if ( pStop1->nLeaves == (unsigned)Limit )
+            break;
+
+    // small by small
+    Cut_ListForEachCutStop( pList0, pTemp0, pStop0 )
+    Cut_ListForEachCutStop( pList1, pTemp1, pStop1 )
+    {
+        if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) )
+            goto Quits;
+    }
+    // small by large
+    Cut_ListForEachCutStop( pList0, pTemp0, pStop0 )
+    Cut_ListForEachCut( pStop1, pTemp1 )
+    {
+        if ( (pTemp0->uSign & pTemp1->uSign) != pTemp0->uSign )
+            continue;
+        if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) )
+            goto Quits;
+    }
+    // small by large
+    Cut_ListForEachCutStop( pList1, pTemp1, pStop1 )
+    Cut_ListForEachCut( pStop0, pTemp0 )
+    {
+        if ( (pTemp0->uSign & pTemp1->uSign) != pTemp1->uSign )
+            continue;
+        if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) )
+            goto Quits;
+    }
+    // large by large
+    Cut_ListForEachCut( pStop0, pTemp0 )
+    Cut_ListForEachCut( pStop1, pTemp1 )
+    {
+        assert( pTemp0->nLeaves == (unsigned)Limit && pTemp1->nLeaves == (unsigned)Limit );
+        if ( pTemp0->uSign != pTemp1->uSign )
+            continue;
+        for ( i = 0; i < Limit; i++ )
+            if ( pTemp0->pLeaves[i] != pTemp1->pLeaves[i] )
+                break;
+        if ( i < Limit )
+            continue;
+        if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) )
+            goto Quits;
+    } 
+    if ( p->nNodeCuts == 0 )
+        p->nNodesNoCuts++;
+Quits:
+    if ( TreeCode & 1 )
+        pList0->pNext = pStore0;
+    if ( TreeCode & 2 )
+        pList1->pNext = pStore1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts by unioning cuts at a choice node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes )
+{
+    Cut_List_t Super, * pSuper = &Super;
+    Cut_Cut_t * pList, * pListStart, * pCut, * pCut2;
+    Cut_Cut_t * pTop = NULL; // Suppress "might be used uninitialized"
+    int i, k, Node, Root, Limit = p->pParams->nVarsMax;
+    abctime clk = Abc_Clock();
+
+    // start the new list
+    Cut_ListStart( pSuper );
+
+    // remember the root node to save the resulting cuts
+    Root = Vec_IntEntry( vNodes, 0 );
+    p->nNodeCuts = 1;
+
+    // collect small cuts first
+    Vec_PtrClear( p->vTemp );
+    Vec_IntForEachEntry( vNodes, Node, i )
+    {
+        // get the cuts of this node
+        pList = Cut_NodeReadCutsNew( p, Node );
+        Cut_NodeWriteCutsNew( p, Node, NULL );
+        assert( pList );
+        // remember the starting point
+        pListStart = pList->pNext;
+        pList->pNext = NULL;
+        // save or recycle the elementary cut
+        if ( i == 0 )
+            Cut_ListAdd( pSuper, pList ), pTop = pList;
+        else
+            Cut_CutRecycle( p, pList );
+        // save all the cuts that are smaller than the limit
+        Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
+        {
+            if ( pCut->nLeaves == (unsigned)Limit )
+            {
+                Vec_PtrPush( p->vTemp, pCut );
+                break;
+            }
+            // check containment
+            if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) )
+                continue;
+            // set the complemented bit by comparing the first cut with the current cut
+            pCut->fCompl = pTop->fSimul ^ pCut->fSimul;
+            pListStart = pCut->pNext;
+            pCut->pNext = NULL;
+            // add to the list
+            Cut_ListAdd( pSuper, pCut );
+            if ( ++p->nNodeCuts == p->pParams->nKeepMax )
+            {
+                // recycle the rest of the cuts of this node
+                Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
+                    Cut_CutRecycle( p, pCut );
+                // recycle all cuts of other nodes
+                Vec_IntForEachEntryStart( vNodes, Node, k, i+1 )
+                    Cut_NodeFreeCuts( p, Node );
+                // recycle the saved cuts of other nodes
+                Vec_PtrForEachEntry( Cut_Cut_t *, p->vTemp, pList, k )
+                    Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+                        Cut_CutRecycle( p, pCut );
+                goto finish;
+            }
+        }
+    } 
+    // collect larger cuts next
+    Vec_PtrForEachEntry( Cut_Cut_t *, p->vTemp, pList, i )
+    {
+        Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+        {
+            // check containment
+            if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) )
+                continue;
+            // set the complemented bit
+            pCut->fCompl = pTop->fSimul ^ pCut->fSimul;
+            pListStart = pCut->pNext;
+            pCut->pNext = NULL;
+            // add to the list
+            Cut_ListAdd( pSuper, pCut );
+            if ( ++p->nNodeCuts == p->pParams->nKeepMax )
+            {
+                // recycle the rest of the cuts
+                Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
+                    Cut_CutRecycle( p, pCut );
+                // recycle the saved cuts of other nodes
+                Vec_PtrForEachEntryStart( Cut_Cut_t *, p->vTemp, pList, k, i+1 )
+                    Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+                        Cut_CutRecycle( p, pCut );
+                goto finish;
+            }
+        }
+    }
+finish :
+    // set the cuts at the node
+    assert( Cut_NodeReadCutsNew(p, Root) == NULL );
+    pList = Cut_ListFinish( pSuper );
+    Cut_NodeWriteCutsNew( p, Root, pList );
+p->timeUnion += Abc_Clock() - clk;
+    // filter the cuts
+//clk = Abc_Clock();
+//    if ( p->pParams->fFilter )
+//        Cut_CutFilter( p, pList );
+//p->timeFilter += Abc_Clock() - clk;
+    p->nNodes -= vNodes->nSize - 1;
+    return pList;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the cuts by unioning cuts at a choice node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_NodeUnionCutsSeq( Cut_Man_t * p, Vec_Int_t * vNodes, int CutSetNum, int fFirst )
+{
+    Cut_List_t Super, * pSuper = &Super;
+    Cut_Cut_t * pList, * pListStart, * pCut, * pCut2, * pTop;
+    int i, k, Node, Root, Limit = p->pParams->nVarsMax;
+    abctime clk = Abc_Clock();
+
+    // start the new list
+    Cut_ListStart( pSuper );
+
+    // remember the root node to save the resulting cuts
+    Root = Vec_IntEntry( vNodes, 0 );
+    p->nNodeCuts = 1;
+
+    // store the original lists for comparison
+    p->pCompareOld = Cut_NodeReadCutsOld( p, Root );
+    p->pCompareNew = (CutSetNum >= 0)? Cut_NodeReadCutsNew( p, Root ) : NULL;
+
+    // get the topmost cut
+    pTop = NULL;
+    if ( (pTop = Cut_NodeReadCutsOld( p, Root )) == NULL )
+        pTop = Cut_NodeReadCutsNew( p, Root );
+    assert( pTop != NULL );
+
+    // collect small cuts first
+    Vec_PtrClear( p->vTemp );
+    Vec_IntForEachEntry( vNodes, Node, i )
+    {
+        // get the cuts of this node
+        if ( i == 0 && CutSetNum >= 0 )
+        {
+            pList = Cut_NodeReadCutsTemp( p, CutSetNum );
+            Cut_NodeWriteCutsTemp( p, CutSetNum, NULL );
+        }
+        else
+        {
+            pList = Cut_NodeReadCutsNew( p, Node );
+            Cut_NodeWriteCutsNew( p, Node, NULL );
+        }
+        if ( pList == NULL )
+            continue;
+
+        // process the cuts
+        if ( fFirst )
+        {
+            // remember the starting point
+            pListStart = pList->pNext;
+            pList->pNext = NULL;
+            // save or recycle the elementary cut
+            if ( i == 0 )
+                Cut_ListAdd( pSuper, pList );
+            else
+                Cut_CutRecycle( p, pList );
+        }
+        else
+            pListStart = pList;
+
+        // save all the cuts that are smaller than the limit
+        Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
+        {
+            if ( pCut->nLeaves == (unsigned)Limit )
+            {
+                Vec_PtrPush( p->vTemp, pCut );
+                break;
+            }
+            // check containment
+//            if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) )
+//                continue;
+            if ( p->pParams->fFilter )
+            {
+                if ( Cut_CutFilterOne(p, pSuper, pCut) )
+                    continue;
+                if ( p->pParams->fSeq )
+                {
+                    if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) )
+                        continue;
+                    if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) )
+                        continue;
+                }
+            }
+
+            // set the complemented bit by comparing the first cut with the current cut
+            pCut->fCompl = pTop->fSimul ^ pCut->fSimul;
+            pListStart = pCut->pNext;
+            pCut->pNext = NULL;
+            // add to the list
+            Cut_ListAdd( pSuper, pCut );
+            if ( ++p->nNodeCuts == p->pParams->nKeepMax )
+            {
+                // recycle the rest of the cuts of this node
+                Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
+                    Cut_CutRecycle( p, pCut );
+                // recycle all cuts of other nodes
+                Vec_IntForEachEntryStart( vNodes, Node, k, i+1 )
+                    Cut_NodeFreeCuts( p, Node );
+                // recycle the saved cuts of other nodes
+                Vec_PtrForEachEntry( Cut_Cut_t *, p->vTemp, pList, k )
+                    Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+                        Cut_CutRecycle( p, pCut );
+                goto finish;
+            }
+        }
+    } 
+    // collect larger cuts next
+    Vec_PtrForEachEntry( Cut_Cut_t *, p->vTemp, pList, i )
+    {
+        Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+        {
+            // check containment
+//            if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) )
+//                continue;
+            if ( p->pParams->fFilter )
+            {
+                if ( Cut_CutFilterOne(p, pSuper, pCut) )
+                    continue;
+                if ( p->pParams->fSeq )
+                {
+                    if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) )
+                        continue;
+                    if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) )
+                        continue;
+                }
+            }
+
+            // set the complemented bit
+            pCut->fCompl = pTop->fSimul ^ pCut->fSimul;
+            pListStart   = pCut->pNext;
+            pCut->pNext  = NULL;
+            // add to the list
+            Cut_ListAdd( pSuper, pCut );
+            if ( ++p->nNodeCuts == p->pParams->nKeepMax )
+            {
+                // recycle the rest of the cuts
+                Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
+                    Cut_CutRecycle( p, pCut );
+                // recycle the saved cuts of other nodes
+                Vec_PtrForEachEntryStart( Cut_Cut_t *, p->vTemp, pList, k, i+1 )
+                    Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+                        Cut_CutRecycle( p, pCut );
+                goto finish;
+            }
+        }
+    }
+finish :
+    // set the cuts at the node
+    pList = Cut_ListFinish( pSuper );
+
+    // set the lists at the node
+//    assert( Cut_NodeReadCutsNew(p, Root) == NULL );
+//    Cut_NodeWriteCutsNew( p, Root, pList );
+    if ( CutSetNum >= 0 )
+    {
+        assert( Cut_NodeReadCutsTemp(p, CutSetNum) == NULL );
+        Cut_NodeWriteCutsTemp( p, CutSetNum, pList );
+    }
+    else
+    {
+        assert( Cut_NodeReadCutsNew(p, Root) == NULL );
+        Cut_NodeWriteCutsNew( p, Root, pList );
+    }
+
+p->timeUnion += Abc_Clock() - clk;
+    // filter the cuts
+//clk = Abc_Clock();
+//    if ( p->pParams->fFilter )
+//        Cut_CutFilter( p, pList );
+//p->timeFilter += Abc_Clock() - clk;
+//    if ( fFirst )
+//        p->nNodes -= vNodes->nSize - 1;
+    return pList;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies that the list contains only non-dominated cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cut_CutListVerify( Cut_Cut_t * pList )
+{ 
+    Cut_Cut_t * pCut, * pDom;
+    Cut_ListForEachCut( pList, pCut )
+    {
+        Cut_ListForEachCutStop( pList, pDom, pCut )
+        {
+            if ( Cut_CutCheckDominance( pDom, pCut ) )
+            {
+                printf( "******************* These are contained cuts:\n" );
+                Cut_CutPrint( pDom, 1 );
+                Cut_CutPrint( pDom, 1 );
+                return 0;
+            }
+        }
+    }
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/cut/cutOracle.c b/abc-build/src/opt/cut/cutOracle.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cut/cutOracle.c
@@ -0,0 +1,424 @@
+/**CFile****************************************************************
+
+  FileName    [cutOracle.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [K-feasible cut computation package.]
+
+  Synopsis    [Procedures to compute cuts for a node using the oracle.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cutOracle.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+struct Cut_OracleStruct_t_
+{
+    // cut comptupatation parameters
+    Cut_Params_t *     pParams;
+    Vec_Int_t *        vFanCounts;
+    int                fSimul;
+    // storage for cuts
+    Vec_Ptr_t *        vCutsNew;
+    Vec_Ptr_t *        vCuts0;
+    Vec_Ptr_t *        vCuts1;
+    // oracle info 
+    Vec_Int_t *        vNodeCuts;
+    Vec_Int_t *        vNodeStarts;
+    Vec_Int_t *        vCutPairs;
+    // memory management
+    Extra_MmFixed_t *  pMmCuts;
+    int                EntrySize;
+    int                nTruthWords;
+    // stats
+    abctime            timeTotal;
+    int                nCuts;
+    int                nCutsTriv;
+};
+
+static Cut_Cut_t * Cut_CutStart( Cut_Oracle_t * p );
+static Cut_Cut_t * Cut_CutTriv( Cut_Oracle_t * p, int Node );
+static Cut_Cut_t * Cut_CutMerge( Cut_Oracle_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the cut oracle.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Oracle_t * Cut_OracleStart( Cut_Man_t * pMan )
+{
+    Cut_Oracle_t * p;
+
+    assert( pMan->pParams->nVarsMax >= 3 && pMan->pParams->nVarsMax <= CUT_SIZE_MAX );
+    assert( pMan->pParams->fRecord );
+
+    p = ABC_ALLOC( Cut_Oracle_t, 1 );
+    memset( p, 0, sizeof(Cut_Oracle_t) );
+
+    // set and correct parameters
+    p->pParams     = pMan->pParams;
+
+    // transfer the recording info
+    p->vNodeCuts   = pMan->vNodeCuts;    pMan->vNodeCuts   = NULL;
+    p->vNodeStarts = pMan->vNodeStarts;  pMan->vNodeStarts = NULL;
+    p->vCutPairs   = pMan->vCutPairs;    pMan->vCutPairs   = NULL;
+
+    // prepare storage for cuts
+    p->vCutsNew = Vec_PtrAlloc( p->pParams->nIdsMax );
+    Vec_PtrFill( p->vCutsNew, p->pParams->nIdsMax, NULL );
+    p->vCuts0 = Vec_PtrAlloc( 100 );
+    p->vCuts1 = Vec_PtrAlloc( 100 );
+
+    // entry size
+    p->EntrySize = sizeof(Cut_Cut_t) + p->pParams->nVarsMax * sizeof(int);
+    if ( p->pParams->fTruth )
+    {
+        if ( p->pParams->nVarsMax > 8 )
+        {
+            p->pParams->fTruth = 0;
+            printf( "Skipping computation of truth table for more than 8 inputs.\n" );
+        }
+        else
+        {
+            p->nTruthWords = Cut_TruthWords( p->pParams->nVarsMax );
+            p->EntrySize += p->nTruthWords * sizeof(unsigned);
+        }
+    }
+    // memory for cuts
+    p->pMmCuts = Extra_MmFixedStart( p->EntrySize );
+    return p;
+}
+/**Function*************************************************************
+
+  Synopsis    [Stop the cut oracle.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_OracleStop( Cut_Oracle_t * p )
+{
+//    if ( p->pParams->fVerbose )
+    {
+        printf( "Cut computation statistics with oracle:\n" );
+        printf( "Current cuts      = %8d. (Trivial = %d.)\n", p->nCuts-p->nCutsTriv, p->nCutsTriv );
+        ABC_PRT( "Total time ", p->timeTotal );
+    }
+
+    if ( p->vCuts0 )      Vec_PtrFree( p->vCuts0 );
+    if ( p->vCuts1 )      Vec_PtrFree( p->vCuts1 );
+    if ( p->vCutsNew )    Vec_PtrFree( p->vCutsNew );
+    if ( p->vFanCounts )  Vec_IntFree( p->vFanCounts );
+
+    if ( p->vNodeCuts )   Vec_IntFree( p->vNodeCuts );
+    if ( p->vNodeStarts ) Vec_IntFree( p->vNodeStarts );
+    if ( p->vCutPairs )   Vec_IntFree( p->vCutPairs );
+
+    Extra_MmFixedStop( p->pMmCuts );
+    ABC_FREE( p ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_OracleSetFanoutCounts( Cut_Oracle_t * p, Vec_Int_t * vFanCounts )
+{
+    p->vFanCounts = vFanCounts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cut_OracleReadDrop( Cut_Oracle_t * p )
+{
+    return p->pParams->fDrop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the trivial cut for the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_OracleNodeSetTriv( Cut_Oracle_t * p, int Node )
+{
+    assert( Vec_PtrEntry( p->vCutsNew, Node ) == NULL );
+    Vec_PtrWriteEntry( p->vCutsNew, Node, Cut_CutTriv(p, Node) );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutStart( Cut_Oracle_t * p )
+{
+    Cut_Cut_t * pCut;
+    // cut allocation
+    pCut = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts );
+    memset( pCut, 0, sizeof(Cut_Cut_t) );
+    pCut->nVarsMax   = p->pParams->nVarsMax;
+    pCut->fSimul     = p->fSimul;
+    p->nCuts++;
+    return pCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the trivial cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutTriv( Cut_Oracle_t * p, int Node )
+{
+    Cut_Cut_t * pCut;
+    pCut = Cut_CutStart( p );
+    pCut->nLeaves    = 1;
+    pCut->pLeaves[0] = Node;
+    if ( p->pParams->fTruth )
+    {
+        unsigned * pTruth = Cut_CutReadTruth(pCut);
+        int i;
+        for ( i = 0; i < p->nTruthWords; i++ )
+            pTruth[i] = 0xAAAAAAAA;
+    }
+    p->nCutsTriv++;
+    return pCut;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutMerge( Cut_Oracle_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+{
+    Cut_Cut_t * pCut;
+    int Limit, i, k, c;
+    // create the leaves of the new cut
+    pCut = Cut_CutStart( p );
+    Limit = p->pParams->nVarsMax;
+    for ( i = k = c = 0; c < Limit; c++ )
+    {
+        if ( k == (int)pCut1->nLeaves )
+        {
+            if ( i == (int)pCut0->nLeaves )
+            {
+                pCut->nLeaves = c;
+                return pCut;
+            }
+            pCut->pLeaves[c] = pCut0->pLeaves[i++];
+            continue;
+        }
+        if ( i == (int)pCut0->nLeaves )
+        {
+            if ( k == (int)pCut1->nLeaves )
+            {
+                pCut->nLeaves = c;
+                return pCut;
+            }
+            pCut->pLeaves[c] = pCut1->pLeaves[k++];
+            continue;
+        }
+        if ( pCut0->pLeaves[i] < pCut1->pLeaves[k] )
+        {
+            pCut->pLeaves[c] = pCut0->pLeaves[i++];
+            continue;
+        }
+        if ( pCut0->pLeaves[i] > pCut1->pLeaves[k] )
+        {
+            pCut->pLeaves[c] = pCut1->pLeaves[k++];
+            continue;
+        }
+        pCut->pLeaves[c] = pCut0->pLeaves[i++]; 
+        k++;
+    }
+    assert( i == (int)pCut0->nLeaves && k == (int)pCut1->nLeaves );
+    pCut->nLeaves = c;
+    return pCut;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Reconstruct the cuts of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_Cut_t * Cut_OracleComputeCuts( Cut_Oracle_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 )
+{
+    Cut_Cut_t * pList = NULL, ** ppTail = &pList;
+    Cut_Cut_t * pCut, * pCut0, * pCut1, * pList0, * pList1;
+    int iCutStart, nCuts, i, Entry;
+    abctime clk = Abc_Clock();
+
+    // get the cuts of the children
+    pList0 = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node0 );
+    pList1 = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node1 );
+    assert( pList0 && pList1 );
+
+    // get the complemented attribute of the cut
+    p->fSimul = (fCompl0 ^ pList0->fSimul) & (fCompl1 ^ pList1->fSimul);
+
+    // collect the cuts
+    Vec_PtrClear( p->vCuts0 );
+    Cut_ListForEachCut( pList0, pCut )
+        Vec_PtrPush( p->vCuts0, pCut );
+    Vec_PtrClear( p->vCuts1 );
+    Cut_ListForEachCut( pList1, pCut )
+        Vec_PtrPush( p->vCuts1, pCut );
+
+    // get the first and last cuts of this node
+    nCuts = Vec_IntEntry(p->vNodeCuts, Node);
+    iCutStart = Vec_IntEntry(p->vNodeStarts, Node);
+
+    // create trivial cut
+    assert( Vec_IntEntry(p->vCutPairs, iCutStart) == 0 );
+    pCut = Cut_CutTriv( p, Node );
+    *ppTail = pCut;
+    ppTail = &pCut->pNext;
+    // create other cuts
+    for ( i = 1; i < nCuts; i++ )
+    {
+        Entry = Vec_IntEntry( p->vCutPairs, iCutStart + i );
+        pCut0 = (Cut_Cut_t *)Vec_PtrEntry( p->vCuts0, Entry & 0xFFFF );
+        pCut1 = (Cut_Cut_t *)Vec_PtrEntry( p->vCuts1, Entry >> 16 );
+        pCut  = Cut_CutMerge( p, pCut0, pCut1 );
+        *ppTail = pCut;
+        ppTail = &pCut->pNext;
+        // compute the truth table
+        if ( p->pParams->fTruth )
+            Cut_TruthComputeOld( pCut, pCut0, pCut1, fCompl0, fCompl1 );
+    }
+    *ppTail = NULL;
+
+    // write the new cut
+    assert( Vec_PtrEntry( p->vCutsNew, Node ) == NULL );
+    Vec_PtrWriteEntry( p->vCutsNew, Node, pList );
+p->timeTotal += Abc_Clock() - clk;
+    return pList;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the cuts at the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_OracleFreeCuts( Cut_Oracle_t * p, int Node )
+{
+    Cut_Cut_t * pList, * pCut, * pCut2;
+    pList = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node );
+    if ( pList == NULL )
+        return;
+    Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+        Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut );
+    Vec_PtrWriteEntry( p->vCutsNew, Node, pList );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Consider dropping cuts if they are useless by now.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_OracleTryDroppingCuts( Cut_Oracle_t * p, int Node )
+{
+    int nFanouts;
+    assert( p->vFanCounts );
+    nFanouts = Vec_IntEntry( p->vFanCounts, Node );
+    assert( nFanouts > 0 );
+    if ( --nFanouts == 0 )
+        Cut_OracleFreeCuts( p, Node );
+    Vec_IntWriteEntry( p->vFanCounts, Node, nFanouts );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/cut/cutPre22.c b/abc-build/src/opt/cut/cutPre22.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cut/cutPre22.c
@@ -0,0 +1,994 @@
+/**CFile****************************************************************
+
+  FileName    [cutPre22.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Precomputes truth tables for the 2x2 macro cell.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cutPre22.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define CUT_CELL_MVAR  9
+
+typedef struct Cut_Cell_t_ Cut_Cell_t;
+typedef struct Cut_CMan_t_ Cut_CMan_t;
+
+struct Cut_Cell_t_
+{
+    Cut_Cell_t *       pNext;                        // pointer to the next cell in the table
+    Cut_Cell_t *       pNextVar;                     // pointer to the next cell of this support size
+    Cut_Cell_t *       pParent;                      // pointer to the cell used to derive this one
+    int                nUsed;                        // the number of times the cell is used
+    char               Box[4];                       // functions in the boxes
+    unsigned           nVars          :  4;          // the number of variables
+    unsigned           CrossBar0      :  4;          // the variable set equal
+    unsigned           CrossBar1      :  4;          // the variable set equal
+    unsigned           CrossBarPhase  :  2;          // the phase of the cross bar (0, 1, or 2)
+    unsigned           CanonPhase     : 18;          // the canonical phase
+    char               CanonPerm[CUT_CELL_MVAR+3];   // semicanonical permutation
+    short              Store[2*CUT_CELL_MVAR];       // minterm counts in the cofactors
+    unsigned           uTruth[1<<(CUT_CELL_MVAR-5)]; // the current truth table
+};
+
+struct Cut_CMan_t_
+{
+    // storage for canonical cells
+    Extra_MmFixed_t *  pMem;
+    st__table *         tTable;
+    Cut_Cell_t *       pSameVar[CUT_CELL_MVAR+1];
+    // elementary truth tables
+    unsigned           uInputs[CUT_CELL_MVAR][1<<(CUT_CELL_MVAR-5)];
+    // temporary truth tables
+    unsigned           uTemp1[22][1<<(CUT_CELL_MVAR-5)];
+    unsigned           uTemp2[22][1<<(CUT_CELL_MVAR-5)];
+    unsigned           uTemp3[22][1<<(CUT_CELL_MVAR-5)];
+    unsigned           uFinal[1<<(CUT_CELL_MVAR-5)];
+    unsigned           puAux[1<<(CUT_CELL_MVAR-5)];
+    // statistical variables
+    int                nTotal;
+    int                nGood;
+    int                nVarCounts[CUT_CELL_MVAR+1];
+    int                nSymGroups[CUT_CELL_MVAR+1];
+    int                nSymGroupsE[CUT_CELL_MVAR+1];
+    abctime            timeCanon;
+    abctime            timeSupp;
+    abctime            timeTable;
+    int                nCellFound;
+    int                nCellNotFound;
+};
+
+// NP-classes of functions of 3 variables (22)
+//static char * s_NP3[22] = {
+//    " 0\n",                          // 00    const 0            // 0 vars
+//    " 1\n",                          // 01    const 1            // 0 vars
+//    "1 1\n",                         // 02    a                  // 1 vars
+//    "11 1\n",                        // 03    ab                 // 2 vars
+//    "11 0\n",                        // 04    (ab)'              // 2 vars
+//    "10 1\n01 1\n",                  // 05    a<+>b              // 2 vars
+//    "111 1\n",                       // 06 0s abc                // 3 vars
+//    "111 0\n",                       // 07    (abc)'             //
+//    "11- 1\n1-1 1\n",                // 08 1p a(b+c)             //
+//    "11- 0\n1-1 0\n",                // 09    (a(b+c))'          //
+//    "111 1\n100 1\n010 1\n001 1\n",  // 10 2s a<+>b<+>c          //
+//    "10- 0\n1-0 0\n011 0\n",         // 11 3p a<+>bc             //
+//    "101 1\n110 1\n",                // 12 4p a(b<+>c)           //
+//    "101 0\n110 0\n",                // 13    (a(b<+>c))'        //
+//    "11- 1\n1-1 1\n-11 1\n",         // 14 5s ab+bc+ac           //
+//    "111 1\n000 1\n",                // 15 6s abc+a'b'c'         //
+//    "111 0\n000 0\n",                // 16    (abc+a'b'c')'      //
+//    "11- 1\n-11 1\n0-1 1\n",         // 17 7  ab+bc+a'c          //
+//    "011 1\n101 1\n110 1\n",         // 18 8s a'bc+ab'c+abc'     //
+//    "011 0\n101 0\n110 0\n",         // 19    (a'bc+ab'c+abc')'  //
+//    "100 1\n-11 1\n",                // 20 9p ab'c'+bc           //
+//    "100 0\n-11 0\n"                 // 21    (ab'c'+bc)'        //
+//};
+
+// NP-classes of functions of 3 variables (22)
+static char * s_NP3Names[22] = {
+    "   const 0            ",
+    "   const 1            ",
+    "   a                  ",
+    "   ab                 ",
+    "   (ab)'              ",
+    "   a<+>b              ",
+    "0s abc                ",
+    "   (abc)'             ",
+    "1p a(b+c)             ",
+    "   (a(b+c))'          ",
+    "2s a<+>b<+>c          ",
+    "3p a<+>bc             ",
+    "4p a(b<+>c)           ",
+    "   (a(b<+>c))'        ",
+    "5s ab+bc+ac           ",
+    "6s abc+a'b'c'         ",
+    "   (abc+a'b'c')'      ",
+    "7  ab+bc+a'c          ",
+    "8s a'bc+ab'c+abc'     ",
+    "   (a'bc+ab'c+abc')'  ",
+    "9p ab'c'+bc           ",
+    "   (ab'c'+bc)'        "
+};
+
+// the number of variables in each function
+//static int s_NP3VarNums[22] = { 0, 0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };
+
+// NPN classes of functions of exactly 3 inputs (10)
+static int s_NPNe3[10] = { 6, 8, 10, 11, 12, 14, 15, 17, 18, 20 };
+
+// NPN classes of functions of exactly 3 inputs that are symmetric (5)
+//static int s_NPNe3s[10] = { 6, 10, 14, 15, 18 };
+
+// NPN classes of functions of exactly 3 inputs (4)
+//static int s_NPNe3p[10] = { 8, 11, 12, 20 };
+
+static Cut_CMan_t * Cut_CManStart();
+static void Cut_CManStop( Cut_CMan_t * p );
+static void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type );
+static void Cut_CellCanonicize( Cut_CMan_t * p, Cut_Cell_t * pCell );
+static int  Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell );
+static void Cut_CellSuppMin( Cut_Cell_t * pCell );
+static void Cut_CellCrossBar( Cut_Cell_t * pCell );
+
+
+static Cut_CMan_t * s_pCMan = NULL;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Start the precomputation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_CellLoad()
+{
+    FILE * pFile;
+    char * pFileName = "cells22_daomap_iwls.txt";
+    char pString[1000];
+    Cut_CMan_t * p;
+    Cut_Cell_t * pCell;
+    int Length; //, i;
+    pFile = fopen( pFileName, "r" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\".\n", pFileName );
+        return;
+    }
+   // start the manager
+    p = Cut_CManStart();
+    // load truth tables
+    while ( fgets(pString, 1000, pFile) )
+    {
+        Length = strlen(pString);
+        pString[Length--] = 0;
+        if ( Length == 0 )
+            continue;
+        // derive the cell
+        pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+        memset( pCell, 0, sizeof(Cut_Cell_t) );
+        pCell->nVars = Abc_Base2Log(Length*4);
+        pCell->nUsed = 1;
+//        Extra_TruthCopy( pCell->uTruth, pTruth, nVars );
+        Extra_ReadHexadecimal( pCell->uTruth, pString, pCell->nVars );
+        Cut_CellSuppMin( pCell );
+/*
+        // set the elementary permutation
+        for ( i = 0; i < (int)pCell->nVars; i++ )
+            pCell->CanonPerm[i] = i;
+        // canonicize
+        pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store );
+*/
+        // add to the table
+        p->nTotal++;
+
+//        Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars ); printf( "\n" );
+//        if ( p->nTotal == 500 )
+//            break;
+
+        if ( !Cut_CellTableLookup( p, pCell ) ) // new cell
+            p->nGood++;
+    }
+    printf( "Read %d cells from file \"%s\". Added %d cells to the table.\n", p->nTotal, pFileName, p->nGood );
+    fclose( pFile );
+//    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Precomputes truth tables for the 2x2 macro cell.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_CellPrecompute()
+{
+    Cut_CMan_t * p;
+    Cut_Cell_t * pCell, * pTemp;
+    int i1, i2, i3, i, j, k, c;
+    abctime clk = Abc_Clock(); //, clk2 = Abc_Clock();
+
+    p = Cut_CManStart();
+
+    // precompute truth tables
+    for ( i = 0; i < 22; i++ )
+        Cut_CellTruthElem( p->uInputs[0], p->uInputs[1], p->uInputs[2], p->uTemp1[i], 9, i );
+    for ( i = 0; i < 22; i++ )
+        Cut_CellTruthElem( p->uInputs[3], p->uInputs[4], p->uInputs[5], p->uTemp2[i], 9, i );
+    for ( i = 0; i < 22; i++ )
+        Cut_CellTruthElem( p->uInputs[6], p->uInputs[7], p->uInputs[8], p->uTemp3[i], 9, i );
+/*
+        if ( k == 8 && ((i1 == 6 && i2 == 14 && i3 == 20) || (i1 == 20 && i2 == 6 && i3 == 14)) )
+        {
+            Extra_PrintBinary( stdout, &pCell->CanonPhase, pCell->nVars+1 ); printf( " : " );
+            for ( i = 0; i < pCell->nVars; i++ )
+                printf( "%d=%d/%d  ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] );
+            Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars );
+            printf( "\n" );
+        }
+*/
+/*
+    // go through symmetric roots
+    for ( k = 0; k < 5; k++ )
+    for ( i1 =  0; i1 < 22; i1++ )
+    for ( i2 = i1; i2 < 22; i2++ )
+    for ( i3 = i2; i3 < 22; i3++ )
+    {
+        // derive the cell
+        pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+        memset( pCell, 0, sizeof(Cut_Cell_t) );
+        pCell->nVars  = 9;
+        pCell->Box[0] = s_NPNe3s[k];
+        pCell->Box[1] = i1;
+        pCell->Box[2] = i2;
+        pCell->Box[3] = i3;
+        // fill in the truth table
+        Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3s[k] );
+        // canonicize
+        Cut_CellCanonicize( pCell );
+
+        // add to the table
+        p->nTotal++;
+        if ( Cut_CellTableLookup( p, pCell ) ) // already exists
+            Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
+        else
+            p->nGood++;
+    }
+
+    // go through partially symmetric roots
+    for ( k = 0; k < 4; k++ )
+    for ( i1 = 0;  i1 < 22; i1++ )
+    for ( i2 = 0;  i2 < 22; i2++ )
+    for ( i3 = i2; i3 < 22; i3++ )
+    {
+        // derive the cell
+        pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+        memset( pCell, 0, sizeof(Cut_Cell_t) );
+        pCell->nVars  = 9;
+        pCell->Box[0] = s_NPNe3p[k];
+        pCell->Box[1] = i1;
+        pCell->Box[2] = i2;
+        pCell->Box[3] = i3;
+        // fill in the truth table
+        Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3p[k] );
+        // canonicize
+        Cut_CellCanonicize( pCell );
+
+        // add to the table
+        p->nTotal++;
+        if ( Cut_CellTableLookup( p, pCell ) ) // already exists
+            Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
+        else
+            p->nGood++;
+    }
+
+    // go through non-symmetric functions
+    for ( i1 = 0; i1 < 22; i1++ )
+    for ( i2 = 0; i2 < 22; i2++ )
+    for ( i3 = 0; i3 < 22; i3++ )
+    {
+        // derive the cell
+        pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+        memset( pCell, 0, sizeof(Cut_Cell_t) );
+        pCell->nVars  = 9;
+        pCell->Box[0] = 17;
+        pCell->Box[1] = i1;
+        pCell->Box[2] = i2;
+        pCell->Box[3] = i3;
+        // fill in the truth table
+        Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, 17 );
+        // canonicize
+        Cut_CellCanonicize( pCell );
+
+        // add to the table
+        p->nTotal++;
+        if ( Cut_CellTableLookup( p, pCell ) ) // already exists
+            Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
+        else
+            p->nGood++;
+    }
+*/
+
+    // go through non-symmetric functions
+    for ( k = 0; k < 10; k++ )
+    for ( i1 = 0; i1 < 22; i1++ )
+    for ( i2 = 0; i2 < 22; i2++ )
+    for ( i3 = 0; i3 < 22; i3++ )
+    {
+        // derive the cell
+        pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+        memset( pCell, 0, sizeof(Cut_Cell_t) );
+        pCell->nVars  = 9;
+        pCell->Box[0] = s_NPNe3[k];
+        pCell->Box[1] = i1;
+        pCell->Box[2] = i2;
+        pCell->Box[3] = i3;
+        // set the elementary permutation
+        for ( i = 0; i < (int)pCell->nVars; i++ )
+            pCell->CanonPerm[i] = i;
+        // fill in the truth table
+        Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3[k] );
+        // minimize the support
+        Cut_CellSuppMin( pCell );
+
+        // canonicize
+        pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store );
+
+        // add to the table
+        p->nTotal++;
+        if ( Cut_CellTableLookup( p, pCell ) ) // already exists
+            Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
+        else
+        {
+            p->nGood++;
+            p->nVarCounts[pCell->nVars]++;
+
+            if ( pCell->nVars )
+            for ( i = 0; i < (int)pCell->nVars-1; i++ )
+            {
+                if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric
+                    continue;
+                // i and i+1 can be symmetric
+                // find the end of this group
+                for ( j = i+1; j < (int)pCell->nVars; j++ )
+                    if ( pCell->Store[2*i] != pCell->Store[2*j] ) 
+                        break;
+
+                if ( pCell->Store[2*i] == pCell->Store[2*i+1] )
+                    p->nSymGroupsE[j-i]++;
+                else
+                    p->nSymGroups[j-i]++;
+                i = j - 1;
+            }
+/*
+            if ( pCell->nVars == 3 )
+            {
+                Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" );
+                for ( i = 0; i < (int)pCell->nVars; i++ )
+                    printf( "%d=%d/%d  ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] );
+                printf( "\n" );
+            }
+*/
+        }
+    }
+
+    printf( "BASIC: Total = %d. Good = %d. Entry = %d. ", (int)p->nTotal, (int)p->nGood, (int)sizeof(Cut_Cell_t) );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    printf( "Cells:  " );
+    for ( i = 0; i <= 9; i++ )
+        printf( "%d=%d ", i, p->nVarCounts[i] );
+    printf( "\nDiffs:  " );
+    for ( i = 0; i <= 9; i++ )
+        printf( "%d=%d ", i, p->nSymGroups[i] );
+    printf( "\nEquals: " );
+    for ( i = 0; i <= 9; i++ )
+        printf( "%d=%d ", i, p->nSymGroupsE[i] );
+    printf( "\n" );
+
+    // continue adding new cells using support
+    for ( k = CUT_CELL_MVAR; k > 3; k-- )
+    {
+        for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar )
+        for ( i1 = 0; i1 < k; i1++ )
+        for ( i2 = i1+1; i2 < k; i2++ )
+        for ( c = 0; c < 3; c++ )
+        {
+            // derive the cell
+            pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+            memset( pCell, 0, sizeof(Cut_Cell_t) );
+            pCell->nVars   = pTemp->nVars;
+            pCell->pParent = pTemp;
+            // set the elementary permutation
+            for ( i = 0; i < (int)pCell->nVars; i++ )
+                pCell->CanonPerm[i] = i;
+            // fill in the truth table
+            Extra_TruthCopy( pCell->uTruth, pTemp->uTruth, pTemp->nVars );
+            // create the cross-bar
+            pCell->CrossBar0 = i1;
+            pCell->CrossBar1 = i2;
+            pCell->CrossBarPhase = c;
+            Cut_CellCrossBar( pCell );
+            // minimize the support
+//clk2 = Abc_Clock();
+            Cut_CellSuppMin( pCell );
+//p->timeSupp += Abc_Clock() - clk2;
+            // canonicize
+//clk2 = Abc_Clock();
+            pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store );
+//p->timeCanon += Abc_Clock() - clk2;
+
+            // add to the table
+//clk2 = Abc_Clock();
+            p->nTotal++;
+            if ( Cut_CellTableLookup( p, pCell ) ) // already exists
+                Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
+            else
+            {
+                p->nGood++;
+                p->nVarCounts[pCell->nVars]++;
+
+                for ( i = 0; i < (int)pCell->nVars-1; i++ )
+                {
+                    if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric
+                        continue;
+                    // i and i+1 can be symmetric
+                    // find the end of this group
+                    for ( j = i+1; j < (int)pCell->nVars; j++ )
+                        if ( pCell->Store[2*i] != pCell->Store[2*j] ) 
+                            break;
+
+                    if ( pCell->Store[2*i] == pCell->Store[2*i+1] )
+                        p->nSymGroupsE[j-i]++;
+                    else
+                        p->nSymGroups[j-i]++;
+                    i = j - 1;
+                }
+/*
+                if ( pCell->nVars == 3 )
+                {
+                    Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" );
+                    for ( i = 0; i < (int)pCell->nVars; i++ )
+                        printf( "%d=%d/%d  ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] );
+                    printf( "\n" );
+                }
+*/
+            }
+//p->timeTable += Abc_Clock() - clk2;
+        }
+
+        printf( "VAR %d: Total = %d. Good = %d. Entry = %d. ", k, p->nTotal, p->nGood, (int)sizeof(Cut_Cell_t) );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+        printf( "Cells:  " );
+        for ( i = 0; i <= 9; i++ )
+            printf( "%d=%d ", i, p->nVarCounts[i] );
+        printf( "\nDiffs:  " );
+        for ( i = 0; i <= 9; i++ )
+            printf( "%d=%d ", i, p->nSymGroups[i] );
+        printf( "\nEquals: " );
+        for ( i = 0; i <= 9; i++ )
+            printf( "%d=%d ", i, p->nSymGroupsE[i] );
+        printf( "\n" );
+    }
+//    printf( "\n" );
+    ABC_PRT( "Supp ", p->timeSupp );
+    ABC_PRT( "Canon", p->timeCanon );
+    ABC_PRT( "Table", p->timeTable );
+//    Cut_CManStop( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check the table.]
+
+  Description [Returns 1 if such a truth table already exists.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell )
+{
+    Cut_Cell_t ** pSlot, * pTemp;
+    unsigned Hash;
+    Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum( pCell->nVars ) );
+    if ( ! st__find_or_add( p->tTable, (char *)(ABC_PTRUINT_T)Hash, (char ***)&pSlot ) )
+        *pSlot = NULL;
+    for ( pTemp = *pSlot; pTemp; pTemp = pTemp->pNext )
+    {
+        if ( pTemp->nVars != pCell->nVars )
+            continue;
+        if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) )
+            return 1;
+    }
+    // the entry is new
+    pCell->pNext = *pSlot;
+    *pSlot = pCell;
+    // add it to the variable support list
+    pCell->pNextVar = p->pSameVar[pCell->nVars];
+    p->pSameVar[pCell->nVars] = pCell;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_CellSuppMin( Cut_Cell_t * pCell )
+{
+    static unsigned uTemp[1<<(CUT_CELL_MVAR-5)];
+    unsigned * pIn, * pOut, * pTemp;
+    int i, k, Counter, Temp;
+
+    // go backward through the support variables and remove redundant
+    for ( k = pCell->nVars - 1; k >= 0; k-- )
+        if ( !Extra_TruthVarInSupport(pCell->uTruth, pCell->nVars, k) )
+        {
+            // shift all the variables above this one
+            Counter = 0;
+            pIn = pCell->uTruth; pOut = uTemp;
+            for ( i = k; i < (int)pCell->nVars - 1; i++ )
+            {
+                Extra_TruthSwapAdjacentVars( pOut, pIn, pCell->nVars, i );
+                pTemp = pIn; pIn = pOut; pOut = pTemp;
+                // swap the support vars
+                Temp = pCell->CanonPerm[i]; 
+                pCell->CanonPerm[i] = pCell->CanonPerm[i+1];
+                pCell->CanonPerm[i+1] = Temp;
+                Counter++;
+            }
+            // return the function back into its place
+            if ( Counter & 1 )
+                Extra_TruthCopy( pOut, pIn, pCell->nVars );
+            // remove one variable
+            pCell->nVars--;
+//            Extra_PrintBinary( stdout, pCell->uTruth, (1<<pCell->nVars) ); printf( "\n" );
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_CellCrossBar( Cut_Cell_t * pCell )
+{
+    static unsigned uTemp0[1<<(CUT_CELL_MVAR-5)];
+    static unsigned uTemp1[1<<(CUT_CELL_MVAR-5)];
+    Extra_TruthCopy( uTemp0, pCell->uTruth, pCell->nVars );
+    Extra_TruthCopy( uTemp1, pCell->uTruth, pCell->nVars );
+    if ( pCell->CanonPhase == 0 )
+    {
+        Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 );
+        Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 );
+        Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 );
+        Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 );
+    }
+    else if ( pCell->CanonPhase == 1 )
+    {
+        Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar0 );
+        Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 );
+        Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar0 );
+        Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 );
+    }
+    else if ( pCell->CanonPhase == 2 )
+    {
+        Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 );
+        Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar1 );
+        Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 );
+        Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar1 );
+    }
+    else assert( 0 );
+    Extra_TruthMux( pCell->uTruth, uTemp0, uTemp1, pCell->nVars, pCell->CrossBar0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type )
+{
+    int nWords = Extra_TruthWordNum( nVars );
+    int i;
+
+    assert( Type < 22 );
+    switch ( Type )
+    {
+    // " 0\n",                         // 00   const 0
+    case 0:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = 0;
+        return;
+    // " 1\n",                         // 01   const 1
+    case 1:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = 0xFFFFFFFF;
+        return;
+    // "1 1\n",                        // 02   a
+    case 2:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = InA[i];
+        return;
+    // "11 1\n",                       // 03   ab
+    case 3:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = InA[i] & InB[i];
+        return;
+    // "11 0\n",                       // 04   (ab)'
+    case 4:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = ~(InA[i] & InB[i]);
+        return;
+    // "10 1\n01 1\n",                 // 05   a<+>b
+    case 5:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = InA[i] ^ InB[i];
+        return;
+    // "111 1\n",                      // 06 + abc
+    case 6:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = InA[i] & InB[i] & InC[i];
+        return;
+    // "111 0\n",                      // 07   (abc)'
+    case 7:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = ~(InA[i] & InB[i] & InC[i]);
+        return;
+    // "11- 1\n1-1 1\n",               // 08 + a(b+c)
+    case 8:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = InA[i] & (InB[i] | InC[i]);
+        return;
+    // "11- 0\n1-1 0\n",               // 09   (a(b+c))'
+    case 9:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = ~(InA[i] & (InB[i] | InC[i]));
+        return;
+    // "111 1\n100 1\n010 1\n001 1\n", // 10 + a<+>b<+>c
+    case 10:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = InA[i] ^ InB[i] ^ InC[i];
+        return;
+    // "10- 0\n1-0 0\n011 0\n",        // 11 + a<+>bc
+    case 11:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = InA[i] ^ (InB[i] & InC[i]);
+        return;
+    // "101 1\n110 1\n",               // 12 + a(b<+>c)
+    case 12:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = InA[i] & (InB[i] ^ InC[i]);
+        return;
+    // "101 0\n110 0\n",               // 13   (a(b<+>c))'
+    case 13:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = ~(InA[i] & (InB[i] ^ InC[i]));
+        return;
+    // "11- 1\n1-1 1\n-11 1\n",        // 14 + ab+bc+ac
+    case 14:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (InA[i] & InC[i]);
+        return;
+    // "111 1\n000 1\n",               // 15 + abc+a'b'c'
+    case 15:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i]);
+        return;
+    // "111 0\n000 0\n",               // 16   (abc+a'b'c')'
+    case 16:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = ~((InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i]));
+        return;
+    // "11- 1\n-11 1\n0-1 1\n",        // 17 + ab+bc+a'c
+    case 17:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (~InA[i] & InC[i]);
+        return;
+    // "011 1\n101 1\n110 1\n",        // 18 + a'bc+ab'c+abc'
+    case 18:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i]);
+        return;
+    // "011 0\n101 0\n110 0\n",        // 19   (a'bc+ab'c+abc')'
+    case 19:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = ~((~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i]));
+        return;
+    // "100 1\n-11 1\n",               // 20 + ab'c'+bc
+    case 20:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = (InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i]);
+        return;
+    // "100 0\n-11 0\n"                // 21   (ab'c'+bc)'
+    case 21:
+        for ( i = 0; i < nWords; i++ )
+            pOut[i] = ~((InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i]));
+        return;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Start the precomputation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cut_CMan_t * Cut_CManStart()
+{
+    Cut_CMan_t * p;
+    int i, k;
+    // start the manager
+    assert( sizeof(unsigned) == 4 );
+    p = ABC_ALLOC( Cut_CMan_t, 1 );
+    memset( p, 0, sizeof(Cut_CMan_t) );
+    // start the table and the memory manager
+    p->tTable = st__init_table( st__ptrcmp, st__ptrhash);;
+    p->pMem = Extra_MmFixedStart( sizeof(Cut_Cell_t) );
+    // set elementary truth tables
+    for ( k = 0; k < CUT_CELL_MVAR; k++ )
+        for ( i = 0; i < (1<<CUT_CELL_MVAR); i++ )
+            if ( i & (1 << k) )
+                p->uInputs[k][i>>5] |= (1 << (i&31));
+    s_pCMan = p;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_CManStop( Cut_CMan_t * p )
+{
+    st__free_table( p->tTable );
+    Extra_MmFixedStop( p->pMem );
+    ABC_FREE( p );
+}
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cut_CellIsRunning()
+{
+    return s_pCMan != NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_CellDumpToFile()
+{
+    FILE * pFile;
+    Cut_CMan_t * p = s_pCMan;
+    Cut_Cell_t * pTemp;
+    char * pFileName = "celllib22.txt";
+    int NumUsed[10][5] = {{0}};
+    int BoxUsed[22][5] = {{0}};
+    int i, k, Counter;
+    abctime clk = Abc_Clock();
+
+    if ( p == NULL )
+    {
+        printf( "Cut_CellDumpToFile: Cell manager is not defined.\n" );
+        return;
+    }
+
+    // count the number of cells used
+    for ( k = CUT_CELL_MVAR; k >= 0; k-- )
+    {
+        for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar )
+        {
+            if ( pTemp->nUsed == 0 )
+                NumUsed[k][0]++;
+            else if ( pTemp->nUsed < 10 )
+                NumUsed[k][1]++;
+            else if ( pTemp->nUsed < 100 )
+                NumUsed[k][2]++;
+            else if ( pTemp->nUsed < 1000 )
+                NumUsed[k][3]++;
+            else 
+                NumUsed[k][4]++;
+
+            for ( i = 0; i < 4; i++ )
+                if ( pTemp->nUsed == 0 )
+                    BoxUsed[ (int)pTemp->Box[i] ][0]++;
+                else if ( pTemp->nUsed < 10 )
+                    BoxUsed[ (int)pTemp->Box[i] ][1]++;
+                else if ( pTemp->nUsed < 100 )
+                    BoxUsed[ (int)pTemp->Box[i] ][2]++;
+                else if ( pTemp->nUsed < 1000 )
+                    BoxUsed[ (int)pTemp->Box[i] ][3]++;
+                else 
+                    BoxUsed[ (int)pTemp->Box[i] ][4]++;
+        }
+    }
+
+    printf( "Functions found = %10d.  Functions not found = %10d.\n", p->nCellFound, p->nCellNotFound );
+    for ( k = 0; k <= CUT_CELL_MVAR; k++ )
+    {
+        printf( "%3d  : ", k );
+        for ( i = 0; i < 5; i++ ) 
+            printf( "%8d ", NumUsed[k][i] );
+        printf( "\n" );
+    }
+    printf( "Box usage:\n" );
+    for ( k = 0; k < 22; k++ )
+    {
+        printf( "%3d  : ", k );
+        for ( i = 0; i < 5; i++ ) 
+            printf( "%8d ", BoxUsed[k][i] );
+        printf( "  %s", s_NP3Names[k] );
+        printf( "\n" );
+    }
+
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        printf( "Cut_CellDumpToFile: Cannout open output file.\n" );
+        return;
+    }
+
+    Counter = 0;
+    for ( k = 0; k <= CUT_CELL_MVAR; k++ )
+    {
+        for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar )
+            if ( pTemp->nUsed > 0 )
+            {
+                Extra_PrintHexadecimal( pFile, pTemp->uTruth, (k <= 5? 5 : k) );
+                fprintf( pFile, "\n" );
+                Counter++;
+            }
+        fprintf( pFile, "\n" );
+    }
+    fclose( pFile );
+
+    printf( "Library composed of %d functions is written into file \"%s\".  ", Counter, pFileName );
+
+    ABC_PRT( "Time", Abc_Clock() - clk );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Looks up if the given function exists in the hash table.]
+
+  Description [If the function exists, returns 1, meaning that it can be
+  implemented using two levels of 3-input LUTs. If the function does not 
+  exist, return 0.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cut_CellTruthLookup( unsigned * pTruth, int nVars )
+{
+    Cut_CMan_t * p = s_pCMan;
+    Cut_Cell_t * pTemp;
+    Cut_Cell_t Cell, * pCell = &Cell;
+    unsigned Hash;
+    int i;
+
+    // cell manager is not defined
+    if ( p == NULL )
+    {
+        printf( "Cut_CellTruthLookup: Cell manager is not defined.\n" );
+        return 0;
+    }
+
+    // canonicize
+    memset( pCell, 0, sizeof(Cut_Cell_t) );
+    pCell->nVars = nVars;
+    Extra_TruthCopy( pCell->uTruth, pTruth, nVars );
+    Cut_CellSuppMin( pCell );
+    // set the elementary permutation
+    for ( i = 0; i < (int)pCell->nVars; i++ )
+        pCell->CanonPerm[i] = i;
+    // canonicize
+    pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store );
+
+
+    // check if the cell exists
+    Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum(pCell->nVars) );
+    if ( st__lookup( p->tTable, (char *)(ABC_PTRUINT_T)Hash, (char **)&pTemp ) )
+    {
+        for ( ; pTemp; pTemp = pTemp->pNext )
+        {
+            if ( pTemp->nVars != pCell->nVars )
+                continue;
+            if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) )
+            {
+                pTemp->nUsed++;
+                p->nCellFound++;
+                return 1;
+            }
+        }
+    }
+    p->nCellNotFound++;
+    return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/cut/cutSeq.c b/abc-build/src/opt/cut/cutSeq.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cut/cutSeq.c
@@ -0,0 +1,232 @@
+/**CFile****************************************************************
+
+  FileName    [cutSeq.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [K-feasible cut computation package.]
+
+  Synopsis    [Sequential cut computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cutSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Shifts all cut leaves of the node by the given number of latches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cut_NodeShiftCutLeaves( Cut_Cut_t * pList, int nLat )
+{
+    Cut_Cut_t * pTemp;
+    int i;
+    // shift the cuts by as many latches
+    Cut_ListForEachCut( pList, pTemp )
+    {
+        pTemp->uSign = 0;
+        for ( i = 0; i < (int)pTemp->nLeaves; i++ )
+        {
+            pTemp->pLeaves[i] += nLat;
+            pTemp->uSign      |= Cut_NodeSign( pTemp->pLeaves[i] );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes sequential cuts for the node from its fanins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_NodeComputeCutsSeq( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int nLat0, int nLat1, int fTriv, int CutSetNum )
+{
+    Cut_List_t Super, * pSuper = &Super;
+    Cut_Cut_t * pListNew;
+    abctime clk;
+    
+    // get the number of cuts at the node
+    p->nNodeCuts = Cut_CutCountList( Cut_NodeReadCutsOld(p, Node) );
+    if ( p->nNodeCuts >= p->pParams->nKeepMax )
+        return;
+
+    // count only the first visit
+    if ( p->nNodeCuts == 0 )
+        p->nNodes++;
+
+    // store the fanin lists
+    p->pStore0[0] = Cut_NodeReadCutsOld( p, Node0 );
+    p->pStore0[1] = Cut_NodeReadCutsNew( p, Node0 );
+    p->pStore1[0] = Cut_NodeReadCutsOld( p, Node1 );
+    p->pStore1[1] = Cut_NodeReadCutsNew( p, Node1 );
+
+    // duplicate the cut lists if fanin nodes are non-standard
+    if ( Node == Node0 || Node == Node1 || Node0 == Node1 )
+    {
+        p->pStore0[0] = Cut_CutDupList( p, p->pStore0[0] );
+        p->pStore0[1] = Cut_CutDupList( p, p->pStore0[1] );
+        p->pStore1[0] = Cut_CutDupList( p, p->pStore1[0] );
+        p->pStore1[1] = Cut_CutDupList( p, p->pStore1[1] );
+    }
+
+    // shift the cuts by as many latches and recompute signatures
+    if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[0], nLat0 );
+    if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[1], nLat0 );
+    if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[0], nLat1 );
+    if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[1], nLat1 );
+
+    // store the original lists for comparison
+    p->pCompareOld = Cut_NodeReadCutsOld( p, Node );
+    p->pCompareNew = Cut_NodeReadCutsNew( p, Node );
+
+    // merge the old and the new
+clk = Abc_Clock();
+    Cut_ListStart( pSuper );
+    Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[0], p->pStore1[1], 0, 0 );
+    Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[1], p->pStore1[0], 0, 0 );
+    Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[1], p->pStore1[1], fTriv, 0 );
+    pListNew = Cut_ListFinish( pSuper );
+p->timeMerge += Abc_Clock() - clk;
+
+    // shift the cuts by as many latches and recompute signatures
+    if ( Node == Node0 || Node == Node1 || Node0 == Node1 )
+    {
+        Cut_CutRecycleList( p, p->pStore0[0] );
+        Cut_CutRecycleList( p, p->pStore0[1] );
+        Cut_CutRecycleList( p, p->pStore1[0] );
+        Cut_CutRecycleList( p, p->pStore1[1] );
+    }
+    else
+    {
+        if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[0], -nLat0 );
+        if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[1], -nLat0 );
+        if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[0], -nLat1 );
+        if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[1], -nLat1 );
+    }
+
+    // set the lists at the node
+    if ( CutSetNum >= 0 )
+    {
+        assert( Cut_NodeReadCutsTemp(p, CutSetNum) == NULL );
+        Cut_NodeWriteCutsTemp( p, CutSetNum, pListNew );
+    }
+    else
+    {
+        assert( Cut_NodeReadCutsNew(p, Node) == NULL );
+        Cut_NodeWriteCutsNew( p, Node, pListNew );
+    }
+
+    // mark the node if we exceeded the number of cuts
+    if ( p->nNodeCuts >= p->pParams->nKeepMax )
+        p->nCutsLimit++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges the new cuts with the old cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_NodeNewMergeWithOld( Cut_Man_t * p, int Node )
+{
+    Cut_Cut_t * pListOld, * pListNew, * pList;
+    // get the new cuts
+    pListNew = Cut_NodeReadCutsNew( p, Node );
+    if ( pListNew == NULL )
+        return;
+    Cut_NodeWriteCutsNew( p, Node, NULL );
+    // get the old cuts
+    pListOld = Cut_NodeReadCutsOld( p, Node );
+    if ( pListOld == NULL )
+    {
+        Cut_NodeWriteCutsOld( p, Node, pListNew );
+        return;
+    }
+    // merge the lists
+    pList = Cut_CutMergeLists( pListOld, pListNew );
+    Cut_NodeWriteCutsOld( p, Node, pList );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the temporary cuts to be the new cuts.]
+
+  Description [Returns 1 if something was transferred.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cut_NodeTempTransferToNew( Cut_Man_t * p, int Node, int CutSetNum )
+{
+    Cut_Cut_t * pList;
+    pList = Cut_NodeReadCutsTemp( p, CutSetNum );
+    Cut_NodeWriteCutsTemp( p, CutSetNum, NULL );
+    Cut_NodeWriteCutsNew( p, Node, pList );
+    return pList != NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the old cuts to be the new cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_NodeOldTransferToNew( Cut_Man_t * p, int Node )
+{
+    Cut_Cut_t * pList;
+    pList = Cut_NodeReadCutsOld( p, Node );
+    Cut_NodeWriteCutsOld( p, Node, NULL );
+    Cut_NodeWriteCutsNew( p, Node, pList );
+//    Cut_CutListVerify( pList );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/cut/cutTruth.c b/abc-build/src/opt/cut/cutTruth.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cut/cutTruth.c
@@ -0,0 +1,232 @@
+/**CFile****************************************************************
+
+  FileName    [cutTruth.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [K-feasible cut computation package.]
+
+  Synopsis    [Incremental truth table computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cutTruth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/* 
+    Truth tables computed in this package are represented as bit-strings
+    stored in the cut data structure. Cuts of any number of inputs have 
+    the truth table with 2^k bits, where k is the max number of cut inputs.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// used in abcCut.c
+int nTotal = 0;
+int nGood  = 0;
+int nEqual = 0;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the stretching phase of the cut w.r.t. the merged cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Cut_TruthPhase( Cut_Cut_t * pCut, Cut_Cut_t * pCut1 )
+{
+    unsigned uPhase = 0;
+    int i, k;
+    for ( i = k = 0; i < (int)pCut->nLeaves; i++ )
+    {
+        if ( k == (int)pCut1->nLeaves )
+            break;
+        if ( pCut->pLeaves[i] < pCut1->pLeaves[k] )
+            continue;
+        assert( pCut->pLeaves[i] == pCut1->pLeaves[k] );
+        uPhase |= (1 << i);
+        k++;
+    }
+    return uPhase;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs truth table computation.]
+
+  Description [This procedure cannot be used while recording oracle
+  because it will overwrite Num0 and Num1.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_TruthNCanonicize( Cut_Cut_t * pCut )
+{
+    unsigned uTruth;
+    unsigned * uCanon2;
+    char * pPhases2;
+    assert( pCut->nVarsMax < 6 );
+
+    // get the direct truth table
+    uTruth = *Cut_CutReadTruth(pCut);
+
+    // compute the direct truth table
+    Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 );
+//    uCanon[0] = uCanon2[0];
+//    uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0];
+//    uPhases[0] = pPhases2[0];
+    pCut->uCanon0 = uCanon2[0];
+    pCut->Num0    = pPhases2[0];
+
+    // get the complemented truth table
+    uTruth = ~*Cut_CutReadTruth(pCut);
+
+    // compute the direct truth table
+    Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 );
+//    uCanon[0] = uCanon2[0];
+//    uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0];
+//    uPhases[0] = pPhases2[0];
+    pCut->uCanon1 = uCanon2[0];
+    pCut->Num1    = pPhases2[0];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs truth table computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_TruthComputeOld( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 )
+{
+    static unsigned uTruth0[8], uTruth1[8];
+    int nTruthWords = Cut_TruthWords( pCut->nVarsMax );
+    unsigned * pTruthRes;
+    int i, uPhase;
+
+    // permute the first table
+    uPhase = Cut_TruthPhase( pCut, pCut0 );
+    Extra_TruthExpand( pCut->nVarsMax, nTruthWords, Cut_CutReadTruth(pCut0), uPhase, uTruth0 );
+    if ( fCompl0 ) 
+    {
+        for ( i = 0; i < nTruthWords; i++ )
+            uTruth0[i] = ~uTruth0[i];
+    }
+
+    // permute the second table
+    uPhase = Cut_TruthPhase( pCut, pCut1 );
+    Extra_TruthExpand( pCut->nVarsMax, nTruthWords, Cut_CutReadTruth(pCut1), uPhase, uTruth1 );
+    if ( fCompl1 ) 
+    {
+        for ( i = 0; i < nTruthWords; i++ )
+            uTruth1[i] = ~uTruth1[i];
+    }
+
+    // write the resulting table
+    pTruthRes = Cut_CutReadTruth(pCut);
+
+    if ( pCut->fCompl )
+    {
+        for ( i = 0; i < nTruthWords; i++ )
+            pTruthRes[i] = ~(uTruth0[i] & uTruth1[i]);
+    }
+    else
+    {
+        for ( i = 0; i < nTruthWords; i++ )
+            pTruthRes[i] = uTruth0[i] & uTruth1[i];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs truth table computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 )
+{
+    // permute the first table
+    if ( fCompl0 ) 
+        Extra_TruthNot( p->puTemp[0], Cut_CutReadTruth(pCut0), pCut->nVarsMax );
+    else
+        Extra_TruthCopy( p->puTemp[0], Cut_CutReadTruth(pCut0), pCut->nVarsMax );
+    Extra_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nLeaves, pCut->nVarsMax, Cut_TruthPhase(pCut, pCut0) );
+    // permute the second table
+    if ( fCompl1 ) 
+        Extra_TruthNot( p->puTemp[1], Cut_CutReadTruth(pCut1), pCut->nVarsMax );
+    else
+        Extra_TruthCopy( p->puTemp[1], Cut_CutReadTruth(pCut1), pCut->nVarsMax );
+    Extra_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nLeaves, pCut->nVarsMax, Cut_TruthPhase(pCut, pCut1) );
+    // produce the resulting table
+    if ( pCut->fCompl )
+        Extra_TruthNand( Cut_CutReadTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nVarsMax );
+    else
+        Extra_TruthAnd( Cut_CutReadTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nVarsMax );
+
+//    Ivy_TruthTestOne( *Cut_CutReadTruth(pCut) );
+
+    // quit if no fancy computation is needed
+    if ( !p->pParams->fFancy )
+        return;
+
+    if ( pCut->nLeaves != 7 )
+        return;
+
+    // count the total number of truth tables computed
+    nTotal++;
+
+    // MAPPING INTO ALTERA 6-2 LOGIC BLOCKS
+    // call this procedure to find the minimum number of common variables in the cofactors
+    // if this number is less or equal than 3, the cut can be implemented using the 6-2 logic block
+    if ( Extra_TruthMinCofSuppOverlap( Cut_CutReadTruth(pCut), pCut->nVarsMax, NULL ) <= 4 )
+        nGood++;
+
+    // MAPPING INTO ACTEL 2x2 CELLS
+    // call this procedure to see if a semi-canonical form can be found in the lookup table 
+    // (if it exists, then a two-level 3-input LUT implementation of the cut exists)
+    // Before this procedure is called, cell manager should be defined by calling
+    // Cut_CellLoad (make sure file "cells22_daomap_iwls.txt" is available in the working dir)
+//    if ( Cut_CellIsRunning() && pCut->nVarsMax <= 9 )
+//        nGood += Cut_CellTruthLookup( Cut_CutReadTruth(pCut), pCut->nVarsMax );
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/cut/module.make b/abc-build/src/opt/cut/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/cut/module.make
@@ -0,0 +1,9 @@
+SRC +=  src/opt/cut/cutApi.c \
+        src/opt/cut/cutCut.c \
+        src/opt/cut/cutMan.c \
+        src/opt/cut/cutMerge.c \
+        src/opt/cut/cutNode.c \
+        src/opt/cut/cutOracle.c \
+        src/opt/cut/cutPre22.c \
+        src/opt/cut/cutSeq.c \
+        src/opt/cut/cutTruth.c 
diff --git a/abc-build/src/opt/dar/dar.h b/abc-build/src/opt/dar/dar.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dar/dar.h
@@ -0,0 +1,116 @@
+/**CFile****************************************************************
+
+  FileName    [dar.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: dar.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__dar__dar_h
+#define ABC__aig__dar__dar_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Dar_RwrPar_t_            Dar_RwrPar_t;
+typedef struct Dar_RefPar_t_            Dar_RefPar_t;
+
+struct Dar_RwrPar_t_  
+{
+    int              nCutsMax;       // the maximum number of cuts to try
+    int              nSubgMax;       // the maximum number of subgraphs to try
+    int              fFanout;        // support fanout representation
+    int              fUpdateLevel;   // update level 
+    int              fUseZeros;      // performs zero-cost replacement
+    int              fPower;         // enables power-aware rewriting
+    int              fRecycle;       // enables cut recycling
+    int              fVerbose;       // enables verbose output
+    int              fVeryVerbose;   // enables very verbose output
+};
+
+struct Dar_RefPar_t_  
+{
+    int              nMffcMin;       // the min MFFC size for which refactoring is used
+    int              nLeafMax;       // the max number of leaves of a cut
+    int              nCutsMax;       // the max number of cuts to consider  
+    int              fExtend;        // extends the cut below MFFC
+    int              fUpdateLevel;   // updates the level after each move
+    int              fUseZeros;      // perform zero-cost replacements
+    int              fVerbose;       // verbosity level
+    int              fVeryVerbose;   // enables very verbose output
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                             ITERATORS                            ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== darLib.c ========================================================*/
+extern void            Dar_LibStart();
+extern void            Dar_LibStop();
+extern void            Dar_LibPrepare( int nSubgraphs );
+extern int             Dar_LibReturnClass( unsigned uTruth );
+/*=== darBalance.c ========================================================*/
+extern Aig_Man_t *     Dar_ManBalance( Aig_Man_t * p, int fUpdateLevel );
+extern Aig_Man_t *     Dar_ManBalanceXor( Aig_Man_t * pAig, int fExor, int fUpdateLevel, int fVerbose );
+extern void            Dar_BalancePrintStats( Aig_Man_t * p );
+/*=== darCore.c ========================================================*/
+extern void            Dar_ManDefaultRwrParams( Dar_RwrPar_t * pPars );
+extern int             Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars );
+extern Aig_MmFixed_t * Dar_ManComputeCuts( Aig_Man_t * pAig, int nCutsMax, int fSkipTtMin, int fVerbose );
+/*=== darRefact.c ========================================================*/
+extern void            Dar_ManDefaultRefParams( Dar_RefPar_t * pPars );
+extern int             Dar_ManRefactor( Aig_Man_t * pAig, Dar_RefPar_t * pPars );
+/*=== darScript.c ========================================================*/
+extern Aig_Man_t *     Dar_ManRewriteDefault( Aig_Man_t * pAig );
+extern Aig_Man_t *     Dar_ManRwsat( Aig_Man_t * pAig, int fBalance, int fVerbose );
+extern Aig_Man_t *     Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose );
+extern Aig_Man_t *     Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose );
+extern Aig_Man_t *     Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/dar/darBalance.c b/abc-build/src/opt/dar/darBalance.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dar/darBalance.c
@@ -0,0 +1,759 @@
+/**CFile****************************************************************
+
+  FileName    [darBalance.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting.]
+
+  Synopsis    [Algebraic AIG balancing.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: darBalance.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "darInt.h"
+#include "misc/tim/tim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+//#define USE_LUTSIZE_BALANCE
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Uniqifies the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar_ObjCompareLits( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 )
+{
+    int Diff = Aig_ObjToLit(*pp1) - Aig_ObjToLit(*pp2);
+    if ( Diff < 0 )
+        return -1;
+    if ( Diff > 0 ) 
+        return 1;
+    return 0; 
+}
+void Dar_BalanceUniqify( Aig_Obj_t * pObj, Vec_Ptr_t * vNodes, int fExor )
+{
+    Aig_Obj_t * pTemp, * pTempNext;
+    int i, k;
+    // sort the nodes by their literal
+    Vec_PtrSort( vNodes, (int (*)())Dar_ObjCompareLits );
+    // remove duplicates
+    k = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pTemp, i )
+    {
+        if ( i + 1 == Vec_PtrSize(vNodes) )
+        {
+            Vec_PtrWriteEntry( vNodes, k++, pTemp );
+            break;
+        }
+        pTempNext = (Aig_Obj_t *)Vec_PtrEntry( vNodes, i+1 );
+        if ( !fExor && pTemp == Aig_Not(pTempNext) ) // pos_lit & neg_lit = 0
+        {
+            Vec_PtrClear( vNodes );
+            return;
+        }
+        if ( pTemp != pTempNext )  // save if different
+            Vec_PtrWriteEntry( vNodes, k++, pTemp );
+        else if ( fExor ) // in case of XOR, remove identical
+            i++;
+    }
+    Vec_PtrShrink( vNodes, k );
+    // check that there is no duplicates
+    pTemp = (Aig_Obj_t *)Vec_PtrEntry( vNodes, 0 );
+    Vec_PtrForEachEntryStart( Aig_Obj_t *, vNodes, pTempNext, i, 1 )
+    {
+        assert( pTemp != pTempNext );
+        pTemp = pTempNext;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the nodes of the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_BalanceCone_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper )
+{
+    if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1 || Vec_PtrSize(vSuper) > 10000) )
+        Vec_PtrPush( vSuper, pObj );
+    else
+    {
+        assert( !Aig_IsComplement(pObj) );
+        assert( Aig_ObjIsNode(pObj) );
+        // go through the branches
+        Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild0(pObj) ), vSuper );
+        Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild1(pObj) ), vSuper );
+    }
+}
+Vec_Ptr_t * Dar_BalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level )
+{
+    Vec_Ptr_t * vNodes;
+    assert( !Aig_IsComplement(pObj) );
+    assert( Aig_ObjIsNode(pObj) );
+    // extend the storage
+    if ( Vec_VecSize( vStore ) <= Level )
+        Vec_VecPush( vStore, Level, 0 );
+    // get the temporary array of nodes
+    vNodes = Vec_VecEntry( vStore, Level );
+    Vec_PtrClear( vNodes );
+    // collect the nodes in the implication supergate
+    Dar_BalanceCone_rec( pObj, pObj, vNodes );
+    // remove duplicates
+    Dar_BalanceUniqify( pObj, vNodes, Aig_ObjIsExor(pObj) );
+    return vNodes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the nodes of the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+int Dar_BalanceCone_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper )
+{
+    int RetValue1, RetValue2, i;
+    // check if the node is visited
+    if ( Aig_Regular(pObj)->fMarkB )
+    {
+        if ( Aig_ObjIsExor(pRoot) )
+        {
+            assert( !Aig_IsComplement(pObj) );
+            // check if the node occurs in the same polarity
+            Vec_PtrRemove( vSuper, pObj );
+            Aig_Regular(pObj)->fMarkB = 0;
+//printf( " Duplicated EXOR input!!! " );
+            return 1;
+        }
+        else
+        {
+            // check if the node occurs in the same polarity
+            for ( i = 0; i < vSuper->nSize; i++ )
+                if ( vSuper->pArray[i] == pObj )
+                    return 1;
+            // check if the node is present in the opposite polarity
+            for ( i = 0; i < vSuper->nSize; i++ )
+                if ( vSuper->pArray[i] == Aig_Not(pObj) )
+                    return -1;
+        }
+        assert( 0 );
+        return 0;
+    }
+    // if the new node is complemented or a PI, another gate begins
+    if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1 || Vec_PtrSize(vSuper) > 10000) )
+    {
+        Vec_PtrPush( vSuper, pObj );
+        Aig_Regular(pObj)->fMarkB = 1;
+        return 0;
+    }
+    assert( !Aig_IsComplement(pObj) );
+    assert( Aig_ObjIsNode(pObj) );
+    // go through the branches
+    RetValue1 = Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild0(pObj) ), vSuper );
+    RetValue2 = Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild1(pObj) ), vSuper );
+    if ( RetValue1 == -1 || RetValue2 == -1 )
+        return -1;
+    // return 1 if at least one branch has a duplicate
+    return RetValue1 || RetValue2;
+}
+Vec_Ptr_t * Dar_BalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level )
+{
+    Vec_Ptr_t * vNodes;
+    int RetValue, i;
+    assert( !Aig_IsComplement(pObj) );
+    // extend the storage
+    if ( Vec_VecSize( vStore ) <= Level )
+        Vec_VecPush( vStore, Level, 0 );
+    // get the temporary array of nodes
+    vNodes = Vec_VecEntry( vStore, Level );
+    Vec_PtrClear( vNodes );
+    // collect the nodes in the implication supergate
+    RetValue = Dar_BalanceCone_rec( pObj, pObj, vNodes );
+    assert( RetValue != 0 || vNodes->nSize > 1 );
+    // unmark the visited nodes
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        Aig_Regular(pObj)->fMarkB = 0;
+    // if we found the node and its complement in the same implication supergate, 
+    // return empty set of nodes (meaning that we should use constant-0 node)
+    if ( RetValue == -1 )
+        vNodes->nSize = 0;
+    return vNodes;
+}
+*/
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the left bound on the next candidate to be paired.]
+
+  Description [The nodes in the array are in the decreasing order of levels. 
+  The last node in the array has the smallest level. By default it would be paired 
+  with the next node on the left. However, it may be possible to pair it with some
+  other node on the left, in such a way that the new node is shared. This procedure
+  finds the index of the left-most node, which can be paired with the last node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar_BalanceFindLeft( Vec_Ptr_t * vSuper )
+{
+    Aig_Obj_t * pObjRight, * pObjLeft;
+    int Current;
+    // if two or less nodes, pair with the first
+    if ( Vec_PtrSize(vSuper) < 3 )
+        return 0;
+    // set the pointer to the one before the last
+    Current = Vec_PtrSize(vSuper) - 2;
+    pObjRight = (Aig_Obj_t *)Vec_PtrEntry( vSuper, Current );
+    // go through the nodes to the left of this one
+    for ( Current--; Current >= 0; Current-- )
+    {
+        // get the next node on the left
+        pObjLeft = (Aig_Obj_t *)Vec_PtrEntry( vSuper, Current );
+        // if the level of this node is different, quit the loop
+        if ( Aig_ObjLevel(Aig_Regular(pObjLeft)) != Aig_ObjLevel(Aig_Regular(pObjRight)) )
+            break;
+    }
+    Current++;    
+    // get the node, for which the equality holds
+    pObjLeft = (Aig_Obj_t *)Vec_PtrEntry( vSuper, Current );
+    assert( Aig_ObjLevel(Aig_Regular(pObjLeft)) == Aig_ObjLevel(Aig_Regular(pObjRight)) );
+    return Current;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Moves closer to the end the node that is best for sharing.]
+
+  Description [If there is no node with sharing, randomly chooses one of 
+  the legal nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_BalancePermute( Aig_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor )
+{
+    Aig_Obj_t * pObj1, * pObj2, * pObj3, * pGhost;
+    int RightBound, i;
+    // get the right bound
+    RightBound = Vec_PtrSize(vSuper) - 2;
+    assert( LeftBound <= RightBound );
+    if ( LeftBound == RightBound )
+        return;
+    // get the two last nodes
+    pObj1 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 );
+    pObj2 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, RightBound     );
+    if ( Aig_Regular(pObj1) == p->pConst1 || Aig_Regular(pObj2) == p->pConst1 || Aig_Regular(pObj1) == Aig_Regular(pObj2) )
+        return;
+    // find the first node that can be shared
+    for ( i = RightBound; i >= LeftBound; i-- )
+    {
+        pObj3 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, i );
+        if ( Aig_Regular(pObj3) == p->pConst1 )
+        {
+            Vec_PtrWriteEntry( vSuper, i,          pObj2 );
+            Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
+            return;
+        }
+        if ( Aig_Regular(pObj1) == Aig_Regular(pObj3) )
+        {
+            if ( pObj3 == pObj2 )
+                return;
+            Vec_PtrWriteEntry( vSuper, i,          pObj2 );
+            Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
+            return;
+        }
+        pGhost = Aig_ObjCreateGhost( p, pObj1, pObj3, fExor? AIG_OBJ_EXOR : AIG_OBJ_AND );
+        if ( Aig_TableLookup( p, pGhost ) )
+        {
+            if ( pObj3 == pObj2 )
+                return;
+            Vec_PtrWriteEntry( vSuper, i,          pObj2 );
+            Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
+            return;
+        }
+    }
+/*
+    // we did not find the node to share, randomize choice
+    {
+        int Choice = Aig_ManRandom(0) % (RightBound - LeftBound + 1);
+        pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice );
+        if ( pObj3 == pObj2 )
+            return;
+        Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 );
+        Vec_PtrWriteEntry( vSuper, RightBound,         pObj3 );
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure used for sorting the nodes in decreasing order of levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_NodeCompareLevelsDecrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 )
+{
+    int Diff = Aig_ObjLevel(Aig_Regular(*pp1)) - Aig_ObjLevel(Aig_Regular(*pp2));
+    if ( Diff > 0 )
+        return -1;
+    if ( Diff < 0 ) 
+        return 1;
+    Diff = Aig_ObjId(Aig_Regular(*pp1)) - Aig_ObjId(Aig_Regular(*pp2));
+    if ( Diff > 0 )
+        return -1;
+    if ( Diff < 0 ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts a new node in the order by levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_BalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Aig_Obj_t * pObj, int fExor )
+{
+    Aig_Obj_t * pObj1, * pObj2;
+    int i;
+    if ( Vec_PtrPushUnique(vStore, pObj) )
+    {
+        if ( fExor )
+            Vec_PtrRemove(vStore, pObj);
+        return;
+    }
+    // find the p of the node
+    for ( i = vStore->nSize-1; i > 0; i-- )
+    {
+        pObj1 = (Aig_Obj_t *)vStore->pArray[i  ];
+        pObj2 = (Aig_Obj_t *)vStore->pArray[i-1];
+        if ( Aig_ObjLevel(Aig_Regular(pObj1)) <= Aig_ObjLevel(Aig_Regular(pObj2)) )
+            break;
+        vStore->pArray[i  ] = pObj2;
+        vStore->pArray[i-1] = pObj1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Builds implication supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Dar_BalanceBuildSuper( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel )
+{
+    Aig_Obj_t * pObj1, * pObj2;
+    int LeftBound;
+    assert( vSuper->nSize > 1 );
+    // sort the new nodes by level in the decreasing order
+    Vec_PtrSort( vSuper, (int (*)(void))Aig_NodeCompareLevelsDecrease );
+    // balance the nodes
+    while ( vSuper->nSize > 1 )
+    {
+        // find the left bound on the node to be paired
+        LeftBound = (!fUpdateLevel)? 0 : Dar_BalanceFindLeft( vSuper );
+        // find the node that can be shared (if no such node, randomize choice)
+        Dar_BalancePermute( p, vSuper, LeftBound, Type == AIG_OBJ_EXOR );
+        // pull out the last two nodes
+        pObj1 = (Aig_Obj_t *)Vec_PtrPop(vSuper);
+        pObj2 = (Aig_Obj_t *)Vec_PtrPop(vSuper);
+        Dar_BalancePushUniqueOrderByLevel( vSuper, Aig_Oper(p, pObj1, pObj2, Type), Type == AIG_OBJ_EXOR );
+    }
+    return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns affective support size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_BaseSize( Aig_Man_t * p, Aig_Obj_t * pObj, int nLutSize )
+{
+    int nBaseSize;
+    pObj = Aig_Regular(pObj);
+    if ( Aig_ObjIsConst1(pObj) )
+        return 0;
+    if ( Aig_ObjLevel(pObj) >= nLutSize )
+        return 1;
+    nBaseSize = Aig_SupportSize( p, pObj );
+    if ( nBaseSize >= nLutSize )
+        return 1;
+    return nBaseSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Builds implication supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Dar_BalanceBuildSuperTop( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel, int nLutSize )
+{
+    Vec_Ptr_t * vSubset;
+    Aig_Obj_t * pObj;
+    int i, nBaseSizeAll, nBaseSize;
+    assert( vSuper->nSize > 1 );
+    // sort the new nodes by level in the decreasing order
+    Vec_PtrSort( vSuper, (int (*)(void))Aig_NodeCompareLevelsDecrease );
+    // add one LUT at a time
+    while ( Vec_PtrSize(vSuper) > 1 )
+    {
+        // isolate the group of nodes with nLutSize inputs
+        nBaseSizeAll = 0;
+        vSubset = Vec_PtrAlloc( nLutSize );
+        Vec_PtrForEachEntryReverse( Aig_Obj_t *, vSuper, pObj, i )
+        {
+            nBaseSize = Aig_BaseSize( p, pObj, nLutSize );
+            if ( nBaseSizeAll + nBaseSize > nLutSize && Vec_PtrSize(vSubset) > 1 )
+                break;
+            nBaseSizeAll += nBaseSize;
+            Vec_PtrPush( vSubset, pObj );
+        }
+        // remove them from vSuper
+        Vec_PtrShrink( vSuper, Vec_PtrSize(vSuper) - Vec_PtrSize(vSubset) );
+        // create the new supergate
+        pObj = Dar_BalanceBuildSuper( p, vSubset, Type, fUpdateLevel );
+        Vec_PtrFree( vSubset );
+        // add the new output
+        Dar_BalancePushUniqueOrderByLevel( vSuper, pObj, Type == AIG_OBJ_EXOR );
+    }
+    return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the new node constructed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Dar_Balance_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel )
+{
+    Aig_Obj_t * pObjNew;
+    Vec_Ptr_t * vSuper;
+    int i;
+    assert( !Aig_IsComplement(pObjOld) );
+    assert( !Aig_ObjIsBuf(pObjOld) );
+    // return if the result is known
+    if ( pObjOld->pData )
+        return (Aig_Obj_t *)pObjOld->pData;
+    assert( Aig_ObjIsNode(pObjOld) );
+    // get the implication supergate
+    vSuper = Dar_BalanceCone( pObjOld, vStore, Level );
+    // check if supergate contains two nodes in the opposite polarity
+    if ( vSuper->nSize == 0 )
+        return (Aig_Obj_t *)(pObjOld->pData = Aig_ManConst0(pNew));
+    // for each old node, derive the new well-balanced node
+    for ( i = 0; i < Vec_PtrSize(vSuper); i++ )
+    {
+        pObjNew = Dar_Balance_rec( pNew, Aig_Regular((Aig_Obj_t *)vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel );
+        if ( pObjNew == NULL )
+            return NULL;
+        vSuper->pArray[i] = Aig_NotCond( pObjNew, Aig_IsComplement((Aig_Obj_t *)vSuper->pArray[i]) );
+    }
+    // check for exactly one node
+    if ( vSuper->nSize == 1 )
+        return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0);
+    // build the supergate
+#ifdef USE_LUTSIZE_BALANCE
+    pObjNew = Dar_BalanceBuildSuperTop( pNew, vSuper, Aig_ObjType(pObjOld), fUpdateLevel, 6 );
+#else
+    pObjNew = Dar_BalanceBuildSuper( pNew, vSuper, Aig_ObjType(pObjOld), fUpdateLevel );
+#endif
+    if ( pNew->Time2Quit && !(Aig_Regular(pObjNew)->Id & 255) && Abc_Clock() > pNew->Time2Quit )
+        return NULL;
+    // make sure the balanced node is not assigned
+//    assert( pObjOld->Level >= Aig_Regular(pObjNew)->Level );
+    assert( pObjOld->pData == NULL );
+    return (Aig_Obj_t *)(pObjOld->pData = pObjNew);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs algebraic balancing of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Dar_ManBalance( Aig_Man_t * p, int fUpdateLevel )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pDriver, * pObjNew;
+    Vec_Vec_t * vStore;
+    int i;
+    assert( Aig_ManVerifyTopoOrder(p) );
+    // create the new manager 
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->nAsserts = p->nAsserts;
+    pNew->nConstrs = p->nConstrs;
+    pNew->nBarBufs = p->nBarBufs;
+    pNew->Time2Quit = p->Time2Quit;
+    if ( p->vFlopNums )
+        pNew->vFlopNums = Vec_IntDup( p->vFlopNums );
+    // map the PI nodes
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    vStore = Vec_VecAlloc( 50 );
+    if ( p->pManTime != NULL )
+    {
+        float arrTime;
+        Tim_ManIncrementTravId( (Tim_Man_t *)p->pManTime );
+        Aig_ManSetCioIds( p );
+        Aig_ManForEachObj( p, pObj, i )
+        {
+            if ( Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(pObj) )
+                continue;
+            if ( Aig_ObjIsCi(pObj) )
+            {
+                // copy the PI
+                pObjNew = Aig_ObjCreateCi(pNew); 
+                pObj->pData = pObjNew;
+                // set the arrival time of the new PI
+                arrTime = Tim_ManGetCiArrival( (Tim_Man_t *)p->pManTime, Aig_ObjCioId(pObj) );
+                pObjNew->Level = (int)arrTime;
+            }
+            else if ( Aig_ObjIsCo(pObj) )
+            {
+                // perform balancing
+                pDriver = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
+                pObjNew = Dar_Balance_rec( pNew, Aig_Regular(pDriver), vStore, 0, fUpdateLevel );
+                if ( pObjNew == NULL )
+                {
+                    Vec_VecFree( vStore );
+                    Aig_ManStop( pNew );
+                    return NULL;
+                }
+                pObjNew = Aig_NotCond( pObjNew, Aig_IsComplement(pDriver) );
+                // save arrival time of the output
+                arrTime = (float)Aig_Regular(pObjNew)->Level;
+                Tim_ManSetCoArrival( (Tim_Man_t *)p->pManTime, Aig_ObjCioId(pObj), arrTime );
+                // create PO
+                pObjNew = Aig_ObjCreateCo( pNew, pObjNew );
+            }
+            else
+                assert( 0 );
+        }
+        Aig_ManCleanCioIds( p );
+        pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 );
+    }
+    else
+    {
+        Aig_ManForEachCi( p, pObj, i )
+        {
+            pObjNew = Aig_ObjCreateCi(pNew); 
+            pObjNew->Level = pObj->Level;
+            pObj->pData = pObjNew;
+        }
+        if ( p->nBarBufs == 0 )
+        {
+            Aig_ManForEachCo( p, pObj, i )
+            {
+                pDriver = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
+                pObjNew = Dar_Balance_rec( pNew, Aig_Regular(pDriver), vStore, 0, fUpdateLevel );
+                if ( pObjNew == NULL )
+                {
+                    Vec_VecFree( vStore );
+                    Aig_ManStop( pNew );
+                    return NULL;
+                }
+                pObjNew = Aig_NotCond( pObjNew, Aig_IsComplement(pDriver) );
+                pObjNew = Aig_ObjCreateCo( pNew, pObjNew );
+            }
+        }
+        else
+        {
+            Vec_Ptr_t * vLits = Vec_PtrStart( Aig_ManCoNum(p) );
+            Aig_ManForEachCo( p, pObj, i )
+            {
+                int k = i < p->nBarBufs ? Aig_ManCoNum(p) - p->nBarBufs + i : i - p->nBarBufs;
+                pObj = Aig_ManCo( p, k );
+                pDriver = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
+                pObjNew = Dar_Balance_rec( pNew, Aig_Regular(pDriver), vStore, 0, fUpdateLevel );
+                if ( pObjNew == NULL )
+                {
+                    Vec_VecFree( vStore );
+                    Aig_ManStop( pNew );
+                    return NULL;
+                }
+                pObjNew = Aig_NotCond( pObjNew, Aig_IsComplement(pDriver) );
+                Vec_PtrWriteEntry( vLits, k, pObjNew );
+                if ( i < p->nBarBufs )
+                    Aig_ManCi(pNew, Aig_ManCiNum(p) - p->nBarBufs + i)->Level = Aig_Regular(pObjNew)->Level;
+            }
+            Aig_ManForEachCo( p, pObj, i )
+                Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vLits, i) );
+            Vec_PtrFree(vLits);
+        }
+    }
+    Vec_VecFree( vStore );
+    // remove dangling nodes
+    Aig_ManCleanup( pNew );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // check the resulting AIG
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Dar_ManBalance(): The check has failed.\n" );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reproduces script "compress2".]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Dar_ManBalanceXor( Aig_Man_t * pAig, int fExor, int fUpdateLevel, int fVerbose )
+{
+    Aig_Man_t * pAigXor, * pRes;
+    if ( fExor )
+    {
+        pAigXor = Aig_ManDupExor( pAig );
+        if ( fVerbose )
+            Dar_BalancePrintStats( pAigXor );
+        pRes = Dar_ManBalance( pAigXor, fUpdateLevel );
+        Aig_ManStop( pAigXor );
+    }
+    else
+    {
+        pRes = Dar_ManBalance( pAig, fUpdateLevel );
+    }
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts a new node in the order by levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_BalancePrintStats( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vSuper;
+    Aig_Obj_t * pObj, * pTemp;
+    int i, k;
+    if ( Aig_ManExorNum(p) == 0 )
+    {
+        printf( "There is no EXOR gates.\n" );
+        return;
+    }
+    Aig_ManForEachExor( p, pObj, i )
+    {
+        Aig_ObjFanin0(pObj)->fMarkA = 1;
+        Aig_ObjFanin1(pObj)->fMarkA = 1;
+        assert( !Aig_ObjFaninC0(pObj) );
+        assert( !Aig_ObjFaninC1(pObj) );
+    }
+    vSuper = Vec_PtrAlloc( 1000 );
+    Aig_ManForEachExor( p, pObj, i )
+    {
+        if ( pObj->fMarkA && pObj->nRefs == 1 )
+            continue;
+        Vec_PtrClear( vSuper );
+        Dar_BalanceCone_rec( pObj, pObj, vSuper );
+        Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pTemp, k )
+            pTemp->fMarkB = 0;
+        if ( Vec_PtrSize(vSuper) < 3 )
+            continue;
+        printf( "  %d(", Vec_PtrSize(vSuper) );
+        Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pTemp, k )
+            printf( " %d", pTemp->Level );
+        printf( " )" );
+    }
+    Vec_PtrFree( vSuper );
+    Aig_ManForEachObj( p, pObj, i )
+        pObj->fMarkA = 0;
+    printf( "\n" );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dar/darCore.c b/abc-build/src/opt/dar/darCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dar/darCore.c
@@ -0,0 +1,348 @@
+/**CFile****************************************************************
+
+  FileName    [darCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting.]
+
+  Synopsis    [Core of the rewriting package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: darCore.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "darInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// iterator over the nodes in the topological order
+#define Aig_ManForEachNodeInOrder( p, pObj )                                    \
+    for ( assert(p->pOrderData), p->iPrev = 0, p->iNext = p->pOrderData[1];     \
+          p->iNext && (((pObj) = Aig_ManObj(p, p->iNext)), 1);                  \
+          p->iNext = p->pOrderData[2*p->iPrev+1] )
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the structure with default assignment of parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_ManDefaultRwrParams( Dar_RwrPar_t * pPars )
+{
+    memset( pPars, 0, sizeof(Dar_RwrPar_t) );
+    pPars->nCutsMax     =  8; // 8
+    pPars->nSubgMax     =  5; // 5 is a "magic number"
+    pPars->fFanout      =  1;
+    pPars->fUpdateLevel =  0;
+    pPars->fUseZeros    =  0;
+    pPars->fPower       =  0;
+    pPars->fRecycle     =  1;
+    pPars->fVerbose     =  0;
+    pPars->fVeryVerbose =  0;
+}
+
+#define MAX_VAL 10
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars )
+{
+    extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne );
+    Dar_Man_t * p;
+//    Bar_Progress_t * pProgress;
+    Dar_Cut_t * pCut;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i, k, nNodesOld, nNodeBefore, nNodeAfter, Required;
+    abctime clk = 0, clkStart;
+    int Counter = 0;
+    int nMffcSize;//, nMffcGains[MAX_VAL+1][MAX_VAL+1] = {{0}};
+    // prepare the library
+    Dar_LibPrepare( pPars->nSubgMax ); 
+    // create rewriting manager
+    p = Dar_ManStart( pAig, pPars );
+    if ( pPars->fPower )
+        pAig->vProbs = Saig_ManComputeSwitchProbs( pAig, 48, 16, 1 );
+    // remove dangling nodes
+    Aig_ManCleanup( pAig );
+    // if updating levels is requested, start fanout and timing
+    if ( p->pPars->fFanout )
+        Aig_ManFanoutStart( pAig );
+    if ( p->pPars->fUpdateLevel )
+        Aig_ManStartReverseLevels( pAig, 0 );
+    // set elementary cuts for the PIs
+//    Dar_ManCutsStart( p );
+    // resynthesize each node once
+    clkStart = Abc_Clock();
+    p->nNodesInit = Aig_ManNodeNum(pAig);
+    nNodesOld = Vec_PtrSize( pAig->vObjs );
+
+//    pProgress = Bar_ProgressStart( stdout, nNodesOld );
+    Aig_ManForEachObj( pAig, pObj, i )
+//    pProgress = Bar_ProgressStart( stdout, 100 );
+//    Aig_ManOrderStart( pAig );
+//    Aig_ManForEachNodeInOrder( pAig, pObj )
+    {
+        if ( pAig->Time2Quit && !(i & 256) && Abc_Clock() > pAig->Time2Quit )
+            break;
+//        Bar_ProgressUpdate( pProgress, 100*pAig->nAndPrev/pAig->nAndTotal, NULL );
+//        Bar_ProgressUpdate( pProgress, i, NULL );
+        if ( !Aig_ObjIsNode(pObj) )
+            continue;
+        if ( i > nNodesOld )
+//        if ( p->pPars->fUseZeros && i > nNodesOld )
+            break;
+        if ( pPars->fRecycle && ++Counter % 50000 == 0 && Aig_DagSize(pObj) < Vec_PtrSize(p->vCutNodes)/100 )
+        {
+//            printf( "Counter = %7d.  Node = %7d.  Dag = %5d. Vec = %5d.\n", 
+//                Counter, i, Aig_DagSize(pObj), Vec_PtrSize(p->vCutNodes) );
+//            fflush( stdout );
+            Dar_ManCutsRestart( p, pObj );
+        }
+
+        // consider freeing the cuts
+//        if ( (i & 0xFFF) == 0 && Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) > 100 )
+//            Dar_ManCutsStart( p );
+
+        // compute cuts for the node
+        p->nNodesTried++;
+clk = Abc_Clock();
+        Dar_ObjSetCuts( pObj, NULL );
+        Dar_ObjComputeCuts_rec( p, pObj );
+p->timeCuts += Abc_Clock() - clk;
+
+        // check if there is a trivial cut
+        Dar_ObjForEachCut( pObj, pCut, k )
+            if ( pCut->nLeaves == 0 || (pCut->nLeaves == 1 && pCut->pLeaves[0] != pObj->Id && Aig_ManObj(p->pAig, pCut->pLeaves[0])) )
+                break;
+        if ( k < (int)pObj->nCuts )
+        {
+            assert( pCut->nLeaves < 2 );
+            if ( pCut->nLeaves == 0 ) // replace by constant
+            {
+                assert( pCut->uTruth == 0 || pCut->uTruth == 0xFFFF );
+                pObjNew = Aig_NotCond( Aig_ManConst1(p->pAig), pCut->uTruth==0 );
+            }
+            else
+            {
+                assert( pCut->uTruth == 0xAAAA || pCut->uTruth == 0x5555 );
+                pObjNew = Aig_NotCond( Aig_ManObj(p->pAig, pCut->pLeaves[0]), pCut->uTruth==0x5555 );
+            }
+            // remove the old cuts
+            Dar_ObjSetCuts( pObj, NULL );
+            // replace the node
+            Aig_ObjReplace( pAig, pObj, pObjNew, p->pPars->fUpdateLevel );
+            continue;
+        }
+
+        // evaluate the cuts
+        p->GainBest = -1;
+        nMffcSize   = -1;
+        Required    = pAig->vLevelR? Aig_ObjRequiredLevel(pAig, pObj) : ABC_INFINITY;
+        Dar_ObjForEachCut( pObj, pCut, k )
+        {
+            int nLeavesOld = pCut->nLeaves;
+            if ( pCut->nLeaves == 3 )
+                pCut->pLeaves[pCut->nLeaves++] = 0;
+            Dar_LibEval( p, pObj, pCut, Required, &nMffcSize );
+            pCut->nLeaves = nLeavesOld; 
+        }
+        // check the best gain
+        if ( !(p->GainBest > 0 || (p->GainBest == 0 && p->pPars->fUseZeros)) )
+        {
+//            Aig_ObjOrderAdvance( pAig );
+            continue;
+        }
+//        nMffcGains[p->GainBest < MAX_VAL ? p->GainBest : MAX_VAL][nMffcSize < MAX_VAL ? nMffcSize : MAX_VAL]++;
+        // remove the old cuts
+        Dar_ObjSetCuts( pObj, NULL );
+        // if we end up here, a rewriting step is accepted
+        nNodeBefore = Aig_ManNodeNum( pAig );
+        pObjNew = Dar_LibBuildBest( p ); // pObjNew can be complemented!
+        pObjNew = Aig_NotCond( pObjNew, Aig_ObjPhaseReal(pObjNew) ^ pObj->fPhase );
+        assert( (int)Aig_Regular(pObjNew)->Level <= Required );
+        // replace the node
+        Aig_ObjReplace( pAig, pObj, pObjNew, p->pPars->fUpdateLevel );
+        // compare the gains
+        nNodeAfter = Aig_ManNodeNum( pAig );
+        assert( p->GainBest <= nNodeBefore - nNodeAfter );
+        // count gains of this class
+        p->ClassGains[p->ClassBest] += nNodeBefore - nNodeAfter;
+    }
+//    Aig_ManOrderStop( pAig );
+/*
+    printf( "Distribution of gain (row) by MFFC size (column) %s 0-costs:\n", p->pPars->fUseZeros? "with":"without" );
+    for ( k = 0; k <= MAX_VAL; k++ )
+        printf( "<%4d> ", k );
+    printf( "\n" );
+    for ( i = 0; i <= MAX_VAL; i++ )
+    {
+        for ( k = 0; k <= MAX_VAL; k++ )
+            printf( "%6d ", nMffcGains[i][k] );
+        printf( "\n" );
+    }
+*/
+
+p->timeTotal = Abc_Clock() - clkStart;
+p->timeOther = p->timeTotal - p->timeCuts - p->timeEval;
+
+//    Bar_ProgressStop( pProgress );
+    Dar_ManCutsFree( p );
+    // put the nodes into the DFS order and reassign their IDs
+//    Aig_NtkReassignIds( p );
+    // fix the levels
+//    Aig_ManVerifyLevel( pAig );
+    if ( p->pPars->fFanout )
+        Aig_ManFanoutStop( pAig );
+    if ( p->pPars->fUpdateLevel )
+    {
+//        Aig_ManVerifyReverseLevel( pAig );
+        Aig_ManStopReverseLevels( pAig );
+    }
+    if ( pAig->vProbs )
+    {
+        Vec_IntFree( pAig->vProbs );
+        pAig->vProbs = NULL;
+    }
+    // stop the rewriting manager
+    Dar_ManStop( p );
+    Aig_ManCheckPhase( pAig );
+    // check
+    if ( !Aig_ManCheck( pAig ) )
+    {
+        printf( "Aig_ManRewrite: The network check has failed.\n" );
+        return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the total number of cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar_ManCutCount( Aig_Man_t * pAig, int * pnCutsK )
+{
+    Dar_Cut_t * pCut;
+    Aig_Obj_t * pObj;
+    int i, k, nCuts = 0, nCutsK = 0;
+    Aig_ManForEachNode( pAig, pObj, i )
+        Dar_ObjForEachCut( pObj, pCut, k )
+        {
+            nCuts++;
+            if ( pCut->nLeaves == 4 )
+                nCutsK++;
+        }
+    if ( pnCutsK )
+        *pnCutsK = nCutsK;
+    return nCuts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_MmFixed_t * Dar_ManComputeCuts( Aig_Man_t * pAig, int nCutsMax, int fSkipTtMin, int fVerbose )
+{ 
+    Dar_Man_t * p;
+    Dar_RwrPar_t Pars, * pPars = &Pars; 
+    Aig_Obj_t * pObj;
+    Aig_MmFixed_t * pMemCuts;
+    int i, nNodes;
+    abctime clk = Abc_Clock();
+    // remove dangling nodes
+    if ( (nNodes = Aig_ManCleanup( pAig )) )
+    {
+//        printf( "Removing %d nodes.\n", nNodes );
+    }
+    // create default parameters
+    Dar_ManDefaultRwrParams( pPars );
+    pPars->nCutsMax = nCutsMax;
+    // create rewriting manager
+    p = Dar_ManStart( pAig, pPars );
+    // set elementary cuts for the PIs
+//    Dar_ManCutsStart( p );
+    Aig_MmFixedRestart( p->pMemCuts );
+    Dar_ObjPrepareCuts( p, Aig_ManConst1(p->pAig) );
+    Aig_ManForEachCi( pAig, pObj, i )
+        Dar_ObjPrepareCuts( p, pObj );
+    // compute cuts for each nodes in the topological order
+    Aig_ManForEachNode( pAig, pObj, i )
+        Dar_ObjComputeCuts( p, pObj, fSkipTtMin );
+    // print verbose stats
+    if ( fVerbose )
+    {
+//        Aig_Obj_t * pObj;
+        int nCuts, nCutsK;//, i;
+        nCuts = Dar_ManCutCount( pAig, &nCutsK );
+        printf( "Nodes = %6d. Total cuts = %6d. 4-input cuts = %6d.\n",
+            Aig_ManObjNum(pAig), nCuts, nCutsK );
+        printf( "Cut size = %2d. Truth size = %2d. Total mem = %5.2f MB  ",
+            (int)sizeof(Dar_Cut_t), (int)4, 1.0*Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) );
+        ABC_PRT( "Runtime", Abc_Clock() - clk );
+/*
+        Aig_ManForEachNode( pAig, pObj, i )
+            if ( i % 300 == 0 )
+                Dar_ObjCutPrint( pAig, pObj );
+*/
+    }
+    // free the cuts
+    pMemCuts = p->pMemCuts;
+    p->pMemCuts = NULL;
+//    Dar_ManCutsFree( p );
+    // stop the rewriting manager
+    Dar_ManStop( p );
+    return pMemCuts;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dar/darCut.c b/abc-build/src/opt/dar/darCut.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dar/darCut.c
@@ -0,0 +1,837 @@
+/**CFile****************************************************************
+
+  FileName    [darCut.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting.]
+
+  Synopsis    [Computation of 4-input cuts.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: darCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "darInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Prints one cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_CutPrint( Dar_Cut_t * pCut )
+{
+    unsigned i;
+    printf( "{" );
+    for ( i = 0; i < pCut->nLeaves; i++ )
+        printf( " %d", pCut->pLeaves[i] );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints one cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_ObjCutPrint( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Dar_Cut_t * pCut;
+    int i;
+    printf( "Cuts for node %d:\n", pObj->Id );
+    Dar_ObjForEachCut( pObj, pCut, i )
+        Dar_CutPrint( pCut );
+//    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of 1s in the machine word.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dar_WordCountOnes( unsigned uWord )
+{
+    uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555);
+    uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333);
+    uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F);
+    uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF);
+    return  (uWord & 0x0000FFFF) + (uWord>>16);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the cost of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dar_CutFindValue( Dar_Man_t * p, Dar_Cut_t * pCut )
+{
+    Aig_Obj_t * pLeaf;
+    int i, Value, nOnes;
+    assert( pCut->fUsed );
+    Value = 0;
+    nOnes = 0;
+    Dar_CutForEachLeaf( p->pAig, pCut, pLeaf, i )
+    {
+        if ( pLeaf == NULL )
+            return 0;
+        assert( pLeaf != NULL );
+        Value += pLeaf->nRefs;
+        nOnes += (pLeaf->nRefs == 1);
+    }
+    if ( pCut->nLeaves < 2 )
+        return 1001;
+//    Value = Value * 100 / pCut->nLeaves;
+    if ( Value > 1000 )
+        Value = 1000;
+    if ( nOnes > 3 )
+        Value = 5 - nOnes;
+    return Value;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the next free cut to use.]
+
+  Description [Uses the cut with the smallest value.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Dar_Cut_t * Dar_CutFindFree( Dar_Man_t * p, Aig_Obj_t * pObj )
+{
+    Dar_Cut_t * pCut, * pCutMax;
+    int i;
+    pCutMax = NULL;
+    Dar_ObjForEachCutAll( pObj, pCut, i )
+    {
+        if ( pCut->fUsed == 0 )
+            return pCut;
+        if ( pCut->nLeaves < 3 )
+            continue;
+        if ( pCutMax == NULL || pCutMax->Value > pCut->Value )
+            pCutMax = pCut;
+    }
+    if ( pCutMax == NULL )
+    {
+        Dar_ObjForEachCutAll( pObj, pCut, i )
+        {
+            if ( pCut->nLeaves < 2 )
+                continue;
+            if ( pCutMax == NULL || pCutMax->Value > pCut->Value )
+                pCutMax = pCut;
+        }
+    }
+    if ( pCutMax == NULL )
+    {
+        Dar_ObjForEachCutAll( pObj, pCut, i )
+        {
+            if ( pCutMax == NULL || pCutMax->Value > pCut->Value )
+                pCutMax = pCut;
+        }
+    }
+    assert( pCutMax != NULL );
+    pCutMax->fUsed = 0;
+    return pCutMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pDom is contained in pCut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dar_CutCheckDominance( Dar_Cut_t * pDom, Dar_Cut_t * pCut )
+{
+    int i, k;
+    assert( pDom->fUsed && pCut->fUsed );
+    for ( i = 0; i < (int)pDom->nLeaves; i++ )
+    {
+        for ( k = 0; k < (int)pCut->nLeaves; k++ )
+            if ( pDom->pLeaves[i] == pCut->pLeaves[k] )
+                break;
+        if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut
+            return 0;
+    }
+    // every node in pDom is contained in pCut
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the cut is contained.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dar_CutFilter( Aig_Obj_t * pObj, Dar_Cut_t * pCut )
+{ 
+    Dar_Cut_t * pTemp;
+    int i;
+    assert( pCut->fUsed );
+    // go through the cuts of the node
+    Dar_ObjForEachCut( pObj, pTemp, i )
+    {
+        if ( pTemp == pCut )
+            continue;
+        if ( pTemp->nLeaves > pCut->nLeaves )
+        {
+            // skip the non-contained cuts
+            if ( (pTemp->uSign & pCut->uSign) != pCut->uSign )
+                continue;
+            // check containment seriously
+            if ( Dar_CutCheckDominance( pCut, pTemp ) )
+            {
+                // remove contained cut
+                pTemp->fUsed = 0;
+            }
+         }
+        else
+        {
+            // skip the non-contained cuts
+            if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign )
+                continue;
+            // check containment seriously
+            if ( Dar_CutCheckDominance( pTemp, pCut ) )
+            {
+                // remove the given cut
+                pCut->fUsed = 0;
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dar_CutMergeOrdered( Dar_Cut_t * pC, Dar_Cut_t * pC0, Dar_Cut_t * pC1 )
+{ 
+    int i, k, c;
+    assert( pC0->nLeaves >= pC1->nLeaves );
+
+    // the case of the largest cut sizes
+    if ( pC0->nLeaves == 4 && pC1->nLeaves == 4 )
+    {
+        if ( pC0->uSign != pC1->uSign )
+            return 0;
+        for ( i = 0; i < (int)pC0->nLeaves; i++ )
+            if ( pC0->pLeaves[i] != pC1->pLeaves[i] )
+                return 0;
+        for ( i = 0; i < (int)pC0->nLeaves; i++ )
+            pC->pLeaves[i] = pC0->pLeaves[i];
+        pC->nLeaves = pC0->nLeaves;
+        return 1;
+    }
+
+    // the case when one of the cuts is the largest
+    if ( pC0->nLeaves == 4 )
+    {
+        if ( (pC0->uSign & pC1->uSign) != pC1->uSign )
+            return 0;
+        for ( i = 0; i < (int)pC1->nLeaves; i++ )
+        {
+            for ( k = (int)pC0->nLeaves - 1; k >= 0; k-- )
+                if ( pC0->pLeaves[k] == pC1->pLeaves[i] )
+                    break;
+            if ( k == -1 ) // did not find
+                return 0;
+        }
+        for ( i = 0; i < (int)pC0->nLeaves; i++ )
+            pC->pLeaves[i] = pC0->pLeaves[i];
+        pC->nLeaves = pC0->nLeaves;
+        return 1;
+    }
+
+    // compare two cuts with different numbers
+    i = k = 0;
+    for ( c = 0; c < 4; c++ )
+    {
+        if ( k == (int)pC1->nLeaves )
+        {
+            if ( i == (int)pC0->nLeaves )
+            {
+                pC->nLeaves = c;
+                return 1;
+            }
+            pC->pLeaves[c] = pC0->pLeaves[i++];
+            continue;
+        }
+        if ( i == (int)pC0->nLeaves )
+        {
+            if ( k == (int)pC1->nLeaves )
+            {
+                pC->nLeaves = c;
+                return 1;
+            }
+            pC->pLeaves[c] = pC1->pLeaves[k++];
+            continue;
+        }
+        if ( pC0->pLeaves[i] < pC1->pLeaves[k] )
+        {
+            pC->pLeaves[c] = pC0->pLeaves[i++];
+            continue;
+        }
+        if ( pC0->pLeaves[i] > pC1->pLeaves[k] )
+        {
+            pC->pLeaves[c] = pC1->pLeaves[k++];
+            continue;
+        }
+        pC->pLeaves[c] = pC0->pLeaves[i++]; 
+        k++;
+    }
+    if ( i < (int)pC0->nLeaves || k < (int)pC1->nLeaves )
+        return 0;
+    pC->nLeaves = c;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the object for FPGA mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dar_CutMerge( Dar_Cut_t * pCut, Dar_Cut_t * pCut0, Dar_Cut_t * pCut1 )
+{ 
+    assert( !pCut->fUsed );
+    // merge the nodes
+    if ( pCut0->nLeaves <= pCut1->nLeaves )
+    {
+        if ( !Dar_CutMergeOrdered( pCut, pCut1, pCut0 ) )
+            return 0;
+    }
+    else
+    {
+        if ( !Dar_CutMergeOrdered( pCut, pCut0, pCut1 ) )
+            return 0;
+    }
+    pCut->uSign = pCut0->uSign | pCut1->uSign;
+    pCut->fUsed = 1;
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the stretching phase of the cut w.r.t. the merged cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Dar_CutTruthPhase( Dar_Cut_t * pCut, Dar_Cut_t * pCut1 )
+{
+    unsigned uPhase = 0;
+    int i, k;
+    for ( i = k = 0; i < (int)pCut->nLeaves; i++ )
+    {
+        if ( k == (int)pCut1->nLeaves )
+            break;
+        if ( pCut->pLeaves[i] < pCut1->pLeaves[k] )
+            continue;
+        assert( pCut->pLeaves[i] == pCut1->pLeaves[k] );
+        uPhase |= (1 << i);
+        k++;
+    }
+    return uPhase;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Swaps two advancent variables of the truth table.]
+
+  Description [Swaps variable iVar and iVar+1.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Dar_CutTruthSwapAdjacentVars( unsigned uTruth, int iVar )
+{
+    assert( iVar >= 0 && iVar <= 2 );
+    if ( iVar == 0 )
+        return (uTruth & 0x99999999) | ((uTruth & 0x22222222) << 1) | ((uTruth & 0x44444444) >> 1);
+    if ( iVar == 1 )
+        return (uTruth & 0xC3C3C3C3) | ((uTruth & 0x0C0C0C0C) << 2) | ((uTruth & 0x30303030) >> 2);
+    if ( iVar == 2 )
+        return (uTruth & 0xF00FF00F) | ((uTruth & 0x00F000F0) << 4) | ((uTruth & 0x0F000F00) >> 4);
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Swaps polarity of the variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Dar_CutTruthSwapPolarity( unsigned uTruth, int iVar )
+{
+    assert( iVar >= 0 && iVar <= 3 );
+    if ( iVar == 0 )
+        return ((uTruth & 0xAAAA) >> 1) | ((uTruth & 0x5555) << 1);
+    if ( iVar == 1 )
+        return ((uTruth & 0xCCCC) >> 2) | ((uTruth & 0x3333) << 2);
+    if ( iVar == 2 )
+        return ((uTruth & 0xF0F0) >> 4) | ((uTruth & 0x0F0F) << 4);
+    if ( iVar == 3 )
+        return ((uTruth & 0xFF00) >> 8) | ((uTruth & 0x00FF) << 8);
+    assert( 0 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Expands the truth table according to the phase.]
+
+  Description [The input and output truth tables are in pIn/pOut. The current number
+  of variables is nVars. The total number of variables in nVarsAll. The last argument
+  (Phase) contains shows where the variables should go.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Dar_CutTruthStretch( unsigned uTruth, int nVars, unsigned Phase )
+{
+    int i, k, Var = nVars - 1;
+    for ( i = 3; i >= 0; i-- )
+        if ( Phase & (1 << i) )
+        {
+            for ( k = Var; k < i; k++ )
+                uTruth = Dar_CutTruthSwapAdjacentVars( uTruth, k );
+            Var--;
+        }
+    assert( Var == -1 );
+    return uTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Shrinks the truth table according to the phase.]
+
+  Description [The input and output truth tables are in pIn/pOut. The current number
+  of variables is nVars. The total number of variables in nVarsAll. The last argument
+  (Phase) contains shows what variables should remain.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Dar_CutTruthShrink( unsigned uTruth, int nVars, unsigned Phase )
+{
+    int i, k, Var = 0;
+    for ( i = 0; i < 4; i++ )
+        if ( Phase & (1 << i) )
+        {
+            for ( k = i-1; k >= Var; k-- )
+                uTruth = Dar_CutTruthSwapAdjacentVars( uTruth, k );
+            Var++;
+        }
+    return uTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sort variables by their ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Dar_CutSortVars( unsigned uTruth, int * pVars )
+{
+    int i, Temp, fChange, Counter = 0;
+    // replace -1 by large number
+    for ( i = 0; i < 4; i++ )
+    {
+        if ( pVars[i] == -1 )
+            pVars[i] = 0x3FFFFFFF;
+        else
+            if ( Abc_LitIsCompl(pVars[i]) )
+        {
+            pVars[i] = Abc_LitNot( pVars[i] );
+            uTruth = Dar_CutTruthSwapPolarity( uTruth, i );
+        }
+    }
+
+    // permute variables
+    do {
+        fChange = 0;
+        for ( i = 0; i < 3; i++ )
+        {
+            if ( pVars[i] <= pVars[i+1] )
+                continue;
+            Counter++;
+            fChange = 1;
+
+            Temp = pVars[i];
+            pVars[i] = pVars[i+1];
+            pVars[i+1] = Temp;
+
+            uTruth = Dar_CutTruthSwapAdjacentVars( uTruth, i );
+        }
+    } while ( fChange );
+
+    // replace large number by -1
+    for ( i = 0; i < 4; i++ )
+    {
+        if ( pVars[i] == 0x3FFFFFFF )
+            pVars[i] = -1;
+//        printf( "%d ", pVars[i] );
+    }
+//    printf( "\n" );
+
+    return uTruth;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs truth table computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Dar_CutTruth( Dar_Cut_t * pCut, Dar_Cut_t * pCut0, Dar_Cut_t * pCut1, int fCompl0, int fCompl1 )
+{
+    unsigned uTruth0 = fCompl0 ? ~pCut0->uTruth : pCut0->uTruth;
+    unsigned uTruth1 = fCompl1 ? ~pCut1->uTruth : pCut1->uTruth;
+    uTruth0 = Dar_CutTruthStretch( uTruth0, pCut0->nLeaves, Dar_CutTruthPhase(pCut, pCut0) );
+    uTruth1 = Dar_CutTruthStretch( uTruth1, pCut1->nLeaves, Dar_CutTruthPhase(pCut, pCut1) );
+    return uTruth0 & uTruth1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Minimize support of the cut.]
+
+  Description [Returns 1 if the node's support has changed]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dar_CutSuppMinimize( Dar_Cut_t * pCut )
+{
+    unsigned uMasks[4][2] = {
+        { 0x5555, 0xAAAA },
+        { 0x3333, 0xCCCC },
+        { 0x0F0F, 0xF0F0 },
+        { 0x00FF, 0xFF00 }
+    };
+    unsigned uPhase = 0, uTruth = 0xFFFF & pCut->uTruth;
+    int i, k, nLeaves;
+    assert( pCut->fUsed );
+    // compute the support of the cut's function
+    nLeaves = pCut->nLeaves;
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        if ( (uTruth & uMasks[i][0]) == ((uTruth & uMasks[i][1]) >> (1 << i)) )
+            nLeaves--;
+        else
+            uPhase |= (1 << i);
+    if ( nLeaves == (int)pCut->nLeaves )
+        return 0;
+    // shrink the truth table
+    uTruth = Dar_CutTruthShrink( uTruth, pCut->nLeaves, uPhase );
+    pCut->uTruth = 0xFFFF & uTruth;
+    // update leaves and signature
+    pCut->uSign = 0;
+    for ( i = k = 0; i < (int)pCut->nLeaves; i++ )
+    {
+        if ( !(uPhase & (1 << i)) )
+            continue;    
+        pCut->pLeaves[k++] = pCut->pLeaves[i];
+        pCut->uSign |= Aig_ObjCutSign( pCut->pLeaves[i] );
+    }
+    assert( k == nLeaves );
+    pCut->nLeaves = nLeaves;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_ManCutsFree( Dar_Man_t * p )
+{
+    if ( p->pMemCuts == NULL )
+        return;
+    Aig_MmFixedStop( p->pMemCuts, 0 );
+    p->pMemCuts = NULL;
+//    Aig_ManCleanData( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dar_Cut_t * Dar_ObjPrepareCuts( Dar_Man_t * p, Aig_Obj_t * pObj )
+{
+    Dar_Cut_t * pCutSet, * pCut;
+    int i;
+    assert( Dar_ObjCuts(pObj) == NULL );
+    pObj->nCuts = p->pPars->nCutsMax;
+    // create the cutset of the node
+    pCutSet = (Dar_Cut_t *)Aig_MmFixedEntryFetch( p->pMemCuts );
+    memset( pCutSet, 0, p->pPars->nCutsMax * sizeof(Dar_Cut_t) );
+    Dar_ObjSetCuts( pObj, pCutSet );
+    Dar_ObjForEachCutAll( pObj, pCut, i )
+        pCut->fUsed = 0;
+    Vec_PtrPush( p->vCutNodes, pObj );
+    // add unit cut if needed
+    pCut = pCutSet;
+    pCut->fUsed = 1;
+    if ( Aig_ObjIsConst1(pObj) )
+    {
+        pCut->nLeaves = 0;
+        pCut->uSign = 0;
+        pCut->uTruth = 0xFFFF;
+    }
+    else
+    {
+        pCut->nLeaves = 1;
+        pCut->pLeaves[0] = pObj->Id;
+        pCut->uSign = Aig_ObjCutSign( pObj->Id );
+        pCut->uTruth = 0xAAAA;
+    }
+    pCut->Value = Dar_CutFindValue( p, pCut );
+    if ( p->nCutMemUsed < Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) )
+        p->nCutMemUsed = Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20);
+    return pCutSet;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_ManCutsRestart( Dar_Man_t * p, Aig_Obj_t * pRoot )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Dar_ObjSetCuts( Aig_ManConst1(p->pAig), NULL );
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vCutNodes, pObj, i )
+        if ( !Aig_ObjIsNone(pObj) )
+            Dar_ObjSetCuts( pObj, NULL );
+    Vec_PtrClear( p->vCutNodes );
+    Aig_MmFixedRestart( p->pMemCuts );
+    Dar_ObjPrepareCuts( p, Aig_ManConst1(p->pAig) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dar_Cut_t * Dar_ObjComputeCuts( Dar_Man_t * p, Aig_Obj_t * pObj, int fSkipTtMin )
+{
+    Aig_Obj_t * pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) );
+    Aig_Obj_t * pFanin1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) );
+    Aig_Obj_t * pFaninR0 = Aig_Regular(pFanin0);
+    Aig_Obj_t * pFaninR1 = Aig_Regular(pFanin1);
+    Dar_Cut_t * pCutSet, * pCut0, * pCut1, * pCut;
+    int i, k; 
+
+    assert( !Aig_IsComplement(pObj) );
+    assert( Aig_ObjIsNode(pObj) );
+    assert( Dar_ObjCuts(pObj) == NULL );
+    assert( Dar_ObjCuts(pFaninR0) != NULL );
+    assert( Dar_ObjCuts(pFaninR1) != NULL );
+
+    // set up the first cut
+    pCutSet = Dar_ObjPrepareCuts( p, pObj );
+    // make sure fanins cuts are computed
+    Dar_ObjForEachCut( pFaninR0, pCut0, i )
+    Dar_ObjForEachCut( pFaninR1, pCut1, k )
+    {
+        p->nCutsAll++;
+        // make sure K-feasible cut exists
+        if ( Dar_WordCountOnes(pCut0->uSign | pCut1->uSign) > 4 )
+            continue;
+        // get the next cut of this node
+        pCut = Dar_CutFindFree( p, pObj );
+        // create the new cut
+        if ( !Dar_CutMerge( pCut, pCut0, pCut1 ) )
+        {
+            assert( !pCut->fUsed );
+            continue;
+        }
+        p->nCutsTried++;
+        // check dominance
+        if ( Dar_CutFilter( pObj, pCut ) )
+        {
+            assert( !pCut->fUsed );
+            continue;
+        }
+        // compute truth table
+        pCut->uTruth = 0xFFFF & Dar_CutTruth( pCut, pCut0, pCut1, Aig_IsComplement(pFanin0), Aig_IsComplement(pFanin1) );
+
+        // minimize support of the cut
+        if ( !fSkipTtMin && Dar_CutSuppMinimize( pCut ) )
+        {
+            int RetValue = Dar_CutFilter( pObj, pCut );
+            assert( !RetValue );
+        }
+
+        // assign the value of the cut
+        pCut->Value = Dar_CutFindValue( p, pCut );
+        // if the cut contains removed node, do not use it
+        if ( pCut->Value == 0 )
+        {
+            p->nCutsSkipped++;
+            pCut->fUsed = 0;
+        }
+        else if ( pCut->nLeaves < 2 )
+            return pCutSet;
+    }
+    // count the number of nontrivial cuts cuts
+    Dar_ObjForEachCut( pObj, pCut, i )
+        p->nCutsUsed += pCut->fUsed;
+    // discount trivial cut
+    p->nCutsUsed--;
+    return pCutSet;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dar_Cut_t * Dar_ObjComputeCuts_rec( Dar_Man_t * p, Aig_Obj_t * pObj )
+{
+    if ( Dar_ObjCuts(pObj) )
+        return Dar_ObjCuts(pObj);
+    if ( Aig_ObjIsCi(pObj) )
+        return Dar_ObjPrepareCuts( p, pObj );
+    if ( Aig_ObjIsBuf(pObj) )
+        return Dar_ObjComputeCuts_rec( p, Aig_ObjFanin0(pObj) );
+    Dar_ObjComputeCuts_rec( p, Aig_ObjFanin0(pObj) );
+    Dar_ObjComputeCuts_rec( p, Aig_ObjFanin1(pObj) );
+    return Dar_ObjComputeCuts( p, pObj, 0 );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dar/darData.c b/abc-build/src/opt/dar/darData.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dar/darData.c
@@ -0,0 +1,11294 @@
+/**CFile****************************************************************
+
+  FileName    [dar_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting.]
+
+  Synopsis    [Storage for AIG subgraph data.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: dar_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "darInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+const int s_nDataSize1 = 2*43906;
+unsigned int s_Data1[2*43906] = {
+    4,    6,    5,    7,    9,   11,    5,    6,    4,    7,   15,   17,
+    2,    8,    4,   21,    3,   10,    5,   25,    7,   25,    9,   25,
+    2,   10,    7,   33,    9,   33,    2,   14,    5,   39,    6,   39,
+   17,   39,    3,   16,    7,   47,   33,   47,    2,   16,    4,   53,
+    7,   53,    3,   14,    5,   59,   17,   59,   53,   59,    3,   11,
+    7,   67,    4,   68,    5,   66,    6,   73,   33,   67,    7,   76,
+    5,   77,    9,   77,    9,   66,   33,   85,    3,    9,    4,   88,
+    7,   91,   88,   93,    6,   88,   21,   89,   11,   89,   21,  100,
+   25,  101,   11,   88,    7,  107,   33,  107,    2,   11,    5,  113,
+    7,  112,   30,  113,   25,  113,    5,  120,    7,  121,    9,  120,
+    9,  113,   25,  128,   21,  129,    9,  112,    2,    9,    6,  137,
+    5,  138,   11,  136,    3,   17,    7,  144,  113,  145,   15,  144,
+  113,  151,    3,   15,    6,  155,    4,  156,   17,  154,  113,  161,
+    2,   17,    7,  165,    5,  166,  155,  165,   15,  164,    2,   15,
+    6,  174,   17,  174,    3,   13,  113,  181,  135,  181,  143,  181,
+    2,   12,    9,  189,  181,  189,    9,  192,    2,   13,   85,  197,
+  107,  197,    3,   12,    7,  203,   11,  203,   33,  203,  197,  203,
+    9,  211,    3,   19,    7,  215,   33,  215,  173,  215,  179,  215,
+    2,   18,  215,  225,    2,   19,  151,  229,  161,  229,    3,   18,
+  113,  235,  229,  235,    2,    4,   25,  241,    9,  241,   15,  241,
+   11,  241,    6,  240,    7,  240,   59,  253,    7,  241,    9,  257,
+    6,  241,  253,  261,    3,    5,  251,  265,    6,  266,  241,  269,
+  253,  265,    7,  272,    7,  273,  241,  277,   53,  265,    7,  280,
+  248,  265,    9,  285,   11,  265,  241,  288,    9,  291,   17,  265,
+    9,  265,  257,  265,   25,  299,  251,  298,    7,  264,    3,  305,
+    5,  305,  128,  305,  101,  305,  299,  305,  241,  305,    7,  317,
+  265,  319,    9,  305,  113,  322,  113,  305,    9,  326,    6,  264,
+  241,  331,   17,  331,   53,  331,  253,  331,    7,  265,   59,  341,
+  241,  343,  331,  341,  241,  346,  241,  347,   15,  341,  113,  353,
+  241,  340,    7,  357,  265,  357,   59,  357,  331,  357,  256,  265,
+    7,  367,   59,  367,  331,  367,    6,  265,    5,  375,  242,  375,
+  316,  375,   25,  375,  241,  382,  305,  375,  241,  386,  241,  387,
+   11,  375,  241,  375,  265,  394,    7,  397,   25,  394,  305,  394,
+  251,  395,  257,  375,  241,  374,  260,  265,  241,  265,  251,  413,
+  331,  413,  261,  413,  375,  413,  257,  413,   19,  413,   12,  413,
+   11,  413,    9,  428,    9,  413,   11,  433,   11,  432,   15,  413,
+   11,  412,    9,  441,    7,  413,  241,  445,  265,  445,  375,  445,
+  409,  445,  411,  445,    6,  412,  241,  457,  445,  457,  241,  460,
+    6,  413,  357,  465,  367,  465,    7,  412,  265,  471,   59,  471,
+  331,  471,  465,  471,  241,  479,    2,    6,  353,  483,  322,  483,
+   30,  483,   25,  483,    9,  490,  305,  483,    9,  494,   19,  483,
+  413,  483,   12,  483,  244,  483,  241,  483,    9,  506,    9,  483,
+  305,  510,   25,  510,   11,  510,  241,  510,  257,  510,  247,  483,
+   11,  483,    2,  524,    4,  527,    5,  524,    3,  531,    9,  524,
+  258,  483,  151,  483,  257,  483,    9,  540,  155,  483,   17,  545,
+  235,  483,  181,  483,  161,  483,    4,  482,    2,  555,    5,  482,
+    2,  559,    6,  559,   17,  559,    5,  483,    2,  567,    6,  566,
+  241,  567,  483,  573,    9,  573,    9,  567,    4,  483,    6,  581,
+    3,  582,    3,    7,  289,  587,  510,  587,   11,  591,   11,  590,
+  516,  587,  413,  587,  483,  598,  498,  587,  500,  587,   19,  587,
+  483,  606,  502,  587,   12,  587,  483,  612,  534,  587,  524,  587,
+    9,  618,  288,  587,  305,  623,   25,  623,   11,  587,  265,  629,
+  331,  631,  510,  628,    9,  628,  483,  636,  483,  628,    9,  640,
+  265,  628,  305,  645,   25,  645,  375,  628,  265,  587,   11,  653,
+   33,  655,   11,  652,   25,  659,  305,  659,  295,  587,  241,  587,
+    9,  587,    4,  668,    2,  671,    3,  668,    5,  675,  524,  668,
+  483,  668,   11,  681,   11,  680,   11,  668,  483,  686,  392,  587,
+  165,  587,  375,  587,   17,  695,   11,  695,   11,  694,  113,  587,
+  567,  587,  305,  705,   25,  705,  555,  704,    5,  586,    3,  713,
+    7,  713,  623,  713,  645,  713,  659,  713,  128,  713,  394,  713,
+  101,  713,  299,  713,  705,  713,  510,  713,  483,  713,    9,  736,
+    9,  713,  113,  740,  483,  740,  241,  713,  375,  746,  375,  713,
+  241,  750,  113,  713,    9,  754,    4,  586,    7,  759,  589,  759,
+   33,  759,    5,  587,    7,  767,    2,  768,   47,  767,  483,  773,
+  759,  767,  483,  777,   17,  767,  113,  781,  483,  781,  483,  766,
+   47,  787,  759,  787,   17,  787,  566,  587,   47,  795,  759,  795,
+   17,  795,    4,  587,    3,  803,    6,  805,    7,  802,  494,  803,
+  490,  803,  736,  803,   25,  803,  483,  816,  305,  803,  483,  820,
+  713,  803,  483,  824,  483,  803,  305,  828,   25,  828,  713,  828,
+  555,  829,  483,  802,  580,  587,  483,  587,  413,  842,   19,  842,
+   12,  842,   11,  843,    9,  851,    9,  842,   11,  855,   11,  854,
+   11,  842,    9,  860,    5,  843,  803,  865,    9,  865,  839,  865,
+  841,  865,    4,  842,  483,  875,  865,  875,  483,  878,    4,  843,
+  787,  883,  795,  883,    5,  842,  587,  889,   47,  889,  759,  889,
+   17,  889,  883,  889,  483,  899,    3,    4,  559,  903,   19,  903,
+   12,  903,  842,  903,  587,  903,  483,  912,  165,  912,    9,  903,
+   11,  918,  483,  903,  241,  923,  555,  923,  587,  922,   11,  922,
+   15,  903,   11,  903,    9,  934,  483,  934,  524,  903,  692,  903,
+  767,  903,  375,  945,  165,  903,    7,  949,  587,  948,    6,  902,
+    3,  955,    7,  902,  787,  959,  795,  959,  889,  959,  767,  959,
+  483,  967,   33,  959,    7,  903,  956,  973,   88,  973,    4,  973,
+    3,  973,  955,  980,    9,  980,    3,  972,    4,  972,  955,  973,
+    3,  990,  375,  973,    9,  973,    3,  996,    6,  903,    4, 1001,
+    3, 1001,    3, 1000,    4, 1000,    2,    5,  955, 1011,  914, 1011,
+  918, 1011,   11, 1017,   11, 1016,  912, 1011,  483, 1022,  920, 1011,
+  906, 1011,   19, 1011,  903, 1030,  842, 1011,  903, 1034,  908, 1011,
+  910, 1011,   12, 1011,  903, 1042,  922, 1011,  587, 1046,  928, 1011,
+  936, 1011,  934, 1011,    9, 1054,   15, 1011,   11, 1011,  918, 1060,
+    9, 1060,  903, 1064,  903, 1060,    9, 1068,  483, 1011,  912, 1072,
+  903, 1072,  587, 1076,  587, 1072,  903, 1080,  155, 1072,  587, 1011,
+  922, 1086,  483, 1086,  903, 1090,  903, 1086,  483, 1094,   11, 1087,
+    9, 1099,    9, 1086,   11, 1103,   17, 1011,    9, 1011,  934, 1108,
+  903, 1108,   11, 1113,   11, 1112,   11, 1108,  903, 1118,  587, 1108,
+   11, 1123,  668, 1011,   11, 1127,  544, 1011,  155, 1011,  483, 1132,
+   67, 1011,  375, 1137,    7, 1010,    2, 1141,  959, 1141,   85, 1141,
+  107, 1141,  203, 1141,   67, 1141,    9, 1153,  215, 1141,   47, 1141,
+  759, 1141,    6, 1010,    2, 1163,    5, 1163,   17, 1163,    7, 1011,
+    2, 1171,    5, 1171,    2, 1170,    5, 1170, 1163, 1171,    5, 1180,
+    2, 1181,  483, 1171,  903, 1170,  375, 1189,  972, 1011,  375, 1193,
+    6, 1011,    2, 1197,    5, 1197,    2, 1196,    5, 1196, 1141, 1197,
+    2, 1206,    5, 1207,  903, 1196, 1000, 1011,  903, 1011,   19, 1216,
+  842, 1216,   12, 1216,   11, 1217,    9, 1225,  587, 1216,  483, 1228,
+   11, 1216,    9, 1232,    9, 1216,   11, 1237,   11, 1236,   15, 1216,
+  483, 1216,  587, 1244,    7, 1217,   59, 1249,  331, 1249, 1213, 1249,
+ 1215, 1249,    6, 1216, 1249, 1259,    6, 1217, 1189, 1263, 1193, 1263,
+    7, 1216,  375, 1269, 1263, 1269,    3,    6,  413, 1275, 1216, 1275,
+  241, 1275,    9, 1281,   11, 1283,   11, 1280,    9, 1287,   17, 1275,
+    3, 1290,    5, 1293,    4, 1290,    2, 1297,  903, 1291, 1011, 1275,
+   11, 1275,  241, 1304,    9, 1307,  248, 1275,    9, 1311,  973, 1275,
+    9, 1315,  341, 1275,  803, 1319,    9, 1319,    5, 1274,    3, 1325,
+   17, 1325,  357, 1325,  367, 1325,  471, 1325,  341, 1325,  241, 1337,
+ 1249, 1325,  253, 1325,   53, 1325,    5, 1275,    6, 1347,    2, 1348,
+  918, 1347,  903, 1347,    9, 1354,    9, 1347,  903, 1358,    4, 1275,
+    6, 1362,  265, 1363,    2,    7,  393, 1369,  334, 1369, 1325, 1369,
+ 1363, 1374,   17, 1374,   62, 1369,  331, 1369,   17, 1382,   59, 1369,
+   17, 1386, 1328, 1369, 1304, 1369,    9, 1393,   17, 1369,  331, 1396,
+  241, 1397,   59, 1396, 1325, 1396,   11, 1369, 1275, 1406,    9, 1409,
+  265, 1369,  241, 1412,   11, 1413,   15, 1369,    5, 1418,    3, 1421,
+    2, 1418,    4, 1425, 1011, 1419,  107, 1369,   67, 1369,  803, 1433,
+    9, 1433, 1359, 1369,  203, 1369,  215, 1369,   85, 1369,    5, 1368,
+    2, 1447,    7, 1447,   47, 1447,   85, 1447,  107, 1447,  203, 1447,
+   67, 1447,    9, 1461,  215, 1447,  759, 1447,  959, 1447,    4, 1368,
+    2, 1471,    7, 1471,  265, 1471,    7, 1476,  331, 1471,   59, 1471,
+ 1325, 1471,    5, 1369,    7, 1486,  803, 1487, 1275, 1486,  803, 1493,
+    9, 1493, 1346, 1369,  803, 1499,    9, 1499,    4, 1369,    7, 1505,
+    3, 1506, 1060, 1505,   11, 1505, 1011, 1512, 1011, 1505,    7, 1517,
+   11, 1517,   11, 1516, 1347, 1505, 1275, 1504, 1362, 1369, 1275, 1369,
+  413, 1531,   19, 1531,   12, 1531, 1216, 1531, 1011, 1531,  903, 1540,
+    9, 1531,   11, 1545,   11, 1544,   11, 1531,    9, 1550,  903, 1531,
+ 1011, 1554,   11, 1530,    9, 1559,    5, 1531,  959, 1563,   47, 1563,
+  759, 1563,   17, 1563, 1527, 1563, 1529, 1563,    4, 1530, 1563, 1577,
+    4, 1531, 1493, 1581, 1499, 1581,    5, 1530,  803, 1587,    9, 1587,
+ 1581, 1587,    1,  974,    1,  975,    1,  982,    1,  983,    0,  204,
+    0,  195,    0,  881,    0,  463,    0,  212,    0,  900,    0,  480,
+    0,  194,    0,  880,    0,  462,    0,  213,    0,  901,    0,  481,
+    0,  205,    0,  216,    0,  217,    1,  446,    0,  448,    0,  415,
+    0,  421,    1,   92,    0,   92,    1,   94, 1645, 1647,    1,   93,
+   88, 1650, 1645, 1653,    0,   93,    1,   95, 1657, 1659,    0,  108,
+    0,  109,    1,  360,    0,  368,    0,  358,    0,  414,    1,  447,
+ 1637, 1675,    0,  449, 1635, 1679,    0,  191,    0,  877,    0,  473,
+    1,  473,    0,  459,    1,  459,    0,  891,    0,  207,    0,  458,
+    0,  876,    0,  190,    1,  458,    0,  472,    0,  890,    0,  206,
+    1,  472,    1,  977,    1,  976,    0,  399,    0,  398,    0,  397,
+    7, 1722,    0,  275,    0,  269,  241, 1728,    0,  270,    1,  279,
+    0,  321,    0,  274,    0,  271,    1,  278,    0,  320,    1,  277,
+  241, 1746,    0,  319,  265, 1750,    1,  276,    0,  318,    1,  926,
+    0, 1518,    0,  950,    0, 1519,    0,  951,    1,  998,    1,  999,
+    0,  575,    0, 1478,    0,  282,    0, 1479,    0,  283,    0,  369,
+    0,  359, 1667, 1785,    0,  420,    1,  422,    1,  927,    1, 1421,
+    5, 1794, 1419, 1797,    3, 1794, 1799, 1801,    0,  527,    2, 1804,
+  525, 1807,    4, 1804, 1809, 1811,    1,  671,    4, 1814,  669, 1817,
+    2, 1814, 1819, 1821,    0, 1293,    3, 1824, 1291, 1827,    5, 1824,
+ 1829, 1831,    1, 1425,    2, 1834, 1419, 1837,    4, 1834, 1839, 1841,
+    0,  531,    5, 1844,  525, 1847,    3, 1844, 1849, 1851,    1,  675,
+    3, 1854,  669, 1857,    5, 1854, 1859, 1861,    0, 1297,    4, 1864,
+ 1291, 1867,    2, 1864, 1869, 1871,    1, 1422,    0,  528,    1,  672,
+    0, 1294,    1, 1426,    0,  532,    1,  676,    0, 1298,    1,  123,
+    0,   79,    1,  993,    0,  124,    1,   80,    0, 1210,    0, 1184,
+    0,  125, 1891, 1905,    1,   81, 1893, 1909,    1,  122, 1897, 1913,
+    0,   78, 1899, 1917,    0, 1208,    0, 1182,    1,  992,    1,  361,
+ 1671, 1927,    0,  574,    1,  984,    1,  985,    1,  114,    9, 1937,
+    0,   68,    1,  980,  955, 1942,    9, 1942,    0,  568,    9, 1949,
+    1,  924,    1,  925,    0,  306,  375, 1957,    0,  308, 1413, 1961,
+    0,   26,    1,  306,    1,  308,    1,  714,    0, 1142,    0, 1448,
+    0, 1450,    1, 1450, 1413, 1979,    0, 1474,    0,   54,    0,   56,
+    1, 1472,    0, 1326,    0,   60,    1,   60,    0, 1166,    0,   40,
+    1,  956,  973, 2001,  973, 2000,    0,  556,    1,   22,    0, 1475,
+    1, 1165, 1168, 2012, 1169, 2013, 2015, 2017, 1168, 2013, 1169, 2012,
+ 2021, 2023,    1, 1167,    2, 2027, 1197, 2029, 1997, 2031,    0,   57,
+    1,  957,    0, 1451, 1980, 2039, 1979, 2039, 1413, 2042, 1413, 2039,
+ 1979, 2046,    1, 1449,    5, 2051, 1451, 2053, 1975, 2055,    1, 1451,
+ 1977, 2059, 1413, 2061,    0,  307, 1967, 2065,  375, 2067,    0,  309,
+ 1969, 2071, 1413, 2073,    0,   41,    1,  307, 1958, 2079, 1957, 2079,
+  375, 2082,  375, 2079, 1957, 2086,    1,  309, 1962, 2091, 1961, 2091,
+ 1413, 2094, 1413, 2091, 1961, 2098,    1,   41,    2, 2103,   43, 2105,
+ 1999, 2107,    1, 1143,    5, 2111, 1171, 2113, 1973, 2115,    1,  561,
+  564, 2118,  565, 2119, 2121, 2123,  564, 2119,  565, 2118, 2127, 2129,
+    0,   91,    7, 2132,    0,  569,    1,  981,    9, 2139,  955, 2139,
+    0,   69,    9, 2145,    1,  115,    0,  432,    0,  500,    0, 1245,
+    0, 1237,    0,  501,    0,  433,    1, 1415,    1,  348,    1,  388,
+    1,  826,    1,  126,    1, 1376,    1,  380,    1,  814,    1,  118,
+    1,  302,    1,  710,    1,  102,    1,  402,    1,  834,    1,  130,
+    1,  404,    1,  836,    1,  132,    1,  314,    1,  732,    1,  104,
+    0, 1236,    0, 1244,    1, 1414,    0,  202,    1,  888,    1,  202,
+ 1603, 2215,    0,  106,    1,  106, 1663, 2221,    1,  794,    0,  366,
+    0,   84,    1,  786,    1,   84, 1941, 2233,    1,  390,    1,  994,
+    1,  450,    1,  105,    1,  733,    1,  405,    1,  315,    1,  837,
+    1,  133,    1,  407,    1,  451,    1,  391,    1, 1383,    0,  905,
+    1,  905,    0, 1477,    1, 1477, 1775, 2269,    6, 2269,    7, 2269,
+    6, 2268, 2275, 2277, 1983, 2269,    7, 2268, 2273, 2283,    0,  281,
+    1,  281, 1777, 2289,    6, 2289,    7, 2289,    6, 2288, 2295, 2297,
+ 1987, 2289,    7, 2288, 2293, 2303,    1, 1387,    1,  406, 2227, 2309,
+    1,  995,    0,  461,    1,  461, 1621, 2317, 1699, 2317,    0, 1261,
+    1, 1261,    0,  879,    0,  193,    1,  879, 1619, 2331, 1701, 2331,
+    1,  193, 1617, 2337, 1703, 2337,    0, 1579,    0,  211,    9, 2344,
+    1, 1579,    1,  211, 1623, 2351, 1711, 2351,    0,  479,  241, 2356,
+    0,  899,  483, 2360,    0,  227,    1,  479, 1627, 2367, 1707, 2367,
+    1,  899, 1625, 2373, 1709, 2373,    1,  227,    0, 1273,    0, 1593,
+    0,  239,    1, 1273,    1, 1593,    1,  239,    0,  478, 2367, 2393,
+    1,  478, 2359, 2397, 1615, 2397, 2357, 2397, 1687, 2397,    0, 1272,
+ 2387, 2407,    1, 1272, 2381, 2411,    0,  898, 2373, 2415,    0,  210,
+ 2351, 2419,    1,  898, 2363, 2423, 1613, 2423, 2361, 2423, 1695, 2423,
+    1,  210, 2347, 2433, 1611, 2433, 2345, 2433, 1697, 2433,    0, 1592,
+ 2389, 2443,    0,  192,    9, 2446, 2337, 2449, 2337, 2447,    1, 1592,
+ 2383, 2455,    1,  192, 1605, 2459, 2329, 2459, 1683, 2459,    0,  460,
+  241, 2466, 2317, 2469, 2317, 2467,    0,  878,  483, 2474, 2331, 2477,
+ 2331, 2475,    0,  238, 2391, 2483,    1,  460, 1609, 2487, 2315, 2487,
+ 1691, 2487,    1,  878, 1607, 2495, 2327, 2495, 1685, 2495,    1,  238,
+ 2385, 2503,    0, 1260, 2325, 2507,    0, 1578, 2349, 2511,    0,  226,
+ 2379, 2515,    1, 1260, 2323, 2519,    1, 1578, 2343, 2523,    1,  226,
+ 2365, 2527,    1,  349,    1,  127,    1,  827,    1,  389,    1,  119,
+    1,  815,    1,  381,    1, 1377,    1,  131,    1,  835,    1,  303,
+    1,  403,    1,  711,    1,  103,    1, 1366,    1,  694,    1,  702,
+    9, 2563,    0,  572,    1,  572, 1931, 2569,    0, 1516,    1, 1516,
+ 1761, 2575,    7, 2575,    6, 2574, 2579, 2581,    6, 2575,    7, 2574,
+ 2585, 2587,    0,  944,    0,  948,    1,  578,  587, 2595,    1,  948,
+ 1763, 2599,    7, 2599,    6, 2598, 2603, 2605,    6, 2599,    7, 2598,
+ 2609, 2611,    1, 1186,    1,  996,    3, 2616,    1,  544,    1,  465,
+  471, 2622, 1687, 2625,    1,  197,  203, 2628, 1697, 2631,    1,  883,
+  889, 2634, 1695, 2637,    1,  181,  189, 2640, 1683, 2643,    0,  445,
+ 1693, 2647, 1713, 2647,  265, 2646, 1675, 2653, 2257, 2647,  375, 2647,
+  457, 2647,    1,  445,  264, 2662,  241, 2662, 1679, 2667,  375, 2662,
+  457, 2662, 1691, 2673,    1,  865,  875, 2676, 1685, 2679,    0,  215,
+    7, 2682,    1,  215, 1633, 2687,    1, 1563,    0,  457,  241, 2692,
+ 2317, 2695,    1,  457,  241, 2698,  445, 2699,  445, 2698, 1691, 2705,
+    0,  875,  483, 2708, 2331, 2711,    1,  875,  865, 2714, 1685, 2717,
+    0,  189,    9, 2720, 2337, 2723,    1,  189,  181, 2726, 1683, 2729,
+    0,  203,    7, 2732, 2215, 2735,   11, 2732, 2351, 2739,    0,  471,
+    7, 2742, 1689, 2745,  265, 2742, 2367, 2749,    0,  889,  587, 2752,
+ 2373, 2755,    1,  203, 1629, 2759,  197, 2758, 1697, 2763,    1,  471,
+  265, 2766, 2647, 2769,  465, 2766, 1687, 2773,    1,  889,  883, 2776,
+ 1695, 2779,    0,  107,    7, 2782, 2221, 2785,    1,  107, 1665, 2789,
+    1,  795,    0,  367, 2255, 2795,  375, 2795,    7, 2794,    1,  367,
+  265, 2802, 1783, 2805,    0,   85,    7, 2808, 2233, 2811,    0,  357,
+    7, 2814, 1927, 2817,    1,   85, 2145, 2821,    1,  357,  265, 2824,
+ 1785, 2827,    1,  787,    0,  573,  483, 2832, 2569, 2835,    1,  579,
+    1,  573, 1773, 2841,    1,  997,    1,  545,    1, 1187,  903, 2849,
+    1, 1367,    0,  949,    7, 2854, 2599, 2857,    0,  945,  483, 2861,
+    1,  949, 1767, 2865,    0, 1517,    7, 2868, 2575, 2871,    1, 1517,
+ 1765, 2875,    1,  703,    1,  695,    1,  332,    1,  266, 1731, 2885,
+ 1733, 2885,    1, 1012,    1,   30,  113, 2892,    0,  316,  265, 2896,
+  375, 2897,    0,  272,    7, 2902, 1735, 2903,    1,  736,  803, 2908,
+    1,  316, 1737, 2913,  375, 2912,    1,  272, 1727, 2919,  241, 2918,
+    0, 1374, 2545, 2925,    1, 1374, 1363, 2928,    1, 1382,    0,  904,
+  483, 2934, 2265, 2937,    1,  904,    0, 1476,    7, 2942, 2269, 2945,
+    1, 1476, 1779, 2949, 2011, 2949,    0,  280,    7, 2954, 2289, 2957,
+    1,  280, 1781, 2961, 2035, 2961,    1, 1386,    1,   99,    1,  991,
+    0, 1181,    2, 2972,    0,  347, 2165, 2977,    1,  347,    1,  263,
+  273, 2983,  272, 2982, 2985, 2987,  272, 2983,  273, 2982, 2991, 2993,
+    0,   77,    0, 1207,    5, 2998,    1,   77,    5, 3002, 1917, 3005,
+    9, 3003,    0,  121,    7, 3010, 1913, 3013,    9, 3011,    0,  387,
+ 2259, 3019,    1,  121,    9, 3023,    1,  825,  483, 3027,    1,  387,
+  241, 3030,  241, 3031,    1,   98,    0, 1206,    2, 3038,    0,  386,
+ 2237, 3043, 3033, 3043,    1,  386,  241, 3048,    1,  824,  483, 3052,
+    1,  990,    3, 3056,    0,  120, 3023, 3061,    9, 3063,    0, 1180,
+    5, 3066,    1,  120, 3016, 3071,    5, 3070, 1897, 3075, 3013, 3075,
+ 3011, 3071,    9, 3080,    9, 3070,    9, 3071, 3011, 3086,    0,   76,
+ 3008, 3091,    7, 3090, 1899, 3095, 3005, 3095, 3003, 3091,    9, 3100,
+    9, 3091, 3003, 3104,    0,  346, 2531, 3109,    1,   76, 2997, 3113,
+    9, 3115,    1,  776,    1,  346,  241, 3120, 2977, 3123,    1,   21,
+    2, 3127, 1275, 3129,    9, 3131,    4, 3126, 3133, 3135,    2, 3126,
+  668, 3139, 3135, 3141,  587, 3139,    9, 3144, 3135, 3147,    9, 3139,
+  587, 3150, 3135, 3153,  100, 3126,  129, 3126,  129, 3127,  100, 3127,
+   89, 3127,   11, 3164,   11, 3127,   89, 3169,   89, 3168,   89, 3126,
+    0,   25, 2243, 3177, 2547, 3177, 2539, 3177, 2533, 3177, 3024, 3177,
+    3, 3177, 1369, 3189,   11, 3191,    5, 3176, 3193, 3195,    3, 3176,
+  524, 3199, 3195, 3201,  483, 3199,   11, 3204, 3195, 3207,   11, 3199,
+  483, 3210, 3195, 3213, 3023, 3177,    9, 3216,  101, 3177,  128, 3177,
+  113, 3177,    9, 3224,    9, 3177, 3023, 3228,  113, 3228,    1,   33,
+    5, 3234,    6, 3237, 2997, 3235,    9, 3241, 3177, 3235,   67, 3235,
+    9, 3247,   67, 3234, 3239, 3251,    1,   25,  128, 3254,  101, 3254,
+  113, 3255,    9, 3254,  113, 3262,  113, 3254,    9, 3266,    9, 3267,
+    0,   33, 2759, 3273, 2789, 3273, 2821, 3273,    9, 3273,   67, 3272,
+    9, 3283,    1,  251,  298, 3286,  395, 3286,  395, 3287,  298, 3287,
+  257, 3287,  265, 3297,  265, 3296,  265, 3287,  257, 3302,  265, 3286,
+    0,  305, 2249, 3309, 2553, 3309, 2543, 3309, 2537, 3309, 3034, 3309,
+ 3031, 3309,  241, 3320, 3235, 3309,  299, 3309,  394, 3309,  375, 3309,
+  241, 3330,  241, 3309, 3031, 3334,  375, 3334,  241, 3308,  375, 3341,
+    1,  331, 2647, 3345,  413, 3345,  241, 3344, 1369, 3344,  341, 3344,
+    0,  253,    7, 3356,  265, 3356, 3345, 3357,    1,  555,  923, 3364,
+  923, 3365,  704, 3364,  829, 3364,  829, 3365,  704, 3365,    0,  713,
+ 2245, 3379, 2549, 3379, 2541, 3379, 2535, 3379, 3028, 3379, 3027, 3379,
+  483, 3390, 3235, 3379,  705, 3379,  828, 3379,  803, 3379,  483, 3400,
+  483, 3379, 3027, 3404,  803, 3404,    1,  759,    3, 3410,    6, 3413,
+ 3273, 3411,  767, 3410, 3415, 3419,    0,  559,    0,  251,  413, 3424,
+  413, 3425,  257, 3425,  413, 3431,  412, 3430, 3433, 3435,  412, 3431,
+  413, 3430, 3439, 3441,    1,  305,    3, 3445,  375, 3447,    3, 3444,
+  394, 3444,  299, 3444,  241, 3444,  375, 3456,  375, 3444,  241, 3460,
+    1,  253,  265, 3464,    0,  555,    4, 3469,   15, 3471,  483, 3473,
+    2, 3468, 3475, 3477,    4, 3468,  524, 3481, 3477, 3483,   11, 3481,
+  483, 3486, 3477, 3489,  483, 3481,   11, 3492, 3477, 3495,    1,  713,
+    5, 3499,   17, 3501,  587, 3503,    3, 3498, 3505, 3507,    5, 3498,
+  668, 3511, 3507, 3513,    9, 3511,  587, 3516, 3507, 3519,  587, 3511,
+    9, 3522, 3507, 3525,  828, 3498,  705, 3498,  483, 3498,  803, 3532,
+  803, 3498,  483, 3536,    1,  559,  903, 3540,    1,  955,  980, 3544,
+    3, 3544,  973, 3549,  973, 3548,  973, 3545, 2139, 3555, 1011, 3544,
+  973, 3544,    3, 3560,    0, 1141,    2, 3564,    9, 3565, 3411, 3565,
+    0, 1447,    9, 3573, 3411, 3573,    1, 1471,    4, 3579,   11, 3581,
+ 1369, 3583,    2, 3578, 3585, 3587,    4, 3578, 1418, 3591, 3587, 3593,
+   15, 3591, 1369, 3596, 3587, 3599, 1369, 3591,   15, 3602, 3587, 3605,
+  265, 3578, 2011, 3609,    0, 1325,    5, 3613,    9, 3615, 1275, 3617,
+    3, 3612, 3619, 3621,    5, 3612, 1290, 3625, 3621, 3627,   17, 3625,
+ 1275, 3630, 3621, 3633, 1275, 3625,   17, 3636, 3621, 3639,    1,   53,
+  265, 3642, 2035, 3645,    0,   59,    5, 3648,    1, 1141, 3177, 3653,
+ 3379, 3653, 3309, 3653,    0, 1163,    5, 3660,    1,  959, 3565, 3665,
+ 3273, 3665, 3573, 3665,    1, 1447, 3177, 3673, 3309, 3673, 3379, 3673,
+    0, 1471,    7, 3680, 2269, 3683, 3345, 3681,    1, 1325, 1369, 3688,
+ 3357, 3689, 3681, 3689,    0,   39,    5, 3696,    1,   47, 3565, 3701,
+ 3573, 3701, 3273, 3701,    0,   53,    2, 3709,  587, 3711,   17, 3713,
+    7, 3708, 2289, 3717,    4, 3708, 3715, 3721,    2, 3708, 1290, 3725,
+ 3721, 3727, 1275, 3725,   17, 3730, 3721, 3733,   17, 3725, 1275, 3736,
+ 3721, 3739, 3345, 3709, 3689, 3709,    1,   59,    3, 3747,  483, 3749,
+   15, 3751,    5, 3746, 3753, 3755,    3, 3746, 1418, 3759, 3755, 3761,
+ 1369, 3759,   15, 3764, 3755, 3767,   15, 3759, 1369, 3770, 3755, 3773,
+ 1369, 3746, 3681, 3747, 3357, 3747, 3709, 3747,    1,  330, 1369, 3785,
+  471, 3785,  367, 3785,  357, 3785,  341, 3785,  241, 3795,    0, 1162,
+   17, 3799,    0,  758,  767, 3803,    0,   32, 2215, 3807, 2221, 3807,
+ 2233, 3807, 3249, 3807, 3246, 3807,    9, 3817, 3235, 3807,   67, 3820,
+    9, 3823,   67, 3807, 3235, 3826,    9, 3829,    1,  758, 3807, 3833,
+    1,   32, 3104, 3837, 3284, 3837, 3091, 3837,    9, 3842, 3283, 3837,
+    9, 3846, 3273, 3837,   67, 3851,    9, 3853,    9, 3837, 3283, 3856,
+ 3091, 3856,    0, 1470, 3785, 3863,    0,   24, 2203, 3867, 3259, 3867,
+ 2191, 3867, 3257, 3867, 2179, 3867, 2895, 3867, 2171, 3867, 3265, 3867,
+ 3269, 3867, 3085, 3867, 3071, 3867,    9, 3889, 3267, 3867,    9, 3893,
+ 2893, 3867,  113, 3897, 3263, 3867,  113, 3901, 3255, 3867,  101, 3905,
+  128, 3905,  113, 3905,    9, 3910,    9, 3905,  113, 3914, 3837, 3867,
+  128, 3867,  101, 3867,    9, 3867,  113, 3924,  113, 3867,    9, 3928,
+    1,   24, 3220, 3933, 3222, 3933, 3232, 3933, 3226, 3933, 3224, 3933,
+    9, 3942, 3228, 3933,  113, 3946, 3177, 3933,  101, 3950,  128, 3950,
+  113, 3950,    9, 3956,    9, 3950,  113, 3960,  128, 3933, 3177, 3964,
+  101, 3933, 3177, 3968,    9, 3933, 3224, 3972, 3177, 3972,  113, 3976,
+  113, 3972, 3177, 3980,  113, 3933, 3228, 3984, 3177, 3984,    9, 3988,
+    9, 3984, 3177, 3992,    0,  712, 2201, 3997, 3531, 3997, 2189, 3997,
+ 3529, 3997, 2177, 3997, 2911, 3997, 2169, 3997, 3535, 3997, 3539, 3997,
+ 3055, 3997, 3053, 3997,  483, 4019, 3537, 3997,  483, 4023, 2909, 3997,
+  803, 4027, 3533, 3997,  803, 4031, 3499, 3997,  705, 4035,  828, 4035,
+  803, 4035,  483, 4040,  483, 4035,  803, 4044, 3837, 3997,  828, 3997,
+  705, 3997,  483, 3997,  803, 4054,  803, 3997,  483, 4058,    0,   52,
+ 3785, 4063,    0,  304, 2199, 4067, 3455, 4067, 2187, 4067, 3453, 4067,
+ 2175, 4067, 2917, 4067, 2167, 4067, 3459, 4067, 3463, 4067, 3051, 4067,
+ 3049, 4067,  241, 4089, 3461, 4067,  241, 4093, 2913, 4067,  375, 4097,
+ 3457, 4067,  375, 4101, 3445, 4067,  299, 4105,  394, 4105,  375, 4105,
+  241, 4110,  241, 4105,  375, 4114, 3837, 4067,  394, 4067,  299, 4067,
+  241, 4067,  375, 4124,  375, 4067,  241, 4128,    0,   38,   17, 4133,
+    0,  252,  265, 4137, 3785, 4137,    0,  558,   17, 4143,    1,  712,
+ 3396, 4147, 3398, 4147, 3408, 4147, 3402, 4147, 3400, 4147,  483, 4156,
+ 3404, 4147,  803, 4160, 3379, 4147,  705, 4164,  828, 4164,  803, 4164,
+  483, 4170,  483, 4164,  803, 4174,    9, 4147,  828, 4147, 3379, 4180,
+  705, 4147, 3379, 4184,  483, 4147, 3400, 4188, 3379, 4188,  803, 4192,
+  803, 4188, 3379, 4196,  803, 4147, 3404, 4200, 3379, 4200,  483, 4204,
+  483, 4200, 3379, 4208,    1,  304, 3326, 4213, 3328, 4213, 3338, 4213,
+ 3332, 4213, 3330, 4213,  241, 4222, 3334, 4213,  375, 4226, 3309, 4213,
+  299, 4230,  394, 4230,  375, 4230,  241, 4236,  241, 4230,  375, 4240,
+    9, 4213,  394, 4213, 3309, 4246,  299, 4213, 3309, 4250,  241, 4213,
+ 3330, 4254, 3309, 4254,  375, 4258,  375, 4254, 3309, 4262,  375, 4213,
+ 3334, 4266, 3309, 4266,  241, 4270,  241, 4266, 3309, 4274,    0, 1446,
+ 3833, 4279,    0, 1140, 3833, 4283,    1, 1446, 3867, 4287, 3997, 4287,
+ 4067, 4287,    1,   46, 4279, 4295, 3807, 4295, 4283, 4295,    1, 1140,
+ 3867, 4303, 4067, 4303, 3997, 4303,    1,   58, 1369, 4311, 4063, 4311,
+ 3863, 4311, 4137, 4311,    1,  958, 3807, 4321, 4279, 4321, 4283, 4321,
+    1, 1324, 1369, 4329, 3863, 4329, 4063, 4329, 4137, 4329,    1,  214,
+ 1631, 4339, 2685, 4339,    0,  214,    1, 1562,    1,  444,  449, 4349,
+    7, 4349,  265, 4353, 2647, 4355, 2658, 4349,  251, 4349, 2647, 4349,
+  375, 4362,  375, 4349, 2647, 4366,    0,  444, 2701, 4371, 1689, 4371,
+ 1705, 4371,  447, 4371, 2665, 4371, 2241, 4371, 3785, 4371, 2671, 4371,
+  265, 4371,  331, 4371, 2663, 4371,  375, 4393,  375, 4371,    1,  510,
+  257, 4399,    1, 1058,    0, 1396,    0, 1406,    0,  628,  375, 4409,
+    1,  652,    1,  288,    1,  267, 1741, 4417,    1, 1013,    1, 1375,
+    1,  333, 2903, 4425, 3361, 4425,    0, 1375, 2931, 4431, 2173, 4431,
+    1,  273, 2905, 4437, 1739, 4437,    6, 4436,    7, 4437, 4443, 4445,
+    6, 4437, 3359, 4437,    7, 4436, 4449, 4453,    0,  273, 2883, 4457,
+ 2913, 4457, 3351, 4457, 3457, 4457, 2923, 4457, 1749, 4457, 1743, 4457,
+    1,   31, 3224, 4473, 3177, 4473,  113, 4476,  113, 4473, 3177, 4480,
+    1,  737, 3400, 4485, 3379, 4485,  803, 4488,  803, 4485, 3379, 4492,
+    1,  317, 2903, 4497, 3361, 4497, 2900, 4497,    7, 4497,  265, 4505,
+ 2897, 4507, 1753, 4497, 1745, 4497, 3330, 4497, 2897, 4497,  375, 4516,
+ 3309, 4497,  375, 4520,  375, 4497, 2897, 4524, 3309, 4524,    0,  317,
+    7, 4530, 2913, 4531,  375, 4535,  375, 4531,    1,  507,    1,  245,
+    0, 1397,    1,  913,    0, 1407,    1,  653,   11, 4551,    1,  289,
+    1,  629,  713, 4557,   25, 4557,  305, 4557,    0,  629,  375, 4565,
+    0,  340, 3785, 4569, 4311, 4569, 4329, 4569, 4555, 4569,    0,  766,
+ 1413, 4579,  922, 4579,  903, 4579,  483, 4584,  483, 4579,  903, 4588,
+    0,   66,   75, 4593,    7, 4593, 3113, 4593,    9, 4599, 3251, 4593,
+    9, 4603,  375, 4593,  483, 4593,    9, 4593,    1,  340,  331, 4613,
+    1,  766,  483, 4616, 2591, 4617,  483, 4621,    1,   66,    5, 4624,
+    6, 4627, 3248, 4625, 1941, 4625,    9, 4633,   36, 4625, 3247, 4625,
+    9, 4638,    9, 4624, 1941, 4643, 3807, 4643,   33, 4625,    9, 4648,
+    9, 4625, 3247, 4652,   33, 4652, 3807, 4625,    9, 4659,    0, 1170,
+ 2615, 4663,  903, 4665,    0,  112, 3972, 4669, 3270, 4669, 3086, 4669,
+ 1938, 4669, 1937, 4669,    9, 4678, 2564, 4669, 3071, 4669,    9, 4684,
+ 3267, 4669,    9, 4688, 2563, 4669,    9, 4692,    9, 4669, 3267, 4696,
+ 3933, 4696, 1937, 4696, 3071, 4696, 2563, 4696, 3933, 4669,    9, 4708,
+    1, 1170, 1413, 4713,  922, 4713,  483, 4713,  903, 4718,  903, 4713,
+  483, 4722,    1,  112,    2, 4727,    7, 4729, 3261, 4727,    9, 4733,
+   25, 4727,  903, 4727,  587, 4727,    9, 4727,    0,  972, 3059, 4745,
+ 1925, 4745, 3563, 4745, 3553, 4745, 3549, 4745, 3547, 4745, 2005, 4745,
+ 2001, 4745, 1595, 4745, 1945, 4745, 1599, 4745, 2239, 4745, 1717, 4745,
+ 2619, 4745, 1769, 4745, 1947, 4745, 1933, 4745, 1943, 4745,  955, 4781,
+    9, 4781,    0,  802,  807, 4787,  375, 4787,    7, 4787,  805, 4793,
+  265, 4793,  483, 4787,    0,  144,  483, 4801,    1,  972, 3551, 4805,
+ 2003, 4805,  375, 4805,  955, 4805,    9, 4805, 1011, 4805,    1,  802,
+  713, 4819,  483, 4819,    1,  144,    0,  256, 2309, 4827, 4437, 4827,
+  264, 4826,  299, 4833,  264, 4827,  367, 4837,  265, 4826, 2309, 4841,
+ 4805, 4827, 4613, 4827,  375, 4827,  510, 4827,  483, 4827,    9, 4852,
+    9, 4827,  483, 4856,    0, 1504,    1,  256, 2798, 4863,    7, 4863,
+  265, 4867,  264, 4862,  264, 4863, 2795, 4863,  375, 4874,  265, 4862,
+ 4873, 4879,  305, 4863,  713, 4863,   25, 4863,  375, 4863, 2795, 4888,
+  265, 4863, 4871, 4893,    1,  164,    0,  374,  241, 4899,    0, 1346,
+    9, 4903,    0,  154,    0, 1412, 2853, 4909, 2163, 4909,    0, 1418,
+    1, 1346,    1,  154,  483, 4919,    1, 1412,  241, 4922,    1, 1290,
+ 4915, 4927,    1, 1280,    1,  246,    0,  566, 2596, 4935,  586, 4934,
+  705, 4939,  586, 4935,  795, 4943, 2595, 4935,  587, 4946,  587, 4935,
+ 2595, 4950,    0, 1086,  375, 4955,    0,  922, 1759, 4959, 2265, 4959,
+ 3367, 4959, 4421, 4959, 1953, 4959,    1,  566,    5, 4971,    6, 4973,
+ 1950, 4971, 1949, 4971,    9, 4978,  586, 4970,  586, 4971,  587, 4970,
+ 4985, 4987, 4827, 4971,    9, 4971, 1949, 4992, 4745, 4971, 4569, 4971,
+  587, 4971, 4983, 5001,    1, 1086,    9, 5005,    1,  922, 3369, 5009,
+  555, 5009,  257, 5009,    1,  932,    0,   88, 3171, 5019,   10, 5018,
+  101, 5023,  101, 5019,   10, 5019,  107, 5029,    0,  934,  375, 5033,
+    0, 1108,  587, 5037,    1, 1362,  265, 5041,    1,   88,   93, 5045,
+ 1643, 5047,   93, 5044, 1645, 5051, 1645, 5045, 2135, 5045,  973, 5044,
+ 4745, 5059, 3163, 5045, 3173, 5045, 3167, 5045,    7, 5044,   10, 5044,
+   10, 5045,   11, 5044, 3807, 5075, 5073, 5075,   33, 5045,   21, 5045,
+  973, 5045, 4805, 5085, 3807, 5045, 4279, 5045, 4283, 5045, 4745, 5045,
+   11, 5045, 5071, 5097,    1, 1304,    1, 1108,  973, 5103,  972, 5102,
+ 5105, 5107,  972, 5103,  973, 5102, 5111, 5113,  257, 5103,    0,  260,
+    0,  580,    0,  136,    0,  668,    1,  260, 4139, 5127, 4138, 5127,
+  264, 5126, 5131, 5133,  264, 5127, 4137, 5137,  265, 5126, 4137, 5141,
+ 5137, 5142, 5129, 5141, 5138, 5141, 5137, 5141, 4137, 5150,  265, 5127,
+ 4137, 5154, 5133, 5157, 5133, 5155, 4137, 5161, 4137, 5127,  265, 5165,
+ 5137, 5167,  265, 5164, 5133, 5171,    1,  580,    1,  136, 5019, 5177,
+    1,  524, 5125, 5181,    1,  296, 5019, 5185,    0, 1413, 2559, 5189,
+ 2209, 5189, 4925, 5189,    0, 1419, 5181, 5197,    1,  295,  973, 5201,
+  972, 5201,   49, 5201,   48, 5201,  972, 5200, 5203, 5211,  973, 5200,
+ 5205, 5215,   48, 5200, 5207, 5219,   49, 5200, 5209, 5223,    1, 1413,
+ 1417, 5227,    1, 1291, 5125, 5231, 5197, 5231,    0, 1087,  375, 5237,
+    0,  923, 1793, 5241, 2941, 5241, 5012, 5241, 3543, 5241, 3559, 5241,
+ 2891, 5241, 5017, 5241, 1955, 5241,  555, 5241, 5009, 5258, 5009, 5241,
+  555, 5262,    1, 1087, 5037, 5267,    1,  923,  555, 5270, 4959, 5273,
+  241, 5270, 4959, 5277, 4959, 5271,  555, 5281,    1,  933, 4959, 5285,
+    0,  935,  375, 5289,    0, 1109, 5005, 5293,    1,  935,    0,  669,
+ 4927, 5299,    1,  525, 4915, 5303, 5299, 5303,    1,  669,    1,  297,
+    0,  341,  483, 5313, 3747, 5313, 3689, 5313, 3345, 5313, 4415, 5313,
+    0,  257, 2255, 5325, 4888, 5325, 4881, 5325, 3467, 5325, 2919, 5325,
+ 4871, 5325, 4893, 5336, 4894, 5325,    7, 5324, 4863, 5343, 4872, 5325,
+ 4879, 5347, 4869, 5325, 4893, 5325, 4871, 5352, 5343, 5353,    3, 5325,
+    5, 5358, 4862, 5360, 4863, 5361, 5363, 5365, 5343, 5364, 4862, 5361,
+ 4863, 5360, 5371, 5373, 5344, 5361, 5343, 5361, 4863, 5378,    5, 5325,
+    3, 5382, 4862, 5384, 4863, 5385, 5387, 5389, 5343, 5388, 4862, 5385,
+ 4863, 5384, 5395, 5397, 5344, 5385, 5343, 5385, 4863, 5402,  264, 5325,
+ 4863, 5406, 4879, 5409, 5344, 5407, 5343, 5407, 4863, 5414, 4863, 5407,
+ 4871, 5419, 5343, 5418,    7, 5325,  265, 5425, 4863, 5427,  266, 5325,
+  375, 5325, 4863, 5432,  510, 5325,  483, 5325,    9, 5438,    9, 5325,
+  483, 5442,  251, 5325,  265, 5446,  265, 5447, 4892, 5325,  265, 5325,
+  257, 5454,    1, 5457,    7, 5455, 5459, 5461,    0, 5461, 5457, 5465,
+  251, 5454, 4863, 5454, 4863, 5325,    3, 5472,    5, 5474,    5, 5472,
+    3, 5478,  375, 5472,    7, 5473, 5361, 5485, 5385, 5485, 5477, 5485,
+ 5481, 5485, 5407, 5485,  264, 5472, 4879, 5497, 5485, 5497,  264, 5473,
+ 4893, 5503,  265, 5472,  265, 5324, 4417, 5509,  251, 5509,    1,  341,
+ 5325, 5515,  331, 5514,    1,  257,  445, 5521,  265, 5522,  449, 5521,
+  448, 5521,  414, 5521,  415, 5521,  421, 5521,  420, 5521,  253, 5521,
+  265, 5538,  340, 5521,  341, 5521,  272, 5520,  241, 5546,  273, 5521,
+ 5549, 5551,  272, 5521,  273, 5520,  412, 5521,  251, 5559,  241, 5520,
+  265, 5562, 5551, 5565,  272, 5563, 5557, 5569,  500, 5521,  432, 5521,
+  501, 5521,  413, 5520, 5525, 5579, 5529, 5579, 5533, 5579, 5535, 5579,
+ 5555, 5579, 5541, 5579,  251, 5579, 5559, 5592, 5560, 5579, 5559, 5579,
+  251, 5598, 5577, 5579,  433, 5521, 5579, 5605,  264, 5520, 5543, 5609,
+  367, 5609,  264, 5521,  299, 5615,  412, 5520, 5527, 5619, 5531, 5619,
+ 5537, 5619, 5551, 5619, 5573, 5619, 5575, 5619,  413, 5521,  375, 5632,
+ 5619, 5635,  251, 5632, 5619, 5639, 5619, 5633,  251, 5643,  483, 5632,
+ 5619, 5647,    9, 5632, 5619, 5651,    7, 5521,  265, 5654, 5609, 5657,
+  265, 5655, 5615, 5661, 2227, 5521,  375, 5665, 4841, 5521,  375, 5669,
+  375, 5520, 2227, 5673, 4841, 5673, 4827, 5673,  375, 5521,  413, 5680,
+ 5619, 5683,  413, 5681, 5559, 5687,  483, 5521,  413, 5690, 5619, 5693,
+  413, 5691, 5559, 5697,    9, 5521,  413, 5700, 5619, 5703,  413, 5701,
+ 5559, 5707,  251, 5521,  413, 5710, 5619, 5713,  413, 5711, 5559, 5717,
+  265, 5521,  445, 5720, 5579, 5723,  253, 5720, 5579, 5727,    7, 5720,
+ 5609, 5731, 4827, 5521,    3, 5735,    5, 5736,    5, 5735,    3, 5740,
+  375, 5735,    7, 5734, 5739, 5747, 5743, 5747,  264, 5735, 5747, 5753,
+  265, 5735,  265, 5520, 2647, 5759, 5545, 5759, 1783, 5759,  241, 5758,
+ 5551, 5767,    0, 1171, 4714, 5771, 4716, 5771, 4720, 5771, 4724, 5771,
+ 2850, 5771, 1413, 5771, 4713, 5782,  922, 5771, 4713, 5786, 4718, 5771,
+  903, 5790, 2849, 5771,  903, 5794,  483, 5771, 4722, 5798,  903, 5798,
+ 4713, 5802, 4713, 5798,  903, 5806, 4722, 5771,  483, 5810,  903, 5771,
+ 4718, 5814, 2849, 5814,  483, 5814, 4713, 5820, 4713, 5814,  483, 5824,
+ 4713, 5771, 1413, 5828,  922, 5828,  483, 5828,  903, 5834,  903, 5828,
+  483, 5838,    0,  973, 1895, 5843, 2037, 5843, 1597, 5843, 1601, 5843,
+ 2142, 5843, 2313, 5843, 4810, 5843, 1715, 5843, 1771, 5843, 1935, 5843,
+ 2140, 5843, 2139, 5843,  955, 5866,    9, 5866,  375, 5843, 4805, 5872,
+  483, 5843,    9, 5843, 2139, 5878,  955, 5843, 2139, 5882, 1011, 5843,
+ 4805, 5843,  375, 5888,    1, 1171,    3, 5892, 4663, 5895,  903, 5897,
+  483, 5892, 4663, 5901,  903, 5903, 4663, 5893, 1413, 5907,  922, 5907,
+  483, 5907,  903, 5912,  903, 5907,  483, 5916,    1,  973,  956, 5920,
+ 4745, 5923,   88, 5920, 4745, 5927,    5, 5920, 4745, 5931, 1011, 5933,
+    3, 5920,  955, 5936, 4745, 5939,    9, 5936, 4745, 5943, 4745, 5937,
+  955, 5947,    9, 5947,  375, 5920, 4745, 5953,  955, 5920,    3, 5956,
+ 4745, 5959, 5325, 5921,    9, 5920,    3, 5964, 4745, 5967, 4745, 5921,
+  375, 5971,    0,  767,  903, 5974, 4617, 5977,  483, 5979, 4617, 5975,
+ 1413, 5983,  922, 5983,  903, 5983,  483, 5988,  483, 5983,  903, 5992,
+    0,  567, 4989, 5997, 4983, 5997, 5001, 6000, 5002, 5997, 4984, 5997,
+ 4987, 6007, 5001, 5997, 4983, 6010,    3, 5997,    7, 6014, 4970, 6016,
+ 4971, 6017, 6019, 6021, 4970, 6017, 4971, 6016, 6025, 6027,    7, 5997,
+    3, 6030, 4970, 6032, 4971, 6033, 6035, 6037, 4970, 6033, 4971, 6032,
+ 6041, 6043,    3, 5996,    7, 6047,    2, 5996, 4992, 6051, 6015, 6051,
+    7, 6055, 4971, 6057,    9, 6051, 4971, 6060, 4971, 6051,    9, 6064,
+  586, 5997, 4971, 6068, 4987, 6071, 4971, 6069, 4983, 6075,    2, 5997,
+ 6048, 6079, 4971, 6081,    7, 6079, 6047, 6084, 4971, 6087, 4971, 6085,
+ 6047, 6091, 6047, 6079,    7, 6094, 4971, 6097, 4992, 5997,  587, 6101,
+ 2839, 5997,  587, 6105,    9, 5997, 4971, 6108,  587, 6111, 4971, 5997,
+    2, 6115,    7, 6117, 4975, 6117,  586, 6114, 4987, 6123,    5, 6114,
+    6, 6127, 6117, 6129, 6119, 6127,  586, 6115, 5001, 6135,    9, 6114,
+  587, 6139,  587, 6115,    9, 6143,    0,   67, 4636, 6147,   37, 6147,
+ 3008, 6147, 4656, 6147, 4650, 6147,    7, 6146, 4643, 6159, 2233, 6159,
+ 4625, 6159,    9, 6165,    5, 6147,    6, 6169,   36, 6147, 4625, 6172,
+ 3807, 6173, 4648, 6147,    9, 6178, 3003, 6147,    9, 6182,   33, 6146,
+ 6151, 6187, 3856, 6187, 3837, 6187,    9, 6192,    9, 6187, 3837, 6196,
+   33, 6147, 4652, 6200, 3807, 6201,    9, 6205,    9, 6200, 4625, 6208,
+ 3807, 6209, 4625, 6200,    9, 6214, 4652, 6147,   33, 6218,    9, 6147,
+ 4648, 6222, 3003, 6222,   33, 6222, 4625, 6228, 3807, 6229,   33, 6223,
+ 3837, 6235, 4625, 6222,   33, 6238, 4625, 6147,   75, 6243, 4629, 6243,
+    7, 6243, 4627, 6249, 6171, 6243,  375, 6243,   36, 6242,   33, 6242,
+    9, 6258,    9, 6242,   33, 6262,    0,   89, 5079, 6267, 5071, 6267,
+ 5097, 6270, 5098, 6267, 5072, 6267, 5075, 6277, 5097, 6267, 5071, 6280,
+  107, 6267,    5, 6267,    7, 6286, 5044, 6288, 5045, 6289, 6291, 6293,
+ 5044, 6289, 5045, 6288, 6297, 6299,    7, 6267,    5, 6302, 5044, 6304,
+ 5045, 6305, 6307, 6309, 5044, 6305, 5045, 6304, 6313, 6315,    5, 6266,
+    7, 6318, 5045, 6321,    7, 6319,    7, 6266,    5, 6326, 5045, 6329,
+ 5075, 6327, 2221, 6327, 5045, 6327,    4, 6266, 6287, 6339,    7, 6341,
+ 5045, 6343,   10, 6266, 5075, 6347, 2221, 6347, 5045, 6347,   10, 6267,
+ 5097, 6355, 5045, 6354, 5075, 6359, 5045, 6355, 5071, 6363, 1274, 6267,
+    4, 6267, 6324, 6369, 5045, 6371,    7, 6369, 6319, 6374, 5045, 6377,
+ 5044, 6374, 5045, 6375, 6319, 6383, 6381, 6383, 5044, 6375, 5045, 6374,
+ 6389, 6391, 6319, 6369,    7, 6394, 5045, 6397,    6, 6267,    3, 6400,
+    3, 6267,    6, 6404,   21, 6267,   11, 6409, 5045, 6411, 5045, 6267,
+   10, 6414, 5075, 6417,   10, 6415, 5097, 6421, 5311, 6267,   11, 6266,
+ 2969, 6427, 5082, 6427, 5045, 6427,   21, 6432,   21, 6427, 5045, 6436,
+    1,  767, 4580, 6441, 4582, 6441, 4586, 6441, 4590, 6441, 2862, 6441,
+ 1413, 6441, 4579, 6452,  922, 6441, 4579, 6456, 4584, 6441,  483, 6460,
+ 2861, 6441,  483, 6464,  759, 6440,  903, 6441, 4588, 6470,  483, 6470,
+ 4579, 6474, 4579, 6470,  483, 6478, 4588, 6441,  903, 6482,  483, 6441,
+ 4584, 6486, 2861, 6486,  903, 6486, 4579, 6492, 4579, 6486,  903, 6496,
+ 4579, 6441, 1413, 6500,  922, 6500,  903, 6500,  483, 6506,  483, 6500,
+  903, 6510,    1,  567,    5, 6514,    6, 6517, 4935, 6517, 2137, 6515,
+    9, 6523,   14, 6515,    2, 6515,  563, 6529, 4935, 6531, 6519, 6529,
+ 4935, 6535,    7, 6529, 6520, 6539, 4935, 6539, 6517, 6542, 6517, 6539,
+ 4935, 6546, 1197, 6529, 4935, 6551,    6, 6515,    5, 6554,    5, 6515,
+    6, 6558, 5325, 6515,  903, 6515,    9, 6514, 4950, 6567,  587, 6567,
+ 4935, 6570, 4935, 6567,  587, 6574,  241, 6515, 4950, 6515,    9, 6581,
+  587, 6515,    9, 6585, 4935, 6587, 4935, 6584,    9, 6591, 4935, 6515,
+    2, 6594,    7, 6597,    5, 6595, 6539, 6601, 6599, 6601,    6, 6601,
+ 6597, 6607,    9, 6595,  587, 6611,  587, 6594,    9, 6615, 5843, 6515,
+ 5313, 6515,  587, 6514,    1,   67, 4594, 6625, 4606, 6625, 3280, 6625,
+   75, 6625, 4593, 6632, 2146, 6625, 2145, 6625,    9, 6638,    7, 6625,
+   73, 6643, 4593, 6645,  375, 6625, 4593, 6648,   33, 6624, 4593, 6653,
+    9, 6655,    9, 6625, 3273, 6658, 2145, 6658, 4593, 6625,   75, 6664,
+  375, 6664,   36, 6665,   33, 6665,    9, 6672,    9, 6665,   33, 6676,
+ 3273, 6625,    9, 6680,    1,   89, 1657, 6685,   25, 6685, 3565, 6685,
+ 3573, 6685, 3273, 6685,   21, 6684,  483, 6685, 5843, 6685,   11, 6684,
+    0, 1487,   10, 6705,    7, 6705,    5, 6708,    5, 6705,    7, 6712,
+    0, 1347,    0,  113, 2149, 6719,    9, 6721, 4736, 6719,    9, 6725,
+ 3023, 6719,    9, 6729, 4740, 6719,    9, 6733, 2879, 6719,    9, 6737,
+  587, 6719, 4727, 6740,    9, 6743,   25, 6719, 4727, 6746,    9, 6749,
+ 4727, 6719,    5, 6753,    6, 6755, 4731, 6755,    2, 6752,    7, 6761,
+ 6755, 6763, 6757, 6761,   25, 6752,    9, 6769,  587, 6752,    9, 6773,
+    9, 6753,   25, 6777,  587, 6777, 3255, 6719,    9, 6783,    0,  137,
+    1,  113,   31, 6788,    2, 6788,    7, 6793, 4669, 6793, 4697, 6789,
+   14, 6788,    6, 6789,    6, 6788,    5, 6804,   11, 6788,    5, 6808,
+    5, 6788,    6, 6813,    6, 6812, 4696, 6813,    9, 6813, 4669, 6820,
+ 4669, 6813,    9, 6824,    7, 6788, 6815, 6829,   15, 6788, 6803, 6833,
+    8, 6788,    8, 6789, 4669, 6839, 1368, 6789,    5, 6789,   35, 6845,
+ 4669, 6847, 6795, 6845, 4669, 6851,    6, 6845, 6796, 6855, 4669, 6855,
+ 6793, 6858, 6793, 6855, 4669, 6862, 1171, 6845, 4669, 6867,   17, 6845,
+ 4669, 6871,    7, 6789, 6811, 6875, 6807, 6875, 6817, 6875, 6801, 6875,
+    2, 6874,    2, 6789,    7, 6886,   30, 6788, 3867, 6891,   25, 6788,
+ 4696, 6895, 3867, 6895,    9, 6899,    9, 6894, 3867, 6903, 4669, 6895,
+    9, 6906,    9, 6895, 4669, 6910,  587, 6788, 4696, 6915,    9, 6915,
+ 4669, 6918, 4669, 6915,    9, 6922,   25, 6789, 4473, 6927, 6791, 6927,
+ 3972, 6927, 3933, 6927,    9, 6934,    9, 6927, 3933, 6938, 4696, 6789,
+ 6837, 6943,   25, 6943,  587, 6943,    9, 6789, 6837, 6951, 4669, 6953,
+  587, 6951, 4669, 6957,   25, 6951, 4669, 6961, 4669, 6950,   25, 6965,
+ 6837, 6965,  587, 6965, 4669, 6789,    5, 6972,    6, 6975,    2, 6973,
+ 6855, 6979, 6977, 6979,    7, 6979, 6975, 6985,   25, 6973,    9, 6989,
+  587, 6973,    9, 6993,    9, 6972, 6837, 6997,   25, 6997,  587, 6997,
+    9, 6973, 6839, 7005,    9, 6788, 6799, 7009, 6840, 7009, 6839, 7009,
+ 4669, 7014, 4669, 7009, 6839, 7018,   25, 7008, 3867, 7023,   25, 7009,
+ 3933, 7027,    1,  137, 6267, 7031,    0,  375,  413, 7034,  413, 7035,
+  241, 7034, 3307, 7041, 2885, 7041,    0,  261,    0,  803,   16, 7049,
+    7, 7049,    4, 7052,    4, 7049,    7, 7056,    0,  581,    0,  145,
+    1,  375,  317, 7064,  265, 7065,  256, 7068,  256, 7069, 4901, 7065,
+    4, 7065,    2, 7077,  265, 7077,    2, 7076, 4899, 7083,    2, 7065,
+  265, 7087,    4, 7086, 4899, 7091,    2, 7064,  265, 7064,    3, 7064,
+ 7084, 7099, 7092, 7099, 7083, 7099, 4899, 7104, 7091, 7099, 4899, 7108,
+ 7075, 7099, 4899, 7099, 7083, 7114, 7091, 7114,  240, 7064,  240, 7065,
+  265, 7123,    7, 7125, 7114, 7123, 7099, 7123, 4899, 7130, 4899, 7123,
+ 7099, 7134,  413, 7065,    7, 7138,    3, 7065, 7079, 7143, 4899, 7145,
+ 7081, 7143, 4899, 7149,    5, 7065, 7089, 7153, 4899, 7155,  445, 7065,
+ 4349, 7159, 7121, 7159,  367, 7065, 4863, 7165,  973, 7065, 4805, 7169,
+  316, 7064, 4067, 7173,  973, 7064, 4745, 7177,  445, 7064, 4371, 7181,
+  257, 7064, 4841, 7185, 2227, 7185, 4827, 7185, 7071, 7185,  305, 7064,
+ 4067, 7195,  241, 7197,  241, 7194, 4067, 7201,  587, 7064,  257, 7065,
+ 4863, 7207, 7073, 7207,  628, 7065,  587, 7065,   11, 7214,   11, 7065,
+  587, 7218,  241, 7219,  305, 7065, 4497, 7225, 7067, 7225, 4254, 7225,
+ 4213, 7225,  241, 7232,  241, 7225, 4213, 7236, 4900, 7065, 7121, 7241,
+ 7095, 7241, 7097, 7241,  241, 7065, 7095, 7249, 4899, 7251, 7097, 7249,
+ 4899, 7255,    6, 7249, 7121, 7249, 4899, 7261, 4899, 7248, 7121, 7265,
+ 7095, 7265, 7097, 7265, 4899, 7065,  241, 7272, 7121, 7275, 7095, 7275,
+ 7097, 7275,  241, 7273, 7123, 7283,  241, 7064, 4371, 7287, 7141, 7287,
+ 7127, 7287, 7075, 7287, 7134, 7287, 7123, 7287, 4899, 7298, 4899, 7287,
+ 7123, 7302,  305, 7286, 4067, 7307,  305, 7287, 4213, 7311,    1,  261,
+  413, 7315, 3357, 7315,  264, 7319,  265, 7318, 7321, 7323,  264, 7318,
+  265, 7319, 7327, 7329,    1,  803,  737, 7332, 4799, 7333, 1274, 7332,
+    6, 7333,    2, 7341,    2, 7340, 4787, 7345,    2, 7333,    6, 7348,
+ 4787, 7351,    2, 7332,    6, 7332,    3, 7356,  587, 7332,    3, 7360,
+    3, 7332, 7346, 7365, 7352, 7365, 7345, 7365, 4787, 7370, 7351, 7365,
+ 4787, 7374,    6, 7365,    6, 7364, 7337, 7365, 4787, 7365, 7345, 7384,
+ 7351, 7384,    7, 7332, 7379, 7391, 1275, 7332, 7341, 7395,  482, 7332,
+  482, 7333, 7384, 7401, 7365, 7401, 4787, 7404, 4787, 7401, 7365, 7408,
+    3, 7333, 7343, 7413, 4787, 7415,    7, 7333, 7363, 7419, 7359, 7419,
+ 7381, 7419, 7339, 7419,  736, 7332, 3997, 7429,  713, 7332, 3997, 7433,
+  483, 7435,  483, 7432, 3997, 7439,   11, 7333,  483, 7443,  713, 7333,
+ 4485, 7447, 7335, 7447, 4188, 7447, 4147, 7447,  483, 7454,  483, 7447,
+ 4147, 7458, 4798, 7333, 7399, 7463, 7355, 7463,  483, 7333, 7355, 7469,
+ 4787, 7471, 7399, 7469, 4787, 7475, 4787, 7468, 7399, 7479, 7355, 7479,
+ 4787, 7333,  483, 7484, 7399, 7487, 7355, 7487,  483, 7485, 7401, 7493,
+  483, 7332, 7337, 7497, 7408, 7497, 7401, 7497, 4787, 7502, 4787, 7497,
+ 7401, 7506,  713, 7496, 3997, 7511,  713, 7497, 4147, 7515,    1,  145,
+  586, 7519,    7, 7519,    3, 7522,    3, 7519,    7, 7526,    1,  155,
+  483, 7530,    0,  175,  482, 7535,    6, 7535,    2, 7538,    2, 7535,
+    6, 7542,    1, 1505, 1011, 7546,    6, 7549,    7, 7549,    6, 7548,
+ 7553, 7555,    7, 7548, 7551, 7559,    1, 1363,    8, 7563,    6, 7563,
+    4, 7566,    4, 7563,    6, 7570, 1374, 7563, 4423, 7575, 1374, 7562,
+ 4431, 7579,  265, 7562, 5189, 7583,    1,  165,  903, 7586,    6, 7589,
+    7, 7589,    6, 7588, 7593, 7595,    7, 7588, 7591, 7599,    1,  175,
+   44, 7602,   45, 7603, 7605, 7607,   44, 7603,   45, 7602, 7611, 7613,
+    0,  299, 3289, 7617, 2181, 7617, 3307, 7617, 2885, 7617,    1,  299,
+ 4371, 7627, 2801, 7627, 1669, 7627, 5461, 7627, 3295, 7627,  305, 7626,
+ 4067, 7639,  251, 7627,  305, 7627, 4213, 7645,    0,  705, 3371, 7649,
+ 2183, 7649,    0,  101, 3157, 7655, 2185, 7655, 3175, 7655, 6697, 7655,
+ 3037, 7655, 6685, 7655,   21, 7667,    1,  705, 3377, 7671,  713, 7670,
+ 3997, 7675,  555, 7671,  713, 7671, 4147, 7681,    1,  101, 3163, 7685,
+   25, 7684, 3867, 7689,   21, 7685,   25, 7685, 3933, 7695,    0,  129,
+ 2253, 7699,   21, 7699,    1,  129,   21, 7704,    0,  395, 2247, 7709,
+ 4417, 7709,  265, 7709,    7, 7715,  251, 7709,    0,  829, 2251, 7721,
+  555, 7721,    1,  395, 2647, 7727, 1719, 7727,  251, 7726,    1,  829,
+  555, 7734,    0,  298,  265, 7739,    7, 7741, 7627, 7743, 2551, 7739,
+ 7642, 7739, 4417, 7739, 7627, 7739,  251, 7752,  251, 7739, 7627, 7756,
+    1,  298, 2647, 7761, 1783, 7761,  251, 7760, 7617, 7767, 7617, 7761,
+  251, 7771,    0,  704, 2555, 7775, 7678, 7775, 7671, 7775,  555, 7780,
+  555, 7775, 7671, 7784,    0,  100, 2557, 7789, 7692, 7789, 2969, 7789,
+ 5082, 7789, 5045, 7789,   21, 7798, 7685, 7789,   21, 7802,   21, 7789,
+ 7685, 7806, 5045, 7806,    1,  704,  555, 7812, 7649, 7815, 7649, 7813,
+  555, 7819,    1,  100,   21, 7822, 7655, 7825, 7655, 7823,   21, 7829,
+    0,  128, 3159, 7833, 2197, 7833, 7707, 7833, 7705, 7833,   21, 7841,
+    1,  128, 3161, 7845, 7702, 7845,   25, 7844, 3867, 7851,   21, 7845,
+ 7699, 7854, 7699, 7845,   21, 7858,   25, 7845, 3933, 7863,    0,  394,
+ 3291, 7867, 2193, 7867, 7733, 7867, 2885, 7867, 3307, 7867, 7727, 7867,
+  251, 7879,    0,  828, 3373, 7883, 2195, 7883, 7737, 7883, 7735, 7883,
+  555, 7891,    1,  394, 4371, 7895, 3293, 7895, 7718, 7895, 1721, 7895,
+ 1725, 7895, 7717, 7895,  305, 7894, 4067, 7909,  251, 7895, 7709, 7912,
+ 7709, 7895,  251, 7916,  305, 7895, 4213, 7921,    1,  828, 3375, 7925,
+ 7724, 7925,  713, 7924, 3997, 7931,  555, 7925, 7721, 7934, 7721, 7925,
+  555, 7938,  713, 7925, 4147, 7943,    0,    8,    6, 7947,    3, 7948,
+ 1274, 7947,  113, 7947,    3, 7947,    0, 7957,    6, 7956,    0, 7956,
+    9, 7963,   11, 7957,  587, 7947,    1,   10, 5081, 7971, 5026, 7971,
+    7, 7971,    2, 7976, 1368, 7971, 5097, 7971,  931, 7971, 1417, 7971,
+  939, 7971,  941, 7971,  272, 7971, 1476, 7971,  280, 7971,  949, 7971,
+ 1517, 7971, 4696, 7971,  149, 7971,  631, 7971,  970, 7971,   50, 7971,
+  764, 7971,  357, 7971,  367, 7971,  471, 7971, 1249, 7971, 5019, 7971,
+  101, 8022,  128, 7971,  101, 7971, 5019, 8028, 4669, 7971,    9, 8032,
+  759, 7971,   33, 8036, 1471, 7971,  265, 8040,  959, 7971,   33, 8044,
+  253, 7971,  265, 8048,  113, 7971,    9, 8052,  375, 7971,   88, 7971,
+   89, 7971,    2, 7971,    1, 8063,    7, 8062,    1, 8062,   11, 8069,
+    9, 8063,    3, 7971,    9, 8074,   33, 7971,  959, 8078,   47, 8078,
+  759, 8078,   25, 7971,  305, 7971,  713, 7971,    2, 7970, 8059, 8093,
+ 8077, 8093, 8075, 8093,    9, 8099, 3867, 8093, 3997, 8093, 4067, 8093,
+    3, 7970, 4696, 8109, 8061, 8109, 8072, 8109, 8063, 8109,    9, 8116,
+ 4669, 8109,    9, 8120,    9, 8109, 4669, 8124, 8063, 8124,   47, 7971,
+   33, 8130,   53, 7971,  265, 8134,  265, 7971,  253, 8138, 1471, 8138,
+   53, 8138,  587, 7971,  483, 7971,    9, 7971, 4669, 8150,  113, 8150,
+    3, 8150, 8093, 8157,    3, 8151, 8063, 8161,    0,   10,  203, 8165,
+  107, 8165, 5019, 8169,   85, 8165, 2215, 8165, 2221, 8165, 2233, 8165,
+ 5075, 8165, 4643, 8165, 5045, 8165,   25, 8185, 4551, 8165,  922, 8165,
+ 1413, 8165,  273, 8165,  281, 8165, 1477, 8165, 1516, 8165,  948, 8165,
+ 4625, 8165,    9, 8205,  759, 8165,  959, 8165,   67, 8165,    9, 8213,
+ 1505, 8165, 1011, 8216,   88, 8165,   33, 8221,   89, 8165, 5019, 8225,
+    3, 8165,   33, 8229,    9, 8231, 8063, 8229,    9, 8228,   33, 8237,
+    2, 8165,    9, 8241,   33, 8165, 1141, 8165, 1447, 8165,    2, 8164,
+ 2215, 8251, 2221, 8251, 5075, 8251, 2233, 8251, 4643, 8251, 8229, 8251,
+ 4625, 8251,    9, 8265, 4295, 8251, 3833, 8251, 4321, 8251, 5045, 8251,
+    3, 8164, 8241, 8277, 8093, 8277, 3837, 8277, 4287, 8277, 4303, 8277,
+  128, 8277,  101, 8277,  113, 8277,    9, 8292,    9, 8277,  113, 8296,
+   47, 8165,  165, 8165,  903, 8302,  265, 8165,  587, 8165, 1011, 8165,
+ 1505, 8310, 1369, 8165,  483, 8165,  903, 8316,  903, 8165,  483, 8320,
+  165, 8320,    9, 8165,    3, 8326,   33, 8329,    3, 8327,  113, 8333,
+    0,  240, 4266, 8337, 4888, 8337, 4892, 8337, 4213, 8337,  375, 8344,
+ 4863, 8337,  375, 8348,  265, 8348,  261, 8337, 3335, 8337,  375, 8357,
+  347, 8337,  386, 8337,  331, 8337,  305, 8337,  375, 8366,  340, 8337,
+  331, 8371,  375, 8337, 4213, 8374, 4863, 8374,  305, 8374, 1325, 8337,
+   59, 8337,    7, 8337,  265, 8387, 4213, 8389, 4863, 8389,  305, 8389,
+  265, 8386,  331, 8397,    7, 8336, 5141, 8401, 5137, 8402, 5137, 8401,
+ 5141, 8406, 5150, 8401, 5154, 8401, 5133, 8413, 5161, 8401, 5127, 8401,
+  265, 8419, 5137, 8421,  265, 8418, 5133, 8425,  265, 8401, 5127, 8429,
+ 5141, 8431, 5127, 8428, 5133, 8435, 3785, 8401, 4329, 8401, 4311, 8401,
+  483, 8337,    9, 8337, 1275, 8337,   15, 8337,  265, 8337, 4863, 8452,
+  257, 8452,    1, 8457,    6, 8452,    1, 8461,  241, 8462,  241, 8461,
+    1, 8466,    7, 8452,  331, 8471,    7, 8453, 7895, 8475, 7287, 8475,
+ 8465, 8475, 8469, 8475, 7627, 8475, 8459, 8475,    0, 8475, 8457, 8489,
+  375, 8475,    1,  264, 3293, 8495, 7718, 8495, 3295, 8495, 3305, 8495,
+ 3301, 8495, 5512, 8495, 5451, 8495, 7756, 8495, 7091, 8495, 4899, 8512,
+ 7083, 8495, 4899, 8516, 7092, 8495, 7084, 8495, 4696, 8495, 7075, 8495,
+ 7123, 8495, 4899, 8528, 7134, 8495,  445, 8495, 4349, 8535, 8386, 8495,
+  331, 8539,  471, 8495,  367, 8495,  357, 8495,  631, 8495, 1249, 8495,
+  628, 8495, 8387, 8495, 8401, 8495, 4137, 8495, 3863, 8495, 4063, 8495,
+ 8475, 8495, 4371, 8495, 4549, 8495, 4545, 8495,  407, 8495, 1417, 8495,
+  665, 8495,  338, 8495, 1480, 8495,  336, 8495, 4745, 8495, 4669, 8495,
+    9, 8586, 4899, 8495, 7091, 8590, 7083, 8590, 7123, 8590, 4569, 8495,
+ 7709, 8495,  251, 8600,  341, 8495, 4863, 8605,  241, 8605,  253, 8495,
+  331, 8610,  251, 8495, 7709, 8614, 5509, 8614, 7739, 8614,  256, 8495,
+  375, 8623, 7739, 8495,  251, 8626, 5509, 8495,  251, 8630,  257, 8495,
+  305, 8635,   53, 8495,  331, 8638, 1471, 8495,  331, 8642,    6, 8495,
+ 4349, 8647, 4497, 8647,  413, 8647, 4213, 8647, 8109, 8647, 4147, 8647,
+ 3933, 8647,  445, 8647,  316, 8647, 4713, 8647, 4863, 8647, 8337, 8647,
+  305, 8647,  241, 8672,  241, 8647,  305, 8676,  587, 8647, 8387, 8647,
+    7, 8495, 3785, 8685, 4329, 8685, 4311, 8685, 8337, 8684,  331, 8693,
+  331, 8685, 8337, 8697,   15, 8685,  241, 8684,  375, 8703,  331, 8495,
+  253, 8706, 1471, 8706,   53, 8706,  305, 8495,    6, 8494, 8539, 8717,
+ 8693, 8717, 4371, 8717, 8623, 8717, 8703, 8717, 8685, 8717, 8337, 8729,
+  241, 8729,  471, 8717,  367, 8717,  357, 8717, 1369, 8717,  341, 8717,
+  241, 8743, 4569, 8717, 4137, 8717, 4063, 8717, 3863, 8717, 8401, 8717,
+    7, 8494, 8389, 8757, 8555, 8757, 8374, 8757, 8670, 8757, 8635, 8757,
+ 8676, 8757, 8647, 8757, 8337, 8770,  241, 8770, 8337, 8757, 8647, 8776,
+  375, 8776,    9, 8757,  375, 8757, 8337, 8784,  241, 8757,    1, 8789,
+ 8647, 8791, 8647, 8788,  587, 8495,   11, 8796,   11, 8495,  587, 8800,
+    9, 8495, 4669, 8804, 1369, 8495,   17, 8495,  241, 8495,    1, 8813,
+    7, 8815, 8717, 8817,    7, 8814, 8647, 8821,    7, 8812, 8717, 8825,
+  375, 8825,    7, 8813,    1, 8830, 8647, 8833, 8647, 8831,  331, 8831,
+    6, 8813, 8337, 8495,    7, 8842, 8717, 8845,  331, 8845,  483, 8843,
+    9, 8843,    7, 8843, 8647, 8855,  375, 8855,    0,  264, 3299, 8861,
+ 5431, 8861, 5469, 8861, 5449, 8861, 4888, 8861, 4863, 8861,  375, 8872,
+  629, 8861,  394, 8861,  299, 8861,  659, 8861,  623, 8861,  645, 8861,
+  101, 8861,  705, 8861,  128, 8861,  828, 8861, 3345, 8861, 3445, 8861,
+  375, 8899, 2981, 8861, 3049, 8861, 7195, 8861, 3461, 8861, 4613, 8861,
+  331, 8910, 4614, 8861,  375, 8861, 4863, 8916,  241, 8916,  803, 8861,
+  483, 8922,  113, 8861,    9, 8926,  256, 8861,  331, 8931, 5455, 8861,
+  251, 8935,    7, 8861,  331, 8939,  241, 8941,  241, 8938,  331, 8945,
+  331, 8861, 4613, 8948,    7, 8860, 3837, 8953, 8093, 8953,  394, 8953,
+  299, 8953,  375, 8953,  241, 8962, 4303, 8953, 4287, 8953,  241, 8953,
+  375, 8970,  483, 8861,  803, 8974,    9, 8861,  113, 8978,   17, 8861,
+  241, 8861,  375, 8984,    7, 8984,  331, 8989,    7, 8985,  375, 8993,
+    1,  240, 3342, 8997, 2900, 8997, 8672, 8997, 8743, 8997, 3795, 8997,
+ 8770, 8997, 8729, 8997, 2658, 8997, 7159, 8997, 2703, 8997, 2660, 8997,
+  413, 8997, 8757, 8997, 8647, 9022, 8684, 8997, 8717, 9027, 8605, 8997,
+  457, 8997, 2647, 9032, 8647, 8997,  305, 9036, 8757, 9036, 8916, 8997,
+  257, 8997, 2647, 8997,  375, 9046,  457, 9046, 3341, 8997,  375, 9052,
+ 2897, 8997,  375, 9056,  305, 8997, 8647, 9060,  340, 8997, 8717, 9065,
+ 3785, 9065, 8495, 9065,  375, 8997, 3341, 9072, 2897, 9072, 2647, 9072,
+ 8861, 9072,    7, 8997,  413, 9082,    0, 9085,    1, 9083,  264, 9088,
+  264, 9089, 8495, 9082, 8717, 9095, 8495, 9083, 8757, 9099,  305, 9099,
+  265, 9083, 2897, 9105, 3341, 9105, 2647, 9105, 9087, 9105,    1, 9105,
+ 9085, 9115, 9093, 9105, 8861, 9105,  265, 9082, 8717, 9123, 3785, 9123,
+ 9091, 9123, 8495, 9123,  483, 8997,    9, 8997,  265, 8997,    7, 9136,
+ 8717, 9139, 3785, 9139, 8495, 9139,    7, 9137, 8647, 9147, 8495, 8997,
+    7, 9150, 8717, 9153,    7, 9151, 8647, 9157, 8861, 8997,  375, 9160,
+    0,  482,    6, 9165,    4, 9167,  803, 9165,    5, 9165,  587, 9173,
+    9, 9173,    5, 9164,   17, 9179,   19, 9165,   12, 9165,    9, 9165,
+   11, 9186,   11, 9165,    9, 9190,    1,  586, 4795, 9195,  807, 9195,
+ 4787, 9198, 4788, 9195, 4790, 9195, 8374, 9195, 8389, 9195, 4797, 9195,
+ 8086, 9195, 8090, 9195, 8251, 9195, 4283, 9195, 4279, 9195, 3807, 9195,
+ 1491, 9195,  631, 9195, 1160, 9195, 1466, 9195,  764, 9195,  357, 9195,
+  367, 9195,  471, 9195, 1249, 9195, 8800, 9195, 8647, 9195, 4787, 9195,
+  807, 9246,  375, 9246,   33, 9195,  759, 9252, 1141, 9195,  759, 9256,
+  803, 9195,  375, 9195, 4787, 9262, 8337, 9262, 8165, 9195,  265, 9269,
+  566, 9195,  567, 9195, 7971, 9195,   25, 9276,  713, 9276, 8495, 9195,
+   11, 9282,    4, 9195,  483, 9287,    5, 9195,   17, 9291,  483, 9290,
+  759, 9195, 1141, 9296, 1447, 9296,   33, 9296,  713, 9195, 7971, 9304,
+   25, 9195, 7971, 9308, 8337, 9195,  375, 9312,    4, 9194, 9273, 9317,
+ 9295, 9317, 9291, 9317,  483, 9323, 4279, 9317, 3807, 9317, 4283, 9317,
+ 8251, 9317,    5, 9194, 9275, 9335, 9288, 9335, 9287, 9335,  483, 9340,
+ 8647, 9335,    9, 9335,  483, 9335, 9287, 9348, 1447, 9195,  759, 9352,
+   11, 9195, 8495, 9357, 8495, 9356,    9, 9195, 1011, 9195,  483, 9195,
+    5, 9366, 9317, 9369,    5, 9367, 9287, 9373,    0,  586,    7, 9377,
+    4, 9378,   16, 9377, 8800, 9377,  273, 9377, 1477, 9377,  281, 9377,
+  948, 9377, 1516, 9377,  750, 9377,  386, 9377,  347, 9377,  510, 9377,
+  767, 9377,  375, 9377,  305, 9406,  713, 9406,  165, 9377,  903, 9412,
+ 8495, 9377,   11, 9416,  566, 9377,  759, 9421,    5, 9377,  759, 9425,
+  483, 9427,  483, 9424,  759, 9431,    4, 9377,    0, 9435,    7, 9434,
+    0, 9434,  587, 9441,  713, 9435,  713, 9377,  375, 9446,  305, 9377,
+  375, 9450,    4, 9376,  767, 9455,    5, 9376, 3837, 9459, 8093, 9459,
+  828, 9459,  705, 9459,  803, 9459,  483, 9468, 4287, 9459, 4303, 9459,
+  483, 9459,  803, 9476, 1505, 9377, 1011, 9480,   11, 9377, 8495, 9484,
+  903, 9377,  165, 9488,    9, 9377,  483, 9492, 1011, 9377, 1505, 9496,
+  483, 9377,    9, 9500,    5, 9500,  759, 9505,    5, 9501,  803, 9509,
+    1,  482,    6, 9513,    5, 9514,   14, 9513,    5, 9513,    1, 9521,
+    6, 9520,    1, 9520,  483, 9527,   11, 9513,    0,  902,  524, 9533,
+ 1291, 9533,  767, 9533,    7, 9533,    3, 9541,  305, 9533,  375, 9544,
+  386, 9533,  347, 9533,  375, 9533,  305, 9552,  483, 9533,   11, 9556,
+   11, 9533,  483, 9560,    1, 1010, 5038, 9565, 5037, 9565,  587, 9568,
+  668, 9565, 1419, 9565, 8982, 9565,    7, 9564, 3867, 9579, 8277, 9579,
+ 9459, 9579, 8953, 9579, 4067, 9579, 3997, 9579,  375, 9565,  483, 9565,
+    9, 9565,  587, 9596,  587, 9565, 5037, 9600,    9, 9600,   17, 9565,
+ 8861, 9606, 8861, 9565,    7, 9611,   17, 9610,    0, 1010, 9535, 9617,
+ 9537, 9617, 9559, 9617, 9563, 9617,    5, 9617,    6, 9627,    7, 9627,
+ 5006, 9617, 5005, 9617,    9, 9634, 9362, 9617, 1290, 9617, 9533, 9641,
+  525, 9617, 9533, 9645, 8804, 9617, 8150, 9617,  922, 9617, 1413, 9617,
+ 7971, 9617,    9, 9656,    6, 9617,   11, 9661, 9195, 9617,    9, 9664,
+    6, 9616,   17, 9669,    7, 9616, 9195, 9673, 9317, 9673, 4321, 9673,
+ 3833, 9673, 4295, 9673, 5045, 9673,   19, 9617,   12, 9617,   11, 9617,
+    9, 9690,  483, 9617,  903, 9694, 1275, 9617,   17, 9698, 9533, 9701,
+    9, 9617, 5005, 9704, 9195, 9704, 7971, 9704, 8495, 9704,   11, 9704,
+   17, 9617, 1275, 9716, 9533, 9719,  903, 9617,  483, 9722, 8495, 9617,
+    9, 9726,    1,  902, 9573, 9731, 9575, 9731, 9599, 9731, 9605, 9731,
+ 1418, 9731, 9565, 9741,  669, 9731, 9565, 9745, 8386, 9731,    7, 9731,
+ 8337, 9750,    7, 9730, 9673, 9755, 8251, 9755, 4283, 9755, 3807, 9755,
+ 4279, 9755,  483, 9731,   15, 9731, 1369, 9768, 9565, 9771, 1369, 9731,
+   15, 9774, 9565, 9777, 1011, 9731, 8337, 9731,    7, 9782, 9617, 9731,
+    6, 9786,    7, 9786,    6, 9787, 9791, 9793,    7, 9787, 9789, 9797,
+    0, 1274,    5, 9801,    1, 1368, 4904, 9805, 4903, 9805,    9, 9808,
+ 9484, 9805, 1517, 9805, 1476, 9805,  272, 9805,  280, 9805,  949, 9805,
+ 1197, 9805, 1471, 9805,  265, 9826,  253, 9805,  265, 9830,   53, 9805,
+  265, 9834,    5, 9804, 3867, 9839, 8277, 9839, 8953, 9839, 9459, 9839,
+ 3997, 9839, 4067, 9839,   11, 9805, 9377, 9852,    9, 9805, 4903, 9856,
+  265, 9805, 1471, 9860,  253, 9860,   53, 9860, 9377, 9805,   11, 9868,
+    5, 9869,    0, 1368, 5075, 9875, 2221, 9875, 4643, 9875, 2233, 9875,
+ 2215, 9875, 4339, 9875,    7, 9875,    5, 9888,    4, 9889,   10, 9875,
+ 8714, 9875, 8800, 9875, 4625, 9875,    9, 9901,   47, 9875,  305, 9875,
+ 8495, 9906,  959, 9875, 5045, 9875, 4551, 9875, 1325, 9875,   59, 9875,
+  331, 9875,    5, 9875,    0, 9923,    7, 9922,    0, 9922, 1369, 9929,
+ 9287, 9923,    4, 9875, 1011, 9935, 8495, 9875,   10, 9938,   10, 9939,
+  305, 9938,   11, 9938, 9943, 9947,   11, 9939, 9941, 9951,    4, 9874,
+ 8495, 9955, 8717, 9955, 4329, 9955, 4311, 9955, 3785, 9955,    5, 9874,
+ 9195, 9967, 9755, 9967, 9317, 9967, 3833, 9967, 4295, 9967, 4321, 9967,
+ 5045, 9967,  759, 9875,   11, 9875, 8495, 9984,   17, 9875,  903, 9875,
+  265, 9875,   15, 9875, 9195, 9875,  241, 9997,    1, 1274,    6,10001,
+    4,10002,    4,10003,    8,10001, 5123,10001,    5,10011,    4,10010,
+10013,10015,    4,10011,    5,10010,10019,10021,  341,10001, 4663,10001,
+  903,10027, 1471,10001,  253,10001,   53,10001,    4,10001,    1,10037,
+    6,10036,    1,10036, 1275,10043,    5,10001, 9935,10047, 8337,10001,
+    9,10051,    5,10000, 8685,10055, 1369,10055, 8401,10055, 3863,10055,
+ 4137,10055, 4063,10055, 4569,10055, 9955,10055,  241,10001,   17,10001,
+ 1369,10001,    5,10077,    0,   14,    6,10081,    2,10082,  482,10081,
+    2,10081,    0,10089,    6,10088,    0,10088,   15,10095,    2,10080,
+   17,10099, 1369,10081,   17,10081,    1,   16,    7,10107,    3,10108,
+  586,10107, 8306,10107, 1447,10107, 1141,10107, 9875,10107,  241,10121,
+  265,10120, 9992,10107,  545,10107,  695,10107, 1382,10107, 1374,10107,
+ 1386,10107,   59,10107, 1369,10138,  154,10107,  483,10143, 1325,10107,
+ 1369,10146,  331,10107, 1369,10150,    3,10107,    1,10155,    7,10154,
+    1,10154,   17,10161, 8241,10155,   15,10154,  483,10167,    3,10106,
+ 9673,10171, 8251,10171, 3807,10171, 4279,10171, 4283,10171, 9967,10171,
+   33,10107, 1369,10107,  331,10186, 1325,10186,   59,10186, 1011,10107,
+  265,10107, 8165,10196, 9875,10196, 1275,10107,   15,10107,    3,10204,
+  483,10207,    3,10205, 1369,10211, 8165,10107,  265,10214,    0,   16,
+    4,10219,    3,10220,    3,10221,    7,10219,    2,10226,10225,10229,
+    2,10227,10223,10233, 1368,10219,10225,10237,  902,10219,10233,10241,
+   59,10219, 1325,10219,  331,10219,    3,10219,    4,10250,10233,10253,
+    2,10219,    7,10256,10225,10259,  903,10257, 8495,10219,  587,10265,
+10001,10219,  903,10269,    2,10218, 8495,10273, 8717,10273,10055,10273,
+ 4311,10273, 4329,10273, 3785,10273,  265,10219, 1275,10219,    1,   14,
+ 8982,10291, 8861,10291,   17,10294, 4745,10291, 1011,10299,   53,10291,
+  253,10291, 1471,10291,    2,10291,    3,10291,  483,10311,10257,10311,
+   59,10291,   17,10316,   62,10291, 1325,10291,   17,10322,  331,10291,
+   17,10326, 1328,10291,  334,10291,  393,10291, 1359,10291, 1031,10291,
+  499,10291, 8337,10291,  483,10343, 9875,10291, 1011,10347,    3,10290,
+ 8685,10351, 1369,10351, 8401,10351, 9955,10351, 4063,10351, 4137,10351,
+ 3863,10351, 4569,10351,10273,10351,  241,10291, 1369,10291,   17,10291,
+ 8861,10374,   59,10374, 1325,10374,  331,10374,    1,   11,  340,10385,
+  341,10385,  264,10385,  375,10391, 1010,10385,  264,10384,  341,10397,
+10387,10397,    5,10385,    6,10402,    2,10402,    2,10403,    7,10385,
+  265,10410,10397,10413,  265,10411,10391,10417,    5,10384,   29,10421,
+  341,10421,    6,10421,   25,10427, 8262,10385,    9,10431, 8279,10385,
+    9,10435,   88,10384, 3807,10439, 6347,10439, 6327,10439, 8251,10439,
+ 9875,10439, 8165,10439, 8229,10385, 8251,10452,    9,10455,    9,10453,
+ 8251,10459, 8241,10385,   33,10385, 6685,10465,    9,10465, 6267,10385,
+  101,10471, 8240,10385, 8296,10475, 8277,10475,    9,10478,    9,10475,
+ 8277,10482, 8228,10385, 6719,10385,    9,10489,  265,10384,10389,10493,
+ 5313,10493, 8251,10385, 8229,10498,    9,10501,  483,10384, 5197,10505,
+ 5125,10505, 1275,10384, 1369,10385, 6685,10513,    9,10513, 1011,10385,
+  265,10385,    7,10520,10397,10523,    2,10384,10423,10527,10428,10527,
+10427,10527,   25,10532,10425,10527,  340,10527,10397,10539,10399,10527,
+10392,10527,  375,10527,10391,10546,    7,10527,  265,10550,10397,10553,
+  265,10551,10391,10557,10391,10527,  375,10560,10463,10527,    9,10565,
+10487,10527,    9,10569,10519,10527,    6,10573,    7,10572,10575,10577,
+    7,10573,    6,10572,10581,10583,   25,10527,10427,10586, 8165,10527,
+  903,10527,  265,10527,    7,10594,10397,10597,    9,10527,    3,10384,
+10482,10603,    5,10602,    6,10607,    5,10603,    6,10611,10475,10613,
+10458,10603,10395,10603,    6,10619,    7,10618,10621,10623,    7,10619,
+    6,10618,10627,10629,10407,10603,    6,10633,    7,10632,10635,10637,
+    7,10633,    6,10632,10641,10643, 8326,10603,10453,10603,    9,10648,
+10475,10603,    9,10652, 9875,10603,    9,10657,10521,10603,  375,10661,
+    9,10602, 8251,10665, 3807,10665, 9875,10665, 8165,10665, 8165,10603,
+    9,10674,    9,10675, 3807,10603,    9,10681,    9,10603,10475,10684,
+10453,10684, 8165,10684, 8251,10603,    9,10693,    2,10385,10613,10697,
+ 8165,10699,10646,10697, 8327,10697,10690,10697,10676,10697,    5,10696,
+10603,10711,    6,10713,    7,10712,10715,10717,    7,10713,    6,10712,
+10721,10723, 8326,10697,10603,10726, 8251,10727,10674,10697,    9,10732,
+ 8165,10696,10613,10737,10705,10737, 8296,10737,10684,10737, 8277,10737,
+    9,10746,10603,10737,    9,10750,    9,10737,10603,10754, 8277,10754,
+  265,10697, 8165,10697,10684,10762, 8251,10763,    9,10767,    9,10762,
+10603,10770, 8251,10771,10603,10762,    9,10776,10684,10697, 8165,10780,
+ 8165,10781,    9,10697,10674,10786, 8165,10786,10603,10790, 8251,10791,
+ 8165,10787,10603,10797, 8277,10797,10603,10786, 8165,10802, 8165,10803,
+10603,10697, 8326,10808, 8165,10808,    9,10812, 8165,10809,    9,10817,
+    9,10808, 8165,10820, 8165,10821,   67,10697,10427,10827,    3,10385,
+ 8225,10831, 8242,10831,10427,10831,10409,10831,    6,10839,    7,10838,
+10841,10843,    7,10839,    6,10838,10847,10849,    7,10831,10421,10853,
+  375,10831,10590,10831,    9,10859, 8165,10830,10527,10863,    9,10865,
+ 8165,10831,10527,10868,    9,10871,    9,10831, 8241,10874,10527,10831,
+ 8326,10879, 8165,10878,    9,10883, 8165,10879,    9,10886,    9,10879,
+ 8165,10890, 8165,10891, 8241,10831,    9,10896,   89,10384,   88,10385,
+ 8225,10903, 8165,10385,  264,10907, 1368,10906,10909,10911,    7,10906,
+    2,10915,    2,10914,10909,10919,  265,10915,    5,10907,    3,10924,
+10919,10927,10911,10927,    3,10925,10917,10933, 1369,10925, 1369,10906,
+  265,10907,10939,10941,    2,10907,10937,10945, 8229,10945,    9,10949,
+10831,10945,    9,10953,    3,10907,    5,10957,    6,10959,10786,10957,
+    5,10956,10919,10965,10911,10965,10697,10957,    9,10970,    9,10957,
+10697,10974,    2,10906,10961,10979,10613,10979, 8296,10979,10974,10979,
+10684,10979,    7,10978,10927,10991,10965,10991,10909,10991, 8277,10979,
+    9,10998,10957,10979,    9,11002,10603,10979,    9,11006,    9,10979,
+10603,11010, 8277,11010,10957,11010,    3,10906,10923,11019,10945,11019,
+    9,11023,10527,11019,    9,11027,    9,10384, 1369,11031,   33,11031,
+    3,11030, 8251,11037, 3807,11037, 9875,11037, 8165,11037,    3,11031,
+ 8241,11047,    1,    9,   69,11051, 6625,11053,  981,11050,  980,11050,
+ 4745,11059, 7966,11050, 7967,11050,    4,11050,    7,11067, 1275,11067,
+ 7954,11051, 7967,11051,11063,11075,  120,11050, 3867,11079,  112,11050,
+11073,11083,   66,11050, 8251,11087, 1941,11087, 6159,11087, 3807,11087,
+ 9875,11087, 8165,11087,  121,11050, 7966,11051,11065,11103, 7957,11051,
+   11,11106, 1141,11051, 1447,11051,   67,11051,    7,11114,11087,11117,
+  113,11051,11083,11121, 7947,11123, 7947,11120,11083,11127,   89,11051,
+ 8495,11131,   25,11050,  113,11134, 3867,11137, 3867,11135,  113,11141,
+  567,11050, 4950,11145,  587,11145, 4935,11148, 4935,11145,  587,11152,
+  973,11050,    3,11156, 4745,11159,  587,11051,  566,11162,  566,11163,
+  567,11163,11165,11169,  567,11162,11167,11173, 1011,11051, 1369,11051,
+ 6625,11179, 7956,11051, 7955,11051,   33,11051, 6625,11187,   25,11051,
+11101,11191, 3984,11191, 3023,11191, 3933,11191,  113,11198,  113,11191,
+ 3933,11202,  973,11051, 2139,11207,11057,11207,  567,11051, 4971,11213,
+  587,11215,  257,11051,  483,11219,  483,11050,  257,11223, 1011,11050,
+  973,11227,  972,11226,11229,11231,  972,11227,  973,11226,11235,11237,
+  257,11227,  265,11050, 5019,11243,  903,11051,    7,11246,    2,11050,
+11187,11251,11073,11251,11127,11251,11207,11251,11113,11251,11111,11251,
+11075,11251,11179,11251,11121,11251, 7947,11269,   25,11251, 5019,11251,
+    3,11050,11068,11276,11069,11277,11279,11281,11068,11277,11069,11276,
+11285,11287,11185,11277,  973,11276, 4745,11293,11103,11277,11109,11277,
+11249,11277,   10,11276,   10,11277,   11,11276, 8251,11307, 3807,11307,
+ 9875,11307,11305,11307, 8165,11307,   33,11277, 7971,11319, 8165,11277,
+   25,11323, 7947,11277,  973,11277, 4805,11329, 3807,11277, 8251,11277,
+ 4279,11277, 4283,11277, 9673,11277, 9967,11277, 9875,11277, 4745,11277,
+   11,11277,11303,11349, 7971,11349,    2,11051,11315,11355,11303,11355,
+11349,11358,11350,11355,11304,11355,11307,11365,11349,11355,11303,11368,
+    5,11355,    7,11372,11276,11374,11277,11375,11377,11379,11276,11375,
+11277,11374,11383,11385,    7,11355,    5,11388,11276,11390,11277,11391,
+11393,11395,11276,11391,11277,11390,11399,11401,    5,11354,    7,11404,
+11277,11407,    7,11405,    7,11354,11087,11413,    5,11412,11277,11417,
+11307,11413,11277,11413,    4,11354,11373,11425,    7,11427,11277,11429,
+   10,11354,11087,11433,11307,11433,11277,11433,   10,11355,11349,11441,
+11277,11440,11307,11445,11277,11441,11303,11449,    4,11355,11410,11453,
+11277,11455,    7,11453,11405,11458,11277,11461,11276,11458,11277,11459,
+11405,11467,11465,11467,11276,11459,11277,11458,11473,11475,11405,11453,
+    7,11478,11277,11481,    1,11452,    1,11355,    4,11486,   67,11355,
+ 1275,11355,    9,11493,11485,11495,11489,11495, 7947,11355,   11,11501,
+11277,11503,11277,11355,   10,11506,11307,11509,   10,11507,11349,11513,
+   11,11354,11326,11517,11277,11517, 7947,11520, 7947,11517,11277,11524,
+    3,11051, 8213,11529, 8052,11529, 7971,11529,  113,11534,  113,11529,
+ 7971,11538, 8241,11529, 7947,11528,  483,11529,  112,11051,11326,11549,
+11277,11549, 7947,11552, 7947,11549,11277,11556,   67,11050,11187,11561,
+11053,11561,11179,11561,   66,11051,  113,11050,11556,11571,11185,11571,
+11549,11571, 7947,11576,   25,11570, 3867,11581, 7947,11571,11549,11584,
+   25,11571, 3933,11589, 7947,11051,  113,11592,11083,11595,11251,11595,
+  113,11593,11549,11601,    3,11593,11549,11605,11517,11605,    3,11592,
+   11,11051, 8116,11613, 8099,11613,11272,11613,11561,11613,11491,11613,
+11251,11613,   25,11624, 8074,11613, 8093,11629,   25,11613,11251,11632,
+ 8109,11613, 8063,11636, 8063,11613, 8109,11640, 7957,11612,11277,11645,
+ 6625,11613,  113,11613,    2,11613,11183,11653,11545,11653,11611,11653,
+11529,11653, 7947,11661,    3,11613, 7971,11664, 8093,11667, 7971,11665,
+ 8109,11671,    2,11612,11605,11675,11326,11675,11277,11675, 7947,11680,
+ 7947,11675,11277,11684, 7971,11613,    3,11688, 8093,11691,    3,11689,
+ 8063,11695,   11,11050,11355,11699,  113,11701, 1369,11699,11251,11705,
+   33,11699,11251,11709,    3,11698, 8251,11713, 3807,11713,11433,11713,
+11413,11713, 9875,11713, 8165,11713,    3,11699, 8241,11727,    0,   11,
+ 8095,11731, 8112,11731, 6688,11731, 6285,11731,  203,11730, 2351,11741,
+ 8159,11731, 8162,11731, 8128,11731, 8114,11731, 8097,11731, 8118,11731,
+ 8100,11731,    5,11730, 1369,11759, 8116,11731,    9,11762, 8099,11731,
+    9,11766,  181,11731,   98,11731, 5019,11773, 8058,11731, 8093,11777,
+ 8156,11731, 8093,11781, 8076,11731, 8093,11785,   30,11731, 8124,11731,
+ 8063,11790, 8072,11731, 8109,11794, 8063,11731, 8161,11798, 8124,11798,
+ 8109,11798,    9,11804,    9,11798, 8109,11808,   25,11731, 6685,11812,
+    9,11812,   89,11731, 5019,11819,   21,11821,   21,11818, 5019,11825,
+ 2759,11731, 2789,11731, 2821,11731, 6658,11731, 6685,11731,   25,11836,
+ 4413,11731,  113,11731,    9,11842,  128,11731,  659,11731,  623,11731,
+  645,11731,  705,11731,  299,11731,  828,11731,  394,11731,  241,11731,
+  375,11862,  483,11731,  803,11866, 8074,11731, 8093,11871,    9,11873,
+    9,11870, 8093,11877,  101,11731,   21,11731,   89,11882, 5019,11885,
+   89,11883, 5045,11889, 8061,11731, 8109,11892,  803,11731,  483,11896,
+  375,11731,  241,11900,  587,11901, 6625,11731,    9,11906, 6789,11731,
+    2,11911, 6855,11913, 1369,11730,  587,11730,  375,11919, 8109,11731,
+ 8061,11922, 8072,11922, 8063,11922,    9,11928,    9,11922, 8063,11932,
+  145,11731,  903,11730,  375,11939,  265,11731, 8161,11731, 8063,11944,
+    2,11730, 8124,11949, 8804,11949, 3972,11949, 8150,11949, 8495,11949,
+    9,11958, 7971,11949,    9,11962, 3933,11949,    9,11966,    9,11949,
+ 8109,11970, 8495,11970, 3933,11970, 7971,11970, 8109,11949,    9,11980,
+    3,11730,  483,11985,    2,11731, 8075,11989,    9,11991,    3,11731,
+ 8151,11994,    5,11995,    6,11999,    0,11998,    0,11995,    5,12004,
+ 8150,11994, 8093,12009, 7971,11994, 8093,12013,    9,12015,    9,12012,
+ 8093,12019, 1369,11995,   11,12023,12003,12025,12007,12025, 7971,11995,
+ 8161,12031,11997,12031, 8124,12031, 8109,12031,    9,12038,    9,12031,
+ 8109,12042,    9,11994, 7971,12046, 8093,12049, 7971,12047, 8109,12053,
+   89,11730, 5082,12057, 2969,12057, 5045,12057,   21,12062,   21,12057,
+ 5045,12066,   88,11731, 7971,12070, 8093,12073, 7971,12071, 8109,12077,
+ 8150,11731,    3,12080, 8093,12083,    3,12081, 8063,12087, 7971,11731,
+ 1368,12091,  264,12090,12093,12095,    5,12090,    3,12099,    3,12098,
+12093,12103, 1369,12099,    7,12091,    2,12108,12103,12111,12095,12111,
+    2,12109,12101,12117,  265,12109,  265,12090, 1369,12091,12123,12125,
+   88,12090, 8093,12129,   88,12091, 8061,12133,    2,12091,12001,12137,
+    7,12136,12103,12141,12095,12141,    9,12137,    3,12091, 8061,12149,
+ 8072,12149,12121,12149, 8063,12149,    9,12156,    9,12149, 8063,12160,
+    2,12090,12107,12165,12149,12165,    9,12169,    3,12090,    5,12173,
+    6,12175,12137,12177,12146,12173,    5,12172,12111,12183,12141,12183,
+12093,12183, 8093,12173,    9,12191,12137,12173,    9,12194,    9,12172,
+ 8093,12199,    9,12173,12137,12202,    9,12090,    3,12206, 8093,12209,
+    3,12207, 8063,12213,    9,11731, 8116,12216, 8099,12216, 8074,12216,
+ 8093,12223,   25,12216, 8109,12216, 8063,12228, 8063,12216, 8109,12232,
+ 6625,12216,  113,12216,    3,12216, 7971,12240, 8093,12243, 7971,12241,
+ 8109,12247, 7971,12216,    3,12250, 8093,12253,    3,12251, 8063,12257,
+    0,    9,  192,12261, 2329,12263,  211,12261, 2419,12267,  211,12260,
+ 2433,12271,  192,12260, 2337,12275,  189,12260, 2337,12279,    4,12261,
+    7,12282,  413,12260,  413,12261, 1216,12260, 1216,12261, 1086,12261,
+ 9617,12295,  137,12261,  587,12261, 1011,12300, 9617,12303, 1011,12301,
+ 9565,12307, 1011,12261, 9617,12311,  587,12313,  587,12310, 9617,12317,
+ 1011,12260, 5267,12321, 9600,12321, 9565,12321,  587,12326,  587,12321,
+ 9565,12330,  587,12260, 5231,12335, 5181,12335,10505,12335, 1275,12261,
+    2,12260,10001,12345,    5,12347,    4,12346,12349,12351,    4,12347,
+    5,12346,12355,12357,    3,12260,11243,12361,11251,12361, 5177,12361,
+ 5185,12361,    2,12261,    3,12261,11355,12373,    1,  265,  471,12376,
+ 2647,12379,  357,12376, 1785,12383,  586,12377,  375,12387,  586,12376,
+  413,12377,    3,12377,    7,12394,  375,12397,    7,12395,  331,12401,
+  483,12395,   15,12405,    5,12377,   17,12409,  587,12411,    3,12376,
+  669,12415, 1418,12415,12413,12415, 1369,12415,   15,12422,   15,12415,
+ 1369,12426,    5,12376,12417,12431, 1419,12431,12415,12435,  668,12431,
+12415,12439,12419,12431,12407,12431,12429,12431,    9,12431,  587,12448,
+12415,12451,12425,12431,  587,12431,    9,12456,12415,12459, 6719,12377,
+    9,12463, 7867,12377,  251,12467, 3357,12377, 3681,12377, 3709,12377,
+ 2647,12377, 5843,12377, 4407,12377,11917,12377,  305,12377,  713,12377,
+   25,12377, 4405,12377, 7041,12377,  251,12493, 1471,12376, 2011,12497,
+   53,12376, 2035,12501,  257,12377,  253,12376, 5325,12507,  251,12376,
+ 7867,12511, 7617,12511, 7041,12511, 7617,12377,  251,12519, 1363,12376,
+ 5189,12523,  483,12377,    9,12377, 8938,12377,  375,12531, 5313,12377,
+ 7035,12377, 7091,12537, 7083,12537, 7123,12537,  241,12537,   11,12376,
+ 5313,12547,  587,12376,12387,12551,11731,12551,    9,12376, 5019,12557,
+12361,12557, 1369,12376,   11,12377,  587,12377,12391,12567,    7,12376,
+    2,12571,    4,12572,12537,12575,    4,12571,    2,12578,12537,12581,
+12545,12571,  240,12571,12537,12587, 8948,12571,  331,12571, 8861,12592,
+ 8861,12571,  331,12596, 4827,12571,    6,12377,  257,12603,  265,12605,
+  241,12603,    1,12609,12607,12611,    7,12377,    3,12614,  375,12617,
+ 8861,12614,  375,12621,  375,12615, 8861,12625,  241,12614,  375,12629,
+  257,12376, 2647,12633, 1783,12633,  256,12377,  375,12639, 8861,12377,
+  261,12643,  260,12643,  256,12643,    6,12643,  241,12650,    7,12643,
+  241,12654,  331,12655,    6,12642,12645,12661,    7,12642,12647,12665,
+12653,12665,  375,12665,  241,12643,    6,12672,12665,12675,    7,12672,
+    6,12673,12679,12681,12655,12681,    7,12673,12675,12687,  241,12377,
+    7,12691,  331,12693,    7,12690,  375,12697, 8997,12691,    7,12701,
+  241,12376, 4457,12705,  374,12705, 5189,12705,  265,12705,    6,12712,
+ 8386,12705,    6,12705,  265,12718,    7,12705, 8337,12722, 8337,12705,
+    7,12726, 8861,12705,    6,12731,    7,12731,    6,12730,12735,12737,
+    7,12730,12733,12741,    1,  241,  448,12745, 4349,12747,  445,12744,
+ 1679,12751,  457,12744, 4371,12755, 8461,12744, 8475,12759,  277,12744,
+ 4457,12763,  923,12744, 4959,12767, 8388,12744, 8389,12744,    4,12745,
+   11,12775, 1369,12777,    2,12745, 1275,12781,    9,12783,    2,12744,
+ 1419,12787,  668,12787,12779,12787,  587,12787,    9,12794,    9,12787,
+  587,12798,    4,12744,12789,12803,  669,12803,12787,12807, 1418,12803,
+12787,12811,12791,12803,12785,12803,12801,12803,   15,12803, 1369,12820,
+12787,12823,12797,12803, 1369,12803,   15,12828,12787,12831,  445,12745,
+  265,12834, 4349,12837,  923,12745, 5009,12841, 8374,12745,  346,12745,
+ 2981,12847,  386,12745,  387,12745, 3049,12853,  347,12745, 8389,12745,
+12771,12859, 1412,12745, 5227,12863,  346,12744, 2977,12867,12857,12867,
+  386,12744, 4067,12873,12853,12873, 1412,12744, 5189,12879,  374,12744,
+12845,12883,  387,12744, 3043,12887,12851,12887,  347,12744,12847,12893,
+  272,12745, 4453,12897, 4437,12897, 1755,12897, 8388,12745, 8495,12905,
+12773,12905, 8387,12745,  265,12911, 8861,12913,  265,12910, 8495,12917,
+  253,12745,   59,12744, 1325,12744,  341,12745,  375,12745,12883,12929,
+ 8337,12931, 8337,12928,12883,12935, 4371,12745,  457,12939,  375,12939,
+ 4531,12745,  375,12945, 8366,12745,  375,12949,  305,12744, 4457,12953,
+  375,12952, 4067,12957, 4067,12953,  375,12961,  331,12744, 4457,12965,
+12927,12965, 8386,12745, 8495,12971,  331,12971, 1325,12971,   59,12971,
+  265,12971, 8375,12745, 8495,12983,  305,12745,12887,12987, 4266,12987,
+ 3031,12987, 4213,12987,  375,12994, 8337,12986,  375,12999,  375,12987,
+ 4213,13002, 5325,12745,    7,13007, 5361,13009, 5385,13009, 5407,13009,
+ 1275,12744,   15,12744, 8475,12745,  375,13021, 8461,13021,    6,12744,
+ 8429,13027, 8428,13027, 4139,13027, 4138,13027,    3,13026,    5,13036,
+    5,13026,    3,13040,  264,13026,13031,13045,13035,13045,  264,13027,
+ 8401,13051, 4137,13051,  265,13026, 8401,13057,13051,13058,13029,13057,
+13052,13057, 4137,13057,13051,13066,13033,13057,13054,13057,13051,13057,
+ 8401,13074, 4137,13074, 4137,13027,  265,13081,13051,13083,  265,13080,
+13045,13087,  341,13027,  265,13027, 8401,13092,13045,13095, 4137,13092,
+13045,13099,13045,13093, 8401,13103, 4137,13103, 8401,13027,  265,13109,
+13051,13111,  265,13108,13045,13115,    7,12744, 8605,13119, 8374,13119,
+ 8916,13119, 8389,13119,  412,13119,  241,13119,  265,13130,  264,13118,
+  264,13119, 8452,13119, 8647,13119,  265,13118,13137,13143, 8861,13119,
+  375,13146, 8337,13119,  375,13150,  265,13150,  305,13119,  713,13119,
+   25,13119,  375,13119, 8861,13162, 8337,13162,  265,13119,  241,13168,
+13135,13169, 8337,13168,    6,12745,12965,13177,13145,13177,13139,13177,
+ 8453,13177,13119,13185,12923,13177,12925,13177,13135,13177,13169,13192,
+13172,13177,13136,13177,13143,13199,13175,13177,13155,13177,13169,13177,
+13135,13206,    3,13177,    5,13210,13118,13212,13119,13213,13215,13217,
+13118,13213,13119,13212,13221,13223,    5,13177,    3,13226,13118,13228,
+13119,13229,13231,13233,13118,13229,13119,13228,13237,13239,  264,13177,
+13119,13242,13143,13245,13119,13243,13135,13249,  413,13177, 8452,13177,
+ 8861,13255,  305,13177, 8337,13177,  265,13260, 8861,13263,  265,13261,
+ 8495,13267,  265,13177, 8337,13270, 8861,13273, 8861,13271, 8337,13277,
+13119,13177,  264,13280,13143,13283,  264,13281,13169,13287,  265,13280,
+13287,13291,  265,13281,13283,13295, 8387,13177,  264,13299,  265,13298,
+13301,13303,  264,13298,  265,13299,13307,13309,  265,13176, 8842,13313,
+ 8495,13313, 8337,13316, 8337,13313, 8495,13320,    7,12745,13039,13325,
+13043,13325,13045,13325,  241,13324,    0,13333, 8717,13325, 8495,13325,
+ 8337,13339,  305,13339, 4311,13325, 4329,13325, 3785,13325,10351,13325,
+10055,13325, 8337,13324, 8495,13355,  331,13355, 1325,13355,   59,13355,
+  265,13355,   59,13325, 8337,13367, 1325,13325, 8337,13371,  331,13325,
+ 8337,13375, 8861,13375,  265,13325,13051,13381,13335,13381, 5325,13381,
+    1,13381,13333,13389, 8861,13381, 8337,13381,13027,13325,  264,13396,
+  264,13397,  265,13396,13401,13403,  265,13397,13399,13407,  265,13324,
+ 8717,13411, 3785,13411,13045,13411, 8495,13411,  374,12745, 8842,13421,
+ 8495,13421, 8337,13424, 8337,13421, 8495,13428,  340,12745, 8717,13433,
+13045,13433, 3785,13433, 8495,13433,  375,12744, 4371,13443,13428,13443,
+12983,13443, 8475,13443,13421,13443, 8337,13452,  305,13442, 4067,13457,
+ 8337,13443,13421,13460,  305,13443, 4213,13465, 8452,12745, 8647,13469,
+    7,13469, 8495,13473, 8337,12745,  375,13476,12883,13479,  375,13477,
+  305,13483,13421,13483,  305,13476,  375,13489,    6,13477, 8453,13493,
+ 8452,13492,13495,13497, 8452,13493, 8453,13492,13501,13503,    7,13477,
+13213,13507,13229,13507,  375,13507,13243,13507,  265,13507,13177,13517,
+    6,13476,    3,13521,    5,13522,13507,13525,    5,13521,    3,13528,
+13507,13531,13517,13521,  264,13521,13507,13537,    7,13476, 8495,13541,
+  331,13541, 1325,13541,   59,13541,  265,13541,  265,13476, 8647,13553,
+    7,13553, 8495,13557,  265,13477,13177,13561,13521,13561,    7,13561,
+  265,12745,  445,13568, 4349,13571,  445,13569, 4371,13575, 8770,13569,
+ 8729,13569,13027,13569,  375,13583, 8684,13569, 8717,13587,  331,13569,
+13177,13591, 8757,13569, 8647,13594, 8647,13569, 8757,13598, 8387,13568,
+ 8495,13603,    6,13569,    7,13569, 8647,13609, 8495,13608, 8717,13613,
+ 8495,13609, 8757,13617,    6,13568, 8842,13621, 8495,13621, 8337,13624,
+13609,13621, 8337,13621, 8495,13630,    7,13568, 8717,13635, 3785,13635,
+13045,13635, 8495,13635,13607,13635, 8337,13568, 8647,13647,    7,13647,
+ 8495,13651, 8495,13569,    6,13654,    7,13654, 8717,13659,    6,13655,
+13659,13663,    7,13655,13657,13667, 8647,13667,  265,12744,13258,13673,
+12845,13673,13091,13673,12935,13673,12927,13673,12929,13673, 8337,13685,
+13479,13673,12911,13673,13260,13673,12859,13673, 4457,13673, 5189,13673,
+13177,13673,  305,13700, 8337,13700,  305,13673,13177,13706, 8386,13673,
+    7,13673, 8337,13712, 8861,13673,    6,13717,    7,13717,    6,13716,
+13721,13723,    7,13716,13719,13727, 8337,13673,13177,13730,    7,13730,
+    1,  587,  264,13737,  375,13739,   16,13737,  264,13736,  341,13745,
+    7,13737,    4,13748,    4,13749,    3,13736,  717,13755,  341,13755,
+    6,13755,  713,13761,   17,13755,  566,13736, 1108,13737, 9565,13769,
+11731,13737,  265,13772,11942,13737, 3565,13737, 3573,13737, 3273,13737,
+  375,13736,  113,13736, 4696,13787,    9,13787, 4669,13790, 4669,13787,
+    9,13794, 1011,13737, 9565,13799,    9,13801,    9,13798, 9565,13805,
+  241,13737,    9,13737, 1011,13810, 9565,13813, 1011,13811, 9617,13817,
+  113,13737, 4727,13821,    9,13823, 7049,13737,  807,13827,  375,13827,
+  265,13736,11731,13833, 1487,13737, 1011,13736, 5293,13839, 9704,13839,
+ 9617,13839,    9,13844,    9,13839, 9617,13848,  265,13737,11731,13852,
+    4,13736,13757,13857,13762,13857,13761,13857,  713,13862,13759,13857,
+  340,13857,13745,13869,13747,13857,13740,13857,  375,13857,13739,13876,
+    7,13857,  265,13880,13745,13883,  265,13881,13739,13887,13739,13857,
+  375,13890,  713,13857,13761,13894,  265,13857,    7,13898,13745,13901,
+  483,13857,    5,13736,13853,13907,  375,13909,  483,13906,    4,13737,
+    7,13914,  767,13915,13761,13919,    5,13737,    3,13923,    1,13924,
+    1,13923,    3,13928,   17,13923,  587,13933,13927,13935,13931,13935,
+  567,13736,  483,13736,    5,13942,    1,  483, 9174,13946, 9175,13946,
+    2,13947,    7,13952,    2,13946,    7,13957,    6,13946, 9170,13947,
+ 9175,13947,13949,13965,  824,13946, 3997,13969,  802,13946,13963,13973,
+  766,13946,  825,13946, 9174,13947,13951,13981,  803,13947,13973,13985,
+ 9165,13987, 9165,13984,13973,13991,  713,13946,  803,13994, 3997,13997,
+ 3997,13995,  803,14001, 1171,13946, 4663,14005,  903,14007,  155,13946,
+ 9172,13947, 9171,13947,  713,13947,13979,14017, 4200,14017, 3027,14017,
+ 4147,14017,  803,14024,  803,14017, 4147,14028, 1171,13947, 4722,14033,
+  903,14033, 4713,14036, 4713,14033,  903,14040,  257,13947,    9,14045,
+    9,13946,  257,14049,  903,13946,  257,14053,   11,13946, 5197,14057,
+ 5125,14057,12335,14057,    4,13946,    2,14065,    7,14067,14013,14069,
+    5,13946,13958,14072,13959,14073,14075,14077,13958,14073,13959,14072,
+14081,14083,  586,14072,  586,14073,  587,14072,14089,14091, 4827,14073,
+    9,14073, 4569,14073, 4745,14073,  587,14073,14087,14103,    4,13947,
+14093,14107,14087,14107,14103,14110,14104,14107,14088,14107,14091,14117,
+14103,14107,14087,14120,    3,14107,    7,14124,14072,14126,14073,14127,
+14129,14131,14072,14127,14073,14126,14135,14137,    7,14107,    3,14140,
+14072,14142,14073,14143,14145,14147,14072,14143,14073,14142,14151,14153,
+    3,14106,    7,14157,    2,14106,14125,14161,    7,14163,14073,14165,
+  586,14107,14073,14168,14091,14171,14073,14169,14087,14175,    2,14107,
+14158,14179,14073,14181,    7,14179,14157,14184,14073,14187,14073,14185,
+14157,14191,14157,14179,    7,14194,14073,14197,14073,14107,  586,14200,
+14091,14203,  586,14201,14103,14207,    5,13947,14069,14211, 9165,14213,
+    6,14211, 9165,14210,14069,14219,   17,14211,  802,13947, 9165,14225,
+  803,13946,14226,14229,14015,14229,14225,14229, 9165,14234,  713,14228,
+ 3997,14239, 9165,14229,14225,14242,  713,14229, 4147,14247, 9165,13947,
+  803,14250,13973,14253,  803,14251,14225,14257,    4,14251,    2,14261,
+    7,14263,    5,14250,14265,14267,14069,14267,  587,13947, 9340,14273,
+ 9323,14273, 9290,14273, 9317,14279, 9335,14273, 9287,14282, 9287,14273,
+ 9335,14286,    5,14273, 9195,14290, 9317,14293, 9195,14291, 9335,14297,
+ 9195,14273,    5,14300, 9317,14303,    5,14301, 9287,14307,  587,13946,
+    5,14310,    0,  265,  446,14315, 4371,14317,  445,14314, 1675,14321,
+ 8725,14315, 8766,14315,  471,14314, 2367,14329, 8827,14315, 8836,14315,
+  319,14314, 4497,14337, 1302,14315,  667,14315, 8794,14315, 8768,14315,
+ 8727,14315, 8774,14315, 8732,14315, 1011,14315, 1275,14354,    3,14315,
+ 1369,14359,   11,14361,    5,14315,    9,14365, 1275,14367,    3,14314,
+ 1291,14371,  524,14371,14369,14371,  483,14371,   11,14378,   11,14371,
+  483,14382,    5,14314,  525,14387,14371,14389,14373,14387,14375,14387,
+ 1290,14387,14371,14397,14363,14387,14385,14387,14381,14387,   17,14387,
+ 1275,14406,14371,14409, 1275,14387,   17,14412,14371,14415, 8770,14315,
+  241,14418, 8729,14315,  241,14422,  445,14315,  241,14426, 4371,14429,
+ 1303,14315,  666,14315, 8784,14315, 4266,14315, 8622,14315, 8717,14441,
+ 8824,14315, 8717,14445, 8702,14315, 8717,14449,  256,14314, 7185,14453,
+ 2309,14453, 5673,14453, 5521,14453,  375,14461, 4213,14315,  375,14464,
+  316,14315, 4533,14469, 1757,14469, 8697,14315,  629,14315,  407,14315,
+ 5325,14479, 3121,14315, 3031,14315, 5519,14315, 3355,14315,  510,14315,
+ 8788,14315, 8647,14492, 8676,14315, 8757,14496, 8647,14315, 8831,14500,
+ 8788,14500, 8757,14500,  241,14506,  241,14500, 8757,14510,  331,14315,
+ 1325,14315,   59,14315, 5521,14315,  375,14521,  375,14315, 4213,14524,
+ 8757,14524,   53,14525, 1471,14525,  253,14525,  253,14314, 4425,14537,
+ 4497,14537,  483,14315,    9,14542,    9,14315,  483,14546, 8684,14315,
+ 8717,14551,  241,14553,  241,14550, 8717,14557,  331,14551,  251,14315,
+  257,14563, 8495,14565, 8635,14315, 8757,14568, 5515,14315,  331,14573,
+ 8757,14315, 8635,14576, 8676,14576, 8647,14576,  241,14582,  375,14576,
+  241,14576, 8647,14588, 1369,14314, 2853,14593,   15,14315, 1275,14315,
+ 1011,14598,  587,14315,  241,14602, 8831,14315, 8647,14606,    6,14314,
+14341,14611,14343,14611,14601,14611,14357,14611, 8495,14611,  241,14611,
+    7,14314,14433,14625,14435,14625,14605,14625, 8495,14625, 3785,14625,
+10055,14625,10351,14625, 4329,14625, 4311,14625, 4555,14625,14073,14625,
+ 4971,14625, 8717,14625,    7,14315, 8813,14652,14623,14653, 8495,14657,
+    4,14653,    2,14660,14620,14663, 8495,14663,14611,14666,14611,14663,
+ 8495,14670,    2,14653,    4,14674,14620,14677, 8495,14677,14611,14680,
+14611,14677, 8495,14684,  240,14653,14620,14689, 8495,14689,14611,14692,
+14611,14689, 8495,14696, 8812,14652, 8717,14701, 8495,14652, 8717,14705,
+  241,14707,  241,14704, 8717,14711,  331,14705,   15,14653,  483,14717,
+ 1275,14653,    9,14721, 8495,14653, 8831,14725,14655,14725, 8788,14725,
+ 8757,14725,  241,14732,  241,14725, 8757,14736,  375,14653, 8647,14653,
+  241,14652, 8647,14745, 8495,14744, 8717,14749, 8495,14745, 8757,14753,
+  257,14314, 8614,14757, 4417,14757, 8495,14757,  251,14762,  251,14757,
+ 8495,14766,  256,14315, 8647,14771, 7207,14771, 5432,14771, 5325,14771,
+  375,14778, 8495,14770, 8717,14783,  375,14771, 5325,14786, 8495,14771,
+ 8757,14791, 8812,14315,    6,14794,    7,14794, 8717,14799,    6,14795,
+14799,14803,    7,14795,14797,14807, 8647,14807, 8495,14315,  261,14812,
+  260,14812,  256,14812, 8717,14819,  256,14813, 8635,14823,    6,14813,
+14815,14827,    7,14813,14817,14831, 8635,14831, 8676,14831, 8647,14831,
+  241,14838,  375,14831,  241,14831, 8647,14844,    6,14812,  241,14848,
+14831,14851,    7,14812, 8717,14855,  241,14857,  241,14854, 8717,14861,
+  331,14855,  241,14812,    6,14866,14831,14869,    7,14866, 8717,14873,
+    6,14867,14873,14877,14855,14877,    7,14867,14869,14883, 8647,14883,
+  241,14315,  445,14888, 4371,14891,  445,14889, 4349,14895, 8770,14888,
+ 8729,14888,  587,14888,14625,14903, 8684,14888, 8717,14907, 8757,14888,
+ 8647,14910, 8387,14889, 8495,14915, 8647,14888, 8757,14918,    6,14889,
+ 8842,14923, 8495,14923, 8337,14926, 8337,14923, 8495,14930,    7,14889,
+ 8717,14935, 3785,14935, 8495,14935,    6,14888,14935,14943,    7,14888,
+ 8647,14947, 8495,14946, 8717,14951,14923,14947, 8495,14947, 8757,14957,
+ 8495,14888,    6,14960,    7,14960, 8717,14965,    6,14961,14965,14969,
+    7,14961,14963,14973, 8647,14973, 8337,14889, 8647,14979,    7,14979,
+ 8495,14983,12745,14315,  375,14987,  241,14314, 9099,14991, 9036,14991,
+ 8647,14991, 8997,14996, 5521,14991,  375,15001,  375,14991, 9082,14991,
+ 8495,15007,    7,14991, 8495,15011, 8997,15013, 8997,15010, 8495,15017,
+ 8997,14991, 8647,15020,    7,15020, 8495,15025,    0,  241,  460,15029,
+ 2315,15031,  479,15029, 2393,15035,  479,15028, 2397,15039,  460,15028,
+ 2317,15043,  457,15028, 2317,15047,  269,15028, 2885,15051,  464,15029,
+   16,15029,  413,15029,    6,15058,    4,15029,    7,15062,    7,15063,
+   15,15063,  483,15069,    2,15029,  587,15073,   17,15075,    2,15028,
+  525,15079, 1290,15079,15071,15079, 1275,15079,   17,15086,   17,15079,
+ 1275,15090,    4,15028, 1291,15095,15079,15097,15081,15095,15083,15095,
+  524,15095,15079,15105,15077,15095,15093,15095,15089,15095,   11,15095,
+  483,15114,15079,15117,  483,15095,   11,15120,15079,15123, 9072,15029,
+  305,15127, 9105,15029,  305,15131, 9083,15029,  413,15135,  412,15134,
+15137,15139,  412,15135,  413,15134,15143,15145, 3445,15029,  375,15149,
+12526,15029,12528,15029,  251,15029,  375,15029,  305,15159, 8997,15161,
+ 8997,15158,  305,15165,12614,15029,  375,15169, 7065,15029,  265,15173,
+ 7259,15175,  305,15028, 9105,15179, 9072,15179,  375,15179, 8997,15184,
+ 8997,15179,  375,15188, 9082,15029,  375,15193,  265,15193, 5521,15029,
+  375,15199,  265,15199,  483,15029,12377,15204,    9,15029,12377,15208,
+   17,15029,13737,15029,  375,15215,    6,15028,    3,15219,    5,15220,
+15193,15223,    5,15219,    3,15226,15193,15229,15197,15219,15057,15219,
+    3,15235,    2,15234,15237,15239,    2,15235,    3,15234,15243,15245,
+15065,15219,    3,15249,    2,15248,15251,15253,    2,15249,    3,15248,
+15257,15259,  264,15219,15193,15263, 8997,15219,    7,15028, 4437,15269,
+15213,15269,    3,15273,    2,15272,15275,15277,    2,15273,    3,15272,
+15281,15283,12571,15269, 4805,15269, 4613,15269,14073,15269,  375,15269,
+  510,15269, 4971,15269,  483,15269,    9,15300,    9,15269,  483,15304,
+    6,15029, 9020,15309, 9021,15309,12393,15309,12392,15309, 8337,15309,
+  265,15318, 8452,15308,  241,15322, 8453,15309,15325,15327, 8452,15309,
+ 8453,15308,  412,15309, 8997,15335,  241,15308,  265,15338,15327,15341,
+ 8452,15339,15333,15345,15067,15309,    3,15349,    2,15348,15351,15353,
+    2,15349,    3,15348,15357,15359,  413,15308,15313,15363,15315,15363,
+15331,15363,15321,15363, 8997,15363,15335,15372,15336,15363,15335,15363,
+ 8997,15378,  412,15308,15311,15383,15317,15383,15327,15383,  413,15309,
+12377,15390,15383,15393, 8997,15390,15383,15397,15383,15391, 8997,15401,
+12377,15309,  413,15404,15383,15407,  413,15405,15335,15411, 8997,15309,
+  413,15414,15383,15417,  413,15415,15335,15421,  265,15309, 8337,15424,
+15363,15427,  265,15308,  241,15430,15327,15433,    7,15029,15223,15437,
+ 8997,15439,15229,15437, 8997,15443,15263,15437, 8997,15447,    4,15436,
+15219,15451,    3,15453,    2,15452,15455,15457,    2,15453,    3,15452,
+15461,15463,  264,15436,  264,15437,12377,15436,  375,15471, 8997,15436,
+15223,15475,15229,15475,  375,15475,15263,15475,  265,15475,15219,15485,
+   59,15437, 1325,15437,  331,15437, 1275,15437,    9,15495,   15,15437,
+  483,15499,  265,15437,15266,15503,15219,15503, 8997,15506,15467,15503,
+ 8997,15503,15219,15512,  305,15503,  265,15436,15469,15519,  331,15519,
+  375,15028, 3307,15525, 2885,15525,12511,15525,12377,15525,  251,15533,
+  340,15029,  331,15537, 9136,15029,    7,15541, 8997,15029,  375,15544,
+  305,15547,  305,15545,  375,15551,    6,15545,    3,15555,    5,15556,
+    5,15555,    3,15560,  264,15555,    7,15545, 8495,15567,  331,15567,
+ 1325,15567,   59,15567,  265,15567,    7,15544,15559,15579,15563,15579,
+15223,15579,15229,15579,  375,15579,15263,15579,15565,15579,  265,15579,
+15219,15595,15555,15595,  265,15544,15555,15601,    7,15601,  265,15545,
+ 8647,15607,    7,15607, 8495,15611,  265,15029,    7,15615,  375,15617,
+    7,15614,  331,15621, 8997,15614,    7,15625,12377,15029,13421,15629,
+13313,15629,13621,15629,14923,15629,12721,15629,12715,15629,12709,15629,
+  375,15629,12705,15645,    7,15629,  331,15649,  483,15628,    9,15628,
+    7,15628,  375,15657,  265,15028, 9036,15661, 9099,15661,  241,15661,
+    6,15667,15629,15669, 8647,15661, 8997,15672, 5521,15661,  375,15677,
+ 9082,15661, 8495,15681,  375,15661,    7,15661, 8495,15687, 8997,15689,
+ 8997,15686, 8495,15693, 8997,15661, 8647,15696,    7,15696, 8495,15701,
+    0,  587, 9319,15705, 9336,15705,  889,15704, 2373,15711, 9371,15705,
+ 9374,15705, 9350,15705, 9338,15705, 9321,15705, 9342,15705, 9324,15705,
+  578,15705,    3,15705,    6,15730,    7,15705,  567,15735, 9195,15737,
+    4,15735, 9366,15741,  483,15741, 9195,15744, 9195,15741,  483,15748,
+    7,15704, 9340,15705,  483,15754, 9323,15705,  483,15758,  579,15705,
+ 9272,15705, 9317,15765, 9368,15705, 9317,15769, 9294,15705, 9317,15773,
+  566,15704,15729,15777, 9348,15705, 9287,15780, 9288,15705, 9335,15784,
+ 9287,15705, 9373,15788, 9348,15788, 9335,15788,  483,15794,  483,15788,
+ 9335,15798,  567,15705,    9,15802,15777,15805,15777,15803,    9,15809,
+12377,15705,   11,15813,    9,15705,  567,15816,15777,15819,  567,15817,
+ 9290,15705, 9317,15825,  483,15827,  483,15824, 9317,15831, 9275,15705,
+ 9335,15834,  375,15705,   11,15839,   11,15704,  375,15843, 9335,15705,
+ 9275,15846, 9288,15846, 9287,15846,  483,15852,  483,15846, 9287,15856,
+    9,15704, 5231,15861, 5181,15861,10505,15861,14057,15861, 1011,15704,
+  375,15871, 9373,15705, 9287,15874,    4,15704, 9262,15879,  375,15879,
+ 9195,15882,    7,15879,  265,15887, 9195,15889, 9195,15879,  375,15892,
+  483,15879,    5,15704,    5,15705, 9367,15900, 9366,15900, 9317,15905,
+ 9195,15900, 9317,15909,  483,15911,  483,15908, 9317,15915, 9195,15901,
+ 9373,15919,15903,15919, 9348,15919, 9335,15919,  483,15926,  483,15919,
+ 9335,15930,  483,15900, 9195,15934, 9317,15937, 9195,15935, 9335,15941,
+  567,15704,15763,15945,    9,15945,  566,15705,15823,15951,15948,15951,
+15945,15951,    9,15956, 9195,15950, 9317,15961, 9195,15951, 9335,15965,
+    9,15951,15945,15968, 9366,15705,    5,15972, 9317,15975,    5,15973,
+ 9287,15979, 9195,15705,  566,15982, 9317,15985,  566,15983, 9275,15989,
+    5,15983, 9275,15993, 9288,15993, 9287,15993,  483,15998,  483,15993,
+ 9287,16002,    5,15982, 9317,16007,  483,16009,  483,16006, 9317,16013,
+  483,15982,    5,16016, 9317,16019,    5,16017, 9287,16023,  483,15705,
+ 9340,16026, 9323,16026, 9290,16026, 9317,16033, 9335,16026, 9287,16036,
+ 9287,16026, 9335,16040,    5,16026, 9195,16044, 9317,16047, 9195,16045,
+ 9335,16051, 9195,16026,    5,16054, 9317,16057,    5,16055, 9287,16061,
+    0,  483,  878,16065, 2327,16067,  899,16065, 2415,16071,  899,16064,
+ 2423,16075,  878,16064, 2331,16079,  875,16064, 2331,16083,  573,16064,
+ 2569,16087,    2,16064,   15,16091,  413,16064,  413,16065,  573,16065,
+ 2567,16099, 1216,16064, 1216,16065,  904,16065, 2263,16107, 6515,16065,
+    5,16111, 6539,16113,  903,16064, 4421,16117, 5285,16117, 2265,16117,
+    4,16064,    5,16064,    4,16065,    2,16129,    7,16131,    0,16130,
+    0,16129,    2,16136,   15,16129,  483,16141,16135,16143,16139,16143,
+ 9513,16065,    5,16149,16133,16151,    4,16148,    2,16155,    7,16157,
+16151,16159,    1, 1011,  996,16162,   14,16162,    5,16163,    6,16169,
+ 9617,16171,    2,16162, 9617,16175,16171,16176,16172,16175,16171,16175,
+ 9617,16182,    7,16175,16169,16187, 9617,16189,    5,16162,16186,16193,
+16175,16193,    7,16196,    7,16197,16187,16193,    6,16192,16195,16205,
+16199,16205,    7,16192,16203,16211,16175,16211,    3,16211,16162,16217,
+    3,16193,    7,16221,16162,16222,16162,16221,    7,16226,    7,16227,
+16205,16231,    6,16193,16201,16235,16214,16235,16175,16235,16211,16240,
+16211,16235,16175,16244,16225,16235,16229,16235,16219,16235,    7,16193,
+16175,16254,16205,16257,16205,16255,16175,16261, 9704,16163,  587,16265,
+ 5293,16163,  587,16269,  997,16162,  972,16162,16235,16275,    9,16275,
+14652,16163,  973,16163,16273,16283,16278,16283,    9,16283,16275,16288,
+16275,16283,    9,16292,  955,16162, 5241,16297, 1505,16162,    6,16301,
+    7,16300,16303,16305,    7,16301,    6,16300,16309,16311,   67,16162,
+16235,16315,    9,16163, 9617,16318,  587,16321,  587,16319, 9617,16325,
+   15,16162,  257,16163,    9,16331,    9,16162,  973,16335,16275,16337,
+  973,16334,  257,16335,  587,16162, 5293,16345, 9704,16345, 9617,16345,
+    9,16350,    9,16345, 9617,16354,    6,16162,    5,16358,    7,16162,
+16221,16362,16235,16365,16235,16363, 8647,16363,  903,16362,16235,16373,
+    6,16163,16329,16377,    7,16163,16167,16381,16205,16381,16361,16381,
+ 8717,16381,14315,16380, 4311,16381, 4329,16381, 3785,16381,10351,16381,
+10055,16381,  973,16162,    9,16402,  972,16163,16341,16407,16165,16407,
+16405,16407,16403,16407,    9,16415, 9617,16163, 1368,16418,   14,16418,
+    2,16418,    7,16425,16423,16427,    7,16424,    5,16418,    6,16433,
+16431,16435,16421,16435,    6,16432,16427,16441,    2,16419,16435,16445,
+16171,16445,    7,16445,16433,16451,    9,16418,  587,16455,  587,16419,
+    9,16459,    6,16418,    5,16462,16427,16465,    7,16418,    2,16468,
+16435,16471,14315,16163,    7,16474,   17,16475,  903,16162,    3,16480,
+    6,16483,    6,16482, 5241,16481, 1274,16480,   15,16480, 1275,16480,
+    6,16480,    3,16496,    5,16496,    7,16480,16485,16503,16235,16503,
+    6,16481,16495,16509,16493,16509,    7,16481,16499,16515,16501,16515,
+16487,16515,16205,16515,16361,16515,16491,16515,16167,16515,    1,  903,
+ 9542,16530, 9543,16530, 1274,16530,    3,16530, 9541,16539,    6,16538,
+    7,16538,    5,16545,16530,16547,    5,16539,    7,16551,16530,16552,
+16530,16551,    7,16556,    7,16557,16543,16561,    6,16539, 9533,16565,
+16545,16565,16555,16565,16559,16565,16549,16565,    7,16539,16543,16577,
+    4,16530,16576,16581,16543,16583,16539,16581,    7,16586,16543,16589,
+    7,16587,16565,16593,16545,16581,16565,16596,16565,16581,16545,16600,
+16568,16581,16579,16581,    7,16581,16539,16608,16543,16611,16539,16609,
+16545,16615, 1170,16530,16565,16619, 9541,16531,16535,16623,  559,16530,
+ 5241,16627,  767,16530,16565,16631,  165,16530,    6,16635,    7,16634,
+16637,16639,    7,16635,    6,16634,16643,16645, 9540,16531,16543,16649,
+16533,16649,16539,16649,16537,16649, 1275,16530,16623,16659, 9533,16659,
+  257,16531,  483,16665,  483,16530,  257,16669,   15,16530, 5241,16673,
+    6,16530,    3,16676,16649,16679,    7,16530,16541,16683,16566,16683,
+16551,16682,16565,16689,16565,16683, 9533,16692,  375,16683, 1011,16682,
+16565,16699, 9533,16683,16565,16702,15269,16683, 4827,16683,    6,16531,
+16662,16711,16659,16711, 9533,16714, 9533,16711,16659,16718,    7,16531,
+16539,16723, 9533,16725,16537,16723, 9533,16729, 1007,16723,16543,16723,
+ 9533,16735,16679,16723, 9533,16739,  331,16723, 1325,16723,   59,16723,
+ 9533,16722,16543,16749,16539,16749,16679,16749,16537,16749, 9533,16531,
+ 1275,16759,16711,16761,    7,16759,16565,16765,    7,16758,16539,16769,
+16543,16769,16679,16769,16537,16769,15029,16531,    7,16779, 1011,16530,
+    5,16782,    6,16785,    6,16784, 5241,16783,   14,16782, 1275,16782,
+   15,16782,    6,16782,    5,16798,    3,16798,    7,16782,16787,16805,
+16565,16805,    6,16783,16797,16811,16795,16811,    7,16783,16801,16817,
+16803,16817,16789,16817,16543,16817,16679,16817,16793,16817,16537,16817,
+    1, 1369, 1010,16833,   16,16833,    2,16833,    5,16838,    5,16839,
+16837,16843,    7,16833,    4,16846,16843,16849,    4,16847,16841,16853,
+16835,16853,    2,16832,   11,16859,15900,16833,  331,16832,   59,16832,
+ 6717,16833,    9,16869, 1325,16832,  265,16832,    4,16833,    7,16876,
+16843,16879,    2,16877,    1,16882,    1,16877,    2,16886,   11,16877,
+ 1369,16891,16885,16893,16889,16893,    5,16833,    2,16898,16853,16901,
+15705,16898, 1275,16898,    9,16907, 1346,16833,    9,16911,15705,16833,
+   11,16915,    5,16914, 1275,16833,    5,16921,   17,16923,    5,16920,
+    9,16927, 1275,16832, 6717,16931,    9,16933,    1, 1275, 5814,16937,
+  902,16937,  902,16936,    3,16937,    7,16944,  413,16937, 1216,16937,
+ 6787,16937,    5,16953,    4,16952,16955,16957,    4,16953,    5,16952,
+16961,16963, 1505,16937, 5771,16937,  903,16968, 1011,16937,  903,16972,
+  903,16936,16941,16977,  241,16936,   17,16936, 5299,16983, 4915,16983,
+   11,16936,  903,16937, 5771,16990,16943,16991, 1011,16990,15208,16937,
+    9,16937,15029,17000,15029,16937,    9,17004,    4,16936,  265,17009,
+    5,16936,    4,16937, 1011,17015, 1369,16936, 6717,17019,    9,17021,
+    1,   17,    4,17025,    6,17026,  113,17025, 1275,17024, 5299,17033,
+ 4915,17033,  241,17025,    2,17024,    3,17024,11731,17025,  265,17045,
+    1,   15, 5886,17049,    5,17048,  483,17053,  413,17049, 1216,17049,
+  165,17049, 5843,17049, 1011,17062,14315,17049,   17,17067,  903,17049,
+ 1011,17070, 1011,17048,  241,17048,  903,17048, 5241,17079, 1011,17049,
+ 5843,17082,  903,17082,15204,17049,  483,17049,15029,17090,15029,17049,
+  483,17094,    3,17048,  483,17099,    2,17049,    3,17049,    5,17105,
+    1,17106,    1,17105,    5,17110,  483,17105,   15,17115,17109,17117,
+17113,17117, 1369,17105,    0, 1011,    2,17125,    7,17127, 9565,17129,
+    5,17124, 9565,17133,17129,17134,17130,17133,17129,17133, 9565,17140,
+    6,17133,17127,17145, 9565,17147, 9600,17125,    9,17151, 5267,17125,
+    9,17155,16722,17125,10385,17125,    9,17161,  587,17125, 9565,17164,
+    9,17167,    9,17165, 9565,17171, 1275,17125,  903,17175,    9,17125,
+  375,17125,  587,17181,    9,17124, 5267,17185, 9600,17185, 9565,17185,
+  587,17190,  587,17185, 9565,17194,  587,17124,  375,17199,13737,17125,
+    9,17203,    6,17124,17176,17207,17175,17207,  903,17210,  903,17207,
+17175,17214,    7,17124,10001,17219,  903,17221,    6,17125,    3,17224,
+17219,17227,  903,17229,    7,17125,   88,17233,   89,17233,  265,17233,
+  264,17232,17239,17241,  264,17233,    3,17233,    9,17246,    3,17232,
+17237,17251,    9,17251,    2,17232,17235,17257,17249,17257,17247,17257,
+    9,17263,  265,17232,17245,17267,    2,17233,17254,17271,    9,17271,
+17251,17274,17251,17271,    9,17278,16531,17232,    9,17233,    3,17284,
+17257,17287,    3,17285,17271,17291,  903,17233, 9565,17125, 1368,17297,
+   14,17297,    2,17296,    7,17303,    2,17297,    7,17306,    7,17307,
+17301,17311,    5,17297,17305,17315,17129,17315,    6,17314,17311,17321,
+    6,17315,17309,17325,17303,17325,17299,17325,  587,17296,    9,17333,
+    9,17297,  587,17337,    6,17297,    5,17340,17311,17343,    7,17297,
+    2,17346,17325,17349,12377,17125,    9,17353,16531,17125,    6,17357,
+    7,17357,    6,17356,17361,17363,    7,17356,17359,17367,    0,  903,
+  767,17370, 4617,17373,  483,17375,   15,17371, 1011,17379,  767,17371,
+ 4588,17383,  483,17383, 4579,17386, 4579,17383,  483,17390,  375,17371,
+   11,17395,  483,17370, 2265,17399, 4421,17399, 5285,17399,   11,17370,
+  375,17407,    6,17370,17380,17411,17379,17411, 1011,17414, 1011,17411,
+17379,17418,    7,17370, 3549,17423, 2001,17423, 8495,17423,10291,17423,
+ 1011,17431,14073,17423,11277,17423, 4971,17423, 5045,17423,    6,17371,
+    5,17442,17423,17445, 1011,17447,    7,17371, 1011,17451,    0, 1369,
+ 2789,17455, 2821,17455, 2759,17455, 2687,17455, 6658,17455,    2,17455,
+    6,17466, 6625,17455,    9,17470,12551,17455, 1347,17455,13808,17455,
+ 6685,17455,13833,17455, 4413,17455,17025,17455,  265,17487,  241,17486,
+17038,17455,  903,17455,    9,17455, 6625,17496,   17,17454,12377,17501,
+   11,17454,12377,17505,  803,17455,   15,17454, 5303,17511, 4927,17511,
+17033,17511,16983,17511,  265,17454, 2853,17521,17082,17455,   11,17455,
+12377,17526,12564,17455,  241,17455,13737,17532,17025,17532, 1011,17455,
+17049,17538,12377,17455,   10,17543,   10,17542,  305,17543,   11,17543,
+17547,17551,   11,17542,17545,17555,17049,17455, 1011,17558,    4,17454,
+    5,17455,13737,17455,  241,17566,    0, 1275,    3,17570,    9,17573,
+    4,17570,    5,17570, 9856,17579, 9805,17579,    9,17582,    9,17579,
+ 9805,17586,    5,17571,    3,17591,    0,17592,    0,17591,    3,17596,
+    9,17591, 1275,17601,17595,17603,17599,17603,   17,17591, 9805,17609,
+ 1369,17590,   17,17613, 1486,17571,   17,17617, 1369,17571,17577,17621,
+    9,17623,    5,17621,    9,17627,    5,17620,   17,17631,    0,   17,
+    4,17634,  587,17637,  155,17635, 1011,17635, 1369,17634,12377,17645,
+16990,17635,  587,17635,12377,17650,12566,17635,  903,17635,16937,17656,
+12377,17635,  587,17660,16937,17635,  903,17664,    3,17634,  483,17669,
+    2,17635,    4,17673,    0,17674,    0,17673,    4,17678,  587,17673,
+   17,17683,17677,17685,17681,17685,    3,17635, 1369,17691,    0,   15,
+    5,17695,    7,17696, 1369,17694, 5303,17701, 4927,17701,16983,17701,
+17033,17701,    3,17694,    3,17695,10104,17712,10105,17713,17715,17717,
+10104,17713,10105,17712,17721,17723,    1,   13,  113,17727,    0,   12,
+17727,17731,    9,17732,    2,17735,    2,17734,  137,17732,  136,17732,
+    2,17733,17741,17745,    3,17733,17739,17749,17743,17749,    2,17732,
+    9,17754,17749,17757,17749,17755,    3,17732,17737,17763,17745,17763,
+    0,   13,    1,   12, 1369,17771,   33,17771,    3,17770, 8251,17777,
+ 3807,17777, 9875,17777, 8165,17777,    3,17771, 8241,17787,17769,17771,
+    9,17791,    2,17792,    2,17793,  137,17791,  136,17791,    2,17791,
+    9,17802,    3,17791,17797,17807,    2,17790,17807,17811,17799,17811,
+    3,17790,17805,17817,17795,17817,17803,17817,17801,17817,    1,  413,
+    4,17826,    2,17826,    5,17826,    6,17833,    6,17832,    3,17826,
+    6,17839,    6,17838, 2653,17827, 1637,17827,14537,17827,14321,17827,
+  260,17826, 2903,17827, 1639,17827, 1641,17827, 3361,17827,  331,17826,
+17521,17827, 4909,17827,14593,17827,  261,17826,  257,17826,   14,17826,
+ 1274,17826, 2159,17827, 2161,17827,  251,17827, 2647,17827,  331,17885,
+   15,17826, 1275,17826,14652,17827,    6,17827,17829,17895,17831,17895,
+ 8997,17895,17863,17895,17871,17895,17889,17895,17891,17895,    7,17827,
+17833,17911,17839,17911, 8495,17911,  413,17910,    0,17919,17837,17911,
+17843,17911,  265,17911,17921,17927,    1,17927,17919,17931, 2647,17927,
+ 8717,17911, 3785,17911,17853,17911,17875,17911,17877,17911,14315,17910,
+  261,17911,    7,17826,17835,17951,17841,17951, 8647,17951,  251,17951,
+    6,17826,    5,17960,17911,17963,    3,17960,17911,17967,15029,17827,
+  265,17971,17895,17973,    7,17971,14315,17827,    6,17978,    7,17978,
+    6,17979,17983,17985,    7,17979,17981,17989,    0,  412, 9036,17993,
+ 9099,17993,17829,17993,17895,17998,17831,17993,17895,18002,17896,17993,
+17898,17993,17913,17993,17915,17993,  446,17993, 4371,18015, 4379,17993,
+17900,17993,17917,17993, 4360,17993, 3429,17993,17882,17993, 7039,17993,
+17958,17993,17949,17993,  241,17993,  445,18036, 4371,18039,  445,18037,
+ 4349,18043,16097,17993,12289,17993, 8647,17993, 8997,18050, 4349,17993,
+  251,18054,17951,17993,  251,18058,  251,17993, 4349,18062,17827,18062,
+17951,18062,17895,17993,17829,18070,17831,18070, 8997,18070, 5521,17993,
+  375,18079,  445,17993,  241,18082, 4371,18085,    3,18083,    2,18082,
+18089,18091,    2,18083,    3,18082,18095,18097,  465,17993,    5,18101,
+    4,18100,18103,18105,    4,18101,    5,18100,18109,18111, 9082,17993,
+ 8495,18115,17910,17993,17833,18119,17839,18119, 8495,18119,  375,17993,
+    7,17993, 8495,18129, 8997,18131,17827,18129,17829,18135,17831,18135,
+ 8997,18135, 8997,18128, 8495,18143,17827,18128,17833,18147,17839,18147,
+ 8495,18147, 8997,17993, 8647,18154,17895,18154,    7,18154, 8495,18161,
+17827,17993,  241,18164,    6,18167,    6,18166,  265,18165,17895,18173,
+  261,18164,  375,18165,  260,18164,  251,18164,    6,18165,18177,18185,
+    7,18165,18171,18189,18181,18189,    6,18164,18173,18195,  241,18194,
+18189,18199,18189,18195,    7,18164,17833,18205,17839,18205,18169,18205,
+18185,18205, 8495,18205,    1,  843,    0,  842,18217,18219,  483,18220,
+    4,18223,    4,18222,  581,18220,  580,18220,    4,18221,18229,18233,
+    5,18221,18227,18237,18231,18237,    4,18220,  483,18242,18237,18245,
+18237,18243,    5,18220,18225,18251,18233,18251,    0,  413,15309,18257,
+  265,18258,15363,18261,15424,18257,15363,18265,13375,18257,13381,18257,
+ 4888,18257,13162,18257,  251,18256,  375,18256,  265,18257,15309,18281,
+15383,18283,15309,18280,15363,18287,  331,18257, 2663,18257,  251,18293,
+    9,18256,  483,18256,  375,18257, 4863,18300,13119,18300, 4863,18257,
+  375,18306,13119,18257,  375,18310,    6,18257,  264,18314,    7,18257,
+  264,18318,  264,18319,  265,18319,18321,18325,  265,18318,18323,18329,
+ 8647,18319,  375,18319,  331,18319,    7,18256, 1689,18339, 1705,18339,
+ 2701,18339,18317,18339, 8717,18339,12755,18339, 7627,18339, 7895,18339,
+ 3785,18339,13443,18339, 7287,18339,  265,18339,  331,18339, 8495,18339,
+  375,18339,12745,18339,  457,18371,  375,18371,    6,18256,18291,18377,
+12745,18257,17895,18381, 8647,18381,    7,18381, 8495,18387,    1,  412,
+ 1679,18391,  448,18391, 4349,18395, 4351,18391, 4390,18391,18300,18391,
+ 4457,18391,18277,18391, 1673,18391,18279,18391, 1789,18391,18364,18391,
+18335,18391, 3427,18391, 7037,18391,  265,18391,  445,18422, 4349,18425,
+  445,18423, 4371,18429,16095,18391,12287,18391, 5189,18391,18299,18391,
+18297,18391, 2153,18391, 2151,18391, 4371,18391,  331,18446,18339,18391,
+  331,18450,  331,18391, 4371,18454,18339,18454,  445,18391,  265,18460,
+ 4349,18463,    5,18461,    4,18460,18467,18469,    4,18461,    5,18460,
+18473,18475,  465,18391,    3,18479,    2,18478,18481,18483,    2,18479,
+    3,18478,18487,18489, 8386,18391,18318,18391,  375,18391,18257,18496,
+    7,18391,  265,18501,18257,18503, 8337,18500,18257,18500, 8337,18391,
+    7,18510, 8861,18391,    6,18515,    7,18515,    6,18514,18519,18521,
+    7,18514,18517,18525,18257,18391,  265,18528,  241,18529,    6,18532,
+    6,18533,  375,18528,  261,18529,  260,18529,  251,18529,    6,18529,
+  241,18546,18531,18547,    7,18529, 8495,18553,18537,18553,    6,18528,
+18553,18559,18541,18559,    7,18528,18549,18565,18535,18565,18547,18565,
+18543,18565,    0,  843,    1,  842,    5,18576,18575,18577,  483,18581,
+    4,18582,    4,18583,  581,18581,  580,18581,    4,18581,  483,18592,
+    5,18581,18587,18597,    4,18580,18597,18601,18589,18601,    5,18580,
+18595,18607,18585,18607,18593,18607,18591,18607,    1, 1217,16117,18617,
+12291,18617,16103,18617, 4959,18617,17399,18617, 2205,18617, 2207,18617,
+ 1269,18617,    5,18633,    4,18632,18635,18637,    4,18633,    5,18632,
+18641,18643, 1259,18617,    2,18647,    3,18646,18649,18651,    3,18647,
+    2,18646,18655,18657,    7,18617,    0, 1216,    9,18662,18617,18665,
+  483,18662,18617,18669,18660,18663,    7,18663,18617,18674,18617,18663,
+    6,18679,    7,18679,    6,18678,18683,18685,    7,18678,18681,18689,
+    1, 1531, 4904,18693,17609,18693,17586,18693, 4903,18693,    9,18700,
+17579,18693,    9,18704,    9,18693, 4903,18708,17579,18708,    5,18692,
+    0, 1530,18693,18717,    4,18719,    5,18719,    4,18718,18723,18725,
+    5,18718,18721,18729,    1,   19, 1369,18733,    3,18733,    3,18732,
+ 9875,18739,    0,   18,18733,18743,    2,18745,    3,18745,    2,18744,
+18749,18751,    3,18744,18747,18755,    0, 1217,12293,18759,16105,18759,
+ 1269,18759,    2,18765,    3,18764,18767,18769,    3,18765,    2,18764,
+18773,18775, 1259,18759,    5,18779,    4,18778,18781,18783,    4,18779,
+    5,18778,18787,18789,  375,18759,    7,18759,    1, 1216,    4,18796,
+18759,18799,    3,18796,    6,18803,    6,18802,    5,18796,    6,18809,
+    6,18808,    2,18796,18759,18815, 5241,18797,   14,18796, 1274,18796,
+ 2157,18797, 2155,18797,18795,18797,18799,18829,18815,18829,   15,18796,
+ 1275,18796,    6,18796,    3,18838,    5,18838,    7,18796,18805,18845,
+18811,18845,18794,18797,18803,18851,18809,18851,    6,18797,18800,18857,
+18816,18857,18799,18857,18759,18862,18815,18857,18759,18866,18835,18857,
+18837,18857,18759,18857,18799,18874,18815,18874,    7,18797,18841,18881,
+18843,18881,18803,18881,18759,18887,18809,18881,18759,18891,18807,18881,
+18813,18881,18821,18881,18823,18881,18759,18880,18803,18903,18809,18903,
+18759,18797,    6,18909,    7,18909,    6,18908,18913,18915,    7,18908,
+18803,18919,18809,18919,18911,18919,    0, 1531,    1, 1530, 6717,18929,
+    9,18931,18927,18929,    4,18935,    5,18935,    4,18934,18939,18941,
+    5,18934,18937,18945,    0,   19,    1,   18,18949,18951,    2,18953,
+    3,18953,    2,18952,18957,18959,    3,18952,18955,18963,    0,    2,
+11303,18967,11349,18968, 5071,18967, 5097,18972,11350,18967, 5098,18967,
+11304,18967,11307,18981, 5072,18967, 5075,18985,11315,18967, 5079,18967,
+13961,18967,  581,18993,    4,18992,18995,18997,    5,18992,  580,18993,
+19001,19003,    5,18993,    4,18993,  483,19008,19001,19011,  483,18993,
+    4,19014,19001,19017,    4,19015,19007,19021, 1181,18966, 1206,18966,
+ 3451,18967,  375,19029, 1967,18967,  375,19033,  567,18966, 4992,19037,
+    9,19037, 4971,19040, 4971,19037,    9,19044, 1141,18966,  555,18966,
+  981,18967,16129,18966,16143,19055, 9523,18967,  483,19059, 9525,19061,
+ 1007,18967, 1297,18966,  524,18966,    0,19069,    4,19070,    4,19069,
+    0,19074,   97,18967,11067,18967, 1275,19080, 7947,19083, 1205,18967,
+  571,18967,11070,18967, 7947,19091,10043,18967, 1275,19094,10041,19097,
+10044,18967,10041,19101, 1206,18967, 3001,19105, 1901,19105,   30,18967,
+ 8165,19111, 8150,18967,   33,19115, 1181,18967, 3663,19119, 1997,19119,
+ 3069,19119, 1923,19119, 9769,18967, 3972,18967, 8124,18967, 9357,18967,
+ 9346,18967, 8782,18967, 4244,18967, 4178,18967, 9768,18967, 8804,18967,
+ 8245,18967, 8249,18967, 8247,18967, 6950,18967,12299,18967, 4652,18967,
+10684,18967,14096,18967, 4992,18967,  203,18967,11731,19167,17771,18967,
+  113,19171,14223,18967,   85,18967,11731,19177,11031,18967,  113,19181,
+  107,18967,11731,19185,11699,18967,  113,19189, 8701,18967, 9293,18967,
+ 3933,18967,    9,19196, 8109,18967,    9,19200, 4213,18967,    9,19204,
+ 4147,18967,    9,19208, 8757,18967,    9,19212, 9335,18967,    9,19216,
+10202,18967, 7947,19221,17637,19221,  578,18967, 4935,19227,11349,18967,
+11303,19230, 5097,18967, 5071,19234, 8647,18967,   11,19239,10603,18967,
+  375,19243,10427,19243,10609,19243,    7,19243,10607,19251,    9,19242,
+ 4625,18967,  375,19257,   75,19257, 4629,19257,    7,19257, 4627,19265,
+    9,19256,11277,18967,   10,19270,11307,19273,   10,19271,11349,19277,
+  483,19271, 5045,18967,   10,19282, 5075,19285,   10,19283, 5097,19289,
+  483,19283, 6789,18967,    9,19294,  288,18967,  525,18967,19073,19301,
+19077,19301, 1811,19301, 1877,19301,    5,19301,17563,19301, 4861,19301,
+ 1290,18967,    5,19317, 3721,19317, 1985,19317,17563,19317, 4861,19317,
+  296,18967, 8861,19329,   12,18967, 8165,19333,   18,18967,   25,18967,
+    9,19338, 8165,19341, 8165,19339,    9,19345, 7971,18967,    9,19348,
+   33,19351,   33,19349,    9,19355,   47,18967,11731,19359,10107,18967,
+ 1275,19362, 7947,19365,17637,19365,  113,19363,   59,18967,17635,19373,
+10291,18967,  165,19377,  375,18967,  510,18967,   11,18967, 8165,19385,
+    9,19387,  265,19384,    9,19384, 8165,19393,    9,18967,  567,19397,
+ 4971,19399,    6,19397,   25,19396, 8165,19405, 7971,19396,   33,19409,
+ 3933,19396, 8109,19396, 4213,19396, 4147,19396, 9335,19396, 8757,19396,
+ 8495,19396, 6789,19396, 4625,19396,10603,19396, 4971,19396,14073,19396,
+  567,19396, 4935,19437,   11,19397, 8109,19441, 3933,19441, 8495,19441,
+ 7971,19441,  265,19396, 8861,19451,   11,19396, 8165,19455,  483,19396,
+   17,18967, 1275,19460, 4861,19463,17563,19463, 3721,19463, 1985,19463,
+   15,19460,   15,18967, 9731,19474, 1011,19475,  483,19475,   17,19474,
+ 6515,18967,  483,19485, 6527,19487, 6557,19487, 6561,19487,14210,18967,
+   17,19495, 4971,18967,    9,19498,14073,18967,    9,19502, 5921,18967,
+  375,19507,10046,18967,   16,18966,    0,19513,    4,19514,19317,19517,
+19463,19517,    4,19513,    0,19522,19317,19525,19463,19525, 8495,19513,
+10351,19513, 4311,19513, 4329,19513, 8717,19513,10055,19513, 3785,19513,
+   14,18966,    6,19545,    2,19546,    2,19545,    6,19550,  482,19545,
+   17,19545,   10,18966,17777,19559, 2215,19559,11307,19559, 5075,19559,
+11713,19559, 2221,19559,11087,19559,10439,19559,10665,19559, 4643,19559,
+11037,19559, 2233,19559, 9195,19559,11277,19559, 5045,19559,19455,19559,
+19333,19559,19393,19559,19385,19559,    9,19597, 9317,19559, 9755,19559,
+ 4321,19559,10171,19559, 4295,19559, 3833,19559,10603,19559,    9,19613,
+ 4625,19559,    9,19617,    8,18967,   11,19621,   14,18967, 9731,19625,
+   17,19625,   11,18966, 8124,19631, 3972,19631, 8804,19631, 8150,19631,
+ 7971,19631,    9,19640, 3933,19631,    9,19644, 8109,19631,    9,19648,
+ 8495,19631,    9,19652,    9,19631, 8109,19656, 3933,19656, 8495,19656,
+ 7971,19656,    9,18966,10001,19667,    5,19669,    4,19668,19671,19673,
+    4,19669,    5,19668,19677,19679,   16,18967,    7,19683,   10,18967,
+11277,19686,11307,19689, 5045,19686, 5075,19693,11349,19687, 5097,19687,
+ 9195,19687,19656,19687,19441,19687,19631,19687,    9,19706,11277,19687,
+11303,19711, 5045,19687, 5071,19715,    9,19687,19631,19718,   19,18967,
+   13,18967,19631,19725,10385,18967,  101,19729,  128,19729,    9,19729,
+  113,19734,  483,19729,10081,19739,11759,19739,10405,19739,  113,19729,
+    9,19746,   67,18967,11613,19751,12216,19751,    9,19751,11731,19756,
+11731,19751,    9,19760,  566,18967,  253,19765, 1471,19765,   53,19765,
+  256,18967,  629,18967, 1413,18967, 1471,19777, 1346,18967,  340,18967,
+ 8165,19783,  567,18967, 4935,19787,    9,19789,    9,19786, 4935,19793,
+  305,18967,  959,18967,11731,19799,  759,18967,11731,19803,  331,18967,
+17635,19807, 1325,18967,17635,19811,10001,18967,10003,19815,    4,19817,
+    4,19816,10007,19815,  580,19815,10006,19815,  483,19815,    4,19828,
+    4,19829,  581,19815,    4,19815,10003,19836,  483,19836,    5,19815,
+19819,19843,19833,19843,    4,19814,19835,19849,19823,19849,19843,19849,
+    5,19814,19839,19857,19821,19857,19825,19857,19827,19857,19841,19857,
+19831,19857,19837,19857, 9731,18967,   15,19872, 8495,18967,  483,19877,
+    9,19876, 9195,18967,  113,19883,11731,19883,  241,18967,    7,19888,
+  483,18967,    9,19892,   17,19893,  903,19897,    5,19892,  253,19901,
+ 1471,19901,   53,19901,    5,19893, 1505,19909,  903,18967,    7,19913,
+ 1275,18967,10043,19916,10041,19919,11067,19916, 7947,19923,17637,19917,
+10107,19927,    0,19916,    4,19931,    0,19932,19917,19935,    7,19932,
+19937,19939,    7,19931,    4,19942,   16,19931,    6,19916,    4,19949,
+    6,19950,19917,19953,    1,19950,19955,19957,    1,19949,    4,19960,
+    8,19916,    4,19965,    1,19966,    1,19965,    4,19970,10107,19916,
+ 7947,19975,17637,19975, 7947,19917,11067,19981,10107,19981,    9,19917,
+ 2009,19987, 3135,19987,19969,19987,19973,19987, 5231,19987,19957,19987,
+19963,19987,    0,19987, 5175,19987,14065,19987,   17,19916,19525,20009,
+19517,20009, 3721,20009, 1985,20009,    1,20009,19987,20019,20003,20009,
+ 4861,20009,17563,20009,    5,19916,    4,19917,    5,19917,  265,18967,
+17635,20035, 5771,20035,    9,20035,   11,20034,   11,20035,    9,20034,
+ 8861,20047,  483,20035,    7,20034, 8165,20053,    7,20035, 8495,20057,
+  587,18967,    7,20061,    4,20063,    4,20062,   16,20061,   17,20061,
+    4,20060,20071,20073,    5,20060,20067,20077,20069,20077,    4,20061,
+    7,20082,20077,20085,    5,20061,20065,20089,13947,18967,    5,20092,
+   17,20095,    5,20093,    9,20099,    4,18966, 8770,20103, 8729,20103,
+ 8697,20103, 8784,20103, 4266,20103, 9262,20103,    2,20103,    7,20117,
+ 8684,20103, 8717,20121,  331,20121, 8647,20103, 8757,20126, 8757,20103,
+ 8647,20130,  375,20130, 4213,20103,  375,20136, 9750,20103,19687,20103,
+  347,20103,  386,20103,  340,20103,  331,20149,  375,20103, 8757,20152,
+ 4213,20152, 9195,20152,  305,20152,    9,20103,10291,20103,  483,20165,
+   59,20103,   15,20103, 9195,20103,  375,20172,  331,20103,10001,20103,
+    9,20179,  305,20103,  375,20182,    7,20103, 8495,20186, 8717,20189,
+  331,20189, 8495,20187, 8757,20195, 9731,20186,  265,20187, 8757,20201,
+ 4213,20201, 9195,20201,  305,20201,  265,20186,  331,20211, 8647,20187,
+ 1325,20103,    7,20102, 8495,20219,10351,20219, 4311,20219, 4329,20219,
+ 3785,20219,10055,20219, 8717,20219,  483,20103, 1275,20103,  265,20103,
+    7,20239, 8495,20241,  375,20241,    7,20238,  331,20247, 9731,20103,
+    7,20250, 8495,20103,    7,20254, 8717,20257,  331,20257,  483,20255,
+    9,20255,    7,20255, 8647,20267,  375,20267,    5,18966, 9535,20273,
+ 9537,20273,    2,20273,    6,20278, 9559,20273,  482,20273, 9563,20273,
+ 9362,20273,  922,20273, 1413,20273,   19,20273,   12,20273, 8150,20273,
+ 8804,20273,19385,20273, 1290,20273, 9533,20305,  525,20273, 9533,20309,
+ 7971,20273,    9,20312,   11,20273,    9,20316,   17,20273, 1275,20320,
+ 9533,20323,    9,20273, 9195,20326,   11,20326, 7971,20326, 8495,20326,
+ 9195,20273,    9,20336,    6,20273,    5,20341,    2,20340,    5,20340,
+18967,20347,   11,20341,    7,20273,    5,20353,    6,20272,   17,20357,
+    7,20272, 9195,20361,11277,20361, 5045,20361, 9755,20361, 4295,20361,
+10171,20361, 4321,20361, 3833,20361, 9317,20361,  483,20273,  903,20380,
+ 1275,20273,   17,20384, 9533,20387,  903,20273,  483,20390, 8495,20273,
+    9,20394, 9731,20273,    6,20398,    7,20398,    6,20399,20403,20405,
+    7,20399,20401,20409,    6,18966,19836,20413,19857,20415,19854,20413,
+19871,20413,19815,20413,    4,20423,19843,20425,    4,20422,19857,20429,
+19477,20413,19145,20413,19875,20413,19843,20413,19849,20438,19849,20413,
+19843,20442,19718,20413,19473,20413,19483,20413,19725,20413,   19,20413,
+   12,20413,19337,20413,19687,20413,    9,20460,19475,20413, 9731,20465,
+   17,20465,    9,20413,19687,20470,   11,20470,   11,20413,    9,20476,
+ 8495,20413,    5,20413,    9,20483,    4,20413,19815,20487,19849,20489,
+19815,20486,19857,20493,    5,20412,   17,20497,    7,18966,10439,20501,
+11087,20501,10665,20501, 4643,20501,11307,20501, 5075,20501,17777,20501,
+ 2215,20501,18739,20501, 4339,20501,11713,20501, 2221,20501,11037,20501,
+ 2233,20501,19626,20501,19129,20501,    0,20501,    4,20534,19301,20537,
+19317,20537,19463,20537,20009,20537,10036,20501,19843,20547, 8800,20501,
+ 8714,20501, 5045,20501,11277,20501, 4551,20501,19628,20501,19455,20501,
+19393,20501,19723,20501,19333,20501,  305,20501, 8495,20570,  959,20501,
+19625,20501, 9731,20576,   17,20576,10603,20501,    9,20583, 4625,20501,
+    9,20587,19385,20501,    9,20591,  759,20501,   47,20501,10107,20501,
+  241,20599,  265,20598,10196,20501,   11,20501, 8495,20606,   17,20501,
+19625,20610,   59,20501,10291,20501, 1011,20617,   15,20501, 1325,20501,
+ 8495,20501,   10,20624,   10,20625,  305,20624,   11,20624,20629,20633,
+   11,20625,20627,20637, 9731,20501,19625,20640,    4,20501,    7,20645,
+  483,20647,18967,20649,    0,20644,19301,20653,19317,20653,19463,20653,
+20009,20653,20651,20653,    7,20644,19916,20665,20653,20667, 1275,20665,
+18967,20670,20653,20673,18967,20665, 1275,20676,20653,20679,10001,20644,
+19843,20683, 1011,20645,10047,20645,    5,20501, 9287,20691,  331,20501,
+    4,20500, 8495,20697, 4311,20697,10351,20697, 3785,20697, 4329,20697,
+ 8717,20697,10055,20697,    5,20500, 9195,20713,11277,20713, 5045,20713,
+ 4321,20713, 9755,20713, 4295,20713,10171,20713, 9317,20713, 3833,20713,
+  903,20501,  265,20501,10107,20734, 9195,20501,  241,20739,10001,20501,
+    4,20742,19843,20745,    5,20742,18967,20748,    4,20743,20751,20753,
+19511,20753,19857,20753,    5,20743,    7,18967, 8810,20762, 8811,20762,
+    2,20763,    1,20768,20483,20763, 8495,20773, 8800,20763,20273,20763,
+ 8495,20763,   11,20780, 8810,20763,20767,20785,10081,20763, 1011,20789,
+ 1010,20788,20791,20793, 1010,20789, 1011,20788,20797,20799,  566,20763,
+   11,20763, 9731,20805, 8495,20805, 8495,20804,  265,20763,20482,20763,
+   17,20815,  567,20763, 9195,20819,    9,20763, 8811,20763,20765,20825,
+  241,20762,  265,20762, 8165,20831, 1011,20763,  375,20763,    4,20762,
+20815,20839,    5,20762,11276,20842, 5044,20842,11277,20842,11276,20843,
+20849,20851, 5045,20842, 5044,20843,20855,20857,20773,20843,20470,20843,
+20103,20843,20413,20843,    9,20866, 9195,20843,11277,20843,20845,20873,
+ 5045,20843,20847,20877,    9,20843,20413,20880,    4,20763,20480,20885,
+    7,20884,20843,20889, 9366,20885,    1,20885,    3,20894,20842,20896,
+20843,20897,20899,20901,20889,20900,20842,20897,20843,20896,20907,20909,
+20890,20897,20889,20897,20843,20914,    3,20885,    1,20918,20842,20920,
+20843,20921,20923,20925,20889,20924,20842,20921,20843,20920,20931,20933,
+20890,20921,20889,20921,20843,20938, 9195,20885,  483,20942,20866,20885,
+ 8495,20885,20413,20948,  483,20885, 9195,20952,20413,20885, 8495,20956,
+20843,20956,20843,20885,    1,20962,    3,20964,    3,20962,    1,20968,
+    7,20963,20897,20973,20921,20973,20967,20973,20971,20973,20413,20962,
+    5,20763,    7,20985,   17,20985,20413,20989,20413,20984,20839,20993,
+   17,20993,  483,20984,20839,20985,    1,21001,    3,21002,    3,21001,
+    1,21006,    7,21000,21005,21011,21009,21011,20413,21001,20413,20763,
+    5,21019,20885,21021,    9,21021,    5,21018,20839,21027,   17,21027,
+  483,20763,    5,21032,    5,18967,    0,21037,    3,21038, 9357,21037,
+20742,21037,20761,21045,20187,21037, 8495,21049,20501,21037,10001,21036,
+20753,21055,20763,21037, 8495,21059,13947,21036,   17,21063,  256,21037,
+20186,21037,20885,21037,    7,21071,20897,21073,20921,21073,    9,21037,
+ 1275,21079, 9533,21081,21041,21081,   17,21037, 9195,21087, 7971,21087,
+ 8495,21087,  483,21036,  253,21095, 1471,21095,   53,21095, 1275,21036,
+    6,21036,20640,21105,20610,21105,21069,21105, 9731,21105,20501,21112,
+20501,21105, 9731,21116,   17,21116,   17,21105,20501,21122,    7,21036,
+11276,21126, 5044,21126,11277,21126,11276,21127,21133,21135, 5045,21126,
+ 5044,21127,21139,21141,    1,21127,    3,21144,18967,21147,    3,21127,
+    1,21150,18967,21153,18967,21127,20470,21127,21049,21127,20413,21127,
+    9,21162,20103,21127, 9195,21127,11277,21127,21129,21171, 5045,21127,
+21131,21175,    9,21127,20413,21178,    6,21037,21149,21183,21155,21183,
+20254,21183,19243,21183,19257,21183,18967,21183,    1,21183,    3,21196,
+21126,21198,21127,21199,21201,21203,21126,21199,21127,21198,21207,21209,
+    3,21183,    1,21212,21126,21214,21127,21215,21217,21219,21126,21215,
+21127,21214,21223,21225, 8495,21183,20103,21228,19687,21183,20843,21183,
+21166,21183,   11,21183,20501,21239,20103,21183, 8495,21242,21127,21242,
+21127,21183,20103,21248,20763,21183, 9731,21253,   17,21253,    7,21037,
+19625,21259,   15,21259,20413,21263,20103,21258,21105,21267,  241,21258,
+21105,21259,20103,21273,20103,21037,    7,21277,21199,21279,21215,21279,
+11277,21279, 5045,21279,21183,21279,    6,21276,    1,21291,    3,21292,
+21279,21295,    3,21291,    1,21298,21279,21301,    7,21276,21105,21305,
+  241,21037,  483,21309,    7,21308,    4,18967,21183,21315,    0,21314,
+20309,21319,  524,21319,20273,21323,20305,21319, 1291,21319,20273,21329,
+21081,21319,20323,21319,20387,21319,   11,21319,  483,21338,20273,21341,
+  483,21319,   11,21344,20273,21347,  165,21315,17635,21315, 1011,21352,
+17642,21315,20413,21315,    6,21359,    9,21315,20352,21315,11277,21365,
+ 5045,21365,20985,21315,   11,21315,10075,21315,  483,21315, 1347,21315,
+    6,21314,    1,21381,    3,21382,21365,21385,    3,21381,    1,21388,
+21365,21391,20273,21381,   11,21381,    7,21314,    6,21315,   17,21401,
+    7,21315,21384,21404,21390,21404,21385,21405,20273,21411,21407,21411,
+21391,21405,20273,21417,21409,21417,21385,21404,21384,21405,21423,21425,
+21391,21404,21390,21405,21429,21431,11276,21404, 5044,21404,11276,21405,
+11277,21404,21439,21441, 5044,21405, 5045,21404,21445,21447,    0,21405,
+    4,21450,    4,21405,    0,21454, 8495,21405, 5045,21405,20273,21461,
+21437,21461,11277,21405,20273,21467,21435,21467,    9,21405,20273,21404,
+21385,21475,21391,21475,11277,21475, 5045,21475,  265,21405,  483,21405,
+18967,21487,21453,21489,21457,21489,21381,21405,20273,21315,    6,21497,
+    1,21499,    3,21500,    3,21499,    1,21504,    7,21496,21503,21509,
+21507,21509,21385,21509,21391,21509,11277,21509, 5045,21509, 1011,21315,
+17635,21522,    6,18967,    2,21526,   11,21529,20103,21527,20690,21527,
+    9,21535,21259,21527,    9,21539,   17,21527,    4,21526,   11,21545,
+    5,21526,20640,21549,21259,21549,20610,21549, 9731,21549,20501,21556,
+20501,21549, 9731,21560,   17,21560,   17,21549,20501,21566,    4,21527,
+   15,21571,    5,21527,  482,21575,    2,21575,    6,21578,    6,21575,
+    2,21582,    9,21575,20501,21587,20501,21574,    9,21591,20501,21527,
+    5,21595,   17,21597,    5,21594,    9,21601,    1,    3,19718,21604,
+19719,21604,19402,21605,20962,21604,20973,21613,21248,21604,21272,21604,
+21494,21604,20963,21604,21249,21604,21001,21604,21011,21627,21273,21604,
+21495,21604,21178,21604,20880,21604,21179,21604,20881,21604,21049,21604,
+20773,21604,21361,21604,15753,21605,  803,21649,14387,21605,  375,21653,
+ 9663,21604, 9177,21604,20351,21604,20485,21604,21360,21604,  990,21604,
+ 4745,21667,19685,21605,21087,21671,21156,21605,21087,21675,21317,21605,
+21291,21604,21279,21681,21499,21604,21509,21685,  996,21604, 4745,21689,
+21472,21604,21473,21604,  761,21605, 3419,21697, 6469,21697, 3119,21697,
+21048,21604,20772,21604,  973,21604,  955,21708, 4745,21711,    9,21708,
+ 4745,21715, 4745,21709,  955,21719,    9,21719, 2077,21605,    7,21725,
+   14,21724,21727,21729,    6,21725,   15,21724,21733,21735,20350,21604,
+20484,21604, 9662,21604, 9176,21604,21380,21604,21104,21604,21126,21604,
+21183,21751,    9,21751,20842,21604,20885,21757,    9,21757,  305,21604,
+18967,21763,  375,21765,  955,21604,  973,21769, 4805,21771,  973,21768,
+ 4745,21775,17423,21769, 4745,21769,  713,21604,21404,21604,21381,21785,
+    9,21785,20884,21604,21316,21605,21182,21604,20501,21795,21793,21795,
+21405,21604,21381,21800,    9,21800,20885,21604,20843,21806,20890,21807,
+20889,21807,20843,21812,20973,21807,21073,21807,20413,21807,20843,21807,
+21757,21823,20889,21822,21183,21604,21127,21828,21279,21829,21679,21829,
+20103,21829,21127,21829,21751,21839,21105,21604,21381,21604,21365,21845,
+21405,21844,20413,21845,21475,21845,21405,21845,21785,21855,20273,21855,
+21509,21845,20843,21604,20885,21862,    9,21862,21127,21604,21183,21868,
+18967,21869,21183,21873,    9,21868, 1199,21605,13923,21604,13935,21881,
+ 9437,21605,  587,21885, 9439,21887, 1177,21605, 1421,21604,  668,21604,
+    1,21895,    5,21896,    5,21895,    1,21900,  117,21605,11759,21605,
+ 1369,21906, 7971,21909,11760,21605, 7971,21913,  809,21605,  989,21605,
+ 9929,21605, 1369,21920, 9927,21923, 9930,21605, 9927,21927,19596,21605,
+    9,21931,19556,21605,20170,21605,19707,21605,    9,21939,20956,21605,
+21791,21943,21242,21605,21795,21947,20773,21605,21707,21951,21049,21605,
+21705,21955,21373,21605,20464,21605,19557,21605,20499,21605,20359,21605,
+ 9181,21605, 9671,21605, 4145,21605, 3801,21605, 4135,21605,10101,21605,
+20577,21605,19656,21605,19441,21605,19332,21605,19392,21605,19454,21605,
+21059,21605,19440,21605,19657,21605, 4134,21605,10100,21605,20498,21605,
+20358,21605,20142,21605,    9,22007,20576,21605,20864,21605,    9,22013,
+21116,21605,21166,21605,21183,22019,    9,22019,21560,21605, 9180,21605,
+ 9670,21605, 3800,21605, 4144,21605,21026,21605,20839,22035,20814,21605,
+20839,22039,20992,21605,20839,22043,21359,21605,21845,22047,21647,22047,
+21053,21605,21795,22053,20779,21605, 8087,21605, 8091,21605, 8089,21605,
+20303,21605,    9,22065,20465,21605,10786,21605,11131,21605, 4696,21605,
+11970,21605,19722,21605,19333,21605,19393,21605,19455,21605,20351,21605,
+21739,22087,20485,21605,21741,22091, 9663,21605,21743,22095, 9177,21605,
+21745,22099,20350,21605,21661,22103,20484,21605,21663,22107, 9662,21605,
+21657,22111, 9176,21605,21659,22115,10099,21605,   17,22119,   17,22118,
+ 4133,21605,   17,22125,   17,22124, 8251,21605,    9,22131, 3807,21605,
+    9,22135,   13,21604,18967,22139,   19,21604,20501,22143, 9875,22143,
+   12,21604, 8251,22149, 3807,22149,19559,22149,20501,22149, 9875,22149,
+ 8165,22149,   18,21604, 3799,21605,   17,22165,   17,22164, 4143,21605,
+   17,22171,   17,22170, 4283,21605,    9,22177, 4279,21605,    9,22181,
+ 9669,21605,   17,22185,   17,22184, 9179,21605,   17,22191,   17,22190,
+ 9673,21605,    9,22197, 9967,21605,    9,22201,19624,21605,20501,22205,
+   17,22205,19686,21605,22149,22211,19441,22211,19656,22211,21607,22211,
+19631,22211,    9,22220,    9,22211,19631,22224,19559,21605,19385,22228,
+    9,22231,    9,22229,19545,21605,   17,22236,   17,22237,10102,21605,
+ 7971,22243,17053,22243,  629,21605,21117,21605,21561,21605,20867,21605,
+20885,22255,21167,21605,21183,22259,21548,21605,   17,22263,20501,22263,
+21104,21605,21069,22269,21267,22269,21305,22269,21259,22269,20103,22277,
+   17,22269,20501,22269,20838,21605,20985,22285,20842,21605,21865,22289,
+21809,22289,21613,22289,21637,22289,21867,22289,20773,22289,20956,22289,
+21863,22289,20885,22305,    9,22305,20885,22289,20413,22310,20413,22289,
+20885,22314,21126,21605,21871,22319,21831,22319,21617,22319,21635,22319,
+21877,22319,21049,22319,21242,22319,21869,22319,21183,22335,    9,22335,
+21183,22319,20103,22340,20103,22319,21183,22344,21020,21605,20885,22349,
+21278,21605,21183,22353,21052,21605,21829,22357,21127,22357,21358,21605,
+21747,22363,21665,22363,21532,21605,20497,21605,   17,22371,   17,22370,
+20361,21605,    9,22377,20713,21605,    9,22381,20357,21605,   17,22385,
+   17,22384,21048,21605,21643,22391,20772,21605,21645,22395,21509,21605,
+21381,22399,21499,22399,    9,22399,21475,21605,21381,22407,    9,22407,
+21365,21605,21381,22413,    9,22413,11971,21605, 4697,21605, 8387,21605,
+    9,22423,11949,21605,   11,22426,    5,22428,    6,22426,    5,22432,
+    5,22426,    6,22436,    6,22437,    7,22426,22441,22443,    7,22427,
+22435,22447,22439,22447,22431,22447,   14,22426,22447,22455,    6,22427,
+   15,22426,22459,22461,    9,22426,    9,22427, 4669,21605,   11,22468,
+    5,22470,    6,22468,    5,22474,    5,22468,    6,22478,    6,22479,
+    7,22468,22483,22485,    7,22469,22477,22489,22481,22489,22473,22489,
+   14,22468,22489,22497,    6,22469,   15,22468,22501,22503,    9,22468,
+    9,22469,12345,21605,    5,22510,    4,22510,   12,22510,   13,22511,
+22517,22519,   12,22511,   13,22510,22523,22525,    4,22511,22513,22529,
+    5,22511,22515,22533, 5123,21605,    5,22536,    4,22536,   12,22536,
+   13,22537,22543,22545,   12,22537,   13,22536,22549,22551,    4,22537,
+22539,22555,    5,22537,22541,22559,10697,21605,    9,22562,19385,21605,
+19559,22566,    9,22569,    9,22567,19559,22573,19397,21605,    6,22576,
+   11,22577,   11,22576,19475,21605,20413,22584, 1406,21605, 1396,21605,
+  525,21605,  903,22593,  934,21605,    9,22597, 1290,21605,  903,22601,
+  669,21605,21899,22605,21903,22605, 1861,22605, 1887,22605,    4,22605,
+17013,22605, 4917,22605,19687,21605,22139,22621,21609,22621,    9,22621,
+20103,22620,    9,22629,19625,21605,20501,22632,19384,21605,21087,22637,
+20326,22637,    9,22636,20273,22637,    9,22644,    9,22637,20273,22648,
+19396,21605,    5,22652,   10,22652,19441,22657,   10,22653,19455,22661,
+   11,22652,22661,22665,   11,22653,22657,22669,19474,21605,20413,22673,
+ 1418,21605,    4,22677, 3755,22677, 1995,22677,17013,22677, 4917,22677,
+   12,21605,22139,22689,18967,22688,   18,21605,22143,22695,21252,21605,
+21279,21605,21183,22701,21291,22701,    9,22701,20483,21605,20763,22708,
+20187,21605,21036,22712,21069,22715,21036,22713,21049,22719,21037,22713,
+21037,22712,    9,22713,20353,21605,    5,22729,21315,22729,   33,21605,
+ 8150,22735,17727,22735,    9,22735, 7971,22740, 7971,22735,    9,22744,
+17025,22735, 8165,21605,   30,22751,  181,22751,    9,22751,   25,22756,
+   25,22751,    9,22760,  145,22751,   53,21605,17049,22767,10219,21605,
+  903,22771,  155,22771,10081,21605, 1369,22776, 7971,22779,17053,22779,
+  257,21605,    9,22785, 1171,21605, 4722,22789, 4713,22789,  903,22792,
+21315,22789,  903,22789, 4713,22798,  628,21605,    9,22803,   11,21605,
+  766,22807,  767,22807,20984,22807,20762,22806,22813,22815,20985,22807,
+20762,22807,22140,22807,19718,22807,19725,22807,  586,22806,22809,22829,
+    5,22807,20763,22832,22815,22835,20763,22833,22821,22839,  587,22832,
+22829,22843,  587,22833,  586,22807,22847,22849, 5515,22807,17043,22807,
+ 4825,22807,17727,22807, 8150,22807,22139,22807,18967,22862,19396,22806,
+19397,22806,19396,22807,22869,22871,19397,22807,22867,22875,22653,22875,
+20763,22807,    5,22880,22815,22883,19687,22807,    9,22886, 7971,22807,
+    9,22890,19461,22807,    9,22807,19687,22896, 7971,22896,18967,22896,
+18967,22807,22139,22904,    9,22904,20103,22905,    9,22911, 1369,22806,
+  903,22806,    9,22917,  587,22807,    5,22920,22829,22923,18967,22806,
+20326,22927,21087,22927,    9,22926,20273,22927,    9,22934,    9,22927,
+20273,22938,    9,22806,18967,22942,20763,22806,22819,22947,  587,22806,
+22811,22951,    9,22951,   17,21605,19722,22956,19723,22957,22959,22961,
+19723,22956,19722,22957,22965,22967,19396,22956,19396,22957,19397,22956,
+22973,22975,19545,22956,20497,22956,20357,22956, 4133,22956,10099,22956,
+ 3799,22956, 4143,22956, 9179,22956, 9669,22956,19475,22957,21315,22957,
+19397,22957,22971,23001, 1369,22956, 1275,22956,  903,23007,  587,22957,
+  903,22957,   15,21605,20103,23014,18967,23015,20501,23019, 1369,23014,
+ 4917,23023,17013,23023, 3755,23023, 1995,23023,18967,23014,20413,23033,
+    9,21605,19631,23036,19384,23036,19384,23037,22567,23043,19385,23036,
+10697,23036, 4669,23036,11949,23036,   11,23037,23047,23055,22567,23055,
+18967,23055,18967,23036,   10,23062,   10,23063,   11,23062,23067,23069,
+   11,23063,23065,23073,   11,23036,18967,23076, 7049,21605,  587,23081,
+ 7051,23083, 7055,23083, 7059,23083,17219,21605,  903,23091, 4663,21605,
+  903,23095, 4745,21605,  955,23099,    9,23099, 4569,21605,17423,21605,
+  955,23107,    9,23107,14625,21605, 5997,21605,    7,23114,    5,23114,
+    6,23119,23117,23121,    6,23118,    6,23114,    5,23126,    7,23115,
+23129,23131,23125,23131,   14,23114,23131,23137,    6,23115,   15,23114,
+23141,23143,20482,21605,20762,23146,20773,23149,20762,23147,20815,23153,
+20839,23147,21399,23147,19683,23147,20763,23147,20843,23163,23149,23163,
+20763,23146,20839,23169,23153,23169,20186,21605,21036,23174,21049,23177,
+21036,23175,21069,23181,  331,23175,   59,23175, 1325,23175,  265,23175,
+20644,21605,20352,21605, 9660,21605, 8386,21605,   59,23199,  331,23199,
+ 1325,23199,  265,23199,21243,21605,21829,23209,20957,21605,21807,23213,
+21272,21605,21631,23217,20962,21605,    9,23221,21248,21605,21625,23225,
+21549,21605,20501,23228,21105,21605,20501,23232,20843,21605,21758,23237,
+21623,23237,21760,23237,21641,23237,20885,23237,21757,23246,20889,23247,
+21757,23237,20885,23252,    9,23252,20103,23236,    9,23259,    9,23237,
+21757,23262,20885,23236,    9,23267,21127,21605,21752,23271,21625,23271,
+21754,23271,21639,23271,18967,23270,21087,23281,21183,23271,21751,23284,
+21751,23271,21183,23288,    9,23288,20103,23270,21183,23295,    9,23295,
+    9,23271,21751,23300,21405,21605,21633,23305,21394,23305,21786,23305,
+21381,23305,20273,23312,21785,23312,20326,23305,21087,23305,21695,23305,
+21037,23305,21036,23304,23325,23327,21036,23305,21037,23304,23331,23333,
+21788,23305,21785,23305,21381,23338,    9,23338,    9,23305,20273,23344,
+21785,23344,20273,23305,21381,23350,    9,23350,21259,21605,21843,23357,
+20885,21605,20763,23360,    5,23363,18967,23362,    6,23360,18967,23368,
+18967,23360,    6,23372,    6,23373,    7,23360,23377,23379,    7,23361,
+23365,23383,    4,23383,23363,23387,23371,23383,23375,23383,23367,23383,
+21526,23360,23383,23397,    6,23361,21527,23360,23401,23403,    9,23361,
+20843,23407,21791,23361,20413,23411,20413,23360,21791,23415,20843,23360,
+    9,23419,21183,21605,21315,23422,21795,23425,21795,23423,20103,23429,
+20103,23422,21795,23433,20763,23422,21249,21605,21617,23439,21001,21605,
+    9,23443,21273,21605,21619,23447,21371,21605,    9,23451,21253,21605,
+    8,21604,22363,23457,22053,23457,21983,23457,23039,23457,21985,23457,
+22077,23457,22075,23457,22465,23457,22507,23457,23053,23457,23051,23457,
+20501,23457,23037,23457,19631,23483,11949,23483, 4669,23483,18967,23457,
+   10,21604,22870,23493,22869,23493,22867,23493,23041,23493,22583,23493,
+21995,23493,22665,23493,21991,23493,19441,23493,22626,23493,21997,23493,
+19656,23493,22908,23493,22902,23493,22419,23493,22421,23493,11970,23493,
+ 4696,23493,21987,23493,23069,23493,21989,23493,23079,23493,22643,23493,
+22933,23493,22945,23493,22693,23493,22904,23493,    9,23546,22896,23493,
+18967,23550,22621,23493,    9,23554,19396,23493,22807,23558, 8647,23493,
+22637,23493,    9,23565,23077,23493,18967,23569,22689,23493,18967,23573,
+22927,23493,    9,23577,22943,23493,18967,23581,22807,23493,19396,23584,
+19396,23585,18967,23584,    9,23590,    9,23584,18967,23594,18967,23585,
+    9,23598,    9,23585,18967,23602,19631,23493,    9,23606,18967,23493,
+22896,23610,22807,23610,    9,23614,    9,23610,22807,23618,    9,23493,
+11949,23622, 4669,23622,22621,23622,19631,23622,22904,23622,22807,23622,
+18967,23634,18967,23622,22807,23638, 4669,23493,    9,23642,11949,23493,
+    9,23646,   16,21604,22979,23651,21935,23651,22239,23651,22389,23651,
+22375,23651,22001,23651,21999,23651,22005,23651,22003,23651,22123,23651,
+22129,23651,22983,23651,22981,23651,22987,23651,22985,23651,22989,23651,
+22995,23651,22993,23651,22991,23651,22169,23651,22029,23651,22027,23651,
+22175,23651,22031,23651,22189,23651,22195,23651,22033,23651,    7,23651,
+    3,23706,    3,23651,    7,23710,  586,23651,22957,23651,19545,23717,
+20357,23717,20497,23717,10099,23717, 4133,23717, 3799,23717, 9669,23717,
+ 9179,23717, 4143,23717,19559,23651,20713,23651,20361,23651, 9967,23651,
+ 9673,23651, 4283,23651, 3807,23651, 8251,23651, 4279,23651,   14,21604,
+23175,23755,23199,23755,    5,23755,    1,23760,22677,23763,23023,23763,
+    1,23755,    5,23768,22677,23771,23023,23771,16381,23755,14625,23755,
+ 4569,23755,13325,23755, 8685,23755,19513,23755, 1369,23755,   17,23755,
+20219,23755, 4063,23755,10273,23755,20697,23755, 4137,23755, 8401,23755,
+ 9955,23755, 3863,23755,19631,21605,   11,23808,    5,23810,    6,23808,
+    5,23814,    5,23808,    6,23818,    6,23819,    7,23808,23823,23825,
+    7,23809,23817,23829,23821,23829,23813,23829,   14,23808,23829,23837,
+    6,23809,   15,23808,23841,23843,    9,23808,23457,23847,    9,23809,
+19667,21605,    5,23852,    4,23852,   12,23852,   13,23853,23859,23861,
+   12,23853,   13,23852,23865,23867,    4,23853,23855,23871,    5,23853,
+23857,23875,    8,21605,23646,23879,23642,23879,23606,23879,23851,23879,
+22467,23879,22509,23879,19384,23879,19631,23879,23493,23894,23493,23879,
+11949,23898, 4669,23898,19631,23898,11949,23879,23493,23906, 4669,23879,
+23493,23910,18967,23879,   11,23914,   11,23915,23493,23919,   11,23879,
+18967,23922,   14,21605,18967,23926,20501,23929,   17,23929,18967,23927,
+20413,23935,   16,21605,22241,23939,22387,23939,22373,23939,22121,23939,
+22127,23939,22167,23939,22173,23939,22187,23939,22193,23939,19545,23939,
+10099,23939, 4133,23939, 3799,23939, 4143,23939, 9669,23939, 9179,23939,
+20357,23939,20497,23939,19625,23939,21549,23939,21105,23939,   11,21604,
+23053,23983,23051,23983,23039,23983,21985,23983,22085,23983,    5,23982,
+    6,23995,21983,23983,22077,23983,22075,23983,22081,23983,22083,23983,
+22572,23983,23847,23983,22465,23983,22507,23983,22211,23983,    9,24017,
+19396,23983,22567,23983,    9,24022, 8165,23983,    9,24027,23037,23983,
+11949,24031, 4669,24031,19631,24031,19559,23983,    9,24039, 8251,23983,
+    9,24043, 3807,23983,    9,24047, 9875,23983,    9,24051,20501,23983,
+    9,24055,    9,23982, 8251,24059, 3807,24059,22211,24059,19559,24059,
+20501,24059, 9875,24059, 8165,24059,    9,23983,22567,24074,18967,24074,
+18967,23983,21183,24081,23997,24081,  375,24081,    7,24081,23995,24089,
+    9,24080,    9,21604,22869,24095,23894,24095,21997,24095,21365,24095,
+21475,24095,21509,24095,21405,24094,22047,24095,22357,24095,23919,24095,
+21995,24095,22583,24095,23906,24095,23910,24095,21127,24094,22319,24125,
+20843,24094,22289,24129,22419,24095,22421,24095,21279,24095,  973,24094,
+ 4745,24139,19559,24095,20361,24095,20713,24095, 9673,24095, 9967,24095,
+ 4283,24095, 4279,24095, 8251,24095, 3807,24095,   33,24095, 7971,24161,
+ 8165,24095,   25,24165, 9875,24095,20501,24095, 4745,24095,17423,24095,
+21405,24095,20273,24177,21785,24177,19631,24095,23879,24182, 4669,24095,
+23879,24186,11949,24095,23879,24190,  973,24095, 4805,24195,19687,24095,
+23493,24199,23879,24095,19631,24202,11949,24202, 4669,24202,20413,24095,
+   11,24094, 8251,24213, 3807,24213,22211,24213,19559,24213,20501,24213,
+ 9875,24213, 8165,24213,21127,24095,21751,24229,20843,24095,21757,24233,
+   11,24095,19687,24237,23610,24237,23493,24237,18967,24242, 7971,24237,
+18967,24237,23493,24248,18967,24095,   10,24252,24213,24255,   10,24253,
+24237,24259,  483,24253,   10,21605,23893,24265,24020,24265,22581,24265,
+22669,24265,19455,24265,23917,24265,19333,24265,23073,24265,19393,24265,
+23060,24265,24092,24265,23925,24265,24078,24265,23651,24265, 9755,24265,
+ 9317,24265, 4321,24265, 3833,24265,10171,24265, 4295,24265,22149,24265,
+18967,24307,24213,24265,18967,24311,24059,24265,18967,24315,21183,24265,
+19396,24265,23983,24320,19559,24321,  922,24265, 1413,24265,19683,24265,
+24074,24265,18967,24332,23055,24265,18967,24336,24080,24265,    9,24340,
+20839,24265,21399,24265,19385,24265,23879,24349,    9,24349,23983,24265,
+19396,24355,19396,24354,18967,24355,    9,24360,    9,24355,18967,24364,
+18967,24354,    9,24368,    9,24354,18967,24372,18967,24264,19441,24377,
+24213,24377,24059,24377,22149,24377,19656,24377,19631,24377,    9,24388,
+23983,24377,    9,24393,    9,24377,19631,24396,  903,24265,  483,24400,
+  483,24265,  903,24404,18967,24265,23055,24408,24074,24408,19559,24409,
+    9,24415,    9,24408,23983,24418,19559,24419,23983,24408,    9,24424,
+    9,24265,24080,24428,18967,24428,19559,24433,23983,24432,23983,24428,
+18967,24438,18967,24429,19631,24443,   17,21604,21963,24447,23958,24447,
+23972,24447,23974,24447,23960,24447,23962,24447,21979,24447,21977,24447,
+21967,24447,21965,24447,23964,24447,23966,24447,23968,24447,23970,24447,
+21971,24447,21969,24447,21975,24447,21973,24447,22807,24447,19545,24447,
+23939,24486,20357,24447,23939,24490,20497,24447,23939,24494, 9669,24447,
+23939,24498, 9179,24447,23939,24502, 3799,24447,23939,24506, 4143,24447,
+23939,24510,10099,24447,23939,24514, 4133,24447,23939,24518,23939,24447,
+19545,24522,20357,24522,20497,24522,10099,24522, 4133,24522, 3799,24522,
+ 9669,24522, 9179,24522, 4143,24522,   15,24446,   15,21604,23357,24545,
+22713,24545,22423,24545, 8337,24545,20103,24545,   17,24544,  483,24545,
+   19,21605,22163,24561,18967,24560,   13,21605,24080,24567,22149,24567,
+23983,24567,18967,24572,18967,24567,23983,24576,  113,21605,10385,24581,
+23879,24583,    9,24583,11731,21605,   67,24589,23879,24591,    9,24591,
+  137,21605,12261,21605,  587,24599,10107,24601,11067,24601,12285,24601,
+ 1346,21605, 1505,24609,  256,21605, 8495,24613,10107,24613, 1486,21605,
+  803,24619, 1504,21605,20029,24623,21103,24623,19781,24623,  973,21605,
+ 2845,24631, 4812,24631,  955,24631, 4805,24636, 2971,24631, 4814,24631,
+    9,24631, 4805,24644, 4805,24631,  955,24648,    9,24648,  341,21605,
+  803,24655,17049,24655,20884,21605,21820,24661,21807,24661,20413,24664,
+20413,24661,21807,24668,21182,21605,21195,24673,21836,24673,21829,24673,
+20103,24678,20103,24673,21829,24682,20984,21605,20839,24687,20413,24689,
+20413,24686,20839,24693,21258,21605,23755,24697,21749,24697,21574,21605,
+    9,24703,21404,21605,24109,24707,21803,24707,21849,24707,21621,24707,
+21693,24707,21805,24707,21801,24707,21381,24721,    9,24721, 1141,21605,
+17025,24727, 1447,21605,17025,24731,  253,21605,17049,24735, 1471,21605,
+17049,24739,21018,21605,    5,24742,20839,24745,    5,24743,20885,24749,
+21276,21605,    7,24753,20413,21605,    6,24756,    4,24759,18967,24760,
+18967,24759,    4,24764,    4,24765,21314,24759,21570,24756,21571,24757,
+24773,24775,    6,24757,21314,24778,21314,24779,20885,24757,24661,24785,
+21571,24756,21570,24757,24789,24791,21315,24757,24783,24795,21381,24757,
+20885,24756,21791,24801,19475,24756,20984,24756,20839,24807,21315,24756,
+21747,24811,24781,24811,23457,24811,    5,24756,20762,24819,20762,24818,
+24763,24819,24767,24819,20839,24819,21399,24819,24771,24819,19683,24819,
+20763,24819,20843,24837,24823,24837,20763,24818,24821,24843,20839,24843,
+    5,24757,24769,24849,20885,24849,24661,24849,20763,24756,    5,24856,
+20839,24859,    5,24857,20885,24863,20103,21605,21183,24867,21127,24869,
+24673,24869,   15,24866,21183,24866,21795,24877,   15,24867,19687,24866,
+    9,24883,19625,24866,20843,24866,    9,24889,21549,24866,21127,24866,
+21183,24895,    9,24895,21105,24866,20763,24866,    5,24903,21527,24866,
+    9,24867,19687,24909,20843,24909,21127,24909,    6,24866,21036,24917,
+    5,24917,18967,24920,18967,24917,    5,24924,21036,24916,    5,24916,
+18967,24930,24881,24917,18967,24916,    5,24936,    7,24866,23755,24941,
+ 1325,24941,  331,24941,   59,24941,  265,24941,    7,24867,23929,24953,
+22205,24953,24919,24953,24923,24953,24927,24953,24929,24953,24933,24953,
+24939,24953,24905,24953,    4,24953,24903,24973,22269,24953,22263,24953,
+  375,24953,21037,24953,24917,24983,    6,24867,    5,24986,24941,24989,
+24901,24987,24893,24987,24887,24987,21037,24866,24987,24999,    7,24999,
+20273,21605,21258,25004,21259,25005,25007,25009,21183,25005,21259,25004,
+21258,25005,25015,25017,  375,25005,    6,25004,    7,25004,    7,25005,
+25023,25027,21315,25027,    6,25005,25025,25033,20501,21605,    7,25036,
+    4,25039,    4,25038,20885,25037,    7,25037,18967,25047,    5,25049,
+    5,25048,    5,25047,18967,25054,    5,25046,21036,25047,21037,25037,
+22269,25063,21105,25063,   16,25036,   10,25037,  803,25037,  903,25037,
+    9,25037,   17,25036,19625,25036,21105,25036,21549,25036,21037,25036,
+21829,25087,25059,25087,21127,25087,24095,25087,25071,25087,   11,25037,
+    4,25036,    7,25100,25051,25101,    5,25036,25041,25107,18967,25106,
+25099,25111,    5,25037,25103,25115,25043,25115,25087,25115,    7,25114,
+25087,25123,25069,25115,    4,25037,25111,25129,25057,25129,25053,25129,
+25061,25129,25079,25129, 9165,21605, 9168,25140, 9169,25141,25143,25145,
+ 9169,25140, 9168,25141,25149,25151, 8337,21605,   15,25155,    6,25155,
+    5,25158,    7,25155,  375,25163,    6,25154,25157,25167,    7,25154,
+25161,25171,23755,25171,   59,25171,  331,25171, 1325,25171,  265,25171,
+ 9617,21605, 9630,25184, 9631,25185,25187,25189, 9629,25185, 9631,25184,
+ 9630,25185,25195,25197,  375,25185,    6,25185,    7,25185,    6,25184,
+25205,25207,    7,25184,25203,25211, 9875,21605,    7,25214,    4,25216,
+    4,25217, 9893,25215,   16,25214,  803,25215,    9,25215,   17,25214,
+  903,25215,    4,25215,25231,25235,    5,25215,25219,25239,25225,25239,
+    4,25214,    7,25244,25239,25247,    5,25214,25221,25251,  843,21605,
+    9,25255,  413,21605,    7,25259,  375,25259, 1530,21605,    9,25265,
+ 1216,21605,    7,25269,21497,21605,    7,25273,21277,21605,    7,25276,
+21183,25279,    7,25277,21105,25283,21019,21605,    5,25286,20885,25289,
+    5,25287,20839,25293,  265,21605,    7,25297, 7971,25299,  587,21605,
+   11,25302,    9,25305,    9,25303,   11,25309,    5,25303,20501,25313,
+ 9875,25313,  903,21605,    9,25319,   11,25321,   11,25318,    9,25325,
+    7,25319, 1141,25329,   33,25329, 1447,25329, 1011,25318,    7,25337,
+ 1275,21605,    9,25341, 1369,25343,   17,25340,  903,25347,    5,25340,
+ 1505,25351,    5,25341,  253,25355,   53,25355, 1471,25355, 1369,25340,
+    9,25363, 1011,21605,    7,25367,  959,25369,   47,25369,  759,25369,
+  903,25366,    7,25377, 1369,21605, 9929,25380, 9927,25383,11759,25380,
+ 7971,25387,17053,25381,10081,25391,    7,25380,    4,25394,    5,25395,
+    7,25398,25381,25401,    0,25398,25403,25405,    4,25395,    0,25395,
+    5,25410,    1,25380,    5,25415,    1,25416,25381,25419,    6,25416,
+25421,25423,    6,25415,    5,25426,   14,25415,   10,25380,    5,25433,
+    0,25434,    0,25433,    5,25438,   16,25380,10081,25380, 7971,25445,
+17053,25445, 7971,25381,11759,25451,10081,25451,   17,25380,   11,25380,
+   11,25381, 1965,25461, 3195,25461,25437,25461,25441,25461, 5197,25461,
+25405,25461,25413,25461,    1,25461, 4579,25461,15899,25461,   15,25380,
+23763,25483,23771,25483, 3755,25483, 1995,25483,    0,25483,25461,25493,
+25477,25483, 4917,25483,17013,25483,    4,25380,    7,25502,20029,25503,
+19781,25503,21103,25503,    5,25380,25409,25513,  803,25513,    4,25381,
+20033,25519,25457,25519,    5,25381,25397,25525,25505,25525,25443,25525,
+10219,25525,  959,25525,   47,25525,  759,25525, 1275,25380,    9,25541,
+  241,21605,    9,25545,  483,25545,    7,25544, 8495,25551,10107,25551,
+17571,21605,    7,25557,    4,25558,    4,25559,   16,25557,   17,25557,
+    4,25556,25567,25569,    5,25556,25561,25573,25565,25573,    4,25557,
+    7,25578,25573,25581,    5,25557,25563,25585,17371,21605,16711,25589,
+    7,25589,14315,21605,    5,25594,    6,25596,    6,25597,   14,25594,
+   15,25594,    6,25594,    5,25606,    7,25594,25601,25611,    6,25595,
+25605,25615,    7,25595,25609,25619,25599,25619,25603,25619,15705,21605,
+  767,25627,  483,25629,    4,25627,  483,25633,21527,21605,20103,25636,
+    5,25637,   17,25641,    5,25636,    9,25645,21315,21605,21183,25648,
+21795,25651,21183,25649,24673,25655,21747,25649,20413,25659,23457,25649,
+20413,25663,20413,25648,23457,25667,21747,25667,21037,21605,21829,25673,
+20501,25675,21127,25673,20501,25679,21105,25673,   11,25673,20501,25685,
+   15,25673,20501,25672,24095,25691,21829,25691,21127,25691,20187,25672,
+24095,25673,20501,25701,    6,25673,    7,25673,    6,25672,25707,25709,
+20103,25709,    7,25672,21749,25715,23755,25715,25705,25715,20103,25672,
+    7,25723,20763,21605,20482,25726,20839,25729,20483,25726,21183,25726,
+    4,25727,23147,25737,24819,25737,    5,25727,23383,25743,20956,25743,
+20773,25743,24953,25743,20885,25743,20413,25752,20413,25743,20885,25756,
+    4,25726,21605,25761,    7,25763,25743,25765,24849,25761,20413,25761,
+    5,25726,20839,25773,20413,25775,20413,25772,20839,25779,20413,25726,
+    5,25782,20839,25785,    5,25783,20885,25789,    5,21604,25275,25793,
+25003,25793,25725,25793,24755,25793,21049,25793,21242,25793,20773,25793,
+20956,25793,25699,25793,22725,25793,22391,25793,24682,25793,23209,25793,
+25712,25793,25733,25793,22711,25793,22395,25793,24668,25793,23213,25793,
+25770,25793,25083,25793,23235,25793,22017,25793,25085,25793,23231,25793,
+22025,25793,25087,25793,25691,25793,22357,25793,22047,25793,23455,25793,
+15567,25793,12971,25793,13355,25793,13541,25793,22869,25793,22635,25793,
+23021,25793,23894,25793,23919,25793,21997,25793,21995,25793,22583,25793,
+23906,25793,23910,25793,22419,25793,22421,25793,23034,25793,19656,25793,
+19441,25793,11970,25793, 4696,25793,22674,25793,22069,25793,25081,25793,
+22011,25793, 9357,25793,25205,25793,25027,25793, 9356,25793,25171,25793,
+24941,25793,23199,25793,23175,25793,20606,25793,25593,25793,19396,25793,
+11131,25793,21059,25793,23018,25793,20501,25933,20057,25793,22633,25793,
+20501,25939,21405,25793,  357,25793,  367,25793,  471,25793, 1249,25793,
+  628,25793, 4569,25793,14625,25793, 4545,25793,13325,25793, 8337,25961,
+ 4549,25793,23229,25793,20501,25967,23233,25793,20501,25971,25706,25793,
+20186,25793, 8386,25793, 9083,25793, 9484,25793, 9984,25793,20187,25793,
+ 8387,25793,19513,25793, 8401,25793,20219,25793, 4137,25793,10273,25793,
+ 4063,25793, 3863,25793,20697,25793, 9955,25793,20353,25793,25709,25793,
+20103,26010,25715,25793,24673,25793,20103,26016,24697,25793,21183,25793,
+20103,26022,21259,25793, 4745,25793,17423,25793, 9082,25793,22673,25793,
+20413,26034,23033,25793,20413,26038,25551,25793,24613,25793,22249,25793,
+20326,25793,21087,25793, 9704,25793,23879,25793,19631,26054,11949,26054,
+ 4669,26054,11949,25793,23879,26062,    9,26062, 4669,25793,23879,26068,
+    9,26068,20805,25793,23015,25793,18967,26076,20501,26079,18967,26077,
+20413,26083,19631,25793,23879,26086,    9,26086, 9377,25793,   11,26092,
+  341,25793,  241,26097, 8165,25793,  256,25793,  257,25793,   11,25793,
+ 9195,26106,20501,26106,  587,26106, 9377,26106, 9875,26106,20763,26106,
+20804,25793,10219,25793,  587,26123,   53,25793,20501,25793,   10,26128,
+   10,26129,   11,26128,26133,26135,   11,26129,26131,26139,20413,25793,
+20885,26142,24661,26142,25761,26142,22673,26142,23033,26142,20762,25793,
+25761,25793,20413,26156,24661,25793,20413,26160,20885,25793,20413,26164,
+   17,25793,20762,26168,20762,26169,20763,26169,26171,26175,20763,26168,
+26173,26179,    9,25793,11949,26182, 4669,26182,19631,26182,18967,26182,
+20273,26182, 9617,26182,20763,25793,   11,26196,25707,25793, 9875,25793,
+   10,26202,   10,26203,   11,26202,26207,26209,   11,26203,26205,26213,
+  253,25793,    6,25793,25273,26219,24753,26219,24999,26219,24953,26219,
+25005,26219,25723,26219,25707,26219,25185,26219,25163,26219,25589,26219,
+24081,26219, 4713,26219,16363,26219, 9195,26219, 4863,26219,13119,26219,
+ 8757,26219, 4213,26219,23493,26219, 8109,26219, 3933,26219, 4147,26219,
+ 9335,26219,20103,26219, 8337,26219,20273,26219, 8997,26219,25673,26219,
+  241,26219,18967,26219,   11,26279,   11,26219,  587,26219, 8387,26219,
+14653,26219,20187,26219,    7,25793, 8717,26293, 3785,26293,25673,26292,
+23755,26293,10351,26293, 4311,26293, 4329,26293,10055,26293,20103,26292,
+ 8337,26292, 8997,26292,   15,26293,18967,26317,18967,26292,  241,26292,
+ 9195,25793,   11,26324, 1471,25793,    6,25792,23175,26331,25977,26331,
+24941,26331,26311,26331,26299,26331,25975,26331,25715,26331,24697,26331,
+26315,26331,23199,26331,25171,26331,25979,26331,26033,26331,26313,26331,
+16381,26331,26323,26331,26103,26331,13325,26331, 8685,26331,26155,26331,
+26321,26331,26293,26331,20103,26375,25673,26375, 8997,26375, 8337,26375,
+  241,26375,18967,26375,   17,26331, 1369,26331, 4569,26331,19513,26331,
+ 4063,26331,10273,26331, 3863,26331,20697,26331, 9955,26331, 4137,26331,
+20219,26331, 8401,26331,14625,26331,    7,25792,25987,26415,26266,26415,
+26201,26415,26274,26415,26272,26415,25989,26415,25981,26415,26268,26415,
+21604,26415,18967,26433,26219,26435, 8997,26415,26219,26438,26105,26415,
+26276,26415, 8647,26415,19396,26415,26197,26415,26278,26415,26219,26415,
+20103,26454,25673,26454, 8997,26454, 8337,26454,  241,26454,18967,26454,
+ 8337,26415,26219,26468,20103,26415,26219,26472,    9,26415,18967,26476,
+  241,26415,    1,26481,26219,26483,26219,26480,25673,26415,26219,26488,
+18967,26415,    9,26492,26219,26492,  587,25793,   11,26498, 1369,25793,
+25673,25793,20501,26505,    6,26504,    7,26504,26331,26511,    6,26505,
+26511,26515,    7,26505,26509,26519,26219,26519,18967,25793,    9,26524,
+23015,26524,20501,26529,  483,26525,    6,26524,    7,26524,26331,26537,
+    7,26525,26219,26541,    6,26525,  241,25793,    1,26547,    7,26549,
+26331,26551,    7,26548,26219,26555,    7,26547,    1,26558,26219,26561,
+26219,26559,    7,26546,26331,26567,20273,25793,    9,26570,14315,25793,
+ 8997,25793,    7,26576,26331,26579,    7,26577,26219,26583, 9617,25793,
+    9,26586, 8337,25793,    7,26590,26331,26593,  483,26591,    9,26591,
+    7,26591,26219,26601,20103,25793,21183,26604,24673,26604,25709,26604,
+    7,26604,26331,26613,  483,26605,    9,26605,    7,26605,26219,26621,
+    4,21604,21955,26625,24877,26625,23433,26625,21947,26625,21951,26625,
+24801,26625,23415,26625,21943,26625,22282,26625,22251,26625,22266,26625,
+22253,26625,24811,26625,25667,26625,22363,26625,22053,26625,21116,26625,
+21560,26625,25735,26625,23437,26625,22699,26625,21253,26625,23930,26625,
+22206,26625,24805,26625,23937,26625,22587,26625,23039,26625,23053,26625,
+23051,26625,21961,26625,21981,26625,20465,26625,20576,26625,21985,26625,
+21983,26625,22077,26625,22075,26625, 9573,26625, 9575,26625,23847,26625,
+22465,26625,22507,26625,    3,26625,    7,26712, 9605,26625,  586,26625,
+ 9599,26625,19474,26625,20413,26723,20186,26625,20805,26625,22423,26625,
+22713,26625,22205,26625,20501,26734,19625,26625,20501,26738,19687,26625,
+23929,26625,20501,26744,23934,26625,20413,26749,22585,26625,20413,26753,
+ 8386,26625,23927,26625,18967,26759,20501,26761,18967,26758,20413,26765,
+23037,26625,19631,26769,11949,26769, 4669,26769, 1418,26625, 9565,26777,
+  669,26625, 9565,26781,22263,26625,20501,26784,22269,26625,20501,26788,
+21549,26625,20501,26792,20843,26625,21105,26625,20501,26798,21127,26625,
+23423,26625,20103,26805,23357,26625, 7971,26625, 1170,26625,25203,26813,
+20501,26625,22269,26816,22263,26816,21105,26816,21549,26816,22205,26816,
+23929,26816,19625,26816,20762,26625,26219,26833,23361,26625,20413,26837,
+   11,26625,    1,26841,18967,26841,   15,26625,18967,26846,20413,26849,
+18967,26847,20501,26853, 1369,26846, 9565,26857,    7,26625,    4,26861,
+    3,26860,    4,26860,21605,26867,20103,26860, 8337,26860,18967,26860,
+26219,26875, 1011,26860,25203,26879,    6,26625,21604,26882,20763,26883,
+    6,26624,24811,26889,22053,26889,22363,26889,25667,26889,20501,26889,
+25649,26889,20413,26901,18967,26889,    7,26624,24265,26907,19559,26907,
+ 9673,26907, 8251,26907, 3807,26907, 4283,26907,20361,26907, 4279,26907,
+20713,26907, 9967,26907,  483,26625, 1369,26625,   15,26930, 9565,26933,
+25649,26625,20413,26937,18967,26625,   15,26940,20413,26943,23927,26940,
+20413,26947,    6,26940,21604,26950,    7,26940,26219,26955,    7,26941,
+26953,26959,26885,26959,26331,26959,23755,26959,    6,26941, 1011,26625,
+    7,26971,25207,26973,23197,26973,    7,26970,25203,26979,20103,26625,
+    7,26982, 8337,26625,    7,26986, 9565,26625, 9617,26625,    6,26992,
+    7,26992,    6,26993,26997,26999,    7,26993,26995,27003,20273,26625,
+    6,27006,    7,27006,    6,27007,27011,27013,    7,27007,27009,27017,
+    7,21604,25987,27021,26266,27021,22732,27021,22733,27021,25087,27021,
+25691,27021,22357,27021,22047,27021,26027,27021,25989,27021,26268,27021,
+20819,27021,20152,27021, 8374,27021, 8389,27021,20201,27021,20952,27021,
+    1,27021,    4,27056,    4,27057,    3,27021,    4,27062,  902,27021,
+19559,27021,20361,27021, 9673,27021,20713,27021, 9967,27021, 4283,27021,
+ 4279,27021, 8251,27021, 3807,27021,26100,27021,26106,27021,26128,27021,
+26202,27021, 8647,27021,20326,27021,25239,27021,25115,27021, 8800,27021,
+21087,27021,  357,27021,  367,27021,  471,27021, 1249,27021, 8086,27021,
+19687,27021, 9704,27021,25742,27021,20885,27021,  483,27122, 1141,27021,
+  375,27021,20103,27128, 8337,27128,25673,27021,20501,27135,26219,27021,
+20103,27138, 8337,27138,   11,27139,   17,27139, 1447,27021,21127,27021,
+20843,27021, 8165,27021,25793,27154,  265,27155,   33,27021,  567,27021,
+22729,27021,21315,27164,   11,27021,25793,27169, 8495,27169,25793,27168,
+ 8495,27168,18967,27169,21037,27169,21497,27021,21277,27021,21276,27021,
+21496,27021,20273,27021,    9,27190,21315,27190,20103,27021,26219,27196,
+  375,27196,21037,27196,21314,27021,22729,27205,20273,27205,21036,27021,
+25129,27211,20103,27211,21183,27021,    9,27021,20273,27218, 9617,27218,
+21315,27021,22729,27224,20273,27224,21037,27021,20103,27230,25743,27021,
+   25,27021, 7971,27236, 7971,27021,   25,27240, 9617,27021,    9,27244,
+ 8337,27021,26219,27248,  375,27248,    4,27021,25037,27255,25215,27255,
+    3,27254,    1,27254,25727,27255,  483,27255,20691,27255, 9923,27255,
+18967,27255,20103,27273,18967,27254,22729,27277,20273,27277,    5,27021,
+27061,27283,    1,27283,25727,27282,18967,27283,22729,27291,20273,27291,
+   17,27283,18967,27297,18967,27282,25129,27301,20103,27301,25793,27021,
+ 8165,27306,   11,27306,20501,27306, 9875,27306, 9731,27021, 8495,27021,
+   11,27318,    4,27020,    1,27323,27283,27324,27286,27323,27289,27323,
+27121,27323,24265,27323,27225,27323,27290,27323,27211,27323,27301,27323,
+27283,27323,    1,27344,25727,27345,18967,27344,18967,27345,19559,27323,
+18967,27323,27283,27356, 4283,27323, 9673,27323, 8251,27323, 3807,27323,
+20361,27323, 9967,27323,20713,27323, 4279,27323,    5,27020,27059,27377,
+27263,27377,27235,27377,27264,27377, 8647,27377,19396,27377,27231,27377,
+27272,27377,27205,27377,27277,27377,27255,27377,    1,27399,25727,27398,
+18967,27398,18967,27399,26219,27377,    9,27377,18967,27410,25727,27377,
+27255,27414,18967,27377,    9,27418,27255,27418, 1011,27021,25727,27021,
+    5,27426,27323,27429,    5,27427,27255,27433,18967,27021,    7,27437,
+21605,27439,    4,27441,    4,27440,    4,27439,21605,27446,    4,27438,
+   16,27437,  113,27437,11731,27437,   17,27437,    4,27436,22729,27461,
+21605,27460,27459,27465,27377,27461,20273,27461,    5,27436,25129,27473,
+27443,27473,27323,27473,20103,27473,    5,27437,25101,27483,23193,27483,
+    7,27483,21605,27489,27461,27491,27449,27483,27445,27483,27461,27483,
+27255,27483,21315,27483,    4,27437,    7,27504,27473,27505,27283,27505,
+21037,27505,  483,27021,20885,27514,20501,27021,  241,27519,25793,27518,
+ 9875,27021,  241,27525,25793,27524,20413,27021,    6,21604,24811,27533,
+25667,27533,22363,27533,22053,27533,    1,27533,    5,27542,22605,27545,
+22677,27545,23023,27545,25483,27545,20644,27533,21359,27533,25793,27557,
+12345,27533,    5,27561,    4,27560,27563,27565,    4,27561,    5,27560,
+27569,27571, 5123,27533,    5,27575,    4,27574,27577,27579,    4,27575,
+    5,27574,27583,27585,19667,27533,    5,27589,    4,27588,27591,27593,
+    4,27589,    5,27588,27597,27599,  341,27533,21052,27533,25793,27605,
+25649,27533,20413,27609,25673,27533,21183,27613,26861,27533,    9,27617,
+26293,27533,    9,27621,17219,27533,  903,27625, 4663,27533,  903,27629,
+23195,27533,21315,27633,10219,27533,  903,27637,   53,27533,25025,27533,
+21315,27643,20103,27533,    9,27647,21314,27533,24795,27651,26142,27651,
+20413,27651,25793,27656,25793,27651,20413,27660,21036,27533,25129,27665,
+21259,27533,26625,27669,   17,27533,21315,27673,21037,27533,25793,27677,
+20501,27679,20501,27676,25793,27683, 8337,27533,    9,27687, 1471,27533,
+    5,27533,    6,27693,  587,27695,21605,27697,    1,27692,22605,27701,
+22677,27701,23023,27701,25483,27701,27699,27701,    6,27692,25380,27713,
+27701,27715, 1369,27713,21605,27718,27701,27721,21605,27713, 1369,27724,
+27701,27727,    9,27693,18967,27692,25129,27733, 9935,27693,20645,27693,
+    4,27533,20501,27740,26524,27741,20501,27745,25793,27741,18967,27748,
+20501,27751,18967,27749,20413,27755,18967,27741,25793,27758,20501,27761,
+20501,27759,25793,27765,18967,27740,26142,27769,20413,27769,25793,27772,
+25793,27769,20413,27776,26940,27533,26969,27781,  253,27533,    4,27532,
+24811,27787,22053,27787,22363,27787,25667,27787,20501,27787,25649,27787,
+20413,27799,18967,27787,    5,27532,24941,27805,23175,27805,25715,27805,
+24697,27805,25171,27805,23199,27805,26959,27805,16381,27805,13325,27805,
+ 8685,27805,26293,27805,   17,27805, 1369,27805, 4569,27805,19513,27805,
+ 4063,27805,10273,27805, 4137,27805,20219,27805, 8401,27805, 3863,27805,
+14625,27805,20697,27805, 9955,27805,  241,27533,18967,27533,20486,27857,
+20487,27857,20413,27857,    4,27862,    4,27863,  580,27857,  483,27857,
+    4,27870,    4,27871,  581,27857,    4,27856,27861,27879,26142,27879,
+27877,27879,20413,27879,25793,27886,25793,27879,20413,27890,    5,27856,
+25129,27895,27859,27895,27865,27895,27869,27895,27873,27895,    5,27857,
+25101,27907,27555,27907,23193,27907,27743,27907,27886,27907,27867,27907,
+27875,27907,20413,27907,27879,27922,27879,27907,20413,27926,    4,27857,
+20413,27930,27895,27933,  483,27930,27895,27937,27895,27931,20413,27941,
+ 1369,27533,    5,27945,20501,27533,21037,27949,    4,27948,27907,27953,
+    5,27948,18967,27956,21037,27948,25793,27961,    4,27949,27959,27965,
+27665,27965,27733,27965,27895,27965,    5,27949,27961,27975,    7,21605,
+    1,27979,    2,27981,    5,27983,    5,27982, 1010,27981,    5,27981,
+    2,27990,    3,27978,    9,27995, 4311,27979,10351,27979, 4329,27979,
+ 3785,27979,10055,27979, 8717,27979,26283,27979,26388,27979,23790,27979,
+27828,27979,22143,27979,22149,27979,24213,27979,24059,27979,  331,27979,
+ 8337,28027,20103,28027,21036,27978,21049,28033,21242,28033,21183,28033,
+20103,28038,20103,28033,21183,28042,26331,27979,20103,28047, 8337,28047,
+   17,28046,21277,27978,21183,28055,27693,27979,18967,28059,25793,27979,
+21127,28063,20843,28063,19687,28063, 8337,28063,20103,28063, 7971,28063,
+  241,28063, 8495,27979,  241,28079, 8337,27978,26331,28083,27805,28083,
+ 1325,28083,  331,28083,   59,28083,23755,28083,25793,28083,  265,28083,
+21037,27979,27665,28101,28033,28101,   11,28101,21315,27979, 1325,27979,
+ 8337,28111,20103,28111,   59,27979, 8337,28117,20103,28117,10291,27979,
+  483,28123,20273,27978,27533,28127,21315,28129,20103,27978,26331,28133,
+27805,28133,23755,28133,  331,28133, 1325,28133,   59,28133,25793,28133,
+  265,28133,21105,27979,   11,27979,20103,28153, 8337,28153,   17,27979,
+26331,28158, 8337,28159,20103,28159,27805,28158,23755,28158,27731,27979,
+27692,27979,    9,28173,23755,27979,20103,28177, 8337,28177,   17,28176,
+23983,27979,    9,28185,   15,27979,    3,28189,20273,28189, 9617,28189,
+27805,27979,20103,28197, 8337,28197,   17,28196,  241,27978,25793,28205,
+ 8495,28205,10107,28205,  265,27979,20103,28213, 8337,28213,    4,27978,
+27985,28219,21105,28219,21549,28219,19625,28219,28173,28219,18967,28229,
+    5,27978,19397,28233,28060,28233,18966,28232,18966,28233,    9,28241,
+27323,28233,23651,28233,26907,28233, 9755,28233, 9317,28233, 4321,28233,
+ 3833,28233,10171,28233, 4295,28233,28101,28233,21183,28233, 1413,28233,
+  922,28233,27856,28233,28059,28233,18967,28272,19396,28233,28239,28277,
+19683,28233,18967,28232,28235,28283,28242,28283,28241,28283,    9,28288,
+    9,28283,28241,28292,27533,28233,18967,28296,    9,28233,18967,28300,
+28239,28303,18967,28301,28241,28307,21399,28233,20839,28233,  483,28233,
+  903,28314,  903,28233,  483,28318,18967,28233,28059,28322,28239,28323,
+    9,28327,27533,28322,    9,28322,28239,28333,    4,27979,27987,28337,
+27993,28337,28270,28337,28330,28337,28298,28337,27989,28337,  586,28337,
+    3,28337,    7,28352,    7,28337,    3,28356,27856,28337,28233,28360,
+21575,28337,28296,28337,18967,28366,27533,28337,28322,28370,18967,28370,
+28233,28374,28233,28370,18967,28378,28322,28337,27533,28382,18967,28337,
+28296,28386,27533,28386,28233,28390,28233,28386,27533,28394,28233,28337,
+27856,28398,27533,28398,18967,28402,18967,28398,27533,28406,    5,27979,
+27255,28411, 9287,28411,20885,28411,27533,28410,28219,28419,18967,28421,
+    9,28419,  241,28411,  483,28427,28219,28411,27856,28431,27533,28431,
+18967,28434,18967,28431,27533,28438,18967,28410,28219,28443,   17,28443,
+21036,27979,21069,28449,21267,28449,21305,28449,28219,28449,21259,28449,
+20103,28459,   17,28449,21037,27978,26331,28465,21749,28465,27805,28465,
+23755,28465,28449,28465,25793,28465,10001,27979,    9,28479,27533,27979,
+21496,28483,21277,28483,20885,28483,27931,28483,    9,28483, 9731,28483,
+21037,28482,21037,28483,21315,28483,20273,28500,21036,28482,28499,28505,
+21036,28483,28497,28509,20273,28483,21315,28512,    4,28483,    5,28483,
+28386,28519,28337,28519,18967,28522,18967,28519,28337,28526,   17,28519,
+    4,28482,28519,28533,    5,28482,28517,28537,28219,28537,18967,28541,
+    9,28537, 1275,27979,20031,28547,20885,28547,    5,28547,18967,27979,
+20103,28555,    5,28555,28337,28559,    9,28559,    5,28554,28219,28565,
+   17,28565,21527,27979,18967,27978,28519,28573,    7,28573,    4,28576,
+    4,28577,28553,28573,21605,28573,    5,28584,28581,28587,    5,28585,
+28579,28591,   16,28573,28591,28595,   11,28573,20273,28573,  567,28573,
+    5,28572,    4,28573,    7,28606,28591,28609,28483,28607,28547,28607,
+  483,28607,    5,28573,21605,28618,28581,28621,20762,21605,20803,28625,
+    7,28625,    4,28628,25743,28631,    4,28629,24687,28635,25773,28635,
+21035,28625,   16,28625,25743,28643,20999,28625,20985,28625,  483,28649,
+   11,28625,20273,28625,  567,28625,    4,28624,20985,28659,    5,28624,
+20956,28663,20773,28663,20885,28663,20413,28668,20413,28663,20885,28672,
+20482,28625,20839,28677,    4,28625,    7,28680,25743,28683,20843,28681,
+  483,28681,    5,28625,21605,28690,28635,28693,20839,28691,20413,28697,
+20413,28690,20839,28701,20413,28625,    5,28705,20885,28707,    5,28704,
+20839,28711,    5,21605,21183,28715,18967,28716,24673,28719,21194,28715,
+24673,28723,28573,28714,28581,28727,20620,28714,20621,28714, 9994,28714,
+ 9995,28714,    1,28715,    1,28714,26781,28741,  668,28741,26625,28745,
+26777,28741, 1419,28741,26625,28751,26857,28741,26933,28741,    2,28741,
+    9,28741,  587,28760,26625,28763,  587,28741,    9,28766,26625,28769,
+21018,28714,20839,28773,19396,28715,22579,28777,21611,28777,19683,28715,
+20413,28783,23490,28715,20413,28787,21526,28714,26816,28791,24953,28791,
+   17,28791,20501,28791,26625,28798,26625,28791,20501,28802,20762,28714,
+20773,28807,20956,28807,20885,28807,20413,28812,20413,28807,20885,28816,
+27787,28715,18967,28821,20501,28823,18967,28820,20413,28827,27802,28715,
+20413,28831,21019,28714,20885,28835,27856,28715,20413,28839,27931,28715,
+20413,28843,26904,28715,20413,28847,26861,28715,18967,28851,20823,28715,
+20645,28715, 9935,28715,21362,28715,21376,28715,27533,28715,18967,28865,
+20501,28867,18967,28864,20413,28871, 9994,28715,28737,28875,20822,28715,
+28807,28879,20763,28715,28835,28883,28816,28883,20866,28883,21021,28883,
+20413,28883,28807,28892,20843,28892,28807,28883,20413,28898,    9,28899,
+20843,28883,20413,28904,    9,28882,28807,28909,  803,28715,   11,28913,
+27979,28715,18967,28917,20621,28715,28731,28921,20413,28714,21399,28925,
+20839,28925,25737,28925,19683,28925,20763,28925,20843,28935,28807,28935,
+20763,28924,20839,28941,25737,28715,20413,28945,20839,28715,20413,28949,
+20620,28715,28733,28953,21399,28715,20413,28957,  483,28715,21315,28960,
+26860,28715,28337,28715,   11,28967,23457,28715,18967,28970,20413,28973,
+18967,28971,20501,28977,    9,28715,21315,28980,20763,28981,20763,28980,
+28807,28987,   17,28715,11949,28991, 4669,28991,19631,28991,18967,28991,
+20273,28991, 9617,28991, 9995,28715,28735,29005, 1275,28714, 1505,29009,
+26889,28715,18967,29012,20413,29015,18967,29013,20501,29019, 1369,28714,
+  803,29023,  587,28715, 1505,28715,    6,28714,26940,29031,20413,29033,
+28965,29031,18967,29037,18967,29030,26816,29041,24953,29041,   17,29041,
+20501,29041,26625,29048,26625,29041,20501,29052,26625,29031,18967,29056,
+20413,29059,18967,29057,20501,29063,18967,29031,20413,29067,26625,29069,
+26625,29066,20413,29073,    7,28714,19397,29077,    0,29077,    2,29080,
+28991,29083,    2,29077,    0,29087,    0,29086,28991,29091,28999,29077,
+    1,29076,29091,29097,29083,29097,29081,29097,    2,29103,    1,29077,
+29089,29107,    2,29107,28852,29077,    0,29076,    2,29115,29107,29116,
+29110,29115,29107,29115,    2,29122,18966,29076,18966,29077,29097,29129,
+28991,29129,    9,29129,27323,29077,23651,29077,26907,29077, 9755,29077,
+ 9317,29077, 4321,29077, 3833,29077,10171,29077, 4295,29077,21183,29077,
+ 1413,29077,  922,29077,26940,29077,28851,29077,18967,29162,19396,29077,
+29127,29167,19683,29077,18967,29076,29079,29173,29134,29173,29129,29173,
+    9,29178,    9,29173,29129,29182,26625,29077,18967,29186,21399,29077,
+    9,29077,18967,29192,29127,29195,18967,29193,29129,29199,20839,29077,
+  483,29077,  903,29204,  903,29077,  483,29208,18967,29077,29115,29213,
+28851,29212,29127,29213,    9,29219,26625,29212,    9,29212,29127,29225,
+    6,28715,29083,29229,29097,29230,29091,29229,29097,29234,29098,29229,
+29100,29229,29105,29229,29109,29229,29119,29229,29121,29229,29125,29229,
+29111,29229,29115,29253,24907,29229,25639,29229,22369,29229,28600,29229,
+28557,29229,28654,29229,22057,29229,29178,29229,29160,29229,19706,29229,
+10737,29229,10475,29229,10979,29229,19597,29229,12137,29229,29219,29229,
+29215,29229,29130,29229,29222,29229,29129,29229,29173,29294,29097,29294,
+29188,29229,29097,29229,29091,29302,29083,29302,29129,29302,    1,29229,
+    5,29310,    5,29229,    1,29314,29173,29229,29129,29318,19687,29229,
+19631,29322,26940,29229,29077,29326,10697,29229, 8165,29331,19631,29229,
+19687,29334,21575,29229,20273,29229,28573,29340,28625,29340,29186,29229,
+18967,29346,19384,29229,19559,29351,28625,29229,20273,29354,28573,29229,
+20273,29358,   11,29229,18967,29362,19559,29365,18967,29363,19631,29369,
+  587,29229,21605,29373,29313,29375,29317,29375,26625,29229,29212,29380,
+18967,29380,29077,29384,29077,29380,18967,29388,29212,29229,29127,29393,
+29115,29393,26625,29392,18967,29229,29186,29400,29077,29401,29173,29405,
+29097,29405,26625,29400,29077,29410,   11,29401,19687,29415,   11,29400,
+19559,29419,29077,29400,29127,29423,26625,29422,29115,29423,29077,29229,
+26940,29430,26625,29430,18967,29434,18967,29430,29127,29439,26625,29438,
+29115,29439,18967,29431,29129,29447,    7,28715,28791,29451,29041,29451,
+19625,29451,21549,29451,21105,29451,26625,29450,29031,29463,18967,29465,
+ 1275,29451,  903,29469,29031,29451,26940,29473,26625,29473,18967,29476,
+18967,29473,26625,29480,20763,28714,28635,29485,28855,29485,20839,29485,
+20413,29491,20413,29484,20839,29495,    9,29485,20762,28715,28941,29501,
+29495,29501,28773,29501,20815,29501,20993,29501,21027,29501,28985,29501,
+29498,29501,29485,29501,20413,29519,    9,29518,20985,29501,20413,29525,
+    9,29501,29485,29528,21527,28714,29229,29533,    9,29533,26940,28715,
+20413,29539, 9731,28715,    7,29543,26625,28715,20762,29547,    6,29547,
+    7,29547,29400,29553,29229,29553,18967,29556,18967,29552,18967,29553,
+29229,29562,    6,29546,29553,29567,    7,29546,29551,29571,29031,29571,
+18967,29575,18967,29546,20413,29579,18967,29547,20501,29583,    6,29582,
+    7,29582,    6,29583,29589,29591,    7,29583,29587,29595,  903,28715,
+    7,29599,18967,28715,21183,29602,24673,29605,21183,29603,21795,29609,
+23457,29602,20413,29613,27787,29602,20413,29617,27533,29602,20413,29621,
+20413,29603,27787,29625,26889,29625,26625,29625,27533,29625,23457,29625,
+26889,29602,20413,29637,26625,29602,20413,29641,21315,28715,21183,29645,
+24673,29645,25709,29645,    7,29645,  483,29644,    9,29644,18967,28714,
+27965,29659,27948,29659,26816,29659,26898,29659,27796,29659,24953,29659,
+20119,29659,25129,29659,29653,29659,26887,29659,23480,29659,25099,29659,
+21605,29659,    6,29684,29645,29687,29451,29659,28625,29691,28573,29691,
+20187,29659,28625,29659,19683,29659,20839,29659,21399,29659,28573,29659,
+27787,29659,20501,29708,20501,29659,27787,29712,26889,29712,26625,29712,
+27533,29712,23457,29712,27533,29659,20501,29724,   17,29659,    6,29658,
+26816,29731,24953,29731,29451,29731,   17,29731,20501,29731,26625,29740,
+26625,29731,20501,29744,    7,29658,29697,29749,20103,29749,20186,29659,
+29731,29755,    6,29659,29752,29759,24941,29759,23175,29759,29645,29759,
+28133,29759,21605,29758,29645,29771,20103,29759,29749,29774,29077,29759,
+29749,29759,20103,29780,   11,29759,20763,29759,26625,29787,    7,29659,
+29731,29791,20103,29793,20103,29790,29731,29797,23457,29659,20501,29800,
+26889,29659,20501,29804,20103,29659,    7,29809,29759,29811,    7,29808,
+29731,29815,26625,29659,20501,29818,    6,29819,    7,29819,    6,29818,
+29825,29827,    7,29818,29823,29831,21036,21605,27965,29835,27951,29835,
+27948,29835,26816,29835,27796,29835,26898,29835,27216,29835,28151,29835,
+28101,29835,26887,29835,21194,29835,24673,29857,24675,29835,21069,29835,
+21267,29835,21305,29835,24953,29835,20119,29835,22723,29835,25129,29835,
+25063,29835,23480,29835,21796,29835,21795,29835,20501,29882,25099,29835,
+18967,29835,21183,29889,21795,29891,21183,29888,24673,29895,21259,29835,
+20103,29899,21183,29835,27021,29902,18967,29902,24673,29907,20187,29835,
+21127,29911,28573,29835,28625,29835,19683,29835,20839,29835,21399,29835,
+27787,29835,20501,29924,27533,29835,20501,29928,27021,29835,21183,29932,
+20501,29835,27787,29936,26889,29936,26625,29936,27533,29936,23457,29936,
+21795,29936,   17,29835,    6,29834,26816,29953,21069,29953,21267,29953,
+24953,29953,21305,29953,25063,29953,21259,29953,20103,29967,   17,29953,
+20501,29953,26625,29972,26625,29953,20501,29976,    7,29834,21242,29981,
+29911,29981,21049,29981,21183,29981,20103,29988,20103,29981,21183,29992,
+20186,29835,29953,29997,21105,29997,    6,29835,28133,30003,21279,30003,
+21166,30003,29992,30003,23175,30003,24941,30003,20103,30003,21127,30016,
+29981,30016,21127,30003,20103,30022,29981,30003,20103,30026,   11,30003,
+20763,30003,26625,30033,    7,29835,21105,30037,20103,30039,29953,30037,
+20103,30043,20103,30036,29953,30047,21105,30047,23457,29835,20501,30052,
+26889,29835,20501,30056,26625,29835,20501,30060,    6,30061,    7,30061,
+    6,30060,30067,30069,    7,30060,30065,30073,20103,29835,    7,30077,
+30003,30079,21183,30079,    7,30076,29953,30085,21105,30085,    4,21605,
+26371,30091,26450,30091,26539,30091,26542,30091,27439,30090,27483,30101,
+17048,30091,26496,30091,26452,30091,26373,30091,26466,30091,26386,30091,
+  586,30091,  803,30117,  586,30090,  767,30121,    1,30091,   15,30124,
+    2,30124,    7,30124,26219,30131,    7,30125,23755,30135,26331,30135,
+27805,30135,25793,30135,    1,30090,26454,30145,26375,30145,26415,30145,
+26219,30150,26219,30145,26415,30154,26292,30145,26331,30159,25793,30145,
+    7,30162,26331,30165,    7,30163,26219,30169,    7,30145,25793,30173,
+26415,30175,25793,30172,26331,30179,    3,30090,  767,30183,26454,30091,
+18967,30186,26375,30091,18967,30190,28159,30091, 8684,30091, 8647,30091,
+26154,30091,26331,30201,26534,30091,26541,30205,26536,30091,26331,30209,
+26320,30091,26331,30213,19384,30091,20501,30217,19474,30091,20611,30091,
+ 9989,30091,20762,30090,20985,30227,27436,30091,20501,30231,27507,30231,
+27451,30231,27453,30231,26492,30091,26219,30240,26278,30091,26415,30244,
+26219,30091,26541,30248,26492,30248,26415,30248,18967,30254,18967,30248,
+26415,30258,27021,30091,18967,30263,20413,30265,18967,30262,20501,30269,
+21527,30091,    9,30273,21258,30091,21575,30091,20501,30279,20985,30091,
+20501,30090,27907,30285,27483,30285,  340,30091,    9,30091,  483,30091,
+26292,30091,26331,30297,18967,30299,18967,30296,26331,30303,20413,30091,
+20763,30307,25793,30309,26197,30091,26415,30312,  375,30091,24095,30091,
+18967,30319,20413,30321,18967,30318,20501,30325,24252,30091,20501,30329,
+   15,30091,    1,30332,18967,30332,   11,30091,18967,30339,20413,30341,
+18967,30338,20501,30345, 1369,30339, 9565,30349,28741,30349,30129,30349,
+27979,30339,19631,30357,11949,30357, 4669,30357,26415,30091,    1,30365,
+26219,30367,26197,30364,26278,30364,26219,30364,18967,30374,18967,30364,
+26219,30378,18967,30365,26219,30383, 1369,30090,20029,30387,19781,30387,
+21103,30387,26541,30091,26219,30394,    6,30090,23646,30399,23642,30399,
+23606,30399,24349,30399,26086,30399,26062,30399,26068,30399,24583,30399,
+24591,30399,19384,30399,24265,30419,25793,30399,19631,30422,11949,30422,
+ 4669,30422,11949,30399,23493,30430,25793,30430, 4669,30399,23493,30436,
+25793,30436,19631,30399,23493,30442,25793,30442,   11,30399,18967,30448,
+24265,30451,18967,30399,   11,30454,24265,30457,   11,30455,23493,30461,
+25793,30461,23493,30399,11949,30466, 4669,30466,19631,30466,    7,30090,
+21549,30475,21105,30475,19625,30475,    6,30091,26524,30483,26545,30485,
+26524,30482,26541,30489,    7,30091,26525,30492,30455,30493,25793,30497,
+    2,30493,    0,30500,30422,30503,25793,30503,30399,30506,30399,30503,
+25793,30510,    0,30493,    2,30514,30422,30517,25793,30517,30399,30520,
+30399,30517,25793,30524,    1,30492,26219,30529,18966,30493,30422,30533,
+25793,30533,30399,30536,30399,30533,25793,30540, 8495,30492,21183,30493,
+ 8495,30493,26524,30492,26331,30551,21037,30492,25793,30492,26331,30557,
+18967,30559,18967,30556,26331,30563,  265,30492,  265,30493,25793,30493,
+26541,30571,30495,30571,26492,30571,26415,30571,18967,30578,18967,30571,
+26415,30582,18967,30492,26219,30587,25793,30586,26331,30591,25793,30587,
+26415,30595,20763,30090,26142,30599,24849,30599,25793,30599,20413,30604,
+20413,30599,25793,30608,20762,30091,26219,30613,20885,30613,25793,30612,
+26331,30619,25793,30613,26415,30623,26524,30091,20501,30627,    6,30626,
+26541,30631,    7,30626,26331,30635,    6,30627,26537,30639,30635,30639,
+    7,30627,30631,30645,26219,30645, 8495,30091,    7,30650,25793,30091,
+    1,30655,    7,30656,26219,30659,    7,30657,26331,30663,20762,30654,
+26331,30667,20762,30655,26197,30671,26219,30671,    6,30655,    7,30655,
+26197,30679,26278,30679,    1,30678,26219,30685,26219,30679,18967,30688,
+18967,30678,26219,30693,18967,30679,26219,30696,    6,30654,30679,30701,
+    7,30654,26331,30705,18967,30707,30677,30705,18967,30704,26331,30713,
+18967,30654,20501,30717,    6,30716,    7,30716,26331,30723,    6,30717,
+30723,30727,    7,30717,30721,30731,26219,30731,18967,30655,20413,30737,
+    7,30736,26219,30741,    7,30737,26331,30745,  265,30091,    0,30748,
+    6,30751,21605,30752,21605,30751,    6,30756,    6,30757,    7,30748,
+30755,30763,30759,30763,    7,30749,30761,30769,18967,30091,26454,30772,
+26375,30772,26292,30772,26331,30779,   11,30772,20501,30783,   15,30772,
+27021,30772,20501,30789,20501,30773,25793,30793,27021,30793,24095,30793,
+26415,30772,26219,30800,20187,30773,25793,30805,26219,30772,26415,30808,
+24095,30772,20501,30813,    6,30773,26604,30817,29645,30817,25793,30817,
+20103,30822,20103,30817,25793,30826,    7,30773,26331,30831,27805,30831,
+23755,30831,25793,30831,    6,30772,30831,30841,    7,30772,26219,30845,
+25793,30844,26331,30849,30817,30845,25793,30845,26415,30855,25793,30772,
+20501,30859,    6,30858,    7,30858,26331,30865,    6,30859,30865,30869,
+    7,30859,30863,30873,26219,30873,20103,30773,26219,30879,    7,30879,
+25793,30883,21037,30091,    6,30887,    7,30887,    6,30886,30891,30893,
+    7,30886,30889,30897,18967,30090,27530,30901,26142,30901,26009,30901,
+26270,30901,28571,30901,26454,30901,26375,30901,24210,30901,27459,30901,
+26219,30901,20273,30920,26415,30920,20413,30901,25793,30926,27021,30926,
+24095,30926,27021,30901,20413,30934,20985,30901,24095,30901,20413,30940,
+20352,30901,25793,30945,26292,30901,26331,30949,    7,30901,25793,30953,
+20273,30955,26415,30955,20273,30952,25793,30961,25793,30952,26331,30965,
+26415,30901,26219,30968,20273,30901,26219,30972,    7,30972,25793,30977,
+25793,30901,20413,30980,    7,30981,26219,30985,    7,30980,26331,30989,
+21314,21605,27530,30993,26142,30993,26270,30993,26009,30993,26454,30993,
+26375,30993,28571,30993,24795,30993,24799,30993,24210,30993,21850,30993,
+21845,30993,20413,31016,27459,30993,18967,30993,    6,31023,29645,31025,
+26219,30993,20273,31028,26415,31028,27021,30993,20413,31034,20413,30993,
+25793,31038,27021,31038,24095,31038,21845,31038,20985,30993,24095,30993,
+20413,31050,26292,30993,26331,31055,20352,30993,25793,31059,    7,30993,
+25793,31063,20273,31065,26415,31065,25793,31062,26331,31071,20273,31062,
+25793,31075,26415,30993,26219,31078,25793,30993,20413,31082,    7,31083,
+26219,31087,    7,31082,26331,31091,20273,30993,26219,31094,    7,31094,
+25793,31099,    6,21605,27347,31103,27401,31103,27378,31103,27327,31103,
+27380,31103,27329,31103,27263,31103,27377,31116,27285,31103,27059,31103,
+27377,31122,27194,31103,27203,31103,27215,31103,27208,31103,27228,31103,
+27233,31103,27188,31103,27187,31103,27184,31103,27183,31103,27294,31103,
+27275,31103,27305,31103,27280,31103,27481,31103,27470,31103,27341,31103,
+27394,31103,27122,31103,27390,31103,27337,31103,26796,31103,26802,31103,
+30939,31103,30229,31103,30616,31103,31049,31103,28681,31103,20843,31180,
+28686,31103,22287,31103,28661,31103,28649,31103,27502,31103,27513,31103,
+25030,31103,24983,31103,30283,31103,25683,31103,21058,31103,29835,31205,
+21195,31103,29835,31209,25629,31103,13894,31103,13919,31103,27498,31103,
+27509,31103,27930,31103,27895,31223,27857,31103,    4,31226,27895,31229,
+    4,31227,27907,31233,27479,31103,27468,31103,27500,31103,27511,31103,
+26941,31103, 9457,31103,30118,31103,30185,31103,30123,31103,30105,31103,
+26742,31103, 9444,31103, 9435,31103,  713,31260,30751,31102,30763,31265,
+30221,31103,19397,31102,28777,31271, 3119,31103, 3027,31103, 3805,31103,
+ 4820,31103, 6469,31103, 3419,31103,27422,31103,27359,31103,27392,31103,
+27339,31103,27343,31103,27396,31103,27404,31103,27351,31103,27352,31103,
+27407,31103, 9539,31103,24554,31103,29659,31102,29645,31311,17294,31103,
+26843,31103,30335,31103,26845,31103,25689,31103,30337,31103,30787,31103,
+24552,31103,25157,31103,24881,31103,28387,31103,28386,31102,31335,31337,
+28387,31102,28386,31103,31341,31343,27287,31103,27323,31347,30127,31103,
+30117,31103,  803,31352,    3,31103,    0,31356,27277,31103,20273,31360,
+27377,31360,27461,31103,20273,31366,27483,31366,27377,31366,27205,31103,
+20273,31374,27377,31374,27218,31103,27316,31103,27398,31103,18967,31384,
+27345,31103,18967,31388,  413,31103,30292,31103,26986,31103,26982,31103,
+ 9287,31103,27224,31103,20273,31402,27323,31403,21276,31103,29835,31409,
+21496,31103,27021,31412,27021,31413,21277,31103,27021,31418,27021,31419,
+21183,31419, 6441,31103,  759,31427, 4403,31103,17075,31103,16329,31103,
+ 4919,31103,17099,31103, 9362,31103, 5309,31103, 4547,31103,27291,31103,
+20273,31446,27323,31447,26810,31103,26990,31103,  777,31103,  824,31103,
+  244,31103, 4933,31103, 5297,31103,17077,31103,13019,31103,12705,31103,
+13673,31103,18391,31103,18617,31103,14597,31103,27210,31103,27323,31481,
+27472,31103,27323,31485,27300,31103,27323,31489,26317,31103,26476,31103,
+ 9134,31103, 1216,31103,19687,31103,26625,31500,19397,31103,29659,31505,
+29835,31505,22655,31505,23622,31103,27410,31103,22139,31103,22163,31103,
+24543,31103,24557,31103,  305,31103,21036,31102,26816,31527,25063,31527,
+31245,31527,21069,31527,21267,31527,21305,31527,24953,31527,21259,31527,
+20103,31543,   17,31527,20501,31527,26625,31548,26625,31527,20501,31552,
+26415,31103,    9,31556,26940,31103,29645,31103,29659,31563,27418,31103,
+27255,31566,27272,31103,27377,31570,27255,31103,27483,31574,27418,31574,
+27377,31574,18967,31580,18967,31574,27377,31584, 8446,31103,  155,31103,
+17049,31103, 1369,31593, 8861,31103,26625,31103,21127,31598,20843,31598,
+19687,31598, 8337,31598,20103,31598, 7971,31598, 9565,31598,18967,31598,
+ 9731,31103,27021,31616,30613,31103,20885,31620, 9617,31102,26973,31625,
+ 8337,31103,24545,31628,26625,31628,    9,31628, 4819,31103,  713,31636,
+13857,31103,  713,31640, 4543,31103,21372,31103,21315,31103,27190,31648,
+27483,31648,25027,31648,27021,31649,20273,31657,27377,31657,27021,31648,
+20273,31662,27323,31663,20273,31648,27021,31668,27021,31669,   11,31648,
+21037,31103,29835,31677,20103,31679,20763,31676,29835,31683,20103,31676,
+29835,31687,  713,31103,13857,31690, 9435,31690, 4819,31690,  803,31690,
+   25,31103, 7971,31103,26625,31702,20884,31103,29659,31707,29835,31707,
+20984,31103,28659,31713,28625,31713,30227,31713,22285,31713,17233,31103,
+  903,31722,30091,31103,    9,31726,20162,31103,20171,31103,25027,31103,
+21315,31734,27190,31103,21315,31738,21127,31103,26625,31742,20843,31103,
+26625,31746,28681,31746, 9565,31103,26625,31752, 8997,31103,    9,31756,
+  766,31103, 9455,31761,30121,31761, 3803,31761,  759,31761,    9,31103,
+27021,31770,30091,31770, 9195,31770,  241,31770,26415,31770, 8997,31770,
+27377,31770,23493,31770, 8337,31770,20103,31770, 1011,31103,  903,31792,
+  241,31103,    9,31796,27297,31103,27282,31103,27323,31803,18967,31805,
+18967,31802,27323,31809,   17,31803,20103,31103,24545,31814,26625,31814,
+21037,31814,29835,31821,    9,31814,21037,31815,25793,31827,20273,31103,
+27224,31830,27291,31830,27205,31830,27277,31830,27461,31830,21315,31830,
+27021,31842,27021,31843,27021,31830,21315,31848,27231,31103,27377,31852,
+  803,31103,30117,31856,  713,31856,20885,31103,27021,31862,30613,31862,
+23493,31103,    9,31868,24545,31103,20103,31872, 8337,31872,   17,31873,
+   11,31103,28715,31881,19631,31883,11949,31883, 4669,31883,21315,31880,
+ 8451,31103,27377,31103,27059,31894,27263,31894,27205,31894,27231,31894,
+27461,31894,27272,31894,27277,31894,27255,31894,18967,31910,    9,31894,
+18967,31894,27255,31916,  903,31103,17233,31920, 1011,31920,  257,31103,
+27483,31103,21315,31928,27461,31928,27255,31928,    4,31102,23646,31937,
+23642,31937,23606,31937,24349,31937,26086,31937,26062,31937,26068,31937,
+24583,31937,24591,31937,19384,31937,24265,31957,25793,31937,19631,31960,
+11949,31960, 4669,31960,11949,31937,23493,31968,25793,31968, 4669,31937,
+23493,31974,25793,31974,19631,31937,23493,31980,25793,31980,   11,31937,
+18967,31986,24265,31989,18967,31937,   11,31992,24265,31995,   11,31993,
+23493,31999,25793,31999,23493,31937,11949,32004, 4669,32004,19631,32004,
+    5,31102,26940,32013,20413,32015,18967,32012,26816,32019,24953,32019,
+31245,32019,   17,32019,20501,32019,26625,32028,26625,32019,20501,32032,
+26625,32013,18967,32036,20413,32039,18967,32037,20501,32043,18967,32013,
+20413,32047,26625,32049,26625,32046,20413,32053,    4,31103,27857,32057,
+27879,32059,27857,32056,27895,32063,20763,32056,29835,32067,29659,32067,
+28715,32057,29083,32073,29091,32073,19631,32073,11949,32073, 4669,32073,
+29129,32073,18967,32073,29077,32087,18967,32056,23147,32091,24819,32091,
+28925,32091,28715,32091,20413,32099,    5,31103,27437,32102,19397,32103,
+21605,32103,20762,32108,20762,32109,  586,32108,  586,32109,31993,32103,
+25793,32119,    2,32103,21605,32123,    0,32122,31960,32127,25793,32127,
+31937,32130,31937,32127,25793,32134,32073,32127,    0,32103,21605,32141,
+    2,32140,31960,32145,25793,32145,31937,32148,31937,32145,25793,32152,
+32073,32145,  586,32140,  586,32141,21605,32102,18966,32102,18966,32103,
+21605,32167,    7,32169,    9,32167,31960,32167,25793,32167,31937,32176,
+31937,32167,25793,32180,32073,32167,    1,32103,32125,32187,31937,32189,
+    3,32103,32143,32193,31937,32195,28573,32103,28625,32103,20843,32201,
+ 9195,32103,20501,32103,21183,32103,27436,32102,27323,32211, 9377,32103,
+  713,32215, 9875,32103,19396,32103,32165,32221,    9,32103,18967,32224,
+32165,32227,18967,32225,32167,32231,20763,32102,22285,32235,28659,32235,
+28625,32235,32111,32235,30227,32235,30772,32103,20501,32247,27021,32102,
+27323,32251,18967,32253,18967,32250,27323,32257,   17,32251, 1369,32103,
+  903,32103,    9,32265,  587,32102, 9455,32269,32159,32269,32115,32269,
+ 3803,32269,30121,32269,  759,32269,25673,32103,20501,32283,20763,32103,
+32113,32287,27021,32287,30613,32287,  587,32103,32161,32295,32117,32295,
+30117,32295,  713,32295,27021,32103,27483,32305,32105,32305,27418,32305,
+27377,32305,18967,32312,18967,32305,27377,32316,31992,32103,32163,32321,
+18967,32103,32163,32325,31937,32327,32165,32325,    9,32331,    9,32324,
+32165,32335,30091,32324,20501,32339,31937,32324,32163,32343,31937,32103,
+18967,32346,32163,32349,30091,32103,    9,32353,18967,32352,20501,32357,
+18967,32353,20413,32361,18967,32102,24953,32365,32171,32365,32107,32365,
+32172,32365,32167,32365,    9,32374,    9,32365,32167,32378,27021,32364,
+27323,32383,27021,32365,27377,32387,21037,31102,26604,32391,31561,32391,
+31615,32391,29645,32391,25793,32391,20103,32400,20103,32391,25793,32404,
+21314,31103,23147,32409,24819,32409,28925,32409,28715,32409,20413,32417,
+21036,31103,25673,32421,20501,32423,25087,32421,25691,32421,22357,32421,
+24953,32421,21049,32421,21242,32421,21183,32421,20103,32438,27021,32420,
+27323,32443,20103,32421,21183,32446,27021,32421,27377,32451,27436,31103,
+    5,32454,27323,32457,    5,32455,27255,32461, 9195,31103,    9,32464,
+27021,31103,21496,32468,21277,32468,20885,32468,    9,32468, 9731,32468,
+21037,32468,21315,32468,20273,32482,27323,32483,21037,32469,21315,32469,
+27205,32491,21036,32468,27323,32495,32489,32495,21036,32469,27231,32501,
+32481,32501,20273,32468,21315,32506,    4,32469,    5,32469,27231,32513,
+27272,32513,27255,32513,18967,32518,18967,32513,27255,32522,    9,32513,
+    4,32468,32513,32529,    5,32468,27323,32533,18967,32535,32511,32533,
+18967,32532,27323,32541,   17,32533,18967,32468,    5,32546,27323,32549,
+    5,32547,27255,32553,  587,31103,30091,32557,  803,32559,    5,32556,
+ 9455,32563, 3803,32563,30121,32563,  759,32563,    5,32557, 9435,32573,
+  803,32573,18967,31103,32391,32579,26625,32581,27398,32578,27345,32578,
+21605,32578,    7,32589,    4,32591,    4,32590,    4,32589,    7,32596,
+   16,32589,27282,32578,27323,32603,26625,32578,32391,32607,27377,32578,
+27255,32610,20483,32579,25793,32615,27255,32578,27377,32618,21183,32579,
+26625,32623,    4,32579,26142,32627,24849,32627,21605,32627,    7,32633,
+25793,32627,20413,32636,20413,32627,25793,32640,    5,32579,32593,32645,
+    4,32578,24819,32649,23147,32649,28925,32649,28715,32649,20413,32657,
+    5,32578,24953,32661,32595,32661,32599,32661,32635,32661,32601,32661,
+27021,32660,27323,32673,27021,32661,27377,32677,27021,32578,    5,32680,
+27323,32683,    5,32681,27255,32687,20763,31103,18967,32691,    5,32692,
+    5,32693,21037,32690,29835,32699,29659,32691,29835,32691,21036,32691,
+21037,32691,25793,32709,30091,32691,20885,32713,    4,32691,32697,32717,
+    5,32691,18967,32720,28681,32721,    4,32690,32723,32727,32695,32727,
+29659,32727,29835,32727,32707,32727,    5,32690,28625,32739,22285,32739,
+28659,32739,30227,32739,32709,32739,18967,31102,    5,32750,26816,32753,
+24953,32753,31245,32753,   17,32753,26625,32753,20501,32762,20501,32753,
+26625,32766,    5,32751,    9,32771,30091,32771,20501,32775,21526,21605,
+    5,32778,26816,32781,24953,32781,   17,32781,26625,32781,20501,32788,
+20501,32781,26625,32792,    5,32779,    9,32797,30091,32797,20501,32801,
+18967,21605,20355,32804,20354,32804,26415,32805,26219,32810,26454,32805,
+26375,32805,21127,32805,21183,32818,21248,32805,21273,32805,20986,32805,
+20987,32805,28109,32804,28108,32805,32831,32833,31676,32805,31527,32837,
+28109,32805,28108,32804,32841,32843,20352,32805,    4,32847,22729,32849,
+22731,32847,32809,32847,20486,32805,26292,32805,26331,32859,19622,32804,
+19623,32805,32863,32865,19623,32804,19622,32805,32869,32871,  386,32805,
+  347,32805,21396,32804,21397,32805,32879,32881,21546,32804,21547,32805,
+32885,32887,21397,32804,21396,32805,32891,32893,21547,32804,21546,32805,
+32897,32899,20477,32805,27673,32805,20476,32805,27672,32805,21127,32804,
+21087,32911,29031,32804,31881,32805,21543,32805,21087,32805,21127,32921,
+31880,32805,21542,32805,26219,32805,26415,32928,27283,32805,31103,32933,
+20353,32805,32807,32937,20487,32805,21403,32804,21402,32805,32943,32945,
+21573,32804,21572,32805,32949,32951,21403,32805,21402,32804,32955,32957,
+21573,32805,21572,32804,32961,32963,20985,32804,32829,32967,21401,32804,
+32056,32805,29450,32805,29041,32975,28791,32975,29731,32975,29659,32975,
+20984,32805,21400,32805,32971,32987,32103,32805,    7,32990,32365,32993,
+32057,32805,29451,32805,32915,32999,20984,32804,32827,33003,20985,32805,
+31103,33007,    7,33006,33003,33011,21400,32804,21401,32805,33015,33017,
+21183,32805,21127,33020,20413,32805,    4,33025,    4,33024,   11,33024,
+27533,32805,   17,33032,20273,32805,    7,33037,    7,33036,   15,33037,
+25793,32805,    7,33045,26219,33047,    7,33044,26331,33051,21527,32805,
+   17,33054,31103,32805,    4,33059,21037,33059,32421,33063,21037,33058,
+31527,33067,    4,33058,   11,33058,21037,32805,31103,33075,32391,33077,
+31103,33074,31527,33081,28715,32805,29031,33085,    7,33085,29759,33089,
+21527,33085,29229,33093,    7,33084,29041,33097,29731,33097,29659,33097,
+28791,33097,   15,33085,  580,32805, 1170,32805,  256,32805,  629,32805,
+ 1413,32805,  922,32805,  581,32805, 1171,32805,  767,32805,31103,33125,
+  375,32805,  305,33128,  510,32805,   18,32804,   12,32804,23493,33137,
+ 1291,32805,  525,32805,   13,32805,22807,33145,33137,33145,   19,32805,
+33135,33151,   18,32805,   13,32804,   12,32805,33157,33159,   19,32804,
+33155,33163,   16,32805,32421,33167,25743,33167,32365,33167,32661,33167,
+27533,33167,21037,33167,31103,33179,   10,32805,19333,33183,33137,33183,
+31648,33183,19455,33183,24237,33183,22896,33183,19393,33183,19385,33183,
+    9,33199,22807,33183,    9,33202,20413,33183,    9,33183,22807,33208,
+21315,33183,31103,33212,31103,33183,21315,33216,   14,32804,32847,33221,
+33041,33221,24953,33221,32975,33221,33097,33221,26816,33221,33167,33221,
+33111,33221,   17,33221,20501,33221,26625,33240,26625,33221,20501,33244,
+   10,32804,22149,33249,19441,33249,24213,33249,24059,33249,19656,33249,
+    9,33249,19631,33260,19631,33249,    9,33264,23983,33249,    9,33269,
+  524,32805, 1290,32805,   11,32804,21087,33277,20326,33277,33183,33277,
+    9,33283,    9,33276,23493,33287,33183,33287,23493,33277,    9,33293,
+20273,33277,    9,33296,    9,33277,20273,33300,    9,32804,   11,33304,
+23493,33307,33183,33307,   11,33305,24265,33313,33249,33313,   15,32804,
+32937,33319,32999,33319,26142,33319,33123,33319,20413,33319,25793,33328,
+20273,33319,25793,33319,20413,33334,   11,32805,24567,33339,33157,33339,
+24428,33339,20413,33338,31103,33338,33260,33339,33249,33339,    9,33352,
+24265,33339,    9,33356,    9,33339,24265,33360,33249,33360,  483,33338,
+    9,32805,30090,33368,30090,33369,30091,33368,33373,33375,  483,33368,
+   11,33369,20273,33381,30091,33369,33371,33385,20501,33385,   17,32805,
+19474,33390,19475,33391,33393,33395,21314,33390,19474,33391,19475,33390,
+33401,33403,21314,33391,21315,33390,33407,33409,27533,33390,21527,33390,
+33319,33391, 1275,33390,21315,33391,33399,33421,  305,32805,  375,33424,
+ 1011,32805,    7,33428,33221,33431,   15,33429,    7,33429,  241,32805,
+    7,33438,  483,32805,    4,33442,  903,33442,    9,33442,    4,33443,
+   11,33442,  903,32805,    9,33455,  483,33454, 1275,32805,   17,33460,
+    7,32805,20985,33464,33003,33467,20985,33465,32985,33471,25672,33465,
+30772,33465,25673,33465,30773,33465,21036,33465,30090,33465,20273,33464,
+33221,33487,25793,33464,26331,33491,28715,33464,29731,33495,29659,33495,
+28791,33495,29041,33495,33221,33495,18967,33465,    5,33506,30091,33506,
+    5,33507,33485,33513,   17,33507,21605,33465,    4,33518,33513,33521,
+21037,33518,    4,33519,33509,33527,33483,33527,   11,33519,25793,33465,
+26415,33535, 1011,33464,33221,33539,  241,33464, 8495,33465,32103,33465,
+20273,33547,32165,33547,21037,33465,21604,33553,21605,33552,33555,33557,
+21605,33553,21604,33552,33561,33563,28715,33465,20273,33567,29533,33567,
+30091,33465,18967,33572,33221,33465,20273,33577,23927,33465,20273,33581,
+29031,33465,20273,33585,32013,33465,20273,33589,   15,33465,29835,33465,
+29659,33465,29077,33597,32102,33465,    4,33465,24687,33603,25773,33603,
+21605,33602,33513,33609,31830,33603,32645,33603,29485,33603,22729,33603,
+31103,33603,20273,33620,20273,33603,31103,33624,    5,33465,18967,33628,
+33527,33631,31103,33628,20103,33629,31103,33637,    5,33464,33519,33641,
+    7,33641,21605,33645,33603,33647,33620,33641,33547,33641,33557,33641,
+33475,33641,33525,33641,33481,33641,31648,33641,20413,33641,33603,33641,
+31103,33666,21315,33641,31103,33670,31103,33641,33603,33674,21315,33674,
+    4,33464,33507,33681,25743,33681,33601,33681,32365,33681,32661,33681,
+33635,33681,33575,33681,33477,33681,33511,33681,33479,33681,32421,33681,
+33221,33681,27533,33681,33629,33681,31103,33709,21037,33681,31103,33713,
+31103,33465,    5,33716,33681,33719,    5,33717,33603,33723,    6,32804,
+33624,33727,33713,33727,33085,33727,29229,33733,33179,33727,21036,33727,
+33681,33739,33167,33739,28714,33727,33567,33745,18967,33727,    5,33749,
+33603,33751,    5,33748,33681,33755,33167,33755,20273,33727,33603,33760,
+33603,33727,20273,33764,29451,33727,   17,33727,    5,33726,26816,33773,
+33681,33773,24953,33773,33487,33773,33041,33773,33495,33773,33097,33773,
+32847,33773,32975,33773,33167,33773,33111,33773,33539,33773,33431,33773,
+   17,33773,33465,33773,20273,33803,26625,33773,20501,33806,20501,33773,
+26625,33810,    5,33727,33603,33815,18967,33814,33681,33819,33167,33819,
+    9,33815,33465,33815,20273,33827,30091,33815,20501,33831,33465,33727,
+18967,33834,    4,33837,    4,33836,21315,33834,21314,33834,    4,33835,
+33843,33847,    5,33835,33841,33851,33845,33851,    4,33834,18967,33856,
+33851,33859,33851,33857,    5,33834,33839,33865,33847,33865,    5,32805,
+27953,33871,27743,33871,27555,33871,    2,33870,    0,33870,    3,33870,
+    1,33870,33609,33871,33521,33871,30285,33871,33485,33871,32717,33871,
+25101,33871,33027,33871,33061,33871,23193,33871,33593,33871,33451,33871,
+20413,33871,20885,33871,33603,33871,27533,33913,23015,33871,20501,33917,
+27741,33871,20501,33921,    9,33871,30492,33871,    6,33871,33879,33929,
+33881,33929,20273,33929,    7,33871,33883,33937,33885,33937,25793,33937,
+32805,33936,    4,33945,21605,33937,33947,33949,    5,33949,33945,33953,
+33603,33949,30091,33936,21527,33937,27533,33937,21315,33963,    7,33870,
+31648,33967,20413,33967,31103,33967,21315,33972,21315,33967,31103,33976,
+21315,33871,21605,33981,33929,33983,30091,33871,20501,33987,    6,33986,
+    7,33986,    6,33987,33993,33995,    7,33987,33991,33999,    4,32804,
+27530,34003,26142,34003,26270,34003,26009,34003,33879,34003,33929,34012,
+33881,34003,33929,34016,33930,34003,33932,34003,33939,34003,33941,34003,
+33506,34003,33681,34029,33683,34003,33934,34003,33943,34003,26454,34003,
+26375,34003,33769,34003,32937,34003,32999,34003,33664,34003,32941,34003,
+33908,34003,32997,34003,28571,34003,33970,34003,33961,34003,18967,34003,
+33465,34062,33681,34065,33465,34063,33641,34069,33206,34003,33123,34003,
+33121,34003,24210,34003,33413,34003,33415,34003,32903,34003,32909,34003,
+33771,34003,32917,34003,32927,34003,33275,34003,33143,34003,27459,34003,
+33419,34003,33463,34003,33035,34003,33057,34003,33517,34003,26219,34003,
+20273,34110,26415,34110,24265,34003,28233,34003,29077,34003,33183,34003,
+20413,34122,33641,34003,20413,34126,33967,34003,20413,34130,33391,34003,
+27533,34135,20413,34003,25793,34138,27021,34138,33641,34138,33871,34138,
+33967,34138,33183,34138,24095,34138,27021,34003,20413,34154,33929,34003,
+33879,34158,33881,34158,20273,34158,20985,34003,31103,34167,   11,34003,
+21605,34171,33465,34003,18967,34174,33681,34177,24095,34003,20413,34180,
+26292,34003,26331,34185,20352,34003,25793,34189,33936,34003,33883,34193,
+33885,34193,25793,34193,    7,34003,25793,34201,20273,34203,26415,34203,
+33871,34201,33879,34209,33881,34209,20273,34209,25793,34200,26331,34217,
+20273,34200,25793,34221,33871,34200,33883,34225,33885,34225,25793,34225,
+26415,34003,26219,34232,20273,34003,26219,34236,33929,34236,    7,34236,
+25793,34243,25793,34003,20413,34246,    7,34247,26219,34251,    7,34246,
+26331,34255,33871,34003,18967,34258,    6,34261,    6,34260,21605,34259,
+33929,34267,21527,34258,31103,34259,21526,34258,20413,34258,    6,34259,
+34271,34279,    7,34259,34265,34283,34275,34283,    6,34258,34267,34289,
+18967,34288,34283,34293,34283,34289,    7,34258,33883,34299,33885,34299,
+34263,34299,34279,34299,25793,34299,    4,32805,    2,34311,    7,34313,
+27669,34311,23357,34311,32468,34311,28483,34311,27978,34311,31746,34311,
+31742,34311,31500,34311,20413,34310,23014,34311,31103,34310,21605,34311,
+    7,34338,    7,34339,33773,34343,33221,34343,   15,34338,27021,34311,
+31103,34350,28411,34311,33629,34311,20413,34357,  483,34310,31103,34311,
+27021,34362,20843,34362,21127,34362,19687,34362,19687,34311,31103,34372,
+20843,34311,31103,34376,21127,34311,31103,34380,   15,34311,21605,34384,
+  375,34311,33727,34311,    9,34391,    7,34311,21605,34394,25793,34395,
+  265,34395,31103,34395,    7,34310,33755,34405,33819,34405,33773,34405,
+33739,34405,25743,34405,32661,34405,32421,34405,32365,34405,33221,34405,
+27533,34405,21037,34405,33727,34427,31103,34427,21037,34311,33929,34433,
+26219,34433,    7,34433,25793,34439,28715,34311,20413,34443,    5,32804,
+27965,34447,27948,34447,26816,34447,27796,34447,26898,34447,20353,34447,
+29451,34447,32847,34447,33487,34447,33041,34447,32975,34447,33495,34447,
+33097,34447,34343,34447,34315,34447,33527,34447,33518,34447,33641,34481,
+33643,34447,24953,34447,20119,34447,33706,34447,34362,34447,32727,34447,
+25129,34447,34333,34447,33029,34447,34337,34447,33071,34447,32691,34447,
+34424,34447,34403,34447,32067,34447,31707,34447,26887,34447,32857,34447,
+32973,34447,21605,34447,33465,34522,33641,34525,33465,34523,33681,34529,
+33176,34447,33111,34447,33109,34447,31505,34447,23480,34447,33347,34447,
+33349,34447,32905,34447,32907,34447,32919,34447,32925,34447,33273,34447,
+33141,34447,25099,34447,33539,34447,34361,34447,33445,34447,33431,34447,
+33367,34447,33453,34447,33031,34447,33073,34447,33533,34447,20187,34447,
+19683,34447,20839,34447,21399,34447,33167,34447,27533,34586,33681,34447,
+27533,34590,34405,34447,27533,34594,28625,34447,28573,34447,33339,34447,
+20413,34603, 1171,34447,27787,34447,20501,34608,27533,34447,20501,34612,
+33681,34612,34405,34612,33167,34612,20501,34447,27787,34622,26889,34622,
+26625,34622,27533,34622,23457,34622,34395,34447,   17,34447,33465,34447,
+29077,34639,20273,34639,21605,34638,33641,34645,28233,34639,24265,34639,
+   11,34639,    6,34446,26816,34655,34405,34655,33041,34655,33097,34655,
+34343,34655,33681,34655,32847,34655,33487,34655,32975,34655,33495,34655,
+24953,34655,33167,34655,33111,34655,33539,34655,33431,34655,   17,34655,
+33465,34655,20273,34689,20501,34655,26625,34692,26625,34655,20501,34696,
+    7,34446,34635,34701,34579,34701,34311,34701,20103,34701,20186,34447,
+34655,34711,34394,34447,34655,34715,31103,34447,34311,34718,    6,34447,
+34706,34723,34395,34723,33039,34723,33089,34723,34397,34723,34341,34723,
+20273,34723,34708,34723,23175,34723,24941,34723,34325,34723,28133,34723,
+33437,34723,20103,34723,34701,34750,34701,34723,34311,34754,20103,34754,
+   11,34723,34311,34723,34701,34762,20763,34723,26625,34767,    7,34447,
+21605,34771,34311,34773,34655,34771,34311,34777,20103,34777,20103,34770,
+34655,34783,34311,34770,34655,34787,23457,34447,20501,34790,26889,34447,
+20501,34794,20103,34447,    7,34799,34723,34801,    7,34798,34655,34805,
+26625,34447,20501,34808,    6,34809,    7,34809,    6,34808,34815,34817,
+    7,34808,34813,34821,34311,34447,21605,34824,18967,34825,    6,34828,
+    6,34829,31103,34824,21527,34825,21526,34825,20413,34825,    6,34825,
+18967,34842,34827,34843,    7,34825,34723,34849,25793,34849,34833,34849,
+    6,34824,34849,34857,34837,34857,    7,34824,34655,34863,34845,34863,
+34831,34863,34843,34863,34839,34863,    6,32805,34236,34875,34120,34875,
+34433,34875,20962,34875,21001,34875,34118,34875,34355,34875,25648,34875,
+21314,34874,34891,34893,25649,34875,33087,34875,21314,34875,34116,34875,
+23017,34875,34335,34875,21937,34875,34170,34875,34173,34875,21959,34875,
+21315,34874,34897,34917,34385,34875,34387,34875,24875,34875,33332,34875,
+33435,34875,33043,34875,33107,34875,34349,34875,21605,34875,21315,34936,
+34893,34939,21315,34937,34901,34943,20273,34875,34003,34946,33319,34946,
+20885,34875,20843,34952,21315,34875,21605,34956,34893,34959,19475,34875,
+26625,34963,24265,34875,34003,34966,29077,34875,34003,34970,28233,34875,
+34003,34974,20843,34875,20885,34978,   11,34875,34003,34982,33319,34875,
+20273,34986,34003,34875,29077,34990,20273,34990,28233,34990,24265,34990,
+   11,34990,30993,34875,30901,34875,20984,34875,20839,35007,    5,34875,
+20763,35011,20843,35013,20763,35010,20839,35017,20763,34875,    5,35020,
+20839,35023,    5,35021,20885,35027,    7,32804,34736,35031,34459,35031,
+34461,35031,29691,35031,29340,35031,28714,35031,33603,35043,21605,35031,
+    5,35047,33681,35049,34405,35049,33167,35049,    5,35046,33603,35057,
+34607,35031,34637,35031,33924,35031,34447,35031,   11,35031,32103,35031,
+29835,35031,29659,35031,20273,35031,34723,35076,29229,35076,35011,35031,
+34723,35031,20273,35084,  567,35031,29229,35031,20273,35090,    9,35031,
+33871,35094,33871,35031,    9,35098,    4,35030,    5,35030,35083,35105,
+34875,35105,35010,35031,35103,35111,    4,35031,35108,35115,    7,35114,
+35049,35119,35105,35115,34875,35122,34875,35115,35105,35126,  483,35115,
+    5,35031,21605,35132,33603,35135,35103,35133,34875,35139,34875,35132,
+35103,35143,34875,35031,18967,35147,    4,35148,    4,35149,21315,35147,
+21314,35147,    4,35147,18967,35158,    5,35147,35115,35163,35153,35163,
+    4,35146,35163,35169,35155,35169,    5,35146,35103,35175,35161,35175,
+35151,35175,35159,35175,35157,35175,    0,    4,14087,35187,14103,35188,
+ 4983,35187, 5001,35192,14104,35187, 5002,35187,14088,35187,14091,35201,
+ 4984,35187, 4987,35205,14093,35187, 4989,35187,28758,35187,29229,35213,
+28741,35187,    2,35216,29229,35219,20501,35186,19463,35223,19317,35223,
+19301,35223,20009,35223,   53,35186,19463,35233,20009,35233,19317,35233,
+19053,35187,  989,35241, 1201,35187,18967,35245, 1203,35247,17673,35186,
+17685,35251,21405,35186,21489,35255,19513,35186,19463,35259,20009,35259,
+19317,35259,10157,35187,   17,35267,10159,35269,20343,35187,18967,35273,
+20345,35275, 1179,35187,  527,35186,19301,35281,19916,35186,    4,35285,
+    7,35286,    7,35285,    4,35290,   16,35285,19069,35186,19301,35297,
+ 1290,35186,    0,35301,    2,35302,    2,35301,    0,35306,18966,35301,
+21530,35187,20501,35313, 1489,35187,16859,35187,   11,35318, 9875,35321,
+21529,35187,   11,35324,20501,35327,  147,35187,16860,35187, 9875,35333,
+  987,35187, 8069,35187,   11,35338, 8067,35341, 8070,35187, 8067,35345,
+27519,35187,27525,35187,26322,35187,26566,35187,26102,35187,26276,35187,
+26105,35187,33464,35187,29600,35187,32295,35187,31856,35187,25636,35187,
+29229,35371,    9,35371,28555,35187,29229,35377,    9,35377,19301,35187,
+20501,35383,  527,35383,19069,35383, 4266,35187, 8056,35187, 8147,35187,
+20739,35187, 9997,35187, 8784,35187, 8622,35187, 8824,35187, 8702,35187,
+ 8697,35187, 8676,35187, 8635,35187,20828,35187,19772,35187,19890,35187,
+19774,35187,19894,35187,19382,35187,19458,35187,32557,35187,  803,35429,
+19463,35187,20501,35433,   53,35433,19513,35433,20009,35187,   53,35441,
+20501,35441,19513,35441,19317,35187,20501,35449,   53,35449,19513,35449,
+19914,35187,21066,35187,20575,35187,21312,35187,21270,35187,  694,35187,
+ 9377,35467,16920,35187,    9,35471,17621,35187,    9,35475, 4213,35187,
+  375,35478, 8757,35187,  375,35482, 9530,35187, 9875,35487,16091,35487,
+20501,35487,19751,35187,   53,35495,  253,35495,  117,35495,   71,35495,
+ 1471,35495, 1397,35187, 9592,35187,16514,35187,19380,35187,13836,35187,
+20595,35187, 9911,35187, 9983,35187, 9905,35187,17566,35187,16816,35187,
+17910,35187,18880,35187,14103,35187,14087,35532, 5001,35187, 4983,35536,
+20597,35187,26219,35187,  241,35542,  587,35543, 8647,35187,  241,35548,
+  587,35549,14073,35187,  586,35554,14091,35557,  586,35555,14103,35561,
+ 4971,35187,  586,35564, 4987,35567,  586,35565, 5001,35571, 1291,35187,
+35305,35575,35309,35575, 1871,35575, 1889,35575,    3,35575,19667,35575,
+12345,35575, 5123,35575,19067,35575,35311,35575,18967,35575, 1297,35597,
+35301,35597,19917,35187,35289,35603,35293,35603,19939,35603,19945,35603,
+    6,35603,19947,35603,35295,35603,   17,35603,19931,35619,35285,35619,
+ 1108,35187,   11,35625,22806,35187,    9,35629,  524,35187,    3,35633,
+ 3477,35633, 2007,35633,19051,35633,19667,35633,12345,35633, 5123,35633,
+18967,35633,  555,35649,  713,35187, 1325,35187,17455,35655,10001,35187,
+ 1505,35659, 9513,35187,   11,35662, 9875,35665,16091,35665,20501,35665,
+19396,35187,  483,35672,17455,35187,13737,35676,  803,35187,31103,35680,
+31103,35187,  803,35684,  113,35187,  375,35187,  587,35691, 9195,35693,
+ 4213,35690, 7971,35690, 8757,35690,  587,35690, 9377,35703, 9565,35690,
+18967,35690,19892,35187,    9,35710,  510,35187,18967,35714,  587,35187,
+  375,35718, 9377,35721, 9377,35719,  375,35725,  483,35187,19396,35728,
+  587,35729,   11,35728, 5123,35735,12345,35735, 3477,35735, 2007,35735,
+19667,35735,19051,35735,18967,35735,  555,35749,18967,35728,    9,35752,
+    9,35728,18967,35756, 1275,35187,16833,35760,    9,35763,  903,35761,
+    9,35761,21575,35187,18967,35771,21577,35773,21581,35773,21585,35773,
+ 6685,35187, 7519,35187,   17,35783, 7521,35785, 7525,35785, 7529,35785,
+21258,35187,  241,35792,16722,35187,32103,35187,    9,35799,10310,35187,
+ 8684,35187,  241,35804,  331,35805,26292,35187,  241,35810,  482,35186,
+    2,35815,    0,35816,35633,35819,35735,35819,    0,35815,    2,35824,
+35633,35827,35735,35827,35749,35815,35649,35815,18966,35815,35735,35837,
+35633,35837, 1368,35186,25793,35843, 8495,35843,23755,35843,10055,35843,
+ 4329,35843, 4311,35843,26331,35843,27805,35843, 3785,35843, 8717,35843,
+10351,35843,  586,35186,31761,35867,32563,35867,32269,35867,    7,35867,
+    4,35874,    4,35867,    7,35878,   16,35867,  767,35867,31103,35885,
+  482,35187,  587,35889, 1274,35187,  587,35186, 9262,35895,  375,35895,
+ 9195,35898,    7,35895,  265,35903, 9195,35905, 9195,35895,  375,35908,
+  483,35895,  483,35186, 1369,35186,19463,35917,19301,35917,20009,35917,
+19317,35917, 1368,35187,    7,35927,  586,35187,14073,35930,14091,35933,
+ 4971,35930, 4987,35937,31856,35931,32295,35931, 7971,35931,14073,35931,
+14087,35947, 4971,35931, 4983,35951,31103,35931,  803,35954,  803,35931,
+31103,35958,  483,35931, 1531,35187,13737,35187, 1487,35966,17455,35966,
+16833,35187, 1196,35972, 1196,35973, 1197,35972,35977,35979, 1197,35973,
+35975,35983, 1275,35972,    9,35987,  767,35187,31103,35991, 1487,35187,
+13737,35994,16937,35187,   17,35999, 9377,36001,17573,36001,16947,36001,
+ 1347,35187,18967,36009,  555,36011,  251,36011, 1365,36011, 1351,36011,
+   21,36011,20762,35187,  241,36022,  256,35187,25793,36026,25793,36027,
+ 8495,36026, 8495,36027,18967,36026,21037,36026,  972,35187, 9377,36041,
+  629,35187,18967,36044,  340,35187, 9377,36049,27978,35187,28353,36053,
+30003,36053,29759,36053,34723,36053,21183,36053,    2,36053,28337,36065,
+28189,36065,28191,36053,  959,36053,  759,36053,   47,36053,   66,35187,
+   89,35187,    7,36080,  973,35187,35895,36085,21527,35187,21605,36088,
+29229,36091,    9,36091,  145,35187,  165,35187,  305,35187,   25,35187,
+27533,35187, 1505,36105,  331,35187,17455,36109,   59,35187,17455,36113,
+29599,35187,    7,36116,26546,35187,    7,36120, 8812,35187,    7,36124,
+10291,35187,    3,36129,    3,36128, 9565,35187,  375,36134, 8495,35187,
+  256,36138,    7,36139,  375,36143,    7,36138,  241,36146,  331,36147,
+  241,36138,    7,36152, 7971,35187,  375,36156,25793,35187,  256,36160,
+    7,36160,  241,36164,  241,36160,    7,36168,32805,35187,    7,36172,
+19888,35187,    7,36176,18967,35187,  256,36180,  629,36180,  510,36180,
+  375,36180,  483,36180,    9,36190,    9,36180,  483,36194,    7,36180,
+  241,36198,    7,36181,25793,36203, 8495,36203,  241,36180,    7,36208,
+  241,35187,26292,36212,26219,36212, 8684,36212, 8647,36212,20762,36212,
+21258,36212,    7,36212,25793,36226,25793,36227, 8495,36226, 8495,36227,
+18967,36226,21037,36226,25793,36212,    7,36240, 8495,36212,    7,36244,
+18967,36212,    7,36248,21037,36212,    7,36252,    9,35187,19892,36256,
+ 1011,36256,   11,36261,18967,36256,  483,36264,  483,36256,18967,36268,
+  903,35187,    7,36272, 9377,36275,19913,35187,    6,36279,    7,36279,
+    6,36278,36283,36285,    7,36278,36281,36289,   15,35187,25381,36293,
+  483,36293,    2,36293,28189,36299, 1011,35187,16710,36303,16711,36303,
+16710,36302,36307,36309,    0,36303,    6,36312,16711,36302,36305,36317,
+    9,36302,   11,36321, 1275,36302,36315,36325,   11,36303,    9,36329,
+    6,36302,    3,36332,    6,36303,    0,36336,36325,36339,    7,36303,
+25793,36343, 8495,36343,21605,35187,21037,36348,21105,36348,21527,36348,
+29229,36355,    9,36355,21549,36348,19625,36348,21526,36348,    5,36364,
+  922,36349,  918,36349, 1505,36349, 1419,36349,  668,36349,  483,36349,
+  903,36378,  587,36349,    9,36382,    9,36349,  903,36386,   11,36387,
+  587,36386,   15,36348,   11,36348,    9,36397,    6,36348,21036,36400,
+    5,36400,18967,36404,18967,36400,    5,36408,    7,36348,30003,36413,
+29759,36413,34723,36413,21183,36413,  959,36413,   47,36413,  759,36413,
+    6,36349,36353,36429,36361,36429,36351,36429,36363,36429,    7,36349,
+36403,36439,31527,36439,22269,36439,28791,36439,22263,36439,32781,36439,
+36367,36439,21105,36439,21549,36439,29953,36439,29731,36439,34655,36439,
+33773,36439,29835,36439,29659,36439,34447,36439,32753,36439,32019,36439,
+29041,36439,23929,36439,22205,36439,19625,36439,33221,36439,36407,36439,
+36411,36439,18967,36348,    5,36490,    6,36493,36413,36495,    6,36492,
+36439,36499,36439,36493,   14,36490,36439,36505,    6,36491,36395,36509,
+    6,36490,    5,36512,36439,36515,  903,36349,    7,36519,    9,36518,
+  483,36518,  265,35187,17455,36527, 5843,36527,  483,36527,  587,36527,
+    9,36527,    7,36526, 9377,36539,    7,36527,   11,35187, 8069,36544,
+ 8067,36547,16859,36544, 9875,36551,21529,36544,20501,36555,16091,36545,
+ 9513,36559,    7,36544,    2,36563,    7,36564,36545,36567,    1,36564,
+36569,36571,    1,36563,    2,36574,    0,36544,    2,36579,    0,36580,
+36545,36583,    6,36580,36585,36587,    6,36579,    2,36590,  482,36579,
+ 1368,36544,    2,36597,    1,36598,    1,36597,    2,36602,18966,36544,
+    2,36607,    6,36608,    6,36607,    2,36612,  482,36607, 9513,36544,
+20501,36619, 9875,36619,16091,36619,20501,36545,21529,36627, 9513,36627,
+ 9875,36545,16859,36633, 9513,36633, 1369,36545, 1989,36639, 3587,36639,
+36601,36639,36605,36639, 5303,36639,36571,36639,36577,36639,    0,36639,
+ 4897,36639,17041,36639,18967,36545,20281,36661,20345,36661,36611,36661,
+36615,36661,36587,36661,36593,36661,    7,36661,20285,36661,36595,36661,
+36617,36661,  483,36661,20273,36683,36579,36683,36607,36683,21605,36544,
+    9,36691,  483,36544,35819,36695,35827,36695, 3477,36695, 2007,36695,
+    1,36695,36639,36705,36655,36695,19051,36695,19667,36695, 5123,36695,
+12345,36695,35837,36695,18967,36695,  555,36721,35815,36721,    3,36544,
+    3,36545,  375,36729,21308,35187,    7,36732,16481,35187,    7,36736,
+21037,35187,  256,36740,    7,36740,  241,36744,  241,36740,    7,36748,
+16531,35187,    7,36752, 1011,36753,    7,36757,18797,35187,    7,36760,
+17827,35187,    7,36764,16783,35187,    7,36768,    2,35186,27138,36773,
+28047,36773,26454,36773, 8770,36773,26375,36773, 8729,36773, 8697,36773,
+ 8784,36773,28197,36773, 4266,36773, 9262,36773,28111,36773,27128,36773,
+28027,36773,28117,36773,28177,36773,31872,36773,28063,36773,31598,36773,
+24545,36773,31103,36812, 8684,36773, 8717,36817,  331,36817,26292,36773,
+26331,36823, 8647,36773, 8757,36826,26219,36773,27021,36830,26415,36830,
+26415,36773,26219,36836, 8757,36773, 8647,36840,  375,36840, 4213,36773,
+  375,36846,28153,36773,26860,36773,28213,36773,35931,36773,28159,36773,
+31770,36773,  347,36773,  386,36773, 9750,36773,27978,36773,26331,36869,
+27805,36869, 1325,36869,  331,36869,   59,36869,23755,36869,25793,36869,
+  265,36869,  340,36773,  331,36887,31103,36773,24545,36890,26625,36890,
+    9,36890,  375,36773, 8757,36898, 4213,36898, 9195,36898,27021,36898,
+  305,36898,  483,36773, 9195,36773,  375,36912,10001,36773,    9,36917,
+ 1325,36773, 1275,36773,  331,36773,27533,36773,    9,36927,  305,36773,
+  375,36930,10291,36773,  483,36935,27021,36773,26219,36938,  375,36938,
+    7,36773,25793,36944,26331,36947, 8495,36944, 8717,36951,  331,36951,
+25793,36945,26415,36957,27021,36957, 8495,36945, 8757,36963,26625,36944,
+ 9731,36944,21605,36945,24545,36971,26625,36971,    9,36971,  265,36945,
+ 8757,36979, 4213,36979,27021,36979, 9195,36979,  305,36979,21605,36944,
+26331,36991,27805,36991,23755,36991,   59,36991,  331,36991, 1325,36991,
+25793,36991,  265,36991,  265,36944,  331,37009, 8647,36945,26219,36945,
+   59,36773,    7,36772,25793,37019, 8495,37019,23755,37019,10055,37019,
+ 4329,37019, 4311,37019, 3785,37019,27805,37019,10351,37019, 8717,37019,
+26331,37019,    9,36773,31103,37042,   15,36773,31103,37047, 9731,36773,
+    7,37050,21605,36773,   15,37055,31103,37057,    6,37055,    5,37060,
+    7,37055,26219,37065,  375,37065,    6,37054,37057,37071,    7,37054,
+26331,37075,37063,37075,27805,37075,23755,37075,   59,37075,  331,37075,
+ 1325,37075,25793,37075,  265,37075,  265,36773,    7,37095, 8495,37097,
+  375,37097,    7,37094,  331,37103,26625,36773,31103,37106,    7,37106,
+ 8495,36773,    7,37112, 8717,37115,  331,37115,    9,37113,  483,37113,
+    7,37113, 8647,37125,  375,37125,25793,36773,    7,37130,26331,37133,
+  483,37131,    9,37131,    7,37131,26219,37141,    3,35186,20305,37145,
+ 9641,37145,20309,37145, 9645,37145,    4,37145,    7,37154,35603,37157,
+ 9719,37145,   16,37145,35603,37163,35619,37145,21081,37145,20323,37145,
+20387,37145, 9701,37145,35719,37145,  524,37145,20273,37179, 9617,37179,
+ 1291,37145, 9617,37185,20273,37185,  305,37145,  375,37190,  386,37145,
+  347,37145,  767,37145,31103,37199,  483,37145,   11,37202, 9617,37205,
+20273,37205,  375,37145,  305,37210,    7,37145,    3,37215,18967,37217,
+35187,37219,    4,37214,35603,37223,37221,37223,    3,37214,35187,37229,
+   11,37145,  483,37232, 9617,37235,20273,37235,    6,35186,19975,37241,
+    0,37241,    2,37244,35575,37247,35633,37247,35735,37247,36695,37247,
+18966,37241,35735,37257,35633,37257,35575,37257,36695,37257,35749,37241,
+35649,37241,36721,37241,35597,37241,19365,37241,19221,37241,19917,37241,
+10107,37279,  587,37241,    3,37241,    2,37241,    6,37287,   17,37289,
+35187,37291,    0,37286,35575,37295,35633,37295,35735,37295,36695,37295,
+37293,37295,    6,37286,36544,37307,37295,37309,   11,37307,35187,37312,
+37295,37315,35187,37307,   11,37318,37295,37321,    7,35186,    4,37325,
+    3,37326,    3,37327,35927,37331,  902,37325,25525,37325, 1325,37325,
+10001,37325,  903,37341, 1275,37325,   59,37325,25793,37325,  587,37349,
+ 8495,37325,  587,37353,    2,37325,    7,37356,37331,37359,  903,37357,
+10311,37357,    3,37325,    4,37366,27533,37325,  903,37371,  331,37325,
+    2,37324,25793,37377, 8495,37377,23755,37377, 4329,37377,10055,37377,
+27805,37377, 3785,37377, 4311,37377,26331,37377, 8717,37377,10351,37377,
+21605,37325,  903,37401,  155,37401,  265,37325,    7,35187, 5045,37408,
+  805,37409, 9195,37413,    4,37408,37279,37417,19916,37417,37241,37421,
+ 1275,37417,18967,37424,37241,37427,18967,37417, 1275,37430,37241,37433,
+26546,37408,32805,37408,29599,37408,  652,37409, 9195,37443, 8812,37408,
+19888,37408,19913,37408,21308,37408,16481,37408,37285,37409,16783,37408,
+17827,37408,18797,37408,26498,37409, 8796,37409, 8495,37408,  241,37468,
+  331,37469,25793,37408,  241,37474,25793,37409,  241,37479,  587,37478,
+ 8495,37409,  241,37485,  587,37484,21037,37408,  241,37490,   88,37409,
+37411,37495,16531,37408,  587,37409,  265,37500, 9195,37503,26625,37501,
+25793,37501, 8495,37501,25793,37500, 8495,37500, 9731,37501,  265,37409,
+  587,37518, 9195,37521, 4213,37519, 7971,37519, 8757,37519,  587,37519,
+ 9377,37531, 9565,37519,   89,37409, 5069,37537, 9195,37537,27021,37537,
+  483,37409, 1275,37409,    9,37547,26503,37409, 8809,37409,18967,37408,
+  241,37554,  241,37408,25793,37558,25793,37559, 8495,37558, 8495,37559,
+18967,37558,21037,37558,  903,37408, 9377,37573,21605,37408,30003,37577,
+29759,37577,34723,37577,21183,37577,37495,37577,  959,37577,   47,37577,
+  759,37577,  265,37408, 9377,37595,  903,37409,31103,37598,31920,37409,
+31103,37409,  903,37604,  375,37409,    2,37408,37331,37611,37495,37611,
+    3,37408,14072,37616, 4970,37616,14072,37617,14073,37616,37623,37625,
+ 4971,37616, 4970,37617,37629,37631,    7,37617,    4,37635,    1,37616,
+37537,37639,    9,37639,36773,37617,37537,37617, 7971,37617,14073,37617,
+37619,37651, 4971,37617,37621,37655,  483,37617,    9,37617,    2,37409,
+37369,37663,37329,37663,37637,37663,    7,37662,37617,37671,37335,37663,
+ 9362,37663,27218,37663,37642,37663,37639,37663,    9,37682,28189,37663,
+    1,37663,    5,37688,37616,37690,37617,37691,37693,37695,37671,37694,
+37616,37691,37617,37690,37701,37703,37672,37691,37671,37691,37617,37708,
+    5,37663,    1,37712,37616,37714,37617,37715,37717,37719,37671,37718,
+37616,37715,37617,37714,37725,37727,37672,37715,37671,37715,37617,37732,
+28337,37663,37660,37663,27021,37663,    9,37740, 9195,37663,    9,37744,
+    9,37663,37639,37748,27021,37748, 9195,37748,37617,37748,37241,37663,
+37617,37663,    1,37760,    5,37762,    5,37760,    1,37766,    7,37761,
+37691,37771,37715,37771,37765,37771,37769,37771,    9,37760,    3,37409,
+37577,37783,    9,37785,   16,37783,    4,37783,    7,37790,    7,37783,
+    4,37794,18967,37783,35187,37799,37789,37801,37793,37801,37797,37801,
+    9,37782,37577,37809,37611,37809,37611,37783,    1,37815,    5,37816,
+    5,37815,    1,37820,    7,37814,37819,37825,37823,37825,    9,37815,
+    9,37409,    3,37832,37577,37835,37611,37835,    3,37833,37663,37841,
+    3,35187,10104,37844,10105,37844,    0,37845,    5,37850,    4,37844,
+36773,37855,10104,37845,37849,37859,10105,37845,37847,37863,36945,37845,
+37855,37867,10291,37844,36944,37845,  265,37873,37663,37845,    7,37877,
+37691,37879,37715,37879, 1369,37845,   11,37885, 9617,37887,37853,37887,
+20273,37887,   11,37844,    6,37844,    7,37844,14072,37898, 4970,37898,
+14073,37898,14072,37899,37905,37907, 4971,37898, 4970,37899,37911,37913,
+35187,37899,36773,37899, 7971,37899,14073,37899,37901,37923, 4971,37899,
+37903,37927,  483,37899,    6,37845,37856,37933,37855,37933,36773,37936,
+    1,37933,    5,37940,37898,37942,37899,37943,37945,37947,37898,37943,
+37899,37942,37951,37953,    5,37933,    1,37956,37898,37958,37899,37959,
+37961,37963,37898,37959,37899,37958,37967,37969,36773,37933,37855,37972,
+37899,37933,    7,37845,  265,37979,36773,37981,35187,37978,    2,37985,
+    4,37979,37987,37989,    3,37989,37985,37993,37663,37989,36773,37978,
+  265,37999,37897,37979,36773,37845,    4,38005,37933,38007,    7,38005,
+37943,38011,37959,38011,14073,38011, 4971,38011,    6,38004,    1,38021,
+    5,38022,38011,38025,    5,38021,    1,38028,38011,38031,38007,38021,
+    7,38004,  265,38037,18967,37845,    4,38041,37933,38043,  256,38041,
+    7,38041,  241,38048,  241,38041,    7,38052,    2,35187,29229,38057,
+28741,38059,28741,38056,29229,38063,    0,38057,    0,38056,28714,38069,
+37185,38069, 1290,38069,37145,38075,37179,38069,  525,38069,37145,38081,
+37887,38069,37205,38069,37235,38069,    5,38069,21605,38090,21605,38069,
+    5,38094, 1275,38069,   17,38098,37145,38101,   17,38069, 1275,38104,
+37145,38107, 1505,38057,17455,38057,  903,38112,17494,38057,  483,38057,
+37214,38057,14073,38121, 4971,38121,37783,38057,  587,38057,10373,38057,
+    9,38057,  155,38057,    6,38056,    1,38137,    5,38138,38121,38141,
+    5,38137,    1,38144,38121,38147,37145,38137,  587,38137,    7,38056,
+37331,38155,    6,38057,    5,38158,18966,38159,    0,38159,    2,38164,
+    2,38159,    0,38168, 1369,38159,   17,38159,35187,38175,38163,38177,
+38167,38177,38171,38177,    7,38057,38141,38185,37145,38187,38147,38185,
+37145,38191,34447,38185,28715,38185,38069,38197,38071,38185,29659,38185,
+29835,38185,38093,38185,38097,38185, 4971,38185,37145,38211,14073,38185,
+37145,38215,37145,38184,38141,38219,38147,38219,14073,38219, 4971,38219,
+21605,38185,  903,38229,37145,38057,    4,38232,    6,38233,    1,38237,
+    5,38238,    5,38237,    1,38242,38235,38237,    7,38233,  265,38249,
+    7,38232,38241,38253,38245,38253,38141,38253,38147,38253,14073,38253,
+ 4971,38253,  903,38057,17455,38266,    6,35187,    4,38271,    1,38272,
+    0,38270,   17,38277,37844,38278,37845,38279,38281,38283,37845,38278,
+37844,38279,38287,38289, 1369,38271,    2,38270,  587,38295,    3,38270,
+    2,38271, 1275,38301,    1,    5,35962,38304,35963,38304,37760,38304,
+37771,38311,37976,38304,38002,38304,37761,38304,37977,38304,37815,38304,
+37825,38323,38003,38304,37930,38304,37658,38304,37931,38304,37659,38304,
+   77,38304, 3095,38337, 1917,38337,  120,38304, 3013,38343, 1897,38343,
+   79,38305, 3113,38349,  125,38305, 3023,38353,35929,38305,37885,38357,
+37916,38305,37885,38361,38021,38304,38011,38365,38237,38304,38253,38369,
+ 4597,38305, 6625,38373,  113,38304, 4696,38377,    9,38377, 4669,38380,
+ 4669,38377,    9,38384,37896,38304,37898,38304,37933,38391,  483,38391,
+37616,38304,37663,38397,  483,38397,   59,38304,23023,38403,25483,38403,
+22677,38403,27533,38304,23023,38411,22677,38411,22605,38411,25483,38411,
+37663,38304,37617,38420,37672,38421,37671,38421,37617,38426,37771,38421,
+37879,38421,37617,38421,38397,38435,37671,38434,37933,38304,37899,38440,
+38011,38441,37899,38441,38391,38447,37897,38304,38137,38304,38121,38453,
+38219,38453,38185,38453,37145,38459,38253,38453,37617,38304,37663,38464,
+  483,38464,37899,38304,37933,38470,  483,38470,  979,38305,21605,38477,
+  987,38479,21879,38305, 1205,38483,29229,38304,29375,38487,17105,38304,
+17117,38491,23755,38304,23023,38495,22677,38495,25483,38495,26863,38305,
+21605,38503,26865,38505,10091,38305,   15,38509,10093,38511, 1009,38305,
+  675,38304,22605,38517, 1418,38304,    1,38521,    3,38522,    3,38521,
+    1,38526,21604,38521,21895,38304,22605,38533,25380,38304,    5,38537,
+    6,38538,    6,38537,    5,38542,   14,38537, 1365,38305,17573,38305,
+    9,38550,10001,38553,27996,38305,27533,38557, 1203,38305,17574,38305,
+10001,38563,  177,38305,27995,38305,    9,38568,27533,38571, 7963,38305,
+    9,38574, 7961,38577, 7964,38305, 7961,38581,  120,38305,   77,38305,
+37758,38305,37972,38305,37457,38305,37867,38305,35912,38305,35733,38305,
+35732,38305,35913,38305,22605,38305,27533,38605,  675,38605,21895,38605,
+36856,38305,  483,38613,37644,38305,  483,38617,37918,38305,37933,38621,
+  483,38621,37177,38305,  483,38627, 4798,38305,15896,38305,23023,38305,
+   59,38635,27533,38635,23755,38635,22677,38305,27533,38643,   59,38643,
+23755,38643,25483,38305,   59,38651,27533,38651,23755,38651,25368,38305,
+30290,38305,27127,38305,30762,38305,30566,38305,  843,38304,35187,38669,
+ 1531,38304,  842,38304, 1530,38304,35930,38305,38675,38679,38307,38679,
+ 9492,38305,10001,38685,13755,38685,27533,38685,24597,38305,   59,38693,
+  331,38693,   97,38693,  141,38693, 1325,38693,  629,38305,37896,38305,
+37610,38305,37783,38709,37616,38305,38467,38713,38423,38713,38311,38713,
+38331,38713,38469,38713,38465,38713,37663,38725,  483,38725,37898,38305,
+38473,38731,38443,38731,38315,38731,38329,38731,38475,38731,38471,38731,
+37933,38743,  483,38743,37866,38305,37456,38305,17508,38305, 9257,38305,
+27149,38305, 9353,38305, 9253,38305,38253,38305,38137,38763,38237,38763,
+  483,38763,38219,38305,38137,38771,  483,38771,38121,38305,38137,38777,
+  483,38777,15897,38305, 4799,38305,27161,38305,20187,38305,  483,38789,
+ 8387,38305,  483,38793, 9541,38305,15879,38305,  483,38798, 4787,38305,
+  483,38802,16125,38305,    3,38806,    2,38806,  842,38806,  843,38807,
+38813,38815,  842,38807,  843,38806,38819,38821,    2,38807,38809,38825,
+    3,38807,38811,38829, 5121,38305,    3,38832,    2,38832,  842,38832,
+  843,38833,38839,38841,  842,38833,  843,38832,38845,38847,    2,38833,
+38835,38851,    3,38833,38837,38855,35729,38305,  587,38859,  587,38858,
+19384,38305,  483,38865,  669,38305, 1011,38869, 1086,38305,  483,38873,
+ 1418,38305, 1011,38877,25381,38305,38541,38881,38545,38881,25423,38881,
+25429,38881,    7,38881,25431,38881,38547,38881,   15,38881,25415,38897,
+38537,38897, 1419,38305,38525,38903,38529,38903, 1801,38903, 1875,38903,
+    2,38903,23983,38903,10603,38903, 4625,38903,21893,38903,38531,38903,
+21605,38903, 1421,38925,38521,38925, 1108,38305, 9565,38931,  246,38305,
+  483,38935,  294,38305, 8495,38939,35931,38305,38669,38943,38309,38943,
+  483,38943,36773,38942,  483,38951,19396,38305,35718,38305,37885,38957,
+37202,38957,37145,38957,  483,38962,  483,38957,37145,38966,  668,38305,
+    2,38971, 3507,38971, 1971,38971,21783,38971,23983,38971,10603,38971,
+ 4625,38971,21605,38971,  713,38987,20060,38305,  483,38991,  713,38305,
+16833,38995,38011,38305,37933,38999,38021,38999,  483,38999,37285,38305,
+37409,39006,36945,38305,37845,39011,37845,39010,  483,39011,37215,38305,
+    3,39019,38057,39019, 9377,38305,    9,39024,10001,39027,13755,39027,
+27533,39027, 1471,38305,16937,39035, 9875,38305, 1011,39039, 1347,39039,
+  555,38305,20763,38305,  566,39046,  566,39047,  567,39046,39051,39053,
+  567,39047,39049,39057,  257,38305,  483,39061,  973,38305, 4816,39065,
+ 4805,39065, 1011,39068,38057,39065, 1011,39065, 4805,39074,  628,38305,
+  483,39079, 1406,38305,  587,38305,23584,39085,24355,39085,37782,39085,
+37408,39084,39091,39093,37783,39085,37408,39085,38670,39085,    3,39085,
+37409,39102,39093,39105,37409,39103,39099,39109,38669,39085,35187,39112,
+35728,39084,23493,39085,22807,39118,22807,39085,23493,39122,35729,39084,
+35728,39085,39127,39129,35729,39085,39117,39133,37409,39085,    3,39136,
+39093,39139,  483,39085,35187,39142,35187,39085,38669,39146,  483,39146,
+36773,39147,  483,39153, 1011,39084,  483,39157,    9,39084, 4625,39161,
+10603,39161, 3507,39161, 1971,39161,23983,39161,21783,39161,21605,39161,
+  713,39175,18967,39084,  483,39179,35187,39084,37202,39183,37885,39183,
+37145,39183,  483,39188,  483,39183,37145,39192,37409,39084,39097,39197,
+   11,39084,  483,39201, 1369,38305,35964,39204,35965,39205,39207,39209,
+35965,39204,35964,39205,39213,39215,35761,39205,38057,39205,   15,39204,
+ 1011,39223,   11,39205, 1011,39205,   11,39204, 1275,38305,  483,38305,
+35895,39234, 4787,39234,15879,39234,21405,38305, 1011,39243,  483,39243,
+ 7535,38305,   15,39249, 7537,39251, 7541,39251, 7545,39251,28337,38305,
+21605,39259,28351,39261,28355,39261,28359,39261, 6147,38305,  483,39269,
+15269,38305,  483,39273,17423,38305, 1011,39277,  483,39277, 4827,38305,
+  483,39283, 4745,38305, 1011,39287,  483,39287,17232,38305,30492,38305,
+25793,39295,  265,39294, 4569,38305,  483,39301,14625,38305,  483,39305,
+ 7063,38305,  483,39309,37284,38305,37356,38305,17233,38305,30493,38305,
+  483,39319,37973,38305,37759,38305,38002,38305,38327,39327,37760,38305,
+  483,39331,37976,38305,38321,39335,37617,38305,38398,39339,38319,39339,
+38400,39339,38335,39339,37663,39339,38397,39348,37671,39349,38397,39339,
+37663,39354,  483,39354,36773,39338,  483,39361,  483,39339,38397,39364,
+37663,39338,  483,39369,37899,38305,38392,39373,38321,39373,38394,39373,
+38333,39373,35187,39372,37885,39383,37933,39373,38391,39386,38391,39373,
+37933,39390,  483,39390,36773,39372,37933,39397,  483,39397,  483,39373,
+38391,39402,38185,38305,38150,39407,38137,39407,37145,39410,37202,39407,
+37885,39407,  483,39407,37145,39418,37145,39407,38137,39422,  483,39422,
+37979,38305,38451,39429,37663,38305,37409,39432,    3,39435,    7,39433,
+39437,39439,    2,39439,39435,39443,  483,39433,37617,39447,37241,39432,
+37617,39432,  483,39453,37933,38305,36773,39456,37977,38305,38315,39461,
+37815,38305,  483,39465,38003,38305,38317,39469,38127,38305,  483,39473,
+  482,38304,    5,39477,    6,39478,    6,39477,    5,39482,   14,39477,
+  586,38304,39122,39489,39128,39489,39127,39489,38863,39489,38601,39489,
+38948,39489,38603,39489,39150,39489,39144,39489,38783,39489,38785,39489,
+    3,39489,    1,39512,38971,39515,39161,39515,    1,39489,    3,39520,
+38971,39523,39161,39523,39175,39489,38987,39489,21604,39489,39161,39533,
+38971,39533,39146,39489,  483,39538,39142,39489,35187,39542,38943,39489,
+  483,39546,35728,39489,39085,39550,22807,39489,39085,39554,26219,39489,
+ 8647,39489,19396,39489,39085,39489,22807,39564,35728,39564,35187,39564,
+  483,39570,  483,39564,35187,39574,35895,39489,    9,39489,18967,39580,
+18967,39489,    9,39584,35187,39489,39142,39588,39085,39588,  483,39592,
+  483,39588,39085,39596,  483,39489,38943,39600,39146,39600,39085,39600,
+35187,39606,35187,39600,39085,39610, 4787,39489,15879,39489, 1368,38304,
+ 3867,39619, 8277,39619, 3997,39619, 4067,39619, 9459,39619, 8953,39619,
+ 1274,38304,27979,39633,14625,39633, 4569,39633,16381,39633,13325,39633,
+26293,39633, 8685,39633,35843,39633, 1369,39633,19513,39633, 3863,39633,
+37019,39633, 9955,39633,37377,39633, 8401,39633,10273,39633,20697,39633,
+ 4137,39633,20219,39633, 4063,39633,35895,38305,  483,39674,35915,38305,
+    3,39678,    2,39678,  842,39678,  843,39679,39685,39687,  842,39679,
+  843,39678,39691,39693,    2,39679,39681,39697,    3,39679,39683,39701,
+  482,38305,39616,39705,39614,39705,39578,39705,35718,39705,35895,39705,
+39489,39714,39489,39705,15879,39718, 4787,39718,35895,39718,15879,39705,
+39489,39726, 4787,39705,39489,39730,35187,39705,  587,39734,  587,39735,
+39489,39739,  587,39705,35187,39742, 1368,38305,  587,38304,39241,39749,
+39239,39749,39237,39749,38599,39749,38597,39749,38633,39749,38631,39749,
+39677,39749,38801,39749,38805,39749,38679,39749,  483,39771,39235,39749,
+15879,39775, 4787,39775,35895,39775,  483,39748,38679,39783,  483,38304,
+38121,39787,38219,39787,38253,39787,37899,39786,38731,39795,37617,39786,
+38713,39799,38011,39787,38185,39787,37145,39805,14625,39787, 4569,39787,
+19396,39787,35931,39787,39489,39815,15269,39787, 4827,39787,  587,39786,
+38679,39823,37899,39787,38391,39827,37617,39787,38397,39831,17423,39787,
+ 4745,39787,    9,39787,18967,39838,18967,39787,    9,39842,  587,39787,
+39588,39847,39489,39847,35187,39850,35187,39847,39489,39854,35187,39787,
+  586,39858,39823,39861,  586,39859,39847,39865,  586,38305,39713,39869,
+38861,39869,39737,39869,39745,39869,38675,39869,35187,39879,39823,39869,
+35187,39883,39783,39869,35187,39887, 1108,39869,  295,39869,35927,39869,
+37611,39869,38155,39869,35719,39869,39705,39901,39749,39869,22807,39905,
+35728,39905,35187,39905,  483,39910,  483,39905,35187,39914,35187,39868,
+39823,39919,39783,39919,38675,39919,39749,39919,  483,39927, 1011,39869,
+    9,39930,    9,39869, 1011,39934, 1369,38304, 1275,39938, 1275,38304,
+39429,39943,23023,39943,22605,39943,25483,39943,22677,39943, 1369,39942,
+  803,38305,17455,39956,13737,39957,39705,39961, 1505,38305,21605,39965,
+  713,39967,  305,39967, 1489,39967, 1509,39967,   25,39967,15705,38305,
+  767,39979,39705,39981,17455,38305,   15,39985, 9513,39987,16859,39987,
+17469,39987,  803,39984,  154,38305,  165,39997,  374,38305,   11,40001,
+   66,38305,  340,38305,30091,40006,27978,38305,39633,40011,23755,40011,
+27805,40011,26331,40011,25793,40011, 8495,40011,  511,38305,   11,40025,
+  935,38305,  483,40029, 1109,38305,   11,40033,  295,38305,  256,38305,
+  375,40039, 9805,40039,20762,38305, 1141,40045, 1447,40045,   33,40045,
+   88,38305,11251,40053, 5177,40053,  136,38305,36727,40059,37895,40059,
+36079,40059,  144,38305,  113,40067,  341,38305,  113,40071,16937,40071,
+27979,38305,38411,40077,  483,40077,39943,40077, 9565,40077,  113,38305,
+ 4727,40087,    9,40089,37662,38305,37241,40093,37932,38305,36773,40097,
+37782,38305,37978,38305,39633,40103,38389,40103,  305,38305,16833,40109,
+   25,38305,16833,40113,20501,38305, 1011,40117, 1347,40117,  253,38305,
+16937,40123,   53,38305,16937,40127,  251,38305,   21,38305,38004,38305,
+    7,40135,37241,38305,    6,40138,    2,40141,35187,40142,35187,40141,
+    2,40146,    2,40147,38056,40141,37663,40138,    3,40138,40145,40157,
+40149,40157,40153,40157,    3,40139,40151,40165,40093,40165,36773,38305,
+37933,40171,37899,40173,37933,40170,35931,40170,  483,40179,37617,40170,
+  483,40183,37899,40170,37933,40187,  483,40187,37409,40170,    3,40193,
+  483,40171,35931,40197,37617,40197,37899,40197,    6,40170,37844,40205,
+    3,40205,35187,40208,35187,40205,    3,40212,    7,40171,40207,40217,
+40211,40217,40215,40217,40195,40217,    2,40217,40193,40227,37845,40217,
+40205,40231,37845,40170,    7,40235,37325,38305,    7,40238,    2,40241,
+    2,40240,    7,40239,35187,40247,    3,40249,    3,40248,    3,40247,
+35187,40254,    3,40246,37844,40247, 1368,40238,  586,40239, 1369,40238,
+37845,40238,40259,40269,40265,40269,  587,40239,    2,40238,    7,40276,
+40251,40277,    3,40238,40243,40283,35187,40282,40275,40287,    3,40239,
+40279,40291,40245,40291,40269,40291,    7,40290,40269,40299,40263,40291,
+    2,40239,40287,40305,40257,40305,40253,40305,40261,40305,40267,40305,
+10219,38305,    7,40316,    2,40318,    2,40319, 1368,40316, 1369,40316,
+    2,40317,40327,40329,    3,40317,40321,40333,40325,40333,    2,40316,
+    7,40338,40333,40341,    3,40316,40323,40345,  413,38305,    7,40349,
+  375,40349, 1217,38305,  483,40355, 1216,38305,    7,40359,  412,38305,
+  483,40363,36348,38305,    2,40366,36429,40369,38233,38305,    7,40373,
+25296,38305,    7,40377,  265,38305,27978,40381,30492,40380,   17,40380,
+ 8495,40387,    6,40380,   11,40391,    7,40380,30091,40394,    7,40381,
+27021,40399, 9195,40399,40391,40399,40001,40399,21605,40398,    6,40381,
+40395,40411,40007,40411,   17,40411,21605,40381,    7,40418,   17,40419,
+  241,40380,  483,40425,21605,40380,    7,40429,30091,40380,    7,40432,
+   11,38305,18967,40436,  483,40439,  587,40436,  483,40443, 1369,40436,
+  483,40437,  587,40449,    3,40436,    3,40437, 9875,40455,20501,40455,
+ 1011,38305,  483,40461,  587,40463,  587,40460,  483,40467,    9,40460,
+ 9565,40471,    7,40461,  959,40475,  759,40475,   47,40475,  903,40460,
+    7,40483,   15,38305, 1369,40486, 1011,40489,  241,40486,  483,40493,
+    3,40486,  165,40497,    3,40487,  253,40501, 1471,40501,   53,40501,
+21605,38305,27533,40509,   15,40509,31103,40513, 1275,40509,    7,40508,
+23755,40519,39633,40519,27805,40519,26331,40519,25793,40519, 8495,40519,
+    7,40509,26219,40533,  305,40533,   25,40533,  713,40533,  265,40509,
+31103,40543,  265,40508,    7,40547,25367,38305,    6,40551,    7,40551,
+    6,40550,40555,40557,    7,40550,40553,40561,   17,38305,19917,40565,
+  587,40565,  265,40564, 8495,40571,  265,40565, 8861,40575,    3,40564,
+  113,40579,    3,40565,10109,40583,10108,40583,10108,40582,40585,40589,
+10109,40582,40587,40593, 1141,40583, 1447,40583,   33,40583,  903,38305,
+    7,40603, 1141,40605, 1447,40605,   33,40605, 1011,40602,    7,40613,
+18967,38305, 1108,40617, 1072,40617,  165,40617, 1291,40617,  524,40617,
+    9,40617, 1011,40628,   11,40616,  483,40633,   11,40617,  483,40636,
+  483,40617,   11,40641, 1011,40640,  587,40641,   11,40640,    9,40616,
+  587,40616,  483,40653,    7,40616, 1141,40657, 1447,40657,   33,40657,
+ 1011,40617,21183,40665,    7,40665,  483,40664,    9,40664,  241,38305,
+  483,40675,   15,40674,  483,40679,    9,40675,    7,40674,  375,40685,
+ 9805,40685,    7,40675,  265,40691,   59,40691,  331,40691, 1325,40691,
+  265,40674,  483,40701,    9,38305, 7963,40704, 7961,40707,27995,40704,
+27533,40711,17573,40704,10001,40715,13755,40705, 9377,40719,    1,40704,
+    3,40723,    1,40724,40705,40727,    7,40724,40729,40731,    7,40723,
+    3,40734,  586,40723,    6,40704,    3,40741,    6,40742,40705,40745,
+    0,40742,40747,40749,    0,40741,    3,40752,21604,40704,    3,40757,
+    7,40758,    7,40757,    3,40762,  586,40757, 1274,40704,    3,40769,
+    0,40770,    0,40769,    3,40774, 9377,40704,27533,40779,10001,40779,
+13755,40779,10001,40705,17573,40787, 9377,40787,27533,40705,27995,40793,
+ 9377,40793,21605,40705,26715,40799,26865,40799,40761,40799,40765,40799,
+40731,40799,40737,40799,    6,40799,26719,40799,40739,40799,40767,40799,
+  587,40799,26625,40821,40723,40821,40757,40821, 1275,40705, 1991,40829,
+ 3621,40829,40773,40829,40777,40829, 5299,40829,40749,40829,40755,40829,
+    1,40829, 4907,40829,17711,40829, 1011,40704, 9565,40851,  587,40704,
+39515,40855,39523,40855, 3507,40855, 1971,40855,    0,40855,40829,40865,
+40845,40855,21783,40855,23983,40855, 4625,40855,10603,40855,39533,40855,
+21605,40855,  713,40881,39489,40881,18967,40704, 1011,40705,18967,40889,
+ 9617,40889,    2,40704,36727,40895,37895,40895,36079,40895,    3,40704,
+11251,40903, 5177,40903,    2,40705,36729,40909,    3,40705,11355,40913,
+30748,38305,    7,40916,17125,38305,    7,40920,30091,38305,  340,40924,
+    7,40924,25793,40929,  265,40928, 1011,40925,    7,40935,  265,40925,
+    7,40939,  265,40924,    7,40942,14315,38305,31103,40947,  375,40947,
+    7,40947, 8495,40953,37845,38305,37897,40957, 1275,40957,36945,40956,
+    6,40957,    7,40957,    6,40956,40967,40969,36773,40969,    7,40956,
+38389,40975,39633,40975,40965,40975,36773,40956,    7,40983,37409,38305,
+37285,40986,  113,40987,    2,40987,39313,40993,40157,40993,    3,40987,
+39439,40999,40217,40999,    2,40986,38305,41005,    7,41007,40999,41009,
+40165,41005,37241,41005,    3,40986,    3,38304,40375,41019,40237,41019,
+40985,41019,40137,41019,40963,41019,39015,41019,38749,41019,40098,41019,
+39323,41019,40972,41019,40989,41019,39009,41019,38751,41019,40094,41019,
+39325,41019,41014,41019,15567,41019,12971,41019,13355,41019,13541,41019,
+21049,41019,21242,41019,39127,41019,39714,41019,39739,41019,38603,41019,
+38601,41019,38863,41019,39726,41019,39730,41019,20956,41019,20773,41019,
+38783,41019,38785,41019,11970,41019,19441,41019,19656,41019, 4696,41019,
+    5,41019,    6,41097,27169,41019,27168,41019,33465,41019,40011,41019,
+30492,41019,40519,41019,39295,41019,30493,41019,40929,41019,  357,41019,
+  367,41019,  471,41019, 1249,41019,  628,41019,20057,41019, 4569,41019,
+14625,41019, 4545,41019,36203,41019,36343,41019,40953,41019,21183,41019,
+20103,41142,13325,41019, 8337,41147, 4549,41019, 9357,41019, 9356,41019,
+40966,41019,36026,41019,37558,41019,36226,41019,36944,41019, 8386,41019,
+20186,41019, 9083,41019, 9484,41019,36027,41019,37559,41019,36227,41019,
+36945,41019, 8387,41019,20187,41019,19513,41019,35843,41019,20219,41019,
+ 8401,41019,37019,41019,20697,41019, 4137,41019, 9955,41019, 3863,41019,
+ 4063,41019,37377,41019,10273,41019,21405,41019,20606,41019, 9984,41019,
+37215,41019,40969,41019,36773,41218,40975,41019,40097,41019,36773,41224,
+40103,41019,37979,41019,19396,41019,11131,41019,21059,41019, 9082,41019,
+28205,41019,25551,41019,24613,41019,20326,41019,21087,41019,39705,41019,
+35895,41250,15879,41250, 4787,41250,11949,41019,    9,41258, 4669,41019,
+    9,41262,15879,41019,39705,41266, 4787,41019,39705,41270,20805,41019,
+37501,41019,19631,41019,    9,41278,35895,41019,39705,41282, 9704,41019,
+40387,41019,38939,41019,40033,41019,40571,41019,20804,41019,  341,41019,
+  241,41299,27979,41019,  241,41303, 9377,41019,   11,41306,  256,41019,
+35187,41310,  257,41019,35187,41315,20763,41019,   11,41318, 4745,41019,
+17423,41019,  587,41019,   11,41326,37409,41326,37500,41019, 9875,41019,
+   10,41334,   10,41335,   11,41334,41339,41341,   11,41335,41337,41345,
+ 1471,41019,37325,41019,  587,41351,37241,41019,40093,41354,41005,41354,
+37408,41019,  241,41360,41005,41019,37241,41364,40093,41019,37241,41368,
+20885,41019,20413,41372, 1369,41019,37409,41377,37409,41019,  241,41381,
+  587,41380,40967,41019, 9195,41019,   11,41388,20413,41019,20885,41392,
+10219,41019,  587,41397,20501,41019,   10,41400,   10,41401,   11,41400,
+41405,41407,   11,41401,41403,41411,  253,41019,    6,41019,40373,41417,
+40135,41417,40235,41417,40983,41417,40967,41417,27021,41417,40533,41417,
+30091,41417, 4713,41417,16363,41417, 4863,41417,13119,41417,26415,41417,
+ 8757,41417,23493,41417,27377,41417, 4213,41417, 9195,41417,39489,41417,
+ 9335,41417, 4147,41417, 3933,41417, 8109,41417,36212,41417,36773,41417,
+20103,41417, 8337,41417,37145,41417, 8997,41417,40957,41417,  241,41417,
+35187,41478,18967,41417,   11,41483,35187,41417,  241,41486,  587,41487,
+  587,41417, 8387,41417,20187,41417,14653,41417,36945,41417,    7,41019,
+30091,41502,26331,41503, 8717,41503,23755,41503,27805,41503, 3785,41503,
+40957,41502,36212,41502,39633,41503,10055,41503, 4329,41503, 4311,41503,
+10351,41503,36773,41502,20103,41502, 8337,41502, 8997,41502, 1275,41503,
+   15,41503,18967,41541,35187,41502,  241,41544,  241,41502,35187,41548,
+27021,41019,   11,41552,   53,41019,    6,41018,41165,41559,41531,41559,
+41517,41559,41157,41559,40975,41559,40103,41559,41537,41559,41169,41559,
+41167,41559,41239,41559,41533,41559,41535,41559,40011,41559,27979,41559,
+40519,41559,41549,41559,41311,41559,16381,41559,13325,41559,26293,41559,
+ 8685,41559,41361,41559,41545,41559,41503,41559,36773,41607,40957,41607,
+ 8997,41607,20103,41607, 8337,41607,  241,41607,35187,41607, 1369,41559,
+ 4569,41559,35843,41559,19513,41559, 3863,41559, 9955,41559, 4063,41559,
+37377,41559,10273,41559,20697,41559, 4137,41559,37019,41559,20219,41559,
+ 8401,41559,14625,41559,    7,41018,41181,41653,41466,41653,41387,41653,
+41476,41653,41474,41653,41185,41653,41183,41653,41171,41653,41468,41653,
+41470,41653, 8997,41653,41417,41674,41315,41653,41478,41653,26219,41653,
+ 8647,41653,41381,41653,41486,41653,19396,41653,41417,41653,36773,41692,
+40957,41692, 8997,41692,20103,41692, 8337,41692,  241,41692,35187,41692,
+20103,41653,41417,41708, 8337,41653,41417,41712,36773,41653,41417,41716,
+  483,41653,    9,41653,18967,41722,  241,41653,    1,41727,41417,41729,
+41417,41726,18967,41653,    9,41734,40957,41653,41417,41738,35187,41653,
+41417,41742,   11,41019,27021,41746,  587,41746, 9195,41746,20501,41746,
+ 9377,41746, 9875,41746,20763,41746,    9,41019, 4669,41762,11949,41762,
+19631,41762,18967,41762,20273,41762, 9617,41762,   17,41019,20762,41776,
+20762,41777,20763,41776,41781,41783,20763,41777,41779,41787,40957,41019,
+    6,41790,    7,41790,41559,41795,    6,41791,41795,41799,    7,41791,
+41793,41803,41417,41803, 9617,41019,    9,41808,36212,41019,    7,41812,
+35187,41019,  256,41816,    7,41816,  241,41820,41559,41821,    7,41817,
+41417,41827,  241,41816,    7,41830,  241,41019,    1,41835,    7,41837,
+41559,41839,    7,41836,41417,41843,37408,41834,    7,41835,    1,41848,
+41417,41851,41417,41849,    7,41834,41559,41857,35187,41856,35187,41834,
+    7,41862,18967,41019,  483,41867,    9,41866,30091,41019,    7,41872,
+14315,41019, 8997,41019,    7,41878,41559,41881,    7,41879,41417,41885,
+20273,41019,    9,41888, 8337,41019,    7,41892,41559,41895,    9,41893,
+  483,41893,    7,41893,41417,41903,20103,41019,21183,41906,    7,41906,
+41559,41911,    9,41907,  483,41907,    7,41907,41417,41919,36773,41019,
+40097,41922,40969,41922,    7,41922,41559,41929,    9,41923,  483,41923,
+    7,41923,41417,41937,    2,38304,38595,41941,40177,41941,39459,41941,
+38591,41941,38593,41941,40155,41941,39451,41941,38589,41941,39237,41941,
+39241,41941,39239,41941,38599,41941,38597,41941,38633,41941,38631,41941,
+26777,41941, 9741,41941,26781,41941, 9745,41941,39677,41941,38801,41941,
+38805,41941,    5,41941,    6,41986,38881,41989, 9771,41941,   14,41941,
+38881,41995,38897,41941,30349,41941,26857,41941,26933,41941, 9777,41941,
+40077,41941,31598,41941,35931,41941,37519,41941,35690,41941,40651,41941,
+38955,41941,40887,41941,39235,41941,35895,42025,15879,42025, 4787,42025,
+ 8982,41941,  668,41941,26625,42035, 9731,42035, 1419,41941, 9731,42041,
+26625,42041,40471,41941,38931,41941,40037,41941,40851,41941,37617,41941,
+37899,41941,39457,41941,36773,42059,39429,41941,27021,41941,  375,41941,
+35187,42066,31103,41941,26625,42070, 9195,41941,  483,41941,39433,41941,
+37241,42079,  587,41941,    1,42083,35187,42083,    9,42082, 9731,42089,
+26625,42089,    6,41941,    2,42095,21605,42097,38305,42099,    5,42094,
+38881,42103,42101,42103,    2,42094,38305,42109,    7,41940, 9459,42113,
+ 8953,42113, 3997,42113, 4067,42113, 8277,42113, 3867,42113,    9,41941,
+  587,42126, 9731,42129,26625,42129,   17,41941, 8861,42134,26625,41941,
+31103,42138, 8861,41941,    7,42143,   17,42142,35187,41941,  375,42148,
+ 9731,41941,    7,38304,39023,42155,41231,42155,25445,42155,    1,42155,
+    2,42162,    3,42162,38903,42167,38971,42167,39161,42167,40855,42167,
+18967,42167,    2,42163,    3,42163,    5,42155,    2,42182,    3,42182,
+    2,42183,42187,42189,    3,42183,42185,42193,21604,42155,18967,42197,
+39161,42197,38971,42197,38903,42197,40855,42197,39175,42155,38987,42155,
+40881,42155,38925,42155,22779,42155,22243,42155,28063,42155,41303,42155,
+31598,42155,25299,42155,  357,42155,  367,42155,  471,42155, 1249,42155,
+35690,42155,37519,42155,  272,42155, 1476,42155,  280,42155,  949,42155,
+ 1517,42155,40387,42155,40571,42155,40033,42155,38939,42155,21087,42155,
+20326,42155, 9704,42155, 9304,42155,35931,42155,40998,42155,  253,42155,
+  265,42270,  375,42155,35187,42274,31103,42155,26625,42278,25381,42155,
+10081,42283,41417,42155, 1369,42287,26625,42155,31103,42290, 9617,42155,
+    9,42294,   53,42155,  265,42298,20273,42155,    9,42302,37899,42155,
+37617,42155, 1471,42155,  265,42310,  587,42155,35187,42315,38233,42155,
+38004,42155,36773,42155,37845,42322,38056,42155,39019,42327,37145,42327,
+37844,42155,40305,42333,37933,42155,  483,42155,37845,42155,36773,42340,
+40999,42155,  305,42155,21605,42347,  713,42155, 9195,42350,21605,42351,
+ 9195,42155,  713,42356,    2,42155,    1,42360, 8229,42361,40987,42361,
+35187,42361,36773,42369,35187,42360,39019,42373,37145,42373,    3,42155,
+42179,42379,    1,42379,    7,42379,   15,42385,38305,42387,    1,42378,
+38903,42391,38971,42391,39161,42391,40855,42391,18967,42391,42389,42391,
+    7,42378,40704,42405,42391,42407,    9,42405,38305,42410,42391,42413,
+38305,42405,    9,42416,42391,42419,40987,42378, 1369,42379,35187,42378,
+40305,42427,   25,42155,21605,42431,    2,42154,    1,42435,42379,42436,
+42382,42435,42423,42435,42269,42435,42333,42435,42427,42435,42379,42435,
+    1,42450,40987,42451,35187,42451, 3997,42435, 4067,42435, 9459,42435,
+ 8953,42435, 8277,42435, 3867,42435,    3,42154,42165,42471,42363,42471,
+42345,42471,42366,42471,26219,42471, 8647,42471,42341,42471,42368,42471,
+19396,42471,42361,42471,    1,42491,40987,42490,35187,42490,41417,42471,
+  483,42471,18967,42471,    9,42502,    9,42471,18967,42506,40987,42471,
+42361,42510,35187,42471,42361,42514,32805,42155,  265,42155,  253,42520,
+ 1471,42520,   53,42520,40987,42155,    3,42528,42435,42531,    3,42529,
+42361,42535,35187,42155,    7,42539,38305,42541,    2,42543,    2,42542,
+    2,42541,38305,42548,    2,42540, 1368,42539,  375,42538, 1369,42539,
+    2,42538,39019,42561,38305,42560,42559,42565,37145,42561,    3,42538,
+40305,42571,42545,42571,42435,42571,    3,42539,40277,42579,39315,42579,
+    7,42579,38305,42585,42561,42587,42551,42579,42547,42579,42561,42579,
+42361,42579,    2,42539,    7,42598,42571,42599,37845,42599,    9,42155,
+20273,42606, 9617,42606,    6,38304,40509,42613,31103,42615,21604,42613,
+40471,42613,40851,42613,40037,42613,38931,42613, 8982,42613,27979,42613,
+  483,42631,41941,42631,40957,42613,37933,42637,41503,42613,  483,42641,
+ 8861,42613,   17,42644,17423,42613, 1011,42649, 4745,42613, 1011,42653,
+ 9875,42613, 1011,42657, 1471,42613,36773,42613,  483,42663,37844,42613,
+40305,42667,37979,42613,41941,42671, 1369,42613,38057,42675,  331,42613,
+   17,42678, 1325,42613,   17,42682,  334,42613, 1328,42613, 8337,42613,
+  483,42691,20103,42613,  483,42695,   53,42613,  393,42613, 1359,42613,
+    3,42613,  483,42705,35187,42704,40305,42709,10257,42705,37357,42705,
+    2,42613,   62,42613,   59,42613,   17,42720,20501,42613, 1011,42725,
+  253,42613,    3,42612,40975,42731,40103,42731,27979,42731,40519,42731,
+40011,42731,16381,42731,13325,42731,26293,42731, 8685,42731,41503,42731,
+ 1369,42731, 4569,42731,35843,42731,19513,42731, 3863,42731, 9955,42731,
+20697,42731, 4137,42731,37019,42731, 8401,42731,20219,42731, 4063,42731,
+14625,42731,37377,42731,10273,42731,18967,42613,  165,42783,  241,42613,
+35187,42613,    3,42788,40305,42791,    3,42789,40277,42795,39315,42795,
+   17,42613, 8861,42800,  331,42800, 1325,42800,   59,42800,    7,38305,
+25004,42810,25005,42810,25184,42810,25185,42810,  264,42811,    5,42811,
+    0,42822,    3,42822,    1,42810,    4,42829,25004,42811,42815,42833,
+25184,42811,42819,42837,25005,42811,42813,42841,25185,42811,42817,42845,
+41493,42811,41622,42811,25367,42810,30748,42810,39650,42811,42752,42811,
+38673,42811,38675,42811,39823,42811,39783,42811,27533,42811,26625,42869,
+  331,42811,35187,42873,41559,42811, 1369,42876,  767,42811,18967,42881,
+41019,42811,37899,42885,37617,42885,35931,42885,27021,42885,30091,42885,
+ 9195,42885,25793,42811,30091,42899,27021,42899,37845,42811,42667,42905,
+   59,42811,35187,42909, 1325,42811,35187,42913,37897,42811,17125,42810,
+30091,42810,25793,42921,41019,42921,  265,42920, 1369,42811,30091,42929,
+41559,42928,20103,42929, 8337,42929,36773,42929,42731,42928,39633,42928,
+42707,42811,42704,42811,  483,42947,39633,42811, 1369,42950,39749,42811,
+  483,42955, 1275,42811,  265,42810,40411,42961,30091,42960,21605,42810,
+26331,42967,25793,42967,23755,42967,27805,42967,39633,42967,42731,42967,
+41559,42967,41019,42967, 8495,42967,42731,42811, 1369,42986,  241,42810,
+  375,42991, 9805,42991,18967,42810, 1141,42997,   33,42997, 1447,42997,
+  265,42811,35187,43005, 9377,43005, 9533,43005,37145,43005,21605,42811,
+34311,43015,42619,43015,26625,43015,24545,43015, 9731,43015,    2,42810,
+    3,42810,    0,43028,43005,43031,  295,43029, 1108,43029,35927,43029,
+38155,43029,37611,43029,    9,43029, 1011,43044, 1011,43029,    9,43048,
+    2,42811,42831,43053,    5,43053,42829,43057,36256,43053,    9,43053,
+35187,43062,35187,43053,    9,43066,    3,42811,    5,43070,22807,43071,
+37663,43071,42613,43070,  483,43079,  241,43071,    9,43083,37845,42810,
+41559,43087,38389,43087,42731,43087,39633,43087,41019,43087,42613,42811,
+32805,43099,37845,43098,37845,43099,37844,43098,43105,43107,37844,43099,
+43103,43111,    3,43099, 1369,43115,    3,43098,  483,43119,   15,42811,
+20273,43123, 9617,43123,35187,42810,    7,43129,    2,43130,    2,43131,
+38305,43129,    3,43136,43135,43139,    3,43137,43133,43143, 1368,43129,
+43143,43147,   59,43129, 1325,43129,  331,43129,  265,43129,    2,43129,
+    7,43158,43143,43161,    3,43129,38305,43164,43135,43167,37408,38305,
+    7,43171,    2,43172,40999,43175,    2,43173,40101,43179,41017,43179,
+ 1368,43171,40999,43185,   59,43171, 1325,43171,  331,43171,  265,43171,
+    2,43170,37783,43197,    2,43171,    7,43200,40999,43203,37617,43201,
+    3,43171,38305,43208,43179,43211,    3,38305,43129,43214,43135,43217,
+    1,43214, 1011,43221,42041,43221, 1418,43221,41941,43227,42035,43221,
+  669,43221,41941,43233,42089,43221,42129,43221, 1369,43221,   15,43240,
+41941,43243,   15,43221, 1369,43246,41941,43249,11989,43215,    9,43253,
+13737,43215,    9,43257,37357,43215,10257,43215,38118,43215,38132,43215,
+37544,43215,37409,43215,  483,43270,  113,43215,  587,43275,37345,43215,
+37241,43214,40993,43281,40993,43215,37241,43285,    9,43215,38057,43288,
+  483,43215,38057,43292,37409,43292,10289,43215,   15,43214,  165,43301,
+   11,43214,    9,43214,11251,43307, 5177,43307,   17,43214,  113,43313,
+   11,43215,  165,43215,    7,43214,    0,43321,    4,43322,    4,43321,
+    0,43326,35186,43321,  295,43321, 1108,43321,35927,43321,38155,43321,
+37611,43321,    9,43321, 1011,43342, 1011,43321,    9,43346,    7,43215,
+21604,43351,    1,43351,    3,43354,    3,43351,    1,43358,   15,43351,
+38305,43363,43353,43365,43357,43365,43361,43365, 1011,43363,37409,43214,
+43179,43375,41941,43215,37408,43379,    7,43379,35187,43382,35187,43379,
+    6,43386,    7,43386,    6,43387,43391,43393,    7,43387,43389,43397,
+ 1011,43215,37408,43401,    7,43401,35187,43404,35187,43401,    7,43408,
+38057,43215,40097,43413,40969,43413,    7,43413,    9,43412,  483,43412,
+35187,43214,40305,43425,40275,43425,38305,43425,    6,43430,43413,43433,
+    6,43425,38305,43436,43413,43439,41941,43425,    6,43443,    7,43443,
+    6,43442,43447,43449,    7,43442,43445,43453, 1011,43425,    7,43457,
+37844,38305,42336,43461,42917,43461,42905,43461,39013,43461,40305,43461,
+40275,43461,37933,43461,42155,43474,42155,43461,37933,43478,    6,43460,
+41941,43461,    6,43485,    7,43485,    6,43484,43489,43491,    7,43484,
+43487,43495, 1011,43461,    7,43499,    2,38305,41603,43503,41686,43503,
+41825,43503,41828,43503,42541,43502,42579,43513,16936,43503,36400,43503,
+36439,43519,36348,43503,    6,43523,36413,43525,    6,43522,36439,43529,
+36439,43523,41744,43503,41688,43503,41605,43503,41706,43503,41620,43503,
+    1,43503, 1275,43544,    4,43544,    7,43544,41417,43551,    7,43545,
+39633,43555,41559,43555,42731,43555,41019,43555,    1,43502,41692,43565,
+41607,43565,41653,43565,41417,43570,41417,43565,41653,43574,41502,43565,
+41559,43579,41019,43565,    7,43582,41559,43585,    7,43583,41417,43589,
+    7,43565,41019,43593,41653,43595,41019,43592,41559,43599,    5,43502,
+21605,43603,42810,43604,42811,43605,43607,43609,42811,43604,42810,43605,
+43613,43615,41692,43503,35187,43618,41607,43503,35187,43622,41360,43503,
+41559,43627,41820,43503,41559,43631,41544,43503,41559,43635,35760,43503,
+ 8315,43503,37408,43502,37783,43643,42538,43503,42601,43647,42553,43647,
+42555,43647,41742,43503,41417,43654,41486,43503,41653,43658,41417,43503,
+41827,43662,41742,43662,41653,43662,35187,43668,35187,43662,41653,43672,
+37783,43503,37325,43502,42795,43679,42579,43679,41502,43503,41559,43685,
+35187,43687,35187,43684,41559,43691,37241,43503,37409,43695,41019,43697,
+41381,43503,41653,43700, 1275,43503,    1,43704,35187,43704,    9,43705,
+ 9731,43711,43221,43711,43549,43711,26625,43711,  587,43503,42811,43721,
+35895,43723,15879,43723, 4787,43723,41653,43503,    1,43731,41417,43733,
+41381,43730,41486,43730,41417,43730,35187,43740,35187,43730,41417,43744,
+    9,43502,36727,43749,36079,43749,37895,43749,41827,43503,41417,43756,
+    6,43502,39616,43761,39614,43761,39578,43761,39901,43761,41282,43761,
+41266,43761,41270,43761,39961,43761,39981,43761,35718,43761,39869,43781,
+41019,43761,35895,43784,15879,43784, 4787,43784,15879,43761,39489,43792,
+41019,43792, 4787,43761,39489,43798,41019,43798,35895,43761,39489,43804,
+41019,43804,  587,43761,35187,43810,39869,43813,35187,43761,  587,43816,
+39869,43819,  587,43817,39489,43823,41019,43823,39489,43761,15879,43828,
+ 4787,43828,35895,43828,    7,43502,    6,43503,36348,43838,36439,43841,
+36348,43839,36429,43845,    7,43503,41817,43848,43817,43849,41019,43853,
+    4,43849,    0,43856,43784,43859,41019,43859,43761,43862,43761,43859,
+41019,43866,    0,43849,    4,43870,43784,43873,41019,43873,43761,43876,
+43761,43873,41019,43880,    1,43848,41417,43885,35186,43849,43784,43889,
+41019,43889,43761,43892,43761,43889,41019,43896,41816,43848,41559,43901,
+41019,43848,41559,43905,35187,43907,35187,43904,41559,43911,41019,43849,
+41827,43915,43851,43915,41742,43915,41653,43915,35187,43922,35187,43915,
+41653,43926,35187,43848,41417,43931,41019,43930,41559,43935,41019,43931,
+41653,43939,37409,43502,41354,43943,40165,43943,41019,43943,37241,43948,
+37241,43943,41019,43952,37408,43503,41417,43957,37663,43957,41019,43956,
+41559,43963,41019,43957,41653,43967,41816,43503,    6,43970,    7,43970,
+41559,43975,    6,43971,43975,43979,    7,43971,43973,43983,41417,43983,
+41019,43503,    1,43989,    7,43990,41417,43993,    7,43991,41559,43997,
+37408,43988,41559,44001,37408,43989,41381,44005,    7,43989,41381,44009,
+41486,44009,    1,44008,41417,44015,41417,44009,35187,44018,35187,44009,
+41417,44022,    7,43988,41559,44027,35187,44029,35187,44026,41559,44033,
+35187,43988,    6,44036,    7,44036,41559,44041,    6,44037,44041,44045,
+    7,44037,44039,44049,41417,44049,21605,43503,    7,44055,  265,44057,
+35187,43503,41692,44060,41607,44060,41502,44060,41559,44067, 1275,44060,
+41653,44060,41417,44072,36945,44061,41019,44077,41417,44060,41653,44080,
+    6,44061,41922,44085,43413,44085,41019,44085,36773,44090,36773,44085,
+41019,44094,    7,44061,41559,44099,42731,44099,39633,44099,41019,44099,
+    6,44060,44099,44109,    7,44060,41417,44113,41019,44112,41559,44117,
+44085,44113,41019,44113,41653,44123,41019,44060,    6,44126,    7,44126,
+41559,44131,    6,44127,44131,44135,    7,44127,44129,44139,41417,44139,
+36773,44061,41417,44145,    7,44145,41019,44149,35187,43502,41217,44153,
+41472,44153,29229,44153,41099,44153,36429,44153,42559,44153,41417,44153,
+37145,44166,37783,44153,37214,44153,41019,44173,    7,44153,41019,44177,
+37145,44179,37145,44176,41019,44183,37145,44153,41417,44186,    7,44186,
+41019,44191,38056,38305,41472,44195,41217,44195,41099,44195,29229,44195,
+36429,44195,42559,44195,35187,44195,    6,44209,43413,44211,41417,44195,
+37145,44214,37783,44195,37214,44195,41019,44221,    7,44195,41019,44225,
+37145,44227,37145,44224,41019,44231,37145,44195,41417,44234,    7,44234,
+41019,44239,    6,38305,42453,44243,42493,44243,42472,44243,42439,44243,
+42474,44243,42441,44243,42363,44243,42471,44256,42381,44243,42165,44243,
+42471,44262,42325,44243,42330,44243,42343,44243,42321,44243,42319,44243,
+42371,44243,42376,44243,42568,44243,42447,44243,42484,44243,42054,44243,
+42056,44243,44171,44243,43645,44243,43960,44243,44219,44243,43201,44243,
+37617,44298,43206,44243,38711,44243,43199,44243,42605,44243,40231,44243,
+43677,44243,40959,44243,10586,44243,10827,44243,42594,44243,42603,44243,
+42577,44243,42596,44243, 6664,44243, 6243,44243, 9780,44242,  566,44242,
+  566,44243,  567,44242,44337,44339,43517,44243, 9781,44242,42012,44243,
+36303,44242,36303,44243,26970,44242,26971,44242,43639,44243, 4593,44243,
+ 6625,44358, 3113,44243, 3023,44243, 4736,44243, 6653,44243,42518,44243,
+ 3251,44243,42516,44243,42486,44243,42449,44243,42496,44243,42456,44243,
+19257,44243,19243,44243,43425,44242,43413,44389,40511,44243,17452,44243,
+42085,44243,43707,44243,42087,44243,40961,44243,43709,44243,44071,44243,
+36099,44243,36098,44242,44409,44411,36099,44242,36098,44243,44415,44417,
+43605,44243,43222,44242,43223,44243,44423,44425,43222,44243,43223,44242,
+44429,44431,42199,44243,24081,44243,42181,44243,42383,44243,42435,44441,
+42401,44243,42177,44243,43547,44243,    5,44242,42283,44451,25380,44451,
+42155,44455, 1369,44451,21605,44458,42155,44461,21605,44451, 1369,44464,
+42155,44467,42373,44243,37145,44470,42561,44243,37145,44474,42579,44474,
+42327,44243,37145,44480,27514,44243,42490,44243,35187,44486,42451,44243,
+35187,44490,  413,44243,32805,44243,42155,44496,28547,44243,42064,44243,
+42138,44243,40517,44243,40543,44243,30294,44243,38004,44243,43461,44513,
+38232,44243,42155,44517,38005,44243,42155,44521,30749,44243, 9780,44243,
+44345,44527,26970,44243,44355,44531, 6625,44243, 4593,44534,   33,44535,
+ 9781,44243,44333,44541,25005,44243,26971,44243,44353,44547,25185,44243,
+25589,44243,42074,44243,42152,44243,10831,44243,   77,44243,  120,44243,
+  506,44243,38041,44243, 5101,44243,16989,44243,10511,44243, 4931,44243,
+ 5267,44243,16981,44243,13017,44243,12705,44243,13673,44243,18391,44243,
+18617,44243,14599,44243, 9366,44243,36302,44243,18217,44243,42332,44243,
+42435,44599,42570,44243,42435,44603,42426,44243,42435,44607,41539,44243,
+41720,44243, 9132,44243, 1216,44243,36302,44242,    3,44618,44351,44621,
+30748,44243,30748,44242,44525,44627,30749,44242,44625,44631,16931,44243,
+35931,44243,41941,44636,39600,44243,42500,44243,18929,44243,38669,44243,
+38677,44243,17019,44243,39941,44243,39955,44243,27021,44243,  483,44656,
+41941,44656,37844,44242,44351,44663,41653,44243,  483,44666,43413,44243,
+43425,44671,42514,44243,42361,44674,42368,44243,42471,44678,42361,44243,
+42579,44682,42514,44682,42471,44682,35187,44688,35187,44682,42471,44692,
+20234,44243, 8444,44243,  567,44243,44335,44701,16937,44243,   11,44705,
+ 1369,44705,26625,44243,41941,44710,41941,44243,37899,44714,37617,44714,
+35931,44714,27021,44714,26625,44714, 9195,44714, 9731,44714,43957,44243,
+37663,44730,20103,44243,  483,44734, 8337,44243,  483,44738, 9533,44243,
+ 4727,44243,   25,44744,10527,44243,   25,44748, 4541,44243,38128,44243,
+38057,44243,42155,44757,37145,44759,37145,44756,42155,44763,  587,44756,
+37845,44243,43461,44769,36773,44771,36773,44768,43461,44775,   25,44243,
+10527,44778, 4727,44778,  113,44778, 9195,44243,41941,44786,  483,44786,
+37782,44243,43197,44793,43643,44793,38709,44793,17451,44243, 1011,44800,
+35688,44243,36910,44243,36923,44243,37899,44243,41941,44810,37617,44243,
+41941,44814,43201,44814, 9731,44243,41941,44820, 8997,44243,  483,44824,
+   66,44243,   33,44829,  483,44243,27021,44832,30091,44832,  241,44832,
+ 9195,44832,41653,44832, 8997,44832,42471,44832,39489,44832,20103,44832,
+ 8337,44832,36773,44832,  903,44243, 1011,44856,18967,44243,  567,44861,
+  566,44860,44863,44865,  566,44861,  567,44860,44869,44871,  241,44243,
+  483,44874,42425,44243,42378,44243,42435,44881,35187,44883,35187,44880,
+42435,44887, 1369,44881,36773,44243,37845,44892,43461,44895,  483,44892,
+37845,44893,41019,44901,37145,44243,42327,44904,42373,44904,42561,44904,
+38057,44904,42155,44913,42341,44243,42471,44916,30091,44243,  483,44920,
+  113,44243,   25,44924,35187,44924,17125,44243,37663,44243,43957,44932,
+39489,44243,  483,44936,39943,44243, 1369,44941,  587,44243,43215,44945,
+35895,44947,15879,44947, 4787,44947,38057,44944, 8449,44243,20237,44243,
+  265,44242,40399,44961,   11,44961,42471,44243,42165,44966,42363,44966,
+42341,44966,42368,44966,42361,44966,35187,44976,  483,44966,35187,44966,
+42361,44982,20834,44243, 1011,44243,17451,44988,35187,44988,  903,44988,
+20763,44988,20763,44243, 1011,44998,  257,44243,42579,44243,42561,45004,
+42361,45004,    2,44242,39616,45011,39614,45011,39578,45011,39901,45011,
+41282,45011,41266,45011,41270,45011,39961,45011,39981,45011,35718,45011,
+39869,45031,41019,45011,35895,45034,15879,45034, 4787,45034,15879,45011,
+39489,45042,41019,45042, 4787,45011,39489,45048,41019,45048,35895,45011,
+39489,45054,41019,45054,  587,45011,35187,45060,39869,45063,35187,45011,
+  587,45066,39869,45069,  587,45067,39489,45073,41019,45073,39489,45011,
+15879,45078, 4787,45078,35895,45078,    3,44242,36302,45087,44349,45089,
+35187,45086,44351,45093,    2,44243,   14,45097,    5,45097,    6,45100,
+    6,45097,    5,45104,21605,45097,38305,45109,45099,45111,45103,45111,
+45107,45111,43215,45097,43325,45119,43329,45119,35895,45119,15879,45119,
+ 4787,45119,43331,45119,35187,45119,43321,45133,35187,45096,39313,45137,
+40157,45137,43281,45137,43215,45137,37241,45145,    3,44243,42539,45148,
+38305,45149,37408,45152,37408,45153,45067,45149,41019,45159,    4,45149,
+    0,45163,38305,45163,    0,45162,45034,45169,41019,45169,45011,45172,
+45011,45169,41019,45176,45119,45169,    0,45149,38305,45183,    4,45182,
+45034,45187,41019,45187,45011,45190,45011,45187,41019,45194,45119,45187,
+    0,45148,38305,45148,    1,45148,45176,45205,45194,45205,45169,45205,
+45011,45210,45187,45205,45011,45214,45159,45205,45011,45205,45169,45220,
+45187,45220,35186,45148,35186,45149,38305,45229,    7,45231,45220,45229,
+45205,45229,45011,45236,45034,45229,41019,45229,45011,45242,45011,45229,
+45205,45246,41019,45246,45119,45229,    1,45149,45165,45255,45011,45257,
+45167,45255,45011,45261,    5,45149,45185,45265,45011,45267,43171,45149,
+37617,45271,42538,45148,42435,45275,37409,45148,38709,45279,43197,45279,
+45155,45279,43643,45279,42155,45148,42435,45289,35187,45291,35187,45288,
+42435,45295, 1369,45289, 1011,45149,  483,45301,   11,45148,   33,45305,
+37409,45149,45157,45309,43957,45309,   11,45149,   25,45315,35187,45315,
+42155,45149,42579,45321,45151,45321,42514,45321,42471,45321,35187,45328,
+35187,45321,42471,45332,45066,45149,45201,45337,45203,45337,35187,45149,
+45201,45343,45011,45345,45203,45343,45011,45349,45011,45342,45201,45353,
+45203,45353,45011,45149,35187,45358,45201,45361,45203,45361,35187,45148,
+40217,45367,45233,45367,42155,45366,42435,45373,42155,45367,42471,45377,
+37845,44242,41922,45381,43413,45381,44595,45381,44993,45381,41019,45381,
+36773,45390,36773,45381,41019,45394,38056,44243,39313,45399,40157,45399,
+43281,45399,43215,45399,37241,45407,37844,44243,40217,45411,42155,45410,
+42435,45415,42155,45411,42471,45419,42538,44243,    3,45422,42435,45425,
+    3,45423,42361,45429,42155,44243,32805,45432,37845,45432,37845,45433,
+37844,45432,42435,45441,45439,45441,37844,45433,42341,45447,45437,45447,
+    3,45433,42341,45453,42368,45453,42361,45453,35187,45458,35187,45453,
+42361,45462,  483,45453,    3,45432,42435,45469,35187,45471,35187,45468,
+42435,45475, 1369,45469,35187,45432,    3,45480,42435,45483,    3,45481,
+42361,45487,   11,44243, 8861,45491,    3,45490,   33,45495,    3,45491,
+  113,45499,  331,45491, 1325,45491,   59,45491,35187,44243,42490,45508,
+42451,45508,38305,45508,    7,45515,    2,45517,    2,45516,    2,45515,
+    7,45522, 1368,45515, 1011,45508,45381,45529,42378,45508,42435,45533,
+42471,45508,42361,45536,37285,45509,41019,45541,42361,45508,42471,45544,
+  113,45508,    2,45509,41354,45551,40165,45551,38305,45551,    7,45557,
+41019,45551,37241,45560,37241,45551,41019,45564,    3,45509,45519,45569,
+    2,45508,40157,45573,39313,45573,43281,45573,43215,45573,37241,45581,
+    3,45508,40217,45585,45521,45585,45525,45585,45559,45585,45527,45585,
+42155,45584,42435,45597,42155,45585,42471,45601,42155,45508,    3,45604,
+42435,45607,    3,45605,42361,45611,37409,44243,43503,45615,37663,45617,
+    3,45615,43201,45621,    3,45614,38709,45625,43197,45625,43643,45625,
+35187,44242,    3,45632,44351,45635,35187,38305,37214,45639,    2,45641,
+39019,45643,39021,45641,37286,45639,35890,45638,35891,45639,45651,45653,
+35891,45638,35890,45639,45657,45659,38152,45638,38153,45639,45663,45665,
+38296,45638,38297,45639,45669,45671,38153,45638,38152,45639,45675,45677,
+38297,45638,38296,45639,45681,45683,37283,45639,42675,45639,37282,45639,
+42674,45639,37899,45638,37885,45695,38293,45639,37885,45639,37899,45701,
+44945,45639,38292,45639,44944,45639,37287,45639,38173,45638,38172,45639,
+45713,45715,38303,45638,38302,45639,45719,45721,38173,45639,38172,45638,
+45725,45727,38303,45639,38302,45638,45731,45733,45096,45639,45149,45639,
+    7,45738,45367,45741,45097,45639,37241,45639,    2,45747,    2,45746,
+  587,45746,42613,45639, 1369,45754,38271,45639, 1369,45758,44243,45639,
+    2,45763,    2,45762,  587,45762,  136,45639,  137,45639, 1530,45638,
+  842,45638,  669,45639, 1419,45639,  843,45639,39085,45783,45777,45783,
+ 1531,45639,45775,45789, 1530,45639,  843,45638,  842,45639,45795,45797,
+ 1531,45638,45793,45801, 1368,45639,45411,45805,40999,45805,45367,45805,
+45585,45805,42613,45805,37845,45805,44243,45817,  586,45639,39847,45821,
+39142,45821,39085,45821,  483,45826,37241,45821,  483,45821,39085,45832,
+  586,45638,38675,45837,39823,45837,39783,45837,39749,45837,  483,45845,
+ 1418,45639,  668,45639,  587,45638,37885,45853,37202,45853,37145,45853,
+  483,45858,  483,45853,37145,45862,  587,45639,37241,45866,44243,45866,
+    9,45866,  483,45639,  587,45875,37145,45877, 1369,45639,35760,45880,
+35761,45881,45883,45885,35760,45881,35761,45880,45889,45891,42613,45880,
+38271,45880,   15,45880,    9,45639,    2,45900,    2,45901,  587,45900,
+  265,45639,  375,45909,   15,45639, 1369,45912,    7,45639,40956,45917,
+44060,45917,40957,45917,44061,45917,43502,45917,37844,45917,35187,45917,
+    3,45930,43503,45930,    3,45931,45927,45937, 1369,45931,38305,45917,
+    2,45942,45937,45945,37845,45942,    2,45943,45933,45951,45929,45951,
+  587,45943,45149,45917,37145,45959,45227,45959,37845,45917,38305,45964,
+43503,45917,35187,45968,  375,45917,45148,45917,    2,45917,40101,45977,
+41017,45977,38305,45976,45937,45983,44904,45977,45569,45977,43375,45977,
+39019,45977,44243,45977,37145,45994,37145,45977,44243,45998,    3,45917,
+35187,46002,45951,46005,44243,46002,    3,45916,45943,46011,    7,46011,
+38305,46015,45977,46017,45994,46011,45959,46011,45967,46011,45919,46011,
+45949,46011,45925,46011,37241,46011,45977,46011,44243,46034,44243,46011,
+45977,46038,    2,45916,45931,46043,40999,46043,45975,46043,45367,46043,
+45585,46043,46009,46043,45971,46043,45921,46043,45935,46043,45923,46043,
+45411,46043,42613,46043,46003,46043,44243,46069,37845,46043,44243,46073,
+44243,45917,    3,46076,46043,46079,    3,46077,45977,46083,    6,45638,
+45998,46087,46073,46087,45817,46087,37844,46087,46043,46095,45805,46095,
+35187,46087,    3,46101,45977,46103,    3,46100,46043,46107,45805,46107,
+37145,46087,45977,46112,45977,46087,37145,46116,    3,46087,35187,46120,
+46043,46123,45805,46123,45917,46121,37145,46129,45917,46087,35187,46132,
+    2,46135,    2,46134,38057,46132,38056,46132,    2,46133,46141,46145,
+    3,46133,46139,46149,46143,46149,    2,46132,35187,46154,46149,46157,
+46149,46155,    3,46132,46137,46163,46145,46163,    3,45639,    5,46169,
+    6,46171,    4,46168,    0,46168,    5,46168,    1,46168,45983,46169,
+45945,46169,43679,46169,45927,46169,40277,46169,45749,46169,45765,46169,
+39315,46169,45905,46169,37241,46169,45977,46169,42613,46203,43848,46169,
+  256,46169,    6,46169,46175,46211,46177,46211,37145,46211,    7,46169,
+46179,46219,46181,46219,41019,46219,45639,46218,    2,46227,38305,46219,
+46229,46231,    3,46231,46227,46235,45977,46231,43503,46218,  241,46218,
+38271,46219,    7,46168,37241,46247,38057,46169,38305,46251,46211,46253,
+43503,46169,    6,46256,    7,46256,    6,46257,46261,46263,    7,46257,
+46259,46267,  241,46169,    7,46270,    2,45638,41472,46275,41217,46275,
+46175,46275,46211,46280,46177,46275,46211,46284,46212,46275,46214,46275,
+46221,46275,46223,46275,46173,46275,45930,46275,46043,46299,46045,46275,
+46216,46275,46225,46275,41099,46275,46032,46275,45711,46275,46200,46275,
+45745,46275,46248,46275,46245,46275,35187,46275,45917,46322,46043,46325,
+45917,46323,46011,46329,45830,46275,29229,46275,45773,46275,36429,46275,
+45895,46275,45897,46275,45687,46275,45693,46275,45705,46275,45707,46275,
+45849,46275,45779,46275,42559,46275,45899,46275,45915,46275,45757,46275,
+45761,46275,45941,46275,41417,46275,37145,46368,45821,46275,37241,46372,
+46011,46275,37241,46376,46247,46275,37241,46380,45881,46275,42613,46385,
+37241,46275,46011,46388,46169,46388,46247,46388,45821,46388,46211,46275,
+46175,46398,46177,46398,37145,46398,37783,46275,44243,46407,45917,46275,
+35187,46410,46043,46413,37214,46275,41019,46417,46218,46275,46179,46421,
+46181,46421,41019,46421,    7,46275,41019,46429,37145,46431,46169,46429,
+46175,46435,46177,46435,37145,46435,37145,46428,41019,46443,46169,46428,
+46179,46447,46181,46447,41019,46447,37145,46275,41417,46454,46211,46454,
+    7,46454,41019,46461,46169,46275,35187,46464,    6,46467,    6,46466,
+38305,46465,46211,46473,38271,46464,44243,46465,38270,46464,37241,46464,
+    6,46465,46477,46485,    7,46465,46471,46489,46481,46489,    6,46464,
+46473,46495,35187,46494,46489,46499,46489,46495,    7,46464,46179,46505,
+46181,46505,46469,46505,46485,46505,41019,46505,    2,45639,42671,46517,
+39429,46517,44814,46517,44810,46517,44636,46517,37241,46516,40077,46517,
+44243,46516,46003,46517,37241,46535,    9,46516,44243,46517,37617,46540,
+37899,46540,35931,46540,35931,46517,44243,46548,37617,46517,44243,46552,
+37899,46517,44243,46556,    7,46517,44243,46561,    7,46516,46107,46565,
+46123,46565,46095,46565,40999,46565,45585,46565,45411,46565,45367,46565,
+42613,46565,37845,46565,46087,46583,44243,46583,37845,46517,46211,46589,
+41417,46589,    7,46589,41019,46595,    3,45638,45951,46599,45942,46599,
+46011,46603,46013,46599,46066,46599,46540,46599,40305,46599,46529,46599,
+45751,46599,46533,46599,45767,46599,46580,46599,46563,46599,45649,46599,
+45737,46599,38305,46599,45917,46630,46011,46633,45917,46631,46043,46637,
+45814,46599,45771,46599,45869,46599,45871,46599,45689,46599,45691,46599,
+45699,46599,45709,46599,45851,46599,45781,46599,40275,46599,46539,46599,
+45903,46599,45873,46599,45907,46599,45753,46599,45769,46599,45957,46599,
+45805,46599,42613,46676,46043,46599,42613,46680,46565,46599,42613,46684,
+45867,46599,37241,46689,42613,46599,46043,46692,46565,46692,45805,46692,
+45917,46599,38305,46700,46011,46703,46560,46599,44243,46599,46517,46708,
+    7,46599,38305,46713,46517,46715,46517,46712,41941,46599,    6,46721,
+    7,46721,    6,46720,46725,46727,    7,46720,46723,46731, 1011,46599,
+    7,46735,46517,46599,38305,46738,35187,46739,    6,46742,    6,46743,
+44243,46738,38271,46739,38270,46739,37241,46739,    6,46739,35187,46756,
+46741,46757,    7,46739,41019,46763,46747,46763,    6,46738,46763,46769,
+46751,46769,    7,46738,46759,46775,46745,46775,46757,46775,46753,46775,
+    6,45639,    7,45638,43214,46787,45977,46789,38305,46787,    3,46793,
+46043,46795,46565,46795,45805,46795,    3,46792,45977,46803,   59,46787,
+ 1325,46787,  331,46787,  265,46787,    2,46787,    7,46814,46795,46817,
+    3,46787,38305,46820,45977,46823,46785,46787,35187,46827,    2,46828,
+    2,46829,38057,46827,38056,46827,    2,46827,35187,46838,    3,46827,
+46833,46843,    2,46826,46843,46847,46835,46847,    3,46826,46841,46853,
+46831,46853,46839,46853,46837,46853,    0,    6,13135,46863,13169,46864,
+ 4871,46863, 4893,46868,13172,46863, 4894,46863,13136,46863,13143,46877,
+ 4872,46863, 4879,46881,13145,46863, 4881,46863,37417,46863,38056,46888,
+38057,46889,46891,46893,38057,46888,38056,46889,46897,46899,17176,46863,
+17380,46863,16950,46863,17058,46863,16948,46863,17056,46863,16974,46863,
+17072,46863,16996,46863,17086,46863, 3348,46863,18291,46863, 7316,46863,
+ 8455,46863, 8343,46863, 8353,46863,13139,46863,13175,46863,13155,46863,
+13517,46863,15197,46863,15485,46863,15512,46863,15595,46863,15203,46863,
+ 5757,46863, 5453,46863, 5471,46863, 5455,46863, 4863,46959, 5507,46863,
+12569,46863,12387,46863,12551,46966,12552,46863,16995,46863,16941,46863,
+16977,46974,16978,46863,17017,46862,17016,46862,19836,46863,19857,46985,
+19815,46863,    4,46988,19857,46991,    4,46989,19843,46995,27930,46863,
+27895,46999,27857,46863,    4,47002,27895,47005,    4,47003,27907,47009,
+36303,46862,36325,47013,27128,46863, 9136,46863,27266,46863,27163,46863,
+34310,46863,34447,47025,46516,46863,46599,47029,33454,46863,33368,46863,
+28027,46863,28111,46863,28117,46863,26928,46863,24253,46863,30569,46863,
+30316,46863,28213,46863,26525,46863, 9137,46863,  273,46863, 1477,46863,
+  281,46863,17011,46863, 5043,46863,15503,46863, 8997,47066,24558,46863,
+26575,46863,41877,46863,  120,46863,   77,46863,16977,46863,16941,47080,
+ 9262,46863,14813,46863,26605,46863,41923,46863, 8843,46863,37131,46863,
+41907,46863,26591,46863,41893,46863,37113,46863,20255,46863, 9288,46863,
+ 8697,46863, 9275,46863, 8784,46863,19877,46863,41867,46863,20043,46863,
+21376,46863,21485,46863,19787,46863,19391,46863,19299,46863,19271,46863,
+19283,46863,17010,46863, 5042,46863,36518,46863,40664,46863,17017,46863,
+46983,47143, 1516,46863,  948,46863,17016,46863,46981,47151,16972,46863,
+  903,47154,17070,46863, 1011,47158,17175,46863,  903,47162,17379,46863,
+ 1011,47166, 4213,46863,  375,47170, 8757,46863,  375,47174, 4266,46863,
+16865,46863,16873,46863,16867,46863,12642,46863, 8896,46863,14740,46863,
+ 8355,46863,  264,47193,  265,47192,47195,47197,  264,47192,  265,47193,
+47201,47203,14515,46863,14517,46863,14519,46863,20201,46863,36979,46863,
+20152,46863,36898,46863,20239,46863,37095,46863,21522,46863,38266,46863,
+17082,46863,  903,47228,16990,46863,16943,47233, 1011,47232,35780,46863,
+29644,46863,43412,46863,15628,46863, 9044,46863,  264,47247,  265,47246,
+47249,47251,  264,47246,  265,47247,47255,47257,12484,46863,12486,46863,
+12488,46863,12551,46863,12387,47266,12547,46863,12633,46863,12507,46863,
+12497,46863,12501,46863,13381,46863,13169,46863,13135,47282, 4893,46863,
+ 4871,47286,12563,46863,27255,46863,  483,47292, 9287,46863,  483,47296,
+13119,46863,  264,47300,13143,47303,  264,47301,13169,47307, 4863,46863,
+  264,47310, 4879,47313,  264,47311, 4893,47317, 7315,46863,  413,47320,
+  264,47320,  264,47321,  265,47320,47327,47329,  265,47321,47325,47333,
+14653,46863,  375,47336,16875,46863,12504,46863,19478,46863,35766,46863,
+20044,46863,36534,46863,12566,46863,12391,47353,33338,46863,34447,47357,
+45866,46863,46599,47361,25545,46863,40675,46863, 1413,46863,  922,46863,
+ 1281,46863,  247,46863,36303,46863,38299,47377,37897,47377,36335,47377,
+35893,47377,20035,46863,   11,47387,   11,47386,36527,46863,  587,47392,
+24545,46863,  483,47396,35761,46863,  903,47400,19475,46863, 1011,47404,
+ 1086,46863,  934,46863, 1216,46863,17049,47412,16937,47412, 9766,46863,
+ 5519,46863, 8389,46863, 8861,46863, 3345,47424,12377,47424, 8337,46863,
+  375,47430, 8374,46863, 8365,46863,20169,46863,36921,46863, 8453,46863,
+ 4863,47443,13119,47443, 9072,46863, 9105,46863,  305,46863,12377,47452,
+ 9731,46863,  483,47456, 8997,46863,15503,47460,  265,47460,  265,47461,
+  257,47460,  264,47469,  265,47468,47471,47473,  264,47468,  265,47469,
+47477,47479,  375,47460,15029,46863,12377,47484,  375,46863,27021,47488,
+30091,47488, 9195,47488, 8757,47488, 4213,47488,14653,47488,20103,47488,
+36773,47488, 8337,47488, 8997,47488,  241,47488, 6578,46863,  394,46863,
+  828,46863,  128,46863,  299,46863,  705,46863,  101,46863,28715,46863,
+21315,47526,  165,46863,  903,47530,43215,46863,38057,47534, 1505,46863,
+ 1011,47538,30091,46863,  375,47542,  113,46863,   25,47546,    9,47546,
+  803,46863,  483,47552,  518,46863,  504,46863,  508,46863,  645,46863,
+  623,46863,  659,46863,  510,46863,  241,47568,  506,46863,    9,47572,
+  244,46863,  483,47576,  265,46863, 8997,47580, 5041,47580,17009,47580,
+ 8861,47581,  241,46863,  265,47591, 6515,47590,  375,47590,  510,47590,
+  483,47590,    9,47600,    9,47590,  483,47604, 1011,46863,16990,47608,
+17070,47608,17379,47608,40617,47608,16937,47608,  903,47618, 1505,47608,
+17049,47608,  903,47624,21315,47608,19475,47608,  587,47608,  903,47608,
+16937,47634,17049,47634,  903,46863,16937,47641,16977,47643,17082,47640,
+16972,47640,17175,47640,32805,47640,36349,47640,17049,47640, 1011,47656,
+  165,47640,16937,47640,16943,47663, 1011,47662,38057,47640,35761,47640,
+  483,47640,   11,47640, 1011,47640,17049,47676,16937,47676,10527,47640,
+ 4727,47640, 6515,47640, 6564,46863, 6685,46863,35187,47690,   11,47691,
+ 6515,46863,  241,47696,  903,47696,  587,47697,10761,46863,10592,46863,
+ 4738,46863,13857,46863,  483,47710,10527,46863,  903,47714,    9,47714,
+ 3345,46863,  413,47720, 8861,47720, 1369,47721,  341,47721, 3747,46863,
+ 1369,47731, 3689,46863, 1369,47735,17000,46863,17090,46863, 2691,46863,
+ 2777,46863, 2793,46863, 2831,46863, 6486,46863, 4415,46863,10493,46863,
+13941,46863,10901,46863, 4727,46863,  903,47760,    9,47760, 4819,46863,
+  483,47766, 6703,46863, 6623,46863, 5759,46863, 7823,46863, 7813,46863,
+ 7761,46863, 7705,46863, 7735,46863, 7727,46863,13904,46863,10600,46863,
+ 4742,46863, 4822,46863, 2875,46863, 2865,46863, 2961,46863, 2949,46863,
+ 2919,46863, 3645,46863, 3609,46863, 3467,46863,17102,46863,17104,46863,
+ 1369,47815, 5041,46863,  265,47819,  265,47818, 4919,46863,  483,47824,
+17100,46863,17009,46863,  265,47831,  265,47830,17099,46863,  483,47836,
+ 4920,46863, 6441,46863,  483,47842,17123,46863, 3353,46863, 3691,46863,
+10154,46863, 3777,46863, 2847,46863, 2881,46863, 2933,46863, 2929,46863,
+ 2967,46863, 5271,46863, 4923,46863, 3355,46863, 3031,46863, 3121,46863,
+20819,46863,37537,46863,20952,46863,37748,46863,20885,46863,  483,47884,
+37663,46863,    9,47888,11529,46863, 1010,46862,23717,47895,24522,47895,
+24447,47895,23939,47900,23939,47895,24447,47904,22956,47895,23651,47909,
+21605,47895,   17,47913,23939,47915,   17,47912,23651,47919,   17,47895,
+21605,47923,24447,47925,21605,47922,23651,47929,  264,46862,47135,47933,
+47823,47933,47835,47933,47137,47933,47587,47933,47585,47933,47465,47933,
+47583,47933,47019,47933,47581,47933,17009,47953, 5041,47953, 8997,47953,
+  265,46862,47063,47961,47065,47961,47055,47961, 8997,47961, 5041,47961,
+17009,47961, 8495,47961,  241,47961,  241,46862,  240,46863,  265,47981,
+    1,47982,    0,47982, 5521,47983, 5520,47982,47989,47991, 5520,47983,
+ 5521,47982,47995,47997,    0,47983,47985,48001,    1,47983,47987,48005,
+  264,46863,15193,48009,15475,48009,15579,48009,13119,48008,13143,48017,
+ 4863,48008, 4879,48021,47972,48009,47970,48009,47821,48009,47833,48009,
+13507,48009,47968,48009,47467,48009,   53,48009, 1471,48009, 8997,48009,
+47961,48042,  253,48009,17009,48009,47961,48048, 5041,48009,47961,48052,
+15437,48009, 8997,48057,20501,48009,47961,48009,17009,48062, 5041,48062,
+ 8997,48062,20219,48009,37019,48009,19513,48009,35843,48009,20697,48009,
+37377,48009,13119,48009,13135,48083, 4863,48009, 4871,48087,18967,48009,
+  483,48091, 1369,48009, 9875,48009, 8401,48009, 9955,48009,10273,48009,
+ 4137,48009, 3863,48009, 4063,48009,  241,48009,  413,46863, 3345,48112,
+ 7315,48112,17049,48112,16937,48112,12377,46863, 8861,48122,15029,48122,
+  305,48122,  713,48122,   25,48122,  587,48123,12387,48135,   11,48123,
+  257,48123,  253,48123, 1471,48123,   53,48123, 1369,48123,  257,48122,
+  587,48122,12391,48153,  257,46863, 9136,48156, 9137,48156,  264,48157,
+48159,48163,17827,48156,48163,48167,  413,48156,    1,48170,  264,48156,
+ 8997,48175,  241,48175,    1,48179,  265,48157, 8997,48183,48175,48184,
+ 4425,48183,48161,48183,48176,48183,48175,48183, 8997,48194, 5579,48183,
+17873,48183, 1791,48183,48173,48183,48181,48183,  265,48156, 8997,48208,
+48163,48211,48163,48209, 8997,48215, 8997,48156,  265,48218,48163,48221,
+  265,48219,48175,48225,12377,48156,36925,46863,20177,46863, 8383,46863,
+ 8385,46863,   88,46863,   11,48239,37409,48239,  566,46863,27021,48245,
+ 9195,48245,20501,48245, 9377,48245, 9875,48245,  587,48245,20763,48245,
+  653,46863,   11,48261,  289,46863,  587,48265,36349,46863,  903,48268,
+40617,46863, 1011,48272,   66,46863,   33,48277,20217,46863,37017,46863,
+37845,46863,38057,46863,  903,48286,43215,48286,  155,48286,21315,46863,
+  483,48294, 1011,48294,28715,48294, 1347,48294, 1347,46863,21315,48304,
+  155,46863,38057,48308,21378,46863,38134,46863,20103,46863,  375,48316,
+36773,46863,  375,48320,  713,46863,12377,48324,   25,46863,  113,48328,
+12377,48328,26625,46863,  483,48334,10107,46863,38056,48338,38056,48339,
+38057,48338,48343,48345,38057,48339,48341,48349,    3,48339,    3,48338,
+ 9195,46863,  375,48356,27021,46863,  375,48360,   19,46863,   59,48365,
+32805,46863,    4,48368,34447,48371,  903,48368,    9,48368,    4,48369,
+33871,48379,   11,48368,34447,48383,45639,46863,    2,48386,46599,48389,
+    2,48387,46169,48393,  587,48386,46599,48397,36256,46863,35187,46863,
+ 6685,48402,    9,48402,  483,46863,27255,48408,26625,48408,24545,48408,
+ 9287,48408,21315,48408,  903,48408, 9731,48408,13857,48408,  803,48408,
+  244,48408,17049,48408, 6441,48408, 4819,48408,17099,48408, 4919,48408,
+    9,48408,  241,48440,  241,48408,    9,48444,20885,48408,    5,48408,
+27021,48451, 9195,48451,20501,48451, 9377,48451, 9875,48451,  587,48451,
+20763,48451,    9,46863,32805,48466,10527,48466,  113,48466,  506,48466,
+16937,48466, 4727,48466,  483,48466,  241,48480,  241,48466,  483,48484,
+37663,48466,  265,48467,   11,48491,    3,48466,   11,48495,37409,48495,
+35187,48466,19917,46863,18967,48503,    5,48504,    5,48505,21036,48503,
+21037,48503,    4,48503,48509,48515,    5,48503,18967,48518,    4,48502,
+48521,48523,48507,48523,48511,48523,    5,48502,48513,48531,  587,46863,
+12377,48535,12551,48537,45639,48535,46275,48541,12377,48534,12391,48545,
+36527,48534,45639,48534,46599,48551,  265,48535,17827,48555, 1011,48534,
+   11,46863,32805,48561,34003,48563,20035,48560,32805,48560,34447,48569,
+  903,48560, 1275,48561,    9,48575,    3,48560,   33,48579,    3,48561,
+  113,48583,16937,46863, 1216,48586,  413,48586,21036,48586,21037,48586,
+21036,48587,48595,48597,21037,48587,48593,48601,  903,48587,16941,48605,
+ 1011,48586,  903,48608,  903,48586,16943,48613, 1011,48612,    9,48586,
+17049,46863, 1216,48620,  413,48620,  903,48620, 1011,48626, 1011,48620,
+  903,48630,  483,48620,    2,48620,    3,48620, 1369,48639,    2,48621,
+    3,48621,  483,48645,    2,46862,    6,48649,    4,48651,    5,48649,
+    9,48655,21604,48657,21604,48656,21605,48657,48661,48663,21605,48656,
+48659,48667,    5,48648,23717,48671,24522,48671,24447,48671,23939,48676,
+23939,48671,24447,48680,22956,48671,23651,48685,   17,48671,21605,48689,
+24447,48691,21605,48688,23651,48695,21605,48671,   17,48699,23939,48701,
+   17,48698,23651,48705,   19,48649,   12,48649,    9,48649,   11,48712,
+   11,48649,    9,48716,21605,48649,48652,48720,48653,48721,48723,48725,
+48653,48720,48652,48721,48729,48731,    3,46862,    5,48735,    4,46862,
+19975,48739,19365,48739,19221,48739,19917,48739,10107,48747,  587,48739,
+    5,46862,25451,48753,42283,48753,19739,48753,    0,48753,    3,48761,
+25380,48753, 7971,48765,42155,48765,  164,48753,48353,48771,20763,48753,
+ 1011,48775, 1010,48774,48777,48779, 1010,48775, 1011,48774,48783,48785,
+    2,48753,   17,48788,48353,48791,    2,48752,23717,48795,24522,48795,
+23939,48795,24447,48800,24447,48795,23939,48804,22956,48795,23651,48809,
+21605,48795,   17,48813,23939,48815,   17,48812,23651,48819,   17,48795,
+21605,48823,24447,48825,21605,48822,23651,48829, 1369,48753,21605,48832,
+ 7971,48835,42155,48835,21605,48753, 1369,48840,42155,48843, 7971,48843,
+   17,48753,37844,48848,48762,48848,48763,48849,48853,48855,37844,48849,
+48763,48848,48762,48849,48861,48863,37845,48848,48859,48867,37845,48849,
+48851,48871,    2,48849,48355,48875,47853,48875,    2,48848,48353,48881,
+    5,46863,  374,48884,  374,48885,  375,48884,48889,48891,19381,48885,
+19380,48884,48895,48897,19381,48884,19380,48885,48901,48903,20812,48884,
+20813,48884,20812,48885,48909,48911, 1197,48885,21604,48915,21604,48914,
+21605,48915,48919,48921,21605,48914,48917,48925,  375,48885,48887,48929,
+20813,48885,48907,48933,20501,48885, 1011,48937,27021,48885,  483,48941,
+ 9195,48885,  483,48945, 9377,48885,  483,48949, 9875,48885, 1011,48953,
+  587,48885,  483,48957, 1369,48885, 1011,48961,38057,48961,20763,48885,
+  483,48967,  903,48885,  375,48971,  483,48884,27021,48975, 9195,48975,
+20501,48975, 9377,48975, 9875,48975,  587,48975,20763,48975,18967,48885,
+  483,48991,  165,48991,    2,48884,48961,48997,    3,48884,13118,49000,
+ 4862,49000,13118,49001,13119,49000,49007,49009, 4863,49000, 4862,49001,
+49013,49015,15193,49001,15475,49001,15579,49001,13507,49001,20501,49001,
+  253,49001,15437,49001, 8997,49031,20219,49001,37019,49001,19513,49001,
+35843,49001,20697,49001,37377,49001,13119,49001,49003,49047, 4863,49001,
+49005,49051,  241,49001, 9875,49001,   53,49001, 1471,49001, 8401,49001,
+ 9955,49001,10273,49001, 4137,49001, 3863,49001, 4063,49001, 1369,49001,
+18967,49001,  483,49077,    2,48885,    1,49081,    7,49082,49000,49084,
+49001,49085,49087,49089,49000,49085,49001,49084,49093,49095,    7,49081,
+    1,49098,49000,49100,49001,49101,49103,49105,49000,49101,49001,49100,
+49109,49111,    1,49080,    7,49115,    7,49080,49001,49119,    0,49080,
+49083,49123,    7,49125,49001,49127,    0,49081,49116,49131,49001,49133,
+    7,49131,49115,49136,49001,49139,49001,49137,49115,49143,49115,49131,
+    7,49146,49001,49149,49001,49081,    3,48885,37357,49155,  165,49155,
+10257,49155,  483,49155,35187,48885,  375,49165,    9,48885,    1,49168,
+    3,49171,46863,49172,46863,49171,    3,49176,    3,49177,37845,49169,
+37845,49168,37844,49168,49183,49187,37844,49169,49185,49191,    2,49168,
+49175,49195,49179,49195,    2,49169,49181,49201,    3,46863,49171,49204,
+49195,49207,    6,49205,   11,49211,    0,49205,    0,49204,40704,49217,
+38305,49217,    9,49220,    9,49217,38305,49224,    6,49204,40705,49229,
+49217,49231,49219,49229,18967,49229,    4,49236,    5,49236,    5,49237,
+    4,49237,46863,49244,49241,49247,46863,49237,    4,49250,49241,49253,
+    4,49251,49243,49257,49227,49229,   17,49229,49223,49229,37325,49205,
+  903,49267,10107,49204,48875,49271,10219,49205,  903,49275,17049,49204,
+ 1369,49279,   11,49205,   25,49283,    9,49283,   17,49205,  903,49289,
+21315,49289,37409,49205,    9,49295, 1011,49205,  375,49299,    9,49204,
+   11,49303,37409,49303,   11,49204,   33,49309,35187,49205, 1505,49313,
+    4,49204,49289,49317,    5,49204,13118,49320, 4862,49320,13118,49321,
+13119,49320,49327,49329, 4863,49320, 4862,49321,49333,49335,15193,49321,
+15475,49321,15579,49321,13507,49321,20501,49321,  253,49321,15437,49321,
+ 8997,49351,37019,49321,20219,49321,35843,49321,19513,49321,37377,49321,
+20697,49321,13119,49321,49323,49367, 4863,49321,49325,49371,  241,49321,
+ 9875,49321, 1471,49321,   53,49321, 8401,49321,10273,49321, 9955,49321,
+ 4137,49321, 4063,49321, 3863,49321, 1369,49321,18967,49321,  483,49397,
+    4,49205,    1,49401,    7,49402,49320,49404,49321,49405,49407,49409,
+49320,49405,49321,49404,49413,49415,    7,49401,    1,49418,49320,49420,
+49321,49421,49423,49425,49320,49421,49321,49420,49429,49431,    1,49400,
+    7,49435,    7,49400,49321,49439,    0,49400,49403,49443,    7,49445,
+49321,49447,    0,49401,49436,49451,49321,49453,    7,49451,49435,49456,
+49321,49459,49321,49457,49435,49463,49435,49451,    7,49466,49321,49469,
+49321,49401,    5,49205,20645,49475, 1505,49475, 9935,49475,18967,49205,
+    7,49483,    4,49484,    4,49485,   16,49483,   17,49483,    4,49482,
+49493,49495,    5,49482,49487,49499,49491,49499,    4,49483,    7,49504,
+49499,49507,    5,49483,49489,49511,    2,46863,    6,49515,   17,49517,
+35187,49519,    0,49515,38305,49523,   15,49525,    0,49514,36545,49529,
+49521,49529,   15,49529,    6,49514,49531,49537,36544,49537,49529,49541,
+49527,49537,   11,49537,35187,49546,49529,49549,35187,49537,   11,49552,
+49529,49555,45639,49514,46599,49559,45639,49515,46275,49563,17125,49515,
+   16,49567,   16,49566,   17,49567,49571,49573,   17,49566,49569,49577,
+17049,49514,    4,49514,    7,49583,    1,49585,  265,49583,    1,49588,
+    0,49588,49587,49589,49586,49588,49595,49597,49587,49588,49586,49589,
+49601,49603,    0,49589,49591,49607,    1,49589,49593,49611,    4,49515,
+ 1011,49615,    1,49617,    0,49617,    1,49616,49621,49623,    0,49616,
+49619,49627,    4,46863,27857,49630,27895,49633,19815,49630,19857,49637,
+49237,49631,49239,49641,49237,49630,49241,49645,32805,49630,34447,49649,
+32805,49631,34003,49653,27857,49631,27879,49657,19815,49631,19849,49661,
+    2,49630,    7,49665,    1,49667,  265,49665,    1,49670,    0,49670,
+49669,49671,49668,49670,49677,49679,49669,49670,49668,49671,49683,49685,
+    0,49671,49673,49689,    1,49671,49675,49693,    2,49631,  903,49697,
+    1,49699,    0,49699,    1,49698,49703,49705,    0,49698,49701,49709,
+    1,    7,  377,49713,48110,49712,48111,49712,49152,49712,49472,49712,
+49153,49712,49473,49712,49374,49712,49054,49712,49375,49712,49055,49712,
+  704,49712,  100,49712,26502,49712,41376,49712, 8808,49712,47622,49713,
+47660,49713,47146,49713,47148,49713,49059,49713,49379,49713,49158,49713,
+49478,49713,49061,49713,49381,49713,48998,49713,49318,49713,47224,49713,
+47226,49713,48041,49713,48039,49713,47058,49713,47060,49713,47220,49713,
+47222,49713,48047,49713,47056,49713,47442,49713,49349,49713,49029,49713,
+49121,49713,49441,49713,47628,49713,47668,49713,48962,49713,49290,49713,
+22798,49713,39074,49713,31498,49713,44616,49713,31392,49713,44494,49713,
+47540,49713,47532,49713,31794,49713,44858,49713,48298,49713,48288,49713,
+31924,49713,44994,49713, 8652,49713, 8535,49713,13252,49713,43989,49712,
+41417,49843,30655,49712,26219,49847,26503,49712,41377,49712, 8809,49712,
+26547,49712,26219,49857,41835,49712,41417,49861,  273,49712,12897,49865,
+ 8813,49712, 8647,49869,  376,49713,  705,49712,  101,49712,  803,49712,
+  483,49879,30091,49712,26219,49883,  113,49712,    9,49887,43503,49712,
+41417,49891,43215,49712,  483,49895,43214,49712,  112,49712,  802,49712,
+49320,49712,49401,49905,  241,49905,49000,49712,49081,49911,  241,49911,
+49081,49712,49001,49916,49001,49917,49911,49921,49401,49712,49321,49924,
+49321,49925,49905,49929,49001,49712,49081,49932,  241,49932,49321,49712,
+49401,49938,  241,49938,  414,49713,18391,49945,  420,49713,18391,49949,
+  449,49713,18391,49953, 8808,49713,49855,49957, 8453,49713,46863,49960,
+20239,49713,46863,49964,37095,49713,46863,49968,47976,49713,47593,49713,
+26502,49713,49851,49977,31921,49713,47592,49713, 8495,49983,  828,49713,
+49903,49987,  128,49713,49901,49991,  705,49713,49737,49995,  101,49713,
+49739,49999,47977,49713, 8495,50003,47488,49713,48122,49713,48480,49713,
+48440,49713,47568,49713, 1344,49713, 1482,49713,   64,49713, 1484,49713,
+  336,49713, 1480,49713,  254,49713, 1342,49713,  338,49713, 1123,49713,
+  931,49713,  665,49713, 1417,49713, 1429,49713, 1301,49713, 1127,49713,
+  941,49713,  523,49713, 1283,49713,  939,49713, 1103,49713,  171,49713,
+ 1525,49713,  407,49713, 1517,49713,  949,49713,  280,49713, 1476,49713,
+  272,49713, 1017,49713, 1077,49713, 1047,49713, 1113,49713, 1245,49713,
+ 1237,49713,  501,49713,  433,49713,  929,49713,  591,49713,  915,49713,
+  681,49713, 1555,49713,  911,49713, 1545,49713,  855,49713,41376,49713,
+49853,50107, 4900,49713,14622,49713,48113,49713, 8997,50115, 1382,49713,
+  695,49713,48286,49713,  903,50122,48294,49713, 1011,50126,26503,49713,
+49741,50131,47530,49713,  903,50134,47538,49713, 1011,50138,49289,49713,
+49317,50142,  903,50142,48961,49713,48997,50148, 1011,50148,21522,49713,
+46863,50154,38266,49713,46863,50158,  394,49713,  299,49713,31792,49713,
+  903,50166,44856,49713, 1011,50170,22789,49713,  903,50174,39065,49713,
+ 1011,50178, 1386,49713,  545,49713,41377,49713,49743,50187,  413,49712,
+ 8647,50191,18062,50191,17993,50191,  251,50196,  251,50191,17993,50200,
+46863,50191,  412,49712,48008,49713,50207,50209,49717,50209,  341,50209,
+40381,49713,   17,50217,  913,49713,  483,50221,  289,49713, 8809,49713,
+49745,50227,49000,49713,49935,50231,49919,50231,49721,50231,49731,50231,
+49937,50231,49933,50231,49081,50243,  241,50243,49320,49713,49941,50249,
+49927,50249,49723,50249,49729,50249,49943,50249,49939,50249,49401,50261,
+  241,50261, 1374,49713, 8672,49713,12534,49713,12921,49713,  264,50273,
+  265,50272,50275,50277,  264,50272,  265,50273,50281,50283, 8605,49713,
+26097,49713,41299,49713,26277,49713,41479,49713,26104,49713,41314,49713,
+ 1477,49713,46863,50300,  281,49713,46863,50304, 1516,49713,46863,50308,
+  948,49713,46863,50312,44988,49713,  903,50316,31920,49713, 1011,50320,
+43293,49713,49895,50325,15156,49713,  264,50329,  265,50328,50331,50333,
+  264,50328,  265,50329,50337,50339, 8916,49713,14623,49713, 8495,50345,
+ 4901,49713, 8495,50349,14611,49713,  241,50352, 4899,49713,  241,50356,
+15219,49713,  412,50360,  413,50361,50363,50365,  412,50361,  413,50360,
+50369,50371, 5119,49713,  412,50374,  413,50375,50377,50379,  412,50375,
+  413,50374,50383,50385,13177,49713,  413,50388,  264,50388,  264,50389,
+  265,50388,50395,50397,  265,50389,50393,50401, 5313,49713,12377,50404,
+47591,49713,  265,50409, 8861,50411,  265,50408, 8495,50415,47641,49713,
+43292,49713,49899,50421,15158,49713,39228,49713,23012,49713,40676,49713,
+25546,49713,  500,49713,18391,50435,  432,49713,18391,50439, 1244,49713,
+18617,50443, 1236,49713,18617,50447, 1109,49713,  903,50451, 1412,49713,
+  305,50455,44832,49713,31770,49713,25545,49713,    9,50462,40675,49713,
+  483,50466,  935,49713,  483,50471, 1087,49713,    9,50475, 1413,49713,
+  295,49713, 1290,49713,  903,50483, 1304,49713,    9,50487,48009,49713,
+50191,50491,49719,50491,  241,50491,22957,49713,  903,50498,39205,49713,
+ 1011,50502,47608,49713, 1505,50506,21315,50506,47640,49713,  165,50512,
+38057,50512,  510,49713,46863,50518,  922,49713, 1108,49713, 1280,49713,
+    9,50527,  246,49713,  483,50531,  412,49713,47460,50535,  483,50535,
+    9,50535, 8997,50535,46863,50542,46863,50535, 8997,50546, 1216,49713,
+44243,50550,31103,50550,  483,50550,18617,50557,    9,50550,18617,50561,
+ 8677,49713,  305,49713,  241,50567,16163,50567, 8647,50566, 8495,49713,
+  257,50574, 1141,49713,16531,50579,  253,49713,   59,50582, 1325,50582,
+  331,50582,  265,50582, 8634,49713, 8611,49713,41349,49713,26127,49713,
+  273,49713,12705,50601,13673,50601,18391,50601, 2923,50601,46863,50600,
+  331,49713,   53,50612, 1471,50612,  253,50612, 1369,50612, 8861,49713,
+  241,50623,  375,50625,  375,50622,  251,49713,  413,50631,17993,50633,
+  413,50630,18391,50637,15029,50630,  264,50641,  265,50640,50643,50645,
+  264,50640,  265,50641,50649,50651,39204,49713,  257,49713,  265,50657,
+26625,50657,25793,50657,41019,50657, 8495,50657, 9731,50657,25793,50656,
+41019,50656, 8495,50656,  265,50656, 4863,50677,12377,49713,46863,50680,
+ 5313,50680,  341,49713,  241,50687,  298,49713, 4863,50691,  704,49713,
+49875,50695, 9195,50695,  100,49713,49877,50701,  395,49713,  829,49713,
+49879,50707, 9195,50707,  129,49713,49887,50713,   89,49713,48884,50716,
+48884,50717,48885,50717,50719,50723,48885,50716,50721,50727,   11,50716,
+  567,49713,42155,50733,41941,50733, 7971,50733, 9565,50733,  587,50733,
+ 9377,50743,  587,50732, 9195,50747,38057,49713,47640,50750,46863,50750,
+  903,50754,  903,50750,46863,50758,21315,49713,47608,50762,46863,50762,
+ 1011,50766, 1011,50762,46863,50770,  628,49713, 1396,49713,  241,50777,
+  288,49713, 7971,50781,  265,49713,23584,50785,39564,50785,24355,50785,
+39905,50785, 5520,50785,  256,50784,50795,50797, 5521,50785,  256,50785,
+50204,50785,   10,50784,    1,50785,  257,50808,50797,50811,  257,50809,
+50803,50815,   10,50785,50191,50785,46863,50820,47590,50784,23493,50785,
+22807,50826,39489,50785,39085,50830,22807,50785,23493,50834,39085,50785,
+39489,50838, 1087,50785,  935,50785,47591,50784, 8495,50847,47590,50785,
+50847,50851, 4213,50785, 8757,50785,26415,50785,41653,50785,27377,50785,
+ 9335,50785,42471,50785, 8109,50785, 4147,50785, 3933,50785,   53,50784,
+ 1471,50784,  253,50784,47591,50785,50825,50881,  257,50785,    1,50884,
+50797,50887,50797,50885, 4827,50885,  305,50785, 8861,50895, 8495,50785,
+  331,50899,46863,50785,50191,50902,  241,50902,  241,50785,46863,50908,
+ 8337,50909,46863,50913, 1369,50784,  305,50917,   11,50785,50807,50921,
+ 8165,50921, 1369,50921,  241,50784,47460,50929,  483,50929,    9,50929,
+ 8997,50929,46863,50936,46863,50929, 8997,50940,  257,50784,50801,50945,
+50803,50945, 4863,50945,   11,50784,50819,50953, 7971,50953, 1011,49713,
+31920,50958,48294,50958,44856,50958,47538,50958,48961,50958,39065,50958,
+21315,50958,46863,50972,31103,50958,  903,50976, 1505,50958,46863,50980,
+44243,50958,  903,50984,39205,50958,    9,50958,  903,50958,31103,50992,
+44243,50992,46863,50958,21315,50998, 1505,50998,  903,49713,44988,51004,
+48286,51004,31792,51004,47530,51004,49289,51004,22789,51004,38057,51004,
+46863,51018,44243,51004, 1011,51022,  165,51004,46863,51026,31103,51004,
+ 1011,51030,22957,51004,  483,51004, 1011,51004,44243,51038,31103,51038,
+46863,51004,38057,51044,  165,51044,  241,49713,47961,51050, 4899,51050,
+14611,51050,  375,51050,12377,51051,  375,51061, 8997,51051,  375,51065,
+  265,51065,46863,51069, 1275,51050,    9,51073,   15,51050,  483,51077,
+  265,51050,47460,51081,  483,51081,    9,51081, 8997,51081,46863,51088,
+46863,51081, 8997,51092, 8647,49713,  413,51096,  305,51097,   11,51097,
+ 1369,51097,  341,51097,  305,51096,41417,49713,   11,51111, 1369,51111,
+26219,49713,   11,51117, 1369,51117,32102,49713,27021,51123,45148,49713,
+   11,51127, 1369,51127,31857,49713,44925,49713,32294,49713,45314,49713,
+17565,49713,32103,49713,  241,51143,  587,51142,45149,49713,   11,51148,
+49317,49713,49289,51152,48997,49713,48961,51156,49001,49713,49912,51161,
+49725,51161,49914,51161,49735,51161,49081,51161,49911,51170,49911,51161,
+49081,51174,  241,51174,  241,51161,49911,51180,49321,49713,49906,51185,
+49727,51185,49908,51185,49733,51185,49401,51185,49905,51194,49905,51185,
+49401,51198,  241,51198,  241,51185,49905,51204,49475,49713, 1505,51208,
+49155,49713,  165,51212,  240,49712,51059,51217,50163,51217,50165,51217,
+51051,51217,  375,51225,  264,49712,49715,51229,50838,51229,50834,51229,
+50850,51229,50847,51229,50945,51229,49983,51229,50415,51229,50677,51229,
+50691,51229,50496,51229,50003,51229,50906,51229,50910,51229,50345,51229,
+50349,51229, 8374,51229, 8389,51229,50705,51229,20152,51229,36898,51229,
+20201,51229,36979,51229,50902,51229,  241,51276,50908,51229,46863,51280,
+50491,51229,  241,51284,47590,51229,50785,51288,22807,51229,50785,51292,
+39085,51229,50785,51296,26219,51229,41417,51229,14524,51229,35690,51229,
+50733,51229,37519,51229,50781,51229,50953,51229,50455,51229,50917,51229,
+19396,51229, 8647,51229,20103,51229,  375,51324,36773,51229,  375,51328,
+ 8337,51229,  375,51332,50785,51229,39085,51336,22807,51336,47590,51336,
+46863,51336,  241,51344,  241,51336,46863,51348,47488,51229,47961,51229,
+    9,51229,18967,51356,  483,51229,35187,51229,  375,51362,18967,51229,
+    9,51366,46863,51229,50908,51370,50785,51370,  241,51374,  241,51370,
+50785,51378,  375,51370,  241,51229,50491,51384,50902,51384,50785,51384,
+46863,51390,46863,51384,50785,51394,  375,51229, 8337,51398,20103,51398,
+36773,51398,14315,51398,35187,51398,46863,51398,14315,51229,  375,51412,
+ 4899,51229,14611,51229, 1010,49712, 3867,51421, 8277,51421, 4067,51421,
+ 3997,51421, 8953,51421, 9459,51421,  902,49712,50321,51435,51031,51435,
+24265,51435,28233,51435,29077,51435,51005,51435,31103,51447,19559,51435,
+ 4283,51435, 9673,51435, 4279,51435, 3807,51435,20361,51435,20713,51435,
+ 9967,51435, 8251,51435,47961,49713,  241,51468,47979,49713,  412,51472,
+  413,51473,51475,51477,  412,51473,  413,51472,51481,51483,  240,49713,
+  340,51487,51398,51487,51418,51487,51416,51487,51354,51487,47974,51487,
+47589,51487, 8590,51487,12537,51487,14620,51487,  375,51487,51229,51508,
+    7,51487,  265,51512,  265,51513,51229,51517,47580,51487, 8861,51521,
+47961,51487,51229,51524, 8495,51524,51229,51487,  375,51530,14611,51530,
+ 4899,51530,47961,51530, 8495,51487, 4899,51540,47961,51540,14611,51540,
+14611,51487,51229,51548, 8495,51548, 4899,51487,51229,51554, 8495,51554,
+46863,51487,  265,51560, 8861,51563,  265,51561, 8495,51567,51229,51567,
+  265,51487,    7,51572,15309,51573,15308,51572,51577,51579,15308,51573,
+15309,51572,51583,51585,46863,51572, 8861,51589,  902,49713,31103,51593,
+43053,51593,46863,51593, 1010,49713, 1505,51601,  918,51601,    9,51601,
+  903,51606,  903,51601,    9,51610,  265,49712,49873,51615,50165,51615,
+51059,51615,51057,51615,51055,51615,51053,51615,49975,51615,49973,51615,
+50113,51615,50111,51615,50163,51615,51471,51615,50355,51615,50359,51615,
+50209,51615,  241,51645, 8948,51615,50225,51615,50479,51615,  331,51615,
+ 8861,51654, 8861,51615,  331,51658, 4827,51615,15269,51615,51051,51615,
+  375,51667,14611,51667, 4899,51667,47961,51667,  241,51614,50209,51677,
+  241,49712,18300,51681, 8605,51681, 8916,51681,50945,51681,49321,51680,
+50249,51691,49001,51680,50231,51695,50705,51681, 8374,51681,51508,51681,
+50691,51681,47443,51681, 8389,51681,50677,51681,51517,51681, 8861,51681,
+  375,51714,26219,51681,41417,51681,  305,51681,48009,51681,51229,51725,
+ 8647,51681, 8452,51681,46863,51731,  713,51681,   25,51681,18257,51681,
+  375,51738, 8337,51681,  375,51742,  265,51742,46863,51747,  375,51681,
+18257,51750, 8861,51750, 8337,51750,51487,51750,51487,51681,  375,51760,
+  265,51680,50209,51765,49321,51681,49905,51769,49001,51681,49911,51773,
+  265,51681,51370,51777,51229,51777,46863,51780,46863,51777,51229,51784,
+ 8337,51776,46863,51789,46863,51681,  264,51792,51765,51795,  264,51793,
+51777,51799,  264,49713,51489,51803,51515,51803,51575,51803,51521,51803,
+50411,51803,50659,51803,51563,51803, 8471,51803, 8397,51803, 8371,51803,
+20149,51803,36887,51803,20211,51803,37009,51803,20247,51803,37103,51803,
+51589,51803,50207,51803,46863,51839,51765,51803,46863,51843,51677,51803,
+46863,51847,36773,51803,46863,51851,20103,51803,46863,51855, 8337,51803,
+46863,51859, 4613,51803,12571,51803,36539,51803,37595,51803,36049,51803,
+47581,51803,51487,51873,51615,51803,39085,51877,22807,51877,47590,51877,
+46863,51877,  241,51884,  241,51877,46863,51888,46863,51802,51765,51893,
+51677,51893,50207,51893,51615,51893,  241,51901,  341,51893, 1369,51803,
+  341,51803,51487,51909, 8337,51909,20103,51909,36773,51909,35187,51909,
+14315,51909,46863,51909,12377,51803,  375,51925, 1011,49712,26219,51929,
+41417,51929, 8647,51929,  903,49712,49981,51937,51594,51937,  375,51937,
+31103,51937,51593,51944,51593,51937,31103,51948,15269,51937, 4827,51937,
+ 1217,49713,  483,51957,    9,51957,  413,49713, 8647,51962,13177,51962,
+  251,51962,18391,51969,  375,51962,18391,51973,44243,51962,31103,51962,
+18391,51963,  251,51981,  483,51962,18391,51985,    9,51962,18391,51989,
+  375,49713,    5,51992,51615,51995,  413,51993,17993,51999,  413,51992,
+18391,52003,  241,51993,51487,52007,46863,51992,  241,51992,51217,52013,
+51615,52013, 8861,51992,12377,51993,51487,52021,15029,51992,14315,49713,
+  341,52027,51487,52029,15029,49713,  266,52032,  267,52032,  264,52033,
+52035,52039,  465,52032,52039,52043,  413,52032,    6,52046,  264,52032,
+  251,52051,  241,52051,    6,52055,  265,52033,  251,52059,52051,52060,
+ 8841,52059,52037,52059,52052,52059,52051,52059,  251,52070,15363,52059,
+15055,52059,15061,52059,52049,52059,52057,52059,  265,52032,  251,52084,
+52039,52087,52039,52085,  251,52091,  251,52032,  265,52094,52039,52097,
+  265,52095,52051,52101,  375,52032, 8639,49713, 8643,49713,26217,49713,
+41415,49713,  164,49713,51593,52115,  903,52115, 1504,49713,51601,52121,
+  144,49713,  113,52125,  802,49713,49880,52129,49879,52129,  483,52132,
+ 9366,52129, 9195,52129,  483,52138,  483,52129,49879,52142, 9195,52142,
+31103,52129,  112,49713,49888,52151,49887,52151,    9,52154,    9,52151,
+49887,52158,44243,52151, 1486,49713,  803,52165,43214,49713,49896,52169,
+49895,52169,  483,52172,  483,52169,49895,52176, 1073,49713,  903,52181,
+  525,49713,  903,52185,  669,49713,  483,52189,  566,49713,51929,52193,
+51615,52193,10107,52193,21036,49713,   17,52201,   88,49713,37611,52205,
+36083,52205,38155,52205,35927,52205, 1346,49713, 1505,52215,  154,49713,
+  483,52219,26329,49713,41557,49713,  165,49713,49155,52226,47640,52226,
+46863,52226,  903,52232,  903,52226,46863,52236,43215,52226, 1505,49713,
+49475,52242,47608,52242,46863,52242, 1011,52248, 1011,52242,46863,52252,
+28715,52242,  803,49713,49903,52259,  483,52261,  483,52258,49903,52265,
+  113,49713,49901,52269,    9,52271,    9,52268,49901,52275,28715,49713,
+ 1505,52278,43215,49713,49899,52283,  483,52285,  483,52282,49899,52289,
+  165,52282,29028,49713,43318,49713,25793,49713,  257,52298,  713,49713,
+  241,52303,16163,52303,41019,49713,  257,52308,   25,49713,  241,52313,
+16163,52313, 1447,49713,16531,52319,   33,49713,16531,52323, 1471,49713,
+   59,52326, 1325,52326,  331,52326,  265,52326,   53,49713, 1325,52336,
+   59,52336,  331,52336,  265,52336, 1325,49713,   53,52346, 1471,52346,
+  253,52346, 1369,52346,   59,49713, 1471,52356,   53,52356,  253,52356,
+ 1369,52356,48466,49713,  483,52366,48408,49713,    9,52370,  843,49713,
+    9,52375, 1530,49713,    9,52379,40436,49713,  113,52383,  587,49713,
+28714,52387,36212,52387,30091,52387,  567,52386, 9195,52395,   11,52386,
+32103,52386,35187,52387,  241,52402,  241,52387,35187,52406,    4,52386,
+ 9366,52411, 9195,52411,  483,52414,  483,52411, 9195,52418,31103,52411,
+    5,52387,21605,52424, 9195,52425,27021,52425,21605,52387,   11,52433,
+    5,52432,   11,49713,32805,52439,19888,52439,19913,52439,  265,52439,
+51803,52447,43503,52439, 1275,52438,    9,52453,   89,52438,  587,52438,
+  265,52438,51229,52461, 7971,52461,45149,52438,18967,52439,  241,52468,
+  241,52439,18967,52472,    2,52438,    9,52477,44243,52477,    3,52439,
+ 7971,52483,42155,52483,    2,52439,52205,52489,38305,52439,  265,52493,
+38305,52438,  113,52497, 1369,49713,  331,52500,   59,52500,40674,52501,
+38305,52501,  265,52509,  241,52508,  241,52501,38305,52514, 1325,52500,
+  265,52500,51229,52521,  305,52521,   17,52500,  241,52527,38305,52500,
+35187,52501,  265,52501,  331,52535,51803,52535,    4,52500,51601,52541,
+    5,52500,  803,52545,    5,52501,  959,52549,   47,52549,  759,52549,
+    4,52501, 1275,52500,    9,52559,   17,49713, 1275,52562,  903,52565,
+ 1369,52562,  241,52569,    2,52562,  903,52573,51593,52573,    3,52562,
+  113,52579,    3,52563, 1141,52583, 1447,52583,   33,52583,    2,52563,
+  265,52591,51803,52591,38305,49713, 1369,52596,    3,52596,    3,52597,
+ 8165,52603,20501,52603, 9875,52603,   11,52603,   11,52596,  113,52613,
+   15,49713, 1010,52617, 1010,52616, 1011,52616,52619,52623, 1011,52617,
+52621,52627,  241,52616,  483,52631,    3,52616,  483,52635,    3,52617,
+ 1369,52639, 1275,49713,   17,52642,  903,52645,   11,52642,    9,52649,
+  241,52642,    9,52653,    9,52643, 1369,52657,   11,52657,    5,52642,
+ 1505,52663,    5,52643,   53,52667, 1471,52667,  253,52667, 1369,52642,
+    9,52675,18967,49713,  241,52679,    9,52681,    5,52678,   17,52685,
+    5,52679,    9,52689,  483,49713,  803,52693,52129,52695,43215,52693,
+52169,52699, 1216,52693,18759,52703,  413,52693,17993,52707,  803,52692,
+49903,52711,48466,52692,43215,52692,49899,52717,40675,52692, 1216,52692,
+18617,52723,  413,52692,18391,52727,44243,52692,38305,52693,46169,52733,
+    9,52692,46863,52736,  903,52692,    5,52692,10107,52743,51929,52743,
+51615,52743,    5,52693,46863,52692,    9,52752,    9,49713,  113,52757,
+52151,52759,    4,52756,    7,52763,    2,52765,    2,52764,    2,52763,
+    7,52770, 1368,52763, 1216,52757,18759,52777,  413,52757,17993,52781,
+  113,52756,49901,52785,48408,52756,25545,52756, 1216,52756,18617,52793,
+  413,52756,18391,52797,31103,52756,  483,52756,46863,52802, 1011,52756,
+    3,52756,52769,52809,52773,52809,37611,52809,38155,52809,35927,52809,
+52489,52809,52775,52809,    3,52757,52767,52825,52151,52825,37663,52825,
+52477,52825,31103,52825,46863,52756,  483,52836,31103,49713, 1216,52840,
+  413,52840,21036,52840,21037,52840,21037,52841,52847,52851,  903,52841,
+51593,52855, 1011,52840,  903,52858,21036,52841,52849,52863,  903,52840,
+51435,52867, 1011,52866,    9,52840,    5,52840,27021,52875,44243,49713,
+ 1216,52878,  413,52878,  903,52878, 1011,52884, 1011,52878,  903,52888,
+  483,52878,    3,52878,   11,52895, 1369,52895,    3,52879,  483,52901,
+49205,49713,    5,52905,48885,49713,  113,52909,    3,52909,    3,49712,
+20819,52915,50945,52915,51508,52915,37537,52915,36898,52915,20152,52915,
+ 8374,52915,50695,52915,50701,52915,50707,52915,50713,52915,50691,52915,
+50705,52915,37748,52915,20952,52915,52395,52915,52457,52915,52142,52915,
+52158,52915, 8389,52915,50677,52915,51517,52915,50747,52915,50731,52915,
+52418,52915,52478,52915,36979,52915,20201,52915,26219,52915,26106,52915,
+52129,52915,  483,52976,52411,52915,  483,52980,51123,52915,32103,52915,
+52875,52915,31770,52915,42885,52915,20885,52915,  483,52994,40399,52915,
+44714,52915,  357,52915,  367,52915,  471,52915, 1249,52915, 8800,52915,
+ 8647,52915,47488,52915, 8086,52915,19687,52915,19559,52915,20361,52915,
+ 9673,52915,20713,52915, 9967,52915, 4283,52915, 4279,52915, 3807,52915,
+ 8251,52915,41746,52915,41417,52915,44832,52915, 9704,52915,20326,52915,
+21087,52915,52906,52915,48245,52915,48975,52915,48451,52915,52151,52915,
+    9,53058,52477,52915,    9,53062,51487,52915,  375,53066,50785,52915,
+ 8165,52915,  265,53073, 1447,52915,38305,53077,21127,52915,20843,52915,
+52425,52915,37663,52915,    9,53086, 1141,52915,38305,53091,  566,52915,
+  567,52915,46863,53097,44243,52915,41941,53100,  483,53100,  375,52915,
+51487,53106,20103,53106, 8337,53106,36773,53106,46863,53106,41941,52915,
+44243,53118,   33,52915,38305,53123, 9617,52915,    9,53126, 8337,52915,
+  375,53130,48884,52915, 1011,52915,48885,52915,  483,53139,52907,52915,
+   25,52915, 7971,53144,41019,52915,   11,53148,  305,52915, 8495,52915,
+   11,53154,20103,52915,  375,53158,20273,52915,    9,53162,    4,52915,
+28411,53167,31103,53167,48408,53167,52905,53167,  483,53167,46863,53176,
+20691,53167, 9923,53167,46863,53167,  483,53184,    5,52915,52905,53188,
+   17,53189,18967,53193,46863,53188,  483,53188,25793,52915,   11,53200,
+  713,52915, 7971,52915,   25,53206,36773,52915,  375,53210,    4,52914,
+53191,53215,53051,53215,24265,53215,28233,53215,29077,53215,53135,53215,
+53197,53215,53189,53215,52905,53231,46863,53231,19559,53215, 9673,53215,
+ 4283,53215,20361,53215, 9967,53215,20713,53215, 8251,53215, 4279,53215,
+ 3807,53215,    5,52914,53143,53255,53174,53255,50785,53255,53139,53255,
+53184,53255,50733,53255,19396,53255,53167,53255,52905,53270,46863,53270,
+ 8647,53255,41417,53255,26219,53255,    9,53255,18967,53282,  483,53255,
+18967,53255,    9,53288,52905,53255,53167,53292,46863,53255,53167,53296,
+   11,52915,25793,53301,25793,53300, 8495,53301, 8495,53300,18967,53301,
+41019,53301,41019,53300,21037,53301,    9,52915,52151,53318,37663,53318,
+52477,53318,31103,53318,20273,53318, 9617,53318,52905,52915,    5,53332,
+53215,53335,    5,53333,53167,53339, 9875,52915,35187,53343,  241,53343,
+46863,52915,  375,53348,    5,53348,53215,53353,    5,53349,53167,53357,
+  483,52915,52129,53360,20885,53360,52411,53360,44243,53360,    5,53361,
+    5,53360,18967,52915,11731,53375,  113,53375,31103,52915,    9,53380,
+20501,52915,35187,53385,  241,53385,    2,49712,52711,53391,52785,53391,
+51059,53391,50165,53391,49995,53391,49999,53391,49987,53391,49991,53391,
+50163,53391,52013,53391,52265,53391,52275,53391,17609,53391, 4904,53391,
+17586,53391,52259,53391,  483,53423,  272,53391, 1476,53391,  280,53391,
+  949,53391, 1517,53391,52269,53391,    9,53437, 9484,53391,51803,53391,
+51051,53391,  375,53445, 4903,53391,    9,53448,17579,53391,    9,53452,
+42991,53391,40039,53391,40685,53391, 1197,53391,  265,53391,  253,53464,
+ 1471,53464,   53,53464,   53,53391,  265,53472,  253,53391,  265,53476,
+    5,53391, 1471,53391,  265,53482,    5,53390, 8953,53487, 9459,53487,
+ 4067,53487, 3997,53487, 8277,53487, 3867,53487,   11,53391, 9377,53500,
+    9,53391, 4903,53504,17579,53504, 9377,53391,   11,53510,    5,53511,
+    5,49712,48765,53517,48835,53517,48843,53517,25445,53517,22779,53517,
+22243,53517,    7,53517,    2,53531,28063,53517,25299,53517,31598,53517,
+53152,53517,50733,53517,35690,53517,37519,53517,50781,53517,52461,53517,
+50953,53517,  272,53517, 1476,53517,  280,53517,  949,53517, 1517,53517,
+  357,53517,  367,53517,  471,53517, 1249,53517, 9304,53517,53204,53517,
+53144,53517,35931,53517,52912,53517,20326,53517,21087,53517,20273,53517,
+    9,53586,50785,53517, 1369,53591,53391,53591,25381,53517,48753,53597,
+10081,53597, 9704,53517,   53,53517,  265,53604,37899,53517,37617,53517,
+52483,53517, 9617,53517,    9,53614,  253,53517,  265,53618,31103,53517,
+26625,53622,  375,53517,35187,53626,26625,53517,31103,53630, 1471,53517,
+  265,53634,  265,53517,  253,53638, 1471,53638,   53,53638,49204,53517,
+49205,53517,52913,53517,  713,53517, 9195,53652,52915,53652,21605,53653,
+  305,53517,52915,53660,21605,53661,    2,53517, 8229,53667,52909,53667,
+46863,53667,    3,53517,52909,53674,53391,53675, 1369,53675,46863,53674,
+52915,53517,  305,53684,  713,53684,   25,53684,   25,53517,52915,53692,
+21605,53693, 9195,53517,  713,53698,    2,53516,53677,53703,53581,53703,
+53647,53703,53683,53703,53675,53703,52909,53713,46863,53713, 4067,53703,
+ 3997,53703, 8953,53703, 9459,53703, 8277,53703, 3867,53703,    3,53516,
+53651,53731,53670,53731,50785,53731,50733,53731,53649,53731,53672,53731,
+19396,53731,53667,53731,52909,53746,46863,53746, 8647,53731,26219,53731,
+41417,53731,  483,53731,18967,53731,    9,53760,    9,53731,18967,53764,
+52909,53731,53667,53768,46863,53731,53667,53772,  587,53517,35187,53777,
+  483,53517,52909,53517,    3,53782,53703,53785,    3,53783,53667,53789,
+46863,53517,    3,53792,53703,53795,    3,53793,53667,53799,    9,53517,
+20273,53802, 9617,53802,35187,53517,  375,53808,    4,49712,48747,53813,
+37279,53813,19981,53813,24601,53813,    7,53813,21605,53823,53071,53813,
+52743,53813,52193,53813,50225,53813, 8306,53813,  545,53813,  695,53813,
+ 1382,53813, 1374,53813, 1386,53813,51906,53813,53442,53813,53199,53813,
+53373,53813,53095,53813,51803,53813, 1369,53856,53391,53856, 9992,53813,
+20734,53813,19916,53813,48739,53867,37241,53867, 7947,53867,28205,53813,
+24613,53813,25551,53813,53189,53813,  483,53881,   33,53813, 9875,53813,
+  265,53886,  241,53887,20501,53813,  265,53892,  241,53893, 1141,53813,
+  154,53813,  483,53901, 1447,53813,  331,53813, 1369,53906,  265,53813,
+ 8165,53910, 9875,53910,20501,53910, 1011,53813,   59,53813, 1369,53920,
+    3,53813, 8241,53925,   15,53924,  483,53929,53391,53813,51803,53932,
+ 1325,53813, 1369,53936,    3,53812,24265,53941,28233,53941,29077,53941,
+ 9673,53941,19559,53941, 4283,53941,20361,53941, 8251,53941, 3807,53941,
+ 9967,53941,20713,53941, 4279,53941, 1369,53813,  331,53966, 1325,53966,
+   59,53966,51803,53966,18967,53813, 1275,53976,48739,53979,37241,53979,
+ 7947,53979,  113,53977, 1275,53813,18967,53988,48739,53991, 7947,53991,
+37241,53991, 8165,53813,  265,53998,46863,53813,38056,54002,38056,54003,
+38057,54002,54007,54009,38057,54003,54005,54013,   15,53813,    3,54017,
+ 1369,54019,    3,54016,  483,54023,    5,49713,  375,54026,51615,54029,
+ 1368,54027,    7,54027,    2,54034,    2,54035,32805,54027,31103,54041,
+20035,54027,  375,54045,  341,54027,18967,54049,12377,54027,  375,54053,
+52915,54027,31103,54057,27021,54027,31103,54061,30091,54027,31103,54065,
+31103,54026,27021,54069,52915,54069,18967,54027,47608,54075,46863,54075,
+ 1011,54078, 1011,54075,46863,54082,53924,54027,53825,54087,  483,54087,
+51929,54027,  483,54093,51615,54027,  375,54097,  483,54097, 1369,54026,
+  803,54103,  483,54026,53813,54107,10107,54107,51929,54107,51615,54107,
+ 1275,54026, 1505,54117,18967,54026,   17,54121, 1369,54027,51601,54125,
+    2,54026,54078,54129,54075,54129,46863,54132,52541,54129, 1505,54129,
+  918,54129,52121,54129,54125,54129,  903,54129,    9,54146,    9,54129,
+  903,54150,46863,54129,54075,54154,    3,54026,54033,54159,54037,54159,
+53966,54159,12571,54159, 4613,54159,51615,54159, 8337,54159,46863,54173,
+52591,54159,53932,54159,53391,54159,53813,54180,53813,54159, 1369,54184,
+53391,54184,36773,54159,46863,54191,20103,54159,46863,54195, 1369,54159,
+53813,54198,    2,54027,    0,54202,54159,54205,46863,54207,    7,54202,
+54159,54211,  265,54203,    9,54215,54159,54203,    9,54219,46863,54219,
+    3,54027,48286,54225,54039,54225,54150,54225,52573,54225,52115,54225,
+38057,54225,46863,54236,53813,54224,53825,54241,  483,54241,    9,54225,
+54129,54246,  483,54225,53813,54251,54154,54225,46863,54225,38057,54256,
+54129,54256,54129,54225,    9,54262,46863,54262,10107,54027,  483,54269,
+53813,54027,  483,54273,    3,54273, 1369,54277,53391,54277,    3,54272,
+53825,54283,  483,54283,   17,54027,20273,54289, 9617,54289,    3,49713,
+16722,54295,16530,54294,54297,54299,16723,54295,16531,54294,54303,54305,
+16530,54295,    1,54295,35187,54311,   17,54313,    7,54295,16531,54316,
+54299,54319,16531,54317,54309,54323,   15,54317,38305,54327,    1,54294,
+40705,54331,54329,54331,   17,54331,    7,54294,54333,54339,40704,54339,
+54331,54343,49713,54339,    4,54346,    4,54339,49713,54350,54315,54339,
+    9,54339,38305,54356,54331,54359,38305,54339,    9,54362,54331,54365,
+52489,54295,    9,54369,36527,54295,  375,54373,  341,54295,12377,54295,
+    9,54379,16531,54295,    7,54382,54299,54385,37611,54295,    9,54389,
+ 8321,54295,35927,54295,    9,54395,38155,54295,    9,54399,43503,54295,
+44243,54403,  113,54295,38305,54406,40086,54295, 8241,54295,44243,54294,
+   11,54415, 1369,54415, 1486,54295,35187,54295,47640,54423,46863,54423,
+  903,54426,  903,54423,46863,54430,53480,54295,11731,54295,51615,54295,
+  241,54295,   17,54294,  113,54443,38305,54294,    9,54294,37611,54449,
+38155,54449,35927,54449,52489,54449,   15,54294,  483,54459,   11,54295,
+44243,54463,38305,54295,  113,54466,38057,54295,    7,54471,  375,54471,
+    4,54294,54426,54477,54423,54477,46863,54480,52573,54477,54377,54477,
+52115,54477,43053,54477,46863,54477,54423,54492,    5,54294,54473,54497,
+    6,54497,54471,54501,53966,54497,12571,54497, 4613,54497,51615,54497,
+ 8337,54497,46863,54513,52591,54497,53932,54497,53813,54497, 1369,54520,
+53391,54520,53391,54497,53813,54526,20103,54497,46863,54531,36773,54497,
+46863,54535, 1369,54497,53813,54538,    4,54295,    0,54542,54497,54545,
+46863,54547,    5,54295,48294,54551,21315,54551,46863,54554,53391,54550,
+ 1369,54550,46863,54551,21315,54562,53391,54295,    5,54567,53813,54569,
+    5,54566, 1369,54295, 9893,54575,52129,54575,54353,54575,54349,54575,
+20885,54575,52411,54575,44243,54575,    5,54574,    5,54575,53813,54593,
+    2,49713,53227,54597,53262,54597,53355,54597,53358,54597,53298,54597,
+53264,54597,53229,54597,53274,54597,53234,54597,49168,54597,    1,54597,
+    7,54597,  567,54621,52915,54623,    4,54621,54575,54627,53360,54627,
+52915,54627,  483,54632,  483,54627,52915,54636,    9,54621,    1,54596,
+36544,54643,35187,54643,   11,54646,   11,54643,35187,54650,    7,54596,
+36545,54655,54643,54657,54645,54655,21605,54655,54653,54655,54649,54655,
+   15,54655,53270,54597,46863,54670,53231,54597,46863,54674,49169,54597,
+54097,54597,53134,54597,53215,54683,53352,54597,53215,54687,53196,54597,
+53215,54691, 8311,54597,48884,54596,54617,54697,53731,54597,53881,54597,
+54283,54597,54241,54597,54087,54597,36256,54597,53296,54597,53167,54712,
+53184,54597,53255,54716,53167,54597,53357,54720,53296,54720,53255,54720,
+46863,54726,46863,54720,53255,54730,48885,54597,    9,54734,54697,54737,
+54697,54735,    9,54741,35187,54597,    9,54744,    9,54597,48885,54748,
+54697,54751,48885,54749,35187,54748,   11,54749,52915,54759,53188,54597,
+53215,54763,46863,54765,46863,54762,53215,54769,53813,54763,53139,54597,
+53255,54774,44243,54597,   11,54779,54225,54597,53813,54783,51229,54597,
+  265,54597,54027,54789,47961,54791,14611,54791, 4899,54791,  375,54791,
+   17,54596,  903,54801,51593,54801,54477,54801,54225,54801,   11,54596,
+53318,54811,52825,54811,52915,54811,    9,54816,    9,54811,52915,54820,
+44243,54811,53255,54597,53139,54826,53184,54826,53167,54826,46863,54832,
+46863,54826,53167,54836,53357,54597,53167,54840,    4,54596,51418,54845,
+51416,54845,51398,54845,51354,54845,51909,54845,  340,54845,51803,54857,
+51873,54845,47974,54845,47589,54845, 8590,54845,14620,54845,12537,54845,
+52021,54845,52029,54845,53106,54845,  375,54845,51229,54878,52915,54878,
+    0,54845,    6,54885,    7,54845,  265,54888,51803,54891,  265,54889,
+51229,54895,52915,54895,47580,54845,51803,54901, 8861,54901, 8495,54845,
+47961,54906, 4899,54906,14611,54906,52915,54845,  375,54914,14611,54845,
+51229,54918, 8495,54918, 4899,54845,51229,54924, 8495,54924,47961,54845,
+51229,54930, 8495,54930,  265,54845,    7,54936,51803,54939,54887,54937,
+54886,54936,54943,54945,54887,54936,54886,54937,54949,54951,46863,54936,
+ 8861,54955,51803,54955,46863,54845,  265,54960,51803,54963, 8861,54963,
+  265,54961,51229,54969, 8495,54969,51229,54845,  375,54974,14611,54974,
+ 4899,54974,47961,54974,    5,54596, 1505,54985,  918,54985,52541,54985,
+52121,54985,54125,54985,  903,54985,    9,54996,    9,54985,  903,55000,
+    5,54597,54889,55005,52915,55007,53349,55004,    6,55005,54914,55013,
+52915,55013,54845,55016,54845,55013,52915,55020,   53,55005, 1471,55005,
+  253,55005,52557,55005,53348,55004,53215,55033,  241,55005,    9,55037,
+52915,55004,53215,55041,46863,55043,46863,55040,53215,55047,53813,55041,
+   17,55005,35187,55053,52915,55005,53357,55057,55011,55057,53296,55057,
+53255,55057,46863,55064,46863,55057,53255,55068,46863,55004,52915,55072,
+53215,55075,52915,55073,53255,55079,48885,54596,54679,55083,    9,55083,
+48884,54597,54755,55089,55086,55089,55083,55089,    9,55094,52915,55088,
+53215,55099,52915,55089,53255,55103,    9,55089,55083,55106,53348,54597,
+    5,55110,53215,55113,    5,55111,53167,55117,52915,54597,48884,55120,
+53215,55123,48884,55121,53139,55127,    5,55121,53139,55131,53184,55131,
+53167,55131,46863,55136,46863,55131,53167,55140,    5,55120,53215,55145,
+46863,55147,46863,55144,53215,55151,53813,55145,46863,55120,    5,55156,
+53215,55159,    5,55157,53167,55163,21605,54597,54027,55167,31103,55169,
+46863,54597,53270,55172,53231,55172,53188,55172,53215,55179,53255,55172,
+53167,55182,53167,55172,53255,55186,    5,55172,52915,55190,53215,55193,
+52915,55191,53255,55197,52915,55172,    5,55200,53215,55203,    5,55201,
+53167,55207,    4,49713,51398,55211,  375,55211,51229,55214,53709,55211,
+53740,55211,51909,55211,53797,55211,53800,55211,  340,55211,51803,55229,
+54339,55210,54575,55233,53774,55211,53742,55211,53711,55211,53750,55211,
+53716,55211,54663,55211,53533,55211, 1368,55211,52205,55251,54449,55251,
+52809,55251,54295,55251,    9,55259,    7,55211,  265,55263,51229,55265,
+   89,55263,52915,55269,  265,55262,51803,55273,    2,55262,52205,55277,
+52809,55277,54449,55277,54295,55277,    9,55285,    2,55263,52825,55289,
+53318,55289,    9,55289,52915,55294,52915,55289,    9,55298,53746,55211,
+46863,55302,53713,55211,46863,55306,31796,55211,25037,55211,25215,55211,
+42338,55211,42076,55211,43053,55211,42959,55211,54575,55211,54339,55325,
+54786,55211,51360,55211,53780,55211,52751,55211, 8148,55211, 9594,55211,
+54377,55211,54439,55211,53758,55211,54700,55211,54826,55211,53286,55211,
+53646,55211,53703,55353,53794,55211,53703,55357,53682,55211,53703,55361,
+53371,55211,  842,55211, 9377,55367,54591,55211,54421,55211,54561,55211,
+53681,55211,53255,55211,54597,55378,  483,55378,53679,55211,54573,55211,
+55131,55211,54559,55211,54435,55211,19892,55211,53772,55211,53667,55396,
+53672,55211,53731,55400,53667,55211,53799,55404,53772,55404,53731,55404,
+46863,55410,46863,55404,53731,55414,  935,55211,20733,55211, 9991,55211,
+41941,55211,  483,55424, 9565,55211,  483,55428, 1487,55211,54597,55211,
+51229,55434,   53,55435, 1471,55435,  253,55435,53731,55434,53255,55434,
+47546,55211,   66,55211, 1369,55451,  241,55211,31103,55454,18967,55211,
+  483,55458,  483,55211,42155,55462,41941,55462,51229,55462,53517,55462,
+ 7971,55462, 9565,55462,53731,55462,53255,55462,  587,55462, 9377,55481,
+18967,55462,  587,55463, 9195,55487,52915,55487,53674,55211,53703,55493,
+46863,55495, 1369,55493,46863,55492,53703,55501,53391,55493,53649,55211,
+53731,55506,31103,55211,  241,55510,  587,55511,  113,55211,46863,55516,
+17455,55211,54551,55211, 1369,55523,53391,55523,51229,55211,  375,55528,
+54597,55528,  483,55528, 1011,55211, 8165,55537, 9875,55537,20501,55537,
+   11,55537,  265,55211,    7,55546,51803,55549,54295,55547,47961,55553,
+14611,55553, 4899,55553,  375,55553, 1369,55210,54985,55563,51601,55563,
+54129,55563,  587,55210, 9366,55571,54575,55571,53360,55571, 9195,55571,
+  483,55578,52915,55571,  483,55582,  483,55571, 9195,55586,52915,55586,
+31103,55571,53731,55211,53649,55594,53672,55594,53667,55594,46863,55600,
+  483,55594,54597,55594,46863,55594,53667,55608,  587,55211, 9377,55613,
+  483,55615,  483,55612, 9377,55619,21605,55211,21526,55622,    6,55623,
+21527,55622,55627,55629,    7,55622,    7,55623,55625,55635,    6,55622,
+18967,55638,55635,55641,18967,55622,    6,55645,55633,55647,    6,55644,
+55635,55651, 1347,55211, 1369,55655,53799,55211,53667,55658,    2,55210,
+51418,55663,51416,55663,51398,55663,51354,55663,51909,55663,  340,55663,
+51803,55675,51873,55663,47974,55663,47589,55663, 8590,55663,14620,55663,
+12537,55663,52021,55663,52029,55663,53106,55663,  375,55663,51229,55696,
+52915,55696,    0,55663,    6,55703,    7,55663,  265,55706,51803,55709,
+  265,55707,51229,55713,52915,55713,47580,55663,51803,55719, 8861,55719,
+ 8495,55663,47961,55724, 4899,55724,14611,55724,52915,55663,  375,55732,
+14611,55663,51229,55736, 8495,55736, 4899,55663,51229,55742, 8495,55742,
+47961,55663,51229,55748, 8495,55748,  265,55663,    7,55754,51803,55757,
+55705,55755,55704,55754,55761,55763,55705,55754,55704,55755,55767,55769,
+46863,55754, 8861,55773,51803,55773,46863,55663,  265,55778,51803,55781,
+ 8861,55781,  265,55779,51229,55787, 8495,55787,51229,55663,  375,55792,
+14611,55792, 4899,55792,47961,55792,    3,55210,54801,55803,52573,55803,
+52115,55803,43053,55803,46863,55803,    2,55211,    7,55814,52205,55817,
+52809,55817,54449,55817,54295,55817,    9,55825,54295,55815,54501,55829,
+    7,55829,54497,55833,  375,55829,    3,55211,55707,55839,52915,55841,
+55706,55839,53793,55838,55779,55839,    6,55839,55732,55851,52915,55851,
+55663,55854,55663,55851,52915,55858,    0,55851,55829,55851,    0,55850,
+55663,55867,    0,55839,    6,55870,55663,55873,    0,55838,49713,55838,
+55845,55879,    1,55838,55868,55883,55874,55883,55867,55883,55663,55888,
+55873,55883,55663,55892,55849,55883,55663,55883,55867,55898,55873,55898,
+46862,55839,55898,55905,55883,55905,55663,55908,55663,55905,55883,55912,
+    1,55839,55863,55917,55663,55919,    7,55839,55663,55922,55879,55925,
+55879,55923,55663,55929,52591,55839,53792,55838,53703,55935,43027,55839,
+43837,55839,39747,55839,53517,55838,53703,55945,46863,55947, 1369,55945,
+46863,55944,53703,55953,53391,55945, 1369,55839,18967,55959,   11,55838,
+ 1369,55963,18967,55839,46863,55967,   11,55839,46863,55971,53517,55839,
+53799,55975,55847,55975,53772,55975,53731,55975,46863,55982,46863,55975,
+53731,55986,55778,55839,55877,55991,46863,55839,55877,55995,55663,55997,
+55663,55994,55877,56001,55663,55839,    7,56004,55879,56007,46863,56004,
+55877,56011,46863,55838,53517,56014,53703,56017,53517,56015,53731,56021,
+49204,55211,53517,56024,53703,56027,53517,56025,53731,56031,53792,55211,
+    3,56034,53703,56037,    3,56035,53667,56041, 7971,55211,  483,56044,
+42155,55211,  483,56048,53517,55211,  483,56052,49204,56052,53703,56057,
+49204,56053,53649,56061,    3,56053,53649,56065,53672,56065,53667,56065,
+46863,56070,  483,56065,54597,56065,46863,56065,53667,56078,    3,56052,
+53703,56083,46863,56085, 1369,56083,46863,56082,53703,56091,53391,56083,
+46863,56052,    3,56096,53703,56099,    3,56097,53667,56103,   11,55211,
+    3,56106, 1369,56109,    3,56107,  483,56113,46863,55211,53746,56116,
+53713,56116,53674,56116,53703,56123,53731,56116,53667,56126,53667,56116,
+53731,56130,  113,56116,    3,56116,53517,56136,53703,56139,53517,56137,
+53731,56143,53517,56116,    3,56146,53703,56149,    3,56147,53667,56153,
+46863,49713,47982,56156,47983,56157,56159,56161,47983,56156,47982,56157,
+56165,56167,49588,56156,49589,56157,56171,56173,49670,56156,49671,56157,
+56177,56179,49589,56156,49588,56157,56183,56185,49671,56156,49670,56157,
+56189,56191, 8453,56156,  273,56156,21522,56156,38266,56156, 1516,56156,
+  948,56156,20239,56156,37095,56156, 1477,56156,  281,56156,49617,56156,
+49616,56157,56215,56217,49699,56156,49698,56157,56221,56223,49617,56157,
+49616,56156,56227,56229,49699,56157,49698,56156,56233,56235, 1216,56156,
+  412,56156,12377,56156,  375,56156,  510,56156,38057,56156,  903,56248,
+  165,56156,  903,56252,21315,56156, 1011,56256, 1505,56156, 1011,56260,
+  413,56157,50785,56265,56241,56265, 1217,56157,56239,56271, 1216,56157,
+  413,56156,  412,56157,56277,56279, 1217,56156,56275,56283,  264,56157,
+51777,56287,50908,56287,50785,56287,  241,56292,  241,56287,50785,56296,
+  375,56287,  264,56156,50207,56303,51765,56303,51677,56303,51615,56303,
+  241,56311,  341,56303, 1011,56156, 1505,56316,21315,56316,  903,56156,
+  165,56322,38057,56322,  483,56156,    9,56328,    9,56156,  483,56332,
+    5,56157,    4,56156,56337,56339,46863,56340,    2,56343,    2,56342,
+49515,56340,49514,56340,    2,56341,56349,56353,    3,56341,56347,56357,
+56351,56357,    2,56340,46863,56362,56357,56365,56357,56363,    3,56340,
+56345,56371,56353,56371,    3,56157,  375,56377,    2,56156,56337,56381,
+    1,56383,    0,56382,56385,56387,    0,56383,    1,56382,56391,56393,
+56377,56381,46863,56396,    4,56399,    4,56398,49631,56396,49630,56396,
+    4,56397,56405,56409,    5,56397,56403,56413,56407,56413,    4,56396,
+46863,56418,56413,56421,56413,56419,    5,56396,56401,56427,56409,56427,
+    2,56157,    3,56156,56337,56435,    7,56437,    6,56436,56439,56441,
+    6,56437,    7,56436,56445,56447,56433,56435,46863,56451,    4,56452,
+    4,56453,49631,56451,49630,56451,    4,56451,46863,56462,    5,56451,
+56457,56467,    4,56450,56467,56471,56459,56471,    5,56450,56465,56477,
+56455,56477,56463,56477,56461,56477,    4,56157,56435,56487,    1,56489,
+    0,56488,56491,56493,    0,56489,    1,56488,56497,56499,56381,56487,
+    7,56503,    6,56502,56505,56507,    6,56503,    7,56502,56511,56513,
+    5,56156,56487,56517,46863,56519,    2,56520,    2,56521,49515,56519,
+49514,56519,    2,56519,46863,56530,    3,56519,56525,56535,    2,56518,
+56535,56539,56527,56539,    3,56518,56533,56545,56523,56545,56531,56545,
+56529,56545,    1,    2,11709,56555,11632,56555,11035,56555,10468,56555,
+17775,56555,11788,56555,12226,56555,11816,56555,11770,56555,44558,56555,
+42181,56555,44243,56576,44438,56555,10856,56555, 3447,56555,  375,56584,
+ 3448,56555,11705,56555,11033,56555,10516,56555,17773,56555,18735,56555,
+10427,56555,10831,56600,10836,56555,10855,56555,16623,56555,16711,56555,
+ 9533,56610,16718,56555, 3555,56555, 5882,56555, 9261,56555,  483,56621,
+ 3699,56555,   15,56625,    6,56624,56627,56629,   14,56625,    7,56624,
+56633,56635, 1999,56555,   15,56639,    6,56638,56641,56643,   14,56639,
+    7,56638,56647,56649,29450,56555,29731,56653,29659,56653,28791,56653,
+29041,56653,38067,56555,    5,56663,38185,56665,42155,56554,44243,56669,
+42471,56670,44966,56669,42471,56669,44243,56676, 1471,56554,36639,56681,
+15390,56555,15383,56685,28715,56555,21527,56689,29229,56691,    7,56689,
+29759,56695,    7,56688,28791,56699,29041,56699,29731,56699,29659,56699,
+ 1005,56555,16877,56554,16893,56711, 9925,56555, 1369,56715, 9927,56717,
+35336,56555,  989,56721,35278,56555, 1177,56725,  987,56555,35187,56728,
+  989,56731,36563,56554,36639,56735,  671,56554,36597,56554,36639,56741,
+ 1418,56554,    1,56745,    4,56746,    4,56745,    1,56750,  147,56555,
+35187,56754,   53,56757,17637,56555,  587,56760,10107,56763,35316,56555,
+ 1471,56767,35330,56555,   53,56771,17638,56555,10107,56775, 1489,56555,
+35187,56778, 1471,56781, 1179,56555,35187,56784, 1177,56787,37229,56555,
+35187,56790,37223,56793, 9441,56555,  587,56796, 9439,56799,37230,56555,
+37223,56803, 9442,56555, 9439,56807,45432,56555,42435,56811,   30,56555,
+11731,56814,45433,56555,56669,56819,43099,56555,52259,56555,  483,56825,
+44742,56555,44904,56555,52613,56555,52383,56555,52497,56555,39231,56555,
+40447,56555,39083,56555,38797,56555,39019,56555,39301,56555,39429,56555,
+39305,56555,  386,56555,  347,56555,54492,56555,45508,56555,56116,56555,
+55812,56555,40987,56555,52909,56555,51598,56555,50419,56555,56332,56555,
+52836,56555,52366,56555,36639,56555, 1471,56881,36563,56881,36597,56881,
+  181,56555,11731,56888,50579,56555,52319,56555,52323,56555,54436,56555,
+54406,56555,52532,56555,52514,56555,55520,56555,44930,56555,39317,56555,
+51141,56555,40123,56555,39228,56555,40676,56555,47366,56555,40682,56555,
+52599,56555,50655,56555,52531,56555,36538,56555,36048,56555,37594,56555,
+42918,56555,40922,56555,39292,56555,11111,56555,11113,56555,11187,56555,
+17508,56555,17180,56555, 3280,56555, 3574,56555, 3568,56555,12216,56555,
+   25,56958,11613,56555,   25,56962,48406,56555,48400,56555,48500,56555,
+43292,56555,47534,56555,17494,56555,39065,56555,48961,56555,49162,56555,
+17496,56555,11179,56555,47892,56555,11546,56555,11207,56555, 5878,56555,
+52446,56555,35506,56555,39035,56555,40087,56555,    9,57003,10513,56555,
+    9,57006,36102,56555,  253,57011,   53,57011,  117,57011, 1471,57011,
+ 7968,56555,53813,57021,10107,57021,11067,57021,37282,56555,53813,57029,
+37417,57029,10107,57029,35652,56555,  253,57037, 1471,57037,  809,57037,
+   53,57037,38293,56555,53813,57047,37417,57047,38275,57047,10107,57047,
+ 1397,56555,35187,57056,52439,56555,  265,57060,40127,56555,43318,56555,
+48750,56555,53813,57069,10107,57069,36100,56555,  253,57075,   53,57075,
+ 1471,57075, 9404,56555,  483,57083, 8053,56555,    9,57087,10465,56555,
+    9,57090,11936,56555,10119,56555,10185,56555,53885,56555,10117,56555,
+45490,56555,   33,57105, 8212,56555,    9,57109,11812,56555,    9,57112,
+53899,56555, 6719,56555,   11,57119,    5,57120,    6,57119,    5,57124,
+    5,57119,    6,57128,    6,57129,    7,57119,57133,57135,   15,57119,
+    6,57118,57139,57141,   14,57119,    7,57118,57131,57147,57127,57147,
+57123,57147,57145,57147, 6787,56555,    5,57157,    4,57157,   12,57157,
+   13,57156,57163,57165,   13,57157,   12,57156,57169,57171,    5,57156,
+57161,57175,    4,57156,57159,57179,10831,56555,  375,57182,44243,57182,
+10427,57182,    9,57183,11529,56555,46863,57192,  483,57192,17640,56555,
+39226,56555,48572,56555,47410,56555,40568,56555,47374,56555,47674,56555,
+17656,56555,47676,56555,47634,56555,48112,56555,47412,56555, 5814,56555,
+  918,56555,36256,56555,46863,57226,48466,56555,49713,57230,35187,57230,
+   11,57231,47608,56555,  903,57238,52756,56555,46863,57242,48620,56555,
+  247,56555,46863,57248, 1419,56555,56749,57253,56753,57253,25519,57253,
+ 1841,57253, 1883,57253,22679,57253,    5,57253,22677,57267,14065,57253,
+ 5175,57253,40565,56555,  587,57274,  922,56555,51593,56555,46863,57280,
+47640,56555,   11,57285, 1011,57284,   11,57284,35718,56555, 9439,57293,
+37223,57293, 9381,57293,37157,57293,35877,57293,35881,57293, 9383,57293,
+37163,57293,35883,57293,   17,57293,37145,57313, 9377,57313,35867,57313,
+51051,56555,  375,57321,50959,56555,    9,57325,39205,56555,   10,57329,
+   10,57328,   11,57329,57333,57335, 1011,57328,   11,57328,57331,57341,
+48402,56555,    9,57344,48560,56555,  903,57348,36544,56555,    6,57353,
+36661,57355,36675,57353, 8067,57353, 7979,57353, 7981,57353,39747,57353,
+43837,57353,43027,57353, 1369,57353, 7971,57373,  934,56555,46863,57376,
+  668,56555,    5,57381,22605,57383,22615,57381, 3135,57381, 2009,57381,
+14065,57381, 5175,57381,53905,56555,55432,56555,10303,56555,42661,56555,
+   25,56555,11613,57404,12216,57404,    9,57404,11731,57410,35187,57404,
+  253,57415,   53,57415,  117,57415, 1471,57415,11731,57404,    9,57424,
+ 8165,56555,   67,57428,    9,57431, 7947,56555,  587,57434,53813,57437,
+10107,57437,11067,57437,17049,56555,46863,57444,  165,56555,43215,57448,
+  113,56555,54295,57452,  767,56555,  483,57457, 9377,57459, 9377,57456,
+  483,57463,  803,56555,17455,57466,  375,56555,10831,57470, 3447,57470,
+  305,57470,17125,57470,  510,56555,   11,56555,   33,57483,44243,57485,
+44243,57482,   33,57489,39205,57482,47640,57482,46863,57482,  903,57496,
+35187,57482,43027,57501,43837,57501, 8067,57501, 7979,57501,39747,57501,
+ 7981,57501, 1369,57501, 7971,57515,  903,57482,46863,57518,    9,56555,
+10465,57522,11812,57522,10513,57522,   25,57522,11731,57530,56156,57522,
+40675,57522, 3565,57522, 3573,57522, 3273,57522,11731,57522,   25,57544,
+48402,57522,17455,57522, 5843,57522,   11,57523,46863,57555,49713,57522,
+46863,57558,  903,57522,35187,57522,46863,57564,46863,57522,49713,57568,
+35187,57568,   11,57569,  587,57522, 5175,57577,14065,57577, 3135,57577,
+ 2009,57577,  483,57522,55839,56555,  483,57589, 5771,56555,  903,57592,
+ 6705,56555, 1369,57597, 6707,57599, 6711,57599, 6715,57599, 3697,56555,
+   16,57607,   16,57606,   17,57607,57611,57613,   17,57606,57609,57617,
+ 3709,56555, 8075,56555,    9,57623, 3273,56555,    9,57626, 3423,56555,
+   16,57631,   16,57630,   17,57631,57635,57637,   17,57630,57633,57641,
+ 3661,56555,   16,57645,   16,57644,   17,57645,57649,57651,   17,57644,
+57647,57655, 3681,56555, 3357,56555,53675,56555,    9,57663,42379,56555,
+    9,57667, 3573,56555,    9,57670, 3565,56555,    9,57674,52878,56555,
+15436,56555,  375,57681,54550,56555,17232,56555,38305,57686, 4935,56555,
+    6,57691,    5,57692,    7,57691,    5,57691,    6,57698,    6,57699,
+57697,57703,    6,57690,   15,57691,57707,57709,    7,57690,57695,57713,
+57701,57713,   14,57691,57713,57719,55803,56555,46863,57722,16127,56555,
+    6,57727,    5,57728,    7,57727,    5,57727,    6,57734,    6,57735,
+57733,57739,    6,57726,   15,57727,57743,57745,    7,57726,57731,57749,
+57737,57749,   14,57727,57749,57755,54477,56555,46863,57758,49155,56555,
+  483,57762, 5843,56555,  955,57766,    9,57766, 5313,56555, 9802,56555,
+48736,56555, 9434,56555,  483,57779,15309,56555,  413,57782,15383,57785,
+  413,57783,15335,57789,    8,56554,    4,57793,    1,57794,57381,57797,
+57577,57797,    1,57793,    4,57802,57381,57805,57577,57805,   10,56554,
+    7,57811,    2,57812,57353,57815,57501,57815,    2,57811,    7,57820,
+57353,57823,57501,57823,57515,57811,57373,57811, 1368,57811,57501,57833,
+57353,57833, 3867,57811, 8277,57811, 3997,57811, 4067,57811, 9459,57811,
+ 8953,57811,57483,57811,    9,57811,   14,56555,38881,57855,   11,56554,
+44778,57859,44243,57859,   25,57862,47640,57859,   25,57859,44243,57868,
+48466,57859,  903,57859,46863,57874,46863,57859,  903,57878,    9,57878,
+    9,57859,46863,57884,    9,56554,40903,57889,40053,57889,43307,57889,
+ 5019,57889,12361,57889,   16,56555,19625,57901,21105,57901,21549,57901,
+17591,57901,   17,56554,36639,57911,   10,56555,57859,57915,11731,56555,
+   30,57918,  181,57918,54295,57918,    9,57918,   25,57926,  145,57918,
+   25,57918,    9,57932,   67,56555,    9,57937, 8165,57939, 8165,57936,
+    9,57943,17635,56555,  155,57946,  903,57946,  145,56555,11731,57952,
+17695,56555, 1369,57957, 7971,57959,53517,57959,17053,57959,17699,57959,
+42155,57959,  155,56555,17635,57970,10305,56555,42699,56555,10307,56555,
+  566,56555,53813,57981,10107,57981,  256,56555,42810,56555,17125,57988,
+ 1170,56555,  629,56555, 1413,56555,37408,56555,25793,57999,41019,57999,
+ 8495,57999,  265,57998, 1346,56555,48884,56555,27021,58011,52915,58011,
+ 9195,58011,20763,58011,  340,56555,  331,58021,35187,58020,38270,56555,
+  766,56555,25519,58029,  802,56555, 9366,58033, 9195,58033,  483,58036,
+  483,58033, 9195,58040,31103,58033,42729,56555,  257,56555,44243,58048,
+ 1487,56555,55211,58052,44243,56555,10831,58056,42181,58056,42155,58057,
+42471,58063,42155,58056,42435,58067, 9533,58056,37145,58056,   11,58057,
+   25,58075,35187,58056,17125,58056,   11,58056,   33,58083,49713,58056,
+  257,58056,55211,56555,46863,58090,17455,58090, 1487,58090, 1197,56555,
+    4,58099,    5,58098,58101,58103,    5,58099,    4,58098,58107,58109,
+ 1505,56555,45002,56555,42155,56555,42435,58117,44243,58119,44243,58116,
+42435,58123,  305,56555,  375,58126,35187,58126,  253,58131, 1471,58131,
+   53,58131,  713,56555,35187,58138,  253,58141, 1471,58141,  809,58141,
+   53,58141,37241,56555,  587,58150,53813,58153,37417,58153,10107,58153,
+  955,56555, 5843,58160,48739,56555,  587,58164,53813,58167,10107,58167,
+40461,56555,    9,58173,52501,56555,35187,58176,  241,58176, 9801,56555,
+   17,58182,    4,58183,58185,58187,    5,58183,57901,58191,    4,58182,
+    7,58194,58191,58197,    5,58182,48735,56555,   17,58202,    4,58203,
+58205,58207,    5,58203,57901,58211,    4,58202,    7,58214,58211,58217,
+    5,58202, 9533,56555,16711,58222,44243,58222,37145,56555,44243,58228,
+ 8861,56555,    5,58233,    6,58235,    6,58234,   14,58233,   15,58233,
+    6,58233,    5,58244,    7,58233,58237,58249,    6,58232,58243,58253,
+    7,58232,58239,58257,58247,58257,58241,58257, 9377,56555,  767,58264,
+  483,58267,    4,58264,  483,58271, 1217,56555,  483,58275,  413,56555,
+15309,58278,15383,58281,15309,58279,15363,58285,46863,58278,  412,56555,
+  483,58291, 1216,56555,46863,58294,56156,56555,    9,58298, 1011,56555,
+39205,58302,47640,58302,46863,58302,  903,58308,    7,58302,  903,58302,
+46863,58314,43215,58302,    7,58319,38305,56555,17232,58322,    7,58322,
+17125,58326,17125,58322,    7,58330,49713,56555,48466,58334,    9,58334,
+46863,58338,44243,58334,46863,58334,    9,58344,  241,56555,52501,58348,
+    7,58348,    7,58349,  265,58355,  265,58348,  483,58359,  483,56555,
+40675,58362,43215,58362,49155,58362,11529,58362,  903,58362,    9,58362,
+    5,58362,53813,58377,10107,58377,    5,58363,55211,58383,40675,56555,
+    7,58387,    9,58386,  483,58386,46863,58386,35187,56555,37229,58396,
+37223,58399, 1177,58397, 1179,58403,  989,58397,  987,58407, 1179,58396,
+ 1177,58411,  987,58396,  989,58415, 1489,58396, 1471,58419,  147,58396,
+   53,58423,  117,58397,   25,58427,  809,58397,  713,58431,    2,58396,
+    7,58435,    2,58436,58397,58439,    5,58436,58441,58443,    5,58435,
+    7,58446,   10,58435,    4,58396,    7,58453,    4,58454,58397,58457,
+    3,58454,58459,58461,    3,58453,    7,58464,  586,58453, 1368,58396,
+    7,58471,    5,58472,    5,58471,    7,58476,   10,58471,   16,58396,
+    7,58483,    3,58484,    3,58483,    7,58488,  586,58483,44243,58396,
+52501,58396,  340,58396,48466,58396, 1397,58396,   25,58396, 1471,58505,
+  253,58505,   53,58505,  117,58505,  713,58396,   53,58515,  253,58515,
+ 1471,58515,  809,58515,   53,58397,  147,58525,  305,58525,  713,58525,
+   25,58525, 1471,58397, 1489,58535,  305,58535,   25,58535,  713,58535,
+  305,58396,  253,58545, 1471,58545,   53,58545,  253,58397,  305,58553,
+   25,58553,  713,58553,    9,58396,46863,58560, 1369,58397, 9891,58565,
+ 9927,58565,58475,58565,58479,58565,58443,58565,58449,58565,    4,58565,
+ 9895,58565,19687,58565,20843,58565,21127,58565,58451,58565,58481,58565,
+   11,58565, 9875,58593,58435,58593,58471,58593,   17,58397,10111,58601,
+10159,58601,58487,58601,58491,58601,36729,58601,58461,58601,58467,58601,
+    2,58601,10113,58601,58469,58601,58493,58601,  587,58601,10107,58625,
+58453,58625,58483,58625,46863,58396,    9,58632,   11,58396,57815,58637,
+57823,58637, 8067,58637, 7979,58637,    3,58637,58601,58647,58617,58637,
+ 7981,58637,39747,58637,43027,58637,43837,58637,57833,58637, 1369,58637,
+ 7971,58663,57811,58663,  587,58396,35877,58669,35881,58669, 9439,58669,
+ 9381,58669,    5,58669,58565,58679,58579,58669,37223,58669,37157,58669,
+ 9383,58669,37163,58669,35883,58669,   17,58669, 9377,58695,37145,58695,
+35867,58695,    6,58396,    7,58396,25793,58705,41019,58705, 8495,58705,
+  265,58704,    6,58397,36661,58715,58705,58715,57999,58715,    7,58397,
+58703,58723,58027,58723,  265,58396,    6,58728,    7,58728,    6,58729,
+58733,58735,    7,58729,58731,58739,  903,56555,17455,58742,17635,58742,
+47608,58742, 5771,58742,48560,58742,   11,58743,46863,58755,    9,58742,
+  483,58742,46863,58742,   11,58763, 1011,58762,   11,58762,   11,58742,
+46863,58770,    7,58743, 8165,58775, 1011,58742,46863,58778,46863,56555,
+21036,58782,21036,58783,21037,58782,58787,58789,21037,58783,58785,58793,
+54477,58782,55211,58782,55803,58782,52756,58782,51593,58782,40675,58782,
+43215,58782,36256,58782,11529,58782,  934,58782,  247,58782, 1216,58782,
+  413,58782,17049,58782,   11,58783,  903,58825,    9,58825,    9,58782,
+49713,58830,35187,58830,   11,58831, 1011,58782,  903,58838,35187,58782,
+    9,58842,  903,58782,   11,58847, 1011,58846,   11,58846,   11,58782,
+  903,58854,    5,58782,27021,58859,52915,58859, 9195,58859,20763,58859,
+49713,58782,    9,58868, 1275,56555,   17,58872,    4,58872,    7,58876,
+    5,58872,    4,58873,58875,58883,    5,58873,58879,58887,57901,58887,
+  265,56555,37408,58892,52439,58892,    7,58892,  331,58899,35187,58898,
+    7,58893,  375,58905,  241,58892,  483,58909,38305,58893,  375,58913,
+35187,58892,    6,58916,    7,58916,    6,58917,58921,58923,    7,58917,
+58919,58927,  587,56555, 9441,58930, 9439,58933,17637,58930,10107,58937,
+37417,58931,37241,58941,11067,58931, 7947,58945,    7,58930,    4,58949,
+    7,58950,58931,58953,    0,58950,58955,58957,    0,58949,    4,58960,
+35186,58949,    1,58930,    4,58967,    1,58968,58931,58971,    6,58968,
+58973,58975,    6,58967,    4,58978,    8,58967,   16,58930,    4,58985,
+    0,58986,    0,58985,    4,58990,35186,58985,22807,58931,37241,58930,
+10107,58999,53813,58999,37417,58999, 7947,58930,53813,59007,10107,59007,
+11067,59007,10107,58931,17637,59015,48739,59015,37241,59015, 7947,59015,
+48739,58930,53813,59025,10107,59025,53813,58931,48739,59031,37241,59031,
+ 7947,59031,40565,58930,   17,58931, 1985,59041, 3721,59041,58989,59041,
+58993,59041, 5299,59041,58957,59041,58963,59041,    1,59041,35233,59041,
+35917,59041, 4861,59041,17563,59041,58965,59041,58995,59041,35187,59041,
+   53,59071,58949,59071,58985,59071,35187,58930,35881,59079,35877,59079,
+37223,59079,37157,59079,    6,59079, 9439,59079, 9381,59079,37163,59079,
+ 9383,59079,35883,59079,   17,59079,37145,59101, 9377,59101,35867,59101,
+    9,58930,57797,59109,57805,59109, 3135,59109, 2009,59109,    0,59109,
+59041,59119,59057,59109, 5175,59109,14065,59109,    4,58930, 9366,59129,
+ 9195,59129,  483,59132,  483,59129, 9195,59136,31103,59129,    5,58930,
+25519,59143,    5,58931,25503,59147,24623,59147,30387,59147,58565,59147,
+22605,59147,36526,56555,    6,59158,    7,59158,    6,59159,59163,59165,
+    7,59159,59161,59169,40920,56555,    7,59172,43400,56555,    7,59177,
+16065,56555,    5,59181,    7,59182,    7,59183,56555,59186,    6,59182,
+59189,59191,    6,59183,56555,59183,    7,59196,59191,59199,    7,59197,
+59195,59203,15029,56555,    5,59206,    6,59209,    6,59208,   14,59206,
+   15,59206,    6,59206,    5,59218,    7,59206,59211,59223,  375,59223,
+    6,59207,59217,59229,    7,59207,59221,59233,59213,59233,   59,59233,
+59215,59233,  331,59233, 1325,59233,  265,59233,43215,56555,    9,59249,
+  483,59248,46863,59248,  165,59248, 1011,59248,    7,59259,17125,56555,
+    4,59262,    7,59265, 1011,59266, 1011,59265,    7,59270,    7,59271,
+ 1170,59265,    5,59263,57993,59279,58313,59279,17129,59279,42811,59263,
+42811,59262,44243,59262,42810,59262,59287,59293,42810,59263,59289,59297,
+  375,59262,    6,59262,59269,59303,59273,59303,59277,59303,    7,59262,
+38305,59310,    6,59263,59275,59315,59311,59315,    7,59263,59303,59321,
+38305,59262,    7,59324,54295,56555,11731,59328,  113,59328,    5,59328,
+    5,59329,57901,59337,17455,56555,    7,59341,    4,59342,    4,59343,
+   16,59341,   17,59341,55211,59340,  803,59340,  903,59340,    9,59340,
+    4,59340,59351,59361,    5,59340,59345,59365,59349,59365,    4,59341,
+    7,59370,59365,59373,    5,59341,59347,59377,    4,56554,26454,59381,
+26375,59381, 8672,59381, 8743,59381,41692,59381,41607,59381, 8770,59381,
+ 8729,59381, 3795,59381,47953,59381,48062,59381,47961,59381,48009,59404,
+48009,59381,47961,59408,26219,59381,26415,59412,41417,59381,41653,59416,
+44832,59381,31770,59381, 8757,59381, 8647,59424,41653,59381,41417,59428,
+26415,59381,26219,59432, 8647,59381,  305,59436, 8757,59436, 8605,59381,
+47580,59381,47933,59445, 8684,59381, 8717,59449, 8916,59381,44243,59381,
+  483,59454,41502,59381,41559,59459,  340,59381, 8717,59463, 3785,59463,
+ 8495,59463,  375,59381, 8861,59470,46863,59470,47488,59381,26292,59381,
+26331,59479,    9,59381,31103,59482,  305,59381, 8647,59486,    7,59381,
+    1,59491,  264,59492,  264,59493,25793,59491,26415,59499,41019,59491,
+41653,59503, 8495,59491,  305,59507, 8757,59507, 8495,59490, 8717,59513,
+41019,59490,41559,59517,  265,59491,59497,59521, 8861,59521,46863,59521,
+25793,59490,26331,59529,  265,59490, 8717,59533,59495,59533, 3785,59533,
+ 8495,59533,31103,59381,    9,59542,  483,59381,44243,59546,46863,59381,
+  265,59551,48009,59553,  265,59550,47933,59557,  375,59550,41019,59381,
+    7,59563,41417,59565,    7,59562,41559,59569,  265,59381,46863,59573,
+47961,59575,46863,59572,47933,59579,    7,59573, 8647,59583,    7,59572,
+ 8717,59587, 3785,59587, 8495,59587,25793,59381,    7,59595,26219,59597,
+    7,59594,26331,59601, 8495,59381,    7,59604, 8717,59607,    7,59605,
+ 8647,59611, 8861,59381,  375,59614,    5,56554,26777,59619, 9741,59619,
+ 9745,59619,26781,59619,30349,59619,26857,59619,26933,59619,    2,59619,
+    7,59634,57353,59637,57501,59637,58637,59637,    6,59635, 9777,59619,
+ 1368,59619,57501,59649,57353,59649,58637,59649,57515,59619,57373,59619,
+58663,59619, 9771,59619,40077,59619,31598,59619,55462,59619,50733,59619,
+37519,59619,35690,59619, 8982,59619,55211,59619,  483,59678,  668,59619,
+ 9731,59683,26625,59683, 1419,59619, 9731,59689,26625,59689,   17,59619,
+ 8861,59694,    9,59619,  587,59698, 9731,59701,26625,59701,  375,59619,
+35187,59706,    6,59619,    7,59619,    5,59713,    2,59712,57353,59717,
+57501,59717,58637,59717,    5,59712,58396,59725,59717,59727,35187,59725,
+56555,59730,59717,59733,56555,59725,35187,59736,59717,59739,    7,59618,
+ 3867,59743, 8277,59743, 3997,59743, 4067,59743, 9459,59743, 8953,59743,
+31103,59619,26625,59756,  483,59619,55211,59760,  587,59619,    9,59764,
+ 9731,59767,26625,59767,35187,59619,  375,59772,26625,59619,31103,59776,
+ 8861,59619,    7,59781,   17,59780,    6,56554,36633,59787,36627,59787,
+    1,59787,    4,59792,57253,59795,57381,59795,57577,59795,59109,59795,
+    5,59792,38304,59787,39987,59787,36544,59787, 9875,59811,20501,59811,
+   11,59787,35187,59816,20501,59819, 9875,59819,    5,59787,    1,59824,
+    4,59787,    6,59829, 1369,59831,56555,59833,    1,59828,57253,59837,
+57381,59837,57577,59837,59109,59837,59835,59837,    6,59828,58930,59849,
+59837,59851,  587,59849,56555,59854,59837,59857,56555,59849,  587,59860,
+59837,59863,35187,59787,   11,59866,20501,59869, 9875,59869,    7,56554,
+ 4904,59875,17586,59875,17609,59875,40685,59875,40039,59875,42991,59875,
+ 9484,59875,  272,59875, 1476,59875,  280,59875,  949,59875, 1517,59875,
+ 1197,59875, 4903,59875,    9,59902,17579,59875,    9,59906,   11,59875,
+ 9377,59910,    9,59875, 4903,59914,17579,59914,  253,59875,  265,59920,
+   53,59875,  265,59924, 1471,59875,  265,59928,    5,59874, 3867,59933,
+ 8277,59933, 4067,59933, 3997,59933, 8953,59933, 9459,59933,  265,59875,
+  253,59946, 1471,59946,   53,59946, 9377,59875,   11,59954,    5,59955,
+    7,56555,59826,59960,59827,59961,59963,59965,59827,59960,59826,59961,
+59969,59971,59804,59960,59805,59961,59975,59977,59805,59960,59804,59961,
+59981,59983,21036,59960,14072,59960,14073,59960,14072,59961,59991,59993,
+59183,59960,59191,59997,59183,59961,59185,60001, 4970,59960, 4971,59960,
+ 4970,59961,60007,60009,16169,59961, 9617,60013,39786,59961,59807,59961,
+59806,59961,28715,59960,28791,60023,29731,60023,29659,60023,29041,60023,
+21036,59961,21037,59960,60033,60035,38304,59961,59787,60038,  483,60038,
+38304,59960,60019,60045,59787,60045,  483,60045,18967,59961,    5,60053,
+    5,60052,    2,59961,    0,60059,56555,60061,    5,60063,59961,60065,
+    7,60064,60067,60069,59960,60065,    6,60064,60073,60075,    1,59961,
+    3,60079,    5,60081,56555,60082,56555,60081,    5,60086,    5,60087,
+ 1011,60079,56555,60093,    5,60079,    1,59960,21036,60099,    3,60099,
+56555,60103,    5,60105,    5,60104,    5,60103,56555,60110,    5,60099,
+18967,60114,18967,60099,    5,60118,    5,60119,    2,59960,59811,60125,
+36545,60125,59787,60129,59819,60125,59869,60125,   15,60125,29659,59961,
+29077,60139,39787,59961,60045,60143,32103,59961,41746,59961,26106,59961,
+ 8800,59961,36526,59960,40920,59960, 1163,59961,41019,59961,   11,60160,
+35187,60161,59619,59961, 4971,59961,60005,60169,14073,59961,59989,60173,
+ 4555,59961,  559,59961,   39,59961, 8495,59961,35187,60183,   11,60182,
+15029,59960,  375,60189,17125,59960,38305,60192,   11,59961,41019,60196,
+25793,60196, 8495,60196,  265,59961, 3447,60205,10831,60205,  305,60205,
+17125,60205,11731,60205,  567,59961,46863,60217,   15,59961, 3651,60221,
+ 1993,60221, 4903,60221,17579,60221,  241,59960,38305,59960,60017,60233,
+60021,60233,60041,60233,60043,60233,60039,60233,59787,60243,  483,60243,
+17125,60232, 1011,59960,59279,60251,21037,59961,59987,60255,   11,60255,
+28715,59961,29533,60261,20273,60261, 9617,60261,35187,59960,25793,60269,
+41019,60269, 8495,60269,58715,60269,  265,60268,  265,59960,  331,60281,
+35187,60280,38305,59961,37845,60287,37844,60286,60289,60291,37844,60287,
+37845,60286,60295,60297,60048,60287,59787,60287,60045,60302,60050,60287,
+60045,60287,59787,60308,  483,60308,  483,60287,60045,60314, 1011,59961,
+25793,59961,35187,60321,   11,60320,    4,59960,60091,60327,60107,60327,
+60033,60327,60101,60327,59337,60327,58191,60327,58211,60327,60057,60327,
+60117,60327,60121,60327,21549,60327,21105,60327,19625,60327,58887,60327,
+17591,60327,    5,59960,    1,60359,    3,60361,60205,60363,60255,60359,
+    4,59961,60085,60369,60089,60369,60113,60369,60109,60369,57685,60369,
+59335,60369,58201,60369,58221,60369,57775,60369,57777,60369,60095,60369,
+60055,60369,60123,60369,31103,60369,21575,60369,58881,60369,58009,60369,
+17579,60369, 4903,60369,48408,60369,46863,60369,  483,60410,  483,60369,
+46863,60414,    5,59961,18967,60418,60327,60421, 1368,60419,    2,60419,
+    7,60426,    7,60419,    2,60430,59787,59961,38304,60435,60287,60437,
+38304,60434,60233,60441,  483,59961,38304,60445,60287,60447,38304,60444,
+60233,60451,    5,56555,60081,60454,60369,60457,60103,60454,60369,60461,
+    1,60455,    3,60464,    1,60454,59491,60469,59490,60469,59381,60469,
+    7,60474,    7,60475,    5,60469,59961,60481,    6,60468,60473,60485,
+60477,60485,    7,60468,60471,60491,59381,60491,    6,60469,59381,60497,
+60491,60498,60479,60497,60494,60497,60491,60497,59381,60506,    7,60469,
+59381,60510,60485,60513,60485,60511,59381,60517,    2,60454,60261,60521,
+60483,60521,53813,60455,  483,60527,52915,60455,46863,60531,59875,60455,
+ 9801,60454,60369,60537,48735,60454,60369,60541,10107,60455,  483,60545,
+ 9195,60455,46863,60549,54295,60454,60369,60553,  587,60455,17455,60557,
+11731,60557,    9,60455, 8861,60563,   17,60455,  587,60567,26625,60569,
+ 9731,60569,60467,60569,  483,60454,53813,60577,10107,60577,20763,60455,
+46863,60583,46863,60454,27021,60587,52915,60587, 9195,60587,20763,60587,
+ 1275,60454,60369,60597,  587,60454,25519,60601,27021,60455,46863,60605,
+    6,60454,38881,60609,59381,60455,30091,60455,31103,60615,    4,56555,
+    2,60619,    0,60621,56555,60623,    5,60625,    7,60621,60627,60629,
+    1,60618,59689,60633, 1418,60633,59619,60637,59683,60633,  669,60633,
+59619,60643,60569,60633,59701,60633,59767,60633,   15,60633, 1369,60652,
+59619,60655, 1369,60633,   15,60658,59619,60661,  842,60619, 9377,60665,
+59787,60619, 9377,60618,  483,60671,  587,60619,  483,60674, 9377,60677,
+ 9377,60675,  483,60681,21527,60619,    9,60685,31103,60619,  587,60689,
+  587,60618, 9366,60693, 9195,60693,  483,60696,  483,60693, 9195,60700,
+31103,60693,  483,60619,  587,60706, 9377,60709, 9377,60707,  587,60707,
+ 9195,60715,    7,60618,59337,60719,58191,60719,58211,60719,21105,60719,
+21549,60719,19625,60719,58887,60719,17591,60719,    6,60619,    1,60737,
+    4,60738,    4,60737,    1,60742, 1369,60737,56555,60747,60741,60749,
+60745,60749,    7,60619,    2,60755,21183,60755, 9377,60755,59619,60619,
+38305,60619,    3,60764,    2,60764,56555,60765,    6,60770,60769,60773,
+    6,60765,56555,60776,60769,60779, 1011,60619,46862,60782,46862,60783,
+46863,60783,60785,60789,46863,60782,60787,60793,    6,56555,36303,60797,
+36302,60796,60799,60801,36303,60796,36302,60797,60805,60807,40946,60796,
+40946,60797,60765,60796,60769,60815,    2,60797,    0,60818,40947,60796,
+60813,60823,40947,60797,60811,60827,60765,60797,60767,60831,59381,60797,
+   17,60797,35187,60837,20501,60839,60125,60839,60821,60839, 9875,60839,
+35187,60796,58723,60849,    5,60796,38881,60853,    0,    3, 8169,60857,
+ 8028,60857, 8173,60857, 8214,60857, 8167,60857, 8154,60857, 8026,60857,
+ 8054,60857,17728,60857,60210,60857,60283,60857,58128,60857,58023,60857,
+57476,60857,56854,60857,56856,60857,58901,60857,58906,60857,58122,60857,
+58066,60857,56810,60857,56822,60857,16743,60857,16696,60857, 4810,60857,
+16745,60857,16729,60857,16714,60857, 6648,60857, 2079,60857,  375,60916,
+ 2086,60857,16733,60857,16565,60857,16683,60924,16692,60857,16735,60857,
+16739,60857,51942,60857,44534,60857,42383,60857,44243,60938,44440,60857,
+16747,60857,   75,60857, 6625,60946, 6632,60857, 6645,60857,60079,60857,
+    5,60955,60327,60957,    5,60954,60369,60961,60096,60857,60369,60965,
+ 1325,60856,40829,60969, 1173,60857,17591,60856,17603,60975,10039,60857,
+ 1275,60979,10041,60981,38560,60857, 1205,60985, 1203,60857,38305,60988,
+ 1205,60991,38514,60857, 1007,60995,40741,60856,40829,60999,  531,60856,
+ 1290,60856,    0,61005,    5,61006,    5,61005,    0,61010,40769,60856,
+40829,61015,38548,60857, 1325,61019,  177,60857,38305,61022,   59,61025,
+17053,60857,  483,61028,10081,61031, 1009,60857,38305,61034, 1007,61037,
+ 1365,60857,38305,61040, 1325,61043,38566,60857,   59,61047,17054,60857,
+10081,61051,42109,60857,38305,61054,42103,61057, 9527,60857,  483,61060,
+ 9525,61063,42110,60857,42103,61067, 9528,60857, 9525,61071,  386,60857,
+56555,61074, 8150,60857,  113,61078,  347,60857,56555,61082,58905,60857,
+  375,61086,45432,60857,56555,61090,43099,60857,56555,61094,40829,60857,
+ 1325,61099,40741,61099,40769,61099,60535,60857,    9,61107,57916,60857,
+    9,61111,57851,60857,    9,61115,17727,60857,  113,61118,57060,60857,
+ 8309,60857,60230,60857,57986,60857,57998,60857,60268,60857,58352,60857,
+58704,60857,13820,60857,13772,60857,57994,60857,58056,60857,42155,61144,
+36101,60857,  375,61149,37407,60857,47392,60857,36532,60857,36536,60857,
+57284,60857,58760,60857,58762,60857,58846,60857,58372,60857,57278,60857,
+57996,60857,57470,60857,  305,61174,60205,60857,  305,61178,58374,60857,
+58830,60857,57586,60857,57480,60857,57230,60857,57568,60857,40684,60857,
+36542,60857,  375,61197,42990,60857,40038,60857,37498,60857,36754,60857,
+35796,60857, 8225,60857, 8242,60857,  128,60857, 7971,61214,  101,60857,
+ 7971,61218,37362,60857,48122,60857,12526,60857, 6698,60857,47690,60857,
+38704,60857,11943,60857,    9,61235,12343,60857,    5,61239,    4,61238,
+61241,61243,    4,61239,    5,61238,61247,61249,40132,60857,  331,61253,
+   59,61253,   97,61253, 1325,61253, 8148,60857,48753,61263,10081,61263,
+11759,61263,39044,60857,  331,61271, 1325,61271,  571,61271,   59,61271,
+42338,60857,48753,61281,44451,61281,10081,61281,42959,60857,48753,61289,
+44451,61289,42825,61289,10081,61289,  629,60857,56555,61298,38305,61298,
+  289,60857,  587,61305,10287,60857,17660,60857,10262,60857,40130,60857,
+  331,61315,   59,61315, 1325,61315,53780,60857,48753,61323,10081,61323,
+60668,60857,    9,61329, 8213,60857,    9,61332,11813,60857,    9,61337,
+17030,60857, 8211,60857, 8301,60857, 8209,60857,38110,60857, 8052,60857,
+    9,61350,10464,60857,    9,61355,10527,60857,    9,61359, 4727,60857,
+    9,61363,11989,60857,   11,61367,    5,61368,    6,61367,    5,61372,
+    5,61367,    6,61376,    6,61377,    7,61367,61381,61383,   15,61367,
+    6,61366,61387,61389,   14,61367,    7,61366,61379,61395,61375,61395,
+61371,61395,61393,61395,12371,60857,    5,61405,    4,61405,   12,61405,
+   13,61404,61411,61413,   13,61405,   12,61404,61417,61419,    5,61404,
+61409,61423,    4,61404,61407,61427, 6625,60857,44243,61430,  375,61430,
+   75,61430,    9,61431, 6685,60857,  483,61440,46863,61440,17060,60857,
+35768,60857,50524,60857,52806,60857,50480,60857,36296,60857,50990,60857,
+  510,60857,56555,61460,47608,60857,36293,60857,  483,61466,  295,60857,
+49713,61470, 1291,60857,61009,61475,61013,61475,20033,61475, 1831,61475,
+ 1881,61475,19319,61475,    4,61475,19317,61489,15899,61475, 4579,61475,
+48561,60857,    9,61497,  922,60857,56555,61500,51937,60857,  375,61504,
+57915,60857,57859,61508,    9,61511,39234,60857,60853,61515,60609,61515,
+ 9525,61515,42103,61515, 9517,61515,41989,61515,39485,61515,39481,61515,
+57855,61515, 9519,61515,41995,61515,39487,61515,   15,61515, 9513,61541,
+41941,61541,39477,61541,50958,60857,    9,61548,35761,60857,    9,61552,
+35719,60857,  375,61557,57482,60857,57852,61561,57811,61561,    9,61564,
+    9,61561,57811,61568,57522,60857,  483,61572,46863,61572, 1072,60857,
+ 1108,60857,49713,61580,  524,60857,    4,61585,19301,61587,19311,61585,
+ 3195,61585, 1965,61585,15899,61585, 4579,61585,40704,60857,    7,61601,
+40799,61603,40813,61601, 7961,61601, 7951,61601, 7953,61601,35893,61601,
+37897,61601,38299,61601, 1275,61601, 7947,61621,52756,60857, 1011,61624,
+10245,60857,37339,60857,   33,60857,10385,61632,    9,61635, 7971,60857,
+  101,61638,  128,61638,    9,61638,  113,61644,  483,61638,48753,61649,
+10081,61649,11759,61649,  113,61638,    9,61656,   21,60857,38305,61660,
+  331,61663,   59,61663,   97,61663, 1325,61663,47640,60857,56555,61672,
+17635,60857,12377,61676,11731,60857,13737,61680,  567,60857,46863,61685,
+55211,60857,44243,60857, 6625,61690,42383,61690,58116,61690,42155,61690,
+56555,61698,56555,61690,42155,61702, 1505,60857,38057,61706,  288,60857,
+46863,61711,48466,60857,56555,61714,   11,60857,  340,61719,  341,61719,
+  264,61718,61721,61725,    7,61719,  265,61728,61725,61731,  265,61729,
+  264,61719,61735,61737,56555,61719,57859,61741,    9,61743,  483,61718,
+ 4579,61747,15899,61747, 3195,61747, 1965,61747,  265,61719,    7,61756,
+61725,61759,56555,61718,57852,61763,57811,61763,    9,61766,    9,61763,
+57811,61770,  265,61718,61723,61775,46863,61775,    9,60857, 8213,61780,
+ 8052,61780, 7971,61780,  113,61786,36527,61780,58782,61780,58362,61780,
+ 8241,61780,  113,61780, 7971,61798,35761,61780,50958,61780,  483,61780,
+56555,61806, 1011,61780,49713,61810,38305,61780,38299,61815,37897,61815,
+ 7961,61815, 7951,61815,35893,61815, 7953,61815, 1275,61815, 7947,61829,
+49713,61780, 1011,61832,56555,61780,46863,61836,  483,61836,46863,61780,
+56555,61842, 7563,60857, 1275,61847, 7565,61849, 7569,61849, 7573,61849,
+ 7065,60857,35187,61857,10089,60857,   16,61861,   16,61860,   17,61861,
+61865,61867,   17,61860,61863,61871,10257,60857,  903,61874, 8241,60857,
+    9,61878, 3255,60857,    9,61883,48789,60857,   16,61887,   16,61886,
+   17,61887,61891,61893,   17,61886,61889,61897,37357,60857,  903,61900,
+ 3499,60857,    9,61905, 3445,60857,    9,61909,38184,60857,  375,61913,
+16722,60857,16543,61917,16679,61917,16537,61917,35187,61916,13922,60857,
+13753,61927, 4805,60857,  375,61930,16683,60857,16565,61934,  375,61934,
+ 6515,60857,    9,61941,59824,60857,60369,61945,    9,61945, 9520,60857,
+    9,61951,16711,60857,16659,61954,    8,60856,    3,61959,    6,61960,
+61601,61963,61815,61963,    6,61959,    3,61968,61601,61971,61815,61971,
+61829,61959,61621,61959, 1274,61959,61815,61981,61601,61981,   16,60856,
+   10,60856,    5,61989,    0,61990,61585,61993,61747,61993,    0,61989,
+    5,61998,61585,62001,61747,62001,57811,61989,59933,61989,59743,61989,
+ 8093,61989, 3837,61989,39619,61989,51421,61989,53703,61989,42435,61989,
+ 4287,61989, 4303,61989,53487,61989,42113,61989, 9839,61989, 9579,61989,
+    9,61989,  113,62036,  128,61989,  101,61989,  113,61989,    9,62044,
+57859,60857,57915,62048,    9,62051,    9,62049,57915,62055,   11,60856,
+  483,62059,    9,60856,57889,62063, 5185,62063,11243,62063,12557,62063,
+11251,62063, 5177,62063,   16,60857,57293,62077,35603,62077,58669,62077,
+59079,62077,55005,62077,   17,60856,61685,62089,  483,62089,   15,60856,
+40829,62095,   10,60857,21183,62099,  759,62099,   47,62099,  959,62099,
+  203,62099,  107,62099,   85,62099,   67,62099,    9,62115,  113,60857,
+ 8150,62118,17727,62118,13737,62118,    9,62118, 7971,62126,17025,62118,
+ 7971,62118,    9,62132,10385,60857,    9,62137,   33,62139,   33,62136,
+    9,62143,  165,60857,17049,62146,17025,60857, 1275,62151, 7947,62153,
+48739,62153,17637,62153,17029,62153,37241,62153,  113,62150,17049,60857,
+  165,62166,10247,60857,37347,60857,10249,60857,16659,60857,16711,62176,
+37408,60857,56555,62180,16531,62180,  340,60857,51803,62187,  331,62187,
+ 1325,62187,   59,62187,52439,60857,56555,62196,52563,60857,  265,62201,
+ 1413,60857,56555,62204,  256,60857,56555,62208,38305,62208,  566,60857,
+61987,62215, 9377,62215,37325,62215,10219,62215,  959,62215,   47,62215,
+  759,62215,  587,62215,20763,62215,42810,60857,43073,62235,42827,62235,
+58703,62235,60849,62235,58027,62235,42821,62235, 1325,62235,   59,62235,
+  331,62235,  265,62235,42613,62235,56555,62257,  241,62234,  580,60857,
+20033,62263,59143,62263,60601,62263,58029,62263,55210,60857,31103,62273,
+37375,60857, 1347,60857,37409,60857,  375,62280,  375,60857,58905,62284,
+16683,62284, 4805,62284,58126,62284, 6625,62284, 2079,62284,51937,62284,
+  305,62284,56555,62300,56555,62284,  305,62304,37409,62284,  803,60857,
+37608,60857,  305,60857,60205,62314,57470,62314,  375,62314,56555,62320,
+56555,62314,  375,62324,58116,60857,44243,62328,58126,60857,  375,62332,
+42155,60857,58056,62336,44243,62336,56555,62340,  483,62336,48753,62345,
+44451,62345,10081,62345,56555,62336,44243,62352,53517,60857,  483,62356,
+48753,62359,10081,62359,  251,60857,38305,62364,  331,62367, 1325,62367,
+   59,62367,  555,60857,38305,62374,  331,62377, 1325,62377,  571,62377,
+   59,62377,60612,60857,    7,62387,36273,60857,    7,62391,59787,60857,
+60619,62394,    9,62397,    5,62394,60369,62401,    9,62401,    5,62395,
+60327,62407,60719,62407,57901,62407,   17,62407,59381,60857,60455,62416,
+    7,62419, 9513,60857,    5,62423,   17,62425,    5,62422,    9,62429,
+58362,60857,  903,62432,    9,62432,58348,60857,    7,62438,58782,60857,
+  903,62442,    9,62442,58396,60857,    7,62448,58742,60857,    9,62453,
+  483,62452,46863,62452,60763,60857,    7,62461,  903,60857,58782,62464,
+58362,62464,37357,62464,10257,62464,  483,62464,56555,62474,46863,62464,
+56555,62478,56555,62464,    9,62483,46863,62482,  483,62482,38057,62464,
+    7,62491,  265,60857,46863,62495,   11,62497,   11,62494,46863,62501,
+    7,62494,51803,62505,  331,62505, 1325,62505,   59,62505,    7,62495,
+  375,62515,35187,60857,59960,62518,16722,62518,    7,62518,56555,62524,
+16531,62524,56555,62518,    7,62530,16531,62518,    7,62534,46863,60857,
+36527,62538,58742,62538,57522,62538,12377,62538, 6685,62538, 1011,62538,
+  903,62538,56555,62552,    9,62538,56555,62556,56555,62538,  903,62560,
+    9,62560,36527,60857,    7,62567,  331,62569,    9,62566,46863,62566,
+  483,62566,    7,62566,  375,62579,38305,60857,42109,62582,42103,62585,
+ 1205,62583, 1203,62589, 1007,62583, 1009,62593, 1203,62582, 1205,62597,
+ 1009,62582, 1007,62601,  177,62582,   59,62605, 1365,62582, 1325,62609,
+  571,62583,  555,62613,   97,62583,   21,62617,    5,62582,    6,62621,
+    5,62622,62583,62625,    2,62622,62627,62629,    2,62621,    6,62632,
+  482,62621,    3,62582,    6,62639,    3,62640,62583,62643,    4,62640,
+62645,62647,    4,62639,    6,62650,    8,62639,   14,62582,    6,62657,
+    2,62658,    2,62657,    6,62662,  482,62657, 1274,62582,    6,62669,
+    4,62670,    4,62669,    6,62674,    8,62669,  256,62582,  629,62582,
+  555,62582,   59,62685,  331,62685, 1325,62685,  571,62685,   21,62582,
+ 1325,62695,  331,62695,   59,62695,   97,62695, 1325,62583, 1365,62705,
+  251,62705,   21,62705,  555,62705,   59,62583,  177,62715,  251,62715,
+  555,62715,   21,62715,  251,62582,  331,62725,   59,62725, 1325,62725,
+  331,62583,  251,62733,  555,62733,   21,62733,   15,62583,10085,62741,
+10093,62741,62661,62741,62665,62741,40909,62741,62629,62741,62635,62741,
+    3,62741,10087,62741,62637,62741,62667,62741,  483,62741,10081,62765,
+62621,62765,62657,62765, 1275,62583,10005,62773,10041,62773,62673,62773,
+62677,62773,62647,62773,62653,62773,    5,62773,10009,62773,23879,62773,
+31937,62773,30399,62773,62655,62773,62679,62773,    9,62773,10001,62801,
+62639,62801,62669,62801,  483,62582,39485,62809,39481,62809, 9525,62809,
+ 9517,62809,    4,62809,62773,62819,62787,62809,42103,62809,41989,62809,
+ 9519,62809,41995,62809,57855,62809,60853,62809,60609,62809,39487,62809,
+   15,62809, 9513,62841,41941,62841,39477,62841,    9,62582,61971,62849,
+61963,62849, 7961,62849, 7951,62849,    2,62849,62741,62859,62757,62849,
+ 7953,62849,35893,62849,38299,62849,37897,62849,61981,62849, 1275,62849,
+ 7947,62875,61959,62875,    6,62582,    7,62582,58703,62883,58027,62883,
+60849,62883,   59,62883, 1325,62883,  331,62883,  265,62883,42613,62883,
+56555,62899,  241,62882,    7,62583,58715,62905,58056,62905,40799,62905,
+  375,62905,56555,62905,44243,62914,44243,62905,56555,62918,  265,62583,
+  375,62923,62881,62923,  241,62582,    6,62928,    7,62928,    6,62929,
+62933,62935,    7,62929,62931,62939, 1011,60857,52756,62942,46863,62942,
+  483,62942,    9,62942,49713,62950,49713,62942,    9,62954,    7,62943,
+10107,62959,53813,62959,49713,60857,22807,62965, 1108,62964,  295,62964,
+    9,62964, 1011,62972, 1011,62964,    9,62976,    4,62964,31103,62981,
+  241,60857,59960,62984,42810,62984,    7,62984,56555,62990,38305,62990,
+56555,62984,    7,62996,38305,62984,    6,63000,    7,63000,    6,63001,
+63005,63007,    7,63001,63003,63011,  483,60857, 9527,63014, 9525,63017,
+17053,63014,10081,63021,11759,63015, 7971,63025,44451,63015,42155,63029,
+    0,63014,    5,63033,    0,63034,63015,63037,    7,63034,63039,63041,
+    7,63033,    5,63044,   10,63033,    6,63014,    5,63051,    6,63052,
+63015,63055,    1,63052,63057,63059,    1,63051,    5,63062,38304,63051,
+   14,63014,    5,63069,    1,63070,    1,63069,    5,63074,38304,63069,
+36527,63014,58742,63014,57522,63014,12377,63014, 6685,63014, 7971,63014,
+48753,63091,10081,63091,11759,63091,42155,63014,10081,63099,48753,63099,
+44451,63099,10081,63015,17053,63107,53517,63107,42155,63107, 7971,63107,
+53517,63014,48753,63117,10081,63117,48753,63015,53517,63123, 7971,63123,
+42155,63123,36293,63014,   17,63015,   11,63015,    9,63014,56555,63136,
+   15,63015, 1995,63141, 3755,63141,63073,63141,63077,63141, 5303,63141,
+63059,63141,63065,63141,    0,63141,38403,63141,39943,63141, 4917,63141,
+17013,63141,63067,63141,63079,63141,38305,63141,   59,63171,63051,63171,
+63069,63171,  903,63014,56555,63178, 1011,63014,   11,63014,61993,63185,
+62001,63185, 3195,63185, 1965,63185,    1,63185,63141,63195,63157,63185,
+ 4579,63185,15899,63185,38305,63014,39481,63205,39485,63205,42103,63205,
+41989,63205,    7,63205, 9525,63205, 9517,63205,41995,63205, 9519,63205,
+57855,63205,60609,63205,60853,63205,39487,63205,   15,63205,41941,63233,
+ 9513,63233,39477,63233,    4,63014,20033,63241,59143,63241,60601,63241,
+58029,63241,63133,63241,    5,63014,61987,63253, 9377,63253,37325,63253,
+10219,63253,  959,63253,   47,63253,  759,63253,  587,63253,20763,63253,
+    4,63015,    7,63272,63253,63275,20029,63273,59147,63273,21103,63273,
+19781,63273,19301,63273,62773,63273,    5,63015,  803,63291,56555,63014,
+  903,63294,    9,63294,40674,60857,    6,63300,    7,63300,    6,63301,
+63305,63307,    7,63301,63303,63311,38266,60857,    7,63315,36752,60857,
+    7,63318,16937,60857,  580,63322,  483,63322,    4,63327,    4,63326,
+49631,63322,49630,63322,  581,63322,    4,63322,  483,63338,46863,63338,
+    5,63322,63329,63345,    4,63323,63333,63349,63337,63349,    5,63323,
+63335,63355,63325,63355,63331,63355,63341,63355,63343,63355,46863,63322,
+    4,63366,63355,63369,    4,63367,63345,63373,38057,60857,    5,63376,
+    6,63379,    6,63378,   14,63376,   15,63376, 1505,63376,    6,63376,
+    5,63390,    7,63376,63381,63395,  375,63395,    6,63377,63387,63401,
+    7,63377,63393,63405,63383,63405,38161,63405,   59,63405,63385,63405,
+  331,63405, 1325,63405,  265,63405,  903,63376,    7,63423,16531,60857,
+ 1275,63427,16711,63429,37408,63426,    7,63426,16543,63435,16679,63435,
+16537,63435,35187,63434,    7,63427,16565,63445,35187,63426,    7,63448,
+12377,60857,    9,63453,46863,63452,  483,63452,17635,63452,13737,60857,
+  113,63462,11731,63462,    5,63462,13753,63469,    5,63463,13751,63473,
+13917,63473,13743,63473,60619,60857,59787,63480,    9,63483,60455,60857,
+59381,63486,    7,63489,    5,60856,45491,63493,42800,63493,59694,63493,
+10374,63493,60563,63493, 9606,63493,42134,63493,  629,63493,  705,63493,
+  101,63493,  299,63493,  828,63493,  128,63493,  394,63493,48122,63493,
+  803,63493,  483,63524,42613,63493,   17,63528,51992,63493,  375,63493,
+  241,63534,49713,63534,10291,63493,   17,63540,  256,63493,  113,63493,
+    9,63546,   17,63493,42613,63550,10291,63550,59619,63550, 9565,63550,
+41941,63550,    9,63493,  113,63562,    7,63493,21605,63567,  241,63566,
+    7,63492,59933,63573,59743,63573,57811,63573, 8093,63573, 3837,63573,
+53703,63573, 4287,63573,42435,63573, 4303,63573,53487,63573, 9839,63573,
+42113,63573, 9579,63573,39619,63573,51421,63573,31103,63493,46863,63493,
+12377,63606,  483,63493,  803,63610,49713,63493,  375,63614,56555,63493,
+    5,63619,    6,63621,    6,63620,   14,63619,   15,63619,    6,63618,
+63629,63631,    7,63618,63625,63635,63627,63635,    7,63619,63623,63641,
+    6,63619,    5,63644,63635,63647,  241,63493,  375,63650,    7,63650,
+59619,63493,    7,63657,   17,63656,12377,63493,46863,63662, 9565,63493,
+    7,63667,   17,63666,41941,63493,    7,63673,   17,63672,    4,60856,
+20305,63679, 9641,63679, 9645,63679,20309,63679,21081,63679,20323,63679,
+20387,63679,    3,63679,    6,63694,61601,63697,61815,63697,62849,63697,
+    6,63695, 9701,63679, 1274,63679,61815,63709,61601,63709,62849,63709,
+61829,63679,61621,63679,62875,63679, 9719,63679,43005,63679,58056,63679,
+  386,63679,  347,63679,  767,63679,31103,63733,  524,63679, 9617,63737,
+20273,63737, 1291,63679, 9617,63743,20273,63743,  305,63679,  375,63748,
+  375,63679,  305,63752,44243,63679,56555,63756,   11,63679,  483,63760,
+ 9617,63763,20273,63763,    7,63679,38305,63769,56555,63771,    6,63679,
+    4,63775,    3,63774,61601,63779,61815,63779,62849,63779,    4,63774,
+62582,63787,63779,63789,38305,63787,60857,63792,63779,63795,60857,63787,
+38305,63798,63779,63801,    7,63678,63253,63805,62215,63805,  483,63679,
+   11,63810, 9617,63813,20273,63813,56555,63679,44243,63818,    7,60856,
+40787,63823,40793,63823,    0,63823,    5,63828,61475,63831,61585,63831,
+61747,63831,63185,63831,36001,63823,26106,63823,32103,63823,41746,63823,
+43005,63823, 8800,63823,59910,63823,36539,63823,37595,63823,36049,63823,
+63253,63823,62215,63823,61305,63823,48975,63823,48245,63823,48451,63823,
+60707,63823,  386,63823,  347,63823,  510,63823,60755,63823, 9852,63823,
+53500,63823,36041,63823,37573,63823,36275,63823,  375,63823,  305,63892,
+  273,63823,  281,63823, 1477,63823, 1516,63823,  948,63823,40704,63823,
+10001,63907,27533,63907, 8495,63823,   11,63912,48885,63823,  483,63917,
+41019,63823,   11,63920,  567,63823,63493,63925,  165,63823,  903,63928,
+   11,63823,25793,63932,41019,63932, 8495,63932,59875,63932, 9805,63932,
+53391,63932,60618,63823,  483,63947,    9,63823,  483,63950,38305,63950,
+27533,63955,10001,63955, 1505,63823, 1011,63960,  305,63823,  375,63964,
+    4,63823,63610,63969,63291,63969,63493,63969,  483,63974,  483,63969,
+63493,63978,56555,63968,  483,63983,    5,63823,    7,63987, 1275,63989,
+60857,63991,    0,63986,61475,63995,61585,63995,61747,63995,63185,63995,
+63993,63995,    7,63986,63014,64007,63995,64009,  483,64007,60857,64012,
+63995,64015,60857,64007,  483,64018,63995,64021,    4,63822,63253,64025,
+62215,64025,    5,63822,59743,64031,59933,64031,57811,64031, 8093,64031,
+ 3837,64031,42435,64031, 4303,64031,53703,64031, 4287,64031,42113,64031,
+ 9579,64031,53487,64031, 9839,64031,51421,64031,39619,64031,25793,63823,
+   11,64062,  903,63823,  165,64066,38305,63823,    9,64070,27533,64073,
+10001,64073, 1011,63823, 1505,64078,56555,63823,    4,64082,  483,64085,
+  483,63823,    9,64088,59875,63823,   11,64092,    5,64093, 9805,63823,
+   11,64098,    5,64099,53391,63823,   11,64104,    5,64105,    6,60856,
+60454,64111,60369,64113,    5,64111,56555,64116,60369,64119,56555,64111,
+   17,64122,    4,64122,    7,64126,    5,64122,60369,64131,    5,64123,
+60327,64135,60719,64135,64129,64135,57901,64135,    4,64123,64125,64145,
+    7,60857,16539,64149,16683,64151,  264,64149,  264,64148,    3,64149,
+16530,64158,16530,64159,    1,64158,58396,64148,58348,64148,36527,64148,
+  375,64171,40674,64148,36752,64148,  331,64149, 1325,64149,   59,64149,
+38057,64148,  375,64185,16531,64148,64161,64189,16543,64189,16679,64189,
+16537,64189,35187,64188,   17,64149,  241,64201,38305,64149,42383,64205,
+ 6625,64205,58116,64205,42155,64205,56555,64212,56555,64205,42155,64216,
+16531,64149,64163,64221,16659,64221,48885,64149,56555,64227,   15,64149,
+  483,64231,38305,64231,27533,64235,64165,64235,10001,64235,35187,64148,
+56555,64242,16531,64242,  265,64148,64155,64249,51803,64249,  331,64249,
+ 1325,64249,   59,64249,  241,64148,56555,64260,38305,64260,38305,64148,
+58703,64267,58027,64267,60849,64267,   59,64267, 1325,64267,  331,64267,
+  265,64267,42613,64267,56555,64283,  241,64266,  265,64149,64157,64289,
+41941,64289,51229,64289, 4213,64289, 8757,64289, 9565,64289,59619,64289,
+  305,64289,  713,64289,   25,64289, 8165,64289, 9617,64289,20273,64289,
+    4,64148,57293,64317,35603,64317,58669,64317,59079,64317,55005,64317,
+    5,64148,    3,64329,    1,64331,64205,64333,21183,64329,  759,64329,
+   47,64329,  959,64329,    4,64149,43053,64345,54985,64345,54129,64345,
+51601,64345,58782,64345,46863,64345,56555,64356,56555,64345,46863,64360,
+    5,64149,  803,64365, 1275,64149,    9,64369,56555,64148,25793,64373,
+ 8495,64373,41019,64373,35187,64372,  241,64372,59960,60857,25793,64385,
+41019,64385, 8495,64385,  241,64384,35187,64384,    5,60857,60079,64396,
+60369,64399,    0,64396,63743,64403, 1290,64403,63679,64407,63737,64403,
+  525,64403,63679,64413,63763,64403,63813,64403,   17,64403, 1275,64420,
+63679,64423, 1275,64403,   17,64426,63679,64429,    3,64396,    6,64433,
+  759,64397,  483,64437,64025,64397,  483,64441,63823,64397,  483,64445,
+ 9377,64397,  483,64449, 9513,64396,    9,64453,  959,64397,  483,64457,
+37325,64397,  483,64461,   47,64397,  483,64465,10219,64397,  483,64469,
+59787,64396,60369,64473,    9,64473,13737,64396,13753,64479,49713,64397,
+61987,64397,  483,64485,    9,64397,42613,64489,59619,64489,10291,64489,
+ 9565,64489,41941,64489,   17,64397,  113,64501,63805,64397,  483,64505,
+20763,64397,  483,64509,  483,64396,64025,64513,63823,64513,61987,64513,
+63805,64513, 9377,64513,37325,64513,10219,64513,  959,64513,   47,64513,
+  759,64513,  587,64513,20763,64513,  587,64397,  483,64539,    7,64396,
+21183,64543,  759,64543,   47,64543,  959,64543,    6,64397,56555,64553,
+    4,64554,    5,64554,    5,64555,64557,64561,    4,64555,64559,64565,
+    7,64397,    0,64569,    5,64570,    5,64569,    0,64574,21105,64569,
+21549,64569,19625,64569, 1275,64569,60857,64585,64573,64587,64577,64587,
+63679,64397,63705,64593,64435,64593,31103,64593,  375,64593,    7,64593,
+64433,64603,  903,64397,  375,64607,    7,64607,35187,64397,60796,64612,
+60797,64612,31103,64613,60797,64613,64615,64621,  375,64613,60796,64613,
+64617,64627,56555,64397,59787,64631,    9,64633,56555,64396,59914,64637,
+60221,64637,59875,64637,    9,64642,60369,64637,    9,64637,59875,64648,
+60454,60857,59914,64653,60221,64653,59875,64653,    9,64658,60369,64653,
+    9,64653,59875,64664,    4,60857, 8743,64669, 8605,64669, 8672,64669,
+ 8647,64669,  305,64676, 3795,64669,10025,64669,27603,64669,31524,64669,
+31690,64669,31700,64669,63569,64669,46862,64669,    0,64669,    2,64696,
+    6,64696,    6,64697,63604,64669,24655,64669,63534,64669, 8916,64669,
+62092,64669,63133,64669,48408,64669,  713,64669,31103,64718,  305,64669,
+ 8647,64722,31103,64722,   25,64669,31103,64728,  340,64669, 8717,64733,
+ 3785,64733, 8495,64733,  483,64669,62089,64740,46863,64740,  375,64669,
+63493,64746, 8861,64746,62089,64669,  483,64752,   15,64669,  483,64757,
+20273,64759, 9617,64759,64403,64759,64699,64759,31103,64669,  305,64768,
+  713,64768,   25,64768,63493,64768,49713,64769,  483,64668,20033,64781,
+59143,64781,58029,64781,60601,64781,49713,64668,31103,64791,46863,64669,
+  483,64794,    6,64668,64795,64799,    2,64801,    3,64800,64803,64805,
+    3,64801,    2,64800,64809,64811,    7,64668,57293,64815,64695,64815,
+    2,64819,    3,64818,64821,64823,    3,64819,    2,64818,64827,64829,
+64701,64815,    2,64833,    3,64832,64835,64837,    3,64833,    2,64832,
+64841,64843,35603,64815,59079,64815,58669,64815,55005,64815,    6,64669,
+    0,64854,64815,64857,    2,64859,    3,64858,64861,64863,    3,64859,
+    2,64858,64867,64869,    7,64669,60857,64873,  264,64874,  264,64875,
+    1,64873,  264,64880,  264,64881,64703,64873,    2,64887,    3,64886,
+64889,64891,    3,64887,    2,64886,64895,64897,25793,64873,41019,64873,
+ 8495,64873,  305,64905,59875,64873,53391,64873, 9805,64873,38305,64873,
+  483,64915,  265,64872, 8717,64919,64883,64919,64877,64919, 3785,64919,
+ 8495,64919,  265,64873,64885,64931,64879,64931,63493,64931, 8861,64931,
+46863,64931, 8861,64669,  375,64942,63493,64669,31103,64946,  375,64946,
+  265,64669,    7,64952, 8717,64955, 3785,64955, 8495,64955,    7,64953,
+ 8647,64963,56555,64669,59381,64967,    7,64969,56555,64668,31103,64973,
+  375,64973,59712,64973,    7,64973,  265,64981,59619,64980,59619,64973,
+    7,64986,60618,60857,31103,64991,  375,64991,59712,64991,    7,64991,
+  265,64999,59619,64998,59619,64991,    7,65004,    6,60857,  264,65009,
+64746,65011,  375,65011,64669,65014,64931,65011,64669,65011,  375,65020,
+  264,65008,64733,65025,  341,65025,64669,65029,64955,65025,64919,65025,
+    3,65008,  341,65037,64669,65039,63907,65037,40705,65037,63823,65045,
+64235,65037,63955,65037,64073,65037,   17,65037,64953,65009,  375,65057,
+    4,65009, 1274,65061,    3,65061,    6,65064,    6,65061,    3,65068,
+56555,65008,60796,60857,56555,60857,  386,65076,45432,65076,  347,65076,
+43099,65076,60418,65077,60327,65087,59961,65077,    5,65091,60369,65093,
+    5,65090,60327,65097,   18,65076,   12,65076, 1291,65076,48561,65076,
+  525,65076,49630,65076,  580,65076, 1170,65076,37408,65076,  256,65076,
+52439,65076,  629,65076, 1413,65076,47640,65076,  922,65076,49631,65076,
+  581,65076, 1171,65076,44243,65076,42155,65136,  375,65076,  305,65140,
+48466,65076,  510,65076,   13,65077,65103,65149,   19,65077,65101,65153,
+   13,65076,   18,65077,   19,65076,65159,65161,   12,65077,65157,65165,
+57915,65165,   14,65077,57901,65171,60719,65171,60327,65171,65115,65171,
+   17,65171,   10,65077,    9,65183,   16,65076,65171,65187,   10,65076,
+65165,65191,48560,65076,  524,65076, 1290,65076,   11,65076,65149,65201,
+57852,65201,65184,65201,65183,65201,    9,65208,57811,65201,    9,65212,
+    9,65201,65183,65216,57811,65216,46863,65200,  483,65200,    9,65076,
+  483,65226,46863,65226,   17,65076, 1275,65232,   11,65077,65191,65237,
+    9,65239,57915,65237,    9,65243,    9,65236,65191,65247,57915,65247,
+    9,65077,   11,65253,65183,65255,57811,65255,   11,65252,65191,65261,
+57915,65261,   15,65077,65233,65267,65135,65267,  305,65076,  375,65272,
+42155,65076,44243,65276, 1011,65076,    7,65281,    7,65280,65171,65285,
+   15,65281,  241,65076,    7,65290,  483,65076,    4,65295,    4,65294,
+  903,65294,    9,65294,   11,65294,  903,65076,    9,65307,46863,65306,
+  483,65306,35187,65076,    7,65314, 1275,65076,   17,65318,46863,65076,
+    4,65323,    4,65322,  903,65322,    9,65322,   11,65322,    7,65077,
+    9,65335,   11,65335,  567,65335,    4,65335,  483,65343,    5,65335,
+    5,65334,65343,65349,    4,65334,65347,65353,    6,65076,65350,65357,
+65355,65357,65289,65357,65349,65357,65343,65364,65343,65357,65349,65368,
+   11,65357,65346,65357,65353,65375,    5,65357,65335,65379,65349,65381,
+65335,65378,65353,65385,65335,65357,    4,65389,    5,65389,65343,65393,
+    4,65388,65393,65397,    5,65388,65391,65401,65353,65401,    5,65077,
+60629,65407,59960,65406,59960,65407,38185,65407,57993,65407,65115,65407,
+65113,65407,65111,65407,59961,65406,65413,65425,60327,65425,65197,65407,
+65195,65407,65105,65407,60251,65407,58313,65407,65299,65407,65327,65407,
+65285,65407,65225,65407,65223,65407,65305,65407,65333,65407,56555,65407,
+    7,65454,    7,65455,59961,65407,60359,65461,65411,65461,   11,65461,
+ 1171,65407,65335,65469,65335,65407,65187,65407,57901,65407,60327,65407,
+60719,65407,   17,65407,65335,65483,59875,65483,64385,65407,64373,65407,
+    6,65407,65459,65493,60755,65493,65283,65493,   11,65493,    7,65407,
+56555,65502,    7,65406,65461,65507,65493,65507,    6,65406,65505,65513,
+65457,65513,60719,65513,65413,65513,60327,65513,57901,65513,65187,65513,
+65115,65513,65285,65513,65503,65513,   17,65513,    4,65076,    2,65537,
+    7,65539,65407,65541,65510,65537,65533,65537,65507,65537,65493,65548,
+31103,65537,65493,65537,65507,65554,  483,65536,65407,65559,46863,65536,
+65407,65563,  375,65537,   15,65537,65357,65569,    7,65536,65513,65573,
+65171,65573,65407,65573,59712,65537,65502,65537,65513,65583,    7,65537,
+65493,65587,65407,65587,65507,65591,  265,65587,59619,65586,65407,65586,
+65513,65599,59619,65537,    7,65602,65407,65537,    6,65607,    7,65607,
+65493,65611,    6,65606,65611,65615,    7,65606,65609,65619,65513,65619,
+    4,65077,65135,65625,65133,65625,65131,65625,65372,65625,65199,65625,
+65109,65625,65107,65625,65235,65625,65321,65625,   11,65625,65357,65644,
+65233,65625,65357,65625,   11,65650,65075,65625,65073,65625,    7,65625,
+60455,65625,    7,65661,    5,65076,    2,65664,65625,65667,    1,65664,
+    3,65664,    0,65664,65625,65675,59914,65665,60221,65665,65336,65665,
+65297,65665,65325,65665,59875,65665,    9,65688,65659,65665,65667,65693,
+65675,65693,60369,65665,    9,65665,65335,65700,59875,65700,65335,65665,
+    9,65706,65658,65665,65671,65711,65673,65711,    6,65665,65668,65717,
+65676,65717,65667,65717,65625,65722,65675,65717,65625,65726,65625,65717,
+65667,65730,65675,65730,    7,65665,65671,65737,65625,65739,65673,65737,
+65625,65743,65625,65736,65671,65747,65673,65747,65625,65665,    6,65753,
+    7,65753,    6,65752,65757,65759,    7,65752,65671,65763,65673,65763,
+65755,65763,    6,65077,60619,65771,    9,65773,   17,65771,65625,65777,
+65537,65771,    9,65781,    5,65771,60369,65785,    9,65785,    5,65770,
+65573,65791,60327,65791,60719,65791,57901,65791,65187,65791,65115,65791,
+65285,65791,   17,65791,    7,65076,25793,65809,41019,65809, 8495,65809,
+ 1011,65808,65513,65817,65791,65817,65407,65817,65171,65817,  241,65808,
+35187,65808,   15,65809,65665,65831,65407,65809,   11,65835,    4,65808,
+65791,65839,65513,65839,65171,65839,65407,65839,    4,65809,65785,65849,
+65665,65849,65771,65809,    4,65855,    5,65855,    4,65854,65859,65861,
+    5,65854,65857,65865,    1,    4,49284,65869,49311,65869,48330,65869,
+48279,65869,47548,65869,47076,65869,47078,65869,48581,65869,48584,65869,
+54254,65869,54260,65869,54266,65869,54222,65869, 8672,65869, 8743,65869,
+ 3795,65869, 8605,65869, 8647,65869,  305,65904,27021,65868,31103,65909,
+27377,65910,31894,65909,27377,65909,31103,65916,   21,65868,57577,65921,
+59109,65921,19987,65921,57381,65921,59787,65868,57577,65931,57381,65931,
+57253,65931,59109,65931,15390,65869,15383,65941,44768,65869,44663,65945,
+48284,65869,37897,65949,44243,65869,37845,65953,45411,65955,37845,65952,
+44663,65959,37845,65869,44243,65963,45381,65965,44243,65962,44663,65969,
+46863,65962,37897,65973, 1175,65869,56555,65977, 1177,65979,49215,65869,
+    9,65983,49229,65985,56709,65869, 1009,65989,54641,65869,54643,65993,
+60737,65868,60749,65997,11355,65868,11495,66001,57793,65868,57577,66005,
+57381,66005,59109,66005,59715,65869,56555,66013,59717,66015, 7959,65869,
+    9,66019, 7961,66021,49534,65869,49537,66025,19086,65869, 1203,66029,
+49529,65869,   15,66032,49537,66035,19064,65869, 1009,66039,54668,65869,
+54643,66043, 1205,65869,18967,66046, 1203,66049,19949,65868,19987,66053,
+ 1425,65868,57253,66057,  668,65868,    1,66061,    2,66062,    2,66061,
+    1,66066,56554,66061,58930,65868,    4,66073,    6,66074,    6,66073,
+    4,66078,    8,66073,19965,65868,19987,66085,56745,65868,57253,66089,
+60136,65869,59787,66093,  571,65869,18967,66096,  555,66099,16091,65869,
+   15,66102, 9513,66105,19078,65869,   21,66109,54655,65869,   15,66112,
+54643,66115, 1007,65869,18967,66118, 1009,66121,60125,65869,   15,66124,
+59787,66127,19088,65869,  555,66131,16092,65869, 9513,66135,   97,65869,
+18967,66138,   21,66141,20347,65869,18967,66144,20345,66147,10095,65869,
+   15,66150,10093,66153,20348,65869,20345,66157,10096,65869,10093,66161,
+32468,65869,27323,66165,33442,65869,48368,65869,32469,65869,65909,66173,
+28483,65869,28479,65869,63604,65869,31690,65869,31700,65869,31524,65869,
+31596,65869,32464,65869,53380,65869,25037,65869,24655,65869,25457,65869,
+23005,65869,27603,65869,22591,65869,23105,65869,23357,65869,23113,65869,
+  120,65869,46863,66212,   77,65869,46863,66216,54154,65869,54225,66220,
+56328,65869,58298,65869,58868,65869,52752,65869,52370,65869,58344,65869,
+57253,65869,59787,66237, 1425,66237,56745,66237,19987,65869,   21,66245,
+19949,66245,19965,66245,25215,65869,48583,65869,  113,66254,25459,65869,
+31920,65869,32263,65869,23099,65869,23107,65869,24631,65869,22915,65869,
+22589,65869,65294,65869,65322,65869,63534,65869,54256,65869,54129,66280,
+25305,65869,32295,65869,31796,65869,62092,65869,63133,65869,22785,65869,
+22803,65869,22951,65869,24735,65869,23012,65869,25546,65869,47364,65869,
+25548,65869,62442,65869,63294,65869,62432,65869,62560,65869,57577,65869,
+   21,66319,59787,66319,57793,66319,57381,65869,59787,66327,   21,66327,
+57793,66327,59109,65869,   21,66335,59787,66335,57793,66335,48578,65869,
+   33,66343,48276,65869,   33,66347,49308,65869,   33,66351,59340,65869,
+63135,65869,61464,65869,61580,65869,61578,65869,62946,65869,62950,65869,
+62550,65869,61810,65869,63182,65869,62948,65869,57660,65869,57766,65869,
+62060,65869,57772,65869,22767,65869,19810,65869,  251,66387,  555,66387,
+ 1365,66387,   21,66387, 9994,65869, 9513,66397,16859,66397,59787,66397,
+20620,65869,59787,66405,21529,66405, 9513,66405,19372,65869,  251,66413,
+   21,66413,  177,66413,  555,66413,20823,65869,59787,66423,21529,66423,
+20771,66423, 9513,66423,57971,65869,   21,66433,  251,66433,  177,66433,
+  159,66433,  555,66433,25303,65869,   11,66445,24739,65869,29028,65869,
+57658,65869,57620,65869,48328,65869,  113,66456,19806,65869,  251,66461,
+  555,66461,   21,66461, 8916,65869,54262,65869,46863,66470,54219,65869,
+46863,66474,32556,65869,  759,66479, 7061,65869,    3,66483,    2,66483,
+  842,66483,  843,66482,66489,66491,  843,66483,  842,66482,66495,66497,
+    3,66482,66487,66501,    2,66482,66485,66505,47546,65869,   25,66508,
+49283,65869,   25,66512,47600,65869,48444,65869,47572,65869,62146,65869,
+17476,65869,23010,65869,63184,65869,61584,65869,48558,65869,47408,65869,
+25460,65869,61474,65869,47372,65869,61746,65869,47632,65869,17538,65869,
+47634,65869,47676,65869,48112,65869,47412,65869, 5886,65869,48095,65869,
+ 1072,65869,60857,66560,48408,65869,49713,66564,  241,66564,  587,66565,
+  903,66564,48420,65869,61780,65869, 1011,66576,47640,65869, 1011,66580,
+  483,66580,47590,65869,  483,66586,47672,65869,47368,65869, 1413,65869,
+46863,66594,52692,65869,46863,66598,47370,65869,  922,65869,46863,66604,
+49075,65869,49395,65869,48586,65869,10025,65869, 1281,65869,46863,66616,
+ 1291,65869,60857,66620,  669,65869,66065,66625,66069,66625,40909,66625,
+ 1821,66625, 1879,66625,38973,66625,    3,66625,38971,66639,57911,66625,
+17041,66625, 4897,66625,56739,66625,66071,66625,56555,66625,  671,66653,
+66061,66653,25381,65869,   11,66659,   11,66658,58931,65869,66077,66665,
+66081,66665,58715,66665,58975,66665,58981,66665,59089,66665,    7,66665,
+59079,66679,23879,66665,30399,66665,31937,66665,58983,66665,66083,66665,
+    9,66665,58967,66693,66073,66693,58782,65869,49713,66698,60857,66698,
+   11,66699, 1108,65869,60857,66706,62089,65869,  483,66710, 4802,65869,
+ 5314,65869,17670,65869,17693,65869,62059,65869,  483,66722,47608,65869,
+60857,66726,  903,66726,   11,66727,  587,66726,19474,65869,10093,66737,
+20345,66737,10085,66737,20281,66737,19549,66737,19553,66737,10087,66737,
+20285,66737,19555,66737,  483,66737,20273,66757,10081,66757,19545,66757,
+61718,65869,  483,66764,22957,65869,  903,66768,  587,66768,62538,65869,
+56555,66774, 1011,66774,  288,65869,    9,66781,19916,65869,    7,66785,
+35603,66787,35613,66785,10041,66785,10005,66785,10009,66785,23879,66785,
+30399,66785,31937,66785,    9,66785,10001,66805,63014,65869,56555,66808,
+   11,66809,  587,66809, 1011,66808,   11,66808,48534,65869, 1011,66820,
+ 1418,65869,    3,66825,38903,66827,38913,66825, 3587,66825, 1989,66825,
+56681,66825,57911,66825,17041,66825, 4897,66825,56555,66825, 1471,66845,
+ 1086,65869,46863,66848,  524,65869,60857,66852, 1304,65869,    9,66857,
+ 1530,65869,    9,66861, 9195,65869,31103,66864,10031,65869,27641,65869,
+  713,65869,31103,66872, 1447,65869,13737,66877, 9875,65869,   15,66880,
+ 9513,66883,16859,66883,59787,66883,  803,66881, 1325,65869,18967,66892,
+  251,66895,  555,66895, 1365,66895,   21,66895,16937,65869,46863,66904,
+ 1505,65869,28715,66908, 5438,65869,49162,65869,  113,65869,48583,66916,
+48328,66916,   25,66916,46863,66922,46863,66916,   25,66926,  375,65869,
+63493,66930, 8861,66930,58334,65869,46863,66936,58362,65869,60857,66940,
+  506,65869,46863,66944,  587,65869,  759,66949,31103,66951,31103,66948,
+  759,66955,22957,66948,47608,66948,46863,66948, 1011,66962, 1011,66948,
+46863,66966, 1369,65869,   15,66970, 4897,66973,17041,66973, 3587,66973,
+ 1989,66973,57911,66973,56681,66973,56555,66973, 1471,66987, 1275,66970,
+    9,66991, 1275,65869,18967,66994,31937,66997,30399,66997,10041,66997,
+10005,66997,23879,66997,10009,66997,    9,66997,10001,67011,   11,66994,
+    9,67015,    9,66995,   11,67019, 1369,67019, 1369,66994,    9,67025,
+  483,65869,32805,67028,56156,67028,65076,67028,25545,67028,62089,67028,
+62942,67028,62059,67028,47590,67028,47640,67028,17669,67028, 5313,67028,
+ 4801,67028,  587,67029,46863,67055,61718,67028,49713,67028,46863,67060,
+ 1011,67028,60857,67064,  903,67028,46863,67068,46863,67028,49713,67072,
+  587,67073,  241,67072,  903,67072,60857,67028,56555,67082,  587,67083,
+   11,67083, 1011,67082,   11,67082,   11,67028,60857,67094, 5325,67028,
+56555,67028,60857,67100,  241,67028,46863,67104, 4593,67028,11985,67028,
+ 5843,67028,49155,67028, 5876,65869,49155,65869,  483,67118, 6267,65869,
+    9,67123, 6367,67125, 6403,67125, 6407,67125,60419,65869,56555,67133,
+60425,67135,60429,67135,60433,67135, 5325,65869,  483,67142,55005,65869,
+    9,67147, 5843,65869,56555,67150, 1011,67150,  483,67150,12023,65869,
+11986,65869, 4608,65869,11985,65869,  483,67164, 3681,65869,56555,67168,
+ 3709,65869,56555,67172, 3357,65869,56555,67176,52840,65869, 4593,65869,
+  483,67182,54202,65869,54159,67187,46863,67189, 4801,65869,  483,67192,
+54129,65869,54256,67196,46863,67196,54225,67200,54225,67196,46863,67204,
+17669,65869,  483,67208, 5313,65869,56555,67212,  483,67212,15309,65869,
+  413,67218,15383,67221,  413,67219,15335,67225,54225,65869,54154,67228,
+46863,67228,54129,67232,54129,67228,46863,67236, 1274,65868,    6,67241,
+    4,67242,66785,67245,66997,67245,    4,67241,    6,67250,66785,67253,
+66997,67253,67011,67241,66805,67241,    8,67241,66997,67263,66785,67263,
+ 1368,65868,    1,67269,    2,67270,66825,67273,66973,67273,    2,67269,
+    1,67278,66825,67281,66973,67281,66987,67269,66845,67269,56554,67269,
+66973,67291,66825,67291,  586,65868,24265,67297,28233,67297,29077,67297,
+19559,67297, 8251,67297,20361,67297, 9673,67297,20713,67297, 4283,67297,
+ 9967,67297, 4279,67297, 3807,67297,  482,65869,  903,67323,    1,67325,
+    0,67325,    1,67324,67329,67331,    0,67324,67327,67335,  587,65868,
+31690,67339,31103,67339,  713,67342,  713,67339,31103,67346,48408,67339,
+46863,67339,  483,67352,  483,67339,46863,67356,  483,65868,57577,67361,
+57253,67361,19987,67361,59109,67361,57381,67361, 1369,65868, 1275,65868,
+47953,67375,48062,67375,47961,67375,48009,67380,48009,67375,47961,67384,
+47580,67375,47933,67389,46863,67375,  265,67393,48009,67395,  265,67392,
+47933,67399,  265,67375,46863,67403,47961,67405,46863,67402,47933,67409,
+ 1368,65869,48009,67413,49321,67413,49001,67413,  265,67413,46863,67421,
+  586,65869,58056,67425,58601,67425,40799,67425,44243,67425,56555,67432,
+35927,67425,38155,67425,37611,67425,  375,67425,  510,67425,    9,67425,
+  483,67446,56555,67425,44243,67450,  483,67425,    9,67454,  843,65869,
+    9,67459,15705,65869,    9,67463,10001,67465,13755,67465,15733,67465,
+27533,67465,17455,65869,56555,67474, 1347,67474, 1011,67474,  767,65869,
+56555,67483, 1471,67485,  253,67485,  809,67485,  771,67485,   53,67485,
+ 1347,65869,17455,67496,  567,65869,    9,67501,10033,65869,27691,65869,
+10035,65869,27978,65869,26331,67511,23755,67511,27805,67511,  256,65869,
+25793,67519,59875,67519,41019,67519, 8495,67519,53391,67519, 9805,67519,
+  972,65869,25793,67533,41019,67533, 8495,67533,20762,65869,58715,67541,
+  375,67541,  154,65869,40909,67547,49204,65869,   11,67550,   33,67553,
+   11,67551,   25,67557, 1369,67551,37409,67551,  340,65869,25793,67565,
+41019,67565, 8717,67565, 8495,67565, 3785,67565,49514,65869,   66,65869,
+   33,67579,46863,67581,46863,67578,   33,67585,  112,65869,44243,67589,
+27785,65869,  257,65869,67373,67595,31103,67594,31103,65869,27021,67601,
+27377,67603,27021,67600,27323,67607,   25,67600,  713,67600,  305,67600,
+63493,67600, 8861,67600, 9195,67600,52915,67600, 1369,67601,  587,67601,
+  713,67627,  903,67600,  241,67600,  587,67600,  759,67635,49713,67600,
+  257,67600,  165,65869,60857,67642,31926,65869,27021,65869,27323,67649,
+31103,67651,31103,67648,27323,67655,52915,65869,31103,67658,  305,65869,
+ 8647,67662,31103,67662,   25,65869,49283,67668,47546,67668,31103,67668,
+  113,67668,46863,67676,46863,67668,  113,67680,20501,65869,   15,67684,
+59787,67687,21529,67687, 9513,67687,  803,67685, 1141,65869,13737,67697,
+   33,65869,13737,67701,  331,65869,18967,67704,  251,67707,   21,67707,
+  555,67707,   59,65869,18967,67714,  251,67717,   21,67717,  177,67717,
+  555,67717, 8861,65869,60796,67727,60797,67727,60796,67726,67731,67733,
+31103,67726,60797,67726,67729,67739,  375,67726,63493,65869,60796,67745,
+60797,67745,31103,67744,60797,67744,67747,67753,60796,67744,67749,67757,
+  375,67744,  413,65869,15309,67762,15383,67765,15309,67763,15363,67769,
+46863,67762,32805,65869,    9,67775,  483,67774,46863,67774, 1216,65869,
+46863,67782,65076,65869,    9,67787,  483,67786,46863,67786,56156,65869,
+  483,67794,56555,67794,56555,65869,56156,67800,63014,67800,62538,67800,
+ 3357,67800,17455,67800, 5313,67800, 5843,67800, 3681,67800, 3709,67800,
+46863,67800,49713,67820,60857,67820,   11,67821,49713,67800,46863,67828,
+  483,67800,60857,67832,   11,67801,46863,67837,60857,67800,    9,67841,
+  483,67840,46863,67840,15029,67800,    7,67849,  903,65869,31103,67852,
+22957,67852,47608,67852,48408,67852,46863,67852, 1011,67862,  483,67862,
+  483,67852,46863,67868,    7,67852,25793,67873,41019,67873, 8495,67873,
+ 1011,67852,46863,67880,28715,67852,    7,67885,21605,65869,   15,67889,
+31103,67891,    7,67888,26331,67895,23755,67895,27805,67895,    7,67889,
+26219,67903,49713,65869,58782,67906,48408,67906,  483,67906,46863,67912,
+31103,67906,56555,67906,46863,67918,    3,67907,31103,67923,46863,67906,
+  483,67926,56555,67926,  241,65869,31103,67932,48408,67932,46863,67932,
+  483,67938,  483,67932,46863,67942,    7,67932,25793,67947,59875,67947,
+41019,67947, 8495,67947,53391,67947, 9805,67947,56555,67933,    7,67961,
+    9,65869,25545,67964,62942,67964,60857,67964, 1011,67970, 1011,67964,
+60857,67974,25545,65869,    7,67979,  483,67978,    9,67978,46863,67978,
+46863,65869,37844,67988,37896,67989,37844,67989,    6,67994,37845,67988,
+67993,67999,67997,67999,67995,67999,37897,67999,54262,67988,54219,67988,
+  120,67988,   77,67988,    6,67989,37844,68017,37844,68016,67999,68021,
+32805,67988,37845,67989,68019,68027,67991,68027,37899,68027,37897,67989,
+67991,68035,54129,67988,54225,68038,52692,67988,58334,67988,65076,67988,
+54225,67988,54129,68048,25545,67988,   66,67988,   33,68055,62942,67988,
+   25,67988,  113,68060,  113,67988,   25,68064,  506,67988, 1086,67988,
+ 1281,67988, 1216,67988,  413,67988,  922,67988, 1413,67988,16937,67988,
+  587,67989,  483,68085,  483,67988,49713,68088,  241,68088,  587,68089,
+  903,68088,  241,67988,  483,68098,  903,67988, 1011,68102,  483,68102,
+ 1275,67989,56555,67988,49713,68110,60857,68110,   11,68111,60857,67988,
+56555,68118, 1011,68118, 1011,67988,60857,68124,  903,68124,   11,68125,
+  587,68124,  587,67988, 1011,68134,    2,67988,    3,67988,   11,68140,
+   33,68143,   11,68141,   25,68147, 1369,68141,37409,68141,    2,67989,
+    3,67989,  483,68157,49713,67988,56555,68160,  483,68160,   11,67988,
+    3,68166,   33,68169,    3,68167,  113,68173,   15,65869,10095,68176,
+10093,68179,54643,68177,54655,68183,49537,68177,49529,68187,54655,68176,
+54643,68191,49529,68176,49537,68195,16091,68176, 9513,68199,60125,68176,
+59787,68203,16859,68177, 9875,68207,21529,68177,20501,68211,    1,68176,
+    2,68215,    1,68216,68177,68219,    7,68216,68221,68223,    7,68215,
+    2,68226, 1368,68215,    6,68176,    2,68233,    6,68234,68177,68237,
+    0,68234,68239,68241,    0,68233,    2,68244,18966,68233,56554,68176,
+    2,68251,    7,68252,    7,68251,    2,68256, 1368,68251,  482,68176,
+    2,68263,    0,68264,    0,68263,    2,68268,18966,68263,20501,68176,
+ 9513,68275,59787,68275,21529,68275, 9875,68176,59787,68283, 9513,68283,
+16859,68283,59787,68177,60125,68291, 9875,68291,20501,68291, 9513,68177,
+16091,68299,20501,68299, 9875,68299,  483,68177, 2007,68307, 3477,68307,
+68267,68307,68271,68307, 5197,68307,68241,68307,68247,68307,    1,68307,
+19051,68307,19667,68307, 5123,68307,12345,68307,68249,68307,68273,68307,
+18967,68307,  555,68337,68233,68337,68263,68337,56555,68177,59637,68345,
+59717,68345,68255,68345,68259,68345,68223,68345,68229,68345,    6,68345,
+59649,68345,39747,68345,43837,68345,43027,68345,68231,68345,68261,68345,
+ 1369,68345,59619,68373,68215,68373,68251,68373,18967,68176,19553,68381,
+19549,68381,20345,68381,20281,68381,    7,68381,68345,68391,68359,68381,
+10093,68381,10085,68381,20285,68381,10087,68381,19555,68381,  483,68381,
+20273,68407,10081,68407,19545,68407, 1369,68176,67281,68415,67273,68415,
+ 3587,68415, 1989,68415,    0,68415,68307,68425,68323,68415,56681,68415,
+57911,68415, 4897,68415,17041,68415,67291,68415,56555,68415, 1471,68441,
+67269,68441,    3,68176,40909,68447,    3,68177,40895,68451,40059,68451,
+43749,68451,38903,68451,18967,65869,20347,68460,20345,68463, 1203,68461,
+ 1205,68467, 1009,68461, 1007,68471, 1205,68460, 1203,68475, 1007,68460,
+ 1009,68479,   97,68460,   21,68483,  571,68460,  555,68487,  177,68461,
+   59,68491, 1365,68461, 1325,68495,    2,68460,    6,68499,    2,68500,
+68461,68503,    5,68500,68505,68507,    5,68499,    6,68510,   14,68499,
+    4,68460,    6,68517,    4,68518,68461,68521,    3,68518,68523,68525,
+    3,68517,    6,68528, 1274,68517,  482,68460,    6,68535,    5,68536,
+    5,68535,    6,68540,   14,68535,    8,68460,    6,68547,    3,68548,
+    3,68547,    6,68552, 1274,68547,  256,68461,  629,68461, 1325,68460,
+   21,68563,  251,68563,  555,68563, 1365,68563,   59,68460,  555,68573,
+  251,68573,   21,68573,  177,68573,  555,68461,  571,68583,  331,68583,
+   59,68583, 1325,68583,   21,68461,   97,68593,  331,68593, 1325,68593,
+   59,68593,  331,68460,  251,68603,  555,68603,   21,68603,  251,68461,
+  331,68611,   59,68611, 1325,68611,    9,68461, 7951,68619, 7961,68619,
+68551,68619,68555,68619,68451,68619,68525,68619,68531,68619,    2,68619,
+ 7953,68619,35893,68619,38299,68619,37897,68619,68533,68619,68557,68619,
+ 1275,68619, 7947,68649,68517,68649,68547,68649,  483,68461, 9517,68657,
+ 9525,68657,68539,68657,68543,68657,20033,68657,68507,68657,68513,68657,
+    4,68657, 9519,68657,57855,68657,60853,68657,60609,68657,68515,68657,
+68545,68657,   15,68657, 9513,68687,68499,68687,68535,68687, 1275,68460,
+67245,68695,67253,68695,10041,68695,10005,68695,    5,68695,68657,68705,
+68673,68695,10009,68695,23879,68695,31937,68695,30399,68695,67263,68695,
+    9,68695,10001,68721,67241,68721,   15,68460,19549,68727,19553,68727,
+10093,68727,10085,68727,    3,68727,68619,68737,68635,68727,20345,68727,
+20281,68727,10087,68727,20285,68727,19555,68727,  483,68727,10081,68753,
+20273,68753,19545,68753,    7,68460,58715,68761,  375,68761,    7,68461,
+58703,68767,58027,68767,60849,68767,68345,68767,35603,68767,   59,68767,
+ 1325,68767,  331,68767,  265,68767,  241,68766,  241,68461,    6,68789,
+    7,68789,    6,68788,68793,68795,    7,68788,68791,68799,  265,68460,
+  375,68803, 1011,65869,59960,68807,61780,68806,63014,68806,62538,68806,
+17455,68806,47640,68806, 5843,68806,48534,68806,  483,68806,60857,68824,
+    9,68806,60857,68828,46863,68806,60857,68832,  903,68832,   11,68833,
+  587,68832,  587,68806,46863,68842,   11,68807,46863,68847,    7,68807,
+56555,68850,63823,68851, 9377,68851,  903,68806,46863,68858,56555,68807,
+    6,68863,    7,68863,    6,68862,68867,68869,    7,68862,68865,68873,
+60857,68806,    7,68877,  483,68876,46863,68876,    9,68876,62942,65869,
+    7,68887,46863,68886,    9,68886,  483,68886,60857,65869,58782,68896,
+58362,68896,47608,68896, 1108,68896, 1072,68896,  165,68896,  524,68896,
+ 1291,68896,   11,68897,  483,68915,    9,68896, 1011,68918,  587,68897,
+  483,68923,46863,68896,56555,68926, 1011,68926,  483,68896,56555,68932,
+  587,68933,   11,68933, 1011,68932,   11,68932,   11,68896,  483,68944,
+    7,68897, 1141,68949, 1447,68949,   33,68949,56555,68896,    9,68957,
+46863,68956,  483,68956, 1011,68896,    7,68965,    9,68964,  483,68964,
+46863,68964,  265,65869,16710,68974,44242,68974,16711,68974,16710,68975,
+68981,68983,45086,68975,44242,68975,    3,68988,44243,68974,68987,68993,
+68991,68993,60797,68975,60796,68974,68999,69001,60796,68975,60797,68974,
+69005,69007,    3,68975,44242,69011,44242,69010,68993,69015,    6,69010,
+ 1274,68975,44243,68975,69013,69023,45087,68975,68979,69027,16711,68975,
+68977,69031, 1275,68975, 4899,69035,14611,69035,47961,69035,   11,68974,
+    9,69043,46863,68974,69019,69047,69021,69047,    9,68975,   11,69053,
+    6,68974,    0,69056,69035,69059,    7,68974,25793,69063,41019,69063,
+ 8717,69063, 8495,69063, 3785,69063,    6,68975,    3,69074,69047,69077,
+    7,68975, 8647,69081,21605,68975,  375,69085,18967,68974,  375,69089,
+   11,65869,39085,69093,49204,69092,   33,69097,  803,69093,63014,69092,
+25381,69092,  265,69092,    9,69107,60857,69092,  483,69110,  483,69092,
+60857,69114, 1275,69092,    9,69119,    2,69092,44243,69123,    3,69092,
+   33,69127,46863,69129,46863,69126,   33,69133,    3,69093,49283,69137,
+47546,69137,  113,69137,46863,69142,46863,69137,  113,69146,46863,69092,
+    3,69150,   33,69153,    3,69151,  113,69157,20034,65869,  375,69161,
+48560,65869,    3,69164,   33,69167,    3,69165,  113,69171,59206,65869,
+    7,69175,29598,65869,    7,69179,60455,65869,  256,69183,  375,69183,
+    7,69183,  241,69188,  241,69183,    7,69192,15029,65869,56555,69196,
+    7,69199,28715,65869,  256,69203, 1505,69202,    7,69203,  241,69208,
+  241,69203,    7,69212,  903,69202,    7,69217,54027,65869,  375,69221,
+    2,69220,54159,69225,46863,69227,    2,69221,54256,69231,46863,69231,
+54225,69234,54225,69231,46863,69238,17635,65869,    7,69243,    2,69244,
+    2,69245, 1368,69243, 1369,69243,    2,69242,69253,69255,    3,69242,
+69247,69259,69251,69259,    2,69243,    7,69264,69259,69267,    3,69243,
+69249,69271,    2,65868,41692,69275,41607,69275, 8672,69275, 8743,69275,
+26454,69275,26375,69275, 8770,69275, 8729,69275, 3795,69275,47953,69275,
+48062,69275,47961,69275,48009,69298,48009,69275,47961,69302,41417,69275,
+41653,69306,26219,69275,26415,69310,31770,69275,44832,69275, 8757,69275,
+ 8647,69318,26415,69275,26219,69322,41653,69275,41417,69326, 8647,69275,
+  305,69330, 8757,69330, 8605,69275,47580,69275,47933,69339, 8684,69275,
+ 8717,69343, 8916,69275,31103,69275,    9,69348,26292,69275,26331,69353,
+  340,69275, 8717,69357, 3785,69357, 8495,69357,  375,69275, 8861,69364,
+46863,69364,47488,69275,41502,69275,41559,69373,  483,69275,44243,69376,
+  305,69275, 8647,69380,    7,69275,    1,69385,  264,69386,  264,69387,
+41019,69385,41653,69393,25793,69385,26415,69397, 8495,69385,  305,69401,
+ 8757,69401, 8495,69384, 8717,69407,25793,69384,26331,69411,  265,69385,
+69391,69415, 8861,69415,46863,69415,41019,69384,41559,69423,  265,69384,
+ 8717,69427,69389,69427, 3785,69427, 8495,69427,44243,69275,  483,69436,
+    9,69275,31103,69440,46863,69275,  265,69445,48009,69447,  265,69444,
+47933,69451,  375,69444,25793,69275,    7,69457,26219,69459,    7,69456,
+26331,69463,  265,69275,46863,69467,47961,69469,46863,69466,47933,69473,
+    7,69467, 8647,69477,    7,69466, 8717,69481, 3785,69481, 8495,69481,
+41019,69275,    7,69489,41417,69491,    7,69488,41559,69495, 8495,69275,
+    7,69498, 8717,69501,    7,69499, 8647,69505, 8861,69275,  375,69508,
+    3,65868,21116,69513,21253,69513,21560,69513,20465,69513,20576,69513,
+59683,69513,42035,69513, 9573,69513,59689,69513, 9575,69513,42041,69513,
+43711,69513,42089,69513,42129,69513,    1,69513,    6,69543,68974,69544,
+68975,69545,69547,69549,68974,69545,68975,69544,69553,69555,    4,69513,
+    6,69558,66665,69561,66785,69561,66997,69561,68695,69561, 9599,69513,
+    8,69513,66997,69573,66785,69573,66665,69573,68695,69573,67011,69513,
+66805,69513,68721,69513,66693,69513,60569,69513,59701,69513,59767,69513,
+ 9605,69513,32468,69513,28483,69513,19625,69513,20501,69602,43015,69513,
+44714,69513,19474,69513,20413,69611,20805,69513,20186,69513,21549,69513,
+20501,69618,21105,69513,20501,69622, 1418,69513,59619,69627, 9565,69627,
+41941,69627,  669,69513, 9565,69635,59619,69635,41941,69635,37501,69513,
+31103,69513,27021,69644, 8386,69513,50657,69513,36944,69513,48408,69513,
+ 1369,69513,   15,69656, 9565,69659,41941,69659,59619,69659,  483,69513,
+46863,69666,20501,69513,21105,69670,21549,69670,19625,69670,    6,69513,
+    3,69679,56555,69681,65869,69683,    4,69678,66665,69687,66785,69687,
+66997,69687,68695,69687,69685,69687,    3,69678,68460,69699,69687,69701,
+18967,69699,65869,69704,69687,69707,65869,69699,18967,69710,69687,69713,
+    7,69513,20103,69716, 8337,69716,36773,69716,27021,69513,31103,69724,
+    7,69512,24265,69729,28233,69729,29077,69729,20361,69729, 9673,69729,
+ 4279,69729, 9967,69729,19559,69729, 4283,69729,20713,69729, 3807,69729,
+ 8251,69729,44243,69513,41941,69754,46863,69513,  483,69758,   15,69513,
+18967,69763,20501,69765,18967,69762,20413,69769, 1369,69762, 9565,69773,
+41941,69773,59619,69773, 8337,69513,    7,69780,18967,69513,   15,69784,
+20413,69787, 1011,69513,44242,69790,44242,69791,44243,69790,69795,69797,
+44243,69791,69793,69801,28715,69513,    7,69805,36773,69513,    7,69808,
+41941,69513,44243,69812,20103,69513,    7,69816,20273,69513,    6,69820,
+    7,69820,    6,69821,69825,69827,    7,69821,69823,69831, 9617,69513,
+    6,69834,    7,69834,    6,69835,69839,69841,    7,69835,69837,69845,
+    6,65868,    1,69849,    3,69850,    4,69849,    3,69855,67988,69856,
+67989,69857,69859,69861,67988,69857,67989,69856,69865,69867,21604,69849,
+    3,69849,    1,69872,    7,65868,59007,69877,58999,69877,59025,69877,
+19981,69877,48747,69877,37279,69877,57047,69877,57029,69877,58153,69877,
+    1,69877,    2,69896,66625,69899,66825,69899,66973,69899,68415,69899,
+58167,69877,56554,69877,66973,69911,66825,69911,66625,69911,68415,69911,
+66987,69877,66845,69877,68441,69877,66653,69877,24601,69877,57437,69877,
+57021,69877,57069,69877,54107,69877,52743,69877,52193,69877,20734,69877,
+25551,69877,24613,69877,28205,69877,20501,69877,  265,69950,  241,69951,
+ 1141,69877,56555,69957,60577,69877,62959,69877,58377,69877,57981,69877,
+19916,69877, 7947,69969,48739,69969,37241,69969,58931,69877,48739,69977,
+ 7947,69977,37241,69977, 8306,69877,   33,69877,56555,69987, 1447,69877,
+56555,69991, 9875,69877,  241,69995,  265,69994, 9992,69877,  545,69877,
+  695,69877, 1382,69877, 1374,69877, 1386,69877,  154,69877,  483,70013,
+60455,69877,  483,70017, 1369,69877,  331,70020, 1325,70020,   59,70020,
+ 1325,69877, 1369,70028, 1275,69877,18967,70032,48739,70035,37241,70035,
+ 7947,70035,   59,69877, 1369,70042,    2,69877,    7,70047,    9,70049,
+65869,70051,    1,70046,66625,70055,66825,70055,66973,70055,68415,70055,
+70053,70055,    7,70046,68176,70067,70055,70069,   15,70067,65869,70072,
+70055,70075,65869,70067,   15,70078,70055,70081,    3,69877, 8241,70085,
+   15,70084,  483,70089,  331,69877, 1369,70092,    3,69876,24265,70097,
+28233,70097,29077,70097,19559,70097,20713,70097, 4283,70097,20361,70097,
+ 9673,70097, 4279,70097, 9967,70097, 8251,70097, 3807,70097,18967,69877,
+ 1275,70122,48739,70125,37241,70125, 7947,70125,  113,70123, 1011,69877,
+  265,69877,20501,70136, 8165,70136, 9875,70136,46863,69877,38056,70144,
+38056,70145,38057,70144,70149,70151,38057,70145,70147,70155,   15,69877,
+    3,70159, 1369,70161,    3,70158,  483,70165,54027,69877,  483,70169,
+ 8165,69877,  265,70172,    7,65869,69874,70176,69875,70177,70179,70181,
+69875,70176,69874,70177,70185,70187,69852,70176,69853,70177,70191,70193,
+69853,70176,69852,70177,70197,70199,11276,70176,11277,70176,11276,70177,
+70205,70207, 5044,70176, 5045,70176, 5044,70177,70213,70215,40583,70177,
+40583,70176,40582,70176,70219,70223,40582,70177,70221,70227,24094,70177,
+69871,70177,69870,70177,21604,70177,69849,70236,    9,70236,21604,70176,
+70233,70243,69849,70243,    9,70243,    4,70177,    0,70250,    1,70177,
+  264,70254,  264,70255,24095,70177,70243,70261,45149,70177,26498,70177,
+41326,70177, 8796,70177,27533,70177,    9,70273,25793,70177,27021,70277,
+  587,70276,  241,70277, 5045,70177,70211,70285,11277,70177,70203,70289,
+ 4551,70177,10001,70177,    9,70295, 8495,70177,  305,70299,  587,70298,
+  241,70299,   88,70177, 1369,70307,  587,70177,25793,70310,41019,70310,
+ 8495,70310, 1369,70177,20103,70319,36773,70319, 8337,70319,  265,70177,
+70259,70327,63493,70327, 8861,70327,46863,70327,   89,70177,46863,70337,
+  483,70177,18967,70341,37241,70343,48739,70343,70253,70343, 7947,70343,
+ 1275,70177,44243,70353,21605,70176,70231,70357,70235,70357,70239,70357,
+70241,70357,70237,70357,69849,70367,    9,70367,26331,70357,23755,70357,
+27805,70357,  241,70176,25793,70379,59875,70379,41019,70379, 8495,70379,
+ 9805,70379,53391,70379,  903,70176,25793,70393, 8495,70393,41019,70393,
+18967,70176,58715,70401,  375,70401,  265,70176,70257,70407,25793,70407,
+41019,70407, 8717,70407, 8495,70407, 3785,70407,21605,70177,70246,70421,
+69849,70421,70243,70424,70248,70421,70243,70421,69849,70430,    9,70430,
+24545,70421,    9,70421,70243,70438,  903,70421,  241,70177,51487,70445,
+  375,70177, 1369,70449,41019,70177,  587,70452,  241,70453,    2,70176,
+48009,70459,  265,70459,46863,70463,49321,70459,49001,70459,    3,70176,
+58056,70471,58601,70471,40799,70471,44243,70471,56555,70478,35927,70471,
+  375,70471,  510,70471,  483,70471,    9,70488,38155,70471,37611,70471,
+56555,70471,44243,70496,    9,70471,  483,70500,    2,70177,44243,70505,
+48466,70505,47640,70505,46863,70505,    9,70512,  903,70512,  903,70505,
+46863,70518,    9,70505,46863,70522,49155,70505,    3,70177, 1369,70529,
+    9,70531,37663,70529,    9,70528, 1369,70537,18967,70529,44243,70541,
+69849,70177,21604,70545,70421,70547,21604,70544,70357,70551,    9,70177,
+21604,70555,70421,70557,21604,70554,70357,70561,    3,70554, 1369,70565,
+    3,70555,  483,70569,    3,65869,60078,70572,60079,70572,13748,70573,
+13736,70572,70579,70581,13736,70573,13737,70572,13749,70573,70587,70589,
+    1,70573,    5,70592,    1,70572,69385,70597,69384,70597,69275,70597,
+    7,70602,    7,70603,59961,70597,    6,70596,70601,70611,70605,70611,
+    7,70596,70599,70617,69275,70617,    6,70597,69275,70623,70617,70624,
+70607,70623,70620,70623,70617,70623,69275,70632,56555,70623,    7,70597,
+69275,70638,70611,70641,70611,70639,69275,70645,48560,70572,   33,70649,
+60230,70573,57986,70573,58352,70573, 8309,70573,13737,70573,    7,70660,
+70581,70663,59960,70573,70575,70667,70611,70667,  241,70666,  256,70573,
+56555,70674,   11,70573,48583,70679,48328,70679,   25,70679,46863,70684,
+46863,70679,   25,70688,59961,70573,70577,70693,  483,70573,   15,70697,
+41941,70699, 9565,70699,70595,70699,59619,70699, 1369,70573,46863,70709,
+37409,70573,46863,70713,46863,70572,   11,70716,   33,70719, 1369,70717,
+   11,70717,   25,70725,37409,70717,   15,70572,40909,70731,   11,70572,
+   33,70735,46863,70737,46863,70734,   33,70741,    6,70572,    1,70744,
+70667,70747,    5,70744,    7,70572,70609,70753,58056,70753,70636,70753,
+70623,70753,56555,70760,40799,70753,58601,70753,44243,70753,56555,70768,
+35927,70753,  375,70753,  510,70753,  483,70753,    9,70778,38155,70753,
+37611,70753,    9,70753,  483,70786,56555,70753,70623,70790,44243,70790,
+    6,70573,70731,70797,56555,70797,    7,70573,13737,70802,70581,70805,
+13737,70803,70585,70809,70611,70803,56555,70813,70747,70803,56555,70817,
+70751,70803,42613,70803,56555,70823,54497,70803,54159,70803,51803,70803,
+58348,70802,10291,70803,56555,70835,   59,70803, 1325,70803,  331,70803,
+ 1275,70803,    9,70845,56555,70802,70611,70849,70747,70849,  241,70848,
+  241,70802,56555,70856,   15,70803,  483,70861,69275,70573,58348,70573,
+    7,70866,38057,70573,    7,70871,43503,70573,44243,70875,56555,70573,
+  256,70878,    7,70878,70611,70883,70747,70883,  241,70882,    7,70879,
+70623,70891,  241,70878,    7,70894,  241,70573,44242,70899,44242,70898,
+44243,70899,70903,70905,59960,70898,44243,70898,70901,70911,    7,70898,
+56555,70914,56555,70898,    7,70918,    2,65869,    1,70922,69635,70925,
+  668,70925,69513,70929,69627,70925, 1419,70925,69513,70935,70699,70925,
+69659,70925,69773,70925,  587,70925,    9,70944,69513,70947,    9,70925,
+  587,70950,69513,70953,54027,70922,54159,70957,46863,70959,54027,70923,
+54154,70963,46863,70963,54129,70966,54129,70963,46863,70970,44243,70923,
+   11,70975,46863,70922,   11,70922,44243,70981,    6,70922,    0,70985,
+    5,70986,    5,70985,    0,70991,    0,70990,    1,70984,70995,70997,
+70989,70997,70987,70997,    5,71003,    1,70985,70993,71007,    5,71007,
+    0,70984,    5,71013,71007,71014,71010,71013,71007,71013,    5,71020,
+  903,70985,    1,71025,    0,71025,    1,71024,71029,71031,    0,71024,
+71027,71035,    7,70922,48009,71039,  265,71039,46863,71043,49321,71039,
+49001,71039,    7,70923,70989,71051,70997,71052,70995,71051,70997,71056,
+70998,71051,71000,71051,71005,71051,71009,71051,71017,71051,71019,71051,
+71023,71051,71011,71051,71013,71075,14219,71051,14013,71051,14267,71051,
+16151,71051,70997,71051,70995,71086,70989,71086,56554,71051,    1,71051,
+    2,71094,    2,71051,    1,71098,14211,71051, 9165,71103,    9,71051,
+65869,71107,71093,71109,71097,71109,71101,71109,70985,71051,69513,70923,
+  903,70923,46862,71120,46862,71121,46863,71121,71123,71127,46863,71120,
+71125,71131,    6,65869,    1,71134,70803,71137,56555,71139,    4,71134,
+69977,71143,58930,71143,69877,71147,69969,71143,19917,71143,69877,71153,
+70343,71143,70035,71143,70125,71143,  587,71143,56555,71162,69877,71165,
+56555,71143,  587,71168,69877,71171,    2,71134,  903,71175,    1,71177,
+    0,71177,    1,71176,71181,71183,    0,71176,71179,71187,    2,71135,
+  265,71191,    0,71192,    1,71192,    0,71193,71197,71199,    1,71193,
+71195,71203,    3,71135,    8,71207,    4,71207,    6,71210,    6,71207,
+    4,71214,56555,71207,65869,71219,71209,71221,71213,71221,71217,71221,
+    0,    5,59619,71229,59961,71230,60166,71229, 1207,71228,19105,71237,
+ 1180,71228,19119,71241,60158,71228,60180,71228,60178,71228,60318,71228,
+60167,71229, 1197,71228,59875,71255,53391,71255, 9805,71255,60159,71228,
+60181,71228,60179,71228,38158,71229,44195,71269, 1196,71228,60319,71228,
+28739,71229,    2,71277,29229,71279,   59,71228,60221,71283,63823,71228,
+61747,71287,61585,71287,61475,71287,63185,71287,   39,71228,56555,71297,
+   15,71299,    6,71298,71301,71303,   14,71299,    7,71298,71307,71309,
+ 1163,71228,19119,71313,   25,71228,61747,71317,63185,71317,25461,71317,
+61585,71317,70985,71228,71086,71327,70997,71327,71051,71330,71051,71327,
+70997,71334,38057,71229,    6,71338,44195,71341,60973,71229, 1179,71345,
+49213,71229,49217,71349,54619,71229,   11,71353,54655,71355, 1003,71229,
+60857,71359, 1007,71361,11995,71228,12025,71365,64569,71228,64587,71369,
+61989,71228,61747,71373,63185,71373,61585,71373, 8065,71229,   11,71381,
+ 8067,71383,63777,71229,60857,71387,63779,71389,21918,71229,  987,71393,
+54336,71229,54339,71397,  989,71229,21605,71400,  987,71403,21890,71229,
+ 1179,71407,49262,71229,49217,71411,54331,71229,   17,71414,54339,71417,
+25395,71228,25461,71421, 1293,71228,61475,71425,25433,71228,25461,71429,
+61005,71228,61475,71433,63014,71228,    5,71437,    7,71438,    7,71437,
+    5,71442,   10,71437,  524,71228,    0,71449,    3,71450,    3,71449,
+    0,71454,60856,71449,21904,71229,   25,71461,  809,71229,21605,71464,
+  713,71467,13755,71229,   17,71470, 9377,71473,65054,71229,63823,71477,
+  117,71229,21605,71480,   25,71483,21916,71229,  713,71487,13764,71229,
+ 9377,71491,65037,71229,   17,71494,63823,71497, 1177,71229,21605,71500,
+ 1179,71503,49229,71229,   17,71506,49217,71509,26867,71229,21605,71512,
+26865,71515,10161,71229,   17,71518,10159,71521,26868,71229,26865,71525,
+10162,71229,10159,71529, 1180,71229, 2975,71533, 1903,71533,19025,71533,
+33464,71229,34655,71541,34447,71541,33221,71541,33773,71541, 1207,71229,
+19027,71551, 3567,71551, 1973,71551, 3041,71551, 1921,71551,19049,71551,
+ 9824,71229,71273,71565,53462,71229,71273,71569,59900,71229,71273,71573,
+60319,71229,71251,71577,60159,71229,71245,71581,60178,71229,71267,71585,
+59901,71229,71255,71589,60158,71229,71263,71593,60180,71229,71265,71597,
+25461,71229,   25,71601,25395,71601,25433,71601,61475,71229,63823,71609,
+ 1293,71609,61005,71609,65808,71229,65513,71617,65791,71617,65407,71617,
+65171,71617,60835,71229,60318,71229,71275,71629, 9617,71629,19797,71229,
+  375,71635,20735,71229,47386,71229,20040,71229,20050,71229,61747,71229,
+63823,71647,   25,71647,61989,71647,63185,71229,   25,71655,63823,71655,
+61989,71655,61585,71229,63823,71663,   25,71663,61989,71663,20056,71229,
+  375,71671, 9825,71229,71255,71675,53463,71229,71255,71679,57562,71229,
+58846,71229,58372,71229,58758,71229,58762,71229,57224,71229,57284,71229,
+57278,71229,58760,71229,20686,71229,24738,71229,  305,71703,  713,71703,
+ 1489,71703,   25,71703,10074,71229, 9377,71713,17573,71713,63823,71713,
+22766,71229,  305,71721,   25,71721,  147,71721,  713,71721,27672,71229,
+63823,71731,27995,71731, 9377,71731,62147,71229,   25,71739,  305,71739,
+  147,71739,  169,71739,  713,71739,31881,71229,63823,71751,27995,71751,
+31359,71751, 9377,71751,60221,71229,   59,71761,  653,71229,   11,71765,
+ 9993,71229,17542,71229, 9936,71229,24734,71229,  305,71775,  713,71775,
+   25,71775,60834,71229,21350,71229,16129,71229,    3,71787,    2,71787,
+  842,71787,  843,71786,71793,71795,  843,71787,  842,71786,71799,71801,
+    3,71786,71791,71805,    2,71786,71789,71809,16966,71229,19480,71229,
+50522,71229,52740,71229,57380,71229,59108,71229,50478,71229,57252,71229,
+19986,71229,51036,71229,57576,71229,58112,71229,58362,71229,  903,71836,
+47640,71229,56555,71840,60179,71229,71249,71845,60181,71229,71247,71849,
+63015,71229,71441,71853,71445,71853,62905,71853,63041,71853,63047,71853,
+63215,71853,    6,71853,63205,71867,19687,71853,21127,71853,20843,71853,
+63049,71853,71447,71853,   11,71853,63033,71881,71437,71881,19917,71229,
+    9,71886,  525,71229,71453,71891,71457,71891,36729,71891, 1851,71891,
+ 1885,71891,35635,71891,    2,71891,35633,71905,62095,71891,17711,71891,
+ 4907,71891,61003,71891,71459,71891,60857,71891,  531,71919,71449,71919,
+ 1413,71229,  331,71925,49713,71924, 1419,71229,56555,71930,58782,71229,
+  903,71934,  296,71229, 8861,71939, 1106,71229,18967,71943, 9617,71943,
+24095,71229,46863,71949,57522,71229,   11,71953,  903,71952,  587,71952,
+51004,71229,  483,71960,22956,71229,70471,71965,70753,71965,10159,71965,
+26865,71965,10111,71965,26715,71965,23709,71965,23713,71965,67425,71965,
+10113,71965,26719,71965,23715,71965,  587,71965,10107,71991,26625,71991,
+23651,71991,19475,71229,  483,71998,  918,71229,56555,72002,  922,71229,
+56555,72006,49713,72006,  668,71229,56555,72012, 1290,71229,    2,72017,
+35575,72019,35585,72017, 3621,72017, 1991,72017,60969,72017,62095,72017,
+17711,72017, 4907,72017,60857,72017, 1325,72037,58930,71229,    9,72040,
+52692,71229,  903,72044,25380,71229,    6,72049,38881,72051,38891,72049,
+ 9927,72049, 9891,72049, 9895,72049,19687,72049,21127,72049,20843,72049,
+   11,72049, 9875,72069, 1447,71229,15705,72073, 9917,71229,20615,71229,
+  759,71229,17455,72081, 9195,71229, 1487,72085, 1471,71229,21605,72088,
+  305,72091,  713,72091, 1489,72091,   25,72091, 9805,71229, 1197,72101,
+ 1275,72101,    9,72105, 1197,72100,71273,72109,10001,71229,   17,72112,
+ 9377,72115,17573,72115,63823,72115,17455,71229,12377,72122,59961,71229,
+59619,72126, 1011,72126, 9617,72131, 1011,72127, 9565,72135,59619,72135,
+   89,71229,17455,72141,60797,71229,59381,72144,  165,71229,21315,72148,
+  587,71229,66971,72153,17455,72153,57522,72152,    9,72152,56555,72160,
+56555,72152,    9,72164,60857,72153,    9,72169, 1369,71229,39085,72173,
+21605,72172,20843,72177,21127,72177, 9927,72177, 9891,72177,19687,72177,
+ 9895,72177,   11,72177, 9875,72191, 1275,71229,   17,72194, 4907,72197,
+17711,72197, 3621,72197, 1991,72197,62095,72197,60969,72197,60857,72197,
+ 1325,72211,  483,71229,20035,72214,58742,72214,19475,72214,51004,72214,
+56555,72214,  903,72224,  903,72214,56555,72228,49713,72228,49713,72214,
+  903,72234,55839,71229,46863,72239,65061,71229,60857,72243,65063,72245,
+65067,72245,65071,72245, 7065,71229,18967,72253, 6789,71229,   11,72257,
+ 6843,72259, 6885,72259, 6889,72259,11277,71229,46863,72267, 9935,71229,
+ 1011,72270,20645,71229, 1011,72274, 3445,71229,  375,72279, 5045,71229,
+46863,72283,17104,71229,48643,72287,12614,71229,  375,72291,69872,71229,
+68155,72295,71116,71229,71013,72299,70985,71229,71013,72303,71051,72305,
+71051,72302,71013,72309,71051,71229,70985,72313,70997,72315,70985,72312,
+71013,72319,  482,71228,23717,72323,24522,72323,24447,72323,23939,72328,
+23939,72323,24447,72332,22956,72323,23651,72337,21605,72323,   17,72341,
+23939,72343,   17,72340,23651,72347,   17,72323,21605,72351,24447,72353,
+21605,72350,23651,72357, 1368,71228,    7,72361,    5,72362,72049,72365,
+72177,72365,    5,72361,    7,72370,72049,72373,72177,72373,72191,72361,
+72069,72361,   10,72361,72177,72383,72049,72383,27021,72361,24095,72361,
+ 9195,72361,52915,72361,23651,72361,51435,72361,21605,72361,    9,72401,
+67297,72361,70097,72361,69729,72361,11277,72361, 5045,72361,10171,72361,
+53941,72361, 9755,72361,26907,72361, 4321,72361,27323,72361, 3833,72361,
+ 9317,72361, 4295,72361,53215,72361, 1274,71228,    3,72435,    0,72436,
+72017,72439,72197,72439,    0,72435,    3,72444,72017,72447,72197,72447,
+72211,72435,72037,72435,60856,72435,72197,72457,72017,72457,  586,71228,
+39619,72463,51421,72463,57811,72463,59933,72463,59743,72463, 8093,72463,
+ 3837,72463,42435,72463, 4287,72463,53703,72463, 4303,72463,42113,72463,
+ 9839,72463,53487,72463, 9579,72463,  483,72463,  803,72494,  828,72463,
+  705,72463,  803,72463,  483,72502,  482,71229,66737,72507,36661,72507,
+62741,72507,68727,72507,68381,72507, 1274,71229,  587,71228,61747,72521,
+25461,72521,61475,72521,63185,72521,61585,72521,  483,71228,56555,72533,
+    6,72535,    5,72536,    7,72535,    5,72535,    6,72542,    6,72543,
+72541,72547,    6,72534,   15,72535,72551,72553,    7,72534,72545,72557,
+72539,72557,   14,72535,72557,72563, 1368,71229,55839,72567,51803,72567,
+54159,72567,54497,72567,  265,72567, 1275,71228,59914,72579,60221,72579,
+18708,72579, 9856,72579,53504,72579, 9805,72579,    9,72590,53391,72579,
+    9,72594,59875,72579,    9,72598,18693,72579,    9,72602,60369,72579,
+    9,72579,18693,72608, 9805,72608,59875,72608,53391,72608,  586,71229,
+   33,72619, 1447,72619, 1141,72619,  889,72619,  795,72619,  787,72619,
+  767,72619,  483,72633, 1505,71229,16937,72636,56555,72636,  581,71229,
+60857,72643, 1325,72645,  331,72645,  571,72645,  585,72645,   59,72645,
+16937,71229, 1505,72656,13947,71229,    2,72661,14217,72663,   11,72661,
+ 9875,72667,16091,72667,13955,72667,20501,72667, 9919,71229,20623,71229,
+ 9921,71229, 1196,71229,72103,72683,71256,72683,71258,72683,71260,72683,
+71255,72683,59875,72692,53391,72692, 9805,72692,59875,72683,71255,72700,
+ 9805,72683,71255,72704,53391,72683,71255,72708,  154,71229,64148,71229,
+ 1325,72715,   59,72715,  331,72715,  265,72715,52501,71229,  265,72725,
+  297,71229,18967,72729, 1107,71229,59960,71229,21105,72735,65513,72735,
+65791,72735,65407,72735,21549,72735,19625,72735,65171,72735,59619,72735,
+   15,72735,   88,71229,70177,72755,70176,72754,72757,72759,70176,72755,
+70177,72754,72763,72765, 1141,72755, 1447,72755,   33,72755,   11,72755,
+37409,72755,  972,71229,   59,72779, 1325,72779,  331,72779,27978,71229,
+60796,71229,59381,72789,31102,71229,62905,72793,68761,72793,70401,72793,
+67541,72793,  164,71229,36729,72803,68447,72803,70731,72803,67547,72803,
+54596,71229,44243,72813,20695,71229,  155,71229,20763,71229,  375,72820,
+ 1197,71229,71273,72825,59875,72827, 9805,72827,53391,72827,53391,72824,
+71273,72835, 9805,72824,71273,72839,59875,72824,71273,72843,  375,71229,
+20763,72846,20836,71229, 1141,71229,15705,72853,   33,71229,15705,72857,
+27021,71229, 1487,72861,  959,71229,17455,72865,52915,71229, 1487,72869,
+   47,71229,17455,72873,59875,71229, 1197,72877,72683,72879, 1275,72877,
+    9,72883, 1197,72876,71273,72887,  253,71229,21605,72890,  305,72893,
+   25,72893,  713,72893,53391,71229, 1197,72901,72683,72903, 1275,72901,
+    9,72907, 1197,72900,71273,72911,   53,71229,21605,72914,  305,72917,
+   25,72917,  147,72917,  713,72917,27533,71229,   17,72926,63823,72929,
+27995,72929, 9377,72929,30749,71229,    7,72937,26970,71229,    7,72941,
+70864,71229,    7,72945,69849,71229,    3,72948,68155,72951,    3,72949,
+67577,72955,68139,72955,70979,72955,69275,71229,70573,72962,    7,72965,
+69513,71229, 1011,72968,    7,72971, 9780,71229,    7,72975,59381,71229,
+    2,72979,72789,72981,60797,72978,    6,72978,56555,72986,72981,72989,
+26625,71229, 1011,72992,    7,72995, 9731,71229, 1011,72998,    7,73001,
+69790,71229,    7,73005,   13,71229,32805,71229,    7,73010,33221,73013,
+34655,73013,33773,73013,34447,73013,   15,73011,34875,73023,    7,73011,
+34723,73027,   19,71229,   59,73031,   18,71229,65076,71229,    7,73037,
+65493,73039,    7,73036,65171,73043,65791,73043,65513,73043,65407,73043,
+   15,73037,65357,73053,   12,71229,68974,71229,  375,73059,71119,71229,
+    7,73063, 1011,71229,52387,73067,20762,73067,59961,73066, 9617,73073,
+20645,73066, 9935,73066,   17,73066,18967,73081, 9617,73081,    6,73066,
+    7,73067,18967,73088,26625,73066,    7,73093,18967,73067,    7,73096,
+   17,73097, 9731,73066,    7,73103,69513,73066,    7,73107,21315,73066,
+    7,73111,   15,71229,18967,73115,   17,73117,    3,73114,    3,73115,
+72567,73123,   17,73114,  265,71229,    9,73128, 8861,73131,60857,73129,
+    9,73135,65869,73128,  375,73139,   11,71229,60857,73143,    9,73145,
+ 1275,73143,    9,73149,    9,73142,60857,71229,    7,73154,   59,73157,
+ 1325,73157,  331,73157,  265,73157,    7,73155,  375,73167,  265,73155,
+  375,73171,12377,73154,    7,73175,18967,71229,    7,73179,25793,73181,
+41019,73181, 8495,73181,46863,71229,20035,73188,58742,73188,  903,73188,
+56555,73194,56555,73188,  903,73198,20035,71229,21183,73203,    7,73203,
+  331,73207,  483,73202,46863,73202,    9,73202,    7,73202,  375,73217,
+49713,71229,39085,73221,  136,73220, 1197,73220,  137,73220,  922,73220,
+ 1413,73220, 1011,73220,    6,73234,  483,73220,  903,73238,  903,73220,
+  483,73242,    2,73220,    9,73246,44243,73247,    3,73220,    5,73253,
+    6,73255,    9,73253,    2,73221,73257,73261,73229,73261,73258,73261,
+29229,73261,72683,73261,73237,73261,73087,73261,    9,73261,73253,73276,
+73253,73261,    9,73280,    3,73221,73225,73285,73249,73285,73227,73285,
+73247,73285,    9,73293,    9,73220,    2,73296,73285,73299,    2,73297,
+73253,73303,   17,71229,10161,73306,10159,73309,54339,73307,54331,73313,
+49217,73307,49229,73317,54331,73306,54339,73321,49229,73306,49217,73325,
+65037,73306,63823,73329,13755,73306, 9377,73333,27995,73307,27533,73337,
+17573,73307,10001,73341,    7,73306,    3,73345,    7,73346,73307,73349,
+    1,73346,73351,73353,    1,73345,    3,73356,21604,73345,    0,73306,
+    3,73363,    0,73364,73307,73367,    6,73364,73369,73371,    6,73363,
+    3,73374, 1274,73363,  586,73306,    3,73381,    1,73382,    1,73381,
+    3,73386,21604,73381,60856,73306,    3,73393,    6,73394,    6,73393,
+    3,73398, 1274,73393,10001,73306,63823,73405, 9377,73405,17573,73405,
+27533,73306, 9377,73413,63823,73413,27995,73413, 9377,73307,13755,73421,
+27533,73421,10001,73421,63823,73307,65037,73429,10001,73429,27533,73429,
+60857,73307,63697,73437,63779,73437,73397,73437,73401,73437,73371,73437,
+73377,73437,    7,73437,63709,73437,35893,73437,37897,73437,38299,73437,
+73379,73437,73403,73437, 1275,73437,63679,73465,73363,73465,73393,73465,
+  587,73307, 1971,73473, 3507,73473,73385,73473,73389,73473, 5231,73473,
+73353,73473,73359,73473,    0,73473,21783,73473,23983,73473, 4625,73473,
+10603,73473,73361,73473,73391,73473,21605,73473,  713,73503,73345,73503,
+73381,73503, 1011,73306,18967,73511, 9617,73511, 1275,73306,72439,73517,
+72447,73517, 3621,73517, 1991,73517,    1,73517,73473,73527,73489,73517,
+60969,73517,62095,73517, 4907,73517,17711,73517,72457,73517,60857,73517,
+ 1325,73543,72435,73543,21605,73306,23713,73549,23709,73549,26865,73549,
+26715,73549,    6,73549,73437,73559,73451,73549,10159,73549,10111,73549,
+26719,73549,10113,73549,67425,73549,70753,73549,70471,73549,23715,73549,
+  587,73549,26625,73581,10107,73581,23651,73581, 1011,73307, 9565,73589,
+    2,73306,36729,73593,68447,73593,67547,73593,70731,73593,    2,73307,
+36727,73603,68451,73603,37895,73603,36079,73603,35575,73603,   15,73306,
+21605,71229,26867,73616,26865,73619, 1179,73617, 1177,73623,  987,73617,
+  989,73627, 1177,73616, 1179,73631,  989,73616,  987,73635,  809,73616,
+  713,73639,  117,73616,   25,73643, 1489,73617, 1471,73647,  147,73617,
+   53,73651,26219,73617,    5,73616,    7,73657,    5,73658,73617,73661,
+    2,73658,73663,73665,    2,73657,    7,73668, 1368,73657,    3,73616,
+    7,73675,    3,73676,73617,73679,    4,73676,73681,73683,    4,73675,
+    7,73686,   16,73675,   10,73616,    7,73693,    2,73694,    2,73693,
+    7,73698, 1368,73693,  586,73616,    7,73705,    4,73706,    4,73705,
+    7,73710,   16,73705,44243,73617,48466,73617,  340,73617, 1397,73617,
+   53,73616,  713,73725,  305,73725,   25,73725,  147,73725, 1471,73616,
+   25,73735,  305,73735,  713,73735, 1489,73735,   25,73617,  117,73745,
+  253,73745, 1471,73745,   53,73745,  713,73617,  809,73755,  253,73755,
+   53,73755, 1471,73755,  253,73616,  305,73765,   25,73765,  713,73765,
+  305,73617,  253,73773, 1471,73773,   53,73773,    9,73617,46863,73780,
+  587,73617, 9381,73785, 9439,73785,73709,73785,73713,73785,25519,73785,
+73683,73785,73689,73785,    5,73785, 9383,73785,62077,73785,64317,73785,
+64815,73785,73691,73785,73715,73785,   17,73785, 9377,73815,73675,73815,
+73705,73815,   11,73617, 7979,73823, 8067,73823,73697,73823,73701,73823,
+73603,73823,73665,73823,73671,73823,    3,73823, 7981,73823,39747,73823,
+43027,73823,43837,73823,73673,73823,73703,73823, 1369,73823, 7971,73853,
+73657,73853,73693,73853,   17,73616,23709,73861,23713,73861,10159,73861,
+10111,73861,    2,73861,73823,73871,73839,73861,26865,73861,26715,73861,
+10113,73861,26719,73861,67425,73861,70471,73861,70753,73861,23715,73861,
+  587,73861,10107,73893,26625,73893,23651,73893, 1369,73616,72365,73901,
+72373,73901, 9927,73901, 9891,73901,    4,73901,73785,73911,73801,73901,
+ 9895,73901,19687,73901,20843,73901,21127,73901,72383,73901,   11,73901,
+ 9875,73927,72361,73927,46863,73617,    9,73932,    6,73616,62905,73937,
+68761,73937,70401,73937,67541,73937,    7,73616,    6,73617,62883,73949,
+68767,73949,64267,73949,62235,73949,38881,73949,73437,73949,73947,73949,
+72787,73949,    7,73617,25793,73967,41019,73967, 8495,73967,73937,73967,
+72793,73967,  265,73966,  265,73617,    6,73981,    7,73981,    6,73980,
+73985,73987,    7,73980,73983,73991,  903,71229,64148,73995,57522,73994,
+58782,73994,58362,73994,52501,73995,52692,73994,46863,73994,56555,74008,
+    9,73994,56555,74012,  483,73994,56555,74016,49713,74016,49713,73994,
+  483,74022,   15,73995,  483,74027,    7,73994,   59,74031, 1325,74031,
+  331,74031,    7,73995,60857,74038,59875,74039,  375,74039, 9805,74039,
+53391,74039,60857,73995,    6,74051,    7,74051,    6,74050,74055,74057,
+    7,74050,74053,74061,56555,73994,    7,74065,46863,74064,  483,74064,
+    9,74064,58742,71229,    7,74075,    9,74074,46863,74074,  483,74074,
+56555,71229,43502,74085,21036,74085,    6,74089,    6,74088,43503,74085,
+    6,74095,    6,74094,21037,74085,59634,74085,59635,74085,    6,74105,
+    6,74104,21104,74085,59645,74085,43838,74085,21548,74085,21526,74085,
+    5,74118,59644,74085,19624,74085,18967,74085,    5,74126,    6,74128,
+    6,74129,    6,74126,    5,74134,    6,74127,   14,74126,38305,74085,
+    2,74142,59619,74085,    2,74146,    5,74085,59961,74151,    6,74151,
+21526,74150,    6,74150,18967,74158,18967,74150,    6,74162,    6,74163,
+    2,74085,59619,74168,38305,74168,   14,74085,18967,74174,21527,74085,
+74155,74179,    9,74179,19625,74085,21549,74085,43839,74085,21105,74085,
+47640,74084,  922,74084,  918,74084, 1505,74084,  668,74084, 1419,74084,
+  483,74084,  903,74204,   11,74085,    9,74209,   15,74085,74139,74213,
+46863,74084,  903,74216,    9,74084,   11,74221,  903,74220,  587,74220,
+  587,74084,    9,74228,    6,74084,74191,74233,74189,74233,74187,74233,
+74113,74233,74087,74233,74101,74233,74103,74233,74171,74233,74169,74233,
+59619,74251,74149,74233,72981,74233,74185,74233,74145,74233,74173,74233,
+74213,74233,59381,74233,    7,74084,74093,74269,74099,74269,74123,74269,
+74109,74269,74159,74269,74089,74269,74095,74269,74105,74269,74151,74269,
+74111,74269,74115,74269,74117,74269,74157,74269,74121,74269,21105,74269,
+21549,74269,65513,74269,65791,74269,65407,74269,74125,74269,19625,74269,
+65171,74269,74175,74269,74131,74269,74129,74269,74137,74269,74177,74269,
+74161,74269,74165,74269,74163,74269,74141,74269,59619,74269,   15,74269,
+    6,74085,21036,74336,74269,74339,43503,74336,74269,74343,59635,74336,
+74269,74347,    5,74336,74269,74351,18967,74350,74269,74355,18967,74336,
+    5,74358,74269,74361,    7,74085,74091,74365,74097,74365,74107,74365,
+74155,74365,21183,74365,65493,74365,74133,74365,74167,74365,    9,74365,
+  959,74365,   47,74365,  759,74365,  903,74084,    7,74391,  483,74390,
+    9,74390,46863,74390,    9,71229,20035,74400,58742,74400,58930,74400,
+19917,74400,  903,74400,56555,74410,  265,74400, 8861,74415,  587,74400,
+56555,74418,56555,74400,   11,74423,  903,74422,  587,74422,  265,74401,
+ 8495,74431,   11,74431,    3,74400,70177,74437,70176,74436,74439,74441,
+70176,74437,70177,74436,74445,74447, 1141,74437, 1447,74437,   33,74437,
+   11,74437,37409,74437,    3,74401,  113,74461,   11,74400,21522,71229,
+    7,74467,63452,71229,    7,74471,13673,71229,    7,74475,17049,71229,
+    3,74478,48643,74481,    2,74479,    3,74479,48637,74487,49581,74487,
+47813,74487,21315,71229,  165,74494, 1011,74494,    7,74499,16163,71229,
+    2,74503,72683,74505,73087,74505,16171,74505,  375,74503,64669,71229,
+    7,74515,  265,74517,12377,71229,  256,74521,17455,74520,    7,74520,
+  375,74527,    7,74521,  241,74530,  331,74531,60857,74520,    7,74537,
+  241,74521,    7,74540,10385,71229,  375,74545,70899,71229,    7,74549,
+18391,71229,    7,74553,18617,71229,    7,74557,12705,71229,    7,74561,
+70573,71229,69275,74564,    7,74567,    3,71228,74332,74571,72750,74571,
+71253,74571,72985,74571,72147,74571,71783,74571,71577,74571,67600,74571,
+45491,74571,42800,74571,59710,74571,74365,74593,74269,74571,59619,74596,
+72735,74571,59619,74600,59694,74571,60563,74571,  629,74571,  101,74571,
+  705,74571,  299,74571,  128,74571,  828,74571,  394,74571,48122,74571,
+70327,74571,66930,74571, 9606,74571,10374,74571,  113,74571,    9,74632,
+74465,74571,73153,74571,73031,74571,73057,74571,73131,74571,71939,74571,
+72733,74571,74415,74571,72145,74571,59381,74653,42134,74571,10291,74571,
+   17,74658,51992,74571,  375,74571,  241,74664,65869,74664,49713,74664,
+60796,74571,74213,74673,  256,74571,  803,74571,  483,74678,  483,74571,
+  803,74682,31103,74571,65869,74686,    6,74571,59619,74690,74365,74693,
+56555,74690,74213,74697,    7,74571,  241,74700,    7,74570,57811,74705,
+59933,74705,59743,74705, 9839,74705, 9579,74705,39619,74705,51421,74705,
+ 4287,74705, 4303,74705, 8093,74705, 3837,74705,53487,74705,42113,74705,
+42435,74705,53703,74705,42613,74571,   17,74736,46863,74571,12377,74740,
+    9,74571,  113,74744,49713,74571,  375,74748,   17,74571,42613,74752,
+59619,74752,10291,74752, 9565,74752,41941,74752, 9565,74571,    7,74765,
+   17,74764,65869,74571,60796,74771,60797,74771,31103,74770,60797,74770,
+74773,74779,60796,74770,74775,74783,  375,74770,  241,74571,  375,74788,
+    7,74788,56555,74571,    5,74795,74269,74797,72735,74797,    6,74797,
+74365,74803,    6,74796,74269,74807,72735,74807,   14,74795,72735,74813,
+74269,74813,   15,74795,    6,74795,    5,74820,74269,74823,72735,74823,
+    7,74795,74803,74829,    6,74794,74213,74833,74819,74833,    7,74794,
+74807,74839,74823,74839,71229,74838,74807,74845,74823,74845,74797,74845,
+74813,74845,74813,74839,12377,74571,46863,74856,41941,74571,    7,74861,
+   17,74860,59619,74571,74269,74866,72735,74866,    6,74866,74365,74873,
+    6,74867,74269,74877,72735,74877,    7,74867,   17,74866,    2,71228,
+71233,74887,56555,74887,72129,74887,72127,74887,59619,74895,71235,74887,
+72790,74887,71627,74887,74153,74887,74155,74887,74365,74906,74372,74887,
+74158,74887,74269,74913,74279,74887,74350,74887,74269,74919,74353,74887,
+74266,74887,74150,74887,    6,74927,74365,74929,    6,74926,74269,74933,
+74269,74927,74287,74887,74336,74887,    5,74940,74269,74943,60261,74887,
+71629,74887,63737,74887,37179,74887, 9535,74887,63743,74887, 9537,74887,
+37185,74887,74264,74887,74174,74887,74269,74965,74315,74887,73073,74887,
+37887,74887,37205,74887,37235,74887,74085,74887,    5,74978,    6,74981,
+74365,74983,    6,74980,74269,74987,74269,74981,    6,74978,    5,74992,
+74269,74995,    6,74979,74213,74999,   14,74978,74269,75003,    5,74887,
+74336,75006,74269,75009,74085,75006,    6,75013,74365,75015,    6,75012,
+74269,75019,74269,75013,74085,75007,74233,75025,    6,75006,72735,75029,
+74085,75028,74269,75033,74269,75029,74085,75029,74233,75039,    7,75006,
+71853,75043,72049,75043,72177,75043,73901,75043,    6,75007,74365,75053,
+    7,75007,72131,74887,72753,74887,74335,74887, 9563,74887,74382,74887,
+   10,74887,72177,75069,72049,75069,71853,75069,73901,75069,   14,74887,
+74085,75079,74233,75081,74085,75078,74269,75085,72735,75079,74269,75079,
+72191,74887,72069,74887,73927,74887,71881,74887,64759,74887,63763,74887,
+63813,74887, 9559,74887,74213,74887,74233,75108,74365,74887,74155,75112,
+    9,75112,43123,74887,42606,74887,53318,74887, 9362,74887,27218,74887,
+28189,74887,74233,74887,59381,75130,74213,75130,72789,74887,59381,75136,
+64289,74887,26182,74887,28991,74887, 8804,74887,54289,74887,53802,74887,
+ 8150,74887, 1290,74887,63679,75155, 9533,75155,37145,75155,  525,74887,
+ 9533,75163,63679,75163,37145,75163,  922,74887, 1413,74887,73615,74887,
+73127,74887,73009,74887,73035,74887,73081,74887,71943,74887,72729,74887,
+73511,74887,41762,74887, 7971,74887,    9,75192,53517,74887,    9,75196,
+  483,74887,  903,75200, 9195,74887,    9,75204, 1275,74887,   17,75208,
+ 9533,75211,37145,75211,63679,75211,27021,74887,    9,75218,    7,74887,
+    2,75223,60857,75225,71229,75227,    5,75222,71853,75231,72049,75231,
+72177,75231,73901,75231,75229,75231,    2,75222,73616,75243,75231,75245,
+21605,75243,71229,75248,75231,75251,71229,75243,21605,75254,75231,75257,
+    6,74887,74150,75260,74269,75263,74085,75260,    5,75266,74269,75269,
+56555,75261,71229,75272,74085,75261,74155,75277,    9,75277,    5,75260,
+72735,75283,74085,75282,74269,75287,74269,75283,74085,75283,74233,75293,
+75275,75283,   11,75261,21604,75299,21604,75298,21605,75299,75303,75305,
+21605,75298,75301,75309,52915,74887,    9,75312,    6,74886,23717,75317,
+24522,75317,24447,75317,23939,75322,23939,75317,24447,75326,22956,75317,
+23651,75331,   17,75317,21605,75335,24447,75337,21605,75334,23651,75341,
+21605,75317,   17,75345,23939,75347,   17,75344,23651,75351,    7,74886,
+27021,75355,24095,75355, 9195,75355,52915,75355,21605,75355,    9,75365,
+67297,75355,26907,75355, 9755,75355, 9317,75355, 3833,75355,23651,75355,
+51435,75355,27323,75355, 4321,75355,69729,75355,53215,75355, 4295,75355,
+70097,75355,53941,75355,10171,75355, 5045,75355,11277,75355,42155,74887,
+    9,75402,   19,74887,   12,74887,   11,74887,    9,75410,    9,74887,
+74365,75414,42155,75414,27021,75414,52915,75414, 9195,75414,25793,75414,
+53517,75414, 7971,75414, 8495,75414,41019,75414,   11,75414,   17,74887,
+ 1275,75438, 9533,75441,37145,75441,63679,75441, 8495,74887,    9,75448,
+  903,74887,  483,75452,21605,74887,26219,75457,42810,75456,75056,75456,
+75057,75457,75463,75465,75053,75457,42810,75457,75057,75456,75056,75457,
+75473,75475,42811,75456,75471,75479,42811,75457,75461,75483,44243,75457,
+  375,75457,    6,75457,    7,75457,25793,75493,    6,75456,75493,75497,
+    7,75456,75491,75501,41019,74887,    9,75504,59381,74887,72789,75508,
+74233,75508,25793,74887,    9,75514,26625,74887,    6,75518,    7,75518,
+    6,75519,75523,75525,    7,75519,75521,75529, 9731,74887,    6,75532,
+    7,75532,    6,75533,75537,75539,    7,75533,75535,75543,69513,74887,
+    6,75546,    7,75546,    6,75547,75551,75553,    7,75547,75549,75557,
+    7,71228,73276,75561,27306,75561,73261,75561,    9,75566,24095,75561,
+52603,75561,53910,75561,55537,75561,20053,75561,20831,75561,19783,75561,
+64289,75561,27021,75561,25793,75586,  265,75587,  959,75561,60857,75593,
+58775,75561, 5045,75561,11277,75561, 4551,75561,70136,75561,10196,75561,
+  273,75561, 1477,75561,  281,75561,  948,75561, 1516,75561,  922,75561,
+ 1413,75561,52915,75561,  265,75623,   47,75561,60857,75627,25793,75561,
+27021,75630, 9195,75561,  265,75635,  759,75561,60857,75639,   89,75561,
+ 5019,75643,60857,75643, 1505,75561, 1011,75648,  587,75561,60857,75653,
+70573,75653, 1369,75561,43503,75659,  483,75561,  903,75662,  165,75561,
+  903,75666, 1141,75561,18967,75671, 1447,75561,18967,75675,    2,75561,
+61780,75679,    9,75679,60857,75682,54295,75679,70085,75679,53925,75679,
+10155,75679,11529,75679,60857,75679,    9,75696,    3,75561,73221,75701,
+    9,75703, 8063,75701,53667,75701,42361,75701,   33,75561,18967,75713,
+    2,75560,27021,75717,24095,75717, 9195,75717,52915,75717,21605,75717,
+    9,75727,67297,75717,23651,75717,51435,75717,27323,75717, 4321,75717,
+ 9755,75717,26907,75717, 9317,75717, 3833,75717,69729,75717,53941,75717,
+10171,75717,70097,75717,53215,75717, 4295,75717, 5045,75717,11277,75717,
+    3,75560,57811,75765,59933,75765,59743,75765,39619,75765,51421,75765,
+ 4287,75765, 4303,75765, 9839,75765, 9579,75765, 8093,75765, 3837,75765,
+42113,75765,53487,75765,42435,75765,53703,75765,  265,75561,53813,75796,
+69877,75796,10107,75796, 1011,75561, 1505,75804,54597,75805,21605,75561,
+    9,75811,  145,75811,  903,75561,  165,75816,  483,75816,54295,75817,
+    9,75561,73261,75824,69877,75561,  265,75828,10107,75561,  265,75832,
+53813,75561,  265,75836,    6,71228,63091,75841,63099,75841,63117,75841,
+25451,75841,53597,75841,42283,75841,61289,75841,61281,75841,62345,75841,
+    0,75841,    3,75860,71891,75863,72017,75863,72197,75863,73517,75863,
+    3,75861,62359,75841,60856,75841,72197,75877,72017,75877,71891,75877,
+73517,75877,72211,75841,72037,75841,73543,75841,71919,75841,19739,75841,
+61649,75841,61263,75841,61323,75841,20763,75841, 1011,75903, 1010,75902,
+75905,75907, 1010,75903, 1011,75902,75911,75913,25380,75841, 7971,75917,
+53517,75917,42155,75917,63015,75841,53517,75925, 7971,75925,42155,75925,
+ 1369,75841,21605,75932,53517,75935,42155,75935, 7971,75935,    3,75841,
+    6,75943,   11,75945,71229,75947,    0,75942,71891,75951,72017,75951,
+72197,75951,73517,75951,75949,75951,    6,75942,73306,75963,75951,75965,
+   17,75963,71229,75968,75951,75971,71229,75963,   17,75974,75951,75977,
+    2,75841,60857,75981,   16,75983,   16,75982,   17,75983,75987,75989,
+   17,75982,75985,75993,    2,75840,23717,75997,24522,75997,23939,75997,
+24447,76002,24447,75997,23939,76006,22956,75997,23651,76011,21605,75997,
+   17,76015,23939,76017,   17,76014,23651,76021,   17,75997,21605,76025,
+24447,76027,21605,76024,23651,76031,21605,75841, 1369,76034,53517,76037,
+42155,76037, 7971,76037,   17,75841,37844,76044,75872,76044,75873,76045,
+76049,76051,37844,76045,75873,76044,75872,76045,76057,76059,37845,76044,
+76055,76063,37845,76045,76047,76067,    7,71229,74797,76071,74829,76073,
+  264,76071,    5,76071,    3,76078,    3,76079,    5,76070,75925,76085,
+63014,76085,75841,76089,75917,76085,25381,76085,75841,76095,75935,76085,
+76037,76085,  483,76085,60857,76102,75841,76105,60857,76085,  483,76108,
+75841,76111,32805,76070,34655,76115,33773,76115,34447,76115,33221,76115,
+32805,76071,34003,76125,33319,76125,34447,76071,35031,76131,65407,76071,
+65335,76135,65076,76070,65513,76139,65791,76139,65407,76139,65171,76139,
+65076,76071,65625,76149,65267,76149,20035,76070,  375,76155,74794,76071,
+59381,76159,74819,76159,74571,76071,56555,76165,59619,76167,56555,76164,
+59381,76171,12377,76070,  375,76175,49204,76071, 1369,76071,  241,76181,
+56555,76071,74571,76184,59381,76187,59381,76185,74571,76191,49205,76071,
+65869,76195, 1275,76071,  903,76199,60857,76070,   59,76203, 1325,76203,
+  331,76203,  265,76203,  903,76070,   59,76213, 1325,76213,  331,76213,
+56555,76070,74877,76221,74866,76221,65513,76221,65791,76221,65407,76221,
+74807,76221,74823,76221,74797,76221,21105,76221,75029,76221,75283,76221,
+21549,76221,19625,76221,65171,76221,75079,76221,74813,76221,59619,76221,
+74571,76254,74571,76221,59619,76258,   15,76221,74887,76263,21605,76070,
+73949,76267,  265,76071,63823,76271,63679,76271,72619,76271, 9377,76271,
+ 9533,76271,37145,76271,    2,76070,76077,76285,76081,76285,55839,76285,
+54159,76285,54497,76285,51803,76285,73123,76285,76179,76285,65869,76301,
+  265,76285,    3,76070,76196,76307,67988,76307,   33,76307, 1447,76307,
+ 1141,76307,76271,76307,76195,76307,65869,76320,    9,76307,46863,76307,
+65869,76326,65869,76307,76195,76330,46863,76330,    2,76071,76310,76337,
+76328,76337,76334,76337,76083,76337,   10,76337,    5,76337,    7,76348,
+    7,76337,    5,76352,55803,76337,54225,76337,54477,76337,51593,76337,
+67988,76337,76307,76364,64345,76337,76324,76337,73121,76337,72713,76337,
+76326,76337,65869,76376,    9,76337,76307,76380,60857,76337,71229,76385,
+76347,76387,76351,76387,76355,76387,  903,76337,46863,76337,76330,76396,
+65869,76396,76307,76400,76307,76396,65869,76404,76330,76337,46863,76408,
+65869,76337,76326,76412,46863,76412,76307,76416,76307,76412,46863,76420,
+76307,76337,67988,76424,    9,76424,46863,76424,65869,76430,65869,76424,
+46863,76434,    3,76071,    5,76438,76285,76441,  113,76439,46863,76438,
+76285,76447,65869,76449,76285,76439,67988,76453,    9,76453,46863,76453,
+65869,76458,65869,76453,46863,76462,   15,76071,74485,76467,73261,76467,
+46863,76071,    3,76472,76285,76475,65869,76477,    3,76473,76412,76481,
+65869,76481,76337,76484,76337,76481,65869,76488,65869,76070,  375,76493,
+70176,71229,  375,76497,    3,71229,70554,76500,    5,76501,    1,76505,
+71229,76507,    2,76509,59961,76505,74887,76513,    6,76505,76511,76517,
+73261,76517,    0,76500,75163,76523,  524,76523,74887,76527,75155,76523,
+ 1291,76523,74887,76533,75211,76523,75441,76523,  483,76523,   11,76540,
+74887,76543,   11,76523,  483,76546,74887,76549,   33,76501,    9,76553,
+ 8147,76501,42315,76501,53777,76501,70555,76500,70176,76500,    9,76565,
+43848,76501,70177,76501,76563,76571,76566,76571,    9,76571,76565,76576,
+76565,76571,    9,76580, 1141,76501,    9,76585, 1447,76501,    9,76589,
+69849,76500,68155,76593,17049,76500,48643,76597, 1369,76501,  803,76601,
+   15,76500,76337,76605,37409,76501,    9,76609,    9,76500,70177,76613,
+76565,76615,70177,76612, 1141,76613, 1447,76613,   33,76613,   11,76613,
+37409,76613,   11,76501,    9,76631,    6,76500,    7,76500,   33,76637,
+ 1447,76637, 1141,76637,76271,76637,    6,76501,60856,76647,    0,76647,
+    3,76650,    3,76647,    0,76654,   11,76647,71229,76659,76649,76661,
+76653,76661,76657,76661,    7,76501,43503,76668,70177,76500,    9,76672,
+70176,76501,76619,76677,76503,76677,76675,76677,76673,76677,    9,76685,
+43503,76501,    7,76688,   17,76689, 1011,76501,  375,76695,    7,76695,
+18967,76501,    4,76700,    5,76700,76071,76705,    6,76704,    6,76705,
+76070,76701,76709,76713,76705,76713,   14,76700,76713,76719,71229,76701,
+    7,76723,76711,76725,    7,76722,76709,76729,76705,76729,76719,76729,
+   15,76723,76071,76701,76703,76739,   15,76700,76739,76743,    6,76700,
+    5,76746,76729,76749,76713,76749,    7,76700,76707,76755,76711,76755,
+    6,76701,76743,76761,76737,76761,    7,76701,76749,76767,76709,76767,
+71229,76766,76749,76773,76709,76773,76705,76773,76719,76773,76719,76767,
+65869,76500,68155,76785,68109,76785,  256,76785,    7,76785,  241,76792,
+  241,76785,    7,76796,70572,71229,68155,76801,68109,76801,  256,76801,
+    7,76801,  241,76808,  241,76801,    7,76812,    2,71229,    0,76817,
+    4,76818,    0,76816,    2,76823,    5,76816,62284,76817,62186,76817,
+64248,76817,62504,76817,64205,76817,61690,76817,52501,76817,70021,76817,
+17496,76817,11179,76817,10187,76817,53967,76817,17455,76817,    9,76852,
+16065,76817,   16,76857,   16,76856,   17,76857,76861,76863,   17,76856,
+76859,76867,70802,76817,  340,76817,60857,76872,64148,76817,  265,76876,
+    9,76817,17455,76880,  375,76817,60857,76884,  587,76817,   17,76889,
+37145,76891, 9533,76891,76523,76891,76821,76891,63679,76891,44243,76817,
+60857,76902,49713,76903,   17,76816,36729,76909,68447,76909,67547,76909,
+70731,76909,49713,76816,44243,76919,54295,76817,    9,76923,    6,76816,
+66737,76927,36661,76927,62741,76927,68381,76927,68727,76927,    7,76816,
+54497,76939,55839,76939,54159,76939,51803,76939,73123,76939,  265,76939,
+    7,76817,62494,76952,70573,76952,  265,76952,60857,76958,60857,76952,
+  265,76962,  265,76953,60857,76967,62494,76817,    7,76970,43215,76817,
+    9,76975,  265,76817,64148,76978,  483,76979,    7,76978,60857,76984,
+60857,76978,    7,76988,60857,76817,42810,76993,42810,76992,42811,76993,
+76997,76999,  375,76992,  340,76992,42811,76992,76995,77007,44243,76992,
+    6,76992,    7,76992,  265,77014,    6,76993,77015,77019,    7,76993,
+77013,77023,  265,76993,    7,77027,  265,76992,    7,77030,65869,76817,
+69275,77035,    7,77037,70573,76817,    6,77041,    7,77041,    6,77040,
+77045,77047,    7,77040,77043,77051,65869,76816,69716,77055,    7,77055,
+69513,77058,69513,77055,    7,77062,70922,71229,69716,77067,    7,77067,
+69513,77070,69513,77067,    7,77074,    6,71229,74890,77079,59619,77081,
+38056,77078,    5,77084,76825,77079,76827,77089,55814,77078,55815,77079,
+77093,77095,55815,77078,55814,77079,77099,77101, 1346,77078, 1346,77079,
+ 1347,77078,77107,77109,17126,77079,17125,77079,    2,77114,17127,77079,
+ 9565,77119,74169,77079,59619,77123,60621,77079,59619,77127,38056,77079,
+38057,77078,44195,77133,58303,77079, 1010,77079, 1010,77078,77119,77141,
+35187,77079,    2,77144,    0,77079,    4,77149,    2,77151,71229,77152,
+71229,77151,    2,77156,    2,77157,76816,77151, 1011,77149,71229,77165,
+    5,77079,    1,77168,    5,77078,38056,77173,77133,77175,    2,77172,
+58302,77079,77141,77181, 9565,77181,59619,77181,20501,77079, 1011,77189,
+ 1010,77188,77191,77193, 1010,77189, 1011,77188,77197,77199,  567,77079,
+21604,77203,21604,77202,21605,77203,77207,77209,21605,77202,77205,77213,
+ 1347,77079,77105,77217,74887,77079,56555,77220,59619,77223,56555,77221,
+59381,77227, 9875,77079, 1011,77231, 1010,77230,77233,77235, 1010,77231,
+ 1011,77230,77239,77241,56555,77079,74887,77244,59619,77247,59619,77245,
+74887,77251, 1011,77244, 9565,77255,77141,77255,59619,77255, 1011,77245,
+ 9617,77263,77139,77263,74887,77263,  587,77079,21605,77271,42155,77273,
+53517,77273,76085,77273,77171,77273, 7971,77273, 1011,77078,77113,77285,
+77117,77285,74505,77285,77131,77285,77137,77285,77147,77285,73261,77285,
+38057,77079,77179,77301,77087,77301,41941,77301,76827,77301, 9565,77301,
+59619,77301,77141,77301,56555,77078,72981,77317,75508,77317,74887,77317,
+59381,77322,59381,77317,74887,77326,21605,77078,62905,77331,68761,77331,
+67541,77331,70401,77331,73967,77331, 1011,77079,56555,77343,59381,77345,
+56555,77342,59619,77349,77141,77349, 9565,77349,    2,77078,66737,77357,
+    5,77356,77301,77361,62741,77357,36661,77357,68727,77357,68381,77357,
+    3,77078,77161,77373,    2,77079,17125,77376,77285,77379,35187,77376,
+77285,77383,    3,77079,77155,77387,77159,77387,77163,77387,77167,77387,
+   11,77079,37844,77397,37844,77396,37845,77397,77401,77403,37845,77396,
+77399,77407,65869,71229, 1530,77410,  842,77410,48535,77410,  669,77410,
+ 1419,77410,49514,77410,  136,77410,49515,77410,  137,77410,  843,77411,
+77415,77431, 1531,77411,77413,77435,  843,77410, 1530,77411, 1531,77410,
+77441,77443,  842,77411,77439,77447, 1418,77410,48534,77410,  668,77410,
+  587,77410,46863,77456,    9,77456, 1369,77410,   15,77462,    9,77410,
+    2,77467,    2,77466,  587,77466,  265,77410,  375,77475,   15,77410,
+ 1369,77478,46863,77410,    2,77483,    2,77482,  587,77482,    7,77411,
+   59,77491, 1325,77491,  331,77491,  265,77491,    6,77410,77491,77501,
+    2,77503,    3,77503,    2,77502,77507,77509,    3,77502,77505,77513,
+    3,77411,67577,77517,77425,77517,77423,77517,68139,77517,70979,77517,
+77455,77517,77453,77517,77421,77517,77471,77517,77487,77517,77461,77517,
+77459,77517,77473,77517,77489,77517,    7,77517, 1011,77517,    7,77549,
+    2,77410,    9,77552,77517,77555,46863,77552,77517,77559,69716,77553,
+77546,77553,    7,77553,69513,77566,77517,77566,69513,77553,    7,77572,
+77517,77553,    6,77577,    7,77577,    6,77576,77581,77583,    7,77576,
+77579,77587,    2,77411,76517,77591,29229,77591,72789,77591,77429,77591,
+77427,77591,72683,77591,74233,77591,77317,77591,77451,77591,77419,77591,
+77417,77591,77285,77591,73087,77591,77465,77591,77481,77591,    7,77591,
+70573,77591,    7,77625,    3,77410,    4,77628,77591,77631,    1,77628,
+    5,77628,    0,77628,77591,77639,    5,77629,    6,77643,77591,77645,
+68155,77629,77469,77629,77485,77629,68109,77629,77623,77629,77631,77657,
+77639,77657,  256,77629,77622,77629,77635,77665,77637,77665,    6,77629,
+77632,77671,77640,77671,77631,77671,77591,77676,77639,77671,77591,77680,
+77591,77671,77631,77684,77639,77684,    7,77629,77635,77691,77591,77693,
+77637,77691,77591,77697,  241,77690,77591,77690,77635,77703,77637,77703,
+  241,77629,    7,77708,77591,77629,    6,77713,    7,77713,    6,77712,
+77717,77719,    7,77712,77635,77723,77637,77723,77715,77723,    6,77411,
+    7,77410,  375,77733,77731,77733,    2,77737,    3,77737,    2,77736,
+77741,77743,    3,77736,77739,77747,    1,    6,18363,77751, 4389,77751,
+18362,77751, 4388,77751,70572,77750,70667,77761,70849,77761,70803,77761,
+56555,77767,70883,77761,  272,77751, 8997,77773, 4425,77773, 8452,77751,
+  251,77779, 8841,77779, 8453,77751,  273,77751, 4139,77751, 8429,77751,
+ 4138,77751, 8428,77751,70879,77751,70797,77797,18257,77751,  465,77801,
+  445,77751,17827,77805, 4371,77751,  265,77808,18339,77751,  265,77812,
+64953,77751,  375,77817,14888,77751,  375,77821,13569,77751,  375,77825,
+ 4137,77751,  265,77828, 8401,77751,  265,77832,  413,77750,77835,77837,
+77831,77837,77795,77837,77793,77837,77815,77837,77811,77837,77757,77837,
+77759,77837,  241,77837, 1217,77750,  412,77750, 8401,77859, 4137,77859,
+18339,77859, 4371,77859,77791,77859,77789,77859,77753,77859,77755,77859,
+ 1216,77750,40461,77751,    9,77879,59573,77751,  375,77883,69467,77751,
+  375,77887, 7047,77751,  412,77891,  413,77890,77893,77895,  413,77891,
+  412,77890,77899,77901,12615,77751,  375,77905,45880,77751,46275,77909,
+33390,77751,34003,77913,77462,77751,77591,77917,65232,77751,65625,77921,
+  923,77751,16481,77925,16783,77925,18797,77925,25367,77751,    9,77933,
+68975,77751,  375,77937,62984,77751,    9,77941, 1412,77751,17827,77945,
+  412,77751,77837,77949, 1216,77751, 9137,77751,  375,77955,  253,77751,
+ 9136,77959, 9137,77959,17826,77959,    1,77959,  413,77966,17827,77959,
+  413,77959,    1,77972,  265,77958, 8997,77977, 4425,77977,77963,77977,
+77965,77977,77969,77977,77975,77977,  265,77959, 8997,77990, 8997,77959,
+  265,77994,  265,77995,12377,77959, 8337,77751,  266,78003,  267,78003,
+  464,78003,    6,78003,  413,78010,  465,78003,  413,78003,    6,78016,
+  265,78002,  251,78021, 8841,78021,78007,78021,78009,78021,78013,78021,
+78019,78021,  265,78003,  251,78034,  251,78003,  265,78038,  265,78039,
+  375,78003,38057,77751,  265,77751,18339,78048,77837,78051, 4371,78048,
+77837,78055,  253,78048, 8997,78059, 4425,78059, 8337,78048,  251,78065,
+ 8841,78065,77837,78049, 8401,78071, 4137,78071,18339,78071, 4371,78071,
+ 4137,78048,77837,78081, 8401,78048,77837,78085,  241,78049, 8401,78089,
+ 4137,78089, 1369,78048,17827,78095,  241,78048, 1011,77751,56555,78101,
+60369,78103,  241,77751,  413,78107,14315,78106,  375,78111,57522,78107,
+67028,78107,  265,78107,60857,78106,    9,78121,56555,78107,    9,78124,
+65869,78107,  483,78128,  483,78107,65869,78132,    9,78107,56555,78136,
+  265,78106, 8685,77751,  375,78143,  264,77750,78066,78147,78060,78147,
+78091,78147,78093,78147,18339,78147, 4371,78147,17911,78147,13433,78147,
+13411,78147,13635,78147,77978,78147,78022,78147,77999,78147,78043,78147,
+77774,78147,77780,78147,64733,78147,64955,78147,78021,78147,  251,78184,
+77977,78147, 8997,78188,78065,78147,  251,78192,78059,78147, 8997,78196,
+77779,78147,  251,78200,77773,78147, 8997,78204, 9139,78147, 9123,78147,
+ 9065,78147,14935,78147,64919,78147,59463,78147,69357,78147,59533,78147,
+69427,78147,59587,78147,69481,78147,78088,78147, 8401,78231, 4137,78231,
+ 8997,78147,78059,78236,77977,78236,77773,78236,  251,78147,78065,78244,
+78021,78244,77779,78244,27979,78147,26293,78147,41503,78147, 8685,78147,
+78141,78147,77949,78147,78099,78147,78049,78147, 8337,78267,  251,78269,
+  253,78267, 8997,78273,  241,78266, 8401,78277, 4137,78277,  241,78267,
+ 1369,78147,  241,78147,    6,78287,78065,78289,78021,78289,77779,78289,
+    1,78287,78059,78297,77977,78297,77773,78297,78049,78286, 8401,78305,
+ 4137,78305,16381,78147,19513,78147,35843,78147,13325,78147,70407,78147,
+69063,78147,67565,78147,  341,78147,64669,78325, 8997,78325,59381,78325,
+69275,78325,65869,78325,  241,78325,  471,78147,  367,78147,  357,78147,
+ 8401,78147, 4137,78147,37019,78147, 4063,78147,20219,78147, 3863,78147,
+20697,78147,37377,78147, 9955,78147,10273,78147,14625,78147, 4569,78147,
+  265,77750,77785,78369,  251,78371,77787,78369, 8997,78375,  253,78369,
+ 8997,78379, 8337,78369,  251,78383,  241,78368, 8401,78387, 4137,78387,
+77791,78387,77789,78387,  241,78369,  241,77750, 8428,78399,78147,78401,
+ 4138,78399,78147,78405, 4137,78399,  265,78409,  265,78408,78147,78413,
+ 8401,78399,  265,78417,  265,78416,78147,78421,  265,78398, 8401,78425,
+ 4137,78425,77791,78425,77789,78425,  265,78399, 8401,78434,78147,78437,
+ 4137,78434,78147,78441,78147,78435, 8401,78445, 4137,78445,  240,77751,
+  265,78451, 1010,77751,28337,78455,  264,77751,78426,78459,78428,78459,
+78419,78459,78411,78459,78388,78459,78390,78459,77860,78459,77862,78459,
+77864,78459,77866,78459,18339,78459,77859,78480, 4371,78459,77859,78484,
+78381,78459,78385,78459,13381,78459,77961,78459,78005,78459,77993,78459,
+78037,78459,77997,78459,78041,78459,78015,78459,77971,78459,77807,78459,
+77803,78459,64746,78459,78382,78459,  251,78517,78378,78459, 8997,78521,
+78035,78459,  251,78525,77991,78459, 8997,78529, 9072,78459, 9105,78459,
+59470,78459,69364,78459,59521,78459,69415,78459,64931,78459,  413,78459,
+77859,78459, 8401,78548, 4137,78548,18339,78548, 4371,78548,78425,78459,
+ 8401,78558, 4137,78558,78387,78459, 8401,78564, 4137,78564, 8401,78459,
+78425,78570,78387,78570,77859,78570, 4137,78459,78425,78578,78387,78578,
+77859,78578, 8337,78459,78369,78586,  251,78589,  253,78459,78369,78592,
+ 8997,78595,78396,78459,78119,78459,78369,78459, 8337,78602,  251,78605,
+  253,78602, 8997,78609,  241,78603, 8401,78613, 4137,78613,  241,78602,
+69275,78459,  375,78620,59381,78459,  375,78624, 8997,78459,  375,78628,
+64669,78459,  375,78632,70327,78459,65869,78459,  375,78638,66930,78459,
+  375,78459,64669,78644, 8997,78644,59381,78644,69275,78644,65869,78644,
+  241,78644,  241,78459,78369,78658,  375,78658,  394,78459,  299,78459,
+ 1217,77751,  413,77751,77859,78671,78369,78671,  375,78671,14315,77751,
+  241,78678,  375,78681,  375,78679,  341,77751,12377,78687,  257,77751,
+  375,78691,70572,77751,70693,78695,70800,78695,70797,78695,56555,78700,
+56555,78695,70797,78704, 1346,77751,    9,78709, 1061,77751,    9,78713,
+  525,77751,    9,78717,64396,77751,    9,78721,38056,77751,29229,78725,
+    9,78725,  137,77751,56555,78731,    5,78733,    4,78732,78735,78737,
+    4,78733,    5,78732,78741,78743,20103,77751,  375,78747, 1471,77751,
+12377,78751,36773,77751,  375,78755,   53,77751,12377,78759,45639,77751,
+ 1369,78762,46275,78765,32805,77751,   17,78768,34003,78771,77410,77751,
+ 1369,78774,77591,78777,65076,77751,   17,78780,65625,78783, 1275,77751,
+    5,78786,    9,78789,    5,78787,   17,78793,35187,77751, 1196,78797,
+    6,78797, 1011,78800,  137,78797,  136,78797, 1197,78797, 1413,78797,
+  922,78797, 1011,78797,    6,78814,  903,78797,  483,78818,  483,78797,
+  903,78822,    2,78796,78805,78827,29229,78827,78799,78827,78817,78827,
+78803,78827,    9,78827,    3,78796,78807,78841,78809,78841,    2,78797,
+78841,78847,    9,78849,    9,78846,78841,78853,    3,78797,    5,78857,
+    6,78859,78827,78861,78838,78857,    9,78857,78827,78866,78827,78857,
+    9,78870,    9,78797,    2,78875,78857,78877,    3,78875,    2,78874,
+78841,78883,    3,78874,   17,77751,65076,78889,65407,78891,32805,78889,
+34447,78895,20035,78889,58742,78889,65076,78888,65625,78903,32805,78888,
+34003,78907,  903,78889,56555,78910,56555,78889,  903,78914,65869,78889,
+    2,78919,    3,78919,    2,78918,    3,78918,18967,77751,  295,78929,
+ 1108,78929, 1011,78929,    9,78934,    9,78929, 1011,78938,  483,78929,
+18967,78943,    5,78944,    5,78945,21036,78943,21037,78943,    4,78943,
+78949,78955,    5,78943,18967,78958,    4,78942,78961,78963,78947,78963,
+78951,78963,    5,78942,78953,78971, 1369,77751,12376,78974,12376,78975,
+12377,78974,78979,78981,77410,78975,77517,78985,45639,78975,46599,78989,
+12377,78975,78977,78993,36527,78975,68806,78975,77410,78974,77591,79001,
+45639,78974,46275,79005, 1011,78975,65869,79008,65869,78975, 1011,79012,
+  265,78974,17827,79017,56555,78975,    4,79021,    5,79021,    4,79020,
+    5,79020,60857,77751,  241,79030,    9,79033,    5,79030,    9,79037,
+    5,79031,   17,79041,70177,77751,38056,79045,38056,79044,38057,79045,
+79049,79051,38057,79044,79047,79055,  375,79045,27979,77751,  375,79061,
+    2,77750,68283,79065,68275,79065,36633,79065,36627,79065,39987,79065,
+66423,79065,66883,79065,66405,79065,66397,79065,67687,79065,78047,79065,
+    9,79087,36544,79065, 9875,79091,20501,79091,68177,79065, 9875,79097,
+20501,79097,64396,79065,    9,79103,    5,79065,60857,79106,    9,79109,
+35187,79065,   11,79112,20501,79115, 9875,79115,   11,79065,35187,79120,
+ 9875,79123,20501,79123,60857,79065,    5,79129,   17,79131,    5,79128,
+    9,79135,    3,77750,40779,79139,63907,79139,73421,79139,73429,79139,
+64235,79139,67465,79139,63955,79139,39027,79139,38685,79139,64073,79139,
+    6,79139,    4,79161,78728,79139,78838,79139,78827,79139,    9,79168,
+78725,79139,    9,79172, 9934,79139,20644,79139, 4663,79139,  903,79181,
+17219,79139,  903,79185,12345,79139,    5,79189,    4,79188,79191,79193,
+    4,79189,    5,79188,79197,79199, 5123,79139,    5,79203,    4,79202,
+79205,79207,    4,79203,    5,79202,79211,79213,19667,79139,    5,79217,
+    4,79216,79219,79221,    4,79217,    5,79216,79225,79227,73306,79139,
+ 9377,79231,63823,79231,40705,79139, 9377,79237,63823,79237,21036,79139,
+70177,79139,    9,79245,  341,79139,64669,79249,65869,79249,  253,79139,
+65869,79255, 8337,79139,    9,79259,  241,79139, 1471,79139,65869,79265,
+37325,79139,  903,79269,20103,79139,    9,79273,10219,79139,  903,79277,
+    4,79139,20501,79280, 9875,79280,    5,79139,    6,79287,78827,79289,
+78725,79289,18967,79286, 9935,79287,20645,79287,36773,79139,    9,79301,
+   53,79139,65869,79305,    5,79138,27979,79309, 8685,79309,41503,79309,
+26293,79309, 1369,79309,16381,79309,13325,79309,35843,79309,19513,79309,
+ 8401,79309, 4137,79309,14625,79309, 4569,79309,37019,79309, 4063,79309,
+ 3863,79309,37377,79309,20219,79309,10273,79309, 9955,79309,20697,79309,
+    9,79139,78725,79352,78827,79352,35187,79139, 1505,79359,   17,79139,
+71229,79362, 9377,79365,63823,79365,21315,79363,71229,79139,   17,79372,
+63823,79375, 9377,79375,18967,79139,20413,79381,    4,79383,    4,79382,
+20487,79381,20486,79381,79161,79381,    4,79393,    4,79392,79163,79381,
+  580,79381,49630,79381,79162,79381,46863,79381,    4,79406,    4,79407,
+  483,79381,    4,79412,    4,79413,49631,79381,  581,79381,    4,79381,
+20413,79422,79161,79422,46863,79422,  483,79422,    5,79381,79385,79433,
+79179,79433,79283,79433,79395,79433,79411,79433,79417,79433,20413,79433,
+    4,79380,79389,79449,79446,79449,79421,79449,79419,79449,79399,79449,
+79433,79449,20413,79460,20413,79449,79433,79464,    5,79380,79425,79469,
+79387,79469,79391,79469,79427,79469,79397,79469,79401,79469,79403,79469,
+79405,79469,79429,79469,79409,79469,79431,79469,79415,79469,79423,79469,
+20413,79495, 1369,79139,    5,79499,27979,79139,65869,79503,    9,79503,
+20501,79139,    4,79508,79433,79511,    5,79508,18967,79514,21037,79508,
+    4,79509,79517,79521,79243,79521,79295,79521,79469,79521,    5,79509,
+79519,79531, 9875,79139,    4,79534,    5,79534,    4,79535,    5,79535,
+    4,77750,    3,79545,    5,77750,10256,79549,37356,79549, 4745,79549,
+ 1011,79555,17423,79549, 1011,79559,63550,79549,64489,79549,63493,79549,
+   17,79566,70803,79549,56555,79571,74752,79549, 8982,79549,74571,79549,
+   17,79578, 8861,79549,   17,79582,37844,79549,27979,79549,  483,79589,
+  253,79549,56555,79593, 8337,79549,  483,79597,  241,79549, 1325,79549,
+   17,79602,  331,79549,   17,79606, 1328,79549,  334,79549,   53,79549,
+56555,79615,20501,79549, 1011,79619,36773,79549,  483,79623, 9875,79549,
+ 1011,79627, 1359,79549,  393,79549,    2,79549,37325,79634,10219,79634,
+    3,79549,  483,79641,35187,79640,10257,79641,37357,79641,   62,79549,
+   59,79549,   17,79652,20103,79549,  483,79657, 1471,79549,56555,79661,
+    3,79548,27979,79665, 8685,79665,26293,79665,41503,79665, 1369,79665,
+16381,79665,13325,79665,19513,79665,35843,79665, 8401,79665, 4137,79665,
+14625,79665, 4569,79665,20219,79665, 3863,79665, 4063,79665,20697,79665,
+37019,79665, 9955,79665,10273,79665,37377,79665,18967,79549,  165,79709,
+ 1369,79549,38057,79713,35187,79549,    3,79717,    3,79716,   17,79549,
+63493,79722,74571,79722, 8861,79722, 1325,79722,  331,79722,   59,79722,
+37325,79549,    2,79736,    3,79736,    2,79737,    3,79737,10219,79549,
+    2,79746,    3,79746,    2,79747,    3,79747,    5,77751, 1196,79756,
+ 1196,79757, 1197,79756,79761,79763,21604,79757,    6,79757,  587,79769,
+21605,79771,    1,79757,    3,79774,    3,79775,18967,79775,  483,79781,
+    1,79756,25381,79785,63014,79785,79773,79785,60857,79785,  483,79792,
+  483,79785,60857,79796,    6,79756,79787,79801,63015,79801,79785,79805,
+25380,79801,79785,79809,79789,79801,79783,79801,79799,79801, 1369,79801,
+21605,79818,79785,79821,79795,79801,21605,79801, 1369,79826,79785,79829,
+ 1216,79757,  413,79757, 1197,79757,79759,79837,79546,79757,  903,79757,
+20735,79757, 9993,79757, 1275,79756,    9,79849,60857,79756,    9,79853,
+56555,79757, 1505,79856,21605,79757,21376,79757,  483,79757,21315,79864,
+58112,79757,21315,79757,  483,79870, 1505,79757,56555,79874,    2,79756,
+79767,79879,    7,79881,    6,79880,79883,79885,    6,79881,    7,79880,
+79889,79891,79777,79879,    7,79895,    6,79894,79897,79899,    6,79895,
+    7,79894,79903,79905,28337,79879,    3,79756,79861,79911,    7,79913,
+    6,79912,79915,79917,    6,79913,    7,79912,79921,79923,    2,79757,
+79779,79927,    7,79929,    6,79928,79931,79933,    6,79929,    7,79928,
+79937,79939,    3,79757,    1,79942,79879,79945,    7,79947,    6,79946,
+79949,79951,    6,79947,    7,79946,79955,79957,79545,79942,79545,79757,
+    2,79963,    3,79963,    2,79962,    3,79962,    9,79757,63493,79973,
+74571,79973, 8861,79973, 1325,79973,  331,79973,   59,79973,    3,77751,
+79112,79987,    9,79989,78847,79987,    9,79993, 1216,79987,12371,79987,
+    5,79999,    4,79998,80001,80003,    4,79999,    5,79998,80007,80009,
+  413,79987,  375,79987,60454,79987,60369,80017,  566,79987,35187,79987,
+79065,80022,    9,80025,79106,79987, 1011,79987,37407,79987,10287,79987,
+65869,79987,  165,80036,38132,79987,    9,79987,38057,80042,67642,79987,
+38057,79987,    9,80048,  165,79987,65869,80052,    5,79986,    4,79987,
+    5,79987,79065,80060,56555,80060,60369,80065,  483,80060,79065,79987,
+35187,80070,    9,80073,    4,80071,    5,80071,    4,80070,    5,80070,
+56555,79987,49630,80084,46863,80084,    4,80089,    4,80088,  581,80084,
+  580,80084,49631,80084,    4,80084,46863,80100,  483,80100,    5,80084,
+60369,80107,80091,80107,    4,80085,80095,80113,80099,80113,    5,80085,
+60327,80119,60719,80119,80097,80119,80087,80119,57901,80119,80093,80119,
+80103,80119,80105,80119,  483,80084,    4,80136,80119,80139,    4,80137,
+80107,80143,  483,79987,    5,80146,    2,77751,79538,80151,79541,80153,
+79514,80151,79521,80157,79024,80151,79027,80161,78958,80151,78963,80165,
+79021,80151,    5,80168,79027,80171,    5,80169,79023,80175,78943,80151,
+    5,80178,78963,80181,    5,80179,78955,80185,    1,80151,    7,80189,
+    4,80191,    4,80190,   16,80189,    4,80189,    7,80198,28714,80151,
+   17,80203,79286,80151,79541,80207,79521,80207,35187,80150,79289,80213,
+29229,80213,79352,80213,    9,80213,79139,80220,79139,80213,    9,80224,
+    9,80151,    4,80150,  265,80231,    5,80150,80193,80235,28337,80235,
+    4,80151, 1011,80241,    5,80151,80195,80245,80201,80245,79534,80245,
+79543,80251,79508,80245,79531,80255,79021,80244,79027,80259,78943,80244,
+78963,80263,79021,80245,79029,80267,78943,80245,78971,80271,80197,80245,
+28219,80245,30475,80245,23939,80245,79139,80244,79541,80283,79521,80283,
+21605,80244,   17,80289,79139,80151,35187,80293,    9,80295,    4,80293,
+    5,80293,79537,80301,79511,80301,79177,80301,79179,80301,79285,80301,
+79283,80301,    4,80292,80301,80315,    5,80292,79541,80319,79521,80319,
+80299,80319,21605,80151,    5,80326,   17,80329,    5,80327,    9,80333,
+    4,77751,79750,80337,79753,80339,79740,80337,79743,80343,78922,80337,
+78925,80347,78880,80337,78883,80351,78919,80337,    3,80354,78925,80357,
+    3,80355,78921,80361,78875,80337,    3,80364,78883,80367,    3,80365,
+78877,80371,    6,80337, 1369,80375,56555,80377,    1,80337,60857,80381,
+ 1275,80383,    1,80336,58931,80387,19916,80387,80379,80387,18967,80387,
+ 1275,80394, 1275,80387,18967,80398,    6,80336,19917,80403,80387,80405,
+80389,80403,80391,80403,58930,80403,80387,80413,80385,80403,80401,80403,
+  587,80403,56555,80420,80387,80423,80397,80403,56555,80403,  587,80428,
+80387,80431,43214,80337,79640,80337,79753,80437,79743,80437,    2,80336,
+  265,80443,    2,80337,  903,80447,    3,80337,67988,80450,67988,80451,
+67989,80450,80455,80457,79746,80451,79755,80461,79736,80451,79745,80465,
+78919,80450,78925,80469,78875,80450,78883,80473,78919,80451,78927,80477,
+78875,80451,78887,80481,67989,80451,80453,80485,79549,80450,79753,80489,
+79743,80489,38305,80450,79549,80337,    2,80497,    3,80497,79749,80501,
+79739,80501,79551,80501,79553,80501,79639,80501,79637,80501,    2,80496,
+80501,80515,    3,80496,79753,80519,79743,80519,80499,80519,38305,80337,
+    3,80526,    3,80527,    0,    7, 1517,80532, 2575,80535,  949,80532,
+ 2599,80539, 1476,80532, 2269,80543,  280,80532, 2289,80547,  272,80532,
+ 4437,80551,  121,80532,38343,80555, 3075,80555, 1913,80555,   76,80532,
+ 3005,80563, 1899,80563,38337,80563,  123,80533, 3061,80571,   81,80533,
+ 2997,80575,  367,80532, 7627,80579,  357,80532, 1927,80583,  397,80532,
+ 7895,80587, 1516,80532,  948,80532,  107,80532, 2221,80595,  203,80532,
+ 2215,80599,  215,80532, 4339,80603,   91,80532, 5045,80607, 1477,80532,
+  281,80532,  273,80532,  317,80532,14469,80617,   67,80532,11087,80621,
+ 4643,80621, 2233,80621, 4625,80621,    9,80629,   53,80532, 2289,80633,
+ 1471,80532, 2269,80637,80012,80533,77949,80641,79834,80533,77949,80645,
+79996,80533,78669,80649,79832,80533,78669,80653,78546,80533,77949,80657,
+78108,80533,78141,80661,77949,80661,77855,80533,77949,80667,  416,80533,
+17993,80671,  418,80533,17993,80675,  447,80533,17993,80679,  295,80532,
+  294,80532,   76,80533,38587,80687,26285,80533,26390,80533,26106,80533,
+  121,80533,38585,80697,26502,80533,32269,80533,31761,80533,32563,80533,
+31921,80533,31591,80533,78287,80533,78141,80713,78099,80713,77949,80713,
+23788,80533,27830,80533,27947,80533,41746,80533,26216,80533,41414,80533,
+26126,80533,41348,80533,26328,80533,41556,80533,29029,80533,43319,80533,
+  203,80533, 2211,80745,60857,80745,   85,80533, 4593,80751, 2229,80751,
+60857,80751,80229,80533,39823,80533,23013,80533,39229,80533,39783,80533,
+38673,80533,38675,80533,  107,80533, 5019,80773, 2219,80773,60857,80773,
+80228,80533,40956,80533,45411,80783,37899,80783,41493,80533, 1517,80533,
+ 2573,80791,80591,80791,  949,80533, 2593,80797,80593,80797,  280,80533,
+ 2287,80803,80613,80803, 1476,80533, 2267,80809,80611,80809,  272,80533,
+ 4457,80815,80615,80815, 8673,80533, 8681,80533, 8800,80533, 8742,80533,
+41622,80533, 8740,80533, 8610,80533, 8642,80533, 8638,80533,39650,80533,
+42752,80533, 8717,80533,  413,80843, 1369,80842,  341,80842, 3785,80533,
+  413,80851, 1369,80850,  341,80850,  413,80532, 8717,80859, 3785,80859,
+13443,80859, 7627,80859, 7287,80859, 7895,80859,12755,80859, 1689,80859,
+ 2701,80859, 1705,80859,77859,80859,78459,80880,78548,80859,78048,80859,
+77837,80887,78071,80859,18454,80859,78147,80859,78459,80859,77859,80896,
+  265,80859,77751,80900,77837,80903,77751,80901,77859,80907,18391,80859,
+  331,80910,  331,80859,18391,80914, 8495,80859,77751,80859,  265,80920,
+77837,80923,12745,80859,  375,80927,  457,80927,  375,80859,13977,80533,
+80021,80533,13767,80533, 4347,80533, 2213,80533, 2225,80533, 2231,80533,
+10079,80533,79501,80533,18715,80533,18579,80533,14313,80533,80149,80533,
+13945,80533, 4987,80533,14091,80533, 4619,80533,80069,80533,13913,80533,
+ 4555,80533,16635,80533,16301,80533, 2575,80533, 2599,80533, 2289,80533,
+ 2269,80533, 4437,80533, 7549,80533, 7589,80533,13785,80533,80015,80533,
+23755,80533, 1369,80996,39633,80533, 1369,81000,78284,80533, 7205,80533,
+ 2561,80533, 2261,80533, 4423,80533, 2307,80533,79318,80533,10058,80533,
+79674,80533,26331,80533, 1369,81022,41559,80533, 1369,81026, 4329,80533,
+ 1369,81030, 4311,80533, 1369,81034,10354,80533, 3786,80533, 4330,80533,
+27805,80533, 1369,81044,42731,80533, 1369,81048,10055,80533, 1369,81052,
+10351,80533, 1369,81056, 4312,80533,78645,80533,78324,80533,78458,80533,
+  375,81067, 3794,80533,78147,80533,  413,81073, 1369,81072,  341,81072,
+  215,80533, 4345,81081,60857,81081,79309,80533, 1369,81086,79665,80533,
+ 1369,81090, 1477,80533,80543,81095,  281,80533,80547,81099, 1516,80533,
+80535,81103,  948,80533,80539,81107,13443,80533,16669,80533,43293,80533,
+26104,80533,41314,80533,26277,80533,41479,80533,13027,80533,  264,81124,
+  264,81125,  413,81125,  265,81124,81129,81133,  265,81125,81127,81137,
+ 5127,80533,  264,81140,  264,81141,  413,81141,  265,81140,81145,81149,
+  265,81141,81143,81153,15309,80533,  412,81157,  413,81156,81159,81161,
+  413,81157,  412,81156,81165,81167,32294,80533,45314,80533,31857,80533,
+44925,80533,14053,80533,22897,80533,39143,80533,78107,80533,  413,81184,
+78141,81187,77949,81187,  413,81185,77859,81193, 1276,80533,17993,81197,
+  438,80533,17993,81201, 1278,80533,18759,81205, 1242,80533,18759,81209,
+22806,80533,  903,81213,    9,81213,39084,80533,  483,81219,39204,80533,
+41941,81223,22956,80533,26625,81227, 1109,80533,35187,81231,  294,80533,
+80683,81235,35187,81235, 1413,80533, 1471,81241,  295,80533,80685,81245,
+39749,80533,  483,81249,24095,80533,35187,81253,   11,81252,39787,80533,
+  241,81259,  903,81259,  587,81258,24236,80533,39846,80533,78459,80533,
+  413,81270,77949,81273,  413,81271,77859,81277,39232,80533,46169,81281,
+  510,80533,   11,81285, 1108,80533,   11,81289, 1216,80533,79987,81292,
+78669,81295,79757,81292,78669,81299, 1275,81292,18759,81303,   15,81292,
+18759,81307, 8808,80533,41376,80533, 7195,80533, 1141,80533,14315,81317,
+  959,80533,17125,81321,  253,80533,25793,81324,41019,81324, 8495,81324,
+  317,80533,15661,81333,14991,81333,17993,81333, 2899,81333,  273,80533,
+80551,81343, 8634,80533, 8677,80533,  331,80533,  413,81351,18391,81353,
+  413,81350,17993,81357, 8861,81351,63493,81351,74571,81351,15029,81351,
+ 8495,80533,  586,81368,  586,81369,  587,81368,81373,81375,   11,81368,
+  253,81368, 1471,81368,   53,81368,  587,81369,81371,81387,  305,81369,
+  713,81369,   25,81369, 1369,81368,  257,81369,  257,81368,14011,80533,
+  257,80533,25793,81404,41019,81404, 8495,81404,  973,80533,20103,81413,
+ 8337,81413,36773,81413,  341,80533,30091,81421, 8717,81420,20103,81421,
+36773,81421, 8337,81421, 3785,81420,78147,81420,   89,80533,10831,81437,
+10903,81437, 5019,81437,60857,81437,17125,81437,  567,80533,63493,81449,
+74571,81449, 8861,81449,  652,80533,60857,81457,  288,80533, 8861,81461,
+  265,80533,78670,81465,77859,81467,  413,81465,77751,81471,77837,81473,
+77751,81470,77859,81477,73154,81465,62059,81465,78107,81465,15029,81465,
+ 4593,81465,11985,81465,78459,81465,80057,81465,79911,81465, 8861,81465,
+63493,81465,74571,81465,72152,81465,61718,81465,77751,81465,  413,81508,
+77859,81511,  413,81509,77949,81515,   17,81464,35187,81519,   11,81465,
+60857,81522,  587,81465,71229,81526,71229,81465,60857,81530,   11,81531,
+  587,81530,60857,81465,   10,81539,   10,81538,  305,81539,   11,81539,
+81543,81547,71229,81538,   11,81538,81541,81553,  587,81464,60857,81557,
+   11,81464, 8861,81561, 1011,80533,50785,81565,    9,81564,   11,81569,
+   11,81565,    9,81573,71229,81565,77387,81577,  903,80533,50959,81581,
+45149,80533,35187,81585,   11,81584,32103,80533,27021,81591,  241,81591,
+  903,81591,  587,81590, 7333,80533,  483,81601, 6789,80533,    9,81605,
+  903,81605,14073,80533,  241,81611,  903,81611,  587,81610,11277,80533,
+35187,81619,   11,81618,42707,80533, 3445,80533,  375,81627,10313,80533,
+79643,80533, 2621,80533,14229,80533,11571,80533, 5045,80533,35187,81641,
+   11,81640, 4971,80533,  241,81647,  903,81647,  587,81646, 7009,80533,
+ 7497,80533, 7287,80533, 7845,80533, 7925,80533, 7895,80533, 7685,80533,
+ 7671,80533, 7627,80533,14102,80533,11348,80533, 5096,80533, 5000,80533,
+ 7533,80533, 4617,80533,  483,81683,13907,80533,  483,81687, 7563,80533,
+  264,81691,  264,81690,  265,81691,81695,81697,  265,81690,81693,81701,
+ 7531,80533,  483,81705,79634,80533,80501,81709,79719,81709,79640,80533,
+  483,81715,42716,80533,42795,81719,42704,80533,  483,81723,10308,80533,
+36131,81727,10310,80533,  483,81731, 5227,80533, 5009,80533, 3461,80533,
+ 2981,80533, 3049,80533,80061,80533,  483,81745,  240,80532,77859,81749,
+78459,81750,78089,81749,78147,81755,78305,81749,78231,81749,78277,81749,
+78445,81749,78564,81749,78613,81749,78558,81749,78548,81749,78071,81749,
+78387,81749,78459,81776,78425,81749,78459,81780,78434,81749,78147,81785,
+13103,81749, 5161,81749,13074,81749, 5150,81749,13057,81749,13051,81796,
+ 5141,81749, 5137,81800,13051,81749,13057,81804, 5137,81749, 5141,81808,
+13092,81749,13045,81813, 5154,81749, 5133,81817,78048,81749,77837,81821,
+78459,81749,78387,81824,78425,81824,77859,81824,25793,81749,41019,81749,
+ 8495,81749,78147,81749,48009,81749,49321,81749,49001,81749,78399,81749,
+  265,81847,78459,81849,  265,81846,78147,81853,  265,81749,13027,81856,
+13045,81859, 5127,81856, 5133,81863,13027,81857,13057,81867, 5127,81857,
+ 5141,81871,78399,81856,78147,81875,77751,81856,77837,81879,77751,81857,
+78387,81883,78425,81883,77859,81883,77751,81749,  265,81890,77837,81893,
+23755,81749,39633,81749, 3785,81749, 8717,81749,79309,81749,79665,81749,
+10055,81749,10351,81749,27805,81749,42731,81749,26331,81749, 4329,81749,
+41559,81749, 4311,81749, 5127,81749,  265,81925, 5137,81927,  265,81924,
+ 5133,81931,13027,81749,  265,81935,13051,81937,  265,81934,13045,81941,
+ 1010,80532,27021,81945,24095,81945,52915,81945, 9195,81945,81565,81945,
+    9,81955,81569,81945,23651,81945,67297,81945,81289,81945,21605,81945,
+    9,81967,51435,81945, 4321,81945, 9755,81945,11277,81945, 5045,81945,
+ 4295,81945, 3833,81945,69729,81945,26907,81945,70097,81945,27323,81945,
+53941,81945,53215,81945,10171,81945, 9317,81945,  264,80532,51421,82001,
+39619,82001,57811,82001,59743,82001,59933,82001, 8093,82001, 3837,82001,
+53703,82001, 4303,82001,42435,82001, 4287,82001,53487,82001, 9579,82001,
+42113,82001, 9839,82001,  241,82001,  375,82032,  394,82001,  299,82001,
+  375,82001,  241,82040,78399,80533,  264,82044,  264,82045,  413,82045,
+  265,82044,82049,82053,  265,82045,82047,82057,  240,80533,78397,82061,
+78459,82063,78099,82061,78147,82066,78264,82061,78283,82061,78260,82061,
+78262,82061,78661,82061,78599,82061,78619,82061,78601,82061,78675,82061,
+77837,82061,77949,82088,78673,82061,77950,82061,78118,82061,78459,82097,
+78670,82061,77859,82101,77949,82061,78147,82104,77837,82104,78141,82061,
+78147,82110,  413,82061,77751,82115,77837,82117,77751,82114,77859,82121,
+78147,82061,78099,82124,78141,82124,77949,82124,78107,82061,  265,82132,
+78459,82135,  265,82133,78147,82139,77751,82061,  413,82142,77859,82145,
+  413,82143,77949,82149,  265,82061,78107,82152,78459,82155,78107,82153,
+78141,82159,  902,80533,37663,82163,37599,82163,  265,80532,25793,82169,
+41019,82169,39787,82169,23755,82169,39633,82169, 8495,82169,78147,82169,
+ 8717,82169, 3785,82169,79309,82169,79665,82169,27805,82169,42731,82169,
+10055,82169,10351,82169,26331,82169,41559,82169, 4329,82169, 4311,82169,
+ 4555,82169,14073,82169, 4971,82169,21605,82169,65869,82215,38305,82169,
+56555,82219,  483,82219,  241,80532, 4437,82225,    7,82225,  265,82229,
+39787,82225,51615,82225, 4613,82225,12571,82225,14073,82225, 4971,82225,
+  375,82225,  510,82225,51937,82225,16683,82225, 4805,82225,    9,82225,
+  483,82254,  483,82225,    9,82258,38305,82225,  483,82263, 1010,80533,
+55211,82267,64345,82267,36256,82267,35187,82267,    9,82274,    9,82267,
+35187,82278, 1011,80532,10001,82283,  903,82285,27533,82283,  903,82289,
+79139,82283,  903,82293,82267,82283,    9,82296,82278,82283,81231,82283,
+21605,82283,  903,82305,    9,82283,82267,82308,  903,80532, 3549,82313,
+ 2001,82313,21769,82313,10291,82313, 1011,82321,42613,82313, 1011,82325,
+79549,82313, 1011,82329,24095,82313,25793,82313, 8495,82313, 5045,82313,
+11277,82313,39787,82313,14073,82313, 4971,82313,21605,82313,  955,82349,
+    9,82349,65869,82349,38305,82313, 1011,82357,  483,82357,41019,82313,
+  264,80533,   53,82365, 1471,82365,  253,82365,72567,82365,76285,82365,
+76939,82365,77751,82364,  375,82379,  471,82365,  367,82365,  357,82365,
+  341,82365,  241,82389,  241,82365,    9,82393,  483,82393,  413,80533,
+78106,82398,78107,82399,82401,82403,78459,82403,78106,82399,78107,82398,
+82409,82411,78141,82411,77949,82411,79987,82398,77949,82419,79757,82398,
+77949,82423,78459,82398,77949,82427,  331,82398,17993,82431,  261,82398,
+17993,82435,77949,82399,78459,82439,17993,82399,  331,82443, 1275,82398,
+17993,82447,   15,82398,17993,82451,  375,80533,   53,82455, 1471,82455,
+  253,82455, 1369,82455,   11,82455,  261,80533,  413,82467,18391,82469,
+  413,82466,17993,82473,15029,82467,  264,82477,  265,82476,82479,82481,
+  264,82476,  265,82477,82485,82487,16531,80533,  483,82491,12745,80533,
+  264,82495,13129,82495,  413,82495,13119,82501,15503,82495,50535,82495,
+50929,82495,51081,82495,82231,82495,13171,82495,13133,82495,  264,82494,
+  265,82495,82519,82521,  265,82494,82497,82525,  375,82495,  257,82495,
+  264,82531,  265,82530,82533,82535,  264,82530,  265,82531,82539,82541,
+  566,80533,   53,82545,  253,82545, 1471,82545,   88,80533, 1369,82553,
+ 1346,80533,55211,82557,28714,80533,28337,82561,60618,80533,60757,82565,
+    3,82565,60755,82569,  154,80533,37663,82573,43214,80533,43053,82577,
+  483,82577,43502,80533,80531,82583,46169,82583,   67,80533,11529,82589,
+11569,82589, 4610,82589,61780,82589,    9,82589, 4593,82598,60857,82598,
+60857,82589,    9,82604, 4593,82589,    9,82608,37845,80533,38305,82612,
+45411,82615,37899,82615,79926,80533,79987,82621,    4,82623,    5,82622,
+82625,82627,    5,82623,    4,82622,82631,82633,80058,80533,79757,82637,
+    2,82639,    3,82638,82641,82643,    3,82639,    2,82638,82647,82649,
+80244,80533,   17,82653, 1447,80533,14315,82657,   33,80533,14315,82661,
+  759,80533,17125,82665,   47,80533,17125,82669, 1471,80533,41019,82672,
+25793,82672, 8495,82672,   53,80533,25793,82680,41019,82680, 8495,82680,
+25793,80533,  586,82688,  586,82689,   11,82688, 1369,82688,  587,82688,
+82693,82699,  253,82688,   53,82688, 1471,82688,  587,82689,82691,82709,
+   25,82689,  713,82689,  305,82689,  257,82688,  257,82689, 1325,80533,
+74571,82723,63493,82723, 8861,82723,15029,82723,41019,80533,  586,82732,
+  586,82733,  587,82732,82737,82739,   11,82732,  253,82732, 1471,82732,
+   53,82732,  713,82733,   25,82733,  305,82733,  587,82733,82735,82757,
+  257,82732, 1369,82732,  257,82733,   59,80533,63493,82767,74571,82767,
+ 8861,82767,15029,82767,79139,80533,80244,82777,80245,82777,80293,82777,
+    4,82782,80319,82785,    4,82783,80301,82789,80298,82777,80319,82793,
+21036,82777,21037,82777, 1216,82777,  413,82777,80245,82776,82779,82805,
+ 1011,82777,  903,82808,21037,82776,82797,82813,80244,82776,82781,82817,
+21036,82776,82799,82821,65869,82777,    9,82777,  903,82777, 1011,82828,
+    4,82777,80293,82833,80315,82835,80293,82832,80319,82839,79549,80533,
+80450,82843,80451,82843,80497,82843,    2,82848,80519,82851,    2,82849,
+80501,82855,80498,82843,80519,82859, 1216,82843,  413,82843,80451,82842,
+82845,82867,  903,82843, 1011,82870,80450,82842,82847,82875,56555,82843,
+  483,82843, 1011,82843,  903,82882,    2,82842,80501,82887,79719,82887,
+    3,82842,80337,82892,  483,82893,    3,82843,82867,82899, 1369,82899,
+    2,82843,82875,82905,82895,82905,80497,82905,80515,82911,80497,82904,
+80519,82915,80519,82905,80437,82905,80489,82905,79587,82905,79721,82905,
+79645,82905,80337,82842,    3,82930,82905,82933,    3,82931,82887,82937,
+27533,80533, 1216,82941,  413,82941,21036,82941,21037,82941, 1011,82941,
+  903,82950,21037,82940,82947,82955,21036,82940,82949,82959,    9,82941,
+65869,82941,  903,82941, 1011,82966,42613,80533, 1216,82971,  413,82971,
+  903,82971, 1011,82976,  483,82971,56555,82971, 1011,82971,  903,82984,
+    2,82971,42667,82989,42791,82989,42709,82989,    3,82971, 1369,82997,
+    2,82970,42795,83001,    3,82970,  483,83005,10001,80533, 1216,83009,
+  413,83009,21036,83009,21037,83009,21036,83008,83017,83019, 1011,83009,
+  903,83022,21037,83008,83015,83027,65869,83009,    9,83009,  903,83009,
+ 1011,83034,10291,80533, 1216,83039,  413,83039,  903,83039, 1011,83044,
+56555,83039,  483,83039, 1011,83039,  903,83052,    2,83039,37871,83057,
+36133,83057,35803,83057,    3,83039, 1369,83065,    2,83038,36131,83069,
+    3,83038,  483,83073, 1369,80533,26331,83076,25793,83076,23755,83076,
+27805,83076,40381,83077,41559,83076, 8717,83076,21036,83077,39633,83076,
+78147,83076,79309,83076,10055,83076,42731,83076, 3785,83076,79665,83076,
+ 4329,83076,10351,83076, 4311,83076,38305,83076,41941,83115,41019,83076,
+ 8495,83076,38305,83077,41019,83123,    5,83077,18967,83126,18967,83077,
+   11,83131,    5,83130,   17,80533,25367,83137,62984,83137,60857,83137,
+  265,83143,  241,83142,  241,83137,60857,83148,21605,83136,26625,83153,
+  265,83136,35187,83157,21605,83137,25793,83161,35187,83137,  265,83165,
+  587,80533,62984,83169,62518,83169,68807,83169,36526,83169,17125,83169,
+  265,83169,35187,83180,35187,83169,60857,83184,  265,83184,32103,83168,
+38305,83168,  483,83193,39787,83168,14073,83168, 4971,83168,  265,83168,
+60857,83203,  241,83169,60857,83206,60857,83169,  241,83210,35187,83210,
+   11,80533,25793,83216,41019,83216, 8495,83216,  265,83217, 8495,83225,
+45149,83216,21605,83216,  903,83231,    9,83231,24095,83216,11277,83216,
+ 5045,83216,  265,83216, 8861,83243,    3,83217,  375,83247,38305,80533,
+76424,83251,54262,83251,54219,83251,76453,83251,42185,83251,42193,83260,
+42194,83251,42191,83251,42193,83251,42185,83268,80450,83251,37844,83251,
+37845,83251,44663,83277,38707,83277,43483,83277,37897,83277,80451,83251,
+80450,83250,83287,83289,  120,83251,   77,83251,32805,83251,54225,83251,
+54129,83298,76337,83251,76307,83302,76307,83251,76337,83306,54129,83251,
+54225,83310,  113,83251,   25,83314,  506,83251, 1216,83251,  413,83251,
+ 1413,83251,37845,83250,45411,83327,83275,83327,37899,83327,37897,83250,
+83275,83335,65076,83251,37844,83250,    6,83340,83277,83343,83277,83341,
+80451,83250,83273,83349,   66,83251,   33,83353,   25,83251,  113,83356,
+ 1281,83251, 1086,83251,  922,83251,  483,83251,  241,83366,  587,83367,
+  903,83366,  241,83251,  483,83374,  903,83251, 1011,83378,  483,83378,
+ 1369,83250,41941,83385,  587,83250,  483,83389,  587,83251, 1011,83392,
+ 1011,83251,  903,83396,   11,83397,  587,83396, 1275,83250,46169,83405,
+60857,83251,56555,83408,56555,83251,   11,83413,60857,83412,    2,83250,
+80531,83419,46169,83419,    3,83250,43053,83425,  483,83425,    2,83251,
+80435,83431,80495,83431,43461,83431,80529,83431,46599,83431,43425,83431,
+    3,83251,43837,83445,43027,83445,   11,83445,   25,83451,39747,83445,
+   11,83444,   33,83457, 1369,83445,   11,83251,    3,83463,  113,83465,
+    3,83462,   33,83469,   15,80533, 1216,83473,18617,83475,  413,83473,
+18391,83479,25545,83473,62942,83473, 1216,83472,18759,83487,  413,83472,
+17993,83491,60857,83473, 1011,83494,18967,83473,   17,83499, 1011,83473,
+60857,83502,    3,83472,37663,83507,    3,83473,37611,83511,38155,83511,
+35927,83511,21605,80533,27065,83519,27261,83519,21036,83519,21037,83519,
+27067,83519,27255,83519,73221,83519,55211,83519,36256,83519,51593,83519,
+55803,83519,64345,83519,54477,83519, 1216,83519,  413,83519,21037,83518,
+83525,83551,21036,83518,83527,83555,  247,83519,  934,83519,    9,83519,
+35187,83562,   11,83563, 1011,83519,  903,83568,   17,83518,26625,83573,
+   11,83518,  903,83577,    9,83577,   11,83519,  903,83582,  903,83519,
+27021,83587, 1011,83586,   11,83587,   11,83586,35187,83519,    9,83596,
+65869,83519,    5,83518,28337,83603,    5,83519,27021,83607,52915,83607,
+ 9195,83607,20501,83607, 9875,83607,30475,83607,28219,83607,23939,83607,
+ 1275,80533,43214,83624,43214,83625,43215,83624,83629,83631, 1216,83625,
+18617,83635,  413,83625,18391,83639,43215,83625,83627,83643,40675,83625,
+73994,83625, 1216,83624,18759,83651,  413,83624,17993,83655,71229,83625,
+  903,83658,  903,83625,71229,83662,38305,83624,46169,83667,    5,83624,
+55211,83671,    5,83625,53813,83675,10107,83675,69877,83675,  483,80533,
+  241,83683,    9,83685,    9,83682,   11,83689,   17,83683,  903,83693,
+   11,83683,    9,83697,    5,83682,   53,83701,  253,83701, 1471,83701,
+    5,83683, 1505,83709,    9,80533,80151,83712, 1011,83713,82267,83717,
+  241,83713,  483,83721,  483,83712,   11,83725, 1011,83712,81945,83729,
+   11,83729,    3,83712, 1369,83735,    3,83713,  483,83739,17025,80533,
+    5,83742,    2,83745,   17,83746,   17,83745,    2,83750,    2,83751,
+  164,83745,38057,83743,38057,83742,38056,83742,83759,83763,38056,83743,
+83761,83767,    3,83742,83749,83771,83753,83771,83757,83771,    3,83743,
+83755,83779,13737,80533,  375,83783,80151,80533,    9,83786,35187,83787,
+    9,83791,    5,83787,    9,83795,    5,83786,   17,83799,79987,80533,
+  413,83802,77949,83805,  413,83803,77859,83809, 1216,83802,78669,83813,
+ 1216,83803,77857,83817,    4,83803,79549,83821,    2,83823,    3,83822,
+83825,83827,    3,83823,    2,83822,83831,83833,    4,83802,79757,83837,
+    2,83839,    3,83838,83841,83843,    3,83839,    2,83838,83847,83849,
+79757,80533,  413,83852,77949,83855,  413,83853,77859,83859, 1216,83852,
+78669,83863, 1216,83853,77857,83867,    2,83853,79139,83871,    4,83873,
+    5,83872,83875,83877,    5,83873,    4,83872,83881,83883,    2,83852,
+79987,83887,    4,83889,    5,83888,83891,83893,    5,83889,    4,83888,
+83897,83899,    3,80532,79231,83903,79237,83903,79365,83903,79375,83903,
+73413,83903,73405,83903,40793,83903,40787,83903,71751,83903,36001,83903,
+71731,83903,72115,83903,72929,83903,71713,83903,    7,83903,    4,83933,
+83519,83935,32103,83903,26106,83903,41746,83903,43005,83903, 8800,83903,
+64513,83903,63253,83903,62215,83903,59910,83903,41019,83903,   11,83956,
+60755,83903,60707,83903, 9852,83903,48975,83903,48245,83903,48451,83903,
+76271,83903,82267,83903,    9,83974,82278,83903,83157,83903,81231,83903,
+81235,83903,81519,83903,  386,83903,  347,83903,  510,83903,  273,83903,
+  281,83903, 1477,83903, 1516,83903,  948,83903,  165,83903,  903,84004,
+40704,83903,79139,84009,27533,84009,10001,84009,73307,83903,79139,84017,
+27533,84017,10001,84017,53500,83903,37595,83903,36049,83903,36539,83903,
+68851,83903,36041,83903,37573,83903,36275,83903, 1505,83903, 1011,84040,
+25793,83903,   11,84044,64397,83903,  483,84049, 8495,83903,   11,84052,
+60618,83903,  483,84057,  375,83903,  305,84060,  903,83903,  165,84064,
+ 1011,83903, 1505,84068,  305,83903,  375,84072,    4,83903,56555,84076,
+  483,84079,    5,83902,57811,84083,59743,84083,59933,84083, 9579,84083,
+ 9839,84083,51421,84083,39619,84083, 4303,84083, 4287,84083, 8093,84083,
+ 3837,84083,42113,84083,53487,84083,53703,84083,42435,84083,48885,83903,
+  483,84115,   11,83903,25793,84118,41019,84118, 8495,84118,59875,84118,
+ 9805,84118,53391,84118,    9,83903,82267,84132,  483,84132,38305,84132,
+79139,84139,10001,84139,27533,84139,38305,83903,    9,84146,79139,84149,
+27533,84149,10001,84149, 9805,83903,   11,84156,    5,84157,  483,83903,
+    9,84162,56555,83903,    4,84166,  483,84169,53391,83903,   11,84172,
+    5,84173,59875,83903,   11,84178,    5,84179,    2,80532,11087,84185,
+11307,84185,11713,84185,10439,84185, 2221,84185,10665,84185,11037,84185,
+ 2233,84185,17777,84185, 2215,84185,18739,84185, 4339,84185,79091,84185,
+79097,84185, 5075,84185, 4643,84185,79115,84185,79123,84185,59811,84185,
+36619,84185,68291,84185,68299,84185,24213,84185,24059,84185,22149,84185,
+22143,84185,72667,84185,60839,84185,35665,84185,59819,84185,59869,84185,
+35487,84185,    7,84185,    4,84251,27306,84185,24095,84185,53910,84185,
+55537,84185,79280,84185,80301,84263,83607,84185,40455,84185,25313,84185,
+ 8714,84185,32103,84185,26106,84185, 8800,84185,41746,84185,81569,84185,
+48009,84185,49001,84185,49321,84185, 4551,84185,81531,84185,81289,84185,
+81245,84185,83729,84185,10196,84185,70136,84185,10603,84185,    9,84305,
+ 4625,84185,    9,84309,81565,84185,    9,84313,23983,84185,    9,84317,
+76501,84185,68176,84185,79065,84323,59787,84323, 9513,84323,36545,84185,
+79065,84331,59787,84331, 9513,84331,  759,84185,35187,84339,10107,84185,
+  265,84342,  241,84343,69877,84185,  265,84348,  241,84349,  305,84185,
+ 8495,84354,  959,84185,35187,84359,28714,84185,77079,84185, 1011,84365,
+ 1010,84364,84367,84369, 1010,84365, 1011,84364,84373,84375,   47,84185,
+35187,84379,48245,84185,48975,84185,48451,84185,11277,84185, 5045,84185,
+52603,84185, 8495,84185,   10,84394,   10,84395,  305,84394,   11,84394,
+84399,84403,   11,84395,84397,84407,  331,84185,71229,84411,79549,84185,
+ 1011,84415,  265,84185,53813,84418,71229,84419,10107,84418,69877,84418,
+79757,84419,  903,84185,55211,84431,10291,84185, 1011,84435,25793,84185,
+   10,84438,   10,84439,27021,84438,   11,84438,84443,84447,   11,84439,
+84441,84451,42613,84185, 1011,84455, 1325,84185,71229,84459,    5,84185,
+27255,84463, 9287,84463,53167,84463,21605,84462,    4,84185,79139,84472,
+80301,84475,49475,84473,73066,84473,28715,84473, 1011,84473,71229,84484,
+71229,84473, 1011,84488,27693,84473,10047,84473,79287,84473,41019,84185,
+   10,84498,   10,84499,   11,84498,84503,84505,   11,84499,84501,84509,
+   59,84185,71229,84513,    4,84184, 8495,84517,41019,84517,25793,84517,
+49001,84517,49321,84517,48009,84517,  265,84517,78147,84517,23755,84517,
+39633,84517, 3785,84517, 8717,84517,41559,84517, 4311,84517,79665,84517,
+10351,84517,26331,84517,42731,84517, 4329,84517,79309,84517,27805,84517,
+10055,84517,    5,84184,27021,84563,24095,84563, 9195,84563,52915,84563,
+21605,84563,    9,84573,23651,84563, 9755,84563,51435,84563,67297,84563,
+ 4321,84563,69729,84563,26907,84563, 9317,84563,53215,84563,27323,84563,
+53941,84563, 3833,84563,10171,84563,70097,84563, 4295,84563, 5045,84563,
+11277,84563,53813,84185,  265,84610,  241,84611,48885,84185, 1011,84617,
+   11,84185,25793,84620, 8495,84620,41019,84620,   17,84185,30091,84629,
+65869,84185,   15,84632,79065,84635,59787,84635, 9513,84635,  803,84633,
+38305,84185, 1011,84645, 1347,84645,   15,84185,28714,84650,28714,84651,
+65869,84650,79065,84657, 9513,84657,59787,84657,28715,84650,84655,84665,
+28715,84651,84653,84669, 9195,84185,  241,84673,35187,84673,21605,84185,
+27255,84679,    7,84678,    4,84682,    4,84683,84253,84679,   16,84678,
+55211,84679,  803,84679,    9,84679,   17,84678,  903,84679,65869,84679,
+    4,84679,84699,84705,    5,84679,84685,84709,84691,84709,27021,84709,
+    4,84678,    7,84716,84709,84719,    5,84678,84687,84723,52915,84185,
+35187,84727,  241,84727,27021,84185,35187,84733,  241,84733,25793,84732,
+79139,84185,80245,84740,    4,84740,80301,84745,    5,84740,80151,84748,
+    4,84741,80319,84753,84751,84753,80207,84753,80283,84753,    5,84741,
+84743,84763,    5,80532,80759,84767,    7,84767,    2,84770,    3,84770,
+83251,84775,    2,84771,84776,84779,84775,84779,83251,84782,83251,84779,
+84775,84786,    3,84771,84773,84791,83251,84793,27306,84767,24095,84767,
+52603,84767,53910,84767,55537,84767,84438,84767,84394,84767,84498,84767,
+81539,84767,25793,84767,27021,84814,84185,84814,64289,84767,84060,84767,
+81569,84767,83729,84767,81245,84767,81289,84767,70136,84767,10196,84767,
+  273,84767, 1477,84767,  281,84767,  948,84767, 1516,84767,81565,84767,
+    9,84847, 1505,84767, 1011,84850, 5045,84767,11277,84767, 4551,84767,
+  922,84767, 1413,84767,20831,84767,19783,84767,20053,84767,58775,84767,
+ 9195,84767,  265,84873,   47,84767,60857,84877,  165,84767,  903,84880,
+41019,84767,84185,84884,27021,84767,25793,84888,  265,84889, 8495,84767,
+84185,84894,  959,84767,60857,84899,   89,84767, 5019,84903,60857,84903,
+  375,84767,83903,84908,  759,84767,60857,84913,  265,84767,53813,84916,
+69877,84916,10107,84916, 1011,84767, 1505,84924,54597,84925,  903,84767,
+  165,84930,  483,84930,54295,84931, 1447,84767,18967,84939, 1141,84767,
+18967,84943,    2,84767,61780,84947,    9,84947,60857,84950,54295,84947,
+70085,84947,11529,84947,10155,84947,53925,84947,60857,84947,    9,84964,
+    3,84767, 8063,84969,42361,84969,53667,84969,84185,84767,41019,84976,
+ 8495,84976,25793,84976,83903,84767,  375,84984,   33,84767,18967,84989,
+    2,84766,27021,84993,24095,84993, 9195,84993,52915,84993,21605,84993,
+    9,85003,67297,84993, 9755,84993,51435,84993,23651,84993, 4321,84993,
+26907,84993,69729,84993,10171,84993,53941,84993,70097,84993,53215,84993,
+ 9317,84993, 4295,84993,27323,84993, 3833,84993, 5045,84993,11277,84993,
+    3,84766,57811,85041,59743,85041,59933,85041,51421,85041,39619,85041,
+ 4303,85041, 4287,85041, 9579,85041, 9839,85041, 8093,85041, 3837,85041,
+53487,85041,42113,85041,53703,85041,42435,85041,52915,84767,  265,85073,
+  587,84767,60857,85077,70573,85077, 1369,84767,43503,85083,  483,84767,
+  903,85086,21605,84767,    9,85091,  145,85091,10107,84767,  265,85096,
+    9,84767,53813,84767,  265,85102,69877,84767,  265,85106,    4,80532,
+83715,85111,80781,85111,83789,85111,    7,85111,    2,85118,83511,85121,
+    2,85119,82163,85125,83507,85125,82573,85125, 1368,85111,83511,85133,
+25525,85111,84498,85111,84438,85111,84709,85111,79634,85111,80501,85145,
+84394,85111,64513,85111,63253,85111,62215,85111,81539,85111,64397,85111,
+  483,85159,83787,85111,    9,85163,43214,85111, 8495,85111,84185,85168,
+  587,85169,  331,85111,60857,85175,79139,85111,  903,85179,  265,85111,
+60857,85183,79987,85183,10001,85111,  903,85189,41019,85111,84185,85192,
+  587,85193,27533,85111,  903,85199,   59,85111,60857,85203,    3,85111,
+    4,85206,85125,85209,38305,85206,    2,85111,    7,85214,83511,85217,
+79549,85214,80501,85221,49155,85215,62464,85215,43215,85215,  903,85215,
+60857,85230,60857,85215,  903,85234,42705,85215,10311,85215,79641,85215,
+84185,85111,25793,85244,41019,85244, 8495,85244,25793,85111,84185,85252,
+  587,85253, 1325,85111,60857,85259,    2,85110, 8495,85263,25793,85263,
+41019,85263,49321,85263,49001,85263,48009,85263,  265,85263,78147,85263,
+39633,85263,23755,85263, 3785,85263, 8717,85263,26331,85263, 4329,85263,
+79309,85263,10055,85263,41559,85263,27805,85263, 4311,85263,79665,85263,
+42731,85263,10351,85263,49205,85111,  903,85309,21605,85111,  903,85313,
+  155,85313, 1275,85111,43215,85319,77751,85111,38305,85111,    7,85324,
+    2,85326,    2,85327, 1368,85324, 1369,85324,    2,85325,85335,85337,
+    3,85325,85329,85341,85333,85341,84185,85341,    2,85324,    7,85348,
+85341,85351,    3,85324,85331,85355,79549,85111,80451,85358,    2,85358,
+80501,85363,    3,85358,80337,85366,    2,85359,80519,85371,85369,85371,
+80437,85371,80489,85371,    3,85359,85361,85381,    5,80533,83932,85385,
+83933,85385,64148,85385,64149,85385,    0,85385,56555,85395, 1369,85397,
+    7,85385,83903,85400,60857,85400,  265,85401,83903,85407, 1275,85401,
+60857,85411,    0,85384,63015,85415,25380,85415,85413,85415,21605,85415,
+ 1369,85422, 1369,85415,21605,85426,    7,85384,85417,85431,25381,85431,
+85415,85435,63014,85431,85415,85439,85419,85431,85399,85431,85429,85431,
+85425,85431,  483,85431,60857,85450,85415,85453,60857,85431,  483,85456,
+85415,85459,54440,85385,83903,85385,    7,85464,27425,85385,53137,85385,
+ 9365,85385,  803,85385,60857,85474,62310,85385,85206,85385,85125,85481,
+  241,85385,  483,85485,54295,85484,54295,85385,  241,85490,  483,85384,
+   53,85495,  253,85495, 1471,85495, 1275,85384,55211,85503,21605,85384,
+28337,85507, 1369,85385, 1011,85511,60857,85385,    7,85514,  803,85514,
+    2,85384,85389,85521,85393,85521,55211,85521,64345,85521,84132,85521,
+36256,85521,83903,85521,    9,85534,    9,85521,83903,85538,35187,85538,
+35187,85521,    9,85544,    3,85384,85467,85549,85387,85549,85403,85549,
+85401,85549,83903,85557,85391,85549,85517,85549,85405,85549,   53,85549,
+ 1471,85549,  253,85549,76285,85549,76939,85549,72567,85549,  241,85549,
+  483,85579,    9,85579,    2,85385,    3,85385,  165,85587, 1108,85587,
+ 1072,85587,76337,85587, 1011,85587,  483,85596,    9,85596,85111,85586,
+85125,85603,    9,85587, 1011,85606,  483,85587, 1011,85610,80151,85384,
+   17,85615,85111,85385, 1368,85618,    7,85618,    2,85623,    2,85622,
+ 1369,85618,    2,85619,85629,85631,    3,85619,85627,85635,85121,85635,
+85217,85635,85621,85635,85133,85635,    2,85618,    7,85646,85635,85649,
+    3,85618,85625,85653,85125,85653,55211,85385,  265,85659,   17,85385,
+    3,80533,73221,85665,    9,85667,78796,85665,    9,85671, 8139,85665,
+53639,85665,42521,85665,85322,85665,    9,85681,55004,85665,85111,85665,
+77751,85686,    9,85689,42613,85664,  483,85693,10291,85664,  483,85697,
+79549,85664,  483,85701,85585,85665,    9,85705,    9,85664, 1369,85709,
+   15,85664,37663,85713,85125,85713,38305,85664,43053,85719,  483,85719,
+   17,85665,  903,85725,35187,85665,77751,85728,    9,85731,    4,85664,
+85125,85735,37663,85735,    5,85664,76939,85741, 1471,85741,   53,85741,
+  253,85741,76285,85741,72567,85741,  241,85741,    9,85755,  483,85755,
+    5,85665, 1505,85761,  922,85761,  918,85761,54597,85760,  903,85761,
+    9,85770,  483,85770,  483,85761,  903,85776,    9,85761,  903,85780,
+77751,85760,    9,85785,79756,85665,    9,85789,84185,85665,   16,85792,
+    7,85792,    4,85797,    4,85796,   17,85792,    4,85793,85803,85805,
+  483,85805,    5,85793,85801,85811,85797,85811,85795,85811,    4,85792,
+    7,85818,85811,85821,    5,85792,85799,85825,54597,85665,   11,85829,
+    5,85828, 1369,85665,    9,85835,18967,85665,    4,85839,  483,85841,
+77751,85665,35187,85844,    9,85847,    9,85845,85111,85851,85111,85844,
+    9,85855,    5,85845,   17,85859,    5,85844,    9,85863,77751,85664,
+  375,85867,79986,80533,  375,85871,    2,80533,80080,85875,80079,85877,
+80298,85875,80319,85881,80293,85875,    4,85884,80319,85887,    4,85885,
+80301,85891,11727,85875,11047,85875,17787,85875,18737,85875,78670,85875,
+77859,85903,10874,85875,77952,85875,77857,85909,    7,85874,83903,85913,
+85167,85875,85355,85875,85213,85875, 1216,85875,77751,85923,77877,85925,
+77751,85922,77857,85929,62310,85875,64483,85875,68896,85875,62464,85875,
+61780,85875,61688,85875,85159,85875,10831,85875,    9,85946,  413,85875,
+77751,85951,77837,85953,77751,85950,77859,85957,74571,85875,17178,85875,
+50959,85875,43400,85875,11177,85875,84077,85875,85913,85971,40675,85875,
+55546,85875,54440,85875,69196,85875,17125,85875,    9,85982,15029,85875,
+65869,85986,52169,85875,49155,85875,40453,85875,43305,85875,40005,85875,
+84767,85875,77751,86001,    9,86003,73994,85875,42613,85874,42795,86009,
+10291,85874,36131,86013,70135,85875,53919,85875,10195,85875,79842,85875,
+79757,85875,  903,86024,63493,85875, 8861,85875,80058,85875,80079,86033,
+54422,85875,11529,85875,54447,85875,52601,85875,  145,85875,35187,86044,
+36096,85875,79601,85875,79549,85874,80501,86053,79719,86053,64396,85875,
+85111,86059, 1011,85875,43215,86062,  241,85875,54295,86066,65869,85875,
+60857,86070,15029,86070,    9,85875,10831,86076,60857,86076,17125,86076,
+84076,85875,  483,86085,  803,85875,60857,86088,  903,85875,53813,86093,
+60857,86092,10107,86093,69877,86093,79757,86092,71229,86092,  265,85875,
+55211,86106,10371,85875,42787,85875,55211,85875,60857,86114,  265,86114,
+38305,85874,46169,86121,80531,86121,72818,85875,   11,85875,43215,86128,
+43316,85875,35187,85875,54295,86134,  145,86134,71229,85875,  903,86140,
+  155,86140,43215,85875,   10,86147,   10,86146,85111,86147, 1011,86146,
+84767,86147,   11,86147,86151,86159,   11,86146,86149,86163,  155,85875,
+71229,86166,    5,85874,55211,86171,64345,86171,84132,86171,36256,86171,
+83903,86171,    9,86180,    9,86171,83903,86184,35187,86184,35187,86171,
+    9,86190,    4,85875,80070,86195,80077,86197,80293,86195,80315,86201,
+80293,86194,80319,86205,  483,86195,83903,86209,80533,86194,    3,86213,
+    7,86195,86215,86217,    2,86217,86213,86221,79987,86194,80079,86225,
+83903,86194,  483,86229,77751,86195,79545,86233,    3,86235,    2,86234,
+86237,86239,    2,86235,    3,86234,86243,86245,77751,86194,79549,86249,
+    3,86251,    2,86250,86253,86255,    2,86251,    3,86250,86259,86261,
+    5,85875,85914,86265,85913,86265,83903,86268,49713,86265,49712,86264,
+86273,86275,49712,86265,49713,86264,86279,86281,53813,86265,64317,86265,
+64815,86265,62077,86265,10107,86265,69877,86265,   17,86265,83903,86297,
+35187,86297,60857,86264,85111,86303,65869,86265,    9,86307,  587,86265,
+60857,86311,83903,86265,85913,86314,79757,85874,79987,86319,    4,86321,
+    5,86320,86323,86325,    5,86321,    4,86320,86329,86331,80336,85875,
+79549,86335,    3,86337,    2,86336,86339,86341,    2,86337,    3,86336,
+86345,86347,83903,85875,   16,86351,    7,86351,86265,86355,    4,86354,
+    4,86355,   17,86351,    4,86351,    7,86364,    5,86351,86361,86369,
+    4,86350,86363,86373,  483,86373,    5,86350,86359,86379,86367,86379,
+86355,86379,86353,86379,54295,85875,  241,86388,35187,86388,60857,85875,
+    7,86395,    4,86396,    4,86397,86265,86397,   16,86395,   17,86395,
+  803,86394,55211,86394,  903,86394,65869,86394,    9,86394,    4,86394,
+86407,86419,    5,86394,86399,86423,86405,86423,85111,86423,    4,86395,
+    7,86430,86423,86433,    5,86395,86401,86437,77751,85875,  413,86440,
+77859,86443,  413,86441,77949,86447, 1216,86440,77857,86451, 1216,86441,
+78669,86455,    4,86441,79757,86459,    3,86461,    2,86460,86463,86465,
+    2,86461,    3,86460,86469,86471,    4,86440,79549,86475,    3,86477,
+    2,86476,86479,86481,    2,86477,    3,86476,86485,86487,79987,85875,
+80244,86491,80245,86491,80151,86491,    5,86496,    5,86497,    4,86491,
+80083,86503,80029,86503,80063,86503,86501,86503,    5,86491,80151,86512,
+    4,86490,80079,86517,86513,86517,86493,86517,86515,86517,86499,86517,
+    5,86490,86495,86529,86503,86529,77751,85874,86529,86535,86503,86536,
+86532,86535,86521,86535,86512,86535,86517,86545,86503,86535,86529,86548,
+86491,86535,    5,86552,86517,86555,    5,86553,86503,86559,85663,86535,
+85100,86535,    9,86535,84767,86566,84767,86535,    9,86570,    5,86535,
+86491,86574,86517,86577,86491,86575,86529,86581,80150,80533,80315,86585,
+80301,86586,80298,86585,80319,86591,80301,86585,80315,86594,80316,86585,
+80325,86585,80293,86585,    4,86602,80319,86605,    4,86603,80301,86609,
+85663,86585,85100,86585,    9,86585,84767,86616,84767,86585,    9,86620,
+    4,86585,80293,86625,80315,86627,80293,86624,80319,86631,    4,80533,
+79968,86635,79967,86637,80498,86635,80519,86641,80497,86635,    2,86644,
+80519,86647,    2,86645,80501,86651,78670,86635,77859,86655,77952,86635,
+77857,86659,    0,86635,21605,86663,  587,86665,    7,86635,  483,86669,
+18967,86671,    0,86634,19917,86675,58930,86675,86673,86675,56555,86675,
+  587,86682,  587,86675,56555,86686,    7,86634,58931,86691,86675,86693,
+86677,86691,86679,86691,19916,86691,86675,86701,86265,86691,86667,86691,
+86689,86691,86685,86691, 1275,86691,18967,86712,86675,86715,18967,86691,
+ 1275,86718,86675,86721,29023,86635,25513,86635,24619,86635,84363,86635,
+84723,86635,84471,86635, 1216,86635,77751,86737,77877,86739,77751,86736,
+77857,86743,63610,86635,63291,86635,84321,86635,86028,86635,86030,86635,
+85960,86635,86437,86635,76631,86635,76601,86635,74682,86635, 8974,86635,
+  413,86635,77751,86769,77837,86771,77751,86768,77859,86775,63493,86635,
+  483,86778,85875,86778,29598,86635,25545,86635,59206,86635,15029,86635,
+56555,86790,62942,86635,80030,86635,79987,86635, 1011,86798,74571,86635,
+85875,86802,  483,86802, 8861,86635,85875,86808,  483,86808,79926,86635,
+79967,86815,85875,86635, 8861,86818,63493,86818,74571,86818,79263,86635,
+76816,86635,77387,86829,76500,86635,84185,86833,   11,86833,  903,86635,
+28715,86838,56555,86635,15029,86842,  483,86635,63493,86846,74571,86846,
+ 8861,86846, 1011,86635,79987,86854,60857,86854,10073,86635,27855,86635,
+62278,86635,  587,86635,28715,86866,29026,86635,60857,86635, 1011,86872,
+ 1347,86872,28715,86635,   11,86879,84185,86879,  903,86878,  587,86878,
+ 1347,86635,60857,86888,    2,86634,    4,86893,    7,86895,    3,86634,
+85125,86899,37663,86899,    2,86635,79962,86905,79965,86907,80497,86905,
+80515,86911,80497,86904,80519,86915,79757,86904,79967,86919,71229,86904,
+77387,86923,77751,86905,79065,86927,    5,86929,    4,86928,86931,86933,
+    4,86929,    5,86928,86937,86939,77751,86904,79139,86943,    5,86945,
+    4,86944,86947,86949,    4,86945,    5,86944,86953,86955,    3,86635,
+85217,86959,85121,86959,86897,86959,86217,86959,85133,86959,    6,86959,
+    6,86958,    7,86958,86971,86975,    7,86959,86973,86979,60755,86959,
+35927,86959,38155,86959,37611,86959,71229,86958,84185,86991,   11,86991,
+79987,86634,79757,86997,    2,86999,    3,86998,87001,87003,    3,86999,
+    2,86998,87007,87009,80150,86635,79139,87013,    5,87015,    4,87014,
+87017,87019,    4,87015,    5,87014,87023,87025,84767,86635, 1368,87029,
+    7,87029,    2,87032,    2,87033, 1369,87029,    2,87029,    7,87040,
+    3,87029,87037,87045,    2,87028,87039,87049,    3,87028,87035,87053,
+87043,87053,87031,87053,71229,86635,    7,87061,    2,87062,    2,87063,
+ 1368,87061, 1369,87061,    2,87060,77387,87073,87071,87073,    3,87060,
+87065,87079,87069,87079,84185,87079,   11,87079,    2,87061,77373,87089,
+76635,87089,    7,87088,87079,87095,72519,87089,    3,87061,87067,87101,
+85875,87101,77751,86635,  413,87106,77859,87109,  413,87107,77949,87113,
+ 1216,87106,77857,87117, 1216,87107,78669,87121,    2,87107,79987,87125,
+    5,87127,    4,87126,87129,87131,    4,87127,    5,87126,87135,87137,
+    2,87106,79139,87141,    5,87143,    4,87142,87145,87147,    4,87143,
+    5,87142,87151,87153,79757,86635,80450,87157,80451,87157,80337,87157,
+    3,87162,    3,87163,    2,87157,79971,87169,79841,87169,79961,87169,
+87167,87169,    3,87157,80337,87178,    2,87156,79967,87183,87179,87183,
+87159,87183,87181,87183,87165,87183,    3,87156,87161,87195,87169,87195,
+77751,86634,87195,87201,87169,87202,87198,87201,87187,87201,87178,87201,
+87183,87211,87169,87201,87195,87214,87157,87201,    3,87218,87183,87221,
+    3,87219,87169,87225,    3,87201,87157,87228,87183,87231,87157,87229,
+87195,87235,80336,80533,80515,87239,80501,87240,80498,87239,80519,87245,
+80501,87239,80515,87248,80516,87239,80525,87239,80497,87239,    2,87256,
+80519,87259,    2,87257,80501,87263,    2,87239,80497,87267,80515,87269,
+80497,87266,80519,87273,77751,80533,79962,87277,    2,87279,79971,87281,
+    2,87278,79967,87285,80070,87277,    4,87289,80083,87291,    4,87288,
+80079,87295,79968,87277,79967,87299,80080,87277,80079,87303,80498,87277,
+80519,87307,80298,87277,80319,87311,80497,87277,    2,87314,80519,87317,
+    2,87315,80501,87321,80293,87277,    4,87324,80319,87327,    4,87325,
+80301,87331,81857,87277,78453,87277,80233,87277,80445,87277, 8453,87277,
+  273,87277,84484,87277,85230,87277,84531,87277,85277,87277,21522,87277,
+ 1516,87277,38266,87277,  948,87277,20239,87277, 1477,87277,37095,87277,
+  281,87277,84473,87277, 1011,87370,85215,87277,  903,87374,80242,87277,
+80448,87277,80447,87277,  903,87382,80241,87277, 1011,87386,38057,87277,
+  903,87390,  165,87277,  903,87394,21315,87277, 1011,87398, 1505,87277,
+ 1011,87402, 1216,87276,  412,87276,  413,87277,87409,87411, 1217,87277,
+87407,87415,  413,87276, 1216,87277, 1217,87276,87421,87423,  412,87277,
+87419,87427,12377,87277,  375,87277,57522,87277,67028,87277,67800,87277,
+  510,87277,  240,87277,  265,87443,77750,87445,77751,87444,87447,87449,
+77751,87445,77750,87444,87453,87455,  264,87277,84517,87459,85263,87459,
+81749,87459,  341,87459,  264,87276,  375,87469,  241,87277,81464,87472,
+81465,87473,87475,87477,81464,87473,81465,87472,87481,87483, 1011,87277,
+84473,87486,80241,87486, 1505,87486,21315,87486,  903,87277,85215,87496,
+80447,87496,  165,87496,38057,87496,  483,87277,65869,87506,    9,87506,
+    9,87277,56555,87512,  483,87512,56555,87277,    9,87518,65869,87518,
+65869,87277,  483,87524,56555,87524,    5,87277,84185,87531, 1011,87533,
+    2,87531,80532,87536,    3,87531,85215,87541,    3,87530,87539,87545,
+85263,87545,84517,87545,81749,87545,    2,87530,87533,87555,    4,87276,
+87531,87559,    2,87561,    3,87561,    2,87560,87565,87567,    3,87560,
+87563,87571,    3,87277,85111,87575,  903,87577,87559,87575,    0,87581,
+    1,87580,87583,87585,    1,87581,    0,87580,87589,87591,    4,87575,
+80532,87594,    5,87575,84473,87599,    5,87574,87597,87603,84517,87603,
+85263,87603,81749,87603,    4,87574,87577,87613,    2,87276,85663,87617,
+85100,87617,    9,87617,84767,87622,84767,87617,    9,87626,87575,87617,
+    4,87631,    5,87631,    4,87630,87635,87637,    5,87630,87633,87641,
+    2,87277,79962,87645,79965,87647,80497,87645,80515,87651,80497,87644,
+80519,87655,79962,87644,79967,87659,87559,87645,    7,87663,    6,87662,
+87665,87667,    6,87663,    7,87662,87671,87673,    4,87645, 1011,87677,
+77751,87679,77750,87678,87681,87683,77750,87679,77751,87678,87687,87689,
+    4,87644,  265,87693,77750,87695,77751,87694,87697,87699,77751,87695,
+77750,87694,87703,87705,    3,87276,  375,87709,87645,87709,    4,87713,
+    5,87713,    4,87712,87717,87719,    5,87712,87715,87723,    4,87277,
+80070,87727,80077,87729,80293,87727,80315,87733,80293,87726,80319,87737,
+80070,87726,80079,87741,    2,87727,  903,87745,77751,87747,77750,87746,
+87749,87751,77750,87747,77751,87746,87755,87757,    2,87726,  265,87761,
+77750,87763,77751,87762,87765,87767,77751,87763,77750,87762,87771,87773,
+    5,87276,87575,87777,    7,87779,    6,87778,87781,87783,    6,87779,
+    7,87778,87787,87789,87645,87777,    0,87793,    1,87792,87795,87797,
+    1,87793,    0,87792,87801,87803,87727,87777,    2,87807,    3,87807,
+    2,87806,87811,87813,    3,87806,87809,87817
+};
+
+const int s_nDataSize2 = 24772;
+unsigned int s_Data2[24772] = {
+    3,    9,    5,    6,  119,  796,  636,  113,  449,  235,  239,  105,
+  789,   96,  439,  624,  630,  230,  111,  110,  787,  786,  628,  627,
+  116,  115,  436,  435,  227,  226,   93,   92,  792,  791,  100,   99,
+  443,  442,  633,  632,  128,  183,  234,  178,  233,   85,  762,  203,
+   32,  742,  356,  169,  152,   12,  672,  741,  127,  168,  671,  740,
+   50,  352,  149,   64,  414,  197,  276,  751,  722,  396,  275,  434,
+  721,  785,  274,  795,  720,  448,  273,  719,  474,  758,  718,  392,
+  269,  748,  715,  400,  118,  794,  635,   81,   76,  750,  747,  597,
+  595,   91,  433,  225,   74,  745,  680,  565,  268,  476,  271,  761,
+  350,  678,  345,  567,  757,  471,  470,  563,  469,  561,  551,  461,
+  465,  706,  650,  714,  261,  332,  641,  708,  676,  542,  260,  458,
+  755,  314,  325,  658,  288,  349,  760,  654,  656,  564,  562,  644,
+  552,  642,  550,  259,  252,  254,  322,  311,  329,  109,  784,  626,
+   43,  395,  182,   55,  399,  186,  104,  447,  238,   41,  389,  173,
+  175,  193,  485,  580,  579,  734,   25,  733,  528,  548,  310,  546,
+  344,  526,  308,  560,  342,  525,  556,  558,  523,  524,  522,  520,
+  307,  622,  623,  431,  618,  620,  429,  617,  305,  615,  519,  518,
+  516,  778,  304,  250,  302,  776,  216,  218,  774,  215,  301,  300,
+  514,  771,  513,  541,  298,  512,  297,  535,  321,  508,  510,  319,
+  538,  539,  533,  507,  509,  296,  146,  705,  531,  537,  317,  557,
+  341,  143,  697,  555,  544,  339,  613,  426,  217,  773,  619,  428,
+  221,  780,  611,  610,  424,  609,  769,  423,  422,  768,  213,  625,
+  783,  670,  732,  782,  578,  577,  731,  484,  387,  668,  669,  171,
+  172,  375,  191,  575,  729,  482,  446,  667,  237,  574,  728,  481,
+  398,  666,  185,  573,  727,  480,  394,  665,  181,  572,  695,  694,
+  140,  738,  372,  246,  690,  689,  136,  244,  369,  767,  212,  766,
+  702,  701,  367,  257,  700,  315,  726,  382,   59,  407,  190,   52,
+  366,  157,   65,  417,  201,   63,  413,  194,  686,  692,  243,  248,
+  699,  256,  150,  354,  365,  364,  353,  156,  685,  348,  242,  661,
+  192,  409,  376,  378,  411,  164,  569,  717,  473,  391,  660,  177,
+  189,  406,  374,  371,  405,  162,  200,  416,  363,  362,  415,  155,
+  313,  324,  361,  360,  331,  312,  328,  381,  316,  330,  359,  323,
+ 4596,24359,41366,41344, 4857,37718, 4594,24357, 4846,37706, 4678,26650,
+ 4592,24355, 4844,37704, 4591,24354, 4843,37703, 8816,41900,22056,15422,
+ 7473, 8464,42932, 8814,41898, 6804,20483,12853, 8462,42930, 8809,42808,
+21978,15306, 7385, 8456,42895, 8807,41327,21965,15246,15293, 7372, 8454,
+42893, 3212,20457,36983, 3516, 6187, 6184,20453,29352,10563,10421, 2593,
+20452, 6183, 5637, 2589, 6182, 2645, 2619, 2283,26212,20199, 2269,12513,
+ 2614, 2661,18113, 2288, 4777,35226, 4775, 4774, 4773,42536, 2198,32674,
+32753, 8833, 8780,40027,43084,39938,43445, 8548, 8831,24157,26148,31156,
+29057, 8503, 8771, 8777,24156,26147,36425,33823,40025,43073,43081,39936,
+43443,22500,18803, 8829, 8770,40023,43072,39934,43438, 8546, 8827,24155,
+26146,31154,29044, 8501, 8765,24153,26140,36424,33800,33820,40022,43066,
+39933,43435,22498,18801,43065,40020,43434,39931,18800,22493, 8764, 8499,
+26128,24151,33799,36411, 8826, 8544,26120,24146,29025,31141, 8762, 8824,
+43063,40019,43432,39929, 2287, 2286,21235,26865,13688,26627,13207,20826,
+ 2106, 2073, 4667, 4378, 1966, 4054,13206,20825, 2159, 2168,18699,39853,
+10355,39675, 2167,39852,13205,18520, 2158,39674,20824,20823,42653,42280,
+18519,10116,21390,13926, 2032,42279, 1932,42652, 2166, 2157,42651, 5184,
+42278, 5035, 2070,21389,20822, 4377,13925,13204, 5034, 5183,13924,21388,
+ 5033, 5182,39673,42650,39851,42277, 4221, 5142,18518,21387,18698,20821,
+ 4220, 4982,10115,13923,10354,13203,39850,42276,39672,42649,20820,18697,
+42648,39671,42275,39849,18517,21386, 4376, 5032,13202,10353,13922,10114,
+ 4375, 5181,20819,18696,21385,18516, 4981, 5141,42274,39848,42647,39670,
+ 5031, 5180,42646, 5140,42273, 4980, 4219,21384,20818, 4374,13921,13201,
+ 5135, 5174,39653,42257,39831,42630, 5172, 5133,24141,26112,31138,29023,
+ 5026, 4969, 4975,24140,26111,36408,33796,39651,42249,42254,39829,42628,
+21363,18686, 5139, 5179,39669,42272,39847,42645, 5178, 5138,18515,20817,
+18695,21383, 5030, 4979,10113,13200,10352,13920,39668,42271,39846,42644,
+21382,18694, 5170,24183, 5169,36516, 5168,39992, 5167,22753, 5166,21404,
+ 5165,39867, 5164,21361, 4045,26846, 4044,21215, 5162,39827, 5191,21359,
+ 5190,39825, 5189, 5160, 5159, 4043, 5157, 5024, 1891,42248, 1847,42621,
+ 4193, 4341,18472,20750, 1681,21357,10093,13145,13869, 2660, 7371, 2659,
+ 2658,13144,20749, 1846, 1890,39824,18682,39649,10344, 1872,39823,18507,
+13143, 1889,39648,20748,20747,42620,42247,10107,18506,21356,13868, 1871,
+42246, 1843,42619, 2205,26240,26211, 2200,24249,24232, 2478, 2517,36625,
+34562,31491,29570, 2507, 2558,34076,37229,29433,31635, 8704, 8600,35491,
+38460,30352,32396,28999, 8171, 8335,38314,35364,32268,30297,30134, 8698,
+ 8591,35488,38453,30345,32384,32389, 8166, 8333,38305,35357,32255,30292,
+ 2285, 7325, 1898,14098, 1896, 1895, 1894,39359,24288,41706,41800,20017,
+37217,39357,36575,18022,26236,20013,24246,39355,39925,18013,18779,20001,
+22482,39395,20196,39397,20208,40017,39923,20064,42324,12370,42658,19065,
+18776,41387,41382, 9904,21392,10687,10412,41365,41360,18055,18053,39685,
+20893,39857,18775,43056,43431,42334,18524,42660,22479,40016,39922,14502,
+15946,39376,39374,20062,20060,21649,22478,39380,39378,12368,18702,43055,
+43430,18057,39680, 9906,39855,39991,21351,22752,39816,39990,39815,22751,
+21350,39639,39814,33754,42230,28989,42602,18468,18677,24118,26056,31087,
+28988,10090,10312,10318,24117,26055,36340,33753,39637,20700,20705,39812,
+18675,42228,42600,42219,42225,18464,42598,21348,39635,39810,13101,13106,
+13844,26054,24116,33752,36339,20699,21346,26053,24115,28987,31086,42218,
+42595,36338,39633,31085,39808,39667,39845,39666,39844,39665,39843,18693,
+18692,10351,10350,18514,39842,13199,13198,10112,39664,20816,20815,10111,
+18513,42270,42643,13919,21381,13918,42269,21380,42642,39806,21403,21344,
+39866,39805,39865,21343,21402,39804,21342,21175,26830,39802,21173,26826,
+21340,39346,24061,39338,32626,39333, 9843,39332,39331, 9814,39328,15936,
+39183,11746,19744,25614,39182,39181,39180,19836,42268,11903,42641,17932,
+17931,40961,40960, 9771,21379, 9770, 9769,40959,40958,17930,17929,39663,
+20814,39841,17928,40957,40956,42267,18512,42640,19835,39179,39178,11902,
+11901,39177,39176,19834,19833,19832,19831,39175,39174,11900,18691,40955,
+40954,17927,39662, 9768,39840,39173,19830,11899,17926,40953,13197, 9767,
+40952,20813, 9766,17925,40951,11898,19829,39172,11897,42266,19828,19827,
+42639,11896,40950,21378,13917,39171,39170,39169,39168,14088, 3310, 3309,
+35263, 2276,26305, 5245, 6267, 5248, 5445,10636,10624, 5401, 7751, 5390,
+ 5674, 2548, 5410, 3350, 3931, 3971, 3960, 6123,28071,22800, 8025,27598,
+16338, 7478,22061,15427, 3847, 3840, 3822, 5835,26825,21172, 7148,26571,
+13617, 6808,20693,13100, 3469, 3729, 3618, 6021,27993,22666, 7965,27534,
+16152,16158, 7368,21963,15285,15291, 3513, 3757, 3655, 6026,28010,22688,
+ 7970,27539,16193, 7376,21969,15297, 3722, 3611,27986,22657,22659,16147,
+ 3608, 3610,25575,25569,25573,25568, 2720, 2722,23945,23941,23943,23940,
+ 3606,26233,26200, 2718,24244,24224, 3603,22654,16143, 2716,22466,15931,
+ 8720, 2547, 2499, 2498,35234, 8719,35524, 7050,35233, 6181,20028, 5622,
+20027, 5610, 7023,23939,24648,23938,24484, 5952, 7920,22462,25567,27390,
+15928,25566,27757, 5620, 7027,36388,33781,31116,29009, 5970, 7936,33795,
+36407,29022,31137, 5612, 7025,24121,24653,24129,24494, 5960, 7922,26081,
+27412,26074,27796, 5601, 7014, 6501, 5946,27753,22458, 7917,27387,15926,
+ 4317, 7284,21850,15156, 5825, 5940, 5824, 5794, 7123, 6732, 6038,28015,
+22709, 7982,27551,16225, 7395,21983,15311, 8718, 5673, 7049, 8717,35523,
+23937,21560,14272,15352,40871,22739,16272,23936,22733,16263,14776,40870,
+21558,14265,23935,21474,14087,15148,40869,22445,15906,23934,41714,40868,
+34075,23933,34079,40867,41730,23932,41537,31827,37396,23931,41448, 4494,
+23930,41503,23929,26451,38349,32305,23928,24323,23927,40866,31785,37351,
+23925,40858, 4472,23924,40862,23923,40853,38197,23920,23919,38475,23914,
+23913,38152,23908,40840,28843,38481,23905,23904,23903,23902,23901,23900,
+23899,23898,23897,23896,40839,40838,23895,23894,40837,40836,23893,40835,
+23892,23891,40834,40833,23890,40832,23889,23888,40831,40830,23887,40829,
+23886,23885,40828,40827,23884,23882,40823,40826,40822,23879,23878,40819,
+40818,23877,23876,23922,23875,23874,32490,32499,23873,23872,32793,23871,
+17197,23870,23869,29043,33819,24320,40817,29655,38507,24317,24309,28839,
+33590,23867,23868,23865,40816,25558,25555,23866,40815,23860,23864,21472,
+14085,40814,22439,15900,25548,23863,40812,23859,23856,40811,40805,40808,
+23858,33581,33583,23854,23881,33580,33592,23853,23852,19635,33579,40804,
+23848,23844,33560,33558,35258,40795,23843,33557,33556,35255,25392,23842,
+33555,33554,23841,24131,24133,23789,17857,23787,18134,25390,26230,23785,
+25387,26229,26199,23783,23782,23781,23780,23779,23778,24120,24128,23777,
+17845,23775,27731,25366,18759,23762,23761,23760,23759,23758,23757,23851,
+23847,40801,40803,23850,33457,33578,35260,23849,33572,23756,33456,23755,
+25328,18750,10402,24219,24218,24217,24239,41600,41620,24216,24215,24238,
+29171,33958,24221,24241,24214,24237,24213,24236,24223,24243,24231,24248,
+24235,24212,41619,41599,24580,24740,24486,24650,24479,24643,24493,24652,
+24536,24696,24535,24695,24534,24694,24533,24693,24640,40701,30096,38438,
+24638,24477,35149,24692,24532,24054,24053,24052,24051,24050,23803,17878,
+23801,25476,23799,23798,23797,33549, 3281, 2981,35267, 2427, 2429, 2425,
+ 2424, 2495, 7047, 7649, 2423,21521,14156, 2422,35247,23754,40705,23741,
+40684,40700,23725, 4338,40674,23724,40673, 7842, 7748, 7750, 7746, 7745,
+ 7744, 7761, 7758, 7769, 7651, 7653, 7648, 7647, 7646, 7645,21520,14155,
+ 6300,21670,14601, 7644,35246, 8354,35392, 7811, 7809, 7813,37284,31745,
+ 7771,36483,31210, 7788, 7802,36473,31194, 4186, 4465, 4184,13064, 4181,
+ 4180, 4236, 4246,23721,39799,39630,23720,18459,23719,10083,18671,39628,
+33435,13819,10309,39797,28701,21329,36039,30815,42588,42206,25299,25298,
+13062,42586,20667,20672,42197,42203,23718,21332,13824,33434,42590,28700,
+42208,30814,36038,25297,20676,13069,39022,22404,15866,17830,43413,13837,
+ 9689,43025,21338, 9687,17828,40683,11384,19518,39000,11387,42593,21639,
+19521,42214,14460,40699,20689,13087,24049,24531,24691, 4190,23717,22449,
+15912,25296,20692,13099,23753,22427,15895,25337,20666,13060,23716,22403,
+15865,25288,20665,13059,13584, 4199, 4197,23711,19508,11363,25282,20745,
+13140, 9063, 9396, 9184, 9168, 9338,38785,32799, 9254,23359,17393, 9336,
+38782,32791, 9247,23353,17357, 9344,38793,32809, 9282,23387,17431, 9456,
+38858,32878, 9094,23244,17141,23710,21540,14212,15278,40657,22649,16130,
+ 2758,21538,14208, 3347, 5771, 1853, 5082, 1788, 4966,42481,42234, 1708,
+26963,42233,26591,42480, 1852, 3346, 3345,42479,37847, 1851,37846, 1835,
+13635,42478,42232,37845,26590, 1785,10346, 1834,35043, 1833,37844,13634,
+ 6891,27206, 6890,42477, 6889,37843, 5951, 5949,22464,27759, 5930, 5929,
+22774,28067, 5928, 5927,20495,26455, 5926, 5925,26249,26192, 5924,26307,
+ 5934, 5932,27724,22402, 5923, 6119, 5922, 7262,27717, 5920, 6917, 6277,
+ 5918, 5917, 5916, 5915, 5914, 5954, 6118, 6927,27234, 6888,42759,27205,
+29027,43024,42739, 8746,29048, 8768,43069, 6886, 6887,27204,42738,28699,
+43023, 8745, 8742,43021, 8741,43020, 8740,43019, 8784,43196, 8739,43018,
+ 8767,43068, 8523, 8744, 4957,42196, 5672,42195, 4956,42194,24230,42193,
+33939,33938,24127,42192,33769,35199,24492,42191,35198,33768,24688,20662,
+24528,20661,24048,41181, 4990, 4842,42304,37700, 5671, 5670,42303,37699,
+ 2546, 2545,37881,42519, 5669, 5668,37880,42518, 2544, 5667, 5666, 4137,
+ 5106, 5104, 5072, 5070, 5074, 5076, 5068, 5067, 5066, 5065, 5064, 5063,
+ 5100, 5096, 5095, 5094, 5084, 5062, 4634, 5061,42190,28698,42457,26562,
+ 4635, 5091,42302,26982,42517,26626, 4666, 5090,37879, 4989,13687,42301,
+42516,37878,26981, 4665,10365, 4136,35060, 5089,42515, 4988,26625,42300,
+42514,26624,26980, 4664,42299, 4135,26979, 5088, 4134, 4987, 4663,42298,
+42513, 2163,37877,13686, 2162,42512, 2150,26623,37876,10364,35059,13685,
+ 2161,42297, 2142,37875, 2140,42511, 2149,42296, 5087, 4986, 1917,26978,
+42295,26622,42510, 2148, 4848, 4862, 4827, 4826, 4841,37698, 4882,13463,
+42509,42294,37697,26621, 4840,10189, 4881,34876, 4839,37696, 4880,13462,
+37874,13684, 5086,37695, 4985,13461,42293,42508,37694,26977, 4838,10188,
+ 4879,34875,23729,34834,40698,40656,23709,34880,40655,41381,24211,34827,
+41560,41559, 4874,34826, 4876,34861, 4892,34905, 4878,37693,13460, 4898,
+37778,13508, 8353,35391, 8390,35436, 8581, 8534, 8602,38462, 8683,38525,
+15448, 8641,38478, 8579,15277,38435,15138,33431,16652,33730,33429,34560,
+29423,29381,40645,41866,33391,26227,33910,40643,18131,33513,11326,11531,
+33511,28664,40769,33510,40787,33508,28642,40785,33751,18774,41232,27772,
+33679,28943,12118,40634,40633,33677,28941,40629,40632,40628,33675,28936,
+41598,41618,33605,33597,33360,33359,33358,33357,33787,39161,39321,39320,
+36288,34527,26330,41849,18165,34522,26325,33349,34055,41845,18161,34536,
+39160,38969,23693,41793,39327,39626,32091,42030,33307,32090, 4703,33453,
+28723,25230,25229,33306,28623,26436,26446,33608,33305,40807,35522,19640,
+33304,40825,35232,19645,33303,34053,33301,34044,34048,33298,41691,33296,
+41683,41686,33295,33536,33540,33535,33292,33287,33282,33286,33935,33933,
+33279,40631,33711,41180,33709,41173,35230,19918,33708,41172,35520,19917,
+33707,41171,33577,28797,33278,28611,33892,29148,33886,29144,33277,28610,
+33276,28609,33275,28608,33274,28607,33291,28620,33273,28606,43071,33822,
+43437,35917,33272,28605,36118,33548,30917,35916,33484,35981,35979,30906,
+28760,30775,33546,36116,33383,36083,28645,33367,28749,33482,33271,35915,
+36081,30729,33270,28604,39412,30728,39470,35914,33309,33311,39410,39456,
+18196,25216,28625,35913,39468,39505,20324,25215,30734,41748,35944,41830,
+23695,23697,28638,39458,33331,39507,25232,25234,30736,33269,41797,41832,
+18192,23675,35964,35966,41701,41752,20319,23674,35912,30727,41697,28603,
+41792,33268,33267,28602,36620,34558,31487,35911,33425,33427,36622,28601,
+37113,31476,28689,35910,31489,33266,34471,37010,34556,30813,36021,36023,
+29384,34420,37214,28675,33409,33411,31478,37012,30791,33265,29426,35909,
+37115,34422,36005,36007,34066,30726,34473,29386,35908,30725,34068,37210,
+29428,33264,39067,39069,23701,30724,23703,35907,23673,39065,33386,25214,
+23672,39063,28670,25213,36000,30777,40776,40768,25250,25252,33263,40764,
+28600,40762,33262,28599,43013,30723,43400,35906,23671,21636,22383,25212,
+14454,15824,15837,33740,28975,43052,33261,43429,36320,33739,28974,43051,
+31074,43428,36319,24075,31084,21648,28986,22477,26012,36329,14493,33749,
+15945,43398,43011,22377,15823,14439,21634,26052,24114,33366,33365,28644,
+33480,28747,36111,33529,30902,36079,33473,33260,33259,33972,33258,33553,
+33285,28618,41597,41617,33284,33970,33294,33539,33528,28778,11448,40591,
+40590,33526,33525,33524,33523,39058,39057,23835,30901,23815,36110,33479,
+25517,28746,25494,40753,40752,33538,28787,40610,40608,33522,33780,40589,
+42861,23670,33778,35362,33256,35344,33254,33463,34043,29414,41685,41783,
+34041,29411,26400,26365,34040,41682,34039,34052,29420,34038,29410,34037,
+29409,34065,34064,29425,34036,29408,39406,31565,39466,37204,34456,39450,
+18188,26395,37101,39499,20313,26360,41742,41824,24283,24274,29519,34552,
+31485,41780,36616,41681,34035,29407,36615,34551,31484,37203,34455,29376,
+37100,31472,34411,37003,34047,29418,41695,41790,34046,34050,34034,34073,
+34032,33930,33941,29158,33932,29155,33929,29153,33798,41083,18043,35223,
+35283,35285,35154,35225,35169,30109,40588,40587,35146,30088,22376,15822,
+35144,30086,22374,15820,35142,30084,22372,15818,39529,39623,35148,35209,
+39159,35167,39318,35262,30208,40586,40585,35254,30204,41614,41595,35257,
+30206,40794,40799,35162,40709,18758,34825,35269,35266,10793,10619,35245,
+10783,10561,35251,35243,35242,33724,33728,33722,33721,33968,34685,29738,
+40704,40703,34727,29780,41380,41359,34710,29763,20739,40561,13138,40560,
+34684,29737,20657,40559,13052,40558,33851,27196, 9902,42736,26993,36435,
+42547,42321,12366,27711,36437,43010,33439,42468, 9680,42735, 9685,36043,
+11382,33445,11374,42216,36041,43009,33849,37911, 9900,42734,35066,36431,
+37907,33847,12364,27710,36433,43008,35081,12602,37746,35083,35007,31772,
+37338,35022,35015,35047,35005,35004,35003,35002,35001,35000,10302,35071,
+10368,35013,35012,35011,34999,10301,13577,37817,34998,42180,10300,28558,
+17770,37820,19393,34996,13579,42450,37818,26546,35045,35058,42292,10363,
+26976,10362,37873,13683,35057,13682,42507,37872,26620,35056,37692,10361,
+13459,34874,37871,37691,35055,13681,10187,37870,34873,35054,37869,10360,
+13680,35053,37868,33660,25733, 9805,40999,26975,36216,42506,42291,11876,
+25732,36215,40998,33659,42505, 9804,40997, 9803,36214,11875,33658,11874,
+42290,36213,40996,33657,37867, 9802,40995,35052,36212,37866,33656,11873,
+25731,36211,40994,33655,37690, 9801,40993,34872,36210,37689,33654,11872,
+25730,36209,40992,33496,34824,18484,18433,34860,34891,18526,34871,42289,
+10186,26974,10185,37688,13458,34870,13457,42504,37687,26619,34869,37686,
+10184,13456,34868,37685,34922,37771,10204,13501,34915,37764,35355,41246,
+40557,24074,35361,40556,41290,23645,35390,35394,35388,35387,35423,35431,
+35421,35420,35419,34424,34430,29390,34410,29375,34409,29374,34408,29373,
+43003,34454,43397,37099,34419,34418,29383,34554,25244,41863,17813,34550,
+27709, 2281,26243,26215, 2280, 2279,26242,26806,26214,26542,23643,17768,
+ 9617,19682,25590, 9615,11631,25602,17766,11650,19701,23641,24043,17975,
+ 9857,19915,25886, 9855,12116,25884,17973,12114,19913,24041,24525,18827,
+24685,10438,18963,10587,18825,10436,24523,10585,24683,18961, 2443, 2442,
+18824,26805,10435,26541, 2441,21154,13576, 9256,38787,32802, 9246,38781,
+32790, 9253,38784,32798, 6490, 6682,39661,39839, 6676, 6675, 6674, 6673,
+ 6672,39158, 6697,23640, 6775, 6783,36532,31231, 6580, 6579,18960,26804,
+10584,26540, 6578,21153,13575, 6857,38536,32501, 6867,38538,32503, 6855,
+38534,32498, 6822,20490,12860, 7477,22060,15426, 6814,20485,12855, 7472,
+22055,15421, 8988,38813,32831, 8677,38488, 8239,38346, 6280,21655, 6279,
+21654, 6320,23639,23638,23637,23636,40555,23635, 6274, 6315,38953, 8751,
+ 8823, 6245,23632,23631,14039,20651,37335,31769,15808,34822,24166,24163,
+37375,31808,23727,25314,39344,39342,23630,14031,25171,15799, 6241,42999,
+ 8753,42998, 6240,42997, 6239,42996, 6238, 7605, 7603,21633,24145,14431,
+24150,23743,21632,14430, 7577, 7576,21645,23768,14481,23764, 6237, 6236,
+21631,42614,14429,42241, 6235,21630,14428,24073,24072,24071,24070,41264,
+24069,24066,24065,37331,31766,24064,26009,24063,21647,14491, 8775,43079,
+ 8774,43078, 8737,42995, 7643,21669,14595,23622,21711,14828, 7827, 7826,
+21710,23621,14827,23620, 7824,21709,14826, 6347, 6349, 6351,38519,32485,
+ 6362,38530,32492, 6364,38532,32494, 6358,38528,32489,18365,24583,18606,
+18598,18597,18596,42444,37811,24657,24497,24634,24469,35138,24040,24039,
+24522,24682,24681,24521,24578,24738,39405,39465,41680,20283,41779,18147,
+18187,41741,20312,39449,41823,39498,24520,24680,24679,24519,24038,24037,
+39157,39156,40949,19826,40948,17924,23619,23846,24202,35241,41126,33720,
+25977,35386,41125,33719,25976,33718,41124,24482,24646,23834,23814,19058,
+10678,43037,36075,43422,30854,19057,10677,42994,35892,43396,30674,15796,
+22352,24144,24149,23613,23612,19134,10762,42990,37248,43394,31694,18444,
+10075,18466,10092,18432,10073,18431,10072,18552,10124,18550,10122,23611,
+23610,24036,24035,24518,24678,24677,24517,18454,10080,23609,23608,22370,
+22368,15817,18448,25149,25148,18744,18741,10391,20660,23752,23751,22426,
+22425,15894,18430,25336,25335,18757,18756,10405,20648,24161,24159,22349,
+22348,15794,18522,26155,26150,18733,18732,10388,20880,35161,40708,34821,
+25334,18505,10106,18494,10104,23607,23606,19397,19395,11212,18488,25147,
+25146,17776,17773, 9620,20742,18381,38855,18383,23136,18385,38407,17765,
+38850,17764,23121,17763,38405,17762,43195,17839,43034,17985,42989,17984,
+42731,28965,42744,31065,17998,28977,19979,31082,42988,19997,43054,18379,
+37275,17761,42173,28551,26945,42439,42170,28550,26539,30673,42436,42437,
+19380,26536,26537,17760,42307,28549,30672,19379,42537,17759,42176,28548,
+26948,37814,17758,34994,19378,30671,42446,19377,37812,17757,42746,28547,
+30670,19376,43059,18265,10019,18264,10018,42987,20311,43393,18186,18921,
+18906,18919,18915,18807,18731,38831,18730,23104,18729,38403,18869,18878,
+18890,18823, 1666, 1701, 1613,22346,27707, 5904,15787,15792,27365, 7899,
+15124,15129,21836, 7255, 1669, 1704, 1616,22339,27700, 5897,15785,27358,
+ 7892,15122,21829, 7248, 1664, 1699, 1611,22772,28065, 6116,16309,27593,
+ 8020,15404,22040, 7459, 1663, 1698, 1610,21183,26835, 5820,13632,26587,
+ 7143,13137,20738, 6799, 1829, 1839,37855,42487, 1838, 1828,42486,37854,
+ 2028, 2063, 1963,40545,40543, 2030, 2065, 1965, 2026, 2061, 1961, 2025,
+ 2060, 1960, 2154, 2146,37897,42535, 2153, 2145,37896,42534, 1827, 1837,
+37853,42485, 1662, 1697,21182,26834, 1622, 4117, 7502, 7272, 7274,27373,
+27378,27730,27742,17756,17854, 7245,27355,27697,18094, 7287,27392,27763,
+ 6313, 7244,27354,27696, 6266, 7243,27353,27695, 6311, 7242,28038,27694,
+ 7421, 7241,27352,27693, 6335, 7267, 7266, 7265, 7494,23605,23604,25145,
+25144,23603,25143, 7324, 7323, 7322, 7321, 7320,20812,13196, 7319, 7318,
+21377,13916, 7317, 4373, 7238,26225,26196, 8973,23120,16979, 8991,23130,
+16996, 7361, 7359,33574,27527,28795,27980,30929,36127,23669,25203,23595,
+25135,23750,25342, 8946,23103,16963,18369,38399,17755,38397,18727,38395,
+39660, 8200,39838, 8199, 8198, 8197, 8196,39155, 8195, 8452,38335,42884,
+ 8140, 8431,38284,42842, 8238, 8459,38345,42916,17754,17853,18767,18068,
+ 4795, 4925,37367,42056, 4484, 4737,42533,37895, 4794, 4924,37366,42055,
+ 4483, 4736,37894,42532, 5148, 4829,39792,26808, 5188, 4825,39864,26903,
+39989,27146, 4804,37381, 4788,37328, 4856,37595, 4824,37717, 5146, 4855,
+39788,26801, 6299,27264,27094, 4457, 7316, 4456,27091,27262, 6297, 4299,
+ 4454,27752,27386, 7280, 4453,27978,27525, 7357, 4452,28047,27577, 7432,
+ 4451,27140,27285, 6329, 4450,27692,27351, 7237,13569, 4475,27089,27259,
+ 6295, 6696,21031,13404,34709,29762, 4560,34755,29808, 4581,34683,29736,
+ 4540,33871,35166,33467,24062,23862,25554,23594,25134,23714,23713,25286,
+ 4462, 4464, 4447, 4446, 4445, 4444, 4443, 4442, 4441, 4490, 4488, 4440,
+ 4439,34673,29726, 4521,33234, 4460, 4438, 4471, 4714, 4116, 4473, 4716,
+ 4119, 4497, 4755, 4167, 4493, 4495, 4753, 4165, 4466, 4711, 4111, 6367,
+21723,14912, 6860,21744,15033, 9259,23362,17407,23593, 6328,21692,14780,
+ 6339,21695,14794, 6324,21690,14774, 4486, 4739, 4149, 4482, 4735, 4147,
+14023, 4480, 4733, 4145, 4479, 4732, 4144, 4793, 4923,37365,42054, 4807,
+37432, 4864,37753, 4806, 4936,37431,42088, 7907,23592,42849,23591,42851,
+23590,42847, 8458,42915, 4918, 4916, 4911, 4910, 4909, 4933, 4932, 4931,
+ 4908, 4907, 4914,33979,42019,18138,33978,33765,42018,18021,35195,35194,
+42017,18787,33764, 4922, 4792,42053,37364, 4747,26177, 4701,26259, 4705,
+ 4704, 4700, 4699, 4698, 4724, 4726, 4741, 4152, 4707, 4109, 4697, 4101,
+ 4696, 4100, 4695, 4099, 4694, 4098, 4693, 4097, 4745, 4156, 4749, 4162,
+ 4751,25133,24475,35152,24229,33977,24126,33763,24491,35193,34428,29388,
+37024,34477,31481,37194,37023,31480,42016,37193,42435,34476,18270,10027,
+26730,20331,26939,18213,20344,12777,42015,18212,42434,20330,18798,10416,
+26729,20025,26938,18796,21497,14105,42014,18038,42433,21501,18025, 9892,
+26728,21500,26937,18037,20021,12308,42013,18795,42432,20024, 4927,42065,
+ 4906,42012, 4935,42087, 4159, 4161, 4096, 4095, 5108,35087, 5099,35070,
+ 5057,34992, 4094, 5661, 4092, 5336,14586,14141,11159,11144, 4091, 5658,
+ 4090, 5522,14874,14302,14990,14331, 5862, 8892,17350,17552, 4089, 4088,
+ 4087, 5339, 4103, 5225,14403,14016, 5549,35329,26162,10521,41333,26658,
+38425,42315,42540,15112,26160,38424,41335,33653,25729, 9800,40991,26618,
+36208,42288,42503,11871,25728,36207,40990, 4791, 4921,37363,42052, 4478,
+ 4731,21062,26749, 4143, 4142,37893,42531, 4053, 4052,21234,26864, 4790,
+ 4920,37362,42051, 4477, 4730,21061,26748, 2152, 2144,37892,42530, 2059,
+ 2024,21233,26863, 4141, 4051, 1959, 4140,35970,21026,19466,37325,19470,
+37594,35973,20647,36795,37324,20288,21025,20446,20646,37216,37593,36757,
+37592,20286,20645,20426,21024,37208,37323,36392,41275,36391,41274,36390,
+41273,36562,26297,36140,27688,36146,27687,37256,36530,36566,21023,20236,
+37322,20194,37591,36542,20644,36570,37273,38249,36136,30938,42243,33227,
+42616,33585,35886,30656,42245,33587,42618,33226,35885,30655,43077,28533,
+43442,33225,36062,30839,43032,28725,43420,33455,35884,30654,42323,28532,
+42657,33224,35963,40621,35883,30653,28530,41592,37231,31646,37228,31634,
+37227,31633,37226,31632,37225,31631,36387,31115,36386,31114,36385,31113,
+36384,31112,36134,40810,36142,40821,36071,40723,42984,38423,38141,32157,
+38140,32156,38139,32155,38149,27088,38109,42750,38108,42749,38107,42748,
+38187,27117,38186,27116,38100,42743,38088,27686,38247,38185,27115,38191,
+27124,38214,27132,38159,27072,38158,32171,38157,32170,38156,32169,38228,
+27110,38222,32183,38091,32101,38138,27063,36315,41193,31056,36314,41192,
+31055,36313,41191,31054,36317,41195,31058,36312,31053,36311,31052,36310,
+31051,36488,36486,36503,36501,37279,38775,37277,23368,37238,21750,37281,
+21729,38738,38749,38748,38747,38746,38867,37264,27685,37262,31730,42983,
+29628,43392,34603,37271,21705,37267,27297,37266,21703,37261,21701,36206,
+40989,40988,36205,36204,40987,11870,25727,37684,13455,36203,40986,11869,
+25726,37865,13677,36202,40985,11868,36078,42982,36077,40791,11447,37590,
+37321,37589,37320,37588,37319,37587,37318,37601,37727,37586,37585,38474,
+27258,38427,42992,38441,43041,42981,38422,38491,38421,40661,15111,25290,
+37828,13590,37018,41853,37017,41852,37016,41851,37014,41847,37022,41855,
+36427,41329,37904,42542,20055,26153,42839,38280,36037,40659,42464,37830,
+19498,25285,42838,38279,36429,41331,27347,21820,20057,26158,42837,38278,
+37832,42467,37810,42431,37809,42430,37825,31965,37834,31981,37808,31952,
+37807,31951,37806,31950,37805,31949,37804,31948,37917,37915,37803,37802,
+37901,37900,37801,42429,37800,42428,37799,42427,37910,42544,37909,32040,
+37903,32034,37891,42529,37361,42050,21232,26862,21060,26747,37890,42528,
+42049,37360,21231,26861,26746,21059,37889,42527,21230,26860,37888,42526,
+21229,26859,36250,41019,31021,36249,41018,31020,36248,41017,31019,40536,
+36252,41021,31023,36246,41015,37359,42048,19815,25716,41014,36245,36244,
+41013,42047,37358,19814,25715,41012,36243,36242,41011,37887,42525,19813,
+25714,41010,36241,36240,41009,42524,37886,19812,25713,41008,36239,36238,
+41007,25712,19811,19810,25711,41006,36237,38303,27404,38277,32219,32089,
+31946,38295,32233,38293,32229,38301,32251,38313,32267,38312,32266,38311,
+32265,38310,32264,38316,32270,38322,27497,38321,32275,38320,32274,38319,
+32273,38348,32304,37330,37597,39790,37599,37315,37576,39863,37575,39988,
+37574,37314,37380,21016,21068,20643,20887,37573,37716,37379,37715,39787,
+37714,37313,37312,37393,37311,31761,37371,31804,37429,31832,37334,37333,
+31768,37340,31774,37317,31763,37373,31806,37310,31760,37309,31759,37308,
+31758,37307,31757,37306,31756,37305,31755,37342,31782,37304,31754,37395,
+31826,37357,42046,21058,26745,37356,42045,21057,26744,37384,21073,20905,
+37725,37383,42080,21072,26757,36539,31236,42240,33909,42613,33908,36552,
+36554,41277,27230,41843,41861,41231,32116,41230,41229,41228,40619,41868,
+26318,41870,26320,40616,41138,41136,41859,41151,41140,40535,21494,14101,
+23589,22490,15957,40534,22327,15761,11105,12188,25952,21433,14012,41188,
+42876,41187,42788,41186,41198,41197,41185,41184,41183,41190,22326,15760,
+25107,21432,14011,40532,21476,14091,25705,22469,15935,40531,22471,15939,
+25961,21478,14093,40530,40528,40529,40526,40524,40522,40521,40546,40520,
+40525,40519,40517,40518,40515,40513,40511,40510,40516,40509,40544,40508,
+40527,40507,41533,40506,41451,40505,41499,40504,26449,40503,25565,42936,
+22325,41892,27294,40502,40500,40501,40498,40497,22354,40496,27209,40495,
+40494,40493,40492,40491,40490,40489,40488,40487,40486,40485,40484,40483,
+40482,40481,40480,40479,40478,40477,40476,40475,40474,40473,40472,40471,
+40470,40844,40873,40842,40469,40468,40467,40731,40727,40726,41525,41516,
+41491,41482,41440,41413,41439,41412,41515,41524,41481,41490,43735,22324,
+15759,16624,28157,21431,14010,43733,32591,21430,14009,28150,22323,15758,
+43855,22322,43755,43758,43761,43764,43754,43757,43760,43763,43720,43719,
+43718,43717,43716,43715,40425,40428,21429,14008,23586,22321,15757,40421,
+40427,40420,40539,21428,14007,25691,22320,15756,40538,40419,41106,41105,
+41104,41103,41102,41101,41100,41099,41098,41097,41096,41095,41094,41093,
+41092,41091,41624,41622,41170,41169,41155,41150,41149,25938,40466,41386,
+41364,41377,41358,41385,41363,41376,41357,41362,41384,41356,41375,40682,
+40681,40697,40696,40680,40695,42655,42309,42637,42264,42636,42263,42635,
+42262,42612,42239,41840,41839,40760,40781,40751,40750,40749,40748,40747,
+40746,40745,40744,40743,19610,11499,40767,40742,19609,11498,40922,40921,
+40920,40919,19824,11893,40806,19637,40824,19642,43451,43494,43383,43382,
+43381,43426,43425,43403,43406,43493,42869,43492,41082,43497,25564,43543,
+26448,43380,27232,43418,27208,41130,41128,41123,41122,41121,19910,41120,
+19909,41119,21668,14585,25832,19949,12173,41118,21519,14140,25831,19948,
+12172,40717,21471,14084,25676,22424,15893,40716,21470,14083,23749,22423,
+15892,40715,21469,14082,25333,20638,13037,40714,40713,21468,21467,14081,
+18429,25332,25331,18755,18754,10404,20637,43096,43094,43089,43552,43379,
+43378,43391,43377,43405,43402,43376,43412,43411,43410,43050,27771,43049,
+27770,43154,43150,43147,43146,42787,42875,42786,42791,42879,42790,42878,
+42785,42874,42784,42873,42783,42872,42797,42800,42887,42799,42886,42804,
+42889,42806,42891,42796,42883,42795,42882,42794,42881,42756,42863,42773,
+42771,42766,42151,26932,42150,26931,42149,42148,42147,43496,43152,43542,
+43214,43417,43030,42146,42578,43375,42972,42145,26304,42144, 8714,42143,
+ 4292,42142,41168,42213,26958,42212,26957,42211,42592,19520,28500,11386,
+33192,42172,26944,42175,26947,41865,40982,40981,36199,25725,40980,33652,
+36198,41589,38420,41594,26258,28531,41575,30651,28499,28529,30616,41573,
+28498,26256,41591,41588,26253,29448,41570,31341,29251,41587,37002,26222,
+41569,34280,36861,41579,41583,42426,42003,42441,42021,42422,42001,42421,
+42000,42420,41999,42419,41998,42418,41997,42549,42554,42417,42416,42415,
+42414,42413,42461,42460,42466,42035,42463,42033,42157,42424,42141,42412,
+40979,40978,25668,42855,26110,42918,25092,42853,42871,42934,22317,42082,
+25091,41996,26252,41995,41994,42037,43149,43093,42770,43091,42768,42068,
+26182,43088,42765,42067,41993,41992,41991,41990,41989,41988,41090,42493,
+42031,42411,42455,41986,42410,42058,35228,41985,33976,41984,33762,41983,
+35192,41982,42064,26720,26751,42079,26756,41556,41555,41554,41553,41552,
+41551,41550,41549,41548,41547,28954,36303,29445,28595,30719,28949,31037,
+31036,28948,29138,29146,42040,18503,28890,11603,42085,18546,29136,12591,
+28992,34983,33191,33607,28497,28496,28495,30615,28494,30614,28598,30722,
+28597,30721,28493,40722,28492,43040,28938,33362,33190,28940,28933,33521,
+28882,33189,28885,28491,33576,28490,28489,34058,28488,43036,30613,28487,
+33738,43048,30612,28486,33188,33589,30951,30611,36138,35850,37007,33187,
+34415,37109,35849,34465,37206,33186,33354,35968,35848,34061,36115,33185,
+33364,35978,35847,33545,36598,33184,33281,35919,35846,33986,37009,33183,
+34417,37112,35845,34470,37005,33182,34413,37103,35844,34460,36002,33181,
+33988,36600,35843,33389,36004,33180,34063,37213,35842,33408,35921,33179,
+33533,36113,35841,33289,29190,34982,29185,31274,29184,33907,37001,33984,
+34407,37098,36596,34453,37212,33407,18346,19496,28643,33544,28617,28614,
+28485,28484,28483,28673,28481,28479,29406,31544,29413,33178,34458,29378,
+33352,37000,34029,34406,37097,37202,34452,29424,33406,34469,29382,29417,
+29281,29422,29317,29405,29250,28838,28836,37849,42483,28814,30940,28478,
+28477,37842,42476,28476,30606,28475,28474,38452,43058,28473,30605,28472,
+28471,42453,37823,28739,28734,38419,42971,29679,43208,29678,43207,31729,
+29627,33177,43206,31728,29626,29677,29650,43205,38505,28776,28775,42970,
+36999,33520,34405,37096,36109,34451,35977,33543,17815,19590,28786,28783,
+28774,28772,28771,30898,28770,28769,42474,37840,29623,12817,34588,34600,
+31712,31658,37250,37234,37236,37269,29630,29589,34609,34590,33919,33906,
+33913,33905,42969,31273,29183,33904,31235,36538,33925,31246,36556,36588,
+29160,33943,37105,34462,18195,20323,37111,34468,18199,20327,37192,34475,
+34981,37798,37021,34427,37199,34486,34447,37041,37036,34442,37198,34485,
+34446,37040,37035,34441,37197,34484,34445,37039,37034,34440,37196,34483,
+34444,37038,37033,34439,29372,42968,31543,29404,33981,31196,30367,30203,
+30366,41981,18427,30356,14108,42029,18442,30336,14049,43491,18868,41980,
+32456,32455,30380,30282,32249,32248,37303,10546,37572,14501,20624,30273,
+35009,30290,34980,30280,30107,30279,30106,42967,38418,34593,34595,19025,
+34597,19027,34592,19023,35427,30962,17897,28470,17732,38480,19333,35429,
+19649,30604,38482,28844,35458,30603,17731,29656,18373,38508,20466,35444,
+19332,31721,38493,28469,35460,31660,18367,29663,18375,38516,20472,35448,
+20459,31725,38495,29587,28963,35440,31716,18371,30078,18726,38490,21427,
+35454,20463,32088,38502,29646,29661,38512,29659,38510,34979,37797,17730,
+19331,34977,37793,37795,35338,30602,17729,30097,18746,38439,21463,35336,
+19330,32099,38437,28468,29180,29178,35416,31261,18112,29162,38477,20192,
+35434,31268,18127,29166,38486,20217,35328,31264,18119,29164,38417,20198,
+35327,31092,18019,30124,18785,38416,21482,35326,20004,32123,38415,28995,
+34436,37030,18144,20280,34399,36995,29581,31652,29460,31502,31466,29366,
+29003,31106,30139,30601,32132,28467,30142,30600,32143,28466,31130,29012,
+34426,37020,17728,19329,34393,36989,28465,30597,29451,31497,31451,29356,
+29455,29447,31340,30077,32087,31494,29249,30178,30202,30177,30299,30201,
+30200,34404,36998,18725,21426,34279,36860,29360,30138,38134,36982,29363,
+30425,38670,36988,29362,36987,29359,36981,29848,31780,31779,37302,10167,
+37571,13097,20623,29838,31753,31752,37378,10150,37713,13026,20886,29854,
+29837,29836,29887,36236,41005,31801,32030,31800,32029,41004,36235,37355,
+42044,31799,32028,31798,32027,29877,29972,42043,37354,31797,32026,31796,
+32025,29876,29971,37885,42523,31795,32024,31794,32023,29875,29970,42522,
+37884,31793,32022,31792,32021,29874,29969,29873,29968,31791,32020,31790,
+32019,29872,29967,37442,31835,31838,29892,20945,13294,37758,10198,37441,
+42091,31834,32051,31837,32054,29891,29979,29963,29965,29961,29949,29948,
+29947,29946,29945,29976,29975,29974,29956,31972,31971,41977,33975,31945,
+33761,31944,31943,35191,29944,31942,31941,42063,42090,32050,32053,29978,
+37353,42042,31017,31016,31015,31014,28924,28923,37883,42521,31013,31012,
+31011,31010,28922,28921,36234,41003,31009,31008,28920,31007,31006,28919,
+36573,36559,30749,41750,39927,27061,36085,28663,39519,26343,39521,26345,
+39517,38971,39061,30955,30953,28834,28832,26597, 9597,20771, 9596,30942,
+28812,13649,13159,36568,29087,20211,36550,30974,39555,30976,31207,31202,
+39566,31213,39568,31215,32332,32324,14975,14864,32331,30971, 9587,30784,
+30885,11334,11536,31035,28947,31034,28946,31033,28945,31032,30680,30682,
+31027,43145,27971,38105,36361,38104,36360,38103,36359,38102,36358,30596,
+30904,30595,30731,30594,30858,30593,30922,30592,31569,30591,31279,41602,
+28464,40779,28463,40729,28462,30788,30920,30787,30919,30589,32108,30587,
+30851,40741,31218,31282,31217,33158,31244,33923,33157,31281,31243,33922,
+31223,31649,31222,33156,34481,31229,33155,31648,34480,31228,31103,41708,
+30586,41705,30751,34057,30585,34060,30837,33551,31227,34479,33921,31242,
+30584,33388,31238,33912,30583,33405,34467,30582,30581,34464,31590,33351,
+33917,31240,31277,33471,30580,33542,30579,35822,28461,24137,33154,24135,
+30578,35821,28460,20315,33153,18190,30577,35820,28459,20322,33152,18194,
+40766,40775,28458,28669,33151,33385,31272,30897,33903,31234,31271,34450,
+33902,31233,31270,36595,29182,20310,33983,18185,30576,35819,28457,20059,
+33150,18701,40773,28667,42406,40772,30889,33149,30856,33148,31111,42577,
+31110,31109,12307,41976,20622,30843,33147,31877,31865,31864,31875,38137,
+37570,31904,31542,30896,31541,34449,31540,37201,29403,20309,34026,18184,
+31630,42576,31629,31628,12776,41975,20621,31903,43374,33146,31108,31627,
+33356,33519,31045,33145,43156,38484,28456,28455,38443,43045,28454,28453,
+31152,30572,38414,42966,29040,29047,43204,38501,29676,29645,30895,36108,
+28768,23808,33518,23827,31710,42921,31727,29625,36586,36582,36581,36580,
+36579,36584,40740,29152,33928,31288,36607,29197,20336,33993,18262,31287,
+36606,29196,20335,33992,18261,31286,36605,29195,23570,33991,23569,31284,
+36603,29194,20334,33990,18260,37259,22029,43144,27970,32398,33816,32358,
+33967,32372,33144,32371,32472,32357,32356,32355,32375,32377,32470,33143,
+32469,32454,31940,32488,14328,32491,14344,32497,14301,32500,14308,39361,
+26101,32247,10545,39782,26792,32246,31751,14500,13025,32238,39552,32227,
+32323,32235,32231,32312,42580,32225,14040,42025,20652,32253,32263,42575,
+32262,32261,14104,41974,20620,32260,32259,32300,32243,41593,28452,30571,
+31099,41604,28451,30570,28450,30569,28449,41607,29090,41606,29089,30841,
+28727,31733,29666,31732,29665,31225,31499,31220,31266,30568,31496,30567,
+31263,30566,32131,30565,31105,30564,31091,30563,32122,30562,28448,42539,
+28447,37827,28446,32197,32191,32196,32190,31097,31096,31095,38514,20470,
+31258,31251,33142,31249,33223,31256,31255,31254,30650,30561,41572,26255,
+41586,29175,31260,32084,31062,28962,32185,25060,43143,27969,32154,32153,
+32152,32151,21506,32150,21505,37792,38136,43087,27905,42764,27245,41135,
+25798,38184,32179,32181,32177,32114,32083,31493,32129,32128,32127,41585,
+29248,31771,10157,39784,26794,31750,10149,39862,26902,39987,27145,31749,
+31778,13024,13096,31777,10166,39781,26791,33466,43424,35165,40725,33880,
+43390,32468,43373,32475,32374,33139,32354,31789,32018,31005,31004,31788,
+32017,31787,32016,31830,13286,31829,32048,32045,25059,31976,25310,31939,
+26251,31947,31983,31938,31937,32043,12475,31936,14107,31974,14074,31959,
+35141,31935,33974,31934,33760,31933,35190,31932,13023,32258,14103,31931,
+13022,31930,13021,32223,14038,32221,32257,32014,32013,31992,11595,31990,
+31988,31986,31985,31963,31929,37791,29943,21499,34974,18036,29942,34973,
+31928,18794,37790,20023,31927,37789,29941,20329,34972,18211,31926,31970,
+32047,31003,32903,32767,32894,32750,32590,32608,16656,32623,12282,11039,
+32630,32627,16680,32582,16581,32576,32615,32614,32573,32572,32570,32568,
+32651,32665,32650,33138,32656,33896,33137,32664,32655,33895,32654,33894,
+34023,32564,32563,33517,32562,41669,32828,32827,17502,17501,32745,32744,
+16798,16797,32825,17495,32917,17319,32824,32850,17318,32849,32783,17544,
+32797,17565,32561,32560,32658,32646,32926,32914,32913,32559,32558,32690,
+32795,17563,17381,32684,32777,17541,17317,32672,17200,32670,17194,32669,
+32741,16962,32740,32739,32738,32789,32923,32737,32736,32766,32755,10229,
+10284,10239,10165,10237,10159,10228,10148,10227,10147,10226,10283, 9863,
+ 9748,40145,10048,40165,10050,40167,32291,31050,30365,28953,30176,28952,
+28951,30343,30129,32290,32168,30364,30175,30174,30363,30199,30379, 9665,
+21011,36541,36756,35972,36365,20445, 9752, 9582, 9750, 9581, 9627, 9634,
+ 9580, 9579, 9578,11036, 9648,11282, 9577,11035, 9667,34545,34581,35202,
+33772, 9889, 9885, 9884, 9883,17877,17837,17713,17879,18133,17856,17712,
+18096,17858,18098,18135,17711, 9949, 9955, 9953, 9952, 9951,18129,18093,
+10037, 9640,23566,23565, 9646,23564,20220,33136,41616, 9694, 9697,23563,
+19433,33135,40607,23562,24496,33134,35221,24699,33133,24539,33132,24046,
+41177,10234,10296,10225,10282, 9726,21010, 9717, 9716, 9715, 9714, 9713,
+11524, 9728,17865,24209,33927,10733,10730,23561,19623,33131,40798,23560,
+24148,33130,33815,10024,21009,23559,20317,33129,41789,23694,20321,33330,
+41796,40707,35160,25330,18753,34859,10070,18483,13378,34808,10099,18426,
+13436,34909,10126,18555,13494,10794,10495,10784,10441,10782,10434,10796,
+10498,10799,10512,10801,10515,10281,10224,10280,10223,10290,10231,35069,
+34971,10279,26303,10278,10277,24228,33937,24125,24490,33767,35197,24673,
+13015,24513,13014,24030,41167,10777,10431,10306,10236,34976,10768,10408,
+10359,10183,10358,10182, 9797, 9796, 9795, 9799, 9794, 9793,10191,10196,
+10146,10145,34402,34382,34392,34391,34390,34389,17710,18023,26235,26237,
+26202,26204,18125,18089,18105,18118,17709,18100,18018,17708,18784,18778,
+17707,18012,18092,26221,26195,18091,18724,18111,37836,42470,21174,26829,
+37838,42472,21177,26832,37857,42495, 9576, 9575,21216,26848,11031,11030,
+36545,41564,20204,26213, 9574,11029,36549,41567,20210,26218,41566,26217,
+10511,10644,10497,10634,10420,10555,10514,10653,10508,10637,10403,34807,
+14078,18425,36535,41546,20191,26194,10473,10618,10430,10580,10480,10623,
+10491,10625,30183,10532,40102,10560,10582,10554,10579,32289,32272,10562,
+10590,10628,10770,10617,10776,10620,10632,10550,10549,10548,10655,10630,
+10616, 9860, 9852, 9851, 9854,10530,20618, 5566,20617, 9573,20885, 9712,
+20616, 4291, 4290, 4289, 4288, 4287, 4286, 4356, 4355, 4354,41343,41339,
+40665, 6669, 6709,20614,13010, 6821,20611,13007, 7470,22053,15419, 6720,
+21548,14238,30101,35158,15891,22422,29753,34700,13136,20737, 4549, 4518,
+29770,34717, 4565,29796,34743, 4572,29734,34681, 4535,41611,18173,41613,
+33786,35208,34535,18103, 4285,42625,32907,32906,32195,32189,32188,32194,
+ 4993,42313, 4949,42140,42312,20607,20879,42139,10304,20606,13058,42138,
+10729,20605,16109,42137,42448,42178,10276,42491,42136,42490, 4948,42489,
+10286,42409, 4954,42443,36593,42135, 4284,42134,10029,42133, 9940,20935,
+ 9939,23558,12616,42351,23557,20934,33126,42350, 9183, 4283,10121,18549,
+ 4282,40459, 4281, 4280,20604,42634,13003,42261, 4279,20603,13002, 5137,
+ 4978,20602,42260,13001,42633,42632,42259,20601,20600,13000,12999,18690,
+10349,20599,20598,12998,18689, 4278,20597,12997,18511,10110,20596,20595,
+12996,18510,40918,20594,12995,17923, 9765,40917,20593,40916,17922,40692,
+40691,40690,40689, 4320, 4322,40418,40417, 4306,40416,42585,42574, 4973,
+42252, 4972,42405,42201,20670,42404,42200,10316,20703,13104,42223,10315,
+42403,10097,18481,20592,20591,18478,12994,13134,20735,18415,18413,20734,
+10063, 4277,20590,12993, 4335,20733,13133,35135,30076,22307,15748, 4399,
+ 4401, 4276, 4275, 4274, 4273, 4272, 4271,29721,34668, 4515, 4304,40712,
+21466,14080,23748,22421,15890,40415,40514,41545,41544, 6668, 8194,33785,
+35207,34534,40424,21425,14006,23588,22306,15747,40423,40414,40413,21439,
+14026,23556,22334,15779, 4372, 4369, 4368, 4367,35151,30093,22413,15879,
+35150, 4709,42027,20654,31957,13047, 4743, 4692,42062,20878,31969,13057,
+32452,16107,32464,32480,32369,18743,24473,20658,26549,18117,24227,20589,
+26528,18017,24124,20588,26527,18783,24489,20587,26526,40412,10275,20877,
+12992,42311,41973,20586,31925,12991,30092,30275,29355,29432,30137,30296,
+29002,29008, 4318,17706,23555,20691,26570,40411,25557, 6570, 4334,29718,
+34665,12990,20585, 8185, 4333,34541,40410,21144,13573,23554,21321,13811,
+ 4337, 4332, 4331,17775,23649,20740,26589,18110,24208,20732,26586, 4339,
+17705,23553,20744,26593,10094,18475,20584,20583,18473,12989,13156,20767,
+18411,18408,20766,10060, 4269,20582,12988, 4346,20765,13155,23552,23551,
+20958,20950,18569,13299,10132,18561,20957,23550,18568,23549,10131,18560,
+23548,20949,23547,13298,10128,18557,20955,20947,18566,13296,23546,20967,
+13309, 4426, 4425,20966,23545,13308,23544, 4422,20964,13306,18123,20907,
+18736,26927,18735,20656,18116,20581,18016,20580,18782,20579,18072,27682,
+18077,20932,18075,26926,18074,20930,18070,20923, 7374,21967,15295, 6806,
+20578,12987, 7475,22058,15424, 7355,21955,15281, 6829,20897,13255, 7482,
+22065,15432,17704,26941,39072,22305,15746,25553,21424,14005, 4345, 4344,
+20764,39836,13154,39658, 4330, 4329,20731,26878,13132,26640, 5176, 5028,
+20763,39657,13153,39835, 4328, 4672,20730,26639,13131,26877,39834,39656,
+20762,20761,13152,13151,26876,26638,20729,20728,13130,13129, 4343,21375,
+13913, 4327,21249,13704,39129,20760,13150,25661,20727,13128, 4364,20803,
+13187, 4385,20846,13227, 4366,17904,26925,17903,20775,18109,20759, 4352,
+ 4363,17703,20773, 7224,21817,15106, 7278,21845,15151, 6793,20758,13149,
+ 7453,22033,15389, 4419, 4418,18063,20916,18723,20909, 4414, 4413,17702,
+20911, 7222,21815,15104, 7399,21987,15317, 7350,21950,15275, 4312, 4362,
+17701,20681, 7220,21813,15100,23543, 7430,22016,15356, 7436,22020,15361,
+ 7409,22000,15333, 7391,21981,15309, 9607, 9609,20868,26645,26883, 9571,
+21254, 9570, 9569, 9568,20862,26642,26881, 9605,21252, 9603, 9711, 9710,
+20845,26634,26872, 9709,21244, 9708,32149,17742,27675,18764,26633,17850,
+27739, 7293,27674,27803, 7219, 7264,27723,27722, 7263,17700,27691, 7218,
+27690,27673, 7233, 4397, 4384, 4387, 4383,10544,26524,14097,37564,10164,
+26523,13611,37563,37712,26522,26665,37562, 4854,37711, 4819,37561,10169,
+26582,13623,37610,37603,26564, 4833,37657,23542,26552,23747,26521,10144,
+26664,13559,37710,24179,26684, 4622,26520, 4642,26575, 4621, 4680,26519,
+26657, 4620, 4010, 4619, 4009, 4618, 4008, 4617, 4007, 4616, 4006, 4615,
+ 4005, 4614, 4004, 4613, 4003, 4612, 4002, 4651, 4042, 4650, 4041, 4649,
+ 4040,17699,42365, 4999,42364,42338,26673,42337,26672,17698,26694,10370,
+26693, 9943,26689, 9942,26688, 4611,26518, 4610,42500, 4609,37862, 4608,
+26517,42499,26516,37861,26515, 4984,42285,42284,26514,10357,26513, 4837,
+37681,37680,26512,10181,26511,40976,36197,36196,40975, 9792,26510, 4627,
+ 4019, 4677, 4066, 4629, 4023, 4679,26656, 9567,17697,26655,26157,26889,
+26152, 9850,17972,26509,25868,26789,25867, 5989, 4001, 5982, 4017, 9724,
+ 9832, 9821, 4068, 4021, 4025, 4000, 3999, 3998, 3997, 3996, 3995, 3994,
+ 3993, 3992,18079,18763,17849,17696, 5676, 3991, 5978, 4076, 9819, 4640,
+ 4639,26788,26573,26828,26827, 4655, 4607,26604,26847,26850,26787, 4653,
+ 4606,26845,26508,26844,26786, 4072, 4071, 4070, 9601, 9599,13239,13706,
+ 9566, 9565,13247,13710, 9707, 9706,13224,13694,32148,17740,27672,18762,
+26869,17848,27738,17695,27802,26341,38967,25052,26190,25051,26188,25050,
+12633,25049,12628,25048,26338,25047,12682,25046,26280,25045,12771,26095,
+26329,25111,12672,25228,25044,25043,25042,25041,25040,25039,25038,25037,
+25270,25269,25980,25979,25036,25035,25034,25033,25032,25295,25294,25293,
+25292,26167,26172,26166,26171,26165,26170,26164,26169,25309,25308,25307,
+26176,26181,26175,26180,26174,26179,25031,25030,25029,25028,25027,25026,
+25025,25024,25023,25022,25021,25020,25019,25018,25017,25016,25015,25014,
+25013,25012,25011,25010,25009,25008,25238,25236,25264,25266,25543,25542,
+25537,25539,26316,26327,26091,25226,26059,26061,26058,32176,38181,25804,
+25806,25802,25801,26108,20020,26093,20015,25242,19468,26336,20349,26335,
+20348,26334,20347,26332,20343,26323,20340,25391,25370,29835,25369,34970,
+26099,31094,32126,31253,35415,38473,36287,38148,36286,36285,25935,27057,
+25934,26098,25933,26374,25963,27671,27340,25960,25932,27255,27085,25931,
+25959,27050,26097,25967,26186,26184,33117,33965,33116,28439,29173,33964,
+29435,34082,33115,28438,33114,34081,26377,26419,25260,33911,33531,28780,
+28785,33537,33915,25007,25006,25005,33469,33960,29416,34045,33300,28622,
+33283,28616,29170,33957,33350,34056,26369,26402,25004,26005,25003,25341,
+29168,33955,34022,33954,26394,26357,28189,22298,28165,28167,33113,33899,
+33112,28437,29150,33898,28123,33901,33516,28767,28122,28121,25552,40394,
+25551,25550,28436,28435,28641,29402,29401,34021,26373,34969,26372,25248,
+19474,11313,19927,25892,12124,28434,28433,25826,25825,26224,25828,26930,
+26924,25830,25824,26967,41117,19947,12165,25389,26063,26083,27025,21441,
+27190,21629,27108,27071,27244,32175,38180,27074,27070,27069,27076,27059,
+21496,27027,27670,27047,34611,35085,27135,27056,34968,27055,38179,35414,
+38472,38147,38146,27084,27254,27083,27253,27052,27222,31101,36363,26296,
+26288,26271,26287,26283,20247,26285,26264,26290,26273,26294,26277,26293,
+26276,26292,26275,25344,28055,28057,27828,27726,27784,27403,27783,27402,
+27715,29840,27669,29881,29192,42830,42130,43047,27769,42402,37788,43086,
+42763,41134,27668,42752,41279,41836,28023,27667,27737,29834,27736,27904,
+27496,27903,27495,38178,32174,28432,28862,29400,29399,29247,27982,27966,
+27515,38471,32426,38145,32163,36284,31043,27984,36120,40793,28431,28430,
+29046,29039,27762,35413,38470,27243,27242,27068,28429,28880,29398,27126,
+27270,27100,26923,27010,27012,26951,26961,26969,26954,26922,26921,26920,
+26919,26918,42210,42129,30264,27000,42552,37919,29189,28991,30289,26917,
+42459,37899,26956,42401,37787,43142,26916,41838,27054,26915,26914,27261,
+27093,27122,27137,27139,27143,26929,27252,27082,26987,26986,26985,26984,
+26965,27045,42306,26262,26269,26268,25864,25862,19907,12099,25861,21133,
+13558,26232,25284,21158,13589,36233,41002,41001,36232,25459,25467,25466,
+25439,25438,25437,25463,25462,25478,25436,25435,25434,25433,25432,25431,
+25430,25429,25448,26797,26913,25450,25428,26630,26868,25427,25455,19572,
+11451,19575,25453,11454,25425,19564,11435,25422,25421,34547,36611,29498,
+31483,40783,36087,27782,27902,27499,27501,27494,27493,27401,27721,27720,
+27719,27519,27514,27513,27512,26737,26742,26739,26717,26716,26715,26714,
+26713,26735,26734,26733,36534,41543,26558,22395,26507,22420,26675,22296,
+26506,20726,26578,20695,26505,20577,20876,26654,30266,30082,29431,29354,
+30295,30136,29007,29001,26504,26785,26503,26784,26502,26783,26501,26782,
+26653,20576,26803,26818,26810,26781,26780,26779,26778,26777,26905,26776,
+26775,26774,26773,26772,26814,27666,26771,27735,27975,27749,28027,28044,
+28037,26796,26770,26831,21179,21176,13621,13619,26843,21132,13557,26822,
+26821,26820,25684,19793,25679,19791,25660,19781,25659,26261,25658,32147,
+25657,26231,25656,25655,25654,27734,25653,25682,27665,27767,25704,27766,
+27664,25703,25707,25652,27718,20178,20182,19439,11301,19435,11297,19999,
+12305,20245,12674,20249,12676,20253,12680,20252,12679,20251,12678,26247,
+21597,21596,21595,21594,30157,35219,33813,29037,29457,34543,40385,40384,
+40383,40625,19655,20477,20475,42960,43367,42673,42571,42959,43366,19653,
+28426,33105,28425,33104,19651,28424,33103,41111,41110,41108,31886,28423,
+28422,28421,28420,19639,11546,19644,11548,19622,19115,41179,41153,19536,
+11398,21323,21148,37369,37702,31765,21152,21314,21131,37377,37709,31776,
+21130,32245,21129,21313,21128,21312,21127,21311,21126,21401,21305,37295,
+37560,31748,21304,21374,13912,20757,20756,13148,21373,21241,13693,20725,
+20724,13127,21240,21372,13911,21371,19612,11504,28419,40382,40381,19823,
+11892,39128,20755,39127,19822,19780,11781,25651,20723,25650,19779,19821,
+11891,19820,19819,11890,11889,19818,41089,41088,19437,11299,19540,11402,
+19531,11393,20034,12310,20037,12329,15739,22295,20036,12328,20290,12758,
+20300,12769,20299,12768,20298,12767,32458,40797,41132,40630,41662,41707,
+41690,41785,41661,41774,41660,41773,41700,41699,41795,41684,41688,41659,
+41727,41811,41725,41657,28418,28417,20229,12982,20228,20575,20225,12655,
+20222,12653,28416,26302,42400,37786,22294,15738,22293,15737,22292,15736,
+22291,15735,22290,15734,22289,15733,22288,15732,22287,15731,34719,29772,
+35227,30162,29728,34675,35140,30081,34689,29742,35134,30075,29774,34721,
+35133,30074,35253,30198,35132,30073,28931,33671,35130,30071,22286,35177,
+22285,22284,22353,22283,31910,29115,29113,31879,28415,28414,22438,15899,
+22282,15730,22746,21563,37294,37559,31747,21562,22748,16285,22750,16288,
+22415,15884,22281,15729,22280,15728,22392,15849,22463,15930,34658,29711,
+35157,30100,29710,34657,35156,30099,22419,15889,31863,29036,29035,22651,
+16133,22653,16140,22658,16151,19922,19920,19906,40380,19905,19904,41087,
+41116,19968,12203,19966,12201,19946,12164,19945,12163,38940,25109,21310,
+21125,20232,12661,20234,12663,20240,12667,20239,12666,20238,12665,20242,
+12669,20305,12687,20304,12686,20303,12685,20307,12689,20176,12631,20175,
+12630,20180,12635,32140,31127,32139,31126,32138,31125,32137,31124,20351,
+20346,31463,31462,31456,31448,31447,31446,31445,31862,32146,31924,41972,
+21504,21503,21578,21577,21576,21575,27661,21437,21457,21455,32173,21534,
+21532,21530,27660,41713,41802,42860,42754,41724,41810,21525,14160,21523,
+14158,21518,14134,21517,14133,21542,14214,22955,23406,23405,23404,23403,
+22986,21686,14735,21651,14505,41289,41281,42958,43365,40371,40370,43076,
+43441,21638,14457,21657,14512,21674,14605,21672,14603,21667,14579,21666,
+14578,19579,11459,19601,11477,25419,25417,19561,35438,30308,41723,41809,
+27202,27033,21034,27713,21008,27733,25368,21007,27659,21075,22411,15877,
+34878,29879,41558,41577,40612,40614,41693,41787,22278,15727,34907,29889,
+26560,26816,22277,15726,26551,26812,22394,15852,22364,15806,34804,29833,
+26500,26769,22363,15805,21481,20207,22481,20203,20213,20206,20202,26499,
+26768,20201,20270,12650,20269,41342,41338,41337,41341,40664,40663,41562,
+41581,20573,12980,29751,34698,34655,29708,34696,29749,34653,29706,41610,
+20570,20569,34533,35206,33784,20568,18102,20567,12979,42624,42623,23537,
+23536,20566,12978,20565,12977,41086,41085,36592,12658,20564,41808,41374,
+41353,41373,41352,41372,41351,41371,40369,40368,40367,40366,40365,40364,
+42597,42570,42569,42627,20664,13056,20563,12976,20800,13184,20754,20753,
+13147,20799,20842,13223,20722,20721,13126,20841,20798,13183,20797,20650,
+13049,20562,12975,20561,12974,20560,12973,20559,12972,41979,31961,42023,
+42061,41971,31968,41970,32451,41969,40363,20875,13250,31923,42060,26496,
+26767,21448,14037,20720,13125,20719,13124,25860,25859,20718,20717,25966,
+25556,20796,13182,20927,13282,20929,13284,20809,13192,20795,13181,20866,
+13243,20840,13222,20852,13232,20839,13221,21150,21156,21136,21124,21123,
+21122,21121,21120,21278,27658,21119,25367,27732,21118,28025,21138,21117,
+13556,21116,13555,21115,13554,21114,13553,21263,21262,21261,25415,25413,
+12352,14223,12821,14281,12823,14284,11140,14523,11132,16013,16393,16380,
+14985,14869,16399,16386,15015,14892,11966,11104,10996,14459,11321,11539,
+11466,10995,11332,11472,11534,10994,11346,16643,10993,16653,11530,11520,
+11433,12281,12285,11348,11345,40140,39228,11990,14113,11989,15240,11988,
+21492,20011,21491,20010,21490,20009,21489,20008,21488,20007,21512,20042,
+34803,29832,23535,23699,24207,21511,20041,33102,11672,22276,35218,11555,
+11551,41176,11366,35137,40362,33101,40361,40523,41542,21487,21370,35188,
+33950,13910,33100,40360,40499,41541,21486,20006,35187,33949,11888,43364,
+33099,43363,12766,42568,18668,12657,36591,33098,32353,11080,12046,12039,
+12010,12036,12014,11189,11191,37683,42287,11099,11101,37864,42502,11089,
+11091,11066,11068,11117,36201,40984,12614,42348,27657,22275,42347,37744,
+12613,12600,42346,37743,12538,12537,33097,13266,23526,27656,22272,12536,
+12510,15773,14398,15722,33962,15721,26417,15720,26663,40355,15797,15719,
+15718,33946,33830,33433,15717,15716,15715,26691,16233,33096,33095,15713,
+33094,37344,33868,37388,33875,20474,32309,33833,33437,33837,17996,33093,
+33092,15709,15706,15921,40354,33812,23525,20040,15834,32487,32496,32776,
+40353,40352,33091,33811,33810,33809,37293,33808,33807,33806,33805,32299,
+32474,32388,33090,32352,17684,23524,27756,22461,27655,22255,17843,23772,
+17841,23746,27728,22418,26585,20716,15700,15099,15888,26495,26494,20558,
+27029,21447,27036,21462,16104,14669,17900,16103,12971,40351,31922,32450,
+25572,19660,17683,23523,26493,20557,16102,15274,26492,20556,12088,12087,
+12086,41166,23522,12131,12085,42128,12084,40627,35975,37785,42399,12082,
+12113,12079,12078,12077,12076,42498,37860,12075,12074,42283,37679,12073,
+12072,40974,36195,12071,12123,41772,41771,41770,41769,41782,36891,41799,
+36967,41768,36859,41807,12968,41806,36986,41805,36985,41767,36858,41766,
+12517,12514,37751,12606,37749,12604,11378,42546,37906,11431,11430,11429,
+11446,11450,11428,11427,11426,21537,12242,20215,20189,20274,21113,20200,
+20268,20272,22254,20265,20555,20264,20794,20263,20262,21369,20261,20260,
+22253,20257,20715,20267,24168,23521,41348,40350,24206,41540,22356,21036,
+22362,21005,21070,22252,21510,21004,21146,22251,21140,22330,21435,21317,
+13366,18487,13365,15909,18447,15816,21112,22361,15804,18405,15803,13364,
+14077,13363,13435,13809,13572,15699,13492,18554,15698,36471,36498,36547,
+15137,14053,16177,14484,40139,39954,15239,14112,15238,14111,15697,15887,
+15864,40711,21465,20752,15098,20937,15326,36469,20468,15273,14182,20554,
+15272,16100,14326,14299,15021,14896,15013,14890,14961,14960,14959,14958,
+14853,14768,14231,14499,14426,14030,14767,14665,14705,14195,14692,14187,
+14663,14180,14730,14577,14729,14132,14728,12159,14727,14726,43440,43362,
+18059,34607,17682,34605,18720,34602,34903,14772,14786,14269,15355,14267,
+14784,16269,15351,16265,14868,14852,14851,14850,14849,14957,14889,25722,
+33651,14576,14575,14574,26973,14573,35051,14572,26612,14571,34867,14570,
+14569,14096,13552,23520,14062,23519,39795,23518,21316,22250,39531,20793,
+14004,39655,14003,21368,14002,39833,14001,14000,13999,39126,19817,40119,
+40138,14280,14283,14228,20553,21485,20792,21484,14237,33758,33757,39753,
+14240,39752,33089,14247,34800,14246,33088,21111,21451,14222,14207,26584,
+15097,16099,14131,25721,33650,14130,14129,14128,26972,14127,35050,14126,
+26611,14125,34866,14124,14123,14052,12157,12155,12153,12182,12152,12151,
+12150,26971,12149,35049,12148,26610,12147,34865,33649,25720,13454,12146,
+16900,17343,16912,17380,16619,16568,23517,16689,16566,24234,16564,22248,
+16724,24188,16723,33085,16729,33890,33084,24187,23516,33889,16728,33888,
+34012,16559,23826,33515,41648,16558,17067,17181,16557,26220,18087,16720,
+16810,16773,16772,20552,17681,16771,16556,18719,16956,16955,17537,17300,
+17536,17299,17535,17534,17297,17295,17293,17292,17291,17290,17533,17388,
+17377,12965,12964,13095,12963,41609,18172,34532,35205,33783,15477,15532,
+17101,12962,32905,32193,32187,16767,12961,13055,41347,13067,12960,18502,
+12959,12958,18545,12957,17199,14073,18441,14048,32032,31967,31921,21110,
+21446,14036,18404,14035,17680,23511,18740,24471,13163,13660,26601,20777,
+18115,24226,18015,24123,18781,24488,12956,13551,26652,20874,40347,13054,
+13588,26487,20551,40346,40512,41539,33756,35186,33948,13180,19648,25562,
+20465,26438,30161,30303,21450,27031,29353,29430,30135,30294,29000,29006,
+21461,27035,36984,41804,12955,13550,37747,42357,12954,13549,40345,25560,
+26486,13123,33952,13122,13121,25965,25559,15460,15514,17055,17772,23647,
+17679,23510,18108,24205,18121,17678,18738,18114,18014,18780,12953,26651,
+18061,18085,17677,18083,18718,18081,15279,16126,15095,15694,17676,17906,
+18107,15149,15902,13263,15344,16259,15353,16267,15187,15955,15289,16156,
+15127,15790,15093,15692,13548,13610,13596,23508,22329,23745,22417,15809,
+34823,15691,34863,22242,24181,15690,15886,20714,13547,40796,35139,33827,
+33803,15828,15687,41794,13546,42222,13545,13544,13587,16239,34799,16238,
+33082,13543,13578,42408,37794,37816,42445,13657,42127,13656,13655,13654,
+42398,37782,13764,42369,17675,42368,13763,42367,13761,17674,13760,15683,
+13728,13727,13542,13541,13540,42497,13539,37859,13538,42282,13537,13536,
+37678,13535,40973,36194,13534,15680,14206,14568,14122,13667,13586,20550,
+13585,11809,11819,11779,11817,12121,11775,11797, 9551,34857,33081,33079,
+ 1870,10340, 1763,21210, 1607,32011, 1803,35041,30536,30534,19291,31901,
+17673,29870,28404,28402, 1820,37989, 1577,29932, 1748,18661, 1887,13864,
+35765,35763,10964,37629, 9549,34854,33077,33074, 1867,10337, 1760,21207,
+ 1604,32008, 1800,35038,30532,30529,19289,31898,17671,29867,28400,28397,
+ 1817,37986, 1574,29929, 1745,18658, 1884,13861,35761,35758,10962,37626,
+ 9546,33071,33068,33066,19054,18717,14385,19286,38275,38056,30331,33064,
+30526,30524,19282,30522,17667,28391,28388,28386,32215,35749,35477,35586,
+10674,17664,21625,22234,35746,35744,10957,35742, 9542,33055,33053,33050,
+19051,18714,14382,19279,38272,38053,30328,33047,30516,30513,19277,30510,
+17661,28384,28382,28379,32212,35739,35474,35583,10671,17657,21622,22231,
+35737,35734,10955,35731,17797,34167,33045,33043,36731,34323,33345,31399,
+18340,31381,19447,34342,35958,30508,19267,31584,17649,29534,33325,28371,
+17808,36906,20409,29311,35939,29295,34185,36925,35717,35715,19461,36750,
+17796,34166,33029,33027,36730,34322,33344,31398,18339,31380,19446,34341,
+35957,30500,19259,31583,17641,29533,33324,28368,17807,36905,20408,29310,
+35938,29294,34184,36924,35713,35711,19460,36749,43358,33025,33022,33020,
+ 7205,40213, 6413,24632, 7559,39912, 6227,33018,42727,30498,27180,30496,
+24775,28366,40212,28363, 7556,35709, 6226,43355, 7202,27333, 6412,42724,
+35706,35704,39911,35702,43361,33015,33058,33061, 7208,40209, 6409,24630,
+ 7562,39908, 6223,33013,42730,30519,27183,30493,24778,28361,40216,28394,
+ 7555,35699, 6230,43354, 7201,27332, 6416,42723,35755,35752,39915,35697,
+17638,10331,34848,35032,30491, 1811,33011, 1568, 9531, 1739,19256, 1878,
+35695,32002,21053,21201,18613,18652,33008,29923,17635, 1861,10944, 1754,
+35692, 1598,28359, 1794,37620,37980,19253,13855,17632,34202,33647,33633,
+36770,34359,33005,31436,18359,31419,19250,34375,35689,30992,19768,31615,
+17920,29549,33004,28918,17631,36945,20439,29346,35688,29330,34219,36962,
+36230,36193,19249,36789,17630,33377,33646,33632,36229,33003,30991,17919,
+30769,19248,35687,19767,28655,28917,35994,36192,17889,10746,35613,35557,
+30927, 8803,33565, 5749, 9746, 8073,19628, 8560,36125,32295,22558,21685,
+18903,19091,33570,30376,17895, 8844,11544, 6969,36132, 6014,28802, 8448,
+38196,38333,19633,14689,17888,10745,35612,35556,30926, 8802,33564, 5748,
+ 9745, 8072,19627, 8559,36124,32294,22557,21684,18902,19090,33569,30375,
+17894, 8843,11543, 6968,36131, 6013,28801, 8447,38195,38332,19632,14688,
+17887,17628,35611,35555,30925,30488,33563,33001, 9744, 9528,19626,19246,
+36123,35685,22556,21683,18901,19089,33568,32999,17893,17626,11542,10941,
+36130,35683,28800,28356,38194,38331,19631,19244,39563,10143,34967,34798,
+30660,42077,33233,26992,33856,42320,31186,31181,39684,31861,24419,21003,
+26998,18587,42331,29831,29068,29085,36449,39689,35890,24423,28540,39559,
+37950,37553,42072,13360,33862,18638,33197,33201,35065,37723,32038,34797,
+31175,18619,33846,21002,30630,37949,31192,19345,29074,17746,28509,34966,
+36467,18586,29079,21066,29936,37552,38021,34889,35855,35859,36462,21109,
+33210,18637,33451,33444,35020,37608,31979,34796,30643,18604,33205,21001,
+30835,37948,30639,19516,28522,17835,28711,34965,35868,18585,28517,21046,
+29911,37551,37970,34832,36049,36060,35864,21108,18010,35175,33221,33215,
+31081,18584,33736,21859,37947,37550,29904,35353,36327,30648,19351,32120,
+17752,30423,33747,28527,31920,38450,34964,34795,36337,18946,28984,21000,
+35874,35879,19988,38641,17823,18358,28697,29563,30809,31435,33401,34358,
+38685,38468,31614,31418,36017,36769,11343,12750, 9663,10013,33421,34218,
+32162,32425,36788,36944,36033,36961,28685,29329,30799,31601,19492,20438,
+17822,18357,28696,29562,30808,31434,33400,34357,38467,38684,31613,31417,
+36016,36768,11342,12749, 9662,10012,33420,34217,32424,32161,36787,36943,
+36032,36960,28684,29328,30798,31600,19491,20437,17821,18356,33685,33684,
+30807,31433,33399,34356,36258,36257,31612,31416,36015,36767,19976,19975,
+17962,17961,33419,34216,31042,31041,36786,36942,36031,36959,28683,29327,
+36265,36264,19490,20436,10003,34321,34165,34340,17795,32160,11309,35238,
+35956,35937,28636,34183,31582,38466,20424,31397,18329,29293,29532,35383,
+30747,36729,33323,33343, 9657,38683,19459,30427,36748,36904,12740,36923,
+10002,34320,34164,34339,17794,32423,11308,35382,35955,35936,28635,34182,
+31581,38682,20423,31396,18328,29292,29531,35237,30746,36728,33322,33342,
+ 9656,38465,19458,30305,36747,36903,12739,36922,33683,34319,34163,34338,
+17793,31040,19974,33715,35954,35935,33682,34181,31580,36256,31048,31395,
+28956,29291,29530,33714,36263,36727,33321,33341,17960,36255,19457,28928,
+36746,36902,36262,36921,43340,17624,32997,32995, 7188,40208, 6408,32993,
+ 7542,39907, 6222,24772,42710,35681,27167,19242,24766,17621,40196,32990,
+ 7554,27177, 6210,43353, 7200,35678, 6396,42722,35675,35673,39895,19240,
+34525,23507,32987, 7309,32975, 7308,24977,23337,17054,17288,23183,40340,
+24975,23336,17053,17287,23182,40338,40336,23181,17052,24973,23335,17286,
+38810,32821,40605,39392,25222,38772,40603,39389,25224,32726,38771,32725,
+40601,40599,23180,39383,17051,39386,25220,25218,23334,24199,17285,24192,
+25279,25281,38770,38769,38961,32820,32724,32723,38959,38809,40652,40654,
+38955,38957,41224,17050,25995,23333,41226,23179,25993,17284,23681,23679,
+32973,39048,40641,13960,23505,13952,23503,13969,23500,23498,39722,23496,
+39746,23493,39745,40067,31682,40070,31685,40072,31687,40066,31681,40065,
+31680,40055,31673,39721, 9923,39744, 9934,39743, 9933,16510,32971, 2826,
+28343, 2824,40334,40332,40331,40329,40327,40325,40323,40321, 6294,22565,
+16042, 6271,22626,16092, 4266,22625,16091,10919,19223, 6624,10911,24964,
+ 7087,19217,24960, 5724, 2709, 3037, 3181, 4265,22622,16089, 4298,22620,
+16087, 7349,21949,15271, 7347,21947,15269, 7345,21945,15267, 3206, 5752,
+10899,17800,34171,33121,33125,36735,34327,33348,31403,18344,31385,19450,
+34346,35961,30552,19305,31588,17694,29538,33328,28443,17811,36910,20413,
+29315,35942,29299,34189,36929,35807,35803,19464,36754,17799,34170,33120,
+33124,36734,34326,33347,31402,18343,31384,19449,34345,35960,30551,19304,
+31587,17693,29537,33327,28442,17810,36909,20412,29314,35941,29298,34188,
+36928,35806,35802,19463,36753,18636,34169,33119,33123,36733,34325,34794,
+31401,18342,31383,20999,34344,37946,30550,19303,31586,17692,29536,34963,
+28441,18583,36908,20411,29313,37549,29297,34187,36927,35805,35801,21107,
+36752,34520,23692,17727,34206,33644,33630,36773,34362,33170,31439,18362,
+31423,19328,34379,35834,30989,19765,31619,17917,29553,33166,28915,17723,
+36949,20442,29350,35830,29333,34222,36965,36227,36190,19324,36793,17726,
+34205,33423,33403,37945,34793,33169,31860,18635,31422,19327,34378,35833,
+30811,19494,31618,17825,29552,33165,28687,17722,36948,21106,29349,35829,
+29830,34962,37548,36019,36035,19323,36792,17725,34204,34961,34792,36772,
+34361,33168,31438,18361,31421,19326,34377,35832,31859,21105,31617,18634,
+29551,33164,29829,17721,36947,20441,29348,35828,29332,34221,36964,37944,
+37547,19322,36791,17719,33381,33643,33629,36226,33162,30988,17916,30773,
+19320,35826,19764,28659,28914,35998,36189,17718,33380,33494,33506,37943,
+34791,33161,31858,18633,30772,19319,33379,35825,30915,19588,30771,17875,
+28658,33160,28758,17717,35997,21104,28657,35824,29828,34960,37546,36106,
+36096,19318,35996,34201,17619,33398,33418,34790,37942,31857,32969,31415,
+18632,34374,19209,30806,35662,31611,19489,29548,17820,28682,32964,36941,
+17615,29345,21103,29827,35647,37538,34959,36030,36014,36785,19204,38965,
+38827,38964,38402,38963,38394,30483,30481,30479,30197,30173,30172,37558,
+37533,33232,26991,33855,42319,26997,31853,42071,34785,30663,10141,42330,
+20996,31185,37937,30659,42076,28539,39558,29067,34954,39683,18580,28536,
+13358,39562,37532,24418,29823,36448,39688,35889,24422,37708,37640,36827,
+41765,29940,37091,37531,38132,37530,29954,29939,29952,29938,18047,17687,
+18179,17690,37648,36442,36300,26727,26710,26725,26709,36053,36296,36454,
+ 8812, 5812, 8435, 8792, 4905,43814,43311,43002,43286,42582,42845,42928,
+42841,17738,17994,17736,17882,37784,37852,36298,36308,42834,26708,42866,
+42924,42836,41896, 4061, 5984, 5996, 3392, 6655, 3665, 5991, 2355,11822,
+11824,12297,12293,41271,41244, 9823, 9825,28555,30678,23629,25170,28972,
+31072,24113,26051,28716,30818,23740,25326,28544,30669,23602,25142, 9678,
+ 9673,12176,11804, 6292,22567,16044,14145,14590, 2539, 5657,14143,14588,
+14164,14610, 2549, 5675, 1621, 5475, 1922, 5500, 3097, 5374, 5384, 3103,
+ 1927, 5218, 5216, 1912, 5230, 1907, 5228, 1909, 1924, 5240, 1920, 5242,
+ 5251, 1915,16600,16633,10970,11111,10966,11285,11116,12195,12208,11050,
+24332,28819,28826,30947,37995,11048,37653,24461,38605,24787,38432,11046,
+28807,30934,11044,43887,43853,43884,43850,43879,43845,43876,43842,14147,
+14592,11113,12199,17610,19104,17607,19103,35640,28333, 8578, 8135, 4818,
+ 4785, 8230, 8669, 8667, 8228, 8584, 8161, 8176, 8596, 8576, 8133, 6923,
+ 6164,36294, 8790,36293, 6921, 6162, 6901, 6157, 4816, 4783, 8178, 8598,
+ 6925, 6166, 8586, 8163, 6903, 6159,24751,12788,39418,38649,38634,36069,
+38630,37529,39997,39585,40148,40037,40013,40113,39995,39678,40109,39587,
+39677,39544,39583,40111,39582,38677,35816,35815,38676,38692,38648,32845,
+30554,32330,30665,31742,31199,32322,32317,10868,10865,28325,28322,28318,
+28315,18253,11572,11569,37502,37165,35655,35652,35793,36302,36292,18631,
+34162,32968,32963,36726,34318,34789,31394,18338,31379,20998,34337,37941,
+30485,19208,31579,17614,29529,34958,28341,18582,36901,20407,29309,37537,
+29290,34180,36920,35646,35661,21102,36745,18630,18355,32967,32962,31856,
+31432,34788,34355,34200,34373,31610,31414,37940,36766,19207,19203,17613,
+17618,34957,34215,29547,29344,36784,36940,37536,36958,29826,29326,35645,
+35660,21101,20435,18629,17873,32966,32961,31855,30913,34787,33504,33376,
+33375,30768,30767,37939,36104,19206,19202,17612,17617,34956,33492,28654,
+28653,35993,35992,37535,36094,29825,28756,35644,35659,21100,19586,35799,
+ 9353, 9466, 9351, 8511, 8467, 9356, 9355,38382,28878,28873,28860,28855,
+36282,36277,35797,18255,27821, 2597,18244,18243, 2456, 2596,18258,20185,
+18251,18250,18248, 2639,37181,37178,37131,37164,37190,37163,37162,37161,
+ 2628, 2484,37160,37130,37159,37189,37158,37107,35671,28353,30196,28348,
+30171,28352,28351,30211,28330,32980,32985,32978,32983,28346,28350,28329,
+32887,32733,36647,36641,39425,39436,39434,17467,17466,17465,11252,11231,
+11249,11228,28577,30701,28571,30695,17464,36512,36527,32681,33885, 2803,
+29143, 2801,33883, 2815,29141, 2814,17283,36510,23099, 8940,16953, 8939,
+24190,24197,17374,36514,23332, 9222,17282, 9221,24186,24195,16899,36509,
+17342,36508,16716,36507,23331, 9220,17281, 9219,23513,23515,16898,35774,
+16770,35773,35812,32912, 9413, 9412,38826,38825,32843,32842,36520,32749,
+36525,32722,36524,32765, 9315, 9314,38768,38767,32721,32720,36523,32902,
+36522,32643,11922,11919,17550,32854,17500,32826,17196,32891,17326,32918,
+14566,13036,13033,13045, 9827,20640,20632, 5980,21627, 6232,20630, 4294,
+28502,30618, 3072, 3390, 3308, 3501, 3294, 3479, 3296, 3485, 3291, 3474,
+24393,42188,24390,42185,10400,38621,10397,38618,38600,37957,38597,37954,
+ 3369, 3053, 2347, 2474, 2341, 2468, 3497, 3306, 3387, 3070, 3372, 3056,
+ 3462, 3288, 3460, 3286, 3367, 3051, 6898, 5577, 6896, 5575, 6912, 5608,
+ 3262,38172,27114, 3033,38221,27106, 3031, 2490,38144,27081, 2488, 9523,
+38143,27080, 9895, 3361, 3413, 3411, 2340, 2338,19193,20045, 3436,16188,
+ 7760,16186,16190,16166, 7755,27548, 7979,27546, 7977,27554, 7985,27371,
+ 7905,27369, 7903,10218,34894,29094,29104,23572,40849,33705,33700, 5477,
+ 3365, 5504, 2343, 5409, 3495, 5442, 3385, 5436, 3375, 5376, 3454, 5430,
+ 3363, 5327, 2345, 5283, 2367,32622,30556,30756,31026,32607,30558,30783,
+30872,30884, 6085, 1558, 5512, 1532, 5502, 1551, 6098, 1541,16642,32605,
+32620,16677,16631,16675,14167,14613,10974,10972, 5387, 3106,12007,12006,
+19884,19883,27888,27479,25821,25820,22532,21907,15995,15226,13355,13354,
+20992,20991,27887,27478,16175,22682, 3640,22681, 3639,28006, 3745,36150,
+14722,16168,31028,14779,14262, 5486, 3092,14788,14271, 5514, 2300,14739,
+14218, 5444, 3337, 3130, 5407,14202,14718, 3108, 5389,14190,14695, 3105,
+ 5386,14188,14693,14733,14211, 5433, 3328, 3090, 5367,14184,14674, 2302,
+ 5285,14115,14519, 2320, 5325,14137,14582,10976,10978, 2315, 5308,14118,
+14556,12287,16679,12187,12185,12167,12213,12211,12145,12210,12220,12171,
+12005,19882,25918,25819,19938,12144,13353,20990,25795,12218,12143,11787,
+16647,11802,11800,11791,11789,12169,12012,11287,12142,12004,11785,11783,
+32625,32624,16645,11772,16644,11535,11333,11771,11770,11769,11768,37781,
+39432,42704,17745,19044,28513,30325,30629,32526,33196,35580,33861,33845,
+31191,31174,35858,38269,11123,14378, 9612,10668,33200,35471,29073,29078,
+36461,36466,35854,38050,28508,30067,30634,32209,19344,21619,17744,37488,
+28512,29885,30628,32037,33195,35064,33860,33844,31190,37929,35857,37722,
+11122,29816, 9611,31846,33199,34888,29072,34947,36460,36465,35853,38020,
+28507,29935,30633,31908,19343,34770,42124,18618,28511,29884,30627,39579,
+33194,35063,33859,39542,31189,31173,41965,37721,26764,13467,24372,10194,
+39541,34887,29071,29077,36459,41964,35852,38019,28506,42123,30632,31907,
+39578,21065,35579,33450,33204,33209,10667, 9684,21618,19515,32208,30827,
+35470,33443,30642,30638,32525,30834,30066,28710,28516,28521,38268,36059,
+30324,28721,19043,17834,14377,11391,35867,35863,38049,36048,35019,33449,
+33203,33208,31845, 9683,34769,19514,31883,30826,34831,33442,37928,30637,
+31978,30833,29910,28709,34946,28520,37607,36058,29852,28720,37487,17833,
+29815,11390,35866,35862,37969,36047,35018,33448,39540,33207,10162,24371,
+21045,39577,31882,30825,34830,39539,30641,30636,39576,30832,42122,28708,
+28515,28519,37606,41963,29851,28719,18603,42121,13429,26763,41962,35861,
+37968,36046,18009,35174,33220,33214,31080,10542,33735,21858, 9872,32383,
+19996,35352,36326,30647,19350,32119,17751,30422,33746,28526,18003,38449,
+12303,30287,36336,18945,28983,15177,35873,35878,19987,38640,18008,35578,
+33219,33213,31079,10666,33734,21857, 9871,32382,19995,35469,36325,30646,
+19349,32524,17750,30421,33745,28525,18002,38448,12302,30323,36335,19042,
+28982,15176,35872,35877,19986,38639,18007,35173,33218,39538,31078,10541,
+39575,21856,24379,32381,39537,35351,36324,30645,19348,39574,17749,42120,
+33744,28524,41961,38447,26910,30286,42119,18944,28981,15175,35871,41960,
+19985,38638,18006,35172,33217,33212,31077,31844,33733,34768, 9870,32380,
+19994,35350,36323,37927,19347,32118,17748,30420,33743,34945,18001,38446,
+12301,30285,36334,37486,28980,29814,35870,35876,19984,38637,35881,43188,
+19019,43115,19000,43043,18937,42904,19125,40860,41464,40864,41531,40856,
+41497,27449,27858,26485,26484,18893,35399,18905,18871,36637, 8640,43490,
+ 8638, 8636, 8632,43488, 8630,27913, 6309,27643, 6199,27650, 6201,27648,
+27317,15071,21781,27319,36291,30114,30113,18035,18034,18843,27630, 6194,
+27198,26411,27628,27627,27626,17953,18752,18873,18877, 6850,14325,14323,
+13562,27200,27195,26544,26498,35410,18842,18840, 7945, 4605,36290,29959,
+29958,18839,26754,26753,18838,30779,28661,28542,28311,32951,38593,37485,
+26198,38808,32719,26208,26206,26210,28413,12590,18544,11602,18501,10103,
+18493,11601,18500, 7875, 7873,27185,26532,26483,27409,27411,26491,27792,
+26530,26719,26489,26712,12815,27808,26482,27790,27795,27794,26070,27380,
+30341,10472,28732,29134,29567,29569,30349,30351,29019,29021,27745,26481,
+26480,25346,25339,25355,38807,32718,26068,26073,25349,25351,25348, 2714,
+26479,25856,26478,25855,26477,25854,26067,26078,32125,19191,26065,26076,
+26476,26475,26072,26080,26131,26136,32145,10040,37484,37483, 4063, 5977,
+22224,15675,18722,38647,38592,36537,38591,26410,26474,26473,26416,26683,
+27293,27228,26245,26662,35635,28328,28327,43141, 8634, 3698, 3417,43138,
+ 8621, 3713, 3441, 4213, 6544, 4218, 6524,40309,21826,15119,24933,20136,
+12548,31819,24935,29131,37427,37426,37408,38126,37407,24931,24929,17280,
+35772,17341,35771, 8954, 8953, 8972, 8971,32782,38780,32780, 9335,38778,
+ 9333,35811,32911,35810,32910,35809,32909, 9436, 9435, 9450, 9449, 8407,
+ 8256,38629, 8415, 8264, 8255, 8406, 8263, 8414,35185,30123,35217,30156,
+35214,30153,35789,40137,14174,32950,32949,32948,32953,35923,39167,35925,
+38697,30195,42782,38646,27407,27788,27787, 8189,35791,12362,12359,11671,
+11668, 8208,38343, 8206,38341, 8147,38291, 8145,38289, 8143,38287,10851,
+27142,10850,27121,10849,27044, 6334, 1523,11177,11175,15347,23665,25199,
+23667,25201,41325,41317,41322,41314,12358,23576,40851,37545,38125,37544,
+37543,37541,41764,40304,28309,28308,28307,43105,18991,28306,28304,28884,
+35642,42567,41159, 9349,33613, 2854,28895, 2849,33611, 2852,28893, 2847,
+13527,26472,11550,36307, 9348,13526,18492,33879,41480,33867,41510,41496,
+41445,41530,41535,43810,43282,43307,37913,41501,41463,13758,43028,41495,
+43007,41529,12582,18534,26682,12589,18543,33877,41478,33870,41514, 4208,
+ 6553, 4263,22580,16060,11642,19693, 6603,11623,25597, 7060,19674,25585,
+ 5684, 2676, 3005, 3140, 4055, 5988, 4207, 6550,20547, 5987,19189,20546,
+ 9831,13525,20545, 9723,40302,40300,40298,38633,31123,25354,25357,40313,
+40315,40312,40311,19187, 2935, 2932, 2975, 2972, 2931, 2389, 2392, 2388,
+38391,12812,38367,38390,38360,10845,23489, 9521,23488,23541,23486,10861,
+35182,30120,10858,12326,35220,30158,12323, 3320, 3318, 3083, 2317,41305,
+27826,27824,27810,30339,28303,30476,21529,28302,30475,21527,28301,30474,
+35418,30472,24979,41370,28299,40542,28298,40374,28297,41301,28504,41303,
+28296,40378,28295,40389, 9517,22223, 9515,22222,28294,30471,15673,28293,
+30470,26087,23485,26085,23484,26089,23634,26143,23482,28291,30468,35840,
+25163,24068,33717,30467,33713,31149,36306,36274,36305,33668,36280,36279,
+33666,41175,33726,30753, 8805, 9754,35271,35600,11567,11566, 8646,35602,
+11561, 8644,40541,43812,40373,43309,40377,40376,43284,40388, 5853,40387,
+35409,30466, 8193,35407,30465, 8192,35381,30464, 8184,35379,30463,35570,
+30461,43352,28290,30460,27624,28289,30459,28287,30457,39372,30625,39369,
+30622,38899,31715,39351,30456,39349,30978,39353,31089,29622,31709,38885,
+31720,38884,30455, 8191,38882,30961,39786,30454,31739,35838,35795, 9519,
+24942,24946,10856,10860,36345,36353,36344,36355,36343,36351,27406,35181,
+30119,35281,30226, 8360, 8356, 8330, 8358,39348,32112,36349,36348,36347,
+35184,30122,28764,41298,25054,40688,35240,30453, 8794,35249,30966,28852,
+35594,28858,28857,35592,35385,30452, 4903,35397,30969,11554,35412,30451,
+24989,41350,37156,36374,38124,38073,32589,11073,42118,18242,16618,38061,
+11079,42117,17959,36254,33491,33503,36103,33681,30912,17872,30766,19973,
+36261,19585,31039,28755,35991,36093,33703,33698,37155,38123,36373,18241,
+37154, 9818,20884,14498,26409,27227,26106,41758,37129,18218,12026,42159,
+18240,12035,42116,35785,38881,32098,33691,33693,33689,22218,12043,13218,
+10294,10292,12028,30542,30450,30538,30449,31151,30448,31161,30447,31163,
+31165,10883,22217, 5329,42155,42974, 8736,42153, 4951,41300,31460,30446,
+31458,30544,31450,30445,30548,30444,30546,30443,30850,30442,31129,30441,
+31171,30440,31177,31167,35657,35781, 5119, 5121,43484,18837,42822,32959,
+28339,32957,28337,10890,10889,35180,30118,10888,35116,30009,32955,28335,
+32956,28336,10886,32142,30439,32107,30438,33826,29060,33828,29062,30848,
+31159,32105,31158,18239,12112,42115,40294,22797,16335,11611,19666,23481,
+11704,19724,23480,11710,19727,23478,11634,19685,23477,11722,19733,23476,
+40292,21574,14298,14322,21593,40290,11726,19737,23475,11202,19384,23474,
+11677,19713,23473,11674,11673,19710,23534,11205,19387,23472,11208,19390,
+23471,11353,19502,23470,11011,19312,23469,11649,19700,23468,12449,20095,
+23467,11007,19309,23466,11630,19681,23465,12445,20092,23464,16116,10909,
+19216, 6507,10843,19185, 7796, 5508, 1553, 6102, 1544,11201,19383, 7799,
+10841,19183, 6769,10917,10916,19222, 6757, 1919, 5507, 5506, 2337,11200,
+19382, 7798, 3099, 5379, 5378, 3456,11204,19386, 7743, 3078, 5354,14173,
+14650,11010,19311, 6602,10930,19231, 7795,10927,10929,19230, 7724,10926,
+19228, 7741, 5302, 2336,11207,19389, 7616,10838,19181,41258,11641,19692,
+41257,10836,19179,41256,16649,22930,25272,11033,19314,25535,11323,19482,
+25545,11004,19307,25874,11315,19476,25895,12442,20090,25866,11468,19595,
+25469,11456,19577,25457,32610,32609,16651,22932,25274,30785,30886,11537,
+11335,11325,19484,25547,25471,19597,11470,16682,12289,16681,25058,22939,
+16691,12141,11331,16598,30781,11329,11767,11766,11320,19480,25541,12003,
+12140,11319,19479,41255,17819,18627,28695,29901,30805,31851,33397,34784,
+34199,34372,31609,31413,36013,37935,11341,13776, 9661,10272,33417,34953,
+29546,29343,36783,36939,36029,37525,28681,29821,30797,31919,19488,21087,
+17818,18651,28694,29922,30804,31892,33396,34847,34198,34371,31608,31412,
+36012,37979,11340,13854, 9660,10330,33416,35031,29545,29342,36782,36938,
+36028,37619,28680,29861,30796,32001,19487,21199,35953,18354,28693,29561,
+30803,31431,33395,34354,34197,34370,35934,31411,36011,36765,28634,12748,
+30745,10011,33415,34214,33340,29341,36781,36937,36027,36957,28679,29325,
+30795,31599,33320,20434,35951,18353,28692,29560,30802,31430,33394,34353,
+34196,34369,35932,31410,36010,36764,28632,12747,30743,10010,33414,34213,
+33338,29340,36780,36936,36026,36956,28678,29324,30794,31598,33318,20433,
+18163,34524,18170,34539,38973,41703,29442,14761,14765,14758,14451,13068,
+10317,20704,13105,42224,24299,30412,43809,43281,43306,38235,27349, 7889,
+14291,14320,14307,14275,27292,32314,26432, 8142,38286, 8205,38340,32311,
+26426,27542, 7973,24301,30414,29621,31708,38245, 2898,34620, 3233,38243,
+ 2890,34618, 3225,38241, 2909,34616, 3245, 2476, 2353,29613,31699,38239,
+ 2333,34614, 2311,38232, 2959,32947, 2997,38230, 2957,33238, 2995,32946,
+ 2920, 3256,38218,33236, 2918, 3254,38216,32945, 2913, 3249,38211,33141,
+ 2911, 3247,38209, 3284, 3458,28841,30957,38225, 2952,33595, 2990,32944,
+ 2906, 3242,38205,33111, 2889, 3224,38171,26471,33619, 2904, 3240,38203,
+33617, 2902, 3238,38201,33615, 2900, 3236,38199, 9347,33603, 2896, 3231,
+38189,33601, 2888, 3223,38170,33599, 2908, 3244,38207,40288, 5473,19177,
+ 6077,19175, 6083,40286, 5510,20671,42202,28668,40774,28870,35518,28876,
+28875,35516, 3026, 2497,12321,35396,30968,43080, 8776,42253, 4974, 9563,
+35780, 9562,35779, 9561,35778, 9560,35777,35621,35776,43187,43525,33087,
+28410, 8381,40344, 6063,40349, 5471, 8656, 8665,35769,35619,43193,43529,
+24924,24922,19170, 6052,40280, 5460,19169, 6094,40279, 5498,40284, 6048,
+40278, 5456,35768, 9554,35767, 9553,42816,42903,33083,28406, 8214, 8219,
+42821,42908,35276,30221,10834,40283, 5465,19173, 6057,40282, 5484,19172,
+ 6072, 4604,35480, 8688,38151, 7004,35486, 8696,38161, 7021,35484, 8694,
+38154, 7019,11715,11706,15672,11667,11713,11702,15669,11664,11699,11717,
+11708, 5397, 3116,14777,14260, 5481, 3113, 5447, 3389,14741,14220, 5446,
+ 3339, 5412, 3500, 3132, 5411,14204,14721, 7329,21927,15249, 5494, 2352,
+ 5372, 3448, 3101, 5382,14186,14691, 2327, 5344,14162,14608, 3077, 5353,
+14172,14646,11648,19699, 6601,35482, 8692,38166, 7017, 5392, 3473, 3110,
+ 5391,14192,14699,23463,43692,43694,24920,38951,22867,16482,33249,28118,
+16479,28586,28115,22864,30710,35901,40584,16114,11661,23661,38948,22861,
+16476,43690,33246,28112,16473,43689,28583,28109,22858,30707,35898,40581,
+25195,23462,43789,43767,24919,23461,43688,43686,24918,16464,28568,30692,
+28588,33251,30712,24853,35903,24812,28590,33253,30714,24855,35905,24814,
+28576,30700,28575,30699,28574,30698,28594,30718,28593,30717,28592,30716,
+23460,26117,23459,26125,25062,24917,25064,24916,23615,26119,23618,26127,
+24915,25159,24914,25161,23458,25068,23457,25070,25378,24913,25384,24912,
+23580,24911,23578,24910,25380,25086,25386,25084,23456,23455,43698,43696,
+43702,43700,24909,24908,23454,28127,23453,28131,28125,24907,28129,24906,
+23452,25073,23451,25076,27214,24905,27040,24904,23584,24903,23582,24902,
+27216,25090,27042,25088, 9897,23617,27212,23825,27038,23807,25508,25507,
+25485,25484,38076,32635,24060,43752,24059,43747,43751,25989,43746,25988,
+16663,38064,23708,23707,28163,28162,28160,28159,25277,25276,33688,11488,
+11501,33695,11465,19593,41254,23833,23813,24901,25514,24900,25491,25516,
+25493,23824,23806,25376,25506,25382,25483,25505,25482,23840,23819,25258,
+25524,25255,25501,25521,25498,16662,40650,40648,12139,16661,17475,16660,
+17494,16708,32634,16655,11765,16654,16668,16665,17463,25268,22928,16640,
+16658,12002,16657,41253,22927,16639,27274,27104, 8615, 2949, 8724, 2967,
+24899,24898, 5711, 3168,27087,27257,39591,39593,39778,39780,24897,24896,
+25305,41442,41415,24895,24981,41405,41436,24894,40670,21283,13733,25304,
+20144,12556,40669,23178,17049,25303,23330,17279,40668,22082,15459,25302,
+21736,14943,40667,22103,15510,25301,21714,14841,31816,38978,12457,20101,
+23723,12456,20100,23722,12455,20099,25853,25930,41147,41165,24893,25153,
+25151,41527,41493,41518,41484,24892,24891,24985,24983,41512,41476,41523,
+41489,24890,24889,29127,37418,38081,38944,38942,25926,25928,41143,41145,
+41161,41163,24888,24887,25157,24316,25155,24308,26445,24886,26435,24885,
+31153,30573, 8606,27241, 8708,27067,24884,11397,24883,19535, 5633,40721,
+ 8611,27268, 8716,27098,24882,13815,24881,21327,27278,27119,15862, 8485,
+22401, 8532,24880,24879,27266,27096,13813, 5014,21325, 5150,24878,24877,
+24305,25080,24314,25078,24876,26430,24875,26443,38381,12808,38372, 9614,
+33240,28553,30852,30588,23810,25510,23829,25487,24874,25489,24873,25512,
+28730,32109,30590, 8604,27239, 8706,27065,25072,11400,25075,19538,23818,
+25523,23839,25500,25257,25497,25254,25520,25114,41379,26145,23677,25211,
+24077,36418,36416,36452,21509,20039,35274,30219,12320,35212,30151,33801,
+29031,33802,29032,12319,12317,12316,12325,33814,29038,29030,31148,29029,
+31147,33804,29034,31169,31146,33818,29042,23805,25504,23823,25481,26115,
+25480,26123,25503,25094,40694,30575,35818,25066,41355,14455,13070,10319,
+20706,13107,42226,34316,10000,34335,34160,17805,17791,20405,11306,35931,
+35950,34178,28631,31377,31577,31392,20421,29288,18326,29307,29527,36724,
+30742,33337,33317,18336, 9654,19444,19455,36899,36743,36918,12737,34315,
+ 9999,34334,34159,17804,17790,20404,11305,35930,35949,34177,28630,31376,
+31576,31391,20420,29287,18325,29306,29526,36723,30741,33336,33316,18335,
+ 9653,19443,19454,36898,36742,36917,12736,34314, 9998,34333,34158,34388,
+36806,31455,29578,35929,35948,34387,28629,31375,31575,31644,20419,29577,
+18324,29305,29525,36980,30740,33335,33315,29358,31643,36979,34229,36897,
+36741,36916,12735,34530,23691,34519,23690,34518,23689,37417,37349,37500,
+37481,37567,37337,37555,33628,33624,33374,33373, 9760, 9764,19763,19759,
+31002,30998,33638,33642,30765,30764,30983,30987,28913,28909,28652,28651,
+36225,36221,28904,28900,17915,17911,11887,11883,35990,35989,36188,36184,
+34783,33502,33372,33371,10271, 9735,21086,19584,31918,30877,34952,33490,
+30763,30762,31850,30911,29820,28754,28650,28649,37934,36102,29900,28792,
+18626,17871,13775,11515,35988,35987,37524,36092,34846,33501,33370,33369,
+10329, 9734,21198,19583,32000,30876,35030,33489,30761,30760,31891,30910,
+29860,28753,28648,28647,37978,36101,29921,28791,18650,17870,13853,11514,
+35986,35985,37618,36091,33500,33499,38464,38679, 9733, 9732,19582,19581,
+30875,30874,33488,33487,30759,30758,30909,30908,28752,28751,32408,32159,
+36100,36099,28790,28789,17869,17868,11513,11512,35984,35983,36090,36089,
+20673,42204,28671,40777,43082, 8778,35236,31145,42255, 4976,12467,15666,
+12584,18536,15665,18529,11600,18499,43684,43683,43682,43681,41521,41506,
+41487,41472,28106,28105,41520,41486,41505,41471,28104,28103,12588,18542,
+35566,30397,17734,29615,31701,29620,31707,11594,11580,11593,11592,13438,
+40317,40319, 2675,11660,19708,41252, 6693,40409,12569,20157,40408,40672,
+12563,20151,40276,40403,40406,12618,42353,20165,42669,40402,40405,40550,
+40548,12621,42356,20168,42672,40274,40272,40554,40552,35279,30224,34631,
+29684,40270,43213,40268,43541,40400,40397,24303,34628,29681,40399,43210,
+40396,43538,32283,11690, 3331,32281,11697,11696,11695,11694,19722, 2733,
+11692,19720, 2731, 6695, 6692,34708,29761,20865,13242,11180,11183,11179,
+11182, 2831,15192,39417,31625,18280,19041,29473,30322,31309,32523,34248,
+35577,34246,34106,31307,31515,36671,38267,12696,14376, 9964,10665,34104,
+35468,29216,29471,36826,36669,36824,38048,29214,30065,31513,32207,20360,
+21617,18318,37584,29511,29813,31361,31913,34295,34944,34300,34148,31356,
+37965,36713,37480,12727,29846, 9992,31873,34152,34767,29271,34991,36876,
+36717,36881,37926,29266,29895,31557,31843,20395,34820,42168,18576,29518,
+29812,31369,39620,34308,34943,34307,39550,31368,31564,42011,37479,26800,
+13352,24374,10138,39549,34766,29279,29517,36889,42010,36888,37925,29278,
+42167,31563,31842,39619,20989,18315,18575,34990,34819,31355,31912,34299,
+34942,34294,34151,31360,31556,36716,37478,21142,21022,18640,18594,34147,
+34765,29265,29510,36880,36712,36875,37924,29270,29894,37964,37583,20398,
+20988,39536,10155,34989,34818,31354,41959,34298,26909,34293,42114,31359,
+31555,39573,31872,24378,21021,26908,18593,42113,29845,29264,29509,36879,
+39572,36874,24377,29269,39535,37963,37582,41958,13391,39547,10137,34941,
+34764,31365,42007,34304,26936,34303,42164,31364,31560,39617,31841,24384,
+20987,26935,18574,42163,29811,29275,29514,36885,39616,36884,24383,29274,
+39546,37923,37477,42006,13351,38766,32717,41738,39446,26352,38806,41818,
+39493,26389,32819,38805,32818,38804,32817,41744,39452,26362,38765,41826,
+39501,26397,32716,38764,32715,41740,41820,23329,39495,17278,39448,26391,
+26354,23177,24271,17048,24282,41746,41828,23176,39503,17047,39454,26399,
+26364,23328,24276,17277,24285,24278,26367,18312,19039,29506,30320,31351,
+32521,34285,35575,34290,34140,31346,31552,36705,38265,12724,14374, 9989,
+10663,34144,35466,29261,29502,36866,36709,36871,38046,29256,30063,31548,
+32205,20392,21615,18311,37476,29505,29843,31350,31955,34284,34987,34289,
+34139,31345,37922,36704,37580,12723,29810, 9988,31840,34143,34816,29260,
+34940,36865,36708,36870,37961,29255,29907,31547,31870,20391,34763,42112,
+18591,29504,29842,31349,39571,34283,34986,34288,39534,31344,31551,41957,
+37579,26762,13389,24370,10153,39533,34815,29259,29501,36864,41956,36869,
+37960,29254,42111,31546,31869,39570,21019,18310,18590,34939,34762,31348,
+31954,34282,34985,34287,34138,31343,31550,36703,37578,21080,20986,18621,
+18573,34142,34814,29258,29500,36863,36707,36868,37959,29253,29906,37921,
+37475,20390,21018,39491,41816,18351,18625,29558,29899,31428,31849,34351,
+34782,34367,34194,31408,31606,36762,37933,12745,13774,10008,10270,34211,
+34951,29338,29543,36934,36778,36954,37523,29322,29819,31596,31917,20431,
+21085,18350,18649,29557,29920,31427,31890,34350,34845,34366,34193,31407,
+31605,36761,37977,12744,13852,10007,10328,34210,35029,29337,29542,36933,
+36777,36953,37617,29321,29859,31595,31999,20430,21197,39509,41834,39497,
+41822,39416,39422,36636,26312,40618,12761, 9997,34313,34157,34332,17789,
+17803,11304,20403,35947,35928,28628,34176,31574,31374,20418,31390,18323,
+29286,29524,29304,30739,36722,33314,33334, 9652,18334,19453,19442,36740,
+36896,12734,36915, 9996,34312,34156,34331,17788,17802,11303,20402,35946,
+35927,28627,34175,31573,31373,20417,31389,18322,29285,29523,29303,30738,
+36721,33313,33333, 9651,18333,19452,19441,36739,36895,12733,36914,26314,
+40623,12765,40108,39363,34244,18711,34242,34102, 9962,32204,20358,35465,
+31511,10662,34100,21614,31305,38045,31303,20356,29212,18278,29210,35574,
+36667,19038,29469,14373,18276,38264,12694,30319,36822,36665,36820,22228,
+34292,18709,34297,34146, 9991,32202,20394,35463,31554,10660,34150,21612,
+31353,38043,31358,20397,29263,18314,29268,35572,36711,19036,29508,14371,
+18317,38262,12726,30317,36873,36715,36878,22226,26350,24269,27187,27023,
+34349,33623,34365,34192,10006, 9763,20429,19758,31594,30997,34209,33641,
+31406,31604,31426,30986,29320,28908,29336,29541,36760,36220,29556,28899,
+18349,17910,12743,11882,36932,36776,36952,36183,34348,33627,34364,34191,
+10005, 9759,20428,19762,31593,31001,34208,33637,31405,31603,31425,30982,
+29319,28912,29335,29540,36759,36224,29555,28903,18348,17914,12742,11886,
+36931,36775,36951,36187,34330,18612,34311,34174, 9995,31998,20416,35028,
+31572,10327,34155,21196,31388,37616,31372,20401,29302,18332,29284,34844,
+36738,18648,29522,13851,18321,37976,12732,29919,36913,36720,36894,21052,
+34329,18579,34310,34173, 9994,31916,20415,34950,31571,10269,34154,21084,
+31387,37522,31371,20400,29301,18331,29283,34781,36737,18624,29521,13773,
+18320,37932,12731,29898,36912,36719,36893,20995,39415,36635,36645,36634,
+18150,32346,18876,18918,24312,24295,43680,43679,43678,43677,26441,26422,
+24311,28102,24294,28101,28100,26440,28099,26421,29619,31706,35564,30395,
+24748,12785,38909,17715,34572,32943,34565,32942,33109,32941,33107,32940,
+33462,32939,33464,33255,33791,32938,33839,32937,26996,33854,42329,33231,
+ 4860,26990, 4869,42075, 4812,31180, 4889,42318,30662,30658,42070,31184,
+42110,29066,28535,28538, 4851,41955, 4868,29084, 4811,42109, 4886,26761,
+41954,35888,26760,36447,33841,33229, 6909, 6154,33836,33460,36639,34574,
+33128,35369,32936,35343,32935,35345,33257, 4929, 4853, 4801, 8174, 8594,
+26661,35341,33835,20883, 4403,27646,33832,36456,29081,34567,33172,36633,
+33793,33174,35371,33176,20032, 6170,31135, 7934,31122,21877,36400,15196,
+38669,38458,32136,32394,36405, 8854,12314, 8759,21876, 7933,32393,31121,
+38668,12313,36399,36404,32135, 8758,15195, 8853,38457,31134,20031, 7031,
+27226,35360,33777, 6907, 6152,27545, 7976,27376, 7910,25374, 5783,40720,
+ 5590,40719,27247, 8608,27078, 8710,11395,25577,19533,25579,25372,34570,
+33459,36372,38122,40107,18793,26105,38657, 5299, 6951, 5277, 6942, 5207,
+35783,36420,35787,36422,35213,30152,35211,30150,35122,30023, 8388, 8378,
+ 8328,24307, 8365,36415,36414,35216,30155,26359,24273, 8422, 8428, 5279,
+ 6944, 5209,32415,39946, 7623, 5315,32412,39943, 7620, 5312,18875,32509,
+16150, 2984,35426,30960,32517,16139,30869,11425,25477,25461,30880,11462,
+30866,11422,39427,30599,35836,36440,36444,10217,34885,14438,42333,10393,
+20892,14503,42335,10413,20894,10266,34883,20882, 5976,26660, 7452,40393,
+22765,40392,42558,17686,24994,24996,38675,37474,26104,38673,37292,41297,
+41296, 5257,41295,42384,35378,31144, 7315,41309,22694,41308,42557,18046,
+26133,26138,42926,17689,25000,24998,26707,26706,11659,19707,23731,16164,
+22675, 3628,22673, 3626,27999, 3736,16172,22678, 3635,22677, 3634,28001,
+ 3741,36160,14714,11656,36158,14704,11128,11130,11151,11166,11150,11165,
+18238,11137,11136,11156,11171,11139,11158,11173,43676,43675,40426,40422,
+23861,43674,43673,25549,11054,28809,30936,11052,11058,24334,28821,28828,
+30949,37997,11056,37655,19527,24456,19529,24467,17847,28737,30847,28736,
+30846,17852,24463,38607,24789,38434,22436,24452,22433,24449,18761,32104,
+30104,18766, 9511,24629,23450,22216,19145,21808, 9502,24823, 9509,24627,
+ 9506,24624,23447,22213,10827,22210,19142,10825,27623,21805, 9499,24821,
+12241,24413,11978,11977,24351,37674,12240,38014,12239,24346,11976,11975,
+24408,38009,12238,37669,36177,23963,36172,23958,34838,10321,34735,29788,
+34724,29777,29106,29096,34761,10289,12275,18486,39272,17971,34802,10265,
+12256,24403,12237,12236,24341,37664,12254,38004,12252,24339,12235,12234,
+24401,38002,12250,37662,36165,23951,36167,23953,34650,29703,34652,29705,
+25917,25916,25915,25914,25913,25912,12270,24399,12269,12268,24337,37660,
+12267,38000,36163,23949,34648,29701,39271,39270,39269,39268,39614, 9840,
+39611, 9837,39311,39313,15815,18446,15664,18407,25958,25957,39326,39325,
+15938,18403,11852,24415,11851,11850,24353,37676,11849,38016,11848,24410,
+11847,11846,24348,37671,11845,38011,36179,23965,36174,23960,23948,36162,
+34737,29790,34726,29779,23955,36169,25637,25636,25635,25634,39114,39113,
+39112,39111,39110,39109,25665,25663,12587,18541,11879,18498,14047,18440,
+25702,25701,39166,39165,14090,18402,39108,17936,11844,24405,11843,11842,
+24343,37666,11841,38006,34806,10216,34670,29723,34760,10233,11867,24398,
+11866,11865,24336,37659,11864,37999,34647,29700,10477, 2940,32467,16149,
+32466,16148,22209,30149,27815,22206,30146,27818,21516,30358,29052,42781,
+ 5262,29055, 5650,32406,39962, 7642, 5292,32403,39959, 7639, 5289,30355,
+31454,31143,27276,27113,15961, 8496,22495, 8542,26122,26114, 9817, 9816,
+40359,40358,40357,38632,36068,38628,36066,25364, 5587,25362, 5585,27744,
+35164,27741,32167,30182,43039, 8749,28286,30437,28285,30436,28557,30676,
+23626,25167,28284,30435,15392,38911,22203,15663,28480,30608,28283,30434,
+13472,38888,38891, 9556, 9558,32073,17462,28408,30540,28282,30433,28281,
+30432,28546,30667,23599,25139,28280,30431,32743,17461,17460,16952,32742,
+32889,17532,32841,17492,32823,28445,30560,26002,23327,17046,17276,23175,
+41237,32840,32328,32320,26000,23174,17275,17045,23326,41235,16461,22851,
+41251,16456,22848,41249,14757,14744,14494,14440,28961,31061,24084,26022,
+ 9874, 9881,41268,41241,15171,24103,26041,24102,26040,24101,26039,24100,
+26038,24099,26037,41261,24098,26036,24096,26034,24095,26033,24094,26032,
+28970,31070,24093,26031,17457,14547, 9868, 9879, 9866, 9877,28967,31067,
+24111,26049,15173,41263,24108,26046,39341,22202,15662,28964,31064,24106,
+26044,28960,31060,24082,26020, 9865, 9876,32852,17456,17548,32851,17455,
+32816,32785,32916,17531,17044, 9586, 9584,32333,32325, 9591, 9589, 9595,
+ 9593,28279,30430,12843,38913,22201,15661,28482,30610,40679,23173,17043,
+25319,23325,17274,40677,23324,17273,25317,23172,17042,32839,32327,32319,
+13094,11464,19592,25465,14477,13090,14461,13088,11377,11369,28713,30829,
+23737,25323,13425,39016,38994,39015,38993,39014,38992,39013,38991,39012,
+38990, 9676, 9671,17454,28706,30823,28704,30821,11381,11373,13427,25313,
+22200,15660,11379,11371,11376,11368,28703,30820,28278,30429,36332,17990,
+14546,14542,14497,14496,22199,15659,17992,36342,13093,13092,22198,15658,
+36055, 2866, 2829, 3638, 3744, 3499, 3633, 3740, 3484,11658, 3631, 3738,
+ 3477,11670,11655, 5719, 3176, 5341, 4133, 4211, 6542, 5449, 3341, 6652,
+ 3662, 3115, 5396,14196,14706, 3112, 5394,14194,14701,42953, 8732,11657,
+19706, 7754, 3118, 5400, 5399, 3481,11676,19712, 7757,11654,19704, 7752,
+ 5403, 3483, 3120, 5402,14198,14713,27282,27129,15657, 8469,22197, 8525,
+25605,25607, 5438, 3330, 5347, 2330, 4205, 6539, 4204, 6536, 4216, 6535,
+18237,30015, 5335,42108, 5656,42107, 5334, 4130, 4202, 6534, 9809, 9807,
+12024,12022,26008,26705,31206,13483,12498,43672,43671,41432,41401,28098,
+41431,41400,28097,12417,12474,37392,41411,10446,37390,41407,43005,41462,
+12490,13482,12473,13478,12472, 4325,13891,13909,41113,11025,11027,11024,
+41934,41909,41932,41907,41930,41905,43557,43224,41928,41903,25633,26470,
+39107,22052,15418,25818,26704,10264,10263,10262,10261, 9791, 9790, 2808,
+12838,12830, 2417, 2470, 2512,26469,25852,26468,26467,26466,26465,12840,
+41950,41925,41947,41922,41942,41917,41939,41914,15417,22051, 7469,12848,
+12847,12835,26703,26702,26701,26700,26699,25611,31367,29516,42166, 4823,
+42009, 4867,26799, 4810, 4873,34306,36887,42106,26907,41953,31562,29277,
+34302,26934,42162, 4821,42005, 4866,31559, 4809, 4871,31363,29273,42105,
+29513,41952,26759,36883,13383,12952,13474,12951,13042,12950,13020,12949,
+14487,15161,13350,13349,20985,20984,27892,27483,13348,20983,25782,13347,
+20982,25206,12948,12947,20544, 4262,12946,12945,26464,14072,26566,26463,
+14046,26580,26462,18439, 4603,14071,13524,14070,18453,18438,17861, 4657,
+26461,17863,13626,18471,14057, 4633,13523,14045,22196,21308,39164,39106,
+39324,34716,29769,10260,10259,10258,10257,10256,10255,13793,13786,13790,
+13783,10254,10253,10252,10251,42104, 9370,42103, 4943,42102, 8891,42101,
+ 4942,42100, 5521,42099, 4941,42098, 4940,42097, 5861,42096, 5548,42095,
+ 4939,42094, 4938,42093, 5224,39607, 6179,39604, 6176,39600, 5011,39597,
+ 5008,32103,30103,11072,11078,12111,13800,13797,39315,12034,12944,13018,
+26606,13076,13075,13600,32387,18401,26557,32345,32365,14060,26556,14059,
+26555,34072,34074,35363,33779,32386,32385,32344,32363,14015,13566,18400,
+18399,32343,32360,41729,41726,14014,13565,32342,31867,18491,10102,13908,
+18497,32463,16138,39646,39105,39267,39266,39104, 8395,38401, 6355,41721,
+ 2806,14942,14940,15509, 2419, 2472, 2515,15507,38567,30014,30070, 6192,
+21609,14364,18236,30013, 5520, 4129,14974,15523,13346,13345,13381,13344,
+13040,13343,14489,15163,24034,23979,13415,25700,25956,25911,18771,18770,
+14056,10057,10087,17950,18452,18437,18457,10079,14044,17955,25910,25632,
+25631,30112,25667,14089,14069,15937,24022,15654,15908,17948,18398,18397,
+32341,15653,30111,12274,11878,12266,12265,12264,12263,11863,11862,11861,
+11860,11840,11839,11838,11837,11836,11835,11834,11833,11974,11973,12233,
+12232,11832,11831,11830,11829,12231,12230,11972,11971,12229,12228,12248,
+12246,12260,12258,12227,12226,32071,25909,12471,23983,23975,13362,39031,
+39034,23974,23973,24018,13370,24017,25987,23323,17041,17272,23171,41218,
+41216,23170,17040,25985,23322,17271,16688,16705,41214,41212,41210,43228,
+43561,41208,41207,43742,19608,11484,16702,22946,41206,41222,23193,17068,
+25991,23345,17302,41220,32632,32631,32629,32628,24058,43750,43745,25983,
+24057,43749,43744,25982,16694,16693,16711,11413,41203,43739,19605,11481,
+16698,22943,41202,11444,12020,11198,11196, 2533, 5649,11154,11169,19364,
+19373,23443,23442,25123,25132,17605,17604, 9495, 9494,11149,11164,19361,
+19370,23441,23439,25120,25129,17603,17601, 9493, 9491,11276,19424,25193,
+11263,28096,22842,19411,28093,16450,25186,22839,16447,14152,14598,14154,
+14600,40573,43670,43669,40565,11273,19421,25190,11260,28090,22836,19408,
+28087,16444,25183,22833,16441,40575,40567,11622,11639,19673,19690,23659,
+23654,25584,25596,17786,17781, 9645, 9639,40577,40569,11148,11163,19360,
+19369,23657,23652,25119,25128,17784,17779, 9643, 9637,11628,11646,19679,
+19697,23437,23436,25589,25601,17599,17598, 9489, 9488,25173,21913,15232,
+25175,22538,16001,12943,12942,20543,20542,27895,27486,11632,11651,19683,
+19702,23644,23642,25591,25603,17769,17767, 9618, 9616,11621,11638,19672,
+19689,23435,23433,25583,25595,17597,17595, 9487, 9485,24843,24802,27885,
+27476,24840,24799,27882,27473,11280,11267,19428,19415,24847,24806,11243,
+11222,11278,11265,19426,19413,24845,24804,11247,11226,11246,11225,11245,
+11224, 9633, 9626, 9631, 9624, 9630, 9623, 9629,22193,22192, 9622,11609,
+19664, 6702,11613,19668, 6646,11653,10814,19162, 2877,11724,19735, 6704,
+11720,19731, 6648,12357,10807,19156, 2750,35666,14645,35664,14654,14724,
+11679,19715, 6691,35668,14649,10928,10937,12356,22619, 3566,27955, 3703,
+22617, 3564,27953, 3701, 3642, 3747, 3503, 3652, 3754, 3510, 3650, 3752,
+ 3508,12361,10908,19215, 2747,10907,19214, 2708,10905,19212, 2706,12355,
+22624, 3568,27957, 3705, 3648, 3750, 3506,10913,19219, 2711,36153,14644,
+ 3409, 2351,16161,22670, 3623,22669, 3622,27996, 3733, 3621, 3732, 3472,
+36155,14698, 5721, 3178,11637,11620,19688,19671,25594,25582, 6644, 2752,
+ 7104, 3068, 5757, 3211,22609, 3556,27948, 3691, 3647, 3749, 3505,11625,
+19676, 2678,14720,14712,14697,12350,20053, 6708,10920,10912,19224,19218,
+24965,24961, 6625, 2710, 7088, 3038, 5725, 3182,14643,11645,11627,19696,
+19678,25600,25588, 6598, 2670, 7057, 3002, 5681, 3137,11643,11624,19694,
+19675,25598,25586, 6604, 2677, 7061, 3006, 5685, 3141, 6665,11636,11619,
+19687,19670,25593,25581, 6597, 2669, 7056, 3001, 5680, 3136, 7420, 8000,
+ 6079,22010,27569, 1609,15345,28036, 1696,16260,22730, 1661, 5493, 1546,
+ 6090, 1536,14782,14264, 5488, 3076,11352,19501, 6767,11351,19500, 6759,
+ 7423, 8002, 6081,22012,27571, 1593,15349,28040, 1694,16262,22732, 1659,
+11360,11358, 4196, 6563, 4559, 2510, 5632, 6430, 6983, 5538, 5417, 3315,
+ 2532, 5648, 6454, 6991, 5552, 7418, 7998, 6076,22006,27567, 1615,15341,
+28034, 1703,16258,22728, 1668, 7429, 8005, 6096,22015,27574, 1945,15354,
+28043, 2010,16268,22736, 2045,11018, 7431, 8007, 6100,22017,27576, 1943,
+15357,28046, 2008,16271,22738, 2043, 7354, 7956, 6008,21954,27522, 3450,
+15280,27974, 3718,16127,22646, 3599,11022, 7356, 7958, 6010,21956,27524,
+ 3452,15282,27977, 3720,16129,22648, 3601, 3219, 5763, 3215, 5759, 3217,
+ 5761,12345, 7373,21966,15294,12347, 7375, 7969, 6025,21968,27538, 3512,
+15296,28009, 3756,16192,22687, 3654, 6020, 3468, 7964, 3728,27533,27992,
+ 7367, 3617,21962,22665,15290,16157,11605,11607, 6022, 3470, 7966, 3730,
+27535,27994, 7369, 3619,21964,22667,15292,16159, 7212, 7880, 5884,21812,
+27338, 1956,15096,27654, 2021,15695,22246, 2056,15652, 7176, 7863, 5878,
+21771,27307, 1958,15057,27622, 2023,15651,22191, 2058, 5882, 1979, 7878,
+ 2086,27336,27652, 7210, 2119,21810,22244,15094,15693,15650, 5877, 1981,
+ 7862, 2088,27306,27621, 7175, 2121,21770,22190,15056,15649, 5903, 1972,
+ 7898, 2079,27364,27706, 7254, 2112,21835,22345,15128,15791, 5905, 1970,
+ 7900, 2077,27366,27708, 7256, 2110,21837,22347,15130,15793, 7277, 7914,
+ 5937,21844,27383, 1947,15150,27748, 2012,15903,22442, 2047, 7279, 7916,
+ 5939,21846,27385, 1942,15152,27751, 2007,15905,22444, 2042,11579,15682,
+15954,15648, 7174, 7861, 5876,21769,27305, 1951,15055,27620, 2016,15647,
+22189, 2051, 7225, 7887, 5893,21818,27346, 1941,15107,27681, 2006,15745,
+22304, 2041, 5965, 1995, 7927, 2103,27417,27801, 7292, 2136,21871,22489,
+15188,15956, 5967, 1997, 7929, 2105,27419,27805, 7295, 2138,21873,22492,
+15190,15959,15725,15646, 5875, 1974, 7860, 2081,27304,27619, 7173, 2114,
+21768,22188,15054,15645, 5898, 1969, 7893, 2076,27359,27701, 7249, 2109,
+21830,22340,15123,15786, 5963, 1993, 7925, 2101,27415,27799, 7290, 2134,
+21869,22487,15186,15953, 5975, 2335, 1930, 5492, 3095, 5371, 1929, 5238,
+ 4396, 6018, 3466, 7962, 3726,27531,27990, 7365, 3615,21960,22663,15288,
+16155,15644, 5874, 1989, 7859, 2097,27303,27618, 7172, 2130,21767,22187,
+15053,15643, 5896, 1991, 7891, 2099,27357,27699, 7247, 2132,21828,22338,
+15121,15784, 5901, 1987, 7896, 2095,27362,27704, 7252, 2128,21833,22343,
+15126,15789,40964,40969,11764,11763,12001,12000,19881,19880,27891,27482,
+25817,25816,22535,21910,15998,15229,11762,11761,19755,19754,27894,27485,
+25630,25629,22537,21912,16000,15231,40905,40903, 9789, 9788,40901,40899,
+40897,40896,40966,40971,40909,40907,40895,40894, 6556, 2584,10923,19227,
+ 7632, 5986, 2350, 6894, 5573, 5343, 2349, 6532, 2574, 6531, 2573,11135,
+ 5333, 2323, 6530, 2572, 6538, 2576, 6558, 2586, 6548, 2579, 6523, 2567,
+ 6552, 2581,42955,43330,42965,43372,42963,43370,43386,42977,43388,42979,
+43328,42952,27399,27780,18424,10069,27918,27458,27867,27441,27850,27237,
+18451,10078,26723,26534,25881,26460,25851,25613,25872,25850,25533,33674,
+28935,33476,28743,34646,29699,15642,22186,10387,20541,25975,33672,28932,
+25970,25973,25724, 6489, 6488,22185,16713,32639,32637,35179,30117,23822,
+35131,30072,15714,22269,15641,22184,15819,22373,15848,22391,12098,15640,
+22183,22249,16565,32569,32571, 9719,33478,28745,23832,25719,25969,25718,
+34680,29733,14043,18436,14466,14392,25879,25878,39323,17980,39257,17970,
+39317,17978,26434,29669,40064,43549,26428,39091,17935,39163,17943,39090,
+17934,39625,18600,34033,34028,34031,32368,15883,33670,28930,41658,41677,
+41679,39052,40789,10443,20697,10475,20687, 6684, 6686,10479,20540, 6681,
+ 6680,18396,10056,14100,18395,32340,15639,21550,16438,32542,32541,22717,
+16437,32540,32539,15638,22182,35542,14642, 7787, 7786,10643,19009,10642,
+24512,19008,24672,12068,19901,24016, 6774, 6773,15637,22181,34007,34006,
+41647,41646,27847,27438,26554, 9787, 9786, 9785, 9784,43226,43559,43555,
+43222,25849,25610,26004,26007,15109,14390,26698,25609,10775,34837,15977,
+15208,22514,21889,27846,27437,15976,15207,27398,27397,21864,21863,22513,
+21888,27779,27778,15181,15180,27845,27436,22476,22475,15944,15943,24033,
+24032,23978,23977,27844,27435,22564,22563,16041,16040,27843,27434,21895,
+21894,15214,15213,27842,27433,22520,22519,15983,15982,15206,21887,15205,
+27865,21886,27456,27841,27432,21015,21014,13387,13386,27840,27431,20628,
+20627,13030,13029,15204,21885,25773,12104,12103,11744,11743,12094,12096,
+10779,34810, 9700,23972,23971,27861,27452,20981,20980,13342,13341,11739,
+11738, 7942, 7940,10724,10721,23970,23969,23982,24015,23968,23967,24014,
+23981,24013,24025,24027,24012,12070,27864,27455,22512,22511,15975,15974,
+27863,27454,20636,20634,13035,13032,24511,24671,19132,19131,10760,10759,
+10732,10735,24516,24676,19106,19108,10731,10734,24510,24670,19113,19112,
+10741,10740,24509,24669,19062,19061,10684,10683,10781,34759,15212,21893,
+25753, 7947,10429,10571,18816,18957,24508,24668,10426,10568,24505,18813,
+18954,24665,27870,27461,21901,21898,15220,15217,27873,27464,22526,22523,
+15989,15986,10439,10588,18828,18964,24526,24686,10437,10586,24524,18826,
+18962,24684,11737,11736,11945,11944,10596,10595,11735,11734, 9849, 9848,
+12067,12066,14142,14587, 9783, 9782,12065,12063,19900,19898,25848,25846,
+24011,24009,17969,17967, 9847, 9845,27876,27467,20539,20538,12941,12940,
+15223,21904,25776,12061,12060,14139,14584,12117,12115,19916,19914,25887,
+25885,24044,24042,17976,17974, 9858, 9856,11432,19557,25411,28147,22914,
+16602,41080,11934,19847,25742,28084,22830,16436,12222,12284,16672,12217,
+12215,41025,43668,11931,19844,25739,28081,22827,16433,11412,41027,11312,
+19473,25900,25247,19933,12130,41029,11109,19341,25898,25106,19931,12128,
+12154,19940,25920,28156,22923,16635,12183,19958,25945,25943,19956,12181,
+12158,19944,25924,25951,19964,12197,11798,19788,25675,25673,19786,11796,
+11776,19772,25641,25639,19770,11774,24992,20537,12939,12938,20536,25208,
+12059,11760,19753,25628,25627,19752,11759,11818,19804,25696,25688,19797,
+11808,11820,19806,25698,25690,19799,11810,40597,40758,40595,40594,11733,
+11449,11453,19574,25452,28145,22912,16597,12058,11816,19802,25694,25686,
+19795,11806,40639,41075,40637,11758,16629,11108,12193,11999,19879,25908,
+25815,19937,12138,12206,12205,12038,11757,19751,25785,25626,19870,11960,
+12937,20535,25784,25002,20534,12936,12057,43728,43725,32603,11411,19550,
+25402,28149,22917,16605,23999,25793,23996,25790,11938,19851,24003,11913,
+11936,19849,24001,11917,11916,11915,12045,12042,13120,15165,12156,19942,
+25922,25823,19886,12009,12122,19926,25891,25643,19774,11778,12125,19928,
+25893,25625,19750,11756,11815,32602,30882,43667,40537,12120,19924,25889,
+25693,19801,11814,11107,12033,12192,19962,25949,28154,22921,16628,12191,
+19961,25948,12190,19960,25947,25839,19892,12032,12296,19991,26015,12292,
+27396,21862,19981,27777,15179,26011,22474,15942,15399,12056,12846,12547,
+17076,15466,12055,15522,39256,39255,39254,39253,39252,39251,39263,39265,
+39250,39249,39248,39247,41047,41046,41059,41061,41051,41045,41043,41042,
+41041,41040,41039,41038,41037,41036,41035,25752,22562,16039,25751,22518,
+15981,25750,21013,13385,25749,20626,13028,13044,20642,25772,11943,12102,
+11742,12092,41054,41053,41056,12137,41034,14685,12136,11996,25761,20979,
+13340,11732,12162,25907,17091,15471,15526,39246,19972,12273,12354,17039,
+15458,15506,25771,22510,15973,24007,19896,12053,12090,24029,19903,12089,
+24006,19895,12052,24005,19894,12051,15407,12851,41065,41064,41063,41070,
+41068,41049,12119,41032,25779,22529,15992,11924,12041,41078,41073,11731,
+11311,19472,25246,28144,22911,16596,12050,25764,20533,12935,12049,12100,
+19908,25863,12189,12110,11106,19340,25105,28153,22920,16627,12109,19912,
+25883,12262,11859,17316,14861,11730,14973,14817,11729,12834,12408,39101,
+39103,39089,39088,39087,39086,39093,39095,39085,39084,39125,39121,39124,
+39120,40887,40886,40885,40884,40883,40882,40927,40893,40881,40880,40879,
+11755,40878,14710,14683,11754,11753,25624,25623,14807,12832,39083,20489,
+12859,39082,20052,12349,39081,21547,14236,39080,39079,43776,43805,39078,
+40447,43732,17270,14840,14939,17396,14901,15027,12225,12244,40915,40914,
+40913, 9781, 9780,11077,40876,40925,40891,40889,40936,40934,39151,39147,
+39150,39146,11813,11812,40932,40930,40938,14394,11970,12224,40944,40943,
+40942,11828,11827,40940,11826,40911,40947,39308,39307,39140,39139,11752,
+19749,25622,25621,19748,11751,14389,39077,39076, 9722, 9721,12135,19936,
+25814,25906,19878,11995,12934,13377,12967,13339,39117,39116,39149,39145,
+39154,39153, 9830, 9829,13375,12933,13338,12970,40737,40739,40734,17453,
+16185,16111,14676,12161,12134,12133,19935,25905,25813,19877,11994,12179,
+11794,11750,11749,16595,11439,11438,19567,25441,15755,17269,15754,15753,
+25531,25446,25408,19555,11420,25620,26459,25475,25474,25473,19599,11474,
+25445,25444,19570,11442,25406,19553,11418,25399,19547,11408,16959,17482,
+13265,13337,15636,39056,22178,15634,28773,30900,39099,39097,39119,39123,
+39075,39074, 9703, 9705,17452,28766,30894,28763,30892,28762,30891,12175,
+19951,25937,25837,19890,12018,40756,16626,11529,39135,39137,14641,11793,
+19784,25671,11748,19747,25619,12932,20532,25424,12048,11528,11522,11747,
+19746,25618,11780,19776,25645,12178,19954,25941,11436,19565,25426,11993,
+11992,19876,19875,27860,27451,25812,25811,22516,21891,15979,15210,25844,
+30888,11476,30863,11415,25810,12017,12016,19889,19888,27839,27430,25836,
+25835,22509,21884,15972,15203,25834,25940,19953,25939,19544,25396,25395,
+25617,19745,25616,19562,25420,25418,25647,19778,25649,19560,25416,25414,
+25670,19783,25669,19543,25394,25393,34715,29768, 1823, 1805,12576,24366,
+ 1065, 1012,24432,38030,12599,37738,35076,34899,38032,37740,24173,22266,
+24434,21419,27315,26681,20922,13278,20920,13276,29112,20926,13281, 1859,
+ 1842, 1150, 1140, 9932,39742, 9931,39741,24819,39740,34742,29795,13907,
+18540, 1482, 1476,12573,24363,12596,37734, 1062, 1009,24428,38026,12611,
+42344,12595,37733,35078,34901,38034,37742,24175,22274,24436,21423, 9930,
+39739, 9929,39738, 9926,39729, 9925,39728,24831,39727,29130,37421,29129,
+37420,29099,29109, 1469,36495,37425,37424,37423,12586,18539,12624,42360,
+20171,42676, 1479, 1473,12626,20173,42362, 1481,42678, 1475, 8054, 9922,
+39720,29125,37415,38037, 1149, 1139, 1152, 1142,12620,20167,42355, 1145,
+42671, 1135,35453,39526,38500,38702,24594,22314,41882,29647,27291,27290,
+27617,27314,27289,12795,30387,38366,30408,38358,38363,38365, 2930,38357,
+ 2387,37255,29642,37254,29641,37253,29640,19022,43201,30416,38370,27663,
+37246,36144,37245,38299,40063,31679,40062,31678,31738,31737,31705,35446,
+31723,24604,15633,41888,29654, 8044,31735,38376, 2386,35443,31719,35442,
+31718,32516,16284,32479,16283,35456,39528,38504,38704,24596,22316,41884,
+29649,24601,29658,41890,15385,37241,37244, 1421,40058,31676,40057,31675,
+38385,12811,24756,12793,29602,30390,38389,38388,29600,29596,29618,31704,
+34636, 1433,29689, 1438,43219,43551,24599,29653,41887,15383,24598,29652,
+41886,15382, 1285, 1418, 8050,38379,12806,24754,12791,24750,12787,38378,
+38384,12810,38375,38387, 1306, 1294, 1303, 1291,29617,31703,29612,31698,
+34634, 1429,29687, 1436,43217,43548,34630, 1300,29683, 1288,43212,43540,
+30964, 3798, 3778, 3800, 3780,35425,30959,32462,16137,32461,16136,36652,
+34579,34586,36650,34577,34584,34085,29464,31470,29585,31656,31506,29370,
+29462,31468,29583,31654,31504,29368,36644,21875, 7932,32392, 5254,31444,
+20450,38667,12312,36398,36403,31443,31624,36800, 8757,12755, 8518,15194,
+ 8852,38456, 8493,31120,31133,36972,36799,36971,12754,32134,20030,31623,
+ 6169,20449, 7030, 8702, 8337,38763, 9313,41293, 8934,36480, 8701,43062,
+ 8761,18031, 8593, 8173,38803,36371,36370,36369,18030,18029,18028,27225,
+41287,29017,38339, 8204,38308, 8169,34386,32391,34385,34228,31132, 7931,
+33774, 8517,31642, 8756,34227, 5253,36397,31641,38666,35366,35201,38455,
+33771,29576,36805, 6168,29575, 8492,36402, 8851,29015, 7029,36978,36804,
+36977,30301, 8061,41292, 7297,38121,38120,36368,18792,38119,36491,38118,
+38117,38116,31119,31118,41283,18027,41285,18033,27911,27641,42858,42857,
+26103,35204, 5619,36383, 5616,36380,24771, 7553,40207, 6407,31301,24617,
+34240,40205,34238,34098,31299,39906,36663, 7199,39905, 6221,43351, 7551,
+34096, 6406,29208,43349,36818,36661,36816,42721,29206,27330,42720, 7197,
+27172, 6220,24769, 7550,40204, 6404,31297,24616,34236,40203,34234,34094,
+31295,39903,36659, 7196,39901, 6218,43348, 7549,34092, 6402,29204,43347,
+36814,36657,36812,42718,29202,27329,42716, 7195,27170, 6216,34504,30404,
+34501,30401,18155,41645, 6885, 6148,41642, 7307,41673,41778,22311,41672,
+22818,41641,22547,41640,22332,41639,26348,26380,22545,41668,18159,41675,
+38227, 2955,34005, 2993, 2916,38213,34004, 3252, 2894,38183,34025, 3229,
+ 2887,38169,34020, 3222, 2627, 2643,38824, 9409,41720, 9218,36476, 2626,
+41719, 2595, 2647, 2634,23169,18235,22102,18234,18217,21766,22081,18233,
+37188,18232,18231,18230,18216,21765,21923,18229,18215,36632,14274,35340,
+34569,20455, 2653,31640,31453,36976,12760,36803, 2617, 8060, 8540, 8244,
+38393, 6849,41718, 6440, 2625,36148, 8149,38297,41717, 3792,18228,18227,
+ 6920, 6161,18226,18225,18224,18223,21921,18222,18221,41757,26415,41756,
+26414,20448, 2591,31622,31442,36970,12753,36798, 2464,18210,26408,26407,
+41754,34549,35325,41666, 7314,41665,41776,22693,41664, 6432,42556,18178,
+26697,26356,26393,34087,38762, 9312,41711, 8933,36479, 2483,41710, 2455,
+38802,37153,37152,37151,18209,18208,21763,18207,29565,21760,37224, 2557,
+18220,37221, 2554,36643,20333,36602,39439,31285,36604,39484,24264,40237,
+40132,40235,40130,39442,31290,36609,41735,39478,24258,40093,40186,40088,
+40181,18143,34398,34435,37029,20279,36994,18145,34400,34437,37031,20281,
+36996,39483,24263,39482,24262,39486,24266,40091,40184,40086,40179,40083,
+40176,40081,40174,40241,40136,40239,40134,34758,10627,34757,10559,39303,
+39305,34812,10557,37291,38086,37290,38094,37289,38080,38614,37288,38662,
+37287,38664,37301,38656,37473,38655,30133,20531,10622,20530,10525,18394,
+10055,18422,10067,18393,10054,26458,26696,10410,13522,15751,22319,25877,
+34645,29698,34644,29697,34660,29713,38660,37435,37440,34753,29806,34751,
+29804,34672,29725,34643,29696,34642,29695,34656,29709,34662,29715,34730,
+29783,34732,29785,34677,29730,34641,29694,34640,29693,34667,29720,34666,
+29719,37327,38096,20808,13191,18392,18391,10053,20807,20851,13231,18390,
+18389,10052,20850,20857,13235,18421,18419,10066,20855,18410,10062,18477,
+10096,20791,13179,18409,18412,10061,20790,14025,18388,13571,18387,20836,
+13215,18414,18417,10064,20835,13521,18416,34836,10553,34691,29744,13625,
+18470,13520,18480,39295,39298,12931,20529,20572,10615,12981,20574,12930,
+20528,12929,20527,12928,20526,32453,16108,27288,18450,10077, 5631,37822,
+ 5630,42452,42565,18490,10101,13290,20941,13178,20789,13214,20834,34706,
+29759,34699,29752,13177,18474,20788,20787,18476,10095,13213,18479,20833,
+20832,18482,10098,13176,18538,13175,18496,32478,16282,32460,16135,13212,
+20831,13174,20786,13220,20838,13190,20806,13230,20849,32339,15631,32362,
+15847,32337,15629,39186,39188,15802,22360,25843,39259,39261,15628,22173,
+25858,39245,39244,12083,12081,10274,39719,40156,40256,40155,40255,24386,
+15813,24636,13407,30271,30269, 6595, 6594,34679,29732,14042,18435, 6251,
+ 6249,13292,20943,34704,29757,34702,29755,34701,29754,13119,13118,18533,
+32482,16287,10342,39718,40154,40254,40153,40253,24396,13488,24439,13440,
+30194,30193,34714,29767,38659,37400,37405, 8700,30362,30361,30170,30169,
+37413,34739,29792,39737,10247,30192,30191,34741,29794,13117,37729,13629,
+42340,24441,13487,24438,13490,39736,10215,39748,10210,39731,10209,39726,
+10220,39735,10208,39725,10245,39733,10222,39717,10213,20954,10594,10379,
+39764,10378,39763,39762,10528,40246,40143,40245,40142,40220,40105,40219,
+40104,18564,10135,20952,13301,18563,18571,10134,20960,10373,39756,18559,
+10130,20948,13297,18558,18567,10129,20956,10205,34916,34923,37772,13502,
+37765,10203,34914,34921,37770,13500,37763,39761,10377,40172,40079,40170,
+40077,40152,40252,40151,40251,39766,10523,40161,40261,40160,40260,40233,
+40128,40231,40126,34851, 9960,34232,34090,10334, 1864,21204, 1757,32005,
+ 1601,35035, 1797,31293,31509,31895,20354,29864,18274,29200,29467,37983,
+ 1814,29926, 1571,18655, 1742,13858, 1881,36810,36655,37623,12692,34934,
+34778,34003, 7306,34002,29395,34001,34498,34011,34508,34000,34497,40229,
+34492,41761,34931,34775,41968,34018,34514,40243,34516,42397, 1037,41633,
+ 1031,41632, 1048,42392, 1022,41635, 1050,42394, 1024,41760,41631, 1046,
+42390, 1020,41629, 2954,41628, 2992,41627, 2915,41626, 3251,41650, 2892,
+41652, 3227,41656, 2886,41654, 3221,34263, 9979,34254,34121, 9970,  936,
+20366,  931,31521,  926,34112,  921,31315,31530,31324,20375,29222,18286,
+29231,29479,36686,  916,29488,  911,18294,  906,12712,  901,36842,36677,
+36833,12703,34381,31639,34224, 2650,34226, 2616,31621, 2599, 2652,36975,
+34384,36802,29572,36797,29574,36969, 2482, 6384,37645,37150,37149,39645,
+37635,37644,37632,37148,37147,37146,37145,37144,27910, 2624, 8314, 6262,
+41716,37187,38260,37297,37347,42609,32086,38078,37639,34016, 7313,34015,
+29397,34014,34512,37090, 2481, 2480, 2630, 2637, 2505, 6421,37518,37128,
+37399,37127,37495,37126,37469,37124,37468,37513,37142,37123,37511,37462,
+37299,37756,37434,37122,37141,37121,37140,39431,36631,37412,37404,37498,
+37494,37472,10043,37461,37460,37467,10039,37458,37457,37647,37138,37137,
+37120,37510,37517,37520,37174,37505,37439,29444,37119,37136,37135,37172,
+37170,37118,37117, 2641, 2632,39414,26406,26405,27640,42564, 2623,37566,
+37286,31638,12764,12757,41733, 2622, 2621,37527,37402,37492,10045,37455,
+37454,37465,37185,37508,37437,37184,37183,26413,27645,42561,20297, 2612,
+20295, 2610,35114, 2608,35112, 2606,12763,37557,39421,18930,22264,27005,
+21417,13951,24817,38564,38257,38562,37452,38560,30007,38068,32735,32711,
+38761,32710, 9311,38760, 9310,38072,32709,38071,32901,38070,32764,17268,
+23321,24825, 9217,24780, 9216,17267,38060,16897,38059,17340,38058,17530,
+38066,27635,27312, 7608,38801,32708,27786,32093,30095,22171,15627,38645,
+30126,38644,38643, 5247, 5530,32815,38800,32814, 9381,38799, 9380,38075,
+32813,27684,30333,18707,35295,27162,27153,35405,22170,39882,38555,24446,
+22351,39919,38609,24465,35332,27193,35291,27160,27150,35403,42950, 8731,
+42949, 8730,42948, 8729,42947, 8728,35377,32076,40005, 8482,40002, 8479,
+35541,14640,35540,14639,14313,27249,27251,17038,23168,24827, 9024,24782,
+ 9023,17037,38063,27021,16563,38690,23265,21508,37451,38084,32336,32515,
+15626,32520,15625,32511,15677,32508,15624,32529,16280,38571, 5200,32335,
+15623,35539,14638,14662,14637,35552,14666, 8626, 8629,14668,14708,18932,
+22271,27007,21421,13942,24829,30360,42780,35108,30005, 5647,35143,30085,
+ 5665,22165,18820, 5605, 5604,35347,32111,32506,15929, 6955, 5331,40061,
+43546,42762,18769, 6937, 5272, 6936, 5271, 6935, 5270, 6933, 5268, 5629,
+22268, 6939, 5274,22180,22164, 6946, 5281,25809,32240,18748, 8323, 8156,
+ 8316, 8158, 8320, 8153, 5580,35374,32097,35335,32096,35334,32095,32513,
+15882,32367,15881,38759, 9309,43061, 8932,36478, 8059,38798,38115,38114,
+38113,18791,18790,18789,30347,37642,37515,37450,38130,37755,38112,38111,
+27909,27639,37569,38128, 3646,22685,16184, 6338, 1522,12640,12645,15371,
+ 6342, 1510,12642,12647,15373, 6782, 6781,14798,21699, 6344,14796,21697,
+ 6341, 7801, 1555, 7440,12375, 7443, 8012, 6107,22026,27582, 1592,15367,
+28052, 1693,16277,22744, 1658, 1489, 7435,12373, 7437, 8010, 6105,22021,
+27580, 1940,15362,28050, 2005,16275,22742, 2040, 7442,22025,15366, 7439,
+22023,15364, 7426, 1562,12340,12333,12338,12331, 5804, 3214,12342,12335,
+ 6027, 3514, 7971, 3758,27540,28011, 7377, 3656,21970,22689,15298,16194,
+15505,12533,15504,14938,16379,14982,16012,12532, 6752, 1497, 6749, 1494,
+41395,41428,41393,41426,41397,41430, 7673, 2785,12396, 3807, 8862,12509,
+12436,12393, 5370, 3094,12439,12401, 5365, 3088,14737,14216, 5440, 3335,
+ 3128, 5405,14200,14716, 3087, 5364,14181,14664, 7871,12398, 4411, 4409,
+12435,20087, 6593, 3074, 5351,14171,14636,12448,20094, 6591,12546,15118,
+21825, 7236,12545,20135, 6451,12407,12544,12406,12388,12506, 3804, 8859,
+12522,12505, 7664, 2776, 7671, 2783, 7717, 2884,41403,41434, 6017, 3465,
+ 7961, 3725,27530,27989, 7364, 3614,21959,22662,15287,16154,15051,21757,
+ 7169,12568,20156, 6382,14937,21735, 6848,41461,41460,12427,20084, 2755,
+31205,31204,16392,12489,12488,12426, 4417,13481, 2225, 7635, 2415,15621,
+ 7167, 7858, 5873,21755,27302, 2239,15049,27613, 2245,15620,22163, 2261,
+ 7304, 7938, 5973,21879,27421, 2241,15198,27830, 2247,15967,22504, 2264,
+ 7251, 7895, 5900,21832,27361, 2237,15125,27703, 2243,15788,22342, 2257,
+16032,12416,20081, 7526,31201,12415,12414,15686,15952, 2667,15619, 7166,
+ 7857, 5872,21754,27301, 1949,15048,27612, 2014,15618,22162, 2049,12423,
+ 7223, 7885, 5891,21816,27344, 1939,15105,27679, 2004,15743,22302, 2039,
+12404, 7351, 7953, 6005,21951,27517, 3446,15276,27968, 3715,16106,22638,
+ 3587, 2256,21296,12567,13748,20155, 2235, 2255,21295,12566,13747,20154,
+ 2234,12560,20148, 6450,41459,15243, 3788,41450,15617,41420,41458,12425,
+20083, 2209,31821,12497,12496,15117,21824, 7235,12562,20150, 6449, 2227,
+ 2223,12487,20114, 4245,12485,20112, 4243,12875,20501, 4242,14245,41418,
+41456,12559,20147, 2220, 6016, 3464, 7960, 3724,27529,27988, 7363, 3613,
+21958,22661,15286,16153,12500,12432, 7405, 7990, 6044,21993,27559, 1591,
+15324,28021, 1692,16231,22715, 1657,15316,41467, 2217,12430, 7400, 7988,
+ 6042,21988,27557, 1938,15318,28019, 2003,16229,22713, 2038, 7404,21992,
+15323, 7402,21990,15321, 1457,21287,12552,13738,20140, 1453,41444,15320,
+41469, 1463,15615,15612,16030,12413,20080, 1444,12412,20079, 1443,31824,
+31818,12565,20153, 2233,12484,32070,12483,12482,13480,13746,21294, 2254,
+12481,20111, 4241,12480,20110, 4240,12492,20116, 6512,12479,20109, 6380,
+ 2268,22161,15610,15609,22160, 2259,15966,22503, 2263,12420,12419,15685,
+22239, 2251,12495,12558,20146, 2219,12554,20142, 1460,15103, 2216,41454,
+12422,41409,41438,15245, 3790,41453,11020,40855,30973,11578,11577,11591,
+11575,11589, 4564,11583,11582, 2666,11586,11585,12828,12826, 5829, 3832,
+12874,12870,20498, 3812,12869,20497, 3811, 3831, 5828, 3830, 5827, 3834,
+ 5831,12877,12879,12873, 7468,22050,15416, 2531, 5823, 3818, 3836, 3843,
+12884,20506, 3875, 3905, 5843, 3898, 5839, 3900, 5841,12888, 7474,22057,
+15423,12890, 7476, 8024, 6122,22059,27597, 3926,15425,28070, 3966,16337,
+22799, 3955, 6117, 1968, 8021, 2075,27594,28066, 7460, 2108,22041,22773,
+15405,16310, 7454, 8017, 6112,22034,27590, 1937,15390,28062, 2002,16302,
+22767, 2037, 6115, 1983, 8019, 2091,27592,28064, 7456, 2124,22037,22769,
+15401,16306, 7450, 8015, 6110,22032,27588, 1954,15388,28060, 2019,16293,
+22756, 2054, 6109, 1977, 8014, 2084,27587,28059, 7449, 2117,22031,22755,
+15387,16292,12895, 7488, 8031, 6129,22071,27604, 1590,15438,28077, 1691,
+16344,22806, 1656, 3810, 3826, 3829,12893, 7483, 8029, 6127,22066,27602,
+ 1936,15433,28075, 2001,16342,22804, 2036, 7487,22070,15437, 7485,22068,
+15435, 5838, 3897, 3886, 3910, 3915, 3877, 3891, 3902, 3874, 3889, 3896,
+ 3873, 3888, 3895, 3879, 3893, 3904, 6124, 3932, 8026, 3972,27599,28072,
+ 7479, 3961,22062,22801,15428,16339, 3884, 3908, 3913, 3809, 3825, 3828,
+12865,43305,43632,43303,43630,43300,43627,43299,43626,14287,43298,43625,
+43296,43623,14936,21734, 6847,22080,14935,22079,19102,22101,19101,14934,
+43294,14933,43621,14932,14931,15462,15475,15457,15456,14956,14950, 6852,
+ 6846, 6845,15485,14333,14993,14992,14981,15007,15006,15005,15022,15014,
+15010,15009,15004,15025,14351,15024,15483,15020,14349,15012, 5524, 1639,
+14997,14337,14991,14332,14980,14979,14978,14995,14335,14984, 5519, 1906,
+14339,15000,14999,43316,43637,15003,15479,14306,43314,43635,15041,14354,
+15040,15493,15044,14356,15043,15495, 6866,14914,21725, 6369,14916,21727,
+ 6371,12858,20488, 6820,12872,20500, 3817, 3953,22796,16334,12883,20505,
+ 3872, 3952,22795,16333, 3951,22794,16332, 3865,22785,16323,19032,19100,
+38551,19030,19099,38548,30001,29999, 6915, 4625, 4602,35104,29997,15608,
+22159,15607,22158,15821,22375, 3127, 3334,35145,30087, 3314, 3325,15606,
+27585, 4632,15846,22390,40060,43545, 2385, 2530, 2543,40009,43415, 2964,
+38234,30168,30190,40054,43537,30277,23167,19097,40033,43462,38797,32707,
+ 2929,30189,40458,23320,17266,25101,23166,17036,40446,23349,17310,25097,
+23198,17075,38926,38925,38924,38923,39028,39026,38922,38921,38920,38919,
+39041,39043,40452,40462,40454,40445,40444,40442,40449,32588,32587,32586,
+40456,23339,17294,25099,23187,17062,32922,32788,16896,17339,32594,40441,
+16617,25096,16879,23055,40439,16911,23063,40438,40437,23400,17527,16871,
+23049,40436,40435,22906,16587,40434,22905,16586,16585,22904,40433,40432,
+22903,16584,16868,23046,40465,16590,22909,40464,16609,16607,16594,43731,
+43730,40431,40430,39039,39038,39037,39036,16616,38937,38936,39243,39241,
+38935,38934,39292,39288,17173,16615,16752,16614,16613,16612,16744,16611,
+16789,39239,39238,16852,17211,32900,32763,16623,16621,11076,11075,39237,
+39236,39278,39277,39276,39275,11952,19862,25769,25748,19855,11942,32899,
+32762,17499,17451,17325,25842,21445,14034,17484,16791,25870,23275,17187,
+25841,23273,17185,25876,23263,17165,11948,19858,25763,13414,13413,39216,
+39215,39197,39196,39291,39287,12478,12477,13373,13336,13335,13368,12031,
+12030,39235,39234,12108,12107,39284,39283,11941,11940,19854,19853,27900,
+27491,25747,25746,22542,21917,16005,15236,39233,39232,39203,39201,27879,
+27470,27855,27446,27838,27429,25904,25903,25745,25955,25902,18666,42563,
+25759,25755,25998,27775,25808,27637,27015,27615,41158,41157,27836,27427,
+27049,27611,39207,39211,11951,11950,19861,19860,27835,27426,25768,25767,
+22508,21883,15971,15202,25766,11956,11954,19866,19864,27875,27466,25778,
+25775,22528,21903,15991,15222,39221,39219,39224,39223,39290,39286,39231,
+39230,39281,39280,14930,14929,14847,14954,14316,21588, 3816,14319,21591,
+ 3882,14318,21590, 2882,14948,14946,14294,21570,  893,14296,21572,  964,
+ 8262, 8413, 8261, 8412, 8253, 8404, 3081, 5860, 3167, 5859, 3175, 8260,
+ 8411, 1395, 1411, 1414,21584,14311,14347,21606, 1403,14305,21581, 1409,
+14342,21602, 3815, 8259, 8410, 8258, 8409, 8252, 8403, 1406, 1393, 1111,
+ 1117,14703,14648,14660, 8187, 8350, 3080, 2322, 5710, 3166, 5718, 3174,
+11162,11147,19368,19359,25127,25118, 6642, 2749, 7102, 3062, 5755, 3209,
+11161,11146,19367,19358,25126,25117, 6623, 2705, 7086, 3036, 5723, 3180,
+14635,11168,11153,19372,19363,25131,25122, 6590, 2665, 7054, 2999, 5678,
+ 3134,11160,11145,19366,19357,25125,25116, 6600, 2674, 7059, 3004, 5683,
+ 3139,14894,16401,15605,15603,14362,15842,14927,16368,43326,42946,43324,
+42944,43321,42941,42939,43319,43255,43588,43263,43596,43262,43595,14473,
+21643, 6260,30231,32200,38696,30229,38545,30262,30167,38588,30018,30166,
+30012, 3276, 3434,43569,43236,43566,43233,16329,22791, 6234,16050,22573,
+ 6247, 7829, 7736, 7585, 7869, 7600, 6756, 7794, 7740, 6576,14475, 6583,
+ 7597, 4175,14479, 4170,15601,22157, 6792,15140,15600,22156, 7261,14360,
+ 2881, 2805, 5527, 2986, 2945, 2937, 2928, 2927, 2384, 2977,38654,30261,
+ 8287, 8126, 8281, 8116,  830, 8286, 8125, 8285, 8124,  824,  827, 8303,
+ 8131, 8302, 8123, 8307, 8101, 8300, 8301, 8120, 8121, 8299, 8119, 8297,
+ 8118, 8295, 8104, 8292, 8129, 8306, 8103, 8308, 8106,30038,30035,38259,
+30315, 8425, 8427,32057,14884,13417,15599,22155, 6511,15656,22195, 7821,
+ 6331, 6427,15712, 6424, 7414,15705,22257, 6844, 5887, 5799,16243,14926,
+21733, 6841,15598,15965, 6473,22154,15597,15868,15596,15840,22386, 6843,
+14445, 5911, 5635,14453,14444,14448,15830,15844,22388, 6840, 5913, 5628,
+15833,15827,15826,14839, 7575,15595, 2872, 2741,14925,21732, 6839,15594,
+22153, 2833,15593,22152, 2835,15592,22151, 2438,15591,22150, 2432, 2664,
+15875,22409, 2445, 2717,15589,22148, 7839,16355,16374,15782,22336, 7823,
+16357,22809, 7240,16207,22702, 7765,14756,14227,14755,14226,14754,14225,
+16218,16217,43513,43174,43510,43171,16224, 6719,21546,14235,16216,22706,
+ 6725,14763,14230,16220,15588,22147, 7390,15933,22467, 7388,43505,43166,
+43502,43163,16209,22704, 7767,15811,22366, 7394,16146,22656, 7387,16145,
+ 3605,22655,16144,15587,22146, 7231,15855,16035,15854,16034, 2839,15860,
+22399, 2838,15859,22398, 7229,15586,22145, 7501,30128,38653,30132,38652,
+38681,38651,30131,13334,16069,22590,16078, 6270,22599, 6269,16181,12927,
+27932, 6914, 6960, 5414, 8057, 5957, 6506, 6505,18941,18940,10538,10537,
+16179,13333,16170,13332,16388,15017, 7588, 6306, 5236, 5811, 5851, 5869,
+ 6740, 7127, 5798, 6468, 6996, 5564,14405,14018,14404,14017,15770, 6466,
+ 6994, 5562,14450,14447,15769,15768,15767,16373,22815, 7228,14407,14020,
+15772,16122,22643, 7227,14409,14022,14443, 5547, 5223,32069,27917,16038,
+22561,16037, 6291,22560, 6288,27915,15874,22408, 4435,15801,22359, 4459,
+ 6574,22144,15585, 6562,22358,15800, 6582,22406,15872,16011, 5655, 4128,
+15584,22143, 4437, 5660, 4093,14634,14633,14632,14631,43483,18998,16048,
+22571, 6258,43478,43131,43475,43128, 6707,21367,13906,16183,22684, 4239,
+14678, 6689,21336,13835,14680,16124,13331, 5770, 5919,14672,14671, 5768,
+ 5868, 5766, 5907, 6561, 4189,15911,22448, 6838, 5943, 5627, 6442, 6987,
+ 5542,15703, 5594, 5416, 5598, 6075, 7011, 7997,28033,27566, 6496, 7417,
+22727,22005,16257,15340,15583, 5600, 5867, 7013, 7854,27610,27300, 6498,
+ 7163,22142,21753,15582,15047, 5945, 5645, 6724, 7116, 5787, 5602, 5947,
+ 7015, 7918,27754,27388, 6502, 7285,22459,21851,15927,15157, 5597, 5962,
+ 7010, 7924,27798,27414, 6495, 7289,22486,21868,15951,15185,15455,16352,
+15503,16351,16350,15513,22106, 7835,14844,21717, 7820,14886,21720, 7819,
+15410,22044, 7818,14825,21708, 7817,14824,21707, 7816,16199,22692, 7815,
+14883,14823,43587,43254,43586,43253, 7825, 2663,16362,22811, 1398,16367,
+16366,43289,43616,43594,43261, 2414,16372,22814, 1155,16371,22813, 2421,
+16359,43280,43613,43252,43585,14838,16365,16364,43278,43611,43275,43608,
+43273,43606,43291,43618,15447,38524, 8682,15449,38526, 8684,43271,43604,
+43270,43603,43598,43265,43259,43592,16370,43269,43602,43017,43408,15858,
+ 3596,22642,16121,15857,22397, 2837,14234,21545, 6718, 5782,14743,21688,
+ 6318,16198,16215,16304,16214,16197,16213,16206,22701, 7764,16205,22700,
+ 7763, 6717,21544,14233,16291,16212, 5810,43103,43458,40124,14170,40123,
+14169,30188,30187,38695,30186,38694,30185,32066,32060,14630,14629,14628,
+ 3343, 7680,39970,32449, 5425, 7677,39967,32446, 5422, 8440, 8451, 3712,
+ 3440, 3696, 3415, 3589, 3585, 3711, 3439,14244,43101,43456, 6671,21079,
+13519,15581,16237,43099,43454,43111,18997, 3710, 3438,43109,18995,43123,
+43470,43120,43467,16101,22636, 3583,15932, 3604,16312,16142,14805, 5765,
+ 5233,43113,43460,16120, 3595,16119,22641, 3594,16118,22640, 3593,14803,
+16047,22570, 3522,16046,22569, 3521, 6706,20785,13173, 6447,21556,14255,
+ 6445,22725,16252, 6333, 6444,14418,14028,14442,15337, 5596, 6067, 7009,
+ 7995,28031,27564, 6494, 7412,22724,22003,16251,15336, 6435,21554,14253,
+ 6438,22722,16249, 6434, 7416,14753,14387, 5540, 6065, 6985, 7993,28029,
+27562, 6437, 7410,22721,22001,16248,15334,15301,21973, 7380, 6030, 5803,
+ 6029, 5775, 6743, 7129, 5801, 6731, 7122, 5793, 6727, 7118, 5789,14760,
+ 6032, 5777,14746, 7386,21979,15307, 5781, 5452, 6034, 5779, 6723, 7115,
+ 5786, 5795, 6039, 7124, 7983,28016,27552, 6733, 7396,22710,21984,16226,
+15312,14752,14748, 5791, 6037, 7120, 7981,28014,27550, 6729, 7392,22708,
+21982,16222,15310,43027,14465,21641, 6257,16327,22789, 6256,32237,15002,
+14464,14463, 6589, 6484,21453,14051,16246,14469,14468,15689,15950, 6254,
+15580, 5571, 5866, 7001, 7853,27609,27299, 6481, 7162,22141,21752,15579,
+15046,14751,14471, 5569, 5889, 6999, 7883,27677,27342, 6479, 7221,22300,
+21814,15741,15101,16326,22788, 3938,43577,43244,43574,43241, 6819,21366,
+13905, 6818,20784,13172,16331,22793, 4238, 5813, 3987, 6796,21319,13807,
+ 5817, 4015, 5809, 4012, 6805,20713,13116, 6807, 7147, 5834,20783,26609,
+ 3845,13171,26853, 3838,13666,21222, 3820, 6790, 7138, 5808,20805,26616,
+ 1953,13189,26857, 2018,13674,21227, 2053, 5807, 1976, 7137, 2083,26636,
+26874, 6789, 2116,20848,21247,13229,13701, 5821, 1967, 7144, 2074,26629,
+26867, 6800, 2107,20830,21239,13211,13692, 6794, 7140, 5815,20782,26608,
+ 1935,13170,26852, 2000,13665,21221, 2035, 5819, 1985, 7142, 2093,26647,
+26885, 6798, 2126,20870,21256,13245,13708,16325,22787, 3937, 3940, 3946,
+ 3921, 3959, 3970, 3930, 3950, 3964, 3924, 3936, 3944, 3919, 3949, 3963,
+ 3923, 3957, 3968, 3928, 6835, 7154, 5848,20903,26670, 1589,13261,26895,
+ 1690,13717,21268, 1655, 3935, 3943, 3918, 6830, 7152, 5846,20898,26668,
+ 1934,13256,26893, 1999,13715,21266, 2034, 6834,20902,13260, 6832,20900,
+13258,16315,22777, 3856, 3855, 3861, 3850, 5836, 3848, 7149, 3841,26628,
+26866, 6809, 3823,20829,21238,13210,13691, 3934, 3942, 3917,14837,21713,
+ 6353,22100,14836,14835,14846, 6851,21738,14952, 6837,21731,14924,15502,
+15501,15516,15528,15540,14882,15536, 5864, 1638,16378, 5858, 4127, 5857,
+ 1905, 6854,21740,14967,14881,15534,14878,14906,15544,15546, 6862,21746,
+15035, 6864,21748,15037,14867,14908,14897,14891,14888,14899,14875,14880,
+16098,16095,22634,22631, 3578, 3575,22629, 3573,27960, 3708,22608, 3555,
+27947, 3688,22606, 3553,27945, 3686,40118,14110,30165,38687,30164,32068,
+ 3274, 3432, 3268, 3426,27965,27963,14626, 5349,27940,35536,14625,35538,
+14627,35535,14624,35534,14623, 6664, 6663, 4303,21444,14033, 6560,21443,
+14032, 5738, 3196, 2528, 2527, 5644, 7042, 8345, 8183, 2526, 3323, 3317,
+ 5640, 7038, 6931, 5266, 5641, 7039, 2524, 3313, 7732,39979,32435, 5362,
+ 7729,39976,32432, 5359,22612, 3559,27951, 3694,22611, 3558,27950, 3693,
+ 7630,39953,32422, 5322, 7627,39950,32419, 5319,35533,14622,35532,14621,
+35531,14620,35545,14653,35530,14619,35544,14652,10716,10713,10708,10705,
+35527,14616,35529,14618,10710,10707,10593,10592, 2702, 2690,18867,18855,
+10470,10458, 5741, 3199, 7099, 3049,24735,24575, 5733, 3191, 3272, 3430,
+ 5735, 3193, 5734, 3192, 7096, 3046,24732,24572, 5731, 3189, 7094, 3044,
+24730,24570, 5728, 3186, 7091, 3041,24727,24567, 5715, 3172, 7083, 3029,
+24724,24564, 3270, 3428, 2700, 2688,18865,18853,10468,10456,43482,18834,
+ 5709, 3165, 5704, 3161, 5626, 4113, 5855, 4085, 5662, 3986, 5701, 3158,
+ 5693, 3150, 7077, 3022, 7069, 3014,24716,24556,24708,24548, 6620, 2699,
+ 6612, 2687,18985,18864,18977,18852,10613,10467,10605,10455, 5697, 3154,
+ 5689, 3146, 7073, 3018,22604, 7065, 3010,24712,24552, 3551,24704,24544,
+ 6616, 2694, 6608, 2682,27943,18981,18859,18973,18847, 3684,10609,10462,
+10601,10450,22603, 3550,27942, 3683, 2696, 2684,18861,18849,10464,10452,
+ 5698, 3155, 5690, 3147, 7074, 3019, 7066, 3011,24713,24553,24705,24545,
+ 6617, 2695, 6609, 2683,18982,18860,18974,18848,10610,10463,10602,10451,
+28004, 3126, 3060, 3379, 3125, 3123, 3122, 3333, 3066, 3383, 3065, 3382,
+10507,18914,10506, 2875,18913, 2874, 3304, 3493, 3302, 3491, 3301, 3490,
+ 2746, 2745,18889,18888,10490,10489, 2744, 2743,18887,18886,10488,10487,
+14522, 5654, 2538,15766,15765,14397, 8138, 8310, 5559, 5546, 5545, 5222,
+ 5707, 5221, 5717, 5544, 5220,16422,16417,16419,43666,43661,43664,43659,
+43656,43654,43652,43650,43643,43648,43641,43646, 1721, 7573, 1718, 7570,
+ 7711, 2859, 7706, 2844,16494, 7690, 2800, 7688, 2798, 7687, 2797, 7709,
+ 2857, 7704, 2842,16484, 7694, 2813,16502, 7685, 2795, 7714, 2864, 7684,
+ 2794,16491,16490, 7693, 2812, 7683, 2793,16534,16541,16532,16539,16547,
+16552,16489,16551,32547,16545,32549,16550,16549,32544,16488,32584,32596,
+16580,22899,28140,32583,38724,43714,22901,28142,38722,43712,16582,32581,
+16671,16593,16569,16412,16411,16410, 7682, 2792, 7692, 2811,16524,16526,
+16408,16407,16430,16406,16509,16506, 3645,22871,16497,16427,16426,22823,
+ 4558,16425,22822, 4556,16592,16500,16511,16465,16469,16467, 7701, 2822,
+ 7699, 2820, 7697, 2818,16504,16951,23098, 8930,32714,16751,16750, 4324,
+16746,32898,32761, 9180,23289,17210, 6722,23032,16851,17209,23288, 9179,
+17215,23293, 9187,16839,16989, 6471,23037,16857,16836,16987,16831,16984,
+43775,43804, 4361, 9178,17191,23279, 9156,17164,23262, 9137,17189,23277,
+ 9154,16785,17184,23272, 9152,17183,23271, 9151,17163,23261, 9136,16793,
+17260,23314, 9210,17259,23313, 9209,17258,17257,17256,17540,17520,16895,
+16894,17384,16916,17373,17084,23204, 9040,17546, 4126, 8890, 8929,23097,
+16950,16949,23096, 8928,16948,23095, 8927,16947,43871,43830,43869,43828,
+17472, 6376,22977,16757,16765,22969, 7161,17449,16799,17459,32713,16749,
+16748,17470,17447, 8952, 8951,16830,23015, 7448,16850,23031, 6788,32760,
+17208,23287, 9177, 8970, 8969,16809,22996, 4555,16808,22995, 6317,16849,
+23030, 7159,16829,23014, 6374,16848,23029, 7446,16828,23013, 6786,17207,
+23286, 9176,16782,16847,23028, 7215,16827,23012, 6419,16779,17480,32732,
+32754,32731,16784,17182,16768, 9189,43807,43778, 4268,17176,17161,43867,
+43826,17160,43865,43824, 9208,23312,17030,17255,23160, 9017, 9207,23311,
+17029,17254,23159, 9016, 9226,23343,17066,17298,23191, 9030,17028,17253,
+ 9206,23310,17252, 9205,23309,17251,17027,23158, 9015,17250,23308, 9204,
+17026,23157, 9014,17249,23307, 9203,17248,23306, 9202,17025,23156, 9013,
+17247,16867,17519,16893,16892,16891,16890,16902,16865,23045, 6470,16873,
+16870,23048, 6378, 6190,23395,17522,16864,23044, 4525,16883,23059, 4509,
+16914,23065, 4508, 9201,23305,17246, 9249,23355,17360,17420,23377, 9272,
+17138,23241, 9091, 5871, 7856, 7524, 7165, 8042, 6140,16927,17143,23076,
+23246, 7522, 9096,28180,28208, 8040, 9120, 6138, 8876,17436,23391, 9286,
+17592,28242, 9307,23430,28276, 8912, 7520, 8038, 6136,17136,23239, 9089,
+17430,23386, 9281,17586,28237, 9302,23425,28271, 8907, 7518, 8036, 6134,
+ 9269,23374,16924,17140,17417,23073,23243, 7516, 9093,28177,28205, 8034,
+ 9117, 6132, 8873,17372,16889, 9229,23348,17074,17309,23197, 9034,17073,
+23196, 9033,16881,23057, 4517,16670,16574,22893,28134,32575,38716,43706,
+22895,28136,38718,43708,16576,32577,32601,16573,22892,28133,16625,22919,
+28152,16946,23094, 8925,16945,23093, 8924,38796,32704,17444,17443,17498,
+17477,17504,17488,17490,17442,17441,16795, 3581,22981,16775,16774,22980,
+ 4507, 3580,23011,16826, 8943,23102,17179,16957,23268, 9147,32748,32893,
+ 3864,22994,16807,16806,22993, 4539, 2179,23010,16825,17509,16846,23027,
+ 2193, 2184,23020,16838,16855,23035, 2197, 2182,23018,16834,16811,22998,
+ 4506,16813,23000, 4524,16982,16819,43800,43771, 9166, 1673, 9200,23304,
+17024,17245,23155, 9012, 9228,23347,17072,17308,23195, 9032, 9224,23341,
+17064,17296,23189, 9028,32759,32897,17214,23292, 9186,17206,23285, 9175,
+ 3948,23026,16845, 3644,23025,16844,43803,43774, 9174, 2192,17159,23260,
+ 9135, 9134,23259,17158,17440,17514,17512,16860,23040, 2191,17000,23134,
+ 8995,16998,23132, 8993, 3591,23024,16843,17222,16994, 9192,23296,17218,
+ 9194,23298,17220,17507,16992,23127, 8987,16862,23042, 1328,23154,17244,
+17023,17474,17243,17022,17497,17021,17486,17439,17496,17057,17093,17020,
+17019,17117,17352,17371,17370,17376,17369,17390,17379,17392,17109, 8894,
+ 1637,17338, 8889, 1904,17356,17103,17438,17401,17126,17403,17128,17409,
+23364, 9261,17411,23366, 9263, 8923,23092,16944, 8922,23091,16943, 9133,
+ 2862, 9144, 2791, 9142, 2810,  838,22973,16764,16761,22976,  840, 9131,
+ 2790,16736,16734,17324, 8978,16842,23023, 3814, 9107,23257,17154,17107,
+23220, 9070, 9076,23226,17115, 8968, 8967,23119,16978,16803,22990, 3881,
+16802,22989, 2880,32747,16805,22992, 1327,16816,23003, 1334, 9165, 8962,
+ 8961, 1344, 9163, 8966,23118,16977, 8964,23116,16975,17217,23295, 9191,
+ 9011,23153,17018,17017,23152, 9010,17120,23229, 9079,17082,23202, 9038,
+ 9062,23213,17099,32758,32757, 8984, 8982, 8977, 8976, 2171, 2170, 2178,
+23009,16824,43802,43773, 9173, 2190, 9199,23303,17016,17242,23151, 9009,
+ 9198,23302,17015,17241,23150, 9008, 9196,23300,17239,23148,17238,17237,
+17236,17235,17234,17233,17232,17231,17518,17517,17172,17337,17336,17335,
+17334,17345,17205,32896,17333,32921,28257, 9056,43837, 9245, 9395,28250,
+ 9329,43796, 9392,28197, 9326,43902,28224, 9053,43895, 9242,43834, 9049,
+28254, 9238, 9388,43793, 9322,28247, 9385,43899, 9319,28194,43892, 9046,
+28221, 9235, 9232,23352,17089,17323,23207, 9043,17321,17320,32773,32680,
+32679,32772,32685,32778,32683,32775,32792,32688,38823,32771,17516,17539,
+17543,17204,23284, 9172,17013,23147,17012, 9006,23146, 9005,17011,17010,
+23145,23144, 9004, 9003,17009,17007,23143,23141, 9002, 9000,17081,17080,
+23201,23200, 9037, 9036,38830, 9416,32848, 9415,32847,38829, 9215,23319,
+17035,17265,23165, 9022, 9213,23317,17033,17263,23163, 9020,17203,23283,
+ 9171,16878,23054, 2188,17529,23402, 1325,17526,23399, 9170,16876,23052,
+ 1324,17525,23398, 2187, 1177, 1188, 1160, 1185, 1167, 1170,32806,32697,
+ 1220, 1215, 1246, 1202, 1250, 1232,32811,32702,17134,23237, 9087,17427,
+17583,23383,23422,28234,28268, 9278, 1184, 9299, 1187, 8904, 1176,16926,
+23075, 1159,17142,28179, 1166,23245,28207, 1169, 9095, 9119, 8875, 9275,
+23380,17423, 9277,23382,17426,17148,16931,23251,23080,28212,28184, 9101,
+ 1236, 9124, 1240, 8880, 1226,32808,32699,38792,38755,43819,43784, 9280,
+ 1245, 9301, 1249, 8906, 1231,23385,23083,28236,28187, 9343, 1254, 9363,
+ 1256, 8883, 1210,38860,38757,43860,43786, 9458, 1260, 9471, 1262, 8911,
+ 1219,17429,16934,28215,28270, 9127, 1208, 9376, 1258,32880,32701,43821,
+43907, 9306, 1214, 9480, 1264,28241,28275, 9365, 1222, 9378, 1242,43862,
+43909, 9473, 1228, 9482, 1252,17153,17585,23256,23424, 9106, 1197,32810,
+32931,38794,38872, 9285, 1201,23390,23429, 9345, 1204,38864,38874, 9462,
+ 1206,17435,17591,32884,32933,17434,17590,23389,23428,28240,28274, 9284,
+ 1200, 9305, 1213, 8910, 1218,17433,17589,23388,23427,28239,28273, 9283,
+ 1199, 9304, 1212, 8909, 1217,17147,16930,23250,23079, 9100, 1235,28211,
+28183, 9123, 1239, 8879, 1225,16933,23082, 1244,17152,28186, 1248,23255,
+28214, 1230, 9105, 9126, 8882,17145,23248, 9098,17151,23254,17150, 9104,
+23253, 9103,38863, 9461,32883, 9460,32882,38862, 1316, 1319, 1337, 1313,
+ 1340, 1322,17098,23212,17097, 9061,23211, 9060,38834, 9427,32857, 9426,
+32856,38833,17367,17366,17365,17364,17363,16908,32794,32925,17425,17582,
+ 9448, 9447, 1380,17560,23409, 1373,38849, 9446,32872, 9444,32870,38847,
+38841, 9434,32864, 9432,32862,38839,38837, 9430,32860, 9429,32859,38836,
+32691,32796,17106,17105,23219,23218, 9069, 9068,38844, 9439,32867, 9438,
+32866,38843, 1370, 1378, 1348, 1375, 1356, 1362,16910,23062, 2186, 1385,
+23412,17568, 9252,23358,17387, 1382, 1390, 1353, 1387, 1359, 1365,32693,
+32800,17114,23225,17113, 9075,23224, 9074,38853, 9453,32875, 9452,32874,
+38852,17332,17331,17330,17329,16888,32787,32920,17432,17588,17358,17556,
+17351,17553,17389,17570,17378,17562,17382,17564,17394,17572,17362,17558,
+ 9442, 9441, 9424, 9423, 1368, 1108,13330,13329,13400,13397,17078,17315,
+17071,17307,15133,13770,13518,14434,15468,14972,15521,14863,13769,14436,
+15135,13517,13768,14811,15395,13516,13767,14420,15116,13515,15518,14860,
+15465,14965,13805,14816,15398,13568,17124,17405,17070,17314,15369,14792,
+14790,15359,14821,15430,15491,14910,14770,15314,12926,13328,15520,14971,
+13327,12925,13326,12924,13325,12923,15542,15031,13469,13253,14815,15397,
+15464,14859,17349,16906,17347,16904,14873,16397,14871,16395,14532,13324,
+14527,13323,14525,13393,14530,12922,14535,12984,14537,12921,14517,12920,
+16382,14987,16384,14989,16022,13322,16017,13321,16015,13395,16020,12919,
+16025,12986,16027,12918,16008,12917,15775,15777,14402,14400,17398,14510,
+14903,14858,14508,14424,14819,16961,17305,14412,14855,13876,13883,13881,
+13873,14422,14414,14416,14809,13946,13944,13878,13889,13887,15029,14923,
+13451,14963,13840,13900,13831,13803,13842,13981,13779,13829,13959,13950,
+13971,13964,13962,13967,16068,22589,16077, 4261,22598, 4260,16066,22587,
+16075, 4259,22596, 4257,15256,21934,15263, 7336,21941, 7343,15254,21932,
+15261, 7334,21939, 7341,12916,20525, 4255,13079,20683, 4314,12915,20524,
+ 4254,12914,20523, 4253,13081,20685, 4316,13320,20978, 4434,13419,21040,
+ 4468,13319,20977, 4433,13318,20976, 4432,13317,20975, 4431,12913,20522,
+ 4252,12912,20521, 4251,12911,20520, 4250, 4301,22781,16319,15412,22046,
+ 7464,12910,20519, 6816,12909,20518, 6634,12908,20517, 6661,12907,20516,
+ 6459,12906,20515, 6453,12905,20514, 6802,13316,20974, 6632,13315,20973,
+ 6637,13314,20972, 6628,13313,20971, 6457,16321,22783, 4249,16308,22771,
+ 4248,16203,22698, 6715,15914,22451, 6492,15305,21977, 7384,15303,21975,
+ 7382,15155,21849, 7283,15414,22048, 7466,13006,20610, 6813,15403,22039,
+ 7458,13009,20613, 6659,16201,22696, 6713,13403,21030, 6639, 8092, 8571,
+ 8574, 8095,38612,37449,38626,37448,38624,37446,38541,37444,14814,17313,
+17312,12904,12903,12902,12901,13083,13012, 7107, 5350,42779,42777, 4169,
+ 4393,14834,14922, 4390, 4349, 4424, 4270, 4347,18969,43135,27930,27928,
+27921, 4601, 4600, 4598,27511,27509,27504, 7785, 6772, 6679, 6487, 6688,
+ 8090, 8569,30259,35323,30254,35317,30252,35315, 8089, 8568,18967,43133,
+30251,35314,30244,35307,30257,35321,30249,35312,15087,21797, 4505, 4504,
+ 4512, 4579, 4577, 4514,29692,34639,29691,34638,29707,34654,29717,34664,
+29799,34746,29801,34748,29740,34687,13958, 6932, 5267, 6930, 5265, 4503,
+ 4502, 4501, 4520, 4519, 4551, 8363, 2934, 2926, 2974, 2970, 8370, 2925,
+ 2383, 2391, 2382, 8368, 8347,30250,35313, 8343, 7722, 7720,19096,19094,
+10709,10706, 4500,22238,15684, 4499,22236,15681,13514,21078, 7566,12900,
+20513, 6779,12899,20512, 6826,12898,20511, 6737,17122,23231, 9081, 9066,
+23216,17102,17111,23222, 9072, 9026,23185,17056,17095,23209, 9058,12897,
+20510, 7806,15550,22120, 7851, 7507,22090,15478,15533,22114, 7845,15538,
+22116, 7847, 7499,22084,15461,15530,22111, 7841,15711,22261, 6742,15708,
+22259, 7774, 7581,22380,15829,15836,22382, 7583,15923,22457, 7564, 7593,
+22241,15688,15442,22075, 7492,15489,22096, 7513,15481,22092, 7509, 7837,
+22108,15515,17005,23139, 8998, 8997,23138,17004,15500,22099, 7832, 7497,
+22078,15454,15453,22077, 7496, 7831,22098,15499,15473,22087, 7504, 4529,
+22140,15578,13822,15577, 4527,22139,15576,13817,15575,15724,13513,15574,
+22138, 4179,15573,13583,14251,15710,15572,22137, 7776,14257,15571,16242,
+15707,15570,22136, 6745,16254,15569,15832,15835,15702,15922,15568,22135,
+ 6500,15567,15925, 4188, 4538,22455,15920, 4537,22454,15919, 7591,22453,
+15918,15917,13613,15916, 7595,22134,15566,14065,15565,17228,14833, 4173,
+13188,20804, 4365,13228,20847, 4386,17227,13237,20859, 4389,13169,20781,
+ 4360,14099,13827, 4534,13603,21164, 7590,14068,14024,13570,13209,20828,
+ 4382,13512,13412,13411,17003,17226,15452,14832,15498,14921,17328,16887,
+14866,16391,14521,13410,16377,14977,16010,13409,14396,13941,13885,13074,
+20679, 4310,13073,20678, 4309, 4308,22776,16314,15300,21972, 7379,13072,
+ 4531,15564,22133, 6475,15870,15563,15825,13599,13511,15764, 6771, 6670,
+ 6678, 6486, 7784,13448,13897, 3266, 3424,42761,42776, 6929, 5264, 2924,
+ 2381,18833,43481, 8713, 2380, 2379, 2962,19078,42868,18806,43450, 2923,
+ 1016, 1058,35100,29992, 1044,35096,29988,15561,22131,35097,29989, 1040,
+ 2404, 1034, 1042, 1054, 1028, 5115, 5117,16064,22585,16073, 4297,22594,
+ 4296,27926, 4624, 6948, 5294,15252,21930,15259, 7332,21937, 7339,27507,
+ 8352,14813,14857,14970,14969,42775,13447,13896,13446,13895, 7110, 5369,
+ 2980, 8377, 7739, 7738,19111,19110,10739,10738,18987,43158, 2942, 8712,
+ 4563,13639,21187, 4554,13904, 4195, 4381,15070,21780, 4533,13903,14067,
+13957,16938,16937,42132,42573,17002,17225,15451,14920,15497,14831,14919,
+15409,22043, 7462,13305,20963, 6811,13304,20962, 6657,16196,22691, 6711,
+13303,13986,13985,13984,17224,14918,14830,42689,42380,42688,42379, 4429,
+13311,20969, 4428,13977,16936,13307,20965, 4423,13509,37779, 4899,13507,
+37777, 4897,13983,42687,42378,42373,42682,13988,42377,42686,42691,42382,
+ 9078,23228,17119, 7511,22094,15487,15440,22073, 7490,13115,20712, 6824,
+42802, 8376, 8375, 7849,22118,15548,13826,13445,13894,13114,13628, 2232,
+21214,13743,13651,21291, 2250, 6477,21167,15144,13606,21841, 7270,13956,
+21399, 2214, 2231,21355,13867,15143,21840, 7269, 6483,21334,13833,13955,
+ 4574,13113,13949, 4571, 4570,13731,21281, 4553,13168,13737,21286, 2230,
+13742,21290, 2249,13954,21398, 2213,13948,21396, 2229,13112,20711, 6735,
+13940,15265,21943,15066,21776,15085,21795,30243,35306,15560,22130, 4548,
+29765,34712,29750,34697, 2378, 5130, 5127,43480,18832, 2377,35094,29986,
+ 2376,35090,29982,15558,22128,35091,29983, 2403,15077,21787,30235,35299,
+30246,35309, 8342,13111,20710, 6777,13110,20709, 7804, 4550,13208,20827,
+ 4380,18680,42605, 4379,13646,18934,42986, 8312, 1778,42238,42611,13167,
+20780, 4359, 7035, 5307,42741, 1710, 1626, 8327, 8326, 2375, 8340, 8325,
+ 7615, 7612,19074,19071,10696,10693, 4562,13166, 8224, 8659,19004,43178,
+15330,21997, 8664, 8226, 2922, 2374, 8223, 8658, 5467,  955, 6059,  953,
+ 5464,  959, 6056,  957, 8661, 8663, 8218, 8221,14243,14242,16236,16235,
+32298,32297, 8076, 6069,42820,42819, 8383,10641,19007,10640, 6755,19006,
+ 6754,15343,22008, 7135, 5491,42828, 2373, 8387, 8386, 7793, 7792,19130,
+19129,10758,10757,19123,42907,43185,43523,42818,42906, 8672, 8675, 1503,
+ 6071, 5483, 1507,32302, 7134, 5490, 8080, 6089,19017,43192,43191,43528,
+43190,43527,42827,42913, 8385, 7791, 7790,19128,19127,10756,10755,10651,
+19016,10648, 6766,19013, 6763, 8233, 8236,42911,42825, 5497, 1549, 6093,
+ 1539, 5496, 1548, 6092, 1538,15069,21779,15332,21999,15083,21793,15090,
+21800,15088,21798,15674,22221,15557,22127,15556,22126,15559,22129,15555,
+22125,15078,21788,15080,21790,15076,21786,15554,22124,15562,22132,15553,
+22123,15552,22122,15074,21784,15073,21783,15184,21867,15949,22485,15948,
+22484,15988,15219,22525,21900,27872,27463,15985,15216,27869,22522,21897,
+27460,27857,27448,27849,27440,25615,27633,27608,21778,15068,27834,27425,
+27765,27606,15970,15201,22507,21882,27833,27424,15969,15200,27899,27898,
+22541,22540,22506,21881,27490,27489,16004,16003,27832,27423,21916,21915,
+15235,15234,27897,27488
+};
+
+
+const int s_nDataSize3 = 24772;
+unsigned int s_Data3[24772] = {
+//Output priorities (total = 24772):
+10, 9, 12, 6, 11, 14, 4, 1, 7, 5, 2, 3, 13, 8, 0,
+0, 1, 2, 219, 218, 76, 217, 216, 77, 1, 0, 74, 78, 79, 75,
+70, 71, 72, 68, 73, 69, 310, 299, 296, 331, 297, 332, 114, 26, 298,
+340, 330, 336, 338, 339, 62, 112, 328, 334, 329, 335, 113, 337, 327, 333,
+115, 60, 27, 61, 63, 273, 215, 36, 213, 31, 35, 39, 319, 312, 320,
+323, 324, 343, 157, 345, 28, 178, 32, 59, 269, 58, 309, 305, 275, 271,
+308, 304, 34, 117, 181, 129, 154, 211, 30, 38, 177, 193, 55, 130, 268,
+33, 303, 174, 29, 37, 119, 212, 143, 188, 66, 270, 141, 183, 194, 179,
+126, 261, 190, 267, 344, 346, 272, 189, 173, 274, 51, 322, 321, 342, 315,
+214, 311, 14, 57, 223, 348, 125, 176, 192, 317, 280, 314, 165, 160, 175,
+326, 127, 17, 247, 172, 262, 5, 231, 99, 138, 124, 54, 301, 325, 167,
+15, 43, 205, 47, 122, 147, 292, 295, 83, 106, 86, 87, 220, 131, 347,
+293, 150, 209, 233, 67, 116, 148, 156, 171, 180, 191, 256, 195, 341, 128,
+277, 291, 281, 289, 294, 313, 102, 46, 103, 207, 229, 236, 240, 224, 227,
+249, 170, 49, 251, 258, 318, 133, 197, 278, 2, 56, 252, 265, 254, 20,
+142, 151, 316, 164, 121, 162, 41, 107, 139, 203, 288, 302, 48, 52, 110,
+53, 64, 4, 16, 284, 135, 307, 3, 40, 155, 202, 23, 93, 22, 92,
+290, 65, 210, 50, 98, 208, 94, 123, 137, 187, 225, 7, 10, 120, 109,
+263, 287, 186, 108, 152, 264, 90, 253, 96, 97, 136, 200, 118, 140, 300,
+306, 185, 6, 11, 89, 259, 85, 101, 132, 196, 24, 45, 260, 244, 91,
+18, 104, 232, 19, 44, 105, 184, 21, 84, 226, 250, 283, 279, 286, 158,
+248, 257, 255, 80, 169, 13, 100, 81, 168, 199, 238, 9, 12, 82, 182,
+201, 266, 146, 204, 230, 239, 241, 159, 221, 285, 134, 88, 242, 246, 8,
+144, 222, 149, 161, 228, 237, 276, 95, 206, 282, 163, 198, 243, 235, 245,
+42, 166, 25, 111, 145, 153, 234, 13, 0, 1, 8, 3, 11, 7, 9,
+2, 12, 4, 6, 5, 10, 0, 61, 62, 0, 2, 3, 5, 6, 8,
+15, 17, 1, 4, 7, 9, 10, 11, 12, 13, 14, 16, 18, 19, 20,
+21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 63, 64, 65, 66, 67,
+68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 4, 5,
+2, 0, 1, 3, 7, 10, 8, 11, 6, 9, 97, 100, 22, 123, 124,
+125, 98, 101, 40, 39, 66, 72, 75, 69, 68, 74, 21, 41, 67, 73,
+77, 30, 71, 23, 106, 36, 54, 55, 63, 96, 32, 99, 58, 59, 65,
+38, 107, 27, 17, 56, 57, 64, 70, 76, 29, 15, 31, 122, 102, 25,
+48, 49, 50, 51, 52, 53, 26, 28, 103, 37, 127, 104, 120, 121, 24,
+33, 46, 47, 62, 112, 113, 116, 105, 20, 13, 126, 128, 35, 34, 19,
+42, 43, 44, 45, 60, 61, 18, 79, 84, 91, 16, 14, 82, 89, 94,
+85, 119, 83, 88, 95, 118, 78, 90, 81, 86, 93, 12, 80, 87, 92,
+108, 109, 110, 111, 114, 115, 117, 148, 542, 149, 147, 303, 531, 555, 573,
+574, 532, 556, 150, 153, 155, 578, 304, 560, 536, 151, 154, 157, 534, 558,
+576, 533, 538, 557, 575, 547, 551, 570, 305, 568, 306, 540, 541, 544, 546,
+550, 553, 562, 564, 565, 571, 552, 554, 572, 535, 559, 577, 537, 561, 569,
+539, 543, 545, 548, 549, 563, 566, 567, 308, 307, 152, 156, 158, 382, 144,
+128, 145, 438, 446, 450, 458, 462, 470, 474, 482, 492, 500, 504, 510, 516,
+522, 530, 204, 394, 528, 381, 397, 480, 498, 396, 400, 436, 444, 448, 456,
+460, 468, 472, 490, 502, 508, 514, 520, 286, 388, 393, 294, 403, 273, 384,
+385, 387, 391, 399, 408, 313, 317, 347, 354, 414, 419, 426, 25, 88, 127,
+130, 198, 275, 336, 483, 126, 281, 283, 341, 432, 299, 325, 390, 402, 415,
+416, 417, 418, 427, 428, 116, 124, 134, 142, 221, 229, 298, 479, 486, 497,
+527, 24, 87, 227, 311, 315, 329, 353, 506, 512, 518, 30, 34, 41, 196,
+300, 484, 48, 104, 186, 191, 264, 335, 343, 363, 234, 276, 441, 443, 453,
+455, 465, 467, 477, 495, 525, 222, 269, 476, 494, 524, 395, 89, 140, 413,
+420, 425, 481, 499, 505, 511, 517, 529, 200, 257, 327, 398, 401, 440, 445,
+452, 457, 464, 469, 32, 36, 42, 47, 345, 365, 435, 442, 447, 454, 459,
+466, 471, 478, 489, 496, 501, 507, 513, 519, 526, 202, 323, 146, 170, 177,
+179, 248, 255, 368, 380, 206, 122, 132, 258, 279, 288, 296, 349, 375, 434,
+46, 114, 165, 180, 201, 219, 243, 250, 297, 405, 429, 33, 38, 43, 172,
+203, 208, 346, 392, 404, 410, 485, 488, 183, 216, 261, 348, 386, 430, 20,
+26, 65, 100, 131, 162, 167, 174, 182, 188, 189, 194, 210, 218, 240, 252,
+260, 266, 272, 284, 360, 372, 383, 423, 12, 17, 57, 92, 99, 129, 213,
+215, 230, 231, 278, 291, 293, 339, 389, 406, 411, 422, 15, 60, 62, 97,
+117, 119, 135, 199, 224, 225, 236, 245, 267, 302, 321, 326, 377, 407, 102,
+137, 175, 274, 431, 412, 421, 424, 173, 238, 246, 251, 253, 262, 270, 282,
+366, 370, 378, 437, 439, 449, 451, 461, 463, 473, 475, 491, 493, 503, 509,
+515, 521, 523, 0, 1, 81, 82, 106, 160, 168, 184, 185, 192, 193, 263,
+271, 277, 322, 358, 22, 28, 31, 40, 67, 98, 103, 105, 138, 254, 316,
+319, 355, 328, 10, 14, 49, 52, 59, 70, 73, 90, 112, 133, 220, 228,
+232, 233, 301, 309, 314, 331, 333, 337, 344, 351, 35, 37, 44, 163, 342,
+409, 433, 487, 259, 27, 29, 39, 50, 161, 164, 176, 178, 181, 187, 190,
+197, 205, 239, 241, 242, 324, 332, 359, 361, 362, 371, 373, 374, 6, 7,
+45, 55, 56, 75, 77, 79, 80, 108, 109, 159, 166, 169, 171, 195, 217,
+237, 247, 249, 256, 265, 268, 280, 334, 340, 350, 357, 367, 369, 379, 2,
+3, 9, 18, 19, 21, 23, 53, 63, 64, 66, 68, 72, 76, 83, 84,
+93, 95, 96, 101, 107, 111, 120, 121, 123, 125, 139, 141, 143, 212, 244,
+290, 295, 310, 312, 318, 320, 330, 338, 352, 356, 4, 5, 8, 11, 13,
+51, 54, 58, 61, 69, 71, 74, 78, 85, 86, 94, 110, 113, 115, 136,
+207, 209, 211, 214, 223, 226, 235, 285, 287, 289, 292, 364, 376, 16, 91,
+118, 0, 3, 19, 149, 96, 20, 150, 5, 1, 6, 4, 2, 147, 93,
+91, 145, 148, 95, 146, 85, 55, 66, 76, 59, 73, 81, 51, 61, 64,
+54, 58, 92, 94, 63, 173, 62, 86, 65, 75, 60, 74, 82, 56, 52,
+53, 57, 171, 167, 160, 159, 170, 72, 141, 162, 172, 28, 68, 29, 140,
+168, 27, 70, 126, 139, 69, 163, 89, 137, 166, 71, 169, 129, 142, 164,
+116, 135, 143, 90, 67, 113, 121, 165, 161, 131, 123, 125, 133, 30, 7,
+138, 10, 117, 119, 11, 120, 127, 134, 130, 132, 115, 124, 114, 136, 9,
+118, 33, 77, 157, 158, 8, 12, 88, 155, 156, 34, 78, 99, 97, 128,
+36, 44, 87, 35, 43, 15, 13, 17, 122, 21, 23, 25, 144, 37, 45,
+47, 103, 32, 42, 80, 39, 49, 83, 108, 40, 50, 84, 38, 46, 48,
+31, 41, 79, 18, 98, 22, 24, 26, 14, 16, 105, 107, 100, 152, 111,
+109, 104, 101, 110, 112, 106, 153, 102, 151, 154, 0, 1, 3, 4, 2,
+12, 13, 10, 11, 14, 9, 6, 5, 7, 8, 21, 24, 23, 22, 20,
+19, 15, 16, 17, 18, 0, 1, 3, 2, 108, 109, 139, 153, 122, 96,
+178, 97, 126, 95, 101, 100, 94, 174, 140, 172, 175, 173, 5, 36, 154,
+88, 83, 80, 35, 161, 151, 19, 11, 6, 147, 143, 34, 176, 123, 37,
+169, 170, 171, 163, 164, 165, 166, 167, 168, 155, 156, 157, 158, 159, 160,
+82, 162, 177, 152, 81, 111, 7, 12, 20, 128, 4, 93, 21, 64, 13,
+148, 60, 62, 118, 10, 18, 33, 144, 30, 48, 135, 149, 86, 114, 99,
+124, 129, 130, 131, 61, 63, 65, 8, 14, 16, 22, 24, 26, 28, 73,
+75, 77, 90, 56, 72, 74, 76, 78, 51, 53, 55, 57, 59, 67, 69,
+71, 79, 89, 91, 50, 52, 54, 58, 66, 68, 70, 92, 107, 39, 41,
+43, 45, 47, 110, 103, 105, 120, 145, 127, 38, 40, 42, 44, 46, 137,
+102, 104, 106, 31, 32, 49, 9, 15, 17, 23, 29, 87, 25, 27, 150,
+141, 142, 84, 85, 146, 98, 116, 119, 133, 115, 121, 136, 132, 125, 117,
+112, 113, 138, 134, 2, 0, 1, 3, 8, 6, 7, 4, 5, 9, 10,
+0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+15, 16, 2, 1, 4, 8, 7, 9, 6, 0, 5, 3, 10, 109, 107,
+108, 97, 105, 28, 30, 21, 81, 26, 32, 106, 20, 24, 35, 22, 34,
+96, 104, 62, 27, 111, 11, 18, 23, 36, 83, 37, 12, 95, 17, 46,
+56, 25, 40, 42, 87, 89, 14, 16, 13, 29, 103, 82, 110, 15, 19,
+31, 33, 102, 38, 66, 67, 68, 69, 70, 71, 72, 85, 41, 115, 117,
+91, 93, 94, 99, 101, 43, 73, 86, 88, 114, 116, 50, 52, 74, 76,
+77, 78, 79, 39, 113, 44, 45, 47, 48, 49, 51, 53, 54, 55, 57,
+58, 59, 60, 61, 63, 64, 65, 75, 80, 84, 90, 92, 98, 100, 112,
+0, 1, 20, 17, 18, 12, 19, 16, 21, 15, 23, 14, 22, 13, 0,
+6, 5, 11, 3, 9, 2, 8, 1, 7, 4, 10, 3, 4, 11, 14,
+17, 32, 0, 1, 2, 5, 6, 7, 8, 9, 10, 12, 13, 15, 16,
+18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33,
+34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 2, 3, 0, 1,
+15, 13, 17, 21, 77, 76, 33, 30, 34, 110, 105, 114, 118, 31, 32,
+35, 101, 100, 16, 131, 12, 14, 130, 135, 132, 112, 120, 116, 111, 115,
+119, 79, 117, 113, 121, 20, 133, 80, 134, 78, 81, 44, 109, 49, 47,
+124, 46, 28, 48, 126, 26, 87, 89, 90, 88, 6, 5, 7, 9, 11,
+19, 36, 38, 40, 42, 86, 91, 18, 4, 10, 39, 8, 37, 41, 43,
+45, 60, 127, 27, 61, 106, 129, 59, 108, 128, 53, 54, 57, 58, 62,
+50, 29, 56, 63, 52, 55, 107, 122, 123, 125, 51, 64, 65, 66, 67,
+68, 69, 70, 71, 72, 73, 74, 75, 82, 83, 84, 85, 92, 93, 94,
+95, 96, 97, 98, 99, 102, 103, 104, 23, 25, 24, 22, 175, 174, 176,
+162, 158, 165, 124, 166, 15, 155, 126, 160, 120, 121, 122, 123, 125, 127,
+128, 129, 153, 157, 171, 152, 163, 170, 96, 97, 108, 0, 3, 6, 9,
+12, 66, 69, 72, 75, 78, 81, 130, 131, 150, 151, 156, 159, 161, 168,
+169, 173, 177, 154, 164, 167, 172, 1, 2, 4, 5, 7, 8, 10, 11,
+13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+59, 60, 61, 62, 63, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77,
+79, 80, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+95, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112,
+113, 114, 115, 116, 117, 118, 119, 132, 133, 134, 135, 136, 137, 138, 139,
+140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 178, 179, 0, 1, 2,
+8, 6, 7, 3, 5, 4, 0, 1305, 1308, 540, 545, 558, 563, 564, 569,
+570, 575, 576, 581, 582, 587, 588, 593, 594, 599, 600, 605, 606, 611, 612,
+617, 618, 623, 624, 629, 630, 635, 636, 641, 642, 647, 648, 653, 654, 657,
+662, 663, 668, 669, 672, 677, 678, 681, 684, 687, 690, 0, 1, 2, 3,
+4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
+109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
+169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
+184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
+199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
+214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
+229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
+244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258,
+259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
+274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
+289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303,
+304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318,
+319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
+334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348,
+349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363,
+364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378,
+379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393,
+394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408,
+409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423,
+424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438,
+439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453,
+454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468,
+469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483,
+484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498,
+499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513,
+514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528,
+529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 541, 542, 543, 544,
+546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 559, 560, 561,
+562, 565, 566, 567, 568, 571, 572, 573, 574, 577, 578, 579, 580, 583, 584,
+585, 586, 589, 590, 591, 592, 595, 596, 597, 598, 601, 602, 603, 604, 607,
+608, 609, 610, 613, 614, 615, 616, 619, 620, 621, 622, 625, 626, 627, 628,
+631, 632, 633, 634, 637, 638, 639, 640, 643, 644, 645, 646, 649, 650, 651,
+652, 655, 656, 658, 659, 660, 661, 664, 665, 666, 667, 670, 671, 673, 674,
+675, 676, 679, 680, 682, 683, 685, 686, 688, 689, 691, 692, 693, 694, 695,
+696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710,
+711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725,
+726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740,
+741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755,
+756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770,
+771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785,
+786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800,
+801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815,
+816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830,
+831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845,
+846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860,
+861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875,
+876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890,
+891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905,
+906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920,
+921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935,
+936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950,
+951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965,
+966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980,
+981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995,
+996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010,
+1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025,
+1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040,
+1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055,
+1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070,
+1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085,
+1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100,
+1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115,
+1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1130,
+1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145,
+1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160,
+1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175,
+1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190,
+1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205,
+1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220,
+1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235,
+1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250,
+1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265,
+1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280,
+1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295,
+1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1306, 1307, 1309, 1310, 158, 161,
+164, 167, 170, 173, 74, 77, 86, 89, 0, 3, 12, 15, 24, 27, 36,
+39, 48, 51, 60, 63, 110, 113, 122, 125, 134, 137, 146, 149, 76, 88,
+156, 160, 162, 165, 169, 171, 2, 132, 175, 26, 38, 50, 62, 72, 83,
+84, 95, 108, 120, 78, 90, 96, 104, 174, 14, 144, 176, 9, 21, 33,
+45, 57, 69, 79, 81, 91, 93, 98, 106, 119, 131, 143, 155, 59, 71,
+157, 159, 163, 166, 168, 172, 99, 101, 103, 105, 11, 35, 47, 73, 75,
+80, 82, 85, 87, 92, 94, 97, 100, 102, 107, 117, 129, 141, 8, 20,
+23, 32, 44, 56, 68, 114, 126, 138, 150, 153, 179, 186, 191, 198, 180,
+192, 1, 4, 5, 6, 7, 10, 13, 16, 17, 18, 19, 22, 25, 28,
+29, 30, 31, 34, 37, 40, 41, 42, 43, 46, 49, 52, 53, 54, 55,
+58, 61, 64, 65, 66, 67, 70, 109, 111, 112, 115, 116, 118, 121, 123,
+124, 127, 128, 130, 133, 135, 136, 139, 140, 142, 145, 147, 148, 151, 152,
+154, 213, 214, 215, 216, 177, 189, 184, 196, 221, 222, 223, 224, 178, 181,
+182, 183, 185, 187, 188, 190, 193, 194, 195, 197, 199, 200, 201, 202, 203,
+204, 205, 206, 207, 208, 209, 210, 211, 212, 217, 218, 219, 220, 2, 4,
+6, 8, 10, 12, 32, 34, 36, 46, 48, 52, 54, 56, 58, 60, 62,
+64, 86, 87, 88, 105, 106, 107, 108, 109, 112, 113, 115, 117, 121, 1,
+3, 5, 7, 9, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23,
+25, 26, 27, 28, 29, 30, 31, 33, 35, 37, 38, 39, 40, 41, 42,
+43, 44, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 66, 67,
+68, 71, 73, 75, 76, 78, 79, 80, 82, 83, 84, 92, 93, 94, 96,
+97, 98, 99, 100, 101, 102, 103, 104, 110, 111, 114, 116, 118, 119, 120,
+122, 124, 126, 127, 129, 131, 141, 143, 145, 146, 148, 150, 152, 153, 156,
+166, 167, 170, 173, 174, 176, 180, 182, 184, 186, 0, 22, 24, 50, 69,
+70, 72, 74, 77, 81, 85, 89, 90, 91, 95, 123, 125, 128, 130, 132,
+133, 134, 135, 136, 137, 138, 139, 140, 142, 144, 147, 149, 151, 154, 155,
+157, 158, 159, 160, 161, 162, 163, 164, 165, 168, 169, 171, 172, 175, 177,
+178, 179, 181, 183, 185, 122, 85, 89, 92, 106, 118, 136, 148, 156, 164,
+27, 35, 37, 38, 52, 57, 62, 67, 71, 83, 55, 65, 68, 121, 26,
+53, 63, 66, 80, 82, 105, 114, 119, 123, 137, 143, 14, 25, 30, 31,
+100, 28, 117, 108, 134, 3, 12, 34, 36, 39, 40, 45, 46, 51, 59,
+60, 61, 73, 74, 75, 76, 77, 78, 84, 86, 87, 88, 90, 91, 93,
+94, 95, 110, 112, 115, 116, 120, 127, 128, 130, 132, 141, 142, 152, 175,
+58, 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 16,
+17, 18, 19, 20, 21, 22, 23, 24, 29, 32, 33, 41, 42, 43, 44,
+47, 48, 49, 50, 54, 56, 64, 69, 70, 72, 79, 81, 96, 97, 98,
+99, 101, 102, 103, 104, 107, 109, 111, 113, 124, 125, 126, 129, 131, 133,
+135, 138, 139, 140, 144, 145, 146, 147, 149, 150, 151, 153, 154, 155, 157,
+158, 159, 160, 161, 162, 163, 165, 166, 167, 168, 169, 170, 171, 172, 173,
+174, 176, 177, 23, 29, 5, 24, 25, 26, 27, 28, 30, 31, 0, 1,
+2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+18, 19, 20, 21, 22, 32, 83, 84, 96, 99, 100, 16, 85, 98, 18,
+26, 27, 37, 40, 49, 52, 17, 51, 55, 57, 97, 8, 3, 19, 9,
+50, 56, 58, 10, 53, 72, 82, 87, 89, 91, 14, 118, 129, 12, 81,
+86, 88, 90, 130, 11, 20, 21, 22, 23, 24, 25, 28, 29, 30, 31,
+32, 33, 34, 35, 36, 43, 67, 68, 69, 93, 95, 41, 45, 47, 4,
+5, 6, 13, 38, 117, 128, 71, 0, 1, 2, 15, 39, 92, 94, 65,
+70, 122, 123, 127, 7, 42, 44, 46, 48, 54, 59, 60, 61, 62, 63,
+64, 66, 105, 106, 109, 110, 111, 112, 113, 114, 121, 124, 126, 73, 74,
+75, 76, 77, 78, 79, 80, 101, 102, 103, 104, 107, 108, 115, 116, 119,
+120, 125, 18, 24, 5, 7, 9, 13, 0, 1, 2, 3, 4, 6, 8,
+10, 11, 12, 14, 15, 16, 17, 19, 20, 21, 22, 23, 25, 26, 27,
+28, 29, 30, 38, 37, 3, 2, 39, 4, 40, 5, 109, 110, 111, 99,
+107, 97, 105, 140, 141, 142, 0, 98, 106, 1, 100, 108, 34, 35, 36,
+10, 11, 42, 46, 50, 54, 58, 62, 66, 70, 13, 17, 21, 30, 6,
+88, 90, 96, 102, 113, 115, 121, 123, 125, 135, 137, 139, 9, 14, 18,
+22, 33, 44, 48, 52, 56, 60, 64, 68, 72, 116, 126, 130, 43, 47,
+51, 55, 59, 63, 67, 71, 85, 91, 93, 103, 80, 82, 83, 73, 75,
+76, 119, 129, 133, 12, 16, 20, 31, 7, 41, 45, 49, 53, 57, 61,
+65, 69, 117, 127, 131, 87, 89, 95, 101, 112, 114, 120, 122, 124, 134,
+136, 138, 86, 92, 94, 104, 118, 128, 132, 79, 81, 84, 74, 77, 78,
+8, 15, 19, 23, 32, 24, 25, 28, 26, 27, 29, 0, 1, 2, 3,
+4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
+109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 34, 5, 6, 7,
+8, 9, 10, 11, 12, 33, 47, 2, 4, 19, 20, 21, 36, 37, 38,
+40, 41, 0, 1, 3, 13, 14, 15, 16, 17, 18, 22, 23, 24, 25,
+26, 27, 28, 29, 30, 31, 32, 35, 39, 42, 43, 44, 45, 46, 48,
+49, 50, 144, 145, 0, 141, 142, 143, 155, 154, 139, 140, 146, 147, 150,
+151, 76, 82, 83, 84, 85, 86, 87, 158, 131, 77, 132, 159, 23, 24,
+25, 26, 27, 28, 32, 33, 73, 79, 91, 95, 1, 3, 5, 12, 13,
+14, 15, 16, 17, 18, 19, 20, 21, 22, 29, 30, 31, 34, 102, 104,
+106, 108, 112, 113, 114, 115, 116, 117, 118, 119, 138, 37, 39, 41, 43,
+48, 50, 52, 54, 2, 4, 6, 7, 8, 9, 10, 11, 36, 38, 40,
+42, 44, 45, 46, 47, 56, 57, 58, 59, 60, 62, 64, 66, 68, 70,
+72, 74, 75, 78, 80, 81, 88, 89, 90, 92, 93, 94, 96, 97, 98,
+100, 103, 105, 107, 109, 137, 160, 161, 162, 35, 49, 51, 53, 55, 61,
+63, 65, 67, 69, 71, 99, 101, 110, 111, 120, 121, 122, 123, 124, 125,
+126, 127, 128, 129, 130, 133, 134, 135, 136, 148, 149, 152, 153, 156, 157,
+4, 11, 5, 6, 7, 8, 10, 9, 12, 17, 18, 19, 21, 2, 3,
+0, 1, 13, 14, 15, 16, 20, 28, 32, 34, 38, 40, 22, 23, 24,
+25, 26, 27, 29, 30, 31, 33, 35, 36, 37, 39, 41, 73, 69, 95,
+11, 72, 14, 12, 13, 93, 71, 74, 94, 87, 81, 86, 79, 60, 96,
+98, 88, 59, 82, 97, 44, 46, 54, 68, 92, 100, 45, 53, 67, 43,
+91, 99, 80, 89, 77, 1, 3, 9, 5, 6, 7, 8, 70, 28, 83,
+22, 34, 42, 49, 51, 57, 17, 23, 29, 37, 63, 19, 25, 31, 39,
+48, 50, 52, 56, 58, 62, 64, 66, 84, 76, 90, 78, 75, 85, 4,
+0, 2, 10, 20, 26, 32, 36, 40, 15, 61, 16, 18, 24, 30, 35,
+38, 47, 55, 65, 21, 27, 33, 41, 0, 1, 2, 3, 4, 5, 6,
+7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+22, 23, 24, 25, 26, 40, 42, 3, 1, 51, 5, 49, 48, 22, 24,
+4, 2, 52, 50, 76, 78, 80, 94, 96, 98, 23, 47, 26, 27, 63,
+64, 65, 70, 71, 21, 77, 79, 81, 17, 20, 33, 37, 41, 43, 57,
+55, 56, 58, 59, 60, 61, 62, 18, 19, 25, 32, 36, 95, 97, 99,
+0, 38, 39, 54, 67, 69, 73, 75, 85, 87, 91, 93, 53, 66, 84,
+86, 90, 89, 6, 7, 11, 12, 13, 82, 83, 68, 72, 74, 92, 8,
+9, 10, 14, 15, 16, 28, 29, 30, 31, 34, 35, 44, 45, 46, 88,
+0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+120, 121, 122, 123, 124, 125, 0, 1, 2, 3, 4, 5, 6, 7, 8,
+9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+84, 85, 86, 87, 88, 89, 90, 91, 92, 0, 1, 2, 3, 4, 5,
+6, 7, 8, 1, 3, 43, 0, 2, 4, 5, 6, 7, 8, 9, 10,
+11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+41, 42, 44, 45, 46, 89, 90, 0, 1, 2, 3, 4, 5, 6, 7,
+8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+83, 84, 85, 86, 87, 88, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+100, 101, 102, 103, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8,
+9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 186, 189, 174,
+185, 179, 180, 177, 181, 188, 191, 60, 63, 175, 183, 176, 184, 64, 61,
+62, 65, 178, 182, 187, 190, 130, 142, 154, 166, 104, 110, 116, 13, 24,
+36, 78, 122, 136, 148, 160, 172, 7, 18, 30, 84, 102, 108, 114, 105,
+111, 117, 120, 123, 74, 86, 98, 107, 113, 119, 125, 1, 9, 20, 32,
+44, 45, 55, 75, 99, 103, 109, 115, 0, 6, 19, 31, 42, 43, 54,
+72, 73, 85, 96, 97, 137, 149, 161, 173, 2, 46, 47, 56, 76, 77,
+100, 101, 127, 133, 139, 145, 151, 157, 163, 169, 8, 21, 33, 87, 106,
+112, 118, 121, 124, 128, 129, 140, 141, 152, 153, 3, 4, 15, 26, 38,
+48, 49, 50, 51, 57, 58, 66, 67, 68, 69, 80, 90, 91, 92, 93,
+126, 131, 134, 138, 143, 146, 150, 155, 158, 162, 167, 170, 10, 11, 22,
+23, 34, 35, 88, 89, 135, 147, 159, 171, 5, 12, 14, 16, 17, 25,
+27, 28, 29, 37, 39, 40, 41, 52, 53, 59, 70, 71, 79, 81, 82,
+83, 94, 95, 132, 144, 156, 164, 165, 168, 756, 759, 761, 104, 105, 640,
+647, 700, 107, 757, 760, 102, 222, 224, 310, 420, 431, 441, 460, 468, 491,
+494, 501, 558, 571, 654, 666, 683, 722, 7, 10, 31, 34, 60, 65, 162,
+165, 178, 434, 467, 477, 480, 550, 569, 657, 671, 682, 718, 751, 13, 37,
+54, 175, 181, 262, 265, 313, 385, 465, 551, 563, 641, 645, 701, 719, 253,
+316, 333, 339, 364, 365, 369, 371, 436, 439, 461, 496, 499, 505, 514, 520,
+522, 577, 585, 588, 598, 601, 608, 617, 622, 685, 727, 733, 223, 240, 191,
+709, 92, 115, 144, 199, 248, 252, 290, 307, 338, 372, 382, 410, 475, 508,
+513, 515, 527, 547, 566, 567, 572, 580, 587, 590, 595, 604, 606, 615, 619,
+688, 716, 725, 730, 735, 739, 747, 11, 16, 22, 23, 35, 40, 46, 47,
+52, 53, 59, 64, 88, 89, 94, 103, 118, 121, 124, 138, 143, 149, 163,
+164, 179, 184, 190, 202, 205, 208, 225, 244, 245, 250, 259, 268, 280, 281,
+284, 285, 291, 322, 328, 332, 340, 373, 379, 388, 400, 401, 404, 405, 411,
+421, 426, 428, 429, 437, 442, 450, 455, 457, 469, 478, 481, 488, 497, 502,
+529, 530, 536, 537, 540, 553, 564, 570, 625, 626, 630, 635, 637, 643, 655,
+656, 668, 670, 678, 681, 691, 692, 699, 703, 704, 724, 738, 749, 750, 753,
+560, 574, 723, 85, 331, 470, 101, 217, 633, 642, 697, 742, 745, 754, 19,
+43, 48, 187, 324, 97, 218, 296, 416, 130, 137, 166, 226, 241, 271, 279,
+319, 327, 391, 399, 440, 482, 142, 283, 325, 403, 443, 453, 485, 758, 0,
+24, 67, 298, 336, 346, 464, 489, 504, 507, 510, 516, 518, 521, 523, 524,
+535, 552, 559, 573, 576, 579, 582, 583, 591, 592, 594, 599, 602, 603, 607,
+611, 614, 616, 620, 623, 632, 644, 649, 651, 661, 663, 667, 669, 684, 687,
+696, 708, 720, 726, 729, 732, 736, 1, 2, 3, 4, 5, 6, 8, 9,
+12, 14, 15, 17, 18, 20, 21, 25, 26, 27, 28, 29, 30, 32, 33,
+36, 38, 39, 41, 42, 44, 45, 49, 50, 51, 55, 56, 57, 58, 61,
+62, 63, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+80, 81, 82, 83, 84, 86, 87, 90, 91, 93, 95, 96, 98, 99, 100,
+106, 108, 109, 110, 111, 112, 113, 114, 116, 117, 119, 120, 122, 123, 125,
+126, 127, 128, 129, 131, 132, 133, 134, 135, 136, 139, 140, 141, 145, 146,
+147, 148, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 167,
+168, 169, 170, 171, 172, 173, 174, 176, 177, 180, 182, 183, 185, 186, 188,
+189, 192, 193, 194, 195, 196, 197, 198, 200, 201, 203, 204, 206, 207, 209,
+210, 211, 212, 213, 214, 215, 216, 219, 220, 221, 227, 228, 229, 230, 231,
+232, 233, 234, 235, 236, 237, 238, 239, 242, 243, 246, 247, 249, 251, 254,
+255, 256, 257, 258, 260, 261, 263, 264, 266, 267, 269, 270, 272, 273, 274,
+275, 276, 277, 278, 282, 286, 287, 288, 289, 292, 293, 294, 295, 297, 299,
+300, 301, 302, 303, 304, 305, 306, 308, 309, 311, 312, 314, 315, 317, 318,
+320, 321, 323, 326, 329, 330, 334, 335, 337, 341, 342, 343, 344, 345, 347,
+348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362,
+363, 366, 367, 368, 370, 374, 375, 376, 377, 378, 380, 381, 383, 384, 386,
+387, 389, 390, 392, 393, 394, 395, 396, 397, 398, 402, 406, 407, 408, 409,
+412, 413, 414, 415, 417, 418, 419, 422, 423, 424, 425, 427, 430, 432, 433,
+435, 438, 444, 445, 446, 447, 448, 449, 451, 452, 454, 456, 458, 459, 462,
+463, 466, 471, 472, 473, 474, 476, 479, 483, 484, 486, 487, 490, 492, 493,
+495, 498, 500, 503, 506, 509, 511, 512, 517, 519, 525, 526, 528, 531, 532,
+533, 534, 538, 539, 541, 542, 543, 544, 545, 546, 548, 549, 554, 555, 556,
+557, 561, 562, 565, 568, 575, 578, 581, 584, 586, 589, 593, 596, 597, 600,
+605, 609, 610, 612, 613, 618, 621, 624, 627, 628, 629, 631, 634, 636, 638,
+639, 646, 648, 650, 652, 653, 658, 659, 660, 662, 664, 665, 672, 673, 674,
+675, 676, 677, 679, 680, 686, 689, 690, 693, 694, 695, 698, 702, 705, 706,
+707, 710, 711, 712, 713, 714, 715, 717, 721, 728, 731, 734, 737, 740, 741,
+743, 744, 746, 748, 752, 755, 325, 326, 324, 15, 258, 103, 123, 3, 9,
+124, 331, 14, 259, 16, 2, 8, 337, 102, 335, 340, 4, 10, 17, 120,
+246, 247, 276, 333, 334, 33, 72, 128, 338, 5, 11, 76, 105, 127, 0,
+13, 74, 73, 122, 1, 75, 7, 300, 336, 364, 6, 12, 228, 235, 263,
+265, 270, 280, 291, 106, 297, 77, 135, 162, 169, 192, 199, 201, 214, 216,
+225, 260, 262, 104, 306, 316, 339, 170, 200, 223, 341, 137, 160, 190, 203,
+215, 218, 141, 150, 157, 171, 180, 187, 312, 313, 317, 39, 125, 143, 148,
+158, 173, 178, 188, 308, 318, 107, 322, 362, 35, 91, 97, 109, 299, 230,
+272, 293, 244, 256, 289, 323, 367, 38, 121, 302, 303, 311, 327, 245, 257,
+261, 290, 305, 234, 264, 279, 34, 36, 79, 85, 115, 126, 298, 307, 309,
+319, 328, 57, 63, 69, 198, 229, 271, 292, 82, 88, 90, 96, 108, 118,
+304, 320, 329, 37, 41, 80, 86, 116, 301, 332, 139, 159, 164, 168, 189,
+194, 205, 213, 217, 220, 222, 40, 136, 145, 167, 177, 197, 202, 212, 227,
+18, 27, 48, 363, 237, 267, 282, 196, 240, 241, 252, 253, 285, 286, 142,
+147, 152, 155, 156, 172, 175, 182, 185, 186, 310, 321, 330, 346, 347, 348,
+355, 138, 163, 165, 193, 195, 204, 210, 219, 226, 131, 132, 208, 250, 251,
+278, 314, 315, 357, 365, 140, 146, 179, 206, 211, 20, 29, 50, 161, 166,
+191, 221, 224, 269, 368, 26, 44, 47, 58, 64, 70, 81, 87, 117, 144,
+151, 153, 174, 181, 183, 93, 99, 111, 232, 274, 295, 59, 65, 71, 133,
+134, 149, 154, 176, 184, 209, 350, 361, 239, 242, 254, 284, 287, 268, 56,
+62, 68, 78, 84, 94, 100, 112, 114, 92, 98, 110, 238, 283, 55, 61,
+67, 349, 236, 243, 255, 266, 281, 288, 19, 24, 28, 42, 45, 49, 129,
+130, 207, 248, 249, 277, 354, 359, 360, 233, 275, 296, 352, 353, 22, 31,
+52, 54, 60, 66, 83, 89, 95, 101, 113, 119, 342, 345, 366, 231, 273,
+294, 25, 43, 46, 23, 32, 53, 343, 351, 358, 21, 30, 51, 344, 356,
+0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
+195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
+225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
+255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269,
+270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
+300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329,
+330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344,
+345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359,
+360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374,
+375, 376, 377, 19, 29, 33, 45, 86, 88, 90, 92, 18, 27, 31, 47,
+82, 103, 37, 41, 55, 87, 11, 35, 39, 43, 49, 51, 53, 57, 61,
+63, 89, 91, 105, 109, 114, 20, 9, 13, 107, 28, 30, 32, 34, 46,
+48, 78, 84, 133, 135, 93, 112, 134, 136, 36, 40, 62, 66, 80, 38,
+42, 44, 50, 52, 54, 56, 58, 64, 127, 131, 137, 1, 15, 16, 21,
+22, 102, 111, 113, 128, 132, 138, 23, 25, 59, 68, 70, 94, 69, 3,
+4, 6, 7, 10, 104, 106, 108, 110, 121, 123, 67, 24, 26, 60, 122,
+124, 72, 76, 81, 96, 85, 74, 98, 129, 83, 125, 0, 2, 5, 8,
+12, 14, 17, 71, 73, 75, 77, 79, 95, 97, 99, 100, 126, 65, 130,
+101, 118, 116, 120, 115, 117, 119, 219, 220, 221, 127, 131, 135, 139, 228,
+229, 230, 231, 232, 233, 234, 235, 222, 223, 224, 225, 226, 227, 236, 237,
+238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
+253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 275,
+276, 277, 278, 9, 13, 17, 21, 25, 29, 36, 40, 44, 48, 49, 56,
+60, 64, 68, 72, 76, 80, 84, 171, 176, 180, 184, 0, 1, 2, 3,
+4, 5, 6, 7, 8, 10, 11, 12, 14, 15, 16, 18, 19, 20, 22,
+23, 24, 26, 27, 28, 30, 31, 32, 33, 34, 35, 37, 38, 39, 41,
+42, 43, 45, 46, 47, 50, 51, 52, 53, 54, 55, 57, 58, 59, 61,
+62, 63, 65, 66, 67, 69, 70, 71, 73, 74, 75, 77, 78, 79, 81,
+82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
+113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 128,
+129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 143, 144, 145, 146,
+147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+162, 163, 164, 165, 166, 167, 168, 169, 170, 172, 173, 174, 175, 177, 178,
+179, 181, 182, 183, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
+196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
+211, 212, 213, 214, 215, 216, 217, 218, 267, 268, 269, 270, 271, 272, 273,
+274, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 1, 2,
+3, 4, 0, 8, 12, 11, 102, 127, 6, 5, 101, 7, 128, 4, 3,
+10, 1, 2, 0, 9, 92, 90, 97, 114, 94, 95, 99, 112, 111, 123,
+116, 118, 120, 121, 125, 98, 89, 91, 96, 93, 100, 113, 24, 34, 16,
+36, 14, 22, 13, 21, 33, 18, 26, 30, 115, 117, 124, 119, 122, 126,
+17, 25, 29, 104, 19, 27, 31, 106, 28, 20, 32, 15, 23, 35, 54,
+56, 110, 51, 72, 88, 38, 40, 49, 58, 60, 64, 66, 74, 81, 105,
+107, 37, 39, 50, 52, 57, 59, 63, 65, 71, 73, 82, 87, 42, 43,
+45, 48, 61, 67, 70, 76, 77, 79, 83, 86, 53, 55, 41, 44, 46,
+47, 62, 68, 69, 75, 78, 80, 84, 85, 109, 103, 108, 7, 8, 6,
+9, 17, 10, 28, 26, 24, 50, 68, 4, 34, 5, 0, 23, 46, 2,
+18, 33, 1, 85, 19, 58, 62, 70, 29, 31, 35, 3, 25, 27, 47,
+48, 49, 51, 11, 90, 30, 32, 36, 40, 41, 42, 43, 44, 45, 12,
+13, 14, 15, 16, 20, 21, 22, 37, 38, 39, 52, 53, 54, 55, 56,
+57, 59, 60, 61, 63, 64, 65, 66, 67, 69, 71, 72, 73, 74, 75,
+76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 88, 125,
+101, 103, 124, 127, 134, 135, 25, 29, 37, 45, 165, 177, 163, 180, 138,
+142, 113, 24, 28, 36, 40, 41, 44, 48, 49, 58, 59, 60, 61, 66,
+67, 68, 69, 70, 71, 72, 73, 89, 92, 93, 145, 148, 149, 94, 105,
+109, 151, 154, 161, 173, 96, 99, 100, 102, 104, 107, 108, 111, 114, 115,
+116, 118, 119, 120, 122, 123, 126, 132, 133, 136, 137, 140, 141, 155, 156,
+159, 160, 164, 169, 171, 172, 175, 176, 179, 181, 182, 183, 0, 1, 2,
+3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+18, 19, 20, 21, 22, 23, 26, 27, 30, 31, 32, 33, 34, 35, 38,
+39, 42, 43, 46, 47, 50, 51, 52, 53, 54, 55, 56, 57, 62, 63,
+64, 65, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+87, 90, 91, 95, 97, 98, 106, 110, 112, 117, 121, 128, 129, 130, 131,
+139, 143, 144, 146, 147, 150, 152, 153, 157, 158, 162, 166, 167, 168, 170,
+174, 178, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 0, 1, 2, 3,
+4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
+109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
+169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
+184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
+199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
+214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
+229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
+244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258,
+259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
+274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
+289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303,
+304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318,
+319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
+334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348,
+349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363,
+364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378,
+379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393,
+394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408,
+409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423,
+424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438,
+439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453,
+454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468,
+469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483,
+484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498,
+499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513,
+514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528,
+529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543,
+544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558,
+559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573,
+574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588,
+589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603,
+604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618,
+619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633,
+634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648,
+649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663,
+664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678,
+679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693,
+694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708,
+709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723,
+724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738,
+739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753,
+754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768,
+769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783,
+784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798,
+799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813,
+814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828,
+829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843,
+844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858,
+859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873,
+874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888,
+889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903,
+904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918,
+919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933,
+934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948,
+949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963,
+964, 965, 966, 967, 968, 969, 970, 971, 306, 146, 158, 174, 216, 233, 27,
+29, 121, 123, 125, 127, 144, 150, 152, 173, 188, 218, 295, 299, 307, 0,
+1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 30, 31, 32,
+33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 122, 124,
+126, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+142, 143, 145, 147, 148, 149, 151, 153, 154, 155, 156, 157, 159, 160, 161,
+162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 175, 176, 177, 178,
+179, 180, 181, 182, 183, 184, 185, 186, 187, 189, 190, 191, 192, 193, 194,
+195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+210, 211, 212, 213, 214, 215, 217, 219, 220, 221, 222, 223, 224, 225, 226,
+227, 228, 229, 230, 231, 232, 234, 235, 236, 237, 238, 239, 240, 241, 242,
+243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257,
+258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272,
+273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287,
+288, 289, 290, 291, 292, 293, 294, 296, 297, 298, 300, 301, 302, 303, 304,
+305, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321,
+322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336,
+337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351,
+352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366,
+367, 368, 369, 370, 371, 372, 373, 374, 76, 106, 77, 107, 125, 115, 126,
+60, 61, 71, 59, 96, 99, 110, 89, 70, 58, 25, 27, 33, 35, 86,
+87, 72, 75, 79, 94, 112, 95, 100, 73, 74, 78, 101, 102, 105, 109,
+88, 26, 32, 34, 103, 104, 108, 24, 97, 98, 113, 114, 44, 64, 69,
+36, 38, 41, 43, 47, 54, 57, 63, 66, 111, 37, 39, 40, 42, 45,
+46, 55, 56, 62, 65, 67, 68, 90, 92, 5, 11, 9, 84, 8, 4,
+10, 2, 48, 50, 52, 81, 82, 0, 6, 12, 14, 85, 80, 83, 49,
+51, 53, 91, 93, 118, 121, 124, 3, 17, 18, 21, 22, 29, 30, 1,
+7, 13, 15, 116, 119, 122, 129, 16, 19, 20, 23, 28, 31, 117, 120,
+123, 127, 128, 130, 3, 4, 5, 6, 25, 26, 27, 28, 29, 33, 41,
+54, 61, 62, 99, 101, 105, 106, 107, 108, 133, 134, 0, 7, 30, 83,
+86, 87, 88, 90, 91, 92, 93, 135, 136, 137, 1, 2, 31, 32, 34,
+100, 102, 103, 104, 119, 132, 138, 139, 140, 16, 21, 22, 23, 24, 44,
+51, 64, 65, 66, 67, 69, 71, 72, 73, 74, 75, 76, 8, 9, 10,
+11, 12, 13, 14, 15, 35, 36, 42, 43, 46, 48, 49, 50, 52, 60,
+63, 77, 78, 79, 80, 81, 82, 85, 89, 94, 95, 96, 97, 98, 109,
+110, 111, 112, 113, 114, 115, 120, 121, 17, 18, 19, 20, 37, 38, 39,
+40, 45, 47, 53, 55, 56, 57, 58, 59, 68, 70, 84, 116, 117, 118,
+122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 141, 142, 143, 144, 145,
+146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
+161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+176, 177, 178, 179, 180, 181, 182, 49, 18, 16, 17, 42, 45, 15, 8,
+46, 39, 6, 48, 7, 9, 10, 41, 44, 5, 40, 43, 30, 47, 51,
+52, 25, 19, 20, 21, 22, 23, 24, 3, 4, 29, 31, 32, 33, 34,
+35, 36, 37, 38, 71, 73, 11, 12, 13, 14, 50, 70, 0, 1, 2,
+26, 27, 28, 60, 62, 69, 61, 63, 64, 65, 72, 75, 76, 54, 55,
+56, 57, 58, 59, 66, 68, 81, 82, 83, 84, 86, 74, 53, 67, 77,
+78, 79, 80, 85, 87, 88, 0, 1, 2, 3, 4, 5, 6, 7, 8,
+9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+114, 115, 116, 117, 118, 119, 120, 121, 122, 0, 1, 2, 3, 4, 5,
+6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+21, 100, 31, 35, 41, 33, 30, 34, 40, 82, 81, 103, 47, 32, 15,
+99, 46, 9, 21, 8, 69, 65, 67, 14, 62, 57, 58, 60, 80, 56,
+20, 11, 97, 10, 85, 86, 1, 22, 26, 36, 16, 17, 78, 79, 105,
+108, 5, 24, 28, 38, 44, 45, 59, 61, 63, 70, 109, 111, 0, 4,
+25, 29, 39, 50, 51, 54, 55, 71, 72, 73, 74, 75, 76, 77, 95,
+96, 101, 102, 104, 110, 98, 18, 19, 83, 84, 89, 23, 27, 37, 42,
+43, 48, 113, 2, 3, 6, 7, 12, 13, 49, 52, 53, 87, 88, 90,
+91, 92, 93, 94, 106, 107, 112, 64, 66, 68, 5, 4, 0, 39, 48,
+17, 8, 6, 7, 77, 78, 75, 76, 79, 80, 16, 15, 73, 56, 55,
+74, 40, 41, 42, 60, 9, 10, 11, 12, 13, 14, 59, 43, 62, 1,
+2, 3, 44, 61, 58, 68, 22, 23, 28, 35, 36, 45, 46, 47, 57,
+67, 69, 70, 71, 19, 18, 20, 21, 24, 25, 26, 27, 29, 30, 31,
+32, 33, 34, 37, 38, 49, 50, 51, 52, 53, 54, 63, 64, 65, 66,
+72, 81, 82, 83, 84, 34, 44, 71, 32, 43, 30, 35, 72, 33, 11,
+10, 39, 37, 13, 38, 42, 36, 12, 41, 31, 8, 9, 40, 50, 69,
+55, 20, 24, 28, 135, 1, 5, 15, 136, 70, 46, 51, 114, 115, 45,
+3, 7, 17, 113, 116, 54, 128, 129, 134, 138, 0, 4, 14, 26, 19,
+23, 27, 48, 62, 63, 68, 123, 124, 125, 126, 131, 132, 29, 49, 59,
+60, 66, 127, 130, 133, 86, 110, 119, 57, 58, 65, 83, 87, 103, 111,
+122, 18, 22, 82, 102, 61, 64, 67, 21, 25, 52, 2, 6, 16, 75,
+76, 85, 90, 95, 99, 100, 109, 120, 56, 73, 74, 77, 78, 79, 80,
+81, 84, 88, 89, 91, 92, 93, 94, 96, 97, 98, 101, 104, 105, 106,
+107, 108, 112, 117, 118, 121, 137, 47, 53, 4, 5, 0, 1, 2, 3,
+7, 8, 6, 9, 10, 20, 25, 27, 18, 19, 21, 23, 24, 26, 28,
+0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+15, 16, 17, 22, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+40, 41, 76, 96, 112, 109, 110, 94, 95, 49, 73, 56, 61, 65, 68,
+102, 30, 37, 38, 40, 41, 44, 45, 47, 48, 55, 57, 59, 60, 79,
+82, 88, 89, 90, 91, 92, 98, 100, 105, 108, 111, 0, 1, 2, 3,
+4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33, 34,
+35, 36, 39, 42, 43, 46, 50, 51, 52, 53, 54, 58, 62, 63, 64,
+66, 67, 69, 70, 71, 72, 74, 75, 77, 78, 80, 81, 83, 84, 85,
+86, 87, 93, 97, 99, 101, 103, 104, 106, 107, 113, 91, 42, 46, 77,
+26, 8, 78, 41, 43, 44, 47, 68, 5, 30, 45, 89, 90, 48, 49,
+50, 51, 25, 76, 93, 14, 70, 88, 4, 23, 24, 29, 59, 63, 75,
+79, 92, 97, 0, 1, 2, 6, 7, 15, 16, 17, 20, 21, 27, 31,
+32, 33, 34, 35, 36, 62, 64, 67, 72, 61, 66, 71, 86, 94, 12,
+74, 55, 58, 60, 81, 83, 3, 9, 10, 11, 13, 18, 19, 22, 28,
+37, 38, 39, 40, 53, 56, 65, 69, 73, 82, 84, 85, 52, 54, 57,
+80, 87, 95, 96, 1, 8, 10, 13, 12, 6, 2, 0, 11, 9, 5,
+25, 7, 19, 43, 44, 45, 32, 33, 34, 50, 51, 52, 26, 22, 23,
+3, 4, 28, 15, 36, 37, 49, 30, 31, 29, 14, 20, 21, 24, 27,
+17, 39, 46, 16, 35, 53, 38, 40, 41, 42, 18, 47, 48, 0, 1,
+2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 49, 310, 312,
+314, 269, 271, 273, 275, 277, 279, 281, 297, 299, 0, 1, 2, 3, 4,
+5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 50,
+51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
+141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170,
+171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185,
+186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200,
+201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
+216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230,
+231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
+246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260,
+261, 262, 263, 264, 265, 266, 267, 268, 270, 272, 274, 276, 278, 280, 282,
+283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 298,
+300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 311, 313, 315, 316, 317,
+318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332,
+333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347,
+348, 349, 350, 351, 352, 353, 354, 355, 179, 200, 161, 175, 243, 100, 104,
+196, 198, 223, 227, 176, 203, 212, 215, 162, 163, 247, 160, 174, 216, 218,
+158, 172, 96, 157, 166, 170, 197, 199, 217, 219, 159, 173, 178, 201, 99,
+101, 103, 105, 177, 202, 213, 214, 98, 102, 92, 108, 112, 116, 120, 124,
+128, 132, 184, 192, 208, 180, 188, 204, 239, 249, 221, 225, 154, 165, 169,
+51, 53, 55, 57, 59, 63, 67, 71, 75, 79, 83, 87, 95, 119, 123,
+127, 131, 138, 142, 146, 150, 183, 191, 207, 236, 241, 245, 250, 61, 65,
+69, 73, 77, 81, 85, 89, 93, 109, 113, 117, 140, 144, 148, 152, 8,
+9, 14, 15, 20, 21, 50, 52, 54, 56, 91, 107, 111, 115, 121, 125,
+129, 133, 134, 135, 136, 137, 141, 145, 149, 153, 155, 164, 168, 181, 187,
+189, 195, 205, 211, 58, 62, 66, 70, 74, 78, 82, 86, 118, 122, 126,
+130, 0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 16, 17,
+18, 19, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+60, 64, 68, 72, 76, 80, 84, 88, 139, 143, 147, 151, 186, 194, 210,
+222, 226, 238, 242, 246, 248, 94, 97, 156, 167, 171, 228, 230, 90, 106,
+110, 114, 220, 224, 237, 240, 244, 251, 182, 185, 190, 193, 206, 209, 229,
+231, 232, 233, 234, 235, 24, 51, 54, 111, 25, 52, 55, 112, 13, 31,
+34, 37, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 26, 27, 28, 29, 30,
+32, 33, 35, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+49, 50, 53, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 113, 114,
+115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 0,
+1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+16, 17, 8, 16, 18, 7, 26, 30, 34, 104, 14, 15, 17, 19, 22,
+48, 68, 73, 75, 79, 11, 1, 6, 20, 28, 32, 36, 38, 40, 44,
+98, 102, 103, 105, 106, 115, 2, 13, 21, 23, 49, 53, 54, 55, 56,
+57, 58, 60, 61, 64, 66, 67, 69, 76, 83, 85, 95, 100, 10, 0,
+3, 4, 5, 9, 12, 24, 25, 27, 29, 31, 33, 35, 37, 39, 41,
+42, 43, 45, 46, 47, 50, 51, 52, 59, 62, 63, 65, 70, 71, 72,
+74, 77, 78, 80, 81, 82, 84, 86, 87, 88, 89, 90, 91, 92, 93,
+94, 96, 97, 99, 101, 107, 108, 109, 110, 111, 112, 113, 114, 116, 117,
+118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 121, 120, 103, 101, 102,
+86, 111, 124, 27, 44, 100, 10, 13, 82, 92, 98, 78, 88, 94, 42,
+40, 9, 11, 12, 14, 80, 84, 90, 96, 45, 119, 122, 46, 48, 50,
+52, 104, 106, 109, 110, 1, 4, 18, 25, 29, 32, 19, 34, 22, 5,
+8, 38, 107, 39, 16, 17, 21, 26, 30, 33, 43, 87, 125, 41, 83,
+93, 99, 2, 24, 28, 31, 35, 53, 55, 81, 91, 97, 105, 0, 3,
+7, 6, 15, 20, 23, 36, 37, 47, 49, 51, 54, 56, 57, 58, 59,
+60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+75, 76, 77, 79, 85, 89, 95, 108, 112, 113, 114, 115, 116, 117, 118,
+123, 161, 57, 60, 95, 169, 165, 171, 0, 160, 40, 168, 164, 39, 58,
+59, 96, 1, 2, 50, 55, 64, 75, 85, 92, 97, 71, 77, 81, 87,
+6, 16, 30, 44, 181, 170, 49, 56, 63, 76, 86, 91, 98, 174, 180,
+5, 15, 29, 43, 72, 78, 82, 88, 113, 126, 194, 195, 198, 158, 159,
+162, 163, 114, 125, 144, 145, 166, 167, 192, 193, 156, 47, 48, 51, 52,
+53, 54, 61, 62, 65, 66, 83, 84, 89, 90, 93, 94, 99, 100, 101,
+102, 103, 104, 130, 131, 132, 133, 134, 135, 152, 175, 176, 177, 67, 69,
+73, 79, 105, 3, 4, 7, 8, 13, 14, 17, 18, 19, 20, 25, 26,
+27, 28, 31, 32, 33, 34, 37, 38, 41, 42, 45, 46, 68, 70, 74,
+80, 106, 117, 118, 142, 143, 178, 179, 138, 9, 140, 147, 148, 107, 109,
+111, 139, 141, 146, 149, 182, 183, 184, 185, 190, 191, 115, 119, 121, 123,
+137, 155, 157, 187, 189, 197, 10, 11, 12, 21, 22, 23, 24, 35, 36,
+108, 110, 112, 116, 120, 122, 124, 127, 128, 129, 136, 150, 151, 153, 154,
+173, 186, 188, 196, 172, 37, 36, 33, 32, 35, 34, 4, 2, 6, 0,
+44, 45, 47, 46, 42, 43, 39, 41, 40, 38, 5, 7, 3, 1, 51,
+17, 11, 15, 19, 9, 13, 10, 14, 18, 16, 23, 24, 27, 28, 31,
+8, 12, 20, 22, 21, 25, 26, 29, 30, 49, 48, 50, 179, 176, 165,
+178, 171, 175, 174, 177, 162, 168, 190, 188, 202, 200, 33, 75, 93, 51,
+81, 87, 173, 164, 157, 114, 3, 6, 156, 15, 21, 27, 170, 167, 123,
+63, 69, 39, 45, 57, 199, 211, 172, 208, 205, 214, 181, 184, 203, 196,
+169, 198, 201, 160, 161, 137, 163, 125, 209, 119, 183, 215, 166, 207, 204,
+213, 197, 191, 206, 210, 182, 212, 187, 185, 53, 83, 89, 192, 186, 193,
+136, 180, 194, 130, 142, 154, 155, 148, 149, 131, 143, 116, 32, 74, 92,
+122, 101, 107, 110, 113, 98, 104, 71, 65, 41, 47, 59, 2, 11, 14,
+20, 26, 195, 189, 147, 150, 151, 145, 133, 127, 139, 126, 138, 132, 144,
+117, 159, 52, 82, 88, 158, 120, 96, 102, 108, 99, 105, 111, 30, 72,
+90, 8, 5, 9, 0, 124, 97, 103, 109, 12, 18, 24, 48, 78, 84,
+66, 60, 70, 62, 35, 77, 95, 68, 42, 50, 80, 86, 17, 23, 29,
+36, 54, 38, 44, 56, 152, 153, 64, 40, 58, 46, 128, 140, 129, 134,
+135, 141, 146, 106, 100, 112, 121, 7, 4, 115, 118, 34, 61, 76, 94,
+16, 22, 28, 37, 43, 55, 49, 79, 85, 67, 1, 13, 19, 25, 31,
+73, 91, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+102, 103, 104, 105, 106, 107, 108, 109, 110, 2, 5, 8, 11, 14, 17,
+20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62,
+65, 68, 0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18,
+19, 21, 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40,
+42, 43, 45, 46, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63,
+64, 66, 67, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+53, 52, 72, 71, 73, 70, 97, 98, 96, 99, 68, 80, 82, 74, 77,
+78, 5, 22, 25, 41, 49, 1, 9, 17, 95, 103, 102, 104, 75, 76,
+79, 66, 69, 93, 67, 94, 81, 83, 84, 85, 86, 87, 88, 89, 90,
+91, 106, 107, 92, 100, 101, 105, 32, 34, 38, 12, 15, 54, 58, 62,
+39, 14, 36, 57, 61, 65, 31, 35, 47, 29, 45, 42, 28, 44, 30,
+46, 18, 16, 55, 59, 63, 40, 21, 26, 50, 3, 7, 11, 19, 0,
+4, 8, 33, 37, 20, 23, 24, 27, 43, 48, 51, 2, 6, 10, 13,
+56, 60, 64, 0, 2, 1, 11, 5, 6, 12, 3, 4, 9, 10, 14,
+7, 8, 13, 21, 36, 18, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+32, 33, 34, 35, 37, 15, 16, 22, 17, 19, 20, 0, 1, 0, 1,
+2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 48, 5, 34, 63,
+4, 62, 50, 47, 49, 33, 35, 36, 29, 3, 6, 61, 64, 54, 58,
+45, 32, 51, 56, 60, 70, 57, 40, 46, 11, 55, 59, 44, 53, 65,
+72, 14, 15, 17, 20, 22, 27, 66, 68, 69, 71, 26, 19, 67, 1,
+9, 12, 7, 25, 24, 28, 30, 31, 10, 8, 16, 18, 21, 23, 52,
+0, 2, 41, 42, 43, 13, 37, 38, 39, 107, 15, 97, 100, 101, 105,
+99, 33, 81, 79, 80, 34, 92, 95, 86, 48, 118, 41, 43, 119, 35,
+36, 37, 75, 102, 103, 104, 23, 24, 25, 26, 31, 4, 17, 19, 21,
+22, 27, 38, 39, 52, 56, 58, 64, 70, 72, 82, 47, 87, 51, 55,
+57, 77, 78, 98, 116, 117, 28, 29, 30, 32, 40, 42, 5, 7, 9,
+93, 96, 1, 2, 3, 6, 8, 10, 12, 54, 59, 65, 66, 68, 69,
+71, 73, 74, 76, 83, 84, 89, 90, 106, 109, 111, 112, 114, 44, 45,
+46, 49, 50, 11, 53, 16, 18, 20, 0, 13, 14, 60, 61, 62, 63,
+67, 85, 88, 91, 94, 108, 110, 113, 115, 13, 4, 46, 47, 2, 6,
+37, 38, 43, 51, 54, 55, 58, 67, 69, 0, 1, 3, 5, 7, 8,
+9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 39, 40, 41,
+42, 44, 45, 48, 49, 50, 52, 53, 56, 57, 59, 60, 61, 62, 63,
+64, 65, 66, 68, 70, 71, 72, 73, 74, 75, 7, 4, 6, 5, 2,
+3, 9, 8, 0, 1, 23, 22, 24, 25, 14, 26, 30, 34, 10, 11,
+12, 13, 15, 16, 17, 18, 19, 20, 21, 27, 28, 29, 31, 32, 33,
+35, 36, 37, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+25, 26, 27, 28, 29, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+70, 71, 72, 73, 0, 1, 2, 3, 4, 4, 0, 1, 2, 3, 5,
+6, 7, 8, 0, 1, 2, 3, 4, 5, 323, 139, 149, 165, 207, 234,
+320, 296, 300, 20, 44, 45, 52, 138, 147, 189, 191, 192, 193, 210, 213,
+215, 217, 226, 232, 236, 238, 293, 322, 325, 74, 122, 306, 150, 264, 4,
+5, 197, 201, 117, 172, 188, 195, 203, 222, 244, 245, 265, 271, 291, 292,
+332, 2, 18, 19, 22, 34, 46, 57, 82, 84, 85, 88, 89, 120, 130,
+133, 134, 136, 137, 140, 142, 143, 145, 146, 148, 153, 159, 160, 161, 162,
+166, 169, 173, 184, 185, 209, 211, 219, 228, 229, 231, 237, 240, 242, 243,
+246, 247, 248, 251, 253, 254, 257, 286, 294, 298, 324, 335, 33, 98, 118,
+200, 204, 303, 305, 327, 100, 196, 205, 275, 123, 126, 282, 0, 1, 3,
+6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 21, 23, 24,
+25, 26, 27, 28, 29, 30, 31, 32, 35, 36, 37, 38, 39, 40, 41,
+42, 43, 47, 48, 49, 50, 51, 53, 54, 55, 56, 58, 59, 60, 61,
+62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 75, 76, 77,
+78, 79, 80, 81, 83, 86, 87, 90, 91, 92, 93, 94, 95, 96, 97,
+99, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+115, 116, 119, 121, 124, 125, 127, 128, 129, 131, 132, 135, 141, 144, 151,
+152, 154, 155, 156, 157, 158, 163, 164, 167, 168, 170, 171, 174, 175, 176,
+177, 178, 179, 180, 181, 182, 183, 186, 187, 190, 194, 198, 199, 202, 206,
+208, 212, 214, 216, 218, 220, 221, 223, 224, 225, 227, 230, 233, 235, 239,
+241, 249, 250, 252, 255, 256, 258, 259, 260, 261, 262, 263, 266, 267, 268,
+269, 270, 272, 273, 274, 276, 277, 278, 279, 280, 281, 283, 284, 285, 287,
+288, 289, 290, 295, 297, 299, 301, 302, 304, 307, 308, 309, 310, 311, 312,
+313, 314, 315, 316, 317, 318, 319, 321, 326, 328, 329, 330, 331, 333, 334,
+336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350,
+351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, 1,
+2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+107, 108, 109, 4, 5, 18, 20, 0, 1, 2, 3, 6, 7, 8, 9,
+10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 22, 23, 24, 25, 26,
+0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+115, 116, 117, 118, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+101, 102, 103, 104, 105, 106, 107, 38, 40, 39, 65, 63, 66, 26, 28,
+11, 20, 24, 32, 108, 8, 47, 45, 48, 49, 105, 109, 139, 75, 124,
+18, 22, 30, 34, 111, 102, 114, 118, 77, 123, 133, 1, 5, 17, 46,
+69, 73, 81, 29, 78, 101, 37, 50, 64, 9, 51, 55, 61, 76, 68,
+72, 84, 2, 6, 14, 19, 23, 35, 67, 71, 79, 83, 107, 113, 115,
+117, 137, 147, 36, 10, 27, 53, 57, 59, 135, 13, 103, 104, 126, 3,
+7, 15, 41, 44, 54, 58, 60, 70, 74, 80, 82, 0, 4, 12, 16,
+21, 25, 31, 33, 42, 43, 52, 56, 62, 85, 88, 91, 94, 106, 110,
+112, 116, 119, 120, 121, 122, 125, 127, 128, 129, 130, 131, 132, 134, 136,
+138, 140, 141, 142, 143, 144, 145, 146, 148, 89, 86, 87, 90, 92, 93,
+95, 96, 97, 98, 99, 100, 0, 1, 2, 3, 4, 5, 6, 7, 8,
+9, 10, 11, 12, 1, 2, 4, 32, 36, 38, 3, 34, 28, 31, 35,
+37, 6, 12, 14, 19, 20, 22, 33, 39, 43, 53, 54, 55, 56, 57,
+61, 67, 69, 70, 71, 30, 0, 5, 7, 8, 9, 10, 11, 13, 15,
+16, 17, 18, 21, 23, 24, 25, 26, 27, 29, 40, 41, 42, 44, 45,
+46, 47, 48, 49, 50, 51, 52, 58, 59, 60, 62, 63, 64, 65, 66,
+68, 72, 16, 28, 34, 38, 42, 2, 14, 15, 18, 19, 26, 29, 30,
+31, 32, 33, 40, 43, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10,
+11, 12, 13, 17, 20, 21, 22, 23, 24, 25, 27, 35, 36, 37, 39,
+41, 2, 0, 7, 1, 86, 5, 74, 21, 89, 85, 88, 3, 4, 6,
+51, 23, 111, 70, 56, 90, 98, 27, 78, 53, 68, 80, 87, 116, 12,
+25, 109, 114, 103, 108, 110, 9, 57, 62, 65, 91, 96, 99, 69, 71,
+72, 73, 81, 49, 50, 52, 93, 101, 36, 55, 64, 125, 19, 20, 22,
+106, 41, 8, 11, 13, 29, 34, 37, 54, 102, 107, 118, 123, 126, 14,
+15, 16, 18, 82, 83, 84, 92, 97, 100, 104, 112, 17, 32, 121, 94,
+24, 113, 76, 77, 79, 10, 61, 95, 26, 28, 30, 31, 35, 38, 39,
+40, 46, 58, 59, 60, 63, 66, 67, 75, 105, 115, 117, 119, 120, 124,
+127, 128, 33, 42, 43, 44, 45, 47, 48, 122, 0, 1, 2, 3, 4,
+5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 2, 0, 1, 3, 4,
+5, 6, 7, 8, 82, 11, 26, 19, 75, 6, 9, 47, 54, 66, 73,
+80, 87, 0, 3, 4, 5, 18, 23, 24, 25, 44, 53, 62, 63, 65,
+67, 68, 69, 70, 72, 76, 77, 86, 88, 89, 90, 91, 92, 93, 22,
+10, 15, 21, 49, 58, 50, 59, 83, 1, 2, 7, 8, 12, 13, 14,
+16, 17, 20, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+39, 40, 41, 42, 43, 45, 46, 48, 51, 52, 55, 56, 57, 60, 61,
+64, 71, 74, 78, 79, 81, 84, 85, 0, 1, 0, 1, 34, 2, 12,
+13, 32, 37, 76, 3, 10, 11, 19, 20, 21, 22, 23, 27, 28, 29,
+30, 35, 53, 55, 78, 4, 16, 17, 5, 6, 7, 8, 9, 14, 15,
+18, 24, 25, 26, 31, 33, 36, 38, 39, 40, 41, 42, 43, 44, 45,
+46, 47, 48, 49, 50, 51, 52, 54, 56, 57, 58, 59, 60, 61, 62,
+63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 77, 79,
+80, 81, 82, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+12, 13, 14, 15, 5, 30, 31, 0, 1, 2, 3, 4, 6, 7, 8,
+9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+24, 25, 26, 27, 28, 29, 32, 33, 34, 35, 36, 37, 59, 0, 1,
+2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+32, 33, 34, 35, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61, 62, 63,
+64, 65, 36, 61, 20, 1, 19, 126, 127, 60, 56, 33, 34, 35, 21,
+22, 52, 59, 67, 71, 72, 63, 65, 66, 32, 45, 57, 84, 91, 114,
+125, 64, 0, 2, 3, 68, 70, 73, 26, 46, 53, 54, 55, 58, 115,
+131, 74, 12, 96, 97, 99, 41, 42, 44, 49, 50, 75, 80, 83, 85,
+103, 106, 107, 108, 109, 110, 111, 112, 113, 116, 117, 118, 119, 120, 124,
+13, 62, 76, 77, 78, 86, 128, 129, 94, 23, 24, 25, 27, 28, 29,
+30, 31, 37, 38, 39, 40, 43, 47, 48, 51, 4, 5, 6, 7, 8,
+9, 10, 11, 14, 15, 16, 17, 18, 69, 79, 81, 82, 87, 88, 89,
+90, 92, 93, 95, 98, 100, 101, 102, 104, 105, 121, 122, 123, 130, 132,
+3, 2, 10, 11, 1, 4, 6, 8, 5, 7, 9, 0, 31, 30, 15,
+43, 49, 53, 57, 45, 12, 13, 16, 18, 32, 34, 36, 14, 33, 35,
+37, 21, 23, 17, 19, 20, 22, 24, 25, 26, 27, 28, 29, 42, 48,
+52, 56, 38, 41, 44, 46, 50, 54, 39, 40, 47, 51, 55, 35, 36,
+3, 5, 7, 9, 11, 2, 17, 30, 34, 14, 20, 23, 4, 6, 13,
+16, 18, 19, 22, 24, 25, 31, 32, 33, 8, 10, 12, 15, 21, 0,
+1, 26, 27, 28, 29, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+40, 41, 42, 43, 44, 45, 46, 47, 5, 4, 6, 21, 0, 3, 18,
+16, 15, 17, 9, 12, 20, 7, 14, 19, 8, 10, 11, 13, 1, 2,
+167, 168, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
+133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147,
+148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
+163, 164, 165, 166, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1,
+2, 3, 7, 6, 8, 9, 16, 2, 18, 19, 28, 27, 24, 25, 26,
+17, 3, 20, 22, 21, 23, 13, 0, 4, 14, 1, 5, 12, 10, 11,
+15, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 12, 13,
+14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8,
+9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+69, 70, 71, 72, 73, 18, 22, 28, 35, 53, 54, 57, 59, 0, 1,
+2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+17, 19, 20, 21, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34,
+36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+51, 52, 55, 56, 58, 9, 13, 4, 6, 11, 15, 8, 12, 5, 7,
+10, 14, 2, 3, 0, 1, 0, 3, 4, 7, 1, 2, 5, 6, 8,
+9, 10, 0, 1, 2, 65, 64, 66, 52, 46, 49, 53, 59, 44, 48,
+45, 57, 34, 25, 26, 27, 36, 56, 24, 43, 47, 0, 1, 2, 3,
+4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+19, 20, 21, 22, 23, 28, 29, 30, 31, 32, 33, 35, 37, 38, 39,
+40, 41, 42, 50, 51, 54, 55, 58, 60, 61, 62, 63, 0, 1, 2,
+3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+108, 109, 110, 111, 112, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+40, 41, 42, 43, 44, 45, 46, 47, 48, 0, 1, 2, 3, 4, 5,
+6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+21, 22, 23, 24, 25, 26, 0, 1, 2, 3, 4, 5, 6, 7, 8,
+9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
+159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
+174, 175, 84, 86, 5, 16, 18, 21, 81, 82, 3, 6, 10, 12, 14,
+22, 24, 26, 29, 39, 41, 42, 54, 56, 58, 60, 62, 75, 0, 1,
+2, 4, 7, 8, 9, 11, 13, 15, 17, 19, 20, 23, 25, 27, 28,
+30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 43, 44, 45, 46, 47,
+48, 49, 50, 51, 52, 53, 55, 57, 59, 61, 63, 64, 65, 66, 67,
+68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 83, 85, 0,
+2, 4, 6, 14, 16, 18, 20, 8, 31, 10, 11, 24, 25, 28, 29,
+32, 33, 36, 38, 40, 41, 44, 45, 9, 30, 1, 3, 5, 7, 12,
+13, 15, 17, 19, 21, 22, 23, 26, 27, 34, 35, 37, 39, 42, 43,
+46, 47, 27, 28, 35, 36, 45, 46, 13, 14, 59, 60, 0, 1, 2,
+3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 16, 17, 18, 19,
+20, 21, 22, 23, 24, 25, 26, 29, 30, 31, 32, 33, 34, 37, 38,
+39, 40, 41, 42, 43, 44, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+56, 57, 58, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
+133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147,
+148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
+163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
+178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192,
+193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222,
+223, 224, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+13, 14, 15, 16, 17, 0, 4, 1, 2, 3, 7, 5, 9, 6, 8,
+0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+30, 31, 32, 33, 34, 35, 36, 37, 8, 11, 9, 10, 0, 1, 4,
+5, 2, 3, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+10, 11, 12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
+117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
+147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
+177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
+207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
+222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
+237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
+252, 253, 254, 255, 256, 257, 0, 1, 2, 3, 4, 5, 6, 7, 8,
+9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+35, 1, 2, 20, 29, 32, 33, 34, 0, 3, 4, 5, 6, 7, 8,
+9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24,
+25, 26, 27, 28, 30, 31, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+45, 46, 47, 48, 49, 50, 51, 52, 53, 0, 1, 2, 3, 4, 5,
+6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+36, 37, 38, 39, 40, 0, 1, 0, 1, 2, 3, 4, 5, 0, 1,
+2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
+182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
+197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
+212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
+227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
+242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256,
+257, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+29, 0, 1, 4, 27, 19, 21, 5, 18, 6, 8, 10, 11, 12, 14,
+15, 16, 17, 20, 0, 1, 2, 3, 7, 9, 13, 22, 23, 24, 25,
+26, 28, 29, 30, 31, 32, 33, 34, 35, 0, 1, 2, 3, 4, 0,
+1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+16, 17, 18, 19, 112, 110, 113, 111, 29, 37, 18, 93, 96, 97, 99,
+98, 92, 100, 104, 105, 108, 101, 61, 62, 69, 77, 86, 70, 78, 85,
+68, 76, 87, 60, 54, 55, 59, 30, 38, 73, 81, 90, 94, 19, 14,
+16, 71, 79, 84, 50, 51, 57, 0, 2, 4, 6, 8, 10, 12, 20,
+26, 34, 44, 64, 72, 80, 91, 40, 63, 13, 5, 7, 9, 11, 15,
+1, 3, 39, 21, 48, 49, 56, 95, 74, 82, 89, 31, 25, 33, 45,
+65, 43, 103, 106, 107, 109, 17, 52, 53, 58, 28, 36, 41, 23, 27,
+35, 47, 42, 66, 22, 24, 32, 46, 67, 75, 83, 88, 102, 6, 7,
+0, 1, 3, 5, 2, 4, 50, 48, 52, 54, 56, 2, 6, 14, 18,
+22, 26, 30, 34, 49, 53, 55, 57, 58, 59, 60, 0, 1, 3, 4,
+5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 19, 20, 21, 23,
+24, 25, 27, 28, 29, 31, 32, 33, 35, 36, 37, 38, 39, 40, 41,
+42, 43, 44, 45, 46, 47, 51, 23, 24, 25, 26, 16, 18, 20, 22,
+15, 17, 19, 21, 6, 8, 10, 12, 14, 0, 2, 1, 3, 4, 5,
+11, 7, 9, 13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
+116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
+131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 1, 0,
+2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1,
+2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+47, 48, 49, 50, 51, 52, 53, 54, 55, 0, 1, 2, 3, 4, 5,
+6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 112, 114, 19, 61, 70,
+18, 111, 3, 5, 6, 66, 82, 109, 110, 113, 58, 102, 104, 31, 35,
+36, 37, 38, 71, 77, 86, 93, 95, 96, 108, 47, 25, 45, 46, 53,
+55, 75, 40, 41, 42, 52, 60, 83, 84, 24, 26, 11, 12, 22, 23,
+28, 30, 57, 63, 65, 69, 81, 90, 106, 32, 33, 34, 49, 50, 51,
+72, 73, 78, 79, 87, 88, 94, 4, 7, 8, 9, 10, 20, 21, 29,
+39, 43, 44, 48, 54, 56, 59, 62, 64, 67, 68, 74, 76, 80, 89,
+91, 92, 100, 101, 115, 116, 16, 99, 13, 14, 15, 17, 27, 85, 97,
+98, 103, 105, 107, 117, 7, 10, 19, 0, 1, 2, 3, 4, 5, 6,
+8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 0, 1, 2, 3, 4,
+5, 7, 17, 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12,
+13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 0, 1, 0, 7, 11,
+5, 6, 10, 3, 4, 1, 2, 8, 9, 12, 0, 1, 2, 3, 4,
+0, 1, 2, 3, 4, 1, 3, 0, 2, 4, 5, 6, 7, 8, 9,
+10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4,
+5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+35, 36, 0, 1, 75, 78, 76, 15, 79, 77, 8, 85, 14, 0, 4,
+10, 81, 83, 84, 87, 12, 80, 82, 11, 9, 2, 6, 86, 36, 38,
+37, 13, 1, 5, 3, 7, 49, 22, 24, 28, 32, 50, 58, 63, 66,
+71, 23, 25, 29, 33, 47, 48, 51, 52, 53, 54, 46, 17, 19, 16,
+20, 21, 26, 27, 30, 31, 34, 35, 39, 40, 41, 42, 43, 44, 45,
+55, 56, 57, 59, 60, 61, 62, 64, 65, 67, 68, 69, 70, 72, 73,
+74, 18, 11, 22, 1, 3, 5, 7, 9, 10, 13, 15, 16, 18, 20,
+26, 28, 0, 2, 4, 6, 8, 12, 14, 17, 19, 21, 23, 24, 25,
+27, 29, 47, 45, 43, 48, 42, 44, 49, 46, 33, 11, 27, 31, 37,
+38, 63, 17, 18, 21, 23, 25, 29, 32, 35, 77, 83, 97, 0, 5,
+9, 15, 16, 19, 39, 41, 53, 69, 20, 22, 24, 26, 28, 30, 34,
+36, 76, 82, 96, 102, 103, 1, 3, 7, 13, 40, 51, 57, 61, 67,
+71, 73, 75, 81, 87, 95, 101, 106, 107, 70, 2, 4, 6, 8, 10,
+12, 14, 50, 52, 54, 55, 56, 58, 59, 60, 62, 64, 65, 66, 68,
+72, 74, 78, 79, 80, 84, 85, 86, 88, 89, 90, 91, 92, 93, 94,
+98, 99, 100, 104, 105, 108, 109, 0, 1, 46, 43, 47, 42, 3, 44,
+5, 20, 4, 18, 24, 26, 30, 38, 34, 36, 7, 9, 22, 2, 45,
+21, 40, 19, 35, 37, 39, 32, 12, 14, 28, 10, 16, 41, 25, 27,
+31, 6, 8, 23, 33, 11, 17, 13, 15, 29, 52, 50, 53, 48, 49,
+51, 0, 1, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5,
+6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
+141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170,
+171, 172, 173, 174, 175, 176, 177, 178, 179, 0, 1, 2, 3, 4, 5,
+6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+111, 112, 113, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+27, 28, 29, 30, 31, 32, 33, 34, 35, 5, 15, 19, 27, 31, 35,
+39, 43, 96, 104, 120, 121, 131, 0, 1, 2, 10, 12, 24, 25, 46,
+47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 76, 77, 78, 79, 80,
+81, 82, 83, 84, 85, 86, 87, 88, 90, 91, 93, 95, 97, 99, 101,
+103, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
+119, 122, 123, 124, 125, 126, 127, 128, 129, 130, 132, 133, 134, 135, 136,
+137, 138, 140, 144, 148, 152, 156, 160, 164, 3, 4, 6, 7, 8, 9,
+11, 13, 14, 16, 17, 18, 20, 21, 22, 23, 26, 28, 29, 30, 32,
+33, 34, 36, 37, 38, 40, 41, 42, 44, 45, 57, 58, 59, 60, 61,
+62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 89,
+92, 94, 98, 100, 102, 139, 141, 142, 143, 145, 146, 147, 149, 150, 151,
+153, 154, 155, 157, 158, 159, 161, 162, 163, 165, 166, 36, 57, 60, 65,
+68, 114, 135, 156, 161, 162, 165, 170, 176, 179, 182, 183, 188, 191, 194,
+197, 198, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+28, 29, 30, 31, 32, 33, 34, 35, 37, 38, 39, 40, 41, 42, 43,
+44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 58, 59,
+61, 62, 63, 64, 66, 67, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+108, 109, 110, 111, 112, 113, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 136, 137, 138, 139,
+140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
+155, 157, 158, 159, 160, 163, 164, 166, 167, 168, 169, 171, 172, 173, 174,
+175, 177, 178, 180, 181, 184, 185, 186, 187, 189, 190, 192, 193, 195, 196,
+199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
+214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
+229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
+244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258,
+259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
+274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
+289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303,
+304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318,
+319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
+334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348,
+349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363,
+364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378,
+379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393,
+394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408,
+409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423,
+424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438,
+439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453,
+454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468,
+469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483,
+484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498,
+499, 500, 501, 502, 503, 504, 505, 506, 0, 1, 2, 3, 4, 5, 6,
+7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
+175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
+205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234,
+235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
+250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279,
+280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309,
+310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
+325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339,
+340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354,
+355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369,
+370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384,
+385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399,
+400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414,
+415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429,
+430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444,
+445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459,
+460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474,
+475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489,
+490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504,
+505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519,
+520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534,
+535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549,
+550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564,
+565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579,
+580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594,
+595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609,
+610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624,
+625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639,
+640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654,
+655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669,
+0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+15, 16, 17, 18, 19, 20, 21, 0, 1, 2, 3, 4, 5, 6, 7,
+8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
+113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
+143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
+158, 159, 160, 161, 162, 163, 164, 165, 166, 0, 1, 2, 3, 4, 5,
+6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1, 2, 3, 4, 5,
+0, 3, 5, 10, 16, 18, 94, 4, 6, 7, 8, 17, 37, 44, 48,
+51, 56, 66, 69, 75, 79, 82, 84, 88, 98, 99, 102, 1, 2, 9,
+11, 12, 13, 14, 15, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+29, 30, 31, 32, 33, 34, 35, 36, 38, 39, 40, 41, 42, 43, 45,
+46, 47, 49, 50, 52, 53, 54, 55, 57, 58, 59, 60, 61, 62, 63,
+64, 65, 67, 68, 70, 71, 72, 73, 74, 76, 77, 78, 80, 81, 83,
+85, 86, 87, 89, 90, 91, 92, 93, 95, 96, 97, 100, 101, 103, 104,
+105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
+81, 18, 24, 33, 69, 83, 19, 25, 35, 71, 0, 1, 2, 3, 4,
+5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21,
+22, 23, 26, 27, 28, 29, 30, 31, 32, 34, 36, 37, 38, 39, 40,
+41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 70, 72,
+73, 74, 75, 76, 77, 78, 79, 80, 82, 84, 85, 86, 87, 88, 89,
+90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+165, 166, 167, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+12, 13, 14, 15, 16, 17, 4, 5, 6, 31, 32, 39, 40, 41, 0,
+1, 2, 3, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 35,
+36, 37, 38, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+129, 130, 131, 132, 133, 134, 135, 136, 0, 1, 3, 22, 23, 26, 34,
+0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+16, 17, 18, 19, 20, 21, 24, 25, 27, 28, 29, 30, 31, 32, 33,
+35, 36, 37, 38, 39, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 0,
+1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+61, 62, 63, 64, 65, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+25, 26, 27, 28, 29, 30, 31, 32, 33, 51, 0, 1, 2, 3, 4,
+5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+50, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 0, 1, 2,
+3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 1,
+2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+77, 74, 75, 92, 93, 116, 143, 144, 149, 14, 15, 34, 35, 36, 37,
+68, 69, 98, 99, 104, 105, 110, 111, 154, 155, 156, 157, 166, 167, 168,
+169, 178, 179, 180, 181, 4, 5, 6, 7, 22, 23, 24, 25, 46, 47,
+50, 51, 56, 57, 60, 61, 80, 82, 85, 87, 121, 122, 123, 124, 133,
+134, 135, 136, 190, 191, 194, 197, 202, 203, 206, 207, 212, 213, 216, 217,
+0, 1, 2, 3, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20,
+21, 26, 27, 28, 29, 30, 31, 32, 33, 38, 39, 40, 41, 42, 43,
+44, 45, 48, 49, 52, 53, 54, 55, 58, 59, 62, 63, 64, 65, 66,
+67, 70, 71, 72, 73, 76, 77, 78, 79, 81, 83, 84, 86, 88, 89,
+90, 91, 94, 95, 96, 97, 100, 101, 102, 103, 106, 107, 108, 109, 112,
+113, 114, 115, 117, 118, 119, 120, 125, 126, 127, 128, 129, 130, 131, 132,
+137, 138, 139, 140, 141, 142, 145, 146, 147, 148, 150, 151, 152, 153, 158,
+159, 160, 161, 162, 163, 164, 165, 170, 171, 172, 173, 174, 175, 176, 177,
+182, 183, 184, 185, 186, 187, 188, 189, 192, 193, 195, 196, 198, 199, 200,
+201, 204, 205, 208, 209, 210, 211, 214, 215, 218, 219, 220, 221, 0, 1,
+2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 0, 1, 2,
+3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
+123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
+138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
+153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
+168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
+183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
+198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212,
+213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
+228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
+243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257,
+258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272,
+273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287,
+288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302,
+303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317,
+318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332,
+333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347,
+348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362,
+363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377,
+0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 0, 1, 2, 3,
+4, 5, 6, 7, 0, 1, 14, 15, 16, 17, 2, 3, 4, 5, 8,
+9, 10, 11, 12, 13, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+28, 29, 30, 31, 32, 33, 11, 2, 5, 10, 8, 4, 9, 1, 7,
+3, 0, 6, 42, 45, 36, 39, 12, 16, 18, 22, 38, 41, 44, 47,
+37, 40, 43, 46, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+11, 13, 14, 15, 17, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29,
+30, 31, 32, 33, 34, 35, 0, 1, 2, 3, 4, 5, 6, 7, 8,
+9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
+159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
+174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+189, 190, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 4, 5,
+6, 8, 1, 3, 0, 2, 7, 9, 0, 1, 2, 3, 4, 5, 6,
+7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
+157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
+202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216,
+217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231,
+232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
+247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261,
+262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276,
+277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306,
+307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321,
+322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336,
+337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351,
+352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366,
+367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381,
+382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396,
+397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411,
+412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426,
+427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441,
+442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456,
+457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471,
+472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486,
+487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501,
+502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516,
+517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531,
+532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546,
+547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561,
+562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576,
+577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591,
+592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606,
+607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621,
+622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636,
+637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651,
+652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666,
+667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681,
+682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696,
+697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711,
+712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726,
+727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741,
+742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756,
+757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771,
+772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786,
+787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801,
+802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816,
+817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831,
+832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846,
+847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861,
+862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876,
+877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891,
+892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906,
+907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921,
+922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936,
+937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951,
+952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966,
+967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981,
+982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996,
+997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011,
+1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026,
+1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041,
+1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056,
+1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071,
+1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086,
+1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101,
+1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116,
+1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1130, 1131,
+1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1146,
+1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161,
+1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176,
+1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191,
+1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206,
+1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221,
+1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236,
+1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251,
+1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266,
+1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281,
+1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296,
+1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311,
+1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1326,
+1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341,
+1342, 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356,
+1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371,
+1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386,
+1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401,
+1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416,
+1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431,
+1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446,
+1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461,
+1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476,
+1477, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487, 1488, 1489, 1490, 1491,
+1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506,
+1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521,
+1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1536,
+1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551,
+1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1565, 1566,
+1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581,
+1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596,
+1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611,
+1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626,
+1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641,
+1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656,
+1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671,
+1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686,
+1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701,
+1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716,
+1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731,
+1732, 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746,
+1747, 1748, 1749, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761,
+1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776,
+1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791,
+1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806,
+1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821,
+1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1834, 1835, 1836,
+1837, 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851,
+1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866,
+1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881,
+1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896,
+1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911,
+1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926,
+1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939, 1940, 1941,
+1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956,
+1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971,
+1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986,
+1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016,
+2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031,
+2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046,
+2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061,
+2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076,
+2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091,
+2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106,
+2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121,
+2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136,
+2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151,
+2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166,
+2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181,
+2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196,
+2197, 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211,
+2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226,
+2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, 2241,
+2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256,
+2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271,
+2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286,
+2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2301,
+2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316,
+2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331,
+2332, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345, 2346,
+2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, 2359, 2360, 2361,
+2362, 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376,
+2377, 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, 2391,
+2392, 2393, 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406,
+2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, 2415, 2416, 2417, 2418, 2419, 2420, 2421,
+2422, 2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, 2431, 2432, 2433, 2434, 2435, 2436,
+2437, 2438, 2439, 2440, 2441, 2442, 2443, 2444, 2445, 2446, 2447, 2448, 2449, 2450, 2451,
+2452, 2453, 2454, 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, 2463, 2464, 2465, 2466,
+2467, 2468, 2469, 2470, 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481,
+2482, 2483, 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2491, 2492, 2493, 2494, 2495, 2496,
+2497, 2498, 2499, 2500, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511,
+2512, 2513, 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526,
+2527, 2528, 2529, 2530, 2531, 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, 2540, 2541,
+2542, 2543, 2544, 2545, 2546, 2547, 2548, 2549, 2550, 2551, 2552, 2553, 2554, 2555, 2556,
+2557, 2558, 2559, 2560, 2561, 2562, 2563, 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571,
+2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, 2580, 2581, 2582, 2583, 2584, 2585, 2586,
+2587, 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, 2596, 2597, 2598, 2599, 2600, 2601,
+2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616,
+2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, 2630, 2631,
+2632, 2633, 2634, 2635, 2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, 2646,
+2647, 2648, 2649, 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661,
+2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676,
+2677, 2678, 2679, 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691,
+2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706,
+2707, 2708, 2709, 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, 2718, 2719, 2720, 2721,
+2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, 2735, 2736,
+2737, 2738, 2739, 2740, 2741, 2742, 2743, 2744, 2745, 2746, 2747, 2748, 2749, 2750, 2751,
+2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766,
+2767, 2768, 2769, 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, 2779, 2780, 2781,
+2782, 2783, 2784, 2785, 2786, 2787, 2788, 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796,
+2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811,
+2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826,
+2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840, 2841,
+2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2856,
+2857, 2858, 2859, 2860, 2861, 2862, 2863, 9, 11, 6, 7, 8, 10, 4, 5,
+0, 1, 2, 3, 0, 2, 10, 3, 6, 1, 9, 11, 4, 8, 7,
+5, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+29, 30, 31, 32, 33, 34, 35, 68, 116, 22, 10, 97, 117, 52, 110,
+7, 19, 111, 115, 6, 18, 0, 74, 88, 12, 48, 108, 99, 109, 38,
+104, 4, 16, 24, 96, 15, 3, 50, 84, 71, 85, 36, 102, 103, 119,
+54, 86, 100, 30, 25, 105, 113, 69, 53, 63, 98, 87, 93, 89, 95,
+9, 21, 62, 114, 5, 17, 26, 55, 2, 14, 65, 8, 20, 64, 92,
+42, 106, 11, 23, 46, 66, 34, 101, 107, 56, 35, 47, 57, 67, 76,
+118, 75, 83, 82, 94, 37, 77, 29, 51, 1, 13, 27, 49, 58, 112,
+39, 59, 28, 70, 44, 73, 80, 81, 32, 72, 31, 43, 33, 40, 41,
+45, 60, 61, 78, 79, 90, 91
+};
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reads library from array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Dar_LibReadNodes()
+{
+    Vec_Int_t * vResult;
+    int i;
+    vResult = Vec_IntAlloc( s_nDataSize1 );
+    for ( i = 0; i < s_nDataSize1; i++ )
+        Vec_IntPush( vResult, s_Data1[i] );
+    return vResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads library from array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Dar_LibReadOuts()
+{
+    Vec_Int_t * vResult;
+    int i;
+    vResult = Vec_IntAlloc( s_nDataSize2 );
+    for ( i = 0; i < s_nDataSize2; i++ )
+        Vec_IntPush( vResult, s_Data2[i] );
+    return vResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads library from array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Dar_LibReadPrios()
+{
+    Vec_Int_t * vResult;
+    int i;
+    vResult = Vec_IntAlloc( s_nDataSize3 );
+    for ( i = 0; i < s_nDataSize3; i++ )
+        Vec_IntPush( vResult, s_Data3[i] );
+    return vResult;
+}
+
+#if 0
+
+#include "base/abc/abc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/**Function*************************************************************
+
+  Synopsis    [Generate arrays.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_NtkGenerateArrays( Abc_Ntk_t * pNtk )
+{
+    extern int Io_WriteAigerEncode( char * pBuffer, int Pos, unsigned x );
+
+    Abc_Obj_t * pObj;
+    int i, Count = 0;
+    assert( Abc_NtkPiNum(pNtk) == 4 );
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( Abc_ObjFanoutNum(Abc_AigConst1(pNtk)) == 0 );
+/*
+    {
+        unsigned char * pBuffer;
+        int Pos, uLit, uLit0, uLit1, Size, Digit;
+
+        Abc_NtkForEachPi( pNtk, pObj, i )
+            pObj->pCopy = (void *)Count++;
+
+        Pos = 0;
+        pBuffer = ABC_ALLOC( char, 200000 );
+        Abc_AigForEachAnd( pNtk, pObj, i )
+        {
+            pObj->pCopy = (void *)Count++;
+            uLit  = ((int)pObj->pCopy << 1);
+            uLit0 = (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj);
+            uLit1 = (((int)Abc_ObjFanin1(pObj)->pCopy) << 1) | Abc_ObjFaninC1(pObj);
+            assert( uLit0 < uLit1 );
+            Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit  - uLit1 );
+            Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 );
+        }
+        // write the buffer
+        Size = 0;
+        for ( i = 0; i < Pos; i++ )
+        {
+            if ( i % 36 == 0 )
+                printf( "\n" );
+
+            Digit = pBuffer[i] & 0xF;
+            if ( Digit < 10 )
+                printf( "%d", Digit );
+            else 
+                printf( "%c", Digit - 10 + 'A' );
+
+
+            Digit = pBuffer[i];
+            Digit >>= 4;
+            if ( Digit < 10 )
+                printf( "%d", Digit );
+            else 
+                printf( "%c", Digit - 10 + 'A' );
+
+        }
+        printf( "\n" );
+        printf( "Size = %d.\n", Pos );
+    }
+*/
+
+
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        pObj->pCopy = (void *)Count++;
+    Abc_AigForEachAnd( pNtk, pObj, i )
+    {
+//        if ( (Count - 4) % 6 == 0 )
+//            printf( "\n" );
+//        printf( "%5d,", (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj) );
+//        printf( "%5d,", (((int)Abc_ObjFanin1(pObj)->pCopy) << 1) | Abc_ObjFaninC1(pObj) );
+        pObj->pCopy = (void *)Count++;
+    }
+//    printf( "\n" );
+//    printf( "Nodes = %d.\n", Count-4 );
+
+
+
+    Abc_NtkForEachPo( pNtk, pObj, i )
+    {
+        if ( i % 12 == 0 )
+            printf( "\n" );
+        printf( "%5d,",  (int)Abc_ObjFanin0(pObj)->pCopy );
+    }
+    printf( "\n" );
+    printf( "Outputs = %d.\n", Abc_NtkPoNum(pNtk) );
+
+
+/*
+    {
+        unsigned char * pBuffer;
+        Vec_Int_t * vOuts;
+        int Pos, Prev, Out;
+
+        vOuts = Vec_IntAlloc( 25000 );
+        Abc_NtkForEachPo( pNtk, pObj, i )
+            Vec_IntPush( vOuts, Abc_ObjFaninId0(pObj) );
+        Vec_IntSort( vOuts, 0 );
+
+        Pos = 0;
+        pBuffer = ABC_ALLOC( char, 50000 );
+        Prev = 0;
+        Vec_IntForEachEntry( vOuts, Out, i )
+        {
+            assert( Prev < Out );
+            Pos = Io_WriteAigerEncode( pBuffer, Pos, Out - Prev );
+            Prev = Out;
+        }
+        Vec_IntFree( vOuts );
+
+        // write the buffer
+        for ( i = 0; i < Pos; i++ )
+        {
+            if ( i % 32 == 0 )
+                printf( "\n" );
+            printf( "%d,",  pBuffer[i] );
+        }
+        printf( "\n" );
+        printf( "Size = %d.\n", Pos );
+    }
+*/
+
+}
+
+#endif
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dar/darInt.h b/abc-build/src/opt/dar/darInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dar/darInt.h
@@ -0,0 +1,169 @@
+/**CFile****************************************************************
+
+  FileName    [darInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: darInt.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__dar__darInt_h
+#define ABC__aig__dar__darInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+#include "aig/aig/aig.h"
+#include "dar.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Dar_Man_t_            Dar_Man_t;
+typedef struct Dar_Cut_t_            Dar_Cut_t;
+
+// the AIG 4-cut
+struct Dar_Cut_t_  // 6 words
+{
+    unsigned         uSign;          // cut signature
+    unsigned         uTruth  : 16;   // the truth table of the cut function
+    unsigned         Value   : 11;   // the value of the cut 
+    unsigned         fBest   :  1;   // marks the best cut
+    unsigned         fUsed   :  1;   // marks the cut currently in use
+    unsigned         nLeaves :  3;   // the number of leaves
+    int              pLeaves[4];     // the array of leaves
+};
+
+// the AIG manager
+struct Dar_Man_t_
+{
+    // input data
+    Dar_RwrPar_t *   pPars;          // rewriting parameters
+    Aig_Man_t *      pAig;           // AIG manager 
+    // various data members
+    Aig_MmFixed_t *  pMemCuts;       // memory manager for cuts
+    void *           pManCnf;        // CNF managers
+    Vec_Ptr_t *      vCutNodes;      // the nodes with cuts allocated
+    // current rewriting step
+    Vec_Ptr_t *      vLeavesBest;    // the best set of leaves
+    int              OutBest;        // the best output (in the library)
+    int              OutNumBest;     // the best number of the output
+    int              GainBest;       // the best gain
+    int              LevelBest;      // the level of node with the best gain
+    int              ClassBest;      // the equivalence class of the best replacement
+    // function statistics
+    int              nTotalSubgs;    // the total number of subgraphs tried
+    int              ClassTimes[222];// the runtimes for each class
+    int              ClassGains[222];// the gains for each class
+    int              ClassSubgs[222];// the graphs for each class
+    int              nCutMemUsed;    // memory used for cuts
+    // rewriting statistics
+    int              nNodesInit;     // the original number of nodes
+    int              nNodesTried;    // the number of nodes attempted
+    int              nCutsAll;       // all cut pairs
+    int              nCutsTried;     // computed cuts
+    int              nCutsUsed;      // used cuts
+    int              nCutsBad;       // bad cuts due to absent fanin
+    int              nCutsGood;      // good cuts
+    int              nCutsSkipped;   // skipped bad cuts
+    // timing statistics
+    abctime          timeCuts;
+    abctime          timeEval;
+    abctime          timeOther;
+    abctime          timeTotal;
+    abctime          time1;
+    abctime          time2;
+};
+
+static inline Dar_Cut_t *  Dar_ObjCuts( Aig_Obj_t * pObj )                         { return (Dar_Cut_t *)pObj->pData;    }
+static inline void         Dar_ObjSetCuts( Aig_Obj_t * pObj, Dar_Cut_t * pCuts )   { assert( !Aig_ObjIsNone(pObj) ); pObj->pData = pCuts;   }
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                          ITERATORS                               ///
+////////////////////////////////////////////////////////////////////////
+
+// iterator over all cuts of the node
+#define Dar_ObjForEachCutAll( pObj, pCut, i )                                   \
+    for ( (pCut) = Dar_ObjCuts(pObj), i = 0; i < (int)(pObj)->nCuts; i++, pCut++ ) 
+#define Dar_ObjForEachCut( pObj, pCut, i )                                      \
+    for ( (pCut) = Dar_ObjCuts(pObj), i = 0; i < (int)(pObj)->nCuts; i++, pCut++ ) if ( (pCut)->fUsed==0 ) {} else
+// iterator over leaves of the cut
+#define Dar_CutForEachLeaf( p, pCut, pLeaf, i )                                 \
+    for ( i = 0; (i < (int)(pCut)->nLeaves) && (((pLeaf) = Aig_ManObj(p, (pCut)->pLeaves[i])), 1); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== darBalance.c ========================================================*/
+/*=== darCore.c ===========================================================*/
+/*=== darCut.c ============================================================*/
+extern void            Dar_ManCutsRestart( Dar_Man_t * p, Aig_Obj_t * pRoot );
+extern void            Dar_ManCutsFree( Dar_Man_t * p );
+extern Dar_Cut_t *     Dar_ObjPrepareCuts( Dar_Man_t * p, Aig_Obj_t * pObj );
+extern Dar_Cut_t *     Dar_ObjComputeCuts_rec( Dar_Man_t * p, Aig_Obj_t * pObj );
+extern Dar_Cut_t *     Dar_ObjComputeCuts( Dar_Man_t * p, Aig_Obj_t * pObj, int fSkipTtMin );
+extern void            Dar_ObjCutPrint( Aig_Man_t * p, Aig_Obj_t * pObj );
+/*=== darData.c ===========================================================*/
+extern Vec_Int_t *     Dar_LibReadNodes();
+extern Vec_Int_t *     Dar_LibReadOuts();
+extern Vec_Int_t *     Dar_LibReadPrios();
+/*=== darLib.c ============================================================*/
+extern void            Dar_LibStart();
+extern void            Dar_LibStop();
+extern void            Dar_LibReturnCanonicals( unsigned * pCanons );
+extern void            Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Required, int * pnMffcSize );
+extern Aig_Obj_t *     Dar_LibBuildBest( Dar_Man_t * p );
+/*=== darMan.c ============================================================*/
+extern Dar_Man_t *     Dar_ManStart( Aig_Man_t * pAig, Dar_RwrPar_t * pPars );
+extern void            Dar_ManStop( Dar_Man_t * p );
+extern void            Dar_ManPrintStats( Dar_Man_t * p );
+/*=== darPrec.c ============================================================*/
+extern char **         Dar_Permutations( int n );
+extern void            Dar_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/dar/darLib.c b/abc-build/src/opt/dar/darLib.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dar/darLib.c
@@ -0,0 +1,1339 @@
+/**CFile****************************************************************
+
+  FileName    [darLib.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting.]
+
+  Synopsis    [Library of AIG subgraphs used for rewriting.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: darLib.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "darInt.h"
+#include "aig/gia/gia.h"
+#include "dar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Dar_Lib_t_            Dar_Lib_t;
+typedef struct Dar_LibObj_t_         Dar_LibObj_t;
+typedef struct Dar_LibDat_t_         Dar_LibDat_t;
+
+struct Dar_LibObj_t_ // library object (2 words)
+{
+    unsigned         Fan0    : 16;  // the first fanin
+    unsigned         Fan1    : 16;  // the second fanin
+    unsigned         fCompl0 :  1;  // the first compl attribute
+    unsigned         fCompl1 :  1;  // the second compl attribute
+    unsigned         fPhase  :  1;  // the phase of the node
+    unsigned         fTerm   :  1;  // indicates a PI
+    unsigned         Num     : 28;  // internal use
+};
+
+struct Dar_LibDat_t_ // library object data
+{
+    union { 
+    Aig_Obj_t *      pFunc;         // the corresponding AIG node if it exists
+    int              iGunc; };      // the corresponding AIG node if it exists
+    int              Level;         // level of this node after it is constructured
+    int              TravId;        // traversal ID of the library object data
+    float            dProb;         // probability of the node being 1
+    unsigned char    fMffc;         // set to one if node is part of MFFC
+    unsigned char    nLats[3];      // the number of latches on the input/output stem
+};
+
+struct Dar_Lib_t_ // library 
+{
+    // objects
+    Dar_LibObj_t *   pObjs;         // the set of library objects
+    int              nObjs;         // the number of objects used
+    int              iObj;          // the current object
+    // structures by class
+    int              nSubgr[222];   // the number of subgraphs by class
+    int *            pSubgr[222];   // the subgraphs for each class
+    int *            pSubgrMem;     // memory for subgraph pointers
+    int              nSubgrTotal;   // the total number of subgraph
+    // structure priorities
+    int *            pPriosMem;     // memory for priority of structures
+    int *            pPrios[222];   // pointers to the priority numbers
+    // structure places in the priorities
+    int *            pPlaceMem;     // memory for places of structures in the priority lists
+    int *            pPlace[222];   // pointers to the places numbers
+    // structure scores
+    int *            pScoreMem;     // memory for scores of structures
+    int *            pScore[222];   // pointers to the scores numbers
+    // nodes by class
+    int              nNodes[222];   // the number of nodes by class
+    int *            pNodes[222];   // the nodes for each class
+    int *            pNodesMem;     // memory for nodes pointers
+    int              nNodesTotal;   // the total number of nodes
+    // prepared library
+    int              nSubgraphs;
+    int              nNodes0Max;
+    // nodes by class
+    int              nNodes0[222];   // the number of nodes by class
+    int *            pNodes0[222];   // the nodes for each class
+    int *            pNodes0Mem;     // memory for nodes pointers
+    int              nNodes0Total;   // the total number of nodes
+    // structures by class
+    int              nSubgr0[222];   // the number of subgraphs by class
+    int *            pSubgr0[222];   // the subgraphs for each class
+    int *            pSubgr0Mem;     // memory for subgraph pointers
+    int              nSubgr0Total;   // the total number of subgraph
+    // object data
+    Dar_LibDat_t *   pDatas;
+    int              nDatas;
+    // information about NPN classes
+    char **          pPerms4;
+    unsigned short * puCanons; 
+    char *           pPhases; 
+    char *           pPerms; 
+    unsigned char *  pMap;
+};
+
+static Dar_Lib_t * s_DarLib = NULL;
+
+static inline Dar_LibObj_t * Dar_LibObj( Dar_Lib_t * p, int Id )    { return p->pObjs + Id; }
+static inline int            Dar_LibObjTruth( Dar_LibObj_t * pObj ) { return pObj->Num < (0xFFFF & ~pObj->Num) ? pObj->Num : (0xFFFF & ~pObj->Num); }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dar_Lib_t * Dar_LibAlloc( int nObjs )
+{
+    unsigned uTruths[4] = { 0xAAAA, 0xCCCC, 0xF0F0, 0xFF00 };
+    Dar_Lib_t * p;
+    int i;//, clk = Abc_Clock();
+    p = ABC_ALLOC( Dar_Lib_t, 1 );
+    memset( p, 0, sizeof(Dar_Lib_t) );
+    // allocate objects
+    p->nObjs = nObjs;
+    p->pObjs = ABC_ALLOC( Dar_LibObj_t, nObjs );
+    memset( p->pObjs, 0, sizeof(Dar_LibObj_t) * nObjs );
+    // allocate canonical data
+    p->pPerms4 = Dar_Permutations( 4 );
+    Dar_Truth4VarNPN( &p->puCanons, &p->pPhases, &p->pPerms, &p->pMap );
+    // start the elementary objects
+    p->iObj = 4;
+    for ( i = 0; i < 4; i++ )
+    {
+        p->pObjs[i].fTerm = 1;
+        p->pObjs[i].Num = uTruths[i];
+    }
+//    ABC_PRT( "Library start", Abc_Clock() - clk );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_LibFree( Dar_Lib_t * p )
+{
+    ABC_FREE( p->pObjs );
+    ABC_FREE( p->pDatas );
+    ABC_FREE( p->pNodesMem );
+    ABC_FREE( p->pNodes0Mem );
+    ABC_FREE( p->pSubgrMem );
+    ABC_FREE( p->pSubgr0Mem );
+    ABC_FREE( p->pPriosMem );
+    ABC_FREE( p->pPlaceMem );
+    ABC_FREE( p->pScoreMem );
+    ABC_FREE( p->pPerms4 );
+    ABC_FREE( p->puCanons );
+    ABC_FREE( p->pPhases );
+    ABC_FREE( p->pPerms );
+    ABC_FREE( p->pMap );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns canonical truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar_LibReturnClass( unsigned uTruth )
+{
+    return s_DarLib->pMap[uTruth & 0xffff];
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns canonical truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_LibReturnCanonicals( unsigned * pCanons )
+{
+    int Visits[222] = {0};
+    int i, k;
+    // find canonical truth tables
+    for ( i = k = 0; i < (1<<16); i++ )
+        if ( !Visits[s_DarLib->pMap[i]] )
+        {
+            Visits[s_DarLib->pMap[i]] = 1;
+            pCanons[k++] = ((i<<16) | i);
+        }
+    assert( k == 222 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one AND to the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_LibAddNode( Dar_Lib_t * p, int Id0, int Id1, int fCompl0, int fCompl1 )
+{
+    Dar_LibObj_t * pFan0 = Dar_LibObj( p, Id0 );
+    Dar_LibObj_t * pFan1 = Dar_LibObj( p, Id1 );
+    Dar_LibObj_t * pObj  = p->pObjs + p->iObj++;
+    pObj->Fan0 = Id0;
+    pObj->Fan1 = Id1;
+    pObj->fCompl0 = fCompl0;
+    pObj->fCompl1 = fCompl1;
+    pObj->fPhase = (fCompl0 ^ pFan0->fPhase) & (fCompl1 ^ pFan1->fPhase);
+    pObj->Num = 0xFFFF & (fCompl0? ~pFan0->Num : pFan0->Num) & (fCompl1? ~pFan1->Num : pFan1->Num);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one AND to the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_LibSetup_rec( Dar_Lib_t * p, Dar_LibObj_t * pObj, int Class, int fCollect )
+{
+    if ( pObj->fTerm || (int)pObj->Num == Class )
+        return;
+    pObj->Num = Class;
+    Dar_LibSetup_rec( p, Dar_LibObj(p, pObj->Fan0), Class, fCollect );
+    Dar_LibSetup_rec( p, Dar_LibObj(p, pObj->Fan1), Class, fCollect );
+    if ( fCollect )
+        p->pNodes[Class][ p->nNodes[Class]++ ] = pObj-p->pObjs;
+    else
+        p->nNodes[Class]++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one AND to the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_LibSetup( Dar_Lib_t * p, Vec_Int_t * vOuts, Vec_Int_t * vPrios )
+{
+    int fTraining = 0;
+    Dar_LibObj_t * pObj;
+    int nNodesTotal, uTruth, Class, Out, i, k;
+    assert( p->iObj == p->nObjs );
+
+    // count the number of representatives of each class
+    for ( i = 0; i < 222; i++ )
+        p->nSubgr[i] = p->nNodes[i] = 0;
+    Vec_IntForEachEntry( vOuts, Out, i )
+    {
+        pObj = Dar_LibObj( p, Out );
+        uTruth = Dar_LibObjTruth( pObj );
+        Class = p->pMap[uTruth];
+        p->nSubgr[Class]++;
+    }
+    // allocate memory for the roots of each class
+    p->pSubgrMem = ABC_ALLOC( int, Vec_IntSize(vOuts) );
+    p->pSubgr0Mem = ABC_ALLOC( int, Vec_IntSize(vOuts) );
+    p->nSubgrTotal = 0;
+    for ( i = 0; i < 222; i++ )
+    {
+        p->pSubgr[i] = p->pSubgrMem + p->nSubgrTotal;
+        p->pSubgr0[i] = p->pSubgr0Mem + p->nSubgrTotal;
+        p->nSubgrTotal += p->nSubgr[i];
+        p->nSubgr[i] = 0;
+    }
+    assert( p->nSubgrTotal == Vec_IntSize(vOuts) );
+    // add the outputs to storage
+    Vec_IntForEachEntry( vOuts, Out, i )
+    {
+        pObj = Dar_LibObj( p, Out );
+        uTruth = Dar_LibObjTruth( pObj );
+        Class = p->pMap[uTruth];
+        p->pSubgr[Class][ p->nSubgr[Class]++ ] = Out;
+    }
+
+    if ( fTraining )
+    {
+        // allocate memory for the priority of roots of each class
+        p->pPriosMem = ABC_ALLOC( int, Vec_IntSize(vOuts) );
+        p->nSubgrTotal = 0;
+        for ( i = 0; i < 222; i++ )
+        {
+            p->pPrios[i] = p->pPriosMem + p->nSubgrTotal;
+            p->nSubgrTotal += p->nSubgr[i];
+            for ( k = 0; k < p->nSubgr[i]; k++ )
+                p->pPrios[i][k] = k;
+
+        }
+        assert( p->nSubgrTotal == Vec_IntSize(vOuts) );
+
+        // allocate memory for the priority of roots of each class
+        p->pPlaceMem = ABC_ALLOC( int, Vec_IntSize(vOuts) );
+        p->nSubgrTotal = 0;
+        for ( i = 0; i < 222; i++ )
+        {
+            p->pPlace[i] = p->pPlaceMem + p->nSubgrTotal;
+            p->nSubgrTotal += p->nSubgr[i];
+            for ( k = 0; k < p->nSubgr[i]; k++ )
+                p->pPlace[i][k] = k;
+
+        }
+        assert( p->nSubgrTotal == Vec_IntSize(vOuts) );
+
+        // allocate memory for the priority of roots of each class
+        p->pScoreMem = ABC_ALLOC( int, Vec_IntSize(vOuts) );
+        p->nSubgrTotal = 0;
+        for ( i = 0; i < 222; i++ )
+        {
+            p->pScore[i] = p->pScoreMem + p->nSubgrTotal;
+            p->nSubgrTotal += p->nSubgr[i];
+            for ( k = 0; k < p->nSubgr[i]; k++ )
+                p->pScore[i][k] = 0;
+
+        }
+        assert( p->nSubgrTotal == Vec_IntSize(vOuts) );
+    }
+    else
+    {
+        int Counter = 0;
+        // allocate memory for the priority of roots of each class
+        p->pPriosMem = ABC_ALLOC( int, Vec_IntSize(vOuts) );
+        p->nSubgrTotal = 0;
+        for ( i = 0; i < 222; i++ )
+        {
+            p->pPrios[i] = p->pPriosMem + p->nSubgrTotal;
+            p->nSubgrTotal += p->nSubgr[i];
+            for ( k = 0; k < p->nSubgr[i]; k++ )
+                p->pPrios[i][k] = Vec_IntEntry(vPrios, Counter++);
+
+        }
+        assert( p->nSubgrTotal == Vec_IntSize(vOuts) );
+        assert( Counter == Vec_IntSize(vPrios) );
+    }
+
+    // create traversal IDs
+    for ( i = 0; i < p->iObj; i++ )
+        Dar_LibObj(p, i)->Num = 0xff;
+    // count nodes in each class
+    for ( i = 0; i < 222; i++ )
+        for ( k = 0; k < p->nSubgr[i]; k++ )
+            Dar_LibSetup_rec( p, Dar_LibObj(p, p->pSubgr[i][k]), i, 0 );
+    // count the total number of nodes
+    p->nNodesTotal = 0;
+    for ( i = 0; i < 222; i++ )
+        p->nNodesTotal += p->nNodes[i];
+    // allocate memory for the nodes of each class
+    p->pNodesMem = ABC_ALLOC( int, p->nNodesTotal );
+    p->pNodes0Mem = ABC_ALLOC( int, p->nNodesTotal );
+    p->nNodesTotal = 0;
+    for ( i = 0; i < 222; i++ )
+    {
+        p->pNodes[i] = p->pNodesMem + p->nNodesTotal;
+        p->pNodes0[i] = p->pNodes0Mem + p->nNodesTotal;
+        p->nNodesTotal += p->nNodes[i];
+        p->nNodes[i] = 0;
+    }
+    // create traversal IDs
+    for ( i = 0; i < p->iObj; i++ )
+        Dar_LibObj(p, i)->Num = 0xff;
+    // add the nodes to storage
+    nNodesTotal = 0;
+    for ( i = 0; i < 222; i++ )
+    {
+         for ( k = 0; k < p->nSubgr[i]; k++ )
+            Dar_LibSetup_rec( p, Dar_LibObj(p, p->pSubgr[i][k]), i, 1 );
+         nNodesTotal += p->nNodes[i];
+//printf( "Class %3d : Subgraphs = %4d. Nodes = %5d.\n", i, p->nSubgr[i], p->nNodes[i] );
+    }
+    assert( nNodesTotal == p->nNodesTotal );
+     // prepare the number of the PI nodes
+    for ( i = 0; i < 4; i++ )
+        Dar_LibObj(p, i)->Num = i;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_LibCreateData( Dar_Lib_t * p, int nDatas )
+{
+    if ( p->nDatas == nDatas )
+        return;
+    ABC_FREE( p->pDatas );
+    // allocate datas
+    p->nDatas = nDatas;
+    p->pDatas = ABC_ALLOC( Dar_LibDat_t, nDatas );
+    memset( p->pDatas, 0, sizeof(Dar_LibDat_t) * nDatas );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one AND to the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_LibSetup0_rec( Dar_Lib_t * p, Dar_LibObj_t * pObj, int Class, int fCollect )
+{
+    if ( pObj->fTerm || (int)pObj->Num == Class )
+        return;
+    pObj->Num = Class;
+    Dar_LibSetup0_rec( p, Dar_LibObj(p, pObj->Fan0), Class, fCollect );
+    Dar_LibSetup0_rec( p, Dar_LibObj(p, pObj->Fan1), Class, fCollect );
+    if ( fCollect )
+        p->pNodes0[Class][ p->nNodes0[Class]++ ] = pObj-p->pObjs;
+    else
+        p->nNodes0[Class]++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_LibPrepare( int nSubgraphs )
+{
+    Dar_Lib_t * p = s_DarLib;
+    int i, k, nNodes0Total;
+    if ( p->nSubgraphs == nSubgraphs )
+        return;
+
+    // favor special classes:
+    //  1 : F = (!d*!c*!b*!a)
+    //  4 : F = (!d*!c*!(b*a))
+    // 12 : F = (!d*!(c*!(!b*!a)))
+    // 20 : F = (!d*!(c*b*a))
+
+    // set the subgraph counters 
+    p->nSubgr0Total = 0;
+    for ( i = 0; i < 222; i++ )
+    {
+//        if ( i == 1 || i == 4 || i == 12 || i == 20 ) // special classes 
+        if ( i == 1 ) // special classes 
+            p->nSubgr0[i] = p->nSubgr[i];
+        else
+            p->nSubgr0[i] = Abc_MinInt( p->nSubgr[i], nSubgraphs );
+        p->nSubgr0Total += p->nSubgr0[i];
+        for ( k = 0; k < p->nSubgr0[i]; k++ )
+            p->pSubgr0[i][k] = p->pSubgr[i][ p->pPrios[i][k] ];
+    }
+
+    // count the number of nodes
+    // clean node counters
+    for ( i = 0; i < 222; i++ )
+        p->nNodes0[i] = 0;
+    // create traversal IDs
+    for ( i = 0; i < p->iObj; i++ )
+        Dar_LibObj(p, i)->Num = 0xff;
+    // count nodes in each class
+    // count the total number of nodes and the largest class
+    p->nNodes0Total = 0;
+    p->nNodes0Max = 0;
+    for ( i = 0; i < 222; i++ )
+    {
+        for ( k = 0; k < p->nSubgr0[i]; k++ )
+            Dar_LibSetup0_rec( p, Dar_LibObj(p, p->pSubgr0[i][k]), i, 0 );
+        p->nNodes0Total += p->nNodes0[i];
+        p->nNodes0Max = Abc_MaxInt( p->nNodes0Max, p->nNodes0[i] );
+    }
+
+    // clean node counters
+    for ( i = 0; i < 222; i++ )
+        p->nNodes0[i] = 0;
+    // create traversal IDs
+    for ( i = 0; i < p->iObj; i++ )
+        Dar_LibObj(p, i)->Num = 0xff;
+    // add the nodes to storage
+    nNodes0Total = 0;
+    for ( i = 0; i < 222; i++ )
+    {
+        for ( k = 0; k < p->nSubgr0[i]; k++ )
+            Dar_LibSetup0_rec( p, Dar_LibObj(p, p->pSubgr0[i][k]), i, 1 );
+         nNodes0Total += p->nNodes0[i];
+    }
+    assert( nNodes0Total == p->nNodes0Total );
+     // prepare the number of the PI nodes
+    for ( i = 0; i < 4; i++ )
+        Dar_LibObj(p, i)->Num = i;
+
+    // realloc the datas
+    Dar_LibCreateData( p, p->nNodes0Max + 32 ); 
+    // allocated more because Dar_LibBuildBest() sometimes requires more entries
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads library from array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dar_Lib_t * Dar_LibRead()
+{
+    Vec_Int_t * vObjs, * vOuts, * vPrios;
+    Dar_Lib_t * p;
+    int i;
+    // read nodes and outputs
+    vObjs  = Dar_LibReadNodes();
+    vOuts  = Dar_LibReadOuts();
+    vPrios = Dar_LibReadPrios();
+    // create library
+    p = Dar_LibAlloc( Vec_IntSize(vObjs)/2 + 4 );
+    // create nodes
+    for ( i = 0; i < vObjs->nSize; i += 2 )
+        Dar_LibAddNode( p, vObjs->pArray[i] >> 1, vObjs->pArray[i+1] >> 1,
+            vObjs->pArray[i] & 1, vObjs->pArray[i+1] & 1 );
+    // create outputs
+    Dar_LibSetup( p, vOuts, vPrios );
+    Vec_IntFree( vObjs );
+    Vec_IntFree( vOuts );
+    Vec_IntFree( vPrios );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_LibStart()
+{
+//    abctime clk = Abc_Clock();
+    assert( s_DarLib == NULL );
+    s_DarLib = Dar_LibRead();
+//    printf( "The 4-input library started with %d nodes and %d subgraphs. ", s_DarLib->nObjs - 4, s_DarLib->nSubgrTotal );
+//    ABC_PRT( "Time", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the library.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_LibStop()
+{
+    assert( s_DarLib != NULL );
+    Dar_LibFree( s_DarLib );
+    s_DarLib = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the score of the class and adjusts the priority of this class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_LibIncrementScore( int Class, int Out, int Gain )
+{
+    int * pPrios = s_DarLib->pPrios[Class];  // pPrios[i] = Out
+    int * pPlace = s_DarLib->pPlace[Class];  // pPlace[Out] = i
+    int * pScore = s_DarLib->pScore[Class];  // score of Out
+    int Out2;
+    assert( Class >= 0 && Class < 222 );
+    assert( Out >= 0 && Out < s_DarLib->nSubgr[Class] );
+    assert( pPlace[pPrios[Out]] == Out );
+    // increment the score
+    pScore[Out] += Gain;
+    // move the out in the order 
+    while ( pPlace[Out] > 0 && pScore[Out] > pScore[ pPrios[pPlace[Out]-1] ] )
+    {
+        // get the previous output in the priority list
+        Out2 = pPrios[pPlace[Out]-1];
+        // swap Out and Out2
+        pPlace[Out]--;
+        pPlace[Out2]++;
+        pPrios[pPlace[Out]] = Out;
+        pPrios[pPlace[Out2]] = Out2;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints out the priorities into the file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_LibDumpPriorities()
+{
+    int i, k, Out, Out2, Counter = 0, Printed = 0;
+    printf( "\nOutput priorities (total = %d):\n", s_DarLib->nSubgrTotal );
+    for ( i = 0; i < 222; i++ )
+    {
+//        printf( "Class%d: ", i );
+        for ( k = 0; k < s_DarLib->nSubgr[i]; k++ )
+        {
+            Out = s_DarLib->pPrios[i][k];
+            Out2 = k == 0 ? Out : s_DarLib->pPrios[i][k-1];
+            assert( s_DarLib->pScore[i][Out2] >= s_DarLib->pScore[i][Out] );
+//            printf( "%d(%d), ", Out, s_DarLib->pScore[i][Out] );
+            printf( "%d, ", Out );
+            Printed++;
+            if ( ++Counter == 15 )
+            {
+                printf( "\n" );
+                Counter = 0;
+            }
+        }
+    }
+    printf( "\n" );
+    assert( Printed == s_DarLib->nSubgrTotal );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Matches the cut with its canonical form.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar_LibCutMatch( Dar_Man_t * p, Dar_Cut_t * pCut )
+{
+    Aig_Obj_t * pFanin;
+    unsigned uPhase;
+    char * pPerm;
+    int i;
+    assert( pCut->nLeaves == 4 );
+    // get the fanin permutation
+    uPhase = s_DarLib->pPhases[pCut->uTruth];
+    pPerm = s_DarLib->pPerms4[ (int)s_DarLib->pPerms[pCut->uTruth] ];
+    // collect fanins with the corresponding permutation/phase
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+    {
+        pFanin = Aig_ManObj( p->pAig, pCut->pLeaves[ (int)pPerm[i] ] );
+        if ( pFanin == NULL )
+        {
+            p->nCutsBad++;
+            return 0;
+        }
+        pFanin = Aig_NotCond(pFanin, ((uPhase >> i) & 1) );
+        s_DarLib->pDatas[i].pFunc = pFanin;
+        s_DarLib->pDatas[i].Level = Aig_Regular(pFanin)->Level;
+        // copy the propability of node being one
+        if ( p->pPars->fPower )
+        {
+            float Prob = Abc_Int2Float( Vec_IntEntry( p->pAig->vProbs, Aig_ObjId(Aig_Regular(pFanin)) ) );
+            s_DarLib->pDatas[i].dProb = Aig_IsComplement(pFanin)? 1.0-Prob : Prob;
+        }
+    }
+    p->nCutsGood++;
+    return 1;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the MFFC of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar_LibCutMarkMffc( Aig_Man_t * p, Aig_Obj_t * pRoot, int nLeaves, float * pPower )
+{
+    int i, nNodes;
+    // mark the cut leaves
+    for ( i = 0; i < nLeaves; i++ )
+        Aig_Regular(s_DarLib->pDatas[i].pFunc)->nRefs++;
+    // label MFFC with current ID
+    nNodes = Aig_NodeMffcLabel( p, pRoot, pPower );
+    // unmark the cut leaves
+    for ( i = 0; i < nLeaves; i++ )
+        Aig_Regular(s_DarLib->pDatas[i].pFunc)->nRefs--;
+    return nNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates one cut.]
+
+  Description [Returns the best gain.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_LibObjPrint_rec( Dar_LibObj_t * pObj )
+{
+    if ( pObj->fTerm )
+    {
+        printf( "%c", 'a' + (int)(pObj - s_DarLib->pObjs) );
+        return;
+    }
+    printf( "(" );
+    Dar_LibObjPrint_rec( Dar_LibObj(s_DarLib, pObj->Fan0) );
+    if ( pObj->fCompl0 )
+        printf( "\'" );
+    Dar_LibObjPrint_rec( Dar_LibObj(s_DarLib, pObj->Fan1) );
+    if ( pObj->fCompl0 )
+        printf( "\'" );
+    printf( ")" );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns numbers to the nodes of one class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_LibEvalAssignNums( Dar_Man_t * p, int Class, Aig_Obj_t * pRoot )
+{
+    Dar_LibObj_t * pObj;
+    Dar_LibDat_t * pData, * pData0, * pData1;
+    Aig_Obj_t * pFanin0, * pFanin1;
+    int i;
+    for ( i = 0; i < s_DarLib->nNodes0[Class]; i++ )
+    {
+        // get one class node, assign its temporary number and set its data
+        pObj = Dar_LibObj(s_DarLib, s_DarLib->pNodes0[Class][i]);
+        pObj->Num = 4 + i;
+        assert( (int)pObj->Num < s_DarLib->nNodes0Max + 4 );
+        pData = s_DarLib->pDatas + pObj->Num;
+        pData->fMffc = 0;
+        pData->pFunc = NULL;
+        pData->TravId = 0xFFFF;
+
+        // explore the fanins
+        assert( (int)Dar_LibObj(s_DarLib, pObj->Fan0)->Num < s_DarLib->nNodes0Max + 4 );
+        assert( (int)Dar_LibObj(s_DarLib, pObj->Fan1)->Num < s_DarLib->nNodes0Max + 4 );
+        pData0 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan0)->Num;
+        pData1 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan1)->Num;
+        pData->Level = 1 + Abc_MaxInt(pData0->Level, pData1->Level);
+        if ( pData0->pFunc == NULL || pData1->pFunc == NULL )
+            continue;
+        pFanin0 = Aig_NotCond( pData0->pFunc, pObj->fCompl0 );
+        pFanin1 = Aig_NotCond( pData1->pFunc, pObj->fCompl1 );
+        if ( Aig_Regular(pFanin0) == pRoot || Aig_Regular(pFanin1) == pRoot )
+            continue;
+        pData->pFunc = Aig_TableLookupTwo( p->pAig, pFanin0, pFanin1 );
+        if ( pData->pFunc )
+        {
+            // update the level to be more accurate
+            pData->Level = Aig_Regular(pData->pFunc)->Level;
+            // mark the node if it is part of MFFC
+            pData->fMffc = Aig_ObjIsTravIdCurrent(p->pAig, Aig_Regular(pData->pFunc));
+            // assign the probability
+            if ( p->pPars->fPower )
+            {
+                float Prob = Abc_Int2Float( Vec_IntEntry( p->pAig->vProbs, Aig_ObjId(Aig_Regular(pData->pFunc)) ) );
+                pData->dProb = Aig_IsComplement(pData->pFunc)? 1.0-Prob : Prob;
+            }
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates one cut.]
+
+  Description [Returns the best gain.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar_LibEval_rec( Dar_LibObj_t * pObj, int Out, int nNodesSaved, int Required, float * pPower )
+{
+    Dar_LibDat_t * pData;
+    float Power0, Power1;
+    int Area;
+    if ( pPower )
+        *pPower = (float)0.0;
+    pData = s_DarLib->pDatas + pObj->Num;
+    if ( pData->TravId == Out )
+        return 0;
+    pData->TravId = Out;
+    if ( pObj->fTerm )
+    {
+        if ( pPower )
+            *pPower = pData->dProb;
+        return 0;
+    }
+    assert( pObj->Num > 3 );
+    if ( pData->Level > Required )
+        return 0xff;
+    if ( pData->pFunc && !pData->fMffc )
+    {
+        if ( pPower )
+            *pPower = pData->dProb;
+        return 0;
+    }
+    // this is a new node - get a bound on the area of its branches
+    nNodesSaved--;
+    Area = Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan0), Out, nNodesSaved, Required+1, pPower? &Power0 : NULL );
+    if ( Area > nNodesSaved )
+        return 0xff;
+    Area += Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan1), Out, nNodesSaved, Required+1, pPower? &Power1 : NULL );
+    if ( Area > nNodesSaved )
+        return 0xff;
+    if ( pPower )
+    {
+        Dar_LibDat_t * pData0 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan0)->Num;
+        Dar_LibDat_t * pData1 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan1)->Num;
+        pData->dProb = (pObj->fCompl0? 1.0 - pData0->dProb : pData0->dProb)*
+                       (pObj->fCompl1? 1.0 - pData1->dProb : pData1->dProb);
+        *pPower = Power0 + 2.0 * pData0->dProb * (1.0 - pData0->dProb) +
+                  Power1 + 2.0 * pData1->dProb * (1.0 - pData1->dProb);
+    }
+    return Area + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates one cut.]
+
+  Description [Returns the best gain.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Required, int * pnMffcSize )
+{
+    int fTraining = 0;
+    float PowerSaved, PowerAdded;
+    Dar_LibObj_t * pObj;
+    int Out, k, Class, nNodesSaved, nNodesAdded, nNodesGained;
+    abctime clk = Abc_Clock();
+    if ( pCut->nLeaves != 4 )
+        return;
+    // check if the cut exits and assigns leaves and their levels
+    if ( !Dar_LibCutMatch(p, pCut) )
+        return;
+    // mark MFFC of the node
+    nNodesSaved = Dar_LibCutMarkMffc( p->pAig, pRoot, pCut->nLeaves, p->pPars->fPower? &PowerSaved : NULL );
+    // evaluate the cut
+    Class = s_DarLib->pMap[pCut->uTruth];
+    Dar_LibEvalAssignNums( p, Class, pRoot );
+    // profile outputs by their savings
+    p->nTotalSubgs += s_DarLib->nSubgr0[Class];
+    p->ClassSubgs[Class] += s_DarLib->nSubgr0[Class];
+    for ( Out = 0; Out < s_DarLib->nSubgr0[Class]; Out++ )
+    {
+        pObj = Dar_LibObj(s_DarLib, s_DarLib->pSubgr0[Class][Out]);
+        if ( Aig_Regular(s_DarLib->pDatas[pObj->Num].pFunc) == pRoot )
+            continue;
+        nNodesAdded = Dar_LibEval_rec( pObj, Out, nNodesSaved - !p->pPars->fUseZeros, Required, p->pPars->fPower? &PowerAdded : NULL );
+        nNodesGained = nNodesSaved - nNodesAdded;
+        if ( p->pPars->fPower && PowerSaved < PowerAdded )
+            continue;
+        if ( fTraining && nNodesGained >= 0 )
+            Dar_LibIncrementScore( Class, Out, nNodesGained + 1 );
+        if ( nNodesGained < 0 || (nNodesGained == 0 && !p->pPars->fUseZeros) )
+            continue;
+        if ( nNodesGained <  p->GainBest || 
+            (nNodesGained == p->GainBest && s_DarLib->pDatas[pObj->Num].Level >= p->LevelBest) )
+            continue;
+        // remember this possibility
+        Vec_PtrClear( p->vLeavesBest );
+        for ( k = 0; k < (int)pCut->nLeaves; k++ )
+            Vec_PtrPush( p->vLeavesBest, s_DarLib->pDatas[k].pFunc );
+        p->OutBest    = s_DarLib->pSubgr0[Class][Out];
+        p->OutNumBest = Out;
+        p->LevelBest  = s_DarLib->pDatas[pObj->Num].Level;
+        p->GainBest   = nNodesGained;
+        p->ClassBest  = Class;
+        assert( p->LevelBest <= Required );
+        *pnMffcSize   = nNodesSaved;
+    }
+clk = Abc_Clock() - clk;
+p->ClassTimes[Class] += clk;
+p->timeEval += clk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Clears the fields of the nodes used in this cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_LibBuildClear_rec( Dar_LibObj_t * pObj, int * pCounter )
+{
+    if ( pObj->fTerm )
+        return;
+    pObj->Num = (*pCounter)++;
+    s_DarLib->pDatas[ pObj->Num ].pFunc = NULL;
+    Dar_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan0), pCounter );
+    Dar_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan1), pCounter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reconstructs the best cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Dar_LibBuildBest_rec( Dar_Man_t * p, Dar_LibObj_t * pObj )
+{
+    Aig_Obj_t * pFanin0, * pFanin1;
+    Dar_LibDat_t * pData = s_DarLib->pDatas + pObj->Num;
+    if ( pData->pFunc )
+        return pData->pFunc;
+    pFanin0 = Dar_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan0) );
+    pFanin1 = Dar_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan1) );
+    pFanin0 = Aig_NotCond( pFanin0, pObj->fCompl0 );
+    pFanin1 = Aig_NotCond( pFanin1, pObj->fCompl1 );
+    pData->pFunc = Aig_And( p->pAig, pFanin0, pFanin1 );
+//    assert( pData->Level == (int)Aig_Regular(pData->pFunc)->Level );
+    return pData->pFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reconstructs the best cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Dar_LibBuildBest( Dar_Man_t * p )
+{
+    int i, Counter = 4;
+    for ( i = 0; i < Vec_PtrSize(p->vLeavesBest); i++ )
+        s_DarLib->pDatas[i].pFunc = (Aig_Obj_t *)Vec_PtrEntry( p->vLeavesBest, i );
+    Dar_LibBuildClear_rec( Dar_LibObj(s_DarLib, p->OutBest), &Counter );
+    return Dar_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, p->OutBest) );
+}
+
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Matches the cut with its canonical form.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar2_LibCutMatch( Gia_Man_t * p, Vec_Int_t * vCutLits, unsigned uTruth )
+{
+    unsigned uPhase;
+    char * pPerm;
+    int i;
+    assert( Vec_IntSize(vCutLits) == 4 );
+    // get the fanin permutation
+    uPhase = s_DarLib->pPhases[uTruth];
+    pPerm  = s_DarLib->pPerms4[ (int)s_DarLib->pPerms[uTruth] ];
+    // collect fanins with the corresponding permutation/phase
+    for ( i = 0; i < Vec_IntSize(vCutLits); i++ )
+    {
+//        pFanin = Gia_ManObj( p, pCut->pLeaves[ (int)pPerm[i] ] );
+//        pFanin = Gia_ManObj( p, Vec_IntEntry( vCutLits, (int)pPerm[i] ) );
+//        pFanin = Gia_ObjFromLit( p, Vec_IntEntry( vCutLits, (int)pPerm[i] ) );
+        s_DarLib->pDatas[i].iGunc = Abc_LitNotCond( Vec_IntEntry(vCutLits, (int)pPerm[i]), ((uPhase >> i) & 1) );
+        s_DarLib->pDatas[i].Level = Gia_ObjLevel( p, Gia_Regular(Gia_ObjFromLit(p, s_DarLib->pDatas[i].iGunc)) );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns numbers to the nodes of one class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar2_LibEvalAssignNums( Gia_Man_t * p, int Class )
+{
+    Dar_LibObj_t * pObj;
+    Dar_LibDat_t * pData, * pData0, * pData1;
+    int iFanin0, iFanin1, i, iLit;
+    for ( i = 0; i < s_DarLib->nNodes0[Class]; i++ )
+    {
+        // get one class node, assign its temporary number and set its data
+        pObj = Dar_LibObj(s_DarLib, s_DarLib->pNodes0[Class][i]);
+        pObj->Num = 4 + i;
+        assert( (int)pObj->Num < s_DarLib->nNodes0Max + 4 );
+        pData = s_DarLib->pDatas + pObj->Num;
+        pData->fMffc = 0;
+        pData->iGunc = -1;
+        pData->TravId = 0xFFFF;
+
+        // explore the fanins
+        assert( (int)Dar_LibObj(s_DarLib, pObj->Fan0)->Num < s_DarLib->nNodes0Max + 4 );
+        assert( (int)Dar_LibObj(s_DarLib, pObj->Fan1)->Num < s_DarLib->nNodes0Max + 4 );
+        pData0 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan0)->Num;
+        pData1 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan1)->Num;
+        pData->Level = 1 + Abc_MaxInt(pData0->Level, pData1->Level);
+        if ( pData0->iGunc == -1 || pData1->iGunc == -1 )
+            continue;
+        iFanin0 = Abc_LitNotCond( pData0->iGunc, pObj->fCompl0 );
+        iFanin1 = Abc_LitNotCond( pData1->iGunc, pObj->fCompl1 );
+        // compute the resulting literal
+        if ( iFanin0 == 0 || iFanin1 == 0 || iFanin0 == Abc_LitNot(iFanin1) )
+            iLit = 0;
+        else if ( iFanin0 == 1 || iFanin0 == iFanin1 )
+            iLit = iFanin1;
+        else if ( iFanin1 == 1 )
+            iLit = iFanin0;
+        else
+        {
+            iLit = Gia_ManHashLookup( p, Gia_ObjFromLit(p, iFanin0), Gia_ObjFromLit(p, iFanin1) );
+            if ( iLit == 0 )
+                iLit = -1;
+        }
+        pData->iGunc = iLit;
+        if ( pData->iGunc >= 0 )
+        {
+            // update the level to be more accurate
+            pData->Level = Gia_ObjLevel( p, Gia_Regular(Gia_ObjFromLit(p, pData->iGunc)) );
+            // mark the node if it is part of MFFC
+//            pData->fMffc = Gia_ObjIsTravIdCurrentArray(p, Gia_Regular(pData->pGunc));
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates one cut.]
+
+  Description [Returns the best gain.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar2_LibEval_rec( Dar_LibObj_t * pObj, int Out )
+{
+    Dar_LibDat_t * pData;
+    int Area;
+    pData = s_DarLib->pDatas + pObj->Num;
+    if ( pData->TravId == Out )
+        return 0;
+    pData->TravId = Out;
+    if ( pObj->fTerm )
+        return 0;
+    assert( pObj->Num > 3 );
+    if ( pData->iGunc >= 0 )//&& !pData->fMffc )
+        return 0;
+    // this is a new node - get a bound on the area of its branches
+//    nNodesSaved--;
+    Area = Dar2_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan0), Out );
+//    if ( Area > nNodesSaved )
+//        return 0xff;
+    Area += Dar2_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan1), Out );
+//    if ( Area > nNodesSaved )
+//        return 0xff;
+    return Area + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates one cut.]
+
+  Description [Returns the best gain.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar2_LibEval( Gia_Man_t * p, Vec_Int_t * vCutLits, unsigned uTruth, int fKeepLevel, Vec_Int_t * vLeavesBest2 )
+{
+    int p_OutBest    = -1;
+    int p_OutNumBest = -1;
+    int p_LevelBest  =  1000000;
+    int p_GainBest   = -1000000;
+    int p_ClassBest  = -1;
+//    int fTraining    =  0;
+    Dar_LibObj_t * pObj;
+    int Out, k, Class, nNodesSaved, nNodesAdded, nNodesGained;
+//    abctime clk = Abc_Clock();
+    assert( Vec_IntSize(vCutLits) == 4 );
+    assert( (uTruth >> 16) == 0 );
+    // check if the cut exits and assigns leaves and their levels
+    if ( !Dar2_LibCutMatch(p, vCutLits, uTruth) )
+        return -1;
+    // mark MFFC of the node
+//    nNodesSaved = Dar2_LibCutMarkMffc( p->pAig, pRoot, pCut->nLeaves, p->pPars->fPower? &PowerSaved : NULL );
+    nNodesSaved = 0;
+    // evaluate the cut
+    Class = s_DarLib->pMap[uTruth];
+    Dar2_LibEvalAssignNums( p, Class );
+    // profile outputs by their savings
+//    p->nTotalSubgs += s_DarLib->nSubgr0[Class];
+//    p->ClassSubgs[Class] += s_DarLib->nSubgr0[Class];
+    for ( Out = 0; Out < s_DarLib->nSubgr0[Class]; Out++ )
+    {
+        pObj = Dar_LibObj(s_DarLib, s_DarLib->pSubgr0[Class][Out]);
+//        nNodesAdded = Dar2_LibEval_rec( pObj, Out, nNodesSaved - !p->pPars->fUseZeros, Required, p->pPars->fPower? &PowerAdded : NULL );
+        nNodesAdded = Dar2_LibEval_rec( pObj, Out );
+        nNodesGained = nNodesSaved - nNodesAdded;
+        if ( fKeepLevel )
+        {
+            if ( s_DarLib->pDatas[pObj->Num].Level >  p_LevelBest || 
+                (s_DarLib->pDatas[pObj->Num].Level == p_LevelBest && nNodesGained <= p_GainBest) )
+                continue;
+        }
+        else
+        {
+            if ( nNodesGained <  p_GainBest || 
+                (nNodesGained == p_GainBest && s_DarLib->pDatas[pObj->Num].Level >= p_LevelBest) )
+                continue;
+        }
+        // remember this possibility
+        Vec_IntClear( vLeavesBest2 );
+        for ( k = 0; k < Vec_IntSize(vCutLits); k++ )
+            Vec_IntPush( vLeavesBest2, s_DarLib->pDatas[k].iGunc );
+        p_OutBest    = s_DarLib->pSubgr0[Class][Out];
+        p_OutNumBest = Out;
+        p_LevelBest  = s_DarLib->pDatas[pObj->Num].Level;
+        p_GainBest   = nNodesGained;
+        p_ClassBest  = Class;
+//        assert( p_LevelBest <= Required );
+    }
+//clk = Abc_Clock() - clk;
+//p->ClassTimes[Class] += clk;
+//p->timeEval += clk;
+    assert( p_OutBest != -1 );
+    return p_OutBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Clears the fields of the nodes used i this cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar2_LibBuildClear_rec( Dar_LibObj_t * pObj, int * pCounter )
+{
+    if ( pObj->fTerm )
+        return;
+    pObj->Num = (*pCounter)++;
+    s_DarLib->pDatas[ pObj->Num ].iGunc = -1;
+    Dar2_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan0), pCounter );
+    Dar2_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan1), pCounter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reconstructs the best cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar2_LibBuildBest_rec( Gia_Man_t * p, Dar_LibObj_t * pObj )
+{
+    Gia_Obj_t * pNode;
+    Dar_LibDat_t * pData;
+    int iFanin0, iFanin1;
+    pData = s_DarLib->pDatas + pObj->Num;
+    if ( pData->iGunc >= 0 )
+        return pData->iGunc;
+    iFanin0 = Dar2_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan0) );
+    iFanin1 = Dar2_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan1) );
+    iFanin0 = Abc_LitNotCond( iFanin0, pObj->fCompl0 );
+    iFanin1 = Abc_LitNotCond( iFanin1, pObj->fCompl1 );
+    pData->iGunc = Gia_ManHashAnd( p, iFanin0, iFanin1 );
+    pNode = Gia_ManObj( p, Abc_Lit2Var(pData->iGunc) );
+    if ( Gia_ObjIsAnd( pNode ) )
+        Gia_ObjSetAndLevel( p, pNode );
+    Gia_ObjSetPhase( p, pNode );
+    return pData->iGunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reconstructs the best cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar2_LibBuildBest( Gia_Man_t * p, Vec_Int_t * vLeavesBest2, int OutBest )
+{
+    int i, iLeaf, Counter = 4;
+    assert( Vec_IntSize(vLeavesBest2) == 4 );
+    Vec_IntForEachEntry( vLeavesBest2, iLeaf, i )
+        s_DarLib->pDatas[i].iGunc = iLeaf;
+    Dar2_LibBuildClear_rec( Dar_LibObj(s_DarLib, OutBest), &Counter );
+    return Dar2_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, OutBest) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluate and build the new node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar_LibEvalBuild( Gia_Man_t * p, Vec_Int_t * vCutLits, unsigned uTruth, int fKeepLevel, Vec_Int_t * vLeavesBest2 )
+{
+    int OutBest = Dar2_LibEval( p, vCutLits, uTruth, fKeepLevel, vLeavesBest2 );
+    return Dar2_LibBuildBest( p, vLeavesBest2, OutBest );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dar/darMan.c b/abc-build/src/opt/dar/darMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dar/darMan.c
@@ -0,0 +1,174 @@
+/**CFile****************************************************************
+
+  FileName    [darMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting.]
+
+  Synopsis    [AIG manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: darMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "darInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the rewriting manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dar_Man_t * Dar_ManStart( Aig_Man_t * pAig, Dar_RwrPar_t * pPars )
+{
+    Dar_Man_t * p;
+    Aig_ManCleanData( pAig );
+    p = ABC_ALLOC( Dar_Man_t, 1 );
+    memset( p, 0, sizeof(Dar_Man_t) );
+    p->pPars = pPars;
+    p->pAig  = pAig;
+    p->vCutNodes = Vec_PtrAlloc( 1000 );
+    p->pMemCuts = Aig_MmFixedStart( p->pPars->nCutsMax * sizeof(Dar_Cut_t), 1024 );
+    p->vLeavesBest = Vec_PtrAlloc( 4 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the rewriting manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_ManStop( Dar_Man_t * p )
+{
+    if ( p->pPars->fVerbose )
+        Dar_ManPrintStats( p );
+    if ( p->vCutNodes )
+        Vec_PtrFree( p->vCutNodes );
+    if ( p->pMemCuts )
+        Aig_MmFixedStop( p->pMemCuts, 0 );
+    if ( p->vLeavesBest ) 
+        Vec_PtrFree( p->vLeavesBest );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_ManPrintStats( Dar_Man_t * p )
+{
+    unsigned pCanons[222];
+    int Gain, i;
+    extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars );
+
+    Gain = p->nNodesInit - Aig_ManNodeNum(p->pAig);
+    printf( "Tried = %8d. Beg = %8d. End = %8d. Gain = %6d. (%6.2f %%).  Cut mem = %d MB\n", 
+        p->nNodesTried, p->nNodesInit, Aig_ManNodeNum(p->pAig), Gain, 100.0*Gain/p->nNodesInit, p->nCutMemUsed );
+    printf( "Cuts = %8d. Tried = %8d. Used = %8d. Bad = %5d. Skipped = %5d. Ave = %.2f.\n", 
+        p->nCutsAll, p->nCutsTried, p->nCutsUsed, p->nCutsBad, p->nCutsSkipped,
+        (float)p->nCutsUsed/Aig_ManNodeNum(p->pAig) );
+
+    printf( "Bufs = %5d. BufMax = %5d. BufReplace = %6d. BufFix = %6d.  Levels = %4d.\n", 
+        Aig_ManBufNum(p->pAig), p->pAig->nBufMax, p->pAig->nBufReplaces, p->pAig->nBufFixes, Aig_ManLevels(p->pAig) );
+    ABC_PRT( "Cuts  ", p->timeCuts );
+    ABC_PRT( "Eval  ", p->timeEval );
+    ABC_PRT( "Other ", p->timeOther );
+    ABC_PRT( "TOTAL ", p->timeTotal );
+
+    if ( !p->pPars->fVeryVerbose )
+        return;
+    Dar_LibReturnCanonicals( pCanons );
+    for ( i = 0; i < 222; i++ )
+    {
+        if ( p->ClassGains[i] == 0 && p->ClassTimes[i] == 0 )
+            continue;
+        printf( "%3d : ", i );
+        printf( "G = %6d (%5.2f %%)  ", p->ClassGains[i], Gain? 100.0*p->ClassGains[i]/Gain : 0.0 );
+        printf( "S = %8d (%5.2f %%)  ", p->ClassSubgs[i], p->nTotalSubgs? 100.0*p->ClassSubgs[i]/p->nTotalSubgs : 0.0 );
+        printf( "R = %7d   ", p->ClassGains[i]? p->ClassSubgs[i]/p->ClassGains[i] : 9999999 );
+//        Kit_DsdPrintFromTruth( pCanons + i, 4 );
+//        ABC_PRTP( "T", p->ClassTimes[i], p->timeEval );
+        printf( "\n" );
+    }
+    fflush( stdout );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+#if 0
+
+ABC_NAMESPACE_IMPL_END
+
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+void Dar_ManPrintScript()
+{
+    unsigned pCanons[222];
+    int i;
+    Dar_LibReturnCanonicals( pCanons );
+    for ( i = 1; i < 222; i++ )
+    {
+        Kit_DsdNtk_t * pNtk;
+        pNtk = Kit_DsdDecompose( pCanons + i, 4 );
+        printf( "    \"" );
+        Kit_DsdPrint( stdout, pNtk );
+        printf( "\",              /* %3d  */\n", i );
+        Kit_DsdNtkFree( pNtk );
+    }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dar/darPrec.c b/abc-build/src/opt/dar/darPrec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dar/darPrec.c
@@ -0,0 +1,394 @@
+/**CFile****************************************************************
+
+  FileName    [darPrec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting.]
+
+  Synopsis    [Truth table precomputation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: darPrec.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "darInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocated one-memory-chunk array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char ** Dar_ArrayAlloc( int nCols, int nRows, int Size )
+{
+    char ** pRes;
+    char * pBuffer;
+    int i;
+    assert( nCols > 0 && nRows > 0 && Size > 0 );
+    pBuffer = ABC_ALLOC( char, nCols * (sizeof(void *) + nRows * Size) );
+    pRes = (char **)pBuffer;
+    pRes[0] = pBuffer + nCols * sizeof(void *);
+    for ( i = 1; i < nCols; i++ )
+        pRes[i] = pRes[0] + i * nRows * Size;
+    return pRes;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the factorial.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int Dar_Factorial( int n )
+{
+    int i, Res = 1;
+    for ( i = 1; i <= n; i++ )
+        Res *= i;
+    return Res;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Fills in the array of permutations.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void Dar_Permutations_rec( char ** pRes, int nFact, int n, char Array[] )
+{
+    char ** pNext;
+    int nFactNext;
+    int iTemp, iCur, iLast, k;
+
+    if ( n == 1 )
+    {
+        pRes[0][0] = Array[0];
+        return;
+    }
+
+    // get the next factorial
+    nFactNext = nFact / n;
+    // get the last entry
+    iLast = n - 1;
+
+    for ( iCur = 0; iCur < n; iCur++ )
+    {
+        // swap Cur and Last
+        iTemp        = Array[iCur];
+        Array[iCur]  = Array[iLast];
+        Array[iLast] = iTemp;
+
+        // get the pointer to the current section
+        pNext = pRes + (n - 1 - iCur) * nFactNext;
+
+        // set the last entry 
+        for ( k = 0; k < nFactNext; k++ )
+            pNext[k][iLast] = Array[iLast];
+
+        // call recursively for this part
+        Dar_Permutations_rec( pNext, nFactNext, n - 1, Array );
+
+        // swap them back
+        iTemp        = Array[iCur];
+        Array[iCur]  = Array[iLast];
+        Array[iLast] = iTemp;
+    }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the set of all permutations.]
+
+  Description [The number of permutations in the array is n!. The number of
+  entries in each permutation is n. Therefore, the resulting array is a 
+  two-dimentional array of the size: n! x n. To free the resulting array,
+  call ABC_FREE() on the pointer returned by this procedure.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+char ** Dar_Permutations( int n )
+{
+    char Array[50];
+    char ** pRes;
+    int nFact, i;
+    // allocate memory
+    nFact = Dar_Factorial( n );
+    pRes  = Dar_ArrayAlloc( nFact, n, sizeof(char) );
+    // fill in the permutations
+    for ( i = 0; i < n; i++ )
+        Array[i] = i;
+    Dar_Permutations_rec( pRes, nFact, n, Array );
+    // print the permutations
+/*
+    {
+    int i, k;
+    for ( i = 0; i < nFact; i++ )
+    {
+        printf( "{" );
+        for ( k = 0; k < n; k++ )
+            printf( " %d", pRes[i][k] );
+        printf( " }\n" );
+    }
+    }
+*/
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Permutes the given vector of minterms.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_TruthPermute_int( int * pMints, int nMints, char * pPerm, int nVars, int * pMintsP )
+{
+    int m, v;
+    // clean the storage for minterms
+    memset( pMintsP, 0, sizeof(int) * nMints );
+    // go through minterms and add the variables
+    for ( m = 0; m < nMints; m++ )
+        for ( v = 0; v < nVars; v++ )
+            if ( pMints[m] & (1 << v) )
+                pMintsP[m] |= (1 << pPerm[v]);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Permutes the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Dar_TruthPermute( unsigned Truth, char * pPerms, int nVars, int fReverse )
+{
+    unsigned Result;
+    int * pMints;
+    int * pMintsP;
+    int nMints;
+    int i, m;
+
+    assert( nVars < 6 );
+    nMints  = (1 << nVars);
+    pMints  = ABC_ALLOC( int, nMints );
+    pMintsP = ABC_ALLOC( int, nMints );
+    for ( i = 0; i < nMints; i++ )
+        pMints[i] = i;
+
+    Dar_TruthPermute_int( pMints, nMints, pPerms, nVars, pMintsP );
+
+    Result = 0;
+    if ( fReverse )
+    {
+        for ( m = 0; m < nMints; m++ )
+            if ( Truth & (1 << pMintsP[m]) )
+                Result |= (1 << m);
+    }
+    else
+    {
+        for ( m = 0; m < nMints; m++ )
+            if ( Truth & (1 << m) )
+                Result |= (1 << pMintsP[m]);
+    }
+
+    ABC_FREE( pMints );
+    ABC_FREE( pMintsP );
+
+    return Result;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Changes the phase of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Dar_TruthPolarize( unsigned uTruth, int Polarity, int nVars )
+{
+    // elementary truth tables
+    static unsigned Signs[5] = {
+        0xAAAAAAAA,    // 1010 1010 1010 1010 1010 1010 1010 1010
+        0xCCCCCCCC,    // 1010 1010 1010 1010 1010 1010 1010 1010
+        0xF0F0F0F0,    // 1111 0000 1111 0000 1111 0000 1111 0000
+        0xFF00FF00,    // 1111 1111 0000 0000 1111 1111 0000 0000
+        0xFFFF0000     // 1111 1111 1111 1111 0000 0000 0000 0000
+    };
+    unsigned uTruthRes, uCof0, uCof1;
+    int nMints, Shift, v;
+    assert( nVars < 6 );
+    nMints = (1 << nVars);
+    uTruthRes = uTruth;
+    for ( v = 0; v < nVars; v++ )
+        if ( Polarity & (1 << v) )
+        {
+            uCof0  = uTruth & ~Signs[v];
+            uCof1  = uTruth &  Signs[v];
+            Shift  = (1 << v);
+            uCof0 <<= Shift;
+            uCof1 >>= Shift;
+            uTruth = uCof0 | uCof1;
+        }
+    return uTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes NPN canonical forms for 4-variable functions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap )
+{
+    unsigned short * uCanons;
+    unsigned char * uMap;
+    unsigned uTruth, uPhase, uPerm;
+    char ** pPerms4, * uPhases, * uPerms;
+    int nFuncs, nClasses;
+    int i, k;
+
+    nFuncs  = (1 << 16);
+    uCanons = ABC_CALLOC( unsigned short, nFuncs );
+    uPhases = ABC_CALLOC( char, nFuncs );
+    uPerms  = ABC_CALLOC( char, nFuncs );
+    uMap    = ABC_CALLOC( unsigned char, nFuncs );
+    pPerms4 = Dar_Permutations( 4 );
+
+    nClasses = 1;
+    nFuncs = (1 << 15);
+    for ( uTruth = 1; uTruth < (unsigned)nFuncs; uTruth++ )
+    {
+        // skip already assigned
+        if ( uCanons[uTruth] )
+        {
+            assert( uTruth > uCanons[uTruth] );
+            uMap[~uTruth & 0xFFFF] = uMap[uTruth] = uMap[uCanons[uTruth]];
+            continue;
+        }
+        uMap[uTruth] = nClasses++;
+        for ( i = 0; i < 16; i++ )
+        {
+            uPhase = Dar_TruthPolarize( uTruth, i, 4 );
+            for ( k = 0; k < 24; k++ )
+            {
+                uPerm = Dar_TruthPermute( uPhase, pPerms4[k], 4, 0 );
+                if ( uCanons[uPerm] == 0 )
+                {
+                    uCanons[uPerm] = uTruth;
+                    uPhases[uPerm] = i;
+                    uPerms[uPerm]  = k;
+                    uMap[uPerm]    = uMap[uTruth];
+
+                    uPerm = ~uPerm & 0xFFFF;
+                    uCanons[uPerm] = uTruth;
+                    uPhases[uPerm] = i | 16;
+                    uPerms[uPerm]  = k;
+                    uMap[uPerm]    = uMap[uTruth];
+                }
+                else
+                    assert( uCanons[uPerm] == uTruth );
+            }
+            uPhase = Dar_TruthPolarize( ~uTruth & 0xFFFF, i, 4 ); 
+            for ( k = 0; k < 24; k++ )
+            {
+                uPerm = Dar_TruthPermute( uPhase, pPerms4[k], 4, 0 );
+                if ( uCanons[uPerm] == 0 )
+                {
+                    uCanons[uPerm] = uTruth;
+                    uPhases[uPerm] = i;
+                    uPerms[uPerm]  = k;
+                    uMap[uPerm]    = uMap[uTruth];
+
+                    uPerm = ~uPerm & 0xFFFF;
+                    uCanons[uPerm] = uTruth;
+                    uPhases[uPerm] = i | 16;
+                    uPerms[uPerm]  = k;
+                    uMap[uPerm]    = uMap[uTruth];
+                }
+                else
+                    assert( uCanons[uPerm] == uTruth );
+            }
+        }
+    }
+    for ( uTruth = 1; uTruth < 0xffff; uTruth++ )
+        assert( uMap[uTruth] != 0 );
+    uPhases[(1<<16)-1] = 16;
+    assert( nClasses == 222 );
+    ABC_FREE( pPerms4 );
+    if ( puCanons ) 
+        *puCanons = uCanons;
+    else
+        ABC_FREE( uCanons );
+    if ( puPhases ) 
+        *puPhases = uPhases;
+    else
+        ABC_FREE( uPhases );
+    if ( puPerms ) 
+        *puPerms = uPerms;
+    else
+        ABC_FREE( uPerms );
+    if ( puMap ) 
+        *puMap = uMap;
+    else
+        ABC_FREE( uMap );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dar/darRefact.c b/abc-build/src/opt/dar/darRefact.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dar/darRefact.c
@@ -0,0 +1,639 @@
+/**CFile****************************************************************
+
+  FileName    [darRefact.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting.]
+
+  Synopsis    [Refactoring.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: darRefact.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "darInt.h"
+#include "bool/kit/kit.h"
+
+#include "bool/bdc/bdc.h"
+#include "bool/bdc/bdcInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// the refactoring manager
+typedef struct Ref_Man_t_            Ref_Man_t;
+struct Ref_Man_t_
+{
+    // input data
+    Dar_RefPar_t *   pPars;          // rewriting parameters
+    Aig_Man_t *      pAig;           // AIG manager 
+    // computed cuts
+    Vec_Vec_t *      vCuts;          // the storage for cuts
+    // truth table and ISOP
+    Vec_Ptr_t *      vTruthElem;     // elementary truth tables
+    Vec_Ptr_t *      vTruthStore;    // storage for truth tables
+    Vec_Int_t *      vMemory;        // storage for ISOP
+    Vec_Ptr_t *      vCutNodes;      // storage for internal nodes of the cut
+    // various data members
+    Vec_Ptr_t *      vLeavesBest;    // the best set of leaves
+    Kit_Graph_t *    pGraphBest;     // the best factored form
+    int              GainBest;       // the best gain
+    int              LevelBest;      // the level of node with the best gain
+    // bi-decomposition
+    Bdc_Par_t        DecPars;        // decomposition parameters
+    Bdc_Man_t *      pManDec;        // decomposition manager
+    // node statistics
+    int              nNodesInit;     // the initial number of nodes
+    int              nNodesTried;    // the number of nodes tried
+    int              nNodesBelow;    // the number of nodes below the level limit
+    int              nNodesExten;    // the number of nodes with extended cut
+    int              nCutsUsed;      // the number of rewriting steps
+    int              nCutsTried;     // the number of cuts tries
+    // timing statistics
+    abctime          timeCuts;
+    abctime          timeEval;
+    abctime          timeOther;
+    abctime          timeTotal;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the structure with default assignment of parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_ManDefaultRefParams( Dar_RefPar_t * pPars )
+{
+    memset( pPars, 0, sizeof(Dar_RefPar_t) );
+    pPars->nMffcMin     =  2;  // the min MFFC size for which refactoring is used
+    pPars->nLeafMax     = 12;  // the max number of leaves of a cut
+    pPars->nCutsMax     =  5;  // the max number of cuts to consider  
+    pPars->fUpdateLevel =  0;
+    pPars->fUseZeros    =  0;
+    pPars->fVerbose     =  0;
+    pPars->fVeryVerbose =  0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the rewriting manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ref_Man_t * Dar_ManRefStart( Aig_Man_t * pAig, Dar_RefPar_t * pPars )
+{
+    Ref_Man_t * p;
+    // start the manager
+    p = ABC_ALLOC( Ref_Man_t, 1 );
+    memset( p, 0, sizeof(Ref_Man_t) );
+    p->pAig         = pAig;
+    p->pPars        = pPars;
+    // other data
+    p->vCuts        = Vec_VecStart( pPars->nCutsMax );
+    p->vTruthElem   = Vec_PtrAllocTruthTables( pPars->nLeafMax );
+    p->vTruthStore  = Vec_PtrAllocSimInfo( 1024, Kit_TruthWordNum(pPars->nLeafMax) );
+    p->vMemory      = Vec_IntAlloc( 1 << 16 );
+    p->vCutNodes    = Vec_PtrAlloc( 256 );
+    p->vLeavesBest  = Vec_PtrAlloc( pPars->nLeafMax );
+    // alloc bi-decomposition manager
+    p->DecPars.nVarsMax = pPars->nLeafMax;
+    p->DecPars.fVerbose = pPars->fVerbose;
+    p->DecPars.fVeryVerbose = 0;
+//    p->pManDec = Bdc_ManAlloc( &p->DecPars );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints out the statistics of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_ManRefPrintStats( Ref_Man_t * p )
+{
+    int Gain = p->nNodesInit - Aig_ManNodeNum(p->pAig);
+    printf( "NodesBeg = %8d. NodesEnd = %8d. Gain = %6d. (%6.2f %%).\n", 
+        p->nNodesInit, Aig_ManNodeNum(p->pAig), Gain, 100.0*Gain/p->nNodesInit );
+    printf( "Tried = %6d. Below = %5d. Extended = %5d.  Used = %5d.  Levels = %4d.\n", 
+        p->nNodesTried, p->nNodesBelow, p->nNodesExten, p->nCutsUsed, Aig_ManLevels(p->pAig) );
+    ABC_PRT( "Cuts  ", p->timeCuts );
+    ABC_PRT( "Eval  ", p->timeEval );
+    ABC_PRT( "Other ", p->timeOther );
+    ABC_PRT( "TOTAL ", p->timeTotal );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the rewriting manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dar_ManRefStop( Ref_Man_t * p )
+{
+    if ( p->pManDec )
+        Bdc_ManFree( p->pManDec );
+    if ( p->pPars->fVerbose )
+        Dar_ManRefPrintStats( p );
+    Vec_VecFree( p->vCuts );
+    Vec_PtrFree( p->vTruthElem );
+    Vec_PtrFree( p->vTruthStore );
+    Vec_PtrFree( p->vLeavesBest );
+    Vec_IntFree( p->vMemory );
+    Vec_PtrFree( p->vCutNodes );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ref_ObjComputeCuts( Aig_Man_t * pAig, Aig_Obj_t * pRoot, Vec_Vec_t * vCuts )
+{
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ref_ObjPrint( Aig_Obj_t * pObj )
+{
+    printf( "%d", pObj? Aig_Regular(pObj)->Id : -1 );
+    if ( pObj )
+        printf( "(%d) ", Aig_IsComplement(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of new nodes added when using this graph.]
+
+  Description [AIG nodes for the fanins should be assigned to pNode->pFunc 
+  of the leaves of the graph before calling this procedure. 
+  Returns -1 if the number of nodes and levels exceeded the given limit or 
+  the number of levels exceeded the maximum allowed level.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar_RefactTryGraph( Aig_Man_t * pAig, Aig_Obj_t * pRoot, Vec_Ptr_t * vCut, Kit_Graph_t * pGraph, int NodeMax, int LevelMax )
+{
+    Kit_Node_t * pNode, * pNode0, * pNode1;
+    Aig_Obj_t * pAnd, * pAnd0, * pAnd1;
+    int i, Counter, LevelNew, LevelOld;
+    // check for constant function or a literal
+    if ( Kit_GraphIsConst(pGraph) || Kit_GraphIsVar(pGraph) )
+        return 0;
+    // set the levels of the leaves
+    Kit_GraphForEachLeaf( pGraph, pNode, i )
+    {
+        pNode->pFunc = Vec_PtrEntry(vCut, i);
+        pNode->Level = Aig_Regular((Aig_Obj_t *)pNode->pFunc)->Level;
+        assert( Aig_Regular((Aig_Obj_t *)pNode->pFunc)->Level < (1<<24)-1 );
+    }
+//printf( "Trying:\n" );
+    // compute the AIG size after adding the internal nodes
+    Counter = 0;
+    Kit_GraphForEachNode( pGraph, pNode, i )
+    {
+        // get the children of this node
+        pNode0 = Kit_GraphNode( pGraph, pNode->eEdge0.Node );
+        pNode1 = Kit_GraphNode( pGraph, pNode->eEdge1.Node );
+        // get the AIG nodes corresponding to the children 
+        pAnd0 = (Aig_Obj_t *)pNode0->pFunc; 
+        pAnd1 = (Aig_Obj_t *)pNode1->pFunc; 
+        if ( pAnd0 && pAnd1 )
+        {
+            // if they are both present, find the resulting node
+            pAnd0 = Aig_NotCond( pAnd0, pNode->eEdge0.fCompl );
+            pAnd1 = Aig_NotCond( pAnd1, pNode->eEdge1.fCompl );
+            pAnd  = Aig_TableLookupTwo( pAig, pAnd0, pAnd1 );
+            // return -1 if the node is the same as the original root
+            if ( Aig_Regular(pAnd) == pRoot )
+                return -1;
+        }
+        else
+            pAnd = NULL;
+        // count the number of added nodes
+        if ( pAnd == NULL || Aig_ObjIsTravIdCurrent(pAig, Aig_Regular(pAnd)) )
+        {
+            if ( ++Counter > NodeMax )
+                return -1;
+        }
+        // count the number of new levels
+        LevelNew = 1 + Abc_MaxInt( pNode0->Level, pNode1->Level );
+        if ( pAnd )
+        {
+            if ( Aig_Regular(pAnd) == Aig_ManConst1(pAig) )
+                LevelNew = 0;
+            else if ( Aig_Regular(pAnd) == Aig_Regular(pAnd0) )
+                LevelNew = (int)Aig_Regular(pAnd0)->Level;
+            else if ( Aig_Regular(pAnd) == Aig_Regular(pAnd1) )
+                LevelNew = (int)Aig_Regular(pAnd1)->Level;
+            LevelOld = (int)Aig_Regular(pAnd)->Level;
+//            assert( LevelNew == LevelOld );
+        }
+        if ( LevelNew > LevelMax )
+            return -1;
+        pNode->pFunc = pAnd;
+        pNode->Level = LevelNew;
+/*
+printf( "Checking " );
+Ref_ObjPrint( pAnd0 );
+printf( " and " );
+Ref_ObjPrint( pAnd1 );
+printf( "  Result " );
+Ref_ObjPrint( pNode->pFunc );
+printf( "\n" );
+*/
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Dar_RefactBuildGraph( Aig_Man_t * pAig, Vec_Ptr_t * vCut, Kit_Graph_t * pGraph )
+{
+    Aig_Obj_t * pAnd0, * pAnd1;
+    Kit_Node_t * pNode = NULL;
+    int i;
+    // check for constant function
+    if ( Kit_GraphIsConst(pGraph) )
+        return Aig_NotCond( Aig_ManConst1(pAig), Kit_GraphIsComplement(pGraph) );
+    // set the leaves
+    Kit_GraphForEachLeaf( pGraph, pNode, i )
+        pNode->pFunc = Vec_PtrEntry(vCut, i);
+    // check for a literal
+    if ( Kit_GraphIsVar(pGraph) )
+        return Aig_NotCond( (Aig_Obj_t *)Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) );
+    // build the AIG nodes corresponding to the AND gates of the graph
+//printf( "Building (current number %d):\n", Aig_ManObjNumMax(pAig) );
+    Kit_GraphForEachNode( pGraph, pNode, i )
+    {
+        pAnd0 = Aig_NotCond( (Aig_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); 
+        pAnd1 = Aig_NotCond( (Aig_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); 
+        pNode->pFunc = Aig_And( pAig, pAnd0, pAnd1 );
+/*
+printf( "Checking " );
+Ref_ObjPrint( pAnd0 );
+printf( " and " );
+Ref_ObjPrint( pAnd1 );
+printf( "  Result " );
+Ref_ObjPrint( pNode->pFunc );
+printf( "\n" );
+*/
+    }
+    // complement the result if necessary
+    return Aig_NotCond( (Aig_Obj_t *)pNode->pFunc, Kit_GraphIsComplement(pGraph) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar_ManRefactorTryCuts( Ref_Man_t * p, Aig_Obj_t * pObj, int nNodesSaved, int Required )
+{
+    Vec_Ptr_t * vCut;
+    Kit_Graph_t * pGraphCur;
+    int k, RetValue, GainCur, nNodesAdded;
+    unsigned * pTruth;
+
+    p->GainBest = -1;
+    p->pGraphBest = NULL;
+    Vec_VecForEachLevel( p->vCuts, vCut, k )
+    {
+        if ( Vec_PtrSize(vCut) == 0 )
+            continue;
+//        if ( Vec_PtrSize(vCut) != 0 && Vec_PtrSize(Vec_VecEntry(p->vCuts, k+1)) != 0 )
+//            continue;
+
+        p->nCutsTried++;
+        // get the cut nodes
+        Aig_ObjCollectCut( pObj, vCut, p->vCutNodes );
+        // get the truth table
+        pTruth = Aig_ManCutTruth( pObj, vCut, p->vCutNodes, p->vTruthElem, p->vTruthStore );
+        if ( Kit_TruthIsConst0(pTruth, Vec_PtrSize(vCut)) )
+        {
+            p->GainBest = Aig_NodeMffcSupp( p->pAig, pObj, 0, NULL );
+            p->pGraphBest = Kit_GraphCreateConst0();
+            Vec_PtrCopy( p->vLeavesBest, vCut );
+            return p->GainBest;
+        }
+        if ( Kit_TruthIsConst1(pTruth, Vec_PtrSize(vCut)) )
+        {
+            p->GainBest = Aig_NodeMffcSupp( p->pAig, pObj, 0, NULL );
+            p->pGraphBest = Kit_GraphCreateConst1();
+            Vec_PtrCopy( p->vLeavesBest, vCut );
+            return p->GainBest;
+        }
+
+        // try the positive phase
+        RetValue = Kit_TruthIsop( pTruth, Vec_PtrSize(vCut), p->vMemory, 0 );
+        if ( RetValue > -1 )
+        {
+            pGraphCur = Kit_SopFactor( p->vMemory, 0, Vec_PtrSize(vCut), p->vMemory );
+/*
+{
+    int RetValue;
+    RetValue = Bdc_ManDecompose( p->pManDec, pTruth, NULL, Vec_PtrSize(vCut), NULL, 1000 );
+    printf( "Graph = %d. Bidec = %d.\n", Kit_GraphNodeNum(pGraphCur), RetValue );
+}
+*/
+            nNodesAdded = Dar_RefactTryGraph( p->pAig, pObj, vCut, pGraphCur, nNodesSaved - !p->pPars->fUseZeros, Required );
+            if ( nNodesAdded > -1 )
+            {
+                GainCur = nNodesSaved - nNodesAdded;
+                if ( p->GainBest < GainCur || (p->GainBest == GainCur && 
+                    (Kit_GraphIsConst(pGraphCur) || Kit_GraphRootLevel(pGraphCur) < Kit_GraphRootLevel(p->pGraphBest))) )
+                {
+                    p->GainBest = GainCur;
+                    if ( p->pGraphBest )
+                        Kit_GraphFree( p->pGraphBest );
+                    p->pGraphBest = pGraphCur;
+                    Vec_PtrCopy( p->vLeavesBest, vCut );
+                }
+                else
+                    Kit_GraphFree( pGraphCur );
+            }
+            else
+                Kit_GraphFree( pGraphCur );
+        }
+        // try negative phase
+        Kit_TruthNot( pTruth, pTruth, Vec_PtrSize(vCut) );
+        RetValue = Kit_TruthIsop( pTruth, Vec_PtrSize(vCut), p->vMemory, 0 );
+//        Kit_TruthNot( pTruth, pTruth, Vec_PtrSize(vCut) );
+        if ( RetValue > -1 )
+        {
+            pGraphCur = Kit_SopFactor( p->vMemory, 1, Vec_PtrSize(vCut), p->vMemory );
+/*
+{
+    int RetValue;
+    RetValue = Bdc_ManDecompose( p->pManDec, pTruth, NULL, Vec_PtrSize(vCut), NULL, 1000 );
+    printf( "Graph = %d. Bidec = %d.\n", Kit_GraphNodeNum(pGraphCur), RetValue );
+}
+*/
+            nNodesAdded = Dar_RefactTryGraph( p->pAig, pObj, vCut, pGraphCur, nNodesSaved - !p->pPars->fUseZeros, Required );
+            if ( nNodesAdded > -1 )
+            {
+                GainCur = nNodesSaved - nNodesAdded;
+                if ( p->GainBest < GainCur || (p->GainBest == GainCur && 
+                    (Kit_GraphIsConst(pGraphCur) || Kit_GraphRootLevel(pGraphCur) < Kit_GraphRootLevel(p->pGraphBest))) )
+                {
+                    p->GainBest = GainCur;
+                    if ( p->pGraphBest )
+                        Kit_GraphFree( p->pGraphBest );
+                    p->pGraphBest = pGraphCur;
+                    Vec_PtrCopy( p->vLeavesBest, vCut );
+                }
+                else
+                    Kit_GraphFree( pGraphCur );
+            }
+            else
+                Kit_GraphFree( pGraphCur );
+        }
+    }
+
+    return p->GainBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if a non-PI node has nLevelMin or below.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar_ObjCutLevelAchieved( Vec_Ptr_t * vCut, int nLevelMin )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i )
+        if ( !Aig_ObjIsCi(pObj) && (int)pObj->Level <= nLevelMin )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+int Dar_ManRefactor( Aig_Man_t * pAig, Dar_RefPar_t * pPars )
+{
+//    Bar_Progress_t * pProgress;
+    Ref_Man_t * p;
+    Vec_Ptr_t * vCut, * vCut2;
+    Aig_Obj_t * pObj, * pObjNew;
+    int nNodesOld, nNodeBefore, nNodeAfter, nNodesSaved, nNodesSaved2;
+    int i, Required, nLevelMin;
+    abctime clkStart, clk;
+
+    // start the manager
+    p = Dar_ManRefStart( pAig, pPars );
+    // remove dangling nodes
+    Aig_ManCleanup( pAig );
+    // if updating levels is requested, start fanout and timing
+    Aig_ManFanoutStart( pAig );
+    if ( p->pPars->fUpdateLevel )
+        Aig_ManStartReverseLevels( pAig, 0 );
+
+    // resynthesize each node once
+    clkStart = Abc_Clock();
+    vCut = Vec_VecEntry( p->vCuts, 0 );
+    vCut2 = Vec_VecEntry( p->vCuts, 1 );
+    p->nNodesInit = Aig_ManNodeNum(pAig);
+    nNodesOld = Vec_PtrSize( pAig->vObjs );
+//    pProgress = Bar_ProgressStart( stdout, nNodesOld );
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+//        Bar_ProgressUpdate( pProgress, i, NULL );
+        if ( !Aig_ObjIsNode(pObj) )
+            continue;
+        if ( i > nNodesOld )
+            break;
+        if ( pAig->Time2Quit && !(i & 256) && Abc_Clock() > pAig->Time2Quit )
+            break;
+        Vec_VecClear( p->vCuts );
+
+//printf( "\nConsidering node %d.\n", pObj->Id );
+        // get the bounded MFFC size
+clk = Abc_Clock();
+        nLevelMin = Abc_MaxInt( 0, Aig_ObjLevel(pObj) - 10 );
+        nNodesSaved = Aig_NodeMffcSupp( pAig, pObj, nLevelMin, vCut );
+        if ( nNodesSaved < p->pPars->nMffcMin ) // too small to consider
+        {
+p->timeCuts += Abc_Clock() - clk;
+            continue; 
+        }
+        p->nNodesTried++;
+        if ( Vec_PtrSize(vCut) > p->pPars->nLeafMax ) // get one reconv-driven cut
+        {
+            Aig_ManFindCut( pObj, vCut, p->vCutNodes, p->pPars->nLeafMax, 50 );
+            nNodesSaved = Aig_NodeMffcLabelCut( p->pAig, pObj, vCut );
+        }
+        else if ( Vec_PtrSize(vCut) < p->pPars->nLeafMax - 2 && p->pPars->fExtend )
+        {
+            if ( !Dar_ObjCutLevelAchieved(vCut, nLevelMin) )
+            {
+                if ( Aig_NodeMffcExtendCut( pAig, pObj, vCut, vCut2 ) )
+                {
+                    nNodesSaved2 = Aig_NodeMffcLabelCut( p->pAig, pObj, vCut );
+                    assert( nNodesSaved2 == nNodesSaved );
+                }
+                if ( Vec_PtrSize(vCut2) > p->pPars->nLeafMax )
+                    Vec_PtrClear(vCut2);
+                if ( Vec_PtrSize(vCut2) > 0 )
+                {
+                    p->nNodesExten++;
+//                    printf( "%d(%d) ", Vec_PtrSize(vCut), Vec_PtrSize(vCut2) );
+                }
+            }
+            else
+                p->nNodesBelow++;
+        }
+p->timeCuts += Abc_Clock() - clk;
+
+        // try the cuts
+clk = Abc_Clock();
+        Required = pAig->vLevelR? Aig_ObjRequiredLevel(pAig, pObj) : ABC_INFINITY;
+        Dar_ManRefactorTryCuts( p, pObj, nNodesSaved, Required );
+p->timeEval += Abc_Clock() - clk;
+
+        // check the best gain
+        if ( !(p->GainBest > 0 || (p->GainBest == 0 && p->pPars->fUseZeros)) )
+        {
+            if ( p->pGraphBest )
+                Kit_GraphFree( p->pGraphBest );
+            continue;
+        }
+//printf( "\n" );
+
+        // if we end up here, a rewriting step is accepted
+        nNodeBefore = Aig_ManNodeNum( pAig );
+        pObjNew = Dar_RefactBuildGraph( pAig, p->vLeavesBest, p->pGraphBest );
+        assert( (int)Aig_Regular(pObjNew)->Level <= Required );
+        // replace the node
+        Aig_ObjReplace( pAig, pObj, pObjNew, p->pPars->fUpdateLevel );
+        // compare the gains
+        nNodeAfter = Aig_ManNodeNum( pAig );
+        assert( p->GainBest <= nNodeBefore - nNodeAfter );
+        Kit_GraphFree( p->pGraphBest );
+        p->nCutsUsed++;
+//        break;
+    }
+p->timeTotal = Abc_Clock() - clkStart;
+p->timeOther = p->timeTotal - p->timeCuts - p->timeEval;
+
+//    Bar_ProgressStop( pProgress );
+    // put the nodes into the DFS order and reassign their IDs
+//    Aig_NtkReassignIds( p );
+    // fix the levels
+    Aig_ManFanoutStop( pAig );
+    if ( p->pPars->fUpdateLevel )
+        Aig_ManStopReverseLevels( pAig );
+/*
+    Aig_ManForEachObj( p->pAig, pObj, i )
+        if ( Aig_ObjIsNode(pObj) && Aig_ObjRefs(pObj) == 0 )
+        {
+            printf( "Unreferenced " );
+            Aig_ObjPrintVerbose( pObj, 0 );
+            printf( "\n" );
+        }
+*/
+    // remove dangling nodes (they should not be here!)
+    Aig_ManCleanup( pAig );
+
+    // stop the rewriting manager
+    Dar_ManRefStop( p );
+//    Aig_ManCheckPhase( pAig );
+    if ( !Aig_ManCheck( pAig ) )
+    {
+        printf( "Dar_ManRefactor: The network check has failed.\n" );
+        return 0;
+    }
+    return 1;
+
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dar/darResub.c b/abc-build/src/opt/dar/darResub.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dar/darResub.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+  FileName    [darResub.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: darResub.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "darInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dar/darScript.c b/abc-build/src/opt/dar/darScript.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dar/darScript.c
@@ -0,0 +1,911 @@
+/**CFile****************************************************************
+
+  FileName    [darScript.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting.]
+
+  Synopsis    [Rewriting scripts.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: darScript.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "darInt.h"
+#include "proof/dch/dch.h"
+#include "aig/gia/gia.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one iteration of AIG rewriting.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Dar_ManRewriteDefault( Aig_Man_t * pAig )
+{
+    Aig_Man_t * pTemp;
+    Dar_RwrPar_t Pars, * pPars = &Pars;
+    Dar_ManDefaultRwrParams( pPars );
+    pAig = Aig_ManDupDfs( pAig ); 
+    Dar_ManRewrite( pAig, pPars );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    return pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reproduces script "rwsat".]
+
+  Description []
+               
+  SideEffects [This procedure does not tighten level during restructuring.]
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Dar_ManRwsat( Aig_Man_t * pAig, int fBalance, int fVerbose )
+//alias rwsat       "st; rw -l; b -l; rw -l; rf -l"
+{
+    Aig_Man_t * pTemp;
+    abctime Time = pAig->Time2Quit;
+
+    Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr;
+    Dar_RefPar_t ParsRef, * pParsRef = &ParsRef;
+
+    Dar_ManDefaultRwrParams( pParsRwr );
+    Dar_ManDefaultRefParams( pParsRef );
+
+    pParsRwr->fUpdateLevel = 0;
+    pParsRef->fUpdateLevel = 0;
+
+    pParsRwr->fVerbose = fVerbose;
+    pParsRef->fVerbose = fVerbose;
+//printf( "1" );
+    pAig = Aig_ManDupDfs( pAig ); 
+    if ( fVerbose ) printf( "Starting:  " ), Aig_ManPrintStats( pAig );
+
+//printf( "2" );
+    // balance
+    if ( fBalance )
+    {
+    pAig->Time2Quit = Time;
+    pAig = Dar_ManBalance( pTemp = pAig, 0 );
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Balance:   " ), Aig_ManPrintStats( pAig );
+    if ( Time && Abc_Clock() > Time )
+        { if ( pAig ) Aig_ManStop( pAig ); return NULL; }
+    }
+   
+//Aig_ManDumpBlif( pAig, "inter.blif", NULL, NULL );
+//printf( "3" );
+    // rewrite
+    pAig->Time2Quit = Time;
+    Dar_ManRewrite( pAig, pParsRwr );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Rewrite:   " ), Aig_ManPrintStats( pAig );
+    if ( Time && Abc_Clock() > Time )
+        { if ( pAig ) Aig_ManStop( pAig ); return NULL; }
+
+//printf( "4" );
+    // refactor
+    pAig->Time2Quit = Time;
+    Dar_ManRefactor( pAig, pParsRef );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Refactor:  " ), Aig_ManPrintStats( pAig );
+    if ( Time && Abc_Clock() > Time )
+        { if ( pAig ) Aig_ManStop( pAig ); return NULL; }
+
+//printf( "5" );
+    // balance
+    if ( fBalance )
+    {
+    pAig->Time2Quit = Time;
+    pAig = Dar_ManBalance( pTemp = pAig, 0 );
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Balance:   " ), Aig_ManPrintStats( pAig );
+    if ( Time && Abc_Clock() > Time )
+        { if ( pAig ) Aig_ManStop( pAig ); return NULL; }
+    }
+
+//printf( "6" );
+    // rewrite
+    pAig->Time2Quit = Time;
+    Dar_ManRewrite( pAig, pParsRwr );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Rewrite:   " ), Aig_ManPrintStats( pAig );
+    if ( Time && Abc_Clock() > Time )
+        { if ( pAig ) Aig_ManStop( pAig ); return NULL; }
+
+//printf( "7" );
+    return pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reproduces script "compress".]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose )
+//alias compress2   "b -l; rw -l; rwz -l; b -l; rwz -l; b -l"
+{
+    Aig_Man_t * pTemp;
+
+    Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr;
+    Dar_RefPar_t ParsRef, * pParsRef = &ParsRef;
+
+    Dar_ManDefaultRwrParams( pParsRwr );
+    Dar_ManDefaultRefParams( pParsRef );
+
+    pParsRwr->fUpdateLevel = fUpdateLevel;
+    pParsRef->fUpdateLevel = fUpdateLevel;
+
+    pParsRwr->fPower = fPower;
+
+    pParsRwr->fVerbose = 0;//fVerbose;
+    pParsRef->fVerbose = 0;//fVerbose;
+
+    pAig = Aig_ManDupDfs( pAig ); 
+    if ( fVerbose ) printf( "Starting:  " ), Aig_ManPrintStats( pAig );
+/*
+    // balance
+    if ( fBalance )
+    {
+    pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Balance:   " ), Aig_ManPrintStats( pAig );
+    }
+*/    
+    // rewrite
+    Dar_ManRewrite( pAig, pParsRwr );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Rewrite:   " ), Aig_ManPrintStats( pAig );
+    
+    // refactor
+    Dar_ManRefactor( pAig, pParsRef );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Refactor:  " ), Aig_ManPrintStats( pAig );
+
+    // balance
+    if ( fBalance )
+    {
+    pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Balance:   " ), Aig_ManPrintStats( pAig );
+    }
+
+    pParsRwr->fUseZeros = 1;
+    pParsRef->fUseZeros = 1;
+    
+    // rewrite
+    Dar_ManRewrite( pAig, pParsRwr );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "RewriteZ:  " ), Aig_ManPrintStats( pAig );
+
+    return pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reproduces script "compress2".]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose )
+//alias compress2   "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l"
+{
+    Aig_Man_t * pTemp;
+
+    Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr;
+    Dar_RefPar_t ParsRef, * pParsRef = &ParsRef;
+
+    Dar_ManDefaultRwrParams( pParsRwr );
+    Dar_ManDefaultRefParams( pParsRef );
+
+    pParsRwr->fUpdateLevel = fUpdateLevel;
+    pParsRef->fUpdateLevel = fUpdateLevel;
+    pParsRwr->fFanout = fFanout;
+    pParsRwr->fPower = fPower;
+
+    pParsRwr->fVerbose = 0;//fVerbose;
+    pParsRef->fVerbose = 0;//fVerbose;
+
+    pAig = Aig_ManDupDfs( pAig ); 
+    if ( fVerbose ) printf( "Starting:  " ), Aig_ManPrintStats( pAig );
+/*
+    // balance
+    if ( fBalance )
+    {
+    pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Balance:   " ), Aig_ManPrintStats( pAig );
+    }
+*/
+    // rewrite
+//    Dar_ManRewrite( pAig, pParsRwr );
+    pParsRwr->fUpdateLevel = 0;  // disable level update
+    Dar_ManRewrite( pAig, pParsRwr );
+    pParsRwr->fUpdateLevel = fUpdateLevel;  // reenable level update if needed
+
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Rewrite:   " ), Aig_ManPrintStats( pAig );
+    
+    // refactor
+    Dar_ManRefactor( pAig, pParsRef );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Refactor:  " ), Aig_ManPrintStats( pAig );
+
+    // balance
+//    if ( fBalance )
+    {
+    pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Balance:   " ), Aig_ManPrintStats( pAig );
+    }
+    
+    // rewrite
+    Dar_ManRewrite( pAig, pParsRwr );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Rewrite:   " ), Aig_ManPrintStats( pAig );
+
+    pParsRwr->fUseZeros = 1;
+    pParsRef->fUseZeros = 1;
+    
+    // rewrite
+    Dar_ManRewrite( pAig, pParsRwr );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "RewriteZ:  " ), Aig_ManPrintStats( pAig );
+
+    // balance
+    if ( fBalance )
+    {
+    pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Balance:   " ), Aig_ManPrintStats( pAig );
+    }
+    
+    // refactor
+    Dar_ManRefactor( pAig, pParsRef );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "RefactorZ: " ), Aig_ManPrintStats( pAig );
+    
+    // rewrite
+    Dar_ManRewrite( pAig, pParsRwr );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "RewriteZ:  " ), Aig_ManPrintStats( pAig );
+
+    // balance
+    if ( fBalance )
+    {
+    pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Balance:   " ), Aig_ManPrintStats( pAig );
+    }
+    return pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reproduces script "compress2".]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Dar_ManChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose )
+//alias resyn    "b; rw; rwz; b; rwz; b"
+//alias resyn2   "b; rw; rf; b; rw; rwz; b; rfz; rwz; b"
+{
+    Vec_Ptr_t * vAigs;
+
+    vAigs = Vec_PtrAlloc( 3 );
+    pAig = Aig_ManDupDfs(pAig);
+    Vec_PtrPush( vAigs, pAig );
+
+    pAig = Dar_ManCompress(pAig, fBalance, fUpdateLevel, fPower, fVerbose);
+    Vec_PtrPush( vAigs, pAig );
+//Aig_ManPrintStats( pAig );
+
+    pAig = Dar_ManCompress2(pAig, fBalance, fUpdateLevel, 1, fPower, fVerbose);
+    Vec_PtrPush( vAigs, pAig );
+//Aig_ManPrintStats( pAig );
+
+    pAig = (Aig_Man_t *)Vec_PtrEntry( vAigs, 1 );
+    return vAigs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reproduces script "compress2".]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose )
+{
+    Aig_Man_t * pMan, * pTemp;
+    Vec_Ptr_t * vAigs;
+    int i;
+    abctime clk;
+
+clk = Abc_Clock();
+//    vAigs = Dar_ManChoiceSynthesisExt();
+    vAigs = Dar_ManChoiceSynthesis( pAig, fBalance, fUpdateLevel, 0, fVerbose );
+
+    // swap the first and last network
+    // this should lead to the primary choice being "better" because of synthesis
+    // (it is also important when constructing choices)
+    if ( !fConstruct )
+    {
+        pMan = (Aig_Man_t *)Vec_PtrPop( vAigs );
+        Vec_PtrPush( vAigs, Vec_PtrEntry(vAigs,0) );
+        Vec_PtrWriteEntry( vAigs, 0, pMan );
+    }
+
+if ( fVerbose )
+{
+ABC_PRT( "Synthesis time", Abc_Clock() - clk );
+}
+clk = Abc_Clock();
+    if ( fConstruct )
+        pMan = Aig_ManChoiceConstructive( vAigs, fVerbose );
+    else
+        pMan = Aig_ManChoicePartitioned( vAigs, 300, nConfMax, nLevelMax, fVerbose );
+    Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, i )
+        Aig_ManStop( pTemp );
+    Vec_PtrFree( vAigs );
+if ( fVerbose )
+{
+ABC_PRT( "Choicing time ", Abc_Clock() - clk );
+}
+    return pMan;
+//    return NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Reproduces script "compress".]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Dar_NewCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose )
+//alias compress2   "b -l; rw -l; rwz -l; b -l; rwz -l; b -l"
+{
+    Aig_Man_t * pTemp;
+
+    Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr;
+    Dar_RefPar_t ParsRef, * pParsRef = &ParsRef;
+
+    Dar_ManDefaultRwrParams( pParsRwr );
+    Dar_ManDefaultRefParams( pParsRef );
+
+    pParsRwr->fUpdateLevel = fUpdateLevel;
+    pParsRef->fUpdateLevel = fUpdateLevel;
+
+    pParsRwr->fPower = fPower;
+
+    pParsRwr->fVerbose = 0;//fVerbose;
+    pParsRef->fVerbose = 0;//fVerbose;
+
+//    pAig = Aig_ManDupDfs( pAig ); 
+    if ( fVerbose ) printf( "Starting:  " ), Aig_ManPrintStats( pAig );
+
+    // rewrite
+    Dar_ManRewrite( pAig, pParsRwr );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Rewrite:   " ), Aig_ManPrintStats( pAig );
+    
+    // refactor
+    Dar_ManRefactor( pAig, pParsRef );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Refactor:  " ), Aig_ManPrintStats( pAig );
+
+    // balance
+    if ( fBalance )
+    {
+    pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Balance:   " ), Aig_ManPrintStats( pAig );
+    }
+
+    pParsRwr->fUseZeros = 1;
+    pParsRef->fUseZeros = 1;
+    
+    // rewrite
+    Dar_ManRewrite( pAig, pParsRwr );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "RewriteZ:  " ), Aig_ManPrintStats( pAig );
+
+    return pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reproduces script "compress2".]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Dar_NewCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fLightSynth, int fVerbose )
+//alias compress2   "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l"
+{
+    Aig_Man_t * pTemp;
+
+    Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr;
+    Dar_RefPar_t ParsRef, * pParsRef = &ParsRef;
+
+    Dar_ManDefaultRwrParams( pParsRwr );
+    Dar_ManDefaultRefParams( pParsRef );
+
+    pParsRwr->fUpdateLevel = fUpdateLevel;
+    pParsRef->fUpdateLevel = fUpdateLevel;
+    pParsRwr->fFanout = fFanout;
+    pParsRwr->fPower = fPower;
+
+    pParsRwr->fVerbose = 0;//fVerbose;
+    pParsRef->fVerbose = 0;//fVerbose;
+
+//    pAig = Aig_ManDupDfs( pAig ); 
+    if ( fVerbose ) printf( "Starting:  " ), Aig_ManPrintStats( pAig );
+
+    // skip if lighter synthesis is requested
+    if ( !fLightSynth )
+    {
+        // rewrite
+        //Dar_ManRewrite( pAig, pParsRwr );
+//        pParsRwr->fUpdateLevel = 0;  // disable level update  // this change was requested in July and later disabled
+        Dar_ManRewrite( pAig, pParsRwr );
+//        pParsRwr->fUpdateLevel = fUpdateLevel;  // reenable level update if needed
+
+        pAig = Aig_ManDupDfs( pTemp = pAig ); 
+        Aig_ManStop( pTemp );
+        if ( fVerbose ) printf( "Rewrite:   " ), Aig_ManPrintStats( pAig );
+    
+        // refactor
+        Dar_ManRefactor( pAig, pParsRef );
+        pAig = Aig_ManDupDfs( pTemp = pAig ); 
+        Aig_ManStop( pTemp );
+        if ( fVerbose ) printf( "Refactor:  " ), Aig_ManPrintStats( pAig );
+    }
+
+    // balance
+    pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Balance:   " ), Aig_ManPrintStats( pAig );
+    
+    // skip if lighter synthesis is requested
+    if ( !fLightSynth )
+    {
+        // rewrite
+        Dar_ManRewrite( pAig, pParsRwr );
+        pAig = Aig_ManDupDfs( pTemp = pAig ); 
+        Aig_ManStop( pTemp );
+        if ( fVerbose ) printf( "Rewrite:   " ), Aig_ManPrintStats( pAig );
+    }
+
+    pParsRwr->fUseZeros = 1;
+    pParsRef->fUseZeros = 1;
+    
+    // rewrite
+    Dar_ManRewrite( pAig, pParsRwr );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "RewriteZ:  " ), Aig_ManPrintStats( pAig );
+
+    // skip if lighter synthesis is requested
+    if ( !fLightSynth )
+    {
+        // balance
+        if ( fBalance )
+        {
+        pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
+        Aig_ManStop( pTemp );
+        if ( fVerbose ) printf( "Balance:   " ), Aig_ManPrintStats( pAig );
+        }
+    }
+    
+    // refactor
+    Dar_ManRefactor( pAig, pParsRef );
+    pAig = Aig_ManDupDfs( pTemp = pAig ); 
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "RefactorZ: " ), Aig_ManPrintStats( pAig );
+    
+    // skip if lighter synthesis is requested
+    if ( !fLightSynth )
+    {
+        // rewrite
+        Dar_ManRewrite( pAig, pParsRwr );
+        pAig = Aig_ManDupDfs( pTemp = pAig ); 
+        Aig_ManStop( pTemp );
+        if ( fVerbose ) printf( "RewriteZ:  " ), Aig_ManPrintStats( pAig );
+    }
+
+    // balance
+    if ( fBalance )
+    {
+    pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel );
+    Aig_ManStop( pTemp );
+    if ( fVerbose ) printf( "Balance:   " ), Aig_ManPrintStats( pAig );
+    }
+    return pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of nodes with very high fanout count.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dar_NewChoiceSynthesisGuard( Aig_Man_t * pAig )
+{
+    Aig_Obj_t * pObj;
+    int i, Count = 0;
+    Aig_ManForEachNode( pAig, pObj, i )
+        if ( Aig_ObjRefs(pObj) > 1000 )
+            Count += Aig_ObjRefs(pObj) / 1000;
+    return (int)(Count > 10);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reproduces script "compress2".]
+
+  Description [Takes AIG manager, consumes it, and produces GIA manager.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Dar_NewChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fLightSynth, int fVerbose )
+//alias resyn    "b; rw; rwz; b; rwz; b"
+//alias resyn2   "b; rw; rf; b; rw; rwz; b; rfz; rwz; b"
+{
+    Vec_Ptr_t * vGias;
+    Gia_Man_t * pGia, * pTemp;
+    int i;
+
+    if ( fUpdateLevel && Dar_NewChoiceSynthesisGuard(pAig) )
+    {
+        if ( fVerbose )
+            printf( "Warning: Due to high fanout count of some nodes, level updating is disabled.\n" );
+        fUpdateLevel = 0;
+    }
+
+    vGias = Vec_PtrAlloc( 3 );
+    pGia = Gia_ManFromAig(pAig);
+    Vec_PtrPush( vGias, pGia );
+
+    pAig = Dar_NewCompress( pAig, fBalance, fUpdateLevel, fPower, fVerbose );
+    pGia = Gia_ManFromAig(pAig);
+    Vec_PtrPush( vGias, pGia );
+//Aig_ManPrintStats( pAig );
+
+    pAig = Dar_NewCompress2( pAig, fBalance, fUpdateLevel, 1, fPower, fLightSynth, fVerbose );
+    pGia = Gia_ManFromAig(pAig);
+    Vec_PtrPush( vGias, pGia );
+//Aig_ManPrintStats( pAig );
+
+    Aig_ManStop( pAig );
+
+    // swap around the first and the last
+    pTemp = (Gia_Man_t *)Vec_PtrPop( vGias );
+    Vec_PtrPush( vGias, Vec_PtrEntry(vGias,0) );
+    Vec_PtrWriteEntry( vGias, 0, pTemp );
+
+//    Aig_Man_t * pAig;
+//    int i;
+//    printf( "Choicing will be performed with %d AIGs:\n", Vec_PtrSize(p->vAigs) );
+//    Vec_PtrForEachEntry( Aig_Man_t *, p->vAigs, pAig, i )
+//        Aig_ManPrintStats( pAig );
+
+    // derive the miter
+    pGia = Gia_ManChoiceMiter( vGias );
+
+    // cleanup
+    Vec_PtrForEachEntry( Gia_Man_t *, vGias, pTemp, i )
+        Gia_ManStop( pTemp );
+    Vec_PtrFree( vGias );
+    return pGia;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reproduces script "compress2".]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars )
+{
+    extern Aig_Man_t * Dch_ComputeChoices( Vec_Ptr_t * vAigs, Dch_Pars_t * pPars );
+    extern Aig_Man_t * Cec_ComputeChoices( Vec_Ptr_t * vAigs, Dch_Pars_t * pPars );
+
+    int fVerbose = pPars->fVerbose;
+    int fConstruct = 0;
+    Aig_Man_t * pMan, * pTemp;
+    Vec_Ptr_t * vAigs;
+    int i;
+    abctime clk;
+
+clk = Abc_Clock();
+//    vAigs = Dar_ManChoiceSynthesisExt();
+//    vAigs = Dar_ManChoiceSynthesis( pAig, 1, 1, pPars->fPower, fVerbose );
+    vAigs = Dar_ManChoiceSynthesis( pAig, 1, 1, pPars->fPower, 0 );
+
+    // swap the first and last network
+    // this should lead to the primary choice being "better" because of synthesis
+    // (it is also important when constructing choices)
+    if ( !fConstruct )
+    {
+        pMan = Vec_PtrPop( vAigs );
+        Vec_PtrPush( vAigs, Vec_PtrEntry(vAigs,0) );
+        Vec_PtrWriteEntry( vAigs, 0, pMan );
+    }
+
+if ( fVerbose )
+{
+//ABC_PRT( "Synthesis time", Abc_Clock() - clk );
+}
+    pPars->timeSynth = Abc_Clock() - clk;
+
+clk = Abc_Clock();
+    // perform choice computation
+    if ( pPars->fUseGia )
+        pMan = Cec_ComputeChoices( vAigs, pPars );
+    else
+        pMan = Dch_ComputeChoices( vAigs, pPars );
+
+    // reconstruct the network
+    pMan = Aig_ManDupDfsGuided( pTemp = pMan, Vec_PtrEntry(vAigs,0) );
+    Aig_ManStop( pTemp );
+    // duplicate the timing manager
+    pTemp = Vec_PtrEntry( vAigs, 0 );
+    if ( pTemp->pManTime )
+    {
+        extern void * Tim_ManDup( void * p, int fDiscrete );     
+        pMan->pManTime = Tim_ManDup( pTemp->pManTime, 0 );
+    }
+    // reset levels
+    Aig_ManChoiceLevel( pMan );
+    ABC_FREE( pMan->pName );
+    ABC_FREE( pMan->pSpec );
+    pMan->pName = Abc_UtilStrsav( pTemp->pName );
+    pMan->pSpec = Abc_UtilStrsav( pTemp->pSpec );
+
+    // cleanup
+    Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, i )
+        Aig_ManStop( pTemp );
+    Vec_PtrFree( vAigs );
+
+if ( fVerbose )
+{
+//ABC_PRT( "Choicing time ", Abc_Clock() - clk );
+}
+    return pMan;
+//    return NULL;
+}
+*/
+
+/**Function*************************************************************
+
+  Synopsis    [Reproduces script "compress2".]
+
+  Description [Consumes the input AIG to reduce memory usage.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Dar_ManChoiceNewAig( Aig_Man_t * pAig, Dch_Pars_t * pPars )
+{
+//    extern Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs );
+    extern Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars );
+    int fVerbose = pPars->fVerbose;
+    Aig_Man_t * pMan, * pTemp;
+    Vec_Ptr_t * vAigs;
+    Vec_Ptr_t * vPios;
+    void * pManTime;
+    char * pName, * pSpec;
+    int i;
+    abctime clk;
+
+clk = Abc_Clock();
+    vAigs = Dar_ManChoiceSynthesis( pAig, 1, 1, pPars->fPower, fVerbose );
+pPars->timeSynth = Abc_Clock() - clk;
+    // swap the first and last network
+    // this should lead to the primary choice being "better" because of synthesis
+    // (it is also important when constructing choices)
+    pMan = (Aig_Man_t *)Vec_PtrPop( vAigs );
+    Vec_PtrPush( vAigs, Vec_PtrEntry(vAigs,0) );
+    Vec_PtrWriteEntry( vAigs, 0, pMan );
+
+    // derive the total AIG
+    pMan = Dch_DeriveTotalAig( vAigs );
+    // cleanup
+    Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, i )
+        Aig_ManStop( pTemp );
+    Vec_PtrFree( vAigs );
+
+    // compute choices
+    pMan = Dch_ComputeChoices( pTemp = pMan, pPars );
+    Aig_ManStop( pTemp );
+
+    // save useful things
+    pManTime = pAig->pManTime; pAig->pManTime = NULL;
+    pName = Abc_UtilStrsav( pAig->pName );
+    pSpec = Abc_UtilStrsav( pAig->pSpec );
+
+    // create guidence
+    vPios = Aig_ManOrderPios( pMan, pAig ); 
+    Aig_ManStop( pAig );
+
+    // reconstruct the network
+    pMan = Aig_ManDupDfsGuided( pTemp = pMan, vPios );
+    Aig_ManStop( pTemp );
+    Vec_PtrFree( vPios );
+
+    // reset levels
+    pMan->pManTime = pManTime;
+    Aig_ManChoiceLevel( pMan );
+
+    // copy names
+    ABC_FREE( pMan->pName );
+    ABC_FREE( pMan->pSpec );
+    pMan->pName = pName;
+    pMan->pSpec = pSpec;
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reproduces script "compress2".]
+
+  Description [Consumes the input AIG to reduce memory usage.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars )
+{
+    extern Aig_Man_t * Cec_ComputeChoices( Gia_Man_t * pGia, Dch_Pars_t * pPars );
+//    extern Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs );
+    extern Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars );
+//    int fVerbose = pPars->fVerbose;
+    Aig_Man_t * pMan, * pTemp;
+    Gia_Man_t * pGia;
+    Vec_Ptr_t * vPios;
+    void * pManTime;
+    char * pName, * pSpec;
+    abctime clk;
+
+    // save useful things
+    pManTime = pAig->pManTime; pAig->pManTime = NULL;
+    pName = Abc_UtilStrsav( pAig->pName );
+    pSpec = Abc_UtilStrsav( pAig->pSpec );
+
+    // perform synthesis
+clk = Abc_Clock();
+    pGia = Dar_NewChoiceSynthesis( Aig_ManDupDfs(pAig), 1, 1, pPars->fPower, pPars->fLightSynth, pPars->fVerbose );
+pPars->timeSynth = Abc_Clock() - clk;
+
+    // perform choice computation
+    if ( pPars->fUseGia )
+        pMan = Cec_ComputeChoices( pGia, pPars );
+    else
+    {
+        pMan = Gia_ManToAigSkip( pGia, 3 );
+        Gia_ManStop( pGia );
+        pMan = Dch_ComputeChoices( pTemp = pMan, pPars );
+        Aig_ManStop( pTemp );
+    }
+
+    // create guidence
+    vPios = Aig_ManOrderPios( pMan, pAig ); 
+    Aig_ManStop( pAig );
+
+    // reconstruct the network
+    pMan = Aig_ManDupDfsGuided( pTemp = pMan, vPios );
+    Aig_ManStop( pTemp );
+    Vec_PtrFree( vPios );
+
+    // reset levels
+    pMan->pManTime = pManTime;
+    Aig_ManChoiceLevel( pMan );
+
+    // copy names
+    ABC_FREE( pMan->pName );
+    ABC_FREE( pMan->pSpec );
+    pMan->pName = pName;
+    pMan->pSpec = pSpec;
+    return pMan;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dar/dar_.c b/abc-build/src/opt/dar/dar_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dar/dar_.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+  FileName    [dar_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: dar_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "darInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dar/module.make b/abc-build/src/opt/dar/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dar/module.make
@@ -0,0 +1,9 @@
+SRC +=	src/opt/dar/darBalance.c \
+	src/opt/dar/darCore.c \
+	src/opt/dar/darCut.c \
+	src/opt/dar/darData.c \
+	src/opt/dar/darLib.c \
+	src/opt/dar/darMan.c \
+	src/opt/dar/darPrec.c \
+	src/opt/dar/darRefact.c \
+	src/opt/dar/darScript.c
diff --git a/abc-build/src/opt/dau/dau.c b/abc-build/src/opt/dau/dau.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dau/dau.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+  FileName    [dau.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware unmapping.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: dau.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dauInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dau/dau.h b/abc-build/src/opt/dau/dau.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dau/dau.h
@@ -0,0 +1,124 @@
+/**CFile****************************************************************
+
+  FileName    [dau.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware unmapping.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: dau.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__DAU___h
+#define ABC__DAU___h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+#include "misc/vec/vec.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+#define DAU_MAX_VAR    12 // should be 6 or more
+#define DAU_MAX_STR  2000
+#define DAU_MAX_WORD  (1<<(DAU_MAX_VAR-6))
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// network types
+typedef enum { 
+    DAU_DSD_NONE = 0,      // 0:  unknown
+    DAU_DSD_CONST0,        // 1:  constant
+    DAU_DSD_VAR,           // 2:  variable
+    DAU_DSD_AND,           // 3:  AND
+    DAU_DSD_XOR,           // 4:  XOR
+    DAU_DSD_MUX,           // 5:  MUX
+    DAU_DSD_PRIME          // 6:  PRIME
+} Dau_DsdType_t;
+
+typedef struct Dss_Man_t_ Dss_Man_t;
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Dau_DsdIsConst( char * p )  { return (p[0] == '0' || p[0] == '1') && p[1] == 0;    }
+static inline int Dau_DsdIsConst0( char * p ) { return  p[0] == '0' && p[1] == 0;                    }
+static inline int Dau_DsdIsConst1( char * p ) { return  p[0] == '1' && p[1] == 0;                    }
+static inline int Dau_DsdIsVar( char * p )    { if ( *p == '!' ) p++; return *p >= 'a' && *p <= 'z'; }
+static inline int Dau_DsdReadVar( char * p )  { if ( *p == '!' ) p++; return *p - 'a';               }
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== dauCanon.c ==========================================================*/
+extern unsigned      Abc_TtCanonicize( word * pTruth, int nVars, char * pCanonPerm );
+extern unsigned      Abc_TtCanonicizePhase( word * pTruth, int nVars );
+/*=== dauDsd.c  ==========================================================*/
+extern int *         Dau_DsdComputeMatches( char * p );
+extern int           Dau_DsdDecompose( word * pTruth, int nVarsInit, int fSplitPrime, int fWriteTruth, char * pRes );
+extern int           Dau_DsdDecomposeLevel( word * pTruth, int nVarsInit, int fSplitPrime, int fWriteTruth, char * pRes, int * pVarLevels );
+extern void          Dau_DsdPrintFromTruthFile( FILE * pFile, word * pTruth, int nVarsInit );
+extern void          Dau_DsdPrintFromTruth( word * pTruth, int nVarsInit );
+extern word *        Dau_DsdToTruth( char * p, int nVars );
+extern word          Dau_Dsd6ToTruth( char * p );
+extern void          Dau_DsdNormalize( char * p );
+extern int           Dau_DsdCountAnds( char * pDsd );
+extern void          Dau_DsdTruthCompose_rec( word * pFunc, word pFanins[DAU_MAX_VAR][DAU_MAX_WORD], word * pRes, int nVars, int nWordsR );
+extern int           Dau_DsdCheck1Step( void * p, word * pTruth, int nVarsInit, int * pVarLevels );
+
+/*=== dauGia.c  ==========================================================*/
+extern int           Dsm_ManTruthToGia( void * p, word * pTruth, Vec_Int_t * vLeaves, Vec_Int_t * vCover );
+extern void *        Dsm_ManDeriveGia( void * p, int fUseMuxes );
+
+/*=== dauMerge.c  ==========================================================*/
+extern void          Dau_DsdRemoveBraces( char * pDsd, int * pMatches );
+extern char *        Dau_DsdMerge( char * pDsd0i, int * pPerm0, char * pDsd1i, int * pPerm1, int fCompl0, int fCompl1, int nVars );
+
+/*=== dauNonDsd.c  ==========================================================*/
+extern Vec_Int_t *   Dau_DecFindSets_int( word * pInit, int nVars, int * pSched[16] );
+extern Vec_Int_t *   Dau_DecFindSets( word * pInit, int nVars );
+extern void          Dau_DecSortSet( unsigned set, int nVars, int * pnUnique, int * pnShared, int * pnFree );
+extern void          Dau_DecPrintSets( Vec_Int_t * vSets, int nVars );
+extern void          Dau_DecPrintSet( unsigned set, int nVars, int fNewLine );
+
+/*=== dauTree.c  ==========================================================*/
+extern Dss_Man_t *   Dss_ManAlloc( int nVars, int nNonDecLimit );
+extern void          Dss_ManFree( Dss_Man_t * p );
+extern int           Dss_ManMerge( Dss_Man_t * p, int * iDsd, int * nFans, int ** pFans, unsigned uSharedMask, int nKLutSize, unsigned char * pPerm, word * pTruth );
+extern void          Dss_ManPrint( char * pFileName, Dss_Man_t * p );
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/dau/dauArray.c b/abc-build/src/opt/dau/dauArray.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dau/dauArray.c
@@ -0,0 +1,257 @@
+/**CFile****************************************************************
+
+  FileName    [dauArray.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware unmapping.]
+
+  Synopsis    [Array representation of DSD.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: dauArray.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dauInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Dau_Dsd_t_ Dau_Dsd_t;
+struct Dau_Dsd_t_
+{
+    unsigned       iVar    :   5;  // variable
+    unsigned       nFans   :   5;  // fanin count
+    unsigned       Depth   :   5;  // tree depth
+    unsigned       Offset  :   5;  // the diff between this and other node
+    unsigned       Data    :   5;  // user data
+    unsigned       Type    :   3;  // node type
+    unsigned       fCompl  :   1;  // the complemented attribute
+    unsigned       fUnused :   1;  // this vertice is unused
+};
+
+static inline void Dau_DsdClean( Dau_Dsd_t * p ) { *((int *)p) = 0; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+int Dau_DsdCountAnd( Dau_Dsd_t * p )
+{
+    int Count, Costs[7] = {0, 0, 0, 1, 3, 3, 3};
+    for ( Count = 0; p->Type; p++ )
+        Count += Costs[p->Type];
+    return Count;
+}
+
+/*
+void Dau_DsdMark( Dau_Dsd_t * p, int nSize, int * pMarks )
+{
+    int pStore[DAU_MAX_VAR] = {0};
+    Dau_Dsd_t * q;
+    if ( p->Type == DAU_DSD_CONST || p->Type == DAU_DSD_VAR )
+        return;
+    for ( q = p + nSize - 1; q >= p; q-- )
+    {
+        if ( q->Type == DAU_DSD_VAR )
+            pStore[q->Depth] += pMarks[q->iVar];
+        else 
+        {
+            q->Data = pStore[q->Depth+1]; pStore[q->Depth+1] = 0;
+            pStore[q->Depth] += (q->Data == q->nFans);            
+        }
+    }
+}
+*/
+
+int Dau_DsdConstruct( char * pDsd, Dau_Dsd_t * pStore )
+{
+    Dau_Dsd_t * pLevel[DAU_MAX_VAR];
+    Dau_Dsd_t * q = pStore;
+    int d = -1, fCompl = 0;
+    if ( Dau_DsdIsConst(pDsd) )
+    {
+        Dau_DsdClean( q );
+        q->Type   = DAU_DSD_CONST0;
+        q->fCompl = Dau_DsdIsConst1(pDsd);
+        return 1;
+    }
+    for ( --q; *pDsd; pDsd++ )
+    {
+        if ( *pDsd == '!' )
+        {
+            fCompl ^= 1;
+            continue;
+        }
+        if ( *pDsd == ')' || *pDsd == ']' || *pDsd == '>' || *pDsd == '}' )
+        {
+            assert( fCompl == 0 );
+            if ( --d >= 0 )
+            {
+                pLevel[d]->nFans++;
+                if ( pLevel[d]->Data > pLevel[d+1]->Data )
+                    pLevel[d]->Data = pLevel[d+1]->Data;
+            }
+            continue;
+        }
+        Dau_DsdClean( ++q );
+        q->Data = 31;
+        q->fCompl = fCompl;
+        fCompl = 0;
+        if ( *pDsd >= 'a' && *pDsd <= 'z' )
+        {
+            q->Type   = DAU_DSD_VAR;
+            q->iVar   = *pDsd - 'a';
+            q->Depth  = d + 1;
+            if ( d >= 0 )
+            {
+                pLevel[d]->nFans++;
+                if ( pLevel[d]->Data > q->iVar )
+                    pLevel[d]->Data = q->iVar;
+            }
+            continue;
+        }
+        if ( *pDsd == '(' )
+            q->Type = DAU_DSD_AND;
+        else if ( *pDsd == '[' )
+            q->Type = DAU_DSD_XOR;
+        else if ( *pDsd == '<' )
+            q->Type = DAU_DSD_MUX;
+        else if ( *pDsd == '{' )
+            q->Type = DAU_DSD_PRIME;
+        else assert( 0 );
+        pLevel[++d] = q;
+        q->Depth = d;
+    }
+    assert( d == -1 );
+    Dau_DsdClean( ++q );
+    return q - pStore;
+}
+
+void Dau_DsdPrint( Dau_Dsd_t * p )
+{
+    char OpenType[7]  = {0, 0, 0, '(', '[', '<', '{'};
+    char CloseType[7] = {0, 0, 0, ')', ']', '>', '}'};
+    char pTypes[DAU_MAX_VAR];
+    int d, pVisits[DAU_MAX_VAR];
+    if ( p->Type == DAU_DSD_CONST0 )
+    {
+        printf( "%d\n", p->fCompl );
+        return;
+    }
+    pVisits[0] = 1;
+    for ( d = 0; p->Type; p++ )
+    {
+        if ( p->fCompl )
+            printf( "!" );
+        if ( p->Type == DAU_DSD_VAR )
+        {
+            printf( "%c", 'a' + p->iVar );
+            while ( d > 0 && --pVisits[d] == 0 )
+                printf( "%c", pTypes[d--] );
+        }
+        else
+        {
+            pVisits[++d] = p->nFans;
+            printf( "%c", OpenType[p->Type] );
+            printf( "%c", 'a' + p->Data );
+            printf( "%d", p->Depth );
+            pTypes[d]  = CloseType[p->Type];
+        }
+    }
+    assert( d == 0 );
+    printf( "\n" );
+}
+
+void Dau_DsdDepth( Dau_Dsd_t * p )
+{
+    int d, pVisits[DAU_MAX_VAR];
+    if ( p->Type == DAU_DSD_CONST0 )
+        return;
+    pVisits[0] = 1;
+    for ( d = 0; p->Type; p++ )
+    {
+        p->Depth = d;
+        if ( p->Type == DAU_DSD_VAR )
+            while ( d > 0 && --pVisits[d] == 0 )
+                d--;
+        else
+            pVisits[++d] = p->nFans;
+    }
+    assert( d == 0 );
+}
+
+void Dau_DsdRemoveUseless( Dau_Dsd_t * p )
+{
+    Dau_Dsd_t * q = p, * pLevel[DAU_MAX_VAR];
+    int d, fChange = 0, pVisits[DAU_MAX_VAR];
+    if ( p->Type == DAU_DSD_CONST0 )
+        return;
+    pVisits[0] = 1;
+    for ( d = 0; p->Type; p++ )
+    {
+        p->Depth = d;
+        if ( p->Type == DAU_DSD_VAR )
+            while ( d > 0 && --pVisits[d] == 0 )
+                d--;
+        else
+        {
+            if ( d > 0 && (pLevel[d-1]->Type == DAU_DSD_XOR && p->Type == DAU_DSD_XOR ||
+                           pLevel[d-1]->Type == DAU_DSD_AND && p->Type == DAU_DSD_AND && !p->fCompl) )
+            {
+                pLevel[d-1]->nFans += p->nFans - 1;
+                pVisits[d] += p->nFans - 1;
+                p->fUnused = 1;
+                fChange = 1;
+            }
+            else
+            {
+                pLevel[d++] = p;
+                pVisits[d] = p->nFans;
+            }
+        }
+    }
+    assert( d == 0 );
+    // compact
+    if ( fChange )
+    {
+        for ( p = q; p->Type; p++ )
+            if ( !p->fUnused )
+                *q++ = *p;
+        Dau_DsdClean( q );
+    }
+}
+
+void Dau_DsdTest22()
+{
+    Dau_Dsd_t pStore[2 * DAU_MAX_VAR];
+//    char * pDsd = "[(ab)c(f!(he))]";
+//    char * pDsd = "[(abd)cf(f!{she})]";
+    char * pDsd = "[(abd)[cf](f(sg(he)))]";
+//    char * pDsd = "[(ab)[cf]]";
+    int i, nSize = Dau_DsdConstruct( pDsd, pStore );
+//    Dau_DsdDepth( pStore );
+    Dau_DsdPrint( pStore );
+
+    Dau_DsdRemoveUseless( pStore );
+
+    Dau_DsdPrint( pStore );
+    i = 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dau/dauCanon.c b/abc-build/src/opt/dau/dauCanon.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dau/dauCanon.c
@@ -0,0 +1,1050 @@
+/**CFile****************************************************************
+
+  FileName    [dauCanon.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware unmapping.]
+
+  Synopsis    [Canonical form computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: dauCanon.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dauInt.h"
+#include "misc/util/utilTruth.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static word s_CMasks6[5] = {
+    ABC_CONST(0x1111111111111111),
+    ABC_CONST(0x0303030303030303),
+    ABC_CONST(0x000F000F000F000F),
+    ABC_CONST(0x000000FF000000FF),
+    ABC_CONST(0x000000000000FFFF)
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    [Compares Cof0 and Cof1.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_TtCompare1VarCofs( word * pTruth, int nWords, int iVar )
+{
+    if ( nWords == 1 )
+    {
+        word Cof0 = pTruth[0] & s_Truths6Neg[iVar];
+        word Cof1 = (pTruth[0] >> (1 << iVar)) & s_Truths6Neg[iVar];
+        if ( Cof0 != Cof1 )
+            return Cof0 < Cof1 ? -1 : 1;
+        return 0;
+    }
+	if ( iVar <= 5 )
+	{
+        word Cof0, Cof1;
+		int w, shift = (1 << iVar);
+		for ( w = 0; w < nWords; w++ )
+        {
+            Cof0 = pTruth[w] & s_Truths6Neg[iVar];
+            Cof1 = (pTruth[w] >> shift) & s_Truths6Neg[iVar];
+            if ( Cof0 != Cof1 )
+                return Cof0 < Cof1 ? -1 : 1;
+        }
+        return 0;
+	}
+	// if ( iVar > 5 )
+	{
+        word * pLimit = pTruth + nWords;
+		int i, iStep = Abc_TtWordNum(iVar);
+        assert( nWords >= 2 );
+		for ( ; pTruth < pLimit; pTruth += 2*iStep )
+			for ( i = 0; i < iStep; i++ )
+                if ( pTruth[i] != pTruth[i + iStep] )
+                    return pTruth[i] < pTruth[i + iStep] ? -1 : 1;
+        return 0;
+	}	
+}
+static inline int Abc_TtCompare1VarCofsRev( word * pTruth, int nWords, int iVar )
+{
+    if ( nWords == 1 )
+    {
+        word Cof0 = pTruth[0] & s_Truths6Neg[iVar];
+        word Cof1 = (pTruth[0] >> (1 << iVar)) & s_Truths6Neg[iVar];
+        if ( Cof0 != Cof1 )
+            return Cof0 < Cof1 ? -1 : 1;
+        return 0;
+    }
+	if ( iVar <= 5 )
+	{
+        word Cof0, Cof1;
+		int w, shift = (1 << iVar);
+		for ( w = nWords - 1; w >= 0; w-- )
+        {
+            Cof0 = pTruth[w] & s_Truths6Neg[iVar];
+            Cof1 = (pTruth[w] >> shift) & s_Truths6Neg[iVar];
+            if ( Cof0 != Cof1 )
+                return Cof0 < Cof1 ? -1 : 1;
+        }
+        return 0;
+	}
+	// if ( iVar > 5 )
+	{
+        word * pLimit = pTruth + nWords;
+		int i, iStep = Abc_TtWordNum(iVar);
+        assert( nWords >= 2 );
+		for ( pLimit -= 2*iStep; pLimit >= pTruth; pLimit -= 2*iStep )
+			for ( i = iStep - 1; i >= 0; i-- )
+                if ( pLimit[i] != pLimit[i + iStep] )
+                    return pLimit[i] < pLimit[i + iStep] ? -1 : 1;
+        return 0;
+	}	
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks equality of pairs of cofactors w.r.t. adjacent variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_TtCheckEqual2VarCofs( word * pTruth, int nWords, int iVar, int Num1, int Num2 )
+{
+    assert( Num1 < Num2 && Num2 < 4 );
+    if ( nWords == 1 )
+        return ((pTruth[0] >> (Num2 * (1 << iVar))) & s_CMasks6[iVar]) == ((pTruth[0] >> (Num1 * (1 << iVar))) & s_CMasks6[iVar]);
+	if ( iVar <= 4 )
+	{
+		int w, shift = (1 << iVar);
+		for ( w = 0; w < nWords; w++ )
+            if ( ((pTruth[w] >> Num2 * shift) & s_CMasks6[iVar]) != ((pTruth[w] >> Num1 * shift) & s_CMasks6[iVar]) )
+                return 0;
+        return 1;
+	}
+	if ( iVar == 5 )
+	{
+        unsigned * pTruthU = (unsigned *)pTruth;
+        unsigned * pLimitU = (unsigned *)(pTruth + nWords);
+        assert( nWords >= 2 );
+		for ( ; pTruthU < pLimitU; pTruthU += 4 )
+            if ( pTruthU[Num2] != pTruthU[Num1] )
+                return 0;
+        return 1;
+	}
+	// if ( iVar > 5 )
+	{
+        word * pLimit = pTruth + nWords;
+		int i, iStep = Abc_TtWordNum(iVar);
+        assert( nWords >= 4 );
+		for ( ; pTruth < pLimit; pTruth += 4*iStep )
+			for ( i = 0; i < iStep; i++ )
+                if ( pTruth[i+Num2*iStep] != pTruth[i+Num1*iStep] )
+                    return 0;
+        return 1;
+	}	
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares pairs of cofactors w.r.t. adjacent variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_TtCompare2VarCofs( word * pTruth, int nWords, int iVar, int Num1, int Num2 )
+{
+    assert( Num1 < Num2 && Num2 < 4 );
+    if ( nWords == 1 )
+    {
+        word Cof1 = (pTruth[0] >> (Num1 * (1 << iVar))) & s_CMasks6[iVar];
+        word Cof2 = (pTruth[0] >> (Num2 * (1 << iVar))) & s_CMasks6[iVar];
+        if ( Cof1 != Cof2 )
+            return Cof1 < Cof2 ? -1 : 1;
+        return 0;
+    }
+	if ( iVar <= 4 )
+	{
+        word Cof1, Cof2;
+		int w, shift = (1 << iVar);
+		for ( w = 0; w < nWords; w++ )
+        {
+            Cof1 = (pTruth[w] >> Num1 * shift) & s_CMasks6[iVar];
+            Cof2 = (pTruth[w] >> Num2 * shift) & s_CMasks6[iVar];
+            if ( Cof1 != Cof2 )
+                return Cof1 < Cof2 ? -1 : 1;
+        }
+        return 0;
+	}
+	if ( iVar == 5 )
+	{
+        unsigned * pTruthU = (unsigned *)pTruth;
+        unsigned * pLimitU = (unsigned *)(pTruth + nWords);
+        assert( nWords >= 2 );
+		for ( ; pTruthU < pLimitU; pTruthU += 4 )
+            if ( pTruthU[Num1] != pTruthU[Num2] )
+                return pTruthU[Num1] < pTruthU[Num2] ? -1 : 1;
+        return 0;
+	}
+	// if ( iVar > 5 )
+	{
+        word * pLimit = pTruth + nWords;
+		int i, iStep = Abc_TtWordNum(iVar);
+        int Offset1 = Num1*iStep;
+        int Offset2 = Num2*iStep;
+        assert( nWords >= 4 );
+		for ( ; pTruth < pLimit; pTruth += 4*iStep )
+			for ( i = 0; i < iStep; i++ )
+                if ( pTruth[i + Offset1] != pTruth[i + Offset2] )
+                    return pTruth[i + Offset1] < pTruth[i + Offset2] ? -1 : 1;
+        return 0;
+	}	
+}
+static inline int Abc_TtCompare2VarCofsRev( word * pTruth, int nWords, int iVar, int Num1, int Num2 )
+{
+    assert( Num1 < Num2 && Num2 < 4 );
+    if ( nWords == 1 )
+    {
+        word Cof1 = (pTruth[0] >> (Num1 * (1 << iVar))) & s_CMasks6[iVar];
+        word Cof2 = (pTruth[0] >> (Num2 * (1 << iVar))) & s_CMasks6[iVar];
+        if ( Cof1 != Cof2 )
+            return Cof1 < Cof2 ? -1 : 1;
+        return 0;
+    }
+	if ( iVar <= 4 )
+	{
+        word Cof1, Cof2;
+		int w, shift = (1 << iVar);
+		for ( w = nWords - 1; w >= 0; w-- )
+        {
+            Cof1 = (pTruth[w] >> Num1 * shift) & s_CMasks6[iVar];
+            Cof2 = (pTruth[w] >> Num2 * shift) & s_CMasks6[iVar];
+            if ( Cof1 != Cof2 )
+                return Cof1 < Cof2 ? -1 : 1;
+        }
+        return 0;
+	}
+	if ( iVar == 5 )
+	{
+        unsigned * pTruthU = (unsigned *)pTruth;
+        unsigned * pLimitU = (unsigned *)(pTruth + nWords);
+        assert( nWords >= 2 );
+		for ( pLimitU -= 4; pLimitU >= pTruthU; pLimitU -= 4 )
+            if ( pLimitU[Num1] != pLimitU[Num2] )
+                return pLimitU[Num1] < pLimitU[Num2] ? -1 : 1;
+        return 0;
+	}
+	// if ( iVar > 5 )
+	{
+        word * pLimit = pTruth + nWords;
+		int i, iStep = Abc_TtWordNum(iVar);
+        int Offset1 = Num1*iStep;
+        int Offset2 = Num2*iStep;
+        assert( nWords >= 4 );
+		for ( pLimit -= 4*iStep; pLimit >= pTruth; pLimit -= 4*iStep )
+			for ( i = iStep - 1; i >= 0; i-- )
+                if ( pLimit[i + Offset1] != pLimit[i + Offset2] )
+                    return pLimit[i + Offset1] < pLimit[i + Offset2] ? -1 : 1;
+        return 0;
+	}	
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Minterm counting in all cofactors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_TtCountOnesInTruth( word * pTruth, int nVars )
+{   
+    int nWords = Abc_TtWordNum( nVars );
+    int k, Counter = 0;
+    for ( k = 0; k < nWords; k++ )
+        if ( pTruth[k] )
+            Counter += Abc_TtCountOnes( pTruth[k] );
+    return Counter;
+}
+static inline void Abc_TtCountOnesInCofs( word * pTruth, int nVars, int * pStore )
+{
+    word Temp;
+    int i, k, Counter, nWords;
+    if ( nVars <= 6 )
+    {
+        for ( i = 0; i < nVars; i++ )
+            pStore[i] = Abc_TtCountOnes( pTruth[0] & s_Truths6Neg[i] );
+        return;
+    }
+    assert( nVars > 6 );
+    nWords = Abc_TtWordNum( nVars );
+    memset( pStore, 0, sizeof(int) * nVars );
+    for ( k = 0; k < nWords; k++ )
+    {
+        // count 1's for the first six variables
+        for ( i = 0; i < 6; i++ )
+            if ( (Temp = (pTruth[k] & s_Truths6Neg[i]) | ((pTruth[k+1] & s_Truths6Neg[i]) << (1 << i))) )
+                pStore[i] += Abc_TtCountOnes( Temp );
+        // count 1's for all other variables
+        if ( pTruth[k] )
+        {
+            Counter = Abc_TtCountOnes( pTruth[k] );
+            for ( i = 6; i < nVars; i++ )
+                if ( (k & (1 << (i-6))) == 0 )
+                    pStore[i] += Counter;
+        }
+        k++;
+        // count 1's for all other variables
+        if ( pTruth[k] )
+        {
+            Counter = Abc_TtCountOnes( pTruth[k] );
+            for ( i = 6; i < nVars; i++ )
+                if ( (k & (1 << (i-6))) == 0 )
+                    pStore[i] += Counter;
+        }
+    } 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Minterm counting in all cofactors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_TtCountOnesInCofsSlow( word * pTruth, int nVars, int * pStore )
+{
+    static int bit_count[256] = {
+      0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+      3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+    };
+    int i, k, nBytes;
+    unsigned char * pTruthC = (unsigned char *)pTruth;
+    nBytes = 8 * Abc_TtWordNum( nVars );
+    memset( pStore, 0, sizeof(int) * nVars );
+    for ( k = 0; k < nBytes; k++ )
+    {
+        pStore[0] += bit_count[ pTruthC[k] & 0x55 ];
+        pStore[1] += bit_count[ pTruthC[k] & 0x33 ];
+        pStore[2] += bit_count[ pTruthC[k] & 0x0F ];
+        for ( i = 3; i < nVars; i++ )
+            if ( (k & (1 << (i-3))) == 0 )
+                pStore[i] += bit_count[pTruthC[k]];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Minterm counting in all cofactors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_TtCountOnesInCofsFast6_rec( word Truth, int iVar, int nBytes, int * pStore )
+{
+    static int bit_count[256] = {
+      0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+      1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+      2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+      3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+    };
+    int nMints0, nMints1;
+    if ( Truth == 0 )
+        return 0;
+    if ( ~Truth == 0 )
+    {
+        int i;
+        for ( i = 0; i <= iVar; i++ )
+            pStore[i] += nBytes * 4;
+        return nBytes * 8;
+    }
+    if ( nBytes == 1 )
+    {
+        assert( iVar == 2 );
+        pStore[0] += bit_count[ Truth & 0x55 ];
+        pStore[1] += bit_count[ Truth & 0x33 ];
+        pStore[2] += bit_count[ Truth & 0x0F ];
+        return bit_count[ Truth & 0xFF ];
+    }
+    nMints0 = Abc_TtCountOnesInCofsFast6_rec( Abc_Tt6Cofactor0(Truth, iVar), iVar - 1, nBytes/2, pStore );
+    nMints1 = Abc_TtCountOnesInCofsFast6_rec( Abc_Tt6Cofactor1(Truth, iVar), iVar - 1, nBytes/2, pStore );
+    pStore[iVar] += nMints0;
+    return nMints0 + nMints1;
+}
+
+int Abc_TtCountOnesInCofsFast_rec( word * pTruth, int iVar, int nWords, int * pStore )
+{
+    int nMints0, nMints1;
+    if ( nWords == 1 )
+    {
+        assert( iVar == 5 );
+        return Abc_TtCountOnesInCofsFast6_rec( pTruth[0], iVar, 8, pStore );
+    }
+    assert( nWords > 1 );
+    assert( iVar > 5 );
+    if ( pTruth[0] & 1 )
+    {
+        if ( Abc_TtIsConst1( pTruth, nWords ) )
+        {
+            int i;
+            for ( i = 0; i <= iVar; i++ )
+                pStore[i] += nWords * 32;
+            return nWords * 64;
+        }
+    }
+    else 
+    {
+        if ( Abc_TtIsConst0( pTruth, nWords ) )
+            return 0;
+    }
+    nMints0 = Abc_TtCountOnesInCofsFast_rec( pTruth,            iVar - 1, nWords/2, pStore );
+    nMints1 = Abc_TtCountOnesInCofsFast_rec( pTruth + nWords/2, iVar - 1, nWords/2, pStore );
+    pStore[iVar] += nMints0;
+    return nMints0 + nMints1;
+}
+int Abc_TtCountOnesInCofsFast( word * pTruth, int nVars, int * pStore )
+{
+    memset( pStore, 0, sizeof(int) * nVars );
+    assert( nVars >= 3 );
+    if ( nVars <= 6 )
+        return Abc_TtCountOnesInCofsFast6_rec( pTruth[0], nVars - 1, Abc_TtByteNum( nVars ), pStore );
+    else
+        return Abc_TtCountOnesInCofsFast_rec( pTruth, nVars - 1, Abc_TtWordNum( nVars ), pStore );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Abc_TtSemiCanonicize( word * pTruth, int nVars, char * pCanonPerm, int * pStoreOut )
+{
+    int fOldSwap = 0;
+    int pStoreIn[17];
+    int * pStore = pStoreOut ? pStoreOut : pStoreIn;
+    int i, nOnes, nWords = Abc_TtWordNum( nVars );
+    unsigned uCanonPhase = 0;
+    assert( nVars <= 16 );
+    for ( i = 0; i < nVars; i++ )
+        pCanonPerm[i] = i;
+    // normalize polarity    
+    nOnes = Abc_TtCountOnesInTruth( pTruth, nVars );
+    if ( nOnes > nWords * 32 )
+    {
+        Abc_TtNot( pTruth, nWords );
+        nOnes = nWords*64 - nOnes;
+        uCanonPhase |= (1 << nVars);
+    }
+    // normalize phase
+    Abc_TtCountOnesInCofs( pTruth, nVars, pStore );
+    pStore[nVars] = nOnes;
+    for ( i = 0; i < nVars; i++ )
+    {
+        if ( pStore[i] >= nOnes - pStore[i] )
+            continue;
+        Abc_TtFlip( pTruth, nWords, i );
+        uCanonPhase |= (1 << i);
+        pStore[i] = nOnes - pStore[i]; 
+    }
+    // normalize permutation
+    if ( fOldSwap )
+    {
+        int fChange;
+        do {
+            fChange = 0;
+            for ( i = 0; i < nVars-1; i++ )
+            {
+                if ( pStore[i] <= pStore[i+1] )
+    //            if ( pStore[i] >= pStore[i+1] )
+                    continue;
+                ABC_SWAP( int, pCanonPerm[i], pCanonPerm[i+1] );
+                ABC_SWAP( int, pStore[i], pStore[i+1] );
+                if ( ((uCanonPhase >> i) & 1) != ((uCanonPhase >> (i+1)) & 1) )
+                {
+                    uCanonPhase ^= (1 << i);
+                    uCanonPhase ^= (1 << (i+1));
+                }
+                Abc_TtSwapAdjacent( pTruth, nWords, i );            
+                fChange = 1;
+    //            nSwaps++;
+            }
+        } 
+        while ( fChange );
+    }
+    else
+    {
+        int k, BestK;
+        for ( i = 0; i < nVars - 1; i++ )
+        {
+            BestK = i + 1;
+            for ( k = i + 2; k < nVars; k++ )
+                if ( pStore[BestK] > pStore[k] )
+    //            if ( pStore[BestK] < pStore[k] )
+                    BestK = k;
+            if ( pStore[i] <= pStore[BestK] )
+    //        if ( pStore[i] >= pStore[BestK] )
+                continue;
+            ABC_SWAP( int, pCanonPerm[i], pCanonPerm[BestK] );
+            ABC_SWAP( int, pStore[i], pStore[BestK] );
+            if ( ((uCanonPhase >> i) & 1) != ((uCanonPhase >> BestK) & 1) )
+            {
+                uCanonPhase ^= (1 << i);
+                uCanonPhase ^= (1 << BestK);
+            }
+            Abc_TtSwapVars( pTruth, nVars, i, BestK );
+    //        nSwaps++;
+        }
+    }
+    return uCanonPhase;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_TtCofactorTest10( word * pTruth, int nVars, int N )
+{
+    static word pCopy1[1024];
+    static word pCopy2[1024];
+    int nWords = Abc_TtWordNum( nVars );
+    int i;
+    for ( i = 0; i < nVars - 1; i++ )
+    {
+//        Kit_DsdPrintFromTruth( pTruth, nVars ); printf( "\n" );
+        Abc_TtCopy( pCopy1, pTruth, nWords, 0 );
+        Abc_TtSwapAdjacent( pCopy1, nWords, i );
+//        Kit_DsdPrintFromTruth( pCopy1, nVars ); printf( "\n" );
+        Abc_TtCopy( pCopy2, pTruth, nWords, 0 );
+        Abc_TtSwapVars( pCopy2, nVars, i, i+1 );
+//        Kit_DsdPrintFromTruth( pCopy2, nVars ); printf( "\n" );
+        assert( Abc_TtEqual( pCopy1, pCopy2, nWords ) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Naive evaluation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_Tt6CofactorPermNaive( word * pTruth, int i, int fSwapOnly )
+{
+    if ( fSwapOnly )
+    {
+        word Copy = Abc_Tt6SwapAdjacent( pTruth[0], i );
+        if ( pTruth[0] > Copy )
+        {
+            pTruth[0] = Copy;
+            return 4;
+        }
+        return 0;
+    }
+    {
+        word Copy = pTruth[0];
+        word Best = pTruth[0];
+        int Config = 0;
+        // PXY
+        // 001
+        Copy = Abc_Tt6Flip( Copy, i );
+        if ( Best > Copy )
+            Best = Copy, Config = 1;
+        // PXY
+        // 011
+        Copy = Abc_Tt6Flip( Copy, i+1 );
+        if ( Best > Copy )
+            Best = Copy, Config = 3;
+        // PXY
+        // 010
+        Copy = Abc_Tt6Flip( Copy, i );
+        if ( Best > Copy )
+            Best = Copy, Config = 2;
+        // PXY
+        // 110
+        Copy = Abc_Tt6SwapAdjacent( Copy, i );
+        if ( Best > Copy )
+            Best = Copy, Config = 6;
+        // PXY
+        // 111
+        Copy = Abc_Tt6Flip( Copy, i+1 );
+        if ( Best > Copy )
+            Best = Copy, Config = 7;
+        // PXY
+        // 101
+        Copy = Abc_Tt6Flip( Copy, i );
+        if ( Best > Copy )
+            Best = Copy, Config = 5;
+        // PXY
+        // 100
+        Copy = Abc_Tt6Flip( Copy, i+1 );
+        if ( Best > Copy )
+            Best = Copy, Config = 4;
+        // PXY
+        // 000
+        Copy = Abc_Tt6SwapAdjacent( Copy, i );
+        assert( Copy == pTruth[0] );
+        assert( Best <= pTruth[0] );
+        pTruth[0] = Best;
+        return Config;
+    }
+}
+int Abc_TtCofactorPermNaive( word * pTruth, int i, int nWords, int fSwapOnly )
+{
+    if ( fSwapOnly )
+    {
+        static word pCopy[1024];
+        Abc_TtCopy( pCopy, pTruth, nWords, 0 );
+        Abc_TtSwapAdjacent( pCopy, nWords, i );
+        if ( Abc_TtCompareRev(pTruth, pCopy, nWords) == 1 )
+        {
+            Abc_TtCopy( pTruth, pCopy, nWords, 0 );
+            return 4;
+        }
+        return 0;
+    }
+    {
+        static word pCopy[1024];
+        static word pBest[1024];
+        int Config = 0;
+        // save two copies
+        Abc_TtCopy( pCopy, pTruth, nWords, 0 );
+        Abc_TtCopy( pBest, pTruth, nWords, 0 );
+        // PXY
+        // 001
+        Abc_TtFlip( pCopy, nWords, i );
+        if ( Abc_TtCompareRev(pBest, pCopy, nWords) == 1 )
+            Abc_TtCopy( pBest, pCopy, nWords, 0 ), Config = 1;
+        // PXY
+        // 011
+        Abc_TtFlip( pCopy, nWords, i+1 );
+        if ( Abc_TtCompareRev(pBest, pCopy, nWords) == 1 )
+            Abc_TtCopy( pBest, pCopy, nWords, 0 ), Config = 3;
+        // PXY
+        // 010
+        Abc_TtFlip( pCopy, nWords, i );
+        if ( Abc_TtCompareRev(pBest, pCopy, nWords) == 1 )
+            Abc_TtCopy( pBest, pCopy, nWords, 0 ), Config = 2;
+        // PXY
+        // 110
+        Abc_TtSwapAdjacent( pCopy, nWords, i );
+        if ( Abc_TtCompareRev(pBest, pCopy, nWords) == 1 )
+            Abc_TtCopy( pBest, pCopy, nWords, 0 ), Config = 6;
+        // PXY
+        // 111
+        Abc_TtFlip( pCopy, nWords, i+1 );
+        if ( Abc_TtCompareRev(pBest, pCopy, nWords) == 1 )
+            Abc_TtCopy( pBest, pCopy, nWords, 0 ), Config = 7;
+        // PXY
+        // 101
+        Abc_TtFlip( pCopy, nWords, i );
+        if ( Abc_TtCompareRev(pBest, pCopy, nWords) == 1 )
+            Abc_TtCopy( pBest, pCopy, nWords, 0 ), Config = 5;
+        // PXY
+        // 100
+        Abc_TtFlip( pCopy, nWords, i+1 );
+        if ( Abc_TtCompareRev(pBest, pCopy, nWords) == 1 )
+            Abc_TtCopy( pBest, pCopy, nWords, 0 ), Config = 4;
+        // PXY
+        // 000
+        Abc_TtSwapAdjacent( pCopy, nWords, i );
+        assert( Abc_TtEqual( pTruth, pCopy, nWords ) );
+        if ( Config == 0 )
+            return 0;
+        assert( Abc_TtCompareRev(pTruth, pBest, nWords) == 1 );
+        Abc_TtCopy( pTruth, pBest, nWords, 0 );
+        return Config;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Smart evaluation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_TtCofactorPermConfig( word * pTruth, int i, int nWords, int fSwapOnly, int fNaive )
+{
+    if ( nWords == 1 )
+        return Abc_Tt6CofactorPermNaive( pTruth, i, fSwapOnly );
+    if ( fNaive )
+        return Abc_TtCofactorPermNaive( pTruth, i, nWords, fSwapOnly );
+    if ( fSwapOnly )
+    {
+        if ( Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 1, 2 ) < 0 ) // Cof1 < Cof2
+        {
+            Abc_TtSwapAdjacent( pTruth, nWords, i );
+            return 4;
+        }
+        return 0;
+    }
+    {  
+        int fComp01, fComp02, fComp03, fComp12, fComp13, fComp23, Config = 0;
+        fComp01 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 0, 1 );
+        fComp23 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 2, 3 );
+        if ( fComp23 >= 0 ) // Cof2 >= Cof3 
+        {
+            if ( fComp01 >= 0 ) // Cof0 >= Cof1
+            {
+                fComp13 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 1, 3 );
+                if ( fComp13 < 0 ) // Cof1 < Cof3 
+                    Abc_TtFlip( pTruth, nWords, i + 1 ), Config = 2;
+                else if ( fComp13 == 0 ) // Cof1 == Cof3 
+                {
+                    fComp02 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 0, 2 );
+                    if ( fComp02 < 0 )
+                        Abc_TtFlip( pTruth, nWords, i + 1 ), Config = 2;
+                }
+                // else   Cof1 > Cof3 -- do nothing
+            }
+            else // Cof0 < Cof1
+            {
+                fComp03 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 0, 3 );
+                if ( fComp03 < 0 ) // Cof0 < Cof3
+                {
+                    Abc_TtFlip( pTruth, nWords, i );
+                    Abc_TtFlip( pTruth, nWords, i + 1 ), Config = 3;
+                }
+                else //  Cof0 >= Cof3
+                {
+                    if ( fComp23 == 0 ) // can flip Cof0 and Cof1
+                        Abc_TtFlip( pTruth, nWords, i ), Config = 1;
+                }
+            }
+        }
+        else // Cof2 < Cof3 
+        {
+            if ( fComp01 >= 0 ) // Cof0 >= Cof1
+            {
+                fComp12 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 1, 2 );
+                if ( fComp12 > 0 ) // Cof1 > Cof2 
+                    Abc_TtFlip( pTruth, nWords, i ), Config = 1;
+                else if ( fComp12 == 0 ) // Cof1 == Cof2 
+                {
+                    Abc_TtFlip( pTruth, nWords, i );
+                    Abc_TtFlip( pTruth, nWords, i + 1 ), Config = 3;
+                }
+                else // Cof1 < Cof2
+                {
+                    Abc_TtFlip( pTruth, nWords, i + 1 ), Config = 2;
+                    if ( fComp01 == 0 )
+                        Abc_TtFlip( pTruth, nWords, i ), Config ^= 1;
+                }
+            }
+            else // Cof0 < Cof1
+            {
+                fComp02 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 0, 2 );
+                if ( fComp02 == -1 ) // Cof0 < Cof2 
+                {
+                    Abc_TtFlip( pTruth, nWords, i );
+                    Abc_TtFlip( pTruth, nWords, i + 1 ), Config = 3;
+                }
+                else if ( fComp02 == 0 ) // Cof0 == Cof2
+                {
+                    fComp13 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 1, 3 );
+                    if ( fComp13 >= 0 ) // Cof1 >= Cof3 
+                        Abc_TtFlip( pTruth, nWords, i ), Config = 1;
+                    else // Cof1 < Cof3 
+                    {
+                        Abc_TtFlip( pTruth, nWords, i );
+                        Abc_TtFlip( pTruth, nWords, i + 1 ), Config = 3;
+                    }
+                }
+                else // Cof0 > Cof2
+                    Abc_TtFlip( pTruth, nWords, i ), Config = 1;
+            }
+        }
+        // perform final swap if needed
+        fComp12 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 1, 2 );
+        if ( fComp12 < 0 ) // Cof1 < Cof2
+            Abc_TtSwapAdjacent( pTruth, nWords, i ), Config ^= 4;
+        return Config;
+    }
+}
+int Abc_TtCofactorPerm( word * pTruth, int i, int nWords, int fSwapOnly, char * pCanonPerm, unsigned * puCanonPhase, int fNaive )
+{
+    if ( fSwapOnly )
+    {
+        int Config = Abc_TtCofactorPermConfig( pTruth, i, nWords, 1, 0 );
+        if ( Config )
+        {
+            if ( ((*puCanonPhase >> i) & 1) != ((*puCanonPhase >> (i+1)) & 1) )
+            {
+                *puCanonPhase ^= (1 << i);
+                *puCanonPhase ^= (1 << (i+1));
+            }
+            ABC_SWAP( int, pCanonPerm[i], pCanonPerm[i+1] );
+        }
+        return Config;
+    }
+    {
+        static word pCopy1[1024];
+        int Config;
+        Abc_TtCopy( pCopy1, pTruth, nWords, 0 );
+        Config = Abc_TtCofactorPermConfig( pTruth, i, nWords, 0, fNaive );
+        if ( Config == 0 )
+            return 0;
+        if ( Abc_TtCompareRev(pTruth, pCopy1, nWords) == 1 ) // made it worse
+        {
+            Abc_TtCopy( pTruth, pCopy1, nWords, 0 );
+            return 0;
+        }
+        // improved
+        if ( Config & 1 )
+            *puCanonPhase ^= (1 << i);
+        if ( Config & 2 )
+            *puCanonPhase ^= (1 << (i+1));
+        if ( Config & 4 )
+        {
+            if ( ((*puCanonPhase >> i) & 1) != ((*puCanonPhase >> (i+1)) & 1) )
+            {
+                *puCanonPhase ^= (1 << i);
+                *puCanonPhase ^= (1 << (i+1));
+            }
+            ABC_SWAP( int, pCanonPerm[i], pCanonPerm[i+1] );
+        }
+        return Config;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Semi-canonical form computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+//#define CANON_VERIFY
+unsigned Abc_TtCanonicize( word * pTruth, int nVars, char * pCanonPerm )
+{
+    int pStoreIn[17];
+    unsigned uCanonPhase;
+    int i, k, nWords = Abc_TtWordNum( nVars );
+    int fNaive = 1;
+
+#ifdef CANON_VERIFY
+    char pCanonPermCopy[16];
+    static word pCopy1[1024];
+    static word pCopy2[1024];
+    Abc_TtCopy( pCopy1, pTruth, nWords, 0 );
+#endif
+
+    uCanonPhase = Abc_TtSemiCanonicize( pTruth, nVars, pCanonPerm, pStoreIn );
+    for ( k = 0; k < 5; k++ )
+    {
+        int fChanges = 0;
+        for ( i = nVars - 2; i >= 0; i-- )
+            if ( pStoreIn[i] == pStoreIn[i+1] )
+                fChanges |= Abc_TtCofactorPerm( pTruth, i, nWords, pStoreIn[i] != pStoreIn[nVars]/2, pCanonPerm, &uCanonPhase, fNaive );
+        if ( !fChanges )
+            break;
+        fChanges = 0;
+        for ( i = 1; i < nVars - 1; i++ )
+            if ( pStoreIn[i] == pStoreIn[i+1] )
+                fChanges |= Abc_TtCofactorPerm( pTruth, i, nWords, pStoreIn[i] != pStoreIn[nVars]/2, pCanonPerm, &uCanonPhase, fNaive );
+        if ( !fChanges )
+            break;
+    }
+
+#ifdef CANON_VERIFY
+    Abc_TtCopy( pCopy2, pTruth, nWords, 0 );
+    memcpy( pCanonPermCopy, pCanonPerm, sizeof(char) * nVars );
+    Abc_TtImplementNpnConfig( pCopy2, nVars, pCanonPermCopy, uCanonPhase );
+    if ( !Abc_TtEqual( pCopy1, pCopy2, nWords ) )
+        printf( "Canonical form verification failed!\n" );
+#endif
+/*
+    if ( !Abc_TtEqual( pCopy1, pCopy2, nWords ) )
+    {
+        Kit_DsdPrintFromTruth( pCopy1, nVars ); printf( "\n" );
+        Kit_DsdPrintFromTruth( pCopy2, nVars ); printf( "\n" );
+        i = 0;
+    }
+*/
+    return uCanonPhase;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Semi-canonical form computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_TtCanonicizePhaseVar6( word * pTruth, int nVars, int v )
+{
+    int w, nWords = Abc_TtWordNum( nVars );
+    int s, nStep = 1 << (v-6);
+    assert( v >= 6 );
+    for ( w = nWords - 1, s = nWords - nStep; w > 0; w-- )
+    {
+        if ( pTruth[w-nStep] == pTruth[w] )
+        {
+            if ( w == s ) { w = s - nStep; s = w - nStep; }
+            continue;
+        }
+        if ( pTruth[w-nStep] > pTruth[w] )
+            return -1;
+        for ( ; w > 0; w-- )
+        {
+            ABC_SWAP( word, pTruth[w-nStep], pTruth[w] );
+            if ( w == s ) { w = s - nStep; s = w - nStep; }
+        }
+        assert( w == -1 );
+        return 1;
+    }
+    return 0;
+}
+static inline int Abc_TtCanonicizePhaseVar5( word * pTruth, int nVars, int v )
+{
+    int w, nWords = Abc_TtWordNum( nVars );
+    int Shift = 1 << v;
+    word Mask = s_Truths6[v];
+    assert( v < 6 );
+    for ( w = nWords - 1; w >= 0; w-- )
+    {
+        if ( ((pTruth[w] << Shift) & Mask) == (pTruth[w] & Mask) )
+            continue;
+        if ( ((pTruth[w] << Shift) & Mask) > (pTruth[w] & Mask) )
+            return -1;
+//        Extra_PrintHex( stdout, (unsigned *)pTruth, nVars ); printf("\n" );
+        for ( ; w >= 0; w-- )
+            pTruth[w] = ((pTruth[w] << Shift) & Mask) | ((pTruth[w] & Mask) >> Shift);
+//        Extra_PrintHex( stdout, (unsigned *)pTruth, nVars ); printf( " changed %d", v ), printf("\n" );
+        return 1;
+    }
+    return 0;
+}
+unsigned Abc_TtCanonicizePhase( word * pTruth, int nVars )
+{
+    unsigned uCanonPhase = 0;
+    int v, nWords = Abc_TtWordNum( nVars );
+//    static int Counter = 0;
+//    Counter++;
+
+#ifdef CANON_VERIFY
+    static word pCopy1[1024];
+    static word pCopy2[1024];
+    Abc_TtCopy( pCopy1, pTruth, nWords, 0 );
+#endif
+
+    if ( (pTruth[nWords-1] >> 63) & 1 )
+    {
+        Abc_TtNot( pTruth, nWords );
+        uCanonPhase ^= (1 << nVars);
+    }
+
+//    while ( 1 )
+//    {
+//        unsigned uCanonPhase2 = uCanonPhase;
+        for ( v = nVars - 1; v >= 6; v-- )
+            if ( Abc_TtCanonicizePhaseVar6( pTruth, nVars, v ) == 1 )
+                uCanonPhase ^= 1 << v;
+        for ( ; v >= 0; v-- )
+            if ( Abc_TtCanonicizePhaseVar5( pTruth, nVars, v ) == 1 )
+                uCanonPhase ^= 1 << v;
+//        if ( uCanonPhase2 == uCanonPhase )
+//            break;
+//    }
+
+//    for ( v = 5; v >= 0; v-- )
+//        assert( Abc_TtCanonicizePhaseVar5( pTruth, nVars, v ) != 1 );
+
+#ifdef CANON_VERIFY
+    Abc_TtCopy( pCopy2, pTruth, nWords, 0 );
+    Abc_TtImplementNpnConfig( pCopy2, nVars, NULL, uCanonPhase );
+    if ( !Abc_TtEqual( pCopy1, pCopy2, nWords ) )
+        printf( "Canonical form verification failed!\n" );
+#endif
+    return uCanonPhase;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dau/dauCore.c b/abc-build/src/opt/dau/dauCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dau/dauCore.c
@@ -0,0 +1,112 @@
+/**CFile****************************************************************
+
+  FileName    [dauCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware unmapping.]
+
+  Synopsis    [Disjoint-support decomposition.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: dauCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dauInt.h"
+#include "aig/aig/aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// parameter structure 
+typedef struct Xyz_ParTry_t_ Xyz_ParTry_t;
+struct Xyz_ParTry_t_
+{
+    int                Par;
+};
+ 
+// operation manager
+typedef struct Xyz_ManTry_t_ Xyz_ManTry_t;
+struct Xyz_ManTry_t_
+{
+    Xyz_ParTry_t *     pPar;           // parameters
+    Aig_Man_t *        pAig;           // user's AIG 
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Xyz_ManTry_t * Xyz_ManTryAlloc( Aig_Man_t * pAig, Xyz_ParTry_t * pPar )
+{
+    Xyz_ManTry_t * p;
+    p = ABC_CALLOC( Xyz_ManTry_t, 1 );
+    p->pAig    = pAig;
+    p->pPar    = pPar;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Xyz_ManTryFree( Xyz_ManTry_t * p )
+{
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Xyz_ManPerform( Aig_Man_t * pAig, Xyz_ParTry_t * pPar )
+{
+    Xyz_ManTry_t * p;
+    int RetValue;
+    p = Xyz_ManTryAlloc( pAig, pPar );
+    RetValue = 1;
+    Xyz_ManTryFree( p );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dau/dauDivs.c b/abc-build/src/opt/dau/dauDivs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dau/dauDivs.c
@@ -0,0 +1,111 @@
+/**CFile****************************************************************
+
+  FileName    [dauDivs.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware unmapping.]
+
+  Synopsis    [Divisor computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: dauDivs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dauInt.h"
+#include "misc/util/utilTruth.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Dau_DsdDivisors( word * pTruth, int nVars )
+{
+    word Copy[DAU_MAX_WORD];
+    int nWords = Abc_TtWordNum(nVars);
+    int nDigits = Abc_TtHexDigitNum(nVars);
+    int i, j, k, Digit, Counter[5];
+
+    printf( "     " );
+    printf( " !a *!b"  );
+    printf( " !a * b"  );
+    printf( "  a *!b"  );
+    printf( "  a * b"  );
+    printf( "  a + b"  );
+    printf( "\n" );
+
+    for ( i = 0; i < nVars; i++ )
+    for ( j = i+1; j < nVars; j++ )
+    {
+        Abc_TtCopy( Copy, pTruth, nWords, 0 );
+        Abc_TtSwapVars( Copy, nVars, 0, i );
+        Abc_TtSwapVars( Copy, nVars, 1, j );
+        for ( k = 0; k < 5; k++ )
+            Counter[k] = 0;
+        for ( k = 0; k < nDigits; k++ )
+        {
+            Digit = Abc_TtGetHex( Copy, k );
+            if ( Digit == 1 || Digit == 14 )
+                Counter[0]++;
+            else if ( Digit == 2 || Digit == 13 )
+                Counter[1]++;
+            else if ( Digit == 4 || Digit == 11 )
+                Counter[2]++;
+            else if ( Digit == 8 || Digit == 7 )
+                Counter[3]++;
+            else if ( Digit == 6 || Digit == 9 )
+                Counter[4]++;
+        }
+        printf( "%c %c  ", 'a'+i, 'a'+j );
+        for ( k = 0; k < 5; k++ )
+            printf( "%7d", Counter[k] );
+        printf( "\n" );
+    }
+    return NULL;
+}
+void Dau_DsdTest000()
+{
+//    char * pDsd = "!(!(abc)!(def))";
+//    char * pDsd = "[(abc)(def)]";
+    char * pDsd = "<<abc>d(ef)>";
+    word t = Dau_Dsd6ToTruth( pDsd );
+//    word t = 0xCA88CA88CA88CA88;
+//    word t = 0x9ef7a8d9c7193a0f;
+    int nVars = Abc_TtSupportSize( &t, 6 );
+    return;
+//    word t = 0xCACACACACACACACA;
+    Dau_DsdDivisors( &t, nVars );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dau/dauDsd.c b/abc-build/src/opt/dau/dauDsd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dau/dauDsd.c
@@ -0,0 +1,2098 @@
+/**CFile****************************************************************
+
+  FileName    [dauDsd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware unmapping.]
+
+  Synopsis    [Disjoint-support decomposition.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: dauDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dauInt.h"
+#include "misc/util/utilTruth.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+/* 
+    This code performs truth-table-based decomposition for 6-variable functions.
+    Representation of operations:
+    ! = not; 
+    (ab) = a and b;  
+    [ab] = a xor b;  
+    <abc> = ITE( a, b, c )
+    FUNCTION{abc} = FUNCTION( a, b, c )
+*/
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Elementary truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word ** Dau_DsdTtElems()
+{
+    static word TtElems[DAU_MAX_VAR+1][DAU_MAX_WORD], * pTtElems[DAU_MAX_VAR+1] = {NULL};
+    if ( pTtElems[0] == NULL )
+    {
+        int v;
+        for ( v = 0; v <= DAU_MAX_VAR; v++ )
+            pTtElems[v] = TtElems[v];
+        Abc_TtElemInit( pTtElems, DAU_MAX_VAR );
+    }
+    return pTtElems;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [DSD formula manipulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Dau_DsdComputeMatches( char * p )
+{
+    static int pMatches[DAU_MAX_STR];
+    int pNested[DAU_MAX_VAR];
+    int v, nNested = 0;
+    for ( v = 0; p[v]; v++ )
+    {
+        pMatches[v] = 0;
+        if ( p[v] == '(' || p[v] == '[' || p[v] == '<' || p[v] == '{' )
+            pNested[nNested++] = v;
+        else if ( p[v] == ')' || p[v] == ']' || p[v] == '>' || p[v] == '}' )
+            pMatches[pNested[--nNested]] = v;
+        assert( nNested < DAU_MAX_VAR );
+    }
+    assert( nNested == 0 );
+    return pMatches;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generate random permutation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dau_DsdFindVarNum( char * pDsd )
+{
+    int vMax = 0;
+    pDsd--;
+    while ( *++pDsd )
+        if ( *pDsd >= 'a' && *pDsd <= 'z' )
+            vMax = Abc_MaxInt( vMax, *pDsd - 'a' );
+    return vMax + 1;
+}
+void Dau_DsdGenRandPerm( int * pPerm, int nVars )
+{
+    int v, vNew;
+    for ( v = 0; v < nVars; v++ )
+        pPerm[v] = v;
+    for ( v = 0; v < nVars; v++ )
+    {
+        vNew = rand() % nVars;
+        ABC_SWAP( int, pPerm[v], pPerm[vNew] );
+    }
+}
+void Dau_DsdPermute( char * pDsd )
+{
+    int pPerm[16];
+    int nVars = Dau_DsdFindVarNum( pDsd );
+    Dau_DsdGenRandPerm( pPerm, nVars );
+    pDsd--;
+    while ( *++pDsd )
+        if ( *pDsd >= 'a' && *pDsd < 'a' + nVars )
+            *pDsd = 'a' + pPerm[*pDsd - 'a'];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Normalize the ordering of components.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Dau_DsdNormalizeCopy( char * pDest, char * pSour, int * pMarks, int i )
+{
+    int s;
+    for ( s = pMarks[i]; s < pMarks[i+1]; s++ )
+        *pDest++ = pSour[s];
+    return pDest;
+}
+int Dau_DsdNormalizeCompare( char * pStr, int * pMarks, int i, int j )
+{
+    char * pStr1 = pStr + pMarks[i];
+    char * pStr2 = pStr + pMarks[j];
+    char * pLimit1 = pStr + pMarks[i+1];
+    char * pLimit2 = pStr + pMarks[j+1];
+    for ( ; pStr1 < pLimit1 && pStr2 < pLimit2; pStr1++, pStr2++ )
+    {
+        if ( !(*pStr1 >= 'a' &&  *pStr1 <= 'z') )
+        {
+            pStr2--;
+            continue;
+        }
+        if ( !(*pStr2 >= 'a' &&  *pStr2 <= 'z') )
+        {
+            pStr1--;
+            continue;
+        }
+        if ( *pStr1 < *pStr2 )
+            return -1;
+        if ( *pStr1 > *pStr2 )
+            return 1;
+    }
+    assert( pStr1 < pLimit1 || pStr2 < pLimit2 );
+    if ( pStr1 == pLimit1 )
+        return -1;
+    if ( pStr2 == pLimit2 )
+        return 1;
+    assert( 0 );
+    return 0;
+}
+int * Dau_DsdNormalizePerm( char * pStr, int * pMarks, int nMarks )
+{
+    static int pPerm[DAU_MAX_VAR];
+    int i, k;
+    for ( i = 0; i < nMarks; i++ )
+        pPerm[i] = i;
+    for ( i = 0; i < nMarks; i++ )
+    {
+        int iBest = i;
+        for ( k = i + 1; k < nMarks; k++ )
+            if ( Dau_DsdNormalizeCompare( pStr, pMarks, pPerm[iBest], pPerm[k] ) == 1 )
+                iBest = k;
+        ABC_SWAP( int, pPerm[i], pPerm[iBest] );
+    }
+    return pPerm;
+}
+void Dau_DsdNormalize_rec( char * pStr, char ** p, int * pMatches )
+{
+    static char pBuffer[DAU_MAX_STR];
+    if ( **p == '!' )
+        (*p)++;
+    while ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') )
+        (*p)++;
+    if ( **p == '<' )
+    {
+        char * q = pStr + pMatches[*p - pStr];
+        if ( *(q+1) == '{' )
+            *p = q+1;
+    }
+    if ( **p >= 'a' && **p <= 'z' ) // var
+        return;
+    if ( **p == '(' || **p == '[' ) // and/or/xor
+    {
+        char * pStore, * pOld = *p + 1;
+        char * q = pStr + pMatches[ *p - pStr ];
+        int i, * pPerm, nMarks = 0, pMarks[DAU_MAX_VAR+1];
+        assert( *q == **p + 1 + (**p != '(') );
+        for ( (*p)++; *p < q; (*p)++ )
+        {
+            pMarks[nMarks++] = *p - pStr;
+            Dau_DsdNormalize_rec( pStr, p, pMatches );
+        }
+        pMarks[nMarks] = *p - pStr;
+        assert( *p == q );
+        // add to buffer in good order
+        pPerm = Dau_DsdNormalizePerm( pStr, pMarks, nMarks );
+        // copy to the buffer
+        pStore = pBuffer;
+        for ( i = 0; i < nMarks; i++ )
+            pStore = Dau_DsdNormalizeCopy( pStore, pStr, pMarks, pPerm[i] );
+        assert( pStore - pBuffer == *p - pOld );
+        memcpy( pOld, pBuffer, pStore - pBuffer );
+        return;
+    }
+    if ( **p == '<' || **p == '{' ) // mux
+    {
+        char * q = pStr + pMatches[ *p - pStr ];
+        assert( *q == **p + 1 + (**p != '(') );
+        if ( (**p == '<') && (*(q+1) == '{') )
+        {
+            *p = q+1;
+            Dau_DsdNormalize_rec( pStr, p, pMatches );
+            return;
+        }
+        for ( (*p)++; *p < q; (*p)++ )
+            Dau_DsdNormalize_rec( pStr, p, pMatches );
+        assert( *p == q );
+        return;
+    }
+    assert( 0 );
+}
+void Dau_DsdNormalize( char * pDsd )
+{
+    if ( pDsd[1] != 0 )
+        Dau_DsdNormalize_rec( pDsd, &pDsd, Dau_DsdComputeMatches(pDsd) );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dau_DsdCountAnds_rec( char * pStr, char ** p, int * pMatches )
+{
+    if ( **p == '!' )
+        (*p)++;
+    while ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') )
+        (*p)++;
+    if ( **p == '<' )
+    {
+        char * q = pStr + pMatches[*p - pStr];
+        if ( *(q+1) == '{' )
+            *p = q+1;
+    }
+    if ( **p >= 'a' && **p <= 'z' ) // var
+        return 0;
+    if ( **p == '(' || **p == '[' ) // and/or/xor
+    {
+        int Counter = 0, AddOn = (**p == '(')? 1 : 3;
+        char * q = pStr + pMatches[ *p - pStr ];
+        assert( *q == **p + 1 + (**p != '(') );
+        for ( (*p)++; *p < q; (*p)++ )
+            Counter += AddOn + Dau_DsdCountAnds_rec( pStr, p, pMatches );
+        assert( *p == q );
+        return Counter - AddOn;
+    }
+    if ( **p == '<' || **p == '{' ) // mux
+    {
+        int Counter = 3;
+        char * q = pStr + pMatches[ *p - pStr ];
+        assert( *q == **p + 1 + (**p != '(') );
+        for ( (*p)++; *p < q; (*p)++ )
+            Counter += Dau_DsdCountAnds_rec( pStr, p, pMatches );
+        assert( *p == q );
+        return Counter;
+    }
+    assert( 0 );
+    return 0;
+}
+int Dau_DsdCountAnds( char * pDsd )
+{
+    if ( pDsd[1] == 0 )
+        return 0;
+    return Dau_DsdCountAnds_rec( pDsd, &pDsd, Dau_DsdComputeMatches(pDsd) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table for the DSD formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word Dau_Dsd6TruthCompose_rec( word Func, word * pFanins, int nVars )
+{
+    word t0, t1;
+    if ( Func == 0 )
+        return 0;
+    if ( Func == ~(word)0 )
+        return ~(word)0;
+    assert( nVars > 0 );
+    if ( --nVars == 0 )
+    {
+        assert( Func == s_Truths6[0] || Func == s_Truths6Neg[0] );
+        return (Func == s_Truths6[0]) ? pFanins[0] : ~pFanins[0];
+    }
+    if ( !Abc_Tt6HasVar(Func, nVars) )
+        return Dau_Dsd6TruthCompose_rec( Func, pFanins, nVars );
+    t0 = Dau_Dsd6TruthCompose_rec( Abc_Tt6Cofactor0(Func, nVars), pFanins, nVars );
+    t1 = Dau_Dsd6TruthCompose_rec( Abc_Tt6Cofactor1(Func, nVars), pFanins, nVars );
+    return (~pFanins[nVars] & t0) | (pFanins[nVars] & t1);
+}
+word Dau_Dsd6ToTruth_rec( char * pStr, char ** p, int * pMatches, word * pTruths )
+{
+    int fCompl = 0;
+    if ( **p == '!' )
+        (*p)++, fCompl = 1;
+    if ( **p >= 'a' && **p <= 'f' ) // var
+    {
+        assert( **p - 'a' >= 0 && **p - 'a' < 6 );
+        return fCompl ? ~pTruths[**p - 'a'] : pTruths[**p - 'a'];
+    }
+    if ( **p == '(' ) // and/or
+    {
+        char * q = pStr + pMatches[ *p - pStr ];
+        word Res = ~(word)0;
+        assert( **p == '(' && *q == ')' );
+        for ( (*p)++; *p < q; (*p)++ )
+            Res &= Dau_Dsd6ToTruth_rec( pStr, p, pMatches, pTruths );
+        assert( *p == q );
+        return fCompl ? ~Res : Res;
+    }
+    if ( **p == '[' ) // xor
+    {
+        char * q = pStr + pMatches[ *p - pStr ];
+        word Res = 0;
+        assert( **p == '[' && *q == ']' );
+        for ( (*p)++; *p < q; (*p)++ )
+            Res ^= Dau_Dsd6ToTruth_rec( pStr, p, pMatches, pTruths );
+        assert( *p == q );
+        return fCompl ? ~Res : Res;
+    }
+    if ( **p == '<' ) // mux
+    {
+        int nVars = 0;
+        word Temp[3], * pTemp = Temp, Res;
+        word Fanins[6], * pTruths2;
+        char * pOld = *p;
+        char * q = pStr + pMatches[ *p - pStr ];
+        // read fanins
+        if ( *(q+1) == '{' )
+        {
+            char * q2;
+            *p = q+1;
+            q2 = pStr + pMatches[ *p - pStr ];
+            assert( **p == '{' && *q2 == '}' );
+            for ( nVars = 0, (*p)++; *p < q2; (*p)++, nVars++ )
+                Fanins[nVars] = Dau_Dsd6ToTruth_rec( pStr, p, pMatches, pTruths );
+            assert( *p == q2 );
+            pTruths2 = Fanins;
+        }
+        else
+            pTruths2 = pTruths;
+        // read MUX
+        *p = pOld;
+        q = pStr + pMatches[ *p - pStr ];
+        assert( **p == '<' && *q == '>' );
+        // verify internal variables
+        if ( nVars )
+            for ( ; pOld < q; pOld++ )
+                if ( *pOld >= 'a' && *pOld <= 'z' )
+                    assert( *pOld - 'a' < nVars );
+        // derive MAX components
+        for ( (*p)++; *p < q; (*p)++ )
+            *pTemp++ = Dau_Dsd6ToTruth_rec( pStr, p, pMatches, pTruths2 );
+        assert( pTemp == Temp + 3 );
+        assert( *p == q );
+        if ( *(q+1) == '{' ) // and/or
+        {
+            char * q = pStr + pMatches[ ++(*p) - pStr ];
+            assert( **p == '{' && *q == '}' );
+            *p = q;
+        }
+        Res = (Temp[0] & Temp[1]) | (~Temp[0] & Temp[2]);
+        return fCompl ? ~Res : Res;
+    }
+    if ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') )
+    {
+        word Func, Fanins[6], Res;
+        char * q;
+        int i, nVars = Abc_TtReadHex( &Func, *p );
+        *p += Abc_TtHexDigitNum( nVars );
+        q = pStr + pMatches[ *p - pStr ];
+        assert( **p == '{' && *q == '}' );
+        for ( i = 0, (*p)++; *p < q; (*p)++, i++ )
+            Fanins[i] = Dau_Dsd6ToTruth_rec( pStr, p, pMatches, pTruths );
+        assert( i == nVars );
+        assert( *p == q );
+        Res = Dau_Dsd6TruthCompose_rec( Func, Fanins, nVars );
+        return fCompl ? ~Res : Res;
+    }
+    assert( 0 );
+    return 0;
+}
+word Dau_Dsd6ToTruth( char * p )
+{
+    word Res;
+    if ( *p == '0' && *(p+1) == 0 )
+        Res = 0;
+    else if ( *p == '1' && *(p+1) == 0 )
+        Res = ~(word)0;
+    else
+        Res = Dau_Dsd6ToTruth_rec( p, &p, Dau_DsdComputeMatches(p), s_Truths6 );
+    assert( *++p == 0 );
+    return Res;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table for the DSD formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dau_DsdTruth6Compose_rec( word Func, word pFanins[DAU_MAX_VAR][DAU_MAX_WORD], word * pRes, int nVars, int nWordsR )
+{
+    if ( Func == 0 )
+    {
+        Abc_TtConst0( pRes, nWordsR );
+        return;
+    }
+    if ( Func == ~(word)0 )
+    {
+        Abc_TtConst1( pRes, nWordsR );
+        return;
+    }
+    assert( nVars > 0 );
+    if ( --nVars == 0 )
+    {
+        assert( Func == s_Truths6[0] || Func == s_Truths6Neg[0] );
+        Abc_TtCopy( pRes, pFanins[0], nWordsR, Func == s_Truths6Neg[0] );
+        return;
+    }
+    if ( !Abc_Tt6HasVar(Func, nVars) )
+    {
+        Dau_DsdTruth6Compose_rec( Func, pFanins, pRes, nVars, nWordsR );
+        return;
+    }
+    {
+        word pTtTemp[2][DAU_MAX_WORD];
+        Dau_DsdTruth6Compose_rec( Abc_Tt6Cofactor0(Func, nVars), pFanins, pTtTemp[0], nVars, nWordsR );
+        Dau_DsdTruth6Compose_rec( Abc_Tt6Cofactor1(Func, nVars), pFanins, pTtTemp[1], nVars, nWordsR );
+        Abc_TtMux( pRes, pFanins[nVars], pTtTemp[1], pTtTemp[0], nWordsR );
+        return;
+    }
+}
+void Dau_DsdTruthCompose_rec( word * pFunc, word pFanins[DAU_MAX_VAR][DAU_MAX_WORD], word * pRes, int nVars, int nWordsR )
+{
+    int nWordsF;
+    if ( nVars <= 6 )
+    {
+        Dau_DsdTruth6Compose_rec( pFunc[0], pFanins, pRes, nVars, nWordsR );
+        return;
+    }
+    nWordsF = Abc_TtWordNum( nVars );
+    assert( nWordsF > 1 );
+    if ( Abc_TtIsConst0(pFunc, nWordsF) )
+    {
+        Abc_TtConst0( pRes, nWordsR );
+        return;
+    }
+    if ( Abc_TtIsConst1(pFunc, nWordsF) )
+    {
+        Abc_TtConst1( pRes, nWordsR );
+        return;
+    }
+    if ( !Abc_TtHasVar( pFunc, nVars, nVars-1 ) )
+    {
+        Dau_DsdTruthCompose_rec( pFunc, pFanins, pRes, nVars-1, nWordsR );
+        return;
+    }
+    {
+        word pTtTemp[2][DAU_MAX_WORD];
+        nVars--;
+        Dau_DsdTruthCompose_rec( pFunc,             pFanins, pTtTemp[0], nVars, nWordsR );
+        Dau_DsdTruthCompose_rec( pFunc + nWordsF/2, pFanins, pTtTemp[1], nVars, nWordsR );
+        Abc_TtMux( pRes, pFanins[nVars], pTtTemp[1], pTtTemp[0], nWordsR );
+        return;
+    }
+}
+void Dau_DsdToTruth_rec( char * pStr, char ** p, int * pMatches, word ** pTtElems, word * pRes, int nVars )
+{
+    int nWords = Abc_TtWordNum( nVars );
+    int fCompl = 0;
+    if ( **p == '!' )
+        (*p)++, fCompl = 1;
+    if ( **p >= 'a' && **p <= 'z' ) // var
+    {
+        assert( **p - 'a' >= 0 && **p - 'a' < nVars );
+        Abc_TtCopy( pRes, pTtElems[**p - 'a'], nWords, fCompl );
+        return;
+    }
+    if ( **p == '(' ) // and/or
+    {
+        char * q = pStr + pMatches[ *p - pStr ];
+        word pTtTemp[DAU_MAX_WORD];
+        assert( **p == '(' && *q == ')' );
+        Abc_TtConst1( pRes, nWords );
+        for ( (*p)++; *p < q; (*p)++ )
+        {
+            Dau_DsdToTruth_rec( pStr, p, pMatches, pTtElems, pTtTemp, nVars );
+            Abc_TtAnd( pRes, pRes, pTtTemp, nWords, 0 );
+        }
+        assert( *p == q );
+        if ( fCompl ) Abc_TtNot( pRes, nWords );
+        return;
+    }
+    if ( **p == '[' ) // xor
+    {
+        char * q = pStr + pMatches[ *p - pStr ];
+        word pTtTemp[DAU_MAX_WORD];
+        assert( **p == '[' && *q == ']' );
+        Abc_TtConst0( pRes, nWords );
+        for ( (*p)++; *p < q; (*p)++ )
+        {
+            Dau_DsdToTruth_rec( pStr, p, pMatches, pTtElems, pTtTemp, nVars );
+            Abc_TtXor( pRes, pRes, pTtTemp, nWords, 0 );
+        }
+        assert( *p == q );
+        if ( fCompl ) Abc_TtNot( pRes, nWords );
+        return;
+    }
+    if ( **p == '<' ) // mux
+    {
+        char * q = pStr + pMatches[ *p - pStr ];
+        word pTtTemp[3][DAU_MAX_WORD];
+        int i;
+        assert( **p == '<' && *q == '>' );
+        for ( i = 0, (*p)++; *p < q; (*p)++, i++ )
+            Dau_DsdToTruth_rec( pStr, p, pMatches, pTtElems, pTtTemp[i], nVars );
+        assert( i == 3 );
+        Abc_TtMux( pRes, pTtTemp[0], pTtTemp[1], pTtTemp[2], nWords );
+        assert( *p == q );
+        if ( fCompl ) Abc_TtNot( pRes, nWords );
+        return;
+    }
+    if ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') )
+    {
+        word pFanins[DAU_MAX_VAR][DAU_MAX_WORD], pFunc[DAU_MAX_WORD];
+        char * q;
+        int i, nVarsF = Abc_TtReadHex( pFunc, *p );
+        *p += Abc_TtHexDigitNum( nVarsF );
+        q = pStr + pMatches[ *p - pStr ];
+        assert( **p == '{' && *q == '}' );
+        for ( i = 0, (*p)++; *p < q; (*p)++, i++ )
+            Dau_DsdToTruth_rec( pStr, p, pMatches, pTtElems, pFanins[i], nVars );
+        assert( i == nVarsF );
+        assert( *p == q );
+        Dau_DsdTruthCompose_rec( pFunc, pFanins, pRes, nVarsF, nWords );
+        if ( fCompl ) Abc_TtNot( pRes, nWords );
+        return;
+    }
+    assert( 0 );
+}
+word * Dau_DsdToTruth( char * p, int nVars )
+{
+    int nWords = Abc_TtWordNum( nVars );
+    word ** pTtElems = Dau_DsdTtElems();
+    word * pRes = pTtElems[DAU_MAX_VAR];
+    assert( nVars <= DAU_MAX_VAR );
+    if ( Dau_DsdIsConst0(p) )
+        Abc_TtConst0( pRes, nWords );
+    else if ( Dau_DsdIsConst1(p) )
+        Abc_TtConst1( pRes, nWords );
+    else
+        Dau_DsdToTruth_rec( p, &p, Dau_DsdComputeMatches(p), pTtElems, pRes, nVars );
+    assert( *++p == 0 );
+    return pRes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dau_DsdTest2()
+{
+//    char * p = Abc_UtilStrsav( "!(ab!(de[cf]))" );
+//    char * p = Abc_UtilStrsav( "!(a![d<ecf>]b)" );
+//    word t = Dau_Dsd6ToTruth( p );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DSD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dau_DsdPerformReplace( char * pBuffer, int PosStart, int Pos, int Symb, char * pNext )
+{
+    static char pTemp[DAU_MAX_STR];
+    char * pCur = pTemp;
+    int i, k, RetValue;
+    for ( i = PosStart; i < Pos; i++ )
+        if ( pBuffer[i] != Symb )
+            *pCur++ = pBuffer[i];
+        else
+            for ( k = 0; pNext[k]; k++ )
+                *pCur++ = pNext[k];
+    RetValue = PosStart + (pCur - pTemp);
+    for ( i = PosStart; i < RetValue; i++ )
+        pBuffer[i] = pTemp[i-PosStart];
+    return RetValue;
+}
+int Dau_DsdPerform_rec( word t, char * pBuffer, int Pos, int * pVars, int nVars )
+{
+    char pNest[10];
+    word Cof0[6], Cof1[6], Cof[4];
+    int pVarsNew[6], nVarsNew, PosStart;
+    int v, u, vBest, CountBest;
+    assert( Pos < DAU_MAX_STR );
+    // perform support minimization
+    nVarsNew = 0;
+    for ( v = 0; v < nVars; v++ )
+        if ( Abc_Tt6HasVar( t, pVars[v] ) )
+            pVarsNew[ nVarsNew++ ] = pVars[v];
+    assert( nVarsNew > 0 );
+    // special case when function is a var
+    if ( nVarsNew == 1 )
+    {
+        if ( t == s_Truths6[ pVarsNew[0] ] )
+        {
+            pBuffer[Pos++] = 'a' +  pVarsNew[0];
+            return Pos;
+        }
+        if ( t == ~s_Truths6[ pVarsNew[0] ] )
+        {
+            pBuffer[Pos++] = '!';
+            pBuffer[Pos++] = 'a' +  pVarsNew[0];
+            return Pos;
+        }
+        assert( 0 );
+        return Pos;
+    }
+    // decompose on the output side
+    for ( v = 0; v < nVarsNew; v++ )
+    {
+        Cof0[v] = Abc_Tt6Cofactor0( t, pVarsNew[v] );
+        Cof1[v] = Abc_Tt6Cofactor1( t, pVarsNew[v] );
+        assert( Cof0[v] != Cof1[v] );
+        if ( Cof0[v] == 0 ) // ax
+        {
+            pBuffer[Pos++] = '(';
+            pBuffer[Pos++] = 'a' + pVarsNew[v];
+            Pos = Dau_DsdPerform_rec( Cof1[v], pBuffer, Pos, pVarsNew, nVarsNew );
+            pBuffer[Pos++] = ')';
+            return Pos;
+        }
+        if ( Cof0[v] == ~(word)0 ) // !(ax)
+        {
+            pBuffer[Pos++] = '!';
+            pBuffer[Pos++] = '(';
+            pBuffer[Pos++] = 'a' + pVarsNew[v];
+            Pos = Dau_DsdPerform_rec( ~Cof1[v], pBuffer, Pos, pVarsNew, nVarsNew );
+            pBuffer[Pos++] = ')';
+            return Pos;
+        }
+        if ( Cof1[v] == 0 ) // !ax
+        {
+            pBuffer[Pos++] = '(';
+            pBuffer[Pos++] = '!';
+            pBuffer[Pos++] = 'a' + pVarsNew[v];
+            Pos = Dau_DsdPerform_rec( Cof0[v], pBuffer, Pos, pVarsNew, nVarsNew );
+            pBuffer[Pos++] = ')';
+            return Pos;
+        }
+        if ( Cof1[v] == ~(word)0 ) // !(!ax)
+        {
+            pBuffer[Pos++] = '!';
+            pBuffer[Pos++] = '(';
+            pBuffer[Pos++] = '!';
+            pBuffer[Pos++] = 'a' + pVarsNew[v];
+            Pos = Dau_DsdPerform_rec( ~Cof0[v], pBuffer, Pos, pVarsNew, nVarsNew );
+            pBuffer[Pos++] = ')';
+            return Pos;
+        }
+        if ( Cof0[v] == ~Cof1[v] ) // a^x
+        {
+            pBuffer[Pos++] = '[';
+            pBuffer[Pos++] = 'a' + pVarsNew[v];
+            Pos = Dau_DsdPerform_rec( Cof0[v], pBuffer, Pos, pVarsNew, nVarsNew );
+            pBuffer[Pos++] = ']';
+            return Pos;
+        }
+    }
+    // decompose on the input side
+    for ( v = 0; v < nVarsNew; v++ )
+    for ( u = v+1; u < nVarsNew; u++ )
+    {
+        Cof[0] = Abc_Tt6Cofactor0( Cof0[v], pVarsNew[u] );
+        Cof[1] = Abc_Tt6Cofactor1( Cof0[v], pVarsNew[u] );
+        Cof[2] = Abc_Tt6Cofactor0( Cof1[v], pVarsNew[u] );
+        Cof[3] = Abc_Tt6Cofactor1( Cof1[v], pVarsNew[u] );
+        if ( Cof[0] == Cof[1] && Cof[0] == Cof[2] ) // vu
+        {
+            PosStart = Pos;
+            sprintf( pNest, "(%c%c)", 'a' + pVarsNew[v], 'a' + pVarsNew[u] );
+            Pos = Dau_DsdPerform_rec( (s_Truths6[pVarsNew[u]] & Cof[3]) | (~s_Truths6[pVarsNew[u]] & Cof[0]), pBuffer, Pos, pVarsNew, nVarsNew );
+            Pos = Dau_DsdPerformReplace( pBuffer, PosStart, Pos, 'a' + pVarsNew[u], pNest );
+            return Pos;
+        }
+        if ( Cof[0] == Cof[1] && Cof[0] == Cof[3] ) // v!u
+        {
+            PosStart = Pos;
+            sprintf( pNest, "(%c!%c)", 'a' + pVarsNew[v], 'a' + pVarsNew[u] );
+            Pos = Dau_DsdPerform_rec( (s_Truths6[pVarsNew[u]] & Cof[2]) | (~s_Truths6[pVarsNew[u]] & Cof[0]), pBuffer, Pos, pVarsNew, nVarsNew );
+            Pos = Dau_DsdPerformReplace( pBuffer, PosStart, Pos, 'a' + pVarsNew[u], pNest );
+            return Pos;
+        }
+        if ( Cof[0] == Cof[2] && Cof[0] == Cof[3] ) // !vu
+        {
+            PosStart = Pos;
+            sprintf( pNest, "(!%c%c)", 'a' + pVarsNew[v], 'a' + pVarsNew[u] );
+            Pos = Dau_DsdPerform_rec( (s_Truths6[pVarsNew[u]] & Cof[1]) | (~s_Truths6[pVarsNew[u]] & Cof[0]), pBuffer, Pos, pVarsNew, nVarsNew );
+            Pos = Dau_DsdPerformReplace( pBuffer, PosStart, Pos, 'a' + pVarsNew[u], pNest );
+            return Pos;
+        }
+        if ( Cof[1] == Cof[2] && Cof[1] == Cof[3] ) // !v!u
+        {
+            PosStart = Pos;
+            sprintf( pNest, "(!%c!%c)", 'a' + pVarsNew[v], 'a' + pVarsNew[u] );
+            Pos = Dau_DsdPerform_rec( (s_Truths6[pVarsNew[u]] & Cof[0]) | (~s_Truths6[pVarsNew[u]] & Cof[1]), pBuffer, Pos, pVarsNew, nVarsNew );
+            Pos = Dau_DsdPerformReplace( pBuffer, PosStart, Pos, 'a' + pVarsNew[u], pNest );
+            return Pos;
+        }
+        if ( Cof[0] == Cof[3] && Cof[1] == Cof[2] ) // v+u
+        {
+            PosStart = Pos;
+            sprintf( pNest, "[%c%c]", 'a' + pVarsNew[v], 'a' + pVarsNew[u] );
+            Pos = Dau_DsdPerform_rec( (s_Truths6[pVarsNew[u]] & Cof[1]) | (~s_Truths6[pVarsNew[u]] & Cof[0]), pBuffer, Pos, pVarsNew, nVarsNew );
+            Pos = Dau_DsdPerformReplace( pBuffer, PosStart, Pos, 'a' + pVarsNew[u], pNest );
+            return Pos;
+        }
+    } 
+    // find best variable for MUX decomposition
+    vBest = -1;
+    CountBest = 10;
+    for ( v = 0; v < nVarsNew; v++ )
+    {
+        int CountCur = 0;
+        for ( u = 0; u < nVarsNew; u++ )
+            if ( u != v && Abc_Tt6HasVar(Cof0[v], pVarsNew[u]) && Abc_Tt6HasVar(Cof1[v], pVarsNew[u]) )
+                CountCur++;
+        if ( CountBest > CountCur )
+        {
+            CountBest = CountCur;
+            vBest = v;
+        }
+        if ( CountCur == 0 )
+            break;
+    }
+    // perform MUX decomposition
+    pBuffer[Pos++] = '<';
+    pBuffer[Pos++] = 'a' + pVarsNew[vBest];
+    Pos = Dau_DsdPerform_rec( Cof1[vBest], pBuffer, Pos, pVarsNew, nVarsNew );
+    Pos = Dau_DsdPerform_rec( Cof0[vBest], pBuffer, Pos, pVarsNew, nVarsNew );
+    pBuffer[Pos++] = '>';
+    return Pos;
+}
+char * Dau_DsdPerform( word t )
+{
+    static char pBuffer[DAU_MAX_STR];
+    int pVarsNew[6] = {0, 1, 2, 3, 4, 5};
+    int Pos = 0;
+    if ( t == 0 )
+        pBuffer[Pos++] = '0';
+    else if ( t == ~(word)0 )
+        pBuffer[Pos++] = '1';
+    else
+        Pos = Dau_DsdPerform_rec( t, pBuffer, Pos, pVarsNew, 6 );
+    pBuffer[Pos++] = 0;
+//    printf( "%d ", strlen(pBuffer) );
+//    printf( "%s ->", pBuffer );
+    Dau_DsdRemoveBraces( pBuffer, Dau_DsdComputeMatches(pBuffer) );
+//    printf( " %s\n", pBuffer );
+    return pBuffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dau_DsdTest3()
+{
+//    word t = s_Truths6[0] & s_Truths6[1] & s_Truths6[2];
+//    word t = ~s_Truths6[0] | (s_Truths6[1] ^ ~s_Truths6[2]);
+//    word t = (s_Truths6[1] & s_Truths6[2]) | (s_Truths6[0] & s_Truths6[3]);
+//    word t = (~s_Truths6[1] & ~s_Truths6[2]) | (s_Truths6[0] ^ s_Truths6[3]);
+//    word t = ((~s_Truths6[1] & ~s_Truths6[2]) | (s_Truths6[0] ^ s_Truths6[3])) ^ s_Truths6[5];
+//    word t = ((s_Truths6[1] & ~s_Truths6[2]) ^ (s_Truths6[0] & s_Truths6[3])) & s_Truths6[5];
+//    word t = (~(~s_Truths6[0] & ~s_Truths6[4]) & s_Truths6[2]) | (~s_Truths6[1] & ~s_Truths6[0] & ~s_Truths6[4]);
+//    word t = 0x0000000000005F3F;
+//    word t = 0xF3F5030503050305;
+//    word t = (s_Truths6[0] & s_Truths6[1] & (s_Truths6[2] ^ s_Truths6[4])) | (~s_Truths6[0] & ~s_Truths6[1] & ~(s_Truths6[2] ^ s_Truths6[4]));
+//    word t = 0x05050500f5f5f5f3;
+    word t = ABC_CONST(0x9ef7a8d9c7193a0f);
+    char * p = Dau_DsdPerform( t );
+    word t2 = Dau_Dsd6ToTruth( p );
+    if ( t != t2 )
+        printf( "Verification failed.\n" );
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Find the best cofactoring variable.]
+
+  Description [Return -2 if non-DSD; -1 if full DSD; otherwise,
+  returns cofactoring variables i (i >= 0).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dau_DsdCheck1Step( void * p, word * pTruth, int nVarsInit, int * pVarLevels )
+{
+    word pCofTemp[DAU_MAX_WORD];
+    int pVarPrios[DAU_MAX_VAR];
+    int nWords = Abc_TtWordNum(nVarsInit);
+    int nSizeNonDec, nSizeNonDec0, nSizeNonDec1;
+    int i, vBest = -2, nSumCofsBest = ABC_INFINITY, nSumCofs;
+    nSizeNonDec = Dau_DsdDecompose( pTruth, nVarsInit, 0, 0, NULL );
+    if ( nSizeNonDec == 0 )
+        return -1;
+    assert( nSizeNonDec > 0 );
+    // find variable priority
+    for ( i = 0; i < nVarsInit; i++ )
+        pVarPrios[i] = i;
+    if ( pVarLevels )
+    {
+        extern int Dau_DsdLevelVar( void * pMan, int iVar );
+        int pVarLevels[DAU_MAX_VAR];
+        for ( i = 0; i < nVarsInit; i++ )
+            pVarLevels[i] = -Dau_DsdLevelVar( p, i );
+//        for ( i = 0; i < nVarsInit; i++ )
+//            printf( "%d ", -pVarLevels[i] );
+//        printf( "\n" );
+        Vec_IntSelectSortCost2( pVarPrios, nVarsInit, pVarLevels );
+//        for ( i = 0; i < nVarsInit; i++ )
+//            printf( "%d ", pVarPrios[i] );
+//        printf( "\n\n" );
+    }
+    for ( i = 0; i < nVarsInit; i++ )
+    {
+        assert( pVarPrios[i] >= 0 && pVarPrios[i] < nVarsInit );
+        // try first cofactor
+        Abc_TtCofactor0p( pCofTemp, pTruth, nWords, pVarPrios[i] );
+        nSumCofs = Abc_TtSupportSize( pCofTemp, nVarsInit );
+        nSizeNonDec0 = Dau_DsdDecompose( pCofTemp, nVarsInit, 0, 0, NULL );
+        // try second cofactor
+        Abc_TtCofactor1p( pCofTemp, pTruth, nWords, pVarPrios[i] );
+        nSumCofs += Abc_TtSupportSize( pCofTemp, nVarsInit );
+        nSizeNonDec1 = Dau_DsdDecompose( pCofTemp, nVarsInit, 0, 0, NULL );
+        // compare cofactors
+        if ( nSizeNonDec0 || nSizeNonDec1 )
+            continue;
+        if ( nSumCofsBest > nSumCofs )
+        {
+            vBest = pVarPrios[i];
+            nSumCofsBest = nSumCofs;
+        }
+    }
+    return vBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Data-structure to store DSD information.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+typedef struct Dau_Dsd_t_ Dau_Dsd_t;
+struct Dau_Dsd_t_
+{
+    int      nVarsInit;            // the initial number of variables
+    int      nVarsUsed;            // the current number of variables
+    int      nPos;                 // writing position
+    int      nSizeNonDec;          // size of the largest non-decomposable block
+    int      nConsts;              // the number of constant decompositions
+    int      uConstMask;           // constant decomposition mask
+    int      fSplitPrime;          // represent prime function as 1-step DSD
+    int      fWriteTruth;          // writing truth table as a hex string
+    int *    pVarLevels;           // variable levels
+    char     pVarDefs[32][8];      // variable definitions
+    char     Cache[32][32];        // variable cache
+    char     pOutput[DAU_MAX_STR]; // output stream
+};
+
+static abctime s_Times[3] = {0};
+
+/**Function*************************************************************
+
+  Synopsis    [Manipulation of DSD data-structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Dau_DsdInitialize( Dau_Dsd_t * p, int nVarsInit )
+{
+    int i, v, u;
+    assert( nVarsInit >= 0 && nVarsInit <= 16 );
+    p->nVarsInit   = nVarsInit;
+    p->nVarsUsed   = nVarsInit;
+    p->nPos        = 0;
+    p->nSizeNonDec = 0;
+    p->nConsts     = 0;
+    p->uConstMask  = 0;
+    for ( i = 0; i < nVarsInit; i++ )
+        p->pVarDefs[i][0] = 'a' + i, p->pVarDefs[i][1] = 0;
+    for ( v = 0; v < nVarsInit; v++ )
+    for ( u = 0; u < nVarsInit; u++ )
+        p->Cache[v][u] = 0;
+
+}
+static inline void Dau_DsdWriteString( Dau_Dsd_t * p, char * pStr )
+{
+    while ( *pStr )
+        p->pOutput[ p->nPos++ ] = *pStr++;
+}
+static inline void Dau_DsdWriteVar( Dau_Dsd_t * p, int iVar, int fInv )
+{
+    char * pStr;
+    if ( fInv )
+        p->pOutput[ p->nPos++ ] = '!';
+    for ( pStr = p->pVarDefs[iVar]; *pStr; pStr++ )
+        if ( *pStr >= 'a' + p->nVarsInit && *pStr < 'a' + p->nVarsUsed )
+            Dau_DsdWriteVar( p, *pStr - 'a', 0 );
+        else
+            p->pOutput[ p->nPos++ ] = *pStr;
+}
+int Dau_DsdLevelVar( void * pMan, int iVar )
+{
+    Dau_Dsd_t * p = (Dau_Dsd_t *)pMan;
+    char * pStr;
+    int LevelMax = 0, Level;
+    for ( pStr = p->pVarDefs[iVar]; *pStr; pStr++ )
+    {
+        if ( *pStr >= 'a' + p->nVarsInit && *pStr < 'a' + p->nVarsUsed )
+            Level = 1 + Dau_DsdLevelVar( p, *pStr - 'a' );
+        else
+            Level = p->pVarLevels[*pStr - 'a'];
+        LevelMax = Abc_MaxInt( LevelMax, Level );
+    }
+    return LevelMax;
+}
+static inline void Dau_DsdTranslate( Dau_Dsd_t * p, int * pVars, int nVars, char * pStr )
+{
+    for ( ; *pStr; pStr++ )
+        if ( *pStr >= 'a' && *pStr < 'a' + nVars )
+            Dau_DsdWriteVar( p, pVars[*pStr - 'a'], 0 );
+        else
+            p->pOutput[ p->nPos++ ] = *pStr;
+}
+static inline int Dau_DsdWritePrime( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars )
+{
+    int v, RetValue = 2;
+    assert( nVars > 2 );
+    if ( p->fSplitPrime )
+    {
+        word pCofTemp[DAU_MAX_WORD];
+        int nWords = Abc_TtWordNum(nVars);
+        int vBest = Dau_DsdCheck1Step( p, pTruth, nVars, p->pVarLevels );
+        assert( vBest != -1 );
+        if ( vBest == -2 ) // non-dec
+            p->nPos += Abc_TtWriteHexRev( p->pOutput + p->nPos, pTruth, nVars );
+        else 
+        {
+            char pRes[DAU_MAX_STR];
+            int nNonDecSize;
+            // compose the result
+            Dau_DsdWriteString( p, "<" );
+            Dau_DsdWriteVar( p, vBest, 0 );
+            // split decomposition
+            Abc_TtCofactor1p( pCofTemp, pTruth, nWords, vBest );
+            nNonDecSize = Dau_DsdDecompose( pCofTemp, nVars, 0, p->fWriteTruth, pRes );
+            assert( nNonDecSize == 0 );
+            Dau_DsdWriteString( p, pRes );
+            // split decomposition
+            Abc_TtCofactor0p( pCofTemp, pTruth, nWords, vBest );
+            nNonDecSize = Dau_DsdDecompose( pCofTemp, nVars, 0, p->fWriteTruth, pRes );
+            assert( nNonDecSize == 0 );
+            Dau_DsdWriteString( p, pRes );
+            Dau_DsdWriteString( p, ">" );
+            RetValue = 1;
+        }
+    }
+    else if ( p->fWriteTruth )
+        p->nPos += Abc_TtWriteHexRev( p->pOutput + p->nPos, pTruth, nVars );
+    Dau_DsdWriteString( p, "{" );
+    for ( v = 0; v < nVars; v++ )
+        Dau_DsdWriteVar( p, pVars[v], 0 );
+    Dau_DsdWriteString( p, "}" );
+    p->nSizeNonDec = nVars;
+    return RetValue;
+}
+static inline void Dau_DsdFinalize( Dau_Dsd_t * p )
+{
+    int i;
+    for ( i = 0; i < p->nConsts; i++ )
+        p->pOutput[ p->nPos++ ] = ((p->uConstMask >> (p->nConsts-1-i)) & 1) ? ']' : ')';
+    p->pOutput[ p->nPos++ ] = 0;
+}
+static inline int Dau_DsdAddVarDef( Dau_Dsd_t * p, char * pStr )
+{
+    int u;
+    assert( strlen(pStr) < 8 );
+    assert( p->nVarsUsed < 32 );
+    for ( u = 0; u < p->nVarsUsed; u++ )
+        p->Cache[p->nVarsUsed][u] = 0;
+    for ( u = 0; u < p->nVarsUsed; u++ )
+        p->Cache[u][p->nVarsUsed] = 0;
+    sprintf( p->pVarDefs[p->nVarsUsed++], "%s", pStr );
+    return p->nVarsUsed - 1;
+}
+static inline int Dau_DsdFindVarDef( int * pVars, int nVars, int VarDef )
+{
+    int v;
+    for ( v = 0; v < nVars; v++ )
+        if ( pVars[v] == VarDef )
+            break;
+    assert( v < nVars );
+    return v;
+}
+static inline void Dau_DsdInsertVarCache( Dau_Dsd_t * p, int v, int u, int Status )
+{
+    assert( v != u );
+    assert( Status > 0 && Status < 4 );
+    assert( p->Cache[v][u] == 0 );
+    p->Cache[v][u] = Status;
+}
+static inline int Dau_DsdLookupVarCache( Dau_Dsd_t * p, int v, int u )
+{
+    return p->Cache[v][u];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedures specialized for 6-variable functions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dau_Dsd6DecomposeSingleVarOne( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v )
+{
+    // consider negative cofactors
+    if ( pTruth[0] & 1 )
+    {        
+        if ( Abc_Tt6Cof0IsConst1( pTruth[0], v ) ) // !(ax)
+        {
+            Dau_DsdWriteString( p, "!(" );
+            pTruth[0] = ~Abc_Tt6Cofactor1( pTruth[0], v );
+            goto finish;            
+        }
+    }
+    else
+    {
+        if ( Abc_Tt6Cof0IsConst0( pTruth[0], v ) ) // ax
+        {
+            Dau_DsdWriteString( p, "(" );
+            pTruth[0] = Abc_Tt6Cofactor1( pTruth[0], v );
+            goto finish;            
+        }
+    }
+    // consider positive cofactors
+    if ( pTruth[0] >> 63 )
+    {        
+        if ( Abc_Tt6Cof1IsConst1( pTruth[0], v ) ) // !(!ax)
+        {
+            Dau_DsdWriteString( p, "!(!" );
+            pTruth[0] = ~Abc_Tt6Cofactor0( pTruth[0], v );
+            goto finish;            
+        }
+    }
+    else
+    {
+        if ( Abc_Tt6Cof1IsConst0( pTruth[0], v ) ) // !ax
+        {
+            Dau_DsdWriteString( p, "(!" );
+            pTruth[0] = Abc_Tt6Cofactor0( pTruth[0], v );
+            goto finish;            
+        }
+    }
+    // consider equal cofactors
+    if ( Abc_Tt6CofsOpposite( pTruth[0], v ) ) // [ax]
+    {
+        Dau_DsdWriteString( p, "[" );
+        pTruth[0] = Abc_Tt6Cofactor0( pTruth[0], v );
+        p->uConstMask |= (1 << p->nConsts);
+        goto finish;            
+    }
+    return 0;
+
+finish:
+    p->nConsts++;
+    Dau_DsdWriteVar( p, pVars[v], 0 );
+    pVars[v] = pVars[nVars-1];
+    Abc_TtSwapVars( pTruth, nVars, v, nVars-1 );
+    return 1;
+}
+int Dau_Dsd6DecomposeSingleVar( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars )
+{
+    abctime clk = Abc_Clock();
+    assert( nVars > 1 );
+    while ( 1 )
+    {
+        int v;
+        for ( v = nVars - 1; v >= 0 && nVars > 1; v-- )
+            if ( Dau_Dsd6DecomposeSingleVarOne( p, pTruth, pVars, nVars, v ) )
+            {
+                nVars--;
+                break;
+            }
+        if ( v == -1 || nVars == 1 )
+            break;
+    }
+    if ( nVars == 1 )
+        Dau_DsdWriteVar( p, pVars[--nVars], (int)(pTruth[0] & 1) );
+    s_Times[0] += Abc_Clock() - clk;
+    return nVars;
+}
+static inline int Dau_Dsd6FindSupportOne( Dau_Dsd_t * p, word tCof0, word tCof1, int * pVars, int nVars, int v, int u )
+{
+    int Status = p ? Dau_DsdLookupVarCache( p, pVars[v], pVars[u] ) : 0;
+    if ( Status == 0 )
+    {
+        Status = (Abc_Tt6HasVar(tCof1, u) << 1) | Abc_Tt6HasVar(tCof0, u);
+        if ( p )
+            Dau_DsdInsertVarCache( p, pVars[v], pVars[u], Status );
+    }
+    return Status;
+}
+static inline unsigned Dau_Dsd6FindSupports( Dau_Dsd_t * p, word  * pTruth, int * pVars, int nVars, int v )
+{
+    int u;
+    unsigned uSupports = 0;
+    word tCof0 = Abc_Tt6Cofactor0( pTruth[0], v );
+    word tCof1 = Abc_Tt6Cofactor1( pTruth[0], v );
+//Kit_DsdPrintFromTruth( (unsigned *)&tCof0, 6 );printf( "\n" );
+//Kit_DsdPrintFromTruth( (unsigned *)&tCof1, 6 );printf( "\n" );
+    for ( u = 0; u < nVars; u++ )
+        if ( u != v )
+            uSupports |= (Dau_Dsd6FindSupportOne( p, tCof0, tCof1, pVars, nVars, v, u ) << (2 * u));
+    return uSupports;
+}
+static inline void Dau_DsdPrintSupports( unsigned uSupp, int nVars )
+{
+    int v, Value;
+    printf( "Cofactor supports: " );
+    for ( v = nVars - 1; v >= 0; v-- )
+    {
+        Value = ((uSupp >> (2*v)) & 3);
+        if ( Value == 1 )
+            printf( "01" );
+        else if ( Value == 2 )
+            printf( "10" );
+        else if ( Value == 3 )
+            printf( "11" );
+        else 
+            printf( "00" );
+        if ( v )
+            printf( "-" );
+    }
+    printf( "\n" );
+}
+// checks decomposability with respect to the pair (v, u)
+static inline int Dau_Dsd6DecomposeDoubleVarsOne( Dau_Dsd_t * p, word  * pTruth, int * pVars, int nVars, int v, int u )
+{
+    char pBuffer[10] = { 0 }; 
+    word tCof0 = Abc_Tt6Cofactor0( pTruth[0], v );
+    word tCof1 = Abc_Tt6Cofactor1( pTruth[0], v );
+    int Status = Dau_Dsd6FindSupportOne( p, tCof0, tCof1, pVars, nVars, v, u );
+    assert( v > u );
+//printf( "Checking %s and %s.\n", p->pVarDefs[pVars[v]], p->pVarDefs[pVars[u]] );
+
+//    Kit_DsdPrintFromTruth( (unsigned *)pTruth, 6 );printf( "\n" );
+    if ( Status == 3 )
+    {
+        // both F(v=0) and F(v=1) depend on u
+        if ( Abc_Tt6Cof0EqualCof1(tCof0, tCof1, u) && Abc_Tt6Cof0EqualCof1(tCof1, tCof0, u) ) // v+u
+        {
+            pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor1(tCof0, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u));
+            sprintf( pBuffer, "[%c%c]", 'a' + pVars[v], 'a' + pVars[u] );
+            goto finish;
+        }
+    }
+    else if ( Status == 2 )
+    {
+        // F(v=0) does not depend on u; F(v=1) depends on u
+        if ( Abc_Tt6Cof0EqualCof0(tCof0, tCof1, u) ) // vu
+        {
+            sprintf( pBuffer, "(%c%c)", 'a' + pVars[v], 'a' + pVars[u] );
+            pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor1(tCof1, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u));
+            goto finish;
+        }
+        if ( Abc_Tt6Cof0EqualCof1(tCof0, tCof1, u) ) // v!u
+        {
+            sprintf( pBuffer, "(%c!%c)", 'a' + pVars[v], 'a' + pVars[u] );
+            pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor0(tCof1, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u));
+            goto finish;
+        }
+    }
+    else if ( Status == 1 )
+    {
+        // F(v=0) depends on u; F(v=1) does not depend on u
+        if ( Abc_Tt6Cof0EqualCof1(tCof0, tCof1, u) ) // !vu
+        {
+            sprintf( pBuffer, "(!%c%c)", 'a' + pVars[v], 'a' + pVars[u] );
+            pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor1(tCof0, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u));
+            goto finish;
+        }
+        if ( Abc_Tt6Cof1EqualCof1(tCof0, tCof1, u) ) // !v!u
+        {
+            sprintf( pBuffer, "(!%c!%c)", 'a' + pVars[v], 'a' + pVars[u] );
+            pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor1(tCof1, u));
+            goto finish;
+        }
+    }
+    return nVars;
+finish: 
+    // finalize decomposition
+    assert( pBuffer[0] );
+    pVars[u] = Dau_DsdAddVarDef( p, pBuffer );
+    pVars[v] = pVars[nVars-1];
+    Abc_TtSwapVars( pTruth, nVars, v, nVars-1 );
+    if ( Dau_Dsd6DecomposeSingleVarOne( p, pTruth, pVars, --nVars, u ) )
+        nVars = Dau_Dsd6DecomposeSingleVar( p, pTruth, pVars, --nVars );
+    return nVars;
+}
+int Dau_Dsd6DecomposeDoubleVars( Dau_Dsd_t * p, word  * pTruth, int * pVars, int nVars )
+{
+    abctime clk = Abc_Clock();
+    while ( 1 )
+    {
+        int v, u, nVarsOld;
+        for ( v = nVars - 1; v > 0; v-- )
+        {
+            for ( u = v - 1; u >= 0; u-- )
+            {
+                if ( Dau_DsdLookupVarCache( p, pVars[v], pVars[u] ) )
+                    continue;
+                nVarsOld = nVars;
+                nVars = Dau_Dsd6DecomposeDoubleVarsOne( p, pTruth, pVars, nVars, v, u );
+                if ( nVars == 0 )
+                {
+                    s_Times[1] += Abc_Clock() - clk;
+                    return 0;
+                }
+                if ( nVarsOld > nVars )
+                    break;
+            }
+            if ( u >= 0 ) // found
+                break;
+        }
+        if ( v == 0 ) // not found
+            break;
+    }
+    s_Times[1] += Abc_Clock() - clk;
+    return nVars;
+}
+
+// look for MUX-decomposable variable on top or at the bottom
+static inline int Dau_Dsd6DecomposeTripleVarsOuter( Dau_Dsd_t * p, word  * pTruth, int * pVars, int nVars, int v )
+{
+    extern int Dau_DsdDecomposeInt( Dau_Dsd_t * p, word * pTruth, int nVarsInit );
+    Dau_Dsd_t P1, * p1 = &P1;
+    word tCof0, tCof1;
+    p1->fSplitPrime = 0;
+    p1->fWriteTruth = p->fWriteTruth;
+    // move this variable to the top
+    ABC_SWAP( int, pVars[v], pVars[nVars-1] );
+    Abc_TtSwapVars( pTruth, nVars, v, nVars-1 );
+    // cofactor w.r.t the last variable
+    tCof0 = Abc_Tt6Cofactor0( pTruth[0], nVars - 1 );
+    tCof1 = Abc_Tt6Cofactor1( pTruth[0], nVars - 1 );
+    // compose the result
+    Dau_DsdWriteString( p, "<" );
+    Dau_DsdWriteVar( p, pVars[nVars - 1], 0 );
+    // split decomposition
+    Dau_DsdDecomposeInt( p1, &tCof1, nVars - 1 );
+    Dau_DsdTranslate( p, pVars, nVars - 1, p1->pOutput );
+    p->nSizeNonDec = p1->nSizeNonDec;
+    if ( p1->nSizeNonDec )
+        *pTruth = tCof1;
+    // split decomposition
+    Dau_DsdDecomposeInt( p1, &tCof0, nVars - 1 );
+    Dau_DsdTranslate( p, pVars, nVars - 1, p1->pOutput );
+    Dau_DsdWriteString( p, ">" );
+    p->nSizeNonDec = Abc_MaxInt( p->nSizeNonDec, p1->nSizeNonDec );
+    if ( p1->nSizeNonDec )
+        *pTruth = tCof0;
+    return 0;
+}
+static inline int Dau_Dsd6DecomposeTripleVarsInner( Dau_Dsd_t * p, word  * pTruth, int * pVars, int nVars, int v, unsigned uSupports )
+{
+    int iVar0 = Abc_TtSuppFindFirst(  uSupports & (~uSupports >> 1) & 0x55555555 ) >> 1;
+    int iVar1 = Abc_TtSuppFindFirst( ~uSupports & ( uSupports >> 1) & 0x55555555 ) >> 1;
+    word tCof0 = Abc_Tt6Cofactor0( pTruth[0], v );
+    word tCof1 = Abc_Tt6Cofactor1( pTruth[0], v );
+    word C00 = Abc_Tt6Cofactor0( tCof0, iVar0 );
+    word C01 = Abc_Tt6Cofactor1( tCof0, iVar0 );
+    word C10 = Abc_Tt6Cofactor0( tCof1, iVar1 );
+    word C11 = Abc_Tt6Cofactor1( tCof1, iVar1 );
+    int fEqual0 = (C00 == C10) && (C01 == C11);
+    int fEqual1 = (C00 == C11) && (C01 == C10);
+    if ( fEqual0 || fEqual1 )
+    {
+        char pBuffer[10];
+        int VarId = pVars[iVar0];
+        pTruth[0] = (s_Truths6[v] & C11) | (~s_Truths6[v] & C10);
+        sprintf( pBuffer, "<%c%c%s%c>", 'a' + pVars[v], 'a' + pVars[iVar1], fEqual1 ? "!":"", 'a' + pVars[iVar0] );
+        pVars[v] = Dau_DsdAddVarDef( p, pBuffer );
+        // remove iVar1
+        ABC_SWAP( int, pVars[iVar1], pVars[nVars-1] );
+        Abc_TtSwapVars( pTruth, nVars, iVar1, nVars-1 ); nVars--;
+        // remove iVar0
+        iVar0 = Dau_DsdFindVarDef( pVars, nVars, VarId );
+        ABC_SWAP( int, pVars[iVar0], pVars[nVars-1] );
+        Abc_TtSwapVars( pTruth, nVars, iVar0, nVars-1 ); nVars--;
+        // find the new var
+        v = Dau_DsdFindVarDef( pVars, nVars, p->nVarsUsed-1 );
+        // remove single variables if possible
+        if ( Dau_Dsd6DecomposeSingleVarOne( p, pTruth, pVars, nVars, v ) )
+            nVars = Dau_Dsd6DecomposeSingleVar( p, pTruth, pVars, --nVars );
+        return nVars;
+    }
+    return nVars;
+}
+int Dau_Dsd6DecomposeTripleVars( Dau_Dsd_t * p, word  * pTruth, int * pVars, int nVars )
+{
+    abctime clk = Abc_Clock();
+    while ( 1 )
+    {
+        int v;
+//        Kit_DsdPrintFromTruth( (unsigned *)pTruth, 6 ); printf( "\n" );
+        for ( v = nVars - 1; v >= 0; v-- )
+        {
+            unsigned uSupports = Dau_Dsd6FindSupports( p, pTruth, pVars, nVars, v );
+//            Dau_DsdPrintSupports( uSupports, nVars );
+            if ( (uSupports & (uSupports >> 1) & 0x55555555) == 0 ) // non-overlapping supports
+                return Dau_Dsd6DecomposeTripleVarsOuter( p, pTruth, pVars, nVars, v );
+            if ( Abc_TtSuppOnlyOne( uSupports & (~uSupports >> 1) & 0x55555555) &&
+                 Abc_TtSuppOnlyOne(~uSupports & ( uSupports >> 1) & 0x55555555) ) // one unique variable in each cofactor
+            {
+                int nVarsNew = Dau_Dsd6DecomposeTripleVarsInner( p, pTruth, pVars, nVars, v, uSupports );
+                if ( nVarsNew == nVars )
+                    continue;
+                if ( nVarsNew == 0 )
+                {
+                    s_Times[2] += Abc_Clock() - clk;
+                    return 0;
+                }
+                nVars = Dau_Dsd6DecomposeDoubleVars( p, pTruth, pVars, nVarsNew );
+                if ( nVars == 0 )
+                {
+                    s_Times[2] += Abc_Clock() - clk;
+                    return 0;
+                }
+                break;
+            }
+        }
+        if ( v == -1 )
+        {
+            s_Times[2] += Abc_Clock() - clk;
+            return nVars;
+        }
+    }
+    assert( 0 );
+    return -1;
+}
+int Dau_Dsd6DecomposeInternal( Dau_Dsd_t * p, word  * pTruth, int * pVars, int nVars )
+{
+    // decompose single variales on the output side
+    nVars = Dau_Dsd6DecomposeSingleVar( p, pTruth, pVars, nVars );
+    if ( nVars == 0 )
+        return 0;
+    // decompose double variables on the input side
+    nVars = Dau_Dsd6DecomposeDoubleVars( p, pTruth, pVars, nVars );
+    if ( nVars == 0 )
+        return 0;
+    // decompose MUX on the output/input side
+    nVars = Dau_Dsd6DecomposeTripleVars( p, pTruth, pVars, nVars );
+    if ( nVars == 0 )
+        return 0;
+    // write non-decomposable function
+    return Dau_DsdWritePrime( p, pTruth, pVars, nVars );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedures specialized for 6-variable functions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dau_DsdDecomposeSingleVarOne( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v )
+{
+    int nWords = Abc_TtWordNum(nVars);
+    // consider negative cofactors
+    if ( pTruth[0] & 1 )
+    {        
+        if ( Abc_TtCof0IsConst1( pTruth, nWords, v ) ) // !(ax)
+        {
+            Dau_DsdWriteString( p, "!(" );
+            Abc_TtCofactor1( pTruth, nWords, v );
+            Abc_TtNot( pTruth, nWords );
+            goto finish;            
+        }
+    }
+    else
+    {
+        if ( Abc_TtCof0IsConst0( pTruth, nWords, v ) ) // ax
+        {
+            Dau_DsdWriteString( p, "(" );
+            Abc_TtCofactor1( pTruth, nWords, v );
+            goto finish;            
+        }
+    }
+    // consider positive cofactors
+    if ( pTruth[nWords-1] >> 63 )
+    {        
+        if ( Abc_TtCof1IsConst1( pTruth, nWords, v ) ) // !(!ax)
+        {
+            Dau_DsdWriteString( p, "!(!" );
+            Abc_TtCofactor0( pTruth, nWords, v );
+            Abc_TtNot( pTruth, nWords );
+            goto finish;            
+        }
+    }
+    else
+    {
+        if ( Abc_TtCof1IsConst0( pTruth, nWords, v ) ) // !ax
+        {
+            Dau_DsdWriteString( p, "(!" );
+            Abc_TtCofactor0( pTruth, nWords, v );
+            goto finish;            
+        }
+    }
+    // consider equal cofactors
+    if ( Abc_TtCofsOpposite( pTruth, nWords, v ) ) // [ax]
+    {
+        Dau_DsdWriteString( p, "[" );
+        Abc_TtCofactor0( pTruth, nWords, v );
+        p->uConstMask |= (1 << p->nConsts);
+        goto finish;            
+    }
+    return 0;
+
+finish:
+    p->nConsts++;
+    Dau_DsdWriteVar( p, pVars[v], 0 );
+    pVars[v] = pVars[nVars-1];
+    Abc_TtSwapVars( pTruth, nVars, v, nVars-1 );
+    return 1;
+}
+int Dau_DsdDecomposeSingleVar( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars )
+{
+    abctime clk = Abc_Clock();
+    assert( nVars > 1 );
+    while ( 1 )
+    {
+        int v;
+        for ( v = nVars - 1; v >= 0 && nVars > 1; v-- )
+            if ( Dau_DsdDecomposeSingleVarOne( p, pTruth, pVars, nVars, v ) )
+            {
+                nVars--;
+                break;
+            }
+        if ( v == -1 || nVars == 1 )
+            break;
+    }
+    if ( nVars == 1 )
+        Dau_DsdWriteVar( p, pVars[--nVars], (int)(pTruth[0] & 1) );
+    s_Times[0] += Abc_Clock() - clk;
+    return nVars;
+}
+
+static inline int Dau_DsdFindSupportOne( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v, int u )
+{
+    int nWords = Abc_TtWordNum(nVars);
+    int Status = p ? Dau_DsdLookupVarCache( p, pVars[v], pVars[u] ) : 0;
+    if ( Status == 0 )
+    {
+//        Status = (Abc_Tt6HasVar(tCof1, u) << 1) | Abc_Tt6HasVar(tCof0, u);
+        if ( v < u )
+            Status = (!Abc_TtCheckEqualCofs(pTruth, nWords, v, u, 1, 3) << 1) | !Abc_TtCheckEqualCofs(pTruth, nWords, v, u, 0, 2);
+        else // if ( v > u )
+            Status = (!Abc_TtCheckEqualCofs(pTruth, nWords, u, v, 2, 3) << 1) | !Abc_TtCheckEqualCofs(pTruth, nWords, u, v, 0, 1);
+        assert( Status != 0 );
+        if ( p )
+            Dau_DsdInsertVarCache( p, pVars[v], pVars[u], Status );
+    }
+    return Status;
+}
+static inline unsigned Dau_DsdFindSupports( Dau_Dsd_t * p, word  * pTruth, int * pVars, int nVars, int v )
+{
+    int u;
+    unsigned uSupports = 0;
+//Kit_DsdPrintFromTruth( (unsigned *)&tCof0, 6 );printf( "\n" );
+//Kit_DsdPrintFromTruth( (unsigned *)&tCof1, 6 );printf( "\n" );
+    for ( u = 0; u < nVars; u++ )
+        if ( u != v )
+            uSupports |= (Dau_DsdFindSupportOne( p, pTruth, pVars, nVars, v, u ) << (2 * u));
+    return uSupports;
+}
+
+// checks decomposability with respect to the pair (v, u)
+static inline int Dau_DsdDecomposeDoubleVarsOne( Dau_Dsd_t * p, word  * pTruth, int * pVars, int nVars, int v, int u )
+{
+    char pBuffer[10] = { 0 }; 
+    int nWords = Abc_TtWordNum(nVars);
+    int Status = Dau_DsdFindSupportOne( p, pTruth, pVars, nVars, v, u );
+    assert( v > u );
+//printf( "Checking %s and %s.\n", p->pVarDefs[pVars[v]], p->pVarDefs[pVars[u]] );
+    if ( Status == 3 )
+    {
+        // both F(v=0) and F(v=1) depend on u
+//        if ( Abc_Tt6Cof0EqualCof1(tCof0, tCof1, u) && Abc_Tt6Cof0EqualCof1(tCof1, tCof0, u) ) // v+u
+        if ( Abc_TtCheckEqualCofs(pTruth, nWords, u, v, 0, 3) && Abc_TtCheckEqualCofs(pTruth, nWords, u, v, 1, 2) ) // 00=11 01=10 v+u
+        {
+            word pTtTemp[2][DAU_MAX_WORD];
+            sprintf( pBuffer, "[%c%c]", 'a' + pVars[v], 'a' + pVars[u] );
+//            pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor1(tCof0, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u));
+            Abc_TtCofactor0p( pTtTemp[0], pTruth, nWords, v );
+            Abc_TtCofactor0( pTtTemp[0], nWords, u );
+            Abc_TtCofactor0p( pTtTemp[1], pTruth, nWords, v );
+            Abc_TtCofactor1( pTtTemp[1], nWords, u );
+            Abc_TtMux( pTruth, Dau_DsdTtElems()[u], pTtTemp[1], pTtTemp[0], nWords );
+            goto finish;
+        }
+    }
+    else if ( Status == 2 )
+    {
+        // F(v=0) does not depend on u; F(v=1) depends on u
+//        if ( Abc_Tt6Cof0EqualCof0(tCof0, tCof1, u) ) // vu
+        if ( Abc_TtCheckEqualCofs(pTruth, nWords, u, v, 0, 2) ) // 00=10 vu
+        {
+            word pTtTemp[2][DAU_MAX_WORD];
+            sprintf( pBuffer, "(%c%c)", 'a' + pVars[v], 'a' + pVars[u] );
+//            pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor1(tCof1, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u));
+            Abc_TtCofactor0p( pTtTemp[0], pTruth, nWords, v );
+            Abc_TtCofactor0( pTtTemp[0], nWords, u );
+            Abc_TtCofactor1p( pTtTemp[1], pTruth, nWords, v );
+            Abc_TtCofactor1( pTtTemp[1], nWords, u );
+            Abc_TtMux( pTruth, Dau_DsdTtElems()[u], pTtTemp[1], pTtTemp[0], nWords );
+            goto finish;
+        }
+//        if ( Abc_Tt6Cof0EqualCof1(tCof0, tCof1, u) ) // v!u
+        if ( Abc_TtCheckEqualCofs(pTruth, nWords, u, v, 0, 3) ) // 00=11 v!u
+        {
+            word pTtTemp[2][DAU_MAX_WORD];
+            sprintf( pBuffer, "(%c!%c)", 'a' + pVars[v], 'a' + pVars[u] );
+//            pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor0(tCof1, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u));
+            Abc_TtCofactor0p( pTtTemp[0], pTruth, nWords, v );
+            Abc_TtCofactor0( pTtTemp[0], nWords, u );
+            Abc_TtCofactor1p( pTtTemp[1], pTruth, nWords, v );
+            Abc_TtCofactor0( pTtTemp[1], nWords, u );
+            Abc_TtMux( pTruth, Dau_DsdTtElems()[u], pTtTemp[1], pTtTemp[0], nWords );
+            goto finish;
+        }
+    }
+    else if ( Status == 1 )
+    {
+        // F(v=0) depends on u; F(v=1) does not depend on u
+//        if ( Abc_Tt6Cof0EqualCof1(tCof0, tCof1, u) ) // !vu
+        if ( Abc_TtCheckEqualCofs(pTruth, nWords, u, v, 0, 3) ) // 00=11 !vu
+        {
+            word pTtTemp[2][DAU_MAX_WORD];
+            sprintf( pBuffer, "(!%c%c)", 'a' + pVars[v], 'a' + pVars[u] );
+//            pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor1(tCof0, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u));
+            Abc_TtCofactor0p( pTtTemp[0], pTruth, nWords, v );
+            Abc_TtCofactor0( pTtTemp[0], nWords, u );
+            Abc_TtCofactor0p( pTtTemp[1], pTruth, nWords, v );
+            Abc_TtCofactor1( pTtTemp[1], nWords, u );
+            Abc_TtMux( pTruth, Dau_DsdTtElems()[u], pTtTemp[1], pTtTemp[0], nWords );
+            goto finish;
+        }
+//        if ( Abc_Tt6Cof1EqualCof1(tCof0, tCof1, u) ) // !v!u
+        if ( Abc_TtCheckEqualCofs(pTruth, nWords, u, v, 1, 3) ) // 01=11 !v!u
+        {
+            word pTtTemp[2][DAU_MAX_WORD];
+            sprintf( pBuffer, "(!%c!%c)", 'a' + pVars[v], 'a' + pVars[u] );
+//            pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor1(tCof1, u));
+            Abc_TtCofactor1p( pTtTemp[0], pTruth, nWords, v );
+            Abc_TtCofactor1( pTtTemp[0], nWords, u );
+            Abc_TtCofactor0p( pTtTemp[1], pTruth, nWords, v );
+            Abc_TtCofactor0( pTtTemp[1], nWords, u );
+            Abc_TtMux( pTruth, Dau_DsdTtElems()[u], pTtTemp[1], pTtTemp[0], nWords );
+            goto finish;
+        }
+    }
+    return nVars;
+finish: 
+    // finalize decomposition
+    assert( pBuffer[0] );
+    pVars[u] = Dau_DsdAddVarDef( p, pBuffer );
+    pVars[v] = pVars[nVars-1];
+    Abc_TtSwapVars( pTruth, nVars, v, nVars-1 );
+    if ( Dau_DsdDecomposeSingleVarOne( p, pTruth, pVars, --nVars, u ) )
+        nVars = Dau_DsdDecomposeSingleVar( p, pTruth, pVars, --nVars );
+    return nVars;
+}
+int Dau_DsdDecomposeDoubleVars( Dau_Dsd_t * p, word  * pTruth, int * pVars, int nVars )
+{
+    abctime clk = Abc_Clock();
+    while ( 1 )
+    {
+        int v, u, nVarsOld;
+        for ( v = nVars - 1; v > 0; v-- )
+        {
+            for ( u = v - 1; u >= 0; u-- )
+            {
+                if ( Dau_DsdLookupVarCache( p, pVars[v], pVars[u] ) )
+                    continue;
+                nVarsOld = nVars;
+                nVars = Dau_DsdDecomposeDoubleVarsOne( p, pTruth, pVars, nVars, v, u );
+                if ( nVars == 0 )
+                {
+                    s_Times[1] += Abc_Clock() - clk;
+                    return 0;
+                }
+                if ( nVarsOld > nVars )
+                    break;
+            }
+            if ( u >= 0 ) // found
+                break;
+        }
+        if ( v == 0 ) // not found
+            break;
+    }
+    s_Times[1] += Abc_Clock() - clk;
+    return nVars;
+}
+
+// look for MUX-decomposable variable on top or at the bottom
+static inline int Dau_DsdDecomposeTripleVarsOuter( Dau_Dsd_t * p, word  * pTruth, int * pVars, int nVars, int v )
+{
+    extern int Dau_DsdDecomposeInt( Dau_Dsd_t * p, word * pTruth, int nVarsInit );
+    Dau_Dsd_t P1, * p1 = &P1;
+    word pTtCof[2][DAU_MAX_WORD];
+    int nWords = Abc_TtWordNum(nVars);
+    p1->fSplitPrime = 0;
+    p1->fWriteTruth = p->fWriteTruth;
+    // move this variable to the top
+    ABC_SWAP( int, pVars[v], pVars[nVars-1] );
+    Abc_TtSwapVars( pTruth, nVars, v, nVars-1 );
+    // cofactor w.r.t the last variable
+//    tCof0 = Abc_Tt6Cofactor0( pTruth[0], nVars - 1 );
+//    tCof1 = Abc_Tt6Cofactor1( pTruth[0], nVars - 1 );
+    Abc_TtCofactor0p( pTtCof[0], pTruth, nWords, nVars - 1 );
+    Abc_TtCofactor1p( pTtCof[1], pTruth, nWords, nVars - 1 );
+    // compose the result
+    Dau_DsdWriteString( p, "<" );
+    Dau_DsdWriteVar( p, pVars[nVars - 1], 0 );
+    // split decomposition
+    Dau_DsdDecomposeInt( p1, pTtCof[1], nVars - 1 );
+    Dau_DsdTranslate( p, pVars, nVars - 1, p1->pOutput );
+    p->nSizeNonDec = p1->nSizeNonDec;
+    if ( p1->nSizeNonDec )
+        Abc_TtCopy( pTruth, pTtCof[1], Abc_TtWordNum(p1->nSizeNonDec), 0 );
+    // split decomposition
+    Dau_DsdDecomposeInt( p1, pTtCof[0], nVars - 1 );
+    Dau_DsdTranslate( p, pVars, nVars - 1, p1->pOutput );
+    Dau_DsdWriteString( p, ">" );
+    p->nSizeNonDec = Abc_MaxInt( p->nSizeNonDec, p1->nSizeNonDec );
+    if ( p1->nSizeNonDec )
+        Abc_TtCopy( pTruth, pTtCof[0], Abc_TtWordNum(p1->nSizeNonDec), 0 );
+    return 0;
+}
+static inline int Dau_DsdDecomposeTripleVarsInner( Dau_Dsd_t * p, word  * pTruth, int * pVars, int nVars, int v, unsigned uSupports )
+{
+    int nWords = Abc_TtWordNum(nVars);
+    int iVar0 = Abc_TtSuppFindFirst(  uSupports & (~uSupports >> 1) & 0x55555555 ) >> 1;
+    int iVar1 = Abc_TtSuppFindFirst( ~uSupports & ( uSupports >> 1) & 0x55555555 ) >> 1;
+    int fEqual0, fEqual1;
+//    word tCof0 = Abc_Tt6Cofactor0( pTruth[0], v );
+//    word tCof1 = Abc_Tt6Cofactor1( pTruth[0], v );
+//    word C00 = Abc_Tt6Cofactor0( tCof0, iVar0 );
+//    word C01 = Abc_Tt6Cofactor1( tCof0, iVar0 );
+//    word C10 = Abc_Tt6Cofactor0( tCof1, iVar1 );
+//    word C11 = Abc_Tt6Cofactor1( tCof1, iVar1 );
+//    int fEqual0 = (C00 == C10) && (C01 == C11);
+//    int fEqual1 = (C00 == C11) && (C01 == C10);
+    word pTtCof[2][DAU_MAX_WORD];
+    word pTtFour[2][2][DAU_MAX_WORD];
+    Abc_TtCofactor0p( pTtCof[0], pTruth, nWords, v );
+    Abc_TtCofactor1p( pTtCof[1], pTruth, nWords, v );
+    Abc_TtCofactor0p( pTtFour[0][0], pTtCof[0], nWords, iVar0 );
+    Abc_TtCofactor1p( pTtFour[0][1], pTtCof[0], nWords, iVar0 );
+    Abc_TtCofactor0p( pTtFour[1][0], pTtCof[1], nWords, iVar1 );
+    Abc_TtCofactor1p( pTtFour[1][1], pTtCof[1], nWords, iVar1 );
+    fEqual0 = Abc_TtEqual(pTtFour[0][0], pTtFour[1][0], nWords) && Abc_TtEqual(pTtFour[0][1], pTtFour[1][1], nWords);
+    fEqual1 = Abc_TtEqual(pTtFour[0][0], pTtFour[1][1], nWords) && Abc_TtEqual(pTtFour[0][1], pTtFour[1][0], nWords);
+    if ( fEqual0 || fEqual1 )
+    {
+        char pBuffer[10];
+        int VarId = pVars[iVar0];
+//        pTruth[0] = (s_Truths6[v] & C11) | (~s_Truths6[v] & C10);
+        Abc_TtMux( pTruth, Dau_DsdTtElems()[v], pTtFour[1][1], pTtFour[1][0], nWords );
+        sprintf( pBuffer, "<%c%c%s%c>", 'a' + pVars[v], 'a' + pVars[iVar1], fEqual1 ? "!":"", 'a' + pVars[iVar0] );
+        pVars[v] = Dau_DsdAddVarDef( p, pBuffer );
+        // remove iVar1
+        ABC_SWAP( int, pVars[iVar1], pVars[nVars-1] );
+        Abc_TtSwapVars( pTruth, nVars, iVar1, nVars-1 ); nVars--;
+        // remove iVar0
+        iVar0 = Dau_DsdFindVarDef( pVars, nVars, VarId );
+        ABC_SWAP( int, pVars[iVar0], pVars[nVars-1] );
+        Abc_TtSwapVars( pTruth, nVars, iVar0, nVars-1 ); nVars--;
+        // find the new var
+        v = Dau_DsdFindVarDef( pVars, nVars, p->nVarsUsed-1 );
+        // remove single variables if possible
+        if ( Dau_DsdDecomposeSingleVarOne( p, pTruth, pVars, nVars, v ) )
+            nVars = Dau_DsdDecomposeSingleVar( p, pTruth, pVars, --nVars );
+        return nVars;
+    }
+    return nVars;
+}
+int Dau_DsdDecomposeTripleVars( Dau_Dsd_t * p, word  * pTruth, int * pVars, int nVars )
+{
+    abctime clk = Abc_Clock();
+    while ( 1 )
+    {
+        int v;
+//        Kit_DsdPrintFromTruth( (unsigned *)pTruth, 6 ); printf( "\n" );
+        for ( v = nVars - 1; v >= 0; v-- )
+        {
+            unsigned uSupports = Dau_DsdFindSupports( p, pTruth, pVars, nVars, v );
+//            Dau_DsdPrintSupports( uSupports, nVars );
+            if ( (uSupports & (uSupports >> 1) & 0x55555555) == 0 ) // non-overlapping supports
+                return Dau_DsdDecomposeTripleVarsOuter( p, pTruth, pVars, nVars, v );
+            if ( Abc_TtSuppOnlyOne( uSupports & (~uSupports >> 1) & 0x55555555) &&
+                 Abc_TtSuppOnlyOne(~uSupports & ( uSupports >> 1) & 0x55555555) ) // one unique variable in each cofactor
+            {
+                int nVarsNew = Dau_DsdDecomposeTripleVarsInner( p, pTruth, pVars, nVars, v, uSupports );
+                if ( nVarsNew == nVars )
+                    continue;
+                if ( nVarsNew == 0 )
+                {
+                    s_Times[2] += Abc_Clock() - clk;
+                    return 0;
+                }
+                nVars = Dau_DsdDecomposeDoubleVars( p, pTruth, pVars, nVarsNew );
+                if ( nVars == 0 )
+                {
+                    s_Times[2] += Abc_Clock() - clk;
+                    return 0;
+                }
+                break;
+            }
+        }
+        if ( v == -1 )
+        {
+            s_Times[2] += Abc_Clock() - clk;
+            return nVars;
+        }
+    }
+    assert( 0 );
+    return -1;
+}
+int Dau_DsdDecomposeInternal( Dau_Dsd_t * p, word  * pTruth, int * pVars, int nVars )
+{
+    // decompose single variales on the output side
+    nVars = Dau_DsdDecomposeSingleVar( p, pTruth, pVars, nVars );
+    if ( nVars == 0 )
+        return 0;
+    // decompose double variables on the input side
+    nVars = Dau_DsdDecomposeDoubleVars( p, pTruth, pVars, nVars );
+    if ( nVars == 0 )
+        return 0;
+    // decompose MUX on the output/input side
+    nVars = Dau_DsdDecomposeTripleVars( p, pTruth, pVars, nVars );
+    if ( nVars == 0 )
+        return 0;
+    // write non-decomposable function
+    return Dau_DsdWritePrime( p, pTruth, pVars, nVars );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fast DSD for truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dau_DsdMinBase( word * pTruth, int nVars, int * pVarsNew )
+{
+    int v;
+    for ( v = 0; v < nVars; v++ )
+        pVarsNew[v] = v;
+    for ( v = nVars - 1; v >= 0; v-- )
+    {
+        if ( Abc_TtHasVar( pTruth, nVars, v ) )
+            continue;
+        Abc_TtSwapVars( pTruth, nVars, v, nVars-1 );
+        pVarsNew[v] = pVarsNew[--nVars];
+    }
+    return nVars;
+}
+int Dau_DsdDecomposeInt( Dau_Dsd_t * p, word * pTruth, int nVarsInit )
+{
+    int Status = 0, nVars, pVars[16];
+    Dau_DsdInitialize( p, nVarsInit );
+    nVars = Dau_DsdMinBase( pTruth, nVarsInit, pVars );
+    assert( nVars > 0 && nVars <= nVarsInit );
+    if ( nVars == 1 )
+        Dau_DsdWriteVar( p, pVars[0], (int)(pTruth[0] & 1) );
+    else if ( nVars <= 6 )
+        Status = Dau_Dsd6DecomposeInternal( p, pTruth, pVars, nVars );
+    else
+        Status = Dau_DsdDecomposeInternal( p, pTruth, pVars, nVars );
+    Dau_DsdFinalize( p );
+    return Status;
+}
+int Dau_DsdDecompose( word * pTruth, int nVarsInit, int fSplitPrime, int fWriteTruth, char * pRes )
+{
+    Dau_Dsd_t P, * p = &P;
+    p->fSplitPrime = fSplitPrime;
+    p->fWriteTruth = fWriteTruth;
+    p->pVarLevels  = NULL;
+    p->nSizeNonDec = 0;
+    if ( (pTruth[0] & 1) == 0 && Abc_TtIsConst0(pTruth, Abc_TtWordNum(nVarsInit)) )
+        { if ( pRes ) pRes[0] = '0', pRes[1] = 0; }
+    else if ( (pTruth[0] & 1) && Abc_TtIsConst1(pTruth, Abc_TtWordNum(nVarsInit)) )
+        { if ( pRes ) pRes[0] = '1', pRes[1] = 0; }
+    else 
+    {
+        int Status = Dau_DsdDecomposeInt( p, pTruth, nVarsInit );
+        Dau_DsdRemoveBraces( p->pOutput, Dau_DsdComputeMatches(p->pOutput) );
+        if ( pRes )
+            strcpy( pRes, p->pOutput );
+        assert( fSplitPrime || Status != 1 );
+        if ( fSplitPrime && Status == 2 )
+            return -1;
+    }
+//    assert( p->nSizeNonDec == 0 );
+    return p->nSizeNonDec;
+}
+int Dau_DsdDecomposeLevel( word * pTruth, int nVarsInit, int fSplitPrime, int fWriteTruth, char * pRes, int * pVarLevels )
+{
+    Dau_Dsd_t P, * p = &P;
+    p->fSplitPrime = fSplitPrime;
+    p->fWriteTruth = fWriteTruth;
+    p->pVarLevels  = pVarLevels;
+    p->nSizeNonDec = 0;
+    if ( (pTruth[0] & 1) == 0 && Abc_TtIsConst0(pTruth, Abc_TtWordNum(nVarsInit)) )
+        { if ( pRes ) pRes[0] = '0', pRes[1] = 0; }
+    else if ( (pTruth[0] & 1) && Abc_TtIsConst1(pTruth, Abc_TtWordNum(nVarsInit)) )
+        { if ( pRes ) pRes[0] = '1', pRes[1] = 0; }
+    else 
+    {
+        int Status = Dau_DsdDecomposeInt( p, pTruth, nVarsInit );
+        Dau_DsdRemoveBraces( p->pOutput, Dau_DsdComputeMatches(p->pOutput) );
+        if ( pRes )
+            strcpy( pRes, p->pOutput );
+        assert( fSplitPrime || Status != 1 );
+        if ( fSplitPrime && Status == 2 )
+            return -1;
+    }
+//    assert( p->nSizeNonDec == 0 );
+    return p->nSizeNonDec;
+}
+void Dau_DsdPrintFromTruthFile( FILE * pFile, word * pTruth, int nVarsInit )
+{
+    char pRes[DAU_MAX_STR];
+    word pTemp[DAU_MAX_WORD];
+    Abc_TtCopy( pTemp, pTruth, Abc_TtWordNum(nVarsInit), 0 );
+    Dau_DsdDecompose( pTemp, nVarsInit, 0, 1, pRes );
+    fprintf( pFile, "%s\n", pRes );
+}
+void Dau_DsdPrintFromTruth( word * pTruth, int nVarsInit )
+{
+    char pRes[DAU_MAX_STR];
+    word pTemp[DAU_MAX_WORD];
+    Abc_TtCopy( pTemp, pTruth, Abc_TtWordNum(nVarsInit), 0 );
+    Dau_DsdDecompose( pTemp, nVarsInit, 0, 1, pRes );
+    fprintf( stdout, "%s\n", pRes );
+}
+
+void Dau_DsdTest44()
+{
+    char pRes[DAU_MAX_STR];
+//    char * pStr = "(!(!a<bcd>)!(!fe))";
+//    char * pStr = "([acb]<!edf>)";
+//    char * pStr = "!(f!(b!c!(d[ea])))";
+//    char * pStr = "[!(a[be])!(c!df)]";
+//    char * pStr = "<(e<bca>)fd>";
+//    char * pStr = "[d8001{abef}c]";
+    char * pStr = "[dc<a(cbd)(!c!b!d)>{abef}]";
+//    char * pStr3;
+    word t = Dau_Dsd6ToTruth( pStr );
+//    return;
+    int nNonDec = Dau_DsdDecompose( &t, 6, 1, 1, pRes );
+//    Dau_DsdNormalize( pStr2 );
+//    Dau_DsdExtract( pStr, 2, 0 );
+    t = 0; 
+    nNonDec = 0;
+}
+
+
+
+void Dau_DsdTest888()
+{
+    char pDsd[DAU_MAX_STR];
+    int nVars = 9;
+//    char * pStr = "[(abc)(def)(ghi)]";
+//    char * pStr = "[a!b!(c!d[e(fg)hi])]";
+//    char * pStr = "[(abc)(def)]";
+//    char * pStr = "[(abc)(def)]";
+//    char * pStr = "[abcdefg]";
+//    char * pStr = "[<abc>(de[ghi])]";
+    char * pStr = "(<abc>(<def><ghi>))";
+    word * pTruth = Dau_DsdToTruth( pStr, 9 );
+    int i, Status;
+//    Kit_DsdPrintFromTruth( (unsigned *)pTruth, 9 ); printf( "\n" );
+/*
+    for ( i = 0; i < 6; i++ )
+    {
+        unsigned uSupp = Dau_Dsd6FindSupports( NULL, pTruth, NULL, 6, i );
+        Dau_DsdPrintSupports( uSupp, 6 );
+    }
+*/
+/*
+    printf( "\n" );
+    for ( i = 0; i < nVars; i++ )
+    {
+        unsigned uSupp = Dau_DsdFindSupports( NULL, pTruth, NULL, nVars, i );
+        Dau_DsdPrintSupports( uSupp, nVars );
+    }
+*/
+    Status = Dau_DsdDecompose( pTruth, nVars, 0, 0, pDsd );
+    i = 0;
+}
+
+void Dau_DsdTest555()
+{
+    int nVars = 10;
+    int nWords = Abc_TtWordNum(nVars);
+    char * pFileName = "_npn/npn/dsd10.txt";
+    FILE * pFile = fopen( pFileName, "rb" );
+    word Tru[2][DAU_MAX_WORD], * pTruth;
+    char pBuffer[DAU_MAX_STR];
+    char pRes[DAU_MAX_STR];
+    int nSizeNonDec;
+    int i, Counter = 0;
+    abctime clk = Abc_Clock(), clkDec = 0, clk2;
+//    return;
+
+    while ( fgets( pBuffer, DAU_MAX_STR, pFile ) != NULL )
+    {
+        char * pStr2 = pBuffer + strlen(pBuffer)-1;
+        if ( *pStr2 == '\n' )
+            *pStr2-- = 0;
+        if ( *pStr2 == '\r' )
+            *pStr2-- = 0;
+        if ( pBuffer[0] == 'V' || pBuffer[0] == 0 )
+            continue;
+        Counter++; 
+
+        for ( i = 0; i < 1; i++ )
+        {
+//            Dau_DsdPermute( pBuffer );
+            pTruth = Dau_DsdToTruth( pBuffer[0] == '*' ? pBuffer + 1 : pBuffer, nVars );
+            Abc_TtCopy( Tru[0], pTruth, nWords, 0 );
+            Abc_TtCopy( Tru[1], pTruth, nWords, 0 );
+            clk2 = Abc_Clock();
+            nSizeNonDec = Dau_DsdDecompose( Tru[1], nVars, 0, 1, pRes );
+            clkDec += Abc_Clock() - clk2;
+            Dau_DsdNormalize( pRes );
+//            pStr2 = Dau_DsdPerform( t ); nSizeNonDec = 0;
+            assert( nSizeNonDec == 0 );
+            pTruth = Dau_DsdToTruth( pRes, nVars );
+            if ( !Abc_TtEqual( pTruth, Tru[0], nWords ) )
+            {
+    //        Kit_DsdPrintFromTruth( (unsigned *)&t, 6 );
+    //        printf( "  " );
+    //        Kit_DsdPrintFromTruth( (unsigned *)&t2, 6 );
+                printf( "%s -> %s \n", pBuffer, pRes );
+                printf( "Verification failed.\n" );
+            }
+        }
+    }
+    printf( "Finished trying %d decompositions.  ", Counter );
+    Abc_PrintTime( 1, "Time", clkDec );
+    Abc_PrintTime( 1, "Total", Abc_Clock() - clk );
+
+    Abc_PrintTime( 1, "Time1", s_Times[0] );
+    Abc_PrintTime( 1, "Time2", s_Times[1] );
+    Abc_PrintTime( 1, "Time3", s_Times[2] );
+
+    fclose( pFile );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/opt/dau/dauDsd2.c b/abc-build/src/opt/dau/dauDsd2.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dau/dauDsd2.c
@@ -0,0 +1,660 @@
+/**CFile****************************************************************
+
+  FileName    [dauDsd2.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware unmapping.]
+
+  Synopsis    [Disjoint-support decomposition.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: dauDsd2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dauInt.h"
+#include "misc/util/utilTruth.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#include DSD_MAX_VAR 12
+#include DSD_MAX_WRD ((DSD_MAX_VAR > 6) ? (1 << (DSD_MAX_VAR-6)) : 1)
+
+typedef struct Dua_Obj_t_ Dua_Obj_t;
+struct Dua_Obj_t_
+{
+    int       Type;                // dec type (1=var; 2=and; 3=xor; 4=mux; 5=prime)
+    int       nFans;               // fanin count
+    char      pFans[DSD_MAX_VAR];  // fanins
+};
+
+typedef struct Dua_Dsd_t_ Dua_Dsd_t;
+struct Dua_Dsd_t_
+{
+    int       nSupp;               // original variables
+    int       nVars;               // remaining variables
+    int       nWords;              // largest non-dec prime
+    int       nObjs;               // object count
+    int       iRoot;               // the root of the tree
+    Dua_Obj_t pObjs[DSD_MAX_VAR];  // objects
+    word      pTruth[DSD_MAX_WRD]; // original/current truth table
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Makes the fCof1-th cofactor of iVar the 0-th cofactor.]
+
+  Description [Variable iVar becomes last varaible; others shift back.
+  Only the 0-th cofactor is computed.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word Abc_Tt6HalfUnShuffleVars( word t, int iVar, int fCof1 )
+{
+    static word Masks[6] = {
+        ABC_CONST(0x5555555555555555),
+        ABC_CONST(0x3333333333333333),
+        ABC_CONST(0x0F0F0F0F0F0F0F0F),
+        ABC_CONST(0x00FF00FF00FF00FF),
+        ABC_CONST(0x0000FFFF0000FFFF),
+        ABC_CONST(0x00000000FFFFFFFF) 
+    };
+    int v, s = (1 << iVar);
+    t = (t >> (fCof1 ? 0 : s)) & Masks[iVar];
+    for ( v = iVar, s = (1 << v); v < 5; v++, s <<= 1 )
+        t = ((t >> s) | t) & Masks[v+1];
+    return t;
+}
+
+static inline void Abc_TtHalfUnShuffleVars( word * pTruth, int nVars, int iVar, int jVar, int fCof1 )
+{
+    int w, nWords = Abc_TtWordNum( nVars );
+    if ( iVar == jVar )
+        return;
+    assert( iVar < jVar );
+    if ( iVar < 5 )
+    {
+        for ( w = 0; w < nWords; w++ )
+            pTruth[w] = Abc_Tt6HalfUnShuffleVars( pTruth[w], iVar, fCof1 );
+        iVar = 5;
+    }
+    if ( jVar < 6 )
+    {
+        for ( w = 0; w < nWords; w++ )
+            pTruth[w] = (pTruth[w] << 32) | pTruth[w];
+        return;
+    }
+    if ( iVar == 5 )
+    {
+        unsigned * pTruthU = (unsigned *)pTruth;
+        for ( w = 0; w < nWords; w += 2 )
+            pTruthU[w] = pTruthU[w+1];
+        iVar = 6;
+    }
+	{
+        word * pLimit = pTruth + nWords;
+		int i, iStep = Abc_TtWordNum(iVar);
+		int j, jStep = Abc_TtWordNum(jVar);
+		for ( ; pTruth < pLimit; pTruth += jStep )
+			for ( i = 0; i < jStep; i += iStep )
+				for ( j = 0; j < iStep; j++ )
+                    pTruth[w++] = pTruth[iStep + i + j];
+        assert( w == (nWords >> 1) );
+        return;
+	}	
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dua_DsdInit( Dua_Dsd_t * pRes, word * pTruth, int nVars )
+{
+    int i;
+    pRes->nSupp  = nVars;
+    pRes->nVars  = nVars;
+    pRes->nWords = Abc_TtWordNum( nVars );
+    pRes->nObjs  = 1;
+    pRes->iRoot  = Abc_Var2Lit( 0, 0 );
+    pRes->pObjs[0].Type = 5;
+    pRes->pObjs[0].nFans = nVars;
+    for ( i = 0; i < nVars; i++ )
+        pRes->pObjs[0].pFans[i] = (char)Abc_Var2Lit( i, 0 );
+    memcpy( pRes->pTruth, pTruth, sizeof(word) * pRes->nWords );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+// returns 1 if the truth table was complemented
+int Dua_DsdTryConst( word * pTruth, int nVars )
+{
+    if ( !(pTruth[0] & 1) )
+        return 0;
+    Abc_TtNot( pTruth, Abc_TtWordNum(nVars) );
+    return 1;
+}
+int Dua_DsdTryVar( word * pTruth, int nWords, int iVar )
+{
+    int nWordsI = Abc_TtWordNum(iVar);
+    word c0 = (iVar < 6) ? Abc_Tt6Cofactor0( pTruth[0], iVar ) : pTruth[0];
+    word c1 = (iVar < 6) ? Abc_Tt6Cofactor1( pTruth[0], iVar ) : pTruth[nWords];
+    if ( c0 != c1 )
+    {
+        if ( c1 < c0 && c1 < ~c1 ) // flip
+        {
+            Abc_TtFlip( pTruth, nWords, iVar );
+            return 0;
+        }
+        if ( ~c1 < c0 && ~c1 < c1 ) // flip and compl
+        {
+            Abc_TtFlipNot( pTruth, nWords, iVar );
+            return 1;
+        }
+    }
+    if ( iVar < 6 )
+    {
+        word * pLimit = pTruth + nWords;
+        for ( pTruth++; pTruth < pLimit; pTruth++ )
+        {
+            c0 = Abc_Tt6Cofactor0( pTruth[0], iVar );
+            c1 = Abc_Tt6Cofactor1( pTruth[0], iVar );
+            if ( c0 == c1 )
+                continue;
+            if ( c0 < c1 )
+                return 0;
+            for ( ; pTruth < pLimit; pTruth++ )
+                pTruth[0] = Abc_Tt6Flip( pTruth[0], iVar );
+            return 0;
+        }
+    }
+    else
+    {
+        for ( ; pTruth < pLimit; pTruth += (nWordsI << 1) )
+        for ( w = 0; w < nWordsI; w++ )
+        {
+            c0 = pTruth[0];
+            c1 = pTruth[nWordsI];
+            if ( c0 == c1 )
+                continue;
+            if ( c0 < c1 )
+                return 0;
+            for ( ; pTruth < pLimit; pTruth += (nWordsI << 1) )
+            for ( ; w < nWordsI; w++ )
+                ABC_SWAP( word, pTruth[0], pTruth[nWordsI] );
+            return 0;
+        }
+    }
+    assert( 0 );
+    return -1;
+}
+int Dua_DsdCheckCof0Const0( word * pTruth, int nWords, int iVar )
+{
+    if ( nWords == 1 )
+        return (pTruth[0] & s_Truths6Neg[iVar]) == 0;
+	if ( iVar <= 5 )
+	{
+		int w;
+		for ( w = 0; w < nWords; w++ )
+            if ( (pTruth[w] & s_Truths6Neg[iVar]) )
+                return 0;
+        return 1;
+	}
+	else // if ( iVar > 5 )
+	{
+        word * pLimit = pTruth + nWords;
+		int i, iStep = Abc_TtWordNum(iVar);
+		for ( ; pTruth < pLimit; pTruth += (iStep << 1) )
+			for ( i = 0; i < iStep; i++ )
+                if ( pTruth[i] )
+                    return 0;
+        return 1;
+	}	
+}
+int Dua_DsdCheckCofsEqualNot( word * pTruth, int nWords, int iVar )
+{
+    if ( nWords == 1 )
+        return (pTruth[0] & s_Truths6Neg[iVar]) == ((~pTruth[0] & s_Truths6[iVar]) >> (1 << iVar));
+	if ( iVar <= 5 )
+	{
+		int w, shift = (1 << iVar);
+		for ( w = 0; w < nWords; w++ )
+            if ( (pTruth[w] & s_Truths6Neg[iVar]) != ((~pTruth[w] & s_Truths6[iVar]) >> shift) )
+                return 0;
+        return 1;
+	}
+	else // if ( iVar > 5 )
+	{
+        word * pLimit = pTruth + nWords;
+		int i, iStep = Abc_TtWordNum(iVar);
+		for ( ; pTruth < pLimit; pTruth += (iStep << 1) )
+			for ( i = 0; i < iStep; i++ )
+                if ( pTruth[i] != ~pTruth[i + iStep] )
+                    return 0;
+        return 1;
+	}	
+}
+int Dua_DsdOneVar( Dua_Dsd_t * pRes )
+{
+    int v, fCompl, fChange = 1;
+    fCompl = Dua_DsdTryConst( pRes->pTruth, pRes->nWords );
+    while ( fChange && pRes->nVars > 2 )
+    {
+        fChange = 0;
+        for ( v = 0; v < pRes->nVars; v++ )
+        {
+            fCompl ^= Dua_DsdTryVar( pRes->pTruth, pRes->nWords, v );
+            if ( Dua_DsdCheckCof0Const0( pRes->pTruth, pRes->nWords, v ) )
+            {
+                fChange = 1;
+                // record AND(v, F)
+            }
+            else if ( Dua_DsdCheckCofsEqualNot( pRes->pTruth, pRes->nWords, v ) )
+            {
+                fChange = 1;
+                // record XOR(v, F)
+            }
+        }
+    }
+    return fCompl;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dua_DsdTrySwap( word * pTruth, int nWords, int iVar )
+{
+    static word s_PMasks[5][3] = {
+        { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) },
+        { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) },
+        { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) },
+        { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) },
+        { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) }
+    };
+    if ( iVar < 5 )
+    {
+        int Shift = (1 << iVar);
+        word c01, c10, * pLimit = pTruth + nWords;
+        for ( ; pTruth < pLimit; pTruth++ )
+        {
+            c01 = (pTruth[0] & s_PMasks[iVar][1]);
+            c10 = (pTruth[0] & s_PMasks[iVar][2]) >> Shift;
+            if ( c01 == c10 )
+                continue;
+            if ( c01 < c10 )
+                return 0;
+            pTruth[0] = (pTruth[0] & s_PMasks[iVar][0]) | ((pTruth[0] & s_PMasks[iVar][1]) << Shift) | ((pTruth[0] & s_PMasks[iVar][2]) >> Shift);
+            return 1;
+        }
+    }
+    else if ( iVar == 5 )
+    {
+        unsigned * pTruthU = (unsigned *)pTruth;
+        unsigned * pLimitU = (unsigned *)(pTruth + nWords);
+		for ( ; pTruthU < pLimitU; pTruthU += 4 )
+        {
+            c01 = pTruthU[1];
+            c10 = pTruthU[2];
+            if ( c01 == c10 )
+                continue;
+            if ( c01 < c10 )
+                return 0;
+		    for ( ; pTruthU < pLimitU; pTruthU += 4 )
+                ABC_SWAP( unsigned, pTruthU[1], pTruthU[2] );
+            return 1;
+        }
+    }
+    else // if ( iVar > 5 )
+    {
+        word * pLimit = pTruth + nWords;
+		int i, iStep = Abc_TtWordNum(iVar);
+		for ( ; pTruth < pLimit; pTruth += 4*iStep )
+		for ( i = 0; i < iStep; i++ )
+        {
+            c01 = pTruth[i + iStep];
+            c10 = pTruth[i + 2*iStep];
+            if ( c01 == c10 )
+                continue;
+            if ( c01 < c10 )
+                return 0;
+		    for ( ; pTruth < pLimit; pTruth += 4*iStep )
+		    for ( ; i < iStep; i++ )
+                ABC_SWAP( word, pTruth[1], pTruth[2] );
+            return 1;
+        }
+    }
+    return 2;
+}
+int Dua_DsdCheckDecomp( word * pTruth, int nWords, int iVar )
+{
+    static word s_PMasks[5][4] = {
+        { ABC_CONST(0x1111111111111111), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444), ABC_CONST(0x8888888888888888) },
+        { ABC_CONST(0x0303030303030303), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030), ABC_CONST(0xC0C0C0C0C0C0C0C0) },
+        { ABC_CONST(0x000F000F000F000F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00), ABC_CONST(0xF000F000F000F000) },
+        { ABC_CONST(0x000000FF000000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000), ABC_CONST(0xFF000000FF000000) },
+        { ABC_CONST(0x000000000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000), ABC_CONST(0xFFFF000000000000) }
+    };
+    int fC0eC1 = 1, fC0eC3 = 1;
+    if ( iVar < 5 )
+    {
+        int Shift = (1 << iVar);
+        word c01, c10, * pLimit = pTruth + nWords;
+        for ( ; pTruth < pLimit; pTruth++ )
+        {
+            if ( fC0eC1 && (pTruth[0] & s_PMasks[iVar][0]) != ((pTruth[0] & s_PMasks[iVar][1]) >>    Shift) )
+                fC0eC1 = 0;
+            if ( fC0eC3 && (pTruth[0] & s_PMasks[iVar][0]) != ((pTruth[0] & s_PMasks[iVar][3]) >> (3*Shift)) )
+                fC0eC3 = 0;
+            if ( !fC0eC1 && !fC0eC3 )
+                return 0;
+        }
+    }
+    if ( iVar == 5 )
+    {
+        unsigned * pTruthU = (unsigned *)pTruth;
+        unsigned * pLimitU = (unsigned *)(pTruth + nWords);
+		for ( ; pTruthU < pLimitU; pTruthU += 4 )
+        {
+            if ( fC0eC1 && pTruthU[0] != pTruthU[1] )
+                fC0eC1 = 0;
+            if ( fC0eC3 && pTruthU[0] != pTruthU[3] )
+                fC0eC3 = 0;
+            if ( !fC0eC1 && !fC0eC3 )
+                return 0;
+        }
+    }
+    else // if ( iVar > 5 )
+    {
+        word * pLimit = pTruth + nWords;
+		int i, iStep = Abc_TtWordNum(iVar);
+		for ( ; pTruth < pLimit; pTruth += 4*iStep )
+		for ( i = 0; i < iStep; i++ )
+        {
+            if ( fC0eC1 && pTruth[0] != pTruth[1] )
+                fC0eC1 = 0;
+            if ( fC0eC3 && pTruth[0] != pTruth[3] )
+                fC0eC3 = 0;
+            if ( !fC0eC1 && !fC0eC3 )
+                return 0;
+        }
+    }
+    assert( fC0eC1 != fC0eC3 );
+    return fC0eC1 ? 1 : 2;
+}
+
+// returns 1 if decomposition detected
+int Dua_DsdTwoVars( Dua_Dsd_t * pRes )
+{
+    int v, RetValue, fChange = 1;
+    while ( fChange && pRes->nVars > 2 )
+    {
+        fChange = 0;
+        for ( v = 0; v < pRes->nVars - 1; v++ )
+        {
+            RetValue = Dua_DsdTrySwap( pRes->pTruth, pRes->nWords, v );            
+            if ( RetValue == 1 )
+                fChange = 1;
+            if ( RetValue != 2 )
+                continue;
+            // vars are symmetric, check decomp
+            RetValue = Dua_DsdCheckDecomp( pRes->pTruth, pRes->nWords, v );
+            if ( RetValue == 0 )
+                continue;
+            if ( RetValue == 1 )
+            {
+                fChange = 1;
+                // record AND(a, b)
+            }
+            else
+            {
+                fChange = 1;
+                // record XOR(a, b)
+            }
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check DSD for bound-set [iVar; jVar).]
+
+  Description [Return D-func if decomposable.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word Dua_DsdRangeVars( word * pTruth, int nVars, int iVar, int jVar, int fPerform )
+{
+    int Part, nParts = 1 << (nVars - jVar);
+    int Mint, nMints = 1 << (jVar - iVar);
+    word MaskOne, MaskAll = 0;
+    assert( jVar - iVar > 2 );
+    assert( jVar - iVar < 7 );
+    if ( iVar < 6 )
+    {
+        int Shift = 6 - iVar, MaskF = (1 << Shift) - 1, iMint = 0;
+        word MaskFF = (((word)1) << (1 << iVar)) - 1;
+        word Cof0, Cof1, Value; 
+        for ( Part = 0; Part < nParts; Part++ )
+        {
+            MaskOne = 0;
+            Cof0 = Cof1 = ~(word)0;
+            for ( Mint = 0; Mint < nMints; Mint++, iMint++ )
+            {
+                Value = (pTruth[iMint>>Shift] >> ((iMint & MaskF)<<iVar)) & MaskFF;
+                if ( !~Cof0 || Cof0 == Value )
+                    Cof0 = Value;
+                else if ( !~Cof1 || Cof1 == Value )
+                {
+                    Cof1 = Value;
+                    MaskOne |= ((word)1) << Mint;
+                }
+                else
+                    return 0;
+            }
+            if ( Part == 0 )
+                MaskAll = MaskOne;
+            else if ( MaskAll != MaskOne )
+                return 0;
+            if ( fPerform )
+            {
+                assert( ~Cof0 && ~Cof1 );
+                Mint = 2 * Part;
+                Value = (pTruth[Mint>>Shift] >> ((Mint & MaskF)<<nVarsF)) & MaskFF;
+                pTruth[Mint>>Shift] ^= (Value ^ Cof0) << ((Mint & MaskF)<<nVarsF)
+                Mint = 2 * Part + 1;
+                Value = (pTruth[Mint>>Shift] >> ((Mint & MaskF)<<nVarsF)) & MaskFF;
+                pTruth[Mint>>Shift] ^= (Value ^ Cof1) << ((Mint & MaskF)<<nVarsF)
+            }
+        }
+        // stretch
+        if ( nVars - (jVar - iVar) + 1 < 6 )
+            pTruth[0] = Abc_Tt6Stretch( pTruth[0], nVars - (jVar - iVar) + 1 );
+    }
+    else
+    {
+        int nWordsF = Abc_TtWordNum(iVar); 
+        int iWord = 0, nBytes = sizeof(word) * nWordsF;
+        word * pCof0, * pCof1;
+        for ( Part = 0; Part < nParts; Part++ )
+        {
+            MaskOne = 0;
+            pCof0 = pCof1 = NULL;
+            for ( Mint = 0; Mint < nMints; Mint++, iWord += nWordsF )
+            {
+                if ( !pCof0 || !memcmp(pCof0, pTruth + iWord, nBytes) )
+                    pCof0 = pTruth + iWord;
+                else if ( !pCof1 || !memcmp(pCof1, pTruth + iWord, nBytes) )
+                {
+                    pCof1 = pTruth + iWord;
+                    MaskOne |= ((word)1) << Mint;
+                }
+                else
+                    return 0;
+            }
+            if ( Part == 0 )
+                MaskAll = MaskOne;
+            else if ( MaskAll != MaskOne )
+                return 0;
+            if ( fPerform )
+            {
+                assert( pCof0 && pCof1 );
+                memcpy( pTruth + (2 * Part + 0) * nWordsF, pCof0, nBytes );
+                memcpy( pTruth + (2 * Part + 1) * nWordsF, pCof1, nBytes );
+            }
+        }
+    }
+    return MaskAll;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check DSD for bound-set [0; iVar).]
+
+  Description [Return D-func if decomposable.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dua_DsdRangeVars0( word * pTruth, int nVars, int iVar, int fPerform )
+{
+    int i, nParts = 1 << (nVars - iVar);
+    assert( iVar > 2 && iVar < nVars );
+    if ( iVar == 3 )
+    {
+        unsigned char * pTruthP = (unsigned char *)pTruth, Dfunc = pTruthP[0];
+        for ( i = 1; i < nParts; i++ )
+            if ( pTruthP[i] != Dfunc && pTruthP[i] != ~Dfunc )
+                return 0;
+    }
+    else if ( iVar == 4 )
+    {
+        unsigned short * pTruthP = (unsigned short *)pTruth, Dfunc = pTruthP[0];
+        for ( i = 1; i < nParts; i++ )
+            if ( pTruthP[i] != Dfunc && pTruthP[i] != ~Dfunc )
+                return 0;
+    }
+    else if ( iVar == 5 )
+    {
+        unsigned int * pTruthP = (unsigned int *)pTruth, Dfunc = pTruthP[0];
+        for ( i = 1; i < nParts; i++ )
+            if ( pTruthP[i] != Dfunc && pTruthP[i] != ~Dfunc )
+                return 0;
+    }
+    else 
+    {
+        int nStep = 1 << (6 - iVar);
+        assert( iVar >= 6 );
+        for ( i = 1; i < nParts; i++ )
+            if ( !Abc_TtEqual(pTruth, pTruth + i * nStep, nStep) && !Abc_TtEqualNot(pTruth, pTruth + i * nStep, nStep) )
+                return 0;
+    }
+    return 1;
+}
+void Dua_DsdRangeVars0Derive( word * pTruth, int nVars, int iVar )
+{
+    int i, nParts = 1 << (nVars - iVar);
+    assert( iVar > 2 && iVar < nVars );
+    if ( iVar == 3 )
+    {
+        unsigned char * pTruthP = (unsigned char *)pTruth, Dfunc = pTruthP[0];
+        for ( i = 0; i < nParts; i++ )
+            if ( Abc_TtGetBit(pTruth, i) ^ (pTruthP[i] != Dfunc) )
+                Abc_TtXorBit(pTruth, i);
+    }
+    else if ( iVar == 4 )
+    {
+        unsigned short * pTruthP = (unsigned short *)pTruth, Dfunc = pTruthP[0];
+        for ( i = 0; i < nParts; i++ )
+            if ( Abc_TtGetBit(pTruth, i) ^ (pTruthP[i] != Dfunc) )
+                Abc_TtXorBit(pTruth, i);
+    }
+    else if ( iVar == 5 )
+    {
+        unsigned int * pTruthP = (unsigned int *)pTruth, Dfunc = pTruthP[0];
+        for ( i = 0; i < nParts; i++ )
+            if ( Abc_TtGetBit(pTruth, i) ^ (pTruthP[i] != Dfunc) )
+                Abc_TtXorBit(pTruth, i);
+    }
+    else 
+    {
+        word Dfunc = pTruth[0];
+        assert( iVar == 6 );
+        for ( i = 0; i < nParts; i++ )
+            if ( Abc_TtGetBit(pTruth, i) ^ (pTruth[i] != Dfunc) )
+                Abc_TtXorBit(pTruth, i);
+   }
+    // stretch
+    if ( nVars - iVar + 1 < 6 )
+        pTruth[0] = Abc_Tt6Stretch( pTruth[0], nVars - iVar + 1 < 6 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dua_DsdTest( word * pTruth, int nVar )
+{
+    Dua_Dsd_t Res, * pRes = &Res;
+    Dua_DsdInit( pRes, pTruth, nVars );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
+
diff --git a/abc-build/src/opt/dau/dauEnum.c b/abc-build/src/opt/dau/dauEnum.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dau/dauEnum.c
@@ -0,0 +1,253 @@
+/**CFile****************************************************************
+
+  FileName    [dauEnum.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware unmapping.]
+
+  Synopsis    [Enumeration of decompositions.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: dauEnum.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dauInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Dau_EnumLift( char * pName, int Shift )
+{
+    static char pBuffer[64];
+    char * pTemp;
+    for ( pTemp = pBuffer; *pName; pTemp++, pName++ )
+        *pTemp = (*pName >= 'a' && *pName <= 'z') ? *pName + Shift : *pName;
+    *pTemp = 0;
+    return pBuffer;
+}
+char * Dau_EnumLift2( char * pName, int Shift )
+{
+    static char pBuffer[64];
+    char * pTemp;
+    for ( pTemp = pBuffer; *pName; pTemp++, pName++ )
+        *pTemp = (*pName >= 'a' && *pName <= 'z') ? *pName + Shift : *pName;
+    *pTemp = 0;
+    return pBuffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dau_EnumCombineTwo( Vec_Ptr_t * vOne, int fStar, int fXor, char * pName1, char * pName2, int Shift2, int fCompl1, int fCompl2 )
+{
+    static char pBuffer[256];
+    pName2 = Dau_EnumLift( pName2, Shift2 );
+    sprintf( pBuffer, "%s%c%s%s%s%s%c", 
+        fStar?"*":"", 
+        fXor?'[':'(', 
+        fCompl1?"!":"", pName1[0] == '*' ? pName1 + 1 : pName1, 
+        fCompl2?"!":"", pName2[0] == '*' ? pName2 + 1 : pName2, 
+        fXor?']':')' );
+//    printf( "%s ", pBuffer );
+    Vec_PtrPush( vOne, Abc_UtilStrsav(pBuffer) );
+}
+void Dau_EnumCombineThree( Vec_Ptr_t * vOne, int fStar, char * pNameC, char * pName1, char * pName2, int Shift1, int Shift2, int fComplC, int fCompl1, int fCompl2 )
+{
+    static char pBuffer[256];
+    pName1 = Dau_EnumLift( pName1, Shift1 );
+    pName2 = Dau_EnumLift2( pName2, Shift2 );
+    sprintf( pBuffer, "%s%c%s%s%s%s%s%s%c", 
+        fStar?"*":"", 
+        '<', 
+        fComplC?"!":"", pNameC[0] == '*' ? pNameC + 1 : pNameC, 
+        fCompl1?"!":"", pName1[0] == '*' ? pName1 + 1 : pName1, 
+        fCompl2?"!":"", pName2[0] == '*' ? pName2 + 1 : pName2, 
+        '>' );
+//    printf( "%s ", pBuffer );
+    Vec_PtrPush( vOne, Abc_UtilStrsav(pBuffer) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dau_EnumTestDump( Vec_Ptr_t * vSets, char * pFileName )
+{ 
+    FILE * pFile;
+    Vec_Ptr_t * vOne;
+    char * pName;
+    int v, k;
+    pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+        return;
+    Vec_PtrForEachEntry( Vec_Ptr_t *, vSets, vOne, v )
+    {
+        fprintf( pFile, "VARIABLE NUMBER %d:\n", v );
+        Vec_PtrForEachEntry( char *, vOne, pName, k )
+            fprintf( pFile, "%s\n", pName );
+    }
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dau_EnumTest()
+{
+    int v, k, nVarMax = 10;
+    Vec_Ptr_t * vSets;
+    Vec_Ptr_t * vOne;
+    char * pName;
+    // 0 vars
+    vSets = Vec_PtrAlloc( 16 );
+    Vec_PtrPush( vSets, Vec_PtrAlloc(0) );
+    // 1 vars
+    vOne = Vec_PtrAlloc( 1 );
+    Vec_PtrPush( vOne, Abc_UtilStrsav("*a") );
+    Vec_PtrPush( vSets, vOne );
+    // 2+ vars
+    for ( v = 2; v <= nVarMax; v++ )
+    {
+        Vec_Ptr_t * vSetI, * vSetJ, * vSetK;
+        char * pNameI, * pNameJ, * pNameK;
+        int i, j, k, i1, j1, k1;
+        vOne = Vec_PtrAlloc( 100 );
+        for ( i = 1; i < v; i++ )
+        for ( j = i; j < v; j++ )
+        {
+            if ( i + j != v )
+                continue;
+            vSetI = (Vec_Ptr_t *)Vec_PtrEntry( vSets, i );
+            vSetJ = (Vec_Ptr_t *)Vec_PtrEntry( vSets, j );
+            Vec_PtrForEachEntry( char *, vSetI, pNameI, i1 )
+            Vec_PtrForEachEntry( char *, vSetJ, pNameJ, j1 )
+            {
+                // AND(a,b)
+                Dau_EnumCombineTwo( vOne, 0, 0, pNameI, pNameJ, i, 0, 0 );
+                // AND(!a,b)
+                if ( pNameI[0] != '*' )
+                Dau_EnumCombineTwo( vOne, 0, 0, pNameI, pNameJ, i, 1, 0 );
+                // AND(a,!b)
+                if ( pNameJ[0] != '*' && !(i == j && i1 == j1) )
+                Dau_EnumCombineTwo( vOne, 0, 0, pNameI, pNameJ, i, 0, 1 );
+                // AND(!a,!b)
+                if ( pNameI[0] != '*' && pNameJ[0] != '*' )
+                Dau_EnumCombineTwo( vOne, 0, 0, pNameI, pNameJ, i, 1, 1 );
+                // XOR(a,b)
+                Dau_EnumCombineTwo( vOne, pNameI[0] == '*' || pNameJ[0] == '*', 1, pNameI, pNameJ, i, 0, 0 );
+            }
+        }
+        for ( k = 1; k < v; k++ )
+        for ( i = 1; i < v; i++ )
+        for ( j = i; j < v; j++ )
+        {
+            if ( k + i + j != v )
+                continue;
+            vSetK = (Vec_Ptr_t *)Vec_PtrEntry( vSets, k );
+            vSetI = (Vec_Ptr_t *)Vec_PtrEntry( vSets, i );
+            vSetJ = (Vec_Ptr_t *)Vec_PtrEntry( vSets, j );
+            Vec_PtrForEachEntry( char *, vSetK, pNameK, k1 )
+            Vec_PtrForEachEntry( char *, vSetI, pNameI, i1 )
+            Vec_PtrForEachEntry( char *, vSetJ, pNameJ, j1 )
+            {
+                int fStar = pNameI[0] == '*' && pNameJ[0] == '*';
+
+                // MUX(c,a,b)
+                Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 0, 0, 0 );
+                // MUX(c,!a,b)
+                if ( pNameI[0] != '*' )
+                Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 0, 1, 0 );
+                // MUX(c,a,!b)
+                if ( pNameJ[0] != '*' && !(i == j && i1 == j1) )
+                Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 0, 0, 1 );
+
+                if ( pNameK[0] != '*' && !(i == j && i1 == j1) )
+                {
+                    // MUX(!c,a,b)
+                    Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 1, 0, 0 );
+                    // MUX(!c,!a,b)
+                    if ( pNameI[0] != '*' )
+                    Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 1, 1, 0 );
+                    // MUX(!c,a,!b)
+                    if ( pNameJ[0] != '*' )
+                    Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 1, 0, 1 );
+                }
+            }
+        }
+        Vec_PtrPush( vSets, vOne );
+    }
+    Dau_EnumTestDump( vSets, "_npn/npn/dsd10.txt" );
+
+    Vec_PtrForEachEntry( Vec_Ptr_t *, vSets, vOne, v )
+    {
+        printf( "VARIABLE NUMBER %d:\n", v );
+        Vec_PtrForEachEntry( char *, vOne, pName, k )
+            printf( "%s\n", pName );
+        if ( v == 4 )
+            break;
+    }
+    Vec_PtrForEachEntry( Vec_Ptr_t *, vSets, vOne, v )
+    {
+        printf( "%d=%d ", v, Vec_PtrSize(vOne) );
+        Vec_PtrFreeFree( vOne );
+    }
+    Vec_PtrFree( vSets );
+    printf( "\n" );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dau/dauGia.c b/abc-build/src/opt/dau/dauGia.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dau/dauGia.c
@@ -0,0 +1,540 @@
+/**CFile****************************************************************
+
+  FileName    [dauGia.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware unmapping.]
+
+  Synopsis    [Coverting DSD into GIA.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: dauGia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dauInt.h"
+#include "aig/gia/gia.h"
+#include "misc/util/utilTruth.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash );
+
+#define DAU_DSD_MAX_VAR 8
+
+static int m_Calls = 0;
+static int m_NonDsd = 0;
+static int m_Non1Step = 0;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    [Derives GIA for the truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dau_DsdToGiaCompose_rec( Gia_Man_t * pGia, word Func, int * pFanins, int nVars )
+{
+    int t0, t1;
+    if ( Func == 0 )
+        return 0;
+    if ( Func == ~(word)0 )
+        return 1;
+    assert( nVars > 0 );
+    if ( --nVars == 0 )
+    {
+        assert( Func == s_Truths6[0] || Func == s_Truths6Neg[0] );
+        return Abc_LitNotCond( pFanins[0], (int)(Func == s_Truths6Neg[0]) );
+    }
+    if ( !Abc_Tt6HasVar(Func, nVars) )
+        return Dau_DsdToGiaCompose_rec( pGia, Func, pFanins, nVars );
+    t0 = Dau_DsdToGiaCompose_rec( pGia, Abc_Tt6Cofactor0(Func, nVars), pFanins, nVars );
+    t1 = Dau_DsdToGiaCompose_rec( pGia, Abc_Tt6Cofactor1(Func, nVars), pFanins, nVars );
+    if ( pGia->pMuxes )
+        return Gia_ManHashMuxReal( pGia, pFanins[nVars], t1, t0 );
+    else
+        return Gia_ManHashMux( pGia, pFanins[nVars], t1, t0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives GIA for the DSD formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dau_DsdToGia2_rec( Gia_Man_t * pGia, char * pStr, char ** p, int * pMatches, int * pLits, Vec_Int_t * vCover )
+{
+    int fCompl = 0;
+    if ( **p == '!' )
+        (*p)++, fCompl = 1;
+    if ( **p >= 'a' && **p < 'a' + DAU_DSD_MAX_VAR ) // var
+        return Abc_LitNotCond( pLits[**p - 'a'], fCompl );
+    if ( **p == '(' ) // and/or
+    {
+        char * q = pStr + pMatches[ *p - pStr ];
+        int Res = 1, Lit;
+        assert( **p == '(' && *q == ')' );
+        for ( (*p)++; *p < q; (*p)++ )
+        {
+            Lit = Dau_DsdToGia2_rec( pGia, pStr, p, pMatches, pLits, vCover );
+            Res = Gia_ManHashAnd( pGia, Res, Lit );
+        }
+        assert( *p == q );
+        return Abc_LitNotCond( Res, fCompl );
+    }
+    if ( **p == '[' ) // xor
+    {
+        char * q = pStr + pMatches[ *p - pStr ];
+        int Res = 0, Lit;
+        assert( **p == '[' && *q == ']' );
+        for ( (*p)++; *p < q; (*p)++ )
+        {
+            Lit = Dau_DsdToGia2_rec( pGia, pStr, p, pMatches, pLits, vCover );
+            if ( pGia->pMuxes )
+                Res = Gia_ManHashXorReal( pGia, Res, Lit );
+            else
+                Res = Gia_ManHashXor( pGia, Res, Lit );
+        }
+        assert( *p == q );
+        return Abc_LitNotCond( Res, fCompl );
+    }
+    if ( **p == '<' ) // mux
+    {
+        int nVars = 0;
+        int Temp[3], * pTemp = Temp, Res;
+        int Fanins[DAU_DSD_MAX_VAR], * pLits2;
+        char * pOld = *p;
+        char * q = pStr + pMatches[ *p - pStr ];
+        // read fanins
+        if ( *(q+1) == '{' )
+        {
+            char * q2;
+            *p = q+1;
+            q2 = pStr + pMatches[ *p - pStr ];
+            assert( **p == '{' && *q2 == '}' );
+            for ( nVars = 0, (*p)++; *p < q2; (*p)++, nVars++ )
+                Fanins[nVars] = Dau_DsdToGia2_rec( pGia, pStr, p, pMatches, pLits, vCover );
+            assert( *p == q2 );
+            pLits2 = Fanins;
+        }
+        else
+            pLits2 = pLits;
+        // read MUX
+        *p = pOld;
+        q = pStr + pMatches[ *p - pStr ];
+        assert( **p == '<' && *q == '>' );
+        // verify internal variables
+        if ( nVars )
+            for ( ; pOld < q; pOld++ )
+                if ( *pOld >= 'a' && *pOld <= 'z' )
+                    assert( *pOld - 'a' < nVars );
+        // derive MUX components
+        for ( (*p)++; *p < q; (*p)++ )
+            *pTemp++ = Dau_DsdToGia2_rec( pGia, pStr, p, pMatches, pLits2, vCover );
+        assert( pTemp == Temp + 3 );
+        assert( *p == q );
+        if ( *(q+1) == '{' ) // and/or
+        {
+            char * q = pStr + pMatches[ ++(*p) - pStr ];
+            assert( **p == '{' && *q == '}' );
+            *p = q;
+        }
+        if ( pGia->pMuxes )
+            Res = Gia_ManHashMuxReal( pGia, Temp[0], Temp[1], Temp[2] );
+        else
+            Res = Gia_ManHashMux( pGia, Temp[0], Temp[1], Temp[2] );
+        return Abc_LitNotCond( Res, fCompl );
+    }
+    if ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') )
+    {
+        Vec_Int_t vLeaves;  char * q;
+        word pFunc[DAU_DSD_MAX_VAR > 6 ? (1 << (DAU_DSD_MAX_VAR-6)) : 1];
+        int Fanins[DAU_DSD_MAX_VAR], Res; 
+        int i, nVars = Abc_TtReadHex( pFunc, *p );
+        *p += Abc_TtHexDigitNum( nVars );
+        q = pStr + pMatches[ *p - pStr ];
+        assert( **p == '{' && *q == '}' );
+        for ( i = 0, (*p)++; *p < q; (*p)++, i++ )
+            Fanins[i] = Dau_DsdToGia2_rec( pGia, pStr, p, pMatches, pLits, vCover );
+        assert( i == nVars );
+        assert( *p == q );
+//        Res = Dau_DsdToGia2Compose_rec( pGia, Func, Fanins, nVars );
+        vLeaves.nCap = nVars;
+        vLeaves.nSize = nVars;
+        vLeaves.pArray = Fanins;        
+        Res = Kit_TruthToGia( pGia, (unsigned *)pFunc, nVars, vCover, &vLeaves, 1 );
+        m_Non1Step++;
+        return Abc_LitNotCond( Res, fCompl );
+    }
+    assert( 0 );
+    return 0;
+}
+int Dau_DsdToGia2( Gia_Man_t * pGia, char * p, int * pLits, Vec_Int_t * vCover )
+{
+    int Res;
+    if ( *p == '0' && *(p+1) == 0 )
+        Res = 0;
+    else if ( *p == '1' && *(p+1) == 0 )
+        Res = 1;
+    else
+        Res = Dau_DsdToGia2_rec( pGia, p, &p, Dau_DsdComputeMatches(p), pLits, vCover );
+    assert( *++p == 0 );
+    return Res;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives GIA for the DSD formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dau_DsdAddToArray( Gia_Man_t * pGia, int * pFans, int nFans, int iFan )
+{
+    int i;
+    pFans[nFans] = iFan;
+    if ( nFans == 0 )
+        return;
+    for ( i = nFans; i > 0; i-- )
+    {
+        if ( Gia_ObjLevelId(pGia, Abc_Lit2Var(pFans[i])) <= Gia_ObjLevelId(pGia, Abc_Lit2Var(pFans[i-1])) )
+            return;
+        ABC_SWAP( int, pFans[i], pFans[i-1] );
+    }
+}
+int Dau_DsdBalance( Gia_Man_t * pGia, int * pFans, int nFans, int fAnd )
+{
+    Gia_Obj_t * pObj;
+    int iFan0, iFan1, iFan;
+    if ( nFans == 1 )
+        return pFans[0];
+    assert( nFans > 1 );
+    iFan0 = pFans[--nFans];
+    iFan1 = pFans[--nFans];
+    if ( fAnd )
+        iFan = Gia_ManHashAnd( pGia, iFan0, iFan1 );
+    else if ( pGia->pMuxes )
+        iFan = Gia_ManHashXorReal( pGia, iFan0, iFan1 );
+    else 
+        iFan = Gia_ManHashXor( pGia, iFan0, iFan1 );
+    pObj = Gia_ManObj(pGia, Abc_Lit2Var(iFan));
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        if ( fAnd )
+            Gia_ObjSetAndLevel( pGia, pObj );
+        else if ( pGia->pMuxes )
+            Gia_ObjSetXorLevel( pGia, pObj );
+        else 
+        {
+            if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) )
+                Gia_ObjSetAndLevel( pGia, Gia_ObjFanin0(pObj) );
+            if ( Gia_ObjIsAnd(Gia_ObjFanin1(pObj)) )
+                Gia_ObjSetAndLevel( pGia, Gia_ObjFanin1(pObj) );
+            Gia_ObjSetAndLevel( pGia, pObj );
+        }
+    }
+    Dau_DsdAddToArray( pGia, pFans, nFans++, iFan );
+    return Dau_DsdBalance( pGia, pFans, nFans, fAnd );
+}
+int Dau_DsdToGia_rec( Gia_Man_t * pGia, char * pStr, char ** p, int * pMatches, int * pLits, Vec_Int_t * vCover )
+{
+    int fCompl = 0;
+    if ( **p == '!' )
+        (*p)++, fCompl = 1;
+    if ( **p >= 'a' && **p < 'a' + DAU_DSD_MAX_VAR ) // var
+        return Abc_LitNotCond( pLits[**p - 'a'], fCompl );
+    if ( **p == '(' ) // and/or
+    {
+        char * q = pStr + pMatches[ *p - pStr ];
+        int pFans[DAU_DSD_MAX_VAR], nFans = 0, Fan;
+        assert( **p == '(' && *q == ')' );
+        for ( (*p)++; *p < q; (*p)++ )
+        {
+            Fan = Dau_DsdToGia_rec( pGia, pStr, p, pMatches, pLits, vCover );
+            Dau_DsdAddToArray( pGia, pFans, nFans++, Fan );
+        }
+        Fan = Dau_DsdBalance( pGia, pFans, nFans, 1 );
+        assert( *p == q );
+        return Abc_LitNotCond( Fan, fCompl );
+    }
+    if ( **p == '[' ) // xor
+    {
+        char * q = pStr + pMatches[ *p - pStr ];
+        int pFans[DAU_DSD_MAX_VAR], nFans = 0, Fan;
+        assert( **p == '[' && *q == ']' );
+        for ( (*p)++; *p < q; (*p)++ )
+        {
+            Fan = Dau_DsdToGia_rec( pGia, pStr, p, pMatches, pLits, vCover );
+            Dau_DsdAddToArray( pGia, pFans, nFans++, Fan );
+        }
+        Fan = Dau_DsdBalance( pGia, pFans, nFans, 0 );
+        assert( *p == q );
+        return Abc_LitNotCond( Fan, fCompl );
+    }
+    if ( **p == '<' ) // mux
+    {
+        Gia_Obj_t * pObj;
+        int nVars = 0;
+        int Temp[3], * pTemp = Temp, Res;
+        int Fanins[DAU_DSD_MAX_VAR], * pLits2;
+        char * pOld = *p;
+        char * q = pStr + pMatches[ *p - pStr ];
+        // read fanins
+        if ( *(q+1) == '{' )
+        {
+            char * q2;
+            *p = q+1;
+            q2 = pStr + pMatches[ *p - pStr ];
+            assert( **p == '{' && *q2 == '}' );
+            for ( nVars = 0, (*p)++; *p < q2; (*p)++, nVars++ )
+                Fanins[nVars] = Dau_DsdToGia_rec( pGia, pStr, p, pMatches, pLits, vCover );
+            assert( *p == q2 );
+            pLits2 = Fanins;
+        }
+        else
+            pLits2 = pLits;
+        // read MUX
+        *p = pOld;
+        q = pStr + pMatches[ *p - pStr ];
+        assert( **p == '<' && *q == '>' );
+        // verify internal variables
+        if ( nVars )
+            for ( ; pOld < q; pOld++ )
+                if ( *pOld >= 'a' && *pOld <= 'z' )
+                    assert( *pOld - 'a' < nVars );
+        // derive MUX components
+        for ( (*p)++; *p < q; (*p)++ )
+            *pTemp++ = Dau_DsdToGia_rec( pGia, pStr, p, pMatches, pLits2, vCover );
+        assert( pTemp == Temp + 3 );
+        assert( *p == q );
+        if ( *(q+1) == '{' ) // and/or
+        {
+            char * q = pStr + pMatches[ ++(*p) - pStr ];
+            assert( **p == '{' && *q == '}' );
+            *p = q;
+        }
+        if ( pGia->pMuxes )
+            Res = Gia_ManHashMuxReal( pGia, Temp[0], Temp[1], Temp[2] );
+        else
+            Res = Gia_ManHashMux( pGia, Temp[0], Temp[1], Temp[2] );
+        pObj = Gia_ManObj(pGia, Abc_Lit2Var(Res));
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            if ( pGia->pMuxes )
+                Gia_ObjSetMuxLevel( pGia, pObj );
+            else 
+            {
+                if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) )
+                    Gia_ObjSetAndLevel( pGia, Gia_ObjFanin0(pObj) );
+                if ( Gia_ObjIsAnd(Gia_ObjFanin1(pObj)) )
+                    Gia_ObjSetAndLevel( pGia, Gia_ObjFanin1(pObj) );
+                Gia_ObjSetAndLevel( pGia, pObj );
+            }
+        }
+        return Abc_LitNotCond( Res, fCompl );
+    }
+    if ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') )
+    {
+        Vec_Int_t vLeaves;  char * q;
+        word pFunc[DAU_DSD_MAX_VAR > 6 ? (1 << (DAU_DSD_MAX_VAR-6)) : 1];
+        int Fanins[DAU_DSD_MAX_VAR], Res, nObjOld; 
+        int i, nVars = Abc_TtReadHex( pFunc, *p );
+        *p += Abc_TtHexDigitNum( nVars );
+        q = pStr + pMatches[ *p - pStr ];
+        assert( **p == '{' && *q == '}' );
+        for ( i = 0, (*p)++; *p < q; (*p)++, i++ )
+            Fanins[i] = Dau_DsdToGia_rec( pGia, pStr, p, pMatches, pLits, vCover );
+        assert( i == nVars );
+        assert( *p == q );
+        vLeaves.nCap = nVars;
+        vLeaves.nSize = nVars;
+        vLeaves.pArray = Fanins;      
+        nObjOld = Gia_ManObjNum(pGia);
+        Res = Kit_TruthToGia( pGia, (unsigned *)pFunc, nVars, vCover, &vLeaves, 1 );
+//        assert( nVars <= 6 );
+//        Res = Dau_DsdToGiaCompose_rec( pGia, pFunc[0], Fanins, nVars );
+        for ( i = nObjOld; i < Gia_ManObjNum(pGia); i++ )
+            Gia_ObjSetGateLevel( pGia, Gia_ManObj(pGia, i) );
+        m_Non1Step++;
+        return Abc_LitNotCond( Res, fCompl );
+    }
+    assert( 0 );
+    return 0;
+}
+int Dau_DsdToGia( Gia_Man_t * pGia, char * p, int * pLits, Vec_Int_t * vCover )
+{
+    int Res;
+    if ( *p == '0' && *(p+1) == 0 )
+        Res = 0;
+    else if ( *p == '1' && *(p+1) == 0 )
+        Res = 1;
+    else
+        Res = Dau_DsdToGia_rec( pGia, p, &p, Dau_DsdComputeMatches(p), pLits, vCover );
+    assert( *++p == 0 );
+    return Res;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Convert TT to GIA via DSD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dsm_ManTruthToGia( void * p, word * pTruth, Vec_Int_t * vLeaves, Vec_Int_t * vCover )
+{
+    int fUseMuxes = 0;
+    int fDelayBalance = 1;
+    Gia_Man_t * pGia = (Gia_Man_t *)p;
+    int nSizeNonDec;
+    char pDsd[1000];
+    m_Calls++;
+    assert( Vec_IntSize(vLeaves) <= DAU_DSD_MAX_VAR );
+    // collect delay information
+    if ( fDelayBalance && fUseMuxes )
+    {
+        int i, iLit, pVarLevels[DAU_DSD_MAX_VAR];
+        Vec_IntForEachEntry( vLeaves, iLit, i )
+            pVarLevels[i] = Gia_ObjLevelId( pGia, Abc_Lit2Var(iLit) );
+        nSizeNonDec = Dau_DsdDecomposeLevel( pTruth, Vec_IntSize(vLeaves), fUseMuxes, 1, pDsd, pVarLevels );
+    }
+    else
+        nSizeNonDec = Dau_DsdDecompose( pTruth, Vec_IntSize(vLeaves), fUseMuxes, 1, pDsd );
+    if ( nSizeNonDec )
+        m_NonDsd++;
+//    printf( "%s\n", pDsd );
+    if ( fDelayBalance )
+        return Dau_DsdToGia( pGia, pDsd, Vec_IntArray(vLeaves), vCover );
+    else
+        return Dau_DsdToGia2( pGia, pDsd, Vec_IntArray(vLeaves), vCover );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Convert TT to GIA via DSD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dsm_ManReportStats()
+{
+    printf( "Calls = %d. NonDSD = %d. Non1Step = %d.\n", m_Calls, m_NonDsd, m_Non1Step );
+    m_Calls = m_NonDsd = m_Non1Step = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs structural hashing on the LUT functions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Dsm_ManDeriveGia( void * pGia, int fUseMuxes )
+{
+    Gia_Man_t * p = (Gia_Man_t *)pGia;
+    Gia_Man_t * pNew, * pTemp;
+    Vec_Int_t * vCover, * vLeaves;
+    Gia_Obj_t * pObj; 
+    int k, i, iLut, iVar;
+    word * pTruth;
+    assert( Gia_ManHasMapping(p) );   
+    // create new manager
+    pNew = Gia_ManStart( 6*Gia_ManObjNum(p)/5 + 100 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    pNew->vLevels = Vec_IntStart( 6*Gia_ManObjNum(p)/5 + 100 );
+    if ( fUseMuxes )
+        pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc );
+    // map primary inputs
+    Gia_ManFillValue(p);
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    // iterate through nodes used in the mapping
+    vLeaves = Vec_IntAlloc( 16 );
+    vCover  = Vec_IntAlloc( 1 << 16 );
+    Gia_ManHashStart( pNew );
+    Gia_ObjComputeTruthTableStart( p, Gia_ManLutSizeMax(p) );
+    Gia_ManForEachLut( p, iLut )
+    {
+        // collect leaves
+        Vec_IntClear( vLeaves );
+        Gia_LutForEachFanin( p, iLut, iVar, k )
+            Vec_IntPush( vLeaves, iVar );
+        pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, iLut), vLeaves );
+        // collect incoming literals
+        Vec_IntClear( vLeaves );
+        Gia_LutForEachFanin( p, iLut, iVar, k )
+            Vec_IntPush( vLeaves, Gia_ManObj(p, iVar)->Value );
+        Gia_ManObj(p, iLut)->Value = Dsm_ManTruthToGia( pNew, pTruth, vLeaves, vCover );
+    }
+    Gia_ObjComputeTruthTableStop( p );
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    Vec_IntFree( vLeaves );
+    Vec_IntFree( vCover );
+/*
+    Gia_ManForEachAnd( pNew, pObj, i )
+    {
+        int iLev  = Gia_ObjLevelId(pNew, i);
+        int iLev0 = Gia_ObjLevelId(pNew, Gia_ObjFaninId0(pObj, i));
+        int iLev1 = Gia_ObjLevelId(pNew, Gia_ObjFaninId1(pObj, i));
+        assert( iLev == 1 + Abc_MaxInt(iLev0, iLev1) );
+    }
+*/
+    // perform cleanup
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dau/dauInt.h b/abc-build/src/opt/dau/dauInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dau/dauInt.h
@@ -0,0 +1,70 @@
+/**CFile****************************************************************
+
+  FileName    [dauInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware unmapping.]
+
+  Synopsis    [Interal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: dauInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__DAU_INT__h
+#define ABC__DAU_INT__h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+#include "misc/vec/vec.h"
+#include "dau.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== zzz.c ==========================================================*/
+ 
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/dau/dauMerge.c b/abc-build/src/opt/dau/dauMerge.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dau/dauMerge.c
@@ -0,0 +1,824 @@
+/**CFile****************************************************************
+
+  FileName    [dauMerge.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware unmapping.]
+
+  Synopsis    [Enumeration of decompositions.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: dauMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dauInt.h"
+#include "misc/util/utilTruth.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    [Substitution storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+typedef struct Dau_Sto_t_ Dau_Sto_t;
+struct Dau_Sto_t_
+{
+    int      iVarUsed;                          // counter of used variables
+    char     pOutput[DAU_MAX_STR];              // storage for reduced function
+    char *   pPosOutput;                        // place in the output
+    char     pStore[DAU_MAX_VAR][DAU_MAX_STR];  // storage for definitions
+    char *   pPosStore[DAU_MAX_VAR];            // place in the store
+};
+
+static inline void Dau_DsdMergeStoreClean( Dau_Sto_t * pS, int nShared )
+{
+    int i;
+    pS->iVarUsed  = nShared;
+    for ( i = 0; i < DAU_MAX_VAR; i++ )
+        pS->pStore[i][0] = 0;
+}
+
+static inline void Dau_DsdMergeStoreCleanOutput( Dau_Sto_t * pS )
+{
+    pS->pPosOutput = pS->pOutput;
+}
+static inline void Dau_DsdMergeStoreAddToOutput( Dau_Sto_t * pS, char * pBeg, char * pEnd )
+{
+    while ( pBeg < pEnd )
+        *pS->pPosOutput++ = *pBeg++;
+}
+static inline void Dau_DsdMergeStoreAddToOutputChar( Dau_Sto_t * pS, char c )
+{
+    *pS->pPosOutput++ = c;
+}
+
+static inline int Dau_DsdMergeStoreStartDef( Dau_Sto_t * pS, char c )
+{
+    pS->pPosStore[pS->iVarUsed] = pS->pStore[pS->iVarUsed];
+    if (c) *pS->pPosStore[pS->iVarUsed]++ = c;
+    return pS->iVarUsed++;
+}
+static inline void Dau_DsdMergeStoreAddToDef( Dau_Sto_t * pS, int New, char * pBeg, char * pEnd )
+{
+    while ( pBeg < pEnd )
+        *pS->pPosStore[New]++ = *pBeg++;
+}
+static inline void Dau_DsdMergeStoreAddToDefChar( Dau_Sto_t * pS, int New, char c )
+{
+    *pS->pPosStore[New]++ = c;
+}
+static inline void Dau_DsdMergeStoreStopDef( Dau_Sto_t * pS, int New, char c )
+{
+    if (c) *pS->pPosStore[New]++ = c;
+    *pS->pPosStore[New]++ = 0;
+}
+
+static inline char Dau_DsdMergeStoreCreateDef( Dau_Sto_t * pS, char * pBeg, char * pEnd )
+{
+    int New = Dau_DsdMergeStoreStartDef( pS, 0 );
+    Dau_DsdMergeStoreAddToDef( pS, New, pBeg, pEnd );
+    Dau_DsdMergeStoreStopDef( pS, New, 0 );
+    return New;
+}
+static inline void Dau_DsdMergeStorePrintDefs( Dau_Sto_t * pS )
+{
+    int i;
+    for ( i = 0; i < DAU_MAX_VAR; i++ )
+        if ( pS->pStore[i][0] )
+            printf( "%c = %s\n", 'a' + i, pS->pStore[i] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates local copy.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Dau_DsdMergeCopy( char * pDsd, int fCompl, char * pRes )
+{
+    if ( fCompl && pDsd[0] == '!' )
+        fCompl = 0, pDsd++;
+    if ( Dau_DsdIsConst(pDsd) ) // constant
+        pRes[0] = (fCompl ? (char)((int)pDsd[0] ^ 1) : pDsd[0]), pRes[1] = 0;
+    else
+        sprintf( pRes, "%s%s", fCompl ? "!" : "", pDsd );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces variables according to the mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Dau_DsdMergeReplace( char * pDsd, int * pMatches, int * pMap )
+{
+    int i;
+    for ( i = 0; pDsd[i]; i++ )
+    {
+        // skip non-DSD block
+        if ( pDsd[i] == '<' && pDsd[pMatches[i]+1] == '{' )
+            i = pMatches[i] + 1;
+        if ( (pDsd[i] >= 'A' && pDsd[i] <= 'F') || (pDsd[i] >= '0' && pDsd[i] <= '9') )
+            while ( (pDsd[i] >= 'A' && pDsd[i] <= 'F') || (pDsd[i] >= '0' && pDsd[i] <= '9') )
+                i++;
+        // detect variables
+        if ( pDsd[i] >= 'a' && pDsd[i] <= 'z' )
+            pDsd[i] = 'a' + pMap[ pDsd[i] - 'a' ];
+    }
+}
+static inline void Dau_DsdMergeMatches( char * pDsd, int * pMatches )
+{
+    int pNested[DAU_MAX_VAR];
+    int i, nNested = 0;
+    for ( i = 0; pDsd[i]; i++ )
+    {
+        pMatches[i] = 0;
+        if ( pDsd[i] == '(' || pDsd[i] == '[' || pDsd[i] == '<' || pDsd[i] == '{' )
+            pNested[nNested++] = i;
+        else if ( pDsd[i] == ')' || pDsd[i] == ']' || pDsd[i] == '>' || pDsd[i] == '}' )
+            pMatches[pNested[--nNested]] = i;
+        assert( nNested < DAU_MAX_VAR );
+    }
+    assert( nNested == 0 );
+}
+static inline void Dau_DsdMergeVarPres( char * pDsd, int * pMatches, int * pPres, int Mask )
+{
+    int i;
+    for ( i = 0; pDsd[i]; i++ )
+    {
+        // skip non-DSD block
+        if ( pDsd[i] == '<' && pDsd[pMatches[i]+1] == '{' )
+            i = pMatches[i] + 1;
+        if ( (pDsd[i] >= 'A' && pDsd[i] <= 'F') || (pDsd[i] >= '0' && pDsd[i] <= '9') )
+            while ( (pDsd[i] >= 'A' && pDsd[i] <= 'F') || (pDsd[i] >= '0' && pDsd[i] <= '9') )
+                i++;
+        // skip non-variables
+        if ( !(pDsd[i] >= 'a' && pDsd[i] <= 'z') )
+            continue;
+        // record the mask
+        assert( pDsd[i]-'a' < DAU_MAX_VAR );
+        pPres[pDsd[i]-'a'] |= Mask;
+    }
+}
+static inline int Dau_DsdMergeCountShared( int * pPres, int Mask )
+{
+    int i, Counter = 0;
+    for ( i = 0; i < DAU_MAX_VAR; i++ )
+        Counter += (pPres[i] == Mask);
+    return Counter;
+}
+static inline int Dau_DsdMergeFindShared( char * pDsd0, char * pDsd1, int * pMatches0, int * pMatches1, int * pVarPres )
+{
+    memset( pVarPres, 0, sizeof(int)*DAU_MAX_VAR );
+    Dau_DsdMergeVarPres( pDsd0, pMatches0, pVarPres, 1 );
+    Dau_DsdMergeVarPres( pDsd1, pMatches1, pVarPres, 2 );
+    return Dau_DsdMergeCountShared( pVarPres, 3 );
+}
+static inline int Dau_DsdMergeCreateMaps( int * pVarPres, int nShared, int * pOld2New, int * pNew2Old )
+{
+    int i, Counter = 0, Counter2 = nShared;
+    for ( i = 0; i < DAU_MAX_VAR; i++ )
+    {
+        if ( pVarPres[i] == 0 )
+            continue;
+        if ( pVarPres[i] == 3 )
+        {
+            pOld2New[i] = Counter;
+            pNew2Old[Counter] = i;
+            Counter++;
+            continue;
+        }
+        assert( pVarPres[i] == 1 || pVarPres[i] == 2 );
+        pOld2New[i] = Counter2;
+        pNew2Old[Counter2] = i;
+        Counter2++;
+    }
+    return Counter2;
+}
+static inline void Dau_DsdMergeInlineDefinitions( char * pDsd, int * pMatches, Dau_Sto_t * pS, char * pRes, int nShared )
+{
+    int i;
+    char * pDef;
+    char * pBegin = pRes;
+    for ( i = 0; pDsd[i]; i++ )
+    {
+        // skip non-DSD block
+        if ( pDsd[i] == '<' && pDsd[pMatches[i]+1] == '{' )
+        {
+            assert( pDsd[pMatches[i]] == '>' );
+            for ( ; i <= pMatches[i]; i++ )
+                *pRes++ = pDsd[i];
+        }
+        if ( (pDsd[i] >= 'A' && pDsd[i] <= 'F') || (pDsd[i] >= '0' && pDsd[i] <= '9') )
+            while ( (pDsd[i] >= 'A' && pDsd[i] <= 'F') || (pDsd[i] >= '0' && pDsd[i] <= '9') )
+                *pRes++ = pDsd[i++];
+        // detect variables
+        if ( !(pDsd[i] >= 'a' && pDsd[i] <= 'z') || (pDsd[i] - 'a' < nShared) )
+        {
+            *pRes++ = pDsd[i];
+            continue;
+        }
+        // inline definition
+        assert( pDsd[i]-'a' < DAU_MAX_STR );
+        for ( pDef = pS->pStore[pDsd[i]-'a']; *pDef; pDef++ )
+            *pRes++ = *pDef;
+    }
+    *pRes++ = 0;
+    assert( pRes - pBegin < DAU_MAX_STR );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes independence status for each opening paranthesis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Dau_DsdMergePrintWithStatus( char * p, int * pStatus )
+{
+    int i;
+    printf( "%s\n", p );
+    for ( i = 0; p[i]; i++ )
+        if ( !(p[i] == '(' || p[i] == '[' || p[i] == '<' || p[i] == '{' || (p[i] >= 'a' && p[i] <= 'z')) )
+            printf( " " );
+        else if ( pStatus[i] >= 0 )
+            printf( "%d", pStatus[i] );
+        else
+            printf( "-" );
+    printf( "\n" );
+}
+int Dau_DsdMergeStatus_rec( char * pStr, char ** p, int * pMatches, int nShared, int * pStatus )
+{
+    // none pure
+    // 1 one pure
+    // 2 two or more pure
+    // 3 all pure
+    if ( **p == '!' )
+    {
+        pStatus[*p - pStr] = -1;
+        (*p)++;
+    }
+    while ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') )
+    {
+        pStatus[*p - pStr] = -1;
+        (*p)++;
+    }
+    if ( **p == '<' )
+    {
+        char * q = pStr + pMatches[ *p - pStr ];
+        if ( *(q+1) == '{' )
+        {
+            char * pTemp = *p;
+            *p = q+1;
+            for ( ; pTemp < q+1; pTemp++ )
+                pStatus[pTemp - pStr] = -1;
+        }
+    }
+    if ( **p >= 'a' && **p <= 'z' ) // var
+        return pStatus[*p - pStr] = (**p - 'a' < nShared) ? 0 : 3;
+    if ( **p == '(' || **p == '[' || **p == '<' || **p == '{' ) // and/or/xor
+    {
+        int Status, nPure = 0, nTotal = 0;
+        char * pOld = *p;
+        char * q = pStr + pMatches[ *p - pStr ];
+        assert( *q == **p + 1 + (**p != '(') );
+        for ( (*p)++; *p < q; (*p)++ )
+        {
+            Status = Dau_DsdMergeStatus_rec( pStr, p, pMatches, nShared, pStatus );
+            nPure += (Status == 3);
+            nTotal++;
+        }
+        assert( *p == q );
+        assert( nTotal > 1 );
+        if ( nPure == 0 )
+            Status = 0;
+        else if ( nPure == 1 )
+            Status = 1;
+        else if ( nPure < nTotal )
+            Status = 2;
+        else if ( nPure == nTotal ) 
+            Status = 3;
+        else assert( 0 );
+        return (pStatus[pOld - pStr] = Status);
+    }
+    assert( 0 );
+    return 0;
+}
+static inline int Dau_DsdMergeStatus( char * pDsd, int * pMatches, int nShared, int * pStatus )
+{
+    return Dau_DsdMergeStatus_rec( pDsd, &pDsd, pMatches, nShared, pStatus );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Extracts the formula.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Dau_DsdMergeGetStatus( char * pBeg, char * pStr, int * pMatches, int * pStatus )
+{
+    if ( *pBeg == '!' )
+        pBeg++;
+    while ( (*pBeg >= 'A' && *pBeg <= 'F') || (*pBeg >= '0' && *pBeg <= '9') )
+        pBeg++;
+    if ( *pBeg == '<' )
+    {
+        char * q = pStr + pMatches[pBeg - pStr];
+        if ( *(q+1) == '{' )
+            pBeg = q+1;
+    }
+    return pStatus[pBeg - pStr];
+}
+void Dau_DsdMergeSubstitute_rec( Dau_Sto_t * pS, char * pStr, char ** p, int * pMatches, int * pStatus, int fWrite )
+{
+//    assert( **p != '!' );
+
+    if ( **p == '!' )
+    {
+        if ( fWrite )
+            Dau_DsdMergeStoreAddToOutputChar( pS, **p );
+        (*p)++;
+    }
+
+    while ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') )
+    {
+        if ( fWrite )
+            Dau_DsdMergeStoreAddToOutputChar( pS, **p );
+        (*p)++;
+    }
+    if ( **p == '<' )
+    {
+        char * q = pStr + pMatches[ *p - pStr ];
+        if ( *(q+1) == '{' )
+        {
+            char * pTemp = *p;
+            *p = q+1;
+            if ( fWrite )
+                for ( ; pTemp < q+1; pTemp++ )
+                    Dau_DsdMergeStoreAddToOutputChar( pS, *pTemp );
+        }
+    }
+    if ( **p >= 'a' && **p <= 'z' ) // var
+    {
+        if ( fWrite )
+            Dau_DsdMergeStoreAddToOutputChar( pS, **p );
+        return;
+    }
+    if ( **p == '(' || **p == '[' || **p == '<' || **p == '{' ) // and/or/xor
+    {
+        int New, StatusFan, Status = pStatus[*p - pStr];
+        char * pBeg, * q = pStr + pMatches[ *p - pStr ];
+        assert( *q == **p + 1 + (**p != '(') );
+        if ( !fWrite )
+        {
+             assert( Status == 3 );
+             *p = q;
+             return;
+        }
+        assert( Status != 3 );
+        if ( Status == 0 ) // none pure
+        {
+            Dau_DsdMergeStoreAddToOutputChar( pS, **p );
+            for ( (*p)++; *p < q; (*p)++ )
+            {
+                if ( **p == '!' )
+                {
+                    Dau_DsdMergeStoreAddToOutputChar( pS, '!' );
+                    (*p)++;
+                }
+                Dau_DsdMergeSubstitute_rec( pS, pStr, p, pMatches, pStatus, 1 );
+            }
+            Dau_DsdMergeStoreAddToOutputChar( pS, **p );
+            assert( *p == q );
+            return;
+        }
+        if ( Status == 1 || **p == '<' || **p == '{' ) // 1 pure
+        {
+            Dau_DsdMergeStoreAddToOutputChar( pS, **p );
+            for ( (*p)++; *p < q; (*p)++ )
+            {
+                if ( **p == '!' )
+                {
+                    Dau_DsdMergeStoreAddToOutputChar( pS, '!' );
+                    (*p)++;
+                }
+                pBeg = *p;
+                StatusFan = Dau_DsdMergeGetStatus( pBeg, pStr, pMatches, pStatus );
+                Dau_DsdMergeSubstitute_rec( pS, pStr, p, pMatches, pStatus, StatusFan != 3 );
+                if ( StatusFan == 3 )
+                {
+                    int New = Dau_DsdMergeStoreCreateDef( pS, pBeg, *p+1 );
+                    Dau_DsdMergeStoreAddToOutputChar( pS, (char)('a' + New) );
+                }
+            }
+            Dau_DsdMergeStoreAddToOutputChar( pS, **p );
+            assert( *p == q );
+            return;
+        }
+        if ( Status == 2 )
+        {
+            // add more than one defs
+            Dau_DsdMergeStoreAddToOutputChar( pS, **p );
+            New = Dau_DsdMergeStoreStartDef( pS, **p );
+            for ( (*p)++; *p < q; (*p)++ )
+            {
+                pBeg = *p;
+                StatusFan = Dau_DsdMergeGetStatus( pBeg, pStr, pMatches, pStatus );
+                if ( **p == '!' )
+                {
+                    if ( StatusFan != 3 )
+                        Dau_DsdMergeStoreAddToOutputChar( pS, '!' );
+                    else
+                        Dau_DsdMergeStoreAddToDefChar( pS, New, '!' );
+                    (*p)++;
+                    pBeg++;
+                }
+                Dau_DsdMergeSubstitute_rec( pS, pStr, p, pMatches, pStatus, StatusFan != 3 );
+                if ( StatusFan == 3 )
+                    Dau_DsdMergeStoreAddToDef( pS, New, pBeg, *p+1 );
+            }
+            Dau_DsdMergeStoreStopDef( pS, New, *q );
+            Dau_DsdMergeStoreAddToOutputChar( pS, (char)('a' + New) );
+            Dau_DsdMergeStoreAddToOutputChar( pS, **p );
+            return;
+        }
+        assert( 0 );
+        return;
+    }
+    assert( 0 );
+}
+static inline void Dau_DsdMergeSubstitute( Dau_Sto_t * pS, char * pDsd, int * pMatches, int * pStatus )
+{
+/*
+    int fCompl = 0;
+    if ( pDsd[0] == '!' )
+    {
+        Dau_DsdMergeStoreAddToOutputChar( pS, '!' );
+        pDsd++;
+        fCompl = 1;
+    }
+*/
+    Dau_DsdMergeSubstitute_rec( pS, pDsd, &pDsd, pMatches, pStatus, 1 );
+    Dau_DsdMergeStoreAddToOutputChar( pS, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes braces.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dau_DsdRemoveBraces_rec( char * pStr, char ** p, int * pMatches )
+{
+    if ( **p == '!' )
+        (*p)++;
+    while ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') )
+        (*p)++;
+    if ( **p == '<' )
+    {
+        char * q = pStr + pMatches[*p - pStr];
+        if ( *(q+1) == '{' )
+            *p = q+1;
+    }
+    if ( **p >= 'a' && **p <= 'z' ) // var
+        return;
+    if ( **p == '(' || **p == '[' || **p == '<' || **p == '{' ) 
+    {
+        char * q = pStr + pMatches[ *p - pStr ];
+        assert( *q == **p + 1 + (**p != '(') );
+        for ( (*p)++; *p < q; (*p)++ )
+        {
+            int fCompl = (**p == '!');
+            char * pBeg = fCompl ? *p + 1 : *p;
+            Dau_DsdRemoveBraces_rec( pStr, p, pMatches );
+            if ( (!fCompl && *pBeg == '(' && *q == ')') || (*pBeg == '[' && *q == ']') )
+            {
+                assert( **p == ')' || **p == ']' );
+                *pBeg = **p = ' ';
+            }
+        }
+        assert( *p == q );
+        return;
+    }
+    assert( 0 );
+}
+void Dau_DsdRemoveBraces( char * pDsd, int * pMatches )
+{
+    char * q, * p = pDsd;
+    if ( pDsd[1] == 0 )
+        return;
+    Dau_DsdRemoveBraces_rec( pDsd, &pDsd, pMatches );
+    for ( q = p; *p; p++ )
+        if ( *p != ' ' )
+        {
+            if ( *p == '!' && *(q-1) == '!' && p != q )
+            {
+                q--;
+                continue;
+            }
+            *q++ = *p;
+        }
+    *q = 0;
+}
+
+
+abctime s_TimeComp[4] = {0};
+
+/**Function*************************************************************
+
+  Synopsis    [Performs merging of two DSD formulas.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Dau_DsdMerge( char * pDsd0i, int * pPerm0, char * pDsd1i, int * pPerm1, int fCompl0, int fCompl1, int nVars )
+{
+    int fVerbose = 0;
+    int fCheck = 0;
+    static int Counter = 0;
+    static char pRes[DAU_MAX_STR];
+    char pDsd0[DAU_MAX_STR];
+    char pDsd1[DAU_MAX_STR];
+    int pMatches0[DAU_MAX_STR];
+    int pMatches1[DAU_MAX_STR];
+    int pVarPres[DAU_MAX_VAR];
+    int pOld2New[DAU_MAX_VAR];
+    int pNew2Old[DAU_MAX_VAR];
+    int pStatus0[DAU_MAX_STR];
+    int pStatus1[DAU_MAX_STR];
+    int pMatches[DAU_MAX_STR];
+    int nVarsShared, nVarsTotal;
+    Dau_Sto_t S, * pS = &S;
+    word * pTruth, * pt = NULL, * pt0 = NULL, * pt1 = NULL;
+    word pParts[3][DAU_MAX_WORD];
+    int Status;
+    abctime clk = Abc_Clock();
+    Counter++;
+    // create local copies
+    Dau_DsdMergeCopy( pDsd0i, fCompl0, pDsd0 );
+    Dau_DsdMergeCopy( pDsd1i, fCompl1, pDsd1 );
+if ( fVerbose )
+printf( "\nAfter copying:\n" );
+if ( fVerbose )
+printf( "%s\n", pDsd0 );
+if ( fVerbose )
+printf( "%s\n", pDsd1 );
+    // handle constants
+    if ( Dau_DsdIsConst(pDsd0) || Dau_DsdIsConst(pDsd1) )
+    {
+        if ( Dau_DsdIsConst0(pDsd0) )
+            strcpy( pRes, pDsd0 );
+        else if ( Dau_DsdIsConst1(pDsd0) )
+            strcpy( pRes, pDsd1 );
+        else if ( Dau_DsdIsConst0(pDsd1) )
+            strcpy( pRes, pDsd1 );
+        else if ( Dau_DsdIsConst1(pDsd1) )
+            strcpy( pRes, pDsd0 );
+        else assert( 0 );
+        return pRes;
+    }
+
+    // compute matches
+    Dau_DsdMergeMatches( pDsd0, pMatches0 );
+    Dau_DsdMergeMatches( pDsd1, pMatches1 );
+    // implement permutation
+    Dau_DsdMergeReplace( pDsd0, pMatches0, pPerm0 );
+    Dau_DsdMergeReplace( pDsd1, pMatches1, pPerm1 );
+if ( fVerbose )
+printf( "After replacement:\n" );
+if ( fVerbose )
+printf( "%s\n", pDsd0 );
+if ( fVerbose )
+printf( "%s\n", pDsd1 );
+
+
+    if ( fCheck )
+    {
+        pt0 = Dau_DsdToTruth( pDsd0, nVars );
+        Abc_TtCopy( pParts[0], pt0, Abc_TtWordNum(nVars), 0 );
+    }
+    if ( fCheck )
+    {
+        pt1 = Dau_DsdToTruth( pDsd1, nVars );
+        Abc_TtCopy( pParts[1], pt1, Abc_TtWordNum(nVars), 0 );
+        Abc_TtAnd( pParts[2], pParts[0], pParts[1], Abc_TtWordNum(nVars), 0 );
+    }
+
+    // find shared varaiables
+    nVarsShared = Dau_DsdMergeFindShared(pDsd0, pDsd1, pMatches0, pMatches1, pVarPres);
+    if ( nVarsShared == 0 )
+    {
+        sprintf( pRes, "(%s%s)", pDsd0, pDsd1 );
+if ( fVerbose )
+printf( "Disjoint:\n" );
+if ( fVerbose )
+printf( "%s\n", pRes );
+
+        Dau_DsdMergeMatches( pRes, pMatches );
+        Dau_DsdRemoveBraces( pRes, pMatches );
+        Dau_DsdNormalize( pRes );
+if ( fVerbose )
+printf( "Normalized:\n" );
+if ( fVerbose )
+printf( "%s\n", pRes );
+
+        s_TimeComp[0] += Abc_Clock() - clk;
+        return pRes;
+    }
+s_TimeComp[3] += Abc_Clock() - clk;
+    // create variable mapping
+    nVarsTotal = Dau_DsdMergeCreateMaps( pVarPres, nVarsShared, pOld2New, pNew2Old );
+    // perform variable replacement
+    Dau_DsdMergeReplace( pDsd0, pMatches0, pOld2New );
+    Dau_DsdMergeReplace( pDsd1, pMatches1, pOld2New );
+    // find uniqueness status
+    Dau_DsdMergeStatus( pDsd0, pMatches0, nVarsShared, pStatus0 );
+    Dau_DsdMergeStatus( pDsd1, pMatches1, nVarsShared, pStatus1 );
+if ( fVerbose )
+printf( "Individual status:\n" );
+if ( fVerbose )
+Dau_DsdMergePrintWithStatus( pDsd0, pStatus0 );
+if ( fVerbose )
+Dau_DsdMergePrintWithStatus( pDsd1, pStatus1 );
+    // prepare storage
+    Dau_DsdMergeStoreClean( pS, nVarsShared );
+    // perform substitutions
+    Dau_DsdMergeStoreCleanOutput( pS );
+    Dau_DsdMergeSubstitute( pS, pDsd0, pMatches0, pStatus0 );
+    strcpy( pDsd0, pS->pOutput );
+if ( fVerbose )
+printf( "Substitutions:\n" );
+if ( fVerbose )
+printf( "%s\n", pDsd0 );
+
+    // perform substitutions
+    Dau_DsdMergeStoreCleanOutput( pS );
+    Dau_DsdMergeSubstitute( pS, pDsd1, pMatches1, pStatus1 );
+    strcpy( pDsd1, pS->pOutput );
+if ( fVerbose )
+printf( "%s\n", pDsd1 );
+if ( fVerbose )
+Dau_DsdMergeStorePrintDefs( pS );
+
+    // create new function
+//    assert( nVarsTotal <= 6 );
+    sprintf( pS->pOutput, "(%s%s)", pDsd0, pDsd1 );
+    pTruth = Dau_DsdToTruth( pS->pOutput, nVarsTotal );
+    Status = Dau_DsdDecompose( pTruth, nVarsTotal, 0, 1, pS->pOutput );
+//printf( "%d ", Status );
+    if ( Status == -1 ) // did not find 1-step DSD
+        return NULL;
+//    if ( Status > 6 ) // non-DSD part is too large
+//        return NULL;
+    if ( Dau_DsdIsConst(pS->pOutput) )
+    {
+        strcpy( pRes, pS->pOutput );
+        return pRes;
+    }
+if ( fVerbose )
+printf( "Decomposition:\n" );
+if ( fVerbose )
+printf( "%s\n", pS->pOutput );
+    // substitute definitions
+    Dau_DsdMergeMatches( pS->pOutput, pMatches );
+    Dau_DsdMergeInlineDefinitions( pS->pOutput, pMatches, pS, pRes, nVarsShared );
+if ( fVerbose )
+printf( "Inlining:\n" );
+if ( fVerbose )
+printf( "%s\n", pRes );
+    // perform variable replacement
+    Dau_DsdMergeMatches( pRes, pMatches );
+    Dau_DsdMergeReplace( pRes, pMatches, pNew2Old );
+    Dau_DsdRemoveBraces( pRes, pMatches );
+if ( fVerbose )
+printf( "Replaced:\n" );
+if ( fVerbose )
+printf( "%s\n", pRes );
+    Dau_DsdNormalize( pRes );
+if ( fVerbose )
+printf( "Normalized:\n" );
+if ( fVerbose )
+printf( "%s\n", pRes );
+
+    if ( fCheck )
+    {
+        pt = Dau_DsdToTruth( pRes, nVars );
+        if ( !Abc_TtEqual( pParts[2], pt, Abc_TtWordNum(nVars) ) )
+            printf( "Dau_DsdMerge(): Verification failed!\n" );
+    }
+
+    if ( Status == 0 )
+        s_TimeComp[1] += Abc_Clock() - clk;
+    else
+        s_TimeComp[2] += Abc_Clock() - clk;
+    return pRes;
+}
+
+
+void Dau_DsdTest66()
+{
+    int Perm0[DAU_MAX_VAR] = { 0, 1, 2, 3, 4, 5 };
+//    int pMatches[DAU_MAX_STR];
+//    int pStatus[DAU_MAX_STR];
+
+//    char * pStr = "(!(!a<bcd>)!(!fe))";
+//    char * pStr = "([acb]<!edf>)";
+//    char * pStr = "!(f!(b!c!(d[ea])))";
+    char * pStr = "[!(a[be])!(c!df)]";
+//    char * pStr = "<(e<bca>)fd>";
+//    char * pStr = "[d8001{abef}c]";
+//    char * pStr1 = "(abc)";
+//    char * pStr2 = "[adf]";
+//    char * pStr1 = "(!abce)";
+//    char * pStr2 = "[adf!b]";
+//    char * pStr1 = "(!abc)";
+//    char * pStr2 = "[ab]";
+//    char * pStr1 = "[d81{abe}c]";
+//    char * pStr1 = "[d<a(bc)(!b!c)>{abe}c]";
+//    char * pStr1 = "[d81{abe}c]";
+//    char * pStr1 = "[d(a[be])c]";
+//    char * pStr2 = "(df)";
+//    char * pStr1 = "(abf)";
+//    char * pStr2 = "(a[(bc)(fde)])";
+//    char * pStr1 = "8001{abc[ef]}";
+//    char * pStr2 = "(abe)";
+
+    char * pStr1 = "(!(ab)de)";
+    char * pStr2 = "(!(ac)f)";
+
+    char * pRes;
+    word t = Dau_Dsd6ToTruth( pStr );
+    return;
+
+//    pStr2 = Dau_DsdDecompose( &t, 6, 0, NULL );
+//    Dau_DsdNormalize( pStr2 );
+
+//    Dau_DsdMergeMatches( pStr, pMatches );
+//    Dau_DsdMergeStatus( pStr, pMatches, 2, pStatus );
+//    Dau_DsdMergePrintWithStatus( pStr, pStatus );
+
+    pRes = Dau_DsdMerge( pStr1, Perm0, pStr2, Perm0, 0, 0, 6 );
+
+    t = 0; 
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dau/dauNonDsd.c b/abc-build/src/opt/dau/dauNonDsd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dau/dauNonDsd.c
@@ -0,0 +1,903 @@
+/**CFile****************************************************************
+
+  FileName    [dauNonDsd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware unmapping.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: dauNonDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dauInt.h"
+#include "misc/util/utilTruth.h"
+#include "misc/extra/extra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    [Checks decomposability with given variable set.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dau_DecCheckSetTop5( word * p, int nVars, int nVarsF, int nVarsB, int nVarsS, int uMaskS, int * pSched, word * pDec, word * pComp )
+{
+    word Cof[2][64], Value;
+    word MaskFF = (((word)1) << (1 << nVarsF)) - 1;
+    int ShiftF = 6 - nVarsF, MaskF = (1 << ShiftF) - 1;
+    int pVarsS[16], pVarsB[16];
+    int nMints  = (1 << nVarsB);
+    int nMintsB = (1 <<(nVarsB-nVarsS));
+    int nMintsS = (1 << nVarsS);
+    int s, b, v, m, Mint, MintB, MintS;
+    assert( nVars == nVarsB + nVarsF );
+    assert( nVars <= 16 );
+    assert( nVarsS <= 6 );
+    assert( nVarsF >= 1 && nVarsF <= 5 );
+    // collect bound/shared variables
+    for ( s = b = v = 0; v < nVarsB; v++ )
+        if ( (uMaskS >> v) & 1 )
+            pVarsB[v] = -1, pVarsS[v] = s++;
+        else
+            pVarsS[v] = -1, pVarsB[v] = b++;
+    assert( s == nVarsS );
+    assert( b == nVarsB-nVarsS );
+    // clean minterm storage
+    for ( s = 0; s < nMintsS; s++ )
+        Cof[0][s] = Cof[1][s] = ~(word)0;
+    // iterate through bound set minters
+    for ( MintS = MintB = Mint = m = 0; m < nMints; m++ )
+    {
+        // find minterm value
+        Value = (p[Mint>>ShiftF] >> ((Mint&MaskF)<<nVarsF)) & MaskFF;
+        // check if this cof already appeared 
+        if ( !~Cof[0][MintS] || Cof[0][MintS] == Value )
+            Cof[0][MintS] = Value;
+        else if ( !~Cof[1][MintS] || Cof[1][MintS] == Value )
+        {
+            Cof[1][MintS] = Value;
+            if ( pDec ) 
+            {
+                int iMintB = MintS * nMintsB + MintB;
+                pDec[iMintB>>6] |= (((word)1)<<(iMintB & 63));     
+            }
+        }
+        else
+            return 0;            
+        // find next minterm
+        v = pSched[m];
+        Mint ^= (1 << v);
+        if ( (uMaskS >> v) & 1 ) // shared variable
+            MintS ^= (1 << pVarsS[v]);
+        else
+            MintB ^= (1 << pVarsB[v]);
+    }
+    // create composition function
+    if ( pComp )
+    {
+        for ( s = 0; s < nMintsS; s++ )
+        {
+            pComp[s>>ShiftF] |= (Cof[0][s] << ((s&MaskF) << nVarsF));
+            if ( ~Cof[1][s] ) 
+                pComp[(s+nMintsS)>>ShiftF] |= (Cof[1][s] << (((s+nMintsS)&MaskF) << nVarsF));
+            else
+                pComp[(s+nMintsS)>>ShiftF] |= (Cof[0][s] << (((s+nMintsS)&MaskF) << nVarsF));
+        }
+        if ( nVarsF + nVarsS + 1 < 6 )
+            pComp[0] = Abc_Tt6Stretch( pComp[0], nVarsF + nVarsS + 1 );
+    }
+    if ( pDec && nVarsB < 6 )
+        pDec[0] = Abc_Tt6Stretch( pDec[0], nVarsB );
+    return 1;
+}
+int Dau_DecCheckSetTop6( word * p, int nVars, int nVarsF, int nVarsB, int nVarsS, int uMaskS, int * pSched, word * pDec, word * pComp )
+{
+    word * Cof[2][64];
+    int nWordsF = Abc_TtWordNum(nVarsF); 
+    int pVarsS[16], pVarsB[16];
+    int nMints  = (1 << nVarsB);
+    int nMintsB = (1 <<(nVarsB-nVarsS));
+    int nMintsS = (1 << nVarsS);
+    int s, b, v, m, Mint, MintB, MintS;
+    assert( nVars == nVarsB + nVarsF );
+    assert( nVars <= 16 );
+    assert( nVarsS <= 6 );
+    assert( nVarsF >= 6 );
+    // collect bound/shared variables
+    for ( s = b = v = 0; v < nVarsB; v++ )
+        if ( (uMaskS >> v) & 1 )
+            pVarsB[v] = -1, pVarsS[v] = s++;
+        else
+            pVarsS[v] = -1, pVarsB[v] = b++;
+    assert( s == nVarsS );
+    assert( b == nVarsB-nVarsS );
+    // clean minterm storage
+    for ( s = 0; s < nMintsS; s++ )
+        Cof[0][s] = Cof[1][s] = NULL;
+    // iterate through bound set minters
+    for ( MintS = MintB = Mint = m = 0; m < nMints; m++ )
+    {
+        // check if this cof already appeared 
+        if ( !Cof[0][MintS] || !memcmp(Cof[0][MintS], p + Mint * nWordsF, sizeof(word) * nWordsF) )
+            Cof[0][MintS] = p + Mint * nWordsF;
+        else if ( !Cof[1][MintS] || !memcmp(Cof[1][MintS], p + Mint * nWordsF, sizeof(word) * nWordsF) )
+        {
+            Cof[1][MintS] = p + Mint * nWordsF;
+            if ( pDec ) 
+            {
+                int iMintB = MintS * nMintsB + MintB;
+                pDec[iMintB>>6] |= (((word)1)<<(iMintB & 63));     
+            }
+        }
+        else
+            return 0;            
+        // find next minterm
+        v = pSched[m];
+        Mint ^= (1 << v);
+        if ( (uMaskS >> v) & 1 ) // shared variable
+            MintS ^= (1 << pVarsS[v]);
+        else
+            MintB ^= (1 << pVarsB[v]);
+    }
+    // create composition function
+    if ( pComp )
+    {
+        for ( s = 0; s < nMintsS; s++ )
+        {
+            memcpy( pComp + s * nWordsF, Cof[0][s], sizeof(word) * nWordsF );
+            if ( Cof[1][s] ) 
+                memcpy( pComp + (s+nMintsS) * nWordsF, Cof[1][s], sizeof(word) * nWordsF );
+            else
+                memcpy( pComp + (s+nMintsS) * nWordsF, Cof[0][s], sizeof(word) * nWordsF );
+        }
+    }
+    if ( pDec && nVarsB < 6 )
+        pDec[0] = Abc_Tt6Stretch( pDec[0], nVarsB );
+    return 1;
+}
+static inline int Dau_DecCheckSetTop( word * p, int nVars, int nVarsF, int nVarsB, int nVarsS, int uMaskS, int * pSched, word * pDec, word * pComp )
+{
+    if ( nVarsF < 6 )
+        return Dau_DecCheckSetTop5( p, nVars, nVarsF, nVarsB, nVarsS, uMaskS, pSched, pDec, pComp );
+    else
+        return Dau_DecCheckSetTop6( p, nVars, nVarsF, nVarsB, nVarsS, uMaskS, pSched, pDec, pComp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks decomposability with given BS variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Dau_DecGetMinterm( word * p, int g, int nVarsS, int uMaskAll )
+{
+    int m, c, v;
+    for ( m = c = v = 0; v < nVarsS; v++ )
+        if ( !((uMaskAll >> v) & 1) ) // not shared bound set variable
+        {
+            if ( (g >> v) & 1 )
+                m |= (1 << c);
+            c++;
+        }
+    assert( c >= 2 );
+    p[m>>6] |= (((word)1)<<(m & 63));                               
+}
+static inline int Dau_DecCheckSet5( word * p, int nVars, int nVarsF, int uMaskAll, int uMaskValue, word * pCof0, word * pCof1, word * pDec )
+{
+    int fFound0 = 0, fFound1 = 0;
+    int g, gMax = (1 << (nVars - nVarsF));
+    int Shift = 6 - nVarsF, Mask = (1 << Shift) - 1;
+    word Mask2 = (((word)1) << (1 << nVarsF)) - 1;
+    word Cof0 = 0, Cof1 = 0, Value;
+    assert( nVarsF >= 1 && nVarsF <= 5 );
+    if ( pDec ) *pDec = 0;
+    for ( g = 0; g < gMax; g++ )
+        if ( (g & uMaskAll) == uMaskValue ) // this minterm g matches shared variable minterm uMaskValue
+        {
+            Value = (p[g>>Shift] >> ((g&Mask)<<nVarsF)) & Mask2;
+            if ( !fFound0 )
+                Cof0 = Value, fFound0 = 1;
+            else if ( Cof0 == Value )
+                continue;
+            else if ( !fFound1 )
+            {
+                Cof1 = Value, fFound1 = 1;
+                if ( pDec ) Dau_DecGetMinterm( pDec, g, nVars-nVarsF, uMaskAll );
+            }
+            else if ( Cof1 == Value )
+            {
+                if ( pDec ) Dau_DecGetMinterm( pDec, g, nVars-nVarsF, uMaskAll );
+                continue;
+            }
+            else
+                return 0;            
+        }
+    if ( pCof0 )
+    {
+        assert( fFound0 );
+        Cof1 = fFound1 ? Cof1 : Cof0;
+        *pCof0 = Abc_Tt6Stretch( Cof0, nVarsF );
+        *pCof1 = Abc_Tt6Stretch( Cof1, nVarsF );
+    }
+    return 1;
+}
+static inline int Dau_DecCheckSet6( word * p, int nVars, int nVarsF, int uMaskAll, int uMaskValue, word * pCof0, word * pCof1, word * pDec )
+{
+    int fFound0 = 0, fFound1 = 0;
+    int g, gMax = (1 << (nVars - nVarsF));
+    int nWords = Abc_TtWordNum(nVarsF);
+    word * Cof0 = NULL, * Cof1 = NULL;
+    assert( nVarsF >= 6 && nVarsF <= nVars - 2 );
+    if ( pDec ) *pDec = 0;
+    for ( g = 0; g < gMax; g++ )
+        if ( (g & uMaskAll) == uMaskValue )
+        {
+            if ( !fFound0 )
+                Cof0 = p + g * nWords, fFound0 = 1;
+            else if ( !memcmp(Cof0, p + g * nWords, sizeof(word) * nWords) )
+                continue;
+            else if ( !fFound1 )
+            {
+                Cof1 = p + g * nWords, fFound1 = 1;
+                if ( pDec ) Dau_DecGetMinterm( pDec, g, nVars-nVarsF, uMaskAll );
+            }
+            else if ( !memcmp(Cof1, p + g * nWords, sizeof(word) * nWords) )
+            {
+                if ( pDec ) Dau_DecGetMinterm( pDec, g, nVars-nVarsF, uMaskAll );
+                continue;
+            }
+            else
+                return 0;            
+        }
+    if ( pCof0 )
+    {
+        assert( fFound0 );
+        Cof1 = fFound1 ? Cof1 : Cof0;
+        memcpy( pCof0, Cof0, sizeof(word) * nWords );
+        memcpy( pCof1, Cof1, sizeof(word) * nWords );
+    }
+    return 1;
+}
+static inline int Dau_DecCheckSetAny( word * p, int nVars, int nVarsF, int uMaskAll, int uMaskValue, word * pCof0, word * pCof1, word * pDec )
+{
+    assert( nVarsF >= 1 && nVarsF <= nVars - 2 );
+    if ( nVarsF < 6 )
+        return Dau_DecCheckSet5( p, nVars, nVarsF, uMaskAll, uMaskValue, pCof0, pCof1, pDec );
+    else
+        return Dau_DecCheckSet6( p, nVars, nVarsF, uMaskAll, uMaskValue, pCof0, pCof1, pDec );
+}
+int Dau_DecCheckSetTopOld( word * p, int nVars, int nVarsF, int nVarsB, int nVarsS, int maskS, word ** pCof0, word ** pCof1, word ** pDec )
+{
+    int i, pVarsS[16];
+    int v, m, mMax = (1 << nVarsS), uMaskValue;
+    assert( nVars >= 3 && nVars <= 16 );
+    assert( nVars == nVarsF + nVarsB );
+    assert( nVarsF >= 1 && nVarsF <= nVars - 2 );
+    assert( nVarsB >= 2 && nVarsB <= nVars - 1 );
+    assert( nVarsS >= 0 && nVarsS <= nVarsB - 2 );
+    if ( nVarsS == 0 )
+        return Dau_DecCheckSetAny( p, nVars, nVarsF, 0, 0, pCof0? pCof0[0] : 0, pCof1? pCof1[0] : 0, pDec? pDec[0] : 0 );
+    // collect shared variables
+    assert( maskS > 0 && maskS < (1 << nVarsB) );
+    for ( i = 0, v = 0; v < nVarsB; v++ )
+        if ( (maskS >> v) & 1 )
+            pVarsS[i++] = v;
+    assert( i == nVarsS );
+    // go through shared set minterms
+    for ( m = 0; m < mMax; m++ )
+    {
+        // generate share set mask
+        uMaskValue = 0;
+        for ( v = 0; v < nVarsS; v++ )
+            if ( (m >> v) & 1 )
+                uMaskValue |= (1 << pVarsS[v]);
+        assert( (maskS & uMaskValue) == uMaskValue );
+        // check decomposition
+        if ( !Dau_DecCheckSetAny( p, nVars, nVarsF, maskS, uMaskValue, pCof0? pCof0[m] : 0, pCof1? pCof1[m] : 0, pDec? pDec[m] : 0 ) )
+            return 0;
+    }
+   return 1;
+}
+ 
+
+/**Function*************************************************************
+
+  Synopsis    [Variable sets.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Dau_DecCreateSet( int * pVarsB, int sizeB, int maskS )
+{
+    unsigned uSet = 0; int v;
+    for ( v = 0; v < sizeB; v++ )
+    {
+        uSet |= (1 <<  (pVarsB[v] << 1));
+        if ( (maskS >> v) & 1 )
+        uSet |= (1 << ((pVarsB[v] << 1)+1));
+    }
+    return uSet;
+}
+static inline int Dau_DecSetHas01( unsigned Mask )
+{
+    return (Mask & ((~Mask) >> 1) & 0x55555555);
+}
+static inline int Dau_DecSetIsContained( Vec_Int_t * vSets, unsigned New )
+// Old=abcD contains New=abcDE
+// Old=abcD contains New=abCD
+{
+    unsigned Old;
+    int i, Entry;
+    Vec_IntForEachEntry( vSets, Entry, i )
+    {
+        Old = (unsigned)Entry;
+        if ( (Old & ~New) == 0 && !Dau_DecSetHas01(~Old & New))
+            return 1;
+    }
+    return 0;
+}
+void Dau_DecSortSet( unsigned set, int nVars, int * pnUnique, int * pnShared, int * pnFree )
+{
+    int v;
+    int nUnique = 0, nShared = 0, nFree = 0;
+    for ( v = 0; v < nVars; v++ )
+    {
+        int Value = ((set >> (v << 1)) & 3);
+        if ( Value == 1 )
+            nUnique++;
+        else if ( Value == 3 )
+            nShared++;
+        else if ( Value == 0 )
+            nFree++;
+        else assert( 0 );
+    }
+    *pnUnique = nUnique;
+    *pnShared = nShared;
+    *pnFree   = nFree;
+}
+void Dau_DecPrintSet( unsigned set, int nVars, int fNewLine )
+{
+    int v, Counter = 0;
+    int nUnique = 0, nShared = 0, nFree = 0;
+    Dau_DecSortSet( set, nVars, &nUnique, &nShared, &nFree );
+    printf( "S =%2d  D =%2d  C =%2d   ", nShared, nUnique+nShared, nShared+nFree+1 );
+
+    printf( "x=" );
+    for ( v = 0; v < nVars; v++ )
+    {
+        int Value = ((set >> (v << 1)) & 3);
+        if ( Value == 1 )
+            printf( "%c", 'a' + v ), Counter++;
+        else if ( Value == 3 )
+            printf( "%c", 'A' + v ), Counter++;
+        else assert( Value == 0 );
+    }
+    printf( " y=x" );
+    for ( v = 0; v < nVars; v++ )
+    {
+        int Value = ((set >> (v << 1)) & 3);
+        if ( Value == 0 )
+            printf( "%c", 'a' + v ), Counter++;
+        else if ( Value == 3 )
+            printf( "%c", 'A' + v ), Counter++;
+    }
+    for ( ; Counter < 15; Counter++ )
+        printf( " " );
+    if ( fNewLine )
+        printf( "\n" );
+}
+unsigned Dau_DecReadSet( char * pStr )
+{
+    unsigned uSet = 0; int v;
+    for ( v = 0; pStr[v]; v++ )
+    {
+        if ( pStr[v] >= 'a' && pStr[v] <= 'z' )
+            uSet |= (1 << ((pStr[v] - 'a') << 1));
+        else if ( pStr[v] >= 'A' && pStr[v] <= 'Z' )
+            uSet |= (1 << ((pStr[v] - 'a') << 1)) | (1 << (((pStr[v] - 'a') << 1)+1));
+        else break;
+    }
+    return uSet;
+}
+void Dau_DecPrintSets( Vec_Int_t * vSets, int nVars )
+{
+    int i, Entry;
+    printf( "The %d-variable set family contains %d sets:\n", nVars, Vec_IntSize(vSets) );
+    Vec_IntForEachEntry( vSets, Entry, i )
+        Dau_DecPrintSet( (unsigned)Entry, nVars, 1 );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find decomposable bound-sets of the given function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dau_DecMoveFreeToLSB( word * p, int nVars, int * V2P, int * P2V, int maskB, int sizeB )
+{
+    int v, c = 0;
+    for ( v = 0; v < nVars; v++ )
+        if ( !((maskB >> v) & 1) )
+            Abc_TtMoveVar( p, nVars, V2P, P2V, v, c++ );
+    assert( c == nVars - sizeB );
+}
+Vec_Int_t * Dau_DecFindSets_int( word * pInit, int nVars, int * pSched[16] )
+{
+    Vec_Int_t * vSets = Vec_IntAlloc( 32 );
+    int V2P[16], P2V[16], pVarsB[16];
+    int Limit = (1 << nVars);
+    int c, v, sizeB, sizeS, maskB, maskS;
+    unsigned setMixed;
+    word p[1<<10]; 
+    memcpy( p, pInit, sizeof(word) * Abc_TtWordNum(nVars) );
+    for ( v = 0; v < nVars; v++ )
+        assert( Abc_TtHasVar( p, nVars, v ) );
+    // initialize permutation
+    for ( v = 0; v < nVars; v++ )
+        V2P[v] = P2V[v] = v;
+    // iterate through bound sets of each size in increasing order
+    for ( sizeB = 2; sizeB < nVars; sizeB++ ) // bound set size
+    for ( maskB = 0; maskB < Limit; maskB++ ) // bound set
+    if ( Abc_TtBitCount16(maskB) == sizeB )
+    {
+        // permute variables to have bound set on top
+        Dau_DecMoveFreeToLSB( p, nVars, V2P, P2V, maskB, sizeB );
+        // collect bound set vars on levels nVars-sizeB to nVars-1
+        for ( c = 0; c < sizeB; c++ )
+            pVarsB[c] = P2V[nVars-sizeB+c];
+        // check disjoint
+//        if ( Dau_DecCheckSetTopOld(p, nVars, nVars-sizeB, sizeB, 0, 0, NULL, NULL, NULL) )
+        if ( Dau_DecCheckSetTop(p, nVars, nVars-sizeB, sizeB, 0, 0, pSched[sizeB], NULL, NULL) )
+        {
+            Vec_IntPush( vSets, Dau_DecCreateSet(pVarsB, sizeB, 0) );
+            continue;
+        }
+        if ( sizeB == 2 )
+            continue;
+        // iterate through shared sets of each size in the increasing order
+        for ( sizeS = 1; sizeS <= sizeB - 2; sizeS++ )   // shared set size
+        if ( sizeS <= 3 )
+//        sizeS = 1; 
+        for ( maskS = 0; maskS < (1 << sizeB); maskS++ ) // shared set
+        if ( Abc_TtBitCount16(maskS) == sizeS )
+        {
+            setMixed = Dau_DecCreateSet( pVarsB, sizeB, maskS );
+//            printf( "Considering %10d ", setMixed );
+//            Dau_DecPrintSet( setMixed, nVars );
+            // check if it exists
+            if ( Dau_DecSetIsContained(vSets, setMixed) )
+                continue;
+            // check if it can be added
+//            if ( Dau_DecCheckSetTopOld(p, nVars, nVars-sizeB, sizeB, sizeS, maskS, NULL, NULL, NULL) )
+            if ( Dau_DecCheckSetTop(p, nVars, nVars-sizeB, sizeB, sizeS, maskS, pSched[sizeB], NULL, NULL) )
+                Vec_IntPush( vSets, setMixed );
+        }
+    }
+    return vSets;
+}
+Vec_Int_t * Dau_DecFindSets( word * pInit, int nVars )
+{
+    Vec_Int_t * vSets;
+    int v, * pSched[16] = {NULL};
+    for ( v = 2; v < nVars; v++ )
+        pSched[v] = Extra_GreyCodeSchedule( v );
+    vSets = Dau_DecFindSets_int( pInit, nVars, pSched );
+    for ( v = 2; v < nVars; v++ )
+        ABC_FREE( pSched[v] );
+    return vSets;
+}
+void Dau_DecFindSetsTest2()
+{
+    Vec_Int_t * vSets;
+    word a0 = (~s_Truths6[1] & s_Truths6[2]) | (s_Truths6[1] & s_Truths6[3]);
+    word a1 = (~s_Truths6[1] & s_Truths6[4]) | (s_Truths6[1] & s_Truths6[5]);
+    word t  = (~s_Truths6[0] & a0)           | (s_Truths6[0] & a1); 
+//    word t = ABC_CONST(0x7EFFFFFFFFFFFF7E); // and(gam1,gam2)
+//    word t = ABC_CONST(0xB0F0BBFFB0F0BAFE); // some funct
+//    word t = ABC_CONST(0x2B0228022B022802); // 5-var non-dec0x0F7700000F770000
+//    word t = ABC_CONST(0x0F7700000F770000); // (!<(ab)cd>e)
+//    word t = ABC_CONST(0x7F00000000000000); // (!(abc)def)
+    int nVars = 5;
+
+    vSets   = Dau_DecFindSets( &t, nVars );
+    Dau_DecPrintSets( vSets, nVars );
+    Vec_IntFree( vSets );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces variables in the string.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dau_DecVarReplace( char * pStr, int * pPerm, int nVars )
+{
+    int v;
+    for ( v = 0; pStr[v]; v++ )
+        if ( pStr[v] >= 'a' && pStr[v] <= 'z' )
+        {
+            assert( pStr[v] - 'a' < nVars );
+            pStr[v] = 'a' + pPerm[pStr[v] - 'a'];
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Decomposes with the given bound-set.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dau_DecDecomposeSet( word * pInit, int nVars, unsigned uSet, word * pComp, word * pDec, int * pPermC, int * pPermD, int * pnVarsC, int * pnVarsD, int * pnVarsS )
+{
+    word p[1<<13], Cof[64], Cof0[64], Cof1[64], Decs[64];
+    word * pCof0[64], * pCof1[64], * pDecs[64], MintC, MintD;
+    int V2P[16], P2V[16], pVarsU[16], pVarsS[16], pVarsF[16];
+    int nVarsU = 0, nVarsS = 0, nVarsF = 0;
+    int nWords = Abc_TtWordNum(nVars);
+    int v, d, c, Status, nDecs;
+    assert( nVars <= 16 );
+    for ( v = 0; v < nVars; v++ )
+        V2P[v] = P2V[v] = v;
+    memcpy( p, pInit, sizeof(word) * nWords );
+    // sort variables
+    for ( v = 0; v < nVars; v++ )
+    {
+        int Value = (uSet >> (v<<1)) & 3;
+        if ( Value == 0 )
+            pVarsF[nVarsF++] = v;
+        else if ( Value == 1 )
+            pVarsU[nVarsU++] = v;
+        else if ( Value == 3 )
+            pVarsS[nVarsS++] = v;
+        else assert(0);
+    }
+    assert( nVarsS >= 0 && nVarsS <= 6 );
+    assert( nVarsF + nVarsS + 1 <= 6 );
+    assert( nVarsU + nVarsS <= 6 );
+    // init space for decomposition functions
+    nDecs = (1 << nVarsS);
+    for ( d = 0; d < nDecs; d++ )
+    {
+        pCof0[d] = Cof0 + d;
+        pCof1[d] = Cof1 + d;
+        pDecs[d] = Decs + d;
+    }
+    // permute variables
+    c = 0;
+    for ( v = 0; v < nVarsF; v++ )
+       Abc_TtMoveVar( p, nVars, V2P, P2V, pVarsF[v], c++ );
+    for ( v = 0; v < nVarsS; v++ )
+       Abc_TtMoveVar( p, nVars, V2P, P2V, pVarsS[v], c++ );
+    for ( v = 0; v < nVarsU; v++ )
+       Abc_TtMoveVar( p, nVars, V2P, P2V, pVarsU[v], c++ );
+    assert( c == nVars );
+    // check decomposition
+    Status = Dau_DecCheckSetTopOld( p, nVars, nVarsF, nVarsS+nVarsU, nVarsS, Abc_InfoMask(nVarsS), pCof0, pCof1, pDecs );
+    if ( !Status )
+        return 0;
+    // compute cofactors
+    assert( nVarsF + nVarsS < 6 );
+    for ( d = 0; d < nDecs; d++ )
+    {
+        Cof[d] = (pCof1[d][0] & s_Truths6[nVarsF + nVarsS]) | (pCof0[d][0] & ~s_Truths6[nVarsF + nVarsS]);
+        pDecs[d][0] = Abc_Tt6Stretch( pDecs[d][0], nVarsU );
+    }
+    // compute the resulting functions
+    pComp[0] = 0;
+    pDec[0] = 0;
+    for ( d = 0; d < nDecs; d++ )
+    {
+        // compute minterms for composition/decomposition function
+        MintC = MintD = ~((word)0);
+        for ( v = 0; v < nVarsS; v++ )
+        {
+            MintC &= ((d >> v) & 1) ? s_Truths6[nVarsF+v] : ~s_Truths6[nVarsF+v];
+            MintD &= ((d >> v) & 1) ? s_Truths6[nVarsU+v] : ~s_Truths6[nVarsU+v];
+        }
+        // derive functions
+        pComp[0] |= MintC & Cof[d];
+        pDec[0] |= MintD & pDecs[d][0];
+    }
+    // derive variable permutations
+    if ( pPermC )
+    {
+        for ( v = 0; v < nVarsF; v++ )
+            pPermC[v] = pVarsF[v];
+        for ( v = 0; v < nVarsS; v++ )
+            pPermC[nVarsF+v] = pVarsS[v];
+        pPermC[nVarsF + nVarsS] = nVars;
+    }
+    if ( pPermD )
+    {
+        for ( v = 0; v < nVarsU; v++ )
+            pPermD[v] = pVarsU[v];
+        for ( v = 0; v < nVarsS; v++ )
+            pPermD[nVarsU+v] = pVarsS[v];
+    }
+    if ( pnVarsC )
+        *pnVarsC = nVarsF + nVarsS + 1;
+    if ( pnVarsD )
+        *pnVarsD = nVarsU + nVarsS;
+    if ( pnVarsS )
+        *pnVarsS = nVarsS;
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Testing procedures.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dau_DecVerify( word * pInit, int nVars, char * pDsdC, char * pDsdD )
+{
+    word pC[1<<13], pD[1<<13], pRes[1<<13]; // max = 16
+    int nWordsC = Abc_TtWordNum(nVars+1);
+    int nWordsD = Abc_TtWordNum(nVars);
+    assert( nVars < 16 );
+    memcpy( pC, Dau_DsdToTruth(pDsdC, nVars+1), sizeof(word) * nWordsC );
+    memcpy( pD, Dau_DsdToTruth(pDsdD, nVars), sizeof(word) * nWordsD );
+    if ( nVars >= 6 )
+    {
+        assert( nWordsD >= 1 );
+        assert( nWordsC > 1 );
+        Abc_TtMux( pRes, pD, pC + nWordsD, pC, nWordsD );
+    }
+    else
+    {
+        word pC0 = Abc_Tt6Stretch( pC[0], nVars );
+        word pC1 = Abc_Tt6Stretch( (pC[0] >> (1 << nVars)), nVars );
+        Abc_TtMux( pRes, pD, &pC1, &pC0, nWordsD );
+    }
+    if ( !Abc_TtEqual(pInit, pRes, nWordsD) )
+        printf( "      Verification failed" );
+//    else
+//        printf( "      Verification successful" );
+    printf( "\n" );
+    return 1;
+}
+int Dau_DecPerform6( word * p, int nVars, unsigned uSet )
+{
+    word tComp = 0, tDec = 0, tDec0, tComp0, tComp1, FuncC, FuncD;
+    char pDsdC[1000], pDsdD[1000];
+    int pPermC[16], pPermD[16];
+    int nVarsC, nVarsD, nVarsS, nVarsU, nVarsF, nPairs;
+    int i, m, v, status, ResC, ResD, Counter = 0;
+    status = Dau_DecDecomposeSet( p, nVars, uSet, &tComp, &tDec0, pPermC, pPermD, &nVarsC, &nVarsD, &nVarsS );
+    if ( !status )
+    {
+        printf( "  Decomposition does not exist\n" );
+        return 0;
+    }
+    nVarsU = nVarsD - nVarsS;
+    nVarsF = nVarsC - nVarsS - 1;
+    tComp0 = Abc_Tt6Cofactor0( tComp, nVarsF + nVarsS );
+    tComp1 = Abc_Tt6Cofactor1( tComp, nVarsF + nVarsS );
+    nPairs = 1 << (1 << nVarsS); 
+    for ( i = 0; i < nPairs; i++ )
+    {
+        if ( i & 1 )
+            continue;
+        // create miterms with this polarity
+        FuncC = FuncD = 0;
+        for ( m = 0; m < (1 << nVarsS); m++ )
+        {
+            word MintC, MintD;
+            if ( !((i >> m) & 1) )
+                continue;
+            MintC = MintD = ~(word)0;
+            for ( v = 0; v < nVarsS; v++ )
+            {
+                MintC &= ((m >> v) & 1) ? s_Truths6[nVarsF+v] : ~s_Truths6[nVarsF+v];
+                MintD &= ((m >> v) & 1) ? s_Truths6[nVarsU+v] : ~s_Truths6[nVarsU+v];
+            }
+            FuncC |= MintC;
+            FuncD |= MintD;
+        }
+        // uncomplement given variables
+        tComp = (~s_Truths6[nVarsF + nVarsS] & ((tComp0 & ~FuncC) | (tComp1 & FuncC))) | (s_Truths6[nVarsF + nVarsS] & ((tComp1 & ~FuncC) | (tComp0 & FuncC)));
+        tDec = tDec0 ^ FuncD;
+        // decompose
+        ResC = Dau_DsdDecompose( &tComp, nVarsC, 0, 1, pDsdC );
+        ResD = Dau_DsdDecompose( &tDec, nVarsD, 0, 1, pDsdD );
+        // replace variables
+        Dau_DecVarReplace( pDsdD, pPermD, nVarsD );
+        Dau_DecVarReplace( pDsdC, pPermC, nVarsC );
+        // report
+//        printf( "  " );
+        printf( "%3d : ", Counter++ );
+        printf( "%24s  ", pDsdD );
+        printf( "%24s  ", pDsdC );
+        Dau_DecVerify( p, nVars, pDsdC, pDsdD );
+    }
+    return 1;
+}
+
+int Dau_DecPerform( word * pInit, int nVars, unsigned uSet )
+{
+    word p[1<<10], pDec[1<<10], pComp[1<<10]; // at most 2^10 words
+    char pDsdC[5000], pDsdD[5000];  // at most 2^12 hex digits
+    int nVarsU, nVarsS, nVarsF, nVarsC = 0, nVarsD = 0;
+    int V2P[16], P2V[16], pPermC[16], pPermD[16], * pSched;
+    int v, i, status, ResC, ResD;
+    int nWords = Abc_TtWordNum(nVars);
+    assert( nVars <= 16 );
+    // backup the function
+    memcpy( p, pInit, sizeof(word) * nWords );
+    // get variable numbers
+    Dau_DecSortSet( uSet, nVars, &nVarsU, &nVarsS, &nVarsF );
+    // permute function and order variables
+    for ( v = 0; v < nVars; v++ )
+        V2P[v] = P2V[v] = v;
+    for ( i = v = 0; v < nVars; v++ )
+        if ( ((uSet >> (v<<1)) & 3) == 0 ) // free first
+           Abc_TtMoveVar( p, nVars, V2P, P2V, v, i++ ), pPermC[nVarsC++] = v;
+    for ( v = 0; v < nVars; v++ )
+        if ( ((uSet >> (v<<1)) & 3) == 3 ) // share second
+           Abc_TtMoveVar( p, nVars, V2P, P2V, v, i++ ), pPermC[nVarsC++] = v;
+    pPermC[nVarsC++] = nVars;
+    for ( v = 0; v < nVars; v++ )
+        if ( ((uSet >> (v<<1)) & 3) == 1 ) // unique last
+           Abc_TtMoveVar( p, nVars, V2P, P2V, v, i++ ), pPermD[nVarsD++] = v;
+    for ( v = 0; v < nVarsS; v++ )
+        pPermD[nVarsD++] = pPermC[nVarsF+v];
+    assert( nVarsD == nVarsU + nVarsS );
+    assert( nVarsC == nVarsF + nVarsS + 1 );
+    assert( i == nVars );
+    // decompose
+    pSched = Extra_GreyCodeSchedule( nVarsU + nVarsS );
+    memset( pDec, 0, sizeof(word) * Abc_TtWordNum(nVarsD) );
+    memset( pComp, 0, sizeof(word) * Abc_TtWordNum(nVarsC) );
+    status = Dau_DecCheckSetTop( p, nVars, nVarsF, nVarsU + nVarsS, nVarsS, nVarsS ? Abc_InfoMask(nVarsS) : 0, pSched, pDec, pComp );
+    ABC_FREE( pSched );
+    if ( !status )
+    {
+        printf( "  Decomposition does not exist\n" );
+        return 0;
+    }
+//    Dau_DsdPrintFromTruth( stdout, pC, nVars+1 ); //printf( "\n" );
+//    Dau_DsdPrintFromTruth( stdout, pD, nVars ); //printf( "\n" );
+//    Kit_DsdPrintFromTruth( (unsigned *)pComp, 6 ); printf( "\n" );
+//    Kit_DsdPrintFromTruth( (unsigned *)pDec, 6 );  printf( "\n" );
+    // decompose
+    ResC = Dau_DsdDecompose( pComp, nVarsC, 0, 1, pDsdC );
+    ResD = Dau_DsdDecompose( pDec, nVarsD, 0, 1, pDsdD );
+    // replace variables
+    Dau_DecVarReplace( pDsdD, pPermD, nVarsD );
+    Dau_DecVarReplace( pDsdC, pPermC, nVarsC );
+    // report
+    printf( "     " );
+    printf( "%3d : ", 0 );
+    printf( "%24s  ", pDsdD );
+    printf( "%24s  ", pDsdC );
+    Dau_DecVerify( pInit, nVars, pDsdC, pDsdD );
+    return 1;
+}
+void Dau_DecTrySets( word * pInit, int nVars, int fVerbose )
+{
+    Vec_Int_t * vSets;
+    int i, Entry;
+    assert( nVars <= 16 );
+    vSets = Dau_DecFindSets( pInit, nVars );
+    if ( !fVerbose )
+    {
+        Vec_IntFree( vSets );
+        return;
+    }
+    Dau_DsdPrintFromTruth( pInit, nVars ); 
+    printf( "This %d-variable function has %d decomposable variable sets:\n", nVars, Vec_IntSize(vSets) );
+    Vec_IntForEachEntry( vSets, Entry, i )
+    {
+        unsigned uSet = (unsigned)Entry;
+        printf( "Set %4d : ", i );
+        if ( nVars > 6 )
+        {
+            Dau_DecPrintSet( uSet, nVars, 0 );
+            Dau_DecPerform( pInit, nVars, uSet );
+        }
+        else
+        {
+            Dau_DecPrintSet( uSet, nVars, 1 );
+            Dau_DecPerform6( pInit, nVars, uSet );
+        }
+    }
+    Vec_IntFree( vSets );
+//    printf( "\n" );
+}
+
+void Dau_DecFindSetsTest3()
+{
+    word a0 = (~s_Truths6[1] & s_Truths6[2]) | (s_Truths6[1] & s_Truths6[3]);
+    word a1 = (~s_Truths6[1] & s_Truths6[4]) | (s_Truths6[1] & s_Truths6[5]);
+    word t  = (~s_Truths6[0] & a0)           | (s_Truths6[0] & a1); 
+//    word t = ABC_CONST(0x0F7700000F770000); // (!<(ab)cd>e)
+    int nVars = 6;
+    char * pStr = "Bcd";
+//    char * pStr = "Abcd";
+//    char * pStr = "ab";
+    unsigned uSet = Dau_DecReadSet( pStr );
+    Dau_DecPerform6( &t, nVars, uSet );
+}
+
+void Dau_DecFindSetsTest()
+{
+    int nVars = 6;
+//    word a0 = (~s_Truths6[1] & s_Truths6[2]) | (s_Truths6[1] & s_Truths6[3]);
+//    word a1 = (~s_Truths6[1] & s_Truths6[4]) | (s_Truths6[1] & s_Truths6[5]);
+//    word t  = (~s_Truths6[0] & a0)           | (s_Truths6[0] & a1); 
+//    word t = ABC_CONST(0x7EFFFFFFFFFFFF7E); // and(gam1,gam2)
+//    word t = ABC_CONST(0xB0F0BBFFB0F0BAFE); // some funct
+//    word t = ABC_CONST(0x00000000901FFFFF); // some funct
+    word t = ABC_CONST(0x000030F00D0D3FFF); // some funct
+//    word t = ABC_CONST(0x00000000690006FF); // some funct
+//    word t = ABC_CONST(0x7000F80007FF0FFF); // some funct
+//    word t = ABC_CONST(0x4133CB334133CB33); // some funct 5 var
+//    word t = ABC_CONST(0x2B0228022B022802); // 5-var non-dec0x0F7700000F770000
+//    word t = ABC_CONST(0x0F7700000F770000); // (!<(ab)cd>e)
+//    word t = ABC_CONST(0x7F00000000000000); // (!(abc)def)
+    Dau_DecTrySets( &t, nVars, 1 );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dau/dauTree.c b/abc-build/src/opt/dau/dauTree.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dau/dauTree.c
@@ -0,0 +1,2022 @@
+/**CFile****************************************************************
+
+  FileName    [dauTree.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware unmapping.]
+
+  Synopsis    [Canonical DSD package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: dauTree.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dauInt.h"
+#include "misc/mem/mem.h"
+#include "misc/util/utilTruth.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Dss_Fun_t_ Dss_Fun_t;
+struct Dss_Fun_t_
+{
+    unsigned       iDsd  :    26;  // DSD literal
+    unsigned       nFans :     6;  // fanin count
+    unsigned char  pFans[0];       // fanins
+};
+
+typedef struct Dss_Ent_t_ Dss_Ent_t;
+struct Dss_Ent_t_
+{
+    Dss_Fun_t *    pFunc;
+    Dss_Ent_t *    pNext;
+    unsigned       iDsd0  :   27;  // dsd entry
+    unsigned       nWords :    5;  // total word count (struct + shared)
+    unsigned       iDsd1  :   27;  // dsd entry
+    unsigned       nShared:    5;  // shared count
+    unsigned char  pShared[0];     // shared literals
+};
+
+typedef struct Dss_Obj_t_ Dss_Obj_t;
+struct Dss_Obj_t_
+{
+    unsigned       Id;             // node ID
+    unsigned       Type    :   3;  // node type
+    unsigned       nSupp   :   8;  // variable
+    unsigned       iVar    :   8;  // variable
+    unsigned       nWords  :   6;  // variable
+    unsigned       fMark0  :   1;  // user mark
+    unsigned       fMark1  :   1;  // user mark
+    unsigned       nFans   :   5;  // fanin count
+    unsigned       pFans[0];       // fanins
+};
+
+typedef struct Dss_Ntk_t_ Dss_Ntk_t;
+struct Dss_Ntk_t_
+{
+    int            nVars;          // the number of variables
+    int            nMem;           // memory used
+    int            nMemAlloc;      // memory allocated
+    word *         pMem;           // memory array
+    Dss_Obj_t *    pRoot;          // root node
+    Vec_Ptr_t *    vObjs;          // internal nodes
+};
+
+struct Dss_Man_t_
+{
+    int            nVars;          // variable number
+    int            nNonDecLimit;   // limit on non-dec size
+    int            nBins;          // table size
+    unsigned *     pBins;          // hash table
+    Mem_Flex_t *   pMem;           // memory for nodes
+    Vec_Ptr_t *    vObjs;          // objects
+    Vec_Int_t *    vNexts;         // next pointers
+    Vec_Int_t *    vLeaves;        // temp
+    Vec_Int_t *    vCopies;        // temp
+    word **        pTtElems;       // elementary TTs
+    Dss_Ent_t **   pCache;         // decomposition cache
+    int            nCache;         // size of decomposition cache
+    Mem_Flex_t *   pMemEnts;       // memory for cache entries
+    int            nCacheHits[2];
+    int            nCacheMisses[2];
+    int            nCacheEntries[2];
+    abctime        timeBeg;
+    abctime        timeDec;
+    abctime        timeLook;
+    abctime        timeEnd;
+};
+
+static inline Dss_Obj_t *  Dss_Regular( Dss_Obj_t * p )                            { return (Dss_Obj_t *)((ABC_PTRUINT_T)(p) & ~01);                                    }
+static inline Dss_Obj_t *  Dss_Not( Dss_Obj_t * p )                                { return (Dss_Obj_t *)((ABC_PTRUINT_T)(p) ^  01);                                    }
+static inline Dss_Obj_t *  Dss_NotCond( Dss_Obj_t * p, int c )                     { return (Dss_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c));                                    }
+static inline int          Dss_IsComplement( Dss_Obj_t * p )                       { return (int)((ABC_PTRUINT_T)(p) & 01);                                             }
+
+static inline int          Dss_EntWordNum( Dss_Ent_t * p )                         { return sizeof(Dss_Ent_t) / 8 + p->nShared / 4 + ((p->nShared & 3) > 0);            }
+static inline int          Dss_FunWordNum( Dss_Fun_t * p )                         { assert(p->nFans >= 2); return (p->nFans + 4) / 8 + (((p->nFans + 4) & 7) > 0);     }
+static inline int          Dss_ObjWordNum( int nFans )                             { return sizeof(Dss_Obj_t) / 8 + nFans / 2 + ((nFans & 1) > 0);                      }
+static inline word *       Dss_ObjTruth( Dss_Obj_t * pObj )                        { return (word *)pObj + pObj->nWords;                                                }
+
+static inline void         Dss_ObjClean( Dss_Obj_t * pObj )                        { memset( pObj, 0, sizeof(Dss_Obj_t) );                                              }
+static inline int          Dss_ObjId( Dss_Obj_t * pObj )                           { return pObj->Id;                                                                   }
+static inline int          Dss_ObjType( Dss_Obj_t * pObj )                         { return pObj->Type;                                                                 }
+static inline int          Dss_ObjSuppSize( Dss_Obj_t * pObj )                     { return pObj->nSupp;                                                                }
+static inline int          Dss_ObjFaninNum( Dss_Obj_t * pObj )                     { return pObj->nFans;                                                                }
+static inline int          Dss_ObjFaninC( Dss_Obj_t * pObj, int i )                { assert(i < (int)pObj->nFans); return Abc_LitIsCompl(pObj->pFans[i]);               }
+
+static inline Dss_Obj_t *  Dss_VecObj( Vec_Ptr_t * p, int Id )                     { return (Dss_Obj_t *)Vec_PtrEntry(p, Id);                                           }
+static inline Dss_Obj_t *  Dss_VecConst0( Vec_Ptr_t * p )                          { return Dss_VecObj( p, 0 );                                                         }
+static inline Dss_Obj_t *  Dss_VecVar( Vec_Ptr_t * p, int v )                      { return Dss_VecObj( p, v+1 );                                                       }
+static inline int          Dss_VecLitSuppSize( Vec_Ptr_t * p, int iLit )           { return Dss_VecObj( p, Abc_Lit2Var(iLit) )->nSupp;                                  }
+
+static inline int          Dss_Obj2Lit( Dss_Obj_t * pObj )                         { return Abc_Var2Lit(Dss_Regular(pObj)->Id, Dss_IsComplement(pObj));                 }
+static inline Dss_Obj_t *  Dss_Lit2Obj( Vec_Ptr_t * p, int iLit )                  { return Dss_NotCond(Dss_VecObj(p, Abc_Lit2Var(iLit)), Abc_LitIsCompl(iLit));        }
+static inline Dss_Obj_t *  Dss_ObjFanin( Vec_Ptr_t * p, Dss_Obj_t * pObj, int i )  { assert(i < (int)pObj->nFans); return Dss_VecObj(p, Abc_Lit2Var(pObj->pFans[i]));   }
+static inline Dss_Obj_t *  Dss_ObjChild( Vec_Ptr_t * p, Dss_Obj_t * pObj, int i )  { assert(i < (int)pObj->nFans); return Dss_Lit2Obj(p, pObj->pFans[i]);               }
+
+#define Dss_VecForEachObj( vVec, pObj, i )                \
+    Vec_PtrForEachEntry( Dss_Obj_t *, vVec, pObj, i )
+#define Dss_VecForEachObjVec( vLits, vVec, pObj, i )      \
+    for ( i = 0; (i < Vec_IntSize(vLits)) && ((pObj) = Dss_Lit2Obj(vVec, Vec_IntEntry(vLits,i))); i++ )
+#define Dss_VecForEachNode( vVec, pObj, i )               \
+    Vec_PtrForEachEntry( Dss_Obj_t *, vVec, pObj, i )     \
+        if ( pObj->Type == DAU_DSD_CONST0 || pObj->Type == DAU_DSD_VAR ) {} else
+#define Dss_ObjForEachFanin( vVec, pObj, pFanin, i )      \
+    for ( i = 0; (i < Dss_ObjFaninNum(pObj)) && ((pFanin) = Dss_ObjFanin(vVec, pObj, i)); i++ )
+#define Dss_ObjForEachChild( vVec, pObj, pFanin, i )      \
+    for ( i = 0; (i < Dss_ObjFaninNum(pObj)) && ((pFanin) = Dss_ObjChild(vVec, pObj, i)); i++ )
+
+static inline int Dss_WordCountOnes( unsigned uWord )
+{
+    uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555);
+    uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333);
+    uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F);
+    uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF);
+    return  (uWord & 0x0000FFFF) + (uWord>>16);
+}
+
+static inline int Dss_Lit2Lit( int * pMapLit, int Lit )   { return Abc_Var2Lit( Abc_Lit2Var(pMapLit[Abc_Lit2Var(Lit)]), Abc_LitIsCompl(Lit) ^ Abc_LitIsCompl(pMapLit[Abc_Lit2Var(Lit)]) );   }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+#if 0
+
+/**Function*************************************************************
+
+  Synopsis    [Check decomposability for 666.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+// recursively collects 6-feasible supports
+int Dss_ObjCheck666_rec( Dss_Ntk_t * p, Dss_Obj_t * pObj, Vec_Int_t * vSupps )
+{
+    Dss_Obj_t * pFanin;
+    int i, uSupp = 0;
+    assert( !Dss_IsComplement(pObj) );
+    if ( pObj->Type == DAU_DSD_VAR )
+    {
+        assert( pObj->iVar >= 0 && pObj->iVar < 30 );
+        return (1 << pObj->iVar);
+    }
+    if ( pObj->Type == DAU_DSD_AND || pObj->Type == DAU_DSD_XOR )
+    {
+        int c0, c1, c2, uSuppTemp;
+        int uSuppVars[16];
+        int nSuppVars = 0;
+        int nFanins = Dss_ObjFaninNum(pObj);
+        int uSupps[16], nSuppSizes[16];
+        Dss_ObjForEachFanin( p->vObjs, pObj, pFanin, i )
+        {
+            uSupps[i] = Dss_ObjCheck666_rec( p, pFanin, vSupps );
+            nSuppSizes[i] = Dss_WordCountOnes( uSupps[i] );
+            uSupp |= uSupps[i];
+            if ( nSuppSizes[i] == 1 )
+                uSuppVars[nSuppVars++] = uSupps[i];
+        }
+        // iterate through the permutations
+        for ( c0 = 0; c0 < nFanins; c0++ )
+        if ( nSuppSizes[c0] > 1 && nSuppSizes[c0] < 6 )
+        {
+            uSuppTemp = uSupps[c0];
+            for ( i = 0; i < nSuppVars; i++ )
+                if ( nSuppSizes[c0] + i < 6 )
+                    uSuppTemp |= uSuppVars[i];
+                else
+                    break;
+            if ( Dss_WordCountOnes(uSuppTemp) <= 6 )
+                Vec_IntPush( vSupps, uSuppTemp );
+
+            for ( c1 = c0 + 1; c1 < nFanins; c1++ )
+            if ( nSuppSizes[c1] > 1 && nSuppSizes[c1] < 6 )
+            {
+                if ( nSuppSizes[c0] + nSuppSizes[c1] <= 6 )
+                    Vec_IntPush( vSupps, uSupps[c0] | uSupps[c1] );
+
+                uSuppTemp = uSupps[c0] | uSupps[c1];
+                for ( i = 0; i < nSuppVars; i++ )
+                    if ( nSuppSizes[c0] + nSuppSizes[c1] + i < 6 )
+                        uSuppTemp |= uSuppVars[i];
+                    else
+                        break;
+                if ( Dss_WordCountOnes(uSuppTemp) <= 6 )
+                    Vec_IntPush( vSupps, uSuppTemp );
+
+                for ( c2 = c1 + 1; c2 < nFanins; c2++ )
+                if ( nSuppSizes[c2] > 1 && nSuppSizes[c2] < 6 )
+                {
+                    if ( nSuppSizes[c0] + nSuppSizes[c1] + nSuppSizes[c2] <= 6 )
+                        Vec_IntPush( vSupps, uSupps[c0] | uSupps[c1] | uSupps[c2] );
+                    assert( nSuppSizes[c0] + nSuppSizes[c1] + nSuppSizes[c2] >= 6 );
+                }
+            }
+        }
+        if ( nSuppVars > 1 && nSuppVars <= 6 )
+        {
+            uSuppTemp = 0;
+            for ( i = 0; i < nSuppVars; i++ )
+                uSuppTemp |= uSuppVars[i];
+            Vec_IntPush( vSupps, uSuppTemp );
+        }
+        else if ( nSuppVars > 6 && nSuppVars <= 12 )
+        {
+            uSuppTemp = 0;
+            for ( i = 0; i < 6; i++ )
+                uSuppTemp |= uSuppVars[i];
+            Vec_IntPush( vSupps, uSuppTemp );
+
+            uSuppTemp = 0;
+            for ( i = 6; i < nSuppVars; i++ )
+                uSuppTemp |= uSuppVars[i];
+            Vec_IntPush( vSupps, uSuppTemp );
+        }
+    }
+    else if ( pObj->Type == DAU_DSD_MUX || pObj->Type == DAU_DSD_PRIME )
+    {
+        Dss_ObjForEachFanin( p->vObjs, pObj, pFanin, i )
+            uSupp |= Dss_ObjCheck666_rec( p, pFanin, vSupps );
+    }
+    if ( Dss_WordCountOnes( uSupp ) <= 6 )
+        Vec_IntPush( vSupps, uSupp );
+    return uSupp;
+}
+int Dss_ObjCheck666( Dss_Ntk_t * p )
+{
+    Vec_Int_t * vSupps;
+    int i, k, SuppI, SuppK;
+    int nSupp = Dss_ObjSuppSize(Dss_Regular(p->pRoot));
+    if ( nSupp <= 6 )
+        return 1;
+    // compute supports
+    vSupps = Vec_IntAlloc( 100 );
+    Dss_ObjCheck666_rec( p, Dss_Regular(p->pRoot), vSupps );
+    Vec_IntUniqify( vSupps );
+    Vec_IntForEachEntry( vSupps, SuppI, i )
+    {
+        k = Dss_WordCountOnes(SuppI);
+        assert( k > 0 && k <= 6 );
+/*
+        for ( k = 0; k < 16; k++ )
+            if ( (SuppI >> k) & 1 )
+                printf( "%c", 'a' + k );
+            else
+                printf( "-" );
+        printf( "\n" );
+*/
+    }
+    // consider support pairs
+    Vec_IntForEachEntry( vSupps, SuppI, i )
+    Vec_IntForEachEntryStart( vSupps, SuppK, k, i+1 )
+    {
+        if ( SuppI & SuppK )
+            continue;
+        if ( Dss_WordCountOnes(SuppI | SuppK) + 4 >= nSupp )
+        {
+            Vec_IntFree( vSupps );
+            return 1;
+        }
+    }
+    Vec_IntFree( vSupps );
+    return 0;
+}
+void Dau_DsdTest_()
+{
+/*
+    extern Dss_Ntk_t * Dss_NtkCreate( char * pDsd, int nVars, word * pTruth );
+    extern void Dss_NtkFree( Dss_Ntk_t * p );
+
+//    char * pDsd = "(!(amn!(bh))[cdeij]!(fklg)o)";
+    char * pDsd = "<[(ab)(cd)(ef)][(gh)(ij)(kl)](mn)>";
+    Dss_Ntk_t * pNtk = Dss_NtkCreate( pDsd, 16, NULL );
+    int Status = Dss_ObjCheck666( pNtk );
+    Dss_NtkFree( pNtk );
+*/
+}
+
+abctime if_dec_time;
+
+void Dau_DsdCheckStructOne( word * pTruth, int nVars, int nLeaves )
+{
+    extern Dss_Ntk_t * Dss_NtkCreate( char * pDsd, int nVars, word * pTruth );
+    extern void Dss_NtkFree( Dss_Ntk_t * p );
+
+    static abctime timeTt  = 0;
+    static abctime timeDsd = 0;
+    abctime clkTt, clkDsd;
+
+    char pDsd[1000];
+    word Truth[1024];
+    Dss_Ntk_t * pNtk;
+    int Status, nNonDec;
+
+    if ( pTruth == NULL )
+    {
+        Abc_PrintTime( 1, "TT  runtime", timeTt );
+        Abc_PrintTime( 1, "DSD runtime", timeDsd );
+        Abc_PrintTime( 1, "Total      ", if_dec_time );
+
+        if_dec_time = 0;
+        timeTt = 0;
+        timeDsd = 0;
+        return;
+    }
+
+    Abc_TtCopy( Truth, pTruth, Abc_TtWordNum(nVars), 0 );
+    nNonDec = Dau_DsdDecompose( Truth, nVars, 0, 0, pDsd );
+    if ( nNonDec > 0 )
+        return;
+
+    pNtk = Dss_NtkCreate( pDsd, 16, NULL );
+
+    // measure DSD runtime
+    clkDsd = Abc_Clock();
+    Status = Dss_ObjCheck666( pNtk );
+    timeDsd += Abc_Clock() - clkDsd;
+
+    Dss_NtkFree( pNtk );
+
+    // measure TT runtime
+    clkTt = Abc_Clock();
+    {
+        #define CLU_VAR_MAX  16
+
+        // decomposition
+        typedef struct If_Grp_t_ If_Grp_t;
+        struct If_Grp_t_
+        {
+            char       nVars;
+            char       nMyu;
+            char       pVars[CLU_VAR_MAX];
+        };
+
+
+        int nLutLeaf  = 6;
+        int nLutLeaf2 = 6;
+        int nLutRoot  = 6;
+
+        If_Grp_t G;
+        If_Grp_t G2, R;
+        word Func0, Func1, Func2;
+
+        {
+            extern If_Grp_t If_CluCheck3( void * p, word * pTruth0, int nVars, int nLutLeaf, int nLutLeaf2, int nLutRoot, 
+                          If_Grp_t * pR, If_Grp_t * pG2, word * pFunc0, word * pFunc1, word * pFunc2 );
+            G = If_CluCheck3( NULL, pTruth, nLeaves, nLutLeaf, nLutLeaf2, nLutRoot, &R, &G2, &Func0, &Func1, &Func2 );
+        }
+
+    }
+    timeTt += Abc_Clock() - clkTt;
+}
+
+#endif
+
+ 
+/**Function*************************************************************
+
+  Synopsis    [Elementary truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline word ** Dss_ManTtElems()
+{
+    static word TtElems[DAU_MAX_VAR+1][DAU_MAX_WORD], * pTtElems[DAU_MAX_VAR+1] = {NULL};
+    if ( pTtElems[0] == NULL )
+    {
+        int v;
+        for ( v = 0; v <= DAU_MAX_VAR; v++ )
+            pTtElems[v] = TtElems[v];
+        Abc_TtElemInit( pTtElems, DAU_MAX_VAR );
+    }
+    return pTtElems;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creating DSD network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dss_Obj_t * Dss_ObjAllocNtk( Dss_Ntk_t * p, int Type, int nFans, int nTruthVars )
+{
+    Dss_Obj_t * pObj;
+    pObj = (Dss_Obj_t *)(p->pMem + p->nMem);
+    Dss_ObjClean( pObj );
+    pObj->nFans  = nFans;
+    pObj->nWords = Dss_ObjWordNum( nFans );
+    pObj->Type   = Type;
+    pObj->Id     = Vec_PtrSize( p->vObjs );
+    pObj->iVar   = 31;
+    Vec_PtrPush( p->vObjs, pObj );
+    p->nMem += pObj->nWords + (nTruthVars ? Abc_TtWordNum(nTruthVars) : 0);
+    assert( p->nMem < p->nMemAlloc );
+    return pObj;
+}
+Dss_Obj_t * Dss_ObjCreateNtk( Dss_Ntk_t * p, int Type, Vec_Int_t * vFaninLits )
+{
+    Dss_Obj_t * pObj;
+    int i, Entry;
+    pObj = Dss_ObjAllocNtk( p, Type, Vec_IntSize(vFaninLits), Type == DAU_DSD_PRIME ? Vec_IntSize(vFaninLits) : 0 );
+    Vec_IntForEachEntry( vFaninLits, Entry, i )
+    {
+        pObj->pFans[i] = Entry;
+        pObj->nSupp += Dss_VecLitSuppSize(p->vObjs, Entry);
+    }
+    assert( i == (int)pObj->nFans );
+    return pObj;
+}
+Dss_Ntk_t * Dss_NtkAlloc( int nVars )
+{
+    Dss_Ntk_t * p;
+    Dss_Obj_t * pObj;
+    int i;
+    p = ABC_CALLOC( Dss_Ntk_t, 1 );
+    p->nVars     = nVars;
+    p->nMemAlloc = DAU_MAX_STR;
+    p->pMem      = ABC_ALLOC( word, p->nMemAlloc );
+    p->vObjs     = Vec_PtrAlloc( 100 );
+    Dss_ObjAllocNtk( p, DAU_DSD_CONST0, 0, 0 );
+    for ( i = 0; i < nVars; i++ )
+    {
+        pObj = Dss_ObjAllocNtk( p, DAU_DSD_VAR, 0, 0 );
+        pObj->iVar = i;
+        pObj->nSupp = 1;
+    }
+    return p;
+}
+void Dss_NtkFree( Dss_Ntk_t * p )
+{
+    Vec_PtrFree( p->vObjs );
+    ABC_FREE( p->pMem );
+    ABC_FREE( p );
+}
+void Dss_NtkPrint_rec( Dss_Ntk_t * p, Dss_Obj_t * pObj )
+{
+    char OpenType[7]  = {0, 0, 0, '(', '[', '<', '{'};
+    char CloseType[7] = {0, 0, 0, ')', ']', '>', '}'};
+    Dss_Obj_t * pFanin;
+    int i;
+    assert( !Dss_IsComplement(pObj) );
+    if ( pObj->Type == DAU_DSD_VAR )
+        { printf( "%c", 'a' + pObj->iVar ); return; }
+    if ( pObj->Type == DAU_DSD_PRIME )
+        Abc_TtPrintHexRev( stdout, Dss_ObjTruth(pObj), pObj->nFans );
+    printf( "%c", OpenType[pObj->Type] );
+    Dss_ObjForEachFanin( p->vObjs, pObj, pFanin, i )
+    {
+        printf( "%s", Dss_ObjFaninC(pObj, i) ? "!":"" );
+        Dss_NtkPrint_rec( p, pFanin );
+    }
+    printf( "%c", CloseType[pObj->Type] );
+}
+void Dss_NtkPrint( Dss_Ntk_t * p )
+{
+    if ( Dss_Regular(p->pRoot)->Type == DAU_DSD_CONST0 )
+        printf( "%d", Dss_IsComplement(p->pRoot) );
+    else
+    {
+        printf( "%s", Dss_IsComplement(p->pRoot) ? "!":"" );        
+        if ( Dss_Regular(p->pRoot)->Type == DAU_DSD_VAR )
+            printf( "%c", 'a' + Dss_Regular(p->pRoot)->iVar );
+        else
+            Dss_NtkPrint_rec( p, Dss_Regular(p->pRoot) );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creating DSD network from SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Dau_DsdMergeMatches( char * pDsd, int * pMatches )
+{
+    int pNested[DAU_MAX_VAR];
+    int i, nNested = 0;
+    for ( i = 0; pDsd[i]; i++ )
+    {
+        pMatches[i] = 0;
+        if ( pDsd[i] == '(' || pDsd[i] == '[' || pDsd[i] == '<' || pDsd[i] == '{' )
+            pNested[nNested++] = i;
+        else if ( pDsd[i] == ')' || pDsd[i] == ']' || pDsd[i] == '>' || pDsd[i] == '}' )
+            pMatches[pNested[--nNested]] = i;
+        assert( nNested < DAU_MAX_VAR );
+    }
+    assert( nNested == 0 );
+}
+int Dss_NtkCreate_rec( char * pStr, char ** p, int * pMatches, Dss_Ntk_t * pNtk, word * pTruth )
+{
+    int fCompl = 0;
+    if ( **p == '!' )
+    {
+        fCompl = 1;
+        (*p)++;
+    }
+    while ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') )
+        (*p)++;
+/*
+    if ( **p == '<' )
+    {
+        char * q = pStr + pMatches[ *p - pStr ];
+        if ( *(q+1) == '{' )
+            *p = q+1;
+    }
+*/
+    if ( **p >= 'a' && **p <= 'z' ) // var
+        return Abc_Var2Lit( Dss_ObjId(Dss_VecVar(pNtk->vObjs, **p - 'a')), fCompl );
+    if ( **p == '(' || **p == '[' || **p == '<' || **p == '{' ) // and/or/xor
+    {
+        Dss_Obj_t * pObj;
+        Vec_Int_t * vFaninLits = Vec_IntAlloc( 10 );
+        char * q = pStr + pMatches[ *p - pStr ];
+        int Type;
+        if ( **p == '(' )
+            Type = DAU_DSD_AND;
+        else if ( **p == '[' )
+            Type = DAU_DSD_XOR;
+        else if ( **p == '<' )
+            Type = DAU_DSD_MUX;
+        else if ( **p == '{' )
+            Type = DAU_DSD_PRIME;
+        else assert( 0 );
+        assert( *q == **p + 1 + (**p != '(') );
+        for ( (*p)++; *p < q; (*p)++ )
+            Vec_IntPush( vFaninLits, Dss_NtkCreate_rec(pStr, p, pMatches, pNtk, pTruth) );
+        assert( *p == q );
+        if ( Type == DAU_DSD_PRIME )
+        {
+            Vec_Int_t * vFaninLitsNew;
+            word pTemp[DAU_MAX_WORD];
+            char pCanonPerm[DAU_MAX_VAR];
+            int i, uCanonPhase, nFanins = Vec_IntSize(vFaninLits);
+            Abc_TtCopy( pTemp, pTruth, Abc_TtWordNum(nFanins), 0 );
+            uCanonPhase = Abc_TtCanonicize( pTemp, nFanins, pCanonPerm );
+            fCompl = (uCanonPhase >> nFanins) & 1;
+            vFaninLitsNew = Vec_IntAlloc( nFanins );
+            for ( i = 0; i < nFanins; i++ )
+                Vec_IntPush( vFaninLitsNew, Abc_LitNotCond(Vec_IntEntry(vFaninLits, pCanonPerm[i]), (uCanonPhase>>i)&1) );
+            pObj = Dss_ObjCreateNtk( pNtk, DAU_DSD_PRIME, vFaninLitsNew );
+            Abc_TtCopy( Dss_ObjTruth(pObj), pTemp, Abc_TtWordNum(nFanins), 0 );
+            Vec_IntFree( vFaninLitsNew );
+        }
+        else
+            pObj = Dss_ObjCreateNtk( pNtk, Type, vFaninLits );
+        Vec_IntFree( vFaninLits );
+        return Abc_LitNotCond( Dss_Obj2Lit(pObj), fCompl );
+    }
+    assert( 0 );
+    return -1;
+}
+Dss_Ntk_t * Dss_NtkCreate( char * pDsd, int nVars, word * pTruth )
+{
+    int fCompl = 0;
+    Dss_Ntk_t * pNtk = Dss_NtkAlloc( nVars );
+    if ( *pDsd == '!' )
+         pDsd++, fCompl = 1;
+    if ( Dau_DsdIsConst(pDsd) )
+        pNtk->pRoot = Dss_VecConst0(pNtk->vObjs);
+    else if ( Dau_DsdIsVar(pDsd) )
+        pNtk->pRoot = Dss_VecVar(pNtk->vObjs, Dau_DsdReadVar(pDsd));
+    else
+    {
+        int iLit, pMatches[DAU_MAX_STR];
+        Dau_DsdMergeMatches( pDsd, pMatches );
+        iLit = Dss_NtkCreate_rec( pDsd, &pDsd, pMatches, pNtk, pTruth );
+        pNtk->pRoot = Dss_Lit2Obj( pNtk->vObjs, iLit );
+    }
+    if ( fCompl )
+        pNtk->pRoot = Dss_Not(pNtk->pRoot);
+    return pNtk;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Comparing two DSD nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dss_ObjCompare( Vec_Ptr_t * p, Dss_Obj_t * p0i, Dss_Obj_t * p1i )
+{
+    Dss_Obj_t * p0 = Dss_Regular(p0i);
+    Dss_Obj_t * p1 = Dss_Regular(p1i);
+    Dss_Obj_t * pChild0, * pChild1;
+    int i, Res;
+    if ( Dss_ObjType(p0) < Dss_ObjType(p1) )
+        return -1;
+    if ( Dss_ObjType(p0) > Dss_ObjType(p1) )
+        return 1;
+    if ( Dss_ObjType(p0) < DAU_DSD_AND )
+        return 0;
+    if ( Dss_ObjFaninNum(p0) < Dss_ObjFaninNum(p1) )
+        return -1;
+    if ( Dss_ObjFaninNum(p0) > Dss_ObjFaninNum(p1) )
+        return 1;
+    for ( i = 0; i < Dss_ObjFaninNum(p0); i++ )
+    {
+        pChild0 = Dss_ObjChild( p, p0, i );
+        pChild1 = Dss_ObjChild( p, p1, i );
+        Res = Dss_ObjCompare( p, pChild0, pChild1 );
+        if ( Res != 0 )
+            return Res;
+    }
+    if ( Dss_IsComplement(p0i) < Dss_IsComplement(p1i) )
+        return -1;
+    if ( Dss_IsComplement(p0i) > Dss_IsComplement(p1i) )
+        return 1;
+    return 0;
+}
+void Dss_ObjSort( Vec_Ptr_t * p, Dss_Obj_t ** pNodes, int nNodes, int * pPerm )
+{
+    int i, j, best_i;
+    for ( i = 0; i < nNodes-1; i++ )
+    {
+        best_i = i;
+        for ( j = i+1; j < nNodes; j++ )
+            if ( Dss_ObjCompare(p, pNodes[best_i], pNodes[j]) == 1 )
+                best_i = j;
+        if ( i == best_i )
+            continue;
+        ABC_SWAP( Dss_Obj_t *, pNodes[i], pNodes[best_i] );
+        if ( pPerm )
+            ABC_SWAP( int, pPerm[i], pPerm[best_i] );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dss_NtkCheck( Dss_Ntk_t * p )
+{
+    Dss_Obj_t * pObj, * pFanin;
+    int i, k;
+    Dss_VecForEachNode( p->vObjs, pObj, i )
+    {
+        Dss_ObjForEachFanin( p->vObjs, pObj, pFanin, k )
+        {
+            if ( pObj->Type == DAU_DSD_AND && pFanin->Type == DAU_DSD_AND )
+                assert( Dss_ObjFaninC(pObj, k) );
+            else if ( pObj->Type == DAU_DSD_XOR )
+                assert( pFanin->Type != DAU_DSD_XOR );
+            else if ( pObj->Type == DAU_DSD_MUX )
+                assert( !Dss_ObjFaninC(pObj, 0) );
+        }
+    }
+}
+int Dss_NtkCollectPerm_rec( Dss_Ntk_t * p, Dss_Obj_t * pObj, int * pPermDsd, int * pnPerms )
+{
+    Dss_Obj_t * pChild;
+    int k, fCompl = Dss_IsComplement(pObj);
+    pObj = Dss_Regular( pObj );
+    if ( pObj->Type == DAU_DSD_VAR )
+    {
+        pPermDsd[*pnPerms] = Abc_Var2Lit(pObj->iVar, fCompl);
+        pObj->iVar = (*pnPerms)++;
+        return fCompl;
+    }
+    Dss_ObjForEachChild( p->vObjs, pObj, pChild, k )
+        if ( Dss_NtkCollectPerm_rec( p, pChild, pPermDsd, pnPerms ) )
+            pObj->pFans[k] = (unsigned char)Abc_LitRegular((int)pObj->pFans[k]);
+    return 0;
+}
+void Dss_NtkTransform( Dss_Ntk_t * p, int * pPermDsd )
+{
+    Dss_Obj_t * pChildren[DAU_MAX_VAR];
+    Dss_Obj_t * pObj, * pChild;
+    int i, k, nPerms;
+    if ( Dss_Regular(p->pRoot)->Type == DAU_DSD_CONST0 )
+        return;
+    Dss_VecForEachNode( p->vObjs, pObj, i )
+    {
+        if ( pObj->Type == DAU_DSD_MUX || pObj->Type == DAU_DSD_PRIME )
+            continue;
+        Dss_ObjForEachChild( p->vObjs, pObj, pChild, k )
+            pChildren[k] = pChild;
+        Dss_ObjSort( p->vObjs, pChildren, Dss_ObjFaninNum(pObj), NULL );
+        for ( k = 0; k < Dss_ObjFaninNum(pObj); k++ )
+            pObj->pFans[k] = Dss_Obj2Lit( pChildren[k] );
+    }
+    nPerms = 0;
+    if ( Dss_NtkCollectPerm_rec( p, p->pRoot, pPermDsd, &nPerms ) )
+        p->pRoot = Dss_Regular(p->pRoot);
+    assert( nPerms == (int)Dss_Regular(p->pRoot)->nSupp );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dss_Obj_t * Dss_ObjAlloc( Dss_Man_t * p, int Type, int nFans, int nTruthVars )
+{
+    int nWords = Dss_ObjWordNum(nFans) + (nTruthVars ? Abc_TtWordNum(nTruthVars) : 0);
+    Dss_Obj_t * pObj = (Dss_Obj_t *)Mem_FlexEntryFetch( p->pMem, sizeof(word) * nWords );
+    Dss_ObjClean( pObj );
+    pObj->Type   = Type;
+    pObj->nFans  = nFans;
+    pObj->nWords = Dss_ObjWordNum(nFans);
+    pObj->Id     = Vec_PtrSize( p->vObjs );
+    pObj->iVar   = 31;
+    Vec_PtrPush( p->vObjs, pObj );
+    Vec_IntPush( p->vNexts, 0 );
+    return pObj;
+}
+Dss_Obj_t * Dss_ObjCreate( Dss_Man_t * p, int Type, Vec_Int_t * vFaninLits, word * pTruth )
+{
+    Dss_Obj_t * pObj, * pFanin, * pPrev = NULL;
+    int i, Entry;
+    // check structural canonicity
+    assert( Type != DAU_DSD_MUX || Vec_IntSize(vFaninLits) == 3 );
+    assert( Type != DAU_DSD_MUX || !Abc_LitIsCompl(Vec_IntEntry(vFaninLits, 0)) );
+    assert( Type != DAU_DSD_MUX || !Abc_LitIsCompl(Vec_IntEntry(vFaninLits, 1)) || !Abc_LitIsCompl(Vec_IntEntry(vFaninLits, 2)) );
+    // check that leaves are in good order
+    if ( Type == DAU_DSD_AND || Type == DAU_DSD_XOR )
+    Dss_VecForEachObjVec( vFaninLits, p->vObjs, pFanin, i )
+    {
+        assert( Type != DAU_DSD_AND || Abc_LitIsCompl(Vec_IntEntry(vFaninLits, i)) || Dss_ObjType(pFanin) != DAU_DSD_AND );
+        assert( Type != DAU_DSD_XOR || Dss_ObjType(pFanin) != DAU_DSD_XOR );
+        assert( pPrev == NULL || Dss_ObjCompare(p->vObjs, pPrev, pFanin) <= 0 );
+        pPrev = pFanin;
+    }
+    // create new node
+    pObj = Dss_ObjAlloc( p, Type, Vec_IntSize(vFaninLits), Type == DAU_DSD_PRIME ? Vec_IntSize(vFaninLits) : 0 );
+    if ( Type == DAU_DSD_PRIME )
+        Abc_TtCopy( Dss_ObjTruth(pObj), pTruth, Abc_TtWordNum(Vec_IntSize(vFaninLits)), 0 );
+    assert( pObj->nSupp == 0 );
+    Vec_IntForEachEntry( vFaninLits, Entry, i )
+    {
+        pObj->pFans[i] = Entry;
+        pObj->nSupp += Dss_VecLitSuppSize(p->vObjs, Entry);
+    }
+/*
+    {
+        extern void Dss_ManPrintOne( Dss_Man_t * p, int iDsdLit, int * pPermLits );
+        Dss_ManPrintOne( p, Dss_Obj2Lit(pObj), NULL );
+    }
+*/
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dss_ManHashProfile( Dss_Man_t * p )
+{
+    Dss_Obj_t * pObj;
+    unsigned * pSpot;
+    int i, Counter;
+    for ( i = 0; i < p->nBins; i++ )
+    {
+        Counter = 0;
+        for ( pSpot = p->pBins + i; *pSpot; pSpot = (unsigned *)Vec_IntEntryP(p->vNexts, pObj->Id), Counter++ )
+             pObj = Dss_VecObj( p->vObjs, *pSpot );
+        if ( Counter )
+            printf( "%d ", Counter );
+    }
+    printf( "\n" );
+}
+static inline unsigned Dss_ObjHashKey( Dss_Man_t * p, int Type, Vec_Int_t * vFaninLits, word * pTruth )
+{
+    static int s_Primes[8] = { 1699, 4177, 5147, 5647, 6343, 7103, 7873, 8147 };
+    int i, Entry;
+    unsigned uHash = Type * 7873 + Vec_IntSize(vFaninLits) * 8147;
+    Vec_IntForEachEntry( vFaninLits, Entry, i )
+        uHash += Entry * s_Primes[i & 0x7];
+    assert( (Type == DAU_DSD_PRIME) == (pTruth != NULL) );
+    if ( pTruth )
+    {
+        unsigned char * pTruthC = (unsigned char *)pTruth;
+        int nBytes = Abc_TtByteNum(Vec_IntSize(vFaninLits));
+        for ( i = 0; i < nBytes; i++ )
+            uHash += pTruthC[i] * s_Primes[i & 0x7];
+    }
+    return uHash % p->nBins;
+}
+unsigned * Dss_ObjHashLookup( Dss_Man_t * p, int Type, Vec_Int_t * vFaninLits, word * pTruth )
+{
+    Dss_Obj_t * pObj;
+    unsigned * pSpot = p->pBins + Dss_ObjHashKey(p, Type, vFaninLits, pTruth);
+    for ( ; *pSpot; pSpot = (unsigned *)Vec_IntEntryP(p->vNexts, pObj->Id) )
+    {
+        pObj = Dss_VecObj( p->vObjs, *pSpot );
+        if ( (int)pObj->Type == Type && 
+             (int)pObj->nFans == Vec_IntSize(vFaninLits) && 
+             !memcmp(pObj->pFans, Vec_IntArray(vFaninLits), sizeof(int)*pObj->nFans) &&
+             (pTruth == NULL || !memcmp(Dss_ObjTruth(pObj), pTruth, Abc_TtByteNum(pObj->nFans))) ) // equal
+            return pSpot;
+    }
+    return pSpot;
+}
+Dss_Obj_t * Dss_ObjFindOrAdd( Dss_Man_t * p, int Type, Vec_Int_t * vFaninLits, word * pTruth )
+{
+    Dss_Obj_t * pObj;
+    unsigned * pSpot = Dss_ObjHashLookup( p, Type, vFaninLits, pTruth );
+    if ( *pSpot )
+        return Dss_VecObj( p->vObjs, *pSpot );
+    *pSpot = Vec_PtrSize( p->vObjs );
+    pObj = Dss_ObjCreate( p, Type, vFaninLits, pTruth );
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cache for decomposition calls.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dss_ManCacheAlloc( Dss_Man_t * p )
+{
+    assert( p->nCache == 0 );
+    p->nCache = Abc_PrimeCudd( 100000 );
+    p->pCache = ABC_CALLOC( Dss_Ent_t *, p->nCache );
+}
+void Dss_ManCacheFree( Dss_Man_t * p )
+{
+    if ( p->pCache == NULL )
+        return;
+    assert( p->nCache != 0 );
+    p->nCache = 0;
+    ABC_FREE( p->pCache );
+}
+static inline unsigned Dss_ManCacheHashKey( Dss_Man_t * p, Dss_Ent_t * pEnt )
+{ 
+    static int s_Primes[8] = { 1699, 4177, 5147, 5647, 6343, 7103, 7873, 8147 };
+    int i;
+    unsigned uHash = pEnt->nShared * 7103 + pEnt->iDsd0 * 7873 + pEnt->iDsd1 * 8147;
+    for ( i = 0; i < 2*(int)pEnt->nShared; i++ )
+        uHash += pEnt->pShared[i] * s_Primes[i & 0x7];
+    return uHash % p->nCache;
+}
+void Dss_ManCacheProfile( Dss_Man_t * p )
+{
+    Dss_Ent_t ** pSpot;
+    int i, Counter;
+    for ( i = 0; i < p->nCache; i++ )
+    {
+        Counter = 0;
+        for ( pSpot = p->pCache + i; *pSpot; pSpot = &(*pSpot)->pNext, Counter++ )
+            ;
+        if ( Counter )
+            printf( "%d ", Counter );
+    }
+    printf( "\n" );
+}
+Dss_Ent_t ** Dss_ManCacheLookup( Dss_Man_t * p, Dss_Ent_t * pEnt )
+{
+    Dss_Ent_t ** pSpot = p->pCache + Dss_ManCacheHashKey( p, pEnt );
+    for ( ; *pSpot; pSpot = &(*pSpot)->pNext )
+    {
+        if ( (*pSpot)->iDsd0   == pEnt->iDsd0 && 
+             (*pSpot)->iDsd1   == pEnt->iDsd1 && 
+             (*pSpot)->nShared == pEnt->nShared && 
+             !memcmp((*pSpot)->pShared, pEnt->pShared, sizeof(char)*2*pEnt->nShared)  ) // equal
+        {
+            p->nCacheHits[pEnt->nShared!=0]++;
+            return pSpot;
+        }
+    }
+    p->nCacheMisses[pEnt->nShared!=0]++;
+    return pSpot;
+}
+Dss_Ent_t * Dss_ManCacheCreate( Dss_Man_t * p, Dss_Ent_t * pEnt0, Dss_Fun_t * pFun0 )
+{
+    Dss_Ent_t * pEnt = (Dss_Ent_t *)Mem_FlexEntryFetch( p->pMemEnts, sizeof(word) * pEnt0->nWords );
+    Dss_Fun_t * pFun = (Dss_Fun_t *)Mem_FlexEntryFetch( p->pMemEnts, sizeof(word) * Dss_FunWordNum(pFun0) );
+    memcpy( pEnt, pEnt0, sizeof(word) * pEnt0->nWords );
+    memcpy( pFun, pFun0, sizeof(word) * Dss_FunWordNum(pFun0) );
+    pEnt->pFunc = pFun;
+    pEnt->pNext = NULL;
+    p->nCacheEntries[pEnt->nShared!=0]++;
+    return pEnt;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dss_Man_t * Dss_ManAlloc( int nVars, int nNonDecLimit )
+{
+    Dss_Man_t * p;
+    p = ABC_CALLOC( Dss_Man_t, 1 );
+    p->nVars  = nVars;
+    p->nNonDecLimit = nNonDecLimit;
+    p->nBins  = Abc_PrimeCudd( 1000000 );
+    p->pBins  = ABC_CALLOC( unsigned, p->nBins );
+    p->pMem   = Mem_FlexStart();
+    p->vObjs  = Vec_PtrAlloc( 10000 );
+    p->vNexts = Vec_IntAlloc( 10000 );
+    Dss_ObjAlloc( p, DAU_DSD_CONST0, 0, 0 );
+    Dss_ObjAlloc( p, DAU_DSD_VAR, 0, 0 )->nSupp = 1;
+    p->vLeaves = Vec_IntAlloc( 32 );
+    p->vCopies = Vec_IntAlloc( 32 );
+    p->pTtElems = Dss_ManTtElems();
+    p->pMemEnts = Mem_FlexStart();
+//    Dss_ManCacheAlloc( p );
+    return p;
+}
+void Dss_ManFree( Dss_Man_t * p )
+{
+    Abc_PrintTime( 1, "Time begin ", p->timeBeg );
+    Abc_PrintTime( 1, "Time decomp", p->timeDec );
+    Abc_PrintTime( 1, "Time lookup", p->timeLook );
+    Abc_PrintTime( 1, "Time end   ", p->timeEnd );
+
+//    Dss_ManCacheProfile( p );
+    Dss_ManCacheFree( p );
+    Mem_FlexStop( p->pMemEnts, 0 );
+    Vec_IntFreeP( &p->vCopies );
+    Vec_IntFreeP( &p->vLeaves );
+    Vec_IntFreeP( &p->vNexts );
+    Vec_PtrFreeP( &p->vObjs );
+    Mem_FlexStop( p->pMem, 0 );
+    ABC_FREE( p->pBins );
+    ABC_FREE( p );
+}
+void Dss_ManPrint_rec( FILE * pFile, Dss_Man_t * p, Dss_Obj_t * pObj, int * pPermLits, int * pnSupp )
+{
+    char OpenType[7]  = {0, 0, 0, '(', '[', '<', '{'};
+    char CloseType[7] = {0, 0, 0, ')', ']', '>', '}'};
+    Dss_Obj_t * pFanin;
+    int i;
+    assert( !Dss_IsComplement(pObj) );
+    if ( pObj->Type == DAU_DSD_CONST0 )
+        { fprintf( pFile, "0" ); return; }
+    if ( pObj->Type == DAU_DSD_VAR )
+    {
+        int iPermLit = pPermLits ? pPermLits[(*pnSupp)++] : Abc_Var2Lit((*pnSupp)++, 0);
+        fprintf( pFile, "%s%c", Abc_LitIsCompl(iPermLit)? "!":"", 'a' + Abc_Lit2Var(iPermLit) );
+        return;
+    }
+    if ( pObj->Type == DAU_DSD_PRIME )
+        Abc_TtPrintHexRev( pFile, Dss_ObjTruth(pObj), pObj->nFans );
+    fprintf( pFile, "%c", OpenType[pObj->Type] );
+    Dss_ObjForEachFanin( p->vObjs, pObj, pFanin, i )
+    {
+        fprintf( pFile, "%s", Dss_ObjFaninC(pObj, i) ? "!":"" );
+        Dss_ManPrint_rec( pFile, p, pFanin, pPermLits, pnSupp );
+    }
+    fprintf( pFile, "%c", CloseType[pObj->Type] );
+}
+void Dss_ManPrintOne( FILE * pFile, Dss_Man_t * p, int iDsdLit, int * pPermLits )
+{
+    int nSupp = 0;
+    fprintf( pFile, "%6d : ", Abc_Lit2Var(iDsdLit) );
+    fprintf( pFile, "%2d ",   Dss_VecLitSuppSize(p->vObjs, iDsdLit) );
+    fprintf( pFile, "%s",     Abc_LitIsCompl(iDsdLit) ? "!" : ""  );
+    Dss_ManPrint_rec( pFile, p, Dss_VecObj(p->vObjs, Abc_Lit2Var(iDsdLit)), pPermLits, &nSupp );
+    fprintf( pFile, "\n" );
+    assert( nSupp == (int)Dss_VecObj(p->vObjs, Abc_Lit2Var(iDsdLit))->nSupp );
+}
+int Dss_ManCheckNonDec_rec( Dss_Man_t * p, Dss_Obj_t * pObj )
+{
+    Dss_Obj_t * pFanin;
+    int i;
+    assert( !Dss_IsComplement(pObj) );
+    if ( pObj->Type == DAU_DSD_CONST0 )
+        return 0;
+    if ( pObj->Type == DAU_DSD_VAR )
+        return 0;
+    if ( pObj->Type == DAU_DSD_PRIME )
+        return 1;
+    Dss_ObjForEachFanin( p->vObjs, pObj, pFanin, i )
+        if ( Dss_ManCheckNonDec_rec( p, pFanin ) )
+            return 1;
+    return 0;
+}
+void Dss_ManDump( Dss_Man_t * p )
+{
+    char * pFileName = "dss_tts.txt";
+    FILE * pFile;
+    word Temp[DAU_MAX_WORD];
+    Dss_Obj_t * pObj;
+    int i;
+    pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\".\n", pFileName );
+        return;
+    }
+    Dss_VecForEachObj( p->vObjs, pObj, i )
+    {
+        if ( pObj->Type != DAU_DSD_PRIME )
+            continue;
+        Abc_TtCopy( Temp, Dss_ObjTruth(pObj), Abc_TtWordNum(pObj->nFans), 0 );
+        Abc_TtStretch6( Temp, pObj->nFans, p->nVars );
+        fprintf( pFile, "0x" );
+        Abc_TtPrintHexRev( pFile, Temp, p->nVars );
+        fprintf( pFile, "\n" );
+
+//        printf( "%6d : ", i );
+//        Abc_TtPrintHexRev( stdout, Temp, p->nVars );
+//        printf( "    " );
+//        Dau_DsdPrintFromTruth( stdout, Temp, p->nVars );
+    }
+    fclose( pFile );
+}
+void Dss_ManPrint( char * pFileName, Dss_Man_t * p )
+{
+    Dss_Obj_t * pObj;
+    int CountNonDsd = 0, CountNonDsdStr = 0;
+    int i, clk = Abc_Clock();
+    FILE * pFile;
+    pFile = pFileName ? fopen( pFileName, "wb" ) : stdout;
+    if ( pFileName && pFile == NULL )
+    {
+        printf( "cannot open output file\n" );
+        return;
+    }
+    Dss_VecForEachObj( p->vObjs, pObj, i )
+    {
+        CountNonDsd += (pObj->Type == DAU_DSD_PRIME);
+        CountNonDsdStr += Dss_ManCheckNonDec_rec( p, pObj );
+    }
+    fprintf( pFile, "Total number of objects    = %8d\n", Vec_PtrSize(p->vObjs) );
+    fprintf( pFile, "Non-DSD objects (max =%2d)  = %8d\n", p->nNonDecLimit, CountNonDsd );
+    fprintf( pFile, "Non-DSD structures         = %8d\n", CountNonDsdStr );
+    fprintf( pFile, "Memory used for objects    = %6.2f MB.\n", 1.0*Mem_FlexReadMemUsage(p->pMem)/(1<<20) );
+    fprintf( pFile, "Memory used for array      = %6.2f MB.\n", 1.0*sizeof(void *)*Vec_PtrCap(p->vObjs)/(1<<20) );
+    fprintf( pFile, "Memory used for hash table = %6.2f MB.\n", 1.0*sizeof(int)*p->nBins/(1<<20) );
+    fprintf( pFile, "Memory used for cache      = %6.2f MB.\n", 1.0*Mem_FlexReadMemUsage(p->pMemEnts)/(1<<20) );
+    fprintf( pFile, "Cache hits    = %8d %8d\n", p->nCacheHits[0],    p->nCacheHits[1] );
+    fprintf( pFile, "Cache misses  = %8d %8d\n", p->nCacheMisses[0],  p->nCacheMisses[1] );
+    fprintf( pFile, "Cache entries = %8d %8d\n", p->nCacheEntries[0], p->nCacheEntries[1] );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+//    Dss_ManHashProfile( p );
+//    Dss_ManDump( p );
+//    return;
+    Dss_VecForEachObj( p->vObjs, pObj, i )
+    {
+        if ( i == 50 )
+            break;
+        Dss_ManPrintOne( pFile, p, Dss_Obj2Lit(pObj), NULL );
+    }
+    fprintf( pFile, "\n" );
+    if ( pFileName )
+        fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dss_ManComputeTruth_rec( Dss_Man_t * p, Dss_Obj_t * pObj, int nVars, word * pRes, int * pPermLits, int * pnSupp )
+{
+    Dss_Obj_t * pChild;
+    int nWords = Abc_TtWordNum(nVars);
+    int i, fCompl = Dss_IsComplement(pObj);
+    pObj = Dss_Regular(pObj);
+    if ( pObj->Type == DAU_DSD_VAR )
+    {
+        int iPermLit = pPermLits[(*pnSupp)++];
+        assert( (*pnSupp) <= nVars );
+        Abc_TtCopy( pRes, p->pTtElems[Abc_Lit2Var(iPermLit)], nWords, fCompl ^ Abc_LitIsCompl(iPermLit) );
+        return;
+    }
+    if ( pObj->Type == DAU_DSD_AND || pObj->Type == DAU_DSD_XOR )
+    {
+        word pTtTemp[DAU_MAX_WORD];
+        if ( pObj->Type == DAU_DSD_AND )
+            Abc_TtConst1( pRes, nWords );
+        else
+            Abc_TtConst0( pRes, nWords );
+        Dss_ObjForEachChild( p->vObjs, pObj, pChild, i )
+        {
+            Dss_ManComputeTruth_rec( p, pChild, nVars, pTtTemp, pPermLits, pnSupp );
+            if ( pObj->Type == DAU_DSD_AND )
+                Abc_TtAnd( pRes, pRes, pTtTemp, nWords, 0 );
+            else
+                Abc_TtXor( pRes, pRes, pTtTemp, nWords, 0 );
+        }
+        if ( fCompl ) Abc_TtNot( pRes, nWords );
+        return;
+    }
+    if ( pObj->Type == DAU_DSD_MUX ) // mux
+    {
+        word pTtTemp[3][DAU_MAX_WORD];
+        Dss_ObjForEachChild( p->vObjs, pObj, pChild, i )
+            Dss_ManComputeTruth_rec( p, pChild, nVars, pTtTemp[i], pPermLits, pnSupp );
+        assert( i == 3 );
+        Abc_TtMux( pRes, pTtTemp[0], pTtTemp[1], pTtTemp[2], nWords );
+        if ( fCompl ) Abc_TtNot( pRes, nWords );
+        return;
+    }
+    if ( pObj->Type == DAU_DSD_PRIME ) // function
+    {
+        word pFanins[DAU_MAX_VAR][DAU_MAX_WORD];
+        Dss_ObjForEachChild( p->vObjs, pObj, pChild, i )
+            Dss_ManComputeTruth_rec( p, pChild, nVars, pFanins[i], pPermLits, pnSupp );
+        Dau_DsdTruthCompose_rec( Dss_ObjTruth(pObj), pFanins, pRes, pObj->nFans, nWords );
+        if ( fCompl ) Abc_TtNot( pRes, nWords );
+        return;
+    }
+    assert( 0 );
+
+}
+word * Dss_ManComputeTruth( Dss_Man_t * p, int iDsd, int nVars, int * pPermLits )
+{
+    Dss_Obj_t * pObj = Dss_Lit2Obj(p->vObjs, iDsd);
+    word * pRes = p->pTtElems[DAU_MAX_VAR];
+    int nWords = Abc_TtWordNum( nVars );
+    int nSupp = 0;
+    assert( nVars <= DAU_MAX_VAR );
+    if ( iDsd == 0 )
+        Abc_TtConst0( pRes, nWords );
+    else if ( iDsd == 1 )
+        Abc_TtConst1( pRes, nWords );
+    else if ( Dss_Regular(pObj)->Type == DAU_DSD_VAR )
+    {
+        int iPermLit = pPermLits[nSupp++];
+        Abc_TtCopy( pRes, p->pTtElems[Abc_Lit2Var(iPermLit)], nWords, Abc_LitIsCompl(iDsd) ^ Abc_LitIsCompl(iPermLit) );
+    }
+    else
+        Dss_ManComputeTruth_rec( p, pObj, nVars, pRes, pPermLits, &nSupp );
+    assert( nSupp == (int)Dss_Regular(pObj)->nSupp );
+    return pRes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+// returns literal of non-shifted tree in p, corresponding to pObj in pNtk, which may be compl
+int Dss_NtkRebuild_rec( Dss_Man_t * p, Dss_Ntk_t * pNtk, Dss_Obj_t * pObj )
+{
+    Dss_Obj_t * pChildren[DAU_MAX_VAR];
+    Dss_Obj_t * pChild, * pObjNew;
+    int i, k, fCompl = Dss_IsComplement(pObj);
+    pObj = Dss_Regular(pObj);
+    if ( pObj->Type == DAU_DSD_VAR )
+        return Abc_Var2Lit( 1, fCompl );
+    Dss_ObjForEachChild( pNtk->vObjs, pObj, pChild, k )
+    {
+        pChildren[k] = Dss_Lit2Obj( p->vObjs, Dss_NtkRebuild_rec( p, pNtk, pChild ) );
+        if ( pObj->Type == DAU_DSD_XOR && Dss_IsComplement(pChildren[k]) )
+            pChildren[k] = Dss_Not(pChildren[k]), fCompl ^= 1;
+    }
+    // normalize MUX
+    if ( pObj->Type == DAU_DSD_MUX )
+    {
+        if ( Dss_IsComplement(pChildren[0]) )
+        {
+            pChildren[0] = Dss_Not(pChildren[0]);
+            ABC_SWAP( Dss_Obj_t *, pChildren[1], pChildren[2] );
+        }
+        if ( Dss_IsComplement(pChildren[1]) )
+        {
+            pChildren[1] = Dss_Not(pChildren[1]);
+            pChildren[2] = Dss_Not(pChildren[2]);
+            fCompl ^= 1;
+        }
+    }
+    // shift subgraphs
+    Vec_IntClear( p->vLeaves );
+    for ( i = 0; i < k; i++ )
+        Vec_IntPush( p->vLeaves, Dss_Obj2Lit(pChildren[i]) );
+    // create new graph
+    pObjNew = Dss_ObjFindOrAdd( p, pObj->Type, p->vLeaves, pObj->Type == DAU_DSD_PRIME ? Dss_ObjTruth(pObj) : NULL );
+    return Abc_Var2Lit( pObjNew->Id, fCompl );
+}
+int Dss_NtkRebuild( Dss_Man_t * p, Dss_Ntk_t * pNtk )
+{
+    assert( p->nVars == pNtk->nVars );
+    if ( Dss_Regular(pNtk->pRoot)->Type == DAU_DSD_CONST0 )
+        return Dss_IsComplement(pNtk->pRoot);
+    if ( Dss_Regular(pNtk->pRoot)->Type == DAU_DSD_VAR )
+        return Abc_Var2Lit( Dss_Regular(pNtk->pRoot)->iVar + 1, Dss_IsComplement(pNtk->pRoot) );
+    return Dss_NtkRebuild_rec( p, pNtk, pNtk->pRoot );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DSD operation on the two literals.]
+
+  Description [Returns the perm of the resulting literals. The perm size 
+  is equal to the number of support variables. The perm variables are 0-based
+  numbers of pLits[0] followed by nLits[0]-based numbers of pLits[1].]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dss_ManOperation( Dss_Man_t * p, int Type, int * pLits, int nLits, unsigned char * pPerm, word * pTruth )
+{
+    Dss_Obj_t * pChildren[DAU_MAX_VAR];
+    Dss_Obj_t * pObj, * pChild;
+    int i, k, nChildren = 0, fCompl = 0, fComplFan;
+
+    assert( Type == DAU_DSD_AND || pPerm == NULL );
+    if ( Type == DAU_DSD_AND && pPerm != NULL )
+    {
+        int pBegEnd[DAU_MAX_VAR];
+        int j, nSSize = 0;
+        for ( k = 0; k < nLits; k++ )
+        {
+            pObj = Dss_Lit2Obj(p->vObjs, pLits[k]);
+            if ( Dss_IsComplement(pObj) || pObj->Type != DAU_DSD_AND )
+            {
+                fComplFan = (Dss_Regular(pObj)->Type == DAU_DSD_VAR && Dss_IsComplement(pObj));
+                if ( fComplFan )
+                    pObj = Dss_Regular(pObj);
+                pBegEnd[nChildren] = (nSSize << 16) | (fComplFan << 8) | (nSSize + Dss_Regular(pObj)->nSupp);
+                nSSize += Dss_Regular(pObj)->nSupp;
+                pChildren[nChildren++] = pObj;
+            }
+            else
+                Dss_ObjForEachChild( p->vObjs, pObj, pChild, i )
+                {
+                    fComplFan = (Dss_Regular(pChild)->Type == DAU_DSD_VAR && Dss_IsComplement(pChild));
+                    if ( fComplFan )
+                        pChild = Dss_Regular(pChild);
+                    pBegEnd[nChildren] = (nSSize << 16) | (fComplFan << 8) | (nSSize + Dss_Regular(pChild)->nSupp);
+                    nSSize += Dss_Regular(pChild)->nSupp;
+                    pChildren[nChildren++] = pChild;
+                }
+        }
+        Dss_ObjSort( p->vObjs, pChildren, nChildren, pBegEnd );
+        // create permutation
+        for ( j = i = 0; i < nChildren; i++ )
+            for ( k = (pBegEnd[i] >> 16); k < (pBegEnd[i] & 0xFF); k++ )
+                pPerm[j++] = (unsigned char)Abc_Var2Lit( k, (pBegEnd[i] >> 8) & 1 );
+        assert( j == nSSize );
+    }
+    else if ( Type == DAU_DSD_AND )
+    {
+        for ( k = 0; k < nLits; k++ )
+        {
+            pObj = Dss_Lit2Obj(p->vObjs, pLits[k]);
+            if ( Dss_IsComplement(pObj) || pObj->Type != DAU_DSD_AND )
+                pChildren[nChildren++] = pObj;
+            else
+                Dss_ObjForEachChild( p->vObjs, pObj, pChild, i )
+                    pChildren[nChildren++] = pChild;
+        }
+        Dss_ObjSort( p->vObjs, pChildren, nChildren, NULL );
+    }
+    else if ( Type == DAU_DSD_XOR )
+    {
+        for ( k = 0; k < nLits; k++ )
+        {
+            fCompl ^= Abc_LitIsCompl(pLits[k]);
+            pObj = Dss_Lit2Obj(p->vObjs, Abc_LitRegular(pLits[k]));
+            if ( pObj->Type != DAU_DSD_XOR )
+                pChildren[nChildren++] = pObj;
+            else
+                Dss_ObjForEachChild( p->vObjs, pObj, pChild, i )
+                {
+                    assert( !Dss_IsComplement(pChild) );
+                    pChildren[nChildren++] = pChild;
+                }
+        }
+        Dss_ObjSort( p->vObjs, pChildren, nChildren, NULL );
+    }
+    else if ( Type == DAU_DSD_MUX )
+    {
+        if ( Abc_LitIsCompl(pLits[0]) )
+        {
+            pLits[0] = Abc_LitNot(pLits[0]);
+            ABC_SWAP( int, pLits[1], pLits[2] );
+        }
+        if ( Abc_LitIsCompl(pLits[1]) )
+        {
+            pLits[1] = Abc_LitNot(pLits[1]);
+            pLits[2] = Abc_LitNot(pLits[2]);
+            fCompl ^= 1;
+        }
+        for ( k = 0; k < nLits; k++ )
+            pChildren[nChildren++] = Dss_Lit2Obj(p->vObjs, pLits[k]);
+    }
+    else if ( Type == DAU_DSD_PRIME )
+    {
+        for ( k = 0; k < nLits; k++ )
+            pChildren[nChildren++] = Dss_Lit2Obj(p->vObjs, pLits[k]);
+    }
+    else assert( 0 );
+
+    // shift subgraphs
+    Vec_IntClear( p->vLeaves );
+    for ( i = 0; i < nChildren; i++ )
+        Vec_IntPush( p->vLeaves, Dss_Obj2Lit(pChildren[i]) );
+    // create new graph
+    pObj = Dss_ObjFindOrAdd( p, Type, p->vLeaves, pTruth );
+    return Abc_Var2Lit( pObj->Id, fCompl );
+}
+Dss_Fun_t * Dss_ManOperationFun( Dss_Man_t * p, int * iDsd, int nFansTot )
+{
+    static char Buffer[100];
+    Dss_Fun_t * pFun = (Dss_Fun_t *)Buffer;
+    pFun->iDsd = Dss_ManOperation( p, DAU_DSD_AND, iDsd, 2, pFun->pFans, NULL );
+//printf( "%d %d -> %d  ", iDsd[0], iDsd[1], pFun->iDsd );
+    pFun->nFans = nFansTot;
+    assert( (int)pFun->nFans == Dss_VecLitSuppSize(p->vObjs, pFun->iDsd) );
+    return pFun;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dss_EntPrint( Dss_Ent_t * p, Dss_Fun_t * pFun )
+{
+    int i;
+    printf( "%d %d ", p->iDsd0, p->iDsd1 );
+    for ( i = 0; i < (int)p->nShared; i++ )
+        printf( "%d=%d ", p->pShared[2*i], p->pShared[2*i+1] );
+    printf( "-> %d   ", pFun->iDsd );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs AND on two DSD functions with support overlap.]
+
+  Description [Returns the perm of the resulting literals. The perm size 
+  is equal to the number of support variables. The perm variables are 0-based
+  numbers of pLits[0] followed by nLits[0]-based numbers of pLits[1].]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dss_Fun_t * Dss_ManBooleanAnd( Dss_Man_t * p, Dss_Ent_t * pEnt, int Counter )
+{
+    static char Buffer[100];
+    Dss_Fun_t * pFun = (Dss_Fun_t *)Buffer;
+    Dss_Ntk_t * pNtk;
+    word * pTruthOne, pTruth[DAU_MAX_WORD];
+    char pDsd[DAU_MAX_STR];
+    int pMapDsd2Truth[DAU_MAX_VAR];
+    int pPermLits[DAU_MAX_VAR];
+    int pPermDsd[DAU_MAX_VAR];
+    int i, nNonDec, nSuppSize = 0;
+    int nFans[2];
+    nFans[0] = Dss_VecLitSuppSize( p->vObjs, pEnt->iDsd0 );
+    nFans[1] = Dss_VecLitSuppSize( p->vObjs, pEnt->iDsd1 );
+    // create first truth table
+    for ( i = 0; i < nFans[0]; i++ )
+    {
+        pMapDsd2Truth[nSuppSize] = i;
+        pPermLits[i] = Abc_Var2Lit( nSuppSize++, 0 );
+    }
+    pTruthOne = Dss_ManComputeTruth( p, pEnt->iDsd0, p->nVars, pPermLits );
+    Abc_TtCopy( pTruth, pTruthOne, Abc_TtWordNum(p->nVars), 0 );
+if ( Counter )
+{
+//Kit_DsdPrintFromTruth( pTruthOne, p->nVars );  printf( "\n" );
+}
+    // create second truth table
+    for ( i = 0; i < nFans[1]; i++ )
+        pPermLits[i] = -1;
+    for ( i = 0; i < (int)pEnt->nShared; i++ )
+        pPermLits[pEnt->pShared[2*i+0]] = pEnt->pShared[2*i+1];
+    for ( i = 0; i < nFans[1]; i++ )
+        if ( pPermLits[i] == -1 )
+        {
+            pMapDsd2Truth[nSuppSize] = nFans[0] + i;
+            pPermLits[i] = Abc_Var2Lit( nSuppSize++, 0 );
+        }
+    pTruthOne = Dss_ManComputeTruth( p, pEnt->iDsd1, p->nVars, pPermLits );
+if ( Counter )
+{
+//Kit_DsdPrintFromTruth( pTruthOne, p->nVars );  printf( "\n" );
+}
+    Abc_TtAnd( pTruth, pTruth, pTruthOne, Abc_TtWordNum(p->nVars), 0 );
+    // perform decomposition
+    nNonDec = Dau_DsdDecompose( pTruth, nSuppSize, 0, 0, pDsd );
+    if ( p->nNonDecLimit && nNonDec > p->nNonDecLimit )
+        return NULL;
+    // derive network and convert it into the manager
+    pNtk = Dss_NtkCreate( pDsd, p->nVars, nNonDec ? pTruth : NULL );
+//Dss_NtkPrint( pNtk );    
+    Dss_NtkCheck( pNtk );
+    Dss_NtkTransform( pNtk, pPermDsd );
+//Dss_NtkPrint( pNtk );    
+    pFun->iDsd = Dss_NtkRebuild( p, pNtk );
+    Dss_NtkFree( pNtk );
+    // pPermDsd maps vars of iDsdRes into literals of pTruth
+    // translate this map into the one that maps vars of iDsdRes into literals of cut
+    pFun->nFans = Dss_VecLitSuppSize( p->vObjs, pFun->iDsd );
+    for ( i = 0; i < (int)pFun->nFans; i++ )
+        pFun->pFans[i] = (unsigned char)Abc_Lit2LitV( pMapDsd2Truth, pPermDsd[i] );
+
+//    Dss_EntPrint( pEnt, pFun );
+    return pFun;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+// returns mapping of variables of dsd1 into literals of dsd0
+Dss_Ent_t * Dss_ManSharedMap( Dss_Man_t * p, int * iDsd, int * nFans, int ** pFans, unsigned uSharedMask )
+{
+    static char Buffer[100];
+    Dss_Ent_t * pEnt = (Dss_Ent_t *)Buffer;
+    pEnt->iDsd0 = iDsd[0];
+    pEnt->iDsd1 = iDsd[1];
+    pEnt->nShared = 0;
+    if ( uSharedMask )
+    {
+        int i, g, pMapGtoL[DAU_MAX_VAR] = {-1};
+        for ( i = 0; i < nFans[0]; i++ )
+            pMapGtoL[ Abc_Lit2Var(pFans[0][i]) ] = Abc_Var2Lit( i, Abc_LitIsCompl(pFans[0][i]) );
+        for ( i = 0; i < nFans[1]; i++ )
+        {
+            g = Abc_Lit2Var( pFans[1][i] );
+            if ( (uSharedMask >> g) & 1 )
+            {
+                assert( pMapGtoL[g] >= 0 );
+                pEnt->pShared[2*pEnt->nShared+0] = (unsigned char)i;
+                pEnt->pShared[2*pEnt->nShared+1] = (unsigned char)Abc_LitNotCond( pMapGtoL[g], Abc_LitIsCompl(pFans[1][i]) );
+                pEnt->nShared++;
+            }
+        }
+    }
+    pEnt->nWords = Dss_EntWordNum( pEnt );
+    return pEnt;
+}
+
+// merge two DSD functions
+int Dss_ManMerge( Dss_Man_t * p, int * iDsd, int * nFans, int ** pFans, unsigned uSharedMask, int nKLutSize, unsigned char * pPermRes, word * pTruth )
+{
+    int fVerbose = 0;
+    int fCheck = 0;
+    static int Counter = 0;
+//    word pTtTemp[DAU_MAX_WORD];
+    word * pTruthOne;
+    int pPermResInt[DAU_MAX_VAR];
+    Dss_Ent_t * pEnt, ** ppSpot;
+    Dss_Fun_t * pFun;
+    int i;
+    abctime clk;
+    Counter++;
+    if ( DAU_MAX_VAR < nKLutSize )
+    {
+        printf( "Paramater DAU_MAX_VAR (%d) smaller than LUT size (%d).\n", DAU_MAX_VAR, nKLutSize );
+        return -1;
+    }
+    assert( iDsd[0] <= iDsd[1] );
+
+if ( fVerbose )
+{
+Dss_ManPrintOne( stdout, p, iDsd[0], pFans[0] );
+Dss_ManPrintOne( stdout, p, iDsd[1], pFans[1] );
+} 
+
+    // constant argument
+    if ( iDsd[0] == 0 ) return 0;
+    if ( iDsd[0] == 1 ) return iDsd[1];
+    if ( iDsd[1] == 0 ) return 0;
+    if ( iDsd[1] == 1 ) return iDsd[0];
+
+    // no overlap
+clk = Abc_Clock();
+    assert( nFans[0] == Dss_VecLitSuppSize(p->vObjs, iDsd[0]) );
+    assert( nFans[1] == Dss_VecLitSuppSize(p->vObjs, iDsd[1]) );
+    assert( nFans[0] + nFans[1] <= nKLutSize + Dss_WordCountOnes(uSharedMask) );
+    // create map of shared variables
+    pEnt = Dss_ManSharedMap( p, iDsd, nFans, pFans, uSharedMask );
+p->timeBeg += Abc_Clock() - clk;
+    // check cache
+    if ( p->pCache == NULL )
+    {
+clk = Abc_Clock();
+        if ( uSharedMask == 0 )
+            pFun = Dss_ManOperationFun( p, iDsd, nFans[0] + nFans[1] );
+        else
+            pFun = Dss_ManBooleanAnd( p, pEnt, 0 );
+        if ( pFun == NULL )
+            return -1;
+        assert( (int)pFun->nFans == Dss_VecLitSuppSize(p->vObjs, pFun->iDsd) );
+        assert( (int)pFun->nFans <= nKLutSize );
+p->timeDec += Abc_Clock() - clk;
+    }
+    else
+    {
+clk = Abc_Clock();
+        ppSpot = Dss_ManCacheLookup( p, pEnt );
+p->timeLook += Abc_Clock() - clk;
+clk = Abc_Clock();
+        if ( *ppSpot == NULL )
+        {
+            if ( uSharedMask == 0 )
+                pFun = Dss_ManOperationFun( p, iDsd, nFans[0] + nFans[1] );
+            else
+                pFun = Dss_ManBooleanAnd( p, pEnt, 0 );
+            if ( pFun == NULL )
+                return -1;
+            assert( (int)pFun->nFans == Dss_VecLitSuppSize(p->vObjs, pFun->iDsd) );
+            assert( (int)pFun->nFans <= nKLutSize );
+            // create cache entry
+            *ppSpot = Dss_ManCacheCreate( p, pEnt, pFun );
+        }
+        pFun = (*ppSpot)->pFunc;
+p->timeDec += Abc_Clock() - clk;
+    }
+
+clk = Abc_Clock();
+    for ( i = 0; i < (int)pFun->nFans; i++ )
+        if ( pFun->pFans[i] < 2 * nFans[0] ) // first dec
+            pPermRes[i] = (unsigned char)Dss_Lit2Lit( pFans[0], pFun->pFans[i] );
+        else
+            pPermRes[i] = (unsigned char)Dss_Lit2Lit( pFans[1], pFun->pFans[i] - 2 * nFans[0] );
+    // perform support minimization
+    if ( uSharedMask && pFun->nFans > 1 )
+    {
+        int pVarPres[DAU_MAX_VAR];
+        int nSupp = 0;
+        for ( i = 0; i < p->nVars; i++ )
+            pVarPres[i] = -1;
+        for ( i = 0; i < (int)pFun->nFans; i++ )
+            pVarPres[ Abc_Lit2Var(pPermRes[i]) ] = i;
+        for ( i = 0; i < p->nVars; i++ )
+            if ( pVarPres[i] >= 0 )
+                pPermRes[pVarPres[i]] = Abc_Var2Lit( nSupp++, Abc_LitIsCompl(pPermRes[pVarPres[i]]) );
+        assert( nSupp == (int)pFun->nFans );
+    }
+
+    for ( i = 0; i < (int)pFun->nFans; i++ )
+        pPermResInt[i] = pPermRes[i];
+p->timeEnd += Abc_Clock() - clk;
+
+if ( fVerbose )
+{
+Dss_ManPrintOne( stdout, p, pFun->iDsd, pPermResInt );
+printf( "\n" );
+}
+
+if ( Counter == 43418 )
+{
+//    int s = 0;
+//    Dss_ManPrint( NULL, p );
+}
+
+
+    if ( fCheck )
+    {
+        pTruthOne = Dss_ManComputeTruth( p, pFun->iDsd, p->nVars, pPermResInt );
+        if ( !Abc_TtEqual( pTruthOne, pTruth, Abc_TtWordNum(p->nVars) ) )
+        {
+            int s;
+    //        Kit_DsdPrintFromTruth( pTruthOne, p->nVars );  printf( "\n" );
+    //        Kit_DsdPrintFromTruth( pTruth, p->nVars );     printf( "\n" );
+            printf( "Verification failed.\n" );
+            s = 0;
+        }
+    }
+    return pFun->iDsd;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dss_Ent_t * Dss_ManSharedMapDerive( Dss_Man_t * p, int iDsd0, int iDsd1, Vec_Str_t * vShared )
+{
+    static char Buffer[100];
+    Dss_Ent_t * pEnt = (Dss_Ent_t *)Buffer;
+    pEnt->iDsd0 = iDsd0;
+    pEnt->iDsd1 = iDsd1;
+    pEnt->nShared = Vec_StrSize(vShared)/2;
+    memcpy( pEnt->pShared, (unsigned char *)Vec_StrArray(vShared), sizeof(char) * Vec_StrSize(vShared) );
+    pEnt->nWords = Dss_EntWordNum( pEnt );
+    return pEnt;
+}
+
+int Mpm_FuncCompute( Dss_Man_t * p, int iDsd0, int iDsd1, Vec_Str_t * vShared, int * pPerm, int * pnLeaves )
+{
+    int fVerbose = 0;
+//    int fCheck = 0;
+    Dss_Ent_t * pEnt, ** ppSpot;
+    Dss_Fun_t * pFun;
+    int iDsd[2] = { iDsd0, iDsd1 };
+    int i;
+    abctime clk;
+
+    assert( iDsd0 <= iDsd1 );
+    if ( DAU_MAX_VAR < *pnLeaves )
+    {
+        printf( "Paramater DAU_MAX_VAR (%d) smaller than LUT size (%d).\n", DAU_MAX_VAR, *pnLeaves );
+        return -1;
+    }
+    if ( fVerbose )
+    {
+        Dss_ManPrintOne( stdout, p, iDsd0, NULL );
+        Dss_ManPrintOne( stdout, p, iDsd1, NULL );
+    } 
+
+clk = Abc_Clock();
+    pEnt = Dss_ManSharedMapDerive( p, iDsd0, iDsd1, vShared );
+    ppSpot = Dss_ManCacheLookup( p, pEnt );
+p->timeLook += Abc_Clock() - clk;
+
+clk = Abc_Clock();
+    if ( *ppSpot == NULL )
+    {
+        if ( Vec_StrSize(vShared) == 0 )
+            pFun = Dss_ManOperationFun( p, iDsd, *pnLeaves );
+        else
+            pFun = Dss_ManBooleanAnd( p, pEnt, 0 );
+        if ( pFun == NULL )
+            return -1;
+        assert( (int)pFun->nFans == Dss_VecLitSuppSize(p->vObjs, pFun->iDsd) );
+        assert( (int)pFun->nFans <= *pnLeaves );
+        // create cache entry
+        *ppSpot = Dss_ManCacheCreate( p, pEnt, pFun );
+    }
+    pFun = (*ppSpot)->pFunc;
+p->timeDec += Abc_Clock() - clk;
+
+    *pnLeaves = (int)pFun->nFans;
+    for ( i = 0; i < (int)pFun->nFans; i++ )
+        pPerm[i] = (int)pFun->pFans[i];
+
+    if ( fVerbose )
+    {
+        Dss_ManPrintOne( stdout, p, pFun->iDsd, NULL );
+        printf( "\n" );
+    }
+
+/*
+    if ( fCheck )
+    {
+        pTruthOne = Dss_ManComputeTruth( p, pFun->iDsd, p->nVars, pPermResInt );
+        if ( !Abc_TtEqual( pTruthOne, pTruth, Abc_TtWordNum(p->nVars) ) )
+        {
+            int s;
+    //        Kit_DsdPrintFromTruth( pTruthOne, p->nVars );  printf( "\n" );
+    //        Kit_DsdPrintFromTruth( pTruth, p->nVars );     printf( "\n" );
+            printf( "Verification failed.\n" );
+            s = 0;
+        }
+    }
+*/
+    return pFun->iDsd;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dss_ObjCheckTransparent( Dss_Man_t * p, Dss_Obj_t * pObj )
+{
+    Dss_Obj_t * pFanin;
+    int i;
+    if ( pObj->Type == DAU_DSD_VAR )
+        return 1;
+    if ( pObj->Type == DAU_DSD_AND )
+        return 0;
+    if ( pObj->Type == DAU_DSD_XOR )
+    {
+        Dss_ObjForEachFanin( p->vObjs, pObj, pFanin, i )
+            if ( Dss_ObjCheckTransparent( p, pFanin ) )
+                return 1;
+        return 0;
+    }
+    if ( pObj->Type == DAU_DSD_MUX )
+    {
+        pFanin = Dss_ObjFanin( p->vObjs, pObj, 1 );
+        if ( !Dss_ObjCheckTransparent(p, pFanin) )
+            return 0;
+        pFanin = Dss_ObjFanin( p->vObjs, pObj, 2 );
+        if ( !Dss_ObjCheckTransparent(p, pFanin) )
+            return 0;
+        return 1;
+    }
+    assert( pObj->Type == DAU_DSD_PRIME );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dau_DsdTest__()
+{
+    int nVars = 8;
+//    char * pDsd = "[(ab)(cd)]";
+    char * pDsd = "(!(a!(bh))[cde]!(fg))";
+    Dss_Ntk_t * pNtk = Dss_NtkCreate( pDsd, nVars, NULL );
+//    Dss_NtkPrint( pNtk );
+//    Dss_NtkCheck( pNtk );
+//    Dss_NtkTransform( pNtk );
+//    Dss_NtkPrint( pNtk );
+    Dss_NtkFree( pNtk );
+    nVars = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dau_DsdTest()
+{
+    int nVars = 8;
+    Vec_Vec_t * vFuncs;
+    Vec_Int_t * vOne, * vTwo, * vRes;//, * vThree;
+    Dss_Man_t * p;
+    int pEntries[3];
+    int iLit, e0, e1;//, e2;
+    int i, k, s;//, j;
+
+    return;
+
+    vFuncs = Vec_VecStart( nVars+1 );
+    assert( nVars < DAU_MAX_VAR );
+    p = Dss_ManAlloc( nVars, 0 );
+
+    // init
+    Vec_VecPushInt( vFuncs, 1, Dss_Obj2Lit(Dss_VecVar(p->vObjs,0)) );
+
+    // enumerate
+    for ( s = 2; s <= nVars; s++ )
+    {
+        vRes = Vec_VecEntryInt( vFuncs, s );
+        for ( i = 1; i < s; i++ )
+        for ( k = i; k < s; k++ )
+        if ( i + k == s )
+        {
+            vOne = Vec_VecEntryInt( vFuncs, i );
+            vTwo = Vec_VecEntryInt( vFuncs, k );
+            Vec_IntForEachEntry( vOne, pEntries[0], e0 )
+            Vec_IntForEachEntry( vTwo, pEntries[1], e1 )
+            {
+                int fAddInv0 = !Dss_ObjCheckTransparent( p, Dss_VecObj(p->vObjs, Abc_Lit2Var(pEntries[0])) );
+                int fAddInv1 = !Dss_ObjCheckTransparent( p, Dss_VecObj(p->vObjs, Abc_Lit2Var(pEntries[1])) );
+
+                iLit = Dss_ManOperation( p, DAU_DSD_AND, pEntries, 2, NULL, NULL );
+                assert( !Abc_LitIsCompl(iLit) );
+                Vec_IntPush( vRes, iLit );
+
+                if ( fAddInv0 )
+                {
+                    pEntries[0] = Abc_LitNot( pEntries[0] );
+                    iLit = Dss_ManOperation( p, DAU_DSD_AND, pEntries, 2, NULL, NULL );
+                    pEntries[0] = Abc_LitNot( pEntries[0] );
+                    assert( !Abc_LitIsCompl(iLit) );
+                    Vec_IntPush( vRes, iLit );
+                }
+
+                if ( fAddInv1 )
+                {
+                    pEntries[1] = Abc_LitNot( pEntries[1] );
+                    iLit = Dss_ManOperation( p, DAU_DSD_AND, pEntries, 2, NULL, NULL );
+                    pEntries[1] = Abc_LitNot( pEntries[1] );
+                    assert( !Abc_LitIsCompl(iLit) );
+                    Vec_IntPush( vRes, iLit );
+                }
+
+                if ( fAddInv0 && fAddInv1 )
+                {
+                    pEntries[0] = Abc_LitNot( pEntries[0] );
+                    pEntries[1] = Abc_LitNot( pEntries[1] );
+                    iLit = Dss_ManOperation( p, DAU_DSD_AND, pEntries, 2, NULL, NULL );
+                    pEntries[0] = Abc_LitNot( pEntries[0] );
+                    pEntries[1] = Abc_LitNot( pEntries[1] );
+                    assert( !Abc_LitIsCompl(iLit) );
+                    Vec_IntPush( vRes, iLit );
+                }
+
+                iLit = Dss_ManOperation( p, DAU_DSD_XOR, pEntries, 2, NULL, NULL );
+                assert( !Abc_LitIsCompl(iLit) );
+                Vec_IntPush( vRes, Abc_LitRegular(iLit) );
+            }
+        }
+/*
+        for ( i = 1; i < s; i++ )
+        for ( k = 1; k < s; k++ )
+        for ( j = 1; j < s; j++ )
+        if ( i + k + j == s )
+        {
+            vOne   = Vec_VecEntryInt( vFuncs, i );
+            vTwo   = Vec_VecEntryInt( vFuncs, k );
+            vThree = Vec_VecEntryInt( vFuncs, j );
+            Vec_IntForEachEntry( vOne,   pEntries[0], e0 )
+            Vec_IntForEachEntry( vTwo,   pEntries[1], e1 )
+            Vec_IntForEachEntry( vThree, pEntries[2], e2 )
+            {
+                int fAddInv0 = !Dss_ObjCheckTransparent( p, Dss_VecObj(p->vObjs, Abc_Lit2Var(pEntries[0])) );
+                int fAddInv1 = !Dss_ObjCheckTransparent( p, Dss_VecObj(p->vObjs, Abc_Lit2Var(pEntries[1])) );
+                int fAddInv2 = !Dss_ObjCheckTransparent( p, Dss_VecObj(p->vObjs, Abc_Lit2Var(pEntries[2])) );
+
+                if ( !fAddInv0 && k > j )
+                    continue;
+
+                iLit = Dss_ManOperation( p, DAU_DSD_MUX, pEntries, 3, NULL, NULL );
+                assert( !Abc_LitIsCompl(iLit) );
+                Vec_IntPush( vRes, iLit );
+
+                if ( fAddInv1 )
+                {
+                    pEntries[1] = Abc_LitNot( pEntries[1] );
+                    iLit = Dss_ManOperation( p, DAU_DSD_MUX, pEntries, 3, NULL, NULL );
+                    pEntries[1] = Abc_LitNot( pEntries[1] );
+                    assert( !Abc_LitIsCompl(iLit) );
+                    Vec_IntPush( vRes, iLit );
+                }
+
+                if ( fAddInv2 )
+                {
+                    pEntries[2] = Abc_LitNot( pEntries[2] );
+                    iLit = Dss_ManOperation( p, DAU_DSD_MUX, pEntries, 3, NULL, NULL );
+                    pEntries[2] = Abc_LitNot( pEntries[2] );
+                    assert( !Abc_LitIsCompl(iLit) );
+                    Vec_IntPush( vRes, iLit );
+                }
+            }
+        }
+*/
+        Vec_IntUniqify( vRes );
+    }
+    Dss_ManPrint( "_npn/npn/dsdcanon.txt", p );
+
+    Dss_ManFree( p );
+    Vec_VecFree( vFuncs );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dau_DsdTest444()
+{
+    Dss_Man_t * p = Dss_ManAlloc( 6, 0 );
+    int iLit1[3] = { 2, 4 };
+    int iLit2[3] = { 2, 4, 6 };
+    int iRes[5];
+    int nFans[2] = { 4, 3 };
+    int pPermLits1[4] = { 0, 2, 5, 6 };
+    int pPermLits2[5] = { 2, 9, 10 };
+    int * pPermLits[2] = { pPermLits1, pPermLits2 };
+    unsigned char pPermRes[6];
+    int pPermResInt[6];
+    unsigned uMaskShared = 2;
+    int i;
+
+    iRes[0] = 1 ^ Dss_ManOperation( p, DAU_DSD_AND, iLit1, 2, NULL, NULL );
+    iRes[1] = iRes[0]; 
+    iRes[2] = 1 ^ Dss_ManOperation( p, DAU_DSD_AND, iRes, 2, NULL, NULL );
+    iRes[3] = Dss_ManOperation( p, DAU_DSD_AND, iLit2, 3, NULL, NULL );
+
+    Dss_ManPrintOne( stdout, p, iRes[0], NULL );
+    Dss_ManPrintOne( stdout, p, iRes[2], NULL );
+    Dss_ManPrintOne( stdout, p, iRes[3], NULL );
+
+    Dss_ManPrintOne( stdout, p, iRes[2], pPermLits1 );
+    Dss_ManPrintOne( stdout, p, iRes[3], pPermLits2 );
+
+    iRes[4] = Dss_ManMerge( p, iRes+2, nFans, pPermLits, uMaskShared, 6, pPermRes, NULL );
+
+    for ( i = 0; i < 6; i++ )
+        pPermResInt[i] = pPermRes[i];
+
+    Dss_ManPrintOne( stdout, p, iRes[4], NULL );
+    Dss_ManPrintOne( stdout, p, iRes[4], pPermResInt );
+
+    Dss_ManFree( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/dau/module.make b/abc-build/src/opt/dau/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/dau/module.make
@@ -0,0 +1,9 @@
+SRC +=	src/opt/dau/dauCanon.c \
+	src/opt/dau/dauCore.c \
+	src/opt/dau/dauDivs.c \
+	src/opt/dau/dauDsd.c \
+	src/opt/dau/dauEnum.c \
+	src/opt/dau/dauGia.c \
+	src/opt/dau/dauMerge.c \
+	src/opt/dau/dauNonDsd.c \
+	src/opt/dau/dauTree.c
diff --git a/abc-build/src/opt/fsim/fsim.h b/abc-build/src/opt/fsim/fsim.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fsim/fsim.h
@@ -0,0 +1,101 @@
+/**CFile****************************************************************
+
+  FileName    [fsim.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast sequential AIG simulator.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: fsim.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__fsim__fsim_h
+#define ABC__aig__fsim__fsim_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Fsim_Man_t_ Fsim_Man_t;
+
+// simulation parameters
+typedef struct Fsim_ParSim_t_ Fsim_ParSim_t;
+struct Fsim_ParSim_t_
+{
+    // user-controlled parameters
+    int             nWords;       // the number of machine words
+    int             nIters;       // the number of timeframes
+    int             TimeLimit;    // time limit in seconds
+    int             fCheckMiter;  // check if miter outputs are non-zero
+    int             fVerbose;     // enables verbose output
+    // internal parameters
+    int             fCompressAig; // compresses internal data
+};
+
+// switching estimation parameters
+typedef struct Fsim_ParSwitch_t_ Fsim_ParSwitch_t;
+struct Fsim_ParSwitch_t_
+{
+    // user-controlled parameters
+    int             nWords;       // the number of machine words
+    int             nIters;       // the number of timeframes
+    int             nPref;        // the number of first timeframes to skip
+    int             nRandPiNum;   // PI trans prob (0=1/2; 1=1/4; 2=1/8, etc)
+    int             fProbOne;     // collect probability of one
+    int             fProbTrans;   // collect probatility of switching
+    int             fVerbose;     // enables verbose output
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== fsimCore.c ==========================================================*/
+extern void           Fsim_ManSetDefaultParamsSim( Fsim_ParSim_t * p );
+extern void           Fsim_ManSetDefaultParamsSwitch( Fsim_ParSwitch_t * p );
+/*=== fsimSim.c ==========================================================*/
+extern int            Fsim_ManSimulate( Aig_Man_t * pAig, Fsim_ParSim_t * pPars );
+/*=== fsimSwitch.c ==========================================================*/
+extern Vec_Int_t *    Fsim_ManSwitchSimulate( Aig_Man_t * pAig, Fsim_ParSwitch_t * pPars );
+/*=== fsimTsim.c ==========================================================*/
+extern Vec_Ptr_t *    Fsim_ManTerSimulate( Aig_Man_t * pAig, int fVerbose );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/fsim/fsimCore.c b/abc-build/src/opt/fsim/fsimCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fsim/fsimCore.c
@@ -0,0 +1,88 @@
+/**CFile****************************************************************
+
+  FileName    [fsimCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast sequential AIG simulator.]
+
+  Synopsis    [Core procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: fsimCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fsimInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fsim_ManSetDefaultParamsSim( Fsim_ParSim_t * p )
+{
+    memset( p, 0, sizeof(Fsim_ParSim_t) );
+    // user-controlled parameters
+    p->nWords       =   8;    // the number of machine words
+    p->nIters       =  32;    // the number of timeframes
+    p->TimeLimit    =  60;    // time limit in seconds
+    p->fCheckMiter  =   0;    // check if miter outputs are non-zero 
+    p->fVerbose     =   1;    // enables verbose output
+    // internal parameters
+    p->fCompressAig =   0;    // compresses internal data
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fsim_ManSetDefaultParamsSwitch( Fsim_ParSwitch_t * p )
+{
+    memset( p, 0, sizeof(Fsim_ParSwitch_t) );
+    // user-controlled parameters
+    p->nWords       =   1;    // the number of machine words
+    p->nIters       =  48;    // the number of timeframes
+    p->nPref        =  16;    // the number of first timeframes to skip
+    p->nRandPiNum   =   0;    // PI trans prob (0=1/2; 1=1/4; 2=1/8, etc)
+    p->fProbOne     =   1;    // collect probability of one
+    p->fProbTrans   =   1;    // collect probatility of switching
+    p->fVerbose     =   1;    // enables verbose output
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fsim/fsimFront.c b/abc-build/src/opt/fsim/fsimFront.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fsim/fsimFront.c
@@ -0,0 +1,369 @@
+/**CFile****************************************************************
+
+  FileName    [fsimFront.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast sequential AIG simulator.]
+
+  Synopsis    [Simulation frontier.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: fsimFront.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fsimInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManStoreNum( Fsim_Man_t * p, int Num )
+{
+    unsigned x = (unsigned)Num;
+    assert( Num >= 0 );
+    while ( x & ~0x7f )
+    {
+        *p->pDataCur++ = (x & 0x7f) | 0x80;
+        x >>= 7;
+    }
+    *p->pDataCur++ = x;
+    assert( p->pDataCur - p->pDataAig < p->nDataAig );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Fsim_ManRestoreNum( Fsim_Man_t * p )
+{
+    int ch, i, x = 0;
+    for ( i = 0; (ch = *p->pDataCur++) & 0x80; i++ )
+        x |= (ch & 0x7f) << (7 * i);
+    assert( p->pDataCur - p->pDataAig < p->nDataAig );
+    return x | (ch << (7 * i));
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManStoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj )
+{
+    if ( p->pDataAig2 )
+    {
+        *p->pDataCur2++ = pObj->iNode;
+        *p->pDataCur2++ = pObj->iFan0;
+        *p->pDataCur2++ = pObj->iFan1;
+        return;
+    }
+    if ( pObj->iFan0 && pObj->iFan1 ) // and
+    {
+        assert( pObj->iNode );
+        assert( pObj->iNode >= p->iNodePrev );
+        assert( (pObj->iNode << 1) > pObj->iFan0 );
+        assert( pObj->iFan0 > pObj->iFan1 );
+        Fsim_ManStoreNum( p, ((pObj->iNode - p->iNodePrev) << 2) | 3 );
+        Fsim_ManStoreNum( p, (pObj->iNode << 1) - pObj->iFan0 );
+        Fsim_ManStoreNum( p, pObj->iFan0 - pObj->iFan1 );
+        p->iNodePrev = pObj->iNode;
+    }
+    else if ( !pObj->iFan0 && !pObj->iFan1 ) // ci
+    {
+        assert( pObj->iNode );
+        assert( pObj->iNode >= p->iNodePrev );
+        Fsim_ManStoreNum( p, ((pObj->iNode - p->iNodePrev) << 2) | 1 );
+        p->iNodePrev = pObj->iNode;
+    }
+    else // if ( !pObj->iFan0 && pObj->iFan1 ) // co
+    {
+        assert( pObj->iNode == 0 );
+        assert( pObj->iFan0 != 0 );
+        assert( pObj->iFan1 == 0 );
+        assert( ((p->iNodePrev << 1) | 1) >= pObj->iFan0 );
+        Fsim_ManStoreNum( p, (((p->iNodePrev << 1) | 1) - pObj->iFan0) << 1 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Fsim_ManRestoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj )
+{
+    int iValue = Fsim_ManRestoreNum( p );
+    if ( (iValue & 3) == 3 ) // and
+    {
+        pObj->iNode = (iValue >> 2) + p->iNodePrev;
+        pObj->iFan0 = (pObj->iNode << 1) - Fsim_ManRestoreNum( p );
+        pObj->iFan1 = pObj->iFan0 - Fsim_ManRestoreNum( p );
+        p->iNodePrev = pObj->iNode;
+    }
+    else if ( (iValue & 3) == 1 ) // ci
+    {
+        pObj->iNode = (iValue >> 2) + p->iNodePrev;
+        pObj->iFan0 = 0;
+        pObj->iFan1 = 0;
+        p->iNodePrev = pObj->iNode;
+    }
+    else // if ( (iValue & 1) == 0 ) // co
+    {
+        pObj->iNode = 0;
+        pObj->iFan0 = ((p->iNodePrev << 1) | 1) - (iValue >> 1);
+        pObj->iFan1 = 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determine the frontier.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Fsim_ManFrontFindNext( Fsim_Man_t * p, char * pFront )
+{
+    assert( p->iNumber < (1 << 30) - p->nFront );
+    while ( 1 )
+    {
+        if ( p->iNumber % p->nFront == 0 )
+            p->iNumber++;
+        if ( pFront[p->iNumber % p->nFront] == 0 )
+        {
+            pFront[p->iNumber % p->nFront] = 1;
+            return p->iNumber;
+        }
+        p->iNumber++;
+    }
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the frontier.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fsim_ManVerifyFront( Fsim_Man_t * p )
+{
+    Fsim_Obj_t * pObj;
+    int * pFans0, * pFans1;  // representation of fanins
+    int * pFrontToId;        // mapping of nodes into frontier variables
+    int i, iVar0, iVar1;
+    pFans0 = ABC_ALLOC( int, p->nObjs );
+    pFans1 = ABC_ALLOC( int, p->nObjs );
+    pFans0[0] = pFans1[0] = 0;
+    pFans0[1] = pFans1[1] = 0;
+    pFrontToId = ABC_CALLOC( int, p->nFront );
+    if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) )
+        pFrontToId[1] = 1;
+    Fsim_ManForEachObj( p, pObj, i )
+    {
+        if ( pObj->iNode )
+            pFrontToId[pObj->iNode % p->nFront] = i;
+        iVar0 = Fsim_Lit2Var(pObj->iFan0);
+        iVar1 = Fsim_Lit2Var(pObj->iFan1);
+        pFans0[i] = Fsim_Var2Lit(pFrontToId[iVar0 % p->nFront], Fsim_LitIsCompl(pObj->iFan0));
+        pFans1[i] = Fsim_Var2Lit(pFrontToId[iVar1 % p->nFront], Fsim_LitIsCompl(pObj->iFan1));
+    }
+    for ( i = 0; i < p->nObjs; i++ )
+    {
+        assert( pFans0[i] == p->pFans0[i] );
+        assert( pFans1[i] == p->pFans1[i] );
+    }
+    ABC_FREE( pFrontToId );
+    ABC_FREE( pFans0 );
+    ABC_FREE( pFans1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determine the frontier.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fsim_ManFront( Fsim_Man_t * p, int fCompressAig )
+{
+    Fsim_Obj_t Obj, * pObj = &Obj;
+    char * pFront;    // places used for the frontier
+    int * pIdToFront; // mapping of nodes into frontier places
+    int i, iVar0, iVar1, nCrossCut = 0, nCrossCutMax = 0;
+    // start the frontier
+    pFront = ABC_CALLOC( char, p->nFront );
+    pIdToFront = ABC_ALLOC( int, p->nObjs );
+    pIdToFront[0] = -1;
+    pIdToFront[1] = -1;
+    // add constant node
+    p->iNumber = 1;
+    if ( p->pRefs[1] )
+    {
+        pIdToFront[1] = Fsim_ManFrontFindNext( p, pFront );
+        nCrossCut = 1;
+    }
+    // allocate room for data
+    if ( fCompressAig )
+    {
+        p->nDataAig = p->nObjs * 6;
+        p->pDataAig = ABC_ALLOC( unsigned char, p->nDataAig );
+        p->pDataCur = p->pDataAig;
+        p->iNodePrev = 0;
+    }
+    else
+    {
+        p->pDataAig2 = ABC_ALLOC( int, 3 * p->nObjs );
+        p->pDataCur2 = p->pDataAig2 + 6;
+    }
+    // iterate through the objects
+    for ( i = 2; i < p->nObjs; i++ )
+    {
+        if ( p->pFans0[i] == 0 ) // ci
+        {
+            // store node
+            pIdToFront[i] = Fsim_ManFrontFindNext( p, pFront );
+            pObj->iNode = pIdToFront[i];
+            pObj->iFan0 = 0;
+            pObj->iFan1 = 0;
+            Fsim_ManStoreObj( p, pObj );
+            // handle CIs without fanout
+            if ( p->pRefs[i] == 0 )
+            {
+                pFront[pIdToFront[i] % p->nFront] = 0;
+                pIdToFront[i] = -1;
+            }
+        }
+        else if ( p->pFans1[i] == 0 ) // co
+        {
+            assert( p->pRefs[i] == 0 );
+            // get the fanin
+            iVar0 = Fsim_Lit2Var(p->pFans0[i]);
+            assert( pIdToFront[iVar0] > 0 );
+            // store node
+            pObj->iNode = 0;
+            pObj->iFan0 = Fsim_Var2Lit(pIdToFront[iVar0], Fsim_LitIsCompl(p->pFans0[i]));
+            pObj->iFan1 = 0;
+            Fsim_ManStoreObj( p, pObj );
+            // deref the fanin
+            if ( --p->pRefs[iVar0] == 0 )
+            {
+                pFront[pIdToFront[iVar0] % p->nFront] = 0;
+                pIdToFront[iVar0] = -1;
+                nCrossCut--;
+            }
+        }
+        else
+        {
+            // get the fanins
+            iVar0 = Fsim_Lit2Var(p->pFans0[i]);
+            assert( pIdToFront[iVar0] > 0 );
+            iVar1 = Fsim_Lit2Var(p->pFans1[i]);
+            assert( pIdToFront[iVar1] > 0 );
+            // store node
+            pIdToFront[i] = Fsim_ManFrontFindNext( p, pFront );
+            pObj->iNode = pIdToFront[i];
+            pObj->iFan0 = Fsim_Var2Lit(pIdToFront[iVar0], Fsim_LitIsCompl(p->pFans0[i]));
+            pObj->iFan1 = Fsim_Var2Lit(pIdToFront[iVar1], Fsim_LitIsCompl(p->pFans1[i]));
+            Fsim_ManStoreObj( p, pObj );
+            // deref the fanins
+            if ( --p->pRefs[iVar0] == 0 )
+            {
+                pFront[pIdToFront[iVar0] % p->nFront] = 0;
+                pIdToFront[iVar0] = -1;
+                nCrossCut--;
+            }
+            if ( --p->pRefs[iVar1] == 0 )
+            {
+                pFront[pIdToFront[iVar1] % p->nFront] = 0;
+                pIdToFront[iVar1] = -1;
+                nCrossCut--;
+            }
+            // handle nodes without fanout (choice nodes)
+            if ( p->pRefs[i] == 0 )
+            {
+                pFront[pIdToFront[i] % p->nFront] = 0;
+                pIdToFront[i] = -1;
+            }
+        }
+        if ( p->pRefs[i] )
+            if ( nCrossCutMax < ++nCrossCut )
+                nCrossCutMax = nCrossCut;
+    }
+    assert( p->pDataAig2 == NULL || p->pDataCur2 - p->pDataAig2 == (3 * p->nObjs) );
+    assert( nCrossCut == 0 );
+    assert( nCrossCutMax == p->nCrossCutMax );
+    for ( i = 0; i < p->nFront; i++ )
+        assert( pFront[i] == 0 );
+    ABC_FREE( pFront );
+    ABC_FREE( pIdToFront );
+//    Fsim_ManVerifyFront( p );
+    ABC_FREE( p->pFans0 );
+    ABC_FREE( p->pFans1 );
+    ABC_FREE( p->pRefs );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fsim/fsimInt.h b/abc-build/src/opt/fsim/fsimInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fsim/fsimInt.h
@@ -0,0 +1,138 @@
+/**CFile****************************************************************
+
+  FileName    [fsimInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast sequential AIG simulator.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: fsimInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__fsim__fsimInt_h
+#define ABC__aig__fsim__fsimInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "aig/saig/saig.h"
+#include "fsim.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// simulation object
+typedef struct Fsim_Obj_t_ Fsim_Obj_t;
+struct Fsim_Obj_t_
+{
+    int             iNode;        // the node ID
+    int             iFan0;        // the first fanin
+    int             iFan1;        // the second fanin
+};
+
+// fast sequential simulation manager
+struct Fsim_Man_t_
+{
+    // parameters
+    Aig_Man_t *     pAig;         // the AIG to be used for simulation
+    int             nWords;       // the number of simulation words
+    // AIG representation
+    int             nPis;         // the number of primary inputs
+    int             nPos;         // the number of primary outputs
+    int             nCis;         // the number of combinational inputs
+    int             nCos;         // the number of combinational outputs
+    int             nNodes;       // the number of internal nodes
+    int             nObjs;        // nCis + nNodes + nCos + 2
+    int *           pFans0;       // fanin0 for all objects
+    int *           pFans1;       // fanin1 for all objects
+    int *           pRefs;        // reference counter for each node
+    int *           pRefsCopy;    // reference counter for each node
+    Vec_Int_t *     vCis2Ids;     // mapping of CIs into their PI ids
+    Vec_Int_t *     vLos;         // register outputs
+    Vec_Int_t *     vLis;         // register inputs
+    // cross-cut representation
+    int             nCrossCut;    // temporary cross-cut variable 
+    int             nCrossCutMax; // maximum cross-cut variable
+    int             nFront;       // the size of frontier
+    // derived AIG representation
+    int             nDataAig;     // the length of allocated data
+    unsigned char * pDataAig;     // AIG representation
+    unsigned char * pDataCur;     // AIG representation (current position)
+    int             iNodePrev;    // previous extracted value
+    int             iNumber;      // the number of the last object
+    Fsim_Obj_t      Obj;          // current object
+    // temporary AIG representation
+    int *           pDataAig2;    // temporary representation
+    int *           pDataCur2;    // AIG representation (current position)
+    // simulation information
+    unsigned *      pDataSim;     // simulation data
+    unsigned *      pDataSimCis;  // simulation data for CIs
+    unsigned *      pDataSimCos;  // simulation data for COs
+    // other information
+    int *           pData1;
+    int *           pData2;
+};
+
+static inline unsigned * Fsim_SimData( Fsim_Man_t * p, int i )    { return p->pDataSim + i * p->nWords;    }
+static inline unsigned * Fsim_SimDataCi( Fsim_Man_t * p, int i )  { return p->pDataSimCis + i * p->nWords; }
+static inline unsigned * Fsim_SimDataCo( Fsim_Man_t * p, int i )  { return p->pDataSimCos + i * p->nWords; }
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int  Fsim_Var2Lit( int Var, int fCompl )  { return Var + Var + fCompl; }
+static inline int  Fsim_Lit2Var( int Lit )              { return Lit >> 1;           }
+static inline int  Fsim_LitIsCompl( int Lit )           { return Lit & 1;            }
+static inline int  Fsim_LitNot( int Lit )               { return Lit ^ 1;            }
+static inline int  Fsim_LitNotCond( int Lit, int c )    { return Lit ^ (int)(c > 0); }
+static inline int  Fsim_LitRegular( int Lit )           { return Lit & ~01;          }
+
+#define Fsim_ManForEachObj( p, pObj, i )\
+    for ( i = 2, p->pDataCur = p->pDataAig, p->iNodePrev = 0, pObj = &p->Obj;\
+        i < p->nObjs && Fsim_ManRestoreObj( p, pObj ); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== fsimFront.c ========================================================*/
+extern void                Fsim_ManFront( Fsim_Man_t * p, int fCompressAig );
+/*=== fsimMan.c ==========================================================*/
+extern Fsim_Man_t *        Fsim_ManCreate( Aig_Man_t * pAig );
+extern void                Fsim_ManDelete( Fsim_Man_t * p );
+extern void                Fsim_ManTest( Aig_Man_t * pAig );
+ 
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/fsim/fsimMan.c b/abc-build/src/opt/fsim/fsimMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fsim/fsimMan.c
@@ -0,0 +1,212 @@
+/**CFile****************************************************************
+
+  FileName    [fsimMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast sequential AIG simulator.]
+
+  Synopsis    [Simulation manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: fsimMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fsimInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates fast simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fsim_ManCreate_rec( Fsim_Man_t * p, Aig_Obj_t * pObj )
+{
+    int iFan0, iFan1, iTemp;
+    assert( !Aig_IsComplement(pObj) );
+    if ( pObj->iData )
+        return pObj->iData;
+    assert( !Aig_ObjIsConst1(pObj) );
+    if ( Aig_ObjIsNode(pObj) )
+    {
+        iFan0 = Fsim_ManCreate_rec( p, Aig_ObjFanin0(pObj) );
+        iFan1 = Fsim_ManCreate_rec( p, Aig_ObjFanin1(pObj) );
+        assert( iFan0 != iFan1 );
+        if ( --p->pRefs[iFan0] == 0 )
+            p->nCrossCut--;
+        iFan0 = Fsim_Var2Lit( iFan0, Aig_ObjFaninC0(pObj) );
+        if ( --p->pRefs[iFan1] == 0 )
+            p->nCrossCut--;
+        iFan1 = Fsim_Var2Lit( iFan1, Aig_ObjFaninC1(pObj) );
+        if ( p->pAig->pEquivs )
+            Fsim_ManCreate_rec( p, Aig_ObjEquiv(p->pAig, pObj) );
+    }
+    else if ( Aig_ObjIsPo(pObj) )
+    {
+        assert( Aig_ObjRefs(pObj) == 0 );
+        iFan0 = Fsim_ManCreate_rec( p, Aig_ObjFanin0(pObj) );
+        if ( --p->pRefs[iFan0] == 0 )
+            p->nCrossCut--;
+        iFan0 = Fsim_Var2Lit( iFan0, Aig_ObjFaninC0(pObj) );
+        iFan1 = 0;
+    }
+    else
+    {
+        iFan0 = iFan1 = 0;
+        Vec_IntPush( p->vCis2Ids, Aig_ObjPioNum(pObj) );
+    }
+    if ( iFan0 < iFan1 )
+        iTemp = iFan0, iFan0 = iFan1, iFan1 = iTemp;
+    p->pFans0[p->nObjs] = iFan0;
+    p->pFans1[p->nObjs] = iFan1;
+    p->pRefs[p->nObjs]  = Aig_ObjRefs(pObj);
+    if ( p->pRefs[p->nObjs] )
+        if ( p->nCrossCutMax < ++p->nCrossCut ) 
+            p->nCrossCutMax = p->nCrossCut;
+    return pObj->iData = p->nObjs++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates fast simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fsim_Man_t * Fsim_ManCreate( Aig_Man_t * pAig )
+{
+    Fsim_Man_t * p;
+    Aig_Obj_t * pObj;
+    int i, nObjs;
+    Aig_ManCleanData( pAig );
+    p = (Fsim_Man_t *)ABC_ALLOC( Fsim_Man_t, 1 );
+    memset( p, 0, sizeof(Fsim_Man_t) );
+    p->pAig = pAig;
+    p->nPis = Saig_ManPiNum(pAig);
+    p->nPos = Saig_ManPoNum(pAig);
+    p->nCis = Aig_ManPiNum(pAig);
+    p->nCos = Aig_ManPoNum(pAig);
+    p->nNodes = Aig_ManNodeNum(pAig);
+    nObjs = p->nCis + p->nCos + p->nNodes + 2;
+    p->pFans0 = ABC_ALLOC( int, nObjs );
+    p->pFans1 = ABC_ALLOC( int, nObjs );
+    p->pRefs  = ABC_ALLOC( int, nObjs );
+    p->vCis2Ids = Vec_IntAlloc( Aig_ManPiNum(pAig) );
+    // add objects (0=unused; 1=const1)
+    p->pFans0[0] = p->pFans1[0] = 0;
+    p->pFans0[1] = p->pFans1[1] = 0;
+    p->pRefs[0] = 0;
+    p->nObjs = 2;
+    pObj = Aig_ManConst1( pAig );
+    pObj->iData = 1;
+    p->pRefs[1] = Aig_ObjRefs(pObj);
+    if ( p->pRefs[1] )
+        p->nCrossCut = 1;
+    Aig_ManForEachPi( pAig, pObj, i )
+        if ( Aig_ObjRefs(pObj) == 0 )
+            Fsim_ManCreate_rec( p, pObj );
+    Aig_ManForEachPo( pAig, pObj, i )
+        Fsim_ManCreate_rec( p, pObj );
+    assert( Vec_IntSize(p->vCis2Ids) == Aig_ManPiNum(pAig) );
+    assert( p->nObjs == nObjs );
+    // check references
+    assert( p->nCrossCut == 0 );
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+        assert( p->pRefs[pObj->iData] == 0 );
+        p->pRefs[pObj->iData] = Aig_ObjRefs(pObj);
+    }
+    // collect flop outputs
+    p->vLos = Vec_IntAlloc( Aig_ManRegNum(pAig) );
+    Saig_ManForEachLo( pAig, pObj, i )
+        Vec_IntPush( p->vLos, pObj->iData );
+    // collect flop inputs
+    p->vLis = Vec_IntAlloc( Aig_ManRegNum(pAig) );
+    Saig_ManForEachLi( pAig, pObj, i )
+        Vec_IntPush( p->vLis, pObj->iData );
+    // determine the frontier size
+    p->nFront = 1 + (int)(1.1 * p->nCrossCutMax); 
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes fast simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fsim_ManDelete( Fsim_Man_t * p )
+{
+    Vec_IntFree( p->vCis2Ids );
+    Vec_IntFree( p->vLos );
+    Vec_IntFree( p->vLis );
+    ABC_FREE( p->pDataAig2 );
+    ABC_FREE( p->pDataAig );
+    ABC_FREE( p->pFans0 );
+    ABC_FREE( p->pFans1 );
+    ABC_FREE( p->pRefs );
+    ABC_FREE( p->pDataSim );
+    ABC_FREE( p->pDataSimCis );
+    ABC_FREE( p->pDataSimCos );
+    ABC_FREE( p->pData1 );
+    ABC_FREE( p->pData2 );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Testing procedure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fsim_ManTest( Aig_Man_t * pAig )
+{
+    Fsim_Man_t * p;
+    p = Fsim_ManCreate( pAig );
+    Fsim_ManFront( p, 0 );
+    Fsim_ManDelete( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fsim/fsimSim.c b/abc-build/src/opt/fsim/fsimSim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fsim/fsimSim.c
@@ -0,0 +1,569 @@
+/**CFile****************************************************************
+
+  FileName    [fsimSim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast sequential AIG simulator.]
+
+  Synopsis    [Simulation procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: fsimSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fsimInt.h"
+#include "aig/ssw/ssw.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManSimInfoRandom( Fsim_Man_t * p, unsigned * pInfo )
+{
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = Aig_ManRandom( 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManSimInfoZero( Fsim_Man_t * p, unsigned * pInfo )
+{
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns index of the first pattern that failed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Fsim_ManSimInfoIsZero( Fsim_Man_t * p, unsigned * pInfo )
+{
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        if ( pInfo[w] )
+            return 32*(w-1) + Aig_WordFindFirstBit( pInfo[w] );
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManSimInfoOne( Fsim_Man_t * p, unsigned * pInfo )
+{
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = ~0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManSimInfoCopy( Fsim_Man_t * p, unsigned * pInfo, unsigned * pInfo0 )
+{
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManSimulateCi( Fsim_Man_t * p, int iNode, int iCi )
+{
+    unsigned * pInfo  = Fsim_SimData( p, iNode % p->nFront );
+    unsigned * pInfo0 = Fsim_SimDataCi( p, iCi );
+    int w;
+    for ( w = p->nWords-1; w >= 0; w-- )
+        pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManSimulateCo( Fsim_Man_t * p, int iCo, int iFan0 )
+{
+    unsigned * pInfo  = Fsim_SimDataCo( p, iCo );
+    unsigned * pInfo0 = Fsim_SimData( p, Fsim_Lit2Var(iFan0) % p->nFront );
+    int w;
+    if ( Fsim_LitIsCompl(iFan0) )
+        for ( w = p->nWords-1; w >= 0; w-- )
+            pInfo[w] = ~pInfo0[w];
+    else //if ( !Fsim_LitIsCompl(iFan0) )
+        for ( w = p->nWords-1; w >= 0; w-- )
+            pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManSimulateNode( Fsim_Man_t * p, int iNode, int iFan0, int iFan1 )
+{
+    unsigned * pInfo  = Fsim_SimData( p, iNode % p->nFront );
+    unsigned * pInfo0 = Fsim_SimData( p, Fsim_Lit2Var(iFan0) % p->nFront );
+    unsigned * pInfo1 = Fsim_SimData( p, Fsim_Lit2Var(iFan1) % p->nFront );
+    int w;
+    if ( Fsim_LitIsCompl(iFan0) && Fsim_LitIsCompl(iFan1) )
+        for ( w = p->nWords-1; w >= 0; w-- )
+            pInfo[w] = ~(pInfo0[w] | pInfo1[w]);
+    else if ( Fsim_LitIsCompl(iFan0) && !Fsim_LitIsCompl(iFan1) )
+        for ( w = p->nWords-1; w >= 0; w-- )
+            pInfo[w] = ~pInfo0[w] & pInfo1[w];
+    else if ( !Fsim_LitIsCompl(iFan0) && Fsim_LitIsCompl(iFan1) )
+        for ( w = p->nWords-1; w >= 0; w-- )
+            pInfo[w] = pInfo0[w] & ~pInfo1[w];
+    else //if ( !Fsim_LitIsCompl(iFan0) && !Fsim_LitIsCompl(iFan1) )
+        for ( w = p->nWords-1; w >= 0; w-- )
+            pInfo[w] = pInfo0[w] & pInfo1[w];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManSimInfoInit( Fsim_Man_t * p )
+{
+    int iPioNum, i;
+    Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i )
+    {
+        if ( iPioNum < p->nPis )
+            Fsim_ManSimInfoRandom( p, Fsim_SimDataCi(p, i) );
+        else
+            Fsim_ManSimInfoZero( p, Fsim_SimDataCi(p, i) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManSimInfoTransfer( Fsim_Man_t * p )
+{
+    int iPioNum, i;
+    Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i )
+    {
+        if ( iPioNum < p->nPis )
+            Fsim_ManSimInfoRandom( p, Fsim_SimDataCi(p, i) );
+        else
+            Fsim_ManSimInfoCopy( p, Fsim_SimDataCi(p, i), Fsim_SimDataCo(p, p->nPos+iPioNum-p->nPis) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Fsim_ManRestoreNum( Fsim_Man_t * p )
+{
+    int ch, i, x = 0;
+    for ( i = 0; (ch = *p->pDataCur++) & 0x80; i++ )
+        x |= (ch & 0x7f) << (7 * i);
+    assert( p->pDataCur - p->pDataAig < p->nDataAig );
+    return x | (ch << (7 * i));
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Fsim_ManRestoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj )
+{
+    int iValue = Fsim_ManRestoreNum( p );
+    if ( (iValue & 3) == 3 ) // and
+    {
+        pObj->iNode = (iValue >> 2) + p->iNodePrev;
+        pObj->iFan0 = (pObj->iNode << 1) - Fsim_ManRestoreNum( p );
+        pObj->iFan1 = pObj->iFan0 - Fsim_ManRestoreNum( p );
+        p->iNodePrev = pObj->iNode;
+    }
+    else if ( (iValue & 3) == 1 ) // ci
+    {
+        pObj->iNode = (iValue >> 2) + p->iNodePrev;
+        pObj->iFan0 = 0;
+        pObj->iFan1 = 0;
+        p->iNodePrev = pObj->iNode;
+    }
+    else // if ( (iValue & 1) == 0 ) // co
+    {
+        pObj->iNode = 0;
+        pObj->iFan0 = ((p->iNodePrev << 1) | 1) - (iValue >> 1);
+        pObj->iFan1 = 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManSimulateRound2( Fsim_Man_t * p )
+{
+    Fsim_Obj_t * pObj;
+    int i, iCis = 0, iCos = 0;
+    if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) )
+        Fsim_ManSimInfoOne( p, Fsim_SimData(p, 1) );
+    Fsim_ManForEachObj( p, pObj, i )
+    {
+        if ( pObj->iFan0 == 0 )
+            Fsim_ManSimulateCi( p, pObj->iNode, iCis++ );
+        else if ( pObj->iFan1 == 0 )
+            Fsim_ManSimulateCo( p, iCos++, pObj->iFan0 );
+        else
+            Fsim_ManSimulateNode( p, pObj->iNode, pObj->iFan0, pObj->iFan1 );
+    }
+    assert( iCis == p->nCis );
+    assert( iCos == p->nCos );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManSimulateRound( Fsim_Man_t * p )
+{
+    int * pCur, * pEnd;
+    int iCis = 0, iCos = 0;
+    if ( p->pDataAig2 == NULL )
+    {
+        Fsim_ManSimulateRound2( p );
+        return;
+    }
+    if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) )
+        Fsim_ManSimInfoOne( p, Fsim_SimData(p, 1) );
+    pCur = p->pDataAig2 + 6;
+    pEnd = p->pDataAig2 + 3 * p->nObjs;
+    while ( pCur < pEnd )
+    {
+        if ( pCur[1] == 0 )
+            Fsim_ManSimulateCi( p, pCur[0], iCis++ );
+        else if ( pCur[2] == 0 )
+            Fsim_ManSimulateCo( p, iCos++, pCur[1] );
+        else
+            Fsim_ManSimulateNode( p, pCur[0], pCur[1], pCur[2] );
+        pCur += 3;
+    }
+    assert( iCis == p->nCis );
+    assert( iCos == p->nCos );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fsim_ManSimulateRoundTest( Fsim_Man_t * p )
+{
+    Fsim_Obj_t * pObj;
+    int i;
+    clock_t clk = clock();
+    Fsim_ManForEachObj( p, pObj, i )
+    {
+    }
+//    ABC_PRT( "Unpacking time", p->pPars->nIters * (clock() - clk) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns index of the PO and pattern that failed it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Fsim_ManCheckPos( Fsim_Man_t * p, int * piPo, int * piPat )
+{
+    int i, iPat;
+    for ( i = 0; i < p->nPos; i++ )
+    {
+        iPat = Fsim_ManSimInfoIsZero( p, Fsim_SimDataCo(p, i) );
+        if ( iPat >= 0 )
+        {
+            *piPo = i;
+            *piPat = iPat;
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Fsim_ManGenerateCounter( Aig_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat, Vec_Int_t * vCis2Ids )
+{
+    Abc_Cex_t * p;
+    unsigned * pData;
+    int f, i, w, iPioId, Counter;
+    p = Abc_CexAlloc( Aig_ManRegNum(pAig), Saig_ManPiNum(pAig), iFrame+1 );
+    p->iFrame = iFrame;
+    p->iPo = iOut;
+    // fill in the binary data
+    Aig_ManRandom( 1 );
+    Counter = p->nRegs;
+    pData = ABC_ALLOC( unsigned, nWords );
+    for ( f = 0; f <= iFrame; f++, Counter += p->nPis )
+    for ( i = 0; i < Aig_ManPiNum(pAig); i++ )
+    {
+        iPioId = Vec_IntEntry( vCis2Ids, i );
+        if ( iPioId >= p->nPis )
+            continue;
+        for ( w = nWords-1; w >= 0; w-- )
+            pData[w] = Aig_ManRandom( 0 );
+        if ( Aig_InfoHasBit( pData, iPat ) )
+            Aig_InfoSetBit( p->pData, Counter + iPioId );
+    }
+    ABC_FREE( pData );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fsim_ManSimulate( Aig_Man_t * pAig, Fsim_ParSim_t * pPars )
+{
+    Fsim_Man_t * p;
+    Sec_MtrStatus_t Status;
+    int i, iOut, iPat;
+    clock_t clk, clkTotal = clock(), clk2, clk2Total = 0;
+    assert( Aig_ManRegNum(pAig) > 0 );
+    if ( pPars->fCheckMiter )
+    {
+        Status = Sec_MiterStatus( pAig );
+        if ( Status.nSat > 0 )
+        {
+            printf( "Miter is trivially satisfiable (output %d).\n", Status.iOut );
+            return 1;
+        }
+        if ( Status.nUndec == 0 )
+        {
+            printf( "Miter is trivially unsatisfiable.\n" );
+            return 0;
+        }
+    }
+    // create manager
+    clk = clock();
+    p = Fsim_ManCreate( pAig );
+    p->nWords = pPars->nWords;
+    if ( pPars->fVerbose )
+    {
+        printf( "Obj = %8d (%8d). Cut = %6d. Front = %6d.  FrtMem = %7.2f MB. ", 
+            p->nObjs, p->nCis + p->nNodes, p->nCrossCutMax, p->nFront, 
+            4.0*p->nWords*(p->nFront)/(1<<20) );
+        ABC_PRT( "Time", clock() - clk );
+    }
+    // create simulation frontier
+    clk = clock();
+    Fsim_ManFront( p, pPars->fCompressAig );
+    if ( pPars->fVerbose )
+    {
+        printf( "Max ID = %8d. Log max ID = %2d.  AigMem = %7.2f MB (%5.2f byte/obj).  ", 
+            p->iNumber, Aig_Base2Log(p->iNumber), 
+            1.0*(p->pDataCur-p->pDataAig)/(1<<20), 
+            1.0*(p->pDataCur-p->pDataAig)/p->nObjs ); 
+        ABC_PRT( "Time", clock() - clk );
+    }
+    // perform simulation
+    Aig_ManRandom( 1 );
+    assert( p->pDataSim == NULL );
+    p->pDataSim = ABC_ALLOC( unsigned, p->nWords * p->nFront );
+    p->pDataSimCis = ABC_ALLOC( unsigned, p->nWords * p->nCis );
+    p->pDataSimCos = ABC_ALLOC( unsigned, p->nWords * p->nCos );
+    Fsim_ManSimInfoInit( p );
+    for ( i = 0; i < pPars->nIters; i++ )
+    { 
+        Fsim_ManSimulateRound( p );
+        if ( pPars->fVerbose )
+        {
+            printf( "Frame %4d out of %4d and timeout %3d sec. ", i+1, pPars->nIters, pPars->TimeLimit );
+            printf( "Time = %7.2f sec\r", (1.0*clock()-clkTotal)/CLOCKS_PER_SEC );
+        }
+        if ( pPars->fCheckMiter && Fsim_ManCheckPos( p, &iOut, &iPat ) )
+        {
+            assert( pAig->pSeqModel == NULL );
+            pAig->pSeqModel = Fsim_ManGenerateCounter( pAig, i, iOut, p->nWords, iPat, p->vCis2Ids );
+            if ( pPars->fVerbose )
+            printf( "Miter is satisfiable after simulation (output %d).\n", iOut );
+            break;
+        }
+        if ( (clock() - clkTotal)/CLOCKS_PER_SEC >= pPars->TimeLimit )
+            break;
+        clk2 = clock();
+        if ( i < pPars->nIters - 1 )
+            Fsim_ManSimInfoTransfer( p );
+        clk2Total += clock() - clk2;
+    }
+    if ( pAig->pSeqModel == NULL )
+        printf( "No bug detected after %d frames with time limit %d seconds.\n", i+1, pPars->TimeLimit );
+    if ( pPars->fVerbose )
+    {
+        printf( "Maxcut = %8d.  AigMem = %7.2f MB.  SimMem = %7.2f MB.  ", 
+            p->nCrossCutMax, 
+            p->pDataAig2? 12.0*p->nObjs/(1<<20) : 1.0*(p->pDataCur-p->pDataAig)/(1<<20), 
+            4.0*p->nWords*(p->nFront+p->nCis+p->nCos)/(1<<20) );
+        ABC_PRT( "Sim time", clock() - clkTotal );
+
+//        ABC_PRT( "Additional time", clk2Total );
+//        Fsim_ManSimulateRoundTest( p );
+//        Fsim_ManSimulateRoundTest2( p );
+    }
+    Fsim_ManDelete( p );
+    return pAig->pSeqModel != NULL;
+
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fsim/fsimSwitch.c b/abc-build/src/opt/fsim/fsimSwitch.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fsim/fsimSwitch.c
@@ -0,0 +1,40 @@
+/**CFile****************************************************************
+
+  FileName    [fsimSwitch.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast sequential AIG simulator.]
+
+  Synopsis    [Computing switching activity.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: fsimSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fsimInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fsim/fsimTsim.c b/abc-build/src/opt/fsim/fsimTsim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fsim/fsimTsim.c
@@ -0,0 +1,416 @@
+/**CFile****************************************************************
+
+  FileName    [fsimTsim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast sequential AIG simulator.]
+
+  Synopsis    [Varius utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: fsimTsim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fsimInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define FSIM_ZER 1
+#define FSIM_ONE 2
+#define FSIM_UND 3
+
+static inline int Aig_XsimNotCond( int Value, int fCompl )   
+{ 
+    if ( Value == FSIM_UND )
+        return FSIM_UND;
+    if ( Value == FSIM_ZER + fCompl )
+        return FSIM_ZER;
+    return FSIM_ONE;
+}
+static inline int Aig_XsimAndCond( int Value0, int fCompl0, int Value1, int fCompl1 )   
+{ 
+    if ( Value0 == FSIM_UND || Value1 == FSIM_UND )
+        return FSIM_UND;
+    if ( Value0 == FSIM_ZER + fCompl0 || Value1 == FSIM_ZER + fCompl1 )
+        return FSIM_ZER;
+    return FSIM_ONE;
+}
+
+static inline int Fsim_ManTerSimInfoGet( unsigned * pInfo, int i )
+{
+    return 3 & (pInfo[i >> 4] >> ((i & 15) << 1));
+}
+static inline void Fsim_ManTerSimInfoSet( unsigned * pInfo, int i, int Value )
+{
+    assert( Value >= FSIM_ZER && Value <= FSIM_UND );
+    Value ^= Fsim_ManTerSimInfoGet( pInfo, i );
+    pInfo[i >> 4] ^= (Value << ((i & 15) << 1));
+}
+
+static inline unsigned * Fsim_ManTerStateNext( unsigned * pState, int nWords )                      { return *((unsigned **)(pState + nWords));  }
+static inline void       Fsim_ManTerStateSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManTerSimulateCi( Fsim_Man_t * p, int iNode, int iCi )
+{
+    Fsim_ManTerSimInfoSet( p->pDataSim, iNode, Fsim_ManTerSimInfoGet(p->pDataSimCis, iCi) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManTerSimulateCo( Fsim_Man_t * p, int iCo, int iFan0 )
+{
+    int Value = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan0) );
+    Fsim_ManTerSimInfoSet( p->pDataSimCos, iCo, Aig_XsimNotCond( Value, Fsim_LitIsCompl(iFan0) ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManTerSimulateNode( Fsim_Man_t * p, int iNode, int iFan0, int iFan1 )
+{
+    int Value0 = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan0) );
+    int Value1 = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan1) );
+    Fsim_ManTerSimInfoSet( p->pDataSim, iNode, Aig_XsimAndCond( Value0, Fsim_LitIsCompl(iFan0), Value1, Fsim_LitIsCompl(iFan1) ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManTerSimInfoInit( Fsim_Man_t * p )
+{
+    int iPioNum, i;
+    Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i )
+    {
+        if ( iPioNum < p->nPis )
+            Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_UND );
+        else
+            Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_ZER );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManTerSimInfoTransfer( Fsim_Man_t * p )
+{
+    int iPioNum, i;
+    Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i )
+    {
+        if ( iPioNum < p->nPis )
+            Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_UND );
+        else
+            Fsim_ManTerSimInfoSet( p->pDataSimCis, i, Fsim_ManTerSimInfoGet( p->pDataSimCos, p->nPos+iPioNum-p->nPis ) );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash value of the node using its simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fsim_ManTerStateHash( unsigned * pState, int nWords, int nTableSize )
+{
+    static int s_FPrimes[128] = { 
+        1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 
+        1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 
+        2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 
+        2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 
+        3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 
+        3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 
+        4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 
+        4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 
+        5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 
+        6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 
+        6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 
+        7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 
+        8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+    };
+    unsigned uHash;
+    int i;
+    uHash = 0;
+    for ( i = 0; i < nWords; i++ )
+        uHash ^= pState[i] * s_FPrimes[i & 0x7F];
+    return uHash % nTableSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts value into the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fsim_ManTerStateLookup( unsigned * pState, int nWords, unsigned ** pBins, int nBins )
+{
+    unsigned * pEntry;
+    int Hash;
+    Hash = Fsim_ManTerStateHash( pState, nWords, nBins );
+    for ( pEntry = pBins[Hash]; pEntry; pEntry = Fsim_ManTerStateNext(pEntry, nWords) )
+        if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts value into the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fsim_ManTerStateInsert( unsigned * pState, int nWords, unsigned ** pBins, int nBins )
+{
+    int Hash = Fsim_ManTerStateHash( pState, nWords, nBins );
+    assert( !Fsim_ManTerStateLookup( pState, nWords, pBins, nBins ) );
+    Fsim_ManTerStateSetNext( pState, nWords, pBins[Hash] );
+    pBins[Hash] = pState;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts value into the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Fsim_ManTerStateCreate( unsigned * pInfo, int nPis, int nCis, int nWords )
+{
+    unsigned * pRes;
+    int i;
+    pRes = (unsigned *)ABC_CALLOC( char, sizeof(unsigned) * nWords + sizeof(unsigned *) );
+    for ( i = nPis; i < nCis; i++ )
+        Fsim_ManTerSimInfoSet( pRes, i-nPis, Fsim_ManTerSimInfoGet(pInfo, i) );
+    return pRes;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts value into the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fsim_ManTerStatePrint( unsigned * pState, int nRegs )
+{
+    int i, Value, nZeros = 0, nOnes = 0, nDcs = 0;
+    for ( i = 0; i < nRegs; i++ )
+    {
+        Value = (Aig_InfoHasBit( pState, 2 * i + 1 ) << 1) | Aig_InfoHasBit( pState, 2 * i );
+        if ( Value == 1 )
+            printf( "0" ), nZeros++;
+        else if ( Value == 2 )
+            printf( "1" ), nOnes++;
+        else if ( Value == 3 )
+            printf( "x" ), nDcs++;
+        else
+            assert( 0 );
+    }
+    printf( " (0=%5d, 1=%5d, x=%5d)\n", nZeros, nOnes, nDcs );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fsim_ManTerSimulateRound( Fsim_Man_t * p )
+{
+    int * pCur, * pEnd;
+    int iCis = 0, iCos = 0;
+    if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) )
+        Fsim_ManTerSimInfoSet( p->pDataSimCis, 1, FSIM_ONE );
+    pCur = p->pDataAig2 + 6;
+    pEnd = p->pDataAig2 + 3 * p->nObjs;
+    while ( pCur < pEnd )
+    {
+        if ( pCur[1] == 0 )
+            Fsim_ManTerSimulateCi( p, pCur[0], iCis++ );
+        else if ( pCur[2] == 0 )
+            Fsim_ManTerSimulateCo( p, iCos++, pCur[1] );
+        else
+            Fsim_ManTerSimulateNode( p, pCur[0], pCur[1], pCur[2] );
+        pCur += 3;
+    }
+    assert( iCis == p->nCis );
+    assert( iCos == p->nCos );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Fsim_ManTerSimulate( Aig_Man_t * pAig, int fVerbose )
+{
+    Fsim_Man_t * p;
+    Vec_Ptr_t * vStates;
+    unsigned ** pBins, * pState;
+    int i, nWords, nBins;
+    clock_t clk, clkTotal = clock();
+    assert( Aig_ManRegNum(pAig) > 0 );
+    // create manager
+    clk = clock();
+    p = Fsim_ManCreate( pAig );
+    if ( fVerbose )
+    {
+        printf( "Obj = %8d (%8d). Cut = %6d. Front = %6d.  FrtMem = %7.2f MB. ", 
+            p->nObjs, p->nCis + p->nNodes, p->nCrossCutMax, p->nFront, 
+            4.0*Aig_BitWordNum(2 * p->nFront)/(1<<20) );
+        ABC_PRT( "Time", clock() - clk );
+    }
+    // create simulation frontier
+    clk = clock();
+    Fsim_ManFront( p, 0 );
+    if ( fVerbose )
+    {
+        printf( "Max ID = %8d. Log max ID = %2d.  AigMem = %7.2f MB (%5.2f byte/obj).  ", 
+            p->iNumber, Aig_Base2Log(p->iNumber), 
+            1.0*(p->pDataCur-p->pDataAig)/(1<<20), 
+            1.0*(p->pDataCur-p->pDataAig)/p->nObjs ); 
+        ABC_PRT( "Time", clock() - clk );
+    }
+    // allocate storage for terminary states
+    nWords  = Abc_BitWordNum( 2*Aig_ManRegNum(pAig) );
+    vStates = Vec_PtrAlloc( 1000 );
+    nBins   = Abc_PrimeCudd( 500 );
+    pBins   = ABC_ALLOC( unsigned *, nBins );
+    memset( pBins, 0, sizeof(unsigned *) * nBins );
+    // perform simulation
+    assert( p->pDataSim == NULL );
+    p->pDataSim = ABC_ALLOC( unsigned, Aig_BitWordNum(2 * p->nFront) * sizeof(unsigned) );
+    p->pDataSimCis = ABC_ALLOC( unsigned, Aig_BitWordNum(2 * p->nCis) * sizeof(unsigned) );
+    p->pDataSimCos = ABC_ALLOC( unsigned, Aig_BitWordNum(2 * p->nCos) * sizeof(unsigned) );
+    Fsim_ManTerSimInfoInit( p );
+    // hash the first state
+    pState = Fsim_ManTerStateCreate( p->pDataSimCis, p->nPis, p->nCis, nWords );
+    Vec_PtrPush( vStates, pState );
+    Fsim_ManTerStateInsert( pState, nWords, pBins, nBins );
+    // perform simuluation till convergence
+    for ( i = 0; ; i++ )
+    {
+        Fsim_ManTerSimulateRound( p );
+        Fsim_ManTerSimInfoTransfer( p );
+        // hash the first state
+        pState = Fsim_ManTerStateCreate( p->pDataSimCis, p->nPis, p->nCis, nWords );
+        Vec_PtrPush( vStates, pState );
+        if ( Fsim_ManTerStateLookup(pState, nWords, pBins, nBins) )
+            break;
+        Fsim_ManTerStateInsert( pState, nWords, pBins, nBins );
+    }
+    if ( fVerbose )
+    {
+        printf( "Maxcut = %8d.  AigMem = %7.2f MB.  SimMem = %7.2f MB.  ", 
+            p->nCrossCutMax, 
+            p->pDataAig2? 12.0*p->nObjs/(1<<20) : 1.0*(p->pDataCur-p->pDataAig)/(1<<20), 
+            4.0*(Aig_BitWordNum(2 * p->nFront)+Aig_BitWordNum(2 * p->nCis)+Aig_BitWordNum(2 * p->nCos))/(1<<20) );
+        ABC_PRT( "Sim time", clock() - clkTotal );
+    }
+    ABC_FREE( pBins );
+    Fsim_ManDelete( p );
+    return vStates;
+
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fsim/module.make b/abc-build/src/opt/fsim/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fsim/module.make
@@ -0,0 +1,6 @@
+SRC +=	src/opt/fsim/fsimCore.c \
+	src/opt/fsim/fsimFront.c \
+	src/opt/fsim/fsimMan.c \
+	src/opt/fsim/fsimSim.c \
+	src/opt/fsim/fsimSwitch.c \
+	src/opt/fsim/fsimTsim.c
diff --git a/abc-build/src/opt/fxu/fxu.c b/abc-build/src/opt/fxu/fxu.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fxu/fxu.c
@@ -0,0 +1,260 @@
+/**CFile****************************************************************
+
+  FileName    [fxu.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [The entrance into the fast extract module.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: fxu.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h" 
+#include "fxu.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+/*===== fxuCreate.c ====================================================*/
+extern Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData );
+extern void         Fxu_CreateCovers( Fxu_Matrix * p, Fxu_Data_t * pData );
+
+static int s_MemoryTotal;
+static int s_MemoryPeak;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fast_extract on a set of covers.]
+
+  Description [All the covers are given in the array p->vSops. 
+  The resulting covers are returned in the array p->vSopsNew.
+  The entries in these arrays correspond to objects in the network.
+  The entries corresponding to the PI and objects with trivial covers are NULL.
+  The number of extracted covers (not exceeding p->nNodesExt) is returned. 
+  Two other things are important for the correct operation of this procedure:
+  (1) The input covers do not have duplicated fanins and are SCC-free. 
+  (2) The fanins array contains the numbers of the fanin objects.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fxu_FastExtract( Fxu_Data_t * pData )
+{
+    int fScrollLines = 0;
+	Fxu_Matrix * p;
+    Fxu_Single * pSingle;
+    Fxu_Double * pDouble;
+	int Weight1, Weight2, Weight3;
+    int Counter = 0;
+
+    s_MemoryTotal = 0;
+    s_MemoryPeak  = 0;
+
+	// create the matrix
+	p = Fxu_CreateMatrix( pData );
+    if ( p == NULL )
+        return -1;
+//    if ( pData->fVerbose )
+//        printf( "Memory usage after construction: Total = %d. Peak = %d.\n", s_MemoryTotal, s_MemoryPeak );
+//Fxu_MatrixPrint( NULL, p );
+
+    if ( pData->fOnlyS )
+    {
+        pData->nNodesNew = 0;
+	    do
+        {
+		    Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle );
+            if ( pData->fVerbose )
+                printf( "Div %5d : Best single = %5d.%s", Counter++, Weight1, fScrollLines?"\n":"\r" );
+            if ( Weight1 > pData->WeightMin || (Weight1 == 0 && pData->fUse0) )
+			    Fxu_UpdateSingle( p );
+            else
+                break;
+        }
+        while ( ++pData->nNodesNew < pData->nNodesExt );
+    }
+    else if ( pData->fOnlyD )
+    {
+        pData->nNodesNew = 0;
+	    do
+        {
+		    Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble );
+            if ( pData->fVerbose )
+                printf( "Div %5d : Best double = %5d.%s", Counter++, Weight2, fScrollLines?"\n":"\r" );
+            if ( Weight2 > pData->WeightMin || (Weight2 == 0 && pData->fUse0) )
+			    Fxu_UpdateDouble( p );
+            else
+                break;
+        }
+        while ( ++pData->nNodesNew < pData->nNodesExt );
+    }
+    else if ( !pData->fUseCompl )
+    {
+        pData->nNodesNew = 0;
+	    do
+        {
+		    Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle );
+		    Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble );
+
+            if ( pData->fVerbose )
+                printf( "Div %5d : Best double = %5d. Best single = %5d.%s", Counter++, Weight2, Weight1, fScrollLines?"\n":"\r" );
+//Fxu_Select( p, &pSingle, &pDouble );
+
+            if ( Weight1 >= Weight2 )
+            {
+                if ( Weight1 > pData->WeightMin || (Weight1 == 0 && pData->fUse0) )
+			        Fxu_UpdateSingle( p );
+                else
+                    break;
+            }
+            else
+            {
+                if ( Weight2 > pData->WeightMin || (Weight2 == 0 && pData->fUse0) )
+			        Fxu_UpdateDouble( p );
+                else
+                    break;
+            }
+        }
+        while ( ++pData->nNodesNew < pData->nNodesExt );
+    }
+    else
+    { // use the complement
+        pData->nNodesNew = 0;
+	    do
+        {
+		    Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle );
+		    Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble );
+
+            // select the best single and double
+            Weight3 = Fxu_Select( p, &pSingle, &pDouble );
+            if ( pData->fVerbose )
+                printf( "Div %5d : Best double = %5d. Best single = %5d. Best complement = %5d.%s", 
+                    Counter++, Weight2, Weight1, Weight3, fScrollLines?"\n":"\r" );
+
+            if ( Weight3 > pData->WeightMin || (Weight3 == 0 && pData->fUse0) )
+                Fxu_Update( p, pSingle, pDouble );
+            else
+                break;
+        }
+        while ( ++pData->nNodesNew < pData->nNodesExt );
+    }
+
+    if ( pData->fVerbose )
+        printf( "Total single = %3d. Total double = %3d. Total compl = %3d.                    \n", 
+        p->nDivs1, p->nDivs2, p->nDivs3 );
+
+    // create the new covers
+    if ( pData->nNodesNew )
+        Fxu_CreateCovers( p, pData );
+	Fxu_MatrixDelete( p );
+//    printf( "Memory usage after deallocation:   Total = %d. Peak = %d.\n", s_MemoryTotal, s_MemoryPeak );
+    if ( pData->nNodesNew == pData->nNodesExt )
+        printf( "Warning: The limit on the number of extracted divisors has been reached.\n" );
+    return pData->nNodesNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Unmarks the cubes in the ring.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_MatrixRingCubesUnmark( Fxu_Matrix * p )
+{
+	Fxu_Cube * pCube, * pCube2;
+    // unmark the cubes
+    Fxu_MatrixForEachCubeInRingSafe( p, pCube, pCube2 )
+        pCube->pOrder = NULL;
+    Fxu_MatrixRingCubesReset( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Unmarks the vars in the ring.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_MatrixRingVarsUnmark( Fxu_Matrix * p )
+{
+	Fxu_Var * pVar, * pVar2;
+    // unmark the vars
+    Fxu_MatrixForEachVarInRingSafe( p, pVar, pVar2 )
+        pVar->pOrder = NULL;
+    Fxu_MatrixRingVarsReset( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Fxu_MemFetch( Fxu_Matrix * p, int nBytes )
+{
+    s_MemoryTotal += nBytes;
+    if ( s_MemoryPeak < s_MemoryTotal )
+        s_MemoryPeak = s_MemoryTotal;
+//    return ABC_ALLOC( char, nBytes );
+    return Extra_MmFixedEntryFetch( p->pMemMan );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_MemRecycle( Fxu_Matrix * p, char * pItem, int nBytes )
+{
+    s_MemoryTotal -= nBytes;
+//    ABC_FREE( pItem );
+    Extra_MmFixedEntryRecycle( p->pMemMan, pItem );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fxu/fxu.h b/abc-build/src/opt/fxu/fxu.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fxu/fxu.h
@@ -0,0 +1,96 @@
+/**CFile****************************************************************
+
+  FileName    [fxu.h]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [External declarations of fast extract for unate covers.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: fxu.h,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__opt__fxu__fxu_h
+#define ABC__opt__fxu__fxu_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "misc/vec/vec.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct FxuDataStruct   Fxu_Data_t;
+
+// structure for the FX input/output data 
+struct FxuDataStruct
+{
+    // user specified parameters
+    int               fOnlyS;           // set to 1 to have only single-cube divs
+    int               fOnlyD;           // set to 1 to have only double-cube divs
+    int               fUse0;            // set to 1 to have 0-weight also extracted
+    int               fUseCompl;        // set to 1 to have complement taken into account
+    int               fVerbose;         // set to 1 to have verbose output
+    int               fVeryVerbose;     // set to 1 to have more verbose output
+    int               nNodesExt;        // the number of divisors to extract
+    int               nSingleMax;       // the max number of single-cube divisors to consider
+    int               nPairsMax;        // the max number of double-cube divisors to consider
+    int               WeightMin;        // the min weight of a divisor to extract
+    int               LitCountMax;      // the max literal count of a divisor to consider
+    // the input information
+    Vec_Ptr_t *       vSops;            // the SOPs for each node in the network
+    Vec_Ptr_t *       vFanins;          // the fanins of each node in the network
+    // output information
+    Vec_Ptr_t *       vSopsNew;         // the SOPs for each node in the network after extraction
+    Vec_Ptr_t *       vFaninsNew;       // the fanins of each node in the network after extraction
+    // the SOP manager
+    Mem_Flex_t *      pManSop;
+    // statistics   
+    int               nNodesOld;        // the old number of nodes
+    int               nNodesNew;        // the number of divisors actually extracted
+};
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*===== fxu.c ==========================================================*/
+extern void   Abc_NtkSetDefaultFxParams( Fxu_Data_t * p );
+extern int    Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p );
+extern void   Abc_NtkFxuFreeInfo( Fxu_Data_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/fxu/fxuCreate.c b/abc-build/src/opt/fxu/fxuCreate.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fxu/fxuCreate.c
@@ -0,0 +1,447 @@
+/**CFile****************************************************************
+
+  FileName    [fxuCreate.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Create matrix from covers and covers from matrix.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: fxuCreate.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+#include "fxu.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void        Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Int_t * vFanins, int * pOrder );
+static int         Fxu_CreateMatrixLitCompare( int * ptrX, int * ptrY );
+static void        Fxu_CreateCoversNode( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode, Fxu_Cube * pCubeFirst, Fxu_Cube * pCubeNext );
+static Fxu_Cube *  Fxu_CreateCoversFirstCube( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode );
+static int * s_pLits;
+
+extern int         Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTotal, int nPairsMax );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the sparse matrix from the array of SOPs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
+{
+    Fxu_Matrix * p;
+    Fxu_Var * pVar;
+    Fxu_Cube * pCubeFirst, * pCubeNew;
+    Fxu_Cube * pCube1, * pCube2;
+    Vec_Int_t * vFanins;
+    char * pSopCover;
+    char * pSopCube;
+    int * pOrder, nBitsMax;
+    int i, v, c;
+    int nCubesTotal;
+    int nPairsTotal;
+    int nPairsStore;
+    int nCubes;
+    int iCube, iPair;
+    int nFanins;
+
+    // collect all sorts of statistics
+    nCubesTotal =  0;
+    nPairsTotal =  0;
+    nPairsStore =  0;
+    nBitsMax    = -1; 
+    for ( i = 0; i < pData->nNodesOld; i++ )
+        if ( (pSopCover = (char *)pData->vSops->pArray[i]) )
+        {
+            nCubes       = Abc_SopGetCubeNum( pSopCover );
+            nFanins      = Abc_SopGetVarNum( pSopCover );
+            assert( nFanins > 1 && nCubes > 0 );
+
+            nCubesTotal += nCubes;
+            nPairsTotal += nCubes * (nCubes - 1) / 2;
+            nPairsStore += nCubes * nCubes;
+            if ( nBitsMax < nFanins )
+                nBitsMax = nFanins;
+        }
+    if ( nBitsMax <= 0 )
+    {
+        printf( "The current network does not have SOPs to perform extraction.\n" );
+        return NULL;
+    }
+
+    if ( nPairsStore > 50000000 )
+    {
+        printf( "The problem is too large to be solved by \"fxu\" (%d cubes and %d cube pairs)\n", nCubesTotal, nPairsStore );
+        return NULL;
+    }
+
+    // start the matrix
+	p = Fxu_MatrixAllocate();
+    // create the column labels 
+    p->ppVars = ABC_ALLOC( Fxu_Var *, 2 * (pData->nNodesOld + pData->nNodesExt) );
+    for ( i = 0; i < 2 * pData->nNodesOld; i++ )
+        p->ppVars[i] = Fxu_MatrixAddVar( p );
+
+    // allocate storage for all cube pairs at once
+    p->pppPairs = ABC_ALLOC( Fxu_Pair **, nCubesTotal + 100 );
+    p->ppPairs  = ABC_ALLOC( Fxu_Pair *,  nPairsStore + 100 );
+    memset( p->ppPairs, 0, sizeof(Fxu_Pair *) * nPairsStore );
+    iCube = 0;
+    iPair = 0;
+    for ( i = 0; i < pData->nNodesOld; i++ )
+        if ( (pSopCover = (char *)pData->vSops->pArray[i]) )
+        {
+            // get the number of cubes
+            nCubes = Abc_SopGetCubeNum( pSopCover );
+            // get the new var in the matrix
+            pVar = p->ppVars[2*i+1];
+            // assign the pair storage
+            pVar->nCubes     = nCubes;
+            if ( nCubes > 0 )
+            {
+                pVar->ppPairs    = p->pppPairs + iCube;
+                pVar->ppPairs[0] = p->ppPairs  + iPair;
+                for ( v = 1; v < nCubes; v++ )
+                    pVar->ppPairs[v] = pVar->ppPairs[v-1] + nCubes;
+            }
+            // update
+            iCube += nCubes;
+            iPair += nCubes * nCubes;
+        }
+    assert( iCube == nCubesTotal );
+    assert( iPair == nPairsStore );
+
+
+    // allocate room for the reordered literals
+    pOrder = ABC_ALLOC( int, nBitsMax );
+    // create the rows
+    for ( i = 0; i < pData->nNodesOld; i++ )
+    if ( (pSopCover = (char *)pData->vSops->pArray[i]) )
+    {
+        // get the new var in the matrix
+        pVar = p->ppVars[2*i+1];
+        // here we sort the literals of the cover
+        // in the increasing order of the numbers of the corresponding nodes
+        // because literals should be added to the matrix in this order
+        vFanins = (Vec_Int_t *)pData->vFanins->pArray[i];
+        s_pLits = vFanins->pArray;
+        // start the variable order
+        nFanins = Abc_SopGetVarNum( pSopCover );
+        for ( v = 0; v < nFanins; v++ )
+            pOrder[v] = v;
+        // reorder the fanins
+        qsort( (void *)pOrder, nFanins, sizeof(int),(int (*)(const void *, const void *))Fxu_CreateMatrixLitCompare);
+        assert( s_pLits[ pOrder[0] ] < s_pLits[ pOrder[nFanins-1] ] );
+        // create the corresponding cubes in the matrix
+        pCubeFirst = NULL;
+        c = 0;
+        Abc_SopForEachCube( pSopCover, nFanins, pSopCube )
+        {
+            // create the cube
+	        pCubeNew = Fxu_MatrixAddCube( p, pVar, c++ );
+            Fxu_CreateMatrixAddCube( p, pCubeNew, pSopCube, vFanins, pOrder );
+            if ( pCubeFirst == NULL )
+                pCubeFirst = pCubeNew;
+            pCubeNew->pFirst = pCubeFirst;
+        }
+        // set the first cube of this var
+        pVar->pFirst = pCubeFirst;
+        // create the divisors without preprocessing
+        if ( nPairsTotal <= pData->nPairsMax )
+        {
+		    for ( pCube1 = pCubeFirst; pCube1; pCube1 = pCube1->pNext )
+			    for ( pCube2 = pCube1? pCube1->pNext: NULL; pCube2; pCube2 = pCube2->pNext )
+				    Fxu_MatrixAddDivisor( p, pCube1, pCube2 );
+        }
+    }
+    ABC_FREE( pOrder );
+
+    // consider the case when cube pairs should be preprocessed
+    // before adding them to the set of divisors
+//    if ( pData->fVerbose )
+//        printf( "The total number of cube pairs is %d.\n", nPairsTotal );
+    if ( nPairsTotal > 10000000 )
+    {
+        printf( "The total number of cube pairs of the network is more than 10,000,000.\n" );
+        printf( "Command \"fx\" takes a long time to run in such cases. It is suggested\n" );
+        printf( "that the user changes the network by reducing the size of logic node and\n" );
+        printf( "consequently the number of cube pairs to be processed by this command.\n" );
+        printf( "It can be achieved as follows: \"st; if -K <num>\" or \"st; renode -s -K <num>\"\n" );
+        printf( "as a proprocessing step, while selecting <num> as approapriate.\n" );
+        return NULL;
+    }
+    if ( nPairsTotal > pData->nPairsMax )
+        if ( !Fxu_PreprocessCubePairs( p, pData->vSops, nPairsTotal, pData->nPairsMax ) )
+            return NULL;
+//    if ( pData->fVerbose )
+//        printf( "Only %d best cube pairs will be used by the fast extract command.\n", pData->nPairsMax );
+
+    if ( p->lVars.nItems > 1000000 )
+    {
+        printf( "The total number of variables is more than 1,000,000.\n" );
+        printf( "Command \"fx\" takes a long time to run in such cases. It is suggested\n" );
+        printf( "that the user changes the network by reducing the size of logic node and\n" );
+        printf( "consequently the number of cube pairs to be processed by this command.\n" );
+        printf( "It can be achieved as follows: \"st; if -K <num>\" or \"st; renode -s -K <num>\"\n" );
+        printf( "as a proprocessing step, while selecting <num> as approapriate.\n" );
+        return NULL;
+    }
+
+
+    // add the var pairs to the heap
+    Fxu_MatrixComputeSingles( p, pData->fUse0, pData->nSingleMax );
+
+    // print stats
+    if ( pData->fVerbose )
+    {
+        double Density;
+        Density = ((double)p->nEntries) / p->lVars.nItems / p->lCubes.nItems;
+	    fprintf( stdout, "Matrix: [vars x cubes] = [%d x %d]  ",
+            p->lVars.nItems, p->lCubes.nItems );
+	    fprintf( stdout, "Lits = %d  Density = %.5f%%\n", 
+            p->nEntries, Density );
+	    fprintf( stdout, "1-cube divs = %6d. (Total = %6d)  ",  p->lSingles.nItems, p->nSingleTotal );
+	    fprintf( stdout, "2-cube divs = %6d. (Total = %6d)",  p->nDivsTotal, nPairsTotal );
+	    fprintf( stdout, "\n" );
+    }
+//    Fxu_MatrixPrint( stdout, p );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one cube with literals to the matrix.]
+
+  Description [Create the cube and literals in the matrix corresponding 
+  to the given cube in the SOP cover. Co-singleton transform is performed here.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Int_t * vFanins, int * pOrder )
+{
+	Fxu_Var * pVar;
+    int Value, i;
+    // add literals to the matrix
+    Abc_CubeForEachVar( pSopCube, Value, i )
+    {
+        Value = pSopCube[pOrder[i]];
+        if ( Value == '0' )
+        {
+            pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]] + 1 ];  // CST
+		    Fxu_MatrixAddLiteral( p, pCube, pVar );
+        }
+        else if ( Value == '1' )
+        {
+            pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]] ];  // CST
+		    Fxu_MatrixAddLiteral( p, pCube, pVar );
+        }
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the new array of Sop covers from the sparse matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_CreateCovers( Fxu_Matrix * p, Fxu_Data_t * pData )
+{
+    Fxu_Cube * pCube, * pCubeFirst, * pCubeNext;
+    char * pSopCover;
+    int iNode, n;
+
+    // get the first cube of the first internal node 
+    pCubeFirst = Fxu_CreateCoversFirstCube( p, pData, 0 );
+
+    // go through the internal nodes
+    for ( n = 0; n < pData->nNodesOld; n++ )
+    if ( (pSopCover = (char *)pData->vSops->pArray[n]) )
+    {
+        // get the number of this node
+        iNode = n;
+        // get the next first cube
+        pCubeNext = Fxu_CreateCoversFirstCube(  p, pData, iNode + 1 );
+        // check if there any new variables in these cubes
+        for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext )
+            if ( pCube->lLits.pTail && pCube->lLits.pTail->iVar >= 2 * pData->nNodesOld )
+                break;
+        if ( pCube != pCubeNext )
+            Fxu_CreateCoversNode( p, pData, iNode, pCubeFirst, pCubeNext );
+        // update the first cube
+        pCubeFirst = pCubeNext;
+    }
+
+    // add the covers for the extracted nodes
+    for ( n = 0; n < pData->nNodesNew; n++ )
+    {
+        // get the number of this node
+        iNode = pData->nNodesOld + n;
+        // get the next first cube
+        pCubeNext = Fxu_CreateCoversFirstCube( p, pData, iNode + 1 );
+        // the node should be added
+        Fxu_CreateCoversNode( p, pData, iNode, pCubeFirst, pCubeNext );
+        // update the first cube
+        pCubeFirst = pCubeNext;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create Sop covers for one node that has changed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_CreateCoversNode( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode, Fxu_Cube * pCubeFirst, Fxu_Cube * pCubeNext )
+{
+    Vec_Int_t * vInputsNew;
+    char * pSopCover, * pSopCube;
+    Fxu_Var * pVar;
+    Fxu_Cube * pCube;
+    Fxu_Lit * pLit;
+    int iNum, nCubes, v;
+
+    // collect positive polarity variable in the cubes between pCubeFirst and pCubeNext
+    Fxu_MatrixRingVarsStart( p );
+    for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext )
+        for ( pLit = pCube->lLits.pHead; pLit; pLit = pLit->pHNext )
+        {
+            pVar = p->ppVars[ 2 * (pLit->pVar->iVar/2) + 1 ];
+            if ( pVar->pOrder == NULL )
+                Fxu_MatrixRingVarsAdd( p, pVar );
+        }
+    Fxu_MatrixRingVarsStop( p );
+
+    // collect the variable numbers
+    vInputsNew = Vec_IntAlloc( 4 );
+    Fxu_MatrixForEachVarInRing( p, pVar )
+        Vec_IntPush( vInputsNew, pVar->iVar / 2 );
+    Fxu_MatrixRingVarsUnmark( p );
+
+    // sort the vars by their number
+    Vec_IntSort( vInputsNew, 0 );
+
+    // mark the vars with their numbers in the sorted array
+    for ( v = 0; v < vInputsNew->nSize; v++ )
+    {
+        p->ppVars[ 2 * vInputsNew->pArray[v] + 0 ]->lLits.nItems = v; // hack - reuse lLits.nItems
+        p->ppVars[ 2 * vInputsNew->pArray[v] + 1 ]->lLits.nItems = v; // hack - reuse lLits.nItems
+    }
+
+    // count the number of cubes
+    nCubes = 0;
+    for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext )
+        if ( pCube->lLits.nItems )
+            nCubes++;
+
+    // allocate room for the new cover
+    pSopCover = Abc_SopStart( pData->pManSop, nCubes, vInputsNew->nSize );
+    // set the correct polarity of the cover
+    if ( iNode < pData->nNodesOld && Abc_SopGetPhase( (char *)pData->vSops->pArray[iNode] ) == 0 )
+        Abc_SopComplement( pSopCover );
+
+    // add the cubes
+    nCubes = 0;
+    for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext )
+    {
+        if ( pCube->lLits.nItems == 0 )
+            continue;
+        // get hold of the SOP cube
+        pSopCube = pSopCover + nCubes * (vInputsNew->nSize + 3);
+        // insert literals
+        for ( pLit = pCube->lLits.pHead; pLit; pLit = pLit->pHNext )
+        {
+            iNum = pLit->pVar->lLits.nItems; // hack - reuse lLits.nItems
+            assert( iNum < vInputsNew->nSize );
+            if ( pLit->pVar->iVar / 2 < pData->nNodesOld )
+                pSopCube[iNum] = (pLit->pVar->iVar & 1)? '0' : '1';   // reverse CST
+            else
+                pSopCube[iNum] = (pLit->pVar->iVar & 1)? '1' : '0';   // no CST
+        }
+        // count the cube
+        nCubes++;
+    }
+    assert( nCubes == Abc_SopGetCubeNum(pSopCover) );
+
+    // set the new cover and the array of fanins
+    pData->vSopsNew->pArray[iNode]   = pSopCover;
+    pData->vFaninsNew->pArray[iNode] = vInputsNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the var to storage.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fxu_Cube * Fxu_CreateCoversFirstCube( Fxu_Matrix * p, Fxu_Data_t * pData, int iVar )
+{
+    int v;
+    for ( v = iVar; v < pData->nNodesOld + pData->nNodesNew; v++ )
+        if ( p->ppVars[ 2*v + 1 ]->pFirst )
+            return p->ppVars[ 2*v + 1 ]->pFirst;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the vars by their number.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fxu_CreateMatrixLitCompare( int * ptrX, int * ptrY )
+{
+    return s_pLits[*ptrX] - s_pLits[*ptrY];
+} 
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fxu/fxuHeapD.c b/abc-build/src/opt/fxu/fxuHeapD.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fxu/fxuHeapD.c
@@ -0,0 +1,450 @@
+/**CFile****************************************************************
+
+  FileName    [fxuHeapD.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [The priority queue for double cube divisors.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: fxuHeapD.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define FXU_HEAP_DOUBLE_WEIGHT(pDiv)           ((pDiv)->Weight)
+#define FXU_HEAP_DOUBLE_CURRENT(p, pDiv)       ((p)->pTree[(pDiv)->HNum])
+#define FXU_HEAP_DOUBLE_PARENT_EXISTS(p, pDiv) ((pDiv)->HNum > 1)
+#define FXU_HEAP_DOUBLE_CHILD1_EXISTS(p, pDiv) (((pDiv)->HNum << 1) <= p->nItems)
+#define FXU_HEAP_DOUBLE_CHILD2_EXISTS(p, pDiv) ((((pDiv)->HNum << 1)+1) <= p->nItems)
+#define FXU_HEAP_DOUBLE_PARENT(p, pDiv)        ((p)->pTree[(pDiv)->HNum >> 1])
+#define FXU_HEAP_DOUBLE_CHILD1(p, pDiv)        ((p)->pTree[(pDiv)->HNum << 1])
+#define FXU_HEAP_DOUBLE_CHILD2(p, pDiv)        ((p)->pTree[((pDiv)->HNum << 1)+1])
+#define FXU_HEAP_DOUBLE_ASSERT(p, pDiv)        assert( (pDiv)->HNum >= 1 && (pDiv)->HNum <= p->nItemsAlloc )
+
+static void Fxu_HeapDoubleResize( Fxu_HeapDouble * p );                  
+static void Fxu_HeapDoubleSwap( Fxu_Double ** pDiv1, Fxu_Double ** pDiv2 );  
+static void Fxu_HeapDoubleMoveUp( Fxu_HeapDouble * p, Fxu_Double * pDiv );  
+static void Fxu_HeapDoubleMoveDn( Fxu_HeapDouble * p, Fxu_Double * pDiv );  
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fxu_HeapDouble * Fxu_HeapDoubleStart()
+{
+	Fxu_HeapDouble * p;
+	p = ABC_ALLOC( Fxu_HeapDouble, 1 );
+	memset( p, 0, sizeof(Fxu_HeapDouble) );
+	p->nItems      = 0;
+	p->nItemsAlloc = 10000;
+	p->pTree       = ABC_ALLOC( Fxu_Double *, p->nItemsAlloc + 1 );
+	p->pTree[0]    = NULL;
+	return p;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapDoubleResize( Fxu_HeapDouble * p )
+{
+	p->nItemsAlloc *= 2;
+	p->pTree = ABC_REALLOC( Fxu_Double *, p->pTree, p->nItemsAlloc + 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapDoubleStop( Fxu_HeapDouble * p )
+{
+	ABC_FREE( p->pTree );
+	ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapDoublePrint( FILE * pFile, Fxu_HeapDouble * p )
+{
+	Fxu_Double * pDiv;
+	int Counter = 1;
+	int Degree  = 1;
+
+	Fxu_HeapDoubleCheck( p );
+	fprintf( pFile, "The contents of the heap:\n" );
+	fprintf( pFile, "Level %d:  ", Degree );
+	Fxu_HeapDoubleForEachItem( p, pDiv )
+	{
+		assert( Counter == p->pTree[Counter]->HNum );
+		fprintf( pFile, "%2d=%3d  ", Counter, FXU_HEAP_DOUBLE_WEIGHT(p->pTree[Counter]) );
+		if ( ++Counter == (1 << Degree) )
+		{
+			fprintf( pFile, "\n" );
+			Degree++;
+			fprintf( pFile, "Level %d:  ", Degree );
+		}
+	}
+	fprintf( pFile, "\n" );
+	fprintf( pFile, "End of the heap printout.\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapDoubleCheck( Fxu_HeapDouble * p )
+{
+	Fxu_Double * pDiv;
+	Fxu_HeapDoubleForEachItem( p, pDiv )
+	{
+		assert( pDiv->HNum == p->i );
+        Fxu_HeapDoubleCheckOne( p, pDiv );
+	}
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapDoubleCheckOne( Fxu_HeapDouble * p, Fxu_Double * pDiv )
+{
+    int Weight1, Weight2;
+	if ( FXU_HEAP_DOUBLE_CHILD1_EXISTS(p,pDiv) )
+	{
+        Weight1 = FXU_HEAP_DOUBLE_WEIGHT(pDiv);
+        Weight2 = FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD1(p,pDiv) );
+        assert( Weight1 >= Weight2 );
+	}
+	if ( FXU_HEAP_DOUBLE_CHILD2_EXISTS(p,pDiv) )
+	{
+        Weight1 = FXU_HEAP_DOUBLE_WEIGHT(pDiv);
+        Weight2 = FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD2(p,pDiv) );
+        assert( Weight1 >= Weight2 );
+	}
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapDoubleInsert( Fxu_HeapDouble * p, Fxu_Double * pDiv )
+{
+	if ( p->nItems == p->nItemsAlloc )
+		Fxu_HeapDoubleResize( p );
+	// put the last entry to the last place and move up
+	p->pTree[++p->nItems] = pDiv;
+	pDiv->HNum = p->nItems;
+	// move the last entry up if necessary
+	Fxu_HeapDoubleMoveUp( p, pDiv );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapDoubleUpdate( Fxu_HeapDouble * p, Fxu_Double * pDiv )
+{
+//printf( "Updating divisor %d.\n", pDiv->Num );
+
+	FXU_HEAP_DOUBLE_ASSERT(p,pDiv);
+	if ( FXU_HEAP_DOUBLE_PARENT_EXISTS(p,pDiv) && 
+         FXU_HEAP_DOUBLE_WEIGHT(pDiv) > FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_PARENT(p,pDiv) ) )
+		Fxu_HeapDoubleMoveUp( p, pDiv );
+	else if ( FXU_HEAP_DOUBLE_CHILD1_EXISTS(p,pDiv) && 
+        FXU_HEAP_DOUBLE_WEIGHT(pDiv) < FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD1(p,pDiv) ) )
+		Fxu_HeapDoubleMoveDn( p, pDiv );
+	else if ( FXU_HEAP_DOUBLE_CHILD2_EXISTS(p,pDiv) && 
+        FXU_HEAP_DOUBLE_WEIGHT(pDiv) < FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD2(p,pDiv) ) )
+		Fxu_HeapDoubleMoveDn( p, pDiv );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapDoubleDelete( Fxu_HeapDouble * p, Fxu_Double * pDiv )
+{
+	FXU_HEAP_DOUBLE_ASSERT(p,pDiv);
+	// put the last entry to the deleted place
+	// decrement the number of entries
+	p->pTree[pDiv->HNum] = p->pTree[p->nItems--];
+	p->pTree[pDiv->HNum]->HNum = pDiv->HNum;
+	// move the top entry down if necessary
+	Fxu_HeapDoubleUpdate( p, p->pTree[pDiv->HNum] );
+    pDiv->HNum = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fxu_Double * Fxu_HeapDoubleReadMax( Fxu_HeapDouble * p )
+{
+	if ( p->nItems == 0 )
+		return NULL;
+	return p->pTree[1];	 
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fxu_Double * Fxu_HeapDoubleGetMax( Fxu_HeapDouble * p )
+{
+	Fxu_Double * pDiv;
+	if ( p->nItems == 0 )
+		return NULL;
+	// prepare the return value
+	pDiv = p->pTree[1];
+	pDiv->HNum = 0;
+	// put the last entry on top
+	// decrement the number of entries
+	p->pTree[1] = p->pTree[p->nItems--];
+	p->pTree[1]->HNum = 1;
+	// move the top entry down if necessary
+	Fxu_HeapDoubleMoveDn( p, p->pTree[1] );
+	return pDiv;	 
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int  Fxu_HeapDoubleReadMaxWeight( Fxu_HeapDouble * p )
+{
+	if ( p->nItems == 0 )
+		return -1;
+	else
+		return FXU_HEAP_DOUBLE_WEIGHT(p->pTree[1]);
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapDoubleSwap( Fxu_Double ** pDiv1, Fxu_Double ** pDiv2 )
+{
+	Fxu_Double * pDiv;
+	int Temp;
+	pDiv   = *pDiv1;
+	*pDiv1 = *pDiv2;
+	*pDiv2 = pDiv;
+	Temp          = (*pDiv1)->HNum;
+	(*pDiv1)->HNum = (*pDiv2)->HNum;
+	(*pDiv2)->HNum = Temp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapDoubleMoveUp( Fxu_HeapDouble * p, Fxu_Double * pDiv )
+{
+	Fxu_Double ** ppDiv, ** ppPar;
+	ppDiv = &FXU_HEAP_DOUBLE_CURRENT(p, pDiv);
+	while ( FXU_HEAP_DOUBLE_PARENT_EXISTS(p,*ppDiv) )
+	{
+		ppPar = &FXU_HEAP_DOUBLE_PARENT(p,*ppDiv);
+		if ( FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) > FXU_HEAP_DOUBLE_WEIGHT(*ppPar) )
+		{
+			Fxu_HeapDoubleSwap( ppDiv, ppPar );
+			ppDiv = ppPar;
+		}
+		else
+			break;
+	}
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapDoubleMoveDn( Fxu_HeapDouble * p, Fxu_Double * pDiv )
+{
+	Fxu_Double ** ppChild1, ** ppChild2, ** ppDiv;
+	ppDiv = &FXU_HEAP_DOUBLE_CURRENT(p, pDiv);
+	while ( FXU_HEAP_DOUBLE_CHILD1_EXISTS(p,*ppDiv) )
+	{ // if Child1 does not exist, Child2 also does not exists
+
+		// get the children
+		ppChild1 = &FXU_HEAP_DOUBLE_CHILD1(p,*ppDiv);
+        if ( FXU_HEAP_DOUBLE_CHILD2_EXISTS(p,*ppDiv) )
+        {
+            ppChild2 = &FXU_HEAP_DOUBLE_CHILD2(p,*ppDiv);
+
+            // consider two cases
+            if ( FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild1) &&
+                 FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild2) )
+            { // Div is larger than both, skip
+                break;
+            }
+            else
+            { // Div is smaller than one of them, then swap it with larger 
+                if ( FXU_HEAP_DOUBLE_WEIGHT(*ppChild1) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild2) )
+                {
+			        Fxu_HeapDoubleSwap( ppDiv, ppChild1 );
+		            // update the pointer
+		            ppDiv = ppChild1;
+                }
+                else
+                {
+			        Fxu_HeapDoubleSwap( ppDiv, ppChild2 );
+		            // update the pointer
+		            ppDiv = ppChild2;
+                }
+            }
+        }
+        else // Child2 does not exist
+        {
+            // consider two cases
+            if ( FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild1) )
+            { // Div is larger than Child1, skip
+                break;
+            }
+            else
+            { // Div is smaller than Child1, then swap them
+			    Fxu_HeapDoubleSwap( ppDiv, ppChild1 );
+		        // update the pointer
+		        ppDiv = ppChild1;
+            }
+        }
+	}
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fxu/fxuHeapS.c b/abc-build/src/opt/fxu/fxuHeapS.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fxu/fxuHeapS.c
@@ -0,0 +1,449 @@
+/**CFile****************************************************************
+
+  FileName    [fxuHeapS.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [The priority queue for variables.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: fxuHeapS.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define FXU_HEAP_SINGLE_WEIGHT(pSingle)           ((pSingle)->Weight)
+#define FXU_HEAP_SINGLE_CURRENT(p, pSingle)       ((p)->pTree[(pSingle)->HNum])
+#define FXU_HEAP_SINGLE_PARENT_EXISTS(p, pSingle) ((pSingle)->HNum > 1)
+#define FXU_HEAP_SINGLE_CHILD1_EXISTS(p, pSingle) (((pSingle)->HNum << 1) <= p->nItems)
+#define FXU_HEAP_SINGLE_CHILD2_EXISTS(p, pSingle) ((((pSingle)->HNum << 1)+1) <= p->nItems)
+#define FXU_HEAP_SINGLE_PARENT(p, pSingle)        ((p)->pTree[(pSingle)->HNum >> 1])
+#define FXU_HEAP_SINGLE_CHILD1(p, pSingle)        ((p)->pTree[(pSingle)->HNum << 1])
+#define FXU_HEAP_SINGLE_CHILD2(p, pSingle)        ((p)->pTree[((pSingle)->HNum << 1)+1])
+#define FXU_HEAP_SINGLE_ASSERT(p, pSingle)        assert( (pSingle)->HNum >= 1 && (pSingle)->HNum <= p->nItemsAlloc )
+
+static void Fxu_HeapSingleResize( Fxu_HeapSingle * p );                  
+static void Fxu_HeapSingleSwap( Fxu_Single ** pSingle1, Fxu_Single ** pSingle2 );  
+static void Fxu_HeapSingleMoveUp( Fxu_HeapSingle * p, Fxu_Single * pSingle );  
+static void Fxu_HeapSingleMoveDn( Fxu_HeapSingle * p, Fxu_Single * pSingle );  
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fxu_HeapSingle * Fxu_HeapSingleStart()
+{
+	Fxu_HeapSingle * p;
+	p = ABC_ALLOC( Fxu_HeapSingle, 1 );
+	memset( p, 0, sizeof(Fxu_HeapSingle) );
+	p->nItems      = 0;
+	p->nItemsAlloc = 2000;
+	p->pTree       = ABC_ALLOC( Fxu_Single *, p->nItemsAlloc + 10 );
+	p->pTree[0]    = NULL;
+	return p;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapSingleResize( Fxu_HeapSingle * p )
+{
+	p->nItemsAlloc *= 2;
+	p->pTree = ABC_REALLOC( Fxu_Single *, p->pTree, p->nItemsAlloc + 10 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapSingleStop( Fxu_HeapSingle * p )
+{
+    int i;
+    i = 0;
+	ABC_FREE( p->pTree );
+    i = 1;
+	ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapSinglePrint( FILE * pFile, Fxu_HeapSingle * p )
+{
+	Fxu_Single * pSingle;
+	int Counter = 1;
+	int Degree  = 1;
+
+	Fxu_HeapSingleCheck( p );
+	fprintf( pFile, "The contents of the heap:\n" );
+	fprintf( pFile, "Level %d:  ", Degree );
+	Fxu_HeapSingleForEachItem( p, pSingle )
+	{
+		assert( Counter == p->pTree[Counter]->HNum );
+		fprintf( pFile, "%2d=%3d  ", Counter, FXU_HEAP_SINGLE_WEIGHT(p->pTree[Counter]) );
+		if ( ++Counter == (1 << Degree) )
+		{
+			fprintf( pFile, "\n" );
+			Degree++;
+			fprintf( pFile, "Level %d:  ", Degree );
+		}
+	}
+	fprintf( pFile, "\n" );
+	fprintf( pFile, "End of the heap printout.\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapSingleCheck( Fxu_HeapSingle * p )
+{
+	Fxu_Single * pSingle;
+	Fxu_HeapSingleForEachItem( p, pSingle )
+	{
+		assert( pSingle->HNum == p->i );
+        Fxu_HeapSingleCheckOne( p, pSingle );
+	}
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapSingleCheckOne( Fxu_HeapSingle * p, Fxu_Single * pSingle )
+{
+    int Weight1, Weight2;
+	if ( FXU_HEAP_SINGLE_CHILD1_EXISTS(p,pSingle) )
+	{
+        Weight1 = FXU_HEAP_SINGLE_WEIGHT(pSingle);
+        Weight2 = FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD1(p,pSingle) );
+        assert( Weight1 >= Weight2 );
+	}
+	if ( FXU_HEAP_SINGLE_CHILD2_EXISTS(p,pSingle) )
+	{
+        Weight1 = FXU_HEAP_SINGLE_WEIGHT(pSingle);
+        Weight2 = FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD2(p,pSingle) );
+        assert( Weight1 >= Weight2 );
+	}
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapSingleInsert( Fxu_HeapSingle * p, Fxu_Single * pSingle )
+{
+	if ( p->nItems == p->nItemsAlloc )
+		Fxu_HeapSingleResize( p );
+	// put the last entry to the last place and move up
+	p->pTree[++p->nItems] = pSingle;
+	pSingle->HNum = p->nItems;
+	// move the last entry up if necessary
+	Fxu_HeapSingleMoveUp( p, pSingle );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapSingleUpdate( Fxu_HeapSingle * p, Fxu_Single * pSingle )
+{
+	FXU_HEAP_SINGLE_ASSERT(p,pSingle);
+	if ( FXU_HEAP_SINGLE_PARENT_EXISTS(p,pSingle) && 
+         FXU_HEAP_SINGLE_WEIGHT(pSingle) > FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_PARENT(p,pSingle) ) )
+		Fxu_HeapSingleMoveUp( p, pSingle );
+	else if ( FXU_HEAP_SINGLE_CHILD1_EXISTS(p,pSingle) && 
+        FXU_HEAP_SINGLE_WEIGHT(pSingle) < FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD1(p,pSingle) ) )
+		Fxu_HeapSingleMoveDn( p, pSingle );
+	else if ( FXU_HEAP_SINGLE_CHILD2_EXISTS(p,pSingle) && 
+        FXU_HEAP_SINGLE_WEIGHT(pSingle) < FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD2(p,pSingle) ) )
+		Fxu_HeapSingleMoveDn( p, pSingle );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapSingleDelete( Fxu_HeapSingle * p, Fxu_Single * pSingle )
+{
+    int Place = pSingle->HNum;
+	FXU_HEAP_SINGLE_ASSERT(p,pSingle);
+	// put the last entry to the deleted place
+	// decrement the number of entries
+	p->pTree[Place] = p->pTree[p->nItems--];
+	p->pTree[Place]->HNum = Place;
+	// move the top entry down if necessary
+	Fxu_HeapSingleUpdate( p, p->pTree[Place] );
+    pSingle->HNum = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fxu_Single * Fxu_HeapSingleReadMax( Fxu_HeapSingle * p )
+{
+	if ( p->nItems == 0 )
+		return NULL;
+	return p->pTree[1];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fxu_Single * Fxu_HeapSingleGetMax( Fxu_HeapSingle * p )
+{
+	Fxu_Single * pSingle;
+	if ( p->nItems == 0 )
+		return NULL;
+	// prepare the return value
+	pSingle = p->pTree[1];
+	pSingle->HNum = 0;
+	// put the last entry on top
+	// decrement the number of entries
+	p->pTree[1] = p->pTree[p->nItems--];
+	p->pTree[1]->HNum = 1;
+	// move the top entry down if necessary
+	Fxu_HeapSingleMoveDn( p, p->pTree[1] );
+	return pSingle;	 
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int  Fxu_HeapSingleReadMaxWeight( Fxu_HeapSingle * p )
+{
+	if ( p->nItems == 0 )
+		return -1;
+	return FXU_HEAP_SINGLE_WEIGHT(p->pTree[1]);
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapSingleSwap( Fxu_Single ** pSingle1, Fxu_Single ** pSingle2 )
+{
+	Fxu_Single * pSingle;
+	int Temp;
+	pSingle   = *pSingle1;
+	*pSingle1 = *pSingle2;
+	*pSingle2 = pSingle;
+	Temp          = (*pSingle1)->HNum;
+	(*pSingle1)->HNum = (*pSingle2)->HNum;
+	(*pSingle2)->HNum = Temp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapSingleMoveUp( Fxu_HeapSingle * p, Fxu_Single * pSingle )
+{
+	Fxu_Single ** ppSingle, ** ppPar;
+	ppSingle = &FXU_HEAP_SINGLE_CURRENT(p, pSingle);
+	while ( FXU_HEAP_SINGLE_PARENT_EXISTS(p,*ppSingle) )
+	{
+		ppPar = &FXU_HEAP_SINGLE_PARENT(p,*ppSingle);
+		if ( FXU_HEAP_SINGLE_WEIGHT(*ppSingle) > FXU_HEAP_SINGLE_WEIGHT(*ppPar) )
+		{
+			Fxu_HeapSingleSwap( ppSingle, ppPar );
+			ppSingle = ppPar;
+		}
+		else
+			break;
+	}
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_HeapSingleMoveDn( Fxu_HeapSingle * p, Fxu_Single * pSingle )
+{
+	Fxu_Single ** ppChild1, ** ppChild2, ** ppSingle;
+	ppSingle = &FXU_HEAP_SINGLE_CURRENT(p, pSingle);
+	while ( FXU_HEAP_SINGLE_CHILD1_EXISTS(p,*ppSingle) )
+	{ // if Child1 does not exist, Child2 also does not exists
+
+		// get the children
+		ppChild1 = &FXU_HEAP_SINGLE_CHILD1(p,*ppSingle);
+        if ( FXU_HEAP_SINGLE_CHILD2_EXISTS(p,*ppSingle) )
+        {
+            ppChild2 = &FXU_HEAP_SINGLE_CHILD2(p,*ppSingle);
+
+            // consider two cases
+            if ( FXU_HEAP_SINGLE_WEIGHT(*ppSingle) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild1) &&
+                 FXU_HEAP_SINGLE_WEIGHT(*ppSingle) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild2) )
+            { // Var is larger than both, skip
+                break;
+            }
+            else
+            { // Var is smaller than one of them, then swap it with larger 
+                if ( FXU_HEAP_SINGLE_WEIGHT(*ppChild1) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild2) )
+                {
+			        Fxu_HeapSingleSwap( ppSingle, ppChild1 );
+		            // update the pointer
+		            ppSingle = ppChild1;
+                }
+                else
+                {
+			        Fxu_HeapSingleSwap( ppSingle, ppChild2 );
+		            // update the pointer
+		            ppSingle = ppChild2;
+                }
+            }
+        }
+        else // Child2 does not exist
+        {
+            // consider two cases
+            if ( FXU_HEAP_SINGLE_WEIGHT(*ppSingle) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild1) )
+            { // Var is larger than Child1, skip
+                break;
+            }
+            else
+            { // Var is smaller than Child1, then swap them
+			    Fxu_HeapSingleSwap( ppSingle, ppChild1 );
+		        // update the pointer
+		        ppSingle = ppChild1;
+            }
+        }
+	}
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fxu/fxuInt.h b/abc-build/src/opt/fxu/fxuInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fxu/fxuInt.h
@@ -0,0 +1,545 @@
+/**CFile****************************************************************
+
+  FileName    [fxuInt.h]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Internal declarations of fast extract for unate covers.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: fxuInt.h,v 1.3 2003/04/10 05:42:44 donald Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__opt__fxu__fxuInt_h
+#define ABC__opt__fxu__fxuInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "base/abc/abc.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+// uncomment this macro to switch to standard memory management
+//#define USE_SYSTEM_MEMORY_MANAGEMENT 
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*  
+	Here is an informal description of the FX data structure.
+	(1) The sparse matrix is filled with literals, associated with 
+	    cubes (row) and variables (columns). The matrix contains 
+        all the cubes of all the nodes in the network.
+	(2) A cube is associated with 
+	    (a) its literals in the matrix,
+	    (b) the output variable of the node, to which this cube belongs,
+	(3) A variable is associated with 
+	    (a) its literals in the matrix and
+		(b) the list of cube pairs in the cover, for which it is the output
+	(4) A cube pair is associated with two cubes and contains the counters
+	    of literals in the base and in the cubes without the base
+	(5) A double-cube divisor is associated with list of all cube pairs 
+        that produce it and its current weight (which is updated automatically 
+        each time a new pair is added or an old pair is removed). 
+	(6) A single-cube divisor is associated the pair of variables. 
+*/
+
+// sparse matrix
+typedef struct FxuMatrix        Fxu_Matrix;     // the sparse matrix
+
+// sparse matrix contents: cubes (rows), vars (columns), literals (entries)
+typedef struct FxuCube          Fxu_Cube;       // one cube in the sparse matrix
+typedef struct FxuVar           Fxu_Var;        // one literal in the sparse matrix
+typedef struct FxuLit           Fxu_Lit;        // one entry in the sparse matrix
+
+// double cube divisors
+typedef struct FxuPair          Fxu_Pair;       // the pair of cubes
+typedef struct FxuDouble        Fxu_Double;     // the double-cube divisor
+typedef struct FxuSingle        Fxu_Single;     // the two-literal single-cube divisor
+
+// various lists
+typedef struct FxuListCube      Fxu_ListCube;   // the list of cubes
+typedef struct FxuListVar       Fxu_ListVar;    // the list of literals
+typedef struct FxuListLit       Fxu_ListLit;    // the list of entries
+typedef struct FxuListPair      Fxu_ListPair;   // the list of pairs
+typedef struct FxuListDouble    Fxu_ListDouble; // the list of divisors
+typedef struct FxuListSingle    Fxu_ListSingle; // the list of single-cube divisors
+
+// various heaps
+typedef struct FxuHeapDouble    Fxu_HeapDouble; // the heap of divisors
+typedef struct FxuHeapSingle    Fxu_HeapSingle; // the heap of variables
+
+
+// various lists
+
+// the list of cubes in the sparse matrix 
+struct FxuListCube
+{
+	Fxu_Cube *       pHead;
+	Fxu_Cube *       pTail;
+	int              nItems;
+};
+
+// the list of literals in the sparse matrix 
+struct FxuListVar
+{
+	Fxu_Var *        pHead;
+	Fxu_Var *        pTail;
+	int              nItems;
+};
+
+// the list of entries in the sparse matrix 
+struct FxuListLit
+{
+	Fxu_Lit *        pHead;
+	Fxu_Lit *        pTail;
+	int              nItems;
+};
+
+// the list of cube pair in the sparse matrix 
+struct FxuListPair
+{
+	Fxu_Pair *       pHead;
+	Fxu_Pair *       pTail;
+	int              nItems;
+};
+
+// the list of divisors in the sparse matrix 
+struct FxuListDouble
+{
+	Fxu_Double *     pHead;
+	Fxu_Double *     pTail;
+	int              nItems;
+};
+
+// the list of divisors in the sparse matrix 
+struct FxuListSingle
+{
+	Fxu_Single *     pHead;
+	Fxu_Single *     pTail;
+	int              nItems;
+};
+
+
+// various heaps
+
+// the heap of double cube divisors by weight
+struct FxuHeapDouble
+{
+	Fxu_Double **    pTree;
+	int              nItems;
+	int              nItemsAlloc;
+	int              i;
+};
+
+// the heap of variable by their occurrence in the cubes
+struct FxuHeapSingle
+{
+	Fxu_Single **    pTree;
+	int              nItems;
+	int              nItemsAlloc;
+	int              i;
+};
+
+
+
+// sparse matrix
+struct FxuMatrix // ~ 30 words
+{
+	// the cubes
+	Fxu_ListCube     lCubes;      // the double linked list of cubes
+    // the values (binary literals)
+	Fxu_ListVar      lVars;       // the double linked list of variables
+  	Fxu_Var **       ppVars;      // the array of variables
+	// the double cube divisors
+	Fxu_ListDouble * pTable;      // the hash table of divisors
+	int              nTableSize;  // the hash table size
+    int              nDivs;       // the number of divisors in the table
+    int              nDivsTotal;  // the number of divisors in the table
+	Fxu_HeapDouble * pHeapDouble;    // the heap of divisors by weight
+    // the single cube divisors
+    Fxu_ListSingle   lSingles;    // the linked list of single cube divisors  
+	Fxu_HeapSingle * pHeapSingle; // the heap of variables by the number of literals in the matrix
+    int              nWeightLimit;// the limit on weight of single cube divisors collected
+    int              nSingleTotal;// the total number of single cube divisors
+    // storage for cube pairs
+    Fxu_Pair ***     pppPairs;
+    Fxu_Pair **      ppPairs;
+	// temporary storage for cubes 
+    Fxu_Cube *       pOrderCubes;
+    Fxu_Cube **      ppTailCubes;
+	// temporary storage for variables 
+    Fxu_Var *        pOrderVars;
+    Fxu_Var **       ppTailVars;
+    // temporary storage for pairs
+    Vec_Ptr_t *      vPairs;
+	// statistics
+	int              nEntries;    // the total number of entries in the sparse matrix
+	int              nDivs1;      // the single cube divisors taken
+	int              nDivs2;      // the double cube divisors taken
+	int              nDivs3;      // the double cube divisors with complement
+	// memory manager
+	Extra_MmFixed_t * pMemMan;     // the memory manager for all small sized entries
+};
+
+// the cube in the sparse matrix
+struct FxuCube // 9 words
+{
+	int              iCube;       // the number of this cube in the cover
+	Fxu_Cube *       pFirst;      // the pointer to the first cube of this cover
+	Fxu_Var *        pVar;        // the variable representing the output of the cover
+	Fxu_ListLit      lLits;       // the row in the table 
+	Fxu_Cube *       pPrev;       // the previous cube
+	Fxu_Cube *       pNext;       // the next cube
+    Fxu_Cube *       pOrder;      // the specialized linked list of cubes
+};
+
+// the variable in the sparse matrix
+struct FxuVar // 10 words
+{
+	int              iVar;        // the number of this variable
+    int              nCubes;      // the number of cubes assoc with this var
+    Fxu_Cube *       pFirst;      // the first cube assoc with this var
+    Fxu_Pair ***     ppPairs;     // the pairs of cubes assoc with this var
+	Fxu_ListLit      lLits;       // the column in the table 
+	Fxu_Var *        pPrev;       // the previous variable
+	Fxu_Var *        pNext;       // the next variable
+    Fxu_Var *        pOrder;      // the specialized linked list of variables
+};
+
+// the literal entry in the sparse matrix 
+struct FxuLit // 8 words
+{
+	int              iVar;        // the number of this variable
+	int              iCube;       // the number of this cube
+	Fxu_Cube *       pCube;       // the cube of this literal
+	Fxu_Var *        pVar;        // the variable of this literal
+	Fxu_Lit *        pHPrev;      // prev lit in the cube
+	Fxu_Lit *        pHNext;      // next lit in the cube
+	Fxu_Lit *        pVPrev;      // prev lit of the var     
+	Fxu_Lit *        pVNext;      // next lit of the var   
+};
+
+// the cube pair
+struct FxuPair // 10 words
+{
+	int              nLits1;      // the number of literals in the two cubes
+	int              nLits2;      // the number of literals in the two cubes
+	int              nBase;       // the number of literals in the base
+	Fxu_Double *     pDiv;        // the divisor of this pair
+	Fxu_Cube *       pCube1;      // the first cube of the pair
+	Fxu_Cube *       pCube2;      // the second cube of the pair
+	int              iCube1;      // the first cube of the pair
+	int              iCube2;      // the second cube of the pair
+	Fxu_Pair *       pDPrev;      // the previous pair in the divisor
+	Fxu_Pair *       pDNext;      // the next pair in the divisor
+};
+
+// the double cube divisor
+struct FxuDouble // 10 words
+{
+	int              Num;         // the unique number of this divisor
+	int              HNum;        // the heap number of this divisor
+	int              Weight;      // the weight of this divisor
+	unsigned         Key;         // the hash key of this divisor
+	Fxu_ListPair     lPairs;      // the pairs of cubes, which produce this divisor
+	Fxu_Double *     pPrev;       // the previous divisor in the table
+	Fxu_Double *     pNext;       // the next divisor in the table
+    Fxu_Double *     pOrder;      // the specialized linked list of divisors
+};
+
+// the single cube divisor
+struct FxuSingle // 7 words
+{
+	int              Num;         // the unique number of this divisor
+	int              HNum;        // the heap number of this divisor
+	int              Weight;      // the weight of this divisor
+	Fxu_Var *        pVar1;       // the first variable of the single-cube divisor
+	Fxu_Var *        pVar2;       // the second variable of the single-cube divisor
+	Fxu_Single *     pPrev;       // the previous divisor in the list
+	Fxu_Single *     pNext;       // the next divisor in the list
+};
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+// minimum/maximum
+#define Fxu_Min( a, b ) ( ((a)<(b))? (a):(b) )
+#define Fxu_Max( a, b ) ( ((a)>(b))? (a):(b) )
+
+// selection of the minimum/maximum cube in the pair
+#define Fxu_PairMinCube( pPair )    (((pPair)->iCube1 < (pPair)->iCube2)? (pPair)->pCube1: (pPair)->pCube2)
+#define Fxu_PairMaxCube( pPair )    (((pPair)->iCube1 > (pPair)->iCube2)? (pPair)->pCube1: (pPair)->pCube2)
+#define Fxu_PairMinCubeInt( pPair ) (((pPair)->iCube1 < (pPair)->iCube2)? (pPair)->iCube1: (pPair)->iCube2)
+#define Fxu_PairMaxCubeInt( pPair ) (((pPair)->iCube1 > (pPair)->iCube2)? (pPair)->iCube1: (pPair)->iCube2)
+
+// iterators
+
+#define Fxu_MatrixForEachCube( Matrix, Cube )\
+	for ( Cube = (Matrix)->lCubes.pHead;\
+          Cube;\
+		  Cube = Cube->pNext )
+#define Fxu_MatrixForEachCubeSafe( Matrix, Cube, Cube2 )\
+	for ( Cube = (Matrix)->lCubes.pHead, Cube2 = (Cube? Cube->pNext: NULL);\
+          Cube;\
+		  Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) )
+
+#define Fxu_MatrixForEachVariable( Matrix, Var )\
+	for ( Var = (Matrix)->lVars.pHead;\
+          Var;\
+		  Var = Var->pNext )
+#define Fxu_MatrixForEachVariableSafe( Matrix, Var, Var2 )\
+	for ( Var = (Matrix)->lVars.pHead, Var2 = (Var? Var->pNext: NULL);\
+          Var;\
+		  Var = Var2, Var2 = (Var? Var->pNext: NULL) )
+
+#define Fxu_MatrixForEachSingle( Matrix, Single )\
+	for ( Single = (Matrix)->lSingles.pHead;\
+          Single;\
+		  Single = Single->pNext )
+#define Fxu_MatrixForEachSingleSafe( Matrix, Single, Single2 )\
+	for ( Single = (Matrix)->lSingles.pHead, Single2 = (Single? Single->pNext: NULL);\
+          Single;\
+		  Single = Single2, Single2 = (Single? Single->pNext: NULL) )
+
+#define Fxu_TableForEachDouble( Matrix, Key, Div )\
+	for ( Div = (Matrix)->pTable[Key].pHead;\
+          Div;\
+		  Div = Div->pNext )
+#define Fxu_TableForEachDoubleSafe( Matrix, Key, Div, Div2 )\
+	for ( Div = (Matrix)->pTable[Key].pHead, Div2 = (Div? Div->pNext: NULL);\
+          Div;\
+		  Div = Div2, Div2 = (Div? Div->pNext: NULL) )
+
+#define Fxu_MatrixForEachDouble( Matrix, Div, Index )\
+    for ( Index = 0; Index < (Matrix)->nTableSize; Index++ )\
+        Fxu_TableForEachDouble( Matrix, Index, Div )
+#define Fxu_MatrixForEachDoubleSafe( Matrix, Div, Div2, Index )\
+    for ( Index = 0; Index < (Matrix)->nTableSize; Index++ )\
+        Fxu_TableForEachDoubleSafe( Matrix, Index, Div, Div2 )
+
+
+#define Fxu_CubeForEachLiteral( Cube, Lit )\
+	for ( Lit = (Cube)->lLits.pHead;\
+          Lit;\
+		  Lit = Lit->pHNext )
+#define Fxu_CubeForEachLiteralSafe( Cube, Lit, Lit2 )\
+	for ( Lit = (Cube)->lLits.pHead, Lit2 = (Lit? Lit->pHNext: NULL);\
+          Lit;\
+		  Lit = Lit2, Lit2 = (Lit? Lit->pHNext: NULL) )
+
+#define Fxu_VarForEachLiteral( Var, Lit )\
+	for ( Lit = (Var)->lLits.pHead;\
+          Lit;\
+		  Lit = Lit->pVNext )
+
+#define Fxu_CubeForEachDivisor( Cube, Div )\
+	for ( Div = (Cube)->lDivs.pHead;\
+          Div;\
+		  Div = Div->pCNext )
+
+#define Fxu_DoubleForEachPair( Div, Pair )\
+	for ( Pair = (Div)->lPairs.pHead;\
+          Pair;\
+		  Pair = Pair->pDNext )
+#define Fxu_DoubleForEachPairSafe( Div, Pair, Pair2 )\
+	for ( Pair = (Div)->lPairs.pHead, Pair2 = (Pair? Pair->pDNext: NULL);\
+          Pair;\
+		  Pair = Pair2, Pair2 = (Pair? Pair->pDNext: NULL) )
+
+
+// iterator through the cube pairs belonging to the given cube 
+#define Fxu_CubeForEachPair( pCube, pPair, i )\
+  for ( i = 0;\
+        i < pCube->pVar->nCubes && (((pPair) = (pCube)->pVar->ppPairs[(pCube)->iCube][i]), 1);\
+		i++ )\
+        if ( pPair == NULL ) {} else
+
+// iterator through all the items in the heap
+#define Fxu_HeapDoubleForEachItem( Heap, Div )\
+	for ( Heap->i = 1;\
+		  Heap->i <= Heap->nItems && (Div = Heap->pTree[Heap->i]);\
+		  Heap->i++ )
+#define Fxu_HeapSingleForEachItem( Heap, Single )\
+	for ( Heap->i = 1;\
+		  Heap->i <= Heap->nItems && (Single = Heap->pTree[Heap->i]);\
+		  Heap->i++ )
+
+// starting the rings
+#define Fxu_MatrixRingCubesStart( Matrix )    (((Matrix)->ppTailCubes = &((Matrix)->pOrderCubes)), ((Matrix)->pOrderCubes = NULL))
+#define Fxu_MatrixRingVarsStart(  Matrix )    (((Matrix)->ppTailVars  = &((Matrix)->pOrderVars)),  ((Matrix)->pOrderVars  = NULL))
+// stopping the rings
+#define Fxu_MatrixRingCubesStop(  Matrix )
+#define Fxu_MatrixRingVarsStop(   Matrix )
+// resetting the rings
+#define Fxu_MatrixRingCubesReset( Matrix )    (((Matrix)->pOrderCubes = NULL), ((Matrix)->ppTailCubes = NULL))
+#define Fxu_MatrixRingVarsReset(  Matrix )    (((Matrix)->pOrderVars  = NULL), ((Matrix)->ppTailVars  = NULL))
+// adding to the rings
+#define Fxu_MatrixRingCubesAdd( Matrix, Cube) ((*((Matrix)->ppTailCubes) = Cube), ((Matrix)->ppTailCubes = &(Cube)->pOrder), ((Cube)->pOrder = (Fxu_Cube *)1))
+#define Fxu_MatrixRingVarsAdd(  Matrix, Var ) ((*((Matrix)->ppTailVars ) = Var ), ((Matrix)->ppTailVars  = &(Var)->pOrder ), ((Var)->pOrder  = (Fxu_Var *)1))
+// iterating through the rings
+#define Fxu_MatrixForEachCubeInRing( Matrix, Cube )\
+    if ( (Matrix)->pOrderCubes )\
+	for ( Cube = (Matrix)->pOrderCubes;\
+          Cube != (Fxu_Cube *)1;\
+		  Cube = Cube->pOrder )
+#define Fxu_MatrixForEachCubeInRingSafe( Matrix, Cube, Cube2 )\
+    if ( (Matrix)->pOrderCubes )\
+	for ( Cube = (Matrix)->pOrderCubes, Cube2 = ((Cube != (Fxu_Cube *)1)? Cube->pOrder: (Fxu_Cube *)1);\
+          Cube != (Fxu_Cube *)1;\
+		  Cube = Cube2, Cube2 = ((Cube != (Fxu_Cube *)1)? Cube->pOrder: (Fxu_Cube *)1) )
+#define Fxu_MatrixForEachVarInRing( Matrix, Var )\
+    if ( (Matrix)->pOrderVars )\
+	for ( Var = (Matrix)->pOrderVars;\
+          Var != (Fxu_Var *)1;\
+		  Var = Var->pOrder )
+#define Fxu_MatrixForEachVarInRingSafe( Matrix, Var, Var2 )\
+    if ( (Matrix)->pOrderVars )\
+	for ( Var = (Matrix)->pOrderVars, Var2 = ((Var != (Fxu_Var *)1)? Var->pOrder: (Fxu_Var *)1);\
+          Var != (Fxu_Var *)1;\
+		  Var = Var2, Var2 = ((Var != (Fxu_Var *)1)? Var->pOrder: (Fxu_Var *)1) )
+// the procedures are related to the above macros
+extern void Fxu_MatrixRingCubesUnmark( Fxu_Matrix * p );
+extern void Fxu_MatrixRingVarsUnmark( Fxu_Matrix * p );
+
+
+// macros working with memory
+// MEM_ALLOC: allocate the given number (Size) of items of type (Type)
+// MEM_FREE:  deallocate the pointer (Pointer) to the given number (Size) of items of type (Type)
+#ifdef USE_SYSTEM_MEMORY_MANAGEMENT
+#define MEM_ALLOC_FXU( Manager, Type, Size )          ((Type *)ABC_ALLOC( char, (Size) * sizeof(Type) ))
+#define MEM_FREE_FXU( Manager, Type, Size, Pointer )  if ( Pointer ) { ABC_FREE(Pointer); Pointer = NULL; }
+#else
+#define MEM_ALLOC_FXU( Manager, Type, Size )\
+        ((Type *)Fxu_MemFetch( Manager, (Size) * sizeof(Type) ))
+#define MEM_FREE_FXU( Manager, Type, Size, Pointer )\
+         if ( Pointer ) { Fxu_MemRecycle( Manager, (char *)(Pointer), (Size) * sizeof(Type) ); Pointer = NULL; }
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*===== fxu.c ====================================================*/
+extern char *       Fxu_MemFetch( Fxu_Matrix * p, int nBytes );
+extern void         Fxu_MemRecycle( Fxu_Matrix * p, char * pItem, int nBytes );
+/*===== fxuCreate.c ====================================================*/
+/*===== fxuReduce.c ====================================================*/
+/*===== fxuPrint.c ====================================================*/
+extern void         Fxu_MatrixPrint( FILE * pFile, Fxu_Matrix * p );
+extern void         Fxu_MatrixPrintDivisorProfile( FILE * pFile, Fxu_Matrix * p );
+/*===== fxuSelect.c ====================================================*/
+extern int          Fxu_Select( Fxu_Matrix * p, Fxu_Single ** ppSingle, Fxu_Double ** ppDouble );
+extern int          Fxu_SelectSCD( Fxu_Matrix * p, int Weight, Fxu_Var ** ppVar1, Fxu_Var ** ppVar2 );
+/*===== fxuUpdate.c ====================================================*/
+extern void         Fxu_Update( Fxu_Matrix * p, Fxu_Single * pSingle, Fxu_Double * pDouble );
+extern void         Fxu_UpdateDouble( Fxu_Matrix * p );
+extern void         Fxu_UpdateSingle( Fxu_Matrix * p );
+/*===== fxuPair.c ====================================================*/
+extern void         Fxu_PairCanonicize( Fxu_Cube ** ppCube1, Fxu_Cube ** ppCube2 );
+extern unsigned     Fxu_PairHashKeyArray( Fxu_Matrix * p, int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 );
+extern unsigned     Fxu_PairHashKey( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, int * pnBase, int * pnLits1, int * pnLits2 );
+extern unsigned     Fxu_PairHashKeyMv( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, int * pnBase, int * pnLits1, int * pnLits2 );
+extern int          Fxu_PairCompare( Fxu_Pair * pPair1, Fxu_Pair * pPair2 );
+extern void         Fxu_PairAllocStorage( Fxu_Var * pVar, int nCubes );
+extern void         Fxu_PairFreeStorage( Fxu_Var * pVar );
+extern void         Fxu_PairClearStorage( Fxu_Cube * pCube );
+extern Fxu_Pair *   Fxu_PairAlloc( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 );
+extern void         Fxu_PairAdd( Fxu_Pair * pPair );
+/*===== fxuSingle.c ====================================================*/
+extern void         Fxu_MatrixComputeSingles( Fxu_Matrix * p, int fUse0, int nSingleMax );
+extern void         Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar );
+extern int          Fxu_SingleCountCoincidence( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2 );
+/*===== fxuMatrix.c ====================================================*/
+// matrix
+extern Fxu_Matrix * Fxu_MatrixAllocate();
+extern void         Fxu_MatrixDelete( Fxu_Matrix * p );
+// double-cube divisor
+extern void         Fxu_MatrixAddDivisor( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 );
+extern void         Fxu_MatrixDelDivisor( Fxu_Matrix * p, Fxu_Double * pDiv );
+// single-cube divisor
+extern void          Fxu_MatrixAddSingle( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, int Weight );
+// variable
+extern Fxu_Var *    Fxu_MatrixAddVar( Fxu_Matrix * p );
+// cube
+extern Fxu_Cube *   Fxu_MatrixAddCube( Fxu_Matrix * p, Fxu_Var * pVar, int iCube );
+// literal
+extern void         Fxu_MatrixAddLiteral( Fxu_Matrix * p, Fxu_Cube * pCube, Fxu_Var * pVar );
+extern void         Fxu_MatrixDelLiteral( Fxu_Matrix * p, Fxu_Lit * pLit );
+/*===== fxuList.c ====================================================*/
+// matrix -> variable 
+extern void         Fxu_ListMatrixAddVariable( Fxu_Matrix * p, Fxu_Var * pVar );
+extern void         Fxu_ListMatrixDelVariable( Fxu_Matrix * p, Fxu_Var * pVar );
+// matrix -> cube
+extern void         Fxu_ListMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube );
+extern void         Fxu_ListMatrixDelCube( Fxu_Matrix * p, Fxu_Cube * pCube );
+// matrix -> single
+extern void         Fxu_ListMatrixAddSingle( Fxu_Matrix * p, Fxu_Single * pSingle );
+extern void         Fxu_ListMatrixDelSingle( Fxu_Matrix * p, Fxu_Single * pSingle );
+// table -> divisor
+extern void         Fxu_ListTableAddDivisor( Fxu_Matrix * p, Fxu_Double * pDiv );
+extern void         Fxu_ListTableDelDivisor( Fxu_Matrix * p, Fxu_Double * pDiv );
+// cube -> literal 
+extern void         Fxu_ListCubeAddLiteral( Fxu_Cube * pCube, Fxu_Lit * pLit );
+extern void         Fxu_ListCubeDelLiteral( Fxu_Cube * pCube, Fxu_Lit * pLit );
+// var -> literal
+extern void         Fxu_ListVarAddLiteral( Fxu_Var * pVar, Fxu_Lit * pLit );
+extern void         Fxu_ListVarDelLiteral( Fxu_Var * pVar, Fxu_Lit * pLit );
+// divisor -> pair
+extern void         Fxu_ListDoubleAddPairLast( Fxu_Double * pDiv, Fxu_Pair * pLink );
+extern void         Fxu_ListDoubleAddPairFirst( Fxu_Double * pDiv, Fxu_Pair * pLink );
+extern void         Fxu_ListDoubleAddPairMiddle( Fxu_Double * pDiv, Fxu_Pair * pSpot, Fxu_Pair * pLink );
+extern void         Fxu_ListDoubleDelPair( Fxu_Double * pDiv, Fxu_Pair * pPair );
+/*===== fxuHeapDouble.c ====================================================*/
+extern Fxu_HeapDouble * Fxu_HeapDoubleStart();
+extern void         Fxu_HeapDoubleStop( Fxu_HeapDouble * p );
+extern void         Fxu_HeapDoublePrint( FILE * pFile, Fxu_HeapDouble * p );
+extern void         Fxu_HeapDoubleCheck( Fxu_HeapDouble * p );
+extern void         Fxu_HeapDoubleCheckOne( Fxu_HeapDouble * p, Fxu_Double * pDiv );
+
+extern void         Fxu_HeapDoubleInsert( Fxu_HeapDouble * p, Fxu_Double * pDiv );  
+extern void         Fxu_HeapDoubleUpdate( Fxu_HeapDouble * p, Fxu_Double * pDiv );  
+extern void         Fxu_HeapDoubleDelete( Fxu_HeapDouble * p, Fxu_Double * pDiv );  
+extern int          Fxu_HeapDoubleReadMaxWeight( Fxu_HeapDouble * p );  
+extern Fxu_Double * Fxu_HeapDoubleReadMax( Fxu_HeapDouble * p );  
+extern Fxu_Double * Fxu_HeapDoubleGetMax( Fxu_HeapDouble * p );  
+/*===== fxuHeapSingle.c ====================================================*/
+extern Fxu_HeapSingle * Fxu_HeapSingleStart();
+extern void         Fxu_HeapSingleStop( Fxu_HeapSingle * p );
+extern void         Fxu_HeapSinglePrint( FILE * pFile, Fxu_HeapSingle * p );
+extern void         Fxu_HeapSingleCheck( Fxu_HeapSingle * p );
+extern void         Fxu_HeapSingleCheckOne( Fxu_HeapSingle * p, Fxu_Single * pSingle );
+
+extern void         Fxu_HeapSingleInsert( Fxu_HeapSingle * p, Fxu_Single * pSingle );  
+extern void         Fxu_HeapSingleUpdate( Fxu_HeapSingle * p, Fxu_Single * pSingle );  
+extern void         Fxu_HeapSingleDelete( Fxu_HeapSingle * p, Fxu_Single * pSingle );  
+extern int          Fxu_HeapSingleReadMaxWeight( Fxu_HeapSingle * p );  
+extern Fxu_Single * Fxu_HeapSingleReadMax( Fxu_HeapSingle * p );
+extern Fxu_Single * Fxu_HeapSingleGetMax( Fxu_HeapSingle * p );  
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                         END OF FILE                              ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/fxu/fxuList.c b/abc-build/src/opt/fxu/fxuList.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fxu/fxuList.c
@@ -0,0 +1,527 @@
+/**CFile****************************************************************
+
+  FileName    [fxuList.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Operations on lists.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: fxuList.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+// matrix -> var
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_ListMatrixAddVariable( Fxu_Matrix * p, Fxu_Var * pLink ) 
+{
+	Fxu_ListVar * pList = &p->lVars;
+	if ( pList->pHead == NULL )
+	{
+		pList->pHead = pLink;
+		pList->pTail = pLink;
+		pLink->pPrev = NULL;
+		pLink->pNext = NULL;
+	}
+	else
+	{
+		pLink->pNext = NULL;
+		pList->pTail->pNext = pLink;
+		pLink->pPrev = pList->pTail;
+		pList->pTail = pLink;
+	}
+	pList->nItems++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_ListMatrixDelVariable( Fxu_Matrix * p, Fxu_Var * pLink )
+{
+	Fxu_ListVar * pList = &p->lVars;
+	if ( pList->pHead == pLink )
+		 pList->pHead = pLink->pNext;
+	if ( pList->pTail == pLink )
+		 pList->pTail = pLink->pPrev;
+	if ( pLink->pPrev )
+		 pLink->pPrev->pNext = pLink->pNext;
+	if ( pLink->pNext )
+		 pLink->pNext->pPrev = pLink->pPrev;
+	pList->nItems--;
+}
+
+
+// matrix -> cube
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_ListMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pLink )
+{
+	Fxu_ListCube * pList = &p->lCubes;
+	if ( pList->pHead == NULL )
+	{
+		pList->pHead = pLink;
+		pList->pTail = pLink;
+		pLink->pPrev = NULL;
+		pLink->pNext = NULL;
+	}
+	else
+	{
+		pLink->pNext = NULL;
+		pList->pTail->pNext = pLink;
+		pLink->pPrev = pList->pTail;
+		pList->pTail = pLink;
+	}
+	pList->nItems++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_ListMatrixDelCube( Fxu_Matrix * p, Fxu_Cube * pLink )
+{
+	Fxu_ListCube * pList = &p->lCubes;
+	if ( pList->pHead == pLink )
+		 pList->pHead = pLink->pNext;
+	if ( pList->pTail == pLink )
+		 pList->pTail = pLink->pPrev;
+	if ( pLink->pPrev )
+		 pLink->pPrev->pNext = pLink->pNext;
+	if ( pLink->pNext )
+		 pLink->pNext->pPrev = pLink->pPrev;
+	pList->nItems--;
+}
+
+
+// matrix -> single
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_ListMatrixAddSingle( Fxu_Matrix * p, Fxu_Single * pLink )
+{
+	Fxu_ListSingle * pList = &p->lSingles;
+	if ( pList->pHead == NULL )
+	{
+		pList->pHead = pLink;
+		pList->pTail = pLink;
+		pLink->pPrev = NULL;
+		pLink->pNext = NULL;
+	}
+	else
+	{
+		pLink->pNext = NULL;
+		pList->pTail->pNext = pLink;
+		pLink->pPrev = pList->pTail;
+		pList->pTail = pLink;
+	}
+	pList->nItems++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_ListMatrixDelSingle( Fxu_Matrix * p, Fxu_Single * pLink )
+{
+	Fxu_ListSingle * pList = &p->lSingles;
+	if ( pList->pHead == pLink )
+		 pList->pHead = pLink->pNext;
+	if ( pList->pTail == pLink )
+		 pList->pTail = pLink->pPrev;
+	if ( pLink->pPrev )
+		 pLink->pPrev->pNext = pLink->pNext;
+	if ( pLink->pNext )
+		 pLink->pNext->pPrev = pLink->pPrev;
+	pList->nItems--;
+}
+
+
+// table -> divisor
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_ListTableAddDivisor( Fxu_Matrix * p, Fxu_Double * pLink ) 
+{
+	Fxu_ListDouble * pList = &(p->pTable[pLink->Key]);
+	if ( pList->pHead == NULL )
+	{
+		pList->pHead = pLink;
+		pList->pTail = pLink;
+		pLink->pPrev = NULL;
+		pLink->pNext = NULL;
+	}
+	else
+	{
+		pLink->pNext = NULL;
+		pList->pTail->pNext = pLink;
+		pLink->pPrev = pList->pTail;
+		pList->pTail = pLink;
+	}
+	pList->nItems++;
+    p->nDivs++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_ListTableDelDivisor( Fxu_Matrix * p, Fxu_Double * pLink ) 
+{
+	Fxu_ListDouble * pList = &(p->pTable[pLink->Key]);
+	if ( pList->pHead == pLink )
+		 pList->pHead = pLink->pNext;
+	if ( pList->pTail == pLink )
+		 pList->pTail = pLink->pPrev;
+	if ( pLink->pPrev )
+		 pLink->pPrev->pNext = pLink->pNext;
+	if ( pLink->pNext )
+		 pLink->pNext->pPrev = pLink->pPrev;
+	pList->nItems--;
+    p->nDivs--;
+}
+
+
+// cube -> literal 
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_ListCubeAddLiteral( Fxu_Cube * pCube, Fxu_Lit * pLink )
+{
+	Fxu_ListLit * pList = &(pCube->lLits);
+	if ( pList->pHead == NULL )
+	{
+		pList->pHead = pLink;
+		pList->pTail = pLink;
+		pLink->pHPrev = NULL;
+		pLink->pHNext = NULL;
+	}
+	else
+	{
+		pLink->pHNext = NULL;
+		pList->pTail->pHNext = pLink;
+		pLink->pHPrev = pList->pTail;
+		pList->pTail = pLink;
+	}
+	pList->nItems++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_ListCubeDelLiteral( Fxu_Cube * pCube, Fxu_Lit * pLink )
+{
+	Fxu_ListLit * pList = &(pCube->lLits);
+	if ( pList->pHead == pLink )
+		 pList->pHead = pLink->pHNext;
+	if ( pList->pTail == pLink )
+		 pList->pTail = pLink->pHPrev;
+	if ( pLink->pHPrev )
+		 pLink->pHPrev->pHNext = pLink->pHNext;
+	if ( pLink->pHNext )
+		 pLink->pHNext->pHPrev = pLink->pHPrev;
+	pList->nItems--;
+}
+
+
+// var -> literal
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_ListVarAddLiteral( Fxu_Var * pVar, Fxu_Lit * pLink )
+{
+	Fxu_ListLit * pList = &(pVar->lLits);
+	if ( pList->pHead == NULL )
+	{
+		pList->pHead = pLink;
+		pList->pTail = pLink;
+		pLink->pVPrev = NULL;
+		pLink->pVNext = NULL;
+	}
+	else
+	{
+		pLink->pVNext = NULL;
+		pList->pTail->pVNext = pLink;
+		pLink->pVPrev = pList->pTail;
+		pList->pTail = pLink;
+	}
+	pList->nItems++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_ListVarDelLiteral( Fxu_Var * pVar, Fxu_Lit * pLink )
+{
+	Fxu_ListLit * pList = &(pVar->lLits);
+	if ( pList->pHead == pLink )
+		 pList->pHead = pLink->pVNext;
+	if ( pList->pTail == pLink )
+		 pList->pTail = pLink->pVPrev;
+	if ( pLink->pVPrev )
+		 pLink->pVPrev->pVNext = pLink->pVNext;
+	if ( pLink->pVNext )
+		 pLink->pVNext->pVPrev = pLink->pVPrev;
+	pList->nItems--;
+}
+
+
+
+// divisor -> pair
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_ListDoubleAddPairLast( Fxu_Double * pDiv, Fxu_Pair * pLink )
+{
+	Fxu_ListPair * pList = &pDiv->lPairs;
+	if ( pList->pHead == NULL )
+	{
+		pList->pHead = pLink;
+		pList->pTail = pLink;
+		pLink->pDPrev = NULL;
+		pLink->pDNext = NULL;
+	}
+	else
+	{
+		pLink->pDNext = NULL;
+		pList->pTail->pDNext = pLink;
+		pLink->pDPrev = pList->pTail;
+		pList->pTail = pLink;
+	}
+	pList->nItems++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_ListDoubleAddPairFirst( Fxu_Double * pDiv, Fxu_Pair * pLink )
+{
+	Fxu_ListPair * pList = &pDiv->lPairs;
+	if ( pList->pHead == NULL )
+	{
+		pList->pHead = pLink;
+		pList->pTail = pLink;
+		pLink->pDPrev = NULL;
+		pLink->pDNext = NULL;
+	}
+	else
+	{
+		pLink->pDPrev = NULL;
+		pList->pHead->pDPrev = pLink;
+		pLink->pDNext = pList->pHead;
+		pList->pHead = pLink;
+	}
+	pList->nItems++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the entry in the middle of the list after the spot.]
+
+  Description [Assumes that spot points to the link, after which the given
+  link should be added. Spot cannot be NULL or the tail of the list.
+  Therefore, the head and the tail of the list are not changed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_ListDoubleAddPairMiddle( Fxu_Double * pDiv, Fxu_Pair * pSpot, Fxu_Pair * pLink )
+{
+	Fxu_ListPair * pList = &pDiv->lPairs;
+	assert( pSpot );
+	assert( pSpot != pList->pTail );
+	pLink->pDPrev = pSpot;
+	pLink->pDNext = pSpot->pDNext;
+	pLink->pDPrev->pDNext = pLink;
+	pLink->pDNext->pDPrev = pLink;
+	pList->nItems++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_ListDoubleDelPair( Fxu_Double * pDiv, Fxu_Pair * pLink )
+{
+	Fxu_ListPair * pList = &pDiv->lPairs;
+	if ( pList->pHead == pLink )
+		 pList->pHead = pLink->pDNext;
+	if ( pList->pTail == pLink )
+		 pList->pTail = pLink->pDPrev;
+	if ( pLink->pDPrev )
+		 pLink->pDPrev->pDNext = pLink->pDNext;
+	if ( pLink->pDNext )
+		 pLink->pDNext->pDPrev = pLink->pDPrev;
+	pList->nItems--;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_ListDoubleAddPairPlace( Fxu_Double * pDiv, Fxu_Pair * pPair, Fxu_Pair * pPairSpot )
+{
+	printf( "Fxu_ListDoubleAddPairPlace() is called!\n" );
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fxu/fxuMatrix.c b/abc-build/src/opt/fxu/fxuMatrix.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fxu/fxuMatrix.c
@@ -0,0 +1,377 @@
+/**CFile****************************************************************
+
+  FileName    [fxuMatrix.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Procedures to manipulate the sparse matrix.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: fxuMatrix.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fxu_Matrix * Fxu_MatrixAllocate()
+{
+	Fxu_Matrix * p;
+	p = ABC_ALLOC( Fxu_Matrix, 1 );
+	memset( p, 0, sizeof(Fxu_Matrix) );
+	p->nTableSize = Abc_PrimeCudd(10000);
+	p->pTable = ABC_ALLOC( Fxu_ListDouble, p->nTableSize );
+	memset( p->pTable, 0, sizeof(Fxu_ListDouble) * p->nTableSize );
+#ifndef USE_SYSTEM_MEMORY_MANAGEMENT
+    {
+        // get the largest size in bytes for the following structures:
+        // Fxu_Cube, Fxu_Var, Fxu_Lit, Fxu_Pair, Fxu_Double, Fxu_Single
+        // (currently, Fxu_Var, Fxu_Pair, Fxu_Double take 10 machine words)
+        int nSizeMax, nSizeCur;
+        nSizeMax = -1;
+        nSizeCur = sizeof(Fxu_Cube);
+        if ( nSizeMax < nSizeCur )
+             nSizeMax = nSizeCur;
+        nSizeCur = sizeof(Fxu_Var);
+        if ( nSizeMax < nSizeCur )
+             nSizeMax = nSizeCur;
+        nSizeCur = sizeof(Fxu_Lit);
+        if ( nSizeMax < nSizeCur )
+             nSizeMax = nSizeCur;
+        nSizeCur = sizeof(Fxu_Pair);
+        if ( nSizeMax < nSizeCur )
+             nSizeMax = nSizeCur;
+        nSizeCur = sizeof(Fxu_Double);
+        if ( nSizeMax < nSizeCur )
+             nSizeMax = nSizeCur;
+        nSizeCur = sizeof(Fxu_Single);
+        if ( nSizeMax < nSizeCur )
+             nSizeMax = nSizeCur;
+    	p->pMemMan  = Extra_MmFixedStart( nSizeMax ); 
+    }
+#endif
+	p->pHeapDouble = Fxu_HeapDoubleStart();
+	p->pHeapSingle = Fxu_HeapSingleStart();
+    p->vPairs = Vec_PtrAlloc( 100 );
+	return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_MatrixDelete( Fxu_Matrix * p )
+{
+	Fxu_HeapDoubleCheck( p->pHeapDouble );
+	Fxu_HeapDoubleStop( p->pHeapDouble );
+    Fxu_HeapSingleStop( p->pHeapSingle );
+
+	// delete other things
+#ifdef USE_SYSTEM_MEMORY_MANAGEMENT
+	// this code is not needed when the custom memory manager is used
+    {
+	    Fxu_Cube * pCube, * pCube2;
+	    Fxu_Var * pVar, * pVar2;
+	    Fxu_Lit * pLit, * pLit2;
+	    Fxu_Double * pDiv, * pDiv2;
+	    Fxu_Single * pSingle, * pSingle2;
+	    Fxu_Pair * pPair, * pPair2;
+        int i;
+	    // delete the divisors
+	    Fxu_MatrixForEachDoubleSafe( p, pDiv, pDiv2, i )
+	    {
+		    Fxu_DoubleForEachPairSafe( pDiv, pPair, pPair2 )
+			    MEM_FREE_FXU( p, Fxu_Pair, 1, pPair );
+   		    MEM_FREE_FXU( p, Fxu_Double, 1, pDiv );
+	    }
+	    Fxu_MatrixForEachSingleSafe( p, pSingle, pSingle2 )
+   		    MEM_FREE_FXU( p, Fxu_Single, 1, pSingle );
+	    // delete the entries
+	    Fxu_MatrixForEachCube( p, pCube )
+		    Fxu_CubeForEachLiteralSafe( pCube, pLit, pLit2 )
+			    MEM_FREE_FXU( p, Fxu_Lit, 1, pLit );
+	    // delete the cubes
+	    Fxu_MatrixForEachCubeSafe( p, pCube, pCube2 )
+		    MEM_FREE_FXU( p, Fxu_Cube, 1, pCube );
+	    // delete the vars
+	    Fxu_MatrixForEachVariableSafe( p, pVar, pVar2 )
+		    MEM_FREE_FXU( p, Fxu_Var, 1, pVar );
+    }
+#else
+	Extra_MmFixedStop( p->pMemMan );
+#endif
+
+    Vec_PtrFree( p->vPairs );
+	ABC_FREE( p->pppPairs );
+	ABC_FREE( p->ppPairs );
+//    ABC_FREE( p->pPairsTemp );
+	ABC_FREE( p->pTable );
+	ABC_FREE( p->ppVars );
+	ABC_FREE( p );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Adds a variable to the matrix.]
+
+  Description [This procedure always adds variables at the end of the matrix.
+  It assigns the var's node and number. It adds the var to the linked list of
+  all variables and to the table of all nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fxu_Var * Fxu_MatrixAddVar( Fxu_Matrix * p )
+{
+	Fxu_Var * pVar;
+	pVar = MEM_ALLOC_FXU( p, Fxu_Var, 1 );
+	memset( pVar, 0, sizeof(Fxu_Var) );
+	pVar->iVar = p->lVars.nItems;
+    p->ppVars[pVar->iVar] = pVar;
+	Fxu_ListMatrixAddVariable( p, pVar );
+	return pVar;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds a literal to the matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fxu_Cube * Fxu_MatrixAddCube( Fxu_Matrix * p, Fxu_Var * pVar, int iCube )
+{
+	Fxu_Cube * pCube;
+	pCube = MEM_ALLOC_FXU( p, Fxu_Cube, 1 );
+	memset( pCube, 0, sizeof(Fxu_Cube) );
+	pCube->pVar  = pVar;
+	pCube->iCube = iCube;
+	Fxu_ListMatrixAddCube( p, pCube );
+	return pCube;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds a literal to the matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_MatrixAddLiteral( Fxu_Matrix * p, Fxu_Cube * pCube, Fxu_Var * pVar )
+{
+	Fxu_Lit * pLit;
+	pLit = MEM_ALLOC_FXU( p, Fxu_Lit, 1 );
+	memset( pLit, 0, sizeof(Fxu_Lit) );
+	// insert the literal into two linked lists
+	Fxu_ListCubeAddLiteral( pCube, pLit );
+	Fxu_ListVarAddLiteral( pVar, pLit );
+	// set the back pointers
+	pLit->pCube = pCube;
+	pLit->pVar  = pVar;
+	pLit->iCube = pCube->iCube;
+	pLit->iVar  = pVar->iVar;
+	// increment the literal counter
+	p->nEntries++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the divisor from the matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_MatrixDelDivisor( Fxu_Matrix * p, Fxu_Double * pDiv )
+{
+	// delete divisor from the table
+	Fxu_ListTableDelDivisor( p, pDiv );
+	// recycle the divisor
+	MEM_FREE_FXU( p, Fxu_Double, 1, pDiv );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the literal fromthe matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_MatrixDelLiteral( Fxu_Matrix * p, Fxu_Lit * pLit )
+{
+    // delete the literal
+	Fxu_ListCubeDelLiteral( pLit->pCube, pLit );
+	Fxu_ListVarDelLiteral( pLit->pVar, pLit );
+	MEM_FREE_FXU( p, Fxu_Lit, 1, pLit );
+	// increment the literal counter
+	p->nEntries--;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates and adds a single cube divisor.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_MatrixAddSingle( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, int Weight )
+{
+    Fxu_Single * pSingle;
+    assert( pVar1->iVar < pVar2->iVar );
+	pSingle = MEM_ALLOC_FXU( p, Fxu_Single, 1 );
+	memset( pSingle, 0, sizeof(Fxu_Single) );
+    pSingle->Num = p->lSingles.nItems;
+    pSingle->Weight = Weight;
+    pSingle->HNum = 0;
+    pSingle->pVar1 = pVar1;
+    pSingle->pVar2 = pVar2;
+    Fxu_ListMatrixAddSingle( p, pSingle );
+    // add to the heap
+    Fxu_HeapSingleInsert( p->pHeapSingle, pSingle );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_MatrixAddDivisor( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 )
+{
+	Fxu_Pair * pPair;
+	Fxu_Double * pDiv;
+    int nBase, nLits1, nLits2;
+    int fFound;
+	unsigned Key;
+
+    // canonicize the pair
+    Fxu_PairCanonicize( &pCube1, &pCube2 );
+    // compute the hash key
+    Key = Fxu_PairHashKey( p, pCube1, pCube2, &nBase, &nLits1, &nLits2 );
+
+    // create the cube pair
+    pPair = Fxu_PairAlloc( p, pCube1, pCube2 );
+    pPair->nBase  = nBase;
+    pPair->nLits1 = nLits1;
+    pPair->nLits2 = nLits2;
+
+    // check if the divisor for this pair already exists
+    fFound = 0;
+    Key %= p->nTableSize;
+	Fxu_TableForEachDouble( p, Key, pDiv )
+    {
+		if ( Fxu_PairCompare( pPair, pDiv->lPairs.pTail ) ) // they are equal
+        {
+            fFound = 1;
+            break;
+        }
+    }
+
+    if ( !fFound )
+    {   // create the new divisor
+	    pDiv = MEM_ALLOC_FXU( p, Fxu_Double, 1 );
+	    memset( pDiv, 0, sizeof(Fxu_Double) );
+	    pDiv->Key = Key;
+	    // set the number of this divisor
+	    pDiv->Num = p->nDivsTotal++; // p->nDivs;
+	    // insert the divisor in the table
+	    Fxu_ListTableAddDivisor( p, pDiv );
+	    // set the initial cost of the divisor
+	    pDiv->Weight -= pPair->nLits1 + pPair->nLits2;
+    }
+
+	// link the pair to the cubes
+	Fxu_PairAdd( pPair );
+	// connect the pair and the divisor
+	pPair->pDiv = pDiv;
+	Fxu_ListDoubleAddPairLast( pDiv, pPair );	
+    // update the max number of pairs in a divisor
+//    if ( p->nPairsMax < pDiv->lPairs.nItems )
+//        p->nPairsMax = pDiv->lPairs.nItems;
+	// update the divisor's weight
+	pDiv->Weight += pPair->nLits1 + pPair->nLits2 - 1 + pPair->nBase;
+    if ( fFound ) // update the divisor in the heap
+        Fxu_HeapDoubleUpdate( p->pHeapDouble, pDiv );
+    else  // add the new divisor to the heap
+        Fxu_HeapDoubleInsert( p->pHeapDouble, pDiv );
+}
+
+/*
+    {
+        int piVarsC1[100], piVarsC2[100], nVarsC1, nVarsC2;
+        Fxu_Double * pDivCur;
+        Fxu_MatrixGetDoubleVars( p, pDiv, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 );
+        pDivCur = Fxu_MatrixFindDouble( p, piVarsC1, piVarsC2, nVarsC1, nVarsC2 );
+        assert( pDivCur == pDiv );
+    }
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fxu/fxuPair.c b/abc-build/src/opt/fxu/fxuPair.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fxu/fxuPair.c
@@ -0,0 +1,560 @@
+/**CFile****************************************************************
+
+  FileName    [fxuPair.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Operations on cube pairs.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: fxuPair.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define MAX_PRIMES      304
+
+static int s_Primes[MAX_PRIMES] =
+{
+	2, 3, 5, 7, 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, 557, 563, 569, 571, 577, 587, 593, 
+	599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 
+	661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 
+	751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 
+	829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 
+	919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 
+	1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 
+	1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 
+	1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 
+	1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 
+	1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 
+	1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 
+	1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 
+	1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 
+	1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 
+	1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 
+	1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 
+	1993, 1997, 1999, 2003 
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Find the canonical permutation of two cubes in the pair.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_PairCanonicize( Fxu_Cube ** ppCube1, Fxu_Cube ** ppCube2 )
+{
+	Fxu_Lit * pLit1, * pLit2;
+	Fxu_Cube * pCubeTemp;
+
+	// walk through the cubes to determine 
+	// the one that has higher first variable
+	pLit1 = (*ppCube1)->lLits.pHead;
+	pLit2 = (*ppCube2)->lLits.pHead;
+	while ( 1 )
+	{
+		if ( pLit1->iVar == pLit2->iVar )
+		{
+			pLit1 = pLit1->pHNext;
+			pLit2 = pLit2->pHNext;
+			continue;
+		}
+		assert( pLit1 && pLit2 ); // this is true if the covers are SCC-free
+		if ( pLit1->iVar > pLit2->iVar )
+		{ // swap the cubes
+			pCubeTemp = *ppCube1;
+			*ppCube1  = *ppCube2;
+			*ppCube2  = pCubeTemp;
+		}
+		break;
+	}
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the canonical permutation of two cubes in the pair.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_PairCanonicize2( Fxu_Cube ** ppCube1, Fxu_Cube ** ppCube2 )
+{
+	Fxu_Cube * pCubeTemp;
+    // canonicize the pair by ordering the cubes
+	if ( (*ppCube1)->iCube > (*ppCube2)->iCube )
+	{ // swap the cubes
+		pCubeTemp = *ppCube1;
+		*ppCube1  = *ppCube2;
+		*ppCube2  = pCubeTemp;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Fxu_PairHashKeyArray( Fxu_Matrix * p, int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 )
+{
+	int Offset1 = 100, Offset2 = 200, i;
+	unsigned Key;
+	// compute the hash key
+	Key = 0;
+    for ( i = 0; i < nVarsC1; i++ )
+    	Key ^= s_Primes[Offset1+i] * piVarsC1[i];
+    for ( i = 0; i < nVarsC2; i++ )
+    	Key ^= s_Primes[Offset2+i] * piVarsC2[i];
+	return Key;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the hash key of the divisor represented by the pair of cubes.]
+
+  Description [Goes through the variables in both cubes. Skips the identical
+  ones (this corresponds to making the cubes cube-free). Computes the hash 
+  value of the cubes. Assigns the number of literals in the base and in the 
+  cubes without base.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Fxu_PairHashKey( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, 
+                         int * pnBase, int * pnLits1, int * pnLits2 )
+{
+	int Offset1 = 100, Offset2 = 200;
+    int nBase, nLits1, nLits2;
+	Fxu_Lit * pLit1, * pLit2;
+	unsigned Key;
+
+	// compute the hash key
+	Key    = 0;
+	nLits1 = 0;
+	nLits2 = 0;
+	nBase  = 0;
+	pLit1  = pCube1->lLits.pHead;
+	pLit2  = pCube2->lLits.pHead;
+	while ( 1 )
+	{
+		if ( pLit1 && pLit2 )
+		{
+			if ( pLit1->iVar == pLit2->iVar )
+			{ // ensure cube-free
+				pLit1 = pLit1->pHNext;
+				pLit2 = pLit2->pHNext;
+				// add this literal to the base
+				nBase++;
+			}
+			else if ( pLit1->iVar < pLit2->iVar )
+			{
+				Key  ^= s_Primes[Offset1+nLits1] * pLit1->iVar;
+				pLit1 = pLit1->pHNext;
+				nLits1++;
+			}
+			else
+			{
+				Key  ^= s_Primes[Offset2+nLits2] * pLit2->iVar;
+				pLit2 = pLit2->pHNext;
+				nLits2++;
+			}
+		}
+		else if ( pLit1 && !pLit2 )
+		{
+			Key  ^= s_Primes[Offset1+nLits1] * pLit1->iVar;
+			pLit1 = pLit1->pHNext;
+			nLits1++;
+		}
+		else if ( !pLit1 && pLit2 )
+		{
+			Key  ^= s_Primes[Offset2+nLits2] * pLit2->iVar;
+			pLit2 = pLit2->pHNext;
+			nLits2++;
+		}
+		else
+			break;
+	}
+    *pnBase  = nBase;
+    *pnLits1 = nLits1;
+    *pnLits2 = nLits2;
+	return Key;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the two pairs.]
+
+  Description [Returns 1 if the divisors represented by these pairs
+  are equal.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fxu_PairCompare( Fxu_Pair * pPair1, Fxu_Pair * pPair2 )
+{
+	Fxu_Lit * pD1C1, * pD1C2;
+	Fxu_Lit * pD2C1, * pD2C2;
+	int TopVar1, TopVar2;
+	int Code;
+
+	if ( pPair1->nLits1 != pPair2->nLits1 )
+		return 0;
+	if ( pPair1->nLits2 != pPair2->nLits2 )
+		return 0;
+
+	pD1C1 = pPair1->pCube1->lLits.pHead;
+	pD1C2 = pPair1->pCube2->lLits.pHead;
+
+	pD2C1 = pPair2->pCube1->lLits.pHead;
+	pD2C2 = pPair2->pCube2->lLits.pHead;
+
+	Code  = pD1C1? 8: 0;
+	Code |= pD1C2? 4: 0;
+	Code |= pD2C1? 2: 0;
+	Code |= pD2C2? 1: 0;
+	assert( Code == 15 );
+
+	while ( 1 )
+	{
+		switch ( Code )
+		{
+		case 0:  // -- --      NULL   NULL     NULL   NULL 
+			return 1;
+		case 1:  // -- -1      NULL   NULL     NULL   pD2C2
+			return 0;
+		case 2:  // -- 1-      NULL   NULL     pD2C1  NULL 
+			return 0;
+		case 3:  // -- 11      NULL   NULL     pD2C1  pD2C2
+			if ( pD2C1->iVar != pD2C2->iVar )
+				return 0;
+			pD2C1 = pD2C1->pHNext;
+			pD2C2 = pD2C2->pHNext;
+			break;
+		case 4:  // -1 --      NULL   pD1C2    NULL   NULL 
+			return 0;
+		case 5:  // -1 -1      NULL   pD1C2    NULL   pD2C2
+			if ( pD1C2->iVar != pD2C2->iVar )
+				return 0;
+			pD1C2 = pD1C2->pHNext;
+			pD2C2 = pD2C2->pHNext;
+			break;
+		case 6:  // -1 1-      NULL   pD1C2    pD2C1  NULL 
+			return 0;
+		case 7:  // -1 11      NULL   pD1C2    pD2C1  pD2C2
+			TopVar2 = Fxu_Min( pD2C1->iVar, pD2C2->iVar );
+			if ( TopVar2 == pD1C2->iVar )
+			{
+				if ( pD2C1->iVar <= pD2C2->iVar )
+					return 0;
+				pD1C2 = pD1C2->pHNext;
+				pD2C2 = pD2C2->pHNext;
+			}
+			else if ( TopVar2 < pD1C2->iVar )
+			{
+				if ( pD2C1->iVar != pD2C2->iVar )
+					return 0;
+				pD2C1 = pD2C1->pHNext;
+				pD2C2 = pD2C2->pHNext;
+			}
+			else
+				return 0;
+			break;
+		case 8:  // 1- --      pD1C1  NULL     NULL   NULL 
+			return 0;
+		case 9:  // 1- -1      pD1C1  NULL     NULL   pD2C2
+			return 0;
+		case 10: // 1- 1-      pD1C1  NULL     pD2C1  NULL 
+			if ( pD1C1->iVar != pD2C1->iVar )
+				return 0;
+			pD1C1 = pD1C1->pHNext;
+			pD2C1 = pD2C1->pHNext;
+			break;
+		case 11: // 1- 11      pD1C1  NULL     pD2C1  pD2C2
+			TopVar2 = Fxu_Min( pD2C1->iVar, pD2C2->iVar );
+			if ( TopVar2 == pD1C1->iVar )
+			{
+				if ( pD2C1->iVar >= pD2C2->iVar )
+					return 0;
+				pD1C1 = pD1C1->pHNext;
+				pD2C1 = pD2C1->pHNext;
+			}
+			else if ( TopVar2 < pD1C1->iVar )
+			{
+				if ( pD2C1->iVar != pD2C2->iVar )
+					return 0;
+				pD2C1 = pD2C1->pHNext;
+				pD2C2 = pD2C2->pHNext;
+			}
+			else
+				return 0;
+			break;
+		case 12: // 11 --      pD1C1  pD1C2    NULL   NULL 
+			if ( pD1C1->iVar != pD1C2->iVar )
+				return 0;
+			pD1C1 = pD1C1->pHNext;
+			pD1C2 = pD1C2->pHNext;
+			break;
+		case 13: // 11 -1      pD1C1  pD1C2    NULL   pD2C2
+			TopVar1 = Fxu_Min( pD1C1->iVar, pD1C2->iVar );
+			if ( TopVar1 == pD2C2->iVar )
+			{
+				if ( pD1C1->iVar <= pD1C2->iVar )
+					return 0;
+				pD1C2 = pD1C2->pHNext;
+				pD2C2 = pD2C2->pHNext;
+			}
+			else if ( TopVar1 < pD2C2->iVar )
+			{
+				if ( pD1C1->iVar != pD1C2->iVar )
+					return 0;
+				pD1C1 = pD1C1->pHNext;
+				pD1C2 = pD1C2->pHNext;
+			}
+			else
+				return 0;
+			break;
+		case 14: // 11 1-      pD1C1  pD1C2    pD2C1  NULL 
+			TopVar1 = Fxu_Min( pD1C1->iVar, pD1C2->iVar );
+			if ( TopVar1 == pD2C1->iVar )
+			{
+				if ( pD1C1->iVar >= pD1C2->iVar )
+					return 0;
+				pD1C1 = pD1C1->pHNext;
+				pD2C1 = pD2C1->pHNext;
+			}
+			else if ( TopVar1 < pD2C1->iVar )
+			{
+				if ( pD1C1->iVar != pD1C2->iVar )
+					return 0;
+				pD1C1 = pD1C1->pHNext;
+				pD1C2 = pD1C2->pHNext;
+			}
+			else
+				return 0;
+			break;
+		case 15: // 11 11      pD1C1  pD1C2    pD2C1  pD2C2
+			TopVar1 = Fxu_Min( pD1C1->iVar, pD1C2->iVar );
+			TopVar2 = Fxu_Min( pD2C1->iVar, pD2C2->iVar );
+			if ( TopVar1 == TopVar2 )
+			{
+				if ( pD1C1->iVar == pD1C2->iVar )
+				{
+					if ( pD2C1->iVar != pD2C2->iVar )
+						return 0;
+					pD1C1 = pD1C1->pHNext;
+					pD1C2 = pD1C2->pHNext;
+					pD2C1 = pD2C1->pHNext;
+					pD2C2 = pD2C2->pHNext;
+				}
+				else
+				{
+					if ( pD2C1->iVar == pD2C2->iVar )
+						return 0;
+					if ( pD1C1->iVar < pD1C2->iVar )
+					{
+						if ( pD2C1->iVar > pD2C2->iVar )
+							return 0;
+						pD1C1 = pD1C1->pHNext;
+						pD2C1 = pD2C1->pHNext;
+					}
+					else
+					{
+						if ( pD2C1->iVar < pD2C2->iVar )
+							return 0;
+						pD1C2 = pD1C2->pHNext;
+						pD2C2 = pD2C2->pHNext;
+					}
+				}
+			}
+			else if ( TopVar1 < TopVar2 )
+			{
+				if ( pD1C1->iVar != pD1C2->iVar )
+					return 0;
+				pD1C1 = pD1C1->pHNext;
+				pD1C2 = pD1C2->pHNext;
+			}
+			else 
+			{
+				if ( pD2C1->iVar != pD2C2->iVar )
+					return 0;
+				pD2C1 = pD2C1->pHNext;
+				pD2C2 = pD2C2->pHNext;
+			}
+			break;
+		default:
+			assert( 0 );
+			break;
+		}
+
+		Code  = pD1C1? 8: 0;
+		Code |= pD1C2? 4: 0;
+		Code |= pD2C1? 2: 0;
+		Code |= pD2C2? 1: 0;
+	}
+	return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the storage for cubes pairs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_PairAllocStorage( Fxu_Var * pVar, int nCubes )
+{
+    int k;
+//    assert( pVar->nCubes == 0 );
+    pVar->nCubes  = nCubes;
+	// allocate memory for all the pairs
+	pVar->ppPairs    = ABC_ALLOC( Fxu_Pair **, nCubes );
+	pVar->ppPairs[0] = ABC_ALLOC( Fxu_Pair *,  nCubes * nCubes );
+    memset( pVar->ppPairs[0], 0, sizeof(Fxu_Pair *) * nCubes * nCubes );
+    for ( k = 1; k < nCubes; k++ )
+        pVar->ppPairs[k] = pVar->ppPairs[k-1] + nCubes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Clears all pairs associated with this cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_PairClearStorage( Fxu_Cube * pCube )
+{
+    Fxu_Var * pVar;
+	int i;
+    pVar = pCube->pVar;
+	for ( i = 0; i < pVar->nCubes; i++ )
+	{
+		pVar->ppPairs[pCube->iCube][i] = NULL;
+		pVar->ppPairs[i][pCube->iCube] = NULL;
+	}
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Clears all pairs associated with this cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_PairFreeStorage( Fxu_Var * pVar )
+{
+    if ( pVar->ppPairs )
+    {
+        ABC_FREE( pVar->ppPairs[0] );
+        ABC_FREE( pVar->ppPairs );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the pair to storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fxu_Pair * Fxu_PairAlloc( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 )
+{
+    Fxu_Pair * pPair;
+   	assert( pCube1->pVar == pCube2->pVar );
+	pPair = MEM_ALLOC_FXU( p, Fxu_Pair, 1 );
+	memset( pPair, 0, sizeof(Fxu_Pair) );
+	pPair->pCube1 = pCube1;
+	pPair->pCube2 = pCube2;
+	pPair->iCube1 = pCube1->iCube;
+	pPair->iCube2 = pCube2->iCube;
+    return pPair;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the pair to storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_PairAdd( Fxu_Pair * pPair )
+{
+    Fxu_Var * pVar;
+
+    pVar = pPair->pCube1->pVar;
+	assert( pVar == pPair->pCube2->pVar );
+
+	pVar->ppPairs[pPair->iCube1][pPair->iCube2] = pPair;
+	pVar->ppPairs[pPair->iCube2][pPair->iCube1] = pPair;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fxu/fxuPrint.c b/abc-build/src/opt/fxu/fxuPrint.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fxu/fxuPrint.c
@@ -0,0 +1,202 @@
+/**CFile****************************************************************
+
+  FileName    [fxuPrint.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Various printing procedures.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: fxuPrint.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_MatrixPrint( FILE * pFile, Fxu_Matrix * p )
+{
+	Fxu_Var * pVar;
+	Fxu_Cube * pCube;
+	Fxu_Double * pDiv;
+    Fxu_Single * pSingle;
+	Fxu_Lit * pLit;
+	Fxu_Pair * pPair;
+	int i, LastNum;
+	int fStdout;
+
+	fStdout = 1;
+	if ( pFile == NULL )
+	{
+		pFile = fopen( "matrix.txt", "w" );
+		fStdout = 0;
+	}
+
+	fprintf( pFile, "Matrix has %d vars, %d cubes, %d literals, %d divisors.\n", 
+		p->lVars.nItems, p->lCubes.nItems, p->nEntries, p->nDivs );
+	fprintf( pFile, "Divisors selected so far: single = %d, double = %d.\n", 
+		p->nDivs1, p->nDivs2 );
+	fprintf( pFile, "\n" );
+
+	// print the numbers on top of the matrix
+	for ( i = 0; i < 12; i++ )
+		fprintf( pFile, " " );
+	Fxu_MatrixForEachVariable( p, pVar )
+		fprintf( pFile, "%d", pVar->iVar % 10 );
+	fprintf( pFile, "\n" );
+
+	// print the rows
+	Fxu_MatrixForEachCube( p, pCube )
+	{
+		fprintf( pFile, "%4d", pCube->iCube );
+		fprintf( pFile, "  " );
+		fprintf( pFile, "%4d", pCube->pVar->iVar );
+		fprintf( pFile, "  " );
+
+		// print the literals
+		LastNum = -1;
+		Fxu_CubeForEachLiteral( pCube, pLit )
+		{
+			for ( i = LastNum + 1; i < pLit->pVar->iVar; i++ )
+				fprintf( pFile, "." );
+			fprintf( pFile, "1" );
+			LastNum = i;
+		}
+		for ( i = LastNum + 1; i < p->lVars.nItems; i++ )
+			fprintf( pFile, "." );
+		fprintf( pFile, "\n" );
+	}
+	fprintf( pFile, "\n" );
+
+	// print the double-cube divisors
+	fprintf( pFile, "The double divisors are:\n" );
+	Fxu_MatrixForEachDouble( p, pDiv, i )
+	{
+		fprintf( pFile, "Divisor #%3d (lit=%d,%d) (w=%2d):  ", 
+			pDiv->Num, pDiv->lPairs.pHead->nLits1, 
+            pDiv->lPairs.pHead->nLits2, pDiv->Weight );
+		Fxu_DoubleForEachPair( pDiv, pPair )
+			fprintf( pFile, " <%d, %d> (b=%d)", 
+				pPair->pCube1->iCube, pPair->pCube2->iCube, pPair->nBase );
+		fprintf( pFile, "\n" );
+	}
+    fprintf( pFile, "\n" );
+
+	// print the divisors associated with each cube
+	fprintf( pFile, "The cubes are:\n" );
+	Fxu_MatrixForEachCube( p, pCube )
+	{
+		fprintf( pFile, "Cube #%3d: ", pCube->iCube );
+        if ( pCube->pVar->ppPairs )
+        {
+		    Fxu_CubeForEachPair( pCube, pPair, i )
+				fprintf( pFile, " <%d %d> (d=%d) (b=%d)", 
+					pPair->iCube1, pPair->iCube2, pPair->pDiv->Num, pPair->nBase );
+        }
+		fprintf( pFile, "\n" );
+	}
+    fprintf( pFile, "\n" );
+
+	// print the single-cube divisors
+	fprintf( pFile, "The single divisors are:\n" );
+	Fxu_MatrixForEachSingle( p, pSingle )
+	{
+		fprintf( pFile, "Single-cube divisor #%5d: Var1 = %4d. Var2 = %4d. Weight = %2d\n", 
+			pSingle->Num, pSingle->pVar1->iVar, pSingle->pVar2->iVar, pSingle->Weight );
+	}
+    fprintf( pFile, "\n" );
+
+/*
+    {
+        int Index;
+		fprintf( pFile, "Distribution of divisors in the hash table:\n" );
+        for ( Index = 0; Index < p->nTableSize; Index++ )
+            fprintf( pFile, " %d", p->pTable[Index].nItems );
+		fprintf( pFile, "\n" );
+    }
+*/
+	if ( !fStdout )
+		fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_MatrixPrintDivisorProfile( FILE * pFile, Fxu_Matrix * p )
+{
+    Fxu_Double * pDiv;
+    int WeightMax;
+    int * pProfile;
+    int Counter1; // the number of -1 weight
+    int CounterL; // the number of less than -1 weight
+    int i;
+
+    WeightMax = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble );
+    pProfile = ABC_ALLOC( int, (WeightMax + 1) );
+    memset( pProfile, 0, sizeof(int) * (WeightMax + 1) );
+
+    Counter1 = 0;
+    CounterL = 0;
+	Fxu_MatrixForEachDouble( p, pDiv, i )
+    {
+        assert( pDiv->Weight <= WeightMax );
+        if ( pDiv->Weight == -1 )
+            Counter1++;
+        else if ( pDiv->Weight < 0 )
+            CounterL++;
+        else
+            pProfile[ pDiv->Weight ]++;
+    }
+
+	fprintf( pFile, "The double divisors profile:\n" );
+	fprintf( pFile, "Weight  < -1 divisors = %6d\n", CounterL );
+	fprintf( pFile, "Weight    -1 divisors = %6d\n", Counter1 );
+    for ( i = 0; i <= WeightMax; i++ )
+        if ( pProfile[i] )
+	        fprintf( pFile, "Weight   %3d divisors = %6d\n", i, pProfile[i] );
+	fprintf( pFile, "End of divisor profile printout\n" );
+    ABC_FREE( pProfile );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fxu/fxuReduce.c b/abc-build/src/opt/fxu/fxuReduce.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fxu/fxuReduce.c
@@ -0,0 +1,213 @@
+/**CFile****************************************************************
+
+  FileName    [fxuReduce.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Procedures to reduce the number of considered cube pairs.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: fxuReduce.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "fxuInt.h"
+#include "fxu.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Fxu_CountPairDiffs( char * pCover, unsigned char pDiffs[] );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Precomputes the pairs to use for creating two-cube divisors.]
+
+  Description [This procedure takes the matrix with variables and cubes 
+  allocated (p), the original covers of the nodes (i-sets) and their number 
+  (ppCovers,nCovers). The maximum number of pairs to compute and the total 
+  number of pairs in existence. This procedure adds to the storage of
+  divisors exactly the given number of pairs (nPairsMax) while taking
+  first those pairs that have the smallest number of literals in their
+  cube-free form.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTotal, int nPairsMax )
+{
+    unsigned char * pnLitsDiff;   // storage for the counters of diff literals
+    int * pnPairCounters;         // the counters of pairs for each number of diff literals
+    Fxu_Cube * pCubeFirst, * pCubeLast;
+    Fxu_Cube * pCube1, * pCube2;
+    Fxu_Var * pVar;
+    int nCubes, nBitsMax, nSum;
+    int CutOffNum = -1, CutOffQuant = -1; // Suppress "might be used uninitialized"
+    int iPair, iQuant, k, c;
+//    abctime clk = Abc_Clock();
+    char * pSopCover;
+    int nFanins;
+
+    assert( nPairsMax < nPairsTotal );
+
+    // allocate storage for counter of diffs
+    pnLitsDiff = ABC_FALLOC( unsigned char, nPairsTotal );
+    // go through the covers and precompute the distances between the pairs
+    iPair    =  0;
+    nBitsMax = -1;
+    for ( c = 0; c < vCovers->nSize; c++ )
+        if ( (pSopCover = (char *)vCovers->pArray[c]) )
+        {
+            nFanins = Abc_SopGetVarNum(pSopCover);
+            // precompute the differences
+            Fxu_CountPairDiffs( pSopCover, pnLitsDiff + iPair );
+            // update the counter
+            nCubes = Abc_SopGetCubeNum( pSopCover );
+            iPair += nCubes * (nCubes - 1) / 2;
+            if ( nBitsMax < nFanins )
+                nBitsMax = nFanins;
+        }
+    assert( iPair == nPairsTotal );
+
+    // allocate storage for counters of cube pairs by difference
+    pnPairCounters = ABC_FALLOC( int, 2 * nBitsMax );
+    memset( pnPairCounters, 0, sizeof(int) * 2 * nBitsMax );
+    // count the number of different pairs
+    for ( k = 0; k < nPairsTotal; k++ )
+        pnPairCounters[ pnLitsDiff[k] ]++;
+    // determine what pairs to take starting from the lower
+    // so that there would be exactly pPairsMax pairs
+    if ( pnPairCounters[0] != 0 )
+    {
+        ABC_FREE( pnLitsDiff );
+        ABC_FREE( pnPairCounters );
+        printf( "The SOPs of the nodes contain duplicated cubes. Run \"bdd; sop\" before \"fx\".\n" );
+        return 0;
+    }
+    if ( pnPairCounters[1] != 0 )
+    {
+        ABC_FREE( pnLitsDiff );
+        ABC_FREE( pnPairCounters );
+        printf( "The SOPs of the nodes are not SCC-free. Run \"bdd; sop\" before \"fx\".\n" );
+        return 0;
+    }
+    assert( pnPairCounters[0] == 0 ); // otherwise, covers are not dup-free
+    assert( pnPairCounters[1] == 0 ); // otherwise, covers are not SCC-free
+    nSum = 0;
+    for ( k = 0; k < 2 * nBitsMax; k++ )
+    {
+        nSum += pnPairCounters[k];
+        if ( nSum >= nPairsMax )
+        {
+            CutOffNum   = k;
+            CutOffQuant = pnPairCounters[k] - (nSum - nPairsMax);
+            break;
+        }
+    }
+    ABC_FREE( pnPairCounters );
+
+    // set to 0 all the pairs above the cut-off number and quantity
+    iQuant = 0;
+    iPair  = 0;
+    for ( k = 0; k < nPairsTotal; k++ )
+        if ( pnLitsDiff[k] > CutOffNum ) 
+            pnLitsDiff[k] = 0;
+        else if ( pnLitsDiff[k] == CutOffNum )
+        {
+            if ( iQuant++ >= CutOffQuant )
+                pnLitsDiff[k] = 0;
+            else
+                iPair++;
+        }
+        else
+            iPair++;
+    assert( iPair == nPairsMax );
+
+    // collect the corresponding pairs and add the divisors
+    iPair = 0;
+    for ( c = 0; c < vCovers->nSize; c++ )
+        if ( (pSopCover = (char *)vCovers->pArray[c]) )
+        {
+            // get the var
+            pVar = p->ppVars[2*c+1];
+            // get the first cube
+            pCubeFirst = pVar->pFirst;
+            // get the last cube
+            pCubeLast = pCubeFirst;
+            for ( k = 0; k < pVar->nCubes; k++ )
+                pCubeLast = pCubeLast->pNext;
+            assert( pCubeLast == NULL || pCubeLast->pVar != pVar );
+
+            // go through the cube pairs
+		    for ( pCube1 = pCubeFirst; pCube1 != pCubeLast; pCube1 = pCube1->pNext )
+			    for ( pCube2 = pCube1->pNext; pCube2 != pCubeLast; pCube2 = pCube2->pNext )
+                    if ( pnLitsDiff[iPair++] )
+                    {   // create the divisors for this pair
+	                    Fxu_MatrixAddDivisor( p, pCube1, pCube2 );
+                    }
+        }
+    assert( iPair == nPairsTotal );
+    ABC_FREE( pnLitsDiff );
+//ABC_PRT( "Preprocess", Abc_Clock() - clk );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the differences in each cube pair in the cover.]
+
+  Description [Takes the cover (pCover) and the array where the
+  diff counters go (pDiffs). The array pDiffs should have as many
+  entries as there are different pairs of cubes in the cover: n(n-1)/2.
+  Fills out the array pDiffs with the following info: For each cube
+  pair, included in the array is the number of literals in both cubes
+  after they are made cube free.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fxu_CountPairDiffs( char * pCover, unsigned char pDiffs[] )
+{
+    char * pCube1, * pCube2;
+    int nOnes, nCubePairs, nFanins, v;
+    nCubePairs = 0;
+    nFanins = Abc_SopGetVarNum(pCover);
+    Abc_SopForEachCube( pCover, nFanins, pCube1 )
+    Abc_SopForEachCube( pCube1, nFanins, pCube2 )
+    {
+        if ( pCube1 == pCube2 )
+            continue;
+        nOnes = 0;
+        for ( v = 0; v < nFanins; v++ )
+            nOnes += (pCube1[v] != pCube2[v]);
+        pDiffs[nCubePairs++] = nOnes;
+    }
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fxu/fxuSelect.c b/abc-build/src/opt/fxu/fxuSelect.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fxu/fxuSelect.c
@@ -0,0 +1,608 @@
+/**CFile****************************************************************
+
+  FileName    [fxuSelect.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Procedures to select the best divisor/complement pair.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: fxuSelect.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define MAX_SIZE_LOOKAHEAD      20
+
+static int Fxu_MatrixFindComplement( Fxu_Matrix * p, int iVar );
+
+static Fxu_Double * Fxu_MatrixFindComplementSingle( Fxu_Matrix * p, Fxu_Single * pSingle );
+static Fxu_Single * Fxu_MatrixFindComplementDouble2( Fxu_Matrix * p, Fxu_Double * pDouble );
+static Fxu_Double * Fxu_MatrixFindComplementDouble4( Fxu_Matrix * p, Fxu_Double * pDouble );
+
+Fxu_Double * Fxu_MatrixFindDouble( Fxu_Matrix * p, 
+     int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 );
+void Fxu_MatrixGetDoubleVars( Fxu_Matrix * p, Fxu_Double * pDouble, 
+    int piVarsC1[], int piVarsC2[], int * pnVarsC1, int * pnVarsC2 );
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Selects the best pair (Single,Double) and returns their weight.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fxu_Select( Fxu_Matrix * p, Fxu_Single ** ppSingle, Fxu_Double ** ppDouble )
+{
+    // the top entries
+    Fxu_Single * pSingles[MAX_SIZE_LOOKAHEAD] = {0};
+    Fxu_Double * pDoubles[MAX_SIZE_LOOKAHEAD] = {0};
+    // the complements
+    Fxu_Double * pSCompl[MAX_SIZE_LOOKAHEAD] = {0};
+    Fxu_Single * pDComplS[MAX_SIZE_LOOKAHEAD] = {0};
+    Fxu_Double * pDComplD[MAX_SIZE_LOOKAHEAD] = {0};
+    Fxu_Pair * pPair;
+    int nSingles;
+    int nDoubles;
+    int i;
+    int WeightBest;
+    int WeightCur;
+    int iNum, fBestS;
+
+    // collect the top entries from the queues
+    for ( nSingles = 0; nSingles < MAX_SIZE_LOOKAHEAD; nSingles++ )
+    {
+        pSingles[nSingles] = Fxu_HeapSingleGetMax( p->pHeapSingle );
+        if ( pSingles[nSingles] == NULL )
+            break;
+    }
+    // put them back into the queue
+    for ( i = 0; i < nSingles; i++ )
+        if ( pSingles[i] )
+            Fxu_HeapSingleInsert( p->pHeapSingle, pSingles[i] );
+        
+    // the same for doubles
+    // collect the top entries from the queues
+    for ( nDoubles = 0; nDoubles < MAX_SIZE_LOOKAHEAD; nDoubles++ )
+    {
+        pDoubles[nDoubles] = Fxu_HeapDoubleGetMax( p->pHeapDouble );
+        if ( pDoubles[nDoubles] == NULL )
+            break;
+    }
+    // put them back into the queue
+    for ( i = 0; i < nDoubles; i++ )
+        if ( pDoubles[i] )
+            Fxu_HeapDoubleInsert( p->pHeapDouble, pDoubles[i] );
+
+    // for each single, find the complement double (if any)
+    for ( i = 0; i < nSingles; i++ )
+        if ( pSingles[i] )
+            pSCompl[i] = Fxu_MatrixFindComplementSingle( p, pSingles[i] );
+
+    // for each double, find the complement single or double (if any)
+    for ( i = 0; i < nDoubles; i++ )
+        if ( pDoubles[i] )
+        {
+            pPair = pDoubles[i]->lPairs.pHead;
+            if ( pPair->nLits1 == 1 && pPair->nLits2 == 1 )
+            {
+                pDComplS[i] = Fxu_MatrixFindComplementDouble2( p, pDoubles[i] );
+                pDComplD[i] = NULL;
+            }
+//            else if ( pPair->nLits1 == 2 && pPair->nLits2 == 2 )
+//            {
+//                pDComplS[i] = NULL;
+//                pDComplD[i] = Fxu_MatrixFindComplementDouble4( p, pDoubles[i] );
+//            }
+            else
+            {
+                pDComplS[i] = NULL;
+                pDComplD[i] = NULL;
+            }
+        }
+
+    // select the best pair
+    WeightBest = -1;
+    for ( i = 0; i < nSingles; i++ )
+    {
+        WeightCur = pSingles[i]->Weight;
+        if ( pSCompl[i] )
+        {
+            // add the weight of the double
+            WeightCur += pSCompl[i]->Weight;
+            // there is no need to implement this double, so...
+            pPair      = pSCompl[i]->lPairs.pHead;
+            WeightCur += pPair->nLits1 + pPair->nLits2;
+        }
+        if ( WeightBest < WeightCur )
+        {
+            WeightBest = WeightCur;
+            *ppSingle = pSingles[i];
+            *ppDouble = pSCompl[i];
+            fBestS = 1;
+            iNum = i;
+        }
+    }
+    for ( i = 0; i < nDoubles; i++ )
+    {
+        WeightCur = pDoubles[i]->Weight;
+        if ( pDComplS[i] )
+        {
+            // add the weight of the single
+            WeightCur += pDComplS[i]->Weight;
+            // there is no need to implement this double, so...
+            pPair      = pDoubles[i]->lPairs.pHead;
+            WeightCur += pPair->nLits1 + pPair->nLits2;
+        }
+        if ( WeightBest < WeightCur )
+        {
+            WeightBest = WeightCur;
+            *ppSingle = pDComplS[i];
+            *ppDouble = pDoubles[i];
+            fBestS = 0;
+            iNum = i;
+        }
+    }
+/*
+    // print the statistics
+    printf( "\n" );
+    for ( i = 0; i < nSingles; i++ )
+    {
+        printf( "Single #%d: Weight = %3d. ", i, pSingles[i]->Weight );
+        printf( "Compl: " );
+        if ( pSCompl[i] == NULL )
+            printf( "None." );
+        else
+            printf( "D  Weight = %3d  Sum = %3d", 
+                pSCompl[i]->Weight, pSCompl[i]->Weight + pSingles[i]->Weight );
+        printf( "\n" );
+    }
+    printf( "\n" );
+    for ( i = 0; i < nDoubles; i++ )
+    {
+        printf( "Double #%d: Weight = %3d. ", i, pDoubles[i]->Weight );
+        printf( "Compl: " );
+        if ( pDComplS[i] == NULL && pDComplD[i] == NULL )
+            printf( "None." );
+        else if ( pDComplS[i] )
+            printf( "S  Weight = %3d  Sum = %3d", 
+                pDComplS[i]->Weight, pDComplS[i]->Weight + pDoubles[i]->Weight );
+        else if ( pDComplD[i] )
+            printf( "D  Weight = %3d  Sum = %3d", 
+                pDComplD[i]->Weight, pDComplD[i]->Weight + pDoubles[i]->Weight );
+        printf( "\n" );
+    }
+    if ( WeightBest == -1 )
+        printf( "Selected NONE\n" );
+    else
+    {
+        printf( "Selected = %s.  ", fBestS? "S": "D" );
+        printf( "Number = %d.  ", iNum );
+        printf( "Weight = %d.\n", WeightBest );
+    }
+    printf( "\n" );
+*/
+    return WeightBest;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fxu_Double * Fxu_MatrixFindComplementSingle( Fxu_Matrix * p, Fxu_Single * pSingle )
+{
+//    int * pValue2Node = p->pValue2Node;
+    int iVar1,  iVar2;
+    int iVar1C, iVar2C;
+    // get the variables of this single div
+    iVar1  = pSingle->pVar1->iVar;
+    iVar2  = pSingle->pVar2->iVar;
+    iVar1C = Fxu_MatrixFindComplement( p, iVar1 );
+    iVar2C = Fxu_MatrixFindComplement( p, iVar2 );
+    if ( iVar1C == -1 || iVar2C == -1 )
+        return NULL;
+    assert( iVar1C < iVar2C );
+    return Fxu_MatrixFindDouble( p, &iVar1C, &iVar2C, 1, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fxu_Single * Fxu_MatrixFindComplementDouble2( Fxu_Matrix * p, Fxu_Double * pDouble )
+{
+//    int * pValue2Node = p->pValue2Node;
+    int piVarsC1[10], piVarsC2[10];
+    int nVarsC1, nVarsC2;
+    int iVar1,  iVar2, iVarTemp;
+    int iVar1C, iVar2C;
+    Fxu_Single * pSingle;
+
+    // get the variables of this double div
+    Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 );
+    assert( nVarsC1 == 1 );
+    assert( nVarsC2 == 1 );
+    iVar1 = piVarsC1[0];
+    iVar2 = piVarsC2[0];
+    assert( iVar1 < iVar2 );
+
+    iVar1C = Fxu_MatrixFindComplement( p, iVar1 );
+    iVar2C = Fxu_MatrixFindComplement( p, iVar2 );
+    if ( iVar1C == -1 || iVar2C == -1 )
+        return NULL;
+ 
+    // go through the queque and find this one
+//    assert( iVar1C < iVar2C );
+    if ( iVar1C > iVar2C )
+    {
+        iVarTemp = iVar1C;
+        iVar1C = iVar2C;
+        iVar2C = iVarTemp;
+    }
+
+    Fxu_MatrixForEachSingle( p, pSingle )
+        if ( pSingle->pVar1->iVar == iVar1C && pSingle->pVar2->iVar == iVar2C )
+            return pSingle;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fxu_Double * Fxu_MatrixFindComplementDouble4( Fxu_Matrix * p, Fxu_Double * pDouble )
+{
+//    int * pValue2Node = p->pValue2Node;
+    int piVarsC1[10], piVarsC2[10];
+    int nVarsC1, nVarsC2;
+    int iVar11,  iVar12,  iVar21,  iVar22;
+    int iVar11C, iVar12C, iVar21C, iVar22C;
+    int RetValue;
+
+    // get the variables of this double div
+    Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 );
+    assert( nVarsC1 == 2 && nVarsC2 == 2 );
+
+    iVar11 = piVarsC1[0];
+    iVar12 = piVarsC1[1];
+    iVar21 = piVarsC2[0];
+    iVar22 = piVarsC2[1];
+    assert( iVar11 < iVar21 );
+
+    iVar11C = Fxu_MatrixFindComplement( p, iVar11 );
+    iVar12C = Fxu_MatrixFindComplement( p, iVar12 );
+    iVar21C = Fxu_MatrixFindComplement( p, iVar21 );
+    iVar22C = Fxu_MatrixFindComplement( p, iVar22 );
+    if ( iVar11C == -1 || iVar12C == -1 || iVar21C == -1 || iVar22C == -1 )
+        return NULL;
+    if ( iVar11C != iVar21 || iVar12C != iVar22 || 
+         iVar21C != iVar11 || iVar22C != iVar12 )
+         return NULL;
+
+    // a'b' + ab   =>  a'b  + ab'
+    // a'b  + ab'  =>  a'b' + ab
+    // swap the second pair in each cube
+    RetValue    = piVarsC1[1];
+    piVarsC1[1] = piVarsC2[1];
+    piVarsC2[1] = RetValue;
+
+    return Fxu_MatrixFindDouble( p, piVarsC1, piVarsC2, 2, 2 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fxu_MatrixFindComplement( Fxu_Matrix * p, int iVar )
+{
+    return iVar ^ 1;
+/*
+//    int * pValue2Node = p->pValue2Node;
+    int iVarC;
+    int iNode;
+    int Beg, End;
+
+    // get the nodes
+    iNode = pValue2Node[iVar];
+    // get the first node with the same var
+    for ( Beg = iVar; Beg >= 0; Beg-- )
+        if ( pValue2Node[Beg] != iNode )
+        {
+            Beg++;
+            break;
+        }
+    // get the last node with the same var
+    for ( End = iVar;          ; End++ )
+        if ( pValue2Node[End] != iNode )
+        {
+            End--;
+            break;
+        }
+
+    // if one of the vars is not binary, quit
+    if ( End - Beg > 1 )
+        return -1;
+
+    // get the complements
+    if ( iVar == Beg )
+        iVarC = End;
+    else if ( iVar == End ) 
+        iVarC = Beg;
+    else
+    {
+        assert( 0 );
+    }
+    return iVarC;
+*/
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_MatrixGetDoubleVars( Fxu_Matrix * p, Fxu_Double * pDouble, 
+    int piVarsC1[], int piVarsC2[], int * pnVarsC1, int * pnVarsC2 )
+{
+    Fxu_Pair * pPair;
+	Fxu_Lit * pLit1, * pLit2;
+    int nLits1, nLits2;
+
+    // get the first pair
+    pPair = pDouble->lPairs.pHead;
+    // init the parameters
+	nLits1 = 0;
+	nLits2 = 0;
+	pLit1 = pPair->pCube1->lLits.pHead;
+	pLit2 = pPair->pCube2->lLits.pHead;
+	while ( 1 )
+	{
+		if ( pLit1 && pLit2 )
+		{
+			if ( pLit1->iVar == pLit2->iVar )
+			{ // ensure cube-free
+				pLit1 = pLit1->pHNext;
+				pLit2 = pLit2->pHNext;
+			}
+			else if ( pLit1->iVar < pLit2->iVar )
+            {
+                piVarsC1[nLits1++] = pLit1->iVar;
+ 				pLit1 = pLit1->pHNext;
+           }
+			else
+            {
+                piVarsC2[nLits2++] = pLit2->iVar;
+				pLit2 = pLit2->pHNext;
+            }
+		}
+		else if ( pLit1 && !pLit2 )
+        {
+            piVarsC1[nLits1++] = pLit1->iVar;
+    		pLit1 = pLit1->pHNext;
+        }
+		else if ( !pLit1 && pLit2 )
+        {
+            piVarsC2[nLits2++] = pLit2->iVar;
+			pLit2 = pLit2->pHNext;
+        }
+		else
+			break;
+	}
+    *pnVarsC1 = nLits1;
+    *pnVarsC2 = nLits2;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fxu_Double * Fxu_MatrixFindDouble( Fxu_Matrix * p, 
+     int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 )
+{
+    int piVarsC1_[100], piVarsC2_[100];
+    int nVarsC1_, nVarsC2_, i;
+    Fxu_Double * pDouble;
+    Fxu_Pair * pPair;
+    unsigned Key;
+
+    assert( nVarsC1 > 0 );
+    assert( nVarsC2 > 0 );
+    assert( piVarsC1[0] < piVarsC2[0] );
+
+    // get the hash key
+    Key = Fxu_PairHashKeyArray( p, piVarsC1, piVarsC2, nVarsC1, nVarsC2 );
+    
+    // check if the divisor for this pair already exists
+    Key %= p->nTableSize;
+	Fxu_TableForEachDouble( p, Key, pDouble )
+    {
+        pPair = pDouble->lPairs.pHead;
+        if ( pPair->nLits1 != nVarsC1 )
+            continue;
+        if ( pPair->nLits2 != nVarsC2 )
+            continue;
+        // get the cubes of this divisor
+        Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1_, piVarsC2_, &nVarsC1_, &nVarsC2_ );
+        // compare lits of the first cube
+        for ( i = 0; i < nVarsC1; i++ )
+            if ( piVarsC1[i] != piVarsC1_[i] )
+                break;
+        if ( i != nVarsC1 )
+            continue;
+        // compare lits of the second cube
+        for ( i = 0; i < nVarsC2; i++ )
+            if ( piVarsC2[i] != piVarsC2_[i] )
+                break;
+        if ( i != nVarsC2 )
+            continue;
+        return pDouble;
+    }
+    return NULL;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fxu_SelectSCD( Fxu_Matrix * p, int WeightLimit, Fxu_Var ** ppVar1, Fxu_Var ** ppVar2 )
+{
+//    int * pValue2Node = p->pValue2Node;
+    Fxu_Var * pVar1;
+    Fxu_Var * pVar2, * pVarTemp;
+    Fxu_Lit * pLitV, * pLitH;
+    int Coin;
+    int CounterAll;
+    int CounterTest;
+    int WeightCur;
+    int WeightBest;
+
+    CounterAll = 0;
+    CounterTest = 0;
+
+    WeightBest = -10;
+    
+    // iterate through the columns in the matrix
+    Fxu_MatrixForEachVariable( p, pVar1 )
+    {
+        // start collecting the affected vars
+        Fxu_MatrixRingVarsStart( p );
+
+        // go through all the literals of this variable
+        for ( pLitV = pVar1->lLits.pHead; pLitV; pLitV = pLitV->pVNext )
+        {
+            // for this literal, go through all the horizontal literals
+            for ( pLitH = pLitV->pHNext; pLitH; pLitH = pLitH->pHNext )
+            {
+                // get another variable
+                pVar2 = pLitH->pVar;
+                CounterAll++;
+                // skip the var if it is already used
+                if ( pVar2->pOrder )
+                    continue;
+                // skip the var if it belongs to the same node
+//                if ( pValue2Node[pVar1->iVar] == pValue2Node[pVar2->iVar] )
+//                    continue;
+                // collect the var
+                Fxu_MatrixRingVarsAdd( p, pVar2 );
+            }
+        }
+        // stop collecting the selected vars
+        Fxu_MatrixRingVarsStop( p );
+
+        // iterate through the selected vars
+        Fxu_MatrixForEachVarInRing( p, pVar2 )
+        {
+            CounterTest++;
+
+            // count the coincidence
+            Coin = Fxu_SingleCountCoincidence( p, pVar1, pVar2 );
+            assert( Coin > 0 );
+
+            // get the new weight
+            WeightCur = Coin - 2;
+
+            // compare the weights
+            if ( WeightBest < WeightCur )
+            {
+                WeightBest = WeightCur;
+                *ppVar1 = pVar1;
+                *ppVar2 = pVar2;
+            }
+        }
+        // unmark the vars
+        Fxu_MatrixForEachVarInRingSafe( p, pVar2, pVarTemp )
+            pVar2->pOrder = NULL;
+        Fxu_MatrixRingVarsReset( p );
+    }
+
+//    if ( WeightBest == WeightLimit )
+//        return -1;
+    return WeightBest;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fxu/fxuSingle.c b/abc-build/src/opt/fxu/fxuSingle.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fxu/fxuSingle.c
@@ -0,0 +1,289 @@
+/**CFile****************************************************************
+
+  FileName    [fxuSingle.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Procedures to compute the set of single-cube divisors.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: fxuSingle.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+#include "misc/vec/vec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Fxu_MatrixComputeSinglesOneCollect( Fxu_Matrix * p, Fxu_Var * pVar, Vec_Ptr_t * vSingles );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes and adds all single-cube divisors to storage.]
+
+  Description [This procedure should be called once when the matrix is
+  already contructed before the process of logic extraction begins..]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_MatrixComputeSingles( Fxu_Matrix * p, int fUse0, int nSingleMax )
+{
+    Fxu_Var * pVar;
+    Vec_Ptr_t * vSingles;
+    int i, k;
+    // set the weight limit
+    p->nWeightLimit = 1 - fUse0;
+    // iterate through columns in the matrix and collect single-cube divisors
+    vSingles = Vec_PtrAlloc( 10000 );
+    Fxu_MatrixForEachVariable( p, pVar )
+        Fxu_MatrixComputeSinglesOneCollect( p, pVar, vSingles );
+    p->nSingleTotal = Vec_PtrSize(vSingles) / 3;
+    // check if divisors should be filtered
+    if ( Vec_PtrSize(vSingles) > nSingleMax )
+    {
+        int * pWeigtCounts, nDivCount, Weight, i, c;;
+        assert( Vec_PtrSize(vSingles) % 3 == 0 );
+        // count how many divisors have the given weight
+        pWeigtCounts = ABC_ALLOC( int, 1000 );
+        memset( pWeigtCounts, 0, sizeof(int) * 1000 );
+        for ( i = 2; i < Vec_PtrSize(vSingles); i += 3 )
+        {
+            Weight = (int)(ABC_PTRUINT_T)Vec_PtrEntry(vSingles, i);
+            if ( Weight >= 999 )
+                pWeigtCounts[999]++;
+            else
+                pWeigtCounts[Weight]++;
+        }
+        // select the bound on the weight (above this bound, singles will be included)
+        nDivCount = 0;
+        for ( c = 999; c >= 0; c-- )
+        {
+            nDivCount += pWeigtCounts[c];
+            if ( nDivCount >= nSingleMax )
+                break;
+        }
+        ABC_FREE( pWeigtCounts );
+        // collect singles with the given costs
+        k = 0;
+        for ( i = 2; i < Vec_PtrSize(vSingles); i += 3 )
+        {
+            Weight = (int)(ABC_PTRUINT_T)Vec_PtrEntry(vSingles, i);
+            if ( Weight < c )
+                continue;
+            Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i-2) );
+            Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i-1) );
+            Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i) );
+            if ( k/3 == nSingleMax )
+                break;
+        }
+        Vec_PtrShrink( vSingles, k );
+        // adjust the weight limit
+        p->nWeightLimit = c;
+    }
+    // collect the selected divisors
+    assert( Vec_PtrSize(vSingles) % 3 == 0 );
+    for ( i = 0; i < Vec_PtrSize(vSingles); i += 3 )
+    {
+        Fxu_MatrixAddSingle( p, 
+            (Fxu_Var *)Vec_PtrEntry(vSingles,i), 
+            (Fxu_Var *)Vec_PtrEntry(vSingles,i+1), 
+            (int)(ABC_PTRUINT_T)Vec_PtrEntry(vSingles,i+2) );
+    }
+    Vec_PtrFree( vSingles );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the single-cube divisors associated with a new column.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_MatrixComputeSinglesOneCollect( Fxu_Matrix * p, Fxu_Var * pVar, Vec_Ptr_t * vSingles )
+{
+    Fxu_Lit * pLitV, * pLitH;
+    Fxu_Var * pVar2;
+    int Coin;
+    int WeightCur;
+
+    // start collecting the affected vars
+    Fxu_MatrixRingVarsStart( p );
+    // go through all the literals of this variable
+    for ( pLitV = pVar->lLits.pHead; pLitV; pLitV = pLitV->pVNext )
+        // for this literal, go through all the horizontal literals
+        for ( pLitH = pLitV->pHPrev; pLitH; pLitH = pLitH->pHPrev )
+        {
+            // get another variable
+            pVar2 = pLitH->pVar;
+            // skip the var if it is already used
+            if ( pVar2->pOrder )
+                continue;
+            // skip the var if it belongs to the same node
+//            if ( pValue2Node[pVar->iVar] == pValue2Node[pVar2->iVar] )
+//                continue;
+            // collect the var
+            Fxu_MatrixRingVarsAdd( p, pVar2 );
+        }
+    // stop collecting the selected vars
+    Fxu_MatrixRingVarsStop( p );
+
+    // iterate through the selected vars
+    Fxu_MatrixForEachVarInRing( p, pVar2 )
+    {
+        // count the coincidence
+        Coin = Fxu_SingleCountCoincidence( p, pVar2, pVar );
+        assert( Coin > 0 );
+        // get the new weight
+        WeightCur = Coin - 2;
+        // peformance fix (August 24, 2007)
+        if ( WeightCur >= p->nWeightLimit )
+        {
+            Vec_PtrPush( vSingles, pVar2 );
+            Vec_PtrPush( vSingles, pVar );
+            Vec_PtrPush( vSingles, (void *)(ABC_PTRUINT_T)WeightCur );
+        }
+    }
+
+    // unmark the vars
+    Fxu_MatrixRingVarsUnmark( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the single-cube divisors associated with a new column.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar )
+{
+    Fxu_Lit * pLitV, * pLitH;
+    Fxu_Var * pVar2;
+    int Coin;
+    int WeightCur;
+
+    // start collecting the affected vars
+    Fxu_MatrixRingVarsStart( p );
+    // go through all the literals of this variable
+    for ( pLitV = pVar->lLits.pHead; pLitV; pLitV = pLitV->pVNext )
+        // for this literal, go through all the horizontal literals
+        for ( pLitH = pLitV->pHPrev; pLitH; pLitH = pLitH->pHPrev )
+        {
+            // get another variable
+            pVar2 = pLitH->pVar;
+            // skip the var if it is already used
+            if ( pVar2->pOrder )
+                continue;
+            // skip the var if it belongs to the same node
+//            if ( pValue2Node[pVar->iVar] == pValue2Node[pVar2->iVar] )
+//                continue;
+            // collect the var
+            Fxu_MatrixRingVarsAdd( p, pVar2 );
+        }
+    // stop collecting the selected vars
+    Fxu_MatrixRingVarsStop( p );
+
+    // iterate through the selected vars
+    Fxu_MatrixForEachVarInRing( p, pVar2 )
+    {
+        // count the coincidence
+        Coin = Fxu_SingleCountCoincidence( p, pVar2, pVar );
+        assert( Coin > 0 );
+        // get the new weight
+        WeightCur = Coin - 2;
+        // peformance fix (August 24, 2007)
+//        if ( WeightCur >= 0 )
+//        Fxu_MatrixAddSingle( p, pVar2, pVar, WeightCur );
+        if ( WeightCur >= p->nWeightLimit )
+            Fxu_MatrixAddSingle( p, pVar2, pVar, WeightCur );
+    }
+    // unmark the vars
+    Fxu_MatrixRingVarsUnmark( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the coincidence count of two columns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fxu_SingleCountCoincidence( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2 )
+{
+	Fxu_Lit * pLit1, * pLit2;
+	int Result;
+
+	// compute the coincidence count
+	Result = 0;
+	pLit1  = pVar1->lLits.pHead;
+	pLit2  = pVar2->lLits.pHead;
+	while ( 1 )
+	{
+		if ( pLit1 && pLit2 )
+		{
+			if ( pLit1->pCube->pVar->iVar == pLit2->pCube->pVar->iVar )
+			{ // the variables are the same
+			    if ( pLit1->iCube == pLit2->iCube )
+			    { // the literals are the same
+				    pLit1 = pLit1->pVNext;
+				    pLit2 = pLit2->pVNext;
+				    // add this literal to the coincidence
+				    Result++;
+			    }
+			    else if ( pLit1->iCube < pLit2->iCube )
+				    pLit1 = pLit1->pVNext;
+			    else
+				    pLit2 = pLit2->pVNext;
+			}
+			else if ( pLit1->pCube->pVar->iVar < pLit2->pCube->pVar->iVar )
+				pLit1 = pLit1->pVNext;
+			else
+				pLit2 = pLit2->pVNext;
+		}
+		else if ( pLit1 && !pLit2 )
+			pLit1 = pLit1->pVNext;
+		else if ( !pLit1 && pLit2 )
+			pLit2 = pLit2->pVNext;
+		else
+			break;
+	}
+	return Result;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fxu/fxuUpdate.c b/abc-build/src/opt/fxu/fxuUpdate.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fxu/fxuUpdate.c
@@ -0,0 +1,811 @@
+/**CFile****************************************************************
+
+  FileName    [fxuUpdate.c]
+
+  PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+  Synopsis    [Updating the sparse matrix when divisors are accepted.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: fxuUpdate.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Fxu_UpdateDoublePairs( Fxu_Matrix * p, Fxu_Double * pDouble, Fxu_Var * pVar );
+static void Fxu_UpdateMatrixDoubleCreateCubes( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, Fxu_Double * pDiv );
+static void Fxu_UpdateMatrixDoubleClean( Fxu_Matrix * p, Fxu_Cube * pCubeUse, Fxu_Cube * pCubeRem );
+static void Fxu_UpdateMatrixSingleClean( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, Fxu_Var * pVarNew );
+
+static void Fxu_UpdateCreateNewVars( Fxu_Matrix * p, Fxu_Var ** ppVarC, Fxu_Var ** ppVarD, int nCubes );
+static int  Fxu_UpdatePairCompare( Fxu_Pair ** ppP1, Fxu_Pair ** ppP2 );
+static void Fxu_UpdatePairsSort( Fxu_Matrix * p, Fxu_Double * pDouble );
+
+static void Fxu_UpdateCleanOldDoubles( Fxu_Matrix * p, Fxu_Double * pDiv, Fxu_Cube * pCube );
+static void Fxu_UpdateAddNewDoubles( Fxu_Matrix * p, Fxu_Cube * pCube );
+static void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p );
+static void Fxu_UpdateAddNewSingles( Fxu_Matrix * p, Fxu_Var * pVar );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the matrix after selecting two divisors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_Update( Fxu_Matrix * p, Fxu_Single * pSingle, Fxu_Double * pDouble )
+{
+	Fxu_Cube * pCube, * pCubeNew;
+	Fxu_Var * pVarC, * pVarD;
+	Fxu_Var * pVar1, * pVar2;
+
+    // consider trivial cases
+    if ( pSingle == NULL )
+    {
+        assert( pDouble->Weight == Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ) );
+        Fxu_UpdateDouble( p );
+        return;
+    }
+    if ( pDouble == NULL )
+    {
+        assert( pSingle->Weight == Fxu_HeapSingleReadMaxWeight( p->pHeapSingle ) );
+        Fxu_UpdateSingle( p );
+        return;
+    }
+
+    // get the variables of the single
+    pVar1 = pSingle->pVar1;
+    pVar2 = pSingle->pVar2;
+
+    // remove the best double from the heap
+    Fxu_HeapDoubleDelete( p->pHeapDouble, pDouble );
+	// remove the best divisor from the table
+	Fxu_ListTableDelDivisor( p, pDouble );
+
+    // create two new columns (vars)
+    Fxu_UpdateCreateNewVars( p, &pVarC, &pVarD, 1 );
+    // create one new row (cube)
+    pCubeNew = Fxu_MatrixAddCube( p, pVarD, 0 );
+    pCubeNew->pFirst = pCubeNew;
+    // set the first cube of the positive var
+    pVarD->pFirst = pCubeNew;
+
+    // start collecting the affected vars and cubes
+    Fxu_MatrixRingCubesStart( p );
+    Fxu_MatrixRingVarsStart( p );
+    // add the vars
+    Fxu_MatrixRingVarsAdd( p, pVar1 );
+    Fxu_MatrixRingVarsAdd( p, pVar2 );
+    // remove the literals and collect the affected cubes
+    // remove the divisors associated with this cube
+   	// add to the affected cube the literal corresponding to the new column
+	Fxu_UpdateMatrixSingleClean( p, pVar1, pVar2, pVarD );
+	// replace each two cubes of the pair by one new cube
+	// the new cube contains the base and the new literal
+    Fxu_UpdateDoublePairs( p, pDouble, pVarC );
+    // stop collecting the affected vars and cubes
+    Fxu_MatrixRingCubesStop( p );
+    Fxu_MatrixRingVarsStop( p );
+
+    // add the literals to the new cube
+    assert( pVar1->iVar < pVar2->iVar );
+    assert( Fxu_SingleCountCoincidence( p, pVar1, pVar2 ) == 0 );
+    Fxu_MatrixAddLiteral( p, pCubeNew, pVar1 );
+    Fxu_MatrixAddLiteral( p, pCubeNew, pVar2 );
+
+    // create new doubles; we cannot add them in the same loop
+	// because we first have to create *all* new cubes for each node
+    Fxu_MatrixForEachCubeInRing( p, pCube )
+   		Fxu_UpdateAddNewDoubles( p, pCube );
+    // update the singles after removing some literals
+    Fxu_UpdateCleanOldSingles( p );
+
+    // undo the temporary rings with cubes and vars
+    Fxu_MatrixRingCubesUnmark( p );
+    Fxu_MatrixRingVarsUnmark( p );
+    // we should undo the rings before creating new singles
+
+    // create new singles
+    Fxu_UpdateAddNewSingles( p, pVarC );
+    Fxu_UpdateAddNewSingles( p, pVarD );
+
+	// recycle the divisor
+	MEM_FREE_FXU( p, Fxu_Double, 1, pDouble );
+	p->nDivs3++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates after accepting single cube divisor.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_UpdateSingle( Fxu_Matrix * p )
+{
+    Fxu_Single * pSingle;
+	Fxu_Cube * pCube, * pCubeNew;
+	Fxu_Var * pVarC, * pVarD;
+	Fxu_Var * pVar1, * pVar2;
+
+    // read the best divisor from the heap
+    pSingle = Fxu_HeapSingleReadMax( p->pHeapSingle );
+    // get the variables of this single-cube divisor
+    pVar1 = pSingle->pVar1;
+    pVar2 = pSingle->pVar2;
+
+    // create two new columns (vars)
+    Fxu_UpdateCreateNewVars( p, &pVarC, &pVarD, 1 );
+    // create one new row (cube)
+    pCubeNew = Fxu_MatrixAddCube( p, pVarD, 0 );
+    pCubeNew->pFirst = pCubeNew;
+    // set the first cube
+    pVarD->pFirst = pCubeNew;
+
+    // start collecting the affected vars and cubes
+    Fxu_MatrixRingCubesStart( p );
+    Fxu_MatrixRingVarsStart( p );
+    // add the vars
+    Fxu_MatrixRingVarsAdd( p, pVar1 );
+    Fxu_MatrixRingVarsAdd( p, pVar2 );
+    // remove the literals and collect the affected cubes
+    // remove the divisors associated with this cube
+   	// add to the affected cube the literal corresponding to the new column
+	Fxu_UpdateMatrixSingleClean( p, pVar1, pVar2, pVarD );
+    // stop collecting the affected vars and cubes
+    Fxu_MatrixRingCubesStop( p );
+    Fxu_MatrixRingVarsStop( p );
+
+    // add the literals to the new cube
+    assert( pVar1->iVar < pVar2->iVar );
+    assert( Fxu_SingleCountCoincidence( p, pVar1, pVar2 ) == 0 );
+    Fxu_MatrixAddLiteral( p, pCubeNew, pVar1 );
+    Fxu_MatrixAddLiteral( p, pCubeNew, pVar2 );
+
+    // create new doubles; we cannot add them in the same loop
+	// because we first have to create *all* new cubes for each node
+    Fxu_MatrixForEachCubeInRing( p, pCube )
+   		Fxu_UpdateAddNewDoubles( p, pCube );
+    // update the singles after removing some literals
+    Fxu_UpdateCleanOldSingles( p );
+    // we should undo the rings before creating new singles
+
+    // unmark the cubes
+    Fxu_MatrixRingCubesUnmark( p );
+    Fxu_MatrixRingVarsUnmark( p );
+
+    // create new singles
+    Fxu_UpdateAddNewSingles( p, pVarC );
+    Fxu_UpdateAddNewSingles( p, pVarD );
+	p->nDivs1++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the matrix after accepting a double cube divisor.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_UpdateDouble( Fxu_Matrix * p )
+{
+    Fxu_Double * pDiv;
+	Fxu_Cube * pCube, * pCubeNew1, * pCubeNew2;
+	Fxu_Var * pVarC, * pVarD;
+
+    // remove the best divisor from the heap
+    pDiv = Fxu_HeapDoubleGetMax( p->pHeapDouble );
+	// remove the best divisor from the table
+	Fxu_ListTableDelDivisor( p, pDiv );
+
+    // create two new columns (vars)
+    Fxu_UpdateCreateNewVars( p, &pVarC, &pVarD, 2 );
+    // create two new rows (cubes)
+    pCubeNew1 = Fxu_MatrixAddCube( p, pVarD, 0 );
+    pCubeNew1->pFirst = pCubeNew1;
+    pCubeNew2 = Fxu_MatrixAddCube( p, pVarD, 1 );
+    pCubeNew2->pFirst = pCubeNew1;
+    // set the first cube
+    pVarD->pFirst = pCubeNew1;
+
+    // add the literals to the new cubes
+    Fxu_UpdateMatrixDoubleCreateCubes( p, pCubeNew1, pCubeNew2, pDiv );
+
+    // start collecting the affected cubes and vars
+    Fxu_MatrixRingCubesStart( p );
+    Fxu_MatrixRingVarsStart( p );
+	// replace each two cubes of the pair by one new cube
+	// the new cube contains the base and the new literal
+    Fxu_UpdateDoublePairs( p, pDiv, pVarD );
+    // stop collecting the affected cubes and vars
+    Fxu_MatrixRingCubesStop( p );
+    Fxu_MatrixRingVarsStop( p );
+    
+    // create new doubles; we cannot add them in the same loop
+	// because we first have to create *all* new cubes for each node
+    Fxu_MatrixForEachCubeInRing( p, pCube )
+   		Fxu_UpdateAddNewDoubles( p, pCube );
+    // update the singles after removing some literals
+    Fxu_UpdateCleanOldSingles( p );
+
+    // undo the temporary rings with cubes and vars
+    Fxu_MatrixRingCubesUnmark( p );
+    Fxu_MatrixRingVarsUnmark( p );
+    // we should undo the rings before creating new singles
+
+    // create new singles
+    Fxu_UpdateAddNewSingles( p, pVarC );
+    Fxu_UpdateAddNewSingles( p, pVarD );
+
+    // recycle the divisor
+	MEM_FREE_FXU( p, Fxu_Double, 1, pDiv );
+	p->nDivs2++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Update the pairs.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_UpdateDoublePairs( Fxu_Matrix * p, Fxu_Double * pDouble, Fxu_Var * pVar )
+{
+    Fxu_Pair * pPair;
+    Fxu_Cube * pCubeUse, * pCubeRem;
+    int i;
+
+    // collect and sort the pairs
+    Fxu_UpdatePairsSort( p, pDouble );
+//    for ( i = 0; i < p->nPairsTemp; i++ )
+    for ( i = 0; i < p->vPairs->nSize; i++ )
+    {
+        // get the pair
+//        pPair = p->pPairsTemp[i];
+        pPair = (Fxu_Pair *)p->vPairs->pArray[i];
+	    // out of the two cubes, select the one which comes earlier
+	    pCubeUse = Fxu_PairMinCube( pPair );
+	    pCubeRem = Fxu_PairMaxCube( pPair );
+        // collect the affected cube
+        assert( pCubeUse->pOrder == NULL );
+        Fxu_MatrixRingCubesAdd( p, pCubeUse );
+
+	    // remove some literals from pCubeUse and all literals from pCubeRem
+	    Fxu_UpdateMatrixDoubleClean( p, pCubeUse, pCubeRem );
+	    // add a literal that depends on the new variable
+	    Fxu_MatrixAddLiteral( p, pCubeUse, pVar );	
+        // check the literal count
+        assert( pCubeUse->lLits.nItems == pPair->nBase + 1 );
+        assert( pCubeRem->lLits.nItems == 0 );
+
+	    // update the divisors by removing useless pairs
+	    Fxu_UpdateCleanOldDoubles( p, pDouble, pCubeUse );
+	    Fxu_UpdateCleanOldDoubles( p, pDouble, pCubeRem );
+	    // remove the pair
+	    MEM_FREE_FXU( p, Fxu_Pair, 1, pPair );
+    }
+    p->vPairs->nSize = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add two cubes corresponding to the given double-cube divisor.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_UpdateMatrixDoubleCreateCubes( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, Fxu_Double * pDiv )
+{
+	Fxu_Lit * pLit1, * pLit2;
+    Fxu_Pair * pPair;
+	int nBase, nLits1, nLits2;
+
+	// fill in the SOP and copy the fanins
+	nBase = nLits1 = nLits2 = 0;
+	pPair = pDiv->lPairs.pHead;
+	pLit1 = pPair->pCube1->lLits.pHead;
+	pLit2 = pPair->pCube2->lLits.pHead;
+	while ( 1 )
+	{
+		if ( pLit1 && pLit2 )
+		{
+			if ( pLit1->iVar == pLit2->iVar )
+			{ // skip the cube free part
+				pLit1 = pLit1->pHNext;
+				pLit2 = pLit2->pHNext;
+                nBase++;
+			}
+			else if ( pLit1->iVar < pLit2->iVar )
+			{	// add literal to the first cube
+                Fxu_MatrixAddLiteral( p, pCube1, pLit1->pVar );
+				// move to the next literal in this cube
+				pLit1 = pLit1->pHNext;
+                nLits1++;
+			}
+			else
+			{	// add literal to the second cube
+                Fxu_MatrixAddLiteral( p, pCube2, pLit2->pVar );
+				// move to the next literal in this cube
+				pLit2 = pLit2->pHNext;
+                nLits2++;
+			}
+		}
+		else if ( pLit1 && !pLit2 )
+		{	// add literal to the first cube
+            Fxu_MatrixAddLiteral( p, pCube1, pLit1->pVar );
+			// move to the next literal in this cube
+			pLit1 = pLit1->pHNext;
+            nLits1++;
+		}
+		else if ( !pLit1 && pLit2 )
+		{	// add literal to the second cube
+            Fxu_MatrixAddLiteral( p, pCube2, pLit2->pVar );
+			// move to the next literal in this cube
+			pLit2 = pLit2->pHNext;
+            nLits2++;
+		}
+		else
+			break;
+	}
+	assert( pPair->nLits1 == nLits1 );
+	assert( pPair->nLits2 == nLits2 );
+	assert( pPair->nBase == nBase );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Create the node equal to double-cube divisor.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_UpdateMatrixDoubleClean( Fxu_Matrix * p, Fxu_Cube * pCubeUse, Fxu_Cube * pCubeRem )
+{
+	Fxu_Lit * pLit1, * bLit1Next;
+	Fxu_Lit * pLit2, * bLit2Next;
+
+	// initialize the starting literals
+	pLit1     = pCubeUse->lLits.pHead;
+	pLit2     = pCubeRem->lLits.pHead;
+	bLit1Next = pLit1? pLit1->pHNext: NULL;
+	bLit2Next = pLit2? pLit2->pHNext: NULL;
+	// go through the pair and remove the literals in the base
+	// from the first cube and all literals from the second cube
+	while ( 1 )
+	{
+		if ( pLit1 && pLit2 )
+		{
+			if ( pLit1->iVar == pLit2->iVar )
+            {  // this literal is present in both cubes - it belongs to the base
+                // mark the affected var
+                if ( pLit1->pVar->pOrder == NULL )
+                    Fxu_MatrixRingVarsAdd( p, pLit1->pVar );
+                // leave the base in pCubeUse; delete it from pCubeRem
+				Fxu_MatrixDelLiteral( p, pLit2 );
+				// step to the next literals
+				pLit1     = bLit1Next;
+				pLit2     = bLit2Next;
+				bLit1Next = pLit1? pLit1->pHNext: NULL;
+				bLit2Next = pLit2? pLit2->pHNext: NULL;
+			}
+			else if ( pLit1->iVar < pLit2->iVar )
+			{ // this literal is present in pCubeUse - remove it
+                // mark the affected var
+                if ( pLit1->pVar->pOrder == NULL )
+                    Fxu_MatrixRingVarsAdd( p, pLit1->pVar );
+                // delete this literal
+                Fxu_MatrixDelLiteral( p, pLit1 );
+				// step to the next literals
+				pLit1     = bLit1Next;
+				bLit1Next = pLit1? pLit1->pHNext: NULL;
+			}
+			else
+			{ // this literal is present in pCubeRem - remove it
+                // mark the affected var
+                if ( pLit2->pVar->pOrder == NULL )
+                    Fxu_MatrixRingVarsAdd( p, pLit2->pVar );
+                // delete this literal
+				Fxu_MatrixDelLiteral( p, pLit2 );
+				// step to the next literals
+				pLit2     = bLit2Next;
+				bLit2Next = pLit2? pLit2->pHNext: NULL;
+			}
+		}
+		else if ( pLit1 && !pLit2 )
+		{ // this literal is present in pCubeUse - leave it
+            // mark the affected var
+            if ( pLit1->pVar->pOrder == NULL )
+                Fxu_MatrixRingVarsAdd( p, pLit1->pVar );
+            // delete this literal
+			Fxu_MatrixDelLiteral( p, pLit1 );
+			// step to the next literals
+			pLit1     = bLit1Next;
+			bLit1Next = pLit1? pLit1->pHNext: NULL;
+		}
+		else if ( !pLit1 && pLit2 )
+		{ // this literal is present in pCubeRem - remove it
+            // mark the affected var
+            if ( pLit2->pVar->pOrder == NULL )
+                Fxu_MatrixRingVarsAdd( p, pLit2->pVar );
+            // delete this literal
+			Fxu_MatrixDelLiteral( p, pLit2 );
+			// step to the next literals
+			pLit2     = bLit2Next;
+			bLit2Next = pLit2? pLit2->pHNext: NULL;
+		}
+		else
+			break;
+	}
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the matrix after selecting a single cube divisor.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_UpdateMatrixSingleClean( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, Fxu_Var * pVarNew )
+{
+	Fxu_Lit * pLit1, * bLit1Next;
+	Fxu_Lit * pLit2, * bLit2Next;
+
+    // initialize the starting literals
+	pLit1     = pVar1->lLits.pHead;
+	pLit2     = pVar2->lLits.pHead;
+	bLit1Next = pLit1? pLit1->pVNext: NULL;
+	bLit2Next = pLit2? pLit2->pVNext: NULL;
+	while ( 1 )
+	{
+		if ( pLit1 && pLit2 )
+		{
+    		if ( pLit1->pCube->pVar->iVar == pLit2->pCube->pVar->iVar )
+			{ // these literals coincide 
+			    if ( pLit1->iCube == pLit2->iCube )
+			    { // these literals coincide 
+                
+                    // collect the affected cube
+                    assert( pLit1->pCube->pOrder == NULL );
+                    Fxu_MatrixRingCubesAdd( p, pLit1->pCube );
+
+                    // add the literal to this cube corresponding to the new column
+		            Fxu_MatrixAddLiteral( p, pLit1->pCube, pVarNew );
+                    // clean the old cubes
+		            Fxu_UpdateCleanOldDoubles( p, NULL, pLit1->pCube );
+
+				    // remove the literals 
+				    Fxu_MatrixDelLiteral( p, pLit1 );
+				    Fxu_MatrixDelLiteral( p, pLit2 );
+
+				    // go to the next literals
+				    pLit1     = bLit1Next;
+				    pLit2     = bLit2Next;
+				    bLit1Next = pLit1? pLit1->pVNext: NULL;
+				    bLit2Next = pLit2? pLit2->pVNext: NULL;
+			    }
+			    else if ( pLit1->iCube < pLit2->iCube )
+			    {
+				    pLit1     = bLit1Next;
+				    bLit1Next = pLit1? pLit1->pVNext: NULL;
+			    }
+			    else
+			    {
+				    pLit2     = bLit2Next;
+				    bLit2Next = pLit2? pLit2->pVNext: NULL;
+			    }
+            }
+			else if ( pLit1->pCube->pVar->iVar < pLit2->pCube->pVar->iVar )
+			{
+				pLit1     = bLit1Next;
+				bLit1Next = pLit1? pLit1->pVNext: NULL;
+			}
+			else
+			{
+				pLit2     = bLit2Next;
+				bLit2Next = pLit2? pLit2->pVNext: NULL;
+			}
+		}
+		else if ( pLit1 && !pLit2 )
+		{
+			pLit1     = bLit1Next;
+			bLit1Next = pLit1? pLit1->pVNext: NULL;
+		}
+		else if ( !pLit1 && pLit2 )
+		{
+			pLit2     = bLit2Next;
+			bLit2Next = pLit2? pLit2->pVNext: NULL;
+		}
+		else
+			break;
+	}
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sort the pairs.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_UpdatePairsSort( Fxu_Matrix * p, Fxu_Double * pDouble )
+{
+    Fxu_Pair * pPair;
+    // order the pairs by the first cube to ensure that new literals are added 
+    // to the matrix from top to bottom - collect pairs into the array
+    p->vPairs->nSize = 0;
+	Fxu_DoubleForEachPair( pDouble, pPair )
+        Vec_PtrPush( p->vPairs, pPair );
+    if ( p->vPairs->nSize < 2 )
+        return;
+    // sort
+    qsort( (void *)p->vPairs->pArray, p->vPairs->nSize, sizeof(Fxu_Pair *), 
+        (int (*)(const void *, const void *)) Fxu_UpdatePairCompare );
+    assert( Fxu_UpdatePairCompare( (Fxu_Pair**)p->vPairs->pArray, (Fxu_Pair**)p->vPairs->pArray + p->vPairs->nSize - 1 ) < 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the vars by their number.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fxu_UpdatePairCompare( Fxu_Pair ** ppP1, Fxu_Pair ** ppP2 )
+{
+    Fxu_Cube * pC1 = (*ppP1)->pCube1;
+    Fxu_Cube * pC2 = (*ppP2)->pCube1;
+    int iP1CubeMin, iP2CubeMin;
+    if ( pC1->pVar->iVar < pC2->pVar->iVar )
+        return -1;
+    if ( pC1->pVar->iVar > pC2->pVar->iVar )
+        return 1;
+    iP1CubeMin = Fxu_PairMinCubeInt( *ppP1 );
+    iP2CubeMin = Fxu_PairMinCubeInt( *ppP2 );
+    if ( iP1CubeMin < iP2CubeMin )
+        return -1;
+    if ( iP1CubeMin > iP2CubeMin )
+        return 1;
+    assert( 0 );
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Create new variables.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_UpdateCreateNewVars( Fxu_Matrix * p, Fxu_Var ** ppVarC, Fxu_Var ** ppVarD, int nCubes )
+{
+    Fxu_Var * pVarC, * pVarD;
+
+	// add a new column for the complement
+	pVarC = Fxu_MatrixAddVar( p );
+    pVarC->nCubes = 0;
+	// add a new column for the divisor
+	pVarD = Fxu_MatrixAddVar( p );
+    pVarD->nCubes = nCubes;
+
+    // mark this entry in the Value2Node array
+//    assert( p->pValue2Node[pVarC->iVar] > 0 );
+//    p->pValue2Node[pVarD->iVar  ] = p->pValue2Node[pVarC->iVar];
+//    p->pValue2Node[pVarD->iVar+1] = p->pValue2Node[pVarC->iVar]+1;
+
+    *ppVarC = pVarC;
+    *ppVarD = pVarD;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_UpdateCleanOldDoubles( Fxu_Matrix * p, Fxu_Double * pDiv, Fxu_Cube * pCube )
+{
+    Fxu_Double * pDivCur;
+	Fxu_Pair * pPair;
+    int i;
+
+    // if the cube is a recently introduced one
+    // it does not have pairs allocated
+    // in this case, there is nothing to update
+    if ( pCube->pVar->ppPairs == NULL )
+        return;
+
+	// go through all the pairs of this cube
+	Fxu_CubeForEachPair( pCube, pPair, i )
+	{
+         // get the divisor of this pair
+        pDivCur = pPair->pDiv;
+		// skip the current divisor
+		if ( pDivCur == pDiv )
+			continue;
+		// remove this pair
+	    Fxu_ListDoubleDelPair( pDivCur, pPair );	
+		// the divisor may have become useless by now
+		if ( pDivCur->lPairs.nItems == 0 )
+        {
+            assert( pDivCur->Weight == pPair->nBase - 1 );
+      		Fxu_HeapDoubleDelete( p->pHeapDouble, pDivCur );
+			Fxu_MatrixDelDivisor( p, pDivCur );
+        }
+        else
+        {
+	        // update the divisor's weight
+	        pDivCur->Weight -= pPair->nLits1 + pPair->nLits2 - 1 + pPair->nBase;
+      	    Fxu_HeapDoubleUpdate( p->pHeapDouble, pDivCur );
+        }
+		MEM_FREE_FXU( p, Fxu_Pair, 1, pPair );
+	}
+	// finally erase all the pair info associated with this cube
+	Fxu_PairClearStorage( pCube );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the new divisors that depend on the cube.]
+
+  Description [Go through all the non-empty cubes of this cover 
+  (except the given cube) and, for each of them, add the new divisor 
+  with the given cube.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_UpdateAddNewDoubles( Fxu_Matrix * p, Fxu_Cube * pCube )
+{
+	Fxu_Cube * pTemp;
+    assert( pCube->pOrder );
+
+    // if the cube is a recently introduced one
+    // it does not have pairs allocated
+    // in this case, there is nothing to update
+    if ( pCube->pVar->ppPairs == NULL )
+        return;
+
+	for ( pTemp = pCube->pFirst; pTemp->pVar == pCube->pVar; pTemp = pTemp->pNext )
+    {
+        // do not add pairs with the empty cubes
+		if ( pTemp->lLits.nItems == 0 )
+            continue;
+        // to prevent adding duplicated pairs of the new cubes
+        // do not add the pair, if the current cube is marked 
+        if ( pTemp->pOrder && pTemp->iCube >= pCube->iCube )
+            continue;
+		Fxu_MatrixAddDivisor( p, pTemp, pCube );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes old single cube divisors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p )
+{ 
+    Fxu_Single * pSingle, * pSingle2;
+    int WeightNew;
+    int Counter = 0;
+
+    Fxu_MatrixForEachSingleSafe( p, pSingle, pSingle2 )
+    {
+        // if at least one of the variables is marked, recalculate
+        if ( pSingle->pVar1->pOrder || pSingle->pVar2->pOrder )
+        {
+            Counter++;
+            // get the new weight
+            WeightNew = -2 + Fxu_SingleCountCoincidence( p, pSingle->pVar1, pSingle->pVar2 );
+            if ( WeightNew >= 0 )
+            {
+                pSingle->Weight = WeightNew;
+                Fxu_HeapSingleUpdate( p->pHeapSingle, pSingle );
+            }
+            else
+            {
+                Fxu_HeapSingleDelete( p->pHeapSingle, pSingle );
+                Fxu_ListMatrixDelSingle( p, pSingle );
+		        MEM_FREE_FXU( p, Fxu_Single, 1, pSingle );
+            }
+        }
+    }
+//    printf( "Called procedure %d times.\n", Counter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the single cube divisors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fxu_UpdateAddNewSingles( Fxu_Matrix * p, Fxu_Var * pVar )
+{
+    Fxu_MatrixComputeSinglesOne( p, pVar );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/fxu/module.make b/abc-build/src/opt/fxu/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/fxu/module.make
@@ -0,0 +1,12 @@
+SRC +=  src/opt/fxu/fxu.c \
+	src/opt/fxu/fxuCreate.c \
+	src/opt/fxu/fxuHeapD.c \
+	src/opt/fxu/fxuHeapS.c \
+	src/opt/fxu/fxuList.c \
+	src/opt/fxu/fxuMatrix.c \
+	src/opt/fxu/fxuPair.c \
+	src/opt/fxu/fxuPrint.c \
+	src/opt/fxu/fxuReduce.c \
+	src/opt/fxu/fxuSelect.c \
+	src/opt/fxu/fxuSingle.c \
+	src/opt/fxu/fxuUpdate.c
diff --git a/abc-build/src/opt/lpk/lpk.h b/abc-build/src/opt/lpk/lpk.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/lpk/lpk.h
@@ -0,0 +1,88 @@
+/**CFile****************************************************************
+
+  FileName    [lpk.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast Boolean matching for LUT structures.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: lpk.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__opt__lpk__lpk_h
+#define ABC__opt__lpk__lpk_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Lpk_Par_t_ Lpk_Par_t;
+struct Lpk_Par_t_
+{
+    // user-controlled parameters
+    int               nLutsMax;      // (N) the maximum number of LUTs in the structure
+    int               nLutsOver;     // (Q) the maximum number of LUTs not in the MFFC
+    int               nVarsShared;   // (S) the maximum number of shared variables (crossbars)
+    int               nGrowthLevel;  // (L) the maximum increase in the node level after resynthesis
+    int               fSatur;        // iterate till saturation
+    int               fZeroCost;     // accept zero-cost replacements
+    int               fFirst;        // use root node and first cut only
+    int               fOldAlgo;      // use old algorithm
+    int               fVerbose;      // the verbosiness flag
+    int               fVeryVerbose;  // additional verbose info printout
+    // internal parameters
+    int               nLutSize;      // (K) the LUT size (determined by the input network)
+    int               nVarsMax;      // (V) the largest number of variables: V = N * (K-1) + 1
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                           ITERATORS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== lpkCore.c ========================================================*/
+extern int     Lpk_Resynthesize( Abc_Ntk_t * pNtk, Lpk_Par_t * pPars );
+
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/lpk/lpkAbcDec.c b/abc-build/src/opt/lpk/lpkAbcDec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/lpk/lpkAbcDec.c
@@ -0,0 +1,294 @@
+/**CFile****************************************************************
+
+  FileName    [lpkAbcDec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast Boolean matching for LUT structures.]
+
+  Synopsis    [The new core procedure.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: lpkAbcDec.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include "lpkInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Implements the function.]
+
+  Description [Returns the node implementing this function.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Lpk_ImplementFun( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * p )
+{
+    extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory );
+    unsigned * pTruth;
+    Abc_Obj_t * pObjNew;
+    int i;
+    if ( p->fMark )
+        pMan->nMuxes++;
+    else
+        pMan->nDsds++;
+    // create the new node
+    pObjNew = Abc_NtkCreateNode( pNtk );
+    for ( i = 0; i < (int)p->nVars; i++ )
+        Abc_ObjAddFanin( pObjNew, Abc_ObjRegular((Abc_Obj_t *)Vec_PtrEntry(vLeaves, p->pFanins[i])) );
+    Abc_ObjSetLevel( pObjNew, Abc_ObjLevelNew(pObjNew) );
+    // assign the node's function
+    pTruth = Lpk_FunTruth(p, 0);
+    if ( p->nVars == 0 )
+    {
+        pObjNew->pData = Hop_NotCond( Hop_ManConst1((Hop_Man_t *)pNtk->pManFunc), !(pTruth[0] & 1) );
+        return pObjNew;
+    }
+    if ( p->nVars == 1 )
+    {
+        pObjNew->pData = Hop_NotCond( Hop_ManPi((Hop_Man_t *)pNtk->pManFunc, 0), (pTruth[0] & 1) );
+        return pObjNew;
+    }
+    // create the logic function
+    pObjNew->pData = Kit_TruthToHop( (Hop_Man_t *)pNtk->pManFunc, pTruth, p->nVars, NULL );
+    return pObjNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements the function.]
+
+  Description [Returns the node implementing this function.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Lpk_Implement_rec( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * pFun )
+{
+    Abc_Obj_t * pFanin, * pRes;
+    int i;
+    // prepare the leaves of the function
+    for ( i = 0; i < (int)pFun->nVars; i++ )
+    {
+        pFanin = (Abc_Obj_t *)Vec_PtrEntry( vLeaves, pFun->pFanins[i] );
+        if ( !Abc_ObjIsComplement(pFanin) )
+            Lpk_Implement_rec( pMan, pNtk, vLeaves, (Lpk_Fun_t *)pFanin );
+        pFanin = (Abc_Obj_t *)Vec_PtrEntry( vLeaves, pFun->pFanins[i] );
+        assert( Abc_ObjIsComplement(pFanin) );
+    }
+    // construct the function
+    pRes = Lpk_ImplementFun( pMan, pNtk, vLeaves, pFun );
+    // replace the function
+    Vec_PtrWriteEntry( vLeaves, pFun->Id, Abc_ObjNot(pRes) );
+    Lpk_FunFree( pFun );
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements the function.]
+
+  Description [Returns the node implementing this function.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Lpk_Implement( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, int nLeavesOld )
+{
+    Abc_Obj_t * pFanin, * pRes;
+    int i;
+    assert( nLeavesOld < Vec_PtrSize(vLeaves) );
+    // mark implemented nodes
+    Vec_PtrForEachEntryStop( Abc_Obj_t *, vLeaves, pFanin, i, nLeavesOld )
+        Vec_PtrWriteEntry( vLeaves, i, Abc_ObjNot(pFanin) );
+    // recursively construct starting from the first entry
+    pRes = Lpk_Implement_rec( pMan, pNtk, vLeaves, (Lpk_Fun_t *)Vec_PtrEntry( vLeaves, nLeavesOld ) );
+    Vec_PtrShrink( vLeaves, nLeavesOld );
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Decomposes the function using recursive MUX decomposition.]
+
+  Description [Returns the ID of the top-most decomposition node 
+  implementing this function, or 0 if there is no decomposition satisfying
+  the constraints on area and delay.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Lpk_Decompose_rec( Lpk_Man_t * pMan, Lpk_Fun_t * p )
+{
+    Lpk_Res_t * pResMux, * pResDsd;
+    Lpk_Fun_t * p2;
+    abctime clk;
+
+    // is only called for non-trivial blocks
+    assert( p->nLutK >= 3 && p->nLutK <= 6 );
+    assert( p->nVars > p->nLutK );
+    // skip if area bound is exceeded
+    if ( Lpk_LutNumLuts(p->nVars, p->nLutK) > (int)p->nAreaLim )
+        return 0;
+    // skip if delay bound is exceeded
+    if ( Lpk_SuppDelay(p->uSupp, p->pDelays) > (int)p->nDelayLim )
+        return 0;
+
+    // compute supports if needed
+    if ( !p->fSupports )
+        Lpk_FunComputeCofSupps( p );
+
+    // check DSD decomposition
+clk = Abc_Clock();
+    pResDsd = Lpk_DsdAnalize( pMan, p, pMan->pPars->nVarsShared );
+pMan->timeEvalDsdAn += Abc_Clock() - clk;
+    if ( pResDsd && (pResDsd->nBSVars == (int)p->nLutK || pResDsd->nBSVars == (int)p->nLutK - 1) && 
+          pResDsd->AreaEst <= (int)p->nAreaLim && pResDsd->DelayEst <= (int)p->nDelayLim )
+    {
+clk = Abc_Clock();
+        p2 = Lpk_DsdSplit( pMan, p, pResDsd->pCofVars, pResDsd->nCofVars, pResDsd->BSVars );
+pMan->timeEvalDsdSp += Abc_Clock() - clk;
+        assert( p2->nVars <= (int)p->nLutK );
+        if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) )
+            return 0;
+        return 1;
+    }
+
+    // check MUX decomposition
+clk = Abc_Clock();
+    pResMux = Lpk_MuxAnalize( pMan, p );
+pMan->timeEvalMuxAn += Abc_Clock() - clk;
+//    pResMux = NULL;
+    assert( !pResMux || (pResMux->DelayEst <= (int)p->nDelayLim && pResMux->AreaEst <= (int)p->nAreaLim) );
+    // accept MUX decomposition if it is "good"
+    if ( pResMux && pResMux->nSuppSizeS <= (int)p->nLutK && pResMux->nSuppSizeL <= (int)p->nLutK )
+        pResDsd = NULL;
+    else if ( pResMux && pResDsd )
+    {
+        // compare two decompositions
+        if ( pResMux->AreaEst < pResDsd->AreaEst || 
+            (pResMux->AreaEst == pResDsd->AreaEst && pResMux->nSuppSizeL < pResDsd->nSuppSizeL) || 
+            (pResMux->AreaEst == pResDsd->AreaEst && pResMux->nSuppSizeL == pResDsd->nSuppSizeL && pResMux->DelayEst < pResDsd->DelayEst) )
+            pResDsd = NULL;
+        else
+            pResMux = NULL;
+    }
+    assert( pResMux == NULL || pResDsd == NULL );
+    if ( pResMux )
+    {
+clk = Abc_Clock();
+        p2 = Lpk_MuxSplit( pMan, p, pResMux->Variable, pResMux->Polarity );
+pMan->timeEvalMuxSp += Abc_Clock() - clk;
+        if ( p2->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p2 ) )
+            return 0;
+        if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) )
+            return 0;
+        return 1;
+    }
+    if ( pResDsd )
+    {
+clk = Abc_Clock();
+        p2 = Lpk_DsdSplit( pMan, p, pResDsd->pCofVars, pResDsd->nCofVars, pResDsd->BSVars );
+pMan->timeEvalDsdSp += Abc_Clock() - clk;
+        assert( p2->nVars <= (int)p->nLutK );
+        if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) )
+            return 0;
+        return 1;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes decomposed nodes from the array of fanins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lpk_DecomposeClean( Vec_Ptr_t * vLeaves, int nLeavesOld )
+{
+    Lpk_Fun_t * pFunc;
+    int i;
+    Vec_PtrForEachEntryStart( Lpk_Fun_t *, vLeaves, pFunc, i, nLeavesOld )
+        Lpk_FunFree( pFunc );
+    Vec_PtrShrink( vLeaves, nLeavesOld );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Decomposes the function using recursive MUX decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Lpk_Decompose( Lpk_Man_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, unsigned * puSupps, int nLutK, int AreaLim, int DelayLim )
+{
+    Lpk_Fun_t * pFun;
+    Abc_Obj_t * pObjNew = NULL;
+    int nLeaves = Vec_PtrSize( vLeaves );
+    pFun = Lpk_FunCreate( pNtk, vLeaves, pTruth, nLutK, AreaLim, DelayLim );
+    if ( puSupps[0] || puSupps[1] )
+    {
+/*
+        int i;
+        Lpk_FunComputeCofSupps( pFun );
+        for ( i = 0; i < nLeaves; i++ )
+        {
+            assert( pFun->puSupps[2*i+0] == puSupps[2*i+0] );
+            assert( pFun->puSupps[2*i+1] == puSupps[2*i+1] );
+        }
+*/
+        memcpy( pFun->puSupps, puSupps, sizeof(unsigned) * 2 * nLeaves );
+        pFun->fSupports = 1;
+    }
+    Lpk_FunSuppMinimize( pFun );
+    if ( pFun->nVars <= pFun->nLutK )
+        pObjNew = Lpk_ImplementFun( p, pNtk, vLeaves, pFun );
+    else if ( Lpk_Decompose_rec(p, pFun) )
+        pObjNew = Lpk_Implement( p, pNtk, vLeaves, nLeaves );
+    Lpk_DecomposeClean( vLeaves, nLeaves );
+    return pObjNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/lpk/lpkAbcDsd.c b/abc-build/src/opt/lpk/lpkAbcDsd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/lpk/lpkAbcDsd.c
@@ -0,0 +1,617 @@
+/**CFile****************************************************************
+
+  FileName    [lpkAbcDsd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast Boolean matching for LUT structures.]
+
+  Synopsis    [LUT-decomposition based on recursive DSD.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: lpkAbcDsd.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Cofactors TTs w.r.t. all vars and finds the best var.]
+
+  Description [The best variable is the variable with the minimum 
+  sum total of the support sizes of all truth tables. This procedure 
+  computes and returns cofactors w.r.t. the best variable.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Lpk_FunComputeMinSuppSizeVar( Lpk_Fun_t * p, unsigned ** ppTruths, int nTruths, unsigned ** ppCofs, unsigned uNonDecSupp )
+{
+    int i, Var, VarBest, nSuppSize0, nSuppSize1;
+    int nSuppTotalMin = -1; // Suppress "might be used uninitialized"
+    int nSuppTotalCur;
+    int nSuppMaxMin = -1; // Suppress "might be used uninitialized"
+    int nSuppMaxCur;
+    assert( nTruths > 0 );
+    VarBest = -1;
+    Lpk_SuppForEachVar( p->uSupp, Var )
+    {
+        if ( (uNonDecSupp & (1 << Var)) == 0 )
+            continue;
+        nSuppMaxCur = 0;
+        nSuppTotalCur = 0;
+        for ( i = 0; i < nTruths; i++ )
+        {
+            if ( nTruths == 1 )
+            {
+                nSuppSize0 = Kit_WordCountOnes( p->puSupps[2*Var+0] );
+                nSuppSize1 = Kit_WordCountOnes( p->puSupps[2*Var+1] );
+            }
+            else
+            {
+                Kit_TruthCofactor0New( ppCofs[2*i+0], ppTruths[i], p->nVars, Var );
+                Kit_TruthCofactor1New( ppCofs[2*i+1], ppTruths[i], p->nVars, Var );
+                nSuppSize0 = Kit_TruthSupportSize( ppCofs[2*i+0], p->nVars );
+                nSuppSize1 = Kit_TruthSupportSize( ppCofs[2*i+1], p->nVars );
+            }        
+            nSuppMaxCur = Abc_MaxInt( nSuppMaxCur, nSuppSize0 );
+            nSuppMaxCur = Abc_MaxInt( nSuppMaxCur, nSuppSize1 );
+            nSuppTotalCur += nSuppSize0 + nSuppSize1;
+        }
+        if ( VarBest == -1 || nSuppMaxMin > nSuppMaxCur ||
+             (nSuppMaxMin == nSuppMaxCur && nSuppTotalMin > nSuppTotalCur) )
+        {
+            VarBest = Var;
+            nSuppMaxMin = nSuppMaxCur;
+            nSuppTotalMin = nSuppTotalCur;
+        }
+    }
+    // recompute cofactors for the best var
+    for ( i = 0; i < nTruths; i++ )
+    {
+        Kit_TruthCofactor0New( ppCofs[2*i+0], ppTruths[i], p->nVars, VarBest );
+        Kit_TruthCofactor1New( ppCofs[2*i+1], ppTruths[i], p->nVars, VarBest );
+    }
+    return VarBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively computes decomposable subsets.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Lpk_ComputeBoundSets_rec( Kit_DsdNtk_t * p, int iLit, Vec_Int_t * vSets, int nSizeMax )
+{
+    unsigned i, iLitFanin, uSupport, uSuppCur;
+    Kit_DsdObj_t * pObj;
+    // consider the case of simple gate
+    pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) );
+    if ( pObj == NULL )
+        return (1 << Abc_Lit2Var(iLit));
+    if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR )
+    {
+        unsigned uSupps[16], Limit, s;
+        uSupport = 0;
+        Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i )
+        {
+            uSupps[i] = Lpk_ComputeBoundSets_rec( p, iLitFanin, vSets, nSizeMax );
+            uSupport |= uSupps[i];
+        }
+        // create all subsets, except empty and full
+        Limit = (1 << pObj->nFans) - 1;
+        for ( s = 1; s < Limit; s++ )
+        {
+            uSuppCur = 0;
+            for ( i = 0; i < pObj->nFans; i++ )
+                if ( s & (1 << i) )
+                    uSuppCur |= uSupps[i];
+            if ( Kit_WordCountOnes(uSuppCur) <= nSizeMax )
+                Vec_IntPush( vSets, uSuppCur );
+        }
+        return uSupport;
+    }
+    assert( pObj->Type == KIT_DSD_PRIME );
+    // get the cumulative support of all fanins
+    uSupport = 0;
+    Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i )
+    {
+        uSuppCur  = Lpk_ComputeBoundSets_rec( p, iLitFanin, vSets, nSizeMax );
+        uSupport |= uSuppCur;
+        if ( Kit_WordCountOnes(uSuppCur) <= nSizeMax )
+            Vec_IntPush( vSets, uSuppCur );
+    }
+    return uSupport;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the set of subsets of decomposable variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Lpk_ComputeBoundSets( Kit_DsdNtk_t * p, int nSizeMax )
+{
+    Vec_Int_t * vSets;
+    unsigned uSupport, Entry;
+    int Number, i;
+    assert( p->nVars <= 16 );
+    vSets = Vec_IntAlloc( 100 );
+    Vec_IntPush( vSets, 0 );
+    if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 )
+        return vSets;
+    if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR )
+    {
+        uSupport = ( 1 << Abc_Lit2Var(Kit_DsdNtkRoot(p)->pFans[0]) );
+        if ( Kit_WordCountOnes(uSupport) <= nSizeMax )
+            Vec_IntPush( vSets, uSupport );
+        return vSets;
+    }
+    uSupport = Lpk_ComputeBoundSets_rec( p, p->Root, vSets, nSizeMax );
+    assert( (uSupport & 0xFFFF0000) == 0 );
+    // add the total support of the network
+    if ( Kit_WordCountOnes(uSupport) <= nSizeMax )
+        Vec_IntPush( vSets, uSupport );
+    // set the remaining variables
+    Vec_IntForEachEntry( vSets, Number, i )
+    {
+        Entry = Number;
+        Vec_IntWriteEntry( vSets, i, Entry | ((uSupport & ~Entry) << 16) );
+    }
+    return vSets;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the sets of subsets.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Lpk_PrintSetOne( int uSupport )
+{
+    unsigned k;
+    for ( k = 0; k < 16; k++ )
+        if ( uSupport & (1<<k) )
+            printf( "%c", 'a'+k );
+    printf( " " );
+}
+/**Function*************************************************************
+
+  Synopsis    [Prints the sets of subsets.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Lpk_PrintSets( Vec_Int_t * vSets )
+{
+    unsigned uSupport;
+    int Number, i;
+    printf( "Subsets(%d): ", Vec_IntSize(vSets) );
+    Vec_IntForEachEntry( vSets, Number, i )
+    {
+        uSupport = Number;
+        Lpk_PrintSetOne( uSupport );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two bound sets.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Lpk_MergeBoundSets( Vec_Int_t * vSets0, Vec_Int_t * vSets1, int nSizeMax )
+{
+    Vec_Int_t * vSets;
+    int Entry0, Entry1, Entry;
+    int i, k;
+    vSets = Vec_IntAlloc( 100 );
+    Vec_IntForEachEntry( vSets0, Entry0, i )
+    Vec_IntForEachEntry( vSets1, Entry1, k )
+    {
+        Entry = Entry0 | Entry1;
+        if ( (Entry & (Entry >> 16)) )
+            continue;
+        if ( Kit_WordCountOnes(Entry & 0xffff) <= nSizeMax )
+            Vec_IntPush( vSets, Entry );
+    }
+    return vSets;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DSD-based decomposition of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lpk_FunCompareBoundSets( Lpk_Fun_t * p, Vec_Int_t * vBSets, int nCofDepth, unsigned uNonDecSupp, unsigned uLateArrSupp, Lpk_Res_t * pRes )
+{
+    int fVerbose = 0;
+    unsigned uBoundSet;
+    int i, nVarsBS, nVarsRem, Delay, Area;
+
+    // compare the resulting boundsets
+    memset( pRes, 0, sizeof(Lpk_Res_t) );
+    Vec_IntForEachEntry( vBSets, uBoundSet, i )
+    {
+        if ( (uBoundSet & 0xFFFF) == 0 ) // skip empty boundset
+            continue;
+        if ( (uBoundSet & uNonDecSupp) == 0 ) // skip those boundsets that are not in the domain of interest
+            continue;
+        if ( (uBoundSet & uLateArrSupp) ) // skip those boundsets that are late arriving
+            continue;
+if ( fVerbose )
+{
+Lpk_PrintSetOne( uBoundSet & 0xFFFF );
+//printf( "\n" );
+//Lpk_PrintSetOne( uBoundSet >> 16 );
+//printf( "\n" );
+}
+        assert( (uBoundSet & (uBoundSet >> 16)) == 0 );
+        nVarsBS = Kit_WordCountOnes( uBoundSet & 0xFFFF );
+        if ( nVarsBS == 1 )
+            continue;
+        assert( nVarsBS <= (int)p->nLutK - nCofDepth );
+        nVarsRem = p->nVars - nVarsBS + 1;
+        Area = 1 + Lpk_LutNumLuts( nVarsRem, p->nLutK );
+        Delay = 1 + Lpk_SuppDelay( uBoundSet & 0xFFFF, p->pDelays );
+if ( fVerbose )
+printf( "area = %d limit = %d  delay = %d limit = %d\n", Area, (int)p->nAreaLim, Delay, (int)p->nDelayLim );
+        if ( Area > (int)p->nAreaLim || Delay > (int)p->nDelayLim )
+            continue;
+        if ( pRes->BSVars == 0 || pRes->nSuppSizeL > nVarsRem || (pRes->nSuppSizeL == nVarsRem && pRes->DelayEst > Delay) )
+        {
+            pRes->nBSVars = nVarsBS;
+            pRes->BSVars = (uBoundSet & 0xFFFF);
+            pRes->nSuppSizeS = nVarsBS + nCofDepth;
+            pRes->nSuppSizeL = nVarsRem;
+            pRes->DelayEst = Delay;
+            pRes->AreaEst = Area;
+        }
+    }
+if ( fVerbose )
+{
+if ( pRes->BSVars )
+{
+printf( "Found bound set " );
+Lpk_PrintSetOne( pRes->BSVars );
+printf( "\n" );
+}
+else
+printf( "Did not find boundsets.\n" );
+printf( "\n" );
+}
+    if ( pRes->BSVars )
+    {
+        assert( pRes->DelayEst <= (int)p->nDelayLim );
+        assert( pRes->AreaEst <= (int)p->nAreaLim );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds late arriving inputs, which cannot be in the bound set.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Lpk_DsdLateArriving( Lpk_Fun_t * p )
+{
+    unsigned i, uLateArrSupp = 0;
+    Lpk_SuppForEachVar( p->uSupp, i )
+        if ( p->pDelays[i] > (int)p->nDelayLim - 2 )
+            uLateArrSupp |= (1 << i);  
+    return uLateArrSupp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DSD-based decomposition of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Lpk_DsdAnalizeOne( Lpk_Fun_t * p, unsigned * ppTruths[5][16], Kit_DsdNtk_t * pNtks[], char pCofVars[], int nCofDepth, Lpk_Res_t * pRes )
+{
+    int fVerbose = 0;
+    Vec_Int_t * pvBSets[4][8];
+    unsigned uNonDecSupp, uLateArrSupp;
+    int i, k, nNonDecSize, nNonDecSizeMax;
+    assert( nCofDepth >= 1 && nCofDepth <= 3 );
+    assert( nCofDepth < (int)p->nLutK - 1 );
+    assert( p->fSupports );
+
+    // find the support of the largest non-DSD block
+    nNonDecSizeMax = 0;
+    uNonDecSupp = p->uSupp;
+    for ( i = 0; i < (1<<(nCofDepth-1)); i++ )
+    {
+        nNonDecSize = Kit_DsdNonDsdSizeMax( pNtks[i] );
+        if ( nNonDecSizeMax < nNonDecSize )
+        {
+            nNonDecSizeMax = nNonDecSize;
+            uNonDecSupp = Kit_DsdNonDsdSupports( pNtks[i] );
+        }
+        else if ( nNonDecSizeMax == nNonDecSize )
+            uNonDecSupp |= Kit_DsdNonDsdSupports( pNtks[i] );
+    }
+
+    // remove those variables that cannot be used because of delay constraints
+    // if variables arrival time is more than p->DelayLim - 2, it cannot be used
+    uLateArrSupp = Lpk_DsdLateArriving( p );
+    if ( (uNonDecSupp & ~uLateArrSupp) == 0 )
+    {
+        memset( pRes, 0, sizeof(Lpk_Res_t) );
+        return 0;
+    }
+
+    // find the next cofactoring variable
+    pCofVars[nCofDepth-1] = Lpk_FunComputeMinSuppSizeVar( p, ppTruths[nCofDepth-1], 1<<(nCofDepth-1), ppTruths[nCofDepth], uNonDecSupp & ~uLateArrSupp );
+
+    // derive decomposed networks
+    for ( i = 0; i < (1<<nCofDepth); i++ )
+    {
+        if ( pNtks[i] )
+            Kit_DsdNtkFree( pNtks[i] );
+        pNtks[i] = Kit_DsdDecomposeExpand( ppTruths[nCofDepth][i], p->nVars );
+if ( fVerbose )
+Kit_DsdPrint( stdout, pNtks[i] );
+        pvBSets[nCofDepth][i] = Lpk_ComputeBoundSets( pNtks[i], p->nLutK - nCofDepth ); // try restricting to those in uNonDecSupp!!!
+    }
+
+    // derive the set of feasible boundsets
+    for ( i = nCofDepth - 1; i >= 0; i-- )
+        for ( k = 0; k < (1<<i); k++ )
+            pvBSets[i][k] = Lpk_MergeBoundSets( pvBSets[i+1][2*k+0], pvBSets[i+1][2*k+1], p->nLutK - nCofDepth );
+    // compare bound-sets
+    Lpk_FunCompareBoundSets( p, pvBSets[0][0], nCofDepth, uNonDecSupp, uLateArrSupp, pRes );
+    // free the bound sets
+    for ( i = nCofDepth; i >= 0; i-- )
+        for ( k = 0; k < (1<<i); k++ )
+            Vec_IntFree( pvBSets[i][k] );
+ 
+    // copy the cofactoring variables
+    if ( pRes->BSVars )
+    {
+        pRes->nCofVars = nCofDepth;
+        for ( i = 0; i < nCofDepth; i++ )
+            pRes->pCofVars[i] = pCofVars[i];
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DSD-based decomposition of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Lpk_Res_t * Lpk_DsdAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p, int nShared )
+{ 
+    static Lpk_Res_t Res0, * pRes0 = &Res0;
+    static Lpk_Res_t Res1, * pRes1 = &Res1;
+    static Lpk_Res_t Res2, * pRes2 = &Res2;
+    static Lpk_Res_t Res3, * pRes3 = &Res3;
+    int fUseBackLooking = 1;
+    Lpk_Res_t * pRes = NULL;
+    Vec_Int_t * vBSets;
+    Kit_DsdNtk_t * pNtks[8] = {NULL};
+    char pCofVars[5];
+    int i;
+
+    assert( p->nLutK >= 3 );
+    assert( nShared >= 0 && nShared <= 3 );
+    assert( p->uSupp == Kit_BitMask(p->nVars) );
+
+    // try decomposition without cofactoring
+    pNtks[0] = Kit_DsdDecomposeExpand( Lpk_FunTruth( p, 0 ), p->nVars );
+    if ( pMan->pPars->fVerbose )
+        pMan->nBlocks[ Kit_DsdNonDsdSizeMax(pNtks[0]) ]++;
+    vBSets = Lpk_ComputeBoundSets( pNtks[0], p->nLutK );
+    Lpk_FunCompareBoundSets( p, vBSets, 0, 0xFFFF, Lpk_DsdLateArriving(p), pRes0 );
+    Vec_IntFree( vBSets );
+
+    // check the result
+    if ( pRes0->nBSVars == (int)p->nLutK )
+        { pRes = pRes0; goto finish; }
+    if ( pRes0->nBSVars == (int)p->nLutK - 1 )
+        { pRes = pRes0; goto finish; }
+    if ( nShared == 0 )
+        goto finish;
+
+    // prepare storage
+    Kit_TruthCopy( pMan->ppTruths[0][0], Lpk_FunTruth( p, 0 ), p->nVars );
+
+    // cofactor 1 time
+    if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 1, pRes1 ) )
+        goto finish;
+    assert( pRes1->nBSVars <= (int)p->nLutK - 1 );
+    if ( pRes1->nBSVars == (int)p->nLutK - 1 )
+        { pRes = pRes1; goto finish; }
+    if ( pRes0->nBSVars == (int)p->nLutK - 2 )
+        { pRes = pRes0; goto finish; }
+    if ( pRes1->nBSVars == (int)p->nLutK - 2 )
+        { pRes = pRes1; goto finish; }
+    if ( nShared == 1 )
+        goto finish;
+
+    // cofactor 2 times
+    if ( p->nLutK >= 4 ) 
+    {
+        if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 2, pRes2 ) )
+            goto finish;
+        assert( pRes2->nBSVars <= (int)p->nLutK - 2 );
+        if ( pRes2->nBSVars == (int)p->nLutK - 2 )
+            { pRes = pRes2; goto finish; }
+        if ( fUseBackLooking )
+        {
+            if ( pRes0->nBSVars == (int)p->nLutK - 3 )
+                { pRes = pRes0; goto finish; }
+            if ( pRes1->nBSVars == (int)p->nLutK - 3 )
+                { pRes = pRes1; goto finish; }
+        }
+        if ( pRes2->nBSVars == (int)p->nLutK - 3 )
+            { pRes = pRes2; goto finish; }
+        if ( nShared == 2 )
+            goto finish;
+        assert( nShared == 3 );
+    }
+
+    // cofactor 3 times
+    if ( p->nLutK >= 5 ) 
+    {
+        if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 3, pRes3 ) )
+            goto finish;
+        assert( pRes3->nBSVars <= (int)p->nLutK - 3 );
+        if ( pRes3->nBSVars == (int)p->nLutK - 3 )
+            { pRes = pRes3; goto finish; }
+        if ( fUseBackLooking )
+        {
+            if ( pRes0->nBSVars == (int)p->nLutK - 4 )
+                { pRes = pRes0; goto finish; }
+            if ( pRes1->nBSVars == (int)p->nLutK - 4 )
+                { pRes = pRes1; goto finish; }
+            if ( pRes2->nBSVars == (int)p->nLutK - 4 )
+                { pRes = pRes2; goto finish; }
+        }
+        if ( pRes3->nBSVars == (int)p->nLutK - 4 )
+            { pRes = pRes3; goto finish; }
+    }
+
+finish:
+    // free the networks
+    for ( i = 0; i < (1<<nShared); i++ )
+        if ( pNtks[i] )
+            Kit_DsdNtkFree( pNtks[i] );
+    // choose the best under these conditions
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Splits the function into two subfunctions using DSD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Lpk_Fun_t * Lpk_DsdSplit( Lpk_Man_t * pMan, Lpk_Fun_t * p, char * pCofVars, int nCofVars, unsigned uBoundSet )
+{
+    Lpk_Fun_t * pNew;
+    Kit_DsdNtk_t * pNtkDec;
+    int i, k, iVacVar, nCofs;
+    // prepare storage
+    Kit_TruthCopy( pMan->ppTruths[0][0], Lpk_FunTruth(p, 0), p->nVars );
+    // get the vacuous variable
+    iVacVar = Kit_WordFindFirstBit( uBoundSet );
+    // compute the cofactors
+    for ( i = 0; i < nCofVars; i++ )
+        for ( k = 0; k < (1<<i); k++ )
+        {
+            Kit_TruthCofactor0New( pMan->ppTruths[i+1][2*k+0], pMan->ppTruths[i][k], p->nVars, pCofVars[i] );
+            Kit_TruthCofactor1New( pMan->ppTruths[i+1][2*k+1], pMan->ppTruths[i][k], p->nVars, pCofVars[i] );
+        }
+    // decompose each cofactor w.r.t. the bound set
+    nCofs = (1<<nCofVars);
+    for ( k = 0; k < nCofs; k++ )
+    {
+        pNtkDec = Kit_DsdDecomposeExpand( pMan->ppTruths[nCofVars][k], p->nVars );
+        Kit_DsdTruthPartialTwo( pMan->pDsdMan, pNtkDec, uBoundSet, iVacVar, pMan->ppTruths[nCofVars+1][k], pMan->ppTruths[nCofVars+1][nCofs+k] );
+        Kit_DsdNtkFree( pNtkDec );
+    }
+    // compute the composition/decomposition functions (they will be in pMan->ppTruths[1][0]/pMan->ppTruths[1][1])
+    for ( i = nCofVars; i >= 1; i-- )
+        for ( k = 0; k < (1<<i); k++ )
+            Kit_TruthMuxVar( pMan->ppTruths[i][k], pMan->ppTruths[i+1][2*k+0], pMan->ppTruths[i+1][2*k+1], p->nVars, pCofVars[i-1] );
+
+    // derive the new component (decomposition function)
+    pNew = Lpk_FunDup( p, pMan->ppTruths[1][1] );
+    // update the old component (composition function)
+    Kit_TruthCopy( Lpk_FunTruth(p, 0), pMan->ppTruths[1][0], p->nVars );
+    p->uSupp = Kit_TruthSupport( Lpk_FunTruth(p, 0), p->nVars );
+    p->pFanins[iVacVar] = pNew->Id;
+    p->pDelays[iVacVar] = Lpk_SuppDelay( pNew->uSupp, pNew->pDelays );
+    // support minimize both
+    p->fSupports = 0;
+    Lpk_FunSuppMinimize( p );
+    Lpk_FunSuppMinimize( pNew );
+    // update delay and area requirements
+    pNew->nDelayLim = p->pDelays[iVacVar];
+    pNew->nAreaLim = 1;
+    p->nAreaLim = p->nAreaLim - 1;
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/lpk/lpkAbcMux.c b/abc-build/src/opt/lpk/lpkAbcMux.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/lpk/lpkAbcMux.c
@@ -0,0 +1,240 @@
+/**CFile****************************************************************
+
+  FileName    [lpkAbcMux.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast Boolean matching for LUT structures.]
+
+  Synopsis    [LUT-decomposition based on recursive MUX decomposition.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: lpkAbcMux.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the possibility of MUX decomposition.]
+
+  Description [Returns the best variable to use for MUX decomposition.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Lpk_Res_t * Lpk_MuxAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p )
+{
+    static Lpk_Res_t Res, * pRes = &Res;
+    int nSuppSize0, nSuppSize1, nSuppSizeS, nSuppSizeL;
+    int Var, Area, Polarity, Delay, Delay0, Delay1, DelayA, DelayB;
+    memset( pRes, 0, sizeof(Lpk_Res_t) );
+    assert( p->uSupp == Kit_BitMask(p->nVars) );
+    assert( p->fSupports );
+    // derive the delay and area after MUX-decomp with each var - and find the best var
+    pRes->Variable = -1;
+    Lpk_SuppForEachVar( p->uSupp, Var )
+    {
+        nSuppSize0 = Kit_WordCountOnes(p->puSupps[2*Var+0]);
+        nSuppSize1 = Kit_WordCountOnes(p->puSupps[2*Var+1]);
+        assert( nSuppSize0 < (int)p->nVars );
+        assert( nSuppSize1 < (int)p->nVars );
+        if ( nSuppSize0 < 1 || nSuppSize1 < 1 )
+            continue;
+//printf( "%d %d    ", nSuppSize0, nSuppSize1 );
+        if ( nSuppSize0 <= (int)p->nLutK - 2 && nSuppSize1 <= (int)p->nLutK - 2 )
+        {
+            // include cof var into 0-block
+            DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<<Var), p->pDelays );
+            DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1]           , p->pDelays );
+            Delay0 = Abc_MaxInt( DelayA, DelayB + 1 );
+            // include cof var into 1-block
+            DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<<Var), p->pDelays );
+            DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0]           , p->pDelays );
+            Delay1 = Abc_MaxInt( DelayA, DelayB + 1 );
+            // get the best delay
+            Delay = Abc_MinInt( Delay0, Delay1 );
+            Area = 2;
+            Polarity = (int)(Delay == Delay1);
+        }
+        else if ( nSuppSize0 <= (int)p->nLutK - 2 )
+        {
+            DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<<Var), p->pDelays );
+            DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1]           , p->pDelays );
+            Delay = Abc_MaxInt( DelayA, DelayB + 1 );
+            Area = 1 + Lpk_LutNumLuts( nSuppSize1, p->nLutK );
+            Polarity = 0;
+        }
+        else if ( nSuppSize1 <= (int)p->nLutK - 2 )
+        {
+            DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<<Var), p->pDelays );
+            DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0]           , p->pDelays );
+            Delay = Abc_MaxInt( DelayA, DelayB + 1 );
+            Area = 1 + Lpk_LutNumLuts( nSuppSize0, p->nLutK );
+            Polarity = 1;
+        }
+        else if ( nSuppSize0 <= (int)p->nLutK )
+        {
+            DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<<Var), p->pDelays );
+            DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0]           , p->pDelays );
+            Delay = Abc_MaxInt( DelayA, DelayB + 1 );
+            Area = 1 + Lpk_LutNumLuts( nSuppSize1+2, p->nLutK );
+            Polarity = 1;
+        }
+        else if ( nSuppSize1 <= (int)p->nLutK )
+        {
+            DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<<Var), p->pDelays );
+            DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1]           , p->pDelays );
+            Delay = Abc_MaxInt( DelayA, DelayB + 1 );
+            Area = 1 + Lpk_LutNumLuts( nSuppSize0+2, p->nLutK );
+            Polarity = 0;
+        }
+        else
+        {
+            // include cof var into 0-block
+            DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<<Var), p->pDelays );
+            DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1]           , p->pDelays );
+            Delay0 = Abc_MaxInt( DelayA, DelayB + 1 );
+            // include cof var into 1-block
+            DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<<Var), p->pDelays );
+            DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0]           , p->pDelays );
+            Delay1 = Abc_MaxInt( DelayA, DelayB + 1 );
+            // get the best delay
+            Delay = Abc_MinInt( Delay0, Delay1 );
+            if ( Delay == Delay0 )
+                Area = Lpk_LutNumLuts( nSuppSize0+2, p->nLutK ) + Lpk_LutNumLuts( nSuppSize1, p->nLutK );
+            else
+                Area = Lpk_LutNumLuts( nSuppSize1+2, p->nLutK ) + Lpk_LutNumLuts( nSuppSize0, p->nLutK );
+            Polarity = (int)(Delay == Delay1);
+        }
+        // find the best variable
+        if ( Delay > (int)p->nDelayLim )
+            continue;
+        if ( Area > (int)p->nAreaLim )
+            continue;
+        nSuppSizeS = Abc_MinInt( nSuppSize0 + 2 *!Polarity, nSuppSize1 + 2 * Polarity );
+        nSuppSizeL = Abc_MaxInt( nSuppSize0 + 2 *!Polarity, nSuppSize1 + 2 * Polarity );
+        if ( nSuppSizeL > (int)p->nVars )
+            continue;
+        if ( pRes->Variable == -1 || pRes->AreaEst > Area || 
+            (pRes->AreaEst == Area && pRes->nSuppSizeS + pRes->nSuppSizeL > nSuppSizeS + nSuppSizeL) || 
+            (pRes->AreaEst == Area && pRes->nSuppSizeS + pRes->nSuppSizeL == nSuppSizeS + nSuppSizeL && pRes->DelayEst > Delay) )
+        {
+            pRes->Variable = Var;
+            pRes->Polarity = Polarity;
+            pRes->AreaEst  = Area;
+            pRes->DelayEst = Delay;
+            pRes->nSuppSizeS = nSuppSizeS;
+            pRes->nSuppSizeL = nSuppSizeL;
+        }
+    }
+    return pRes->Variable == -1 ? NULL : pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the function decomposed by the MUX decomposition.]
+
+  Description [Returns the best variable to use for MUX decomposition.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Lpk_Fun_t * Lpk_MuxSplit( Lpk_Man_t * pMan, Lpk_Fun_t * p, int Var, int Pol )
+{
+    Lpk_Fun_t * pNew;
+    unsigned * pTruth  = Lpk_FunTruth( p, 0 );
+    unsigned * pTruth0 = Lpk_FunTruth( p, 1 );
+    unsigned * pTruth1 = Lpk_FunTruth( p, 2 );
+//    unsigned uSupp;
+    int iVarVac; 
+    assert( Var >= 0 && Var < (int)p->nVars );
+    assert( p->nAreaLim >= 2 );
+    assert( p->uSupp == Kit_BitMask(p->nVars) );
+    Kit_TruthCofactor0New( pTruth0, pTruth, p->nVars, Var );
+    Kit_TruthCofactor1New( pTruth1, pTruth, p->nVars, Var );
+/*
+uSupp = Kit_TruthSupport( pTruth, p->nVars );
+Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n" );
+uSupp = Kit_TruthSupport( pTruth0, p->nVars );
+Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n" );
+uSupp = Kit_TruthSupport( pTruth1, p->nVars );
+Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n\n" );
+*/
+    // derive the new component
+    pNew = Lpk_FunDup( p, Pol ? pTruth0 : pTruth1 );
+    // update the support of the old component
+    p->uSupp  = Kit_TruthSupport( Pol ? pTruth1 : pTruth0, p->nVars );
+    p->uSupp |= (1 << Var);
+    // update the truth table of the old component
+    iVarVac = Kit_WordFindFirstBit( ~p->uSupp );
+    assert( iVarVac < (int)p->nVars );
+    p->uSupp |= (1 << iVarVac);
+    Kit_TruthIthVar( pTruth, p->nVars, iVarVac );
+    if ( Pol )
+        Kit_TruthMuxVar( pTruth, pTruth, pTruth1, p->nVars, Var );
+    else
+        Kit_TruthMuxVar( pTruth, pTruth0, pTruth, p->nVars, Var );
+    assert( p->uSupp == Kit_TruthSupport(pTruth, p->nVars) );
+    // set the decomposed variable
+    p->pFanins[iVarVac] = pNew->Id;
+    p->pDelays[iVarVac] = p->nDelayLim - 1;
+    // support minimize both
+    p->fSupports = 0;
+    Lpk_FunSuppMinimize( p );
+    Lpk_FunSuppMinimize( pNew );
+    // update delay and area requirements
+    pNew->nDelayLim = p->nDelayLim - 1;
+    if ( pNew->nVars <= pNew->nLutK )
+    {
+        pNew->nAreaLim = 1;
+        p->nAreaLim = p->nAreaLim - 1;
+    }
+    else if ( p->nVars <= p->nLutK )
+    {
+        pNew->nAreaLim = p->nAreaLim - 1;
+        p->nAreaLim = 1;
+    }
+    else if ( p->nVars < pNew->nVars )
+    {
+        pNew->nAreaLim = p->nAreaLim / 2 + p->nAreaLim % 2;
+        p->nAreaLim = p->nAreaLim / 2 - p->nAreaLim % 2;
+    }
+    else // if ( pNew->nVars < p->nVars )
+    {
+        pNew->nAreaLim = p->nAreaLim / 2 - p->nAreaLim % 2;
+        p->nAreaLim = p->nAreaLim / 2 + p->nAreaLim % 2;
+    }
+    pNew->fMark = 1;
+    return pNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/lpk/lpkAbcUtil.c b/abc-build/src/opt/lpk/lpkAbcUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/lpk/lpkAbcUtil.c
@@ -0,0 +1,249 @@
+/**CFile****************************************************************
+
+  FileName    [lpkAbcUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast Boolean matching for LUT structures.]
+
+  Synopsis    [Procedures working on decomposed functions.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: lpkAbcUtil.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Lpk_Fun_t * Lpk_FunAlloc( int nVars )
+{
+    Lpk_Fun_t * p;
+    p = (Lpk_Fun_t *)ABC_ALLOC( char, sizeof(Lpk_Fun_t) + sizeof(unsigned) * Kit_TruthWordNum(nVars) * 3 );
+    memset( p, 0, sizeof(Lpk_Fun_t) );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the function]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lpk_FunFree( Lpk_Fun_t * p )
+{
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the starting function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Lpk_Fun_t * Lpk_FunCreate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, int nLutK, int AreaLim, int DelayLim )
+{
+    Lpk_Fun_t * p;
+    Abc_Obj_t * pNode;
+    int i;
+    p = Lpk_FunAlloc( Vec_PtrSize(vLeaves) );
+    p->Id = Vec_PtrSize(vLeaves);
+    p->vNodes = vLeaves;
+    p->nVars = Vec_PtrSize(vLeaves);
+    p->nLutK = nLutK;
+    p->nAreaLim = AreaLim;
+    p->nDelayLim = DelayLim;
+    p->uSupp = Kit_TruthSupport( pTruth, p->nVars );
+    Kit_TruthCopy( Lpk_FunTruth(p,0), pTruth, p->nVars );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i )
+    {
+        p->pFanins[i] = i;
+        p->pDelays[i] = pNode->Level;
+    }
+    Vec_PtrPush( p->vNodes, p );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the new function with the given truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Lpk_Fun_t * Lpk_FunDup( Lpk_Fun_t * p, unsigned * pTruth )
+{
+    Lpk_Fun_t * pNew;
+    pNew = Lpk_FunAlloc( p->nVars );
+    pNew->Id = Vec_PtrSize(p->vNodes);
+    pNew->vNodes = p->vNodes;
+    pNew->nVars = p->nVars;
+    pNew->nLutK = p->nLutK;
+    pNew->nAreaLim = p->nAreaLim;
+    pNew->nDelayLim = p->nDelayLim;
+    pNew->uSupp = Kit_TruthSupport( pTruth, p->nVars );
+    Kit_TruthCopy( Lpk_FunTruth(pNew,0), pTruth, p->nVars );
+    memcpy( pNew->pFanins, p->pFanins, 16 );
+    memcpy( pNew->pDelays, p->pDelays, 16 );
+    Vec_PtrPush( p->vNodes, pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Minimizes support of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Lpk_FunSuppMinimize( Lpk_Fun_t * p )
+{
+    int i, k, nVarsNew;
+    // compress the truth table
+    if ( p->uSupp == Kit_BitMask(p->nVars) )
+        return 0;
+    // invalidate support info
+    p->fSupports = 0;
+//Extra_PrintBinary( stdout, &p->uSupp, p->nVars ); printf( "\n" );
+    // minimize support
+    nVarsNew = Kit_WordCountOnes(p->uSupp);
+    Kit_TruthShrink( Lpk_FunTruth(p, 1), Lpk_FunTruth(p, 0), nVarsNew, p->nVars, p->uSupp, 1 );
+    k = 0;
+    Lpk_SuppForEachVar( p->uSupp, i )
+    {
+        p->pFanins[k] = p->pFanins[i];
+        p->pDelays[k] = p->pDelays[i];
+/*
+        if ( p->fSupports )
+        {
+            p->puSupps[2*k+0] = p->puSupps[2*i+0];
+            p->puSupps[2*k+1] = p->puSupps[2*i+1];
+        }
+*/
+        k++;
+    }
+    assert( k == nVarsNew );
+    p->nVars = k;
+    p->uSupp = Kit_BitMask(p->nVars);
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes cofactors w.r.t. each variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lpk_FunComputeCofSupps( Lpk_Fun_t * p )
+{
+    unsigned * pTruth  = Lpk_FunTruth( p, 0 );
+    unsigned * pTruth0 = Lpk_FunTruth( p, 1 );
+    unsigned * pTruth1 = Lpk_FunTruth( p, 2 );
+    int Var;
+    assert( p->fSupports == 0 );
+//    Lpk_SuppForEachVar( p->uSupp, Var )
+    for ( Var = 0; Var < (int)p->nVars; Var++ )
+    {
+        Kit_TruthCofactor0New( pTruth0, pTruth, p->nVars, Var );
+        Kit_TruthCofactor1New( pTruth1, pTruth, p->nVars, Var );
+        p->puSupps[2*Var+0] = Kit_TruthSupport( pTruth0, p->nVars );
+        p->puSupps[2*Var+1] = Kit_TruthSupport( pTruth1, p->nVars );
+    }
+    p->fSupports = 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Get the delay of the bound set.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Lpk_SuppDelay( unsigned uSupp, char * pDelays )
+{
+    int Delay, Var;
+    Delay = 0;
+    Lpk_SuppForEachVar( uSupp, Var )
+        Delay = Abc_MaxInt( Delay, pDelays[Var] );
+    return Delay + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts support into variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Lpk_SuppToVars( unsigned uBoundSet, char * pVars )
+{
+    int i, nVars = 0;
+    Lpk_SuppForEachVar( uBoundSet, i )
+        pVars[nVars++] = i;
+    return nVars;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/lpk/lpkCore.c b/abc-build/src/opt/lpk/lpkCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/lpk/lpkCore.c
@@ -0,0 +1,694 @@
+/**CFile****************************************************************
+
+  FileName    [lpkCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast Boolean matching for LUT structures.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: lpkCore.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include "lpkInt.h"
+#include "bool/kit/cloud.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the mapping manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lpk_IfManStart( Lpk_Man_t * p )
+{
+    If_Par_t * pPars;
+    assert( p->pIfMan == NULL );
+    // set defaults
+    pPars = ABC_ALLOC( If_Par_t, 1 );
+    memset( pPars, 0, sizeof(If_Par_t) );
+    // user-controlable paramters
+    pPars->nLutSize    =  p->pPars->nLutSize;
+    pPars->nCutsMax    = 16;
+    pPars->nFlowIters  =  0; // 1
+    pPars->nAreaIters  =  0; // 1 
+    pPars->DelayTarget = -1;
+    pPars->Epsilon     =  (float)0.005;
+    pPars->fPreprocess =  0;
+    pPars->fArea       =  1;
+    pPars->fFancy      =  0;
+    pPars->fExpRed     =  0; //
+    pPars->fLatchPaths =  0;
+    pPars->fVerbose    =  0;
+    // internal parameters
+    pPars->fTruth      =  1;
+    pPars->fUsePerm    =  0; 
+    pPars->nLatchesCi  =  0;
+    pPars->nLatchesCo  =  0;
+    pPars->pLutLib     =  NULL; // Abc_FrameReadLibLut();
+    pPars->pTimesArr   =  NULL; 
+    pPars->pTimesArr   =  NULL;   
+    pPars->fUseBdds    =  0;
+    pPars->fUseSops    =  0;
+    pPars->fUseCnfs    =  0;
+    pPars->fUseMv      =  0;
+    // start the mapping manager and set its parameters
+    p->pIfMan = If_ManStart( pPars );
+    If_ManSetupSetAll( p->pIfMan, 1000 );
+    p->pIfMan->pPars->pTimesArr = ABC_ALLOC( float, 32 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if at least one entry has changed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Lpk_NodeHasChanged( Lpk_Man_t * p, int iNode )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pTemp;
+    int i;
+    vNodes = Vec_VecEntry( p->vVisited, iNode );
+    if ( Vec_PtrSize(vNodes) == 0 )
+        return 1;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pTemp, i )
+    {
+        // check if the node has changed
+        pTemp = Abc_NtkObj( p->pNtk, (int)(ABC_PTRUINT_T)pTemp );
+        if ( pTemp == NULL )
+            return 1;
+        // check if the number of fanouts has changed
+//        if ( Abc_ObjFanoutNum(pTemp) != (int)Vec_PtrEntry(vNodes, i+1) )
+//            return 1;
+        i++;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the mapping manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Lpk_ExploreCut( Lpk_Man_t * p, Lpk_Cut_t * pCut, Kit_DsdNtk_t * pNtk )
+{
+    extern Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover );
+    Kit_DsdObj_t * pRoot;
+    If_Obj_t * pDriver, * ppLeaves[16];
+    Abc_Obj_t * pLeaf, * pObjNew;
+    int nGain, i;
+    abctime clk;
+    int nNodesBef;
+//    int nOldShared;
+
+    // check special cases
+    pRoot = Kit_DsdNtkRoot( pNtk );
+    if ( pRoot->Type == KIT_DSD_CONST1 )
+    {
+        if ( Abc_LitIsCompl(pNtk->Root) )
+            pObjNew = Abc_NtkCreateNodeConst0( p->pNtk );
+        else
+            pObjNew = Abc_NtkCreateNodeConst1( p->pNtk );
+        Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels );
+        p->nGainTotal += pCut->nNodes - pCut->nNodesDup;
+        return 1;
+    }
+    if ( pRoot->Type == KIT_DSD_VAR )
+    {
+        pObjNew = Abc_NtkObj( p->pNtk, pCut->pLeaves[ Abc_Lit2Var(pRoot->pFans[0]) ] );
+        if ( Abc_LitIsCompl(pNtk->Root) ^ Abc_LitIsCompl(pRoot->pFans[0]) )
+            pObjNew = Abc_NtkCreateNodeInv( p->pNtk, pObjNew );
+        Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels );
+        p->nGainTotal += pCut->nNodes - pCut->nNodesDup;
+        return 1;
+    }
+    assert( pRoot->Type == KIT_DSD_AND || pRoot->Type == KIT_DSD_XOR || pRoot->Type == KIT_DSD_PRIME );
+
+    // start the mapping manager
+    if ( p->pIfMan == NULL )
+        Lpk_IfManStart( p );
+
+    // prepare the mapping manager
+    If_ManRestart( p->pIfMan );
+    // create the PI variables
+    for ( i = 0; i < p->pPars->nVarsMax; i++ )
+        ppLeaves[i] = If_ManCreateCi( p->pIfMan );
+    // set the arrival times
+    Lpk_CutForEachLeaf( p->pNtk, pCut, pLeaf, i )
+        p->pIfMan->pPars->pTimesArr[i] = (float)pLeaf->Level;
+    // prepare the PI cuts
+    If_ManSetupCiCutSets( p->pIfMan );
+    // create the internal nodes
+    p->fCalledOnce = 0;
+    p->nCalledSRed = 0;
+    pDriver = Lpk_MapTree_rec( p, pNtk, ppLeaves, pNtk->Root, NULL );
+    if ( pDriver == NULL )
+        return 0;
+    // create the PO node
+    If_ManCreateCo( p->pIfMan, If_Regular(pDriver) );
+
+    // perform mapping
+    p->pIfMan->pPars->fAreaOnly = 1;
+clk = Abc_Clock();
+    If_ManPerformMappingComb( p->pIfMan );
+p->timeMap += Abc_Clock() - clk;
+
+    // compute the gain in area
+    nGain = pCut->nNodes - pCut->nNodesDup - (int)p->pIfMan->AreaGlo;
+    if ( p->pPars->fVeryVerbose )
+        printf( "       Mffc = %2d. Mapped = %2d. Gain = %3d. Depth increase = %d. SReds = %d.\n", 
+            pCut->nNodes - pCut->nNodesDup, (int)p->pIfMan->AreaGlo, nGain, (int)p->pIfMan->RequiredGlo - (int)p->pObj->Level, p->nCalledSRed );
+
+    // quit if there is no gain
+    if ( !(nGain > 0 || (p->pPars->fZeroCost && nGain == 0)) )
+        return 0;
+
+    // quit if depth increases too much
+    if ( (int)p->pIfMan->RequiredGlo > Abc_ObjRequiredLevel(p->pObj) )
+        return 0;
+
+    // perform replacement
+    p->nGainTotal += nGain;
+    p->nChanges++;
+    if ( p->nCalledSRed )
+        p->nBenefited++;
+
+    nNodesBef = Abc_NtkNodeNum(p->pNtk);
+    // prepare the mapping manager
+    If_ManCleanNodeCopy( p->pIfMan );
+    If_ManCleanCutData( p->pIfMan );
+    // set the PIs of the cut
+    Lpk_CutForEachLeaf( p->pNtk, pCut, pLeaf, i )
+        If_ObjSetCopy( If_ManCi(p->pIfMan, i), pLeaf );
+    // get the area of mapping
+    pObjNew = Abc_NodeFromIf_rec( p->pNtk, p->pIfMan, If_Regular(pDriver), p->vCover );
+    pObjNew->pData = Hop_NotCond( (Hop_Obj_t *)pObjNew->pData, If_IsComplement(pDriver) );
+    // perform replacement
+    Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels );
+//printf( "%3d : %d-%d=%d(%d) \n", p->nChanges, nNodesBef, Abc_NtkNodeNum(p->pNtk), nNodesBef-Abc_NtkNodeNum(p->pNtk), nGain );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs resynthesis for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Lpk_ResynthesizeNode( Lpk_Man_t * p )
+{
+//    static int Count = 0;
+    Kit_DsdNtk_t * pDsdNtk;
+    Lpk_Cut_t * pCut;
+    unsigned * pTruth;
+    int i, k, nSuppSize, nCutNodes, RetValue;
+    abctime clk;
+
+    // compute the cuts
+clk = Abc_Clock();
+    if ( !Lpk_NodeCuts( p ) )
+    {
+p->timeCuts += Abc_Clock() - clk;
+        return 0;
+    }
+p->timeCuts += Abc_Clock() - clk;
+
+//return 0;
+
+    if ( p->pPars->fVeryVerbose )
+    printf( "Node %5d : Mffc size = %5d. Cuts = %5d.\n", p->pObj->Id, p->nMffc, p->nEvals );
+    // try the good cuts
+    p->nCutsTotal  += p->nCuts;
+    p->nCutsUseful += p->nEvals;
+    for ( i = 0; i < p->nEvals; i++ )
+    {
+        // get the cut
+        pCut = p->pCuts + p->pEvals[i];
+        if ( p->pPars->fFirst && i == 1 )
+            break;
+
+        // skip bad cuts        
+//        printf( "Mffc size = %d.  ", Abc_NodeMffcLabel(p->pObj) );
+        for ( k = 0; k < (int)pCut->nLeaves; k++ )
+            Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize++;
+        nCutNodes = Abc_NodeMffcLabel(p->pObj);
+//        printf( "Mffc with cut = %d.  ", nCutNodes );
+        for ( k = 0; k < (int)pCut->nLeaves; k++ )
+            Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize--;
+//        printf( "Mffc cut = %d.  ", (int)pCut->nNodes - (int)pCut->nNodesDup );
+//        printf( "\n" );
+        if ( nCutNodes != (int)pCut->nNodes - (int)pCut->nNodesDup )
+            continue;
+
+        // compute the truth table
+clk = Abc_Clock();
+        pTruth = Lpk_CutTruth( p, pCut, 0 );
+        nSuppSize = Extra_TruthSupportSize(pTruth, pCut->nLeaves);
+p->timeTruth += Abc_Clock() - clk;
+
+        pDsdNtk = Kit_DsdDecompose( pTruth, pCut->nLeaves ); 
+//        Kit_DsdVerify( pDsdNtk, pTruth, pCut->nLeaves ); 
+        // skip 16-input non-DSD because ISOP will not work
+        if ( Kit_DsdNtkRoot(pDsdNtk)->nFans == 16 ) 
+        {
+            Kit_DsdNtkFree( pDsdNtk );
+            continue;
+        }
+
+        // if DSD has nodes that require splitting to fit them into LUTs
+        // we can skip those cuts that cannot lead to improvement
+        // (a full DSD network requires  V = Nmin * (K-1) + 1 for improvement)
+        if ( Kit_DsdNonDsdSizeMax(pDsdNtk) > p->pPars->nLutSize && 
+             nSuppSize >= ((int)pCut->nNodes - (int)pCut->nNodesDup - 1) * (p->pPars->nLutSize - 1) + 1 )
+        {
+            Kit_DsdNtkFree( pDsdNtk );
+            continue;
+        }
+
+        if ( p->pPars->fVeryVerbose )
+        {
+//            char * pFileName;
+            printf( "  C%02d: L= %2d/%2d  V= %2d/%d  N= %d  W= %4.2f  ", 
+                i, pCut->nLeaves, nSuppSize, pCut->nNodes, pCut->nNodesDup, pCut->nLuts, pCut->Weight );
+            Kit_DsdPrint( stdout, pDsdNtk );
+            Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves );
+//            pFileName = Kit_TruthDumpToFile( pTruth, pCut->nLeaves, Count++ );
+//            printf( "Saved truth table in file \"%s\".\n", pFileName );
+        }
+
+        // update the network
+clk = Abc_Clock();
+        RetValue = Lpk_ExploreCut( p, pCut, pDsdNtk );
+p->timeEval += Abc_Clock() - clk;
+        Kit_DsdNtkFree( pDsdNtk );
+        if ( RetValue )
+            break;
+    }
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes supports of the cofactors of the function.]
+
+  Description [This procedure should be called after Lpk_CutTruth(p,pCut,0)]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lpk_ComputeSupports( Lpk_Man_t * p, Lpk_Cut_t * pCut, unsigned * pTruth )
+{
+    unsigned * pTruthInv;
+    int RetValue1, RetValue2;
+    pTruthInv = Lpk_CutTruth( p, pCut, 1 );
+    RetValue1 = Kit_CreateCloudFromTruth( p->pDsdMan->dd, pTruth, pCut->nLeaves, p->vBddDir );
+    RetValue2 = Kit_CreateCloudFromTruth( p->pDsdMan->dd, pTruthInv, pCut->nLeaves, p->vBddInv );
+    if ( RetValue1 && RetValue2 && Vec_IntSize(p->vBddDir) > 1 && Vec_IntSize(p->vBddInv) > 1 )
+        Kit_TruthCofSupports( p->vBddDir, p->vBddInv, pCut->nLeaves, p->vMemory, p->puSupps ); 
+    else
+        p->puSupps[0] = p->puSupps[1] = 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs resynthesis for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Lpk_ResynthesizeNodeNew( Lpk_Man_t * p )
+{
+//    static int Count = 0;
+    Abc_Obj_t * pObjNew, * pLeaf;
+    Lpk_Cut_t * pCut;
+    unsigned * pTruth;
+    int nNodesBef, nNodesAft, nCutNodes;
+    int i, k;
+    abctime clk;
+    int Required = Abc_ObjRequiredLevel(p->pObj);
+//    CloudNode * pFun2;//, * pFun1;
+
+    // compute the cuts
+clk = Abc_Clock();
+    if ( !Lpk_NodeCuts( p ) )
+    {
+p->timeCuts += Abc_Clock() - clk;
+        return 0;
+    }
+p->timeCuts += Abc_Clock() - clk;
+
+    if ( p->pPars->fVeryVerbose )
+        printf( "Node %5d : Mffc size = %5d. Cuts = %5d.  Level = %2d. Req = %2d.\n", 
+            p->pObj->Id, p->nMffc, p->nEvals, p->pObj->Level, Required );
+    // try the good cuts
+    p->nCutsTotal  += p->nCuts;
+    p->nCutsUseful += p->nEvals;
+    for ( i = 0; i < p->nEvals; i++ )
+    {
+        // get the cut
+        pCut = p->pCuts + p->pEvals[i];
+        if ( p->pPars->fFirst && i == 1 )
+            break;
+//        if ( pCut->Weight < 1.05 )
+//            continue;
+
+        // skip bad cuts        
+//        printf( "Mffc size = %d.  ", Abc_NodeMffcLabel(p->pObj) );
+        for ( k = 0; k < (int)pCut->nLeaves; k++ )
+            Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize++;
+        nCutNodes = Abc_NodeMffcLabel(p->pObj);
+//        printf( "Mffc with cut = %d.  ", nCutNodes );
+        for ( k = 0; k < (int)pCut->nLeaves; k++ )
+            Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize--;
+//        printf( "Mffc cut = %d.  ", (int)pCut->nNodes - (int)pCut->nNodesDup );
+//        printf( "\n" );
+        if ( nCutNodes != (int)pCut->nNodes - (int)pCut->nNodesDup )
+            continue;
+
+        // collect nodes into the array
+        Vec_PtrClear( p->vLeaves );
+        for ( k = 0; k < (int)pCut->nLeaves; k++ )
+            Vec_PtrPush( p->vLeaves, Abc_NtkObj(p->pNtk, pCut->pLeaves[k]) );
+
+        // compute the truth table
+clk = Abc_Clock();
+        pTruth = Lpk_CutTruth( p, pCut, 0 );
+p->timeTruth += Abc_Clock() - clk;
+clk = Abc_Clock();
+        Lpk_ComputeSupports( p, pCut, pTruth );        
+p->timeSupps += Abc_Clock() - clk;
+//clk = Abc_Clock();
+//        pFun1 = Lpk_CutTruthBdd( p, pCut );
+//p->timeTruth2 += Abc_Clock() - clk;
+/*
+clk = Abc_Clock();
+        Cloud_Restart( p->pDsdMan->dd );
+        pFun2 = Kit_TruthToCloud( p->pDsdMan->dd, pTruth, pCut->nLeaves );
+        RetValue = Kit_CreateCloud( p->pDsdMan->dd, pFun2, p->vBddNodes );
+p->timeTruth3 += Abc_Clock() - clk;
+*/
+//        if ( pFun1 != pFun2 )
+//            printf( "Truth tables do not agree!\n" );
+//        else
+//            printf( "Fine!\n" );
+
+        if ( p->pPars->fVeryVerbose )
+        {
+//            char * pFileName;
+            int nSuppSize = Extra_TruthSupportSize( pTruth, pCut->nLeaves );
+            printf( "  C%02d: L= %2d/%2d  V= %2d/%d  N= %d  W= %4.2f  ", 
+                i, pCut->nLeaves, nSuppSize, pCut->nNodes, pCut->nNodesDup, pCut->nLuts, pCut->Weight );
+            Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pLeaf, k )
+                printf( "%c=%d ", 'a'+k, Abc_ObjLevel(pLeaf) );
+            printf( "\n" );
+            Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves );
+//            pFileName = Kit_TruthDumpToFile( pTruth, pCut->nLeaves, Count++ );
+//            printf( "Saved truth table in file \"%s\".\n", pFileName );
+        }
+
+        // update the network
+        nNodesBef = Abc_NtkNodeNum(p->pNtk);
+clk = Abc_Clock();
+        pObjNew = Lpk_Decompose( p, p->pNtk, p->vLeaves, pTruth, p->puSupps, p->pPars->nLutSize,
+            (int)pCut->nNodes - (int)pCut->nNodesDup - 1 + (int)(p->pPars->fZeroCost > 0), Required );
+p->timeEval += Abc_Clock() - clk;
+        nNodesAft = Abc_NtkNodeNum(p->pNtk);
+
+        // perform replacement
+        if ( pObjNew )
+        {
+            int nGain = (int)pCut->nNodes - (int)pCut->nNodesDup - (nNodesAft - nNodesBef);
+            assert( nGain >= 1 - p->pPars->fZeroCost );
+            assert( Abc_ObjLevel(pObjNew) <= Required );
+/*
+            if ( nGain <= 0 )
+            {
+                int x = 0;
+            }
+            if ( Abc_ObjLevel(pObjNew) > Required )
+            {
+                int x = 0;
+            }
+*/
+            p->nGainTotal += nGain;
+            p->nChanges++;
+            if ( p->pPars->fVeryVerbose )
+                printf( "Performed resynthesis: Gain = %2d. Level = %2d. Req = %2d.\n", nGain, Abc_ObjLevel(pObjNew), Required );
+            Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels );
+//printf( "%3d : %d-%d=%d(%d) \n", p->nChanges, nNodesBef, Abc_NtkNodeNum(p->pNtk), nNodesBef-Abc_NtkNodeNum(p->pNtk), nGain );
+            break;
+        }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs resynthesis for one network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Lpk_Resynthesize( Abc_Ntk_t * pNtk, Lpk_Par_t * pPars )
+{
+    ProgressBar * pProgress = NULL; // Suppress "might be used uninitialized"
+    Lpk_Man_t * p;
+    Abc_Obj_t * pObj;
+    double Delta;
+//    int * pnFanouts, nObjMax;
+    int i, Iter, nNodes, nNodesPrev;
+    abctime clk = Abc_Clock();
+    assert( Abc_NtkIsLogic(pNtk) );
+ 
+    // sweep dangling nodes as a preprocessing step
+    Abc_NtkSweep( pNtk, 0 );
+
+    // get the number of inputs
+    if ( Abc_FrameReadLibLut() )
+        pPars->nLutSize = ((If_LibLut_t *)Abc_FrameReadLibLut())->LutMax;
+    else
+        pPars->nLutSize = Abc_NtkGetFaninMax( pNtk );
+    if ( pPars->nLutSize > 6 )
+        pPars->nLutSize = 6;
+    if ( pPars->nLutSize < 3 )
+        pPars->nLutSize = 3;
+    // adjust the number of crossbars based on LUT size
+    if ( pPars->nVarsShared > pPars->nLutSize - 2 )
+        pPars->nVarsShared = pPars->nLutSize - 2;
+    // get the max number of LUTs tried
+    pPars->nVarsMax = pPars->nLutsMax * (pPars->nLutSize - 1) + 1; // V = N * (K-1) + 1
+    while ( pPars->nVarsMax > 16 )
+    {
+        pPars->nLutsMax--;
+        pPars->nVarsMax = pPars->nLutsMax * (pPars->nLutSize - 1) + 1;
+
+    }
+    if ( pPars->fVerbose )
+    {
+        printf( "Resynthesis for %d %d-LUTs with %d non-MFFC LUTs, %d crossbars, and %d-input cuts.\n",
+            pPars->nLutsMax, pPars->nLutSize, pPars->nLutsOver, pPars->nVarsShared, pPars->nVarsMax );
+    }
+ 
+
+    // convert into the AIG
+    if ( !Abc_NtkToAig(pNtk) )
+    {
+        fprintf( stdout, "Converting to BDD has failed.\n" );
+        return 0;
+    }
+    assert( Abc_NtkHasAig(pNtk) );
+
+    // set the number of levels
+    Abc_NtkLevel( pNtk );
+    Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel );
+
+    // start the manager
+    p = Lpk_ManStart( pPars );
+    p->pNtk = pNtk;
+    p->nNodesTotal = Abc_NtkNodeNum(pNtk);
+    p->vLevels = Vec_VecStart( pNtk->LevelMax ); 
+    if ( p->pPars->fSatur )
+        p->vVisited = Vec_VecStart( 0 );
+    if ( pPars->fVerbose )
+    {
+        p->nTotalNets = Abc_NtkGetTotalFanins(pNtk);
+        p->nTotalNodes = Abc_NtkNodeNum(pNtk);
+    }
+/*
+    // save the number of fanouts of all objects
+    nObjMax = Abc_NtkObjNumMax( pNtk );
+    pnFanouts = ABC_ALLOC( int, nObjMax );
+    memset( pnFanouts, 0, sizeof(int) * nObjMax );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pnFanouts[pObj->Id] = Abc_ObjFanoutNum(pObj);
+*/
+
+    // iterate over the network
+    nNodesPrev = p->nNodesTotal;
+    for ( Iter = 1; ; Iter++ )
+    {
+        // expand storage for changed nodes
+        if ( p->pPars->fSatur )
+            Vec_VecExpand( p->vVisited, Abc_NtkObjNumMax(pNtk) + 1 );
+
+        // consider all nodes
+        nNodes = Abc_NtkObjNumMax(pNtk);
+        if ( !pPars->fVeryVerbose )
+            pProgress = Extra_ProgressBarStart( stdout, nNodes );
+        Abc_NtkForEachNode( pNtk, pObj, i )
+        {
+            // skip all except the final node
+            if ( pPars->fFirst )
+            {
+                if ( !Abc_ObjIsCo(Abc_ObjFanout0(pObj)) )
+                    continue;
+            }
+            if ( i >= nNodes )
+                break;
+            if ( !pPars->fVeryVerbose )
+                Extra_ProgressBarUpdate( pProgress, i, NULL );
+            // skip the nodes that did not change
+            if ( p->pPars->fSatur && !Lpk_NodeHasChanged(p, pObj->Id) )
+                continue;
+            // resynthesize
+            p->pObj = pObj;
+            if ( p->pPars->fOldAlgo )
+                Lpk_ResynthesizeNode( p );
+            else
+                Lpk_ResynthesizeNodeNew( p );
+        }
+        if ( !pPars->fVeryVerbose )
+            Extra_ProgressBarStop( pProgress );
+
+        // check the increase
+        Delta = 100.00 * (nNodesPrev - Abc_NtkNodeNum(pNtk)) / p->nNodesTotal;
+        if ( Delta < 0.05 )
+            break;
+        nNodesPrev = Abc_NtkNodeNum(pNtk);
+        if ( !p->pPars->fSatur )
+            break;
+
+        if ( pPars->fFirst )
+            break;
+    }
+    Abc_NtkStopReverseLevels( pNtk );
+/*
+    // report the fanout changes
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        if ( i >= nObjMax )
+            continue;
+        if ( Abc_ObjFanoutNum(pObj) - pnFanouts[pObj->Id] == 0 )
+            continue;
+        printf( "%d ", Abc_ObjFanoutNum(pObj) - pnFanouts[pObj->Id] );
+    }
+    printf( "\n" );
+*/
+
+    if ( pPars->fVerbose )
+    {
+//        Cloud_PrintInfo( p->pDsdMan->dd );
+        p->nTotalNets2 = Abc_NtkGetTotalFanins(pNtk);
+        p->nTotalNodes2 = Abc_NtkNodeNum(pNtk);
+        printf( "Node gain = %5d. (%.2f %%)  ", 
+            p->nTotalNodes-p->nTotalNodes2, 100.0*(p->nTotalNodes-p->nTotalNodes2)/p->nTotalNodes );
+        printf( "Edge gain = %5d. (%.2f %%)  ", 
+            p->nTotalNets-p->nTotalNets2, 100.0*(p->nTotalNets-p->nTotalNets2)/p->nTotalNets );
+        printf( "Muxes = %4d. Dsds = %4d.", p->nMuxes, p->nDsds );
+        printf( "\n" );
+        printf( "Nodes = %5d (%3d)  Cuts = %5d (%4d)  Changes = %5d  Iter = %2d  Benefit = %d.\n", 
+            p->nNodesTotal, p->nNodesOver, p->nCutsTotal, p->nCutsUseful, p->nChanges, Iter, p->nBenefited );
+
+        printf( "Non-DSD:" );
+        for ( i = 3; i <= pPars->nVarsMax; i++ )
+            if ( p->nBlocks[i] )
+                printf( " %d=%d", i, p->nBlocks[i] );
+        printf( "\n" );
+
+        p->timeTotal = Abc_Clock() - clk;
+        p->timeEval  = p->timeEval  - p->timeMap;
+        p->timeOther = p->timeTotal - p->timeCuts - p->timeTruth - p->timeEval - p->timeMap;
+        ABC_PRTP( "Cuts  ", p->timeCuts,  p->timeTotal );
+        ABC_PRTP( "Truth ", p->timeTruth, p->timeTotal );
+        ABC_PRTP( "CSupps", p->timeSupps, p->timeTotal );
+        ABC_PRTP( "Eval  ", p->timeEval,  p->timeTotal );
+        ABC_PRTP( " MuxAn", p->timeEvalMuxAn, p->timeEval );
+        ABC_PRTP( " MuxSp", p->timeEvalMuxSp, p->timeEval );
+        ABC_PRTP( " DsdAn", p->timeEvalDsdAn, p->timeEval );
+        ABC_PRTP( " DsdSp", p->timeEvalDsdSp, p->timeEval );
+        ABC_PRTP( " Other", p->timeEval-p->timeEvalMuxAn-p->timeEvalMuxSp-p->timeEvalDsdAn-p->timeEvalDsdSp, p->timeEval );
+        ABC_PRTP( "Map   ", p->timeMap,   p->timeTotal );
+        ABC_PRTP( "Other ", p->timeOther, p->timeTotal );
+        ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal );
+    }
+
+    Lpk_ManStop( p );
+    // check the resulting network
+    if ( !Abc_NtkCheck( pNtk ) )
+    {
+        printf( "Lpk_Resynthesize: The network check has failed.\n" );
+        return 0;
+    }
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/lpk/lpkCut.c b/abc-build/src/opt/lpk/lpkCut.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/lpk/lpkCut.c
@@ -0,0 +1,689 @@
+/**CFile****************************************************************
+
+  FileName    [lpkCut.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast Boolean matching for LUT structures.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: lpkCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+#include "bool/kit/cloud.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the truth table of one cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+CloudNode * Lpk_CutTruthBdd_rec( CloudManager * dd, Hop_Man_t * pMan, Hop_Obj_t * pObj, int nVars )
+{
+    CloudNode * pTruth, * pTruth0, * pTruth1;
+    assert( !Hop_IsComplement(pObj) );
+    if ( pObj->pData )
+    {
+        assert( ((unsigned)(ABC_PTRUINT_T)pObj->pData) & 0xffff0000 );
+        return (CloudNode *)pObj->pData;
+    }
+    // get the plan for a new truth table
+    if ( Hop_ObjIsConst1(pObj) )
+        pTruth = dd->one;
+    else
+    {
+        assert( Hop_ObjIsAnd(pObj) );
+        // compute the truth tables of the fanins
+        pTruth0 = Lpk_CutTruthBdd_rec( dd, pMan, Hop_ObjFanin0(pObj), nVars );
+        pTruth1 = Lpk_CutTruthBdd_rec( dd, pMan, Hop_ObjFanin1(pObj), nVars );
+        pTruth0 = Cloud_NotCond( pTruth0, Hop_ObjFaninC0(pObj) );
+        pTruth1 = Cloud_NotCond( pTruth1, Hop_ObjFaninC1(pObj) );
+        // creat the truth table of the node
+        pTruth = Cloud_bddAnd( dd, pTruth0, pTruth1 );
+    }
+    pObj->pData = pTruth;
+    return pTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies that the factoring is correct.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+CloudNode * Lpk_CutTruthBdd( Lpk_Man_t * p, Lpk_Cut_t * pCut )
+{
+    CloudManager * dd = p->pDsdMan->dd;
+    Hop_Man_t * pManHop = (Hop_Man_t *)p->pNtk->pManFunc;
+    Hop_Obj_t * pObjHop;
+    Abc_Obj_t * pObj, * pFanin;
+    CloudNode * pTruth = NULL; // Suppress "might be used uninitialized"
+    int i, k;
+
+//    return NULL;
+//    Lpk_NodePrintCut( p, pCut );
+    // initialize the leaves
+    Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)dd->vars[pCut->nLeaves-1-i];
+
+    // construct truth table in the topological order
+    Lpk_CutForEachNodeReverse( p->pNtk, pCut, pObj, i )
+    {
+        // get the local AIG
+        pObjHop = Hop_Regular((Hop_Obj_t *)pObj->pData);
+        // clean the data field of the nodes in the AIG subgraph
+        Hop_ObjCleanData_rec( pObjHop );
+        // set the initial truth tables at the fanins
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+        {
+            assert( ((unsigned)(ABC_PTRUINT_T)pFanin->pCopy) & 0xffff0000 );
+            Hop_ManPi( pManHop, k )->pData = pFanin->pCopy;
+        }
+        // compute the truth table of internal nodes
+        pTruth = Lpk_CutTruthBdd_rec( dd, pManHop, pObjHop, pCut->nLeaves );
+        if ( Hop_IsComplement((Hop_Obj_t *)pObj->pData) )
+            pTruth = Cloud_Not(pTruth);
+        // set the truth table at the node
+        pObj->pCopy = (Abc_Obj_t *)pTruth;
+        
+    }
+
+//    Cloud_bddPrint( dd, pTruth );
+//    printf( "Bdd size = %d. Total nodes = %d.\n", Cloud_DagSize( dd, pTruth ), dd->nNodesCur-dd->nVars-1 );
+    return pTruth;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the truth table of one cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Lpk_CutTruth_rec( Hop_Man_t * pMan, Hop_Obj_t * pObj, int nVars, Vec_Ptr_t * vTtNodes, int * piCount )
+{
+    unsigned * pTruth, * pTruth0, * pTruth1;
+    assert( !Hop_IsComplement(pObj) );
+    if ( pObj->pData )
+    {
+        assert( ((unsigned)(ABC_PTRUINT_T)pObj->pData) & 0xffff0000 );
+        return (unsigned *)pObj->pData;
+    }
+    // get the plan for a new truth table
+    pTruth = (unsigned *)Vec_PtrEntry( vTtNodes, (*piCount)++ );
+    if ( Hop_ObjIsConst1(pObj) )
+        Kit_TruthFill( pTruth, nVars );
+    else
+    {
+        assert( Hop_ObjIsAnd(pObj) );
+        // compute the truth tables of the fanins
+        pTruth0 = Lpk_CutTruth_rec( pMan, Hop_ObjFanin0(pObj), nVars, vTtNodes, piCount );
+        pTruth1 = Lpk_CutTruth_rec( pMan, Hop_ObjFanin1(pObj), nVars, vTtNodes, piCount );
+        // creat the truth table of the node
+        Kit_TruthAndPhase( pTruth, pTruth0, pTruth1, nVars, Hop_ObjFaninC0(pObj), Hop_ObjFaninC1(pObj) );
+    }
+    pObj->pData = pTruth;
+    return pTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the truth able of one cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Lpk_CutTruth( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fInv )
+{
+    Hop_Man_t * pManHop = (Hop_Man_t *)p->pNtk->pManFunc;
+    Hop_Obj_t * pObjHop;
+    Abc_Obj_t * pObj = NULL; // Suppress "might be used uninitialized"
+    Abc_Obj_t * pFanin;
+    unsigned * pTruth = NULL; // Suppress "might be used uninitialized"
+    int i, k, iCount = 0;
+//    Lpk_NodePrintCut( p, pCut );
+    assert( pCut->nNodes > 0 );
+
+    // initialize the leaves
+    Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)Vec_PtrEntry( p->vTtElems, fInv? pCut->nLeaves-1-i : i );
+
+    // construct truth table in the topological order
+    Lpk_CutForEachNodeReverse( p->pNtk, pCut, pObj, i )
+    {
+        // get the local AIG
+        pObjHop = Hop_Regular((Hop_Obj_t *)pObj->pData);
+        // clean the data field of the nodes in the AIG subgraph
+        Hop_ObjCleanData_rec( pObjHop );
+        // set the initial truth tables at the fanins
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+        {
+            assert( ((unsigned)(ABC_PTRUINT_T)pFanin->pCopy) & 0xffff0000 );
+            Hop_ManPi( pManHop, k )->pData = pFanin->pCopy;
+        }
+        // compute the truth table of internal nodes
+        pTruth = Lpk_CutTruth_rec( pManHop, pObjHop, pCut->nLeaves, p->vTtNodes, &iCount );
+        if ( Hop_IsComplement((Hop_Obj_t *)pObj->pData) )
+            Kit_TruthNot( pTruth, pTruth, pCut->nLeaves );
+        // set the truth table at the node
+        pObj->pCopy = (Abc_Obj_t *)pTruth;
+    }
+
+    // make sure direct truth table is stored elsewhere (assuming the first call for direct truth!!!)
+    if ( fInv == 0 )
+    {
+        pTruth = (unsigned *)Vec_PtrEntry( p->vTtNodes, iCount++ );
+        Kit_TruthCopy( pTruth, (unsigned *)(ABC_PTRUINT_T)pObj->pCopy, pCut->nLeaves );
+    }
+    assert( iCount <= Vec_PtrSize(p->vTtNodes) );
+    return pTruth;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if at least one entry has changed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lpk_NodeRecordImpact( Lpk_Man_t * p )
+{
+    Lpk_Cut_t * pCut;
+    Vec_Ptr_t * vNodes = Vec_VecEntry( p->vVisited, p->pObj->Id );
+    Abc_Obj_t * pNode;
+    int i, k;
+    // collect the nodes that impact the given node
+    Vec_PtrClear( vNodes );
+    for ( i = 0; i < p->nCuts; i++ )
+    {
+        pCut = p->pCuts + i;
+        for ( k = 0; k < (int)pCut->nLeaves; k++ )
+        {
+            pNode = Abc_NtkObj( p->pNtk, pCut->pLeaves[k] );
+            if ( pNode->fMarkC )
+                continue;
+            pNode->fMarkC = 1;
+            Vec_PtrPush( vNodes, (void *)(ABC_PTRUINT_T)pNode->Id );
+            Vec_PtrPush( vNodes, (void *)(ABC_PTRUINT_T)Abc_ObjFanoutNum(pNode) );
+        }
+    }
+    // clear the marks
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        pNode = Abc_NtkObj( p->pNtk, (int)(ABC_PTRUINT_T)pNode );
+        pNode->fMarkC = 0;
+        i++;
+    }
+//printf( "%d ", Vec_PtrSize(vNodes) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the cut has structural DSD.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Lpk_NodeCutsCheckDsd( Lpk_Man_t * p, Lpk_Cut_t * pCut )
+{
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k, nCands, fLeavesOnly, RetValue;
+    assert( pCut->nLeaves > 0 );
+    // clear ref counters
+    memset( p->pRefs, 0, sizeof(int) * pCut->nLeaves );
+    // mark cut leaves
+    Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
+    {
+        assert( pObj->fMarkA == 0 );
+        pObj->fMarkA = 1;
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)i;
+    }
+    // ref leaves pointed from the internal nodes
+    nCands = 0;
+    Lpk_CutForEachNode( p->pNtk, pCut, pObj, i )
+    {
+        fLeavesOnly = 1;
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+            if ( pFanin->fMarkA )
+                p->pRefs[(int)(ABC_PTRUINT_T)pFanin->pCopy]++;
+            else
+                fLeavesOnly = 0;
+        if ( fLeavesOnly )
+            p->pCands[nCands++] = pObj->Id;
+    }
+    // look at the nodes that only point to the leaves
+    RetValue = 0;
+    for ( i = 0; i < nCands; i++ )
+    {
+        pObj = Abc_NtkObj( p->pNtk, p->pCands[i] );
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+        {
+            assert( pFanin->fMarkA == 1 );
+            if ( p->pRefs[(int)(ABC_PTRUINT_T)pFanin->pCopy] > 1 )
+                break;
+        }
+        if ( k == Abc_ObjFaninNum(pObj) )
+        {
+            RetValue = 1;
+            break;
+        }
+    }
+    // unmark cut leaves
+    Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
+        pObj->fMarkA = 0;
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pDom is contained in pCut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Lpk_NodeCutsOneDominance( Lpk_Cut_t * pDom, Lpk_Cut_t * pCut )
+{
+    int i, k;
+    for ( i = 0; i < (int)pDom->nLeaves; i++ )
+    {
+        for ( k = 0; k < (int)pCut->nLeaves; k++ )
+            if ( pDom->pLeaves[i] == pCut->pLeaves[k] )
+                break;
+        if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut
+            return 0;
+    }
+    // every node in pDom is contained in pCut
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check if the cut exists.]
+
+  Description [Returns 1 if the cut exists.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Lpk_NodeCutsOneFilter( Lpk_Cut_t * pCuts, int nCuts, Lpk_Cut_t * pCutNew )
+{
+    Lpk_Cut_t * pCut;
+    int i, k;
+    assert( pCutNew->uSign[0] || pCutNew->uSign[1] );
+    // try to find the cut
+    for ( i = 0; i < nCuts; i++ )
+    {
+        pCut = pCuts + i;
+        if ( pCut->nLeaves == 0 )
+            continue;
+        if ( pCut->nLeaves == pCutNew->nLeaves )
+        {
+            if ( pCut->uSign[0] == pCutNew->uSign[0] && pCut->uSign[1] == pCutNew->uSign[1] )
+            {
+                for ( k = 0; k < (int)pCutNew->nLeaves; k++ )
+                    if ( pCut->pLeaves[k] != pCutNew->pLeaves[k] )
+                        break;
+                if ( k == (int)pCutNew->nLeaves )
+                    return 1;
+            }
+            continue;
+        }
+        if ( pCut->nLeaves < pCutNew->nLeaves )
+        {
+            // skip the non-contained cuts
+            if ( (pCut->uSign[0] & pCutNew->uSign[0]) != pCut->uSign[0] )
+                continue;
+            if ( (pCut->uSign[1] & pCutNew->uSign[1]) != pCut->uSign[1] )
+                continue;
+            // check containment seriously
+            if ( Lpk_NodeCutsOneDominance( pCut, pCutNew ) )
+                return 1;
+            continue;
+        }
+        // check potential containment of other cut
+
+        // skip the non-contained cuts
+        if ( (pCut->uSign[0] & pCutNew->uSign[0]) != pCutNew->uSign[0] )
+            continue;
+        if ( (pCut->uSign[1] & pCutNew->uSign[1]) != pCutNew->uSign[1] )
+            continue;
+        // check containment seriously
+        if ( Lpk_NodeCutsOneDominance( pCutNew, pCut ) )
+            pCut->nLeaves = 0; // removed
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the given cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lpk_NodePrintCut( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fLeavesOnly )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    if ( !fLeavesOnly )
+        printf( "LEAVES:\n" );
+    Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
+        printf( "%d,", pObj->Id );
+    if ( !fLeavesOnly )
+    {
+        printf( "\nNODES:\n" );
+        Lpk_CutForEachNode( p->pNtk, pCut, pObj, i )
+        {
+            printf( "%d,", pObj->Id );
+            assert( Abc_ObjIsNode(pObj) );
+        }
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Set the cut signature.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lpk_NodeCutSignature( Lpk_Cut_t * pCut )
+{
+    unsigned i;
+    pCut->uSign[0] = pCut->uSign[1] = 0;
+    for ( i = 0; i < pCut->nLeaves; i++ )
+    {
+        pCut->uSign[(pCut->pLeaves[i] & 32) > 0] |= (1 << (pCut->pLeaves[i] & 31));
+        if ( i != pCut->nLeaves - 1 )
+            assert( pCut->pLeaves[i] < pCut->pLeaves[i+1] );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the set of all cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lpk_NodeCutsOne( Lpk_Man_t * p, Lpk_Cut_t * pCut, int Node )
+{
+    Lpk_Cut_t * pCutNew;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k, j, nLeavesNew;
+/*
+    printf( "Exploring cut " );
+    Lpk_NodePrintCut( p, pCut, 1 );
+    printf( "with node %d\n", Node );
+*/
+    // check if the cut can stand adding one more internal node
+    if ( pCut->nNodes == LPK_SIZE_MAX )
+        return;
+
+    // if the node is a PI, quit
+    pObj = Abc_NtkObj( p->pNtk, Node );
+    if ( Abc_ObjIsCi(pObj) )
+        return;
+    assert( Abc_ObjIsNode(pObj) );
+//    assert( Abc_ObjFaninNum(pObj) <= p->pPars->nLutSize );
+
+    // if the node is not in the MFFC, check the limit
+    if ( !Abc_NodeIsTravIdCurrent(pObj) )
+    {
+        if ( (int)pCut->nNodesDup == p->pPars->nLutsOver )
+            return;
+        assert( (int)pCut->nNodesDup < p->pPars->nLutsOver );
+    }
+
+    // check the possibility of adding this node using the signature
+    nLeavesNew = pCut->nLeaves - 1;
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+    {
+        if ( (pCut->uSign[(pFanin->Id & 32) > 0] & (1 << (pFanin->Id & 31))) )
+            continue;
+        if ( ++nLeavesNew > p->pPars->nVarsMax )
+            return;
+    }
+
+    // initialize the set of leaves to the nodes in the cut
+    assert( p->nCuts < LPK_CUTS_MAX );
+    pCutNew = p->pCuts + p->nCuts;
+    pCutNew->nLeaves = 0;
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        if ( pCut->pLeaves[i] != Node )
+            pCutNew->pLeaves[pCutNew->nLeaves++] = pCut->pLeaves[i];
+
+    // add new nodes
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+    {
+        // find the place where this node belongs
+        for ( k = 0; k < (int)pCutNew->nLeaves; k++ )
+            if ( pCutNew->pLeaves[k] >= pFanin->Id )
+                break;
+        if ( k < (int)pCutNew->nLeaves && pCutNew->pLeaves[k] == pFanin->Id )
+            continue;
+        // check if there is room
+        if ( (int)pCutNew->nLeaves == p->pPars->nVarsMax )
+            return;
+        // move all the nodes
+        for ( j = pCutNew->nLeaves; j > k; j-- )
+            pCutNew->pLeaves[j] = pCutNew->pLeaves[j-1];
+        pCutNew->pLeaves[k] = pFanin->Id;
+        pCutNew->nLeaves++;
+        assert( pCutNew->nLeaves <= LPK_SIZE_MAX );
+
+    }
+    // skip the contained cuts
+    Lpk_NodeCutSignature( pCutNew );
+    if ( Lpk_NodeCutsOneFilter( p->pCuts, p->nCuts, pCutNew ) )
+        return;
+
+    // update the set of internal nodes
+    assert( pCut->nNodes < LPK_SIZE_MAX );
+    memcpy( pCutNew->pNodes, pCut->pNodes, pCut->nNodes * sizeof(int) );
+    pCutNew->nNodes = pCut->nNodes;
+    pCutNew->nNodesDup = pCut->nNodesDup;
+
+    // check if the node is already there
+    // if so, move the node to be the last
+    for ( i = 0; i < (int)pCutNew->nNodes; i++ )
+        if ( pCutNew->pNodes[i] == Node )
+        {
+            for ( k = i; k < (int)pCutNew->nNodes - 1; k++ )
+                pCutNew->pNodes[k] = pCutNew->pNodes[k+1];
+            pCutNew->pNodes[k] = Node;
+            break;
+        }
+    if ( i == (int)pCutNew->nNodes ) // new node
+    {
+        pCutNew->pNodes[ pCutNew->nNodes++ ] = Node;
+        pCutNew->nNodesDup += !Abc_NodeIsTravIdCurrent(pObj);
+    }
+    // the number of nodes does not exceed MFFC plus duplications
+    assert( pCutNew->nNodes <= p->nMffc + pCutNew->nNodesDup );
+    // add the cut to storage
+    assert( p->nCuts < LPK_CUTS_MAX );
+    p->nCuts++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the set of all cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Lpk_NodeCuts( Lpk_Man_t * p )
+{
+    Lpk_Cut_t * pCut, * pCut2;
+    int i, k, Temp, nMffc, fChanges;
+
+    // mark the MFFC of the node with the current trav ID
+    nMffc = p->nMffc = Abc_NodeMffcLabel( p->pObj );
+    assert( nMffc > 0 );
+    if ( nMffc == 1 )
+        return 0;
+
+    // initialize the first cut
+    pCut = p->pCuts; p->nCuts = 1;
+    pCut->nNodes = 0; 
+    pCut->nNodesDup = 0;
+    pCut->nLeaves = 1;
+    pCut->pLeaves[0] = p->pObj->Id;
+    // assign the signature
+    Lpk_NodeCutSignature( pCut );
+
+    // perform the cut computation
+    for ( i = 0; i < p->nCuts; i++ )
+    {
+        pCut = p->pCuts + i;
+        if ( pCut->nLeaves == 0 )
+            continue;
+
+        // try to expand the fanins of this cut
+        for ( k = 0; k < (int)pCut->nLeaves; k++ )
+        {
+            // create a new cut
+            Lpk_NodeCutsOne( p, pCut, pCut->pLeaves[k] );
+            // quit if the number of cuts has exceeded the limit
+            if ( p->nCuts == LPK_CUTS_MAX )
+                break;
+        }
+        if ( p->nCuts == LPK_CUTS_MAX )
+            break;
+    }
+    if ( p->nCuts == LPK_CUTS_MAX ) 
+        p->nNodesOver++;
+
+    // record the impact of this node
+    if ( p->pPars->fSatur )
+        Lpk_NodeRecordImpact( p );
+
+    // compress the cuts by removing empty ones, those with negative Weight, and decomposable ones
+    p->nEvals = 0;
+    for ( i = 0; i < p->nCuts; i++ )
+    {
+        pCut = p->pCuts + i;
+        if ( pCut->nLeaves < 2 )
+            continue;
+        // compute the minimum number of LUTs needed to implement this cut
+        // V = N * (K-1) + 1  ~~~~~  N = Ceiling[(V-1)/(K-1)] = (V-1)/(K-1) + [(V-1)%(K-1) > 0]
+        pCut->nLuts = Lpk_LutNumLuts( pCut->nLeaves, p->pPars->nLutSize ); 
+//        pCut->Weight = (float)1.0 * (pCut->nNodes - pCut->nNodesDup - 1) / pCut->nLuts; //p->pPars->nLutsMax;
+        pCut->Weight = (float)1.0 * (pCut->nNodes - pCut->nNodesDup) / pCut->nLuts; //p->pPars->nLutsMax;
+        if ( pCut->Weight <= 1.001 )
+//        if ( pCut->Weight <= 0.999 )
+            continue;
+        pCut->fHasDsd = Lpk_NodeCutsCheckDsd( p, pCut );
+        if ( pCut->fHasDsd )
+            continue;
+        p->pEvals[p->nEvals++] = i;
+    }
+    if ( p->nEvals == 0 )
+        return 0;
+
+    // sort the cuts by Weight
+    do {
+        fChanges = 0;
+        for ( i = 0; i < p->nEvals - 1; i++ )
+        {
+            pCut = p->pCuts + p->pEvals[i];
+            pCut2 = p->pCuts + p->pEvals[i+1];
+            if ( pCut->Weight >= pCut2->Weight - 0.001 )
+                continue;
+            Temp = p->pEvals[i];
+            p->pEvals[i] = p->pEvals[i+1];
+            p->pEvals[i+1] = Temp;
+            fChanges = 1;
+        }
+    } while ( fChanges );
+/*
+    for ( i = 0; i < p->nEvals; i++ )
+    {
+        pCut = p->pCuts + p->pEvals[i];
+        printf( "Cut %3d : W = %5.2f.\n", i, pCut->Weight );
+    }
+    printf( "\n" );
+*/
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/lpk/lpkInt.h b/abc-build/src/opt/lpk/lpkInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/lpk/lpkInt.h
@@ -0,0 +1,250 @@
+/**CFile****************************************************************
+
+  FileName    [lpkInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast Boolean matching for LUT structures.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: lpkInt.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__opt__lpk__lpkInt_h
+#define ABC__opt__lpk__lpkInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "base/abc/abc.h"
+#include "bool/kit/kit.h"
+#include "map/if/if.h"
+#include "lpk.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define LPK_SIZE_MAX             24     // the largest size of the function
+#define LPK_CUTS_MAX            512     // the largest number of cuts considered
+
+typedef struct Lpk_Man_t_ Lpk_Man_t;
+typedef struct Lpk_Cut_t_ Lpk_Cut_t;
+
+struct Lpk_Cut_t_
+{
+    unsigned     nLeaves       : 6;     // (L) the number of leaves
+    unsigned     nNodes        : 6;     // (M) the number of nodes
+    unsigned     nNodesDup     : 6;     // (Q) nodes outside of MFFC
+    unsigned     nLuts         : 6;     // (N) the number of LUTs to try
+    unsigned     unused        : 6;     // unused
+    unsigned     fHasDsd       : 1;     // set to 1 if the cut has structural DSD (and so cannot be used)
+    unsigned     fMark         : 1;     // multipurpose mark
+    unsigned     uSign[2];              // the signature
+    float        Weight;                // the weight of the cut: (M - Q)/N(V)   (the larger the better)
+    int          Gain;                  // the gain achieved using this cut
+    int          pLeaves[LPK_SIZE_MAX]; // the leaves of the cut
+    int          pNodes[LPK_SIZE_MAX];  // the nodes of the cut
+};
+
+struct Lpk_Man_t_
+{
+    // parameters
+    Lpk_Par_t *  pPars;                 // the set of parameters
+    // current representation
+    Abc_Ntk_t *  pNtk;                  // the network
+    Abc_Obj_t *  pObj;                  // the node to resynthesize 
+    // cut representation
+    int          nMffc;                 // the size of MFFC of the node
+    int          nCuts;                 // the total number of cuts    
+    int          nCutsMax;              // the largest possible number of cuts
+    int          nEvals;                // the number of good cuts
+    Lpk_Cut_t    pCuts[LPK_CUTS_MAX];   // the storage for cuts
+    int          pEvals[LPK_CUTS_MAX];  // the good cuts
+    // visited nodes 
+    Vec_Vec_t *  vVisited;
+    // mapping manager
+    If_Man_t *   pIfMan;
+    Vec_Int_t *  vCover; 
+    Vec_Vec_t *  vLevels;
+    // temporary variables
+    int          fCofactoring;          // working in the cofactoring mode
+    int          fCalledOnce;           // limits the depth of MUX cofactoring
+    int          nCalledSRed;           // the number of called to SRed
+    int          pRefs[LPK_SIZE_MAX];   // fanin reference counters 
+    int          pCands[LPK_SIZE_MAX];  // internal nodes pointing only to the leaves
+    Vec_Ptr_t *  vLeaves;
+    // truth table representation
+    Vec_Ptr_t *  vTtElems;              // elementary truth tables
+    Vec_Ptr_t *  vTtNodes;              // storage for temporary truth tables of the nodes 
+    Vec_Int_t *  vMemory;
+    Vec_Int_t *  vBddDir;
+    Vec_Int_t *  vBddInv;
+    unsigned     puSupps[32];           // the supports of the cofactors
+    unsigned *   ppTruths[5][16];
+    // variable sets
+    Vec_Int_t *  vSets[8];
+    Kit_DsdMan_t* pDsdMan;
+    // statistics
+    int          nNodesTotal;           // total number of nodes
+    int          nNodesOver;            // nodes with cuts over the limit 
+    int          nCutsTotal;            // total number of cuts
+    int          nCutsUseful;           // useful cuts 
+    int          nGainTotal;            // the gain in LUTs
+    int          nChanges;              // the number of changed nodes
+    int          nBenefited;            // the number of gainful that benefited from decomposition
+    int          nMuxes;
+    int          nDsds;
+    int          nTotalNets;
+    int          nTotalNets2;
+    int          nTotalNodes;
+    int          nTotalNodes2;
+    // counter of non-DSD blocks
+    int          nBlocks[17];
+    // runtime
+    abctime      timeCuts;
+    abctime      timeTruth;
+    abctime      timeSupps;
+    abctime      timeTruth2;
+    abctime      timeTruth3;
+    abctime      timeEval;
+    abctime      timeMap;
+    abctime      timeOther;
+    abctime      timeTotal;
+    // runtime of eval
+    abctime      timeEvalMuxAn;
+    abctime      timeEvalMuxSp;
+    abctime      timeEvalDsdAn;
+    abctime      timeEvalDsdSp;
+ 
+};
+
+
+// internal representation of the function to be decomposed
+typedef struct Lpk_Fun_t_ Lpk_Fun_t;
+struct Lpk_Fun_t_
+{
+    Vec_Ptr_t *  vNodes;           // the array of leaves and decomposition nodes
+    unsigned     Id         :  7;  // the ID of this node
+    unsigned     nVars      :  5;  // the number of variables
+    unsigned     nLutK      :  4;  // the number of LUT inputs
+    unsigned     nAreaLim   :  5;  // the area limit (the largest allowed)
+    unsigned     nDelayLim  :  9;  // the delay limit (the largest allowed)
+    unsigned     fSupports  :  1;  // supports of cofactors were precomputed
+    unsigned     fMark      :  1;  // marks the MUX-based dec
+    unsigned     uSupp;            // the support of this component
+    unsigned     puSupps[32];      // the supports of the cofactors
+    char         pDelays[16];      // the delays of the inputs
+    char         pFanins[16];      // the fanins of this function
+    unsigned     pTruth[0];        // the truth table (contains room for three truth tables)    
+};
+
+// preliminary decomposition result
+typedef struct Lpk_Res_t_ Lpk_Res_t;
+struct Lpk_Res_t_
+{
+    int          nBSVars;          // the number of bound set variables
+    unsigned     BSVars;           // the bound set
+    int          nCofVars;         // the number of cofactoring variables
+    char         pCofVars[4];      // the cofactoring variables
+    int          nSuppSizeS;       // support size of the smaller (decomposed) function 
+    int          nSuppSizeL;       // support size of the larger (composition) function
+    int          DelayEst;         // estimated delay of the decomposition
+    int          AreaEst;          // estimated area of the decomposition
+    int          Variable;         // variable in MUX decomposition
+    int          Polarity;         // polarity in MUX decomposition
+};
+
+static inline int        Lpk_LutNumVars( int nLutsLim, int nLutK ) { return  nLutsLim * (nLutK - 1) + 1;                                            }
+static inline int        Lpk_LutNumLuts( int nVarsMax, int nLutK ) { return (nVarsMax - 1) / (nLutK - 1) + (int)((nVarsMax - 1) % (nLutK - 1) > 0); }
+static inline unsigned * Lpk_FunTruth( Lpk_Fun_t * p, int Num )    { assert( Num < 3 ); return p->pTruth + Kit_TruthWordNum(p->nVars) * Num;        }
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                           ITERATORS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define Lpk_CutForEachLeaf( pNtk, pCut, pObj, i )                                        \
+    for ( i = 0; (i < (int)(pCut)->nLeaves) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pLeaves[i])), 1); i++ )
+#define Lpk_CutForEachNode( pNtk, pCut, pObj, i )                                        \
+    for ( i = 0; (i < (int)(pCut)->nNodes) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pNodes[i])), 1); i++ )
+#define Lpk_CutForEachNodeReverse( pNtk, pCut, pObj, i )                                 \
+    for ( i = (int)(pCut)->nNodes - 1; (i >= 0) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pNodes[i])), 1); i-- )
+#define Lpk_SuppForEachVar( Supp, Var )\
+    for ( Var = 0; Var < 16; Var++ )\
+        if ( !(Supp & (1<<Var)) ) {} else
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== lpkAbcDec.c ============================================================*/
+extern Abc_Obj_t *    Lpk_Decompose( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, unsigned * puSupps, int nLutK, int AreaLim, int DelayLim );
+/*=== lpkAbcDsd.c ============================================================*/
+extern Lpk_Res_t *    Lpk_DsdAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p, int nShared );
+extern Lpk_Fun_t *    Lpk_DsdSplit( Lpk_Man_t * pMan, Lpk_Fun_t * p, char * pCofVars, int nCofVars, unsigned uBoundSet );
+/*=== lpkAbcMux.c ============================================================*/
+extern Lpk_Res_t *    Lpk_MuxAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p );
+extern Lpk_Fun_t *    Lpk_MuxSplit( Lpk_Man_t * pMan, Lpk_Fun_t * p, int Var, int Pol );
+/*=== lpkAbcUtil.c ============================================================*/
+extern Lpk_Fun_t *    Lpk_FunAlloc( int nVars );
+extern void           Lpk_FunFree( Lpk_Fun_t * p );
+extern Lpk_Fun_t *    Lpk_FunCreate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, int nLutK, int AreaLim, int DelayLim );
+extern Lpk_Fun_t *    Lpk_FunDup( Lpk_Fun_t * p, unsigned * pTruth );
+extern int            Lpk_FunSuppMinimize( Lpk_Fun_t * p );
+extern void           Lpk_FunComputeCofSupps( Lpk_Fun_t * p );
+extern int            Lpk_SuppDelay( unsigned uSupp, char * pDelays );
+extern int            Lpk_SuppToVars( unsigned uBoundSet, char * pVars );
+
+
+/*=== lpkCut.c =========================================================*/
+extern unsigned *     Lpk_CutTruth( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fInv );
+extern int            Lpk_NodeCuts( Lpk_Man_t * p );
+/*=== lpkMap.c =========================================================*/
+extern Lpk_Man_t *    Lpk_ManStart( Lpk_Par_t * pPars );
+extern void           Lpk_ManStop( Lpk_Man_t * p );
+/*=== lpkMap.c =========================================================*/
+extern If_Obj_t *     Lpk_MapPrime( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves );
+extern If_Obj_t *     Lpk_MapTree_rec( Lpk_Man_t * p, Kit_DsdNtk_t * pNtk, If_Obj_t ** ppLeaves, int iLit, If_Obj_t * pResult );
+/*=== lpkMulti.c =======================================================*/
+extern If_Obj_t *     Lpk_MapTreeMulti( Lpk_Man_t * p, unsigned * pTruth, int nLeaves, If_Obj_t ** ppLeaves );
+/*=== lpkMux.c =========================================================*/
+extern If_Obj_t *     Lpk_MapTreeMux_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves );
+extern If_Obj_t *     Lpk_MapSuppRedDec_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves );
+/*=== lpkSets.c =========================================================*/
+extern unsigned       Lpk_MapSuppRedDecSelect( Lpk_Man_t * p, unsigned * pTruth, int nVars, int * piVar, int * piVarReused );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/lpk/lpkMan.c b/abc-build/src/opt/lpk/lpkMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/lpk/lpkMan.c
@@ -0,0 +1,127 @@
+/**CFile****************************************************************
+
+  FileName    [lpkMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast Boolean matching for LUT structures.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: lpkMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Lpk_Man_t * Lpk_ManStart( Lpk_Par_t * pPars )
+{
+    Lpk_Man_t * p;
+    int i, nWords;
+    assert( pPars->nLutsMax <= 16 );
+    assert( pPars->nVarsMax > 0 && pPars->nVarsMax <= 16 );
+    p = ABC_ALLOC( Lpk_Man_t, 1 );
+    memset( p, 0, sizeof(Lpk_Man_t) );
+    p->pPars = pPars;
+    p->nCutsMax = LPK_CUTS_MAX;
+    p->vTtElems = Vec_PtrAllocTruthTables( pPars->nVarsMax );
+    p->vTtNodes = Vec_PtrAllocSimInfo( 1024, Abc_TruthWordNum(pPars->nVarsMax) );
+    p->vCover = Vec_IntAlloc( 1 << 12 );
+    p->vLeaves = Vec_PtrAlloc( 32 );
+    for ( i = 0; i < 8; i++ )
+        p->vSets[i] = Vec_IntAlloc(100);
+    p->pDsdMan = Kit_DsdManAlloc( pPars->nVarsMax, 64 );
+    p->vMemory = Vec_IntAlloc( 1024 * 32 );
+    p->vBddDir = Vec_IntAlloc( 256 );
+    p->vBddInv = Vec_IntAlloc( 256 );
+    // allocate temporary storage for truth tables
+    nWords = Kit_TruthWordNum(pPars->nVarsMax);
+    p->ppTruths[0][0] = ABC_ALLOC( unsigned, 32 * nWords );
+    p->ppTruths[1][0] = p->ppTruths[0][0] + 1 * nWords;
+    for ( i = 1; i < 2; i++ )
+        p->ppTruths[1][i] = p->ppTruths[1][0] + i * nWords;
+    p->ppTruths[2][0] = p->ppTruths[1][0] + 2 * nWords;
+    for ( i = 1; i < 4; i++ )
+        p->ppTruths[2][i] = p->ppTruths[2][0] + i * nWords;
+    p->ppTruths[3][0] = p->ppTruths[2][0] + 4 * nWords; 
+    for ( i = 1; i < 8; i++ )
+        p->ppTruths[3][i] = p->ppTruths[3][0] + i * nWords;
+    p->ppTruths[4][0] = p->ppTruths[3][0] + 8 * nWords; 
+    for ( i = 1; i < 16; i++ )
+        p->ppTruths[4][i] = p->ppTruths[4][0] + i * nWords;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lpk_ManStop( Lpk_Man_t * p )
+{
+    int i;
+    ABC_FREE( p->ppTruths[0][0] );
+    Vec_IntFree( p->vBddDir );
+    Vec_IntFree( p->vBddInv );
+    Vec_IntFree( p->vMemory );
+    Kit_DsdManFree( p->pDsdMan );
+    for ( i = 0; i < 8; i++ )
+        Vec_IntFree(p->vSets[i]);
+    if ( p->pIfMan )
+    {
+        void * pPars = p->pIfMan->pPars;
+        If_ManStop( p->pIfMan );
+        ABC_FREE( pPars );
+    }
+    if ( p->vLevels )
+        Vec_VecFree( p->vLevels );
+    if ( p->vVisited )
+        Vec_VecFree( p->vVisited );
+    Vec_PtrFree( p->vLeaves );
+    Vec_IntFree( p->vCover );
+    Vec_PtrFree( p->vTtElems );
+    Vec_PtrFree( p->vTtNodes );
+    ABC_FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/lpk/lpkMap.c b/abc-build/src/opt/lpk/lpkMap.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/lpk/lpkMap.c
@@ -0,0 +1,210 @@
+/**CFile****************************************************************
+
+  FileName    [lpkMap.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast Boolean matching for LUT structures.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: lpkMap.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms the decomposition graph into the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapPrimeInternal( If_Man_t * pIfMan, Kit_Graph_t * pGraph )
+{
+    Kit_Node_t * pNode = NULL; // Suppress "might be used uninitialized"
+    If_Obj_t * pAnd0, * pAnd1;
+    int i;
+    // check for constant function
+    if ( Kit_GraphIsConst(pGraph) )
+        return If_ManConst1(pIfMan);
+    // check for a literal
+    if ( Kit_GraphIsVar(pGraph) )
+        return (If_Obj_t *)Kit_GraphVar(pGraph)->pFunc;
+    // build the AIG nodes corresponding to the AND gates of the graph
+    Kit_GraphForEachNode( pGraph, pNode, i )
+    {
+        pAnd0 = (If_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc; 
+        pAnd1 = (If_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc; 
+        pNode->pFunc = If_ManCreateAnd( pIfMan, 
+            If_NotCond( If_Regular(pAnd0), If_IsComplement(pAnd0) ^ pNode->eEdge0.fCompl ), 
+            If_NotCond( If_Regular(pAnd1), If_IsComplement(pAnd1) ^ pNode->eEdge1.fCompl ) );
+    }
+    return (If_Obj_t *)pNode->pFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes one logic node using its SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapPrime( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves )
+{
+    Kit_Graph_t * pGraph;
+    Kit_Node_t * pNode;
+    If_Obj_t * pRes;
+    int i;
+    // derive the factored form
+    pGraph = Kit_TruthToGraph( pTruth, nVars, p->vCover );
+    if ( pGraph == NULL )
+        return NULL;
+    // collect the fanins
+    Kit_GraphForEachLeaf( pGraph, pNode, i )
+        pNode->pFunc = ppLeaves[i];
+    // perform strashing
+    pRes = Lpk_MapPrimeInternal( p->pIfMan, pGraph );
+    pRes = If_NotCond( pRes, Kit_GraphIsComplement(pGraph) );
+    Kit_GraphFree( pGraph );
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the mapping manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapTree_rec( Lpk_Man_t * p, Kit_DsdNtk_t * pNtk, If_Obj_t ** ppLeaves, int iLit, If_Obj_t * pResult )
+{
+    Kit_DsdObj_t * pObj;
+    If_Obj_t * pObjNew = NULL, * pObjNew2 = NULL, * pFansNew[16];
+    unsigned i, iLitFanin;
+
+    assert( iLit >= 0 );
+
+    // consider the case of a gate
+    pObj = Kit_DsdNtkObj( pNtk, Abc_Lit2Var(iLit) );
+    if ( pObj == NULL )
+    {
+        pObjNew = ppLeaves[Abc_Lit2Var(iLit)];
+        return If_NotCond( pObjNew, Abc_LitIsCompl(iLit) );
+    }
+    if ( pObj->Type == KIT_DSD_CONST1 )
+    {
+        return If_NotCond( If_ManConst1(p->pIfMan), Abc_LitIsCompl(iLit) );
+    }
+    if ( pObj->Type == KIT_DSD_VAR )
+    {
+        pObjNew = ppLeaves[Abc_Lit2Var(pObj->pFans[0])];
+        return If_NotCond( pObjNew, Abc_LitIsCompl(iLit) ^ Abc_LitIsCompl(pObj->pFans[0]) );
+    }
+    if ( pObj->Type == KIT_DSD_AND )
+    {
+        assert( pObj->nFans == 2 );
+        pFansNew[0] = Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[0], NULL );
+        pFansNew[1] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[1], NULL );
+        if ( pFansNew[0] == NULL || pFansNew[1] == NULL )
+            return NULL;
+        pObjNew = If_ManCreateAnd( p->pIfMan, pFansNew[0], pFansNew[1] ); 
+        return If_NotCond( pObjNew, Abc_LitIsCompl(iLit) );
+    }
+    if ( pObj->Type == KIT_DSD_XOR )
+    {
+        int fCompl = Abc_LitIsCompl(iLit);
+        assert( pObj->nFans == 2 );
+        pFansNew[0] = Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[0], NULL );
+        pFansNew[1] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[1], NULL );
+        if ( pFansNew[0] == NULL || pFansNew[1] == NULL )
+            return NULL;
+        fCompl ^= If_IsComplement(pFansNew[0]) ^ If_IsComplement(pFansNew[1]);
+        pObjNew = If_ManCreateXor( p->pIfMan, If_Regular(pFansNew[0]), If_Regular(pFansNew[1]) );
+        return If_NotCond( pObjNew, fCompl );
+    }
+    assert( pObj->Type == KIT_DSD_PRIME );
+    p->nBlocks[pObj->nFans]++;
+
+    // solve for the inputs
+    Kit_DsdObjForEachFanin( pNtk, pObj, iLitFanin, i )
+    {
+        if ( i == 0 )
+            pFansNew[i] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, iLitFanin, NULL );
+        else
+            pFansNew[i] = Lpk_MapTree_rec( p, pNtk, ppLeaves, iLitFanin, NULL );
+        if ( pFansNew[i] == NULL )
+            return NULL;
+    }
+/* 
+    if ( !p->fCofactoring && p->pPars->nVarsShared > 0 && (int)pObj->nFans > p->pPars->nLutSize )
+    {
+        pObjNew = Lpk_MapTreeMulti( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew );
+        return If_NotCond( pObjNew, Abc_LitIsCompl(iLit) );
+    }
+*/
+/*
+    if ( (int)pObj->nFans > p->pPars->nLutSize )
+    {
+        pObjNew2 = Lpk_MapTreeMux_rec( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew );
+//        if ( pObjNew2 )
+//            return If_NotCond( pObjNew2, Abc_LitIsCompl(iLit) );
+    }
+*/
+
+    // find best cofactoring variable
+    if ( p->pPars->nVarsShared > 0 && (int)pObj->nFans > p->pPars->nLutSize )
+    {
+        pObjNew2 = Lpk_MapSuppRedDec_rec( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew );
+        if ( pObjNew2 )
+            return If_NotCond( pObjNew2, Abc_LitIsCompl(iLit) );
+    }
+
+    pObjNew = Lpk_MapPrime( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew );
+
+    // add choice
+    if ( pObjNew && pObjNew2 )
+    {
+        If_ObjSetChoice( If_Regular(pObjNew), If_Regular(pObjNew2) );
+        If_ManCreateChoice( p->pIfMan, If_Regular(pObjNew) );
+    }
+    return If_NotCond( pObjNew, Abc_LitIsCompl(iLit) );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/lpk/lpkMulti.c b/abc-build/src/opt/lpk/lpkMulti.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/lpk/lpkMulti.c
@@ -0,0 +1,513 @@
+/**CFile****************************************************************
+
+  FileName    [lpkMulti.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast Boolean matching for LUT structures.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: lpkMulti.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Records variable order.]
+
+  Description [Increaments Order[x][y] by 1 if x should be above y in the DSD.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lpk_CreateVarOrder( Kit_DsdNtk_t * pNtk, char pTable[][16] )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned uSuppFanins, k;
+    int Above[16], Below[16];
+    int nAbove, nBelow, iFaninLit, i, x, y;
+    // iterate through the nodes
+    Kit_DsdNtkForEachObj( pNtk, pObj, i )
+    {
+        // collect fanin support of this node
+        nAbove = 0;
+        uSuppFanins = 0;
+        Kit_DsdObjForEachFanin( pNtk, pObj, iFaninLit, k )
+        {
+            if ( Kit_DsdLitIsLeaf( pNtk, iFaninLit ) )
+                Above[nAbove++] = Abc_Lit2Var(iFaninLit);
+            else
+                uSuppFanins |= Kit_DsdLitSupport( pNtk, iFaninLit );
+        }
+        // find the below variables
+        nBelow = 0;
+        for ( y = 0; y < 16; y++ )
+            if ( uSuppFanins & (1 << y) )
+                Below[nBelow++] = y;
+        // create all pairs
+        for ( x = 0; x < nAbove; x++ )
+            for ( y = 0; y < nBelow; y++ )
+                pTable[Above[x]][Below[y]]++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates commmon variable order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lpk_CreateCommonOrder( char pTable[][16], int piCofVar[], int nCBars, int pPrios[], int nVars, int fVerbose )
+{
+    int Score[16] = {0}, pPres[16];
+    int i, y, x, iVarBest, ScoreMax, PrioCount;
+
+    // mark the present variables
+    for ( i = 0; i < nVars; i++ )
+        pPres[i] = 1;
+    // remove cofactored variables
+    for ( i = 0; i < nCBars; i++ )
+        pPres[piCofVar[i]] = 0;
+
+    // compute scores for each leaf
+    for ( i = 0; i < nVars; i++ )
+    {
+        if ( pPres[i] == 0 )
+            continue;
+        for ( y = 0; y < nVars; y++ )
+            Score[i] += pTable[i][y];
+        for ( x = 0; x < nVars; x++ )
+            Score[i] -= pTable[x][i];
+    }
+
+    // print the scores
+    if ( fVerbose )
+    {
+        printf( "Scores: " );
+        for ( i = 0; i < nVars; i++ )
+            printf( "%c=%d ", 'a'+i, Score[i] );
+        printf( "   " );
+        printf( "Prios: " );
+    }
+
+    // derive variable priority
+    // variables with equal score receive the same priority
+    for ( i = 0; i < nVars; i++ )
+        pPrios[i] = 16;
+
+    // iterate until variables remain
+    for ( PrioCount = 1; ; PrioCount++ )
+    {
+        // find the present variable with the highest score
+        iVarBest = -1;
+        ScoreMax = -100000;
+        for ( i = 0; i < nVars; i++ )
+        {
+            if ( pPres[i] == 0 )
+                continue;
+            if ( ScoreMax < Score[i] )
+            {
+                ScoreMax = Score[i];
+                iVarBest = i;
+            }
+        }
+        if ( iVarBest == -1 )
+            break;
+        // give the next priority to all vars having this score
+        if ( fVerbose )
+            printf( "%d=", PrioCount );
+        for ( i = 0; i < nVars; i++ )
+        {
+            if ( pPres[i] == 0 )
+                continue;
+            if ( Score[i] == ScoreMax )
+            {
+                pPrios[i] = PrioCount;
+                pPres[i] = 0;
+                if ( fVerbose )
+                    printf( "%c", 'a'+i );
+            }
+        }
+        if ( fVerbose )
+            printf( " " );
+    }
+    if ( fVerbose )
+        printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds components with the highest priority.]
+
+  Description [Returns the number of components selected.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Lpk_FindHighest( Kit_DsdNtk_t ** ppNtks, int * piLits, int nSize, int * pPrio, int * pDecision )
+{
+    Kit_DsdObj_t * pObj;
+    unsigned uSupps[8], uSuppFanin, uSuppTotal, uSuppLarge;
+    int i, pTriv[8], PrioMin, iVarMax, nComps, fOneNonTriv;
+
+    // find individual support and total support 
+    uSuppTotal = 0;
+    for ( i = 0; i < nSize; i++ )
+    {
+        pTriv[i] = 1;
+        if ( piLits[i] < 0 ) 
+            uSupps[i] = 0;
+        else if ( Kit_DsdLitIsLeaf(ppNtks[i], piLits[i]) )
+            uSupps[i] = Kit_DsdLitSupport( ppNtks[i], piLits[i] );
+        else
+        {
+            pObj = Kit_DsdNtkObj( ppNtks[i], Abc_Lit2Var(piLits[i]) );
+            if ( pObj->Type == KIT_DSD_PRIME )
+            {
+                pTriv[i] = 0;
+                uSuppFanin = Kit_DsdLitSupport( ppNtks[i], pObj->pFans[0] );
+            }
+            else
+            {
+                assert( pObj->nFans == 2 );
+                if ( !Kit_DsdLitIsLeaf(ppNtks[i], pObj->pFans[0]) )
+                    pTriv[i] = 0;
+                uSuppFanin = Kit_DsdLitSupport( ppNtks[i], pObj->pFans[1] );
+            }
+            uSupps[i] = Kit_DsdLitSupport( ppNtks[i], piLits[i] ) & ~uSuppFanin;
+        }
+        assert( uSupps[i] <= 0xFFFF );
+        uSuppTotal |= uSupps[i];
+    }
+    if ( uSuppTotal == 0 )
+        return 0;
+
+    // find one support variable with the highest priority
+    PrioMin = ABC_INFINITY;
+    iVarMax = -1;
+    for ( i = 0; i < 16; i++ )
+        if ( uSuppTotal & (1 << i) )
+            if ( PrioMin > pPrio[i] )
+            {
+                PrioMin = pPrio[i];
+                iVarMax = i;
+            }
+    assert( iVarMax != -1 );
+
+    // select components, which have this variable
+    nComps = 0;
+    fOneNonTriv = 0;
+    uSuppLarge = 0;
+    for ( i = 0; i < nSize; i++ )
+        if ( uSupps[i] & (1<<iVarMax) )
+        {
+            if ( pTriv[i] || !fOneNonTriv )
+            {
+                if ( !pTriv[i] )
+                {
+                    uSuppLarge = uSupps[i];
+                    fOneNonTriv = 1;
+                }
+                pDecision[i] = 1;
+                nComps++;
+            }
+            else
+                pDecision[i] = 0;
+        }
+        else
+            pDecision[i] = 0;
+
+    // add other non-trivial not-taken components whose support is contained in the current large component support
+    if ( fOneNonTriv )
+        for ( i = 0; i < nSize; i++ )
+            if ( !pTriv[i] && pDecision[i] == 0 && (uSupps[i] & ~uSuppLarge) == 0 )
+            {
+                pDecision[i] = 1;
+                nComps++;
+            }
+
+    return nComps;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the mapping manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapTreeMulti_rec( Lpk_Man_t * p, Kit_DsdNtk_t ** ppNtks, int * piLits, int * piCofVar, int nCBars, If_Obj_t ** ppLeaves, int nLeaves, int * pPrio )
+{
+    Kit_DsdObj_t * pObj;
+    If_Obj_t * pObjsNew[4][8], * pResPrev;
+    int piLitsNew[8], pDecision[8];
+    int i, k, nComps, nSize;
+
+    // find which of the variables is highest in the order
+    nSize = (1 << nCBars);
+    nComps = Lpk_FindHighest( ppNtks, piLits, nSize, pPrio, pDecision );
+    if ( nComps == 0 )
+        return If_Not( If_ManConst1(p->pIfMan) );
+
+    // iterate over the nodes
+    if ( p->pPars->fVeryVerbose )
+        printf( "Decision: " );
+    for ( i = 0; i < nSize; i++ )
+    {
+        if ( pDecision[i] )
+        {
+            if ( p->pPars->fVeryVerbose )
+                printf( "%d ", i );
+            assert( piLits[i] >= 0 );
+            pObj = Kit_DsdNtkObj( ppNtks[i], Abc_Lit2Var(piLits[i]) );
+            if ( pObj == NULL )
+                piLitsNew[i] = -2;
+            else if ( pObj->Type == KIT_DSD_PRIME )
+                piLitsNew[i] = pObj->pFans[0];
+            else
+                piLitsNew[i] = pObj->pFans[1];
+        }
+        else
+            piLitsNew[i] = piLits[i];
+    }
+    if ( p->pPars->fVeryVerbose )
+        printf( "\n" );
+
+    // call again
+    pResPrev = Lpk_MapTreeMulti_rec( p, ppNtks, piLitsNew, piCofVar, nCBars, ppLeaves, nLeaves, pPrio );
+
+    // create new set of nodes
+    for ( i = 0; i < nSize; i++ )
+    {
+        if ( pDecision[i] )
+            pObjsNew[nCBars][i] = Lpk_MapTree_rec( p, ppNtks[i], ppLeaves, piLits[i], pResPrev );
+        else if ( piLits[i] == -1 )
+            pObjsNew[nCBars][i] = If_ManConst1(p->pIfMan);
+        else if ( piLits[i] == -2 )
+            pObjsNew[nCBars][i] = If_Not( If_ManConst1(p->pIfMan) );
+        else
+            pObjsNew[nCBars][i] = pResPrev;
+    }
+
+    // create MUX using these outputs
+    for ( k = nCBars; k > 0; k-- )
+    {
+        nSize /= 2;
+        for ( i = 0; i < nSize; i++ )
+            pObjsNew[k-1][i] = If_ManCreateMux( p->pIfMan, pObjsNew[k][2*i+0], pObjsNew[k][2*i+1], ppLeaves[piCofVar[k-1]] );
+    }
+    assert( nSize == 1 );
+    return pObjsNew[0][0];  
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the mapping manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapTreeMulti( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves )
+{
+    static int Counter = 0;
+    If_Obj_t * pResult;
+    Kit_DsdNtk_t * ppNtks[8] = {0}, * pTemp;
+    Kit_DsdObj_t * pRoot;
+    int piCofVar[4], pPrios[16], pFreqs[16] = {0}, piLits[16];
+    int i, k, nCBars, nSize, nMemSize;
+    unsigned * ppCofs[4][8], uSupport;
+    char pTable[16][16] = {
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
+    };
+    int fVerbose = p->pPars->fVeryVerbose;
+
+    Counter++;
+//    printf( "Run %d.\n", Counter );
+
+    // allocate storage for cofactors
+    nMemSize = Kit_TruthWordNum(nVars);
+    ppCofs[0][0] = ABC_ALLOC( unsigned, 32 * nMemSize );
+    nSize = 0;
+    for ( i = 0; i < 4; i++ )
+    for ( k = 0; k < 8; k++ )
+        ppCofs[i][k] = ppCofs[0][0] + nMemSize * nSize++;
+    assert( nSize == 32 );
+
+    // find the best cofactoring variables
+    nCBars = Kit_DsdCofactoring( pTruth, nVars, piCofVar, p->pPars->nVarsShared, 0 );
+//    nCBars = 2;
+//    piCofVar[0] = 0;
+//    piCofVar[1] = 1;
+
+
+    // copy the function
+    Kit_TruthCopy( ppCofs[0][0], pTruth, nVars );
+
+    // decompose w.r.t. these variables
+    for ( k = 0; k < nCBars; k++ )
+    {
+        nSize = (1 << k);
+        for ( i = 0; i < nSize; i++ )
+        {
+            Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] );
+            Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] );
+        }
+    }
+    nSize = (1 << nCBars);
+    // compute DSD networks
+    for ( i = 0; i < nSize; i++ )
+    {
+        ppNtks[i] = Kit_DsdDecompose( ppCofs[nCBars][i], nVars );
+        ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] );
+        Kit_DsdNtkFree( pTemp );
+        if ( fVerbose )
+        {
+            printf( "Cof%d%d: ", nCBars, i );
+            Kit_DsdPrint( stdout, ppNtks[i] );
+        }
+    }
+
+    // compute variable frequences
+    for ( i = 0; i < nSize; i++ )
+    {
+        uSupport = Kit_TruthSupport( ppCofs[nCBars][i], nVars );
+        for ( k = 0; k < nVars; k++ )
+            if ( uSupport & (1<<k) )
+                pFreqs[k]++;
+    }
+
+    // find common variable order
+    for ( i = 0; i < nSize; i++ )
+    {
+        Kit_DsdGetSupports( ppNtks[i] );
+        Lpk_CreateVarOrder( ppNtks[i], pTable );
+    }
+    Lpk_CreateCommonOrder( pTable, piCofVar, nCBars, pPrios, nVars, fVerbose );
+    // update priorities with frequences
+    for ( i = 0; i < nVars; i++ )
+        pPrios[i] = pPrios[i] * 256 + (16 - pFreqs[i]) * 16 + i;
+
+    if ( fVerbose )
+        printf( "After restructuring with priority:\n" );
+
+    // transform all networks according to the variable order
+    for ( i = 0; i < nSize; i++ )
+    {
+        ppNtks[i] = Kit_DsdShrink( pTemp = ppNtks[i], pPrios );
+        Kit_DsdNtkFree( pTemp );
+        Kit_DsdGetSupports( ppNtks[i] );
+        assert( ppNtks[i]->pSupps[0] <= 0xFFFF );
+        // undec nodes should be rotated in such a way that the first input has as many shared inputs as possible
+        Kit_DsdRotate( ppNtks[i], pFreqs );
+        // print the resulting networks
+        if ( fVerbose )
+        {
+            printf( "Cof%d%d: ", nCBars, i );
+            Kit_DsdPrint( stdout, ppNtks[i] );
+        }
+    }
+ 
+    for ( i = 0; i < nSize; i++ )
+    {
+        // collect the roots
+        pRoot = Kit_DsdNtkRoot(ppNtks[i]);
+        if ( pRoot->Type == KIT_DSD_CONST1 )
+            piLits[i] = Abc_LitIsCompl(ppNtks[i]->Root)? -2: -1;
+        else if ( pRoot->Type == KIT_DSD_VAR )
+            piLits[i] = Abc_LitNotCond( pRoot->pFans[0], Abc_LitIsCompl(ppNtks[i]->Root) );
+        else
+            piLits[i] = ppNtks[i]->Root;
+    }
+
+
+    // recursively construct AIG for mapping
+    p->fCofactoring = 1;
+    pResult = Lpk_MapTreeMulti_rec( p, ppNtks, piLits, piCofVar, nCBars, ppLeaves, nVars, pPrios );
+    p->fCofactoring = 0;
+
+    if ( fVerbose )
+        printf( "\n" );
+
+    // verify the transformations
+    nSize = (1 << nCBars);
+    for ( i = 0; i < nSize; i++ )
+        Kit_DsdTruth( ppNtks[i], ppCofs[nCBars][i] );
+    // mux the truth tables
+    for ( k = nCBars-1; k >= 0; k-- )
+    {
+        nSize = (1 << k);
+        for ( i = 0; i < nSize; i++ )
+            Kit_TruthMuxVar( ppCofs[k][i], ppCofs[k+1][2*i+0], ppCofs[k+1][2*i+1], nVars, piCofVar[k] );
+    }
+    if ( !Extra_TruthIsEqual( pTruth, ppCofs[0][0], nVars ) )
+        printf( "Verification failed.\n" );
+
+
+    // free the networks
+    for ( i = 0; i < 8; i++ )
+        if ( ppNtks[i] )
+            Kit_DsdNtkFree( ppNtks[i] );
+    ABC_FREE( ppCofs[0][0] );
+
+    return pResult;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/lpk/lpkMux.c b/abc-build/src/opt/lpk/lpkMux.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/lpk/lpkMux.c
@@ -0,0 +1,252 @@
+/**CFile****************************************************************
+
+  FileName    [lpkMux.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast Boolean matching for LUT structures.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: lpkMux.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Find the best cofactoring variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Lpk_MapTreeBestCofVar( Lpk_Man_t * p, unsigned * pTruth, int nVars, unsigned * pCof0, unsigned * pCof1 )
+{
+    int i, iBestVar, nSuppSizeCur0, nSuppSizeCur1, nSuppSizeCur, nSuppSizeMin;
+    // iterate through variables
+    iBestVar = -1;
+    nSuppSizeMin = KIT_INFINITY;
+    for ( i = 0; i < nVars; i++ )
+    {
+        // cofactor the functiona and get support sizes
+        Kit_TruthCofactor0New( pCof0, pTruth, nVars, i );
+        Kit_TruthCofactor1New( pCof1, pTruth, nVars, i );
+        nSuppSizeCur0 = Kit_TruthSupportSize( pCof0, nVars );
+        nSuppSizeCur1 = Kit_TruthSupportSize( pCof1, nVars );
+        nSuppSizeCur  = nSuppSizeCur0 + nSuppSizeCur1;
+        // skip cofactoring that goes above the limit
+        if ( nSuppSizeCur0 > p->pPars->nLutSize || nSuppSizeCur1 > p->pPars->nLutSize )
+            continue;
+        // compare this variable with other variables
+        if ( nSuppSizeMin > nSuppSizeCur ) 
+        {
+            nSuppSizeMin = nSuppSizeCur;
+            iBestVar = i;
+        }
+    }
+    // cofactor w.r.t. this variable
+    if ( iBestVar != -1 )
+    {
+        Kit_TruthCofactor0New( pCof0, pTruth, nVars, iBestVar );
+        Kit_TruthCofactor1New( pCof1, pTruth, nVars, iBestVar );
+    }
+    return iBestVar;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Maps the function by the best cofactoring.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapTreeMux_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves )
+{
+    unsigned * pCof0 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 0 );
+    unsigned * pCof1 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 1 );
+    If_Obj_t * pObj0, * pObj1;
+    Kit_DsdNtk_t * ppNtks[2];
+    int iBestVar;
+    assert( nVars > 3 );
+    p->fCalledOnce = 1;
+    // cofactor w.r.t. the best variable
+    iBestVar = Lpk_MapTreeBestCofVar( p, pTruth, nVars, pCof0, pCof1 );
+    if ( iBestVar == -1 )
+        return NULL;
+    // decompose the functions
+    ppNtks[0] = Kit_DsdDecompose( pCof0, nVars );
+    ppNtks[1] = Kit_DsdDecompose( pCof1, nVars );
+    if ( p->pPars->fVeryVerbose )
+    {
+        printf( "Cofactoring w.r.t. var %c (%d -> %d+%d supp vars):\n", 
+            'a'+iBestVar, nVars, Kit_TruthSupportSize(pCof0, nVars), Kit_TruthSupportSize(pCof1, nVars) );
+        Kit_DsdPrintExpanded( ppNtks[0] );
+        Kit_DsdPrintExpanded( ppNtks[1] );
+    }
+    // map the DSD structures
+    pObj0 = Lpk_MapTree_rec( p, ppNtks[0], ppLeaves, ppNtks[0]->Root, NULL );
+    pObj1 = Lpk_MapTree_rec( p, ppNtks[1], ppLeaves, ppNtks[1]->Root, NULL );
+    Kit_DsdNtkFree( ppNtks[0] );
+    Kit_DsdNtkFree( ppNtks[1] );
+    return If_ManCreateMux( p->pIfMan, pObj0, pObj1, ppLeaves[iBestVar] );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Implements support-reducing decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapSuppRedDec_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves )
+{
+    Kit_DsdNtk_t * pNtkDec, * pNtkComp, * ppNtks[2], * pTemp;
+    If_Obj_t * pObjNew;
+    unsigned * pCof0 = (unsigned *)Vec_PtrEntry( p->vTtNodes,  0 );
+    unsigned * pCof1 = (unsigned *)Vec_PtrEntry( p->vTtNodes,  1 );
+    unsigned * pDec0 = (unsigned *)Vec_PtrEntry( p->vTtNodes,  2 );
+    unsigned * pDec1 = (unsigned *)Vec_PtrEntry( p->vTtNodes,  3 );
+    unsigned * pDec  = (unsigned *)Vec_PtrEntry( p->vTtNodes,  4 );
+    unsigned * pCo00 = (unsigned *)Vec_PtrEntry( p->vTtNodes,  5 );
+    unsigned * pCo01 = (unsigned *)Vec_PtrEntry( p->vTtNodes,  6 );
+    unsigned * pCo10 = (unsigned *)Vec_PtrEntry( p->vTtNodes,  7 );
+    unsigned * pCo11 = (unsigned *)Vec_PtrEntry( p->vTtNodes,  8 );
+    unsigned * pCo0  = (unsigned *)Vec_PtrEntry( p->vTtNodes,  9 );
+    unsigned * pCo1  = (unsigned *)Vec_PtrEntry( p->vTtNodes, 10 );
+    unsigned * pCo   = (unsigned *)Vec_PtrEntry( p->vTtNodes, 11 );
+    int TrueMint0, TrueMint1, FalseMint0, FalseMint1;
+    int uSubsets, uSubset0, uSubset1, iVar, iVarReused, i;
+
+    // determine if supp-red decomposition exists
+    uSubsets = Lpk_MapSuppRedDecSelect( p, pTruth, nVars, &iVar, &iVarReused );
+    if ( uSubsets == 0 )
+        return NULL;
+    p->nCalledSRed++;
+
+    // get the cofactors
+    Kit_TruthCofactor0New( pCof0, pTruth, nVars, iVar );
+    Kit_TruthCofactor1New( pCof1, pTruth, nVars, iVar );
+
+    // get the bound sets
+    uSubset0 = uSubsets & 0xFFFF;
+    uSubset1 = uSubsets >> 16;
+
+    // compute the decomposed functions
+    ppNtks[0] = Kit_DsdDecompose( pCof0, nVars );
+    ppNtks[1] = Kit_DsdDecompose( pCof1, nVars );
+    ppNtks[0] = Kit_DsdExpand( pTemp = ppNtks[0] );      Kit_DsdNtkFree( pTemp );
+    ppNtks[1] = Kit_DsdExpand( pTemp = ppNtks[1] );      Kit_DsdNtkFree( pTemp );
+    Kit_DsdTruthPartial( p->pDsdMan, ppNtks[0], pDec0, uSubset0 );
+    Kit_DsdTruthPartial( p->pDsdMan, ppNtks[1], pDec1, uSubset1 );
+//    Kit_DsdTruthPartialTwo( p->pDsdMan, ppNtks[0], uSubset0, iVarReused, pCo0, pDec0 );
+//    Kit_DsdTruthPartialTwo( p->pDsdMan, ppNtks[1], uSubset1, iVarReused, pCo1, pDec1 );
+    Kit_DsdNtkFree( ppNtks[0] );
+    Kit_DsdNtkFree( ppNtks[1] );
+//Kit_DsdPrintFromTruth( pDec0, nVars );
+//Kit_DsdPrintFromTruth( pDec1, nVars );
+    // get the decomposed function
+    Kit_TruthMuxVar( pDec, pDec0, pDec1, nVars, iVar );
+
+    // find any true assignments of the decomposed functions
+    TrueMint0 = Kit_TruthFindFirstBit( pDec0, nVars );
+    TrueMint1 = Kit_TruthFindFirstBit( pDec1, nVars );
+    assert( TrueMint0 >= 0 && TrueMint1 >= 0 );
+    // find any false assignments of the decomposed functions
+    FalseMint0 = Kit_TruthFindFirstZero( pDec0, nVars );
+    FalseMint1 = Kit_TruthFindFirstZero( pDec1, nVars );
+    assert( FalseMint0 >= 0 && FalseMint1 >= 0 );
+
+    // cofactor the cofactors according to these minterms
+    Kit_TruthCopy( pCo00, pCof0, nVars );
+    Kit_TruthCopy( pCo01, pCof0, nVars );
+    for ( i = 0; i < nVars; i++ )
+        if ( uSubset0 & (1 << i) )
+        {
+            if ( FalseMint0 & (1 << i) )
+                Kit_TruthCofactor1( pCo00, nVars, i );
+            else
+                Kit_TruthCofactor0( pCo00, nVars, i );
+            if ( TrueMint0 & (1 << i) )
+                Kit_TruthCofactor1( pCo01, nVars, i );
+            else
+                Kit_TruthCofactor0( pCo01, nVars, i );
+        }
+    Kit_TruthCopy( pCo10, pCof1, nVars );
+    Kit_TruthCopy( pCo11, pCof1, nVars );
+    for ( i = 0; i < nVars; i++ )
+        if ( uSubset1 & (1 << i) )
+        {
+            if ( FalseMint1 & (1 << i) )
+                Kit_TruthCofactor1( pCo10, nVars, i );
+            else
+                Kit_TruthCofactor0( pCo10, nVars, i );
+            if ( TrueMint1 & (1 << i) )
+                Kit_TruthCofactor1( pCo11, nVars, i );
+            else
+                Kit_TruthCofactor0( pCo11, nVars, i );
+        }
+
+    // derive the functions by composing them with the new variable (iVarReused)
+    Kit_TruthMuxVar( pCo0, pCo00, pCo01, nVars, iVarReused );
+    Kit_TruthMuxVar( pCo1, pCo10, pCo11, nVars, iVarReused );
+//Kit_DsdPrintFromTruth( pCo0, nVars );
+//Kit_DsdPrintFromTruth( pCo1, nVars );
+
+    // derive the composition function
+    Kit_TruthMuxVar( pCo , pCo0 , pCo1 , nVars, iVar );
+
+    // process the decomposed function
+    pNtkDec = Kit_DsdDecompose( pDec, nVars );
+    pNtkComp = Kit_DsdDecompose( pCo, nVars );
+//Kit_DsdPrint( stdout, pNtkDec );
+//Kit_DsdPrint( stdout, pNtkComp );
+//printf( "cofactored variable %c\n", 'a' + iVar );
+//printf( "reused variable %c\n", 'a' + iVarReused );
+
+    ppLeaves[iVarReused] = Lpk_MapTree_rec( p, pNtkDec, ppLeaves, pNtkDec->Root, NULL );
+    pObjNew = Lpk_MapTree_rec( p, pNtkComp, ppLeaves, pNtkComp->Root, NULL );
+
+    Kit_DsdNtkFree( pNtkDec );
+    Kit_DsdNtkFree( pNtkComp );
+    return pObjNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/lpk/lpkSets.c b/abc-build/src/opt/lpk/lpkSets.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/lpk/lpkSets.c
@@ -0,0 +1,445 @@
+/**CFile****************************************************************
+
+  FileName    [lpkSets.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast Boolean matching for LUT structures.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: lpkSets.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Lpk_Set_t_ Lpk_Set_t;
+struct Lpk_Set_t_
+{
+    char         iVar;        // the cofactoring variable
+    char         Over;        // the overlap in supports
+    char         SRed;        // the support reduction
+    char         Size;        // the size of the boundset
+    unsigned     uSubset0;    // the first subset (with removed)
+    unsigned     uSubset1;    // the second subset (with removed)
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively computes decomposable subsets.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Lpk_ComputeSets_rec( Kit_DsdNtk_t * p, int iLit, Vec_Int_t * vSets )
+{
+    unsigned i, iLitFanin, uSupport, uSuppCur;
+    Kit_DsdObj_t * pObj;
+    // consider the case of simple gate
+    pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) );
+    if ( pObj == NULL )
+        return (1 << Abc_Lit2Var(iLit));
+    if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR )
+    {
+        unsigned uSupps[16], Limit, s;
+        uSupport = 0;
+        Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i )
+        {
+            uSupps[i] = Lpk_ComputeSets_rec( p, iLitFanin, vSets );
+            uSupport |= uSupps[i];
+        }
+        // create all subsets, except empty and full
+        Limit = (1 << pObj->nFans) - 1;
+        for ( s = 1; s < Limit; s++ )
+        {
+            uSuppCur = 0;
+            for ( i = 0; i < pObj->nFans; i++ )
+                if ( s & (1 << i) )
+                    uSuppCur |= uSupps[i];
+            Vec_IntPush( vSets, uSuppCur );
+        }
+        return uSupport;
+    }
+    assert( pObj->Type == KIT_DSD_PRIME );
+    // get the cumulative support of all fanins
+    uSupport = 0;
+    Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i )
+    {
+        uSuppCur  = Lpk_ComputeSets_rec( p, iLitFanin, vSets );
+        uSupport |= uSuppCur;
+        Vec_IntPush( vSets, uSuppCur );
+    }
+    return uSupport;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the set of subsets of decomposable variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Lpk_ComputeSets( Kit_DsdNtk_t * p, Vec_Int_t * vSets )
+{
+    unsigned uSupport, Entry;
+    int Number, i;
+    assert( p->nVars <= 16 );
+    Vec_IntClear( vSets );
+    Vec_IntPush( vSets, 0 );
+    if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 )
+        return 0;
+    if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR )
+    {
+        uSupport = ( 1 << Abc_Lit2Var(Kit_DsdNtkRoot(p)->pFans[0]) );
+        Vec_IntPush( vSets, uSupport );
+        return uSupport;
+    }
+    uSupport = Lpk_ComputeSets_rec( p, p->Root, vSets );
+    assert( (uSupport & 0xFFFF0000) == 0 );
+    Vec_IntPush( vSets, uSupport );
+    // set the remaining variables
+    Vec_IntForEachEntry( vSets, Number, i )
+    {
+        Entry = Number;
+        Vec_IntWriteEntry( vSets, i, Entry | ((uSupport & ~Entry) << 16) );
+    }
+    return uSupport;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the sets of subsets.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Lpk_PrintSetOne( int uSupport )
+{
+    unsigned k;
+    for ( k = 0; k < 16; k++ )
+        if ( uSupport & (1<<k) )
+            printf( "%c", 'a'+k );
+    printf( " " );
+}
+/**Function*************************************************************
+
+  Synopsis    [Prints the sets of subsets.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Lpk_PrintSets( Vec_Int_t * vSets )
+{
+    unsigned uSupport;
+    int Number, i;
+    printf( "Subsets(%d): ", Vec_IntSize(vSets) );
+    Vec_IntForEachEntry( vSets, Number, i )
+    {
+        uSupport = Number;
+        Lpk_PrintSetOne( uSupport );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes maximal support reducing bound-sets.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lpk_ComposeSets( Vec_Int_t * vSets0, Vec_Int_t * vSets1, int nVars, int iCofVar,
+    Lpk_Set_t * pStore, int * pSize, int nSizeLimit )
+{
+    static int nTravId = 0;            // the number of the times this is visited
+    static int TravId[1<<16] = {0};    // last visited
+    static char SRed[1<<16];           // best support reduction
+    static char Over[1<<16];           // best overlaps
+    static unsigned Parents[1<<16];    // best set of parents
+    static unsigned short Used[1<<16]; // storage for used subsets
+    int nSuppSize, nSuppOver, nSuppRed, nUsed, nMinOver, i, k, s;
+    unsigned Entry, Entry0, Entry1;
+    unsigned uSupp, uSupp0, uSupp1, uSuppTotal;
+    Lpk_Set_t * pEntry;
+
+    if ( nTravId == (1 << 30) )
+        memset( TravId, 0, sizeof(int) * (1 << 16) );
+
+    // collect support reducing subsets
+    nUsed = 0;
+    nTravId++;
+    uSuppTotal = Kit_BitMask(nVars) & ~(1<<iCofVar);
+    Vec_IntForEachEntry( vSets0, Entry0, i )
+    Vec_IntForEachEntry( vSets1, Entry1, k )
+    {
+        uSupp0 = (Entry0 & 0xFFFF);
+        uSupp1 = (Entry1 & 0xFFFF);
+        // skip trivial
+        if ( uSupp0 == 0 || uSupp1 == 0 || (uSupp0 | uSupp1) == uSuppTotal )
+            continue;
+        if ( Kit_WordHasOneBit(uSupp0) && Kit_WordHasOneBit(uSupp1) )
+            continue;
+        // get the entry
+        Entry = Entry0 | Entry1;
+        uSupp = Entry & 0xFFFF;
+        // set the bound set size
+        nSuppSize = Kit_WordCountOnes( uSupp );
+        // get the number of overlapping vars
+        nSuppOver = Kit_WordCountOnes( Entry & (Entry >> 16) );
+        // get the support reduction
+        nSuppRed  = nSuppSize - 1 - nSuppOver;
+        // only consider support-reducing subsets
+        if ( nSuppRed <= 0 )
+            continue;
+        // check if this support is already used
+        if ( TravId[uSupp] < nTravId )
+        {
+            Used[nUsed++] = uSupp;
+
+            TravId[uSupp] = nTravId;
+            SRed[uSupp] = nSuppRed;
+            Over[uSupp] = nSuppOver;
+            Parents[uSupp] = (k << 16) | i;
+        }
+        else if ( TravId[uSupp] == nTravId && SRed[uSupp] < nSuppRed )
+        {
+            TravId[uSupp] = nTravId;
+            SRed[uSupp] = nSuppRed;
+            Over[uSupp] = nSuppOver;
+            Parents[uSupp] = (k << 16) | i;
+        }
+    }
+
+    // find the minimum overlap
+    nMinOver = 1000;
+    for ( s = 0; s < nUsed; s++ )
+        if ( nMinOver > Over[Used[s]] )
+            nMinOver = Over[Used[s]];
+
+
+    // collect the accumulated ones
+    for ( s = 0; s < nUsed; s++ )
+        if ( Over[Used[s]] == nMinOver )
+        {
+            // save the entry
+            if ( *pSize == nSizeLimit )
+                return;
+            pEntry = pStore + (*pSize)++;
+
+            i = Parents[Used[s]] & 0xFFFF;
+            k = Parents[Used[s]] >> 16;
+
+            pEntry->uSubset0 = Vec_IntEntry(vSets0, i);
+            pEntry->uSubset1 = Vec_IntEntry(vSets1, k);
+            Entry  = pEntry->uSubset0 | pEntry->uSubset1;
+
+            // record the cofactoring variable
+            pEntry->iVar = iCofVar;
+            // set the bound set size
+            pEntry->Size = Kit_WordCountOnes( Entry & 0xFFFF );
+            // get the number of overlapping vars
+            pEntry->Over = Kit_WordCountOnes( Entry & (Entry >> 16) );
+            // get the support reduction
+            pEntry->SRed = pEntry->Size - 1 - pEntry->Over;
+            assert( pEntry->SRed > 0 );
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints one set.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lpk_MapSuppPrintSet( Lpk_Set_t * pSet, int i )
+{
+    unsigned Entry;
+    Entry = pSet->uSubset0 | pSet->uSubset1;
+    printf( "%2d : ", i );
+    printf( "Var = %c  ",  'a' + pSet->iVar );
+    printf( "Size = %2d  ", pSet->Size );
+    printf( "Over = %2d  ", pSet->Over );
+    printf( "SRed = %2d  ", pSet->SRed );
+    Lpk_PrintSetOne( Entry );
+    printf( "              " );
+    Lpk_PrintSetOne( Entry >> 16 );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates the cofactors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Lpk_MapSuppRedDecSelect( Lpk_Man_t * p, unsigned * pTruth, int nVars, int * piVar, int * piVarReused )
+{
+    static int nStoreSize = 256;
+    static Lpk_Set_t pStore[256], * pSet, * pSetBest;
+    Kit_DsdNtk_t * ppNtks[2], * pTemp;
+    Vec_Int_t * vSets0 = p->vSets[0];
+    Vec_Int_t * vSets1 = p->vSets[1];
+    unsigned * pCof0 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 0 );
+    unsigned * pCof1 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 1 );
+    int nSets, i, SizeMax;//, SRedMax;
+    unsigned Entry;
+    int fVerbose = p->pPars->fVeryVerbose;
+//    int fVerbose = 0;
+
+    // collect decomposable subsets for each pair of cofactors
+    if ( fVerbose )
+    {
+        printf( "\nExploring support-reducing bound-sets of function:\n" );
+        Kit_DsdPrintFromTruth( pTruth, nVars );
+    }
+    nSets = 0;
+    for ( i = 0; i < nVars; i++ )
+    {
+        if ( fVerbose )
+        printf( "Evaluating variable %c:\n", 'a'+i );
+        // evaluate the cofactor pair
+        Kit_TruthCofactor0New( pCof0, pTruth, nVars, i );
+        Kit_TruthCofactor1New( pCof1, pTruth, nVars, i );
+        // decompose and expand
+        ppNtks[0] = Kit_DsdDecompose( pCof0, nVars );
+        ppNtks[1] = Kit_DsdDecompose( pCof1, nVars );
+        ppNtks[0] = Kit_DsdExpand( pTemp = ppNtks[0] );      Kit_DsdNtkFree( pTemp );
+        ppNtks[1] = Kit_DsdExpand( pTemp = ppNtks[1] );      Kit_DsdNtkFree( pTemp );
+        if ( fVerbose )
+        Kit_DsdPrint( stdout, ppNtks[0] );
+        if ( fVerbose )
+        Kit_DsdPrint( stdout, ppNtks[1] );
+        // compute subsets
+        Lpk_ComputeSets( ppNtks[0], vSets0 );
+        Lpk_ComputeSets( ppNtks[1], vSets1 );
+        // print subsets
+        if ( fVerbose )
+        Lpk_PrintSets( vSets0 );
+        if ( fVerbose )
+        Lpk_PrintSets( vSets1 );
+        // free the networks
+        Kit_DsdNtkFree( ppNtks[0] );
+        Kit_DsdNtkFree( ppNtks[1] );
+        // evaluate the pair
+        Lpk_ComposeSets( vSets0, vSets1, nVars, i, pStore, &nSets, nStoreSize );
+    }
+
+    // print the results
+    if ( fVerbose )
+    printf( "\n" );
+    if ( fVerbose )
+    for ( i = 0; i < nSets; i++ )
+        Lpk_MapSuppPrintSet( pStore + i, i );
+
+    // choose the best subset
+    SizeMax = 0;
+    pSetBest = NULL;
+    for ( i = 0; i < nSets; i++ )
+    {
+        pSet = pStore + i;
+        if ( pSet->Size > p->pPars->nLutSize - 1 )
+            continue;
+        if ( SizeMax < pSet->Size )
+        {
+            pSetBest = pSet;
+            SizeMax = pSet->Size;
+        }
+    }
+/*
+    // if the best is not choosen, select the one with largest reduction
+    SRedMax = 0;
+    if ( pSetBest == NULL )
+    {
+        for ( i = 0; i < nSets; i++ )
+        {
+            pSet = pStore + i;
+            if ( SRedMax < pSet->SRed )
+            {
+                pSetBest = pSet;
+                SRedMax = pSet->SRed;
+            }
+        }
+    }
+*/
+    if ( pSetBest == NULL )
+    {
+        if ( fVerbose )
+        printf( "Could not select a subset.\n" );
+        return 0;
+    }
+    else
+    {
+        if ( fVerbose )
+        printf( "Selected the following subset:\n" );
+        if ( fVerbose )
+        Lpk_MapSuppPrintSet( pSetBest, pSetBest - pStore );
+    }
+
+    // prepare the return result
+    // get the remaining variables
+    Entry = ((pSetBest->uSubset0 >> 16) | (pSetBest->uSubset1 >> 16));
+    // get the variables to be removed
+    Entry = Kit_BitMask(nVars) & ~(1<<pSetBest->iVar) & ~Entry;
+    // make sure there are some - otherwise it is not supp-red
+    assert( Entry );
+    // remember the first such variable
+    *piVarReused = Kit_WordFindFirstBit( Entry );
+    *piVar = pSetBest->iVar;
+    return (pSetBest->uSubset1 << 16) | (pSetBest->uSubset0 & 0xFFFF);
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/lpk/lpk_.c b/abc-build/src/opt/lpk/lpk_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/lpk/lpk_.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+  FileName    [lpk_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Fast Boolean matching for LUT structures.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: lpk_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/lpk/module.make b/abc-build/src/opt/lpk/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/lpk/module.make
@@ -0,0 +1,11 @@
+SRC +=	src/opt/lpk/lpkCore.c \
+	src/opt/lpk/lpkAbcDec.c \
+	src/opt/lpk/lpkAbcMux.c \
+	src/opt/lpk/lpkAbcDsd.c \
+	src/opt/lpk/lpkAbcUtil.c \
+	src/opt/lpk/lpkCut.c \
+	src/opt/lpk/lpkMan.c \
+	src/opt/lpk/lpkMap.c \
+	src/opt/lpk/lpkMulti.c \
+	src/opt/lpk/lpkMux.c \
+	src/opt/lpk/lpkSets.c 
diff --git a/abc-build/src/opt/mfs/mfs.h b/abc-build/src/opt/mfs/mfs.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/mfs/mfs.h
@@ -0,0 +1,89 @@
+/**CFile****************************************************************
+
+  FileName    [mfs.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The good old minimization with complete don't-cares.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mfs.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__opt__mfs__mfs_h
+#define ABC__opt__mfs__mfs_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Mfs_Par_t_ Mfs_Par_t;
+struct Mfs_Par_t_
+{
+    // general parameters
+    int           nWinTfoLevs;   // the maximum fanout levels
+    int           nFanoutsMax;   // the maximum number of fanouts
+    int           nDepthMax;     // the maximum number of logic levels
+    int           nWinMax;       // the maximum size of the window
+    int           nGrowthLevel;  // the maximum allowed growth in level
+    int           nBTLimit;      // the maximum number of conflicts in one SAT run
+    int           fRrOnly;       // perform redundance removal
+    int           fResub;        // performs resubstitution
+    int           fArea;         // performs optimization for area
+    int           fMoreEffort;   // performs high-affort minimization
+    int           fSwapEdge;     // performs edge swapping
+    int           fOneHotness;   // adds one-hotness conditions
+    int           fDelay;        // performs optimization for delay
+    int           fPower;        // performs power-aware optimization
+    int           fGiaSat;       // use new SAT solver
+    int           fVerbose;      // enable basic stats
+    int           fVeryVerbose;  // enable detailed stats
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== mfsCore.c ==========================================================*/
+extern void        Abc_NtkMfsParsDefault( Mfs_Par_t * pPars );
+extern int         Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars );
+
+ 
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/mfs/mfsCore.c b/abc-build/src/opt/mfs/mfsCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/mfs/mfsCore.c
@@ -0,0 +1,596 @@
+/**CFile****************************************************************
+
+  FileName    [mfsCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The good old minimization with complete don't-cares.]
+
+  Synopsis    [Core procedures of this package.]
+
+  Author      [Alan Mishchenko]
+
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mfsCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mfsInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Abc_NtkMfsSolveSatResub( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int fOnlyRemove, int fSkipUpdate );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMfsParsDefault( Mfs_Par_t * pPars )
+{
+    memset( pPars, 0, sizeof(Mfs_Par_t) );
+    pPars->nWinTfoLevs  =    2;
+    pPars->nFanoutsMax  =   30;
+    pPars->nDepthMax    =   20;
+    pPars->nWinMax      =  300;
+    pPars->nGrowthLevel =    0;
+    pPars->nBTLimit     = 5000;
+    pPars->fRrOnly      =    0;
+    pPars->fResub       =    1;
+    pPars->fArea        =    0;
+    pPars->fMoreEffort  =    0;
+    pPars->fSwapEdge    =    0;
+    pPars->fOneHotness  =    0;
+    pPars->fVerbose     =    0;
+    pPars->fVeryVerbose =    0;
+}
+/*
+int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    // try replacing area critical fanins
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+	{
+        if ( Abc_MfsObjProb(p, pFanin) >= 0.4 )
+        {
+            if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+                return 1;
+        } else if ( Abc_MfsObjProb(p, pFanin) >= 0.3 )
+        {
+            if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) )
+                return 1;
+        }
+	}
+    return 0;
+}
+*/
+
+int Abc_WinNode(Mfs_Man_t * p, Abc_Obj_t *pNode)
+{
+//    abctime clk;
+//    Abc_Obj_t * pFanin;
+//    int i;
+
+    p->nNodesTried++;
+    // prepare data structure for this node
+    Mfs_ManClean( p );
+    // compute window roots, window support, and window nodes
+    p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax );
+    p->vSupp  = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) );
+    p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) );
+    if ( p->pPars->nWinMax && Vec_PtrSize(p->vNodes) > p->pPars->nWinMax )
+        return 1;
+    // compute the divisors of the window
+    p->vDivs  = Abc_MfsComputeDivisors( p, pNode, Abc_ObjRequiredLevel(pNode) - 1 );
+    p->nTotalDivs += Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode);
+    // construct AIG for the window
+    p->pAigWin = Abc_NtkConstructAig( p, pNode );
+    // translate it into CNF
+    p->pCnf = Cnf_DeriveSimple( p->pAigWin, 1 + Vec_PtrSize(p->vDivs) );
+    // create the SAT problem
+    p->pSat = Abc_MfsCreateSolverResub( p, NULL, 0, 0 );
+    if ( p->pSat == NULL )
+    {
+        p->nNodesBad++;
+        return 1;
+    }
+	return 0;
+}
+
+/*
+int Abc_NtkMfsPowerResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    abctime clk;
+    Abc_Obj_t * pFanin;
+    int i;
+
+	if (Abc_WinNode(p, pNode)  // something wrong
+		return 1;
+
+    // solve the SAT problem
+	// Abc_NtkMfsEdgePower( p, pNode );
+    // try replacing area critical fanins
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        if ( Abc_MfsObjProb(p, pFanin) >= 0.37 && Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+	        return 1;
+
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        if ( Abc_MfsObjProb(p, pFanin) >= 0.1 && Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) )
+	        return 1;
+
+    if ( Abc_ObjFaninNum(pNode) == p->nFaninMax )
+        return 0;
+
+    // try replacing area critical fanins while adding two new fanins
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+            if ( Abc_MfsObjProb(p, pFanin) >= 0.37 && Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) )
+                return 1;
+        }
+    return 0;
+
+    return 1;
+}
+*/
+
+void Abc_NtkMfsPowerResub( Mfs_Man_t * p, Mfs_Par_t * pPars)
+{
+	int i, k;
+	Abc_Obj_t *pFanin, *pNode;
+	Abc_Ntk_t *pNtk = p->pNtk;
+	int nFaninMax = Abc_NtkGetFaninMax(p->pNtk);
+
+	Abc_NtkForEachNode( pNtk, pNode, k )
+	{
+		if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax )
+			continue;
+		if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax )
+			continue;
+		if (Abc_WinNode(p, pNode) )  // something wrong
+			continue;
+
+		// solve the SAT problem
+		// Abc_NtkMfsEdgePower( p, pNode );
+		// try replacing area critical fanins
+		Abc_ObjForEachFanin( pNode, pFanin, i )
+			if ( Abc_MfsObjProb(p, pFanin) >= 0.35 && Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+				continue;
+	}
+
+	Abc_NtkForEachNode( pNtk, pNode, k )
+	{
+		if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax )
+			continue;
+		if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax )
+			continue;
+		if (Abc_WinNode(p, pNode) )  // something wrong
+			continue;
+
+		// solve the SAT problem
+		// Abc_NtkMfsEdgePower( p, pNode );
+		// try replacing area critical fanins
+		Abc_ObjForEachFanin( pNode, pFanin, i )
+			if ( Abc_MfsObjProb(p, pFanin) >= 0.35 && Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+				continue;
+	}
+
+	Abc_NtkForEachNode( pNtk, pNode, k )
+	{
+		if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax )
+			continue;
+		if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax )
+			continue;
+		if (Abc_WinNode(p, pNode) ) // something wrong
+			continue;
+
+		Abc_ObjForEachFanin( pNode, pFanin, i )
+			if ( Abc_MfsObjProb(p, pFanin) >= 0.2 && Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) )
+				continue;
+	}
+/*
+	Abc_NtkForEachNode( pNtk, pNode, k )
+	{
+		if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax )
+			continue;
+		if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax - 2)
+			continue;
+		if (Abc_WinNode(p, pNode) ) // something wrong
+			continue;
+
+		Abc_ObjForEachFanin( pNode, pFanin, i )
+			if ( Abc_MfsObjProb(p, pFanin) >= 0.37 && Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) )
+				continue;
+	}
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsResub( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    abctime clk;
+    p->nNodesTried++;
+    // prepare data structure for this node
+    Mfs_ManClean( p );
+    // compute window roots, window support, and window nodes
+clk = Abc_Clock();
+    p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax );
+    p->vSupp  = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) );
+    p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) );
+p->timeWin += Abc_Clock() - clk;
+    if ( p->pPars->nWinMax && Vec_PtrSize(p->vNodes) > p->pPars->nWinMax )
+    {
+        p->nMaxDivs++;
+        return 1;
+    }
+    // compute the divisors of the window
+clk = Abc_Clock();
+    p->vDivs  = Abc_MfsComputeDivisors( p, pNode, Abc_ObjRequiredLevel(pNode) - 1 );
+    p->nTotalDivs += Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode);
+p->timeDiv += Abc_Clock() - clk;
+    // construct AIG for the window
+clk = Abc_Clock();
+    p->pAigWin = Abc_NtkConstructAig( p, pNode );
+p->timeAig += Abc_Clock() - clk;
+    // translate it into CNF
+clk = Abc_Clock();
+    p->pCnf = Cnf_DeriveSimple( p->pAigWin, 1 + Vec_PtrSize(p->vDivs) );
+p->timeCnf += Abc_Clock() - clk;
+    // create the SAT problem
+clk = Abc_Clock();
+    p->pSat = Abc_MfsCreateSolverResub( p, NULL, 0, 0 );
+    if ( p->pSat == NULL )
+    {
+        p->nNodesBad++;
+        return 1;
+    }
+//clk = Abc_Clock();
+//    if ( p->pPars->fGiaSat )
+//        Abc_NtkMfsConstructGia( p );
+//p->timeGia += Abc_Clock() - clk;
+    // solve the SAT problem
+    if ( p->pPars->fPower )
+        Abc_NtkMfsEdgePower( p, pNode );
+    else if ( p->pPars->fSwapEdge )
+        Abc_NtkMfsEdgeSwapEval( p, pNode );
+    else
+    {
+        Abc_NtkMfsResubNode( p, pNode );
+        if ( p->pPars->fMoreEffort )
+            Abc_NtkMfsResubNode2( p, pNode );
+    }
+p->timeSat += Abc_Clock() - clk;
+//    if ( p->pPars->fGiaSat )
+//        Abc_NtkMfsDeconstructGia( p );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsNode( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    Hop_Obj_t * pObj;
+    int RetValue;
+    float dProb;
+    extern Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb );
+
+    int nGain;
+    abctime clk;
+    p->nNodesTried++;
+    // prepare data structure for this node
+    Mfs_ManClean( p );
+    // compute window roots, window support, and window nodes
+clk = Abc_Clock();
+    p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax );
+    p->vSupp  = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) );
+    p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) );
+p->timeWin += Abc_Clock() - clk;
+    // count the number of patterns
+//    p->dTotalRatios += Abc_NtkConstraintRatio( p, pNode );
+    // construct AIG for the window
+clk = Abc_Clock();
+    p->pAigWin = Abc_NtkConstructAig( p, pNode );
+p->timeAig += Abc_Clock() - clk;
+    // translate it into CNF
+clk = Abc_Clock();
+    p->pCnf = Cnf_DeriveSimple( p->pAigWin, Abc_ObjFaninNum(pNode) );
+p->timeCnf += Abc_Clock() - clk;
+    // create the SAT problem
+clk = Abc_Clock();
+    p->pSat = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 );
+    if ( p->pSat && p->pPars->fOneHotness )
+        Abc_NtkAddOneHotness( p );
+    if ( p->pSat == NULL )
+        return 0;
+    // solve the SAT problem
+    RetValue = Abc_NtkMfsSolveSat( p, pNode );
+    p->nTotConfLevel += p->pSat->stats.conflicts;
+p->timeSat += Abc_Clock() - clk;
+    if ( RetValue == 0 )
+    {
+        p->nTimeOutsLevel++;
+        p->nTimeOuts++;
+        return 0;
+    }
+    // minimize the local function of the node using bi-decomposition
+    assert( p->nFanins == Abc_ObjFaninNum(pNode) );
+    dProb = p->pPars->fPower? ((float *)p->vProbs->pArray)[pNode->Id] : -1.0;
+    pObj = Abc_NodeIfNodeResyn( p->pManDec, (Hop_Man_t *)pNode->pNtk->pManFunc, (Hop_Obj_t *)pNode->pData, p->nFanins, p->vTruth, p->uCare, dProb );
+    nGain = Hop_DagSize((Hop_Obj_t *)pNode->pData) - Hop_DagSize(pObj);
+    if ( nGain >= 0 )
+    {
+        p->nNodesDec++;
+        p->nNodesGained += nGain;
+        p->nNodesGainedLevel += nGain;
+        pNode->pData = pObj;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars )
+{
+    extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+
+    Bdc_Par_t Pars = {0}, * pDecPars = &Pars;
+    ProgressBar * pProgress;
+    Mfs_Man_t * p;
+    Abc_Obj_t * pObj;
+    Vec_Vec_t * vLevels;
+    Vec_Ptr_t * vNodes;
+    int i, k, nNodes, nFaninMax;
+    abctime clk = Abc_Clock(), clk2;
+    int nTotalNodesBeg = Abc_NtkNodeNum(pNtk);
+    int nTotalEdgesBeg = Abc_NtkGetTotalFanins(pNtk);
+
+    assert( Abc_NtkIsLogic(pNtk) );
+    nFaninMax = Abc_NtkGetFaninMax(pNtk);
+    if ( pPars->fResub )
+    {
+        if ( nFaninMax > 8 )
+        {
+            printf( "Nodes with more than %d fanins will not be processed.\n", 8 );
+            nFaninMax = 8;
+        }
+    }
+    else
+    {
+        if ( nFaninMax > MFS_FANIN_MAX )
+        {
+            printf( "Nodes with more than %d fanins will not be processed.\n", MFS_FANIN_MAX );
+            nFaninMax = MFS_FANIN_MAX;
+        }
+    }
+    // perform the network sweep
+//    Abc_NtkSweep( pNtk, 0 );
+    // convert into the AIG
+    if ( !Abc_NtkToAig(pNtk) )
+    {
+        fprintf( stdout, "Converting to AIGs has failed.\n" );
+        return 0;
+    }
+    assert( Abc_NtkHasAig(pNtk) );
+
+    // start the manager
+    p = Mfs_ManAlloc( pPars );
+    p->pNtk = pNtk;
+    p->nFaninMax = nFaninMax;
+
+    // precomputer power-aware metrics
+    if ( pPars->fPower )
+    {
+        extern Vec_Int_t * Abc_NtkPowerEstimate( Abc_Ntk_t * pNtk, int fProbOne );
+        if ( pPars->fResub )
+            p->vProbs = Abc_NtkPowerEstimate( pNtk, 0 );
+        else
+            p->vProbs = Abc_NtkPowerEstimate( pNtk, 1 );
+#if 0
+        printf( "Total switching before = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) );
+#else
+		p->TotalSwitchingBeg = Abc_NtkMfsTotalSwitching(pNtk);
+#endif
+    }
+
+    if ( pNtk->pExcare )
+    {
+        Abc_Ntk_t * pTemp;
+        if ( Abc_NtkPiNum((Abc_Ntk_t *)pNtk->pExcare) != Abc_NtkCiNum(pNtk) )
+            printf( "The PI count of careset (%d) and logic network (%d) differ. Careset is not used.\n",
+                Abc_NtkPiNum((Abc_Ntk_t *)pNtk->pExcare), Abc_NtkCiNum(pNtk) );
+        else
+        {
+            pTemp = Abc_NtkStrash( (Abc_Ntk_t *)pNtk->pExcare, 0, 0, 0 );
+            p->pCare = Abc_NtkToDar( pTemp, 0, 0 );
+            Abc_NtkDelete( pTemp );
+            p->vSuppsInv = Aig_ManSupportsInverse( p->pCare );
+        }
+    }
+    if ( p->pCare != NULL )
+        printf( "Performing optimization with %d external care clauses.\n", Aig_ManCoNum(p->pCare) );
+    // prepare the BDC manager
+    if ( !pPars->fResub )
+    {
+        pDecPars->nVarsMax = (nFaninMax < 3) ? 3 : nFaninMax;
+        pDecPars->fVerbose = pPars->fVerbose;
+        p->vTruth = Vec_IntAlloc( 0 );
+        p->pManDec = Bdc_ManAlloc( pDecPars );
+    }
+
+    // label the register outputs
+    if ( p->pCare )
+    {
+        Abc_NtkForEachCi( pNtk, pObj, i )
+            pObj->pData = (void *)(ABC_PTRUINT_T)i;
+    }
+
+    // compute levels
+    Abc_NtkLevel( pNtk );
+    Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel );
+
+    // compute don't-cares for each node
+    nNodes = 0;
+    p->nTotalNodesBeg = nTotalNodesBeg;
+    p->nTotalEdgesBeg = nTotalEdgesBeg;
+    if ( pPars->fResub )
+    {
+#if 0
+        printf( "TotalSwitching (%7.2f --> ", Abc_NtkMfsTotalSwitching(pNtk) );
+#endif
+		if (pPars->fPower)
+		{
+			Abc_NtkMfsPowerResub( p, pPars);
+		} else
+		{
+        pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+        Abc_NtkForEachNode( pNtk, pObj, i )
+        {
+            if ( p->pPars->nDepthMax && (int)pObj->Level > p->pPars->nDepthMax )
+                continue;
+            if ( Abc_ObjFaninNum(pObj) < 2 || Abc_ObjFaninNum(pObj) > nFaninMax )
+                continue;
+            if ( !p->pPars->fVeryVerbose )
+                Extra_ProgressBarUpdate( pProgress, i, NULL );
+            if ( pPars->fResub )
+                Abc_NtkMfsResub( p, pObj );
+            else
+                Abc_NtkMfsNode( p, pObj );
+        }
+        Extra_ProgressBarStop( pProgress );
+#if 0
+        printf( " %7.2f )\n", Abc_NtkMfsTotalSwitching(pNtk) );
+#endif
+    }
+	} else
+    {
+#if 0
+        printf( "Total switching before  = %7.2f,  ----> ", Abc_NtkMfsTotalSwitching(pNtk) );
+#endif
+        pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) );
+        vLevels = Abc_NtkLevelize( pNtk );
+        Vec_VecForEachLevelStart( vLevels, vNodes, k, 1 )
+        {
+            if ( !p->pPars->fVeryVerbose )
+                Extra_ProgressBarUpdate( pProgress, nNodes, NULL );
+            p->nNodesGainedLevel = 0;
+            p->nTotConfLevel = 0;
+            p->nTimeOutsLevel = 0;
+            clk2 = Abc_Clock();
+            Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+            {
+                if ( p->pPars->nDepthMax && (int)pObj->Level > p->pPars->nDepthMax )
+                    break;
+                if ( Abc_ObjFaninNum(pObj) < 2 || Abc_ObjFaninNum(pObj) > nFaninMax )
+                    continue;
+                if ( pPars->fResub )
+                    Abc_NtkMfsResub( p, pObj );
+                else
+                    Abc_NtkMfsNode( p, pObj );
+            }
+            nNodes += Vec_PtrSize(vNodes);
+            if ( pPars->fVerbose )
+            {
+				/*
+            printf( "Lev = %2d. Node = %5d. Ave gain = %5.2f. Ave conf = %5.2f. T/o = %6.2f %%  ",
+                k, Vec_PtrSize(vNodes),
+                1.0*p->nNodesGainedLevel/Vec_PtrSize(vNodes),
+                1.0*p->nTotConfLevel/Vec_PtrSize(vNodes),
+                100.0*p->nTimeOutsLevel/Vec_PtrSize(vNodes) );
+            ABC_PRT( "Time", Abc_Clock() - clk2 );
+			*/
+            }
+        }
+        Extra_ProgressBarStop( pProgress );
+        Vec_VecFree( vLevels );
+#if 0
+        printf( " %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) );
+#endif
+    }
+    Abc_NtkStopReverseLevels( pNtk );
+
+    // perform the sweeping
+    if ( !pPars->fResub )
+    {
+        extern void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose );
+//        Abc_NtkSweep( pNtk, 0 );
+//        Abc_NtkBidecResyn( pNtk, 0 );
+    }
+
+    p->nTotalNodesEnd = Abc_NtkNodeNum(pNtk);
+    p->nTotalEdgesEnd = Abc_NtkGetTotalFanins(pNtk);
+
+    // undo labesl
+    if ( p->pCare )
+    {
+        Abc_NtkForEachCi( pNtk, pObj, i )
+            pObj->pData = NULL;
+    }
+
+    if ( pPars->fPower )
+	{
+#if 1
+		p->TotalSwitchingEnd = Abc_NtkMfsTotalSwitching(pNtk);
+//        printf( "Total switching after  = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) );
+#else
+        printf( "Total switching after  = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) );
+#endif
+	}
+
+    // free the manager
+    p->timeTotal = Abc_Clock() - clk;
+    Mfs_ManStop( p );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/mfs/mfsCore_.c b/abc-build/src/opt/mfs/mfsCore_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/mfs/mfsCore_.c
@@ -0,0 +1,394 @@
+/**CFile****************************************************************
+
+  FileName    [mfsCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The good old minimization with complete don't-cares.]
+
+  Synopsis    [Core procedures of this package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mfsCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mfsInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMfsParsDefault( Mfs_Par_t * pPars )
+{
+    memset( pPars, 0, sizeof(Mfs_Par_t) );
+    pPars->nWinTfoLevs  =    2;
+    pPars->nFanoutsMax  =   10;
+    pPars->nDepthMax    =   20;
+    pPars->nWinSizeMax  =  300;
+    pPars->nGrowthLevel =    0;
+    pPars->nBTLimit     = 5000;
+    pPars->fResub       =    1;
+    pPars->fArea        =    0;
+    pPars->fMoreEffort  =    0;
+    pPars->fSwapEdge    =    0;
+    pPars->fOneHotness  =    0;
+    pPars->fVerbose     =    0;
+    pPars->fVeryVerbose =    0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsResub( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    clock_t clk;
+    p->nNodesTried++;
+    // prepare data structure for this node
+    Mfs_ManClean( p ); 
+    // compute window roots, window support, and window nodes
+clk = clock();
+    p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax );
+    p->vSupp  = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) );
+    p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) );
+p->timeWin += clock() - clk;
+    if ( p->pPars->nWinSizeMax && Vec_PtrSize(p->vNodes) > p->pPars->nWinSizeMax )
+        return 1;
+    // compute the divisors of the window
+clk = clock();
+    p->vDivs  = Abc_MfsComputeDivisors( p, pNode, Abc_ObjRequiredLevel(pNode) - 1 );
+    p->nTotalDivs += Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode);
+p->timeDiv += clock() - clk;
+    // construct AIG for the window
+clk = clock();
+    p->pAigWin = Abc_NtkConstructAig( p, pNode );
+p->timeAig += clock() - clk;
+    // translate it into CNF
+clk = clock();
+    p->pCnf = Cnf_DeriveSimple( p->pAigWin, 1 + Vec_PtrSize(p->vDivs) );
+p->timeCnf += clock() - clk;
+    // create the SAT problem
+clk = clock();
+    p->pSat = Abc_MfsCreateSolverResub( p, NULL, 0, 0 );
+    if ( p->pSat == NULL )
+    {
+        p->nNodesBad++;
+        return 1;
+    }
+    // solve the SAT problem
+    if ( p->pPars->fPower )
+        Abc_NtkMfsEdgePower( p, pNode );
+    else if ( p->pPars->fSwapEdge )
+        Abc_NtkMfsEdgeSwapEval( p, pNode );
+    else
+    {
+        Abc_NtkMfsResubNode( p, pNode );
+        if ( p->pPars->fMoreEffort )
+            Abc_NtkMfsResubNode2( p, pNode );
+    }
+p->timeSat += clock() - clk;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsNode( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    Hop_Obj_t * pObj;
+    int RetValue;
+    float dProb;
+    extern Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb );
+
+    int nGain;
+    clock_t clk;
+    p->nNodesTried++;
+    // prepare data structure for this node
+    Mfs_ManClean( p );
+    // compute window roots, window support, and window nodes
+clk = clock();
+    p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax );
+    p->vSupp  = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) );
+    p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) );
+p->timeWin += clock() - clk;
+    // count the number of patterns
+//    p->dTotalRatios += Abc_NtkConstraintRatio( p, pNode );
+    // construct AIG for the window
+clk = clock();
+    p->pAigWin = Abc_NtkConstructAig( p, pNode );
+p->timeAig += clock() - clk;
+    // translate it into CNF
+clk = clock();
+    p->pCnf = Cnf_DeriveSimple( p->pAigWin, Abc_ObjFaninNum(pNode) );
+p->timeCnf += clock() - clk;
+    // create the SAT problem
+clk = clock();
+    p->pSat = Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 );
+    if ( p->pSat && p->pPars->fOneHotness )
+        Abc_NtkAddOneHotness( p );
+    if ( p->pSat == NULL )
+        return 0;
+    // solve the SAT problem
+    RetValue = Abc_NtkMfsSolveSat( p, pNode );
+    p->nTotConfLevel += p->pSat->stats.conflicts;
+p->timeSat += clock() - clk;
+    if ( RetValue == 0 )
+    {
+        p->nTimeOutsLevel++;
+        p->nTimeOuts++;
+        return 0;
+    }
+    // minimize the local function of the node using bi-decomposition
+    assert( p->nFanins == Abc_ObjFaninNum(pNode) );
+    dProb = p->pPars->fPower? ((float *)p->vProbs->pArray)[pNode->Id] : -1.0;
+    pObj = Abc_NodeIfNodeResyn( p->pManDec, pNode->pNtk->pManFunc, pNode->pData, p->nFanins, p->vTruth, p->uCare, dProb );
+    nGain = Hop_DagSize(pNode->pData) - Hop_DagSize(pObj);
+    if ( nGain >= 0 )
+    {
+        p->nNodesDec++;
+        p->nNodesGained += nGain;
+        p->nNodesGainedLevel += nGain;
+        pNode->pData = pObj;    
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars )
+{
+    extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+
+    Bdc_Par_t Pars = {0}, * pDecPars = &Pars;
+    ProgressBar * pProgress;
+    Mfs_Man_t * p;
+    Abc_Obj_t * pObj;
+    Vec_Vec_t * vLevels;
+    Vec_Ptr_t * vNodes;
+    int i, k, nNodes, nFaninMax;
+    clock_t clk = clock(), clk2;
+    int nTotalNodesBeg = Abc_NtkNodeNum(pNtk);
+    int nTotalEdgesBeg = Abc_NtkGetTotalFanins(pNtk);
+
+    assert( Abc_NtkIsLogic(pNtk) );
+    nFaninMax = Abc_NtkGetFaninMax(pNtk);
+    if ( pPars->fResub )
+    {
+        if ( nFaninMax > 8 )
+        {
+            printf( "Nodes with more than %d fanins will not be processed.\n", 8 );
+            nFaninMax = 8;
+        }
+    }
+    else
+    {
+        if ( nFaninMax > MFS_FANIN_MAX )
+        {
+            printf( "Nodes with more than %d fanins will not be processed.\n", MFS_FANIN_MAX );
+            nFaninMax = MFS_FANIN_MAX;
+        }
+    }
+    // perform the network sweep
+    Abc_NtkSweep( pNtk, 0 );
+    // convert into the AIG
+    if ( !Abc_NtkToAig(pNtk) )
+    {
+        fprintf( stdout, "Converting to AIGs has failed.\n" );
+        return 0;
+    }
+    assert( Abc_NtkHasAig(pNtk) );
+
+    // start the manager
+    p = Mfs_ManAlloc( pPars );
+    p->pNtk = pNtk;
+    p->nFaninMax = nFaninMax;
+
+    // precomputer power-aware metrics
+    if ( pPars->fPower )
+    {
+        extern Vec_Int_t * Abc_NtkPowerEstimate( Abc_Ntk_t * pNtk, int fProbOne );
+        if ( pPars->fResub )
+            p->vProbs = Abc_NtkPowerEstimate( pNtk, 0 );
+        else
+            p->vProbs = Abc_NtkPowerEstimate( pNtk, 1 );
+        printf( "Total switching before = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) );
+    }
+
+    if ( pNtk->pExcare )
+    {
+        Abc_Ntk_t * pTemp;
+        if ( Abc_NtkPiNum(pNtk->pExcare) != Abc_NtkCiNum(pNtk) )
+            printf( "The PI count of careset (%d) and logic network (%d) differ. Careset is not used.\n", 
+                Abc_NtkPiNum(pNtk->pExcare), Abc_NtkCiNum(pNtk) );
+        else
+        {
+            pTemp = Abc_NtkStrash( pNtk->pExcare, 0, 0, 0 );
+            p->pCare = Abc_NtkToDar( pTemp, 0, 0 );
+            Abc_NtkDelete( pTemp );
+            p->vSuppsInv = Aig_ManSupportsInverse( p->pCare );
+        }
+    }
+    if ( p->pCare != NULL )
+        printf( "Performing optimization with %d external care clauses.\n", Aig_ManPoNum(p->pCare) );
+    // prepare the BDC manager
+    if ( !pPars->fResub )
+    {
+        pDecPars->nVarsMax = (nFaninMax < 3) ? 3 : nFaninMax;
+        pDecPars->fVerbose = pPars->fVerbose;
+        p->vTruth = Vec_IntAlloc( 0 );
+        p->pManDec = Bdc_ManAlloc( pDecPars );
+    }
+
+    // label the register outputs
+    if ( p->pCare )
+    {
+        Abc_NtkForEachCi( pNtk, pObj, i )
+            pObj->pData = (void *)(PORT_PTRUINT_T)i;
+    }
+ 
+    // compute levels
+    Abc_NtkLevel( pNtk );
+    Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel );
+
+    // compute don't-cares for each node
+    nNodes = 0;
+    p->nTotalNodesBeg = nTotalNodesBeg;
+    p->nTotalEdgesBeg = nTotalEdgesBeg;
+    if ( pPars->fResub )
+    {
+        pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+        Abc_NtkForEachNode( pNtk, pObj, i )
+        {
+            if ( p->pPars->nDepthMax && (int)pObj->Level > p->pPars->nDepthMax )
+                continue;
+            if ( Abc_ObjFaninNum(pObj) < 2 || Abc_ObjFaninNum(pObj) > nFaninMax )
+                continue;
+            if ( !p->pPars->fVeryVerbose )
+                Extra_ProgressBarUpdate( pProgress, i, NULL );
+            if ( pPars->fResub )
+                Abc_NtkMfsResub( p, pObj );
+            else
+                Abc_NtkMfsNode( p, pObj );
+        }
+        Extra_ProgressBarStop( pProgress );
+    }
+    else
+    {
+        pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) );
+        vLevels = Abc_NtkLevelize( pNtk );
+        Vec_VecForEachLevelStart( vLevels, vNodes, k, 1 )
+        {
+            if ( !p->pPars->fVeryVerbose )
+                Extra_ProgressBarUpdate( pProgress, nNodes, NULL );
+            p->nNodesGainedLevel = 0;
+            p->nTotConfLevel = 0;
+            p->nTimeOutsLevel = 0;
+            clk2 = clock();
+            Vec_PtrForEachEntry( vNodes, pObj, i )
+            {
+                if ( p->pPars->nDepthMax && (int)pObj->Level > p->pPars->nDepthMax )
+                    break;
+                if ( Abc_ObjFaninNum(pObj) < 2 || Abc_ObjFaninNum(pObj) > nFaninMax )
+                    continue;
+                if ( pPars->fResub )
+                    Abc_NtkMfsResub( p, pObj );
+                else 
+                    Abc_NtkMfsNode( p, pObj );
+            }
+            nNodes += Vec_PtrSize(vNodes);
+            if ( pPars->fVerbose )
+            {
+            printf( "Lev = %2d. Node = %5d. Ave gain = %5.2f. Ave conf = %5.2f. T/o = %6.2f %%  ", 
+                k, Vec_PtrSize(vNodes),
+                1.0*p->nNodesGainedLevel/Vec_PtrSize(vNodes),
+                1.0*p->nTotConfLevel/Vec_PtrSize(vNodes),
+                100.0*p->nTimeOutsLevel/Vec_PtrSize(vNodes) );
+            PRT( "Time", clock() - clk2 );
+            }
+        }
+        Extra_ProgressBarStop( pProgress );
+        Vec_VecFree( vLevels );
+    }
+    Abc_NtkStopReverseLevels( pNtk );
+
+    // perform the sweeping
+    if ( !pPars->fResub )
+    {
+        extern void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose );
+//        Abc_NtkSweep( pNtk, 0 );
+//        Abc_NtkBidecResyn( pNtk, 0 );
+    }
+
+    p->nTotalNodesEnd = Abc_NtkNodeNum(pNtk);
+    p->nTotalEdgesEnd = Abc_NtkGetTotalFanins(pNtk);
+
+    // undo labesl
+    if ( p->pCare )
+    {
+        Abc_NtkForEachCi( pNtk, pObj, i )
+            pObj->pData = NULL;
+    }
+    if ( pPars->fPower )
+        printf( "Total switching after  = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) );
+
+    // free the manager
+    p->timeTotal = clock() - clk;
+    Mfs_ManStop( p );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/mfs/mfsDiv.c b/abc-build/src/opt/mfs/mfsDiv.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/mfs/mfsDiv.c
@@ -0,0 +1,309 @@
+/**CFile****************************************************************
+
+  FileName    [mfsDiv.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The good old minimization with complete don't-cares.]
+
+  Synopsis    [Procedures to compute candidate divisors.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mfsDiv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mfsInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Marks and collects the TFI cone of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MfsWinMarkTfi_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vCone )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return;
+    Abc_NodeSetTravIdCurrent( pObj );
+    if ( Abc_ObjIsCi(pObj) )
+    {
+        Vec_PtrPush( vCone, pObj );
+        return;
+    }
+    assert( Abc_ObjIsNode(pObj) );
+    // visit the fanins of the node
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        Abc_MfsWinMarkTfi_rec( pFanin, vCone );
+    Vec_PtrPush( vCone, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks and collects the TFI cone of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_MfsWinMarkTfi( Abc_Obj_t * pNode )
+{
+    Vec_Ptr_t * vCone;
+    vCone = Vec_PtrAlloc( 100 );
+    Abc_MfsWinMarkTfi_rec( pNode, vCone );
+    return vCone;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the TFO of the collected nodes up to the given level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MfsWinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    if ( Abc_ObjIsCo(pObj) || (int)pObj->Level > nLevelLimit )
+        return;
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return;
+    Abc_NodeSetTravIdCurrent( pObj );
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        Abc_MfsWinSweepLeafTfo_rec( pFanout, nLevelLimit );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences the node's MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_MfsNodeDeref_rec( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    int i, Counter = 1;
+    if ( Abc_ObjIsCi(pNode) )
+        return 0;
+    Abc_NodeSetTravIdCurrent( pNode );
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        assert( pFanin->vFanouts.nSize > 0 );
+        if ( --pFanin->vFanouts.nSize == 0 )
+            Counter += Abc_MfsNodeDeref_rec( pFanin );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [References the node's MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_MfsNodeRef_rec( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    int i, Counter = 1;
+    if ( Abc_ObjIsCi(pNode) )
+        return 0;
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        if ( pFanin->vFanouts.nSize++ == 0 )
+            Counter += Abc_MfsNodeRef_rec( pFanin );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Labels MFFC of the node with the current trav ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_MfsWinVisitMffc( Abc_Obj_t * pNode )
+{
+    int Count1, Count2;
+    assert( Abc_ObjIsNode(pNode) );
+    // dereference the node (mark with the current trav ID)
+    Count1 = Abc_MfsNodeDeref_rec( pNode );
+    // reference it back
+    Count2 = Abc_MfsNodeRef_rec( pNode );
+    assert( Count1 == Count2 );
+    return Count1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes divisors and add them to nodes in the window.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_MfsComputeDivisors( Mfs_Man_t * p, Abc_Obj_t * pNode, int nLevDivMax )
+{
+    Vec_Ptr_t * vCone, * vDivs;
+    Abc_Obj_t * pObj, * pFanout, * pFanin;
+    int k, f, m;
+    int nDivsPlus = 0, nTrueSupp;
+    assert( p->vDivs == NULL );
+
+    // mark the TFI with the current trav ID
+    Abc_NtkIncrementTravId( pNode->pNtk );
+    vCone = Abc_MfsWinMarkTfi( pNode );
+
+    // count the number of PIs
+    nTrueSupp = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, k )
+        nTrueSupp += Abc_ObjIsCi(pObj);
+//    printf( "%d(%d) ", Vec_PtrSize(p->vSupp), m );
+
+    // mark with the current trav ID those nodes that should not be divisors:
+    // (1) the node and its TFO
+    // (2) the MFFC of the node
+    // (3) the node's fanins (these are treated as a special case)
+    Abc_NtkIncrementTravId( pNode->pNtk );
+    Abc_MfsWinSweepLeafTfo_rec( pNode, nLevDivMax );
+//    Abc_MfsWinVisitMffc( pNode );
+    Abc_ObjForEachFanin( pNode, pObj, k )
+        Abc_NodeSetTravIdCurrent( pObj );
+
+    // at this point the nodes are marked with two trav IDs:
+    // nodes to be collected as divisors are marked with previous trav ID
+    // nodes to be avoided as divisors are marked with current trav ID
+
+    // start collecting the divisors
+    vDivs = Vec_PtrAlloc( p->pPars->nWinMax );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, k )
+    {
+        if ( !Abc_NodeIsTravIdPrevious(pObj) )
+            continue;
+        if ( (int)pObj->Level > nLevDivMax )
+            continue;
+        Vec_PtrPush( vDivs, pObj );
+        if ( Vec_PtrSize(vDivs) >= p->pPars->nWinMax )
+            break;
+    }
+    Vec_PtrFree( vCone );
+
+    // explore the fanouts of already collected divisors
+    if ( Vec_PtrSize(vDivs) < p->pPars->nWinMax )
+    Vec_PtrForEachEntry( Abc_Obj_t *, vDivs, pObj, k )
+    {
+        // consider fanouts of this node
+        Abc_ObjForEachFanout( pObj, pFanout, f )
+        {
+            // stop if there are too many fanouts
+            if ( p->pPars->nFanoutsMax && f > p->pPars->nFanoutsMax )
+                break;
+            // skip nodes that are already added
+            if ( Abc_NodeIsTravIdPrevious(pFanout) )
+                continue;
+            // skip nodes in the TFO or in the MFFC of node
+            if ( Abc_NodeIsTravIdCurrent(pFanout) )
+                continue;
+            // skip COs
+            if ( !Abc_ObjIsNode(pFanout) ) 
+                continue;
+            // skip nodes with large level
+            if ( (int)pFanout->Level > nLevDivMax )
+                continue;
+            // skip nodes whose fanins are not divisors  -- here we skip more than we need to skip!!! (revise later)  August 7, 2009
+            Abc_ObjForEachFanin( pFanout, pFanin, m )
+                if ( !Abc_NodeIsTravIdPrevious(pFanin) )
+                    break;
+            if ( m < Abc_ObjFaninNum(pFanout) )
+                continue;
+            // make sure this divisor in not among the nodes
+//            Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodes, pFanin, m )
+//                assert( pFanout != pFanin );
+            // add the node to the divisors
+            Vec_PtrPush( vDivs, pFanout );
+//            Vec_PtrPush( p->vNodes, pFanout );
+            Vec_PtrPushUnique( p->vNodes, pFanout );
+            Abc_NodeSetTravIdPrevious( pFanout );
+            nDivsPlus++;
+            if ( Vec_PtrSize(vDivs) >= p->pPars->nWinMax )
+                break;
+        }
+        if ( Vec_PtrSize(vDivs) >= p->pPars->nWinMax )
+            break;
+    }
+    p->nMaxDivs += (Vec_PtrSize(vDivs) >= p->pPars->nWinMax);
+
+    // sort the divisors by level in the increasing order
+    Vec_PtrSort( vDivs, (int (*)(void))Abc_NodeCompareLevelsIncrease );
+
+    // add the fanins of the node
+    Abc_ObjForEachFanin( pNode, pFanin, k )
+        Vec_PtrPush( vDivs, pFanin );
+
+/*
+    printf( "Node level = %d.  ", Abc_ObjLevel(p->pNode) );
+    Vec_PtrForEachEntryStart( Abc_Obj_t *, vDivs, pObj, k, Vec_PtrSize(vDivs)-p->nDivsPlus )
+        printf( "%d ", Abc_ObjLevel(pObj) );
+    printf( "\n" );
+*/
+//printf( "%d ", p->nDivsPlus );
+//    printf( "(%d+%d)(%d+%d+%d) ", Vec_PtrSize(p->vSupp), Vec_PtrSize(p->vNodes), 
+//        nTrueSupp, Vec_PtrSize(vDivs)-nTrueSupp-nDivsPlus, nDivsPlus );
+    return vDivs;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/mfs/mfsGia.c b/abc-build/src/opt/mfs/mfsGia.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/mfs/mfsGia.c
@@ -0,0 +1,301 @@
+/**CFile****************************************************************
+
+  FileName    [mfsGia.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The good old minimization with complete don't-cares.]
+
+  Synopsis    [Experimental code based on the new AIG package.]
+
+  Author      [Alan Mishchenko]
+
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - July 29, 2009.]
+
+  Revision    [$Id: mfsGia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include "mfsInt.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Gia_ObjChild0Copy( Aig_Obj_t * pObj )  { return Gia_LitNotCond( Aig_ObjFanin0(pObj)->iData, Aig_ObjFaninC0(pObj) ); }
+static inline int Gia_ObjChild1Copy( Aig_Obj_t * pObj )  { return Gia_LitNotCond( Aig_ObjFanin1(pObj)->iData, Aig_ObjFaninC1(pObj) ); }
+
+// r i10_if6.blif;  ps; mfs -v
+// r pj1_if6.blif;  ps; mfs -v
+// r x/01_if6.blif; ps; mfs -v
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the resubstitution miter as an GIA.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+Gia_Man_t * Gia_ManCreateResubMiter( Aig_Man_t * p )
+{
+    Gia_Man_t * pNew;//, * pTemp;
+    Aig_Obj_t * pObj;
+    int i, * pOuts0, * pOuts1;
+    Aig_ManSetPioNumbers( p );
+    // create the new manager
+    pNew = Gia_ManStart( Aig_ManObjNum(p) );
+    pNew->pName = Gia_UtilStrsav( p->pName );
+    pNew->pSpec = Gia_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+    // create the objects
+    pOuts0 = ABC_ALLOC( int, Aig_ManPoNum(p) );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( Aig_ObjIsAnd(pObj) )
+            pObj->iData = Gia_ManHashAnd( pNew, Gia_ObjChild0Copy(pObj), Gia_ObjChild1Copy(pObj) );
+        else if ( Aig_ObjIsPi(pObj) )
+            pObj->iData = Gia_ManAppendCi( pNew );
+        else if ( Aig_ObjIsPo(pObj) )
+            pOuts0[ Aig_ObjPioNum(pObj) ] = Gia_ObjChild0Copy(pObj);
+        else if ( Aig_ObjIsConst1(pObj) )
+            pObj->iData = 1;
+        else
+            assert( 0 );
+    }
+    // create the objects
+    pOuts1 = ABC_ALLOC( int, Aig_ManPoNum(p) );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( Aig_ObjIsAnd(pObj) )
+            pObj->iData = Gia_ManHashAnd( pNew, Gia_ObjChild0Copy(pObj), Gia_ObjChild1Copy(pObj) );
+        else if ( Aig_ObjIsPi(pObj) )
+            pObj->iData = Gia_ManAppendCi( pNew );
+        else if ( Aig_ObjIsPo(pObj) )
+            pOuts1[ Aig_ObjPioNum(pObj) ] = Gia_ObjChild0Copy(pObj);
+        else if ( Aig_ObjIsConst1(pObj) )
+            pObj->iData = 1;
+        else
+            assert( 0 );
+    }
+    // add the outputs
+    Gia_ManAppendCo( pNew, pOuts0[0] );
+    Gia_ManAppendCo( pNew, pOuts1[0] );
+    Gia_ManAppendCo( pNew, pOuts0[1] );
+    Gia_ManAppendCo( pNew, Gia_LitNot(pOuts1[1]) );
+    for ( i = 2; i < Aig_ManPoNum(p); i++ )
+        Gia_ManAppendCo( pNew, Gia_LitNot( Gia_ManHashXor(pNew, pOuts0[i], pOuts1[i]) ) );
+    Gia_ManHashStop( pNew );
+    ABC_FREE( pOuts0 );
+    ABC_FREE( pOuts1 );
+//    pNew = Gia_ManCleanup( pTemp = pNew );
+//    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMfsConstructGia( Mfs_Man_t * p )
+{
+    int nBTLimit = 500;
+    // prepare AIG
+    assert( p->pGia == NULL );
+    p->pGia = Gia_ManCreateResubMiter( p->pAigWin );
+    // prepare AIG
+    Gia_ManCreateRefs( p->pGia );
+    Gia_ManCleanMark0( p->pGia );
+    Gia_ManCleanMark1( p->pGia );
+    Gia_ManFillValue ( p->pGia ); // maps nodes into trail ids
+    Gia_ManCleanPhase( p->pGia ); 
+    // prepare solver
+    p->pTas = Tas_ManAlloc( p->pGia, nBTLimit );
+    p->vCex = Tas_ReadModel( p->pTas );
+    p->vGiaLits = Vec_PtrAlloc( 100 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMfsDeconstructGia( Mfs_Man_t * p )
+{
+    assert( p->pGia != NULL );
+    Gia_ManStop( p->pGia ); p->pGia = NULL;
+    Tas_ManStop( p->pTas ); p->pTas = NULL;
+    Vec_PtrFree( p->vGiaLits );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMfsResimulate( Gia_Man_t * p, Vec_Int_t * vCex )
+{
+    Gia_Obj_t * pObj;
+    int i, Entry;
+//    Gia_ManCleanMark1( p );
+    Gia_ManConst0(p)->fMark1 = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->fMark1 = 0;
+//        pObj->fMark1 = Gia_ManRandom(0);
+    Vec_IntForEachEntry( vCex, Entry, i )
+    {
+        pObj = Gia_ManCi( p, Gia_Lit2Var(Entry) );
+        pObj->fMark1 = !Gia_LitIsCompl(Entry);
+    }
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) & 
+                       (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj));
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->fMark1 =  Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj);
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsTryResubOnceGia( Mfs_Man_t * p, int * pCands, int nCands )
+{
+    int fVeryVerbose = 0;
+    int fUseGia = 1;
+    unsigned * pData;
+    int i, iVar, status, iOut;
+    clock_t clk = clock();
+    p->nSatCalls++;
+//    return -1;
+    assert( p->pGia != NULL );
+    assert( p->pTas != NULL );
+    // convert to literals
+    Vec_PtrClear( p->vGiaLits );
+    // create the first four literals
+    Vec_PtrPush( p->vGiaLits, Gia_ObjChild0(Gia_ManPo(p->pGia, 0)) );
+    Vec_PtrPush( p->vGiaLits, Gia_ObjChild0(Gia_ManPo(p->pGia, 1)) );
+    Vec_PtrPush( p->vGiaLits, Gia_ObjChild0(Gia_ManPo(p->pGia, 2)) );
+    Vec_PtrPush( p->vGiaLits, Gia_ObjChild0(Gia_ManPo(p->pGia, 3)) );
+    for ( i = 0; i < nCands; i++ )
+    {
+        // get the output number
+        iOut = Gia_Lit2Var(pCands[i]) - 2 * p->pCnf->nVars;
+        // write the literal
+        Vec_PtrPush( p->vGiaLits, Gia_ObjChild0(Gia_ManPo(p->pGia, 4 + iOut)) );
+    }
+    // perform SAT solving
+    status = Tas_ManSolveArray( p->pTas, p->vGiaLits );
+    if ( status == -1 )
+    {
+        p->nTimeOuts++;
+        if ( fVeryVerbose )
+        printf( "t" );
+//        p->nSatUndec++;
+//        p->nConfUndec += p->Pars.nBTThis;
+//        Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout
+//        p->timeSatUndec += clock() - clk;
+    }
+    else if ( status == 1 )
+    {
+        if ( fVeryVerbose )
+        printf( "u" );
+//        p->nSatUnsat++;
+//        p->nConfUnsat += p->Pars.nBTThis;
+//        p->timeSatUnsat += clock() - clk;
+    }
+    else
+    {
+        p->nSatCexes++;
+        if ( fVeryVerbose )
+        printf( "s" );
+//        p->nSatSat++;
+//        p->nConfSat += p->Pars.nBTThis;
+//        Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit );
+//        Cec_ManSatAddToStore( vCexStore, vCex, i );
+//        p->timeSatSat += clock() - clk;
+
+        // resimulate the counter-example
+        Abc_NtkMfsResimulate( p->pGia, Tas_ReadModel(p->pTas) );
+   
+        if ( fUseGia )
+        {
+/*
+            int Val0 = Gia_ManPo(p->pGia, 0)->fMark1;
+            int Val1 = Gia_ManPo(p->pGia, 1)->fMark1;
+            int Val2 = Gia_ManPo(p->pGia, 2)->fMark1;
+            int Val3 = Gia_ManPo(p->pGia, 3)->fMark1;
+            assert( Val0 == 1 );
+            assert( Val1 == 1 );
+            assert( Val2 == 1 );
+            assert( Val3 == 1 );
+*/
+            // store the counter-example
+            Vec_IntForEachEntry( p->vProjVarsSat, iVar, i )
+            {
+                pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, i );
+                iOut = iVar - 2 * p->pCnf->nVars;
+//                if ( !Gia_ManPo( p->pGia, 4 + iOut )->fMark1 ) // remove 0s!!!
+                if ( Gia_ManPo( p->pGia, 4 + iOut )->fMark1 ) // remove 0s!!!  - rememeber complemented attribute
+                {
+                    assert( Aig_InfoHasBit(pData, p->nCexes) );
+                    Aig_InfoXorBit( pData, p->nCexes );
+                }
+            }
+            p->nCexes++;
+        }
+
+    }
+    return status;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/mfs/mfsInt.h b/abc-build/src/opt/mfs/mfsInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/mfs/mfsInt.h
@@ -0,0 +1,192 @@
+/**CFile****************************************************************
+
+  FileName    [mfsInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The good old minimization with complete don't-cares.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mfsInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__opt__mfs__mfsInt_h
+#define ABC__opt__mfs__mfsInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "base/abc/abc.h"
+#include "mfs.h"
+#include "aig/aig/aig.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver.h"
+#include "sat/bsat/satStore.h"
+#include "bool/bdc/bdc.h"
+#include "aig/gia/gia.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+#define MFS_FANIN_MAX   12
+
+typedef struct Mfs_Man_t_ Mfs_Man_t;
+struct Mfs_Man_t_
+{
+    // input data
+    Mfs_Par_t *         pPars;
+    Abc_Ntk_t *         pNtk;
+    Aig_Man_t *         pCare;
+    Vec_Ptr_t *         vSuppsInv;
+    int                 nFaninMax;
+    // intermeditate data for the node
+    Vec_Ptr_t *         vRoots;    // the roots of the window
+    Vec_Ptr_t *         vSupp;     // the support of the window
+    Vec_Ptr_t *         vNodes;    // the internal nodes of the window
+    Vec_Ptr_t *         vDivs;     // the divisors of the node
+    Vec_Int_t *         vDivLits;  // the SAT literals of divisor nodes
+    Vec_Int_t *         vProjVarsCnf; // the projection variables
+    Vec_Int_t *         vProjVarsSat; // the projection variables
+    // intermediate simulation data
+    Vec_Ptr_t *         vDivCexes; // the counter-example for dividors
+    int                 nDivWords; // the number of words
+    int                 nCexes;    // the numbe rof current counter-examples
+    int                 nSatCalls; 
+    int                 nSatCexes;
+/*
+    // intermediate AIG data
+    Gia_Man_t *         pGia;      // replica of the AIG in the new package
+//    Gia_Obj_t **        pSat2Gia;  // mapping of PO SAT var into internal GIA nodes
+    Tas_Man_t *         pTas;      // the SAT solver
+    Vec_Int_t *         vCex;      // the counter-example
+    Vec_Ptr_t *         vGiaLits;  // literals given as assumptions
+*/
+    // used for bidecomposition
+    Vec_Int_t *         vTruth;
+    Bdc_Man_t *         pManDec;
+    int                 nNodesDec;
+    int                 nNodesGained;
+    int                 nNodesGainedLevel;
+    // solving data
+    Aig_Man_t *         pAigWin;   // window AIG with constraints
+    Cnf_Dat_t *         pCnf;      // the CNF for the window
+    sat_solver *        pSat;      // the SAT solver used 
+    Int_Man_t *         pMan;      // interpolation manager;
+    Vec_Int_t *         vMem;      // memory for intermediate SOPs
+    Vec_Vec_t *         vLevels;   // levelized structure for updating
+    Vec_Ptr_t *         vMfsFanins;   // the new set of fanins
+    int                 nTotConfLim; // total conflict limit
+    int                 nTotConfLevel; // total conflicts on this level
+    // switching activity
+    Vec_Int_t *         vProbs; 
+    // the result of solving
+    int                 nFanins;   // the number of fanins
+    int                 nWords;    // the number of words
+    int                 nCares;    // the number of care minterms
+    unsigned            uCare[(MFS_FANIN_MAX<=5)?1:1<<(MFS_FANIN_MAX-5)];  // the computed care-set
+    // performance statistics
+    int                 nTryRemoves; // number of fanin removals
+    int                 nTryResubs;  // number of resubstitutions
+    int                 nRemoves;    // number of fanin removals
+    int                 nResubs;     // number of resubstitutions
+    int                 nNodesTried;
+    int                 nNodesResub;
+    int                 nMintsCare;
+    int                 nMintsTotal;
+    int                 nNodesBad;
+    int                 nTotalDivs;
+    int                 nTimeOuts;
+    int                 nTimeOutsLevel;
+    int                 nDcMints;
+    int                 nMaxDivs;
+    double              dTotalRatios;
+    // node/edge stats
+    int                 nTotalNodesBeg;
+    int                 nTotalNodesEnd;
+    int                 nTotalEdgesBeg;
+    int                 nTotalEdgesEnd;
+    float               TotalSwitchingBeg;
+    float               TotalSwitchingEnd;
+    // statistics
+    abctime             timeWin;
+    abctime             timeDiv;
+    abctime             timeAig;
+    abctime             timeGia;
+    abctime             timeCnf;
+    abctime             timeSat;
+    abctime             timeInt;
+    abctime             timeTotal;
+};
+
+static inline float Abc_MfsObjProb( Mfs_Man_t * p, Abc_Obj_t * pObj ) { return (p->vProbs && pObj->Id < Vec_IntSize(p->vProbs))? Abc_Int2Float(Vec_IntEntry(p->vProbs,pObj->Id)) : 0.0; }
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== mfsDiv.c ==========================================================*/
+extern Vec_Ptr_t *      Abc_MfsComputeDivisors( Mfs_Man_t * p, Abc_Obj_t * pNode, int nLevDivMax );
+/*=== mfsInter.c ==========================================================*/
+extern sat_solver *     Abc_MfsCreateSolverResub( Mfs_Man_t * p, int * pCands, int nCands, int fInvert );
+extern Hop_Obj_t *      Abc_NtkMfsInterplate( Mfs_Man_t * p, int * pCands, int nCands );
+extern int              Abc_NtkMfsInterplateEval( Mfs_Man_t * p, int * pCands, int nCands );
+/*=== mfsMan.c ==========================================================*/
+extern Mfs_Man_t *      Mfs_ManAlloc( Mfs_Par_t * pPars );
+extern void             Mfs_ManStop( Mfs_Man_t * p );
+extern void             Mfs_ManClean( Mfs_Man_t * p );
+/*=== mfsResub.c ==========================================================*/
+extern void             Abc_NtkMfsPrintResubStats( Mfs_Man_t * p );
+extern int              Abc_NtkMfsEdgeSwapEval( Mfs_Man_t * p, Abc_Obj_t * pNode );
+extern int              Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode );
+extern int              Abc_NtkMfsResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode );
+extern int              Abc_NtkMfsResubNode2( Mfs_Man_t * p, Abc_Obj_t * pNode );
+/*=== mfsSat.c ==========================================================*/
+extern int              Abc_NtkMfsSolveSat( Mfs_Man_t * p, Abc_Obj_t * pNode );
+extern int              Abc_NtkAddOneHotness( Mfs_Man_t * p );
+/*=== mfsStrash.c ==========================================================*/
+extern Aig_Man_t *      Abc_NtkConstructAig( Mfs_Man_t * p, Abc_Obj_t * pNode );
+extern double           Abc_NtkConstraintRatio( Mfs_Man_t * p, Abc_Obj_t * pNode );
+/*=== mfsWin.c ==========================================================*/
+extern Vec_Ptr_t *      Abc_MfsComputeRoots( Abc_Obj_t * pNode, int nWinTfoMax, int nFanoutLimit );
+
+/*=== mfsGia.c ==========================================================*/
+extern void             Abc_NtkMfsConstructGia( Mfs_Man_t * p );
+extern void             Abc_NtkMfsDeconstructGia( Mfs_Man_t * p );
+extern int              Abc_NtkMfsTryResubOnceGia( Mfs_Man_t * p, int * pCands, int nCands );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/mfs/mfsInter.c b/abc-build/src/opt/mfs/mfsInter.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/mfs/mfsInter.c
@@ -0,0 +1,398 @@
+/**CFile****************************************************************
+
+  FileName    [mfsInter.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The good old minimization with complete don't-cares.]
+
+  Synopsis    [Procedures for computing resub function by interpolation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mfsInter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mfsInt.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Adds constraints for the two-input AND-gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_MfsSatAddXor( sat_solver * pSat, int iVarA, int iVarB, int iVarC )
+{
+    lit Lits[3];
+
+    Lits[0] = toLitCond( iVarA, 1 );
+    Lits[1] = toLitCond( iVarB, 1 );
+    Lits[2] = toLitCond( iVarC, 1 );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVarA, 1 );
+    Lits[1] = toLitCond( iVarB, 0 );
+    Lits[2] = toLitCond( iVarC, 0 );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVarA, 0 );
+    Lits[1] = toLitCond( iVarB, 1 );
+    Lits[2] = toLitCond( iVarC, 0 );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVarA, 0 );
+    Lits[1] = toLitCond( iVarB, 0 );
+    Lits[2] = toLitCond( iVarC, 1 );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) )
+        return 0;
+
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates miter for checking resubsitution.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+sat_solver * Abc_MfsCreateSolverResub( Mfs_Man_t * p, int * pCands, int nCands, int fInvert )
+{
+    sat_solver * pSat;
+    Aig_Obj_t * pObjPo;
+    int Lits[2], status, iVar, i, c;
+
+    // get the literal for the output of F
+    pObjPo = Aig_ManCo( p->pAigWin, Aig_ManCoNum(p->pAigWin) - Vec_PtrSize(p->vDivs) - 1 );
+    Lits[0] = toLitCond( p->pCnf->pVarNums[pObjPo->Id], fInvert );
+
+    // collect the outputs of the divisors
+    Vec_IntClear( p->vProjVarsCnf );
+    Vec_PtrForEachEntryStart( Aig_Obj_t *, p->pAigWin->vCos, pObjPo, i, Aig_ManCoNum(p->pAigWin) - Vec_PtrSize(p->vDivs) )
+    {
+        assert( p->pCnf->pVarNums[pObjPo->Id] >= 0 );
+        Vec_IntPush( p->vProjVarsCnf, p->pCnf->pVarNums[pObjPo->Id] );
+    }
+    assert( Vec_IntSize(p->vProjVarsCnf) == Vec_PtrSize(p->vDivs) );
+
+    // start the solver
+    pSat = sat_solver_new();
+    sat_solver_setnvars( pSat, 2 * p->pCnf->nVars + Vec_PtrSize(p->vDivs) );
+    if ( pCands )
+        sat_solver_store_alloc( pSat );
+
+    // load the first copy of the clauses
+    for ( i = 0; i < p->pCnf->nClauses; i++ )
+    {
+        if ( !sat_solver_addclause( pSat, p->pCnf->pClauses[i], p->pCnf->pClauses[i+1] ) )
+        {
+            sat_solver_delete( pSat );
+            return NULL;
+        }
+    }
+    // add the clause for the first output of F
+    if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) )
+    {
+        sat_solver_delete( pSat );
+        return NULL;
+    }
+
+    // add one-hotness constraints
+    if ( p->pPars->fOneHotness )
+    {
+        p->pSat = pSat;
+        if ( !Abc_NtkAddOneHotness( p ) )
+            return NULL;
+        p->pSat = NULL;
+    }
+
+    // bookmark the clauses of A
+    if ( pCands )
+        sat_solver_store_mark_clauses_a( pSat );
+
+    // transform the literals
+    for ( i = 0; i < p->pCnf->nLiterals; i++ )
+        p->pCnf->pClauses[0][i] += 2 * p->pCnf->nVars;
+    // load the second copy of the clauses
+    for ( i = 0; i < p->pCnf->nClauses; i++ )
+    {
+        if ( !sat_solver_addclause( pSat, p->pCnf->pClauses[i], p->pCnf->pClauses[i+1] ) )
+        {
+            sat_solver_delete( pSat );
+            return NULL;
+        }
+    }
+    // add one-hotness constraints
+    if ( p->pPars->fOneHotness )
+    {
+        p->pSat = pSat;
+        if ( !Abc_NtkAddOneHotness( p ) )
+            return NULL;
+        p->pSat = NULL;
+    }
+    // transform the literals
+    for ( i = 0; i < p->pCnf->nLiterals; i++ )
+        p->pCnf->pClauses[0][i] -= 2 * p->pCnf->nVars;
+    // add the clause for the second output of F
+    Lits[0] = 2 * p->pCnf->nVars + lit_neg( Lits[0] );
+    if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) )
+    {
+        sat_solver_delete( pSat );
+        return NULL;
+    }
+
+    if ( pCands )
+    {
+        // add relevant clauses for EXOR gates
+        for ( c = 0; c < nCands; c++ )
+        {
+            // get the variable number of this divisor
+            i = lit_var( pCands[c] ) - 2 * p->pCnf->nVars;
+            // get the corresponding SAT variable
+            iVar = Vec_IntEntry( p->vProjVarsCnf, i );
+            // add the corresponding EXOR gate
+            if ( !Abc_MfsSatAddXor( pSat, iVar, iVar + p->pCnf->nVars, 2 * p->pCnf->nVars + i ) )
+            {
+                sat_solver_delete( pSat );
+                return NULL;
+            }
+            // add the corresponding clause
+            if ( !sat_solver_addclause( pSat, pCands + c, pCands + c + 1 ) )
+            {
+                sat_solver_delete( pSat );
+                return NULL;
+            }
+        }
+        // bookmark the roots
+        sat_solver_store_mark_roots( pSat );
+    }
+    else
+    {
+        // add the clauses for the EXOR gates - and remember their outputs
+        Vec_IntClear( p->vProjVarsSat );
+        Vec_IntForEachEntry( p->vProjVarsCnf, iVar, i )
+        {
+            if ( !Abc_MfsSatAddXor( pSat, iVar, iVar + p->pCnf->nVars, 2 * p->pCnf->nVars + i ) )
+            {
+                sat_solver_delete( pSat );
+                return NULL;
+            }
+            Vec_IntPush( p->vProjVarsSat, 2 * p->pCnf->nVars + i );
+        }
+        assert( Vec_IntSize(p->vProjVarsCnf) == Vec_IntSize(p->vProjVarsSat) );
+        // simplify the solver
+        status = sat_solver_simplify(pSat);
+        if ( status == 0 )
+        {
+//            printf( "Abc_MfsCreateSolverResub(): SAT solver construction has failed. Skipping node.\n" );
+            sat_solver_delete( pSat );
+            return NULL;
+        }
+    }
+    return pSat;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs interpolation.]
+
+  Description [Derives the new function of the node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Abc_NtkMfsInterplateTruth( Mfs_Man_t * p, int * pCands, int nCands, int fInvert )
+{
+    sat_solver * pSat;
+    Sto_Man_t * pCnf = NULL;
+    unsigned * puTruth;
+    int nFanins, status;
+    int c, i, * pGloVars;
+
+    // derive the SAT solver for interpolation
+    pSat = Abc_MfsCreateSolverResub( p, pCands, nCands, fInvert );
+
+    // solve the problem
+    status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( status != l_False )
+    {
+        p->nTimeOuts++;
+        return NULL;
+    }
+    // get the learned clauses
+    pCnf = (Sto_Man_t *)sat_solver_store_release( pSat );
+    sat_solver_delete( pSat );
+
+    // set the global variables
+    pGloVars = Int_ManSetGlobalVars( p->pMan, nCands );
+    for ( c = 0; c < nCands; c++ )
+    {
+        // get the variable number of this divisor
+        i = lit_var( pCands[c] ) - 2 * p->pCnf->nVars;
+        // get the corresponding SAT variable
+        pGloVars[c] = Vec_IntEntry( p->vProjVarsCnf, i );
+    }
+
+    // derive the interpolant
+    nFanins = Int_ManInterpolate( p->pMan, pCnf, 0, &puTruth );
+    Sto_ManFree( pCnf );
+    assert( nFanins == nCands );
+    return puTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs interpolation.]
+
+  Description [Derives the new function of the node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsInterplateEval( Mfs_Man_t * p, int * pCands, int nCands )
+{
+    unsigned * pTruth, uTruth0[2], uTruth1[2];
+    int nCounter;
+    pTruth = Abc_NtkMfsInterplateTruth( p, pCands, nCands, 0 );
+    if ( nCands == 6 )
+    {
+        uTruth1[0] = pTruth[0];
+        uTruth1[1] = pTruth[1];
+    }
+    else
+    {
+        uTruth1[0] = pTruth[0];
+        uTruth1[1] = pTruth[0];
+    }
+    pTruth = Abc_NtkMfsInterplateTruth( p, pCands, nCands, 1 );
+    if ( nCands == 6 )
+    {
+        uTruth0[0] = ~pTruth[0];
+        uTruth0[1] = ~pTruth[1];
+    }
+    else
+    {
+        uTruth0[0] = ~pTruth[0];
+        uTruth0[1] = ~pTruth[0];
+    }
+    nCounter  = Extra_WordCountOnes( uTruth0[0] ^ uTruth1[0] );
+    nCounter += Extra_WordCountOnes( uTruth0[1] ^ uTruth1[1] );
+//    printf( "%d ", nCounter );
+    return nCounter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs interpolation.]
+
+  Description [Derives the new function of the node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Abc_NtkMfsInterplate( Mfs_Man_t * p, int * pCands, int nCands )
+{
+    extern Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph );
+    int fDumpFile = 0;
+    char FileName[32];
+    sat_solver * pSat;
+    Sto_Man_t * pCnf = NULL;
+    unsigned * puTruth;
+    Kit_Graph_t * pGraph;
+    Hop_Obj_t * pFunc;
+    int nFanins, status;
+    int c, i, * pGloVars;
+//    abctime clk = Abc_Clock();
+//    p->nDcMints += Abc_NtkMfsInterplateEval( p, pCands, nCands );
+
+    // derive the SAT solver for interpolation
+    pSat = Abc_MfsCreateSolverResub( p, pCands, nCands, 0 );
+
+    // dump CNF file (remember to uncomment two-lit clases in clause_create_new() in 'satSolver.c')
+    if ( fDumpFile )
+    {
+        static int Counter = 0;
+        sprintf( FileName, "cnf\\pj1_if6_mfs%03d.cnf", Counter++ );
+        Sat_SolverWriteDimacs( pSat, FileName, NULL, NULL, 1 );
+    }
+
+    // solve the problem
+    status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( fDumpFile )
+        printf( "File %s has UNSAT problem with %d conflicts.\n", FileName, (int)pSat->stats.conflicts );
+    if ( status != l_False )
+    {
+        p->nTimeOuts++;
+        return NULL;
+    }
+//printf( "%d\n", pSat->stats.conflicts );
+//    ABC_PRT( "S", Abc_Clock() - clk );
+    // get the learned clauses
+    pCnf = (Sto_Man_t *)sat_solver_store_release( pSat );
+    sat_solver_delete( pSat );
+
+    // set the global variables
+    pGloVars = Int_ManSetGlobalVars( p->pMan, nCands );
+    for ( c = 0; c < nCands; c++ )
+    {
+        // get the variable number of this divisor
+        i = lit_var( pCands[c] ) - 2 * p->pCnf->nVars;
+        // get the corresponding SAT variable
+        pGloVars[c] = Vec_IntEntry( p->vProjVarsCnf, i );
+    }
+
+    // derive the interpolant
+    nFanins = Int_ManInterpolate( p->pMan, pCnf, 0, &puTruth );
+    Sto_ManFree( pCnf );
+    assert( nFanins == nCands );
+
+    // transform interpolant into AIG
+    pGraph = Kit_TruthToGraph( puTruth, nFanins, p->vMem );
+    pFunc = Kit_GraphToHop( (Hop_Man_t *)p->pNtk->pManFunc, pGraph );
+    Kit_GraphFree( pGraph );
+    return pFunc;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/mfs/mfsMan.c b/abc-build/src/opt/mfs/mfsMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/mfs/mfsMan.c
@@ -0,0 +1,202 @@
+/**CFile****************************************************************
+
+  FileName    [mfsMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The good old minimization with complete don't-cares.]
+
+  Synopsis    [Procedures working with the manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mfsMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mfsInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Mfs_Man_t * Mfs_ManAlloc( Mfs_Par_t * pPars )
+{
+    Mfs_Man_t * p;
+    // start the manager
+    p = ABC_ALLOC( Mfs_Man_t, 1 );
+    memset( p, 0, sizeof(Mfs_Man_t) );
+    p->pPars     = pPars;
+    p->vProjVarsCnf = Vec_IntAlloc( 100 );
+    p->vProjVarsSat = Vec_IntAlloc( 100 );
+    p->vDivLits  = Vec_IntAlloc( 100 );
+    p->nDivWords = Abc_BitWordNum(p->pPars->nWinMax + MFS_FANIN_MAX);
+    p->vDivCexes = Vec_PtrAllocSimInfo( p->pPars->nWinMax + MFS_FANIN_MAX + 1, p->nDivWords );
+    p->pMan      = Int_ManAlloc();
+    p->vMem      = Vec_IntAlloc( 0 );
+    p->vLevels   = Vec_VecStart( 32 );
+    p->vMfsFanins= Vec_PtrAlloc( 32 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mfs_ManClean( Mfs_Man_t * p )
+{
+    if ( p->pAigWin )
+        Aig_ManStop( p->pAigWin );
+    if ( p->pCnf )
+        Cnf_DataFree( p->pCnf );
+    if ( p->pSat )
+        sat_solver_delete( p->pSat );
+    if ( p->vRoots )
+        Vec_PtrFree( p->vRoots );
+    if ( p->vSupp )
+        Vec_PtrFree( p->vSupp );
+    if ( p->vNodes )
+        Vec_PtrFree( p->vNodes );
+    if ( p->vDivs )
+        Vec_PtrFree( p->vDivs );
+    p->pAigWin = NULL;
+    p->pCnf    = NULL;
+    p->pSat    = NULL;
+    p->vRoots  = NULL;
+    p->vSupp   = NULL;
+    p->vNodes  = NULL;
+    p->vDivs   = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mfs_ManPrint( Mfs_Man_t * p )
+{
+    if ( p->pPars->fResub )
+    {
+        printf( "Nodes = %d. Try = %d. Resub = %d. Div = %d. SAT calls = %d. Timeouts = %d. MaxDivs = %d.\n",
+            p->nTotalNodesBeg, p->nNodesTried, p->nNodesResub, p->nTotalDivs, p->nSatCalls, p->nTimeOuts, p->nMaxDivs );
+
+        printf( "Attempts :   " );
+        printf( "Remove %6d out of %6d (%6.2f %%)   ", p->nRemoves, p->nTryRemoves, 100.0*p->nRemoves/Abc_MaxInt(1, p->nTryRemoves) );
+        printf( "Resub  %6d out of %6d (%6.2f %%)   ", p->nResubs,  p->nTryResubs,  100.0*p->nResubs /Abc_MaxInt(1, p->nTryResubs)  );
+        printf( "\n" );
+
+        printf( "Reduction:   " );
+        printf( "Nodes  %6d out of %6d (%6.2f %%)   ", p->nTotalNodesBeg-p->nTotalNodesEnd, p->nTotalNodesBeg, 100.0*(p->nTotalNodesBeg-p->nTotalNodesEnd)/Abc_MaxInt(1, p->nTotalNodesBeg) );
+        printf( "Edges  %6d out of %6d (%6.2f %%)   ", p->nTotalEdgesBeg-p->nTotalEdgesEnd, p->nTotalEdgesBeg, 100.0*(p->nTotalEdgesBeg-p->nTotalEdgesEnd)/Abc_MaxInt(1, p->nTotalEdgesBeg) );
+        printf( "\n" );
+
+        if (p->pPars->fPower)
+            printf( "Power( %5.2f, %4.2f%%) \n",
+                 p->TotalSwitchingBeg - p->TotalSwitchingEnd,
+                 100.0*(p->TotalSwitchingBeg-p->TotalSwitchingEnd)/p->TotalSwitchingBeg );
+        if ( p->pPars->fSwapEdge )
+            printf( "Swappable edges = %d. Total edges = %d. Ratio = %5.2f.\n",
+                p->nNodesResub, Abc_NtkGetTotalFanins(p->pNtk), 1.00 * p->nNodesResub / Abc_NtkGetTotalFanins(p->pNtk) );
+//        printf( "Average ratio of DCs in the resubed nodes = %.2f.\n", 1.0*p->nDcMints/(64 * p->nNodesResub) );
+    }
+    else
+    {
+        printf( "Nodes = %d. Try = %d. Total mints = %d. Local DC mints = %d. Ratio = %5.2f.\n", 
+            p->nTotalNodesBeg, p->nNodesTried, p->nMintsTotal, p->nMintsTotal-p->nMintsCare, 
+            1.0 * (p->nMintsTotal-p->nMintsCare) / p->nMintsTotal );
+//        printf( "Average ratio of sequential DCs in the global space = %5.2f.\n", 
+//            1.0-(p->dTotalRatios/p->nNodesTried) );
+        printf( "Nodes resyn = %d. Ratio = %5.2f.  Total AIG node gain = %d. Timeouts = %d.\n", 
+            p->nNodesDec, 1.0 * p->nNodesDec / p->nNodesTried, p->nNodesGained, p->nTimeOuts );
+    }
+
+    ABC_PRTP( "Win", p->timeWin            ,  p->timeTotal );
+    ABC_PRTP( "Div", p->timeDiv            ,  p->timeTotal );
+    ABC_PRTP( "Aig", p->timeAig            ,  p->timeTotal );
+    ABC_PRTP( "Gia", p->timeGia            ,  p->timeTotal );
+    ABC_PRTP( "Cnf", p->timeCnf            ,  p->timeTotal );
+    ABC_PRTP( "Sat", p->timeSat-p->timeInt ,  p->timeTotal );
+    ABC_PRTP( "Int", p->timeInt            ,  p->timeTotal );
+    ABC_PRTP( "ALL", p->timeTotal          ,  p->timeTotal );
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Mfs_ManStop( Mfs_Man_t * p )
+{
+    if ( p->pPars->fVerbose )
+        Mfs_ManPrint( p );
+    if ( p->vTruth )
+        Vec_IntFree( p->vTruth );
+    if ( p->pManDec )
+        Bdc_ManFree( p->pManDec );
+    if ( p->pCare )
+        Aig_ManStop( p->pCare );
+    if ( p->vSuppsInv )
+        Vec_VecFree( (Vec_Vec_t *)p->vSuppsInv );
+    if ( p->vProbs )
+        Vec_IntFree( p->vProbs );
+    Mfs_ManClean( p );
+    Int_ManFree( p->pMan );
+    Vec_IntFree( p->vMem );
+    Vec_VecFree( p->vLevels );
+    Vec_PtrFree( p->vMfsFanins );
+    Vec_IntFree( p->vProjVarsCnf );
+    Vec_IntFree( p->vProjVarsSat );
+    Vec_IntFree( p->vDivLits );
+    Vec_PtrFree( p->vDivCexes );
+    ABC_FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/mfs/mfsResub.c b/abc-build/src/opt/mfs/mfsResub.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/mfs/mfsResub.c
@@ -0,0 +1,622 @@
+/**CFile****************************************************************
+
+  FileName    [mfsResub.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The good old minimization with complete don't-cares.]
+
+  Synopsis    [Procedures to perform resubstitution.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mfsResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mfsInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    [Updates the network after resubstitution.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMfsUpdateNetwork( Mfs_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vMfsFanins, Hop_Obj_t * pFunc )
+{
+    Abc_Obj_t * pObjNew, * pFanin;
+    int k;
+    // create the new node
+    pObjNew = Abc_NtkCreateNode( pObj->pNtk );
+    pObjNew->pData = pFunc;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vMfsFanins, pFanin, k )
+        Abc_ObjAddFanin( pObjNew, pFanin );
+    // replace the old node by the new node
+//printf( "Replacing node " ); Abc_ObjPrint( stdout, pObj );
+//printf( "Inserting node " ); Abc_ObjPrint( stdout, pObjNew );
+    // update the level of the node
+    Abc_NtkUpdate( pObj, pObjNew, p->vLevels );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints resub candidate stats.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMfsPrintResubStats( Mfs_Man_t * p )
+{
+    Abc_Obj_t * pFanin, * pNode;
+    int i, k, nAreaCrits = 0, nAreaExpanse = 0;
+    int nFaninMax = Abc_NtkGetFaninMax(p->pNtk);
+    Abc_NtkForEachNode( p->pNtk, pNode, i )
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+        {
+            if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+            {
+                nAreaCrits++;
+                nAreaExpanse += (int)(Abc_ObjFaninNum(pNode) < nFaninMax);
+            }
+        }
+//    printf( "Total area-critical fanins = %d. Belonging to expandable nodes = %d.\n", 
+//        nAreaCrits, nAreaExpanse );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tries resubstitution.]
+
+  Description [Returns 1 if it is feasible, or 0 if c-ex is found.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsTryResubOnce( Mfs_Man_t * p, int * pCands, int nCands )
+{
+    int fVeryVerbose = 0;
+    unsigned * pData;
+    int RetValue, RetValue2 = -1, iVar, i;//, clk = Abc_Clock();
+/*
+    if ( p->pPars->fGiaSat )
+    {
+        RetValue2 = Abc_NtkMfsTryResubOnceGia( p, pCands, nCands );
+p->timeGia += Abc_Clock() - clk;
+        return RetValue2;
+    }
+*/ 
+    p->nSatCalls++;
+    RetValue = sat_solver_solve( p->pSat, pCands, pCands + nCands, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+//    assert( RetValue == l_False || RetValue == l_True );
+
+    if ( RetValue != l_Undef && RetValue2 != -1 )
+    {
+        assert( (RetValue == l_False) == (RetValue2 == 1) );
+    }
+
+    if ( RetValue == l_False )
+    {
+        if ( fVeryVerbose )
+        printf( "U " );
+        return 1;
+    }
+    if ( RetValue != l_True )
+    {
+        if ( fVeryVerbose )
+        printf( "T " );
+        p->nTimeOuts++;
+        return -1;
+    }
+    if ( fVeryVerbose )
+    printf( "S " );
+    p->nSatCexes++;
+    // store the counter-example
+    Vec_IntForEachEntry( p->vProjVarsSat, iVar, i )
+    {
+        pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, i );
+        if ( !sat_solver_var_value( p->pSat, iVar ) ) // remove 0s!!!
+        {
+            assert( Abc_InfoHasBit(pData, p->nCexes) );
+            Abc_InfoXorBit( pData, p->nCexes );
+        }
+    }
+    p->nCexes++;
+    return 0;
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs resubstitution for the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsSolveSatResub( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int fOnlyRemove, int fSkipUpdate )
+{
+    int fVeryVerbose = 0;//p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 200;// || pNode->Id == 556;
+    unsigned * pData;
+    int pCands[MFS_FANIN_MAX];
+    int RetValue, iVar, i, nCands, nWords, w;
+    abctime clk;
+    Abc_Obj_t * pFanin;
+    Hop_Obj_t * pFunc;
+    assert( iFanin >= 0 );
+    p->nTryRemoves++;
+
+    // clean simulation info
+    Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords ); 
+    p->nCexes = 0;
+    if ( p->pPars->fVeryVerbose )
+    {
+//        printf( "\n" );
+        printf( "%5d : Lev =%3d. Leaf =%3d. Node =%3d. Divs =%3d.  Fanin = %4d (%d/%d), MFFC = %d\n", 
+            pNode->Id, pNode->Level, Vec_PtrSize(p->vSupp), Vec_PtrSize(p->vNodes), Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode), 
+            Abc_ObjFaninId(pNode, iFanin), iFanin, Abc_ObjFaninNum(pNode), 
+            Abc_ObjFanoutNum(Abc_ObjFanin(pNode, iFanin)) == 1 ? Abc_NodeMffcLabel(Abc_ObjFanin(pNode, iFanin)) : 0 );
+    }
+
+    // try fanins without the critical fanin
+    nCands = 0;
+    Vec_PtrClear( p->vMfsFanins );
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        if ( i == iFanin )
+            continue;
+        Vec_PtrPush( p->vMfsFanins, pFanin );
+        iVar = Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode) + i;
+        pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVarsSat, iVar ), 1 );
+    }
+    RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands );
+    if ( RetValue == -1 )
+        return 0;
+    if ( RetValue == 1 )
+    {
+        if ( p->pPars->fVeryVerbose )
+            printf( "Node %d: Fanin %d can be removed.\n", pNode->Id, iFanin );
+        p->nNodesResub++;
+        p->nNodesGainedLevel++;
+        if ( fSkipUpdate )
+            return 1;
+clk = Abc_Clock();
+        // derive the function
+        pFunc = Abc_NtkMfsInterplate( p, pCands, nCands );
+        if ( pFunc == NULL )
+            return 0;
+        // update the network
+        Abc_NtkMfsUpdateNetwork( p, pNode, p->vMfsFanins, pFunc );
+p->timeInt += Abc_Clock() - clk;
+        p->nRemoves++;
+        return 1;
+    }
+
+    if ( fOnlyRemove || p->pPars->fRrOnly )
+        return 0;
+
+    p->nTryResubs++;
+    if ( fVeryVerbose )
+    {
+        for ( i = 0; i < 9; i++ )
+            printf( " " );
+        for ( i = 0; i < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); i++ )
+            printf( "%d", i % 10 );
+        for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
+            if ( i == iFanin )
+                printf( "*" );
+            else
+                printf( "%c", 'a' + i );
+        printf( "\n" );
+    }
+    iVar = -1;
+    while ( 1 ) 
+    {
+        if ( fVeryVerbose )
+        {
+            printf( "%3d: %3d ", p->nCexes, iVar );
+            for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ )
+            {
+                pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, i );
+                printf( "%d", Abc_InfoHasBit(pData, p->nCexes-1) );
+            }
+            printf( "\n" );
+        }
+
+        // find the next divisor to try
+        nWords = Abc_BitWordNum(p->nCexes);
+        assert( nWords <= p->nDivWords );
+        for ( iVar = 0; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ )
+        {
+            if ( p->pPars->fPower )
+            {
+                Abc_Obj_t * pDiv = (Abc_Obj_t *)Vec_PtrEntry(p->vDivs, iVar);
+                // only accept the divisor if it is "cool"
+                if ( Abc_MfsObjProb(p, pDiv) >= 0.15 )
+                    continue;
+            }
+            pData  = (unsigned *)Vec_PtrEntry( p->vDivCexes, iVar );
+            for ( w = 0; w < nWords; w++ )
+                if ( pData[w] != ~0 )
+                    break;
+            if ( w == nWords )
+                break;
+        }
+        if ( iVar == Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode) )
+            return 0;
+
+        pCands[nCands] = toLitCond( Vec_IntEntry(p->vProjVarsSat, iVar), 1 );
+        RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands+1 );
+        if ( RetValue == -1 )
+            return 0;
+        if ( RetValue == 1 )
+        {
+            if ( p->pPars->fVeryVerbose )
+                printf( "Node %d: Fanin %d can be replaced by divisor %d.\n", pNode->Id, iFanin, iVar );
+            p->nNodesResub++;
+            p->nNodesGainedLevel++;
+            if ( fSkipUpdate )
+                return 1;
+clk = Abc_Clock();
+            // derive the function
+            pFunc = Abc_NtkMfsInterplate( p, pCands, nCands+1 );
+            if ( pFunc == NULL )
+                return 0;
+            // update the network
+            Vec_PtrPush( p->vMfsFanins, Vec_PtrEntry(p->vDivs, iVar) );
+            Abc_NtkMfsUpdateNetwork( p, pNode, p->vMfsFanins, pFunc );
+p->timeInt += Abc_Clock() - clk;
+            p->nResubs++;
+            return 1;
+        }
+        if ( p->nCexes >= p->pPars->nWinMax )
+            break;
+    }
+    if ( p->pPars->fVeryVerbose )
+        printf( "Node %d: Cannot find replacement for fanin %d.\n", pNode->Id, iFanin );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs resubstitution for the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsSolveSatResub2( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int iFanin2 )
+{
+    int fVeryVerbose = p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 80;
+    unsigned * pData, * pData2;
+    int pCands[MFS_FANIN_MAX];
+    int RetValue, iVar, iVar2, i, w, nCands, nWords, fBreak;
+    abctime clk;
+    Abc_Obj_t * pFanin;
+    Hop_Obj_t * pFunc;
+    assert( iFanin >= 0 );
+    assert( iFanin2 >= 0 || iFanin2 == -1 );
+
+    // clean simulation info
+    Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords ); 
+    p->nCexes = 0;
+    if ( fVeryVerbose )
+    {
+        printf( "\n" );
+        printf( "Node %5d : Level = %2d. Divs = %3d.  Fanins = %d/%d (out of %d). MFFC = %d\n", 
+            pNode->Id, pNode->Level, Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode), 
+            iFanin, iFanin2, Abc_ObjFaninNum(pNode), 
+            Abc_ObjFanoutNum(Abc_ObjFanin(pNode, iFanin)) == 1 ? Abc_NodeMffcLabel(Abc_ObjFanin(pNode, iFanin)) : 0 );
+    }
+
+    // try fanins without the critical fanin
+    nCands = 0;
+    Vec_PtrClear( p->vMfsFanins );
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        if ( i == iFanin || i == iFanin2 )
+            continue;
+        Vec_PtrPush( p->vMfsFanins, pFanin );
+        iVar = Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode) + i;
+        pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVarsSat, iVar ), 1 );
+    }
+    RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands );
+    if ( RetValue == -1 )
+        return 0;
+    if ( RetValue == 1 )
+    {
+        if ( fVeryVerbose )
+        printf( "Node %d: Fanins %d/%d can be removed.\n", pNode->Id, iFanin, iFanin2 );
+        p->nNodesResub++;
+        p->nNodesGainedLevel++;
+clk = Abc_Clock();
+        // derive the function
+        pFunc = Abc_NtkMfsInterplate( p, pCands, nCands );
+        if ( pFunc == NULL )
+            return 0;
+        // update the network
+        Abc_NtkMfsUpdateNetwork( p, pNode, p->vMfsFanins, pFunc );
+p->timeInt += Abc_Clock() - clk;
+        return 1;
+    }
+
+    if ( fVeryVerbose )
+    {
+        for ( i = 0; i < 11; i++ )
+            printf( " " );
+        for ( i = 0; i < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); i++ )
+            printf( "%d", i % 10 );
+        for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
+            if ( i == iFanin || i == iFanin2 )
+                printf( "*" );
+            else
+                printf( "%c", 'a' + i );
+        printf( "\n" );
+    }
+    iVar = iVar2 = -1;
+    while ( 1 )
+    {
+#if 1 // sjang
+#endif
+        if ( fVeryVerbose )
+        {
+            printf( "%3d: %2d %2d ", p->nCexes, iVar, iVar2 );
+            for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ )
+            {
+                pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, i );
+                printf( "%d", Abc_InfoHasBit(pData, p->nCexes-1) );
+            }
+            printf( "\n" );
+        }
+
+        // find the next divisor to try
+        nWords = Abc_BitWordNum(p->nCexes);
+        assert( nWords <= p->nDivWords );
+        fBreak = 0;
+        for ( iVar = 1; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ )
+        {
+            pData  = (unsigned *)Vec_PtrEntry( p->vDivCexes, iVar );
+#if 1  // sjang
+            if ( p->pPars->fPower )
+            {
+                Abc_Obj_t * pDiv = (Abc_Obj_t *)Vec_PtrEntry(p->vDivs, iVar);
+                // only accept the divisor if it is "cool"
+                if ( Abc_MfsObjProb(p, pDiv) >= 0.12 )
+                    continue;
+            }
+#endif
+            for ( iVar2 = 0; iVar2 < iVar; iVar2++ )
+            {
+                pData2 = (unsigned *)Vec_PtrEntry( p->vDivCexes, iVar2 );
+#if 1 // sjang
+	            if ( p->pPars->fPower )
+		        {
+			        Abc_Obj_t * pDiv = (Abc_Obj_t *)Vec_PtrEntry(p->vDivs, iVar2);
+				    // only accept the divisor if it is "cool"
+					if ( Abc_MfsObjProb(p, pDiv) >= 0.12 )
+						continue;
+	            }
+#endif
+                for ( w = 0; w < nWords; w++ )
+                    if ( (pData[w] | pData2[w]) != ~0 )
+                        break;
+                if ( w == nWords )
+                {
+                    fBreak = 1;
+                    break;
+                }
+            }
+            if ( fBreak )
+                break;
+        }
+        if ( iVar == Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode) )
+            return 0;
+
+        pCands[nCands]   = toLitCond( Vec_IntEntry(p->vProjVarsSat, iVar2), 1 );
+        pCands[nCands+1] = toLitCond( Vec_IntEntry(p->vProjVarsSat, iVar), 1 );
+        RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands+2 );
+        if ( RetValue == -1 )
+            return 0;
+        if ( RetValue == 1 )
+        {
+            if ( fVeryVerbose )
+            printf( "Node %d: Fanins %d/%d can be replaced by divisors %d/%d.\n", pNode->Id, iFanin, iFanin2, iVar, iVar2 );
+            p->nNodesResub++;
+            p->nNodesGainedLevel++;
+clk = Abc_Clock();
+            // derive the function
+            pFunc = Abc_NtkMfsInterplate( p, pCands, nCands+2 );
+            if ( pFunc == NULL )
+                return 0;
+            // update the network
+            Vec_PtrPush( p->vMfsFanins, Vec_PtrEntry(p->vDivs, iVar2) );
+            Vec_PtrPush( p->vMfsFanins, Vec_PtrEntry(p->vDivs, iVar) );
+            assert( Vec_PtrSize(p->vMfsFanins) == nCands + 2 );
+            Abc_NtkMfsUpdateNetwork( p, pNode, p->vMfsFanins, pFunc );
+p->timeInt += Abc_Clock() - clk;
+            return 1;
+        }
+        if ( p->nCexes >= p->pPars->nWinMax )
+            break;
+    }
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates the possibility of replacing given edge by another edge.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsEdgeSwapEval( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 1 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates the possibility of replacing given edge by another edge.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    // try replacing area critical fanins
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+	{
+        if ( Abc_MfsObjProb(p, pFanin) >= 0.35 )
+        {
+            if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+                return 1;
+        } else if ( Abc_MfsObjProb(p, pFanin) >= 0.25 ) // sjang
+        {
+            if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) )
+                return 1;
+        }
+        }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs resubstitution for the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    // try replacing area critical fanins
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+        {
+            if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+                return 1;
+        }
+    // try removing redundant edges
+    if ( !p->pPars->fArea )
+    {
+        Abc_ObjForEachFanin( pNode, pFanin, i )
+            if ( Abc_ObjIsCi(pFanin) || Abc_ObjFanoutNum(pFanin) != 1 )
+            {
+                if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) )
+                    return 1;
+            }
+    }
+    if ( Abc_ObjFaninNum(pNode) == p->nFaninMax )
+        return 0;
+/*
+    // try replacing area critical fanins while adding two new fanins
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+        {
+            if ( Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) )
+                return 1;
+        }
+*/
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs resubstitution for the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsResubNode2( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin, * pFanin2;
+    int i, k;
+/*
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+        {
+            if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+                return 1;
+        }
+*/
+    if ( Abc_ObjFaninNum(pNode) < 2 )
+        return 0;
+    // try replacing one area critical fanin and one other fanin while adding two new fanins
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+        {
+            // consider second fanin to remove at the same time
+            Abc_ObjForEachFanin( pNode, pFanin2, k )
+            {
+                if ( i != k && Abc_NtkMfsSolveSatResub2( p, pNode, i, k ) )
+                    return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/mfs/mfsResub_.c b/abc-build/src/opt/mfs/mfsResub_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/mfs/mfsResub_.c
@@ -0,0 +1,567 @@
+/**CFile****************************************************************
+
+  FileName    [mfsResub.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The good old minimization with complete don't-cares.]
+
+  Synopsis    [Procedures to perform resubstitution.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mfsResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mfsInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the network after resubstitution.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMfsUpdateNetwork( Mfs_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc )
+{
+    Abc_Obj_t * pObjNew, * pFanin;
+    int k;
+    // create the new node
+    pObjNew = Abc_NtkCreateNode( pObj->pNtk );
+    pObjNew->pData = pFunc;
+    Vec_PtrForEachEntry( vFanins, pFanin, k )
+        Abc_ObjAddFanin( pObjNew, pFanin );
+    // replace the old node by the new node
+//printf( "Replacing node " ); Abc_ObjPrint( stdout, pObj );
+//printf( "Inserting node " ); Abc_ObjPrint( stdout, pObjNew );
+    // update the level of the node
+    Abc_NtkUpdate( pObj, pObjNew, p->vLevels );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints resub candidate stats.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMfsPrintResubStats( Mfs_Man_t * p )
+{
+    Abc_Obj_t * pFanin, * pNode;
+    int i, k, nAreaCrits = 0, nAreaExpanse = 0;
+    int nFaninMax = Abc_NtkGetFaninMax(p->pNtk);
+    Abc_NtkForEachNode( p->pNtk, pNode, i )
+        Abc_ObjForEachFanin( pNode, pFanin, k )
+        {
+            if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+            {
+                nAreaCrits++;
+                nAreaExpanse += (int)(Abc_ObjFaninNum(pNode) < nFaninMax);
+            }
+        }
+    printf( "Total area-critical fanins = %d. Belonging to expandable nodes = %d.\n", 
+        nAreaCrits, nAreaExpanse );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tries resubstitution.]
+
+  Description [Returns 1 if it is feasible, or 0 if c-ex is found.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsTryResubOnce( Mfs_Man_t * p, int * pCands, int nCands )
+{
+    unsigned * pData;
+    int RetValue, iVar, i;
+    p->nSatCalls++;
+    RetValue = sat_solver_solve( p->pSat, pCands, pCands + nCands, (sint64)p->pPars->nBTLimit, (sint64)0, (sint64)0, (sint64)0 );
+//    assert( RetValue == l_False || RetValue == l_True );
+    if ( RetValue == l_False )
+        return 1;
+    if ( RetValue != l_True )
+    {
+        p->nTimeOuts++;
+        return -1;
+    }
+    p->nSatCexes++;
+    // store the counter-example
+    Vec_IntForEachEntry( p->vProjVars, iVar, i )
+    {
+        pData = Vec_PtrEntry( p->vDivCexes, i );
+        if ( !sat_solver_var_value( p->pSat, iVar ) ) // remove 0s!!!
+        {
+            assert( Aig_InfoHasBit(pData, p->nCexes) );
+            Aig_InfoXorBit( pData, p->nCexes );
+        }
+    }
+    p->nCexes++;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs resubstitution for the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsSolveSatResub( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int fOnlyRemove, int fSkipUpdate )
+{
+    int fVeryVerbose = p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 80;
+    unsigned * pData;
+    int pCands[MFS_FANIN_MAX];
+    int RetValue, iVar, i, nCands, nWords, w;
+    clock_t clk;
+    Abc_Obj_t * pFanin;
+    Hop_Obj_t * pFunc;
+    assert( iFanin >= 0 );
+
+    // clean simulation info
+    Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords ); 
+    p->nCexes = 0;
+    if ( fVeryVerbose )
+    {
+        printf( "\n" );
+        printf( "Node %5d : Level = %2d. Divs = %3d.  Fanin = %d (out of %d). MFFC = %d\n", 
+            pNode->Id, pNode->Level, Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode), 
+            iFanin, Abc_ObjFaninNum(pNode), 
+            Abc_ObjFanoutNum(Abc_ObjFanin(pNode, iFanin)) == 1 ? Abc_NodeMffcLabel(Abc_ObjFanin(pNode, iFanin)) : 0 );
+    }
+
+    // try fanins without the critical fanin
+    nCands = 0;
+    Vec_PtrClear( p->vFanins );
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        if ( i == iFanin )
+            continue;
+        Vec_PtrPush( p->vFanins, pFanin );
+        iVar = Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode) + i;
+        pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVars, iVar ), 1 );
+    }
+    RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands );
+    if ( RetValue == -1 )
+        return 0;
+    if ( RetValue == 1 )
+    {
+        if ( fVeryVerbose )
+        printf( "Node %d: Fanin %d can be removed.\n", pNode->Id, iFanin );
+        p->nNodesResub++;
+        p->nNodesGainedLevel++;
+        if ( fSkipUpdate )
+            return 1;
+clk = clock();
+        // derive the function
+        pFunc = Abc_NtkMfsInterplate( p, pCands, nCands );
+        if ( pFunc == NULL )
+            return 0;
+        // update the network
+        Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc );
+p->timeInt += clock() - clk;
+        return 1;
+    }
+
+    if ( fOnlyRemove )
+        return 0;
+
+    if ( fVeryVerbose )
+    {
+        for ( i = 0; i < 8; i++ )
+            printf( " " );
+        for ( i = 0; i < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); i++ )
+            printf( "%d", i % 10 );
+        for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
+            if ( i == iFanin )
+                printf( "*" );
+            else
+                printf( "%c", 'a' + i );
+        printf( "\n" );
+    }
+    iVar = -1;
+    while ( 1 )
+    {
+        float * pProbab = (float *)(p->vProbs? p->vProbs->pArray : NULL);
+        assert( (pProbab != NULL) == p->pPars->fPower );
+        if ( fVeryVerbose )
+        {
+            printf( "%3d: %2d ", p->nCexes, iVar );
+            for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ )
+            {
+                pData = Vec_PtrEntry( p->vDivCexes, i );
+                printf( "%d", Aig_InfoHasBit(pData, p->nCexes-1) );
+            }
+            printf( "\n" );
+        }
+
+        // find the next divisor to try
+        nWords = Aig_BitWordNum(p->nCexes);
+        assert( nWords <= p->nDivWords );
+        for ( iVar = 0; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ )
+        {
+            if ( p->pPars->fPower )
+            {
+                Abc_Obj_t * pDiv = Vec_PtrEntry(p->vDivs, iVar);
+                // only accept the divisor if it is "cool"
+                if ( pProbab[Abc_ObjId(pDiv)] >= 0.2 )
+                    continue;
+            }
+            pData  = Vec_PtrEntry( p->vDivCexes, iVar );
+            for ( w = 0; w < nWords; w++ )
+                if ( pData[w] != ~0 )
+                    break;
+            if ( w == nWords )
+                break;
+        }
+        if ( iVar == Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode) )
+            return 0;
+
+        pCands[nCands] = toLitCond( Vec_IntEntry(p->vProjVars, iVar), 1 );
+        RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands+1 );
+        if ( RetValue == -1 )
+            return 0;
+        if ( RetValue == 1 )
+        {
+            if ( fVeryVerbose )
+            printf( "Node %d: Fanin %d can be replaced by divisor %d.\n", pNode->Id, iFanin, iVar );
+            p->nNodesResub++;
+            p->nNodesGainedLevel++;
+            if ( fSkipUpdate )
+                return 1;
+clk = clock();
+            // derive the function
+            pFunc = Abc_NtkMfsInterplate( p, pCands, nCands+1 );
+            if ( pFunc == NULL )
+                return 0;
+            // update the network
+            Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar) );
+            Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc );
+p->timeInt += clock() - clk;
+            return 1;
+        }
+        if ( p->nCexes >= p->pPars->nDivMax )
+            break;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs resubstitution for the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsSolveSatResub2( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int iFanin2 )
+{
+    int fVeryVerbose = p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 80;
+    unsigned * pData, * pData2;
+    int pCands[MFS_FANIN_MAX];
+    int RetValue, iVar, iVar2, i, w, nCands, nWords, fBreak;
+    clock_t clk;
+    Abc_Obj_t * pFanin;
+    Hop_Obj_t * pFunc;
+    assert( iFanin >= 0 );
+    assert( iFanin2 >= 0 || iFanin2 == -1 );
+
+    // clean simulation info
+    Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords ); 
+    p->nCexes = 0;
+    if ( fVeryVerbose )
+    {
+        printf( "\n" );
+        printf( "Node %5d : Level = %2d. Divs = %3d.  Fanins = %d/%d (out of %d). MFFC = %d\n", 
+            pNode->Id, pNode->Level, Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode), 
+            iFanin, iFanin2, Abc_ObjFaninNum(pNode), 
+            Abc_ObjFanoutNum(Abc_ObjFanin(pNode, iFanin)) == 1 ? Abc_NodeMffcLabel(Abc_ObjFanin(pNode, iFanin)) : 0 );
+    }
+
+    // try fanins without the critical fanin
+    nCands = 0;
+    Vec_PtrClear( p->vFanins );
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        if ( i == iFanin || i == iFanin2 )
+            continue;
+        Vec_PtrPush( p->vFanins, pFanin );
+        iVar = Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode) + i;
+        pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVars, iVar ), 1 );
+    }
+    RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands );
+    if ( RetValue == -1 )
+        return 0;
+    if ( RetValue == 1 )
+    {
+        if ( fVeryVerbose )
+        printf( "Node %d: Fanins %d/%d can be removed.\n", pNode->Id, iFanin, iFanin2 );
+        p->nNodesResub++;
+        p->nNodesGainedLevel++;
+clk = clock();
+        // derive the function
+        pFunc = Abc_NtkMfsInterplate( p, pCands, nCands );
+        if ( pFunc == NULL )
+            return 0;
+        // update the network
+        Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc );
+p->timeInt += clock() - clk;
+        return 1;
+    }
+
+    if ( fVeryVerbose )
+    {
+        for ( i = 0; i < 11; i++ )
+            printf( " " );
+        for ( i = 0; i < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); i++ )
+            printf( "%d", i % 10 );
+        for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
+            if ( i == iFanin || i == iFanin2 )
+                printf( "*" );
+            else
+                printf( "%c", 'a' + i );
+        printf( "\n" );
+    }
+    iVar = iVar2 = -1;
+    while ( 1 )
+    {
+        if ( fVeryVerbose )
+        {
+            printf( "%3d: %2d %2d ", p->nCexes, iVar, iVar2 );
+            for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ )
+            {
+                pData = Vec_PtrEntry( p->vDivCexes, i );
+                printf( "%d", Aig_InfoHasBit(pData, p->nCexes-1) );
+            }
+            printf( "\n" );
+        }
+
+        // find the next divisor to try
+        nWords = Aig_BitWordNum(p->nCexes);
+        assert( nWords <= p->nDivWords );
+        fBreak = 0;
+        for ( iVar = 1; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ )
+        {
+            pData  = Vec_PtrEntry( p->vDivCexes, iVar );
+            for ( iVar2 = 0; iVar2 < iVar; iVar2++ )
+            {
+                pData2 = Vec_PtrEntry( p->vDivCexes, iVar2 );
+                for ( w = 0; w < nWords; w++ )
+                    if ( (pData[w] | pData2[w]) != ~0 )
+                        break;
+                if ( w == nWords )
+                {
+                    fBreak = 1;
+                    break;
+                }
+            }
+            if ( fBreak )
+                break;
+        }
+        if ( iVar == Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode) )
+            return 0;
+
+        pCands[nCands]   = toLitCond( Vec_IntEntry(p->vProjVars, iVar2), 1 );
+        pCands[nCands+1] = toLitCond( Vec_IntEntry(p->vProjVars, iVar), 1 );
+        RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands+2 );
+        if ( RetValue == -1 )
+            return 0;
+        if ( RetValue == 1 )
+        {
+            if ( fVeryVerbose )
+            printf( "Node %d: Fanins %d/%d can be replaced by divisors %d/%d.\n", pNode->Id, iFanin, iFanin2, iVar, iVar2 );
+            p->nNodesResub++;
+            p->nNodesGainedLevel++;
+clk = clock();
+            // derive the function
+            pFunc = Abc_NtkMfsInterplate( p, pCands, nCands+2 );
+            if ( pFunc == NULL )
+                return 0;
+            // update the network
+            Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar2) );
+            Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar) );
+            assert( Vec_PtrSize(p->vFanins) == nCands + 2 );
+            Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc );
+p->timeInt += clock() - clk;
+            return 1;
+        }
+        if ( p->nCexes >= p->pPars->nDivMax )
+            break;
+    }
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates the possibility of replacing given edge by another edge.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsEdgeSwapEval( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 1 );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates the possibility of replacing given edge by another edge.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    float * pProbab = (float *)p->vProbs->pArray;
+    int i;
+    // try replacing area critical fanins
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        if ( pProbab[pFanin->Id] >= 0.4 )
+        {
+            if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+                return 1;
+        }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs resubstitution for the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    // try replacing area critical fanins
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+        {
+            if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+                return 1;
+        }
+    // try removing redundant edges
+    if ( !p->pPars->fArea )
+    {
+        Abc_ObjForEachFanin( pNode, pFanin, i )
+            if ( Abc_ObjIsCi(pFanin) || Abc_ObjFanoutNum(pFanin) != 1 )
+            {
+                if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) )
+                    return 1;
+            }
+    }
+    if ( Abc_ObjFaninNum(pNode) == p->nFaninMax )
+        return 0;
+    // try replacing area critical fanins while adding two new fanins
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+        {
+            if ( Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) )
+                return 1;
+        }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs resubstitution for the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsResubNode2( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin, * pFanin2;
+    int i, k;
+/*
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+        {
+            if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+                return 1;
+        }
+*/
+    if ( Abc_ObjFaninNum(pNode) < 2 )
+        return 0;
+    // try replacing one area critical fanin and one other fanin while adding two new fanins
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+        {
+            // consider second fanin to remove at the same time
+            Abc_ObjForEachFanin( pNode, pFanin2, k )
+            {
+                if ( i != k && Abc_NtkMfsSolveSatResub2( p, pNode, i, k ) )
+                    return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/mfs/mfsSat.c b/abc-build/src/opt/mfs/mfsSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/mfs/mfsSat.c
@@ -0,0 +1,182 @@
+/**CFile****************************************************************
+
+  FileName    [mfsSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The good old minimization with complete don't-cares.]
+
+  Synopsis    [Procedures to compute don't-cares using SAT.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mfsSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mfsInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Enumerates through the SAT assignments.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMfsSolveSat_iter( Mfs_Man_t * p )
+{
+    int Lits[MFS_FANIN_MAX];
+    int RetValue, nBTLimit, iVar, b, Mint;
+//    int nConfs = p->pSat->stats.conflicts;
+    if ( p->nTotConfLim && p->nTotConfLim <= p->pSat->stats.conflicts )
+        return -1;
+    nBTLimit = p->nTotConfLim? p->nTotConfLim - p->pSat->stats.conflicts : 0;
+    RetValue = sat_solver_solve( p->pSat, NULL, NULL, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    assert( RetValue == l_Undef || RetValue == l_True || RetValue == l_False );
+//printf( "%c", RetValue==l_Undef ? '?' : (RetValue==l_False ? '-' : '+') );
+//printf( "%d ", p->pSat->stats.conflicts-nConfs );
+//if ( RetValue==l_False )
+//printf( "\n" );
+    if ( RetValue == l_Undef )
+        return -1;
+    if ( RetValue == l_False )
+        return 0;
+    p->nCares++;
+    // add SAT assignment to the solver
+    Mint = 0;
+    Vec_IntForEachEntry( p->vProjVarsSat, iVar, b )
+    {
+        Lits[b] = toLit( iVar );
+        if ( sat_solver_var_value( p->pSat, iVar ) )
+        {
+            Mint |= (1 << b);
+            Lits[b] = lit_neg( Lits[b] );
+        }
+    }
+    assert( !Abc_InfoHasBit(p->uCare, Mint) );
+    Abc_InfoSetBit( p->uCare, Mint );
+    // add the blocking clause
+    RetValue = sat_solver_addclause( p->pSat, Lits, Lits + Vec_IntSize(p->vProjVarsSat) );
+    if ( RetValue == 0 )
+        return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Enumerates through the SAT assignments.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+int Abc_NtkMfsSolveSat( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    Aig_Obj_t * pObjPo;
+    int RetValue, i;
+    // collect projection variables
+    Vec_IntClear( p->vProjVarsSat );
+    Vec_PtrForEachEntryStart( Aig_Obj_t *, p->pAigWin->vCos, pObjPo, i, Aig_ManCoNum(p->pAigWin) - Abc_ObjFaninNum(pNode) )
+    {
+        assert( p->pCnf->pVarNums[pObjPo->Id] >= 0 );
+        Vec_IntPush( p->vProjVarsSat, p->pCnf->pVarNums[pObjPo->Id] );
+    }
+
+    // prepare the truth table of care set
+    p->nFanins = Vec_IntSize( p->vProjVarsSat );
+    p->nWords = Abc_TruthWordNum( p->nFanins );
+    memset( p->uCare, 0, sizeof(unsigned) * p->nWords );
+
+    // iterate through the SAT assignments
+    p->nCares = 0;
+    p->nTotConfLim = p->pPars->nBTLimit;
+    while ( (RetValue = Abc_NtkMfsSolveSat_iter(p)) == 1 );
+    if ( RetValue == -1 )
+        return 0;
+
+    // write statistics
+    p->nMintsCare  += p->nCares;
+    p->nMintsTotal += (1<<p->nFanins);
+
+    if ( p->pPars->fVeryVerbose )
+    {
+        printf( "Node %4d : Care = %2d. Total = %2d.  ", pNode->Id, p->nCares, (1<<p->nFanins) );
+        Extra_PrintBinary( stdout, p->uCare, (1<<p->nFanins) );
+        printf( "\n" );
+    }
+
+    // map the care 
+    if ( p->nFanins > 4 )
+        return 1;
+    if ( p->nFanins == 4 )
+        p->uCare[0] = p->uCare[0] | (p->uCare[0] << 16);
+    if ( p->nFanins == 3 )
+        p->uCare[0] = p->uCare[0] | (p->uCare[0] << 8) | (p->uCare[0] << 16) | (p->uCare[0] << 24);
+    if ( p->nFanins == 2 )
+        p->uCare[0] = p->uCare[0] | (p->uCare[0] <<  4) | (p->uCare[0] <<  8) | (p->uCare[0] << 12) |
+              (p->uCare[0] << 16) | (p->uCare[0] << 20) | (p->uCare[0] << 24) | (p->uCare[0] << 28);
+    assert( p->nFanins != 1 );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one-hotness constraints for the window inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+int Abc_NtkAddOneHotness( Mfs_Man_t * p )
+{
+    Aig_Obj_t * pObj1, * pObj2;
+    int i, k, Lits[2];
+    for ( i = 0; i < Vec_PtrSize(p->pAigWin->vCis); i++ )
+    for ( k = i+1; k < Vec_PtrSize(p->pAigWin->vCis); k++ )
+    {
+        pObj1 = Aig_ManCi( p->pAigWin, i );
+        pObj2 = Aig_ManCi( p->pAigWin, k );
+        Lits[0] = toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 );
+        Lits[1] = toLitCond( p->pCnf->pVarNums[pObj2->Id], 1 );
+        if ( !sat_solver_addclause( p->pSat, Lits, Lits+2 ) )
+        {
+            sat_solver_delete( p->pSat );
+            p->pSat = NULL;
+            return 0;
+        }
+    }
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/mfs/mfsStrash.c b/abc-build/src/opt/mfs/mfsStrash.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/mfs/mfsStrash.c
@@ -0,0 +1,406 @@
+/**CFile****************************************************************
+
+  FileName    [mfsStrash.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The good old minimization with complete don't-cares.]
+
+  Synopsis    [Structural hashing of the window with ODCs.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mfsStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mfsInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively converts AIG from Aig_Man_t into Hop_Obj_t.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MfsConvertAigToHop_rec( Aig_Obj_t * pObj, Hop_Man_t * pHop )
+{
+    assert( !Aig_IsComplement(pObj) );
+    if ( pObj->pData )
+        return;
+    Abc_MfsConvertAigToHop_rec( Aig_ObjFanin0(pObj), pHop ); 
+    Abc_MfsConvertAigToHop_rec( Aig_ObjFanin1(pObj), pHop );
+    pObj->pData = Hop_And( pHop, (Hop_Obj_t *)Aig_ObjChild0Copy(pObj), (Hop_Obj_t *)Aig_ObjChild1Copy(pObj) ); 
+    assert( !Hop_IsComplement((Hop_Obj_t *)pObj->pData) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts AIG from Aig_Man_t into Hop_Obj_t.]
+
+  Description [Assumes that Aig_Man_t has exactly one primary outputs.
+  Returns the pointer to the root node (Hop_Obj_t) in Hop_Man_t.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Abc_MfsConvertAigToHop( Aig_Man_t * pMan, Hop_Man_t * pHop )
+{
+    Aig_Obj_t * pRoot, * pObj;
+    int i;
+    assert( Aig_ManCoNum(pMan) == 1 );
+    pRoot = Aig_ManCo( pMan, 0 );
+    // check the case of a constant
+    if ( Aig_ObjIsConst1( Aig_ObjFanin0(pRoot) ) )
+        return Hop_NotCond( Hop_ManConst1(pHop), Aig_ObjFaninC0(pRoot) );
+    // set the PI mapping
+    Aig_ManCleanData( pMan );
+    Aig_ManForEachCi( pMan, pObj, i )
+        pObj->pData = Hop_IthVar( pHop, i );
+    // construct the AIG
+    Abc_MfsConvertAigToHop_rec( Aig_ObjFanin0(pRoot), pHop );
+    return Hop_NotCond( (Hop_Obj_t *)Aig_ObjFanin0(pRoot)->pData, Aig_ObjFaninC0(pRoot) );
+}
+
+// should be called as follows:   pNodeNew->pData = Abc_MfsConvertAigToHop( pAigManInterpol, pNodeNew->pNtk->pManFunc );
+
+/**Function*************************************************************
+
+  Synopsis    [Construct BDDs and mark AIG nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MfsConvertHopToAig_rec( Hop_Obj_t * pObj, Aig_Man_t * pMan )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+        return;
+    Abc_MfsConvertHopToAig_rec( Hop_ObjFanin0(pObj), pMan ); 
+    Abc_MfsConvertHopToAig_rec( Hop_ObjFanin1(pObj), pMan );
+    pObj->pData = Aig_And( pMan, (Aig_Obj_t *)Hop_ObjChild0Copy(pObj), (Aig_Obj_t *)Hop_ObjChild1Copy(pObj) ); 
+    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjSetMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the network from AIG to BDD representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MfsConvertHopToAig( Abc_Obj_t * pObjOld, Aig_Man_t * pMan )
+{
+    Hop_Man_t * pHopMan;
+    Hop_Obj_t * pRoot;
+    Abc_Obj_t * pFanin;
+    int i;
+    // get the local AIG
+    pHopMan = (Hop_Man_t *)pObjOld->pNtk->pManFunc;
+    pRoot = (Hop_Obj_t *)pObjOld->pData;
+    // check the case of a constant
+    if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) )
+    {
+        pObjOld->pCopy = (Abc_Obj_t *)Aig_NotCond( Aig_ManConst1(pMan), Hop_IsComplement(pRoot) );
+        pObjOld->pNext = pObjOld->pCopy;
+        return;
+    }
+
+    // assign the fanin nodes
+    Abc_ObjForEachFanin( pObjOld, pFanin, i )
+        Hop_ManPi(pHopMan, i)->pData = pFanin->pCopy;
+    // construct the AIG
+    Abc_MfsConvertHopToAig_rec( Hop_Regular(pRoot), pMan );
+    pObjOld->pCopy = (Abc_Obj_t *)Aig_NotCond( (Aig_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );  
+    Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
+
+    // assign the fanin nodes
+    Abc_ObjForEachFanin( pObjOld, pFanin, i )
+        Hop_ManPi(pHopMan, i)->pData = pFanin->pNext;
+    // construct the AIG
+    Abc_MfsConvertHopToAig_rec( Hop_Regular(pRoot), pMan );
+    pObjOld->pNext = (Abc_Obj_t *)Aig_NotCond( (Aig_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );  
+    Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the care set of the node under ODCs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Abc_NtkConstructAig_rec( Mfs_Man_t * p, Abc_Obj_t * pNode, Aig_Man_t * pMan )
+{
+    Aig_Obj_t * pRoot, * pExor;
+    Abc_Obj_t * pObj;
+    int i;
+    // assign AIG nodes to the leaves
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vSupp, pObj, i )
+        pObj->pCopy = pObj->pNext = (Abc_Obj_t *)Aig_ObjCreateCi( pMan );
+    // strash intermediate nodes
+    Abc_NtkIncrementTravId( pNode->pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodes, pObj, i )
+    {
+        Abc_MfsConvertHopToAig( pObj, pMan );
+        if ( pObj == pNode )
+            pObj->pNext = Abc_ObjNot(pObj->pNext);
+    }
+    // create the observability condition
+    pRoot = Aig_ManConst0(pMan);
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i )
+    {
+        pExor = Aig_Exor( pMan, (Aig_Obj_t *)pObj->pCopy, (Aig_Obj_t *)pObj->pNext );
+        pRoot = Aig_Or( pMan, pRoot, pExor );
+    }
+    return pRoot;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds relevant constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Abc_NtkConstructCare_rec( Aig_Man_t * pCare, Aig_Obj_t * pObj, Aig_Man_t * pMan )
+{
+    Aig_Obj_t * pObj0, * pObj1;
+    if ( Aig_ObjIsTravIdCurrent( pCare, pObj ) )
+        return (Aig_Obj_t *)pObj->pData;
+    Aig_ObjSetTravIdCurrent( pCare, pObj );
+    if ( Aig_ObjIsCi(pObj) )
+        return (Aig_Obj_t *)(pObj->pData = NULL);
+    pObj0 = Abc_NtkConstructCare_rec( pCare, Aig_ObjFanin0(pObj), pMan );
+    if ( pObj0 == NULL )
+        return (Aig_Obj_t *)(pObj->pData = NULL);
+    pObj1 = Abc_NtkConstructCare_rec( pCare, Aig_ObjFanin1(pObj), pMan );
+    if ( pObj1 == NULL )
+        return (Aig_Obj_t *)(pObj->pData = NULL);
+    pObj0 = Aig_NotCond( pObj0, Aig_ObjFaninC0(pObj) );
+    pObj1 = Aig_NotCond( pObj1, Aig_ObjFaninC1(pObj) );
+    return (Aig_Obj_t *)(pObj->pData = Aig_And( pMan, pObj0, pObj1 ));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates AIG for the window with constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Abc_NtkConstructAig( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    Aig_Man_t * pMan;
+    Abc_Obj_t * pFanin;
+    Aig_Obj_t * pObjAig, * pPi, * pPo;
+    Vec_Int_t * vOuts;
+    int i, k, iOut;
+    // start the new manager
+    pMan = Aig_ManStart( 1000 );
+    // construct the root node's AIG cone
+    pObjAig = Abc_NtkConstructAig_rec( p, pNode, pMan );
+//    assert( Aig_ManConst1(pMan) == pObjAig );
+    Aig_ObjCreateCo( pMan, pObjAig );
+    if ( p->pCare )
+    {
+        // mark the care set
+        Aig_ManIncrementTravId( p->pCare );
+        Vec_PtrForEachEntry( Abc_Obj_t *, p->vSupp, pFanin, i )
+        {
+            pPi = Aig_ManCi( p->pCare, (int)(ABC_PTRUINT_T)pFanin->pData );
+            Aig_ObjSetTravIdCurrent( p->pCare, pPi );
+            pPi->pData = pFanin->pCopy;
+        }
+        // construct the constraints
+        Vec_PtrForEachEntry( Abc_Obj_t *, p->vSupp, pFanin, i )
+        {
+            vOuts = (Vec_Int_t *)Vec_PtrEntry( p->vSuppsInv, (int)(ABC_PTRUINT_T)pFanin->pData );
+            Vec_IntForEachEntry( vOuts, iOut, k )
+            {
+                pPo = Aig_ManCo( p->pCare, iOut );
+                if ( Aig_ObjIsTravIdCurrent( p->pCare, pPo ) )
+                    continue;
+                Aig_ObjSetTravIdCurrent( p->pCare, pPo );
+                if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(p->pCare) )
+                    continue;
+                pObjAig = Abc_NtkConstructCare_rec( p->pCare, Aig_ObjFanin0(pPo), pMan );
+                if ( pObjAig == NULL )
+                    continue;
+                pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) );
+                Aig_ObjCreateCo( pMan, pObjAig );
+            }
+        }
+/*
+        Aig_ManForEachCo( p->pCare, pPo, i )
+        {
+//            assert( Aig_ObjFanin0(pPo) != Aig_ManConst1(p->pCare) );
+            if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(p->pCare) )
+                continue;
+            pObjAig = Abc_NtkConstructCare_rec( p->pCare, Aig_ObjFanin0(pPo), pMan );
+            if ( pObjAig == NULL )
+                continue;
+            pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) );
+            Aig_ObjCreateCo( pMan, pObjAig );
+        }
+*/
+    }
+    if ( p->pPars->fResub )
+    {
+        // construct the node
+        pObjAig = (Aig_Obj_t *)pNode->pCopy;
+        Aig_ObjCreateCo( pMan, pObjAig );
+        // construct the divisors
+        Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs, pFanin, i )
+        {
+            pObjAig = (Aig_Obj_t *)pFanin->pCopy;
+            Aig_ObjCreateCo( pMan, pObjAig );
+        }
+    }
+    else
+    {
+        // construct the fanins
+        Abc_ObjForEachFanin( pNode, pFanin, i )
+        {
+            pObjAig = (Aig_Obj_t *)pFanin->pCopy;
+            Aig_ObjCreateCo( pMan, pObjAig );
+        }
+    }
+    Aig_ManCleanup( pMan );
+    return pMan;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates AIG for the window with constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Abc_NtkAigForConstraints( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    Aig_Man_t * pMan;
+    Aig_Obj_t * pPi, * pPo, * pObjAig, * pObjRoot;
+    Vec_Int_t * vOuts;
+    int i, k, iOut;
+    if ( p->pCare == NULL )
+        return NULL;
+    pMan = Aig_ManStart( 1000 );
+    // mark the care set
+    Aig_ManIncrementTravId( p->pCare );
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vSupp, pFanin, i )
+    {
+        pPi = Aig_ManCi( p->pCare, (int)(ABC_PTRUINT_T)pFanin->pData );
+        Aig_ObjSetTravIdCurrent( p->pCare, pPi );
+        pPi->pData = Aig_ObjCreateCi(pMan);
+    }
+    // construct the constraints
+    pObjRoot = Aig_ManConst1(pMan);
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vSupp, pFanin, i )
+    {
+        vOuts = (Vec_Int_t *)Vec_PtrEntry( p->vSuppsInv, (int)(ABC_PTRUINT_T)pFanin->pData );
+        Vec_IntForEachEntry( vOuts, iOut, k )
+        {
+            pPo = Aig_ManCo( p->pCare, iOut );
+            if ( Aig_ObjIsTravIdCurrent( p->pCare, pPo ) )
+                continue;
+            Aig_ObjSetTravIdCurrent( p->pCare, pPo );
+            if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(p->pCare) )
+                continue;
+            pObjAig = Abc_NtkConstructCare_rec( p->pCare, Aig_ObjFanin0(pPo), pMan );
+            if ( pObjAig == NULL )
+                continue;
+            pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) );
+            pObjRoot = Aig_And( pMan, pObjRoot, pObjAig );
+        }
+    }
+    Aig_ObjCreateCo( pMan, pObjRoot );
+    Aig_ManCleanup( pMan );
+    return pMan;
+}
+
+ABC_NAMESPACE_IMPL_END
+
+#include "proof/fra/fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the ratio of don't-cares.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+double Abc_NtkConstraintRatio( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+    int nSimWords = 256;
+    Aig_Man_t * pMan;
+    Fra_Sml_t * pSim;
+    int Counter;
+    pMan = Abc_NtkAigForConstraints( p, pNode );
+    pSim = Fra_SmlSimulateComb( pMan, nSimWords, 0 );
+    Counter = Fra_SmlNodeCountOnes( pSim, Aig_ManCo(pMan, 0) );
+    Aig_ManStop( pMan );
+    Fra_SmlStop( pSim );
+    return 1.0 * Counter / (32 * nSimWords);
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/mfs/mfsWin.c b/abc-build/src/opt/mfs/mfsWin.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/mfs/mfsWin.c
@@ -0,0 +1,117 @@
+/**CFile****************************************************************
+
+  FileName    [mfsWin.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The good old minimization with complete don't-cares.]
+
+  Synopsis    [Procedures to compute windows stretching to the PIs.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mfsWin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mfsInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node should be a root.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_MfsComputeRootsCheck( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    // the node is the root if one of the following is true:
+    // (1) the node has more than fanouts than the limit
+    if ( Abc_ObjFanoutNum(pNode) > nFanoutLimit )
+        return 1;
+    // (2) the node has CO fanouts
+    // (3) the node has fanouts above the cutoff level
+    Abc_ObjForEachFanout( pNode, pFanout, i )
+        if ( Abc_ObjIsCo(pFanout) || (int)pFanout->Level > nLevelMax )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively collects the root candidates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_MfsComputeRoots_rec( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit, Vec_Ptr_t * vRoots )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    assert( Abc_ObjIsNode(pNode) );
+    if ( Abc_NodeIsTravIdCurrent(pNode) )
+        return;
+    Abc_NodeSetTravIdCurrent( pNode );
+    // check if the node should be the root
+    if ( Abc_MfsComputeRootsCheck( pNode, nLevelMax, nFanoutLimit ) )
+        Vec_PtrPush( vRoots, pNode );
+    else // if not, explore its fanouts
+        Abc_ObjForEachFanout( pNode, pFanout, i )
+            Abc_MfsComputeRoots_rec( pFanout, nLevelMax, nFanoutLimit, vRoots );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively collects the root candidates.]
+
+  Description [Returns 1 if the only root is this node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_MfsComputeRoots( Abc_Obj_t * pNode, int nWinTfoMax, int nFanoutLimit )
+{
+    Vec_Ptr_t * vRoots;
+    vRoots = Vec_PtrAlloc( 10 );
+    Abc_NtkIncrementTravId( pNode->pNtk );
+    Abc_MfsComputeRoots_rec( pNode, pNode->Level + nWinTfoMax, nFanoutLimit, vRoots );
+    assert( Vec_PtrSize(vRoots) > 0 );
+//    if ( Vec_PtrSize(vRoots) == 1 && Vec_PtrEntry(vRoots, 0) == pNode )
+//        return 0;
+    return vRoots;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/mfs/mfs_.c b/abc-build/src/opt/mfs/mfs_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/mfs/mfs_.c
@@ -0,0 +1,52 @@
+/**CFile****************************************************************
+
+  FileName    [mfs_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [The good old minimization with complete don't-cares.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: mfs_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mfsInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/mfs/module.make b/abc-build/src/opt/mfs/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/mfs/module.make
@@ -0,0 +1,8 @@
+SRC +=  src/opt/mfs/mfsCore.c \
+	src/opt/mfs/mfsDiv.c \
+	src/opt/mfs/mfsInter.c \
+	src/opt/mfs/mfsMan.c \
+	src/opt/mfs/mfsResub.c \
+	src/opt/mfs/mfsSat.c \
+	src/opt/mfs/mfsStrash.c \
+	src/opt/mfs/mfsWin.c
diff --git a/abc-build/src/opt/nwk/module.make b/abc-build/src/opt/nwk/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/module.make
@@ -0,0 +1,14 @@
+SRC +=	src/opt/nwk/nwkAig.c \
+	src/opt/nwk/nwkCheck.c \
+	src/opt/nwk/nwkBidec.c \
+	src/opt/nwk/nwkDfs.c \
+	src/opt/nwk/nwkFanio.c \
+	src/opt/nwk/nwkFlow.c \
+	src/opt/nwk/nwkMan.c \
+	src/opt/nwk/nwkMap.c \
+	src/opt/nwk/nwkMerge.c \
+	src/opt/nwk/nwkObj.c \
+	src/opt/nwk/nwkSpeedup.c \
+	src/opt/nwk/nwkStrash.c \
+	src/opt/nwk/nwkTiming.c \
+	src/opt/nwk/nwkUtil.c
diff --git a/abc-build/src/opt/nwk/ntlnwk.h b/abc-build/src/opt/nwk/ntlnwk.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/ntlnwk.h
@@ -0,0 +1,113 @@
+/**CFile****************************************************************
+
+  FileName    [ntlnwk.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Netlist and network representation.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: ntlnwk.h,v 1.3 2008/10/24 14:18:44 mjarvin Exp $]
+
+***********************************************************************/
+ 
+#ifndef __NTLNWK_abc_opt_nwk_h
+#define __NTLNWK_abc_opt_nwk_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ntl_Man_t_    Ntl_Man_t;
+typedef struct Nwk_Man_t_    Nwk_Man_t;
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      INLINED FUNCTIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         ITERATORS                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+extern ABC_DLL Ntl_Man_t * Ntl_ManReadBlif( char * pFileName, int fCheck );
+extern ABC_DLL void        Ntl_ManWriteBlif( Ntl_Man_t * p, char * pFileName );
+
+extern ABC_DLL Tim_Man_t * Ntl_ManReadTimeMan( Ntl_Man_t * p );
+extern ABC_DLL Ntl_Man_t * Ntl_ManDup( Ntl_Man_t * p );
+extern ABC_DLL void        Ntl_ManFree( Ntl_Man_t * p );
+extern ABC_DLL int         Ntl_ManIsComb( Ntl_Man_t * p );
+extern ABC_DLL void        Ntl_ManPrintStats( Ntl_Man_t * p );
+extern ABC_DLL int         Ntl_ManSweep( Ntl_Man_t * p, int fVerbose );
+extern ABC_DLL Ntl_Man_t * Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk );
+extern ABC_DLL Ntl_Man_t * Ntl_ManInsertAig( Ntl_Man_t * p, Aig_Man_t * pAig );
+extern ABC_DLL Aig_Man_t * Ntl_ManExtract( Ntl_Man_t * p );
+extern ABC_DLL Aig_Man_t * Ntl_ManCollapse( Ntl_Man_t * p, int fSeq );
+extern ABC_DLL Aig_Man_t * Ntl_ManCollapseSeq( Ntl_Man_t * p, int nMinDomSize, int fVerbose );
+extern ABC_DLL Ntl_Man_t * Ntl_ManDupCollapseLuts( Ntl_Man_t * p );
+extern ABC_DLL Ntl_Man_t * Ntl_ManFraig( Ntl_Man_t * p, int nPartSize, int nConfLimit, int nLevelMax, int fUseCSat, int fVerbose );
+extern ABC_DLL void        Ntl_ManPrepareCecMans( Ntl_Man_t * pMan1, Ntl_Man_t * pMan2, Aig_Man_t ** ppAig1, Aig_Man_t ** ppAig2 );
+extern ABC_DLL Vec_Ptr_t * Ntl_ManCollectCiNames( Ntl_Man_t * p );
+extern ABC_DLL Vec_Ptr_t * Ntl_ManCollectCoNames( Ntl_Man_t * p );
+extern ABC_DLL Ntl_Man_t * Ntl_ManScl( Ntl_Man_t * p, int fLatchConst, int fLatchEqual, int fVerbose );
+extern ABC_DLL Ntl_Man_t * Ntl_ManLcorr( Ntl_Man_t * p, int nConfMax, int fScorrGia, int fUseCSat, int fVerbose );
+extern ABC_DLL Ntl_Man_t * Ntl_ManSsw( Ntl_Man_t * p, Fra_Ssw_t * pPars );
+extern ABC_DLL Ntl_Man_t * Ntl_ManScorr( Ntl_Man_t * p, Ssw_Pars_t * pPars );
+extern ABC_DLL void        Ntl_ManTransformInitValues( Ntl_Man_t * p );
+
+extern ABC_DLL void        Ntl_ManPrepareCec( char * pFileName1, char * pFileName2, Aig_Man_t ** ppMan1, Aig_Man_t ** ppMan2 );
+extern ABC_DLL Aig_Man_t * Ntl_ManPrepareSec( char * pFileName1, char * pFileName2 );
+
+extern ABC_DLL Nwk_Man_t * Ntl_ManExtractNwk( Ntl_Man_t * p, Aig_Man_t * pAig, Tim_Man_t * pManTime );
+extern ABC_DLL Nwk_Man_t * Ntl_ManReadNwk( char * pFileName, Aig_Man_t * pAig, Tim_Man_t * pManTime );
+extern ABC_DLL void        Nwk_ManPrintStats( Nwk_Man_t * p, If_LibLut_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, Ntl_Man_t * pNtl );
+extern ABC_DLL void        Nwk_ManPrintStatsShort( Ntl_Man_t * p, Aig_Man_t * pAig, Nwk_Man_t * pNtk );
+extern ABC_DLL void        Nwk_ManPrintFanioNew( Nwk_Man_t * p );
+extern ABC_DLL Nwk_Man_t * Nwk_MappingIf( Aig_Man_t * p, Tim_Man_t * pManTime, If_Par_t * pPars );
+extern ABC_DLL void        Nwk_ManSetIfParsDefault( If_Par_t * pPars );
+extern ABC_DLL void        Nwk_ManBidecResyn( Nwk_Man_t * p, int fVerbose );
+extern ABC_DLL Aig_Man_t * Nwk_ManSpeedup( Nwk_Man_t * p, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose );
+extern ABC_DLL Aig_Man_t * Nwk_ManStrash( Nwk_Man_t * p );
+extern ABC_DLL Vec_Int_t * Nwk_ManLutMerge( Nwk_Man_t * p, void * pPars );
+extern ABC_DLL int         Nwk_ManCheck( Nwk_Man_t * p );
+extern ABC_DLL void        Nwk_ManDumpBlif( Nwk_Man_t * p, char * pFileName, Vec_Ptr_t * vCiNames, Vec_Ptr_t * vCoNames );
+extern ABC_DLL void        Nwk_ManFree( Nwk_Man_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/nwk/nwk.h b/abc-build/src/opt/nwk/nwk.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwk.h
@@ -0,0 +1,307 @@
+/**CFile****************************************************************
+
+  FileName    [nwk.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Logic network representation.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwk.h,v 1.1 2008/05/14 22:13:09 wudenni Exp $]
+
+***********************************************************************/
+ 
+#ifndef __NWK_abc_opt_nwk_h
+#define __NWK_abc_opt_nwk_h
+
+ 
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "aig/aig/aig.h"
+#include "aig/hop/hop.h"
+#include "misc/tim/tim.h"
+#include "map/if/if.h"
+#include "bool/bdc/bdc.h"
+
+#include "proof/fra/fra.h"
+#include "proof/ssw/ssw.h"
+#include "ntlnwk.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Nwk_Obj_t_    Nwk_Obj_t;
+
+// object types
+typedef enum { 
+    NWK_OBJ_NONE,                      // 0: non-existant object
+    NWK_OBJ_CI,                        // 1: combinational input
+    NWK_OBJ_CO,                        // 2: combinational output
+    NWK_OBJ_NODE,                      // 3: logic node
+    NWK_OBJ_LATCH,                     // 4: register
+    NWK_OBJ_VOID                       // 5: unused object
+} Nwk_Type_t;
+
+struct Nwk_Man_t_
+{
+    // models of this design
+    char *             pName;          // the name of this design
+    char *             pSpec;          // the name of input file
+    // node representation
+    Vec_Ptr_t *        vCis;           // the primary inputs of the extracted part
+    Vec_Ptr_t *        vCos;           // the primary outputs of the extracted part 
+    Vec_Ptr_t *        vObjs;          // the objects in the topological order
+    int                nObjs[NWK_OBJ_VOID]; // counter of objects of each type
+    int                nFanioPlus;     // the number of extra fanins/fanouts alloc by default
+    // functionality, timing, memory, etc
+    Hop_Man_t *        pManHop;        // the functionality representation
+    Tim_Man_t *        pManTime;       // the timing manager
+    If_LibLut_t *         pLutLib;        // the LUT library
+    Aig_MmFlex_t *     pMemObjs;       // memory for objects
+    Vec_Ptr_t *        vTemp;          // array used for incremental updates
+    int                nTravIds;       // the counter of traversal IDs
+    int                nRealloced;     // the number of realloced nodes
+    // sequential information
+    int                nLatches;       // the total number of latches 
+    int                nTruePis;       // the number of true primary inputs
+    int                nTruePos;       // the number of true primary outputs
+};
+
+struct Nwk_Obj_t_
+{
+    Nwk_Man_t *        pMan;           // the manager  
+    Hop_Obj_t *        pFunc;          // functionality
+    void *             pCopy;          // temporary pointer
+    union {
+        void *         pNext;          // temporary pointer
+        int            iTemp;          // temporary number
+    };
+    // node information
+    unsigned           Type     :  3;  // object type
+    unsigned           fInvert  :  1;  // complemented attribute
+    unsigned           MarkA    :  1;  // temporary mark  
+    unsigned           MarkB    :  1;  // temporary mark
+    unsigned           MarkC    :  1;  // temporary mark
+    unsigned           PioId    : 25;  // number of this node in the PI/PO list
+    int                Id;             // unique ID
+    int                TravId;         // traversal ID
+    // timing information
+    int                Level;          // the topological level
+    float              tArrival;       // the arrival time
+    float              tRequired;      // the required time
+    float              tSlack;         // the slack
+    // fanin/fanout representation
+    int                nFanins;        // the number of fanins
+    int                nFanouts;       // the number of fanouts
+    int                nFanioAlloc;    // the number of allocated fanins/fanouts
+    Nwk_Obj_t **       pFanio;         // fanins/fanouts
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                      INLINED FUNCTIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int         Nwk_ManCiNum( Nwk_Man_t * p )           { return p->nObjs[NWK_OBJ_CI];                } 
+static inline int         Nwk_ManCoNum( Nwk_Man_t * p )           { return p->nObjs[NWK_OBJ_CO];                } 
+static inline int         Nwk_ManNodeNum( Nwk_Man_t * p )         { return p->nObjs[NWK_OBJ_NODE];              } 
+static inline int         Nwk_ManLatchNum( Nwk_Man_t * p )        { return p->nObjs[NWK_OBJ_LATCH];             } 
+static inline int         Nwk_ManObjNumMax( Nwk_Man_t * p )       { return Vec_PtrSize(p->vObjs);               }
+
+static inline Nwk_Obj_t * Nwk_ManCi( Nwk_Man_t * p, int i )       { return (Nwk_Obj_t *)Vec_PtrEntry( p->vCis, i );          } 
+static inline Nwk_Obj_t * Nwk_ManCo( Nwk_Man_t * p, int i )       { return (Nwk_Obj_t *)Vec_PtrEntry( p->vCos, i );          } 
+static inline Nwk_Obj_t * Nwk_ManObj( Nwk_Man_t * p, int i )      { return (Nwk_Obj_t *)Vec_PtrEntry( p->vObjs, i );         } 
+
+static inline int         Nwk_ObjId( Nwk_Obj_t * p )              { return p->Id;                               } 
+static inline int         Nwk_ObjPioNum( Nwk_Obj_t * p )          { return p->PioId;                            } 
+static inline int         Nwk_ObjFaninNum( Nwk_Obj_t * p )        { return p->nFanins;                          } 
+static inline int         Nwk_ObjFanoutNum( Nwk_Obj_t * p )       { return p->nFanouts;                         } 
+
+static inline Nwk_Obj_t * Nwk_ObjFanin0( Nwk_Obj_t * p )          { return p->pFanio[0];                        } 
+static inline Nwk_Obj_t * Nwk_ObjFanout0( Nwk_Obj_t * p )         { return p->pFanio[p->nFanins];               } 
+static inline Nwk_Obj_t * Nwk_ObjFanin( Nwk_Obj_t * p, int i )    { return p->pFanio[i];                        } 
+static inline Nwk_Obj_t * Nwk_ObjFanout( Nwk_Obj_t * p, int i )   { return p->pFanio[p->nFanins+1];             } 
+
+static inline int         Nwk_ObjIsNone( Nwk_Obj_t * p )          { return p->Type == NWK_OBJ_NONE;             } 
+static inline int         Nwk_ObjIsCi( Nwk_Obj_t * p )            { return p->Type == NWK_OBJ_CI;               } 
+static inline int         Nwk_ObjIsCo( Nwk_Obj_t * p )            { return p->Type == NWK_OBJ_CO;               } 
+static inline int         Nwk_ObjIsNode( Nwk_Obj_t * p )          { return p->Type == NWK_OBJ_NODE;             } 
+static inline int         Nwk_ObjIsLatch( Nwk_Obj_t * p )         { return p->Type == NWK_OBJ_LATCH;            } 
+static inline int         Nwk_ObjIsPi( Nwk_Obj_t * p )            { return Nwk_ObjIsCi(p) && (p->pMan->pManTime == NULL || Tim_ManBoxForCi(p->pMan->pManTime, p->PioId) == -1); } 
+static inline int         Nwk_ObjIsPo( Nwk_Obj_t * p )            { return Nwk_ObjIsCo(p) && (p->pMan->pManTime == NULL || Tim_ManBoxForCo(p->pMan->pManTime, p->PioId) == -1);  }
+static inline int         Nwk_ObjIsLi( Nwk_Obj_t * p )            { return p->pMan->nTruePos && Nwk_ObjIsCo(p) && (int)p->PioId >= p->pMan->nTruePos;       } 
+static inline int         Nwk_ObjIsLo( Nwk_Obj_t * p )            { return p->pMan->nTruePis && Nwk_ObjIsCi(p) && (int)p->PioId >= p->pMan->nTruePis;       } 
+
+static inline float       Nwk_ObjArrival( Nwk_Obj_t * pObj )                 { return pObj->tArrival;           }
+static inline float       Nwk_ObjRequired( Nwk_Obj_t * pObj )                { return pObj->tRequired;          }
+static inline float       Nwk_ObjSlack( Nwk_Obj_t * pObj )                   { return pObj->tSlack;             }
+static inline void        Nwk_ObjSetArrival( Nwk_Obj_t * pObj, float Time )  { pObj->tArrival   = Time;         }
+static inline void        Nwk_ObjSetRequired( Nwk_Obj_t * pObj, float Time ) { pObj->tRequired  = Time;         }
+static inline void        Nwk_ObjSetSlack( Nwk_Obj_t * pObj, float Time )    { pObj->tSlack     = Time;         }
+
+static inline int         Nwk_ObjLevel( Nwk_Obj_t * pObj )                   { return pObj->Level;              }
+static inline void        Nwk_ObjSetLevel( Nwk_Obj_t * pObj, int Level )     { pObj->Level = Level;             }
+
+static inline void        Nwk_ObjSetTravId( Nwk_Obj_t * pObj, int TravId )   { pObj->TravId = TravId;                           }
+static inline void        Nwk_ObjSetTravIdCurrent( Nwk_Obj_t * pObj )        { pObj->TravId = pObj->pMan->nTravIds;             }
+static inline void        Nwk_ObjSetTravIdPrevious( Nwk_Obj_t * pObj )       { pObj->TravId = pObj->pMan->nTravIds - 1;         }
+static inline int         Nwk_ObjIsTravIdCurrent( Nwk_Obj_t * pObj )         { return pObj->TravId == pObj->pMan->nTravIds;     }
+static inline int         Nwk_ObjIsTravIdPrevious( Nwk_Obj_t * pObj )        { return pObj->TravId == pObj->pMan->nTravIds - 1; }
+
+static inline int         Nwk_ManTimeEqual( float f1, float f2, float Eps )  { return (f1 < f2 + Eps) && (f2 < f1 + Eps);  }
+static inline int         Nwk_ManTimeLess( float f1, float f2, float Eps )   { return (f1 < f2 + Eps);                     }
+static inline int         Nwk_ManTimeMore( float f1, float f2, float Eps )   { return (f1 + Eps > f2);                     }
+
+////////////////////////////////////////////////////////////////////////
+///                         ITERATORS                                ///
+////////////////////////////////////////////////////////////////////////
+
+#define Nwk_ManForEachCi( p, pObj, i )                                     \
+    Vec_PtrForEachEntry( Nwk_Obj_t *, p->vCis, pObj, i )
+#define Nwk_ManForEachCo( p, pObj, i )                                     \
+    Vec_PtrForEachEntry( Nwk_Obj_t *, p->vCos, pObj, i )
+#define Nwk_ManForEachPi( p, pObj, i )                                     \
+    Vec_PtrForEachEntry( Nwk_Obj_t *, p->vCis, pObj, i )                                \
+        if ( !Nwk_ObjIsPi(pObj) ) {} else
+#define Nwk_ManForEachPo( p, pObj, i )                                     \
+    Vec_PtrForEachEntry( Nwk_Obj_t *, p->vCos, pObj, i )                                \
+        if ( !Nwk_ObjIsPo(pObj) ) {} else
+#define Nwk_ManForEachObj( p, pObj, i )                                    \
+    for ( i = 0; (i < Vec_PtrSize(p->vObjs)) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vObjs, i)), 1); i++ ) \
+        if ( pObj == NULL ) {} else
+#define Nwk_ManForEachNode( p, pObj, i )                                   \
+    for ( i = 0; (i < Vec_PtrSize(p->vObjs)) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vObjs, i)), 1); i++ ) \
+        if ( (pObj) == NULL || !Nwk_ObjIsNode(pObj) ) {} else
+#define Nwk_ManForEachLatch( p, pObj, i )                                  \
+    for ( i = 0; (i < Vec_PtrSize(p->vObjs)) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vObjs, i)), 1); i++ ) \
+        if ( (pObj) == NULL || !Nwk_ObjIsLatch(pObj) ) {} else
+
+#define Nwk_ObjForEachFanin( pObj, pFanin, i )                                  \
+    for ( i = 0; (i < (int)(pObj)->nFanins) && ((pFanin) = (pObj)->pFanio[i]); i++ )
+#define Nwk_ObjForEachFanout( pObj, pFanout, i )                                \
+    for ( i = 0; (i < (int)(pObj)->nFanouts) && ((pFanout) = (pObj)->pFanio[(pObj)->nFanins+i]); i++ )
+
+// sequential iterators
+#define Nwk_ManForEachPiSeq( p, pObj, i )                                           \
+    Vec_PtrForEachEntryStop( Nwk_Obj_t *, p->vCis, pObj, i, (p)->nTruePis )
+#define Nwk_ManForEachPoSeq( p, pObj, i )                                           \
+    Vec_PtrForEachEntryStop( Nwk_Obj_t *, p->vCos, pObj, i, (p)->nTruePos )
+#define Nwk_ManForEachLoSeq( p, pObj, i )                                           \
+    for ( i = 0; (i < (p)->nLatches) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vCis, i+(p)->nTruePis)), 1); i++ )
+#define Nwk_ManForEachLiSeq( p, pObj, i )                                           \
+    for ( i = 0; (i < (p)->nLatches) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vCos, i+(p)->nTruePos)), 1); i++ )
+#define Nwk_ManForEachLiLoSeq( p, pObjLi, pObjLo, i )                               \
+    for ( i = 0; (i < (p)->nLatches) && (((pObjLi) = Nwk_ManCo(p, i+(p)->nTruePos)), 1)        \
+        && (((pObjLo) = Nwk_ManCi(p, i+(p)->nTruePis)), 1); i++ )
+
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== nwkAig.c ==========================================================*/
+extern ABC_DLL Vec_Ptr_t *     Nwk_ManDeriveRetimingCut( Aig_Man_t * p, int fForward, int fVerbose );
+/*=== nwkBidec.c ==========================================================*/
+extern ABC_DLL void            Nwk_ManBidecResyn( Nwk_Man_t * pNtk, int fVerbose );
+extern ABC_DLL Hop_Obj_t *     Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb );
+/*=== nwkCheck.c ==========================================================*/
+extern ABC_DLL int             Nwk_ManCheck( Nwk_Man_t * p );
+/*=== nwkDfs.c ==========================================================*/
+extern ABC_DLL int             Nwk_ManVerifyTopoOrder( Nwk_Man_t * pNtk );
+extern ABC_DLL int             Nwk_ManLevelBackup( Nwk_Man_t * pNtk );
+extern ABC_DLL int             Nwk_ManLevel( Nwk_Man_t * pNtk );
+extern ABC_DLL int             Nwk_ManLevelMax( Nwk_Man_t * pNtk );
+extern ABC_DLL Vec_Vec_t *     Nwk_ManLevelize( Nwk_Man_t * pNtk );
+extern ABC_DLL Vec_Ptr_t *     Nwk_ManDfs( Nwk_Man_t * pNtk );
+extern ABC_DLL Vec_Ptr_t *     Nwk_ManDfsNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes );
+extern ABC_DLL Vec_Ptr_t *     Nwk_ManDfsReverse( Nwk_Man_t * pNtk );
+extern ABC_DLL Vec_Ptr_t *     Nwk_ManSupportNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes );
+extern ABC_DLL void            Nwk_ManSupportSum( Nwk_Man_t * pNtk );
+extern ABC_DLL int             Nwk_ObjMffcLabel( Nwk_Obj_t * pNode );
+/*=== nwkFanio.c ==========================================================*/
+extern ABC_DLL void            Nwk_ObjCollectFanins( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes );
+extern ABC_DLL void            Nwk_ObjCollectFanouts( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes );
+extern ABC_DLL int             Nwk_ObjFindFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin );
+extern ABC_DLL int             Nwk_ObjFindFanout( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanout );
+extern ABC_DLL void            Nwk_ObjAddFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin );
+extern ABC_DLL void            Nwk_ObjDeleteFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin );
+extern ABC_DLL void            Nwk_ObjPatchFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFaninOld, Nwk_Obj_t * pFaninNew );
+extern ABC_DLL void            Nwk_ObjTransferFanout( Nwk_Obj_t * pNodeFrom, Nwk_Obj_t * pNodeTo );
+extern ABC_DLL void            Nwk_ObjReplace( Nwk_Obj_t * pNodeOld, Nwk_Obj_t * pNodeNew );
+/*=== nwkFlow.c ============================================================*/
+extern ABC_DLL Vec_Ptr_t *     Nwk_ManRetimeCutForward( Nwk_Man_t * pMan, int nLatches, int fVerbose );
+extern ABC_DLL Vec_Ptr_t *     Nwk_ManRetimeCutBackward( Nwk_Man_t * pMan, int nLatches, int fVerbose );
+/*=== nwkMan.c ============================================================*/
+extern ABC_DLL Nwk_Man_t *     Nwk_ManAlloc();
+extern ABC_DLL void            Nwk_ManFree( Nwk_Man_t * p );
+extern ABC_DLL float           Nwl_ManComputeTotalSwitching( Nwk_Man_t * pNtk );
+extern ABC_DLL void            Nwk_ManPrintStats( Nwk_Man_t * p, If_LibLut_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, Ntl_Man_t * pNtl );
+/*=== nwkMap.c ============================================================*/
+extern ABC_DLL Nwk_Man_t *     Nwk_MappingIf( Aig_Man_t * p, Tim_Man_t * pManTime, If_Par_t * pPars );
+/*=== nwkObj.c ============================================================*/
+extern ABC_DLL Nwk_Obj_t *     Nwk_ManCreateCi( Nwk_Man_t * pMan, int nFanouts );
+extern ABC_DLL Nwk_Obj_t *     Nwk_ManCreateCo( Nwk_Man_t * pMan );
+extern ABC_DLL Nwk_Obj_t *     Nwk_ManCreateNode( Nwk_Man_t * pMan, int nFanins, int nFanouts );
+extern ABC_DLL Nwk_Obj_t *     Nwk_ManCreateBox( Nwk_Man_t * pMan, int nFanins, int nFanouts );
+extern ABC_DLL Nwk_Obj_t *     Nwk_ManCreateLatch( Nwk_Man_t * pMan );
+extern ABC_DLL void            Nwk_ManDeleteNode( Nwk_Obj_t * pObj );
+extern ABC_DLL void            Nwk_ManDeleteNode_rec( Nwk_Obj_t * pObj );
+/*=== nwkSpeedup.c ============================================================*/
+extern ABC_DLL Aig_Man_t *     Nwk_ManSpeedup( Nwk_Man_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose );
+/*=== nwkStrash.c ============================================================*/
+extern ABC_DLL Aig_Man_t *     Nwk_ManStrash( Nwk_Man_t * pNtk );
+/*=== nwkTiming.c ============================================================*/
+extern ABC_DLL int             Nwk_ManVerifyTiming(  Nwk_Man_t * pNtk );
+extern ABC_DLL void            Nwk_ManDelayTraceSortPins( Nwk_Obj_t * pNode, int * pPinPerm, float * pPinDelays );
+extern ABC_DLL float           Nwk_ManDelayTraceLut( Nwk_Man_t * pNtk );
+extern ABC_DLL void            Nwk_ManDelayTracePrint( Nwk_Man_t * pNtk );
+extern ABC_DLL void            Nwk_ManUpdate( Nwk_Obj_t * pObj, Nwk_Obj_t * pObjNew, Vec_Vec_t * vLevels );
+extern ABC_DLL int             Nwk_ManVerifyLevel( Nwk_Man_t * pNtk );
+/*=== nwkUtil.c ============================================================*/
+extern ABC_DLL void            Nwk_ManIncrementTravId( Nwk_Man_t * pNtk );
+extern ABC_DLL int             Nwk_ManGetFaninMax( Nwk_Man_t * pNtk );
+extern ABC_DLL int             Nwk_ManGetTotalFanins( Nwk_Man_t * pNtk );
+extern ABC_DLL int             Nwk_ManPiNum( Nwk_Man_t * pNtk );
+extern ABC_DLL int             Nwk_ManPoNum( Nwk_Man_t * pNtk );
+extern ABC_DLL int             Nwk_ManGetAigNodeNum( Nwk_Man_t * pNtk );
+extern ABC_DLL int             Nwk_NodeCompareLevelsIncrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 );
+extern ABC_DLL int             Nwk_NodeCompareLevelsDecrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 );
+extern ABC_DLL void            Nwk_ObjPrint( Nwk_Obj_t * pObj );
+extern ABC_DLL void            Nwk_ManDumpBlif( Nwk_Man_t * pNtk, char * pFileName, Vec_Ptr_t * vCiNames, Vec_Ptr_t * vCoNames );
+extern ABC_DLL void            Nwk_ManPrintFanioNew( Nwk_Man_t * pNtk );
+extern ABC_DLL void            Nwk_ManCleanMarks( Nwk_Man_t * pNtk );
+extern ABC_DLL void            Nwk_ManMinimumBase( Nwk_Man_t * pNtk, int fVerbose );
+extern ABC_DLL void            Nwk_ManRemoveDupFanins( Nwk_Man_t * pNtk, int fVerbose );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/nwk/nwkAig.c b/abc-build/src/opt/nwk/nwkAig.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwkAig.c
@@ -0,0 +1,299 @@
+/**CFile****************************************************************
+
+  FileName    [nwkAig.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Netlist representation.]
+
+  Synopsis    [Translating of AIG into the network.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwkAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nwk.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Converts AIG into the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Nwk_Man_t * Nwk_ManDeriveFromAig( Aig_Man_t * p )
+{
+    Nwk_Man_t * pNtk;
+    Aig_Obj_t * pObj;
+    int i;
+    pNtk = Nwk_ManAlloc();
+    pNtk->nFanioPlus = 0;
+    Hop_ManStop( pNtk->pManHop );
+    pNtk->pManHop = NULL;
+    pNtk->pName = Abc_UtilStrsav( p->pName );
+    pNtk->pSpec = Abc_UtilStrsav( p->pSpec );
+    pObj = Aig_ManConst1(p);
+    pObj->pData = Nwk_ManCreateNode( pNtk, 0, pObj->nRefs );
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->pData = Nwk_ManCreateCi( pNtk, pObj->nRefs );
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        pObj->pData = Nwk_ManCreateNode( pNtk, 2, pObj->nRefs );
+        Nwk_ObjAddFanin( (Nwk_Obj_t *)pObj->pData, (Nwk_Obj_t *)Aig_ObjFanin0(pObj)->pData );
+        Nwk_ObjAddFanin( (Nwk_Obj_t *)pObj->pData, (Nwk_Obj_t *)Aig_ObjFanin1(pObj)->pData );
+    }
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        pObj->pData = Nwk_ManCreateCo( pNtk );
+        Nwk_ObjAddFanin( (Nwk_Obj_t *)pObj->pData, (Nwk_Obj_t *)Aig_ObjFanin0(pObj)->pData );
+    }
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts AIG into the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Nwk_ManDeriveRetimingCut( Aig_Man_t * p, int fForward, int fVerbose )
+{ 
+    Vec_Ptr_t * vNodes;
+    Nwk_Man_t * pNtk;
+    Nwk_Obj_t * pNode;
+    Aig_Obj_t * pObj;
+    int i;
+    pNtk = Nwk_ManDeriveFromAig( p );
+    if ( fForward )
+        vNodes = Nwk_ManRetimeCutForward( pNtk, Aig_ManRegNum(p), fVerbose );
+    else
+        vNodes = Nwk_ManRetimeCutBackward( pNtk, Aig_ManRegNum(p), fVerbose );
+    Aig_ManForEachObj( p, pObj, i )
+        ((Nwk_Obj_t *)pObj->pData)->pCopy = pObj;
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pNode, i )
+        Vec_PtrWriteEntry( vNodes, i, pNode->pCopy );
+    Nwk_ManFree( pNtk );
+//    assert( Vec_PtrSize(vNodes) <= Aig_ManRegNum(p) );
+    return vNodes;
+}
+
+
+ABC_NAMESPACE_IMPL_END
+
+#include "proof/abs/abs.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/**Function*************************************************************
+
+  Synopsis    [Collects reachable nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManColleacReached_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes, Vec_Int_t * vLeaves )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+    {
+        Vec_IntPush( vLeaves, Gia_ObjId(p, pObj) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Nwk_ManColleacReached_rec( p, Gia_ObjFanin0(pObj), vNodes, vLeaves );
+    Nwk_ManColleacReached_rec( p, Gia_ObjFanin1(pObj), vNodes, vLeaves );
+    Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Converts AIG into the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Nwk_Man_t * Nwk_ManCreateFromGia( Gia_Man_t * p, Vec_Int_t * vPPis, Vec_Int_t * vNodes, Vec_Int_t * vLeaves, Vec_Int_t ** pvMapInv )
+{
+    Nwk_Man_t * pNtk;
+    Nwk_Obj_t ** ppCopies;
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vMaps;
+    int i;
+//    assert( Vec_IntSize(vLeaves) >= Vec_IntSize(vPPis) );
+    Gia_ManCreateRefs( p );
+    pNtk = Nwk_ManAlloc();
+    pNtk->pName = Abc_UtilStrsav( p->pName );
+    pNtk->nFanioPlus = 0;
+    Hop_ManStop( pNtk->pManHop );
+    pNtk->pManHop = NULL;
+    // allocate
+    vMaps = Vec_IntAlloc( Vec_IntSize(vNodes) + Abc_MaxInt(Vec_IntSize(vPPis), Vec_IntSize(vLeaves)) + 1 );
+    ppCopies = ABC_ALLOC( Nwk_Obj_t *, Gia_ManObjNum(p) );
+    // copy objects
+    pObj = Gia_ManConst0(p);
+//    ppCopies[Gia_ObjId(p,pObj)] = Nwk_ManCreateNode( pNtk, 0, Gia_ObjRefNum(p,pObj) );
+    ppCopies[Gia_ObjId(p,pObj)] = Nwk_ManCreateNode( pNtk, 0, Gia_ObjRefNum(p,pObj) + (Vec_IntSize(vLeaves) > Vec_IntSize(vPPis) ? Vec_IntSize(vLeaves) - Vec_IntSize(vPPis) : 0) );
+    Vec_IntPush( vMaps, Gia_ObjId(p,pObj) );
+    Gia_ManForEachObjVec( vLeaves, p, pObj, i )
+    {
+        ppCopies[Gia_ObjId(p,pObj)] = Nwk_ManCreateCi( pNtk, Gia_ObjRefNum(p,pObj) );
+        assert( Vec_IntSize(vMaps) == Nwk_ObjId(ppCopies[Gia_ObjId(p,pObj)]) );
+        Vec_IntPush( vMaps, Gia_ObjId(p,pObj) );
+    }
+    for ( i = Vec_IntSize(vLeaves); i < Vec_IntSize(vPPis); i++ )
+    {
+        Nwk_ManCreateCi( pNtk, 0 );
+        Vec_IntPush( vMaps, -1 );
+    }
+    Gia_ManForEachObjVec( vNodes, p, pObj, i )
+    {
+        ppCopies[Gia_ObjId(p,pObj)] = Nwk_ManCreateNode( pNtk, 2, Gia_ObjRefNum(p,pObj) );
+        Nwk_ObjAddFanin( ppCopies[Gia_ObjId(p,pObj)], ppCopies[Gia_ObjFaninId0p(p,pObj)] );
+        Nwk_ObjAddFanin( ppCopies[Gia_ObjId(p,pObj)], ppCopies[Gia_ObjFaninId1p(p,pObj)] );
+        assert( Vec_IntSize(vMaps) == Nwk_ObjId(ppCopies[Gia_ObjId(p,pObj)]) );
+        Vec_IntPush( vMaps, Gia_ObjId(p,pObj) );
+    }
+    Gia_ManForEachObjVec( vPPis, p, pObj, i )
+    {
+        assert( ppCopies[Gia_ObjId(p,pObj)] != NULL );
+        Nwk_ObjAddFanin( Nwk_ManCreateCo(pNtk), ppCopies[Gia_ObjId(p,pObj)] );
+    }
+    for ( i = Vec_IntSize(vPPis); i < Vec_IntSize(vLeaves); i++ )
+        Nwk_ObjAddFanin( Nwk_ManCreateCo(pNtk), ppCopies[0] );
+    assert( Vec_IntSize(vMaps) == Vec_IntSize(vNodes) + Abc_MaxInt(Vec_IntSize(vPPis), Vec_IntSize(vLeaves)) + 1 );
+    ABC_FREE( ppCopies );
+    *pvMapInv = vMaps;
+    return pNtk;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns min-cut in the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManDeriveMinCut( Gia_Man_t * p, int fVerbose )
+{
+    Nwk_Man_t * pNtk;
+    Nwk_Obj_t * pNode;
+    Vec_Ptr_t * vMinCut;
+    Vec_Int_t * vPPis, * vNodes, * vLeaves, * vNodes2, * vLeaves2, * vMapInv;
+    Vec_Int_t * vCommon, * vDiff0, * vDiff1;
+    Gia_Obj_t * pObj;
+    int i, iObjId;
+    // get inputs
+    Gia_ManGlaCollect( p, p->vGateClasses, NULL, &vPPis, NULL, NULL );
+    // collect nodes rechable from PPIs
+    vNodes = Vec_IntAlloc( 100 );
+    vLeaves = Vec_IntAlloc( 100 );
+    Gia_ManIncrementTravId( p );
+    Gia_ManForEachObjVec( vPPis, p, pObj, i )
+        Nwk_ManColleacReached_rec( p, pObj, vNodes, vLeaves );
+    // derive the new network
+    pNtk = Nwk_ManCreateFromGia( p, vPPis, vNodes, vLeaves, &vMapInv );
+    assert( Nwk_ManPiNum(pNtk) == Nwk_ManPoNum(pNtk) );
+    // create min-cut
+    vMinCut = Nwk_ManRetimeCutBackward( pNtk, Nwk_ManPiNum(pNtk), fVerbose );
+    // copy from the GIA back
+//    Aig_ManForEachObj( p, pObj, i )
+//        ((Nwk_Obj_t *)pObj->pData)->pCopy = pObj;
+    // mark min-cut nodes
+    vNodes2 = Vec_IntAlloc( 100 );
+    vLeaves2 = Vec_IntAlloc( 100 );
+    Gia_ManIncrementTravId( p );
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vMinCut, pNode, i )
+    {
+        pObj = Gia_ManObj( p, Vec_IntEntry(vMapInv, Nwk_ObjId(pNode)) );
+        if ( Gia_ObjIsConst0(pObj) )
+            continue;
+        Nwk_ManColleacReached_rec( p, pObj, vNodes2, vLeaves2 );
+    }
+    if ( fVerbose )
+        printf( "Min-cut: %d -> %d.  Nodes %d -> %d.  ", Vec_IntSize(vPPis)+1, Vec_PtrSize(vMinCut), Vec_IntSize(vNodes), Vec_IntSize(vNodes2) );
+    Vec_IntFree( vPPis );
+    Vec_PtrFree( vMinCut );
+    Vec_IntFree( vMapInv );
+    Nwk_ManFree( pNtk );
+
+    // sort the results
+    Vec_IntSort( vNodes, 0 );
+    Vec_IntSort( vNodes2, 0 );
+    vCommon = Vec_IntAlloc( Vec_IntSize(vNodes) );
+    vDiff0 = Vec_IntAlloc( 100 );
+    vDiff1 = Vec_IntAlloc( 100 );
+    Vec_IntTwoSplit( vNodes, vNodes2, vCommon, vDiff0, vDiff1 );
+    if ( fVerbose )
+        printf( "Common = %d.  Diff0 = %d. Diff1 = %d.\n", Vec_IntSize(vCommon), Vec_IntSize(vDiff0), Vec_IntSize(vDiff1) );
+
+    // fill in
+    Vec_IntForEachEntry( vDiff0, iObjId, i )
+        Vec_IntWriteEntry( p->vGateClasses, iObjId, 1 );
+
+    Vec_IntFree( vLeaves );
+    Vec_IntFree( vNodes );
+    Vec_IntFree( vLeaves2 );
+    Vec_IntFree( vNodes2 );
+
+    Vec_IntFree( vCommon );
+    Vec_IntFree( vDiff0 );
+    Vec_IntFree( vDiff1 );
+
+    // check abstraction
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Vec_IntEntry( p->vGateClasses, i ) == 0 )
+            continue;
+        assert( Gia_ObjIsConst0(pObj) || Gia_ObjIsRo(p, pObj) || Gia_ObjIsAnd(pObj) );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/nwk/nwkBidec.c b/abc-build/src/opt/nwk/nwkBidec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwkBidec.c
@@ -0,0 +1,177 @@
+/**CFile****************************************************************
+
+  FileName    [nwkBidec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Logic network representation.]
+
+  Synopsis    [Bi-decomposition of local functions.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwkBidec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nwk.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int  Extra_TruthWordNum( int nVars )  { return nVars <= 5 ? 1 : (1 << (nVars - 5)); }
+static inline void Extra_TruthNot( unsigned * pOut, unsigned * pIn, int nVars )
+{
+    int w;
+    for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = ~pIn[w];
+}
+static inline void Extra_TruthOr( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+    int w;
+    for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = pIn0[w] | pIn1[w];
+}
+static inline void Extra_TruthSharp( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+    int w;
+    for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+        pOut[w] = pIn0[w] & ~pIn1[w];
+}
+
+static inline Hop_Obj_t * Bdc_FunCopyHop( Bdc_Fun_t * pObj )  { return Hop_NotCond( (Hop_Obj_t *)Bdc_FuncCopy(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) );  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Resynthesizes nodes using bi-decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb )
+{
+    unsigned * pTruth;
+    Bdc_Fun_t * pFunc;
+    int nNodes, i;
+    assert( nVars <= 16 );
+    // derive truth table
+    pTruth = Hop_ManConvertAigToTruth( pHop, Hop_Regular(pRoot), nVars, vTruth, 0 );
+    if ( Hop_IsComplement(pRoot) )
+        for ( i = Abc_TruthWordNum(nVars)-1; i >= 0; i-- )
+            pTruth[i] = ~pTruth[i];
+    // perform power-aware decomposition
+    if ( dProb >= 0.0 )
+    {
+        float Prob = (float)2.0 * dProb * (1.0 - dProb);
+        assert( Prob >= 0.0 && Prob <= 0.5 );
+        if ( Prob >= 0.4 )
+        {
+            Extra_TruthNot( puCare, puCare, nVars );
+            if ( dProb > 0.5 ) // more 1s than 0s
+                Extra_TruthOr( pTruth, pTruth, puCare, nVars );
+            else
+                Extra_TruthSharp( pTruth, pTruth, puCare, nVars );
+            Extra_TruthNot( puCare, puCare, nVars );
+            // decompose truth table
+            Bdc_ManDecompose( p, pTruth, NULL, nVars, NULL, 1000 );
+        }
+        else
+        {
+            // decompose truth table
+            Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 );
+        }
+    }
+    else
+    {
+        // decompose truth table
+        Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 );
+    }
+    // convert back into HOP
+    Bdc_FuncSetCopy( Bdc_ManFunc( p, 0 ), Hop_ManConst1( pHop ) );
+    for ( i = 0; i < nVars; i++ )
+        Bdc_FuncSetCopy( Bdc_ManFunc( p, i+1 ), Hop_ManPi( pHop, i ) );
+    nNodes = Bdc_ManNodeNum(p);
+    for ( i = nVars + 1; i < nNodes; i++ )
+    {
+        pFunc = Bdc_ManFunc( p, i );
+        Bdc_FuncSetCopy( pFunc, Hop_And( pHop, Bdc_FunCopyHop(Bdc_FuncFanin0(pFunc)), Bdc_FunCopyHop(Bdc_FuncFanin1(pFunc)) ) );
+    }
+    return Bdc_FunCopyHop( Bdc_ManRoot(p) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resynthesizes nodes using bi-decomposition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManBidecResyn( Nwk_Man_t * pNtk, int fVerbose )
+{
+    Bdc_Par_t Pars = {0}, * pPars = &Pars;
+    Bdc_Man_t * p;
+    Nwk_Obj_t * pObj;
+    Vec_Int_t * vTruth;
+    int i, nGainTotal = 0, nNodes1, nNodes2;
+    abctime clk = Abc_Clock();
+    pPars->nVarsMax = Nwk_ManGetFaninMax( pNtk );
+    pPars->fVerbose = fVerbose;
+    if ( pPars->nVarsMax < 2 )
+    {
+        printf( "Resynthesis is not performed for networks whose nodes are less than 2 inputs.\n" );
+        return;
+    }
+    if ( pPars->nVarsMax > 15 )
+    {
+        if ( fVerbose )
+        printf( "Resynthesis is not performed for nodes with more than 15 inputs.\n" );
+        pPars->nVarsMax = 15;
+    }
+    vTruth = Vec_IntAlloc( 0 );
+    p = Bdc_ManAlloc( pPars );
+    Nwk_ManForEachNode( pNtk, pObj, i )
+    {
+        if ( Nwk_ObjFaninNum(pObj) > 15 )
+            continue;
+        nNodes1 = Hop_DagSize(pObj->pFunc);
+        pObj->pFunc = Nwk_NodeIfNodeResyn( p, pNtk->pManHop, pObj->pFunc, Nwk_ObjFaninNum(pObj), vTruth, NULL, -1.0 );
+        nNodes2 = Hop_DagSize(pObj->pFunc);
+        nGainTotal += nNodes1 - nNodes2;
+    }
+    Bdc_ManFree( p );
+    Vec_IntFree( vTruth );
+    if ( fVerbose )
+    {
+    printf( "Total gain in AIG nodes = %d.  ", nGainTotal );
+    ABC_PRT( "Total runtime", Abc_Clock() - clk );
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/nwk/nwkCheck.c b/abc-build/src/opt/nwk/nwkCheck.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwkCheck.c
@@ -0,0 +1,76 @@
+/**CFile****************************************************************
+
+  FileName    [nwkCheck.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Logic network representation.]
+
+  Synopsis    [Consistency checking procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwkCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nwk.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Checking the logic network for consistency.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManCheck( Nwk_Man_t * p )
+{
+    Nwk_Obj_t * pObj, * pNext;
+    int i, k, m;
+    // check if the nodes have duplicated fanins
+    Nwk_ManForEachNode( p, pObj, i )
+    {
+        for ( k = 0; k < pObj->nFanins; k++ )
+            for ( m = k + 1; m < pObj->nFanins; m++ )
+                if ( pObj->pFanio[k] == pObj->pFanio[m] )
+                    printf( "Node %d has duplicated fanin %d.\n", pObj->Id, pObj->pFanio[k]->Id );
+    }
+    // check if all nodes are in the correct fanin/fanout relationship
+    Nwk_ManForEachObj( p, pObj, i )
+    {
+        Nwk_ObjForEachFanin( pObj, pNext, k )
+            if ( Nwk_ObjFanoutNum(pNext) < 100 && Nwk_ObjFindFanout( pNext, pObj ) == -1 )
+                printf( "Nwk_ManCheck(): Object %d has fanin %d which does not have a corresponding fanout.\n", pObj->Id, pNext->Id );
+        Nwk_ObjForEachFanout( pObj, pNext, k )
+            if ( Nwk_ObjFindFanin( pNext, pObj ) == -1 )
+                printf( "Nwk_ManCheck(): Object %d has fanout %d which does not have a corresponding fanin.\n", pObj->Id, pNext->Id );
+    }
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/nwk/nwkDfs.c b/abc-build/src/opt/nwk/nwkDfs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwkDfs.c
@@ -0,0 +1,664 @@
+/**CFile****************************************************************
+
+  FileName    [nwkDfs.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Logic network representation.]
+
+  Synopsis    [DFS traversals.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwkDfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nwk.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies that the objects are in a topo order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManVerifyTopoOrder( Nwk_Man_t * pNtk )
+{
+    Nwk_Obj_t * pObj, * pNext;
+    int i, k, iBox, iTerm1, nTerms;
+    Nwk_ManIncrementTravId( pNtk );
+    Nwk_ManForEachObj( pNtk, pObj, i )
+    {
+        if ( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCo(pObj) )
+        {
+            Nwk_ObjForEachFanin( pObj, pNext, k )
+            {
+                if ( !Nwk_ObjIsTravIdCurrent(pNext) )
+                {
+                    printf( "Node %d has fanin %d that is not in a topological order.\n", pObj->Id, pNext->Id );
+                    return 0;
+                }
+            }
+        }
+        else if ( Nwk_ObjIsCi(pObj) )
+        {
+            if ( pNtk->pManTime )
+            {
+                iBox = Tim_ManBoxForCi( pNtk->pManTime, pObj->PioId );
+                if ( iBox >= 0 ) // this is not a true PI
+                {
+                    iTerm1 = Tim_ManBoxInputFirst( pNtk->pManTime, iBox );
+                    nTerms = Tim_ManBoxInputNum( pNtk->pManTime, iBox );
+                    for ( k = 0; k < nTerms; k++ )
+                    {
+                        pNext = Nwk_ManCo( pNtk, iTerm1 + k );
+                        if ( !Nwk_ObjIsTravIdCurrent(pNext) )
+                        {
+                            printf( "Box %d has input %d that is not in a topological order.\n", iBox, pNext->Id );
+                            return 0;
+                        }
+                    }
+                }
+            }
+        }
+        else
+            assert( 0 );
+        Nwk_ObjSetTravIdCurrent( pObj );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the number of logic levels not counting PIs/POs.]
+
+  Description [Assumes that white boxes have unit level.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManLevelBackup( Nwk_Man_t * pNtk )
+{
+    Tim_Man_t * pManTimeUnit;
+    Nwk_Obj_t * pObj, * pFanin;
+    int i, k, LevelMax, Level;
+    assert( Nwk_ManVerifyTopoOrder(pNtk) );
+    // clean the levels
+    Nwk_ManForEachObj( pNtk, pObj, i )
+        Nwk_ObjSetLevel( pObj, 0 );
+    // perform level computation
+    LevelMax = 0;
+    pManTimeUnit = pNtk->pManTime ? Tim_ManDup( pNtk->pManTime, 1 ) : NULL;
+    if ( pManTimeUnit )
+        Tim_ManIncrementTravId( pManTimeUnit );
+    Nwk_ManForEachObj( pNtk, pObj, i )
+    {
+        if ( Nwk_ObjIsCi(pObj) )
+        {
+            Level = pManTimeUnit? (int)Tim_ManGetCiArrival( pManTimeUnit, pObj->PioId ) : 0;
+            Nwk_ObjSetLevel( pObj, Level );
+        }
+        else if ( Nwk_ObjIsCo(pObj) )
+        {
+            Level = Nwk_ObjLevel( Nwk_ObjFanin0(pObj) );
+            if ( pManTimeUnit )
+                Tim_ManSetCoArrival( pManTimeUnit, pObj->PioId, (float)Level );
+            Nwk_ObjSetLevel( pObj, Level );
+            if ( LevelMax < Nwk_ObjLevel(pObj) )
+                LevelMax = Nwk_ObjLevel(pObj);
+        }
+        else if ( Nwk_ObjIsNode(pObj) )
+        {
+            Level = 0;
+            Nwk_ObjForEachFanin( pObj, pFanin, k )
+                if ( Level < Nwk_ObjLevel(pFanin) )
+                    Level = Nwk_ObjLevel(pFanin);
+            Nwk_ObjSetLevel( pObj, Level + 1 );
+        }
+        else
+            assert( 0 );
+    }
+    // set the old timing manager
+    if ( pManTimeUnit )
+        Tim_ManStop( pManTimeUnit );
+    return LevelMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the number of logic levels not counting PIs/POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManLevel_rec( Nwk_Obj_t * pObj )
+{
+    Tim_Man_t * pManTime = pObj->pMan->pManTime;
+    Nwk_Obj_t * pNext;
+    int i, iBox, iTerm1, nTerms, LevelMax = 0;
+    if ( Nwk_ObjIsTravIdCurrent( pObj ) )
+        return;
+    Nwk_ObjSetTravIdCurrent( pObj );
+    if ( Nwk_ObjIsCi(pObj) )
+    {
+        if ( pManTime ) 
+        {
+            iBox = Tim_ManBoxForCi( pManTime, pObj->PioId );
+            if ( iBox >= 0 ) // this is not a true PI
+            {
+                iTerm1 = Tim_ManBoxInputFirst( pManTime, iBox );
+                nTerms = Tim_ManBoxInputNum( pManTime, iBox );
+                for ( i = 0; i < nTerms; i++ )
+                {
+                    pNext = Nwk_ManCo(pObj->pMan, iTerm1 + i);
+                    Nwk_ManLevel_rec( pNext );
+                    if ( LevelMax < Nwk_ObjLevel(pNext) )
+                        LevelMax = Nwk_ObjLevel(pNext);
+                }
+                LevelMax++;
+            }
+        }
+    }
+    else if ( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCo(pObj) )
+    {
+        Nwk_ObjForEachFanin( pObj, pNext, i )
+        {
+            Nwk_ManLevel_rec( pNext );
+            if ( LevelMax < Nwk_ObjLevel(pNext) )
+                LevelMax = Nwk_ObjLevel(pNext);
+        }
+        if ( Nwk_ObjIsNode(pObj) && Nwk_ObjFaninNum(pObj) > 0 )
+            LevelMax++;
+    }
+    else
+        assert( 0 );
+    Nwk_ObjSetLevel( pObj, LevelMax );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the number of logic levels not counting PIs/POs.]
+
+  Description [Does not assume that the objects are in a topo order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManLevel( Nwk_Man_t * pNtk )
+{
+    Nwk_Obj_t * pObj;
+    int i, LevelMax = 0;
+    Nwk_ManForEachObj( pNtk, pObj, i )
+        Nwk_ObjSetLevel( pObj, 0 );
+    Nwk_ManIncrementTravId( pNtk );
+    Nwk_ManForEachPo( pNtk, pObj, i )
+    {
+        Nwk_ManLevel_rec( pObj );
+        if ( LevelMax < Nwk_ObjLevel(pObj) )
+            LevelMax = Nwk_ObjLevel(pObj);
+    }
+    Nwk_ManForEachCi( pNtk, pObj, i )
+    {
+        Nwk_ManLevel_rec( pObj );
+        if ( LevelMax < Nwk_ObjLevel(pObj) )
+            LevelMax = Nwk_ObjLevel(pObj);
+    }
+    return LevelMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the number of logic levels not counting PIs/POs.]
+
+  Description [Does not assume that the objects are in a topo order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManLevelMax( Nwk_Man_t * pNtk )
+{
+    Nwk_Obj_t * pObj;
+    int i, LevelMax = 0;
+    Nwk_ManForEachPo( pNtk, pObj, i )
+        if ( LevelMax < Nwk_ObjLevel(pObj) )
+            LevelMax = Nwk_ObjLevel(pObj);
+    return LevelMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of objects in the AIG manager ordered by level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Nwk_ManLevelize( Nwk_Man_t * pNtk )
+{
+    Nwk_Obj_t * pObj;
+    Vec_Vec_t * vLevels;
+    int nLevels, i;
+    assert( Nwk_ManVerifyLevel(pNtk) );
+    nLevels = Nwk_ManLevelMax( pNtk );
+    vLevels = Vec_VecStart( nLevels + 1 );
+    Nwk_ManForEachNode( pNtk, pObj, i )
+    {
+        assert( Nwk_ObjLevel(pObj) <= nLevels );
+        Vec_VecPush( vLevels, Nwk_ObjLevel(pObj), pObj );
+    }
+    return vLevels;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DFS for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManDfs_rec( Nwk_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( Nwk_ObjIsTravIdCurrent( pObj ) )
+        return;
+    Nwk_ObjSetTravIdCurrent( pObj );
+    Nwk_ObjForEachFanin( pObj, pNext, i )
+        Nwk_ManDfs_rec( pNext, vNodes );
+    Vec_PtrPush( vNodes, pObj );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Returns the DFS ordered array of all objects except latches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Nwk_ManDfs( Nwk_Man_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Nwk_Obj_t * pObj;
+    int i;
+    Nwk_ManIncrementTravId( pNtk );
+    vNodes = Vec_PtrAlloc( 100 );
+    Nwk_ManForEachObj( pNtk, pObj, i )
+    {
+        if ( Nwk_ObjIsCi(pObj) )
+        {
+            Nwk_ObjSetTravIdCurrent( pObj );
+            Vec_PtrPush( vNodes, pObj );
+        }
+        else if ( Nwk_ObjIsCo(pObj) )
+            Nwk_ManDfs_rec( pObj, vNodes );
+    }
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DFS for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManDfsNodes_rec( Nwk_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( Nwk_ObjIsTravIdCurrent( pObj ) )
+        return;
+    Nwk_ObjSetTravIdCurrent( pObj );
+    if ( Nwk_ObjIsCi(pObj) )
+        return;
+    assert( Nwk_ObjIsNode(pObj) );
+    Nwk_ObjForEachFanin( pObj, pNext, i )
+        Nwk_ManDfsNodes_rec( pNext, vNodes );
+    Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the set of internal nodes rooted in the given nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Nwk_ManDfsNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes )
+{
+    Vec_Ptr_t * vNodes;
+    int i;
+    // set the traversal ID
+    Nwk_ManIncrementTravId( pNtk );
+    // start the array of nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    // go through the PO nodes and call for each of them
+    for ( i = 0; i < nNodes; i++ )
+        if ( Nwk_ObjIsCo(ppNodes[i]) )
+            Nwk_ManDfsNodes_rec( Nwk_ObjFanin0(ppNodes[i]), vNodes );
+        else
+            Nwk_ManDfsNodes_rec( ppNodes[i], vNodes );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DFS for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManDfsReverse_rec( Nwk_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    Nwk_Obj_t * pNext;
+    int i, iBox, iTerm1, nTerms;
+    if ( Nwk_ObjIsTravIdCurrent( pObj ) )
+        return;
+    Nwk_ObjSetTravIdCurrent( pObj );
+    if ( Nwk_ObjIsCo(pObj) )
+    {
+        if ( pObj->pMan->pManTime )
+        {
+            iBox = Tim_ManBoxForCo( pObj->pMan->pManTime, pObj->PioId );
+            if ( iBox >= 0 ) // this is not a true PO
+            {
+                iTerm1 = Tim_ManBoxOutputFirst( pObj->pMan->pManTime, iBox );
+                nTerms = Tim_ManBoxOutputNum( pObj->pMan->pManTime, iBox );
+                for ( i = 0; i < nTerms; i++ )
+                {
+                    pNext = Nwk_ManCi(pObj->pMan, iTerm1 + i);
+                    Nwk_ManDfsReverse_rec( pNext, vNodes );
+                }
+            }
+        }
+    }
+    else if ( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCi(pObj) )
+    {
+        Nwk_ObjForEachFanout( pObj, pNext, i )
+            Nwk_ManDfsReverse_rec( pNext, vNodes );
+    }
+    else
+        assert( 0 );
+    Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the DFS ordered array of all objects except latches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Nwk_ManDfsReverse( Nwk_Man_t * pNtk )
+{
+    Vec_Ptr_t * vNodes;
+    Nwk_Obj_t * pObj;
+    int i;
+    Nwk_ManIncrementTravId( pNtk );
+    vNodes = Vec_PtrAlloc( 100 );
+    Nwk_ManForEachPi( pNtk, pObj, i )
+        Nwk_ManDfsReverse_rec( pObj, vNodes );
+    // add nodes without fanins
+    Nwk_ManForEachNode( pNtk, pObj, i )
+        if ( Nwk_ObjFaninNum(pObj) == 0 && !Nwk_ObjIsTravIdCurrent(pObj) )
+            Vec_PtrPush( vNodes, pObj );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs DFS for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManSupportNodes_rec( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    Nwk_Obj_t * pFanin;
+    int i;
+    // if this node is already visited, skip
+    if ( Nwk_ObjIsTravIdCurrent( pNode ) )
+        return;
+    // mark the node as visited
+    Nwk_ObjSetTravIdCurrent( pNode );
+    // collect the CI
+    if ( Nwk_ObjIsCi(pNode) )
+    {
+        Vec_PtrPush( vNodes, pNode );
+        return;
+    }
+    assert( Nwk_ObjIsNode( pNode ) );
+    // visit the transitive fanin of the node
+    Nwk_ObjForEachFanin( pNode, pFanin, i )
+        Nwk_ManSupportNodes_rec( pFanin, vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the set of CI nodes in the support of the given nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Nwk_ManSupportNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes )
+{
+    Vec_Ptr_t * vNodes;
+    int i;
+    // set the traversal ID
+    Nwk_ManIncrementTravId( pNtk );
+    // start the array of nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    // go through the PO nodes and call for each of them
+    for ( i = 0; i < nNodes; i++ )
+        if ( Nwk_ObjIsCo(ppNodes[i]) )
+            Nwk_ManSupportNodes_rec( Nwk_ObjFanin0(ppNodes[i]), vNodes );
+        else
+            Nwk_ManSupportNodes_rec( ppNodes[i], vNodes );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the sum total of supports of all outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManSupportSum( Nwk_Man_t * pNtk )
+{
+    Vec_Ptr_t * vSupp;
+    Nwk_Obj_t * pObj;
+    int i, nTotalSupps = 0;
+    Nwk_ManForEachCo( pNtk, pObj, i )
+    {
+        vSupp = Nwk_ManSupportNodes( pNtk, &pObj, 1 );
+        nTotalSupps += Vec_PtrSize( vSupp );
+        Vec_PtrFree( vSupp );
+    }
+    printf( "Total supports = %d.\n", nTotalSupps );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences the node's MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ObjDeref_rec( Nwk_Obj_t * pNode )
+{
+    Nwk_Obj_t * pFanin;
+    int i, Counter = 1;
+    if ( Nwk_ObjIsCi(pNode) )
+        return 0;
+    Nwk_ObjForEachFanin( pNode, pFanin, i )
+    {
+        assert( pFanin->nFanouts > 0 );
+        if ( --pFanin->nFanouts == 0 )
+            Counter += Nwk_ObjDeref_rec( pFanin );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [References the node's MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ObjRef_rec( Nwk_Obj_t * pNode )
+{
+    Nwk_Obj_t * pFanin;
+    int i, Counter = 1;
+    if ( Nwk_ObjIsCi(pNode) )
+        return 0;
+    Nwk_ObjForEachFanin( pNode, pFanin, i )
+    {
+        if ( pFanin->nFanouts++ == 0 )
+            Counter += Nwk_ObjRef_rec( pFanin );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the internal and boundary nodes in the derefed MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ObjMffcLabel_rec( Nwk_Obj_t * pNode, int fTopmost )
+{
+    Nwk_Obj_t * pFanin;
+    int i;
+    // add to the new support nodes
+    if ( !fTopmost && (Nwk_ObjIsCi(pNode) || pNode->nFanouts > 0) )
+        return;
+    // skip visited nodes
+    if ( Nwk_ObjIsTravIdCurrent(pNode) )
+        return;
+    Nwk_ObjSetTravIdCurrent(pNode);
+    // recur on the children
+    Nwk_ObjForEachFanin( pNode, pFanin, i )
+        Nwk_ObjMffcLabel_rec( pFanin, 0 );
+    // collect the internal node
+//    printf( "%d ", pNode->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the internal nodes of the MFFC limited by cut.]
+
+  Description []
+               
+  SideEffects [Increments the trav ID and marks visited nodes.]
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ObjMffcLabel( Nwk_Obj_t * pNode )
+{
+    int Count1, Count2;
+    // dereference the node
+    Count1 = Nwk_ObjDeref_rec( pNode );
+    // collect the nodes inside the MFFC
+    Nwk_ManIncrementTravId( pNode->pMan );
+    Nwk_ObjMffcLabel_rec( pNode, 1 );
+    // reference it back
+    Count2 = Nwk_ObjRef_rec( pNode );
+    assert( Count1 == Count2 );
+    return Count1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/nwk/nwkFanio.c b/abc-build/src/opt/nwk/nwkFanio.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwkFanio.c
@@ -0,0 +1,320 @@
+/**CFile****************************************************************
+
+  FileName    [nwkFanio.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Logic network representation.]
+
+  Synopsis    [Manipulation of fanins/fanouts.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwkFanio.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nwk.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Collects fanins of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ObjCollectFanins( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    Nwk_Obj_t * pFanin;
+    int i;
+    Vec_PtrClear(vNodes);
+    Nwk_ObjForEachFanin( pNode, pFanin, i )
+        Vec_PtrPush( vNodes, pFanin );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects fanouts of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ObjCollectFanouts( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    Nwk_Obj_t * pFanout;
+    int i;
+    Vec_PtrClear(vNodes);
+    Nwk_ObjForEachFanout( pNode, pFanout, i )
+        Vec_PtrPush( vNodes, pFanout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of the fanin of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ObjFindFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin )
+{  
+    Nwk_Obj_t * pTemp;
+    int i;
+    Nwk_ObjForEachFanin( pObj, pTemp, i )
+        if ( pTemp == pFanin )
+            return i;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of the fanout of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ObjFindFanout( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanout )
+{  
+    Nwk_Obj_t * pTemp;
+    int i;
+    Nwk_ObjForEachFanout( pObj, pTemp, i )
+        if ( pTemp == pFanout )
+            return i;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node has to be reallocated.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Nwk_ObjReallocIsNeeded( Nwk_Obj_t * pObj )
+{  
+    return pObj->nFanins + pObj->nFanouts == pObj->nFanioAlloc;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Reallocates the object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Nwk_Obj_t * Nwk_ManReallocNode( Nwk_Obj_t * pObj )
+{  
+    Nwk_Obj_t ** pFanioOld = pObj->pFanio;
+    assert( Nwk_ObjReallocIsNeeded(pObj) );
+    pObj->pFanio = (Nwk_Obj_t **)Aig_MmFlexEntryFetch( pObj->pMan->pMemObjs, 2 * pObj->nFanioAlloc * sizeof(Nwk_Obj_t *) );
+    memmove( pObj->pFanio, pFanioOld, pObj->nFanioAlloc * sizeof(Nwk_Obj_t *) );
+    pObj->nFanioAlloc *= 2;
+    pObj->pMan->nRealloced++;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates fanout/fanin relationship between the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ObjAddFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin )
+{
+    int i;
+    assert( pObj->pMan == pFanin->pMan );
+    assert( pObj->Id >= 0 && pFanin->Id >= 0 );
+    if ( Nwk_ObjReallocIsNeeded(pObj) )
+        Nwk_ManReallocNode( pObj );
+    if ( Nwk_ObjReallocIsNeeded(pFanin) )
+        Nwk_ManReallocNode( pFanin );
+    for ( i = pObj->nFanins + pObj->nFanouts; i > pObj->nFanins; i-- )
+        pObj->pFanio[i] = pObj->pFanio[i-1];
+    pObj->pFanio[pObj->nFanins++] = pFanin;
+    pFanin->pFanio[pFanin->nFanins + pFanin->nFanouts++] = pObj;
+    pObj->Level = Abc_MaxInt( pObj->Level, pFanin->Level + Nwk_ObjIsNode(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes fanout/fanin relationship between the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ObjDeleteFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin )
+{
+    int i, k, Limit, fFound;
+    // remove pFanin from the fanin list of pObj
+    Limit = pObj->nFanins + pObj->nFanouts;
+    fFound = 0;
+    for ( k = i = 0; i < Limit; i++ )
+        if ( fFound || pObj->pFanio[i] != pFanin )
+            pObj->pFanio[k++] = pObj->pFanio[i];
+        else
+            fFound = 1;
+    assert( i == k + 1 ); // if it fails, likely because of duplicated fanin
+    pObj->nFanins--;
+    // remove pObj from the fanout list of pFanin
+    Limit = pFanin->nFanins + pFanin->nFanouts;
+    fFound = 0;
+    for ( k = i = pFanin->nFanins; i < Limit; i++ )
+        if ( fFound || pFanin->pFanio[i] != pObj )
+            pFanin->pFanio[k++] = pFanin->pFanio[i];
+        else
+            fFound = 1;
+    assert( i == k + 1 ); // if it fails, likely because of duplicated fanout
+    pFanin->nFanouts--; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces a fanin of the node.]
+
+  Description [The node is pObj. An old fanin of this node (pFaninOld) has to be
+  replaced by a new fanin (pFaninNew). Assumes that the node and the old fanin 
+  are not complemented. The new fanin can be complemented. In this case, the
+  polarity of the new fanin will change, compared to the polarity of the old fanin.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ObjPatchFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFaninOld, Nwk_Obj_t * pFaninNew )
+{
+    int i, k, iFanin, Limit;
+    assert( pFaninOld != pFaninNew );
+    assert( pObj != pFaninOld );
+    assert( pObj != pFaninNew );
+    assert( pObj->pMan == pFaninOld->pMan );
+    assert( pObj->pMan == pFaninNew->pMan );
+    // update the fanin
+    iFanin = Nwk_ObjFindFanin( pObj, pFaninOld );
+    if ( iFanin == -1 )
+    {
+        printf( "Nwk_ObjPatchFanin(); Error! Node %d is not among", pFaninOld->Id );
+        printf( " the fanins of node %d...\n", pObj->Id );
+        return;
+    }
+    pObj->pFanio[iFanin] = pFaninNew;
+    // remove pObj from the fanout list of pFaninOld
+    Limit = pFaninOld->nFanins + pFaninOld->nFanouts;
+    for ( k = i = pFaninOld->nFanins; i < Limit; i++ )
+        if ( pFaninOld->pFanio[i] != pObj )
+            pFaninOld->pFanio[k++] = pFaninOld->pFanio[i];
+    pFaninOld->nFanouts--;
+    // add pObj to the fanout list of pFaninNew
+    if ( Nwk_ObjReallocIsNeeded(pFaninNew) )
+        Nwk_ManReallocNode( pFaninNew );
+    pFaninNew->pFanio[pFaninNew->nFanins + pFaninNew->nFanouts++] = pObj;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers fanout from the old node to the new node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ObjTransferFanout( Nwk_Obj_t * pNodeFrom, Nwk_Obj_t * pNodeTo )
+{
+    Vec_Ptr_t * vFanouts = pNodeFrom->pMan->vTemp;
+    Nwk_Obj_t * pTemp;
+    int nFanoutsOld, i;
+    assert( !Nwk_ObjIsCo(pNodeFrom) && !Nwk_ObjIsCo(pNodeTo) );
+    assert( pNodeFrom->pMan == pNodeTo->pMan );
+    assert( pNodeFrom != pNodeTo );
+    assert( Nwk_ObjFanoutNum(pNodeFrom) > 0 );
+    // get the fanouts of the old node
+    nFanoutsOld = Nwk_ObjFanoutNum(pNodeTo);
+    Nwk_ObjCollectFanouts( pNodeFrom, vFanouts );
+    // patch the fanin of each of them
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vFanouts, pTemp, i )
+        Nwk_ObjPatchFanin( pTemp, pNodeFrom, pNodeTo );
+    assert( Nwk_ObjFanoutNum(pNodeFrom) == 0 );
+    assert( Nwk_ObjFanoutNum(pNodeTo) == nFanoutsOld + Vec_PtrSize(vFanouts) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces the node by a new node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ObjReplace( Nwk_Obj_t * pNodeOld, Nwk_Obj_t * pNodeNew )
+{
+    assert( pNodeOld->pMan == pNodeNew->pMan );
+    assert( pNodeOld != pNodeNew );
+    assert( Nwk_ObjFanoutNum(pNodeOld) > 0 );
+    // transfer the fanouts to the old node
+    Nwk_ObjTransferFanout( pNodeOld, pNodeNew );
+    // remove the old node
+    Nwk_ManDeleteNode_rec( pNodeOld );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/nwk/nwkFlow.c b/abc-build/src/opt/nwk/nwkFlow.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwkFlow.c
@@ -0,0 +1,606 @@
+/**CFile****************************************************************
+
+  FileName    [nwkFlow.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Netlist representation.]
+
+  Synopsis    [Max-flow/min-cut computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwkFlow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nwk.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+    This code is based on the papers:
+    A. Hurst, A. Mishchenko, and R. Brayton, "Fast minimum-register retiming 
+    via binary maximum-flow", Proc. FMCAD '07, pp. 181-187. 
+    A. Hurst, A. Mishchenko, and R. Brayton, "Scalable min-area retiming 
+    under simultaneous delay and initial state constraints". Proc. DAC'08. 
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// predecessors
+static inline Nwk_Obj_t * Nwk_ObjPred( Nwk_Obj_t * pObj )                   { return (Nwk_Obj_t *)pObj->pCopy;        }
+static inline int         Nwk_ObjSetPred( Nwk_Obj_t * pObj, Nwk_Obj_t * p ) { pObj->pCopy = p; return 1; }
+// sink
+static inline int         Nwk_ObjIsSink( Nwk_Obj_t * pObj )                 { return pObj->MarkA;        }
+static inline void        Nwk_ObjSetSink( Nwk_Obj_t * pObj )                { pObj->MarkA = 1;           }
+// flow
+static inline int         Nwk_ObjHasFlow( Nwk_Obj_t * pObj )                { return pObj->MarkB;        }
+static inline void        Nwk_ObjSetFlow( Nwk_Obj_t * pObj )                { pObj->MarkB = 1;           }
+static inline void        Nwk_ObjClearFlow( Nwk_Obj_t * pObj )              { pObj->MarkB = 0;           }
+ 
+// representation of visited nodes
+// pObj->TravId  < pNtk->nTravIds-2   --- not visited
+// pObj->TravId == pNtk->nTravIds-2   --- visited bot only
+// pObj->TravId == pNtk->nTravIds-1   --- visited top only
+// pObj->TravId == pNtk->nTravIds     --- visited bot and top
+static inline int  Nwk_ObjVisitedBotOnly( Nwk_Obj_t * pObj )   
+{
+    return pObj->TravId == pObj->pMan->nTravIds - 2;
+}
+static inline int  Nwk_ObjVisitedBot( Nwk_Obj_t * pObj )     
+{ 
+    return pObj->TravId == pObj->pMan->nTravIds - 2 || pObj->TravId == pObj->pMan->nTravIds; 
+}
+static inline int  Nwk_ObjVisitedTop( Nwk_Obj_t * pObj )     
+{ 
+    return pObj->TravId == pObj->pMan->nTravIds - 1 || pObj->TravId == pObj->pMan->nTravIds; 
+}
+static inline void Nwk_ObjSetVisitedBot( Nwk_Obj_t * pObj )  
+{
+    if ( pObj->TravId < pObj->pMan->nTravIds - 2 )
+        pObj->TravId = pObj->pMan->nTravIds - 2;
+    else if ( pObj->TravId == pObj->pMan->nTravIds - 1 )
+        pObj->TravId = pObj->pMan->nTravIds;
+    else
+        assert( 0 );
+}
+static inline void Nwk_ObjSetVisitedTop( Nwk_Obj_t * pObj )  
+{
+    if ( pObj->TravId < pObj->pMan->nTravIds - 2 )
+        pObj->TravId = pObj->pMan->nTravIds - 1;
+    else if ( pObj->TravId == pObj->pMan->nTravIds - 2 )
+        pObj->TravId = pObj->pMan->nTravIds;
+    else
+        assert( 0 );
+}
+static inline void Nwk_ManIncrementTravIdFlow( Nwk_Man_t * pMan )
+{
+    Nwk_ManIncrementTravId( pMan );
+    Nwk_ManIncrementTravId( pMan );
+    Nwk_ManIncrementTravId( pMan );
+}
+
+static int Nwk_ManPushForwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred );
+static int Nwk_ManPushForwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred );
+
+static int Nwk_ManPushBackwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred );
+static int Nwk_ManPushBackwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Marks TFI of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManMarkTfiCone_rec( Nwk_Obj_t * pObj )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( pObj->MarkA )
+        return;
+    pObj->MarkA = 1;
+    Nwk_ObjForEachFanin( pObj, pNext, i )
+        Nwk_ManMarkTfiCone_rec( pNext );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks TFO of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManMarkTfoCone_rec( Nwk_Obj_t * pObj )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( pObj->MarkA )
+        return;
+    pObj->MarkA = 1;
+    Nwk_ObjForEachFanout( pObj, pNext, i )
+        Nwk_ManMarkTfoCone_rec( pNext );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fast forward flow pushing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManPushForwardFast_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( Nwk_ObjIsTravIdCurrent( pObj ) )
+        return 0;
+    Nwk_ObjSetTravIdCurrent( pObj );
+    if ( Nwk_ObjHasFlow(pObj) )
+        return 0;
+    if ( Nwk_ObjIsSink(pObj) )
+    {
+        Nwk_ObjSetFlow(pObj);
+        return Nwk_ObjSetPred( pObj, pPred );
+    }
+    Nwk_ObjForEachFanout( pObj, pNext, i )
+        if ( Nwk_ManPushForwardFast_rec( pNext, pObj ) )
+        {
+            Nwk_ObjSetFlow(pObj);
+            return Nwk_ObjSetPred( pObj, pPred );
+        }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fast backward flow pushing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManPushBackwardFast_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( Nwk_ObjIsTravIdCurrent( pObj ) )
+        return 0;
+    Nwk_ObjSetTravIdCurrent( pObj );
+    if ( Nwk_ObjHasFlow(pObj) )
+        return 0;
+    if ( Nwk_ObjIsSink(pObj) )
+    {
+        Nwk_ObjSetFlow(pObj);
+        return Nwk_ObjSetPred( pObj, pPred );
+    }
+    Nwk_ObjForEachFanin( pObj, pNext, i )
+        if ( Nwk_ManPushBackwardFast_rec( pNext, pObj ) )
+        {
+            Nwk_ObjSetFlow(pObj);
+            return Nwk_ObjSetPred( pObj, pPred );
+        }
+    return 0;
+}
+  
+/**Function*************************************************************
+
+  Synopsis    [Pushing the flow through the bottom part of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManPushForwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( Nwk_ObjVisitedBot(pObj) )
+        return 0;
+    Nwk_ObjSetVisitedBot(pObj);
+    // propagate through the internal edge
+    if ( Nwk_ObjHasFlow(pObj) )
+    {
+        if ( Nwk_ObjPred(pObj) )
+            if ( Nwk_ManPushForwardTop_rec( Nwk_ObjPred(pObj), Nwk_ObjPred(pObj) ) )
+                return Nwk_ObjSetPred( pObj, pPred ); 
+    }
+    else if ( Nwk_ManPushForwardTop_rec(pObj, pObj) )
+    {
+        Nwk_ObjSetFlow( pObj );
+        return Nwk_ObjSetPred( pObj, pPred );
+    }
+    // try to push through the fanins
+    Nwk_ObjForEachFanin( pObj, pNext, i )
+        if ( Nwk_ManPushForwardBot_rec( pNext, pPred ) )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Pushing the flow through the top part of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManPushForwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( Nwk_ObjVisitedTop(pObj) )
+        return 0;
+    Nwk_ObjSetVisitedTop(pObj);
+    // check if this is the sink
+    if ( Nwk_ObjIsSink(pObj) )
+        return 1;
+    // try to push through the fanouts
+    Nwk_ObjForEachFanout( pObj, pNext, i )
+        if ( Nwk_ManPushForwardBot_rec( pNext, pPred ) )
+            return 1;
+    // redirect the flow
+    if ( Nwk_ObjHasFlow(pObj) && !Nwk_ObjIsCi(pObj) )
+        if ( Nwk_ManPushForwardBot_rec( pObj, Nwk_ObjPred(pObj) ) )
+        {
+            Nwk_ObjClearFlow( pObj );
+            return Nwk_ObjSetPred( pObj, NULL );
+        }
+    return 0;
+}
+  
+/**Function*************************************************************
+
+  Synopsis    [Pushing the flow through the bottom part of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManPushBackwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred )
+{
+    if ( Nwk_ObjVisitedBot(pObj) )
+        return 0;
+    Nwk_ObjSetVisitedBot(pObj);
+    // propagate through the internal edge
+    if ( Nwk_ObjHasFlow(pObj) )
+    {
+        if ( Nwk_ObjPred(pObj) )
+            if ( Nwk_ManPushBackwardTop_rec( Nwk_ObjPred(pObj), Nwk_ObjPred(pObj) ) )
+                return Nwk_ObjSetPred( pObj, pPred ); 
+    }
+    else if ( Nwk_ManPushBackwardTop_rec(pObj, pObj) )
+    {
+        Nwk_ObjSetFlow( pObj );
+        return Nwk_ObjSetPred( pObj, pPred );
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Pushing the flow through the top part of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManPushBackwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( Nwk_ObjVisitedTop(pObj) )
+        return 0;
+    Nwk_ObjSetVisitedTop(pObj);
+    // check if this is the sink
+    if ( Nwk_ObjIsSink(pObj) )
+        return 1;
+    // try to push through the fanins
+    Nwk_ObjForEachFanin( pObj, pNext, i )
+        if ( Nwk_ManPushBackwardBot_rec( pNext, pPred ) )
+            return 1;
+    // try to push through the fanouts
+    Nwk_ObjForEachFanout( pObj, pNext, i )
+        if ( !Nwk_ObjIsCo(pObj) && Nwk_ManPushBackwardTop_rec( pNext, pPred ) )
+            return 1;
+    // redirect the flow
+    if ( Nwk_ObjHasFlow(pObj) )
+        if ( Nwk_ObjPred(pObj) && Nwk_ManPushBackwardBot_rec( pObj, Nwk_ObjPred(pObj) ) )
+        {
+            Nwk_ObjClearFlow( pObj );
+            return Nwk_ObjSetPred( pObj, NULL );
+        }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 0 if there is an unmarked path to a CI.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManVerifyCut_rec( Nwk_Obj_t * pObj )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( pObj->MarkA )
+        return 1;
+    if ( Nwk_ObjIsLo(pObj) )
+        return 0;
+    if ( Nwk_ObjIsTravIdCurrent( pObj ) )
+        return 1;
+    Nwk_ObjSetTravIdCurrent( pObj );
+    Nwk_ObjForEachFanin( pObj, pNext, i )
+        if ( !Nwk_ManVerifyCut_rec( pNext ) )
+            return 0;
+    return 1;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Verifies the forward cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManRetimeVerifyCutForward( Nwk_Man_t * pMan, Vec_Ptr_t * vNodes )
+{
+    Nwk_Obj_t * pObj;
+    int i;
+    // mark the nodes
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i )
+    {
+        assert( pObj->MarkA == 0 );
+        pObj->MarkA = 1;
+    }
+    // traverse from the COs
+    Nwk_ManIncrementTravId( pMan );
+    Nwk_ManForEachCo( pMan, pObj, i )
+        if ( !Nwk_ManVerifyCut_rec( pObj ) )
+            printf( "Nwk_ManRetimeVerifyCutForward(): Internal cut verification failed.\n" );
+    // unmark the nodes
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i )
+        pObj->MarkA = 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the forward cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManRetimeVerifyCutBackward( Nwk_Man_t * pMan, Vec_Ptr_t * vNodes )
+{
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes minimum cut for forward retiming.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Nwk_ManRetimeCutForward( Nwk_Man_t * pMan, int nLatches, int fVerbose )
+{
+    Vec_Ptr_t * vNodes;
+    Nwk_Obj_t * pObj;
+    int i, RetValue, Counter = 0, Counter2 = 0;
+    abctime clk = Abc_Clock();
+    // set the sequential parameters
+    pMan->nLatches = nLatches;
+    pMan->nTruePis = Nwk_ManCiNum(pMan) - nLatches;
+    pMan->nTruePos = Nwk_ManCoNum(pMan) - nLatches;
+    // mark the COs and the TFO of PIs
+    Nwk_ManForEachCo( pMan, pObj, i )
+        pObj->MarkA = 1;
+    Nwk_ManForEachPiSeq( pMan, pObj, i )
+        Nwk_ManMarkTfoCone_rec( pObj );
+    // start flow computation from each LO
+    Nwk_ManIncrementTravIdFlow( pMan );
+    Nwk_ManForEachLoSeq( pMan, pObj, i )
+    {
+        if ( !Nwk_ManPushForwardFast_rec( pObj, NULL ) )
+            continue;
+        Nwk_ManIncrementTravIdFlow( pMan );
+        Counter++;
+    }
+    if ( fVerbose )
+    printf( "Forward:  Max-flow = %4d -> ", Counter );
+    // continue flow computation from each LO
+    Nwk_ManIncrementTravIdFlow( pMan );
+    Nwk_ManForEachLoSeq( pMan, pObj, i )
+    {
+        if ( !Nwk_ManPushForwardBot_rec( pObj, NULL ) )
+            continue;
+        Nwk_ManIncrementTravIdFlow( pMan );
+        Counter2++;
+    }
+    if ( fVerbose )
+    printf( "%4d.  ", Counter+Counter2 );
+    // repeat flow computation from each LO
+    if ( Counter2 > 0 )
+    {
+        Nwk_ManIncrementTravIdFlow( pMan );
+        Nwk_ManForEachLoSeq( pMan, pObj, i )
+        {
+            RetValue = Nwk_ManPushForwardBot_rec( pObj, NULL );
+            assert( !RetValue );
+        }
+    }
+    // cut is a set of nodes whose bottom is visited but top is not visited
+    vNodes = Vec_PtrAlloc( Counter+Counter2 );
+    Counter = 0;
+    Nwk_ManForEachObj( pMan, pObj, i )
+    {
+        if ( Nwk_ObjVisitedBotOnly(pObj) )
+        {
+            assert( Nwk_ObjHasFlow(pObj) );
+            assert( !Nwk_ObjIsCo(pObj) );
+            Vec_PtrPush( vNodes, pObj );
+            Counter += Nwk_ObjIsCi(pObj);
+        }
+    }
+    Nwk_ManCleanMarks( pMan );
+//    assert( Nwk_ManRetimeVerifyCutForward(pMan, vNodes) );
+    if ( fVerbose )
+    {
+    printf( "Min-cut = %4d.  Unmoved = %4d. ", Vec_PtrSize(vNodes), Counter );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes minimum cut for backward retiming.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Nwk_ManRetimeCutBackward( Nwk_Man_t * pMan, int nLatches, int fVerbose )
+{
+    Vec_Ptr_t * vNodes;
+    Nwk_Obj_t * pObj;
+    int i, RetValue, Counter = 0, Counter2 = 0;
+    abctime clk = Abc_Clock();
+    // set the sequential parameters
+    pMan->nLatches = nLatches;
+    pMan->nTruePis = Nwk_ManCiNum(pMan) - nLatches;
+    pMan->nTruePos = Nwk_ManCoNum(pMan) - nLatches;
+    // mark the CIs, the TFI of POs, and the constant nodes
+    Nwk_ManForEachCi( pMan, pObj, i )
+        pObj->MarkA = 1;
+    Nwk_ManForEachPoSeq( pMan, pObj, i )
+        Nwk_ManMarkTfiCone_rec( pObj );
+    Nwk_ManForEachNode( pMan, pObj, i )
+        if ( Nwk_ObjFaninNum(pObj) == 0 )
+            pObj->MarkA = 1;
+    // start flow computation from each LI driver
+    Nwk_ManIncrementTravIdFlow( pMan );
+    Nwk_ManForEachLiSeq( pMan, pObj, i )
+    {
+        if ( !Nwk_ManPushBackwardFast_rec( Nwk_ObjFanin0(pObj), NULL ) )
+            continue;
+        Nwk_ManIncrementTravIdFlow( pMan );
+        Counter++; 
+    }
+    if ( fVerbose ) 
+    printf( "Backward: Max-flow = %4d -> ", Counter );
+    // continue flow computation from each LI driver
+    Nwk_ManIncrementTravIdFlow( pMan );
+    Nwk_ManForEachLiSeq( pMan, pObj, i )
+    {
+        if ( !Nwk_ManPushBackwardBot_rec( Nwk_ObjFanin0(pObj), NULL ) )
+            continue;
+        Nwk_ManIncrementTravIdFlow( pMan );
+        Counter2++;
+    }
+    if ( fVerbose )
+    printf( "%4d.  ", Counter+Counter2 );
+    // repeat flow computation from each LI driver
+    if ( Counter2 > 0 )
+    {
+        Nwk_ManIncrementTravIdFlow( pMan );
+        Nwk_ManForEachLiSeq( pMan, pObj, i )
+        {
+            RetValue = Nwk_ManPushBackwardBot_rec( Nwk_ObjFanin0(pObj), NULL );
+            assert( !RetValue );
+        }
+    }
+    // cut is a set of nodes whose bottom is visited but top is not visited
+    vNodes = Vec_PtrAlloc( Counter+Counter2 );
+    Nwk_ManForEachObj( pMan, pObj, i )
+    {
+        if ( Nwk_ObjVisitedBotOnly(pObj) )
+        {
+            assert( Nwk_ObjHasFlow(pObj) );
+            assert( !Nwk_ObjIsCo(pObj) );
+            Vec_PtrPush( vNodes, pObj );
+        }
+    }
+    // count CO drivers
+    Counter = 0;
+    Nwk_ManForEachLiSeq( pMan, pObj, i )
+        if ( Nwk_ObjVisitedBotOnly( Nwk_ObjFanin0(pObj) ) )
+            Counter++;
+    Nwk_ManCleanMarks( pMan );
+//    assert( Nwk_ManRetimeVerifyCutBackward(pMan, vNodes) );
+    if ( fVerbose )
+    {
+    printf( "Min-cut = %4d.  Unmoved = %4d. ", Vec_PtrSize(vNodes), Counter );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    return vNodes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/nwk/nwkFlow_depth.c b/abc-build/src/opt/nwk/nwkFlow_depth.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwkFlow_depth.c
@@ -0,0 +1,631 @@
+/**CFile****************************************************************
+
+  FileName    [nwkFlow.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Netlist representation.]
+
+  Synopsis    [Max-flow/min-cut computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwkFlow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nwk.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+    This code is based on the papers:
+    A. Hurst, A. Mishchenko, and R. Brayton, "Fast minimum-register retiming 
+    via binary maximum-flow", Proc. FMCAD '07, pp. 181-187. 
+    A. Hurst, A. Mishchenko, and R. Brayton, "Scalable min-area retiming 
+    under simultaneous delay and initial state constraints". Proc. DAC'08. 
+*/
+
+int DepthFwd, DepthBwd, DepthFwdMax, DepthBwdMax;
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// predecessors
+static inline Nwk_Obj_t * Nwk_ObjPred( Nwk_Obj_t * pObj )                   { return pObj->pCopy;        }
+static inline int         Nwk_ObjSetPred( Nwk_Obj_t * pObj, Nwk_Obj_t * p ) { pObj->pCopy = p; return 1; }
+// sink
+static inline int         Nwk_ObjIsSink( Nwk_Obj_t * pObj )                 { return pObj->MarkA;        }
+static inline void        Nwk_ObjSetSink( Nwk_Obj_t * pObj )                { pObj->MarkA = 1;           }
+// flow
+static inline int         Nwk_ObjHasFlow( Nwk_Obj_t * pObj )                { return pObj->MarkB;        }
+static inline void        Nwk_ObjSetFlow( Nwk_Obj_t * pObj )                { pObj->MarkB = 1;           }
+static inline void        Nwk_ObjClearFlow( Nwk_Obj_t * pObj )              { pObj->MarkB = 0;           }
+ 
+// representation of visited nodes
+// pObj->TravId  < pNtk->nTravIds-2   --- not visited
+// pObj->TravId == pNtk->nTravIds-2   --- visited bot only
+// pObj->TravId == pNtk->nTravIds-1   --- visited top only
+// pObj->TravId == pNtk->nTravIds     --- visited bot and top
+static inline int  Nwk_ObjVisitedBotOnly( Nwk_Obj_t * pObj )   
+{
+    return pObj->TravId == pObj->pMan->nTravIds - 2;
+}
+static inline int  Nwk_ObjVisitedBot( Nwk_Obj_t * pObj )     
+{ 
+    return pObj->TravId == pObj->pMan->nTravIds - 2 || pObj->TravId == pObj->pMan->nTravIds; 
+}
+static inline int  Nwk_ObjVisitedTop( Nwk_Obj_t * pObj )     
+{ 
+    return pObj->TravId == pObj->pMan->nTravIds - 1 || pObj->TravId == pObj->pMan->nTravIds; 
+}
+static inline void Nwk_ObjSetVisitedBot( Nwk_Obj_t * pObj )  
+{
+    if ( pObj->TravId < pObj->pMan->nTravIds - 2 )
+        pObj->TravId = pObj->pMan->nTravIds - 2;
+    else if ( pObj->TravId == pObj->pMan->nTravIds - 1 )
+        pObj->TravId = pObj->pMan->nTravIds;
+    else
+        assert( 0 );
+}
+static inline void Nwk_ObjSetVisitedTop( Nwk_Obj_t * pObj )  
+{
+    if ( pObj->TravId < pObj->pMan->nTravIds - 2 )
+        pObj->TravId = pObj->pMan->nTravIds - 1;
+    else if ( pObj->TravId == pObj->pMan->nTravIds - 2 )
+        pObj->TravId = pObj->pMan->nTravIds;
+    else
+        assert( 0 );
+}
+static inline Nwk_ManIncrementTravIdFlow( Nwk_Man_t * pMan )
+{
+    Nwk_ManIncrementTravId( pMan );
+    Nwk_ManIncrementTravId( pMan );
+    Nwk_ManIncrementTravId( pMan );
+}
+
+static int Nwk_ManPushForwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred );
+static int Nwk_ManPushForwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred );
+
+static int Nwk_ManPushBackwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred );
+static int Nwk_ManPushBackwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Marks TFI of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManMarkTfiCone_rec( Nwk_Obj_t * pObj )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( pObj->MarkA )
+        return;
+    pObj->MarkA = 1;
+    Nwk_ObjForEachFanin( pObj, pNext, i )
+        Nwk_ManMarkTfiCone_rec( pNext );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks TFO of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManMarkTfoCone_rec( Nwk_Obj_t * pObj )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( pObj->MarkA )
+        return;
+    pObj->MarkA = 1;
+    Nwk_ObjForEachFanout( pObj, pNext, i )
+        Nwk_ManMarkTfoCone_rec( pNext );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fast forward flow pushing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManPushForwardFast_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( Nwk_ObjIsTravIdCurrent( pObj ) )
+        return 0;
+    Nwk_ObjSetTravIdCurrent( pObj );
+    if ( Nwk_ObjHasFlow(pObj) )
+        return 0;
+    if ( Nwk_ObjIsSink(pObj) )
+    {
+        Nwk_ObjSetFlow(pObj);
+        return Nwk_ObjSetPred( pObj, pPred );
+    }
+    Nwk_ObjForEachFanout( pObj, pNext, i )
+        if ( Nwk_ManPushForwardFast_rec( pNext, pObj ) )
+        {
+            Nwk_ObjSetFlow(pObj);
+            return Nwk_ObjSetPred( pObj, pPred );
+        }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fast backward flow pushing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManPushBackwardFast_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( Nwk_ObjIsTravIdCurrent( pObj ) )
+        return 0;
+    Nwk_ObjSetTravIdCurrent( pObj );
+    if ( Nwk_ObjHasFlow(pObj) )
+        return 0;
+    if ( Nwk_ObjIsSink(pObj) )
+    {
+        Nwk_ObjSetFlow(pObj);
+        return Nwk_ObjSetPred( pObj, pPred );
+    }
+    Nwk_ObjForEachFanin( pObj, pNext, i )
+        if ( Nwk_ManPushBackwardFast_rec( pNext, pObj ) )
+        {
+            Nwk_ObjSetFlow(pObj);
+            return Nwk_ObjSetPred( pObj, pPred );
+        }
+    return 0;
+}
+  
+/**Function*************************************************************
+
+  Synopsis    [Pushing the flow through the bottom part of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManPushForwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( Nwk_ObjVisitedBot(pObj) )
+        return 0;
+    Nwk_ObjSetVisitedBot(pObj);
+    DepthFwd++;
+    if ( DepthFwdMax < DepthFwd )
+        DepthFwdMax = DepthFwd;
+    // propagate through the internal edge
+    if ( Nwk_ObjHasFlow(pObj) )
+    {
+        if ( Nwk_ObjPred(pObj) )
+            if ( Nwk_ManPushForwardTop_rec( Nwk_ObjPred(pObj), Nwk_ObjPred(pObj) ) )
+            {
+                DepthFwd--;
+                return Nwk_ObjSetPred( pObj, pPred ); 
+            }
+    }
+    else if ( Nwk_ManPushForwardTop_rec(pObj, pObj) )
+    {
+        DepthFwd--;
+        Nwk_ObjSetFlow( pObj );
+        return Nwk_ObjSetPred( pObj, pPred );
+    }
+    // try to push through the fanins
+    Nwk_ObjForEachFanin( pObj, pNext, i )
+        if ( Nwk_ManPushForwardBot_rec( pNext, pPred ) )
+        {
+            DepthFwd--;
+            return 1;
+        }
+    DepthFwd--;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Pushing the flow through the top part of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManPushForwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( Nwk_ObjVisitedTop(pObj) )
+        return 0;
+    Nwk_ObjSetVisitedTop(pObj);
+    // check if this is the sink
+    if ( Nwk_ObjIsSink(pObj) )
+        return 1;
+    DepthFwd++;
+    if ( DepthFwdMax < DepthFwd )
+        DepthFwdMax = DepthFwd;
+    // try to push through the fanouts
+    Nwk_ObjForEachFanout( pObj, pNext, i )
+        if ( Nwk_ManPushForwardBot_rec( pNext, pPred ) )
+        {
+            DepthFwd--;
+            return 1;
+        }
+    // redirect the flow
+    if ( Nwk_ObjHasFlow(pObj) && !Nwk_ObjIsCi(pObj) )
+        if ( Nwk_ManPushForwardBot_rec( pObj, Nwk_ObjPred(pObj) ) )
+        {
+            DepthFwd--;
+            Nwk_ObjClearFlow( pObj );
+            return Nwk_ObjSetPred( pObj, NULL );
+        }
+    DepthFwd--;
+    return 0;
+}
+  
+/**Function*************************************************************
+
+  Synopsis    [Pushing the flow through the bottom part of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManPushBackwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred )
+{
+    if ( Nwk_ObjVisitedBot(pObj) )
+        return 0;
+    Nwk_ObjSetVisitedBot(pObj);
+    // propagate through the internal edge
+    if ( Nwk_ObjHasFlow(pObj) )
+    {
+        if ( Nwk_ObjPred(pObj) )
+            if ( Nwk_ManPushBackwardTop_rec( Nwk_ObjPred(pObj), Nwk_ObjPred(pObj) ) )
+                return Nwk_ObjSetPred( pObj, pPred ); 
+    }
+    else if ( Nwk_ManPushBackwardTop_rec(pObj, pObj) )
+    {
+        Nwk_ObjSetFlow( pObj );
+        return Nwk_ObjSetPred( pObj, pPred );
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Pushing the flow through the top part of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManPushBackwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( Nwk_ObjVisitedTop(pObj) )
+        return 0;
+    Nwk_ObjSetVisitedTop(pObj);
+    // check if this is the sink
+    if ( Nwk_ObjIsSink(pObj) )
+        return 1;
+    // try to push through the fanins
+    Nwk_ObjForEachFanin( pObj, pNext, i )
+        if ( Nwk_ManPushBackwardBot_rec( pNext, pPred ) )
+            return 1;
+    // try to push through the fanouts
+    Nwk_ObjForEachFanout( pObj, pNext, i )
+        if ( !Nwk_ObjIsCo(pObj) && Nwk_ManPushBackwardTop_rec( pNext, pPred ) )
+            return 1;
+    // redirect the flow
+    if ( Nwk_ObjHasFlow(pObj) )
+        if ( Nwk_ObjPred(pObj) && Nwk_ManPushBackwardBot_rec( pObj, Nwk_ObjPred(pObj) ) )
+        {
+            Nwk_ObjClearFlow( pObj );
+            return Nwk_ObjSetPred( pObj, NULL );
+        }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 0 if there is an unmarked path to a CI.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManVerifyCut_rec( Nwk_Obj_t * pObj )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( pObj->MarkA )
+        return 1;
+    if ( Nwk_ObjIsLo(pObj) )
+        return 0;
+    if ( Nwk_ObjIsTravIdCurrent( pObj ) )
+        return 1;
+    Nwk_ObjSetTravIdCurrent( pObj );
+    Nwk_ObjForEachFanin( pObj, pNext, i )
+        if ( !Nwk_ManVerifyCut_rec( pNext ) )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the forward cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManRetimeVerifyCutForward( Nwk_Man_t * pMan, Vec_Ptr_t * vNodes )
+{
+    Nwk_Obj_t * pObj;
+    int i;
+    // mark the nodes
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i )
+    {
+        assert( pObj->MarkA == 0 );
+        pObj->MarkA = 1;
+    }
+    // traverse from the COs
+    Nwk_ManIncrementTravId( pMan );
+    Nwk_ManForEachCo( pMan, pObj, i )
+        if ( !Nwk_ManVerifyCut_rec( pObj ) )
+            printf( "Nwk_ManRetimeVerifyCutForward(): Internal cut verification failed.\n" );
+    // unmark the nodes
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i )
+        pObj->MarkA = 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the forward cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManRetimeVerifyCutBackward( Nwk_Man_t * pMan, Vec_Ptr_t * vNodes )
+{
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes minimum cut for forward retiming.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Nwk_ManRetimeCutForward( Nwk_Man_t * pMan, int nLatches, int fVerbose )
+{
+    Vec_Ptr_t * vNodes;
+    Nwk_Obj_t * pObj;
+    int i, RetValue, Counter = 0, Counter2 = 0;
+    clock_t clk = clock();
+    // set the sequential parameters
+    pMan->nLatches = nLatches;
+    pMan->nTruePis = Nwk_ManCiNum(pMan) - nLatches;
+    pMan->nTruePos = Nwk_ManCoNum(pMan) - nLatches;
+    // mark the COs and the TFO of PIs
+    Nwk_ManForEachCo( pMan, pObj, i )
+        pObj->MarkA = 1;
+    Nwk_ManForEachPiSeq( pMan, pObj, i )
+        Nwk_ManMarkTfoCone_rec( pObj );
+    // start flow computation from each LO
+    Nwk_ManIncrementTravIdFlow( pMan );
+    Nwk_ManForEachLoSeq( pMan, pObj, i )
+    {
+        if ( !Nwk_ManPushForwardFast_rec( pObj, NULL ) )
+            continue;
+        Nwk_ManIncrementTravIdFlow( pMan );
+        Counter++;
+    }
+    if ( fVerbose )
+    printf( "Forward:  Max-flow = %4d -> ", Counter );
+    // continue flow computation from each LO
+    DepthFwdMax = DepthFwd = 0;
+    Nwk_ManIncrementTravIdFlow( pMan );
+    Nwk_ManForEachLoSeq( pMan, pObj, i )
+    {
+    printf( "%d ", DepthFwdMax );
+        if ( !Nwk_ManPushForwardBot_rec( pObj, NULL ) )
+            continue;
+        assert( DepthFwd == 0 );
+        Nwk_ManIncrementTravIdFlow( pMan );
+        Counter2++;
+    }
+    printf( "DepthMax = %d.\n", DepthFwdMax );
+    if ( fVerbose )
+    printf( "%4d.  ", Counter+Counter2 );
+    // repeat flow computation from each LO
+    if ( Counter2 > 0 )
+    {
+        Nwk_ManIncrementTravIdFlow( pMan );
+        Nwk_ManForEachLoSeq( pMan, pObj, i )
+        {
+            RetValue = Nwk_ManPushForwardBot_rec( pObj, NULL );
+            assert( !RetValue );
+        }
+    }
+    // cut is a set of nodes whose bottom is visited but top is not visited
+    vNodes = Vec_PtrAlloc( Counter+Counter2 );
+    Counter = 0;
+    Nwk_ManForEachObj( pMan, pObj, i )
+    {
+        if ( Nwk_ObjVisitedBotOnly(pObj) )
+        {
+            assert( Nwk_ObjHasFlow(pObj) );
+            assert( !Nwk_ObjIsCo(pObj) );
+            Vec_PtrPush( vNodes, pObj );
+            Counter += Nwk_ObjIsCi(pObj);
+        }
+    }
+    Nwk_ManCleanMarks( pMan );
+    assert( Nwk_ManRetimeVerifyCutForward(pMan, vNodes) );
+    if ( fVerbose )
+    {
+    printf( "Min-cut = %4d.  Unmoved = %4d. ", Vec_PtrSize(vNodes), Counter );
+    PRT( "Time", clock() - clk );
+    }
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes minimum cut for backward retiming.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Nwk_ManRetimeCutBackward( Nwk_Man_t * pMan, int nLatches, int fVerbose )
+{
+    Vec_Ptr_t * vNodes;
+    Nwk_Obj_t * pObj;
+    int i, RetValue, Counter = 0, Counter2 = 0;
+    clock_t clk = clock();
+    // set the sequential parameters
+    pMan->nLatches = nLatches;
+    pMan->nTruePis = Nwk_ManCiNum(pMan) - nLatches;
+    pMan->nTruePos = Nwk_ManCoNum(pMan) - nLatches;
+    // mark the CIs, the TFI of POs, and the constant nodes
+    Nwk_ManForEachCi( pMan, pObj, i )
+        pObj->MarkA = 1;
+    Nwk_ManForEachPoSeq( pMan, pObj, i )
+        Nwk_ManMarkTfiCone_rec( pObj );
+    Nwk_ManForEachNode( pMan, pObj, i )
+        if ( Nwk_ObjFaninNum(pObj) == 0 )
+            pObj->MarkA = 1;
+    // start flow computation from each LI driver
+    Nwk_ManIncrementTravIdFlow( pMan );
+    Nwk_ManForEachLiSeq( pMan, pObj, i )
+    {
+        if ( !Nwk_ManPushBackwardFast_rec( Nwk_ObjFanin0(pObj), NULL ) )
+            continue;
+        Nwk_ManIncrementTravIdFlow( pMan );
+        Counter++; 
+    }
+    if ( fVerbose ) 
+    printf( "Backward: Max-flow = %4d -> ", Counter );
+    // continue flow computation from each LI driver
+    Nwk_ManIncrementTravIdFlow( pMan );
+    Nwk_ManForEachLiSeq( pMan, pObj, i )
+    {
+        if ( !Nwk_ManPushBackwardBot_rec( Nwk_ObjFanin0(pObj), NULL ) )
+            continue;
+        Nwk_ManIncrementTravIdFlow( pMan );
+        Counter2++;
+    }
+    if ( fVerbose )
+    printf( "%4d.  ", Counter+Counter2 );
+    // repeat flow computation from each LI driver
+    if ( Counter2 > 0 )
+    {
+        Nwk_ManIncrementTravIdFlow( pMan );
+        Nwk_ManForEachLiSeq( pMan, pObj, i )
+        {
+            RetValue = Nwk_ManPushBackwardBot_rec( Nwk_ObjFanin0(pObj), NULL );
+            assert( !RetValue );
+        }
+    }
+    // cut is a set of nodes whose bottom is visited but top is not visited
+    vNodes = Vec_PtrAlloc( Counter+Counter2 );
+    Nwk_ManForEachObj( pMan, pObj, i )
+    {
+        if ( Nwk_ObjVisitedBotOnly(pObj) )
+        {
+            assert( Nwk_ObjHasFlow(pObj) );
+            assert( !Nwk_ObjIsCo(pObj) );
+            Vec_PtrPush( vNodes, pObj );
+        }
+    }
+    // count CO drivers
+    Counter = 0;
+    Nwk_ManForEachLiSeq( pMan, pObj, i )
+        if ( Nwk_ObjVisitedBotOnly( Nwk_ObjFanin0(pObj) ) )
+            Counter++;
+    Nwk_ManCleanMarks( pMan );
+    assert( Nwk_ManRetimeVerifyCutBackward(pMan, vNodes) );
+    if ( fVerbose )
+    {
+    printf( "Min-cut = %4d.  Unmoved = %4d. ", Vec_PtrSize(vNodes), Counter );
+    PRT( "Time", clock() - clk );
+    }
+    return vNodes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/nwk/nwkMan.c b/abc-build/src/opt/nwk/nwkMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwkMan.c
@@ -0,0 +1,278 @@
+/**CFile****************************************************************
+
+  FileName    [nwkMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Logic network representation.]
+ 
+  Synopsis    [Network manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwkMan.c,v 1.1 2008/10/10 14:09:30 mjarvin Exp $]
+
+***********************************************************************/
+
+#include "nwk.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Nwk_Man_t * Nwk_ManAlloc()
+{
+    Nwk_Man_t * p;
+    p = ABC_ALLOC( Nwk_Man_t, 1 );
+    memset( p, 0, sizeof(Nwk_Man_t) );
+    p->vCis = Vec_PtrAlloc( 1000 );
+    p->vCos = Vec_PtrAlloc( 1000 );
+    p->vObjs = Vec_PtrAlloc( 1000 );
+    p->vTemp = Vec_PtrAlloc( 1000 );
+    p->nFanioPlus = 2;
+    p->pMemObjs = Aig_MmFlexStart();
+    p->pManHop = Hop_ManStart();
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManFree( Nwk_Man_t * p )
+{
+//    printf( "The number of realloced nodes = %d.\n", p->nRealloced );
+    if ( p->pName )    ABC_FREE( p->pName );
+    if ( p->pSpec )    ABC_FREE( p->pSpec );
+    if ( p->vCis )     Vec_PtrFree( p->vCis );
+    if ( p->vCos )     Vec_PtrFree( p->vCos );
+    if ( p->vObjs )    Vec_PtrFree( p->vObjs );
+    if ( p->vTemp )    Vec_PtrFree( p->vTemp );
+    if ( p->pManTime ) Tim_ManStop( p->pManTime );
+    if ( p->pMemObjs ) Aig_MmFlexStop( p->pMemObjs, 0 );
+    if ( p->pManHop )  Hop_ManStop( p->pManHop );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManPrintLutSizes( Nwk_Man_t * p, If_LibLut_t * pLutLib )
+{
+    Nwk_Obj_t * pObj;
+    int i, Counters[256] = {0};
+    Nwk_ManForEachNode( p, pObj, i )
+        Counters[Nwk_ObjFaninNum(pObj)]++;
+    printf( "LUTs by size: " );
+    for ( i = 0; i <= pLutLib->LutMax; i++ )
+        printf( "%d:%d ", i, Counters[i] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [If the network is best, saves it in "best.blif" and returns 1.]
+
+  Description [If the networks are incomparable, saves the new network, 
+  returns its parameters in the internal parameter structure, and returns 1.
+  If the new network is not a logic network, quits without saving and returns 0.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManCompareAndSaveBest( Nwk_Man_t * pNtk, void * pNtl )
+{
+//    extern void Ntl_WriteBlifLogic( Nwk_Man_t * pNtk, void * pNtl, char * pFileName );
+    extern void Nwk_ManDumpBlif( Nwk_Man_t * pNtk, char * pFileName, Vec_Ptr_t * vPiNames, Vec_Ptr_t * vPoNames );
+    static struct ParStruct {
+        char * pName;  // name of the best saved network
+        int    Depth;  // depth of the best saved network
+        int    Flops;  // flops in the best saved network 
+        int    Nodes;  // nodes in the best saved network
+        int    nPis;   // the number of primary inputs
+        int    nPos;   // the number of primary outputs
+    } ParsNew, ParsBest = { 0 };
+    // free storage for the name
+    if ( pNtk == NULL )
+    {
+        ABC_FREE( ParsBest.pName );
+        return 0;
+    }
+    // get the parameters
+    ParsNew.Depth = Nwk_ManLevel( pNtk );
+    ParsNew.Flops = Nwk_ManLatchNum( pNtk );
+    ParsNew.Nodes = Nwk_ManNodeNum( pNtk );
+    ParsNew.nPis  = Nwk_ManPiNum( pNtk );
+    ParsNew.nPos  = Nwk_ManPoNum( pNtk );
+    // reset the parameters if the network has the same name
+    if (  ParsBest.pName == NULL ||
+          strcmp(ParsBest.pName, pNtk->pName) ||
+          ParsBest.Depth >  ParsNew.Depth ||
+         (ParsBest.Depth == ParsNew.Depth && ParsBest.Flops >  ParsNew.Flops) ||
+         (ParsBest.Depth == ParsNew.Depth && ParsBest.Flops == ParsNew.Flops && ParsBest.Nodes >  ParsNew.Nodes) )
+    {
+        ABC_FREE( ParsBest.pName );
+        ParsBest.pName = Abc_UtilStrsav( pNtk->pName );
+        ParsBest.Depth = ParsNew.Depth; 
+        ParsBest.Flops = ParsNew.Flops; 
+        ParsBest.Nodes = ParsNew.Nodes; 
+        ParsBest.nPis  = ParsNew.nPis; 
+        ParsBest.nPos  = ParsNew.nPos;
+        // write the network
+//        Ntl_WriteBlifLogic( pNtk, pNtl, "best.blif" );
+//        Nwk_ManDumpBlif( pNtk, "best_map.blif", NULL, NULL );
+        return 1;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Nwk_FileNameGeneric( char * FileName )
+{
+    char * pDot, * pRes;
+    pRes = Abc_UtilStrsav( FileName );
+    if ( (pDot = strrchr( pRes, '.' )) )
+        *pDot = 0;
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks nodes for power-optimization.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Nwl_ManComputeTotalSwitching( Nwk_Man_t * pNtk )
+{
+    extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne );
+    Vec_Int_t * vSwitching;
+    float * pSwitching;
+    Aig_Man_t * pAig;
+    Aig_Obj_t * pObjAig;
+    Nwk_Obj_t * pObjAbc;
+    float Result = (float)0;
+    int i;
+    // strash the network
+    // map network into an AIG
+    pAig = Nwk_ManStrash( pNtk );
+    vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, 0 );
+    pSwitching = (float *)vSwitching->pArray;
+    Nwk_ManForEachObj( pNtk, pObjAbc, i )
+    {
+        if ( (pObjAig = Aig_Regular((Aig_Obj_t *)pObjAbc->pCopy)) )
+            Result += Nwk_ObjFanoutNum(pObjAbc) * pSwitching[pObjAig->Id];
+    }
+    Vec_IntFree( vSwitching );
+    Aig_ManStop( pAig );
+    return Result;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Prints stats of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManPrintStats( Nwk_Man_t * pNtk, If_LibLut_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, Ntl_Man_t * pNtl )
+{
+//    extern int Ntl_ManLatchNum( Ntl_Man_t * p );
+//    extern void Ntl_ManWriteBlifLogic( Nwk_Man_t * pNtk, void * pNtl, char * pFileName );
+    if ( fSaveBest )
+        Nwk_ManCompareAndSaveBest( pNtk, pNtl );
+    if ( fDumpResult )
+    {
+        char Buffer[1000] = {0};
+        const char * pNameGen = pNtk->pSpec? Nwk_FileNameGeneric( pNtk->pSpec ) : "nameless_";
+        sprintf( Buffer, "%s_dump.blif", pNameGen );
+//        Ntl_ManWriteBlifLogic( pNtk, pNtl, Buffer );
+//        sprintf( Buffer, "%s_dump_map.blif", pNameGen );
+//        Nwk_ManDumpBlif( pNtk, Buffer, NULL, NULL );
+        if ( pNtk->pSpec ) ABC_FREE( pNameGen );
+    }
+
+    pNtk->pLutLib = pLutLib;
+    printf( "%-15s : ",      pNtk->pName );
+    printf( "pi = %5d  ",    Nwk_ManPiNum(pNtk) );
+    printf( "po = %5d  ",    Nwk_ManPoNum(pNtk) );
+    printf( "ci = %5d  ",    Nwk_ManCiNum(pNtk) );
+    printf( "co = %5d  ",    Nwk_ManCoNum(pNtk) );
+//    printf( "lat = %5d  ",   Ntl_ManLatchNum(pNtl) );
+    printf( "node = %5d  ",  Nwk_ManNodeNum(pNtk) );
+    printf( "edge = %5d  ",  Nwk_ManGetTotalFanins(pNtk) );
+    printf( "aig = %6d  ",   Nwk_ManGetAigNodeNum(pNtk) );
+    printf( "lev = %3d  ",   Nwk_ManLevel(pNtk) );
+//    printf( "lev2 = %3d  ",  Nwk_ManLevelBackup(pNtk) );
+    printf( "delay = %5.2f  ", Nwk_ManDelayTraceLut(pNtk) );
+    if ( fPower )
+        printf( "power = %7.2f   ", Nwl_ManComputeTotalSwitching(pNtk) );
+    Nwk_ManPrintLutSizes( pNtk, pLutLib );
+    printf( "\n" );
+//    Nwk_ManDelayTracePrint( pNtk, pLutLib );
+    fflush( stdout );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/nwk/nwkMap.c b/abc-build/src/opt/nwk/nwkMap.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwkMap.c
@@ -0,0 +1,396 @@
+/**CFile****************************************************************
+
+  FileName    [nwkMap.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Logic network representation.]
+
+  Synopsis    [Interface to technology mapping.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwkMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nwk.h"
+#include "map/if/if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Load the network into FPGA manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManSetIfParsDefault( If_Par_t * pPars )
+{
+//    extern void * Abc_FrameReadLibLut();
+    // set defaults
+    memset( pPars, 0, sizeof(If_Par_t) );
+    // user-controlable paramters
+//    pPars->nLutSize    = -1;
+    pPars->nLutSize    =  6;
+    pPars->nCutsMax    =  8;
+    pPars->nFlowIters  =  1;
+    pPars->nAreaIters  =  2;
+    pPars->DelayTarget = -1;
+    pPars->Epsilon     =  (float)0.005;
+    pPars->fPreprocess =  1;
+    pPars->fArea       =  0;
+    pPars->fFancy      =  0;
+    pPars->fExpRed     =  1; ////
+    pPars->fLatchPaths =  0;
+    pPars->fEdge       =  1;
+    pPars->fPower      =  0;
+    pPars->fCutMin     =  0;
+    pPars->fVerbose    =  0;
+    // internal parameters
+    pPars->fTruth      =  0;
+    pPars->nLatchesCi  =  0;
+    pPars->nLatchesCo  =  0;
+    pPars->fLiftLeaves =  0;
+//    pPars->pLutLib     =  Abc_FrameReadLibLut();
+    pPars->pLutLib     =  NULL;
+    pPars->pTimesArr   =  NULL; 
+    pPars->pTimesArr   =  NULL;   
+    pPars->pFuncCost   =  NULL;   
+/*
+    if ( pPars->nLutSize == -1 )
+    {
+        if ( pPars->pLutLib == NULL )
+        {
+            printf( "The LUT library is not given.\n" );
+            return;
+        }
+        // get LUT size from the library
+        pPars->nLutSize = pPars->pLutLib->LutMax;
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Load the network into FPGA manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Man_t * Nwk_ManToIf( Aig_Man_t * p, If_Par_t * pPars, Vec_Ptr_t * vAigToIf )
+{
+    extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne );
+    Vec_Int_t * vSwitching = NULL, * vSwitching2 = NULL;
+    float * pSwitching = NULL, * pSwitching2 = NULL;
+    If_Man_t * pIfMan;
+    If_Obj_t * pIfObj;
+    Aig_Obj_t * pNode, * pFanin, * pPrev;
+    int i;
+    abctime clk = Abc_Clock();
+    // set the number of registers (switch activity will be combinational)
+    Aig_ManSetRegNum( p, 0 );
+    if ( pPars->fPower )
+    {
+        vSwitching  = Saig_ManComputeSwitchProbs( p, 48, 16, 0 );
+        if ( pPars->fVerbose )
+        {
+            ABC_PRT( "Computing switching activity", Abc_Clock() - clk );
+        }
+        pSwitching  = (float *)vSwitching->pArray;
+        vSwitching2 = Vec_IntStart( Aig_ManObjNumMax(p) );
+        pSwitching2 = (float *)vSwitching2->pArray;
+    }
+    // start the mapping manager and set its parameters
+    pIfMan = If_ManStart( pPars );
+    pIfMan->vSwitching = vSwitching2;
+    // load the AIG into the mapper
+    Aig_ManForEachObj( p, pNode, i )
+    {
+        if ( Aig_ObjIsAnd(pNode) )
+        {
+            pIfObj = If_ManCreateAnd( pIfMan, 
+                If_NotCond( (If_Obj_t *)Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ), 
+                If_NotCond( (If_Obj_t *)Aig_ObjFanin1(pNode)->pData, Aig_ObjFaninC1(pNode) ) );
+//            printf( "no%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) );
+        }
+        else if ( Aig_ObjIsCi(pNode) )
+        {
+            pIfObj = If_ManCreateCi( pIfMan );
+            If_ObjSetLevel( pIfObj, Aig_ObjLevel(pNode) );
+//            printf( "pi%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) );
+            if ( pIfMan->nLevelMax < (int)pIfObj->Level )
+                pIfMan->nLevelMax = (int)pIfObj->Level;
+        }
+        else if ( Aig_ObjIsCo(pNode) )
+        {
+            pIfObj = If_ManCreateCo( pIfMan, If_NotCond( (If_Obj_t *)Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ) );
+//            printf( "po%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) );
+        }
+        else if ( Aig_ObjIsConst1(pNode) )
+            pIfObj = If_ManConst1( pIfMan );
+        else // add the node to the mapper
+            assert( 0 );
+        // save the result
+        assert( Vec_PtrEntry(vAigToIf, i) == NULL );
+        Vec_PtrWriteEntry( vAigToIf, i, pIfObj );
+        pNode->pData = pIfObj;
+        if ( vSwitching2 )
+            pSwitching2[pIfObj->Id] = pSwitching[pNode->Id];            
+        // set up the choice node
+        if ( Aig_ObjIsChoice( p, pNode ) )
+        {
+            for ( pPrev = pNode, pFanin = Aig_ObjEquiv(p, pNode); pFanin; pPrev = pFanin, pFanin = Aig_ObjEquiv(p, pFanin) )
+                If_ObjSetChoice( (If_Obj_t *)pPrev->pData, (If_Obj_t *)pFanin->pData );
+            If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pData );
+        }
+//        assert( If_ObjLevel(pIfObj) == Aig_ObjLevel(pNode) );
+    }
+    if ( vSwitching )
+        Vec_IntFree( vSwitching );
+    return pIfMan;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively derives the local AIG for the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Nwk_NodeIfToHop2_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited )
+{
+    If_Cut_t * pCut;
+    If_Obj_t * pTemp;
+    Hop_Obj_t * gFunc, * gFunc0, * gFunc1;
+    // get the best cut
+    pCut = If_ObjCutBest(pIfObj);
+    // if the cut is visited, return the result
+    if ( If_CutData(pCut) )
+        return (Hop_Obj_t *)If_CutData(pCut);
+    // mark the node as visited
+    Vec_PtrPush( vVisited, pCut );
+    // insert the worst case
+    If_CutSetData( pCut, (void *)1 );
+    // skip in case of primary input
+    if ( If_ObjIsCi(pIfObj) )
+        return (Hop_Obj_t *)If_CutData(pCut);
+    // compute the functions of the children
+    for ( pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv )
+    {
+        gFunc0 = Nwk_NodeIfToHop2_rec( pHopMan, pIfMan, pTemp->pFanin0, vVisited );
+        if ( gFunc0 == (void *)1 )
+            continue;
+        gFunc1 = Nwk_NodeIfToHop2_rec( pHopMan, pIfMan, pTemp->pFanin1, vVisited );
+        if ( gFunc1 == (void *)1 )
+            continue;
+        // both branches are solved
+        gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, pTemp->fCompl0), Hop_NotCond(gFunc1, pTemp->fCompl1) ); 
+        if ( pTemp->fPhase != pIfObj->fPhase )
+            gFunc = Hop_Not(gFunc);
+        If_CutSetData( pCut, gFunc );
+        break;
+    }
+    return (Hop_Obj_t *)If_CutData(pCut);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the local AIG for the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Hop_Obj_t * Nwk_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj )
+{
+    If_Cut_t * pCut;
+    Hop_Obj_t * gFunc;
+    If_Obj_t * pLeaf;
+    int i;
+    // get the best cut
+    pCut = If_ObjCutBest(pIfObj);
+    assert( pCut->nLeaves > 1 );
+    // set the leaf variables
+    If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+        If_CutSetData( If_ObjCutBest(pLeaf), Hop_IthVar(pHopMan, i) );
+    // recursively compute the function while collecting visited cuts
+    Vec_PtrClear( pIfMan->vTemp );
+    gFunc = Nwk_NodeIfToHop2_rec( pHopMan, pIfMan, pIfObj, pIfMan->vTemp ); 
+    if ( gFunc == (void *)1 )
+    {
+        printf( "Nwk_NodeIfToHop(): Computing local AIG has failed.\n" );
+        return NULL;
+    }
+//    printf( "%d ", Vec_PtrSize(p->vTemp) );
+    // clean the cuts
+    If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+        If_CutSetData( If_ObjCutBest(pLeaf), NULL );
+    Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i )
+        If_CutSetData( pCut, NULL );
+    return gFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Nwk_Man_t * Nwk_ManFromIf( If_Man_t * pIfMan, Aig_Man_t * p, Vec_Ptr_t * vAigToIf )
+{
+    Vec_Ptr_t * vIfToAig;
+    Nwk_Man_t * pNtk;
+    Nwk_Obj_t * pObjNew;
+    Aig_Obj_t * pObj, * pObjRepr;
+    If_Obj_t * pIfObj;
+    If_Cut_t * pCutBest;
+    int i, k, nLeaves, * ppLeaves;
+    assert( Aig_ManCiNum(p) == If_ManCiNum(pIfMan) );
+    assert( Aig_ManCoNum(p) == If_ManCoNum(pIfMan) );
+    assert( Aig_ManNodeNum(p) == If_ManAndNum(pIfMan) );
+    Aig_ManCleanData( p );
+    If_ManCleanCutData( pIfMan );
+    // create mapping of IF to AIG
+    vIfToAig = Vec_PtrStart( If_ManObjNum(pIfMan) );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        pIfObj = (If_Obj_t *)Vec_PtrEntry( vAigToIf, i );
+        Vec_PtrWriteEntry( vIfToAig, pIfObj->Id, pObj );
+    }
+    // construct the network
+    pNtk = Nwk_ManAlloc();
+    pNtk->pName = Abc_UtilStrsav( p->pName );
+    pNtk->pSpec = Abc_UtilStrsav( p->pSpec );
+//    pNtk->nLatches = Aig_ManRegNum(p);
+//    pNtk->nTruePis = Nwk_ManCiNum(pNtk) - pNtk->nLatches;
+//    pNtk->nTruePos = Nwk_ManCoNum(pNtk) - pNtk->nLatches;
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        pIfObj = (If_Obj_t *)Vec_PtrEntry( vAigToIf, i );
+        if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) )
+            continue;
+        if ( Aig_ObjIsNode(pObj) )
+        {
+            pCutBest = If_ObjCutBest( pIfObj );
+            nLeaves  = If_CutLeaveNum( pCutBest ); 
+            ppLeaves = If_CutLeaves( pCutBest );
+            // create node
+            pObjNew = Nwk_ManCreateNode( pNtk, nLeaves, pIfObj->nRefs );
+            for ( k = 0; k < nLeaves; k++ )
+            {
+                pObjRepr = (Aig_Obj_t *)Vec_PtrEntry( vIfToAig, ppLeaves[k] );
+                Nwk_ObjAddFanin( pObjNew, (Nwk_Obj_t *)pObjRepr->pData );
+            }
+            // get the functionality
+            pObjNew->pFunc = Nwk_NodeIfToHop( pNtk->pManHop, pIfMan, pIfObj );
+        }
+        else if ( Aig_ObjIsCi(pObj) )
+            pObjNew = Nwk_ManCreateCi( pNtk, pIfObj->nRefs );
+        else if ( Aig_ObjIsCo(pObj) )
+        {
+            pObjNew = Nwk_ManCreateCo( pNtk );
+            pObjNew->fInvert = Aig_ObjFaninC0(pObj);
+            Nwk_ObjAddFanin( pObjNew, (Nwk_Obj_t *)Aig_ObjFanin0(pObj)->pData );
+//printf( "%d ", pObjNew->Id );
+        }
+        else if ( Aig_ObjIsConst1(pObj) )
+        {
+            pObjNew = Nwk_ManCreateNode( pNtk, 0, pIfObj->nRefs );
+            pObjNew->pFunc = Hop_ManConst1( pNtk->pManHop );
+        }
+        else
+            assert( 0 );
+        pObj->pData = pObjNew;
+    }
+//printf( "\n" );
+    Vec_PtrFree( vIfToAig );
+    pNtk->pManTime = Tim_ManDup( pIfMan->pManTim, 0 );
+    Nwk_ManMinimumBase( pNtk, 0 );
+    assert( Nwk_ManCheck( pNtk ) );
+    return pNtk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Interface with the FPGA mapping package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Nwk_Man_t * Nwk_MappingIf( Aig_Man_t * p, Tim_Man_t * pManTime, If_Par_t * pPars )
+{
+    Nwk_Man_t * pNtk;
+    If_Man_t * pIfMan;
+    Vec_Ptr_t * vAigToIf;
+    // set the arrival times
+    pPars->pTimesArr = ABC_ALLOC( float, Aig_ManCiNum(p) );
+    memset( pPars->pTimesArr, 0, sizeof(float) * Aig_ManCiNum(p) );
+    // translate into the mapper
+    vAigToIf = Vec_PtrStart( Aig_ManObjNumMax(p) );
+    pIfMan = Nwk_ManToIf( p, pPars, vAigToIf );    
+    if ( pIfMan == NULL )
+        return NULL;
+    pIfMan->pManTim = Tim_ManDup( pManTime, 0 );
+    pIfMan->pPars->fCutMin = 0; // is not compatible with deriving result
+    if ( !If_ManPerformMapping( pIfMan ) )
+    {
+        If_ManStop( pIfMan );
+        return NULL;
+    }
+    // transform the result of mapping into the new network
+    pNtk = Nwk_ManFromIf( pIfMan, p, vAigToIf );
+    if ( pPars->fBidec && pPars->nLutSize <= 8 )
+        Nwk_ManBidecResyn( pNtk, 0 );
+    If_ManStop( pIfMan );
+    Vec_PtrFree( vAigToIf );
+    return pNtk;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/nwk/nwkMerge.c b/abc-build/src/opt/nwk/nwkMerge.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwkMerge.c
@@ -0,0 +1,1046 @@
+/**CFile****************************************************************
+
+  FileName    [nwkMerge.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Netlist representation.]
+
+  Synopsis    [LUT merging algorithm.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwkMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nwk.h"
+#include "nwkMerge.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Nwk_Grf_t * Nwk_ManGraphAlloc( int nVertsMax )
+{
+    Nwk_Grf_t * p;
+    p = ABC_ALLOC( Nwk_Grf_t, 1 );
+    memset( p, 0, sizeof(Nwk_Grf_t) );
+    p->nVertsMax = nVertsMax;
+    p->nEdgeHash = Abc_PrimeCudd( 3 * nVertsMax );
+    p->pEdgeHash = ABC_CALLOC( Nwk_Edg_t *, p->nEdgeHash );
+    p->pMemEdges = Aig_MmFixedStart( sizeof(Nwk_Edg_t), p->nEdgeHash );
+    p->vPairs    = Vec_IntAlloc( 1000 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManGraphFree( Nwk_Grf_t * p )
+{
+    if ( p->vPairs )    Vec_IntFree( p->vPairs );
+    if ( p->pMemEdges ) Aig_MmFixedStop( p->pMemEdges, 0 );
+    if ( p->pMemVerts ) Aig_MmFlexStop( p->pMemVerts, 0 );
+    ABC_FREE( p->pVerts );
+    ABC_FREE( p->pEdgeHash );
+    ABC_FREE( p->pMapLut2Id );
+    ABC_FREE( p->pMapId2Lut );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the graph for solving the problem.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManGraphReportMemoryUsage( Nwk_Grf_t * p )
+{
+    p->nMemBytes1 = 
+        sizeof(Nwk_Grf_t) +
+        sizeof(void *) * p->nEdgeHash + 
+        sizeof(int) * (p->nObjs + p->nVertsMax) +
+        sizeof(Nwk_Edg_t) * p->nEdges;
+    p->nMemBytes2 = 
+        sizeof(Nwk_Vrt_t) * p->nVerts + 
+        sizeof(int) * 2 * p->nEdges;
+    printf( "Memory usage stats:  Preprocessing = %.2f MB.  Solving = %.2f MB.\n",
+        1.0 * p->nMemBytes1 / (1<<20), 1.0 * p->nMemBytes2 / (1<<20) );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds or adds the edge to the graph.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManGraphHashEdge( Nwk_Grf_t * p, int iLut1, int iLut2 )
+{
+    Nwk_Edg_t * pEntry;
+    unsigned Key;
+    if ( iLut1 == iLut2 )
+        return;
+    if ( iLut1 > iLut2 )
+    {
+        Key = iLut1;
+        iLut1 = iLut2;
+        iLut2 = Key;
+    }
+    assert( iLut1 < iLut2 );
+    if ( p->nObjs < iLut2 )
+        p->nObjs = iLut2;
+    Key = (unsigned)(741457 * iLut1 + 4256249 * iLut2) % p->nEdgeHash;
+    for ( pEntry = p->pEdgeHash[Key]; pEntry; pEntry = pEntry->pNext )
+        if ( pEntry->iNode1 == iLut1 && pEntry->iNode2 == iLut2 )
+            return;
+    pEntry = (Nwk_Edg_t *)Aig_MmFixedEntryFetch( p->pMemEdges );
+    pEntry->iNode1 = iLut1;
+    pEntry->iNode2 = iLut2;
+    pEntry->pNext = p->pEdgeHash[Key];
+    p->pEdgeHash[Key] = pEntry;
+    p->nEdges++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one entry to the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Nwk_ManGraphListAdd( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t * pVertex )
+{
+    if ( *pList )
+    {
+        Nwk_Vrt_t * pHead;
+        pHead = p->pVerts[*pList];
+        pVertex->iPrev = 0;
+        pVertex->iNext = pHead->Id;
+        pHead->iPrev = pVertex->Id;
+    }
+    *pList = pVertex->Id;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes one entry from the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Nwk_ManGraphListDelete( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t * pVertex )
+{
+    assert( *pList );
+    if ( pVertex->iPrev )
+    {
+//        assert( p->pVerts[pVertex->iPrev]->iNext == pVertex->Id );
+        p->pVerts[pVertex->iPrev]->iNext = pVertex->iNext;
+    }
+    if ( pVertex->iNext )
+    {
+//        assert( p->pVerts[pVertex->iNext]->iPrev == pVertex->Id );
+        p->pVerts[pVertex->iNext]->iPrev = pVertex->iPrev;
+    }
+    if ( *pList == pVertex->Id )
+        *pList = pVertex->iNext;
+    pVertex->iPrev = pVertex->iNext = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the edge into one of the linked lists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Nwk_ManGraphListInsert( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex )
+{
+    Nwk_Vrt_t * pNext;
+    assert( pVertex->nEdges > 0 );
+
+    if ( pVertex->nEdges == 1 )
+    {
+        pNext = p->pVerts[ pVertex->pEdges[0] ];
+        if ( pNext->nEdges >= NWK_MAX_LIST )
+            Nwk_ManGraphListAdd( p, p->pLists1 + NWK_MAX_LIST, pVertex );
+        else
+            Nwk_ManGraphListAdd( p, p->pLists1 + pNext->nEdges, pVertex );
+    }
+    else
+    {
+        if ( pVertex->nEdges >= NWK_MAX_LIST )
+            Nwk_ManGraphListAdd( p, p->pLists2 + NWK_MAX_LIST, pVertex );
+        else
+            Nwk_ManGraphListAdd( p, p->pLists2 + pVertex->nEdges, pVertex );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Extracts the edge from one of the linked lists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Nwk_ManGraphListExtract( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex )
+{
+    Nwk_Vrt_t * pNext;
+    assert( pVertex->nEdges > 0 );
+
+    if ( pVertex->nEdges == 1 )
+    {
+        pNext = p->pVerts[ pVertex->pEdges[0] ];
+        if ( pNext->nEdges >= NWK_MAX_LIST )
+            Nwk_ManGraphListDelete( p, p->pLists1 + NWK_MAX_LIST, pVertex );
+        else
+            Nwk_ManGraphListDelete( p, p->pLists1 + pNext->nEdges, pVertex );
+    }
+    else
+    {
+        if ( pVertex->nEdges >= NWK_MAX_LIST )
+            Nwk_ManGraphListDelete( p, p->pLists2 + NWK_MAX_LIST, pVertex );
+        else
+            Nwk_ManGraphListDelete( p, p->pLists2 + pVertex->nEdges, pVertex );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the graph for solving the problem.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManGraphPrepare( Nwk_Grf_t * p )
+{
+    Nwk_Edg_t * pEntry;
+    Nwk_Vrt_t * pVertex;
+    int * pnEdges, nBytes, i;
+    // allocate memory for the present objects
+    p->pMapLut2Id = ABC_ALLOC( int, p->nObjs+1 );
+    p->pMapId2Lut = ABC_ALLOC( int, p->nVertsMax+1 );
+    memset( p->pMapLut2Id, 0xff, sizeof(int) * (p->nObjs+1) );
+    memset( p->pMapId2Lut, 0xff, sizeof(int) * (p->nVertsMax+1) );
+    // mark present objects
+    Nwk_GraphForEachEdge( p, pEntry, i )
+    {
+        assert( pEntry->iNode1 <= p->nObjs );
+        assert( pEntry->iNode2 <= p->nObjs );
+        p->pMapLut2Id[ pEntry->iNode1 ] = 0;
+        p->pMapLut2Id[ pEntry->iNode2 ] = 0;
+    }
+    // map objects
+    p->nVerts = 0;
+    for ( i = 0; i <= p->nObjs; i++ )
+    {
+        if ( p->pMapLut2Id[i] == 0 )
+        {
+            p->pMapLut2Id[i] = ++p->nVerts;
+            p->pMapId2Lut[p->nVerts] = i;
+        }
+    }
+    // count the edges and mark present objects
+    pnEdges = ABC_CALLOC( int, p->nVerts+1 );
+    Nwk_GraphForEachEdge( p, pEntry, i )
+    {
+        // translate into vertices
+        assert( pEntry->iNode1 <= p->nObjs );
+        assert( pEntry->iNode2 <= p->nObjs );
+        pEntry->iNode1 = p->pMapLut2Id[pEntry->iNode1];
+        pEntry->iNode2 = p->pMapLut2Id[pEntry->iNode2];
+        // count the edges
+        assert( pEntry->iNode1 <= p->nVerts );
+        assert( pEntry->iNode2 <= p->nVerts );
+        pnEdges[pEntry->iNode1]++;
+        pnEdges[pEntry->iNode2]++;
+    }
+    // allocate the real graph
+    p->pMemVerts  = Aig_MmFlexStart();
+    p->pVerts = ABC_ALLOC( Nwk_Vrt_t *, p->nVerts + 1 );
+    p->pVerts[0] = NULL;
+    for ( i = 1; i <= p->nVerts; i++ )
+    {
+        assert( pnEdges[i] > 0 );
+        nBytes = sizeof(Nwk_Vrt_t) + sizeof(int) * pnEdges[i];
+        p->pVerts[i] = (Nwk_Vrt_t *)Aig_MmFlexEntryFetch( p->pMemVerts, nBytes );
+        memset( p->pVerts[i], 0, nBytes );
+        p->pVerts[i]->Id = i;
+    }
+    // add edges to the real graph
+    Nwk_GraphForEachEdge( p, pEntry, i )
+    {
+        pVertex = p->pVerts[pEntry->iNode1];
+        pVertex->pEdges[ pVertex->nEdges++ ] = pEntry->iNode2;
+        pVertex = p->pVerts[pEntry->iNode2];
+        pVertex->pEdges[ pVertex->nEdges++ ] = pEntry->iNode1;
+    }
+    // put vertices into the data structure
+    for ( i = 1; i <= p->nVerts; i++ )
+    {
+        assert( p->pVerts[i]->nEdges == pnEdges[i] );
+        Nwk_ManGraphListInsert( p, p->pVerts[i] );
+    }
+    // clean up
+    Aig_MmFixedStop( p->pMemEdges, 0 ); p->pMemEdges = NULL;
+    ABC_FREE( p->pEdgeHash );
+//    p->nEdgeHash = 0;
+    ABC_FREE( pnEdges );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sort pairs by the first vertex in the topological order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManGraphSortPairs( Nwk_Grf_t * p )
+{
+    int nSize = Vec_IntSize(p->vPairs);
+    int * pIdToPair, i;
+    // allocate storage
+    pIdToPair = ABC_ALLOC( int, p->nObjs+1 );
+    for ( i = 0; i <= p->nObjs; i++ )
+        pIdToPair[i] = -1;
+    // create mapping
+    for ( i = 0; i < p->vPairs->nSize; i += 2 )
+    {
+        assert( pIdToPair[ p->vPairs->pArray[i] ] == -1 );
+        pIdToPair[ p->vPairs->pArray[i] ] = p->vPairs->pArray[i+1];
+    }
+    // recreate pairs
+    Vec_IntClear( p->vPairs );
+    for ( i = 0; i <= p->nObjs; i++ )
+        if ( pIdToPair[i] >= 0 )
+        {
+            assert( i < pIdToPair[i] );
+            Vec_IntPush( p->vPairs, i );
+            Vec_IntPush( p->vPairs, pIdToPair[i] );
+        }
+    assert( nSize == Vec_IntSize(p->vPairs) );
+    ABC_FREE( pIdToPair );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the problem after pulling out one edge.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManGraphCheckLists( Nwk_Grf_t * p )
+{
+    Nwk_Vrt_t * pVertex, * pNext;
+    int i, j;
+    assert( p->pLists1[0] == 0 );
+    for ( i = 1; i <= NWK_MAX_LIST; i++ )
+        if ( p->pLists1[i] )
+        {
+            pVertex = p->pVerts[ p->pLists1[i] ];
+            assert( pVertex->nEdges == 1 );
+            pNext = p->pVerts[ pVertex->pEdges[0] ];
+            assert( pNext->nEdges == i || pNext->nEdges > NWK_MAX_LIST );
+        }
+    // find the next vertext to extract
+    assert( p->pLists2[0] == 0 );
+    assert( p->pLists2[1] == 0 );
+    for ( j = 2; j <= NWK_MAX_LIST; j++ )
+        if ( p->pLists2[j] )
+        {
+            pVertex = p->pVerts[ p->pLists2[j] ];
+            assert( pVertex->nEdges == j || pVertex->nEdges > NWK_MAX_LIST );
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Extracts the edge from one of the linked lists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Nwk_ManGraphVertexRemoveEdge( Nwk_Vrt_t * pThis, Nwk_Vrt_t * pNext )
+{
+    int k;
+    for ( k = 0; k < pThis->nEdges; k++ )
+        if ( pThis->pEdges[k] == pNext->Id )
+            break;
+    assert( k < pThis->nEdges );
+    pThis->nEdges--;
+    for ( ; k < pThis->nEdges; k++ )
+        pThis->pEdges[k] = pThis->pEdges[k+1];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the problem after pulling out one edge.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManGraphUpdate( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex, Nwk_Vrt_t * pNext )
+{
+    Nwk_Vrt_t * pChanged, * pOther;
+    int i, k;
+//    Nwk_ManGraphCheckLists( p );
+    Nwk_ManGraphListExtract( p, pVertex );
+    Nwk_ManGraphListExtract( p, pNext );
+    // update neihbors of pVertex
+    Nwk_VertexForEachAdjacent( p, pVertex, pChanged, i )
+    {
+        if ( pChanged == pNext )
+            continue;
+        Nwk_ManGraphListExtract( p, pChanged );
+        // move those that use this one
+        if ( pChanged->nEdges > 1 )
+        Nwk_VertexForEachAdjacent( p, pChanged, pOther, k )
+        {
+            if ( pOther == pVertex || pOther->nEdges > 1 )
+                continue;
+            assert( pOther->nEdges == 1 );
+            Nwk_ManGraphListExtract( p, pOther );
+            pChanged->nEdges--;
+            Nwk_ManGraphListInsert( p, pOther );
+            pChanged->nEdges++;
+        }
+        // remove the edge
+        Nwk_ManGraphVertexRemoveEdge( pChanged, pVertex );
+        // add the changed vertex back
+        if ( pChanged->nEdges > 0 )
+            Nwk_ManGraphListInsert( p, pChanged );
+    }
+    // update neihbors of pNext
+    Nwk_VertexForEachAdjacent( p, pNext, pChanged, i )
+    {
+        if ( pChanged == pVertex )
+            continue;
+        Nwk_ManGraphListExtract( p, pChanged );
+        // move those that use this one
+        if ( pChanged->nEdges > 1 )
+        Nwk_VertexForEachAdjacent( p, pChanged, pOther, k )
+        {
+            if ( pOther == pNext || pOther->nEdges > 1 )
+                continue;
+            assert( pOther->nEdges == 1 );
+            Nwk_ManGraphListExtract( p, pOther );
+            pChanged->nEdges--;
+            Nwk_ManGraphListInsert( p, pOther );
+            pChanged->nEdges++;
+        }
+        // remove the edge
+        Nwk_ManGraphVertexRemoveEdge( pChanged, pNext );
+        // add the changed vertex back
+        if ( pChanged->nEdges > 0 )
+            Nwk_ManGraphListInsert( p, pChanged );
+    }
+    // add to the result
+    if ( pVertex->Id < pNext->Id )
+    {
+        Vec_IntPush( p->vPairs, p->pMapId2Lut[pVertex->Id] ); 
+        Vec_IntPush( p->vPairs, p->pMapId2Lut[pNext->Id] ); 
+    }
+    else
+    {
+        Vec_IntPush( p->vPairs, p->pMapId2Lut[pNext->Id] ); 
+        Vec_IntPush( p->vPairs, p->pMapId2Lut[pVertex->Id] ); 
+    }
+//    Nwk_ManGraphCheckLists( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of entries in the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManGraphListLength( Nwk_Grf_t * p, int List )
+{
+    Nwk_Vrt_t * pThis;
+    int fVerbose = 0;
+    int Counter = 0;
+    Nwk_ListForEachVertex( p, List, pThis )
+    {
+        if ( fVerbose && Counter < 20 )
+            printf( "%d ", p->pVerts[pThis->pEdges[0]]->nEdges );
+        Counter++;
+    }
+    if ( fVerbose )
+        printf( "\n" );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the adjacent vertex with the mininum number of edges.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Nwk_Vrt_t * Nwk_ManGraphListFindMinEdge( Nwk_Grf_t * p, Nwk_Vrt_t * pVert )
+{
+    Nwk_Vrt_t * pThis, * pMinCost = NULL;
+    int k;
+    Nwk_VertexForEachAdjacent( p, pVert, pThis, k )
+    {
+        if ( pMinCost == NULL || pMinCost->nEdges > pThis->nEdges )
+            pMinCost = pThis;
+    }
+    return pMinCost;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the best vertext in the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Nwk_Vrt_t * Nwk_ManGraphListFindMin( Nwk_Grf_t * p, int List )
+{
+    Nwk_Vrt_t * pThis, * pMinCost = NULL;
+    int k, Counter = 10000, BestCost = 1000000;
+    Nwk_ListForEachVertex( p, List, pThis )
+    {
+        for ( k = 0; k < pThis->nEdges; k++ )
+        {
+            if ( pMinCost == NULL || BestCost > p->pVerts[pThis->pEdges[k]]->nEdges )
+            {
+                BestCost = p->pVerts[pThis->pEdges[k]]->nEdges;
+                pMinCost = pThis;
+            }
+        }
+        if ( --Counter == 0 )
+            break;
+    }
+    return pMinCost;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Solves the problem by extracting one edge at a time.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManGraphSolve( Nwk_Grf_t * p )
+{
+    Nwk_Vrt_t * pVertex, * pNext;
+    int i, j;
+    Nwk_ManGraphPrepare( p );
+    while ( 1 )
+    {
+        // find the next vertex to extract
+        assert( p->pLists1[0] == 0 );
+        for ( i = 1; i <= NWK_MAX_LIST; i++ )
+            if ( p->pLists1[i] )
+            {
+//                printf( "%d ", i );
+//                printf( "ListA = %2d. Length = %5d.\n", i, Nwk_ManGraphListLength(p,p->pLists1[i]) );
+                pVertex = p->pVerts[ p->pLists1[i] ];
+                assert( pVertex->nEdges == 1 );
+                pNext = p->pVerts[ pVertex->pEdges[0] ];
+                Nwk_ManGraphUpdate( p, pVertex, pNext );
+                break;
+            }
+        if ( i < NWK_MAX_LIST + 1 )
+            continue;
+        // find the next vertex to extract
+        assert( p->pLists2[0] == 0 );
+        assert( p->pLists2[1] == 0 );
+        for ( j = 2; j <= NWK_MAX_LIST; j++ )
+            if ( p->pLists2[j] )
+            {
+//                printf( "***%d ", j );
+//                printf( "ListB = %2d. Length = %5d.\n", j, Nwk_ManGraphListLength(p,p->pLists2[j]) );
+                pVertex = Nwk_ManGraphListFindMin( p, p->pLists2[j] ); 
+                assert( pVertex->nEdges == j || j == NWK_MAX_LIST );
+                pNext = Nwk_ManGraphListFindMinEdge( p, pVertex );
+                Nwk_ManGraphUpdate( p, pVertex, pNext );
+                break;
+            }
+        if ( j == NWK_MAX_LIST + 1 )
+            break;
+    }
+    Nwk_ManGraphSortPairs( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads graph from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Nwk_Grf_t * Nwk_ManLutMergeReadGraph( char * pFileName )
+{
+    Nwk_Grf_t * p;
+    FILE * pFile;
+    char Buffer[100];
+    int nNodes, nEdges, iNode1, iNode2;
+    int RetValue;
+    pFile = fopen( pFileName, "r" );
+    RetValue = fscanf( pFile, "%s %d", Buffer, &nNodes );
+    RetValue = fscanf( pFile, "%s %d", Buffer, &nEdges );
+    p = Nwk_ManGraphAlloc( nNodes );
+    while ( fscanf( pFile, "%s %d %d", Buffer, &iNode1, &iNode2 ) == 3 )
+        Nwk_ManGraphHashEdge( p, iNode1, iNode2 );
+    assert( p->nEdges == nEdges );
+    fclose( pFile );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Solves the graph coming from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManLutMergeGraphTest( char * pFileName )
+{
+    int nPairs;
+    Nwk_Grf_t * p;
+    abctime clk = Abc_Clock();
+    p = Nwk_ManLutMergeReadGraph( pFileName );
+    ABC_PRT( "Reading", Abc_Clock() - clk );
+    clk = Abc_Clock();
+    Nwk_ManGraphSolve( p );
+    printf( "GRAPH: Nodes = %6d. Edges = %6d.  Pairs = %6d.  ", 
+        p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 );
+    ABC_PRT( "Solving", Abc_Clock() - clk );
+    nPairs = Vec_IntSize(p->vPairs)/2;
+    Nwk_ManGraphReportMemoryUsage( p );
+    Nwk_ManGraphFree( p );
+    return nPairs;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the fanins of the node with the current trav ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManMarkFanins_rec( Nwk_Obj_t * pLut, int nLevMin )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( !Nwk_ObjIsNode(pLut) )
+        return;
+    if ( Nwk_ObjIsTravIdCurrent( pLut ) )
+        return;
+    Nwk_ObjSetTravIdCurrent( pLut );
+    if ( Nwk_ObjLevel(pLut) < nLevMin )
+        return;
+    Nwk_ObjForEachFanin( pLut, pNext, i )
+        Nwk_ManMarkFanins_rec( pNext, nLevMin );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the fanouts of the node with the current trav ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManMarkFanouts_rec( Nwk_Obj_t * pLut, int nLevMax, int nFanMax )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    if ( !Nwk_ObjIsNode(pLut) )
+        return;
+    if ( Nwk_ObjIsTravIdCurrent( pLut ) )
+        return;
+    Nwk_ObjSetTravIdCurrent( pLut );
+    if ( Nwk_ObjLevel(pLut) > nLevMax )
+        return;
+    if ( Nwk_ObjFanoutNum(pLut) > nFanMax )
+        return;
+    Nwk_ObjForEachFanout( pLut, pNext, i )
+        Nwk_ManMarkFanouts_rec( pNext, nLevMax, nFanMax );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the circle of nodes around the given set.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax )
+{
+    Nwk_Obj_t * pObj, * pNext;
+    int i, k;
+    Vec_PtrClear( vNext );
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vStart, pObj, i )
+    {
+        Nwk_ObjForEachFanin( pObj, pNext, k )
+        {
+            if ( !Nwk_ObjIsNode(pNext) )
+                continue;
+            if ( Nwk_ObjIsTravIdCurrent( pNext ) )
+                continue;
+            Nwk_ObjSetTravIdCurrent( pNext );
+            Vec_PtrPush( vNext, pNext );
+        }
+        Nwk_ObjForEachFanout( pObj, pNext, k )
+        {
+            if ( !Nwk_ObjIsNode(pNext) )
+                continue;
+            if ( Nwk_ObjIsTravIdCurrent( pNext ) )
+                continue;
+            Nwk_ObjSetTravIdCurrent( pNext );
+            if ( Nwk_ObjFanoutNum(pNext) > nFanMax )
+                continue;
+            Vec_PtrPush( vNext, pNext );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the circle of nodes removes from the given one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManCollectNonOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars )
+{
+    Vec_Ptr_t * vTemp;
+    Nwk_Obj_t * pObj;
+    int i, k;
+    Vec_PtrClear( vCands );
+    if ( pPars->nMaxSuppSize - Nwk_ObjFaninNum(pLut) <= 1 )
+        return;
+
+    // collect nodes removed by this distance
+    assert( pPars->nMaxDistance > 0 );
+    Vec_PtrClear( vStart );
+    Vec_PtrPush( vStart, pLut );
+    Nwk_ManIncrementTravId( pLut->pMan );
+    Nwk_ObjSetTravIdCurrent( pLut );
+    for ( i = 1; i <= pPars->nMaxDistance; i++ )
+    {
+        Nwk_ManCollectCircle( vStart, vNext, pPars->nMaxFanout );
+        vTemp  = vStart;
+        vStart = vNext;
+        vNext  = vTemp;
+        // collect the nodes in vStart
+        Vec_PtrForEachEntry( Nwk_Obj_t *, vStart, pObj, k )
+            Vec_PtrPush( vCands, pObj );
+    }
+
+    // mark the TFI/TFO nodes
+    Nwk_ManIncrementTravId( pLut->pMan );
+    if ( pPars->fUseTfiTfo )
+        Nwk_ObjSetTravIdCurrent( pLut );
+    else
+    {
+        Nwk_ObjSetTravIdPrevious( pLut );
+        Nwk_ManMarkFanins_rec( pLut, Nwk_ObjLevel(pLut) - pPars->nMaxDistance );
+        Nwk_ObjSetTravIdPrevious( pLut );
+        Nwk_ManMarkFanouts_rec( pLut, Nwk_ObjLevel(pLut) + pPars->nMaxDistance, pPars->nMaxFanout );
+    }
+
+    // collect nodes satisfying the following conditions:
+    // - they are close enough in terms of distance
+    // - they are not in the TFI/TFO of the LUT
+    // - they have no more than the given number of fanins
+    // - they have no more than the given diff in delay
+    k = 0;
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vCands, pObj, i )
+    {
+        if ( Nwk_ObjIsTravIdCurrent(pObj) )
+            continue;
+        if ( Nwk_ObjFaninNum(pLut) + Nwk_ObjFaninNum(pObj) > pPars->nMaxSuppSize )
+            continue;
+        if ( Nwk_ObjLevel(pLut) - Nwk_ObjLevel(pObj) > pPars->nMaxLevelDiff || 
+             Nwk_ObjLevel(pObj) - Nwk_ObjLevel(pLut) > pPars->nMaxLevelDiff )
+             continue;
+        Vec_PtrWriteEntry( vCands, k++, pObj );
+    }
+    Vec_PtrShrink( vCands, k );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Count the total number of fanins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManCountTotalFanins( Nwk_Obj_t * pLut, Nwk_Obj_t * pCand )
+{
+    Nwk_Obj_t * pFanin;
+    int i, nCounter = Nwk_ObjFaninNum(pLut);
+    Nwk_ObjForEachFanin( pCand, pFanin, i )
+        nCounter += !pFanin->MarkC;
+    return nCounter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects overlapping candidates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManCollectOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars )
+{
+    Nwk_Obj_t * pFanin, * pObj;
+    int i, k;
+    // mark fanins of pLut
+    Nwk_ObjForEachFanin( pLut, pFanin, i )
+        pFanin->MarkC = 1;
+    // collect the matching fanouts of each fanin of the node
+    Vec_PtrClear( vCands );
+    Nwk_ManIncrementTravId( pLut->pMan );
+    Nwk_ObjSetTravIdCurrent( pLut );
+    Nwk_ObjForEachFanin( pLut, pFanin, i )
+    {
+        if ( !Nwk_ObjIsNode(pFanin) )
+            continue;
+        if ( Nwk_ObjFanoutNum(pFanin) > pPars->nMaxFanout )
+            continue;
+        Nwk_ObjForEachFanout( pFanin, pObj, k )
+        {
+            if ( !Nwk_ObjIsNode(pObj) )
+                continue;
+            if ( Nwk_ObjIsTravIdCurrent( pObj ) )
+                continue;
+            Nwk_ObjSetTravIdCurrent( pObj );
+            // check the difference in delay
+            if ( Nwk_ObjLevel(pLut) - Nwk_ObjLevel(pObj) > pPars->nMaxLevelDiff || 
+                 Nwk_ObjLevel(pObj) - Nwk_ObjLevel(pLut) > pPars->nMaxLevelDiff )
+                 continue;
+            // check the total number of fanins of the node
+            if ( Nwk_ManCountTotalFanins(pLut, pObj) > pPars->nMaxSuppSize )
+                continue;
+            Vec_PtrPush( vCands, pObj );
+        }
+    }
+    // unmark fanins of pLut
+    Nwk_ObjForEachFanin( pLut, pFanin, i )
+        pFanin->MarkC = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs LUT merging with parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Nwk_ManLutMerge( Nwk_Man_t * pNtk, void * pParsInit )
+{
+    Nwk_LMPars_t * pPars = (Nwk_LMPars_t *)pParsInit;
+    Nwk_Grf_t * p;
+    Vec_Int_t * vResult;
+    Vec_Ptr_t * vStart, * vNext, * vCands1, * vCands2;
+    Nwk_Obj_t * pLut, * pCand;
+    int i, k, nVertsMax, nCands;
+    abctime clk = Abc_Clock();
+    // count the number of vertices
+    nVertsMax = 0;
+    Nwk_ManForEachNode( pNtk, pLut, i )
+        nVertsMax += (int)(Nwk_ObjFaninNum(pLut) <= pPars->nMaxLutSize);
+    p = Nwk_ManGraphAlloc( nVertsMax );
+    // create graph
+    vStart  = Vec_PtrAlloc( 1000 );
+    vNext   = Vec_PtrAlloc( 1000 );
+    vCands1 = Vec_PtrAlloc( 1000 );
+    vCands2 = Vec_PtrAlloc( 1000 );
+    nCands  = 0;
+    Nwk_ManForEachNode( pNtk, pLut, i )
+    {
+        if ( Nwk_ObjFaninNum(pLut) > pPars->nMaxLutSize )
+            continue;
+        Nwk_ManCollectOverlapCands( pLut, vCands1, pPars );
+        if ( pPars->fUseDiffSupp )
+            Nwk_ManCollectNonOverlapCands( pLut, vStart, vNext, vCands2, pPars );
+        if ( Vec_PtrSize(vCands1) == 0 && Vec_PtrSize(vCands2) == 0 )
+            continue;
+        nCands += Vec_PtrSize(vCands1) + Vec_PtrSize(vCands2);
+        // save candidates
+        Vec_PtrForEachEntry( Nwk_Obj_t *, vCands1, pCand, k )
+            Nwk_ManGraphHashEdge( p, Nwk_ObjId(pLut), Nwk_ObjId(pCand) );
+        Vec_PtrForEachEntry( Nwk_Obj_t *, vCands2, pCand, k )
+            Nwk_ManGraphHashEdge( p, Nwk_ObjId(pLut), Nwk_ObjId(pCand) );
+        // print statistics about this node
+        if ( pPars->fVeryVerbose )
+        printf( "Node %6d : Fanins = %d. Fanouts = %3d.  Cand1 = %3d. Cand2 = %3d.\n",
+            Nwk_ObjId(pLut), Nwk_ObjFaninNum(pLut), Nwk_ObjFaninNum(pLut), 
+            Vec_PtrSize(vCands1), Vec_PtrSize(vCands2) );
+    }
+    Vec_PtrFree( vStart );
+    Vec_PtrFree( vNext );
+    Vec_PtrFree( vCands1 );
+    Vec_PtrFree( vCands2 );
+    if ( pPars->fVerbose )
+    {
+        printf( "Mergable LUTs = %6d. Total cands = %6d. ", p->nVertsMax, nCands );
+        ABC_PRT( "Deriving graph", Abc_Clock() - clk );
+    }
+    // solve the graph problem
+    clk = Abc_Clock();
+    Nwk_ManGraphSolve( p );
+    if ( pPars->fVerbose )
+    {
+        printf( "GRAPH: Nodes = %6d. Edges = %6d.  Pairs = %6d.  ", 
+            p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 );
+        ABC_PRT( "Solving", Abc_Clock() - clk );
+        Nwk_ManGraphReportMemoryUsage( p );
+    }
+    vResult = p->vPairs; p->vPairs = NULL;
+/*
+    for ( i = 0; i < vResult->nSize; i += 2 )
+        printf( "(%d,%d) ", vResult->pArray[i], vResult->pArray[i+1] );
+    printf( "\n" );
+*/
+    Nwk_ManGraphFree( p );
+    return vResult;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/nwk/nwkMerge.h b/abc-build/src/opt/nwk/nwkMerge.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwkMerge.h
@@ -0,0 +1,153 @@
+/**CFile****************************************************************
+
+  FileName    [nwkMerge.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Logic network representation.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwkMerge.h,v 1.1 2008/05/14 22:13:09 wudenni Exp $]
+
+***********************************************************************/
+ 
+#ifndef __NWK_MERGE_H__
+#define __NWK_MERGE_H__
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+#define NWK_MAX_LIST  16
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// the LUT merging parameters
+typedef struct Nwk_LMPars_t_  Nwk_LMPars_t;
+struct Nwk_LMPars_t_
+{
+    int    nMaxLutSize;    // the max LUT size for merging (N=5)
+    int    nMaxSuppSize;   // the max total support size after merging (S=5)
+    int    nMaxDistance;   // the max number of nodes separating LUTs
+    int    nMaxLevelDiff;  // the max difference in levels
+    int    nMaxFanout;     // the max number of fanouts to traverse
+    int    fUseDiffSupp;   // enables the use of nodes with different support
+    int    fUseTfiTfo;     // enables the use of TFO/TFO nodes as candidates
+    int    fVeryVerbose;   // enables additional verbose output
+    int    fVerbose;       // enables verbose output
+};
+
+// edge of the graph
+typedef struct Nwk_Edg_t_  Nwk_Edg_t;
+struct Nwk_Edg_t_
+{
+    int             iNode1;      // the first node
+    int             iNode2;      // the second node
+    Nwk_Edg_t *     pNext;       // the next edge
+};
+
+// vertex of the graph
+typedef struct Nwk_Vrt_t_  Nwk_Vrt_t;
+struct Nwk_Vrt_t_
+{
+    int             Id;          // the vertex number
+    int             iPrev;       // the previous vertex in the list
+    int             iNext;       // the next vertex in the list
+    int             nEdges;      // the number of edges
+    int             pEdges[0];   // the array of edges
+};
+
+// the connectivity graph
+typedef struct Nwk_Grf_t_  Nwk_Grf_t;
+struct Nwk_Grf_t_
+{
+    // preliminary graph representation
+    int             nObjs;       // the number of objects
+    int             nVertsMax;   // the upper bound on the number of vertices
+    int             nEdgeHash;   // an approximate number of edges
+    Nwk_Edg_t **    pEdgeHash;   // hash table for edges
+    Aig_MmFixed_t * pMemEdges;   // memory for edges
+    // graph representation
+    int             nEdges;      // the number of edges
+    int             nVerts;      // the number of vertices
+    Nwk_Vrt_t **    pVerts;      // the array of vertices
+    Aig_MmFlex_t *  pMemVerts;   // memory for vertices
+    // intermediate data
+    int pLists1[NWK_MAX_LIST+1]; // lists of nodes with one edge
+    int pLists2[NWK_MAX_LIST+1]; // lists of nodes with more than one edge
+    // the results of matching
+    Vec_Int_t *     vPairs;      // pairs matched in the graph
+    // object mappings
+    int *           pMapLut2Id;  // LUT numbers into vertex IDs
+    int *           pMapId2Lut;  // vertex IDs into LUT numbers
+    // other things
+    int             nMemBytes1;  // memory usage in bytes
+    int             nMemBytes2;  // memory usage in bytes
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define Nwk_GraphForEachEdge( p, pEdge, k )             \
+    for ( k = 0; k < p->nEdgeHash; k++ )                \
+        for ( pEdge = p->pEdgeHash[k]; pEdge; pEdge = pEdge->pNext )
+
+#define Nwk_ListForEachVertex( p, List, pVrt )          \
+    for ( pVrt = List? p->pVerts[List] : NULL;  pVrt;   \
+          pVrt = pVrt->iNext? p->pVerts[pVrt->iNext] : NULL )
+
+#define Nwk_VertexForEachAdjacent( p, pVrt, pNext, k )  \
+    for ( k = 0; (k < pVrt->nEdges) && (((pNext) = p->pVerts[pVrt->pEdges[k]]), 1); k++ )
+
+////////////////////////////////////////////////////////////////////////
+///                      INLINED FUNCTIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         ITERATORS                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== nwkMerge.c ==========================================================*/
+extern ABC_DLL Nwk_Grf_t *   Nwk_ManGraphAlloc( int nVertsMax );
+extern ABC_DLL void          Nwk_ManGraphFree( Nwk_Grf_t * p );
+extern ABC_DLL void          Nwk_ManGraphReportMemoryUsage( Nwk_Grf_t * p );
+extern ABC_DLL void          Nwk_ManGraphHashEdge( Nwk_Grf_t * p, int iLut1, int iLut2 );
+extern ABC_DLL void          Nwk_ManGraphSolve( Nwk_Grf_t * p );
+extern ABC_DLL int           Nwk_ManLutMergeGraphTest( char * pFileName );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/nwk/nwkObj.c b/abc-build/src/opt/nwk/nwkObj.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwkObj.c
@@ -0,0 +1,204 @@
+/**CFile****************************************************************
+
+  FileName    [nwkObj.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Logic network representation.]
+
+  Synopsis    [Manipulation of objects.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwkObj.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nwk.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates an object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Nwk_Obj_t * Nwk_ManCreateObj( Nwk_Man_t * p, int nFanins, int nFanouts )
+{
+    Nwk_Obj_t * pObj;
+    pObj = (Nwk_Obj_t *)Aig_MmFlexEntryFetch( p->pMemObjs, sizeof(Nwk_Obj_t) + (nFanins + nFanouts + p->nFanioPlus) * sizeof(Nwk_Obj_t *) );
+    memset( pObj, 0, sizeof(Nwk_Obj_t) );
+    pObj->pFanio = (Nwk_Obj_t **)((char *)pObj + sizeof(Nwk_Obj_t));
+    pObj->Id = Vec_PtrSize( p->vObjs );
+    Vec_PtrPush( p->vObjs, pObj );
+    pObj->pMan        = p;
+    pObj->nFanioAlloc = nFanins + nFanouts + p->nFanioPlus;
+    return pObj;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a primary input.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Nwk_Obj_t * Nwk_ManCreateCi( Nwk_Man_t * p, int nFanouts )
+{
+    Nwk_Obj_t * pObj;
+    pObj = Nwk_ManCreateObj( p, 1, nFanouts );
+    pObj->PioId = Vec_PtrSize( p->vCis );
+    Vec_PtrPush( p->vCis, pObj );
+    pObj->Type = NWK_OBJ_CI;
+    p->nObjs[NWK_OBJ_CI]++;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a primary output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Nwk_Obj_t * Nwk_ManCreateCo( Nwk_Man_t * p )
+{
+    Nwk_Obj_t * pObj;
+    pObj = Nwk_ManCreateObj( p, 1, 1 );
+    pObj->PioId = Vec_PtrSize( p->vCos );
+    Vec_PtrPush( p->vCos, pObj );
+    pObj->Type = NWK_OBJ_CO;
+    p->nObjs[NWK_OBJ_CO]++;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a latch.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Nwk_Obj_t * Nwk_ManCreateLatch( Nwk_Man_t * p )
+{
+    Nwk_Obj_t * pObj;
+    pObj = Nwk_ManCreateObj( p, 1, 1 );
+    pObj->Type = NWK_OBJ_LATCH;
+    p->nObjs[NWK_OBJ_LATCH]++;
+    return pObj;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Nwk_Obj_t * Nwk_ManCreateNode( Nwk_Man_t * p, int nFanins, int nFanouts )
+{
+    Nwk_Obj_t * pObj;
+    pObj = Nwk_ManCreateObj( p, nFanins, nFanouts );
+    pObj->Type = NWK_OBJ_NODE;
+    p->nObjs[NWK_OBJ_NODE]++;
+    return pObj;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManDeleteNode( Nwk_Obj_t * pObj )
+{
+    Vec_Ptr_t * vNodes = pObj->pMan->vTemp;
+    Nwk_Obj_t * pTemp;
+    int i;
+    assert( Nwk_ObjFanoutNum(pObj) == 0 );
+    // delete fanins
+    Nwk_ObjCollectFanins( pObj, vNodes );
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pTemp, i )
+        Nwk_ObjDeleteFanin( pObj, pTemp );
+    // remove from the list of objects
+    Vec_PtrWriteEntry( pObj->pMan->vObjs, pObj->Id, NULL );
+    pObj->pMan->nObjs[pObj->Type]--;
+    memset( pObj, 0, sizeof(Nwk_Obj_t) );
+    pObj->Id = -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the node and MFFC of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManDeleteNode_rec( Nwk_Obj_t * pObj )
+{
+    Vec_Ptr_t * vNodes;
+    int i;
+    assert( !Nwk_ObjIsCi(pObj) );
+    assert( Nwk_ObjFanoutNum(pObj) == 0 );
+    vNodes = Vec_PtrAlloc( 100 );
+    Nwk_ObjCollectFanins( pObj, vNodes );
+    Nwk_ManDeleteNode( pObj );
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i )
+        if ( Nwk_ObjIsNode(pObj) && Nwk_ObjFanoutNum(pObj) == 0 )
+            Nwk_ManDeleteNode_rec( pObj );
+    Vec_PtrFree( vNodes );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/nwk/nwkSpeedup.c b/abc-build/src/opt/nwk/nwkSpeedup.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwkSpeedup.c
@@ -0,0 +1,382 @@
+/**CFile****************************************************************
+
+  FileName    [nwkSpeedup.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Netlist representation.]
+
+  Synopsis    [Global delay optimization using structural choices.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwkSpeedup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nwk.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Adds strashed nodes for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManSpeedupNode_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    if ( Aig_ObjIsTravIdCurrent(pAig, pNode) )
+        return 1;
+    if ( Aig_ObjIsCi(pNode) )
+        return 0;
+    assert( Aig_ObjIsNode(pNode) );
+    Aig_ObjSetTravIdCurrent( pAig, pNode );
+    if ( !Aig_ManSpeedupNode_rec( pAig, Aig_ObjFanin0(pNode), vNodes ) )
+        return 0;
+    if ( !Aig_ManSpeedupNode_rec( pAig, Aig_ObjFanin1(pNode), vNodes ) )
+        return 0;
+    Vec_PtrPush( vNodes, pNode );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds strashed nodes for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManSpeedupNode( Nwk_Man_t * pNtk, Aig_Man_t * pAig, Nwk_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vTimes )
+{
+    Vec_Ptr_t * vNodes;
+    Nwk_Obj_t * pObj, * pObj2;
+    Aig_Obj_t * ppCofs[32], * pAnd, * pTemp;
+    int nCofs, i, k, nSkip;
+
+    // quit of regulars are the same
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj, i )
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj2, k )
+        if ( i != k && Aig_Regular((Aig_Obj_t *)pObj->pCopy) == Aig_Regular((Aig_Obj_t *)pObj2->pCopy) )
+        {
+//            printf( "Identical after structural hashing!!!\n" );
+            return;
+        }
+
+    // collect the AIG nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    Aig_ManIncrementTravId( pAig );
+    Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) );
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj, i )
+    {
+        pAnd = (Aig_Obj_t *)pObj->pCopy;
+        Aig_ObjSetTravIdCurrent( pAig, Aig_Regular(pAnd) );
+    }
+    // traverse from the root node
+    pAnd = (Aig_Obj_t *)pNode->pCopy;
+    if ( !Aig_ManSpeedupNode_rec( pAig, Aig_Regular(pAnd), vNodes ) )
+    {
+//        printf( "Bad node!!!\n" );
+        Vec_PtrFree( vNodes );
+        return;
+    }
+
+    // derive cofactors
+    nCofs = (1 << Vec_PtrSize(vTimes));
+    for ( i = 0; i < nCofs; i++ )
+    {
+        Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj, k )
+        {
+            pAnd = (Aig_Obj_t *)pObj->pCopy;
+            Aig_Regular(pAnd)->pData = Aig_Regular(pAnd);
+        }
+        Vec_PtrForEachEntry( Nwk_Obj_t *, vTimes, pObj, k )
+        {
+            pAnd = (Aig_Obj_t *)pObj->pCopy;
+            Aig_Regular(pAnd)->pData = Aig_NotCond( Aig_ManConst1(pAig), ((i & (1<<k)) == 0) );
+        }
+        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pTemp, k )
+            pTemp->pData = Aig_And( pAig, Aig_ObjChild0Copy(pTemp), Aig_ObjChild1Copy(pTemp) );
+        // save the result
+        pAnd = (Aig_Obj_t *)pNode->pCopy;
+        ppCofs[i] = Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pAnd)->pData, Aig_IsComplement(pAnd) );
+    }
+    Vec_PtrFree( vNodes );
+
+//Nwk_ObjAddFanin( Nwk_ManCreatePo(pAig), ppCofs[0] );
+//Nwk_ObjAddFanin( Nwk_ManCreatePo(pAig), ppCofs[1] );
+
+    // collect the resulting tree
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vTimes, pObj, k )
+        for ( nSkip = (1<<k), i = 0; i < nCofs; i += 2*nSkip )
+        {
+            pAnd = (Aig_Obj_t *)pObj->pCopy;
+            ppCofs[i] = Aig_Mux( pAig, Aig_Regular(pAnd), ppCofs[i+nSkip], ppCofs[i] );
+        }
+//Nwk_ObjAddFanin( Nwk_ManCreatePo(pAig), ppCofs[0] );
+
+    // create choice node
+    pAnd  = Aig_Regular((Aig_Obj_t *)pNode->pCopy); // repr
+    pTemp = Aig_Regular(ppCofs[0]);    // new
+    if ( Aig_ObjEquiv(pAig, pAnd) == NULL && Aig_ObjEquiv(pAig, pTemp) == NULL && !Aig_ObjCheckTfi(pAig, pTemp, pAnd) )
+        pAig->pEquivs[pAnd->Id] = pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determines timing-critical edges of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Nwk_ManDelayTraceTCEdges( Nwk_Man_t * pNtk, Nwk_Obj_t * pNode, float tDelta, int fUseLutLib )
+{
+    int pPinPerm[32];
+    float pPinDelays[32];
+    If_LibLut_t * pLutLib = fUseLutLib? pNtk->pLutLib : NULL;
+    Nwk_Obj_t * pFanin;
+    unsigned uResult = 0;
+    float tRequired, * pDelays;
+    int k;
+    tRequired = Nwk_ObjRequired(pNode);
+    if ( pLutLib == NULL )
+    {
+        Nwk_ObjForEachFanin( pNode, pFanin, k )
+            if ( tRequired < Nwk_ObjArrival(pFanin) + 1.0 + tDelta )
+                uResult |= (1 << k);
+    }
+    else if ( !pLutLib->fVarPinDelays )
+    {
+        pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pNode)];
+        Nwk_ObjForEachFanin( pNode, pFanin, k )
+            if ( tRequired < Nwk_ObjArrival(pFanin) + pDelays[0] + tDelta )
+                uResult |= (1 << k);
+    }
+    else
+    {
+        pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pNode)];
+        Nwk_ManDelayTraceSortPins( pNode, pPinPerm, pPinDelays );
+        Nwk_ObjForEachFanin( pNode, pFanin, k )
+            if ( tRequired < Nwk_ObjArrival(Nwk_ObjFanin(pNode,pPinPerm[k])) + pDelays[k] + tDelta )
+                uResult |= (1 << pPinPerm[k]);
+    }
+    return uResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds choices to speed up the network by the given percentage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Nwk_ManSpeedup( Nwk_Man_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose )
+{
+    Aig_Man_t * pAig, * pTemp;
+    Vec_Ptr_t * vTimeCries, * vTimeFanins;
+    Nwk_Obj_t * pNode, * pFanin, * pFanin2;
+    Aig_Obj_t * pAnd;
+    If_LibLut_t * pTempLib = pNtk->pLutLib;
+    Tim_Man_t * pTempTim = NULL; 
+    float tDelta, tArrival;
+    int i, k, k2, Counter, CounterRes, nTimeCris;
+    unsigned * puTCEdges;
+    // perform delay trace
+    if ( !fUseLutLib )
+    {
+        pNtk->pLutLib = NULL;
+        if ( pNtk->pManTime )
+        {
+            pTempTim = pNtk->pManTime;
+            pNtk->pManTime = Tim_ManDup( pTempTim, 1 );
+        }
+    }
+    tArrival = Nwk_ManDelayTraceLut( pNtk );
+    tDelta = fUseLutLib ? tArrival*Percentage/100.0 : 1.0;
+    if ( fVerbose )
+    {
+        printf( "Max delay = %.2f. Delta = %.2f. ", tArrival, tDelta );
+        printf( "Using %s model. ", fUseLutLib? "LUT library" : "unit-delay" );
+        if ( fUseLutLib )
+            printf( "Percentage = %d. ", Percentage );
+        printf( "\n" );
+    }
+    // mark the timing critical nodes and edges
+    puTCEdges = ABC_ALLOC( unsigned, Nwk_ManObjNumMax(pNtk) );
+    memset( puTCEdges, 0, sizeof(unsigned) * Nwk_ManObjNumMax(pNtk) );
+    Nwk_ManForEachNode( pNtk, pNode, i )
+    {
+        if ( Nwk_ObjSlack(pNode) >= tDelta )
+            continue;
+        puTCEdges[pNode->Id] = Nwk_ManDelayTraceTCEdges( pNtk, pNode, tDelta, fUseLutLib );
+    }
+    if ( fVerbose )
+    {
+        Counter = CounterRes = 0;
+        Nwk_ManForEachNode( pNtk, pNode, i )
+        {
+            Nwk_ObjForEachFanin( pNode, pFanin, k )
+                if ( !Nwk_ObjIsCi(pFanin) && Nwk_ObjSlack(pFanin) < tDelta )
+                    Counter++;
+            CounterRes += Aig_WordCountOnes( puTCEdges[pNode->Id] );
+        }
+        printf( "Edges: Total = %7d. 0-slack = %7d. Critical = %7d. Ratio = %4.2f\n", 
+            Nwk_ManGetTotalFanins(pNtk), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 );
+    }
+    // start the resulting network
+    pAig = Nwk_ManStrash( pNtk );
+    pAig->pEquivs = ABC_ALLOC( Aig_Obj_t *, 3 * Aig_ManObjNumMax(pAig) );
+    memset( pAig->pEquivs, 0, sizeof(Aig_Obj_t *) * 3 * Aig_ManObjNumMax(pAig) );
+
+    // collect nodes to be used for resynthesis
+    Counter = CounterRes = 0;
+    vTimeCries = Vec_PtrAlloc( 16 );
+    vTimeFanins = Vec_PtrAlloc( 16 );
+    Nwk_ManForEachNode( pNtk, pNode, i )
+    {
+        if ( Nwk_ObjSlack(pNode) >= tDelta )
+            continue;
+        // count the number of non-PI timing-critical nodes
+        nTimeCris = 0;
+        Nwk_ObjForEachFanin( pNode, pFanin, k )
+            if ( !Nwk_ObjIsCi(pFanin) && (puTCEdges[pNode->Id] & (1<<k)) )
+                nTimeCris++;
+        if ( !fVeryVerbose && nTimeCris == 0 )
+            continue;
+        Counter++;
+        // count the total number of timing critical second-generation nodes
+        Vec_PtrClear( vTimeCries );
+        if ( nTimeCris )
+        {
+            Nwk_ObjForEachFanin( pNode, pFanin, k )
+                if ( !Nwk_ObjIsCi(pFanin) && (puTCEdges[pNode->Id] & (1<<k)) )
+                    Nwk_ObjForEachFanin( pFanin, pFanin2, k2 )
+                        if ( puTCEdges[pFanin->Id] & (1<<k2) )
+                            Vec_PtrPushUnique( vTimeCries, pFanin2 );
+        }
+//        if ( !fVeryVerbose && (Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree) )
+        if ( (Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree) )
+            continue;
+        CounterRes++;
+        // collect second generation nodes
+        Vec_PtrClear( vTimeFanins );
+        Nwk_ObjForEachFanin( pNode, pFanin, k )
+        {
+            if ( Nwk_ObjIsCi(pFanin) )
+                Vec_PtrPushUnique( vTimeFanins, pFanin );
+            else
+                Nwk_ObjForEachFanin( pFanin, pFanin2, k2 )
+                    Vec_PtrPushUnique( vTimeFanins, pFanin2 );                    
+        }
+        // print the results
+        if ( fVeryVerbose )
+        {
+        printf( "%5d Node %5d : %d %2d %2d  ", Counter, pNode->Id, 
+            nTimeCris, Vec_PtrSize(vTimeCries), Vec_PtrSize(vTimeFanins) );
+        Nwk_ObjForEachFanin( pNode, pFanin, k )
+            printf( "%d(%.2f)%s ", pFanin->Id, Nwk_ObjSlack(pFanin), (puTCEdges[pNode->Id] & (1<<k))? "*":"" );
+        printf( "\n" );
+        }
+        // add the node to choices
+        if ( Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree )
+            continue;
+        // order the fanins in the increasing order of criticalily
+        if ( Vec_PtrSize(vTimeCries) > 1 )
+        {
+            pFanin = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 0 );
+            pFanin2 = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 1 );
+            if ( Nwk_ObjSlack(pFanin) < Nwk_ObjSlack(pFanin2) )
+            {
+                Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 );
+                Vec_PtrWriteEntry( vTimeCries, 1, pFanin );
+            }
+        }
+        if ( Vec_PtrSize(vTimeCries) > 2 )
+        {
+            pFanin = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 1 );
+            pFanin2 = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 2 );
+            if ( Nwk_ObjSlack(pFanin) < Nwk_ObjSlack(pFanin2) )
+            {
+                Vec_PtrWriteEntry( vTimeCries, 1, pFanin2 );
+                Vec_PtrWriteEntry( vTimeCries, 2, pFanin );
+            }
+            pFanin = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 0 );
+            pFanin2 = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 1 );
+            if ( Nwk_ObjSlack(pFanin) < Nwk_ObjSlack(pFanin2) )
+            {
+                Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 );
+                Vec_PtrWriteEntry( vTimeCries, 1, pFanin );
+            }
+        }
+        // add choice
+        Aig_ManSpeedupNode( pNtk, pAig, pNode, vTimeFanins, vTimeCries );
+    }
+    Vec_PtrFree( vTimeCries );
+    Vec_PtrFree( vTimeFanins );
+    ABC_FREE( puTCEdges );
+    if ( fVerbose )
+        printf( "Nodes: Total = %7d. 0-slack = %7d. Workable = %7d. Ratio = %4.2f\n", 
+        Nwk_ManNodeNum(pNtk), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 ); 
+
+    // remove invalid choice nodes
+    Aig_ManForEachNode( pAig, pAnd, i )
+        if ( Aig_ObjEquiv(pAig, pAnd) )
+        {
+            if ( Aig_ObjRefs(Aig_ObjEquiv(pAig, pAnd)) > 0 )
+                pAig->pEquivs[pAnd->Id] = NULL;
+        }
+
+    // put back the library
+    if ( !fUseLutLib )
+        pNtk->pLutLib = pTempLib;
+    if ( pTempTim )
+    {
+        Tim_ManStop( pNtk->pManTime );
+        pNtk->pManTime = pTempTim;
+    }
+
+    // reconstruct the network
+    pAig = Aig_ManDupDfs( pTemp = pAig );
+    Aig_ManStop( pTemp );
+    // reset levels
+    Aig_ManChoiceLevel( pAig );
+    return pAig;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/nwk/nwkStrash.c b/abc-build/src/opt/nwk/nwkStrash.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwkStrash.c
@@ -0,0 +1,149 @@
+/**CFile****************************************************************
+
+  FileName    [nwkStrash.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Logic network representation.]
+
+  Synopsis    [Performs structural hashing for the network.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwkStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nwk.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives AIG from the local functions of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManStrashNode_rec( Aig_Man_t * p, Hop_Obj_t * pObj )
+{
+    assert( !Hop_IsComplement(pObj) );
+    if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+        return;
+    Nwk_ManStrashNode_rec( p, Hop_ObjFanin0(pObj) ); 
+    Nwk_ManStrashNode_rec( p, Hop_ObjFanin1(pObj) );
+    pObj->pData = Aig_And( p, (Aig_Obj_t *)Hop_ObjChild0Copy(pObj), (Aig_Obj_t *)Hop_ObjChild1Copy(pObj) );
+    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+    Hop_ObjSetMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives AIG from the local functions of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Nwk_ManStrashNode( Aig_Man_t * p, Nwk_Obj_t * pObj )
+{
+    Hop_Man_t * pMan = pObj->pMan->pManHop;
+    Hop_Obj_t * pRoot = pObj->pFunc;
+    Nwk_Obj_t * pFanin;
+    int i;
+    assert( Nwk_ObjIsNode(pObj) );
+    // check the constant case
+    if ( Hop_Regular(pRoot) == Hop_ManConst1(pMan) )
+        return Aig_NotCond( Aig_ManConst1(p), Hop_IsComplement(pRoot) );
+    // set elementary variables
+    Nwk_ObjForEachFanin( pObj, pFanin, i )
+        Hop_IthVar(pMan, i)->pData = pFanin->pCopy;
+    // strash the AIG of this node
+    Nwk_ManStrashNode_rec( p, Hop_Regular(pRoot) );
+    Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
+    // return the final node
+    return Aig_NotCond( (Aig_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives AIG from the logic network.]
+
+  Description [Assumes topological ordering of nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Nwk_ManStrash( Nwk_Man_t * pNtk )
+{
+    Vec_Ptr_t * vObjs;
+    Aig_Man_t * pMan;
+    Aig_Obj_t * pObjNew;
+    Nwk_Obj_t * pObj;
+    int i, Level;
+    pMan = Aig_ManStart( Nwk_ManGetAigNodeNum(pNtk) );
+    pMan->pName = Abc_UtilStrsav( pNtk->pName );
+    pMan->pSpec = Abc_UtilStrsav( pNtk->pSpec );
+    pMan->pManTime = Tim_ManDup( (Tim_Man_t *)pNtk->pManTime, 1 );
+    Tim_ManIncrementTravId( (Tim_Man_t *)pMan->pManTime );
+    Nwk_ManForEachObj( pNtk, pObj, i )
+        pObj->pCopy = NULL;
+//    Nwk_ManForEachObj( pNtk, pObj, i )
+    vObjs = Nwk_ManDfs( pNtk );
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vObjs, pObj, i )
+    {
+        if ( Nwk_ObjIsCi(pObj) )
+        {
+            pObjNew = Aig_ObjCreateCi(pMan);
+            Level = Tim_ManGetCiArrival( (Tim_Man_t *)pMan->pManTime, pObj->PioId );
+            Aig_ObjSetLevel( pObjNew, Level );
+        }
+        else if ( Nwk_ObjIsCo(pObj) )
+        {
+            pObjNew = Aig_ObjCreateCo( pMan, Aig_NotCond((Aig_Obj_t *)Nwk_ObjFanin0(pObj)->pCopy, pObj->fInvert) );
+            Level = Aig_ObjLevel( pObjNew );
+            Tim_ManSetCoArrival( (Tim_Man_t *)pMan->pManTime, pObj->PioId, (float)Level );
+        }
+        else if ( Nwk_ObjIsNode(pObj) )
+        {
+            pObjNew = Nwk_ManStrashNode( pMan, pObj );
+        }
+        else
+            assert( 0 );
+        pObj->pCopy = pObjNew;
+    }
+    Vec_PtrFree( vObjs );
+    Aig_ManCleanup( pMan );
+    Aig_ManSetRegNum( pMan, 0 );
+    return pMan;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/nwk/nwkTiming.c b/abc-build/src/opt/nwk/nwkTiming.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwkTiming.c
@@ -0,0 +1,894 @@
+/**CFile****************************************************************
+
+  FileName    [nwkTiming.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Logic network representation.]
+
+  Synopsis    [Manipulation of timing information.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwkTiming.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include "nwk.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans timing information for all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManCleanTiming( Nwk_Man_t * pNtk )
+{
+    Nwk_Obj_t * pObj;
+    int i;
+    Nwk_ManForEachObj( pNtk, pObj, i )
+    {
+        pObj->tArrival = pObj->tSlack = 0.0;
+        pObj->tRequired = TIM_ETERNITY;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts the pins in the decreasing order of delays.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManDelayTraceSortPins( Nwk_Obj_t * pNode, int * pPinPerm, float * pPinDelays )
+{
+    Nwk_Obj_t * pFanin;
+    int i, j, best_i, temp;
+    // start the trivial permutation and collect pin delays
+    Nwk_ObjForEachFanin( pNode, pFanin, i )
+    {
+        pPinPerm[i] = i;
+        pPinDelays[i] = Nwk_ObjArrival(pFanin);
+    }
+    // selection sort the pins in the decreasible order of delays
+    // this order will match the increasing order of LUT input pins
+    for ( i = 0; i < Nwk_ObjFaninNum(pNode)-1; i++ )
+    {
+        best_i = i;
+        for ( j = i+1; j < Nwk_ObjFaninNum(pNode); j++ )
+            if ( pPinDelays[pPinPerm[j]] > pPinDelays[pPinPerm[best_i]] )
+                best_i = j;
+        if ( best_i == i )
+            continue;
+        temp = pPinPerm[i]; 
+        pPinPerm[i] = pPinPerm[best_i]; 
+        pPinPerm[best_i] = temp;
+    }
+    // verify
+    assert( Nwk_ObjFaninNum(pNode) == 0 || pPinPerm[0] < Nwk_ObjFaninNum(pNode) );
+    for ( i = 1; i < Nwk_ObjFaninNum(pNode); i++ )
+    {
+        assert( pPinPerm[i] < Nwk_ObjFaninNum(pNode) );
+        assert( pPinDelays[pPinPerm[i-1]] >= pPinDelays[pPinPerm[i]] );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts the pins in the decreasing order of delays.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManWhereIsPin( Nwk_Obj_t * pFanout, Nwk_Obj_t * pFanin, int * pPinPerm )
+{
+    int i;
+    for ( i = 0; i < Nwk_ObjFaninNum(pFanout); i++ )
+        if ( Nwk_ObjFanin(pFanout, pPinPerm[i]) == pFanin )
+            return i;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the arrival times for the given object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Nwk_NodeComputeArrival( Nwk_Obj_t * pObj, int fUseSorting )
+{
+    If_LibLut_t * pLutLib = pObj->pMan->pLutLib;
+    int pPinPerm[32];
+    float pPinDelays[32];
+    Nwk_Obj_t * pFanin;
+    float tArrival, * pDelays;
+    int k;
+    assert( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCi(pObj) || Nwk_ObjIsCo(pObj) );
+    if ( Nwk_ObjIsCi(pObj) )
+        return Nwk_ObjArrival(pObj);
+    if ( Nwk_ObjIsCo(pObj) )
+        return Nwk_ObjArrival( Nwk_ObjFanin0(pObj) );
+    tArrival = -TIM_ETERNITY;
+    if ( pLutLib == NULL )
+    {
+        Nwk_ObjForEachFanin( pObj, pFanin, k )
+            if ( tArrival < Nwk_ObjArrival(pFanin) + 1.0 )
+                tArrival = Nwk_ObjArrival(pFanin) + 1.0;
+    }
+    else if ( !pLutLib->fVarPinDelays )
+    {
+        pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pObj)];
+        Nwk_ObjForEachFanin( pObj, pFanin, k )
+            if ( tArrival < Nwk_ObjArrival(pFanin) + pDelays[0] )
+                tArrival = Nwk_ObjArrival(pFanin) + pDelays[0];
+    }
+    else
+    {
+        pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pObj)];
+        if ( fUseSorting )
+        {
+            Nwk_ManDelayTraceSortPins( pObj, pPinPerm, pPinDelays );
+            Nwk_ObjForEachFanin( pObj, pFanin, k ) 
+                if ( tArrival < Nwk_ObjArrival(Nwk_ObjFanin(pObj,pPinPerm[k])) + pDelays[k] )
+                    tArrival = Nwk_ObjArrival(Nwk_ObjFanin(pObj,pPinPerm[k])) + pDelays[k];
+        }
+        else
+        {
+            Nwk_ObjForEachFanin( pObj, pFanin, k )
+                if ( tArrival < Nwk_ObjArrival(pFanin) + pDelays[k] )
+                    tArrival = Nwk_ObjArrival(pFanin) + pDelays[k];
+        }
+    }
+    if ( Nwk_ObjFaninNum(pObj) == 0 )
+        tArrival = 0.0;
+    return tArrival;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the required times for the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Nwk_NodeComputeRequired( Nwk_Obj_t * pObj, int fUseSorting )
+{
+    If_LibLut_t * pLutLib = pObj->pMan->pLutLib;
+    int pPinPerm[32];
+    float pPinDelays[32];
+    Nwk_Obj_t * pFanout;
+    float tRequired, tDelay, * pDelays;
+    int k, iFanin;
+    assert( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCi(pObj) || Nwk_ObjIsCo(pObj) );
+    if ( Nwk_ObjIsCo(pObj) )
+        return Nwk_ObjRequired(pObj);
+    tRequired = TIM_ETERNITY;
+    if ( pLutLib == NULL )
+    {
+        Nwk_ObjForEachFanout( pObj, pFanout, k )
+        {
+            tDelay = Nwk_ObjIsCo(pFanout)? 0.0 : 1.0;
+            if ( tRequired > Nwk_ObjRequired(pFanout) - tDelay )
+                tRequired = Nwk_ObjRequired(pFanout) - tDelay;
+        }
+    }
+    else if ( !pLutLib->fVarPinDelays )
+    {
+        Nwk_ObjForEachFanout( pObj, pFanout, k )
+        {
+            pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pFanout)];
+            tDelay = Nwk_ObjIsCo(pFanout)? 0.0 : pDelays[0];
+            if ( tRequired > Nwk_ObjRequired(pFanout) - tDelay )
+                tRequired = Nwk_ObjRequired(pFanout) - tDelay;
+        }
+    }
+    else
+    {
+        if ( fUseSorting )
+        {
+            Nwk_ObjForEachFanout( pObj, pFanout, k ) 
+            {
+                pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pFanout)];
+                Nwk_ManDelayTraceSortPins( pFanout, pPinPerm, pPinDelays );
+                iFanin = Nwk_ManWhereIsPin( pFanout, pObj, pPinPerm );
+                assert( Nwk_ObjFanin(pFanout,pPinPerm[iFanin]) == pObj );
+                tDelay = Nwk_ObjIsCo(pFanout)? 0.0 : pDelays[iFanin];
+                if ( tRequired > Nwk_ObjRequired(pFanout) - tDelay )
+                    tRequired = Nwk_ObjRequired(pFanout) - tDelay;
+            }
+        }
+        else
+        {
+            Nwk_ObjForEachFanout( pObj, pFanout, k )
+            {
+                pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pFanout)];
+                iFanin = Nwk_ObjFindFanin( pFanout, pObj );
+                assert( Nwk_ObjFanin(pFanout,iFanin) == pObj );
+                tDelay = Nwk_ObjIsCo(pFanout)? 0.0 : pDelays[iFanin];
+                if ( tRequired > Nwk_ObjRequired(pFanout) - tDelay )
+                    tRequired = Nwk_ObjRequired(pFanout) - tDelay;
+            }
+        }
+    }
+    return tRequired;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagates the required times through the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Nwk_NodePropagateRequired( Nwk_Obj_t * pObj, int fUseSorting )
+{
+    If_LibLut_t * pLutLib = pObj->pMan->pLutLib;
+    int pPinPerm[32];
+    float pPinDelays[32];
+    Nwk_Obj_t * pFanin;
+    float tRequired = 0.0; // Suppress "might be used uninitialized"
+    float * pDelays;
+    int k;
+    assert( Nwk_ObjIsNode(pObj) );
+    if ( pLutLib == NULL )
+    {
+        tRequired = Nwk_ObjRequired(pObj) - (float)1.0;
+        Nwk_ObjForEachFanin( pObj, pFanin, k )
+            if ( Nwk_ObjRequired(pFanin) > tRequired )
+                Nwk_ObjSetRequired( pFanin, tRequired );
+    }
+    else if ( !pLutLib->fVarPinDelays )
+    {
+        pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pObj)];
+        tRequired = Nwk_ObjRequired(pObj) - pDelays[0];
+        Nwk_ObjForEachFanin( pObj, pFanin, k )
+            if ( Nwk_ObjRequired(pFanin) > tRequired )
+                Nwk_ObjSetRequired( pFanin, tRequired );
+    }
+    else 
+    {
+        pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pObj)];
+        if ( fUseSorting )
+        {
+            Nwk_ManDelayTraceSortPins( pObj, pPinPerm, pPinDelays );
+            Nwk_ObjForEachFanin( pObj, pFanin, k )
+            {
+                tRequired = Nwk_ObjRequired(pObj) - pDelays[k];
+                if ( Nwk_ObjRequired(Nwk_ObjFanin(pObj,pPinPerm[k])) > tRequired )
+                    Nwk_ObjSetRequired( Nwk_ObjFanin(pObj,pPinPerm[k]), tRequired );
+            }
+        }
+        else
+        {
+            Nwk_ObjForEachFanin( pObj, pFanin, k )
+            {
+                tRequired = Nwk_ObjRequired(pObj) - pDelays[k];
+                if ( Nwk_ObjRequired(pFanin) > tRequired )
+                    Nwk_ObjSetRequired( pFanin, tRequired );
+            }
+        }
+    }
+    return tRequired;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the delay trace of the given network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Nwk_ManDelayTraceLut( Nwk_Man_t * pNtk )
+{
+    Vec_Ptr_t * vObjs;
+    int fUseSorting = 1;
+    If_LibLut_t * pLutLib = pNtk->pLutLib;
+    Vec_Ptr_t * vNodes;
+    Nwk_Obj_t * pObj;
+    float tArrival, tRequired, tSlack;
+    int i;
+
+    // get the library
+    if ( pLutLib && pLutLib->LutMax < Nwk_ManGetFaninMax(pNtk) )
+    {
+        printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", 
+            pLutLib->LutMax, Nwk_ManGetFaninMax(pNtk) );
+        return -TIM_ETERNITY;
+    }
+
+    // compute the reverse order of all objects
+    vNodes = Nwk_ManDfsReverse( pNtk );
+
+    // initialize the arrival times
+    Nwk_ManCleanTiming( pNtk );
+
+    // propagate arrival times
+    if ( pNtk->pManTime )
+        Tim_ManIncrementTravId( pNtk->pManTime );
+//    Nwk_ManForEachObj( pNtk, pObj, i )
+    vObjs = Nwk_ManDfs( pNtk );
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vObjs, pObj, i )
+    {
+        tArrival = Nwk_NodeComputeArrival( pObj, fUseSorting );
+        if ( Nwk_ObjIsCi(pObj) && pNtk->pManTime )
+            tArrival = Tim_ManGetCiArrival( pNtk->pManTime, pObj->PioId );
+        if ( Nwk_ObjIsCo(pObj) && pNtk->pManTime )
+            Tim_ManSetCoArrival( pNtk->pManTime, pObj->PioId, tArrival );
+        Nwk_ObjSetArrival( pObj, tArrival );
+    }
+    Vec_PtrFree( vObjs );
+
+    // get the latest arrival times
+    tArrival = -TIM_ETERNITY;
+    Nwk_ManForEachPo( pNtk, pObj, i )
+        if ( tArrival < Nwk_ObjArrival(pObj) )
+            tArrival = Nwk_ObjArrival(pObj);
+
+    // initialize the required times
+    if ( pNtk->pManTime )
+    {
+        Tim_ManIncrementTravId( pNtk->pManTime );
+        Tim_ManInitPoRequiredAll( pNtk->pManTime, tArrival );
+    }
+    else
+    {
+        Nwk_ManForEachCo( pNtk, pObj, i )
+            Nwk_ObjSetRequired( pObj, tArrival );
+    }
+
+    // propagate the required times
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i )
+    {
+        if ( Nwk_ObjIsNode(pObj) )
+        {
+            Nwk_NodePropagateRequired( pObj, fUseSorting );
+        }
+        else if ( Nwk_ObjIsCi(pObj) )
+        {
+            if ( pNtk->pManTime )
+                Tim_ManSetCiRequired( pNtk->pManTime, pObj->PioId, Nwk_ObjRequired(pObj) );
+        }
+        else if ( Nwk_ObjIsCo(pObj) )
+        {
+            if ( pNtk->pManTime )
+            {
+                tRequired = Tim_ManGetCoRequired( pNtk->pManTime, pObj->PioId );
+                Nwk_ObjSetRequired( pObj, tRequired );
+            }
+            if ( Nwk_ObjRequired(Nwk_ObjFanin0(pObj)) > Nwk_ObjRequired(pObj) )
+                Nwk_ObjSetRequired( Nwk_ObjFanin0(pObj), Nwk_ObjRequired(pObj) );
+        }
+
+        // set slack for this object
+        tSlack = Nwk_ObjRequired(pObj) - Nwk_ObjArrival(pObj);
+        assert( tSlack + 0.01 > 0.0 );
+        Nwk_ObjSetSlack( pObj, tSlack < 0.0 ? 0.0 : tSlack );
+    }
+    Vec_PtrFree( vNodes );
+    return tArrival;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the arrival times for the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManVerifyTiming(  Nwk_Man_t * pNtk )
+{
+    Nwk_Obj_t * pObj;
+    float tArrival, tRequired;
+    int i;
+    Nwk_ManForEachObj( pNtk, pObj, i )
+    {
+        if ( Nwk_ObjIsCi(pObj) && Nwk_ObjFanoutNum(pObj) == 0 )
+            continue;
+        tArrival = Nwk_NodeComputeArrival( pObj, 1 );
+        tRequired = Nwk_NodeComputeRequired( pObj, 1 );
+        if ( !Nwk_ManTimeEqual( tArrival, Nwk_ObjArrival(pObj), (float)0.01 ) )
+            printf( "Nwk_ManVerifyTiming(): Object %d has different arrival time (%.2f) from computed (%.2f).\n", 
+                pObj->Id, Nwk_ObjArrival(pObj), tArrival );
+        if ( !Nwk_ManTimeEqual( tRequired, Nwk_ObjRequired(pObj), (float)0.01 ) )
+            printf( "Nwk_ManVerifyTiming(): Object %d has different required time (%.2f) from computed (%.2f).\n", 
+                pObj->Id, Nwk_ObjRequired(pObj), tRequired );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the delay trace for the given network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManDelayTracePrint( Nwk_Man_t * pNtk )
+{
+    If_LibLut_t * pLutLib = pNtk->pLutLib;
+    Nwk_Obj_t * pNode;
+    int i, Nodes, * pCounters;
+    float tArrival, tDelta, nSteps, Num;
+    // get the library
+    if ( pLutLib && pLutLib->LutMax < Nwk_ManGetFaninMax(pNtk) )
+    {
+        printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", 
+            pLutLib->LutMax, Nwk_ManGetFaninMax(pNtk) );
+        return;
+    }
+    // decide how many steps
+    nSteps = pLutLib ? 20 : Nwk_ManLevelMax(pNtk);
+    pCounters = ABC_ALLOC( int, nSteps + 1 );
+    memset( pCounters, 0, sizeof(int)*(nSteps + 1) );
+    // perform delay trace
+    tArrival = Nwk_ManDelayTraceLut( pNtk );
+    tDelta = tArrival / nSteps;
+    // count how many nodes have slack in the corresponding intervals
+    Nwk_ManForEachNode( pNtk, pNode, i )
+    {
+        if ( Nwk_ObjFaninNum(pNode) == 0 )
+            continue;
+        Num = Nwk_ObjSlack(pNode) / tDelta;
+        if ( Num > nSteps )
+            continue;
+        assert( Num >=0 && Num <= nSteps );
+        pCounters[(int)Num]++;
+    }
+    // print the results
+    printf( "Max delay = %6.2f. Delay trace using %s model:\n", tArrival, pLutLib? "LUT library" : "unit-delay" );
+    Nodes = 0;
+    for ( i = 0; i < nSteps; i++ )
+    {
+        Nodes += pCounters[i];
+        printf( "%3d %s : %5d  (%6.2f %%)\n", pLutLib? 5*(i+1) : i+1, 
+            pLutLib? "%":"lev", Nodes, 100.0*Nodes/Nwk_ManNodeNum(pNtk) );
+    }
+    ABC_FREE( pCounters );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts node into the queue of nodes sorted by level.]
+
+  Description [The inserted node should not go before the current position 
+  given by iCurrent. If the arrival times are computed, the nodes are sorted
+  in the increasing order of levels. If the required times are computed, 
+  the nodes are sorted in the decreasing order of levels.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_NodeUpdateAddToQueue( Vec_Ptr_t * vQueue, Nwk_Obj_t * pObj, int iCurrent, int fArrival )
+{
+    Nwk_Obj_t * pTemp1, * pTemp2;
+    int i;
+    Vec_PtrPush( vQueue, pObj );
+    for ( i = Vec_PtrSize(vQueue) - 1; i > iCurrent + 1; i-- )
+    {
+        pTemp1 = (Nwk_Obj_t *)vQueue->pArray[i];
+        pTemp2 = (Nwk_Obj_t *)vQueue->pArray[i-1];
+        if ( fArrival )
+        {
+            if ( Nwk_ObjLevel(pTemp2) <= Nwk_ObjLevel(pTemp1) )
+                break;
+        }
+        else
+        {
+            if ( Nwk_ObjLevel(pTemp2) >= Nwk_ObjLevel(pTemp1) )
+                break;
+        }
+        vQueue->pArray[i-1] = pTemp1;
+        vQueue->pArray[i]   = pTemp2;
+    }
+    // verification
+    for ( i = iCurrent + 1; i < Vec_PtrSize(vQueue) - 1; i++ )
+    {
+        pTemp1 = (Nwk_Obj_t *)vQueue->pArray[i];
+        pTemp2 = (Nwk_Obj_t *)vQueue->pArray[i+1];
+        if ( fArrival )
+            assert( Nwk_ObjLevel(pTemp1) <= Nwk_ObjLevel(pTemp2) );
+        else
+            assert( Nwk_ObjLevel(pTemp1) >= Nwk_ObjLevel(pTemp2) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Incrementally updates arrival times of the node.]
+
+  Description [Supports variable-pin delay model and white-boxes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_NodeUpdateArrival( Nwk_Obj_t * pObj )
+{
+    Tim_Man_t * pManTime = pObj->pMan->pManTime;
+    Vec_Ptr_t * vQueue = pObj->pMan->vTemp;
+    Nwk_Obj_t * pTemp;
+    Nwk_Obj_t * pNext = NULL; // Suppress "might be used uninitialized"
+    float tArrival;
+    int iCur, k, iBox, iTerm1, nTerms;
+    assert( Nwk_ObjIsNode(pObj) );
+    // verify the arrival time
+    tArrival = Nwk_NodeComputeArrival( pObj, 1 );
+    assert( Nwk_ManTimeLess( tArrival, Nwk_ObjRequired(pObj), (float)0.01 ) );
+    // initialize the queue with the node
+    Vec_PtrClear( vQueue );
+    Vec_PtrPush( vQueue, pObj );
+    pObj->MarkA = 1;
+    // process objects
+    if ( pManTime )
+        Tim_ManIncrementTravId( pManTime );
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vQueue, pTemp, iCur )
+    {
+        pTemp->MarkA = 0;
+        tArrival = Nwk_NodeComputeArrival( pTemp, 1 );
+        if ( Nwk_ObjIsCi(pTemp) && pManTime )
+            tArrival = Tim_ManGetCiArrival( pManTime, pTemp->PioId );
+        if ( Nwk_ManTimeEqual( tArrival, Nwk_ObjArrival(pTemp), (float)0.01 ) )
+            continue;
+        Nwk_ObjSetArrival( pTemp, tArrival );
+        // add the fanouts to the queue
+        if ( Nwk_ObjIsCo(pTemp) )
+        {
+            if ( pManTime )
+            {
+                iBox = Tim_ManBoxForCo( pManTime, pTemp->PioId );
+                if ( iBox >= 0 ) // this CO is an input of the box
+                {
+                    // it may happen that a box-input (CO) was already marked as visited
+                    // when some other box-input of the same box was visited - here we undo this
+                    if ( Tim_ManIsCoTravIdCurrent( pManTime, pTemp->PioId ) )
+                        Tim_ManSetPreviousTravIdBoxInputs( pManTime, iBox );
+                    Tim_ManSetCoArrival( pManTime, pTemp->PioId, tArrival );
+                    Tim_ManSetCurrentTravIdBoxInputs( pManTime, iBox );
+                    iTerm1 = Tim_ManBoxOutputFirst( pManTime, iBox );
+                    nTerms = Tim_ManBoxOutputNum( pManTime, iBox );
+                    for ( k = 0; k < nTerms; k++ )
+                    {
+                        pNext = Nwk_ManCi(pNext->pMan, iTerm1 + k);
+                        if ( pNext->MarkA )
+                            continue;
+                        Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 1 );
+                        pNext->MarkA = 1;
+                    }
+                }
+            }
+        }
+        else
+        {
+            Nwk_ObjForEachFanout( pTemp, pNext, k )
+            {
+                if ( pNext->MarkA )
+                    continue;
+                Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 1 );
+                pNext->MarkA = 1;
+            }
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Incrementally updates required times of the node.]
+
+  Description [Supports variable-pin delay model and white-boxes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_NodeUpdateRequired( Nwk_Obj_t * pObj )
+{
+    Tim_Man_t * pManTime = pObj->pMan->pManTime;
+    Vec_Ptr_t * vQueue = pObj->pMan->vTemp;
+    Nwk_Obj_t * pTemp;
+    Nwk_Obj_t * pNext = NULL; // Suppress "might be used uninitialized"
+    float tRequired;
+    int iCur, k, iBox, iTerm1, nTerms;
+    assert( Nwk_ObjIsNode(pObj) );
+    // make sure the node's required time remained the same
+    tRequired = Nwk_NodeComputeRequired( pObj, 1 );
+    assert( Nwk_ManTimeEqual( tRequired, Nwk_ObjRequired(pObj), (float)0.01 ) );
+    // initialize the queue with the node's faninsa and the old node's fanins
+    Vec_PtrClear( vQueue );
+    Nwk_ObjForEachFanin( pObj, pNext, k )
+    {
+        if ( pNext->MarkA )
+            continue;
+        Nwk_NodeUpdateAddToQueue( vQueue, pNext, -1, 0 );
+        pNext->MarkA = 1;
+    }
+    // process objects
+    if ( pManTime )
+        Tim_ManIncrementTravId( pManTime );
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vQueue, pTemp, iCur )
+    {
+        pTemp->MarkA = 0;
+        tRequired = Nwk_NodeComputeRequired( pTemp, 1 );
+        if ( Nwk_ObjIsCo(pTemp) && pManTime )
+            tRequired = Tim_ManGetCoRequired( pManTime, pTemp->PioId );
+        if ( Nwk_ManTimeEqual( tRequired, Nwk_ObjRequired(pTemp), (float)0.01 ) )
+            continue;
+        Nwk_ObjSetRequired( pTemp, tRequired );
+        // add the fanins to the queue
+        if ( Nwk_ObjIsCi(pTemp) )
+        {
+            if ( pManTime )
+            {
+                iBox = Tim_ManBoxForCi( pManTime, pTemp->PioId );
+                if ( iBox >= 0 ) // this CI is an output of the box
+                {
+                    // it may happen that a box-output (CI) was already marked as visited
+                    // when some other box-output of the same box was visited - here we undo this
+                    if ( Tim_ManIsCiTravIdCurrent( pManTime, pTemp->PioId ) )
+                        Tim_ManSetPreviousTravIdBoxOutputs( pManTime, iBox );
+                    Tim_ManSetCiRequired( pManTime, pTemp->PioId, tRequired );
+                    Tim_ManSetCurrentTravIdBoxOutputs( pManTime, iBox );
+                    iTerm1 = Tim_ManBoxInputFirst( pManTime, iBox );
+                    nTerms = Tim_ManBoxInputNum( pManTime, iBox );
+                    for ( k = 0; k < nTerms; k++ )
+                    {
+                        pNext = Nwk_ManCo(pNext->pMan, iTerm1 + k);
+                        if ( pNext->MarkA )
+                            continue;
+                        Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 0 );
+                        pNext->MarkA = 1;
+                    }
+                }
+            }
+        }
+        else
+        {
+            Nwk_ObjForEachFanin( pTemp, pNext, k )
+            {
+                if ( pNext->MarkA )
+                    continue;
+                Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 0 );
+                pNext->MarkA = 1;
+            }
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the level of the node using its fanin levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ObjLevelNew( Nwk_Obj_t * pObj )
+{
+    Tim_Man_t * pManTime = pObj->pMan->pManTime;
+    Nwk_Obj_t * pFanin;
+    int i, iBox, iTerm1, nTerms, Level = 0;
+    if ( Nwk_ObjIsCi(pObj) || Nwk_ObjIsLatch(pObj) )
+    {
+        if ( pManTime )
+        {
+            iBox = Tim_ManBoxForCi( pManTime, pObj->PioId );
+            if ( iBox >= 0 ) // this CI is an output of the box
+            {
+                iTerm1 = Tim_ManBoxInputFirst( pManTime, iBox );
+                nTerms = Tim_ManBoxInputNum( pManTime, iBox );
+                for ( i = 0; i < nTerms; i++ )
+                {
+                    pFanin = Nwk_ManCo(pObj->pMan, iTerm1 + i);
+                    Level = Abc_MaxInt( Level, Nwk_ObjLevel(pFanin) );
+                }
+                Level++;
+            }
+        }
+        return Level;
+    }
+    assert( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCo(pObj) );
+    Nwk_ObjForEachFanin( pObj, pFanin, i )
+        Level = Abc_MaxInt( Level, Nwk_ObjLevel(pFanin) );
+    return Level + (Nwk_ObjIsNode(pObj) && Nwk_ObjFaninNum(pObj) > 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Incrementally updates level of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManUpdateLevel( Nwk_Obj_t * pObj )
+{
+    Tim_Man_t * pManTime = pObj->pMan->pManTime;
+    Vec_Ptr_t * vQueue = pObj->pMan->vTemp;
+    Nwk_Obj_t * pTemp;
+    Nwk_Obj_t * pNext = NULL; // Suppress "might be used uninitialized"
+    int LevelNew, iCur, k, iBox, iTerm1, nTerms;
+    assert( Nwk_ObjIsNode(pObj) );
+    // initialize the queue with the node
+    Vec_PtrClear( vQueue );
+    Vec_PtrPush( vQueue, pObj );
+    pObj->MarkA = 1;
+    // process objects
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vQueue, pTemp, iCur )
+    {
+        pTemp->MarkA = 0;
+        LevelNew = Nwk_ObjLevelNew( pTemp );
+        if ( LevelNew == Nwk_ObjLevel(pTemp) )
+            continue;
+        Nwk_ObjSetLevel( pTemp, LevelNew );
+        // add the fanouts to the queue
+        if ( Nwk_ObjIsCo(pTemp) )
+        {
+            if ( pManTime )
+            {
+                iBox = Tim_ManBoxForCo( pManTime, pTemp->PioId );
+                if ( iBox >= 0 ) // this is not a true PO
+                {
+                    Tim_ManSetCurrentTravIdBoxInputs( pManTime, iBox );
+                    iTerm1 = Tim_ManBoxOutputFirst( pManTime, iBox );
+                    nTerms = Tim_ManBoxOutputNum( pManTime, iBox );
+                    for ( k = 0; k < nTerms; k++ )
+                    {
+                        pNext = Nwk_ManCi(pNext->pMan, iTerm1 + k);
+                        if ( pNext->MarkA )
+                            continue;
+                        Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 1 );
+                        pNext->MarkA = 1;
+                    }
+                }
+            }
+        }
+        else
+        {
+            Nwk_ObjForEachFanout( pTemp, pNext, k )
+            {
+                if ( pNext->MarkA )
+                    continue;
+                Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 1 );
+                pNext->MarkA = 1;
+            }
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the level of the node using its fanin levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManVerifyLevel( Nwk_Man_t * pNtk )
+{
+    Nwk_Obj_t * pObj;
+    int LevelNew, i;
+    Nwk_ManForEachObj( pNtk, pObj, i )
+    {
+        assert( pObj->MarkA == 0 );
+        LevelNew = Nwk_ObjLevelNew( pObj );
+        if ( Nwk_ObjLevel(pObj) != LevelNew )
+        {
+            printf( "Object %6d: Mismatch betweeh levels: Actual = %d. Correct = %d.\n", 
+                i, Nwk_ObjLevel(pObj), LevelNew );
+        }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Replaces the node and incrementally updates levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManUpdate( Nwk_Obj_t * pObj, Nwk_Obj_t * pObjNew, Vec_Vec_t * vLevels )
+{
+    assert( pObj->pMan == pObjNew->pMan );
+    assert( pObj != pObjNew );
+    assert( Nwk_ObjFanoutNum(pObj) > 0 );
+    assert( Nwk_ObjIsNode(pObj) && !Nwk_ObjIsCo(pObjNew) );
+    // transfer fanouts to the old node
+    Nwk_ObjTransferFanout( pObj, pObjNew );
+    // transfer the timing information
+    // (this is needed because updating level happens if the level has changed;
+    // when we set the old level, it will be recomputed by the level updating
+    // procedure, which will update level of other nodes if there is a difference)
+    pObjNew->Level = pObj->Level;
+    pObjNew->tArrival = pObj->tArrival;
+    pObjNew->tRequired = pObj->tRequired;
+    // update required times of the old fanins
+    pObj->tRequired = TIM_ETERNITY;
+    Nwk_NodeUpdateRequired( pObj );
+    // remove the old node
+    Nwk_ManDeleteNode_rec( pObj );
+    // update the information of the new node
+    Nwk_ManUpdateLevel( pObjNew );
+    Nwk_NodeUpdateArrival( pObjNew );
+    Nwk_NodeUpdateRequired( pObjNew );
+//Nwk_ManVerifyTiming( pObjNew->pMan );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/nwk/nwkUtil.c b/abc-build/src/opt/nwk/nwkUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwkUtil.c
@@ -0,0 +1,644 @@
+/**CFile****************************************************************
+
+  FileName    [nwkUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Logic network representation.]
+
+  Synopsis    [Various utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwkUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <math.h>
+#include "nwk.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Increments the current traversal ID of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManIncrementTravId( Nwk_Man_t * pNtk )
+{
+    Nwk_Obj_t * pObj;
+    int i;
+    if ( pNtk->nTravIds >= (1<<26)-1 )
+    {
+        pNtk->nTravIds = 0;
+        Nwk_ManForEachObj( pNtk, pObj, i )
+            pObj->TravId = 0;
+    }
+    pNtk->nTravIds++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the maximum number of fanins of a node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManGetFaninMax( Nwk_Man_t * pNtk )
+{
+    Nwk_Obj_t * pNode;
+    int i, nFaninsMax = 0;
+    Nwk_ManForEachNode( pNtk, pNode, i )
+    {
+        if ( nFaninsMax < Nwk_ObjFaninNum(pNode) )
+            nFaninsMax = Nwk_ObjFaninNum(pNode);
+    }
+    return nFaninsMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the total number of all fanins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManGetTotalFanins( Nwk_Man_t * pNtk )
+{
+    Nwk_Obj_t * pNode;
+    int i, nFanins = 0;
+    Nwk_ManForEachNode( pNtk, pNode, i )
+        nFanins += Nwk_ObjFaninNum(pNode);
+    return nFanins;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of true PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManPiNum( Nwk_Man_t * pNtk )
+{
+    Nwk_Obj_t * pNode;
+    int i, Counter = 0;
+    Nwk_ManForEachCi( pNtk, pNode, i )
+        Counter += Nwk_ObjIsPi( pNode );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of true POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManPoNum( Nwk_Man_t * pNtk )
+{
+    Nwk_Obj_t * pNode;
+    int i, Counter = 0;
+    Nwk_ManForEachCo( pNtk, pNode, i )
+        Counter += Nwk_ObjIsPo( pNode );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the number of AIG nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManGetAigNodeNum( Nwk_Man_t * pNtk )
+{
+    Nwk_Obj_t * pNode;
+    int i, nNodes = 0;
+    Nwk_ManForEachNode( pNtk, pNode, i )
+    {
+        if ( pNode->pFunc == NULL )
+        {
+            printf( "Nwk_ManGetAigNodeNum(): Local AIG of node %d is not assigned.\n", pNode->Id );
+            continue;
+        }
+        if ( Nwk_ObjFaninNum(pNode) < 2 )
+            continue;
+        nNodes += Hop_DagSize( pNode->pFunc );
+    }
+    return nNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure used for sorting the nodes in increasing order of levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_NodeCompareLevelsIncrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 )
+{
+    int Diff = (*pp1)->Level - (*pp2)->Level;
+    if ( Diff < 0 )
+        return -1;
+    if ( Diff > 0 ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure used for sorting the nodes in decreasing order of levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_NodeCompareLevelsDecrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 )
+{
+    int Diff = (*pp1)->Level - (*pp2)->Level;
+    if ( Diff > 0 )
+        return -1;
+    if ( Diff < 0 ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ObjPrint( Nwk_Obj_t * pObj )
+{
+    Nwk_Obj_t * pNext;
+    int i;
+    printf( "ObjId = %5d.  ", pObj->Id );
+    if ( Nwk_ObjIsPi(pObj) )
+        printf( "PI" );
+    if ( Nwk_ObjIsPo(pObj) )
+        printf( "PO" );
+    if ( Nwk_ObjIsNode(pObj) )
+        printf( "Node" );
+    printf( "   Fanins = " );
+    Nwk_ObjForEachFanin( pObj, pNext, i )
+        printf( "%d ", pNext->Id );
+    printf( "   Fanouts = " );
+    Nwk_ObjForEachFanout( pObj, pNext, i )
+        printf( "%d ", pNext->Id );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dumps the BLIF file for the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManDumpBlif( Nwk_Man_t * pNtk, char * pFileName, Vec_Ptr_t * vPiNames, Vec_Ptr_t * vPoNames )
+{
+    FILE * pFile;
+    Vec_Ptr_t * vNodes;
+    Vec_Int_t * vTruth;
+    Vec_Int_t * vCover;
+    Nwk_Obj_t * pObj, * pFanin;
+    Aig_MmFlex_t * pMem;
+    char * pSop = NULL;
+    unsigned * pTruth;
+    int i, k, nDigits;
+    if ( Nwk_ManPoNum(pNtk) == 0 )
+    {
+        printf( "Nwk_ManDumpBlif(): Network does not have POs.\n" );
+        return;
+    }
+    // collect nodes in the DFS order
+    nDigits = Abc_Base10Log( Nwk_ManObjNumMax(pNtk) );
+    // write the file 
+    pFile = fopen( pFileName, "w" );
+    fprintf( pFile, "# BLIF file written by procedure Nwk_ManDumpBlif()\n" );
+//    fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" );
+    fprintf( pFile, ".model %s\n", pNtk->pName );
+    // write PIs
+    fprintf( pFile, ".inputs" );
+    Nwk_ManForEachCi( pNtk, pObj, i )
+        if ( vPiNames )
+            fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, i) );
+        else
+            fprintf( pFile, " n%0*d", nDigits, pObj->Id );
+    fprintf( pFile, "\n" );
+    // write POs
+    fprintf( pFile, ".outputs" );
+    Nwk_ManForEachCo( pNtk, pObj, i )
+        if ( vPoNames )
+            fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPoNames, i) );
+        else
+            fprintf( pFile, " n%0*d", nDigits, pObj->Id );
+    fprintf( pFile, "\n" );
+    // write nodes
+    pMem = Aig_MmFlexStart();
+    vTruth = Vec_IntAlloc( 1 << 16 );
+    vCover = Vec_IntAlloc( 1 << 16 );
+    vNodes = Nwk_ManDfs( pNtk );
+    Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i )
+    {
+        if ( !Nwk_ObjIsNode(pObj) )
+            continue;
+        // derive SOP for the AIG
+        pTruth = Hop_ManConvertAigToTruth( pNtk->pManHop, Hop_Regular(pObj->pFunc), Nwk_ObjFaninNum(pObj), vTruth, 0 );
+        if ( Hop_IsComplement(pObj->pFunc) )
+            Kit_TruthNot( pTruth, pTruth, Nwk_ObjFaninNum(pObj) );
+        pSop = Kit_PlaFromTruth( pMem, pTruth, Nwk_ObjFaninNum(pObj), vCover );
+        // write the node
+        fprintf( pFile, ".names" );
+        if ( !Kit_TruthIsConst0(pTruth, Nwk_ObjFaninNum(pObj)) && !Kit_TruthIsConst1(pTruth, Nwk_ObjFaninNum(pObj)) )
+        {
+            Nwk_ObjForEachFanin( pObj, pFanin, k )
+                if ( vPiNames && Nwk_ObjIsPi(pFanin) )
+                    fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Nwk_ObjPioNum(pFanin)) );
+                else
+                    fprintf( pFile, " n%0*d", nDigits, pFanin->Id );
+        }
+        fprintf( pFile, " n%0*d\n", nDigits, pObj->Id );
+        // write the function
+        fprintf( pFile, "%s", pSop );
+    }
+    Vec_IntFree( vCover );
+    Vec_IntFree( vTruth );
+    Vec_PtrFree( vNodes );
+    Aig_MmFlexStop( pMem, 0 );
+    // write POs
+    Nwk_ManForEachCo( pNtk, pObj, i )
+    {
+        fprintf( pFile, ".names" );
+        if ( vPiNames && Nwk_ObjIsPi(Nwk_ObjFanin0(pObj)) )
+            fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Nwk_ObjPioNum(Nwk_ObjFanin0(pObj))) );
+        else
+            fprintf( pFile, " n%0*d", nDigits, Nwk_ObjFanin0(pObj)->Id );
+        if ( vPoNames )
+            fprintf( pFile, " %s\n", (char*)Vec_PtrEntry(vPoNames, Nwk_ObjPioNum(pObj)) );
+        else
+            fprintf( pFile, " n%0*d\n", nDigits, pObj->Id );
+        fprintf( pFile, "%d 1\n", !pObj->fInvert );
+    }
+    fprintf( pFile, ".end\n\n" );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the distribution of fanins/fanouts in the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManPrintFanioNew( Nwk_Man_t * pNtk )
+{
+    char Buffer[100];
+    Nwk_Obj_t * pNode;
+    Vec_Int_t * vFanins, * vFanouts;
+    int nFanins, nFanouts, nFaninsMax, nFanoutsMax, nFaninsAll, nFanoutsAll;
+    int i, k, nSizeMax;
+
+    // determine the largest fanin and fanout
+    nFaninsMax = nFanoutsMax = 0;
+    nFaninsAll = nFanoutsAll = 0;
+    Nwk_ManForEachNode( pNtk, pNode, i )
+    {
+        nFanins  = Nwk_ObjFaninNum(pNode);
+        nFanouts = Nwk_ObjFanoutNum(pNode);
+        nFaninsAll  += nFanins;
+        nFanoutsAll += nFanouts;
+        nFaninsMax   = Abc_MaxInt( nFaninsMax, nFanins );
+        nFanoutsMax  = Abc_MaxInt( nFanoutsMax, nFanouts );
+    }
+
+    // allocate storage for fanin/fanout numbers
+    nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nFaninsMax) + 1), 10 * (Abc_Base10Log(nFanoutsMax) + 1) );
+    vFanins  = Vec_IntStart( nSizeMax );
+    vFanouts = Vec_IntStart( nSizeMax );
+
+    // count the number of fanins and fanouts
+    Nwk_ManForEachNode( pNtk, pNode, i )
+    {
+        nFanins  = Nwk_ObjFaninNum(pNode);
+        nFanouts = Nwk_ObjFanoutNum(pNode);
+//        nFanouts = Nwk_NodeMffcSize(pNode);
+
+        if ( nFanins < 10 )
+            Vec_IntAddToEntry( vFanins, nFanins, 1 );
+        else if ( nFanins < 100 )
+            Vec_IntAddToEntry( vFanins, 10 + nFanins/10, 1 );
+        else if ( nFanins < 1000 )
+            Vec_IntAddToEntry( vFanins, 20 + nFanins/100, 1 );
+        else if ( nFanins < 10000 )
+            Vec_IntAddToEntry( vFanins, 30 + nFanins/1000, 1 );
+        else if ( nFanins < 100000 )
+            Vec_IntAddToEntry( vFanins, 40 + nFanins/10000, 1 );
+        else if ( nFanins < 1000000 )
+            Vec_IntAddToEntry( vFanins, 50 + nFanins/100000, 1 );
+        else if ( nFanins < 10000000 )
+            Vec_IntAddToEntry( vFanins, 60 + nFanins/1000000, 1 );
+
+        if ( nFanouts < 10 )
+            Vec_IntAddToEntry( vFanouts, nFanouts, 1 );
+        else if ( nFanouts < 100 )
+            Vec_IntAddToEntry( vFanouts, 10 + nFanouts/10, 1 );
+        else if ( nFanouts < 1000 )
+            Vec_IntAddToEntry( vFanouts, 20 + nFanouts/100, 1 );
+        else if ( nFanouts < 10000 )
+            Vec_IntAddToEntry( vFanouts, 30 + nFanouts/1000, 1 );
+        else if ( nFanouts < 100000 )
+            Vec_IntAddToEntry( vFanouts, 40 + nFanouts/10000, 1 );
+        else if ( nFanouts < 1000000 )
+            Vec_IntAddToEntry( vFanouts, 50 + nFanouts/100000, 1 );
+        else if ( nFanouts < 10000000 )
+            Vec_IntAddToEntry( vFanouts, 60 + nFanouts/1000000, 1 );
+    }
+
+    printf( "The distribution of fanins and fanouts in the network:\n" );
+    printf( "         Number   Nodes with fanin  Nodes with fanout\n" );
+    for ( k = 0; k < nSizeMax; k++ )
+    {
+        if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 )
+            continue;
+        if ( k < 10 )
+            printf( "%15d : ", k );
+        else
+        {
+            sprintf( Buffer, "%d - %d", (int)pow((double)10, k/10) * (k%10), (int)pow((double)10, k/10) * (k%10+1) - 1 ); 
+            printf( "%15s : ", Buffer );
+        }
+        if ( vFanins->pArray[k] == 0 )
+            printf( "              " );
+        else
+            printf( "%12d  ", vFanins->pArray[k] );
+        printf( "    " );
+        if ( vFanouts->pArray[k] == 0 )
+            printf( "              " );
+        else
+            printf( "%12d  ", vFanouts->pArray[k] );
+        printf( "\n" );
+    }
+    Vec_IntFree( vFanins );
+    Vec_IntFree( vFanouts );
+
+    printf( "Fanins: Max = %d. Ave = %.2f.  Fanouts: Max = %d. Ave =  %.2f.\n", 
+        nFaninsMax,  1.0*nFaninsAll/Nwk_ManNodeNum(pNtk), 
+        nFanoutsMax, 1.0*nFanoutsAll/Nwk_ManNodeNum(pNtk)  );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the temporary marks of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManCleanMarks( Nwk_Man_t * pMan )
+{
+    Nwk_Obj_t * pObj;
+    int i;
+    Nwk_ManForEachObj( pMan, pObj, i )
+        pObj->MarkA = pObj->MarkB = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Minimizes the support of all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManMinimumBaseNode( Nwk_Obj_t * pObj, Vec_Int_t * vTruth, int fVerbose )
+{
+    unsigned * pTruth;
+    Nwk_Obj_t * pFanin, * pObjNew;
+    Nwk_Man_t * pNtk = pObj->pMan;
+    int uSupp, nSuppSize, k, Counter = 0;
+    pTruth = Hop_ManConvertAigToTruth( pNtk->pManHop, Hop_Regular(pObj->pFunc), Nwk_ObjFaninNum(pObj), vTruth, 0 );
+    nSuppSize = Kit_TruthSupportSize(pTruth, Nwk_ObjFaninNum(pObj));
+    if ( nSuppSize == Nwk_ObjFaninNum(pObj) )
+        return 0;
+    Counter++;
+    uSupp = Kit_TruthSupport( pTruth, Nwk_ObjFaninNum(pObj) );
+    // create new node with the given support
+    pObjNew = Nwk_ManCreateNode( pNtk, nSuppSize, Nwk_ObjFanoutNum(pObj) );
+    Nwk_ObjForEachFanin( pObj, pFanin, k )
+        if ( uSupp & (1 << k) )
+            Nwk_ObjAddFanin( pObjNew, pFanin );
+    pObjNew->pFunc = Hop_Remap( pNtk->pManHop, pObj->pFunc, uSupp, Nwk_ObjFaninNum(pObj) );
+    if ( fVerbose )
+        printf( "Reducing node %d fanins from %d to %d.\n", 
+            pObj->Id, Nwk_ObjFaninNum(pObj), Nwk_ObjFaninNum(pObjNew) );
+    Nwk_ObjReplace( pObj, pObjNew );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Minimizes the support of all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Nwk_ManMinimumBaseInt( Nwk_Man_t * pNtk, int fVerbose )
+{
+    Vec_Int_t * vTruth;
+    Nwk_Obj_t * pObj;
+    int i, Counter = 0;
+    vTruth = Vec_IntAlloc( 1 << 16 );
+    Nwk_ManForEachNode( pNtk, pObj, i )
+        Counter += Nwk_ManMinimumBaseNode( pObj, vTruth, fVerbose );
+    if ( fVerbose && Counter )
+        printf( "Support minimization reduced support of %d nodes.\n", Counter );
+    Vec_IntFree( vTruth );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Minimizes the support of all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManMinimumBaseRec( Nwk_Man_t * pNtk, int fVerbose )
+{
+    int i;
+    abctime clk = Abc_Clock();
+    for ( i = 0; Nwk_ManMinimumBaseInt( pNtk, fVerbose ); i++ );
+    ABC_PRT( "Minbase", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Minimizes the support of all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManMinimumBase( Nwk_Man_t * pNtk, int fVerbose )
+{
+    Vec_Int_t * vTruth;
+    Nwk_Obj_t * pObj;
+    int i, Counter = 0;
+    vTruth = Vec_IntAlloc( 1 << 16 );
+    Nwk_ManForEachNode( pNtk, pObj, i )
+        Counter += Nwk_ManMinimumBaseNode( pObj, vTruth, fVerbose );
+    if ( fVerbose && Counter )
+        printf( "Support minimization reduced support of %d nodes.\n", Counter );
+    Vec_IntFree( vTruth );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Minimizes the support of all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManRemoveDupFaninsNode( Nwk_Obj_t * pObj, int iFan0, int iFan1, Vec_Int_t * vTruth )
+{
+    Hop_Man_t * pManHop = pObj->pMan->pManHop;
+//    Nwk_Obj_t * pFanin0 = pObj->pFanio[iFan0];
+//    Nwk_Obj_t * pFanin1 = pObj->pFanio[iFan1];
+    assert( pObj->pFanio[iFan0] == pObj->pFanio[iFan1] );
+    pObj->pFunc = Hop_Compose( pManHop, pObj->pFunc, Hop_IthVar(pManHop,iFan0), iFan1 );
+    Nwk_ManMinimumBaseNode( pObj, vTruth, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Minimizes the support of all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Nwk_ManRemoveDupFanins( Nwk_Man_t * pNtk, int fVerbose )
+{
+    Vec_Int_t * vTruth;
+    Nwk_Obj_t * pObj;
+    int i, k, m, fFound;
+    // check if the nodes have duplicated fanins
+    vTruth = Vec_IntAlloc( 1 << 16 );
+    Nwk_ManForEachNode( pNtk, pObj, i )
+    {
+        fFound = 0;
+        for ( k = 0; k < pObj->nFanins; k++ )
+        {
+            for ( m = k + 1; m < pObj->nFanins; m++ )
+                if ( pObj->pFanio[k] == pObj->pFanio[m] )
+                {
+                    if ( fVerbose )
+                        printf( "Removing duplicated fanins of node %d (fanins %d and %d).\n", 
+                            pObj->Id, pObj->pFanio[k]->Id, pObj->pFanio[m]->Id );
+                    Nwk_ManRemoveDupFaninsNode( pObj, k, m, vTruth );
+                    fFound = 1;
+                    break;
+                }
+            if ( fFound )
+                break;
+        }
+    }
+    Vec_IntFree( vTruth );
+//    Nwk_ManMinimumBase( pNtk, fVerbose );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/nwk/nwk_.c b/abc-build/src/opt/nwk/nwk_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/nwk/nwk_.c
@@ -0,0 +1,52 @@
+/**CFile****************************************************************
+
+  FileName    [nwk_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Netlist representation.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: nwk_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nwk.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/res/module.make b/abc-build/src/opt/res/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/res/module.make
@@ -0,0 +1,7 @@
+SRC +=  src/opt/res/resCore.c \
+	src/opt/res/resDivs.c \
+	src/opt/res/resFilter.c \
+	src/opt/res/resSat.c \
+	src/opt/res/resSim.c \
+	src/opt/res/resStrash.c \
+	src/opt/res/resWin.c
diff --git a/abc-build/src/opt/res/res.h b/abc-build/src/opt/res/res.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/res/res.h
@@ -0,0 +1,79 @@
+/**CFile****************************************************************
+
+  FileName    [res.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resynthesis package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 15, 2007.]
+
+  Revision    [$Id: res.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__opt__res__res_h
+#define ABC__opt__res__res_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Res_Par_t_ Res_Par_t;
+struct Res_Par_t_
+{
+    // general parameters
+    int           nWindow;       // window size
+    int           nGrowthLevel;  // the maximum allowed growth in level after one iteration of resynthesis
+    int           nSimWords;     // the number of simulation words 
+    int           nCands;        // the number of candidates to try
+    int           fArea;         // performs optimization for area
+    int           fDelay;        // performs optimization for delay
+    int           fVerbose;      // enable basic stats
+    int           fVeryVerbose;  // enable detailed stats
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== resCore.c ==========================================================*/
+extern int        Abc_NtkResynthesize( Abc_Ntk_t * pNtk, Res_Par_t * pPars );
+
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/res/resCore.c b/abc-build/src/opt/res/resCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/res/resCore.c
@@ -0,0 +1,427 @@
+/**CFile****************************************************************
+
+  FileName    [resCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resynthesis package.]
+
+  Synopsis    [Top-level resynthesis procedure.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 15, 2007.]
+
+  Revision    [$Id: resCore.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "resInt.h"
+#include "bool/kit/kit.h"
+#include "sat/bsat/satStore.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Res_Man_t_ Res_Man_t;
+struct Res_Man_t_
+{
+    // general parameters
+    Res_Par_t *   pPars;
+    // specialized manager
+    Res_Win_t *   pWin;          // windowing manager
+    Abc_Ntk_t *   pAig;          // the strashed window
+    Res_Sim_t *   pSim;          // simulation manager
+    Sto_Man_t *   pCnf;          // the CNF of the SAT problem
+    Int_Man_t *   pMan;          // interpolation manager;
+    Vec_Int_t *   vMem;          // memory for intermediate SOPs
+    Vec_Vec_t *   vResubs;       // resubstitution candidates of the AIG
+    Vec_Vec_t *   vResubsW;      // resubstitution candidates of the window
+    Vec_Vec_t *   vLevels;       // levelized structure for updating
+    // statistics
+    int           nWins;         // the number of windows tried
+    int           nWinNodes;     // the total number of window nodes
+    int           nDivNodes;     // the total number of divisors
+    int           nWinsTriv;     // the total number of trivial windows
+    int           nWinsUsed;     // the total number of useful windows (with at least one candidate)
+    int           nConstsUsed;   // the total number of constant nodes under ODC
+    int           nCandSets;     // the total number of candidates
+    int           nProvedSets;   // the total number of proved groups
+    int           nSimEmpty;     // the empty simulation info
+    int           nTotalNets;    // the total number of nets
+    int           nTotalNodes;   // the total number of nodess
+    int           nTotalNets2;   // the total number of nets
+    int           nTotalNodes2;  // the total number of nodess
+    // runtime
+    abctime       timeWin;       // windowing
+    abctime       timeDiv;       // divisors
+    abctime       timeAig;       // strashing
+    abctime       timeSim;       // simulation
+    abctime       timeCand;      // resubstitution candidates
+    abctime       timeSatTotal;  // SAT solving total 
+    abctime       timeSatSat;    // SAT solving (sat calls)
+    abctime       timeSatUnsat;  // SAT solving (unsat calls)
+    abctime       timeSatSim;    // SAT solving (simulation)
+    abctime       timeInt;       // interpolation 
+    abctime       timeUpd;       // updating  
+    abctime       timeTotal;     // total runtime
+};
+
+extern Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph );
+
+extern abctime s_ResynTime;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocate resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Res_Man_t * Res_ManAlloc( Res_Par_t * pPars )
+{
+    Res_Man_t * p;
+    p = ABC_ALLOC( Res_Man_t, 1 );
+    memset( p, 0, sizeof(Res_Man_t) );
+    assert( pPars->nWindow > 0 && pPars->nWindow < 100 );
+    assert( pPars->nCands > 0 && pPars->nCands < 100 );
+    p->pPars = pPars;
+    p->pWin = Res_WinAlloc();
+    p->pSim = Res_SimAlloc( pPars->nSimWords );
+    p->pMan = Int_ManAlloc();
+    p->vMem = Vec_IntAlloc( 0 );
+    p->vResubs  = Vec_VecStart( pPars->nCands );
+    p->vResubsW = Vec_VecStart( pPars->nCands );
+    p->vLevels  = Vec_VecStart( 32 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocate resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_ManFree( Res_Man_t * p )
+{
+    if ( p->pPars->fVerbose )
+    {
+        printf( "Reduction in nodes = %5d. (%.2f %%) ", 
+            p->nTotalNodes-p->nTotalNodes2, 
+            100.0*(p->nTotalNodes-p->nTotalNodes2)/p->nTotalNodes );
+        printf( "Reduction in edges = %5d. (%.2f %%) ", 
+            p->nTotalNets-p->nTotalNets2, 
+            100.0*(p->nTotalNets-p->nTotalNets2)/p->nTotalNets );
+        printf( "\n" );
+
+        printf( "Winds = %d. ", p->nWins );
+        printf( "Nodes = %d. (Ave = %5.1f)  ", p->nWinNodes, 1.0*p->nWinNodes/p->nWins );
+        printf( "Divs = %d. (Ave = %5.1f)  ",  p->nDivNodes, 1.0*p->nDivNodes/p->nWins );
+        printf( "\n" );
+        printf( "WinsTriv = %d. ", p->nWinsTriv );
+        printf( "SimsEmpt = %d. ", p->nSimEmpty );
+        printf( "Const = %d. ", p->nConstsUsed );
+        printf( "WindUsed = %d. ", p->nWinsUsed );
+        printf( "Cands = %d. ", p->nCandSets );
+        printf( "Proved = %d.", p->nProvedSets );
+        printf( "\n" );
+
+        ABC_PRTP( "Windowing  ", p->timeWin,      p->timeTotal );
+        ABC_PRTP( "Divisors   ", p->timeDiv,      p->timeTotal );
+        ABC_PRTP( "Strashing  ", p->timeAig,      p->timeTotal );
+        ABC_PRTP( "Simulation ", p->timeSim,      p->timeTotal );
+        ABC_PRTP( "Candidates ", p->timeCand,     p->timeTotal );
+        ABC_PRTP( "SAT solver ", p->timeSatTotal, p->timeTotal );
+        ABC_PRTP( "    sat    ", p->timeSatSat,   p->timeTotal );
+        ABC_PRTP( "    unsat  ", p->timeSatUnsat, p->timeTotal );
+        ABC_PRTP( "    simul  ", p->timeSatSim,   p->timeTotal );
+        ABC_PRTP( "Interpol   ", p->timeInt,      p->timeTotal );
+        ABC_PRTP( "Undating   ", p->timeUpd,      p->timeTotal );
+        ABC_PRTP( "TOTAL      ", p->timeTotal,    p->timeTotal );
+    }
+    Res_WinFree( p->pWin );
+    if ( p->pAig ) Abc_NtkDelete( p->pAig );
+    Res_SimFree( p->pSim );
+    if ( p->pCnf ) Sto_ManFree( p->pCnf );
+    Int_ManFree( p->pMan );
+    Vec_IntFree( p->vMem );
+    Vec_VecFree( p->vResubs );
+    Vec_VecFree( p->vResubsW );
+    Vec_VecFree( p->vLevels );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Incrementally updates level of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_UpdateNetwork( Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc, Vec_Vec_t * vLevels )
+{
+    Abc_Obj_t * pObjNew, * pFanin;
+    int k;
+
+    // create the new node
+    pObjNew = Abc_NtkCreateNode( pObj->pNtk );
+    pObjNew->pData = pFunc;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pFanin, k )
+        Abc_ObjAddFanin( pObjNew, pFanin );
+    // replace the old node by the new node
+//printf( "Replacing node " ); Abc_ObjPrint( stdout, pObj );
+//printf( "Inserting node " ); Abc_ObjPrint( stdout, pObjNew );
+    // update the level of the node
+    Abc_NtkUpdate( pObj, pObjNew, vLevels );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Entrace into the resynthesis package.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkResynthesize( Abc_Ntk_t * pNtk, Res_Par_t * pPars )
+{
+    ProgressBar * pProgress;
+    Res_Man_t * p;
+    Abc_Obj_t * pObj;
+    Hop_Obj_t * pFunc;
+    Kit_Graph_t * pGraph;
+    Vec_Ptr_t * vFanins;
+    unsigned * puTruth;
+    int i, k, RetValue, nNodesOld, nFanins, nFaninsMax;
+    abctime clk, clkTotal = Abc_Clock();
+
+    // start the manager
+    p = Res_ManAlloc( pPars );
+    p->nTotalNets = Abc_NtkGetTotalFanins(pNtk);
+    p->nTotalNodes = Abc_NtkNodeNum(pNtk);
+    nFaninsMax = Abc_NtkGetFaninMax(pNtk);
+    if ( nFaninsMax > 8 )
+        nFaninsMax = 8;
+
+    // perform the network sweep
+    Abc_NtkSweep( pNtk, 0 );
+
+    // convert into the AIG
+    if ( !Abc_NtkToAig(pNtk) )
+    {
+        fprintf( stdout, "Converting to BDD has failed.\n" );
+        Res_ManFree( p );
+        return 0;
+    }
+    assert( Abc_NtkHasAig(pNtk) );
+
+    // set the number of levels
+    Abc_NtkLevel( pNtk );
+    Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel );
+
+    // try resynthesizing nodes in the topological order
+    nNodesOld = Abc_NtkObjNumMax(pNtk);
+    pProgress = Extra_ProgressBarStart( stdout, nNodesOld );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        Extra_ProgressBarUpdate( pProgress, i, NULL );
+        if ( !Abc_ObjIsNode(pObj) )
+            continue;
+        if ( Abc_ObjFaninNum(pObj) > 8 )
+            continue;
+        if ( pObj->Id > nNodesOld )
+            break;
+
+        // create the window for this node
+clk = Abc_Clock();
+        RetValue = Res_WinCompute( pObj, p->pPars->nWindow/10, p->pPars->nWindow%10, p->pWin );
+p->timeWin += Abc_Clock() - clk;
+        if ( !RetValue )
+            continue;
+        p->nWinsTriv += Res_WinIsTrivial( p->pWin );
+
+        if ( p->pPars->fVeryVerbose )
+        {
+            printf( "%5d (lev=%2d) : ", pObj->Id, pObj->Level );
+            printf( "Win = %3d/%3d/%4d/%3d   ", 
+                Vec_PtrSize(p->pWin->vLeaves), 
+                Vec_PtrSize(p->pWin->vBranches),
+                Vec_PtrSize(p->pWin->vNodes), 
+                Vec_PtrSize(p->pWin->vRoots) );
+        }
+
+        // collect the divisors
+clk = Abc_Clock();
+        Res_WinDivisors( p->pWin, Abc_ObjRequiredLevel(pObj) - 1 );
+p->timeDiv += Abc_Clock() - clk;
+
+        p->nWins++;
+        p->nWinNodes += Vec_PtrSize(p->pWin->vNodes);
+        p->nDivNodes += Vec_PtrSize( p->pWin->vDivs);
+
+        if ( p->pPars->fVeryVerbose )
+        {
+            printf( "D = %3d ", Vec_PtrSize(p->pWin->vDivs) );
+            printf( "D+ = %3d ", p->pWin->nDivsPlus );
+        }
+
+        // create the AIG for the window
+clk = Abc_Clock();
+        if ( p->pAig ) Abc_NtkDelete( p->pAig );
+        p->pAig = Res_WndStrash( p->pWin );
+p->timeAig += Abc_Clock() - clk;
+
+        if ( p->pPars->fVeryVerbose )
+        {
+            printf( "AIG = %4d ", Abc_NtkNodeNum(p->pAig) );
+            printf( "\n" );
+        }
+ 
+        // prepare simulation info
+clk = Abc_Clock();
+        RetValue = Res_SimPrepare( p->pSim, p->pAig, Vec_PtrSize(p->pWin->vLeaves), 0 ); //p->pPars->fVerbose );
+p->timeSim += Abc_Clock() - clk;
+        if ( !RetValue )
+        {
+            p->nSimEmpty++;
+            continue;
+        }
+
+        // consider the case of constant node
+        if ( p->pSim->fConst0 || p->pSim->fConst1 )
+        {
+            p->nConstsUsed++;
+
+            pFunc = p->pSim->fConst1? Hop_ManConst1((Hop_Man_t *)pNtk->pManFunc) : Hop_ManConst0((Hop_Man_t *)pNtk->pManFunc);
+            vFanins = Vec_VecEntry( p->vResubsW, 0 );
+            Vec_PtrClear( vFanins );
+            Res_UpdateNetwork( pObj, vFanins, pFunc, p->vLevels );
+            continue;
+        }
+
+//        printf( " " );
+
+        // find resub candidates for the node
+clk = Abc_Clock();
+        if ( p->pPars->fArea )
+            RetValue = Res_FilterCandidates( p->pWin, p->pAig, p->pSim, p->vResubs, p->vResubsW, nFaninsMax, 1 );
+        else
+            RetValue = Res_FilterCandidates( p->pWin, p->pAig, p->pSim, p->vResubs, p->vResubsW, nFaninsMax, 0 );
+p->timeCand += Abc_Clock() - clk;
+        p->nCandSets += RetValue;
+        if ( RetValue == 0 )
+            continue;
+
+//        printf( "%d(%d) ", Vec_PtrSize(p->pWin->vDivs), RetValue );
+
+        p->nWinsUsed++;
+
+        // iterate through candidate resubstitutions
+        Vec_VecForEachLevel( p->vResubs, vFanins, k )
+        {
+            if ( Vec_PtrSize(vFanins) == 0 )
+                break;
+
+            // solve the SAT problem and get clauses
+clk = Abc_Clock();
+            if ( p->pCnf ) Sto_ManFree( p->pCnf );
+            p->pCnf = (Sto_Man_t *)Res_SatProveUnsat( p->pAig, vFanins );
+            if ( p->pCnf == NULL )
+            {
+p->timeSatSat += Abc_Clock() - clk;
+//                printf( " Sat\n" );
+//                printf( "-" );
+                continue;
+            }
+p->timeSatUnsat += Abc_Clock() - clk;
+//            printf( "+" );
+
+            p->nProvedSets++;
+//            printf( " Unsat\n" );
+//            continue;
+//            printf( "Proved %d.\n", k );
+
+            // write it into a file
+//            Sto_ManDumpClauses( p->pCnf, "trace.cnf" );
+
+            // interpolate the problem if it was UNSAT
+clk = Abc_Clock();
+            nFanins = Int_ManInterpolate( p->pMan, p->pCnf, 0, &puTruth );
+p->timeInt += Abc_Clock() - clk;
+            if ( nFanins != Vec_PtrSize(vFanins) - 2 )
+                continue;
+            assert( puTruth );
+//            Extra_PrintBinary( stdout, puTruth, 1 << nFanins );  printf( "\n" );
+
+            // transform interpolant into the AIG
+            pGraph = Kit_TruthToGraph( puTruth, nFanins, p->vMem );
+
+            // derive the AIG for the decomposition tree
+            pFunc = Kit_GraphToHop( (Hop_Man_t *)pNtk->pManFunc, pGraph );
+            Kit_GraphFree( pGraph );
+
+            // update the network
+clk = Abc_Clock();
+            Res_UpdateNetwork( pObj, Vec_VecEntry(p->vResubsW, k), pFunc, p->vLevels );
+p->timeUpd += Abc_Clock() - clk;
+            break;
+        }
+//        printf( "\n" );
+    }
+    Extra_ProgressBarStop( pProgress );
+    Abc_NtkStopReverseLevels( pNtk );
+
+p->timeSatSim += p->pSim->timeSat;
+p->timeSatTotal = p->timeSatSat + p->timeSatUnsat + p->timeSatSim;
+
+    p->nTotalNets2 = Abc_NtkGetTotalFanins(pNtk);
+    p->nTotalNodes2 = Abc_NtkNodeNum(pNtk);
+
+    // quit resubstitution manager
+p->timeTotal = Abc_Clock() - clkTotal;
+    Res_ManFree( p );
+
+s_ResynTime += Abc_Clock() - clkTotal;
+    // check the resulting network
+    if ( !Abc_NtkCheck( pNtk ) )
+    {
+        fprintf( stdout, "Abc_NtkResynthesize(): Network check has failed.\n" );
+        return 0;
+    }
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/res/resDivs.c b/abc-build/src/opt/res/resDivs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/res/resDivs.c
@@ -0,0 +1,290 @@
+/**CFile****************************************************************
+
+  FileName    [resDivs.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resynthesis package.]
+
+  Synopsis    [Collect divisors for the given window.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 15, 2007.]
+
+  Revision    [$Id: resDivs.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "resInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Res_WinMarkTfi( Res_Win_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Adds candidate divisors of the node to its window.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_WinDivisors( Res_Win_t * p, int nLevDivMax )
+{
+    Abc_Obj_t * pObj, * pFanout, * pFanin;
+    int k, f, m;
+
+    // set the maximum level of the divisors
+    p->nLevDivMax = nLevDivMax;
+
+    // mark the TFI with the current trav ID
+    Abc_NtkIncrementTravId( p->pNode->pNtk );
+    Res_WinMarkTfi( p );
+
+    // mark with the current trav ID those nodes that should not be divisors:
+    // (1) the node and its TFO
+    // (2) the MFFC of the node
+    // (3) the node's fanins (these are treated as a special case)
+    Abc_NtkIncrementTravId( p->pNode->pNtk );
+    Res_WinSweepLeafTfo_rec( p->pNode, p->nLevDivMax );
+    Res_WinVisitMffc( p->pNode );
+    Abc_ObjForEachFanin( p->pNode, pObj, k )
+        Abc_NodeSetTravIdCurrent( pObj );
+
+    // at this point the nodes are marked with two trav IDs:
+    // nodes to be collected as divisors are marked with previous trav ID
+    // nodes to be avoided as divisors are marked with current trav ID
+
+    // start collecting the divisors
+    Vec_PtrClear( p->vDivs );
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, k )
+    {
+        assert( (int)pObj->Level >= p->nLevLeafMin ); 
+        if ( !Abc_NodeIsTravIdPrevious(pObj) )
+            continue;
+        if ( (int)pObj->Level > p->nLevDivMax )
+            continue;
+        Vec_PtrPush( p->vDivs, pObj );
+    }
+    // add the internal nodes to the data structure
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodes, pObj, k )
+    {
+        if ( !Abc_NodeIsTravIdPrevious(pObj) )
+            continue;
+        if ( (int)pObj->Level > p->nLevDivMax )
+            continue;
+        Vec_PtrPush( p->vDivs, pObj );
+    }
+
+    // explore the fanouts of already collected divisors
+    p->nDivsPlus = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs, pObj, k )
+    {
+        // consider fanouts of this node
+        Abc_ObjForEachFanout( pObj, pFanout, f )
+        {
+            // stop if there are too many fanouts
+            if ( f > 20 )
+                break;
+            // skip nodes that are already added
+            if ( Abc_NodeIsTravIdPrevious(pFanout) )
+                continue;
+            // skip nodes in the TFO or in the MFFC of node
+            if ( Abc_NodeIsTravIdCurrent(pFanout) )
+                continue;
+            // skip COs
+            if ( !Abc_ObjIsNode(pFanout) ) 
+                continue;
+            // skip nodes with large level
+            if ( (int)pFanout->Level > p->nLevDivMax )
+                continue;
+            // skip nodes whose fanins are not divisors
+            Abc_ObjForEachFanin( pFanout, pFanin, m )
+                if ( !Abc_NodeIsTravIdPrevious(pFanin) )
+                    break;
+            if ( m < Abc_ObjFaninNum(pFanout) )
+                continue;
+            // add the node to the divisors
+            Vec_PtrPush( p->vDivs, pFanout );
+            Vec_PtrPush( p->vNodes, pFanout );
+            Abc_NodeSetTravIdPrevious( pFanout );
+            p->nDivsPlus++;
+        }
+    }
+/*
+    printf( "Node level = %d.  ", Abc_ObjLevel(p->pNode) );
+    Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs, pObj, k, Vec_PtrSize(p->vDivs)-p->nDivsPlus )
+        printf( "%d ", Abc_ObjLevel(pObj) );
+    printf( "\n" );
+*/
+//printf( "%d ", p->nDivsPlus );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the TFI cone of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_WinMarkTfi_rec( Res_Win_t * p, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return;
+    Abc_NodeSetTravIdCurrent( pObj );
+    assert( Abc_ObjIsNode(pObj) );
+    // visit the fanins of the node
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        Res_WinMarkTfi_rec( p, pFanin );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the TFI cone of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_WinMarkTfi( Res_Win_t * p )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    // mark the leaves
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, i )
+        Abc_NodeSetTravIdCurrent( pObj );
+    // start from the node
+    Res_WinMarkTfi_rec( p, p->pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the TFO of the collected nodes up to the given level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_WinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    if ( Abc_ObjIsCo(pObj) || (int)pObj->Level > nLevelLimit )
+        return;
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return;
+    Abc_NodeSetTravIdCurrent( pObj );
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        Res_WinSweepLeafTfo_rec( pFanout, nLevelLimit );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences the node's MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_NodeDeref_rec( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    int i, Counter = 1;
+    if ( Abc_ObjIsCi(pNode) )
+        return 0;
+    Abc_NodeSetTravIdCurrent( pNode );
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        assert( pFanin->vFanouts.nSize > 0 );
+        if ( --pFanin->vFanouts.nSize == 0 )
+            Counter += Res_NodeDeref_rec( pFanin );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [References the node's MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_NodeRef_rec( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    int i, Counter = 1;
+    if ( Abc_ObjIsCi(pNode) )
+        return 0;
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        if ( pFanin->vFanouts.nSize++ == 0 )
+            Counter += Res_NodeRef_rec( pFanin );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Labels MFFC of the node with the current trav ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_WinVisitMffc( Abc_Obj_t * pNode )
+{
+    int Count1, Count2;
+    assert( Abc_ObjIsNode(pNode) );
+    // dereference the node (mark with the current trav ID)
+    Count1 = Res_NodeDeref_rec( pNode );
+    // reference it back
+    Count2 = Res_NodeRef_rec( pNode );
+    assert( Count1 == Count2 );
+    return Count1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/res/resFilter.c b/abc-build/src/opt/res/resFilter.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/res/resFilter.c
@@ -0,0 +1,439 @@
+/**CFile****************************************************************
+
+  FileName    [resFilter.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resynthesis package.]
+
+  Synopsis    [Filtering resubstitution candidates.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 15, 2007.]
+
+  Revision    [$Id: resFilter.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "resInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static unsigned * Res_FilterCollectFaninInfo( Res_Win_t * pWin, Res_Sim_t * pSim, unsigned uMask );
+static int        Res_FilterCriticalFanin( Abc_Obj_t * pNode );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Finds sets of feasible candidates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+int Res_FilterCandidates( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax, int fArea )
+{
+    Abc_Obj_t * pFanin, * pFanin2, * pFaninTemp;
+    unsigned * pInfo, * pInfoDiv, * pInfoDiv2;
+    int Counter, RetValue, i, i2, d, d2, iDiv, iDiv2, k;
+
+    // check that the info the node is one
+    pInfo = (unsigned *)Vec_PtrEntry( pSim->vOuts, 1 );
+    RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+    if ( RetValue == 0 )
+    {
+//        printf( "Failed 1!\n" );
+        return 0;
+    }
+
+    // collect the fanin info
+    pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~0 );
+    RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+    if ( RetValue == 0 )
+    {
+//        printf( "Failed 2!\n" );
+        return 0;
+    }
+
+    // try removing each fanin
+//    printf( "Fanins: " );
+    Counter = 0;
+    Vec_VecClear( vResubs );
+    Vec_VecClear( vResubsW );
+    Abc_ObjForEachFanin( pWin->pNode, pFanin, i )
+    {
+        if ( fArea && Abc_ObjFanoutNum(pFanin) > 1 )
+            continue;
+        // get simulation info without this fanin
+        pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) );
+        RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+        if ( RetValue )
+        {
+//            printf( "Node %4d. Candidate fanin %4d.\n", pWin->pNode->Id, pFanin->Id );
+            // collect the nodes
+            Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+            Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+            Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k )
+            {
+                if ( k != i )
+                {
+                    Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+                    Vec_VecPush( vResubsW, Counter, pFaninTemp );
+                }
+            }
+            Counter++;
+            if ( Counter == Vec_VecSize(vResubs) )
+                return Counter;    
+        }
+    }
+
+    // try replacing each critical fanin by a non-critical fanin
+    Abc_ObjForEachFanin( pWin->pNode, pFanin, i )
+    {
+        if ( Abc_ObjFanoutNum(pFanin) > 1 )
+            continue;
+        // get simulation info without this fanin
+        pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) );
+        // go over the set of divisors
+        for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ )
+        {
+            pInfoDiv = (unsigned *)Vec_PtrEntry( pSim->vOuts, d );
+            iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2);
+            if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) )
+                continue;
+            // collect the nodes
+            Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+            Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+            // collect the remaning fanins and the divisor
+            Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k )
+            {
+                if ( k != i )
+                {
+                    Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+                    Vec_VecPush( vResubsW, Counter, pFaninTemp );
+                }
+            }
+            // collect the divisor
+            Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) );
+            Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) );
+            Counter++;
+            if ( Counter == Vec_VecSize(vResubs) )
+                return Counter;           
+        }
+    }
+
+    // consider the case when two fanins can be added instead of one
+    if ( Abc_ObjFaninNum(pWin->pNode) < nFaninsMax )
+    {
+        // try to replace each critical fanin by two non-critical fanins
+        Abc_ObjForEachFanin( pWin->pNode, pFanin, i )
+        {
+            if ( Abc_ObjFanoutNum(pFanin) > 1 )
+                continue;
+            // get simulation info without this fanin
+            pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) );
+            // go over the set of divisors
+            for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ )
+            {
+                pInfoDiv = (unsigned *)Vec_PtrEntry( pSim->vOuts, d );
+                iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2);
+                // go through the second divisor
+                for ( d2 = d + 1; d2 < Abc_NtkPoNum(pAig); d2++ )
+                {
+                    pInfoDiv2 = (unsigned *)Vec_PtrEntry( pSim->vOuts, d2 );
+                    iDiv2 = d2 - (Abc_ObjFaninNum(pWin->pNode) + 2);
+                    if ( !Abc_InfoIsOrOne3( pInfo, pInfoDiv, pInfoDiv2, pSim->nWordsOut ) )
+                        continue;
+                    // collect the nodes
+                    Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+                    Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+                    // collect the remaning fanins and the divisor
+                    Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k )
+                    {
+                        if ( k != i )
+                        {
+                            Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+                            Vec_VecPush( vResubsW, Counter, pFaninTemp );
+                        }
+                    }
+                    // collect the divisor
+                    Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) );
+                    Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d2) );
+                    Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) );
+                    Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv2) );
+                    Counter++;
+                    if ( Counter == Vec_VecSize(vResubs) )
+                        return Counter;           
+                }
+            }
+        }
+    }
+
+    // try to replace two nets by one
+    if ( !fArea )
+    {
+        Abc_ObjForEachFanin( pWin->pNode, pFanin, i )
+        {
+            for ( i2 = i + 1; i2 < Abc_ObjFaninNum(pWin->pNode); i2++ )
+            {
+                pFanin2 = Abc_ObjFanin(pWin->pNode, i2);
+                // get simulation info without these fanins
+                pInfo = Res_FilterCollectFaninInfo( pWin, pSim, (~(1 << i)) & (~(1 << i2)) );
+                // go over the set of divisors
+                for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ )
+                {
+                    pInfoDiv = (unsigned *)Vec_PtrEntry( pSim->vOuts, d );
+                    iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2);
+                    if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) )
+                        continue;
+                    // collect the nodes
+                    Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+                    Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+                    // collect the remaning fanins and the divisor
+                    Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k )
+                    {
+                        if ( k != i && k != i2 )
+                        {
+                            Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+                            Vec_VecPush( vResubsW, Counter, pFaninTemp );
+                        }
+                    }
+                    // collect the divisor
+                    Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) );
+                    Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) );
+                    Counter++;
+                    if ( Counter == Vec_VecSize(vResubs) )
+                        return Counter;           
+                }
+            }
+        }
+    }
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds sets of feasible candidates.]
+
+  Description [This procedure is a special case of the above.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_FilterCandidatesArea( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax )
+{
+    Abc_Obj_t * pFanin;
+    unsigned * pInfo, * pInfoDiv, * pInfoDiv2;
+    int Counter, RetValue, d, d2, k, iDiv, iDiv2, iBest;
+
+    // check that the info the node is one
+    pInfo = (unsigned *)Vec_PtrEntry( pSim->vOuts, 1 );
+    RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+    if ( RetValue == 0 )
+    {
+//        printf( "Failed 1!\n" );
+        return 0;
+    }
+
+    // collect the fanin info
+    pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~0 );
+    RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+    if ( RetValue == 0 )
+    {
+//        printf( "Failed 2!\n" );
+        return 0;
+    }
+
+    // try removing fanins
+//    printf( "Fanins: " );
+    Counter = 0;
+    Vec_VecClear( vResubs );
+    Vec_VecClear( vResubsW );
+    // get the best fanins
+    iBest = Res_FilterCriticalFanin( pWin->pNode );
+    if ( iBest == -1 )
+        return 0;
+
+    // get the info without the critical fanin
+    pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << iBest) );
+    RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+    if ( RetValue )
+    {
+//        printf( "Can be done without one!\n" );
+        // collect the nodes
+        Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+        Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+        Abc_ObjForEachFanin( pWin->pNode, pFanin, k )
+        {
+            if ( k != iBest )
+            {
+                Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+                Vec_VecPush( vResubsW, Counter, pFanin );
+            }
+        }
+        Counter++;
+//        printf( "*" );
+        return Counter;
+    }
+
+    // go through the divisors
+    for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ )
+    {
+        pInfoDiv = (unsigned *)Vec_PtrEntry( pSim->vOuts, d );
+        iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2);
+        if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) )
+            continue;
+//if ( Abc_ObjLevel(pWin->pNode) <= Abc_ObjLevel( Vec_PtrEntry(pWin->vDivs, iDiv) ) )
+//    printf( "Node level = %d. Divisor level = %d.\n", Abc_ObjLevel(pWin->pNode), Abc_ObjLevel( Vec_PtrEntry(pWin->vDivs, iDiv) ) );
+        // collect the nodes
+        Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+        Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+        // collect the remaning fanins and the divisor
+        Abc_ObjForEachFanin( pWin->pNode, pFanin, k )
+        {
+            if ( k != iBest )
+            {
+                Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+                Vec_VecPush( vResubsW, Counter, pFanin );
+            }
+        }
+        // collect the divisor
+        Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) );
+        Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) );
+        Counter++;
+
+        if ( Counter == Vec_VecSize(vResubs) )
+            break;            
+    }
+
+    if ( Counter > 0 || Abc_ObjFaninNum(pWin->pNode) >= nFaninsMax )
+        return Counter;
+
+    // try to find the node pairs
+    for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ )
+    {
+        pInfoDiv = (unsigned *)Vec_PtrEntry( pSim->vOuts, d );
+        iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2);
+        // go through the second divisor
+        for ( d2 = d + 1; d2 < Abc_NtkPoNum(pAig); d2++ )
+        {
+            pInfoDiv2 = (unsigned *)Vec_PtrEntry( pSim->vOuts, d2 );
+            iDiv2 = d2 - (Abc_ObjFaninNum(pWin->pNode) + 2);
+
+            if ( !Abc_InfoIsOrOne3( pInfo, pInfoDiv, pInfoDiv2, pSim->nWordsOut ) )
+                continue;
+            // collect the nodes
+            Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+            Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+            // collect the remaning fanins and the divisor
+            Abc_ObjForEachFanin( pWin->pNode, pFanin, k )
+            {
+                if ( k != iBest )
+                {
+                    Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+                    Vec_VecPush( vResubsW, Counter, pFanin );
+                }
+            }
+            // collect the divisor
+            Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) );
+            Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d2) );
+            Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) );
+            Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv2) );
+            Counter++;
+
+            if ( Counter == Vec_VecSize(vResubs) )
+                break;            
+        }
+        if ( Counter == Vec_VecSize(vResubs) )
+            break;            
+    }
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds sets of feasible candidates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Res_FilterCollectFaninInfo( Res_Win_t * pWin, Res_Sim_t * pSim, unsigned uMask )
+{
+    Abc_Obj_t * pFanin;
+    unsigned * pInfo;
+    int i;
+    pInfo = (unsigned *)Vec_PtrEntry( pSim->vOuts, 0 );
+    Abc_InfoClear( pInfo, pSim->nWordsOut );
+    Abc_ObjForEachFanin( pWin->pNode, pFanin, i )
+    {
+        if ( uMask & (1 << i) )
+            Abc_InfoOr( pInfo, (unsigned *)Vec_PtrEntry(pSim->vOuts, 2+i), pSim->nWordsOut );
+    }
+    return pInfo;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the index of the most critical fanin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_FilterCriticalFanin( Abc_Obj_t * pNode )
+{
+    Abc_Obj_t * pFanin;
+    int i, iBest = -1, CostMax = 0, CostCur;
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+    {
+        if ( !Abc_ObjIsNode(pFanin) )
+            continue;
+        if ( Abc_ObjFanoutNum(pFanin) > 1 )
+            continue;
+        CostCur = Res_WinVisitMffc( pFanin );
+        if ( CostMax < CostCur )
+        {
+            CostMax = CostCur;
+            iBest = i;
+        }
+    }
+//    if ( CostMax > 0 )
+//        printf( "<%d>", CostMax );
+    return iBest;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/res/resInt.h b/abc-build/src/opt/res/resInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/res/resInt.h
@@ -0,0 +1,141 @@
+/**CFile****************************************************************
+
+  FileName    [resInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resynthesis package.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 15, 2007.]
+
+  Revision    [$Id: resInt.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__opt__res__resInt_h
+#define ABC__opt__res__resInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "res.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Res_Win_t_ Res_Win_t;
+struct Res_Win_t_
+{
+    // windowing parameters
+    Abc_Obj_t *      pNode;        // the node in the center
+    int              nWinTfiMax;   // the fanin levels
+    int              nWinTfoMax;   // the fanout levels
+    int              nLevDivMax;   // the maximum divisor level
+    // internal windowing parameters
+    int              nFanoutLimit; // the limit on the fanout count of a TFO node (if more, the node is treated as a root)
+    int              nLevTfiMinus; // the number of additional levels to search from TFO below the level of leaves
+    // derived windowing parameters
+    int              nLevLeafMin;  // the minimum level of a leaf
+    int              nLevTravMin;  // the minimum level to search from TFO
+    int              nDivsPlus;    // the number of additional divisors
+    // the window data
+    Vec_Ptr_t *      vRoots;       // outputs of the window
+    Vec_Ptr_t *      vLeaves;      // inputs of the window
+    Vec_Ptr_t *      vBranches;    // side nodes of the window
+    Vec_Ptr_t *      vNodes;       // internal nodes of the window
+    Vec_Ptr_t *      vDivs;        // candidate divisors of the node
+    // temporary data
+    Vec_Vec_t *      vMatrix;      // TFI nodes below the given node
+};
+
+typedef struct Res_Sim_t_ Res_Sim_t;
+struct Res_Sim_t_
+{
+    Abc_Ntk_t *      pAig;         // AIG for simulation
+    int              nTruePis;     // the number of true PIs of the window
+    int              fConst0;      // the node can be replaced by constant 0
+    int              fConst1;      // the node can be replaced by constant 0
+    // simulation parameters
+    int              nWords;       // the number of simulation words
+    int              nPats;        // the number of patterns
+    int              nWordsIn;     // the number of simulation words in the input patterns
+    int              nPatsIn;      // the number of patterns in the input patterns 
+    int              nBytesIn;     // the number of bytes in the input patterns
+    int              nWordsOut;    // the number of simulation words in the output patterns
+    int              nPatsOut;     // the number of patterns in the output patterns 
+    // simulation info
+    Vec_Ptr_t *      vPats;        // input simulation patterns
+    Vec_Ptr_t *      vPats0;       // input simulation patterns
+    Vec_Ptr_t *      vPats1;       // input simulation patterns
+    Vec_Ptr_t *      vOuts;        // output simulation info
+    int              nPats0;       // the number of 0-patterns accumulated
+    int              nPats1;       // the number of 1-patterns accumulated
+    // resub candidates
+    Vec_Vec_t *      vCands;       // resubstitution candidates
+    // statistics
+    abctime          timeSat;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== resDivs.c ==========================================================*/
+extern void          Res_WinDivisors( Res_Win_t * p, int nLevDivMax );
+extern void          Res_WinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit );
+extern int           Res_WinVisitMffc( Abc_Obj_t * pNode );
+/*=== resFilter.c ==========================================================*/
+extern int           Res_FilterCandidates( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax, int fArea );
+extern int           Res_FilterCandidatesArea( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax );
+/*=== resSat.c ==========================================================*/
+extern void *        Res_SatProveUnsat( Abc_Ntk_t * pAig, Vec_Ptr_t * vFanins );
+extern int           Res_SatSimulate( Res_Sim_t * p, int nPats, int fOnSet );
+/*=== resSim.c ==========================================================*/
+extern Res_Sim_t *   Res_SimAlloc( int nWords );
+extern void          Res_SimFree( Res_Sim_t * p );
+extern int           Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose );
+/*=== resStrash.c ==========================================================*/
+extern Abc_Ntk_t *   Res_WndStrash( Res_Win_t * p );
+/*=== resWnd.c ==========================================================*/
+extern void          Res_UpdateNetwork( Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc, Vec_Vec_t * vLevels );
+/*=== resWnd.c ==========================================================*/
+extern Res_Win_t *   Res_WinAlloc();
+extern void          Res_WinFree( Res_Win_t * p );
+extern int           Res_WinIsTrivial( Res_Win_t * p );
+extern int           Res_WinCompute( Abc_Obj_t * pNode, int nWinTfiMax, int nWinTfoMax, Res_Win_t * p );
+
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/res/resSat.c b/abc-build/src/opt/res/resSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/res/resSat.c
@@ -0,0 +1,414 @@
+/**CFile****************************************************************
+
+  FileName    [resSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resynthesis package.]
+
+  Synopsis    [Interface with the SAT solver.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 15, 2007.]
+
+  Revision    [$Id: resSat.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "resInt.h"
+#include "aig/hop/hop.h"
+#include "sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Res_SatAddConst1( sat_solver * pSat, int iVar, int fCompl );
+extern int Res_SatAddEqual( sat_solver * pSat, int iVar0, int iVar1, int fCompl );
+extern int Res_SatAddAnd( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Loads AIG into the SAT solver for checking resubstitution.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Res_SatProveUnsat( Abc_Ntk_t * pAig, Vec_Ptr_t * vFanins )
+{
+    void * pCnf = NULL;
+    sat_solver * pSat;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj;
+    int i, nNodes, status;
+
+    // make sure fanins contain POs of the AIG
+    pObj = (Abc_Obj_t *)Vec_PtrEntry( vFanins, 0 );
+    assert( pObj->pNtk == pAig && Abc_ObjIsPo(pObj) );
+
+    // collect reachable nodes
+    vNodes = Abc_NtkDfsNodes( pAig, (Abc_Obj_t **)vFanins->pArray, vFanins->nSize );
+
+    // assign unique numbers to each node
+    nNodes = 0;
+    Abc_AigConst1(pAig)->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++;
+    Abc_NtkForEachPi( pAig, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i ) // useful POs
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++;
+
+    // start the solver
+    pSat = sat_solver_new();
+    sat_solver_store_alloc( pSat );
+
+    // add clause for the constant node
+    Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)Abc_AigConst1(pAig)->pCopy, 0 );
+    // add clauses for AND gates
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        Res_SatAddAnd( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, 
+            (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, (int)(ABC_PTRUINT_T)Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+    Vec_PtrFree( vNodes );
+    // add clauses for POs
+    Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i )
+        Res_SatAddEqual( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, 
+            (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) );
+    // add trivial clauses
+    pObj = (Abc_Obj_t *)Vec_PtrEntry(vFanins, 0);
+    Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, 0 ); // care-set
+    pObj = (Abc_Obj_t *)Vec_PtrEntry(vFanins, 1);
+    Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, 0 ); // on-set
+
+    // bookmark the clauses of A
+    sat_solver_store_mark_clauses_a( pSat );
+
+    // duplicate the clauses
+    pObj = (Abc_Obj_t *)Vec_PtrEntry(vFanins, 1);
+    Sat_SolverDoubleClauses( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy );
+    // add the equality constraints
+    Vec_PtrForEachEntryStart( Abc_Obj_t *, vFanins, pObj, i, 2 )
+        Res_SatAddEqual( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, ((int)(ABC_PTRUINT_T)pObj->pCopy) + nNodes, 0 );
+
+    // bookmark the roots
+    sat_solver_store_mark_roots( pSat );
+
+    // solve the problem
+    status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)10000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( status == l_False )
+    {
+        pCnf = sat_solver_store_release( pSat );
+//        printf( "unsat\n" );
+    }
+    else if ( status == l_True )
+    {
+//        printf( "sat\n" );
+    }
+    else
+    {
+//        printf( "undef\n" );
+    }
+    sat_solver_delete( pSat );
+    return pCnf;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Loads AIG into the SAT solver for constrained simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Res_SatSimulateConstr( Abc_Ntk_t * pAig, int fOnSet )
+{
+    sat_solver * pSat;
+    Vec_Ptr_t * vFanins;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj;
+    int i, nNodes;
+
+    // start the array
+    vFanins = Vec_PtrAlloc( 2 );
+    pObj = Abc_NtkPo( pAig, 0 );
+    Vec_PtrPush( vFanins, pObj );
+    pObj = Abc_NtkPo( pAig, 1 );
+    Vec_PtrPush( vFanins, pObj );
+
+    // collect reachable nodes
+    vNodes = Abc_NtkDfsNodes( pAig, (Abc_Obj_t **)vFanins->pArray, vFanins->nSize );
+
+    // assign unique numbers to each node
+    nNodes = 0;
+    Abc_AigConst1(pAig)->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++;
+    Abc_NtkForEachPi( pAig, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i ) // useful POs
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++;
+
+    // start the solver
+    pSat = sat_solver_new();
+
+    // add clause for the constant node
+    Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)Abc_AigConst1(pAig)->pCopy, 0 );
+    // add clauses for AND gates
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        Res_SatAddAnd( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, 
+            (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, (int)(ABC_PTRUINT_T)Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+    Vec_PtrFree( vNodes );
+    // add clauses for the first PO
+    pObj = Abc_NtkPo( pAig, 0 );
+    Res_SatAddEqual( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, 
+        (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) );
+    // add clauses for the second PO
+    pObj = Abc_NtkPo( pAig, 1 );
+    Res_SatAddEqual( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, 
+        (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) );
+
+    // add trivial clauses
+    pObj = Abc_NtkPo( pAig, 0 );
+    Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, 0 ); // care-set
+
+    pObj = Abc_NtkPo( pAig, 1 );
+    Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, !fOnSet ); // on-set
+
+    Vec_PtrFree( vFanins );
+    return pSat;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Loads AIG into the SAT solver for constrained simulation.]
+
+  Description [Returns 1 if the required number of patterns are found. 
+  Returns 0 if the solver ran out of time or proved a constant. 
+  In the latter, case one of the flags, fConst0 or fConst1, are set to 1.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_SatSimulate( Res_Sim_t * p, int nPatsLimit, int fOnSet )
+{
+    Vec_Int_t * vLits;
+    Vec_Ptr_t * vPats;
+    sat_solver * pSat;
+    int RetValue = -1; // Suppress "might be used uninitialized"
+    int i, k, value, status, Lit, Var, iPat;
+    abctime clk = Abc_Clock();
+
+//printf( "Looking for %s:  ", fOnSet? "onset " : "offset" );
+
+    // decide what problem should be solved
+    Lit = toLitCond( (int)(ABC_PTRUINT_T)Abc_NtkPo(p->pAig,1)->pCopy, !fOnSet );
+    if ( fOnSet )
+    {
+        iPat = p->nPats1;
+        vPats = p->vPats1;
+    }
+    else
+    {
+        iPat = p->nPats0;
+        vPats = p->vPats0;
+    }
+    assert( iPat < nPatsLimit );
+
+    // derive the SAT solver
+    pSat = (sat_solver *)Res_SatSimulateConstr( p->pAig, fOnSet );
+    pSat->fSkipSimplify = 1;
+    status = sat_solver_simplify( pSat );
+    if ( status == 0 )
+    {
+        if ( iPat == 0 )
+        {
+//            if ( fOnSet )
+//                p->fConst0 = 1;
+//            else
+//                p->fConst1 = 1;
+            RetValue = 0;
+        }
+        goto finish;
+    }
+ 
+    // enumerate through the SAT assignments
+    RetValue = 1;
+    vLits = Vec_IntAlloc( 32 );
+    for ( k = iPat; k < nPatsLimit; k++ )
+    {
+        // solve with the assumption
+//        status = sat_solver_solve( pSat, &Lit, &Lit + 1, (ABC_INT64_T)10000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)10000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        if ( status == l_False )
+        {
+//printf( "Const %d\n", !fOnSet );
+            if ( k == 0 )
+            {
+                if ( fOnSet )
+                    p->fConst0 = 1;
+                else
+                    p->fConst1 = 1;
+                RetValue = 0;
+            }
+            break;
+        }
+        else if ( status == l_True )
+        {
+            // save the pattern
+            Vec_IntClear( vLits );
+            for ( i = 0; i < p->nTruePis; i++ )
+            {
+                Var = (int)(ABC_PTRUINT_T)Abc_NtkPi(p->pAig,i)->pCopy;
+//                value = (int)(pSat->model.ptr[Var] == l_True);
+                value = sat_solver_var_value(pSat, Var);
+                if ( value )
+                    Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(vPats, i), k );
+                Lit = toLitCond( Var, value );
+                Vec_IntPush( vLits, Lit );
+//                printf( "%d", value );
+            }
+//            printf( "\n" );
+
+            status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
+            if ( status == 0 )
+            {
+                k++;
+                RetValue = 1; 
+                break;
+            }
+        }
+        else
+        {
+//printf( "Undecided\n" );
+            if ( k == 0 )
+                RetValue = 0;
+            else
+                RetValue = 1; 
+            break;
+        }
+    }
+    Vec_IntFree( vLits );
+//printf( "Found %d patterns\n", k - iPat );
+
+    // set the new number of patterns
+    if ( fOnSet )
+        p->nPats1 = k;
+    else
+        p->nPats0 = k;
+
+finish:
+
+    sat_solver_delete( pSat );
+p->timeSat += Abc_Clock() - clk;
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Asserts equality of the variable to a constant.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_SatAddConst1( sat_solver * pSat, int iVar, int fCompl )
+{
+    lit Lit = toLitCond( iVar, fCompl );
+    if ( !sat_solver_addclause( pSat, &Lit, &Lit + 1 ) )
+        return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Asserts equality of two variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_SatAddEqual( sat_solver * pSat, int iVar0, int iVar1, int fCompl )
+{
+    lit Lits[2];
+
+    Lits[0] = toLitCond( iVar0, 0 );
+    Lits[1] = toLitCond( iVar1, !fCompl );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVar0, 1 );
+    Lits[1] = toLitCond( iVar1, fCompl );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+        return 0;
+
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds constraints for the two-input AND-gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_SatAddAnd( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 )
+{
+    lit Lits[3];
+
+    Lits[0] = toLitCond( iVar, 1 );
+    Lits[1] = toLitCond( iVar0, fCompl0 );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVar, 1 );
+    Lits[1] = toLitCond( iVar1, fCompl1 );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVar, 0 );
+    Lits[1] = toLitCond( iVar0, !fCompl0 );
+    Lits[2] = toLitCond( iVar1, !fCompl1 );
+    if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) )
+        return 0;
+
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/res/resSim.c b/abc-build/src/opt/res/resSim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/res/resSim.c
@@ -0,0 +1,795 @@
+/**CFile****************************************************************
+
+  FileName    [resSim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resynthesis package.]
+
+  Synopsis    [Simulation engine.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 15, 2007.]
+
+  Revision    [$Id: resSim.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "resInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocate simulation engine.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+Res_Sim_t * Res_SimAlloc( int nWords )
+{
+    Res_Sim_t * p;
+    p = ABC_ALLOC( Res_Sim_t, 1 );
+    memset( p, 0, sizeof(Res_Sim_t) );
+    // simulation parameters
+    p->nWords    = nWords;
+    p->nPats     = p->nWords * 8 * sizeof(unsigned);
+    p->nWordsIn  = p->nPats;
+    p->nBytesIn  = p->nPats * sizeof(unsigned);
+    p->nPatsIn   = p->nPats * 8 * sizeof(unsigned);
+    p->nWordsOut = p->nPats * p->nWords;
+    p->nPatsOut  = p->nPats * p->nPats;
+    // simulation info
+    p->vPats     = Vec_PtrAllocSimInfo( 1024, p->nWordsIn );
+    p->vPats0    = Vec_PtrAllocSimInfo( 128, p->nWords );
+    p->vPats1    = Vec_PtrAllocSimInfo( 128, p->nWords );
+    p->vOuts     = Vec_PtrAllocSimInfo( 128, p->nWordsOut );
+    // resub candidates
+    p->vCands    = Vec_VecStart( 16 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocate simulation engine.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimAdjust( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis )
+{
+    srand( 0xABC );
+
+    assert( Abc_NtkIsStrash(pAig) );
+    p->pAig = pAig;
+    p->nTruePis = nTruePis;
+    if ( Vec_PtrSize(p->vPats) < Abc_NtkObjNumMax(pAig)+1 )
+    {
+        Vec_PtrFree( p->vPats );
+        p->vPats = Vec_PtrAllocSimInfo( Abc_NtkObjNumMax(pAig)+1, p->nWordsIn );
+    }
+    if ( Vec_PtrSize(p->vPats0) < nTruePis )
+    {
+        Vec_PtrFree( p->vPats0 );
+        p->vPats0 = Vec_PtrAllocSimInfo( nTruePis, p->nWords );
+    }
+    if ( Vec_PtrSize(p->vPats1) < nTruePis )
+    {
+        Vec_PtrFree( p->vPats1 );
+        p->vPats1 = Vec_PtrAllocSimInfo( nTruePis, p->nWords );
+    }
+    if ( Vec_PtrSize(p->vOuts) < Abc_NtkPoNum(pAig) )
+    {
+        Vec_PtrFree( p->vOuts );
+        p->vOuts = Vec_PtrAllocSimInfo( Abc_NtkPoNum(pAig), p->nWordsOut );
+    }
+    // clean storage info for patterns
+    Abc_InfoClear( (unsigned *)Vec_PtrEntry(p->vPats0,0), p->nWords * nTruePis );
+    Abc_InfoClear( (unsigned *)Vec_PtrEntry(p->vPats1,0), p->nWords * nTruePis );
+    p->nPats0 = 0;
+    p->nPats1 = 0;
+    p->fConst0 = 0;
+    p->fConst1 = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Free simulation engine.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimFree( Res_Sim_t * p )
+{
+    Vec_PtrFree( p->vPats );
+    Vec_PtrFree( p->vPats0 );
+    Vec_PtrFree( p->vPats1 );
+    Vec_PtrFree( p->vOuts );
+    Vec_VecFree( p->vCands );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sets random PI simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_InfoRandomBytes( unsigned * p, int nWords ) 
+{ 
+    int i, Num; 
+    for ( i = nWords - 1; i >= 0; i-- ) 
+    { 
+        Num = rand(); 
+        p[i] = (Num & 1)? 0xff : 0;
+        p[i] = (p[i] << 8) | ((Num & 2)? 0xff : 0);
+        p[i] = (p[i] << 8) | ((Num & 4)? 0xff : 0);
+        p[i] = (p[i] << 8) | ((Num & 8)? 0xff : 0);
+    } 
+//    Extra_PrintBinary( stdout, p, 32 ); printf( "\n" );
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Sets random PI simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimSetRandomBytes( Res_Sim_t * p )
+{
+    Abc_Obj_t * pObj;
+    unsigned * pInfo;
+    int i;
+    Abc_NtkForEachPi( p->pAig, pObj, i )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id );
+        if ( i < p->nTruePis )
+            Abc_InfoRandomBytes( pInfo, p->nWordsIn );
+        else
+            Abc_InfoRandom( pInfo, p->nWordsIn );
+    }
+/*
+    // double-check that all are byte-patterns
+    Abc_NtkForEachPi( p->pAig, pObj, i )
+    {
+        if ( i == p->nTruePis )
+            break;
+        pInfoC = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+        for ( k = 0; k < p->nBytesIn; k++ )
+            assert( pInfoC[k] == 0 || pInfoC[k] == 0xff );
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets random PI simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimSetDerivedBytes( Res_Sim_t * p, int fUseWalk )
+{
+    Vec_Ptr_t * vPatsSource[2];
+    int nPatsSource[2];
+    Abc_Obj_t * pObj;
+    unsigned char * pInfo;
+    int i, k, z, s, nPats;
+
+    // set several random patterns
+    assert( p->nBytesIn % 32 == 0 );
+    nPats = p->nBytesIn/8;
+    Abc_NtkForEachPi( p->pAig, pObj, i )
+    {
+        if ( i == p->nTruePis )
+            break;
+        Abc_InfoRandomBytes( (unsigned *)Vec_PtrEntry(p->vPats, pObj->Id), nPats/4 );
+    }
+
+    // set special patterns
+    if ( fUseWalk )
+    {
+        for ( z = 0; z < 2; z++ )
+        {
+            // set the zero pattern
+            Abc_NtkForEachPi( p->pAig, pObj, i )
+            {
+                if ( i == p->nTruePis )
+                    break;
+                pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+                pInfo[nPats] = z ? 0xff : 0;
+            }
+            if ( ++nPats == p->nBytesIn )
+                return;
+            // set the walking zero pattern
+            for ( k = 0; k < p->nTruePis; k++ )
+            {
+                Abc_NtkForEachPi( p->pAig, pObj, i )
+                {
+                    if ( i == p->nTruePis )
+                        break;
+                    pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+                    pInfo[nPats] = ((i == k) ^ z) ? 0xff : 0;
+                }
+                if ( ++nPats == p->nBytesIn )
+                    return;
+            }
+        }
+    }
+
+    // decide what patterns to set first
+    if ( p->nPats0 < p->nPats1 )
+    {
+        nPatsSource[0] = p->nPats0;
+        vPatsSource[0] = p->vPats0;
+        nPatsSource[1] = p->nPats1;
+        vPatsSource[1] = p->vPats1;
+    }
+    else
+    {
+        nPatsSource[0] = p->nPats1;
+        vPatsSource[0] = p->vPats1;
+        nPatsSource[1] = p->nPats0;
+        vPatsSource[1] = p->vPats0;
+    }
+    for ( z = 0; z < 2; z++ )
+    {
+        for ( s = nPatsSource[z] - 1; s >= 0; s-- )
+        {
+//            if ( s == 0 )
+//            printf( "Patterns:\n" );
+            // set the given source pattern
+            for ( k = 0; k < p->nTruePis; k++ )
+            {
+                Abc_NtkForEachPi( p->pAig, pObj, i )
+                {
+                    if ( i == p->nTruePis )
+                        break;
+                    pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+                    if ( (i == k) ^ Abc_InfoHasBit( (unsigned *)Vec_PtrEntry(vPatsSource[z], i), s ) )
+                    {
+                        pInfo[nPats] = 0xff;
+//                        if ( s == 0 )
+//                        printf( "1" );
+                    }
+                    else
+                    {
+                        pInfo[nPats] = 0;
+//                        if ( s == 0 )
+//                        printf( "0" );
+                    }
+                }
+//                if ( s == 0 )
+//                printf( "\n" );
+                if ( ++nPats == p->nBytesIn )
+                    return;
+            }
+        }
+    }
+    // clean the rest
+    for ( z = nPats; z < p->nBytesIn; z++ )
+    {
+        Abc_NtkForEachPi( p->pAig, pObj, i )
+        {
+            if ( i == p->nTruePis )
+                break;
+            pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+            memset( pInfo + nPats, 0, p->nBytesIn - nPats );
+        }
+    }
+/*
+    // double-check that all are byte-patterns
+    Abc_NtkForEachPi( p->pAig, pObj, i )
+    {
+        if ( i == p->nTruePis )
+            break;
+        pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+        for ( k = 0; k < p->nBytesIn; k++ )
+            assert( pInfo[k] == 0 || pInfo[k] == 0xff );
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets given PI simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimSetGiven( Res_Sim_t * p, Vec_Ptr_t * vInfo )
+{
+    Abc_Obj_t * pObj;
+    unsigned * pInfo, * pInfo2;
+    int i, w;
+    Abc_NtkForEachPi( p->pAig, pObj, i )
+    {
+        if ( i == p->nTruePis )
+            break;
+        pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id );
+        pInfo2 = (unsigned *)Vec_PtrEntry( vInfo, i );
+        for ( w = 0; w < p->nWords; w++ )
+            pInfo[w] = pInfo2[w];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimPerformOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords )
+{
+    unsigned * pInfo, * pInfo1, * pInfo2;
+    int k, fComp1, fComp2;
+    // simulate the internal nodes
+    assert( Abc_ObjIsNode(pNode) );
+    pInfo  = (unsigned *)Vec_PtrEntry(vSimInfo, pNode->Id);
+    pInfo1 = (unsigned *)Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
+    pInfo2 = (unsigned *)Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode));
+    fComp1 = Abc_ObjFaninC0(pNode);
+    fComp2 = Abc_ObjFaninC1(pNode);
+    if ( fComp1 && fComp2 )
+        for ( k = 0; k < nSimWords; k++ )
+            pInfo[k] = ~pInfo1[k] & ~pInfo2[k];
+    else if ( fComp1 && !fComp2 )
+        for ( k = 0; k < nSimWords; k++ )
+            pInfo[k] = ~pInfo1[k] &  pInfo2[k];
+    else if ( !fComp1 && fComp2 )
+        for ( k = 0; k < nSimWords; k++ )
+            pInfo[k] =  pInfo1[k] & ~pInfo2[k];
+    else // if ( fComp1 && fComp2 )
+        for ( k = 0; k < nSimWords; k++ )
+            pInfo[k] =  pInfo1[k] &  pInfo2[k];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one CO node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimTransferOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords )
+{
+    unsigned * pInfo, * pInfo1;
+    int k, fComp1;
+    // simulate the internal nodes
+    assert( Abc_ObjIsCo(pNode) );
+    pInfo  = (unsigned *)Vec_PtrEntry(vSimInfo, pNode->Id);
+    pInfo1 = (unsigned *)Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
+    fComp1 = Abc_ObjFaninC0(pNode);
+    if ( fComp1 )
+        for ( k = 0; k < nSimWords; k++ )
+            pInfo[k] = ~pInfo1[k];
+    else 
+        for ( k = 0; k < nSimWords; k++ )
+            pInfo[k] =  pInfo1[k];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one round of simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimPerformRound( Res_Sim_t * p, int nWords )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_InfoFill( (unsigned *)Vec_PtrEntry(p->vPats,0), nWords );
+    Abc_AigForEachAnd( p->pAig, pObj, i )
+        Res_SimPerformOne( pObj, p->vPats, nWords );
+    Abc_NtkForEachPo( p->pAig, pObj, i )
+        Res_SimTransferOne( pObj, p->vPats, nWords );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Pads the extra space with duplicated simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimPadSimInfo( Vec_Ptr_t * vPats, int nPats, int nWords )
+{
+    unsigned * pInfo;
+    int i, w, iWords;
+    assert( nPats > 0 && nPats < nWords * 8 * (int) sizeof(unsigned) );
+    // pad the first word
+    if ( nPats < 8 * sizeof(unsigned) )
+    {
+        Vec_PtrForEachEntry( unsigned *, vPats, pInfo, i )
+            if ( pInfo[0] & 1 )
+                pInfo[0] |= ((~0) << nPats);
+        nPats = 8 * sizeof(unsigned);
+    }
+    // pad the empty words
+    iWords = nPats / (8 * sizeof(unsigned));
+    Vec_PtrForEachEntry( unsigned *, vPats, pInfo, i )
+    {
+        for ( w = iWords; w < nWords; w++ )
+            pInfo[w] = pInfo[0];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the simulation info to fill the space.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimDeriveInfoReplicate( Res_Sim_t * p )
+{
+    unsigned * pInfo, * pInfo2;
+    Abc_Obj_t * pObj;
+    int i, j, w;
+    Abc_NtkForEachPo( p->pAig, pObj, i )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id );
+        pInfo2 = (unsigned *)Vec_PtrEntry( p->vOuts, i );
+        for ( j = 0; j < p->nPats; j++ )
+            for ( w = 0; w < p->nWords; w++ )
+                *pInfo2++ = pInfo[w];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Complement the simulation info if necessary.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimDeriveInfoComplement( Res_Sim_t * p )
+{
+    unsigned * pInfo, * pInfo2;
+    Abc_Obj_t * pObj;
+    int i, j, w;
+    Abc_NtkForEachPo( p->pAig, pObj, i )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id );
+        pInfo2 = (unsigned *)Vec_PtrEntry( p->vOuts, i );
+        for ( j = 0; j < p->nPats; j++, pInfo2 += p->nWords )
+            if ( Abc_InfoHasBit( pInfo, j ) )
+                for ( w = 0; w < p->nWords; w++ )
+                    pInfo2[w] = ~pInfo2[w];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints output patterns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimPrintOutPatterns( Res_Sim_t * p, Abc_Ntk_t * pAig )
+{
+    Abc_Obj_t * pObj;
+    unsigned * pInfo2;
+    int i;
+    Abc_NtkForEachPo( pAig, pObj, i )
+    {
+        pInfo2 = (unsigned *)Vec_PtrEntry( p->vOuts, i );
+        Extra_PrintBinary( stdout, pInfo2, p->nPatsOut );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints output patterns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimPrintNodePatterns( Res_Sim_t * p, Abc_Ntk_t * pAig )
+{
+    unsigned * pInfo;
+    pInfo = (unsigned *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
+    Extra_PrintBinary( stdout, pInfo, p->nPats );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of patters of different type.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimCountResults( Res_Sim_t * p, int * pnDcs, int * pnOnes, int * pnZeros, int fVerbose )
+{
+    unsigned char * pInfoCare, * pInfoNode;
+    int i, nTotal = 0;
+    pInfoCare = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id );
+    pInfoNode = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
+    for ( i = 0; i < p->nBytesIn; i++ )
+    {
+        if ( !pInfoCare[i] )
+            (*pnDcs)++;
+        else if ( !pInfoNode[i] )
+            (*pnZeros)++;
+        else
+            (*pnOnes)++;
+    }
+    nTotal += *pnDcs;
+    nTotal += *pnZeros;
+    nTotal += *pnOnes;
+    if ( fVerbose )
+    {
+        printf( "Dc = %7.2f %%  ",  100.0*(*pnDcs)  /nTotal );
+        printf( "On = %7.2f %%  ",  100.0*(*pnOnes) /nTotal );
+        printf( "Off = %7.2f %%  ", 100.0*(*pnZeros)/nTotal );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of patters of different type.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimCollectPatterns( Res_Sim_t * p, int fVerbose )
+{
+    Abc_Obj_t * pObj;
+    unsigned char * pInfoCare, * pInfoNode, * pInfo;
+    int i, j;
+    pInfoCare = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id );
+    pInfoNode = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
+    for ( i = 0; i < p->nBytesIn; i++ )
+    {
+        // skip don't-care patterns
+        if ( !pInfoCare[i] )
+            continue;
+        // separate offset and onset patterns
+        assert( pInfoNode[i] == 0 || pInfoNode[i] == 0xff );
+        if ( !pInfoNode[i] )
+        {
+            if ( p->nPats0 >= p->nPats )
+                continue;
+            Abc_NtkForEachPi( p->pAig, pObj, j )
+            {
+                if ( j == p->nTruePis )
+                    break;
+                pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+                assert( pInfo[i] == 0 || pInfo[i] == 0xff );
+                if ( pInfo[i] )
+                    Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(p->vPats0, j), p->nPats0 );
+            }
+            p->nPats0++;
+        }
+        else
+        {
+            if ( p->nPats1 >= p->nPats )
+                continue;
+            Abc_NtkForEachPi( p->pAig, pObj, j )
+            {
+                if ( j == p->nTruePis )
+                    break;
+                pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+                assert( pInfo[i] == 0 || pInfo[i] == 0xff );
+                if ( pInfo[i] )
+                    Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(p->vPats1, j), p->nPats1 );
+            }
+            p->nPats1++;
+        }
+        if ( p->nPats0 >= p->nPats && p->nPats1 >= p->nPats )
+            break;
+    }
+    if ( fVerbose )
+    {
+        printf( "|  " );
+        printf( "On = %3d  ", p->nPats1 );
+        printf( "Off = %3d  ", p->nPats0 );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the last pattern.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_SimVerifyValue( Res_Sim_t * p, int fOnSet )
+{
+    Abc_Obj_t * pObj;
+    unsigned * pInfo, * pInfo2;
+    int i, value;
+    Abc_NtkForEachPi( p->pAig, pObj, i )
+    {
+        if ( i == p->nTruePis )
+            break;
+        if ( fOnSet )
+        {
+            pInfo2 = (unsigned *)Vec_PtrEntry( p->vPats1, i );
+            value = Abc_InfoHasBit( pInfo2, p->nPats1 - 1 );
+        }
+        else
+        {
+            pInfo2 = (unsigned *)Vec_PtrEntry( p->vPats0, i );
+            value = Abc_InfoHasBit( pInfo2, p->nPats0 - 1 );
+        }
+        pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id );
+        pInfo[0] = value ? ~0 : 0;
+    }
+    Res_SimPerformRound( p, 1 );
+    pObj = Abc_NtkPo( p->pAig, 1 );
+    pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id );
+    assert( pInfo[0] == 0 || pInfo[0] == ~0 );
+    return pInfo[0] > 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares simulation info for candidate filtering.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose )
+{
+    int i, nOnes = 0, nZeros = 0, nDcs = 0;
+    if ( fVerbose )
+        printf( "\n" );
+    // prepare the manager
+    Res_SimAdjust( p, pAig, nTruePis );
+    // estimate the number of patterns
+    Res_SimSetRandomBytes( p );
+    Res_SimPerformRound( p, p->nWordsIn );
+    Res_SimCountResults( p, &nDcs, &nOnes, &nZeros, fVerbose );
+    // collect the patterns
+    Res_SimCollectPatterns( p, fVerbose );
+    // add more patterns using constraint simulation
+    if ( p->nPats0 < 8 )
+    {
+        if ( !Res_SatSimulate( p, 16, 0 ) )
+            return p->fConst0 || p->fConst1;
+//            return 0;
+//        printf( "Value0 = %d\n", Res_SimVerifyValue( p, 0 ) );
+    }
+    if ( p->nPats1 < 8 )
+    {
+        if ( !Res_SatSimulate( p, 16, 1 ) )
+            return p->fConst0 || p->fConst1;
+//            return 0;
+//        printf( "Value1 = %d\n", Res_SimVerifyValue( p, 1 ) );
+    }
+    // generate additional patterns
+    for ( i = 0; i < 2; i++ )
+    {
+        if ( p->nPats0 > p->nPats*7/8 && p->nPats1 > p->nPats*7/8 )
+            break;
+        Res_SimSetDerivedBytes( p, i==0 );
+        Res_SimPerformRound( p, p->nWordsIn );
+        Res_SimCountResults( p, &nDcs, &nOnes, &nZeros, fVerbose );
+        Res_SimCollectPatterns( p, fVerbose );
+    }
+    // create bit-matrix info
+    if ( p->nPats0 < p->nPats )
+        Res_SimPadSimInfo( p->vPats0, p->nPats0, p->nWords );
+    if ( p->nPats1 < p->nPats )
+        Res_SimPadSimInfo( p->vPats1, p->nPats1, p->nWords );
+    // resimulate 0-patterns
+    Res_SimSetGiven( p, p->vPats0 );
+    Res_SimPerformRound( p, p->nWords );
+//Res_SimPrintNodePatterns( p, pAig );
+    Res_SimDeriveInfoReplicate( p );
+    // resimulate 1-patterns
+    Res_SimSetGiven( p, p->vPats1 );
+    Res_SimPerformRound( p, p->nWords );
+//Res_SimPrintNodePatterns( p, pAig );
+    Res_SimDeriveInfoComplement( p );
+    // print output patterns
+//    Res_SimPrintOutPatterns( p, pAig );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/res/resSim_old.c b/abc-build/src/opt/res/resSim_old.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/res/resSim_old.c
@@ -0,0 +1,526 @@
+/**CFile****************************************************************
+
+  FileName    [resSim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resynthesis package.]
+
+  Synopsis    [Simulation engine.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 15, 2007.]
+
+  Revision    [$Id: resSim.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "resInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocate simulation engine.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+Res_Sim_t * Res_SimAlloc( int nWords )
+{
+    Res_Sim_t * p;
+    p = ALLOC( Res_Sim_t, 1 );
+    memset( p, 0, sizeof(Res_Sim_t) );
+    // simulation parameters
+    p->nWords    = nWords;
+    p->nPats     = 8 * sizeof(unsigned) * p->nWords;
+    p->nWordsOut = p->nPats * p->nWords;
+    p->nPatsOut  = p->nPats * p->nPats;
+    // simulation info
+    p->vPats     = Vec_PtrAllocSimInfo( 1024, p->nWords );
+    p->vPats0    = Vec_PtrAllocSimInfo( 128,  p->nWords );
+    p->vPats1    = Vec_PtrAllocSimInfo( 128,  p->nWords );
+    p->vOuts     = Vec_PtrAllocSimInfo( 128,  p->nWordsOut );
+    // resub candidates
+    p->vCands    = Vec_VecStart( 16 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocate simulation engine.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimAdjust( Res_Sim_t * p, Abc_Ntk_t * pAig )
+{
+    srand( 0xABC );
+
+    assert( Abc_NtkIsStrash(pAig) );
+    p->pAig = pAig;
+    if ( Vec_PtrSize(p->vPats) < Abc_NtkObjNumMax(pAig)+1 )
+    {
+        Vec_PtrFree( p->vPats );
+        p->vPats = Vec_PtrAllocSimInfo( Abc_NtkObjNumMax(pAig)+1, p->nWords );
+    }
+    if ( Vec_PtrSize(p->vPats0) < Abc_NtkPiNum(pAig) )
+    {
+        Vec_PtrFree( p->vPats0 );
+        p->vPats0 = Vec_PtrAllocSimInfo( Abc_NtkPiNum(pAig), p->nWords );
+    }
+    if ( Vec_PtrSize(p->vPats1) < Abc_NtkPiNum(pAig) )
+    {
+        Vec_PtrFree( p->vPats1 );
+        p->vPats1 = Vec_PtrAllocSimInfo( Abc_NtkPiNum(pAig), p->nWords );
+    }
+    if ( Vec_PtrSize(p->vOuts) < Abc_NtkPoNum(pAig) )
+    {
+        Vec_PtrFree( p->vOuts );
+        p->vOuts = Vec_PtrAllocSimInfo( Abc_NtkPoNum(pAig), p->nWordsOut );
+    }
+    // clean storage info for patterns
+    Abc_InfoClear( Vec_PtrEntry(p->vPats0,0), p->nWords * Abc_NtkPiNum(pAig) );
+    Abc_InfoClear( Vec_PtrEntry(p->vPats1,0), p->nWords * Abc_NtkPiNum(pAig) );
+    p->nPats0 = 0;
+    p->nPats1 = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Free simulation engine.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimFree( Res_Sim_t * p )
+{
+    Vec_PtrFree( p->vPats );
+    Vec_PtrFree( p->vPats0 );
+    Vec_PtrFree( p->vPats1 );
+    Vec_PtrFree( p->vOuts );
+    Vec_VecFree( p->vCands );
+    free( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sets random PI simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimSetRandom( Res_Sim_t * p )
+{
+    Abc_Obj_t * pObj;
+    unsigned * pInfo;
+    int i;
+    Abc_NtkForEachPi( p->pAig, pObj, i )
+    {
+        pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+        Abc_InfoRandom( pInfo, p->nWords );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets given PI simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimSetGiven( Res_Sim_t * p, Vec_Ptr_t * vInfo )
+{
+    Abc_Obj_t * pObj;
+    unsigned * pInfo, * pInfo2;
+    int i, w;
+    Abc_NtkForEachPi( p->pAig, pObj, i )
+    {
+        pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+        pInfo2 = Vec_PtrEntry( vInfo, i );
+        for ( w = 0; w < p->nWords; w++ )
+            pInfo[w] = pInfo2[w];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimPerformOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords )
+{
+    unsigned * pInfo, * pInfo1, * pInfo2;
+    int k, fComp1, fComp2;
+    // simulate the internal nodes
+    assert( Abc_ObjIsNode(pNode) );
+    pInfo  = Vec_PtrEntry(vSimInfo, pNode->Id);
+    pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
+    pInfo2 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode));
+    fComp1 = Abc_ObjFaninC0(pNode);
+    fComp2 = Abc_ObjFaninC1(pNode);
+    if ( fComp1 && fComp2 )
+        for ( k = 0; k < nSimWords; k++ )
+            pInfo[k] = ~pInfo1[k] & ~pInfo2[k];
+    else if ( fComp1 && !fComp2 )
+        for ( k = 0; k < nSimWords; k++ )
+            pInfo[k] = ~pInfo1[k] &  pInfo2[k];
+    else if ( !fComp1 && fComp2 )
+        for ( k = 0; k < nSimWords; k++ )
+            pInfo[k] =  pInfo1[k] & ~pInfo2[k];
+    else // if ( fComp1 && fComp2 )
+        for ( k = 0; k < nSimWords; k++ )
+            pInfo[k] =  pInfo1[k] &  pInfo2[k];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one CO node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimTransferOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords )
+{
+    unsigned * pInfo, * pInfo1;
+    int k, fComp1;
+    // simulate the internal nodes
+    assert( Abc_ObjIsCo(pNode) );
+    pInfo  = Vec_PtrEntry(vSimInfo, pNode->Id);
+    pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
+    fComp1 = Abc_ObjFaninC0(pNode);
+    if ( fComp1 )
+        for ( k = 0; k < nSimWords; k++ )
+            pInfo[k] = ~pInfo1[k];
+    else 
+        for ( k = 0; k < nSimWords; k++ )
+            pInfo[k] =  pInfo1[k];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one round of simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimPerformRound( Res_Sim_t * p )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_InfoFill( Vec_PtrEntry(p->vPats,0), p->nWords );
+    Abc_AigForEachAnd( p->pAig, pObj, i )
+        Res_SimPerformOne( pObj, p->vPats, p->nWords );
+    Abc_NtkForEachPo( p->pAig, pObj, i )
+        Res_SimTransferOne( pObj, p->vPats, p->nWords );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Processes simulation patterns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimProcessPats( Res_Sim_t * p )
+{
+    Abc_Obj_t * pObj;
+    unsigned * pInfoCare, * pInfoNode;
+    int i, j, nDcs = 0;
+    pInfoCare = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id );
+    pInfoNode = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
+    for ( i = 0; i < p->nPats; i++ )
+    {
+        // skip don't-care patterns
+        if ( !Abc_InfoHasBit(pInfoCare, i) )
+        {
+            nDcs++;
+            continue;
+        }
+        // separate offset and onset patterns
+        if ( !Abc_InfoHasBit(pInfoNode, i) )
+        {
+            if ( p->nPats0 >= p->nPats )
+                continue;
+            Abc_NtkForEachPi( p->pAig, pObj, j )
+                if ( Abc_InfoHasBit( Vec_PtrEntry(p->vPats, pObj->Id), i ) )
+                    Abc_InfoSetBit( Vec_PtrEntry(p->vPats0, j), p->nPats0 );
+            p->nPats0++;
+        }
+        else
+        {
+            if ( p->nPats1 >= p->nPats )
+                continue;
+            Abc_NtkForEachPi( p->pAig, pObj, j )
+                if ( Abc_InfoHasBit( Vec_PtrEntry(p->vPats, pObj->Id), i ) )
+                    Abc_InfoSetBit( Vec_PtrEntry(p->vPats1, j), p->nPats1 );
+            p->nPats1++;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Pads the extra space with duplicated simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimPadSimInfo( Vec_Ptr_t * vPats, int nPats, int nWords )
+{
+    unsigned * pInfo;
+    int i, w, iWords;
+    assert( nPats > 0 && nPats < nWords * 8 * (int) sizeof(unsigned) );
+    // pad the first word
+    if ( nPats < 8 * sizeof(unsigned) )
+    {
+        Vec_PtrForEachEntry( unsigned *, vPats, pInfo, i )
+            if ( pInfo[0] & 1 )
+                pInfo[0] |= ((~0) << nPats);
+        nPats = 8 * sizeof(unsigned);
+    }
+    // pad the empty words
+    iWords = nPats / (8 * sizeof(unsigned));
+    Vec_PtrForEachEntry( unsigned *, vPats, pInfo, i )
+    {
+        for ( w = iWords; w < nWords; w++ )
+            pInfo[w] = pInfo[0];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the simulation info to fill the space.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimDeriveInfoReplicate( Res_Sim_t * p )
+{
+    unsigned * pInfo, * pInfo2;
+    Abc_Obj_t * pObj;
+    int i, j, w;
+    Abc_NtkForEachPo( p->pAig, pObj, i )
+    {
+        pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+        pInfo2 = Vec_PtrEntry( p->vOuts, i );
+        for ( j = 0; j < p->nPats; j++ )
+            for ( w = 0; w < p->nWords; w++ )
+                *pInfo2++ = pInfo[w];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Complement the simulation info if necessary.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimDeriveInfoComplement( Res_Sim_t * p )
+{
+    unsigned * pInfo, * pInfo2;
+    Abc_Obj_t * pObj;
+    int i, j, w;
+    Abc_NtkForEachPo( p->pAig, pObj, i )
+    {
+        pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+        pInfo2 = Vec_PtrEntry( p->vOuts, i );
+        for ( j = 0; j < p->nPats; j++, pInfo2 += p->nWords )
+            if ( Abc_InfoHasBit( pInfo, j ) )
+                for ( w = 0; w < p->nWords; w++ )
+                    pInfo2[w] = ~pInfo2[w];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Free simulation engine.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimReportOne( Res_Sim_t * p )
+{
+    unsigned * pInfoCare, * pInfoNode;
+    int i, nDcs, nOnes, nZeros;
+    pInfoCare = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id );
+    pInfoNode = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
+    nDcs = nOnes = nZeros = 0;
+    for ( i = 0; i < p->nPats; i++ )
+    {
+        // skip don't-care patterns
+        if ( !Abc_InfoHasBit(pInfoCare, i) )
+        {
+            nDcs++;
+            continue;
+        }
+        // separate offset and onset patterns
+        if ( !Abc_InfoHasBit(pInfoNode, i) )
+            nZeros++;
+        else
+            nOnes++;
+    }
+    printf( "On = %3d (%7.2f %%)  ",  nOnes,  100.0*nOnes/p->nPats );
+    printf( "Off = %3d (%7.2f %%)  ", nZeros, 100.0*nZeros/p->nPats );
+    printf( "Dc = %3d (%7.2f %%)  ",  nDcs,   100.0*nDcs/p->nPats );
+    printf( "P0 = %3d ", p->nPats0 );
+    printf( "P1 = %3d ", p->nPats1 );
+    if ( p->nPats0 < 4 || p->nPats1 < 4 )
+        printf( "*" );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints output patterns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_SimPrintOutPatterns( Res_Sim_t * p, Abc_Ntk_t * pAig )
+{
+    Abc_Obj_t * pObj;
+    unsigned * pInfo2;
+    int i;
+    Abc_NtkForEachPo( pAig, pObj, i )
+    {
+        pInfo2 = Vec_PtrEntry( p->vOuts, i );
+        Extra_PrintBinary( stdout, pInfo2, p->nPatsOut );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares simulation info for candidate filtering.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose )
+{
+    int Limit;
+    // prepare the manager
+    Res_SimAdjust( p, pAig );
+    // collect 0/1 simulation info
+    for ( Limit = 0; Limit < 10; Limit++ )
+    {
+        Res_SimSetRandom( p );
+        Res_SimPerformRound( p );
+        Res_SimProcessPats( p );
+        if ( !(p->nPats0 < p->nPats || p->nPats1 < p->nPats) )
+            break;
+    }
+//    printf( "%d   ", Limit );
+    // report the last set of patterns
+//    Res_SimReportOne( p );
+//    printf( "\n" );
+    // quit if there is not enough
+//    if ( p->nPats0 < 4 || p->nPats1 < 4 )
+    if ( p->nPats0 < 4 || p->nPats1 < 4 )
+    {
+//        Res_SimReportOne( p );
+        return 0;
+    }
+    // create bit-matrix info
+    if ( p->nPats0 < p->nPats )
+        Res_SimPadSimInfo( p->vPats0, p->nPats0, p->nWords );
+    if ( p->nPats1 < p->nPats )
+        Res_SimPadSimInfo( p->vPats1, p->nPats1, p->nWords );
+    // resimulate 0-patterns
+    Res_SimSetGiven( p, p->vPats0 );
+    Res_SimPerformRound( p );
+    Res_SimDeriveInfoReplicate( p );
+    // resimulate 1-patterns
+    Res_SimSetGiven( p, p->vPats1 );
+    Res_SimPerformRound( p );
+    Res_SimDeriveInfoComplement( p );
+    // print output patterns
+//    Res_SimPrintOutPatterns( p, pAig );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/res/resStrash.c b/abc-build/src/opt/res/resStrash.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/res/resStrash.c
@@ -0,0 +1,122 @@
+/**CFile****************************************************************
+
+  FileName    [resStrash.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resynthesis package.]
+
+  Synopsis    [Structural hashing of the nodes in the window.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 15, 2007.]
+
+  Revision    [$Id: resStrash.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "resInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern Abc_Obj_t * Abc_ConvertAigToAig( Abc_Ntk_t * pAig, Abc_Obj_t * pObjOld );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Structurally hashes the given window.]
+
+  Description [The first PO is the observability condition. The second 
+  is the node's function. The remaining POs are the candidate divisors.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Res_WndStrash( Res_Win_t * p )
+{
+    Vec_Ptr_t * vPairs;
+    Abc_Ntk_t * pAig;
+    Abc_Obj_t * pObj, * pMiter;
+    int i;
+    assert( Abc_NtkHasAig(p->pNode->pNtk) );
+//    Abc_NtkCleanCopy( p->pNode->pNtk );
+    // create the network
+    pAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    pAig->pName = Extra_UtilStrsav( "window" );
+    // create the inputs
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, i )
+        pObj->pCopy = Abc_NtkCreatePi( pAig );
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vBranches, pObj, i )
+        pObj->pCopy = Abc_NtkCreatePi( pAig );
+    // go through the nodes in the topological order
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodes, pObj, i )
+    {
+        pObj->pCopy = Abc_ConvertAigToAig( pAig, pObj );
+        if ( pObj == p->pNode )
+            pObj->pCopy = Abc_ObjNot( pObj->pCopy );
+    }
+    // collect the POs
+    vPairs = Vec_PtrAlloc( 2 * Vec_PtrSize(p->vRoots) );
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i )
+    {
+        Vec_PtrPush( vPairs, pObj->pCopy );
+        Vec_PtrPush( vPairs, NULL );
+    }
+    // mark the TFO of the node
+    Abc_NtkIncrementTravId( p->pNode->pNtk );
+    Res_WinSweepLeafTfo_rec( p->pNode, (int)p->pNode->Level + p->nWinTfoMax );
+    // update strashing of the node
+    p->pNode->pCopy = Abc_ObjNot( p->pNode->pCopy );
+    Abc_NodeSetTravIdPrevious( p->pNode );
+    // redo strashing in the TFO
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodes, pObj, i )
+    {
+        if ( Abc_NodeIsTravIdCurrent(pObj) )
+            pObj->pCopy = Abc_ConvertAigToAig( pAig, pObj );
+    }
+    // collect the POs
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i )
+        Vec_PtrWriteEntry( vPairs, 2 * i + 1, pObj->pCopy );
+    // add the miter
+    pMiter = Abc_AigMiter( (Abc_Aig_t *)pAig->pManFunc, vPairs, 0 );
+    Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pMiter );
+    Vec_PtrFree( vPairs );
+    // add the node
+    Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), p->pNode->pCopy );
+    // add the fanins
+    Abc_ObjForEachFanin( p->pNode, pObj, i )
+        Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pObj->pCopy );
+    // add the divisors
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs, pObj, i )
+        Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pObj->pCopy );
+    // add the names
+    Abc_NtkAddDummyPiNames( pAig );
+    Abc_NtkAddDummyPoNames( pAig );
+    // check the resulting network
+    if ( !Abc_NtkCheck( pAig ) )
+        fprintf( stdout, "Res_WndStrash(): Network check has failed.\n" );
+    return pAig;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/res/resWin.c b/abc-build/src/opt/res/resWin.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/res/resWin.c
@@ -0,0 +1,490 @@
+/**CFile****************************************************************
+
+  FileName    [resWin.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resynthesis package.]
+
+  Synopsis    [Windowing algorithm.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 15, 2007.]
+
+  Revision    [$Id: resWin.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "resInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the window.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Res_Win_t * Res_WinAlloc()
+{
+    Res_Win_t * p;
+    // start the manager
+    p = ABC_ALLOC( Res_Win_t, 1 );
+    memset( p, 0, sizeof(Res_Win_t) );
+    // set internal parameters
+    p->nFanoutLimit = 10;
+    p->nLevTfiMinus =  3;
+    // allocate storage
+    p->vRoots    = Vec_PtrAlloc( 256 );
+    p->vLeaves   = Vec_PtrAlloc( 256 );
+    p->vBranches = Vec_PtrAlloc( 256 );
+    p->vNodes    = Vec_PtrAlloc( 256 );
+    p->vDivs     = Vec_PtrAlloc( 256 );
+    p->vMatrix   = Vec_VecStart( 128 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the window.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_WinFree( Res_Win_t * p )
+{
+    Vec_PtrFree( p->vRoots  );
+    Vec_PtrFree( p->vLeaves );
+    Vec_PtrFree( p->vBranches );
+    Vec_PtrFree( p->vNodes  );
+    Vec_PtrFree( p->vDivs   );
+    Vec_VecFree( p->vMatrix );
+    ABC_FREE( p );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collect the limited TFI cone of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_WinCollectLeavesAndNodes( Res_Win_t * p )
+{
+    Vec_Ptr_t * vFront;
+    Abc_Obj_t * pObj, * pTemp;
+    int i, k, m;
+
+    assert( p->nWinTfiMax > 0 );
+    assert( Vec_VecSize(p->vMatrix) > p->nWinTfiMax );
+
+    // start matrix with the node
+    Vec_VecClear( p->vMatrix );
+    Vec_VecPush( p->vMatrix, 0, p->pNode );
+    Abc_NtkIncrementTravId( p->pNode->pNtk );
+    Abc_NodeSetTravIdCurrent( p->pNode );
+
+    // collect the leaves (nodes pTemp such that "p->pNode->Level - pTemp->Level > p->nWinTfiMax")
+    Vec_PtrClear( p->vLeaves );
+    Vec_VecForEachLevelStartStop( p->vMatrix, vFront, i, 0, p->nWinTfiMax+1 )
+    {
+        Vec_PtrForEachEntry( Abc_Obj_t *, vFront, pObj, k )
+        {
+            Abc_ObjForEachFanin( pObj, pTemp, m )
+            {
+                if ( Abc_NodeIsTravIdCurrent( pTemp ) )
+                    continue;
+                Abc_NodeSetTravIdCurrent( pTemp );
+                if ( Abc_ObjIsCi(pTemp) || (int)(p->pNode->Level - pTemp->Level) > p->nWinTfiMax )                    
+                    Vec_PtrPush( p->vLeaves, pTemp );
+                else
+                    Vec_VecPush( p->vMatrix, p->pNode->Level - pTemp->Level, pTemp );
+            }
+        }
+    }
+    if ( Vec_PtrSize(p->vLeaves) == 0 )
+        return 0;
+
+    // collect the nodes in the reverse order
+    Vec_PtrClear( p->vNodes );
+    Vec_VecForEachLevelReverseStartStop( p->vMatrix, vFront, i, p->nWinTfiMax+1, 0 )
+    {
+        Vec_PtrForEachEntry( Abc_Obj_t *, vFront, pObj, k )
+            Vec_PtrPush( p->vNodes, pObj );
+        Vec_PtrClear( vFront );
+    }
+
+    // get the lowest leaf level
+    p->nLevLeafMin = ABC_INFINITY;
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, k )
+        p->nLevLeafMin = Abc_MinInt( p->nLevLeafMin, (int)pObj->Level );
+
+    // set minimum traversal level
+    p->nLevTravMin = Abc_MaxInt( ((int)p->pNode->Level) - p->nWinTfiMax - p->nLevTfiMinus, p->nLevLeafMin );
+    assert( p->nLevTravMin >= 0 );
+    return 1;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node should be a root.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Res_WinComputeRootsCheck( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    // the node is the root if one of the following is true:
+    // (1) the node has more than fanouts than the limit
+    if ( Abc_ObjFanoutNum(pNode) > nFanoutLimit )
+        return 1;
+    // (2) the node has CO fanouts
+    // (3) the node has fanouts above the cutoff level
+    Abc_ObjForEachFanout( pNode, pFanout, i )
+        if ( Abc_ObjIsCo(pFanout) || (int)pFanout->Level > nLevelMax )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively collects the root candidates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_WinComputeRoots_rec( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit, Vec_Ptr_t * vRoots )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    assert( Abc_ObjIsNode(pNode) );
+    if ( Abc_NodeIsTravIdCurrent(pNode) )
+        return;
+    Abc_NodeSetTravIdCurrent( pNode );
+    // check if the node should be the root
+    if ( Res_WinComputeRootsCheck( pNode, nLevelMax, nFanoutLimit ) )
+        Vec_PtrPush( vRoots, pNode );
+    else // if not, explore its fanouts
+        Abc_ObjForEachFanout( pNode, pFanout, i )
+            Res_WinComputeRoots_rec( pFanout, nLevelMax, nFanoutLimit, vRoots );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively collects the root candidates.]
+
+  Description [Returns 1 if the only root is this node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_WinComputeRoots( Res_Win_t * p )
+{
+    Vec_PtrClear( p->vRoots );
+    Abc_NtkIncrementTravId( p->pNode->pNtk );
+    Res_WinComputeRoots_rec( p->pNode, p->pNode->Level + p->nWinTfoMax, p->nFanoutLimit, p->vRoots );
+    assert( Vec_PtrSize(p->vRoots) > 0 );
+    if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode )
+        return 0;
+    return 1;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the paths from the roots to the leaves.]
+
+  Description [Returns 1 if the the node can reach a leaf.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_WinMarkPaths_rec( Abc_Obj_t * pNode, Abc_Obj_t * pPivot, int nLevelMin )
+{
+    Abc_Obj_t * pFanin;
+    int i, RetValue;
+    // skip visited nodes
+    if ( Abc_NodeIsTravIdCurrent(pNode) )
+        return 1;
+    if ( Abc_NodeIsTravIdPrevious(pNode) )
+        return 0;
+    // assume that the node does not have access to the leaves
+    Abc_NodeSetTravIdPrevious( pNode );
+    // skip nodes below the given level
+    if ( pNode == pPivot || (int)pNode->Level <= nLevelMin )
+        return 0;
+    assert( Abc_ObjIsNode(pNode) );
+    // check if the fanins have access to the leaves
+    RetValue = 0;
+    Abc_ObjForEachFanin( pNode, pFanin, i )
+        RetValue |= Res_WinMarkPaths_rec( pFanin, pPivot, nLevelMin );
+    // relabel the node if it has access to the leaves
+    if ( RetValue )
+        Abc_NodeSetTravIdCurrent( pNode );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the paths from the roots to the leaves.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_WinMarkPaths( Res_Win_t * p )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    // mark the leaves
+    Abc_NtkIncrementTravId( p->pNode->pNtk );
+    Abc_NtkIncrementTravId( p->pNode->pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, i )
+        Abc_NodeSetTravIdCurrent( pObj );
+    // traverse from the roots and mark the nodes that can reach leaves
+    // the nodes that do not reach leaves have previous trav ID
+    // the nodes that reach leaves have current trav ID
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i )
+        Res_WinMarkPaths_rec( pObj, p->pNode, p->nLevTravMin );
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively collects the roots.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_WinFinalizeRoots_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vRoots )
+{
+    Abc_Obj_t * pFanout;
+    int i;
+    assert( Abc_ObjIsNode(pObj) );
+    assert( Abc_NodeIsTravIdCurrent(pObj) );
+    // check if the node has all fanouts marked
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        if ( !Abc_NodeIsTravIdCurrent(pFanout) )
+            break;
+    // if some of the fanouts are unmarked, add the node to the roots
+    if ( i < Abc_ObjFanoutNum(pObj) ) 
+        Vec_PtrPushUnique( vRoots, pObj );
+    else  // otherwise, call recursively
+        Abc_ObjForEachFanout( pObj, pFanout, i )
+            Res_WinFinalizeRoots_rec( pFanout, vRoots );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finalizes the roots of the window.]
+
+  Description [Roots of the window are the nodes that have at least
+  one fanout that it not in the TFO of the leaves.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_WinFinalizeRoots( Res_Win_t * p )
+{
+    assert( !Abc_NodeIsTravIdCurrent(p->pNode) );
+    // mark the node with the old traversal ID
+    Abc_NodeSetTravIdCurrent( p->pNode ); 
+    // recollect the roots
+    Vec_PtrClear( p->vRoots );
+    Res_WinFinalizeRoots_rec( p->pNode, p->vRoots );
+    assert( Vec_PtrSize(p->vRoots) > 0 );
+    if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode )
+        return 0;
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively adds missing nodes and leaves.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_WinAddMissing_rec( Res_Win_t * p, Abc_Obj_t * pObj, int nLevTravMin )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    // skip the already collected leaves, nodes, and branches
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return;
+    // if this is not an internal node - make it a new branch
+    if ( !Abc_NodeIsTravIdPrevious(pObj) )
+    {
+        assert( Vec_PtrFind(p->vLeaves, pObj) == -1 );
+        Abc_NodeSetTravIdCurrent( pObj );
+        Vec_PtrPush( p->vBranches, pObj );
+        return;
+    }
+    assert( Abc_ObjIsNode(pObj) ); // if this is a CI, then the window is incorrect!
+    Abc_NodeSetTravIdCurrent( pObj );
+    // visit the fanins of the node
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        Res_WinAddMissing_rec( p, pFanin, nLevTravMin );
+    // collect the node
+    Vec_PtrPush( p->vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds to the window nodes and leaves in the TFI of the roots.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Res_WinAddMissing( Res_Win_t * p )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    // mark the leaves
+    Abc_NtkIncrementTravId( p->pNode->pNtk );
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, i )
+        Abc_NodeSetTravIdCurrent( pObj );        
+    // mark the already collected nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodes, pObj, i )
+        Abc_NodeSetTravIdCurrent( pObj );        
+    // explore from the roots
+    Vec_PtrClear( p->vBranches );
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i )
+        Res_WinAddMissing_rec( p, pObj, p->nLevTravMin );
+}
+
+
+
+ 
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the window is trivial (without TFO).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_WinIsTrivial( Res_Win_t * p )
+{
+    return Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the window.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Res_WinCompute( Abc_Obj_t * pNode, int nWinTfiMax, int nWinTfoMax, Res_Win_t * p )
+{
+    assert( Abc_ObjIsNode(pNode) );
+    assert( nWinTfiMax > 0 && nWinTfiMax < 10 );
+    assert( nWinTfoMax >= 0 && nWinTfoMax < 10 );
+
+    // initialize the window
+    p->pNode      = pNode;
+    p->nWinTfiMax = nWinTfiMax;
+    p->nWinTfoMax = nWinTfoMax;
+
+    Vec_PtrClear( p->vBranches );
+    Vec_PtrClear( p->vDivs );
+    Vec_PtrClear( p->vRoots );
+    Vec_PtrPush( p->vRoots, pNode );
+
+    // compute the leaves
+    if ( !Res_WinCollectLeavesAndNodes( p ) )
+        return 0;
+
+    // compute the candidate roots
+    if ( p->nWinTfoMax > 0 && Res_WinComputeRoots(p) )
+    {
+        // mark the paths from the roots to the leaves
+        Res_WinMarkPaths( p );
+        // refine the roots and add branches and missing nodes
+        if ( Res_WinFinalizeRoots( p ) )
+            Res_WinAddMissing( p );
+    }
+
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/res/res_.c b/abc-build/src/opt/res/res_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/res/res_.c
@@ -0,0 +1,55 @@
+/**CFile****************************************************************
+
+  FileName    [res_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Resynthesis package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 15, 2007.]
+
+  Revision    [$Id: res_.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "res.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/ret/module.make b/abc-build/src/opt/ret/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/ret/module.make
@@ -0,0 +1,8 @@
+SRC +=  src/opt/ret/retArea.c \
+        src/opt/ret/retCore.c \
+        src/opt/ret/retDelay.c \
+        src/opt/ret/retFlow.c \
+        src/opt/ret/retIncrem.c \
+        src/opt/ret/retInit.c \
+        src/opt/ret/retLvalue.c
+
diff --git a/abc-build/src/opt/ret/retArea.c b/abc-build/src/opt/ret/retArea.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/ret/retArea.c
@@ -0,0 +1,544 @@
+/**CFile****************************************************************
+
+  FileName    [retArea.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Retiming package.]
+
+  Synopsis    [Min-area retiming.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Oct 31, 2006.]
+
+  Revision    [$Id: retArea.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t * Abc_NtkRetimeMinAreaOne( Abc_Ntk_t * pNtk, int fForward, int fVerbose );
+static void        Abc_NtkRetimeMinAreaPrepare( Abc_Ntk_t * pNtk, int fForward );
+static void        Abc_NtkRetimeMinAreaInitValues( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut );
+static Abc_Ntk_t * Abc_NtkRetimeMinAreaConstructNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut );
+static void        Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward );
+
+extern Abc_Ntk_t * Abc_NtkAttachBottom( Abc_Ntk_t * pNtkTop, Abc_Ntk_t * pNtkBottom );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs min-area retiming.]
+
+  Description [Returns the number of latches reduced.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeMinArea( Abc_Ntk_t * pNtk, int fForwardOnly, int fBackwardOnly, int fVerbose )
+{
+    Abc_Ntk_t * pNtkTotal = NULL, * pNtkBottom;
+    Vec_Int_t * vValuesNew = NULL, * vValues;
+    int nLatches = Abc_NtkLatchNum(pNtk);
+    int fOneFrame = 0;
+    assert( !fForwardOnly || !fBackwardOnly );
+    // there should not be black boxes
+    assert( Abc_NtkIsSopLogic(pNtk) );
+    assert( Abc_NtkLatchNum(pNtk) == Vec_PtrSize(pNtk->vBoxes) );
+    // reorder CI/CO/latch inputs
+    Abc_NtkOrderCisCos( pNtk );
+    // perform forward retiming
+    if ( !fBackwardOnly )
+    {
+        if ( fOneFrame )
+            Abc_NtkRetimeMinAreaOne( pNtk, 1, fVerbose );
+        else
+            while ( Abc_NtkRetimeMinAreaOne( pNtk, 1, fVerbose ) );
+    }
+    // remember initial values
+    vValues = Abc_NtkCollectLatchValues( pNtk );
+    // perform backward retiming
+    if ( !fForwardOnly )
+    {
+        if ( fOneFrame )
+            pNtkTotal = Abc_NtkRetimeMinAreaOne( pNtk, 0, fVerbose );
+        else
+            while ( (pNtkBottom = Abc_NtkRetimeMinAreaOne( pNtk, 0, fVerbose )) )
+                pNtkTotal = Abc_NtkAttachBottom( pNtkTotal, pNtkBottom );  
+    }
+    // compute initial values
+    vValuesNew = Abc_NtkRetimeInitialValues( pNtkTotal, vValues, fVerbose );
+    if ( pNtkTotal ) Abc_NtkDelete( pNtkTotal );
+    // insert new initial values
+    Abc_NtkInsertLatchValues( pNtk, vValuesNew );
+    if ( vValuesNew ) Vec_IntFree( vValuesNew );
+    if ( vValues )    Vec_IntFree( vValues );
+    // fix the COs (this changes the circuit structure)
+//    Abc_NtkLogicMakeSimpleCos( pNtk, 0 );
+    // check for correctness
+    if ( !Abc_NtkCheck( pNtk ) )
+        fprintf( stdout, "Abc_NtkRetimeMinArea(): Network check has failed.\n" );
+    // return the number of latches saved
+    return nLatches - Abc_NtkLatchNum(pNtk);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs min-area retiming backward.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRetimeMinAreaOne( Abc_Ntk_t * pNtk, int fForward, int fVerbose )
+{ 
+    Abc_Ntk_t * pNtkNew = NULL;
+    Vec_Ptr_t * vMinCut;
+    // mark current latches and TFI(POs)
+    Abc_NtkRetimeMinAreaPrepare( pNtk, fForward );
+    // run the maximum forward flow
+    vMinCut = Abc_NtkMaxFlow( pNtk, fForward, fVerbose );
+//    assert( Vec_PtrSize(vMinCut) <= Abc_NtkLatchNum(pNtk) );
+    // create new latch boundary if there is improvement
+    if ( Vec_PtrSize(vMinCut) < Abc_NtkLatchNum(pNtk) )
+    {
+        pNtkNew = (Abc_Ntk_t *)1;
+        if ( fForward )
+            Abc_NtkRetimeMinAreaInitValues( pNtk, vMinCut );
+        else
+            pNtkNew = Abc_NtkRetimeMinAreaConstructNtk( pNtk, vMinCut );
+        Abc_NtkRetimeMinAreaUpdateLatches( pNtk, vMinCut, fForward );
+    }
+    // clean up
+    Vec_PtrFree( vMinCut );
+    Abc_NtkCleanMarkA( pNtk );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the cone with MarkA.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward )
+{
+    Abc_Obj_t * pNext;
+    int i;
+    if ( pObj->fMarkA )
+        return;
+    pObj->fMarkA = 1;
+    if ( fForward )
+    {
+        Abc_ObjForEachFanout( pObj, pNext, i )
+            Abc_NtkMarkCone_rec( pNext, fForward );
+    }
+    else
+    {
+        Abc_ObjForEachFanin( pObj, pNext, i )
+            Abc_NtkMarkCone_rec( pNext, fForward );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the cone with MarkA.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkUnmarkCone_rec( Abc_Obj_t * pObj, int fForward )
+{
+    Abc_Obj_t * pNext;
+    int i;
+    if ( !pObj->fMarkA || Abc_ObjIsLatch(pObj) )
+        return;
+    pObj->fMarkA = 0;
+    if ( fForward )
+    {
+        Abc_ObjForEachFanout( pObj, pNext, i )
+            Abc_NtkUnmarkCone_rec( pNext, fForward );
+    }
+    else
+    {
+        Abc_ObjForEachFanin( pObj, pNext, i )
+            Abc_NtkUnmarkCone_rec( pNext, fForward );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the network for running MaxFlow.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkRetimeMinAreaPrepare( Abc_Ntk_t * pNtk, int fForward )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k;
+    if ( fForward )
+    {
+        // mark the frontier
+        Abc_NtkForEachPo( pNtk, pObj, i )
+            pObj->fMarkA = 1;
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+        {
+            pObj->fMarkA = 1;
+            Abc_ObjFanin0(pObj)->fMarkA = 1;
+        }
+        // mark the nodes reachable from the PIs
+        Abc_NtkForEachPi( pNtk, pObj, i )
+            Abc_NtkMarkCone_rec( pObj, fForward );
+        // collect the unmarked fanins of the marked nodes
+        vNodes = Vec_PtrAlloc( 100 );
+        Abc_NtkForEachObj( pNtk, pObj, i )
+            if ( pObj->fMarkA )
+                Abc_ObjForEachFanin( pObj, pFanin, k )
+                    if ( !pFanin->fMarkA )
+                        Vec_PtrPush( vNodes, pFanin );
+        // mark these nodes
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+            pObj->fMarkA = 1;
+        Vec_PtrFree( vNodes );
+    }
+    else
+    {
+        // mark the frontier
+        Abc_NtkForEachPi( pNtk, pObj, i )
+            pObj->fMarkA = 1;
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+        {
+            pObj->fMarkA = 1;
+            Abc_ObjFanout0(pObj)->fMarkA = 1;
+        }
+        // mark the nodes reachable from the POs
+        Abc_NtkForEachPo( pNtk, pObj, i )
+            Abc_NtkMarkCone_rec( pObj, fForward );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute initial values.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeMinAreaInitValues_rec( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    // skip visited nodes
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return (int)(ABC_PTRUINT_T)pObj->pCopy;
+    Abc_NodeSetTravIdCurrent(pObj);
+    // consider the case of a latch output
+    if ( Abc_ObjIsBo(pObj) )
+    {
+        assert( Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) );
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_NtkRetimeMinAreaInitValues_rec( Abc_ObjFanin0(pObj) );
+        return (int)(ABC_PTRUINT_T)pObj->pCopy;
+    }
+    assert( Abc_ObjIsNode(pObj) );
+    // visit the fanins
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        Abc_NtkRetimeMinAreaInitValues_rec( pFanin );
+    // compute the value of the node
+    pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_ObjSopSimulate(pObj);
+    return (int)(ABC_PTRUINT_T)pObj->pCopy;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute initial values.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkRetimeMinAreaInitValues( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    // transfer initial values to pCopy and mark the latches
+    Abc_NtkIncrementTravId(pNtk);
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+    {
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_LatchIsInit1(pObj);
+        Abc_NodeSetTravIdCurrent( pObj );
+    }
+    // propagate initial values
+    Vec_PtrForEachEntry( Abc_Obj_t *, vMinCut, pObj, i )
+        Abc_NtkRetimeMinAreaInitValues_rec( pObj );
+    // unmark the latches
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        Abc_NodeSetTravIdPrevious( pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs min-area retiming backward.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkRetimeMinAreaConstructNtk_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanin;
+    int i;
+    // skip visited nodes
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return pObj->pCopy;
+    Abc_NodeSetTravIdCurrent(pObj);
+    // consider the case of a latch output
+    if ( Abc_ObjIsBi(pObj) )
+    {
+        pObj->pCopy = Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, Abc_ObjFanin0(pObj) );
+        return pObj->pCopy;
+    }
+    assert( Abc_ObjIsNode(pObj) );
+    // visit the fanins
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, pFanin );
+    // compute the value of the node
+    Abc_NtkDupObj( pNtkNew, pObj, 0 );
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+    return pObj->pCopy;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the network from computing initial state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRetimeMinAreaConstructNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut )
+{
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObj, * pObjNew;
+    int i;
+    // create new network
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+    // map new latches into PIs of the new network
+    Abc_NtkIncrementTravId(pNtk);
+    Vec_PtrForEachEntry( Abc_Obj_t *, vMinCut, pObj, i )
+    {
+        pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+        Abc_NodeSetTravIdCurrent( pObj );
+    }
+    // construct the network recursively
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+    {
+        pObjNew = Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, Abc_ObjFanin0(pObj) );
+        Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pObjNew );
+    }
+    // unmark the nodes in the cut
+    Vec_PtrForEachEntry( Abc_Obj_t *, vMinCut, pObj, i )
+        Abc_NodeSetTravIdPrevious( pObj );
+    // unmark the latches
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        Abc_NodeSetTravIdPrevious( pObj );
+    // assign dummy node names
+    Abc_NtkAddDummyPiNames( pNtkNew );
+    Abc_NtkAddDummyPoNames( pNtkNew );
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkRetimeMinAreaConstructNtk(): Network check has failed.\n" );
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the network after backward retiming.]
+
+  Description [Assumes that fMarkA denotes all nodes reachabe from
+  the latches toward the cut.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward )
+{
+    Vec_Ptr_t * vCis, * vCos, * vBoxes, * vBoxesNew, * vNodes, * vBuffers;
+    Abc_Obj_t * pObj, * pLatch, * pLatchIn, * pLatchOut, * pNext, * pBuffer;
+    int i, k;
+    // create new latches
+    Vec_PtrShrink( pNtk->vCis, Abc_NtkCiNum(pNtk) - Abc_NtkLatchNum(pNtk) );
+    Vec_PtrShrink( pNtk->vCos, Abc_NtkCoNum(pNtk) - Abc_NtkLatchNum(pNtk) );
+    vCis   = pNtk->vCis;   pNtk->vCis   = NULL;  
+    vCos   = pNtk->vCos;   pNtk->vCos   = NULL;  
+    vBoxes = pNtk->vBoxes; pNtk->vBoxes = NULL; 
+    // transfer boxes
+    vBoxesNew = Vec_PtrAlloc(100);
+    Vec_PtrForEachEntry( Abc_Obj_t *, vBoxes, pObj, i )
+        if ( !Abc_ObjIsLatch(pObj) )
+            Vec_PtrPush( vBoxesNew, pObj );
+    // create or reuse latches
+    vNodes = Vec_PtrAlloc( 100 );
+    vBuffers = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vMinCut, pObj, i )
+    {
+        if ( Abc_ObjIsCi(pObj) && fForward )
+        {
+            pLatchOut = pObj;
+            pLatch    = Abc_ObjFanin0(pLatchOut);
+            pLatchIn  = Abc_ObjFanin0(pLatch);
+            assert( Abc_ObjIsBo(pLatchOut) && Abc_ObjIsLatch(pLatch) && Abc_ObjIsBi(pLatchIn) );
+            // mark the latch as reused
+            Abc_NodeSetTravIdCurrent( pLatch );
+
+            // check if there are marked fanouts
+            // (these are fanouts to be connected to the latch input)
+            Abc_ObjForEachFanout( pObj, pNext, k )
+                if ( pNext->fMarkA )
+                    break;
+            if ( k < Abc_ObjFanoutNum(pObj) )
+            {
+                // add the buffer
+                pBuffer = Abc_NtkCreateNodeBuf( pNtk, Abc_ObjFanin0(pLatchIn) );
+                Abc_ObjPatchFanin( pLatchIn, Abc_ObjFanin0(pLatchIn), pBuffer );
+                Vec_PtrPush( vBuffers, pBuffer );
+                // redirect edges to the unvisited fanouts of the node
+                Abc_NodeCollectFanouts( pObj, vNodes );
+                Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNext, k )
+                    if ( pNext->fMarkA )
+                        Abc_ObjPatchFanin( pNext, pObj, pBuffer );
+            }
+            assert( Abc_ObjFanoutNum(pObj) > 0 );
+//            if ( Abc_ObjFanoutNum(pObj) == 0 )
+//                Abc_NtkDeleteObj_rec( pObj, 0 );
+        }
+        else if ( Abc_ObjIsCo(pObj) && !fForward )
+        {
+            pLatchIn  = pObj;
+            pLatch    = Abc_ObjFanout0(pLatchIn);
+            pLatchOut = Abc_ObjFanout0(pLatch);
+            assert( Abc_ObjIsBo(pLatchOut) && Abc_ObjIsLatch(pLatch) && Abc_ObjIsBi(pLatchIn) );
+            // mark the latch as reused
+            Abc_NodeSetTravIdCurrent( pLatch );
+            assert( !Abc_ObjFanin0(pLatchIn)->fMarkA );
+        }
+        else
+        {
+            pLatchOut = Abc_NtkCreateBo(pNtk);
+            pLatch    = Abc_NtkCreateLatch(pNtk);
+            pLatchIn  = Abc_NtkCreateBi(pNtk);
+            Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_out" );
+            Abc_ObjAssignName( pLatchIn,  Abc_ObjName(pLatch), "_in" );
+            // connect
+            Abc_ObjAddFanin( pLatchOut, pLatch );
+            Abc_ObjAddFanin( pLatch, pLatchIn );
+            if ( fForward )
+            {
+                pLatch->pData = (void *)(ABC_PTRUINT_T)(pObj->pCopy? ABC_INIT_ONE : ABC_INIT_ZERO);
+                // redirect edges to the unvisited fanouts of the node
+                Abc_NodeCollectFanouts( pObj, vNodes );
+                Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNext, k )
+                    if ( !pNext->fMarkA )
+                        Abc_ObjPatchFanin( pNext, pObj, pLatchOut );
+            }
+            else
+            {
+                // redirect edges to the visited fanouts of the node
+                Abc_NodeCollectFanouts( pObj, vNodes );
+                Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNext, k )
+                    if ( pNext->fMarkA )
+                        Abc_ObjPatchFanin( pNext, pObj, pLatchOut );
+            }
+            // connect latch to the node
+            Abc_ObjAddFanin( pLatchIn, pObj );
+        }
+        Vec_PtrPush( vCis, pLatchOut );
+        Vec_PtrPush( vBoxesNew, pLatch );
+        Vec_PtrPush( vCos, pLatchIn );
+    }
+    Vec_PtrFree( vNodes );
+    // remove buffers
+    Vec_PtrForEachEntry( Abc_Obj_t *, vBuffers, pObj, i )
+    {
+        Abc_ObjTransferFanout( pObj, Abc_ObjFanin0(pObj) );
+        Abc_NtkDeleteObj( pObj );
+    }
+    Vec_PtrFree( vBuffers );
+    // remove useless latches
+    Vec_PtrForEachEntry( Abc_Obj_t *, vBoxes, pObj, i )
+    {
+        if ( !Abc_ObjIsLatch(pObj) )
+            continue;
+        if ( Abc_NodeIsTravIdCurrent(pObj) )
+            continue;
+        pLatchOut = Abc_ObjFanout0(pObj);
+        pLatch    = pObj;
+        pLatchIn  = Abc_ObjFanin0(pObj);
+        if ( Abc_ObjFanoutNum(pLatchOut) > 0 )
+            Abc_ObjTransferFanout( pLatchOut, Abc_ObjFanin0(pLatchIn) );
+        Abc_NtkDeleteObj( pLatchOut );
+        Abc_NtkDeleteObj( pObj );
+        Abc_NtkDeleteObj( pLatchIn );
+    }
+    // set the arrays
+    pNtk->vCis = vCis;
+    pNtk->vCos = vCos;
+    pNtk->vBoxes = vBoxesNew;
+    Vec_PtrFree( vBoxes );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/ret/retCore.c b/abc-build/src/opt/ret/retCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/ret/retCore.c
@@ -0,0 +1,138 @@
+/**CFile****************************************************************
+
+  FileName    [retCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Retiming package.]
+
+  Synopsis    [The core retiming procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Oct 31, 2006.]
+
+  Revision    [$Id: retCore.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+abctime timeRetime = 0;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Implementation of retiming.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int nDelayLim, int fForwardOnly, int fBackwardOnly, int fOneStep, int fVerbose )
+{
+    int nLatches = Abc_NtkLatchNum(pNtk);
+    int nLevels  = Abc_NtkLevel(pNtk);
+    int RetValue = 0;
+    abctime clkTotal = Abc_Clock();
+    int nNodesOld, nLatchesOld;
+    assert( Mode > 0 && Mode < 7 );
+    assert( !fForwardOnly || !fBackwardOnly );
+
+    // cleanup the network
+    nNodesOld   = Abc_NtkNodeNum(pNtk);
+    nLatchesOld = Abc_NtkLatchNum(pNtk);
+    Abc_NtkCleanupSeq(pNtk, 0, 0, 0);
+    if ( nNodesOld > Abc_NtkNodeNum(pNtk) || nLatchesOld > Abc_NtkLatchNum(pNtk) )
+        printf( "Cleanup before retiming removed %d dangling nodes and %d dangling latches.\n",
+            nNodesOld - Abc_NtkNodeNum(pNtk), nLatchesOld - Abc_NtkLatchNum(pNtk) );
+
+    // perform retiming
+    switch ( Mode )
+    {
+    case 1: // forward 
+        RetValue = Abc_NtkRetimeIncremental( pNtk, nDelayLim, 1, 0, 0, fVerbose );
+        break;
+    case 2: // backward 
+        RetValue = Abc_NtkRetimeIncremental( pNtk, nDelayLim, 0, 0, 0, fVerbose );
+        break;
+    case 3: // min-area 
+        RetValue = Abc_NtkRetimeMinArea( pNtk, fForwardOnly, fBackwardOnly, fVerbose );
+        break;
+    case 4: // min-delay
+        if ( !fBackwardOnly )
+            RetValue += Abc_NtkRetimeIncremental( pNtk, nDelayLim, 1, 1, fOneStep, fVerbose );
+        if ( !fForwardOnly )
+            RetValue += Abc_NtkRetimeIncremental( pNtk, nDelayLim, 0, 1, fOneStep, fVerbose );
+        break;
+    case 5: // min-area + min-delay
+        RetValue  = Abc_NtkRetimeMinArea( pNtk, fForwardOnly, fBackwardOnly, fVerbose );
+        if ( !fBackwardOnly )
+            RetValue += Abc_NtkRetimeIncremental( pNtk, nDelayLim, 1, 1, 0, fVerbose );
+        if ( !fForwardOnly )
+            RetValue += Abc_NtkRetimeIncremental( pNtk, nDelayLim, 0, 1, 0, fVerbose );
+        break;
+    case 6: // Pan's algorithm
+        RetValue = Abc_NtkRetimeLValue( pNtk, 500, fVerbose );
+        break;
+    default:
+        printf( "Unknown retiming option.\n" );
+        break;
+    }
+    if ( fVerbose )
+    {
+        printf( "Reduction in area = %3d. Reduction in delay = %3d. ", 
+            nLatches - Abc_NtkLatchNum(pNtk), nLevels - Abc_NtkLevel(pNtk) );
+        ABC_PRT( "Total runtime", Abc_Clock() - clkTotal );
+    }
+    timeRetime = Abc_Clock() - clkTotal;
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Used for automated debugging.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeDebug( Abc_Ntk_t * pNtk )
+{
+    extern int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose );
+    Abc_Ntk_t * pNtkRet;
+    assert( Abc_NtkIsLogic(pNtk) );
+    Abc_NtkToSop( pNtk, 0 );
+//    if ( !Abc_NtkCheck( pNtk ) )
+//        fprintf( stdout, "Abc_NtkRetimeDebug(): Network check has failed.\n" );
+//    Io_WriteBlifLogic( pNtk, "debug_temp.blif", 1 );
+    pNtkRet = Abc_NtkDup( pNtk );
+    Abc_NtkRetime( pNtkRet, 3, 0, 0, 1, 0, 0 ); // debugging backward flow
+    return !Abc_NtkSecFraig( pNtk, pNtkRet, 10000, 3, 0 );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/ret/retDelay.c b/abc-build/src/opt/ret/retDelay.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/ret/retDelay.c
@@ -0,0 +1,315 @@
+/**CFile****************************************************************
+
+  FileName    [retDelay.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Retiming package.]
+
+  Synopsis    [Incremental retiming for optimum delay.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Oct 31, 2006.]
+
+  Revision    [$Id: retDelay.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_NtkRetimeMinDelayTry( Abc_Ntk_t * pNtk, int nDelayLim, int fForward, int fInitial, int nIterLimit, int * pIterBest, int fVerbose );
+static int Abc_NtkRetimeTiming( Abc_Ntk_t * pNtk, int fForward, Vec_Ptr_t * vCritical );
+static int Abc_NtkRetimeTiming_rec( Abc_Obj_t * pObj, int fForward );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Retimes incrementally for minimum delay.]
+
+  Description [This procedure cannot be called in the application code
+  because it assumes that the network is preprocessed by removing LIs/LOs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeMinDelay( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkCopy, int nDelayLim, int nIterLimit, int fForward, int fVerbose )
+{
+    int IterBest, DelayBest;
+    int IterBest2, DelayBest2;
+    // try to find the best delay iteration on a copy
+    DelayBest = Abc_NtkRetimeMinDelayTry( pNtkCopy, nDelayLim, fForward, 0, nIterLimit, &IterBest, fVerbose );
+    if ( IterBest == 0 )
+        return 1;
+    // perform the given number of iterations on the original network
+    DelayBest2 = Abc_NtkRetimeMinDelayTry( pNtk, nDelayLim, fForward, 1, IterBest, &IterBest2, fVerbose );
+    assert( DelayBest == DelayBest2 );
+    assert( IterBest == IterBest2 );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the best delay and the number of best iteration.]
+
+  Description [] 
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeMinDelayTry( Abc_Ntk_t * pNtk, int nDelayLim, int fForward, int fInitial, int nIterLimit, int * pIterBest, int fVerbose )
+{
+    Abc_Ntk_t * pNtkNew = NULL;
+    Vec_Ptr_t * vCritical;
+    Vec_Int_t * vValues = NULL; // Suppress "might be used uninitialized"
+    Abc_Obj_t * pObj;
+    int i, k, IterBest, DelayCur, DelayBest;
+    int DelayStart = -1; // Suppress "might be used uninitialized"
+    int LatchesBest;
+    // transfer intitial values
+    if ( fInitial )
+    {
+        if ( fForward )
+            Abc_NtkRetimeTranferToCopy( pNtk );
+        else
+        {
+            // save initial value of the latches
+            vValues = Abc_NtkRetimeCollectLatchValues( pNtk );
+            // start the network for initial value computation
+            pNtkNew = Abc_NtkRetimeBackwardInitialStart( pNtk );
+        }
+    }
+
+if ( fVerbose && !fInitial )
+    printf( "Performing analysis:\n" );
+    // find the best iteration
+    DelayBest = ABC_INFINITY; IterBest = 0; LatchesBest = Abc_NtkLatchNum(pNtk);
+    vCritical = Vec_PtrAlloc( 100 );
+    for ( i = 0; ; i++ )
+    {
+        // perform moves for the timing-critical nodes
+        DelayCur = Abc_NtkRetimeTiming( pNtk, fForward, vCritical );
+        if ( i == 0 )
+            DelayStart = DelayCur;
+        // record this position if it has the best delay
+        if ( DelayBest > DelayCur )
+        {
+if ( fVerbose && !fInitial )
+    printf( "%s Iter = %3d. Delay = %3d. Latches = %5d. Delta = %6.2f. Ratio = %4.2f %%\n", 
+        fForward ? "Fwd": "Bwd", i, DelayCur, Abc_NtkLatchNum(pNtk), 
+        1.0*(Abc_NtkLatchNum(pNtk)-LatchesBest)/(DelayBest-DelayCur), 
+        100.0*(Abc_NtkLatchNum(pNtk)-LatchesBest)/Abc_NtkLatchNum(pNtk)/(DelayBest-DelayCur) );
+
+            DelayBest = DelayCur;
+            IterBest = i;
+            LatchesBest = Abc_NtkLatchNum(pNtk);
+        }
+        // quit after timing analysis
+        if ( i == nIterLimit )
+            break;
+        // skip if 10 interations did not give improvement
+        if ( i - IterBest > 20 )
+            break;
+        // skip if delay limit is reached
+        if ( nDelayLim > 0 && DelayCur <= nDelayLim )
+            break;
+        // try retiming to improve the delay
+        Vec_PtrForEachEntry( Abc_Obj_t *, vCritical, pObj, k )
+            if ( Abc_NtkRetimeNodeIsEnabled(pObj, fForward) )
+                Abc_NtkRetimeNode( pObj, fForward, fInitial );
+        // share latches
+        if ( !fForward )
+            Abc_NtkRetimeShareLatches( pNtk, fInitial );    
+    }
+    Vec_PtrFree( vCritical );
+    // transfer the initial state back to the latches
+    if ( fInitial )
+    {
+        if ( fForward )
+            Abc_NtkRetimeTranferFromCopy( pNtk );
+        else
+        {
+            Abc_NtkRetimeBackwardInitialFinish( pNtk, pNtkNew, vValues, fVerbose );
+            Abc_NtkDelete( pNtkNew );
+            Vec_IntFree( vValues );
+        }
+    }
+if ( fVerbose && !fInitial )
+    printf( "%s : Starting delay = %3d.  Final delay = %3d.  IterBest = %2d (out of %2d).\n", 
+        fForward? "Forward " : "Backward", DelayStart, DelayBest, IterBest, nIterLimit );
+    *pIterBest = (nIterLimit == 1) ? 1 : IterBest;
+    return DelayBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the set of timing-critical nodes.]
+
+  Description [Performs static timing analysis on the network. Uses 
+  unit-delay model.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeTiming( Abc_Ntk_t * pNtk, int fForward, Vec_Ptr_t * vCritical )
+{
+    Vec_Ptr_t * vLatches;
+    Abc_Obj_t * pObj, * pNext;
+    int i, k, LevelCur, LevelMax = 0;
+    // mark all objects except nodes
+    Abc_NtkIncrementTravId(pNtk);
+    vLatches = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        if ( Abc_ObjIsLatch(pObj) )
+            Vec_PtrPush( vLatches, pObj );
+        if ( Abc_ObjIsNode(pObj) )
+            continue;
+        pObj->Level = 0;
+        Abc_NodeSetTravIdCurrent( pObj );
+    }
+    // perform analysis from CIs/COs
+    if ( fForward )
+    {
+        Vec_PtrForEachEntry( Abc_Obj_t *, vLatches, pObj, i )
+        {
+            Abc_ObjForEachFanout( pObj, pNext, k )
+            {
+                LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward );
+                if ( LevelMax < LevelCur )
+                    LevelMax = LevelCur;
+            }
+        }
+        Abc_NtkForEachPi( pNtk, pObj, i )
+        {
+            Abc_ObjForEachFanout( pObj, pNext, k )
+            {
+                LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward );
+                if ( LevelMax < LevelCur )
+                    LevelMax = LevelCur;
+            }
+        }
+    }
+    else
+    {
+        Vec_PtrForEachEntry( Abc_Obj_t *, vLatches, pObj, i )
+        {
+            LevelCur = Abc_NtkRetimeTiming_rec( Abc_ObjFanin0(pObj), fForward );
+            if ( LevelMax < LevelCur )
+                LevelMax = LevelCur;
+        }
+        Abc_NtkForEachPo( pNtk, pObj, i )
+        {
+            LevelCur = Abc_NtkRetimeTiming_rec( Abc_ObjFanin0(pObj), fForward );
+            if ( LevelMax < LevelCur )
+                LevelMax = LevelCur;
+        }
+    }
+    // collect timing critical nodes, which should be retimed forward/backward
+    Vec_PtrClear( vCritical );
+    Abc_NtkIncrementTravId(pNtk);
+    if ( fForward )
+    {
+        Vec_PtrForEachEntry( Abc_Obj_t *, vLatches, pObj, i )
+        {
+            Abc_ObjForEachFanout( pObj, pNext, k )
+            {
+                if ( Abc_NodeIsTravIdCurrent(pNext) )
+                    continue;
+                if ( LevelMax != (int)pNext->Level )
+                    continue;
+                // new critical node
+                Vec_PtrPush( vCritical, pNext );
+                Abc_NodeSetTravIdCurrent( pNext );
+            }
+        }
+    }
+    else
+    {
+        Vec_PtrForEachEntry( Abc_Obj_t *, vLatches, pObj, i )
+        {
+            Abc_ObjForEachFanin( pObj, pNext, k )
+            {
+                if ( Abc_NodeIsTravIdCurrent(pNext) )
+                    continue;
+                if ( LevelMax != (int)pNext->Level )
+                    continue;
+                // new critical node
+                Vec_PtrPush( vCritical, pNext );
+                Abc_NodeSetTravIdCurrent( pNext );
+            }
+        }
+    }
+    Vec_PtrFree( vLatches );
+    return LevelMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively performs timing analysis.]
+
+  Description [Performs static timing analysis on the network. Uses 
+  unit-delay model.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeTiming_rec( Abc_Obj_t * pObj, int fForward )
+{
+    Abc_Obj_t * pNext;
+    int i, LevelCur, LevelMax = 0;
+    // skip visited nodes
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return pObj->Level;
+    Abc_NodeSetTravIdCurrent(pObj);
+    // visit the next nodes
+    if ( fForward )
+    {
+        Abc_ObjForEachFanout( pObj, pNext, i )
+        {
+            LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward );
+            if ( LevelMax < LevelCur )
+                LevelMax = LevelCur;
+        }
+    }
+    else
+    {
+        Abc_ObjForEachFanin( pObj, pNext, i )
+        {
+            LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward );
+            if ( LevelMax < LevelCur )
+                LevelMax = LevelCur;
+        }
+    }
+//    printf( "Node %3d -> Level %3d.\n", pObj->Id, LevelMax + 1 );
+    pObj->Level = LevelMax + 1;
+    return pObj->Level;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/ret/retFlow.c b/abc-build/src/opt/ret/retFlow.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/ret/retFlow.c
@@ -0,0 +1,789 @@
+/**CFile****************************************************************
+
+  FileName    [retFlow.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Implementation of maximum flow (min-area retiming).]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Oct 31, 2006.]
+
+  Revision    [$Id: retFlow.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int         Abc_ObjSetPath( Abc_Obj_t * pObj, Abc_Obj_t * pNext ) { pObj->pCopy = pNext; return 1;   }
+static inline Abc_Obj_t * Abc_ObjGetPath( Abc_Obj_t * pObj )                    { return pObj->pCopy;              }
+static inline Abc_Obj_t * Abc_ObjGetFanoutPath( Abc_Obj_t * pObj ) 
+{ 
+    Abc_Obj_t * pFanout;
+    int i;
+    assert( Abc_ObjGetPath(pObj) ); 
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+        if ( Abc_ObjGetPath(pFanout) == pObj )
+            return pFanout;
+    return NULL;
+}
+static inline Abc_Obj_t * Abc_ObjGetFaninPath( Abc_Obj_t * pObj ) 
+{ 
+    Abc_Obj_t * pFanin;
+    int i;
+    assert( Abc_ObjGetPath(pObj) ); 
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        if ( Abc_ObjGetPath(pFanin) == pObj )
+            return pFanin;
+    return NULL;
+}
+static inline Abc_Obj_t * Abc_ObjGetPredecessorBwd( Abc_Obj_t * pObj ) 
+{ 
+    Abc_Obj_t * pNext;
+    int i;
+    Abc_ObjForEachFanout( pObj, pNext, i )
+        if ( Abc_ObjGetPath(pNext) == pObj )
+            return pNext;
+    Abc_ObjForEachFanin( pObj, pNext, i )
+        if ( Abc_ObjGetPath(pNext) == pObj )
+            return pNext;
+    return NULL;
+}
+static inline Abc_Obj_t * Abc_ObjGetPredecessorFwd( Abc_Obj_t * pObj ) 
+{ 
+    Abc_Obj_t * pNext;
+    int i;
+    Abc_ObjForEachFanin( pObj, pNext, i )
+        if ( Abc_ObjGetPath(pNext) == pObj )
+            return pNext;
+    Abc_ObjForEachFanout( pObj, pNext, i )
+        if ( Abc_ObjGetPath(pNext) == pObj )
+            return pNext;
+    return NULL;
+}
+
+static int         Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj );
+static int         Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj );
+static int         Abc_NtkMaxFlowBwdPath2_rec( Abc_Obj_t * pObj );
+static int         Abc_NtkMaxFlowFwdPath2_rec( Abc_Obj_t * pObj );
+//static int         Abc_NtkMaxFlowBwdPath3_rec( Abc_Obj_t * pObj );
+static int         Abc_NtkMaxFlowFwdPath3_rec( Abc_Obj_t * pObj, Abc_Obj_t * pPrev, int fFanin );
+static Vec_Ptr_t * Abc_NtkMaxFlowMinCut( Abc_Ntk_t * pNtk, int fForward );
+static void        Abc_NtkMaxFlowMinCutUpdate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward );
+static int         Abc_NtkMaxFlowVerifyCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward );
+static void        Abc_NtkMaxFlowPrintCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut );
+static void        Abc_NtkMaxFlowPrintFlow( Abc_Ntk_t * pNtk, int fForward );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Test-bench for the max-flow computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vMinCut;
+    Abc_Obj_t * pObj;
+    int i;
+
+    // forward flow
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        pObj->fMarkA = 1;
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        pObj->fMarkA = Abc_ObjFanin0(pObj)->fMarkA = 1;
+//        Abc_ObjFanin0(pObj)->fMarkA = 1;
+    vMinCut = Abc_NtkMaxFlow( pNtk, 1, 1 );
+    Vec_PtrFree( vMinCut );
+    Abc_NtkCleanMarkA( pNtk );
+
+    // backward flow
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        pObj->fMarkA = 1;
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        pObj->fMarkA = Abc_ObjFanout0(pObj)->fMarkA = 1;
+//        Abc_ObjFanout0(pObj)->fMarkA = 1;
+    vMinCut = Abc_NtkMaxFlow( pNtk, 0, 1 );
+    Vec_PtrFree( vMinCut );
+    Abc_NtkCleanMarkA( pNtk );
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implementation of max-flow/min-cut computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkMaxFlow( Abc_Ntk_t * pNtk, int fForward, int fVerbose )
+{
+    Vec_Ptr_t * vMinCut;
+    Abc_Obj_t * pLatch;
+    int Flow, FlowCur, RetValue, i;
+    abctime clk = Abc_Clock();
+    int fUseDirectedFlow = 1;
+
+    // find the max-flow
+    Abc_NtkCleanCopy( pNtk );
+    Flow = 0;
+    Abc_NtkIncrementTravId(pNtk);
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+        if ( fForward )
+        {
+//            assert( !Abc_ObjFanout0(pLatch)->fMarkA );
+            FlowCur  = Abc_NtkMaxFlowFwdPath2_rec( Abc_ObjFanout0(pLatch) );
+//            FlowCur  = Abc_NtkMaxFlowFwdPath3_rec( Abc_ObjFanout0(pLatch), pLatch, 1 );
+            Flow    += FlowCur;
+        }
+        else
+        {
+            assert( !Abc_ObjFanin0(pLatch)->fMarkA );
+            FlowCur  = Abc_NtkMaxFlowBwdPath2_rec( Abc_ObjFanin0(pLatch) );
+            Flow    += FlowCur;
+        }
+        if ( FlowCur )
+            Abc_NtkIncrementTravId(pNtk);
+    }
+
+    if ( !fUseDirectedFlow )
+    {
+        Abc_NtkIncrementTravId(pNtk);
+        Abc_NtkForEachLatch( pNtk, pLatch, i )
+        {
+            if ( fForward )
+            {
+    //            assert( !Abc_ObjFanout0(pLatch)->fMarkA );
+                FlowCur  = Abc_NtkMaxFlowFwdPath_rec( Abc_ObjFanout0(pLatch) );
+                Flow    += FlowCur;
+            }
+            else
+            {
+                assert( !Abc_ObjFanin0(pLatch)->fMarkA );
+                FlowCur  = Abc_NtkMaxFlowBwdPath_rec( Abc_ObjFanin0(pLatch) );
+                Flow    += FlowCur;
+            }
+            if ( FlowCur )
+                Abc_NtkIncrementTravId(pNtk);
+        }
+    }
+//    Abc_NtkMaxFlowPrintFlow( pNtk, fForward );
+
+    // mark the nodes reachable from the latches
+    Abc_NtkIncrementTravId(pNtk);
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+        if ( fForward )
+        {
+//            assert( !Abc_ObjFanout0(pLatch)->fMarkA );
+            if ( fUseDirectedFlow )
+                RetValue = Abc_NtkMaxFlowFwdPath2_rec( Abc_ObjFanout0(pLatch) );
+//                RetValue = Abc_NtkMaxFlowFwdPath3_rec( Abc_ObjFanout0(pLatch), pLatch, 1 );
+            else
+                RetValue = Abc_NtkMaxFlowFwdPath_rec( Abc_ObjFanout0(pLatch) );
+        }
+        else
+        {
+            assert( !Abc_ObjFanin0(pLatch)->fMarkA );
+            if ( fUseDirectedFlow )
+                RetValue = Abc_NtkMaxFlowBwdPath2_rec( Abc_ObjFanin0(pLatch) );
+            else
+                RetValue = Abc_NtkMaxFlowBwdPath_rec( Abc_ObjFanin0(pLatch) );
+        }
+        assert( RetValue == 0 );
+    }
+
+    // find the min-cut with the smallest volume
+    vMinCut = Abc_NtkMaxFlowMinCut( pNtk, fForward );
+    // verify the cut
+    if ( !Abc_NtkMaxFlowVerifyCut(pNtk, vMinCut, fForward) )
+        printf( "Abc_NtkMaxFlow() error! The computed min-cut is not a cut!\n" );
+    // make the cut retimable
+    Abc_NtkMaxFlowMinCutUpdate( pNtk, vMinCut, fForward );
+
+    // report the results
+    if ( fVerbose )
+    {
+    printf( "L = %6d. %s max-flow = %6d.  Min-cut = %6d.  ", 
+        Abc_NtkLatchNum(pNtk), fForward? "Forward " : "Backward", Flow, Vec_PtrSize(vMinCut) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+
+//    Abc_NtkMaxFlowPrintCut( pNtk, vMinCut );
+    return vMinCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tries to find an augmenting path originating in this node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pNext, * pPred;
+    int i;
+    // skip visited nodes
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return 0;
+    Abc_NodeSetTravIdCurrent(pObj);
+    // get the predecessor
+    pPred = Abc_ObjGetPredecessorBwd( pObj );
+    // process node without flow
+    if ( !Abc_ObjGetPath(pObj) )
+    {
+        // start the path if we reached a terminal node
+        if ( pObj->fMarkA )
+            return Abc_ObjSetPath( pObj, (Abc_Obj_t *)1 );
+        // explore the fanins
+        Abc_ObjForEachFanin( pObj, pNext, i )
+            if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec(pNext) )
+                return Abc_ObjSetPath( pObj, pNext );
+        Abc_ObjForEachFanout( pObj, pNext, i )
+            if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec(pNext) )
+                return Abc_ObjSetPath( pObj, pNext );
+        return 0;
+    }
+    // pObj has flow - find the fanout with flow
+    if ( pPred == NULL )
+        return 0;
+    // go through the successors of the predecessor
+    Abc_ObjForEachFanin( pPred, pNext, i )
+        if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec( pNext ) )
+            return Abc_ObjSetPath( pPred, pNext );
+    Abc_ObjForEachFanout( pPred, pNext, i )
+        if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec( pNext ) )
+            return Abc_ObjSetPath( pPred, pNext );
+    // try the fanout
+    if ( Abc_NtkMaxFlowBwdPath_rec( pPred ) )
+        return Abc_ObjSetPath( pPred, NULL );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tries to find an augmenting path originating in this node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pNext, * pPred;
+    int i;
+    // skip visited nodes
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return 0;
+    Abc_NodeSetTravIdCurrent(pObj);
+    // get the predecessor
+    pPred = Abc_ObjGetPredecessorFwd( pObj );
+    // process node without flow
+    if ( !Abc_ObjGetPath(pObj) )
+    {
+        // start the path if we reached a terminal node
+        if ( pObj->fMarkA )
+            return Abc_ObjSetPath( pObj, (Abc_Obj_t *)1 );
+        // explore the fanins
+        Abc_ObjForEachFanout( pObj, pNext, i )
+            if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec(pNext) )
+                return Abc_ObjSetPath( pObj, pNext );
+        Abc_ObjForEachFanin( pObj, pNext, i )
+            if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec(pNext) )
+                return Abc_ObjSetPath( pObj, pNext );
+        return 0;
+    }
+    // pObj has flow - find the fanout with flow
+    if ( pPred == NULL )
+        return 0;
+    // go through the successors of the predecessor
+    Abc_ObjForEachFanout( pPred, pNext, i )
+        if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec( pNext ) )
+            return Abc_ObjSetPath( pPred, pNext );
+    Abc_ObjForEachFanin( pPred, pNext, i )
+        if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec( pNext ) )
+            return Abc_ObjSetPath( pPred, pNext );
+    // try the fanout
+    if ( Abc_NtkMaxFlowFwdPath_rec( pPred ) )
+        return Abc_ObjSetPath( pPred, NULL );
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Tries to find an augmenting path originating in this edge.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMaxFlowFwdPath3_rec( Abc_Obj_t * pObj, Abc_Obj_t * pPrev, int fFanin )
+{
+    Abc_Obj_t * pFanin, * pFanout;
+    int i;
+    // skip visited nodes
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return 0;
+    Abc_NodeSetTravIdCurrent(pObj);
+    // skip the fanin which already has flow
+    if ( fFanin && Abc_ObjGetPath(pPrev) )
+        return 0;
+    // if the node has no flow, try to push through the fanouts
+    if ( !Abc_ObjGetPath(pObj) )
+    {
+        // start the path if we reached a terminal node
+        if ( pObj->fMarkA )
+            return Abc_ObjSetPath( pObj, (Abc_Obj_t *)1 );
+        // try to push flow through the fanouts
+        Abc_ObjForEachFanout( pObj, pFanout, i )
+            if ( Abc_NtkMaxFlowFwdPath3_rec(pFanout, pObj, 1) )
+                return fFanin? Abc_ObjSetPath(pPrev, pObj) : 1;
+    }
+    // try to push through the fanins
+    Abc_ObjForEachFanin( pObj, pFanin, i )
+        if ( !Abc_ObjIsLatch(pFanin) && Abc_NtkMaxFlowFwdPath3_rec(pFanin, pObj, 0) )
+            return Abc_ObjSetPath( pFanin, NULL );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tries to find an augmenting path originating in this node.]
+
+  Description [This procedure works for directed graphs only!]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMaxFlowBwdPath2_rec( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout, * pFanin;
+    int i;
+    // skip visited nodes
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return 0;
+    Abc_NodeSetTravIdCurrent(pObj);
+    // process node without flow
+    if ( !Abc_ObjGetPath(pObj) )
+    {
+        // start the path if we reached a terminal node
+        if ( pObj->fMarkA )
+            return Abc_ObjSetPath( pObj, (Abc_Obj_t *)1 );
+        // explore the fanins
+        Abc_ObjForEachFanin( pObj, pFanin, i )
+            if ( Abc_NtkMaxFlowBwdPath2_rec(pFanin) )
+                return Abc_ObjSetPath( pObj, pFanin );
+        return 0;
+    }
+    // pObj has flow - find the fanout with flow
+    pFanout = Abc_ObjGetFanoutPath( pObj );
+    if ( pFanout == NULL )
+        return 0;
+    // go through the fanins of the fanout with flow
+    Abc_ObjForEachFanin( pFanout, pFanin, i )
+        if ( Abc_NtkMaxFlowBwdPath2_rec( pFanin ) )
+            return Abc_ObjSetPath( pFanout, pFanin );
+    // try the fanout
+    if ( Abc_NtkMaxFlowBwdPath2_rec( pFanout ) )
+        return Abc_ObjSetPath( pFanout, NULL );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tries to find an augmenting path originating in this node.]
+
+  Description [This procedure works for directed graphs only!]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMaxFlowFwdPath2_rec( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout, * pFanin;
+    int i;
+    // skip visited nodes
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return 0;
+    Abc_NodeSetTravIdCurrent(pObj);
+    // process node without flow
+    if ( !Abc_ObjGetPath(pObj) )
+    { 
+        // start the path if we reached a terminal node
+        if ( pObj->fMarkA )
+            return Abc_ObjSetPath( pObj, (Abc_Obj_t *)1 );
+        // explore the fanins
+        Abc_ObjForEachFanout( pObj, pFanout, i )
+            if ( Abc_NtkMaxFlowFwdPath2_rec(pFanout) )
+                return Abc_ObjSetPath( pObj, pFanout );
+        return 0;
+    }
+    // pObj has flow - find the fanout with flow
+    pFanin = Abc_ObjGetFaninPath( pObj );
+    if ( pFanin == NULL )
+        return 0;
+    // go through the fanins of the fanout with flow
+    Abc_ObjForEachFanout( pFanin, pFanout, i )
+        if ( Abc_NtkMaxFlowFwdPath2_rec( pFanout ) )
+            return Abc_ObjSetPath( pFanin, pFanout );
+    // try the fanout
+    if ( Abc_NtkMaxFlowFwdPath2_rec( pFanin ) )
+        return Abc_ObjSetPath( pFanin, NULL );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find minimum-volume minumum cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkMaxFlowMinCut( Abc_Ntk_t * pNtk, int fForward )
+{
+    Vec_Ptr_t * vMinCut;
+    Abc_Obj_t * pObj;
+    int i;
+    // collect the cut nodes
+    vMinCut = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+    {
+        // node without flow is not a cut node
+        if ( !Abc_ObjGetPath(pObj) )
+            continue;
+        // unvisited node is below the cut
+        if ( !Abc_NodeIsTravIdCurrent(pObj) )
+            continue;
+        // add terminal with flow or node whose path is not visited
+        if ( pObj->fMarkA || !Abc_NodeIsTravIdCurrent( Abc_ObjGetPath(pObj) ) )
+            Vec_PtrPush( vMinCut, pObj );
+    }
+    return vMinCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the TFI cone with MarkA.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMaxFlowMarkCut_rec( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pNext;
+    int i;
+    if ( pObj->fMarkA )
+        return;
+    pObj->fMarkA = 1;
+    Abc_ObjForEachFanin( pObj, pNext, i )
+        Abc_NtkMaxFlowMarkCut_rec( pNext );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Visits the TFI up to marked nodes and collects marked nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMaxFlowCollectCut_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    Abc_Obj_t * pNext;
+    int i;
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return;
+    Abc_NodeSetTravIdCurrent(pObj);
+    if ( pObj->fMarkA )
+    {
+        Vec_PtrPush( vNodes, pObj );
+        return;
+    }
+    Abc_ObjForEachFanin( pObj, pNext, i )
+        Abc_NtkMaxFlowCollectCut_rec( pNext, vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the minimum cut to be retimable.]
+
+  Description [This procedure also labels the nodes reachable from
+  the latches to the cut with fMarkA.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMaxFlowMinCutUpdate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward )
+{
+    Abc_Obj_t * pObj, * pNext;
+    int i, k;
+    // clean marks
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        pObj->fMarkA = 0;
+    // set latch outputs
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        Abc_ObjFanout0(pObj)->fMarkA = 1;
+    // traverse from cut nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vMinCut, pObj, i )
+        Abc_NtkMaxFlowMarkCut_rec( pObj );
+    if ( fForward )
+    {
+        // change mincut to be nodes with unmarked fanouts
+        Vec_PtrClear( vMinCut );
+        Abc_NtkForEachObj( pNtk, pObj, i )
+        {
+            if ( !pObj->fMarkA )
+                continue;
+            Abc_ObjForEachFanout( pObj, pNext, k )
+            {
+                if ( pNext->fMarkA )
+                    continue;
+                Vec_PtrPush( vMinCut, pObj );
+                break;
+            }
+        }
+    }
+    else
+    {
+        // change mincut to be marked fanins of the unmarked nodes
+        Vec_PtrClear( vMinCut );
+        Abc_NtkIncrementTravId(pNtk);
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+            Abc_NtkMaxFlowCollectCut_rec( Abc_ObjFanin0(pObj), vMinCut );
+        // transfer the attribute
+        Abc_NtkForEachObj( pNtk, pObj, i )
+            pObj->fMarkA = Abc_NodeIsTravIdCurrent(pObj);
+        // unmark the cut nodes
+        Vec_PtrForEachEntry( Abc_Obj_t *, vMinCut, pObj, i )
+            pObj->fMarkA = 0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the min-cut is indeed a cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMaxFlowVerifyCut_rec( Abc_Obj_t * pObj, int fForward )
+{
+    Abc_Obj_t * pNext;
+    int i;
+    // skip visited nodes
+    if ( Abc_NodeIsTravIdCurrent(pObj) )
+        return 1;
+    Abc_NodeSetTravIdCurrent(pObj);
+    // visit the node
+    if ( fForward )
+    {
+        if ( Abc_ObjIsCo(pObj) )
+            return 0;
+        // explore the fanouts
+        Abc_ObjForEachFanout( pObj, pNext, i )
+            if ( !Abc_NtkMaxFlowVerifyCut_rec(pNext, fForward) )
+                return 0;
+    }
+    else
+    {
+        if ( Abc_ObjIsCi(pObj) )
+            return 0;
+        // explore the fanins
+        Abc_ObjForEachFanin( pObj, pNext, i )
+            if ( !Abc_NtkMaxFlowVerifyCut_rec(pNext, fForward) )
+                return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the min-cut is indeed a cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkMaxFlowVerifyCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    // mark the cut with the current traversal ID
+    Abc_NtkIncrementTravId(pNtk);
+    Vec_PtrForEachEntry( Abc_Obj_t *, vMinCut, pObj, i )
+        Abc_NodeSetTravIdCurrent( pObj );
+    // search from the latches for a path to the COs/CIs
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+    {
+        if ( fForward )
+        {
+            if ( !Abc_NtkMaxFlowVerifyCut_rec( Abc_ObjFanout0(pObj), fForward ) )
+                return 0;
+        }
+        else
+        {
+            if ( !Abc_NtkMaxFlowVerifyCut_rec( Abc_ObjFanin0(pObj), fForward ) )
+                return 0;
+        }
+    }
+/*
+    {
+        // count the volume of the cut
+        int Counter = 0;
+        Abc_NtkForEachObj( pNtk, pObj, i )
+            Counter += Abc_NodeIsTravIdCurrent( pObj );
+        printf( "Volume = %d.\n", Counter );
+    }
+*/
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the flows.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMaxFlowPrintFlow( Abc_Ntk_t * pNtk, int fForward )
+{
+    Abc_Obj_t * pLatch, * pNext;
+    Abc_Obj_t * pPrev = NULL; // Suppress "might be used uninitialized"
+    int i;
+    if ( fForward )
+    {
+        Vec_PtrForEachEntry( Abc_Obj_t *, pNtk->vBoxes, pLatch, i )
+        {
+            assert( !Abc_ObjFanout0(pLatch)->fMarkA );
+            if ( Abc_ObjGetPath(Abc_ObjFanout0(pLatch)) == NULL ) // no flow through this latch
+                continue;
+            printf( "Path = " );
+            for ( pNext = Abc_ObjFanout0(pLatch); pNext != (void *)1; pNext = Abc_ObjGetPath(pNext) )
+            {
+                printf( "%s(%d) ", Abc_ObjName(pNext), pNext->Id );
+                pPrev = pNext;
+            }
+            if ( !Abc_ObjIsPo(pPrev) )
+            printf( "%s(%d) ", Abc_ObjName(Abc_ObjFanout0(pPrev)), Abc_ObjFanout0(pPrev)->Id );
+            printf( "\n" );
+        }
+    }
+    else
+    {
+        Vec_PtrForEachEntry( Abc_Obj_t *, pNtk->vBoxes, pLatch, i )
+        {
+            assert( !Abc_ObjFanin0(pLatch)->fMarkA );
+            if ( Abc_ObjGetPath(Abc_ObjFanin0(pLatch)) == NULL ) // no flow through this latch
+                continue;
+            printf( "Path = " );
+            for ( pNext = Abc_ObjFanin0(pLatch); pNext != (void *)1; pNext = Abc_ObjGetPath(pNext) )
+            {
+                printf( "%s(%d) ", Abc_ObjName(pNext), pNext->Id );
+                pPrev = pNext;
+            }
+            if ( !Abc_ObjIsPi(pPrev) )
+            printf( "%s(%d) ", Abc_ObjName(Abc_ObjFanin0(pPrev)), Abc_ObjFanin0(pPrev)->Id );
+            printf( "\n" );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the min-cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkMaxFlowPrintCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    printf( "Min-cut: " );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vMinCut, pObj, i )
+        printf( "%s(%d) ", Abc_ObjName(pObj), pObj->Id );
+    printf( "\n" );
+    printf( "Marked nodes: " );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( pObj->fMarkA )
+            printf( "%s(%d) ", Abc_ObjName(pObj), pObj->Id );
+    printf( "\n" );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/ret/retIncrem.c b/abc-build/src/opt/ret/retIncrem.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/ret/retIncrem.c
@@ -0,0 +1,470 @@
+/**CFile****************************************************************
+
+  FileName    [retIncrem.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Retiming package.]
+
+  Synopsis    [Incremental retiming in one direction.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Oct 31, 2006.]
+
+  Revision    [$Id: retIncrem.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_NtkRetimeOneWay( Abc_Ntk_t * pNtk, int fForward, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs retiming in one direction.]
+
+  Description [Currently does not retime over black boxes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeIncremental( Abc_Ntk_t * pNtk, int nDelayLim, int fForward, int fMinDelay, int fOneStep, int fVerbose )
+{
+    Abc_Ntk_t * pNtkCopy = NULL;
+    Vec_Ptr_t * vBoxes;
+    st__table * tLatches;
+    int nLatches = Abc_NtkLatchNum(pNtk);
+    int nIdMaxStart = Abc_NtkObjNumMax(pNtk);
+    int RetValue;
+    int nIterLimit = -1; // Suppress "might be used uninitialized"
+    if ( Abc_NtkNodeNum(pNtk) == 0 )
+        return 0;
+    // reorder CI/CO/latch inputs
+    Abc_NtkOrderCisCos( pNtk );
+    if ( fMinDelay ) 
+    {
+        nIterLimit = fOneStep? 1 : 2 * Abc_NtkLevel(pNtk);
+        pNtkCopy = Abc_NtkDup( pNtk );
+        tLatches = Abc_NtkRetimePrepareLatches( pNtkCopy );
+        st__free_table( tLatches );
+    }
+    // collect latches and remove CIs/COs
+    tLatches = Abc_NtkRetimePrepareLatches( pNtk );
+    // share the latches
+    Abc_NtkRetimeShareLatches( pNtk, 0 );    
+    // save boxes
+    vBoxes = pNtk->vBoxes;  pNtk->vBoxes = NULL;
+    // perform the retiming
+    if ( fMinDelay )
+        Abc_NtkRetimeMinDelay( pNtk, pNtkCopy, nDelayLim, nIterLimit, fForward, fVerbose );
+    else
+        Abc_NtkRetimeOneWay( pNtk, fForward, fVerbose );
+    if ( fMinDelay ) 
+        Abc_NtkDelete( pNtkCopy );
+    // share the latches
+    Abc_NtkRetimeShareLatches( pNtk, 0 );    
+    // restore boxes
+    pNtk->vBoxes = vBoxes;
+    // finalize the latches
+    RetValue = Abc_NtkRetimeFinalizeLatches( pNtk, tLatches, nIdMaxStart );
+    st__free_table( tLatches );
+    if ( RetValue == 0 )
+        return 0;
+    // fix the COs
+//    Abc_NtkLogicMakeSimpleCos( pNtk, 0 );
+    // check for correctness
+    if ( !Abc_NtkCheck( pNtk ) )
+        fprintf( stdout, "Abc_NtkRetimeForward(): Network check has failed.\n" );
+    // return the number of latches saved
+    return nLatches - Abc_NtkLatchNum(pNtk);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the network for retiming.]
+
+  Description [Hash latches into their number in the original network.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+ st__table * Abc_NtkRetimePrepareLatches( Abc_Ntk_t * pNtk )
+{
+    st__table * tLatches;
+    Abc_Obj_t * pLatch, * pLatchIn, * pLatchOut, * pFanin;
+    int i, nOffSet = Abc_NtkBoxNum(pNtk) - Abc_NtkLatchNum(pNtk);
+    // collect latches and remove CIs/COs
+    tLatches = st__init_table( st__ptrcmp, st__ptrhash );
+    Abc_NtkForEachLatch( pNtk, pLatch, i )
+    {
+        // map latch into its true number
+        st__insert( tLatches, (char *)(ABC_PTRUINT_T)pLatch, (char *)(ABC_PTRUINT_T)(i-nOffSet) );
+        // disconnect LI     
+        pLatchIn = Abc_ObjFanin0(pLatch);
+        pFanin = Abc_ObjFanin0(pLatchIn);
+        Abc_ObjTransferFanout( pLatchIn, pFanin );
+        Abc_ObjDeleteFanin( pLatchIn, pFanin );
+        // disconnect LO     
+        pLatchOut = Abc_ObjFanout0(pLatch);
+        pFanin = Abc_ObjFanin0(pLatchOut);
+        if ( Abc_ObjFanoutNum(pLatchOut) > 0 )
+            Abc_ObjTransferFanout( pLatchOut, pFanin );
+        Abc_ObjDeleteFanin( pLatchOut, pFanin );
+    }
+    return tLatches;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finalizes the latches after retiming.]
+
+  Description [Reuses the LIs/LOs for old latches.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeFinalizeLatches( Abc_Ntk_t * pNtk, st__table * tLatches, int nIdMaxStart )
+{
+    Vec_Ptr_t * vCisOld, * vCosOld, * vBoxesOld, * vCisNew, * vCosNew, * vBoxesNew;
+    Abc_Obj_t * pObj, * pLatch, * pLatchIn, * pLatchOut;
+    int i, Index;
+    // create new arrays
+    vCisOld   = pNtk->vCis;    pNtk->vCis   = NULL;  vCisNew   = Vec_PtrAlloc( 100 );
+    vCosOld   = pNtk->vCos;    pNtk->vCos   = NULL;  vCosNew   = Vec_PtrAlloc( 100 );  
+    vBoxesOld = pNtk->vBoxes;  pNtk->vBoxes = NULL;  vBoxesNew = Vec_PtrAlloc( 100 );
+    // copy boxes and their CIs/COs
+    Vec_PtrForEachEntryStop( Abc_Obj_t *, vCisOld, pObj, i, Vec_PtrSize(vCisOld) - st__count(tLatches) )
+        Vec_PtrPush( vCisNew, pObj );
+    Vec_PtrForEachEntryStop( Abc_Obj_t *, vCosOld, pObj, i, Vec_PtrSize(vCosOld) - st__count(tLatches) )
+        Vec_PtrPush( vCosNew, pObj );
+    Vec_PtrForEachEntryStop( Abc_Obj_t *, vBoxesOld, pObj, i, Vec_PtrSize(vBoxesOld) - st__count(tLatches) )
+        Vec_PtrPush( vBoxesNew, pObj );
+    // go through the latches
+    Abc_NtkForEachObj( pNtk, pLatch, i )
+    {
+        if ( !Abc_ObjIsLatch(pLatch) )
+            continue;
+        if ( Abc_ObjId(pLatch) >= (unsigned)nIdMaxStart )
+        {
+            // this is a new latch 
+            pLatchIn  = Abc_NtkCreateBi(pNtk);
+            pLatchOut = Abc_NtkCreateBo(pNtk);
+            Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_out" );
+            Abc_ObjAssignName( pLatchIn,  Abc_ObjName(pLatch), "_in" );
+        }
+        else
+        {
+            // this is an old latch 
+            // get its number in the original order
+            if ( ! st__lookup( tLatches, (char *)pLatch, (char **)&Index ) )
+            {
+                printf( "Abc_NtkRetimeFinalizeLatches(): Internal error.\n" );
+                return 0;
+            }
+            assert( pLatch == Vec_PtrEntry(vBoxesOld, Vec_PtrSize(vBoxesOld) - st__count(tLatches) + Index) );
+            // reconnect with the old LIs/LOs
+            pLatchIn  = (Abc_Obj_t *)Vec_PtrEntry( vCosOld, Vec_PtrSize(vCosOld) - st__count(tLatches) + Index );
+            pLatchOut = (Abc_Obj_t *)Vec_PtrEntry( vCisOld, Vec_PtrSize(vCisOld) - st__count(tLatches) + Index );
+        }
+        // connect
+        Abc_ObjAddFanin( pLatchIn, Abc_ObjFanin0(pLatch) );
+        Abc_ObjPatchFanin( pLatch, Abc_ObjFanin0(pLatch), pLatchIn );
+        if ( Abc_ObjFanoutNum(pLatch) > 0 )
+            Abc_ObjTransferFanout( pLatch, pLatchOut );
+        Abc_ObjAddFanin( pLatchOut, pLatch );
+        // add to the arrays
+        Vec_PtrPush( vCisNew, pLatchOut );
+        Vec_PtrPush( vCosNew, pLatchIn );
+        Vec_PtrPush( vBoxesNew, pLatch );
+    }
+    // free useless Cis/Cos
+    Vec_PtrForEachEntry( Abc_Obj_t *, vCisOld, pObj, i )
+        if ( !Abc_ObjIsPi(pObj) && Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 )
+            Abc_NtkDeleteObj(pObj);
+    Vec_PtrForEachEntry( Abc_Obj_t *, vCosOld, pObj, i )
+        if ( !Abc_ObjIsPo(pObj) && Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 )
+            Abc_NtkDeleteObj(pObj);
+    // set the new arrays
+    pNtk->vCis   = vCisNew;   Vec_PtrFree( vCisOld );
+    pNtk->vCos   = vCosNew;   Vec_PtrFree( vCosOld );
+    pNtk->vBoxes = vBoxesNew; Vec_PtrFree( vBoxesOld );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs retiming one way, forward or backward.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeOneWay( Abc_Ntk_t * pNtk, int fForward, int fVerbose )
+{
+    Abc_Ntk_t * pNtkNew = NULL; // Suppress "might be used uninitialized"
+    Vec_Int_t * vValues = NULL; // Suppress "might be used uninitialized"
+    Abc_Obj_t * pObj;
+    int i, fChanges, nTotalMoves = 0, nTotalMovesLimit = 10000;
+    if ( fForward )
+        Abc_NtkRetimeTranferToCopy( pNtk );
+    else
+    {
+        // save initial values of the latches
+        vValues = Abc_NtkRetimeCollectLatchValues( pNtk );
+        // start the network for initial value computation
+        pNtkNew = Abc_NtkRetimeBackwardInitialStart( pNtk );
+    }
+    // try to move latches forward whenever possible
+    do {
+        fChanges = 0;
+        Abc_NtkForEachObj( pNtk, pObj, i )
+        {
+            if ( !Abc_ObjIsNode(pObj) )
+                continue;
+            if ( Abc_NtkRetimeNodeIsEnabled( pObj, fForward ) )
+            {
+                Abc_NtkRetimeNode( pObj, fForward, 1 );
+                fChanges = 1;
+                nTotalMoves++;
+                if ( nTotalMoves >= nTotalMovesLimit )
+                {
+                    printf( "Stopped after %d latch moves.\n", nTotalMoves );
+                    break;
+                }
+            }
+        }
+    } while ( fChanges && nTotalMoves < nTotalMovesLimit );
+    // transfer the initial state back to the latches
+    if ( fForward )
+        Abc_NtkRetimeTranferFromCopy( pNtk );
+    else
+    {
+        Abc_NtkRetimeBackwardInitialFinish( pNtk, pNtkNew, vValues, fVerbose );
+        Abc_NtkDelete( pNtkNew );
+        Vec_IntFree( vValues );
+    }
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if retiming forward/backward is possible.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeNodeIsEnabled( Abc_Obj_t * pObj, int fForward )
+{
+    Abc_Obj_t * pNext;
+    int i;
+    assert( Abc_ObjIsNode(pObj) );
+    if ( fForward )
+    {
+        Abc_ObjForEachFanin( pObj, pNext, i )
+            if ( !Abc_ObjIsLatch(pNext) )
+                return 0;
+    }
+    else
+    {
+        Abc_ObjForEachFanout( pObj, pNext, i )
+            if ( !Abc_ObjIsLatch(pNext) )
+                return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Retimes the node backward or forward.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkRetimeNode( Abc_Obj_t * pObj, int fForward, int fInitial )
+{
+    Abc_Ntk_t * pNtkNew = NULL;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pNext, * pLatch;
+    int i;
+    vNodes = Vec_PtrAlloc( 10 );
+    if ( fForward ) 
+    {
+        // compute the initial value
+        if ( fInitial )
+            pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_ObjSopSimulate( pObj );
+        // collect fanins
+        Abc_NodeCollectFanins( pObj, vNodes );
+        // make the node point to the fanins fanins
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNext, i )
+        {
+            assert( Abc_ObjIsLatch(pNext) );
+            Abc_ObjPatchFanin( pObj, pNext, Abc_ObjFanin0(pNext) );
+            if ( Abc_ObjFanoutNum(pNext) == 0 )
+                Abc_NtkDeleteObj(pNext);            
+        }
+        // add a new latch on top
+        pNext = Abc_NtkCreateLatch(pObj->pNtk);
+        if ( Abc_ObjFanoutNum(pObj) > 0 )
+            Abc_ObjTransferFanout( pObj, pNext );
+        Abc_ObjAddFanin( pNext, pObj );
+        // set the initial value
+        if ( fInitial )
+            pNext->pCopy = pObj->pCopy;
+    }
+    else
+    {
+        // compute the initial value
+        if ( fInitial )
+        {
+            pNtkNew = Abc_ObjFanout0(pObj)->pCopy->pNtk;
+            Abc_NtkDupObj( pNtkNew, pObj, 0 );
+            Abc_ObjForEachFanout( pObj, pNext, i )
+            {
+                assert( Abc_ObjFaninNum(pNext->pCopy) == 0 );
+                Abc_ObjAddFanin( pNext->pCopy, pObj->pCopy );
+            }
+        }
+        // collect fanouts
+        Abc_NodeCollectFanouts( pObj, vNodes );
+        // make the fanouts fanouts point to the node
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNext, i )
+        {
+            assert( Abc_ObjIsLatch(pNext) );
+            Abc_ObjTransferFanout( pNext, pObj );
+            Abc_NtkDeleteObj( pNext );  
+        }
+        // add new latches to the fanins
+        Abc_ObjForEachFanin( pObj, pNext, i )
+        {
+            pLatch = Abc_NtkCreateLatch(pObj->pNtk);
+            Abc_ObjPatchFanin( pObj, pNext, pLatch );
+            Abc_ObjAddFanin( pLatch, pNext );
+            // create buffer isomorphic to this latch
+            if ( fInitial )
+            {
+                pLatch->pCopy = Abc_NtkCreateNodeBuf( pNtkNew, NULL );
+                Abc_ObjAddFanin( pObj->pCopy, pLatch->pCopy );
+            }
+        }
+    }
+    Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of compatible fanout latches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeCheckCompatibleLatchFanouts( Abc_Obj_t * pObj )
+{
+    Abc_Obj_t * pFanout;
+    int i, nLatches = 0, Init = -1;
+    Abc_ObjForEachFanout( pObj, pFanout, i )
+    {
+        if ( !Abc_ObjIsLatch(pFanout) )
+            continue;
+        if ( Init == -1 )
+        {
+            Init = (int)(ABC_PTRUINT_T)pObj->pData;
+            nLatches++;
+        }
+        else if ( Init == (int)(ABC_PTRUINT_T)pObj->pData )
+            nLatches++;
+    }
+    return nLatches;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Retimes the node backward or forward.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkRetimeShareLatches( Abc_Ntk_t * pNtk, int fInitial )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pFanin, * pLatchTop, * pLatchCur;
+    int i, k;
+    vNodes = Vec_PtrAlloc( 10 );
+    // consider latch fanins
+    Abc_NtkForEachObj( pNtk, pFanin, i )
+    {
+        if ( Abc_NtkRetimeCheckCompatibleLatchFanouts(pFanin) <= 1 )
+            continue;
+        // get the first latch
+        pLatchTop = NULL;
+        Abc_ObjForEachFanout( pFanin, pLatchTop, k )
+            if ( Abc_ObjIsLatch(pLatchTop) )
+                break;
+        assert( pLatchTop && Abc_ObjIsLatch(pLatchTop) );
+        // redirect compatible fanout latches to the first latch
+        Abc_NodeCollectFanouts( pFanin, vNodes );
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pLatchCur, k )
+        {
+            if ( !Abc_ObjIsLatch(pLatchCur) )
+                continue;
+            if ( pLatchCur == pLatchTop )
+                continue;
+            if ( pLatchCur->pData != pLatchTop->pData )
+                continue;
+            // connect the initial state
+            if ( fInitial )
+                Abc_ObjAddFanin( pLatchCur->pCopy, pLatchTop->pCopy );
+            // redirect the fanouts
+            Abc_ObjTransferFanout( pLatchCur, pLatchTop );
+            Abc_NtkDeleteObj(pLatchCur);
+        }
+    }
+    Vec_PtrFree( vNodes );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/ret/retInit.c b/abc-build/src/opt/ret/retInit.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/ret/retInit.c
@@ -0,0 +1,355 @@
+/**CFile****************************************************************
+
+  FileName    [retInit.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Retiming package.]
+
+  Synopsis    [Initial state computation for backward retiming.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Oct 31, 2006.]
+
+  Revision    [$Id: retInit.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_NtkRetimeVerifyModel( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int * pModel );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes initial values of the new latches.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkRetimeInitialValues( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int fVerbose )
+{
+    Vec_Int_t * vSolution;
+    Abc_Ntk_t * pNtkMiter, * pNtkLogic;
+    int RetValue;
+    abctime clk;
+    if ( pNtkCone == NULL )
+        return Vec_IntDup( vValues );
+    // convert the target network to AIG
+    pNtkLogic = Abc_NtkDup( pNtkCone );
+    Abc_NtkToAig( pNtkLogic );
+    // get the miter
+    pNtkMiter = Abc_NtkCreateTarget( pNtkLogic, pNtkLogic->vCos, vValues );
+    if ( fVerbose )
+        printf( "The miter for initial state computation has %d AIG nodes. ", Abc_NtkNodeNum(pNtkMiter) );
+    // solve the miter
+    clk = Abc_Clock();
+    RetValue = Abc_NtkMiterSat( pNtkMiter, (ABC_INT64_T)500000, (ABC_INT64_T)50000000, 0, NULL, NULL );
+    if ( fVerbose ) 
+        { ABC_PRT( "SAT solving time", Abc_Clock() - clk ); }
+    // analyze the result
+    if ( RetValue == 1 )
+        printf( "Abc_NtkRetimeInitialValues(): The problem is unsatisfiable. DC latch values are used.\n" );
+    else if ( RetValue == -1 )
+        printf( "Abc_NtkRetimeInitialValues(): The SAT problem timed out. DC latch values are used.\n" );
+    else if ( !Abc_NtkRetimeVerifyModel( pNtkCone, vValues, pNtkMiter->pModel ) )
+        printf( "Abc_NtkRetimeInitialValues(): The computed counter-example is incorrect.\n" );
+    // set the values of the latches
+    vSolution = RetValue? NULL : Vec_IntAllocArray( pNtkMiter->pModel, Abc_NtkPiNum(pNtkLogic) );
+    pNtkMiter->pModel = NULL;
+    Abc_NtkDelete( pNtkMiter );
+    Abc_NtkDelete( pNtkLogic );
+    return vSolution;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the results of simulating one node.]
+
+  Description [Assumes that fanins have pCopy set to the input values.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_ObjSopSimulate( Abc_Obj_t * pObj )
+{
+    char * pCube, * pSop = (char *)pObj->pData;
+    int nVars, Value, v, ResOr, ResAnd, ResVar;
+    assert( pSop && !Abc_SopIsExorType(pSop) );
+    // simulate the SOP of the node
+    ResOr = 0;
+    nVars = Abc_SopGetVarNum(pSop);
+    Abc_SopForEachCube( pSop, nVars, pCube )
+    {
+        ResAnd = 1;
+        Abc_CubeForEachVar( pCube, Value, v )
+        {
+            if ( Value == '0' )
+                ResVar = 1 ^ ((int)(ABC_PTRUINT_T)Abc_ObjFanin(pObj, v)->pCopy);
+            else if ( Value == '1' )
+                ResVar = (int)(ABC_PTRUINT_T)Abc_ObjFanin(pObj, v)->pCopy;
+            else
+                continue;
+            ResAnd &= ResVar;
+        }
+        ResOr |= ResAnd;
+    }
+    // complement the result if necessary
+    if ( !Abc_SopGetPhase(pSop) )
+        ResOr ^= 1;
+    return ResOr;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeVerifyModel( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int * pModel )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj;
+    int i, Counter = 0;
+    assert( Abc_NtkIsSopLogic(pNtkCone) );
+    // set the PIs
+    Abc_NtkForEachPi( pNtkCone, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)pModel[i];
+    // simulate the internal nodes
+    vNodes = Abc_NtkDfs( pNtkCone, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_ObjSopSimulate( pObj );
+    Vec_PtrFree( vNodes );
+    // compare the outputs
+    Abc_NtkForEachPo( pNtkCone, pObj, i )
+        pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy;
+    Abc_NtkForEachPo( pNtkCone, pObj, i )
+        Counter += (Vec_IntEntry(vValues, i) != (int)(ABC_PTRUINT_T)pObj->pCopy);
+    if ( Counter > 0 )
+        printf( "%d outputs (out of %d) have a value mismatch.\n", Counter, Abc_NtkPoNum(pNtkCone) );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfer latch initial values to pCopy.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkRetimeTranferToCopy( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( Abc_ObjIsLatch(pObj) )
+            pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_LatchIsInit1(pObj);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfer latch initial values from pCopy.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkRetimeTranferFromCopy( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( Abc_ObjIsLatch(pObj) )
+            pObj->pData = (void *)(ABC_PTRUINT_T)(pObj->pCopy? ABC_INIT_ONE : ABC_INIT_ZERO);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfer latch initial values to pCopy.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkRetimeCollectLatchValues( Abc_Ntk_t * pNtk )
+{
+    Vec_Int_t * vValues;
+    Abc_Obj_t * pObj;
+    int i;
+    vValues = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( Abc_ObjIsLatch(pObj) )
+            Vec_IntPush( vValues, Abc_LatchIsInit1(pObj) );
+    return vValues;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfer latch initial values from pCopy.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkRetimeInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues )
+{
+    Abc_Obj_t * pObj;
+    int i, Counter = 0;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( Abc_ObjIsLatch(pObj) )
+            pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Counter++;
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( Abc_ObjIsLatch(pObj) )
+            pObj->pData = (Abc_Obj_t *)(ABC_PTRUINT_T)(vValues? (Vec_IntEntry(vValues,(int)(ABC_PTRUINT_T)pObj->pCopy)? ABC_INIT_ONE : ABC_INIT_ZERO) : ABC_INIT_DC);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfer latch initial values to pCopy.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRetimeBackwardInitialStart( Abc_Ntk_t * pNtk )
+{
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObj;
+    int i;
+    // create the network used for the initial state computation
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+    // create POs corresponding to the initial values
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( Abc_ObjIsLatch(pObj) )
+            pObj->pCopy = Abc_NtkCreatePo(pNtkNew);
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfer latch initial values to pCopy.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkRetimeBackwardInitialFinish( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Vec_Int_t * vValuesOld, int fVerbose )
+{
+    Vec_Int_t * vValuesNew;
+    Abc_Obj_t * pObj;
+    int i;
+    // create PIs corresponding to the initial values
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( Abc_ObjIsLatch(pObj) )
+            Abc_ObjAddFanin( pObj->pCopy, Abc_NtkCreatePi(pNtkNew) );
+    // assign dummy node names
+    Abc_NtkAddDummyPiNames( pNtkNew );
+    Abc_NtkAddDummyPoNames( pNtkNew );
+    // check the network
+    if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkRetimeBackwardInitialFinish(): Network check has failed.\n" );
+    // derive new initial values
+    vValuesNew = Abc_NtkRetimeInitialValues( pNtkNew, vValuesOld, fVerbose );
+    // insert new initial values
+    Abc_NtkRetimeInsertLatchValues( pNtk, vValuesNew );
+    if ( vValuesNew ) Vec_IntFree( vValuesNew );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Cycles the circuit to create a new initial state.]
+
+  Description [Simulates the circuit with random input for the given 
+  number of timeframes to get a better initial state.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pObj;
+    int i, f;
+    assert( Abc_NtkIsSopLogic(pNtk) );
+    srand( 0x12341234 );
+    // initialize the values
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)(rand() & 1);
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_LatchIsInit1(pObj);
+    // simulate for the given number of timeframes
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // simulate internal nodes
+        Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+            pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_ObjSopSimulate( pObj );
+        // bring the results to the COs
+        Abc_NtkForEachCo( pNtk, pObj, i )
+            pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy;
+        // assign PI values
+        Abc_NtkForEachPi( pNtk, pObj, i )
+            pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)(rand() & 1);
+        // transfer the latch values
+        Abc_NtkForEachLatch( pNtk, pObj, i )
+            Abc_ObjFanout0(pObj)->pCopy = Abc_ObjFanin0(pObj)->pCopy;
+    }
+    Vec_PtrFree( vNodes );
+    // set the final values
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        pObj->pData = (void *)(ABC_PTRUINT_T)(Abc_ObjFanout0(pObj)->pCopy ? ABC_INIT_ONE : ABC_INIT_ZERO);
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/ret/retInt.h b/abc-build/src/opt/ret/retInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/ret/retInt.h
@@ -0,0 +1,88 @@
+/**CFile****************************************************************
+
+  FileName    [retInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Retiming package.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Oct 31, 2006.]
+
+  Revision    [$Id: retInt.h,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__opt__ret__retInt_h
+#define ABC__opt__ret__retInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "base/abc/abc.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== retArea.c ========================================================*/
+extern int         Abc_NtkRetimeMinArea( Abc_Ntk_t * pNtk, int fForwardOnly, int fBackwardOnly, int fVerbose );
+/*=== retCore.c ========================================================*/
+extern int         Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int nDelayLim, int fForwardOnly, int fBackwardOnly, int fOneStep, int fVerbose );
+/*=== retDelay.c ========================================================*/
+extern int         Abc_NtkRetimeMinDelay( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkCopy, int nDelayLim, int nIterLimit, int fForward, int fVerbose );
+/*=== retDirect.c ========================================================*/
+extern int         Abc_NtkRetimeIncremental( Abc_Ntk_t * pNtk, int nDelayLim, int fForward, int fMinDelay, int fOneStep, int fVerbose );
+extern void        Abc_NtkRetimeShareLatches( Abc_Ntk_t * pNtk, int fInitial );
+extern int         Abc_NtkRetimeNodeIsEnabled( Abc_Obj_t * pObj, int fForward );
+extern void        Abc_NtkRetimeNode( Abc_Obj_t * pObj, int fForward, int fInitial );
+extern st__table *  Abc_NtkRetimePrepareLatches( Abc_Ntk_t * pNtk );
+extern int         Abc_NtkRetimeFinalizeLatches( Abc_Ntk_t * pNtk, st__table * tLatches, int nIdMaxStart );
+/*=== retFlow.c ========================================================*/
+extern void        Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk );
+extern Vec_Ptr_t * Abc_NtkMaxFlow( Abc_Ntk_t * pNtk, int fForward, int fVerbose );
+/*=== retInit.c ========================================================*/
+extern Vec_Int_t * Abc_NtkRetimeInitialValues( Abc_Ntk_t * pNtkSat, Vec_Int_t * vValues, int fVerbose );
+extern int         Abc_ObjSopSimulate( Abc_Obj_t * pObj );
+extern void        Abc_NtkRetimeTranferToCopy( Abc_Ntk_t * pNtk );
+extern void        Abc_NtkRetimeTranferFromCopy( Abc_Ntk_t * pNtk );
+extern Vec_Int_t * Abc_NtkRetimeCollectLatchValues( Abc_Ntk_t * pNtk );
+extern void        Abc_NtkRetimeInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues );
+extern Abc_Ntk_t * Abc_NtkRetimeBackwardInitialStart( Abc_Ntk_t * pNtk );
+extern void        Abc_NtkRetimeBackwardInitialFinish( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Vec_Int_t * vValuesOld, int fVerbose );
+/*=== retLvalue.c ========================================================*/
+extern int         Abc_NtkRetimeLValue( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/abc-build/src/opt/ret/retLvalue.c b/abc-build/src/opt/ret/retLvalue.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/ret/retLvalue.c
@@ -0,0 +1,402 @@
+/**CFile****************************************************************
+
+  FileName    [retLvalue.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Retiming package.]
+
+  Synopsis    [Implementation of Pan's retiming algorithm.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Oct 31, 2006.]
+
+  Revision    [$Id: retLvalue.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// node status after updating its arrival time
+enum { ABC_RET_UPDATE_FAIL, ABC_RET_UPDATE_NO, ABC_RET_UPDATE_YES };
+
+// the internal procedures
+static Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose );
+static int         Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int FiMin, int FiMax, int nMaxIters, int fVerbose );
+static int         Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi, int nMaxIters, int fVerbose );
+static int         Abc_NtkRetimeUpdateLValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi );
+static int         Abc_NtkRetimePosOverLimit( Abc_Ntk_t * pNtk, int Fi );
+static Vec_Ptr_t * Abc_ManCollectLatches( Abc_Ntk_t * pNtk );
+static int         Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose );
+
+static inline int  Abc_NodeComputeLag( int LValue, int Fi )          { return (LValue + (1<<16)*Fi)/Fi - (1<<16) - (int)(LValue % Fi == 0);     }
+static inline int  Abc_NodeGetLValue( Abc_Obj_t * pNode )            { return (int)(ABC_PTRUINT_T)pNode->pCopy;        }
+static inline void Abc_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { pNode->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Value;    }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Implements Pan's retiming algorithm.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeLValue( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose )
+{
+    Vec_Int_t * vLags;
+    int nLatches = Abc_NtkLatchNum(pNtk);
+    assert( Abc_NtkIsLogic( pNtk ) );
+    // get the lags
+    vLags = Abc_NtkRetimeGetLags( pNtk, nIterLimit, fVerbose );
+    // compute the retiming
+//    Abc_NtkRetimeUsingLags( pNtk, vLags, fVerbose );
+    Vec_IntFree( vLags );
+    // fix the COs
+//    Abc_NtkLogicMakeSimpleCos( pNtk, 0 );
+    // check for correctness
+    if ( !Abc_NtkCheck( pNtk ) )
+        fprintf( stdout, "Abc_NtkRetimeLValue(): Network check has failed.\n" );
+    // return the number of latches saved
+    return nLatches - Abc_NtkLatchNum(pNtk);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the retiming lags.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose )
+{
+    Vec_Int_t * vLags;
+    Vec_Ptr_t * vNodes, * vLatches;
+    Abc_Obj_t * pNode;
+    int i, FiMax, FiBest, RetValue;
+    abctime clk, clkIter;
+    char NodeLag;
+
+    // get the upper bound on the clock period
+    FiMax = Abc_NtkLevel(pNtk);
+
+    // make sure this clock period is feasible
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    vLatches = Abc_ManCollectLatches( pNtk );
+    if ( !Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, FiMax, nIterLimit, fVerbose ) )
+    {
+        Vec_PtrFree( vLatches );
+        Vec_PtrFree( vNodes );
+        printf( "Abc_NtkRetimeGetLags() error: The upper bound on the clock period cannot be computed.\n" );
+        return Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
+    }
+ 
+    // search for the optimal clock period between 0 and nLevelMax
+clk = Abc_Clock();
+    FiBest = Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, 0, FiMax, nIterLimit, fVerbose );
+clkIter = Abc_Clock() - clk;
+
+    // recompute the best l-values
+    RetValue = Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, FiBest, nIterLimit, fVerbose );
+    assert( RetValue );
+
+    // fix the problem with non-converged delays
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        if ( Abc_NodeGetLValue(pNode) < -ABC_INFINITY/2 )
+            Abc_NodeSetLValue( pNode, 0 );
+
+    // write the retiming lags
+    vLags = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        NodeLag = Abc_NodeComputeLag( Abc_NodeGetLValue(pNode), FiBest );
+        Vec_IntWriteEntry( vLags, pNode->Id, NodeLag );
+    }
+/*
+    Abc_NtkForEachPo( pNtk, pNode, i )
+        printf( "%d ", Abc_NodeGetLValue(Abc_ObjFanin0(pNode)) );
+    printf( "\n" );
+    Abc_NtkForEachLatch( pNtk, pNode, i )
+        printf( "%d/%d ", Abc_NodeGetLValue(Abc_ObjFanout0(pNode)), Abc_NodeGetLValue(Abc_ObjFanout0(pNode)) + FiBest );
+    printf( "\n" );
+*/
+
+    // print the result
+//    if ( fVerbose )
+    printf( "The best clock period is %3d. (Currently, network is not modified.)\n", FiBest );
+/*
+    {
+        FILE * pTable;
+        pTable = fopen( "iscas/seqmap__stats2.txt", "a+" );
+        fprintf( pTable, "%d ", FiBest );
+        fprintf( pTable, "\n" );
+        fclose( pTable );
+    }
+*/
+    Vec_PtrFree( vNodes );
+    Vec_PtrFree( vLatches );
+    return vLags;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs binary search for the optimal clock period.]
+
+  Description [Assumes that FiMin is infeasible while FiMax is feasible.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int FiMin, int FiMax, int nMaxIters, int fVerbose )
+{
+    int Median;
+    assert( FiMin < FiMax );
+    if ( FiMin + 1 == FiMax )
+        return FiMax;
+    Median = FiMin + (FiMax - FiMin)/2;
+    if ( Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, Median, nMaxIters, fVerbose ) )
+        return Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, FiMin, Median, nMaxIters, fVerbose ); // Median is feasible
+    else 
+        return Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, Median, FiMax, nMaxIters, fVerbose ); // Median is infeasible
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if retiming with this clock period is feasible.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi, int nMaxIters, int fVerbose )
+{
+    Abc_Obj_t * pObj;
+    int c, i, fConverged;
+    // set l-values of all nodes to be minus infinity, except PIs and constants
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( Abc_ObjFaninNum(pObj) == 0 )
+            Abc_NodeSetLValue( pObj, 0 );
+        else
+            Abc_NodeSetLValue( pObj, -ABC_INFINITY );
+    // update all values iteratively
+    fConverged = 0;
+    for ( c = 1; c <= nMaxIters; c++ )
+    {
+        if ( !Abc_NtkRetimeUpdateLValue( pNtk, vNodes, vLatches, Fi ) )
+        {
+            fConverged = 1;
+            break;
+        }
+        if ( Abc_NtkRetimePosOverLimit(pNtk, Fi) )
+            break;
+    }
+    // report the results
+    if ( fVerbose )
+    {
+        if ( !fConverged )
+            printf( "Period = %3d.  Iterations = %3d.    Infeasible %s\n", Fi, c, (c > nMaxIters)? "(timeout)" : "" );
+        else
+            printf( "Period = %3d.  Iterations = %3d.      Feasible\n",    Fi, c );
+    }
+/*
+    // check if any AND gates have infinite delay
+    Counter = 0;
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        Counter += (Abc_NodeGetLValue(pObj) < -ABC_INFINITY/2);
+    if ( Counter > 0 )
+        printf( "Warning: %d internal nodes have wrong l-values!\n", Counter );
+*/
+    return fConverged;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one iteration of l-value computation for the nodes.]
+
+  Description [Experimentally it was found that checking POs changes
+  is not enough to detect the convergence of l-values in the network.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeUpdateLValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi )
+{
+    Abc_Obj_t * pObj, * pFanin;
+    int i, k, lValueNew, fChange;
+    // go through the nodes and detect change
+    fChange = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+    {
+        assert( Abc_ObjIsNode(pObj) );
+        lValueNew = -ABC_INFINITY;
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+        {
+            if ( lValueNew < Abc_NodeGetLValue(pFanin) )
+                lValueNew = Abc_NodeGetLValue(pFanin);
+        }
+        lValueNew++;
+        if ( Abc_NodeGetLValue(pObj) < lValueNew )
+        {
+            Abc_NodeSetLValue( pObj, lValueNew );
+            fChange = 1;
+        }
+    }
+    // propagate values through the latches
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLatches, pObj, i )
+        Abc_NodeSetLValue( Abc_ObjFanout0(pObj), Abc_NodeGetLValue(Abc_ObjFanin0(Abc_ObjFanin0(pObj))) - Fi );
+    return fChange;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detects the case when l-values exceeded the limit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimePosOverLimit( Abc_Ntk_t * pNtk, int Fi )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        if ( Abc_NodeGetLValue(Abc_ObjFanin0(pObj)) > Fi )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects latches in the topological order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+void Abc_ManCollectLatches_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLatches )
+{
+    Abc_Obj_t * pDriver;
+    if ( !Abc_ObjIsLatch(pObj) )
+        return;
+    // skip already collected latches
+    if ( Abc_NodeIsTravIdCurrent(pObj)  )
+        return;
+    Abc_NodeSetTravIdCurrent(pObj);
+    // get the driver node feeding into the latch
+    pDriver = Abc_ObjFanin0(Abc_ObjFanin0(pObj));
+    // call recursively if the driver looks like a latch output
+    if ( Abc_ObjIsBo(pDriver) )
+        Abc_ManCollectLatches_rec( Abc_ObjFanin0(pDriver), vLatches );
+    // collect the latch
+    Vec_PtrPush( vLatches, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects latches in the topological order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_ManCollectLatches( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vLatches;
+    Abc_Obj_t * pObj;
+    int i;
+    vLatches = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) );
+    Abc_NtkIncrementTravId( pNtk );
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+        Abc_ManCollectLatches_rec( pObj, vLatches );
+    assert( Vec_PtrSize(vLatches) == Abc_NtkLatchNum(pNtk) );
+    return vLatches;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implements the retiming given as the array of retiming lags.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose )
+{
+    Abc_Obj_t * pObj;
+    int fChanges, fForward, nTotalMoves, Lag, Counter, i;
+    // iterate over the nodes
+    nTotalMoves = 0;
+    do {
+        fChanges = 0;
+        Abc_NtkForEachNode( pNtk, pObj, i )
+        {
+            Lag = Vec_IntEntry( vLags, pObj->Id );
+            if ( !Lag )
+                continue;
+            fForward = (Lag < 0);
+            if ( Abc_NtkRetimeNodeIsEnabled( pObj, fForward ) )
+            {
+                Abc_NtkRetimeNode( pObj, fForward, 0 );
+                fChanges = 1;
+                nTotalMoves++;
+                Vec_IntAddToEntry( vLags, pObj->Id, fForward? 1 : -1 );
+            }
+        }
+    } while ( fChanges );
+    if ( fVerbose )
+        printf( "Total latch moves = %d.\n", nTotalMoves );
+    // check if there are remaining lags
+    Counter = 0;
+    Abc_NtkForEachNode( pNtk, pObj, i )
+        Counter += (Vec_IntEntry( vLags, pObj->Id ) != 0);
+    if ( Counter )
+        printf( "Warning! The number of nodes with unrealized lag = %d.\n", Counter );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/ret/ret_.c b/abc-build/src/opt/ret/ret_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/ret/ret_.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+  FileName    [ret_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Retiming package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Oct 31, 2006.]
+
+  Revision    [$Id: ret_.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/rwr/module.make b/abc-build/src/opt/rwr/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/rwr/module.make
@@ -0,0 +1,7 @@
+SRC +=  src/opt/rwr/rwrDec.c \
+	src/opt/rwr/rwrEva.c \
+	src/opt/rwr/rwrExp.c \
+	src/opt/rwr/rwrLib.c \
+	src/opt/rwr/rwrMan.c \
+	src/opt/rwr/rwrPrint.c \
+	src/opt/rwr/rwrUtil.c
diff --git a/abc-build/src/opt/rwr/rwr.h b/abc-build/src/opt/rwr/rwr.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/rwr/rwr.h
@@ -0,0 +1,173 @@
+/**CFile****************************************************************
+
+  FileName    [rwr.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rwr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__opt__rwr__rwr_h
+#define ABC__opt__rwr__rwr_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "base/abc/abc.h"
+#include "opt/cut/cut.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+#define RWR_LIMIT  1048576/4  // ((1 << 20) 
+
+typedef struct Rwr_Man_t_   Rwr_Man_t;
+typedef struct Rwr_Node_t_  Rwr_Node_t;
+
+struct Rwr_Man_t_
+{
+    // internal lookups
+    int                nFuncs;           // number of four var functions
+    unsigned short *   puCanons;         // canonical forms
+    char *             pPhases;          // canonical phases
+    char *             pPerms;           // canonical permutations
+    unsigned char *    pMap;             // mapping of functions into class numbers
+    unsigned short *   pMapInv;          // mapping of classes into functions
+    char *             pPractical;       // practical NPN classes
+    char **            pPerms4;          // four-var permutations
+    // node space
+    Vec_Ptr_t *        vForest;          // all the nodes
+    Rwr_Node_t **      pTable;           // the hash table of nodes by their canonical form
+    Vec_Vec_t *        vClasses;         // the nodes of the equivalence classes
+    Extra_MmFixed_t *  pMmNode;          // memory for nodes and cuts
+    // statistical variables
+    int                nTravIds;         // the counter of traversal IDs
+    int                nConsidered;      // the number of nodes considered
+    int                nAdded;           // the number of nodes added to lists
+    int                nClasses;         // the number of NN classes
+    // the result of resynthesis
+    int                fCompl;           // indicates if the output of FF should be complemented
+    void *             pGraph;           // the decomposition tree (temporary)
+    Vec_Ptr_t *        vFanins;          // the fanins array (temporary)
+    Vec_Ptr_t *        vFaninsCur;       // the fanins array (temporary)
+    Vec_Int_t *        vLevNums;         // the array of levels (temporary)
+    Vec_Ptr_t *        vNodesTemp;       // the nodes in MFFC (temporary)
+    // node statistics
+    int                nNodesConsidered;
+    int                nNodesRewritten;
+    int                nNodesGained;
+    int                nNodesBeg;
+    int                nNodesEnd;
+    int                nScores[222];
+    int                nCutsGood;
+    int                nCutsBad;
+    int                nSubgraphs;
+    // runtime statistics
+    abctime            timeStart;
+    abctime            timeCut;
+    abctime            timeRes;
+    abctime            timeEval;
+    abctime            timeMffc;
+    abctime            timeUpdate;
+    abctime            timeTotal;
+};
+
+struct Rwr_Node_t_ // 24 bytes
+{
+    int                Id;               // ID 
+    int                TravId;           // traversal ID
+    short              nScore;
+    short              nGain;
+    short              nAdded;
+    unsigned           uTruth : 16;      // truth table
+    unsigned           Volume :  8;      // volume
+    unsigned           Level  :  6;      // level
+    unsigned           fUsed  :  1;      // mark
+    unsigned           fExor  :  1;      // mark
+    Rwr_Node_t *       p0;               // first child
+    Rwr_Node_t *       p1;               // second child
+    Rwr_Node_t *       pNext;            // next in the table
+};
+
+// manipulation of complemented attributes
+static inline int          Rwr_IsComplement( Rwr_Node_t * p )    { return (int )(((ABC_PTRUINT_T)p) & 01);           }
+static inline Rwr_Node_t * Rwr_Regular( Rwr_Node_t * p )         { return (Rwr_Node_t *)((ABC_PTRUINT_T)(p) & ~01);  }
+static inline Rwr_Node_t * Rwr_Not( Rwr_Node_t * p )             { return (Rwr_Node_t *)((ABC_PTRUINT_T)(p) ^  01);  }
+static inline Rwr_Node_t * Rwr_NotCond( Rwr_Node_t * p, int c )  { return (Rwr_Node_t *)((ABC_PTRUINT_T)(p) ^ (c));  }
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== rwrDec.c ========================================================*/
+extern void              Rwr_ManPreprocess( Rwr_Man_t * p );
+/*=== rwrEva.c ========================================================*/
+extern int               Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUpdateLevel, int fUseZeros, int fPlaceEnable );
+extern void              Rwr_ScoresClean( Rwr_Man_t * p );
+extern void              Rwr_ScoresReport( Rwr_Man_t * p );
+/*=== rwrLib.c ========================================================*/
+extern void              Rwr_ManPrecompute( Rwr_Man_t * p );
+extern Rwr_Node_t *      Rwr_ManAddVar( Rwr_Man_t * p, unsigned uTruth, int fPrecompute );
+extern Rwr_Node_t *      Rwr_ManAddNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume );
+extern int               Rwr_ManNodeVolume( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1 );
+extern void              Rwr_ManIncTravId( Rwr_Man_t * p );
+/*=== rwrMan.c ========================================================*/
+extern Rwr_Man_t *       Rwr_ManStart( int  fPrecompute );
+extern void              Rwr_ManStop( Rwr_Man_t * p );
+extern void              Rwr_ManPrintStats( Rwr_Man_t * p );
+extern void              Rwr_ManPrintStatsFile( Rwr_Man_t * p );
+extern void *            Rwr_ManReadDecs( Rwr_Man_t * p );
+extern Vec_Ptr_t *       Rwr_ManReadLeaves( Rwr_Man_t * p );
+extern int               Rwr_ManReadCompl( Rwr_Man_t * p );
+extern void              Rwr_ManAddTimeCuts( Rwr_Man_t * p, abctime Time );
+extern void              Rwr_ManAddTimeUpdate( Rwr_Man_t * p, abctime Time );
+extern void              Rwr_ManAddTimeTotal( Rwr_Man_t * p, abctime Time );
+/*=== rwrPrint.c ========================================================*/
+extern void              Rwr_ManPrint( Rwr_Man_t * p );
+/*=== rwrUtil.c ========================================================*/
+extern void              Rwr_ManWriteToArray( Rwr_Man_t * p );
+extern void              Rwr_ManLoadFromArray( Rwr_Man_t * p, int fVerbose );
+extern void              Rwr_ManWriteToFile( Rwr_Man_t * p, char * pFileName );
+extern void              Rwr_ManLoadFromFile( Rwr_Man_t * p, char * pFileName );
+extern void              Rwr_ListAddToTail( Rwr_Node_t ** ppList, Rwr_Node_t * pNode );
+extern char *            Rwr_ManGetPractical( Rwr_Man_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/rwr/rwrDec.c b/abc-build/src/opt/rwr/rwrDec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/rwr/rwrDec.c
@@ -0,0 +1,155 @@
+/**CFile****************************************************************
+
+  FileName    [rwrDec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting package.]
+
+  Synopsis    [Evaluation and decomposition procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rwrDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rwr.h"
+#include "bool/dec/dec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Dec_Graph_t * Rwr_NodePreprocess( Rwr_Man_t * p, Rwr_Node_t * pNode );
+static Dec_Edge_t    Rwr_TravCollect_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, Dec_Graph_t * pGraph );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Preprocesses computed library of subgraphs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_ManPreprocess( Rwr_Man_t * p )
+{
+    Dec_Graph_t * pGraph;
+    Rwr_Node_t * pNode;
+    int i, k;
+    // put the nodes into the structure
+    p->pMapInv  = ABC_ALLOC( unsigned short, 222 );
+    memset( p->pMapInv, 0, sizeof(unsigned short) * 222 );
+    p->vClasses = Vec_VecStart( 222 );
+    for ( i = 0; i < p->nFuncs; i++ )
+    {
+        if ( p->pTable[i] == NULL )
+            continue;
+        // consider all implementations of this function
+        for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext )
+        {
+            assert( pNode->uTruth == p->pTable[i]->uTruth );
+            assert( p->pMap[pNode->uTruth] < 222 ); // Guaranteed to be >=0 b/c unsigned
+            Vec_VecPush( p->vClasses, p->pMap[pNode->uTruth], pNode );
+            p->pMapInv[ p->pMap[pNode->uTruth] ] = p->puCanons[pNode->uTruth];
+        }
+    }
+    // compute decomposition forms for each node and verify them
+    Vec_VecForEachEntry( Rwr_Node_t *, p->vClasses, pNode, i, k )
+    {
+        pGraph = Rwr_NodePreprocess( p, pNode );
+        pNode->pNext = (Rwr_Node_t *)pGraph;
+        assert( pNode->uTruth == (Dec_GraphDeriveTruth(pGraph) & 0xFFFF) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Preprocesses subgraphs rooted at this node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Rwr_NodePreprocess( Rwr_Man_t * p, Rwr_Node_t * pNode )
+{
+    Dec_Graph_t * pGraph;
+    Dec_Edge_t eRoot;
+    assert( !Rwr_IsComplement(pNode) );
+    // consider constant
+    if ( pNode->uTruth == 0 )
+        return Dec_GraphCreateConst0();
+    // consider the case of elementary var
+    if ( pNode->uTruth == 0x00FF )
+        return Dec_GraphCreateLeaf( 3, 4, 1 );
+    // start the subgraphs
+    pGraph = Dec_GraphCreate( 4 );
+    // collect the nodes
+    Rwr_ManIncTravId( p );
+    eRoot = Rwr_TravCollect_rec( p, pNode, pGraph );
+    Dec_GraphSetRoot( pGraph, eRoot );
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Edge_t Rwr_TravCollect_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, Dec_Graph_t * pGraph )
+{
+    Dec_Edge_t eNode0, eNode1, eNode;
+    // elementary variable
+    if ( pNode->fUsed )
+        return Dec_EdgeCreate( pNode->Id - 1, 0 );
+    // previously visited node
+    if ( pNode->TravId == p->nTravIds )
+        return Dec_IntToEdge( pNode->Volume );
+    pNode->TravId = p->nTravIds;
+    // solve for children
+    eNode0 = Rwr_TravCollect_rec( p, Rwr_Regular(pNode->p0), pGraph );
+    if ( Rwr_IsComplement(pNode->p0) )    
+        eNode0.fCompl = !eNode0.fCompl;
+    eNode1 = Rwr_TravCollect_rec( p, Rwr_Regular(pNode->p1), pGraph );
+    if ( Rwr_IsComplement(pNode->p1) )    
+        eNode1.fCompl = !eNode1.fCompl;
+    // create the decomposition node(s)
+    if ( pNode->fExor )
+        eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1, 0 );
+    else
+        eNode = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
+    // save the result
+    pNode->Volume = Dec_EdgeToInt( eNode );
+    return eNode;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/rwr/rwrEva.c b/abc-build/src/opt/rwr/rwrEva.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/rwr/rwrEva.c
@@ -0,0 +1,599 @@
+/**CFile****************************************************************
+
+  FileName    [rwrDec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting package.]
+
+  Synopsis    [Evaluation and decomposition procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rwrDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rwr.h"
+#include "bool/dec/dec.h"
+#include "aig/ivy/ivy.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, int fPlaceEnable );
+static int Rwr_CutIsBoolean( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves );
+static int Rwr_CutCountNumNodes( Abc_Obj_t * pObj, Cut_Cut_t * pCut );
+static int Rwr_NodeGetDepth_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs rewriting for one node.]
+
+  Description [This procedure considers all the cuts computed for the node
+  and tries to rewrite each of them using the "forest" of different AIG
+  structures precomputed and stored in the RWR manager. 
+  Determines the best rewriting and computes the gain in the number of AIG
+  nodes in the final network. In the end, p->vFanins contains information 
+  about the best cut that can be used for rewriting, while p->pGraph gives 
+  the decomposition dag (represented using decomposition graph data structure).
+  Returns gain in the number of nodes or -1 if node cannot be rewritten.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUpdateLevel, int fUseZeros, int fPlaceEnable )
+{
+    int fVeryVerbose = 0;
+    Dec_Graph_t * pGraph;
+    Cut_Cut_t * pCut;//, * pTemp;
+    Abc_Obj_t * pFanin;
+    unsigned uPhase;
+    unsigned uTruthBest = 0; // Suppress "might be used uninitialized"
+    unsigned uTruth;
+    char * pPerm;
+    int Required, nNodesSaved;
+    int nNodesSaveCur = -1; // Suppress "might be used uninitialized"
+    int i, GainCur, GainBest = -1;
+    abctime clk, clk2;//, Counter;
+
+    p->nNodesConsidered++;
+    // get the required times
+    Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY;
+
+    // get the node's cuts
+clk = Abc_Clock();
+    pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, 0, 0 );
+    assert( pCut != NULL );
+p->timeCut += Abc_Clock() - clk;
+
+//printf( " %d", Rwr_CutCountNumNodes(pNode, pCut) );
+/*
+    Counter = 0;
+    for ( pTemp = pCut->pNext; pTemp; pTemp = pTemp->pNext )
+        Counter++;
+    printf( "%d ", Counter );
+*/
+    // go through the cuts
+clk = Abc_Clock();
+    for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext )
+    {
+        // consider only 4-input cuts
+        if ( pCut->nLeaves < 4 )
+            continue;
+//            Cut_CutPrint( pCut, 0 ), printf( "\n" );
+
+        // get the fanin permutation
+        uTruth = 0xFFFF & *Cut_CutReadTruth(pCut);
+        pPerm = p->pPerms4[ (int)p->pPerms[uTruth] ];
+        uPhase = p->pPhases[uTruth];
+        // collect fanins with the corresponding permutation/phase
+        Vec_PtrClear( p->vFaninsCur );
+        Vec_PtrFill( p->vFaninsCur, (int)pCut->nLeaves, 0 );
+        for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        {
+            pFanin = Abc_NtkObj( pNode->pNtk, pCut->pLeaves[(int)pPerm[i]] );
+            if ( pFanin == NULL )
+                break;
+            pFanin = Abc_ObjNotCond(pFanin, ((uPhase & (1<<i)) > 0) );
+            Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin );
+        }
+        if ( i != (int)pCut->nLeaves )
+        {
+            p->nCutsBad++;
+            continue;
+        }
+        p->nCutsGood++;
+
+        {
+            int Counter = 0;
+            Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i )
+                if ( Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) == 1 )
+                    Counter++;
+            if ( Counter > 2 )
+                continue;
+        }
+
+clk2 = Abc_Clock();
+/*
+        printf( "Considering: (" );
+        Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i )
+            printf( "%d ", Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) );
+        printf( ")\n" );
+*/
+        // mark the fanin boundary 
+        Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i )
+            Abc_ObjRegular(pFanin)->vFanouts.nSize++;
+
+        // label MFFC with current ID
+        Abc_NtkIncrementTravId( pNode->pNtk );
+        nNodesSaved = Abc_NodeMffcLabelAig( pNode );
+        // unmark the fanin boundary
+        Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i )
+            Abc_ObjRegular(pFanin)->vFanouts.nSize--;
+p->timeMffc += Abc_Clock() - clk2;
+
+        // evaluate the cut
+clk2 = Abc_Clock();
+        pGraph = Rwr_CutEvaluate( p, pNode, pCut, p->vFaninsCur, nNodesSaved, Required, &GainCur, fPlaceEnable );
+p->timeEval += Abc_Clock() - clk2;
+
+        // check if the cut is better than the current best one
+        if ( pGraph != NULL && GainBest < GainCur )
+        {
+            // save this form
+            nNodesSaveCur = nNodesSaved;
+            GainBest  = GainCur;
+            p->pGraph  = pGraph;
+            p->fCompl = ((uPhase & (1<<4)) > 0);
+            uTruthBest = 0xFFFF & *Cut_CutReadTruth(pCut);
+            // collect fanins in the
+            Vec_PtrClear( p->vFanins );
+            Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i )
+                Vec_PtrPush( p->vFanins, pFanin );
+        }
+    }
+p->timeRes += Abc_Clock() - clk;
+
+    if ( GainBest == -1 )
+        return -1;
+/*
+    if ( GainBest > 0 )
+    {
+        printf( "Class %d  ", p->pMap[uTruthBest] );
+        printf( "Gain = %d. Node %d : ", GainBest, pNode->Id );
+        Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanins, pFanin, i )
+            printf( "%d ", Abc_ObjRegular(pFanin)->Id );
+        Dec_GraphPrint( stdout, p->pGraph, NULL, NULL );
+        printf( "\n" );
+    }
+*/
+
+//    printf( "%d", nNodesSaveCur - GainBest );
+/*
+    if ( GainBest > 0 )
+    {
+        if ( Rwr_CutIsBoolean( pNode, p->vFanins ) )
+            printf( "b" );
+        else
+        {
+            printf( "Node %d : ", pNode->Id );
+            Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanins, pFanin, i )
+                printf( "%d ", Abc_ObjRegular(pFanin)->Id );
+            printf( "a" );
+        }
+    }
+*/
+/*
+    if ( GainBest > 0 )
+        if ( p->fCompl )
+            printf( "c" );
+        else
+            printf( "." );
+*/
+
+    // copy the leaves
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanins, pFanin, i )
+        Dec_GraphNode((Dec_Graph_t *)p->pGraph, i)->pFunc = pFanin;
+/*
+    printf( "(" );
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanins, pFanin, i )
+        printf( " %d", Abc_ObjRegular(pFanin)->vFanouts.nSize - 1 );
+    printf( " )  " );
+*/
+//    printf( "%d ", Rwr_NodeGetDepth_rec( pNode, p->vFanins ) );
+
+    p->nScores[p->pMap[uTruthBest]]++;
+    p->nNodesGained += GainBest;
+    if ( fUseZeros || GainBest > 0 )
+    {
+        p->nNodesRewritten++;
+    }
+
+    // report the progress
+    if ( fVeryVerbose && GainBest > 0 )
+    {
+        printf( "Node %6s :   ", Abc_ObjName(pNode) );
+        printf( "Fanins = %d. ", p->vFanins->nSize );
+        printf( "Save = %d.  ", nNodesSaveCur );
+        printf( "Add = %d.  ",  nNodesSaveCur-GainBest );
+        printf( "GAIN = %d.  ", GainBest );
+        printf( "Cone = %d.  ", p->pGraph? Dec_GraphNodeNum((Dec_Graph_t *)p->pGraph) : 0 );
+        printf( "Class = %d.  ", p->pMap[uTruthBest] );
+        printf( "\n" );
+    }
+    return GainBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, int fPlaceEnable )
+{
+    extern int            Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax );
+    Vec_Ptr_t * vSubgraphs;
+    Dec_Graph_t * pGraphBest = NULL; // Suppress "might be used uninitialized"
+    Dec_Graph_t * pGraphCur;
+    Rwr_Node_t * pNode, * pFanin;
+    int nNodesAdded, GainBest, i, k;
+    unsigned uTruth;
+    float CostBest;//, CostCur;
+    // find the matching class of subgraphs
+    uTruth = 0xFFFF & *Cut_CutReadTruth(pCut);
+    vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] );
+    p->nSubgraphs += vSubgraphs->nSize;
+    // determine the best subgraph
+    GainBest = -1;
+    CostBest = ABC_INFINITY;
+    Vec_PtrForEachEntry( Rwr_Node_t *, vSubgraphs, pNode, i )
+    {
+        // get the current graph
+        pGraphCur = (Dec_Graph_t *)pNode->pNext;
+        // copy the leaves
+        Vec_PtrForEachEntry( Rwr_Node_t *, vFaninsCur, pFanin, k )
+            Dec_GraphNode(pGraphCur, k)->pFunc = pFanin;
+        // detect how many unlabeled nodes will be reused
+        nNodesAdded = Dec_GraphToNetworkCount( pRoot, pGraphCur, nNodesSaved, LevelMax );
+        if ( nNodesAdded == -1 )
+            continue;
+        assert( nNodesSaved >= nNodesAdded );
+/*
+        // evaluate the cut
+        if ( fPlaceEnable )
+        {
+            extern float Abc_PlaceEvaluateCut( Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins );
+
+            float Alpha = 0.5; // ???
+            float PlaceCost;
+
+            // get the placement cost of the cut
+            PlaceCost = Abc_PlaceEvaluateCut( pRoot, vFaninsCur );
+
+            // get the weigted cost of the cut
+            CostCur = nNodesSaved - nNodesAdded + Alpha * PlaceCost;
+
+            // do not allow uphill moves
+            if ( nNodesSaved - nNodesAdded < 0 )
+                continue;
+
+            // decide what cut to use
+            if ( CostBest > CostCur )
+            {
+                GainBest   = nNodesSaved - nNodesAdded; // pure node cost
+                CostBest   = CostCur;                   // cost with placement
+                pGraphBest = pGraphCur;                 // subgraph to be used for rewriting
+
+                // score the graph
+                if ( nNodesSaved - nNodesAdded > 0 )
+                {
+                    pNode->nScore++;
+                    pNode->nGain += GainBest;
+                    pNode->nAdded += nNodesAdded;
+                }
+            }
+        }
+        else
+*/
+        {
+            // count the gain at this node
+            if ( GainBest < nNodesSaved - nNodesAdded )
+            {
+                GainBest   = nNodesSaved - nNodesAdded;
+                pGraphBest = pGraphCur;
+
+                // score the graph
+                if ( nNodesSaved - nNodesAdded > 0 )
+                {
+                    pNode->nScore++;
+                    pNode->nGain += GainBest;
+                    pNode->nAdded += nNodesAdded;
+                }
+            }
+        }
+    }
+    if ( GainBest == -1 )
+        return NULL;
+    *pGainBest = GainBest;
+    return pGraphBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the type of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_CutIsBoolean_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves, int fMarkA )
+{
+    if ( Vec_PtrFind(vLeaves, pObj) >= 0 || Vec_PtrFind(vLeaves, Abc_ObjNot(pObj)) >= 0 )
+    {
+        if ( fMarkA )
+            pObj->fMarkA = 1;
+        else
+            pObj->fMarkB = 1;
+        return;
+    }
+    assert( !Abc_ObjIsCi(pObj) );
+    Rwr_CutIsBoolean_rec( Abc_ObjFanin0(pObj), vLeaves, fMarkA );
+    Rwr_CutIsBoolean_rec( Abc_ObjFanin1(pObj), vLeaves, fMarkA );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the type of the cut.]
+
+  Description [Returns 1(0) if the cut is Boolean (algebraic).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rwr_CutIsBoolean( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves )
+{
+    Abc_Obj_t * pTemp;
+    int i, RetValue;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pTemp, i )
+    {
+        pTemp = Abc_ObjRegular(pTemp);
+        assert( !pTemp->fMarkA && !pTemp->fMarkB );
+    }
+    Rwr_CutIsBoolean_rec( Abc_ObjFanin0(pObj), vLeaves, 1 );
+    Rwr_CutIsBoolean_rec( Abc_ObjFanin1(pObj), vLeaves, 0 );
+    RetValue = 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pTemp, i )
+    {
+        pTemp = Abc_ObjRegular(pTemp);
+        RetValue |= pTemp->fMarkA && pTemp->fMarkB;
+        pTemp->fMarkA = pTemp->fMarkB = 0;
+    }
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Count the nodes in the cut space of a node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_CutCountNumNodes_rec( Abc_Obj_t * pObj, Cut_Cut_t * pCut, Vec_Ptr_t * vNodes )
+{
+    int i;
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        if ( pCut->pLeaves[i] == pObj->Id )
+        {
+            // check if the node is collected
+            if ( pObj->fMarkC == 0 )
+            {
+                pObj->fMarkC = 1;
+                Vec_PtrPush( vNodes, pObj );
+            }
+            return;
+        }
+    assert( Abc_ObjIsNode(pObj) );
+    // check if the node is collected
+    if ( pObj->fMarkC == 0 )
+    {
+        pObj->fMarkC = 1;
+        Vec_PtrPush( vNodes, pObj );
+    }
+    // traverse the fanins
+    Rwr_CutCountNumNodes_rec( Abc_ObjFanin0(pObj), pCut, vNodes );
+    Rwr_CutCountNumNodes_rec( Abc_ObjFanin1(pObj), pCut, vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the nodes in the cut space of a node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rwr_CutCountNumNodes( Abc_Obj_t * pObj, Cut_Cut_t * pCut )
+{
+    Vec_Ptr_t * vNodes;
+    int i, Counter;
+    // collect all nodes
+    vNodes = Vec_PtrAlloc( 100 );
+    for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext )
+        Rwr_CutCountNumNodes_rec( pObj, pCut, vNodes );
+    // clean all nodes
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
+        pObj->fMarkC = 0;
+    // delete and return
+    Counter = Vec_PtrSize(vNodes);
+    Vec_PtrFree( vNodes );
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns depth of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rwr_NodeGetDepth_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves )
+{
+    Abc_Obj_t * pLeaf;
+    int i, Depth0, Depth1;
+    if ( Abc_ObjIsCi(pObj) )
+        return 0;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pLeaf, i )
+        if ( pObj == Abc_ObjRegular(pLeaf) )
+            return 0;
+    Depth0 = Rwr_NodeGetDepth_rec( Abc_ObjFanin0(pObj), vLeaves );
+    Depth1 = Rwr_NodeGetDepth_rec( Abc_ObjFanin1(pObj), vLeaves );
+    return 1 + Abc_MaxInt( Depth0, Depth1 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_ScoresClean( Rwr_Man_t * p )
+{
+    Vec_Ptr_t * vSubgraphs;
+    Rwr_Node_t * pNode;
+    int i, k;
+    for ( i = 0; i < p->vClasses->nSize; i++ )
+    {
+        vSubgraphs = Vec_VecEntry( p->vClasses, i );
+        Vec_PtrForEachEntry( Rwr_Node_t *, vSubgraphs, pNode, k )
+            pNode->nScore = pNode->nGain = pNode->nAdded = 0;
+    }
+}
+
+static int Gains[222];
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rwr_ScoresCompare( int * pNum1, int * pNum2 )
+{
+    if ( Gains[*pNum1] > Gains[*pNum2] )
+        return -1;
+    if ( Gains[*pNum1] < Gains[*pNum2] )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_ScoresReport( Rwr_Man_t * p )
+{
+    extern void Ivy_TruthDsdComputePrint( unsigned uTruth );
+    int Perm[222];
+    Vec_Ptr_t * vSubgraphs;
+    Rwr_Node_t * pNode;
+    int i, iNew, k;
+    unsigned uTruth;
+    // collect total gains
+    assert( p->vClasses->nSize == 222 );
+    for ( i = 0; i < p->vClasses->nSize; i++ )
+    {
+        Perm[i] = i;
+        Gains[i] = 0;
+        vSubgraphs = Vec_VecEntry( p->vClasses, i );
+        Vec_PtrForEachEntry( Rwr_Node_t *, vSubgraphs, pNode, k )
+            Gains[i] += pNode->nGain;
+    }
+    // sort the gains
+    qsort( Perm, 222, sizeof(int), (int (*)(const void *, const void *))Rwr_ScoresCompare );
+
+    // print classes
+    for ( i = 0; i < p->vClasses->nSize; i++ )
+    {
+        iNew = Perm[i];
+        if ( Gains[iNew] == 0 )
+            break;
+        vSubgraphs = Vec_VecEntry( p->vClasses, iNew );
+        printf( "CLASS %3d: Subgr = %3d. Total gain = %6d.  ", iNew, Vec_PtrSize(vSubgraphs), Gains[iNew] );
+        uTruth = (unsigned)p->pMapInv[iNew];
+        Extra_PrintBinary( stdout, &uTruth, 16 );
+        printf( "  " );
+        Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[iNew] | ((unsigned)p->pMapInv[iNew] << 16) );
+        Vec_PtrForEachEntry( Rwr_Node_t *, vSubgraphs, pNode, k )
+        {
+            if ( pNode->nScore == 0 )
+                continue;
+            printf( "    %2d: S=%5d. A=%5d. G=%6d. ", k, pNode->nScore, pNode->nAdded, pNode->nGain );
+            Dec_GraphPrint( stdout, (Dec_Graph_t *)pNode->pNext, NULL, NULL );
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/rwr/rwrExp.c b/abc-build/src/opt/rwr/rwrExp.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/rwr/rwrExp.c
@@ -0,0 +1,336 @@
+/**CFile****************************************************************
+
+  FileName    [rwrExp.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting package.]
+
+  Synopsis    [Computation of practically used NN-classes of 4-input cuts.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rwrExp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rwr.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Rwr_Man4_t_ Rwr_Man4_t;
+struct Rwr_Man4_t_
+{
+    // internal lookups
+    int                nFuncs;           // the number of four-var functions
+    unsigned short *   puCanons;         // canonical forms
+    int *              pnCounts;         // the counters of functions in each class
+    int                nConsidered;      // the number of nodes considered
+    int                nClasses;         // the number of NN classes
+};
+
+typedef struct Rwr_Man5_t_ Rwr_Man5_t;
+struct Rwr_Man5_t_
+{
+    // internal lookups
+    stmm_table *       tTableNN;         // the NN canonical forms
+    stmm_table *       tTableNPN;        // the NPN canonical forms
+};
+
+static Rwr_Man4_t * s_pManRwrExp4 = NULL;
+static Rwr_Man5_t * s_pManRwrExp5 = NULL;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Collects stats about 4-var functions appearing in netlists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_Man4ExploreStart()
+{
+    Rwr_Man4_t * p;
+    p = ABC_ALLOC( Rwr_Man4_t, 1 );
+    memset( p, 0, sizeof(Rwr_Man4_t) );
+    // canonical forms
+    p->nFuncs    = (1<<16);
+    // canonical forms, phases, perms
+    Extra_Truth4VarNPN( &p->puCanons, NULL, NULL, NULL );
+    // counters
+    p->pnCounts  = ABC_ALLOC( int, p->nFuncs );
+    memset( p->pnCounts, 0, sizeof(int) * p->nFuncs );
+    s_pManRwrExp4 = p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects stats about 4-var functions appearing in netlists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_Man4ExploreCount( unsigned uTruth )
+{
+    assert( uTruth < (1<<16) );
+    s_pManRwrExp4->pnCounts[ s_pManRwrExp4->puCanons[uTruth] ]++;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects stats about 4-var functions appearing in netlists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_Man4ExplorePrint()
+{
+    FILE * pFile;
+    int i, CountMax, CountWrite, nCuts, nClasses;
+    int * pDistrib;
+    int * pReprs;
+    // find the max number of occurences
+    nCuts = nClasses = 0;
+    CountMax = 0;
+    for ( i = 0; i < s_pManRwrExp4->nFuncs; i++ )
+    {
+        if ( CountMax < s_pManRwrExp4->pnCounts[i] )
+            CountMax = s_pManRwrExp4->pnCounts[i];
+        nCuts += s_pManRwrExp4->pnCounts[i];
+        if ( s_pManRwrExp4->pnCounts[i] > 0 )
+            nClasses++;
+    }
+    printf( "Number of cuts considered       = %8d.\n", nCuts );
+    printf( "Classes occurring at least once = %8d.\n", nClasses );
+    // print the distribution of classes
+    pDistrib = ABC_ALLOC( int, CountMax + 1 );
+    pReprs   = ABC_ALLOC( int, CountMax + 1 );
+    memset( pDistrib, 0, sizeof(int)*(CountMax + 1) );
+    for ( i = 0; i < s_pManRwrExp4->nFuncs; i++ )
+    {
+        pDistrib[ s_pManRwrExp4->pnCounts[i] ]++;
+        pReprs[ s_pManRwrExp4->pnCounts[i] ] = i;
+    }
+
+    printf( "Occurence = %6d.  Num classes = %4d.  \n", 0, 2288-nClasses );
+    for ( i = 1; i <= CountMax; i++ )
+        if ( pDistrib[i] )
+        {
+            printf( "Occurence = %6d.  Num classes = %4d.  Repr = ", i, pDistrib[i] );
+            Extra_PrintBinary( stdout, (unsigned*)&(pReprs[i]), 16 ); 
+            printf( "\n" );
+        }
+    ABC_FREE( pDistrib );
+    ABC_FREE( pReprs );
+    // write into a file all classes above limit (5)
+    CountWrite = 0;
+    pFile = fopen( "npnclass_stats4.txt", "w" );
+    for ( i = 0; i < s_pManRwrExp4->nFuncs; i++ )
+        if ( s_pManRwrExp4->pnCounts[i] > 0 )
+        {
+            Extra_PrintHex( pFile, (unsigned *)&i, 4 );
+            fprintf( pFile, " %10d\n", s_pManRwrExp4->pnCounts[i] );
+//            fprintf( pFile, "%d ", i );
+            CountWrite++;
+        }
+    fclose( pFile );
+    printf( "%d classes written into file \"%s\".\n", CountWrite, "npnclass_stats4.txt" );
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects stats about 4-var functions appearing in netlists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_Man5ExploreStart()
+{
+    Rwr_Man5_t * p;
+    p = ABC_ALLOC( Rwr_Man5_t, 1 );
+    memset( p, 0, sizeof(Rwr_Man5_t) );
+    p->tTableNN  = stmm_init_table( st__numcmp, st__numhash );
+    p->tTableNPN = stmm_init_table( st__numcmp, st__numhash );
+    s_pManRwrExp5 = p;
+
+//Extra_PrintHex( stdout, Extra_TruthCanonNPN( 0x0000FFFF, 5 ), 5 );
+//printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects stats about 4-var functions appearing in netlists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_Man5ExploreCount( unsigned uTruth )
+{
+    int * pCounter;
+    if ( !stmm_find_or_add( s_pManRwrExp5->tTableNN, (char *)(ABC_PTRUINT_T)uTruth, (char***)&pCounter ) )
+        *pCounter = 0;
+    (*pCounter)++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects stats about 4-var functions appearing in netlists.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_Man5ExplorePrint()
+{
+    FILE * pFile;
+    stmm_generator * gen;
+    int i, CountMax, nCuts, Counter;
+    int * pDistrib;
+    unsigned * pReprs;
+    unsigned uTruth, uTruthC;
+    abctime clk = Abc_Clock();
+    Vec_Int_t * vClassesNN, * vClassesNPN;
+
+    // find the max number of occurences
+    nCuts = 0;
+    CountMax = 0;
+    stmm_foreach_item( s_pManRwrExp5->tTableNN, gen, (char **)&uTruth, (char **)&Counter )
+    {
+        nCuts += Counter;
+        if ( CountMax < Counter )
+            CountMax = Counter;
+    }
+    printf( "Number of cuts considered       = %8d.\n", nCuts );
+    printf( "Classes occurring at least once = %8d.\n", stmm_count(s_pManRwrExp5->tTableNN) );
+    printf( "The largest number of occurence = %8d.\n", CountMax );
+
+    // print the distribution of classes
+    pDistrib = ABC_ALLOC( int, CountMax + 1 );
+    pReprs   = ABC_ALLOC( unsigned, CountMax + 1 );
+    memset( pDistrib, 0, sizeof(int)*(CountMax + 1) );
+    stmm_foreach_item( s_pManRwrExp5->tTableNN, gen, (char **)&uTruth, (char **)&Counter )
+    {
+        assert( Counter <= CountMax );
+        pDistrib[ Counter ]++;
+        pReprs[ Counter ] = uTruth;
+    }
+
+    for ( i = 1; i <= CountMax; i++ )
+        if ( pDistrib[i] )
+        {
+            printf( "Occurence = %6d.  Num classes = %4d.  Repr = ", i, pDistrib[i] );
+            Extra_PrintBinary( stdout, pReprs + i, 32 ); 
+            printf( "\n" );
+        }
+    ABC_FREE( pDistrib );
+    ABC_FREE( pReprs );
+
+
+    // put them into an array
+    vClassesNN = Vec_IntAlloc( stmm_count(s_pManRwrExp5->tTableNN) );
+    stmm_foreach_item( s_pManRwrExp5->tTableNN, gen, (char **)&uTruth, NULL )
+        Vec_IntPush( vClassesNN, (int)uTruth );
+    Vec_IntSortUnsigned( vClassesNN );
+
+    // write into a file all classes
+    pFile = fopen( "nnclass_stats5.txt", "w" );
+    Vec_IntForEachEntry( vClassesNN, uTruth, i )
+    {
+        if ( !stmm_lookup( s_pManRwrExp5->tTableNN, (char *)(ABC_PTRUINT_T)uTruth, (char **)&Counter ) )
+        {
+            assert( 0 );
+        }
+        Extra_PrintHex( pFile, &uTruth, 5 );
+        fprintf( pFile, " %10d\n", Counter );
+    }
+    fclose( pFile );
+    printf( "%d classes written into file \"%s\".\n", vClassesNN->nSize, "nnclass_stats5.txt" );
+
+
+clk = Abc_Clock();
+    // how many NPN classes exist?
+    Vec_IntForEachEntry( vClassesNN, uTruth, i )
+    {
+        int * pCounter;
+        uTruthC = Extra_TruthCanonNPN( uTruth, 5 );
+        if ( !stmm_find_or_add( s_pManRwrExp5->tTableNPN, (char *)(ABC_PTRUINT_T)uTruthC, (char***)&pCounter ) )
+            *pCounter = 0;
+        if ( !stmm_lookup( s_pManRwrExp5->tTableNN, (char *)(ABC_PTRUINT_T)uTruth, (char **)&Counter ) )
+        {
+            assert( 0 );
+        }
+        (*pCounter) += Counter;
+    }
+    printf( "The numbe of NPN classes = %d.\n", stmm_count(s_pManRwrExp5->tTableNPN) );
+ABC_PRT( "Computing NPN classes", Abc_Clock() - clk );
+
+    // put them into an array
+    vClassesNPN = Vec_IntAlloc( stmm_count(s_pManRwrExp5->tTableNPN) );
+    stmm_foreach_item( s_pManRwrExp5->tTableNPN, gen, (char **)&uTruth, NULL )
+        Vec_IntPush( vClassesNPN, (int)uTruth );
+    Vec_IntSortUnsigned( vClassesNPN );
+
+    // write into a file all classes
+    pFile = fopen( "npnclass_stats5.txt", "w" );
+    Vec_IntForEachEntry( vClassesNPN, uTruth, i )
+    {
+        if ( !stmm_lookup( s_pManRwrExp5->tTableNPN, (char *)(ABC_PTRUINT_T)uTruth, (char **)&Counter ) )
+        {
+            assert( 0 );
+        }
+        Extra_PrintHex( pFile, &uTruth, 5 );
+        fprintf( pFile, " %10d\n", Counter );
+    }
+    fclose( pFile );
+    printf( "%d classes written into file \"%s\".\n", vClassesNPN->nSize, "npnclass_stats5.txt" );
+
+
+    // can they be uniquely characterized?
+
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/rwr/rwrLib.c b/abc-build/src/opt/rwr/rwrLib.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/rwr/rwrLib.c
@@ -0,0 +1,367 @@
+/**CFile****************************************************************
+
+  FileName    [rwrLib.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rwrLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rwr.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Rwr_Node_t *        Rwr_ManTryNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume );
+static void                Rwr_MarkUsed_rec( Rwr_Man_t * p, Rwr_Node_t * pNode );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Precomputes the forest in the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_ManPrecompute( Rwr_Man_t * p )
+{
+    Rwr_Node_t * p0, * p1;
+    int i, k, Level, Volume;
+    int LevelOld = -1;
+    int nNodes;
+
+    Vec_PtrForEachEntryStart( Rwr_Node_t *, p->vForest, p0, i, 1 )
+    Vec_PtrForEachEntryStart( Rwr_Node_t *, p->vForest, p1, k, 1 )
+    {
+        if ( LevelOld < (int)p0->Level )
+        {
+            LevelOld = p0->Level;
+            printf( "Starting level %d  (at %d nodes).\n", LevelOld+1, i );
+            printf( "Considered = %5d M.   Found = %8d.   Classes = %6d.   Trying %7d.\n", 
+                p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i );
+        }
+
+        if ( k == i )
+            break;
+//        if ( p0->Level + p1->Level > 6 ) // hard
+//            break;
+
+        if ( p0->Level + p1->Level > 5 ) // easy 
+            break;
+
+//        if ( p0->Level + p1->Level > 6 || (p0->Level == 3 && p1->Level == 3) )
+//            break;
+
+        // compute the level and volume of the new nodes
+        Level  = 1 + Abc_MaxInt( p0->Level, p1->Level );
+        Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 );
+        // try four different AND nodes
+        Rwr_ManTryNode( p,         p0 ,         p1 , 0, Level, Volume );
+        Rwr_ManTryNode( p, Rwr_Not(p0),         p1 , 0, Level, Volume );
+        Rwr_ManTryNode( p,         p0 , Rwr_Not(p1), 0, Level, Volume );
+        Rwr_ManTryNode( p, Rwr_Not(p0), Rwr_Not(p1), 0, Level, Volume );
+        // try EXOR
+        Rwr_ManTryNode( p,         p0 ,         p1 , 1, Level, Volume + 1 );
+        // report the progress
+        if ( p->nConsidered % 50000000 == 0 )
+            printf( "Considered = %5d M.   Found = %8d.   Classes = %6d.   Trying %7d.\n", 
+                p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i );
+        // quit after some time
+        if ( p->vForest->nSize == RWR_LIMIT + 5 )
+        {
+            printf( "Considered = %5d M.   Found = %8d.   Classes = %6d.   Trying %7d.\n", 
+                p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i );
+            goto save;
+        }
+    }
+save :
+
+    // mark the relevant ones
+    Rwr_ManIncTravId( p );
+    k = 5;
+    nNodes = 0;
+    Vec_PtrForEachEntryStart( Rwr_Node_t *, p->vForest, p0, i, 5 )
+        if ( p0->uTruth == p->puCanons[p0->uTruth] )
+        {
+            Rwr_MarkUsed_rec( p, p0 );
+            nNodes++;
+        }
+
+    // compact the array by throwing away non-canonical
+    k = 5;
+    Vec_PtrForEachEntryStart( Rwr_Node_t *, p->vForest, p0, i, 5 )
+        if ( p0->fUsed )
+        {
+            p->vForest->pArray[k] = p0;
+            p0->Id = k++;
+        }
+    p->vForest->nSize = k;
+    printf( "Total canonical = %4d. Total used = %5d.\n", nNodes, p->vForest->nSize );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Rwr_Node_t * Rwr_ManTryNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume )
+{
+    Rwr_Node_t * pOld, * pNew, ** ppPlace;
+    unsigned uTruth;
+    // compute truth table, level, volume
+    p->nConsidered++;
+    if ( fExor )
+    {
+//        printf( "Considering EXOR of %d and %d.\n", p0->Id, p1->Id );
+        uTruth = (p0->uTruth ^ p1->uTruth);
+    }
+    else
+        uTruth = (Rwr_IsComplement(p0)? ~Rwr_Regular(p0)->uTruth : Rwr_Regular(p0)->uTruth) & 
+                 (Rwr_IsComplement(p1)? ~Rwr_Regular(p1)->uTruth : Rwr_Regular(p1)->uTruth) & 0xFFFF;
+    // skip non-practical classes
+    if ( Level > 2 && !p->pPractical[p->puCanons[uTruth]] )
+        return NULL;
+    // enumerate through the nodes with the same canonical form
+    ppPlace = p->pTable + uTruth;
+    for ( pOld = *ppPlace; pOld; ppPlace = &pOld->pNext, pOld = pOld->pNext )
+    {
+        if ( pOld->Level <  (unsigned)Level && pOld->Volume < (unsigned)Volume )
+            return NULL;
+        if ( pOld->Level == (unsigned)Level && pOld->Volume < (unsigned)Volume )
+            return NULL;
+//        if ( pOld->Level <  (unsigned)Level && pOld->Volume == (unsigned)Volume )
+//            return NULL;
+    }
+/*
+    // enumerate through the nodes with the opposite polarity
+    for ( pOld = p->pTable[~uTruth & 0xFFFF]; pOld; pOld = pOld->pNext )
+    {
+        if ( pOld->Level <  (unsigned)Level && pOld->Volume < (unsigned)Volume )
+            return NULL;
+        if ( pOld->Level == (unsigned)Level && pOld->Volume < (unsigned)Volume )
+            return NULL;
+//        if ( pOld->Level <  (unsigned)Level && pOld->Volume == (unsigned)Volume )
+//            return NULL;
+    }
+*/
+    // count the classes
+    if ( p->pTable[uTruth] == NULL && p->puCanons[uTruth] == uTruth )
+        p->nClasses++;
+    // create the new node
+    pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode );
+    pNew->Id     = p->vForest->nSize;
+    pNew->TravId = 0;
+    pNew->uTruth = uTruth;
+    pNew->Level  = Level;
+    pNew->Volume = Volume;
+    pNew->fUsed  = 0;
+    pNew->fExor  = fExor;
+    pNew->p0     = p0;
+    pNew->p1     = p1;
+    pNew->pNext  = NULL;
+    Vec_PtrPush( p->vForest, pNew );
+    *ppPlace     = pNew;
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Rwr_Node_t * Rwr_ManAddNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume )
+{
+    Rwr_Node_t * pNew;
+    unsigned uTruth;
+    // compute truth table, leve, volume
+    p->nConsidered++;
+    if ( fExor )
+        uTruth = (p0->uTruth ^ p1->uTruth);
+    else
+        uTruth = (Rwr_IsComplement(p0)? ~Rwr_Regular(p0)->uTruth : Rwr_Regular(p0)->uTruth) & 
+                 (Rwr_IsComplement(p1)? ~Rwr_Regular(p1)->uTruth : Rwr_Regular(p1)->uTruth) & 0xFFFF;
+    // create the new node
+    pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode );
+    pNew->Id     = p->vForest->nSize;
+    pNew->TravId = 0;
+    pNew->uTruth = uTruth;
+    pNew->Level  = Level;
+    pNew->Volume = Volume;
+    pNew->fUsed  = 0;
+    pNew->fExor  = fExor;
+    pNew->p0     = p0;
+    pNew->p1     = p1;
+    pNew->pNext  = NULL;
+    Vec_PtrPush( p->vForest, pNew );
+    // do not add if the node is not essential
+    if ( uTruth != p->puCanons[uTruth] )
+        return pNew;
+
+    // add to the list
+    p->nAdded++;
+    if ( p->pTable[uTruth] == NULL )
+        p->nClasses++;
+    Rwr_ListAddToTail( p->pTable + uTruth, pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Rwr_Node_t * Rwr_ManAddVar( Rwr_Man_t * p, unsigned uTruth, int fPrecompute )
+{
+    Rwr_Node_t * pNew;
+    pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode );
+    pNew->Id     = p->vForest->nSize;
+    pNew->TravId = 0;
+    pNew->uTruth = uTruth;
+    pNew->Level  = 0;
+    pNew->Volume = 0;
+    pNew->fUsed  = 1;
+    pNew->fExor  = 0;
+    pNew->p0     = NULL;
+    pNew->p1     = NULL;    
+    pNew->pNext  = NULL;
+    Vec_PtrPush( p->vForest, pNew );
+    if ( fPrecompute )
+        Rwr_ListAddToTail( p->pTable + uTruth, pNew );
+    return pNew;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_MarkUsed_rec( Rwr_Man_t * p, Rwr_Node_t * pNode )
+{
+    if ( pNode->fUsed || pNode->TravId == p->nTravIds )
+        return;
+    pNode->TravId = p->nTravIds;
+    pNode->fUsed = 1;
+    Rwr_MarkUsed_rec( p, Rwr_Regular(pNode->p0) );
+    Rwr_MarkUsed_rec( p, Rwr_Regular(pNode->p1) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_Trav_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, int * pVolume )
+{
+    if ( pNode->fUsed || pNode->TravId == p->nTravIds )
+        return;
+    pNode->TravId = p->nTravIds;
+    (*pVolume)++;
+    if ( pNode->fExor )
+        (*pVolume)++;
+    Rwr_Trav_rec( p, Rwr_Regular(pNode->p0), pVolume );
+    Rwr_Trav_rec( p, Rwr_Regular(pNode->p1), pVolume );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rwr_ManNodeVolume( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1 )
+{
+    int Volume = 0;
+    Rwr_ManIncTravId( p );
+    Rwr_Trav_rec( p, p0, &Volume );
+    Rwr_Trav_rec( p, p1, &Volume );
+    return Volume;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_ManIncTravId( Rwr_Man_t * p )
+{
+    Rwr_Node_t * pNode;
+    int i;
+    if ( p->nTravIds++ < 0x8FFFFFFF )
+        return;
+    Vec_PtrForEachEntry( Rwr_Node_t *, p->vForest, pNode, i )
+        pNode->TravId = 0;
+    p->nTravIds = 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/rwr/rwrMan.c b/abc-build/src/opt/rwr/rwrMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/rwr/rwrMan.c
@@ -0,0 +1,323 @@
+/**CFile****************************************************************
+
+  FileName    [rwrMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting package.]
+
+  Synopsis    [Rewriting manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rwrMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rwr.h"
+#include "base/main/main.h"
+#include "bool/dec/dec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts rewriting manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Rwr_Man_t * Rwr_ManStart( int  fPrecompute )
+{
+    Dec_Man_t * pManDec;
+    Rwr_Man_t * p;
+    abctime clk = Abc_Clock();
+clk = Abc_Clock();
+    p = ABC_ALLOC( Rwr_Man_t, 1 );
+    memset( p, 0, sizeof(Rwr_Man_t) );
+    p->nFuncs = (1<<16);
+    pManDec   = (Dec_Man_t *)Abc_FrameReadManDec();
+    p->puCanons = pManDec->puCanons; 
+    p->pPhases  = pManDec->pPhases; 
+    p->pPerms   = pManDec->pPerms; 
+    p->pMap     = pManDec->pMap; 
+    // initialize practical NPN classes
+    p->pPractical  = Rwr_ManGetPractical( p );
+    // create the table
+    p->pTable = ABC_ALLOC( Rwr_Node_t *, p->nFuncs );
+    memset( p->pTable, 0, sizeof(Rwr_Node_t *) * p->nFuncs );
+    // create the elementary nodes
+    p->pMmNode  = Extra_MmFixedStart( sizeof(Rwr_Node_t) );
+    p->vForest  = Vec_PtrAlloc( 100 );
+    Rwr_ManAddVar( p, 0x0000, fPrecompute ); // constant 0
+    Rwr_ManAddVar( p, 0xAAAA, fPrecompute ); // var A
+    Rwr_ManAddVar( p, 0xCCCC, fPrecompute ); // var B
+    Rwr_ManAddVar( p, 0xF0F0, fPrecompute ); // var C
+    Rwr_ManAddVar( p, 0xFF00, fPrecompute ); // var D
+    p->nClasses = 5;
+    // other stuff
+    p->nTravIds   = 1;
+    p->pPerms4    = Extra_Permutations( 4 );
+    p->vLevNums   = Vec_IntAlloc( 50 );
+    p->vFanins    = Vec_PtrAlloc( 50 );
+    p->vFaninsCur = Vec_PtrAlloc( 50 );
+    p->vNodesTemp = Vec_PtrAlloc( 50 );
+    if ( fPrecompute )
+    {   // precompute subgraphs
+        Rwr_ManPrecompute( p );
+//        Rwr_ManPrint( p );
+        Rwr_ManWriteToArray( p );
+    }
+    else
+    {   // load saved subgraphs
+        Rwr_ManLoadFromArray( p, 0 );
+//        Rwr_ManPrint( p );
+        Rwr_ManPreprocess( p );
+    }
+p->timeStart = Abc_Clock() - clk;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops rewriting manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_ManStop( Rwr_Man_t * p )
+{
+    if ( p->vClasses )
+    {
+        Rwr_Node_t * pNode;
+        int i, k;
+        Vec_VecForEachEntry( Rwr_Node_t *, p->vClasses, pNode, i, k )
+            Dec_GraphFree( (Dec_Graph_t *)pNode->pNext );
+    }
+    if ( p->vClasses )  Vec_VecFree( p->vClasses );
+    Vec_PtrFree( p->vNodesTemp );
+    Vec_PtrFree( p->vForest );
+    Vec_IntFree( p->vLevNums );
+    Vec_PtrFree( p->vFanins );
+    Vec_PtrFree( p->vFaninsCur );
+    Extra_MmFixedStop( p->pMmNode );
+    ABC_FREE( p->pMapInv );
+    ABC_FREE( p->pTable );
+    ABC_FREE( p->pPractical );
+    ABC_FREE( p->pPerms4 );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_ManPrintStats( Rwr_Man_t * p )
+{
+    int i, Counter = 0;
+    for ( i = 0; i < 222; i++ )
+        Counter += (p->nScores[i] > 0);
+
+    printf( "Rewriting statistics:\n" );
+    printf( "Total cuts tries  = %8d.\n", p->nCutsGood );
+    printf( "Bad cuts found    = %8d.\n", p->nCutsBad );
+    printf( "Total subgraphs   = %8d.\n", p->nSubgraphs );
+    printf( "Used NPN classes  = %8d.\n", Counter );
+    printf( "Nodes considered  = %8d.\n", p->nNodesConsidered );
+    printf( "Nodes rewritten   = %8d.\n", p->nNodesRewritten );
+    printf( "Gain              = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg );
+    ABC_PRT( "Start       ", p->timeStart );
+    ABC_PRT( "Cuts        ", p->timeCut );
+    ABC_PRT( "Resynthesis ", p->timeRes );
+    ABC_PRT( "    Mffc    ", p->timeMffc );
+    ABC_PRT( "    Eval    ", p->timeEval );
+    ABC_PRT( "Update      ", p->timeUpdate );
+    ABC_PRT( "TOTAL       ", p->timeTotal );
+
+/*
+    printf( "The scores are:\n" );
+    for ( i = 0; i < 222; i++ )
+        if ( p->nScores[i] > 0 )
+        {
+            extern void Ivy_TruthDsdComputePrint( unsigned uTruth );
+            printf( "%3d = %8d  canon = %5d  ", i, p->nScores[i], p->pMapInv[i] );
+            Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[i] | ((unsigned)p->pMapInv[i] << 16) );
+        }
+*/
+    printf( "\n" );
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_ManPrintStatsFile( Rwr_Man_t * p )
+{
+    FILE * pTable;
+    pTable = fopen( "stats.txt", "a+" );
+    fprintf( pTable, "%d ", p->nCutsGood );
+    fprintf( pTable, "%d ", p->nSubgraphs );
+    fprintf( pTable, "%d ", p->nNodesRewritten );
+    fprintf( pTable, "%d", p->nNodesGained );
+    fprintf( pTable, "\n" );
+    fclose( pTable );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Rwr_ManReadDecs( Rwr_Man_t * p )
+{
+    return p->pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Rwr_ManReadLeaves( Rwr_Man_t * p )
+{
+    return p->vFanins;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rwr_ManReadCompl( Rwr_Man_t * p )
+{
+    return p->fCompl;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_ManAddTimeCuts( Rwr_Man_t * p, abctime Time )
+{
+    p->timeCut += Time;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_ManAddTimeUpdate( Rwr_Man_t * p, abctime Time )
+{
+    p->timeUpdate += Time;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_ManAddTimeTotal( Rwr_Man_t * p, abctime Time )
+{
+    p->timeTotal += Time;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Precomputes AIG subgraphs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_Precompute()
+{
+    Rwr_Man_t * p;
+    p = Rwr_ManStart( 1 );
+    Rwr_ManStop( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/rwr/rwrPrint.c b/abc-build/src/opt/rwr/rwrPrint.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/rwr/rwrPrint.c
@@ -0,0 +1,271 @@
+/**CFile****************************************************************
+
+  FileName    [rwrCut.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting package.]
+
+  Synopsis    [Cut computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rwrCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rwr.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    [Adds one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_Trav2_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, int * pVolume )
+{
+    if ( pNode->fUsed || pNode->TravId == p->nTravIds )
+        return;
+    pNode->TravId = p->nTravIds;
+    (*pVolume)++;
+    Rwr_Trav2_rec( p, Rwr_Regular(pNode->p0), pVolume );
+    Rwr_Trav2_rec( p, Rwr_Regular(pNode->p1), pVolume );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the node to the end of the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_GetBushVolume( Rwr_Man_t * p, int Entry, int * pVolume, int * pnFuncs )
+{
+    Rwr_Node_t * pNode;
+    int Volume = 0;
+    int nFuncs = 0;
+    Rwr_ManIncTravId( p );
+    for ( pNode = p->pTable[Entry]; pNode; pNode = pNode->pNext )
+    {
+        if ( pNode->uTruth != p->puCanons[pNode->uTruth] )
+            continue;
+        nFuncs++;
+        Rwr_Trav2_rec( p, pNode, &Volume );
+    }
+    *pVolume = Volume;
+    *pnFuncs = nFuncs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the node to the end of the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rwr_GetBushSumOfVolumes( Rwr_Man_t * p, int Entry )
+{
+    Rwr_Node_t * pNode;
+    int Volume, VolumeTotal = 0;
+    for ( pNode = p->pTable[Entry]; pNode; pNode = pNode->pNext )
+    {
+        if ( pNode->uTruth != p->puCanons[pNode->uTruth] )
+            continue;
+        Volume = 0;
+        Rwr_ManIncTravId( p );
+        Rwr_Trav2_rec( p, pNode, &Volume );
+        VolumeTotal += Volume;
+    }
+    return VolumeTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints one rwr node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_NodePrint_rec( FILE * pFile, Rwr_Node_t * pNode )
+{
+    assert( !Rwr_IsComplement(pNode) );
+
+    if ( pNode->Id == 0 )
+    {
+        fprintf( pFile, "Const1" );
+        return;
+    }
+
+    if ( pNode->Id < 5 )
+    {
+        fprintf( pFile, "%c", 'a' + pNode->Id - 1 );
+        return;
+    }
+
+    if ( Rwr_IsComplement(pNode->p0) )
+    {
+        if ( Rwr_Regular(pNode->p0)->Id < 5 )
+        {
+            Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) );
+            fprintf( pFile, "\'" );
+        }
+        else
+        {
+            fprintf( pFile, "(" );
+            Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) );
+            fprintf( pFile, ")\'" );
+        }
+    }
+    else
+    {
+        if ( Rwr_Regular(pNode->p0)->Id < 5 )
+        {
+            Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) );
+        }
+        else
+        {
+            fprintf( pFile, "(" );
+            Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) );
+            fprintf( pFile, ")" );
+        }
+    }
+
+    if ( pNode->fExor )
+        fprintf( pFile, "+" );
+
+    if ( Rwr_IsComplement(pNode->p1) )
+    {
+        if ( Rwr_Regular(pNode->p1)->Id < 5 )
+        {
+            Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) );
+            fprintf( pFile, "\'" );
+        }
+        else
+        {
+            fprintf( pFile, "(" );
+            Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) );
+            fprintf( pFile, ")\'" );
+        }
+    }
+    else
+    {
+        if ( Rwr_Regular(pNode->p1)->Id < 5 )
+        {
+            Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) );
+        }
+        else
+        {
+            fprintf( pFile, "(" );
+            Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) );
+            fprintf( pFile, ")" );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints one rwr node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_NodePrint( FILE * pFile, Rwr_Man_t * p, Rwr_Node_t * pNode )
+{
+    unsigned uTruth;
+    fprintf( pFile, "%5d : ", pNode->Id );
+    uTruth = pNode->uTruth;
+    Extra_PrintHex( pFile, &uTruth, 4 );
+    fprintf( pFile, " tt=" );
+    Extra_PrintBinary( pFile, &uTruth, 16 );
+//    fprintf( pFile, " cn=", pNode->Id );
+//    uTruth = p->puCanons[pNode->uTruth];
+//    Extra_PrintBinary( pFile, &uTruth, 16 );
+    fprintf( pFile, " lev=%d", pNode->Level );
+    fprintf( pFile, " vol=%d", pNode->Volume );
+    fprintf( pFile, "  " );
+    Rwr_NodePrint_rec( pFile, pNode );
+    fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints one rwr node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_ManPrint( Rwr_Man_t * p )
+{
+    FILE * pFile;
+    Rwr_Node_t * pNode;
+    unsigned uTruth;
+    int Limit, Counter, Volume, nFuncs, i;
+    pFile = fopen( "graph_lib.txt", "w" );
+    Counter = 0;
+    Limit = (1 << 16);
+    for ( i = 0; i < Limit; i++ )
+    {
+        if ( p->pTable[i] == NULL )
+            continue;
+        if ( i != p->puCanons[i] )
+            continue;
+        fprintf( pFile, "\nClass %3d. Func %6d.  ", p->pMap[i], Counter++ );
+        Rwr_GetBushVolume( p, i, &Volume, &nFuncs );
+        fprintf( pFile, "Roots = %3d. Vol = %3d. Sum = %3d.  ", nFuncs, Volume, Rwr_GetBushSumOfVolumes(p, i) );
+        uTruth = i;
+        Extra_PrintBinary( pFile, &uTruth, 16 );
+        fprintf( pFile, "\n" );
+        for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext )
+            if ( pNode->uTruth == p->puCanons[pNode->uTruth] )
+                Rwr_NodePrint( pFile, p, pNode );
+    }
+    fclose( pFile );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/rwr/rwrTemp.c b/abc-build/src/opt/rwr/rwrTemp.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/rwr/rwrTemp.c
@@ -0,0 +1,126 @@
+/**CFile****************************************************************
+
+  FileName    [rwrCut.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting package.]
+
+  Synopsis    [Cut computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rwrCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rwr.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int pTruths[13719];
+static int pFreqs[13719];
+static int pPerm[13719];
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rwr_TempCompare( int * pNum1, int * pNum2 )
+{
+    int Freq1 = pFreqs[*pNum1];
+    int Freq2 = pFreqs[*pNum2];
+    if ( Freq1 < Freq2 )
+        return 1;
+    if ( Freq1 > Freq2 )
+        return -1;
+    return 0; 
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_Temp()
+{
+    char Buffer[32];
+    int nFuncs = 13719;
+    int nEntries = 100;
+    unsigned uTruth;
+    int i, k;
+    FILE * pFile;
+
+    pFile = fopen( "nnclass_stats5.txt", "r" );
+    for ( i = 0; i < 13719; i++ )
+    {
+        int RetValue = fscanf( pFile, "%s%d", Buffer, &pFreqs[i] );
+        Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 );
+        pTruths[i] = uTruth;
+    }
+    fclose( pFile );
+
+    for ( i = 0; i < 13719; i++ )
+        pPerm[i] = i;
+
+    qsort( (void *)pPerm, 13719, sizeof(int), 
+            (int (*)(const void *, const void *)) Rwr_TempCompare );
+
+
+    pFile = fopen( "5npn_100.blif", "w" );
+    fprintf( pFile, "# Most frequent NPN classes of 5 vars.\n" );
+    fprintf( pFile, ".model 5npn\n" );
+    fprintf( pFile, ".inputs a b c d e\n" );
+    fprintf( pFile, ".outputs" );
+    for ( i = 0; i < nEntries; i++ )
+        fprintf( pFile, " %02d", i );
+    fprintf( pFile, "\n" );
+
+    for ( i = 0; i < nEntries; i++ )
+    {
+        fprintf( pFile, ".names a b c d e %02d\n", i );
+        uTruth = pTruths[pPerm[i]];
+        for ( k = 0; k < 32; k++ )
+            if ( uTruth & (1 << k) )
+            {
+                Extra_PrintBinary( pFile, (unsigned *)&k, 5 );
+                fprintf( pFile, " 1\n" );
+            }
+    }
+    fprintf( pFile, ".end\n" );
+    fclose( pFile );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/rwr/rwrUtil.c b/abc-build/src/opt/rwr/rwrUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/rwr/rwrUtil.c
@@ -0,0 +1,661 @@
+/**CFile****************************************************************
+
+  FileName    [rwrUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting package.]
+
+  Synopsis    [Various utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rwrUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rwr.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// precomputed data
+// the following 135 practical NPN classes of 4-variable functions were computed
+// by considering all 4-input cuts appearing in IWLS, MCNC, and ISCAS benchmarks
+static unsigned short s_RwrPracticalClasses[] =
+{
+    0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, 0x001b,
+    0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, 0x007f, 0x00ff,
+    0x0116, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, 0x012c, 0x012d, 0x012f, 0x013c,
+    0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016f, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183,
+    0x0186, 0x0189, 0x018b, 0x018f, 0x0198, 0x0199, 0x019b, 0x01a8, 0x01a9, 0x01aa, 0x01ab,
+    0x01ac, 0x01ad, 0x01ae, 0x01af, 0x01bf, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, 0x01fe,
+    0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035f, 0x0368,
+    0x0369, 0x036c, 0x036e, 0x037d, 0x03c0, 0x03c1, 0x03c3, 0x03c7, 0x03cf, 0x03d4, 0x03d5,
+    0x03d7, 0x03d8, 0x03d9, 0x03dc, 0x03dd, 0x03de, 0x03fc, 0x0660, 0x0661, 0x0666, 0x0669,
+    0x066f, 0x0676, 0x067e, 0x0690, 0x0696, 0x0697, 0x069f, 0x06b1, 0x06b6, 0x06f0, 0x06f2,
+    0x06f6, 0x06f9, 0x0776, 0x0778, 0x07b0, 0x07b1, 0x07b4, 0x07bc, 0x07f0, 0x07f2, 0x07f8,
+    0x0ff0, 0x1683, 0x1696, 0x1698, 0x169e, 0x16e9, 0x178e, 0x17e8, 0x18e7, 0x19e6, 0x1be4,
+    0x1ee1, 0x3cc3, 0x6996, 0x0000
+};
+
+static unsigned short s_RwtAigSubgraphs[] =
+{
+    0x0008,0x0002, 0x000a,0x0002, 0x0008,0x0003, 0x000a,0x0003, 0x0009,0x0002,
+    0x000c,0x0002, 0x000e,0x0002, 0x000c,0x0003, 0x000e,0x0003, 0x000d,0x0002,
+    0x000c,0x0004, 0x000e,0x0004, 0x000c,0x0005, 0x000e,0x0005, 0x000d,0x0004,
+    0x0010,0x0002, 0x0012,0x0002, 0x0010,0x0003, 0x0012,0x0003, 0x0011,0x0002,
+    0x0010,0x0004, 0x0012,0x0004, 0x0010,0x0005, 0x0012,0x0005, 0x0011,0x0004,
+    0x0010,0x0006, 0x0012,0x0006, 0x0010,0x0007, 0x0012,0x0007, 0x0011,0x0006,
+    0x0016,0x0005, 0x0014,0x0006, 0x0016,0x0006, 0x0014,0x0007, 0x0016,0x0007,
+    0x0015,0x0006, 0x0014,0x0008, 0x0016,0x0008, 0x0014,0x0009, 0x0016,0x0009,
+    0x0015,0x0008, 0x0018,0x0006, 0x001a,0x0006, 0x0018,0x0007, 0x001a,0x0007,
+    0x0019,0x0006, 0x0018,0x0009, 0x001a,0x0009, 0x0019,0x0008, 0x001e,0x0005,
+    0x001c,0x0006, 0x001e,0x0006, 0x001c,0x0007, 0x001e,0x0007, 0x001d,0x0006,
+    0x001c,0x0008, 0x001e,0x0008, 0x001c,0x0009, 0x001e,0x0009, 0x001d,0x0008,
+    0x0020,0x0006, 0x0022,0x0006, 0x0020,0x0007, 0x0022,0x0007, 0x0021,0x0006,
+    0x0020,0x0008, 0x0022,0x0008, 0x0020,0x0009, 0x0022,0x0009, 0x0021,0x0008,
+    0x0024,0x0006, 0x0026,0x0006, 0x0024,0x0007, 0x0026,0x0007, 0x0025,0x0006,
+    0x0026,0x0008, 0x0024,0x0009, 0x0026,0x0009, 0x0025,0x0008, 0x0028,0x0004,
+    0x002a,0x0004, 0x0028,0x0005, 0x002a,0x0007, 0x0028,0x0008, 0x002a,0x0009,
+    0x0029,0x0008, 0x002a,0x000b, 0x0029,0x000a, 0x002a,0x000f, 0x0029,0x000e,
+    0x002a,0x0011, 0x002a,0x0013, 0x002c,0x0004, 0x002e,0x0004, 0x002c,0x0005,
+    0x002c,0x0009, 0x002e,0x0009, 0x002d,0x0008, 0x002d,0x000c, 0x002e,0x000f,
+    0x002e,0x0011, 0x002e,0x0012, 0x0030,0x0004, 0x0032,0x0007, 0x0032,0x0009,
+    0x0031,0x0008, 0x0032,0x000b, 0x0032,0x000d, 0x0032,0x000f, 0x0031,0x000e,
+    0x0032,0x0013, 0x0034,0x0004, 0x0036,0x0004, 0x0034,0x0005, 0x0036,0x0005,
+    0x0035,0x0004, 0x0036,0x0008, 0x0034,0x0009, 0x0036,0x0009, 0x0035,0x0008,
+    0x0036,0x000b, 0x0036,0x000d, 0x0036,0x0011, 0x0035,0x0010, 0x0036,0x0013,
+    0x0038,0x0004, 0x0039,0x0004, 0x0038,0x0009, 0x003a,0x0009, 0x0039,0x0008,
+    0x0038,0x000b, 0x003a,0x000b, 0x003a,0x000d, 0x003a,0x0011, 0x003a,0x0012,
+    0x0038,0x0013, 0x003a,0x0013, 0x003c,0x0002, 0x003e,0x0002, 0x003c,0x0003,
+    0x003e,0x0005, 0x003e,0x0007, 0x003c,0x0008, 0x003e,0x0008, 0x003c,0x0009,
+    0x003e,0x0009, 0x003d,0x0008, 0x003e,0x000d, 0x003e,0x0011, 0x003e,0x0013,
+    0x003e,0x0017, 0x003e,0x001b, 0x003e,0x001d, 0x0040,0x0002, 0x0042,0x0002,
+    0x0042,0x0005, 0x0041,0x0006, 0x0042,0x0008, 0x0041,0x0008, 0x0042,0x000d,
+    0x0042,0x0011, 0x0042,0x0015, 0x0042,0x0019, 0x0042,0x001b, 0x0042,0x001c,
+    0x0041,0x001c, 0x0044,0x0002, 0x0046,0x0003, 0x0045,0x0004, 0x0046,0x0007,
+    0x0045,0x0008, 0x0046,0x000b, 0x0046,0x000f, 0x0046,0x0013, 0x0045,0x0012,
+    0x0046,0x0017, 0x0046,0x001b, 0x0046,0x0021, 0x0048,0x0002, 0x004a,0x0002,
+    0x0048,0x0003, 0x004a,0x0003, 0x0049,0x0002, 0x0048,0x0008, 0x004a,0x0008,
+    0x0048,0x0009, 0x004a,0x0009, 0x0049,0x0008, 0x004a,0x000b, 0x004a,0x000f,
+    0x004a,0x0011, 0x004a,0x0012, 0x004a,0x0013, 0x004a,0x0015, 0x004a,0x0019,
+    0x004a,0x001b, 0x004a,0x001d, 0x004c,0x0002, 0x004c,0x0003, 0x004d,0x0002,
+    0x004c,0x0008, 0x004e,0x0008, 0x004c,0x0009, 0x004e,0x0009, 0x004d,0x0008,
+    0x004c,0x000b, 0x004e,0x000b, 0x004c,0x000f, 0x004e,0x000f, 0x004e,0x0011,
+    0x004c,0x0012, 0x004c,0x0013, 0x004e,0x0013, 0x004e,0x0015, 0x004c,0x0017,
+    0x004e,0x0019, 0x004c,0x001b, 0x004e,0x001b, 0x004c,0x001c, 0x004c,0x001d,
+    0x004e,0x001d, 0x0050,0x0004, 0x0052,0x0004, 0x0050,0x0006, 0x0052,0x0009,
+    0x0052,0x000d, 0x0052,0x000f, 0x0052,0x0013, 0x0052,0x0017, 0x0052,0x0019,
+    0x0052,0x001d, 0x0052,0x001f, 0x0052,0x0021, 0x0052,0x0023, 0x0052,0x0024,
+    0x0052,0x0025, 0x0051,0x0024, 0x0052,0x0027, 0x0054,0x0004, 0x0056,0x0004,
+    0x0054,0x0005, 0x0056,0x0006, 0x0054,0x0007, 0x0056,0x0011, 0x0056,0x001b,
+    0x0056,0x001e, 0x0054,0x001f, 0x0056,0x001f, 0x0056,0x0020, 0x0054,0x0021,
+    0x0055,0x0020, 0x0056,0x0024, 0x0054,0x0025, 0x0056,0x0025, 0x0055,0x0024,
+    0x0054,0x0027, 0x0056,0x0027, 0x0055,0x0026, 0x005a,0x0007, 0x005a,0x0009,
+    0x005a,0x000b, 0x005a,0x0015, 0x005a,0x001f, 0x0059,0x0020, 0x0058,0x0024,
+    0x005a,0x0024, 0x005a,0x0027, 0x0059,0x0026, 0x005c,0x0004, 0x005e,0x0004,
+    0x005c,0x0005, 0x005e,0x0006, 0x005c,0x0007, 0x005d,0x0006, 0x005e,0x000d,
+    0x005e,0x0013, 0x005e,0x0017, 0x005c,0x001f, 0x005d,0x001e, 0x005e,0x0020,
+    0x005e,0x0021, 0x005e,0x0022, 0x005e,0x0023, 0x005c,0x0024, 0x005e,0x0024,
+    0x005c,0x0025, 0x005e,0x0025, 0x005d,0x0024, 0x005e,0x0026, 0x005e,0x0027,
+    0x0062,0x0004, 0x0061,0x0004, 0x0062,0x0006, 0x0061,0x0006, 0x0060,0x000f,
+    0x0060,0x0013, 0x0062,0x0013, 0x0060,0x0019, 0x0062,0x001c, 0x0060,0x001d,
+    0x0062,0x001d, 0x0062,0x001f, 0x0060,0x0021, 0x0060,0x0023, 0x0062,0x0024,
+    0x0060,0x0027, 0x0061,0x0026, 0x0064,0x0002, 0x0066,0x0002, 0x0064,0x0006,
+    0x0066,0x0007, 0x0066,0x0009, 0x0066,0x000d, 0x0066,0x0013, 0x0066,0x0015,
+    0x0066,0x0017, 0x0066,0x0019, 0x0066,0x001a, 0x0065,0x001a, 0x0066,0x001f,
+    0x0066,0x0023, 0x0066,0x0027, 0x0066,0x002f, 0x0066,0x0030, 0x006a,0x0002,
+    0x0068,0x0003, 0x0068,0x0006, 0x006a,0x0006, 0x006a,0x0011, 0x0068,0x0016,
+    0x0068,0x0017, 0x006a,0x0017, 0x006a,0x001a, 0x006a,0x001b, 0x006a,0x0025,
+    0x006a,0x002d, 0x006e,0x0003, 0x006e,0x0007, 0x006e,0x0009, 0x006e,0x000b,
+    0x006e,0x0015, 0x006e,0x0016, 0x006e,0x0017, 0x006c,0x001a, 0x006e,0x001a,
+    0x006e,0x001f, 0x006e,0x002b, 0x006e,0x0035, 0x0070,0x0002, 0x0070,0x0003,
+    0x0072,0x0006, 0x0070,0x0007, 0x0071,0x0006, 0x0072,0x000b, 0x0072,0x000f,
+    0x0072,0x0013, 0x0070,0x0015, 0x0071,0x0014, 0x0072,0x0017, 0x0072,0x0018,
+    0x0070,0x0019, 0x0072,0x0019, 0x0070,0x001a, 0x0070,0x001b, 0x0072,0x001b,
+    0x0071,0x001a, 0x0072,0x0021, 0x0072,0x0029, 0x0076,0x0002, 0x0076,0x0003,
+    0x0075,0x0002, 0x0076,0x0006, 0x0074,0x0007, 0x0076,0x0007, 0x0075,0x0006,
+    0x0076,0x000d, 0x0076,0x0011, 0x0076,0x0013, 0x0075,0x0014, 0x0076,0x0019,
+    0x0076,0x001a, 0x0076,0x001b, 0x0075,0x001c, 0x0074,0x0023, 0x0075,0x0022,
+    0x0074,0x0026, 0x0076,0x0026, 0x0074,0x0027, 0x0076,0x002b, 0x0076,0x002f,
+    0x0078,0x0002, 0x0078,0x0004, 0x007a,0x0004, 0x007a,0x0005, 0x0079,0x0004,
+    0x007a,0x0009, 0x007a,0x000a, 0x007a,0x000b, 0x007a,0x000d, 0x007a,0x000f,
+    0x007a,0x0010, 0x007a,0x0011, 0x007a,0x0012, 0x007a,0x0013, 0x007a,0x0017,
+    0x007a,0x001b, 0x007a,0x0021, 0x007a,0x0027, 0x007a,0x002b, 0x007a,0x002f,
+    0x007a,0x0030, 0x0079,0x0034, 0x007a,0x0039, 0x007a,0x003a, 0x007e,0x0002,
+    0x007c,0x0004, 0x007e,0x0004, 0x007e,0x000c, 0x007c,0x000d, 0x007e,0x0011,
+    0x007e,0x0013, 0x007e,0x001b, 0x007e,0x0025, 0x007e,0x002d, 0x007e,0x0037,
+    0x0082,0x0003, 0x0082,0x0005, 0x0082,0x0009, 0x0082,0x000b, 0x0080,0x0010,
+    0x0082,0x0010, 0x0082,0x0012, 0x0082,0x0015, 0x0082,0x001f, 0x0082,0x002b,
+    0x0082,0x0035, 0x0082,0x0039, 0x0082,0x003f, 0x0084,0x0002, 0x0086,0x0002,
+    0x0084,0x0003, 0x0086,0x0003, 0x0085,0x0002, 0x0086,0x0004, 0x0084,0x0005,
+    0x0085,0x0004, 0x0086,0x000a, 0x0084,0x000b, 0x0085,0x000a, 0x0086,0x000d,
+    0x0086,0x000e, 0x0086,0x000f, 0x0084,0x0010, 0x0084,0x0011, 0x0086,0x0011,
+    0x0085,0x0010, 0x0084,0x0012, 0x0084,0x0013, 0x0086,0x0013, 0x0085,0x0012,
+    0x0086,0x0019, 0x0086,0x0023, 0x0086,0x0029, 0x0086,0x0033, 0x0086,0x0039,
+    0x008a,0x0003, 0x0089,0x0002, 0x0088,0x0004, 0x008a,0x0004, 0x0088,0x0005,
+    0x0089,0x0004, 0x008a,0x000b, 0x008a,0x0010, 0x0088,0x0011, 0x008a,0x0011,
+    0x0089,0x0010, 0x0088,0x0012, 0x008a,0x0012, 0x0089,0x0012, 0x008a,0x0017,
+    0x008a,0x001b, 0x0089,0x0020, 0x008a,0x0025, 0x0088,0x0027, 0x008a,0x002b,
+    0x008a,0x002f, 0x008a,0x0039, 0x0088,0x003a, 0x008d,0x0044, 0x0092,0x0009,
+    0x0092,0x0025, 0x0092,0x0029, 0x0092,0x002d, 0x0092,0x0033, 0x0092,0x0037,
+    0x0092,0x003d, 0x0092,0x0041, 0x0095,0x0002, 0x0095,0x0004, 0x0095,0x0010,
+    0x0095,0x0012, 0x0096,0x0021, 0x0096,0x0029, 0x0095,0x002e, 0x0096,0x0030,
+    0x0096,0x0033, 0x0096,0x003a, 0x0096,0x0043, 0x009a,0x0008, 0x009a,0x0009,
+    0x0099,0x0008, 0x009a,0x0011, 0x009a,0x0023, 0x009a,0x0033, 0x009a,0x003d,
+    0x009a,0x0044, 0x009a,0x0045, 0x0099,0x0044, 0x009d,0x0002, 0x009e,0x0008,
+    0x009c,0x0009, 0x009e,0x0009, 0x009d,0x0008, 0x009e,0x0011, 0x009d,0x0010,
+    0x009e,0x001f, 0x009e,0x003f, 0x00a0,0x0009, 0x00a0,0x0011, 0x00a2,0x0030,
+    0x00a2,0x0033, 0x00a6,0x0006, 0x00a6,0x0007, 0x00a6,0x0011, 0x00a6,0x0044,
+    0x00a6,0x004b, 0x00aa,0x0007, 0x00aa,0x0015, 0x00ae,0x0006, 0x00ae,0x0011,
+    0x00ae,0x001b, 0x00ae,0x0025, 0x00ae,0x003d, 0x00ae,0x0041, 0x00ae,0x0043,
+    0x00ae,0x0045, 0x00b2,0x0006, 0x00b0,0x0007, 0x00b1,0x0006, 0x00b2,0x0017,
+    0x00b1,0x0016, 0x00b0,0x0019, 0x00b2,0x0021, 0x00b2,0x003d, 0x00b5,0x004a,
+    0x00ba,0x0009, 0x00ba,0x000f, 0x00bc,0x0009, 0x00be,0x0009, 0x00be,0x000f,
+    0x00bd,0x000e, 0x00be,0x0017, 0x00c2,0x0009, 0x00c2,0x0019, 0x00c2,0x001f,
+    0x00c2,0x0033, 0x00c6,0x0009, 0x00c5,0x000e, 0x00c6,0x0015, 0x00c6,0x0023,
+    0x00c4,0x002d, 0x00c6,0x002f, 0x00c5,0x002e, 0x00c6,0x0045, 0x00ce,0x0007,
+    0x00ce,0x0021, 0x00ce,0x0023, 0x00ce,0x0025, 0x00ce,0x0027, 0x00ce,0x0033,
+    0x00ce,0x003d, 0x00d2,0x0006, 0x00d0,0x0015, 0x00d0,0x001b, 0x00d2,0x001b,
+    0x00d1,0x001a, 0x00d0,0x001f, 0x00d2,0x0025, 0x00d1,0x0024, 0x00d2,0x0037,
+    0x00d2,0x0041, 0x00d2,0x0045, 0x00d9,0x0044, 0x00e1,0x0004, 0x00e2,0x000d,
+    0x00e2,0x0021, 0x00e0,0x003a, 0x00e6,0x003d, 0x00e6,0x0061, 0x00e6,0x0067,
+    0x00e9,0x0004, 0x00ea,0x0008, 0x00ea,0x0009, 0x00ea,0x0039, 0x00e9,0x0038,
+    0x00ea,0x003f, 0x00ec,0x000d, 0x00ee,0x000d, 0x00ee,0x0037, 0x00f2,0x003d,
+    0x00f2,0x0062, 0x00f5,0x0002, 0x00fa,0x0017, 0x00fa,0x003d, 0x00fe,0x0006,
+    0x00fd,0x0006, 0x00fc,0x0015, 0x00fe,0x001b, 0x00fc,0x0025, 0x00fe,0x0025,
+    0x00fd,0x0024, 0x00fe,0x0041, 0x00fe,0x004d, 0x00fd,0x004e, 0x0101,0x0014,
+    0x0106,0x004d, 0x010a,0x0009, 0x010a,0x000b, 0x0109,0x000a, 0x010a,0x004f,
+    0x010a,0x0058, 0x010e,0x0008, 0x010c,0x0009, 0x010e,0x0009, 0x010d,0x0008,
+    0x010e,0x000b, 0x010e,0x002b, 0x010d,0x002a, 0x010e,0x0035, 0x010e,0x003d,
+    0x010e,0x003f, 0x010e,0x0049, 0x010e,0x0057, 0x010d,0x0056, 0x010d,0x0058,
+    0x0111,0x0004, 0x0111,0x0006, 0x0110,0x0009, 0x0112,0x0009, 0x0111,0x0008,
+    0x0112,0x002f, 0x0110,0x0035, 0x0110,0x0037, 0x0112,0x0039, 0x0112,0x003d,
+    0x0112,0x003f, 0x0112,0x0045, 0x0111,0x0044, 0x0112,0x004b, 0x0112,0x0059,
+    0x0112,0x0069, 0x0112,0x007f, 0x0116,0x0009, 0x0115,0x0008, 0x0114,0x000b,
+    0x0116,0x000b, 0x0116,0x0058, 0x011a,0x0015, 0x011a,0x001f, 0x011a,0x002b,
+    0x011a,0x003f, 0x011a,0x0049, 0x011a,0x0085, 0x011e,0x0007, 0x011e,0x0019,
+    0x011e,0x001b, 0x011e,0x0023, 0x011e,0x0027, 0x011e,0x002f, 0x011e,0x0043,
+    0x011e,0x004b, 0x011e,0x004e, 0x011e,0x004f, 0x011e,0x005f, 0x011e,0x0061,
+    0x011e,0x0065, 0x011e,0x0083, 0x0122,0x0006, 0x0120,0x0007, 0x0122,0x0007,
+    0x0121,0x0006, 0x0122,0x0049, 0x0121,0x004e, 0x0122,0x008f, 0x0125,0x0004,
+    0x0124,0x0007, 0x0125,0x0006, 0x0124,0x001b, 0x0126,0x001b, 0x0126,0x0045,
+    0x0126,0x0087, 0x0128,0x0007, 0x0129,0x0006, 0x012a,0x0019, 0x012a,0x003d,
+    0x012a,0x0051, 0x012a,0x0065, 0x012a,0x0083, 0x012d,0x005a, 0x0132,0x0009,
+    0x0132,0x008f, 0x0134,0x0009, 0x0135,0x003e, 0x013a,0x003d, 0x013a,0x0044,
+    0x0139,0x0044, 0x013e,0x0009, 0x013d,0x0008, 0x013c,0x003d, 0x013c,0x0044,
+    0x013c,0x0053, 0x013e,0x008f, 0x013e,0x0095, 0x0142,0x0044, 0x0142,0x0097,
+    0x0142,0x009e, 0x0144,0x0007, 0x0148,0x0015, 0x0148,0x001c, 0x0148,0x001f,
+    0x0148,0x0026, 0x0149,0x0086, 0x014d,0x0006, 0x014e,0x0044, 0x014d,0x0048,
+    0x014e,0x009e, 0x0152,0x0009, 0x0151,0x00a6, 0x0155,0x0030, 0x015d,0x003a,
+    0x0162,0x009e, 0x0164,0x000f, 0x0164,0x0013, 0x0169,0x000e, 0x0174,0x0009,
+    0x0179,0x0008, 0x0180,0x0009, 0x0181,0x0044, 0x0186,0x0044, 0x0185,0x0044,
+    0x018a,0x0068, 0x0195,0x004e, 0x01a6,0x0009, 0x01a5,0x0008, 0x01b1,0x003a,
+    0x01c4,0x0029, 0x01c4,0x0030, 0x01ca,0x008f, 0x01ca,0x0095, 0x01cc,0x0029,
+    0x01cc,0x0033, 0x01ce,0x003d, 0x01d6,0x00b2, 0x01d8,0x0009, 0x01d9,0x002a,
+    0x01d9,0x0056, 0x01d9,0x00a4, 0x01dd,0x003a, 0x01e2,0x00b2, 0x01e6,0x0013,
+    0x01e6,0x009f, 0x01e6,0x00ba, 0x01e6,0x00c0, 0x01e6,0x00d3, 0x01e6,0x00d5,
+    0x01e6,0x00e5, 0x01e8,0x0005, 0x01f2,0x0013, 0x01f2,0x0095, 0x01f2,0x009f,
+    0x01f2,0x00ba, 0x01f2,0x00c0, 0x01f2,0x00d3, 0x0202,0x008f, 0x0202,0x0095,
+    0x0202,0x00f3, 0x0202,0x00f9, 0x020a,0x0044, 0x0209,0x00b4, 0x020e,0x0009,
+    0x020d,0x0008, 0x020c,0x003d, 0x020c,0x0044, 0x020c,0x0053, 0x020e,0x008f,
+    0x020e,0x0095, 0x020c,0x00b1, 0x020e,0x00f3, 0x020e,0x00f9, 0x0210,0x0013,
+    0x0211,0x0024, 0x0210,0x0026, 0x0219,0x0004, 0x021e,0x008f, 0x021e,0x0095,
+    0x0221,0x003a, 0x0230,0x0009, 0x0236,0x0009, 0x0234,0x0029, 0x0234,0x0030,
+    0x0234,0x0033, 0x0234,0x003a, 0x0234,0x003d, 0x0234,0x0044, 0x0235,0x00a6,
+    0x023a,0x0009, 0x023d,0x003a, 0x0245,0x0044, 0x0249,0x003a, 0x024e,0x009e,
+    0x024e,0x0106, 0x0251,0x0026, 0x0258,0x0013, 0x0259,0x0024, 0x0258,0x0061,
+    0x0259,0x0086, 0x0258,0x00c7, 0x0258,0x00df, 0x0259,0x00ec, 0x0258,0x00fc,
+    0x025d,0x0024, 0x025d,0x00de, 0x0260,0x00f6, 0x0268,0x0009, 0x0269,0x0044,
+    0x0268,0x00f3, 0x0268,0x00f9, 0x026d,0x003a, 0x0270,0x0068, 0x0275,0x003a,
+    0x027a,0x0044, 0x0279,0x0044, 0x027e,0x007e, 0x0281,0x0044, 0x0285,0x0008,
+    0x028d,0x0006, 0x028d,0x00d2, 0x0295,0x00cc, 0x0296,0x00f6, 0x0295,0x00f8,
+    0x0299,0x0030, 0x029e,0x007e, 0x029d,0x0080, 0x02a6,0x008f, 0x02a6,0x0095,
+    0x02aa,0x0029, 0x02aa,0x0030, 0x02b5,0x0008, 0x02b9,0x003a, 0x02bd,0x0004,
+    0x02bd,0x00fc, 0x02c2,0x00b2, 0x02c1,0x00b4, 0x02c4,0x0029, 0x02c8,0x0029,
+    0x02c8,0x0033, 0x02ca,0x003d, 0x02ce,0x0029, 0x02ce,0x0030, 0x02d2,0x0068,
+    0x02d1,0x006a, 0x02d5,0x006a, 0x02d9,0x0008, 0x02de,0x012c, 0x02e2,0x012c,
+    0x02e4,0x0009, 0x02e5,0x002a, 0x02e5,0x0056, 0x02e5,0x012c, 0x02ea,0x0029,
+    0x02ea,0x0030, 0x02e9,0x0030, 0x02ec,0x0029, 0x02ec,0x0030, 0x02ee,0x012c,
+    0x02f1,0x0068, 0x02f1,0x00b2, 0x02f1,0x0108, 0x02f1,0x012c, 0x02f6,0x0013,
+    0x02f6,0x0015, 0x02f6,0x001f, 0x02f6,0x0030, 0x02f6,0x0065, 0x02f6,0x0067,
+    0x02f6,0x009f, 0x02f6,0x00b6, 0x02f6,0x00b9, 0x02f6,0x00c0, 0x02f6,0x00cf,
+    0x02f6,0x0107, 0x02f6,0x010b, 0x02f6,0x010f, 0x02f6,0x0115, 0x02f6,0x012d,
+    0x02f6,0x0134, 0x02f6,0x0153, 0x02f6,0x0171, 0x02f6,0x0176, 0x02f8,0x0003,
+    0x02fa,0x017b, 0x02fc,0x00ba, 0x02fc,0x00d3, 0x0302,0x0013, 0x0302,0x001f,
+    0x0302,0x0030, 0x0302,0x005d, 0x0302,0x0065, 0x0302,0x0067, 0x0302,0x0099,
+    0x0302,0x009f, 0x0302,0x00ad, 0x0302,0x00b9, 0x0302,0x00c0, 0x0302,0x00cf,
+    0x0301,0x00d2, 0x0301,0x00fe, 0x0302,0x0107, 0x0302,0x010b, 0x0302,0x010f,
+    0x0302,0x0117, 0x0302,0x0134, 0x0302,0x0153, 0x0302,0x0157, 0x0302,0x0176,
+    0x0306,0x0029, 0x0308,0x00b2, 0x0309,0x00dc, 0x030d,0x00f8, 0x0312,0x00f3,
+    0x0318,0x007e, 0x031d,0x0080, 0x0321,0x0008, 0x0321,0x0094, 0x0326,0x017b,
+    0x0326,0x0181, 0x0329,0x012e, 0x032a,0x017b, 0x032a,0x0181, 0x032e,0x008f,
+    0x032e,0x0095, 0x032e,0x00f3, 0x032e,0x00f9, 0x0332,0x0009, 0x0331,0x0008,
+    0x0330,0x003d, 0x0330,0x0044, 0x0330,0x0053, 0x0332,0x008f, 0x0332,0x0095,
+    0x0330,0x00b1, 0x0332,0x00f3, 0x0332,0x00f9, 0x0330,0x0127, 0x0332,0x017b,
+    0x0332,0x0181, 0x033c,0x0013, 0x033c,0x001c, 0x033d,0x0086, 0x033d,0x00ec,
+    0x033d,0x0172, 0x033e,0x019d, 0x0345,0x0002, 0x0344,0x008f, 0x0344,0x00f3,
+    0x034d,0x0030, 0x0352,0x0033, 0x0354,0x0029, 0x0354,0x0030, 0x035a,0x0009,
+    0x035a,0x017b, 0x035a,0x019b, 0x035a,0x01a2, 0x035e,0x0181, 0x0360,0x0009,
+    0x0366,0x0009, 0x0364,0x0029, 0x0364,0x0030, 0x0364,0x0033, 0x0364,0x003a,
+    0x0364,0x003d, 0x0364,0x0044, 0x0369,0x0030, 0x0370,0x0029, 0x0370,0x0030,
+    0x0376,0x0033, 0x037a,0x0009, 0x037a,0x019b, 0x037a,0x01a2, 0x037c,0x0009,
+    0x0382,0x0181, 0x0386,0x0009, 0x0384,0x0029, 0x0384,0x0030, 0x0384,0x0033,
+    0x0384,0x003a, 0x0384,0x003d, 0x0384,0x0044, 0x038a,0x0044, 0x038a,0x009e,
+    0x038a,0x0106, 0x038a,0x0198, 0x038d,0x010e, 0x038d,0x0152, 0x038d,0x0158,
+    0x0392,0x009e, 0x0392,0x0106, 0x0392,0x0198, 0x0395,0x0086, 0x0395,0x009a,
+    0x0395,0x00ec, 0x0395,0x0172, 0x0398,0x014e, 0x0398,0x0175, 0x0398,0x018d,
+    0x039c,0x0023, 0x039c,0x0027, 0x039c,0x00ef, 0x039c,0x0139, 0x039c,0x0168,
+    0x03a0,0x0019, 0x03a0,0x001d, 0x03a0,0x0023, 0x03a0,0x0027, 0x03a1,0x004e,
+    0x03a4,0x0162, 0x03a4,0x0183, 0x03a8,0x0013, 0x03a8,0x0027, 0x03a8,0x0133,
+    0x03a8,0x0148, 0x03a8,0x0181, 0x03ac,0x0013, 0x03ac,0x0027, 0x03b0,0x017b,
+    0x03b0,0x0181, 0x03b4,0x004b, 0x03b4,0x00e0, 0x03b4,0x00fb, 0x03b8,0x000f,
+    0x03b8,0x0013, 0x03b8,0x00ab, 0x03b8,0x00bf, 0x03b8,0x00d0, 0x03bd,0x00da,
+    0x03bd,0x012c, 0x03c8,0x000f, 0x03c8,0x0013, 0x03c8,0x0019, 0x03c8,0x001d,
+    0x03cd,0x0086, 0x03cd,0x00ec, 0x03cd,0x0172, 0x03d2,0x00e0, 0x03d2,0x00ef,
+    0x03d2,0x0112, 0x03d2,0x0139, 0x03d2,0x0168, 0x03d6,0x017b, 0x03d6,0x0181,
+    0x03da,0x0133, 0x03da,0x0148, 0x03e2,0x0023, 0x03e2,0x0027, 0x03e6,0x0027,
+    0x03e6,0x0181, 0x03ee,0x017b, 0x03ee,0x0181, 0x03fe,0x003d, 0x0401,0x012a,
+    0x0401,0x019e, 0x0405,0x01a0, 0x040a,0x000d, 0x040a,0x011f, 0x040a,0x016f,
+    0x040d,0x012a, 0x0412,0x017b, 0x041a,0x0033, 0x041a,0x003d, 0x041a,0x0181,
+    0x0421,0x0086, 0x0421,0x009a, 0x0421,0x00ec, 0x0421,0x0172, 0x042e,0x0205,
+    0x043a,0x0205, 0x043e,0x017b, 0x0442,0x01f5, 0x044c,0x0007, 0x0452,0x0033,
+    0x0452,0x01ce, 0x0452,0x01d0, 0x0452,0x01f1, 0x0452,0x01fb, 0x0452,0x0225,
+    0x0454,0x0005, 0x045a,0x0033, 0x045a,0x0181, 0x045a,0x01ce, 0x045a,0x01d0,
+    0x045a,0x01f1, 0x0469,0x01de, 0x046e,0x0181, 0x047a,0x01ce, 0x047a,0x01f1,
+    0x0485,0x012c, 0x0489,0x012c, 0x0490,0x01d8, 0x0496,0x0033, 0x0496,0x003d,
+    0x0498,0x008f, 0x0498,0x00f3, 0x049e,0x0044, 0x049e,0x0221, 0x04a1,0x0006,
+    0x04a2,0x0044, 0x04a6,0x0221, 0x04a9,0x0004, 0x04ac,0x0027, 0x04b1,0x009a,
+    0x04b6,0x0097, 0x04b8,0x0027, 0x04c6,0x0219, 0x04ca,0x017b, 0x04cc,0x004b,
+    0x04d0,0x00ab, 0x04d6,0x017b, 0x04d8,0x000f, 0x04d8,0x0019, 0x04d8,0x0033,
+    0x04d8,0x003d, 0x04de,0x003d, 0x04de,0x0103, 0x04de,0x018b, 0x04de,0x0231,
+    0x04e2,0x0044, 0x04e2,0x009e, 0x04e2,0x0106, 0x04e2,0x0198, 0x04e5,0x01a4,
+    0x04e5,0x01b6, 0x04ea,0x009e, 0x04ea,0x0106, 0x04ea,0x0198, 0x04ed,0x002e,
+    0x04ed,0x0038, 0x04ed,0x00a2, 0x04f1,0x0086, 0x04f1,0x009a, 0x04f1,0x00ec,
+    0x04f1,0x0172, 0x04f9,0x004e, 0x04f8,0x0229, 0x04f8,0x022d, 0x0500,0x023e,
+    0x0504,0x0217, 0x0510,0x00f3, 0x0514,0x0043, 0x0514,0x004d, 0x0514,0x00c3,
+    0x0514,0x013d, 0x0514,0x0215, 0x0514,0x0232, 0x0515,0x0260, 0x0519,0x002a,
+    0x0518,0x0030, 0x0518,0x0067, 0x0518,0x00c9, 0x0518,0x01eb, 0x0518,0x01ef,
+    0x051c,0x0139, 0x051c,0x0168, 0x0520,0x0027, 0x0526,0x014e, 0x0526,0x0175,
+    0x0526,0x018d, 0x052d,0x0200, 0x0532,0x0021, 0x0532,0x00bf, 0x0532,0x00d0,
+    0x0532,0x0239, 0x0532,0x0266, 0x053d,0x0024, 0x053d,0x00da, 0x054a,0x000f,
+    0x054a,0x00ab, 0x054a,0x023a, 0x054e,0x0043, 0x054e,0x004d, 0x054e,0x00c3,
+    0x054e,0x013d, 0x054e,0x0215, 0x054e,0x0232, 0x054e,0x029d, 0x0552,0x014e,
+    0x0552,0x018d, 0x0556,0x00f3, 0x0556,0x01e4, 0x055a,0x0299, 0x055d,0x0086,
+    0x055d,0x009a, 0x055d,0x00ec, 0x055d,0x0172, 0x0566,0x01dc, 0x0566,0x02a5,
+    0x056d,0x020a, 0x057a,0x003d, 0x057a,0x01d4, 0x057a,0x01f3, 0x0579,0x025e,
+    0x057e,0x0139, 0x057e,0x0168, 0x0581,0x0006, 0x0586,0x017b, 0x0586,0x0181,
+    0x0586,0x028c, 0x0588,0x0007, 0x058e,0x0033, 0x058e,0x008f, 0x058e,0x01d0,
+    0x058e,0x027c, 0x0590,0x0003, 0x0596,0x0033, 0x0596,0x008f, 0x0596,0x0095,
+    0x0596,0x01d0, 0x0596,0x027c, 0x05a2,0x026f, 0x05a5,0x0284, 0x05aa,0x017b,
+    0x05ac,0x0205, 0x05b2,0x008f, 0x05b6,0x017b, 0x05b8,0x01da, 0x05c1,0x0276,
+    0x05c6,0x0248, 0x05c8,0x0247, 0x05c8,0x027e, 0x05cc,0x003d, 0x05cc,0x01d4,
+    0x05cc,0x01f3, 0x05d0,0x014e, 0x05d0,0x018d, 0x05da,0x00f9, 0x05dd,0x0006,
+    0x05de,0x0044, 0x05e5,0x002e, 0x05e6,0x02f1, 0x05ea,0x01d4, 0x05ea,0x01f3,
+    0x05ea,0x022d, 0x05ed,0x0002, 0x05f6,0x0027, 0x05fa,0x0097, 0x05fc,0x003d,
+    0x0602,0x003d, 0x0606,0x00f3, 0x060a,0x0027, 0x060e,0x003d, 0x060e,0x0103,
+    0x060e,0x018b, 0x060e,0x0231, 0x060e,0x02d1, 0x0611,0x01fc, 0x0611,0x0234,
+    0x061a,0x0287, 0x061d,0x0214, 0x0621,0x01d4, 0x062a,0x0027, 0x062a,0x022d,
+    0x062e,0x009e, 0x062e,0x0106, 0x062e,0x0198, 0x0632,0x009e, 0x0632,0x0106,
+    0x0632,0x0198, 0x0639,0x0042, 0x0639,0x00b2, 0x0639,0x0108, 0x063d,0x01f8,
+    0x0641,0x0086, 0x0641,0x009a, 0x0641,0x00ec, 0x0641,0x0172, 0x0645,0x0044,
+    0x0649,0x0042, 0x0648,0x0087, 0x0648,0x00ed, 0x0648,0x0173, 0x0649,0x01a0,
+    0x0648,0x0241, 0x0648,0x026f, 0x0648,0x02df, 0x0648,0x0307, 0x064c,0x023a,
+    0x064c,0x02b3, 0x0651,0x0062, 0x0650,0x0217, 0x0651,0x02ac, 0x0650,0x02d6,
+    0x0655,0x0042, 0x065d,0x0042, 0x0664,0x02b1, 0x0664,0x02ce, 0x0669,0x0238,
+    0x066d,0x002a, 0x066c,0x0039, 0x066d,0x01f6, 0x066c,0x0213, 0x066c,0x022e,
+    0x066d,0x02a2, 0x066c,0x02e1, 0x0671,0x002a, 0x0670,0x0030, 0x0670,0x0067,
+    0x0670,0x00c9, 0x0670,0x01eb, 0x0670,0x01ef, 0x0670,0x02c3, 0x0675,0x0020,
+    0x0678,0x0133, 0x0678,0x0148, 0x067c,0x0027, 0x0681,0x023a, 0x0684,0x0021,
+    0x0684,0x00bf, 0x0684,0x00d0, 0x0689,0x01fc, 0x068e,0x0162, 0x068e,0x0183,
+    0x0691,0x0200, 0x0696,0x0023, 0x0696,0x00e0, 0x0696,0x00fb, 0x0696,0x0268,
+    0x069a,0x0282, 0x069d,0x007e, 0x06a2,0x004b, 0x06a2,0x023e, 0x06a2,0x02dc,
+    0x06a6,0x0097, 0x06aa,0x02b1, 0x06aa,0x02ce, 0x06ae,0x0039, 0x06ae,0x0213,
+    0x06ae,0x022e, 0x06ae,0x02e1, 0x06b2,0x0162, 0x06b2,0x0183, 0x06b6,0x0023,
+    0x06b6,0x00e0, 0x06b6,0x00fb, 0x06ba,0x008f, 0x06ba,0x01e4, 0x06be,0x034b,
+    0x06c1,0x0086, 0x06c1,0x009a, 0x06c1,0x00ec, 0x06c1,0x0172, 0x06c6,0x01da,
+    0x06c6,0x0280, 0x06c6,0x0351, 0x06ce,0x008f, 0x06d2,0x01e3, 0x06d2,0x0287,
+    0x06d2,0x0353, 0x06d6,0x027a, 0x06d6,0x029b, 0x06da,0x0033, 0x06da,0x01ce,
+    0x06da,0x01f1, 0x06de,0x0133, 0x06de,0x0148, 0x06e2,0x0021, 0x06e2,0x00bf,
+    0x06e2,0x00d0, 0x06e5,0x023a, 0x06e9,0x0004, 0x06ee,0x028c, 0x06ee,0x0338,
+    0x06f2,0x0328, 0x06f2,0x0330, 0x06f4,0x0005, 0x06f9,0x01e0, 0x06fe,0x0328,
+    0x06fe,0x0330, 0x0702,0x003d, 0x0702,0x00f3, 0x0702,0x0330, 0x0704,0x0003,
+    0x070a,0x003d, 0x070a,0x00f3, 0x070a,0x01d4, 0x070a,0x01f3, 0x070a,0x0330,
+    0x0711,0x032a, 0x0711,0x032e, 0x0716,0x003d, 0x0718,0x0205, 0x0718,0x0282,
+    0x071e,0x00f3, 0x0720,0x01dc, 0x0720,0x02a5, 0x0726,0x0324, 0x072a,0x028a,
+    0x072a,0x02a7, 0x0729,0x031c, 0x0729,0x032a, 0x072e,0x003d, 0x072e,0x00f9,
+    0x072e,0x022d, 0x072e,0x0248, 0x072e,0x02e4, 0x0730,0x003d, 0x0730,0x0247,
+    0x0730,0x02e3, 0x0730,0x0324, 0x0732,0x0324, 0x0739,0x032e, 0x073e,0x003d,
+    0x0740,0x003d, 0x0744,0x027a, 0x0744,0x029b, 0x0748,0x0033, 0x0748,0x01ce,
+    0x0748,0x01f1, 0x074c,0x0162, 0x074c,0x0183, 0x0750,0x0023, 0x0750,0x00e0,
+    0x0750,0x00fb, 0x0755,0x0246, 0x075a,0x0095, 0x075a,0x0397, 0x075d,0x0004,
+    0x076a,0x03b3, 0x076d,0x0002, 0x0772,0x02fb, 0x0772,0x0301, 0x0772,0x0315,
+    0x0772,0x0397, 0x0776,0x008f, 0x077e,0x0027, 0x078a,0x00a1, 0x0792,0x009d,
+    0x0792,0x00c3, 0x0792,0x02fb, 0x0792,0x0301, 0x0792,0x0315, 0x0792,0x03bd,
+    0x0796,0x0027, 0x0796,0x024f, 0x079e,0x009d, 0x07a6,0x009d, 0x07a6,0x02fb,
+    0x07a6,0x0301, 0x07a6,0x0315, 0x07a6,0x03bd, 0x07aa,0x0027, 0x07aa,0x024f,
+    0x07ae,0x009d, 0x07b9,0x004e, 0x07b8,0x0087, 0x07b8,0x00ed, 0x07b8,0x0173,
+    0x07b8,0x0197, 0x07b9,0x021a, 0x07b9,0x02b8, 0x07b9,0x0364, 0x07be,0x0029,
+    0x07be,0x0030, 0x07c0,0x017b, 0x07c6,0x017b, 0x07c8,0x00f3, 0x07ce,0x00f3,
+    0x07d0,0x008f, 0x07d6,0x008f, 0x07d9,0x01e8, 0x07dd,0x0292, 0x07e2,0x0053,
+    0x07e6,0x008f, 0x07e6,0x00f3, 0x07e6,0x017b, 0x07e8,0x0029, 0x07e8,0x0030,
+    0x07ec,0x0021, 0x07ec,0x02ad, 0x07f2,0x0181, 0x07f2,0x0315, 0x07f4,0x0021,
+    0x07f8,0x020f, 0x07fd,0x002e, 0x0800,0x008f, 0x0805,0x0006, 0x0809,0x03c2,
+    0x080d,0x0084, 0x0812,0x0009, 0x0811,0x0008, 0x0812,0x00f3, 0x0812,0x00f9,
+    0x0812,0x017b, 0x0812,0x0181, 0x0814,0x0033, 0x0818,0x0023, 0x081c,0x0285,
+    0x0826,0x03bd, 0x082c,0x008f, 0x082c,0x017b, 0x0832,0x0043, 0x0832,0x011b,
+    0x0832,0x01b3, 0x0832,0x01c3, 0x0835,0x032a, 0x0838,0x0085, 0x0839,0x032a,
+    0x083e,0x0049, 0x083d,0x0084, 0x083e,0x02fb, 0x083e,0x0301, 0x083e,0x0315,
+    0x083e,0x0397, 0x0842,0x0009, 0x0841,0x0008, 0x0844,0x0009, 0x0846,0x008f,
+    0x084a,0x0033, 0x084e,0x0285, 0x0851,0x009a, 0x0856,0x00a1, 0x0859,0x031c,
+    0x085d,0x00b2, 0x0861,0x0012, 0x0861,0x02cc, 0x0865,0x0058, 0x0865,0x007e,
+    0x0869,0x004a, 0x0871,0x0010, 0x0876,0x003d, 0x0879,0x032c, 0x087e,0x0089,
+    0x0882,0x0229, 0x0882,0x022d, 0x0882,0x02c7, 0x0882,0x02cb, 0x0886,0x0021,
+    0x0886,0x02ad, 0x0885,0x0356, 0x088a,0x0017, 0x088a,0x020f, 0x0889,0x0354,
+    0x088d,0x009c, 0x0892,0x0089, 0x0895,0x0246, 0x089a,0x03bd, 0x089e,0x008f,
+    0x089e,0x02f9, 0x089e,0x0313, 0x08a1,0x032a, 0x08a6,0x0053, 0x08a6,0x0095,
+    0x08a6,0x0397, 0x08a8,0x017b, 0x08ad,0x031a, 0x08b2,0x017b, 0x08b4,0x00f3,
+    0x08b5,0x02a0, 0x08b8,0x0089, 0x08c1,0x0024, 0x08c4,0x00f3, 0x08c9,0x007e,
+    0x08cd,0x007c, 0x08cd,0x0222, 0x08cd,0x0294, 0x08d1,0x003a, 0x08d6,0x0009,
+    0x08d9,0x003a, 0x08dc,0x001f, 0x08e0,0x008f, 0x08e0,0x017b, 0x08e4,0x0009,
+    0x08e8,0x01ed, 0x08ed,0x031c, 0x08f2,0x003d, 0x08f6,0x008f, 0x08f6,0x017b,
+    0x08fa,0x0009, 0x08fe,0x003d, 0x0902,0x01e9, 0x0904,0x01e9, 0x0904,0x0381,
+    0x090a,0x03b1, 0x090d,0x031a, 0x0910,0x0299, 0x0914,0x034b, 0x0919,0x0008,
+    0x091c,0x0033, 0x091c,0x003d, 0x0920,0x0027, 0x0924,0x0027, 0x0924,0x01fb,
+    0x092a,0x01ce, 0x092a,0x01f1, 0x092d,0x031c, 0x0930,0x001f, 0x0936,0x00c5,
+    0x0938,0x00c5, 0x0938,0x0381, 0x093c,0x001b, 0x0942,0x017d, 0x094a,0x0027,
+    0x094e,0x0027, 0x094e,0x01fb, 0x0952,0x03b1, 0x095a,0x0029, 0x095a,0x0030,
+    0x095d,0x0030, 0x0961,0x0030, 0x0966,0x02f9, 0x0966,0x0313, 0x0968,0x02eb,
+    0x096d,0x0008, 0x0970,0x017b, 0x0974,0x0033, 0x0979,0x0150, 0x097d,0x009a,
+    0x0982,0x0293, 0x0984,0x0293, 0x0984,0x0379, 0x098a,0x02eb, 0x098e,0x0009,
+    0x0992,0x003d, 0x0996,0x003d, 0x0999,0x0062, 0x099e,0x003d, 0x09a0,0x0027,
+    0x09a5,0x0144, 0x09a8,0x02b5, 0x09ae,0x008f, 0x09ae,0x009d, 0x09b2,0x004d,
+    0x09b2,0x0053, 0x09b2,0x00c3, 0x09b2,0x013d, 0x09b2,0x01c5, 0x09b2,0x0271,
+    0x09b4,0x0025, 0x09ba,0x0033, 0x09ba,0x0079, 0x09bc,0x0015, 0x09c2,0x013f,
+    0x09c4,0x013f, 0x09c4,0x0379, 0x09ca,0x02b5, 0x09cd,0x0006, 0x09da,0x0009,
+    0x09d9,0x0008, 0x09dc,0x000b, 0x09dc,0x004f, 0x09dd,0x0086, 0x09e0,0x0009,
+    0x09e6,0x00a1, 0x09e8,0x0009, 0x09ed,0x0086, 0x09f2,0x001f, 0x09f2,0x002f,
+    0x09f2,0x0049, 0x09f2,0x006f, 0x09f2,0x0085, 0x09f2,0x0091, 0x09f2,0x00a9,
+    0x09f2,0x00d3, 0x09f2,0x00d7, 0x09f2,0x011d, 0x09f2,0x0121, 0x09f2,0x0235,
+    0x09f2,0x0393, 0x09f6,0x0324, 0x09f8,0x0049, 0x09f8,0x00a9, 0x09f8,0x011d,
+    0x09fe,0x001f, 0x09fe,0x0029, 0x09fe,0x0033, 0x09fe,0x003d, 0x09fe,0x0085,
+    0x09fe,0x008f, 0x09fe,0x00d3, 0x0a00,0x003d, 0x0a06,0x012d, 0x0a0e,0x00b3,
+    0x0a10,0x000b, 0x0a10,0x0387, 0x0a16,0x0059, 0x0a18,0x0009, 0x0a1e,0x0043,
+    0x0a24,0x0085, 0x0a2a,0x0009, 0x0a2d,0x0008, 0x0a32,0x028a, 0x0a32,0x02a7,
+    0x0a31,0x031c, 0x0a35,0x032e, 0x0a39,0x0006, 0x0a3a,0x0105, 0x0a3a,0x024f,
+    0x0a3c,0x0299, 0x0a42,0x01ed, 0x0a46,0x0299, 0x0a48,0x01ed, 0x0a4c,0x0059,
+    0x0a52,0x000b, 0x0a52,0x0387, 0x0a56,0x000b, 0x0a5e,0x0009, 0x0a60,0x003d,
+    0x0a66,0x0105, 0x0a6a,0x0195, 0x0a6c,0x000b, 0x0a76,0x0053, 0x0a78,0x0009,
+    0x0a7a,0x008f, 0x0a82,0x0299, 0x0a86,0x01ed, 0x0a8a,0x0027, 0x0a8e,0x004b,
+    0x0a92,0x003d, 0x0a95,0x0322, 0x0a99,0x0038, 0x0a99,0x0090, 0x0a9c,0x0061,
+    0x0a9c,0x00c7, 0x0a9c,0x012d, 0x0a9c,0x016f, 0x0a9c,0x017d, 0x0a9c,0x02c9,
+    0x0a9c,0x0383, 0x0aa1,0x0010, 0x0aa4,0x00b3, 0x0aa8,0x002f, 0x0aac,0x0027,
+    0x0ab0,0x004b, 0x0ab4,0x0043, 0x0ab9,0x0090, 0x0abd,0x0010, 0x0ac4,0x0019,
+    0x0acc,0x00f5, 0x0acc,0x022b, 0x0acc,0x037b, 0x0ad2,0x008f, 0x0ad2,0x01f1,
+    0x0ad6,0x0324, 0x0ad9,0x0330, 0x0ade,0x008f, 0x0ade,0x01f1, 0x0ae0,0x017b,
+    0x0ae4,0x008f, 0x0ae9,0x004e, 0x0aee,0x0027, 0x0af2,0x028a, 0x0af2,0x02a7,
+    0x0af1,0x031c, 0x0af6,0x0027, 0x0af9,0x031c, 0x0afe,0x00e9, 0x0afe,0x02bb,
+    0x0b02,0x000b, 0x0b06,0x00f5, 0x0b06,0x022b, 0x0b06,0x037b, 0x0b0a,0x003d,
+    0x0000,0x0000
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Writes data.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_ManWriteToArray( Rwr_Man_t * p )
+{
+    FILE * pFile;
+    Rwr_Node_t * pNode;
+    unsigned Entry0, Entry1;
+    int i, nEntries;
+    abctime clk = Abc_Clock();
+    // prepare the buffer
+    nEntries = p->vForest->nSize - 5;
+    pFile = fopen( "npn4_aig_array.txt", "w" );
+    fprintf( pFile, "static unsigned short s_RwtAigSubgraphs[] = \n{" );
+    for ( i = 0; i < nEntries; i++ )
+    {
+        if ( i % 5 == 0 )
+            fprintf( pFile, "\n    " );
+        pNode = (Rwr_Node_t *)p->vForest->pArray[i+5];
+        Entry0 = (Rwr_Regular(pNode->p0)->Id << 1) | Rwr_IsComplement(pNode->p0);
+        Entry1 = (Rwr_Regular(pNode->p1)->Id << 1) | Rwr_IsComplement(pNode->p1);
+        Entry0 = (Entry0 << 1) | pNode->fExor;
+        Extra_PrintHex( pFile, &Entry0, 4 );
+        fprintf( pFile, "," );
+        Extra_PrintHex( pFile, &Entry1, 4 );
+        fprintf( pFile, ", " );
+    }
+    if ( i % 5 == 0 )
+        fprintf( pFile, "\n    " );
+    Entry0 = 0;
+    Extra_PrintHex( pFile, &Entry0, 4 );
+    fprintf( pFile, "," );
+    Extra_PrintHex( pFile, &Entry0, 4 );
+    fprintf( pFile, " \n};\n" );
+    fclose( pFile );
+    printf( "The number of nodes saved = %d.   ", nEntries );  ABC_PRT( "Saving", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Loads data.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_ManLoadFromArray( Rwr_Man_t * p, int fVerbose )
+{
+    unsigned short * pArray = s_RwtAigSubgraphs;
+    Rwr_Node_t * p0, * p1;
+    unsigned Entry0, Entry1;
+    int Level, Volume, nEntries, fExor;
+    int i;
+    abctime clk = Abc_Clock();
+
+    // reconstruct the forest
+    for ( i = 0; ; i++ )
+    {
+        Entry0 = pArray[2*i + 0];
+        Entry1 = pArray[2*i + 1];
+        if ( Entry0 == 0 && Entry1 == 0 )
+            break;
+        // get EXOR flag
+        fExor = (Entry0 & 1);
+        Entry0 >>= 1;
+        // get the nodes
+        p0 = (Rwr_Node_t *)p->vForest->pArray[Entry0 >> 1];
+        p1 = (Rwr_Node_t *)p->vForest->pArray[Entry1 >> 1];
+        // compute the level and volume of the new nodes
+        Level  = 1 + Abc_MaxInt( p0->Level, p1->Level );
+        Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 );
+        // set the complemented attributes
+        p0 = Rwr_NotCond( p0, (Entry0 & 1) );
+        p1 = Rwr_NotCond( p1, (Entry1 & 1) );
+        // add the node
+//        Rwr_ManTryNode( p, p0, p1, Level, Volume );
+        Rwr_ManAddNode( p, p0, p1, fExor, Level, Volume + fExor );
+    }
+    nEntries = i - 1;
+    if ( fVerbose )
+    {
+        printf( "The number of classes = %d. Canonical nodes = %d.\n", p->nClasses, p->nAdded );
+        printf( "The number of nodes loaded = %d.  ", nEntries );  ABC_PRT( "Loading", Abc_Clock() - clk );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_ManWriteToFile( Rwr_Man_t * p, char * pFileName )
+{
+    FILE * pFile;
+    Rwr_Node_t * pNode;
+    unsigned * pBuffer;
+    int i, nEntries;
+    abctime clk = Abc_Clock();
+    // prepare the buffer
+    nEntries = p->vForest->nSize - 5;
+    pBuffer = ABC_ALLOC( unsigned, nEntries * 2 );
+    for ( i = 0; i < nEntries; i++ )
+    {
+        pNode = (Rwr_Node_t *)p->vForest->pArray[i+5];
+        pBuffer[2*i + 0] = (Rwr_Regular(pNode->p0)->Id << 1) | Rwr_IsComplement(pNode->p0);
+        pBuffer[2*i + 1] = (Rwr_Regular(pNode->p1)->Id << 1) | Rwr_IsComplement(pNode->p1);
+        // save EXOR flag
+        pBuffer[2*i + 0] = (pBuffer[2*i + 0] << 1) | pNode->fExor;
+
+    }
+    pFile = fopen( pFileName, "wb" );
+    fwrite( &nEntries, sizeof(int), 1, pFile );
+    fwrite( pBuffer, sizeof(unsigned), nEntries * 2, pFile );
+    ABC_FREE( pBuffer );
+    fclose( pFile );
+    printf( "The number of nodes saved = %d.   ", nEntries );  ABC_PRT( "Saving", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Loads data.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_ManLoadFromFile( Rwr_Man_t * p, char * pFileName )
+{
+    FILE * pFile;
+    Rwr_Node_t * p0, * p1;
+    unsigned * pBuffer;
+    int Level, Volume, nEntries, fExor;
+    int i;
+    abctime clk = Abc_Clock();
+    int RetValue;
+
+    // load the data
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Rwr_ManLoadFromFile: Cannot open file \"%s\".\n", pFileName );
+        return;
+    }
+    RetValue = fread( &nEntries, sizeof(int), 1, pFile );
+    pBuffer = ABC_ALLOC( unsigned, nEntries * 2 );
+    RetValue = fread( pBuffer, sizeof(unsigned), nEntries * 2, pFile );
+    fclose( pFile );
+    // reconstruct the forest
+    for ( i = 0; i < nEntries; i++ )
+    {
+        // get EXOR flag
+        fExor = (pBuffer[2*i + 0] & 1);
+        pBuffer[2*i + 0] = (pBuffer[2*i + 0] >> 1);
+        // get the nodes
+        p0 = (Rwr_Node_t *)p->vForest->pArray[pBuffer[2*i + 0] >> 1];
+        p1 = (Rwr_Node_t *)p->vForest->pArray[pBuffer[2*i + 1] >> 1];
+        // compute the level and volume of the new nodes
+        Level  = 1 + Abc_MaxInt( p0->Level, p1->Level );
+        Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 );
+        // set the complemented attributes
+        p0 = Rwr_NotCond( p0, (pBuffer[2*i + 0] & 1) );
+        p1 = Rwr_NotCond( p1, (pBuffer[2*i + 1] & 1) );
+        // add the node
+//        Rwr_ManTryNode( p, p0, p1, Level, Volume );
+        Rwr_ManAddNode( p, p0, p1, fExor, Level, Volume + fExor );
+    }
+    ABC_FREE( pBuffer );
+    printf( "The number of classes = %d. Canonical nodes = %d.\n", p->nClasses, p->nAdded );
+    printf( "The number of nodes loaded = %d.   ", nEntries );  ABC_PRT( "Loading", Abc_Clock() - clk );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the node to the end of the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwr_ListAddToTail( Rwr_Node_t ** ppList, Rwr_Node_t * pNode )
+{
+    Rwr_Node_t * pTemp;
+    // find the last one
+    for ( pTemp = *ppList; pTemp; pTemp = pTemp->pNext )
+        ppList = &pTemp->pNext;
+    // attach at the end
+    *ppList = pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create practical classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Rwr_ManGetPractical( Rwr_Man_t * p )
+{
+    char * pPractical;
+    int i;
+    pPractical = ABC_ALLOC( char, p->nFuncs );
+    memset( pPractical, 0, sizeof(char) * p->nFuncs );
+    pPractical[0] = 1;
+    for ( i = 1; ; i++ )
+    {
+        if ( s_RwrPracticalClasses[i] == 0 )
+            break;
+        pPractical[ s_RwrPracticalClasses[i] ] = 1;
+    }
+    return pPractical;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/rwt/module.make b/abc-build/src/opt/rwt/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/rwt/module.make
@@ -0,0 +1,3 @@
+SRC +=  src/opt/rwt/rwtDec.c \
+	src/opt/rwt/rwtMan.c \
+	src/opt/rwt/rwtUtil.c
diff --git a/abc-build/src/opt/rwt/rwt.h b/abc-build/src/opt/rwt/rwt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/rwt/rwt.h
@@ -0,0 +1,165 @@
+/**CFile****************************************************************
+
+  FileName    [rwt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rwt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__rwt__rwt_h
+#define ABC__aig__rwt__rwt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+#include "misc/extra/extra.h"
+#include "misc/mem/mem.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+#define RWT_LIMIT  1048576/4  // ((1 << 20) 
+#define RWT_MIN(a,b)      (((a) < (b))? (a) : (b))
+#define RWT_MAX(a,b)      (((a) > (b))? (a) : (b))
+
+typedef struct Rwt_Man_t_   Rwt_Man_t;
+typedef struct Rwt_Node_t_  Rwt_Node_t;
+
+struct Rwt_Man_t_
+{
+    // internal lookups
+    int                nFuncs;           // number of four var functions
+    unsigned short *   puCanons;         // canonical forms
+    char *             pPhases;          // canonical phases
+    char *             pPerms;           // canonical permutations
+    unsigned char *    pMap;             // mapping of functions into class numbers
+    unsigned short *   pMapInv;          // mapping of classes into functions
+    char *             pPractical;       // practical NPN classes
+    char **            pPerms4;          // four-var permutations
+    // node space
+    Vec_Ptr_t *        vForest;          // all the nodes
+    Rwt_Node_t **      pTable;           // the hash table of nodes by their canonical form
+    Vec_Vec_t *        vClasses;         // the nodes of the equivalence classes
+    Mem_Fixed_t *      pMmNode;          // memory for nodes and cuts
+    // statistical variables
+    int                nTravIds;         // the counter of traversal IDs
+    int                nConsidered;      // the number of nodes considered
+    int                nAdded;           // the number of nodes added to lists
+    int                nClasses;         // the number of NN classes
+    // the result of resynthesis
+    int                fCompl;           // indicates if the output of FF should be complemented
+    void *             pCut;             // the decomposition tree (temporary)
+    void *             pGraph;           // the decomposition tree (temporary)
+    char *             pPerm;            // permutation used for the best cut
+    Vec_Ptr_t *        vFanins;          // the fanins array (temporary)
+    Vec_Ptr_t *        vFaninsCur;       // the fanins array (temporary)
+    Vec_Int_t *        vLevNums;         // the array of levels (temporary)
+    Vec_Ptr_t *        vNodesTemp;       // the nodes in MFFC (temporary)
+    // node statistics
+    int                nNodesConsidered;
+    int                nNodesRewritten;
+    int                nNodesGained;
+    int                nScores[222];
+    int                nCutsGood;
+    int                nCutsBad;
+    int                nSubgraphs;
+    // runtime statistics
+    abctime            timeStart;
+    abctime            timeTruth;
+    abctime            timeCut;
+    abctime            timeRes;
+    abctime            timeEval;
+    abctime            timeMffc;
+    abctime            timeUpdate;
+    abctime            timeTotal;
+};
+
+struct Rwt_Node_t_ // 24 bytes
+{
+    int                Id;               // ID 
+    int                TravId;           // traversal ID
+    unsigned           uTruth : 16;      // truth table
+    unsigned           Volume :  8;      // volume
+    unsigned           Level  :  6;      // level
+    unsigned           fUsed  :  1;      // mark
+    unsigned           fExor  :  1;      // mark
+    Rwt_Node_t *       p0;               // first child
+    Rwt_Node_t *       p1;               // second child
+    Rwt_Node_t *       pNext;            // next in the table
+};
+
+// manipulation of complemented attributes
+static inline int          Rwt_IsComplement( Rwt_Node_t * p )    { return (int)(((ABC_PTRUINT_T)p) & 01);            }
+static inline Rwt_Node_t * Rwt_Regular( Rwt_Node_t * p )         { return (Rwt_Node_t *)((ABC_PTRUINT_T)(p) & ~01);  }
+static inline Rwt_Node_t * Rwt_Not( Rwt_Node_t * p )             { return (Rwt_Node_t *)((ABC_PTRUINT_T)(p) ^  01);  }
+static inline Rwt_Node_t * Rwt_NotCond( Rwt_Node_t * p, int c )  { return (Rwt_Node_t *)((ABC_PTRUINT_T)(p) ^ (c));  }
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== rwrDec.c ========================================================*/
+extern void              Rwt_ManPreprocess( Rwt_Man_t * p );
+/*=== rwrMan.c ========================================================*/
+extern Rwt_Man_t *       Rwt_ManStart( int fPrecompute );
+extern void              Rwt_ManStop( Rwt_Man_t * p );
+extern void              Rwt_ManPrintStats( Rwt_Man_t * p );
+extern void              Rwt_ManPrintStatsFile( Rwt_Man_t * p );
+extern void *            Rwt_ManReadDecs( Rwt_Man_t * p );
+extern Vec_Ptr_t *       Rwt_ManReadLeaves( Rwt_Man_t * p );
+extern int               Rwt_ManReadCompl( Rwt_Man_t * p );
+extern void              Rwt_ManAddTimeCuts( Rwt_Man_t * p, abctime Time );
+extern void              Rwt_ManAddTimeUpdate( Rwt_Man_t * p, abctime Time );
+extern void              Rwt_ManAddTimeTotal( Rwt_Man_t * p, abctime Time );
+/*=== rwrUtil.c ========================================================*/
+extern void              Rwt_ManLoadFromArray( Rwt_Man_t * p, int fVerbose );
+extern char *            Rwt_ManGetPractical( Rwt_Man_t * p );
+extern Rwt_Node_t *      Rwt_ManAddVar( Rwt_Man_t * p, unsigned uTruth, int fPrecompute );
+extern void              Rwt_ManIncTravId( Rwt_Man_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/rwt/rwtDec.c b/abc-build/src/opt/rwt/rwtDec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/rwt/rwtDec.c
@@ -0,0 +1,155 @@
+/**CFile****************************************************************
+
+  FileName    [rwtDec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting package.]
+
+  Synopsis    [Evaluation and decomposition procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rwtDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rwt.h"
+#include "bool/deco/deco.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Dec_Graph_t * Rwt_NodePreprocess( Rwt_Man_t * p, Rwt_Node_t * pNode );
+static Dec_Edge_t    Rwt_TravCollect_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, Dec_Graph_t * pGraph );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Preprocesses computed library of subgraphs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_ManPreprocess( Rwt_Man_t * p )
+{
+    Dec_Graph_t * pGraph;
+    Rwt_Node_t * pNode;
+    int i, k;
+    // put the nodes into the structure
+    p->pMapInv  = ABC_ALLOC( unsigned short, 222 );
+    memset( p->pMapInv, 0, sizeof(unsigned short) * 222 );
+    p->vClasses = Vec_VecStart( 222 );
+    for ( i = 0; i < p->nFuncs; i++ )
+    {
+        if ( p->pTable[i] == NULL )
+            continue;
+        // consider all implementations of this function
+        for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext )
+        {
+            assert( pNode->uTruth == p->pTable[i]->uTruth );
+            assert( p->pMap[pNode->uTruth] < 222 ); // Always >= 0 b/c unsigned.
+            Vec_VecPush( p->vClasses, p->pMap[pNode->uTruth], pNode );
+            p->pMapInv[ p->pMap[pNode->uTruth] ] = p->puCanons[pNode->uTruth];
+        }
+    }
+    // compute decomposition forms for each node and verify them
+    Vec_VecForEachEntry( Rwt_Node_t *, p->vClasses, pNode, i, k )
+    {
+        pGraph = Rwt_NodePreprocess( p, pNode );
+        pNode->pNext = (Rwt_Node_t *)pGraph;
+//        assert( pNode->uTruth == (Dec_GraphDeriveTruth(pGraph) & 0xFFFF) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Preprocesses subgraphs rooted at this node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Graph_t * Rwt_NodePreprocess( Rwt_Man_t * p, Rwt_Node_t * pNode )
+{
+    Dec_Graph_t * pGraph;
+    Dec_Edge_t eRoot;
+    assert( !Rwt_IsComplement(pNode) );
+    // consider constant
+    if ( pNode->uTruth == 0 )
+        return Dec_GraphCreateConst0();
+    // consider the case of elementary var
+    if ( pNode->uTruth == 0x00FF )
+        return Dec_GraphCreateLeaf( 3, 4, 1 );
+    // start the subgraphs
+    pGraph = Dec_GraphCreate( 4 );
+    // collect the nodes
+    Rwt_ManIncTravId( p );
+    eRoot = Rwt_TravCollect_rec( p, pNode, pGraph );
+    Dec_GraphSetRoot( pGraph, eRoot );
+    return pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dec_Edge_t Rwt_TravCollect_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, Dec_Graph_t * pGraph )
+{
+    Dec_Edge_t eNode0, eNode1, eNode;
+    // elementary variable
+    if ( pNode->fUsed )
+        return Dec_EdgeCreate( pNode->Id - 1, 0 );
+    // previously visited node
+    if ( pNode->TravId == p->nTravIds )
+        return Dec_IntToEdge( pNode->Volume );
+    pNode->TravId = p->nTravIds;
+    // solve for children
+    eNode0 = Rwt_TravCollect_rec( p, Rwt_Regular(pNode->p0), pGraph );
+    if ( Rwt_IsComplement(pNode->p0) )    
+        eNode0.fCompl = !eNode0.fCompl;
+    eNode1 = Rwt_TravCollect_rec( p, Rwt_Regular(pNode->p1), pGraph );
+    if ( Rwt_IsComplement(pNode->p1) )    
+        eNode1.fCompl = !eNode1.fCompl;
+    // create the decomposition node(s)
+    if ( pNode->fExor )
+        eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1, 0 );
+    else
+        eNode = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
+    // save the result
+    pNode->Volume = Dec_EdgeToInt( eNode );
+    return eNode;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/rwt/rwtMan.c b/abc-build/src/opt/rwt/rwtMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/rwt/rwtMan.c
@@ -0,0 +1,363 @@
+/**CFile****************************************************************
+
+  FileName    [rwtMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting package.]
+
+  Synopsis    [Rewriting manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rwtMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rwt.h"
+#include "bool/deco/deco.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static unsigned short * s_puCanons = NULL; 
+static char *           s_pPhases = NULL; 
+static char *           s_pPerms = NULL; 
+static unsigned char *  s_pMap = NULL;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts residual rewriting manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_ManGlobalStart()
+{ 
+    if ( s_puCanons == NULL )
+        Extra_Truth4VarNPN( &s_puCanons, &s_pPhases, &s_pPerms, &s_pMap );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts residual rewriting manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_ManGlobalStop()
+{ 
+    ABC_FREE( s_puCanons );
+    ABC_FREE( s_pPhases );
+    ABC_FREE( s_pPerms );
+    ABC_FREE( s_pMap );
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Starts rewriting manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Rwt_Man_t * Rwt_ManStart( int fPrecompute )
+{
+    Rwt_Man_t * p;
+    abctime clk = Abc_Clock();
+clk = Abc_Clock();
+    p = ABC_ALLOC( Rwt_Man_t, 1 );
+    memset( p, 0, sizeof(Rwt_Man_t) );
+    p->nFuncs = (1<<16);
+    // copy the global tables
+    Rwt_ManGlobalStart();
+    p->puCanons = s_puCanons; 
+    p->pPhases  = s_pPhases; 
+    p->pPerms   = s_pPerms; 
+    p->pMap     = s_pMap; 
+    // initialize practical NPN classes
+    p->pPractical  = Rwt_ManGetPractical( p );
+    // create the table
+    p->pTable = ABC_ALLOC( Rwt_Node_t *, p->nFuncs );
+    memset( p->pTable, 0, sizeof(Rwt_Node_t *) * p->nFuncs );
+    // create the elementary nodes
+    p->pMmNode  = Mem_FixedStart( sizeof(Rwt_Node_t) );
+    p->vForest  = Vec_PtrAlloc( 100 );
+    Rwt_ManAddVar( p, 0x0000, fPrecompute ); // constant 0
+    Rwt_ManAddVar( p, 0xAAAA, fPrecompute ); // var A
+    Rwt_ManAddVar( p, 0xCCCC, fPrecompute ); // var B
+    Rwt_ManAddVar( p, 0xF0F0, fPrecompute ); // var C
+    Rwt_ManAddVar( p, 0xFF00, fPrecompute ); // var D
+    p->nClasses = 5;
+    // other stuff
+    p->nTravIds   = 1;
+    p->pPerms4    = Extra_Permutations( 4 );
+    p->vLevNums   = Vec_IntAlloc( 50 );
+    p->vFanins    = Vec_PtrAlloc( 50 );
+    p->vFaninsCur = Vec_PtrAlloc( 50 );
+    p->vNodesTemp = Vec_PtrAlloc( 50 );
+    if ( fPrecompute )
+    {   // precompute subgraphs
+//        Rwt_ManPrecompute( p );
+//        Rwt_ManPrint( p );
+//        Rwt_ManWriteToArray( p );
+    }
+    else
+    {   // load saved subgraphs
+        Rwt_ManLoadFromArray( p, 0 );
+//        Rwt_ManPrint( p );
+        Rwt_ManPreprocess( p );
+    }
+p->timeStart = Abc_Clock() - clk;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops rewriting manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_ManStop( Rwt_Man_t * p )
+{
+    if ( p->vClasses )
+    {
+        Rwt_Node_t * pNode;
+        int i, k;
+        Vec_VecForEachEntry( Rwt_Node_t *, p->vClasses, pNode, i, k )
+            Dec_GraphFree( (Dec_Graph_t *)pNode->pNext );
+    }
+    if ( p->vClasses )  Vec_VecFree( p->vClasses );
+    Vec_PtrFree( p->vNodesTemp );
+    Vec_PtrFree( p->vForest );
+    Vec_IntFree( p->vLevNums );
+    Vec_PtrFree( p->vFanins );
+    Vec_PtrFree( p->vFaninsCur );
+    Mem_FixedStop( p->pMmNode, 0 );
+    ABC_FREE( p->pMapInv );
+    ABC_FREE( p->pTable );
+    ABC_FREE( p->pPractical );
+    ABC_FREE( p->pPerms4 );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_ManPrintStats( Rwt_Man_t * p )
+{
+    int i, Counter = 0;
+    for ( i = 0; i < 222; i++ )
+        Counter += (p->nScores[i] > 0);
+
+    printf( "Rewriting statistics:\n" );
+    printf( "Total cuts tries  = %8d.\n", p->nCutsGood );
+    printf( "Bad cuts found    = %8d.\n", p->nCutsBad );
+    printf( "Total subgraphs   = %8d.\n", p->nSubgraphs );
+    printf( "Used NPN classes  = %8d.\n", Counter );
+    printf( "Nodes considered  = %8d.\n", p->nNodesConsidered );
+    printf( "Nodes rewritten   = %8d.\n", p->nNodesRewritten );
+    printf( "Calculated gain   = %8d.\n", p->nNodesGained     );
+    ABC_PRT( "Start       ", p->timeStart );
+    ABC_PRT( "Cuts        ", p->timeCut );
+    ABC_PRT( "Truth       ", p->timeTruth );
+    ABC_PRT( "Resynthesis ", p->timeRes );
+    ABC_PRT( "    Mffc    ", p->timeMffc );
+    ABC_PRT( "    Eval    ", p->timeEval );
+    ABC_PRT( "Update      ", p->timeUpdate );
+    ABC_PRT( "TOTAL       ", p->timeTotal );
+
+/*
+    printf( "The scores are:\n" );
+    for ( i = 0; i < 222; i++ )
+        if ( p->nScores[i] > 0 )
+        {
+            extern void Ivy_TruthDsdComputePrint( unsigned uTruth );
+            printf( "%3d = %8d  canon = %5d  ", i, p->nScores[i], p->pMapInv[i] );
+            Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[i] | ((unsigned)p->pMapInv[i] << 16) );
+        }
+    printf( "\n" );
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_ManPrintStatsFile( Rwt_Man_t * p )
+{
+    FILE * pTable;
+    pTable = fopen( "stats.txt", "a+" );
+    fprintf( pTable, "%d ", p->nCutsGood );
+    fprintf( pTable, "%d ", p->nSubgraphs );
+    fprintf( pTable, "%d ", p->nNodesRewritten );
+    fprintf( pTable, "%d", p->nNodesGained );
+    fprintf( pTable, "\n" );
+    fclose( pTable );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Rwt_ManReadDecs( Rwt_Man_t * p )
+{
+    return p->pGraph;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Rwt_ManReadLeaves( Rwt_Man_t * p )
+{
+    return p->vFanins;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rwt_ManReadCompl( Rwt_Man_t * p )
+{
+    return p->fCompl;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_ManAddTimeCuts( Rwt_Man_t * p, abctime Time )
+{
+    p->timeCut += Time;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_ManAddTimeUpdate( Rwt_Man_t * p, abctime Time )
+{
+    p->timeUpdate += Time;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the resynthesis manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_ManAddTimeTotal( Rwt_Man_t * p, abctime Time )
+{
+    p->timeTotal += Time;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Precomputes AIG subgraphs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_Precompute()
+{
+    Rwt_Man_t * p;
+    p = Rwt_ManStart( 1 );
+    Rwt_ManStop( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/rwt/rwtUtil.c b/abc-build/src/opt/rwt/rwtUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/rwt/rwtUtil.c
@@ -0,0 +1,663 @@
+/**CFile****************************************************************
+
+  FileName    [rwtUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting package.]
+
+  Synopsis    [Various utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rwtUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rwt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// precomputed data
+static unsigned short s_RwtAigSubgraphs[] = 
+{
+    0x0008,0x0002, 0x000a,0x0002, 0x0008,0x0003, 0x000a,0x0003, 0x0009,0x0002, 
+    0x000c,0x0002, 0x000e,0x0002, 0x000c,0x0003, 0x000e,0x0003, 0x000d,0x0002, 
+    0x000c,0x0004, 0x000e,0x0004, 0x000c,0x0005, 0x000e,0x0005, 0x000d,0x0004, 
+    0x0010,0x0002, 0x0012,0x0002, 0x0010,0x0003, 0x0012,0x0003, 0x0011,0x0002, 
+    0x0010,0x0004, 0x0012,0x0004, 0x0010,0x0005, 0x0012,0x0005, 0x0011,0x0004, 
+    0x0010,0x0006, 0x0012,0x0006, 0x0010,0x0007, 0x0012,0x0007, 0x0011,0x0006, 
+    0x0016,0x0005, 0x0014,0x0006, 0x0016,0x0006, 0x0014,0x0007, 0x0016,0x0007, 
+    0x0015,0x0006, 0x0014,0x0008, 0x0016,0x0008, 0x0014,0x0009, 0x0016,0x0009, 
+    0x0015,0x0008, 0x0018,0x0006, 0x001a,0x0006, 0x0018,0x0007, 0x001a,0x0007, 
+    0x0019,0x0006, 0x0018,0x0009, 0x001a,0x0009, 0x0019,0x0008, 0x001e,0x0005, 
+    0x001c,0x0006, 0x001e,0x0006, 0x001c,0x0007, 0x001e,0x0007, 0x001d,0x0006, 
+    0x001c,0x0008, 0x001e,0x0008, 0x001c,0x0009, 0x001e,0x0009, 0x001d,0x0008, 
+    0x0020,0x0006, 0x0022,0x0006, 0x0020,0x0007, 0x0022,0x0007, 0x0021,0x0006, 
+    0x0020,0x0008, 0x0022,0x0008, 0x0020,0x0009, 0x0022,0x0009, 0x0021,0x0008, 
+    0x0024,0x0006, 0x0026,0x0006, 0x0024,0x0007, 0x0026,0x0007, 0x0025,0x0006, 
+    0x0026,0x0008, 0x0024,0x0009, 0x0026,0x0009, 0x0025,0x0008, 0x0028,0x0004, 
+    0x002a,0x0004, 0x0028,0x0005, 0x002a,0x0007, 0x0028,0x0008, 0x002a,0x0009, 
+    0x0029,0x0008, 0x002a,0x000b, 0x0029,0x000a, 0x002a,0x000f, 0x0029,0x000e, 
+    0x002a,0x0011, 0x002a,0x0013, 0x002c,0x0004, 0x002e,0x0004, 0x002c,0x0005, 
+    0x002c,0x0009, 0x002e,0x0009, 0x002d,0x0008, 0x002d,0x000c, 0x002e,0x000f, 
+    0x002e,0x0011, 0x002e,0x0012, 0x0030,0x0004, 0x0032,0x0007, 0x0032,0x0009, 
+    0x0031,0x0008, 0x0032,0x000b, 0x0032,0x000d, 0x0032,0x000f, 0x0031,0x000e, 
+    0x0032,0x0013, 0x0034,0x0004, 0x0036,0x0004, 0x0034,0x0005, 0x0036,0x0005, 
+    0x0035,0x0004, 0x0036,0x0008, 0x0034,0x0009, 0x0036,0x0009, 0x0035,0x0008, 
+    0x0036,0x000b, 0x0036,0x000d, 0x0036,0x0011, 0x0035,0x0010, 0x0036,0x0013, 
+    0x0038,0x0004, 0x0039,0x0004, 0x0038,0x0009, 0x003a,0x0009, 0x0039,0x0008, 
+    0x0038,0x000b, 0x003a,0x000b, 0x003a,0x000d, 0x003a,0x0011, 0x003a,0x0012, 
+    0x0038,0x0013, 0x003a,0x0013, 0x003c,0x0002, 0x003e,0x0002, 0x003c,0x0003, 
+    0x003e,0x0005, 0x003e,0x0007, 0x003c,0x0008, 0x003e,0x0008, 0x003c,0x0009, 
+    0x003e,0x0009, 0x003d,0x0008, 0x003e,0x000d, 0x003e,0x0011, 0x003e,0x0013, 
+    0x003e,0x0017, 0x003e,0x001b, 0x003e,0x001d, 0x0040,0x0002, 0x0042,0x0002, 
+    0x0042,0x0005, 0x0041,0x0006, 0x0042,0x0008, 0x0041,0x0008, 0x0042,0x000d, 
+    0x0042,0x0011, 0x0042,0x0015, 0x0042,0x0019, 0x0042,0x001b, 0x0042,0x001c, 
+    0x0041,0x001c, 0x0044,0x0002, 0x0046,0x0003, 0x0045,0x0004, 0x0046,0x0007, 
+    0x0045,0x0008, 0x0046,0x000b, 0x0046,0x000f, 0x0046,0x0013, 0x0045,0x0012, 
+    0x0046,0x0017, 0x0046,0x001b, 0x0046,0x0021, 0x0048,0x0002, 0x004a,0x0002, 
+    0x0048,0x0003, 0x004a,0x0003, 0x0049,0x0002, 0x0048,0x0008, 0x004a,0x0008, 
+    0x0048,0x0009, 0x004a,0x0009, 0x0049,0x0008, 0x004a,0x000b, 0x004a,0x000f, 
+    0x004a,0x0011, 0x004a,0x0012, 0x004a,0x0013, 0x004a,0x0015, 0x004a,0x0019, 
+    0x004a,0x001b, 0x004a,0x001d, 0x004c,0x0002, 0x004c,0x0003, 0x004d,0x0002, 
+    0x004c,0x0008, 0x004e,0x0008, 0x004c,0x0009, 0x004e,0x0009, 0x004d,0x0008, 
+    0x004c,0x000b, 0x004e,0x000b, 0x004c,0x000f, 0x004e,0x000f, 0x004e,0x0011, 
+    0x004c,0x0012, 0x004c,0x0013, 0x004e,0x0013, 0x004e,0x0015, 0x004c,0x0017, 
+    0x004e,0x0019, 0x004c,0x001b, 0x004e,0x001b, 0x004c,0x001c, 0x004c,0x001d, 
+    0x004e,0x001d, 0x0050,0x0004, 0x0052,0x0004, 0x0050,0x0006, 0x0052,0x0009, 
+    0x0052,0x000d, 0x0052,0x000f, 0x0052,0x0013, 0x0052,0x0017, 0x0052,0x0019, 
+    0x0052,0x001d, 0x0052,0x001f, 0x0052,0x0021, 0x0052,0x0023, 0x0052,0x0024, 
+    0x0052,0x0025, 0x0051,0x0024, 0x0052,0x0027, 0x0054,0x0004, 0x0056,0x0004, 
+    0x0054,0x0005, 0x0056,0x0006, 0x0054,0x0007, 0x0056,0x0011, 0x0056,0x001b, 
+    0x0056,0x001e, 0x0054,0x001f, 0x0056,0x001f, 0x0056,0x0020, 0x0054,0x0021, 
+    0x0055,0x0020, 0x0056,0x0024, 0x0054,0x0025, 0x0056,0x0025, 0x0055,0x0024, 
+    0x0054,0x0027, 0x0056,0x0027, 0x0055,0x0026, 0x005a,0x0007, 0x005a,0x0009, 
+    0x005a,0x000b, 0x005a,0x0015, 0x005a,0x001f, 0x0059,0x0020, 0x0058,0x0024, 
+    0x005a,0x0024, 0x005a,0x0027, 0x0059,0x0026, 0x005c,0x0004, 0x005e,0x0004, 
+    0x005c,0x0005, 0x005e,0x0006, 0x005c,0x0007, 0x005d,0x0006, 0x005e,0x000d, 
+    0x005e,0x0013, 0x005e,0x0017, 0x005c,0x001f, 0x005d,0x001e, 0x005e,0x0020, 
+    0x005e,0x0021, 0x005e,0x0022, 0x005e,0x0023, 0x005c,0x0024, 0x005e,0x0024, 
+    0x005c,0x0025, 0x005e,0x0025, 0x005d,0x0024, 0x005e,0x0026, 0x005e,0x0027, 
+    0x0062,0x0004, 0x0061,0x0004, 0x0062,0x0006, 0x0061,0x0006, 0x0060,0x000f, 
+    0x0060,0x0013, 0x0062,0x0013, 0x0060,0x0019, 0x0062,0x001c, 0x0060,0x001d, 
+    0x0062,0x001d, 0x0062,0x001f, 0x0060,0x0021, 0x0060,0x0023, 0x0062,0x0024, 
+    0x0060,0x0027, 0x0061,0x0026, 0x0064,0x0002, 0x0066,0x0002, 0x0064,0x0006, 
+    0x0066,0x0007, 0x0066,0x0009, 0x0066,0x000d, 0x0066,0x0013, 0x0066,0x0015, 
+    0x0066,0x0017, 0x0066,0x0019, 0x0066,0x001a, 0x0065,0x001a, 0x0066,0x001f, 
+    0x0066,0x0023, 0x0066,0x0027, 0x0066,0x002f, 0x0066,0x0030, 0x006a,0x0002, 
+    0x0068,0x0003, 0x0068,0x0006, 0x006a,0x0006, 0x006a,0x0011, 0x0068,0x0016, 
+    0x0068,0x0017, 0x006a,0x0017, 0x006a,0x001a, 0x006a,0x001b, 0x006a,0x0025, 
+    0x006a,0x002d, 0x006e,0x0003, 0x006e,0x0007, 0x006e,0x0009, 0x006e,0x000b, 
+    0x006e,0x0015, 0x006e,0x0016, 0x006e,0x0017, 0x006c,0x001a, 0x006e,0x001a, 
+    0x006e,0x001f, 0x006e,0x002b, 0x006e,0x0035, 0x0070,0x0002, 0x0070,0x0003, 
+    0x0072,0x0006, 0x0070,0x0007, 0x0071,0x0006, 0x0072,0x000b, 0x0072,0x000f, 
+    0x0072,0x0013, 0x0070,0x0015, 0x0071,0x0014, 0x0072,0x0017, 0x0072,0x0018, 
+    0x0070,0x0019, 0x0072,0x0019, 0x0070,0x001a, 0x0070,0x001b, 0x0072,0x001b, 
+    0x0071,0x001a, 0x0072,0x0021, 0x0072,0x0029, 0x0076,0x0002, 0x0076,0x0003, 
+    0x0075,0x0002, 0x0076,0x0006, 0x0074,0x0007, 0x0076,0x0007, 0x0075,0x0006, 
+    0x0076,0x000d, 0x0076,0x0011, 0x0076,0x0013, 0x0075,0x0014, 0x0076,0x0019, 
+    0x0076,0x001a, 0x0076,0x001b, 0x0075,0x001c, 0x0074,0x0023, 0x0075,0x0022, 
+    0x0074,0x0026, 0x0076,0x0026, 0x0074,0x0027, 0x0076,0x002b, 0x0076,0x002f, 
+    0x0078,0x0002, 0x0078,0x0004, 0x007a,0x0004, 0x007a,0x0005, 0x0079,0x0004, 
+    0x007a,0x0009, 0x007a,0x000a, 0x007a,0x000b, 0x007a,0x000d, 0x007a,0x000f, 
+    0x007a,0x0010, 0x007a,0x0011, 0x007a,0x0012, 0x007a,0x0013, 0x007a,0x0017, 
+    0x007a,0x001b, 0x007a,0x0021, 0x007a,0x0027, 0x007a,0x002b, 0x007a,0x002f, 
+    0x007a,0x0030, 0x0079,0x0034, 0x007a,0x0039, 0x007a,0x003a, 0x007e,0x0002, 
+    0x007c,0x0004, 0x007e,0x0004, 0x007e,0x000c, 0x007c,0x000d, 0x007e,0x0011, 
+    0x007e,0x0013, 0x007e,0x001b, 0x007e,0x0025, 0x007e,0x002d, 0x007e,0x0037, 
+    0x0082,0x0003, 0x0082,0x0005, 0x0082,0x0009, 0x0082,0x000b, 0x0080,0x0010, 
+    0x0082,0x0010, 0x0082,0x0012, 0x0082,0x0015, 0x0082,0x001f, 0x0082,0x002b, 
+    0x0082,0x0035, 0x0082,0x0039, 0x0082,0x003f, 0x0084,0x0002, 0x0086,0x0002, 
+    0x0084,0x0003, 0x0086,0x0003, 0x0085,0x0002, 0x0086,0x0004, 0x0084,0x0005, 
+    0x0085,0x0004, 0x0086,0x000a, 0x0084,0x000b, 0x0085,0x000a, 0x0086,0x000d, 
+    0x0086,0x000e, 0x0086,0x000f, 0x0084,0x0010, 0x0084,0x0011, 0x0086,0x0011, 
+    0x0085,0x0010, 0x0084,0x0012, 0x0084,0x0013, 0x0086,0x0013, 0x0085,0x0012, 
+    0x0086,0x0019, 0x0086,0x0023, 0x0086,0x0029, 0x0086,0x0033, 0x0086,0x0039, 
+    0x008a,0x0003, 0x0089,0x0002, 0x0088,0x0004, 0x008a,0x0004, 0x0088,0x0005, 
+    0x0089,0x0004, 0x008a,0x000b, 0x008a,0x0010, 0x0088,0x0011, 0x008a,0x0011, 
+    0x0089,0x0010, 0x0088,0x0012, 0x008a,0x0012, 0x0089,0x0012, 0x008a,0x0017, 
+    0x008a,0x001b, 0x0089,0x0020, 0x008a,0x0025, 0x0088,0x0027, 0x008a,0x002b, 
+    0x008a,0x002f, 0x008a,0x0039, 0x0088,0x003a, 0x008d,0x0044, 0x0092,0x0009, 
+    0x0092,0x0025, 0x0092,0x0029, 0x0092,0x002d, 0x0092,0x0033, 0x0092,0x0037, 
+    0x0092,0x003d, 0x0092,0x0041, 0x0095,0x0002, 0x0095,0x0004, 0x0095,0x0010, 
+    0x0095,0x0012, 0x0096,0x0021, 0x0096,0x0029, 0x0095,0x002e, 0x0096,0x0030, 
+    0x0096,0x0033, 0x0096,0x003a, 0x0096,0x0043, 0x009a,0x0008, 0x009a,0x0009, 
+    0x0099,0x0008, 0x009a,0x0011, 0x009a,0x0023, 0x009a,0x0033, 0x009a,0x003d, 
+    0x009a,0x0044, 0x009a,0x0045, 0x0099,0x0044, 0x009d,0x0002, 0x009e,0x0008, 
+    0x009c,0x0009, 0x009e,0x0009, 0x009d,0x0008, 0x009e,0x0011, 0x009d,0x0010, 
+    0x009e,0x001f, 0x009e,0x003f, 0x00a0,0x0009, 0x00a0,0x0011, 0x00a2,0x0030, 
+    0x00a2,0x0033, 0x00a6,0x0006, 0x00a6,0x0007, 0x00a6,0x0011, 0x00a6,0x0044, 
+    0x00a6,0x004b, 0x00aa,0x0007, 0x00aa,0x0015, 0x00ae,0x0006, 0x00ae,0x0011, 
+    0x00ae,0x001b, 0x00ae,0x0025, 0x00ae,0x003d, 0x00ae,0x0041, 0x00ae,0x0043, 
+    0x00ae,0x0045, 0x00b2,0x0006, 0x00b0,0x0007, 0x00b1,0x0006, 0x00b2,0x0017, 
+    0x00b1,0x0016, 0x00b0,0x0019, 0x00b2,0x0021, 0x00b2,0x003d, 0x00b5,0x004a, 
+    0x00ba,0x0009, 0x00ba,0x000f, 0x00bc,0x0009, 0x00be,0x0009, 0x00be,0x000f, 
+    0x00bd,0x000e, 0x00be,0x0017, 0x00c2,0x0009, 0x00c2,0x0019, 0x00c2,0x001f, 
+    0x00c2,0x0033, 0x00c6,0x0009, 0x00c5,0x000e, 0x00c6,0x0015, 0x00c6,0x0023, 
+    0x00c4,0x002d, 0x00c6,0x002f, 0x00c5,0x002e, 0x00c6,0x0045, 0x00ce,0x0007, 
+    0x00ce,0x0021, 0x00ce,0x0023, 0x00ce,0x0025, 0x00ce,0x0027, 0x00ce,0x0033, 
+    0x00ce,0x003d, 0x00d2,0x0006, 0x00d0,0x0015, 0x00d0,0x001b, 0x00d2,0x001b, 
+    0x00d1,0x001a, 0x00d0,0x001f, 0x00d2,0x0025, 0x00d1,0x0024, 0x00d2,0x0037, 
+    0x00d2,0x0041, 0x00d2,0x0045, 0x00d9,0x0044, 0x00e1,0x0004, 0x00e2,0x000d, 
+    0x00e2,0x0021, 0x00e0,0x003a, 0x00e6,0x003d, 0x00e6,0x0061, 0x00e6,0x0067, 
+    0x00e9,0x0004, 0x00ea,0x0008, 0x00ea,0x0009, 0x00ea,0x0039, 0x00e9,0x0038, 
+    0x00ea,0x003f, 0x00ec,0x000d, 0x00ee,0x000d, 0x00ee,0x0037, 0x00f2,0x003d, 
+    0x00f2,0x0062, 0x00f5,0x0002, 0x00fa,0x0017, 0x00fa,0x003d, 0x00fe,0x0006, 
+    0x00fd,0x0006, 0x00fc,0x0015, 0x00fe,0x001b, 0x00fc,0x0025, 0x00fe,0x0025, 
+    0x00fd,0x0024, 0x00fe,0x0041, 0x00fe,0x004d, 0x00fd,0x004e, 0x0101,0x0014, 
+    0x0106,0x004d, 0x010a,0x0009, 0x010a,0x000b, 0x0109,0x000a, 0x010a,0x004f, 
+    0x010a,0x0058, 0x010e,0x0008, 0x010c,0x0009, 0x010e,0x0009, 0x010d,0x0008, 
+    0x010e,0x000b, 0x010e,0x002b, 0x010d,0x002a, 0x010e,0x0035, 0x010e,0x003d, 
+    0x010e,0x003f, 0x010e,0x0049, 0x010e,0x0057, 0x010d,0x0056, 0x010d,0x0058, 
+    0x0111,0x0004, 0x0111,0x0006, 0x0110,0x0009, 0x0112,0x0009, 0x0111,0x0008, 
+    0x0112,0x002f, 0x0110,0x0035, 0x0110,0x0037, 0x0112,0x0039, 0x0112,0x003d, 
+    0x0112,0x003f, 0x0112,0x0045, 0x0111,0x0044, 0x0112,0x004b, 0x0112,0x0059, 
+    0x0112,0x0069, 0x0112,0x007f, 0x0116,0x0009, 0x0115,0x0008, 0x0114,0x000b, 
+    0x0116,0x000b, 0x0116,0x0058, 0x011a,0x0015, 0x011a,0x001f, 0x011a,0x002b, 
+    0x011a,0x003f, 0x011a,0x0049, 0x011a,0x0085, 0x011e,0x0007, 0x011e,0x0019, 
+    0x011e,0x001b, 0x011e,0x0023, 0x011e,0x0027, 0x011e,0x002f, 0x011e,0x0043, 
+    0x011e,0x004b, 0x011e,0x004e, 0x011e,0x004f, 0x011e,0x005f, 0x011e,0x0061, 
+    0x011e,0x0065, 0x011e,0x0083, 0x0122,0x0006, 0x0120,0x0007, 0x0122,0x0007, 
+    0x0121,0x0006, 0x0122,0x0049, 0x0121,0x004e, 0x0122,0x008f, 0x0125,0x0004, 
+    0x0124,0x0007, 0x0125,0x0006, 0x0124,0x001b, 0x0126,0x001b, 0x0126,0x0045, 
+    0x0126,0x0087, 0x0128,0x0007, 0x0129,0x0006, 0x012a,0x0019, 0x012a,0x003d, 
+    0x012a,0x0051, 0x012a,0x0065, 0x012a,0x0083, 0x012d,0x005a, 0x0132,0x0009, 
+    0x0132,0x008f, 0x0134,0x0009, 0x0135,0x003e, 0x013a,0x003d, 0x013a,0x0044, 
+    0x0139,0x0044, 0x013e,0x0009, 0x013d,0x0008, 0x013c,0x003d, 0x013c,0x0044, 
+    0x013c,0x0053, 0x013e,0x008f, 0x013e,0x0095, 0x0142,0x0044, 0x0142,0x0097, 
+    0x0142,0x009e, 0x0144,0x0007, 0x0148,0x0015, 0x0148,0x001c, 0x0148,0x001f, 
+    0x0148,0x0026, 0x0149,0x0086, 0x014d,0x0006, 0x014e,0x0044, 0x014d,0x0048, 
+    0x014e,0x009e, 0x0152,0x0009, 0x0151,0x00a6, 0x0155,0x0030, 0x015d,0x003a, 
+    0x0162,0x009e, 0x0164,0x000f, 0x0164,0x0013, 0x0169,0x000e, 0x0174,0x0009, 
+    0x0179,0x0008, 0x0180,0x0009, 0x0181,0x0044, 0x0186,0x0044, 0x0185,0x0044, 
+    0x018a,0x0068, 0x0195,0x004e, 0x01a6,0x0009, 0x01a5,0x0008, 0x01b1,0x003a, 
+    0x01c4,0x0029, 0x01c4,0x0030, 0x01ca,0x008f, 0x01ca,0x0095, 0x01cc,0x0029, 
+    0x01cc,0x0033, 0x01ce,0x003d, 0x01d6,0x00b2, 0x01d8,0x0009, 0x01d9,0x002a, 
+    0x01d9,0x0056, 0x01d9,0x00a4, 0x01dd,0x003a, 0x01e2,0x00b2, 0x01e6,0x0013, 
+    0x01e6,0x009f, 0x01e6,0x00ba, 0x01e6,0x00c0, 0x01e6,0x00d3, 0x01e6,0x00d5, 
+    0x01e6,0x00e5, 0x01e8,0x0005, 0x01f2,0x0013, 0x01f2,0x0095, 0x01f2,0x009f, 
+    0x01f2,0x00ba, 0x01f2,0x00c0, 0x01f2,0x00d3, 0x0202,0x008f, 0x0202,0x0095, 
+    0x0202,0x00f3, 0x0202,0x00f9, 0x020a,0x0044, 0x0209,0x00b4, 0x020e,0x0009, 
+    0x020d,0x0008, 0x020c,0x003d, 0x020c,0x0044, 0x020c,0x0053, 0x020e,0x008f, 
+    0x020e,0x0095, 0x020c,0x00b1, 0x020e,0x00f3, 0x020e,0x00f9, 0x0210,0x0013, 
+    0x0211,0x0024, 0x0210,0x0026, 0x0219,0x0004, 0x021e,0x008f, 0x021e,0x0095, 
+    0x0221,0x003a, 0x0230,0x0009, 0x0236,0x0009, 0x0234,0x0029, 0x0234,0x0030, 
+    0x0234,0x0033, 0x0234,0x003a, 0x0234,0x003d, 0x0234,0x0044, 0x0235,0x00a6, 
+    0x023a,0x0009, 0x023d,0x003a, 0x0245,0x0044, 0x0249,0x003a, 0x024e,0x009e, 
+    0x024e,0x0106, 0x0251,0x0026, 0x0258,0x0013, 0x0259,0x0024, 0x0258,0x0061, 
+    0x0259,0x0086, 0x0258,0x00c7, 0x0258,0x00df, 0x0259,0x00ec, 0x0258,0x00fc, 
+    0x025d,0x0024, 0x025d,0x00de, 0x0260,0x00f6, 0x0268,0x0009, 0x0269,0x0044, 
+    0x0268,0x00f3, 0x0268,0x00f9, 0x026d,0x003a, 0x0270,0x0068, 0x0275,0x003a, 
+    0x027a,0x0044, 0x0279,0x0044, 0x027e,0x007e, 0x0281,0x0044, 0x0285,0x0008, 
+    0x028d,0x0006, 0x028d,0x00d2, 0x0295,0x00cc, 0x0296,0x00f6, 0x0295,0x00f8, 
+    0x0299,0x0030, 0x029e,0x007e, 0x029d,0x0080, 0x02a6,0x008f, 0x02a6,0x0095, 
+    0x02aa,0x0029, 0x02aa,0x0030, 0x02b5,0x0008, 0x02b9,0x003a, 0x02bd,0x0004, 
+    0x02bd,0x00fc, 0x02c2,0x00b2, 0x02c1,0x00b4, 0x02c4,0x0029, 0x02c8,0x0029, 
+    0x02c8,0x0033, 0x02ca,0x003d, 0x02ce,0x0029, 0x02ce,0x0030, 0x02d2,0x0068, 
+    0x02d1,0x006a, 0x02d5,0x006a, 0x02d9,0x0008, 0x02de,0x012c, 0x02e2,0x012c, 
+    0x02e4,0x0009, 0x02e5,0x002a, 0x02e5,0x0056, 0x02e5,0x012c, 0x02ea,0x0029, 
+    0x02ea,0x0030, 0x02e9,0x0030, 0x02ec,0x0029, 0x02ec,0x0030, 0x02ee,0x012c, 
+    0x02f1,0x0068, 0x02f1,0x00b2, 0x02f1,0x0108, 0x02f1,0x012c, 0x02f6,0x0013, 
+    0x02f6,0x0015, 0x02f6,0x001f, 0x02f6,0x0030, 0x02f6,0x0065, 0x02f6,0x0067, 
+    0x02f6,0x009f, 0x02f6,0x00b6, 0x02f6,0x00b9, 0x02f6,0x00c0, 0x02f6,0x00cf, 
+    0x02f6,0x0107, 0x02f6,0x010b, 0x02f6,0x010f, 0x02f6,0x0115, 0x02f6,0x012d, 
+    0x02f6,0x0134, 0x02f6,0x0153, 0x02f6,0x0171, 0x02f6,0x0176, 0x02f8,0x0003, 
+    0x02fa,0x017b, 0x02fc,0x00ba, 0x02fc,0x00d3, 0x0302,0x0013, 0x0302,0x001f, 
+    0x0302,0x0030, 0x0302,0x005d, 0x0302,0x0065, 0x0302,0x0067, 0x0302,0x0099, 
+    0x0302,0x009f, 0x0302,0x00ad, 0x0302,0x00b9, 0x0302,0x00c0, 0x0302,0x00cf, 
+    0x0301,0x00d2, 0x0301,0x00fe, 0x0302,0x0107, 0x0302,0x010b, 0x0302,0x010f, 
+    0x0302,0x0117, 0x0302,0x0134, 0x0302,0x0153, 0x0302,0x0157, 0x0302,0x0176, 
+    0x0306,0x0029, 0x0308,0x00b2, 0x0309,0x00dc, 0x030d,0x00f8, 0x0312,0x00f3, 
+    0x0318,0x007e, 0x031d,0x0080, 0x0321,0x0008, 0x0321,0x0094, 0x0326,0x017b, 
+    0x0326,0x0181, 0x0329,0x012e, 0x032a,0x017b, 0x032a,0x0181, 0x032e,0x008f, 
+    0x032e,0x0095, 0x032e,0x00f3, 0x032e,0x00f9, 0x0332,0x0009, 0x0331,0x0008, 
+    0x0330,0x003d, 0x0330,0x0044, 0x0330,0x0053, 0x0332,0x008f, 0x0332,0x0095, 
+    0x0330,0x00b1, 0x0332,0x00f3, 0x0332,0x00f9, 0x0330,0x0127, 0x0332,0x017b, 
+    0x0332,0x0181, 0x033c,0x0013, 0x033c,0x001c, 0x033d,0x0086, 0x033d,0x00ec, 
+    0x033d,0x0172, 0x033e,0x019d, 0x0345,0x0002, 0x0344,0x008f, 0x0344,0x00f3, 
+    0x034d,0x0030, 0x0352,0x0033, 0x0354,0x0029, 0x0354,0x0030, 0x035a,0x0009, 
+    0x035a,0x017b, 0x035a,0x019b, 0x035a,0x01a2, 0x035e,0x0181, 0x0360,0x0009, 
+    0x0366,0x0009, 0x0364,0x0029, 0x0364,0x0030, 0x0364,0x0033, 0x0364,0x003a, 
+    0x0364,0x003d, 0x0364,0x0044, 0x0369,0x0030, 0x0370,0x0029, 0x0370,0x0030, 
+    0x0376,0x0033, 0x037a,0x0009, 0x037a,0x019b, 0x037a,0x01a2, 0x037c,0x0009, 
+    0x0382,0x0181, 0x0386,0x0009, 0x0384,0x0029, 0x0384,0x0030, 0x0384,0x0033, 
+    0x0384,0x003a, 0x0384,0x003d, 0x0384,0x0044, 0x038a,0x0044, 0x038a,0x009e, 
+    0x038a,0x0106, 0x038a,0x0198, 0x038d,0x010e, 0x038d,0x0152, 0x038d,0x0158, 
+    0x0392,0x009e, 0x0392,0x0106, 0x0392,0x0198, 0x0395,0x0086, 0x0395,0x009a, 
+    0x0395,0x00ec, 0x0395,0x0172, 0x0398,0x014e, 0x0398,0x0175, 0x0398,0x018d, 
+    0x039c,0x0023, 0x039c,0x0027, 0x039c,0x00ef, 0x039c,0x0139, 0x039c,0x0168, 
+    0x03a0,0x0019, 0x03a0,0x001d, 0x03a0,0x0023, 0x03a0,0x0027, 0x03a1,0x004e, 
+    0x03a4,0x0162, 0x03a4,0x0183, 0x03a8,0x0013, 0x03a8,0x0027, 0x03a8,0x0133, 
+    0x03a8,0x0148, 0x03a8,0x0181, 0x03ac,0x0013, 0x03ac,0x0027, 0x03b0,0x017b, 
+    0x03b0,0x0181, 0x03b4,0x004b, 0x03b4,0x00e0, 0x03b4,0x00fb, 0x03b8,0x000f, 
+    0x03b8,0x0013, 0x03b8,0x00ab, 0x03b8,0x00bf, 0x03b8,0x00d0, 0x03bd,0x00da, 
+    0x03bd,0x012c, 0x03c8,0x000f, 0x03c8,0x0013, 0x03c8,0x0019, 0x03c8,0x001d, 
+    0x03cd,0x0086, 0x03cd,0x00ec, 0x03cd,0x0172, 0x03d2,0x00e0, 0x03d2,0x00ef, 
+    0x03d2,0x0112, 0x03d2,0x0139, 0x03d2,0x0168, 0x03d6,0x017b, 0x03d6,0x0181, 
+    0x03da,0x0133, 0x03da,0x0148, 0x03e2,0x0023, 0x03e2,0x0027, 0x03e6,0x0027, 
+    0x03e6,0x0181, 0x03ee,0x017b, 0x03ee,0x0181, 0x03fe,0x003d, 0x0401,0x012a, 
+    0x0401,0x019e, 0x0405,0x01a0, 0x040a,0x000d, 0x040a,0x011f, 0x040a,0x016f, 
+    0x040d,0x012a, 0x0412,0x017b, 0x041a,0x0033, 0x041a,0x003d, 0x041a,0x0181, 
+    0x0421,0x0086, 0x0421,0x009a, 0x0421,0x00ec, 0x0421,0x0172, 0x042e,0x0205, 
+    0x043a,0x0205, 0x043e,0x017b, 0x0442,0x01f5, 0x044c,0x0007, 0x0452,0x0033, 
+    0x0452,0x01ce, 0x0452,0x01d0, 0x0452,0x01f1, 0x0452,0x01fb, 0x0452,0x0225, 
+    0x0454,0x0005, 0x045a,0x0033, 0x045a,0x0181, 0x045a,0x01ce, 0x045a,0x01d0, 
+    0x045a,0x01f1, 0x0469,0x01de, 0x046e,0x0181, 0x047a,0x01ce, 0x047a,0x01f1, 
+    0x0485,0x012c, 0x0489,0x012c, 0x0490,0x01d8, 0x0496,0x0033, 0x0496,0x003d, 
+    0x0498,0x008f, 0x0498,0x00f3, 0x049e,0x0044, 0x049e,0x0221, 0x04a1,0x0006, 
+    0x04a2,0x0044, 0x04a6,0x0221, 0x04a9,0x0004, 0x04ac,0x0027, 0x04b1,0x009a, 
+    0x04b6,0x0097, 0x04b8,0x0027, 0x04c6,0x0219, 0x04ca,0x017b, 0x04cc,0x004b, 
+    0x04d0,0x00ab, 0x04d6,0x017b, 0x04d8,0x000f, 0x04d8,0x0019, 0x04d8,0x0033, 
+    0x04d8,0x003d, 0x04de,0x003d, 0x04de,0x0103, 0x04de,0x018b, 0x04de,0x0231, 
+    0x04e2,0x0044, 0x04e2,0x009e, 0x04e2,0x0106, 0x04e2,0x0198, 0x04e5,0x01a4, 
+    0x04e5,0x01b6, 0x04ea,0x009e, 0x04ea,0x0106, 0x04ea,0x0198, 0x04ed,0x002e, 
+    0x04ed,0x0038, 0x04ed,0x00a2, 0x04f1,0x0086, 0x04f1,0x009a, 0x04f1,0x00ec, 
+    0x04f1,0x0172, 0x04f9,0x004e, 0x04f8,0x0229, 0x04f8,0x022d, 0x0500,0x023e, 
+    0x0504,0x0217, 0x0510,0x00f3, 0x0514,0x0043, 0x0514,0x004d, 0x0514,0x00c3, 
+    0x0514,0x013d, 0x0514,0x0215, 0x0514,0x0232, 0x0515,0x0260, 0x0519,0x002a, 
+    0x0518,0x0030, 0x0518,0x0067, 0x0518,0x00c9, 0x0518,0x01eb, 0x0518,0x01ef, 
+    0x051c,0x0139, 0x051c,0x0168, 0x0520,0x0027, 0x0526,0x014e, 0x0526,0x0175, 
+    0x0526,0x018d, 0x052d,0x0200, 0x0532,0x0021, 0x0532,0x00bf, 0x0532,0x00d0, 
+    0x0532,0x0239, 0x0532,0x0266, 0x053d,0x0024, 0x053d,0x00da, 0x054a,0x000f, 
+    0x054a,0x00ab, 0x054a,0x023a, 0x054e,0x0043, 0x054e,0x004d, 0x054e,0x00c3, 
+    0x054e,0x013d, 0x054e,0x0215, 0x054e,0x0232, 0x054e,0x029d, 0x0552,0x014e, 
+    0x0552,0x018d, 0x0556,0x00f3, 0x0556,0x01e4, 0x055a,0x0299, 0x055d,0x0086, 
+    0x055d,0x009a, 0x055d,0x00ec, 0x055d,0x0172, 0x0566,0x01dc, 0x0566,0x02a5, 
+    0x056d,0x020a, 0x057a,0x003d, 0x057a,0x01d4, 0x057a,0x01f3, 0x0579,0x025e, 
+    0x057e,0x0139, 0x057e,0x0168, 0x0581,0x0006, 0x0586,0x017b, 0x0586,0x0181, 
+    0x0586,0x028c, 0x0588,0x0007, 0x058e,0x0033, 0x058e,0x008f, 0x058e,0x01d0, 
+    0x058e,0x027c, 0x0590,0x0003, 0x0596,0x0033, 0x0596,0x008f, 0x0596,0x0095, 
+    0x0596,0x01d0, 0x0596,0x027c, 0x05a2,0x026f, 0x05a5,0x0284, 0x05aa,0x017b, 
+    0x05ac,0x0205, 0x05b2,0x008f, 0x05b6,0x017b, 0x05b8,0x01da, 0x05c1,0x0276, 
+    0x05c6,0x0248, 0x05c8,0x0247, 0x05c8,0x027e, 0x05cc,0x003d, 0x05cc,0x01d4, 
+    0x05cc,0x01f3, 0x05d0,0x014e, 0x05d0,0x018d, 0x05da,0x00f9, 0x05dd,0x0006, 
+    0x05de,0x0044, 0x05e5,0x002e, 0x05e6,0x02f1, 0x05ea,0x01d4, 0x05ea,0x01f3, 
+    0x05ea,0x022d, 0x05ed,0x0002, 0x05f6,0x0027, 0x05fa,0x0097, 0x05fc,0x003d, 
+    0x0602,0x003d, 0x0606,0x00f3, 0x060a,0x0027, 0x060e,0x003d, 0x060e,0x0103, 
+    0x060e,0x018b, 0x060e,0x0231, 0x060e,0x02d1, 0x0611,0x01fc, 0x0611,0x0234, 
+    0x061a,0x0287, 0x061d,0x0214, 0x0621,0x01d4, 0x062a,0x0027, 0x062a,0x022d, 
+    0x062e,0x009e, 0x062e,0x0106, 0x062e,0x0198, 0x0632,0x009e, 0x0632,0x0106, 
+    0x0632,0x0198, 0x0639,0x0042, 0x0639,0x00b2, 0x0639,0x0108, 0x063d,0x01f8, 
+    0x0641,0x0086, 0x0641,0x009a, 0x0641,0x00ec, 0x0641,0x0172, 0x0645,0x0044, 
+    0x0649,0x0042, 0x0648,0x0087, 0x0648,0x00ed, 0x0648,0x0173, 0x0649,0x01a0, 
+    0x0648,0x0241, 0x0648,0x026f, 0x0648,0x02df, 0x0648,0x0307, 0x064c,0x023a, 
+    0x064c,0x02b3, 0x0651,0x0062, 0x0650,0x0217, 0x0651,0x02ac, 0x0650,0x02d6, 
+    0x0655,0x0042, 0x065d,0x0042, 0x0664,0x02b1, 0x0664,0x02ce, 0x0669,0x0238, 
+    0x066d,0x002a, 0x066c,0x0039, 0x066d,0x01f6, 0x066c,0x0213, 0x066c,0x022e, 
+    0x066d,0x02a2, 0x066c,0x02e1, 0x0671,0x002a, 0x0670,0x0030, 0x0670,0x0067, 
+    0x0670,0x00c9, 0x0670,0x01eb, 0x0670,0x01ef, 0x0670,0x02c3, 0x0675,0x0020, 
+    0x0678,0x0133, 0x0678,0x0148, 0x067c,0x0027, 0x0681,0x023a, 0x0684,0x0021, 
+    0x0684,0x00bf, 0x0684,0x00d0, 0x0689,0x01fc, 0x068e,0x0162, 0x068e,0x0183, 
+    0x0691,0x0200, 0x0696,0x0023, 0x0696,0x00e0, 0x0696,0x00fb, 0x0696,0x0268, 
+    0x069a,0x0282, 0x069d,0x007e, 0x06a2,0x004b, 0x06a2,0x023e, 0x06a2,0x02dc, 
+    0x06a6,0x0097, 0x06aa,0x02b1, 0x06aa,0x02ce, 0x06ae,0x0039, 0x06ae,0x0213, 
+    0x06ae,0x022e, 0x06ae,0x02e1, 0x06b2,0x0162, 0x06b2,0x0183, 0x06b6,0x0023, 
+    0x06b6,0x00e0, 0x06b6,0x00fb, 0x06ba,0x008f, 0x06ba,0x01e4, 0x06be,0x034b, 
+    0x06c1,0x0086, 0x06c1,0x009a, 0x06c1,0x00ec, 0x06c1,0x0172, 0x06c6,0x01da, 
+    0x06c6,0x0280, 0x06c6,0x0351, 0x06ce,0x008f, 0x06d2,0x01e3, 0x06d2,0x0287, 
+    0x06d2,0x0353, 0x06d6,0x027a, 0x06d6,0x029b, 0x06da,0x0033, 0x06da,0x01ce, 
+    0x06da,0x01f1, 0x06de,0x0133, 0x06de,0x0148, 0x06e2,0x0021, 0x06e2,0x00bf, 
+    0x06e2,0x00d0, 0x06e5,0x023a, 0x06e9,0x0004, 0x06ee,0x028c, 0x06ee,0x0338, 
+    0x06f2,0x0328, 0x06f2,0x0330, 0x06f4,0x0005, 0x06f9,0x01e0, 0x06fe,0x0328, 
+    0x06fe,0x0330, 0x0702,0x003d, 0x0702,0x00f3, 0x0702,0x0330, 0x0704,0x0003, 
+    0x070a,0x003d, 0x070a,0x00f3, 0x070a,0x01d4, 0x070a,0x01f3, 0x070a,0x0330, 
+    0x0711,0x032a, 0x0711,0x032e, 0x0716,0x003d, 0x0718,0x0205, 0x0718,0x0282, 
+    0x071e,0x00f3, 0x0720,0x01dc, 0x0720,0x02a5, 0x0726,0x0324, 0x072a,0x028a, 
+    0x072a,0x02a7, 0x0729,0x031c, 0x0729,0x032a, 0x072e,0x003d, 0x072e,0x00f9, 
+    0x072e,0x022d, 0x072e,0x0248, 0x072e,0x02e4, 0x0730,0x003d, 0x0730,0x0247, 
+    0x0730,0x02e3, 0x0730,0x0324, 0x0732,0x0324, 0x0739,0x032e, 0x073e,0x003d, 
+    0x0740,0x003d, 0x0744,0x027a, 0x0744,0x029b, 0x0748,0x0033, 0x0748,0x01ce, 
+    0x0748,0x01f1, 0x074c,0x0162, 0x074c,0x0183, 0x0750,0x0023, 0x0750,0x00e0, 
+    0x0750,0x00fb, 0x0755,0x0246, 0x075a,0x0095, 0x075a,0x0397, 0x075d,0x0004, 
+    0x076a,0x03b3, 0x076d,0x0002, 0x0772,0x02fb, 0x0772,0x0301, 0x0772,0x0315, 
+    0x0772,0x0397, 0x0776,0x008f, 0x077e,0x0027, 0x078a,0x00a1, 0x0792,0x009d, 
+    0x0792,0x00c3, 0x0792,0x02fb, 0x0792,0x0301, 0x0792,0x0315, 0x0792,0x03bd, 
+    0x0796,0x0027, 0x0796,0x024f, 0x079e,0x009d, 0x07a6,0x009d, 0x07a6,0x02fb, 
+    0x07a6,0x0301, 0x07a6,0x0315, 0x07a6,0x03bd, 0x07aa,0x0027, 0x07aa,0x024f, 
+    0x07ae,0x009d, 0x07b9,0x004e, 0x07b8,0x0087, 0x07b8,0x00ed, 0x07b8,0x0173, 
+    0x07b8,0x0197, 0x07b9,0x021a, 0x07b9,0x02b8, 0x07b9,0x0364, 0x07be,0x0029, 
+    0x07be,0x0030, 0x07c0,0x017b, 0x07c6,0x017b, 0x07c8,0x00f3, 0x07ce,0x00f3, 
+    0x07d0,0x008f, 0x07d6,0x008f, 0x07d9,0x01e8, 0x07dd,0x0292, 0x07e2,0x0053, 
+    0x07e6,0x008f, 0x07e6,0x00f3, 0x07e6,0x017b, 0x07e8,0x0029, 0x07e8,0x0030, 
+    0x07ec,0x0021, 0x07ec,0x02ad, 0x07f2,0x0181, 0x07f2,0x0315, 0x07f4,0x0021, 
+    0x07f8,0x020f, 0x07fd,0x002e, 0x0800,0x008f, 0x0805,0x0006, 0x0809,0x03c2, 
+    0x080d,0x0084, 0x0812,0x0009, 0x0811,0x0008, 0x0812,0x00f3, 0x0812,0x00f9, 
+    0x0812,0x017b, 0x0812,0x0181, 0x0814,0x0033, 0x0818,0x0023, 0x081c,0x0285, 
+    0x0826,0x03bd, 0x082c,0x008f, 0x082c,0x017b, 0x0832,0x0043, 0x0832,0x011b, 
+    0x0832,0x01b3, 0x0832,0x01c3, 0x0835,0x032a, 0x0838,0x0085, 0x0839,0x032a, 
+    0x083e,0x0049, 0x083d,0x0084, 0x083e,0x02fb, 0x083e,0x0301, 0x083e,0x0315, 
+    0x083e,0x0397, 0x0842,0x0009, 0x0841,0x0008, 0x0844,0x0009, 0x0846,0x008f, 
+    0x084a,0x0033, 0x084e,0x0285, 0x0851,0x009a, 0x0856,0x00a1, 0x0859,0x031c, 
+    0x085d,0x00b2, 0x0861,0x0012, 0x0861,0x02cc, 0x0865,0x0058, 0x0865,0x007e, 
+    0x0869,0x004a, 0x0871,0x0010, 0x0876,0x003d, 0x0879,0x032c, 0x087e,0x0089, 
+    0x0882,0x0229, 0x0882,0x022d, 0x0882,0x02c7, 0x0882,0x02cb, 0x0886,0x0021, 
+    0x0886,0x02ad, 0x0885,0x0356, 0x088a,0x0017, 0x088a,0x020f, 0x0889,0x0354, 
+    0x088d,0x009c, 0x0892,0x0089, 0x0895,0x0246, 0x089a,0x03bd, 0x089e,0x008f, 
+    0x089e,0x02f9, 0x089e,0x0313, 0x08a1,0x032a, 0x08a6,0x0053, 0x08a6,0x0095, 
+    0x08a6,0x0397, 0x08a8,0x017b, 0x08ad,0x031a, 0x08b2,0x017b, 0x08b4,0x00f3, 
+    0x08b5,0x02a0, 0x08b8,0x0089, 0x08c1,0x0024, 0x08c4,0x00f3, 0x08c9,0x007e, 
+    0x08cd,0x007c, 0x08cd,0x0222, 0x08cd,0x0294, 0x08d1,0x003a, 0x08d6,0x0009, 
+    0x08d9,0x003a, 0x08dc,0x001f, 0x08e0,0x008f, 0x08e0,0x017b, 0x08e4,0x0009, 
+    0x08e8,0x01ed, 0x08ed,0x031c, 0x08f2,0x003d, 0x08f6,0x008f, 0x08f6,0x017b, 
+    0x08fa,0x0009, 0x08fe,0x003d, 0x0902,0x01e9, 0x0904,0x01e9, 0x0904,0x0381, 
+    0x090a,0x03b1, 0x090d,0x031a, 0x0910,0x0299, 0x0914,0x034b, 0x0919,0x0008, 
+    0x091c,0x0033, 0x091c,0x003d, 0x0920,0x0027, 0x0924,0x0027, 0x0924,0x01fb, 
+    0x092a,0x01ce, 0x092a,0x01f1, 0x092d,0x031c, 0x0930,0x001f, 0x0936,0x00c5, 
+    0x0938,0x00c5, 0x0938,0x0381, 0x093c,0x001b, 0x0942,0x017d, 0x094a,0x0027, 
+    0x094e,0x0027, 0x094e,0x01fb, 0x0952,0x03b1, 0x095a,0x0029, 0x095a,0x0030, 
+    0x095d,0x0030, 0x0961,0x0030, 0x0966,0x02f9, 0x0966,0x0313, 0x0968,0x02eb, 
+    0x096d,0x0008, 0x0970,0x017b, 0x0974,0x0033, 0x0979,0x0150, 0x097d,0x009a, 
+    0x0982,0x0293, 0x0984,0x0293, 0x0984,0x0379, 0x098a,0x02eb, 0x098e,0x0009, 
+    0x0992,0x003d, 0x0996,0x003d, 0x0999,0x0062, 0x099e,0x003d, 0x09a0,0x0027, 
+    0x09a5,0x0144, 0x09a8,0x02b5, 0x09ae,0x008f, 0x09ae,0x009d, 0x09b2,0x004d, 
+    0x09b2,0x0053, 0x09b2,0x00c3, 0x09b2,0x013d, 0x09b2,0x01c5, 0x09b2,0x0271, 
+    0x09b4,0x0025, 0x09ba,0x0033, 0x09ba,0x0079, 0x09bc,0x0015, 0x09c2,0x013f, 
+    0x09c4,0x013f, 0x09c4,0x0379, 0x09ca,0x02b5, 0x09cd,0x0006, 0x09da,0x0009, 
+    0x09d9,0x0008, 0x09dc,0x000b, 0x09dc,0x004f, 0x09dd,0x0086, 0x09e0,0x0009, 
+    0x09e6,0x00a1, 0x09e8,0x0009, 0x09ed,0x0086, 0x09f2,0x001f, 0x09f2,0x002f, 
+    0x09f2,0x0049, 0x09f2,0x006f, 0x09f2,0x0085, 0x09f2,0x0091, 0x09f2,0x00a9, 
+    0x09f2,0x00d3, 0x09f2,0x00d7, 0x09f2,0x011d, 0x09f2,0x0121, 0x09f2,0x0235, 
+    0x09f2,0x0393, 0x09f6,0x0324, 0x09f8,0x0049, 0x09f8,0x00a9, 0x09f8,0x011d, 
+    0x09fe,0x001f, 0x09fe,0x0029, 0x09fe,0x0033, 0x09fe,0x003d, 0x09fe,0x0085, 
+    0x09fe,0x008f, 0x09fe,0x00d3, 0x0a00,0x003d, 0x0a06,0x012d, 0x0a0e,0x00b3, 
+    0x0a10,0x000b, 0x0a10,0x0387, 0x0a16,0x0059, 0x0a18,0x0009, 0x0a1e,0x0043, 
+    0x0a24,0x0085, 0x0a2a,0x0009, 0x0a2d,0x0008, 0x0a32,0x028a, 0x0a32,0x02a7, 
+    0x0a31,0x031c, 0x0a35,0x032e, 0x0a39,0x0006, 0x0a3a,0x0105, 0x0a3a,0x024f, 
+    0x0a3c,0x0299, 0x0a42,0x01ed, 0x0a46,0x0299, 0x0a48,0x01ed, 0x0a4c,0x0059, 
+    0x0a52,0x000b, 0x0a52,0x0387, 0x0a56,0x000b, 0x0a5e,0x0009, 0x0a60,0x003d, 
+    0x0a66,0x0105, 0x0a6a,0x0195, 0x0a6c,0x000b, 0x0a76,0x0053, 0x0a78,0x0009, 
+    0x0a7a,0x008f, 0x0a82,0x0299, 0x0a86,0x01ed, 0x0a8a,0x0027, 0x0a8e,0x004b, 
+    0x0a92,0x003d, 0x0a95,0x0322, 0x0a99,0x0038, 0x0a99,0x0090, 0x0a9c,0x0061, 
+    0x0a9c,0x00c7, 0x0a9c,0x012d, 0x0a9c,0x016f, 0x0a9c,0x017d, 0x0a9c,0x02c9, 
+    0x0a9c,0x0383, 0x0aa1,0x0010, 0x0aa4,0x00b3, 0x0aa8,0x002f, 0x0aac,0x0027, 
+    0x0ab0,0x004b, 0x0ab4,0x0043, 0x0ab9,0x0090, 0x0abd,0x0010, 0x0ac4,0x0019, 
+    0x0acc,0x00f5, 0x0acc,0x022b, 0x0acc,0x037b, 0x0ad2,0x008f, 0x0ad2,0x01f1, 
+    0x0ad6,0x0324, 0x0ad9,0x0330, 0x0ade,0x008f, 0x0ade,0x01f1, 0x0ae0,0x017b, 
+    0x0ae4,0x008f, 0x0ae9,0x004e, 0x0aee,0x0027, 0x0af2,0x028a, 0x0af2,0x02a7, 
+    0x0af1,0x031c, 0x0af6,0x0027, 0x0af9,0x031c, 0x0afe,0x00e9, 0x0afe,0x02bb, 
+    0x0b02,0x000b, 0x0b06,0x00f5, 0x0b06,0x022b, 0x0b06,0x037b, 0x0b0a,0x003d, 
+    0x0000,0x0000 
+};
+
+
+static unsigned short s_RwtPracticalClasses[] =
+{
+    0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, 0x001b,
+    0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, 0x007f, 0x00ff,
+    0x0116, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, 0x012c, 0x012d, 0x012f, 0x013c,
+    0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016f, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183,
+    0x0186, 0x0189, 0x018b, 0x018f, 0x0198, 0x0199, 0x019b, 0x01a8, 0x01a9, 0x01aa, 0x01ab,
+    0x01ac, 0x01ad, 0x01ae, 0x01af, 0x01bf, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, 0x01fe,
+    0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035f, 0x0368,
+    0x0369, 0x036c, 0x036e, 0x037d, 0x03c0, 0x03c1, 0x03c3, 0x03c7, 0x03cf, 0x03d4, 0x03d5,
+    0x03d7, 0x03d8, 0x03d9, 0x03dc, 0x03dd, 0x03de, 0x03fc, 0x0660, 0x0661, 0x0666, 0x0669,
+    0x066f, 0x0676, 0x067e, 0x0690, 0x0696, 0x0697, 0x069f, 0x06b1, 0x06b6, 0x06f0, 0x06f2,
+    0x06f6, 0x06f9, 0x0776, 0x0778, 0x07b0, 0x07b1, 0x07b4, 0x07bc, 0x07f0, 0x07f2, 0x07f8,
+    0x0ff0, 0x1683, 0x1696, 0x1698, 0x169e, 0x16e9, 0x178e, 0x17e8, 0x18e7, 0x19e6, 0x1be4,
+    0x1ee1, 0x3cc3, 0x6996, 0x0000
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the node to the end of the list.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_ListAddToTail( Rwt_Node_t ** ppList, Rwt_Node_t * pNode )
+{
+    Rwt_Node_t * pTemp;
+    // find the last one
+    for ( pTemp = *ppList; pTemp; pTemp = pTemp->pNext )
+        ppList = &pTemp->pNext;
+    // attach at the end
+    *ppList = pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Rwt_Node_t * Rwt_ManAddVar( Rwt_Man_t * p, unsigned uTruth, int fPrecompute )
+{
+    Rwt_Node_t * pNew;
+    pNew = (Rwt_Node_t *)Mem_FixedEntryFetch( p->pMmNode );
+    pNew->Id     = p->vForest->nSize;
+    pNew->TravId = 0;
+    pNew->uTruth = uTruth;
+    pNew->Level  = 0;
+    pNew->Volume = 0;
+    pNew->fUsed  = 1;
+    pNew->fExor  = 0;
+    pNew->p0     = NULL;
+    pNew->p1     = NULL;
+    pNew->pNext  = NULL;
+    Vec_PtrPush( p->vForest, pNew );
+    if ( fPrecompute )
+        Rwt_ListAddToTail( p->pTable + uTruth, pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Rwt_Node_t * Rwt_ManAddNode( Rwt_Man_t * p, Rwt_Node_t * p0, Rwt_Node_t * p1, int fExor, int Level, int Volume )
+{
+    Rwt_Node_t * pNew;
+    unsigned uTruth;
+    // compute truth table, leve, volume
+    p->nConsidered++;
+    if ( fExor )
+        uTruth = (p0->uTruth ^ p1->uTruth);
+    else
+        uTruth = (Rwt_IsComplement(p0)? ~Rwt_Regular(p0)->uTruth : Rwt_Regular(p0)->uTruth) &
+                 (Rwt_IsComplement(p1)? ~Rwt_Regular(p1)->uTruth : Rwt_Regular(p1)->uTruth) & 0xFFFF;
+    // create the new node
+    pNew = (Rwt_Node_t *)Mem_FixedEntryFetch( p->pMmNode );
+    pNew->Id     = p->vForest->nSize;
+    pNew->TravId = 0;
+    pNew->uTruth = uTruth;
+    pNew->Level  = Level;
+    pNew->Volume = Volume;
+    pNew->fUsed  = 0;
+    pNew->fExor  = fExor;
+    pNew->p0     = p0;
+    pNew->p1     = p1;
+    pNew->pNext  = NULL;
+    Vec_PtrPush( p->vForest, pNew );
+    // do not add if the node is not essential
+    if ( uTruth != p->puCanons[uTruth] )
+        return pNew;
+
+    // add to the list
+    p->nAdded++;
+    if ( p->pTable[uTruth] == NULL )
+        p->nClasses++;
+    Rwt_ListAddToTail( p->pTable + uTruth, pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_Trav_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, int * pVolume )
+{
+    if ( pNode->fUsed || pNode->TravId == p->nTravIds )
+        return;
+    pNode->TravId = p->nTravIds;
+    (*pVolume)++;
+    if ( pNode->fExor )
+        (*pVolume)++;
+    Rwt_Trav_rec( p, Rwt_Regular(pNode->p0), pVolume );
+    Rwt_Trav_rec( p, Rwt_Regular(pNode->p1), pVolume );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_ManIncTravId( Rwt_Man_t * p )
+{
+    Rwt_Node_t * pNode;
+    int i;
+    if ( p->nTravIds++ < 0x8FFFFFFF )
+        return;
+    Vec_PtrForEachEntry( Rwt_Node_t *, p->vForest, pNode, i )
+        pNode->TravId = 0;
+    p->nTravIds = 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rwt_ManNodeVolume( Rwt_Man_t * p, Rwt_Node_t * p0, Rwt_Node_t * p1 )
+{
+    int Volume = 0;
+    Rwt_ManIncTravId( p );
+    Rwt_Trav_rec( p, p0, &Volume );
+    Rwt_Trav_rec( p, p1, &Volume );
+    return Volume;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Loads data.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rwt_ManLoadFromArray( Rwt_Man_t * p, int fVerbose )
+{
+    unsigned short * pArray = s_RwtAigSubgraphs;
+    Rwt_Node_t * p0, * p1;
+    unsigned Entry0, Entry1;
+    int Level, Volume, nEntries, fExor;
+    int i;
+    abctime clk = Abc_Clock();
+
+    // reconstruct the forest
+    for ( i = 0; ; i++ )
+    {
+        Entry0 = pArray[2*i + 0];
+        Entry1 = pArray[2*i + 1];
+        if ( Entry0 == 0 && Entry1 == 0 )
+            break;
+        // get EXOR flag
+        fExor = (Entry0 & 1);
+        Entry0 >>= 1;
+        // get the nodes
+        p0 = (Rwt_Node_t *)p->vForest->pArray[Entry0 >> 1];
+        p1 = (Rwt_Node_t *)p->vForest->pArray[Entry1 >> 1];
+        // compute the level and volume of the new nodes
+        Level  = 1 + RWT_MAX( p0->Level, p1->Level );
+        Volume = 1 + Rwt_ManNodeVolume( p, p0, p1 );
+        // set the complemented attributes
+        p0 = Rwt_NotCond( p0, (Entry0 & 1) );
+        p1 = Rwt_NotCond( p1, (Entry1 & 1) );
+        // add the node
+//        Rwt_ManTryNode( p, p0, p1, Level, Volume );
+        Rwt_ManAddNode( p, p0, p1, fExor, Level, Volume + fExor );
+    }
+    nEntries = i - 1;
+    if ( fVerbose )
+    {
+        printf( "The number of classes = %d. Canonical nodes = %d.\n", p->nClasses, p->nAdded );
+        printf( "The number of nodes loaded = %d.  ", nEntries );  ABC_PRT( "Loading", Abc_Clock() - clk );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create practical classes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Rwt_ManGetPractical( Rwt_Man_t * p )
+{
+    char * pPractical;
+    int i;
+    pPractical = ABC_ALLOC( char, p->nFuncs );
+    memset( pPractical, 0, sizeof(char) * p->nFuncs );
+    pPractical[0] = 1;
+    for ( i = 1; ; i++ )
+    {
+        if ( s_RwtPracticalClasses[i] == 0 )
+            break;
+        pPractical[ s_RwtPracticalClasses[i] ] = 1;
+    }
+    return pPractical;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+// the following 135 practical NPN classes of 4-variable functions were computed
+// by considering all 4-input cuts appearing in IWLS, MCNC, and ISCAS benchmarks
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/sfm/module.make b/abc-build/src/opt/sfm/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sfm/module.make
@@ -0,0 +1,5 @@
+SRC +=	src/opt/sfm/sfmCnf.c \
+	src/opt/sfm/sfmCore.c \
+	src/opt/sfm/sfmNtk.c \
+	src/opt/sfm/sfmSat.c \
+	src/opt/sfm/sfmWin.c
diff --git a/abc-build/src/opt/sfm/sfm.h b/abc-build/src/opt/sfm/sfm.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sfm/sfm.h
@@ -0,0 +1,90 @@
+/**CFile****************************************************************
+
+  FileName    [sfm.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based optimization using internal don't-cares.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: sfm.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__opt_sfm__h
+#define ABC__opt_sfm__h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "misc/vec/vecWec.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Sfm_Ntk_t_ Sfm_Ntk_t;
+typedef struct Sfm_Par_t_ Sfm_Par_t;
+struct Sfm_Par_t_
+{
+    int             nTfoLevMax;    // the maximum fanout levels
+    int             nFanoutMax;    // the maximum number of fanouts
+    int             nDepthMax;     // the maximum depth to try
+    int             nWinSizeMax;   // the maximum window size
+    int             nGrowthLevel;  // the maximum allowed growth in level
+    int             nBTLimit;      // the maximum number of conflicts in one SAT run
+    int             nNodesMax;     // the maximum number of nodes to try
+    int             nFirstFixed;   // the number of first nodes to be treated as fixed
+    int             fRrOnly;       // perform redundance removal
+    int             fArea;         // performs optimization for area
+    int             fMoreEffort;   // performs high-affort minimization
+    int             fVerbose;      // enable basic stats
+    int             fVeryVerbose;  // enable detailed stats
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== sfmCnf.c ==========================================================*/
+/*=== sfmCore.c ==========================================================*/
+extern void         Sfm_ParSetDefault( Sfm_Par_t * pPars );
+extern int          Sfm_NtkPerform( Sfm_Ntk_t * p, Sfm_Par_t * pPars );
+/*=== sfmNtk.c ==========================================================*/
+extern Sfm_Ntk_t *  Sfm_NtkConstruct( Vec_Wec_t * vFanins, int nPis, int nPos, Vec_Str_t * vFixed, Vec_Str_t * vEmpty, Vec_Wrd_t * vTruths );
+extern void         Sfm_NtkFree( Sfm_Ntk_t * p );
+extern Vec_Int_t *  Sfm_NodeReadFanins( Sfm_Ntk_t * p, int i );
+extern word *       Sfm_NodeReadTruth( Sfm_Ntk_t * p, int i );
+extern int          Sfm_NodeReadFixed( Sfm_Ntk_t * p, int i );
+extern int          Sfm_NodeReadUsed( Sfm_Ntk_t * p, int i );
+/*=== sfmWin.c ==========================================================*/
+extern Vec_Int_t *  Sfm_NtkDfs( Sfm_Ntk_t * p );
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/sfm/sfmCnf.c b/abc-build/src/opt/sfm/sfmCnf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sfm/sfmCnf.c
@@ -0,0 +1,179 @@
+/**CFile****************************************************************
+
+  FileName    [sfmCnf.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based optimization using internal don't-cares.]
+
+  Synopsis    [CNF computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: sfmCnf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sfmInt.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sfm_PrintCnf( Vec_Str_t * vCnf )
+{
+    char Entry;
+    int i, Lit;
+    Vec_StrForEachEntry( vCnf, Entry, i )
+    {
+        Lit = (int)Entry;
+        if ( Lit == -1 )
+            printf( "\n" );
+        else
+            printf( "%s%d ", Abc_LitIsCompl(Lit) ? "-":"", Abc_Lit2Var(Lit) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sfm_TruthToCnf( word Truth, int nVars, Vec_Int_t * vCover, Vec_Str_t * vCnf )
+{
+    Vec_StrClear( vCnf );
+    if ( Truth == 0 || ~Truth == 0 )
+    {
+//        assert( nVars == 0 );
+        Vec_StrPush( vCnf, (char)(Truth == 0) );
+        Vec_StrPush( vCnf, (char)-1 );
+        return 1;
+    }
+    else 
+    {
+        int i, k, c, RetValue, Literal, Cube, nCubes = 0;
+        assert( nVars > 0 );
+        for ( c = 0; c < 2; c ++ )
+        {
+            Truth = c ? ~Truth : Truth;
+            RetValue = Kit_TruthIsop( (unsigned *)&Truth, nVars, vCover, 0 );
+            assert( RetValue == 0 );
+            nCubes += Vec_IntSize( vCover );
+            Vec_IntForEachEntry( vCover, Cube, i )
+            {
+                for ( k = 0; k < nVars; k++ )
+                {
+                    Literal = 3 & (Cube >> (k << 1));
+                    if ( Literal == 1 )      // '0'  -> pos lit
+                        Vec_StrPush( vCnf, (char)Abc_Var2Lit(k, 0) );
+                    else if ( Literal == 2 ) // '1'  -> neg lit
+                        Vec_StrPush( vCnf, (char)Abc_Var2Lit(k, 1) );
+                    else if ( Literal != 0 )
+                        assert( 0 );
+                }
+                Vec_StrPush( vCnf, (char)Abc_Var2Lit(nVars, c) );
+                Vec_StrPush( vCnf, (char)-1 );
+            }
+        }
+        return nCubes;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Wec_t * Sfm_CreateCnf( Sfm_Ntk_t * p )
+{
+    Vec_Wec_t * vCnfs;
+    Vec_Str_t * vCnf, * vCnfBase;
+    word uTruth;
+    int i, nCubes;
+    vCnf = Vec_StrAlloc( 100 );
+    vCnfs = Vec_WecStart( p->nObjs );
+    Vec_WrdForEachEntryStartStop( p->vTruths, uTruth, i, p->nPis, Vec_WrdSize(p->vTruths)-p->nPos )
+    {
+        nCubes = Sfm_TruthToCnf( uTruth, Sfm_ObjFaninNum(p, i), p->vCover, vCnf );
+        vCnfBase = (Vec_Str_t *)Vec_WecEntry( vCnfs, i );
+        Vec_StrGrow( vCnfBase, Vec_StrSize(vCnf) );
+        memcpy( Vec_StrArray(vCnfBase), Vec_StrArray(vCnf), Vec_StrSize(vCnf) );
+        vCnfBase->nSize = Vec_StrSize(vCnf);
+    }
+    Vec_StrFree( vCnf );
+    return vCnfs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sfm_TranslateCnf( Vec_Wec_t * vRes, Vec_Str_t * vCnf, Vec_Int_t * vFaninMap, int iPivotVar )
+{
+    Vec_Int_t * vClause;
+    char Entry;
+    int i, Lit;
+    Vec_WecClear( vRes );
+    vClause = Vec_WecPushLevel( vRes );
+    Vec_StrForEachEntry( vCnf, Entry, i )
+    {
+        if ( (int)Entry == -1 )
+        {
+            vClause = Vec_WecPushLevel( vRes );
+            continue;
+        }
+        Lit = Abc_Lit2LitV( Vec_IntArray(vFaninMap), (int)Entry );
+        Lit = Abc_LitNotCond( Lit, Abc_Lit2Var(Lit) == iPivotVar );
+        Vec_IntPush( vClause, Lit );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/sfm/sfmCore.c b/abc-build/src/opt/sfm/sfmCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sfm/sfmCore.c
@@ -0,0 +1,300 @@
+/**CFile****************************************************************
+
+  FileName    [sfmCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based optimization using internal don't-cares.]
+
+  Synopsis    [Core procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: sfmCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sfmInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Setup parameter structure.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sfm_ParSetDefault( Sfm_Par_t * pPars )
+{
+    memset( pPars, 0, sizeof(Sfm_Par_t) );
+    pPars->nTfoLevMax   =    2;  // the maximum fanout levels
+    pPars->nFanoutMax   =   30;  // the maximum number of fanouts
+    pPars->nDepthMax    =   20;  // the maximum depth to try  
+    pPars->nWinSizeMax  =  300;  // the maximum window size
+    pPars->nGrowthLevel =    0;  // the maximum allowed growth in level
+    pPars->nBTLimit     = 5000;  // the maximum number of conflicts in one SAT run
+    pPars->fRrOnly      =    0;  // perform redundancy removal
+    pPars->fArea        =    0;  // performs optimization for area
+    pPars->fMoreEffort  =    0;  // performs high-affort minimization
+    pPars->fVerbose     =    0;  // enable basic stats
+    pPars->fVeryVerbose =    0;  // enable detailed stats
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints statistics.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sfm_NtkPrintStats( Sfm_Ntk_t * p )
+{
+    p->timeOther = p->timeTotal - p->timeWin - p->timeDiv - p->timeCnf - p->timeSat;
+    printf( "Nodes = %d. Try = %d. Resub = %d. Div = %d. SAT calls = %d. Timeouts = %d. MaxDivs = %d.\n",
+        Sfm_NtkNodeNum(p), p->nNodesTried, p->nRemoves + p->nResubs, p->nTotalDivs, p->nSatCalls, p->nTimeOuts, p->nMaxDivs );
+
+    printf( "Attempts :   " );
+    printf( "Remove %6d out of %6d (%6.2f %%)   ", p->nRemoves, p->nTryRemoves, 100.0*p->nRemoves/Abc_MaxInt(1, p->nTryRemoves) );
+    printf( "Resub  %6d out of %6d (%6.2f %%)   ", p->nResubs,  p->nTryResubs,  100.0*p->nResubs /Abc_MaxInt(1, p->nTryResubs)  );
+    printf( "\n" );
+
+    printf( "Reduction:   " );
+    printf( "Nodes  %6d out of %6d (%6.2f %%)   ", p->nTotalNodesBeg-p->nTotalNodesEnd, p->nTotalNodesBeg, 100.0*(p->nTotalNodesBeg-p->nTotalNodesEnd)/Abc_MaxInt(1, p->nTotalNodesBeg) );
+    printf( "Edges  %6d out of %6d (%6.2f %%)   ", p->nTotalEdgesBeg-p->nTotalEdgesEnd, p->nTotalEdgesBeg, 100.0*(p->nTotalEdgesBeg-p->nTotalEdgesEnd)/Abc_MaxInt(1, p->nTotalEdgesBeg) );
+    printf( "\n" );
+
+    ABC_PRTP( "Win", p->timeWin  ,  p->timeTotal );
+    ABC_PRTP( "Div", p->timeDiv  ,  p->timeTotal );
+    ABC_PRTP( "Cnf", p->timeCnf  ,  p->timeTotal );
+    ABC_PRTP( "Sat", p->timeSat  ,  p->timeTotal );
+    ABC_PRTP( "Oth", p->timeOther,  p->timeTotal );
+    ABC_PRTP( "ALL", p->timeTotal,  p->timeTotal );
+//    ABC_PRTP( "   ", p->time1    ,  p->timeTotal );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs resubstitution for the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sfm_NodeResubSolve( Sfm_Ntk_t * p, int iNode, int f, int fRemoveOnly )
+{
+    int fSkipUpdate  = 0;
+    int fVeryVerbose = 0;//p->pPars->fVeryVerbose && Vec_IntSize(p->vDivs) < 200;// || pNode->Id == 556;
+    int i, iFanin, iVar = -1;
+    word uTruth, uSign, uMask;
+    abctime clk;
+    assert( Sfm_ObjIsNode(p, iNode) );
+    assert( f >= 0 && f < Sfm_ObjFaninNum(p, iNode) );
+    p->nTryRemoves++;
+    // report init stats
+    if ( p->pPars->fVeryVerbose )
+        printf( "%5d : Lev =%3d. Leaf =%3d.  Node =%3d.  Div=%3d.  Fanin =%4d (%d/%d). MFFC = %d\n", 
+            iNode, Sfm_ObjLevel(p, iNode), 0, Vec_IntSize(p->vNodes), Vec_IntSize(p->vDivs), 
+            Sfm_ObjFanin(p, iNode, f), f, Sfm_ObjFaninNum(p, iNode), Sfm_ObjMffcSize(p, Sfm_ObjFanin(p, iNode, f)) );
+    // clean simulation info
+    p->nCexes = 0;
+    Vec_WrdFill( p->vDivCexes, Vec_IntSize(p->vDivs), 0 );
+    // try removing the critical fanin
+    Vec_IntClear( p->vDivIds );
+    Sfm_ObjForEachFanin( p, iNode, iFanin, i )
+        if ( i != f )
+            Vec_IntPush( p->vDivIds, Sfm_ObjSatVar(p, iFanin) );
+clk = Abc_Clock();
+    uTruth = Sfm_ComputeInterpolant( p );
+p->timeSat += Abc_Clock() - clk;
+    // analyze outcomes
+    if ( uTruth == SFM_SAT_UNDEC )
+    {
+        p->nTimeOuts++;
+        return 0;
+    }
+    if ( uTruth != SFM_SAT_SAT )
+        goto finish;
+    if ( fRemoveOnly || p->pPars->fRrOnly || Vec_IntSize(p->vDivs) == 0 )
+        return 0;
+
+    p->nTryResubs++;
+    if ( fVeryVerbose )
+    {
+        for ( i = 0; i < 9; i++ )
+            printf( " " );
+        for ( i = 0; i < Vec_IntSize(p->vDivs); i++ )
+            printf( "%d", i % 10 );
+        printf( "\n" );
+    }
+    while ( 1 ) 
+    {
+        if ( fVeryVerbose )
+        {
+            printf( "%3d: %3d ", p->nCexes, iVar );
+            Vec_WrdForEachEntry( p->vDivCexes, uSign, i )
+                printf( "%d", Abc_InfoHasBit((unsigned *)&uSign, p->nCexes-1) );
+            printf( "\n" );
+        }
+        // find the next divisor to try
+        uMask = (~(word)0) >> (64 - p->nCexes);
+        Vec_WrdForEachEntry( p->vDivCexes, uSign, iVar )
+            if ( uSign == uMask )
+                break;
+        if ( iVar == Vec_IntSize(p->vDivs) )
+            return 0;
+        // try replacing the critical fanin
+        Vec_IntPush( p->vDivIds, Sfm_ObjSatVar(p, Vec_IntEntry(p->vDivs, iVar)) );
+clk = Abc_Clock();
+        uTruth = Sfm_ComputeInterpolant( p );
+p->timeSat += Abc_Clock() - clk;
+        // analyze outcomes
+        if ( uTruth == SFM_SAT_UNDEC )
+        {
+            p->nTimeOuts++;
+            return 0;
+        }
+        if ( uTruth != SFM_SAT_SAT )
+            goto finish;
+        if ( p->nCexes == 64 )
+            return 0;
+        // remove the last variable
+        Vec_IntPop( p->vDivIds );
+    }
+finish:
+    if ( p->pPars->fVeryVerbose )
+    {
+        if ( iVar == -1 )
+            printf( "Node %d: Fanin %d (%d) can be removed.  ", iNode, f, Sfm_ObjFanin(p, iNode, f) );
+        else
+            printf( "Node %d: Fanin %d (%d) can be replaced by divisor %d (%d).   ", 
+            iNode, f, Sfm_ObjFanin(p, iNode, f), iVar, Vec_IntEntry(p->vDivs, iVar) );
+        Kit_DsdPrintFromTruth( (unsigned *)&uTruth, Vec_IntSize(p->vDivIds) ); printf( "\n" );
+    }
+    if ( iVar == -1 )
+        p->nRemoves++;
+    else
+        p->nResubs++;
+    if ( fSkipUpdate )
+        return 0;
+    // update the network
+    Sfm_NtkUpdate( p, iNode, f, (iVar == -1 ? iVar : Vec_IntEntry(p->vDivs, iVar)), uTruth );
+    return 1;
+ }
+int Sfm_NodeResub( Sfm_Ntk_t * p, int iNode )
+{
+    int i, iFanin;
+    p->nNodesTried++;
+    // prepare SAT solver
+    if ( !Sfm_NtkCreateWindow( p, iNode, p->pPars->fVeryVerbose ) )
+        return 0;
+    if ( !Sfm_NtkWindowToSolver( p ) )
+        return 0;
+    // try replacing area critical fanins
+    Sfm_ObjForEachFanin( p, iNode, iFanin, i )
+        if ( Sfm_ObjIsNode(p, iFanin) && Sfm_ObjFanoutNum(p, iFanin) == 1 )
+        {
+            if ( Sfm_NodeResubSolve( p, iNode, i, 0 ) )
+                return 1;
+        }
+    if ( p->pPars->fArea )
+        return 0;
+    // try removing redundant edges
+    Sfm_ObjForEachFanin( p, iNode, iFanin, i )
+        if ( !(Sfm_ObjIsNode(p, iFanin) && Sfm_ObjFanoutNum(p, iFanin) == 1) )
+        {
+            if ( Sfm_NodeResubSolve( p, iNode, i, 1 ) )
+                return 1;
+        }
+/*
+    // try replacing area critical fanins while adding two new fanins
+    if ( Sfm_ObjFaninNum(p, iNode) < p->nFaninMax )
+        Abc_ObjForEachFanin( pNode, pFanin, i )
+            if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+            {
+                if ( Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) )
+                    return 1;
+            }
+*/
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sfm_NtkPerform( Sfm_Ntk_t * p, Sfm_Par_t * pPars )
+{
+    int i, k, Counter = 0;
+    p->timeTotal = Abc_Clock();
+    if ( pPars->fVerbose && Vec_StrSum(p->vFixed) > 0 )
+        printf( "Performing MFS with %d fixed objects.\n", Vec_StrSum(p->vFixed) );
+    p->pPars = pPars;
+    Sfm_NtkPrepare( p );
+//    Sfm_ComputeInterpolantCheck( p );
+//    return 0;
+    p->nTotalNodesBeg = Vec_WecSizeUsedLimits( &p->vFanins, Sfm_NtkPiNum(p), Vec_WecSize(&p->vFanins) - Sfm_NtkPoNum(p) );
+    p->nTotalEdgesBeg = Vec_WecSizeSize(&p->vFanins) - Sfm_NtkPoNum(p);
+    Sfm_NtkForEachNode( p, i )
+    {
+        if ( Sfm_ObjIsFixed( p, i ) )
+            continue;
+        if ( p->pPars->nDepthMax && Sfm_ObjLevel(p, i) > p->pPars->nDepthMax )
+            continue;
+        if ( Sfm_ObjFaninNum(p, i) < 2 || Sfm_ObjFaninNum(p, i) > 6 )
+            continue;
+        for ( k = 0; Sfm_NodeResub(p, i); k++ )
+        {
+//            Counter++;
+//            break;
+        }
+        Counter += (k > 0);
+        if ( pPars->nNodesMax && Counter >= pPars->nNodesMax )
+            break;
+    }
+    p->nTotalNodesEnd = Vec_WecSizeUsedLimits( &p->vFanins, Sfm_NtkPiNum(p), Vec_WecSize(&p->vFanins) - Sfm_NtkPoNum(p) );
+    p->nTotalEdgesEnd = Vec_WecSizeSize(&p->vFanins) - Sfm_NtkPoNum(p);
+    p->timeTotal = Abc_Clock() - p->timeTotal;
+    if ( pPars->fVerbose )
+        Sfm_NtkPrintStats( p );
+    return Counter;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/sfm/sfmInt.h b/abc-build/src/opt/sfm/sfmInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sfm/sfmInt.h
@@ -0,0 +1,203 @@
+/**CFile****************************************************************
+
+  FileName    [rsbInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based optimization using internal don't-cares.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: rsbInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__opt_sfmInt__h
+#define ABC__opt_sfmInt__h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+#include "sat/bsat/satSolver.h"
+#include "sfm.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+#define SFM_FANIN_MAX 6
+#define SFM_SAT_UNDEC 0x1234567812345678
+#define SFM_SAT_SAT   0x8765432187654321
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+struct Sfm_Ntk_t_
+{
+    // parameters
+    Sfm_Par_t *       pPars;       // parameters
+    // objects
+    int               nPis;        // PI count (PIs should be first objects)
+    int               nPos;        // PO count (POs should be last objects)
+    int               nNodes;      // internal nodes
+    int               nObjs;       // total objects
+    int               nLevelMax;   // maximum level
+    // user data
+    Vec_Str_t *       vFixed;      // persistent objects
+    Vec_Str_t *       vEmpty;      // transparent objects
+    Vec_Wrd_t *       vTruths;     // truth tables
+    Vec_Wec_t         vFanins;     // fanins
+    // attributes
+    Vec_Wec_t         vFanouts;    // fanouts
+    Vec_Int_t         vLevels;     // logic level
+    Vec_Int_t         vLevelsR;    // logic level
+    Vec_Int_t         vCounts;     // fanin counters
+    Vec_Int_t         vId2Var;     // ObjId -> SatVar
+    Vec_Int_t         vVar2Id;     // SatVar -> ObjId
+    Vec_Wec_t *       vCnfs;       // CNFs
+    Vec_Int_t *       vCover;      // temporary
+    // traversal IDs
+    Vec_Int_t         vTravIds;    // traversal IDs
+    Vec_Int_t         vTravIds2;   // traversal IDs
+    int               nTravIds;    // traversal IDs
+    int               nTravIds2;   // traversal IDs
+    // window
+    int               iPivotNode;  // window pivot
+    Vec_Int_t *       vNodes;      // internal
+    Vec_Int_t *       vDivs;       // divisors
+    Vec_Int_t *       vRoots;      // roots
+    Vec_Int_t *       vTfo;        // TFO (excluding iNode)
+    // SAT solving
+    sat_solver *      pSat;        // SAT solver
+    int               nSatVars;    // the number of variables
+    int               nTryRemoves; // number of fanin removals
+    int               nTryResubs;  // number of resubstitutions
+    int               nRemoves;    // number of fanin removals
+    int               nResubs;     // number of resubstitutions
+    // counter-examples
+    int               nCexes;      // number of CEXes
+    Vec_Wrd_t *       vDivCexes;   // counter-examples
+    // intermediate data
+    Vec_Int_t *       vOrder;      // object order
+    Vec_Int_t *       vDivVars;    // divisor SAT variables
+    Vec_Int_t *       vDivIds;     // divisors indexes
+    Vec_Int_t *       vLits;       // literals
+    Vec_Int_t *       vValues;     // SAT variable values
+    Vec_Wec_t *       vClauses;    // CNF clauses for the node
+    Vec_Int_t *       vFaninMap;   // mapping fanins into their SAT vars
+    // nodes
+    int               nTotalNodesBeg;
+    int               nTotalEdgesBeg;
+    int               nTotalNodesEnd;
+    int               nTotalEdgesEnd;
+    int               nNodesTried;
+    int               nTotalDivs;
+    int               nSatCalls;
+    int               nTimeOuts;
+    int               nMaxDivs;
+    // runtime
+    abctime           timeWin;
+    abctime           timeDiv;
+    abctime           timeCnf;
+    abctime           timeSat;
+    abctime           timeOther;
+    abctime           timeTotal;
+//    abctime           time1;
+};
+
+static inline int  Sfm_NtkPiNum( Sfm_Ntk_t * p )                        { return p->nPis;                                   }
+static inline int  Sfm_NtkPoNum( Sfm_Ntk_t * p )                        { return p->nPos;                                   }
+static inline int  Sfm_NtkNodeNum( Sfm_Ntk_t * p )                      { return p->nObjs - p->nPis - p->nPos;              }
+
+static inline int  Sfm_ObjIsPi( Sfm_Ntk_t * p, int i )                  { return i < p->nPis;                               }
+static inline int  Sfm_ObjIsPo( Sfm_Ntk_t * p, int i )                  { return i + p->nPos >= p->nObjs;                   }
+static inline int  Sfm_ObjIsNode( Sfm_Ntk_t * p, int i )                { return i >= p->nPis && i + p->nPos < p->nObjs;    }
+static inline int  Sfm_ObjIsFixed( Sfm_Ntk_t * p, int i )               { return Vec_StrEntry(p->vFixed, i);                }
+static inline int  Sfm_ObjAddsLevelArray( Vec_Str_t * p, int i )        { return p == NULL || Vec_StrEntry(p, i) == 0;      }
+static inline int  Sfm_ObjAddsLevel( Sfm_Ntk_t * p, int i )             { return Sfm_ObjAddsLevelArray(p->vEmpty, i);       }
+
+static inline Vec_Int_t * Sfm_ObjFiArray( Sfm_Ntk_t * p, int i )        { return Vec_WecEntry(&p->vFanins, i);              }
+static inline Vec_Int_t * Sfm_ObjFoArray( Sfm_Ntk_t * p, int i )        { return Vec_WecEntry(&p->vFanouts, i);             }
+
+static inline int  Sfm_ObjFaninNum( Sfm_Ntk_t * p, int i )              { return Vec_IntSize(Sfm_ObjFiArray(p, i));         }
+static inline int  Sfm_ObjFanoutNum( Sfm_Ntk_t * p, int i )             { return Vec_IntSize(Sfm_ObjFoArray(p, i));         }
+
+static inline int  Sfm_ObjRefIncrement( Sfm_Ntk_t * p, int iObj )       { return ++Sfm_ObjFoArray(p, iObj)->nSize;          } 
+static inline int  Sfm_ObjRefDecrement( Sfm_Ntk_t * p, int iObj )       { return --Sfm_ObjFoArray(p, iObj)->nSize;          } 
+
+static inline int  Sfm_ObjFanin( Sfm_Ntk_t * p, int i, int k )          { return Vec_IntEntry(Sfm_ObjFiArray(p, i), k);     }
+static inline int  Sfm_ObjFanout( Sfm_Ntk_t * p, int i, int k )         { return Vec_IntEntry(Sfm_ObjFoArray(p, i), k);     }
+
+static inline int  Sfm_ObjSatVar( Sfm_Ntk_t * p, int iObj )             { assert(Vec_IntEntry(&p->vId2Var, iObj) > 0); return Vec_IntEntry(&p->vId2Var, iObj);  }
+static inline void Sfm_ObjSetSatVar( Sfm_Ntk_t * p, int iObj, int Num ) { assert(Vec_IntEntry(&p->vId2Var, iObj) == -1); Vec_IntWriteEntry(&p->vId2Var, iObj, Num);  Vec_IntWriteEntry(&p->vVar2Id, Num, iObj);  }
+static inline void Sfm_ObjCleanSatVar( Sfm_Ntk_t * p, int Num )         { int iObj = Vec_IntEntry(&p->vVar2Id, Num); assert(Vec_IntEntry(&p->vId2Var, iObj) > 0); Vec_IntWriteEntry(&p->vId2Var, iObj, -1);  Vec_IntWriteEntry(&p->vVar2Id, Num, -1); }
+static inline void Sfm_NtkCleanVars( Sfm_Ntk_t * p )                    { int i; for ( i = 1; i < p->nSatVars; i++ )  if ( Vec_IntEntry(&p->vVar2Id, i) != -1 ) Sfm_ObjCleanSatVar( p, i ); }
+
+static inline int  Sfm_ObjLevel( Sfm_Ntk_t * p, int iObj )              { return Vec_IntEntry( &p->vLevels, iObj );                         }
+static inline void Sfm_ObjSetLevel( Sfm_Ntk_t * p, int iObj, int Lev )  { Vec_IntWriteEntry( &p->vLevels, iObj, Lev );                      }
+
+static inline int  Sfm_ObjLevelR( Sfm_Ntk_t * p, int iObj )             { return Vec_IntEntry( &p->vLevelsR, iObj );                        }
+static inline void Sfm_ObjSetLevelR( Sfm_Ntk_t * p, int iObj, int Lev ) { Vec_IntWriteEntry( &p->vLevelsR, iObj, Lev );                     }
+
+static inline int  Sfm_ObjUpdateFaninCount( Sfm_Ntk_t * p, int iObj )   { return Vec_IntAddToEntry(&p->vCounts, iObj, -1);                  }
+static inline void Sfm_ObjResetFaninCount( Sfm_Ntk_t * p, int iObj )    { Vec_IntWriteEntry(&p->vCounts, iObj, Sfm_ObjFaninNum(p, iObj)-1); }
+
+extern void        Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars );
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define Sfm_NtkForEachPi( p, i )                 for ( i = 0; i < p->nPis; i++ )
+#define Sfm_NtkForEachPo( p, i )                 for ( i = p->nObjs - p->nPos; i < p->nObjs; i++ )
+#define Sfm_NtkForEachNode( p, i )               for ( i = p->nPis; i + p->nPos < p->nObjs; i++ )
+#define Sfm_NtkForEachNodeReverse( p, i )        for ( i = p->nObjs - p->nPos - 1; i >= p->nPis; i-- )
+#define Sfm_ObjForEachFanin( p, Node, Fan, i )   for ( i = 0; i < Sfm_ObjFaninNum(p, Node)  && ((Fan = Sfm_ObjFanin(p, Node, i)), 1);  i++ )
+#define Sfm_ObjForEachFanout( p, Node, Fan, i )  for ( i = 0; i < Sfm_ObjFanoutNum(p, Node) && ((Fan = Sfm_ObjFanout(p, Node, i)), 1); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== sfmCnf.c ==========================================================*/
+extern void         Sfm_PrintCnf( Vec_Str_t * vCnf );
+extern int          Sfm_TruthToCnf( word Truth, int nVars, Vec_Int_t * vCover, Vec_Str_t * vCnf );
+extern Vec_Wec_t *  Sfm_CreateCnf( Sfm_Ntk_t * p );
+extern void         Sfm_TranslateCnf( Vec_Wec_t * vRes, Vec_Str_t * vCnf, Vec_Int_t * vFaninMap, int iPivotVar );
+/*=== sfmCore.c ==========================================================*/
+/*=== sfmNtk.c ==========================================================*/
+extern Sfm_Ntk_t *  Sfm_ConstructNetwork( Vec_Wec_t * vFanins, int nPis, int nPos );
+extern void         Sfm_NtkPrepare( Sfm_Ntk_t * p );
+extern void         Sfm_NtkUpdate( Sfm_Ntk_t * p, int iNode, int f, int iFaninNew, word uTruth );
+/*=== sfmSat.c ==========================================================*/
+extern int          Sfm_NtkWindowToSolver( Sfm_Ntk_t * p );
+extern word         Sfm_ComputeInterpolant( Sfm_Ntk_t * p );
+/*=== sfmWin.c ==========================================================*/
+extern int          Sfm_ObjMffcSize( Sfm_Ntk_t * p, int iObj );
+extern int          Sfm_NtkCreateWindow( Sfm_Ntk_t * p, int iNode, int fVerbose );
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/sfm/sfmNtk.c b/abc-build/src/opt/sfm/sfmNtk.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sfm/sfmNtk.c
@@ -0,0 +1,380 @@
+/**CFile****************************************************************
+
+  FileName    [sfmNtk.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based optimization using internal don't-cares.]
+
+  Synopsis    [Logic network.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: sfmNtk.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sfmInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sfm_CheckConsistency( Vec_Wec_t * vFanins, int nPis, int nPos, Vec_Str_t * vFixed )
+{
+    Vec_Int_t * vArray;
+    int i, k, Fanin;
+    // check entries
+    Vec_WecForEachLevel( vFanins, vArray, i )
+    {
+        // PIs have no fanins
+        if ( i < nPis )
+            assert( Vec_IntSize(vArray) == 0 && Vec_StrEntry(vFixed, i) == (char)0 );
+        // nodes are in a topo order; POs cannot be fanins
+        Vec_IntForEachEntry( vArray, Fanin, k )
+            assert( Fanin < i && Fanin + nPos < Vec_WecSize(vFanins) );
+        // POs have one fanout
+        if ( i + nPos >= Vec_WecSize(vFanins) )
+            assert( Vec_IntSize(vArray) == 1 && Vec_StrEntry(vFixed, i) == (char)0 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sfm_CreateFanout( Vec_Wec_t * vFanins, Vec_Wec_t * vFanouts )
+{
+    Vec_Int_t * vArray;
+    int i, k, Fanin;
+    // count fanouts
+    Vec_WecInit( vFanouts, Vec_WecSize(vFanins) );
+    Vec_WecForEachLevel( vFanins, vArray, i )
+        Vec_IntForEachEntry( vArray, Fanin, k )
+            Vec_WecEntry( vFanouts, Fanin )->nSize++;
+    // allocate fanins
+    Vec_WecForEachLevel( vFanouts, vArray, i )
+    {
+        k = vArray->nSize; vArray->nSize = 0;
+        Vec_IntGrow( vArray, k );
+    }
+    // add fanouts
+    Vec_WecForEachLevel( vFanins, vArray, i )
+        Vec_IntForEachEntry( vArray, Fanin, k )
+            Vec_IntPush( Vec_WecEntry( vFanouts, Fanin ), i );
+    // verify
+    Vec_WecForEachLevel( vFanouts, vArray, i )
+        assert( Vec_IntSize(vArray) == Vec_IntCap(vArray) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Sfm_ObjLevelNew( Vec_Int_t * vArray, Vec_Int_t * vLevels, int fAddLevel )
+{
+    int k, Fanin, Level = 0;
+    Vec_IntForEachEntry( vArray, Fanin, k )
+        Level = Abc_MaxInt( Level, Vec_IntEntry(vLevels, Fanin) );
+    return Level + fAddLevel;
+}
+void Sfm_CreateLevel( Vec_Wec_t * vFanins, Vec_Int_t * vLevels, Vec_Str_t * vEmpty )
+{
+    Vec_Int_t * vArray;
+    int i;
+    assert( Vec_IntSize(vLevels) == 0 );
+    Vec_IntFill( vLevels, Vec_WecSize(vFanins), 0 );
+    Vec_WecForEachLevel( vFanins, vArray, i )
+        Vec_IntWriteEntry( vLevels, i, Sfm_ObjLevelNew(vArray, vLevels, Sfm_ObjAddsLevelArray(vEmpty, i)) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Sfm_ObjLevelNewR( Vec_Int_t * vArray, Vec_Int_t * vLevelsR, int fAddLevel )
+{
+    int k, Fanout, LevelR = 0;
+    Vec_IntForEachEntry( vArray, Fanout, k )
+        LevelR = Abc_MaxInt( LevelR, Vec_IntEntry(vLevelsR, Fanout) );
+    return LevelR + fAddLevel;
+}
+void Sfm_CreateLevelR( Vec_Wec_t * vFanouts, Vec_Int_t * vLevelsR, Vec_Str_t * vEmpty )
+{
+    Vec_Int_t * vArray;
+    int i;
+    assert( Vec_IntSize(vLevelsR) == 0 );
+    Vec_IntFill( vLevelsR, Vec_WecSize(vFanouts), 0 );
+    Vec_WecForEachLevelReverse( vFanouts, vArray, i )
+        Vec_IntWriteEntry( vLevelsR, i, Sfm_ObjLevelNewR(vArray, vLevelsR, Sfm_ObjAddsLevelArray(vEmpty, i)) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Sfm_Ntk_t * Sfm_NtkConstruct( Vec_Wec_t * vFanins, int nPis, int nPos, Vec_Str_t * vFixed, Vec_Str_t * vEmpty, Vec_Wrd_t * vTruths )
+{
+    Sfm_Ntk_t * p;
+    Sfm_CheckConsistency( vFanins, nPis, nPos, vFixed );
+    p = ABC_CALLOC( Sfm_Ntk_t, 1 );
+    p->nObjs    = Vec_WecSize( vFanins );
+    p->nPis     = nPis;
+    p->nPos     = nPos;
+    p->nNodes   = p->nObjs - p->nPis - p->nPos;
+    // user data
+    p->vFixed   = vFixed;
+    p->vEmpty   = vEmpty;
+    p->vTruths  = vTruths;
+    p->vFanins  = *vFanins;
+    ABC_FREE( vFanins );
+    // attributes
+    Sfm_CreateFanout( &p->vFanins, &p->vFanouts );
+    Sfm_CreateLevel( &p->vFanins, &p->vLevels, vEmpty );
+    Sfm_CreateLevelR( &p->vFanouts, &p->vLevelsR, vEmpty );
+    Vec_IntFill( &p->vCounts,   p->nObjs,  0 );
+    Vec_IntFill( &p->vTravIds,  p->nObjs,  0 );
+    Vec_IntFill( &p->vTravIds2, p->nObjs,  0 );
+    Vec_IntFill( &p->vId2Var,   2*p->nObjs, -1 );
+    Vec_IntFill( &p->vVar2Id,   2*p->nObjs, -1 );
+    p->vCover   = Vec_IntAlloc( 1 << 16 );
+    p->vCnfs    = Sfm_CreateCnf( p );
+    return p;
+}
+void Sfm_NtkPrepare( Sfm_Ntk_t * p )
+{
+    p->nLevelMax = Vec_IntFindMax(&p->vLevels) + p->pPars->nGrowthLevel;
+    p->vNodes    = Vec_IntAlloc( 1000 );
+    p->vDivs     = Vec_IntAlloc( 100 );
+    p->vRoots    = Vec_IntAlloc( 1000 );
+    p->vTfo      = Vec_IntAlloc( 1000 );
+    p->vDivCexes = Vec_WrdStart( p->pPars->nWinSizeMax );
+    p->vOrder    = Vec_IntAlloc( 100 );
+    p->vDivVars  = Vec_IntAlloc( 100 );
+    p->vDivIds   = Vec_IntAlloc( 1000 );
+    p->vLits     = Vec_IntAlloc( 100 );
+    p->vValues   = Vec_IntAlloc( 100 );
+    p->vClauses  = Vec_WecAlloc( 100 );
+    p->vFaninMap = Vec_IntAlloc( 10 );
+    p->pSat      = sat_solver_new();
+    sat_solver_setnvars( p->pSat, p->pPars->nWinSizeMax );
+}
+void Sfm_NtkFree( Sfm_Ntk_t * p )
+{
+    // user data
+    Vec_StrFree( p->vFixed );
+    Vec_StrFreeP( &p->vEmpty );
+    Vec_WrdFree( p->vTruths );
+    Vec_WecErase( &p->vFanins );
+    // attributes
+    Vec_WecErase( &p->vFanouts );
+    ABC_FREE( p->vLevels.pArray );
+    ABC_FREE( p->vLevelsR.pArray );
+    ABC_FREE( p->vCounts.pArray );
+    ABC_FREE( p->vTravIds.pArray );
+    ABC_FREE( p->vTravIds2.pArray );
+    ABC_FREE( p->vId2Var.pArray );
+    ABC_FREE( p->vVar2Id.pArray );
+    Vec_WecFree( p->vCnfs );
+    Vec_IntFree( p->vCover );
+    // other data
+    Vec_IntFreeP( &p->vNodes );
+    Vec_IntFreeP( &p->vDivs  );
+    Vec_IntFreeP( &p->vRoots );
+    Vec_IntFreeP( &p->vTfo   );
+    Vec_WrdFreeP( &p->vDivCexes );
+    Vec_IntFreeP( &p->vOrder );
+    Vec_IntFreeP( &p->vDivVars );
+    Vec_IntFreeP( &p->vDivIds );
+    Vec_IntFreeP( &p->vLits  );
+    Vec_IntFreeP( &p->vValues );
+    Vec_WecFreeP( &p->vClauses );
+    Vec_IntFreeP( &p->vFaninMap );
+    if ( p->pSat  ) sat_solver_delete( p->pSat );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs resubstitution for the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sfm_NtkRemoveFanin( Sfm_Ntk_t * p, int iNode, int iFanin )
+{
+    int RetValue;
+    assert( Sfm_ObjIsNode(p, iNode) );
+    assert( !Sfm_ObjIsPo(p, iFanin) );
+    RetValue = Vec_IntRemove( Sfm_ObjFiArray(p, iNode), iFanin );
+    assert( RetValue );
+    RetValue = Vec_IntRemove( Sfm_ObjFoArray(p, iFanin), iNode );
+    assert( RetValue );
+}
+void Sfm_NtkAddFanin( Sfm_Ntk_t * p, int iNode, int iFanin )
+{
+    if ( iFanin < 0 )
+        return;
+    assert( Sfm_ObjIsNode(p, iNode) );
+    assert( !Sfm_ObjIsPo(p, iFanin) );
+    assert( Vec_IntFind( Sfm_ObjFiArray(p, iNode), iFanin ) == -1 );
+    assert( Vec_IntFind( Sfm_ObjFoArray(p, iFanin), iNode ) == -1 );
+    Vec_IntPush( Sfm_ObjFiArray(p, iNode), iFanin );
+    Vec_IntPush( Sfm_ObjFoArray(p, iFanin), iNode );
+}
+void Sfm_NtkDeleteObj_rec( Sfm_Ntk_t * p, int iNode )
+{
+    int i, iFanin;
+    if ( Sfm_ObjFanoutNum(p, iNode) > 0 || Sfm_ObjIsPi(p, iNode) || Sfm_ObjIsFixed(p, iNode) )
+        return;
+    assert( Sfm_ObjIsNode(p, iNode) );
+    Sfm_ObjForEachFanin( p, iNode, iFanin, i )
+    {
+        int RetValue = Vec_IntRemove( Sfm_ObjFoArray(p, iFanin), iNode );  assert( RetValue );
+        Sfm_NtkDeleteObj_rec( p, iFanin );
+    }
+    Vec_IntClear( Sfm_ObjFiArray(p, iNode) );
+    Vec_WrdWriteEntry( p->vTruths, iNode, (word)0 );
+}
+void Sfm_NtkUpdateLevel_rec( Sfm_Ntk_t * p, int iNode )
+{
+    int i, iFanout;
+    int LevelNew = Sfm_ObjLevelNew( Sfm_ObjFiArray(p, iNode), &p->vLevels, Sfm_ObjAddsLevel(p, iNode) );
+    if ( LevelNew == Sfm_ObjLevel(p, iNode) )
+        return;
+    Sfm_ObjSetLevel( p, iNode, LevelNew );
+    Sfm_ObjForEachFanout( p, iNode, iFanout, i )
+        Sfm_NtkUpdateLevel_rec( p, iFanout );
+}
+void Sfm_NtkUpdateLevelR_rec( Sfm_Ntk_t * p, int iNode )
+{
+    int i, iFanin;
+    int LevelNew = Sfm_ObjLevelNewR( Sfm_ObjFoArray(p, iNode), &p->vLevelsR, Sfm_ObjAddsLevel(p, iNode) );
+    if ( LevelNew == Sfm_ObjLevelR(p, iNode) )
+        return;
+    Sfm_ObjSetLevelR( p, iNode, LevelNew );
+    Sfm_ObjForEachFanin( p, iNode, iFanin, i )
+        Sfm_NtkUpdateLevelR_rec( p, iFanin );
+}
+void Sfm_NtkUpdate( Sfm_Ntk_t * p, int iNode, int f, int iFaninNew, word uTruth )
+{
+    int iFanin = Sfm_ObjFanin( p, iNode, f );
+    assert( Sfm_ObjIsNode(p, iNode) );
+    assert( iFanin != iFaninNew );
+    if ( uTruth == 0 || ~uTruth == 0 )
+    {
+        Sfm_ObjForEachFanin( p, iNode, iFanin, f )
+        {
+            int RetValue = Vec_IntRemove( Sfm_ObjFoArray(p, iFanin), iNode );  assert( RetValue );
+            Sfm_NtkDeleteObj_rec( p, iFanin );
+        }
+        Vec_IntClear( Sfm_ObjFiArray(p, iNode) );
+    }
+    else
+    {
+        // replace old fanin by new fanin
+        Sfm_NtkRemoveFanin( p, iNode, iFanin );
+        Sfm_NtkAddFanin( p, iNode, iFaninNew );
+        // recursively remove MFFC
+        Sfm_NtkDeleteObj_rec( p, iFanin );
+    }
+    // update logic level
+    Sfm_NtkUpdateLevel_rec( p, iNode );
+    if ( iFaninNew != -1 )
+        Sfm_NtkUpdateLevelR_rec( p, iFaninNew );
+    if ( Sfm_ObjFanoutNum(p, iFanin) > 0 )
+        Sfm_NtkUpdateLevelR_rec( p, iFanin );
+    // update truth table
+    Vec_WrdWriteEntry( p->vTruths, iNode, uTruth );
+    Sfm_TruthToCnf( uTruth, Sfm_ObjFaninNum(p, iNode), p->vCover, (Vec_Str_t *)Vec_WecEntry(p->vCnfs, iNode) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Public APIs of this network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t *  Sfm_NodeReadFanins( Sfm_Ntk_t * p, int i )
+{
+    return Vec_WecEntry( &p->vFanins, i );
+}
+word * Sfm_NodeReadTruth( Sfm_Ntk_t * p, int i )
+{
+    return Vec_WrdEntryP( p->vTruths, i );
+}
+int Sfm_NodeReadFixed( Sfm_Ntk_t * p, int i )
+{
+    return (int)Vec_StrEntry( p->vFixed, i );
+}
+int Sfm_NodeReadUsed( Sfm_Ntk_t * p, int i )
+{
+    return (Sfm_ObjFaninNum(p, i) > 0) || (Sfm_ObjFanoutNum(p, i) > 0);
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/sfm/sfmSat.c b/abc-build/src/opt/sfm/sfmSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sfm/sfmSat.c
@@ -0,0 +1,271 @@
+/**CFile****************************************************************
+
+  FileName    [sfmSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based optimization using internal don't-cares.]
+
+  Synopsis    [SAT-based procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: sfmSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sfmInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static word s_Truths6[6] = {
+    ABC_CONST(0xAAAAAAAAAAAAAAAA),
+    ABC_CONST(0xCCCCCCCCCCCCCCCC),
+    ABC_CONST(0xF0F0F0F0F0F0F0F0),
+    ABC_CONST(0xFF00FF00FF00FF00),
+    ABC_CONST(0xFFFF0000FFFF0000),
+    ABC_CONST(0xFFFFFFFF00000000)
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Converts a window into a SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sfm_NtkWindowToSolver( Sfm_Ntk_t * p )
+{
+    // p->vOrder contains all variables in the window in a good order
+    // p->vDivs is a subset of nodes in p->vOrder used as divisor candidates
+    // p->vTfo contains TFO of the node (does not include node)
+    // p->vRoots contains roots of the TFO of the node (may include node)
+    Vec_Int_t * vClause;
+    int RetValue, iNode = -1, iFanin, i, k;
+    abctime clk = Abc_Clock();
+//    if ( p->pSat )
+//        printf( "%d  ", p->pSat->stats.learnts );
+    sat_solver_restart( p->pSat );
+    sat_solver_setnvars( p->pSat, 1 + Vec_IntSize(p->vOrder) + Vec_IntSize(p->vTfo) + Vec_IntSize(p->vRoots) + 10 );
+    // create SAT variables
+    Sfm_NtkCleanVars( p );
+    p->nSatVars = 1;
+    Vec_IntForEachEntry( p->vOrder, iNode, i )
+        Sfm_ObjSetSatVar( p, iNode, p->nSatVars++ );
+    // collect divisor variables
+    Vec_IntClear( p->vDivVars );
+    Vec_IntForEachEntry( p->vDivs, iNode, i )
+        Vec_IntPush( p->vDivVars, Sfm_ObjSatVar(p, iNode) );
+    // add CNF clauses for the TFI
+    Vec_IntForEachEntry( p->vOrder, iNode, i )
+    {
+        if ( Sfm_ObjIsPi(p, iNode) )
+            continue;
+        // collect fanin variables
+        Vec_IntClear( p->vFaninMap );
+        Sfm_ObjForEachFanin( p, iNode, iFanin, k )
+            Vec_IntPush( p->vFaninMap, Sfm_ObjSatVar(p, iFanin) );
+        Vec_IntPush( p->vFaninMap, Sfm_ObjSatVar(p, iNode) );
+        // generate CNF 
+        Sfm_TranslateCnf( p->vClauses, (Vec_Str_t *)Vec_WecEntry(p->vCnfs, iNode), p->vFaninMap, -1 );
+        // add clauses
+        Vec_WecForEachLevel( p->vClauses, vClause, k )
+        {
+            if ( Vec_IntSize(vClause) == 0 )
+                break;
+            RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause) );
+            assert( RetValue );
+        }
+    }
+    if ( Vec_IntSize(p->vTfo) > 0 )
+    {
+        assert( p->pPars->nTfoLevMax > 0 );
+        assert( Vec_IntSize(p->vRoots) > 0 );
+        assert( Vec_IntEntry(p->vTfo, 0) != p->iPivotNode );
+        // collect variables of root nodes
+        Vec_IntClear( p->vLits );
+        Vec_IntForEachEntry( p->vRoots, iNode, i )
+            Vec_IntPush( p->vLits, Sfm_ObjSatVar(p, iNode) );
+        // assign new variables to the TFO nodes
+        Vec_IntForEachEntry( p->vTfo, iNode, i )
+        {
+            Sfm_ObjCleanSatVar( p, Sfm_ObjSatVar(p, iNode) );
+            Sfm_ObjSetSatVar( p, iNode, p->nSatVars++ );
+        }
+        // add CNF clauses for the TFO
+        Vec_IntForEachEntry( p->vTfo, iNode, i )
+        {
+            assert( Sfm_ObjIsNode(p, iNode) );
+            // collect fanin variables
+            Vec_IntClear( p->vFaninMap );
+            Sfm_ObjForEachFanin( p, iNode, iFanin, k )
+                Vec_IntPush( p->vFaninMap, Sfm_ObjSatVar(p, iFanin) );
+            Vec_IntPush( p->vFaninMap, Sfm_ObjSatVar(p, iNode) );
+            // generate CNF 
+            Sfm_TranslateCnf( p->vClauses, (Vec_Str_t *)Vec_WecEntry(p->vCnfs, iNode), p->vFaninMap, Sfm_ObjSatVar(p, p->iPivotNode) );
+            // add clauses
+            Vec_WecForEachLevel( p->vClauses, vClause, k )
+            {
+                if ( Vec_IntSize(vClause) == 0 )
+                    break;
+                RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause) );
+                assert( RetValue );
+            }
+        }
+        // create XOR clauses for the roots
+        Vec_IntForEachEntry( p->vRoots, iNode, i )
+        {
+            sat_solver_add_xor( p->pSat, Vec_IntEntry(p->vLits, i), Sfm_ObjSatVar(p, iNode), p->nSatVars++, 0 );
+            Vec_IntWriteEntry( p->vLits, i, Abc_Var2Lit(p->nSatVars-1, 0) );
+        }
+        // make OR clause for the last nRoots variables
+        RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntArray(p->vLits) + Vec_IntSize(p->vLits) );
+        if ( RetValue == 0 )
+            return 0;
+    }
+    // finalize
+    RetValue = sat_solver_simplify( p->pSat );
+    p->timeCnf += Abc_Clock() - clk;
+    return RetValue;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Takes SAT solver and returns interpolant.]
+
+  Description [If interpolant does not exist, records difference variables.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word Sfm_ComputeInterpolant( Sfm_Ntk_t * p )
+{
+    word * pSign, uCube, uTruth = 0;
+    int status, i, Div, iVar, nFinal, * pFinal, nIter = 0;
+    int pLits[2], nVars = sat_solver_nvars( p->pSat );
+    sat_solver_setnvars( p->pSat, nVars + 1 );
+    pLits[0] = Abc_Var2Lit( Sfm_ObjSatVar(p, p->iPivotNode), 0 ); // F = 1
+    pLits[1] = Abc_Var2Lit( nVars, 0 ); // iNewLit
+    while ( 1 ) 
+    {
+        // find onset minterm
+        p->nSatCalls++;
+        status = sat_solver_solve( p->pSat, pLits, pLits + 2, p->pPars->nBTLimit, 0, 0, 0 );
+        if ( status == l_Undef )
+            return SFM_SAT_UNDEC;
+        if ( status == l_False )
+            return uTruth;
+        assert( status == l_True );
+        // remember variable values
+        Vec_IntClear( p->vValues );
+        Vec_IntForEachEntry( p->vDivVars, iVar, i )
+            Vec_IntPush( p->vValues, sat_solver_var_value(p->pSat, iVar) );
+        // collect divisor literals
+        Vec_IntClear( p->vLits );
+        Vec_IntPush( p->vLits, Abc_LitNot(pLits[0]) ); // F = 0
+        Vec_IntForEachEntry( p->vDivIds, Div, i )
+            Vec_IntPush( p->vLits, sat_solver_var_literal(p->pSat, Div) );
+        // check against offset
+        p->nSatCalls++;
+        status = sat_solver_solve( p->pSat, Vec_IntArray(p->vLits), Vec_IntArray(p->vLits) + Vec_IntSize(p->vLits), p->pPars->nBTLimit, 0, 0, 0 );
+        if ( status == l_Undef )
+            return SFM_SAT_UNDEC;
+        if ( status == l_True )
+            break;
+        assert( status == l_False );
+        // compute cube and add clause
+        nFinal = sat_solver_final( p->pSat, &pFinal );
+        uCube = ~(word)0;
+        Vec_IntClear( p->vLits );
+        Vec_IntPush( p->vLits, Abc_LitNot(pLits[1]) ); // NOT(iNewLit)
+        for ( i = 0; i < nFinal; i++ )
+        {
+            if ( pFinal[i] == pLits[0] )
+                continue;
+            Vec_IntPush( p->vLits, pFinal[i] );
+            iVar = Vec_IntFind( p->vDivIds, Abc_Lit2Var(pFinal[i]) );   assert( iVar >= 0 );
+            uCube &= Abc_LitIsCompl(pFinal[i]) ? s_Truths6[iVar] : ~s_Truths6[iVar];
+        }
+        uTruth |= uCube;
+        status = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntArray(p->vLits) + Vec_IntSize(p->vLits) );
+        assert( status );
+        nIter++;
+    }
+    assert( status == l_True );
+    // store the counter-example
+    Vec_IntForEachEntry( p->vDivVars, iVar, i )
+        if ( Vec_IntEntry(p->vValues, i) ^ sat_solver_var_value(p->pSat, iVar) ) // insert 1
+        {
+            pSign = Vec_WrdEntryP( p->vDivCexes, i );
+            assert( !Abc_InfoHasBit( (unsigned *)pSign, p->nCexes) );
+            Abc_InfoXorBit( (unsigned *)pSign, p->nCexes );
+        }
+    p->nCexes++;
+    return SFM_SAT_SAT;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks resubstitution.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sfm_ComputeInterpolantCheck( Sfm_Ntk_t * p )
+{
+    int iNode = 3;
+    int iDiv0 = 6;
+    int iDiv1 = 7;
+    word uTruth;
+//    int i;
+//    Sfm_NtkForEachNode( p, i )
+    {
+        Sfm_NtkCreateWindow( p, iNode, 1 );
+        Sfm_NtkWindowToSolver( p );
+
+        // collect SAT variables of divisors
+        Vec_IntClear( p->vDivIds );
+        Vec_IntPush( p->vDivIds, Sfm_ObjSatVar(p, iDiv0) );
+        Vec_IntPush( p->vDivIds, Sfm_ObjSatVar(p, iDiv1) );
+
+        uTruth = Sfm_ComputeInterpolant( p );
+
+        if ( uTruth == SFM_SAT_SAT )
+            printf( "The problem is SAT.\n" );
+        else if ( uTruth == SFM_SAT_UNDEC )
+            printf( "The problem is UNDEC.\n" );
+        else
+            Kit_DsdPrintFromTruth( (unsigned *)&uTruth, 2 ); printf( "\n" );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/sfm/sfmWin.c b/abc-build/src/opt/sfm/sfmWin.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sfm/sfmWin.c
@@ -0,0 +1,455 @@
+/**CFile****************************************************************
+
+  FileName    [sfmWin.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based optimization using internal don't-cares.]
+
+  Synopsis    [Structural window computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: sfmWin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sfmInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the MFFC size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sfm_ObjRef_rec( Sfm_Ntk_t * p, int iObj )
+{
+    int i, iFanin, Value, Count;
+    if ( Sfm_ObjIsPi(p, iObj) )
+        return 0;
+    assert( Sfm_ObjIsNode(p, iObj) );
+    Value = Sfm_ObjRefIncrement(p, iObj);
+    if ( Value > 1 )
+        return 0;
+    assert( Value == 1 );
+    Count = 1;
+    Sfm_ObjForEachFanin( p, iObj, iFanin, i )
+        Count += Sfm_ObjRef_rec( p, iFanin );
+    return Count;
+}
+int Sfm_ObjRef( Sfm_Ntk_t * p, int iObj )
+{
+    int i, iFanin, Count = 1;
+    Sfm_ObjForEachFanin( p, iObj, iFanin, i )
+        Count += Sfm_ObjRef_rec( p, iFanin );
+    return Count;
+}
+int Sfm_ObjDeref_rec( Sfm_Ntk_t * p, int iObj )
+{
+    int i, iFanin, Value, Count;
+    if ( Sfm_ObjIsPi(p, iObj) )
+        return 0;
+    assert( Sfm_ObjIsNode(p, iObj) );
+    Value = Sfm_ObjRefDecrement(p, iObj);
+    if ( Value > 0 )
+        return 0;
+    assert( Value == 0 );
+    Count = 1;
+    Sfm_ObjForEachFanin( p, iObj, iFanin, i )
+        Count += Sfm_ObjDeref_rec( p, iFanin );
+    return Count;
+}
+int Sfm_ObjDeref( Sfm_Ntk_t * p, int iObj )
+{
+    int i, iFanin, Count = 1;
+    Sfm_ObjForEachFanin( p, iObj, iFanin, i )
+        Count += Sfm_ObjDeref_rec( p, iFanin );
+    return Count;
+}
+int Sfm_ObjMffcSize( Sfm_Ntk_t * p, int iObj )
+{
+    int Count1, Count2;
+    if ( Sfm_ObjIsPi(p, iObj) )
+        return 0;
+    if ( Sfm_ObjFanoutNum(p, iObj) != 1 )
+        return 0;
+    assert( Sfm_ObjIsNode( p, iObj ) );
+    Count1 = Sfm_ObjDeref( p, iObj );
+    Count2 = Sfm_ObjRef( p, iObj );
+    assert( Count1 == Count2 );
+    return Count1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Working with traversal IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void  Sfm_NtkIncrementTravId( Sfm_Ntk_t * p )            { p->nTravIds++;                                            }       
+static inline void  Sfm_ObjSetTravIdCurrent( Sfm_Ntk_t * p, int Id )   { Vec_IntWriteEntry( &p->vTravIds, Id, p->nTravIds );       }
+static inline int   Sfm_ObjIsTravIdCurrent( Sfm_Ntk_t * p, int Id )    { return (Vec_IntEntry(&p->vTravIds, Id) == p->nTravIds);   }   
+static inline int   Sfm_ObjIsTravIdPrevious( Sfm_Ntk_t * p, int Id )   { return (Vec_IntEntry(&p->vTravIds, Id) == p->nTravIds-1); }   
+
+static inline void  Sfm_NtkIncrementTravId2( Sfm_Ntk_t * p )           { p->nTravIds2++;                                           }       
+static inline void  Sfm_ObjSetTravIdCurrent2( Sfm_Ntk_t * p, int Id )  { Vec_IntWriteEntry( &p->vTravIds2, Id, p->nTravIds2 );     }
+static inline int   Sfm_ObjIsTravIdCurrent2( Sfm_Ntk_t * p, int Id )   { return (Vec_IntEntry(&p->vTravIds2, Id) == p->nTravIds2); }   
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects used internal nodes in a topological order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sfm_NtkDfs_rec( Sfm_Ntk_t * p, int iNode, Vec_Int_t * vNodes )
+{
+    int i, iFanin;
+    if ( Sfm_ObjIsPi(p, iNode) )
+        return;
+    if ( Sfm_ObjIsTravIdCurrent(p, iNode) )
+        return;
+    Sfm_ObjSetTravIdCurrent(p, iNode);
+    Sfm_ObjForEachFanin( p, iNode, iFanin, i )
+        Sfm_NtkDfs_rec( p, iFanin, vNodes );
+    Vec_IntPush( vNodes, iNode );
+}
+Vec_Int_t * Sfm_NtkDfs( Sfm_Ntk_t * p )
+{
+    Vec_Int_t * vNodes;
+    int i;
+    vNodes = Vec_IntAlloc( p->nObjs );
+    Sfm_NtkIncrementTravId( p );
+    Sfm_NtkForEachPo( p, i )
+        Sfm_NtkDfs_rec( p, Sfm_ObjFanin(p, i, 0), vNodes );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check if this fanout overlaps with TFI cone of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sfm_NtkCheckOverlap_rec( Sfm_Ntk_t * p, int iThis, int iNode )
+{
+    int i, iFanin;
+    if ( Sfm_ObjIsTravIdCurrent2(p, iThis) || iThis == iNode )
+        return 0;
+//    if ( Sfm_ObjIsTravIdCurrent(p, iThis) )
+    if ( Sfm_ObjIsTravIdPrevious(p, iThis) )
+        return 1;
+    Sfm_ObjSetTravIdCurrent2(p, iThis);
+    Sfm_ObjForEachFanin( p, iThis, iFanin, i )
+        if ( Sfm_NtkCheckOverlap_rec(p, iFanin, iNode) )
+            return 1;
+    return 0;
+}
+int Sfm_NtkCheckOverlap( Sfm_Ntk_t * p, int iFan, int iNode )
+{
+    Sfm_NtkIncrementTravId2( p );
+    return Sfm_NtkCheckOverlap_rec( p, iFan, iNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively collects roots of the window.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Sfm_NtkCheckRoot( Sfm_Ntk_t * p, int iNode, int nLevelMax )
+{
+    int i, iFanout;
+    // the node is the root if one of the following is true:
+    // (1) the node has more than fanouts than the limit or has no fanouts (should not happen in general)
+    if ( Sfm_ObjFanoutNum(p, iNode) == 0 || Sfm_ObjFanoutNum(p, iNode) > p->pPars->nFanoutMax )
+        return 1;
+    // (2) the node has CO fanouts
+    // (3) the node has fanouts above the cutoff level
+    Sfm_ObjForEachFanout( p, iNode, iFanout, i )
+        if ( Sfm_ObjIsPo(p, iFanout) || Sfm_ObjLevel(p, iFanout) > nLevelMax )//|| !Sfm_NtkCheckOverlap(p, iFanout, iNode) )
+            return 1;
+    return 0;
+}
+void Sfm_NtkComputeRoots_rec( Sfm_Ntk_t * p, int iNode, int nLevelMax, Vec_Int_t * vRoots, Vec_Int_t * vTfo )
+{
+    int i, iFanout;
+    assert( Sfm_ObjIsNode(p, iNode) );
+    if ( Sfm_ObjIsTravIdCurrent(p, iNode) )
+        return;
+    Sfm_ObjSetTravIdCurrent(p, iNode);
+    if ( iNode != p->iPivotNode )
+        Vec_IntPush( vTfo, iNode );
+    // check if the node should be the root
+    if ( Sfm_NtkCheckRoot( p, iNode, nLevelMax ) )
+        Vec_IntPush( vRoots, iNode );
+    else // if not, explore its fanouts
+        Sfm_ObjForEachFanout( p, iNode, iFanout, i )
+            Sfm_NtkComputeRoots_rec( p, iFanout, nLevelMax, vRoots, vTfo );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects divisors of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sfm_NtkAddDivisors( Sfm_Ntk_t * p, int iNode, int nLevelMax )
+{
+    int i, iFanout;
+    Sfm_ObjForEachFanout( p, iNode, iFanout, i )
+    {
+        // skip some of the fanouts if the number is large
+        if ( p->pPars->nFanoutMax && i > p->pPars->nFanoutMax )
+            return;
+        // skip TFI nodes, PO nodes, or nodes with high logic level
+        if ( Sfm_ObjIsTravIdCurrent(p, iFanout) || Sfm_ObjIsPo(p, iFanout) || Sfm_ObjLevel(p, iFanout) > nLevelMax )
+            continue;
+        // handle single-input nodes
+        if ( Sfm_ObjFaninNum(p, iFanout) == 1 )
+            Vec_IntPush( p->vDivs, iFanout );
+        // visit node for the first time
+        else if ( !Sfm_ObjIsTravIdCurrent2(p, iFanout) )
+        {
+            assert( Sfm_ObjFaninNum(p, iFanout) > 1 );
+            Sfm_ObjSetTravIdCurrent2( p, iFanout );
+            Sfm_ObjResetFaninCount( p, iFanout );
+        }
+        // visit node again
+        else if ( Sfm_ObjUpdateFaninCount(p, iFanout) == 0 )
+            Vec_IntPush( p->vDivs, iFanout );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fixed object is useful when it has a non-fixed fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Sfm_ObjIsUseful( Sfm_Ntk_t * p, int iNode )
+{
+    int i, iFanout;
+    if ( !Sfm_ObjIsFixed(p, iNode) )
+        return 1;
+    Sfm_ObjForEachFanout( p, iNode, iFanout, i )
+        if ( !Sfm_ObjIsFixed(p, iFanout) )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes structural window.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sfm_NtkCollectTfi_rec( Sfm_Ntk_t * p, int iNode, Vec_Int_t * vNodes )
+{
+    int i, iFanin;
+    if ( Sfm_ObjIsTravIdCurrent( p, iNode ) )
+        return 0;
+    Sfm_ObjSetTravIdCurrent( p, iNode );
+    Sfm_ObjForEachFanin( p, iNode, iFanin, i )
+        if ( Sfm_NtkCollectTfi_rec( p, iFanin, vNodes ) )
+            return 1;
+    Vec_IntPush( vNodes, iNode );
+    return p->pPars->nWinSizeMax && (Vec_IntSize(vNodes) > p->pPars->nWinSizeMax);
+}
+int Sfm_NtkCreateWindow( Sfm_Ntk_t * p, int iNode, int fVerbose )
+{
+    int i, k, iTemp;
+    abctime clkDiv, clkWin = Abc_Clock();
+
+    assert( Sfm_ObjIsNode( p, iNode ) );
+    p->iPivotNode = iNode;
+    Vec_IntClear( p->vNodes );  // internal
+    Vec_IntClear( p->vDivs );   // divisors
+    Vec_IntClear( p->vRoots );  // roots
+    Vec_IntClear( p->vTfo );    // roots
+    Vec_IntClear( p->vOrder );  // variable order
+
+    // collect transitive fanin
+    Sfm_NtkIncrementTravId( p );
+    if ( Sfm_NtkCollectTfi_rec( p, iNode, p->vNodes ) )
+    {
+        p->nMaxDivs++;
+        p->timeWin += Abc_Clock() - clkWin;
+        return 0;
+    }
+
+    // create divisors
+    clkDiv = Abc_Clock();
+    Vec_IntClear( p->vDivs );
+    Vec_IntAppend( p->vDivs, p->vNodes );
+    Vec_IntPop( p->vDivs );
+    // add non-topological divisors
+    if ( Vec_IntSize(p->vDivs) < p->pPars->nWinSizeMax + 0 )
+    {
+        Sfm_NtkIncrementTravId2( p );
+        Vec_IntForEachEntry( p->vDivs, iTemp, i )
+            if ( Vec_IntSize(p->vDivs) < p->pPars->nWinSizeMax + 0 )
+//                Sfm_NtkAddDivisors( p, iTemp, Sfm_ObjLevel(p, iNode) - 1 );
+                Sfm_NtkAddDivisors( p, iTemp, p->nLevelMax - Sfm_ObjLevelR(p, iNode) ); 
+    }
+    if ( Vec_IntSize(p->vDivs) > p->pPars->nWinSizeMax )
+    {
+/*
+        k = 0;
+        Vec_IntForEachEntryStart( p->vDivs, iTemp, i, Vec_IntSize(p->vDivs) - p->pPars->nWinSizeMax )
+            Vec_IntWriteEntry( p->vDivs, k++, iTemp );
+        assert( k == p->pPars->nWinSizeMax );
+*/
+        Vec_IntShrink( p->vDivs, p->pPars->nWinSizeMax );
+    }
+    assert( Vec_IntSize(p->vDivs) <= p->pPars->nWinSizeMax );
+    p->nMaxDivs += (int)(Vec_IntSize(p->vDivs) == p->pPars->nWinSizeMax);
+    // remove node/fanins from divisors
+    // mark fanins
+    Sfm_NtkIncrementTravId2( p );
+    Sfm_ObjSetTravIdCurrent2( p, iNode );
+    Sfm_ObjForEachFanin( p, iNode, iTemp, i )
+        Sfm_ObjSetTravIdCurrent2( p, iTemp );
+    // compact divisors
+    k = 0;
+    Vec_IntForEachEntry( p->vDivs, iTemp, i )
+        if ( !Sfm_ObjIsTravIdCurrent2(p, iTemp) && Sfm_ObjIsUseful(p, iTemp) )
+            Vec_IntWriteEntry( p->vDivs, k++, iTemp );
+    Vec_IntShrink( p->vDivs, k );
+    assert( Vec_IntSize(p->vDivs) <= p->pPars->nWinSizeMax );
+    clkDiv = Abc_Clock() - clkDiv;
+    p->timeDiv += clkDiv;
+    p->nTotalDivs += Vec_IntSize(p->vDivs);
+ 
+    // collect TFO and window roots
+    if ( p->pPars->nTfoLevMax > 0 && !Sfm_NtkCheckRoot(p, iNode, Sfm_ObjLevel(p, iNode) + p->pPars->nTfoLevMax) )
+    {
+        // explore transitive fanout
+        Sfm_NtkIncrementTravId( p );
+        Sfm_NtkComputeRoots_rec( p, iNode, Sfm_ObjLevel(p, iNode) + p->pPars->nTfoLevMax, p->vRoots, p->vTfo );
+        assert( Vec_IntSize(p->vRoots) > 0 );
+        assert( Vec_IntSize(p->vTfo) > 0 );
+        // compute new leaves and nodes
+        Sfm_NtkIncrementTravId( p );
+        Vec_IntForEachEntry( p->vRoots, iTemp, i )
+            if ( Sfm_NtkCollectTfi_rec( p, iTemp, p->vOrder ) )
+            {
+                Vec_IntClear( p->vRoots );
+                Vec_IntClear( p->vTfo );
+                Vec_IntClear( p->vOrder );
+                break;
+            }
+        if ( Vec_IntSize(p->vRoots) > 0 )
+        Vec_IntForEachEntry( p->vTfo, iTemp, i )
+            if ( Sfm_NtkCollectTfi_rec( p, iTemp, p->vOrder ) )
+            {
+                Vec_IntClear( p->vRoots );
+                Vec_IntClear( p->vTfo );
+                Vec_IntClear( p->vOrder );
+                break;
+            }
+        if ( Vec_IntSize(p->vRoots) > 0 )
+        Vec_IntForEachEntry( p->vDivs, iTemp, i )
+            if ( Sfm_NtkCollectTfi_rec( p, iTemp, p->vOrder ) )
+            {
+                Vec_IntClear( p->vRoots );
+                Vec_IntClear( p->vTfo );
+                Vec_IntClear( p->vOrder );
+                break;
+            }
+    }
+
+    if ( Vec_IntSize(p->vOrder) == 0 )
+    {
+        int Temp = p->pPars->nWinSizeMax;
+        p->pPars->nWinSizeMax = 0;
+        Sfm_NtkIncrementTravId( p );
+        Sfm_NtkCollectTfi_rec( p, iNode, p->vOrder );
+        Vec_IntForEachEntry( p->vDivs, iTemp, i )
+            Sfm_NtkCollectTfi_rec( p, iTemp, p->vOrder );
+        p->pPars->nWinSizeMax = Temp;
+    }
+
+    // statistics
+    p->timeWin += Abc_Clock() - clkWin - clkDiv;
+    if ( !fVerbose )
+        return 1;
+
+    // print stats about the window
+    printf( "%6d : ", iNode );
+    printf( "Leaves = %5d. ", 0 );
+    printf( "Nodes = %5d. ",  Vec_IntSize(p->vNodes) );
+    printf( "Roots = %5d. ",  Vec_IntSize(p->vRoots) );
+    printf( "Divs = %5d. ",   Vec_IntSize(p->vDivs) );
+    printf( "\n" );
+    return 1;
+}
+void Sfm_NtkWindowTest( Sfm_Ntk_t * p, int iNode )
+{
+    int i;
+    Sfm_NtkForEachNode( p, i )
+        Sfm_NtkCreateWindow( p, i, 1 );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/sim/module.make b/abc-build/src/opt/sim/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sim/module.make
@@ -0,0 +1,9 @@
+SRC +=  src/opt/sim/simMan.c \
+	src/opt/sim/simSeq.c \
+	src/opt/sim/simSupp.c \
+	src/opt/sim/simSwitch.c \
+	src/opt/sim/simSym.c \
+	src/opt/sim/simSymSat.c \
+	src/opt/sim/simSymSim.c \
+	src/opt/sim/simSymStr.c \
+	src/opt/sim/simUtils.c
diff --git a/abc-build/src/opt/sim/sim.h b/abc-build/src/opt/sim/sim.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sim/sim.h
@@ -0,0 +1,237 @@
+/**CFile****************************************************************
+
+  FileName    [sim.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Simulation package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: sim.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__opt__sim__sim_h
+#define ABC__opt__sim__sim_h
+
+
+/*
+    The ideas realized in this package are described in the paper:
+    "Detecting Symmetries in Boolean Functions using Circuit Representation, 
+    Simulation, and Satisfiability".
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Sym_Man_t_ Sym_Man_t;
+struct Sym_Man_t_
+{
+    // info about the network
+    Abc_Ntk_t *       pNtk;          // the network 
+    Vec_Ptr_t *       vNodes;        // internal nodes in topological order
+    int               nInputs;
+    int               nOutputs;
+    // internal simulation information
+    int               nSimWords;     // the number of bits in simulation info
+    Vec_Ptr_t *       vSim;          // simulation info
+    // support information
+    Vec_Ptr_t *       vSuppFun;      // bit representation
+    Vec_Vec_t *       vSupports;     // integer representation
+    // symmetry info for each output
+    Vec_Ptr_t *       vMatrSymms;    // symmetric pairs
+    Vec_Ptr_t *       vMatrNonSymms; // non-symmetric pairs
+    Vec_Int_t *       vPairsTotal;   // total pairs
+    Vec_Int_t *       vPairsSym;     // symmetric pairs
+    Vec_Int_t *       vPairsNonSym;  // non-symmetric pairs
+    // temporary simulation info
+    unsigned *        uPatRand;
+    unsigned *        uPatCol;
+    unsigned *        uPatRow;
+    // temporary
+    Vec_Int_t *       vVarsU;
+    Vec_Int_t *       vVarsV;
+    int               iOutput;
+    int               iVar1;
+    int               iVar2;
+    int               iVar1Old;
+    int               iVar2Old;
+    // internal data structures
+    int               nSatRuns;
+    int               nSatRunsSat;
+    int               nSatRunsUnsat;
+    // pairs
+    int               nPairsSymm;
+    int               nPairsSymmStr;
+    int               nPairsNonSymm;
+    int               nPairsRem;
+    int               nPairsTotal;
+    // runtime statistics
+    abctime           timeStruct;
+    abctime           timeCount;
+    abctime           timeMatr;
+    abctime           timeSim;
+    abctime           timeFraig;
+    abctime           timeSat;
+    abctime           timeTotal;
+};
+
+typedef struct Sim_Man_t_ Sim_Man_t;
+struct Sim_Man_t_
+{
+    // info about the network
+    Abc_Ntk_t *       pNtk;
+    int               nInputs;
+    int               nOutputs;
+    int               fLightweight;
+    // internal simulation information
+    int               nSimBits;      // the number of bits in simulation info
+    int               nSimWords;     // the number of words in simulation info
+    Vec_Ptr_t *       vSim0;         // simulation info 1
+    Vec_Ptr_t *       vSim1;         // simulation info 2
+    // support information
+    int               nSuppBits;     // the number of bits in support info
+    int               nSuppWords;    // the number of words in support info
+    Vec_Ptr_t *       vSuppStr;      // structural supports
+    Vec_Ptr_t *       vSuppFun;      // functional supports
+    // simulation targets
+    Vec_Vec_t *       vSuppTargs;    // support targets
+    int               iInput;        // the input current processed
+    // internal data structures
+    Extra_MmFixed_t * pMmPat;   
+    Vec_Ptr_t *       vFifo;
+    Vec_Int_t *       vDiffs;
+    int               nSatRuns;
+    int               nSatRunsSat;
+    int               nSatRunsUnsat;
+    // runtime statistics
+    abctime           timeSim;
+    abctime           timeTrav;
+    abctime           timeFraig;
+    abctime           timeSat;
+    abctime           timeTotal;
+};
+
+typedef struct Sim_Pat_t_ Sim_Pat_t;
+struct Sim_Pat_t_
+{
+    int              Input;         // the input which it has detected
+    int              Output;        // the output for which it was collected
+    unsigned *       pData;         // the simulation data
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+#define SIM_NUM_WORDS(n)      (((n)>>5) + (((n)&31) > 0))
+#define SIM_LAST_BITS(n)      ((((n)&31) > 0)? (n)&31 : 32)
+
+#define SIM_MASK_FULL         (0xFFFFFFFF)
+#define SIM_MASK_BEG(n)       (SIM_MASK_FULL >> (32-n))
+#define SIM_MASK_END(n)       (SIM_MASK_FULL << (n))
+#define SIM_SET_0_FROM(m,n)   ((m) & ~SIM_MASK_BEG(n))
+#define SIM_SET_1_FROM(m,n)   ((m) |  SIM_MASK_END(n))
+
+// generating random unsigned (#define RAND_MAX 0x7fff)
+#define SIM_RANDOM_UNSIGNED   ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand()))
+
+// macros to get hold of bits in a bit string
+#define Sim_SetBit(p,i)       ((p)[(i)>>5] |= (1<<((i) & 31)))
+#define Sim_XorBit(p,i)       ((p)[(i)>>5] ^= (1<<((i) & 31)))
+#define Sim_HasBit(p,i)      (((p)[(i)>>5]  & (1<<((i) & 31))) > 0)
+
+// macros to get hold of the support info
+#define Sim_SuppStrSetVar(vSupps,pNode,v)     Sim_SetBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v))
+#define Sim_SuppStrHasVar(vSupps,pNode,v)     Sim_HasBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v))
+#define Sim_SuppFunSetVar(vSupps,Output,v)    Sim_SetBit((unsigned*)(vSupps)->pArray[Output],(v))
+#define Sim_SuppFunHasVar(vSupps,Output,v)    Sim_HasBit((unsigned*)(vSupps)->pArray[Output],(v))
+#define Sim_SimInfoSetVar(vSupps,pNode,v)     Sim_SetBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v))
+#define Sim_SimInfoHasVar(vSupps,pNode,v)     Sim_HasBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v))
+#define Sim_SimInfoGet(vInfo,pNode)           ((unsigned *)((vInfo)->pArray[(pNode)->Id]))
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== simMan.c ==========================================================*/
+extern Sym_Man_t *     Sym_ManStart( Abc_Ntk_t * pNtk, int fVerbose );
+extern void            Sym_ManStop( Sym_Man_t * p );
+extern void            Sym_ManPrintStats( Sym_Man_t * p );
+extern Sim_Man_t *     Sim_ManStart( Abc_Ntk_t * pNtk, int fLightweight );
+extern void            Sim_ManStop( Sim_Man_t * p );
+extern void            Sim_ManPrintStats( Sim_Man_t * p );
+extern Sim_Pat_t *     Sim_ManPatAlloc( Sim_Man_t * p );
+extern void            Sim_ManPatFree( Sim_Man_t * p, Sim_Pat_t * pPat );
+/*=== simSeq.c ==========================================================*/
+extern Vec_Ptr_t *     Sim_SimulateSeqRandom( Abc_Ntk_t * pNtk, int nFrames, int nWords );
+extern Vec_Ptr_t *     Sim_SimulateSeqModel( Abc_Ntk_t * pNtk, int nFrames, int * pModel );
+/*=== simSupp.c ==========================================================*/
+extern Vec_Ptr_t *     Sim_ComputeStrSupp( Abc_Ntk_t * pNtk );
+extern Vec_Ptr_t *     Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose );
+/*=== simSym.c ==========================================================*/
+extern int             Sim_ComputeTwoVarSymms( Abc_Ntk_t * pNtk, int fVerbose );
+/*=== simSymSat.c ==========================================================*/
+extern int             Sim_SymmsGetPatternUsingSat( Sym_Man_t * p, unsigned * pPattern );
+/*=== simSymStr.c ==========================================================*/
+extern void            Sim_SymmsStructCompute( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMatrs, Vec_Ptr_t * vSuppFun );
+/*=== simSymSim.c ==========================================================*/
+extern void            Sim_SymmsSimulate( Sym_Man_t * p, unsigned * pPatRand, Vec_Ptr_t * vMatrsNonSym );
+/*=== simUtil.c ==========================================================*/
+extern Vec_Ptr_t *     Sim_UtilInfoAlloc( int nSize, int nWords, int  fClean );
+extern void            Sim_UtilInfoFree( Vec_Ptr_t * p );
+extern void            Sim_UtilInfoAdd( unsigned * pInfo1, unsigned * pInfo2, int nWords );
+extern void            Sim_UtilInfoDetectDiffs( unsigned * pInfo1, unsigned * pInfo2, int nWords, Vec_Int_t * vDiffs );
+extern void            Sim_UtilInfoDetectNews( unsigned * pInfo1, unsigned * pInfo2, int nWords, Vec_Int_t * vDiffs );
+extern void            Sim_UtilInfoFlip( Sim_Man_t * p, Abc_Obj_t * pNode );
+extern int             Sim_UtilInfoCompare( Sim_Man_t * p, Abc_Obj_t * pNode );
+extern void            Sim_UtilSimulate( Sim_Man_t * p, int  fFirst );
+extern void            Sim_UtilSimulateNode( Sim_Man_t * p, Abc_Obj_t * pNode, int  fType, int  fType1, int  fType2 );
+extern void            Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset );
+extern void            Sim_UtilTransferNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset, int fShift );
+extern int             Sim_UtilCountSuppSizes( Sim_Man_t * p, int fStruct );
+extern int             Sim_UtilCountOnes( unsigned * pSimInfo, int nSimWords );
+extern Vec_Int_t *     Sim_UtilCountOnesArray( Vec_Ptr_t * vInfo, int nSimWords );
+extern void            Sim_UtilSetRandom( unsigned * pPatRand, int nSimWords );
+extern void            Sim_UtilSetCompl( unsigned * pPatRand, int nSimWords );
+extern void            Sim_UtilSetConst( unsigned * pPatRand, int nSimWords, int fConst1 );
+extern int             Sim_UtilInfoIsEqual( unsigned * pPats1, unsigned * pPats2, int nSimWords );
+extern int             Sim_UtilInfoIsImp( unsigned * pPats1, unsigned * pPats2, int nSimWords );
+extern int             Sim_UtilInfoIsClause( unsigned * pPats1, unsigned * pPats2, int nSimWords );
+extern int             Sim_UtilCountAllPairs( Vec_Ptr_t * vSuppFun, int nSimWords, Vec_Int_t * vCounters );
+extern void            Sim_UtilCountPairsAll( Sym_Man_t * p );
+extern int             Sim_UtilMatrsAreDisjoint( Sym_Man_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/opt/sim/simMan.c b/abc-build/src/opt/sim/simMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sim/simMan.c
@@ -0,0 +1,293 @@
+/**CFile****************************************************************
+
+  FileName    [simMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Simulation manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: simMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "sim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Sym_Man_t * Sym_ManStart( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    Sym_Man_t * p;
+    int i, v; 
+    // start the manager
+    p = ABC_ALLOC( Sym_Man_t, 1 );
+    memset( p, 0, sizeof(Sym_Man_t) );
+    p->pNtk = pNtk;
+    p->vNodes     = Abc_NtkDfs( pNtk, 0 );
+    p->nInputs    = Abc_NtkCiNum(p->pNtk);
+    p->nOutputs   = Abc_NtkCoNum(p->pNtk);
+    // internal simulation information
+    p->nSimWords  = SIM_NUM_WORDS(p->nInputs);
+    p->vSim       = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 );
+    // symmetry info for each output
+    p->vMatrSymms    = Vec_PtrStart( p->nOutputs );
+    p->vMatrNonSymms = Vec_PtrStart( p->nOutputs );
+    p->vPairsTotal   = Vec_IntStart( p->nOutputs );
+    p->vPairsSym     = Vec_IntStart( p->nOutputs );
+    p->vPairsNonSym  = Vec_IntStart( p->nOutputs );
+    for ( i = 0; i < p->nOutputs; i++ )
+    {
+        p->vMatrSymms->pArray[i]    = Extra_BitMatrixStart( p->nInputs );
+        p->vMatrNonSymms->pArray[i] = Extra_BitMatrixStart( p->nInputs );
+    }
+    // temporary patterns
+    p->uPatRand = ABC_ALLOC( unsigned, p->nSimWords );
+    p->uPatCol  = ABC_ALLOC( unsigned, p->nSimWords );
+    p->uPatRow  = ABC_ALLOC( unsigned, p->nSimWords );
+    p->vVarsU   = Vec_IntStart( 100 );
+    p->vVarsV   = Vec_IntStart( 100 );
+    // compute supports
+    p->vSuppFun  = Sim_ComputeFunSupp( pNtk, fVerbose );
+    p->vSupports = Vec_VecStart( p->nOutputs );
+    for ( i = 0; i < p->nOutputs; i++ )
+        for ( v = 0; v < p->nInputs; v++ )
+            if ( Sim_SuppFunHasVar( p->vSuppFun, i, v ) )
+                Vec_VecPush( p->vSupports, i, (void *)(ABC_PTRUINT_T)v );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sym_ManStop( Sym_Man_t * p )
+{
+    int i;
+    Sym_ManPrintStats( p );
+    if ( p->vSuppFun )     Sim_UtilInfoFree( p->vSuppFun );   
+    if ( p->vSim )         Sim_UtilInfoFree( p->vSim );   
+    if ( p->vNodes )       Vec_PtrFree( p->vNodes );
+    if ( p->vSupports )    Vec_VecFree( p->vSupports );
+    for ( i = 0; i < p->nOutputs; i++ )
+    {
+        Extra_BitMatrixStop( (Extra_BitMat_t *)p->vMatrSymms->pArray[i] );
+        Extra_BitMatrixStop( (Extra_BitMat_t *)p->vMatrNonSymms->pArray[i] );
+    }
+    Vec_IntFree( p->vVarsU );
+    Vec_IntFree( p->vVarsV );
+    Vec_PtrFree( p->vMatrSymms );
+    Vec_PtrFree( p->vMatrNonSymms );
+    Vec_IntFree( p->vPairsTotal );
+    Vec_IntFree( p->vPairsSym );
+    Vec_IntFree( p->vPairsNonSym );
+    ABC_FREE( p->uPatRand );
+    ABC_FREE( p->uPatCol );
+    ABC_FREE( p->uPatRow );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the manager statisticis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sym_ManPrintStats( Sym_Man_t * p )
+{
+//    printf( "Inputs = %5d. Outputs = %5d. Sim words = %5d.\n", 
+//        Abc_NtkCiNum(p->pNtk), Abc_NtkCoNum(p->pNtk), p->nSimWords );
+    printf( "Total symm         = %8d.\n", p->nPairsSymm );
+    printf( "Structural symm    = %8d.\n", p->nPairsSymmStr );
+    printf( "Total non-sym      = %8d.\n", p->nPairsNonSymm );
+    printf( "Total var pairs    = %8d.\n", p->nPairsTotal );
+    printf( "Sat runs SAT       = %8d.\n", p->nSatRunsSat );
+    printf( "Sat runs UNSAT     = %8d.\n", p->nSatRunsUnsat );
+    ABC_PRT( "Structural  ", p->timeStruct );
+    ABC_PRT( "Simulation  ", p->timeSim );
+    ABC_PRT( "Matrix      ", p->timeMatr );
+    ABC_PRT( "Counting    ", p->timeCount );
+    ABC_PRT( "Fraiging    ", p->timeFraig );
+    ABC_PRT( "SAT         ", p->timeSat );
+    ABC_PRT( "TOTAL       ", p->timeTotal );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk, int fLightweight )
+{
+    Sim_Man_t * p;
+    // start the manager
+    p = ABC_ALLOC( Sim_Man_t, 1 );
+    memset( p, 0, sizeof(Sim_Man_t) );
+    p->pNtk = pNtk;
+    p->nInputs    = Abc_NtkCiNum(p->pNtk);
+    p->nOutputs   = Abc_NtkCoNum(p->pNtk);
+    // internal simulation information
+    p->nSimBits   = 2048;
+    p->nSimWords  = SIM_NUM_WORDS(p->nSimBits);
+    p->vSim0      = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 );
+    p->fLightweight = fLightweight;
+    if (!p->fLightweight) {
+        p->vSim1      = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 );
+        // support information
+        p->nSuppBits  = Abc_NtkCiNum(pNtk);
+        p->nSuppWords = SIM_NUM_WORDS(p->nSuppBits);
+        p->vSuppStr   = Sim_ComputeStrSupp( pNtk );
+        p->vSuppFun   = Sim_UtilInfoAlloc( Abc_NtkCoNum(p->pNtk),  p->nSuppWords, 1 );
+        // other data
+        p->pMmPat     = Extra_MmFixedStart( sizeof(Sim_Pat_t) + p->nSuppWords * sizeof(unsigned) ); 
+        p->vFifo      = Vec_PtrAlloc( 100 );
+        p->vDiffs     = Vec_IntAlloc( 100 );
+        // allocate support targets (array of unresolved outputs for each input)
+        p->vSuppTargs = Vec_VecStart( p->nInputs );
+    }
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_ManStop( Sim_Man_t * p )
+{
+    Sim_ManPrintStats( p );
+    if ( p->vSim0 )        Sim_UtilInfoFree( p->vSim0 );       
+    if ( p->vSim1 )        Sim_UtilInfoFree( p->vSim1 );       
+    if ( p->vSuppStr )     Sim_UtilInfoFree( p->vSuppStr );    
+//    if ( p->vSuppFun )     Sim_UtilInfoFree( p->vSuppFun );    
+    if ( p->vSuppTargs )   Vec_VecFree( p->vSuppTargs );
+    if ( p->pMmPat )       Extra_MmFixedStop( p->pMmPat );
+    if ( p->vFifo )        Vec_PtrFree( p->vFifo );
+    if ( p->vDiffs )       Vec_IntFree( p->vDiffs );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the manager statisticis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_ManPrintStats( Sim_Man_t * p )
+{
+//    printf( "Inputs = %5d. Outputs = %5d. Sim words = %5d.\n", 
+//        Abc_NtkCiNum(p->pNtk), Abc_NtkCoNum(p->pNtk), p->nSimWords );
+    printf( "Total func supps   = %8d.\n", Sim_UtilCountSuppSizes(p, 0) );
+    printf( "Total struct supps = %8d.\n", Sim_UtilCountSuppSizes(p, 1) );
+    printf( "Sat runs SAT       = %8d.\n", p->nSatRunsSat );
+    printf( "Sat runs UNSAT     = %8d.\n", p->nSatRunsUnsat );
+    ABC_PRT( "Simulation  ", p->timeSim );
+    ABC_PRT( "Traversal   ", p->timeTrav );
+    ABC_PRT( "Fraiging    ", p->timeFraig );
+    ABC_PRT( "SAT         ", p->timeSat );
+    ABC_PRT( "TOTAL       ", p->timeTotal );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns one simulation pattern.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Sim_Pat_t * Sim_ManPatAlloc( Sim_Man_t * p )
+{
+    Sim_Pat_t * pPat;
+    pPat = (Sim_Pat_t *)Extra_MmFixedEntryFetch( p->pMmPat );
+    pPat->Output = -1;
+    pPat->pData  = (unsigned *)((char *)pPat + sizeof(Sim_Pat_t));
+    memset( pPat->pData, 0, p->nSuppWords * sizeof(unsigned) );
+    return pPat;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns one simulation pattern.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_ManPatFree( Sim_Man_t * p, Sim_Pat_t * pPat )
+{
+    Extra_MmFixedEntryRecycle( p->pMmPat, (char *)pPat );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/sim/simSat.c b/abc-build/src/opt/sim/simSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sim/simSat.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+  FileName    [simSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Simulation to determine functional support.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: simSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "sim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/sim/simSeq.c b/abc-build/src/opt/sim/simSeq.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sim/simSeq.c
@@ -0,0 +1,176 @@
+/**CFile****************************************************************
+
+  FileName    [simSeq.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Simulation for sequential circuits.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: simUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "sim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Sim_SimulateSeqFrame( Vec_Ptr_t * vInfo, Abc_Ntk_t * pNtk, int iFrames, int nWords, int fTransfer );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates sequential circuit.]
+
+  Description [Takes sequential circuit (pNtk). Simulates the given number
+  (nFrames) of the circuit with the given number of machine words (nWords)
+  of random simulation data, starting from the initial state. If the initial
+  state of some latches is a don't-care, uses random input for that latch.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Sim_SimulateSeqRandom( Abc_Ntk_t * pNtk, int nFrames, int nWords )
+{
+    Vec_Ptr_t * vInfo;
+    Abc_Obj_t * pNode;
+    int i;
+    assert( Abc_NtkIsStrash(pNtk) );
+    vInfo = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nWords * nFrames, 0 );
+    // set the constant data
+    pNode = Abc_AigConst1(pNtk);
+    Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords * nFrames, 1 );
+    // set the random PI data
+    Abc_NtkForEachPi( pNtk, pNode, i )
+        Sim_UtilSetRandom( Sim_SimInfoGet(vInfo,pNode), nWords * nFrames );
+    // set the initial state data
+    Abc_NtkForEachLatch( pNtk, pNode, i )
+        if ( Abc_LatchIsInit0(pNode) )
+            Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords, 0 );
+        else if ( Abc_LatchIsInit1(pNode) )
+            Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords, 1 );
+        else 
+            Sim_UtilSetRandom( Sim_SimInfoGet(vInfo,pNode), nWords );
+    // simulate the nodes for the given number of timeframes
+    for ( i = 0; i < nFrames; i++ )
+        Sim_SimulateSeqFrame( vInfo, pNtk, i, nWords, (int)(i < nFrames-1) );
+    return vInfo;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates sequential circuit.]
+
+  Description [Takes sequential circuit (pNtk). Simulates the given number
+  (nFrames) of the circuit with the given model. The model is assumed to 
+  contain values of PIs for each frame. The latches are initialized to
+  the initial state. One word of data is simulated.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Sim_SimulateSeqModel( Abc_Ntk_t * pNtk, int nFrames, int * pModel )
+{
+    Vec_Ptr_t * vInfo;
+    Abc_Obj_t * pNode;
+    unsigned * pUnsigned;
+    int i, k;
+    vInfo = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nFrames, 0 );
+    // set the constant data
+    pNode = Abc_AigConst1(pNtk);
+    Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nFrames, 1 );
+    // set the random PI data
+    Abc_NtkForEachPi( pNtk, pNode, i )
+    {
+        pUnsigned = Sim_SimInfoGet(vInfo,pNode);
+        for ( k = 0; k < nFrames; k++ )
+            pUnsigned[k] = pModel[k * Abc_NtkPiNum(pNtk) + i] ? ~((unsigned)0) : 0;
+    }
+    // set the initial state data
+    Abc_NtkForEachLatch( pNtk, pNode, i )
+    {
+        pUnsigned = Sim_SimInfoGet(vInfo,pNode);
+        if ( Abc_LatchIsInit0(pNode) )
+            pUnsigned[0] = 0;
+        else if ( Abc_LatchIsInit1(pNode) )
+            pUnsigned[0] = ~((unsigned)0);
+        else 
+            pUnsigned[0] = SIM_RANDOM_UNSIGNED;
+    }
+    // simulate the nodes for the given number of timeframes
+    for ( i = 0; i < nFrames; i++ )
+        Sim_SimulateSeqFrame( vInfo, pNtk, i, 1, (int)(i < nFrames-1) );
+/*
+    // print the simulated values
+    for ( i = 0; i < nFrames; i++ )
+    {
+        printf( "Frame %d : ", i+1 );
+        Abc_NtkForEachPi( pNtk, pNode, k )
+            printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 );
+        printf( " " );
+        Abc_NtkForEachLatch( pNtk, pNode, k )
+            printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 );
+        printf( " " );
+        Abc_NtkForEachPo( pNtk, pNode, k )
+            printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 );
+        printf( "\n" );
+    }
+    printf( "\n" );
+*/
+    return vInfo;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one frame of sequential circuit.]
+
+  Description [Assumes that the latches and POs are already initialized.
+  In the end transfers the data to the latches of the next frame.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_SimulateSeqFrame( Vec_Ptr_t * vInfo, Abc_Ntk_t * pNtk, int iFrames, int nWords, int fTransfer )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    Abc_NtkForEachNode( pNtk, pNode, i )
+        Sim_UtilSimulateNodeOne( pNode, vInfo, nWords, iFrames * nWords );
+    Abc_NtkForEachPo( pNtk, pNode, i )
+        Sim_UtilTransferNodeOne( pNode, vInfo, nWords, iFrames * nWords, 0 );
+    if ( !fTransfer )
+        return;
+    Abc_NtkForEachLatch( pNtk, pNode, i )
+        Sim_UtilTransferNodeOne( pNode, vInfo, nWords, iFrames * nWords, 1 );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/sim/simSupp.c b/abc-build/src/opt/sim/simSupp.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sim/simSupp.c
@@ -0,0 +1,603 @@
+/**CFile****************************************************************
+
+  FileName    [simSupp.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Simulation to determine functional support.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: simSupp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "proof/fraig/fraig.h"
+#include "sim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+static int    Sim_ComputeSuppRound( Sim_Man_t * p, int  fUseTargets );
+static int    Sim_ComputeSuppRoundNode( Sim_Man_t * p, int iNumCi, int  fUseTargets );
+static void   Sim_ComputeSuppSetTargets( Sim_Man_t * p );
+
+static void   Sim_UtilAssignRandom( Sim_Man_t * p );
+static void   Sim_UtilAssignFromFifo( Sim_Man_t * p );
+static void   Sim_SolveTargetsUsingSat( Sim_Man_t * p, int nCounters );
+static int    Sim_SolveSuppModelVerify( Abc_Ntk_t * pNtk, int * pModel, int Input, int Output );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes structural supports.]
+
+  Description [Supports are returned as an array of bit strings, one
+  for each CO.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Sim_ComputeStrSupp( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vSuppStr;
+    Abc_Obj_t * pNode;
+    unsigned * pSimmNode, * pSimmNode1, * pSimmNode2;
+    int nSuppWords, i, k;
+    // allocate room for structural supports
+    nSuppWords = SIM_NUM_WORDS( Abc_NtkCiNum(pNtk) );
+    vSuppStr   = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nSuppWords, 1 );
+    // assign the structural support to the PIs
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        Sim_SuppStrSetVar( vSuppStr, pNode, i );
+    // derive the structural supports of the internal nodes
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+//        if ( Abc_NodeIsConst(pNode) )
+//            continue;
+        pSimmNode  = (unsigned *)vSuppStr->pArray[ pNode->Id ];
+        pSimmNode1 = (unsigned *)vSuppStr->pArray[ Abc_ObjFaninId0(pNode) ];
+        pSimmNode2 = (unsigned *)vSuppStr->pArray[ Abc_ObjFaninId1(pNode) ];
+        for ( k = 0; k < nSuppWords; k++ )
+            pSimmNode[k] = pSimmNode1[k] | pSimmNode2[k];
+    }
+    // set the structural supports of the PO nodes
+    Abc_NtkForEachCo( pNtk, pNode, i )
+    {
+        pSimmNode  = (unsigned *)vSuppStr->pArray[ pNode->Id ];
+        pSimmNode1 = (unsigned *)vSuppStr->pArray[ Abc_ObjFaninId0(pNode) ];
+        for ( k = 0; k < nSuppWords; k++ )
+            pSimmNode[k] = pSimmNode1[k];
+    }
+    return vSuppStr;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute functional supports.]
+
+  Description [Supports are returned as an array of bit strings, one
+  for each CO.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    Sim_Man_t * p;
+    Vec_Ptr_t * vResult;
+    int nSolved, i;
+    abctime clk = Abc_Clock();
+
+    srand( 0xABC );
+
+    // start the simulation manager
+    p = Sim_ManStart( pNtk, 0 );
+
+    // compute functional support using one round of random simulation
+    Sim_UtilAssignRandom( p );
+    Sim_ComputeSuppRound( p, 0 );
+
+    // set the support targets 
+    Sim_ComputeSuppSetTargets( p );
+if ( fVerbose )
+    printf( "Number of support targets after simulation = %5d.\n", Vec_VecSizeSize(p->vSuppTargs) );
+    if ( Vec_VecSizeSize(p->vSuppTargs) == 0 )
+        goto exit;
+
+    for ( i = 0; i < 1; i++ )
+    {
+        // compute patterns using one round of random simulation
+        Sim_UtilAssignRandom( p );
+        nSolved = Sim_ComputeSuppRound( p, 1 );
+        if ( Vec_VecSizeSize(p->vSuppTargs) == 0 )
+            goto exit;
+
+if ( fVerbose )
+    printf( "Targets = %5d.   Solved = %5d.  Fifo = %5d.\n", 
+       Vec_VecSizeSize(p->vSuppTargs), nSolved, Vec_PtrSize(p->vFifo) );
+    }
+
+    // try to solve the support targets
+    while ( Vec_VecSizeSize(p->vSuppTargs) > 0 )
+    {
+        // solve targets until the first disproved one (which gives counter-example)
+        Sim_SolveTargetsUsingSat( p, p->nSimWords/p->nSuppWords );
+        // compute additional functional support
+        Sim_UtilAssignFromFifo( p );
+        nSolved = Sim_ComputeSuppRound( p, 1 );
+
+if ( fVerbose )
+    printf( "Targets = %5d.   Solved = %5d.  Fifo = %5d.  SAT runs = %3d.\n", 
+            Vec_VecSizeSize(p->vSuppTargs), nSolved, Vec_PtrSize(p->vFifo), p->nSatRuns );
+    }
+
+exit:
+p->timeTotal = Abc_Clock() - clk;
+    vResult = p->vSuppFun;  
+    //  p->vSuppFun = NULL;
+    Sim_ManStop( p );
+    return vResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes functional support using one round of simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_ComputeSuppRound( Sim_Man_t * p, int  fUseTargets )
+{
+    Vec_Int_t * vTargets;
+    int i, Counter = 0;
+    abctime clk;
+    // perform one round of random simulation
+clk = Abc_Clock();
+    Sim_UtilSimulate( p, 0 );
+p->timeSim += Abc_Clock() - clk;
+    // iterate through the CIs and detect COs that depend on them
+    for ( i = p->iInput; i < p->nInputs; i++ )
+    {
+        vTargets = (Vec_Int_t *)p->vSuppTargs->pArray[i];
+        if ( fUseTargets && vTargets->nSize == 0 )
+            continue;
+        Counter += Sim_ComputeSuppRoundNode( p, i, fUseTargets );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes functional support for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_ComputeSuppRoundNode( Sim_Man_t * p, int iNumCi, int  fUseTargets )
+{
+    int fVerbose = 0;
+    Sim_Pat_t * pPat;
+    Vec_Int_t * vTargets;
+    Vec_Vec_t * vNodesByLevel;
+    Abc_Obj_t * pNodeCi, * pNode;
+    int i, k, v, Output, LuckyPat, fType0, fType1;
+    int Counter = 0;
+    int fFirst = 1;
+    abctime clk;
+    // collect nodes by level in the TFO of the CI 
+    // this proceduredoes not collect the CIs and COs
+    // but it increments TravId of the collected nodes and CIs/COs
+clk = Abc_Clock();
+    pNodeCi       = Abc_NtkCi( p->pNtk, iNumCi );
+    vNodesByLevel = Abc_DfsLevelized( pNodeCi, 0 );
+p->timeTrav += Abc_Clock() - clk;
+    // complement the simulation info of the selected CI
+    Sim_UtilInfoFlip( p, pNodeCi );
+    // simulate the levelized structure of nodes
+    Vec_VecForEachEntry( Abc_Obj_t *, vNodesByLevel, pNode, i, k )
+    {
+        fType0 = Abc_NodeIsTravIdCurrent( Abc_ObjFanin0(pNode) );
+        fType1 = Abc_NodeIsTravIdCurrent( Abc_ObjFanin1(pNode) );
+clk = Abc_Clock();
+        Sim_UtilSimulateNode( p, pNode, 1, fType0, fType1 );
+p->timeSim += Abc_Clock() - clk;
+    }
+    // set the simulation info of the affected COs
+    if ( fUseTargets )
+    {
+        vTargets = (Vec_Int_t *)p->vSuppTargs->pArray[iNumCi];
+        for ( i = vTargets->nSize - 1; i >= 0; i-- )
+        {
+            // get the target output
+            Output = vTargets->pArray[i];
+            // get the target node
+            pNode  = Abc_ObjFanin0( Abc_NtkCo(p->pNtk, Output) );
+            // the output should be in the cone
+            assert( Abc_NodeIsTravIdCurrent(pNode) );
+
+            // skip if the simulation info is equal
+            if ( Sim_UtilInfoCompare( p, pNode ) )
+                continue;
+
+            // otherwise, we solved a new target
+            Vec_IntRemove( vTargets, Output );
+if ( fVerbose )
+    printf( "(%d,%d) ", iNumCi, Output );
+            Counter++;
+            // make sure this variable is not yet detected
+            assert( !Sim_SuppFunHasVar(p->vSuppFun, Output, iNumCi) );
+            // set this variable
+            Sim_SuppFunSetVar( p->vSuppFun, Output, iNumCi );
+            
+            // detect the differences in the simulation info
+            Sim_UtilInfoDetectDiffs( (unsigned *)p->vSim0->pArray[pNode->Id], (unsigned *)p->vSim1->pArray[pNode->Id], p->nSimWords, p->vDiffs );
+            // create new patterns
+            if ( !fFirst && p->vFifo->nSize > 1000 )
+                continue;
+
+            Vec_IntForEachEntry( p->vDiffs, LuckyPat, k )
+            {
+                // set the new pattern
+                pPat = Sim_ManPatAlloc( p );
+                pPat->Input  = iNumCi;
+                pPat->Output = Output;
+                Abc_NtkForEachCi( p->pNtk, pNodeCi, v )
+                    if ( Sim_SimInfoHasVar( p->vSim0, pNodeCi, LuckyPat ) )
+                        Sim_SetBit( pPat->pData, v );
+                Vec_PtrPush( p->vFifo, pPat );
+
+                fFirst = 0;
+                break;
+            }
+        }
+if ( fVerbose && Counter )
+printf( "\n" );
+    }
+    else
+    {
+        Abc_NtkForEachCo( p->pNtk, pNode, Output )
+        {
+            if ( !Abc_NodeIsTravIdCurrent( pNode ) )
+                continue;
+            if ( !Sim_UtilInfoCompare( p, Abc_ObjFanin0(pNode) ) )
+            {
+                if ( !Sim_SuppFunHasVar(p->vSuppFun, Output, iNumCi) )
+                {
+                    Counter++;
+                    Sim_SuppFunSetVar( p->vSuppFun, Output, iNumCi );
+                }
+            }
+        }
+    }
+    Vec_VecFree( vNodesByLevel );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the simulation targets.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_ComputeSuppSetTargets( Sim_Man_t * p )
+{
+    Abc_Obj_t * pNode;
+    unsigned * pSuppStr, * pSuppFun;
+    int i, k, Num;
+    Abc_NtkForEachCo( p->pNtk, pNode, i )
+    {
+        pSuppStr = (unsigned *)p->vSuppStr->pArray[pNode->Id];
+        pSuppFun = (unsigned *)p->vSuppFun->pArray[i];
+        // find vars in the structural support that are not in the functional support
+        Sim_UtilInfoDetectNews( pSuppFun, pSuppStr, p->nSuppWords, p->vDiffs );
+        Vec_IntForEachEntry( p->vDiffs, Num, k )
+            Vec_VecPush( p->vSuppTargs, Num, (void *)(ABC_PTRUINT_T)i );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns random simulation info to the PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_UtilAssignRandom( Sim_Man_t * p )
+{
+    Abc_Obj_t * pNode;
+    unsigned * pSimInfo;
+    int i, k;
+    // assign the random/systematic simulation info to the PIs
+    Abc_NtkForEachCi( p->pNtk, pNode, i )
+    {
+        pSimInfo = (unsigned *)p->vSim0->pArray[pNode->Id];
+        for ( k = 0; k < p->nSimWords; k++ )
+            pSimInfo[k] = SIM_RANDOM_UNSIGNED;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the new patterns from fifo.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_UtilAssignFromFifo( Sim_Man_t * p )
+{
+    int fUseOneWord = 0;
+    Abc_Obj_t * pNode;
+    Sim_Pat_t * pPat;
+    unsigned * pSimInfo;
+    int nWordsNew, iWord, iWordLim, i, w;
+    int iBeg, iEnd;
+    int Counter = 0;
+    // go through the patterns and fill in the dist-1 minterms for each
+    for ( iWord = 0; p->vFifo->nSize > 0; iWord = iWordLim )
+    {
+        ++Counter;
+        // get the pattern
+        pPat = (Sim_Pat_t *)Vec_PtrPop( p->vFifo );
+        if ( fUseOneWord )
+        {
+            // get the first word of the next series
+            iWordLim = iWord + 1; 
+            // set the pattern for all PIs from iBit to iWord + p->nInputs
+            iBeg = p->iInput;
+            iEnd = Abc_MinInt( iBeg + 32, p->nInputs );
+//            for ( i = iBeg; i < iEnd; i++ )
+            Abc_NtkForEachCi( p->pNtk, pNode, i )
+            {
+                pNode = Abc_NtkCi(p->pNtk,i);
+                pSimInfo = (unsigned *)p->vSim0->pArray[pNode->Id];
+                if ( Sim_HasBit(pPat->pData, i) )
+                    pSimInfo[iWord] = SIM_MASK_FULL;
+                else
+                    pSimInfo[iWord] = 0;
+                // flip one bit
+                if ( i >= iBeg && i < iEnd )
+                    Sim_XorBit( pSimInfo + iWord, i-iBeg );
+            }
+        }
+        else
+        {
+            // get the number of words for the remaining inputs
+            nWordsNew = p->nSuppWords;
+//            nWordsNew = SIM_NUM_WORDS( p->nInputs - p->iInput );
+            // get the first word of the next series
+            iWordLim = (iWord + nWordsNew < p->nSimWords)? iWord + nWordsNew : p->nSimWords; 
+            // set the pattern for all CIs from iWord to iWord + nWordsNew
+            Abc_NtkForEachCi( p->pNtk, pNode, i )
+            {
+                pSimInfo = (unsigned *)p->vSim0->pArray[pNode->Id];
+                if ( Sim_HasBit(pPat->pData, i) )
+                {
+                    for ( w = iWord; w < iWordLim; w++ )
+                        pSimInfo[w] = SIM_MASK_FULL;
+                }
+                else
+                {
+                    for ( w = iWord; w < iWordLim; w++ )
+                        pSimInfo[w] = 0;
+                }
+                Sim_XorBit( pSimInfo + iWord, i );
+                // flip one bit
+//                if ( i >= p->iInput )
+//                    Sim_XorBit( pSimInfo + iWord, i-p->iInput );
+            }
+        }
+        Sim_ManPatFree( p, pPat );
+        // stop if we ran out of room for patterns
+        if ( iWordLim == p->nSimWords )
+            break;
+//        if ( Counter == 1 )
+//            break;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Get the given number of counter-examples using SAT.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_SolveTargetsUsingSat( Sim_Man_t * p, int Limit )
+{
+    Fraig_Params_t Params;
+    Fraig_Man_t * pMan;
+    Abc_Obj_t * pNodeCi;
+    Abc_Ntk_t * pMiter;
+    Sim_Pat_t * pPat;
+    void * pEntry;
+    int * pModel;
+    int RetValue, Output, Input, k, v;
+    int Counter = 0;
+    abctime clk;
+
+    p->nSatRuns = 0;
+    // put targets into one array
+    Vec_VecForEachEntryReverse( void *, p->vSuppTargs, pEntry, Input, k )
+    {
+        p->nSatRuns++;
+        Output = (int)(ABC_PTRUINT_T)pEntry;
+
+        // set up the miter for the two cofactors of this output w.r.t. this input
+        pMiter = Abc_NtkMiterForCofactors( p->pNtk, Output, Input, -1 );
+
+        // transform the miter into a fraig
+        Fraig_ParamsSetDefault( &Params );
+        Params.nSeconds = ABC_INFINITY;
+        Params.fInternal = 1;
+clk = Abc_Clock();
+        pMan = (Fraig_Man_t *)Abc_NtkToFraig( pMiter, &Params, 0, 0 ); 
+p->timeFraig += Abc_Clock() - clk;
+clk = Abc_Clock();
+        Fraig_ManProveMiter( pMan );
+p->timeSat += Abc_Clock() - clk;
+
+        // analyze the result
+        RetValue = Fraig_ManCheckMiter( pMan );
+        assert( RetValue >= 0 );
+        if ( RetValue == 1 ) // unsat
+        {
+            p->nSatRunsUnsat++;
+            pModel = NULL;
+            Vec_PtrRemove( (Vec_Ptr_t *)p->vSuppTargs->pArray[Input], pEntry );
+        }
+        else // sat
+        {
+            p->nSatRunsSat++;
+            pModel = Fraig_ManReadModel( pMan );
+            assert( pModel != NULL );
+            assert( Sim_SolveSuppModelVerify( p->pNtk, pModel, Input, Output ) );
+
+//printf( "Solved by SAT (%d,%d).\n", Input, Output );
+            // set the new pattern
+            pPat = Sim_ManPatAlloc( p );
+            pPat->Input  = Input;
+            pPat->Output = Output;
+            Abc_NtkForEachCi( p->pNtk, pNodeCi, v )
+                if ( pModel[v] )
+                    Sim_SetBit( pPat->pData, v );
+            Vec_PtrPush( p->vFifo, pPat );
+/*
+            // set the new pattern
+            pPat = Sim_ManPatAlloc( p );
+            pPat->Input  = Input;
+            pPat->Output = Output;
+            Abc_NtkForEachCi( p->pNtk, pNodeCi, v )
+                if ( pModel[v] )
+                    Sim_SetBit( pPat->pData, v );
+            Sim_XorBit( pPat->pData, Input );  // add this bit in the opposite polarity
+            Vec_PtrPush( p->vFifo, pPat );
+*/
+            Counter++;
+        }
+        // delete the fraig manager
+        Fraig_ManFree( pMan );
+        // delete the miter
+        Abc_NtkDelete( pMiter );
+
+        // makr the input, which we are processing
+        p->iInput = Input;
+
+        // stop when we found enough patterns
+//        if ( Counter == Limit )
+        if ( Counter == 1 )
+            return;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Saves the counter example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_NtkSimTwoPats_rec( Abc_Obj_t * pNode )
+{
+    int Value0, Value1;
+    if ( Abc_NodeIsTravIdCurrent( pNode ) )
+        return (int)(ABC_PTRUINT_T)pNode->pCopy;
+    Abc_NodeSetTravIdCurrent( pNode );
+    Value0 = Sim_NtkSimTwoPats_rec( Abc_ObjFanin0(pNode) );
+    Value1 = Sim_NtkSimTwoPats_rec( Abc_ObjFanin1(pNode) );
+    if ( Abc_ObjFaninC0(pNode) )
+        Value0 = ~Value0;
+    if ( Abc_ObjFaninC1(pNode) )
+        Value1 = ~Value1;
+    pNode->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)(Value0 & Value1);
+    return Value0 & Value1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies that pModel proves the presence of Input in the support of Output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_SolveSuppModelVerify( Abc_Ntk_t * pNtk, int * pModel, int Input, int Output )
+{
+    Abc_Obj_t * pNode;
+    int RetValue, i;
+    // set the PI values
+    Abc_NtkIncrementTravId( pNtk );
+    Abc_NtkForEachCi( pNtk, pNode, i )
+    {
+        Abc_NodeSetTravIdCurrent( pNode );
+        if ( pNode == Abc_NtkCi(pNtk,Input) )
+            pNode->pCopy = (Abc_Obj_t *)1;
+        else if ( pModel[i] == 1 )
+            pNode->pCopy = (Abc_Obj_t *)3;
+        else
+            pNode->pCopy = NULL;
+    }
+    // perform the traversal
+    RetValue = 3 & Sim_NtkSimTwoPats_rec( Abc_ObjFanin0( Abc_NtkCo(pNtk,Output) ) );
+//    assert( RetValue == 1 || RetValue == 2 ); 
+    return RetValue == 1 || RetValue == 2;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/sim/simSwitch.c b/abc-build/src/opt/sim/simSwitch.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sim/simSwitch.c
@@ -0,0 +1,112 @@
+/**CFile****************************************************************
+
+  FileName    [simSwitch.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Computes switching activity of nodes in the ABC network.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: simSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "sim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Sim_NodeSimulate( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords );
+static float Sim_ComputeSwitching( unsigned * pSimInfo, int nSimWords );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes switching activity using simulation.]
+
+  Description [Computes switching activity, which is understood as the
+  probability of switching under random simulation. Assigns the
+  random simulation information at the CI and propagates it through
+  the internal nodes of the AIG.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns )
+{
+    Vec_Int_t * vSwitching;
+    float * pSwitching;
+    Vec_Ptr_t * vNodes;
+    Vec_Ptr_t * vSimInfo;
+    Abc_Obj_t * pNode;
+    unsigned * pSimInfo;
+    int nSimWords, i;
+
+    // allocate space for simulation info of all nodes
+    nSimWords = SIM_NUM_WORDS(nPatterns);
+    vSimInfo = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nSimWords, 0 );
+    // assign the random simulation to the CIs
+    vSwitching = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
+    pSwitching = (float *)vSwitching->pArray;
+    Abc_NtkForEachCi( pNtk, pNode, i )
+    {
+        pSimInfo = (unsigned *)Vec_PtrEntry(vSimInfo, pNode->Id);
+        Sim_UtilSetRandom( pSimInfo, nSimWords );
+        pSwitching[pNode->Id] = Sim_ComputeSwitching( pSimInfo, nSimWords );
+    }
+    // simulate the internal nodes
+    vNodes  = Abc_AigDfs( pNtk, 1, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        pSimInfo = (unsigned *)Vec_PtrEntry(vSimInfo, pNode->Id);
+        Sim_UtilSimulateNodeOne( pNode, vSimInfo, nSimWords, 0 );
+        pSwitching[pNode->Id] = Sim_ComputeSwitching( pSimInfo, nSimWords );
+    }
+    Vec_PtrFree( vNodes );
+    Sim_UtilInfoFree( vSimInfo );
+    return vSwitching;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes switching activity of one node.]
+
+  Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Sim_ComputeSwitching( unsigned * pSimInfo, int nSimWords )
+{
+    int nOnes, nTotal;
+    nTotal = 32 * nSimWords;
+    nOnes = Sim_UtilCountOnes( pSimInfo, nSimWords );
+    return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/sim/simSym.c b/abc-build/src/opt/sim/simSym.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sim/simSym.c
@@ -0,0 +1,148 @@
+/**CFile****************************************************************
+
+  FileName    [simSym.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Simulation to determine two-variable symmetries.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: simSym.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "sim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes two variable symmetries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_ComputeTwoVarSymms( Abc_Ntk_t * pNtk, int fVerbose )
+{
+    Sym_Man_t * p;
+    Vec_Ptr_t * vResult;
+    int Result;
+    int i;
+    abctime clk, clkTotal = Abc_Clock();
+
+    srand( 0xABC );
+
+    // start the simulation manager
+    p = Sym_ManStart( pNtk, fVerbose );
+    p->nPairsTotal = p->nPairsRem = Sim_UtilCountAllPairs( p->vSuppFun, p->nSimWords, p->vPairsTotal );
+    if ( fVerbose )
+        printf( "Total = %8d.  Sym = %8d.  NonSym = %8d.  Remaining = %8d.\n", 
+               p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem );
+
+    // detect symmetries using circuit structure
+clk = Abc_Clock();
+    Sim_SymmsStructCompute( pNtk, p->vMatrSymms, p->vSuppFun );
+p->timeStruct = Abc_Clock() - clk;
+
+    Sim_UtilCountPairsAll( p );
+    p->nPairsSymmStr = p->nPairsSymm;
+    if ( fVerbose )
+        printf( "Total = %8d.  Sym = %8d.  NonSym = %8d.  Remaining = %8d.\n", 
+            p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem );
+
+    // detect symmetries using simulation
+    for ( i = 1; i <= 1000; i++ )
+    {
+        // simulate this pattern
+        Sim_UtilSetRandom( p->uPatRand, p->nSimWords );
+        Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms );
+        if ( i % 50 != 0 )
+            continue;
+        // check disjointness
+        assert( Sim_UtilMatrsAreDisjoint( p ) );
+        // count the number of pairs
+        Sim_UtilCountPairsAll( p );
+        if ( i % 500 != 0 )
+            continue;
+        if ( fVerbose )
+            printf( "Total = %8d.  Sym = %8d.  NonSym = %8d.  Remaining = %8d.\n", 
+                p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem );
+    }
+
+    // detect symmetries using SAT
+    for ( i = 1; Sim_SymmsGetPatternUsingSat( p, p->uPatRand ); i++ )
+    {
+        // simulate this pattern in four polarities
+        Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms );
+        Sim_XorBit( p->uPatRand, p->iVar1 );
+        Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms );
+        Sim_XorBit( p->uPatRand, p->iVar2 );
+        Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms );
+        Sim_XorBit( p->uPatRand, p->iVar1 );
+        Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms );
+        Sim_XorBit( p->uPatRand, p->iVar2 );
+/*
+        // try the previuos pair
+        Sim_XorBit( p->uPatRand, p->iVar1Old );
+        Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms );
+        Sim_XorBit( p->uPatRand, p->iVar2Old );
+        Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms );
+        Sim_XorBit( p->uPatRand, p->iVar1Old );
+        Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms );
+*/
+        if ( i % 10 != 0 )
+            continue;
+        // check disjointness
+        assert( Sim_UtilMatrsAreDisjoint( p ) );
+        // count the number of pairs
+        Sim_UtilCountPairsAll( p );
+        if ( i % 50 != 0 )
+            continue;
+        if ( fVerbose )
+            printf( "Total = %8d.  Sym = %8d.  NonSym = %8d.  Remaining = %8d.\n", 
+                p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem );
+    }
+
+    // count the number of pairs
+    Sim_UtilCountPairsAll( p );
+    if ( fVerbose )
+        printf( "Total = %8d.  Sym = %8d.  NonSym = %8d.  Remaining = %8d.\n", 
+            p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem );
+//    Sim_UtilCountPairsAllPrint( p );
+
+    Result = p->nPairsSymm;
+    vResult = p->vMatrSymms;  
+p->timeTotal = Abc_Clock() - clkTotal;
+    //  p->vMatrSymms = NULL;
+    Sym_ManStop( p );
+    return Result;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/sim/simSymSat.c b/abc-build/src/opt/sim/simSymSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sim/simSymSat.c
@@ -0,0 +1,205 @@
+/**CFile****************************************************************
+
+  FileName    [simSymSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Satisfiability to determine two variable symmetries.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: simSymSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "proof/fraig/fraig.h"
+#include "sim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Sim_SymmsSatProveOne( Sym_Man_t * p, int Out, int Var1, int Var2, unsigned * pPattern );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Tries to prove the remaining pairs using SAT.]
+
+  Description [Continues to prove as long as it encounters symmetric pairs.
+  Returns 1 if a non-symmetric pair is found (which gives a counter-example).
+  Returns 0 if it finishes considering all pairs for all outputs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_SymmsGetPatternUsingSat( Sym_Man_t * p, unsigned * pPattern )
+{
+    Vec_Int_t * vSupport;
+    Extra_BitMat_t * pMatSym, * pMatNonSym;
+    int Index1, Index2, Index3, IndexU, IndexV;
+    int v, u, i, k, b, out;
+
+    // iterate through outputs
+    for ( out = p->iOutput; out < p->nOutputs; out++ )
+    {
+        pMatSym    = (Extra_BitMat_t *)Vec_PtrEntry( p->vMatrSymms,    out );
+        pMatNonSym = (Extra_BitMat_t *)Vec_PtrEntry( p->vMatrNonSymms, out );
+
+        // go through the remaining variable pairs
+        vSupport = Vec_VecEntryInt( p->vSupports, out );
+        Vec_IntForEachEntry( vSupport, v, Index1 )
+        Vec_IntForEachEntryStart( vSupport, u, Index2, Index1+1 )
+        {
+            if ( Extra_BitMatrixLookup1( pMatSym, v, u ) || Extra_BitMatrixLookup1( pMatNonSym, v, u ) )
+                continue;
+            p->nSatRuns++;
+
+            // collect the support variables that are symmetric with u and v
+            Vec_IntClear( p->vVarsU );
+            Vec_IntClear( p->vVarsV );
+            Vec_IntForEachEntry( vSupport, b, Index3 )
+            {
+                if ( Extra_BitMatrixLookup1( pMatSym, u, b ) )
+                    Vec_IntPush( p->vVarsU, b );
+                if ( Extra_BitMatrixLookup1( pMatSym, v, b ) )
+                    Vec_IntPush( p->vVarsV, b );
+            }
+
+            if ( Sim_SymmsSatProveOne( p, out, v, u, pPattern ) )
+            { // update the symmetric variable info            
+                p->nSatRunsUnsat++;
+                Vec_IntForEachEntry( p->vVarsU, i, IndexU )
+                Vec_IntForEachEntry( p->vVarsV, k, IndexV )
+                {
+                    Extra_BitMatrixInsert1( pMatSym,  i, k );  // Theorem 1
+                    Extra_BitMatrixInsert2( pMatSym,  i, k );  // Theorem 1
+                    Extra_BitMatrixOrTwo( pMatNonSym, i, k );  // Theorem 2
+                }
+            }
+            else
+            { // update the assymmetric variable info
+                p->nSatRunsSat++;
+                Vec_IntForEachEntry( p->vVarsU, i, IndexU )
+                Vec_IntForEachEntry( p->vVarsV, k, IndexV )
+                {
+                    Extra_BitMatrixInsert1( pMatNonSym, i, k );   // Theorem 3
+                    Extra_BitMatrixInsert2( pMatNonSym, i, k );   // Theorem 3
+                }
+
+                // remember the out
+                p->iOutput = out;
+                p->iVar1Old = p->iVar1;
+                p->iVar2Old = p->iVar2;
+                p->iVar1 = v;
+                p->iVar2 = u;
+                return 1;
+
+            }
+        }
+        // make sure that the symmetry matrix contains only cliques
+        assert( Extra_BitMatrixIsClique( pMatSym ) );
+    }
+
+    // mark that we finished all outputs
+    p->iOutput = p->nOutputs;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the variables are symmetric; 0 otherwise.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_SymmsSatProveOne( Sym_Man_t * p, int Out, int Var1, int Var2, unsigned * pPattern )
+{
+    Fraig_Params_t Params;
+    Fraig_Man_t * pMan;
+    Abc_Ntk_t * pMiter;
+    int RetValue, i;
+    abctime clk;
+    int * pModel;
+
+    // get the miter for this problem
+    pMiter = Abc_NtkMiterForCofactors( p->pNtk, Out, Var1, Var2 );
+    // transform the miter into a fraig
+    Fraig_ParamsSetDefault( &Params );
+    Params.fInternal = 1;
+    Params.nPatsRand = 512;
+    Params.nPatsDyna = 512;
+    Params.nSeconds = ABC_INFINITY;
+
+clk = Abc_Clock();
+    pMan = (Fraig_Man_t *)Abc_NtkToFraig( pMiter, &Params, 0, 0 ); 
+p->timeFraig += Abc_Clock() - clk;
+clk = Abc_Clock();
+    Fraig_ManProveMiter( pMan );
+p->timeSat += Abc_Clock() - clk;
+
+    // analyze the result
+    RetValue = Fraig_ManCheckMiter( pMan );
+//    assert( RetValue >= 0 );
+    // save the pattern
+    if ( RetValue == 0 )
+    {
+        // get the pattern
+        pModel = Fraig_ManReadModel( pMan );
+        assert( pModel != NULL );
+//printf( "Disproved by SAT: out = %d  pair = (%d, %d)\n", Out, Var1, Var2 );
+        // transfer the model into the pattern
+        for ( i = 0; i < p->nSimWords; i++ )
+            pPattern[i] = 0;
+        for ( i = 0; i < p->nInputs; i++ )
+            if ( pModel[i] )
+                Sim_SetBit( pPattern, i );
+        // make sure these variables have the same value (1)
+        Sim_SetBit( pPattern, Var1 );
+        Sim_SetBit( pPattern, Var2 );
+    }
+    else if ( RetValue == -1 )
+    {
+        // this should never happen; if it happens, such is life
+        // we are conservative and assume that there is no symmetry
+//printf( "STRANGE THING: out = %d %s  pair = (%d %s, %d %s)\n", 
+//                        Out, Abc_ObjName(Abc_NtkCo(p->pNtk,Out)), 
+//                        Var1, Abc_ObjName(Abc_NtkCi(p->pNtk,Var1)), 
+//                        Var2, Abc_ObjName(Abc_NtkCi(p->pNtk,Var2)) );
+        memset( pPattern, 0, sizeof(unsigned) * p->nSimWords );
+        RetValue = 0;
+    }
+    // delete the fraig manager
+    Fraig_ManFree( pMan );
+    // delete the miter
+    Abc_NtkDelete( pMiter );
+    return RetValue;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/sim/simSymSim.c b/abc-build/src/opt/sim/simSymSim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sim/simSymSim.c
@@ -0,0 +1,178 @@
+/**CFile****************************************************************
+
+  FileName    [simSymSim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Simulation to determine two-variable symmetries.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: simSymSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "sim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Sim_SymmsCreateSquare( Sym_Man_t * p, unsigned * pPat );
+static void Sim_SymmsDeriveInfo( Sym_Man_t * p, unsigned * pPat, Abc_Obj_t * pNode, Vec_Ptr_t * vMatrsNonSym, int Output );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Detects non-symmetric pairs using one pattern.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_SymmsSimulate( Sym_Man_t * p, unsigned * pPat, Vec_Ptr_t * vMatrsNonSym )
+{
+    Abc_Obj_t * pNode;
+    int i, nPairsTotal, nPairsSym, nPairsNonSym;
+    abctime clk;
+
+    // create the simulation matrix
+    Sim_SymmsCreateSquare( p, pPat );
+    // simulate each node in the DFS order
+clk = Abc_Clock();
+    Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodes, pNode, i )
+    {
+//        if ( Abc_NodeIsConst(pNode) )
+//            continue;
+        Sim_UtilSimulateNodeOne( pNode, p->vSim, p->nSimWords, 0 );
+    }
+p->timeSim += Abc_Clock() - clk;
+    // collect info into the CO matrices
+clk = Abc_Clock();
+    Abc_NtkForEachCo( p->pNtk, pNode, i )
+    {
+        pNode = Abc_ObjFanin0(pNode);
+//        if ( Abc_ObjIsCi(pNode) || Abc_AigNodeIsConst(pNode) )
+//            continue;
+        nPairsTotal  = Vec_IntEntry(p->vPairsTotal, i);
+        nPairsSym    = Vec_IntEntry(p->vPairsSym,   i);
+        nPairsNonSym = Vec_IntEntry(p->vPairsNonSym,i);
+        assert( nPairsTotal >= nPairsSym + nPairsNonSym ); 
+        if ( nPairsTotal == nPairsSym + nPairsNonSym )
+            continue;
+        Sim_SymmsDeriveInfo( p, pPat, pNode, vMatrsNonSym, i );
+    }
+p->timeMatr += Abc_Clock() - clk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the square matrix of simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_SymmsCreateSquare( Sym_Man_t * p, unsigned * pPat )
+{
+    unsigned * pSimInfo;
+    Abc_Obj_t * pNode;
+    int i, w;
+    // for each PI var copy the pattern
+    Abc_NtkForEachCi( p->pNtk, pNode, i )
+    {
+        pSimInfo = (unsigned *)Vec_PtrEntry( p->vSim, pNode->Id );
+        if ( Sim_HasBit(pPat, i) )
+        {
+            for ( w = 0; w < p->nSimWords; w++ )
+                pSimInfo[w] = SIM_MASK_FULL;
+        }
+        else
+        {
+            for ( w = 0; w < p->nSimWords; w++ )
+                pSimInfo[w] = 0;
+        }
+        // flip one bit
+        Sim_XorBit( pSimInfo, i );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the info to the POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_SymmsDeriveInfo( Sym_Man_t * p, unsigned * pPat, Abc_Obj_t * pNode, Vec_Ptr_t * vMatrsNonSym, int Output )
+{
+    Extra_BitMat_t * pMat;
+    Vec_Int_t * vSupport;
+    unsigned * pSupport;
+    unsigned * pSimInfo;
+    int i, w, Index;
+    // get the matrix, the support, and the simulation info
+    pMat = (Extra_BitMat_t *)Vec_PtrEntry( vMatrsNonSym, Output );
+    vSupport = Vec_VecEntryInt( p->vSupports, Output );
+    pSupport = (unsigned *)Vec_PtrEntry( p->vSuppFun, Output );
+    pSimInfo = (unsigned *)Vec_PtrEntry( p->vSim, pNode->Id );
+    // generate vectors A1 and A2
+    for ( w = 0; w < p->nSimWords; w++ )
+    {
+        p->uPatCol[w] = pSupport[w] & pPat[w] &  pSimInfo[w];
+        p->uPatRow[w] = pSupport[w] & pPat[w] & ~pSimInfo[w];
+    }
+    // add two dimensions
+    Vec_IntForEachEntry( vSupport, i, Index )
+        if ( Sim_HasBit( p->uPatCol, i ) )
+            Extra_BitMatrixOr( pMat, i, p->uPatRow );
+    // add two dimensions
+    Vec_IntForEachEntry( vSupport, i, Index )
+        if ( Sim_HasBit( p->uPatRow, i ) )
+            Extra_BitMatrixOr( pMat, i, p->uPatCol );
+    // generate vectors B1 and B2
+    for ( w = 0; w < p->nSimWords; w++ )
+    {
+        p->uPatCol[w] = pSupport[w] & ~pPat[w] &  pSimInfo[w];
+        p->uPatRow[w] = pSupport[w] & ~pPat[w] & ~pSimInfo[w];
+    }
+    // add two dimensions
+    Vec_IntForEachEntry( vSupport, i, Index )
+        if ( Sim_HasBit( p->uPatCol, i ) )
+            Extra_BitMatrixOr( pMat, i, p->uPatRow );
+    // add two dimensions
+    Vec_IntForEachEntry( vSupport, i, Index )
+        if ( Sim_HasBit( p->uPatRow, i ) )
+            Extra_BitMatrixOr( pMat, i, p->uPatCol );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/sim/simSymStr.c b/abc-build/src/opt/sim/simSymStr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sim/simSymStr.c
@@ -0,0 +1,493 @@
+/**CFile****************************************************************
+
+  FileName    [simSymStr.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Structural detection of symmetries.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: simSymStr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "sim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define SIM_READ_SYMMS(pNode)       ((Vec_Int_t *)pNode->pCopy) 
+#define SIM_SET_SYMMS(pNode,vVect)  (pNode->pCopy = (Abc_Obj_t *)(vVect)) 
+
+static void  Sim_SymmsStructComputeOne( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int * pMap );
+static void  Sim_SymmsBalanceCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes );
+static void  Sim_SymmsPartitionNodes( Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesPis0, Vec_Ptr_t * vNodesPis1, Vec_Ptr_t * vNodesOther );
+static void  Sim_SymmsAppendFromGroup( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodesPi, Vec_Ptr_t * vNodesOther, Vec_Int_t * vSymms, int * pMap );
+static void  Sim_SymmsAppendFromNode( Abc_Ntk_t * pNtk, Vec_Int_t * vSymms0, Vec_Ptr_t * vNodesOther, Vec_Ptr_t * vNodesPi0, Vec_Ptr_t * vNodesPi1, Vec_Int_t * vSymms, int * pMap );
+static int   Sim_SymmsIsCompatibleWithNodes( Abc_Ntk_t * pNtk, unsigned uSymm, Vec_Ptr_t * vNodesOther, int * pMap );
+static int   Sim_SymmsIsCompatibleWithGroup( unsigned uSymm, Vec_Ptr_t * vNodesPi, int * pMap );
+static void  Sim_SymmsPrint( Vec_Int_t * vSymms );
+static void  Sim_SymmsTrans( Vec_Int_t * vSymms );
+static void  Sim_SymmsTransferToMatrix( Extra_BitMat_t * pMatSymm, Vec_Int_t * vSymms, unsigned * pSupport );
+static int * Sim_SymmsCreateMap( Abc_Ntk_t * pNtk );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes symmetries for a single output function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_SymmsStructCompute( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMatrs, Vec_Ptr_t * vSuppFun )
+{
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t * pTemp;
+    int * pMap, i;
+
+    assert( Abc_NtkCiNum(pNtk) + 10 < (1<<16) );
+
+    // get the structural support
+    pNtk->vSupps = Sim_ComputeStrSupp( pNtk );
+    // set elementary info for the CIs
+    Abc_NtkForEachCi( pNtk, pTemp, i )
+        SIM_SET_SYMMS( pTemp, Vec_IntAlloc(0) );
+    // create the map of CI ids into their numbers
+    pMap = Sim_SymmsCreateMap( pNtk );
+    // collect the nodes in the TFI cone of this output
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pTemp, i )
+    {
+//        if ( Abc_NodeIsConst(pTemp) )
+//            continue;
+        Sim_SymmsStructComputeOne( pNtk, pTemp, pMap );
+    }
+    // collect the results for the COs;
+    Abc_NtkForEachCo( pNtk, pTemp, i )
+    {
+//printf( "Output %d:\n", i );
+        pTemp = Abc_ObjFanin0(pTemp);
+        if ( Abc_ObjIsCi(pTemp) || Abc_AigNodeIsConst(pTemp) )
+            continue;
+        Sim_SymmsTransferToMatrix( (Extra_BitMat_t *)Vec_PtrEntry(vMatrs, i), SIM_READ_SYMMS(pTemp), (unsigned *)Vec_PtrEntry(vSuppFun, i) );
+    }
+    // clean the intermediate results
+    Sim_UtilInfoFree( pNtk->vSupps );
+    pNtk->vSupps = NULL;
+    Abc_NtkForEachCi( pNtk, pTemp, i )
+        Vec_IntFree( SIM_READ_SYMMS(pTemp) );
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pTemp, i )
+//        if ( !Abc_NodeIsConst(pTemp) )
+            Vec_IntFree( SIM_READ_SYMMS(pTemp) );
+    Vec_PtrFree( vNodes );
+    ABC_FREE( pMap );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively computes symmetries. ]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_SymmsStructComputeOne( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int * pMap )
+{
+    Vec_Ptr_t * vNodes, * vNodesPi0, * vNodesPi1, * vNodesOther;
+    Vec_Int_t * vSymms;
+    Abc_Obj_t * pTemp;
+    int i;
+
+    // allocate the temporary arrays
+    vNodes      = Vec_PtrAlloc( 10 );
+    vNodesPi0   = Vec_PtrAlloc( 10 );
+    vNodesPi1   = Vec_PtrAlloc( 10 );
+    vNodesOther = Vec_PtrAlloc( 10 );  
+
+    // collect the fanins of the implication supergate
+    Sim_SymmsBalanceCollect_rec( pNode, vNodes );
+
+    // sort the nodes in the implication supergate
+    Sim_SymmsPartitionNodes( vNodes, vNodesPi0, vNodesPi1, vNodesOther );
+
+    // start the resulting set
+    vSymms = Vec_IntAlloc( 10 );
+    // generate symmetries from the groups
+    Sim_SymmsAppendFromGroup( pNtk, vNodesPi0, vNodesOther, vSymms, pMap );
+    Sim_SymmsAppendFromGroup( pNtk, vNodesPi1, vNodesOther, vSymms, pMap );
+    // add symmetries from other inputs
+    for ( i = 0; i < vNodesOther->nSize; i++ )
+    {
+        pTemp = Abc_ObjRegular((Abc_Obj_t *)vNodesOther->pArray[i]);
+        Sim_SymmsAppendFromNode( pNtk, SIM_READ_SYMMS(pTemp), vNodesOther, vNodesPi0, vNodesPi1, vSymms, pMap );
+    }
+    Vec_PtrFree( vNodes );
+    Vec_PtrFree( vNodesPi0 );
+    Vec_PtrFree( vNodesPi1 );
+    Vec_PtrFree( vNodesOther );
+
+    // set the symmetry at the node
+    SIM_SET_SYMMS( pNode, vSymms );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_SymmsBalanceCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+    // if the new node is complemented, another gate begins
+    if ( Abc_ObjIsComplement(pNode) )
+    {
+        Vec_PtrPushUnique( vNodes, pNode );
+        return;
+    }
+    // if pNew is the PI node, return
+    if ( Abc_ObjIsCi(pNode) )
+    {
+        Vec_PtrPushUnique( vNodes, pNode );
+        return;    
+    }
+    // go through the branches
+    Sim_SymmsBalanceCollect_rec( Abc_ObjChild0(pNode), vNodes );
+    Sim_SymmsBalanceCollect_rec( Abc_ObjChild1(pNode), vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Divides PI variables into groups.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_SymmsPartitionNodes( Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesPis0, 
+    Vec_Ptr_t * vNodesPis1, Vec_Ptr_t * vNodesOther )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
+    {
+        if ( !Abc_ObjIsCi(Abc_ObjRegular(pNode)) )
+            Vec_PtrPush( vNodesOther, pNode );
+        else if ( Abc_ObjIsComplement(pNode) )
+            Vec_PtrPush( vNodesPis0, pNode );
+        else
+            Vec_PtrPush( vNodesPis1, pNode );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Makes the product of two partitions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_SymmsAppendFromGroup( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodesPi, Vec_Ptr_t * vNodesOther, Vec_Int_t * vSymms, int * pMap )
+{
+    Abc_Obj_t * pNode1, * pNode2;
+    unsigned uSymm;
+    int i, k;
+
+    if ( vNodesPi->nSize == 0 )
+        return;
+
+    // go through the pairs
+    for ( i = 0; i < vNodesPi->nSize; i++ )
+    for ( k = i+1; k < vNodesPi->nSize; k++ )
+    {
+        // get the two PI nodes
+        pNode1 = Abc_ObjRegular((Abc_Obj_t *)vNodesPi->pArray[i]);
+        pNode2 = Abc_ObjRegular((Abc_Obj_t *)vNodesPi->pArray[k]);
+        assert( pMap[pNode1->Id] != pMap[pNode2->Id] );
+        assert( pMap[pNode1->Id] >= 0 );
+        assert( pMap[pNode2->Id] >= 0 );
+        // generate symmetry
+        if ( pMap[pNode1->Id] < pMap[pNode2->Id] )
+            uSymm = ((pMap[pNode1->Id] << 16) | pMap[pNode2->Id]);
+        else
+            uSymm = ((pMap[pNode2->Id] << 16) | pMap[pNode1->Id]);
+        // check if symmetry belongs
+        if ( Sim_SymmsIsCompatibleWithNodes( pNtk, uSymm, vNodesOther, pMap ) )
+            Vec_IntPushUnique( vSymms, (int)uSymm );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add the filters symmetries from the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_SymmsAppendFromNode( Abc_Ntk_t * pNtk, Vec_Int_t * vSymms0, Vec_Ptr_t * vNodesOther, 
+    Vec_Ptr_t * vNodesPi0, Vec_Ptr_t * vNodesPi1, Vec_Int_t * vSymms, int * pMap )
+{
+    unsigned uSymm;
+    int i;
+
+    if ( vSymms0->nSize == 0 )
+        return;
+
+    // go through the pairs
+    for ( i = 0; i < vSymms0->nSize; i++ )
+    {
+        uSymm = (unsigned)vSymms0->pArray[i];
+        // check if symmetry belongs
+        if ( Sim_SymmsIsCompatibleWithNodes( pNtk, uSymm, vNodesOther, pMap ) &&
+             Sim_SymmsIsCompatibleWithGroup( uSymm, vNodesPi0, pMap ) && 
+             Sim_SymmsIsCompatibleWithGroup( uSymm, vNodesPi1, pMap ) )
+            Vec_IntPushUnique( vSymms, (int)uSymm );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if symmetry is compatible with the group of nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_SymmsIsCompatibleWithNodes( Abc_Ntk_t * pNtk, unsigned uSymm, Vec_Ptr_t * vNodesOther, int * pMap )
+{
+    Vec_Int_t * vSymmsNode;
+    Abc_Obj_t * pNode;
+    int i, s, Ind1, Ind2, fIsVar1, fIsVar2;
+
+    if ( vNodesOther->nSize == 0 )
+        return 1;
+
+    // get the indices of the PI variables
+    Ind1 = (uSymm & 0xffff);
+    Ind2 = (uSymm >> 16);
+
+    // go through the nodes
+    // if they do not belong to a support, it is okay
+    // if one belongs, the other does not belong, quit
+    // if they belong, but are not part of symmetry, quit
+    for ( i = 0; i < vNodesOther->nSize; i++ )
+    {
+        pNode = Abc_ObjRegular((Abc_Obj_t *)vNodesOther->pArray[i]);
+        fIsVar1 = Sim_SuppStrHasVar( pNtk->vSupps, pNode, Ind1 );
+        fIsVar2 = Sim_SuppStrHasVar( pNtk->vSupps, pNode, Ind2 );
+
+        if ( !fIsVar1 && !fIsVar2 )
+            continue;
+        if ( fIsVar1 ^ fIsVar2 )
+            return 0;
+        // both belong
+        // check if there is a symmetry
+        vSymmsNode = SIM_READ_SYMMS( pNode );
+        for ( s = 0; s < vSymmsNode->nSize; s++ )
+            if ( uSymm == (unsigned)vSymmsNode->pArray[s] )
+                break;
+        if ( s == vSymmsNode->nSize )
+            return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if symmetry is compatible with the group of PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_SymmsIsCompatibleWithGroup( unsigned uSymm, Vec_Ptr_t * vNodesPi, int * pMap )
+{
+    Abc_Obj_t * pNode;
+    int i, Ind1, Ind2, fHasVar1, fHasVar2;
+
+    if ( vNodesPi->nSize == 0 )
+        return 1;
+
+    // get the indices of the PI variables
+    Ind1 = (uSymm & 0xffff);
+    Ind2 = (uSymm >> 16);
+
+    // go through the PI nodes
+    fHasVar1 = fHasVar2 = 0;
+    for ( i = 0; i < vNodesPi->nSize; i++ )
+    {
+        pNode = Abc_ObjRegular((Abc_Obj_t *)vNodesPi->pArray[i]);
+        if ( pMap[pNode->Id] == Ind1 )
+            fHasVar1 = 1;
+        else if ( pMap[pNode->Id] == Ind2 )
+            fHasVar2 = 1;
+    }
+    return fHasVar1 == fHasVar2;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Improvements due to transitivity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_SymmsTrans( Vec_Int_t * vSymms )
+{
+    unsigned uSymm, uSymma, uSymmr;
+    int i, Ind1, Ind2;
+    int k, Ind1a, Ind2a;
+    int j;
+    int nTrans = 0;
+
+    for ( i = 0; i < vSymms->nSize; i++ )
+    {
+        uSymm = (unsigned)vSymms->pArray[i];
+        Ind1 = (uSymm & 0xffff);
+        Ind2 = (uSymm >> 16);
+        // find other symmetries that have Ind1
+        for ( k = i+1; k < vSymms->nSize; k++ )
+        {
+            uSymma = (unsigned)vSymms->pArray[k];
+            if ( uSymma == uSymm )
+                continue;
+            Ind1a = (uSymma & 0xffff);
+            Ind2a = (uSymma >> 16);
+            if ( Ind1a == Ind1 )
+            {
+                // find the symmetry (Ind2,Ind2a)
+                if ( Ind2 < Ind2a )
+                    uSymmr = ((Ind2 << 16) | Ind2a);
+                else
+                    uSymmr = ((Ind2a << 16) | Ind2);
+                for ( j = 0; j < vSymms->nSize; j++ )
+                    if ( uSymmr == (unsigned)vSymms->pArray[j] )
+                        break;
+                if ( j == vSymms->nSize )
+                    nTrans++;
+            }
+        }
+
+    }
+    printf( "Trans = %d.\n", nTrans );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers from the vector to the matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_SymmsTransferToMatrix( Extra_BitMat_t * pMatSymm, Vec_Int_t * vSymms, unsigned * pSupport )
+{
+    int i, Ind1, Ind2, nInputs;
+    unsigned uSymm;
+    // add diagonal elements
+    nInputs = Extra_BitMatrixReadSize( pMatSymm );
+    for ( i = 0; i < nInputs; i++ )
+        Extra_BitMatrixInsert1( pMatSymm, i, i );
+    // add non-diagonal elements
+    for ( i = 0; i < vSymms->nSize; i++ )
+    {
+        uSymm = (unsigned)vSymms->pArray[i];
+        Ind1 = (uSymm & 0xffff);
+        Ind2 = (uSymm >> 16);
+//printf( "%d,%d ", Ind1, Ind2 );
+        // skip variables that are not in the true support
+        assert( Sim_HasBit(pSupport, Ind1) == Sim_HasBit(pSupport, Ind2) );
+        if ( !Sim_HasBit(pSupport, Ind1) || !Sim_HasBit(pSupport, Ind2) )
+            continue;
+        Extra_BitMatrixInsert1( pMatSymm, Ind1, Ind2 );
+        Extra_BitMatrixInsert2( pMatSymm, Ind1, Ind2 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Mapping of indices into numbers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Sim_SymmsCreateMap( Abc_Ntk_t * pNtk )
+{
+    int * pMap;
+    Abc_Obj_t * pNode;
+    int i;
+    pMap = ABC_ALLOC( int, Abc_NtkObjNumMax(pNtk) );
+    for ( i = 0; i < Abc_NtkObjNumMax(pNtk); i++ )
+        pMap[i] = -1;
+    Abc_NtkForEachCi( pNtk, pNode, i )
+        pMap[pNode->Id] = i;
+    return pMap;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/opt/sim/simUtils.c b/abc-build/src/opt/sim/simUtils.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/opt/sim/simUtils.c
@@ -0,0 +1,718 @@
+/**CFile****************************************************************
+
+  FileName    [simUtils.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Various simulation utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: simUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "sim.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+static int bit_count[256] = {
+  0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+  1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+  1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+  2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+  1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+  2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+  2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+  3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates simulation information for all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Sim_UtilInfoAlloc( int nSize, int nWords, int fClean )
+{
+    Vec_Ptr_t * vInfo;
+    int i;
+    assert( nSize > 0 && nWords > 0 );
+    vInfo = Vec_PtrAlloc( nSize );
+    vInfo->pArray[0] = ABC_ALLOC( unsigned, nSize * nWords );
+    if ( fClean )
+        memset( vInfo->pArray[0], 0, sizeof(unsigned) * nSize * nWords );
+    for ( i = 1; i < nSize; i++ )
+        vInfo->pArray[i] = ((unsigned *)vInfo->pArray[i-1]) + nWords;
+    vInfo->nSize = nSize;
+    return vInfo;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates simulation information for all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_UtilInfoFree( Vec_Ptr_t * p )
+{
+    ABC_FREE( p->pArray[0] );
+    Vec_PtrFree( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the second supp-info the first.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_UtilInfoAdd( unsigned * pInfo1, unsigned * pInfo2, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        pInfo1[w] |= pInfo2[w];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the positions where pInfo2 is 1 while pInfo1 is 0.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_UtilInfoDetectDiffs( unsigned * pInfo1, unsigned * pInfo2, int nWords, Vec_Int_t * vDiffs )
+{
+    int w, b;
+    unsigned uMask;
+    vDiffs->nSize = 0;
+    for ( w = 0; w < nWords; w++ )
+        if ( (uMask = (pInfo2[w] ^ pInfo1[w])) )
+            for ( b = 0; b < 32; b++ )
+                if ( uMask & (1 << b) )
+                    Vec_IntPush( vDiffs, 32*w + b );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the positions where pInfo2 is 1 while pInfo1 is 0.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_UtilInfoDetectNews( unsigned * pInfo1, unsigned * pInfo2, int nWords, Vec_Int_t * vDiffs )
+{
+    int w, b;
+    unsigned uMask;
+    vDiffs->nSize = 0;
+    for ( w = 0; w < nWords; w++ )
+        if ( (uMask = (pInfo2[w] & ~pInfo1[w])) )
+            for ( b = 0; b < 32; b++ )
+                if ( uMask & (1 << b) )
+                    Vec_IntPush( vDiffs, 32*w + b );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Flips the simulation info of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_UtilInfoFlip( Sim_Man_t * p, Abc_Obj_t * pNode )
+{
+    unsigned * pSimInfo1, * pSimInfo2;
+    int k;
+    pSimInfo1 = (unsigned *)p->vSim0->pArray[pNode->Id];
+    pSimInfo2 = (unsigned *)p->vSim1->pArray[pNode->Id];
+    for ( k = 0; k < p->nSimWords; k++ )
+        pSimInfo2[k] = ~pSimInfo1[k];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the simulation infos are equal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_UtilInfoCompare( Sim_Man_t * p, Abc_Obj_t * pNode )
+{
+    unsigned * pSimInfo1, * pSimInfo2;
+    int k;
+    pSimInfo1 = (unsigned *)p->vSim0->pArray[pNode->Id];
+    pSimInfo2 = (unsigned *)p->vSim1->pArray[pNode->Id];
+    for ( k = 0; k < p->nSimWords; k++ )
+        if ( pSimInfo2[k] != pSimInfo1[k] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_UtilSimulate( Sim_Man_t * p, int fType )
+{
+    Abc_Obj_t * pNode;
+    int i;
+    // simulate the internal nodes
+    Abc_NtkForEachNode( p->pNtk, pNode, i )
+        Sim_UtilSimulateNode( p, pNode, fType, fType, fType );
+    // assign simulation info of the CO nodes
+    Abc_NtkForEachCo( p->pNtk, pNode, i )
+        Sim_UtilSimulateNode( p, pNode, fType, fType, fType );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_UtilSimulateNode( Sim_Man_t * p, Abc_Obj_t * pNode, int fType, int fType1, int fType2 )
+{
+    unsigned * pSimmNode, * pSimmNode1, * pSimmNode2;
+    int k, fComp1, fComp2;
+    // simulate the internal nodes
+    if ( Abc_ObjIsNode(pNode) )
+    {
+        if ( fType )
+            pSimmNode  = (unsigned *)p->vSim1->pArray[ pNode->Id ];
+        else
+            pSimmNode  = (unsigned *)p->vSim0->pArray[ pNode->Id ];
+
+        if ( fType1 )
+            pSimmNode1 = (unsigned *)p->vSim1->pArray[ Abc_ObjFaninId0(pNode) ];
+        else
+            pSimmNode1 = (unsigned *)p->vSim0->pArray[ Abc_ObjFaninId0(pNode) ];
+
+        if ( fType2 )
+            pSimmNode2 = (unsigned *)p->vSim1->pArray[ Abc_ObjFaninId1(pNode) ];
+        else
+            pSimmNode2 = (unsigned *)p->vSim0->pArray[ Abc_ObjFaninId1(pNode) ];
+
+        fComp1 = Abc_ObjFaninC0(pNode);
+        fComp2 = Abc_ObjFaninC1(pNode);
+        if ( fComp1 && fComp2 )
+            for ( k = 0; k < p->nSimWords; k++ )
+                pSimmNode[k] = ~pSimmNode1[k] & ~pSimmNode2[k];
+        else if ( fComp1 && !fComp2 )
+            for ( k = 0; k < p->nSimWords; k++ )
+                pSimmNode[k] = ~pSimmNode1[k] &  pSimmNode2[k];
+        else if ( !fComp1 && fComp2 )
+            for ( k = 0; k < p->nSimWords; k++ )
+                pSimmNode[k] =  pSimmNode1[k] & ~pSimmNode2[k];
+        else // if ( fComp1 && fComp2 )
+            for ( k = 0; k < p->nSimWords; k++ )
+                pSimmNode[k] =  pSimmNode1[k] &  pSimmNode2[k];
+    }
+    else 
+    {
+        assert( Abc_ObjFaninNum(pNode) == 1 );
+        if ( fType )
+            pSimmNode  = (unsigned *)p->vSim1->pArray[ pNode->Id ];
+        else
+            pSimmNode  = (unsigned *)p->vSim0->pArray[ pNode->Id ];
+
+        if ( fType1 )
+            pSimmNode1 = (unsigned *)p->vSim1->pArray[ Abc_ObjFaninId0(pNode) ];
+        else
+            pSimmNode1 = (unsigned *)p->vSim0->pArray[ Abc_ObjFaninId0(pNode) ];
+
+        fComp1 = Abc_ObjFaninC0(pNode);
+        if ( fComp1 )
+            for ( k = 0; k < p->nSimWords; k++ )
+                pSimmNode[k] = ~pSimmNode1[k];
+        else 
+            for ( k = 0; k < p->nSimWords; k++ )
+                pSimmNode[k] =  pSimmNode1[k];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset )
+{
+    unsigned * pSimmNode, * pSimmNode1, * pSimmNode2;
+    int k, fComp1, fComp2;
+    // simulate the internal nodes
+    assert( Abc_ObjIsNode(pNode) );
+    pSimmNode  = (unsigned *)Vec_PtrEntry(vSimInfo, pNode->Id);
+    pSimmNode1 = (unsigned *)Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
+    pSimmNode2 = (unsigned *)Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode));
+    pSimmNode  += nOffset;
+    pSimmNode1 += nOffset;
+    pSimmNode2 += nOffset;
+    fComp1 = Abc_ObjFaninC0(pNode);
+    fComp2 = Abc_ObjFaninC1(pNode);
+    if ( fComp1 && fComp2 )
+        for ( k = 0; k < nSimWords; k++ )
+            pSimmNode[k] = ~pSimmNode1[k] & ~pSimmNode2[k];
+    else if ( fComp1 && !fComp2 )
+        for ( k = 0; k < nSimWords; k++ )
+            pSimmNode[k] = ~pSimmNode1[k] &  pSimmNode2[k];
+    else if ( !fComp1 && fComp2 )
+        for ( k = 0; k < nSimWords; k++ )
+            pSimmNode[k] =  pSimmNode1[k] & ~pSimmNode2[k];
+    else // if ( fComp1 && fComp2 )
+        for ( k = 0; k < nSimWords; k++ )
+            pSimmNode[k] =  pSimmNode1[k] &  pSimmNode2[k];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_UtilTransferNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset, int fShift )
+{
+    unsigned * pSimmNode, * pSimmNode1;
+    int k, fComp1;
+    // simulate the internal nodes
+    assert( Abc_ObjIsCo(pNode) );
+    pSimmNode  = (unsigned *)Vec_PtrEntry(vSimInfo, pNode->Id);
+    pSimmNode1 = (unsigned *)Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
+    pSimmNode  += nOffset + (fShift > 0)*nSimWords;
+    pSimmNode1 += nOffset;
+    fComp1 = Abc_ObjFaninC0(pNode);
+    if ( fComp1 )
+        for ( k = 0; k < nSimWords; k++ )
+            pSimmNode[k] = ~pSimmNode1[k];
+    else 
+        for ( k = 0; k < nSimWords; k++ )
+            pSimmNode[k] =  pSimmNode1[k];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the simulation infos are equal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_UtilCountSuppSizes( Sim_Man_t * p, int fStruct )
+{
+    Abc_Obj_t * pNode, * pNodeCi;
+    int i, v, Counter;
+    Counter = 0;
+    if ( fStruct )
+    {
+        Abc_NtkForEachCo( p->pNtk, pNode, i )
+            Abc_NtkForEachCi( p->pNtk, pNodeCi, v )
+                Counter += Sim_SuppStrHasVar( p->vSuppStr, pNode, v );
+    }
+    else
+    {
+        Abc_NtkForEachCo( p->pNtk, pNode, i )
+            Abc_NtkForEachCi( p->pNtk, pNodeCi, v )
+                Counter += Sim_SuppFunHasVar( p->vSuppFun, i, v );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of 1's in the bitstring.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_UtilCountOnes( unsigned * pSimInfo, int nSimWords )
+{
+    unsigned char * pBytes;
+    int nOnes, nBytes, i;
+    pBytes = (unsigned char *)pSimInfo;
+    nBytes = 4 * nSimWords;
+    nOnes  = 0;
+    for ( i = 0; i < nBytes; i++ )
+        nOnes += bit_count[ pBytes[i] ];
+    return nOnes;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of 1's in the bitstring.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Sim_UtilCountOnesArray( Vec_Ptr_t * vInfo, int nSimWords )
+{
+    Vec_Int_t * vCounters;
+    unsigned * pSimInfo;
+    int i;
+    vCounters = Vec_IntStart( Vec_PtrSize(vInfo) );
+    Vec_PtrForEachEntry( unsigned *, vInfo, pSimInfo, i )
+        Vec_IntWriteEntry( vCounters, i, Sim_UtilCountOnes(pSimInfo, nSimWords) );
+    return vCounters;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns random patterns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_UtilSetRandom( unsigned * pPatRand, int nSimWords )
+{
+    int k;
+    for ( k = 0; k < nSimWords; k++ )
+        pPatRand[k] = SIM_RANDOM_UNSIGNED;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns complemented patterns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_UtilSetCompl( unsigned * pPatRand, int nSimWords )
+{
+    int k;
+    for ( k = 0; k < nSimWords; k++ )
+        pPatRand[k] = ~pPatRand[k];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns constant patterns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_UtilSetConst( unsigned * pPatRand, int nSimWords, int fConst1 )
+{
+    int k;
+    for ( k = 0; k < nSimWords; k++ )
+        pPatRand[k] = 0;
+    if ( fConst1 )
+        Sim_UtilSetCompl( pPatRand, nSimWords );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if equal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_UtilInfoIsEqual( unsigned * pPats1, unsigned * pPats2, int nSimWords )
+{
+    int k;
+    for ( k = 0; k < nSimWords; k++ )
+        if ( pPats1[k] != pPats2[k] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if Node1 implies Node2.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_UtilInfoIsImp( unsigned * pPats1, unsigned * pPats2, int nSimWords )
+{
+    int k;
+    for ( k = 0; k < nSimWords; k++ )
+        if ( pPats1[k] & ~pPats2[k] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if Node1 v Node2 is always true.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_UtilInfoIsClause( unsigned * pPats1, unsigned * pPats2, int nSimWords )
+{
+    int k;
+    for ( k = 0; k < nSimWords; k++ )
+        if ( ~pPats1[k] & ~pPats2[k] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the total number of pairs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_UtilCountAllPairs( Vec_Ptr_t * vSuppFun, int nSimWords, Vec_Int_t * vCounters )
+{
+    unsigned * pSupp;
+    int Counter, nOnes, nPairs, i;
+    Counter = 0;
+    Vec_PtrForEachEntry( unsigned *, vSuppFun, pSupp, i )
+    {
+        nOnes  = Sim_UtilCountOnes( pSupp, nSimWords );
+        nPairs = nOnes * (nOnes - 1) / 2;
+        Vec_IntWriteEntry( vCounters, i, nPairs );
+        Counter += nPairs;
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of entries in the array of matrices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_UtilCountPairsOne( Extra_BitMat_t * pMat, Vec_Int_t * vSupport )
+{
+    int i, k, Index1, Index2;
+    int Counter = 0;
+//    int Counter2;
+    Vec_IntForEachEntry( vSupport, i, Index1 )
+    Vec_IntForEachEntryStart( vSupport, k, Index2, Index1+1 )
+        Counter += Extra_BitMatrixLookup1( pMat, i, k );
+//    Counter2 = Extra_BitMatrixCountOnesUpper(pMat);
+//    assert( Counter == Counter2 );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of entries in the array of matrices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_UtilCountPairsOnePrint( Extra_BitMat_t * pMat, Vec_Int_t * vSupport )
+{
+    int i, k, Index1, Index2;
+    Vec_IntForEachEntry( vSupport, i, Index1 )
+    Vec_IntForEachEntryStart( vSupport, k, Index2, Index1+1 )
+        if ( Extra_BitMatrixLookup1( pMat, i, k ) )
+            printf( "(%d,%d) ", i, k );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of entries in the array of matrices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_UtilCountPairsAllPrint( Sym_Man_t * p )
+{
+    int i;
+    abctime clk;
+clk = Abc_Clock();
+    for ( i = 0; i < p->nOutputs; i++ )
+    {
+        printf( "Output %2d :", i );
+        Sim_UtilCountPairsOnePrint( (Extra_BitMat_t *)Vec_PtrEntry(p->vMatrSymms, i), Vec_VecEntryInt(p->vSupports, i) );
+        printf( "\n" );
+    }
+p->timeCount += Abc_Clock() - clk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of entries in the array of matrices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sim_UtilCountPairsAll( Sym_Man_t * p )
+{
+    int nPairsTotal, nPairsSym, nPairsNonSym, i;
+    abctime clk;
+clk = Abc_Clock();
+    p->nPairsSymm    = 0;
+    p->nPairsNonSymm = 0;
+    for ( i = 0; i < p->nOutputs; i++ )
+    {
+        nPairsTotal  = Vec_IntEntry(p->vPairsTotal, i);
+        nPairsSym    = Vec_IntEntry(p->vPairsSym,   i);
+        nPairsNonSym = Vec_IntEntry(p->vPairsNonSym,i);
+        assert( nPairsTotal >= nPairsSym + nPairsNonSym ); 
+        if ( nPairsTotal == nPairsSym + nPairsNonSym )
+        {
+            p->nPairsSymm    += nPairsSym;
+            p->nPairsNonSymm += nPairsNonSym;
+            continue;
+        }
+        nPairsSym    = Sim_UtilCountPairsOne( (Extra_BitMat_t *)Vec_PtrEntry(p->vMatrSymms,   i), Vec_VecEntryInt(p->vSupports, i) );
+        nPairsNonSym = Sim_UtilCountPairsOne( (Extra_BitMat_t *)Vec_PtrEntry(p->vMatrNonSymms,i), Vec_VecEntryInt(p->vSupports, i) );
+        assert( nPairsTotal >= nPairsSym + nPairsNonSym ); 
+        Vec_IntWriteEntry( p->vPairsSym,    i, nPairsSym );
+        Vec_IntWriteEntry( p->vPairsNonSym, i, nPairsNonSym );
+        p->nPairsSymm    += nPairsSym;
+        p->nPairsNonSymm += nPairsNonSym;
+//        printf( "%d ", nPairsTotal - nPairsSym - nPairsNonSym );
+    }
+//printf( "\n" );
+    p->nPairsRem = p->nPairsTotal-p->nPairsSymm-p->nPairsNonSymm;
+p->timeCount += Abc_Clock() - clk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sim_UtilMatrsAreDisjoint( Sym_Man_t * p )
+{
+    int i;
+    for ( i = 0; i < p->nOutputs; i++ )
+        if ( !Extra_BitMatrixIsDisjoint( (Extra_BitMat_t *)Vec_PtrEntry(p->vMatrSymms,i), (Extra_BitMat_t *)Vec_PtrEntry(p->vMatrNonSymms,i) ) )
+            return 0;
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/phys/place/Makefile b/abc-build/src/phys/place/Makefile
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/Makefile
@@ -0,0 +1,30 @@
+TARGETS = place_test BookshelfView.class
+
+CFLAGS = -g -pedantic -Wall
+
+STATIC_LIBS = libhmetis.a
+DYNAMIC_LIBS = -lm
+
+OBJECTS = place_test.o place_qpsolver.o place_base.o place_pads.o place_genqp.o place_gordian.o \
+	place_partition.o place_legalize.o place_bin.o
+
+
+# For hMetis free code, uncomment the following lines
+#
+# CFLAGS = -g -pedantic -Wall -DNO_HMETIS
+# STATIC_LIBS =
+
+
+all: $(TARGETS)
+
+%.o: %.c *.h
+	gcc $(CFLAGS) -c -o $@ $<
+
+place_test: $(OBJECTS)
+	gcc *.o $(STATIC_LIBS) $(DYNAMIC_LIBS) -o place_test
+
+BookshelfView.class: BookshelfView.java
+	javac BookshelfView.java
+
+clean:
+	rm -rf *.o place_test *.class *~
diff --git a/abc-build/src/phys/place/README b/abc-build/src/phys/place/README
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/README
@@ -0,0 +1,50 @@
+/*===================================================================*/
+//  
+// GORDIAN-like placement package
+//
+//              Aaron P. Hurst (ahurst@eecs.berkeley.edu)
+//              Addl code from Philip Chong (pchong@cadence.com)
+//              hMetis partitioner (www.cs.umn.edu/~metis)
+//
+/*===================================================================*/
+
+1. Requirements
+
+An i386 Linux system (though others will certainly work with some tweaks).
+A standard ANSI C development platform.  
+
+The following are optional, but useful:
+
+- hMetis partitioner.  This can be obtained from (www.cs.umn.edu/~metis)
+    Place (links to) the files "libhmetis.a" and "libhtmetis.h" in this directory.
+    Otherwise, #define NO_HMETIS in the file "place_gordian.h"
+- Java SDK, if compiling BookshelfView is desired.
+- Perl, if additional script utilities are desired.
+
+2. Descriptions of contents:
+
+place_base.h contains the basic data structures and "external" API.
+place_gordian.h contains the "internal" API and configuration options.
+
+There are also several utilities:
+
+i) place_test 
+
+Reads a netlist description in GSRC Bookshelf format, performs global placement,
+and rewrites the placement file.  An example usage:
+
+./place_test ac97_emap.nodes ac97_emap.nets ac97_emap.pl
+
+ii) BookshelfView
+
+A simple Java GUI to view the resulting placements.  It has been tested with
+Java 5 and 6.  Usage:
+
+java BookshelfView ac97_emap.nodes ac97_emap.pl
+
+iii) hpwl
+
+A perl script to print the half-perimeter wirelength of a placement.  Usage:
+
+./hpwl ac97_emap.nets ac97_emal.pl
+
diff --git a/abc-build/src/phys/place/hpwl b/abc-build/src/phys/place/hpwl
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/hpwl
@@ -0,0 +1,57 @@
+#! /usr/bin/perl
+
+$netsfile = shift;
+$plfile = shift;
+
+# ------------------------------ read placement
+
+open FILE, $plfile;
+while (<FILE>) {
+  chop;
+  if (/(\w+)\s+([\-\d\.]+)\s+([\-\d\.]+)\s+\:/) {
+    $loc{$1} = "$2 $3";
+  }
+}
+close FILE;
+
+open FILE, $netsfile;
+while (<FILE>) {
+  chop;
+  $net = $2 if /NetDegree\s+\:\s+(\d+)\s+(\w+)/;
+  if (/(\w+)\s+(\w+)\s+\:/) {
+    $netconn{$net} .= "$1 ";
+    $cellconn{$1} .= "$net ";
+  }
+}
+close FILE;
+
+# ----------------------------- compute HPWL
+
+$hpwl = 0;
+foreach $net (keys %netconn) {
+  @conns = split ' ',$netconn{$net};
+  $min_x = $min_y = 1e12;
+  $max_x = $max_y = -1e12;
+  foreach $cell (@conns) {
+    if (!exists $loc{$cell}) {
+      print "WARNING: Unknown cell location: $cell\n";
+    } else {
+      ($x, $y) = split ' ',$loc{$cell};
+      $min_x = $x if $x < $min_x;
+      $min_y = $y if $y < $min_y;
+      $max_x = $x if $x > $max_x;
+      $max_y = $y if $y > $max_y;
+    }
+  }
+  
+  if ($min_x eq 1e12 or $min_y eq 1e12 or
+      $max_x eq -1e12 or $max_y eq -1e12) {
+    print "WARNING: Unbounded box\n";
+  } else {
+    $hpwl = $hpwl + $max_x - $min_x + $max_y - $min_y;
+  }
+}
+
+print "HPWL = ";
+printf "%e",$hpwl;
+print "\n";
diff --git a/abc-build/src/phys/place/libhmetis.h b/abc-build/src/phys/place/libhmetis.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/libhmetis.h
@@ -0,0 +1,39 @@
+// A. Hurst ahurst@eecs.berkeley.edu
+
+#ifndef ABC__phys__place__libhmetis_h
+#define ABC__phys__place__libhmetis_h
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+static void HMETIS_PartRecursive(int nvtxs, 
+			  int nhedges, 
+			  int *vwgts, 
+			  int *eptr,
+			  int *eind,
+			  int *hewgts, 
+			  int nparts, 
+			  int nbfactor, 
+			  int *options, 
+			  int *part, 
+              int *edgecnt ) {} //;
+
+
+static void HMETIS_PartKway(int nvtxs, 
+		     int nhedges, 
+		     int *vwgts, 
+		     int *eptr, 
+		     int *eind,
+		     int *hewgts, 
+		     int nparts, 
+		     int nbfactor, 
+		     int *options, 
+		     int *part, 
+             int *edgecnt ) {} //;
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/phys/place/module.make b/abc-build/src/phys/place/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/module.make
@@ -0,0 +1,10 @@
+SRC +=  src/phys/place/place_base.c \
+	src/phys/place/place_bin.c \
+	src/phys/place/place_genqp.c \
+	src/phys/place/place_gordian.c \
+	src/phys/place/place_legalize.c \
+	src/phys/place/place_pads.c \
+	src/phys/place/place_partition.c \
+	src/phys/place/place_qpsolver.c \
+        src/phys/place/place_io.c \
+        src/phys/place/place_inc.c
diff --git a/abc-build/src/phys/place/place_base.c b/abc-build/src/phys/place/place_base.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/place_base.c
@@ -0,0 +1,350 @@
+/*===================================================================*/
+//  
+//     place_base.c
+//
+//		Aaron P. Hurst, 2003-2007
+//              ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdlib.h>
+#include <limits.h>
+#include <assert.h>
+#include <string.h>
+
+#include "place_base.h"
+#include "place_gordian.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+// --------------------------------------------------------------------
+// Global variables
+//
+// --------------------------------------------------------------------
+
+int   g_place_numCells = 0;
+int   g_place_numNets = 0;
+float g_place_rowHeight = 1.0;
+
+Rect  g_place_coreBounds;
+Rect  g_place_padBounds;
+
+ConcreteCell **g_place_concreteCells = NULL;
+int            g_place_concreteCellsSize = 0;
+ConcreteNet  **g_place_concreteNets = NULL;
+int            g_place_concreteNetsSize = 0;
+
+
+// --------------------------------------------------------------------
+// getNetBBox()
+//
+/// \brief Returns the bounding box of a net.
+//
+// --------------------------------------------------------------------
+Rect   getNetBBox(const ConcreteNet *net) {
+  int t;
+  Rect r;
+
+  assert(net);
+
+  r.x = r.y = INT_MAX;
+  r.w = r.h = -INT_MAX;
+  for(t=0; t<net->m_numTerms; t++) {
+    r.x = net->m_terms[t]->m_x < r.x ? net->m_terms[t]->m_x : r.x;
+    r.y = net->m_terms[t]->m_y < r.y ? net->m_terms[t]->m_y : r.y;
+    r.w = net->m_terms[t]->m_x > r.w ? net->m_terms[t]->m_x : r.w;
+    r.h = net->m_terms[t]->m_y > r.h ? net->m_terms[t]->m_y : r.h;
+  }
+  r.w -= r.x; r.h -= r.y;
+  return r;
+}
+
+
+// --------------------------------------------------------------------
+// getNetWirelength()
+//
+/// \brief Returns the half-perimeter wirelength of a net.
+//
+// --------------------------------------------------------------------
+float getNetWirelength(const ConcreteNet *net) {
+  Rect r;
+
+  assert(net);
+
+  r = getNetBBox(net);
+  return r.w+r.h;
+}
+
+
+// --------------------------------------------------------------------
+// getTotalWirelength()
+//
+/// \brief Returns the total HPWL of all nets.
+//
+// --------------------------------------------------------------------
+float getTotalWirelength() {
+  float r = 0;
+  int n;
+  for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n])
+    r += getNetWirelength(g_place_concreteNets[n]);
+  return r;
+}
+
+
+// --------------------------------------------------------------------
+// getCellArea()
+//
+// --------------------------------------------------------------------
+float getCellArea(const ConcreteCell *cell) {
+  assert(cell);
+  return cell->m_parent->m_width*cell->m_parent->m_height;
+}
+
+
+// --------------------------------------------------------------------
+// addConcreteNet()
+//
+/// \brief Adds a net to the placement database.
+///
+/// The net object must already be allocated and the ID must be set
+/// appropriately.
+//
+// --------------------------------------------------------------------
+void   addConcreteNet(ConcreteNet *net) {
+  assert(net);
+  assert(net->m_id >= 0);
+  if (net->m_id >= g_place_concreteNetsSize) {
+    g_place_concreteNetsSize = (net->m_id > g_place_concreteNetsSize ? 
+                               net->m_id : g_place_concreteNetsSize);
+    g_place_concreteNetsSize *= 1.5;
+    g_place_concreteNetsSize += 20;
+    g_place_concreteNets = (ConcreteNet**)realloc(g_place_concreteNets, 
+             sizeof(ConcreteNet*)*g_place_concreteNetsSize);
+    assert(g_place_concreteNets);
+  }
+  if (net->m_id >= g_place_numNets) {
+    memset(&(g_place_concreteNets[g_place_numNets]), 0,
+            sizeof(ConcreteNet*)*(net->m_id+1-g_place_numNets));
+    g_place_numNets = net->m_id+1;
+    assert(g_place_numNets <= g_place_concreteNetsSize);
+  }
+  g_place_concreteNets[net->m_id] = net;
+}
+
+
+// --------------------------------------------------------------------
+// delConcreteNet()
+//
+/// Does not deallocate memory.
+// --------------------------------------------------------------------
+void   delConcreteNet(ConcreteNet *net) {
+  assert(net);
+  g_place_concreteNets[net->m_id] = 0;
+  while(!g_place_concreteNets[g_place_numNets-1]) g_place_numNets--;
+}
+
+
+// --------------------------------------------------------------------
+// addConcreteCell()
+//
+/// The cell object must already be allocated and the ID must be set
+/// appropriately.
+//
+// --------------------------------------------------------------------
+void   addConcreteCell(ConcreteCell *cell) {
+  assert(cell);
+  assert(cell->m_id >= 0);
+  if (cell->m_id >= g_place_concreteCellsSize) {
+    g_place_concreteCellsSize = (cell->m_id > g_place_concreteCellsSize ? 
+                                 cell->m_id : g_place_concreteCellsSize);
+    g_place_concreteCellsSize *= 1.5;
+    g_place_concreteCellsSize += 20;
+    g_place_concreteCells = (ConcreteCell**)realloc(g_place_concreteCells, 
+          sizeof(ConcreteCell*)*g_place_concreteCellsSize);
+    assert(g_place_concreteCells);
+  }
+  if (cell->m_id >= g_place_numCells) {
+    memset(&(g_place_concreteCells[g_place_numCells]), 0,
+          sizeof(ConcreteCell*)*(cell->m_id+1-g_place_numCells));
+    g_place_numCells = cell->m_id+1;
+  }
+  g_place_concreteCells[cell->m_id] = cell;
+}
+
+
+// --------------------------------------------------------------------
+// delCellFromPartition()
+//
+// --------------------------------------------------------------------
+void delCellFromPartition(ConcreteCell *cell, Partition *p) {
+  int c;
+  bool found = false;
+
+  assert(cell);
+  assert(p);
+
+  for(c=0; c<p->m_numMembers; c++) 
+    if (p->m_members[c] == cell) {
+      p->m_members[c] = 0;
+      p->m_area -= getCellArea(cell);
+      found = true;
+      break;
+    }
+     
+  if (!found) return;
+
+  if (!p->m_leaf) {
+    delCellFromPartition(cell, p->m_sub1);
+    delCellFromPartition(cell, p->m_sub2);
+  }
+}
+
+
+// --------------------------------------------------------------------
+// delConcreteCell()
+//
+/// \brief Removes a cell from the placement database.
+///
+/// Does not deallocate memory.
+///
+/// Important: does not modify nets that may point to this
+/// cell. If these are connections are not removed, segmentation faults 
+/// and other nasty errors will occur.
+//
+// --------------------------------------------------------------------
+void   delConcreteCell(ConcreteCell *cell) {
+  assert(cell);
+  g_place_concreteCells[cell->m_id] = 0;
+  while(!g_place_concreteCells[g_place_numCells-1]) g_place_numCells--;
+
+  if (g_place_rootPartition) delCellFromPartition(cell, g_place_rootPartition);
+}
+
+
+// --------------------------------------------------------------------
+// netSortByX...
+//
+/// \brief Sorts nets by position of one of its corners.
+//
+/// These are for use with qsort().
+///
+/// Can tolerate pointers to NULL objects.
+///
+// --------------------------------------------------------------------
+int netSortByL(const void *a, const void *b) {
+  const ConcreteNet *pa = *(const ConcreteNet **)a;
+  const ConcreteNet *pb = *(const ConcreteNet **)b;
+  Rect ba, bb;
+
+  if (!pa && !pb) return 0;
+  else if (!pa) return -1;
+  else if (!pb) return 1;
+  ba = getNetBBox(pa), bb = getNetBBox(pb);
+  if (ba.x < bb.x) return -1;
+  if (ba.x > bb.x) return 1;
+  return 0;
+}
+
+int netSortByR(const void *a, const void *b) {
+  const ConcreteNet *pa = *(const ConcreteNet **)a;
+  const ConcreteNet *pb = *(const ConcreteNet **)b;
+  Rect ba, bb;
+
+  if (!pa && !pb) return 0;
+  else if (!pa) return -1;
+  else if (!pb) return 1;
+  ba = getNetBBox(pa), bb = getNetBBox(pb);
+  if (ba.x + ba.w < bb.x + bb.w) return -1;
+  if (ba.x + ba.w > bb.x + bb.w) return 1;
+  return 0;
+}
+
+int netSortByB(const void *a, const void *b) {
+  const ConcreteNet *pa = *(const ConcreteNet **)a;
+  const ConcreteNet *pb = *(const ConcreteNet **)b;
+  Rect ba, bb;
+
+  if (!pa && !pb) return 0;
+  else if (!pa) return -1;
+  else if (!pb) return 1;
+  ba = getNetBBox(pa), bb = getNetBBox(pb);
+  if (ba.y + ba.h < bb.y + bb.h) return -1;
+  if (ba.y + ba.h > bb.y + bb.h) return 1;
+  return 0;
+}
+
+int netSortByT(const void *a, const void *b) {
+  const ConcreteNet *pa = *(const ConcreteNet **)a;
+  const ConcreteNet *pb = *(const ConcreteNet **)b;
+  Rect ba, bb;
+
+  if (!pa && !pb) return 0;
+  else if (!pa) return -1;
+  else if (!pb) return 1;
+  ba = getNetBBox(pa), bb = getNetBBox(pb);
+  if (ba.y < bb.y) return -1;
+  if (ba.y > bb.y) return 1;
+  return 0;
+}
+
+int netSortByID(const void *a, const void *b) {
+  const ConcreteNet *pa = *(const ConcreteNet **)a;
+  const ConcreteNet *pb = *(const ConcreteNet **)b;
+
+  if (!pa && !pb) return 0;
+  else if (!pa) return -1;
+  else if (!pb) return 1;
+  if (pa->m_id < pb->m_id) return -1;
+  if (pa->m_id > pb->m_id) return 1;
+  return 0;
+}
+
+
+// --------------------------------------------------------------------
+// cellSortByX...
+//
+/// \brief Sorts cells by either position coordinate.
+//
+/// These are for use with qsort().
+///
+/// Can tolerate pointers to NULL objects.
+//
+// --------------------------------------------------------------------
+int cellSortByX(const void *a, const void *b) {
+  const ConcreteCell *pa = *(const ConcreteCell **)a;
+  const ConcreteCell *pb = *(const ConcreteCell **)b;
+
+  if (!pa && !pb) return 0;
+  else if (!pa) return -1;
+  else if (!pb) return 1;
+  if (pa->m_x < pb->m_x) return -1;
+  if (pa->m_x > pb->m_x) return 1;
+  return 0;
+}
+
+int cellSortByY(const void *a, const void *b) {
+  const ConcreteCell *pa = *(const ConcreteCell **)a;
+  const ConcreteCell *pb = *(const ConcreteCell **)b;
+
+  if (!pa && !pb) return 0;
+  else if (!pa) return -1;
+  else if (!pb) return 1;
+  if (pa->m_y < pb->m_y) return -1;
+  if (pa->m_y > pb->m_y) return 1;
+  return 0;
+}
+
+int cellSortByID(const void *a, const void *b) {
+  const ConcreteCell *pa = *(const ConcreteCell **)a;
+  const ConcreteCell *pb = *(const ConcreteCell **)b;
+
+  if (!pa && !pb) return 0;
+  else if (!pa) return -1;
+  else if (!pb) return 1;
+  if (pa->m_id < pb->m_id) return -1;
+  if (pa->m_id > pb->m_id) return 1;
+  return 0;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/phys/place/place_base.h b/abc-build/src/phys/place/place_base.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/place_base.h
@@ -0,0 +1,145 @@
+/*===================================================================*/
+//  
+//     place_base.h
+//
+//		Aaron P. Hurst, 2003-2007
+//              ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#if !defined(PLACE_BASE_H_)
+#define ABC__phys__place__place_base_h
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+// --------------------------------------------------------------------
+// Data structures
+//
+// --------------------------------------------------------------------
+
+// --- a C++ bool-like type
+//typedef char bool;
+#ifndef ABC__phys__place__place_base_h
+#define bool int
+#endif
+
+#define true 1
+#define false 0
+
+
+// --- Rect - rectangle
+
+typedef struct Rect {
+  float x, y;
+  float w, h;
+} Rect;
+
+
+// --- AbstractCell - a definition of a cell type
+
+typedef struct AbstractCell {
+  char *m_label;            // string description
+
+  float m_width, m_height;  // dimensions
+
+  bool  m_pad;              // a pad (external I/O) cell?
+} AbstractCell;
+
+
+// --- ConcreteCell - a design object
+
+typedef struct ConcreteCell {
+  int           m_id;       // a unique ID (see below)
+  char         *m_label;    // string description
+
+  AbstractCell *m_parent;   // cell type
+
+  bool          m_fixed;    // position is fixed?
+  float         m_x, m_y;   // center of cell
+
+  int           m_data;
+} ConcreteCell;
+
+
+// --- ConcreteNet - a design net
+
+typedef struct ConcreteNet {
+  int            m_id;       // a unique ID (see below)
+
+  int            m_numTerms; // num. of connected cells
+  ConcreteCell **m_terms;    // connected cells
+
+  float          m_weight;   // relative weight
+
+  int            m_data;
+} ConcreteNet;
+
+
+// A note about IDs - the IDs are non-nonegative integers. They need not
+// be contiguous, but this is certainly a good idea, as they are stored
+// in a non-sparse array.
+// Cells and nets have separate ID spaces.
+
+// --------------------------------------------------------------------
+// Global variable prototypes
+//
+// --------------------------------------------------------------------
+
+// NOTE: None of these need to be managed externally.
+
+extern int   g_place_numCells;   // number of cells
+extern int   g_place_numNets;    // number of nets
+extern float g_place_rowHeight;  // height of placement row
+extern Rect  g_place_coreBounds; // border of placeable area
+                                 // (x,y) = corner
+extern Rect  g_place_padBounds;  // border of total die area
+                                 // (x,y) = corner
+
+extern ConcreteCell **g_place_concreteCells; // all concrete cells
+extern ConcreteNet  **g_place_concreteNets;  // all concrete nets
+
+
+// --------------------------------------------------------------------
+// Function prototypes
+//
+// --------------------------------------------------------------------
+
+void   addConcreteNet(ConcreteNet *net);
+void   addConcreteCell(ConcreteCell *cell);
+void   delConcreteNet(ConcreteNet *net);
+void   delConcreteCell(ConcreteCell *cell);
+
+void   globalPreplace(float utilization);
+void   globalPlace();
+void   globalIncremental();
+void   globalFixDensity(int numBins, float maxMovement);
+
+float fastEstimate(ConcreteCell *cell,
+                   int numNets, ConcreteNet *nets[]);
+float fastTopoPlace(int numCells, ConcreteCell *cells[], 
+                    int numNets, ConcreteNet *nets[]);
+
+Rect   getNetBBox(const ConcreteNet *net);
+float  getNetWirelength(const ConcreteNet *net);
+float  getTotalWirelength();
+float  getCellArea(const ConcreteCell *cell);
+
+void   writeBookshelf(const char *filename);
+
+// comparative qsort-style functions
+int    netSortByL(const void *a, const void *b);
+int    netSortByR(const void *a, const void *b);
+int    netSortByB(const void *a, const void *b);
+int    netSortByT(const void *a, const void *b);
+int    netSortByID(const void *a, const void *b);
+int    cellSortByX(const void *a, const void *b);
+int    cellSortByY(const void *a, const void *b);
+int    cellSortByID(const void *a, const void *b);
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/phys/place/place_bin.c b/abc-build/src/phys/place/place_bin.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/place_bin.c
@@ -0,0 +1,282 @@
+/*===================================================================*/
+//  
+//     place_bin.c
+//
+//		Aaron P. Hurst, 2007
+//              ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+
+//#define DEBUG
+
+#include "place_base.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+// --------------------------------------------------------------------
+// Global variables
+//
+// --------------------------------------------------------------------
+
+
+// --------------------------------------------------------------------
+// Function prototypes and local data structures
+//
+// --------------------------------------------------------------------
+
+void spreadDensityX(int numBins, float maxMovement);
+void spreadDensityY(int numBins, float maxMovement);
+
+
+// --------------------------------------------------------------------
+// globalFixDensity()
+//
+/// Doesn't deal well with fixed cells in the core area.
+// --------------------------------------------------------------------
+void globalFixDensity(int numBins, float maxMovement) {
+  
+  printf("QCLN-10 : \tbin-based density correction\n");
+    
+  spreadDensityX(numBins, maxMovement);
+  // spreadDensityY(numBins, maxMovement);
+}
+
+
+// --------------------------------------------------------------------
+// spreadDensityX()
+//
+// --------------------------------------------------------------------
+void spreadDensityX(int numBins, float maxMovement) {
+
+  int c, c2, c3, x, y;
+  float totalArea = 0;
+  int moveableCells = 0;
+  float yBinArea = 0,  yCumArea = 0;
+  int   yBinStart = 0, yBinCount = 0;
+  int  xBinCount, xBinStart;
+  float xBinArea, xCumArea;
+  float lastOldEdge;
+  float lastNewEdge;
+  float curOldEdge, curNewEdge;
+  float stretch, w;
+  ConcreteCell *xCell, *yCell;
+  ConcreteCell **binCells;
+  ConcreteCell **allCells;
+
+  binCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells);
+  allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells);
+
+  for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
+    ConcreteCell *cell =  g_place_concreteCells[c];
+    if (!cell->m_fixed && !cell->m_parent->m_pad) {
+      allCells[moveableCells++] = cell;
+      totalArea += getCellArea(cell);
+    }
+  }
+  
+  // spread X
+  qsort(allCells, moveableCells, sizeof(ConcreteCell*), cellSortByY);
+
+  y = 0;
+
+  // for each y-bin...
+  for(c=0; c<moveableCells; c++) {
+    yCell = allCells[c];
+    yBinArea += getCellArea(yCell);
+    yCumArea += getCellArea(yCell);
+    yBinCount++;
+
+    // have we filled up a y-bin?
+    if (yCumArea >= totalArea*(y+1)/numBins && yBinArea > 0) {
+      memcpy(binCells, &(allCells[yBinStart]), sizeof(ConcreteCell*)*yBinCount);
+      qsort(binCells, yBinCount, sizeof(ConcreteCell*), cellSortByX);
+
+#if defined(DEBUG)
+      printf("y-bin %d count=%d area=%f\n",y,yBinCount, yBinArea);
+#endif
+
+      x = 0;
+      xBinCount = 0, xBinStart =  0;
+      xBinArea = 0, xCumArea = 0;
+      lastOldEdge = g_place_coreBounds.x;
+      lastNewEdge = g_place_coreBounds.x;
+
+      // for each x-bin...
+      for(c2=0; c2<yBinCount; c2++) {
+        xCell = binCells[c2];
+        xBinArea += getCellArea(xCell);
+        xCumArea += getCellArea(xCell);
+        xBinCount++;
+        curOldEdge = xCell->m_x;
+        
+        printf("%.3f ", xCell->m_x);
+
+        // have we filled up an x-bin?
+        if (xCumArea >= yBinArea*(x+1)/numBins && xBinArea > 0) {
+          curNewEdge = lastNewEdge + g_place_coreBounds.w*xBinArea/yBinArea;
+
+          if (curNewEdge > g_place_coreBounds.x+g_place_coreBounds.w) 
+            curNewEdge = g_place_coreBounds.x+g_place_coreBounds.w;
+          if ((curNewEdge-curOldEdge)>maxMovement) curNewEdge = curOldEdge + maxMovement;
+          if ((curOldEdge-curNewEdge)>maxMovement) curNewEdge = curOldEdge - maxMovement;
+
+#if defined(DEBUG)
+          printf("->\tx-bin %d count=%d area=%f (%f,%f)->(%f,%f)\n",x, xBinCount, xBinArea,
+                 curOldEdge, lastOldEdge, curNewEdge, lastNewEdge);
+#endif
+          
+          stretch = (curNewEdge-lastNewEdge)/(curOldEdge-lastOldEdge);
+          
+          // stretch!
+          for(c3=xBinStart; c3<xBinStart+xBinCount; c3++) {
+            if (curOldEdge == lastOldEdge)
+              binCells[c3]->m_x = lastNewEdge+(c3-xBinStart)*(curNewEdge-lastNewEdge);
+            else
+              binCells[c3]->m_x = lastNewEdge+(binCells[c3]->m_x-lastOldEdge)*stretch;
+            
+              // force within core
+            w = binCells[c3]->m_parent->m_width*0.5;
+            if (binCells[c3]->m_x-w < g_place_coreBounds.x)
+              binCells[c3]->m_x = g_place_coreBounds.x+w;
+            if (binCells[c3]->m_x+w > g_place_coreBounds.x+g_place_coreBounds.w)
+              binCells[c3]->m_x = g_place_coreBounds.x+g_place_coreBounds.w-w;
+          }
+          
+          lastOldEdge = curOldEdge;
+          lastNewEdge = curNewEdge;
+          x++;
+          xBinCount = 0;
+          xBinArea = 0;
+          xBinStart = c2+1;
+        }
+      }
+      
+      y++;
+      yBinCount = 0;
+      yBinArea = 0;
+      yBinStart = c+1;
+    }
+  }
+
+  free(binCells);
+  free(allCells);
+}
+
+
+// --------------------------------------------------------------------
+// spreadDensityY()
+//
+// --------------------------------------------------------------------
+void spreadDensityY(int numBins, float maxMovement) {
+
+  int c, c2, c3, x, y;
+  float totalArea = 0;
+  int moveableCells = 0;
+  float xBinArea = 0,  xCumArea = 0;
+  int   xBinStart = 0, xBinCount = 0;
+  int   yBinCount, yBinStart;
+  float yBinArea, yCumArea;
+  float lastOldEdge;
+  float lastNewEdge;
+  float curOldEdge, curNewEdge;
+  float stretch, h;
+  ConcreteCell *xCell, *yCell;
+  ConcreteCell **binCells;
+  ConcreteCell **allCells;
+
+  binCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells);
+  allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells);
+
+  for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
+    ConcreteCell *cell =  g_place_concreteCells[c];
+    if (!cell->m_fixed && !cell->m_parent->m_pad) {
+      allCells[moveableCells++] = cell;
+      totalArea += getCellArea(cell);
+    }
+  }
+  
+  // spread Y
+  qsort(allCells, moveableCells, sizeof(ConcreteCell*), cellSortByX);
+
+  x = 0;
+
+  // for each x-bin...
+  for(c=0; c<moveableCells; c++) {
+    xCell = allCells[c];
+    xBinArea += getCellArea(xCell);
+    xCumArea += getCellArea(xCell);
+    xBinCount++;
+
+    // have we filled up an x-bin?
+    if (xCumArea >= totalArea*(x+1)/numBins && xBinArea > 0) {
+      memcpy(binCells, &(allCells[xBinStart]), sizeof(ConcreteCell*)*xBinCount);
+      qsort(binCells, xBinCount, sizeof(ConcreteCell*), cellSortByY);
+
+      // printf("x-bin %d count=%d area=%f\n",y,yBinCount, yBinArea);
+
+      y = 0;
+      yBinCount = 0, yBinStart =  0;
+      yBinArea = 0, yCumArea = 0;
+      lastOldEdge = g_place_coreBounds.y;
+      lastNewEdge = g_place_coreBounds.y;
+      
+      // for each y-bin...
+      for(c2=0; c2<xBinCount; c2++) {
+        yCell = binCells[c2];
+        yBinArea += getCellArea(yCell);
+        yCumArea += getCellArea(yCell);
+        yBinCount++;
+        curOldEdge = yCell->m_y;
+        
+        // have we filled up an x-bin?
+        if (yCumArea >= xBinArea*(y+1)/numBins && yBinArea > 0) {
+          curNewEdge = lastNewEdge + g_place_coreBounds.h*yBinArea/xBinArea;
+
+          if (curNewEdge > g_place_coreBounds.y+g_place_coreBounds.h) 
+            curNewEdge = g_place_coreBounds.y+g_place_coreBounds.h;
+          if ((curNewEdge-curOldEdge)>maxMovement) curNewEdge = curOldEdge + maxMovement;
+          if ((curOldEdge-curNewEdge)>maxMovement) curNewEdge = curOldEdge - maxMovement;
+
+          if (curOldEdge == lastOldEdge) continue; // hmmm
+          stretch = (curNewEdge-lastNewEdge)/(curOldEdge-lastOldEdge);
+
+          // stretch!
+          for(c3=yBinStart; c3<yBinStart+yBinCount; c3++) {
+            binCells[c3]->m_y = lastNewEdge+(binCells[c3]->m_y-lastOldEdge)*stretch;
+
+            // force within core
+            h = binCells[c3]->m_parent->m_height;
+            if (binCells[c3]->m_y-h < g_place_coreBounds.y)
+              binCells[c3]->m_y = g_place_coreBounds.y+h;
+            if (binCells[c3]->m_y+h > g_place_coreBounds.y+g_place_coreBounds.h)
+              binCells[c3]->m_y = g_place_coreBounds.y+g_place_coreBounds.h-h;
+          }
+
+          lastOldEdge = curOldEdge;
+          lastNewEdge = curNewEdge;
+          y++;
+          yBinCount = 0;
+          yBinArea = 0;
+          yBinStart = c2+1;
+        }
+      }
+
+      x++;
+      xBinCount = 0;
+      xBinArea = 0;
+      xBinStart = c+1;
+    }
+  }
+
+  free(binCells);
+  free(allCells);
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/phys/place/place_genqp.c b/abc-build/src/phys/place/place_genqp.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/place_genqp.c
@@ -0,0 +1,314 @@
+/*===================================================================*/
+//  
+//     place_genqp.c
+//
+//		Aaron P. Hurst, 2003-2007
+//              ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdlib.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "place_base.h"
+#include "place_qpsolver.h"
+#include "place_gordian.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+// --------------------------------------------------------------------
+// Global variables
+//
+// --------------------------------------------------------------------
+
+qps_problem_t *g_place_qpProb = NULL;
+
+
+// --------------------------------------------------------------------
+// splitPenalty()
+//
+/// \brief Returns a weight for all of the edges in the clique for a multipin net.
+//
+// --------------------------------------------------------------------
+float splitPenalty(int pins) {
+
+  if (pins > 1) {
+    return 1.0 + CLIQUE_PENALTY/(pins - 1);
+    // return pow(pins - 1, CLIQUE_PENALTY);
+  }
+  return 1.0 + CLIQUE_PENALTY;
+}
+
+
+// --------------------------------------------------------------------
+// constructQuadraticProblem()
+//
+/// \brief Constructs the matrices necessary to do analytical placement.
+//
+// --------------------------------------------------------------------
+void constructQuadraticProblem() {
+  int maxConnections = 1;
+  int ignoreNum = 0;
+  int n,t,c,c2,p;
+  ConcreteCell  *cell;
+  ConcreteNet   *net;
+  int           *cell_numTerms = calloc(g_place_numCells, sizeof(int));
+  ConcreteNet ***cell_terms = calloc(g_place_numCells, sizeof(ConcreteNet**));
+  bool incremental = false;
+  int nextIndex = 1;
+  int *seen = calloc(g_place_numCells, sizeof(int));
+  float weight;
+  int last_index;
+
+  // create problem object
+  if (!g_place_qpProb) {
+    g_place_qpProb = malloc(sizeof(qps_problem_t));
+    g_place_qpProb->area = NULL;
+    g_place_qpProb->x = NULL;
+    g_place_qpProb->y = NULL;
+    g_place_qpProb->fixed = NULL;
+    g_place_qpProb->connect = NULL;
+    g_place_qpProb->edge_weight = NULL;
+  }
+
+  // count the maximum possible number of non-sparse entries
+  for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n]) {
+    ConcreteNet *net = g_place_concreteNets[n];
+    if (net->m_numTerms > IGNORE_NETSIZE) {
+      ignoreNum++;
+    }
+    else {
+      maxConnections += net->m_numTerms*(net->m_numTerms-1);
+      for(t=0; t<net->m_numTerms; t++) {
+        c = net->m_terms[t]->m_id;
+        p = ++cell_numTerms[c];
+        cell_terms[c] = (ConcreteNet**)realloc(cell_terms[c], p*sizeof(ConcreteNet*));
+        cell_terms[c][p-1] = net;
+      }
+    }
+  }
+  if(ignoreNum) {
+    printf("QMAN-10 : \t\t%d large nets ignored\n", ignoreNum);
+  }
+
+  // initialize the data structures
+  g_place_qpProb->num_cells = g_place_numCells;
+  maxConnections += g_place_numCells + 1;
+
+  g_place_qpProb->area        = realloc(g_place_qpProb->area,
+                                       sizeof(float)*g_place_numCells);// "area" matrix
+  g_place_qpProb->edge_weight = realloc(g_place_qpProb->edge_weight,
+                                       sizeof(float)*maxConnections);  // "weight" matrix
+  g_place_qpProb->connect     = realloc(g_place_qpProb->connect,
+                                       sizeof(int)*maxConnections);    // "connectivity" matrix
+  g_place_qpProb->fixed       = realloc(g_place_qpProb->fixed,
+                                       sizeof(int)*g_place_numCells);  // "fixed" matrix
+
+  // initialize or keep preexisting locations
+  if (g_place_qpProb->x != NULL && g_place_qpProb->y != NULL) {
+    printf("QMAN-10 :\tperforming incremental placement\n");
+    incremental = true;
+  }
+  g_place_qpProb->x = (float*)realloc(g_place_qpProb->x, sizeof(float)*g_place_numCells);
+  g_place_qpProb->y = (float*)realloc(g_place_qpProb->y, sizeof(float)*g_place_numCells);
+
+  // form a row for each cell
+  // build data
+  for(c = 0; c < g_place_numCells; c++) if (g_place_concreteCells[c]) {
+    cell = g_place_concreteCells[c];
+    
+    // fill in the characteristics for this cell
+    g_place_qpProb->area[c] = getCellArea(cell);
+    if (cell->m_fixed || cell->m_parent->m_pad) {
+      g_place_qpProb->x[c] = cell->m_x;
+      g_place_qpProb->y[c] = cell->m_y;
+      g_place_qpProb->fixed[c] = 1;
+    } else {
+      if (!incremental) {
+        g_place_qpProb->x[c] = g_place_coreBounds.x+g_place_coreBounds.w*0.5;
+        g_place_qpProb->y[c] = g_place_coreBounds.y+g_place_coreBounds.h*0.5;
+      }
+      g_place_qpProb->fixed[c] = 0;
+    }
+
+    // update connectivity matrices
+    last_index = nextIndex;
+    for(n=0; n<cell_numTerms[c]; n++) {
+      net = cell_terms[c][n];
+      weight = net->m_weight / splitPenalty(net->m_numTerms);
+      for(t=0; t<net->m_numTerms; t++) {
+        c2 = net->m_terms[t]->m_id;
+        if (c2 == c) continue;
+        if (seen[c2] < last_index) {
+          // not seen
+          g_place_qpProb->connect[nextIndex-1] = c2;
+          g_place_qpProb->edge_weight[nextIndex-1] = weight;
+          seen[c2] = nextIndex;
+          nextIndex++;
+        } else {
+          // seen
+          g_place_qpProb->edge_weight[seen[c2]-1] += weight;
+        }
+      }
+    }
+    g_place_qpProb->connect[nextIndex-1] = -1;
+    g_place_qpProb->edge_weight[nextIndex-1] = -1.0;    
+    nextIndex++;
+  } else {
+    // fill in dummy values for connectivity matrices
+    g_place_qpProb->connect[nextIndex-1] = -1;
+    g_place_qpProb->edge_weight[nextIndex-1] = -1.0;    
+    nextIndex++;    
+  }
+
+  free(cell_numTerms);
+  free(cell_terms);
+  free(seen);
+}
+
+typedef struct reverseCOG {
+  float      x,y;
+  Partition *part;
+  float      delta;
+} reverseCOG;
+
+
+// --------------------------------------------------------------------
+// generateCoGConstraints()
+//
+/// \brief Generates center of gravity constraints.
+//
+// --------------------------------------------------------------------
+int generateCoGConstraints(reverseCOG COG_rev[]) {
+  int numConstraints = 0; // actual num constraints
+  int cogRevNum = 0;
+  Partition **stack = malloc(sizeof(Partition*)*g_place_numPartitions*2);
+  int stackPtr = 0;
+  Partition *p;
+  float cgx, cgy;
+  int next_index = 0, last_constraint = 0;
+  bool isTrueConstraint = false;
+  int i, m;
+  float totarea;
+  ConcreteCell *cell;
+
+  // each partition may give rise to a center-of-gravity constraint
+  stack[stackPtr] = g_place_rootPartition;
+  while(stackPtr >= 0) {
+    p = stack[stackPtr--];
+    assert(p);
+
+    // traverse down the partition tree to leaf nodes-only
+    if (!p->m_leaf) {
+      stack[++stackPtr] = p->m_sub1;
+      stack[++stackPtr] = p->m_sub2;
+    } else {
+      /*
+      cout << "adding a COG constraint for box "
+	   << p->bounds.x << ","
+	   << p->bounds.y << " of size"
+	   << p->bounds.w << "x"
+	   << p->bounds.h
+	   << endl;
+      */
+      cgx = p->m_bounds.x + p->m_bounds.w*0.5;
+      cgy = p->m_bounds.y + p->m_bounds.h*0.5;
+      COG_rev[cogRevNum].x = cgx;
+      COG_rev[cogRevNum].y = cgy;
+      COG_rev[cogRevNum].part = p;
+      COG_rev[cogRevNum].delta = 0;
+
+      cogRevNum++;
+    }
+  }
+
+  assert(cogRevNum == g_place_numPartitions);
+  
+  for (i = 0; i < g_place_numPartitions; i++) {
+    p = COG_rev[i].part;
+    assert(p);
+    g_place_qpProb->cog_x[numConstraints] = COG_rev[i].x;
+    g_place_qpProb->cog_y[numConstraints] = COG_rev[i].y;
+    totarea = 0.0;
+    for(m=0; m<p->m_numMembers; m++) if (p->m_members[m]) {
+      cell = p->m_members[m];
+      assert(cell);
+
+      if (!cell->m_fixed && !cell->m_parent->m_pad) {
+	isTrueConstraint = true;
+      }
+      else {
+	continue;
+      }
+      g_place_qpProb->cog_list[next_index++] = cell->m_id;
+      totarea += getCellArea(cell);
+    }
+    if (totarea == 0.0) {
+      isTrueConstraint = false;
+    }
+    if (isTrueConstraint) {
+      numConstraints++;
+      g_place_qpProb->cog_list[next_index++] = -1;
+      last_constraint = next_index;
+    }
+    else {
+      next_index = last_constraint;
+    }
+  }
+
+  free(stack);
+
+  return --numConstraints;
+}
+
+
+// --------------------------------------------------------------------
+// solveQuadraticProblem()
+//
+/// \brief Calls quadratic solver.
+//
+// --------------------------------------------------------------------
+void solveQuadraticProblem(bool useCOG) {
+  int c;
+
+  reverseCOG *COG_rev = malloc(sizeof(reverseCOG)*g_place_numPartitions);
+
+  g_place_qpProb->cog_list = malloc(sizeof(int)*(g_place_numPartitions+g_place_numCells));
+  g_place_qpProb->cog_x = malloc(sizeof(float)*g_place_numPartitions);
+  g_place_qpProb->cog_y = malloc(sizeof(float)*g_place_numPartitions);
+
+  // memset(g_place_qpProb->x, 0, sizeof(float)*g_place_numCells);
+  // memset(g_place_qpProb->y, 0, sizeof(float)*g_place_numCells);
+
+  qps_init(g_place_qpProb);
+
+  if (useCOG)
+      g_place_qpProb->cog_num = generateCoGConstraints(COG_rev);
+  else
+      g_place_qpProb->cog_num = 0;
+
+  g_place_qpProb->loop_num = 0;
+
+  qps_solve(g_place_qpProb);
+
+  qps_clean(g_place_qpProb);
+
+  // set the positions
+  for(c = 0; c < g_place_numCells; c++) if (g_place_concreteCells[c]) {
+    g_place_concreteCells[c]->m_x = g_place_qpProb->x[c];
+    g_place_concreteCells[c]->m_y = g_place_qpProb->y[c];
+  }
+  
+  // clean up
+  free(g_place_qpProb->cog_list);
+  free(g_place_qpProb->cog_x);
+  free(g_place_qpProb->cog_y);
+
+  free(COG_rev);
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/phys/place/place_gordian.c b/abc-build/src/phys/place/place_gordian.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/place_gordian.c
@@ -0,0 +1,165 @@
+/*===================================================================*/
+//  
+//     place_gordian.c
+//
+//		Aaron P. Hurst, 2003-2007
+//              ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <assert.h>
+#include <limits.h>
+
+#include "place_gordian.h"
+#include "place_base.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+// --------------------------------------------------------------------
+// Global variables
+//
+// --------------------------------------------------------------------
+
+int g_place_numPartitions;
+
+
+// --------------------------------------------------------------------
+// globalPlace()
+//
+/// \brief Performs analytic placement using a GORDIAN-like algorithm.
+//
+/// Updates the positions of all non-fixed non-pad cells.
+///
+// --------------------------------------------------------------------
+void globalPlace() {
+  bool completionFlag = false;
+  int iteration = 0;  
+
+  printf("PLAC-10 : Global placement (wirelength-driven Gordian)\n");
+
+  initPartitioning();
+
+  // build matrices representing interconnections
+  printf("QMAN-00 : \tconstructing initial quadratic problem...\n");
+  constructQuadraticProblem();
+
+  // iterate placement until termination condition is met
+  while(!completionFlag) {
+    printf("QMAN-01 : \titeration %d numPartitions = %d\n",iteration,g_place_numPartitions);
+    
+    // do the global optimization in each direction
+    printf("QMAN-01 : \t\tglobal optimization\n");
+    solveQuadraticProblem(!IGNORE_COG);
+      
+    // -------- PARTITIONING BASED CELL SPREADING ------
+
+    // bisection
+    printf("QMAN-01 : \t\tpartition refinement\n");
+    if (REALLOCATE_PARTITIONS) reallocPartitions();
+    completionFlag |= refinePartitions();
+      
+    printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
+      
+    iteration++;
+  }
+  
+  // final global optimization
+  printf("QMAN-02 : \t\tfinal pass\n");
+  if (FINAL_REALLOCATE_PARTITIONS) reallocPartitions();
+  solveQuadraticProblem(!IGNORE_COG);
+  printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
+
+  // clean up
+  sanitizePlacement();
+  printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
+  globalFixDensity(25, g_place_rowHeight*5);
+  printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
+}
+
+
+// --------------------------------------------------------------------
+// globalIncremental()
+//
+/// \brief Performs analytic placement using a GORDIAN-like algorithm.
+//
+/// Requires a valid set of partitions.
+///
+// --------------------------------------------------------------------
+
+void   globalIncremental() {
+  if (!g_place_rootPartition) {
+    printf("WARNING: Can not perform incremental placement\n");
+    globalPlace();
+    return;
+  }
+
+  printf("PLAC-10 : Incremental global placement\n");
+
+  incrementalPartition();
+
+  printf("QMAN-00 : \tconstructing initial quadratic problem...\n");
+  constructQuadraticProblem();
+
+  solveQuadraticProblem(!IGNORE_COG);
+  printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
+  
+  // clean up
+  sanitizePlacement();
+  printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
+  globalFixDensity(25, g_place_rowHeight*5);
+  printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
+}
+
+
+// --------------------------------------------------------------------
+// sanitizePlacement()
+//
+/// \brief Moves any cells that are outside of the core bounds to the nearest location within.
+//
+// --------------------------------------------------------------------
+void sanitizePlacement() { 
+  int c;
+  float order_width = g_place_rowHeight;
+  float x, y, edge, w, h;
+  
+  printf("QCLN-10 : \tsanitizing placement\n");
+
+  for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
+    ConcreteCell *cell = g_place_concreteCells[c];
+    if (cell->m_fixed || cell->m_parent->m_pad) {
+      continue;
+    }
+    // the new locations of the cells will be distributed within
+    // a small margin inside the border so that ordering is preserved
+    order_width = g_place_rowHeight;
+
+    x = cell->m_x, y = cell->m_y,
+      w = cell->m_parent->m_width, h = cell->m_parent->m_height;
+
+    if ((edge=x-w*0.5) < g_place_coreBounds.x) {
+      x = g_place_coreBounds.x+w*0.5 +
+        order_width/(1.0+g_place_coreBounds.x-edge);
+    }
+    else if ((edge=x+w*0.5) > g_place_coreBounds.x+g_place_coreBounds.w) {
+      x = g_place_coreBounds.x+g_place_coreBounds.w-w*0.5 -
+        order_width/(1.0+edge-g_place_coreBounds.x-g_place_coreBounds.w);
+    }
+    if ((edge=y-h*0.5) < g_place_coreBounds.y) {
+      y = g_place_coreBounds.y+h*0.5 +
+        order_width/(1.0+g_place_coreBounds.y-edge);
+    }
+    else if ((edge=y+h*0.5) > g_place_coreBounds.y+g_place_coreBounds.h) {
+      y = g_place_coreBounds.y+g_place_coreBounds.h-h*0.5 -
+        order_width/(1.0+edge-g_place_coreBounds.x-g_place_coreBounds.w);
+    }
+    cell->m_x = x;
+    cell->m_y = y;
+  }
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/phys/place/place_gordian.h b/abc-build/src/phys/place/place_gordian.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/place_gordian.h
@@ -0,0 +1,86 @@
+/*===================================================================*/
+//  
+//     place_gordian.h
+//
+//		Aaron P. Hurst, 2003-2007
+//              ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#if !defined(PLACE_GORDIAN_H_)
+#define ABC__phys__place__place_gordian_h
+
+
+#include "place_base.h"
+#include "place_qpsolver.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+// Parameters for analytic placement
+#define CLIQUE_PENALTY 1.0
+#define IGNORE_NETSIZE 20
+
+// Parameters for partitioning
+#define LARGEST_FINAL_SIZE 20
+#define PARTITION_AREA_ONLY true
+#define REALLOCATE_PARTITIONS false
+#define FINAL_REALLOCATE_PARTITIONS false
+#define IGNORE_COG false
+#define MAX_PARTITION_NONSYMMETRY 0.30
+
+// Parameters for re-partitioning
+#define REPARTITION_LEVEL_DEPTH 4
+#define REPARTITION_TARGET_FRACTION 0.15
+#define REPARTITION_FM false
+#define REPARTITION_HMETIS true
+
+// Parameters for F-M re-partitioning
+#define FM_MAX_BIN 10
+#define FM_MAX_PASSES 10
+
+extern int g_place_numPartitions;
+
+extern qps_problem_t *g_place_qpProb;
+
+typedef struct Partition {
+
+  int               m_numMembers;
+  ConcreteCell    **m_members;
+  Rect              m_bounds;
+  bool              m_done, 
+                    m_leaf, 
+                    m_vertical;
+  float             m_area;
+  int               m_level;
+  struct Partition *m_sub1, *m_sub2;
+} Partition;
+
+extern Partition *g_place_rootPartition;
+
+void initPartitioning();
+
+void incrementalPartition();
+
+bool refinePartitions();
+void reallocPartitions();
+bool refinePartition(Partition *p);
+void resizePartition(Partition *p);
+void reallocPartition(Partition *p);
+
+void repartitionHMetis(Partition *parent);
+void repartitionFM(Partition *parent);
+
+void partitionScanlineMincut(Partition *parent);
+void partitionEqualArea(Partition *parent);
+
+void sanitizePlacement();
+
+void constructQuadraticProblem();
+void solveQuadraticProblem(bool useCOG);
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/phys/place/place_inc.c b/abc-build/src/phys/place/place_inc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/place_inc.c
@@ -0,0 +1,111 @@
+/*===================================================================*/
+//  
+//     place_inc.c
+//
+//		Aaron P. Hurst, 2003-2007
+//              ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdlib.h>
+#include <limits.h>
+#include <assert.h>
+#include <string.h>
+
+#include "place_base.h"
+#include "place_gordian.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+inline int sqHashId(int id, int max) {
+  return ((id * (id+17)) % max);
+}
+
+#if 0
+// --------------------------------------------------------------------
+// fastPlace()
+//
+/// The first cell is assumed to be the "output".
+// --------------------------------------------------------------------
+float fastPlace(int numCells, ConcreteCell *cells[], 
+                int numNets, ConcreteNet *nets[]) {
+  
+  int n, t, c, i, local_id = 0, pass;
+  const int NUM_PASSES = 4;
+  int *cell_numTerms = calloc(numCells, sizeof(int));
+  ConcreteNet **cell_terms;
+  ConcreteNet  *net;
+  Rect outputBox;
+
+  outputBox = getNetBBox(nets[0]);
+
+  // assign local ids
+  // put cells in reasonable initial location
+  for(n=0; n<numNets; n++)
+    for(t=0; nets[n]->m_numTerms; t++)
+      nets[n]->m_terms[t]->m_data = -1;
+
+  for(c=0; c<numCells; c++) {
+    cells[c]->m_data = local_id;
+    cells[c]->m_x = outputBox.x + 0.5*outputBox.w;
+    cells[c]->m_y = outputBox.y + 0.5*outputBox.h;
+  }
+
+  // build reverse map of cells to nets
+  for(n=0; n<numNets; n++)
+    for(t=0; nets[n]->m_numTerms; t++) {
+      local_id = nets[n]->m_terms[t]->m_data;
+      if (local_id >= 0)
+        cell_numTerms[local_id]++;
+    }
+
+  for(c=0; c<numCells; c++) {
+    cell_terms[c] = malloc(sizeof(ConcreteNet*)*cell_numTerms[c]);
+    cell_numTerms[c] = 0;
+  }
+
+  for(n=0; n<numNets; n++)
+    for(t=0; nets[n]->m_numTerms; t++) {
+      local_id = nets[n]->m_terms[t]->m_data;
+      if (local_id >= 0)
+        cell_terms[cell_numTerms[local_id]++] = nets[n];
+    }
+
+  // topological order?
+  
+  // iterative linear 
+  for(pass=0; pass<NUM_PASSES; pass++)
+    for(c=0; c<numCells; c++) {
+      for(n=0; n<cell_numTerms[c]; n++) {
+        net = cell_terms[c];
+        for(t=0; t<net->m_numTerms; t++);
+      }
+    }
+}
+#endif
+
+// --------------------------------------------------------------------
+// fastEstimate()
+//
+// --------------------------------------------------------------------
+float fastEstimate(ConcreteCell *cell, 
+                   int numNets, ConcreteNet *nets[]) {
+  float len = 0;
+  int n;
+  Rect box;
+
+  assert(cell);
+
+  for(n=0; n<numNets; n++) {
+    box = getNetBBox(nets[n]);
+    if (cell->m_x < box.x) len += (box.x - cell->m_x);
+    if (cell->m_x > box.x+box.w) len += (cell->m_x-box.x-box.w);
+    if (cell->m_y < box.y) len += (box.x - cell->m_y);
+    if (cell->m_y > box.y+box.h) len += (cell->m_y-box.y-box.h);
+  }
+  
+  return len;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/phys/place/place_io.c b/abc-build/src/phys/place/place_io.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/place_io.c
@@ -0,0 +1,99 @@
+/*===================================================================*/
+//  
+//     place_io.c
+//
+//		Aaron P. Hurst, 2003-2007
+//              ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdlib.h>
+#include <limits.h>
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "place_base.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+// --------------------------------------------------------------------
+// writeBookshelfNodes()
+//
+// --------------------------------------------------------------------
+void writeBookshelfNodes(const char *filename) {
+  
+  int c = 0;
+  int numNodes, numTerms;
+
+  FILE *nodesFile = fopen(filename, "w");
+  if (!nodesFile) {
+    printf("ERROR: Could not open .nodes file\n");
+    exit(1);
+  }
+
+  numNodes = numTerms = 0;
+  for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
+      numNodes++;
+      if (g_place_concreteCells[c]->m_parent->m_pad)
+        numTerms++;
+    }
+
+
+
+  fprintf(nodesFile, "UCLA nodes 1.0\n");
+  fprintf(nodesFile, "NumNodes : %d\n", numNodes);
+  fprintf(nodesFile, "NumTerminals : %d\n", numTerms);
+
+  for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
+    fprintf(nodesFile, "CELL%d %f %f %s\n", 
+            g_place_concreteCells[c]->m_id,
+            g_place_concreteCells[c]->m_parent->m_width,
+            g_place_concreteCells[c]->m_parent->m_height,
+            (g_place_concreteCells[c]->m_parent->m_pad ? " terminal" : ""));
+  }
+
+  fclose(nodesFile);  
+}
+
+
+// --------------------------------------------------------------------
+// writeBookshelfPl()
+//
+// --------------------------------------------------------------------
+void writeBookshelfPl(const char *filename) {
+  
+  int c = 0;
+
+  FILE *plFile = fopen(filename, "w");
+  if (!plFile) {
+    printf("ERROR: Could not open .pl file\n");
+    exit(1);
+  }
+
+  fprintf(plFile, "UCLA pl 1.0\n");
+  for(c=0; c<g_place_numCells; c++)  if (g_place_concreteCells[c]) {
+    fprintf(plFile, "CELL%d %f %f : N %s\n", 
+            g_place_concreteCells[c]->m_id,
+            g_place_concreteCells[c]->m_x,
+            g_place_concreteCells[c]->m_y,
+            (g_place_concreteCells[c]->m_fixed ? "\\FIXED" : ""));
+  }
+
+  fclose(plFile);  
+
+}
+
+
+// --------------------------------------------------------------------
+// writeBookshelf()
+//
+// --------------------------------------------------------------------
+void writeBookshelf(const char *filename) {
+  writeBookshelfNodes("out.nodes");
+  writeBookshelfPl("out.pl");
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/phys/place/place_legalize.c b/abc-build/src/phys/place/place_legalize.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/place_legalize.c
@@ -0,0 +1,28 @@
+/*===================================================================*/
+//  
+//     place_legalize.c
+//
+//		Aaron P. Hurst, 2007
+//              ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <limits.h>
+#include <assert.h>
+
+#include "place_base.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+// --------------------------------------------------------------------
+// legalize()
+//
+// --------------------------------------------------------------------
+void legalize() {
+  // UNIMPLEMENTED
+}
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/phys/place/place_pads.c b/abc-build/src/phys/place/place_pads.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/place_pads.c
@@ -0,0 +1,146 @@
+/*===================================================================*/
+//  
+//     place_pads.c
+//
+//		Aaron P. Hurst, 2003-2007
+//              ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <limits.h>
+
+#include "place_base.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+// --------------------------------------------------------------------
+// globalPreplace()
+//
+/// \brief Place pad ring, leaving a core area to meet a desired utilization.
+//
+/// Sets the position of pads that aren't already fixed.
+///
+/// Computes g_place_coreBounds and g_place_padBounds.  Determines
+/// g_place_rowHeight.
+//
+// --------------------------------------------------------------------
+void globalPreplace(float utilization) {
+  int i, c, h, numRows;
+  float coreArea = 0, totalArea = 0;
+  int padCount = 0;
+  float area;
+  ConcreteCell **padCells = NULL;
+  AbstractCell *padType = NULL;
+  ConcreteCell *cell;
+  float nextPos;
+  int remainingPads, northPads, southPads, eastPads, westPads;
+
+  printf("PLAC-00 : Placing IO pads\n");;
+
+  // identify the pads and compute the total core area
+  g_place_coreBounds.x = g_place_coreBounds.y = 0;
+  g_place_coreBounds.w = g_place_coreBounds.h = -INT_MAX;
+
+  for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
+    cell = g_place_concreteCells[c];
+    area = getCellArea(cell);
+    if (cell->m_parent->m_pad) {
+      padType = cell->m_parent;
+    } else {
+      coreArea += area;
+      g_place_rowHeight = cell->m_parent->m_height;
+    }
+
+    if (cell->m_fixed) {
+      g_place_coreBounds.x = g_place_coreBounds.x < cell->m_x ? g_place_coreBounds.x : cell->m_x;
+      g_place_coreBounds.y = g_place_coreBounds.y < cell->m_y ? g_place_coreBounds.y : cell->m_y;
+      g_place_coreBounds.w = g_place_coreBounds.w > cell->m_x ? g_place_coreBounds.w : cell->m_x;
+      g_place_coreBounds.h = g_place_coreBounds.h > cell->m_y ? g_place_coreBounds.h : cell->m_y;
+    } else if (cell->m_parent->m_pad) {
+      padCells = realloc(padCells, sizeof(ConcreteCell **)*(padCount+1));
+      padCells[padCount++] = cell;
+    }
+    totalArea += area;
+  }
+  if (!padType) {
+    printf("ERROR: No pad cells\n");
+    exit(1);
+  }
+  g_place_padBounds.w -= g_place_padBounds.x;
+  g_place_padBounds.h -= g_place_padBounds.y;
+
+  coreArea /= utilization;
+
+  // create the design boundaries
+  numRows = sqrt(coreArea)/g_place_rowHeight+1;
+  h = numRows * g_place_rowHeight;
+  g_place_coreBounds.h = g_place_coreBounds.h > h ? g_place_coreBounds.h : h;
+  g_place_coreBounds.w = g_place_coreBounds.w > coreArea/g_place_coreBounds.h ? 
+    g_place_coreBounds.w : coreArea/g_place_coreBounds.h;
+  // increase the dimensions by the width of the padring
+  g_place_padBounds = g_place_coreBounds;
+  if (padCount) {
+    printf("PLAC-05 : \tpreplacing %d pad cells\n", padCount);
+    g_place_padBounds.x -= padType->m_width;
+    g_place_padBounds.y -= padType->m_height;
+    g_place_padBounds.w = g_place_coreBounds.w+2*padType->m_width;
+    g_place_padBounds.h = g_place_coreBounds.h+2*padType->m_height;
+  }
+
+  printf("PLAC-05 : \tplaceable rows  : %d\n", numRows);
+  printf("PLAC-05 : \tcore dimensions : %.0fx%.0f\n",
+         g_place_coreBounds.w, g_place_coreBounds.h);
+  printf("PLAC-05 : \tchip dimensions : %.0fx%.0f\n",
+         g_place_padBounds.w, g_place_padBounds.h);
+  
+  remainingPads = padCount;
+  c = 0;
+
+  // north pads
+  northPads = remainingPads/4; remainingPads -= northPads;
+  nextPos = 0;
+  for(i=0; i<northPads; i++) {
+    cell = padCells[c++];
+    cell->m_x = g_place_padBounds.x+cell->m_parent->m_width*0.5 + nextPos;
+    cell->m_y = g_place_padBounds.y+cell->m_parent->m_height*0.5;
+    nextPos += (g_place_padBounds.w-padType->m_width) / northPads;
+  }
+  
+  // south pads
+  southPads = remainingPads/3; remainingPads -= southPads;
+  nextPos = 0;
+  for(i=0; i<southPads; i++) {
+    cell = padCells[c++];
+    cell->m_x = g_place_padBounds.w+g_place_padBounds.x-cell->m_parent->m_width*0.5 - nextPos;
+    cell->m_y = g_place_padBounds.h+g_place_padBounds.y-cell->m_parent->m_height*0.5;
+    nextPos += (g_place_padBounds.w-2*padType->m_width) / southPads;
+  }
+
+  // east pads
+  eastPads = remainingPads/2; remainingPads -= eastPads;
+  nextPos = 0;
+  for(i=0; i<eastPads; i++) {
+    cell = padCells[c++];
+    cell->m_x = g_place_padBounds.w+g_place_padBounds.x-cell->m_parent->m_width*0.5;
+    cell->m_y = g_place_padBounds.y+cell->m_parent->m_height*0.5 + nextPos;
+    nextPos += (g_place_padBounds.h-padType->m_height) / eastPads;
+  }
+
+  // west pads
+  westPads = remainingPads;
+  nextPos = 0;
+  for(i=0; i<westPads; i++) {
+    cell = padCells[c++];
+    cell->m_x = g_place_padBounds.x+cell->m_parent->m_width*0.5;
+    cell->m_y = g_place_padBounds.h+g_place_padBounds.y-cell->m_parent->m_height*0.5 - nextPos;
+    nextPos += (g_place_padBounds.h-padType->m_height) / westPads;
+  }
+
+}
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/phys/place/place_partition.c b/abc-build/src/phys/place/place_partition.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/place_partition.c
@@ -0,0 +1,1140 @@
+/*===================================================================*/
+//  
+//     place_partition.c
+//
+//		Aaron P. Hurst, 2003-2007
+//              ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <limits.h>
+#include <assert.h>
+//#include <sys/stat.h>
+//#include <unistd.h>
+
+#include "place_base.h"
+#include "place_gordian.h"
+
+#if !defined(NO_HMETIS)
+#include "libhmetis.h"
+
+ABC_NAMESPACE_IMPL_START
+
+#endif
+
+// --------------------------------------------------------------------
+// Global variables
+//
+// --------------------------------------------------------------------
+
+Partition *g_place_rootPartition = NULL;
+ConcreteNet **allNetsR2 = NULL, 
+  **allNetsL2 = NULL, 
+  **allNetsB2 = NULL, 
+  **allNetsT2 = NULL;
+
+
+// --------------------------------------------------------------------
+// Function prototypes and local data structures
+//
+// --------------------------------------------------------------------
+
+typedef struct FM_cell {
+    int loc;
+    int gain;
+    ConcreteCell *cell;
+    struct FM_cell *next, *prev;
+    bool locked;
+} FM_cell;
+
+void FM_updateGains(ConcreteNet *net, int partition, int inc, 
+                    FM_cell target [], FM_cell *bin [], 
+                    int count_1 [], int count_2 []);
+
+
+// --------------------------------------------------------------------
+// initPartitioning()
+//
+/// \brief Initializes data structures necessary for partitioning.
+//
+/// Creates a valid g_place_rootPartition.
+///
+// --------------------------------------------------------------------
+void initPartitioning() {
+  int i;
+  float area;
+
+  // create root partition
+  g_place_numPartitions = 1;
+  if (g_place_rootPartition) free(g_place_rootPartition);
+  g_place_rootPartition = malloc(sizeof(Partition));
+  g_place_rootPartition->m_level = 0;
+  g_place_rootPartition->m_area = 0;
+  g_place_rootPartition->m_bounds = g_place_coreBounds;
+  g_place_rootPartition->m_vertical = false;
+  g_place_rootPartition->m_done = false;
+  g_place_rootPartition->m_leaf = true;
+      
+  // add all of the cells to this partition
+  g_place_rootPartition->m_members = malloc(sizeof(ConcreteCell*)*g_place_numCells);
+  g_place_rootPartition->m_numMembers = 0;
+  for (i=0; i<g_place_numCells; i++) 
+    if (g_place_concreteCells[i]) {
+      if (!g_place_concreteCells[i]->m_fixed) {
+        area = getCellArea(g_place_concreteCells[i]);
+        g_place_rootPartition->m_members[g_place_rootPartition->m_numMembers++] =
+          g_place_concreteCells[i];
+        g_place_rootPartition->m_area += area;
+      }
+    }
+}
+
+
+// --------------------------------------------------------------------
+// presortNets()
+//
+/// \brief Sorts nets by corner positions.
+//
+/// Allocates allNetsX2 structures.
+///
+// --------------------------------------------------------------------
+void presortNets() {
+  allNetsL2 = (ConcreteNet**)realloc(allNetsL2, sizeof(ConcreteNet*)*g_place_numNets);
+  allNetsR2 = (ConcreteNet**)realloc(allNetsR2, sizeof(ConcreteNet*)*g_place_numNets);
+  allNetsB2 = (ConcreteNet**)realloc(allNetsB2, sizeof(ConcreteNet*)*g_place_numNets);
+  allNetsT2 = (ConcreteNet**)realloc(allNetsT2, sizeof(ConcreteNet*)*g_place_numNets);
+  memcpy(allNetsL2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets);
+  memcpy(allNetsR2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets);
+  memcpy(allNetsB2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets);
+  memcpy(allNetsT2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets);
+  qsort(allNetsL2, g_place_numNets, sizeof(ConcreteNet*), netSortByL);
+  qsort(allNetsR2, g_place_numNets, sizeof(ConcreteNet*), netSortByR);
+  qsort(allNetsB2, g_place_numNets, sizeof(ConcreteNet*), netSortByB);
+  qsort(allNetsT2, g_place_numNets, sizeof(ConcreteNet*), netSortByT);
+}
+
+// --------------------------------------------------------------------
+// refinePartitions()
+//
+/// \brief Splits large leaf partitions.
+//
+// --------------------------------------------------------------------
+bool refinePartitions() {
+
+  return refinePartition(g_place_rootPartition);
+}
+
+
+// --------------------------------------------------------------------
+// reallocPartitions()
+//
+/// \brief Reallocates the partitions based on placement information.
+//
+// --------------------------------------------------------------------
+void reallocPartitions() {
+
+  reallocPartition(g_place_rootPartition);
+}
+
+
+// --------------------------------------------------------------------
+// refinePartition()
+//
+/// \brief Splits any large leaves within a partition.
+//
+// --------------------------------------------------------------------
+bool refinePartition(Partition *p) {
+  bool degenerate = false;
+  int nonzeroCount = 0;
+  int i;
+
+  assert(p);
+
+  // is this partition completed?
+  if (p->m_done) return true;
+
+  // is this partition a non-leaf node?
+  if (!p->m_leaf) {
+    p->m_done = refinePartition(p->m_sub1);
+    p->m_done &= refinePartition(p->m_sub2);
+    return p->m_done;
+  }
+  
+  // leaf...
+  // create two new subpartitions
+  g_place_numPartitions++;
+  p->m_sub1 = malloc(sizeof(Partition));
+  p->m_sub1->m_level = p->m_level+1;
+  p->m_sub1->m_leaf = true;
+  p->m_sub1->m_done = false;
+  p->m_sub1->m_area = 0;
+  p->m_sub1->m_vertical = !p->m_vertical;
+  p->m_sub1->m_numMembers = 0;
+  p->m_sub1->m_members = NULL;
+  p->m_sub2 = malloc(sizeof(Partition));
+  p->m_sub2->m_level = p->m_level+1;
+  p->m_sub2->m_leaf = true;
+  p->m_sub2->m_done = false;
+  p->m_sub2->m_area = 0;
+  p->m_sub2->m_vertical = !p->m_vertical;
+  p->m_sub2->m_numMembers = 0;
+  p->m_sub2->m_members = NULL;
+  p->m_leaf = false;
+
+  // --- INITIAL PARTITION
+
+  if (PARTITION_AREA_ONLY)
+    partitionEqualArea(p);
+  else 
+    partitionScanlineMincut(p);
+
+  resizePartition(p);
+
+  // --- PARTITION IMPROVEMENT
+
+  if (p->m_level < REPARTITION_LEVEL_DEPTH) {
+    if (REPARTITION_FM)
+      repartitionFM(p);
+    else if (REPARTITION_HMETIS)
+      repartitionHMetis(p);
+  }
+    
+  resizePartition(p);
+  
+  // fix imbalances due to zero-area cells
+  for(i=0; i<p->m_sub1->m_numMembers; i++)
+    if (p->m_sub1->m_members[i]) 
+      if (getCellArea(p->m_sub1->m_members[i]) > 0) {
+        nonzeroCount++;
+      }
+  
+  // is this leaf now done?
+  if (nonzeroCount <= LARGEST_FINAL_SIZE)
+      p->m_sub1->m_done = true;
+  if (nonzeroCount == 0)
+      degenerate = true;
+
+  nonzeroCount = 0;
+  for(i=0; i<p->m_sub2->m_numMembers; i++)
+    if (p->m_sub2->m_members[i])
+      if (getCellArea(p->m_sub2->m_members[i]) > 0) {
+        nonzeroCount++;
+      }
+
+  // is this leaf now done?
+  if (nonzeroCount <= LARGEST_FINAL_SIZE)
+      p->m_sub2->m_done = true;
+  if (nonzeroCount == 0)
+      degenerate = true;
+
+  // have we found a degenerate partitioning?
+  if (degenerate) {
+    printf("QPART-35 : WARNING: degenerate partition generated\n");
+    partitionEqualArea(p);
+    resizePartition(p);
+    p->m_sub1->m_done = true;
+    p->m_sub2->m_done = true;
+  }
+  
+  // is this parent now finished?
+  if (p->m_sub1->m_done && p->m_sub2->m_done) p->m_done = true;
+  
+  return p->m_done;
+}
+
+
+// --------------------------------------------------------------------
+// repartitionHMetis()
+//
+/// \brief Repartitions the two subpartitions using the hMetis min-cut library.
+///
+/// The number of cut nets between the two partitions will be minimized.
+//
+// --------------------------------------------------------------------
+void repartitionHMetis(Partition *parent) {
+#if defined(NO_HMETIS)
+  printf("QPAR_02 : \t\tERROR: hMetis not available.  Ignoring.\n");
+#else
+
+  int n,c,t, i;
+  float area;
+  int *edgeConnections = NULL;
+  int *partitionAssignment = (int *)calloc(g_place_numCells, sizeof(int));
+  int *vertexWeights = (int *)calloc(g_place_numCells, sizeof(int));
+  int *edgeDegree = (int *)malloc(sizeof(int)*(g_place_numNets+1));
+  int numConnections = 0;
+  int numEdges = 0;
+  float initial_cut;
+  int targets = 0;
+  ConcreteCell *cell = NULL;
+  int options[9];
+  int afterCuts = 0;
+
+  assert(parent);
+  assert(parent->m_sub1);
+  assert(parent->m_sub2);
+
+  printf("QPAR-02 : \t\trepartitioning with hMetis\n");
+
+  // count edges
+  edgeDegree[0] = 0;
+  for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n])
+    if (g_place_concreteNets[n]->m_numTerms > 1) {
+      numConnections += g_place_concreteNets[n]->m_numTerms;
+      edgeDegree[++numEdges] = numConnections;
+    }
+  
+  if (parent->m_vertical) {
+    // vertical
+    initial_cut = parent->m_sub2->m_bounds.x;
+    
+    // initialize all cells
+    for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
+      if (g_place_concreteCells[c]->m_x < initial_cut)
+        partitionAssignment[c] = 0;
+      else
+        partitionAssignment[c] = 1;
+    }
+  
+    // initialize cells in partition 1
+    for(t=0; t<parent->m_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) {
+      cell = parent->m_sub1->m_members[t];
+      vertexWeights[cell->m_id] = getCellArea(cell);
+      // pay attention to cells that are close to the cut
+      if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
+        targets++;
+        partitionAssignment[cell->m_id] = -1;
+      }
+    }
+    
+    // initialize cells in partition 2
+    for(t=0; t<parent->m_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) {
+      cell = parent->m_sub2->m_members[t];
+      vertexWeights[cell->m_id] = getCellArea(cell);
+      // pay attention to cells that are close to the cut
+      if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
+        targets++;
+        partitionAssignment[cell->m_id] = -1;
+      }		
+    }
+    
+  } else {
+    // horizontal
+    initial_cut = parent->m_sub2->m_bounds.y;
+    
+    // initialize all cells
+    for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
+      if (g_place_concreteCells[c]->m_y < initial_cut)
+        partitionAssignment[c] = 0;
+      else
+        partitionAssignment[c] = 1;
+    }
+    
+    // initialize cells in partition 1
+    for(t=0; t<parent->m_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) {
+      cell = parent->m_sub1->m_members[t];
+      vertexWeights[cell->m_id] = getCellArea(cell);
+      // pay attention to cells that are close to the cut
+      if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
+        targets++;
+        partitionAssignment[cell->m_id] = -1;
+      }
+    }
+    
+    // initialize cells in partition 2
+    for(t=0; t<parent->m_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) {
+      cell = parent->m_sub2->m_members[t];
+      vertexWeights[cell->m_id] = getCellArea(cell);
+      // pay attention to cells that are close to the cut
+      if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
+        targets++;
+        partitionAssignment[cell->m_id] = -1;
+      }		
+    }
+  }
+
+  options[0] = 1;  // any non-default values?
+  options[1] = 3; // num bisections
+  options[2] = 1;  // grouping scheme
+  options[3] = 1;  // refinement scheme
+  options[4] = 1;  // cycle refinement scheme
+  options[5] = 0;  // reconstruction scheme
+  options[6] = 0;  // fixed assignments?
+  options[7] = 12261980; // random seed
+  options[8] = 0;  // debugging level
+
+  edgeConnections = (int *)malloc(sizeof(int)*numConnections);
+
+  i = 0;
+  for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n]) {
+    if (g_place_concreteNets[n]->m_numTerms > 1)
+      for(t=0; t<g_place_concreteNets[n]->m_numTerms; t++)
+        edgeConnections[i++] = g_place_concreteNets[n]->m_terms[t]->m_id;
+  }
+
+  HMETIS_PartRecursive(g_place_numCells, numEdges, vertexWeights,
+		       edgeDegree, edgeConnections, NULL,
+		       2, (int)(100*MAX_PARTITION_NONSYMMETRY),
+		       options, partitionAssignment, &afterCuts);
+	
+  /*
+  printf("HMET-20 : \t\t\tbalance before %d / %d ... ", parent->m_sub1->m_numMembers,
+         parent->m_sub2->m_numMembers);
+  */
+
+  // reassign members to subpartitions
+  parent->m_sub1->m_numMembers = 0;
+  parent->m_sub1->m_area = 0;
+  parent->m_sub2->m_numMembers = 0;
+  parent->m_sub2->m_area = 0;
+  parent->m_sub1->m_members = (ConcreteCell**)realloc(parent->m_sub1->m_members, 
+       sizeof(ConcreteCell*)*parent->m_numMembers); 
+  parent->m_sub2->m_members = (ConcreteCell**)realloc(parent->m_sub2->m_members, 
+       sizeof(ConcreteCell*)*parent->m_numMembers); 
+ 
+  for(t=0; t<parent->m_numMembers; t++) if (parent->m_members[t]) {
+    cell = parent->m_members[t];
+    area = getCellArea(cell);
+    if (partitionAssignment[cell->m_id] == 0) {
+      parent->m_sub1->m_members[parent->m_sub1->m_numMembers++] = cell;
+      parent->m_sub1->m_area += area;
+    }
+    else {
+      parent->m_sub2->m_members[parent->m_sub2->m_numMembers++] = cell;
+      parent->m_sub2->m_area += area;
+    }
+  }
+  /*
+  printf("after %d / %d\n", parent->m_sub1->m_numMembers,
+         parent->m_sub2->m_numMembers);
+  */
+
+  // cout << "HMET-21 : \t\t\tloc: " << initial_cut <<  " targetting: " << targets*100/parent->m_members.length() << "%" << endl;
+  // cout << "HMET-22 : \t\t\tstarting cuts= " << beforeCuts << " final cuts= " << afterCuts << endl;
+
+  free(edgeConnections);
+  free(vertexWeights);
+  free(edgeDegree);
+  free(partitionAssignment);
+#endif
+}
+
+
+// --------------------------------------------------------------------
+// repartitionFM()
+//
+/// \brief Fiduccia-Matheyses mincut partitioning algorithm.
+//
+/// UNIMPLEMENTED (well, un-C-ified)
+//
+// --------------------------------------------------------------------
+void repartitionFM(Partition *parent) {
+#if 0
+    assert(!parent->leaf && parent->m_sub1->leaf && parent->m_sub2->leaf);
+
+    // count of each net's number of cells in each bipartition
+    int count_1[m_design->nets.length()];
+    memset(count_1, 0, sizeof(int)*m_design->nets.length());
+    int count_2[m_design->nets.length()];
+    memset(count_2, 0, sizeof(int)*m_design->nets.length());
+
+    FM_cell target[m_design->cells.length()];
+    memset(target, 0, sizeof(FM_cell)*m_design->cells.length());
+    FM_cell *bin[FM_MAX_BIN+1];
+    FM_cell *locked = 0;
+    memset(bin, 0, sizeof(FM_cell *)*(FM_MAX_BIN+1));
+
+    int max_gain = 0;
+    int before_cuts = 0, current_cuts = 0;
+    double initial_cut;
+    int targets = 0;
+    long cell_id;
+    double halfArea = parent->m_area / 2.0;
+    double areaFlexibility = parent->m_area * MAX_PARTITION_NONSYMMETRY;
+    ConcreteNet *net;
+
+    // INITIALIZATION
+    //   select cells to partition
+
+    if (parent->vertical) {
+	// vertical
+
+	initial_cut = parent->m_sub2->m_bounds.x;
+
+	// initialize all cells
+	for(h::list<ConcreteCell *>::iterator it = rootPartition->m_members.begin(); !it; it++) {
+	    cell_id = (*it)->getID();
+	    if ((*it)->temp_x < initial_cut)
+		target[cell_id].loc = -1;
+	    else
+		target[cell_id].loc = -2;
+	    target[cell_id].cell = *it;
+	    target[cell_id].gain = 0;
+	}
+
+	// initialize cells in partition 1
+	for(h::list<ConcreteCell *>::iterator it = parent->m_sub1->m_members.begin(); !it; it++) {
+	    cell_id = (*it)->getID();
+	    // pay attention to cells that are close to the cut
+	    if (abs((*it)->temp_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
+		targets++;
+		target[cell_id].loc = 1;
+	    }
+	}
+
+	// initialize cells in partition 2
+	for(h::list<ConcreteCell *>::iterator it = parent->m_sub2->m_members.begin(); !it; it++) {
+	    cell_id = (*it)->getID();
+	    // pay attention to cells that are close to the cut
+	    if (abs((*it)->temp_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
+		targets++;
+		target[cell_id].loc = 2;
+	    }		
+	}
+
+   	// count the number of cells on each side of the partition for every net 
+	for(h::hash_map<ConcreteNet *>::iterator n_it = m_design->nets.begin(); !n_it; n_it++) {
+	    for(ConcretePinList::iterator p_it = (net = *n_it)->getPins().begin(); !p_it; p_it++)
+		if (abs(target[(*p_it)->getCell()->getID()].loc) == 1)
+		    count_1[net->getID()]++;
+		else if (abs(target[(*p_it)->getCell()->getID()].loc) == 2)
+		    count_2[net->getID()]++;
+		else if ((*p_it)->getCell()->temp_x < initial_cut) 
+		    count_1[net->getID()]++;
+		else
+		    count_2[net->getID()]++;
+	    if (count_1[net->getID()] > 0 && count_2[net->getID()] > 0) before_cuts++;
+	}
+	
+    } else {
+	// horizontal
+
+	initial_cut = parent->m_sub2->m_bounds.y;
+
+	// initialize all cells
+	for(h::list<ConcreteCell *>::iterator it = rootPartition->m_members.begin(); !it; it++) {
+	    cell_id = (*it)->getID();
+	    if ((*it)->temp_y < initial_cut)
+		target[cell_id].loc = -1;
+	    else
+		target[cell_id].loc = -2;
+	    target[cell_id].cell = *it;
+	    target[cell_id].gain = 0;
+	}
+
+	// initialize cells in partition 1
+	for(h::list<ConcreteCell *>::iterator it = parent->m_sub1->m_members.begin(); !it; it++) {
+	    cell_id = (*it)->getID();
+	    // pay attention to cells that are close to the cut
+	    if (abs((*it)->temp_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
+		targets++;
+		target[cell_id].loc = 1;
+	    }
+	}
+
+	// initialize cells in partition 2
+	for(h::list<ConcreteCell *>::iterator it = parent->m_sub2->m_members.begin(); !it; it++) {
+	    cell_id = (*it)->getID();
+	    // pay attention to cells that are close to the cut
+	    if (abs((*it)->temp_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
+		targets++;
+		target[cell_id].loc = 2;
+	    }		
+	}
+
+   	// count the number of cells on each side of the partition for every net 
+	for(h::hash_map<ConcreteNet *>::iterator n_it = m_design->nets.begin(); !n_it; n_it++) {
+	    for(ConcretePinList::iterator p_it = (net = *n_it)->getPins().begin(); !p_it; p_it++)
+		if (abs(target[(*p_it)->getCell()->getID()].loc) == 1)
+		    count_1[net->getID()]++;
+		else if (abs(target[(*p_it)->getCell()->getID()].loc) == 2)
+		    count_2[net->getID()]++;
+		else if ((*p_it)->getCell()->temp_y < initial_cut) 
+		    count_1[net->getID()]++;
+		else
+		    count_2[net->getID()]++;
+	    if (count_1[net->getID()] > 0 && count_2[net->getID()] > 0) before_cuts++;
+	}
+    }
+
+    // INITIAL GAIN CALCULATION
+    for(long id=0; id < m_design->cells.length(); id++)
+	if (target[id].loc > 0) {
+	    assert(target[id].cell != 0);
+	    assert(target[id].gain == 0);
+
+	    // examine counts for the net on each pin
+	    for(ConcretePinMap::iterator p_it = target[id].cell->getPins().begin(); !p_it; p_it++)
+		if ((*p_it)->isAttached()) {
+		    int n_id = (*p_it)->getNet()->getID();
+		    if (target[id].loc == 1 && count_1[n_id] == 1) target[id].gain++;
+		    if (target[id].loc == 1 && count_2[n_id] == 0) target[id].gain--;
+		    if (target[id].loc == 2 && count_1[n_id] == 0) target[id].gain--;
+		    if (target[id].loc == 2 && count_2[n_id] == 1) target[id].gain++;
+		}
+
+	    assert(target[id].cell->getPins().length() >= abs(target[id].gain));
+
+	    // add it to a bin
+	    int bin_num = min(max(0, target[id].gain),FM_MAX_BIN);
+	    max_gain = max(max_gain, bin_num);
+
+	    assert(bin_num >= 0 && bin_num <= FM_MAX_BIN);
+	    target[id].next = bin[bin_num];
+	    target[id].prev = 0;
+	    if (bin[bin_num] != 0)
+		bin[bin_num]->prev = &target[id];
+	    bin[bin_num] = &target[id];
+	}
+
+    // OUTER F-M LOOP
+    current_cuts = before_cuts;
+    int num_moves = 1;
+    int pass = 0;
+    while(num_moves > 0 && pass < FM_MAX_PASSES) {
+	pass++;
+	num_moves = 0;	
+
+	// check_list(bin, locked, targets); // DEBUG
+
+	// move all locked cells back
+	int moved_back = 0;
+	while(locked != 0) {
+	    FM_cell *current = locked;
+	    current->locked = false;
+
+	    int bin_num = min(max(0, current->gain),FM_MAX_BIN);	   
+	    max_gain = max(max_gain, bin_num);
+
+	    locked = current->next;
+	    if (locked != 0)
+		locked->prev = 0;
+
+	    if (bin[bin_num] != 0)
+		bin[bin_num]->prev = current;
+	    current->next = bin[bin_num];
+	    bin[bin_num] = current;
+
+	    moved_back++;
+	}
+	// cout << "\tmoved back: " << moved_back << endl;
+	// check_list(bin, locked, targets); // DEBUG	
+	
+	max_gain = FM_MAX_BIN;
+	while(bin[max_gain] == 0 && max_gain > 0) max_gain--;
+
+	// INNER F-M LOOP (single pass)
+	while(1) {
+
+	    int bin_num = FM_MAX_BIN;
+	    FM_cell *current = bin[bin_num];
+
+	    // look for next cell to move
+	    while (bin_num > 0 && (current == 0 || 
+		(current->loc==1 && current->cell->getArea()+parent->m_sub2->m_area > halfArea+areaFlexibility) ||
+		(current->loc==2 && current->cell->getArea()+parent->m_sub1->m_area > halfArea+areaFlexibility))) {
+
+		if (current == 0) current = bin[--bin_num]; else current = current->next;		
+	    }
+	    if (bin_num == 0)
+		break;
+
+	    num_moves++;
+	    current->locked = true;
+	    // cout << "moving cell " << current->cell->getID() << " gain=" << current->gain << " pins= " << current->cell->getPins().length() << " from " << current->loc;
+
+	    // change partition marking and areas
+	    if (current->loc == 1) {
+		current->loc = 2;
+		parent->m_sub1->m_area -= current->cell->getArea();
+		parent->m_sub2->m_area += current->cell->getArea();
+
+		// update partition counts on all nets attached to this cell
+		for(ConcretePinMap::iterator p_it = current->cell->getPins().begin(); 
+		    !p_it; p_it++) {
+		    
+		    if (!(*p_it)->isAttached()) // ignore unattached pins
+			continue;
+		    net = (*p_it)->getNet();
+		    
+		    count_1[net->getID()]--;
+		    count_2[net->getID()]++;
+
+		    // cout << "\tnet " << net->getID() << " was " << count_1[net->getID()]+1 << "/" << count_2[net->getID()]-1 << " now " << count_1[net->getID()] << "/" << count_2[net->getID()] << endl;
+
+		    // if net becomes critical, update gains on attached cells and resort bins
+		    if (count_1[net->getID()] == 0) { current_cuts--; FM_updateGains(net, 2, -1, target, bin, count_1, count_2); }
+		    if (count_2[net->getID()] == 1) { current_cuts++; FM_updateGains(net, 1, -1, target, bin, count_1, count_2); }
+		    
+		    // check_list(bin, locked, targets); // DEBUG
+		}
+
+	    } else {
+		current->loc = 1;
+		parent->m_sub2->m_area -= current->cell->getArea();
+		parent->m_sub1->m_area += current->cell->getArea();
+
+		// update gains on all nets attached to this cell
+		for(ConcretePinMap::iterator p_it = current->cell->getPins().begin(); 
+		    !p_it; p_it++) {
+		    
+		    if (!(*p_it)->isAttached()) // ignore unattached pins
+			continue;
+		    net = (*p_it)->getNet();
+		    count_2[net->getID()]--;
+		    count_1[net->getID()]++;
+
+		    // cout << "\tnet " << net->getID() << " was " << count_1[net->getID()]-1 << "/" << count_2[net->getID()]+1 << " now " << count_1[net->getID()] << "/" << count_2[net->getID()] << endl;
+
+		    if (count_2[net->getID()] == 0) { current_cuts--; FM_updateGains(net, 2, -1, target, bin, count_1, count_2); }
+		    if (count_1[net->getID()] == 1) { current_cuts++; FM_updateGains(net, 1, -1, target, bin, count_1, count_2); }
+		
+		    // check_list(bin, locked, targets); // DEBUG
+		}
+	    }
+
+	    //cout << " cuts=" << current_cuts << endl;
+
+	    // move current to locked
+
+/*
+	    cout << "b=" << bin[bin_num] << " ";
+	    cout << current->prev << "-> ";
+	    if (current->prev == 0)
+		cout << "X";
+	    else cout << current->prev->next;
+	    cout  << "=" << current << "=";
+	    if (current->next == 0)
+		cout << "X";
+	    else
+		cout << current->next->prev;
+	    cout << " ->" << current->next << endl;
+*/
+
+	    if (bin[bin_num] == current)
+		bin[bin_num] = current->next;
+	    if (current->prev != 0)
+		current->prev->next = current->next;
+	    if (current->next != 0)
+		current->next->prev = current->prev;
+
+/*
+	    cout << "b=" << bin[bin_num] << " ";
+	    cout << current->prev << "-> ";
+	    if (current->prev == 0)
+		cout << "X";
+	    else cout << current->prev->next;
+	    cout  << "=" << current << "=";
+	    if (current->next == 0)
+		cout << "X";
+	    else
+		cout << current->next->prev;
+	    cout << " ->" << current->next << endl;
+*/
+
+	    current->prev = 0;
+	    current->next = locked;
+	    if (locked != 0)
+		locked->prev = current;
+	    locked = current;
+	    
+	    // check_list(bin, locked, targets); // DEBUG	
+
+	    // update max_gain
+	    max_gain = FM_MAX_BIN;
+	    while(bin[max_gain] == 0 && max_gain > 0) max_gain--;
+	}
+
+	// cout << "\tcurrent cuts= " << current_cuts << " moves= " << num_moves << endl;
+    }
+
+    // reassign members to subpartitions
+    cout << "FIDM-20 : \tbalance before " << parent->m_sub1->m_members.length() << "/"
+       << parent->m_sub2->m_members.length() << " ";
+    parent->m_sub1->m_members.clear();
+    parent->m_sub1->m_area = 0;
+    parent->m_sub2->m_members.clear();
+    parent->m_sub2->m_area = 0;
+    for(h::list<ConcreteCell *>::iterator it = parent->m_members.begin(); !it; it++) {
+	if (target[(*it)->getID()].loc == 1 || target[(*it)->getID()].loc == -1) {
+	    parent->m_sub1->m_members.push_back(*it);
+	    parent->m_sub1->m_area += (*it)->getArea();
+	}
+	else {
+	    parent->m_sub2->m_members.push_back(*it);
+	    parent->m_sub2->m_area += (*it)->getArea();
+	}
+    }
+    cout << " after " << parent->m_sub1->m_members.length() << "/"
+       << parent->m_sub2->m_members.length() << endl;
+
+
+    cout << "FIDM-21 : \tloc: " << initial_cut <<  " targetting: " << targets*100/parent->m_members.length() << "%" << endl;
+    cout << "FIDM-22 : \tstarting cuts= " << before_cuts << " final cuts= " << current_cuts << endl;
+#endif
+}
+
+// ----- FM_updateGains()
+//   moves a cell between bins
+#if 0
+void FM_updateGains(ConcreteNet *net, int partition, int inc, 
+                    FM_cell target [], FM_cell *bin [], 
+                    int count_1 [], int count_2 []) {
+
+    for(ConcretePinList::iterator it = net->getPins().begin(); !it; it++) {
+	FM_cell *current = &(target[(*it)->getCell()->getID()]);
+	assert(current->cell != 0);
+	
+	int old_gain = current->gain;
+	current->gain = 0;
+
+	// examine counts for the net on each pin
+	for(ConcretePinMap::iterator p_it = current->cell->getPins().begin(); !p_it; p_it++)
+	    if ((*p_it)->isAttached()) {
+		int n_id = (*p_it)->getNet()->getID();
+		if (current->loc == 1 && count_1[n_id] == 1) current->gain++;
+		if (current->loc == 1 && count_2[n_id] == 0) current->gain--;
+		if (current->loc == 2 && count_1[n_id] == 0) current->gain--;
+		if (current->loc == 2 && count_2[n_id] == 1) current->gain++;
+	    }
+
+	if (!current->locked) {
+	    // remove cell from existing bin
+	    int bin_num =  min(max(0, old_gain),FM_MAX_BIN);
+	    if (bin[bin_num] == current)
+		bin[bin_num] = current->next;
+	    if (current->prev != 0)
+		current->prev->next = current->next;
+	    if (current->next != 0)
+		current->next->prev = current->prev;
+	    // add cell to correct bin
+	    bin_num =  min(max(0, current->gain),FM_MAX_BIN);
+	    current->prev = 0;
+	    current->next = bin[bin_num];
+	    if (bin[bin_num] != 0)
+		bin[bin_num]->prev = current;
+	    bin[bin_num] = current;
+	}
+    }
+    
+}
+#endif
+
+
+// --------------------------------------------------------------------
+// partitionEqualArea()
+//
+/// \brief Splits a partition into two halves of equal area.
+//
+// --------------------------------------------------------------------
+void partitionEqualArea(Partition *parent) {
+  float halfArea, area;
+  int i=0;
+  
+  // which way to sort?
+  if (parent->m_vertical)
+    // sort by X position
+    qsort(parent->m_members, parent->m_numMembers, sizeof(ConcreteCell*), cellSortByX);
+  else
+    // sort by Y position
+    qsort(parent->m_members, parent->m_numMembers, sizeof(ConcreteCell*), cellSortByY);
+
+  // split the list
+  halfArea = parent->m_area*0.5;
+  parent->m_sub1->m_area = 0.0;
+  parent->m_sub1->m_numMembers = 0;
+  parent->m_sub1->m_members = (ConcreteCell**)realloc(parent->m_sub1->m_members, 
+                                  sizeof(ConcreteCell*)*parent->m_numMembers);
+  parent->m_sub2->m_area = 0.0;
+  parent->m_sub2->m_numMembers = 0;
+  parent->m_sub2->m_members = (ConcreteCell**)realloc(parent->m_sub2->m_members, 
+                                  sizeof(ConcreteCell*)*parent->m_numMembers);
+
+  for(; parent->m_sub1->m_area < halfArea; i++) 
+    if (parent->m_members[i]) {
+      area = getCellArea(parent->m_members[i]);
+      parent->m_sub1->m_members[parent->m_sub1->m_numMembers++] = parent->m_members[i];
+      parent->m_sub1->m_area += area;
+  }
+  for(; i<parent->m_numMembers; i++) 
+    if (parent->m_members[i]) {
+      area = getCellArea(parent->m_members[i]);
+      parent->m_sub2->m_members[parent->m_sub2->m_numMembers++] = parent->m_members[i];
+      parent->m_sub2->m_area += area;
+    }
+  
+}
+
+
+// --------------------------------------------------------------------
+// partitionScanlineMincut()
+//
+/// \brief Scans the cells within a partition from left to right and chooses the min-cut.
+//
+// --------------------------------------------------------------------
+void partitionScanlineMincut(Partition *parent) {
+#if 0
+  int current_cuts = 0;
+  int minimum_cuts = INT_MAX;
+  ConcreteCell *minimum_location = NULL;
+  double currentArea = 0, halfArea = parent->m_area * 0.5;
+  double areaFlexibility = parent->m_area * MAX_PARTITION_NONSYMMETRY;
+  double newLine, oldLine = -DBL_MAX;
+
+  for(ConcreteNetList::iterator n_it = m_design->nets.begin(); !n_it; n_it++)
+    (*n_it)->m_mark = 0;
+  for(h::list<ConcreteCell *>::iterator i = parent->m_members.begin();
+      !i.isDone(); i++) {
+    assert(*i);
+    for(ConcretePinMap::iterator j = (*i)->getPins().begin();
+	!j.isDone(); j++) {
+      assert(*j);
+      if((*j)->isAttached()) {
+	(*j)->getNet()->m_mark = 1;
+      }
+    }
+  }
+
+  if (parent->vertical) {
+    parent->m_members.sort(sortByX);
+    int all1 = 0, all2 = 0;
+    h::list<ConcreteCell *>::iterator local = parent->m_members.begin();
+    for(; !local.isDone(); local++) {
+      currentArea += (*local)->getArea();
+      if (currentArea < halfArea-areaFlexibility)
+	continue;
+      if (currentArea > halfArea+areaFlexibility)
+	break;
+      newLine = (*local)->temp_x;
+      while(all1 < g_place_numNets && allNetsL2[all1]->getBoundingBox().left() <= newLine) {
+	if(allNetsL2[all1]->m_mark) {
+	  current_cuts++;
+	}
+	all1++;
+      }
+      while(all2 < g_place_numNets && allNetsR2[all2]->getBoundingBox().right() <= newLine) {
+	if(allNetsR2[all2]->m_mark) {
+	  current_cuts--;
+	}
+	all2++;
+      }
+      if (current_cuts < minimum_cuts) {
+	minimum_cuts = current_cuts;
+	minimum_location = *local;
+      }
+      oldLine = newLine;
+    }
+  }
+  else {
+    parent->m_members.sort(sortByY);
+    int all1 = 0, all2 = 0;
+    h::list<ConcreteCell *>::iterator local = parent->m_members.begin();
+    for(; !local.isDone(); local++) {
+      currentArea += (*local)->getArea();
+      if (currentArea < halfArea-areaFlexibility)
+	continue;
+      if (currentArea > halfArea+areaFlexibility)
+	break;
+      newLine = (*local)->temp_y;
+      while(all1 < g_place_numNets && allNetsB2[all1]->getBoundingBox().top() <= newLine) {
+	if(allNetsB2[all1]->m_mark) {
+	  current_cuts++;
+	}
+	all1++;
+      }
+      while(all2 < g_place_numNets && allNetsT2[all2]->getBoundingBox().bottom() <= newLine) {
+	if(allNetsT2[all2]->m_mark) {
+	  current_cuts--;
+	}
+	all2++;
+      }
+      if (current_cuts < minimum_cuts) {
+	minimum_cuts = current_cuts;
+	minimum_location = *local;
+      }
+      oldLine = newLine;
+    }
+  }
+  if (minimum_location == NULL) {
+    return partitionEqualArea(parent);
+  }
+  h::list<ConcreteCell *>::iterator it = parent->m_members.begin();
+  parent->m_sub1->m_members.clear();
+  parent->m_sub1->m_area = 0;
+  for(; *it != minimum_location; it++) {
+    parent->m_sub1->m_members.push_front(*it);
+    parent->m_sub1->m_area += (*it)->getArea();
+  }
+  parent->m_sub2->m_members.clear();
+  parent->m_sub2->m_area = 0;
+  for(; !it; it++) {
+    parent->m_sub2->m_members.push_front(*it);
+    parent->m_sub2->m_area += (*it)->getArea();
+  }
+#endif
+}
+
+
+// --------------------------------------------------------------------
+// reallocPartition()
+//
+/// \brief Reallocates a partition and all of its children.
+//
+// --------------------------------------------------------------------
+void reallocPartition(Partition *p) {
+
+  if (p->m_leaf) {
+    return;
+  }
+
+  // --- INITIAL PARTITION
+
+  if (PARTITION_AREA_ONLY)
+    partitionEqualArea(p);
+  else 
+    partitionScanlineMincut(p);
+
+  resizePartition(p);
+
+  // --- PARTITION IMPROVEMENT
+  if (p->m_level < REPARTITION_LEVEL_DEPTH) {
+    if (REPARTITION_HMETIS)
+      repartitionHMetis(p);
+    
+    resizePartition(p);
+  }
+
+  reallocPartition(p->m_sub1);
+  reallocPartition(p->m_sub2);
+}
+
+
+// --------------------------------------------------------------------
+// resizePartition()
+//
+/// \brief Recomputes the bounding boxes of the child partitions based on their relative areas.
+//
+// --------------------------------------------------------------------
+void resizePartition(Partition *p) {
+  // compute the new bounding box
+  p->m_sub1->m_bounds.x = p->m_bounds.x;
+  p->m_sub1->m_bounds.y = p->m_bounds.y;
+  if (p->m_vertical) {
+    p->m_sub1->m_bounds.w = p->m_bounds.w*(p->m_sub1->m_area/p->m_area);
+    p->m_sub1->m_bounds.h = p->m_bounds.h;
+    p->m_sub2->m_bounds.x = p->m_bounds.x + p->m_sub1->m_bounds.w;
+    p->m_sub2->m_bounds.w = p->m_bounds.w*(p->m_sub2->m_area/p->m_area);
+    p->m_sub2->m_bounds.y = p->m_bounds.y;
+    p->m_sub2->m_bounds.h = p->m_bounds.h;
+  } else {
+    p->m_sub1->m_bounds.h = p->m_bounds.h*(p->m_sub1->m_area/p->m_area);
+    p->m_sub1->m_bounds.w = p->m_bounds.w;
+    p->m_sub2->m_bounds.y = p->m_bounds.y + p->m_sub1->m_bounds.h;
+    p->m_sub2->m_bounds.h = p->m_bounds.h*(p->m_sub2->m_area/p->m_area);
+    p->m_sub2->m_bounds.x = p->m_bounds.x;
+    p->m_sub2->m_bounds.w = p->m_bounds.w;
+  }
+}
+
+
+// --------------------------------------------------------------------
+// incrementalSubpartition()
+//
+/// \brief Adds new cells to an existing partition.  Partition sizes/locations are unchanged.
+///
+/// The function recurses, adding new cells to appropriate subpartitions.
+//
+// --------------------------------------------------------------------
+void incrementalSubpartition(Partition *p, ConcreteCell *newCells [], const int numNewCells) {
+  int c;
+  ConcreteCell **newCells1 = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*numNewCells), 
+    **newCells2 = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*numNewCells);
+  int numNewCells1 = 0, numNewCells2 = 0;
+  float cut_loc;
+
+  assert(p);
+
+  // add new cells to partition list
+  p->m_members = (ConcreteCell**)realloc(p->m_members, 
+       sizeof(ConcreteCell*)*(p->m_numMembers+numNewCells));
+  memcpy(&(p->m_members[p->m_numMembers]), newCells, sizeof(ConcreteCell*)*numNewCells);
+  p->m_numMembers += numNewCells;
+
+  // if is a leaf partition, finished
+  if (p->m_leaf) return;
+
+  // split new cells into sub-partitions based on location
+  if (p->m_vertical) {
+    cut_loc = p->m_sub2->m_bounds.x;
+    for(c=0; c<numNewCells; c++)
+      if (newCells[c]->m_x < cut_loc)
+        newCells1[numNewCells1++] = newCells[c];
+      else
+        newCells2[numNewCells2++] = newCells[c];
+  } else {
+    cut_loc = p->m_sub2->m_bounds.y;
+    for(c=0; c<numNewCells; c++)
+      if (newCells[c]->m_y < cut_loc)
+        newCells1[numNewCells1++] = newCells[c];
+      else
+        newCells2[numNewCells2++] = newCells[c];    
+  }
+
+  if (numNewCells1 > 0) incrementalSubpartition(p->m_sub1, newCells1, numNewCells1);
+  if (numNewCells2 > 0) incrementalSubpartition(p->m_sub2, newCells2, numNewCells2);
+
+  free(newCells1);
+  free(newCells2);
+}
+
+
+// --------------------------------------------------------------------
+// incrementalPartition()
+//
+/// \brief Adds new cells to an existing partition.  Partition sizes/locations are unchanged.
+///
+/// The function recurses, adding new cells to appropriate subpartitions.
+//
+// --------------------------------------------------------------------
+void incrementalPartition() {
+  int c = 0, c2 = 0;
+  int numNewCells = 0;
+  ConcreteCell **allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells),
+    **newCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells);
+
+  assert(g_place_rootPartition);
+
+  // update cell list of root partition
+  memcpy(allCells, g_place_concreteCells, sizeof(ConcreteCell*)*g_place_numCells);
+  qsort(allCells, g_place_numCells, sizeof(ConcreteCell*), cellSortByID);
+  qsort(g_place_rootPartition->m_members, g_place_rootPartition->m_numMembers,
+        sizeof(ConcreteCell*), cellSortByID);
+
+  // scan sorted lists and collect cells not in partitions
+  while(!allCells[c++]);
+  while(!g_place_rootPartition->m_members[c2++]);
+
+  for(; c<g_place_numCells; c++, c2++) {
+    while(c2 < g_place_rootPartition->m_numMembers &&
+          allCells[c]->m_id > g_place_rootPartition->m_members[c2]->m_id) c2++;
+    while(c < g_place_numCells && 
+          (c2 >= g_place_rootPartition->m_numMembers ||
+           allCells[c]->m_id < g_place_rootPartition->m_members[c2]->m_id)) {
+      // a new cell!
+      newCells[numNewCells++] = allCells[c];
+      c++;
+    }
+  }
+  
+  printf("QPRT-50 : \tincremental partitioning with %d new cells\n", numNewCells);
+  if (numNewCells>0) incrementalSubpartition(g_place_rootPartition, newCells, numNewCells);
+
+  free(allCells);
+  free(newCells);
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/phys/place/place_qpsolver.c b/abc-build/src/phys/place/place_qpsolver.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/place_qpsolver.c
@@ -0,0 +1,1275 @@
+/*===================================================================*/
+//  
+//     place_qpsolver.c
+//
+//		Philip Chong
+//              pchong@cadence.com
+//
+/*===================================================================*/
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "place_qpsolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+#undef  QPS_DEBUG
+
+#define QPS_TOL 1.0e-3
+#define QPS_EPS (QPS_TOL * QPS_TOL)
+
+#define QPS_MAX_TOL 0.1
+#define QPS_LOOP_TOL 1.0e-3
+
+#define QPS_RELAX_ITER 180
+#define QPS_MAX_ITER 200
+#define QPS_STEPSIZE_RETRIES 2
+#define QPS_MINSTEP 1.0e-6
+#define QPS_DEC_CHANGE 0.01
+
+#define QPS_PRECON
+#define QPS_PRECON_EPS 1.0e-9
+
+#undef QPS_HOIST
+
+#if defined(QPS_DEBUG)
+#define QPS_DEBUG_FILE "/tmp/qps_debug.log"
+#endif
+
+#if 0
+  /* ii is an array [0..p->num_cells-1] of indices from cells of original
+     problem to modified problem variables.  If ii[k] >= 0, cell is an
+     independent cell; ii[k], ii[k]+1 are the indices of the corresponding
+     variables for the modified problem.  If ii[k] == -1, cell is a fixed
+     cell.  If ii[k] <= -2, cell is a dependent cell; -(ii[k]+2) is the index 
+     of the corresponding COG constraint. */
+int *ii;
+
+  /* gt is an array [0..p->cog_num-1] of indices from COG constraints to
+     locations in the gl array (in qps_problem_t).  gt[k] is the offset into
+     gl where the kth constraint begins. */
+int *gt;
+
+  /* n is the number of variables in the modified problem.  n should be twice
+     the number of independent cells. */
+int n;
+
+qps_float_t *cp;		/* current location during CG iteration */
+qps_float_t f;			/* value of cost function at p */
+
+#endif
+
+/**********************************************************************/
+
+static void
+qps_settp(qps_problem_t * p)
+{
+  /* Fill in the p->priv_tp array with the current locations of all cells
+     (independent, dependent and fixed). */
+
+  int i;
+  int t, u;
+  int pr;
+  qps_float_t rx, ry;
+  qps_float_t ta;
+
+  int *ii = p->priv_ii;
+  qps_float_t *tp = p->priv_tp;
+  qps_float_t *cp = p->priv_cp;
+
+  /* do independent and fixed cells first */
+  for (i = p->num_cells; i--;) {
+    t = ii[i];
+    if (t >= 0) {		/* indep cell */
+      tp[i * 2] = cp[t];
+      tp[i * 2 + 1] = cp[t + 1];
+    }
+    else if (t == -1) {		/* fixed cell */
+      tp[i * 2] = p->x[i];
+      tp[i * 2 + 1] = p->y[i];
+    }
+  }
+  /* now do dependent cells */
+  for (i = p->num_cells; i--;) {
+    if (ii[i] < -1) {
+      t = -(ii[i] + 2);		/* index of COG constraint */
+      ta = 0.0;
+      rx = 0.0;
+      ry = 0.0;
+      pr = p->priv_gt[t];
+      while ((u = p->cog_list[pr++]) >= 0) {
+	ta += p->area[u];
+	if (u != i) {
+	  rx -= p->area[u] * tp[u * 2];
+	  ry -= p->area[u] * tp[u * 2 + 1];
+	}
+      }
+      rx += p->cog_x[t] * ta;
+      ry += p->cog_y[t] * ta;
+      tp[i * 2] = rx / p->area[i];
+      tp[i * 2 + 1] = ry / p->area[i];
+    }
+  }
+
+#if (QPS_DEBUG > 5)
+  fprintf(p->priv_fp, "### qps_settp()\n");
+  for (i = 0; i < p->num_cells; i++) {
+    fprintf(p->priv_fp, "%f %f\n", tp[i * 2], tp[i * 2 + 1]);
+  }
+#endif
+}
+
+/**********************************************************************/
+
+static qps_float_t
+qps_func(qps_problem_t * p)
+{
+  /* Return f(p).  qps_settp() should have already been called before
+     entering here */
+
+  int j, k;
+  int pr;
+  qps_float_t jx, jy, tx, ty;
+  qps_float_t f;
+  qps_float_t w;
+
+#if !defined(QPS_HOIST)
+  int i;
+  int st;
+  qps_float_t kx, ky, sx, sy;
+  qps_float_t t;
+#endif
+
+  qps_float_t *tp = p->priv_tp;
+
+  f = 0.0;
+  pr = 0;
+  for (j = 0; j < p->num_cells; j++) {
+    jx = tp[j * 2];
+    jy = tp[j * 2 + 1];
+    while ((k = p->priv_cc[pr]) >= 0) {
+      w = p->priv_cw[pr];
+      tx = tp[k * 2] - jx;
+      ty = tp[k * 2 + 1] - jy;
+      f += w * (tx * tx + ty * ty);
+      pr++;
+    }
+    pr++;
+  }
+  p->f = f;
+
+#if !defined(QPS_HOIST)
+  /* loop penalties */
+  pr = 0;
+  for (i = 0; i < p->loop_num; i++) {
+    t = 0.0;
+    j = st = p->loop_list[pr++];
+    jx = sx = tp[j * 2];
+    jy = sy = tp[j * 2 + 1];
+    while ((k = p->loop_list[pr]) >= 0) {
+      kx = tp[k * 2];
+      ky = tp[k * 2 + 1];
+      tx = jx - kx;
+      ty = jy - ky;
+      t += tx * tx + ty * ty;
+      j = k;
+      jx = kx;
+      jy = ky;
+      pr++;
+    }
+    tx = jx - sx;
+    ty = jy - sy;
+    t += tx * tx + ty * ty;
+    t -= p->loop_max[i];
+#if (QPS_DEBUG > 5)
+    fprintf(p->priv_fp, "### qps_penalty() %d %f %f\n",
+	    i, p->loop_max[i], t);
+#endif
+    p->priv_lt[i] = t;
+    f += p->loop_penalty[i] * t;
+    pr++;
+  }
+#endif /* QPS_HOIST */
+
+  if (p->max_enable) {
+    for (j = p->num_cells; j--;) {
+      f += p->priv_mxl[j] * (-tp[j * 2]);
+      f += p->priv_mxh[j] * (tp[j * 2] - p->max_x);
+      f += p->priv_myl[j] * (-tp[j * 2 + 1]);
+      f += p->priv_myh[j] * (tp[j * 2 + 1] - p->max_y);
+    }
+  }
+
+#if (QPS_DEBUG > 5)
+  fprintf(p->priv_fp, "### qps_func() %f %f\n", f, p->f);
+#endif
+  return f;
+}
+
+/**********************************************************************/
+
+static void
+qps_dfunc(qps_problem_t * p, qps_float_t * d)
+{
+  /* Set d to grad f(p).  First computes partial derivatives wrt all cells
+     then finds gradient wrt only the independent cells.  qps_settp() should
+     have already been called before entering here */
+
+  int i, j, k;
+  int pr = 0;
+  qps_float_t jx, jy, kx, ky, tx, ty;
+  int ji, ki;
+  qps_float_t w;
+
+#if !defined(QPS_HOIST)
+  qps_float_t sx, sy;
+  int st;
+#endif
+
+  qps_float_t *tp = p->priv_tp;
+  qps_float_t *tp2 = p->priv_tp2;
+
+  /* compute partials and store in tp2 */
+  for (i = p->num_cells; i--;) {
+    tp2[i * 2] = 0.0;
+    tp2[i * 2 + 1] = 0.0;
+  }
+  for (j = 0; j < p->num_cells; j++) {
+    jx = tp[j * 2];
+    jy = tp[j * 2 + 1];
+    while ((k = p->priv_cc[pr]) >= 0) {
+      w = 2.0 * p->priv_cw[pr];
+      kx = tp[k * 2];
+      ky = tp[k * 2 + 1];
+      tx = w * (jx - kx);
+      ty = w * (jy - ky);
+      tp2[j * 2] += tx;
+      tp2[k * 2] -= tx;
+      tp2[j * 2 + 1] += ty;
+      tp2[k * 2 + 1] -= ty;
+      pr++;
+    }
+    pr++;
+  }
+
+#if !defined(QPS_HOIST)
+  /* loop penalties */
+  pr = 0;
+  for (i = 0; i < p->loop_num; i++) {
+    j = st = p->loop_list[pr++];
+    jx = sx = tp[j * 2];
+    jy = sy = tp[j * 2 + 1];
+    w = 2.0 * p->loop_penalty[i];
+    while ((k = p->loop_list[pr]) >= 0) {
+      kx = tp[k * 2];
+      ky = tp[k * 2 + 1];
+      tx = w * (jx - kx);
+      ty = w * (jy - ky);
+      tp2[j * 2] += tx;
+      tp2[k * 2] -= tx;
+      tp2[j * 2 + 1] += ty;
+      tp2[k * 2 + 1] -= ty;
+      j = k;
+      jx = kx;
+      jy = ky;
+      pr++;
+    }
+    tx = w * (jx - sx);
+    ty = w * (jy - sy);
+    tp2[j * 2] += tx;
+    tp2[st * 2] -= tx;
+    tp2[j * 2 + 1] += ty;
+    tp2[st * 2 + 1] -= ty;
+    pr++;
+  }
+#endif /* QPS_HOIST */
+
+  if (p->max_enable) {
+    for (j = p->num_cells; j--;) {
+      tp2[j * 2] += p->priv_mxh[j] - p->priv_mxl[j];
+      tp2[j * 2 + 1] += p->priv_myh[j] - p->priv_myl[j];
+    }
+  }
+
+#if (QPS_DEBUG > 5)
+  fprintf(p->priv_fp, "### qps_dfunc() partials\n");
+  for (j = 0; j < p->num_cells; j++) {
+    fprintf(p->priv_fp, "%f %f\n", tp2[j * 2], tp2[j * 2 + 1]);
+  }
+#endif
+
+  /* translate partials to independent variables */
+  for (j = p->priv_n; j--;) {
+    d[j] = 0.0;
+  }
+  for (j = p->num_cells; j--;) {
+    ji = p->priv_ii[j];
+    if (ji >= 0) {		/* indep var */
+      d[ji] += tp2[j * 2];
+      d[ji + 1] += tp2[j * 2 + 1];
+    }
+    else if (ji < -1) {		/* dependent variable */
+      ji = -(ji + 2);		/* get COG index */
+      pr = p->priv_gt[ji];
+      while ((k = p->cog_list[pr]) >= 0) {
+	ki = p->priv_ii[k];
+	if (ki >= 0) {
+	  w = p->priv_gw[pr];
+#if (QPS_DEBUG > 0)
+	  assert(fabs(w - p->area[k] / p->area[j]) < 1.0e-6);
+#endif
+	  d[ki] -= tp2[j * 2] * w;
+	  d[ki + 1] -= tp2[j * 2 + 1] * w;
+	}
+	pr++;
+      }
+    }
+  }
+
+#if (QPS_DEBUG > 5)
+  fprintf(p->priv_fp, "### qps_dfunc() gradient\n");
+  for (j = 0; j < p->priv_n; j++) {
+    fprintf(p->priv_fp, "%f\n", d[j]);
+  }
+#endif
+}
+
+/**********************************************************************/
+
+static void
+qps_linmin(qps_problem_t * p, qps_float_t dgg, qps_float_t * h)
+{
+  /* Perform line minimization.  p->priv_cp is the current location, h is
+     direction of the gradient.  Updates p->priv_cp to line minimal position
+     based on formulas from "Handbook of Applied Optimization", Pardalos and
+     Resende, eds., Oxford Univ. Press, 2002.  qps_settp() should have
+     already been called before entering here.  Since p->priv_cp is changed,
+     p->priv_tp array becomes invalid following this routine. */
+
+  int i, j, k;
+  int pr;
+  int ji, ki;
+  qps_float_t jx, jy, kx, ky;
+  qps_float_t f = 0.0;
+  qps_float_t w;
+
+#if !defined(QPS_HOIST)
+  int st;
+  qps_float_t sx, sy, tx, ty;
+  qps_float_t t;
+#endif
+
+  qps_float_t *tp = p->priv_tp;
+
+  /* translate h vector to partials over all variables and store in tp */
+  for (i = p->num_cells; i--;) {
+    tp[i * 2] = 0.0;
+    tp[i * 2 + 1] = 0.0;
+  }
+  for (j = p->num_cells; j--;) {
+    ji = p->priv_ii[j];
+    if (ji >= 0) {		/* indep cell */
+      tp[j * 2] = h[ji];
+      tp[j * 2 + 1] = h[ji + 1];
+    }
+    else if (ji < -1) {		/* dep cell */
+      ji = -(ji + 2);		/* get COG index */
+      pr = p->priv_gt[ji];
+      while ((k = p->cog_list[pr]) >= 0) {
+	ki = p->priv_ii[k];
+	if (ki >= 0) {
+	  w = p->priv_gw[pr];
+#if (QPS_DEBUG > 0)
+	  assert(fabs(w - p->area[k] / p->area[j]) < 1.0e-6);
+#endif
+	  tp[j * 2] -= h[ki] * w;
+	  tp[j * 2 + 1] -= h[ki + 1] * w;
+	}
+	pr++;
+      }
+    }
+  }
+
+  /* take product x^T Z^T C Z x */
+  pr = 0;
+  for (j = 0; j < p->num_cells; j++) {
+    jx = tp[j * 2];
+    jy = tp[j * 2 + 1];
+    while ((k = p->priv_cc[pr]) >= 0) {
+      w = p->priv_cw[pr];
+      kx = tp[k * 2] - jx;
+      ky = tp[k * 2 + 1] - jy;
+      f += w * (kx * kx + ky * ky);
+      pr++;
+    }
+    pr++;
+  }
+
+#if !defined(QPS_HOIST)
+  /* add loop penalties */
+  pr = 0;
+  for (i = 0; i < p->loop_num; i++) {
+    t = 0.0;
+    j = st = p->loop_list[pr++];
+    jx = sx = tp[j * 2];
+    jy = sy = tp[j * 2 + 1];
+    while ((k = p->loop_list[pr]) >= 0) {
+      kx = tp[k * 2];
+      ky = tp[k * 2 + 1];
+      tx = jx - kx;
+      ty = jy - ky;
+      t += tx * tx + ty * ty;
+      j = k;
+      jx = kx;
+      jy = ky;
+      pr++;
+    }
+    tx = jx - sx;
+    ty = jy - sy;
+    t += tx * tx + ty * ty;
+    f += p->loop_penalty[i] * t;
+    pr++;
+  }
+#endif /* QPS_HOIST */
+
+#if (QPS_DEBUG > 0)
+  assert(f);
+#endif
+
+  /* compute step size */
+  f = (dgg / f) / 2.0;
+  for (j = p->priv_n; j--;) {
+    p->priv_cp[j] += f * h[j];
+  }
+#if (QPS_DEBUG > 5)
+  fprintf(p->priv_fp, "### qps_linmin() step %f\n", f);
+  for (j = 0; j < p->priv_n; j++) {
+    fprintf(p->priv_fp, "%f\n", p->priv_cp[j]);
+  }
+#endif
+}
+
+/**********************************************************************/
+
+static void
+qps_cgmin(qps_problem_t * p)
+{
+  /* Perform CG minimization. Mostly from "Numerical Recipes", Press et al.,
+     Cambridge Univ. Press, 1992, with some changes to help performance in
+     our restricted problem domain. */
+
+  qps_float_t fp, gg, dgg, gam;
+  qps_float_t t;
+  int i, j;
+
+  int n = p->priv_n;
+  qps_float_t *g = p->priv_g;
+  qps_float_t *h = p->priv_h;
+  qps_float_t *xi = p->priv_xi;
+
+  qps_settp(p);
+  fp = qps_func(p);
+  qps_dfunc(p, g);
+
+  dgg = 0.0;
+  for (j = n; j--;) {
+    g[j] = -g[j];
+    h[j] = g[j];
+#if defined(QPS_PRECON)
+    h[j] *= p->priv_pcgt[j];
+#endif
+    dgg += g[j] * h[j];
+  }
+
+  for (i = 0; i < 2 * n; i++) {
+
+#if (QPS_DEBUG > 5)
+    fprintf(p->priv_fp, "### qps_cgmin() top\n");
+    for (j = 0; j < p->priv_n; j++) {
+      fprintf(p->priv_fp, "%f\n", p->priv_cp[j]);
+    }
+#endif
+
+    if (dgg == 0.0) {
+      break;
+    }
+    qps_linmin(p, dgg, h);
+    qps_settp(p);
+    p->priv_f = qps_func(p);
+    if (fabs((p->priv_f) - fp) <=
+	(fabs(p->priv_f) + fabs(fp) + QPS_EPS) * QPS_TOL / 2.0) {
+      break;
+    }
+    fp = p->priv_f;
+    qps_dfunc(p, xi);
+    gg = dgg;
+    dgg = 0.0;
+    for (j = n; j--;) {
+      t = xi[j] * xi[j];
+#if defined(QPS_PRECON)
+      t *= p->priv_pcgt[j];
+#endif
+      dgg += t;
+    }
+    gam = dgg / gg;
+    for (j = n; j--;) {
+      g[j] = -xi[j];
+      t = g[j];
+#if defined(QPS_PRECON)
+      t *= p->priv_pcgt[j];
+#endif
+      h[j] = t + gam * h[j];
+    }
+  }
+#if (QPS_DEBUG > 0)
+  fprintf(p->priv_fp, "### CG ITERS=%d %d %d\n", i, p->cog_num, p->loop_num);
+#endif
+  if (i == 2 * n) {
+    fprintf(stderr, "### Too many iterations in qps_cgmin()\n");
+#if defined(QPS_DEBUG)
+    fprintf(p->priv_fp, "### Too many iterations in qps_cgmin()\n");
+#endif
+  }
+}
+
+/**********************************************************************/
+
+void
+qps_init(qps_problem_t * p)
+{
+  int i, j;
+  int pr, pw;
+
+#if defined(QPS_DEBUG)
+  p->priv_fp = fopen(QPS_DEBUG_FILE, "a");
+  assert(p->priv_fp);
+#endif
+
+#if (QPS_DEBUG > 5)
+  fprintf(p->priv_fp, "### n=%d gn=%d ln=%d\n", p->num_cells, p->cog_num,
+	  p->loop_num);
+  pr = 0;
+  fprintf(p->priv_fp, "### (c w) values\n");
+  for (i = 0; i < p->num_cells; i++) {
+    fprintf(p->priv_fp, "net %d: ", i);
+    while (p->connect[pr] >= 0) {
+      fprintf(p->priv_fp, "(%d %f) ", p->connect[pr], p->edge_weight[pr]);
+      pr++;
+    }
+    fprintf(p->priv_fp, "(-1 -1.0)\n");
+    pr++;
+  }
+  fprintf(p->priv_fp, "### (x y f) values\n");
+  for (i = 0; i < p->num_cells; i++) {
+    fprintf(p->priv_fp, "cell %d: (%f %f %d)\n", i, p->x[i], p->y[i],
+	    p->fixed[i]);
+  }
+#if 0
+  if (p->cog_num) {
+    fprintf(p->priv_fp, "### ga values\n");
+    for (i = 0; i < p->num_cells; i++) {
+      fprintf(p->priv_fp, "cell %d: (%f)\n", i, p->area[i]);
+    }
+  }
+  pr = 0;
+  fprintf(p->priv_fp, "### gl values\n");
+  for (i = 0; i < p->cog_num; i++) {
+    fprintf(p->priv_fp, "cog %d: ", i);
+    while (p->cog_list[pr] >= 0) {
+      fprintf(p->priv_fp, "%d ", p->cog_list[pr]);
+      pr++;
+    }
+    fprintf(p->priv_fp, "-1\n");
+    pr++;
+  }
+  fprintf(p->priv_fp, "### (gx gy) values\n");
+  for (i = 0; i < p->cog_num; i++) {
+    fprintf(p->priv_fp, "cog %d: (%f %f)\n", i, p->cog_x[i], p->cog_y[i]);
+  }
+#endif
+#endif /* QPS_DEBUG */
+
+  p->priv_ii = (int *)malloc(p->num_cells * sizeof(int));
+  assert(p->priv_ii);
+
+  p->max_enable = 0;
+
+  p->priv_fopt = 0.0;
+
+  /* canonify c and w */
+  pr = pw = 0;
+  for (i = 0; i < p->num_cells; i++) {
+    while ((j = p->connect[pr]) >= 0) {
+      if (j > i) {
+	pw++;
+      }
+      pr++;
+    }
+    pw++;
+    pr++;
+  }
+  p->priv_cc = (int *)malloc(pw * sizeof(int));
+  assert(p->priv_cc);
+  p->priv_cr = (int *)malloc(p->num_cells * sizeof(int));
+  assert(p->priv_cr);
+  p->priv_cw = (qps_float_t*)malloc(pw * sizeof(qps_float_t));
+  assert(p->priv_cw);
+  p->priv_ct = (qps_float_t*)malloc(pw * sizeof(qps_float_t));
+  assert(p->priv_ct);
+  p->priv_cm = pw;
+  pr = pw = 0;
+  for (i = 0; i < p->num_cells; i++) {
+    p->priv_cr[i] = pw;
+    while ((j = p->connect[pr]) >= 0) {
+      if (j > i) {
+	p->priv_cc[pw] = p->connect[pr];
+	p->priv_ct[pw] = p->edge_weight[pr];
+	pw++;
+      }
+      pr++;
+    }
+    p->priv_cc[pw] = -1;
+    p->priv_ct[pw] = -1.0;
+    pw++;
+    pr++;
+  }
+  assert(pw == p->priv_cm);
+
+  /* temp arrays for function eval */
+  p->priv_tp = (qps_float_t *) malloc(4 * p->num_cells * sizeof(qps_float_t));
+  assert(p->priv_tp);
+  p->priv_tp2 = p->priv_tp + 2 * p->num_cells;
+}
+
+/**********************************************************************/
+
+static qps_float_t
+qps_estopt(qps_problem_t * p)
+{
+  int i, j, cell;
+  qps_float_t r;
+  qps_float_t *t1, *t2;
+  qps_float_t t;
+
+  if (p->max_enable) {
+    r = 0.0;
+    t1 = (qps_float_t *) malloc(2 * p->num_cells * sizeof(qps_float_t));
+#if (QPS_DEBUG > 0)
+    assert(t1);
+#endif
+    for (i = 2 * p->num_cells; i--;) {
+      t1[i] = 0.0;
+    }
+    j = 0;
+    for (i = 0; i < p->cog_num; i++) {
+      while ((cell = p->cog_list[j]) >= 0) {
+	t1[cell * 2] = p->cog_x[i];
+	t1[cell * 2 + 1] = p->cog_y[i];
+	j++;
+      }
+      j++;
+    }
+    t2 = p->priv_tp;
+    p->priv_tp = t1;
+    r = qps_func(p);
+    p->priv_tp = t2;
+    free(t1);
+    t = (p->max_x * p->max_x + p->max_y * p->max_y);
+    t *= p->num_cells;
+    for (i = p->num_cells; i--;) {
+      if (p->fixed[i]) {
+	r += t;
+      }
+    }
+  }
+  else {
+    r = p->priv_f;
+  }
+  if (p->loop_num) {
+    /* FIXME hacky */
+    r *= 8.0;
+  }
+  return r;
+}
+
+/**********************************************************************/
+
+static void
+qps_solve_inner(qps_problem_t * p)
+{
+  int i;
+  qps_float_t t;
+  qps_float_t z;
+  qps_float_t pm1, pm2, tp;
+  qps_float_t *tw;
+#if defined(QPS_HOIST)
+  int j, k;
+  qps_float_t jx, jy, kx, ky, sx, sy, tx, ty;
+  int pr, st;
+#endif
+
+  tw = p->priv_cw;
+#if defined(QPS_HOIST)
+  if (!p->loop_num) {
+    p->priv_cw = p->priv_ct;
+  }
+  else {
+    for(i=p->priv_cm; i--;) {
+      p->priv_cw[i] = p->priv_ct[i];
+    }
+    /* augment with loop penalties */
+    pr = 0;
+    for (i = 0; i < p->loop_num; i++) {
+      while ((j = p->priv_la[pr++]) != -1) {
+	if (j >= 0) {
+	  p->priv_cw[j] += p->loop_penalty[i];
+	}
+      }
+      pr++;
+    }
+  }
+#else /* !QPS_HOIST */
+  p->priv_cw = p->priv_ct;
+#endif /* QPS_HOIST */
+
+  qps_cgmin(p);
+
+  if (p->max_enable || p->loop_num) {
+    if (p->max_enable == 1 || (p->loop_num && p->loop_k == 0)) {
+      p->priv_eps = 2.0;
+      p->priv_fmax = p->priv_f;
+      p->priv_fprev = p->priv_f;
+      p->priv_fopt = qps_estopt(p);
+      p->priv_pn = 0;
+      p->loop_fail = 0;
+    }
+    else {
+      if (p->priv_f < p->priv_fprev &&
+	  (p->priv_fprev - p->priv_f) >
+	  QPS_DEC_CHANGE * fabs(p->priv_fprev)) {
+	if (p->priv_pn++ >= QPS_STEPSIZE_RETRIES) {
+	  p->priv_eps /= 2.0;
+	  p->priv_pn = 0;
+	}
+      }
+      p->priv_fprev = p->priv_f;
+      if (p->priv_fmax < p->priv_f) {
+	p->priv_fmax = p->priv_f;
+      }
+      if (p->priv_f >= p->priv_fopt) {
+	p->priv_fopt = p->priv_fmax * 2.0;
+	p->loop_fail |= 2;
+#if (QPS_DEBUG > 0)
+	fprintf(p->priv_fp, "### warning: changing fopt\n");
+#endif
+      }
+    }
+#if (QPS_DEBUG > 0)
+    fprintf(p->priv_fp, "### max_stat %.2e %.2e %.2e %.2e\n",
+	    p->priv_f, p->priv_eps, p->priv_fmax, p->priv_fopt);
+    fflush(p->priv_fp);
+#endif
+  }
+
+  p->loop_done = 1;
+  if (p->loop_num) {
+#if (QPS_DEBUG > 0)
+    fprintf(p->priv_fp, "### begin_update %d\n", p->loop_k);
+#endif
+    p->loop_k++;
+
+#if defined(QPS_HOIST)
+    /* calc loop penalties */
+    pr = 0;
+    for (i = 0; i < p->loop_num; i++) {
+      t = 0.0;
+      j = st = p->loop_list[pr++];
+      jx = sx = p->priv_tp[j * 2];
+      jy = sy = p->priv_tp[j * 2 + 1];
+      while ((k = p->loop_list[pr]) >= 0) {
+	kx = p->priv_tp[k * 2];
+	ky = p->priv_tp[k * 2 + 1];
+	tx = jx - kx;
+	ty = jy - ky;
+	t += tx * tx + ty * ty;
+	j = k;
+	jx = kx;
+	jy = ky;
+	pr++;
+      }
+      tx = jx - sx;
+      ty = jy - sy;
+      t += tx * tx + ty * ty;
+      p->priv_lt[i] = t - p->loop_max[i];
+      pr++;
+    }
+#endif /* QPS_HOIST */
+
+    /* check KKT conditions */
+#if (QPS_DEBUG > 1)
+    for (i = p->loop_num; i--;) {
+      if (p->loop_penalty[i] != 0.0) {
+	fprintf(p->priv_fp, "### penalty %d %.2e\n", i, p->loop_penalty[i]);
+      }
+    }
+#endif
+    t = 0.0;
+    for (i = p->loop_num; i--;) {
+      if (p->priv_lt[i] > 0.0 || p->loop_penalty[i] > 0.0) {
+	t += p->priv_lt[i] * p->priv_lt[i];
+      }
+      if (fabs(p->priv_lt[i]) < QPS_LOOP_TOL) {
+#if (QPS_DEBUG > 4)
+	fprintf(p->priv_fp, "### skip %d %f\n", i, p->priv_lt[i]);
+#endif
+	continue;
+      }
+      z = QPS_LOOP_TOL * p->loop_max[i];
+      if (p->priv_lt[i] > z || (p->loop_k < QPS_RELAX_ITER &&
+				p->loop_penalty[i] * p->priv_lt[i] < -z)) {
+	p->loop_done = 0;
+#if (QPS_DEBUG > 1)
+	fprintf(p->priv_fp, "### not_done %d %f %f %f %f\n", i,
+		p->priv_lt[i], z, p->loop_max[i], p->loop_penalty[i]);
+#endif
+      }
+#if (QPS_DEBUG > 5)
+      else {
+	fprintf(p->priv_fp, "### done %d %f %f %f %f\n", i,
+		p->priv_lt[i], z, p->loop_max[i], p->loop_penalty[i]);
+      }
+#endif
+    }
+    /* update penalties */
+    if (!p->loop_done) {
+      t = p->priv_eps * (p->priv_fopt - p->priv_f) / t;
+      tp = 0.0;
+      for (i = p->loop_num; i--;) {
+	pm1 = p->loop_penalty[i];
+#if (QPS_DEBUG > 5)
+	fprintf(p->priv_fp, "### update %d %.2e %.2e %.2e %.2e %.2e\n", i,
+		t, p->priv_lt[i], t * p->priv_lt[i], pm1, p->loop_max[i]);
+#endif
+	p->loop_penalty[i] += t * p->priv_lt[i];
+	if (p->loop_penalty[i] < 0.0) {
+	  p->loop_penalty[i] = 0.0;
+	}
+	pm2 = p->loop_penalty[i];
+	tp += fabs(pm1 - pm2);
+      }
+#if (QPS_DEBUG > 4)
+      fprintf(p->priv_fp, "### penalty mag %f\n", tp);
+#endif
+    }
+  }
+
+  p->max_done = 1;
+  if (p->max_enable) {
+#if (QPS_DEBUG > 4)
+    fprintf(p->priv_fp, "### begin_max_update %d\n", p->max_enable);
+#endif
+    t = 0.0;
+    for (i = p->num_cells; i--;) {
+      z = -(p->x[i]);
+      t += z * z;
+      if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER &&
+			  p->priv_mxl[i] * z < -QPS_MAX_TOL)) {
+	p->max_done = 0;
+#if (QPS_DEBUG > 4)
+	fprintf(p->priv_fp, "### nxl %d %f %f\n", i, z, p->priv_mxl[i]);
+#endif
+      }
+      z = (p->x[i] - p->max_x);
+      t += z * z;
+      if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER &&
+			  p->priv_mxh[i] * z < -QPS_MAX_TOL)) {
+	p->max_done = 0;
+#if (QPS_DEBUG > 4)
+	fprintf(p->priv_fp, "### nxh %d %f %f\n", i, z, p->priv_mxh[i]);
+#endif
+      }
+      z = -(p->y[i]);
+      t += z * z;
+      if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER &&
+			  p->priv_myl[i] * z < -QPS_MAX_TOL)) {
+	p->max_done = 0;
+#if (QPS_DEBUG > 4)
+	fprintf(p->priv_fp, "### nyl %d %f %f\n", i, z, p->priv_myl[i]);
+#endif
+      }
+      z = (p->y[i] - p->max_y);
+      t += z * z;
+      if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER &&
+			  p->priv_myh[i] * z < -QPS_MAX_TOL)) {
+	p->max_done = 0;
+#if (QPS_DEBUG > 4)
+	fprintf(p->priv_fp, "### nyh %d %f %f\n", i, z, p->priv_myh[i]);
+#endif
+      }
+    }
+#if (QPS_DEBUG > 4)
+    fprintf(p->priv_fp, "### max_done %d %f\n", p->max_done, t);
+#endif
+    if (!p->max_done) {
+      t = p->priv_eps * (p->priv_fopt - p->priv_f) / t;
+      tp = 0.0;
+      for (i = p->num_cells; i--;) {
+	z = -(p->x[i]);
+	pm1 = p->priv_mxl[i];
+	p->priv_mxl[i] += t * z;
+	if (p->priv_mxl[i] < 0.0) {
+	  p->priv_mxl[i] = 0.0;
+	}
+	pm2 = p->priv_mxl[i];
+	tp += fabs(pm1 - pm2);
+
+	z = (p->x[i] - p->max_x);
+	pm1 = p->priv_mxh[i];
+	p->priv_mxh[i] += t * z;
+	if (p->priv_mxh[i] < 0.0) {
+	  p->priv_mxh[i] = 0.0;
+	}
+	pm2 = p->priv_mxh[i];
+	tp += fabs(pm1 - pm2);
+
+	z = -(p->y[i]);
+	pm1 = p->priv_myl[i];
+	p->priv_myl[i] += t * z;
+	if (p->priv_myl[i] < 0.0) {
+	  p->priv_myl[i] = 0.0;
+	}
+	pm2 = p->priv_myl[i];
+	tp += fabs(pm1 - pm2);
+
+	z = (p->y[i] - p->max_y);
+	pm1 = p->priv_myh[i];
+	p->priv_myh[i] += t * z;
+	if (p->priv_myh[i] < 0.0) {
+	  p->priv_myh[i] = 0.0;
+	}
+	pm2 = p->priv_myh[i];
+	tp += fabs(pm1 - pm2);
+      }
+    }
+#if (QPS_DEBUG > 4)
+    for (i = p->num_cells; i--;) {
+      fprintf(p->priv_fp, "### max_penalty %d %f %f %f %f\n", i,
+	      p->priv_mxl[i], p->priv_mxh[i], p->priv_myl[i], p->priv_myh[i]);
+    }
+#endif
+    p->max_enable++;
+  }
+
+  if (p->loop_k >= QPS_MAX_ITER || p->priv_eps < QPS_MINSTEP) {
+    p->loop_fail |= 1;
+  }
+
+  if (p->loop_fail) {
+    p->loop_done = 1;
+  }
+
+  p->priv_cw = tw;
+}
+
+/**********************************************************************/
+
+void
+qps_solve(qps_problem_t * p)
+{
+  int i, j;
+  int pr, pw;
+  qps_float_t bk;
+  int tk;
+
+#if defined(QPS_PRECON)
+  int c;
+  qps_float_t t;
+#endif
+
+#if defined(QPS_HOIST)
+  int k;
+  int st;
+  int m1, m2;
+#endif
+
+  if (p->max_enable) {
+    p->priv_mxl = (qps_float_t *)
+	malloc(4 * p->num_cells * sizeof(qps_float_t));
+    assert(p->priv_mxl);
+    p->priv_mxh = p->priv_mxl + p->num_cells;
+    p->priv_myl = p->priv_mxl + 2 * p->num_cells;
+    p->priv_myh = p->priv_mxl + 3 * p->num_cells;
+    for (i = 4 * p->num_cells; i--;) {
+      p->priv_mxl[i] = 0.0;
+    }
+  }
+
+  /* flag fixed cells with -1 */
+  for (i = p->num_cells; i--;) {
+    p->priv_ii[i] = (p->fixed[i]) ? (-1) : (0);
+  }
+
+  /* read gl and set up dependent variables */
+  if (p->cog_num) {
+    p->priv_gt = (int *)malloc(p->cog_num * sizeof(int));
+    assert(p->priv_gt);
+    p->priv_gm = (qps_float_t*)malloc(p->cog_num * sizeof(qps_float_t));
+    assert(p->priv_gm);
+    pr = 0;
+    for (i = 0; i < p->cog_num; i++) {
+      tk = -1;
+      bk = -1.0;
+      pw = pr;
+      while ((j = p->cog_list[pr++]) >= 0) {
+	if (!p->fixed[j]) {
+	  /* use largest entry for numerical stability; see Gordian paper */
+	  if (p->area[j] > bk) {
+	    tk = j;
+	    bk = p->area[j];
+	  }
+	}
+      }
+      assert(bk > 0.0);
+      /* dependent variables have index=(-2-COG_constraint) */
+      p->priv_ii[tk] = -2 - i;
+      p->priv_gt[i] = pw;
+      p->priv_gm[i] = bk;
+    }
+    p->priv_gw = (qps_float_t*)malloc(pr * sizeof(qps_float_t));
+    assert(p->priv_gw);
+    pr = 0;
+    for (i = 0; i < p->cog_num; i++) {
+      while ((j = p->cog_list[pr]) >= 0) {
+	p->priv_gw[pr] = p->area[j] / p->priv_gm[i];
+	pr++;
+      }
+      p->priv_gw[pr] = -1.0;
+      pr++;
+    }
+  }
+
+  /* set up indexes from independent floating cells to variables */
+  p->priv_n = 0;
+  for (i = p->num_cells; i--;) {
+    if (!p->priv_ii[i]) {
+      p->priv_ii[i] = 2 * (p->priv_n++);
+    }
+  }
+  p->priv_n *= 2;
+
+#if (QPS_DEBUG > 5)
+  for (i = 0; i < p->num_cells; i++) {
+    fprintf(p->priv_fp, "### ii %d %d\n", i, p->priv_ii[i]);
+  }
+#endif
+
+#if defined(QPS_PRECON)
+  p->priv_pcg = (qps_float_t *) malloc(p->num_cells * sizeof(qps_float_t));
+  assert(p->priv_pcg);
+  p->priv_pcgt = (qps_float_t *) malloc(p->priv_n * sizeof(qps_float_t));
+  assert(p->priv_pcgt);
+  for (i = p->num_cells; i--;) {
+    p->priv_pcg[i] = 0.0;
+  }
+  pr = 0;
+  for (i = 0; i < p->num_cells; i++) {
+    while ((c = p->priv_cc[pr]) >= 0) {
+      t = p->priv_ct[pr];
+      p->priv_pcg[i] += t;
+      p->priv_pcg[c] += t;
+      pr++;
+    }
+    pr++;
+  }
+  pr = 0;
+  for (i = 0; i < p->loop_num; i++) {
+    t = 2.0 * p->loop_penalty[i];
+    while ((c = p->loop_list[pr++]) >= 0) {
+      p->priv_pcg[c] += t;
+    }
+    pr++;
+  }
+#if (QPS_DEBUG > 6)
+  for (i = p->num_cells; i--;) {
+    fprintf(p->priv_fp, "### precon %d %.2e\n", i, p->priv_pcg[i]);
+  }
+#endif
+  for (i = p->priv_n; i--;) {
+      p->priv_pcgt[i] = 0.0;
+  }
+  for (i = 0; i < p->num_cells; i++) {
+    c = p->priv_ii[i];
+    if (c >= 0) {
+      t = p->priv_pcg[i];
+      p->priv_pcgt[c] += t;
+      p->priv_pcgt[c + 1] += t;
+    }
+#if 0
+    else if (c < -1) {
+      pr = p->priv_gt[-(c+2)];
+      while ((j = p->cog_list[pr++]) >= 0) {
+	ji = p->priv_ii[j];
+	if (ji >= 0) {
+	  w = p->area[j] / p->area[i];
+	  t = w * w * p->priv_pcg[i];
+	  p->priv_pcgt[ji] += t;
+	  p->priv_pcgt[ji + 1] += t;
+	}
+      }
+    }
+#endif
+  }
+  for (i = 0; i < p->priv_n; i++) {
+    t = p->priv_pcgt[i];
+    if (fabs(t) < QPS_PRECON_EPS || fabs(t) > 1.0/QPS_PRECON_EPS) {
+      p->priv_pcgt[i] = 1.0;
+    }
+    else {
+      p->priv_pcgt[i] = 1.0 / p->priv_pcgt[i];
+    }
+  }
+#endif
+
+  /* allocate variable storage */
+  p->priv_cp = (qps_float_t *) malloc(4 * p->priv_n * sizeof(qps_float_t));
+  assert(p->priv_cp);
+
+  /* temp arrays for cg */
+  p->priv_g = p->priv_cp + p->priv_n;
+  p->priv_h = p->priv_cp + 2 * p->priv_n;
+  p->priv_xi = p->priv_cp + 3 * p->priv_n;
+
+  /* set values */
+  for (i = p->num_cells; i--;) {
+    if (p->priv_ii[i] >= 0) {
+      p->priv_cp[p->priv_ii[i]] = p->x[i];
+      p->priv_cp[p->priv_ii[i] + 1] = p->y[i];
+    }
+  }
+
+  if (p->loop_num) {
+    p->priv_lt = (qps_float_t *) malloc(p->loop_num * sizeof(qps_float_t));
+    assert(p->priv_lt);
+#if defined(QPS_HOIST)
+    pr = 0;
+    for (i=p->loop_num; i--;) {
+      while (p->loop_list[pr++] >= 0) {
+      }
+      pr++;
+    }
+    p->priv_lm = pr;
+    p->priv_la = (int *) malloc(pr * sizeof(int));
+    assert(p->priv_la);
+    pr = 0;
+    for (i = 0; i < p->loop_num; i++) {
+      j = st = p->loop_list[pr++];
+      while ((k = p->loop_list[pr]) >= 0) {
+	if (j > k) {
+	  m1 = k;
+	  m2 = j;
+	}
+	else {
+	  assert(k > j);
+	  m1 = j;
+	  m2 = k;
+	}
+	pw = p->priv_cr[m1];
+	while (p->priv_cc[pw] != m2) {
+/*	  assert(p->priv_cc[pw] >= 0); */
+	  if (p->priv_cc[pw] < 0) {
+	    pw = -2;
+	    break;
+	  }
+	  pw++;
+	}
+	p->priv_la[pr-1] = pw;
+	j = k;
+	pr++;
+      }
+      if (j > st) {
+	m1 = st;
+	m2 = j;
+      }
+      else {
+	assert(st > j);
+	m1 = j;
+	m2 = st;
+      }
+      pw = p->priv_cr[m1];
+      while (p->priv_cc[pw] != m2) {
+/*	assert(p->priv_cc[pw] >= 0); */
+	if (p->priv_cc[pw] < 0) {
+	  pw = -2;
+	  break;
+	}
+	pw++;
+      }
+      p->priv_la[pr-1] = pw;
+      p->priv_la[pr] = -1;
+      pr++;
+    }
+#endif /* QPS_HOIST */
+  }
+
+  do {
+    qps_solve_inner(p);
+  } while (!p->loop_done || !p->max_done);
+
+  /* retrieve values */
+  /* qps_settp() should have already been called at this point */
+  for (i = p->num_cells; i--;) {
+    p->x[i] = p->priv_tp[i * 2];
+    p->y[i] = p->priv_tp[i * 2 + 1];
+  }
+#if (QPS_DEBUG > 5)
+  for (i = p->num_cells; i--;) {
+    fprintf(p->priv_fp, "### cloc %d %f %f\n", i, p->x[i], p->y[i]);
+  }
+#endif
+
+  free(p->priv_cp);
+  if (p->max_enable) {
+    free(p->priv_mxl);
+  }
+  if (p->cog_num) {
+    free(p->priv_gt);
+    free(p->priv_gm);
+    free(p->priv_gw);
+  }
+  if(p->loop_num) {
+    free(p->priv_lt);
+#if defined(QPS_HOIST)
+    free(p->priv_la);
+#endif
+  }
+
+#if defined(QPS_PRECON)
+  free(p->priv_pcg);
+  free(p->priv_pcgt);
+#endif
+}
+
+/**********************************************************************/
+
+void
+qps_clean(qps_problem_t * p)
+{
+  free(p->priv_tp);
+  free(p->priv_ii);
+  free(p->priv_cc);
+  free(p->priv_cr);
+  free(p->priv_cw);
+  free(p->priv_ct);
+
+#if defined(QPS_DEBUG)
+  fclose(p->priv_fp);
+#endif /* QPS_DEBUG */
+}
+
+/**********************************************************************/
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/phys/place/place_qpsolver.h b/abc-build/src/phys/place/place_qpsolver.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/place_qpsolver.h
@@ -0,0 +1,148 @@
+/*===================================================================*/
+//  
+//     place_qpsolver.h
+//
+//		Philip Chong
+//              pchong@cadence.com
+//
+/*===================================================================*/
+
+#if !defined(_QPS_H)
+#define ABC__phys__place__place_qpsolver_h
+
+
+#include <stdio.h>
+
+ABC_NAMESPACE_HEADER_START
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif				/* __cplusplus */
+
+  typedef float qps_float_t;
+
+  typedef struct qps_problem {
+
+    /* Basic stuff */
+    int num_cells;		/* Total number of cells (both fixed and
+				   floating) to be placed. */
+    int *connect;		/* Connectivity array.  Must contain at least 
+				   num_cells elements with value -1. The
+				   entries which precede the first element
+				   with value -1 are the indices of the cells 
+				   which connect to cell 0; the entries
+				   which lie between the first and second
+				   elements with value -1 are the indices of
+				   the cells which connect to cell 1; etc.
+				   Example: cells 0 and 1 are connected
+				   together, and 1 and 2 are connected as
+				   well.  *connect = { 1, -1, 0, 2, -1, 1, -1
+				   }. */
+    qps_float_t *edge_weight;	/* Same structure as connectivity array, but
+				   giving the weights assigned to each edge
+				   instead. */
+    qps_float_t *x;		/* num_cells element array which contains the
+				   x-coordinates of the cells. This is used
+				   for the initial values in the iterative
+				   solution of floating cells, and for the
+				   fixed location of fixed cells. */
+    qps_float_t *y;		/* num_cells element array of
+				   y-coordinates. */
+    int *fixed;			/* num_cells element array with value 1 if
+				   corresponding cell is fixed, 0 if
+				   floating. */
+    qps_float_t f;		/* return value for sum-of-square
+				   wirelengths. */
+
+    /* COG stuff */
+    int cog_num;		/* Number of COG constraints. */
+    int *cog_list;		/* Array indicating for each COG constraint
+				   which cells belong to that constraint.
+				   Format is similar to c array: there must
+				   be at least cog_num elements with value
+				   -1.  The entries of cog_list preceding the 
+				   first -1 element are the indices of the
+				   cells which belong to the first COG
+				   constraint; etc.  Example: cells 0 and 1
+				   belong to one COG constraint, cells 4 and
+				   5 belong to another.  *cog_list= { 0, 1,
+				   -1, 4, 5, -1 }. */
+    qps_float_t *cog_x;		/* cog_num element array whose values are the
+				   x-coordinates for the corresponding COG
+				   constraints. */
+    qps_float_t *cog_y;		/* cog_num element array whose values are the
+				   y-coordinates for the corresponding COG
+				   constraints. */
+    qps_float_t *area;     	/* num_cells element array whose values are
+				   the areas for the corresponding cells;
+				   only useful with COG constraints. */
+
+    /* Loop constraint stuff */
+    int loop_num;		/* Number of loop constraints. */
+    int *loop_list;		/* Array with list of cells for each loop
+				   constraint. Format is similar to cog_list. 
+				 */
+    qps_float_t *loop_max;	/* loop_num element array indicating maximum
+				   distance for each loop. */
+    qps_float_t *loop_penalty;	/* loop_num element array indicating penalty
+				   for each loop. */
+    int loop_k;			/* Current iteration for loop optimization. */
+    int loop_done;		/* Done flag for loop optimization. */
+    int loop_fail;
+
+    /* max_x/max_y stuff */
+    qps_float_t max_x;		/* max x location;  only used in
+				   constrained optimization. */
+    qps_float_t max_y;		/* max y location;  only used in
+				   constrained optimization. */
+    int max_enable;		/* Set to 1 after qps_init() to enable
+				   max_x/max_y. */
+    int max_done;		/* Done flag for max optimization. */
+
+    /* Private stuff */
+    int *priv_ii;
+    int *priv_cc, *priv_cr;
+    qps_float_t *priv_cw, *priv_ct;
+    int priv_cm;
+    int *priv_gt;
+    int *priv_la;
+    int priv_lm;
+    qps_float_t *priv_gm, *priv_gw;
+    qps_float_t *priv_g, *priv_h, *priv_xi;
+    qps_float_t *priv_tp, *priv_tp2;
+    int priv_n;
+    qps_float_t *priv_cp;
+    qps_float_t priv_f;
+    qps_float_t *priv_lt;
+    qps_float_t *priv_pcg, *priv_pcgt;
+    qps_float_t priv_fmax;
+    qps_float_t priv_fprev;
+    qps_float_t priv_fopt;
+    qps_float_t priv_eps;
+    int priv_pn;
+    qps_float_t *priv_mxl, *priv_mxh, *priv_myl, *priv_myh;
+    int priv_ik;
+    FILE *priv_fp;
+
+  } qps_problem_t;
+
+  /* call qps_init() as soon as the qps_problem_t has been set up */
+  /* this initializes some private data structures */
+  extern void qps_init(qps_problem_t *);
+
+  /* call qps_solve() to solve the given qp problem */
+  extern void qps_solve(qps_problem_t *);
+
+  /* call qps_clean() when finished with the qps_problem_t */
+  /* this discards the private data structures assigned by qps_init() */
+  extern void qps_clean(qps_problem_t *);
+
+#if defined(__cplusplus)
+}
+#endif				/* __cplusplus */
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif				/* _QPS_H */
diff --git a/abc-build/src/phys/place/place_test.c b/abc-build/src/phys/place/place_test.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/phys/place/place_test.c
@@ -0,0 +1,365 @@
+/*===================================================================*/
+//  
+//     place_test.c
+//
+//		Aaron P. Hurst, 2003-2007
+//              ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "place_base.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+
+// --------------------------------------------------------------------
+// Hash type/functions
+//
+// --------------------------------------------------------------------
+
+struct hash_element {
+  ConcreteCell        *obj;
+  struct hash_element *next;
+} hash_element;
+
+int hash_string(int hash_max, const char *str) {
+  unsigned int hash = 0;
+  int p;
+  for(p = 0; p<strlen(str); p++)
+    hash += str[p]*p;
+  return hash % hash_max;
+}
+
+void hash_add(struct hash_element **hash, int hash_max,
+              ConcreteCell *cell) {
+  int key = hash_string(hash_max, cell->m_label);
+  // printf("adding %s key = %d\n", cell->m_label, key);
+  struct hash_element *element = malloc(sizeof(struct hash_element));
+  assert(element);
+  element->obj = cell;
+  element->next = hash[key];
+  hash[key] = element;
+}
+
+ConcreteCell *hash_find(struct hash_element **hash, int hash_max, const char *str) {
+  int key = hash_string(hash_max, str);
+  // printf("looking for %s key = %d\n", str, key);
+  struct hash_element *next = hash[key];
+  while(next) {
+    if (!strcmp(str, next->obj->m_label))
+      return next->obj;
+    next = next->next;
+  }
+  return 0;
+}
+
+// --------------------------------------------------------------------
+// Global variables
+//
+// --------------------------------------------------------------------
+
+struct hash_element **hash_cellname;
+
+int numCells = 0, numNets = 0;
+
+AbstractCell *abstractCells;
+ConcreteCell *concreteCells;
+ConcreteNet  *concreteNets;
+
+// --------------------------------------------------------------------
+// Function implementations
+//
+// --------------------------------------------------------------------
+
+void readBookshelfNets(char *filename) {
+  char *tok;
+  char buf[1024];
+  const char *DELIMITERS = " \n\t:";
+  int id = 0;
+  int t;
+  ConcreteCell *cell;
+
+  FILE *netsFile = fopen(filename, "r");
+  if (!netsFile) {
+    printf("ERROR: Could not open .nets file\n");
+    exit(1);
+  }
+
+  // line 1 : version
+  while (fgets(buf, 1024, netsFile) && (buf[0] == '\n' || buf[0] == '#'));
+
+  // line 2 : number of nets
+  while (fgets(buf, 1024, netsFile) && (buf[0] == '\n' || buf[0] == '#'));
+  tok = strtok(buf, DELIMITERS);
+  tok = strtok(NULL, DELIMITERS);
+  numNets = atoi(tok);
+  printf("READ-20 : number of nets = %d\n", numNets);
+  concreteNets = malloc(sizeof(ConcreteNet)*numNets);
+
+  // line 3 : number of pins
+  while (fgets(buf, 1024, netsFile) && (buf[0] == '\n' || buf[0] == '#'));
+
+  // line XXX : net definitions
+  while(fgets(buf, 1024, netsFile)) {
+    if (buf[0] == '\n' || buf[0] == '#') continue;
+
+    concreteNets[id].m_id = id;
+    concreteNets[id].m_weight = 1.0;
+
+    tok = strtok(buf, DELIMITERS);
+    if (!!strcmp(tok, "NetDegree")) {
+      printf("%s\n",buf);
+      printf("ERROR: Incorrect format in .nets file\n");
+      exit(1);
+    }
+
+    tok = strtok(NULL, DELIMITERS);
+    concreteNets[id].m_numTerms = atoi(tok);
+    if (concreteNets[id].m_numTerms < 0 ||
+        concreteNets[id].m_numTerms > 100000) {
+      printf("ERROR: Bad net degree\n");
+      exit(1); 
+    }
+    concreteNets[id].m_terms = malloc(sizeof(ConcreteCell*)*
+         concreteNets[id].m_numTerms);
+
+    // read terms
+    t = 0;
+    while(t < concreteNets[id].m_numTerms &&
+          fgets(buf, 1024, netsFile)) {
+      if (buf[0] == '\n' || buf[0] == '#') continue;
+      
+      // cell name
+      tok = strtok(buf, DELIMITERS);
+      cell = hash_find(hash_cellname, numCells, tok);
+      if (!cell) {
+        printf("ERROR: Could not find cell %s in .nodes file\n", tok);
+        exit(1);
+      }
+      concreteNets[id].m_terms[t] = cell;
+      t++;
+    }
+
+    // add!
+    addConcreteNet(&(concreteNets[id]));
+
+    id++;
+  }
+
+  fclose(netsFile);
+}
+
+void readBookshelfNodes(char *filename) {
+  char *tok;
+  char buf[1024];
+  const char *DELIMITERS = " \n\t:";
+  int id = 0;
+
+  FILE *nodesFile = fopen(filename, "r");
+  if (!nodesFile) {
+    printf("ERROR: Could not open .nodes file\n");
+    exit(1);
+  }
+
+  // line 1 : version
+  while (fgets(buf, 1024, nodesFile) && (buf[0] == '\n' || buf[0] == '#'));
+
+  // line 2 : num nodes
+  while (fgets(buf, 1024, nodesFile) && (buf[0] == '\n' || buf[0] == '#'));
+  tok = strtok(buf, DELIMITERS);
+  tok = strtok(NULL, DELIMITERS);
+  numCells = atoi(tok);
+  printf("READ-10 : number of cells = %d\n", numCells);
+  concreteCells = malloc(sizeof(ConcreteCell)*numCells);
+  abstractCells = malloc(sizeof(AbstractCell)*numCells);
+  hash_cellname = calloc(numCells, sizeof(struct hash_element*));
+
+  // line 3 : num terminals
+  while (fgets(buf, 1024, nodesFile) && (buf[0] == '\n' || buf[0] == '#'));
+
+  // line XXX : cell definitions
+  while(fgets(buf, 1024, nodesFile)) {
+    if (buf[0] == '\n' || buf[0] == '#') continue;
+
+    tok = strtok(buf, DELIMITERS);
+    concreteCells[id].m_id = id;;
+    
+    // label
+    concreteCells[id].m_parent = &(abstractCells[id]);
+    concreteCells[id].m_label = malloc(sizeof(char)*strlen(tok)+1);
+    strcpy(concreteCells[id].m_label, tok);
+    abstractCells[id].m_label = concreteCells[id].m_label;
+    hash_add(hash_cellname, numCells, 
+             &(concreteCells[id]));
+
+    // dimensions
+    tok = strtok(NULL, DELIMITERS);
+    abstractCells[id].m_width = atof(tok);
+    tok = strtok(NULL, DELIMITERS);
+    abstractCells[id].m_height = atof(tok);
+    tok = strtok(NULL, DELIMITERS);
+    // terminal
+    abstractCells[id].m_pad = tok && !strcmp(tok, "terminal");
+
+    // add!
+    addConcreteCell(&(concreteCells[id]));
+
+    // DEBUG
+    /*
+    printf("\"%s\" : %f x %f\n", concreteCells[id].m_label,
+           abstractCells[id].m_width,
+           abstractCells[id].m_height);
+    */
+    id++;
+  }
+
+  fclose(nodesFile);
+}
+
+void readBookshelfPlacement(char *filename) {
+  char *tok;
+  char buf[1024];
+  const char *DELIMITERS = " \n\t:";
+  ConcreteCell *cell;
+
+  FILE *plFile = fopen(filename, "r");
+  FILE *netsFile = fopen(filename, "r");
+  if (!plFile) {
+    printf("ERROR: Could not open .pl file\n");
+    exit(1);
+  }
+  if (!netsFile) {
+    printf("ERROR: Could not open .nets file\n");
+    exit(1);
+  }
+
+  // line 1 : version
+  while (fgets(buf, 1024, plFile) && (buf[0] == '\n' || buf[0] == '#'));
+
+  // line XXX : placement definitions
+  while(fgets(buf, 1024, plFile)) {
+    if (buf[0] == '\n' || buf[0] == '#') continue;
+
+    tok = strtok(buf, DELIMITERS);
+
+    // cell name
+    cell = hash_find(hash_cellname, numCells, tok);
+    if (!cell) {
+      printf("ERROR: Could not find cell %s in .nodes file\n",tok);
+      exit(1);
+    }
+
+    // position
+    tok = strtok(NULL, DELIMITERS);
+    cell->m_x = atof(tok);
+    tok = strtok(NULL, DELIMITERS);
+    cell->m_y = atof(tok);
+
+    // hfixed
+    cell->m_fixed = strtok(NULL, DELIMITERS) && 
+      (tok = strtok(NULL, DELIMITERS)) &&
+      !strcmp(tok, "\\FIXED");
+  }
+  
+  fclose(plFile);
+}
+
+void writeBookshelfPlacement(char *filename) {
+  int c = 0;
+
+  FILE *plFile = fopen(filename, "w");
+  if (!plFile) {
+    printf("ERROR: Could not open .pl file\n");
+    exit(1);
+  }
+
+  fprintf(plFile, "UCLA pl 1.0\n");
+  for(c=0; c<numCells; c++) {
+    fprintf(plFile, "%s %f %f : N %s\n", 
+            concreteCells[c].m_label,
+            concreteCells[c].m_x,
+            concreteCells[c].m_y,
+            (concreteCells[c].m_fixed ? "\\FIXED" : ""));
+  }
+
+  fclose(plFile);
+}
+
+// deletes all connections to a cell
+void delNetConnections(ConcreteCell *cell) {
+  int n, t, t2, count = 0;
+  ConcreteCell **old = malloc(sizeof(ConcreteCell*)*g_place_numCells);
+
+  for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n]) {
+    ConcreteNet *net = g_place_concreteNets[n];
+    count = 0;
+    for(t=0; t<net->m_numTerms; t++)
+      if (net->m_terms[t] == cell) count++;
+    if (count) {
+      memcpy(old, net->m_terms, sizeof(ConcreteCell*)*net->m_numTerms);
+      net->m_terms = realloc(net->m_terms, 
+                             sizeof(ConcreteCell*)*(net->m_numTerms-count));
+      t2 = 0;
+      for(t=0; t<net->m_numTerms; t++)
+        if (old[t] != cell) net->m_terms[t2++] = old[t];
+      net->m_numTerms -= count;
+    }
+  }
+  free(old);
+}
+
+int main(int argc, char **argv) {
+
+  if (argc != 4) {
+    printf("Usage: %s [nodes] [nets] [pl]\n", argv[0]);
+    exit(1);
+  }
+
+  readBookshelfNodes(argv[1]);
+  readBookshelfNets(argv[2]);
+  readBookshelfPlacement(argv[3]);
+
+  globalPreplace(0.8);
+  globalPlace();
+
+  // DEBUG net/cell removal/addition
+  /*
+  int i;
+  for(i=1000; i<2000; i++) {
+    delConcreteNet(g_place_concreteNets[i]);
+    delNetConnections(g_place_concreteCells[i]);
+    delConcreteCell(g_place_concreteCells[i]);
+  }
+  
+  ConcreteCell newCell[2];
+  newCell[0].m_id = g_place_numCells+1;
+  newCell[0].m_x = 1000;
+  newCell[0].m_y = 1000;
+  newCell[0].m_fixed = false;
+  newCell[0].m_parent = &(abstractCells[1000]);
+  newCell[0].m_label = " ";
+  addConcreteCell(&newCell[0]);
+  newCell[1].m_id = g_place_numCells+3;
+  newCell[1].m_x = 1000;
+  newCell[1].m_y = 1000;
+  newCell[1].m_fixed = false;
+  newCell[1].m_parent = &(abstractCells[1000]);
+  newCell[1].m_label = " ";
+  addConcreteCell(&newCell[1]);
+  */
+
+  globalIncremental();
+
+  writeBookshelfPlacement(argv[3]);
+
+  free(hash_cellname);
+
+  return 0;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/abs.c b/abc-build/src/proof/abs/abs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/abs.c
@@ -0,0 +1,52 @@
+/**CFile****************************************************************
+
+  FileName    [abs.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Abstraction package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include "abs.h"
+
+ABC_NAMESPACE_IMPL_START 
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/abs.h b/abc-build/src/proof/abs/abs.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/abs.h
@@ -0,0 +1,177 @@
+/**CFile****************************************************************
+
+  FileName    [abs.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Abstraction package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abs.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__proof_abs__Abs_h
+#define ABC__proof_abs__Abs_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "aig/gia/gia.h"
+#include "aig/gia/giaAig.h"
+#include "aig/saig/saig.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// abstraction parameters
+typedef struct Abs_Par_t_ Abs_Par_t;
+struct Abs_Par_t_
+{
+    int            nFramesMax;         // maximum frames
+    int            nFramesStart;       // starting frame 
+    int            nFramesPast;        // overlap frames
+    int            nConfLimit;         // conflict limit
+    int            nLearnedMax;        // max number of learned clauses
+    int            nLearnedStart;      // max number of learned clauses
+    int            nLearnedDelta;      // delta increase of learned clauses
+    int            nLearnedPerce;      // percentage of clauses to leave
+    int            nTimeOut;           // timeout in seconds
+    int            nRatioMin;          // stop when less than this % of object is unabstracted
+    int            nRatioMin2;         // stop when less than this % of object is unabstracted during refinement
+    int            nRatioMax;          // restart when the number of abstracted object is more than this
+    int            fUseTermVars;       // use terminal variables
+    int            fUseRollback;       // use rollback to the starting number of frames
+    int            fPropFanout;        // propagate fanout implications
+    int            fAddLayer;          // refinement strategy by adding layers
+    int            fNewRefine;         // uses new refinement heuristics
+    int            fUseSkip;           // skip proving intermediate timeframes
+    int            fUseSimple;         // use simple CNF construction
+    int            fSkipHash;          // skip hashing CNF while unrolling
+    int            fUseFullProof;      // use full proof for UNSAT cores
+    int            fDumpVabs;          // dumps the abstracted model
+    int            fDumpMabs;          // dumps the original AIG with abstraction map
+    int            fCallProver;        // calls the prover
+    int            fSimpProver;        // calls simplification before prover
+    char *         pFileVabs;          // dumps the abstracted model into this file
+    int            fVerbose;           // verbose flag
+    int            fVeryVerbose;       // print additional information
+    int            iFrame;             // the number of frames covered
+    int            iFrameProved;       // the number of frames proved
+    int            nFramesNoChange;    // the number of last frames without changes
+    int            nFramesNoChangeLim; // the number of last frames without changes to dump abstraction
+};
+
+// old abstraction parameters
+typedef struct Gia_ParAbs_t_ Gia_ParAbs_t;
+struct Gia_ParAbs_t_
+{
+    int            Algo;               // the algorithm to be used
+    int            nFramesMax;         // timeframes for PBA
+    int            nConfMax;           // conflicts for PBA
+    int            fDynamic;           // dynamic unfolding for PBA
+    int            fConstr;            // use constraints
+    int            nFramesBmc;         // timeframes for BMC
+    int            nConfMaxBmc;        // conflicts for BMC
+    int            nStableMax;         // the number of stable frames to quit
+    int            nRatio;             // ratio of flops to quit
+    int            TimeOut;            // approximate timeout in seconds
+    int            TimeOutVT;          // approximate timeout in seconds
+    int            nBobPar;            // Bob's parameter
+    int            fUseBdds;           // use BDDs to refine abstraction
+    int            fUseDprove;         // use 'dprove' to refine abstraction
+    int            fUseStart;          // use starting frame
+    int            fVerbose;           // verbose output
+    int            fVeryVerbose;       // printing additional information
+    int            Status;             // the problem status
+    int            nFramesDone;        // the number of frames covered
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int         Ga2_ObjOffset( Gia_Man_t * p, Gia_Obj_t * pObj )          { return Vec_IntEntry(p->vMapping, Gia_ObjId(p, pObj));                                                         }
+static inline int         Ga2_ObjLeaveNum( Gia_Man_t * p, Gia_Obj_t * pObj )        { return Vec_IntEntry(p->vMapping, Ga2_ObjOffset(p, pObj));                                                     }
+static inline int *       Ga2_ObjLeavePtr( Gia_Man_t * p, Gia_Obj_t * pObj )        { return Vec_IntEntryP(p->vMapping, Ga2_ObjOffset(p, pObj) + 1);                                                }
+static inline unsigned    Ga2_ObjTruth( Gia_Man_t * p, Gia_Obj_t * pObj )           { return (unsigned)Vec_IntEntry(p->vMapping, Ga2_ObjOffset(p, pObj) + Ga2_ObjLeaveNum(p, pObj) + 1);            }
+static inline int         Ga2_ObjRefNum( Gia_Man_t * p, Gia_Obj_t * pObj )          { return (unsigned)Vec_IntEntry(p->vMapping, Ga2_ObjOffset(p, pObj) + Ga2_ObjLeaveNum(p, pObj) + 2);            }
+static inline Vec_Int_t * Ga2_ObjLeaves( Gia_Man_t * p, Gia_Obj_t * pObj )          { static Vec_Int_t v; v.nSize = Ga2_ObjLeaveNum(p, pObj), v.pArray = Ga2_ObjLeavePtr(p, pObj); return &v;       }
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== abs.c =========================================================*/
+/*=== absDup.c =========================================================*/
+extern Gia_Man_t *       Gia_ManDupAbsFlops( Gia_Man_t * p, Vec_Int_t * vFlopClasses );
+extern Gia_Man_t *       Gia_ManDupAbsGates( Gia_Man_t * p, Vec_Int_t * vGateClasses );
+extern void              Gia_ManGlaCollect( Gia_Man_t * p, Vec_Int_t * vGateClasses, Vec_Int_t ** pvPis, Vec_Int_t ** pvPPis, Vec_Int_t ** pvFlops, Vec_Int_t ** pvNodes );
+extern void              Gia_ManPrintFlopClasses( Gia_Man_t * p );
+extern void              Gia_ManPrintObjClasses( Gia_Man_t * p );
+extern void              Gia_ManPrintGateClasses( Gia_Man_t * p );
+/*=== absGla.c =========================================================*/
+extern int               Gia_ManPerformGla( Gia_Man_t * p, Abs_Par_t * pPars );
+/*=== absGlaOld.c =========================================================*/
+extern int               Gia_ManPerformGlaOld( Gia_Man_t * p, Abs_Par_t * pPars, int fStartVta );
+/*=== absIter.c =========================================================*/
+extern Gia_Man_t *       Gia_ManShrinkGla( Gia_Man_t * p, int nFrameMax, int nTimeOut, int fUsePdr, int fUseSat, int fUseBdd, int fVerbose );
+/*=== absPth.c =========================================================*/
+extern void              Gia_GlaProveAbsracted( Gia_Man_t * p, int fSimpProver, int fVerbose );
+extern void              Gia_GlaProveCancel( int fVerbose );
+extern int               Gia_GlaProveCheck( int fVerbose );
+/*=== absVta.c =========================================================*/
+extern int               Gia_VtaPerform( Gia_Man_t * pAig, Abs_Par_t * pPars );
+/*=== absUtil.c =========================================================*/
+extern void              Abs_ParSetDefaults( Abs_Par_t * p );
+extern Vec_Int_t *       Gia_VtaConvertToGla( Gia_Man_t * p, Vec_Int_t * vVta );
+extern Vec_Int_t *       Gia_VtaConvertFromGla( Gia_Man_t * p, Vec_Int_t * vGla, int nFrames );
+extern Vec_Int_t *       Gia_FlaConvertToGla( Gia_Man_t * p, Vec_Int_t * vFla );
+extern Vec_Int_t *       Gia_GlaConvertToFla( Gia_Man_t * p, Vec_Int_t * vGla );
+extern int               Gia_GlaCountFlops( Gia_Man_t * p, Vec_Int_t * vGla );
+extern int               Gia_GlaCountNodes( Gia_Man_t * p, Vec_Int_t * vGla );
+
+/*=== absRpm.c =========================================================*/
+extern Gia_Man_t *       Abs_RpmPerform( Gia_Man_t * p, int nCutMax, int fVerbose, int fVeryVerbose );
+/*=== absRpmOld.c =========================================================*/
+extern Gia_Man_t *       Abs_RpmPerformOld( Gia_Man_t * p, int fVerbose );
+extern void              Gia_ManAbsSetDefaultParams( Gia_ParAbs_t * p );
+extern Vec_Int_t *       Saig_ManCexAbstractionFlops( Aig_Man_t * p, Gia_ParAbs_t * pPars );
+
+/*=== absOldCex.c ==========================================================*/
+extern Vec_Int_t *       Saig_ManCbaFilterFlops( Aig_Man_t * pAig, Abc_Cex_t * pAbsCex, Vec_Int_t * vFlopClasses, Vec_Int_t * vAbsFfsToAdd, int nFfsToSelect );
+extern Abc_Cex_t *       Saig_ManCbaFindCexCareBits( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, int fVerbose );
+/*=== absOldRef.c ==========================================================*/
+extern int               Gia_ManCexAbstractionRefine( Gia_Man_t * pGia, Abc_Cex_t * pCex, int nFfToAddMax, int fTryFour, int fSensePath, int fVerbose );
+/*=== absOldSat.c ==========================================================*/
+extern Vec_Int_t *       Saig_ManExtendCounterExampleTest3( Aig_Man_t * pAig, int iFirstFlopPi, Abc_Cex_t * pCex, int fVerbose );
+/*=== absOldSim.c ==========================================================*/
+extern Vec_Int_t *       Saig_ManExtendCounterExampleTest2( Aig_Man_t * p, int iFirstPi, Abc_Cex_t * pCex, int fVerbose );
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/abs/absDup.c b/abc-build/src/proof/abs/absDup.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absDup.c
@@ -0,0 +1,445 @@
+/**CFile****************************************************************
+
+  FileName    [absDup.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Abstraction package.]
+
+  Synopsis    [Duplication procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: absDup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include "abs.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager recursively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManDupAbsFlops_rec( Gia_Man_t * pNew, Gia_Obj_t * pObj )
+{
+    if ( ~pObj->Value )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManDupAbsFlops_rec( pNew, Gia_ObjFanin0(pObj) );
+    Gia_ManDupAbsFlops_rec( pNew, Gia_ObjFanin1(pObj) );
+    pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Extractes a flop-level abstraction given a flop map.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupAbsFlops( Gia_Man_t * p, Vec_Int_t * vFlopClasses )
+{ 
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, nFlops = 0;
+    Gia_ManFillValue( p );
+    // start the new manager
+    pNew = Gia_ManStart( 5000 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // create PIs
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    // create additional PIs
+    Gia_ManForEachRo( p, pObj, i )
+        if ( !Vec_IntEntry(vFlopClasses, i) )
+            pObj->Value = Gia_ManAppendCi(pNew);
+    // create ROs
+    Gia_ManForEachRo( p, pObj, i )
+        if ( Vec_IntEntry(vFlopClasses, i) )
+            pObj->Value = Gia_ManAppendCi(pNew);
+    // create POs
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachPo( p, pObj, i )
+    {
+        Gia_ManDupAbsFlops_rec( pNew, Gia_ObjFanin0(pObj) );
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+    // create RIs
+    Gia_ManForEachRi( p, pObj, i )
+        if ( Vec_IntEntry(vFlopClasses, i) )
+        {
+            Gia_ManDupAbsFlops_rec( pNew, Gia_ObjFanin0(pObj) );
+            Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+            nFlops++;
+        }
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, nFlops );
+    // clean up
+    pNew = Gia_ManSeqCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of neighbors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_GlaCollectAssigned( Gia_Man_t * p, Vec_Int_t * vGateClasses )
+{
+    Vec_Int_t * vAssigned;
+    Gia_Obj_t * pObj;
+    int i, Entry;
+    vAssigned = Vec_IntAlloc( 1000 );
+    Vec_IntForEachEntry( vGateClasses, Entry, i )
+    {
+        if ( Entry == 0 )
+            continue;
+        assert( Entry > 0 );
+        pObj = Gia_ManObj( p, i );
+        Vec_IntPush( vAssigned, Gia_ObjId(p, pObj) );
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            Vec_IntPush( vAssigned, Gia_ObjFaninId0p(p, pObj) );
+            Vec_IntPush( vAssigned, Gia_ObjFaninId1p(p, pObj) );
+        }
+        else if ( Gia_ObjIsRo(p, pObj) )
+            Vec_IntPush( vAssigned, Gia_ObjFaninId0p(p, Gia_ObjRoToRi(p, pObj)) );
+        else assert( Gia_ObjIsConst0(pObj) );
+    }
+    Vec_IntUniqify( vAssigned );
+    return vAssigned;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects PIs and PPIs of the abstraction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManGlaCollect( Gia_Man_t * p, Vec_Int_t * vGateClasses, Vec_Int_t ** pvPis, Vec_Int_t ** pvPPis, Vec_Int_t ** pvFlops, Vec_Int_t ** pvNodes )
+{ 
+    Vec_Int_t * vAssigned;
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Gia_ManPoNum(p) == 1 );
+    assert( Vec_IntSize(vGateClasses) == Gia_ManObjNum(p) );
+    // create included objects and their fanins
+    vAssigned = Gia_GlaCollectAssigned( p, vGateClasses );
+    // create additional arrays
+    if ( pvPis )   *pvPis   = Vec_IntAlloc( 100 );
+    if ( pvPPis )  *pvPPis  = Vec_IntAlloc( 100 );
+    if ( pvFlops ) *pvFlops = Vec_IntAlloc( 100 );
+    if ( pvNodes ) *pvNodes = Vec_IntAlloc( 1000 );
+    Gia_ManForEachObjVec( vAssigned, p, pObj, i )
+    {
+        if ( Gia_ObjIsPi(p, pObj) )
+            { if ( pvPis )   Vec_IntPush( *pvPis, Gia_ObjId(p,pObj) );   }
+        else if ( !Vec_IntEntry(vGateClasses, Gia_ObjId(p,pObj)) )
+            { if ( pvPPis )  Vec_IntPush( *pvPPis, Gia_ObjId(p,pObj) );  }
+        else if ( Gia_ObjIsRo(p, pObj) )
+            { if ( pvFlops ) Vec_IntPush( *pvFlops, Gia_ObjId(p,pObj) ); }
+        else if ( Gia_ObjIsAnd(pObj) )
+            { if ( pvNodes ) Vec_IntPush( *pvNodes, Gia_ObjId(p,pObj) ); }
+        else assert( Gia_ObjIsConst0(pObj) );
+    }
+    Vec_IntFree( vAssigned );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager recursively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManDupAbsGates_rec( Gia_Man_t * pNew, Gia_Obj_t * pObj )
+{
+    if ( ~pObj->Value )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManDupAbsGates_rec( pNew, Gia_ObjFanin0(pObj) );
+    Gia_ManDupAbsGates_rec( pNew, Gia_ObjFanin1(pObj) );
+    pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Extractes a gate-level abstraction given a gate map.]
+
+  Description [The array contains 1 for those objects (const, RO, AND)
+  that are included in the abstraction; 0, otherwise.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupAbsGates( Gia_Man_t * p, Vec_Int_t * vGateClasses )
+{ 
+    Vec_Int_t * vPis, * vPPis, * vFlops, * vNodes;
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pCopy;
+    int i;//, nFlops = 0;
+    assert( Gia_ManPoNum(p) == 1 );
+    assert( Vec_IntSize(vGateClasses) == Gia_ManObjNum(p) );
+
+    // create additional arrays
+    Gia_ManGlaCollect( p, vGateClasses, &vPis, &vPPis, &vFlops, &vNodes );
+
+    // start the new manager
+    pNew = Gia_ManStart( 5000 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // create constant
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    // create PIs
+    Gia_ManForEachObjVec( vPis, p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    // create additional PIs
+    Gia_ManForEachObjVec( vPPis, p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    // create ROs
+    Gia_ManForEachObjVec( vFlops, p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    // create internal nodes
+    Gia_ManForEachObjVec( vNodes, p, pObj, i )
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+//        Gia_ManDupAbsGates_rec( pNew, pObj );
+    // create PO
+    Gia_ManForEachPo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    // create RIs
+    Gia_ManForEachObjVec( vFlops, p, pObj, i )
+        Gia_ObjRoToRi(p, pObj)->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ObjRoToRi(p, pObj)) );
+    Gia_ManSetRegNum( pNew, Vec_IntSize(vFlops) );
+    // clean up
+    pNew = Gia_ManSeqCleanup( pTemp = pNew );
+    // transfer copy values: (p -> pTemp -> pNew) => (p -> pNew)
+    if ( Gia_ManObjNum(pTemp) != Gia_ManObjNum(pNew) )
+    {
+//        printf( "Gia_ManDupAbsGates() Internal error: object mismatch.\n" );
+        Gia_ManForEachObj( p, pObj, i )
+        {
+            if ( !~pObj->Value )
+                continue;
+            assert( !Abc_LitIsCompl(pObj->Value) );
+            pCopy = Gia_ObjCopy( pTemp, pObj );
+            if ( !~pCopy->Value )
+            {
+                Vec_IntWriteEntry( vGateClasses, i, 0 );
+                pObj->Value = ~0;
+                continue;
+            }
+            assert( !Abc_LitIsCompl(pCopy->Value) );
+            pObj->Value = pCopy->Value;
+        }
+    }
+    Gia_ManStop( pTemp );
+
+    Vec_IntFree( vPis );
+    Vec_IntFree( vPPis );
+    Vec_IntFree( vFlops );
+    Vec_IntFree( vNodes );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats for the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintFlopClasses( Gia_Man_t * p )
+{
+    int Counter0, Counter1;
+    if ( p->vFlopClasses == NULL )
+        return;
+    if ( Vec_IntSize(p->vFlopClasses) != Gia_ManRegNum(p) )
+    {
+        printf( "Gia_ManPrintFlopClasses(): The number of flop map entries differs from the number of flops.\n" );
+        return;
+    }
+    Counter0 = Vec_IntCountEntry( p->vFlopClasses, 0 );
+    Counter1 = Vec_IntCountEntry( p->vFlopClasses, 1 );
+    printf( "Flop-level abstraction:  Excluded FFs = %d  Included FFs = %d  (%.2f %%) ", 
+        Counter0, Counter1, 100.0*Counter1/(Counter0 + Counter1 + 1) );
+    if ( Counter0 + Counter1 < Gia_ManRegNum(p) )
+        printf( "and there are other FF classes..." );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats for the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintGateClasses( Gia_Man_t * p )
+{
+    Vec_Int_t * vPis, * vPPis, * vFlops, * vNodes;
+    int nTotal;
+    if ( p->vGateClasses == NULL )
+        return;
+    if ( Vec_IntSize(p->vGateClasses) != Gia_ManObjNum(p) )
+    {
+        printf( "Gia_ManPrintGateClasses(): The number of flop map entries differs from the number of flops.\n" );
+        return;
+    }
+    // create additional arrays
+    Gia_ManGlaCollect( p, p->vGateClasses, &vPis, &vPPis, &vFlops, &vNodes );
+    nTotal = 1 + Vec_IntSize(vFlops) + Vec_IntSize(vNodes);
+    printf( "Gate-level abstraction:  PI = %d  PPI = %d  FF = %d (%.2f %%)  AND = %d (%.2f %%)  Obj = %d (%.2f %%)\n", 
+        Vec_IntSize(vPis), Vec_IntSize(vPPis), 
+        Vec_IntSize(vFlops), 100.0*Vec_IntSize(vFlops)/(Gia_ManRegNum(p)+1), 
+        Vec_IntSize(vNodes), 100.0*Vec_IntSize(vNodes)/(Gia_ManAndNum(p)+1), 
+        nTotal,              100.0*nTotal             /(Gia_ManRegNum(p)+Gia_ManAndNum(p)+1) );
+    Vec_IntFree( vPis );
+    Vec_IntFree( vPPis );
+    Vec_IntFree( vFlops );
+    Vec_IntFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats for the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintObjClasses( Gia_Man_t * p )
+{
+    Vec_Int_t * vSeens;  // objects seen so far
+    Vec_Int_t * vAbs = p->vObjClasses;
+    int i, k, Entry, iStart, iStop = -1, nFrames;
+    int nObjBits, nObjMask, iObj, iFrame, nWords;
+    unsigned * pInfo;
+	int * pCountAll, * pCountUni;
+    if ( vAbs == NULL )
+        return;
+    nFrames = Vec_IntEntry( vAbs, 0 );
+    assert( Vec_IntEntry(vAbs, nFrames+1) == Vec_IntSize(vAbs) );
+    pCountAll = ABC_ALLOC( int, nFrames + 1 );
+    pCountUni = ABC_ALLOC( int, nFrames + 1 );
+    // start storage for seen objects
+    nWords = Abc_BitWordNum( nFrames );
+    vSeens = Vec_IntStart( Gia_ManObjNum(p) * nWords );
+    // get the bitmasks
+    nObjBits = Abc_Base2Log( Gia_ManObjNum(p) );
+    nObjMask = (1 << nObjBits) - 1;
+    assert( Gia_ManObjNum(p) <= nObjMask );
+    // print info about frames
+    printf( "Frame   Core   F0   F1   F2   F3 ...\n" );
+    for ( i = 0; i < nFrames; i++ )
+    {
+        iStart = Vec_IntEntry( vAbs, i+1 );
+        iStop  = Vec_IntEntry( vAbs, i+2 );
+        memset( pCountAll, 0, sizeof(int) * (nFrames + 1) );
+        memset( pCountUni, 0, sizeof(int) * (nFrames + 1) );
+        Vec_IntForEachEntryStartStop( vAbs, Entry, k, iStart, iStop )
+        {
+            iObj   = (Entry &  nObjMask);
+            iFrame = (Entry >> nObjBits);
+            pInfo  = (unsigned *)Vec_IntEntryP( vSeens, nWords * iObj );
+            if ( Abc_InfoHasBit(pInfo, iFrame) == 0 )
+            {
+                Abc_InfoSetBit( pInfo, iFrame );
+                pCountUni[iFrame+1]++;
+                pCountUni[0]++;
+            }
+            pCountAll[iFrame+1]++;
+            pCountAll[0]++;
+        }
+        assert( pCountAll[0] == (iStop - iStart) );
+//        printf( "%5d%5d  ", pCountAll[0], pCountUni[0] ); 
+        printf( "%3d :", i );
+        printf( "%7d", pCountAll[0] ); 
+        if ( i >= 10 )
+        {
+            for ( k = 0; k < 4; k++ )
+                printf( "%5d", pCountAll[k+1] ); 
+            printf( "  ..." );
+            for ( k = i-4; k <= i; k++ )
+                printf( "%5d", pCountAll[k+1] ); 
+        }
+        else
+        {
+            for ( k = 0; k <= i; k++ )
+                if ( k <= i )
+                    printf( "%5d", pCountAll[k+1] ); 
+        }
+//        for ( k = 0; k < nFrames; k++ )
+//            if ( k <= i )
+//                printf( "%5d", pCountAll[k+1] ); 
+        printf( "\n" );
+    }
+    assert( iStop == Vec_IntSize(vAbs) );
+    Vec_IntFree( vSeens );
+    ABC_FREE( pCountAll );
+    ABC_FREE( pCountUni );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/absGla.c b/abc-build/src/proof/abs/absGla.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absGla.c
@@ -0,0 +1,1873 @@
+/**CFile****************************************************************
+
+  FileName    [absGla2.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Abstraction package.]
+
+  Synopsis    [Scalable gate-level abstraction.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: absGla2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/main/main.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver2.h"
+#include "bool/kit/kit.h"
+#include "abs.h"
+#include "absRef.h"
+//#include "absRef2.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define GA2_BIG_NUM 0x3FFFFFF0
+
+typedef struct Ga2_Man_t_ Ga2_Man_t; // manager
+struct Ga2_Man_t_
+{
+    // user data
+    Gia_Man_t *    pGia;         // working AIG manager
+    Abs_Par_t *    pPars;        // parameters
+    // markings 
+    Vec_Ptr_t *    vCnfs;        // for each object: CNF0, CNF1
+    // abstraction
+    Vec_Int_t *    vIds;         // abstraction ID for each GIA object
+    Vec_Int_t *    vProofIds;    // mapping of GIA objects into their proof IDs
+    Vec_Int_t *    vAbs;         // array of abstracted objects
+    Vec_Int_t *    vValues;      // array of objects with abstraction ID assigned
+    int            nProofIds;    // the counter of proof IDs
+    int            LimAbs;       // limit value for starting abstraction objects
+    int            LimPpi;       // limit value for starting PPI objects
+    int            nMarked;      // total number of marked nodes and flops
+    int            fUseNewLine;  // remember that you used new line
+    // refinement
+    Rnm_Man_t *    pRnm;         // refinement manager
+//    Rf2_Man_t *    pRf2;         // refinement manager
+    // SAT solver and variables
+    Vec_Ptr_t *    vId2Lit;      // mapping, for each timeframe, of object ID into SAT literal
+    sat_solver2 *  pSat;         // incremental SAT solver
+    int            nSatVars;     // the number of SAT variables
+    int            nCexes;       // the number of counter-examples
+    int            nObjAdded;    // objs added during refinement
+    int            nPdrCalls;    // count the number of concurrent calls
+    // hash table
+    int *          pTable;
+    int            nTable;
+    int            nHashHit;
+    int            nHashMiss;
+    int            nHashOver;
+    // temporaries
+    Vec_Int_t *    vLits;
+    Vec_Int_t *    vIsopMem;
+    char * pSopSizes, ** pSops;  // CNF representation
+    // statistics  
+    abctime        timeStart;
+    abctime        timeInit;
+    abctime        timeSat;
+    abctime        timeUnsat;
+    abctime        timeCex;
+    abctime        timeOther;
+};
+
+static inline int         Ga2_ObjId( Ga2_Man_t * p, Gia_Obj_t * pObj )           { return Vec_IntEntry(p->vIds, Gia_ObjId(p->pGia, pObj));                                                  }
+static inline void        Ga2_ObjSetId( Ga2_Man_t * p, Gia_Obj_t * pObj, int i ) { Vec_IntWriteEntry(p->vIds, Gia_ObjId(p->pGia, pObj), i);                                                 }
+
+static inline Vec_Int_t * Ga2_ObjCnf0( Ga2_Man_t * p, Gia_Obj_t * pObj )         { assert(Ga2_ObjId(p,pObj) >= 0); return (Vec_Int_t *)Vec_PtrEntry( p->vCnfs, 2*Ga2_ObjId(p,pObj)   );                  }
+static inline Vec_Int_t * Ga2_ObjCnf1( Ga2_Man_t * p, Gia_Obj_t * pObj )         { assert(Ga2_ObjId(p,pObj) >= 0); return (Vec_Int_t *)Vec_PtrEntry( p->vCnfs, 2*Ga2_ObjId(p,pObj)+1 );                  }
+
+static inline int         Ga2_ObjIsAbs0( Ga2_Man_t * p, Gia_Obj_t * pObj )       { assert(Ga2_ObjId(p,pObj) >= 0); return Ga2_ObjId(p,pObj) >= 0         && Ga2_ObjId(p,pObj) < p->LimAbs;  }
+static inline int         Ga2_ObjIsLeaf0( Ga2_Man_t * p, Gia_Obj_t * pObj )      { assert(Ga2_ObjId(p,pObj) >= 0); return Ga2_ObjId(p,pObj) >= p->LimAbs && Ga2_ObjId(p,pObj) < p->LimPpi;  }
+static inline int         Ga2_ObjIsAbs( Ga2_Man_t * p, Gia_Obj_t * pObj )        { return Ga2_ObjId(p,pObj) >= 0 &&  Ga2_ObjCnf0(p,pObj);                                                   }
+static inline int         Ga2_ObjIsLeaf( Ga2_Man_t * p, Gia_Obj_t * pObj )       { return Ga2_ObjId(p,pObj) >= 0 && !Ga2_ObjCnf0(p,pObj);                                                   }
+
+static inline Vec_Int_t * Ga2_MapFrameMap( Ga2_Man_t * p, int f )                { return (Vec_Int_t *)Vec_PtrEntry( p->vId2Lit, f );                                                       }
+
+// returns literal of this object, or -1 if SAT variable of the object is not assigned
+static inline int Ga2_ObjFindLit( Ga2_Man_t * p, Gia_Obj_t * pObj, int f )  
+{ 
+//    int Id = Ga2_ObjId(p,pObj);
+    assert( Ga2_ObjId(p,pObj) >= 0 && Ga2_ObjId(p,pObj) < Vec_IntSize(p->vValues) );
+    return Vec_IntEntry( Ga2_MapFrameMap(p, f), Ga2_ObjId(p,pObj) );
+}
+// inserts literal of this object
+static inline void Ga2_ObjAddLit( Ga2_Man_t * p, Gia_Obj_t * pObj, int f, int Lit )  
+{ 
+//    assert( Lit > 1 );
+    assert( Ga2_ObjFindLit(p, pObj, f) == -1 );
+    Vec_IntSetEntry( Ga2_MapFrameMap(p, f), Ga2_ObjId(p,pObj), Lit );
+}
+// returns or inserts-and-returns literal of this object
+static inline int Ga2_ObjFindOrAddLit( Ga2_Man_t * p, Gia_Obj_t * pObj, int f )  
+{ 
+    int Lit = Ga2_ObjFindLit( p, pObj, f );
+    if ( Lit == -1 )
+    {
+        Lit = toLitCond( p->nSatVars++, 0 );
+        Ga2_ObjAddLit( p, pObj, f, Lit );
+    }
+//    assert( Lit > 1 );
+    return Lit;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes truth table for the marked node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Ga2_ObjComputeTruth_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int fFirst )
+{
+    unsigned Val0, Val1;
+    if ( pObj->fPhase && !fFirst )
+        return pObj->Value;
+    assert( Gia_ObjIsAnd(pObj) );
+    Val0 = Ga2_ObjComputeTruth_rec( p, Gia_ObjFanin0(pObj), 0 );
+    Val1 = Ga2_ObjComputeTruth_rec( p, Gia_ObjFanin1(pObj), 0 );
+    return (Gia_ObjFaninC0(pObj) ? ~Val0 : Val0) & (Gia_ObjFaninC1(pObj) ? ~Val1 : Val1);
+}
+unsigned Ga2_ManComputeTruth( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves )
+{
+    static unsigned uTruth5[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+    Gia_Obj_t * pObj;
+    unsigned Res;
+    int i;
+    Gia_ManForEachObjVec( vLeaves, p, pObj, i )
+        pObj->Value = uTruth5[i];
+    Res = Ga2_ObjComputeTruth_rec( p, pRoot, 1 );
+    Gia_ManForEachObjVec( vLeaves, p, pObj, i )
+        pObj->Value = 0;
+    return Res;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns AIG marked for CNF generation.]
+
+  Description [The marking satisfies the following requirements:
+  Each marked node has the number of marked fanins no more than N.]
+               
+  SideEffects [Uses pObj->fPhase to store the markings.]
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ga2_ManBreakTree_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int fFirst, int N )
+{   // breaks a tree rooted at the node into N-feasible subtrees
+    int Val0, Val1;
+    if ( pObj->fPhase && !fFirst )
+        return 1;
+    Val0 = Ga2_ManBreakTree_rec( p, Gia_ObjFanin0(pObj), 0, N );
+    Val1 = Ga2_ManBreakTree_rec( p, Gia_ObjFanin1(pObj), 0, N );
+    if ( Val0 + Val1 < N )
+        return Val0 + Val1;
+    if ( Val0 + Val1 == N )
+    {
+        pObj->fPhase = 1;
+        return 1;
+    }
+    assert( Val0 + Val1 > N );
+    assert( Val0 < N && Val1 < N );
+    if ( Val0 >= Val1 )
+    {
+        Gia_ObjFanin0(pObj)->fPhase = 1;
+        Val0 = 1;
+    }
+    else 
+    {
+        Gia_ObjFanin1(pObj)->fPhase = 1;
+        Val1 = 1;
+    }
+    if ( Val0 + Val1 < N )
+        return Val0 + Val1;
+    if ( Val0 + Val1 == N )
+    {
+        pObj->fPhase = 1;
+        return 1;
+    }
+    assert( 0 );
+    return -1;
+}
+int Ga2_ManCheckNodesAnd( Gia_Man_t * p, Vec_Int_t * vNodes )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObjVec( vNodes, p, pObj, i )
+        if ( (!Gia_ObjFanin0(pObj)->fPhase && Gia_ObjFaninC0(pObj)) || 
+             (!Gia_ObjFanin1(pObj)->fPhase && Gia_ObjFaninC1(pObj)) )
+            return 0;
+    return 1;
+}
+void Ga2_ManCollectNodes_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes, int fFirst )
+{
+    if ( pObj->fPhase && !fFirst )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    Ga2_ManCollectNodes_rec( p, Gia_ObjFanin0(pObj), vNodes, 0 );
+    Ga2_ManCollectNodes_rec( p, Gia_ObjFanin1(pObj), vNodes, 0 );
+    Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+
+}
+void Ga2_ManCollectLeaves_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves, int fFirst )
+{
+    if ( pObj->fPhase && !fFirst )
+    {
+        Vec_IntPushUnique( vLeaves, Gia_ObjId(p, pObj) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Ga2_ManCollectLeaves_rec( p, Gia_ObjFanin0(pObj), vLeaves, 0 );
+    Ga2_ManCollectLeaves_rec( p, Gia_ObjFanin1(pObj), vLeaves, 0 );
+}
+int Ga2_ManMarkup( Gia_Man_t * p, int N, int fSimple )
+{
+    static unsigned uTruth5[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+//    abctime clk = Abc_Clock();
+    Vec_Int_t * vLeaves;
+    Gia_Obj_t * pObj;
+    int i, k, Leaf, CountMarks;
+
+    vLeaves = Vec_IntAlloc( 100 );
+
+    if ( fSimple )
+    {
+        Gia_ManForEachObj( p, pObj, i )
+            pObj->fPhase = !Gia_ObjIsCo(pObj);
+    }
+    else
+    {
+        // label nodes with multiple fanouts and inputs MUXes
+        Gia_ManForEachObj( p, pObj, i )
+        {
+            pObj->Value = 0;
+            if ( !Gia_ObjIsAnd(pObj) )
+                continue;
+            Gia_ObjFanin0(pObj)->Value++;
+            Gia_ObjFanin1(pObj)->Value++;
+            if ( !Gia_ObjIsMuxType(pObj) )
+                continue;
+            Gia_ObjFanin0(Gia_ObjFanin0(pObj))->Value++;
+            Gia_ObjFanin1(Gia_ObjFanin0(pObj))->Value++;
+            Gia_ObjFanin0(Gia_ObjFanin1(pObj))->Value++;
+            Gia_ObjFanin1(Gia_ObjFanin1(pObj))->Value++;
+        }
+        Gia_ManForEachObj( p, pObj, i )
+        {
+            pObj->fPhase = 0;
+            if ( Gia_ObjIsAnd(pObj) )
+                pObj->fPhase = (pObj->Value > 1);
+            else if ( Gia_ObjIsCo(pObj) )
+                Gia_ObjFanin0(pObj)->fPhase = 1;
+            else 
+                pObj->fPhase = 1;
+        } 
+        // add marks when needed
+        Gia_ManForEachAnd( p, pObj, i )
+        {
+            if ( !pObj->fPhase )
+                continue;
+            Vec_IntClear( vLeaves );
+            Ga2_ManCollectLeaves_rec( p, pObj, vLeaves, 1 );
+            if ( Vec_IntSize(vLeaves) > N )
+                Ga2_ManBreakTree_rec( p, pObj, 1, N );
+        }
+    }
+
+    // verify that the tree is split correctly
+    Vec_IntFreeP( &p->vMapping );
+    p->vMapping = Vec_IntStart( Gia_ManObjNum(p) );
+    Gia_ManForEachRo( p, pObj, i )
+    {
+        Gia_Obj_t * pObjRi = Gia_ObjRoToRi(p, pObj);
+        assert( pObj->fPhase );
+        assert( Gia_ObjFanin0(pObjRi)->fPhase );
+        // create map
+        Vec_IntWriteEntry( p->vMapping, Gia_ObjId(p, pObj), Vec_IntSize(p->vMapping) );
+        Vec_IntPush( p->vMapping, 1 );
+        Vec_IntPush( p->vMapping, Gia_ObjFaninId0p(p, pObjRi) );
+        Vec_IntPush( p->vMapping, Gia_ObjFaninC0(pObjRi) ? 0x55555555 : 0xAAAAAAAA );
+        Vec_IntPush( p->vMapping, -1 );  // placeholder for ref counter
+    }
+    CountMarks = Gia_ManRegNum(p);
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        if ( !pObj->fPhase )
+            continue;
+        Vec_IntClear( vLeaves );
+        Ga2_ManCollectLeaves_rec( p, pObj, vLeaves, 1 );
+        assert( Vec_IntSize(vLeaves) <= N );
+        // create map
+        Vec_IntWriteEntry( p->vMapping, i, Vec_IntSize(p->vMapping) );
+        Vec_IntPush( p->vMapping, Vec_IntSize(vLeaves) );
+        Vec_IntForEachEntry( vLeaves, Leaf, k )
+        {            
+            Vec_IntPush( p->vMapping, Leaf );
+            Gia_ManObj(p, Leaf)->Value = uTruth5[k];
+            assert( Gia_ManObj(p, Leaf)->fPhase );
+        }
+        Vec_IntPush( p->vMapping,  (int)Ga2_ObjComputeTruth_rec( p, pObj, 1 ) );
+        Vec_IntPush( p->vMapping, -1 );  // placeholder for ref counter
+        CountMarks++;
+    }
+//    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    Vec_IntFree( vLeaves );
+    Gia_ManCleanValue( p );
+    return CountMarks;
+}
+void Ga2_ManComputeTest( Gia_Man_t * p )
+{
+    abctime clk;
+//    unsigned uTruth;
+    Gia_Obj_t * pObj;
+    int i, Counter = 0;
+    clk = Abc_Clock();
+    Ga2_ManMarkup( p, 5, 0 );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        if ( !pObj->fPhase )
+            continue;
+//        uTruth = Ga2_ObjTruth( p, pObj );
+//        printf( "%6d : ", Counter );
+//        Kit_DsdPrintFromTruth( &uTruth, Ga2_ObjLeaveNum(p, pObj) ); 
+//        printf( "\n" );
+        Counter++;
+    }
+    Abc_Print( 1, "Marked AND nodes = %6d.  ", Counter );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ga2_Man_t * Ga2_ManStart( Gia_Man_t * pGia, Abs_Par_t * pPars )
+{
+    Ga2_Man_t * p;
+    p = ABC_CALLOC( Ga2_Man_t, 1 );
+    p->timeStart = Abc_Clock();
+    p->fUseNewLine = 1;
+    // user data
+    p->pGia      = pGia;
+    p->pPars     = pPars;
+    // markings 
+    p->nMarked   = Ga2_ManMarkup( pGia, 5, pPars->fUseSimple );
+    p->vCnfs     = Vec_PtrAlloc( 1000 );
+    Vec_PtrPush( p->vCnfs, Vec_IntAlloc(0) );
+    Vec_PtrPush( p->vCnfs, Vec_IntAlloc(0) );
+    // abstraction
+    p->vIds      = Vec_IntStartFull( Gia_ManObjNum(pGia) );
+    p->vProofIds = Vec_IntAlloc( 0 );
+    p->vAbs      = Vec_IntAlloc( 1000 );
+    p->vValues   = Vec_IntAlloc( 1000 );
+    // add constant node to abstraction
+    Ga2_ObjSetId( p, Gia_ManConst0(pGia), 0 );
+    Vec_IntPush( p->vValues, 0 );
+    Vec_IntPush( p->vAbs, 0 );
+    // refinement
+    p->pRnm      = Rnm_ManStart( pGia );
+//    p->pRf2      = Rf2_ManStart( pGia );
+    // SAT solver and variables
+    p->vId2Lit   = Vec_PtrAlloc( 1000 );
+    // temporaries
+    p->vLits     = Vec_IntAlloc( 100 );
+    p->vIsopMem  = Vec_IntAlloc( 100 );
+    Cnf_ReadMsops( &p->pSopSizes, &p->pSops );
+    // hash table
+    p->nTable = Abc_PrimeCudd(1<<18);
+    p->pTable = ABC_CALLOC( int, 6 * p->nTable ); 
+    return p;
+}
+
+void Ga2_ManDumpStats( Gia_Man_t * pGia, Abs_Par_t * pPars, sat_solver2 * pSat, int iFrame, int fUseN )
+{
+    FILE * pFile;
+    char pFileName[32];
+    sprintf( pFileName, "stats_gla%s%s.txt", fUseN ? "n":"", pPars->fUseFullProof ? "p":"" ); 
+
+    pFile = fopen( pFileName, "a+" );
+
+    fprintf( pFile, "%s pi=%d ff=%d and=%d mem=%d bmc=%d", 
+        pGia->pName, 
+        Gia_ManPiNum(pGia), Gia_ManRegNum(pGia), Gia_ManAndNum(pGia), 
+        (int)(1 + sat_solver2_memory_proof(pSat)/(1<<20)),
+        iFrame );
+
+    if ( pGia->vGateClasses )
+    fprintf( pFile, " ff=%d and=%d",                 
+        Gia_GlaCountFlops( pGia, pGia->vGateClasses ),
+        Gia_GlaCountNodes( pGia, pGia->vGateClasses )  );
+
+    fprintf( pFile, "\n" );
+    fclose( pFile );
+}
+void Ga2_ManReportMemory( Ga2_Man_t * p )
+{
+    double memTot = 0;
+    double memAig = 1.0 * p->pGia->nObjsAlloc * sizeof(Gia_Obj_t) + Vec_IntMemory(p->pGia->vMapping);
+    double memSat = sat_solver2_memory( p->pSat, 1 );
+    double memPro = sat_solver2_memory_proof( p->pSat );
+    double memMap = Vec_VecMemoryInt( (Vec_Vec_t *)p->vId2Lit );
+    double memRef = Rnm_ManMemoryUsage( p->pRnm );
+    double memHash= sizeof(int) * 6 * p->nTable;
+    double memOth = sizeof(Ga2_Man_t);
+    memOth += Vec_VecMemoryInt( (Vec_Vec_t *)p->vCnfs );
+    memOth += Vec_IntMemory( p->vIds );
+    memOth += Vec_IntMemory( p->vProofIds );
+    memOth += Vec_IntMemory( p->vAbs );
+    memOth += Vec_IntMemory( p->vValues );
+    memOth += Vec_IntMemory( p->vLits );
+    memOth += Vec_IntMemory( p->vIsopMem );
+    memOth += 336450 + (sizeof(char) + sizeof(char*)) * 65536;
+    memTot = memAig + memSat + memPro + memMap + memRef + memHash + memOth;
+    ABC_PRMP( "Memory: AIG      ", memAig, memTot );
+    ABC_PRMP( "Memory: SAT      ", memSat, memTot );
+    ABC_PRMP( "Memory: Proof    ", memPro, memTot );
+    ABC_PRMP( "Memory: Map      ", memMap, memTot );
+    ABC_PRMP( "Memory: Refine   ", memRef, memTot );
+    ABC_PRMP( "Memory: Hash     ", memHash,memTot );
+    ABC_PRMP( "Memory: Other    ", memOth, memTot );
+    ABC_PRMP( "Memory: TOTAL    ", memTot, memTot );
+}
+void Ga2_ManStop( Ga2_Man_t * p )
+{
+    Vec_IntFreeP( &p->pGia->vMapping );
+    Gia_ManSetPhase( p->pGia );
+    if ( p->pPars->fVerbose )
+        Abc_Print( 1, "SAT solver:  Var = %d  Cla = %d  Conf = %d  Lrn = %d  Reduce = %d  Cex = %d  ObjsAdded = %d\n", 
+            sat_solver2_nvars(p->pSat), sat_solver2_nclauses(p->pSat), 
+            sat_solver2_nconflicts(p->pSat), sat_solver2_nlearnts(p->pSat), 
+            p->pSat->nDBreduces, p->nCexes, p->nObjAdded );
+    if ( p->pPars->fVerbose )
+    Abc_Print( 1, "Hash hits = %d.  Hash misses = %d.  Hash overs = %d.  Concurrent calls = %d.\n", 
+        p->nHashHit, p->nHashMiss, p->nHashOver, p->nPdrCalls );
+
+    if( p->pSat ) sat_solver2_delete( p->pSat );
+    Vec_VecFree( (Vec_Vec_t *)p->vCnfs );
+    Vec_VecFree( (Vec_Vec_t *)p->vId2Lit );
+    Vec_IntFree( p->vIds );
+    Vec_IntFree( p->vProofIds );
+    Vec_IntFree( p->vAbs );
+    Vec_IntFree( p->vValues );
+    Vec_IntFree( p->vLits );
+    Vec_IntFree( p->vIsopMem );
+    Rnm_ManStop( p->pRnm, 0 );
+//    Rf2_ManStop( p->pRf2, p->pPars->fVerbose );
+    ABC_FREE( p->pTable );
+    ABC_FREE( p->pSopSizes );
+    ABC_FREE( p->pSops[1] );
+    ABC_FREE( p->pSops );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes a minimized truth table.]
+
+  Description [Input literals can be 0/1 (const 0/1), non-trivial literals 
+  (integers that are more than 1) and unassigned literals (large integers).
+  This procedure computes the truth table that essentially depends on input
+  variables ordered in the increasing order of their positive literals.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Ga2_ObjTruthDepends( unsigned t, int v )
+{
+    static unsigned uInvTruth5[5] = { 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF };
+    assert( v >= 0 && v <= 4 );
+    return ((t ^ (t >> (1 << v))) & uInvTruth5[v]);
+}
+unsigned Ga2_ObjComputeTruthSpecial( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vLits )
+{
+    int fVerbose = 0;
+    static unsigned uTruth5[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+    unsigned Res;
+    Gia_Obj_t * pObj;
+    int i, Entry;
+//    int Id = Gia_ObjId(p, pRoot);
+    assert( Gia_ObjIsAnd(pRoot) );
+
+    if ( fVerbose )
+    printf( "Object %d.\n", Gia_ObjId(p, pRoot) );
+
+    // assign elementary truth tables
+    Gia_ManForEachObjVec( vLeaves, p, pObj, i )
+    {
+        Entry = Vec_IntEntry( vLits, i );
+        assert( Entry >= 0 );
+        if ( Entry == 0 )
+            pObj->Value = 0;
+        else if ( Entry == 1 )
+            pObj->Value = ~0;
+        else // non-trivial literal
+            pObj->Value = uTruth5[i];
+        if ( fVerbose )
+        printf( "%d ", Entry );
+    }
+
+    if ( fVerbose )
+    {
+    Res = Ga2_ObjTruth( p, pRoot );
+//    Kit_DsdPrintFromTruth( &Res, Vec_IntSize(vLeaves) );
+    printf( "\n" );
+    }
+
+    // compute truth table
+    Res = Ga2_ObjComputeTruth_rec( p, pRoot, 1 );
+    if ( Res != 0 && Res != ~0 )
+    {
+        // find essential variables
+        int nUsed = 0, pUsed[5];
+        for ( i = 0; i < Vec_IntSize(vLeaves); i++ )
+            if ( Ga2_ObjTruthDepends( Res, i ) )
+                pUsed[nUsed++] = i;
+        assert( nUsed > 0 );
+        // order positions by literal value
+        Vec_IntSelectSortCost( pUsed, nUsed, vLits );
+        assert( Vec_IntEntry(vLits, pUsed[0]) <= Vec_IntEntry(vLits, pUsed[nUsed-1]) );
+        // assign elementary truth tables to the leaves
+        Gia_ManForEachObjVec( vLeaves, p, pObj, i )
+        {
+            Entry = Vec_IntEntry( vLits, i );
+            assert( Entry >= 0 );
+            if ( Entry == 0 )
+                pObj->Value = 0;
+            else if ( Entry == 1 )
+                pObj->Value = ~0;
+            else // non-trivial literal
+                pObj->Value = 0xDEADCAFE; // not important
+        }
+        for ( i = 0; i < nUsed; i++ )
+        {
+            Entry = Vec_IntEntry( vLits, pUsed[i] );
+            assert( Entry > 1 );
+            pObj = Gia_ManObj( p, Vec_IntEntry(vLeaves, pUsed[i]) );
+            pObj->Value = Abc_LitIsCompl(Entry) ? ~uTruth5[i] : uTruth5[i];
+//            pObj->Value = uTruth5[i];
+            // remember this literal
+            pUsed[i] = Abc_LitRegular(Entry);
+//            pUsed[i] = Entry;
+        }
+        // compute truth table
+        Res = Ga2_ObjComputeTruth_rec( p, pRoot, 1 );
+        // reload the literals
+        Vec_IntClear( vLits );
+        for ( i = 0; i < nUsed; i++ )
+        {
+            Vec_IntPush( vLits, pUsed[i] );
+            assert( Ga2_ObjTruthDepends(Res, i) );
+            if ( fVerbose )
+            printf( "%d ", pUsed[i] );
+        }
+        for ( ; i < 5; i++ )
+            assert( !Ga2_ObjTruthDepends(Res, i) );
+
+if ( fVerbose )
+{
+//    Kit_DsdPrintFromTruth( &Res, nUsed );
+    printf( "\n" );
+}
+
+    }
+    else
+    {
+
+if ( fVerbose )
+{
+    Vec_IntClear( vLits );
+    printf( "Const %d\n", Res > 0 );
+}
+
+    }
+    Gia_ManForEachObjVec( vLeaves, p, pObj, i )
+        pObj->Value = 0;
+    return Res;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns CNF of the function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Ga2_ManCnfCompute( unsigned uTruth, int nVars, Vec_Int_t * vCover )
+{
+    int RetValue;
+    assert( nVars <= 5 );
+    // transform truth table into the SOP
+    RetValue = Kit_TruthIsop( &uTruth, nVars, vCover, 0 );
+    assert( RetValue == 0 );
+    // check the case of constant cover
+    return Vec_IntDup( vCover );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CNF for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Ga2_ManCnfAddDynamic( Ga2_Man_t * p, int uTruth, int Lits[], int iLitOut, int ProofId )
+{
+    int i, k, b, Cube, nClaLits, ClaLits[6];
+//    assert( uTruth > 0 && uTruth < 0xffff );
+    for ( i = 0; i < 2; i++ )
+    {
+        if ( i )
+            uTruth = 0xffff & ~uTruth;
+//        Extra_PrintBinary( stdout, &uTruth, 16 ); printf( "\n" );
+        for ( k = 0; k < p->pSopSizes[uTruth]; k++ )
+        {
+            nClaLits = 0;
+            ClaLits[nClaLits++] = i ? lit_neg(iLitOut) : iLitOut;
+            Cube = p->pSops[uTruth][k];
+            for ( b = 3; b >= 0; b-- )
+            {
+                if ( Cube % 3 == 0 ) // value 0 --> add positive literal
+                {
+                    assert( Lits[b] > 1 );
+                    ClaLits[nClaLits++] = Lits[b];
+                }
+                else if ( Cube % 3 == 1 ) // value 1 --> add negative literal
+                {
+                    assert( Lits[b] > 1 );
+                    ClaLits[nClaLits++] = lit_neg(Lits[b]);
+                }
+                Cube = Cube / 3;
+            }
+            sat_solver2_addclause( p->pSat, ClaLits, ClaLits+nClaLits, ProofId );
+        }
+    }
+}
+void Ga2_ManCnfAddStatic( sat_solver2 * pSat, Vec_Int_t * vCnf0, Vec_Int_t * vCnf1, int Lits[], int iLitOut, int ProofId )
+{
+    Vec_Int_t * vCnf;
+    int i, k, b, Cube, Literal, nClaLits, ClaLits[6];
+    for ( i = 0; i < 2; i++ )
+    {
+        vCnf = i ? vCnf1 : vCnf0;
+        Vec_IntForEachEntry( vCnf, Cube, k )
+        {
+            nClaLits = 0;
+            ClaLits[nClaLits++] = i ? lit_neg(iLitOut) : iLitOut;
+            for ( b = 0; b < 5; b++ )
+            {
+                Literal = 3 & (Cube >> (b << 1));
+                if ( Literal == 1 ) // value 0 --> add positive literal
+                {
+//                    assert( Lits[b] > 1 );
+                    ClaLits[nClaLits++] = Lits[b];
+                }
+                else if ( Literal == 2 ) // value 1 --> add negative literal
+                {
+//                    assert( Lits[b] > 1 );
+                    ClaLits[nClaLits++] = lit_neg(Lits[b]);
+                }
+                else if ( Literal != 0 )
+                    assert( 0 );
+            }
+            sat_solver2_addclause( pSat, ClaLits, ClaLits+nClaLits, ProofId );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Saig_ManBmcHashKey( int * pArray )
+{
+    static int s_Primes[5] = { 12582917, 25165843, 50331653, 100663319, 201326611 };
+    unsigned i, Key = 0;
+    for ( i = 0; i < 5; i++ )
+        Key += pArray[i] * s_Primes[i];
+    return Key;
+}
+static inline int * Saig_ManBmcLookup( Ga2_Man_t * p, int * pArray )
+{
+    int * pTable = p->pTable + 6 * (Saig_ManBmcHashKey(pArray) % p->nTable);
+    if ( memcmp( pTable, pArray, 20 ) )
+    {
+        if ( pTable[0] == 0 )
+            p->nHashMiss++;
+        else
+            p->nHashOver++;
+        memcpy( pTable, pArray, 20 );
+        pTable[5] = 0;
+    }
+    else
+        p->nHashHit++;
+    assert( pTable + 5 < pTable + 6 * p->nTable );
+    return pTable + 5;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Ga2_ManSetupNode( Ga2_Man_t * p, Gia_Obj_t * pObj, int fAbs )
+{
+    unsigned uTruth;
+    int nLeaves;
+//    int Id = Gia_ObjId(p->pGia, pObj);
+    assert( pObj->fPhase );
+    assert( Vec_PtrSize(p->vCnfs) == 2 * Vec_IntSize(p->vValues) );
+    // assign abstraction ID to the node
+    if ( Ga2_ObjId(p,pObj) == -1 )
+    {
+        Ga2_ObjSetId( p, pObj, Vec_IntSize(p->vValues) );
+        Vec_IntPush( p->vValues, Gia_ObjId(p->pGia, pObj) );
+        Vec_PtrPush( p->vCnfs, NULL );
+        Vec_PtrPush( p->vCnfs, NULL );
+    }
+    assert( Ga2_ObjCnf0(p, pObj) == NULL );
+    if ( !fAbs )
+        return;
+    Vec_IntPush( p->vAbs, Gia_ObjId(p->pGia, pObj) );
+    assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsRo(p->pGia, pObj) );
+    // compute parameters
+    nLeaves = Ga2_ObjLeaveNum(p->pGia, pObj);
+    uTruth = Ga2_ObjTruth( p->pGia, pObj );
+    // create CNF for pos/neg phases
+    Vec_PtrWriteEntry( p->vCnfs, 2 * Ga2_ObjId(p,pObj),     Ga2_ManCnfCompute( uTruth, nLeaves, p->vIsopMem) );    
+    Vec_PtrWriteEntry( p->vCnfs, 2 * Ga2_ObjId(p,pObj) + 1, Ga2_ManCnfCompute(~uTruth, nLeaves, p->vIsopMem) );
+}
+
+static inline void Ga2_ManAddToAbsOneStatic( Ga2_Man_t * p, Gia_Obj_t * pObj, int f, int fUseId )
+{
+    Vec_Int_t * vLeaves;
+    Gia_Obj_t * pLeaf;
+    int k, Lit, iLitOut = Ga2_ObjFindOrAddLit( p, pObj, f );
+    assert( iLitOut > 1 );
+    assert( Gia_ObjIsConst0(pObj) || Gia_ObjIsRo(p->pGia, pObj) || Gia_ObjIsAnd(pObj) );
+    if ( Gia_ObjIsConst0(pObj) || (f == 0 && Gia_ObjIsRo(p->pGia, pObj)) )
+    {
+        iLitOut = Abc_LitNot( iLitOut );
+        sat_solver2_addclause( p->pSat, &iLitOut, &iLitOut + 1, fUseId ? Gia_ObjId(p->pGia, pObj) : -1 );
+    }
+    else
+    {
+        int fUseStatic = 1;
+        Vec_IntClear( p->vLits );
+        vLeaves = Ga2_ObjLeaves( p->pGia, pObj );
+        Gia_ManForEachObjVec( vLeaves, p->pGia, pLeaf, k )
+        {
+            Lit = Ga2_ObjFindOrAddLit( p, pLeaf, f - Gia_ObjIsRo(p->pGia, pObj) );
+            Vec_IntPush( p->vLits, Lit );
+            if ( Lit < 2 )
+                fUseStatic = 0;
+        }
+        if ( fUseStatic || Gia_ObjIsRo(p->pGia, pObj) )
+            Ga2_ManCnfAddStatic( p->pSat, Ga2_ObjCnf0(p, pObj), Ga2_ObjCnf1(p, pObj), Vec_IntArray(p->vLits), iLitOut, fUseId ? Gia_ObjId(p->pGia, pObj) : -1 );
+        else
+        {
+            unsigned uTruth = Ga2_ObjComputeTruthSpecial( p->pGia, pObj, vLeaves, p->vLits );
+            Ga2_ManCnfAddDynamic( p, uTruth & 0xFFFF, Vec_IntArray(p->vLits), iLitOut, Gia_ObjId(p->pGia, pObj) );
+        }
+    }
+}
+static inline void Ga2_ManAddToAbsOneDynamic( Ga2_Man_t * p, Gia_Obj_t * pObj, int f )
+{
+//    int Id = Gia_ObjId(p->pGia, pObj);
+    Vec_Int_t * vLeaves;
+    Gia_Obj_t * pLeaf;
+    unsigned uTruth;
+    int i, Lit;
+
+    assert( Ga2_ObjIsAbs0(p, pObj) );
+    assert( Gia_ObjIsConst0(pObj) || Gia_ObjIsRo(p->pGia, pObj) || Gia_ObjIsAnd(pObj) );
+    if ( Gia_ObjIsConst0(pObj) || (f == 0 && Gia_ObjIsRo(p->pGia, pObj)) )
+    {
+        Ga2_ObjAddLit( p, pObj, f, 0 );
+    }
+    else if ( Gia_ObjIsRo(p->pGia, pObj) )
+    {
+        // if flop is included in the abstraction, but its driver is not
+        // flop input driver has no variable assigned -- we assign it here
+        pLeaf = Gia_ObjRoToRi( p->pGia, pObj );
+        Lit = Ga2_ObjFindOrAddLit( p, Gia_ObjFanin0(pLeaf), f-1 );
+        assert( Lit >= 0 );
+        Lit = Abc_LitNotCond( Lit, Gia_ObjFaninC0(pLeaf) );
+        Ga2_ObjAddLit( p, pObj, f, Lit );
+    }
+    else
+    {
+        assert( Gia_ObjIsAnd(pObj) );
+        Vec_IntClear( p->vLits );
+        vLeaves = Ga2_ObjLeaves( p->pGia, pObj );
+        Gia_ManForEachObjVec( vLeaves, p->pGia, pLeaf, i )
+        {
+            if ( Ga2_ObjIsAbs0(p, pLeaf) )      // belongs to original abstraction
+            {
+                Lit = Ga2_ObjFindLit( p, pLeaf, f );
+                assert( Lit >= 0 );
+            }
+            else if ( Ga2_ObjIsLeaf0(p, pLeaf) ) // belongs to original PPIs
+            {
+                Lit = Ga2_ObjFindLit( p, pLeaf, f );
+//                Lit = Ga2_ObjFindOrAddLit( p, pLeaf, f );
+                if ( Lit == -1 )
+                {
+                    Lit = GA2_BIG_NUM + 2*i;
+//                    assert( 0 );
+                }
+            }
+            else assert( 0 );
+            Vec_IntPush( p->vLits, Lit );
+        }
+
+        // minimize truth table
+        uTruth = Ga2_ObjComputeTruthSpecial( p->pGia, pObj, vLeaves, p->vLits );
+        if ( uTruth == 0 || uTruth == ~0 ) // const 0 / 1
+        {
+            Lit = (uTruth > 0);
+            Ga2_ObjAddLit( p, pObj, f, Lit );
+        }
+        else if ( uTruth == 0xAAAAAAAA || uTruth == 0x55555555 )  // buffer / inverter
+        {
+            Lit = Vec_IntEntry( p->vLits, 0 );
+            if ( Lit >= GA2_BIG_NUM )
+            {
+                pLeaf = Gia_ManObj( p->pGia, Vec_IntEntry(vLeaves, (Lit-GA2_BIG_NUM)/2) );
+                Lit = Ga2_ObjFindLit( p, pLeaf, f );
+                assert( Lit == -1 );
+                Lit = Ga2_ObjFindOrAddLit( p, pLeaf, f );
+            }
+            assert( Lit >= 0 );
+            Lit = Abc_LitNotCond( Lit, uTruth == 0x55555555 );
+            Ga2_ObjAddLit( p, pObj, f, Lit );
+            assert( Lit < 10000000 );
+        }
+        else
+        {
+            assert( Vec_IntSize(p->vLits) > 1 && Vec_IntSize(p->vLits) < 6 );
+            // replace literals
+            Vec_IntForEachEntry( p->vLits, Lit, i )
+            {
+                if ( Lit >= GA2_BIG_NUM )
+                {
+                    pLeaf = Gia_ManObj( p->pGia, Vec_IntEntry(vLeaves, (Lit-GA2_BIG_NUM)/2) );
+                    Lit = Ga2_ObjFindLit( p, pLeaf, f );
+                    assert( Lit == -1 );
+                    Lit = Ga2_ObjFindOrAddLit( p, pLeaf, f );
+                    Vec_IntWriteEntry( p->vLits, i, Lit );
+                }
+                assert( Lit < 10000000 );
+            }
+
+            // add new nodes
+            if ( Vec_IntSize(p->vLits) == 5 )
+            {
+                Vec_IntClear( p->vLits );
+                Gia_ManForEachObjVec( vLeaves, p->pGia, pLeaf, i )
+                    Vec_IntPush( p->vLits, Ga2_ObjFindOrAddLit( p, pLeaf, f ) );
+                Lit = Ga2_ObjFindOrAddLit(p, pObj, f);
+                Ga2_ManCnfAddStatic( p->pSat, Ga2_ObjCnf0(p, pObj), Ga2_ObjCnf1(p, pObj), Vec_IntArray(p->vLits), Lit, -1 );
+            }
+            else
+            {
+//                int fUseHash = 1;
+                if ( !p->pPars->fSkipHash )
+                {
+                    int * pLookup, nSize = Vec_IntSize(p->vLits);
+                    assert( Vec_IntSize(p->vLits) < 5 );
+                    assert( Vec_IntEntry(p->vLits, 0) <= Vec_IntEntryLast(p->vLits) );
+                    assert( Ga2_ObjFindLit(p, pObj, f) == -1 );
+                    for ( i = Vec_IntSize(p->vLits); i < 4; i++ )
+                        Vec_IntPush( p->vLits, GA2_BIG_NUM );
+                    Vec_IntPush( p->vLits, (int)uTruth );
+                    assert( Vec_IntSize(p->vLits) == 5 );
+
+                    // perform structural hashing here!!!
+                    pLookup = Saig_ManBmcLookup( p, Vec_IntArray(p->vLits) );
+                    if ( *pLookup == 0 )
+                    {
+                        *pLookup = Ga2_ObjFindOrAddLit(p, pObj, f);
+                        Vec_IntShrink( p->vLits, nSize );
+                        Ga2_ManCnfAddDynamic( p, uTruth & 0xFFFF, Vec_IntArray(p->vLits), *pLookup, -1 );
+                    }
+                    else
+                        Ga2_ObjAddLit( p, pObj, f, *pLookup );
+
+                }
+                else
+                {
+                    Lit = Ga2_ObjFindOrAddLit(p, pObj, f);
+                    Ga2_ManCnfAddDynamic( p, uTruth & 0xFFFF, Vec_IntArray(p->vLits), Lit, -1 );
+                }
+            }
+        }
+    }
+}
+
+void Ga2_ManAddAbsClauses( Ga2_Man_t * p, int f )
+{
+    int fSimple = 0;
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObjVec( p->vValues, p->pGia, pObj, i )
+    {
+        if ( i == p->LimAbs )
+            break;
+        if ( fSimple )
+            Ga2_ManAddToAbsOneStatic( p, pObj, f, 0 );
+        else
+            Ga2_ManAddToAbsOneDynamic( p, pObj, f );
+    }
+    Gia_ManForEachObjVec( p->vAbs, p->pGia, pObj, i )
+        if ( i >= p->LimAbs )
+            Ga2_ManAddToAbsOneStatic( p, pObj, f, 1 );
+//    sat_solver2_simplify( p->pSat );
+}
+
+void Ga2_ManAddToAbs( Ga2_Man_t * p, Vec_Int_t * vToAdd )
+{
+    Vec_Int_t * vLeaves;
+    Gia_Obj_t * pObj, * pFanin;
+    int f, i, k;
+    // add abstraction objects
+    Gia_ManForEachObjVec( vToAdd, p->pGia, pObj, i )
+    {
+        Ga2_ManSetupNode( p, pObj, 1 );
+        if ( p->pSat->pPrf2 )
+            Vec_IntWriteEntry( p->vProofIds, Gia_ObjId(p->pGia, pObj), p->nProofIds++ );
+    }
+    // add PPI objects
+    Gia_ManForEachObjVec( vToAdd, p->pGia, pObj, i )
+    {
+        vLeaves = Ga2_ObjLeaves( p->pGia, pObj );
+        Gia_ManForEachObjVec( vLeaves, p->pGia, pFanin, k )
+            if ( Ga2_ObjId( p, pFanin ) == -1 )
+                Ga2_ManSetupNode( p, pFanin, 0 );
+    }
+    // add new clauses to the timeframes
+    for ( f = 0; f <= p->pPars->iFrame; f++ )
+    {
+        Vec_IntFillExtra( Ga2_MapFrameMap(p, f), Vec_IntSize(p->vValues), -1 );
+        Gia_ManForEachObjVec( vToAdd, p->pGia, pObj, i )
+            Ga2_ManAddToAbsOneStatic( p, pObj, f, 1 );
+    }
+//    sat_solver2_simplify( p->pSat );
+}
+
+void Ga2_ManShrinkAbs( Ga2_Man_t * p, int nAbs, int nValues, int nSatVars )
+{
+    Vec_Int_t * vMap;
+    Gia_Obj_t * pObj;
+    int i, k, Entry;
+    assert( nAbs > 0 );
+    assert( nValues > 0 );
+    assert( nSatVars > 0 );
+    // shrink abstraction
+    Gia_ManForEachObjVec( p->vAbs, p->pGia, pObj, i )
+    {
+        if ( !i ) continue;
+        assert( Ga2_ObjCnf0(p, pObj) != NULL );
+        assert( Ga2_ObjCnf1(p, pObj) != NULL );
+        if ( i < nAbs )
+            continue;
+        Vec_IntFree( Ga2_ObjCnf0(p, pObj) );
+        Vec_IntFree( Ga2_ObjCnf1(p, pObj) );
+        Vec_PtrWriteEntry( p->vCnfs, 2 * Ga2_ObjId(p,pObj),     NULL );    
+        Vec_PtrWriteEntry( p->vCnfs, 2 * Ga2_ObjId(p,pObj) + 1, NULL );
+    }
+    Vec_IntShrink( p->vAbs, nAbs );
+    // shrink values
+    Gia_ManForEachObjVec( p->vValues, p->pGia, pObj, i )
+    {
+        assert( Ga2_ObjId(p,pObj) >= 0 );
+        if ( i < nValues )
+            continue;
+        Ga2_ObjSetId( p, pObj, -1 );
+    }
+    Vec_IntShrink( p->vValues, nValues );
+    Vec_PtrShrink( p->vCnfs, 2 * nValues );
+    // hack to clear constant
+    if ( nValues == 1 )
+        nValues = 0;
+    // clean mapping for each timeframe
+    Vec_PtrForEachEntry( Vec_Int_t *, p->vId2Lit, vMap, i )
+    {
+        Vec_IntShrink( vMap, nValues );
+        Vec_IntForEachEntryStart( vMap, Entry, k, p->LimAbs )
+            if ( Entry >= 2*nSatVars )
+                Vec_IntWriteEntry( vMap, k, -1 );
+    }
+    // shrink SAT variables
+    p->nSatVars = nSatVars;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ga2_ManAbsTranslate_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vClasses, int fFirst )
+{
+    if ( pObj->fPhase && !fFirst )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    Ga2_ManAbsTranslate_rec( p, Gia_ObjFanin0(pObj), vClasses, 0 );
+    Ga2_ManAbsTranslate_rec( p, Gia_ObjFanin1(pObj), vClasses, 0 );
+    Vec_IntWriteEntry( vClasses, Gia_ObjId(p, pObj), 1 );
+}
+
+Vec_Int_t * Ga2_ManAbsTranslate( Ga2_Man_t * p )
+{
+    Vec_Int_t * vGateClasses;
+    Gia_Obj_t * pObj;
+    int i;
+    vGateClasses = Vec_IntStart( Gia_ManObjNum(p->pGia) );
+    Vec_IntWriteEntry( vGateClasses, 0, 1 );
+    Gia_ManForEachObjVec( p->vAbs, p->pGia, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+            Ga2_ManAbsTranslate_rec( p->pGia, pObj, vGateClasses, 1 );
+        else if ( Gia_ObjIsRo(p->pGia, pObj) )
+            Vec_IntWriteEntry( vGateClasses, Gia_ObjId(p->pGia, pObj), 1 );
+        else if ( !Gia_ObjIsConst0(pObj) )
+            assert( 0 );
+//        Gia_ObjPrint( p->pGia, pObj );
+    }
+    return vGateClasses;
+}
+
+Vec_Int_t * Ga2_ManAbsDerive( Gia_Man_t * p )
+{
+    Vec_Int_t * vToAdd;
+    Gia_Obj_t * pObj;
+    int i;
+    vToAdd = Vec_IntAlloc( 1000 );
+    Gia_ManForEachRo( p, pObj, i )
+        if ( pObj->fPhase && Vec_IntEntry(p->vGateClasses, Gia_ObjId(p, pObj)) )
+            Vec_IntPush( vToAdd, Gia_ObjId(p, pObj) );
+    Gia_ManForEachAnd( p, pObj, i )
+        if ( pObj->fPhase && Vec_IntEntry(p->vGateClasses, i) )
+            Vec_IntPush( vToAdd, i );
+    return vToAdd;
+}
+
+void Ga2_ManRestart( Ga2_Man_t * p )
+{
+    Vec_Int_t * vToAdd;
+    int Lit = 1;
+    assert( p->pGia != NULL && p->pGia->vGateClasses != NULL );
+    assert( Gia_ManPi(p->pGia, 0)->fPhase ); // marks are set
+    // clear SAT variable numbers (begin with 1)
+    if ( p->pSat ) sat_solver2_delete( p->pSat );
+    p->pSat      = sat_solver2_new();
+    p->pSat->nLearntStart = p->pPars->nLearnedStart;
+    p->pSat->nLearntDelta = p->pPars->nLearnedDelta;
+    p->pSat->nLearntRatio = p->pPars->nLearnedPerce;
+    p->pSat->nLearntMax   = p->pSat->nLearntStart;
+    // add clause x0 = 0  (lit0 = 1; lit1 = 0)
+    sat_solver2_addclause( p->pSat, &Lit, &Lit + 1, -1 );
+    // remove previous abstraction
+    Ga2_ManShrinkAbs( p, 1, 1, 1 );
+    // start new abstraction
+    vToAdd = Ga2_ManAbsDerive( p->pGia );
+    assert( p->pSat->pPrf2 == NULL );
+    assert( p->pPars->iFrame < 0 );
+    Ga2_ManAddToAbs( p, vToAdd );
+    Vec_IntFree( vToAdd );
+    p->LimAbs = Vec_IntSize(p->vAbs);
+    p->LimPpi = Vec_IntSize(p->vValues);
+    // set runtime limit
+    if ( p->pPars->nTimeOut )
+        sat_solver2_set_runtime_limit( p->pSat, p->pPars->nTimeOut * CLOCKS_PER_SEC + p->timeStart );
+    // clean the hash table
+    memset( p->pTable, 0, 6 * sizeof(int) * p->nTable );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Ga2_ObjSatValue( Ga2_Man_t * p, Gia_Obj_t * pObj, int f )
+{
+    int Lit = Ga2_ObjFindLit( p, pObj, f );
+    assert( !Gia_ObjIsConst0(pObj) );
+    if ( Lit == -1 )
+        return 0;
+    if ( Abc_Lit2Var(Lit) >= p->pSat->size )
+        return 0;
+    return Abc_LitIsCompl(Lit) ^ sat_solver2_var_value( p->pSat, Abc_Lit2Var(Lit) );
+}
+Abc_Cex_t * Ga2_ManDeriveCex( Ga2_Man_t * p, Vec_Int_t * vPis )
+{
+    Abc_Cex_t * pCex;
+    Gia_Obj_t * pObj;
+    int i, f;
+    pCex = Abc_CexAlloc( Gia_ManRegNum(p->pGia), Gia_ManPiNum(p->pGia), p->pPars->iFrame+1 );
+    pCex->iPo = 0;
+    pCex->iFrame = p->pPars->iFrame;
+    Gia_ManForEachObjVec( vPis, p->pGia, pObj, i )
+    {
+        if ( !Gia_ObjIsPi(p->pGia, pObj) )
+            continue;
+        assert( Gia_ObjIsPi(p->pGia, pObj) );
+        for ( f = 0; f <= pCex->iFrame; f++ )
+            if ( Ga2_ObjSatValue( p, pObj, f ) )
+                Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + Gia_ObjCioId(pObj) );
+    }
+    return pCex;
+} 
+void Ga2_ManRefinePrint( Ga2_Man_t * p, Vec_Int_t * vVec )
+{
+    Gia_Obj_t * pObj, * pFanin;
+    int i, k;
+    printf( "\n         Unsat core: \n" );
+    Gia_ManForEachObjVec( vVec, p->pGia, pObj, i )
+    {
+        Vec_Int_t * vLeaves = Ga2_ObjLeaves( p->pGia, pObj );
+        printf( "%12d : ", i );
+        printf( "Obj =%6d ", Gia_ObjId(p->pGia, pObj) );
+        if ( Gia_ObjIsRo(p->pGia, pObj) )
+            printf( "ff " );
+        else
+            printf( "   " );
+        if ( Ga2_ObjIsAbs0(p, pObj) )
+            printf( "a " );
+        else if ( Ga2_ObjIsLeaf0(p, pObj) )
+            printf( "l " );
+        else 
+            printf( "  " );
+        printf( "Fanins: " );
+        Gia_ManForEachObjVec( vLeaves, p->pGia, pFanin, k )
+        {
+            printf( "%6d ", Gia_ObjId(p->pGia, pFanin) );
+            if ( Gia_ObjIsRo(p->pGia, pFanin) )
+                printf( "ff " );
+            else
+                printf( "   " );
+            if ( Ga2_ObjIsAbs0(p, pFanin) )
+                printf( "a " );
+            else if ( Ga2_ObjIsLeaf0(p, pFanin) )
+                printf( "l " );
+            else
+                printf( "  " );
+        }
+        printf( "\n" );
+    }
+}
+void Ga2_ManRefinePrintPPis( Ga2_Man_t * p )
+{
+    Vec_Int_t * vVec = Vec_IntAlloc( 100 );
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObjVec( p->vValues, p->pGia, pObj, i )
+    {
+        if ( !i ) continue;
+        if ( Ga2_ObjIsAbs(p, pObj) )
+            continue;
+        assert( pObj->fPhase );
+        assert( Ga2_ObjIsLeaf(p, pObj) );
+        assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsCi(pObj) );
+        Vec_IntPush( vVec, Gia_ObjId(p->pGia, pObj) );
+    }
+    printf( "        Current PPIs (%d): ", Vec_IntSize(vVec) );
+    Vec_IntSort( vVec, 1 );
+    Gia_ManForEachObjVec( vVec, p->pGia, pObj, i )
+        printf( "%d ", Gia_ObjId(p->pGia, pObj) );
+    printf( "\n" );
+    Vec_IntFree( vVec );
+}
+
+
+void Ga2_GlaPrepareCexAndMap( Ga2_Man_t * p, Abc_Cex_t ** ppCex, Vec_Int_t ** pvMaps )
+{
+    Abc_Cex_t * pCex;
+    Vec_Int_t * vMap;
+    Gia_Obj_t * pObj;
+    int f, i, k;
+/*
+    Gia_ManForEachObj( p->pGia, pObj, i )
+        if ( Ga2_ObjId(p, pObj) >= 0 )
+            assert( Vec_IntEntry(p->vValues, Ga2_ObjId(p, pObj)) == i );
+*/
+    // find PIs and PPIs
+    vMap = Vec_IntAlloc( 1000 );
+    Gia_ManForEachObjVec( p->vValues, p->pGia, pObj, i )
+    {
+        if ( !i ) continue;
+        if ( Ga2_ObjIsAbs(p, pObj) )
+            continue;
+        assert( pObj->fPhase );
+        assert( Ga2_ObjIsLeaf(p, pObj) );
+        assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsCi(pObj) );
+        Vec_IntPush( vMap, Gia_ObjId(p->pGia, pObj) );
+    }
+    // derive counter-example
+    pCex = Abc_CexAlloc( 0, Vec_IntSize(vMap), p->pPars->iFrame+1 );
+    pCex->iFrame = p->pPars->iFrame;
+    for ( f = 0; f <= p->pPars->iFrame; f++ )
+        Gia_ManForEachObjVec( vMap, p->pGia, pObj, k )
+            if ( Ga2_ObjSatValue( p, pObj, f ) )
+                Abc_InfoSetBit( pCex->pData, f * Vec_IntSize(vMap) + k );
+    *pvMaps = vMap;
+    *ppCex = pCex;
+}
+Vec_Int_t * Ga2_ManRefine( Ga2_Man_t * p )
+{
+    Abc_Cex_t * pCex;
+    Vec_Int_t * vMap, * vVec;
+    Gia_Obj_t * pObj;
+    int i, k;
+    if ( p->pPars->fAddLayer )
+    {
+        // use simplified refinement strategy, which adds logic near at PPI without finding important ones
+        vVec = Vec_IntAlloc( 100 );
+        Gia_ManForEachObjVec( p->vValues, p->pGia, pObj, i )
+        {
+            if ( !i ) continue;
+            if ( Ga2_ObjIsAbs(p, pObj) )
+                continue;
+            assert( pObj->fPhase );
+            assert( Ga2_ObjIsLeaf(p, pObj) );
+            assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsCi(pObj) );
+            if ( Gia_ObjIsPi(p->pGia, pObj) )
+                continue;
+            Vec_IntPush( vVec, Gia_ObjId(p->pGia, pObj) );
+        }
+        p->nObjAdded += Vec_IntSize(vVec);
+        return vVec;
+    }
+    Ga2_GlaPrepareCexAndMap( p, &pCex, &vMap );
+ //    Rf2_ManRefine( p->pRf2, pCex, vMap, p->pPars->fPropFanout, 1 );
+    vVec = Rnm_ManRefine( p->pRnm, pCex, vMap, p->pPars->fPropFanout, p->pPars->fNewRefine, 1 );
+//    printf( "Refinement %d\n", Vec_IntSize(vVec) );
+    Abc_CexFree( pCex );
+    if ( Vec_IntSize(vVec) == 0 )
+    {
+        Vec_IntFree( vVec );
+        Abc_CexFreeP( &p->pGia->pCexSeq );
+        p->pGia->pCexSeq = Ga2_ManDeriveCex( p, vMap );
+        Vec_IntFree( vMap );
+        return NULL;
+    }
+    Vec_IntFree( vMap );
+    // remove those already added
+    k = 0;
+    Gia_ManForEachObjVec( vVec, p->pGia, pObj, i )
+        if ( !Ga2_ObjIsAbs(p, pObj) )
+            Vec_IntWriteEntry( vVec, k++, Gia_ObjId(p->pGia, pObj) );
+    Vec_IntShrink( vVec, k );
+
+    // these objects should be PPIs that are not abstracted yet
+    Gia_ManForEachObjVec( vVec, p->pGia, pObj, i )
+        assert( pObj->fPhase );//&& Ga2_ObjIsLeaf(p, pObj) );
+    p->nObjAdded += Vec_IntSize(vVec);
+    return vVec;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ga2_GlaAbsCount( Ga2_Man_t * p, int fRo, int fAnd )
+{
+    Gia_Obj_t * pObj;
+    int i, Counter = 0;
+    if ( fRo )
+        Gia_ManForEachObjVec( p->vAbs, p->pGia, pObj, i )
+            Counter += Gia_ObjIsRo(p->pGia, pObj);
+    else if ( fAnd )
+        Gia_ManForEachObjVec( p->vAbs, p->pGia, pObj, i )
+            Counter += Gia_ObjIsAnd(pObj);
+    else assert( 0 );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ga2_ManAbsPrintFrame( Ga2_Man_t * p, int nFrames, int nConfls, int nCexes, abctime Time, int fFinal )
+{
+    int fUseNewLine = ((fFinal && nCexes) || p->pPars->fVeryVerbose);
+    if ( Abc_FrameIsBatchMode() && !fUseNewLine )
+        return;
+    p->fUseNewLine = fUseNewLine;
+    Abc_Print( 1, "%4d :", nFrames );
+    Abc_Print( 1, "%4d", Abc_MinInt(100, 100 * Vec_IntSize(p->vAbs) / p->nMarked) ); 
+    Abc_Print( 1, "%6d", Vec_IntSize(p->vAbs) );
+    Abc_Print( 1, "%5d", Vec_IntSize(p->vValues)-Vec_IntSize(p->vAbs)-1 );
+    Abc_Print( 1, "%5d", Ga2_GlaAbsCount(p, 1, 0) );
+    Abc_Print( 1, "%6d", Ga2_GlaAbsCount(p, 0, 1) );
+    Abc_Print( 1, "%8d", nConfls );
+    if ( nCexes == 0 )
+        Abc_Print( 1, "%5c", '-' ); 
+    else
+        Abc_Print( 1, "%5d", nCexes ); 
+    Abc_PrintInt( sat_solver2_nvars(p->pSat) );
+    Abc_PrintInt( sat_solver2_nclauses(p->pSat) );
+    Abc_PrintInt( sat_solver2_nlearnts(p->pSat) );
+    Abc_Print( 1, "%9.2f sec", 1.0*Time/CLOCKS_PER_SEC );
+    Abc_Print( 1, "%5.0f MB", (sat_solver2_memory_proof(p->pSat) + sat_solver2_memory(p->pSat, 0)) / (1<<20) );
+    Abc_Print( 1, "%s", fUseNewLine ? "\n" : "\r" );
+    fflush( stdout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Send abstracted model or send cancel.]
+
+  Description [Counter-example will be sent automatically when &vta terminates.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Ga2_GlaGetFileName( Ga2_Man_t * p, int fAbs )
+{
+    static char * pFileNameDef = "glabs.aig";
+    if ( p->pPars->pFileVabs )
+        return p->pPars->pFileVabs;
+    if ( p->pGia->pSpec )
+    {
+        if ( fAbs )
+            return Extra_FileNameGenericAppend( p->pGia->pSpec, "_abs.aig");
+        else
+            return Extra_FileNameGenericAppend( p->pGia->pSpec, "_gla.aig");
+    }
+    return pFileNameDef;
+}
+
+void Ga2_GlaDumpAbsracted( Ga2_Man_t * p, int fVerbose )
+{
+    char * pFileName;
+    assert( p->pPars->fDumpMabs || p->pPars->fDumpVabs );
+    if ( p->pPars->fDumpMabs )
+    {
+        pFileName = Ga2_GlaGetFileName(p, 0);
+        if ( fVerbose )
+            Abc_Print( 1, "Dumping miter with abstraction map into file \"%s\"...\n", pFileName );
+        // dump abstraction map
+        Vec_IntFreeP( &p->pGia->vGateClasses );
+        p->pGia->vGateClasses = Ga2_ManAbsTranslate( p );
+        Gia_AigerWrite( p->pGia, pFileName, 0, 0 );
+    }
+    else if ( p->pPars->fDumpVabs )
+    {
+        Vec_Int_t * vGateClasses;
+        Gia_Man_t * pAbs;
+        pFileName = Ga2_GlaGetFileName(p, 1);
+        if ( fVerbose )
+            Abc_Print( 1, "Dumping abstracted model into file \"%s\"...\n", pFileName );
+        // dump absracted model
+        vGateClasses = Ga2_ManAbsTranslate( p );
+        pAbs = Gia_ManDupAbsGates( p->pGia, vGateClasses );
+        Gia_ManCleanValue( p->pGia );
+        Gia_AigerWrite( pAbs, pFileName, 0, 0 );
+        Gia_ManStop( pAbs );
+        Vec_IntFreeP( &vGateClasses );
+    }
+    else assert( 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Send abstracted model or send cancel.]
+
+  Description [Counter-example will be sent automatically when &vta terminates.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_Ga2SendAbsracted( Ga2_Man_t * p, int fVerbose )
+{
+    Gia_Man_t * pAbs;
+    Vec_Int_t * vGateClasses;
+    assert( Abc_FrameIsBridgeMode() );
+//    if ( fVerbose )
+//        Abc_Print( 1, "Sending abstracted model...\n" );
+    // create abstraction (value of p->pGia is not used here)
+    vGateClasses = Ga2_ManAbsTranslate( p );
+    pAbs = Gia_ManDupAbsGates( p->pGia, vGateClasses );
+    Vec_IntFreeP( &vGateClasses );
+    Gia_ManCleanValue( p->pGia );
+    // send it out
+    Gia_ManToBridgeAbsNetlist( stdout, pAbs, BRIDGE_ABS_NETLIST );
+    Gia_ManStop( pAbs );
+}
+void Gia_Ga2SendCancel( Ga2_Man_t * p, int fVerbose )
+{
+    extern int Gia_ManToBridgeBadAbs( FILE * pFile );
+    assert( Abc_FrameIsBridgeMode() );
+//    if ( fVerbose )
+//        Abc_Print( 1, "Cancelling previously sent model...\n" );
+    Gia_ManToBridgeBadAbs( stdout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs gate-level abstraction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManPerformGla( Gia_Man_t * pAig, Abs_Par_t * pPars )
+{
+    int fUseSecondCore = 1;
+    Ga2_Man_t * p;
+    Vec_Int_t * vCore, * vPPis;
+    abctime clk2, clk = Abc_Clock();
+    int Status = l_Undef, RetValue = -1, iFrameTryToProve = -1, fOneIsSent = 0;
+    int i, c, f, Lit;
+    pPars->iFrame = -1;
+    // check trivial case 
+    assert( Gia_ManPoNum(pAig) == 1 ); 
+    ABC_FREE( pAig->pCexSeq );
+    if ( Gia_ObjIsConst0(Gia_ObjFanin0(Gia_ManPo(pAig,0))) )
+    {
+        if ( !Gia_ObjFaninC0(Gia_ManPo(pAig,0)) )
+        {
+            Abc_Print( 1, "Sequential miter is trivially UNSAT.\n" );
+            return 1;
+        }
+        pAig->pCexSeq = Abc_CexMakeTriv( Gia_ManRegNum(pAig), Gia_ManPiNum(pAig), 1, 0 );
+        Abc_Print( 1, "Sequential miter is trivially SAT.\n" );
+        return 0;
+    }
+    // create gate classes if not given
+    if ( pAig->vGateClasses == NULL )
+    {
+        pAig->vGateClasses = Vec_IntStart( Gia_ManObjNum(pAig) );
+        Vec_IntWriteEntry( pAig->vGateClasses, 0, 1 );
+        Vec_IntWriteEntry( pAig->vGateClasses, Gia_ObjFaninId0p(pAig, Gia_ManPo(pAig, 0)), 1 );
+    }
+    // start the manager
+    p = Ga2_ManStart( pAig, pPars );
+    p->timeInit = Abc_Clock() - clk;
+    // perform initial abstraction
+    if ( p->pPars->fVerbose )
+    {
+        Abc_Print( 1, "Running gate-level abstraction (GLA) with the following parameters:\n" );
+        Abc_Print( 1, "FrameMax = %d  ConfMax = %d  Timeout = %d  Limit = %d %%  Limit2 = %d %%  RatioMax = %d %%\n", 
+            pPars->nFramesMax, pPars->nConfLimit, pPars->nTimeOut, pPars->nRatioMin, pPars->nRatioMin2, pPars->nRatioMax );
+        Abc_Print( 1, "LrnStart = %d  LrnDelta = %d  LrnRatio = %d %%  Skip = %d  SimpleCNF = %d  Dump = %d\n", 
+            pPars->nLearnedStart, pPars->nLearnedDelta, pPars->nLearnedPerce, pPars->fUseSkip, pPars->fUseSimple, pPars->fDumpVabs|pPars->fDumpMabs );
+        if ( pPars->fDumpVabs || pPars->fDumpMabs )
+            Abc_Print( 1, "%s will be dumped into file \"%s\".\n", 
+                pPars->fDumpVabs ? "Abstracted model" : "Miter with abstraction map",
+                Ga2_GlaGetFileName(p, pPars->fDumpVabs) );
+        Abc_Print( 1, " Frame   %%   Abs  PPI   FF   LUT   Confl  Cex   Vars   Clas   Lrns     Time        Mem\n" );
+    }
+    // iterate unrolling
+    for ( i = f = 0; !pPars->nFramesMax || f < pPars->nFramesMax; i++ )
+    {
+        int nAbsOld;
+        // remember the timeframe
+        p->pPars->iFrame = -1;
+        // create new SAT solver
+        Ga2_ManRestart( p );
+        // remember abstraction size after the last restart
+        nAbsOld = Vec_IntSize(p->vAbs);
+        // unroll the circuit
+        for ( f = 0; !pPars->nFramesMax || f < pPars->nFramesMax; f++ )
+        {
+            // remember current limits
+            int nConflsBeg = sat_solver2_nconflicts(p->pSat);
+            int nAbs       = Vec_IntSize(p->vAbs);
+            int nValues    = Vec_IntSize(p->vValues);
+            int nVarsOld;
+            // remember the timeframe
+            p->pPars->iFrame = f;
+            // extend and clear storage
+            if ( f == Vec_PtrSize(p->vId2Lit) )
+                Vec_PtrPush( p->vId2Lit, Vec_IntAlloc(0) );
+            Vec_IntFillExtra( Ga2_MapFrameMap(p, f), Vec_IntSize(p->vValues), -1 );
+            // add static clauses to this timeframe
+            Ga2_ManAddAbsClauses( p, f );
+            // skip checking if skipcheck is enabled (&gla -s)
+            if ( p->pPars->fUseSkip && f <= p->pPars->iFrameProved )
+                continue;
+            // skip checking if we need to skip several starting frames (&gla -S <num>)
+            if ( p->pPars->nFramesStart && f <= p->pPars->nFramesStart )
+                continue;
+            // get the output literal
+//            Lit = Ga2_ManUnroll_rec( p, Gia_ManPo(pAig,0), f );
+            Lit = Ga2_ObjFindLit( p, Gia_ObjFanin0(Gia_ManPo(pAig,0)), f );
+            assert( Lit >= 0 );
+            Lit = Abc_LitNotCond( Lit, Gia_ObjFaninC0(Gia_ManPo(pAig,0)) );
+            if ( Lit == 0 )
+                continue;
+            assert( Lit > 1 );
+            // check for counter-examples
+            if ( p->nSatVars > sat_solver2_nvars(p->pSat) )
+                sat_solver2_setnvars( p->pSat, p->nSatVars );
+            nVarsOld = p->nSatVars;
+            for ( c = 0; ; c++ )
+            {
+                // consider the special case when the target literal is implied false
+                // by implications which happened as a result of previous refinements
+                // note that incremental UNSAT core cannot be computed because there is no learned clauses
+                // in this case, we will assume that UNSAT core cannot reduce the problem
+                if ( var_is_assigned(p->pSat, Abc_Lit2Var(Lit)) )
+                {
+                    Prf_ManStopP( &p->pSat->pPrf2 );
+                    break;
+                }
+                // perform SAT solving
+                clk2 = Abc_Clock();
+                Status = sat_solver2_solve( p->pSat, &Lit, &Lit+1, (ABC_INT64_T)pPars->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+                if ( Status == l_True ) // perform refinement
+                {
+                    p->nCexes++;
+                    p->timeSat += Abc_Clock() - clk2;
+
+                    // cancel old one if it was sent
+                    if ( Abc_FrameIsBridgeMode() && fOneIsSent )
+                    {
+                        Gia_Ga2SendCancel( p, pPars->fVerbose );
+                        fOneIsSent = 0;
+                    }
+                    if ( iFrameTryToProve >= 0 )
+                    {
+                        Gia_GlaProveCancel( pPars->fVerbose );
+                        iFrameTryToProve = -1;
+                    }
+
+                    // perform refinement
+                    clk2 = Abc_Clock();
+                    Rnm_ManSetRefId( p->pRnm, c );
+                    vPPis = Ga2_ManRefine( p );
+                    p->timeCex += Abc_Clock() - clk2;
+                    if ( vPPis == NULL )
+                    {
+                        if ( pPars->fVerbose )
+                            Ga2_ManAbsPrintFrame( p, f, sat_solver2_nconflicts(p->pSat)-nConflsBeg, c, Abc_Clock() - clk, 1 );
+                        goto finish;
+                    }
+
+                    if ( c == 0 )
+                    {
+//                        Ga2_ManRefinePrintPPis( p );
+                        // create bookmark to be used for rollback
+                        assert( nVarsOld == p->pSat->size );
+                        sat_solver2_bookmark( p->pSat );
+                        // start incremental proof manager
+                        assert( p->pSat->pPrf2 == NULL );
+                        p->pSat->pPrf2 = Prf_ManAlloc();
+                        if ( p->pSat->pPrf2 )
+                        {
+                            p->nProofIds = 0;
+                            Vec_IntFill( p->vProofIds, Gia_ManObjNum(p->pGia), -1 );
+                            Prf_ManRestart( p->pSat->pPrf2, p->vProofIds, sat_solver2_nlearnts(p->pSat), Vec_IntSize(vPPis) );
+                        }
+                    }
+                    else
+                    {
+                        // resize the proof logger
+                        if ( p->pSat->pPrf2 )
+                            Prf_ManGrow( p->pSat->pPrf2, p->nProofIds + Vec_IntSize(vPPis) );
+                    }
+
+                    Ga2_ManAddToAbs( p, vPPis );
+                    Vec_IntFree( vPPis );
+                    if ( pPars->fVerbose )
+                        Ga2_ManAbsPrintFrame( p, f, sat_solver2_nconflicts(p->pSat)-nConflsBeg, c+1, Abc_Clock() - clk, 0 );
+                    // check if the number of objects is below limit
+                    if ( pPars->nRatioMin2 && Vec_IntSize(p->vAbs) >= p->nMarked * pPars->nRatioMin2 / 100 )
+                    {
+                        Status = l_Undef;
+                        goto finish;
+                    }
+                    continue;
+                }
+                p->timeUnsat += Abc_Clock() - clk2;
+                if ( Status == l_Undef ) // ran out of resources
+                    goto finish;
+                if ( p->pSat->nRuntimeLimit && Abc_Clock() > p->pSat->nRuntimeLimit ) // timeout
+                    goto finish;
+                if ( c == 0 )
+                {
+                    if ( f > p->pPars->iFrameProved )
+                        p->pPars->nFramesNoChange++;
+                    break;
+                }
+                if ( f > p->pPars->iFrameProved )
+                    p->pPars->nFramesNoChange = 0;
+
+                // derive the core
+                assert( p->pSat->pPrf2 != NULL );
+                vCore = (Vec_Int_t *)Sat_ProofCore( p->pSat );
+                Prf_ManStopP( &p->pSat->pPrf2 );
+                // update the SAT solver
+                sat_solver2_rollback( p->pSat );
+                // reduce abstraction
+                Ga2_ManShrinkAbs( p, nAbs, nValues, nVarsOld );
+
+                // purify UNSAT core
+                if ( fUseSecondCore )
+                {
+//                    int nOldCore = Vec_IntSize(vCore);
+                    // reverse the order of objects in the core
+//                    Vec_IntSort( vCore, 0 );
+//                    Vec_IntPrint( vCore );
+                    // create bookmark to be used for rollback
+                    assert( nVarsOld == p->pSat->size );
+                    sat_solver2_bookmark( p->pSat );
+                    // start incremental proof manager
+                    assert( p->pSat->pPrf2 == NULL );
+                    p->pSat->pPrf2 = Prf_ManAlloc();
+                    if ( p->pSat->pPrf2 )
+                    {
+                        p->nProofIds = 0;
+                        Vec_IntFill( p->vProofIds, Gia_ManObjNum(p->pGia), -1 );
+                        Prf_ManRestart( p->pSat->pPrf2, p->vProofIds, sat_solver2_nlearnts(p->pSat), Vec_IntSize(vCore) );
+
+                        Ga2_ManAddToAbs( p, vCore );
+                        Vec_IntFree( vCore );
+                    }
+                    // run SAT solver
+                    clk2 = Abc_Clock();
+                    Status = sat_solver2_solve( p->pSat, &Lit, &Lit+1, (ABC_INT64_T)pPars->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+                    if ( Status == l_Undef )
+                        goto finish;
+                    assert( Status == l_False );
+                    p->timeUnsat += Abc_Clock() - clk2;
+
+                    // derive the core
+                    assert( p->pSat->pPrf2 != NULL );
+                    vCore = (Vec_Int_t *)Sat_ProofCore( p->pSat );
+                    Prf_ManStopP( &p->pSat->pPrf2 );
+                    // update the SAT solver
+                    sat_solver2_rollback( p->pSat );
+                    // reduce abstraction
+                    Ga2_ManShrinkAbs( p, nAbs, nValues, nVarsOld );
+//                    printf( "\n%4d -> %4d\n", nOldCore, Vec_IntSize(vCore) );
+                }
+
+                Ga2_ManAddToAbs( p, vCore );
+//                Ga2_ManRefinePrint( p, vCore );
+                Vec_IntFree( vCore );
+                break;
+            }
+            // remember the last proved frame
+            if ( p->pPars->iFrameProved < f )
+                p->pPars->iFrameProved = f;
+            // print statistics
+            if ( pPars->fVerbose )
+                Ga2_ManAbsPrintFrame( p, f, sat_solver2_nconflicts(p->pSat)-nConflsBeg, c, Abc_Clock() - clk, 1 );
+            // check if abstraction was proved
+            if ( Gia_GlaProveCheck( pPars->fVerbose ) )
+            {
+                RetValue = 1;
+                goto finish;
+            }
+            if ( c > 0 ) 
+            {
+                if ( p->pPars->fVeryVerbose )
+                    Abc_Print( 1, "\n" );
+                // recompute the abstraction
+                Vec_IntFreeP( &pAig->vGateClasses );
+                pAig->vGateClasses = Ga2_ManAbsTranslate( p );
+                // check if the number of objects is below limit
+                if ( pPars->nRatioMin && Vec_IntSize(p->vAbs) >= p->nMarked * pPars->nRatioMin / 100 )
+                {
+                    Status = l_Undef;
+                    goto finish;
+                }
+            }
+            // check the number of stable frames
+            if ( p->pPars->nFramesNoChange == p->pPars->nFramesNoChangeLim )
+            {
+                // dump the model into file
+                if ( p->pPars->fDumpVabs || p->pPars->fDumpMabs )
+                {
+                    char Command[1000];
+                    Abc_FrameSetStatus( -1 );
+                    Abc_FrameSetCex( NULL );
+                    Abc_FrameSetNFrames( f );
+                    sprintf( Command, "write_status %s", Extra_FileNameGenericAppend((char *)(p->pPars->pFileVabs ? p->pPars->pFileVabs : "glabs.aig"), ".status"));
+                    Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command );
+                    Ga2_GlaDumpAbsracted( p, pPars->fVerbose );
+                }
+                // call the prover
+                if ( p->pPars->fCallProver )
+                {
+                    // cancel old one if it is proving
+                    if ( iFrameTryToProve >= 0 )
+                        Gia_GlaProveCancel( pPars->fVerbose );
+                    // prove new one
+                    Gia_GlaProveAbsracted( pAig, pPars->fSimpProver, pPars->fVeryVerbose );
+                    iFrameTryToProve = f;
+                    p->nPdrCalls++;
+                }
+                // speak to the bridge
+                if ( Abc_FrameIsBridgeMode() )
+                {
+                    // cancel old one if it was sent
+                    if ( fOneIsSent )
+                        Gia_Ga2SendCancel( p, pPars->fVerbose );
+                    // send new one 
+                    Gia_Ga2SendAbsracted( p, pPars->fVerbose );
+                    fOneIsSent = 1;
+                }
+            }
+            // if abstraction grew more than a certain percentage, force a restart
+            if ( pPars->nRatioMax == 0 )
+                continue;
+            if ( c > 0 && (f > 20 || Vec_IntSize(p->vAbs) > 100) && Vec_IntSize(p->vAbs) - nAbsOld >= nAbsOld * pPars->nRatioMax / 100 )
+            {
+                if ( p->pPars->fVerbose )
+                Abc_Print( 1, "Forcing restart because abstraction grew from %d to %d (more than %d %%).\n", 
+                    nAbsOld, Vec_IntSize(p->vAbs), pPars->nRatioMax );
+                break;
+            }
+        }
+    }
+finish:
+    Prf_ManStopP( &p->pSat->pPrf2 );
+    // cancel old one if it is proving
+    if ( iFrameTryToProve >= 0 )
+        Gia_GlaProveCancel( pPars->fVerbose );
+    // analize the results
+    if ( !p->fUseNewLine )
+        Abc_Print( 1, "\n" );
+    if ( RetValue == 1 )
+        Abc_Print( 1, "GLA completed %d frames and proved abstraction derived in frame %d  ", p->pPars->iFrameProved+1, iFrameTryToProve );
+    else if ( pAig->pCexSeq == NULL )
+    {
+        Vec_IntFreeP( &pAig->vGateClasses );
+        pAig->vGateClasses = Ga2_ManAbsTranslate( p );
+        if ( p->pPars->nTimeOut && Abc_Clock() >= p->pSat->nRuntimeLimit ) 
+            Abc_Print( 1, "GLA reached timeout %d sec in frame %d with a %d-stable abstraction.    ", p->pPars->nTimeOut, p->pPars->iFrameProved+1, p->pPars->nFramesNoChange );
+        else if ( pPars->nConfLimit && sat_solver2_nconflicts(p->pSat) >= pPars->nConfLimit )
+            Abc_Print( 1, "GLA exceeded %d conflicts in frame %d with a %d-stable abstraction.  ", pPars->nConfLimit, p->pPars->iFrameProved+1, p->pPars->nFramesNoChange );
+        else if ( pPars->nRatioMin2 && Vec_IntSize(p->vAbs) >= p->nMarked * pPars->nRatioMin2 / 100 )
+            Abc_Print( 1, "GLA found that the size of abstraction exceeds %d %% in frame %d during refinement.  ", pPars->nRatioMin2, p->pPars->iFrameProved+1 );
+        else if ( pPars->nRatioMin && Vec_IntSize(p->vAbs) >= p->nMarked * pPars->nRatioMin / 100 )
+            Abc_Print( 1, "GLA found that the size of abstraction exceeds %d %% in frame %d.  ", pPars->nRatioMin, p->pPars->iFrameProved+1 );
+        else
+            Abc_Print( 1, "GLA finished %d frames and produced a %d-stable abstraction.  ", p->pPars->iFrameProved+1, p->pPars->nFramesNoChange );
+        p->pPars->iFrame = p->pPars->iFrameProved;
+    }
+    else
+    {
+        if ( p->pPars->fVerbose )
+            Abc_Print( 1, "\n" );
+        if ( !Gia_ManVerifyCex( pAig, pAig->pCexSeq, 0 ) )
+            Abc_Print( 1, "    Gia_ManPerformGlaOld(): CEX verification has failed!\n" );
+        Abc_Print( 1, "True counter-example detected in frame %d.  ", f );
+        p->pPars->iFrame = f - 1;
+        Vec_IntFreeP( &pAig->vGateClasses );
+        RetValue = 0;
+    }
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    if ( p->pPars->fVerbose )
+    {
+        p->timeOther = (Abc_Clock() - clk) - p->timeUnsat - p->timeSat - p->timeCex - p->timeInit;
+        ABC_PRTP( "Runtime: Initializing", p->timeInit,   Abc_Clock() - clk );
+        ABC_PRTP( "Runtime: Solver UNSAT", p->timeUnsat,  Abc_Clock() - clk );
+        ABC_PRTP( "Runtime: Solver SAT  ", p->timeSat,    Abc_Clock() - clk );
+        ABC_PRTP( "Runtime: Refinement  ", p->timeCex,    Abc_Clock() - clk );
+        ABC_PRTP( "Runtime: Other       ", p->timeOther,  Abc_Clock() - clk );
+        ABC_PRTP( "Runtime: TOTAL       ", Abc_Clock() - clk, Abc_Clock() - clk );
+        Ga2_ManReportMemory( p );
+    }
+//    Ga2_ManDumpStats( p->pGia, p->pPars, p->pSat, p->pPars->iFrameProved, 0 );
+    Ga2_ManStop( p );
+    fflush( stdout );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/absGlaOld.c b/abc-build/src/proof/abs/absGlaOld.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absGlaOld.c
@@ -0,0 +1,1956 @@
+/**CFile****************************************************************
+
+  FileName    [absGla.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Abstraction package.]
+
+  Synopsis    [Gate-level abstraction.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: absGla.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver2.h"
+#include "base/main/main.h"
+#include "abs.h"
+#include "absRef.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Rfn_Obj_t_ Rfn_Obj_t; // refinement object
+struct Rfn_Obj_t_
+{
+    unsigned       Value     :  1;  // value
+    unsigned       fVisit    :  1;  // visited
+    unsigned       fPPi      :  1;  // PPI
+    unsigned       Prio      : 16;  // priority
+    unsigned       Sign      : 12;  // traversal signature
+};
+
+typedef struct Gla_Obj_t_ Gla_Obj_t; // abstraction object
+struct Gla_Obj_t_
+{
+    int            iGiaObj;         // corresponding GIA obj
+    unsigned       fAbs      :  1;  // belongs to abstraction
+    unsigned       fCompl0   :  1;  // compl bit of the first fanin
+    unsigned       fConst    :  1;  // object attribute
+    unsigned       fPi       :  1;  // object attribute
+    unsigned       fPo       :  1;  // object attribute
+    unsigned       fRo       :  1;  // object attribute
+    unsigned       fRi       :  1;  // object attribute
+    unsigned       fAnd      :  1;  // object attribute
+    unsigned       fMark     :  1;  // nearby object
+    unsigned       nFanins   : 23;  // fanin count
+    int            Fanins[4];       // fanins
+    Vec_Int_t      vFrames;         // variables in each timeframe
+};
+
+typedef struct Gla_Man_t_ Gla_Man_t; // manager
+struct Gla_Man_t_
+{
+    // user data
+    Gia_Man_t *    pGia0;           // starting AIG manager
+    Gia_Man_t *    pGia;            // working AIG manager
+    Abs_Par_t *    pPars;           // parameters
+    // internal data
+    Vec_Int_t *    vAbs;            // abstracted objects
+    Gla_Obj_t *    pObjRoot;        // the primary output
+    Gla_Obj_t *    pObjs;           // objects
+    unsigned *     pObj2Obj;        // mapping of GIA obj into GLA obj
+    int            nObjs;           // the number of objects
+    int            nAbsOld;         // previous abstraction
+//    int            nAbsNew;         // previous abstraction
+//    int            nLrnOld;         // the number of bytes
+//    int            nLrnNew;         // the number of bytes
+    // other data
+    int            nCexes;          // the number of counter-examples
+    int            nObjAdded;       // total number of objects added
+    int            nSatVars;        // the number of SAT variables
+    Cnf_Dat_t *    pCnf;            // CNF derived for the nodes
+    sat_solver2 *  pSat;            // incremental SAT solver
+    Vec_Int_t *    vTemp;           // temporary array
+    Vec_Int_t *    vAddedNew;       // temporary array
+    Vec_Int_t *    vObjCounts;      // object counters
+    Vec_Int_t *    vCoreCounts;     // counts how many times each object appears in the core
+    Vec_Int_t *    vProofIds;       // counts how many times each object appears in the core
+    int            nProofIds;       // proof ID counter
+    // refinement
+    Vec_Int_t *    pvRefis;         // vectors of each object
+    // refinement manager
+    Gia_Man_t *    pGia2;
+    Rnm_Man_t *    pRnm;
+    // statistics  
+    abctime        timeInit;
+    abctime        timeSat;
+    abctime        timeUnsat;
+    abctime        timeCex;
+    abctime        timeOther;
+};
+
+// declarations
+static Vec_Int_t * Gla_ManCollectPPis( Gla_Man_t * p, Vec_Int_t * vPis );
+static int         Gla_ManCheckVar( Gla_Man_t * p, int iObj, int iFrame );
+static int         Gla_ManGetVar( Gla_Man_t * p, int iObj, int iFrame );
+
+// object procedures
+static inline int         Gla_ObjId( Gla_Man_t * p, Gla_Obj_t * pObj )      { assert( pObj > p->pObjs && pObj < p->pObjs + p->nObjs ); return pObj - p->pObjs;    }
+static inline Gla_Obj_t * Gla_ManObj( Gla_Man_t * p, int i )                { assert( i >= 0 && i < p->nObjs ); return i ? p->pObjs + i : NULL;                   }
+static inline Gia_Obj_t * Gla_ManGiaObj( Gla_Man_t * p, Gla_Obj_t * pObj )  { return Gia_ManObj( p->pGia, pObj->iGiaObj );                                        }
+static inline int         Gla_ObjSatValue( Gla_Man_t * p, int iGia, int f ) { return Gla_ManCheckVar(p, p->pObj2Obj[iGia], f) ? sat_solver2_var_value( p->pSat, Gla_ManGetVar(p, p->pObj2Obj[iGia], f) ) : 0;  }
+
+static inline Rfn_Obj_t * Gla_ObjRef( Gla_Man_t * p, Gia_Obj_t * pObj, int f ) { return (Rfn_Obj_t *)Vec_IntGetEntryP( &(p->pvRefis[Gia_ObjId(p->pGia, pObj)]), f ); }
+static inline void        Gla_ObjClearRef( Rfn_Obj_t * p )                     { *((int *)p) = 0;                                                                    }
+
+
+// iterator through abstracted objects
+#define Gla_ManForEachObj( p, pObj )                       \
+    for ( pObj = p->pObjs + 1; pObj < p->pObjs + p->nObjs; pObj++ ) 
+#define Gla_ManForEachObjAbs( p, pObj, i )                 \
+    for ( i = 0; i < Vec_IntSize(p->vAbs) && ((pObj = Gla_ManObj(p, Vec_IntEntry(p->vAbs, i))),1); i++) 
+#define Gla_ManForEachObjAbsVec( vVec, p, pObj, i )        \
+    for ( i = 0; i < Vec_IntSize(vVec) && ((pObj = Gla_ManObj(p, Vec_IntEntry(vVec, i))),1); i++) 
+
+// iterator through fanins of an abstracted object
+#define Gla_ObjForEachFanin( p, pObj, pFanin, i )          \
+    for ( i = 0; (i < (int)pObj->nFanins) && ((pFanin = Gla_ManObj(p, pObj->Fanins[i])),1); i++ )
+
+// some lessons learned from debugging mismatches between GIA and mapped CNF
+// - inputs/output of AND-node may be PPIs (have SAT vars), but the node is not included in the abstraction
+// - some logic node can be a PPI of one LUT and an internal node of another LUT
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares CEX and vMap for refinement.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_GlaPrepareCexAndMap( Gla_Man_t * p, Abc_Cex_t ** ppCex, Vec_Int_t ** pvMap )
+{
+    Abc_Cex_t * pCex;
+    Vec_Int_t * vMap;
+    Gla_Obj_t * pObj, * pFanin;
+    Gia_Obj_t * pGiaObj;
+    int f, i, k;
+    // find PIs and PPIs
+    vMap = Vec_IntAlloc( 1000 );
+    Gla_ManForEachObjAbs( p, pObj, i )
+    {
+        assert( pObj->fConst || pObj->fRo || pObj->fAnd );
+        Gla_ObjForEachFanin( p, pObj, pFanin, k )
+            if ( !pFanin->fAbs )
+                Vec_IntPush( vMap, pFanin->iGiaObj );
+    }
+    Vec_IntUniqify( vMap );
+    // derive counter-example
+    pCex = Abc_CexAlloc( 0, Vec_IntSize(vMap), p->pPars->iFrame+1 );
+    pCex->iFrame = p->pPars->iFrame;
+    for ( f = 0; f <= p->pPars->iFrame; f++ )
+        Gia_ManForEachObjVec( vMap, p->pGia, pGiaObj, k )
+            if ( Gla_ObjSatValue( p, Gia_ObjId(p->pGia, pGiaObj), f ) )
+                Abc_InfoSetBit( pCex->pData, f * Vec_IntSize(vMap) + k );
+    *pvMap = vMap;
+    *ppCex = pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives counter-example using current assignments.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Gla_ManDeriveCex( Gla_Man_t * p, Vec_Int_t * vPis )
+{
+    Abc_Cex_t * pCex;
+    Gia_Obj_t * pObj;
+    int i, f;
+    pCex = Abc_CexAlloc( Gia_ManRegNum(p->pGia), Gia_ManPiNum(p->pGia), p->pPars->iFrame+1 );
+    pCex->iPo = 0;
+    pCex->iFrame = p->pPars->iFrame;
+    Gia_ManForEachObjVec( vPis, p->pGia, pObj, i )
+    {
+        if ( !Gia_ObjIsPi(p->pGia, pObj) )
+            continue;
+        assert( Gia_ObjIsPi(p->pGia, pObj) );
+        for ( f = 0; f <= pCex->iFrame; f++ )
+            if ( Gla_ObjSatValue( p, Gia_ObjId(p->pGia, pObj), f ) )
+                Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + Gia_ObjCioId(pObj) );
+    }
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects GIA abstraction objects.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gla_ManCollectInternal_rec( Gia_Man_t * p, Gia_Obj_t * pGiaObj, Vec_Int_t * vRoAnds )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pGiaObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pGiaObj);
+    assert( Gia_ObjIsAnd(pGiaObj) );
+    Gla_ManCollectInternal_rec( p, Gia_ObjFanin0(pGiaObj), vRoAnds );
+    Gla_ManCollectInternal_rec( p, Gia_ObjFanin1(pGiaObj), vRoAnds );
+    Vec_IntPush( vRoAnds, Gia_ObjId(p, pGiaObj) );
+}
+void Gla_ManCollect( Gla_Man_t * p, Vec_Int_t * vPis, Vec_Int_t * vPPis, Vec_Int_t * vCos, Vec_Int_t * vRoAnds )
+{
+    Gla_Obj_t * pObj, * pFanin; 
+    Gia_Obj_t * pGiaObj;
+    int i, k;
+
+    // collect COs
+    Vec_IntPush( vCos, Gia_ObjId(p->pGia, Gia_ManPo(p->pGia, 0)) );
+    // collect fanins of abstracted objects
+    Gla_ManForEachObjAbs( p, pObj, i )
+    {
+        assert( pObj->fConst || pObj->fRo || pObj->fAnd );
+        if ( pObj->fRo )
+        {
+            pGiaObj = Gia_ObjRoToRi( p->pGia, Gia_ManObj(p->pGia, pObj->iGiaObj) );
+            Vec_IntPush( vCos, Gia_ObjId(p->pGia, pGiaObj) );
+        }
+        Gla_ObjForEachFanin( p, pObj, pFanin, k )
+            if ( !pFanin->fAbs )
+                Vec_IntPush( (pFanin->fPi ? vPis : vPPis), pFanin->iGiaObj );
+    }
+    Vec_IntUniqify( vPis );
+    Vec_IntUniqify( vPPis );
+    Vec_IntSort( vCos, 0 );
+    // sorting PIs/PPIs/COs leads to refinements that are more "well-aligned"...
+
+    // mark const/PIs/PPIs
+    Gia_ManIncrementTravId( p->pGia );
+    Gia_ObjSetTravIdCurrent( p->pGia, Gia_ManConst0(p->pGia) );
+    Gia_ManForEachObjVec( vPis, p->pGia, pGiaObj, i )
+        Gia_ObjSetTravIdCurrent( p->pGia, pGiaObj );
+    Gia_ManForEachObjVec( vPPis, p->pGia, pGiaObj, i )
+        Gia_ObjSetTravIdCurrent( p->pGia, pGiaObj );
+    // mark and add ROs first
+    Gia_ManForEachObjVec( vCos, p->pGia, pGiaObj, i )
+    {
+        if ( i == 0 ) continue;
+        pGiaObj = Gia_ObjRiToRo( p->pGia, pGiaObj );
+        Gia_ObjSetTravIdCurrent( p->pGia, pGiaObj );
+        Vec_IntPush( vRoAnds, Gia_ObjId(p->pGia, pGiaObj) );
+    }
+    // collect nodes between PIs/PPIs/ROs and COs
+    Gia_ManForEachObjVec( vCos, p->pGia, pGiaObj, i )
+        Gla_ManCollectInternal_rec( p->pGia, Gia_ObjFanin0(pGiaObj), vRoAnds );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Drive implications of the given node towards primary outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManRefSetAndPropFanout_rec( Gla_Man_t * p, Gia_Obj_t * pObj, int f, Vec_Int_t * vSelect, int Sign )
+{
+    int i;//, Id = Gia_ObjId(p->pGia, pObj);
+    Rfn_Obj_t * pRef0, * pRef1, * pRef = Gla_ObjRef( p, pObj, f );
+    Gia_Obj_t * pFanout;
+    int k;
+    if ( (int)pRef->Sign != Sign )
+        return;
+    assert( pRef->fVisit == 0 );
+    pRef->fVisit = 1;
+    if ( pRef->fPPi )
+    {
+        assert( (int)pRef->Prio > 0 );
+        for ( i = p->pPars->iFrame; i >= 0; i-- )
+            if ( !Gla_ObjRef(p, pObj, i)->fVisit )
+                Gia_ManRefSetAndPropFanout_rec( p, pObj, i, vSelect, Sign );
+        Vec_IntPush( vSelect, Gia_ObjId(p->pGia, pObj) );
+        return;
+    }
+    if ( (Gia_ObjIsCo(pObj) && f == p->pPars->iFrame) || Gia_ObjIsPo(p->pGia, pObj) )
+        return;
+    if ( Gia_ObjIsRi(p->pGia, pObj) )
+    {
+        pFanout = Gia_ObjRiToRo(p->pGia, pObj);
+        if ( !Gla_ObjRef(p, pFanout, f+1)->fVisit )
+            Gia_ManRefSetAndPropFanout_rec( p, pFanout, f+1, vSelect, Sign );
+        return;
+    }
+    assert( Gia_ObjIsRo(p->pGia, pObj) || Gia_ObjIsAnd(pObj) );
+    Gia_ObjForEachFanoutStatic( p->pGia, pObj, pFanout, k )
+    {
+//        Rfn_Obj_t * pRefF = Gla_ObjRef(p, pFanout, f);
+        if ( Gla_ObjRef(p, pFanout, f)->fVisit )
+            continue;
+        if ( Gia_ObjIsCo(pFanout) )
+        {
+            Gia_ManRefSetAndPropFanout_rec( p, pFanout, f, vSelect, Sign );
+            continue;
+        } 
+        assert( Gia_ObjIsAnd(pFanout) );
+        pRef0 = Gla_ObjRef( p, Gia_ObjFanin0(pFanout), f );
+        pRef1 = Gla_ObjRef( p, Gia_ObjFanin1(pFanout), f );
+        if ( ((pRef0->Value ^ Gia_ObjFaninC0(pFanout)) == 0 && pRef0->fVisit) ||
+             ((pRef1->Value ^ Gia_ObjFaninC1(pFanout)) == 0 && pRef1->fVisit) || 
+           ( ((pRef0->Value ^ Gia_ObjFaninC0(pFanout)) == 1 && pRef0->fVisit) && 
+             ((pRef1->Value ^ Gia_ObjFaninC1(pFanout)) == 1 && pRef1->fVisit) ) )
+           Gia_ManRefSetAndPropFanout_rec( p, pFanout, f, vSelect, Sign );
+    }
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Selects assignments to be refined.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gla_ManRefSelect_rec( Gla_Man_t * p, Gia_Obj_t * pObj, int f, Vec_Int_t * vSelect, int Sign )
+{ 
+    int i;//, Id = Gia_ObjId(p->pGia, pObj);
+    Rfn_Obj_t * pRef = Gla_ObjRef( p, pObj, f );
+//    assert( (int)pRef->Sign == Sign );
+    if ( pRef->fVisit )
+        return;
+    if ( p->pPars->fPropFanout )
+        Gia_ManRefSetAndPropFanout_rec( p, pObj, f, vSelect, Sign );
+    else
+        pRef->fVisit = 1;
+    if ( pRef->fPPi )
+    {
+        assert( (int)pRef->Prio > 0 );
+        if ( p->pPars->fPropFanout )
+        {
+            for ( i = p->pPars->iFrame; i >= 0; i-- )
+                if ( !Gla_ObjRef(p, pObj, i)->fVisit )
+                    Gia_ManRefSetAndPropFanout_rec( p, pObj, i, vSelect, Sign );
+        }
+        else
+        {
+            Vec_IntPush( vSelect, Gia_ObjId(p->pGia, pObj) );
+            Vec_IntAddToEntry( p->vObjCounts, f, 1 );
+        }
+        return;
+    }
+    if ( Gia_ObjIsPi(p->pGia, pObj) || Gia_ObjIsConst0(pObj) )
+        return;
+    if ( Gia_ObjIsRo(p->pGia, pObj) )
+    {
+        if ( f > 0 )
+            Gla_ManRefSelect_rec( p, Gia_ObjFanin0(Gia_ObjRoToRi(p->pGia, pObj)), f-1, vSelect, Sign );
+        return;
+    }
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        Rfn_Obj_t * pRef0 = Gla_ObjRef( p, Gia_ObjFanin0(pObj), f );
+        Rfn_Obj_t * pRef1 = Gla_ObjRef( p, Gia_ObjFanin1(pObj), f );
+        if ( pRef->Value == 1 )
+        {
+            if ( pRef0->Prio > 0 )
+                Gla_ManRefSelect_rec( p, Gia_ObjFanin0(pObj), f, vSelect, Sign );
+            if ( pRef1->Prio > 0 )
+                Gla_ManRefSelect_rec( p, Gia_ObjFanin1(pObj), f, vSelect, Sign );
+        }
+        else // select one value
+        {
+            if ( (pRef0->Value ^ Gia_ObjFaninC0(pObj)) == 0 && (pRef1->Value ^ Gia_ObjFaninC1(pObj)) == 0 )
+            {
+                if ( pRef0->Prio <= pRef1->Prio ) // choice
+                {
+                    if ( pRef0->Prio > 0 )
+                        Gla_ManRefSelect_rec( p, Gia_ObjFanin0(pObj), f, vSelect, Sign );
+                }
+                else
+                {
+                    if ( pRef1->Prio > 0 )
+                        Gla_ManRefSelect_rec( p, Gia_ObjFanin1(pObj), f, vSelect, Sign );
+                }
+            }
+            else if ( (pRef0->Value ^ Gia_ObjFaninC0(pObj)) == 0 )
+            {
+                if ( pRef0->Prio > 0 )
+                    Gla_ManRefSelect_rec( p, Gia_ObjFanin0(pObj), f, vSelect, Sign );
+            }
+            else if ( (pRef1->Value ^ Gia_ObjFaninC1(pObj)) == 0 )
+            {
+                if ( pRef1->Prio > 0 )
+                    Gla_ManRefSelect_rec( p, Gia_ObjFanin1(pObj), f, vSelect, Sign );
+            }
+            else assert( 0 );
+        }
+    }
+    else assert( 0 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs refinement.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gla_ManVerifyUsingTerSim( Gla_Man_t * p, Vec_Int_t * vPis, Vec_Int_t * vPPis, Vec_Int_t * vRoAnds, Vec_Int_t * vCos, Vec_Int_t * vRes )
+{
+    Gia_Obj_t * pObj;
+    int i, f;
+//    Gia_ManForEachObj( p->pGia, pObj, i )
+//        assert( Gia_ObjTerSimGetC(pObj) );
+    for ( f = 0; f <= p->pPars->iFrame; f++ )
+    {
+        Gia_ObjTerSimSet0( Gia_ManConst0(p->pGia) );
+        Gia_ManForEachObjVec( vPis, p->pGia, pObj, i )
+        {
+            if ( Gla_ObjSatValue( p, Gia_ObjId(p->pGia, pObj), f ) )
+                Gia_ObjTerSimSet1( pObj );
+            else
+                Gia_ObjTerSimSet0( pObj );
+        }
+        Gia_ManForEachObjVec( vPPis, p->pGia, pObj, i )
+            Gia_ObjTerSimSetX( pObj );
+        Gia_ManForEachObjVec( vRes, p->pGia, pObj, i )
+            if ( Gla_ObjSatValue( p, Gia_ObjId(p->pGia, pObj), f ) )
+                Gia_ObjTerSimSet1( pObj );
+            else
+                Gia_ObjTerSimSet0( pObj );
+
+        Gia_ManForEachObjVec( vRoAnds, p->pGia, pObj, i )
+        {
+            if ( Gia_ObjIsAnd(pObj) )
+                Gia_ObjTerSimAnd( pObj );
+            else if ( f == 0 )
+                Gia_ObjTerSimSet0( pObj );
+            else
+                Gia_ObjTerSimRo( p->pGia, pObj );
+        }
+        Gia_ManForEachObjVec( vCos, p->pGia, pObj, i )
+            Gia_ObjTerSimCo( pObj );
+    }
+    pObj = Gia_ManPo( p->pGia, 0 );
+    if ( !Gia_ObjTerSimGet1(pObj) )
+        Abc_Print( 1, "\nRefinement verification has failed!!!\n" );
+    // clear
+    Gia_ObjTerSimSetC( Gia_ManConst0(p->pGia) );
+    Gia_ManForEachObjVec( vPis, p->pGia, pObj, i )
+        Gia_ObjTerSimSetC( pObj );
+    Gia_ManForEachObjVec( vPPis, p->pGia, pObj, i )
+        Gia_ObjTerSimSetC( pObj );
+    Gia_ManForEachObjVec( vRoAnds, p->pGia, pObj, i )
+        Gia_ObjTerSimSetC( pObj );
+    Gia_ManForEachObjVec( vCos, p->pGia, pObj, i )
+        Gia_ObjTerSimSetC( pObj );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs refinement.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gla_ManRefinement( Gla_Man_t * p )
+{
+    Abc_Cex_t * pCex;
+    Vec_Int_t * vMap, * vVec;
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_GlaPrepareCexAndMap( p, &pCex, &vMap );
+    vVec = Rnm_ManRefine( p->pRnm, pCex, vMap, p->pPars->fPropFanout, p->pPars->fNewRefine, 1 );
+    Abc_CexFree( pCex );
+    if ( Vec_IntSize(vVec) == 0 )
+    {
+        Vec_IntFree( vVec );
+        Abc_CexFreeP( &p->pGia->pCexSeq );
+        p->pGia->pCexSeq = Gla_ManDeriveCex( p, vMap );
+        Vec_IntFree( vMap );
+        return NULL;
+    }
+    Vec_IntFree( vMap );
+    // remap them into GLA objects
+    Gia_ManForEachObjVec( vVec, p->pGia, pObj, i )
+        Vec_IntWriteEntry( vVec, i, p->pObj2Obj[Gia_ObjId(p->pGia, pObj)] );
+    p->nObjAdded += Vec_IntSize(vVec);
+    return vVec;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs refinement.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gla_ManRefinement2( Gla_Man_t * p )
+{
+    int fVerify = 1;
+    static int Sign = 0;
+    Vec_Int_t * vPis, * vPPis, * vCos, * vRoAnds, * vSelect = NULL;
+    Rfn_Obj_t * pRef, * pRef0, * pRef1;
+    Gia_Obj_t * pObj;
+    int i, f;
+    Sign++;
+
+    // compute PIs and pseudo-PIs
+    vCos = Vec_IntAlloc( 1000 );
+    vPis = Vec_IntAlloc( 1000 );  
+    vPPis = Vec_IntAlloc( 1000 );
+    vRoAnds = Vec_IntAlloc( 1000 );  
+    Gla_ManCollect( p, vPis, vPPis, vCos, vRoAnds );
+
+/*
+    // check how many pseudo PIs have variables
+    Gla_ManForEachObjAbsVec( vPis, p, pGla, i )
+    {
+        Abc_Print( 1, "  %5d : ", Gla_ObjId(p, pGla) );
+        for ( f = 0; f <= p->pPars->iFrame; f++ )
+            Abc_Print( 1, "%d", Gla_ManCheckVar(p, Gla_ObjId(p, pGla), f) );
+        Abc_Print( 1, "\n" );
+    }    
+
+    // check how many pseudo PIs have variables
+    Gla_ManForEachObjAbsVec( vPPis, p, pGla, i )
+    {
+        Abc_Print( 1, "%5d : ", Gla_ObjId(p, pGla) );
+        for ( f = 0; f <= p->pPars->iFrame; f++ )
+            Abc_Print( 1, "%d", Gla_ManCheckVar(p, Gla_ObjId(p, pGla), f) );
+        Abc_Print( 1, "\n" );
+    }    
+*/
+    // propagate values
+    for ( f = 0; f <= p->pPars->iFrame; f++ )
+    {
+        // constant
+        pRef = Gla_ObjRef( p, Gia_ManConst0(p->pGia), f );  Gla_ObjClearRef( pRef );
+        pRef->Value  = 0;
+        pRef->Prio   = 0;
+        pRef->Sign   = Sign;
+        // primary input
+        Gia_ManForEachObjVec( vPis, p->pGia, pObj, i )
+        {
+//            assert( f == p->pPars->iFrame || Gla_ManCheckVar(p, p->pObj2Obj[Gia_ObjId(p->pGia, pObj)], f) );
+            pRef = Gla_ObjRef( p, pObj, f );   Gla_ObjClearRef( pRef );
+            pRef->Value = Gla_ObjSatValue( p, Gia_ObjId(p->pGia, pObj), f );
+            pRef->Prio  = 0;
+            pRef->Sign  = Sign;
+            assert( pRef->fVisit == 0 );
+        }
+        // primary input
+        Gia_ManForEachObjVec( vPPis, p->pGia, pObj, i )
+        {
+//            assert( f == p->pPars->iFrame || Gla_ManCheckVar(p, p->pObj2Obj[Gia_ObjId(p->pGia, pObj)], f) );
+            assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsRo(p->pGia, pObj) );
+            pRef = Gla_ObjRef( p, pObj, f );   Gla_ObjClearRef( pRef );
+            pRef->Value = Gla_ObjSatValue( p, Gia_ObjId(p->pGia, pObj), f );
+            pRef->Prio  = i+1;
+            pRef->fPPi  = 1;
+            pRef->Sign  = Sign;
+            assert( pRef->fVisit == 0 );
+        }
+        // internal nodes
+        Gia_ManForEachObjVec( vRoAnds, p->pGia, pObj, i )
+        {
+            assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsRo(p->pGia, pObj) );
+            pRef = Gla_ObjRef( p, pObj, f );   Gla_ObjClearRef( pRef );
+            if ( Gia_ObjIsRo(p->pGia, pObj) )
+            {
+                if ( f == 0 )
+                {
+                    pRef->Value = 0;
+                    pRef->Prio  = 0;
+                    pRef->Sign  = Sign;
+                }
+                else
+                {
+                    pRef0 = Gla_ObjRef( p, Gia_ObjRoToRi(p->pGia, pObj), f-1 );
+                    pRef->Value = pRef0->Value;
+                    pRef->Prio  = pRef0->Prio;
+                    pRef->Sign  = Sign;
+                }
+                continue;
+            }
+            assert( Gia_ObjIsAnd(pObj) );
+            pRef0 = Gla_ObjRef( p, Gia_ObjFanin0(pObj), f );
+            pRef1 = Gla_ObjRef( p, Gia_ObjFanin1(pObj), f );
+            pRef->Value = (pRef0->Value ^ Gia_ObjFaninC0(pObj)) & (pRef1->Value ^ Gia_ObjFaninC1(pObj));
+
+            if ( p->pObj2Obj[Gia_ObjId(p->pGia, pObj)] != ~0 && 
+                 Gla_ManCheckVar(p, p->pObj2Obj[Gia_ObjId(p->pGia, pObj)], f) &&
+                 (int)pRef->Value != Gla_ObjSatValue(p, Gia_ObjId(p->pGia, pObj), f) )
+            {
+                    Abc_Print( 1, "Object has value mismatch    " );
+                    Gia_ObjPrint( p->pGia, pObj );
+            }
+
+            if ( pRef->Value == 1 )
+                pRef->Prio  = Abc_MaxInt( pRef0->Prio, pRef1->Prio );
+            else if ( (pRef0->Value ^ Gia_ObjFaninC0(pObj)) == 0 && (pRef1->Value ^ Gia_ObjFaninC1(pObj)) == 0 )
+                pRef->Prio  = Abc_MinInt( pRef0->Prio, pRef1->Prio ); // choice
+            else if ( (pRef0->Value ^ Gia_ObjFaninC0(pObj)) == 0 )
+                pRef->Prio  = pRef0->Prio;
+            else 
+                pRef->Prio  = pRef1->Prio;
+            assert( pRef->fVisit == 0 );
+            pRef->Sign  = Sign;
+        }
+        // output nodes
+        Gia_ManForEachObjVec( vCos, p->pGia, pObj, i )
+        {
+            pRef = Gla_ObjRef( p, pObj, f );    Gla_ObjClearRef( pRef );
+            pRef0 = Gla_ObjRef( p, Gia_ObjFanin0(pObj), f ); 
+            pRef->Value = (pRef0->Value ^ Gia_ObjFaninC0(pObj));
+            pRef->Prio  = pRef0->Prio;
+            assert( pRef->fVisit == 0 );
+            pRef->Sign  = Sign;
+        }
+    } 
+
+    // make sure the output value is 1
+    pObj = Gia_ManPo( p->pGia, 0 );
+    pRef = Gla_ObjRef( p, pObj, p->pPars->iFrame );
+    if ( pRef->Value != 1 )
+        Abc_Print( 1, "\nCounter-example verification has failed!!!\n" );
+
+    // check the CEX
+    if ( pRef->Prio == 0 )
+    {
+        p->pGia->pCexSeq = Gla_ManDeriveCex( p, vPis );
+        Vec_IntFree( vPis );
+        Vec_IntFree( vPPis );
+        Vec_IntFree( vRoAnds );
+        Vec_IntFree( vCos );
+        return NULL;
+    }
+
+    // select objects
+    vSelect = Vec_IntAlloc( 100 );
+    Vec_IntFill( p->vObjCounts, p->pPars->iFrame+1, 0 );
+    Gla_ManRefSelect_rec( p, Gia_ObjFanin0(Gia_ManPo(p->pGia, 0)), p->pPars->iFrame, vSelect, Sign );
+    Vec_IntUniqify( vSelect );
+
+/*
+    for ( f = 0; f < p->pPars->iFrame; f++ )
+        printf( "%2d", Vec_IntEntry(p->vObjCounts, f) );
+    printf( "\n" );
+*/
+    if ( fVerify )
+        Gla_ManVerifyUsingTerSim( p, vPis, vPPis, vRoAnds, vCos, vSelect );
+
+    // remap them into GLA objects
+    Gia_ManForEachObjVec( vSelect, p->pGia, pObj, i )
+        Vec_IntWriteEntry( vSelect, i, p->pObj2Obj[Gia_ObjId(p->pGia, pObj)] );
+
+    Vec_IntFree( vPis );
+    Vec_IntFree( vPPis );
+    Vec_IntFree( vRoAnds );
+    Vec_IntFree( vCos );
+
+    p->nObjAdded += Vec_IntSize(vSelect);
+    return vSelect;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Adds clauses for the given obj in the given frame.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gla_ManCollectFanins( Gla_Man_t * p, Gla_Obj_t * pGla, int iObj, Vec_Int_t * vFanins )
+{
+    int i, nClauses, iFirstClause, * pLit;
+    nClauses = p->pCnf->pObj2Count[pGla->iGiaObj];
+    iFirstClause = p->pCnf->pObj2Clause[pGla->iGiaObj];
+    Vec_IntClear( vFanins );
+    for ( i = iFirstClause; i < iFirstClause + nClauses; i++ )
+        for ( pLit = p->pCnf->pClauses[i]; pLit < p->pCnf->pClauses[i+1]; pLit++ )
+            if ( lit_var(*pLit) != iObj )
+                Vec_IntPushUnique( vFanins, lit_var(*pLit) );
+    assert( Vec_IntSize( vFanins ) <= 4 );
+    Vec_IntSort( vFanins, 0 );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG while decoupling nodes duplicated in the mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManDupMapped_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Man_t * pNew )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManDupMapped_rec( p, Gia_ObjFanin0(pObj), pNew );
+    Gia_ManDupMapped_rec( p, Gia_ObjFanin1(pObj), pNew );
+    pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Vec_IntPush( pNew->vLutConfigs, Gia_ObjId(p, pObj) );
+}
+Gia_Man_t * Gia_ManDupMapped( Gia_Man_t * p, Vec_Int_t * vMapping )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj, * pFanin;
+    int i, k, * pMapping, * pObj2Obj;
+    // start new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // start mapping
+    Gia_ManFillValue( p );
+    pObj2Obj = ABC_FALLOC( int, Gia_ManObjNum(p) );
+    pObj2Obj[0] = 0;
+    // create reverse mapping and attach it to the node
+    pNew->vLutConfigs = Vec_IntAlloc( Gia_ManObjNum(p) * 4 / 3 );
+    Vec_IntPush( pNew->vLutConfigs, 0 );
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsAnd(pObj) )
+        { 
+            int Offset = Vec_IntEntry(vMapping, Gia_ObjId(p, pObj));
+            if ( Offset == 0 )
+                continue;
+            pMapping = Vec_IntEntryP( vMapping, Offset );
+            Gia_ManIncrementTravId( p );
+            for ( k = 1; k <= 4; k++ )
+            {
+                if ( pMapping[k] == -1 )
+                    continue;
+                pFanin = Gia_ManObj(p, pMapping[k]);
+                Gia_ObjSetTravIdCurrent( p, pFanin );
+                pFanin->Value = pObj2Obj[pMapping[k]];
+                assert( ~pFanin->Value );
+            }
+            assert( !Gia_ObjIsTravIdCurrent(p, pObj) );
+            assert( !~pObj->Value );
+            Gia_ManDupMapped_rec( p, pObj, pNew );
+            pObj2Obj[i] = pObj->Value;
+            assert( ~pObj->Value );
+        }
+        else if ( Gia_ObjIsCi(pObj) )
+        {
+            pObj2Obj[i] = Gia_ManAppendCi( pNew );
+            Vec_IntPush( pNew->vLutConfigs, i );
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+        {
+            Gia_ObjFanin0(pObj)->Value = pObj2Obj[Gia_ObjFaninId0p(p, pObj)];
+            assert( ~Gia_ObjFanin0(pObj)->Value );
+            pObj2Obj[i] = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+            Vec_IntPush( pNew->vLutConfigs, i );
+        }
+    }
+    assert( Vec_IntSize(pNew->vLutConfigs) == Gia_ManObjNum(pNew) );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    // map original AIG into the new AIG
+    Gia_ManForEachObj( p, pObj, i )
+        pObj->Value = pObj2Obj[i];
+    ABC_FREE( pObj2Obj );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gla_Man_t * Gla_ManStart( Gia_Man_t * pGia0, Abs_Par_t * pPars )
+{
+    Gla_Man_t * p;
+    Aig_Man_t * pAig;
+    Gia_Obj_t * pObj;
+    Gla_Obj_t * pGla;
+    Vec_Int_t * vMappingNew;
+    int i, k, Offset, * pMapping, * pLits, * pObj2Count, * pObj2Clause;
+
+    // start
+    p = ABC_CALLOC( Gla_Man_t, 1 );
+    p->pGia0 = pGia0;
+    p->pPars = pPars;
+    p->vAbs  = Vec_IntAlloc( 100 );
+    p->vTemp = Vec_IntAlloc( 100 );
+    p->vAddedNew = Vec_IntAlloc( 100 );
+    p->vObjCounts = Vec_IntAlloc( 100 );
+
+    // internal data
+    pAig = Gia_ManToAigSimple( pGia0 );
+    p->pCnf = Cnf_DeriveOther( pAig, 1 );
+    Aig_ManStop( pAig );
+    // create working GIA
+    p->pGia = Gia_ManDupMapped( pGia0, p->pCnf->vMapping );
+    if ( pPars->fPropFanout )
+        Gia_ManStaticFanoutStart( p->pGia );
+
+    // derive new gate map
+    assert( pGia0->vGateClasses != 0 );
+    p->pGia->vGateClasses = Vec_IntStart( Gia_ManObjNum(p->pGia) );
+    p->vCoreCounts = Vec_IntStart( Gia_ManObjNum(p->pGia) );
+    p->vProofIds = Vec_IntAlloc(0);
+    // update p->pCnf->vMapping, p->pCnf->pObj2Count, p->pCnf->pObj2Clause 
+    // (here are not updating p->pCnf->pVarNums because it is not needed)
+    vMappingNew = Vec_IntStart( Gia_ManObjNum(p->pGia) );
+    pObj2Count  = ABC_FALLOC( int, Gia_ManObjNum(p->pGia) );
+    pObj2Clause = ABC_FALLOC( int, Gia_ManObjNum(p->pGia) );
+    Gia_ManForEachObj( pGia0, pObj, i )
+    {
+        // skip internal nodes not used in the mapping
+        if ( !~pObj->Value )
+            continue;
+        // replace positive literal by variable
+        assert( !Abc_LitIsCompl(pObj->Value) );
+        pObj->Value = Abc_Lit2Var(pObj->Value);
+        assert( (int)pObj->Value < Gia_ManObjNum(p->pGia) );
+        // update arrays
+        pObj2Count[pObj->Value] = p->pCnf->pObj2Count[i];
+        pObj2Clause[pObj->Value] = p->pCnf->pObj2Clause[i];
+        if ( Vec_IntEntry(pGia0->vGateClasses, i) )
+            Vec_IntWriteEntry( p->pGia->vGateClasses, pObj->Value, 1 );
+        // update mappings
+        Offset = Vec_IntEntry(p->pCnf->vMapping, i);
+        Vec_IntWriteEntry( vMappingNew, pObj->Value, Vec_IntSize(vMappingNew) );
+        pMapping = Vec_IntEntryP(p->pCnf->vMapping, Offset);
+        Vec_IntPush( vMappingNew, pMapping[0] );
+        for ( k = 1; k <= 4; k++ )
+        {
+            if ( pMapping[k] == -1 )
+                Vec_IntPush( vMappingNew, -1 );
+            else
+            {
+                assert( ~Gia_ManObj(pGia0, pMapping[k])->Value );
+                Vec_IntPush( vMappingNew, Gia_ManObj(pGia0, pMapping[k])->Value );
+            }
+        }
+    }
+    // update mapping after the offset (currently not being done because it is not used)
+    Vec_IntFree( p->pCnf->vMapping );  p->pCnf->vMapping    = vMappingNew;
+    ABC_FREE( p->pCnf->pObj2Count );   p->pCnf->pObj2Count  = pObj2Count;
+    ABC_FREE( p->pCnf->pObj2Clause );  p->pCnf->pObj2Clause = pObj2Clause;
+
+
+    // count the number of variables
+    p->nObjs = 1;
+    Gia_ManForEachObj( p->pGia, pObj, i )
+        if ( p->pCnf->pObj2Count[i] >= 0 )
+            pObj->Value = p->nObjs++;
+        else
+            pObj->Value = ~0;
+
+    // re-express CNF using new variable IDs
+    pLits = p->pCnf->pClauses[0];
+    for ( i = 0; i < p->pCnf->nLiterals; i++ )
+    {
+        // find the original AIG object
+        pObj = Gia_ManObj( pGia0, lit_var(pLits[i]) );
+        assert( ~pObj->Value );
+        // find the working AIG object
+        pObj = Gia_ManObj( p->pGia, pObj->Value );
+        assert( ~pObj->Value );
+        // express literal in terms of LUT variables
+        pLits[i] = toLitCond( pObj->Value, lit_sign(pLits[i]) );
+    }
+
+    // create objects 
+    p->pObjs    = ABC_CALLOC( Gla_Obj_t, p->nObjs );
+    p->pObj2Obj = ABC_FALLOC( unsigned, Gia_ManObjNum(p->pGia) );
+//    p->pvRefis  = ABC_CALLOC( Vec_Int_t, Gia_ManObjNum(p->pGia) );
+    Gia_ManForEachObj( p->pGia, pObj, i )
+    {
+        p->pObj2Obj[i] = pObj->Value;
+        if ( !~pObj->Value )
+            continue;
+        pGla = Gla_ManObj( p, pObj->Value );
+        pGla->iGiaObj = i;
+        pGla->fCompl0 = Gia_ObjFaninC0(pObj);
+        pGla->fConst  = Gia_ObjIsConst0(pObj);
+        pGla->fPi     = Gia_ObjIsPi(p->pGia, pObj);
+        pGla->fPo     = Gia_ObjIsPo(p->pGia, pObj);
+        pGla->fRi     = Gia_ObjIsRi(p->pGia, pObj);
+        pGla->fRo     = Gia_ObjIsRo(p->pGia, pObj);
+        pGla->fAnd    = Gia_ObjIsAnd(pObj);
+        if ( Gia_ObjIsConst0(pObj) || Gia_ObjIsPi(p->pGia, pObj) )
+            continue;
+        if ( Gia_ObjIsCo(pObj) )
+        {
+            pGla->nFanins = 1;
+            pGla->Fanins[0] = Gia_ObjFanin0(pObj)->Value;
+            continue;
+        }
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+//            Gla_ManCollectFanins( p, pGla, pObj->Value, p->vTemp );
+//            pGla->nFanins = Vec_IntSize( p->vTemp );
+//            memcpy( pGla->Fanins, Vec_IntArray(p->vTemp), sizeof(int) * Vec_IntSize(p->vTemp) );
+            Offset = Vec_IntEntry( p->pCnf->vMapping, i );
+            pMapping = Vec_IntEntryP( p->pCnf->vMapping, Offset );
+            pGla->nFanins = 0;
+            for ( k = 1; k <= 4; k++ )
+                if ( pMapping[k] != -1 )
+                    pGla->Fanins[ pGla->nFanins++ ] = Gia_ManObj(p->pGia, pMapping[k])->Value;
+            continue;
+        }
+        assert( Gia_ObjIsRo(p->pGia, pObj) );
+        pGla->nFanins   = 1;
+        pGla->Fanins[0] = Gia_ObjFanin0( Gia_ObjRoToRi(p->pGia, pObj) )->Value;
+        pGla->fCompl0   = Gia_ObjFaninC0( Gia_ObjRoToRi(p->pGia, pObj) );
+    }
+    p->pObjRoot = Gla_ManObj( p, Gia_ManPo(p->pGia, 0)->Value );
+    // abstraction 
+    assert( p->pGia->vGateClasses != NULL );
+    Gla_ManForEachObj( p, pGla )
+    {
+        if ( Vec_IntEntry( p->pGia->vGateClasses, pGla->iGiaObj ) == 0 )
+            continue;
+        pGla->fAbs = 1;
+        Vec_IntPush( p->vAbs, Gla_ObjId(p, pGla) );
+    }
+    // other 
+    p->pSat        = sat_solver2_new();
+    if ( pPars->fUseFullProof )
+        p->pSat->pPrf1 = Vec_SetAlloc( 20 );
+//    p->pSat->fVerbose = p->pPars->fVerbose;
+//    sat_solver2_set_learntmax( p->pSat, pPars->nLearnedMax );
+    p->pSat->nLearntStart = p->pPars->nLearnedStart;
+    p->pSat->nLearntDelta = p->pPars->nLearnedDelta;
+    p->pSat->nLearntRatio = p->pPars->nLearnedPerce;
+    p->pSat->nLearntMax   = p->pSat->nLearntStart;
+    p->nSatVars  = 1;
+    // start the refinement manager
+//    p->pGia2 = Gia_ManDup( p->pGia );
+    p->pRnm = Rnm_ManStart( p->pGia );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gla_Man_t * Gla_ManStart2( Gia_Man_t * pGia, Abs_Par_t * pPars )
+{
+    Gla_Man_t * p;
+    Aig_Man_t * pAig;
+    Gia_Obj_t * pObj;
+    Gla_Obj_t * pGla;
+    int i, * pLits;
+    // start
+    p = ABC_CALLOC( Gla_Man_t, 1 );
+    p->pGia  = pGia;
+    p->pPars = pPars;
+    p->vAbs = Vec_IntAlloc( 100 );
+    p->vTemp = Vec_IntAlloc( 100 );
+    p->vAddedNew = Vec_IntAlloc( 100 );
+    // internal data
+    pAig = Gia_ManToAigSimple( p->pGia );
+    p->pCnf  = Cnf_DeriveOther( pAig, 1 );
+    Aig_ManStop( pAig );
+    // count the number of variables
+    p->nObjs = 1;
+    Gia_ManForEachObj( p->pGia, pObj, i )
+        if ( p->pCnf->pObj2Count[i] >= 0 )
+            pObj->Value = p->nObjs++;
+        else
+            pObj->Value = ~0;
+    // re-express CNF using new variable IDs
+    pLits = p->pCnf->pClauses[0];
+    for ( i = 0; i < p->pCnf->nLiterals; i++ )
+    {
+        pObj = Gia_ManObj( p->pGia, lit_var(pLits[i]) );
+        assert( ~pObj->Value );
+        pLits[i] = toLitCond( pObj->Value, lit_sign(pLits[i]) );
+    }
+    // create objects 
+    p->pObjs    = ABC_CALLOC( Gla_Obj_t, p->nObjs );
+    p->pObj2Obj = ABC_FALLOC( unsigned, Gia_ManObjNum(p->pGia) );
+//    p->pvRefis  = ABC_CALLOC( Vec_Int_t, Gia_ManObjNum(p->pGia) );
+    Gia_ManForEachObj( p->pGia, pObj, i )
+    {
+        p->pObj2Obj[i] = pObj->Value;
+        if ( !~pObj->Value )
+            continue;
+        pGla = Gla_ManObj( p, pObj->Value );
+        pGla->iGiaObj = i;
+        pGla->fCompl0 = Gia_ObjFaninC0(pObj);
+        pGla->fConst  = Gia_ObjIsConst0(pObj);
+        pGla->fPi     = Gia_ObjIsPi(p->pGia, pObj);
+        pGla->fPo     = Gia_ObjIsPo(p->pGia, pObj);
+        pGla->fRi     = Gia_ObjIsRi(p->pGia, pObj);
+        pGla->fRo     = Gia_ObjIsRo(p->pGia, pObj);
+        pGla->fAnd    = Gia_ObjIsAnd(pObj);
+        if ( Gia_ObjIsConst0(pObj) || Gia_ObjIsPi(p->pGia, pObj) )
+            continue;
+        if ( Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) )
+        {
+            Gla_ManCollectFanins( p, pGla, pObj->Value, p->vTemp );
+            pGla->nFanins = Vec_IntSize( p->vTemp );
+            memcpy( pGla->Fanins, Vec_IntArray(p->vTemp), sizeof(int) * Vec_IntSize(p->vTemp) );
+            continue;
+        }
+        assert( Gia_ObjIsRo(p->pGia, pObj) );
+        pGla->nFanins   = 1;
+        pGla->Fanins[0] = Gia_ObjFanin0( Gia_ObjRoToRi(p->pGia, pObj) )->Value;
+        pGla->fCompl0   = Gia_ObjFaninC0( Gia_ObjRoToRi(p->pGia, pObj) );
+    }
+    p->pObjRoot = Gla_ManObj( p, Gia_ManPo(p->pGia, 0)->Value );
+    // abstraction 
+    assert( pGia->vGateClasses != NULL );
+    Gla_ManForEachObj( p, pGla )
+    {
+        if ( Vec_IntEntry( pGia->vGateClasses, pGla->iGiaObj ) == 0 )
+            continue;
+        pGla->fAbs = 1;
+        Vec_IntPush( p->vAbs, Gla_ObjId(p, pGla) );
+    }
+    // other 
+    p->pSat      = sat_solver2_new();
+    p->nSatVars  = 1;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gla_ManStop( Gla_Man_t * p )
+{
+    Gla_Obj_t * pGla;
+    int i;
+
+    if ( p->pPars->fVerbose )
+        Abc_Print( 1, "SAT solver:  Var = %d  Cla = %d  Conf = %d  Lrn = %d  Reduce = %d  Cex = %d  Objs+ = %d\n", 
+            sat_solver2_nvars(p->pSat), sat_solver2_nclauses(p->pSat), sat_solver2_nconflicts(p->pSat), 
+            sat_solver2_nlearnts(p->pSat), p->pSat->nDBreduces, p->nCexes, p->nObjAdded );
+
+    // stop the refinement manager
+//    Gia_ManStopP( &p->pGia2 );
+    Rnm_ManStop( p->pRnm, 0 );
+
+    if ( p->pvRefis )
+    for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ )
+        ABC_FREE( p->pvRefis[i].pArray );
+    Gla_ManForEachObj( p, pGla )
+        ABC_FREE( pGla->vFrames.pArray );
+    Cnf_DataFree( p->pCnf );
+    if ( p->pGia0 != NULL )
+        Gia_ManStop( p->pGia );
+//    Gia_ManStaticFanoutStart( p->pGia0 );
+    sat_solver2_delete( p->pSat );
+    Vec_IntFreeP( &p->vObjCounts );
+    Vec_IntFreeP( &p->vAddedNew );
+    Vec_IntFreeP( &p->vCoreCounts );
+    Vec_IntFreeP( &p->vProofIds );
+    Vec_IntFreeP( &p->vTemp );
+    Vec_IntFreeP( &p->vAbs );
+    ABC_FREE( p->pvRefis );
+    ABC_FREE( p->pObj2Obj );
+    ABC_FREE( p->pObjs );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_GlaAbsCount( Gla_Man_t * p, int fRo, int fAnd )
+{
+    Gla_Obj_t * pObj;
+    int i, Counter = 0;
+    if ( fRo )
+        Gla_ManForEachObjAbs( p, pObj, i )
+            Counter += (pObj->fRo && pObj->fAbs);
+    else if ( fAnd )
+        Gla_ManForEachObjAbs( p, pObj, i )
+            Counter += (pObj->fAnd && pObj->fAbs);
+    else
+        Gla_ManForEachObjAbs( p, pObj, i )
+            Counter += (pObj->fAbs);
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives new abstraction map.]
+
+  Description [Returns 1 if node contains abstracted leaf on the path.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gla_ManTranslate_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vGla, int nUsageCount )
+{
+    int Value0, Value1;
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return 1;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+        return 0;
+    assert( Gia_ObjIsAnd(pObj) );
+    Value0 = Gla_ManTranslate_rec( p, Gia_ObjFanin0(pObj), vGla, nUsageCount );
+    Value1 = Gla_ManTranslate_rec( p, Gia_ObjFanin1(pObj), vGla, nUsageCount );
+    if ( Value0 || Value1 )
+        Vec_IntAddToEntry( vGla, Gia_ObjId(p, pObj), nUsageCount );
+    return Value0 || Value1;
+}
+Vec_Int_t * Gla_ManTranslate( Gla_Man_t * p )
+{
+    Vec_Int_t * vGla, * vGla2;
+    Gla_Obj_t * pObj, * pFanin;
+    Gia_Obj_t * pGiaObj;
+    int i, k, nUsageCount;
+    vGla = Vec_IntStart( Gia_ManObjNum(p->pGia) );
+    Gla_ManForEachObjAbs( p, pObj, i )
+    {
+        nUsageCount = Vec_IntEntry(p->vCoreCounts, pObj->iGiaObj);
+        assert( nUsageCount >= 0 );
+        if ( nUsageCount == 0 )
+            nUsageCount++;
+        pGiaObj = Gla_ManGiaObj( p, pObj );
+        if ( Gia_ObjIsConst0(pGiaObj) || Gia_ObjIsRo(p->pGia, pGiaObj) )
+        {
+            Vec_IntWriteEntry( vGla, pObj->iGiaObj, nUsageCount );
+            continue;
+        }
+        assert( Gia_ObjIsAnd(pGiaObj) );
+        Gia_ManIncrementTravId( p->pGia );
+        Gla_ObjForEachFanin( p, pObj, pFanin, k )
+            Gia_ObjSetTravIdCurrent( p->pGia, Gla_ManGiaObj(p, pFanin) );
+        Gla_ManTranslate_rec( p->pGia, pGiaObj, vGla, nUsageCount );
+    }
+    Vec_IntWriteEntry( vGla, 0, p->pPars->iFrame+1 );
+    if ( p->pGia->vLutConfigs ) // use mapping from new to old
+    {
+        vGla2 = Vec_IntStart( Gia_ManObjNum(p->pGia0) );
+        for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ )
+            if ( Vec_IntEntry(vGla, i) )
+                Vec_IntWriteEntry( vGla2, Vec_IntEntry(p->pGia->vLutConfigs, i), Vec_IntEntry(vGla, i) );
+        Vec_IntFree( vGla );
+        return vGla2;
+    }
+    return vGla;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collect pseudo-PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gla_ManCollectPPis( Gla_Man_t * p, Vec_Int_t * vPis )
+{
+    Vec_Int_t * vPPis;
+    Gla_Obj_t * pObj, * pFanin;
+    int i, k;
+    vPPis = Vec_IntAlloc( 1000 );
+    if ( vPis )
+        Vec_IntClear( vPis );
+    Gla_ManForEachObjAbs( p, pObj, i )
+    {
+        assert( pObj->fConst || pObj->fRo || pObj->fAnd );
+        Gla_ObjForEachFanin( p, pObj, pFanin, k )
+            if ( !pFanin->fPi && !pFanin->fAbs )
+                Vec_IntPush( vPPis, pObj->Fanins[k] );
+            else if ( vPis && pFanin->fPi && !pFanin->fAbs )
+                Vec_IntPush( vPis, pObj->Fanins[k] );
+    }
+    Vec_IntUniqify( vPPis );
+    Vec_IntReverseOrder( vPPis );
+    if ( vPis )
+        Vec_IntUniqify( vPis );
+    return vPPis;
+}
+int Gla_ManCountPPis( Gla_Man_t * p )
+{
+    Vec_Int_t * vPPis = Gla_ManCollectPPis( p, NULL );
+    int RetValue = Vec_IntSize( vPPis );
+    Vec_IntFree( vPPis );
+    return RetValue;
+}
+void Gla_ManExplorePPis( Gla_Man_t * p, Vec_Int_t * vPPis )
+{
+    static int Round = 0;
+    Gla_Obj_t * pObj, * pFanin;
+    int i, j, k, Count;
+    if ( (Round++ % 5) == 0 )
+        return;
+    j = 0;
+    Gla_ManForEachObjAbsVec( vPPis, p, pObj, i )
+    {
+        assert( pObj->fAbs == 0 );
+        Count = 0;
+        Gla_ObjForEachFanin( p, pObj, pFanin, k )
+            Count += pFanin->fAbs;
+        if ( Count == 0 || ((Round & 1) && Count == 1) )
+            continue;
+        Vec_IntWriteEntry( vPPis, j++, Gla_ObjId(p, pObj) );
+    }
+//    printf( "\n%d -> %d\n", Vec_IntSize(vPPis), j );
+    Vec_IntShrink( vPPis, j );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Adds CNF for the given timeframe.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gla_ManCheckVar( Gla_Man_t * p, int iObj, int iFrame )
+{
+    Gla_Obj_t * pGla = Gla_ManObj( p, iObj );
+    int iVar = Vec_IntGetEntry( &pGla->vFrames, iFrame );
+    assert( !pGla->fPo && !pGla->fRi );
+    return (iVar > 0);
+}
+int Gla_ManGetVar( Gla_Man_t * p, int iObj, int iFrame )
+{
+    Gla_Obj_t * pGla = Gla_ManObj( p, iObj );
+    int iVar = Vec_IntGetEntry( &pGla->vFrames, iFrame );
+    assert( !pGla->fPo && !pGla->fRi );
+    if ( iVar == 0 )
+    {
+        Vec_IntSetEntry( &pGla->vFrames, iFrame, (iVar = p->nSatVars++) );
+        // remember the change
+        Vec_IntPush( p->vAddedNew, iObj );
+        Vec_IntPush( p->vAddedNew, iFrame );
+    }
+    return iVar;
+}
+void Gla_ManAddClauses( Gla_Man_t * p, int iObj, int iFrame, Vec_Int_t * vLits )
+{
+    Gla_Obj_t * pGlaObj = Gla_ManObj( p, iObj );
+    int iVar, iVar1, iVar2;
+    if ( pGlaObj->fConst )
+    {
+        iVar = Gla_ManGetVar( p, iObj, iFrame );
+        sat_solver2_add_const( p->pSat, iVar, 1, 0, iObj );
+    }
+    else if ( pGlaObj->fRo )
+    {
+        assert( pGlaObj->nFanins == 1 );
+        if ( iFrame == 0 )
+        {
+            iVar = Gla_ManGetVar( p, iObj, iFrame );
+            sat_solver2_add_const( p->pSat, iVar, 1, 0, iObj );
+        }
+        else
+        {
+            iVar1 = Gla_ManGetVar( p, iObj, iFrame );
+            iVar2 = Gla_ManGetVar( p, pGlaObj->Fanins[0], iFrame-1 );
+            sat_solver2_add_buffer( p->pSat, iVar1, iVar2, pGlaObj->fCompl0, 0, iObj );
+        }
+    }
+    else if ( pGlaObj->fAnd )
+    {
+        int i, RetValue, nClauses, iFirstClause, * pLit;
+        nClauses = p->pCnf->pObj2Count[pGlaObj->iGiaObj];
+        iFirstClause = p->pCnf->pObj2Clause[pGlaObj->iGiaObj];
+        for ( i = iFirstClause; i < iFirstClause + nClauses; i++ )
+        {
+            Vec_IntClear( vLits );
+            for ( pLit = p->pCnf->pClauses[i]; pLit < p->pCnf->pClauses[i+1]; pLit++ )
+            {
+                iVar = Gla_ManGetVar( p, lit_var(*pLit), iFrame );
+                Vec_IntPush( vLits, toLitCond( iVar, lit_sign(*pLit) ) );
+            }
+            RetValue = sat_solver2_addclause( p->pSat, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits), iObj );
+        }
+    }
+    else assert( 0 );
+}
+void Gia_GlaAddToCounters( Gla_Man_t * p, Vec_Int_t * vCore )
+{
+    Gla_Obj_t * pGla;
+    int i;
+    Gla_ManForEachObjAbsVec( vCore, p, pGla, i )
+        Vec_IntAddToEntry( p->vCoreCounts, pGla->iGiaObj, 1 );
+}
+void Gia_GlaAddToAbs( Gla_Man_t * p, Vec_Int_t * vAbsAdd, int fCheck )
+{
+    Gla_Obj_t * pGla;
+    int i, k = 0;
+    Gla_ManForEachObjAbsVec( vAbsAdd, p, pGla, i )
+    {
+        if ( fCheck )
+        {
+            assert( pGla->fAbs == 0 );
+            if ( p->pSat->pPrf2 )
+                Vec_IntWriteEntry( p->vProofIds, Gla_ObjId(p, pGla), p->nProofIds++ );
+        }
+        if ( pGla->fAbs )
+            continue;
+        pGla->fAbs = 1;
+        Vec_IntPush( p->vAbs, Gla_ObjId(p, pGla) );
+        // filter clauses to remove those contained in the abstraction
+        Vec_IntWriteEntry( vAbsAdd, k++, Gla_ObjId(p, pGla) );
+    }
+    Vec_IntShrink( vAbsAdd, k );
+}
+void Gia_GlaAddTimeFrame( Gla_Man_t * p, int f )
+{
+    Gla_Obj_t * pObj;
+    int i;
+    Gla_ManForEachObjAbs( p, pObj, i )
+        Gla_ManAddClauses( p, Gla_ObjId(p, pObj), f, p->vTemp );
+    sat_solver2_simplify( p->pSat );
+}
+void Gia_GlaAddOneSlice( Gla_Man_t * p, int fCur, Vec_Int_t * vCore )
+{
+    int f, i, iGlaObj;
+    for ( f = fCur; f >= 0; f-- )
+        Vec_IntForEachEntry( vCore, iGlaObj, i )
+            Gla_ManAddClauses( p, iGlaObj, f, p->vTemp );
+    sat_solver2_simplify( p->pSat );
+}
+void Gla_ManRollBack( Gla_Man_t * p )
+{
+    int i, iObj, iFrame;
+    Vec_IntForEachEntryDouble( p->vAddedNew, iObj, iFrame, i )
+    {
+        assert( Vec_IntEntry( &Gla_ManObj(p, iObj)->vFrames, iFrame ) > 0 );
+        Vec_IntWriteEntry( &Gla_ManObj(p, iObj)->vFrames, iFrame, 0 );
+    }
+    Vec_IntForEachEntryStart( p->vAbs, iObj, i, p->nAbsOld )
+    {
+        assert( Gla_ManObj( p, iObj )->fAbs == 1 );
+        Gla_ManObj( p, iObj )->fAbs = 0;
+    }
+    Vec_IntShrink( p->vAbs, p->nAbsOld );
+}
+
+
+            
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the set of clauses involved in the UNSAT core.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gla_ManGetOutLit( Gla_Man_t * p, int f )
+{
+    Gla_Obj_t * pFanin = Gla_ManObj( p, p->pObjRoot->Fanins[0] );
+    int iSat = Vec_IntEntry( &pFanin->vFrames, f );
+    assert( iSat > 0 );
+    if ( f == 0 && pFanin->fRo && !p->pObjRoot->fCompl0 )
+        return -1;
+    return Abc_Var2Lit( iSat, p->pObjRoot->fCompl0 );
+}
+Vec_Int_t * Gla_ManUnsatCore( Gla_Man_t * p, int f, sat_solver2 * pSat, int nConfMax, int fVerbose, int * piRetValue, int * pnConfls )
+{
+    Vec_Int_t * vCore = NULL;
+    int nConfPrev = pSat->stats.conflicts;
+    int RetValue, iLit = Gla_ManGetOutLit( p, f );
+    abctime clk = Abc_Clock();
+    if ( piRetValue )
+        *piRetValue = 1;
+    // consider special case when PO points to the flop
+    // this leads to immediate conflict in the first timeframe
+    if ( iLit == -1 )
+    {
+        vCore = Vec_IntAlloc( 1 );
+        Vec_IntPush( vCore, p->pObjRoot->Fanins[0] );
+        return vCore;
+    }
+    // solve the problem
+    RetValue = sat_solver2_solve( pSat, &iLit, &iLit+1, (ABC_INT64_T)nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( pnConfls )
+        *pnConfls = (int)pSat->stats.conflicts - nConfPrev;
+    if ( RetValue == l_Undef )
+    {
+        if ( piRetValue )
+            *piRetValue = -1;
+        return NULL;
+    }
+    if ( RetValue == l_True )
+    {
+        if ( piRetValue )
+            *piRetValue = 0;
+        return NULL;
+    }
+    if ( fVerbose )
+    {
+//        Abc_Print( 1, "%6d", (int)pSat->stats.conflicts - nConfPrev );
+//        Abc_Print( 1, "UNSAT after %7d conflicts.      ", pSat->stats.conflicts );
+//        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    assert( RetValue == l_False );
+    // derive the UNSAT core
+    clk = Abc_Clock();
+    vCore = (Vec_Int_t *)Sat_ProofCore( pSat );
+    if ( vCore )
+        Vec_IntSort( vCore, 1 );
+    if ( fVerbose )
+    {
+//        Abc_Print( 1, "Core is %8d vars    (out of %8d).   ", Vec_IntSize(vCore), sat_solver2_nvars(pSat) );
+//        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    return vCore;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gla_ManAbsPrintFrame( Gla_Man_t * p, int nCoreSize, int nFrames, int nConfls, int nCexes, abctime Time )
+{
+    if ( Abc_FrameIsBatchMode() && nCoreSize <= 0 )
+        return;
+    Abc_Print( 1, "%4d :", nFrames-1 );
+    Abc_Print( 1, "%4d", Abc_MinInt(100, 100 * Gia_GlaAbsCount(p, 0, 0) / (p->nObjs - Gia_ManPoNum(p->pGia) + Gia_ManCoNum(p->pGia) + 1)) ); 
+    Abc_Print( 1, "%6d", Gia_GlaAbsCount(p, 0, 0) );
+    Abc_Print( 1, "%5d", Gla_ManCountPPis(p) );
+    Abc_Print( 1, "%5d", Gia_GlaAbsCount(p, 1, 0) );
+    Abc_Print( 1, "%6d", Gia_GlaAbsCount(p, 0, 1) );
+    Abc_Print( 1, "%8d", nConfls );
+    if ( nCexes == 0 )
+        Abc_Print( 1, "%5c", '-' ); 
+    else
+        Abc_Print( 1, "%5d", nCexes ); 
+//    Abc_Print( 1, " %9d", sat_solver2_nvars(p->pSat) ); 
+    Abc_PrintInt( sat_solver2_nvars(p->pSat) );
+    Abc_PrintInt( sat_solver2_nclauses(p->pSat) );
+    Abc_PrintInt( sat_solver2_nlearnts(p->pSat) );
+//    Abc_Print( 1, " %6d", nCoreSize > 0 ? nCoreSize : 0 ); 
+    Abc_Print( 1, "%9.2f sec", 1.0*Time/CLOCKS_PER_SEC );
+    Abc_Print( 1, "%5.0f MB", (sat_solver2_memory_proof(p->pSat) + sat_solver2_memory(p->pSat, 0)) / (1<<20) );
+//    Abc_PrintInt( p->nAbsNew );
+//    Abc_PrintInt( p->nLrnNew );
+//    Abc_Print( 1, "%4.1f MB", 4.0 * p->nLrnNew * Abc_BitWordNum(p->nAbsNew) / (1<<20) );
+    Abc_Print( 1, "%s", (nCoreSize > 0 && nCexes > 0) ? "\n" : "\r" );
+    fflush( stdout );
+}
+void Gla_ManReportMemory( Gla_Man_t * p )
+{
+    Gla_Obj_t * pGla;
+    double memTot = 0;
+    double memAig = Gia_ManObjNum(p->pGia) * sizeof(Gia_Obj_t);
+    double memSat = sat_solver2_memory( p->pSat, 1 );
+    double memPro = sat_solver2_memory_proof( p->pSat );
+    double memMap = p->nObjs * sizeof(Gla_Obj_t) + Gia_ManObjNum(p->pGia) * sizeof(int);
+    double memRef = Rnm_ManMemoryUsage( p->pRnm );
+    double memOth = sizeof(Gla_Man_t);
+    for ( pGla = p->pObjs; pGla < p->pObjs + p->nObjs; pGla++ )
+        memMap += Vec_IntCap(&pGla->vFrames) * sizeof(int);
+    memOth += Vec_IntCap(p->vAddedNew) * sizeof(int);
+    memOth += Vec_IntCap(p->vTemp) * sizeof(int);
+    memOth += Vec_IntCap(p->vAbs) * sizeof(int);
+    memTot = memAig + memSat + memPro + memMap + memRef + memOth;
+    ABC_PRMP( "Memory: AIG      ", memAig, memTot );
+    ABC_PRMP( "Memory: SAT      ", memSat, memTot );
+    ABC_PRMP( "Memory: Proof    ", memPro, memTot );
+    ABC_PRMP( "Memory: Map      ", memMap, memTot );
+    ABC_PRMP( "Memory: Refine   ", memRef, memTot );
+    ABC_PRMP( "Memory: Other    ", memOth, memTot );
+    ABC_PRMP( "Memory: TOTAL    ", memTot, memTot );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Send abstracted model or send cancel.]
+
+  Description [Counter-example will be sent automatically when &vta terminates.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_GlaSendAbsracted( Gla_Man_t * p, int fVerbose )
+{
+    Gia_Man_t * pAbs;
+    Vec_Int_t * vGateClasses;
+    assert( Abc_FrameIsBridgeMode() );
+//    if ( fVerbose )
+//        Abc_Print( 1, "Sending abstracted model...\n" );
+    // create abstraction (value of p->pGia is not used here)
+    vGateClasses = Gla_ManTranslate( p );
+    pAbs = Gia_ManDupAbsGates( p->pGia0, vGateClasses );
+    Vec_IntFreeP( &vGateClasses );
+    // send it out
+    Gia_ManToBridgeAbsNetlist( stdout, pAbs, BRIDGE_ABS_NETLIST );
+    Gia_ManStop( pAbs );
+}
+void Gia_GlaSendCancel( Gla_Man_t * p, int fVerbose )
+{
+    extern int Gia_ManToBridgeBadAbs( FILE * pFile );
+    assert( Abc_FrameIsBridgeMode() );
+//    if ( fVerbose )
+//        Abc_Print( 1, "Cancelling previously sent model...\n" );
+    Gia_ManToBridgeBadAbs( stdout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Send abstracted model or send cancel.]
+
+  Description [Counter-example will be sent automatically when &vta terminates.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_GlaDumpAbsracted( Gla_Man_t * p, int fVerbose )
+{
+    char * pFileNameDef = "glabs.aig";
+    char * pFileName = p->pPars->pFileVabs ? p->pPars->pFileVabs : pFileNameDef;
+    Gia_Man_t * pAbs;
+    Vec_Int_t * vGateClasses;
+    if ( fVerbose )
+        Abc_Print( 1, "Dumping abstracted model into file \"%s\"...\n", pFileName );
+    // create abstraction
+    vGateClasses = Gla_ManTranslate( p );
+    pAbs = Gia_ManDupAbsGates( p->pGia0, vGateClasses );
+    Vec_IntFreeP( &vGateClasses );
+    // write into file
+    Gia_AigerWrite( pAbs, pFileName, 0, 0 );
+    Gia_ManStop( pAbs );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs gate-level abstraction]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManPerformGlaOld( Gia_Man_t * pAig, Abs_Par_t * pPars, int fStartVta )
+{
+    extern int Gia_VtaPerformInt( Gia_Man_t * pAig, Abs_Par_t * pPars );
+    extern void Ga2_ManDumpStats( Gia_Man_t * pGia, Abs_Par_t * pPars, sat_solver2 * pSat, int iFrame, int fUseN );
+    Gla_Man_t * p;
+    Vec_Int_t * vPPis, * vCore;//, * vCore2 = NULL;
+    Abc_Cex_t * pCex = NULL;
+    int f, i, iPrev, nConfls, Status, nVarsOld = 0, nCoreSize, fOneIsSent = 0, RetValue = -1;
+    abctime clk2, clk = Abc_Clock();
+    // preconditions
+    assert( Gia_ManPoNum(pAig) == 1 );
+    assert( pPars->nFramesMax == 0 || pPars->nFramesStart <= pPars->nFramesMax );
+    if ( Gia_ObjIsConst0(Gia_ObjFanin0(Gia_ManPo(pAig,0))) )
+    {
+        if ( !Gia_ObjFaninC0(Gia_ManPo(pAig,0)) )
+        {
+            printf( "Sequential miter is trivially UNSAT.\n" );
+            return 1;
+        }
+        ABC_FREE( pAig->pCexSeq );
+        pAig->pCexSeq = Abc_CexMakeTriv( Gia_ManRegNum(pAig), Gia_ManPiNum(pAig), 1, 0 );
+        printf( "Sequential miter is trivially SAT.\n" );
+        return 0;
+    }
+
+    // compute intial abstraction
+    if ( pAig->vGateClasses == NULL )
+    {
+        if ( fStartVta )
+        {
+            int nFramesMaxOld   = pPars->nFramesMax;
+            int nFramesStartOld = pPars->nFramesStart;
+            int nTimeOutOld     = pPars->nTimeOut;
+            int nDumpOld        = pPars->fDumpVabs;
+            pPars->nFramesMax   = pPars->nFramesStart;
+            pPars->nFramesStart = Abc_MinInt( pPars->nFramesStart/2 + 1, 3 );
+            pPars->nTimeOut     = 20;
+            pPars->fDumpVabs    = 0;
+            RetValue = Gia_VtaPerformInt( pAig, pPars );
+            pPars->nFramesMax   = nFramesMaxOld;
+            pPars->nFramesStart = nFramesStartOld;
+            pPars->nTimeOut     = nTimeOutOld;
+            pPars->fDumpVabs    = nDumpOld;
+            // create gate classes
+            Vec_IntFreeP( &pAig->vGateClasses );
+            if ( pAig->vObjClasses )
+                pAig->vGateClasses = Gia_VtaConvertToGla( pAig, pAig->vObjClasses );
+            Vec_IntFreeP( &pAig->vObjClasses );
+            // return if VTA solve the problem if could not start
+            if ( RetValue == 0 || pAig->vGateClasses == NULL )
+                return RetValue;
+        }
+        else
+        {
+            pAig->vGateClasses = Vec_IntStart( Gia_ManObjNum(pAig) );
+            Vec_IntWriteEntry( pAig->vGateClasses, 0, 1 );
+            Vec_IntWriteEntry( pAig->vGateClasses, Gia_ObjFaninId0p(pAig, Gia_ManPo(pAig, 0)), 1 );
+        }
+    }
+    // start the manager
+    p = Gla_ManStart( pAig, pPars );
+    p->timeInit = Abc_Clock() - clk;
+    // set runtime limit
+    if ( p->pPars->nTimeOut )
+        sat_solver2_set_runtime_limit( p->pSat, p->pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock() );
+    // perform initial abstraction
+    if ( p->pPars->fVerbose )
+    {
+        Abc_Print( 1, "Running gate-level abstraction (GLA) with the following parameters:\n" );
+        Abc_Print( 1, "FrameMax = %d  ConfMax = %d  Timeout = %d  RatioMin = %d %%.\n", 
+            pPars->nFramesMax, pPars->nConfLimit, pPars->nTimeOut, pPars->nRatioMin );
+        Abc_Print( 1, "LearnStart = %d  LearnDelta = %d  LearnRatio = %d %%.\n", 
+            pPars->nLearnedStart, pPars->nLearnedDelta, pPars->nLearnedPerce );
+        Abc_Print( 1, " Frame   %%   Abs  PPI   FF   LUT   Confl  Cex   Vars   Clas   Lrns     Time        Mem\n" );
+    }
+    for ( f = i = iPrev = 0; !p->pPars->nFramesMax || f < p->pPars->nFramesMax; f++, iPrev = i )
+    {
+        int nConflsBeg = sat_solver2_nconflicts(p->pSat);
+        p->pPars->iFrame = f;
+
+        // load timeframe
+        Gia_GlaAddTimeFrame( p, f );
+
+        // iterate as long as there are counter-examples
+        for ( i = 0; ; i++ )
+        { 
+            clk2 = Abc_Clock();
+            vCore = Gla_ManUnsatCore( p, f, p->pSat, pPars->nConfLimit, pPars->fVerbose, &Status, &nConfls );
+//            assert( (vCore != NULL) == (Status == 1) );
+            if ( Status == -1 || (p->pSat->nRuntimeLimit && Abc_Clock() > p->pSat->nRuntimeLimit) ) // resource limit is reached
+            {
+                Prf_ManStopP( &p->pSat->pPrf2 );
+//                if ( Gia_ManRegNum(p->pGia) > 1 ) // for comb cases, return the abstraction
+//                    Vec_IntShrink( p->vAbs, p->nAbsOld );
+                goto finish;
+            }
+            if ( Status == 1 )
+            {
+                Prf_ManStopP( &p->pSat->pPrf2 );
+                p->timeUnsat += Abc_Clock() - clk2;
+                break;
+            } 
+            p->timeSat += Abc_Clock() - clk2;
+            assert( Status == 0 );
+            p->nCexes++;
+
+            // cancel old one if it was sent
+            if ( Abc_FrameIsBridgeMode() && fOneIsSent )
+            {
+                Gia_GlaSendCancel( p, pPars->fVerbose );
+                fOneIsSent = 0;
+            }
+
+            // perform the refinement
+            clk2 = Abc_Clock();
+            if ( pPars->fAddLayer )
+            {
+                vPPis = Gla_ManCollectPPis( p, NULL );
+//                Gla_ManExplorePPis( p, vPPis );
+            }
+            else
+            {
+                vPPis = Gla_ManRefinement( p );
+                if ( vPPis == NULL )
+                {
+                    Prf_ManStopP( &p->pSat->pPrf2 );
+                    pCex = p->pGia->pCexSeq; p->pGia->pCexSeq = NULL;
+                    break;
+                }
+            } 
+            assert( pCex == NULL );
+
+            // start proof logging
+            if ( i == 0 )
+            {
+                // create bookmark to be used for rollback
+                sat_solver2_bookmark( p->pSat );
+                Vec_IntClear( p->vAddedNew );
+                p->nAbsOld = Vec_IntSize( p->vAbs );
+                nVarsOld = p->nSatVars;
+//                p->nLrnOld = sat_solver2_nlearnts( p->pSat );
+//                p->nAbsNew = 0;
+//                p->nLrnNew = 0;
+
+                // start incremental proof manager
+                assert( p->pSat->pPrf2 == NULL );
+                if ( p->pSat->pPrf1 == NULL )
+                    p->pSat->pPrf2 = Prf_ManAlloc();
+                if ( p->pSat->pPrf2 )
+                {
+                    p->nProofIds = 0;
+                    Vec_IntFill( p->vProofIds, Gia_ManObjNum(p->pGia), -1 );
+                    Prf_ManRestart( p->pSat->pPrf2, p->vProofIds, sat_solver2_nlearnts(p->pSat), Vec_IntSize(vPPis) );
+                }
+            }
+            else
+            {
+                // resize the proof logger
+                if ( p->pSat->pPrf2 )
+                    Prf_ManGrow( p->pSat->pPrf2, p->nProofIds + Vec_IntSize(vPPis) );
+            }
+
+            Gia_GlaAddToAbs( p, vPPis, 1 );
+            Gia_GlaAddOneSlice( p, f, vPPis );
+            Vec_IntFree( vPPis );
+
+            // print the result (do not count it towards change)
+            if ( p->pPars->fVerbose )
+            Gla_ManAbsPrintFrame( p, -1, f+1, sat_solver2_nconflicts(p->pSat)-nConflsBeg, i, Abc_Clock() - clk );
+        }
+        if ( pCex != NULL )
+            break;
+        assert( Status == 1 );
+
+        // valid core is obtained
+        nCoreSize = 1;
+        if ( vCore )
+        {
+            nCoreSize += Vec_IntSize( vCore );
+            Gia_GlaAddToCounters( p, vCore );
+        }
+        if ( i == 0 )
+        {
+            p->pPars->nFramesNoChange++;
+            Vec_IntFreeP( &vCore );
+        }
+        else
+        {
+            p->pPars->nFramesNoChange = 0;
+//            p->nAbsNew = Vec_IntSize( p->vAbs ) - p->nAbsOld;
+//            p->nLrnNew = Abc_AbsInt( sat_solver2_nlearnts( p->pSat ) - p->nLrnOld );
+            // update the SAT solver
+            sat_solver2_rollback( p->pSat );
+            // update storage
+            Gla_ManRollBack( p );
+            p->nSatVars = nVarsOld;
+            // load this timeframe
+            Gia_GlaAddToAbs( p, vCore, 0 );
+            Gia_GlaAddOneSlice( p, f, vCore );
+            Vec_IntFree( vCore );
+            // run SAT solver
+            clk2 = Abc_Clock();
+            vCore = Gla_ManUnsatCore( p, f, p->pSat, pPars->nConfLimit, p->pPars->fVerbose, &Status, &nConfls );
+            p->timeUnsat += Abc_Clock() - clk2;
+//            assert( (vCore != NULL) == (Status == 1) );
+            Vec_IntFreeP( &vCore );
+            if ( Status == -1 ) // resource limit is reached
+                break;
+            if ( Status == 0 )
+            {
+                assert( 0 );
+    //            Vta_ManSatVerify( p );
+                // make sure, there was no initial abstraction (otherwise, it was invalid)
+                assert( pAig->vObjClasses == NULL && f < p->pPars->nFramesStart );
+    //            pCex = Vga_ManDeriveCex( p );
+                break;
+            }
+        }
+        // print the result
+        if ( p->pPars->fVerbose )
+        Gla_ManAbsPrintFrame( p, nCoreSize, f+1, sat_solver2_nconflicts(p->pSat)-nConflsBeg, i, Abc_Clock() - clk );
+
+        if ( f > 2 && iPrev > 0 && i == 0 ) // change has happened
+        {
+            if ( Abc_FrameIsBridgeMode() )
+            {
+                // cancel old one if it was sent
+                if ( fOneIsSent )
+                    Gia_GlaSendCancel( p, pPars->fVerbose );
+                // send new one 
+                Gia_GlaSendAbsracted( p, pPars->fVerbose );
+                fOneIsSent = 1;
+            }
+
+            // dump the model into file
+            if ( p->pPars->fDumpVabs )
+            {
+                char Command[1000];
+                Abc_FrameSetStatus( -1 );
+                Abc_FrameSetCex( NULL );
+                Abc_FrameSetNFrames( f+1 );
+                sprintf( Command, "write_status %s", Extra_FileNameGenericAppend((char *)(p->pPars->pFileVabs ? p->pPars->pFileVabs : "glabs.aig"), ".status") );
+                Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command );
+                Gia_GlaDumpAbsracted( p, pPars->fVerbose );
+            }
+        }
+
+        // check if the number of objects is below limit
+        if ( Gia_GlaAbsCount(p,0,0) >= (p->nObjs - 1) * (100 - pPars->nRatioMin) / 100 )
+        {
+            Status = -1;
+            break;
+        }
+    }
+finish:
+    // analize the results
+    if ( pCex == NULL )
+    {
+        if ( p->pPars->fVerbose && Status == -1 )
+            printf( "\n" );
+//        if ( pAig->vGateClasses != NULL )
+//            Abc_Print( 1, "Replacing the old abstraction by a new one.\n" );
+        Vec_IntFreeP( &pAig->vGateClasses );
+        pAig->vGateClasses = Gla_ManTranslate( p );
+        if ( Status == -1 )
+        {
+            if ( p->pPars->nTimeOut && Abc_Clock() >= p->pSat->nRuntimeLimit ) 
+                Abc_Print( 1, "Timeout %d sec in frame %d with a %d-stable abstraction.    ", p->pPars->nTimeOut, f, p->pPars->nFramesNoChange );
+            else if ( pPars->nConfLimit && sat_solver2_nconflicts(p->pSat) >= pPars->nConfLimit )
+                Abc_Print( 1, "Exceeded %d conflicts in frame %d with a %d-stable abstraction.  ", pPars->nConfLimit, f, p->pPars->nFramesNoChange );
+            else if ( Gia_GlaAbsCount(p,0,0) >= (p->nObjs - 1) * (100 - pPars->nRatioMin) / 100 )
+                Abc_Print( 1, "The ratio of abstracted objects is less than %d %% in frame %d.  ", pPars->nRatioMin, f );
+            else
+                Abc_Print( 1, "Abstraction stopped for unknown reason in frame %d.  ", f );
+        }
+        else
+        {
+            p->pPars->iFrame++;
+            Abc_Print( 1, "GLA completed %d frames with a %d-stable abstraction.  ", f, p->pPars->nFramesNoChange );
+        }
+    }
+    else
+    {
+        if ( p->pPars->fVerbose )
+            printf( "\n" );
+        ABC_FREE( pAig->pCexSeq );
+        pAig->pCexSeq = pCex;
+        if ( !Gia_ManVerifyCex( pAig, pCex, 0 ) )
+            Abc_Print( 1, "    Gia_ManPerformGlaOld(): CEX verification has failed!\n" );
+        Abc_Print( 1, "Counter-example detected in frame %d.  ", f );
+        p->pPars->iFrame = pCex->iFrame - 1;
+        Vec_IntFreeP( &pAig->vGateClasses );
+        RetValue = 0;
+    }
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    if ( p->pPars->fVerbose )
+    {
+        p->timeOther = (Abc_Clock() - clk) - p->timeUnsat - p->timeSat - p->timeCex - p->timeInit;
+        ABC_PRTP( "Runtime: Initializing", p->timeInit,   Abc_Clock() - clk );
+        ABC_PRTP( "Runtime: Solver UNSAT", p->timeUnsat,  Abc_Clock() - clk );
+        ABC_PRTP( "Runtime: Solver SAT  ", p->timeSat,    Abc_Clock() - clk );
+        ABC_PRTP( "Runtime: Refinement  ", p->timeCex,    Abc_Clock() - clk );
+        ABC_PRTP( "Runtime: Other       ", p->timeOther,  Abc_Clock() - clk );
+        ABC_PRTP( "Runtime: TOTAL       ", Abc_Clock() - clk, Abc_Clock() - clk );
+        Gla_ManReportMemory( p );
+    }
+//    Ga2_ManDumpStats( pAig, p->pPars, p->pSat, p->pPars->iFrame, 1 );
+    Gla_ManStop( p );
+    fflush( stdout );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/absIter.c b/abc-build/src/proof/abs/absIter.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absIter.c
@@ -0,0 +1,148 @@
+/**CFile****************************************************************
+
+  FileName    [absIter.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Abstraction package.]
+
+  Synopsis    [Iterative improvement of abstraction.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: absIter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abs.h"
+#include "sat/bmc/bmc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int  Gia_ObjIsInGla( Gia_Man_t * p, Gia_Obj_t * pObj )    { return Vec_IntEntry(p->vGateClasses, Gia_ObjId(p, pObj));  }
+static inline void Gia_ObjAddToGla( Gia_Man_t * p, Gia_Obj_t * pObj )   { Vec_IntWriteEntry(p->vGateClasses, Gia_ObjId(p, pObj), 1); }
+static inline void Gia_ObjRemFromGla( Gia_Man_t * p, Gia_Obj_t * pObj ) { Vec_IntWriteEntry(p->vGateClasses, Gia_ObjId(p, pObj), 0); }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_IterTryImprove( Gia_Man_t * p, int nTimeOut, int iFrame0 )
+{
+    Gia_Man_t * pAbs = Gia_ManDupAbsGates( p, p->vGateClasses );
+    Aig_Man_t * pAig = Gia_ManToAigSimple( pAbs );
+    int nStart      =            0;
+    int nFrames     =  iFrame0 ? iFrame0 + 1 : 10000000;
+    int nNodeDelta  =         2000;
+    int nBTLimit    =            0;
+    int nBTLimitAll =            0;
+    int fVerbose    =            0;
+    int RetValue, iFrame; 
+    RetValue = Saig_BmcPerform( pAig, nStart, nFrames, nNodeDelta, nTimeOut, nBTLimit, nBTLimitAll, fVerbose, 0, &iFrame, 1 );
+    assert( RetValue == 0 || RetValue == -1 );
+    Aig_ManStop( pAig );
+    Gia_ManStop( pAbs );
+    return iFrame;
+}
+Gia_Man_t * Gia_ManShrinkGla( Gia_Man_t * p, int nFrameMax, int nTimeOut, int fUsePdr, int fUseSat, int fUseBdd, int fVerbose )
+{
+    Gia_Obj_t * pObj;
+    int i, iFrame0, iFrame;
+    int nTotal = 0, nRemoved = 0;
+    Vec_Int_t * vGScopy;
+    abctime clk, clkTotal = Abc_Clock();
+    assert( Gia_ManPoNum(p) == 1 );
+    assert( p->vGateClasses != NULL );
+    vGScopy = Vec_IntDup( p->vGateClasses );
+    if ( nFrameMax == 0 )
+        iFrame0 = Gia_IterTryImprove( p, 0, 0 );
+    else
+        iFrame0 = nFrameMax - 1;
+    while ( 1 )
+    {
+        int fChanges = 0;
+        Gia_ManForEachObj1( p, pObj, i )
+        {
+            if ( pObj->fMark0 )
+                continue;
+            if ( !Gia_ObjIsInGla(p, pObj) )
+                continue;
+            if ( pObj == Gia_ObjFanin0( Gia_ManPo(p, 0) ) )
+                continue;
+            if ( Gia_ObjIsAnd(pObj) )
+            {
+                if ( Gia_ObjIsInGla(p, Gia_ObjFanin0(pObj)) && Gia_ObjIsInGla(p, Gia_ObjFanin1(pObj)) )
+                    continue;
+            }
+            if ( Gia_ObjIsRo(p, pObj) )
+            {
+                if ( Gia_ObjIsInGla(p, Gia_ObjFanin0(Gia_ObjRoToRi(p, pObj))) )
+                    continue;
+            }        
+            clk = Abc_Clock();
+            printf( "%5d : ", nTotal );
+            printf( "Obj =%7d   ", i );
+            Gia_ObjRemFromGla( p, pObj );
+            iFrame = Gia_IterTryImprove( p, nTimeOut, iFrame0 );
+            if ( nFrameMax )
+                assert( iFrame <= nFrameMax );
+            else
+                assert( iFrame <= iFrame0 );
+            printf( "Frame =%6d   ", iFrame );
+            if ( iFrame < iFrame0 )
+            {
+                pObj->fMark0 = 1;
+                Gia_ObjAddToGla( p, pObj );
+                printf( "           " );
+            }
+            else
+            {
+                fChanges = 1;
+                nRemoved++;
+                printf( "Removing   " );
+                Vec_IntWriteEntry( vGScopy, Gia_ObjId(p, pObj), 0 );
+            }
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+            nTotal++;
+            // update the classes
+            Vec_IntFreeP( &p->vGateClasses );
+            p->vGateClasses = Vec_IntDup(vGScopy);
+        }
+        if ( !fChanges )
+            break;
+    }
+    Gia_ManCleanMark0(p);
+    Vec_IntFree( vGScopy );
+    printf( "Tried = %d.  ",     nTotal );
+    printf( "Removed = %d. (%.2f %%)  ",  nRemoved, 100.0 * nRemoved / Vec_IntCountPositive(p->vGateClasses) );
+    Abc_PrintTime( 1, "Time",  Abc_Clock() - clkTotal );
+    return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/absOldCex.c b/abc-build/src/proof/abs/absOldCex.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absOldCex.c
@@ -0,0 +1,873 @@
+/**CFile****************************************************************
+
+  FileName    [saigAbsCba.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [CEX-based abstraction.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigAbsCba.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abs.h"
+#include "sat/bmc/bmc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// local manager
+typedef struct Saig_ManCba_t_ Saig_ManCba_t;
+struct Saig_ManCba_t_
+{
+    // user data
+    Aig_Man_t * pAig;       // user's AIG
+    Abc_Cex_t * pCex;       // user's CEX
+    int         nInputs;    // the number of first inputs to skip
+    int         fVerbose;   // verbose flag
+    // unrolling
+    Aig_Man_t * pFrames;    // unrolled timeframes
+    Vec_Int_t * vMapPiF2A;  // mapping of frame PIs into real PIs
+    // additional information
+    Vec_Vec_t * vReg2Frame; // register to frame mapping
+    Vec_Vec_t * vReg2Value; // register to value mapping
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    [Selects the best flops from the given array.]
+
+  Description [Selects the best 'nFfsToSelect' flops among the array 
+  'vAbsFfsToAdd' of flops that should be added to the abstraction.
+  To this end, this procedure simulates the original AIG (pAig) using
+  the given CEX (pAbsCex), which was detected for the abstraction.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManCbaFilterFlops( Aig_Man_t * pAig, Abc_Cex_t * pAbsCex, Vec_Int_t * vFlopClasses, Vec_Int_t * vAbsFfsToAdd, int nFfsToSelect )
+{
+    Aig_Obj_t * pObj, * pObjRi, * pObjRo;
+    Vec_Int_t * vMapEntries, * vFlopCosts, * vFlopAddCosts, * vFfsToAddBest;
+    int i, k, f, Entry, iBit, * pPerm;
+    assert( Aig_ManRegNum(pAig) == Vec_IntSize(vFlopClasses) );
+    assert( Vec_IntSize(vAbsFfsToAdd) > nFfsToSelect );
+    // map previously abstracted flops into their original numbers
+    vMapEntries = Vec_IntAlloc( Vec_IntSize(vFlopClasses) );
+    Vec_IntForEachEntry( vFlopClasses, Entry, i )
+        if ( Entry == 0 )
+            Vec_IntPush( vMapEntries, i );
+    // simulate one frame at a time
+    assert( Saig_ManPiNum(pAig) + Vec_IntSize(vMapEntries) == pAbsCex->nPis );
+    vFlopCosts = Vec_IntStart( Vec_IntSize(vMapEntries) );
+    // initialize the flops
+    Aig_ManCleanMarkB(pAig);
+    Aig_ManConst1(pAig)->fMarkB = 1;
+    Saig_ManForEachLo( pAig, pObj, i )
+        pObj->fMarkB = 0;
+    for ( f = 0; f < pAbsCex->iFrame; f++ )
+    {
+        // override the flop values according to the cex
+        iBit = pAbsCex->nRegs + f * pAbsCex->nPis + Saig_ManPiNum(pAig);
+        Vec_IntForEachEntry( vMapEntries, Entry, k )
+            Saig_ManLo(pAig, Entry)->fMarkB = Abc_InfoHasBit(pAbsCex->pData, iBit + k);
+        // simulate
+        Aig_ManForEachNode( pAig, pObj, k )
+            pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & 
+                           (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj));
+        Aig_ManForEachCo( pAig, pObj, k )
+            pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj);
+        // transfer
+        Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k )
+            pObjRo->fMarkB = pObjRi->fMarkB;
+        // compare
+        iBit = pAbsCex->nRegs + (f + 1) * pAbsCex->nPis + Saig_ManPiNum(pAig);
+        Vec_IntForEachEntry( vMapEntries, Entry, k )
+            if ( Saig_ManLi(pAig, Entry)->fMarkB != (unsigned)Abc_InfoHasBit(pAbsCex->pData, iBit + k) )
+                Vec_IntAddToEntry( vFlopCosts, k, 1 );
+    }
+//    Vec_IntForEachEntry( vFlopCosts, Entry, i )
+//        printf( "%d ", Entry );
+//    printf( "\n" );
+    // remap the cost
+    vFlopAddCosts = Vec_IntAlloc( Vec_IntSize(vAbsFfsToAdd) );
+    Vec_IntForEachEntry( vAbsFfsToAdd, Entry, i )
+        Vec_IntPush( vFlopAddCosts, -Vec_IntEntry(vFlopCosts, Entry) );
+    // sort the flops
+    pPerm = Abc_MergeSortCost( Vec_IntArray(vFlopAddCosts), Vec_IntSize(vFlopAddCosts) );
+    // shrink the array
+    vFfsToAddBest = Vec_IntAlloc( nFfsToSelect );
+    for ( i = 0; i < nFfsToSelect; i++ )
+    {
+//        printf( "%d ", Vec_IntEntry(vFlopAddCosts, pPerm[i]) );
+        Vec_IntPush( vFfsToAddBest, Vec_IntEntry(vAbsFfsToAdd, pPerm[i]) );
+    }
+//    printf( "\n" );
+    // cleanup
+    ABC_FREE( pPerm );
+    Vec_IntFree( vMapEntries );
+    Vec_IntFree( vFlopCosts );
+    Vec_IntFree( vFlopAddCosts );
+    Aig_ManCleanMarkB(pAig);
+    // return the computed flops
+    return vFfsToAddBest;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicate with literals.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManDupWithCubes( Aig_Man_t * pAig, Vec_Vec_t * vReg2Value )
+{
+    Vec_Int_t * vLevel;
+    Aig_Man_t * pAigNew;
+    Aig_Obj_t * pObj, * pMiter;
+    int i, k, Lit;
+    assert( pAig->nConstrs == 0 );
+    // start the new manager
+    pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) + Vec_VecSizeSize(vReg2Value) );
+    pAigNew->pName = Abc_UtilStrsav( pAig->pName );
+    // map the constant node
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew );
+    // create variables for PIs
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pAigNew );
+    // add internal nodes of this frame
+    Aig_ManForEachNode( pAig, pObj, i )
+        pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // create POs for cubes
+    Vec_VecForEachLevelInt( vReg2Value, vLevel, i )
+    {
+        pMiter = Aig_ManConst1( pAigNew );
+        Vec_IntForEachEntry( vLevel, Lit, k )
+        {
+            pObj = Saig_ManLi( pAig, Abc_Lit2Var(Lit) );
+            pMiter = Aig_And( pAigNew, pMiter, Aig_NotCond(Aig_ObjChild0Copy(pObj), Abc_LitIsCompl(Lit)) );
+        }
+        Aig_ObjCreateCo( pAigNew, pMiter );
+    }
+    // transfer to register outputs
+    Saig_ManForEachLi( pAig, pObj, i )
+        Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) );
+    // finalize
+    Aig_ManCleanup( pAigNew );
+    Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) );
+    return pAigNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Maps array of frame PI IDs into array of additional PI IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManCbaReason2Inputs( Saig_ManCba_t * p, Vec_Int_t * vReasons )
+{
+    Vec_Int_t * vOriginal, * vVisited;
+    int i, Entry;
+    vOriginal = Vec_IntAlloc( Saig_ManPiNum(p->pAig) ); 
+    vVisited = Vec_IntStart( Saig_ManPiNum(p->pAig) );
+    Vec_IntForEachEntry( vReasons, Entry, i )
+    {
+        int iInput = Vec_IntEntry( p->vMapPiF2A, 2*Entry );
+        assert( iInput >= p->nInputs && iInput < Aig_ManCiNum(p->pAig) );
+        if ( Vec_IntEntry(vVisited, iInput) == 0 )
+            Vec_IntPush( vOriginal, iInput - p->nInputs );
+        Vec_IntAddToEntry( vVisited, iInput, 1 );
+    }
+    Vec_IntFree( vVisited );
+    return vOriginal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Saig_ManCbaReason2Cex( Saig_ManCba_t * p, Vec_Int_t * vReasons )
+{
+    Abc_Cex_t * pCare;
+    int i, Entry, iInput, iFrame;
+    pCare = Abc_CexDup( p->pCex, p->pCex->nRegs );
+    memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) );
+    Vec_IntForEachEntry( vReasons, Entry, i )
+    {
+        assert( Entry >= 0 && Entry < Aig_ManCiNum(p->pFrames) );
+        iInput = Vec_IntEntry( p->vMapPiF2A, 2*Entry );
+        iFrame = Vec_IntEntry( p->vMapPiF2A, 2*Entry+1 );
+        Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput );
+    }
+/*
+    for ( iFrame = 0; iFrame <= pCare->iFrame; iFrame++ )
+    {
+        int Count = 0;
+        for ( i = 0; i < pCare->nPis; i++ )
+            Count +=  Abc_InfoHasBit(pCare->pData, pCare->nRegs + pCare->nPis * iFrame + i);
+        printf( "%d ", Count );
+    }
+printf( "\n" );
+*/
+    return pCare;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns reasons for the property to fail.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManCbaFindReason_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vPrios, Vec_Int_t * vReasons )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Aig_ObjIsConst1(pObj) )
+        return;
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        Vec_IntPush( vReasons, Aig_ObjCioId(pObj) );
+        return;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    if ( pObj->fPhase )
+    {
+        Saig_ManCbaFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons );
+        Saig_ManCbaFindReason_rec( p, Aig_ObjFanin1(pObj), vPrios, vReasons );
+    }
+    else
+    {
+        int fPhase0 = Aig_ObjFaninC0(pObj) ^ Aig_ObjFanin0(pObj)->fPhase;
+        int fPhase1 = Aig_ObjFaninC1(pObj) ^ Aig_ObjFanin1(pObj)->fPhase;
+        assert( !fPhase0 || !fPhase1 );
+        if ( !fPhase0 && fPhase1 )
+            Saig_ManCbaFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons );
+        else if ( fPhase0 && !fPhase1 )
+            Saig_ManCbaFindReason_rec( p, Aig_ObjFanin1(pObj), vPrios, vReasons );
+        else 
+        {
+            int iPrio0 = Vec_IntEntry( vPrios, Aig_ObjFaninId0(pObj) );
+            int iPrio1 = Vec_IntEntry( vPrios, Aig_ObjFaninId1(pObj) );
+            if ( iPrio0 <= iPrio1 )
+                Saig_ManCbaFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons );
+            else
+                Saig_ManCbaFindReason_rec( p, Aig_ObjFanin1(pObj), vPrios, vReasons );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns reasons for the property to fail.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManCbaFindReason( Saig_ManCba_t * p )
+{
+    Aig_Obj_t * pObj;
+    Vec_Int_t * vPrios, * vReasons;
+    int i;
+
+    // set PI values according to CEX
+    vPrios = Vec_IntStartFull( Aig_ManObjNumMax(p->pFrames) );
+    Aig_ManConst1(p->pFrames)->fPhase = 1;
+    Aig_ManForEachCi( p->pFrames, pObj, i )
+    {
+        int iInput = Vec_IntEntry( p->vMapPiF2A, 2*i );
+        int iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 );
+        pObj->fPhase = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput );
+        Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), i );
+    }
+
+    // traverse and set the priority
+    Aig_ManForEachNode( p->pFrames, pObj, i )
+    {
+        int fPhase0 = Aig_ObjFaninC0(pObj) ^ Aig_ObjFanin0(pObj)->fPhase;
+        int fPhase1 = Aig_ObjFaninC1(pObj) ^ Aig_ObjFanin1(pObj)->fPhase;
+        int iPrio0  = Vec_IntEntry( vPrios, Aig_ObjFaninId0(pObj) );
+        int iPrio1  = Vec_IntEntry( vPrios, Aig_ObjFaninId1(pObj) );
+        pObj->fPhase = fPhase0 && fPhase1;
+        if ( fPhase0 && fPhase1 ) // both are one
+            Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), Abc_MaxInt(iPrio0, iPrio1) );
+        else if ( !fPhase0 && fPhase1 ) 
+            Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), iPrio0 );
+        else if ( fPhase0 && !fPhase1 )
+            Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), iPrio1 );
+        else // both are zero
+            Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), Abc_MinInt(iPrio0, iPrio1) );
+    }
+    // check the property output
+    pObj = Aig_ManCo( p->pFrames, 0 );
+    pObj->fPhase = Aig_ObjFaninC0(pObj) ^ Aig_ObjFanin0(pObj)->fPhase;
+    assert( !pObj->fPhase );
+
+    // select the reason
+    vReasons = Vec_IntAlloc( 100 );
+    Aig_ManIncrementTravId( p->pFrames );
+    Saig_ManCbaFindReason_rec( p->pFrames, Aig_ObjFanin0(pObj), vPrios, vReasons );
+    Vec_IntFree( vPrios );
+//    assert( !Aig_ObjIsTravIdCurrent(p->pFrames, Aig_ManConst1(p->pFrames)) );
+    return vReasons;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collect nodes in the unrolled timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManCbaUnrollCollect_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vObjs, Vec_Int_t * vRoots )
+{
+    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(pAig, pObj);
+    if ( Aig_ObjIsCo(pObj) )
+        Saig_ManCbaUnrollCollect_rec( pAig, Aig_ObjFanin0(pObj), vObjs, vRoots );
+    else if ( Aig_ObjIsNode(pObj) )
+    {
+        Saig_ManCbaUnrollCollect_rec( pAig, Aig_ObjFanin0(pObj), vObjs, vRoots );
+        Saig_ManCbaUnrollCollect_rec( pAig, Aig_ObjFanin1(pObj), vObjs, vRoots );
+    }
+    if ( vRoots && Saig_ObjIsLo( pAig, pObj ) )
+        Vec_IntPush( vRoots, Aig_ObjId( Saig_ObjLoToLi(pAig, pObj) ) );
+    Vec_IntPush( vObjs, Aig_ObjId(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive unrolled timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManCbaUnrollWithCex( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, Vec_Int_t ** pvMapPiF2A, Vec_Vec_t ** pvReg2Frame )
+{
+    Aig_Man_t * pFrames;     // unrolled timeframes
+    Vec_Vec_t * vFrameCos;   // the list of COs per frame
+    Vec_Vec_t * vFrameObjs;  // the list of objects per frame
+    Vec_Int_t * vRoots, * vObjs;
+    Aig_Obj_t * pObj;
+    int i, f;
+    // sanity checks
+    assert( Saig_ManPiNum(pAig) == pCex->nPis );
+//    assert( Saig_ManRegNum(pAig) == pCex->nRegs );
+    assert( pCex->iPo >= 0 && pCex->iPo < Saig_ManPoNum(pAig) );
+
+    // map PIs of the unrolled frames into PIs of the original design
+    *pvMapPiF2A = Vec_IntAlloc( 1000 );
+
+    // collect COs and Objs visited in each frame
+    vFrameCos  = Vec_VecStart( pCex->iFrame+1 );
+    vFrameObjs = Vec_VecStart( pCex->iFrame+1 );
+    // initialized the topmost frame
+    pObj = Aig_ManCo( pAig, pCex->iPo );
+    Vec_VecPushInt( vFrameCos, pCex->iFrame, Aig_ObjId(pObj) );
+    for ( f = pCex->iFrame; f >= 0; f-- )
+    {
+        // collect nodes starting from the roots
+        Aig_ManIncrementTravId( pAig );
+        vRoots = Vec_VecEntryInt( vFrameCos, f );
+        Aig_ManForEachObjVec( vRoots, pAig, pObj, i )
+            Saig_ManCbaUnrollCollect_rec( pAig, pObj, 
+                Vec_VecEntryInt(vFrameObjs, f),
+                (Vec_Int_t *)(f ? Vec_VecEntry(vFrameCos, f-1) : NULL) );
+    }
+
+    // derive unrolled timeframes
+    pFrames = Aig_ManStart( 10000 );
+    pFrames->pName = Abc_UtilStrsav( pAig->pName );
+    pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec );
+    // initialize the flops 
+    if ( Saig_ManRegNum(pAig) == pCex->nRegs )
+    {
+        Saig_ManForEachLo( pAig, pObj, i )
+            pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Abc_InfoHasBit(pCex->pData, i) );
+    }
+    else // this is the case when synthesis was applied, assume all-0 init state
+    {
+        Saig_ManForEachLo( pAig, pObj, i )
+            pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), 1 );
+    }
+    // iterate through the frames
+    for ( f = 0; f <= pCex->iFrame; f++ )
+    {
+        // construct
+        vObjs = Vec_VecEntryInt( vFrameObjs, f );
+        Aig_ManForEachObjVec( vObjs, pAig, pObj, i )
+        {
+            if ( Aig_ObjIsNode(pObj) )
+                pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+            else if ( Aig_ObjIsCo(pObj) )
+                pObj->pData = Aig_ObjChild0Copy(pObj);
+            else if ( Aig_ObjIsConst1(pObj) )
+                pObj->pData = Aig_ManConst1(pFrames);
+            else if ( Saig_ObjIsPi(pAig, pObj) )
+            {
+                if ( Aig_ObjCioId(pObj) < nInputs )
+                {
+                    int iBit = pCex->nRegs + f * pCex->nPis + Aig_ObjCioId(pObj);
+                    pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Abc_InfoHasBit(pCex->pData, iBit) );
+                }
+                else
+                {
+                    pObj->pData = Aig_ObjCreateCi( pFrames );
+                    Vec_IntPush( *pvMapPiF2A, Aig_ObjCioId(pObj) );
+                    Vec_IntPush( *pvMapPiF2A, f );
+                }
+            }
+        }
+        if ( f == pCex->iFrame )
+            break;
+        // transfer
+        vRoots = Vec_VecEntryInt( vFrameCos, f );
+        Aig_ManForEachObjVec( vRoots, pAig, pObj, i )
+        {
+            Saig_ObjLiToLo( pAig, pObj )->pData = pObj->pData;
+            if ( *pvReg2Frame )
+            {
+                Vec_VecPushInt( *pvReg2Frame, f, Aig_ObjId(pObj) );             // record LO
+                Vec_VecPushInt( *pvReg2Frame, f, Aig_ObjToLit((Aig_Obj_t *)pObj->pData) ); // record its literal
+            }
+        }
+    }
+    // create output
+    pObj = Aig_ManCo( pAig, pCex->iPo );
+    Aig_ObjCreateCo( pFrames, Aig_Not((Aig_Obj_t *)pObj->pData) );
+    Aig_ManSetRegNum( pFrames, 0 );
+    // cleanup
+    Vec_VecFree( vFrameCos );
+    Vec_VecFree( vFrameObjs );
+    // finallize
+    Aig_ManCleanup( pFrames );
+    // return
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates refinement manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Saig_ManCba_t * Saig_ManCbaStart( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, int fVerbose )
+{
+    Saig_ManCba_t * p;
+    p = ABC_CALLOC( Saig_ManCba_t, 1 );
+    p->pAig = pAig;
+    p->pCex = pCex;
+    p->nInputs = nInputs;
+    p->fVerbose = fVerbose;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Destroys refinement manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManCbaStop( Saig_ManCba_t * p )
+{
+    Vec_VecFreeP( &p->vReg2Frame );
+    Vec_VecFreeP( &p->vReg2Value );
+    Aig_ManStopP( &p->pFrames );
+    Vec_IntFreeP( &p->vMapPiF2A );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Destroys refinement manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManCbaShrink( Saig_ManCba_t * p )
+{
+    Aig_Man_t * pManNew;
+    Aig_Obj_t * pObjLi, * pObjFrame;
+    Vec_Int_t * vLevel, * vLevel2;
+    int f, k, ObjId, Lit;
+    // assuming that important objects are labeled in Saig_ManCbaFindReason()
+    Vec_VecForEachLevelInt( p->vReg2Frame, vLevel, f )
+    {
+        Vec_IntForEachEntryDouble( vLevel, ObjId, Lit, k )
+        {
+            pObjFrame = Aig_ManObj( p->pFrames, Abc_Lit2Var(Lit) );
+            if ( pObjFrame == NULL || (!Aig_ObjIsConst1(pObjFrame) && !Aig_ObjIsTravIdCurrent(p->pFrames, pObjFrame)) )
+                continue;
+            pObjLi = Aig_ManObj( p->pAig, ObjId );
+            assert( Saig_ObjIsLi(p->pAig, pObjLi) );
+            Vec_VecPushInt( p->vReg2Value, f, Abc_Var2Lit( Aig_ObjCioId(pObjLi) - Saig_ManPoNum(p->pAig), Abc_LitIsCompl(Lit) ^ !pObjFrame->fPhase ) );
+        }
+    }
+    // print statistics
+    Vec_VecForEachLevelInt( p->vReg2Frame, vLevel, k )
+    {
+        vLevel2 = Vec_VecEntryInt( p->vReg2Value, k );
+        printf( "Level = %4d   StateBits = %4d (%6.2f %%)  CareBits = %4d (%6.2f %%)\n", k, 
+            Vec_IntSize(vLevel)/2, 100.0 * (Vec_IntSize(vLevel)/2) / Aig_ManRegNum(p->pAig),
+            Vec_IntSize(vLevel2),  100.0 * Vec_IntSize(vLevel2) / Aig_ManRegNum(p->pAig) );
+    }
+    // try reducing the frames
+    pManNew = Saig_ManDupWithCubes( p->pAig, p->vReg2Value );
+//    Ioa_WriteAiger( pManNew, "aigcube.aig", 0, 0 );
+    Aig_ManStop( pManNew );
+}
+
+static inline void Saig_ObjCexMinSet0( Aig_Obj_t * pObj ) { pObj->fMarkA = 1; pObj->fMarkB = 0;    }
+static inline void Saig_ObjCexMinSet1( Aig_Obj_t * pObj ) { pObj->fMarkA = 0; pObj->fMarkB = 1;    }
+static inline void Saig_ObjCexMinSetX( Aig_Obj_t * pObj ) { pObj->fMarkA = 1; pObj->fMarkB = 1;    }
+
+static inline int  Saig_ObjCexMinGet0( Aig_Obj_t * pObj ) { return  pObj->fMarkA && !pObj->fMarkB; }
+static inline int  Saig_ObjCexMinGet1( Aig_Obj_t * pObj ) { return !pObj->fMarkA &&  pObj->fMarkB; }
+static inline int  Saig_ObjCexMinGetX( Aig_Obj_t * pObj ) { return  pObj->fMarkA &&  pObj->fMarkB; }
+
+static inline int  Saig_ObjCexMinGet0Fanin0( Aig_Obj_t * pObj ) { return (Saig_ObjCexMinGet1(Aig_ObjFanin0(pObj)) && Aig_ObjFaninC0(pObj)) || (Saig_ObjCexMinGet0(Aig_ObjFanin0(pObj)) && !Aig_ObjFaninC0(pObj)); }
+static inline int  Saig_ObjCexMinGet1Fanin0( Aig_Obj_t * pObj ) { return (Saig_ObjCexMinGet0(Aig_ObjFanin0(pObj)) && Aig_ObjFaninC0(pObj)) || (Saig_ObjCexMinGet1(Aig_ObjFanin0(pObj)) && !Aig_ObjFaninC0(pObj)); }
+
+static inline int  Saig_ObjCexMinGet0Fanin1( Aig_Obj_t * pObj ) { return (Saig_ObjCexMinGet1(Aig_ObjFanin1(pObj)) && Aig_ObjFaninC1(pObj)) || (Saig_ObjCexMinGet0(Aig_ObjFanin1(pObj)) && !Aig_ObjFaninC1(pObj)); }
+static inline int  Saig_ObjCexMinGet1Fanin1( Aig_Obj_t * pObj ) { return (Saig_ObjCexMinGet0(Aig_ObjFanin1(pObj)) && Aig_ObjFaninC1(pObj)) || (Saig_ObjCexMinGet1(Aig_ObjFanin1(pObj)) && !Aig_ObjFaninC1(pObj)); }
+
+static inline void Saig_ObjCexMinSim( Aig_Obj_t * pObj )
+{
+    if ( Aig_ObjIsAnd(pObj) )
+    {
+        if ( Saig_ObjCexMinGet0Fanin0(pObj) || Saig_ObjCexMinGet0Fanin1(pObj) )
+            Saig_ObjCexMinSet0( pObj );
+        else if ( Saig_ObjCexMinGet1Fanin0(pObj) && Saig_ObjCexMinGet1Fanin1(pObj) )
+            Saig_ObjCexMinSet1( pObj );
+        else 
+            Saig_ObjCexMinSetX( pObj );
+    }
+    else if ( Aig_ObjIsCo(pObj) )
+    {
+        if ( Saig_ObjCexMinGet0Fanin0(pObj) )
+            Saig_ObjCexMinSet0( pObj );
+        else if ( Saig_ObjCexMinGet1Fanin0(pObj) )
+            Saig_ObjCexMinSet1( pObj );
+        else 
+            Saig_ObjCexMinSetX( pObj );
+    }
+    else assert( 0 );
+}
+
+static inline void Saig_ObjCexMinPrint( Aig_Obj_t * pObj )
+{
+    if ( Saig_ObjCexMinGet0(pObj) )
+        printf( "0" );
+    else if ( Saig_ObjCexMinGet1(pObj) )
+        printf( "1" );
+    else if ( Saig_ObjCexMinGetX(pObj) )
+        printf( "X" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManCexVerifyUsingTernary( Aig_Man_t * pAig, Abc_Cex_t * pCex, Abc_Cex_t * pCare )
+{
+    Aig_Obj_t * pObj, * pObjRi, * pObjRo;
+    int i, f, iBit = 0;
+    assert( pCex->iFrame == pCare->iFrame );
+    assert( pCex->nBits  == pCare->nBits );
+    assert( pCex->iPo < Saig_ManPoNum(pAig) );
+    Saig_ObjCexMinSet1( Aig_ManConst1(pAig) );
+    // set flops to the init state
+    Saig_ManForEachLo( pAig, pObj, i )
+    {
+        assert( !Abc_InfoHasBit(pCex->pData, iBit) );
+        assert( !Abc_InfoHasBit(pCare->pData, iBit) );
+//        if ( Abc_InfoHasBit(pCare->pData, iBit++) )
+            Saig_ObjCexMinSet0( pObj );
+//        else
+//            Saig_ObjCexMinSetX( pObj );
+    }
+    iBit = pCex->nRegs;
+    for ( f = 0; f <= pCex->iFrame; f++ )
+    {
+        // init inputs
+        Saig_ManForEachPi( pAig, pObj, i )
+        {
+            if ( Abc_InfoHasBit(pCare->pData, iBit++) )
+            {
+                if ( Abc_InfoHasBit(pCex->pData, iBit-1) )
+                    Saig_ObjCexMinSet1( pObj );
+                else
+                    Saig_ObjCexMinSet0( pObj );
+            }
+            else
+                Saig_ObjCexMinSetX( pObj );
+        }
+        // simulate internal nodes
+        Aig_ManForEachNode( pAig, pObj, i )
+            Saig_ObjCexMinSim( pObj );
+        // simulate COs
+        Aig_ManForEachCo( pAig, pObj, i )
+            Saig_ObjCexMinSim( pObj );
+/*
+        Aig_ManForEachObj( pAig, pObj, i )
+        {
+            Aig_ObjPrint(pAig, pObj);
+            printf( "  Value = " );
+            Saig_ObjCexMinPrint( pObj );
+            printf( "\n" );
+        }
+*/
+        // transfer
+        Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, i )
+            pObjRo->fMarkA = pObjRi->fMarkA,
+            pObjRo->fMarkB = pObjRi->fMarkB;
+    }
+    assert( iBit == pCex->nBits );
+    return Saig_ObjCexMinGet1( Aig_ManCo( pAig, pCex->iPo ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [SAT-based refinement of the counter-example.]
+
+  Description [The first parameter (nInputs) indicates how many first 
+  primary inputs to skip without considering as care candidates.]
+               
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Saig_ManCbaFindCexCareBits( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, int fVerbose )
+{
+    Saig_ManCba_t * p;
+    Vec_Int_t * vReasons;
+    Abc_Cex_t * pCare;
+    abctime clk = Abc_Clock();
+
+    clk = Abc_Clock();
+    p = Saig_ManCbaStart( pAig, pCex, nInputs, fVerbose );
+
+//    p->vReg2Frame = Vec_VecStart( pCex->iFrame );
+//    p->vReg2Value = Vec_VecStart( pCex->iFrame );
+    p->pFrames = Saig_ManCbaUnrollWithCex( pAig, pCex, nInputs, &p->vMapPiF2A, &p->vReg2Frame );
+    vReasons = Saig_ManCbaFindReason( p );
+    if ( p->vReg2Frame )
+        Saig_ManCbaShrink( p );
+
+
+//if ( fVerbose )
+//Aig_ManPrintStats( p->pFrames );
+
+    if ( fVerbose )
+    {
+        Vec_Int_t * vRes = Saig_ManCbaReason2Inputs( p, vReasons );
+        printf( "Frame PIs = %4d (essential = %4d)   AIG PIs = %4d (essential = %4d)   ",
+            Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), 
+            Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) );
+        Vec_IntFree( vRes );
+ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+
+    pCare = Saig_ManCbaReason2Cex( p, vReasons );
+    Vec_IntFree( vReasons );
+    Saig_ManCbaStop( p );
+
+if ( fVerbose )
+{
+printf( "Real " );
+Abc_CexPrintStats( pCex );
+}
+if ( fVerbose )
+{
+printf( "Care " );
+Abc_CexPrintStats( pCare );
+}
+/*
+    // verify the reduced counter-example using ternary simulation
+    if ( !Saig_ManCexVerifyUsingTernary( pAig, pCex, pCare ) )
+        printf( "Saig_ManCbaFindCexCareBits(): Minimized counter-example verification has failed!!!\n" );
+    else if ( fVerbose )
+        printf( "Saig_ManCbaFindCexCareBits(): Minimized counter-example verification is successful.\n" );
+*/
+    Aig_ManCleanMarkAB( pAig );
+    return pCare;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of PIs for flops that should not be absracted.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManCbaFilterInputs( Aig_Man_t * pAig, int iFirstFlopPi, Abc_Cex_t * pCex, int fVerbose )
+{
+    Saig_ManCba_t * p;
+    Vec_Int_t * vRes, * vReasons;
+    abctime clk;
+    if ( Saig_ManPiNum(pAig) != pCex->nPis )
+    {
+        printf( "Saig_ManCbaFilterInputs(): The PI count of AIG (%d) does not match that of cex (%d).\n", 
+            Aig_ManCiNum(pAig), pCex->nPis );
+        return NULL;
+    }
+
+clk = Abc_Clock();
+    p = Saig_ManCbaStart( pAig, pCex, iFirstFlopPi, fVerbose );
+    p->pFrames = Saig_ManCbaUnrollWithCex( pAig, pCex, iFirstFlopPi, &p->vMapPiF2A, &p->vReg2Frame );
+    vReasons = Saig_ManCbaFindReason( p );
+    vRes = Saig_ManCbaReason2Inputs( p, vReasons );
+    if ( fVerbose )
+    {
+        printf( "Frame PIs = %4d (essential = %4d)   AIG PIs = %4d (essential = %4d)   ",
+            Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), 
+            Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+
+    Vec_IntFree( vReasons );
+    Saig_ManCbaStop( p );
+    return vRes;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the abstracted model for a counter-example.]
+
+  Description [Returns the array of abstracted flops that should be added
+  to the abstraction.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManCbaPerform( Aig_Man_t * pAbs, int nInputs, Saig_ParBmc_t * pPars )
+{
+    Vec_Int_t * vAbsFfsToAdd;
+    int RetValue;
+    abctime clk = Abc_Clock();
+//    assert( pAbs->nRegs > 0 );
+    // perform BMC
+    RetValue = Saig_ManBmcScalable( pAbs, pPars );
+    if ( RetValue == -1 ) // time out - nothing to add
+    {
+        printf( "Resource limit is reached during BMC.\n" );
+        assert( pAbs->pSeqModel == NULL );
+        return Vec_IntAlloc( 0 );
+    }
+    if ( pAbs->pSeqModel == NULL )
+    {
+        printf( "BMC did not detect a CEX with the given depth.\n" );
+        return Vec_IntAlloc( 0 );
+    }
+    if ( pPars->fVerbose )
+        Abc_CexPrintStats( pAbs->pSeqModel );
+    // CEX is detected - refine the flops
+    vAbsFfsToAdd = Saig_ManCbaFilterInputs( pAbs, nInputs, pAbs->pSeqModel, pPars->fVerbose );
+    if ( Vec_IntSize(vAbsFfsToAdd) == 0 )
+    {
+        Vec_IntFree( vAbsFfsToAdd );
+        return NULL;
+    }
+    if ( pPars->fVerbose )
+    {
+        printf( "Adding %d registers to the abstraction (total = %d).  ", 
+            Vec_IntSize(vAbsFfsToAdd), Aig_ManRegNum(pAbs)+Vec_IntSize(vAbsFfsToAdd) );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    return vAbsFfsToAdd;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/absOldRef.c b/abc-build/src/proof/abs/absOldRef.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absOldRef.c
@@ -0,0 +1,474 @@
+/**CFile****************************************************************
+
+  FileName    [saigAbsStart.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Counter-example-based abstraction.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigAbsStart.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abs.h"
+#include "proof/ssw/ssw.h"
+#include "proof/fra/fra.h"
+#include "proof/bbr/bbr.h"
+#include "proof/pdr/pdr.h"
+#include "sat/bmc/bmc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManAbsSetDefaultParams( Gia_ParAbs_t * p )
+{
+    memset( p, 0, sizeof(Gia_ParAbs_t) );
+    p->Algo        =        0;    // algorithm: CBA
+    p->nFramesMax  =       10;    // timeframes for PBA
+    p->nConfMax    =    10000;    // conflicts for PBA
+    p->fDynamic    =        1;    // dynamic unfolding for PBA
+    p->fConstr     =        0;    // use constraints
+    p->nFramesBmc  =      250;    // timeframes for BMC
+    p->nConfMaxBmc =     5000;    // conflicts for BMC
+    p->nStableMax  =  1000000;    // the number of stable frames to quit
+    p->nRatio      =       10;    // ratio of flops to quit
+    p->nBobPar     =  1000000;    // the number of frames before trying to quit
+    p->fUseBdds    =        0;    // use BDDs to refine abstraction
+    p->fUseDprove  =        0;    // use 'dprove' to refine abstraction
+    p->fUseStart   =        1;    // use starting frame
+    p->fVerbose    =        0;    // verbose output
+    p->fVeryVerbose=        0;    // printing additional information
+    p->Status      =       -1;    // the problem status
+    p->nFramesDone =       -1;    // the number of rames covered
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derive a new counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Saig_ManCexRemap( Aig_Man_t * p, Aig_Man_t * pAbs, Abc_Cex_t * pCexAbs )
+{
+    Abc_Cex_t * pCex;
+    Aig_Obj_t * pObj;
+    int i, f;
+    if ( !Saig_ManVerifyCex( pAbs, pCexAbs ) )
+        printf( "Saig_ManCexRemap(): The initial counter-example is invalid.\n" );
+//    else
+//        printf( "Saig_ManCexRemap(): The initial counter-example is correct.\n" );
+    // start the counter-example
+    pCex = Abc_CexAlloc( Aig_ManRegNum(p), Saig_ManPiNum(p), pCexAbs->iFrame+1 );
+    pCex->iFrame = pCexAbs->iFrame;
+    pCex->iPo    = pCexAbs->iPo;
+    // copy the bit data
+    for ( f = 0; f <= pCexAbs->iFrame; f++ )
+    {
+        Saig_ManForEachPi( pAbs, pObj, i )
+        {
+            if ( i == Saig_ManPiNum(p) )
+                break;
+            if ( Abc_InfoHasBit( pCexAbs->pData, pCexAbs->nRegs + pCexAbs->nPis * f + i ) )
+                Abc_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * f + i );
+        }
+    }
+    // verify the counter example
+    if ( !Saig_ManVerifyCex( p, pCex ) )
+    {
+        printf( "Saig_ManCexRemap(): Counter-example is invalid.\n" );
+        Abc_CexFree( pCex );
+        pCex = NULL;
+    }
+    else
+    {
+        Abc_Print( 1, "Counter-example verification is successful.\n" );
+        Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. \n", pCex->iPo, p->pName, pCex->iFrame );
+    }
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the first PI corresponding to the flop.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManCexFirstFlopPi( Aig_Man_t * p, Aig_Man_t * pAbs )
+{ 
+    Aig_Obj_t * pObj;
+    int i;
+    assert( pAbs->vCiNumsOrig != NULL );
+    Aig_ManForEachCi( p, pObj, i )
+    {
+        if ( Vec_IntEntry(pAbs->vCiNumsOrig, i) >= Saig_ManPiNum(p) )
+            return i;
+    }
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines abstraction using one step.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManCexRefine( Aig_Man_t * p, Aig_Man_t * pAbs, Vec_Int_t * vFlops, int nFrames, int nConfMaxOne, int fUseBdds, int fUseDprove, int fVerbose, int * pnUseStart, int * piRetValue, int * pnFrames )
+{ 
+    Vec_Int_t * vFlopsNew;
+    int i, Entry, RetValue;
+    *piRetValue = -1;
+    if ( fUseDprove && Aig_ManRegNum(pAbs) > 0 )
+    {
+/*
+        Fra_Sec_t SecPar, * pSecPar = &SecPar;
+        Fra_SecSetDefaultParams( pSecPar );
+        pSecPar->fVerbose       = fVerbose;
+        RetValue = Fra_FraigSec( pAbs, pSecPar, NULL );
+*/
+        Aig_Man_t * pAbsOrpos = Saig_ManDupOrpos( pAbs );
+        Pdr_Par_t Pars, * pPars = &Pars;
+        Pdr_ManSetDefaultParams( pPars );
+        pPars->nTimeOut = 10;
+        pPars->fVerbose = fVerbose;
+        if ( pPars->fVerbose )
+            printf( "Running property directed reachability...\n" );
+        RetValue = Pdr_ManSolve( pAbsOrpos, pPars );
+        if ( pAbsOrpos->pSeqModel )
+            pAbsOrpos->pSeqModel->iPo = Saig_ManFindFailedPoCex( pAbs, pAbsOrpos->pSeqModel );
+        pAbs->pSeqModel = pAbsOrpos->pSeqModel;
+        pAbsOrpos->pSeqModel = NULL;
+        Aig_ManStop( pAbsOrpos );
+        if ( RetValue )
+            *piRetValue = 1;
+
+    }
+    else if ( fUseBdds && (Aig_ManRegNum(pAbs) > 0 && Aig_ManRegNum(pAbs) <= 80) )
+    {
+        Saig_ParBbr_t Pars, * pPars = &Pars;
+        Bbr_ManSetDefaultParams( pPars );
+        pPars->TimeLimit     = 0;
+        pPars->nBddMax       = 1000000;
+        pPars->nIterMax      = nFrames;
+        pPars->fPartition    = 1;
+        pPars->fReorder      = 1;
+        pPars->fReorderImage = 1;
+        pPars->fVerbose      = fVerbose;
+        pPars->fSilent       = 0;
+        RetValue = Aig_ManVerifyUsingBdds( pAbs, pPars );
+        if ( RetValue )
+            *piRetValue = 1;
+    }
+    else 
+    {
+        Saig_BmcPerform( pAbs, pnUseStart? *pnUseStart: 0, nFrames, 2000, 0, nConfMaxOne, 0, fVerbose, 0, pnFrames, 0 );
+    }
+    if ( pAbs->pSeqModel == NULL )
+        return NULL;
+    if ( pnUseStart )
+        *pnUseStart = pAbs->pSeqModel->iFrame;
+//    vFlopsNew = Saig_ManExtendCounterExampleTest( pAbs, Saig_ManCexFirstFlopPi(p, pAbs), pAbs->pSeqModel, 1, fVerbose );
+    vFlopsNew = Saig_ManExtendCounterExampleTest3( pAbs, Saig_ManCexFirstFlopPi(p, pAbs), pAbs->pSeqModel, fVerbose );
+    if ( vFlopsNew == NULL )
+        return NULL;
+    if ( Vec_IntSize(vFlopsNew) == 0 )
+    {
+        printf( "Discovered a true counter-example!\n" );
+        p->pSeqModel = Saig_ManCexRemap( p, pAbs, pAbs->pSeqModel );
+        Vec_IntFree( vFlopsNew );
+        *piRetValue = 0;
+        return NULL;
+    }
+    // vFlopsNew contains PI numbers that should be kept in pAbs
+    if ( fVerbose )
+        printf( "Adding %d registers to the abstraction (total = %d).\n\n", Vec_IntSize(vFlopsNew), Aig_ManRegNum(pAbs)+Vec_IntSize(vFlopsNew) );
+    // add to the abstraction
+    Vec_IntForEachEntry( vFlopsNew, Entry, i )
+    {
+        Entry = Vec_IntEntry(pAbs->vCiNumsOrig, Entry);
+        assert( Entry >= Saig_ManPiNum(p) );
+        assert( Entry < Aig_ManCiNum(p) );
+        Vec_IntPush( vFlops, Entry-Saig_ManPiNum(p) );
+    }
+    Vec_IntFree( vFlopsNew );
+
+    Vec_IntSort( vFlops, 0 );
+    Vec_IntForEachEntryStart( vFlops, Entry, i, 1 )
+        assert( Vec_IntEntry(vFlops, i-1) != Entry );
+
+    return Saig_ManDupAbstraction( p, vFlops );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Refines abstraction using one step.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManCexRefineStep( Aig_Man_t * p, Vec_Int_t * vFlops, Vec_Int_t * vFlopClasses, Abc_Cex_t * pCex, int nFfToAddMax, int fTryFour, int fSensePath, int fVerbose )
+{
+    Aig_Man_t * pAbs;
+    Vec_Int_t * vFlopsNew;
+    int i, Entry;
+    abctime clk = Abc_Clock();
+    pAbs = Saig_ManDupAbstraction( p, vFlops );
+    if ( fSensePath )
+        vFlopsNew = Saig_ManExtendCounterExampleTest2( pAbs, Saig_ManCexFirstFlopPi(p, pAbs), pCex, fVerbose );
+    else
+//        vFlopsNew = Saig_ManExtendCounterExampleTest( pAbs, Saig_ManCexFirstFlopPi(p, pAbs), pCex, fTryFour, fVerbose );
+        vFlopsNew = Saig_ManExtendCounterExampleTest3( pAbs, Saig_ManCexFirstFlopPi(p, pAbs), pCex, fVerbose );
+    if ( vFlopsNew == NULL )
+    {
+        Aig_ManStop( pAbs );
+        return 0;
+    }
+    if ( Vec_IntSize(vFlopsNew) == 0 )
+    {
+        printf( "Refinement did not happen. Discovered a true counter-example.\n" );
+        printf( "Remapping counter-example from %d to %d primary inputs.\n", Aig_ManCiNum(pAbs), Aig_ManCiNum(p) );
+        p->pSeqModel = Saig_ManCexRemap( p, pAbs, pCex );
+        Vec_IntFree( vFlopsNew );
+        Aig_ManStop( pAbs );
+        return 0;
+    }
+    if ( fVerbose )
+    {
+        printf( "Adding %d registers to the abstraction (total = %d).  ", Vec_IntSize(vFlopsNew), Aig_ManRegNum(p)+Vec_IntSize(vFlopsNew) );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    // vFlopsNew contains PI numbers that should be kept in pAbs
+    // select the most useful flops among those to be added
+    if ( nFfToAddMax > 0 && Vec_IntSize(vFlopsNew) > nFfToAddMax )
+    {
+        Vec_Int_t * vFlopsNewBest;
+        // shift the indices
+        Vec_IntForEachEntry( vFlopsNew, Entry, i )
+            Vec_IntAddToEntry( vFlopsNew, i, -Saig_ManPiNum(p) );
+        // create new flops
+        vFlopsNewBest = Saig_ManCbaFilterFlops( p, pCex, vFlopClasses, vFlopsNew, nFfToAddMax );
+        assert( Vec_IntSize(vFlopsNewBest) == nFfToAddMax );
+        printf( "Filtering flops based on cost (%d -> %d).\n", Vec_IntSize(vFlopsNew), Vec_IntSize(vFlopsNewBest) );
+        // update
+        Vec_IntFree( vFlopsNew );
+        vFlopsNew = vFlopsNewBest;
+        // shift the indices
+        Vec_IntForEachEntry( vFlopsNew, Entry, i )
+            Vec_IntAddToEntry( vFlopsNew, i, Saig_ManPiNum(p) );
+    }
+    // add to the abstraction
+    Vec_IntForEachEntry( vFlopsNew, Entry, i )
+    {
+        Entry = Vec_IntEntry(pAbs->vCiNumsOrig, Entry);
+        assert( Entry >= Saig_ManPiNum(p) );
+        assert( Entry < Aig_ManCiNum(p) );
+        Vec_IntPush( vFlops, Entry-Saig_ManPiNum(p) );
+    }
+    Vec_IntFree( vFlopsNew );
+    Aig_ManStop( pAbs );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transform flop map into flop list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManClasses2Flops( Vec_Int_t * vFlopClasses )
+{
+    Vec_Int_t * vFlops;
+    int i, Entry;
+    vFlops = Vec_IntAlloc( 100 );
+    Vec_IntForEachEntry( vFlopClasses, Entry, i )
+        if ( Entry )
+            Vec_IntPush( vFlops, i );
+    return vFlops;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transform flop list into flop map.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManFlops2Classes( Gia_Man_t * pGia, Vec_Int_t * vFlops )
+{
+    Vec_Int_t * vFlopClasses;
+    int i, Entry;
+    vFlopClasses = Vec_IntStart( Gia_ManRegNum(pGia) );
+    Vec_IntForEachEntry( vFlops, Entry, i )
+        Vec_IntWriteEntry( vFlopClasses, Entry, 1 );
+    return vFlopClasses;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines abstraction using the latch map.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCexAbstractionRefine( Gia_Man_t * pGia, Abc_Cex_t * pCex, int nFfToAddMax, int fTryFour, int fSensePath, int fVerbose )
+{
+    Aig_Man_t * pNew;
+    Vec_Int_t * vFlops;
+    if ( pGia->vFlopClasses == NULL )
+    {
+        printf( "Gia_ManCexAbstractionRefine(): Abstraction latch map is missing.\n" );
+        return -1;
+    }
+    pNew = Gia_ManToAig( pGia, 0 );
+    vFlops = Gia_ManClasses2Flops( pGia->vFlopClasses );
+    if ( !Saig_ManCexRefineStep( pNew, vFlops, pGia->vFlopClasses, pCex, nFfToAddMax, fTryFour, fSensePath, fVerbose ) )
+    {
+        pGia->pCexSeq = pNew->pSeqModel; pNew->pSeqModel = NULL;
+        Vec_IntFree( vFlops );
+        Aig_ManStop( pNew );
+        return 0;
+    }
+    Vec_IntFree( pGia->vFlopClasses );
+    pGia->vFlopClasses = Gia_ManFlops2Classes( pGia, vFlops );
+    Vec_IntFree( vFlops );
+    Aig_ManStop( pNew );
+    return -1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the flops to remain after abstraction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+Vec_Int_t * Saig_ManCexAbstractionFlops( Aig_Man_t * p, Gia_ParAbs_t * pPars )
+{
+    int nUseStart = 0;
+    Aig_Man_t * pAbs, * pTemp;
+    Vec_Int_t * vFlops;
+    int Iter;//, clk = Abc_Clock(), clk2 = Abc_Clock();//, iFlop;
+    assert( Aig_ManRegNum(p) > 0 );
+    if ( pPars->fVerbose )
+        printf( "Performing counter-example-based refinement.\n" );
+    Aig_ManSetCioIds( p );
+    vFlops = Vec_IntStartNatural( 1 );
+/*
+    iFlop = Saig_ManFindFirstFlop( p );
+    assert( iFlop >= 0 );
+    vFlops = Vec_IntAlloc( 1 );
+    Vec_IntPush( vFlops, iFlop );
+*/
+    // create the resulting AIG
+    pAbs = Saig_ManDupAbstraction( p, vFlops );
+    if ( !pPars->fVerbose )
+    {
+        printf( "Init : " );
+        Aig_ManPrintStats( pAbs );
+    }
+    printf( "Refining abstraction...\n" );
+    for ( Iter = 0; ; Iter++ )
+    {
+        pTemp = Saig_ManCexRefine( p, pAbs, vFlops, pPars->nFramesBmc, pPars->nConfMaxBmc, pPars->fUseBdds, pPars->fUseDprove, pPars->fVerbose, pPars->fUseStart?&nUseStart:NULL, &pPars->Status, &pPars->nFramesDone );
+        if ( pTemp == NULL )
+        {
+            ABC_FREE( p->pSeqModel );
+            p->pSeqModel = pAbs->pSeqModel;
+            pAbs->pSeqModel = NULL;
+            Aig_ManStop( pAbs );
+            break;
+        }
+        Aig_ManStop( pAbs );
+        pAbs = pTemp;
+        printf( "ITER %4d : ", Iter );
+        if ( !pPars->fVerbose )
+            Aig_ManPrintStats( pAbs );
+        // output the intermediate result of abstraction
+        Ioa_WriteAiger( pAbs, "gabs.aig", 0, 0 );
+//            printf( "Intermediate abstracted model was written into file \"%s\".\n", "gabs.aig" );
+        // check if the ratio is reached
+        if ( 100.0*(Aig_ManRegNum(p)-Aig_ManRegNum(pAbs))/Aig_ManRegNum(p) < 1.0*pPars->nRatio )
+        {
+            printf( "Refinements is stopped because flop reduction is less than %d%%\n", pPars->nRatio );
+            Aig_ManStop( pAbs );
+            pAbs = NULL;
+            Vec_IntFree( vFlops );
+            vFlops = NULL;
+            break;
+        }
+    }
+    return vFlops;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/absOldSat.c b/abc-build/src/proof/abs/absOldSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absOldSat.c
@@ -0,0 +1,986 @@
+/**CFile****************************************************************
+
+  FileName    [saigRefSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [SAT based refinement of a counter-example.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigRefSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abs.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// local manager
+typedef struct Saig_RefMan_t_ Saig_RefMan_t;
+struct Saig_RefMan_t_
+{
+    // user data
+    Aig_Man_t * pAig;       // user's AIG
+    Abc_Cex_t * pCex;       // user's CEX
+    int         nInputs;    // the number of first inputs to skip
+    int         fVerbose;   // verbose flag
+    // unrolling
+    Aig_Man_t * pFrames;    // unrolled timeframes
+    Vec_Int_t * vMapPiF2A;  // mapping of frame PIs into real PIs
+};
+
+// performs ternary simulation
+extern int Saig_ManSimDataInit( Aig_Man_t * p, Abc_Cex_t * pCex, Vec_Ptr_t * vSimInfo, Vec_Int_t * vRes );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Maps array of frame PI IDs into array of original PI IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_RefManReason2Inputs( Saig_RefMan_t * p, Vec_Int_t * vReasons )
+{
+    Vec_Int_t * vOriginal, * vVisited;
+    int i, Entry;
+    vOriginal = Vec_IntAlloc( Saig_ManPiNum(p->pAig) ); 
+    vVisited = Vec_IntStart( Saig_ManPiNum(p->pAig) );
+    Vec_IntForEachEntry( vReasons, Entry, i )
+    {
+        int iInput = Vec_IntEntry( p->vMapPiF2A, 2*Entry );
+        assert( iInput >= 0 && iInput < Aig_ManCiNum(p->pAig) );
+        if ( Vec_IntEntry(vVisited, iInput) == 0 )
+            Vec_IntPush( vOriginal, iInput );
+        Vec_IntAddToEntry( vVisited, iInput, 1 );
+    }
+    Vec_IntFree( vVisited );
+    return vOriginal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Saig_RefManReason2Cex( Saig_RefMan_t * p, Vec_Int_t * vReasons )
+{
+    Abc_Cex_t * pCare;
+    int i, Entry, iInput, iFrame;
+    pCare = Abc_CexDup( p->pCex, p->pCex->nRegs );
+    memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) );
+    Vec_IntForEachEntry( vReasons, Entry, i )
+    {
+        assert( Entry >= 0 && Entry < Aig_ManCiNum(p->pFrames) );
+        iInput = Vec_IntEntry( p->vMapPiF2A, 2*Entry );
+        iFrame = Vec_IntEntry( p->vMapPiF2A, 2*Entry+1 );
+        Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput );
+    }
+    return pCare;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns reasons for the property to fail.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_RefManFindReason_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vPrios, Vec_Int_t * vReasons )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        Vec_IntPush( vReasons, Aig_ObjCioId(pObj) );
+        return;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    if ( pObj->fPhase )
+    {
+        Saig_RefManFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons );
+        Saig_RefManFindReason_rec( p, Aig_ObjFanin1(pObj), vPrios, vReasons );
+    }
+    else
+    {
+        int fPhase0 = Aig_ObjFaninC0(pObj) ^ Aig_ObjFanin0(pObj)->fPhase;
+        int fPhase1 = Aig_ObjFaninC1(pObj) ^ Aig_ObjFanin1(pObj)->fPhase;
+        assert( !fPhase0 || !fPhase1 );
+        if ( !fPhase0 && fPhase1 )
+            Saig_RefManFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons );
+        else if ( fPhase0 && !fPhase1 )
+            Saig_RefManFindReason_rec( p, Aig_ObjFanin1(pObj), vPrios, vReasons );
+        else 
+        {
+            int iPrio0 = Vec_IntEntry( vPrios, Aig_ObjFaninId0(pObj) );
+            int iPrio1 = Vec_IntEntry( vPrios, Aig_ObjFaninId1(pObj) );
+            if ( iPrio0 <= iPrio1 )
+                Saig_RefManFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons );
+            else
+                Saig_RefManFindReason_rec( p, Aig_ObjFanin1(pObj), vPrios, vReasons );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns reasons for the property to fail.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_RefManFindReason( Saig_RefMan_t * p )
+{
+    Aig_Obj_t * pObj;
+    Vec_Int_t * vPrios, * vPi2Prio, * vReasons;
+    int i, CountPrios;
+
+    vPi2Prio = Vec_IntStartFull( Saig_ManPiNum(p->pAig) );
+    vPrios   = Vec_IntStartFull( Aig_ManObjNumMax(p->pFrames) );
+
+    // set PI values according to CEX
+    CountPrios = 0;
+    Aig_ManConst1(p->pFrames)->fPhase = 1;
+    Aig_ManForEachCi( p->pFrames, pObj, i )
+    {
+        int iInput = Vec_IntEntry( p->vMapPiF2A, 2*i );
+        int iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 );
+        pObj->fPhase = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput );
+        // assign priority
+        if ( Vec_IntEntry(vPi2Prio, iInput) == ~0 )
+            Vec_IntWriteEntry( vPi2Prio, iInput, CountPrios++ );
+//        Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), Vec_IntEntry(vPi2Prio, iInput) );
+        Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), i );
+    }
+//    printf( "Priority numbers = %d.\n", CountPrios );
+    Vec_IntFree( vPi2Prio );
+
+    // traverse and set the priority
+    Aig_ManForEachNode( p->pFrames, pObj, i )
+    {
+        int fPhase0 = Aig_ObjFaninC0(pObj) ^ Aig_ObjFanin0(pObj)->fPhase;
+        int fPhase1 = Aig_ObjFaninC1(pObj) ^ Aig_ObjFanin1(pObj)->fPhase;
+        int iPrio0  = Vec_IntEntry( vPrios, Aig_ObjFaninId0(pObj) );
+        int iPrio1  = Vec_IntEntry( vPrios, Aig_ObjFaninId1(pObj) );
+        pObj->fPhase = fPhase0 && fPhase1;
+        if ( fPhase0 && fPhase1 ) // both are one
+            Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), Abc_MaxInt(iPrio0, iPrio1) );
+        else if ( !fPhase0 && fPhase1 ) 
+            Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), iPrio0 );
+        else if ( fPhase0 && !fPhase1 )
+            Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), iPrio1 );
+        else // both are zero
+            Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), Abc_MinInt(iPrio0, iPrio1) );
+    }
+    // check the property output
+    pObj = Aig_ManCo( p->pFrames, 0 );
+    assert( (int)Aig_ObjFanin0(pObj)->fPhase == Aig_ObjFaninC0(pObj) );
+
+    // select the reason
+    vReasons = Vec_IntAlloc( 100 );
+    Aig_ManIncrementTravId( p->pFrames );
+    if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) )
+        Saig_RefManFindReason_rec( p->pFrames, Aig_ObjFanin0(pObj), vPrios, vReasons );
+    Vec_IntFree( vPrios );
+    return vReasons;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collect nodes in the unrolled timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManUnrollCollect_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vObjs, Vec_Int_t * vRoots )
+{
+    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(pAig, pObj);
+    if ( Aig_ObjIsCo(pObj) )
+        Saig_ManUnrollCollect_rec( pAig, Aig_ObjFanin0(pObj), vObjs, vRoots );
+    else if ( Aig_ObjIsNode(pObj) )
+    {
+        Saig_ManUnrollCollect_rec( pAig, Aig_ObjFanin0(pObj), vObjs, vRoots );
+        Saig_ManUnrollCollect_rec( pAig, Aig_ObjFanin1(pObj), vObjs, vRoots );
+    }
+    if ( vRoots && Saig_ObjIsLo( pAig, pObj ) )
+        Vec_IntPush( vRoots, Aig_ObjId( Saig_ObjLoToLi(pAig, pObj) ) );
+    Vec_IntPush( vObjs, Aig_ObjId(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive unrolled timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManUnrollWithCex( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, Vec_Int_t ** pvMapPiF2A )
+{
+    Aig_Man_t * pFrames;     // unrolled timeframes
+    Vec_Vec_t * vFrameCos;   // the list of COs per frame
+    Vec_Vec_t * vFrameObjs;  // the list of objects per frame
+    Vec_Int_t * vRoots, * vObjs;
+    Aig_Obj_t * pObj;
+    int i, f;
+    // sanity checks
+    assert( Saig_ManPiNum(pAig) == pCex->nPis );
+    assert( Saig_ManRegNum(pAig) == pCex->nRegs );
+    assert( pCex->iPo >= 0 && pCex->iPo < Saig_ManPoNum(pAig) );
+
+    // map PIs of the unrolled frames into PIs of the original design
+    *pvMapPiF2A = Vec_IntAlloc( 1000 );
+
+    // collect COs and Objs visited in each frame
+    vFrameCos  = Vec_VecStart( pCex->iFrame+1 );
+    vFrameObjs = Vec_VecStart( pCex->iFrame+1 );
+    // initialized the topmost frame
+    pObj = Aig_ManCo( pAig, pCex->iPo );
+    Vec_VecPushInt( vFrameCos, pCex->iFrame, Aig_ObjId(pObj) );
+    for ( f = pCex->iFrame; f >= 0; f-- )
+    {
+        // collect nodes starting from the roots
+        Aig_ManIncrementTravId( pAig );
+        vRoots = Vec_VecEntryInt( vFrameCos, f );
+        Aig_ManForEachObjVec( vRoots, pAig, pObj, i )
+            Saig_ManUnrollCollect_rec( pAig, pObj, 
+                Vec_VecEntryInt(vFrameObjs, f),
+                (Vec_Int_t *)(f ? Vec_VecEntry(vFrameCos, f-1) : NULL) );
+    }
+
+    // derive unrolled timeframes
+    pFrames = Aig_ManStart( 10000 );
+    pFrames->pName = Abc_UtilStrsav( pAig->pName );
+    pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec );
+    // initialize the flops 
+    Saig_ManForEachLo( pAig, pObj, i )
+        pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Abc_InfoHasBit(pCex->pData, i) );
+    // iterate through the frames
+    for ( f = 0; f <= pCex->iFrame; f++ )
+    {
+        // construct
+        vObjs = Vec_VecEntryInt( vFrameObjs, f );
+        Aig_ManForEachObjVec( vObjs, pAig, pObj, i )
+        {
+            if ( Aig_ObjIsNode(pObj) )
+                pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+            else if ( Aig_ObjIsCo(pObj) )
+                pObj->pData = Aig_ObjChild0Copy(pObj);
+            else if ( Aig_ObjIsConst1(pObj) )
+                pObj->pData = Aig_ManConst1(pFrames);
+            else if ( Saig_ObjIsPi(pAig, pObj) )
+            {
+                if ( Aig_ObjCioId(pObj) < nInputs )
+                {
+                    int iBit = pCex->nRegs + f * pCex->nPis + Aig_ObjCioId(pObj);
+                    pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Abc_InfoHasBit(pCex->pData, iBit) );
+                }
+                else
+                {
+                    pObj->pData = Aig_ObjCreateCi( pFrames );
+                    Vec_IntPush( *pvMapPiF2A, Aig_ObjCioId(pObj) );
+                    Vec_IntPush( *pvMapPiF2A, f );
+                }
+            }
+        }
+        if ( f == pCex->iFrame )
+            break;
+        // transfer
+        vRoots = Vec_VecEntryInt( vFrameCos, f );
+        Aig_ManForEachObjVec( vRoots, pAig, pObj, i )
+            Saig_ObjLiToLo( pAig, pObj )->pData = pObj->pData;
+    }
+    // create output
+    pObj = Aig_ManCo( pAig, pCex->iPo );
+    Aig_ObjCreateCo( pFrames, Aig_Not((Aig_Obj_t *)pObj->pData) );
+    Aig_ManSetRegNum( pFrames, 0 );
+    // cleanup
+    Vec_VecFree( vFrameCos );
+    Vec_VecFree( vFrameObjs );
+    // finallize
+    Aig_ManCleanup( pFrames );
+    // return
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates refinement manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Saig_RefMan_t * Saig_RefManStart( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, int fVerbose )
+{
+    Saig_RefMan_t * p;
+    p = ABC_CALLOC( Saig_RefMan_t, 1 );
+    p->pAig = pAig;
+    p->pCex = pCex;
+    p->nInputs = nInputs;
+    p->fVerbose = fVerbose;
+    p->pFrames = Saig_ManUnrollWithCex( pAig, pCex, nInputs, &p->vMapPiF2A );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Destroys refinement manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_RefManStop( Saig_RefMan_t * p )
+{
+    Aig_ManStopP( &p->pFrames );
+    Vec_IntFreeP( &p->vMapPiF2A );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets phase bits in the timeframe AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_RefManSetPhases( Saig_RefMan_t * p, Abc_Cex_t * pCare, int fValue1 )
+{
+    Aig_Obj_t * pObj;
+    int i, iFrame, iInput;
+    Aig_ManConst1( p->pFrames )->fPhase = 1;
+    Aig_ManForEachCi( p->pFrames, pObj, i )
+    {
+        iInput = Vec_IntEntry( p->vMapPiF2A, 2*i );
+        iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 );
+        pObj->fPhase = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput );
+        // update value if it is a don't-care
+        if ( pCare && !Abc_InfoHasBit( pCare->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ) )
+            pObj->fPhase = fValue1;
+    }
+    Aig_ManForEachNode( p->pFrames, pObj, i )
+        pObj->fPhase = ( Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj) )
+                     & ( Aig_ObjFanin1(pObj)->fPhase ^ Aig_ObjFaninC1(pObj) );
+    Aig_ManForEachCo( p->pFrames, pObj, i )
+        pObj->fPhase = ( Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj) );
+    pObj = Aig_ManCo( p->pFrames, 0 );
+    return pObj->fPhase;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tries to remove literals from abstraction.]
+
+  Description [The literals are sorted more desirable first.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Saig_RefManOrderLiterals( Saig_RefMan_t * p, Vec_Int_t * vVar2PiId, Vec_Int_t * vAssumps )
+{
+    Vec_Vec_t * vLits;
+    Vec_Int_t * vVar2New;
+    int i, Entry, iInput, iFrame;
+    // collect literals
+    vLits = Vec_VecAlloc( 100 );
+    vVar2New = Vec_IntStartFull( Saig_ManPiNum(p->pAig) );
+    Vec_IntForEachEntry( vAssumps, Entry, i )
+    {
+        int iPiNum = Vec_IntEntry( vVar2PiId, lit_var(Entry) );
+        assert( iPiNum >= 0 && iPiNum < Aig_ManCiNum(p->pFrames) );
+        iInput = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum );
+        iFrame = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum+1 );
+//        Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput );
+        if ( Vec_IntEntry( vVar2New, iInput ) == ~0 )
+            Vec_IntWriteEntry( vVar2New, iInput, Vec_VecSize(vLits) );
+        Vec_VecPushInt( vLits, Vec_IntEntry( vVar2New, iInput ), Entry );
+    }
+    Vec_IntFree( vVar2New );
+    return vLits;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Generate the care set using SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Saig_RefManCreateCex( Saig_RefMan_t * p, Vec_Int_t * vVar2PiId, Vec_Int_t * vAssumps )
+{
+    Abc_Cex_t * pCare;
+    int i, Entry, iInput, iFrame;
+    // create counter-example
+    pCare = Abc_CexDup( p->pCex, p->pCex->nRegs );
+    memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) );
+    Vec_IntForEachEntry( vAssumps, Entry, i )
+    {
+        int iPiNum = Vec_IntEntry( vVar2PiId, lit_var(Entry) );
+        assert( iPiNum >= 0 && iPiNum < Aig_ManCiNum(p->pFrames) );
+        iInput = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum );
+        iFrame = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum+1 );
+        Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput );
+    }
+    return pCare;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generate the care set using SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Saig_RefManRunSat( Saig_RefMan_t * p, int fNewOrder )
+{
+    int nConfLimit = 1000000;
+    Abc_Cex_t * pCare;
+    Cnf_Dat_t * pCnf;
+    sat_solver * pSat;
+    Aig_Obj_t * pObj;
+    Vec_Vec_t * vLits = NULL;
+    Vec_Int_t * vAssumps, * vVar2PiId;
+    int i, k, Entry, RetValue;//, f = 0, Counter = 0;
+    int nCoreLits, * pCoreLits;
+    abctime clk = Abc_Clock();
+    // create CNF
+    assert( Aig_ManRegNum(p->pFrames) == 0 );
+//    pCnf = Cnf_Derive( p->pFrames, 0 ); // too slow
+    pCnf = Cnf_DeriveSimple( p->pFrames, 0 );
+    RetValue = Saig_RefManSetPhases( p, NULL, 0 );
+    if ( RetValue )
+    {
+        printf( "Constructed frames are incorrect.\n" );
+        Cnf_DataFree( pCnf );
+        return NULL;
+    }
+    Cnf_DataTranformPolarity( pCnf, 0 );
+    // create SAT solver
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+    if ( pSat == NULL )
+    {
+        Cnf_DataFree( pCnf );
+        return NULL;
+    }
+//Abc_PrintTime( 1, "Preparing", Abc_Clock() - clk );
+    // look for a true counter-example
+    if ( p->nInputs > 0 )
+    {
+        RetValue = sat_solver_solve( pSat, NULL, NULL, 
+            (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        if ( RetValue == l_False )
+        {
+            printf( "The problem is trivially UNSAT. The CEX is real.\n" );
+            // create counter-example
+            pCare = Abc_CexDup( p->pCex, p->pCex->nRegs );
+            memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) );
+            return pCare;
+        }
+        // the problem is SAT - it is expected
+    }
+    // create assumptions
+    vVar2PiId = Vec_IntStartFull( pCnf->nVars );
+    vAssumps = Vec_IntAlloc( Aig_ManCiNum(p->pFrames) );
+    Aig_ManForEachCi( p->pFrames, pObj, i )
+    {
+//        RetValue = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput );
+//        Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !RetValue ) );
+        Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 1 ) );
+        Vec_IntWriteEntry( vVar2PiId, pCnf->pVarNums[Aig_ObjId(pObj)], i );
+    }
+
+    // reverse the order of assumptions
+//    if ( fNewOrder )
+//    Vec_IntReverseOrder( vAssumps );
+
+    if ( fNewOrder )
+    {
+        // create literals
+        vLits = Saig_RefManOrderLiterals( p, vVar2PiId, vAssumps );
+        // sort literals
+        Vec_VecSort( vLits, 1 );
+        // save literals
+        Vec_IntClear( vAssumps );
+        Vec_VecForEachEntryInt( vLits, Entry, i, k )
+            Vec_IntPush( vAssumps, Entry );
+
+        for ( i = 0; i < Vec_VecSize(vLits); i++ )
+            printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) );
+        printf( "\n" );
+
+        if ( p->fVerbose )
+            printf( "Total PIs = %d. Essential PIs = %d.\n", 
+                Saig_ManPiNum(p->pAig) - p->nInputs, Vec_VecSize(vLits) );
+    }
+
+    // solve
+clk = Abc_Clock();
+    RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), 
+        (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+//Abc_PrintTime( 1, "Solving", Abc_Clock() - clk );
+    if ( RetValue != l_False )
+    {
+        if ( RetValue == l_True )
+            printf( "Internal Error!!! The resulting problem is SAT.\n" );
+        else
+            printf( "Internal Error!!! SAT solver timed out.\n" );
+        Cnf_DataFree( pCnf );
+        sat_solver_delete( pSat );
+        Vec_IntFree( vAssumps );
+        Vec_IntFree( vVar2PiId );
+        return NULL;
+    }
+    assert( RetValue == l_False ); // UNSAT
+
+    // get relevant SAT literals
+    nCoreLits = sat_solver_final( pSat, &pCoreLits );
+    assert( nCoreLits > 0 );
+    if ( p->fVerbose )
+    printf( "AnalizeFinal selected %d assumptions (out of %d). Conflicts = %d.\n", 
+        nCoreLits, Vec_IntSize(vAssumps), (int)pSat->stats.conflicts );
+
+    // save literals
+    Vec_IntClear( vAssumps );
+    for ( i = 0; i < nCoreLits; i++ )
+        Vec_IntPush( vAssumps, pCoreLits[i] );
+
+
+    // create literals
+    vLits = Saig_RefManOrderLiterals( p, vVar2PiId, vAssumps );
+    // sort literals
+//    Vec_VecSort( vLits, 0 );
+    // save literals
+    Vec_IntClear( vAssumps );
+    Vec_VecForEachEntryInt( vLits, Entry, i, k )
+        Vec_IntPush( vAssumps, Entry );
+
+//    for ( i = 0; i < Vec_VecSize(vLits); i++ )
+//        printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) );
+//    printf( "\n" );
+
+    if ( p->fVerbose )
+        printf( "Total PIs = %d. Essential PIs = %d.\n", 
+            Saig_ManPiNum(p->pAig) - p->nInputs, Vec_VecSize(vLits) );
+/*
+    // try assumptions in different order
+    RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), 
+        (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", 
+        Vec_IntSize(vAssumps), (RetValue == l_False ? "UNSAT" : "SAT"), (int)pSat->stats.conflicts );
+
+    // create different sets of assumptions
+    Counter = Vec_VecSize(vLits);
+    for ( f = 0; f < Vec_VecSize(vLits); f++ )
+    {
+        Vec_IntClear( vAssumps );
+        Vec_VecForEachEntryInt( vLits, Entry, i, k )
+            if ( i != f )
+                Vec_IntPush( vAssumps, Entry );
+
+        // try the new assumptions
+        RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), 
+            (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", 
+            Vec_IntSize(vAssumps), RetValue == l_False ? "UNSAT" : "SAT", (int)pSat->stats.conflicts );
+        if ( RetValue != l_False )
+            continue;
+
+        // UNSAT - remove literals
+        Vec_IntClear( Vec_VecEntryInt(vLits, f) );
+        Counter--;
+    }
+
+    for ( i = 0; i < Vec_VecSize(vLits); i++ )
+        printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) );
+    printf( "\n" );
+
+    if ( p->fVerbose )
+        printf( "Total PIs = %d. Essential PIs = %d.\n", 
+            Saig_ManPiNum(p->pAig) - p->nInputs, Counter );
+
+    // save literals
+    Vec_IntClear( vAssumps );
+    Vec_VecForEachEntryInt( vLits, Entry, i, k )
+        Vec_IntPush( vAssumps, Entry );
+*/
+    // create counter-example
+    pCare = Saig_RefManCreateCex( p, vVar2PiId, vAssumps );
+
+    // cleanup
+    Cnf_DataFree( pCnf );
+    sat_solver_delete( pSat );
+    Vec_IntFree( vAssumps );
+    Vec_IntFree( vVar2PiId );
+    Vec_VecFreeP( &vLits );
+
+    // verify counter-example
+    RetValue = Saig_RefManSetPhases( p, pCare, 0 );
+    if ( RetValue )
+        printf( "Reduced CEX verification has failed.\n" );
+    RetValue = Saig_RefManSetPhases( p, pCare, 1 );
+    if ( RetValue )
+        printf( "Reduced CEX verification has failed.\n" );
+    return pCare;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []               
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_RefManRefineWithSat( Saig_RefMan_t * p, Vec_Int_t * vAigPis )
+{
+    int nConfLimit = 1000000;
+    Cnf_Dat_t * pCnf;
+    sat_solver * pSat;
+    Aig_Obj_t * pObj;
+    Vec_Vec_t * vLits;
+    Vec_Int_t * vReasons, * vAssumps, * vVisited, * vVar2PiId;
+    int i, k, f, Entry, RetValue, Counter;
+
+    // create CNF and SAT solver
+    pCnf = Cnf_DeriveSimple( p->pFrames, 0 );
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+    if ( pSat == NULL )
+    {
+        Cnf_DataFree( pCnf );
+        return NULL;
+    }
+
+    // mark used AIG inputs
+    vVisited = Vec_IntStart( Saig_ManPiNum(p->pAig) );
+    Vec_IntForEachEntry( vAigPis, Entry, i )
+    {
+        assert( Entry >= 0 && Entry < Aig_ManCiNum(p->pAig) );
+        Vec_IntWriteEntry( vVisited, Entry, 1 );
+    }
+
+    // create assumptions
+    vVar2PiId = Vec_IntStartFull( pCnf->nVars );
+    vAssumps = Vec_IntAlloc( Aig_ManCiNum(p->pFrames) );
+    Aig_ManForEachCi( p->pFrames, pObj, i )
+    {
+        int iInput = Vec_IntEntry( p->vMapPiF2A, 2*i );
+        int iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 );
+        if ( Vec_IntEntry(vVisited, iInput) == 0 )
+            continue;
+        RetValue = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput );
+        Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !RetValue ) );
+//        Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 1 ) );
+        Vec_IntWriteEntry( vVar2PiId, pCnf->pVarNums[Aig_ObjId(pObj)], i );
+    }
+    Vec_IntFree( vVisited );
+
+    // try assumptions in different order
+    RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), 
+        (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", 
+        Vec_IntSize(vAssumps), (RetValue == l_False ? "UNSAT" : "SAT"), (int)pSat->stats.conflicts );
+
+/*
+    // AnalizeFinal does not work because it implications propagate directly
+    // and SAT solver does not kick in (the number of conflicts in 0).
+
+    // count the number of lits in the unsat core
+    {
+        int nCoreLits, * pCoreLits;
+        nCoreLits = sat_solver_final( pSat, &pCoreLits );
+        assert( nCoreLits > 0 );
+
+        // count the number of flops
+        vVisited = Vec_IntStart( Saig_ManPiNum(p->pAig) );
+        for ( i = 0; i < nCoreLits; i++ )
+        {
+            int iPiNum = Vec_IntEntry( vVar2PiId, lit_var(pCoreLits[i]) );
+            int iInput = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum );
+            int iFrame = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum+1 );
+            Vec_IntWriteEntry( vVisited, iInput, 1 );
+        }
+        // count the number of entries
+        Counter = 0;
+        Vec_IntForEachEntry( vVisited, Entry, i )
+            Counter += Entry;
+        Vec_IntFree( vVisited );
+
+//        if ( p->fVerbose )
+        printf( "AnalizeFinal: Assumptions %d (out of %d). Essential PIs = %d. Conflicts = %d.\n", 
+            nCoreLits, Vec_IntSize(vAssumps), Counter, (int)pSat->stats.conflicts );
+    }
+*/
+
+    // derive literals
+    vLits = Saig_RefManOrderLiterals( p, vVar2PiId, vAssumps );
+    for ( i = 0; i < Vec_VecSize(vLits); i++ )
+        printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) );
+    printf( "\n" );
+
+    // create different sets of assumptions
+    Counter = Vec_VecSize(vLits);
+    for ( f = 0; f < Vec_VecSize(vLits); f++ )
+    {
+        Vec_IntClear( vAssumps );
+        Vec_VecForEachEntryInt( vLits, Entry, i, k )
+            if ( i != f )
+                Vec_IntPush( vAssumps, Entry );
+
+        // try the new assumptions
+        RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), 
+            (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", 
+            Vec_IntSize(vAssumps), RetValue == l_False ? "UNSAT" : "SAT", (int)pSat->stats.conflicts );
+        if ( RetValue != l_False )
+            continue;
+
+        // UNSAT - remove literals
+        Vec_IntClear( Vec_VecEntryInt(vLits, f) );
+        Counter--;
+    }
+
+    for ( i = 0; i < Vec_VecSize(vLits); i++ )
+        printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) );
+    printf( "\n" );
+
+    // create assumptions
+    Vec_IntClear( vAssumps );
+    Vec_VecForEachEntryInt( vLits, Entry, i, k )
+        Vec_IntPush( vAssumps, Entry );
+
+    // try assumptions in different order
+    RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), 
+        (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", 
+        Vec_IntSize(vAssumps), (RetValue == l_False ? "UNSAT" : "SAT"), (int)pSat->stats.conflicts );
+
+//    if ( p->fVerbose )
+//        printf( "Total PIs = %d. Essential PIs = %d.\n", 
+//            Saig_ManPiNum(p->pAig) - p->nInputs, Counter );
+
+
+    // transform assumptions into reasons
+    vReasons = Vec_IntAlloc( 100 );
+    Vec_IntForEachEntry( vAssumps, Entry, i )
+    {
+        int iPiNum = Vec_IntEntry( vVar2PiId, lit_var(Entry) );
+        assert( iPiNum >= 0 && iPiNum < Aig_ManCiNum(p->pFrames) );
+        Vec_IntPush( vReasons, iPiNum );
+    }
+
+    // cleanup
+    Cnf_DataFree( pCnf );
+    sat_solver_delete( pSat );
+    Vec_IntFree( vAssumps );
+    Vec_IntFree( vVar2PiId );
+    Vec_VecFreeP( &vLits );
+
+    return vReasons;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [SAT-based refinement of the counter-example.]
+
+  Description [The first parameter (nInputs) indicates how many first 
+  primary inputs to skip without considering as care candidates.]
+               
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Saig_ManFindCexCareBits( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, int fNewOrder, int fVerbose )
+{
+    Saig_RefMan_t * p;
+    Vec_Int_t * vReasons;
+    Abc_Cex_t * pCare;
+    abctime clk = Abc_Clock();
+
+    clk = Abc_Clock();
+    p = Saig_RefManStart( pAig, pCex, nInputs, fVerbose );
+    vReasons = Saig_RefManFindReason( p );
+
+if ( fVerbose )
+Aig_ManPrintStats( p->pFrames );
+
+//    if ( fVerbose )
+    {
+        Vec_Int_t * vRes = Saig_RefManReason2Inputs( p, vReasons );
+        printf( "Frame PIs = %4d (essential = %4d)   AIG PIs = %4d (essential = %4d)   ",
+            Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), 
+            Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+
+        Vec_IntFree( vRes );
+
+/*
+        ////////////////////////////////////
+        Vec_IntFree( vReasons );
+        vReasons = Saig_RefManRefineWithSat( p, vRes );
+        ////////////////////////////////////
+
+        Vec_IntFree( vRes );
+        vRes = Saig_RefManReason2Inputs( p, vReasons );
+        printf( "Frame PIs = %4d (essential = %4d)   AIG PIs = %4d (essential = %4d)   ",
+            Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), 
+            Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) );
+
+        Vec_IntFree( vRes );
+ABC_PRT( "Time", Abc_Clock() - clk );
+*/
+    }
+
+    pCare = Saig_RefManReason2Cex( p, vReasons );
+    Vec_IntFree( vReasons );
+    Saig_RefManStop( p );
+
+if ( fVerbose )
+Abc_CexPrintStats( pCex );
+if ( fVerbose )
+Abc_CexPrintStats( pCare );
+
+    return pCare;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of PIs for flops that should not be absracted.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManExtendCounterExampleTest3( Aig_Man_t * pAig, int iFirstFlopPi, Abc_Cex_t * pCex, int fVerbose )
+{
+    Saig_RefMan_t * p;
+    Vec_Int_t * vRes, * vReasons;
+    abctime clk;
+    if ( Saig_ManPiNum(pAig) != pCex->nPis )
+    {
+        printf( "Saig_ManExtendCounterExampleTest3(): The PI count of AIG (%d) does not match that of cex (%d).\n", 
+            Aig_ManCiNum(pAig), pCex->nPis );
+        return NULL;
+    }
+
+clk = Abc_Clock();
+
+    p = Saig_RefManStart( pAig, pCex, iFirstFlopPi, fVerbose );
+    vReasons = Saig_RefManFindReason( p );
+    vRes = Saig_RefManReason2Inputs( p, vReasons );
+
+//    if ( fVerbose )
+    {
+        printf( "Frame PIs = %4d (essential = %4d)   AIG PIs = %4d (essential = %4d)   ",
+            Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), 
+            Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+
+/*
+    ////////////////////////////////////
+    Vec_IntFree( vReasons );
+    vReasons = Saig_RefManRefineWithSat( p, vRes );
+    ////////////////////////////////////
+
+    // derive new result
+    Vec_IntFree( vRes );
+    vRes = Saig_RefManReason2Inputs( p, vReasons );
+//    if ( fVerbose )
+    {
+        printf( "Frame PIs = %4d (essential = %4d)   AIG PIs = %4d (essential = %4d)   ",
+            Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), 
+            Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+*/
+
+    Vec_IntFree( vReasons );
+    Saig_RefManStop( p );
+    return vRes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/absOldSim.c b/abc-build/src/proof/abs/absOldSim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absOldSim.c
@@ -0,0 +1,477 @@
+/**CFile****************************************************************
+
+  FileName    [saigSimExt2.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Sequential AIG package.]
+
+  Synopsis    [Extending simulation trace to contain ternary values.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: saigSimExt2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abs.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define SAIG_ZER 1
+#define SAIG_ONE 2
+#define SAIG_UND 3
+
+static inline int Saig_ManSimInfoNot( int Value )
+{
+    if ( Value == SAIG_ZER )
+        return SAIG_ONE;
+    if ( Value == SAIG_ONE )
+        return SAIG_ZER;
+    return SAIG_UND;
+}
+
+static inline int Saig_ManSimInfoAnd( int Value0, int Value1 )
+{
+    if ( Value0 == SAIG_ZER || Value1 == SAIG_ZER )
+        return SAIG_ZER;
+    if ( Value0 == SAIG_ONE && Value1 == SAIG_ONE )
+        return SAIG_ONE;
+    return SAIG_UND;
+}
+
+static inline int Saig_ManSimInfoGet( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame )
+{
+    unsigned * pInfo = (unsigned *)Vec_PtrEntry( vSimInfo, Aig_ObjId(pObj) );
+    return 3 & (pInfo[iFrame >> 4] >> ((iFrame & 15) << 1));
+}
+
+static inline void Saig_ManSimInfoSet( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame, int Value )
+{
+    unsigned * pInfo = (unsigned *)Vec_PtrEntry( vSimInfo, Aig_ObjId(pObj) );
+    assert( Value >= SAIG_ZER && Value <= SAIG_UND );
+    Value ^= Saig_ManSimInfoGet( vSimInfo, pObj, iFrame );
+    pInfo[iFrame >> 4] ^= (Value << ((iFrame & 15) << 1));
+}
+
+
+
+#define SAIG_ZER_NEW 0   // 0 not visited
+#define SAIG_ONE_NEW 1   // 1 not visited
+#define SAIG_ZER_OLD 2   // 0 visited
+#define SAIG_ONE_OLD 3   // 1 visited
+
+static inline int Saig_ManSimInfo2IsOld( int Value )
+{
+    return Value == SAIG_ZER_OLD || Value == SAIG_ONE_OLD;
+}
+
+static inline int Saig_ManSimInfo2SetOld( int Value )
+{
+    if ( Value == SAIG_ZER_NEW )
+        return SAIG_ZER_OLD;
+    if ( Value == SAIG_ONE_NEW )
+        return SAIG_ONE_OLD;
+    assert( 0 );
+    return 0;
+}
+
+static inline int Saig_ManSimInfo2Not( int Value )
+{
+    if ( Value == SAIG_ZER_NEW )
+        return SAIG_ONE_NEW;
+    if ( Value == SAIG_ONE_NEW )
+        return SAIG_ZER_NEW;
+    if ( Value == SAIG_ZER_OLD )
+        return SAIG_ONE_OLD;
+    if ( Value == SAIG_ONE_OLD )
+        return SAIG_ZER_OLD;
+    assert( 0 );
+    return 0;
+}
+
+static inline int Saig_ManSimInfo2And( int Value0, int Value1 )
+{
+    if ( Value0 == SAIG_ZER_NEW || Value1 == SAIG_ZER_NEW )
+        return SAIG_ZER_NEW;
+    if ( Value0 == SAIG_ONE_NEW && Value1 == SAIG_ONE_NEW )
+        return SAIG_ONE_NEW;
+    assert( 0 );
+    return 0;
+}
+
+static inline int Saig_ManSimInfo2Get( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame )
+{
+    unsigned * pInfo = (unsigned *)Vec_PtrEntry( vSimInfo, Aig_ObjId(pObj) );
+    return 3 & (pInfo[iFrame >> 4] >> ((iFrame & 15) << 1));
+}
+
+static inline void Saig_ManSimInfo2Set( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame, int Value )
+{
+    unsigned * pInfo = (unsigned *)Vec_PtrEntry( vSimInfo, Aig_ObjId(pObj) );
+    Value ^= Saig_ManSimInfo2Get( vSimInfo, pObj, iFrame );
+    pInfo[iFrame >> 4] ^= (Value << ((iFrame & 15) << 1));
+}
+
+// performs ternary simulation
+//extern int Saig_ManSimDataInit( Aig_Man_t * p, Abc_Cex_t * pCex, Vec_Ptr_t * vSimInfo, Vec_Int_t * vRes );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs ternary simulation for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManExtendOneEval( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame )
+{
+    int Value0, Value1, Value;
+    Value0 = Saig_ManSimInfoGet( vSimInfo, Aig_ObjFanin0(pObj), iFrame );
+    if ( Aig_ObjFaninC0(pObj) )
+        Value0 = Saig_ManSimInfoNot( Value0 );
+    if ( Aig_ObjIsCo(pObj) )
+    {
+        Saig_ManSimInfoSet( vSimInfo, pObj, iFrame, Value0 );
+        return Value0;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    Value1 = Saig_ManSimInfoGet( vSimInfo, Aig_ObjFanin1(pObj), iFrame );
+    if ( Aig_ObjFaninC1(pObj) )
+        Value1 = Saig_ManSimInfoNot( Value1 );
+    Value = Saig_ManSimInfoAnd( Value0, Value1 );
+    Saig_ManSimInfoSet( vSimInfo, pObj, iFrame, Value );
+    return Value;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs ternary simulation for one design.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManSimDataInit( Aig_Man_t * p, Abc_Cex_t * pCex, Vec_Ptr_t * vSimInfo, Vec_Int_t * vRes )
+{
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i, f, Entry, iBit = 0;
+    Saig_ManForEachLo( p, pObj, i )
+        Saig_ManSimInfoSet( vSimInfo, pObj, 0, Abc_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE:SAIG_ZER );
+    for ( f = 0; f <= pCex->iFrame; f++ )
+    {
+        Saig_ManSimInfoSet( vSimInfo, Aig_ManConst1(p), f, SAIG_ONE );
+        Saig_ManForEachPi( p, pObj, i )
+            Saig_ManSimInfoSet( vSimInfo, pObj, f, Abc_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE:SAIG_ZER );
+        if ( vRes )
+        Vec_IntForEachEntry( vRes, Entry, i )
+            Saig_ManSimInfoSet( vSimInfo, Aig_ManCi(p, Entry), f, SAIG_UND );
+        Aig_ManForEachNode( p, pObj, i )
+            Saig_ManExtendOneEval( vSimInfo, pObj, f );
+        Aig_ManForEachCo( p, pObj, i )
+            Saig_ManExtendOneEval( vSimInfo, pObj, f );
+        if ( f == pCex->iFrame )
+            break;
+        Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
+            Saig_ManSimInfoSet( vSimInfo, pObjLo, f+1, Saig_ManSimInfoGet(vSimInfo, pObjLi, f) );
+    }
+    // make sure the output of the property failed
+    pObj = Aig_ManCo( p, pCex->iPo );
+    return Saig_ManSimInfoGet( vSimInfo, pObj, pCex->iFrame );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs ternary simulation for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManExtendOneEval2( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame )
+{
+    int Value0, Value1, Value;
+    Value0 = Saig_ManSimInfo2Get( vSimInfo, Aig_ObjFanin0(pObj), iFrame );
+    if ( Aig_ObjFaninC0(pObj) )
+        Value0 = Saig_ManSimInfo2Not( Value0 );
+    if ( Aig_ObjIsCo(pObj) )
+    {
+        Saig_ManSimInfo2Set( vSimInfo, pObj, iFrame, Value0 );
+        return Value0;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    Value1 = Saig_ManSimInfo2Get( vSimInfo, Aig_ObjFanin1(pObj), iFrame );
+    if ( Aig_ObjFaninC1(pObj) )
+        Value1 = Saig_ManSimInfo2Not( Value1 );
+    Value = Saig_ManSimInfo2And( Value0, Value1 );
+    Saig_ManSimInfo2Set( vSimInfo, pObj, iFrame, Value );
+    return Value;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs sensitization analysis for one design.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManSimDataInit2( Aig_Man_t * p, Abc_Cex_t * pCex, Vec_Ptr_t * vSimInfo )
+{
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i, f, iBit = 0;
+    Saig_ManForEachLo( p, pObj, i )
+        Saig_ManSimInfo2Set( vSimInfo, pObj, 0, Abc_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE_NEW:SAIG_ZER_NEW );
+    for ( f = 0; f <= pCex->iFrame; f++ )
+    {
+        Saig_ManSimInfo2Set( vSimInfo, Aig_ManConst1(p), f, SAIG_ONE_NEW );
+        Saig_ManForEachPi( p, pObj, i )
+            Saig_ManSimInfo2Set( vSimInfo, pObj, f, Abc_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE_NEW:SAIG_ZER_NEW );
+        Aig_ManForEachNode( p, pObj, i )
+            Saig_ManExtendOneEval2( vSimInfo, pObj, f );
+        Aig_ManForEachCo( p, pObj, i )
+            Saig_ManExtendOneEval2( vSimInfo, pObj, f );
+        if ( f == pCex->iFrame )
+            break;
+        Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
+            Saig_ManSimInfo2Set( vSimInfo, pObjLo, f+1, Saig_ManSimInfo2Get(vSimInfo, pObjLi, f) );
+    }
+    // make sure the output of the property failed
+    pObj = Aig_ManCo( p, pCex->iPo );
+    return Saig_ManSimInfo2Get( vSimInfo, pObj, pCex->iFrame );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Drive implications of the given node towards primary outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManSetAndDriveImplications_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int f, int fMax, Vec_Ptr_t * vSimInfo )
+{
+    Aig_Obj_t * pFanout;
+    int k, iFanout = -1, Value0, Value1;
+    int Value = Saig_ManSimInfo2Get( vSimInfo, pObj, f );
+    assert( !Saig_ManSimInfo2IsOld( Value ) );
+    Saig_ManSimInfo2Set( vSimInfo, pObj, f, Saig_ManSimInfo2SetOld(Value) );
+    if ( (Aig_ObjIsCo(pObj) && f == fMax) || Saig_ObjIsPo(p, pObj) )
+        return;
+    if ( Saig_ObjIsLi( p, pObj ) )
+    {
+        assert( f < fMax );
+        pFanout = Saig_ObjLiToLo(p, pObj);
+        Value = Saig_ManSimInfo2Get( vSimInfo, pFanout, f+1 );
+        if ( !Saig_ManSimInfo2IsOld( Value ) )
+            Saig_ManSetAndDriveImplications_rec( p, pFanout, f+1, fMax, vSimInfo );
+        return;
+    }
+    assert( Aig_ObjIsCi(pObj) || Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(pObj) );
+    Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, k )
+    {
+        Value = Saig_ManSimInfo2Get( vSimInfo, pFanout, f );
+        if ( Saig_ManSimInfo2IsOld( Value ) )
+            continue;
+        if ( Aig_ObjIsCo(pFanout) )
+        {
+            Saig_ManSetAndDriveImplications_rec( p, pFanout, f, fMax, vSimInfo );
+            continue;
+        }
+        assert( Aig_ObjIsNode(pFanout) );
+        Value0 = Saig_ManSimInfo2Get( vSimInfo, Aig_ObjFanin0(pFanout), f );
+        Value1 = Saig_ManSimInfo2Get( vSimInfo, Aig_ObjFanin1(pFanout), f );
+        if ( Aig_ObjFaninC0(pFanout) )
+            Value0 = Saig_ManSimInfo2Not( Value0 );
+        if ( Aig_ObjFaninC1(pFanout) )
+            Value1 = Saig_ManSimInfo2Not( Value1 );
+        if ( Value0 == SAIG_ZER_OLD || Value1 == SAIG_ZER_OLD || 
+            (Value0 == SAIG_ONE_OLD && Value1 == SAIG_ONE_OLD) )
+            Saig_ManSetAndDriveImplications_rec( p, pFanout, f, fMax, vSimInfo );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs recursive sensetization analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManExplorePaths_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int f, int fMax, Vec_Ptr_t * vSimInfo )
+{
+    int Value = Saig_ManSimInfo2Get( vSimInfo, pObj, f );
+    if ( Saig_ManSimInfo2IsOld( Value ) )
+        return;
+    Saig_ManSetAndDriveImplications_rec( p, pObj, f, fMax, vSimInfo );
+    assert( !Aig_ObjIsConst1(pObj) );
+    if ( Saig_ObjIsLo(p, pObj) && f == 0 )
+        return;
+    if ( Saig_ObjIsPi(p, pObj) )
+    {
+        // propagate implications of this assignment
+        int i, iPiNum = Aig_ObjCioId(pObj);
+        for ( i = fMax; i >= 0; i-- )
+            if ( i != f )
+                Saig_ManSetAndDriveImplications_rec( p, Aig_ManCi(p, iPiNum), i, fMax, vSimInfo );
+        return;
+    }
+    if ( Saig_ObjIsLo( p, pObj ) )
+    {
+        assert( f > 0 );
+        Saig_ManExplorePaths_rec( p, Saig_ObjLoToLi(p, pObj), f-1, fMax, vSimInfo );
+        return;
+    }
+    if ( Aig_ObjIsCo(pObj) )
+    {
+        Saig_ManExplorePaths_rec( p, Aig_ObjFanin0(pObj), f, fMax, vSimInfo );
+        return;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    if ( Value == SAIG_ZER_OLD )
+    {
+//        if ( (Aig_ObjId(pObj) & 1) == 0 )
+            Saig_ManExplorePaths_rec( p, Aig_ObjFanin0(pObj), f, fMax, vSimInfo );
+//        else
+//            Saig_ManExplorePaths_rec( p, Aig_ObjFanin1(pObj), f, fMax, vSimInfo );
+    }
+    else
+    {
+        Saig_ManExplorePaths_rec( p, Aig_ObjFanin0(pObj), f, fMax, vSimInfo );
+        Saig_ManExplorePaths_rec( p, Aig_ObjFanin1(pObj), f, fMax, vSimInfo );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of PIs for flops that should not be absracted.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManProcessCex( Aig_Man_t * p, int iFirstFlopPi, Abc_Cex_t * pCex, Vec_Ptr_t * vSimInfo, int fVerbose )
+{
+    Aig_Obj_t * pObj;
+    Vec_Int_t * vRes, * vResInv;
+    int i, f, Value;
+//    assert( Aig_ManRegNum(p) > 0 );
+    assert( (unsigned *)Vec_PtrEntry(vSimInfo,1) - (unsigned *)Vec_PtrEntry(vSimInfo,0) >= Abc_BitWordNum(2*(pCex->iFrame+1)) );
+    // start simulation data
+    Value = Saig_ManSimDataInit2( p, pCex, vSimInfo );
+    assert( Value == SAIG_ONE_NEW );
+    // derive implications of constants and primary inputs
+    Saig_ManForEachLo( p, pObj, i )
+        Saig_ManSetAndDriveImplications_rec( p, pObj, 0, pCex->iFrame, vSimInfo );
+    for ( f = pCex->iFrame; f >= 0; f-- )
+    {
+        Saig_ManSetAndDriveImplications_rec( p, Aig_ManConst1(p), f, pCex->iFrame, vSimInfo );
+        for ( i = 0; i < iFirstFlopPi; i++ )
+            Saig_ManSetAndDriveImplications_rec( p, Aig_ManCi(p, i), f, pCex->iFrame, vSimInfo );
+    }
+    // recursively compute justification
+    Saig_ManExplorePaths_rec( p, Aig_ManCo(p, pCex->iPo), pCex->iFrame, pCex->iFrame, vSimInfo );
+    // select the result
+    vRes = Vec_IntAlloc( 1000 );
+    vResInv = Vec_IntAlloc( 1000 );
+    for ( i = iFirstFlopPi; i < Saig_ManPiNum(p); i++ )
+    {
+        for ( f = pCex->iFrame; f >= 0; f-- )
+        {
+            Value = Saig_ManSimInfo2Get( vSimInfo, Aig_ManCi(p, i), f );
+            if ( Saig_ManSimInfo2IsOld( Value ) )
+                break;
+        }
+        if ( f >= 0 )
+            Vec_IntPush( vRes, i );
+        else
+            Vec_IntPush( vResInv, i );
+    }
+    // resimulate to make sure it is valid
+    Value = Saig_ManSimDataInit( p, pCex, vSimInfo, vResInv );
+    assert( Value == SAIG_ONE );
+    Vec_IntFree( vResInv );
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of PIs for flops that should not be absracted.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManExtendCounterExampleTest2( Aig_Man_t * p, int iFirstFlopPi, Abc_Cex_t * pCex, int fVerbose )
+{
+    Vec_Int_t * vRes;
+    Vec_Ptr_t * vSimInfo;
+    abctime clk;
+    if ( Saig_ManPiNum(p) != pCex->nPis )
+    {
+        printf( "Saig_ManExtendCounterExampleTest2(): The PI count of AIG (%d) does not match that of cex (%d).\n", 
+            Aig_ManCiNum(p), pCex->nPis );
+        return NULL;
+    }
+    Aig_ManFanoutStart( p );
+    vSimInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p), Abc_BitWordNum(2*(pCex->iFrame+1)) );
+    Vec_PtrCleanSimInfo( vSimInfo, 0, Abc_BitWordNum(2*(pCex->iFrame+1)) );
+
+clk = Abc_Clock();
+    vRes = Saig_ManProcessCex( p, iFirstFlopPi, pCex, vSimInfo, fVerbose );
+    if ( fVerbose )
+    {
+        printf( "Total new PIs = %3d. Non-removable PIs = %3d.  ", Saig_ManPiNum(p)-iFirstFlopPi, Vec_IntSize(vRes) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    Vec_PtrFree( vSimInfo );
+    Aig_ManFanoutStop( p );
+    return vRes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/absOut.c b/abc-build/src/proof/abs/absOut.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absOut.c
@@ -0,0 +1,458 @@
+/**CFile****************************************************************
+
+  FileName    [absOut.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Abstraction package.]
+
+  Synopsis    [Abstraction refinement outside of abstraction engines.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: absOut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abs.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derive a new counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Gia_ManCexRemap( Gia_Man_t * p, Abc_Cex_t * pCexAbs, Vec_Int_t * vPis )
+{
+    Abc_Cex_t * pCex;
+    int i, f, iPiNum;
+    assert( pCexAbs->iPo == 0 );
+    // start the counter-example
+    pCex = Abc_CexAlloc( Gia_ManRegNum(p), Gia_ManPiNum(p), pCexAbs->iFrame+1 );
+    pCex->iFrame = pCexAbs->iFrame;
+    pCex->iPo    = pCexAbs->iPo;
+    // copy the bit data
+    for ( f = 0; f <= pCexAbs->iFrame; f++ )
+        for ( i = 0; i < Vec_IntSize(vPis); i++ )
+        {
+            if ( Abc_InfoHasBit( pCexAbs->pData, pCexAbs->nRegs + pCexAbs->nPis * f + i ) )
+            {
+                iPiNum = Gia_ObjCioId( Gia_ManObj(p, Vec_IntEntry(vPis, i)) );
+                Abc_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * f + iPiNum );
+            }
+        }
+    // verify the counter example
+    if ( !Gia_ManVerifyCex( p, pCex, 0 ) )
+    {
+        Abc_Print( 1, "Gia_ManCexRemap(): Counter-example is invalid.\n" );
+        Abc_CexFree( pCex );
+        pCex = NULL;
+    }
+    else
+    {
+        Abc_Print( 1, "Counter-example verification is successful.\n" );
+        Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. \n", pCex->iPo, p->pName, pCex->iFrame );
+    }
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines gate-level abstraction using the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManGlaRefine( Gia_Man_t * p, Abc_Cex_t * pCex, int fMinCut, int fVerbose )
+{
+    extern void Nwk_ManDeriveMinCut( Gia_Man_t * p, int fVerbose );
+    int fAddOneLayer = 1;
+    Abc_Cex_t * pCexNew = NULL;
+    Gia_Man_t * pAbs;
+    Aig_Man_t * pAig;
+    Abc_Cex_t * pCare;
+    Vec_Int_t * vPis, * vPPis;
+    int f, i, iObjId;
+    abctime clk = Abc_Clock();
+    int nOnes = 0, Counter = 0;
+    if ( p->vGateClasses == NULL )
+    {
+        Abc_Print( 1, "Gia_ManGlaRefine(): Abstraction gate map is missing.\n" );
+        return -1;
+    }
+    // derive abstraction
+    pAbs = Gia_ManDupAbsGates( p, p->vGateClasses );
+    Gia_ManStop( pAbs );
+    pAbs = Gia_ManDupAbsGates( p, p->vGateClasses );
+    if ( Gia_ManPiNum(pAbs) != pCex->nPis )
+    {
+        Abc_Print( 1, "Gia_ManGlaRefine(): The PI counts in GLA and in CEX do not match.\n" );
+        Gia_ManStop( pAbs );
+        return -1;
+    }
+    if ( !Gia_ManVerifyCex( pAbs, pCex, 0 ) )
+    {
+        Abc_Print( 1, "Gia_ManGlaRefine(): The initial counter-example is invalid.\n" );
+//        Gia_ManStop( pAbs );
+//        return -1;
+    }
+//    else
+//        Abc_Print( 1, "Gia_ManGlaRefine(): The initial counter-example is correct.\n" );
+    // get inputs
+    Gia_ManGlaCollect( p, p->vGateClasses, &vPis, &vPPis, NULL, NULL );
+    assert( Vec_IntSize(vPis) + Vec_IntSize(vPPis) == Gia_ManPiNum(pAbs) );
+    // add missing logic
+    if ( fAddOneLayer )
+    {
+        Gia_Obj_t * pObj;
+        // check if this is a real counter-example
+        Gia_ObjTerSimSet0( Gia_ManConst0(pAbs) );
+        for ( f = 0; f <= pCex->iFrame; f++ )
+        {
+            Gia_ManForEachPi( pAbs, pObj, i )
+            {
+                if ( i >= Vec_IntSize(vPis) ) // PPIs
+                    Gia_ObjTerSimSetX( pObj );
+                else if ( Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i) )
+                    Gia_ObjTerSimSet1( pObj );
+                else
+                    Gia_ObjTerSimSet0( pObj );
+            }
+            Gia_ManForEachRo( pAbs, pObj, i )
+            {
+                if ( f == 0 )
+                    Gia_ObjTerSimSet0( pObj );
+                else
+                    Gia_ObjTerSimRo( pAbs, pObj );
+            }
+            Gia_ManForEachAnd( pAbs, pObj, i )
+                Gia_ObjTerSimAnd( pObj );
+            Gia_ManForEachCo( pAbs, pObj, i )
+                Gia_ObjTerSimCo( pObj );
+        }
+        pObj = Gia_ManPo( pAbs, 0 );
+        if ( Gia_ObjTerSimGet1(pObj) )
+        {
+            pCexNew = Gia_ManCexRemap( p, pCex, vPis );
+            Abc_Print( 1, "Procedure &gla_refine found a real counter-example in frame %d.\n", pCexNew->iFrame );
+        }
+//        else
+//            Abc_Print( 1, "CEX is not real.\n" );
+        Gia_ManForEachObj( pAbs, pObj, i )
+            Gia_ObjTerSimSetC( pObj );
+        if ( pCexNew == NULL )
+        {
+            // grow one layer
+            Vec_IntForEachEntry( vPPis, iObjId, i )
+            {
+                assert( Vec_IntEntry( p->vGateClasses, iObjId ) == 0 );
+                Vec_IntWriteEntry( p->vGateClasses, iObjId, 1 );
+            }
+            if ( fVerbose )
+            {
+                Abc_Print( 1, "Additional objects = %d.  ", Vec_IntSize(vPPis) );
+                Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+            }
+        }
+    }
+    else
+    {
+        // minimize the CEX
+        pAig = Gia_ManToAigSimple( pAbs );
+        pCare = Saig_ManCbaFindCexCareBits( pAig, pCex, Vec_IntSize(vPis), fVerbose );
+        Aig_ManStop( pAig );
+        if ( pCare == NULL )
+            Abc_Print( 1, "Counter-example minimization has failed.\n" );
+        // add new objects to the map
+        iObjId = -1;
+        for ( f = 0; f <= pCare->iFrame; f++ )
+            for ( i = 0; i < pCare->nPis; i++ )
+                if ( Abc_InfoHasBit( pCare->pData, pCare->nRegs + f * pCare->nPis + i ) )
+                {
+                    nOnes++;
+                    assert( i >= Vec_IntSize(vPis) );
+                    iObjId = Vec_IntEntry( vPPis, i - Vec_IntSize(vPis) );
+                    assert( iObjId > 0 && iObjId < Gia_ManObjNum(p) );
+                    if ( Vec_IntEntry( p->vGateClasses, iObjId ) > 0 )
+                        continue;
+                    assert( Vec_IntEntry( p->vGateClasses, iObjId ) == 0 );
+                    Vec_IntWriteEntry( p->vGateClasses, iObjId, 1 );
+    //                Abc_Print( 1, "Adding object %d.\n", iObjId );
+    //                Gia_ObjPrint( p, Gia_ManObj(p, iObjId) );
+                    Counter++;
+                }
+        Abc_CexFree( pCare );
+        if ( fVerbose )
+        {
+            Abc_Print( 1, "Essential bits = %d.  Additional objects = %d.  ", nOnes, Counter );
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+        }
+        // consider the case of SAT
+        if ( iObjId == -1 )
+        {
+            pCexNew = Gia_ManCexRemap( p, pCex, vPis );
+            Abc_Print( 1, "Procedure &gla_refine found a real counter-example in frame %d.\n", pCexNew->iFrame );
+        }
+    }
+    Vec_IntFree( vPis );
+    Vec_IntFree( vPPis );
+    Gia_ManStop( pAbs );
+    if ( pCexNew )
+    {
+        ABC_FREE( p->pCexSeq );
+        p->pCexSeq = pCexNew;
+        return 0;
+    }
+    // extract abstraction to include min-cut
+    if ( fMinCut )
+        Nwk_ManDeriveMinCut( p, fVerbose );
+    return -1;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulates the counter-example and returns flop values.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManGetStateAndCheckCex( Gia_Man_t * pAig, Abc_Cex_t * p, int iFrame )
+{
+    Vec_Int_t * vInit = Vec_IntAlloc( Gia_ManRegNum(pAig) );
+    Gia_Obj_t * pObj, * pObjRi, * pObjRo;
+    int RetValue, i, k, iBit = 0;
+    assert( iFrame >= 0 && iFrame <= p->iFrame );
+    Gia_ManCleanMark0(pAig);
+    Gia_ManForEachRo( pAig, pObj, i )
+        pObj->fMark0 = 0;//Abc_InfoHasBit(p->pData, iBit++);
+    for ( i = 0, iBit = p->nRegs; i <= p->iFrame; i++ )
+    {
+        if ( i == iFrame )
+        {
+            Gia_ManForEachRo( pAig, pObjRo, k )
+                Vec_IntPush( vInit, pObjRo->fMark0 );
+        }
+        Gia_ManForEachPi( pAig, pObj, k )
+            pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++);
+        Gia_ManForEachAnd( pAig, pObj, k )
+            pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & 
+                           (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+        Gia_ManForEachCo( pAig, pObj, k )
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+        if ( i == p->iFrame )
+            break;
+        Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, k )
+            pObjRo->fMark0 = pObjRi->fMark0;
+    }
+    assert( iBit == p->nBits );
+    RetValue = Gia_ManPo(pAig, p->iPo)->fMark0;
+    if ( RetValue != 1 )
+        Vec_IntFreeP( &vInit );
+    Gia_ManCleanMark0(pAig);
+    return vInit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verify counter-example starting in the given timeframe.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCheckCex( Gia_Man_t * pAig, Abc_Cex_t * p, int iFrame )
+{
+    Gia_Obj_t * pObj, * pObjRi, * pObjRo;
+    int RetValue, i, k, iBit = 0;
+    assert( iFrame >= 0 && iFrame <= p->iFrame );
+    Gia_ManCleanMark0(pAig);
+    Gia_ManForEachRo( pAig, pObj, i )
+        pObj->fMark0 = 0;//Abc_InfoHasBit(p->pData, iBit++);
+    for ( i = iFrame, iBit += p->nRegs + Gia_ManPiNum(pAig) * iFrame; i <= p->iFrame; i++ )
+    {
+        Gia_ManForEachPi( pAig, pObj, k )
+            pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++);
+        Gia_ManForEachAnd( pAig, pObj, k )
+            pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & 
+                           (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+        Gia_ManForEachCo( pAig, pObj, k )
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+        if ( i == p->iFrame )
+            break;
+        Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, k )
+            pObjRo->fMark0 = pObjRi->fMark0;
+    }
+    assert( iBit == p->nBits );
+    RetValue = Gia_ManPo(pAig, p->iPo)->fMark0;
+    Gia_ManCleanMark0(pAig);
+    if ( RetValue == 1 )
+        printf( "Shortened CEX holds for the abstraction of the fast-forwarded model.\n" );
+    else
+        printf( "Shortened CEX does not hold for the abstraction of the fast-forwarded model.\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManTransformFlops( Gia_Man_t * p, Vec_Int_t * vFlops, Vec_Int_t * vInit )
+{
+    Vec_Bit_t * vInitNew;
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i, iFlopId;
+    assert( Vec_IntSize(vInit) == Vec_IntSize(vFlops) );
+    vInitNew = Vec_BitStart( Gia_ManRegNum(p) );
+    Gia_ManForEachObjVec( vFlops, p, pObj, i )
+    {
+        assert( Gia_ObjIsRo(p, pObj) );
+        if ( Vec_IntEntry(vInit, i) == 0 )
+            continue;
+        iFlopId = Gia_ObjCioId(pObj) - Gia_ManPiNum(p);
+        assert( iFlopId >= 0 && iFlopId < Gia_ManRegNum(p) );
+        Vec_BitWriteEntry( vInitNew, iFlopId, 1 );
+    }
+    pNew = Gia_ManDupFlip( p, Vec_BitArray(vInitNew) );
+    Vec_BitFree( vInitNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManNewRefine( Gia_Man_t * p, Abc_Cex_t * pCex, int iFrameStart, int iFrameExtra, int fVerbose )
+{
+    Gia_Man_t * pAbs, * pNew;
+    Vec_Int_t * vFlops, * vInit;
+    Vec_Int_t * vCopy;
+//    abctime clk = Abc_Clock();
+    int RetValue;
+    ABC_FREE( p->pCexSeq );
+    if ( p->vGateClasses == NULL )
+    {
+        Abc_Print( 1, "Gia_ManNewRefine(): Abstraction gate map is missing.\n" );
+        return -1;
+    }
+    vCopy = Vec_IntDup( p->vGateClasses );
+    Abc_Print( 1, "Refining with %d-frame CEX, starting in frame %d, with %d extra frames.\n", pCex->iFrame, iFrameStart, iFrameExtra );
+    // derive abstraction
+    pAbs = Gia_ManDupAbsGates( p, p->vGateClasses );
+    Gia_ManStop( pAbs );
+    pAbs = Gia_ManDupAbsGates( p, p->vGateClasses );
+    if ( Gia_ManPiNum(pAbs) != pCex->nPis )
+    {
+        Abc_Print( 1, "Gia_ManNewRefine(): The PI counts in GLA and in CEX do not match.\n" );
+        Gia_ManStop( pAbs );
+        Vec_IntFree( vCopy );
+        return -1;
+    }
+    // get the state in frame iFrameStart
+    vInit = Gia_ManGetStateAndCheckCex( pAbs, pCex, iFrameStart );
+    if ( vInit == NULL )
+    {
+        Abc_Print( 1, "Gia_ManNewRefine(): The initial counter-example is invalid.\n" );
+        Gia_ManStop( pAbs );
+        Vec_IntFree( vCopy );
+        return -1;
+    }
+    if ( fVerbose )
+        Abc_Print( 1, "Gia_ManNewRefine(): The initial counter-example is correct.\n" );
+    // get inputs
+    Gia_ManGlaCollect( p, p->vGateClasses, NULL, NULL, &vFlops, NULL );
+//    assert( Vec_IntSize(vPis) + Vec_IntSize(vPPis) == Gia_ManPiNum(pAbs) );
+    Gia_ManStop( pAbs );
+//Vec_IntPrint( vFlops );
+//Vec_IntPrint( vInit );
+    // transform the manager to have new init state
+    pNew = Gia_ManTransformFlops( p, vFlops, vInit );
+    Vec_IntFree( vFlops );
+    Vec_IntFree( vInit );
+    // verify abstraction
+    {
+        Gia_Man_t * pAbs = Gia_ManDupAbsGates( pNew, p->vGateClasses );
+        Gia_ManCheckCex( pAbs, pCex, iFrameStart );
+        Gia_ManStop( pAbs );
+    }
+    // transfer abstraction
+    assert( pNew->vGateClasses == NULL );
+    pNew->vGateClasses = Vec_IntDup( p->vGateClasses );
+    // perform abstraction for the new AIG
+    {
+        Abs_Par_t Pars, * pPars = &Pars;
+        Abs_ParSetDefaults( pPars );
+        pPars->nFramesMax = pCex->iFrame - iFrameStart + 1 + iFrameExtra;
+        pPars->fVerbose = fVerbose;
+        RetValue = Gia_ManPerformGla( pNew, pPars );
+        if ( RetValue == 0 ) // spurious SAT
+        {
+            Vec_IntFreeP( &pNew->vGateClasses );
+            pNew->vGateClasses = Vec_IntDup( vCopy );
+        }
+    }
+    // move the abstraction map
+    Vec_IntFreeP( &p->vGateClasses );
+    p->vGateClasses = pNew->vGateClasses;
+    pNew->vGateClasses = NULL;
+    // cleanup
+    Gia_ManStop( pNew );
+    Vec_IntFree( vCopy );
+    return -1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/absPth.c b/abc-build/src/proof/abs/absPth.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absPth.c
@@ -0,0 +1,205 @@
+/**CFile****************************************************************
+
+  FileName    [absPth.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Abstraction package.]
+
+  Synopsis    [Interface to pthreads.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: absPth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include "abs.h"
+#include "proof/pdr/pdr.h"
+#include "proof/ssw/ssw.h"
+
+
+#ifdef ABC_USE_PTHREADS
+
+#ifdef _WIN32
+#include "../lib/pthread.h"
+#else
+#include <pthread.h>
+#include <unistd.h>
+#endif
+
+#endif
+
+ABC_NAMESPACE_IMPL_START 
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#ifndef ABC_USE_PTHREADS
+
+void Gia_GlaProveAbsracted( Gia_Man_t * p, int fSimpProver, int fVerbose ) {}
+void Gia_GlaProveCancel( int fVerbose )                                    {}
+int  Gia_GlaProveCheck( int fVerbose )                                     { return 0; }
+
+#else // pthreads are used
+
+// information given to the thread
+typedef struct Abs_ThData_t_
+{
+    Aig_Man_t * pAig;
+    int         fVerbose;
+    int         RunId;
+} Abs_ThData_t;
+
+// mutext to control access to shared variables
+pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
+static volatile int g_nRunIds = 0;             // the number of the last prover instance
+static volatile int g_fAbstractionProved = 0;  // set to 1 when prover successed to prove
+
+// call back procedure for PDR
+int Abs_CallBackToStop( int RunId ) { assert( RunId <= g_nRunIds ); return RunId < g_nRunIds; }
+
+// test procedure to replace PDR
+int Pdr_ManSolve_test( Aig_Man_t * pAig, Pdr_Par_t * pPars, Abc_Cex_t ** ppCex )
+{
+    char * p = ABC_ALLOC( char, 111 );
+    while ( 1 )
+    {
+        if ( pPars->pFuncStop && pPars->pFuncStop(pPars->RunId) )
+            break;
+    }
+    ABC_FREE( p );
+    return -1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Create one thread]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Abs_ProverThread( void * pArg )
+{
+    Abs_ThData_t * pThData = (Abs_ThData_t *)pArg;
+    Pdr_Par_t Pars, * pPars = &Pars;
+    int RetValue, status;
+    // call PDR
+    Pdr_ManSetDefaultParams( pPars );
+    pPars->fSilent   = 1;
+    pPars->RunId     = pThData->RunId;
+    pPars->pFuncStop = Abs_CallBackToStop;
+    RetValue = Pdr_ManSolve( pThData->pAig, pPars );
+    // update the result
+    if ( RetValue == 1 )
+    {
+        status = pthread_mutex_lock(&g_mutex);  assert( status == 0 );
+        g_fAbstractionProved = 1;
+        status = pthread_mutex_unlock(&g_mutex);  assert( status == 0 );
+    }
+    // quit this thread
+    if ( pThData->fVerbose )
+    {
+        if ( RetValue == 1 )
+            Abc_Print( 1, "Proved abstraction %d.\n", pThData->RunId );
+        else if ( RetValue == 0 )
+            Abc_Print( 1, "Disproved abstraction %d.\n", pThData->RunId );
+        else if ( RetValue == -1 )
+            Abc_Print( 1, "Cancelled abstraction %d.\n", pThData->RunId );
+        else assert( 0 );
+    }
+    // free memory
+    Aig_ManStop( pThData->pAig );
+    ABC_FREE( pThData );
+    // quit this thread
+	pthread_exit( NULL );
+	assert(0);
+	return NULL;
+}
+void Gia_GlaProveAbsracted( Gia_Man_t * pGia, int fSimpProver, int fVerbose )
+{
+    extern Aig_Man_t * Dar_ManRwsat( Aig_Man_t * pAig, int fBalance, int fVerbose );
+    Abs_ThData_t * pThData;
+    Ssw_Pars_t Pars, * pPars = &Pars;
+    Aig_Man_t * pAig, * pTemp;
+    Gia_Man_t * pAbs;
+	pthread_t ProverThread;
+    int status;
+    // disable verbosity
+//    fVerbose = 0;
+    // create abstraction 
+    assert( pGia->vGateClasses != NULL );
+    pAbs = Gia_ManDupAbsGates( pGia, pGia->vGateClasses );
+    Gia_ManCleanValue( pGia );
+    pAig = Gia_ManToAigSimple( pAbs );
+    Gia_ManStop( pAbs );
+    // simplify abstraction
+    if ( fSimpProver )
+    {
+        Ssw_ManSetDefaultParams( pPars );
+        pPars->nFramesK = 4;
+        pAig = Ssw_SignalCorrespondence( pTemp = pAig, pPars );
+//printf( "\n" );
+//Aig_ManPrintStats( pTemp );
+//Aig_ManPrintStats( pAig );
+        Aig_ManStop( pTemp );
+    }
+    // synthesize abstraction
+//    pAig = Dar_ManRwsat( pTemp = pAig, 0, 0 ); 
+//    Aig_ManStop( pTemp );
+    // reset the proof 
+    status = pthread_mutex_lock(&g_mutex);  assert( status == 0 );
+    g_fAbstractionProved = 0;
+    status = pthread_mutex_unlock(&g_mutex);  assert( status == 0 );
+    // collect thread data
+    pThData = ABC_CALLOC( Abs_ThData_t, 1 );
+    pThData->pAig = pAig;
+    pThData->fVerbose = fVerbose;
+    status = pthread_mutex_lock(&g_mutex);  assert( status == 0 );
+    pThData->RunId = ++g_nRunIds;
+    status = pthread_mutex_unlock(&g_mutex);  assert( status == 0 );
+    // create thread
+    if ( fVerbose )  Abc_Print( 1, "\nTrying to prove abstraction %d.\n", pThData->RunId );
+    status = pthread_create( &ProverThread, NULL, Abs_ProverThread, pThData );
+    assert( status == 0 );
+}
+void Gia_GlaProveCancel( int fVerbose )
+{
+    int status;
+    status = pthread_mutex_lock(&g_mutex);  assert( status == 0 );
+    g_nRunIds++;
+    status = pthread_mutex_unlock(&g_mutex);  assert( status == 0 );
+}
+int Gia_GlaProveCheck( int fVerbose )
+{
+    int status;
+    if ( g_fAbstractionProved == 0 )
+        return 0;
+    status = pthread_mutex_lock(&g_mutex);  assert( status == 0 );
+    g_fAbstractionProved = 0;
+    status = pthread_mutex_unlock(&g_mutex);  assert( status == 0 );
+    return 1;
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/absRef.c b/abc-build/src/proof/abs/absRef.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absRef.c
@@ -0,0 +1,751 @@
+/**CFile****************************************************************
+
+  FileName    [absRef.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Abstraction package.]
+
+  Synopsis    [Refinement manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: absRef.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sat/bsat/satSolver2.h"
+#include "abs.h"
+#include "absRef.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/*
+    Description of the refinement manager
+
+    This refinement manager should be 
+    * started by calling Rnm_ManStart()
+       this procedure takes one argument, the user's seq miter as a GIA manager
+       - the manager should have only one property output
+       - this manager should not change while the refinement manager is alive
+       - it cannot be used by external applications for any purpose
+       - when the refinement manager stop, GIA manager is the same as at the beginning
+       - in the meantime, it will have some data-structures attached to its nodes...
+    * stopped by calling Rnm_ManStop()
+    * between starting and stopping, refinements are obtained by calling Rnm_ManRefine()
+
+    Procedure Rnm_ManRefine() takes the following arguments:
+    * the refinement manager previously started by Rnm_ManStart()
+    * counter-example (CEX) obtained by abstracting some logic of GIA
+    * mapping (vMap) of inputs of the CEX into the object IDs of the GIA manager
+       - only PI, flop outputs, and internal AND nodes can be used in vMap
+       - the ordering of objects in vMap is not important
+       - however, the index of a non-PI object in vMap is used as its priority
+         (the smaller the index, the more likely this non-PI object apears in a refinement)
+       - only the logic between PO and the objects listed in vMap is traversed by the manager
+         (as a result, GIA can be arbitrarily large, but only objects used in the abstraction
+         and the pseudo-PI, that is, objects in the cut, will be visited by the manager)
+    * flag fPropFanout defines whether value propagation is done through the fanout
+       - it this flag is enabled, theoretically refinement should be better (the result smaller)
+    * flag fVerbose may print some statistics
+
+    The refinement manager returns a minimal-size array of integer IDs of GIA objects
+    which should be added to the abstraction to possibly prevent the given counter-example
+       - only flop output and internal AND nodes from vMap may appear in the resulting array
+       - if the resulting array is empty, the CEX is a true CEX 
+         (in other words, non-PI objects are not needed to set the PO value to 1)
+
+    Verification of the selected refinement is performed by 
+       - initializing all PI objects in vMap to value 0 or 1 they have in the CEX
+       - initializing all remaining objects in vMap to value X
+       - initializing objects used in the refiment to value 0 or 1 they have in the CEX
+       - simulating through as many timeframes as required by the CEX
+       - if the PO value in the last frame is 1, the refinement is correct
+         (however, the minimality of the refinement is not currently checked)
+        
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+/*
+static inline int         Rnm_ObjSatVar( Rnm_Man_t * p, Gia_Obj_t * pObj )          { return Vec_IntEntry( p->vSatVars, Gia_ObjId(p->pGia, pObj) );                                                 }
+static inline void        Rnm_ObjSetSatVar( Rnm_Man_t * p, Gia_Obj_t * pObj, int c) { Vec_IntWriteEntry( p->vSatVars, Gia_ObjId(p->pGia, pObj), c );                                                }
+static inline int         Rnm_ObjFindOrAddSatVar( Rnm_Man_t * p, Gia_Obj_t * pObj)  { if ( Rnm_ObjSatVar(p, pObj) == 0 ) { Rnm_ObjSetSatVar(p, pObj, Vec_IntSize(p->vSat2Ids)); Vec_IntPush(p->vSat2Ids, Gia_ObjId(p->pGia, pObj)); }; return 2*Rnm_ObjSatVar(p, pObj); }
+*/
+extern void               Ga2_ManCnfAddStatic( sat_solver2 * pSat, Vec_Int_t * vCnf0, Vec_Int_t * vCnf1, int * pLits, int iLitOut, int ProofId );
+extern Vec_Int_t *        Ga2_ManCnfCompute( unsigned uTruth, int nVars, Vec_Int_t * vCover );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+#if 0 
+
+/**Function*************************************************************
+
+  Synopsis    [Performs UNSAT-core-based refinement.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rnm_ManRefineCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vVisited, Vec_Int_t * vFlops )
+{
+    Vec_Int_t * vLeaves;
+    Gia_Obj_t * pFanin;
+    int k;
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+    {
+        if ( Gia_ObjIsRo(p, pObj) )
+            Vec_IntPush( vFlops, Gia_ObjId(p, pObj) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    vLeaves = Ga2_ObjLeaves( p, pObj );
+    Gia_ManForEachObjVec( vLeaves, p, pFanin, k )
+        Rnm_ManRefineCollect_rec( p, pFanin, vVisited, vFlops );
+    Vec_IntPush( vVisited, Gia_ObjId(p, pObj) );
+}
+
+Vec_Int_t * Rnm_ManRefineUnsatCore( Rnm_Man_t * p, Vec_Int_t * vPPIs )
+{
+    Vec_Int_t * vCnf0, * vCnf1;
+    Vec_Int_t * vLeaves, * vLits, * vPpi2Map;
+    Vec_Int_t * vVisited, * vFlops, * vCore, * vCoreFinal;
+    Gia_Obj_t * pObj, * pFanin;
+    int i, k, f, Status, Entry, pLits[5], iBit = p->pCex->nRegs;
+    // map PPIs into their positions in the map  // CAN BE MADE FASTER
+    vPpi2Map = Vec_IntAlloc( Vec_IntSize(vPPIs) );
+    Vec_IntForEachEntry( vPPIs, Entry, i )
+    {
+        Entry = Vec_IntFind( p->vMap, Entry );
+        assert( Entry >= 0 );
+        Vec_IntPush( vPpi2Map, Entry );
+    }
+    // collect nodes between selected PPIs and CIs
+    vFlops = Vec_IntAlloc( 100 );
+    vVisited = Vec_IntAlloc( 100 );
+    Gia_ManIncrementTravId( p->pGia );
+    Gia_ManForEachObjVec( vPPIs, p->pGia, pObj, i )
+//        if ( !Gia_ObjIsRo(p->pGia, pObj) ) // SKIP PPIs that are flops
+            Rnm_ManRefineCollect_rec( p->pGia, pObj, vVisited, vFlops );
+    // create SAT variables and SAT solver
+    Vec_IntFill( p->vSat2Ids, 1, -1 );
+    assert( p->pSat == NULL );
+    p->pSat = sat_solver2_new();
+    Vec_IntFill( p->vSatVars, Gia_ManObjNum(p->pGia), 0 ); // NO NEED TO CLEAN EACH TIME
+    // assign PPI variables
+    Gia_ManForEachObjVec( vFlops, p->pGia, pObj, i )
+        Rnm_ObjFindOrAddSatVar( p, pObj );
+    // assign other variables
+    Gia_ManForEachObjVec( vVisited, p->pGia, pObj, i )
+    {
+        vLeaves = Ga2_ObjLeaves( p->pGia, pObj );
+        Gia_ManForEachObjVec( vLeaves, p->pGia, pFanin, k )
+            pLits[k] = Rnm_ObjFindOrAddSatVar( p, pFanin );
+        vCnf0 = Ga2_ManCnfCompute(  Ga2_ObjTruth(p->pGia, pObj), Vec_IntSize(vLeaves), p->vIsopMem );
+        vCnf1 = Ga2_ManCnfCompute( ~Ga2_ObjTruth(p->pGia, pObj), Vec_IntSize(vLeaves), p->vIsopMem );
+        Ga2_ManCnfAddStatic( p->pSat, vCnf0, vCnf1, pLits, Rnm_ObjFindOrAddSatVar(p, pObj), Rnm_ObjFindOrAddSatVar(p, pObj)/2 );
+        Vec_IntFree( vCnf0 );
+        Vec_IntFree( vCnf1 );
+    }
+
+//    printf( "\n" );
+
+    p->pSat->pPrf2 = Prf_ManAlloc();
+    Prf_ManRestart( p->pSat->pPrf2, NULL, sat_solver2_nlearnts(p->pSat), Vec_IntSize(p->vSat2Ids) );
+
+    // iterate UNSAT core computation for each timeframe
+    vLits = Vec_IntAlloc( 100 );
+    vCoreFinal = Vec_IntAlloc( 100 );
+    for ( f = 0; f <= p->pCex->iFrame; f++, iBit += p->pCex->nPis )
+    {
+        // collect values of PPIs in this timeframe
+        Vec_IntClear( vLits );
+        Gia_ManForEachObjVec( vPPIs, p->pGia, pObj, i )
+        {
+            Entry = Abc_InfoHasBit( p->pCex->pData, iBit + Vec_IntEntry(vPpi2Map, i) );
+            Vec_IntPush( vLits, Abc_LitNotCond( Rnm_ObjFindOrAddSatVar(p, pObj), !Entry ) );
+        }
+
+        // handle the first timeframe in a special vay
+        if ( f == 0 )
+            Gia_ManForEachObjVec( vFlops, p->pGia, pObj, i )
+                if ( Vec_IntFind( vPPIs, Gia_ObjId(p->pGia, pObj) ) == -1 )
+                    Vec_IntPush( vLits, Abc_LitNotCond( Rnm_ObjFindOrAddSatVar(p, pObj), 1 ) );
+/* 
+        // uniqify literals and detect special conflicts
+        Vec_IntUniqify( vLits );
+        Vec_IntForEachEntryStart( vLits, Entry, i, 1 )
+            if ( Vec_IntEntry(vLits, i-1) == Abc_LitNot(Entry) )
+                break;
+        if ( i < Vec_IntSize(vLits) )
+            printf( "triv_unsat " );
+        else
+*/
+
+        Status = sat_solver2_solve( p->pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits), (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        if ( Status != l_False )
+            continue;
+        vCore = (Vec_Int_t *)Sat_ProofCore( p->pSat );
+//        vCore = Vec_IntAlloc( 0 );
+        // add to the UNSAT core
+        Vec_IntAppend( vCoreFinal, vCore );
+
+//        printf( "Frame %d : ", f );
+//        Vec_IntPrint( vCore );
+        Vec_IntFree( vCore );
+    }
+    assert( iBit == p->pCex->nBits );
+    Vec_IntUniqify( vCoreFinal );
+    Vec_IntFree( vLits );
+    Prf_ManStopP( &p->pSat->pPrf2 );
+    sat_solver2_delete( p->pSat );
+    p->pSat = NULL;
+
+    // translate from entry into ID
+    Vec_IntForEachEntry( vCoreFinal, Entry, i )
+    {
+        assert( Vec_IntEntry(p->vSat2Ids, Entry) >= 0 );
+        assert( Vec_IntEntry(p->vSat2Ids, Entry) < Gia_ManObjNum(p->pGia) );
+        Vec_IntWriteEntry( vCoreFinal, i, Vec_IntEntry(p->vSat2Ids, Entry) );
+    }
+    // if there are flop outputs, add them
+    Gia_ManForEachObjVec( vPPIs, p->pGia, pObj, i )
+        if ( Gia_ObjIsRo(p->pGia, pObj) )
+            Vec_IntPush( vCoreFinal, Gia_ObjId(p->pGia, pObj) );
+    Vec_IntUniqify( vCoreFinal );
+
+//    printf( "\n" );
+//    Vec_IntPrint( vPPIs );
+//    Vec_IntPrint( vCoreFinal );
+
+//    printf( "\n" );
+
+    // clean SAT variable numbers
+    Gia_ManForEachObjVec( vVisited, p->pGia, pObj, i )
+    {
+        Rnm_ObjSetSatVar( p, pObj, 0 );
+        vLeaves = Ga2_ObjLeaves( p->pGia, pObj );
+        Gia_ManForEachObjVec( vLeaves, p->pGia, pFanin, k )
+            Rnm_ObjSetSatVar( p, pFanin, 0 );
+    }
+    Vec_IntFree( vFlops );
+    Vec_IntFree( vVisited );
+    Vec_IntFree( vPpi2Map );
+    return vCoreFinal;
+}
+
+#endif
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Rnm_Man_t * Rnm_ManStart( Gia_Man_t * pGia )
+{
+    Rnm_Man_t * p;
+    assert( Gia_ManPoNum(pGia) == 1 );
+    p = ABC_CALLOC( Rnm_Man_t, 1 );
+    p->pGia = pGia;
+    p->vObjs = Vec_IntAlloc( 100 );
+    p->vCounts = Vec_StrStart( Gia_ManObjNum(pGia) );
+    p->vFanins = Vec_IntAlloc( 1000 );
+//    p->vSatVars = Vec_IntAlloc( 0 );
+//    p->vSat2Ids = Vec_IntAlloc( 1000 );
+//    p->vIsopMem  = Vec_IntAlloc( 0 );
+    p->nObjsAlloc = 10000;
+    p->pObjs = ABC_ALLOC( Rnm_Obj_t, p->nObjsAlloc );
+    if ( p->pGia->vFanout == NULL )
+        Gia_ManStaticFanoutStart( p->pGia );
+    Gia_ManCleanValue(pGia);
+    Gia_ManCleanMark0(pGia);
+    Gia_ManCleanMark1(pGia);
+    return p;
+}
+void Rnm_ManStop( Rnm_Man_t * p, int fProfile )
+{
+    if ( !p ) return;
+    // print runtime statistics
+    if ( fProfile && p->nCalls )
+    {
+        double MemGia = sizeof(Gia_Man_t) + sizeof(Gia_Obj_t) * p->pGia->nObjsAlloc + sizeof(int) * p->pGia->nTravIdsAlloc;
+        double MemOther = sizeof(Rnm_Man_t) + sizeof(Rnm_Obj_t) * p->nObjsAlloc + sizeof(int) * Vec_IntCap(p->vObjs);
+        abctime timeOther = p->timeTotal - p->timeFwd - p->timeBwd - p->timeVer;
+        printf( "Abstraction refinement runtime statistics:\n" );
+        ABC_PRTP( "Sensetization", p->timeFwd,   p->timeTotal );
+        ABC_PRTP( "Justification", p->timeBwd,   p->timeTotal );
+        ABC_PRTP( "Verification ", p->timeVer,   p->timeTotal );
+        ABC_PRTP( "Other        ", timeOther,    p->timeTotal );
+        ABC_PRTP( "TOTAL        ", p->timeTotal, p->timeTotal );
+        printf( "Total calls = %d.  Average refine = %.1f. GIA mem = %.3f MB.  Other mem = %.3f MB.\n", 
+            p->nCalls, 1.0*p->nRefines/p->nCalls, MemGia/(1<<20), MemOther/(1<<20) );
+    }
+
+    Gia_ManCleanMark0(p->pGia);
+    Gia_ManCleanMark1(p->pGia);
+    Gia_ManStaticFanoutStop(p->pGia);
+//    Gia_ManSetPhase(p->pGia);
+//    Vec_IntFree( p->vIsopMem );
+//    Vec_IntFree( p->vSatVars );
+//    Vec_IntFree( p->vSat2Ids );
+    Vec_StrFree( p->vCounts );
+    Vec_IntFree( p->vFanins );
+    Vec_IntFree( p->vObjs );
+    ABC_FREE( p->pObjs );
+    ABC_FREE( p );
+}
+double Rnm_ManMemoryUsage( Rnm_Man_t * p )
+{
+    return (double)(sizeof(Rnm_Man_t) + sizeof(Rnm_Obj_t) * p->nObjsAlloc + sizeof(int) * Vec_IntCap(p->vObjs));
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collect internal objects to be used in value propagation.]
+
+  Description [Resulting array vObjs contains RO, AND, PO/RI in a topo order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rnm_ManCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vObjs, int nAddOn )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCo(pObj) )
+        Rnm_ManCollect_rec( p, Gia_ObjFanin0(pObj), vObjs, nAddOn );
+    else if ( Gia_ObjIsAnd(pObj) )
+    {
+        Rnm_ManCollect_rec( p, Gia_ObjFanin0(pObj), vObjs, nAddOn );
+        Rnm_ManCollect_rec( p, Gia_ObjFanin1(pObj), vObjs, nAddOn );
+    }
+    else if ( !Gia_ObjIsRo(p, pObj) )
+        assert( 0 );
+    pObj->Value = Vec_IntSize(vObjs) + nAddOn;
+    Vec_IntPush( vObjs, Gia_ObjId(p, pObj) );
+}
+void Rnm_ManCollect( Rnm_Man_t * p )
+{
+    Gia_Obj_t * pObj = NULL;
+    int i;
+    // mark const/PIs/PPIs
+    Gia_ManIncrementTravId( p->pGia );
+    Gia_ObjSetTravIdCurrent( p->pGia, Gia_ManConst0(p->pGia) );
+    Gia_ManConst0(p->pGia)->Value = 0;
+    Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+    {
+        assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) );
+        Gia_ObjSetTravIdCurrent( p->pGia, pObj );
+        pObj->Value = 1 + i;
+    }
+    // collect objects
+    Vec_IntClear( p->vObjs );
+    Rnm_ManCollect_rec( p->pGia, Gia_ManPo(p->pGia, 0), p->vObjs, 1 + Vec_IntSize(p->vMap) );
+    Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i )
+        if ( Gia_ObjIsRo(p->pGia, pObj) )
+            Rnm_ManCollect_rec( p->pGia, Gia_ObjRoToRi(p->pGia, pObj), p->vObjs, 1 + Vec_IntSize(p->vMap) );
+    // the last object should be a CO
+    assert( Gia_ObjIsCo(pObj) );
+    assert( (int)pObj->Value == Vec_IntSize(p->vMap) + Vec_IntSize(p->vObjs) );
+}
+void Rnm_ManCleanValues( Rnm_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+        pObj->Value = 0;
+    Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i )
+        pObj->Value = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs sensitization analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rnm_ManSensitize( Rnm_Man_t * p )
+{
+    Rnm_Obj_t * pRnm, * pRnm0, * pRnm1;
+    Gia_Obj_t * pObj;
+    int f, i, iBit = p->pCex->nRegs;
+    // const0 is initialized automatically in all timeframes
+    for ( f = 0; f <= p->pCex->iFrame; f++, iBit += p->pCex->nPis )
+    {
+        Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+        {
+            assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) );
+            pRnm = Rnm_ManObj( p, pObj, f );
+            pRnm->Value = Abc_InfoHasBit( p->pCex->pData, iBit + i );
+            if ( !Gia_ObjIsPi(p->pGia, pObj) ) // this is PPI
+            {
+                assert( pObj->Value > 0 );
+                pRnm->Prio = pObj->Value;
+                pRnm->fPPi = 1;
+            }
+        }
+        Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i )
+        {
+            assert( Gia_ObjIsRo(p->pGia, pObj) || Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) );
+            pRnm = Rnm_ManObj( p, pObj, f );
+            assert( !pRnm->fPPi );
+            if ( Gia_ObjIsRo(p->pGia, pObj) )
+            {
+                if ( f == 0 )
+                    continue;
+                pRnm0 = Rnm_ManObj( p, Gia_ObjRoToRi(p->pGia, pObj), f-1 );
+                pRnm->Value = pRnm0->Value;
+                pRnm->Prio  = pRnm0->Prio;
+                continue;
+            }
+            if ( Gia_ObjIsCo(pObj) )
+            {
+                pRnm0 = Rnm_ManObj( p, Gia_ObjFanin0(pObj), f );
+                pRnm->Value = (pRnm0->Value ^ Gia_ObjFaninC0(pObj));
+                pRnm->Prio  = pRnm0->Prio;
+                continue;
+            }
+            assert( Gia_ObjIsAnd(pObj) );
+            pRnm0 = Rnm_ManObj( p, Gia_ObjFanin0(pObj), f );
+            pRnm1 = Rnm_ManObj( p, Gia_ObjFanin1(pObj), f );
+            pRnm->Value = (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) & (pRnm1->Value ^ Gia_ObjFaninC1(pObj));
+            if ( pRnm->Value == 1 )
+                pRnm->Prio  = Abc_MaxInt( pRnm0->Prio, pRnm1->Prio );
+            else if ( (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) == 0 && (pRnm1->Value ^ Gia_ObjFaninC1(pObj)) == 0 )
+                pRnm->Prio  = Abc_MinInt( pRnm0->Prio, pRnm1->Prio ); // choice
+            else if ( (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) == 0 )
+                pRnm->Prio  = pRnm0->Prio;
+            else 
+                pRnm->Prio  = pRnm1->Prio;
+        }
+    }
+    assert( iBit == p->pCex->nBits );
+    pRnm = Rnm_ManObj( p, Gia_ManPo(p->pGia, 0), p->pCex->iFrame );
+    if ( pRnm->Value != 1 )
+        printf( "Output value is incorrect.\n" );
+    return pRnm->Prio;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Drive implications of the given node towards primary outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rnm_ManJustifyPropFanout_rec( Rnm_Man_t * p, Gia_Obj_t * pObj, int f, Vec_Int_t * vSelect )
+{
+    Rnm_Obj_t * pRnm0, * pRnm1, * pRnm = Rnm_ManObj( p, pObj, f );
+    Gia_Obj_t * pFanout = NULL;
+    int i, k;//, Id = Gia_ObjId(p->pGia, pObj);
+    assert( pRnm->fVisit == 0 );
+    pRnm->fVisit = 1;
+    if ( Rnm_ManObj( p, pObj, 0 )->fVisitJ == 0 )
+    {
+        Rnm_ManObj( p, pObj, 0 )->fVisitJ = 1;
+        p->nVisited++;
+    }
+    if ( pRnm->fPPi )
+    {
+        assert( (int)pRnm->Prio > 0 );
+        for ( i = p->pCex->iFrame; i >= 0; i-- )
+            if ( !Rnm_ManObj(p, pObj, i)->fVisit )
+                Rnm_ManJustifyPropFanout_rec( p, pObj, i, vSelect );
+        Vec_IntPush( vSelect, Gia_ObjId(p->pGia, pObj) );
+        return;
+    }
+    if ( (Gia_ObjIsCo(pObj) && f == p->pCex->iFrame) || Gia_ObjIsPo(p->pGia, pObj) )
+        return;
+    if ( Gia_ObjIsRi(p->pGia, pObj) )
+    {
+        pFanout = Gia_ObjRiToRo(p->pGia, pObj);
+        if ( !Rnm_ManObj(p, pFanout, f+1)->fVisit )
+            Rnm_ManJustifyPropFanout_rec( p, pFanout, f+1, vSelect );
+        return;
+    }
+    assert( Gia_ObjIsRo(p->pGia, pObj) || Gia_ObjIsAnd(pObj) );
+    Gia_ObjForEachFanoutStatic( p->pGia, pObj, pFanout, k )
+    {
+        Rnm_Obj_t * pRnmF;
+        if ( pFanout->Value == 0 )
+            continue;
+        pRnmF = Rnm_ManObj(p, pFanout, f);
+        if ( pRnmF->fPPi || pRnmF->fVisit )
+            continue;
+        if ( Gia_ObjIsCo(pFanout) )
+        {
+            Rnm_ManJustifyPropFanout_rec( p, pFanout, f, vSelect );
+            continue;
+        } 
+        assert( Gia_ObjIsAnd(pFanout) );
+        pRnm0 = Rnm_ManObj( p, Gia_ObjFanin0(pFanout), f );
+        pRnm1 = Rnm_ManObj( p, Gia_ObjFanin1(pFanout), f );
+        if ( ((pRnm0->Value ^ Gia_ObjFaninC0(pFanout)) == 0 && pRnm0->fVisit) ||
+             ((pRnm1->Value ^ Gia_ObjFaninC1(pFanout)) == 0 && pRnm1->fVisit) || 
+           ( ((pRnm0->Value ^ Gia_ObjFaninC0(pFanout)) == 1 && pRnm0->fVisit) && 
+             ((pRnm1->Value ^ Gia_ObjFaninC1(pFanout)) == 1 && pRnm1->fVisit) ) )
+           Rnm_ManJustifyPropFanout_rec( p, pFanout, f, vSelect );
+    }
+}
+void Rnm_ManJustify_rec( Rnm_Man_t * p, Gia_Obj_t * pObj, int f, Vec_Int_t * vSelect )
+{ 
+    Rnm_Obj_t * pRnm = Rnm_ManObj( p, pObj, f );
+    int i;//, Id = Gia_ObjId(p->pGia, pObj);
+    if ( pRnm->fVisit )
+        return;
+    if ( p->fPropFanout )
+        Rnm_ManJustifyPropFanout_rec( p, pObj, f, vSelect );
+    else
+    {
+        pRnm->fVisit = 1;
+        if ( Rnm_ManObj( p, pObj, 0 )->fVisitJ == 0 )
+        {
+            Rnm_ManObj( p, pObj, 0 )->fVisitJ = 1;
+            p->nVisited++;
+        }
+    }
+    if ( pRnm->fPPi )
+    {
+        assert( (int)pRnm->Prio > 0 );
+        if ( p->fPropFanout )
+        {
+            for ( i = p->pCex->iFrame; i >= 0; i-- )
+                if ( !Rnm_ManObj(p, pObj, i)->fVisit )
+                    Rnm_ManJustifyPropFanout_rec( p, pObj, i, vSelect );
+        }
+        else
+        {
+            Vec_IntPush( vSelect, Gia_ObjId(p->pGia, pObj) );
+//            for ( i = p->pCex->iFrame; i >= 0; i-- )
+//                Rnm_ManObj(p, pObj, i)->fVisit = 1;
+        }
+        return;
+    }
+    if ( Gia_ObjIsPi(p->pGia, pObj) || Gia_ObjIsConst0(pObj) )
+        return;
+    if ( Gia_ObjIsRo(p->pGia, pObj) )
+    {
+        if ( f > 0 )
+            Rnm_ManJustify_rec( p, Gia_ObjFanin0(Gia_ObjRoToRi(p->pGia, pObj)), f-1, vSelect );
+        return;
+    }
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        Rnm_Obj_t * pRnm0 = Rnm_ManObj( p, Gia_ObjFanin0(pObj), f );
+        Rnm_Obj_t * pRnm1 = Rnm_ManObj( p, Gia_ObjFanin1(pObj), f );
+        if ( pRnm->Value == 1 )
+        {
+            if ( pRnm0->Prio > 0 )
+                Rnm_ManJustify_rec( p, Gia_ObjFanin0(pObj), f, vSelect );
+            if ( pRnm1->Prio > 0 )
+                Rnm_ManJustify_rec( p, Gia_ObjFanin1(pObj), f, vSelect );
+        }
+        else // select one value
+        {
+            if ( (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) == 0 && (pRnm1->Value ^ Gia_ObjFaninC1(pObj)) == 0 )
+            {
+                if ( pRnm0->Prio <= pRnm1->Prio ) // choice
+                {
+                    if ( pRnm0->Prio > 0 )
+                        Rnm_ManJustify_rec( p, Gia_ObjFanin0(pObj), f, vSelect );
+                }
+                else
+                {
+                    if ( pRnm1->Prio > 0 )
+                        Rnm_ManJustify_rec( p, Gia_ObjFanin1(pObj), f, vSelect );
+                }
+            }
+            else if ( (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) == 0 )
+            {
+                if ( pRnm0->Prio > 0 )
+                    Rnm_ManJustify_rec( p, Gia_ObjFanin0(pObj), f, vSelect );
+            }
+            else if ( (pRnm1->Value ^ Gia_ObjFaninC1(pObj)) == 0 )
+            {
+                if ( pRnm1->Prio > 0 )
+                    Rnm_ManJustify_rec( p, Gia_ObjFanin1(pObj), f, vSelect );
+            }
+            else assert( 0 );
+        }
+    }
+    else assert( 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs refinement.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rnm_ManVerifyUsingTerSim( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vMap, Vec_Int_t * vObjs, Vec_Int_t * vRes )
+{
+    Gia_Obj_t * pObj;
+    int i, f, iBit = pCex->nRegs;
+    Gia_ObjTerSimSet0( Gia_ManConst0(p) );
+    for ( f = 0; f <= pCex->iFrame; f++, iBit += pCex->nPis )
+    {
+        Gia_ManForEachObjVec( vMap, p, pObj, i )
+        {
+            pObj->Value = Abc_InfoHasBit( pCex->pData, iBit + i );
+            if ( !Gia_ObjIsPi(p, pObj) )
+                Gia_ObjTerSimSetX( pObj );
+            else if ( pObj->Value )
+                Gia_ObjTerSimSet1( pObj );
+            else
+                Gia_ObjTerSimSet0( pObj );
+        }
+        Gia_ManForEachObjVec( vRes, p, pObj, i ) // vRes is subset of vMap
+        {
+            if ( pObj->Value )
+                Gia_ObjTerSimSet1( pObj );
+            else
+                Gia_ObjTerSimSet0( pObj );
+        }
+        Gia_ManForEachObjVec( vObjs, p, pObj, i )
+        {
+            if ( Gia_ObjIsCo(pObj) )
+                Gia_ObjTerSimCo( pObj );
+            else if ( Gia_ObjIsAnd(pObj) )
+                Gia_ObjTerSimAnd( pObj );
+            else if ( f == 0 )
+                Gia_ObjTerSimSet0( pObj );
+            else
+                Gia_ObjTerSimRo( p, pObj );
+        }
+    }
+    Gia_ManForEachObjVec( vMap, p, pObj, i )
+        pObj->Value = 0;
+    pObj = Gia_ManPo( p, 0 );
+    if ( !Gia_ObjTerSimGet1(pObj) )
+        Abc_Print( 1, "\nRefinement verification has failed!!!\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the refinement for a given counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Rnm_ManRefine( Rnm_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vMap, int fPropFanout, int fNewRefinement, int fVerbose )
+{
+    int fVerify = 1;
+    Vec_Int_t * vGoodPPis, * vNewPPis;
+    abctime clk, clk2 = Abc_Clock();
+    int RetValue;
+    p->nCalls++;
+//    Gia_ManCleanValue( p->pGia );
+    // initialize
+    p->pCex = pCex;
+    p->vMap = vMap;
+    p->fPropFanout = fPropFanout;
+    p->fVerbose    = fVerbose;
+    // collects used objects
+    Rnm_ManCollect( p );
+    // initialize datastructure
+    p->nObjsFrame = 1 + Vec_IntSize(vMap) + Vec_IntSize(p->vObjs);
+    p->nObjs = p->nObjsFrame * (pCex->iFrame + 1);
+    if ( p->nObjs > p->nObjsAlloc )
+        p->pObjs = ABC_REALLOC( Rnm_Obj_t, p->pObjs, (p->nObjsAlloc = p->nObjs + 10000) );
+    memset( p->pObjs, 0, sizeof(Rnm_Obj_t) * p->nObjs );
+    // propagate priorities
+    clk = Abc_Clock();
+    vGoodPPis = Vec_IntAlloc( 100 );
+    if ( Rnm_ManSensitize( p ) ) // the CEX is not a true CEX
+    {
+        p->timeFwd += Abc_Clock() - clk;
+        // select refinement
+        clk = Abc_Clock();
+        p->nVisited = 0;
+        Rnm_ManJustify_rec( p, Gia_ObjFanin0(Gia_ManPo(p->pGia, 0)), pCex->iFrame, vGoodPPis );
+        RetValue = Vec_IntUniqify( vGoodPPis );
+//        assert( RetValue == 0 );
+        p->timeBwd += Abc_Clock() - clk;
+    }
+
+    // verify (empty) refinement
+    // (only works when post-processing is not applied)
+    if ( fVerify )
+    {
+        clk = Abc_Clock();
+        Rnm_ManVerifyUsingTerSim( p->pGia, p->pCex, p->vMap, p->vObjs, vGoodPPis );
+        p->timeVer += Abc_Clock() - clk;
+    }
+
+    // at this point array vGoodPPis contains the set of important PPIs
+    if ( Vec_IntSize(vGoodPPis) > 0 ) // spurious CEX resulting in a non-trivial refinement 
+    {
+        // filter selected set
+        if ( !fNewRefinement )  // default 
+            vNewPPis = Rnm_ManFilterSelected( p, vGoodPPis );
+        else // this is enabled when &gla is called with -r (&gla -r)
+            vNewPPis = Rnm_ManFilterSelectedNew( p, vGoodPPis );
+
+        // replace the PPI array if necessary
+        if ( Vec_IntSize(vNewPPis) > 0 ) // something to select, replace current refinement 
+            Vec_IntFree( vGoodPPis ), vGoodPPis = vNewPPis;
+        else // if there is nothing to select, do not change the current refinement array
+            Vec_IntFree( vNewPPis );
+    }
+
+    // clean values
+    // we cannot do this before, because we need to remember what objects
+    // belong to the abstraction when we do Rnm_ManFilterSelected()
+    Rnm_ManCleanValues( p );
+
+//    Vec_IntReverseOrder( vGoodPPis );
+    p->timeTotal += Abc_Clock() - clk2;
+    p->nRefines += Vec_IntSize(vGoodPPis);
+    return vGoodPPis;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/absRef.h b/abc-build/src/proof/abs/absRef.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absRef.h
@@ -0,0 +1,129 @@
+/**CFile****************************************************************
+
+  FileName    [absRef.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Abstraction package.]
+
+  Synopsis    [Refinement manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: absRef.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__proof_abs__AbsRef_h
+#define ABC__proof_abs__AbsRef_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Rnm_Obj_t_ Rnm_Obj_t; // refinement object
+struct Rnm_Obj_t_
+{
+    unsigned        Value     :  1;  // binary value
+    unsigned        fVisit    :  1;  // visited object
+    unsigned        fVisitJ   :  1;  // justified visited object
+    unsigned        fPPi      :  1;  // PPI object
+    unsigned        Prio      : 24;  // priority (0 - highest)
+};
+
+typedef struct Rnm_Man_t_ Rnm_Man_t; // refinement manager
+struct Rnm_Man_t_
+{
+    // user data
+    Gia_Man_t *     pGia;            // working AIG manager (it is completely owned by this package)
+    Abc_Cex_t *     pCex;            // counter-example
+    Vec_Int_t *     vMap;            // mapping of CEX inputs into objects (PI + PPI, in any order)
+    int             fPropFanout;     // propagate fanouts
+    int             fVerbose;        // verbose flag
+    int             nRefId;          // refinement ID
+    // traversing data
+    Vec_Int_t *     vObjs;           // internal objects used in value propagation
+    // filtering of selected objects
+    Vec_Str_t *     vCounts;         // fanin counters
+    Vec_Int_t *     vFanins;         // fanins
+/*
+    // SAT solver
+    sat_solver2 *   pSat;            // incremental SAT solver
+    Vec_Int_t *     vSatVars;        // SAT variables
+    Vec_Int_t *     vSat2Ids;        // mapping of SAT variables into object IDs
+    Vec_Int_t *     vIsopMem;        // memory for ISOP computation
+*/
+    // internal data
+    Rnm_Obj_t *     pObjs;           // refinement objects
+    int             nObjs;           // the number of used objects
+    int             nObjsAlloc;      // the number of allocated objects
+    int             nObjsFrame;      // the number of used objects in each frame
+    int             nCalls;          // total number of calls
+    int             nRefines;        // total refined objects
+    int             nVisited;        // visited during justification
+    // statistics  
+    abctime         timeFwd;         // forward propagation
+    abctime         timeBwd;         // backward propagation
+    abctime         timeVer;         // ternary simulation
+    abctime         timeTotal;       // other time
+};
+
+// accessing the refinement object
+static inline Rnm_Obj_t * Rnm_ManObj( Rnm_Man_t * p, Gia_Obj_t * pObj, int f )  
+{ 
+    assert( Gia_ObjIsConst0(pObj) || pObj->Value );
+    assert( (int)pObj->Value < p->nObjsFrame );
+    assert( f >= 0 && f <= p->pCex->iFrame ); 
+    return p->pObjs + f * p->nObjsFrame + pObj->Value;  
+}
+static inline void  Rnm_ManSetRefId( Rnm_Man_t * p, int RefId )               { p->nRefId = RefId; }
+
+static inline int   Rnm_ObjCount( Rnm_Man_t * p, Gia_Obj_t * pObj )           { return Vec_StrEntry( p->vCounts, Gia_ObjId(p->pGia, pObj) );                           }
+static inline void  Rnm_ObjSetCount( Rnm_Man_t * p, Gia_Obj_t * pObj, int c ) { Vec_StrWriteEntry( p->vCounts, Gia_ObjId(p->pGia, pObj), (char)c );                    }
+static inline int   Rnm_ObjAddToCount( Rnm_Man_t * p, Gia_Obj_t * pObj )      { int c = Rnm_ObjCount(p, pObj); if ( c < 16 )  Rnm_ObjSetCount(p, pObj, c+1); return c; }
+
+static inline int   Rnm_ObjIsJust( Rnm_Man_t * p, Gia_Obj_t * pObj )          { return Gia_ObjIsConst0(pObj) || (pObj->Value && Rnm_ManObj(p, pObj, 0)->fVisitJ);      }
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== absRef.c ===========================================================*/
+extern Rnm_Man_t *  Rnm_ManStart( Gia_Man_t * pGia );
+extern void         Rnm_ManStop( Rnm_Man_t * p, int fProfile );
+extern double       Rnm_ManMemoryUsage( Rnm_Man_t * p );
+extern Vec_Int_t *  Rnm_ManRefine( Rnm_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vMap, int fPropFanout, int fNewRefinement, int fVerbose );
+/*=== absRefSelected.c ===========================================================*/
+extern Vec_Int_t *  Rnm_ManFilterSelected( Rnm_Man_t * p, Vec_Int_t * vOldPPis );
+extern Vec_Int_t *  Rnm_ManFilterSelectedNew( Rnm_Man_t * p, Vec_Int_t * vOldPPis );
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/abs/absRefJ.c b/abc-build/src/proof/abs/absRefJ.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absRefJ.c
@@ -0,0 +1,916 @@
+/**CFile****************************************************************
+
+  FileName    [absRef2.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Abstraction package.]
+
+  Synopsis    [Refinement manager to compute all justifying subsets.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: absRef2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abs.h"
+#include "absRef2.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/*
+    Description of the refinement manager
+
+    This refinement manager should be 
+    * started by calling Rf2_ManStart()
+       this procedure takes one argument, the user's seq miter as a GIA manager
+       - the manager should have only one property output
+       - this manager should not change while the refinement manager is alive
+       - it cannot be used by external applications for any purpose
+       - when the refinement manager stop, GIA manager is the same as at the beginning
+       - in the meantime, it will have some data-structures attached to its nodes...
+    * stopped by calling Rf2_ManStop()
+    * between starting and stopping, refinements are obtained by calling Rf2_ManRefine()
+
+    Procedure Rf2_ManRefine() takes the following arguments:
+    * the refinement manager previously started by Rf2_ManStart()
+    * counter-example (CEX) obtained by abstracting some logic of GIA
+    * mapping (vMap) of inputs of the CEX into the object IDs of the GIA manager
+       - only PI, flop outputs, and internal AND nodes can be used in vMap
+       - the ordering of objects in vMap is not important
+       - however, the index of a non-PI object in vMap is used as its priority
+         (the smaller the index, the more likely this non-PI object apears in a refinement)
+       - only the logic between PO and the objects listed in vMap is traversed by the manager
+         (as a result, GIA can be arbitrarily large, but only objects used in the abstraction
+         and the pseudo-PI, that is, objects in the cut, will be visited by the manager)
+    * flag fPropFanout defines whether value propagation is done through the fanout
+       - it this flag is enabled, theoretically refinement should be better (the result smaller)
+    * flag fVerbose may print some statistics
+
+    The refinement manager returns a minimal-size array of integer IDs of GIA objects
+    which should be added to the abstraction to possibly prevent the given counter-example
+       - only flop output and internal AND nodes from vMap may appear in the resulting array
+       - if the resulting array is empty, the CEX is a true CEX 
+         (in other words, non-PI objects are not needed to set the PO value to 1)
+
+    Verification of the selected refinement is performed by 
+       - initializing all PI objects in vMap to value 0 or 1 they have in the CEX
+       - initializing all remaining objects in vMap to value X
+       - initializing objects used in the refiment to value 0 or 1 they have in the CEX
+       - simulating through as many timeframes as required by the CEX
+       - if the PO value in the last frame is 1, the refinement is correct
+         (however, the minimality of the refinement is not currently checked)
+        
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Rf2_Obj_t_ Rf2_Obj_t; // refinement object
+struct Rf2_Obj_t_
+{
+    unsigned       Value     :  1;  // binary value
+    unsigned       fVisit    :  1;  // visited object
+    unsigned       fPPi      :  1;  // PPI object
+    unsigned       Prio      : 24;  // priority (0 - highest)
+};
+
+struct Rf2_Man_t_
+{
+    // user data
+    Gia_Man_t *    pGia;            // working AIG manager (it is completely owned by this package)
+    Abc_Cex_t *    pCex;            // counter-example
+    Vec_Int_t *    vMap;            // mapping of CEX inputs into objects (PI + PPI, in any order)
+    int            fPropFanout;     // propagate fanouts
+    int            fVerbose;        // verbose flag
+    // traversing data
+    Vec_Int_t *    vObjs;           // internal objects used in value propagation
+    Vec_Int_t *    vFanins;         // fanins of the PPI nodes
+    Vec_Int_t *    pvVecs;          // vectors of integers for each object
+    Vec_Vec_t *    vGrp2Ppi;        // for each node, the set of PPIs to include
+    int            nMapWords;
+    // internal data
+    Rf2_Obj_t *    pObjs;           // refinement objects
+    int            nObjs;           // the number of used objects
+    int            nObjsAlloc;      // the number of allocated objects
+    int            nObjsFrame;      // the number of used objects in each frame
+    int            nCalls;          // total number of calls
+    int            nRefines;        // total refined objects
+    // statistics  
+    clock_t        timeFwd;         // forward propagation
+    clock_t        timeBwd;         // backward propagation
+    clock_t        timeVer;         // ternary simulation
+    clock_t        timeTotal;       // other time
+};
+
+// accessing the refinement object
+static inline Rf2_Obj_t * Rf2_ManObj( Rf2_Man_t * p, Gia_Obj_t * pObj, int f )  
+{ 
+    assert( Gia_ObjIsConst0(pObj) || pObj->Value );
+    assert( (int)pObj->Value < p->nObjsFrame );
+    assert( f >= 0 && f <= p->pCex->iFrame ); 
+    return p->pObjs + f * p->nObjsFrame + pObj->Value;  
+}
+
+static inline Vec_Int_t * Rf2_ObjVec( Rf2_Man_t * p, Gia_Obj_t * pObj )  
+{
+    return p->pvVecs + Gia_ObjId(p->pGia, pObj);
+}
+
+
+static inline unsigned * Rf2_ObjA( Rf2_Man_t * p, Gia_Obj_t * pObj )  
+{
+    return (unsigned *)Vec_IntArray(Rf2_ObjVec(p, pObj));
+}
+static inline unsigned * Rf2_ObjN( Rf2_Man_t * p, Gia_Obj_t * pObj )  
+{
+    return (unsigned *)Vec_IntArray(Rf2_ObjVec(p, pObj)) + p->nMapWords;
+}
+static inline void Rf2_ObjClear( Rf2_Man_t * p, Gia_Obj_t * pObj )  
+{
+    Vec_IntFill( Rf2_ObjVec(p, pObj), 2*p->nMapWords, 0 );
+}
+static inline void Rf2_ObjStart( Rf2_Man_t * p, Gia_Obj_t * pObj, int i )  
+{
+    Vec_Int_t * vVec = Rf2_ObjVec(p, pObj);
+    int w;
+    Vec_IntClear( vVec );
+    for ( w = 0; w < p->nMapWords; w++ )
+        Vec_IntPush( vVec, 0 );
+    for ( w = 0; w < p->nMapWords; w++ )
+        Vec_IntPush( vVec, ~0 );
+    Abc_InfoSetBit( Rf2_ObjA(p, pObj), i );
+    Abc_InfoXorBit( Rf2_ObjN(p, pObj), i );
+}
+static inline void Rf2_ObjCopy( Rf2_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanin )  
+{
+    assert( Vec_IntSize(Rf2_ObjVec(p, pObj)) == 2*p->nMapWords );
+    memcpy( Rf2_ObjA(p, pObj), Rf2_ObjA(p, pFanin), sizeof(unsigned) * 2 * p->nMapWords );
+}
+static inline void Rf2_ObjDeriveAnd( Rf2_Man_t * p, Gia_Obj_t * pObj, int One )  
+{
+    unsigned * pInfo, * pInfo0, * pInfo1;
+    int i;
+    assert( Gia_ObjIsAnd(pObj) );
+    assert( One == (int)pObj->fMark0 );
+    assert( One == (int)(Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) );
+    assert( One == (int)(Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)) );
+    assert( Vec_IntSize(Rf2_ObjVec(p, pObj)) == 2*p->nMapWords );
+
+    pInfo  = Rf2_ObjA( p, pObj );
+    pInfo0 = Rf2_ObjA( p, Gia_ObjFanin0(pObj) );
+    pInfo1 = Rf2_ObjA( p, Gia_ObjFanin1(pObj) );
+    for ( i = 0; i < p->nMapWords; i++ )
+        pInfo[i] = One ? (pInfo0[i] & pInfo1[i]) : (pInfo0[i] | pInfo1[i]);
+
+    pInfo  = Rf2_ObjN( p, pObj );
+    pInfo0 = Rf2_ObjN( p, Gia_ObjFanin0(pObj) );
+    pInfo1 = Rf2_ObjN( p, Gia_ObjFanin1(pObj) );
+    for ( i = 0; i < p->nMapWords; i++ )
+        pInfo[i] = One ? (pInfo0[i] | pInfo1[i]) : (pInfo0[i] & pInfo1[i]);
+}
+static inline void Rf2_ObjPrint( Rf2_Man_t * p, Gia_Obj_t * pRoot )  
+{
+    Gia_Obj_t * pObj;
+    unsigned * pInfo;
+    int i;
+    pInfo  = Rf2_ObjA( p, pRoot );
+    Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+        if ( !Gia_ObjIsPi(p->pGia, pObj) )
+            printf( "%d", Abc_InfoHasBit(pInfo, i) );
+    printf( "\n" );
+    pInfo  = Rf2_ObjN( p, pRoot );
+    Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+        if ( !Gia_ObjIsPi(p->pGia, pObj) )
+            printf( "%d", !Abc_InfoHasBit(pInfo, i) );
+    printf( "\n" );
+
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    [Creates a new manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Rf2_Man_t * Rf2_ManStart( Gia_Man_t * pGia )
+{
+    Rf2_Man_t * p;
+    assert( Gia_ManPoNum(pGia) == 1 );
+    p = ABC_CALLOC( Rf2_Man_t, 1 );
+    p->pGia = pGia;
+    p->vObjs = Vec_IntAlloc( 1000 );
+    p->vFanins = Vec_IntAlloc( 1000 );
+    p->pvVecs = ABC_CALLOC( Vec_Int_t, Gia_ManObjNum(pGia) );
+    p->vGrp2Ppi = Vec_VecStart( 100 );
+    Gia_ManCleanMark0(pGia);
+    Gia_ManCleanMark1(pGia);
+    return p;
+}
+void Rf2_ManStop( Rf2_Man_t * p, int fProfile )
+{
+    if ( !p ) return;
+    // print runtime statistics
+    if ( fProfile && p->nCalls )
+    {
+        double MemGia = sizeof(Gia_Man_t) + sizeof(Gia_Obj_t) * p->pGia->nObjsAlloc + sizeof(int) * p->pGia->nTravIdsAlloc;
+        double MemOther = sizeof(Rf2_Man_t) + sizeof(Rf2_Obj_t) * p->nObjsAlloc + sizeof(int) * Vec_IntCap(p->vObjs);
+        clock_t timeOther = p->timeTotal - p->timeFwd - p->timeBwd - p->timeVer;
+        printf( "Abstraction refinement runtime statistics:\n" );
+        ABC_PRTP( "Sensetization", p->timeFwd,   p->timeTotal );
+        ABC_PRTP( "Justification", p->timeBwd,   p->timeTotal );
+        ABC_PRTP( "Verification ", p->timeVer,   p->timeTotal );
+        ABC_PRTP( "Other        ", timeOther,    p->timeTotal );
+        ABC_PRTP( "TOTAL        ", p->timeTotal, p->timeTotal );
+        printf( "Total calls = %d.  Average refine = %.1f. GIA mem = %.3f MB.  Other mem = %.3f MB.\n", 
+            p->nCalls, 1.0*p->nRefines/p->nCalls, MemGia/(1<<20), MemOther/(1<<20) );
+    }
+    Vec_IntFree( p->vObjs );
+    Vec_IntFree( p->vFanins );
+    Vec_VecFree( p->vGrp2Ppi );
+    ABC_FREE( p->pvVecs );
+    ABC_FREE( p );
+}
+double Rf2_ManMemoryUsage( Rf2_Man_t * p )
+{
+    return (double)(sizeof(Rf2_Man_t) + sizeof(Vec_Int_t) * Gia_ManObjNum(p->pGia));
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collect internal objects to be used in value propagation.]
+
+  Description [Resulting array vObjs contains RO, AND, PO/RI in a topo order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rf2_ManCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vObjs )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCo(pObj) )
+        Rf2_ManCollect_rec( p, Gia_ObjFanin0(pObj), vObjs );
+    else if ( Gia_ObjIsAnd(pObj) )
+    {
+        Rf2_ManCollect_rec( p, Gia_ObjFanin0(pObj), vObjs );
+        Rf2_ManCollect_rec( p, Gia_ObjFanin1(pObj), vObjs );
+    }
+    else if ( !Gia_ObjIsRo(p, pObj) )
+        assert( 0 );
+    Vec_IntPush( vObjs, Gia_ObjId(p, pObj) );
+}
+void Rf2_ManCollect( Rf2_Man_t * p )
+{
+    Gia_Obj_t * pObj = NULL;
+    int i;
+    // mark const/PIs/PPIs
+    Gia_ManIncrementTravId( p->pGia );
+    Gia_ObjSetTravIdCurrent( p->pGia, Gia_ManConst0(p->pGia) );
+    Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+    {
+        assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) );
+        Gia_ObjSetTravIdCurrent( p->pGia, pObj );
+    }
+    // collect objects
+    Vec_IntClear( p->vObjs );
+    Rf2_ManCollect_rec( p->pGia, Gia_ManPo(p->pGia, 0), p->vObjs );
+    Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i )
+        if ( Gia_ObjIsRo(p->pGia, pObj) )
+            Rf2_ManCollect_rec( p->pGia, Gia_ObjRoToRi(p->pGia, pObj), p->vObjs );
+    // the last object should be a CO
+    assert( Gia_ObjIsCo(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs sensitization analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rf2_ManSensitize( Rf2_Man_t * p )
+{
+    Rf2_Obj_t * pRnm, * pRnm0, * pRnm1;
+    Gia_Obj_t * pObj;
+    int f, i, iBit = p->pCex->nRegs;
+    // const0 is initialized automatically in all timeframes
+    for ( f = 0; f <= p->pCex->iFrame; f++, iBit += p->pCex->nPis )
+    {
+        Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+        {
+            assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) );
+            pRnm = Rf2_ManObj( p, pObj, f );
+            pRnm->Value = Abc_InfoHasBit( p->pCex->pData, iBit + i );
+            if ( !Gia_ObjIsPi(p->pGia, pObj) ) // this is PPI
+            {
+                assert( pObj->Value > 0 );
+                pRnm->Prio = pObj->Value;
+                pRnm->fPPi = 1;
+            }
+        }
+        Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i )
+        {
+            assert( Gia_ObjIsRo(p->pGia, pObj) || Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) );
+            pRnm = Rf2_ManObj( p, pObj, f );
+            assert( !pRnm->fPPi );
+            if ( Gia_ObjIsRo(p->pGia, pObj) )
+            {
+                if ( f == 0 )
+                    continue;
+                pRnm0 = Rf2_ManObj( p, Gia_ObjRoToRi(p->pGia, pObj), f-1 );
+                pRnm->Value = pRnm0->Value;
+                pRnm->Prio  = pRnm0->Prio;
+                continue;
+            }
+            if ( Gia_ObjIsCo(pObj) )
+            {
+                pRnm0 = Rf2_ManObj( p, Gia_ObjFanin0(pObj), f );
+                pRnm->Value = (pRnm0->Value ^ Gia_ObjFaninC0(pObj));
+                pRnm->Prio  = pRnm0->Prio;
+                continue;
+            }
+            assert( Gia_ObjIsAnd(pObj) );
+            pRnm0 = Rf2_ManObj( p, Gia_ObjFanin0(pObj), f );
+            pRnm1 = Rf2_ManObj( p, Gia_ObjFanin1(pObj), f );
+            pRnm->Value = (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) & (pRnm1->Value ^ Gia_ObjFaninC1(pObj));
+            if ( pRnm->Value == 1 )
+                pRnm->Prio  = Abc_MaxInt( pRnm0->Prio, pRnm1->Prio );
+            else if ( (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) == 0 && (pRnm1->Value ^ Gia_ObjFaninC1(pObj)) == 0 )
+                pRnm->Prio  = Abc_MinInt( pRnm0->Prio, pRnm1->Prio ); // choice
+            else if ( (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) == 0 )
+                pRnm->Prio  = pRnm0->Prio;
+            else 
+                pRnm->Prio  = pRnm1->Prio;
+        }
+    }
+    assert( iBit == p->pCex->nBits );
+    pRnm = Rf2_ManObj( p, Gia_ManPo(p->pGia, 0), p->pCex->iFrame );
+    if ( pRnm->Value != 1 )
+        printf( "Output value is incorrect.\n" );
+    return pRnm->Prio;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs refinement.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rf2_ManVerifyUsingTerSim( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vMap, Vec_Int_t * vObjs, Vec_Int_t * vRes )
+{
+    Gia_Obj_t * pObj;
+    int i, f, iBit = pCex->nRegs;
+    Gia_ObjTerSimSet0( Gia_ManConst0(p) );
+    for ( f = 0; f <= pCex->iFrame; f++, iBit += pCex->nPis )
+    {
+        Gia_ManForEachObjVec( vMap, p, pObj, i )
+        {
+            pObj->Value = Abc_InfoHasBit( pCex->pData, iBit + i );
+            if ( !Gia_ObjIsPi(p, pObj) )
+                Gia_ObjTerSimSetX( pObj );
+            else if ( pObj->Value )
+                Gia_ObjTerSimSet1( pObj );
+            else
+                Gia_ObjTerSimSet0( pObj );
+        }
+        Gia_ManForEachObjVec( vRes, p, pObj, i ) // vRes is subset of vMap
+        {
+            if ( pObj->Value )
+                Gia_ObjTerSimSet1( pObj );
+            else
+                Gia_ObjTerSimSet0( pObj );
+        }
+        Gia_ManForEachObjVec( vObjs, p, pObj, i )
+        {
+            if ( Gia_ObjIsCo(pObj) )
+                Gia_ObjTerSimCo( pObj );
+            else if ( Gia_ObjIsAnd(pObj) )
+                Gia_ObjTerSimAnd( pObj );
+            else if ( f == 0 )
+                Gia_ObjTerSimSet0( pObj );
+            else
+                Gia_ObjTerSimRo( p, pObj );
+        }
+    }
+    Gia_ManForEachObjVec( vMap, p, pObj, i )
+        pObj->Value = 0;
+    pObj = Gia_ManPo( p, 0 );
+    if ( !Gia_ObjTerSimGet1(pObj) )
+        Abc_Print( 1, "\nRefinement verification has failed!!!\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the refinement for a given counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rf2_ManGatherFanins_rec( Rf2_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vFanins, int Depth, int RootId, int fFirst )
+{
+    if ( Gia_ObjIsTravIdCurrent(p->pGia, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p->pGia, pObj);
+    if ( pObj->fPhase && !fFirst )
+    {
+        Vec_Int_t * vVec = Rf2_ObjVec( p, pObj );
+//        if ( Vec_IntEntry( vVec, 0 ) == 0 )
+//            return;
+        if ( Vec_IntSize(vVec) == 0 )
+            Vec_IntPush( vFanins, Gia_ObjId(p->pGia, pObj) );
+        Vec_IntPushUnique( vVec, RootId );
+        if ( Depth == 0 )
+            return;
+    }
+    if ( Gia_ObjIsPi(p->pGia, pObj) || Gia_ObjIsConst0(pObj) )
+        return;
+    if ( Gia_ObjIsRo(p->pGia, pObj) )
+    {
+        assert( pObj->fPhase );
+        pObj = Gia_ObjRoToRi(p->pGia, pObj);
+        Rf2_ManGatherFanins_rec( p, Gia_ObjFanin0(pObj), vFanins, Depth - 1, RootId, 0 );
+    }
+    else if ( Gia_ObjIsAnd(pObj) )
+    {
+        Rf2_ManGatherFanins_rec( p, Gia_ObjFanin0(pObj), vFanins, Depth - pObj->fPhase, RootId, 0 );
+        Rf2_ManGatherFanins_rec( p, Gia_ObjFanin1(pObj), vFanins, Depth - pObj->fPhase, RootId, 0 );
+    }
+    else assert( 0 );
+}
+void Rf2_ManGatherFanins( Rf2_Man_t * p, int Depth )
+{
+    Vec_Int_t * vUsed;
+    Vec_Int_t * vVec;
+    Gia_Obj_t * pObj;
+    int i, k, Entry;
+    // mark PPIs
+    Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+    {
+        vVec = Rf2_ObjVec( p, pObj );
+        assert( Vec_IntSize(vVec) == 0 );
+        Vec_IntPush( vVec, 0 );
+    }
+    // collect internal
+    Vec_IntClear( p->vFanins );
+    Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+    {
+        if ( Gia_ObjIsPi(p->pGia, pObj) )
+            continue;
+        Gia_ManIncrementTravId( p->pGia );
+        Rf2_ManGatherFanins_rec( p, pObj, p->vFanins, Depth, i, 1 );
+    }
+
+    vUsed = Vec_IntStart( Vec_IntSize(p->vMap) );
+
+    // evaluate collected
+    printf( "\nMap (%d): ", Vec_IntSize(p->vMap) );
+    Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+    {
+        vVec = Rf2_ObjVec( p, pObj );
+        if ( Vec_IntSize(vVec) > 1 )
+            printf( "%d=%d ", i, Vec_IntSize(vVec) - 1 );
+        Vec_IntForEachEntryStart( vVec, Entry, k, 1 )
+            Vec_IntAddToEntry( vUsed, Entry, 1 );
+        Vec_IntClear( vVec );
+    }
+    printf( "\n" );
+    // evaluate internal
+    printf( "Int (%d): ", Vec_IntSize(p->vFanins) );
+    Gia_ManForEachObjVec( p->vFanins, p->pGia, pObj, i )
+    {
+        vVec = Rf2_ObjVec( p, pObj );
+        if ( Vec_IntSize(vVec) > 1 )
+            printf( "%d=%d ", i, Vec_IntSize(vVec) );
+        if ( Vec_IntSize(vVec) > 1 )
+            Vec_IntForEachEntry( vVec, Entry, k )
+                Vec_IntAddToEntry( vUsed, Entry, 1 );
+        Vec_IntClear( vVec );
+    }
+    printf( "\n" );
+    // evaluate PPIs    
+    Vec_IntForEachEntry( vUsed, Entry, k )
+        printf( "%d ", Entry );
+    printf( "\n" );
+
+    Vec_IntFree( vUsed );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sort, make dup- and containment-free, and filter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Rf2_ManCountPpis( Rf2_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, Counter = 0;
+    Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+        if ( !Gia_ObjIsPi(p->pGia, pObj) ) // this is PPI
+            Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sort, make dup- and containment-free, and filter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Rf2_ManPrintVector( Vec_Int_t * p, int Num )
+{
+    int i, k, Entry;
+    Vec_IntForEachEntry( p, Entry, i )
+    {
+        for ( k = 0; k < Num; k++ )
+            printf( "%c", '0' + ((Entry>>k) & 1) );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sort, make dup- and containment-free, and filter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Rf2_ManProcessVector( Vec_Int_t * p, int Limit )
+{
+//    int Start = Vec_IntSize(p);
+    int Start = 0;
+    int i, j, k, Entry, Entry2;
+//    printf( "%d", Vec_IntSize(p) );
+    if ( Start > 5 )
+    {
+        printf( "Before: \n" );
+        Rf2_ManPrintVector( p, 31 );
+    }
+
+    k = 0;
+    Vec_IntForEachEntry( p, Entry, i )
+        if ( Gia_WordCountOnes((unsigned)Entry) <= Limit )
+            Vec_IntWriteEntry( p, k++, Entry );
+    Vec_IntShrink( p, k );            
+    Vec_IntSort( p, 0 );
+    k = 0;
+    Vec_IntForEachEntry( p, Entry, i )
+    {
+        Vec_IntForEachEntryStop( p, Entry2, j, i )
+            if ( (Entry2 & Entry) == Entry2 ) // Entry2 is a subset of Entry
+                break; 
+        if ( j == i ) // Entry is not contained in any Entry2
+            Vec_IntWriteEntry( p, k++, Entry );
+    }
+    Vec_IntShrink( p, k );            
+//    printf( "->%d ", Vec_IntSize(p) );
+    if ( Start > 5 )
+    {
+        printf( "After: \n" );
+        Rf2_ManPrintVector( p, 31 );
+        k = 0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns a unique justifification ID for each PPI.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Rf2_ManAssignJustIds( Rf2_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int nPpis = Rf2_ManCountPpis( p );
+    int nGroupSize = (nPpis / 30) + (nPpis % 30 > 0);
+    int i, k = 0;
+    Vec_VecClear( p->vGrp2Ppi );
+    Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+        if ( !Gia_ObjIsPi(p->pGia, pObj) ) // this is PPI
+            Vec_VecPushInt( p->vGrp2Ppi, (k++ / nGroupSize), i );
+    printf( "Considering %d PPIs combined into %d groups of size %d.\n", k, (k-1)/nGroupSize+1, nGroupSize );
+    return (k-1)/nGroupSize+1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sort, make dup- and containment-free, and filter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Rf2_ManPrintVectorSpecial( Rf2_Man_t * p, Vec_Int_t * vVec )
+{
+    Gia_Obj_t * pObj;
+    int nPpis = Rf2_ManCountPpis( p );
+    int nGroupSize = (nPpis / 30) + (nPpis % 30 > 0);
+    int s, i, k, Entry, Counter;
+
+    Vec_IntForEachEntry( vVec, Entry, s )
+    {
+        k = 0;
+        Counter = 0;
+        Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+        {
+            if ( !Gia_ObjIsPi(p->pGia, pObj) ) // this is PPI
+            {
+                if ( (Entry >> (k++ / nGroupSize)) & 1 )
+                    printf( "1" ), Counter++;
+                else
+                    printf( "0" );
+            }
+            else
+                printf( "-" );
+        }
+        printf( " %3d \n", Counter );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs justification propagation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Rf2_ManPropagate( Rf2_Man_t * p, int Limit )
+{
+    Vec_Int_t * vVec, * vVec0, * vVec1;
+    Gia_Obj_t * pObj;
+    int f, i, k, j, Entry, Entry2, iBit = p->pCex->nRegs;
+    // init constant
+    pObj = Gia_ManConst0(p->pGia);
+    pObj->fMark0 = 0;
+    Vec_IntFill( Rf2_ObjVec(p, pObj), 1, 0 );
+    // iterate through the timeframes
+    for ( f = 0; f <= p->pCex->iFrame; f++, iBit += p->pCex->nPis )
+    {
+        // initialize frontier values and init justification sets
+        Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+        {
+            assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) );
+            pObj->fMark0 = Abc_InfoHasBit( p->pCex->pData, iBit + i );
+            Vec_IntFill( Rf2_ObjVec(p, pObj), 1, 0 );
+        }
+        // assign justification sets for PPis
+        Vec_VecForEachLevelInt( p->vGrp2Ppi, vVec, i )
+            Vec_IntForEachEntry( vVec, Entry, k )
+            {
+                assert( i < 31 );
+                pObj = Gia_ManObj( p->pGia, Vec_IntEntry(p->vMap, Entry) );
+                assert( Vec_IntSize(Rf2_ObjVec(p, pObj)) == 1 );
+                Vec_IntAddToEntry( Rf2_ObjVec(p, pObj), 0, (1 << i) );
+            }
+        // propagate internal nodes
+        Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i )
+        {
+            pObj->fMark0 = 0;
+            vVec = Rf2_ObjVec(p, pObj);
+            Vec_IntClear( vVec );
+            if ( Gia_ObjIsRo(p->pGia, pObj) )
+            {
+                if ( f == 0 )
+                {
+                    Vec_IntPush( vVec, 0 );
+                    continue;
+                }
+                pObj->fMark0 = Gia_ObjRoToRi(p->pGia, pObj)->fMark0;
+                vVec0 = Rf2_ObjVec( p, Gia_ObjRoToRi(p->pGia, pObj) );
+                Vec_IntAppend( vVec, vVec0 );
+                continue;
+            }
+            if ( Gia_ObjIsCo(pObj) )
+            {
+                pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj));
+                vVec0 = Rf2_ObjVec( p, Gia_ObjFanin0(pObj) );
+                Vec_IntAppend( vVec, vVec0 );
+                continue;
+            }
+            assert( Gia_ObjIsAnd(pObj) );
+            vVec0 = Rf2_ObjVec(p, Gia_ObjFanin0(pObj));
+            vVec1 = Rf2_ObjVec(p, Gia_ObjFanin1(pObj));
+            pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+            if ( pObj->fMark0 == 1 )
+            {
+                Vec_IntForEachEntry( vVec0, Entry, k )
+                    Vec_IntForEachEntry( vVec1, Entry2, j )
+                        Vec_IntPush( vVec, Entry | Entry2 );
+                Rf2_ManProcessVector( vVec, Limit );
+            }
+            else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 && (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)) == 0 )
+            {
+                Vec_IntAppend( vVec, vVec0 );
+                Vec_IntAppend( vVec, vVec1 );
+                Rf2_ManProcessVector( vVec, Limit );
+            }
+            else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 )
+                Vec_IntAppend( vVec, vVec0 );
+            else 
+                Vec_IntAppend( vVec, vVec1 );
+        }
+    }
+    assert( iBit == p->pCex->nBits );
+    if ( Gia_ManPo(p->pGia, 0)->fMark0 != 1 )
+        printf( "Output value is incorrect.\n" );
+    return Rf2_ObjVec(p, Gia_ManPo(p->pGia, 0));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs justification propagation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rf2_ManBounds( Rf2_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int f, i, iBit = p->pCex->nRegs;
+    // init constant
+    pObj = Gia_ManConst0(p->pGia);
+    pObj->fMark0 = 0;
+    Rf2_ObjStart( p, pObj, Vec_IntSize(p->vMap) + Vec_IntSize(p->vObjs) );
+    // iterate through the timeframes
+    for ( f = 0; f <= p->pCex->iFrame; f++, iBit += p->pCex->nPis )
+    {
+        // initialize frontier values and init justification sets
+        Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+        {
+            assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) );
+            pObj->fMark0 = Abc_InfoHasBit( p->pCex->pData, iBit + i );
+            Rf2_ObjStart( p, pObj, i );
+        }
+        // propagate internal nodes
+        Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i )
+        {
+            pObj->fMark0 = 0;
+            Rf2_ObjClear( p, pObj );
+            if ( Gia_ObjIsRo(p->pGia, pObj) )
+            {
+                if ( f == 0 )
+                {
+                    Rf2_ObjStart( p, pObj, Vec_IntSize(p->vMap) + i );
+                    continue;
+                }
+                pObj->fMark0 = Gia_ObjRoToRi(p->pGia, pObj)->fMark0;
+                Rf2_ObjCopy( p, pObj, Gia_ObjRoToRi(p->pGia, pObj) );
+                continue;
+            }
+            if ( Gia_ObjIsCo(pObj) )
+            {
+                pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj));
+                Rf2_ObjCopy( p, pObj, Gia_ObjFanin0(pObj) );
+                continue;
+            }
+            assert( Gia_ObjIsAnd(pObj) );
+            pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+            if ( pObj->fMark0 == 1 )
+                Rf2_ObjDeriveAnd( p, pObj, 1 );
+            else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 && (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)) == 0 )
+                Rf2_ObjDeriveAnd( p, pObj, 0 );
+            else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 )
+                Rf2_ObjCopy( p, pObj, Gia_ObjFanin0(pObj) );
+            else 
+                Rf2_ObjCopy( p, pObj, Gia_ObjFanin1(pObj) );
+        }
+    }
+    assert( iBit == p->pCex->nBits );
+    if ( Gia_ManPo(p->pGia, 0)->fMark0 != 1 )
+        printf( "Output value is incorrect.\n" );
+
+    printf( "Bounds: \n" );
+    Rf2_ObjPrint( p, Gia_ManPo(p->pGia, 0) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the refinement for a given counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Rf2_ManRefine( Rf2_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vMap, int fPropFanout, int fVerbose )
+{
+    Vec_Int_t * vJusts;
+//    Vec_Int_t * vSelected = Vec_IntAlloc( 100 );
+    Vec_Int_t * vSelected = NULL;
+    clock_t clk, clk2 = clock();
+    int nGroups;
+    p->nCalls++;
+    // initialize
+    p->pCex = pCex;
+    p->vMap = vMap;
+    p->fPropFanout = fPropFanout;
+    p->fVerbose    = fVerbose;
+    // collects used objects
+    Rf2_ManCollect( p );
+    // collect reconvergence points
+//    Rf2_ManGatherFanins( p, 2 );
+    // propagate justification IDs
+    nGroups = Rf2_ManAssignJustIds( p );
+    vJusts = Rf2_ManPropagate( p, 32 );
+
+//    printf( "\n" );
+//    Rf2_ManPrintVector( vJusts, nGroups );
+    Rf2_ManPrintVectorSpecial( p, vJusts );
+    if ( Vec_IntSize(vJusts) == 0 )
+    {
+        printf( "Empty set of justifying subsets.\n" );
+        return NULL;
+    }
+
+//    p->nMapWords = Abc_BitWordNum( Vec_IntSize(p->vMap) + Vec_IntSize(p->vObjs) + 1 ); // Map + Flops + Const
+//    Rf2_ManBounds( p );
+
+    // select the result
+//    Abc_PrintTime( 1, "Time", clock() - clk2 );
+
+    // verify (empty) refinement
+    clk = clock();
+//    Rf2_ManVerifyUsingTerSim( p->pGia, p->pCex, p->vMap, p->vObjs, vSelected );
+//    Vec_IntUniqify( vSelected );
+//    Vec_IntReverseOrder( vSelected );
+    p->timeVer += clock() - clk;
+    p->timeTotal += clock() - clk2;
+//    p->nRefines += Vec_IntSize(vSelected);
+    return vSelected;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/absRefJ.h b/abc-build/src/proof/abs/absRefJ.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absRefJ.h
@@ -0,0 +1,67 @@
+/**CFile****************************************************************
+
+  FileName    [absRef2.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Abstraction package.]
+
+  Synopsis    [Refinement manager to compute all justifying subsets.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: absRef2.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__proof_abs__AbsRef2_h
+#define ABC__proof_abs__AbsRef2_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Rf2_Man_t_ Rf2_Man_t; // refinement manager
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== giaAbsRef.c ===========================================================*/
+extern Rf2_Man_t *  Rf2_ManStart( Gia_Man_t * pGia );
+extern void         Rf2_ManStop( Rf2_Man_t * p, int fProfile );
+extern double       Rf2_ManMemoryUsage( Rf2_Man_t * p );
+extern Vec_Int_t *  Rf2_ManRefine( Rf2_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vMap, int fPropFanout, int fVerbose );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/abs/absRefSelect.c b/abc-build/src/proof/abs/absRefSelect.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absRefSelect.c
@@ -0,0 +1,309 @@
+/**CFile****************************************************************
+
+  FileName    [absRefSelect.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Abstraction package.]
+
+  Synopsis    [Post-processes the set of selected refinement objects.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: absRefSelect.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include "abs.h"
+#include "absRef.h"
+
+ABC_NAMESPACE_IMPL_START 
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Rnm_ManPrintSelected( Rnm_Man_t * p, Vec_Int_t * vNewPPis )
+{
+    Gia_Obj_t * pObj;
+    int i, Counter = 0;
+    Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+        if ( Gia_ObjIsPi(p->pGia, pObj) ) 
+            printf( "-" );
+        else if ( Vec_IntFind(vNewPPis, Gia_ObjId(p->pGia, pObj)) >= 0 )// this is PPI
+            printf( "1" ), Counter++;
+        else
+            printf( "0" );
+    printf( " %3d\n", Counter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform structural analysis.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ga2_StructAnalize( Gia_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vInter, Vec_Int_t * vNewPPis )
+{
+    Vec_Int_t * vFanins;
+    Gia_Obj_t * pObj, * pFanin;
+    int i, k;
+    // clean labels
+    Gia_ManForEachObj( p, pObj, i )
+        pObj->fMark0 = pObj->fMark1 = 0;
+    // label frontier
+    Gia_ManForEachObjVec( vFront, p, pObj, i )
+        pObj->fMark0 = 1, pObj->fMark1 = 0;
+    // label objects
+    Gia_ManForEachObjVec( vInter, p, pObj, i )
+        pObj->fMark1 = 0, pObj->fMark1 = 1;
+    // label selected
+    Gia_ManForEachObjVec( vNewPPis, p, pObj, i )
+        pObj->fMark1 = 1, pObj->fMark1 = 1;
+    // explore selected
+    Gia_ManForEachObjVec( vNewPPis, p, pObj, i )
+    {
+        printf( "Selected PPI %3d : ", i+1 );
+        printf( "%6d ",  Gia_ObjId(p, pObj) );
+        printf( "\n" );
+        vFanins = Ga2_ObjLeaves( p, pObj );
+        Gia_ManForEachObjVec( vFanins, p, pFanin, k )
+        {
+            printf( "    " );
+            printf( "%6d ", Gia_ObjId(p, pFanin) );
+            if ( pFanin->fMark0 && pFanin->fMark1 )
+                printf( "selected PPI" );
+            else if ( pFanin->fMark0 && !pFanin->fMark1 )
+                printf( "frontier (original PI or PPI)" );
+            else if ( !pFanin->fMark0 &&  pFanin->fMark1 )
+                printf( "abstracted node" );
+            else if ( !pFanin->fMark0 && !pFanin->fMark1 )
+                printf( "free variable" );
+            printf( "\n" );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Postprocessing the set of PPIs using structural analysis.]
+
+  Description [The following sets are used:
+  The set of all PI+PPI is in p->vMap.
+  The set of all abstracted objects is in p->vObjs;
+  The set of important PPIs is in vOldPPis.
+  The new set of selected PPIs is in vNewPPis.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Rnm_ManFilterSelected( Rnm_Man_t * p, Vec_Int_t * vOldPPis )
+{
+    int fVerbose = 0;
+    Vec_Int_t * vNewPPis, * vFanins;
+    Gia_Obj_t * pObj, * pFanin;
+    int i, k, RetValue, Counters[3] = {0};
+
+    // (0) make sure fanin counters are 0 at the beginning
+//    Gia_ManForEachObj( p->pGia, pObj, i )
+//        assert( Rnm_ObjCount(p, pObj) == 0 );
+
+    // (1) increment PPI fanin counters
+    Vec_IntClear( p->vFanins );
+    Gia_ManForEachObjVec( vOldPPis, p->pGia, pObj, i )
+    {
+        vFanins = Ga2_ObjLeaves( p->pGia, pObj );
+        Gia_ManForEachObjVec( vFanins, p->pGia, pFanin, k )
+            if ( Rnm_ObjAddToCount(p, pFanin) == 0 ) // fanin counter is 0 -- save it
+                Vec_IntPush( p->vFanins, Gia_ObjId(p->pGia, pFanin) );
+    }
+
+    // (3) select objects with reconvergence, which create potential constraints
+    // - flop objects
+    // - objects whose fanin belongs to the justified area
+    // - objects whose fanins overlap
+    // (these do not guantee reconvergence, but may potentially have it)
+    // (other objects cannot have reconvergence, even if they are added)
+    vNewPPis = Vec_IntAlloc( 100 );
+    Gia_ManForEachObjVec( vOldPPis, p->pGia, pObj, i )
+    {
+        if ( Gia_ObjIsRo(p->pGia, pObj) )
+        {
+            if ( fVerbose )
+                Counters[0]++;
+            Vec_IntPush( vNewPPis, Gia_ObjId(p->pGia, pObj) );
+            continue;
+        }
+        vFanins = Ga2_ObjLeaves( p->pGia, pObj );
+        Gia_ManForEachObjVec( vFanins, p->pGia, pFanin, k )
+        {
+            if ( Rnm_ObjIsJust(p, pFanin) || Rnm_ObjCount(p, pFanin) > 1 )
+            {
+                if ( fVerbose )
+                    Counters[1] += Rnm_ObjIsJust(p, pFanin);
+                if ( fVerbose )
+                    Counters[2] += (Rnm_ObjCount(p, pFanin) > 1);
+                Vec_IntPush( vNewPPis, Gia_ObjId(p->pGia, pObj) );
+                break;
+            }
+        }
+    }
+    RetValue = Vec_IntUniqify( vNewPPis );
+    assert( RetValue == 0 );
+
+    // (4) clear fanin counters
+    // this is important for counters to be correctly set in the future iterations -- see step (0)
+    Gia_ManForEachObjVec( p->vFanins, p->pGia, pObj, i )
+        Rnm_ObjSetCount( p, pObj, 0 );
+
+    // visualize
+    if ( fVerbose )
+        printf( "*** Refinement %3d : PI+PPI =%4d. Old =%4d. New =%4d.   FF =%4d. Just =%4d. Shared =%4d.\n", 
+            p->nRefId, Vec_IntSize(p->vMap), Vec_IntSize(vOldPPis), Vec_IntSize(vNewPPis), Counters[0], Counters[1], Counters[2] );
+
+//    Rnm_ManPrintSelected( p, vNewPPis );
+//    Ga2_StructAnalize( p->pGia, p->vMap, p->vObjs, vNewPPis );
+    return vNewPPis;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Improved postprocessing the set of PPIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Rnm_ManFilterSelectedNew( Rnm_Man_t * p, Vec_Int_t * vOldPPis )
+{
+    static int Counter = 0;
+    int fVerbose = 0;
+    Vec_Int_t * vNewPPis, * vFanins, * vFanins2;
+    Gia_Obj_t * pObj, * pFanin, * pFanin2;
+    int i, k, k2, RetValue, Counters[3] = {0};
+
+    // return full set of PPIs once in a while
+    if ( ++Counter % 9 == 0 )
+        return Vec_IntDup( vOldPPis );
+    return Rnm_ManFilterSelected( p, vOldPPis );
+
+    // (0) make sure fanin counters are 0 at the beginning
+//    Gia_ManForEachObj( p->pGia, pObj, i )
+//        assert( Rnm_ObjCount(p, pObj) == 0 );
+
+    // (1) increment two levels of PPI fanin counters
+    Vec_IntClear( p->vFanins );
+    Gia_ManForEachObjVec( vOldPPis, p->pGia, pObj, i )
+    {
+        // go through the fanins
+        vFanins = Ga2_ObjLeaves( p->pGia, pObj );
+        Gia_ManForEachObjVec( vFanins, p->pGia, pFanin, k )
+        {
+            Rnm_ObjAddToCount(p, pFanin);
+            if ( Rnm_ObjIsJust(p, pFanin) )   // included in the abstraction
+                Rnm_ObjAddToCount(p, pFanin); // count it second time!
+            Vec_IntPush( p->vFanins, Gia_ObjId(p->pGia, pFanin) );
+
+            // go through the fanins of the fanins
+            vFanins2 = Ga2_ObjLeaves( p->pGia, pFanin );
+            Gia_ManForEachObjVec( vFanins2, p->pGia, pFanin2, k2 )
+            {
+                Rnm_ObjAddToCount(p, pFanin2);
+                if ( Rnm_ObjIsJust(p, pFanin2) )   // included in the abstraction
+                    Rnm_ObjAddToCount(p, pFanin2); // count it second time!
+                Vec_IntPush( p->vFanins, Gia_ObjId(p->pGia, pFanin2) );
+            }
+        }
+    }
+
+    // (3) select objects with reconvergence, which create potential constraints
+    // - flop objects - yes
+    // - objects whose fanin (or fanins' fanin) belongs to the justified area - yes
+    // - objects whose fanins (or fanins' fanin) overlap - yes
+    // (these do not guantee reconvergence, but may potentially have it)
+    // (other objects cannot have reconvergence, even if they are added)
+    vNewPPis = Vec_IntAlloc( 100 );
+    Gia_ManForEachObjVec( vOldPPis, p->pGia, pObj, i )
+    {
+        if ( Gia_ObjIsRo(p->pGia, pObj) )
+        {
+            if ( fVerbose )
+                Counters[0]++;
+            Vec_IntPush( vNewPPis, Gia_ObjId(p->pGia, pObj) );
+            continue;
+        } 
+        // go through the first fanins
+        vFanins = Ga2_ObjLeaves( p->pGia, pObj );
+        Gia_ManForEachObjVec( vFanins, p->pGia, pFanin, k )
+        {
+            if ( Rnm_ObjCount(p, pFanin) > 1 )
+                Vec_IntPush( vNewPPis, Gia_ObjId(p->pGia, pObj) );
+            continue;
+
+            // go through the fanins of the fanins
+            vFanins2 = Ga2_ObjLeaves( p->pGia, pFanin );
+            Gia_ManForEachObjVec( vFanins2, p->pGia, pFanin2, k2 )
+            {
+                if ( Rnm_ObjCount(p, pFanin2) > 1 )
+                {
+//                    Vec_IntPush( vNewPPis, Gia_ObjId(p->pGia, pFanin) );
+                    Vec_IntPush( vNewPPis, Gia_ObjId(p->pGia, pObj) );
+                }
+            }
+        }
+    }
+    RetValue = Vec_IntUniqify( vNewPPis );
+//    assert( RetValue == 0 ); // we will have duplicated entries here!
+
+    // (4) clear fanin counters
+    // this is important for counters to be correctly set in the future iterations -- see step (0)
+    Gia_ManForEachObjVec( p->vFanins, p->pGia, pObj, i )
+        Rnm_ObjSetCount( p, pObj, 0 );
+
+    // visualize
+    if ( fVerbose )
+        printf( "*** Refinement %3d : PI+PPI =%4d. Old =%4d. New =%4d.   FF =%4d. Just =%4d. Shared =%4d.\n", 
+            p->nRefId, Vec_IntSize(p->vMap), Vec_IntSize(vOldPPis), Vec_IntSize(vNewPPis), Counters[0], Counters[1], Counters[2] );
+
+//    Rnm_ManPrintSelected( p, vNewPPis );
+//    Ga2_StructAnalize( p->pGia, p->vMap, p->vObjs, vNewPPis );
+    return vNewPPis;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/absRpm.c b/abc-build/src/proof/abs/absRpm.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absRpm.c
@@ -0,0 +1,793 @@
+/**CFile****************************************************************
+
+  FileName    [absRpm.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Abstraction package.]
+
+  Synopsis    [Structural reparameterization.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: absRpm.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include "abs.h"
+
+ABC_NAMESPACE_IMPL_START 
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int   Gia_ObjDom( Gia_Man_t * p, Gia_Obj_t * pObj )            { return Vec_IntEntry(p->vDoms, Gia_ObjId(p, pObj));   }
+static inline void  Gia_ObjSetDom( Gia_Man_t * p, Gia_Obj_t * pObj, int d )  { Vec_IntWriteEntry(p->vDoms, Gia_ObjId(p, pObj), d);  }
+
+static int Abs_ManSupport2( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp );
+static int Abs_GiaObjDeref_rec( Gia_Man_t * p, Gia_Obj_t * pNode );
+static int Abs_GiaObjRef_rec( Gia_Man_t * p, Gia_Obj_t * pNode );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes one-node dominators.]
+
+  Description [For each node, computes the closest one-node dominator,
+  which can be the node itself if the node has no other dominators.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManAddDom( Gia_Man_t * p, Gia_Obj_t * pObj, int iDom0 )
+{
+    int iDom1, iDomNext;
+    if ( Gia_ObjDom(p, pObj) == -1 )
+    {
+        Gia_ObjSetDom( p, pObj, iDom0 );
+        return;
+    }
+    iDom1 = Gia_ObjDom( p, pObj );
+    while ( 1 )
+    {
+        if ( iDom0 > iDom1 )
+        {
+            iDomNext = Gia_ObjDom( p, Gia_ManObj(p, iDom1) );
+            if ( iDomNext == iDom1 )
+                break;
+            iDom1 = iDomNext;
+            continue;
+        }
+        if ( iDom1 > iDom0 )
+        {
+            iDomNext = Gia_ObjDom( p, Gia_ManObj(p, iDom0) );
+            if ( iDomNext == iDom0 )
+                break;
+            iDom0 = iDomNext;
+            continue;
+        }
+        assert( iDom0 == iDom1 );
+        Gia_ObjSetDom( p, pObj, iDom0 );
+        return;
+    }
+    Gia_ObjSetDom( p, pObj, Gia_ObjId(p, pObj) );
+}
+void Gia_ManComputeDoms( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    if ( p->vDoms == NULL )
+        p->vDoms = Vec_IntAlloc( 0 );
+    Vec_IntFill( p->vDoms, Gia_ManObjNum(p), -1 );
+    Gia_ManForEachObjReverse( p, pObj, i )
+    {
+        if ( i == 0 || Gia_ObjIsCi(pObj) )
+            continue;
+        if ( pObj->fMark1 || (p->pRefs && Gia_ObjIsAnd(pObj) && Gia_ObjRefNum(p, pObj) == 0) )
+            continue;
+        if ( Gia_ObjIsCo(pObj) )
+        {
+            Gia_ObjSetDom( p, pObj, i );
+            Gia_ManAddDom( p, Gia_ObjFanin0(pObj), i );
+            continue;
+        }
+        assert( Gia_ObjIsAnd(pObj) );
+        Gia_ManAddDom( p, Gia_ObjFanin0(pObj), i );
+        Gia_ManAddDom( p, Gia_ObjFanin1(pObj), i );
+    }
+}
+void Gia_ManTestDoms2( Gia_Man_t * p )
+{
+    Vec_Int_t * vNodes;
+    Gia_Obj_t * pObj, * pDom;
+    abctime clk = Abc_Clock();
+    int i;
+    assert( p->vDoms == NULL );
+    Gia_ManComputeDoms( p );
+/*
+    Gia_ManForEachPi( p, pObj, i )
+        if ( Gia_ObjId(p, pObj) != Gia_ObjDom(p, pObj) )
+            printf( "PI =%6d  Id =%8d. Dom =%8d.\n", i, Gia_ObjId(p, pObj), Gia_ObjDom(p, pObj) );
+*/
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    // for each dominated PI, when if the PIs is in a leaf of the MFFC of the dominator
+    Gia_ManCleanMark1( p );
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->fMark1 = 1;
+    vNodes = Vec_IntAlloc( 100 );
+    Gia_ManCreateRefs( p );
+    Gia_ManForEachPi( p, pObj, i )
+    {
+        if ( Gia_ObjId(p, pObj) == Gia_ObjDom(p, pObj) )
+            continue;
+
+        pDom = Gia_ManObj(p, Gia_ObjDom(p, pObj));
+        if ( Gia_ObjIsCo(pDom) )
+        {
+            assert( Gia_ObjFanin0(pDom) == pObj );
+            continue;
+        }
+        assert( Gia_ObjIsAnd(pDom) );
+        Abs_GiaObjDeref_rec( p, pDom );
+        Abs_ManSupport2( p, pDom, vNodes );
+        Abs_GiaObjRef_rec( p, pDom );
+
+        if ( Vec_IntFind(vNodes, Gia_ObjId(p, pObj)) == -1 )
+            printf( "FAILURE.\n" );
+//        else
+//            printf( "Success.\n" );
+    }
+    Vec_IntFree( vNodes );
+    Gia_ManCleanMark1( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect PI doms.]
+
+  Description [Assumes that some PIs and ANDs are marked with fMark1.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManCollectDoms( Gia_Man_t * p )
+{
+    Vec_Int_t * vNodes;
+    Gia_Obj_t * pObj;
+    int Lev, LevMax = ABC_INFINITY;
+    int i, iDom, iDomNext;
+    vNodes = Vec_IntAlloc( 100 );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( !pObj->fMark1 )
+            continue;
+        if ( p->pRefs && Gia_ObjRefNum(p, pObj) == 0 )
+            continue;
+        iDom = Gia_ObjDom(p, pObj);
+        if ( iDom == -1 )
+            continue;
+        if ( iDom == i )
+            continue;
+        for ( Lev = 0; Lev < LevMax && Gia_ObjIsAnd( Gia_ManObj(p, iDom) ); Lev++ )
+        {
+            Vec_IntPush( vNodes, iDom );
+            iDomNext = Gia_ObjDom( p, Gia_ManObj(p, iDom) );
+            if ( iDomNext == iDom )
+                break;
+            iDom = iDomNext;
+        }
+    }
+    Vec_IntUniqify( vNodes );
+    return vNodes;
+}
+Vec_Int_t * Gia_ManComputePiDoms( Gia_Man_t * p )
+{
+    Vec_Int_t * vNodes;
+    Gia_ManComputeDoms( p );
+    vNodes = Gia_ManCollectDoms( p );
+//    Vec_IntPrint( vNodes );
+    return vNodes;
+}
+void Gia_ManTestDoms( Gia_Man_t * p )
+{
+    Vec_Int_t * vNodes;
+    Gia_Obj_t * pObj;
+    int i;
+    // mark PIs
+//    Gia_ManCreateRefs( p );
+    Gia_ManCleanMark1( p );
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->fMark1 = 1;
+    // compute dominators
+    assert( p->vDoms == NULL );
+    vNodes = Gia_ManComputePiDoms( p );
+//    printf( "Nodes = %d. Doms = %d.\n", Gia_ManAndNum(p), Vec_IntSize(vNodes) );
+    Vec_IntFree( vNodes );
+    // unmark PIs
+    Gia_ManCleanMark1( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Counts flops without fanout.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCountFanoutlessFlops( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    int Counter = 0;
+    Gia_ManCreateRefs( p );
+    Gia_ManForEachRo( p, pObj, i )
+        if ( Gia_ObjRefNum(p, pObj) == 0 )
+            Counter++;
+    printf( "Fanoutless flops = %d.\n", Counter );
+    ABC_FREE( p->pRefs );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCountPisNodes_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPis, Vec_Int_t * vAnds )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( pObj->fMark1 )
+    {
+        Vec_IntPush( vPis, Gia_ObjId(p, pObj) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManCountPisNodes_rec( p, Gia_ObjFanin0(pObj), vPis, vAnds );
+    Gia_ManCountPisNodes_rec( p, Gia_ObjFanin1(pObj), vPis, vAnds );
+    Vec_IntPush( vAnds, Gia_ObjId(p, pObj) );
+}
+void Gia_ManCountPisNodes( Gia_Man_t * p, Vec_Int_t * vPis, Vec_Int_t * vAnds )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    // mark const0 and flop output
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+    Gia_ManForEachRo( p, pObj, i )
+        Gia_ObjSetTravIdCurrent( p, pObj );
+    // count PIs and internal nodes reachable from COs
+    Vec_IntClear( vPis );
+    Vec_IntClear( vAnds );
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManCountPisNodes_rec( p, Gia_ObjFanin0(pObj), vPis, vAnds );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abs_GiaObjDeref_rec( Gia_Man_t * p, Gia_Obj_t * pNode )
+{
+    Gia_Obj_t * pFanin;
+    int Counter = 0;
+    if ( pNode->fMark1 || Gia_ObjIsRo(p, pNode) )
+        return 0;
+    assert( Gia_ObjIsAnd(pNode) );
+    pFanin = Gia_ObjFanin0(pNode);
+    assert( Gia_ObjRefNum(p, pFanin) > 0 );
+    if ( Gia_ObjRefDec(p, pFanin) == 0 )
+        Counter += Abs_GiaObjDeref_rec( p, pFanin );
+    pFanin = Gia_ObjFanin1(pNode);
+    assert( Gia_ObjRefNum(p, pFanin) > 0 );
+    if ( Gia_ObjRefDec(p, pFanin) == 0 )
+        Counter += Abs_GiaObjDeref_rec( p, pFanin );
+    return Counter + 1;
+}
+int Abs_GiaObjRef_rec( Gia_Man_t * p, Gia_Obj_t * pNode )
+{
+    Gia_Obj_t * pFanin;
+    int Counter = 0;
+    if ( pNode->fMark1 || Gia_ObjIsRo(p, pNode) )
+        return 0;
+    assert( Gia_ObjIsAnd(pNode) );
+    pFanin = Gia_ObjFanin0(pNode);
+    if ( Gia_ObjRefInc(p, pFanin) == 0 )
+        Counter += Abs_GiaObjRef_rec( p, pFanin );
+    pFanin = Gia_ObjFanin1(pNode);
+    if ( Gia_ObjRefInc(p, pFanin) == 0 )
+        Counter += Abs_GiaObjRef_rec( p, pFanin );
+    return Counter + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of nodes with zero refs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abs_GiaSortNodes( Gia_Man_t * p, Vec_Int_t * vSupp )
+{
+    Gia_Obj_t * pObj;
+    int nSize = Vec_IntSize(vSupp);
+    int i, RetValue;
+    Gia_ManForEachObjVec( vSupp, p, pObj, i )
+        if ( i < nSize && Gia_ObjRefNum(p, pObj) == 0 && !Gia_ObjIsRo(p, pObj) ) // add removable leaves
+        {
+            assert( pObj->fMark1 );
+            Vec_IntPush( vSupp, Gia_ObjId(p, pObj) );
+        }
+    RetValue = Vec_IntSize(vSupp) - nSize;
+    Gia_ManForEachObjVec( vSupp, p, pObj, i )
+        if ( i < nSize && !(Gia_ObjRefNum(p, pObj) == 0 && !Gia_ObjIsRo(p, pObj)) ) // add non-removable leaves
+            Vec_IntPush( vSupp, Gia_ObjId(p, pObj) );
+    assert( Vec_IntSize(vSupp) == 2 * nSize );
+    memmove( Vec_IntArray(vSupp), Vec_IntArray(vSupp) + nSize, sizeof(int) * nSize );
+    Vec_IntShrink( vSupp, nSize );
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes support in terms of PIs and flops.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abs_ManSupport1_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( pObj->fMark1 || Gia_ObjIsRo(p, pObj) )
+    {
+        Vec_IntPush( vSupp, Gia_ObjId(p, pObj) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Abs_ManSupport1_rec( p, Gia_ObjFanin0(pObj), vSupp );
+    Abs_ManSupport1_rec( p, Gia_ObjFanin1(pObj), vSupp );
+}
+int Abs_ManSupport1( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp )
+{
+    assert( Gia_ObjIsAnd(pObj) );
+    Vec_IntClear( vSupp );
+    Gia_ManIncrementTravId( p );
+    Abs_ManSupport1_rec( p, pObj, vSupp );
+    return Vec_IntSize(vSupp);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes support of the MFFC.]
+
+  Description [Should be called when pObj's cone is dereferenced.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abs_ManSupport2_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( pObj->fMark1 || Gia_ObjIsRo(p, pObj) || Gia_ObjRefNum(p, pObj) > 0 )
+    {
+        Vec_IntPush( vSupp, Gia_ObjId(p, pObj) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Abs_ManSupport2_rec( p, Gia_ObjFanin0(pObj), vSupp );
+    Abs_ManSupport2_rec( p, Gia_ObjFanin1(pObj), vSupp );
+}
+int Abs_ManSupport2( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp )
+{
+    assert( Gia_ObjIsAnd(pObj) );
+    Vec_IntClear( vSupp );
+    Gia_ManIncrementTravId( p );
+    Abs_ManSupport2_rec( p, Gia_ObjFanin0(pObj), vSupp );
+    Abs_ManSupport2_rec( p, Gia_ObjFanin1(pObj), vSupp );
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    return Vec_IntSize(vSupp);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes support of the extended MFFC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abs_ManSupport3( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp )
+{
+    Gia_Obj_t * pTemp, * pFan0, * pFan1;
+    int i, nSize0;
+    // collect MFFC
+    Abs_ManSupport2( p, pObj, vSupp );
+    // move dominated to the front
+    nSize0 = Abs_GiaSortNodes( p, vSupp );
+    assert( nSize0 > 0 );
+    // consider remaining nodes
+    while ( 1 )
+    {
+        int fChanges = 0;
+        Gia_ManForEachObjVec( vSupp, p, pTemp, i )
+        {
+            if ( i < nSize0 )
+                continue;
+            if ( !Gia_ObjIsAnd(pTemp) )
+                continue;
+            assert( !pTemp->fMark1 );
+            assert( Gia_ObjRefNum(p, pTemp) > 0 );
+            pFan0 = Gia_ObjFanin0(pTemp);
+            pFan1 = Gia_ObjFanin1(pTemp);
+            if ( Gia_ObjIsTravIdCurrent(p, pFan0) && Gia_ObjIsTravIdCurrent(p, pFan1) )
+            {
+                Vec_IntRemove( vSupp, Gia_ObjId(p, pTemp) );
+                fChanges = 1;
+                break;
+            }
+            if ( Gia_ObjIsTravIdCurrent(p, pFan0) )
+            {
+                Vec_IntRemove( vSupp, Gia_ObjId(p, pTemp) );
+                Vec_IntPush( vSupp, Gia_ObjId(p, pFan1) );
+                assert( !Gia_ObjIsTravIdCurrent(p, pFan1) );
+                Gia_ObjSetTravIdCurrent(p, pFan1);
+                fChanges = 1;
+                break;
+            }
+            if ( Gia_ObjIsTravIdCurrent(p, pFan1) )
+            {
+                Vec_IntRemove( vSupp, Gia_ObjId(p, pTemp) );
+                Vec_IntPush( vSupp, Gia_ObjId(p, pFan0) );
+                assert( !Gia_ObjIsTravIdCurrent(p, pFan0) );
+                Gia_ObjSetTravIdCurrent(p, pFan0);
+                fChanges = 1;
+                break;
+            }
+        }
+        if ( !fChanges )
+            break;
+    }
+    return Vec_IntSize(vSupp);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abs_GiaCofPrint( word * pTruth, int nSize, int nSize0, int Res )
+{
+    int i, Bit;
+    int nBits = (1 << nSize);
+    int nStep = (1 << nSize0);
+    int Mark[2] = {1,1};
+    for ( i = 0; i < nBits; i++ )
+    {
+        if ( i % nStep == 0 )
+        {
+            printf( " " );
+            assert( Res || (Mark[0] && Mark[1]) );
+            Mark[0] = Mark[1] = 0;
+        }
+        Bit = Abc_InfoHasBit((unsigned *)pTruth, i);
+        Mark[Bit] = 1;
+        printf( "%d", Bit );
+    }
+    printf( "\n" );
+    assert( Res || (Mark[0] && Mark[1]) );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if truth table has no const cofactors.]
+
+  Description [The cofactoring variables are the (nSize-nSize0)
+  most significant vars.  Each cofactor depends on nSize0 vars.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abs_GiaCheckTruth( word * pTruth, int nSize, int nSize0 )
+{
+    unsigned char * pStr = (unsigned char *)pTruth;
+    int nStr = (nSize >= 3 ? (1 << (nSize - 3)) : 1);
+    int i, k, nSteps;
+    assert( nSize0 > 0 && nSize0 <= nSize );
+    if ( nSize0 == 1 )
+    {
+        for ( i = 0; i < nStr; i++ )
+            if ( (((unsigned)pStr[i] ^ ((unsigned)pStr[i] >> 1)) & 0x55) != 0x55 )
+                return 0;
+        return 1;
+    }
+    if ( nSize0 == 2 )
+    {
+        for ( i = 0; i < nStr; i++ )
+            if ( ((unsigned)pStr[i] & 0xF) == 0x0 || (((unsigned)pStr[i] >> 4) & 0xF) == 0x0 || 
+                 ((unsigned)pStr[i] & 0xF) == 0xF || (((unsigned)pStr[i] >> 4) & 0xF) == 0xF  )
+                return 0;
+        return 1;
+    }
+    assert( nSize0 >= 3 );
+    nSteps = (1 << (nSize0 - 3));
+    for ( i = 0; i < nStr; i += nSteps )
+    {
+        for ( k = 0; k < nSteps; k++ )
+            if ( ((unsigned)pStr[i+k] & 0xFF) != 0x00 )
+                break;
+        if ( k == nSteps )
+            break;
+        for ( k = 0; k < nSteps; k++ )
+            if ( ((unsigned)pStr[i+k] & 0xFF) != 0xFF )
+                break;
+        if ( k == nSteps )
+            break;
+    }
+    assert( i <= nStr );
+    return (int)( i == nStr );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if truth table has const cofactors.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abs_RpmPerformMark( Gia_Man_t * p, int nCutMax, int fVerbose, int fVeryVerbose )
+{
+    Vec_Int_t * vPis, * vAnds, * vDoms;
+    Vec_Int_t * vSupp, * vSupp1, * vSupp2;
+    Gia_Obj_t * pObj;
+    word * pTruth;
+    int Iter, i, nSize0, nNodes;
+    int fHasConst, fChanges = 1;
+    Gia_ManCreateRefs( p );
+    Gia_ManCleanMark1( p );
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->fMark1 = 1;
+    vPis = Vec_IntAlloc( 100 );
+    vAnds = Vec_IntAlloc( 100 );
+    vSupp1 = Vec_IntAlloc( 100 );
+    vSupp2 = Vec_IntAlloc( 100 );
+    for ( Iter = 0; fChanges; Iter++ )
+    {
+        fChanges = 0;
+        vDoms = Gia_ManComputePiDoms( p );
+        // count the number of PIs and internal nodes
+        if ( fVerbose || fVeryVerbose )
+        {
+            Gia_ManCountPisNodes( p, vPis, vAnds );
+            printf( "Iter %3d :  ", Iter );
+            printf( "PI = %5d  (%6.2f %%)  ",  Vec_IntSize(vPis),  100.0 * Vec_IntSize(vPis)  / Gia_ManPiNum(p)  );
+            printf( "And = %6d  (%6.2f %%) ",  Vec_IntSize(vAnds), 100.0 * Vec_IntSize(vAnds) / Gia_ManAndNum(p) );
+            printf( "Dom = %5d  (%6.2f %%)  ", Vec_IntSize(vDoms), 100.0 * Vec_IntSize(vDoms) / Gia_ManAndNum(p)  );
+            printf( "\n" );
+        }
+//        pObj = Gia_ObjFanin0( Gia_ManPo(p, 1) );
+        Gia_ManForEachObjVec( vDoms, p, pObj, i )
+        {
+            assert( !pObj->fMark1 );
+            assert( Gia_ObjRefNum( p, pObj ) > 0 );
+            // dereference root node
+            nNodes = Abs_GiaObjDeref_rec( p, pObj );
+/*
+            // compute support of full cone
+            if ( Abs_ManSupport1(p, pObj, vSupp1) > nCutMax )
+//            if ( 1 )
+            {
+                // check support of MFFC
+                if ( Abs_ManSupport2(p, pObj, vSupp2) > nCutMax )
+//                if ( 1 )
+                {
+                    Abs_GiaObjRef_rec( p, pObj );
+                    continue;
+                }
+                vSupp = vSupp2;
+//                printf( "-" );
+            }
+            else
+            {
+                vSupp = vSupp1;
+//                printf( "+" );
+            }
+*/
+            if ( Abs_ManSupport2(p, pObj, vSupp2) > nCutMax )
+            {
+                Abs_GiaObjRef_rec( p, pObj );
+                continue;
+            }
+            vSupp = vSupp2;
+
+            // order nodes by their ref counts
+            nSize0 = Abs_GiaSortNodes( p, vSupp );
+            assert( nSize0 > 0 && nSize0 <= nCutMax );
+            // check if truth table has const cofs
+            pTruth = Gia_ObjComputeTruthTableCut( p, pObj, vSupp );
+            if ( pTruth == NULL )
+            {
+                Abs_GiaObjRef_rec( p, pObj );
+                continue;
+            }
+            fHasConst = !Abs_GiaCheckTruth( pTruth, Vec_IntSize(vSupp), nSize0 );
+            if ( fVeryVerbose )
+            {
+                printf( "Nodes =%3d ",  nNodes );
+                printf( "Size =%3d ",   Vec_IntSize(vSupp) );
+                printf( "Size0 =%3d  ", nSize0 );
+                printf( "%3s", fHasConst ? "yes" : "no" );
+                Abs_GiaCofPrint( pTruth, Vec_IntSize(vSupp), nSize0, fHasConst );
+            }
+            if ( fHasConst )
+            {
+                Abs_GiaObjRef_rec( p, pObj );
+                continue;
+            }
+            // pObj can be reparamed
+            pObj->fMark1 = 1;
+            fChanges = 1;
+        }
+        Vec_IntFree( vDoms );
+    }
+    // count the number of PIs and internal nodes
+    if ( fVeryVerbose )
+    {
+        Gia_ManCountPisNodes( p, vPis, vAnds );
+        printf( "Iter %3d :  ", Iter );
+        printf( "PI = %5d  (%6.2f %%)  ",  Vec_IntSize(vPis),  100.0 * Vec_IntSize(vPis)  / Gia_ManPiNum(p)  );
+        printf( "And = %6d  (%6.2f %%) ",  Vec_IntSize(vAnds), 100.0 * Vec_IntSize(vAnds) / Gia_ManAndNum(p) );
+//        printf( "Dom = %5d  (%6.2f %%)  ", Vec_IntSize(vDoms), 100.0 * Vec_IntSize(vDoms) / Gia_ManAndNum(p)  );
+        printf( "\n" );
+    }
+    // cleanup
+    Vec_IntFree( vPis );
+    Vec_IntFree( vAnds );
+    Vec_IntFree( vSupp1 );
+    Vec_IntFree( vSupp2 );
+//    Gia_ManCleanMark1( p ); // this will erase markings
+    ABC_FREE( p->pRefs );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assumed that fMark1 marks the internal PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupRpm( Gia_Man_t * p )
+{
+    Vec_Int_t * vPis, * vAnds;
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    // derive PIs and internal nodes
+    vPis = Vec_IntAlloc( 100 );
+    vAnds = Vec_IntAlloc( 100 );
+    Gia_ManCountPisNodes( p, vPis, vAnds );
+
+    // duplicate AIG
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    // create PIs
+    Gia_ManForEachObjVec( vPis, p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    // create flops
+    Gia_ManForEachRo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    // create internal nodes
+    Gia_ManForEachObjVec( vAnds, p, pObj, i )
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    // create COs
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+
+    // cleanup
+    Vec_IntFree( vPis );
+    Vec_IntFree( vAnds );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs structural reparametrization.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Abs_RpmPerform( Gia_Man_t * p, int nCutMax, int fVerbose, int fVeryVerbose )
+{
+    Gia_Man_t * pNew;
+//    Gia_ManTestDoms( p );
+//    return NULL;
+    // perform structural analysis
+    Gia_ObjComputeTruthTableStart( p, nCutMax );
+    Abs_RpmPerformMark( p, nCutMax, fVerbose, fVeryVerbose );
+    Gia_ObjComputeTruthTableStop( p );
+    // derive new AIG
+    pNew = Gia_ManDupRpm( p );
+    Gia_ManCleanMark1( p );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/absRpmOld.c b/abc-build/src/proof/abs/absRpmOld.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absRpmOld.c
@@ -0,0 +1,201 @@
+/**CFile****************************************************************
+
+  FileName    [absRpmOld.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Scalable AIG package.]
+
+  Synopsis    [Old min-cut-based reparametrization.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: absRpmOld.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abs.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Specialized duplication.]
+
+  Description [Replaces registers by PIs/POs and PIs by registers.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupIn2Ff( Gia_Man_t * p )
+{
+    Vec_Int_t * vPiOuts;
+    Gia_Man_t * pNew; 
+    Gia_Obj_t * pObj;
+    int i;
+    vPiOuts = Vec_IntAlloc( Gia_ManPiNum(p) );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) + 2 * Gia_ManPiNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachPi( p, pObj, i )
+        Vec_IntPush( vPiOuts, Gia_ManAppendCi(pNew) );
+    Gia_ManForEachRo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachPo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManForEachRi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManForEachPi( p, pObj, i )
+        Gia_ManAppendCo( pNew, Vec_IntEntry(vPiOuts, i) );
+    Gia_ManSetRegNum( pNew, Gia_ManPiNum(p) );
+    Vec_IntFree( vPiOuts );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reverses the above step.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManDupFf2In_rec( Gia_Man_t * pNew, Gia_Obj_t * pObj )
+{
+    if ( pObj->Value != ~0 )
+        return pObj->Value;
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManDupFf2In_rec( pNew, Gia_ObjFanin0(pObj) );
+    Gia_ManDupFf2In_rec( pNew, Gia_ObjFanin1(pObj) );
+    return pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reverses the above step.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDupFf2In( Gia_Man_t * p, int nFlopsOld )
+{
+    Gia_Man_t * pNew; 
+    Gia_Obj_t * pObj;
+    int i;
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachRo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    for ( i = Gia_ManPiNum(p) - nFlopsOld; i < Gia_ManPiNum(p); i++ )
+        Gia_ManPi(p, i)->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachPo( p, pObj, i )
+        Gia_ManDupFf2In_rec( pNew, Gia_ObjFanin0(pObj) );
+    Gia_ManForEachPo( p, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManSetRegNum( pNew, nFlopsOld );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reparameterized to get rid of useless primary inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Abs_RpmPerformOld( Gia_Man_t * p, int fVerbose )
+{
+//    extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose );
+    Aig_Man_t * pMan, * pTemp;
+    Gia_Man_t * pNew, * pTmp;
+    int nFlopsOld = Gia_ManRegNum(p);
+    if ( fVerbose )
+    {
+        printf( "Original AIG:\n" );
+        Gia_ManPrintStats( p, NULL );
+    }
+
+    // perform input trimming
+    pNew = Gia_ManDupTrimmed( p, 1, 0, 0, -1 );
+    if ( fVerbose )
+    {
+        printf( "After PI trimming:\n" );
+        Gia_ManPrintStats( pNew, NULL );
+    }
+    // transform GIA
+    pNew = Gia_ManDupIn2Ff( pTmp = pNew );
+    Gia_ManStop( pTmp );
+    if ( fVerbose )
+    {
+        printf( "After PI-2-FF transformation:\n" );
+        Gia_ManPrintStats( pNew, NULL );
+    }
+
+    // derive AIG
+    pMan = Gia_ManToAigSimple( pNew );
+    Gia_ManStop( pNew );
+    // perform min-reg retiming
+    pMan = Saig_ManRetimeMinArea( pTemp = pMan, 10, 0, 0, 1, 0 );
+    Aig_ManStop( pTemp );
+    // derive GIA
+    pNew = Gia_ManFromAigSimple( pMan );
+    Aig_ManStop( pMan );
+    if ( fVerbose )
+    {
+        printf( "After min-area retiming:\n" );
+        Gia_ManPrintStats( pNew, NULL );
+    }
+
+    // transform back
+    pNew = Gia_ManDupFf2In( pTmp = pNew, nFlopsOld );
+    Gia_ManStop( pTmp );
+    if ( fVerbose )
+    {
+        printf( "After FF-2-PI tranformation:\n" );
+        Gia_ManPrintStats( pNew, NULL );
+    }
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/absUtil.c b/abc-build/src/proof/abs/absUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absUtil.c
@@ -0,0 +1,257 @@
+/**CFile****************************************************************
+
+  FileName    [absUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Abstraction package.]
+
+  Synopsis    [Interface to pthreads.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: absUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#include "abs.h"
+
+ABC_NAMESPACE_IMPL_START 
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abs_ParSetDefaults( Abs_Par_t * p )
+{
+    memset( p, 0, sizeof(Abs_Par_t) );
+    p->nFramesMax         =      0;   // maximum frames
+    p->nFramesStart       =      0;   // starting frame 
+    p->nFramesPast        =      4;   // overlap frames
+    p->nConfLimit         =      0;   // conflict limit
+    p->nLearnedMax        =   1000;   // max number of learned clauses
+    p->nLearnedStart      =   1000;   // max number of learned clauses
+    p->nLearnedDelta      =    200;   // max number of learned clauses
+    p->nLearnedPerce      =     70;   // max number of learned clauses
+    p->nTimeOut           =      0;   // timeout in seconds
+    p->nRatioMin          =      0;   // stop when less than this % of object is abstracted
+    p->nRatioMax          =     30;   // restart when more than this % of object is abstracted
+    p->fUseTermVars       =      0;   // use terminal variables
+    p->fUseRollback       =      0;   // use rollback to the starting number of frames
+    p->fPropFanout        =      1;   // propagate fanouts during refinement
+    p->fVerbose           =      0;   // verbose flag
+    p->iFrame             =     -1;   // the number of frames covered 
+    p->iFrameProved       =     -1;   // the number of frames proved
+    p->nFramesNoChangeLim =      2;   // the number of frames without change to dump abstraction
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converting VTA vector to GLA vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_VtaConvertToGla( Gia_Man_t * p, Vec_Int_t * vVta )
+{
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vGla;
+    int nObjMask, nObjs = Gia_ManObjNum(p);
+    int i, Entry, nFrames = Vec_IntEntry( vVta, 0 );
+    assert( Vec_IntEntry(vVta, nFrames+1) == Vec_IntSize(vVta) );
+    // get the bitmask
+    nObjMask = (1 << Abc_Base2Log(nObjs)) - 1;
+    assert( nObjs <= nObjMask );
+    // go through objects
+    vGla = Vec_IntStart( nObjs );
+    Vec_IntForEachEntryStart( vVta, Entry, i, nFrames+2 )
+    {
+        pObj = Gia_ManObj( p, (Entry &  nObjMask) );
+        assert( Gia_ObjIsRo(p, pObj) || Gia_ObjIsAnd(pObj) || Gia_ObjIsConst0(pObj) );
+        Vec_IntAddToEntry( vGla, (Entry &  nObjMask), 1 );
+    }
+    Vec_IntWriteEntry( vGla, 0, nFrames );
+    return vGla;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converting GLA vector to VTA vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_VtaConvertFromGla( Gia_Man_t * p, Vec_Int_t * vGla, int nFrames )
+{
+    Vec_Int_t * vVta;
+    int nObjBits, nObjMask, nObjs = Gia_ManObjNum(p);
+    int i, k, j, Entry, Counter, nGlaSize;
+    //. get the GLA size
+    nGlaSize = Vec_IntSum(vGla);
+    // get the bitmask
+    nObjBits = Abc_Base2Log(nObjs);
+    nObjMask = (1 << Abc_Base2Log(nObjs)) - 1;
+    assert( nObjs <= nObjMask );
+    // go through objects
+    vVta = Vec_IntAlloc( 1000 );
+    Vec_IntPush( vVta, nFrames );
+    Counter = nFrames + 2;
+    for ( i = 0; i <= nFrames; i++, Counter += i * nGlaSize )
+        Vec_IntPush( vVta, Counter );
+    for ( i = 0; i < nFrames; i++ )
+        for ( k = 0; k <= i; k++ )
+            Vec_IntForEachEntry( vGla, Entry, j )
+                if ( Entry ) 
+                    Vec_IntPush( vVta, (k << nObjBits) | j );
+    Counter = Vec_IntEntry(vVta, nFrames+1);
+    assert( Vec_IntEntry(vVta, nFrames+1) == Vec_IntSize(vVta) );
+    return vVta;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converting GLA vector to FLA vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_FlaConvertToGla_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vGla )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    Vec_IntWriteEntry( vGla, Gia_ObjId(p, pObj), 1 );
+    if ( Gia_ObjIsRo(p, pObj) )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_FlaConvertToGla_rec( p, Gia_ObjFanin0(pObj), vGla );
+    Gia_FlaConvertToGla_rec( p, Gia_ObjFanin1(pObj), vGla );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converting FLA vector to GLA vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_FlaConvertToGla( Gia_Man_t * p, Vec_Int_t * vFla )
+{
+    Vec_Int_t * vGla;
+    Gia_Obj_t * pObj;
+    int i;
+    // mark const0 and relevant CI objects
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent(p, Gia_ManConst0(p));
+    Gia_ManForEachPi( p, pObj, i )
+        Gia_ObjSetTravIdCurrent(p, pObj);
+    Gia_ManForEachRo( p, pObj, i )
+        if ( !Vec_IntEntry(vFla, i) )
+            Gia_ObjSetTravIdCurrent(p, pObj);
+    // label all objects reachable from the PO and selected flops
+    vGla = Vec_IntStart( Gia_ManObjNum(p) );
+    Vec_IntWriteEntry( vGla, 0, 1 );
+    Gia_ManForEachPo( p, pObj, i )
+        Gia_FlaConvertToGla_rec( p, Gia_ObjFanin0(pObj), vGla );
+    Gia_ManForEachRi( p, pObj, i )
+        if ( Vec_IntEntry(vFla, i) )
+            Gia_FlaConvertToGla_rec( p, Gia_ObjFanin0(pObj), vGla );
+    return vGla;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converting GLA vector to FLA vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_GlaConvertToFla( Gia_Man_t * p, Vec_Int_t * vGla )
+{
+    Vec_Int_t * vFla;
+    Gia_Obj_t * pObj;
+    int i;
+    vFla = Vec_IntStart( Gia_ManRegNum(p) );
+    Gia_ManForEachRo( p, pObj, i )
+        if ( Vec_IntEntry(vGla, Gia_ObjId(p, pObj)) )
+            Vec_IntWriteEntry( vFla, i, 1 );
+    return vFla;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_GlaCountFlops( Gia_Man_t * p, Vec_Int_t * vGla )
+{
+    Gia_Obj_t * pObj;
+    int i, Count = 0;
+    Gia_ManForEachRo( p, pObj, i )
+        if ( Vec_IntEntry(vGla, Gia_ObjId(p, pObj)) )
+            Count++;
+    return Count;
+}
+int Gia_GlaCountNodes( Gia_Man_t * p, Vec_Int_t * vGla )
+{
+    Gia_Obj_t * pObj;
+    int i, Count = 0;
+    Gia_ManForEachAnd( p, pObj, i )
+        if ( Vec_IntEntry(vGla, Gia_ObjId(p, pObj)) )
+            Count++;
+    return Count;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/absVta.c b/abc-build/src/proof/abs/absVta.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/absVta.c
@@ -0,0 +1,1764 @@
+/**CFile****************************************************************
+
+  FileName    [absVta.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Abstraction package.]
+
+  Synopsis    [Variable time-frame abstraction.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: absVta.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sat/bsat/satSolver2.h"
+#include "base/main/main.h"
+#include "abs.h"
+
+ABC_NAMESPACE_IMPL_START
+
+#define VTA_LARGE  0xFFFFFFF
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vta_Obj_t_ Vta_Obj_t; // object
+struct Vta_Obj_t_
+{
+    int           iObj;
+    int           iFrame;
+    int           iNext;
+    unsigned      Prio   : 28;  // related to VTA_LARGE
+    unsigned      Value  :  2;
+    unsigned      fAdded :  1;
+    unsigned      fVisit :  1;
+};
+
+typedef struct Vta_Man_t_ Vta_Man_t; // manager
+struct Vta_Man_t_
+{
+    // user data
+    Gia_Man_t *   pGia;         // AIG manager
+    Abs_Par_t *   pPars;        // parameters
+    // internal data
+    int           nObjs;        // the number of objects
+    int           nObjsAlloc;   // the number of objects allocated
+    int           nBins;        // number of hash table entries
+    int *         pBins;        // hash table bins
+    Vta_Obj_t *   pObjs;        // storage for objects
+    Vec_Int_t *   vOrder;       // objects in DPS order
+    // abstraction
+    int           nObjBits;     // the number of bits to represent objects
+    unsigned      nObjMask;     // object mask
+    Vec_Ptr_t *   vFrames;      // start abstraction for each frame
+    int           nWords;       // the number of words in the record
+    int           nCexes;       // the number of CEXes
+    int           nObjAdded;    // objects added to the abstraction
+    Vec_Int_t *   vSeens;       // seen objects
+    Vec_Bit_t *   vSeenGla;     // seen objects in all frames
+    int           nSeenGla;     // seen objects in all frames
+    int           nSeenAll;     // seen objects in all frames
+    // other data
+    Vec_Ptr_t *   vCores;       // unsat core for each frame
+    sat_solver2 * pSat;         // incremental SAT solver
+    Vec_Int_t *   vAddedNew;    // the IDs of variables added to the solver
+    // statistics 
+    abctime       timeSat;
+    abctime       timeUnsat;
+    abctime       timeCex;
+    abctime       timeOther;
+};
+
+
+// ternary simulation
+
+#define VTA_VAR0   1
+#define VTA_VAR1   2
+#define VTA_VARX   3
+
+static inline int Vta_ValIs0( Vta_Obj_t * pThis, int fCompl )
+{
+    if ( pThis->Value == VTA_VAR1 && fCompl )
+        return 1;
+    if ( pThis->Value == VTA_VAR0 && !fCompl )
+        return 1;
+    return 0;
+}
+static inline int Vta_ValIs1( Vta_Obj_t * pThis, int fCompl )
+{
+    if ( pThis->Value == VTA_VAR0 && fCompl )
+        return 1;
+    if ( pThis->Value == VTA_VAR1 && !fCompl )
+        return 1;
+    return 0;
+}
+
+static inline Vta_Obj_t *  Vta_ManObj( Vta_Man_t * p, int i )           { assert( i >= 0 && i < p->nObjs ); return i ? p->pObjs + i : NULL;                     }
+static inline int          Vta_ObjId( Vta_Man_t * p, Vta_Obj_t * pObj ) { assert( pObj > p->pObjs && pObj < p->pObjs + p->nObjs ); return pObj - p->pObjs;      }
+
+#define Vta_ManForEachObj( p, pObj, i )                                 \
+    for ( i = 1; (i < p->nObjs) && ((pObj) = Vta_ManObj(p, i)); i++ )
+#define Vta_ManForEachObjObj( p, pObjVta, pObjGia, i )                  \
+    for ( i = 1; (i < p->nObjs) && ((pObjVta) = Vta_ManObj(p, i)) && ((pObjGia) = Gia_ManObj(p->pGia, pObjVta->iObj)); i++ )
+#define Vta_ManForEachObjObjReverse( p, pObjVta, pObjGia, i )           \
+    for ( i = Vec_IntSize(vVec) - 1; (i >= 1) && ((pObjVta) = Vta_ManObj(p, i)) && ((pObjGia) = Gia_ManObj(p->pGia, pObjVta->iObj)); i++ )
+
+#define Vta_ManForEachObjVec( vVec, p, pObj, i )                        \
+    for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Vta_ManObj(p, Vec_IntEntry(vVec,i))); i++ )
+#define Vta_ManForEachObjVecReverse( vVec, p, pObj, i )                 \
+    for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && ((pObj) = Vta_ManObj(p, Vec_IntEntry(vVec,i))); i-- )
+
+#define Vta_ManForEachObjObjVec( vVec, p, pObj, pObjG, i )              \
+    for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Vta_ManObj(p, Vec_IntEntry(vVec,i))) && ((pObjG) = Gia_ManObj(p->pGia, pObj->iObj)); i++ )
+#define Vta_ManForEachObjObjVecReverse( vVec, p, pObj, pObjG, i )       \
+    for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && ((pObj) = Vta_ManObj(p, Vec_IntEntry(vVec,i))) && ((pObjG) = Gia_ManObj(p->pGia, pObj->iObj)); i-- )
+
+
+// abstraction is given as an array of integers:
+// - the first entry is the number of timeframes (F)
+// - the next (F+1) entries give the beginning position of each timeframe
+// - the following entries give the object IDs
+// invariant:  assert( vec[vec[0]+1] == size(vec) );
+
+extern void Vga_ManAddClausesOne( Vta_Man_t * p, int iObj, int iFrame );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Converting from one array to per-frame arrays.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Gia_VtaAbsToFrames( Vec_Int_t * vAbs )
+{
+    Vec_Ptr_t * vFrames;
+    Vec_Int_t * vFrame;
+    int i, k, Entry, iStart, iStop = -1;
+    int nFrames = Vec_IntEntry( vAbs, 0 );
+    assert( Vec_IntEntry(vAbs, nFrames+1) == Vec_IntSize(vAbs) );
+    vFrames = Vec_PtrAlloc( nFrames );
+    for ( i = 0; i < nFrames; i++ )
+    {
+        iStart = Vec_IntEntry( vAbs, i+1 );
+        iStop  = Vec_IntEntry( vAbs, i+2 );
+        vFrame = Vec_IntAlloc( iStop - iStart );
+        Vec_IntForEachEntryStartStop( vAbs, Entry, k, iStart, iStop )
+            Vec_IntPush( vFrame, Entry );
+        Vec_PtrPush( vFrames, vFrame );
+    }
+    assert( iStop == Vec_IntSize(vAbs) );
+    return vFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converting from per-frame arrays to one integer array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_VtaFramesToAbs( Vec_Vec_t * vFrames )
+{
+    Vec_Int_t * vOne, * vAbs;
+    int i, k, Entry, nSize;
+    vAbs = Vec_IntAlloc( 2 + Vec_VecSize(vFrames) + Vec_VecSizeSize(vFrames) );
+    Vec_IntPush( vAbs, Vec_VecSize(vFrames) );
+    nSize = Vec_VecSize(vFrames) + 2;
+    Vec_VecForEachLevelInt( vFrames, vOne, i )
+    {
+        Vec_IntPush( vAbs, nSize );
+        nSize += Vec_IntSize( vOne );
+    }
+    Vec_IntPush( vAbs, nSize );
+    assert( Vec_IntSize(vAbs) == Vec_VecSize(vFrames) + 2 );
+    Vec_VecForEachLevelInt( vFrames, vOne, i )
+        Vec_IntForEachEntry( vOne, Entry, k )
+            Vec_IntPush( vAbs, Entry );
+    assert( Vec_IntEntry(vAbs, Vec_IntEntry(vAbs,0)+1) == Vec_IntSize(vAbs) );
+    return vAbs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detects how many frames are completed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Vta_ManDeriveAbsAll( Vec_Int_t * p, int nWords )
+{
+    Vec_Int_t * vRes;
+    unsigned * pThis;
+    int i, w, nObjs = Vec_IntSize(p) / nWords;
+    assert( Vec_IntSize(p) % nWords == 0 );
+    vRes = Vec_IntAlloc( nObjs );
+    for ( i = 0; i < nObjs; i++ )
+    {
+        pThis = (unsigned *)Vec_IntEntryP( p, nWords * i );
+        for ( w = 0; w < nWords; w++ )
+            if ( pThis[w] )
+                break;
+        Vec_IntPush( vRes, (int)(w < nWords) );
+    }
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect nodes/flops involved in different timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Vec_IntDoubleWidth( Vec_Int_t * p, int nWords )
+{
+    int * pArray = ABC_CALLOC( int, Vec_IntSize(p) * 2 );
+    int i, w, nObjs = Vec_IntSize(p) / nWords;
+    assert( Vec_IntSize(p) % nWords == 0 );
+    for ( i = 0; i < nObjs; i++ )
+        for ( w = 0; w < nWords; w++ )
+            pArray[2 * nWords * i + w] = p->pArray[nWords * i + w];
+    ABC_FREE( p->pArray );
+    p->pArray = pArray;
+    p->nSize *= 2;
+    p->nCap = p->nSize;
+    return 2 * nWords;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vga_ManHash( int iObj, int iFrame, int nBins )
+{
+    return ((unsigned)((iObj + iFrame)*(iObj + iFrame + 1))) % nBins;
+}
+static inline int * Vga_ManLookup( Vta_Man_t * p, int iObj, int iFrame )
+{
+    Vta_Obj_t * pThis;
+    int * pPlace = p->pBins + Vga_ManHash( iObj, iFrame, p->nBins );
+    for ( pThis = Vta_ManObj(p, *pPlace); 
+          pThis;  pPlace = &pThis->iNext, 
+          pThis = Vta_ManObj(p, *pPlace) )
+        if ( pThis->iObj == iObj && pThis->iFrame == iFrame )
+            break;
+    return pPlace;
+}
+static inline Vta_Obj_t * Vga_ManFind( Vta_Man_t * p, int iObj, int iFrame )
+{
+    int * pPlace = Vga_ManLookup( p, iObj, iFrame );
+    return Vta_ManObj(p, *pPlace);
+}
+static inline Vta_Obj_t * Vga_ManFindOrAdd( Vta_Man_t * p, int iObj, int iFrame )
+{
+    Vta_Obj_t * pThis;
+    int i, * pPlace;
+    assert( iObj >= 0 && iFrame >= -1 );
+    if ( p->nObjs == p->nObjsAlloc )
+    {
+        // resize objects
+        p->pObjs = ABC_REALLOC( Vta_Obj_t, p->pObjs, 2 * p->nObjsAlloc );
+        memset( p->pObjs + p->nObjsAlloc, 0, p->nObjsAlloc * sizeof(Vta_Obj_t) );
+        p->nObjsAlloc *= 2;
+        // rehash entries in the table
+        ABC_FREE( p->pBins );
+        p->nBins = Abc_PrimeCudd( 2 * p->nBins );
+        p->pBins = ABC_CALLOC( int, p->nBins );
+        Vta_ManForEachObj( p, pThis, i )
+        {
+            pThis->iNext = 0;
+            pPlace = Vga_ManLookup( p, pThis->iObj, pThis->iFrame );
+            assert( *pPlace == 0 );
+            *pPlace = i;
+        }
+    }
+    pPlace = Vga_ManLookup( p, iObj, iFrame );
+    if ( *pPlace )
+        return Vta_ManObj(p, *pPlace);
+    *pPlace = p->nObjs++;
+    pThis = Vta_ManObj(p, *pPlace);
+    pThis->iObj   = iObj;
+    pThis->iFrame = iFrame;
+    return pThis;
+}
+static inline void Vga_ManDelete( Vta_Man_t * p, int iObj, int iFrame )
+{
+    int * pPlace = Vga_ManLookup( p, iObj, iFrame );
+    Vta_Obj_t * pThis = Vta_ManObj(p, *pPlace);
+    assert( pThis != NULL );
+    *pPlace = pThis->iNext;
+    pThis->iNext = -1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives counter-example using current assignments.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Vga_ManDeriveCex( Vta_Man_t * p )
+{
+    Abc_Cex_t * pCex;
+    Vta_Obj_t * pThis;
+    Gia_Obj_t * pObj;
+    int i;
+    pCex = Abc_CexAlloc( Gia_ManRegNum(p->pGia), Gia_ManPiNum(p->pGia), p->pPars->iFrame+1 );
+    pCex->iPo = 0;
+    pCex->iFrame = p->pPars->iFrame;
+    Vta_ManForEachObjObj( p, pThis, pObj, i )
+        if ( Gia_ObjIsPi(p->pGia, pObj) && sat_solver2_var_value(p->pSat, Vta_ObjId(p, pThis)) )
+            Abc_InfoSetBit( pCex->pData, pCex->nRegs + pThis->iFrame * pCex->nPis + Gia_ObjCioId(pObj) );
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Remaps core into frame/node pairs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Vta_ManUnsatCoreRemap( Vta_Man_t * p, Vec_Int_t * vCore )
+{
+    Vta_Obj_t * pThis;
+    int i, Entry;
+    Vec_IntForEachEntry( vCore, Entry, i )
+    {
+        pThis = Vta_ManObj( p, Entry );
+        Entry = (pThis->iFrame << p->nObjBits) | pThis->iObj;
+        Vec_IntWriteEntry( vCore, i, Entry );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares two objects by their distance.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Vta_ManComputeDepthIncrease( Vta_Obj_t ** pp1, Vta_Obj_t ** pp2 )
+{
+    int Diff = (*pp1)->Prio - (*pp2)->Prio;
+    if ( Diff < 0 )
+        return -1;
+    if ( Diff > 0 ) 
+        return 1;
+    Diff = (*pp1) - (*pp2);
+    if ( Diff < 0 )
+        return -1;
+    if ( Diff > 0 ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the object is already used.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Vta_ManObjIsUsed( Vta_Man_t * p, int iObj )
+{
+    int i;
+    unsigned * pInfo = (unsigned *)Vec_IntEntryP( p->vSeens, p->nWords * iObj );
+    for ( i = 0; i < p->nWords; i++ )
+        if ( pInfo[i] )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds predecessors of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vta_ObjPreds( Vta_Man_t * p, Vta_Obj_t * pThis, Gia_Obj_t * pObj, Vta_Obj_t ** ppThis0, Vta_Obj_t ** ppThis1 )
+{
+    *ppThis0 = NULL;
+    *ppThis1 = NULL;
+//    if ( !pThis->fAdded )
+//        return;
+    assert( !Gia_ObjIsPi(p->pGia, pObj) );
+    if ( Gia_ObjIsConst0(pObj) || (Gia_ObjIsCi(pObj) && pThis->iFrame == 0) )
+        return;
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        *ppThis0 = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), pThis->iFrame );
+        *ppThis1 = Vga_ManFind( p, Gia_ObjFaninId1p(p->pGia, pObj), pThis->iFrame );
+//        assert( *ppThis0 && *ppThis1 );
+        return;
+    }
+    assert( Gia_ObjIsRo(p->pGia, pObj) && pThis->iFrame > 0 );
+    pObj = Gia_ObjRoToRi( p->pGia, pObj );
+    *ppThis0 = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), pThis->iFrame-1 );
+//    assert( *ppThis0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect const/PI/RO/AND in a topological order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Vta_ManCollectNodes_rec( Vta_Man_t * p, Vta_Obj_t * pThis, Vec_Int_t * vOrder )
+{
+    Gia_Obj_t * pObj;
+    Vta_Obj_t * pThis0, * pThis1;
+    if ( pThis->fVisit )
+        return;
+    pThis->fVisit = 1;
+    pObj = Gia_ManObj( p->pGia, pThis->iObj );
+    if ( pThis->fAdded )
+    {
+        Vta_ObjPreds( p, pThis, pObj, &pThis0, &pThis1 );
+        if ( pThis0 ) Vta_ManCollectNodes_rec( p, pThis0, vOrder );
+        if ( pThis1 ) Vta_ManCollectNodes_rec( p, pThis1, vOrder );
+    }
+    Vec_IntPush( vOrder, Vta_ObjId(p, pThis) );
+}
+Vec_Int_t * Vta_ManCollectNodes( Vta_Man_t * p, int f )
+{
+    Vta_Obj_t * pThis;
+    Gia_Obj_t * pObj;
+    Vec_IntClear( p->vOrder );
+    pObj = Gia_ManPo( p->pGia, 0 );
+    pThis = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), f );
+    assert( pThis != NULL );
+    assert( !pThis->fVisit );
+    Vta_ManCollectNodes_rec( p, pThis, p->vOrder );
+    assert( pThis->fVisit );
+    return p->vOrder;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines abstraction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Vta_ManSatVerify( Vta_Man_t * p )
+{
+    Vta_Obj_t * pThis, * pThis0, * pThis1;
+    Gia_Obj_t * pObj;
+    int i;
+    Vta_ManForEachObj( p, pThis, i )
+        pThis->Value = (sat_solver2_var_value(p->pSat, i) ? VTA_VAR1 : VTA_VAR0);
+    Vta_ManForEachObjObj( p, pThis, pObj, i )
+    {
+        if ( !pThis->fAdded )
+            continue;
+        Vta_ObjPreds( p, pThis, pObj, &pThis0, &pThis1 );
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            if ( pThis->Value == VTA_VAR1 )
+                assert( Vta_ValIs1(pThis0, Gia_ObjFaninC0(pObj)) && Vta_ValIs1(pThis1, Gia_ObjFaninC1(pObj)) );
+            else if ( pThis->Value == VTA_VAR0 )
+                assert( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) || Vta_ValIs0(pThis1, Gia_ObjFaninC1(pObj)) );
+            else assert( 0 );
+        }
+        else if ( Gia_ObjIsRo(p->pGia, pObj) )
+        {
+            pObj = Gia_ObjRoToRi( p->pGia, pObj );
+            if ( pThis->iFrame == 0 )
+                assert( pThis->Value == VTA_VAR0 );
+            else if ( pThis->Value == VTA_VAR0 )
+                assert( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) );
+            else if ( pThis->Value == VTA_VAR1 )
+                assert( Vta_ValIs1(pThis0, Gia_ObjFaninC0(pObj)) );
+            else assert( 0 );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines abstraction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Vta_ManProfileAddition( Vta_Man_t * p, Vec_Int_t * vTermsToAdd )
+{
+    Vta_Obj_t * pThis;
+    Gia_Obj_t * pObj;
+    // profile the added ones
+    int i, * pCounters = ABC_CALLOC( int, p->pPars->iFrame+1 );
+    Vta_ManForEachObjObjVec( vTermsToAdd, p, pThis, pObj, i )
+        pCounters[pThis->iFrame]++;
+    for ( i = 0; i <= p->pPars->iFrame; i++ )
+        Abc_Print( 1, "%2d", pCounters[i] );
+    Abc_Print( 1, "***\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines abstraction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Vta_ManRefineAbstraction( Vta_Man_t * p, int f )
+{
+    int fVerify = 0;
+    Abc_Cex_t * pCex = NULL;
+    Vec_Int_t * vOrder, * vTermsToAdd;
+    Vec_Ptr_t * vTermsUsed, * vTermsUnused;
+    Vta_Obj_t * pThis, * pThis0, * pThis1, * pTop;
+    Gia_Obj_t * pObj;
+    int i, Counter;
+
+    if ( fVerify )
+    Vta_ManSatVerify( p );
+
+    // collect nodes in a topological order
+    vOrder = Vta_ManCollectNodes( p, f );
+    Vta_ManForEachObjObjVec( vOrder, p, pThis, pObj, i )
+    {
+        pThis->Prio = VTA_LARGE;
+        pThis->Value = sat_solver2_var_value(p->pSat, Vta_ObjId(p, pThis)) ? VTA_VAR1 : VTA_VAR0;
+        pThis->fVisit = 0;
+    }
+
+    // verify
+    if ( fVerify )
+    Vta_ManForEachObjObjVec( vOrder, p, pThis, pObj, i )
+    {
+        if ( !pThis->fAdded )
+            continue;
+        Vta_ObjPreds( p, pThis, pObj, &pThis0, &pThis1 );
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            if ( pThis->Value == VTA_VAR1 )
+                assert( Vta_ValIs1(pThis0, Gia_ObjFaninC0(pObj)) && Vta_ValIs1(pThis1, Gia_ObjFaninC1(pObj)) );
+            else if ( pThis->Value == VTA_VAR0 )
+                assert( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) || Vta_ValIs0(pThis1, Gia_ObjFaninC1(pObj)) );
+            else assert( 0 );
+        }
+        else if ( Gia_ObjIsRo(p->pGia, pObj) )
+        {
+            pObj = Gia_ObjRoToRi( p->pGia, pObj );
+            if ( pThis->iFrame == 0 )
+                assert( pThis->Value == VTA_VAR0 );
+            else if ( pThis->Value == VTA_VAR0 )
+                assert( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) );
+            else if ( pThis->Value == VTA_VAR1 )
+                assert( Vta_ValIs1(pThis0, Gia_ObjFaninC0(pObj)) );
+            else assert( 0 );
+        }
+    }
+
+    // compute distance in reverse order
+    pThis = Vta_ManObj( p, Vec_IntEntryLast(vOrder) );
+    pThis->Prio  = 1;
+    // collect used and unused terms
+    vTermsUsed   = Vec_PtrAlloc( 1015 );
+    vTermsUnused = Vec_PtrAlloc( 1016 );
+    Vta_ManForEachObjObjVecReverse( vOrder, p, pThis, pObj, i )
+    {
+        // there is no unreachable states
+        assert( pThis->Prio < VTA_LARGE );
+        // skip constants and PIs
+        if ( Gia_ObjIsConst0(pObj) || Gia_ObjIsPi(p->pGia, pObj) )
+        {
+            pThis->Prio = 0; // set highest priority
+            continue;
+        }
+        // collect terminals
+        assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsRo(p->pGia, pObj) );
+        if ( !pThis->fAdded )
+        {
+            assert( pThis->Prio > 0 );
+            if ( Vta_ManObjIsUsed(p, pThis->iObj) )
+                Vec_PtrPush( vTermsUsed, pThis );
+            else
+                Vec_PtrPush( vTermsUnused, pThis );
+            continue;
+        }
+        // propagate
+        Vta_ObjPreds( p, pThis, pObj, &pThis0, &pThis1 );
+        if ( pThis0 ) 
+            pThis0->Prio = Abc_MinInt( pThis0->Prio, pThis->Prio + 1 );
+        if ( pThis1 ) 
+            pThis1->Prio = Abc_MinInt( pThis1->Prio, pThis->Prio + 1 );
+    }
+
+/*
+    Vta_ManForEachObjObjVecReverse( vOrder, p, pThis, pObj, i )
+        if ( pThis->Prio > 0 )
+            pThis->Prio = 10;
+*/
+/*
+    // update priorities according to reconvergence counters
+    Vec_PtrForEachEntry( Vta_Obj_t *, vTermsUsed, pThis, i )
+    {
+        Vta_Obj_t * pThis0, * pThis1;
+        Gia_Obj_t * pObj = Gia_ManObj( p->pGia, pThis->iObj );
+        Vta_ObjPreds( p, pThis, pObj, &pThis0, &pThis1 );
+        pThis->Prio += 10000000;
+        if ( pThis0 )
+            pThis->Prio -= 1000000 * pThis0->fAdded;
+        if ( pThis1 )
+            pThis->Prio -= 1000000 * pThis1->fAdded;
+    }
+    Vec_PtrForEachEntry( Vta_Obj_t *, vTermsUnused, pThis, i )
+    {
+        Vta_Obj_t * pThis0, * pThis1;
+        Gia_Obj_t * pObj = Gia_ManObj( p->pGia, pThis->iObj );
+        Vta_ObjPreds( p, pThis, pObj, &pThis0, &pThis1 );
+        pThis->Prio += 10000000;
+        if ( pThis0 )
+            pThis->Prio -= 1000000 * pThis0->fAdded;
+        if ( pThis1 )
+            pThis->Prio -= 1000000 * pThis1->fAdded;
+    }
+*/
+
+
+    // update priorities according to reconvergence counters
+    Vec_PtrForEachEntry( Vta_Obj_t *, vTermsUsed, pThis, i )
+        pThis->Prio = pThis->iObj;
+    Vec_PtrForEachEntry( Vta_Obj_t *, vTermsUnused, pThis, i )
+        pThis->Prio = pThis->iObj;
+
+
+    // objects with equal distance should receive priority based on number
+    // those objects whose prototypes have been added in other timeframes
+    // should have higher priority than the current object
+    Vec_PtrSort( vTermsUsed,   (int (*)(void))Vta_ManComputeDepthIncrease );
+    Vec_PtrSort( vTermsUnused, (int (*)(void))Vta_ManComputeDepthIncrease );
+    if ( Vec_PtrSize(vTermsUsed) > 1 )
+    {
+        pThis0 = (Vta_Obj_t *)Vec_PtrEntry(vTermsUsed, 0);
+        pThis1 = (Vta_Obj_t *)Vec_PtrEntryLast(vTermsUsed);
+        assert( pThis0->Prio <= pThis1->Prio );
+    }
+    // assign the priority based on these orders
+    Counter = 1;
+    Vec_PtrForEachEntry( Vta_Obj_t *, vTermsUsed, pThis, i )
+        pThis->Prio = Counter++;
+    Vec_PtrForEachEntry( Vta_Obj_t *, vTermsUnused, pThis, i )
+        pThis->Prio = Counter++;
+//    Abc_Print( 1, "Used %d  Unused %d\n", Vec_PtrSize(vTermsUsed), Vec_PtrSize(vTermsUnused) );
+
+
+    // propagate in the direct order
+    Vta_ManForEachObjObjVec( vOrder, p, pThis, pObj, i )
+    {
+        assert( pThis->fVisit == 0 );
+        assert( pThis->Prio < VTA_LARGE );
+        // skip terminal objects
+        if ( !pThis->fAdded )
+            continue;
+        // assumes that values are assigned!!!
+        assert( pThis->Value != 0 );
+        // propagate
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            pThis0 = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), pThis->iFrame );
+            pThis1 = Vga_ManFind( p, Gia_ObjFaninId1p(p->pGia, pObj), pThis->iFrame );
+            assert( pThis0 && pThis1 );
+            if ( pThis->Value == VTA_VAR1 )
+            {
+                assert( Vta_ValIs1(pThis0, Gia_ObjFaninC0(pObj)) && Vta_ValIs1(pThis1, Gia_ObjFaninC1(pObj)) );
+                pThis->Prio = Abc_MaxInt( pThis0->Prio, pThis1->Prio );
+            }
+            else if ( pThis->Value == VTA_VAR0 )
+            {
+                if ( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) && Vta_ValIs0(pThis1, Gia_ObjFaninC1(pObj)) )
+                    pThis->Prio = Abc_MinInt( pThis0->Prio, pThis1->Prio ); // choice!!!
+                else if ( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) )
+                    pThis->Prio = pThis0->Prio;
+                else if ( Vta_ValIs0(pThis1, Gia_ObjFaninC1(pObj)) )
+                    pThis->Prio = pThis1->Prio;
+                else assert( 0 );
+            }
+            else assert( 0 );
+        }
+        else if ( Gia_ObjIsRo(p->pGia, pObj) )
+        {
+            if ( pThis->iFrame > 0 )
+            {
+                pObj = Gia_ObjRoToRi( p->pGia, pObj );
+                pThis0 = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), pThis->iFrame-1 );
+                assert( pThis0 );
+                pThis->Prio = pThis0->Prio;
+            }
+            else
+                pThis->Prio = 0;
+        }
+        else if ( Gia_ObjIsConst0(pObj) )
+            pThis->Prio = 0;
+        else
+            assert( 0 );
+    }
+
+    // select important values
+    pTop = Vta_ManObj( p, Vec_IntEntryLast(vOrder) );
+    pTop->fVisit = 1;
+    vTermsToAdd = Vec_IntAlloc( 100 );
+    Vta_ManForEachObjObjVecReverse( vOrder, p, pThis, pObj, i )
+    {
+        if ( !pThis->fVisit )
+            continue;
+        pThis->fVisit = 0;
+        assert( pThis->Prio >= 0 && pThis->Prio <= pTop->Prio );
+        // skip terminal objects
+        if ( !pThis->fAdded )
+        {
+            assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsRo(p->pGia, pObj) || Gia_ObjIsConst0(pObj) || Gia_ObjIsPi(p->pGia, pObj) );
+            Vec_IntPush( vTermsToAdd, Vta_ObjId(p, pThis) );
+            continue;
+        }
+        // assumes that values are assigned!!!
+        assert( pThis->Value != 0 );
+        // propagate
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            pThis0 = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), pThis->iFrame );
+            pThis1 = Vga_ManFind( p, Gia_ObjFaninId1p(p->pGia, pObj), pThis->iFrame );
+            assert( pThis0 && pThis1 );
+            if ( pThis->Value == VTA_VAR1 )
+            {
+                assert( Vta_ValIs1(pThis0, Gia_ObjFaninC0(pObj)) && Vta_ValIs1(pThis1, Gia_ObjFaninC1(pObj)) );
+                assert( pThis0->Prio <= pThis->Prio );
+                assert( pThis1->Prio <= pThis->Prio );
+                pThis0->fVisit = 1;
+                pThis1->fVisit = 1;
+            }
+            else if ( pThis->Value == VTA_VAR0 )
+            {
+                if ( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) && Vta_ValIs0(pThis1, Gia_ObjFaninC1(pObj)) )
+                {
+                    if ( pThis0->fVisit )
+                    {
+                    }
+                    else if ( pThis1->fVisit )
+                    {
+                    }
+                    else if ( pThis0->Prio <= pThis1->Prio ) // choice!!!
+                    {
+                        pThis0->fVisit = 1;
+                        assert( pThis0->Prio == pThis->Prio );
+                    }
+                    else
+                    {
+                        pThis1->fVisit = 1;
+                        assert( pThis1->Prio == pThis->Prio );
+                    }
+                }
+                else if ( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) )
+                {
+                    pThis0->fVisit = 1;
+                    assert( pThis0->Prio == pThis->Prio );
+                }
+                else if ( Vta_ValIs0(pThis1, Gia_ObjFaninC1(pObj)) )
+                {
+                    pThis1->fVisit = 1;
+                    assert( pThis1->Prio == pThis->Prio );
+                }
+                else assert( 0 );
+            }
+            else assert( 0 );
+        }
+        else if ( Gia_ObjIsRo(p->pGia, pObj) )
+        {
+            if ( pThis->iFrame > 0 )
+            {
+                pObj = Gia_ObjRoToRi( p->pGia, pObj );
+                pThis0 = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), pThis->iFrame-1 );
+                assert( pThis0 );
+                pThis0->fVisit = 1;
+                assert( pThis0->Prio == pThis->Prio );
+            }
+        }
+        else if ( !Gia_ObjIsConst0(pObj) )
+            assert( 0 );
+    }
+
+    if ( p->pPars->fAddLayer )
+    {
+        // mark those currently included
+        Vta_ManForEachObjVec( vTermsToAdd, p, pThis, i )
+        {
+            assert( pThis->fVisit == 0 );
+            pThis->fVisit = 1;
+        }
+        // add used terms, which have close relationship
+        Counter = Vec_IntSize(vTermsToAdd);
+        Vec_PtrForEachEntry( Vta_Obj_t *, vTermsUsed, pThis, i )
+        {
+            if ( pThis->fVisit )
+                continue;
+    //        Vta_ObjPreds( p, pThis, Gia_ManObj(p->pGia, pThis->iObj), &pThis0, &pThis1 );
+    //        if ( (pThis0 && (pThis0->fAdded || pThis0->fVisit)) || (pThis1 && (pThis1->fAdded || pThis1->fVisit)) )
+                Vec_IntPush( vTermsToAdd, Vta_ObjId(p, pThis) );
+        }
+        // remove those currenty included
+        Vta_ManForEachObjVec( vTermsToAdd, p, pThis, i )
+            pThis->fVisit = 0;
+    }
+//    printf( "\n%d -> %d\n", Counter, Vec_IntSize(vTermsToAdd) );
+//Vec_IntReverseOrder( vTermsToAdd );
+//Vec_IntSort( vTermsToAdd, 1 );
+
+
+    // cleanup
+    Vec_PtrFree( vTermsUsed );
+    Vec_PtrFree( vTermsUnused );
+
+
+    if ( fVerify )
+    {
+    // verify
+    Vta_ManForEachObjVec( vOrder, p, pThis, i )
+        pThis->Value = VTA_VARX;
+    Vta_ManForEachObjVec( vTermsToAdd, p, pThis, i )
+    {
+        assert( !pThis->fAdded );
+        pThis->Value = sat_solver2_var_value(p->pSat, Vta_ObjId(p, pThis)) ? VTA_VAR1 : VTA_VAR0;
+    }
+    // simulate 
+    Vta_ManForEachObjObjVec( vOrder, p, pThis, pObj, i )
+    {
+        assert( pThis->fVisit == 0 );
+        if ( !pThis->fAdded )
+            continue;
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            pThis0 = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), pThis->iFrame );
+            pThis1 = Vga_ManFind( p, Gia_ObjFaninId1p(p->pGia, pObj), pThis->iFrame );
+            assert( pThis0 && pThis1 );
+            if ( Vta_ValIs1(pThis0, Gia_ObjFaninC0(pObj)) && Vta_ValIs1(pThis1, Gia_ObjFaninC1(pObj)) )
+                pThis->Value = VTA_VAR1;
+            else if ( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) || Vta_ValIs0(pThis1, Gia_ObjFaninC1(pObj)) )
+                pThis->Value = VTA_VAR0;
+            else
+                pThis->Value = VTA_VARX;
+        }
+        else if ( Gia_ObjIsRo(p->pGia, pObj) )
+        {
+            if ( pThis->iFrame > 0 )
+            {
+                pObj = Gia_ObjRoToRi( p->pGia, pObj );
+                pThis0 = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), pThis->iFrame-1 );
+                assert( pThis0 );
+                if ( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) )
+                    pThis->Value = VTA_VAR0;
+                else if ( Vta_ValIs1(pThis0, Gia_ObjFaninC0(pObj)) )
+                    pThis->Value = VTA_VAR1;
+                else
+                    pThis->Value = VTA_VARX;
+            }
+            else
+            {
+                pThis->Value = VTA_VAR0;
+            }
+        }
+        else if ( Gia_ObjIsConst0(pObj) )
+        {
+            pThis->Value = VTA_VAR0;
+        }
+        else assert( 0 );
+        // double check the solver
+        assert( pThis->Value == VTA_VARX || (int)pThis->Value == (sat_solver2_var_value(p->pSat, Vta_ObjId(p, pThis)) ? VTA_VAR1 : VTA_VAR0) );
+    }
+
+    // check the output
+    if ( !Vta_ValIs1(pTop, Gia_ObjFaninC0(Gia_ManPo(p->pGia, 0))) )
+        Abc_Print( 1, "Vta_ManRefineAbstraction(): Terminary simulation verification failed!\n" );
+//    else
+//        Abc_Print( 1, "Verification OK.\n" );
+    }
+
+
+    // produce true counter-example
+    if ( pTop->Prio == 0 )
+        pCex = Vga_ManDeriveCex( p );
+    else
+    {
+//       Vta_ManProfileAddition( p, vTermsToAdd );
+
+        Vta_ManForEachObjObjVec( vTermsToAdd, p, pThis, pObj, i )
+            if ( !Gia_ObjIsPi(p->pGia, pObj) )
+                Vga_ManAddClausesOne( p, pThis->iObj, pThis->iFrame );
+        sat_solver2_simplify( p->pSat );
+    }
+    p->nObjAdded += Vec_IntSize(vTermsToAdd);
+    Vec_IntFree( vTermsToAdd );
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vta_Man_t * Vga_ManStart( Gia_Man_t * pGia, Abs_Par_t * pPars )
+{
+    Vta_Man_t * p;
+    p = ABC_CALLOC( Vta_Man_t, 1 );
+    p->pGia        = pGia;
+    p->pPars       = pPars;
+    // internal data
+    p->nObjsAlloc  = (1 << 18);
+    p->pObjs       = ABC_CALLOC( Vta_Obj_t, p->nObjsAlloc );
+    p->nObjs       = 1;
+    p->nBins       = Abc_PrimeCudd( 2*p->nObjsAlloc );
+    p->pBins       = ABC_CALLOC( int, p->nBins );
+    p->vOrder      = Vec_IntAlloc( 1013 );
+    // abstraction
+    p->nObjBits    = Abc_Base2Log( Gia_ManObjNum(pGia) );
+    p->nObjMask    = (1 << p->nObjBits) - 1;
+    assert( Gia_ManObjNum(pGia) <= (int)p->nObjMask );
+    p->nWords      = 1;
+    p->vSeens      = Vec_IntStart( Gia_ManObjNum(pGia) * p->nWords );
+    p->vSeenGla    = Vec_BitStart( Gia_ManObjNum(pGia) );
+    p->nSeenGla    = 1;
+    p->nSeenAll    = 1;
+    // other data
+    p->vCores      = Vec_PtrAlloc( 100 );
+    p->pSat        = sat_solver2_new();
+    p->pSat->pPrf1 = Vec_SetAlloc( 20 );
+//    p->pSat->fVerbose = p->pPars->fVerbose;
+//    sat_solver2_set_learntmax( p->pSat, pPars->nLearnedMax );
+    p->pSat->nLearntStart = p->pPars->nLearnedStart;
+    p->pSat->nLearntDelta = p->pPars->nLearnedDelta;
+    p->pSat->nLearntRatio = p->pPars->nLearnedPerce;
+    p->pSat->nLearntMax   = p->pSat->nLearntStart;
+    // start the abstraction
+    assert( pGia->vObjClasses != NULL );
+    p->vFrames = Gia_VtaAbsToFrames( pGia->vObjClasses );
+    p->vAddedNew   = Vec_IntAlloc( 1000 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Delete manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Vga_ManStop( Vta_Man_t * p )
+{
+    if ( p->pPars->fVerbose )
+        Abc_Print( 1, "SAT solver:  Var = %d  Cla = %d  Conf = %d  Lrn = %d  Reduce = %d  Cex = %d  Objs+ = %d\n", 
+            sat_solver2_nvars(p->pSat), sat_solver2_nclauses(p->pSat), sat_solver2_nconflicts(p->pSat), 
+            sat_solver2_nlearnts(p->pSat), p->pSat->nDBreduces, p->nCexes, p->nObjAdded );
+    Vec_VecFreeP( (Vec_Vec_t **)&p->vCores );
+    Vec_VecFreeP( (Vec_Vec_t **)&p->vFrames );
+    Vec_BitFreeP( &p->vSeenGla );
+    Vec_IntFreeP( &p->vSeens );
+    Vec_IntFreeP( &p->vOrder );
+    Vec_IntFreeP( &p->vAddedNew );
+    sat_solver2_delete( p->pSat );
+    ABC_FREE( p->pBins );
+    ABC_FREE( p->pObjs );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the output literal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Vga_ManGetOutLit( Vta_Man_t * p, int f )
+{
+    Gia_Obj_t * pObj = Gia_ManPo(p->pGia, 0);
+    Vta_Obj_t * pThis = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), f );
+    assert( pThis != NULL && pThis->fAdded );
+    if ( f == 0 && Gia_ObjIsRo(p->pGia, Gia_ObjFanin0(pObj)) && !Gia_ObjFaninC0(pObj) )
+        return -Vta_ObjId(p, pThis);
+    return Abc_Var2Lit( Vta_ObjId(p, pThis), Gia_ObjFaninC0(pObj) );
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Finds the set of clauses involved in the UNSAT core.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Vta_ManUnsatCore( int iLit, sat_solver2 * pSat, int nConfMax, int fVerbose, int * piRetValue, int * pnConfls )
+{
+    abctime clk = Abc_Clock();
+    Vec_Int_t * vCore;
+    int RetValue, nConfPrev = pSat->stats.conflicts;
+    if ( piRetValue )
+        *piRetValue = 1;
+    // consider special case when PO points to the flop
+    // this leads to immediate conflict in the first timeframe
+    if ( iLit < 0 )
+    {
+        vCore = Vec_IntAlloc( 1 );
+        Vec_IntPush( vCore, -iLit );
+        return vCore;
+    }
+    // solve the problem
+    RetValue = sat_solver2_solve( pSat, &iLit, &iLit+1, (ABC_INT64_T)nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( pnConfls )
+        *pnConfls = (int)pSat->stats.conflicts - nConfPrev;
+    if ( RetValue == l_Undef )
+    {
+        if ( piRetValue )
+            *piRetValue = -1;
+        return NULL;
+    }
+    if ( RetValue == l_True )
+    {
+        if ( piRetValue )
+            *piRetValue = 0;
+        return NULL;
+    }
+    if ( fVerbose )
+    {
+//        Abc_Print( 1, "%6d", (int)pSat->stats.conflicts - nConfPrev );
+//        Abc_Print( 1, "UNSAT after %7d conflicts.      ", pSat->stats.conflicts );
+//        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    assert( RetValue == l_False );
+    // derive the UNSAT core
+    clk = Abc_Clock();
+    vCore = (Vec_Int_t *)Sat_ProofCore( pSat );
+    if ( fVerbose )
+    {
+//        Abc_Print( 1, "Core is %8d vars    (out of %8d).   ", Vec_IntSize(vCore), sat_solver2_nvars(pSat) );
+//        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    return vCore;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Vta_ManAbsPrintFrame( Vta_Man_t * p, Vec_Int_t * vCore, int nFrames, int nConfls, int nCexes, abctime Time, int fVerbose )
+{
+    unsigned * pInfo;
+	int * pCountAll = NULL, * pCountUni = NULL;
+    int i, iFrame, iObj, Entry, fChanges = 0;
+    // print info about frames
+    if ( vCore )
+    {
+        pCountAll = ABC_CALLOC( int, nFrames + 1 );
+        pCountUni = ABC_CALLOC( int, nFrames + 1 );
+        Vec_IntForEachEntry( vCore, Entry, i )
+        {
+            iObj   = (Entry &  p->nObjMask);
+            iFrame = (Entry >> p->nObjBits);
+            assert( iFrame < nFrames );
+            pInfo  = (unsigned *)Vec_IntEntryP( p->vSeens, p->nWords * iObj );
+            if ( !Abc_InfoHasBit(pInfo, iFrame) )
+            {
+                Abc_InfoSetBit( pInfo, iFrame );
+                pCountUni[iFrame+1]++;
+                pCountUni[0]++;
+                p->nSeenAll++;
+            }
+            pCountAll[iFrame+1]++;
+            pCountAll[0]++;
+            if ( !Vec_BitEntry(p->vSeenGla, iObj) )
+            {
+                Vec_BitWriteEntry(p->vSeenGla, iObj, 1);
+                p->nSeenGla++;
+                fChanges = 1;
+            }
+        }
+    }
+    if ( !fVerbose )
+    {
+        ABC_FREE( pCountAll );
+        ABC_FREE( pCountUni );
+        return fChanges;
+    }
+
+    if ( Abc_FrameIsBatchMode() && !vCore )
+        return fChanges;
+
+//    Abc_Print( 1, "%5d%5d", pCountAll[0], pCountUni[0] ); 
+    Abc_Print( 1, "%4d :", nFrames-1 );
+    Abc_Print( 1, "%4d", Abc_MinInt(100, 100 * p->nSeenGla / (Gia_ManRegNum(p->pGia) + Gia_ManAndNum(p->pGia) + 1)) ); 
+    Abc_Print( 1, "%6d", p->nSeenGla ); 
+    Abc_Print( 1, "%4d", Abc_MinInt(100, 100 * p->nSeenAll / (p->nSeenGla * nFrames)) ); 
+    Abc_Print( 1, "%8d", nConfls );
+    if ( nCexes == 0 )
+        Abc_Print( 1, "%5c", '-' ); 
+    else
+        Abc_Print( 1, "%5d", nCexes ); 
+//    Abc_Print( 1, " %9d", sat_solver2_nvars(p->pSat) ); 
+    Abc_PrintInt( sat_solver2_nvars(p->pSat) );
+    Abc_PrintInt( sat_solver2_nclauses(p->pSat) );
+    Abc_PrintInt( sat_solver2_nlearnts(p->pSat) );
+    if ( vCore == NULL )
+    {
+        Abc_Print( 1, "    ..." ); 
+//        for ( k = 0; k < 7; k++ )
+//            Abc_Print( 1, "     " );
+        Abc_Print( 1, "%9.2f sec", 1.0*Time/CLOCKS_PER_SEC );
+        Abc_Print( 1, "%5.1f GB", (sat_solver2_memory_proof(p->pSat) + sat_solver2_memory(p->pSat, 0)) / (1<<30) );
+        Abc_Print( 1, "\r" );
+    }
+    else
+    {
+        Abc_PrintInt( pCountAll[0] );
+/*
+        if ( nFrames > 7 )
+        {
+            for ( k = 0; k < 3; k++ )
+                Abc_Print( 1, "%5d", pCountAll[k+1] ); 
+            Abc_Print( 1, "  ..." );
+            for ( k = nFrames-3; k < nFrames; k++ )
+                Abc_Print( 1, "%5d", pCountAll[k+1] ); 
+        }
+        else
+        {
+            for ( k = 0; k < nFrames; k++ )
+                Abc_Print( 1, "%5d", pCountAll[k+1] ); 
+            for ( k = nFrames; k < 7; k++ )
+                Abc_Print( 1, "     " );
+        }
+*/
+        Abc_Print( 1, "%9.2f sec", 1.0*Time/CLOCKS_PER_SEC );
+        Abc_Print( 1, "%5.1f GB", (sat_solver2_memory_proof(p->pSat) + sat_solver2_memory(p->pSat, 0)) / (1<<30) );
+        Abc_Print( 1, "\n" );
+    }
+    fflush( stdout );
+
+    if ( vCore )
+    {
+        ABC_FREE( pCountAll );
+        ABC_FREE( pCountUni );
+    }
+    return fChanges;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds clauses to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Vga_ManAddClausesOne( Vta_Man_t * p, int iObj, int iFrame )
+{ 
+    Vta_Obj_t * pThis0, * pThis1;
+    Gia_Obj_t * pObj = Gia_ManObj( p->pGia, iObj );
+    Vta_Obj_t * pThis = Vga_ManFindOrAdd( p, iObj, iFrame );
+    int iThis0, iMainVar = Vta_ObjId(p, pThis);
+    assert( pThis->iObj == iObj && pThis->iFrame == iFrame );
+    if ( pThis->fAdded )
+        return;
+    pThis->fAdded = 1;
+    Vec_IntPush( p->vAddedNew, iMainVar );
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        pThis0 = Vga_ManFindOrAdd( p, Gia_ObjFaninId0p(p->pGia, pObj), iFrame );
+        iThis0 = Vta_ObjId(p, pThis0);
+        pThis1 = Vga_ManFindOrAdd( p, Gia_ObjFaninId1p(p->pGia, pObj), iFrame );
+        sat_solver2_add_and( p->pSat, iMainVar, iThis0, Vta_ObjId(p, pThis1), 
+            Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0, iMainVar );
+    }
+    else if ( Gia_ObjIsRo(p->pGia, pObj) )
+    {
+        if ( iFrame == 0 )
+        {
+            if ( p->pPars->fUseTermVars )
+            {
+                pThis0 = Vga_ManFindOrAdd( p, iObj, -1 );
+                sat_solver2_add_constraint( p->pSat, iMainVar, Vta_ObjId(p, pThis0), 1, 0, iMainVar );
+            }
+            else
+            {
+                sat_solver2_add_const( p->pSat, iMainVar, 1, 0, iMainVar );
+            }
+        }
+        else
+        {
+            pObj = Gia_ObjRoToRi( p->pGia, pObj );
+            pThis0 = Vga_ManFindOrAdd( p, Gia_ObjFaninId0p(p->pGia, pObj), iFrame-1 );
+            sat_solver2_add_buffer( p->pSat, iMainVar, Vta_ObjId(p, pThis0), Gia_ObjFaninC0(pObj), 0, iMainVar );  
+        }
+    }
+    else if ( Gia_ObjIsConst0(pObj) )
+    {
+        sat_solver2_add_const( p->pSat, iMainVar, 1, 0, iMainVar );
+    }
+    else //if ( !Gia_ObjIsPi(p->pGia, pObj) )
+        assert( 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Vga_ManLoadSlice( Vta_Man_t * p, Vec_Int_t * vOne, int Lift )
+{
+    int i, Entry;
+    Vec_IntForEachEntry( vOne, Entry, i )
+        Vga_ManAddClausesOne( p, Entry & p->nObjMask, (Entry >> p->nObjBits) + Lift );
+    sat_solver2_simplify( p->pSat );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Vga_ManPrintCore( Vta_Man_t * p, Vec_Int_t * vCore, int Lift )
+{
+    int i, Entry, iObj, iFrame;
+    Vec_IntForEachEntry( vCore, Entry, i )
+    {
+        iObj   = (Entry &  p->nObjMask);
+        iFrame = (Entry >> p->nObjBits);
+        Abc_Print( 1, "%d*%d ", iObj, iFrame+Lift );
+    }
+    Abc_Print( 1, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Vga_ManRollBack( Vta_Man_t * p, int nObjOld )
+{
+    Vta_Obj_t * pThis  = p->pObjs + nObjOld;
+    Vta_Obj_t * pLimit = p->pObjs + p->nObjs;
+    int i, Entry;
+    for ( ; pThis < pLimit; pThis++ )
+        Vga_ManDelete( p, pThis->iObj, pThis->iFrame );
+    memset( p->pObjs + nObjOld, 0, sizeof(Vta_Obj_t) * (p->nObjs - nObjOld) );
+    p->nObjs = nObjOld;
+    Vec_IntForEachEntry( p->vAddedNew, Entry, i )
+        if ( Entry < p->nObjs )
+        {
+            pThis = Vta_ManObj(p, Entry);
+            assert( pThis->fAdded == 1 );
+            pThis->fAdded = 0;
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Send abstracted model or send cancel.]
+
+  Description [Counter-example will be sent automatically when &vta terminates.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_VtaSendAbsracted( Vta_Man_t * p, int fVerbose )
+{
+    Gia_Man_t * pAbs;
+    assert( Abc_FrameIsBridgeMode() );
+//    if ( fVerbose )
+//        Abc_Print( 1, "Sending abstracted model...\n" );
+    // create obj classes
+    Vec_IntFreeP( &p->pGia->vObjClasses );
+    p->pGia->vObjClasses = Gia_VtaFramesToAbs( (Vec_Vec_t *)p->vCores );
+    // create gate classes
+    Vec_IntFreeP( &p->pGia->vGateClasses );
+    p->pGia->vGateClasses = Gia_VtaConvertToGla( p->pGia, p->pGia->vObjClasses );
+    Vec_IntFreeP( &p->pGia->vObjClasses );
+    // create abstrated model
+    pAbs = Gia_ManDupAbsGates( p->pGia, p->pGia->vGateClasses );
+    Vec_IntFreeP( &p->pGia->vGateClasses );
+    // send it out
+    Gia_ManToBridgeAbsNetlist( stdout, pAbs, BRIDGE_ABS_NETLIST );
+    Gia_ManStop( pAbs );
+}
+void Gia_VtaSendCancel( Vta_Man_t * p, int fVerbose )
+{
+    extern int Gia_ManToBridgeBadAbs( FILE * pFile );
+    assert( Abc_FrameIsBridgeMode() );
+//    if ( fVerbose )
+//        Abc_Print( 1, "Cancelling previously sent model...\n" );
+    Gia_ManToBridgeBadAbs( stdout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Send abstracted model or send cancel.]
+
+  Description [Counter-example will be sent automatically when &vta terminates.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_VtaDumpAbsracted( Vta_Man_t * p, int fVerbose )
+{
+    char * pFileNameDef = "vabs.aig";
+    char * pFileName = p->pPars->pFileVabs ? p->pPars->pFileVabs : pFileNameDef;
+    Gia_Man_t * pAbs;
+    if ( fVerbose )
+        Abc_Print( 1, "Dumping abstracted model into file \"%s\"...\n", pFileName );
+    // create obj classes
+    Vec_IntFreeP( &p->pGia->vObjClasses );
+    p->pGia->vObjClasses = Gia_VtaFramesToAbs( (Vec_Vec_t *)p->vCores );
+    // create gate classes
+    Vec_IntFreeP( &p->pGia->vGateClasses );
+    p->pGia->vGateClasses = Gia_VtaConvertToGla( p->pGia, p->pGia->vObjClasses );
+    Vec_IntFreeP( &p->pGia->vObjClasses );
+    // create abstrated model
+    pAbs = Gia_ManDupAbsGates( p->pGia, p->pGia->vGateClasses );
+    Vec_IntFreeP( &p->pGia->vGateClasses );
+    // send it out
+    Gia_AigerWrite( pAbs, pFileName, 0, 0 );
+    Gia_ManStop( pAbs );
+}
+
+    
+/**Function*************************************************************
+
+  Synopsis    [Print memory report.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_VtaPrintMemory( Vta_Man_t * p )
+{
+    double memTot = 0;
+    double memAig = Gia_ManObjNum(p->pGia) * sizeof(Gia_Obj_t);
+    double memSat = sat_solver2_memory( p->pSat, 1 );
+    double memPro = sat_solver2_memory_proof( p->pSat );
+    double memMap = p->nObjsAlloc * sizeof(Vta_Obj_t) + p->nBins * sizeof(int);
+    double memOth = sizeof(Vta_Man_t);
+    memOth += Vec_IntCap(p->vOrder) * sizeof(int);
+    memOth += Vec_VecMemoryInt( (Vec_Vec_t *)p->vFrames );
+    memOth += Vec_BitCap(p->vSeenGla) * sizeof(int);
+    memOth += Vec_VecMemoryInt( (Vec_Vec_t *)p->vCores );
+    memOth += Vec_IntCap(p->vAddedNew) * sizeof(int);
+    memTot = memAig + memSat + memPro + memMap + memOth;
+    ABC_PRMP( "Memory: AIG     ", memAig, memTot );
+    ABC_PRMP( "Memory: SAT     ", memSat, memTot );
+    ABC_PRMP( "Memory: Proof   ", memPro, memTot );
+    ABC_PRMP( "Memory: Map     ", memMap, memTot );
+    ABC_PRMP( "Memory: Other   ", memOth, memTot );
+    ABC_PRMP( "Memory: TOTAL   ", memTot, memTot );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collect nodes/flops involved in different timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_VtaPerformInt( Gia_Man_t * pAig, Abs_Par_t * pPars )
+{
+    Vta_Man_t * p;
+    Vec_Int_t * vCore;
+    Abc_Cex_t * pCex = NULL;
+    int i, f, nConfls, Status, nObjOld, RetValue = -1, nCountNoChange = 0, fOneIsSent = 0;
+    abctime clk = Abc_Clock(), clk2;
+    // preconditions
+    assert( Gia_ManPoNum(pAig) == 1 );
+    assert( pPars->nFramesMax == 0 || pPars->nFramesStart <= pPars->nFramesMax );
+    if ( Gia_ObjIsConst0(Gia_ObjFanin0(Gia_ManPo(pAig,0))) )
+    {
+        if ( !Gia_ObjFaninC0(Gia_ManPo(pAig,0)) )
+        {
+            printf( "Sequential miter is trivially UNSAT.\n" );
+            return 1;
+        } 
+        ABC_FREE( pAig->pCexSeq );
+        pAig->pCexSeq = Abc_CexMakeTriv( Gia_ManRegNum(pAig), Gia_ManPiNum(pAig), 1, 0 );
+        printf( "Sequential miter is trivially SAT.\n" );
+        return 0;
+    }
+
+    // compute intial abstraction
+    if ( pAig->vObjClasses == NULL )
+    {
+        pAig->vObjClasses = Vec_IntAlloc( 5 );
+        Vec_IntPush( pAig->vObjClasses, 1 );
+        Vec_IntPush( pAig->vObjClasses, 3 );
+        Vec_IntPush( pAig->vObjClasses, 4 );
+        Vec_IntPush( pAig->vObjClasses, Gia_ObjFaninId0p(pAig, Gia_ManPo(pAig, 0)) );
+    }
+    // start the manager
+    p = Vga_ManStart( pAig, pPars );
+    // set runtime limit
+    if ( p->pPars->nTimeOut )
+        sat_solver2_set_runtime_limit( p->pSat, p->pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock() );
+    // perform initial abstraction
+    if ( p->pPars->fVerbose )
+    {
+        Abc_Print( 1, "Running variable-timeframe abstraction (VTA) with the following parameters:\n" );
+        Abc_Print( 1, "FramePast = %d  FrameMax = %d  ConfMax = %d  Timeout = %d  RatioMin = %d %%\n", 
+            pPars->nFramesPast, pPars->nFramesMax, pPars->nConfLimit, pPars->nTimeOut, pPars->nRatioMin );
+        Abc_Print( 1, "LearnStart = %d  LearnDelta = %d  LearnRatio = %d %%.\n", 
+            pPars->nLearnedStart, pPars->nLearnedDelta, pPars->nLearnedPerce );
+//        Abc_Print( 1, "Frame   %%   Abs   %%   Confl  Cex    SatVar   Core   F0   F1   F2  ...\n" );
+        Abc_Print( 1, " Frame   %%   Abs   %%   Confl  Cex   Vars   Clas   Lrns   Core     Time      Mem\n" );
+    }
+    assert( Vec_PtrSize(p->vFrames) > 0 );
+    for ( f = i = 0; !p->pPars->nFramesMax || f < p->pPars->nFramesMax; f++ )
+    {
+        int nConflsBeg = sat_solver2_nconflicts(p->pSat);
+        p->pPars->iFrame = f;
+        // realloc storage for abstraction marks
+        if ( f == p->nWords * 32 )
+            p->nWords = Vec_IntDoubleWidth( p->vSeens, p->nWords );
+
+        // create bookmark to be used for rollback
+        nObjOld = p->nObjs;
+        sat_solver2_bookmark( p->pSat );
+        Vec_IntClear( p->vAddedNew );
+
+        // load new timeframe
+        Vga_ManAddClausesOne( p, 0, f );
+        if ( f < Vec_PtrSize(p->vFrames) )
+            Vga_ManLoadSlice( p, (Vec_Int_t *)Vec_PtrEntry(p->vFrames, f), 0 );
+        else
+        {
+            for ( i = 1; i <= Abc_MinInt(p->pPars->nFramesPast, f); i++ )
+                Vga_ManLoadSlice( p, (Vec_Int_t *)Vec_PtrEntry(p->vCores, f-i), i );
+        }
+
+        // iterate as long as there are counter-examples
+        for ( i = 0; ; i++ )
+        { 
+            clk2 = Abc_Clock();
+            vCore = Vta_ManUnsatCore( Vga_ManGetOutLit(p, f), p->pSat, pPars->nConfLimit, pPars->fVerbose, &Status, &nConfls );
+            assert( (vCore != NULL) == (Status == 1) );
+            if ( Status == -1 ) // resource limit is reached
+            {
+                Vga_ManRollBack( p, nObjOld );
+                goto finish;
+            }
+            // check timeout
+            if ( p->pSat->nRuntimeLimit && Abc_Clock() > p->pSat->nRuntimeLimit )
+            {
+                Vga_ManRollBack( p, nObjOld );
+                goto finish;
+            }
+            if ( vCore != NULL )
+            {
+                p->timeUnsat += Abc_Clock() - clk2;
+                break;
+            }
+            p->timeSat += Abc_Clock() - clk2;
+            assert( Status == 0 );
+            p->nCexes++;
+            // perform the refinement
+            clk2 = Abc_Clock();
+            pCex = Vta_ManRefineAbstraction( p, f );
+            p->timeCex += Abc_Clock() - clk2;
+            if ( pCex != NULL )
+                goto finish;
+            // print the result (do not count it towards change)
+            Vta_ManAbsPrintFrame( p, NULL, f+1, sat_solver2_nconflicts(p->pSat)-nConflsBeg, i, Abc_Clock() - clk, p->pPars->fVerbose );
+        }
+        assert( Status == 1 );
+        // valid core is obtained
+        Vta_ManUnsatCoreRemap( p, vCore );
+        Vec_IntSort( vCore, 1 );
+        // update the SAT solver
+        sat_solver2_rollback( p->pSat );
+        // update storage
+        Vga_ManRollBack( p, nObjOld );
+        // load this timeframe
+        Vga_ManLoadSlice( p, vCore, 0 );
+        Vec_IntFree( vCore );
+
+        // run SAT solver
+        clk2 = Abc_Clock();
+        vCore = Vta_ManUnsatCore( Vga_ManGetOutLit(p, f), p->pSat, pPars->nConfLimit, p->pPars->fVerbose, &Status, &nConfls );
+        p->timeUnsat += Abc_Clock() - clk2;
+        assert( (vCore != NULL) == (Status == 1) );
+        if ( Status == -1 ) // resource limit is reached
+            break;
+        if ( Status == 0 )
+        {
+            Vta_ManSatVerify( p );
+            // make sure, there was no initial abstraction (otherwise, it was invalid)
+            assert( pAig->vObjClasses == NULL && f < p->pPars->nFramesStart );
+            pCex = Vga_ManDeriveCex( p );
+            break;
+        }
+        // add the core
+        Vta_ManUnsatCoreRemap( p, vCore );
+        // add in direct topological order
+        Vec_IntSort( vCore, 1 );
+        Vec_PtrPush( p->vCores, vCore );
+        // print the result
+        if ( Vta_ManAbsPrintFrame( p, vCore, f+1, sat_solver2_nconflicts(p->pSat)-nConflsBeg, i, Abc_Clock() - clk, p->pPars->fVerbose ) )
+        {
+            // reset the counter of frames without change
+            nCountNoChange = 1;
+            p->pPars->nFramesNoChange = 0;
+        }
+        else if ( ++nCountNoChange == 2 ) // time to send
+        {
+            p->pPars->nFramesNoChange++;
+            if ( Abc_FrameIsBridgeMode() )
+            {
+                // cancel old one if it was sent
+                if ( fOneIsSent )
+                    Gia_VtaSendCancel( p, pPars->fVerbose );
+                // send new one 
+                Gia_VtaSendAbsracted( p, pPars->fVerbose );
+                fOneIsSent = 1;
+            }
+        }
+        // dump the model
+        if ( p->pPars->fDumpVabs && (f & 1) )
+        {
+            char Command[1000];
+            Abc_FrameSetStatus( -1 );
+            Abc_FrameSetCex( NULL );
+            Abc_FrameSetNFrames( f+1 );
+            sprintf( Command, "write_status %s", Extra_FileNameGenericAppend((char *)(p->pPars->pFileVabs ? p->pPars->pFileVabs : "vtabs.aig"), ".status") );
+            Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command );
+            Gia_VtaDumpAbsracted( p, pPars->fVerbose );
+        }
+        // check if the number of objects is below limit
+        if ( p->nSeenGla >= Gia_ManCandNum(pAig) * (100-pPars->nRatioMin) / 100 )
+        {
+            Status = -1;
+            break;
+        }
+    }
+finish:
+    // analize the results
+    if ( pCex == NULL )
+    {
+        if ( p->pPars->fVerbose && Status == -1 )
+            printf( "\n" );
+        if ( Vec_PtrSize(p->vCores) == 0 )
+            Abc_Print( 1, "Abstraction is not produced because first frame is not solved.  " );
+        else
+        {
+            assert( Vec_PtrSize(p->vCores) > 0 );
+//            if ( pAig->vObjClasses != NULL )
+//                Abc_Print( 1, "Replacing the old abstraction by a new one.\n" );
+            Vec_IntFreeP( &pAig->vObjClasses );
+            pAig->vObjClasses = Gia_VtaFramesToAbs( (Vec_Vec_t *)p->vCores );
+            if ( Status == -1 )
+            {
+                if ( p->pPars->nTimeOut && Abc_Clock() >= p->pSat->nRuntimeLimit ) 
+                    Abc_Print( 1, "Timeout %d sec in frame %d with a %d-stable abstraction.    ", p->pPars->nTimeOut, f, p->pPars->nFramesNoChange );
+                else if ( pPars->nConfLimit && sat_solver2_nconflicts(p->pSat) >= pPars->nConfLimit )
+                    Abc_Print( 1, "Exceeded %d conflicts in frame %d with a %d-stable abstraction.  ", pPars->nConfLimit, f, p->pPars->nFramesNoChange );
+                else if ( p->nSeenGla >= Gia_ManCandNum(pAig) * (100-pPars->nRatioMin) / 100 )
+                    Abc_Print( 1, "The ratio of abstracted objects is less than %d %% in frame %d.  ", pPars->nRatioMin, f );
+                else
+                    Abc_Print( 1, "Abstraction stopped for unknown reason in frame %d.  ", f );
+            }
+            else
+            {
+                p->pPars->iFrame++;
+                Abc_Print( 1, "VTA completed %d frames with a %d-stable abstraction.  ", f, p->pPars->nFramesNoChange );
+            }
+        }
+    }
+    else
+    {
+        if ( p->pPars->fVerbose )
+            printf( "\n" );
+        ABC_FREE( p->pGia->pCexSeq );
+        p->pGia->pCexSeq = pCex;
+        if ( !Gia_ManVerifyCex( p->pGia, pCex, 0 ) )
+            Abc_Print( 1, "    Gia_VtaPerform(): CEX verification has failed!\n" );
+        Abc_Print( 1, "Counter-example detected in frame %d.  ", f );
+        p->pPars->iFrame = pCex->iFrame - 1;
+        Vec_IntFreeP( &pAig->vObjClasses );
+        RetValue = 0;
+    }
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+
+    if ( p->pPars->fVerbose )
+    {
+        p->timeOther = (Abc_Clock() - clk) - p->timeUnsat - p->timeSat - p->timeCex;
+        ABC_PRTP( "Runtime: Solver UNSAT", p->timeUnsat,  Abc_Clock() - clk );
+        ABC_PRTP( "Runtime: Solver SAT  ", p->timeSat,    Abc_Clock() - clk );
+        ABC_PRTP( "Runtime: Refinement  ", p->timeCex,    Abc_Clock() - clk );
+        ABC_PRTP( "Runtime: Other       ", p->timeOther,  Abc_Clock() - clk );
+        ABC_PRTP( "Runtime: TOTAL       ", Abc_Clock() - clk, Abc_Clock() - clk );
+        Gia_VtaPrintMemory( p );
+    }
+
+    Vga_ManStop( p );
+    fflush( stdout );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect nodes/flops involved in different timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_VtaPerform( Gia_Man_t * pAig, Abs_Par_t * pPars )
+{
+    int RetValue = -1;
+    if ( pAig->vObjClasses == NULL && pPars->fUseRollback )
+    {
+        int nFramesMaxOld = pPars->nFramesMax;
+        pPars->nFramesMax = pPars->nFramesStart;
+        RetValue = Gia_VtaPerformInt( pAig, pPars );
+        pPars->nFramesMax = nFramesMaxOld;
+    }
+    if ( RetValue == 0 )
+        return RetValue;
+    return Gia_VtaPerformInt( pAig, pPars );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/abs/module.make b/abc-build/src/proof/abs/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/abs/module.make
@@ -0,0 +1,16 @@
+SRC +=	src/proof/abs/absDup.c \
+	src/proof/abs/absGla.c \
+	src/proof/abs/absGlaOld.c \
+	src/proof/abs/absIter.c \
+	src/proof/abs/absOldCex.c \
+	src/proof/abs/absOldRef.c \
+	src/proof/abs/absOldSat.c \
+	src/proof/abs/absOldSim.c \
+	src/proof/abs/absOut.c \
+	src/proof/abs/absPth.c \
+	src/proof/abs/absRef.c \
+	src/proof/abs/absRefSelect.c \
+	src/proof/abs/absRpm.c \
+	src/proof/abs/absRpmOld.c \
+	src/proof/abs/absVta.c \
+	src/proof/abs/absUtil.c
diff --git a/abc-build/src/proof/bbr/bbr.h b/abc-build/src/proof/bbr/bbr.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/bbr/bbr.h
@@ -0,0 +1,93 @@
+/**CFile****************************************************************
+
+  FileName    [bbr.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD-based reachability analysis.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bbr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__bbr__bbr_h
+#define ABC__aig__bbr__bbr_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "aig/aig/aig.h"
+#include "aig/saig/saig.h"
+#include "bdd/cudd/cuddInt.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline DdNode * Aig_ObjGlobalBdd( Aig_Obj_t * pObj )  { return (DdNode *)pObj->pData; }
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== bbrImage.c ==========================================================*/
+typedef struct Bbr_ImageTree_t_  Bbr_ImageTree_t;
+extern Bbr_ImageTree_t * Bbr_bddImageStart( 
+    DdManager * dd, DdNode * bCare,
+    int nParts, DdNode ** pbParts,
+    int nVars, DdNode ** pbVars, int nBddMax, int fVerbose );
+extern DdNode *    Bbr_bddImageCompute( Bbr_ImageTree_t * pTree, DdNode * bCare );
+extern void        Bbr_bddImageTreeDelete( Bbr_ImageTree_t * pTree );
+extern DdNode *    Bbr_bddImageRead( Bbr_ImageTree_t * pTree );
+typedef struct Bbr_ImageTree2_t_  Bbr_ImageTree2_t;
+extern Bbr_ImageTree2_t * Bbr_bddImageStart2( 
+    DdManager * dd, DdNode * bCare,
+    int nParts, DdNode ** pbParts,
+    int nVars, DdNode ** pbVars, int fVerbose );
+extern DdNode *    Bbr_bddImageCompute2( Bbr_ImageTree2_t * pTree, DdNode * bCare );
+extern void        Bbr_bddImageTreeDelete2( Bbr_ImageTree2_t * pTree );
+extern DdNode *    Bbr_bddImageRead2( Bbr_ImageTree2_t * pTree );
+/*=== bbrNtbdd.c ==========================================================*/
+extern void        Aig_ManFreeGlobalBdds( Aig_Man_t * p, DdManager * dd );
+extern int         Aig_ManSizeOfGlobalBdds( Aig_Man_t * p );
+extern DdManager * Aig_ManComputeGlobalBdds( Aig_Man_t * p, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose );
+/*=== bbrReach.c ==========================================================*/
+extern int         Aig_ManVerifyUsingBdds( Aig_Man_t * p, Saig_ParBbr_t * pPars );
+extern void        Bbr_ManSetDefaultParams( Saig_ParBbr_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/bbr/bbrCex.c b/abc-build/src/proof/bbr/bbrCex.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/bbr/bbrCex.c
@@ -0,0 +1,172 @@
+/**CFile****************************************************************
+
+  FileName    [bbrCex.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD-based reachability analysis.]
+
+  Synopsis    [Procedures to derive a satisfiable counter-example.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bbrCex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bbr.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern DdNode * Bbr_bddComputeRangeCube( DdManager * dd, int iStart, int iStop );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the counter-example using the set of reached states.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Aig_ManVerifyUsingBddsCountExample( Aig_Man_t * p, DdManager * dd, 
+    DdNode ** pbParts, Vec_Ptr_t * vOnionRings, DdNode * bCubeFirst,
+    int iOutput, int fVerbose, int fSilent )
+{
+    Abc_Cex_t * pCex;
+    Aig_Obj_t * pObj;
+    Bbr_ImageTree_t * pTree;
+    DdNode * bCubeNs, * bState, * bImage;
+    DdNode * bTemp, * bVar, * bRing;
+    int i, v, RetValue, nPiOffset;
+    char * pValues;
+    abctime clk = Abc_Clock();
+//printf( "\nDeriving counter-example.\n" );
+
+    // allocate room for the counter-example
+    pCex = Abc_CexAlloc( Saig_ManRegNum(p), Saig_ManPiNum(p), Vec_PtrSize(vOnionRings)+1 );
+    pCex->iFrame = Vec_PtrSize(vOnionRings);
+    pCex->iPo = iOutput;
+    nPiOffset = Saig_ManRegNum(p) + Saig_ManPiNum(p) * Vec_PtrSize(vOnionRings);
+
+    // create the cube of NS variables
+    bCubeNs  = Bbr_bddComputeRangeCube( dd, Saig_ManCiNum(p), Saig_ManCiNum(p)+Saig_ManRegNum(p) );    Cudd_Ref( bCubeNs );
+    pTree = Bbr_bddImageStart( dd, bCubeNs, Saig_ManRegNum(p), pbParts, Saig_ManCiNum(p), dd->vars, 100000000, fVerbose );
+    Cudd_RecursiveDeref( dd, bCubeNs );
+    if ( pTree == NULL )
+    {
+        if ( !fSilent )
+            printf( "BDDs blew up during qualitification scheduling.  " );
+        return NULL;
+    }
+
+    // allocate room for the cube
+    pValues = ABC_ALLOC( char, dd->size );
+
+    // get the last cube
+    RetValue = Cudd_bddPickOneCube( dd, bCubeFirst, pValues );
+    assert( RetValue );
+
+    // write PIs of counter-example
+    Saig_ManForEachPi( p, pObj, i )
+        if ( pValues[i] == 1 )
+            Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+    nPiOffset -= Saig_ManPiNum(p);
+
+    // write state in terms of NS variables
+    bState = (dd)->one; Cudd_Ref( bState );
+    Saig_ManForEachLo( p, pObj, i )
+    {
+        bVar = Cudd_NotCond( dd->vars[Saig_ManCiNum(p)+i], pValues[Saig_ManPiNum(p)+i] != 1 );
+        bState = Cudd_bddAnd( dd, bTemp = bState, bVar );  Cudd_Ref( bState );
+        Cudd_RecursiveDeref( dd, bTemp ); 
+    }
+
+    // perform backward analysis
+    Vec_PtrForEachEntryReverse( DdNode *, vOnionRings, bRing, v )
+    { 
+        // compute the next states
+        bImage = Bbr_bddImageCompute( pTree, bState );           
+        if ( bImage == NULL )
+        {
+            Cudd_RecursiveDeref( dd, bState );
+            if ( !fSilent )
+                printf( "BDDs blew up during image computation.  " );
+            Bbr_bddImageTreeDelete( pTree );
+            ABC_FREE( pValues );
+            return NULL;
+        }
+        Cudd_Ref( bImage );
+        Cudd_RecursiveDeref( dd, bState );
+
+        // intersect with the previous set
+        bImage = Cudd_bddAnd( dd, bTemp = bImage, bRing );  Cudd_Ref( bImage );
+        Cudd_RecursiveDeref( dd, bTemp );
+
+        // find any assignment of the BDD
+        RetValue = Cudd_bddPickOneCube( dd, bImage, pValues );
+        assert( RetValue );
+        Cudd_RecursiveDeref( dd, bImage );
+
+        // write PIs of counter-example
+        Saig_ManForEachPi( p, pObj, i )
+            if ( pValues[i] == 1 )
+                Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+        nPiOffset -= Saig_ManPiNum(p);
+
+        // check that we get the init state
+        if ( v == 0 )
+        {
+            Saig_ManForEachLo( p, pObj, i )
+                assert( pValues[Saig_ManPiNum(p)+i] == 0 );
+            break;
+        }
+
+        // write state in terms of NS variables
+        bState = (dd)->one; Cudd_Ref( bState );
+        Saig_ManForEachLo( p, pObj, i )
+        {
+            bVar = Cudd_NotCond( dd->vars[Saig_ManCiNum(p)+i], pValues[Saig_ManPiNum(p)+i] != 1 );
+            bState = Cudd_bddAnd( dd, bTemp = bState, bVar );  Cudd_Ref( bState );
+            Cudd_RecursiveDeref( dd, bTemp ); 
+        }
+    }
+    // cleanup
+    Bbr_bddImageTreeDelete( pTree );
+    ABC_FREE( pValues );
+    // verify the counter example
+    if ( Vec_PtrSize(vOnionRings) < 1000 )
+    {
+    RetValue = Saig_ManVerifyCex( p, pCex );
+    if ( RetValue == 0 && !fSilent )
+        printf( "Aig_ManVerifyUsingBdds(): Counter-example verification has FAILED.\n" );
+    }
+    if ( fVerbose && !fSilent )
+    {
+    ABC_PRT( "Counter-example generation time", Abc_Clock() - clk );
+    }
+    return pCex;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/bbr/bbrImage.c b/abc-build/src/proof/bbr/bbrImage.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/bbr/bbrImage.c
@@ -0,0 +1,1327 @@
+/**CFile****************************************************************
+
+  FileName    [bbrImage.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD-based reachability analysis.]
+
+  Synopsis    [Performs image computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bbrImage.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bbr.h"
+#include "bdd/mtr/mtr.h"
+
+ABC_NAMESPACE_IMPL_START
+ 
+
+/* 
+    The ideas implemented in this file are inspired by the paper:
+    Pankaj Chauhan, Edmund Clarke, Somesh Jha, Jim Kukula, Tom Shiple, 
+    Helmut Veith, Dong Wang. Non-linear Quantification Scheduling in 
+    Image Computation. ICCAD, 2001.
+*/
+ 
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+typedef struct Bbr_ImageNode_t_  Bbr_ImageNode_t;
+typedef struct Bbr_ImagePart_t_  Bbr_ImagePart_t;
+typedef struct Bbr_ImageVar_t_   Bbr_ImageVar_t;
+
+struct Bbr_ImageTree_t_
+{
+    Bbr_ImageNode_t *   pRoot;      // the root of quantification tree
+    Bbr_ImageNode_t *   pCare;      // the leaf node with the care set
+    DdNode *            bCareSupp;  // the cube to quantify from the care
+    int                 fVerbose;   // the verbosity flag
+    int                 nNodesMax;  // the max number of nodes in one iter
+    int                 nNodesMaxT; // the overall max number of nodes
+    int                 nIter;      // the number of iterations with this tree
+    int                 nBddMax;    // the number of node to stop
+};
+
+struct Bbr_ImageNode_t_
+{
+    DdManager *         dd;         // the manager 
+    DdNode *            bCube;      // the cube to quantify
+    DdNode *            bImage;     // the partial image
+    Bbr_ImageNode_t *   pNode1;     // the first branch
+    Bbr_ImageNode_t *   pNode2;     // the second branch
+    Bbr_ImagePart_t *   pPart;      // the partition (temporary)
+};
+
+struct Bbr_ImagePart_t_
+{
+    DdNode *            bFunc;      // the partition
+    DdNode *            bSupp;      // the support of this partition
+    int                 nNodes;     // the number of BDD nodes
+    short               nSupp;      // the number of support variables
+    short               iPart;      // the number of this partition
+};
+
+struct Bbr_ImageVar_t_
+{
+    int                 iNum;       // the BDD index of this variable
+    DdNode *            bParts;     // the partition numbers
+    int                 nParts;     // the number of partitions
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#define     b0     Cudd_Not((dd)->one)
+#define     b1              (dd)->one
+
+#ifndef ABC_PRB
+#define ABC_PRB(dd,f)       printf("%s = ", #f); Bbr_bddPrint(dd,f); printf("\n")
+#endif
+
+/**AutomaticStart*************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static Bbr_ImagePart_t ** Bbr_CreateParts( DdManager * dd,
+    int nParts, DdNode ** pbParts, DdNode * bCare );
+static Bbr_ImageVar_t ** Bbr_CreateVars( DdManager * dd,
+    int nParts, Bbr_ImagePart_t ** pParts,
+    int nVars, DdNode ** pbVarsNs );
+static Bbr_ImageNode_t ** Bbr_CreateNodes( DdManager * dd, 
+    int nParts, Bbr_ImagePart_t ** pParts, 
+    int nVars,  Bbr_ImageVar_t ** pVars );
+static void Bbr_DeleteParts_rec( Bbr_ImageNode_t * pNode );
+static int Bbr_BuildTreeNode( DdManager * dd, 
+    int nNodes, Bbr_ImageNode_t ** pNodes, 
+    int nVars,  Bbr_ImageVar_t ** pVars, int * pfStop, int nBddMax );
+static Bbr_ImageNode_t * Bbr_MergeTopNodes( DdManager * dd, 
+    int nNodes, Bbr_ImageNode_t ** pNodes );
+static void Bbr_bddImageTreeDelete_rec( Bbr_ImageNode_t * pNode );
+static int Bbr_bddImageCompute_rec( Bbr_ImageTree_t * pTree, Bbr_ImageNode_t * pNode );
+static int Bbr_FindBestVariable( DdManager * dd,
+    int nNodes, Bbr_ImageNode_t ** pNodes, 
+    int nVars,  Bbr_ImageVar_t ** pVars );
+static void Bbr_FindBestPartitions( DdManager * dd, DdNode * bParts, 
+    int nNodes, Bbr_ImageNode_t ** pNodes, 
+    int * piNode1, int * piNode2 );
+static Bbr_ImageNode_t * Bbr_CombineTwoNodes( DdManager * dd, DdNode * bCube,
+    Bbr_ImageNode_t * pNode1, Bbr_ImageNode_t * pNode2 );
+
+static void Bbr_bddImagePrintLatchDependency( DdManager * dd, DdNode * bCare,
+    int nParts, DdNode ** pbParts,
+    int nVars, DdNode ** pbVars );
+static void Bbr_bddImagePrintLatchDependencyOne( DdManager * dd, DdNode * bFunc, 
+    DdNode * bVarsCs, DdNode * bVarsNs, int iPart );
+
+static void Bbr_bddImagePrintTree( Bbr_ImageTree_t * pTree );
+static void Bbr_bddImagePrintTree_rec( Bbr_ImageNode_t * pNode, int nOffset );
+
+static void Bbr_bddPrint( DdManager * dd, DdNode * F );
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the image computation using tree-based scheduling.]
+
+  Description [This procedure starts the image computation. It uses
+  the given care set to test-run the image computation and creates the 
+  quantification tree by scheduling variable quantifications. The tree can 
+  be used to compute images for other care sets without rescheduling.
+  In this case, Bbr_bddImageCompute() should be called.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bbr_ImageTree_t * Bbr_bddImageStart( 
+    DdManager * dd, DdNode * bCare, // the care set
+    int nParts, DdNode ** pbParts,  // the partitions for image computation
+    int nVars, DdNode ** pbVars, int nBddMax, int fVerbose )   // the NS and parameter variables (not quantified!)
+{
+    Bbr_ImageTree_t * pTree;
+    Bbr_ImagePart_t ** pParts;
+    Bbr_ImageVar_t ** pVars;
+    Bbr_ImageNode_t ** pNodes, * pCare;
+    int fStop, v;
+
+    if ( fVerbose && dd->size <= 80 )
+        Bbr_bddImagePrintLatchDependency( dd, bCare, nParts, pbParts, nVars, pbVars );
+
+    // create variables, partitions and leaf nodes
+    pParts = Bbr_CreateParts( dd, nParts, pbParts, bCare );
+    pVars  = Bbr_CreateVars( dd, nParts + 1, pParts, nVars, pbVars );
+    pNodes = Bbr_CreateNodes( dd, nParts + 1, pParts, dd->size, pVars );
+    pCare  = pNodes[nParts];
+
+    // process the nodes
+    while ( Bbr_BuildTreeNode( dd, nParts + 1, pNodes, dd->size, pVars, &fStop, nBddMax ) );
+
+    // consider the case of BDD node blowup
+    if ( fStop )
+    {
+        for ( v = 0; v < dd->size; v++ )
+            if ( pVars[v] )
+                ABC_FREE( pVars[v] );
+        ABC_FREE( pVars );
+        for ( v = 0; v <= nParts; v++ )
+            if ( pNodes[v] )
+            {
+                Bbr_DeleteParts_rec( pNodes[v] );
+                Bbr_bddImageTreeDelete_rec( pNodes[v] );
+            }
+        ABC_FREE( pNodes );
+        ABC_FREE( pParts );
+        return NULL;
+    }
+
+    // make sure the variables are gone
+    for ( v = 0; v < dd->size; v++ )
+        assert( pVars[v] == NULL );
+    ABC_FREE( pVars );
+    
+    // create the tree
+    pTree = ABC_ALLOC( Bbr_ImageTree_t, 1 );
+    memset( pTree, 0, sizeof(Bbr_ImageTree_t) );
+    pTree->pCare = pCare;
+    pTree->nBddMax = nBddMax;
+    pTree->fVerbose = fVerbose;
+
+    // merge the topmost nodes
+    while ( (pTree->pRoot = Bbr_MergeTopNodes( dd, nParts + 1, pNodes )) == NULL );
+
+    // make sure the nodes are gone
+    for ( v = 0; v < nParts + 1; v++ )
+        assert( pNodes[v] == NULL );
+    ABC_FREE( pNodes );
+
+//    if ( fVerbose )
+//        Bbr_bddImagePrintTree( pTree );
+
+    // set the support of the care set
+    pTree->bCareSupp = Cudd_Support( dd, bCare );  Cudd_Ref( pTree->bCareSupp );
+
+    // clean the partitions
+    Bbr_DeleteParts_rec( pTree->pRoot );
+    ABC_FREE( pParts );
+
+    return pTree;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the image.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Bbr_bddImageCompute( Bbr_ImageTree_t * pTree, DdNode * bCare )
+{
+    DdManager * dd = pTree->pCare->dd;
+    DdNode * bSupp, * bRem;
+
+    pTree->nIter++;
+
+    // make sure the supports are okay
+    bSupp = Cudd_Support( dd, bCare );        Cudd_Ref( bSupp );
+    if ( bSupp != pTree->bCareSupp )
+    {
+        bRem = Cudd_bddExistAbstract( dd, bSupp, pTree->bCareSupp );  Cudd_Ref( bRem );
+        if ( bRem != b1 )
+        {
+printf( "Original care set support: " );
+ABC_PRB( dd, pTree->bCareSupp );
+printf( "Current care set support: " );
+ABC_PRB( dd, bSupp );
+            Cudd_RecursiveDeref( dd, bSupp );
+            Cudd_RecursiveDeref( dd, bRem );
+            printf( "The care set depends on some vars that were not in the care set during scheduling.\n" );
+            return NULL;
+        }
+        Cudd_RecursiveDeref( dd, bRem );
+    }
+    Cudd_RecursiveDeref( dd, bSupp );
+
+    // remove the previous image
+    Cudd_RecursiveDeref( dd, pTree->pCare->bImage );
+    pTree->pCare->bImage = bCare;   Cudd_Ref( bCare );
+
+    // compute the image
+    pTree->nNodesMax = 0;
+    if ( !Bbr_bddImageCompute_rec( pTree, pTree->pRoot ) )
+        return NULL;
+    if ( pTree->nNodesMaxT < pTree->nNodesMax )
+        pTree->nNodesMaxT = pTree->nNodesMax;
+
+//    if ( pTree->fVerbose )
+//        printf( "Iter %2d : Max nodes = %5d.\n", pTree->nIter, pTree->nNodesMax );
+    return pTree->pRoot->bImage;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Delete the tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbr_bddImageTreeDelete( Bbr_ImageTree_t * pTree )
+{
+    if ( pTree->bCareSupp )
+        Cudd_RecursiveDeref( pTree->pRoot->dd, pTree->bCareSupp );
+    Bbr_bddImageTreeDelete_rec( pTree->pRoot );
+    ABC_FREE( pTree );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the image from the tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Bbr_bddImageRead( Bbr_ImageTree_t * pTree )
+{
+    return pTree->pRoot->bImage;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Outputs the BDD in a readable format.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void Bbr_bddPrint( DdManager * dd, DdNode * F )
+{
+    DdGen * Gen;
+    int * Cube;
+    CUDD_VALUE_TYPE Value;
+    int nVars = dd->size;
+    int fFirstCube = 1;
+    int i;
+
+    if ( F == NULL )
+    {
+        printf("NULL");
+        return;
+    }
+    if ( F == b0 )
+    {
+        printf("Constant 0");
+        return;
+    }
+    if ( F == b1 )
+    {
+        printf("Constant 1");
+        return;
+    }
+
+    Cudd_ForeachCube( dd, F, Gen, Cube, Value )
+    {
+        if ( fFirstCube )
+            fFirstCube = 0;
+        else
+//          Output << " + ";
+            printf( " + " );
+
+        for ( i = 0; i < nVars; i++ )
+            if ( Cube[i] == 0 )
+                printf( "[%d]'", i );
+//              printf( "%c'", (char)('a'+i) );
+            else if ( Cube[i] == 1 )
+                printf( "[%d]", i );
+//              printf( "%c", (char)('a'+i) );
+    }
+
+//  printf("\n");
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static Functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+  Synopsis    [Creates partitions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bbr_ImagePart_t ** Bbr_CreateParts( DdManager * dd,
+    int nParts, DdNode ** pbParts, DdNode * bCare )
+{
+    Bbr_ImagePart_t ** pParts;
+    int i;
+
+    // start the partitions
+    pParts = ABC_ALLOC( Bbr_ImagePart_t *, nParts + 1 );
+    // create structures for each variable
+    for ( i = 0; i < nParts; i++ )
+    {
+        pParts[i] = ABC_ALLOC( Bbr_ImagePart_t, 1 );
+        pParts[i]->bFunc  = pbParts[i];                           Cudd_Ref( pParts[i]->bFunc );
+        pParts[i]->bSupp  = Cudd_Support( dd, pParts[i]->bFunc ); Cudd_Ref( pParts[i]->bSupp );
+        pParts[i]->nSupp  = Cudd_SupportSize( dd, pParts[i]->bSupp );
+        pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc );
+        pParts[i]->iPart  = i;
+    }
+    // add the care set as the last partition
+    pParts[nParts] = ABC_ALLOC( Bbr_ImagePart_t, 1 );
+    pParts[nParts]->bFunc = bCare;                                     Cudd_Ref( pParts[nParts]->bFunc );
+    pParts[nParts]->bSupp = Cudd_Support( dd, pParts[nParts]->bFunc ); Cudd_Ref( pParts[nParts]->bSupp );
+    pParts[nParts]->nSupp = Cudd_SupportSize( dd, pParts[nParts]->bSupp );
+    pParts[nParts]->nNodes = Cudd_DagSize( pParts[nParts]->bFunc );
+    pParts[nParts]->iPart  = nParts;
+    return pParts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bbr_ImageVar_t ** Bbr_CreateVars( DdManager * dd,
+    int nParts, Bbr_ImagePart_t ** pParts,
+    int nVars, DdNode ** pbVars )
+{
+    Bbr_ImageVar_t ** pVars;
+    DdNode ** pbFuncs;
+    DdNode * bCubeNs, * bSupp, * bParts, * bTemp, * bSuppTemp;
+    int nVarsTotal, iVar, p, Counter;
+
+    // put all the functions into one array
+    pbFuncs = ABC_ALLOC( DdNode *, nParts );
+    for ( p = 0; p < nParts; p++ )
+        pbFuncs[p] = pParts[p]->bSupp;
+    bSupp = Cudd_VectorSupport( dd, pbFuncs, nParts );  Cudd_Ref( bSupp );
+    ABC_FREE( pbFuncs );
+
+    // remove the NS vars
+    bCubeNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars );        Cudd_Ref( bCubeNs );
+    bSupp = Cudd_bddExistAbstract( dd, bTemp = bSupp, bCubeNs );     Cudd_Ref( bSupp );
+    Cudd_RecursiveDeref( dd, bTemp );
+    Cudd_RecursiveDeref( dd, bCubeNs );
+
+    // get the number of I and CS variables to be quantified
+    nVarsTotal = Cudd_SupportSize( dd, bSupp );
+
+    // start the variables
+    pVars = ABC_ALLOC( Bbr_ImageVar_t *, dd->size );
+    memset( pVars, 0, sizeof(Bbr_ImageVar_t *) * dd->size );
+    // create structures for each variable
+    for ( bSuppTemp = bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) )
+    {
+        iVar = bSuppTemp->index;
+        pVars[iVar] = ABC_ALLOC( Bbr_ImageVar_t, 1 );
+        pVars[iVar]->iNum = iVar;
+        // collect all the parts this var belongs to
+        Counter = 0;
+        bParts = b1; Cudd_Ref( bParts );
+        for ( p = 0; p < nParts; p++ )
+            if ( Cudd_bddLeq( dd, pParts[p]->bSupp, dd->vars[bSuppTemp->index] ) )
+            {
+                bParts = Cudd_bddAnd( dd, bTemp = bParts, dd->vars[p] );  Cudd_Ref( bParts );
+                Cudd_RecursiveDeref( dd, bTemp );
+                Counter++;
+            }
+        pVars[iVar]->bParts = bParts; // takes ref
+        pVars[iVar]->nParts = Counter;
+    }
+    Cudd_RecursiveDeref( dd, bSupp );
+    return pVars;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bbr_ImageNode_t ** Bbr_CreateNodes( DdManager * dd, 
+    int nParts, Bbr_ImagePart_t ** pParts, 
+    int nVars,  Bbr_ImageVar_t ** pVars )
+{
+    Bbr_ImageNode_t ** pNodes;
+    Bbr_ImageNode_t * pNode;
+    DdNode * bTemp;
+    int i, v, iPart;
+/*
+    DdManager *         dd;       // the manager 
+    DdNode *            bCube;    // the cube to quantify
+    DdNode *            bImage;   // the partial image
+    Bbr_ImageNode_t * pNode1;   // the first branch
+    Bbr_ImageNode_t * pNode2;   // the second branch
+    Bbr_ImagePart_t * pPart;    // the partition (temporary)
+*/
+    // start the partitions
+    pNodes = ABC_ALLOC( Bbr_ImageNode_t *, nParts );
+    // create structures for each leaf nodes
+    for ( i = 0; i < nParts; i++ )
+    {
+        pNodes[i] = ABC_ALLOC( Bbr_ImageNode_t, 1 );
+        memset( pNodes[i], 0, sizeof(Bbr_ImageNode_t) );
+        pNodes[i]->dd    = dd;
+        pNodes[i]->pPart = pParts[i];
+    }
+    // find the quantification cubes for each leaf node
+    for ( v = 0; v < nVars; v++ )
+    {
+        if ( pVars[v] == NULL )
+            continue;
+        assert( pVars[v]->nParts > 0 );
+        if ( pVars[v]->nParts > 1 )
+            continue;
+        iPart = pVars[v]->bParts->index;
+        if ( pNodes[iPart]->bCube == NULL )
+        {
+            pNodes[iPart]->bCube = dd->vars[v];   
+            Cudd_Ref( dd->vars[v] );
+        }
+        else
+        {
+            pNodes[iPart]->bCube = Cudd_bddAnd( dd, bTemp = pNodes[iPart]->bCube, dd->vars[v] );  
+            Cudd_Ref( pNodes[iPart]->bCube );
+            Cudd_RecursiveDeref( dd, bTemp );
+        }
+        // remove these  variables
+        Cudd_RecursiveDeref( dd, pVars[v]->bParts );
+        ABC_FREE( pVars[v] );
+    }
+
+    // assign the leaf node images
+    for ( i = 0; i < nParts; i++ )
+    {
+        pNode = pNodes[i];
+        if ( pNode->bCube )
+        {
+            // update the partition
+            pParts[i]->bFunc = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bFunc, pNode->bCube );
+            Cudd_Ref( pParts[i]->bFunc );
+            Cudd_RecursiveDeref( dd, bTemp );
+            // update the support the partition
+            pParts[i]->bSupp = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bSupp, pNode->bCube ); 
+            Cudd_Ref( pParts[i]->bSupp );
+            Cudd_RecursiveDeref( dd, bTemp );
+            // update the numbers
+            pParts[i]->nSupp  = Cudd_SupportSize( dd, pParts[i]->bSupp );
+            pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc );
+            // get rid of the cube
+            // save the last (care set) quantification cube
+            if ( i < nParts - 1 )
+            {
+                Cudd_RecursiveDeref( dd, pNode->bCube );
+                pNode->bCube = NULL;
+            }
+        }
+        // copy the function
+        pNode->bImage = pParts[i]->bFunc;   Cudd_Ref( pNode->bImage );
+    }
+/*
+    for ( i = 0; i < nParts; i++ )
+    {
+        pNode = pNodes[i];
+ABC_PRB( dd, pNode->bCube );
+ABC_PRB( dd, pNode->pPart->bFunc );
+ABC_PRB( dd, pNode->pPart->bSupp );
+printf( "\n" );
+    }
+*/
+    return pNodes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Delete the partitions from the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbr_DeleteParts_rec( Bbr_ImageNode_t * pNode )
+{
+    Bbr_ImagePart_t * pPart;
+    if ( pNode->pNode1 )
+        Bbr_DeleteParts_rec( pNode->pNode1 );
+    if ( pNode->pNode2 )
+        Bbr_DeleteParts_rec( pNode->pNode2 );
+    pPart = pNode->pPart;
+    Cudd_RecursiveDeref( pNode->dd, pPart->bFunc );
+    Cudd_RecursiveDeref( pNode->dd, pPart->bSupp );
+    ABC_FREE( pNode->pPart );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Delete the partitions from the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbr_bddImageTreeDelete_rec( Bbr_ImageNode_t * pNode )
+{
+    if ( pNode->pNode1 )
+        Bbr_bddImageTreeDelete_rec( pNode->pNode1 );
+    if ( pNode->pNode2 )
+        Bbr_bddImageTreeDelete_rec( pNode->pNode2 );
+    if ( pNode->bCube )
+        Cudd_RecursiveDeref( pNode->dd, pNode->bCube );
+    if ( pNode->bImage )
+        Cudd_RecursiveDeref( pNode->dd, pNode->bImage );
+    assert( pNode->pPart == NULL );
+    ABC_FREE( pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recompute the image.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bbr_bddImageCompute_rec( Bbr_ImageTree_t * pTree, Bbr_ImageNode_t * pNode )
+{
+    DdManager * dd = pNode->dd;
+    DdNode * bTemp;
+    int nNodes;
+
+    // trivial case
+    if ( pNode->pNode1 == NULL )
+    {
+        if ( pNode->bCube )
+        {
+            pNode->bImage = Cudd_bddExistAbstract( dd, bTemp = pNode->bImage, pNode->bCube ); 
+            Cudd_Ref( pNode->bImage );
+            Cudd_RecursiveDeref( dd, bTemp );
+        }
+        return 1;
+    }
+
+    // compute the children
+    if ( pNode->pNode1 )
+        if ( !Bbr_bddImageCompute_rec( pTree, pNode->pNode1 ) )
+            return 0;
+    if ( pNode->pNode2 )
+        if ( !Bbr_bddImageCompute_rec( pTree, pNode->pNode2 ) )
+            return 0;
+
+    // clean the old image
+    if ( pNode->bImage )
+        Cudd_RecursiveDeref( dd, pNode->bImage );
+    pNode->bImage = NULL;
+
+    // compute the new image
+    if ( pNode->bCube )
+        pNode->bImage = Cudd_bddAndAbstract( dd, 
+            pNode->pNode1->bImage, pNode->pNode2->bImage, pNode->bCube );
+    else
+        pNode->bImage = Cudd_bddAnd( dd, pNode->pNode1->bImage, pNode->pNode2->bImage );
+    Cudd_Ref( pNode->bImage );
+
+    if ( pTree->fVerbose )
+    {
+        nNodes = Cudd_DagSize( pNode->bImage );
+        if ( pTree->nNodesMax < nNodes )
+            pTree->nNodesMax = nNodes;
+    }
+    if ( dd->keys-dd->dead > (unsigned)pTree->nBddMax )
+        return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Builds the tree.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bbr_BuildTreeNode( DdManager * dd, 
+    int nNodes, Bbr_ImageNode_t ** pNodes, 
+    int nVars,  Bbr_ImageVar_t ** pVars, int * pfStop, int nBddMax )
+{
+    Bbr_ImageNode_t * pNode1, * pNode2;
+    Bbr_ImageVar_t * pVar;
+    Bbr_ImageNode_t * pNode;
+    DdNode * bCube, * bTemp, * bSuppTemp;//, * bParts;
+    int iNode1, iNode2;
+    int iVarBest, nSupp, v;
+
+    // find the best variable
+    iVarBest = Bbr_FindBestVariable( dd, nNodes, pNodes, nVars, pVars );
+    if ( iVarBest == -1 )
+        return 0;
+/*
+for ( v = 0; v < nVars; v++ )
+{
+    DdNode * bSupp;
+    if ( pVars[v] == NULL )
+        continue;
+    printf( "%3d :", v );
+    printf( "%3d ", pVars[v]->nParts );
+    bSupp = Cudd_Support( dd, pVars[v]->bParts );  Cudd_Ref( bSupp );
+    Bbr_bddPrint( dd, bSupp ); printf( "\n" );
+    Cudd_RecursiveDeref( dd, bSupp );
+}
+*/
+    pVar = pVars[iVarBest];
+
+    // this var cannot appear in one partition only
+    nSupp = Cudd_SupportSize( dd, pVar->bParts );
+    assert( nSupp == pVar->nParts );
+    assert( nSupp != 1 );
+//printf( "var = %d  supp = %d\n\n", iVarBest, nSupp );
+
+    // if it appears in only two partitions, quantify it
+    if ( pVar->nParts == 2 )
+    {
+        // get the nodes
+        iNode1 = pVar->bParts->index;
+        iNode2 = cuddT(pVar->bParts)->index;
+        pNode1 = pNodes[iNode1];
+        pNode2 = pNodes[iNode2];
+
+        // get the quantification cube
+        bCube = dd->vars[pVar->iNum];    Cudd_Ref( bCube );
+        // add the variables that appear only in these partitions
+        for ( v = 0; v < nVars; v++ )
+            if ( pVars[v] && v != iVarBest && pVars[v]->bParts == pVars[iVarBest]->bParts )
+            {
+                // add this var
+                bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[pVars[v]->iNum] );   Cudd_Ref( bCube );
+                Cudd_RecursiveDeref( dd, bTemp );
+                // clean this var
+                Cudd_RecursiveDeref( dd, pVars[v]->bParts );
+                ABC_FREE( pVars[v] );
+            }
+        // clean the best var
+        Cudd_RecursiveDeref( dd, pVars[iVarBest]->bParts );
+        ABC_FREE( pVars[iVarBest] );
+
+        // combines two nodes
+        pNode = Bbr_CombineTwoNodes( dd, bCube, pNode1, pNode2 );
+        Cudd_RecursiveDeref( dd, bCube );
+    }
+    else // if ( pVar->nParts > 2 )
+    {
+        // find two smallest BDDs that have this var
+        Bbr_FindBestPartitions( dd, pVar->bParts, nNodes, pNodes, &iNode1, &iNode2 );
+        pNode1 = pNodes[iNode1];
+        pNode2 = pNodes[iNode2];
+//printf( "smallest bdds with this var: %d %d\n", iNode1, iNode2 );
+/*
+        // it is not possible that a var appears only in these two
+        // otherwise, it would have a different cost
+        bParts = Cudd_bddAnd( dd, dd->vars[iNode1], dd->vars[iNode2] ); Cudd_Ref( bParts );
+        for ( v = 0; v < nVars; v++ )
+            if ( pVars[v] && pVars[v]->bParts == bParts )
+                assert( 0 );
+        Cudd_RecursiveDeref( dd, bParts );
+*/
+        // combines two nodes
+        pNode = Bbr_CombineTwoNodes( dd, b1, pNode1, pNode2 );
+    }
+
+    // clean the old nodes
+    pNodes[iNode1] = pNode;
+    pNodes[iNode2] = NULL;
+//printf( "Removing node %d (leaving node %d)\n", iNode2, iNode1 );
+    
+    // update the variables that appear in pNode[iNode2]
+    for ( bSuppTemp = pNode2->pPart->bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) )
+    {
+        pVar = pVars[bSuppTemp->index];
+        if ( pVar == NULL ) // this variable is not be quantified
+            continue;
+        // quantify this var
+        assert( Cudd_bddLeq( dd, pVar->bParts, dd->vars[iNode2] ) );
+        pVar->bParts = Cudd_bddExistAbstract( dd, bTemp = pVar->bParts, dd->vars[iNode2] ); Cudd_Ref( pVar->bParts );
+        Cudd_RecursiveDeref( dd, bTemp );
+        // add the new var
+        pVar->bParts = Cudd_bddAnd( dd, bTemp = pVar->bParts, dd->vars[iNode1] ); Cudd_Ref( pVar->bParts );
+        Cudd_RecursiveDeref( dd, bTemp );
+        // update the score
+        pVar->nParts = Cudd_SupportSize( dd, pVar->bParts );
+    }
+
+    *pfStop = 0;
+    if ( dd->keys-dd->dead > (unsigned)nBddMax )
+    {
+        *pfStop = 1;
+        return 0;
+    }
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Merges the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bbr_ImageNode_t * Bbr_MergeTopNodes(
+    DdManager * dd, int nNodes, Bbr_ImageNode_t ** pNodes )
+{
+    Bbr_ImageNode_t * pNode;
+    int n1 = -1, n2 = -1, n;
+
+    // find the first and the second non-empty spots
+    for ( n = 0; n < nNodes; n++ )
+        if ( pNodes[n] )
+        {
+            if ( n1 == -1 )
+                n1 = n;
+            else if ( n2 == -1 )
+            {
+                n2 = n;
+                break;
+            }
+        }
+    assert( n1 != -1 );
+    // check the situation when only one such node is detected
+    if ( n2 == -1 )
+    {
+        // save the node
+        pNode = pNodes[n1];
+        // clean the node
+        pNodes[n1] = NULL;
+        return pNode;
+    }
+  
+    // combines two nodes
+    pNode = Bbr_CombineTwoNodes( dd, b1, pNodes[n1], pNodes[n2] );
+
+    // clean the old nodes
+    pNodes[n1] = pNode;
+    pNodes[n2] = NULL;
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bbr_ImageNode_t * Bbr_CombineTwoNodes( DdManager * dd, DdNode * bCube,
+    Bbr_ImageNode_t * pNode1, Bbr_ImageNode_t * pNode2 )
+{
+    Bbr_ImageNode_t * pNode;
+    Bbr_ImagePart_t * pPart;
+
+    // create a new partition
+    pPart = ABC_ALLOC( Bbr_ImagePart_t, 1 );
+    memset( pPart, 0, sizeof(Bbr_ImagePart_t) );
+    // create the function
+    pPart->bFunc = Cudd_bddAndAbstract( dd, pNode1->pPart->bFunc, pNode2->pPart->bFunc, bCube );
+    Cudd_Ref( pPart->bFunc );
+    // update the support the partition
+    pPart->bSupp = Cudd_bddAndAbstract( dd, pNode1->pPart->bSupp, pNode2->pPart->bSupp, bCube );
+    Cudd_Ref( pPart->bSupp );
+    // update the numbers
+    pPart->nSupp  = Cudd_SupportSize( dd, pPart->bSupp );
+    pPart->nNodes = Cudd_DagSize( pPart->bFunc );
+    pPart->iPart = -1;
+/*
+ABC_PRB( dd, pNode1->pPart->bSupp );
+ABC_PRB( dd, pNode2->pPart->bSupp );
+ABC_PRB( dd, pPart->bSupp );
+*/
+    // create a new node
+    pNode = ABC_ALLOC( Bbr_ImageNode_t, 1 );
+    memset( pNode, 0, sizeof(Bbr_ImageNode_t) );
+    pNode->dd     = dd;
+    pNode->pPart  = pPart;
+    pNode->pNode1 = pNode1;
+    pNode->pNode2 = pNode2;
+    // compute the image
+    pNode->bImage = Cudd_bddAndAbstract( dd, pNode1->bImage, pNode2->bImage, bCube ); 
+    Cudd_Ref( pNode->bImage );
+    // save the cube
+    if ( bCube != b1 )
+    {
+        pNode->bCube = bCube;   Cudd_Ref( bCube );
+    }
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the best variable.]
+
+  Description [The variables is the best if the sum of squares of the
+  BDD sizes of the partitions, in which it participates, is the minimum.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bbr_FindBestVariable( DdManager * dd,
+    int nNodes, Bbr_ImageNode_t ** pNodes, 
+    int nVars,  Bbr_ImageVar_t ** pVars )
+{
+    DdNode * bTemp;
+    int iVarBest, v;
+    double CostBest, CostCur;
+
+    CostBest = 100000000000000.0;
+    iVarBest = -1;
+
+    // check if there are two-variable partitions
+    for ( v = 0; v < nVars; v++ )
+        if ( pVars[v] && pVars[v]->nParts == 2 )
+        {
+            CostCur = 0;
+            for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) )
+                CostCur += pNodes[bTemp->index]->pPart->nNodes * 
+                           pNodes[bTemp->index]->pPart->nNodes;
+            if ( CostBest > CostCur )
+            {
+                CostBest = CostCur;
+                iVarBest = v;
+            }
+        }
+    if ( iVarBest >= 0 )
+        return iVarBest;
+
+    // find other partition
+    for ( v = 0; v < nVars; v++ )
+        if ( pVars[v] )
+        {
+            assert( pVars[v]->nParts > 1 );
+            CostCur = 0;
+            for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) )
+                CostCur += pNodes[bTemp->index]->pPart->nNodes * 
+                           pNodes[bTemp->index]->pPart->nNodes;
+            if ( CostBest > CostCur )
+            {
+                CostBest = CostCur;
+                iVarBest = v;
+            }
+        }
+    return iVarBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes two smallest partions that have this var.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbr_FindBestPartitions( DdManager * dd, DdNode * bParts, 
+    int nNodes, Bbr_ImageNode_t ** pNodes, 
+    int * piNode1, int * piNode2 )
+{
+    DdNode * bTemp;
+    int iPart1, iPart2;
+    int CostMin1, CostMin2, Cost;
+
+    // go through the partitions
+    iPart1 = iPart2 = -1;
+    CostMin1 = CostMin2 = 1000000;
+    for ( bTemp = bParts; bTemp != b1; bTemp = cuddT(bTemp) )
+    {
+        Cost = pNodes[bTemp->index]->pPart->nNodes;
+        if ( CostMin1 > Cost )
+        {
+            CostMin2 = CostMin1;    iPart2 = iPart1;
+            CostMin1 = Cost;        iPart1 = bTemp->index;
+        }
+        else if ( CostMin2 > Cost )
+        {
+            CostMin2 = Cost;        iPart2 = bTemp->index;
+        }
+    }
+
+    *piNode1 = iPart1;
+    *piNode2 = iPart2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the latch dependency matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbr_bddImagePrintLatchDependency( 
+    DdManager * dd, DdNode * bCare, // the care set
+    int nParts, DdNode ** pbParts,  // the partitions for image computation
+    int nVars, DdNode ** pbVars )   // the NS and parameter variables (not quantified!)
+{
+    int i;
+    DdNode * bVarsCs, * bVarsNs;
+
+    bVarsCs = Cudd_Support( dd, bCare );                       Cudd_Ref( bVarsCs );
+    bVarsNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars );  Cudd_Ref( bVarsNs );
+
+    printf( "The latch dependency matrix:\n" );
+    printf( "Partitions = %d   Variables: total = %d  non-quantifiable = %d\n",
+        nParts, dd->size, nVars );
+    printf( "     : " );
+    for ( i = 0; i < dd->size; i++ )
+        printf( "%d", i % 10 );
+    printf( "\n" );
+
+    for ( i = 0; i < nParts; i++ )
+        Bbr_bddImagePrintLatchDependencyOne( dd, pbParts[i], bVarsCs, bVarsNs, i );
+    Bbr_bddImagePrintLatchDependencyOne( dd, bCare, bVarsCs, bVarsNs, nParts );
+
+    Cudd_RecursiveDeref( dd, bVarsCs );
+    Cudd_RecursiveDeref( dd, bVarsNs );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints one row of the latch dependency matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbr_bddImagePrintLatchDependencyOne(
+    DdManager * dd, DdNode * bFunc,      // the function
+    DdNode * bVarsCs, DdNode * bVarsNs,  // the current/next state vars
+    int iPart )
+{
+    DdNode * bSupport;
+    int v;
+    bSupport = Cudd_Support( dd, bFunc );  Cudd_Ref( bSupport );
+    printf( " %3d : ", iPart );
+    for ( v = 0; v < dd->size; v++ )
+    {
+        if ( Cudd_bddLeq( dd, bSupport, dd->vars[v] ) )
+        {
+            if ( Cudd_bddLeq( dd, bVarsCs, dd->vars[v] ) )
+                printf( "c" );
+            else if ( Cudd_bddLeq( dd, bVarsNs, dd->vars[v] ) ) 
+                printf( "n" );
+            else
+                printf( "i" );
+        }
+        else
+            printf( "." );
+    }
+    printf( "\n" );
+    Cudd_RecursiveDeref( dd, bSupport );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the tree for quenstification scheduling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbr_bddImagePrintTree( Bbr_ImageTree_t * pTree )
+{
+    printf( "The quantification scheduling tree:\n" );
+    Bbr_bddImagePrintTree_rec( pTree->pRoot, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the tree for quenstification scheduling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbr_bddImagePrintTree_rec( Bbr_ImageNode_t * pNode, int Offset )
+{
+    DdNode * Cube;
+    int i;
+
+    Cube = pNode->bCube;
+
+    if ( pNode->pNode1 == NULL )
+    {
+        printf( "<%d> ", pNode->pPart->iPart );
+        if ( Cube != NULL )
+        {
+            ABC_PRB( pNode->dd, Cube );
+        }
+        else
+            printf( "\n" );
+        return;
+    }
+
+    printf( "<*> " );
+    if ( Cube != NULL )
+    {
+        ABC_PRB( pNode->dd, Cube );
+    }
+    else
+        printf( "\n" );
+
+    for ( i = 0; i < Offset; i++ )
+        printf( "    " );
+    Bbr_bddImagePrintTree_rec( pNode->pNode1, Offset + 1 );
+
+    for ( i = 0; i < Offset; i++ )
+        printf( "    " );
+    Bbr_bddImagePrintTree_rec( pNode->pNode2, Offset + 1 );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the positive polarty cube composed of the first vars in the array.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Bbr_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars )
+{
+    DdNode * bRes;
+    DdNode * bTemp;
+    int i;
+
+    bRes = b1; Cudd_Ref( bRes );
+    for ( i = 0; i < nVars; i++ )
+    {
+        bRes = Cudd_bddAnd( dd, bTemp = bRes, bXVars[i] );  Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+
+    Cudd_Deref( bRes );
+    return bRes;
+}
+
+
+
+
+
+struct Bbr_ImageTree2_t_
+{
+    DdManager * dd;
+    DdNode *    bRel;
+    DdNode *    bCube;
+    DdNode *    bImage;
+};
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the monolithic image computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bbr_ImageTree2_t * Bbr_bddImageStart2( 
+    DdManager * dd, DdNode * bCare,
+    int nParts, DdNode ** pbParts,
+    int nVars, DdNode ** pbVars, int fVerbose )
+{
+    Bbr_ImageTree2_t * pTree;
+    DdNode * bCubeAll, * bCubeNot, * bTemp;
+    int i;
+
+    pTree = ABC_ALLOC( Bbr_ImageTree2_t, 1 );
+    pTree->dd = dd;
+    pTree->bImage = NULL;
+
+    bCubeAll = Bbr_bddComputeCube( dd, dd->vars, dd->size );      Cudd_Ref( bCubeAll );
+    bCubeNot = Bbr_bddComputeCube( dd, pbVars,   nVars );         Cudd_Ref( bCubeNot );
+    pTree->bCube = Cudd_bddExistAbstract( dd, bCubeAll, bCubeNot ); Cudd_Ref( pTree->bCube );
+    Cudd_RecursiveDeref( dd, bCubeAll );
+    Cudd_RecursiveDeref( dd, bCubeNot );
+
+    // derive the monolithic relation
+    pTree->bRel = b1;   Cudd_Ref( pTree->bRel );
+    for ( i = 0; i < nParts; i++ )
+    {
+        pTree->bRel = Cudd_bddAnd( dd, bTemp = pTree->bRel, pbParts[i] ); Cudd_Ref( pTree->bRel );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    Bbr_bddImageCompute2( pTree, bCare );
+    return pTree;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Bbr_bddImageCompute2( Bbr_ImageTree2_t * pTree, DdNode * bCare )
+{
+    if ( pTree->bImage )
+        Cudd_RecursiveDeref( pTree->dd, pTree->bImage );
+    pTree->bImage = Cudd_bddAndAbstract( pTree->dd, pTree->bRel, bCare, pTree->bCube ); 
+    Cudd_Ref( pTree->bImage );
+    return pTree->bImage;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbr_bddImageTreeDelete2( Bbr_ImageTree2_t * pTree )
+{
+    if ( pTree->bRel )
+        Cudd_RecursiveDeref( pTree->dd, pTree->bRel );
+    if ( pTree->bCube )
+        Cudd_RecursiveDeref( pTree->dd, pTree->bCube );
+    if ( pTree->bImage )
+        Cudd_RecursiveDeref( pTree->dd, pTree->bImage );
+    ABC_FREE( pTree );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the previously computed image.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Bbr_bddImageRead2( Bbr_ImageTree2_t * pTree )
+{
+    return pTree->bImage;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/bbr/bbrNtbdd.c b/abc-build/src/proof/bbr/bbrNtbdd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/bbr/bbrNtbdd.c
@@ -0,0 +1,218 @@
+/**CFile****************************************************************
+
+  FileName    [bbrNtbdd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD-based reachability analysis.]
+
+  Synopsis    [Procedures to construct global BDDs for the network.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bbrNtbdd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bbr.h"
+//#include "bar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+typedef char ProgressBar;
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline void     Aig_ObjSetGlobalBdd( Aig_Obj_t * pObj, DdNode * bFunc )   { pObj->pData = bFunc; }
+static inline void     Aig_ObjCleanGlobalBdd( DdManager * dd, Aig_Obj_t * pObj ) { Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); pObj->pData = NULL; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the global BDD for one AIG node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Bbr_NodeGlobalBdds_rec( DdManager * dd, Aig_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose )
+{
+    DdNode * bFunc, * bFunc0, * bFunc1;
+    assert( !Aig_IsComplement(pNode) );
+    if ( Cudd_ReadKeys(dd)-Cudd_ReadDead(dd) > (unsigned)nBddSizeMax )
+    {
+//        Extra_ProgressBarStop( pProgress );
+        if ( fVerbose )
+        printf( "The number of live nodes reached %d.\n", nBddSizeMax );
+        fflush( stdout );
+        return NULL;
+    }
+    // if the result is available return
+    if ( Aig_ObjGlobalBdd(pNode) == NULL )
+    {
+        // compute the result for both branches
+        bFunc0 = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin0(pNode), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); 
+        if ( bFunc0 == NULL )
+            return NULL;
+        Cudd_Ref( bFunc0 );
+        bFunc1 = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin1(pNode), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); 
+        if ( bFunc1 == NULL )
+            return NULL;
+        Cudd_Ref( bFunc1 );
+        bFunc0 = Cudd_NotCond( bFunc0, Aig_ObjFaninC0(pNode) );
+        bFunc1 = Cudd_NotCond( bFunc1, Aig_ObjFaninC1(pNode) );
+        // get the final result
+        bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 );   Cudd_Ref( bFunc );
+        Cudd_RecursiveDeref( dd, bFunc0 );
+        Cudd_RecursiveDeref( dd, bFunc1 );
+        // add the number of used nodes
+        (*pCounter)++;
+        // set the result
+        assert( Aig_ObjGlobalBdd(pNode) == NULL );
+        Aig_ObjSetGlobalBdd( pNode, bFunc );
+        // increment the progress bar
+//        if ( pProgress )
+//            Extra_ProgressBarUpdate( pProgress, *pCounter, NULL );
+    }
+    // prepare the return value
+    bFunc = Aig_ObjGlobalBdd(pNode);
+    // dereference BDD at the node
+    if ( --pNode->nRefs == 0 && fDropInternal )
+    {
+        Cudd_Deref( bFunc );
+        Aig_ObjSetGlobalBdd( pNode, NULL );
+    }
+    return bFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the global BDDs of the network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManFreeGlobalBdds( Aig_Man_t * p, DdManager * dd ) 
+{ 
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachObj( p, pObj, i )
+        if ( Aig_ObjGlobalBdd(pObj) )
+            Aig_ObjCleanGlobalBdd( dd, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the shared size of global BDDs of the COs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManSizeOfGlobalBdds( Aig_Man_t * p ) 
+{
+    Vec_Ptr_t * vFuncsGlob;
+    Aig_Obj_t * pObj;
+    int RetValue, i;
+    // complement the global functions
+    vFuncsGlob = Vec_PtrAlloc( Aig_ManCoNum(p) );
+    Aig_ManForEachCo( p, pObj, i )
+        Vec_PtrPush( vFuncsGlob, Aig_ObjGlobalBdd(pObj) );
+    RetValue = Cudd_SharingSize( (DdNode **)Vec_PtrArray(vFuncsGlob), Vec_PtrSize(vFuncsGlob) );
+    Vec_PtrFree( vFuncsGlob );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively computes global BDDs for the AIG in the manager.]
+
+  Description [On exit, BDDs are stored in the pNode->pData fields.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdManager * Aig_ManComputeGlobalBdds( Aig_Man_t * p, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose )
+{
+    ProgressBar * pProgress = NULL;
+    Aig_Obj_t * pObj;
+    DdManager * dd;
+    DdNode * bFunc;
+    int i, Counter;
+    // start the manager
+    dd = Cudd_Init( Aig_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    // set reordering
+    if ( fReorder )
+        Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+    // prepare to construct global BDDs
+    Aig_ManCleanData( p );
+    // assign the constant node BDD
+    Aig_ObjSetGlobalBdd( Aig_ManConst1(p), dd->one );   Cudd_Ref( dd->one );
+    // set the elementary variables
+    Aig_ManForEachCi( p, pObj, i )
+    {
+        Aig_ObjSetGlobalBdd( pObj, dd->vars[i] );  Cudd_Ref( dd->vars[i] );
+    }
+
+    // collect the global functions of the COs
+    Counter = 0;
+    // construct the BDDs
+//    pProgress = Extra_ProgressBarStart( stdout, Aig_ManNodeNum(p) );
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        bFunc = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin0(pObj), nBddSizeMax, fDropInternal, pProgress, &Counter, fVerbose );
+        if ( bFunc == NULL )
+        {
+            if ( fVerbose )
+            printf( "Constructing global BDDs is aborted.\n" );
+            Aig_ManFreeGlobalBdds( p, dd );
+            Cudd_Quit( dd ); 
+            // reset references
+            Aig_ManResetRefs( p );
+            return NULL;
+        }
+        bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pObj) );  Cudd_Ref( bFunc ); 
+        Aig_ObjSetGlobalBdd( pObj, bFunc );
+    }
+//    Extra_ProgressBarStop( pProgress );
+    // reset references
+    Aig_ManResetRefs( p );
+    // reorder one more time
+    if ( fReorder )
+    {
+        Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 );
+        Cudd_AutodynDisable( dd );
+    }
+//    Cudd_PrintInfo( dd, stdout );
+    return dd;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/bbr/bbrReach.c b/abc-build/src/proof/bbr/bbrReach.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/bbr/bbrReach.c
@@ -0,0 +1,615 @@
+/**CFile****************************************************************
+
+  FileName    [bbrReach.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD-based reachability analysis.]
+
+  Synopsis    [Procedures to perform reachability analysis.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bbrReach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bbr.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern Abc_Cex_t * Aig_ManVerifyUsingBddsCountExample( Aig_Man_t * p, DdManager * dd, 
+    DdNode ** pbParts, Vec_Ptr_t * vOnionRings, DdNode * bCubeFirst, 
+    int iOutput, int fVerbose, int fSilent );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default resynthesis parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbr_ManSetDefaultParams( Saig_ParBbr_t * p )
+{
+    memset( p, 0, sizeof(Saig_ParBbr_t) );
+    p->TimeLimit     =     0;
+    p->nBddMax       = 50000;
+    p->nIterMax      =  1000;
+    p->fPartition    =     1;
+    p->fReorder      =     1;
+    p->fReorderImage =     1;
+    p->fVerbose      =     0;
+    p->fSilent       =     0;
+    p->iFrame        =    -1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the reordering-sensitive step of Extra_bddMove().]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode * Bbr_bddComputeRangeCube( DdManager * dd, int iStart, int iStop )
+{
+    DdNode * bTemp, * bProd;
+    int i;
+    assert( iStart <= iStop );
+    assert( iStart >= 0 && iStart <= dd->size );
+    assert( iStop >= 0  && iStop  <= dd->size );
+    bProd = (dd)->one;         Cudd_Ref( bProd );
+    for ( i = iStart; i < iStop; i++ )
+    {
+        bProd = Cudd_bddAnd( dd, bTemp = bProd, dd->vars[i] );      Cudd_Ref( bProd );
+        Cudd_RecursiveDeref( dd, bTemp ); 
+    }
+    Cudd_Deref( bProd );
+    return bProd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bbr_StopManager( DdManager * dd )
+{
+    int RetValue;
+    // check for remaining references in the package
+    RetValue = Cudd_CheckZeroRef( dd );
+    if ( RetValue > 0 )
+        printf( "\nThe number of referenced nodes = %d\n\n", RetValue );
+//  Cudd_PrintInfo( dd, stdout );
+    Cudd_Quit( dd );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the initial state and sets up the variable map.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Aig_ManInitStateVarMap( DdManager * dd, Aig_Man_t * p, int fVerbose )
+{
+    DdNode ** pbVarsX, ** pbVarsY;
+    DdNode * bTemp, * bProd;
+    Aig_Obj_t * pLatch;
+    int i;
+
+    // set the variable mapping for Cudd_bddVarMap()
+    pbVarsX = ABC_ALLOC( DdNode *, dd->size );
+    pbVarsY = ABC_ALLOC( DdNode *, dd->size );
+    bProd = (dd)->one;         Cudd_Ref( bProd );
+    Saig_ManForEachLo( p, pLatch, i )
+    {
+        pbVarsX[i] = dd->vars[ Saig_ManPiNum(p) + i ];
+        pbVarsY[i] = dd->vars[ Saig_ManCiNum(p) + i ];
+        // get the initial value of the latch
+        bProd = Cudd_bddAnd( dd, bTemp = bProd, Cudd_Not(pbVarsX[i]) );      Cudd_Ref( bProd );
+        Cudd_RecursiveDeref( dd, bTemp ); 
+    }
+    Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Saig_ManRegNum(p) );
+    ABC_FREE( pbVarsX );
+    ABC_FREE( pbVarsY );
+
+    Cudd_Deref( bProd );
+    return bProd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the array of output BDDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode ** Aig_ManCreateOutputs( DdManager * dd, Aig_Man_t * p )
+{
+    DdNode ** pbOutputs;
+    Aig_Obj_t * pNode;
+    int i;
+    // compute the transition relation
+    pbOutputs = ABC_ALLOC( DdNode *, Saig_ManPoNum(p) );
+    Saig_ManForEachPo( p, pNode, i )
+    {
+        pbOutputs[i] = Aig_ObjGlobalBdd(pNode);  Cudd_Ref( pbOutputs[i] );
+    }
+    return pbOutputs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the array of partition BDDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode ** Aig_ManCreatePartitions( DdManager * dd, Aig_Man_t * p, int fReorder, int fVerbose )
+{
+    DdNode ** pbParts;
+    DdNode * bVar;
+    Aig_Obj_t * pNode;
+    int i;
+
+    // extand the BDD manager to represent NS variables
+    assert( dd->size == Saig_ManCiNum(p) );
+    Cudd_bddIthVar( dd, Saig_ManCiNum(p) + Saig_ManRegNum(p) - 1 );
+
+    // enable reordering
+    if ( fReorder )
+        Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+    else
+        Cudd_AutodynDisable( dd );
+
+    // compute the transition relation
+    pbParts = ABC_ALLOC( DdNode *, Saig_ManRegNum(p) );
+    Saig_ManForEachLi( p, pNode, i )
+    {
+        bVar  = Cudd_bddIthVar( dd, Saig_ManCiNum(p) + i );
+        pbParts[i] = Cudd_bddXnor( dd, bVar, Aig_ObjGlobalBdd(pNode) );  Cudd_Ref( pbParts[i] );
+    }
+    // free global BDDs
+    Aig_ManFreeGlobalBdds( p, dd );
+
+    // reorder and disable reordering
+    if ( fReorder )
+    {
+        if ( fVerbose )
+            fprintf( stdout, "BDD nodes in the partitions before reordering %d.\n", Cudd_SharingSize(pbParts,Saig_ManRegNum(p)) );
+        Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+        Cudd_AutodynDisable( dd );
+        if ( fVerbose )
+            fprintf( stdout, "BDD nodes in the partitions after reordering %d.\n", Cudd_SharingSize(pbParts,Saig_ManRegNum(p)) );
+    }
+    return pbParts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the set of unreachable states.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManComputeReachable( DdManager * dd, Aig_Man_t * p, DdNode ** pbParts, DdNode * bInitial, DdNode ** pbOutputs, Saig_ParBbr_t * pPars, int fCheckOutputs )
+{
+    int fInternalReorder = 0;
+    Bbr_ImageTree_t * pTree = NULL; // Suppress "might be used uninitialized"
+    Bbr_ImageTree2_t * pTree2 = NULL; // Supprses "might be used uninitialized"
+    DdNode * bReached, * bCubeCs;
+    DdNode * bCurrent;
+    DdNode * bNext = NULL; // Suppress "might be used uninitialized"
+    DdNode * bTemp;
+    Cudd_ReorderingType method;
+    int i, nIters, nBddSize = 0, status;
+    int nThreshold = 10000;
+    abctime clk = Abc_Clock();
+    Vec_Ptr_t * vOnionRings;
+    int fixedPoint = 0;
+
+    status = Cudd_ReorderingStatus( dd, &method );
+    if ( status )
+        Cudd_AutodynDisable( dd );
+
+    // start the image computation
+    bCubeCs  = Bbr_bddComputeRangeCube( dd, Saig_ManPiNum(p), Saig_ManCiNum(p) );    Cudd_Ref( bCubeCs );
+    if ( pPars->fPartition )
+        pTree = Bbr_bddImageStart( dd, bCubeCs, Saig_ManRegNum(p), pbParts, Saig_ManRegNum(p), dd->vars+Saig_ManCiNum(p), pPars->nBddMax, pPars->fVerbose );
+    else
+        pTree2 = Bbr_bddImageStart2( dd, bCubeCs, Saig_ManRegNum(p), pbParts, Saig_ManRegNum(p), dd->vars+Saig_ManCiNum(p), pPars->fVerbose );
+    Cudd_RecursiveDeref( dd, bCubeCs );
+    if ( pTree == NULL )
+    {
+        if ( !pPars->fSilent )
+            printf( "BDDs blew up during qualitification scheduling.  " );
+        return -1;
+    }
+
+    if ( status )
+        Cudd_AutodynEnable( dd, method );
+
+    // start the onion rings
+    vOnionRings = Vec_PtrAlloc( 1000 );
+
+    // perform reachability analysis
+    bCurrent = bInitial;   Cudd_Ref( bCurrent );
+    bReached = bInitial;   Cudd_Ref( bReached );
+    Vec_PtrPush( vOnionRings, bCurrent );  Cudd_Ref( bCurrent );
+    for ( nIters = 0; nIters < pPars->nIterMax; nIters++ )
+    { 
+        // check the runtime limit
+        if ( pPars->TimeLimit && pPars->TimeLimit <= (Abc_Clock()-clk)/CLOCKS_PER_SEC )
+        {
+            printf( "Reached timeout after image computation (%d seconds).\n",  pPars->TimeLimit );
+            Vec_PtrFree( vOnionRings );
+            // undo the image tree
+            if ( pPars->fPartition )
+                Bbr_bddImageTreeDelete( pTree );
+            else
+                Bbr_bddImageTreeDelete2( pTree2 );
+            pPars->iFrame = nIters - 1;
+            return -1;
+        }
+
+        // compute the next states
+        if ( pPars->fPartition )
+            bNext = Bbr_bddImageCompute( pTree, bCurrent );           
+        else
+            bNext = Bbr_bddImageCompute2( pTree2, bCurrent );  
+        if ( bNext == NULL )
+        {
+            if ( !pPars->fSilent )
+                printf( "BDDs blew up during image computation.  " );
+            if ( pPars->fPartition )
+                Bbr_bddImageTreeDelete( pTree );
+            else
+                Bbr_bddImageTreeDelete2( pTree2 );
+            Vec_PtrFree( vOnionRings );
+            pPars->iFrame = nIters - 1;
+            return -1;
+        }
+        Cudd_Ref( bNext );
+        Cudd_RecursiveDeref( dd, bCurrent );
+
+        // remap these states into the current state vars
+        bNext = Cudd_bddVarMap( dd, bTemp = bNext );                    Cudd_Ref( bNext );
+        Cudd_RecursiveDeref( dd, bTemp );
+        // check if there are any new states
+        if ( Cudd_bddLeq( dd, bNext, bReached ) ) {
+            fixedPoint = 1;
+            break;
+        }
+        // check the BDD size
+        nBddSize = Cudd_DagSize(bNext);
+        if ( nBddSize > pPars->nBddMax )
+            break;
+        // check the result
+        for ( i = 0; i < Saig_ManPoNum(p); i++ )
+        {
+            if ( fCheckOutputs && !Cudd_bddLeq( dd, bNext, Cudd_Not(pbOutputs[i]) ) )
+            {
+                DdNode * bIntersect;
+                bIntersect = Cudd_bddIntersect( dd, bNext, pbOutputs[i] );  Cudd_Ref( bIntersect );
+                assert( p->pSeqModel == NULL );
+                p->pSeqModel = Aig_ManVerifyUsingBddsCountExample( p, dd, pbParts, 
+                    vOnionRings, bIntersect, i, pPars->fVerbose, pPars->fSilent ); 
+                Cudd_RecursiveDeref( dd, bIntersect );
+                if ( !pPars->fSilent )
+                    Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", i, p->pName, Vec_PtrSize(vOnionRings) );
+                Cudd_RecursiveDeref( dd, bReached );
+                bReached = NULL;
+                pPars->iFrame = nIters;
+                break;
+            }
+        }
+        if ( i < Saig_ManPoNum(p) )
+            break;
+        // get the new states
+        bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) );        Cudd_Ref( bCurrent );
+        Vec_PtrPush( vOnionRings, bCurrent );  Cudd_Ref( bCurrent );
+        // minimize the new states with the reached states
+//        bCurrent = Cudd_bddConstrain( dd, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent );
+//        Cudd_RecursiveDeref( dd, bTemp );
+        // add to the reached states
+        bReached = Cudd_bddOr( dd, bTemp = bReached, bNext );           Cudd_Ref( bReached );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bNext );
+        if ( pPars->fVerbose )
+            fprintf( stdout, "Frame = %3d. BDD = %5d. ", nIters, nBddSize );
+        if ( fInternalReorder && pPars->fReorder && nBddSize > nThreshold )
+        {
+            if ( pPars->fVerbose )
+                fprintf( stdout, "Reordering... Before = %5d. ", Cudd_DagSize(bReached) );
+            Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+            Cudd_AutodynDisable( dd );
+            if ( pPars->fVerbose )
+                fprintf( stdout, "After = %5d.\r", Cudd_DagSize(bReached) );
+            nThreshold *= 2;
+        }
+        if ( pPars->fVerbose )
+//            fprintf( stdout, "\r" );
+            fprintf( stdout, "\n" );
+
+        if ( pPars->fVerbose )
+        {
+            double nMints = Cudd_CountMinterm(dd, bReached, Saig_ManRegNum(p) );
+//            Extra_bddPrint( dd, bReached );printf( "\n" );
+            fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p)) );
+            fflush( stdout ); 
+        }
+
+    }
+    Cudd_RecursiveDeref( dd, bNext );
+    // free the onion rings
+    Vec_PtrForEachEntry( DdNode *, vOnionRings, bTemp, i )
+        Cudd_RecursiveDeref( dd, bTemp );
+    Vec_PtrFree( vOnionRings );
+    // undo the image tree
+    if ( pPars->fPartition )
+        Bbr_bddImageTreeDelete( pTree );
+    else
+        Bbr_bddImageTreeDelete2( pTree2 );
+    if ( bReached == NULL )
+        return 0; // proved reachable
+    // report the stats
+    if ( pPars->fVerbose )
+    {
+        double nMints = Cudd_CountMinterm(dd, bReached, Saig_ManRegNum(p) );
+        if ( nIters > pPars->nIterMax || nBddSize > pPars->nBddMax )
+            fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters );
+        else
+            fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters );
+        fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p)) );
+        fflush( stdout );
+    }
+//ABC_PRB( dd, bReached );
+    Cudd_RecursiveDeref( dd, bReached );
+    // SPG
+    //
+    if ( fixedPoint ) {
+      if ( !pPars->fSilent ) {
+        printf( "The miter is proved unreachable after %d iterations.  ", nIters );
+      }
+      pPars->iFrame = nIters - 1;
+      return 1;
+    }
+    assert(nIters >= pPars->nIterMax || nBddSize >= pPars->nBddMax);
+    if ( !pPars->fSilent )
+      printf( "Verified only for states reachable in %d frames.  ", nIters );
+    pPars->iFrame = nIters - 1;
+    return -1; // undecided
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs reachability to see if any PO can be asserted.]
+
+  Description []
+               
+  SideEffects []
+ 
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManVerifyUsingBdds_int( Aig_Man_t * p, Saig_ParBbr_t * pPars )
+{
+    int fCheckOutputs = !pPars->fSkipOutCheck;
+    DdManager * dd;
+    DdNode ** pbParts, ** pbOutputs;
+    DdNode * bInitial, * bTemp;
+    int RetValue, i;
+    abctime clk = Abc_Clock();
+    Vec_Ptr_t * vOnionRings;
+
+    assert( Saig_ManRegNum(p) > 0 );
+
+    // compute the global BDDs of the latches
+    dd = Aig_ManComputeGlobalBdds( p, pPars->nBddMax, 1, pPars->fReorder, pPars->fVerbose );    
+    if ( dd == NULL )
+    {
+        if ( !pPars->fSilent )
+            printf( "The number of intermediate BDD nodes exceeded the limit (%d).\n", pPars->nBddMax );
+        return -1;
+    }
+    if ( pPars->fVerbose )
+        printf( "Shared BDD size is %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+
+    // check the runtime limit
+    if ( pPars->TimeLimit && pPars->TimeLimit <= (Abc_Clock()-clk)/CLOCKS_PER_SEC )
+    {
+        printf( "Reached timeout after constructing global BDDs (%d seconds).\n",  pPars->TimeLimit );
+        Cudd_Quit( dd );
+        return -1;
+    }
+
+    // start the onion rings
+    vOnionRings = Vec_PtrAlloc( 1000 );
+
+    // save outputs
+    pbOutputs = Aig_ManCreateOutputs( dd, p );
+
+    // create partitions
+    pbParts = Aig_ManCreatePartitions( dd, p, pPars->fReorder, pPars->fVerbose );
+
+    // create the initial state and the variable map
+    bInitial  = Aig_ManInitStateVarMap( dd, p, pPars->fVerbose );  Cudd_Ref( bInitial );
+
+    // set reordering
+    if ( pPars->fReorderImage )
+        Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+
+    // check the result
+    RetValue = -1;
+    for ( i = 0; i < Saig_ManPoNum(p); i++ )
+    {
+        if ( fCheckOutputs && !Cudd_bddLeq( dd, bInitial, Cudd_Not(pbOutputs[i]) ) )
+        {
+            DdNode * bIntersect;
+            bIntersect = Cudd_bddIntersect( dd, bInitial, pbOutputs[i] );  Cudd_Ref( bIntersect );
+            assert( p->pSeqModel == NULL );
+            p->pSeqModel = Aig_ManVerifyUsingBddsCountExample( p, dd, pbParts, 
+                vOnionRings, bIntersect, i, pPars->fVerbose, pPars->fSilent ); 
+            Cudd_RecursiveDeref( dd, bIntersect );
+            if ( !pPars->fSilent )
+                Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", i, p->pName, -1 );
+            RetValue = 0;
+            break;
+        }
+    }
+    // free the onion rings
+    Vec_PtrForEachEntry( DdNode *, vOnionRings, bTemp, i )
+        Cudd_RecursiveDeref( dd, bTemp );
+    Vec_PtrFree( vOnionRings );
+    // explore reachable states
+    if ( RetValue == -1 )
+        RetValue = Aig_ManComputeReachable( dd, p, pbParts, bInitial, pbOutputs, pPars, fCheckOutputs ); 
+
+    // cleanup
+    Cudd_RecursiveDeref( dd, bInitial );
+    for ( i = 0; i < Saig_ManRegNum(p); i++ )
+        Cudd_RecursiveDeref( dd, pbParts[i] );
+    ABC_FREE( pbParts );
+    for ( i = 0; i < Saig_ManPoNum(p); i++ )
+        Cudd_RecursiveDeref( dd, pbOutputs[i] );
+    ABC_FREE( pbOutputs );
+//    if ( RetValue == -1 )
+        Cudd_Quit( dd );
+//    else
+//        Bbr_StopManager( dd );
+
+    // report the runtime
+    if ( !pPars->fSilent )
+    {
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    fflush( stdout );
+    }
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs reachability to see if any PO can be asserted.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManVerifyUsingBdds( Aig_Man_t * pInit, Saig_ParBbr_t * pPars )
+{
+    Abc_Cex_t * pCexOld, * pCexNew;
+    Aig_Man_t * p;
+    Aig_Obj_t * pObj;
+    Vec_Int_t * vInputMap;
+    int i, k, Entry, iBitOld, iBitNew, RetValue;
+//    pPars->fVerbose = 1;
+    // check if there are PIs without fanout
+    Saig_ManForEachPi( pInit, pObj, i )
+        if ( Aig_ObjRefs(pObj) == 0 )
+            break;
+    if ( i == Saig_ManPiNum(pInit) )
+        return Aig_ManVerifyUsingBdds_int( pInit, pPars );
+    // create new AIG
+    p = Aig_ManDupTrim( pInit );
+    assert( Aig_ManCiNum(p) < Aig_ManCiNum(pInit) );
+    assert( Aig_ManRegNum(p) == Aig_ManRegNum(pInit) );
+    RetValue = Aig_ManVerifyUsingBdds_int( p, pPars );
+    if ( RetValue != 0 )
+    {
+        Aig_ManStop( p );
+        return RetValue;
+    }
+    // the problem is satisfiable - remap the pattern
+    pCexOld = p->pSeqModel;
+    assert( pCexOld != NULL );
+    // create input map
+    vInputMap = Vec_IntAlloc( Saig_ManPiNum(pInit) );
+    Saig_ManForEachPi( pInit, pObj, i )
+        if ( pObj->pData != NULL )
+            Vec_IntPush( vInputMap, Aig_ObjCioId((Aig_Obj_t *)pObj->pData) );
+        else
+            Vec_IntPush( vInputMap, -1 );
+    // create new pattern
+    pCexNew = Abc_CexAlloc( Saig_ManRegNum(pInit), Saig_ManPiNum(pInit), pCexOld->iFrame+1 );
+    pCexNew->iFrame = pCexOld->iFrame;
+    pCexNew->iPo    = pCexOld->iPo;
+    // copy the bit-data
+    for ( iBitOld = 0; iBitOld < pCexOld->nRegs; iBitOld++ )
+        if ( Abc_InfoHasBit( pCexOld->pData, iBitOld ) )
+            Abc_InfoSetBit( pCexNew->pData, iBitOld );
+    // copy the primary input data
+    iBitNew = iBitOld;
+    for ( i = 0; i <= pCexNew->iFrame; i++ )
+    {
+        Vec_IntForEachEntry( vInputMap, Entry, k )
+        {
+            if ( Entry == -1 )
+                continue;
+            if ( Abc_InfoHasBit( pCexOld->pData, iBitOld + Entry ) )
+                Abc_InfoSetBit( pCexNew->pData, iBitNew + k );
+        }
+        iBitOld += Saig_ManPiNum(p);
+        iBitNew += Saig_ManPiNum(pInit);
+    }
+    assert( iBitOld < iBitNew );
+    assert( iBitOld == pCexOld->nBits );
+    assert( iBitNew == pCexNew->nBits );
+    Vec_IntFree( vInputMap );
+    pInit->pSeqModel = pCexNew;
+    Aig_ManStop( p );
+    return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/bbr/bbr_.c b/abc-build/src/proof/bbr/bbr_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/bbr/bbr_.c
@@ -0,0 +1,52 @@
+/**CFile****************************************************************
+
+  FileName    [.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName []
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: .c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "__Int.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/bbr/module.make b/abc-build/src/proof/bbr/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/bbr/module.make
@@ -0,0 +1,4 @@
+SRC +=	src/proof/bbr/bbrCex.c \
+	src/proof/bbr/bbrImage.c \
+	src/proof/bbr/bbrNtbdd.c \
+	src/proof/bbr/bbrReach.c
diff --git a/abc-build/src/proof/cec/cec.c b/abc-build/src/proof/cec/cec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/cec.c
@@ -0,0 +1,53 @@
+**CFile****************************************************************
+
+  FileName    [cec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Combinational equivalence checking.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/cec/cec.h b/abc-build/src/proof/cec/cec.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/cec.h
@@ -0,0 +1,234 @@
+/**CFile****************************************************************
+
+  FileName    [cec.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Combinational equivalence checking.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__cec__cec_h
+#define ABC__aig__cec__cec_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// dynamic SAT parameters
+typedef struct Cec_ParSat_t_ Cec_ParSat_t;
+struct Cec_ParSat_t_
+{
+    int              nBTLimit;      // conflict limit at a node
+    int              nSatVarMax;    // the max number of SAT variables
+    int              nCallsRecycle; // calls to perform before recycling SAT solver
+    int              fNonChrono;    // use non-chronological backtracling (for circuit SAT only)
+    int              fPolarFlip;    // flops polarity of variables
+    int              fCheckMiter;   // the circuit is the miter
+//    int              fFirstStop;    // stop on the first sat output
+    int              fLearnCls;     // perform clause learning
+    int              fVerbose;      // verbose stats
+};
+
+// simulation parameters
+typedef struct Cec_ParSim_t_ Cec_ParSim_t;
+struct Cec_ParSim_t_ 
+{
+    int              nWords;        // the number of simulation words
+    int              nFrames;       // the number of simulation frames
+    int              nRounds;       // the number of simulation rounds
+    int              nNonRefines;   // the max number of rounds without refinement
+    int              TimeLimit;     // the runtime limit in seconds
+    int              fDualOut;      // miter with separate outputs
+    int              fCheckMiter;   // the circuit is the miter
+//    int              fFirstStop;    // stop on the first sat output
+    int              fSeqSimulate;  // performs sequential simulation
+    int              fLatchCorr;    // consider only latch outputs
+    int              fConstCorr;    // consider only constants
+    int              fVeryVerbose;  // verbose stats
+    int              fVerbose;      // verbose stats
+};
+
+// semiformal parameters
+typedef struct Cec_ParSmf_t_ Cec_ParSmf_t;
+struct Cec_ParSmf_t_
+{
+    int              nWords;        // the number of simulation words
+    int              nRounds;       // the number of simulation rounds
+    int              nFrames;       // the max number of time frames
+    int              nNonRefines;   // the max number of rounds without refinement
+    int              nMinOutputs;   // the min outputs to accumulate
+    int              nBTLimit;      // conflict limit at a node
+    int              TimeLimit;     // the runtime limit in seconds
+    int              fDualOut;      // miter with separate outputs
+    int              fCheckMiter;   // the circuit is the miter
+//    int              fFirstStop;    // stop on the first sat output
+    int              fVerbose;      // verbose stats
+};
+
+// combinational SAT sweeping parameters
+typedef struct Cec_ParFra_t_ Cec_ParFra_t;
+struct Cec_ParFra_t_
+{
+    int              nWords;        // the number of simulation words
+    int              nRounds;       // the number of simulation rounds
+    int              nItersMax;     // the maximum number of iterations of SAT sweeping
+    int              nBTLimit;      // conflict limit at a node
+    int              TimeLimit;     // the runtime limit in seconds
+    int              nLevelMax;     // restriction on the level nodes to be swept
+    int              nDepthMax;     // the depth in terms of steps of speculative reduction
+    int              fRewriting;    // enables AIG rewriting
+    int              fCheckMiter;   // the circuit is the miter
+//    int              fFirstStop;    // stop on the first sat output
+    int              fDualOut;      // miter with separate outputs
+    int              fColorDiff;    // miter with separate outputs
+    int              fSatSweeping;  // enable SAT sweeping
+    int              fVeryVerbose;  // verbose stats
+    int              fVerbose;      // verbose stats
+    int              iOutFail;      // the failed output
+};
+
+// combinational equivalence checking parameters
+typedef struct Cec_ParCec_t_ Cec_ParCec_t;
+struct Cec_ParCec_t_
+{
+    int              nBTLimit;      // conflict limit at a node
+    int              TimeLimit;     // the runtime limit in seconds
+//    int              fFirstStop;    // stop on the first sat output
+    int              fUseSmartCnf;  // use smart CNF computation
+    int              fRewriting;    // enables AIG rewriting
+    int              fVeryVerbose;  // verbose stats
+    int              fVerbose;      // verbose stats
+    int              iOutFail;      // the number of failed output
+};
+
+// sequential register correspodence parameters
+typedef struct Cec_ParCor_t_ Cec_ParCor_t;
+struct Cec_ParCor_t_
+{
+    int              nWords;        // the number of simulation words
+    int              nRounds;       // the number of simulation rounds
+    int              nFrames;       // the number of time frames
+    int              nPrefix;       // the number of time frames in the prefix
+    int              nBTLimit;      // conflict limit at a node
+    int              nLevelMax;     // (scorr only) the max number of levels
+    int              nStepsMax;     // (scorr only) the max number of induction steps
+    int              fLatchCorr;    // consider only latch outputs
+    int              fConstCorr;    // consider only constants
+    int              fUseRings;     // use rings
+    int              fMakeChoices;  // use equilvaences as choices
+    int              fUseCSat;      // use circuit-based solver
+//    int              fFirstStop;    // stop on the first sat output
+    int              fUseSmartCnf;  // use smart CNF computation
+    int              fStopWhenGone; // quit when PO is not a candidate constant
+    int              fVerboseFlops; // verbose stats
+    int              fVeryVerbose;  // verbose stats
+    int              fVerbose;      // verbose stats
+    // callback
+    void *           pData;
+    void *           pFunc;
+};
+
+// sequential register correspodence parameters
+typedef struct Cec_ParChc_t_ Cec_ParChc_t;
+struct Cec_ParChc_t_
+{
+    int              nWords;        // the number of simulation words
+    int              nRounds;       // the number of simulation rounds
+    int              nBTLimit;      // conflict limit at a node
+    int              fUseRings;     // use rings
+    int              fUseCSat;      // use circuit-based solver
+    int              fVeryVerbose;  // verbose stats
+    int              fVerbose;      // verbose stats
+};
+
+// sequential synthesis parameters
+typedef struct Cec_ParSeq_t_ Cec_ParSeq_t;
+struct Cec_ParSeq_t_
+{
+    int              fUseLcorr;     // enables latch correspondence
+    int              fUseScorr;     // enables signal correspondence
+    int              nBTLimit;      // (scorr/lcorr) conflict limit at a node
+    int              nFrames;       // (scorr/lcorr) the number of timeframes
+    int              nLevelMax;     // (scorr only) the max number of levels
+    int              fConsts;       // (scl only) merging constants
+    int              fEquivs;       // (scl only) merging equivalences
+    int              fUseMiniSat;   // enables MiniSat in lcorr/scorr
+    int              nMinDomSize;   // the size of minimum clock domain
+    int              fVeryVerbose;  // verbose stats
+    int              fVerbose;      // verbose stats
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== cecCec.c ==========================================================*/
+extern int           Cec_ManVerify( Gia_Man_t * p, Cec_ParCec_t * pPars );
+extern int           Cec_ManVerifyTwo( Gia_Man_t * p0, Gia_Man_t * p1, int fVerbose );
+/*=== cecChoice.c ==========================================================*/
+extern Gia_Man_t *   Cec_ManChoiceComputation( Gia_Man_t * pAig, Cec_ParChc_t * pPars );
+/*=== cecCorr.c ==========================================================*/
+extern int           Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars );
+extern Gia_Man_t *   Cec_ManLSCorrespondence( Gia_Man_t * pAig, Cec_ParCor_t * pPars );
+/*=== cecCore.c ==========================================================*/
+extern void          Cec_ManSatSetDefaultParams( Cec_ParSat_t * p );
+extern void          Cec_ManSimSetDefaultParams( Cec_ParSim_t * p );
+extern void          Cec_ManSmfSetDefaultParams( Cec_ParSmf_t * p );
+extern void          Cec_ManFraSetDefaultParams( Cec_ParFra_t * p );
+extern void          Cec_ManCecSetDefaultParams( Cec_ParCec_t * p );
+extern void          Cec_ManCorSetDefaultParams( Cec_ParCor_t * p );
+extern void          Cec_ManChcSetDefaultParams( Cec_ParChc_t * p );
+extern Gia_Man_t *   Cec_ManSatSweeping( Gia_Man_t * pAig, Cec_ParFra_t * pPars );
+extern Gia_Man_t *   Cec_ManSatSolving( Gia_Man_t * pAig, Cec_ParSat_t * pPars );
+extern void          Cec_ManSimulation( Gia_Man_t * pAig, Cec_ParSim_t * pPars );
+/*=== cecSeq.c ==========================================================*/
+extern int           Cec_ManSeqResimulateCounter( Gia_Man_t * pAig, Cec_ParSim_t * pPars, Abc_Cex_t * pCex );
+extern int           Cec_ManSeqSemiformal( Gia_Man_t * pAig, Cec_ParSmf_t * pPars );
+extern int           Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig );
+/*=== cecSynth.c ==========================================================*/
+extern int           Cec_SeqReadMinDomSize( Cec_ParSeq_t * p );
+extern int           Cec_SeqReadVerbose( Cec_ParSeq_t * p );
+extern void          Cec_SeqSynthesisSetDefaultParams( Cec_ParSeq_t * pPars );
+extern int           Cec_SequentialSynthesisPart( Gia_Man_t * p, Cec_ParSeq_t * pPars );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/cec/cecCec.c b/abc-build/src/proof/cec/cecCec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/cecCec.c
@@ -0,0 +1,429 @@
+/**CFile****************************************************************
+
+  FileName    [cecCec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Combinational equivalence checking.]
+
+  Synopsis    [Integrated combinatinal equivalence checker.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cecCec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+#include "proof/fra/fra.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Saves the input pattern with the given number.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManTransformPattern( Gia_Man_t * p, int iOut, int * pValues )
+{
+    int i;
+    assert( p->pCexComb == NULL );
+    p->pCexComb = Abc_CexAlloc( 0, Gia_ManCiNum(p), 1 );
+    p->pCexComb->iPo = iOut;
+    for ( i = 0; i < Gia_ManCiNum(p); i++ )
+        if ( pValues && pValues[i] )
+            Abc_InfoSetBit( p->pCexComb->pData, i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Interface to the old CEC engine]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManVerifyOld( Gia_Man_t * pMiter, int fVerbose, int * piOutFail, abctime clkTotal )
+{
+//    extern int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose );
+    extern int Ssw_SecCexResimulate( Aig_Man_t * p, int * pModel, int * pnOutputs );
+    Gia_Man_t * pTemp = Gia_ManTransformMiter( pMiter );
+    Aig_Man_t * pMiterCec = Gia_ManToAig( pTemp, 0 );
+    int RetValue, iOut, nOuts;
+    if ( piOutFail )
+        *piOutFail = -1;
+    Gia_ManStop( pTemp );
+    // run CEC on this miter
+    RetValue = Fra_FraigCec( &pMiterCec, 10000000, fVerbose );
+    // report the miter
+    if ( RetValue == 1 )
+    {
+        Abc_Print( 1, "Networks are equivalent.   " );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+    }
+    else if ( RetValue == 0 )
+    {
+        Abc_Print( 1, "Networks are NOT EQUIVALENT.   " );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+        if ( pMiterCec->pData == NULL )
+            Abc_Print( 1, "Counter-example is not available.\n" );
+        else
+        {
+            iOut = Ssw_SecCexResimulate( pMiterCec, (int *)pMiterCec->pData, &nOuts );
+            if ( iOut == -1 )
+                Abc_Print( 1, "Counter-example verification has failed.\n" );
+            else 
+            {
+//                Aig_Obj_t * pObj = Aig_ManCo(pMiterCec, iOut);
+//                Aig_Obj_t * pFan = Aig_ObjFanin0(pObj);
+                Abc_Print( 1, "Primary output %d has failed", iOut );
+                if ( nOuts-1 >= 0 )
+                    Abc_Print( 1, ", along with other %d incorrect outputs", nOuts-1 );
+                Abc_Print( 1, ".\n" );
+                if ( piOutFail )
+                    *piOutFail = iOut;
+            }
+            Cec_ManTransformPattern( pMiter, iOut, (int *)pMiterCec->pData );
+        }
+    }
+    else
+    {
+        Abc_Print( 1, "Networks are UNDECIDED.   " );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+    }
+    fflush( stdout );
+    Aig_ManStop( pMiterCec );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManHandleSpecialCases( Gia_Man_t * p, Cec_ParCec_t * pPars )
+{
+    Gia_Obj_t * pObj1, * pObj2;
+    Gia_Obj_t * pDri1, * pDri2;
+    int i;
+    abctime clk = Abc_Clock();
+    Gia_ManSetPhase( p );
+    Gia_ManForEachPo( p, pObj1, i )
+    {
+        pObj2 = Gia_ManPo( p, ++i );
+        // check if they different on all-0 pattern
+        // (for example, when they have the same driver but complemented)
+        if ( Gia_ObjPhase(pObj1) != Gia_ObjPhase(pObj2) )
+        {
+            Abc_Print( 1, "Networks are NOT EQUIVALENT. Output %d trivially differs (different phase).  ", i/2 );
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+            pPars->iOutFail = i/2;
+            Cec_ManTransformPattern( p, i/2, NULL );
+            return 0;
+        }
+        // get the drivers
+        pDri1 = Gia_ObjFanin0(pObj1);
+        pDri2 = Gia_ObjFanin0(pObj2);
+        // drivers are different PIs
+        if ( Gia_ObjIsPi(p, pDri1) && Gia_ObjIsPi(p, pDri2) && pDri1 != pDri2 )
+        {
+            Abc_Print( 1, "Networks are NOT EQUIVALENT. Output %d trivially differs (different PIs).  ", i/2 );
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+            pPars->iOutFail = i/2;
+            Cec_ManTransformPattern( p, i/2, NULL );
+            // if their compl attributes are the same - one should be complemented
+            assert( Gia_ObjFaninC0(pObj1) == Gia_ObjFaninC0(pObj2) );
+            Abc_InfoSetBit( p->pCexComb->pData, Gia_ObjCioId(pDri1) );
+            return 0;
+        }
+        // one of the drivers is a PI; another is a constant 0
+        if ( (Gia_ObjIsPi(p, pDri1) && Gia_ObjIsConst0(pDri2)) || 
+             (Gia_ObjIsPi(p, pDri2) && Gia_ObjIsConst0(pDri1)) )
+        {
+            Abc_Print( 1, "Networks are NOT EQUIVALENT. Output %d trivially differs (PI vs. constant).  ", i/2 );
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+            pPars->iOutFail = i/2;
+            Cec_ManTransformPattern( p, i/2, NULL );
+            // the compl attributes are the same - the PI should be complemented
+            assert( Gia_ObjFaninC0(pObj1) == Gia_ObjFaninC0(pObj2) );
+            if ( Gia_ObjIsPi(p, pDri1) )
+                Abc_InfoSetBit( p->pCexComb->pData, Gia_ObjCioId(pDri1) );
+            else
+                Abc_InfoSetBit( p->pCexComb->pData, Gia_ObjCioId(pDri2) );
+            return 0;
+        }
+    }
+    if ( Gia_ManAndNum(p) == 0 )
+    {
+        Abc_Print( 1, "Networks are equivalent.  " );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+        return 1;
+    }
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [New CEC engine.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManVerify( Gia_Man_t * pInit, Cec_ParCec_t * pPars )
+{
+    int fDumpUndecided = 0;
+    Cec_ParFra_t ParsFra, * pParsFra = &ParsFra;
+    Gia_Man_t * p, * pNew;
+    int RetValue;
+    abctime clk = Abc_Clock();
+    abctime clkTotal = Abc_Clock();
+    // consider special cases:
+    // 1) (SAT) a pair of POs have different value under all-0 pattern
+    // 2) (SAT) a pair of POs has different PI/Const drivers
+    // 3) (UNSAT) 1-2 do not hold and there is no nodes
+    RetValue = Cec_ManHandleSpecialCases( pInit, pPars );
+    if ( RetValue == 0 || RetValue == 1 )
+        return RetValue;
+    // preprocess 
+    p = Gia_ManDup( pInit );
+    Gia_ManEquivFixOutputPairs( p );
+    p = Gia_ManCleanup( pNew = p );
+    Gia_ManStop( pNew );
+    // sweep for equivalences
+    Cec_ManFraSetDefaultParams( pParsFra );
+    pParsFra->nItersMax    = 1000;
+    pParsFra->nBTLimit     = pPars->nBTLimit;
+    pParsFra->TimeLimit    = pPars->TimeLimit;
+    pParsFra->fVerbose     = pPars->fVerbose;
+    pParsFra->fCheckMiter  = 1;
+    pParsFra->fDualOut     = 1;
+    pNew = Cec_ManSatSweeping( p, pParsFra );
+    pPars->iOutFail = pParsFra->iOutFail;
+    // update
+    pInit->pCexComb = p->pCexComb; p->pCexComb = NULL;
+    Gia_ManStop( p );
+    p = pInit;
+    // continue
+    if ( pNew == NULL )
+    {
+        if ( p->pCexComb != NULL )
+        {
+            if ( p->pCexComb && !Gia_ManVerifyCex( p, p->pCexComb, 1 ) )
+                Abc_Print( 1, "Counter-example simulation has failed.\n" );
+            Abc_Print( 1, "Networks are NOT EQUIVALENT.  " );
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+            return 0;
+        }
+        p = Gia_ManDup( pInit );
+        Gia_ManEquivFixOutputPairs( p );
+        p = Gia_ManCleanup( pNew = p );
+        Gia_ManStop( pNew );
+        pNew = p;
+    }
+    if ( pPars->fVerbose )
+    {
+        Abc_Print( 1, "Networks are UNDECIDED after the new CEC engine.  " );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    if ( fDumpUndecided )
+    {
+        ABC_FREE( pNew->pReprs );
+        ABC_FREE( pNew->pNexts );
+        Gia_AigerWrite( pNew, "gia_cec_undecided.aig", 0, 0 );
+        Abc_Print( 1, "The result is written into file \"%s\".\n", "gia_cec_undecided.aig" );
+    }
+    if ( pPars->TimeLimit && (Abc_Clock() - clkTotal)/CLOCKS_PER_SEC >= pPars->TimeLimit )
+    {
+        Gia_ManStop( pNew );
+        return -1;
+    }
+    // call other solver
+    if ( pPars->fVerbose )
+        Abc_Print( 1, "Calling the old CEC engine.\n" );
+    fflush( stdout );
+    RetValue = Cec_ManVerifyOld( pNew, pPars->fVerbose, &pPars->iOutFail, clkTotal );
+    p->pCexComb = pNew->pCexComb; pNew->pCexComb = NULL;
+    if ( p->pCexComb && !Gia_ManVerifyCex( p, p->pCexComb, 1 ) )
+        Abc_Print( 1, "Counter-example simulation has failed.\n" );
+    Gia_ManStop( pNew );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [New CEC engine applied to two circuits.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManVerifyTwo( Gia_Man_t * p0, Gia_Man_t * p1, int fVerbose )
+{
+    Cec_ParCec_t ParsCec, * pPars = &ParsCec;
+    Gia_Man_t * pMiter;
+    int RetValue;
+    Cec_ManCecSetDefaultParams( pPars );
+    pPars->fVerbose = fVerbose;
+    pMiter = Gia_ManMiter( p0, p1, 0, 1, 0, 0, pPars->fVerbose );
+    if ( pMiter == NULL )
+        return -1;
+    RetValue = Cec_ManVerify( pMiter, pPars );
+    p0->pCexComb = pMiter->pCexComb; pMiter->pCexComb = NULL;
+    Gia_ManStop( pMiter );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [New CEC engine applied to two circuits.]
+
+  Description [Returns 1 if equivalent, 0 if counter-example, -1 if undecided.
+  Counter-example is returned in the first manager as pAig0->pSeqModel.
+  The format is given in Abc_Cex_t (file "abc\src\aig\gia\gia.h").]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManVerifyTwoAigs( Aig_Man_t * pAig0, Aig_Man_t * pAig1, int fVerbose )
+{
+    Gia_Man_t * p0, * p1, * pTemp;
+    int RetValue;
+
+    p0 = Gia_ManFromAig( pAig0 );
+    p0 = Gia_ManCleanup( pTemp = p0 );
+    Gia_ManStop( pTemp );
+
+    p1 = Gia_ManFromAig( pAig1 );
+    p1 = Gia_ManCleanup( pTemp = p1 );
+    Gia_ManStop( pTemp );
+
+    RetValue = Cec_ManVerifyTwo( p0, p1, fVerbose );
+    pAig0->pSeqModel = p0->pCexComb; p0->pCexComb = NULL;
+    Gia_ManStop( p0 );
+    Gia_ManStop( p1 );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implementation of new signal correspodence.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Cec_LatchCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat )
+{
+    Gia_Man_t * pGia;
+    Cec_ParCor_t CorPars, * pCorPars = &CorPars;
+    Cec_ManCorSetDefaultParams( pCorPars );
+    pCorPars->fLatchCorr = 1;
+    pCorPars->fUseCSat   = fUseCSat;
+    pCorPars->nBTLimit   = nConfs;
+    pGia = Gia_ManFromAigSimple( pAig );
+    Cec_ManLSCorrespondenceClasses( pGia, pCorPars );
+    Gia_ManReprToAigRepr( pAig, pGia );
+    Gia_ManStop( pGia );
+    return Aig_ManDupSimple( pAig );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implementation of new signal correspodence.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Cec_SignalCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat )
+{
+    Gia_Man_t * pGia;
+    Cec_ParCor_t CorPars, * pCorPars = &CorPars;
+    Cec_ManCorSetDefaultParams( pCorPars );
+    pCorPars->fUseCSat  = fUseCSat;
+    pCorPars->nBTLimit  = nConfs;
+    pGia = Gia_ManFromAigSimple( pAig );
+    Cec_ManLSCorrespondenceClasses( pGia, pCorPars );
+    Gia_ManReprToAigRepr( pAig, pGia );
+    Gia_ManStop( pGia );
+    return Aig_ManDupSimple( pAig );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implementation of fraiging.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Cec_FraigCombinational( Aig_Man_t * pAig, int nConfs, int fVerbose )
+{
+    Gia_Man_t * pGia;
+    Cec_ParFra_t FraPars, * pFraPars = &FraPars;
+    Cec_ManFraSetDefaultParams( pFraPars );
+    pFraPars->fSatSweeping = 1;
+    pFraPars->nBTLimit  = nConfs;
+    pFraPars->nItersMax = 20;
+    pFraPars->fVerbose  = fVerbose;
+    pGia = Gia_ManFromAigSimple( pAig );
+    Cec_ManSatSweeping( pGia, pFraPars );
+    Gia_ManReprToAigRepr( pAig, pGia );
+    Gia_ManStop( pGia );
+    return Aig_ManDupSimple( pAig );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/cec/cecChoice.c b/abc-build/src/proof/cec/cecChoice.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/cecChoice.c
@@ -0,0 +1,410 @@
+/**CFile****************************************************************
+
+  FileName    [cecChoice.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Combinational equivalence checking.]
+
+  Synopsis    [Computation of structural choices.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cecChoice.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+#include "aig/gia/giaAig.h"
+#include "proof/dch/dch.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Cec_ManCombSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj );
+
+extern int Cec_ManResimulateCounterExamplesComb( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore );
+extern int Gia_ManCheckRefinements( Gia_Man_t * p, Vec_Str_t * vStatus, Vec_Int_t * vOutputs, Cec_ManSim_t * pSim, int fRings );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the real value of the literal w/o spec reduction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cec_ManCombSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    assert( Gia_ObjIsAnd(pObj) );
+    Cec_ManCombSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    Cec_ManCombSpecReduce_rec( pNew, p, Gia_ObjFanin1(pObj) );
+    return Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively performs speculative reduction for the object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManCombSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    Gia_Obj_t * pRepr;
+    if ( ~pObj->Value )
+        return;
+    if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+    {
+        Cec_ManCombSpecReduce_rec( pNew, p, pRepr );
+        pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) );
+        return;
+    }
+    pObj->Value = Cec_ManCombSpecReal( pNew, p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives SRM for signal correspondence.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Cec_ManCombSpecReduce( Gia_Man_t * p, Vec_Int_t ** pvOutputs, int fRings )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pRepr;
+    Vec_Int_t * vXorLits;
+    int i, iPrev, iObj, iPrevNew, iObjNew;
+    assert( p->pReprs != NULL );
+    Gia_ManSetPhase( p );
+    Gia_ManFillValue( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    *pvOutputs = Vec_IntAlloc( 1000 );
+    vXorLits = Vec_IntAlloc( 1000 );
+    if ( fRings )
+    {
+        Gia_ManForEachObj1( p, pObj, i )
+        {
+            if ( Gia_ObjIsConst( p, i ) )
+            {
+                iObjNew = Cec_ManCombSpecReal( pNew, p, pObj );
+                iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) );
+                if ( iObjNew != 0 )
+                {
+                    Vec_IntPush( *pvOutputs, 0 );
+                    Vec_IntPush( *pvOutputs, i );
+                    Vec_IntPush( vXorLits, iObjNew );
+                }
+            }
+            else if ( Gia_ObjIsHead( p, i ) )
+            {
+                iPrev = i;
+                Gia_ClassForEachObj1( p, i, iObj )
+                {
+                    iPrevNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iPrev) );
+                    iObjNew  = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iObj) );
+                    iPrevNew = Abc_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) );
+                    iObjNew  = Abc_LitNotCond( iObjNew,  Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) );
+                    if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 )
+                    {
+                        Vec_IntPush( *pvOutputs, iPrev );
+                        Vec_IntPush( *pvOutputs, iObj );
+                        Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) );
+                    }
+                    iPrev = iObj;
+                }
+                iObj = i;
+                iPrevNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iPrev) );
+                iObjNew  = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iObj) );
+                iPrevNew = Abc_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) );
+                iObjNew  = Abc_LitNotCond( iObjNew,  Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) );
+                if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 )
+                {
+                    Vec_IntPush( *pvOutputs, iPrev );
+                    Vec_IntPush( *pvOutputs, iObj );
+                    Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) );
+                }
+            }
+        }
+    }
+    else
+    {
+        Gia_ManForEachObj1( p, pObj, i )
+        {
+            pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) );
+            if ( pRepr == NULL )
+                continue;
+            iPrevNew = Gia_ObjIsConst(p, i)? 0 : Cec_ManCombSpecReal( pNew, p, pRepr );
+            iObjNew  = Cec_ManCombSpecReal( pNew, p, pObj );
+            iObjNew  = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) );
+            if ( iPrevNew != iObjNew )
+            {
+                Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) );
+                Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) );
+                Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) );
+            }
+        }
+    }
+    Vec_IntForEachEntry( vXorLits, iObjNew, i )
+        Gia_ManAppendCo( pNew, iObjNew );
+    Vec_IntFree( vXorLits );
+    Gia_ManHashStop( pNew );
+//Abc_Print( 1, "Before sweeping = %d\n", Gia_ManAndNum(pNew) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+//Abc_Print( 1, "After sweeping = %d\n", Gia_ManAndNum(pNew) );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManChoiceComputation_int( Gia_Man_t * pAig, Cec_ParChc_t * pPars )
+{
+    int nItersMax = 1000;
+    Vec_Str_t * vStatus;
+    Vec_Int_t * vOutputs;
+    Vec_Int_t * vCexStore;
+    Cec_ParSim_t ParsSim, * pParsSim = &ParsSim;
+    Cec_ParSat_t ParsSat, * pParsSat = &ParsSat;
+    Cec_ManSim_t * pSim;
+    Gia_Man_t * pSrm;
+    int r, RetValue;
+    abctime clkSat = 0, clkSim = 0, clkSrm = 0, clkTotal = Abc_Clock();
+    abctime clk2, clk = Abc_Clock();
+    ABC_FREE( pAig->pReprs );
+    ABC_FREE( pAig->pNexts );
+    Gia_ManRandom( 1 );
+    // prepare simulation manager
+    Cec_ManSimSetDefaultParams( pParsSim );
+    pParsSim->nWords     = pPars->nWords;
+    pParsSim->nFrames    = pPars->nRounds;
+    pParsSim->fVerbose   = pPars->fVerbose;
+    pParsSim->fLatchCorr   = 0;
+    pParsSim->fSeqSimulate = 0;
+    // create equivalence classes of registers
+    pSim = Cec_ManSimStart( pAig, pParsSim );
+    Cec_ManSimClassesPrepare( pSim, -1 );
+    Cec_ManSimClassesRefine( pSim );
+    // prepare SAT solving
+    Cec_ManSatSetDefaultParams( pParsSat );
+    pParsSat->nBTLimit = pPars->nBTLimit;
+    pParsSat->fVerbose = pPars->fVerbose;
+    if ( pPars->fVerbose )
+    {
+        Abc_Print( 1, "Obj = %7d. And = %7d. Conf = %5d. Ring = %d. CSat = %d.\n",
+            Gia_ManObjNum(pAig), Gia_ManAndNum(pAig), pPars->nBTLimit, pPars->fUseRings, pPars->fUseCSat );
+        Cec_ManRefinedClassPrintStats( pAig, NULL, 0, Abc_Clock() - clk );
+    }
+    // perform refinement of equivalence classes
+    for ( r = 0; r < nItersMax; r++ )
+    { 
+        clk = Abc_Clock();
+        // perform speculative reduction
+        clk2 = Abc_Clock();
+        pSrm = Cec_ManCombSpecReduce( pAig, &vOutputs, pPars->fUseRings );
+        assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManCiNum(pSrm) == Gia_ManCiNum(pAig) );
+        clkSrm += Abc_Clock() - clk2;
+        if ( Gia_ManCoNum(pSrm) == 0 )
+        {
+            if ( pPars->fVerbose )
+                Cec_ManRefinedClassPrintStats( pAig, NULL, r+1, Abc_Clock() - clk );
+            Vec_IntFree( vOutputs );
+            Gia_ManStop( pSrm );            
+            break;
+        }
+//Gia_DumpAiger( pSrm, "choicesrm", r, 2 );
+        // found counter-examples to speculation
+        clk2 = Abc_Clock();
+        if ( pPars->fUseCSat )
+            vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 );
+        else
+            vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus );
+        Gia_ManStop( pSrm );
+        clkSat += Abc_Clock() - clk2;
+        if ( Vec_IntSize(vCexStore) == 0 )
+        {
+            if ( pPars->fVerbose )
+                Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, Abc_Clock() - clk );
+            Vec_IntFree( vCexStore );
+            Vec_StrFree( vStatus );
+            Vec_IntFree( vOutputs );
+            break;
+        }
+        // refine classes with these counter-examples
+        clk2 = Abc_Clock();
+        RetValue = Cec_ManResimulateCounterExamplesComb( pSim, vCexStore );
+        Vec_IntFree( vCexStore );
+        clkSim += Abc_Clock() - clk2;
+        Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings );
+        if ( pPars->fVerbose )
+            Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, Abc_Clock() - clk );
+        Vec_StrFree( vStatus );
+        Vec_IntFree( vOutputs );
+//Gia_ManEquivPrintClasses( pAig, 1, 0 );
+    }
+    // check the overflow
+    if ( r == nItersMax )
+        Abc_Print( 1, "The refinement was not finished. The result may be incorrect.\n" );
+    Cec_ManSimStop( pSim );
+    clkTotal = Abc_Clock() - clkTotal;
+    // report the results
+    if ( pPars->fVerbose )
+    {
+        Abc_PrintTimeP( 1, "Srm  ", clkSrm,                        clkTotal );
+        Abc_PrintTimeP( 1, "Sat  ", clkSat,                        clkTotal );
+        Abc_PrintTimeP( 1, "Sim  ", clkSim,                        clkTotal );
+        Abc_PrintTimeP( 1, "Other", clkTotal-clkSat-clkSrm-clkSim, clkTotal );
+        Abc_PrintTime( 1, "TOTAL",  clkTotal );
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes choices for the vector of AIGs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Cec_ManChoiceComputationVec( Gia_Man_t * pGia, int nGias, Cec_ParChc_t * pPars )
+{
+    Gia_Man_t * pNew;
+    int RetValue;
+    // compute equivalences of the miter
+//    pMiter = Gia_ManChoiceMiter( vGias );
+//    Gia_ManSetRegNum( pMiter, 0 );
+    RetValue = Cec_ManChoiceComputation_int( pGia, pPars );
+    // derive AIG with choices
+    pNew = Gia_ManEquivToChoices( pGia, nGias );
+//    Gia_ManHasChoices_very_old( pNew );
+//    Gia_ManStop( pMiter );
+    // report the results
+    if ( pPars->fVerbose )
+    {
+//        Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%).  RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", 
+//            Gia_ManAndNum(pAig), Gia_ManAndNum(pNew), 
+//            100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(pNew))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1), 
+//            Gia_ManRegNum(pAig), Gia_ManRegNum(pNew), 
+//            100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(pNew))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) );
+    }
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes choices for one AIGs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Cec_ManChoiceComputation( Gia_Man_t * pAig, Cec_ParChc_t * pParsChc )
+{
+//    extern Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars );
+    Dch_Pars_t Pars, * pPars = &Pars;
+    Aig_Man_t * pMan, * pManNew;
+    Gia_Man_t * pGia;
+    if ( 0 ) 
+    {
+        pGia = Cec_ManChoiceComputationVec( pAig, 3, pParsChc );
+    }
+    else
+    {
+        pMan = Gia_ManToAig( pAig, 0 );
+        Dch_ManSetDefaultParams( pPars );
+        pPars->fUseGia  = 1;
+        pPars->nBTLimit = pParsChc->nBTLimit;
+        pPars->fUseCSat = pParsChc->fUseCSat;
+        pPars->fVerbose = pParsChc->fVerbose;
+        pManNew = Dar_ManChoiceNew( pMan, pPars );
+        pGia = Gia_ManFromAig( pManNew );
+        Aig_ManStop( pManNew );
+//        Aig_ManStop( pMan );
+    }
+    return pGia;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs computation of AIGs with choices.]
+
+  Description [Takes several AIGs and performs choicing.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Cec_ComputeChoices( Gia_Man_t * pGia, Dch_Pars_t * pPars )
+{
+    Cec_ParChc_t ParsChc, * pParsChc = &ParsChc;
+    Aig_Man_t * pAig;
+    if ( pPars->fVerbose )
+        Abc_PrintTime( 1, "Synthesis time", pPars->timeSynth );
+    Cec_ManChcSetDefaultParams( pParsChc );
+    pParsChc->nBTLimit = pPars->nBTLimit;
+    pParsChc->fUseCSat = pPars->fUseCSat;
+    if ( pParsChc->fUseCSat && pParsChc->nBTLimit > 100 )
+        pParsChc->nBTLimit = 100;
+    pParsChc->fVerbose = pPars->fVerbose;
+    pGia = Cec_ManChoiceComputationVec( pGia, 3, pParsChc );
+    Gia_ManSetRegNum( pGia, Gia_ManRegNum(pGia) );
+    pAig = Gia_ManToAig( pGia, 1 );
+    Gia_ManStop( pGia );
+    return pAig;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/cec/cecClass.c b/abc-build/src/proof/cec/cecClass.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/cecClass.c
@@ -0,0 +1,931 @@
+/**CFile****************************************************************
+
+  FileName    [cecClass.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Combinational equivalence checking.]
+
+  Synopsis    [Equivalence class refinement.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cecClass.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline unsigned * Cec_ObjSim( Cec_ManSim_t * p, int Id )            { return p->pMems + p->pSimInfo[Id] + 1;   }
+static inline void       Cec_ObjSetSim( Cec_ManSim_t * p, int Id, int n )  { p->pSimInfo[Id] = n;                     }
+
+static inline float      Cec_MemUsage( Cec_ManSim_t * p )                  { return 1.0*p->nMemsMax*(p->pPars->nWords+1)/(1<<20);   }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Compares simulation info of one node with constant 0.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSimCompareConst( unsigned * p, int nWords )
+{
+    int w;
+    if ( p[0] & 1 )
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( p[w] != ~0 )
+                return 0;
+        return 1;
+    }
+    else
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( p[w] != 0 )
+                return 0;
+        return 1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares simulation info of two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSimCompareEqual( unsigned * p0, unsigned * p1, int nWords )
+{
+    int w;
+    if ( (p0[0] & 1) == (p1[0] & 1) )
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( p0[w] != p1[w] )
+                return 0;
+        return 1;
+    }
+    else
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( p0[w] != ~p1[w] )
+                return 0;
+        return 1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of the first non-equal bit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSimCompareConstFirstBit( unsigned * p, int nWords )
+{
+    int w;
+    if ( p[0] & 1 )
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( p[w] != ~0 )
+                return 32*w + Gia_WordFindFirstBit( ~p[w] );
+        return -1;
+    }
+    else
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( p[w] != 0 )
+                return 32*w + Gia_WordFindFirstBit( p[w] );
+        return -1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares simulation info of two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSimCompareEqualFirstBit( unsigned * p0, unsigned * p1, int nWords )
+{
+    int w;
+    if ( (p0[0] & 1) == (p1[0] & 1) )
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( p0[w] != p1[w] )
+                return 32*w + Gia_WordFindFirstBit( p0[w] ^ p1[w] );
+        return -1;
+    }
+    else
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( p0[w] != ~p1[w] )
+                return 32*w + Gia_WordFindFirstBit( p0[w] ^ ~p1[w] );
+        return -1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of the first non-equal bit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSimCompareConstScore( unsigned * p, int nWords, int * pScores )
+{
+    int w, b;
+    if ( p[0] & 1 )
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( p[w] != ~0 )
+                for ( b = 0; b < 32; b++ )
+                    if ( ((~p[w]) >> b ) & 1 )
+                        pScores[32*w + b]++;
+    }
+    else
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( p[w] != 0 )
+                for ( b = 0; b < 32; b++ )
+                    if ( ((p[w]) >> b ) & 1 )
+                        pScores[32*w + b]++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares simulation info of two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSimCompareEqualScore( unsigned * p0, unsigned * p1, int nWords, int * pScores )
+{
+    int w, b;
+    if ( (p0[0] & 1) == (p1[0] & 1) )
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( p0[w] != p1[w] )
+                for ( b = 0; b < 32; b++ )
+                    if ( ((p0[w] ^ p1[w]) >> b ) & 1 )
+                        pScores[32*w + b]++;
+    }
+    else
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( p0[w] != ~p1[w] )
+                for ( b = 0; b < 32; b++ )
+                    if ( ((p0[w] ^ ~p1[w]) >> b ) & 1 )
+                        pScores[32*w + b]++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates equivalence class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSimClassCreate( Gia_Man_t * p, Vec_Int_t * vClass )
+{
+    int Repr = GIA_VOID, EntPrev = -1, Ent, i;
+    assert( Vec_IntSize(vClass) > 0 );
+    Vec_IntForEachEntry( vClass, Ent, i )
+    {
+        if ( i == 0 )
+        {
+            Repr = Ent;
+            Gia_ObjSetRepr( p, Ent, GIA_VOID );
+            EntPrev = Ent;
+        }
+        else
+        {
+            assert( Repr < Ent );
+            Gia_ObjSetRepr( p, Ent, Repr );
+            Gia_ObjSetNext( p, EntPrev, Ent );
+            EntPrev = Ent;
+        }
+    }
+    Gia_ObjSetNext( p, EntPrev, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines one equivalence class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSimClassRefineOne( Cec_ManSim_t * p, int i )
+{
+    unsigned * pSim0, * pSim1;
+    int Ent;
+    Vec_IntClear( p->vClassOld );
+    Vec_IntClear( p->vClassNew );
+    Vec_IntPush( p->vClassOld, i );
+    pSim0 = Cec_ObjSim(p, i);
+    Gia_ClassForEachObj1( p->pAig, i, Ent )
+    {
+        pSim1 = Cec_ObjSim(p, Ent);
+        if ( Cec_ManSimCompareEqual( pSim0, pSim1, p->nWords ) )
+            Vec_IntPush( p->vClassOld, Ent );
+        else
+        {
+            Vec_IntPush( p->vClassNew, Ent );
+            if ( p->pBestState )
+                Cec_ManSimCompareEqualScore( pSim0, pSim1, p->nWords, p->pScores );
+        }
+    }
+    if ( Vec_IntSize( p->vClassNew ) == 0 )
+        return 0;
+    Cec_ManSimClassCreate( p->pAig, p->vClassOld );
+    Cec_ManSimClassCreate( p->pAig, p->vClassNew );
+    if ( Vec_IntSize(p->vClassNew) > 1 )
+        return 1 + Cec_ManSimClassRefineOne( p, Vec_IntEntry(p->vClassNew,0) );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines one equivalence class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSimClassRemoveOne( Cec_ManSim_t * p, int i )
+{
+    int iRepr, Ent;
+    if ( Gia_ObjIsConst(p->pAig, i) )
+    {
+        Gia_ObjSetRepr( p->pAig, i, GIA_VOID );
+        return 1;
+    }
+    if ( !Gia_ObjIsClass(p->pAig, i) )
+        return 0;
+    assert( Gia_ObjIsClass(p->pAig, i) );
+    iRepr = Gia_ObjRepr( p->pAig, i );
+    if ( iRepr == GIA_VOID )
+        iRepr = i;
+    // collect nodes
+    Vec_IntClear( p->vClassOld );
+    Vec_IntClear( p->vClassNew );
+    Gia_ClassForEachObj( p->pAig, iRepr, Ent )
+    {
+        if ( Ent == i )
+            Vec_IntPush( p->vClassNew, Ent );
+        else
+            Vec_IntPush( p->vClassOld, Ent );
+    }
+    assert( Vec_IntSize( p->vClassNew ) == 1 );
+    Cec_ManSimClassCreate( p->pAig, p->vClassOld );
+    Cec_ManSimClassCreate( p->pAig, p->vClassNew );
+    assert( !Gia_ObjIsClass(p->pAig, i) );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash key of the simuation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSimHashKey( unsigned * pSim, int nWords, int nTableSize )
+{
+    static int s_Primes[16] = { 
+        1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, 
+        4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 };
+    unsigned uHash = 0;
+    int i;
+    if ( pSim[0] & 1 )
+        for ( i = 0; i < nWords; i++ )
+            uHash ^= ~pSim[i] * s_Primes[i & 0xf];
+    else
+        for ( i = 0; i < nWords; i++ )
+            uHash ^= pSim[i] * s_Primes[i & 0xf];
+    return (int)(uHash % nTableSize);
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resets pointers to the simulation memory.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSimMemRelink( Cec_ManSim_t * p )
+{
+    unsigned * pPlace, Ent;
+    pPlace = (unsigned *)&p->MemFree;
+    for ( Ent = p->nMems * (p->nWords + 1); 
+          Ent + p->nWords + 1 < (unsigned)p->nWordsAlloc; 
+          Ent += p->nWords + 1 )
+    {
+        *pPlace = Ent;
+        pPlace = p->pMems + Ent;
+    }
+    *pPlace = 0;
+    p->nWordsOld = p->nWords;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [References simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Cec_ManSimSimRef( Cec_ManSim_t * p, int i )
+{
+    unsigned * pSim;
+    assert( p->pSimInfo[i] == 0 );
+    if ( p->MemFree == 0 )
+    {
+        if ( p->nWordsAlloc == 0 )
+        {
+            assert( p->pMems == NULL );
+            p->nWordsAlloc = (1<<17); // -> 1Mb
+            p->nMems = 1;
+        }
+        p->nWordsAlloc *= 2;
+        p->pMems = ABC_REALLOC( unsigned, p->pMems, p->nWordsAlloc );
+        Cec_ManSimMemRelink( p );
+    }
+    p->pSimInfo[i] = p->MemFree;
+    pSim = p->pMems + p->MemFree;
+    p->MemFree = pSim[0];
+    pSim[0] = Gia_ObjValue( Gia_ManObj(p->pAig, i) );
+    p->nMems++;
+    if ( p->nMemsMax < p->nMems )
+        p->nMemsMax = p->nMems;
+    return pSim;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences simulaton info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Cec_ManSimSimDeref( Cec_ManSim_t * p, int i )
+{
+    unsigned * pSim;
+    assert( p->pSimInfo[i] > 0 );
+    pSim = p->pMems + p->pSimInfo[i];
+    if ( --pSim[0] == 0 )
+    {
+        pSim[0] = p->MemFree;
+        p->MemFree = p->pSimInfo[i];
+        p->pSimInfo[i] = 0;
+        p->nMems--;
+    }
+    return pSim;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines nodes belonging to candidate constant class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSimProcessRefined( Cec_ManSim_t * p, Vec_Int_t * vRefined )
+{
+    unsigned * pSim;
+    int * pTable, nTableSize, i, k, Key;
+    if ( Vec_IntSize(vRefined) == 0 )
+        return;
+    nTableSize = Abc_PrimeCudd( 100 + Vec_IntSize(vRefined) / 3 );
+    pTable = ABC_CALLOC( int, nTableSize );
+    Vec_IntForEachEntry( vRefined, i, k )
+    {
+        pSim = Cec_ObjSim( p, i );
+        assert( !Cec_ManSimCompareConst( pSim, p->nWords ) );
+        Key = Cec_ManSimHashKey( pSim, p->nWords, nTableSize );
+        if ( pTable[Key] == 0 )
+        {
+            assert( Gia_ObjRepr(p->pAig, i) == 0 );
+            assert( Gia_ObjNext(p->pAig, i) == 0 );
+            Gia_ObjSetRepr( p->pAig, i, GIA_VOID );
+        }
+        else
+        {
+            Gia_ObjSetNext( p->pAig, pTable[Key], i );
+            Gia_ObjSetRepr( p->pAig, i, Gia_ObjRepr(p->pAig, pTable[Key]) );
+            if ( Gia_ObjRepr(p->pAig, i) == GIA_VOID )
+                Gia_ObjSetRepr( p->pAig, i, pTable[Key] );
+            assert( Gia_ObjRepr(p->pAig, i) > 0 );
+        }
+        pTable[Key] = i;
+    }
+    Vec_IntForEachEntry( vRefined, i, k )
+    {
+        if ( Gia_ObjIsHead( p->pAig, i ) )
+            Cec_ManSimClassRefineOne( p, i );
+    }
+    Vec_IntForEachEntry( vRefined, i, k )
+        Cec_ManSimSimDeref( p, i );
+    ABC_FREE( pTable );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Saves the input pattern with the given number.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSimSavePattern( Cec_ManSim_t * p, int iPat )
+{
+    unsigned * pInfo;
+    int i;
+    assert( p->pCexComb == NULL );
+    assert( iPat >= 0 && iPat < 32 * p->nWords );
+    p->pCexComb = (Abc_Cex_t *)ABC_CALLOC( char, 
+        sizeof(Abc_Cex_t) + sizeof(unsigned) * Abc_BitWordNum(Gia_ManCiNum(p->pAig)) );
+    p->pCexComb->iPo = p->iOut;
+    p->pCexComb->nPis = Gia_ManCiNum(p->pAig);
+    p->pCexComb->nBits = Gia_ManCiNum(p->pAig);
+    for ( i = 0; i < Gia_ManCiNum(p->pAig); i++ )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, i );
+        if ( Abc_InfoHasBit( pInfo, iPat ) )
+            Abc_InfoSetBit( p->pCexComb->pData, i );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the best pattern using the scores.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSimFindBestPattern( Cec_ManSim_t * p )
+{ 
+    unsigned * pInfo;
+    int i, ScoreBest = 0, iPatBest = 1; // set the first pattern
+    // find the best pattern
+    for ( i = 0; i < 32 * p->nWords; i++ )
+        if ( ScoreBest < p->pScores[i] )
+        {
+            ScoreBest = p->pScores[i];
+            iPatBest = i;
+        }
+    // compare this with the available patterns - and save
+    if ( p->pBestState->iPo <= ScoreBest )
+    {
+        assert( p->pBestState->nRegs == Gia_ManRegNum(p->pAig) );
+        for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ )
+        {
+            pInfo = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, Gia_ManPiNum(p->pAig) + i );
+            if ( Abc_InfoHasBit(p->pBestState->pData, i) != Abc_InfoHasBit(pInfo, iPatBest) )
+                Abc_InfoXorBit( p->pBestState->pData, i );
+        }
+        p->pBestState->iPo = ScoreBest;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if computation should stop.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSimAnalyzeOutputs( Cec_ManSim_t * p )
+{
+    unsigned * pInfo, * pInfo2;
+    int i;
+    if ( !p->pPars->fCheckMiter )
+        return 0;
+    assert( p->vCoSimInfo != NULL );
+    // compare outputs with 0
+    if ( p->pPars->fDualOut )
+    {
+        assert( (Gia_ManPoNum(p->pAig) & 1) == 0 );
+        for ( i = 0; i < Gia_ManPoNum(p->pAig); i++ )
+        {
+            pInfo  = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, i );
+            pInfo2 = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, ++i );
+            if ( !Cec_ManSimCompareEqual( pInfo, pInfo2, p->nWords ) )
+            {
+                if ( p->iOut == -1 )
+                {
+                    p->iOut = i/2;
+                    Cec_ManSimSavePattern( p, Cec_ManSimCompareEqualFirstBit(pInfo, pInfo2, p->nWords) );
+                }
+                if ( p->pCexes == NULL )
+                    p->pCexes = ABC_CALLOC( void *, Gia_ManPoNum(p->pAig)/2 );
+                if ( p->pCexes[i/2] == NULL )
+                {
+                    p->nOuts++;
+                    p->pCexes[i/2] = (void *)1;
+                }
+            }
+        }
+    }
+    else
+    {
+        for ( i = 0; i < Gia_ManPoNum(p->pAig); i++ )
+        {
+            pInfo = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, i );
+            if ( !Cec_ManSimCompareConst( pInfo, p->nWords ) )
+            {
+                if ( p->iOut == -1 )
+                {
+                    p->iOut = i;
+                    Cec_ManSimSavePattern( p, Cec_ManSimCompareConstFirstBit(pInfo, p->nWords) );
+                }
+                if ( p->pCexes == NULL )
+                    p->pCexes = ABC_CALLOC( void *, Gia_ManPoNum(p->pAig) );
+                if ( p->pCexes[i] == NULL )
+                {
+                    p->nOuts++;
+                    p->pCexes[i] = (void *)1;
+                }
+            }
+        }
+    }
+    return p->pCexes != NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one round.]
+
+  Description [Returns the number of PO entry if failed; 0 otherwise.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSimSimulateRound( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos )
+{
+    Gia_Obj_t * pObj;
+    unsigned * pRes0, * pRes1, * pRes;
+    int i, k, w, Ent, iCiId = 0, iCoId = 0;
+    // prepare internal storage
+    if ( p->nWordsOld != p->nWords )
+        Cec_ManSimMemRelink( p );
+    p->nMemsMax = 0;
+    // allocate score counters
+    ABC_FREE( p->pScores );
+    if ( p->pBestState )
+        p->pScores = ABC_CALLOC( int, 32 * p->nWords );
+    // simulate nodes
+    Vec_IntClear( p->vRefinedC );
+    if ( Gia_ObjValue(Gia_ManConst0(p->pAig)) )
+    {
+        pRes = Cec_ManSimSimRef( p, 0 );
+        for ( w = 1; w <= p->nWords; w++ )
+            pRes[w] = 0;
+    }
+    Gia_ManForEachObj1( p->pAig, pObj, i )
+    {
+        if ( Gia_ObjIsCi(pObj) ) 
+        {
+            if ( Gia_ObjValue(pObj) == 0 )
+            {
+                iCiId++;
+                continue;
+            }
+            pRes = Cec_ManSimSimRef( p, i );
+            if ( vInfoCis ) 
+            {
+                pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, iCiId++ );
+                for ( w = 1; w <= p->nWords; w++ )
+                    pRes[w] = pRes0[w-1];
+            }
+            else
+            {
+                for ( w = 1; w <= p->nWords; w++ )
+                    pRes[w] = Gia_ManRandom( 0 );
+            }
+            // make sure the first pattern is always zero
+            pRes[1] ^= (pRes[1] & 1);
+            goto references;
+        }
+        if ( Gia_ObjIsCo(pObj) ) // co always has non-zero 1st fanin and zero 2nd fanin
+        {
+            pRes0 = Cec_ManSimSimDeref( p, Gia_ObjFaninId0(pObj,i) );
+            if ( vInfoCos )
+            {
+                pRes = (unsigned *)Vec_PtrEntry( vInfoCos, iCoId++ );
+                if ( Gia_ObjFaninC0(pObj) )
+                    for ( w = 1; w <= p->nWords; w++ )
+                        pRes[w-1] = ~pRes0[w];
+                else 
+                    for ( w = 1; w <= p->nWords; w++ )
+                        pRes[w-1] = pRes0[w];
+            }
+            continue;
+        }
+        assert( Gia_ObjValue(pObj) );
+        pRes  = Cec_ManSimSimRef( p, i );
+        pRes0 = Cec_ManSimSimDeref( p, Gia_ObjFaninId0(pObj,i) );
+        pRes1 = Cec_ManSimSimDeref( p, Gia_ObjFaninId1(pObj,i) );
+
+//        Abc_Print( 1, "%d,%d  ", Gia_ObjValue( Gia_ObjFanin0(pObj) ), Gia_ObjValue( Gia_ObjFanin1(pObj) ) );
+
+        if ( Gia_ObjFaninC0(pObj) )
+        {
+            if ( Gia_ObjFaninC1(pObj) )
+                for ( w = 1; w <= p->nWords; w++ )
+                    pRes[w] = ~(pRes0[w] | pRes1[w]);
+            else
+                for ( w = 1; w <= p->nWords; w++ )
+                    pRes[w] = ~pRes0[w] & pRes1[w];
+        }
+        else
+        {
+            if ( Gia_ObjFaninC1(pObj) )
+                for ( w = 1; w <= p->nWords; w++ )
+                    pRes[w] = pRes0[w] & ~pRes1[w];
+            else
+                for ( w = 1; w <= p->nWords; w++ )
+                    pRes[w] = pRes0[w] & pRes1[w];
+        }
+
+references:
+        // if this node is candidate constant, collect it
+        if ( Gia_ObjIsConst(p->pAig, i) && !Cec_ManSimCompareConst(pRes + 1, p->nWords) )
+        {
+            pRes[0]++;
+            Vec_IntPush( p->vRefinedC, i );
+            if ( p->pBestState )
+                Cec_ManSimCompareConstScore( pRes + 1, p->nWords, p->pScores );
+        }
+        // if the node belongs to a class, save it
+        if ( Gia_ObjIsClass(p->pAig, i) )
+            pRes[0]++;
+        // if this is the last node of the class, process it
+        if ( Gia_ObjIsTail(p->pAig, i) )
+        {
+            Vec_IntClear( p->vClassTemp );
+            Gia_ClassForEachObj( p->pAig, Gia_ObjRepr(p->pAig, i), Ent )
+                Vec_IntPush( p->vClassTemp, Ent );
+            Cec_ManSimClassRefineOne( p, Gia_ObjRepr(p->pAig, i) );
+            Vec_IntForEachEntry( p->vClassTemp, Ent, k )
+                Cec_ManSimSimDeref( p, Ent );
+        }
+    }
+
+    if ( p->pPars->fConstCorr )
+    {
+        Vec_IntForEachEntry( p->vRefinedC, i, k )
+        {
+            Gia_ObjSetRepr( p->pAig, i, GIA_VOID );
+            Cec_ManSimSimDeref( p, i );
+        }
+        Vec_IntClear( p->vRefinedC );
+    }
+
+    if ( Vec_IntSize(p->vRefinedC) > 0 )
+        Cec_ManSimProcessRefined( p, p->vRefinedC );
+    assert( vInfoCis == NULL || iCiId == Gia_ManCiNum(p->pAig) );
+    assert( vInfoCos == NULL || iCoId == Gia_ManCoNum(p->pAig) );
+    assert( p->nMems == 1 );
+    if ( p->nMems != 1 )
+        Abc_Print( 1, "Cec_ManSimSimulateRound(): Memory management error!\n" );
+    if ( p->pPars->fVeryVerbose )
+        Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) );
+    if ( p->pBestState )
+        Cec_ManSimFindBestPattern( p );
+/*
+    if ( p->nMems > 1 ) {
+        for ( i = 1; i < p->nObjs; i++ )
+        if ( p->pSims[i] ) {
+            int x = 0;
+        }
+    }
+*/
+    return Cec_ManSimAnalyzeOutputs( p );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates simulation info for this round.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSimCreateInfo( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos )
+{
+    unsigned * pRes0, * pRes1;
+    int i, w;
+    if ( p->pPars->fSeqSimulate && Gia_ManRegNum(p->pAig) > 0 )
+    {
+        assert( vInfoCis && vInfoCos );
+        for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ )
+        {
+            pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, i );
+            for ( w = 0; w < p->nWords; w++ )
+                pRes0[w] = Gia_ManRandom( 0 );
+        }
+        for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ )
+        {
+            pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, Gia_ManPiNum(p->pAig) + i );
+            pRes1 = (unsigned *)Vec_PtrEntry( vInfoCos, Gia_ManPoNum(p->pAig) + i );
+            for ( w = 0; w < p->nWords; w++ )
+                pRes0[w] = pRes1[w];
+        }
+    }
+    else 
+    {
+        for ( i = 0; i < Gia_ManCiNum(p->pAig); i++ )
+        {
+            pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, i );
+            for ( w = 0; w < p->nWords; w++ )
+                pRes0[w] = Gia_ManRandom( 0 );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the bug is found.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSimClassesPrepare( Cec_ManSim_t * p, int LevelMax )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    assert( p->pAig->pReprs == NULL );
+    // allocate representation
+    p->pAig->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p->pAig) );
+    p->pAig->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p->pAig) );
+    // create references
+    Gia_ManCreateValueRefs( p->pAig );
+    // set starting representative of internal nodes to be constant 0
+    if ( p->pPars->fLatchCorr )
+        Gia_ManForEachObj( p->pAig, pObj, i )
+            Gia_ObjSetRepr( p->pAig, i, GIA_VOID );
+    else if ( LevelMax == -1 )
+        Gia_ManForEachObj( p->pAig, pObj, i )
+            Gia_ObjSetRepr( p->pAig, i, Gia_ObjIsAnd(pObj) ? 0 : GIA_VOID );
+    else
+    {
+        Gia_ManLevelNum( p->pAig );
+        Gia_ManForEachObj( p->pAig, pObj, i )
+            Gia_ObjSetRepr( p->pAig, i, (Gia_ObjIsAnd(pObj) && Gia_ObjLevel(p->pAig,pObj) <= LevelMax) ? 0 : GIA_VOID );
+        Vec_IntFreeP( &p->pAig->vLevels );
+    }
+    // if sequential simulation, set starting representative of ROs to be constant 0
+    if ( p->pPars->fSeqSimulate )
+        Gia_ManForEachRo( p->pAig, pObj, i )
+            if ( pObj->Value )
+                Gia_ObjSetRepr( p->pAig, Gia_ObjId(p->pAig, pObj), 0 );
+    // perform simulation
+    p->nWords = 1;
+    do {
+        if ( p->pPars->fVerbose )
+            Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) );
+        for ( i = 0; i < 4; i++ )
+        {
+            Cec_ManSimCreateInfo( p, p->vCiSimInfo, p->vCoSimInfo );
+            if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) )
+                return 1;
+        }
+        p->nWords = 2 * p->nWords + 1;
+    }
+    while ( p->nWords <= p->pPars->nWords );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the bug is found.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSimClassesRefine( Cec_ManSim_t * p )
+{
+    int i;
+    Gia_ManCreateValueRefs( p->pAig );
+    p->nWords = p->pPars->nWords;
+    for ( i = 0; i < p->pPars->nRounds; i++ )
+    {
+        if ( (i % (p->pPars->nRounds / 5)) == 0 && p->pPars->fVerbose )
+            Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) );
+        Cec_ManSimCreateInfo( p, p->vCiSimInfo, p->vCoSimInfo );
+        if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) )
+            return 1;
+    }
+    if ( p->pPars->fVerbose )
+        Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) );
+    return 0;
+}
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/cec/cecCore.c b/abc-build/src/proof/cec/cecCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/cecCore.c
@@ -0,0 +1,543 @@
+/**CFile****************************************************************
+
+  FileName    [cecCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Combinational equivalence checking.]
+
+  Synopsis    [Core procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cecCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+void Cec_ManSatSetDefaultParams( Cec_ParSat_t * p )
+{
+    memset( p, 0, sizeof(Cec_ParSat_t) );
+    p->nBTLimit       =     100;  // conflict limit at a node
+    p->nSatVarMax     =    2000;  // the max number of SAT variables
+    p->nCallsRecycle  =     200;  // calls to perform before recycling SAT solver
+    p->fNonChrono     =       0;  // use non-chronological backtracling (for circuit SAT only)
+    p->fPolarFlip     =       1;  // flops polarity of variables
+    p->fCheckMiter    =       0;  // the circuit is the miter
+//    p->fFirstStop     =       0;  // stop on the first sat output
+    p->fLearnCls      =       0;  // perform clause learning
+    p->fVerbose       =       0;  // verbose stats
+}  
+
+/**Function************  *************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSimSetDefaultParams( Cec_ParSim_t * p )
+{
+    memset( p, 0, sizeof(Cec_ParSim_t) );
+    p->nWords         =      31;  // the number of simulation words
+    p->nFrames        =     100;  // the number of simulation frames
+    p->nRounds        =      20;  // the max number of simulation rounds
+    p->nNonRefines    =       3;  // the max number of rounds without refinement
+    p->TimeLimit      =       0;  // the runtime limit in seconds
+    p->fCheckMiter    =       0;  // the circuit is the miter
+//    p->fFirstStop     =       0;  // stop on the first sat output
+    p->fDualOut       =       0;  // miter with separate outputs
+    p->fConstCorr     =       0;  // consider only constants
+    p->fSeqSimulate   =       0;  // performs sequential simulation
+    p->fVeryVerbose   =       0;  // verbose stats
+    p->fVerbose       =       0;  // verbose stats
+} 
+
+/**Function************  *************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSmfSetDefaultParams( Cec_ParSmf_t * p )
+{
+    memset( p, 0, sizeof(Cec_ParSmf_t) );
+    p->nWords         =      31;  // the number of simulation words
+    p->nRounds        =     200;  // the number of simulation rounds
+    p->nFrames        =     200;  // the max number of time frames
+    p->nNonRefines    =       3;  // the max number of rounds without refinement
+    p->nMinOutputs    =       0;  // the min outputs to accumulate
+    p->nBTLimit       =     100;  // conflict limit at a node
+    p->TimeLimit      =       0;  // the runtime limit in seconds
+    p->fDualOut       =       0;  // miter with separate outputs
+    p->fCheckMiter    =       0;  // the circuit is the miter
+//    p->fFirstStop     =       0;  // stop on the first sat output
+    p->fVerbose       =       0;  // verbose stats
+} 
+
+/**Function************  *************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManFraSetDefaultParams( Cec_ParFra_t * p )
+{
+    memset( p, 0, sizeof(Cec_ParFra_t) );
+    p->nWords         =      15;  // the number of simulation words
+    p->nRounds        =      15;  // the number of simulation rounds
+    p->TimeLimit      =       0;  // the runtime limit in seconds
+    p->nItersMax      =      10;  // the maximum number of iterations of SAT sweeping
+    p->nBTLimit       =     100;  // conflict limit at a node
+    p->nLevelMax      =       0;  // restriction on the level of nodes to be swept
+    p->nDepthMax      =       1;  // the depth in terms of steps of speculative reduction
+    p->fRewriting     =       0;  // enables AIG rewriting
+    p->fCheckMiter    =       0;  // the circuit is the miter
+//    p->fFirstStop     =       0;  // stop on the first sat output
+    p->fDualOut       =       0;  // miter with separate outputs
+    p->fColorDiff     =       0;  // miter with separate outputs
+    p->fSatSweeping   =       0;  // enable SAT sweeping
+    p->fVeryVerbose   =       0;  // verbose stats
+    p->fVerbose       =       0;  // verbose stats
+    p->iOutFail       =      -1;  // the failed output
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManCecSetDefaultParams( Cec_ParCec_t * p )
+{
+    memset( p, 0, sizeof(Cec_ParCec_t) );
+    p->nBTLimit       =    1000;  // conflict limit at a node
+    p->TimeLimit      =       0;  // the runtime limit in seconds
+//    p->fFirstStop     =       0;  // stop on the first sat output
+    p->fUseSmartCnf   =       0;  // use smart CNF computation
+    p->fRewriting     =       0;  // enables AIG rewriting
+    p->fVeryVerbose   =       0;  // verbose stats
+    p->fVerbose       =       0;  // verbose stats
+    p->iOutFail       =      -1;  // the number of failed output
+}  
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManCorSetDefaultParams( Cec_ParCor_t * p )
+{
+    memset( p, 0, sizeof(Cec_ParCor_t) );
+    p->nWords         =      15;  // the number of simulation words
+    p->nRounds        =      15;  // the number of simulation rounds
+    p->nFrames        =       1;  // the number of time frames
+    p->nBTLimit       =     100;  // conflict limit at a node
+    p->nLevelMax      =      -1;  // (scorr only) the max number of levels
+    p->nStepsMax      =      -1;  // (scorr only) the max number of induction steps
+    p->fLatchCorr     =       0;  // consider only latch outputs
+    p->fConstCorr     =       0;  // consider only constants
+    p->fUseRings      =       1;  // combine classes into rings
+    p->fUseCSat       =       1;  // use circuit-based solver
+//    p->fFirstStop     =       0;  // stop on the first sat output
+    p->fUseSmartCnf   =       0;  // use smart CNF computation
+    p->fVeryVerbose   =       0;  // verbose stats
+    p->fVerbose       =       0;  // verbose stats
+}  
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManChcSetDefaultParams( Cec_ParChc_t * p )
+{
+    memset( p, 0, sizeof(Cec_ParChc_t) );
+    p->nWords         =      15;  // the number of simulation words
+    p->nRounds        =      15;  // the number of simulation rounds
+    p->nBTLimit       =    1000;  // conflict limit at a node
+    p->fUseRings      =       1;  // use rings
+    p->fUseCSat       =       0;  // use circuit-based solver
+    p->fVeryVerbose   =       0;  // verbose stats
+    p->fVerbose       =       0;  // verbose stats
+}  
+
+/**Function*************************************************************
+
+  Synopsis    [Core procedure for SAT sweeping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Cec_ManSatSolving( Gia_Man_t * pAig, Cec_ParSat_t * pPars )
+{
+    Gia_Man_t * pNew;
+    Cec_ManPat_t * pPat;
+    pPat = Cec_ManPatStart();
+    Cec_ManSatSolve( pPat, pAig, pPars );
+//    pNew = Gia_ManDupDfsSkip( pAig );
+    pNew = Gia_ManDup( pAig );
+    Cec_ManPatStop( pPat );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Core procedure for simulation.]
+
+  Description [Returns 1 if refinement has happened.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSimulationOne( Gia_Man_t * pAig, Cec_ParSim_t * pPars )
+{
+    Cec_ManSim_t * pSim;
+    int RetValue = 0;
+    abctime clkTotal = Abc_Clock();
+    pSim = Cec_ManSimStart( pAig, pPars );
+    if ( (pAig->pReprs == NULL && (RetValue = Cec_ManSimClassesPrepare( pSim, -1 ))) ||
+         (RetValue == 0 &&        (RetValue = Cec_ManSimClassesRefine( pSim ))) )
+        Abc_Print( 1, "The number of failed outputs of the miter = %6d. (Words = %4d. Frames = %4d.)\n", 
+            pSim->nOuts, pPars->nWords, pPars->nFrames );
+    if ( pPars->fVerbose )
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+    Cec_ManSimStop( pSim );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Core procedure for simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSimulation( Gia_Man_t * pAig, Cec_ParSim_t * pPars )
+{
+    int r, nLitsOld, nLitsNew, nCountNoRef = 0, fStop = 0;
+    Gia_ManRandom( 1 );
+    if ( pPars->fSeqSimulate )
+        Abc_Print( 1, "Performing rounds of random simulation of %d frames with %d words.\n", 
+            pPars->nRounds, pPars->nFrames, pPars->nWords );
+    nLitsOld = Gia_ManEquivCountLits( pAig );
+    for ( r = 0; r < pPars->nRounds; r++ )
+    {
+        if ( Cec_ManSimulationOne( pAig, pPars ) )
+        {
+            fStop = 1;
+            break;
+        }
+        // decide when to stop
+        nLitsNew = Gia_ManEquivCountLits( pAig );
+        if ( nLitsOld == 0 || nLitsOld > nLitsNew )
+        {
+            nLitsOld = nLitsNew;
+            nCountNoRef = 0;
+        }
+        else if ( ++nCountNoRef == pPars->nNonRefines )
+        {
+            r++;
+            break;
+        }
+        assert( nLitsOld == nLitsNew );
+    }
+//    if ( pPars->fVerbose )
+    if ( r == pPars->nRounds || fStop )
+        Abc_Print( 1, "Random simulation is stopped after %d rounds.\n", r );
+    else
+        Abc_Print( 1, "Random simulation saturated after %d rounds.\n", r );
+    if ( pPars->fCheckMiter )
+    {
+        int nNonConsts = Cec_ManCountNonConstOutputs( pAig );
+        if ( nNonConsts )
+            Abc_Print( 1, "The number of POs that are not const-0 candidates = %d.\n", nNonConsts );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Core procedure for SAT sweeping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Cec_ManSatSweeping( Gia_Man_t * pAig, Cec_ParFra_t * pPars )
+{
+    int fOutputResult = 0;
+    Cec_ParSat_t ParsSat, * pParsSat = &ParsSat;
+    Cec_ParSim_t ParsSim, * pParsSim = &ParsSim;
+    Gia_Man_t * pIni, * pSrm, * pTemp;
+    Cec_ManFra_t * p;
+    Cec_ManSim_t * pSim;
+    Cec_ManPat_t * pPat;
+    int i, fTimeOut = 0, nMatches = 0;
+    abctime clk, clk2, clkTotal = Abc_Clock();
+
+    // duplicate AIG and transfer equivalence classes
+    Gia_ManRandom( 1 );
+    pIni = Gia_ManDup(pAig);
+    pIni->pReprs = pAig->pReprs; pAig->pReprs = NULL;
+    pIni->pNexts = pAig->pNexts; pAig->pNexts = NULL;
+
+    // prepare the managers
+    // SAT sweeping
+    p = Cec_ManFraStart( pIni, pPars );
+    if ( pPars->fDualOut )
+        pPars->fColorDiff = 1;
+    // simulation
+    Cec_ManSimSetDefaultParams( pParsSim );
+    pParsSim->nWords      = pPars->nWords;
+    pParsSim->nFrames     = pPars->nRounds;
+    pParsSim->fCheckMiter = pPars->fCheckMiter;
+    pParsSim->fDualOut    = pPars->fDualOut;
+    pParsSim->fVerbose    = pPars->fVerbose;
+    pSim = Cec_ManSimStart( p->pAig, pParsSim );
+    // SAT solving
+    Cec_ManSatSetDefaultParams( pParsSat );
+    pParsSat->nBTLimit = pPars->nBTLimit;
+    pParsSat->fVerbose = pPars->fVeryVerbose;
+    // simulation patterns
+    pPat = Cec_ManPatStart();
+    pPat->fVerbose = pPars->fVeryVerbose;
+
+    // start equivalence classes
+clk = Abc_Clock();
+    if ( p->pAig->pReprs == NULL )
+    {
+        if ( Cec_ManSimClassesPrepare(pSim, -1) || Cec_ManSimClassesRefine(pSim) )
+        {
+            Gia_ManStop( p->pAig );
+            p->pAig = NULL;
+            goto finalize;
+        }
+    }
+p->timeSim += Abc_Clock() - clk;
+    // perform solving
+    for ( i = 1; i <= pPars->nItersMax; i++ )
+    {
+        clk2 = Abc_Clock();
+        nMatches = 0;
+        if ( pPars->fDualOut )
+        {
+            nMatches = Gia_ManEquivSetColors( p->pAig, pPars->fVeryVerbose );
+//            p->pAig->pIso = Cec_ManDetectIsomorphism( p->pAig );
+//            Gia_ManEquivTransform( p->pAig, 1 );
+        }
+        pSrm = Cec_ManFraSpecReduction( p ); 
+
+//        Gia_AigerWrite( pSrm, "gia_srm.aig", 0, 0 );
+
+        if ( pPars->fVeryVerbose )
+            Gia_ManPrintStats( pSrm, NULL );
+        if ( Gia_ManCoNum(pSrm) == 0 )
+        {
+            Gia_ManStop( pSrm );
+            if ( p->pPars->fVerbose )
+                Abc_Print( 1, "Considered all available candidate equivalences.\n" );
+            if ( pPars->fDualOut && Gia_ManAndNum(p->pAig) > 0 )
+            {
+                if ( pPars->fColorDiff )
+                {
+                    if ( p->pPars->fVerbose )
+                        Abc_Print( 1, "Switching into reduced mode.\n" );
+                    pPars->fColorDiff = 0;
+                }
+                else
+                {
+                    if ( p->pPars->fVerbose )
+                        Abc_Print( 1, "Switching into normal mode.\n" );
+                    pPars->fDualOut = 0;
+                }
+                continue;
+            }
+            break;
+        }
+clk = Abc_Clock();
+        Cec_ManSatSolve( pPat, pSrm, pParsSat ); 
+p->timeSat += Abc_Clock() - clk;
+        if ( Cec_ManFraClassesUpdate( p, pSim, pPat, pSrm ) )
+        {
+            Gia_ManStop( pSrm );
+            Gia_ManStop( p->pAig );
+            p->pAig = NULL;
+            goto finalize;
+        }
+        Gia_ManStop( pSrm );
+
+        // update the manager
+        pSim->pAig = p->pAig = Gia_ManEquivReduceAndRemap( pTemp = p->pAig, 0, pParsSim->fDualOut );
+        if ( p->pAig == NULL )
+        {
+            p->pAig = pTemp;
+            break;
+        }
+        Gia_ManStop( pTemp );
+        if ( p->pPars->fVerbose )
+        {
+            Abc_Print( 1, "%3d : P =%7d. D =%7d. F =%6d. M = %7d. And =%8d. ", 
+                i, p->nAllProved, p->nAllDisproved, p->nAllFailed, nMatches, Gia_ManAndNum(p->pAig) );
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 );
+        }
+        if ( Gia_ManAndNum(p->pAig) == 0 )
+        {
+            if ( p->pPars->fVerbose )
+                Abc_Print( 1, "Network after reduction is empty.\n" );
+            break;
+        }
+        // check resource limits
+        if ( p->pPars->TimeLimit && (Abc_Clock() - clkTotal)/CLOCKS_PER_SEC >= p->pPars->TimeLimit )
+        {
+            fTimeOut = 1;
+            break;
+        }
+//        if ( p->nAllFailed && !p->nAllProved && !p->nAllDisproved )
+        if ( p->nAllFailed > p->nAllProved + p->nAllDisproved )
+        {
+            if ( pParsSat->nBTLimit >= 10001 )
+                break;
+            if ( pPars->fSatSweeping )
+            {
+                if ( p->pPars->fVerbose )
+                    Abc_Print( 1, "Exceeded the limit on the number of conflicts (%d).\n", pParsSat->nBTLimit );
+                break;
+            }
+            pParsSat->nBTLimit *= 10;
+            if ( p->pPars->fVerbose )
+            {
+                if ( p->pPars->fVerbose )
+                    Abc_Print( 1, "Increasing conflict limit to %d.\n", pParsSat->nBTLimit );
+                if ( fOutputResult )
+                {
+                    Gia_AigerWrite( p->pAig, "gia_cec_temp.aig", 0, 0 );
+                    Abc_Print( 1,"The result is written into file \"%s\".\n", "gia_cec_temp.aig" );
+                }
+            }
+        }
+        if ( pPars->fDualOut && pPars->fColorDiff && (Gia_ManAndNum(p->pAig) < 100000 || p->nAllProved + p->nAllDisproved < 10) )
+        {
+            if ( p->pPars->fVerbose )
+                Abc_Print( 1, "Switching into reduced mode.\n" );
+            pPars->fColorDiff = 0;
+        }
+//        if ( pPars->fDualOut && Gia_ManAndNum(p->pAig) < 20000 )
+        else if ( pPars->fDualOut && (Gia_ManAndNum(p->pAig) < 20000 || p->nAllProved + p->nAllDisproved < 10) )
+        {
+            if ( p->pPars->fVerbose )
+                Abc_Print( 1, "Switching into normal mode.\n" );
+            pPars->fColorDiff = 0;
+            pPars->fDualOut = 0;
+        }
+    }
+finalize:
+    if ( p->pPars->fVerbose && p->pAig )
+    {
+        Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%).  RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", 
+            Gia_ManAndNum(pAig), Gia_ManAndNum(p->pAig), 
+            100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(p->pAig))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1), 
+            Gia_ManRegNum(pAig), Gia_ManRegNum(p->pAig), 
+            100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(p->pAig))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) );
+        Abc_PrintTimeP( 1, "Sim ", p->timeSim, Abc_Clock() - (int)clkTotal );
+        Abc_PrintTimeP( 1, "Sat ", p->timeSat-pPat->timeTotalSave, Abc_Clock() - (int)clkTotal );
+        Abc_PrintTimeP( 1, "Pat ", p->timePat+pPat->timeTotalSave, Abc_Clock() - (int)clkTotal );
+        Abc_PrintTime( 1, "Time", (int)(Abc_Clock() - clkTotal) );
+    }
+
+    pTemp = p->pAig; p->pAig = NULL;
+    if ( pTemp == NULL && pSim->iOut >= 0 )
+    {
+        Abc_Print( 1, "Disproved at least one output of the miter (zero-based number %d).\n", pSim->iOut );
+        pPars->iOutFail = pSim->iOut;
+    }
+    else if ( pSim->pCexes )
+        Abc_Print( 1, "Disproved %d outputs of the miter.\n", pSim->nOuts );
+    if ( fTimeOut )
+        Abc_Print( 1, "Timed out after %d seconds.\n", (int)((double)Abc_Clock() - clkTotal)/CLOCKS_PER_SEC );
+
+    pAig->pCexComb = pSim->pCexComb; pSim->pCexComb = NULL;
+    Cec_ManSimStop( pSim );
+    Cec_ManPatStop( pPat );
+    Cec_ManFraStop( p );
+    return pTemp;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/cec/cecCorr.c b/abc-build/src/proof/cec/cecCorr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/cecCorr.c
@@ -0,0 +1,1229 @@
+/**CFile****************************************************************
+
+  FileName    [cecCorr.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Combinational equivalence checking.]
+
+  Synopsis    [Latch/signal correspondence computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cecCorr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the real value of the literal w/o spec reduction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix )
+{
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), f, nPrefix );
+        Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin1(pObj), f, nPrefix );
+        return Gia_ManHashAnd( pNew, Gia_ObjFanin0CopyF(p, f, pObj), Gia_ObjFanin1CopyF(p, f, pObj) );
+    }
+    if ( f == 0 )
+    {
+        assert( Gia_ObjIsRo(p, pObj) );
+        return Gia_ObjCopyF(p, f, pObj);
+    }
+    assert( f && Gia_ObjIsRo(p, pObj) );
+    pObj = Gia_ObjRoToRi( p, pObj );
+    Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), f-1, nPrefix );
+    return Gia_ObjFanin0CopyF( p, f-1, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively performs speculative reduction for the object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix )
+{
+    Gia_Obj_t * pRepr;
+    int iLitNew;
+    if ( ~Gia_ObjCopyF(p, f, pObj) )
+        return;
+    if ( f >= nPrefix && (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+    {
+        Gia_ManCorrSpecReduce_rec( pNew, p, pRepr, f, nPrefix );
+        iLitNew = Abc_LitNotCond( Gia_ObjCopyF(p, f, pRepr), Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) );
+        Gia_ObjSetCopyF( p, f, pObj, iLitNew );
+        return;
+    }
+    assert( Gia_ObjIsCand(pObj) );
+    iLitNew = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix );
+    Gia_ObjSetCopyF( p, f, pObj, iLitNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives SRM for signal correspondence.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManCorrSpecReduce( Gia_Man_t * p, int nFrames, int fScorr, Vec_Int_t ** pvOutputs, int fRings )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pRepr;
+    Vec_Int_t * vXorLits;
+    int f, i, iPrev, iObj, iPrevNew, iObjNew;
+    assert( nFrames > 0 );
+    assert( Gia_ManRegNum(p) > 0 );
+    assert( p->pReprs != NULL );
+    p->pCopies = ABC_FALLOC( int, (nFrames+fScorr)*Gia_ManObjNum(p) );
+    Gia_ManSetPhase( p );
+    pNew = Gia_ManStart( nFrames * Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+    Gia_ObjSetCopyF( p, 0, Gia_ManConst0(p), 0 );
+    Gia_ManForEachRo( p, pObj, i )
+        Gia_ObjSetCopyF( p, 0, pObj, Gia_ManAppendCi(pNew) );
+    Gia_ManForEachRo( p, pObj, i )
+        if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+            Gia_ObjSetCopyF( p, 0, pObj, Gia_ObjCopyF(p, 0, pRepr) );
+    for ( f = 0; f < nFrames+fScorr; f++ )
+    { 
+        Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 );
+        Gia_ManForEachPi( p, pObj, i )
+            Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) );
+    }
+    *pvOutputs = Vec_IntAlloc( 1000 );
+    vXorLits = Vec_IntAlloc( 1000 );
+    if ( fRings )
+    {
+        Gia_ManForEachObj1( p, pObj, i )
+        {
+            if ( Gia_ObjIsConst( p, i ) )
+            {
+                iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 );
+                iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) );
+                if ( iObjNew != 0 )
+                {
+                    Vec_IntPush( *pvOutputs, 0 );
+                    Vec_IntPush( *pvOutputs, i );
+                    Vec_IntPush( vXorLits, iObjNew );
+                }
+            }
+            else if ( Gia_ObjIsHead( p, i ) )
+            {
+                iPrev = i;
+                Gia_ClassForEachObj1( p, i, iObj )
+                {
+                    iPrevNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 );
+                    iObjNew  = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 );
+                    iPrevNew = Abc_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) );
+                    iObjNew  = Abc_LitNotCond( iObjNew,  Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) );
+                    if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 )
+                    {
+                        Vec_IntPush( *pvOutputs, iPrev );
+                        Vec_IntPush( *pvOutputs, iObj );
+                        Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) );
+                    }
+                    iPrev = iObj;
+                }
+                iObj = i;
+                iPrevNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 );
+                iObjNew  = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 );
+                iPrevNew = Abc_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) );
+                iObjNew  = Abc_LitNotCond( iObjNew,  Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) );
+                if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 )
+                {
+                    Vec_IntPush( *pvOutputs, iPrev );
+                    Vec_IntPush( *pvOutputs, iObj );
+                    Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) );
+                }
+            }
+        }
+    }
+    else
+    {
+        Gia_ManForEachObj1( p, pObj, i )
+        {
+            pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) );
+            if ( pRepr == NULL )
+                continue;
+            iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, nFrames, 0 );
+            iObjNew  = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 );
+            iObjNew  = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) );
+            if ( iPrevNew != iObjNew )
+            {
+                Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) );
+                Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) );
+                Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) );
+            }
+        }
+    }
+    Vec_IntForEachEntry( vXorLits, iObjNew, i )
+        Gia_ManAppendCo( pNew, iObjNew );
+    Vec_IntFree( vXorLits );
+    Gia_ManHashStop( pNew );
+    ABC_FREE( p->pCopies );
+//Abc_Print( 1, "Before sweeping = %d\n", Gia_ManAndNum(pNew) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+//Abc_Print( 1, "After sweeping = %d\n", Gia_ManAndNum(pNew) );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives SRM for signal correspondence.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManCorrSpecReduceInit( Gia_Man_t * p, int nFrames, int nPrefix, int fScorr, Vec_Int_t ** pvOutputs, int fRings )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pRepr;
+    Vec_Int_t * vXorLits;
+    int f, i, iPrevNew, iObjNew;
+    assert( (!fScorr && nFrames > 1) || (fScorr && nFrames > 0) || nPrefix );
+    assert( Gia_ManRegNum(p) > 0 );
+    assert( p->pReprs != NULL );
+    p->pCopies = ABC_FALLOC( int, (nFrames+nPrefix+fScorr)*Gia_ManObjNum(p) );
+    Gia_ManSetPhase( p );
+    pNew = Gia_ManStart( (nFrames+nPrefix) * Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachRo( p, pObj, i )
+    {
+        Gia_ManAppendCi(pNew);
+        Gia_ObjSetCopyF( p, 0, pObj, 0 );
+    }
+    for ( f = 0; f < nFrames+nPrefix+fScorr; f++ )
+    { 
+        Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 );
+        Gia_ManForEachPi( p, pObj, i )
+            Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) );
+    }
+    *pvOutputs = Vec_IntAlloc( 1000 );
+    vXorLits = Vec_IntAlloc( 1000 );
+    for ( f = nPrefix; f < nFrames+nPrefix; f++ )
+    {
+        Gia_ManForEachObj1( p, pObj, i )
+        {
+            pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) );
+            if ( pRepr == NULL )
+                continue;
+            iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, f, nPrefix );
+            iObjNew  = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix );
+            iObjNew  = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) );
+            if ( iPrevNew != iObjNew )
+            {
+                Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) );
+                Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) );
+                Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) );
+            }
+        }
+    }
+    Vec_IntForEachEntry( vXorLits, iObjNew, i )
+        Gia_ManAppendCo( pNew, iObjNew );
+    Vec_IntFree( vXorLits );
+    Gia_ManHashStop( pNew );
+    ABC_FREE( p->pCopies );
+//Abc_Print( 1, "Before sweeping = %d\n", Gia_ManAndNum(pNew) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+//Abc_Print( 1, "After sweeping = %d\n", Gia_ManAndNum(pNew) );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Initializes simulation info for lcorr/scorr counter-examples.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManStartSimInfo( Vec_Ptr_t * vInfo, int nFlops )
+{
+    unsigned * pInfo;
+    int k, w, nWords;
+    nWords = Vec_PtrReadWordsSimInfo( vInfo );
+    assert( nFlops <= Vec_PtrSize(vInfo) );
+    for ( k = 0; k < nFlops; k++ )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry( vInfo, k );
+        for ( w = 0; w < nWords; w++ )
+            pInfo[w] = 0;
+    }
+    for ( k = nFlops; k < Vec_PtrSize(vInfo); k++ )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry( vInfo, k );
+        for ( w = 0; w < nWords; w++ )
+            pInfo[w] = Gia_ManRandom( 0 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Remaps simulation info from SRM to the original AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCorrRemapSimInfo( Gia_Man_t * p, Vec_Ptr_t * vInfo )
+{
+    Gia_Obj_t * pObj, * pRepr;
+    unsigned * pInfoObj, * pInfoRepr;
+    int i, w, nWords;
+    nWords = Vec_PtrReadWordsSimInfo( vInfo );
+    Gia_ManForEachRo( p, pObj, i )
+    {
+        // skip ROs without representatives
+        pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) );
+        if ( pRepr == NULL || Gia_ObjFailed(p, Gia_ObjId(p,pObj)) )
+            continue;
+        pInfoObj = (unsigned *)Vec_PtrEntry( vInfo, i );
+        for ( w = 0; w < nWords; w++ )
+            assert( pInfoObj[w] == 0 );
+        // skip ROs with constant representatives
+        if ( Gia_ObjIsConst0(pRepr) )
+            continue;
+        assert( Gia_ObjIsRo(p, pRepr) );
+//        Abc_Print( 1, "%d -> %d    ", i, Gia_ObjId(p, pRepr) );
+        // transfer info from the representative
+        pInfoRepr = (unsigned *)Vec_PtrEntry( vInfo, Gia_ObjCioId(pRepr) - Gia_ManPiNum(p) );
+        for ( w = 0; w < nWords; w++ )
+            pInfoObj[w] = pInfoRepr[w];
+    }
+//    Abc_Print( 1, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects information about remapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManCorrCreateRemapping( Gia_Man_t * p )
+{
+    Vec_Int_t * vPairs;
+    Gia_Obj_t * pObj, * pRepr;
+    int i;
+    vPairs = Vec_IntAlloc( 100 );
+    Gia_ManForEachRo( p, pObj, i )
+    {
+        // skip ROs without representatives
+        pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) );
+        if ( pRepr == NULL || Gia_ObjIsConst0(pRepr) || Gia_ObjFailed(p, Gia_ObjId(p,pObj)) )
+//        if ( pRepr == NULL || Gia_ObjIsConst0(pRepr) || Gia_ObjIsFailedPair(p, Gia_ObjId(p, pRepr), Gia_ObjId(p, pObj)) )
+            continue;
+        assert( Gia_ObjIsRo(p, pRepr) );
+//        Abc_Print( 1, "%d -> %d    ", Gia_ObjId(p,pObj), Gia_ObjId(p, pRepr) );
+        // remember the pair
+        Vec_IntPush( vPairs, Gia_ObjCioId(pRepr) - Gia_ManPiNum(p) );
+        Vec_IntPush( vPairs, i );
+    }
+    return vPairs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Remaps simulation info from SRM to the original AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCorrPerformRemapping( Vec_Int_t * vPairs, Vec_Ptr_t * vInfo )
+{
+    unsigned * pInfoObj, * pInfoRepr;
+    int w, i, iObj, iRepr, nWords;
+    nWords = Vec_PtrReadWordsSimInfo( vInfo );
+    Vec_IntForEachEntry( vPairs, iRepr, i )
+    {
+        iObj = Vec_IntEntry( vPairs, ++i );
+        pInfoObj = (unsigned *)Vec_PtrEntry( vInfo, iObj );
+        pInfoRepr = (unsigned *)Vec_PtrEntry( vInfo, iRepr );
+        for ( w = 0; w < nWords; w++ )
+        {
+            assert( pInfoObj[w] == 0 );
+            pInfoObj[w] = pInfoRepr[w];
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Packs one counter-examples into the array of simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+*************************************`**********************************/
+int Cec_ManLoadCounterExamplesTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * pLits, int nLits )
+{
+    unsigned * pInfo, * pPres;
+    int i;
+    for ( i = 0; i < nLits; i++ )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i]));
+        pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i]));
+        if ( Abc_InfoHasBit( pPres, iBit ) && 
+             Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) )
+             return 0;
+    }
+    for ( i = 0; i < nLits; i++ )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i]));
+        pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i]));
+        Abc_InfoSetBit( pPres, iBit );
+        if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) )
+            Abc_InfoXorBit( pInfo, iBit );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs bitpacking of counter-examples.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManLoadCounterExamples( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart )
+{ 
+    Vec_Int_t * vPat;
+    Vec_Ptr_t * vPres;
+    int nWords = Vec_PtrReadWordsSimInfo(vInfo);
+    int nBits = 32 * nWords; 
+    int k, nSize, kMax = 0;//, iBit = 1;
+    vPat  = Vec_IntAlloc( 100 );
+    vPres = Vec_PtrAllocSimInfo( Vec_PtrSize(vInfo), nWords );
+    Vec_PtrCleanSimInfo( vPres, 0, nWords );
+    while ( iStart < Vec_IntSize(vCexStore) )
+    {
+        // skip the output number
+        iStart++;
+        // get the number of items
+        nSize = Vec_IntEntry( vCexStore, iStart++ );
+        if ( nSize <= 0 )
+            continue;
+        // extract pattern
+        Vec_IntClear( vPat );
+        for ( k = 0; k < nSize; k++ )
+            Vec_IntPush( vPat, Vec_IntEntry( vCexStore, iStart++ ) );
+        // add pattern to storage
+        for ( k = 1; k < nBits; k++ )
+            if ( Cec_ManLoadCounterExamplesTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) )
+                break;
+        kMax = Abc_MaxInt( kMax, k );
+        if ( k == nBits-1 )
+            break;
+    }
+    Vec_PtrFree( vPres );
+    Vec_IntFree( vPat );
+    return iStart;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs bitpacking of counter-examples.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManLoadCounterExamples2( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart )
+{ 
+    unsigned * pInfo;
+    int nBits = 32 * Vec_PtrReadWordsSimInfo(vInfo); 
+    int k, iLit, nLits, Out, iBit = 1;
+    while ( iStart < Vec_IntSize(vCexStore) )
+    {
+        // skip the output number
+//        iStart++;
+        Out = Vec_IntEntry( vCexStore, iStart++ );
+//        Abc_Print( 1, "iBit = %d. Out = %d.\n", iBit, Out );
+        // get the number of items
+        nLits = Vec_IntEntry( vCexStore, iStart++ );
+        if ( nLits <= 0 )
+            continue;
+        // add pattern to storage
+        for ( k = 0; k < nLits; k++ )
+        {
+            iLit = Vec_IntEntry( vCexStore, iStart++ );
+            pInfo = (unsigned *)Vec_PtrEntry( vInfo, Abc_Lit2Var(iLit) );
+            if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(iLit) )
+                Abc_InfoXorBit( pInfo, iBit );
+        }
+        if ( ++iBit == nBits )
+            break;
+    }
+//    Abc_Print( 1, "added %d bits\n", iBit-1 );
+    return iStart;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulates counter-examples derived by the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManResimulateCounterExamples( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore, int nFrames )
+{ 
+    Vec_Int_t * vPairs;
+    Vec_Ptr_t * vSimInfo; 
+    int RetValue = 0, iStart = 0;
+    vPairs = Gia_ManCorrCreateRemapping( pSim->pAig );
+    Gia_ManCreateValueRefs( pSim->pAig );
+//    pSim->pPars->nWords  = 63;
+    pSim->pPars->nFrames = nFrames;
+    vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pSim->pAig) + Gia_ManPiNum(pSim->pAig) * nFrames, pSim->pPars->nWords );
+    while ( iStart < Vec_IntSize(vCexStore) )
+    {
+        Cec_ManStartSimInfo( vSimInfo, Gia_ManRegNum(pSim->pAig) );
+        iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart );
+//        iStart = Cec_ManLoadCounterExamples2( vSimInfo, vCexStore, iStart );
+//        Gia_ManCorrRemapSimInfo( pSim->pAig, vSimInfo );
+        Gia_ManCorrPerformRemapping( vPairs, vSimInfo );
+        RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo );
+//        Cec_ManSeqResimulateInfo( pSim->pAig, vSimInfo, NULL );
+    }
+//Gia_ManEquivPrintOne( pSim->pAig, 85, 0 );
+    assert( iStart == Vec_IntSize(vCexStore) );
+    Vec_PtrFree( vSimInfo );
+    Vec_IntFree( vPairs );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulates counter-examples derived by the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManResimulateCounterExamplesComb( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore )
+{ 
+    Vec_Ptr_t * vSimInfo; 
+    int RetValue = 0, iStart = 0;
+    Gia_ManCreateValueRefs( pSim->pAig );
+    pSim->pPars->nFrames = 1;
+    vSimInfo = Vec_PtrAllocSimInfo( Gia_ManCiNum(pSim->pAig), pSim->pPars->nWords );
+    while ( iStart < Vec_IntSize(vCexStore) )
+    {
+        Cec_ManStartSimInfo( vSimInfo, 0 );
+        iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart );
+        RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo );
+    }
+    assert( iStart == Vec_IntSize(vCexStore) );
+    Vec_PtrFree( vSimInfo );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates equivalence classes by marking those that timed out.]
+
+  Description [Returns 1 if all ndoes are proved.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCheckRefinements( Gia_Man_t * p, Vec_Str_t * vStatus, Vec_Int_t * vOutputs, Cec_ManSim_t * pSim, int fRings )
+{
+    int i, status, iRepr, iObj;
+    int Counter = 0;
+    assert( 2 * Vec_StrSize(vStatus) == Vec_IntSize(vOutputs) );
+    Vec_StrForEachEntry( vStatus, status, i )
+    {
+        iRepr = Vec_IntEntry( vOutputs, 2*i );
+        iObj  = Vec_IntEntry( vOutputs, 2*i+1 );
+        if ( status == 1 )
+            continue;
+        if ( status == 0 )
+        {
+            if ( Gia_ObjHasSameRepr(p, iRepr, iObj) )
+                Counter++;
+//            if ( Gia_ObjHasSameRepr(p, iRepr, iObj) )
+//                Abc_Print( 1, "Gia_ManCheckRefinements(): Disproved equivalence (%d,%d) is not refined!\n", iRepr, iObj );
+//            if ( Gia_ObjHasSameRepr(p, iRepr, iObj) )
+//                Cec_ManSimClassRemoveOne( pSim, iObj );
+            continue;
+        }
+        if ( status == -1 )
+        {
+//            if ( !Gia_ObjFailed( p, iObj ) )
+//                Abc_Print( 1, "Gia_ManCheckRefinements(): Failed equivalence is not marked as failed!\n" );
+//            Gia_ObjSetFailed( p, iRepr );
+//            Gia_ObjSetFailed( p, iObj );        
+//            if ( fRings )
+//            Cec_ManSimClassRemoveOne( pSim, iRepr );
+            Cec_ManSimClassRemoveOne( pSim, iObj );
+            continue;
+        }
+    }
+//    if ( Counter )
+//    Abc_Print( 1, "Gia_ManCheckRefinements(): Could not refine %d nodes.\n", Counter );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManCorrReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    Gia_Obj_t * pRepr;
+    if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+    {
+        Gia_ManCorrReduce_rec( pNew, p, pRepr );
+        pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) );
+        return;
+    }
+    if ( ~pObj->Value )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin1(pObj) );
+    pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces AIG using equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManCorrReduce( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManSetPhase( p );
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManFillValue( p );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin0(pObj) );
+    Gia_ManForEachCo( p, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints statistics during solving.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManRefinedClassPrintStats( Gia_Man_t * p, Vec_Str_t * vStatus, int iIter, abctime Time )
+{ 
+    int nLits, CounterX = 0, Counter0 = 0, Counter = 0;
+    int i, Entry, nProve = 0, nDispr = 0, nFail = 0;
+    for ( i = 1; i < Gia_ManObjNum(p); i++ )
+    {
+        if ( Gia_ObjIsNone(p, i) )
+            CounterX++;
+        else if ( Gia_ObjIsConst(p, i) )
+            Counter0++;
+        else if ( Gia_ObjIsHead(p, i) )
+            Counter++;
+    }
+    CounterX -= Gia_ManCoNum(p);
+    nLits = Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX;
+    if ( iIter == -1 )
+        Abc_Print( 1, "BMC : " );
+    else
+        Abc_Print( 1, "%3d : ", iIter );
+    Abc_Print( 1, "c =%8d  cl =%7d  lit =%8d  ", Counter0, Counter, nLits );
+    if ( vStatus )
+    Vec_StrForEachEntry( vStatus, Entry, i )
+    {
+        if ( Entry == 1 )
+            nProve++;
+        else if ( Entry == 0 )
+            nDispr++;
+        else if ( Entry == -1 )
+            nFail++;
+    }
+    Abc_Print( 1, "p =%6d  d =%6d  f =%6d  ", nProve, nDispr, nFail );
+    Abc_Print( 1, "%c  ", Gia_ObjIsConst( p, Gia_ObjFaninId0p(p, Gia_ManPo(p, 0)) ) ? '+' : '-' );
+    Abc_PrintTime( 1, "T", Time );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Runs BMC for the equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManLSCorrespondenceBmc( Gia_Man_t * pAig, Cec_ParCor_t * pPars, int nPrefs )
+{  
+    Cec_ParSim_t ParsSim, * pParsSim = &ParsSim;
+    Cec_ParSat_t ParsSat, * pParsSat = &ParsSat;
+    Vec_Str_t * vStatus;
+    Vec_Int_t * vOutputs;
+    Vec_Int_t * vCexStore;
+    Cec_ManSim_t * pSim;
+    Gia_Man_t * pSrm;
+    int fChanges, RetValue;
+    // prepare simulation manager
+    Cec_ManSimSetDefaultParams( pParsSim );
+    pParsSim->nWords     = pPars->nWords;
+    pParsSim->nFrames    = pPars->nRounds;
+    pParsSim->fVerbose   = pPars->fVerbose;
+    pParsSim->fLatchCorr = pPars->fLatchCorr;
+    pParsSim->fSeqSimulate = 1;
+    pSim = Cec_ManSimStart( pAig, pParsSim );
+    // prepare SAT solving
+    Cec_ManSatSetDefaultParams( pParsSat );
+    pParsSat->nBTLimit = pPars->nBTLimit;
+    pParsSat->fVerbose = pPars->fVerbose;
+    fChanges = 1;
+    while ( fChanges )
+    {
+        abctime clkBmc = Abc_Clock();
+        fChanges = 0;
+        pSrm = Gia_ManCorrSpecReduceInit( pAig, pPars->nFrames, nPrefs, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings );
+        if ( Gia_ManPoNum(pSrm) == 0 )
+        {
+            Gia_ManStop( pSrm );
+            Vec_IntFree( vOutputs );
+            break;
+        } 
+        pParsSat->nBTLimit *= 10;
+        if ( pPars->fUseCSat )
+            vCexStore = Tas_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 );
+        else
+            vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus );
+        // refine classes with these counter-examples
+        if ( Vec_IntSize(vCexStore) )
+        {
+            RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nPrefs );
+            Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings );
+            fChanges = 1;
+        }
+        if ( pPars->fVerbose )
+            Cec_ManRefinedClassPrintStats( pAig, vStatus, -1, Abc_Clock() - clkBmc );
+        // recycle
+        Vec_IntFree( vCexStore );
+        Vec_StrFree( vStatus );
+        Gia_ManStop( pSrm );
+        Vec_IntFree( vOutputs );
+    }
+    Cec_ManSimStop( pSim );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManLSCorrAnalyzeDependence( Gia_Man_t * p, Vec_Int_t * vEquivs, Vec_Str_t * vStatus )
+{
+    Gia_Obj_t * pObj, * pObjRo;
+    int i, Iter, iObj, iRepr, fPrev, Total, Count0, Count1;
+    assert( Vec_StrSize(vStatus) * 2 == Vec_IntSize(vEquivs) );
+    Total = 0;
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        assert( pObj->fMark1 == 0 );
+        if ( Gia_ObjHasRepr(p, i) )
+            Total++;
+    }
+    Count0 = 0;
+    for ( i = 0; i < Vec_StrSize(vStatus); i++ )
+    {
+        iRepr = Vec_IntEntry(vEquivs, 2*i);
+        iObj = Vec_IntEntry(vEquivs, 2*i+1);
+        assert( iRepr == Gia_ObjRepr(p, iObj) );
+        if ( Vec_StrEntry(vStatus, i) != 1 ) // disproved or undecided
+        {
+            Gia_ManObj(p, iObj)->fMark1 = 1;
+            Count0++;
+        }
+    }
+    for ( Iter = 0; Iter < 100; Iter++ )
+    {
+        int fChanges = 0;
+        Gia_ManForEachObj1( p, pObj, i )
+        {
+            if ( Gia_ObjIsCi(pObj) )
+                continue;
+            assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) );
+//            fPrev = pObj->fMark1;
+            if ( Gia_ObjIsAnd(pObj) )
+                pObj->fMark1 |= Gia_ObjFanin0(pObj)->fMark1 | Gia_ObjFanin1(pObj)->fMark1;
+            else
+                pObj->fMark1 |= Gia_ObjFanin0(pObj)->fMark1;
+//            fChanges += fPrev ^ pObj->fMark1;
+        }
+        Gia_ManForEachRiRo( p, pObj, pObjRo, i )
+        {
+            fPrev = pObjRo->fMark1;
+            pObjRo->fMark1 = pObj->fMark1;
+            fChanges += fPrev ^ pObjRo->fMark1;
+        }
+        if ( fChanges == 0 )
+            break;
+    }
+    Count1 = 0;
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( pObj->fMark1 && Gia_ObjHasRepr(p, i) )
+            Count1++;
+        pObj->fMark1 = 0;
+    }
+    printf( "%5d -> %5d (%3d)  ", Count0, Count1, Iter );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Internal procedure for register correspondence.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars )
+{  
+    int nIterMax     = 100000;
+    int nAddFrames   = 1; // additional timeframes to simulate
+    int fRunBmcFirst = 1;
+    Vec_Str_t * vStatus;
+    Vec_Int_t * vOutputs;
+    Vec_Int_t * vCexStore;
+    Cec_ParSim_t ParsSim, * pParsSim = &ParsSim;
+    Cec_ParSat_t ParsSat, * pParsSat = &ParsSat;
+    Cec_ManSim_t * pSim;
+    Gia_Man_t * pSrm;
+    int r, RetValue;
+    abctime clkTotal = Abc_Clock();
+    abctime clkSat = 0, clkSim = 0, clkSrm = 0;
+    abctime clk2, clk = Abc_Clock();
+    if ( Gia_ManRegNum(pAig) == 0 )
+    {
+        Abc_Print( 1, "Cec_ManLatchCorrespondence(): Not a sequential AIG.\n" );
+        return 0;
+    }
+    Gia_ManRandom( 1 );
+    // prepare simulation manager
+    Cec_ManSimSetDefaultParams( pParsSim );
+    pParsSim->nWords     = pPars->nWords;
+    pParsSim->nFrames    = pPars->nFrames;
+    pParsSim->fVerbose   = pPars->fVerbose;
+    pParsSim->fLatchCorr = pPars->fLatchCorr;
+    pParsSim->fConstCorr = pPars->fConstCorr;
+    pParsSim->fSeqSimulate = 1;
+    // create equivalence classes of registers
+    pSim = Cec_ManSimStart( pAig, pParsSim );
+    if ( pAig->pReprs == NULL )
+    {
+        Cec_ManSimClassesPrepare( pSim, pPars->nLevelMax );
+        Cec_ManSimClassesRefine( pSim );
+    }
+    // prepare SAT solving
+    Cec_ManSatSetDefaultParams( pParsSat );
+    pParsSat->nBTLimit = pPars->nBTLimit;
+    pParsSat->fVerbose = pPars->fVerbose;
+    // limit the number of conflicts in the circuit-based solver
+    if ( pPars->fUseCSat )
+        pParsSat->nBTLimit = Abc_MinInt( pParsSat->nBTLimit, 1000 );
+    if ( pPars->fVerbose )
+    {
+        Abc_Print( 1, "Obj = %7d. And = %7d. Conf = %5d. Fr = %d. Lcorr = %d. Ring = %d. CSat = %d.\n",
+            Gia_ManObjNum(pAig), Gia_ManAndNum(pAig), 
+            pPars->nBTLimit, pPars->nFrames, pPars->fLatchCorr, pPars->fUseRings, pPars->fUseCSat );
+        Cec_ManRefinedClassPrintStats( pAig, NULL, 0, Abc_Clock() - clk );
+    }
+    // check the base case
+    if ( fRunBmcFirst && (!pPars->fLatchCorr || pPars->nFrames > 1) )
+        Cec_ManLSCorrespondenceBmc( pAig, pPars, 0 );
+    if ( pPars->pFunc )
+    {
+        ((int (*)(void *))pPars->pFunc)( pPars->pData );
+        ((int (*)(void *))pPars->pFunc)( pPars->pData );
+    }
+    if ( pPars->nStepsMax == 0 )
+    {
+        Abc_Print( 1, "Stopped signal correspondence after BMC.\n" );
+        Cec_ManSimStop( pSim );
+        return 1;
+    }
+    // perform refinement of equivalence classes
+    for ( r = 0; r < nIterMax; r++ )
+    { 
+        if ( pPars->nStepsMax == r )
+        {
+            Cec_ManSimStop( pSim );
+            Abc_Print( 1, "Stopped signal correspondence after %d refiment iterations.\n", r );
+            return 1;
+        }
+        clk = Abc_Clock();
+        // perform speculative reduction
+        clk2 = Abc_Clock();
+        pSrm = Gia_ManCorrSpecReduce( pAig, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings );
+        assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManPiNum(pSrm) == Gia_ManRegNum(pAig)+(pPars->nFrames+!pPars->fLatchCorr)*Gia_ManPiNum(pAig) );
+        clkSrm += Abc_Clock() - clk2;
+        if ( Gia_ManCoNum(pSrm) == 0 )
+        {
+            Vec_IntFree( vOutputs );
+            Gia_ManStop( pSrm );            
+            break;
+        }
+//Gia_DumpAiger( pSrm, "corrsrm", r, 2 );
+        // found counter-examples to speculation
+        clk2 = Abc_Clock();
+        if ( pPars->fUseCSat )
+            vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 );
+        else
+            vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus );
+        Gia_ManStop( pSrm );
+        clkSat += Abc_Clock() - clk2;
+        if ( Vec_IntSize(vCexStore) == 0 )
+        {
+            Vec_IntFree( vCexStore );
+            Vec_StrFree( vStatus );
+            Vec_IntFree( vOutputs );
+            break;
+        }
+//        Cec_ManLSCorrAnalyzeDependence( pAig, vOutputs, vStatus );        
+
+        // refine classes with these counter-examples
+        clk2 = Abc_Clock();
+        RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nAddFrames );
+        Vec_IntFree( vCexStore );
+        clkSim += Abc_Clock() - clk2;
+        Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings );
+        if ( pPars->fVerbose )
+            Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, Abc_Clock() - clk );
+        Vec_StrFree( vStatus );
+        Vec_IntFree( vOutputs );
+//Gia_ManEquivPrintClasses( pAig, 1, 0 );
+        if ( pPars->pFunc )
+            ((int (*)(void *))pPars->pFunc)( pPars->pData );
+        // quit if const is no longer there
+        if ( pPars->fStopWhenGone && Gia_ManPoNum(pAig) == 1 && !Gia_ObjIsConst( pAig, Gia_ObjFaninId0p(pAig, Gia_ManPo(pAig, 0)) ) )
+        {
+            printf( "Iterative refinement is stopped after iteration %d\n", r );
+            printf( "because the property output is no longer a candidate constant.\n" );
+            Cec_ManSimStop( pSim );
+            return 0;
+        }
+    }
+    if ( pPars->fVerbose )
+        Cec_ManRefinedClassPrintStats( pAig, NULL, r+1, Abc_Clock() - clk );
+    // check the overflow
+    if ( r == nIterMax )
+        Abc_Print( 1, "The refinement was not finished. The result may be incorrect.\n" );
+    Cec_ManSimStop( pSim );
+    // check the base case
+    if ( !fRunBmcFirst && (!pPars->fLatchCorr || pPars->nFrames > 1) )
+        Cec_ManLSCorrespondenceBmc( pAig, pPars, 0 );
+    clkTotal = Abc_Clock() - clkTotal;
+    // report the results
+    if ( pPars->fVerbose )
+    {
+        ABC_PRTP( "Srm  ", clkSrm,                        clkTotal );
+        ABC_PRTP( "Sat  ", clkSat,                        clkTotal );
+        ABC_PRTP( "Sim  ", clkSim,                        clkTotal );
+        ABC_PRTP( "Other", clkTotal-clkSat-clkSrm-clkSim, clkTotal );
+        Abc_PrintTime( 1, "TOTAL",  clkTotal );
+    }
+    return 1;
+}    
+
+/**Function*************************************************************
+
+  Synopsis    [Computes new initial state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Cec_ManComputeInitState( Gia_Man_t * pAig, int nFrames )
+{  
+    Gia_Obj_t * pObj, * pObjRo, * pObjRi;
+    unsigned * pInitState;
+    int i, f; 
+    Gia_ManRandom( 1 );
+//    Abc_Print( 1, "Simulating %d timeframes.\n", nFrames );
+    Gia_ManForEachRo( pAig, pObj, i )
+        pObj->fMark1 = 0;
+    for ( f = 0; f < nFrames; f++ )
+    {
+        Gia_ManConst0(pAig)->fMark1 = 0;
+        Gia_ManForEachPi( pAig, pObj, i )
+            pObj->fMark1 = Gia_ManRandom(0) & 1;
+        Gia_ManForEachAnd( pAig, pObj, i )
+            pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) & 
+                (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj));
+        Gia_ManForEachRi( pAig, pObj, i )
+            pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj));
+        Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, i )
+            pObjRo->fMark1 = pObjRi->fMark1;
+    }
+    pInitState = ABC_CALLOC( unsigned, Abc_BitWordNum(Gia_ManRegNum(pAig)) );
+    Gia_ManForEachRo( pAig, pObj, i )
+    {
+        if ( pObj->fMark1 )
+            Abc_InfoSetBit( pInitState, i );
+//        Abc_Print( 1, "%d", pObj->fMark1 );
+    }
+//    Abc_Print( 1, "\n" );
+    Gia_ManCleanMark1( pAig );
+    return pInitState;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints flop equivalences.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManPrintFlopEquivs( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pRepr;
+    int i;
+    assert( p->vNamesIn != NULL );
+    Gia_ManForEachRo( p, pObj, i )
+    {
+        if ( Gia_ObjIsConst(p, Gia_ObjId(p, pObj)) )
+            Abc_Print( 1, "Original flop %s is proved equivalent to constant.\n", Vec_PtrEntry(p->vNamesIn, Gia_ObjCioId(pObj)) );
+        else if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+        {
+            if ( Gia_ObjIsCi(pRepr) )
+                Abc_Print( 1, "Original flop %s is proved equivalent to flop %s.\n",
+                    Vec_PtrEntry( p->vNamesIn, Gia_ObjCioId(pObj)  ),
+                    Vec_PtrEntry( p->vNamesIn, Gia_ObjCioId(pRepr) ) );
+            else
+                Abc_Print( 1, "Original flop %s is proved equivalent to internal node %d.\n",
+                    Vec_PtrEntry( p->vNamesIn, Gia_ObjCioId(pObj) ), Gia_ObjId(p, pRepr) );
+        }
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Top-level procedure for register correspondence.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Cec_ManLSCorrespondence( Gia_Man_t * pAig, Cec_ParCor_t * pPars )
+{  
+    Gia_Man_t * pNew, * pTemp;
+    unsigned * pInitState;
+    int RetValue;
+    ABC_FREE( pAig->pReprs );
+    ABC_FREE( pAig->pNexts );
+    if ( pPars->nPrefix == 0 )
+    {
+        RetValue = Cec_ManLSCorrespondenceClasses( pAig, pPars );
+        if ( RetValue == 0 )
+            return Gia_ManDup( pAig );
+    }
+    else
+    {
+        // compute the cycles AIG
+        pInitState = Cec_ManComputeInitState( pAig, pPars->nPrefix );
+        pTemp = Gia_ManDupFlip( pAig, (int *)pInitState );
+        ABC_FREE( pInitState );
+        // compute classes of this AIG
+        RetValue = Cec_ManLSCorrespondenceClasses( pTemp, pPars );
+        // transfer the class info
+        pAig->pReprs = pTemp->pReprs; pTemp->pReprs = NULL;
+        pAig->pNexts = pTemp->pNexts; pTemp->pNexts = NULL;
+        // perform additional BMC
+        pPars->fUseCSat = 0;
+        pPars->nBTLimit = Abc_MaxInt( pPars->nBTLimit, 1000 );
+        Cec_ManLSCorrespondenceBmc( pAig, pPars, pPars->nPrefix );
+/*
+        // transfer the class info back
+        pTemp->pReprs = pAig->pReprs; pAig->pReprs = NULL;
+        pTemp->pNexts = pAig->pNexts; pAig->pNexts = NULL;
+        // continue refining
+        RetValue = Cec_ManLSCorrespondenceClasses( pTemp, pPars );
+        // transfer the class info
+        pAig->pReprs = pTemp->pReprs; pTemp->pReprs = NULL;
+        pAig->pNexts = pTemp->pNexts; pTemp->pNexts = NULL;
+*/
+        Gia_ManStop( pTemp );
+    }
+    // derive reduced AIG
+    if ( pPars->fMakeChoices )
+    {
+        pNew = Gia_ManEquivToChoices( pAig, 1 );
+//        Gia_ManHasChoices_very_old( pNew );
+    }
+    else
+    {
+//        Gia_ManEquivImprove( pAig );
+        pNew = Gia_ManCorrReduce( pAig );
+        pNew = Gia_ManSeqCleanup( pTemp = pNew );
+        Gia_ManStop( pTemp );
+        //Gia_AigerWrite( pNew, "reduced.aig", 0, 0 );
+    }
+    // report the results
+    if ( pPars->fVerbose )
+    {
+        Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%).  RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", 
+            Gia_ManAndNum(pAig), Gia_ManAndNum(pNew), 
+            100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(pNew))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1), 
+            Gia_ManRegNum(pAig), Gia_ManRegNum(pNew), 
+            100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(pNew))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) );
+    }
+    if ( pPars->nPrefix && (Gia_ManAndNum(pNew) < Gia_ManAndNum(pAig) || Gia_ManRegNum(pNew) < Gia_ManRegNum(pAig)) )
+        Abc_Print( 1, "The reduced AIG was produced using %d-th invariants and will not verify.\n", pPars->nPrefix );
+    // print verbose info about equivalences
+    if ( pPars->fVerboseFlops )
+    {
+        if ( pAig->vNamesIn == NULL )
+            Abc_Print( 1, "Flop output names are not available. Use command \"&get -n\".\n" );
+        else
+            Cec_ManPrintFlopEquivs( pAig );
+    }
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/cec/cecInt.h b/abc-build/src/proof/cec/cecInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/cecInt.h
@@ -0,0 +1,225 @@
+/**CFile****************************************************************
+
+  FileName    [cecInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Combinational equivalence checking.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__cec__cecInt_h
+#define ABC__aig__cec__cecInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "sat/bsat/satSolver.h"
+#include "misc/bar/bar.h"
+#include "aig/gia/gia.h"
+#include "cec.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// simulation pattern manager
+typedef struct Cec_ManPat_t_ Cec_ManPat_t;
+struct Cec_ManPat_t_
+{
+    Vec_Int_t *      vPattern1;      // pattern in terms of primary inputs
+    Vec_Int_t *      vPattern2;      // pattern in terms of primary inputs
+    Vec_Str_t *      vStorage;       // storage for compressed patterns
+    int              iStart;         // position in the array where recent patterns begin
+    int              nPats;          // total number of recent patterns
+    int              nPatsAll;       // total number of all patterns
+    int              nPatLits;       // total number of literals in recent patterns
+    int              nPatLitsAll;    // total number of literals in all patterns
+    int              nPatLitsMin;    // total number of literals in minimized recent patterns
+    int              nPatLitsMinAll; // total number of literals in minimized all patterns
+    int              nSeries;        // simulation series
+    int              fVerbose;       // verbose stats
+    // runtime statistics
+    abctime          timeFind;       // detecting the pattern  
+    abctime          timeShrink;     // minimizing the pattern
+    abctime          timeVerify;     // verifying the result of minimisation
+    abctime          timeSort;       // sorting literals 
+    abctime          timePack;       // packing into sim info structures 
+    abctime          timeTotal;      // total runtime  
+    abctime          timeTotalSave;  // total runtime for saving  
+};
+
+// SAT solving manager
+typedef struct Cec_ManSat_t_ Cec_ManSat_t;
+struct Cec_ManSat_t_
+{
+    // parameters
+    Cec_ParSat_t *   pPars;          
+    // AIGs used in the package
+    Gia_Man_t *      pAig;           // the AIG whose outputs are considered
+    Vec_Int_t *      vStatus;        // status for each output
+    // SAT solving
+    sat_solver *     pSat;           // recyclable SAT solver
+    int              nSatVars;       // the counter of SAT variables
+    int *            pSatVars;       // mapping of each node into its SAT var
+    Vec_Ptr_t *      vUsedNodes;     // nodes whose SAT vars are assigned
+    int              nRecycles;      // the number of times SAT solver was recycled
+    int              nCallsSince;    // the number of calls since the last recycle
+    Vec_Ptr_t *      vFanins;        // fanins of the CNF node
+    // counter-examples
+    Vec_Int_t *      vCex;           // the latest counter-example
+    Vec_Int_t *      vVisits;        // temporary array for visited nodes  
+    // SAT calls statistics
+    int              nSatUnsat;      // the number of proofs
+    int              nSatSat;        // the number of failure
+    int              nSatUndec;      // the number of timeouts
+    int              nSatTotal;      // the number of calls
+    int              nCexLits;
+    // conflicts
+    int              nConfUnsat;     // conflicts in unsat problems
+    int              nConfSat;       // conflicts in sat problems
+    int              nConfUndec;     // conflicts in undec problems
+    // runtime stats
+    int              timeSatUnsat;   // unsat
+    int              timeSatSat;     // sat
+    int              timeSatUndec;   // undecided
+    int              timeTotal;      // total runtime
+};
+
+// combinational simulation manager
+typedef struct Cec_ManSim_t_ Cec_ManSim_t;
+struct Cec_ManSim_t_
+{
+    // parameters
+    Gia_Man_t *      pAig;           // the AIG to be used for simulation
+    Cec_ParSim_t *   pPars;          // simulation parameters 
+    int              nWords;         // the number of simulation words
+    // recycable memory
+    int *            pSimInfo;       // simulation information offsets
+    unsigned *       pMems;          // allocated simulaton memory
+    int              nWordsAlloc;    // the number of allocated entries
+    int              nMems;          // the number of used entries  
+    int              nMemsMax;       // the max number of used entries 
+    int              MemFree;        // next free entry
+    int              nWordsOld;      // the number of simulation words after previous relink
+    // internal simulation info
+    Vec_Ptr_t *      vCiSimInfo;     // CI simulation info  
+    Vec_Ptr_t *      vCoSimInfo;     // CO simulation info  
+    // counter examples
+    void **          pCexes;         // counter-examples for each output
+    int              iOut;           // first failed output
+    int              nOuts;          // the number of failed outputs
+    Abc_Cex_t *      pCexComb;       // counter-example for the first failed output
+    Abc_Cex_t *      pBestState;     // the state that led to most of the refinements
+    // scoring simulation patterns
+    int *            pScores;        // counters of refinement for each pattern
+    // temporaries
+    Vec_Int_t *      vClassOld;      // old class numbers
+    Vec_Int_t *      vClassNew;      // new class numbers
+    Vec_Int_t *      vClassTemp;     // temporary storage
+    Vec_Int_t *      vRefinedC;      // refined const reprs
+};
+
+// combinational simulation manager
+typedef struct Cec_ManFra_t_ Cec_ManFra_t;
+struct Cec_ManFra_t_
+{
+    // parameters
+    Gia_Man_t *      pAig;           // the AIG to be used for simulation
+    Cec_ParFra_t *   pPars;          // SAT sweeping parameters 
+    // simulation patterns
+    Vec_Int_t *      vXorNodes;      // nodes used in speculative reduction
+    int              nAllProved;     // total number of proved nodes
+    int              nAllDisproved;  // total number of disproved nodes
+    int              nAllFailed;     // total number of failed nodes
+    // runtime stats
+    abctime          timeSim;        // unsat
+    abctime          timePat;        // unsat
+    abctime          timeSat;        // sat
+    abctime          timeTotal;      // total runtime
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== cecCorr.c ============================================================*/
+extern void                 Cec_ManRefinedClassPrintStats( Gia_Man_t * p, Vec_Str_t * vStatus, int iIter, abctime Time );
+/*=== cecClass.c ============================================================*/
+extern int                  Cec_ManSimClassRemoveOne( Cec_ManSim_t * p, int i );
+extern int                  Cec_ManSimClassesPrepare( Cec_ManSim_t * p, int LevelMax );
+extern int                  Cec_ManSimClassesRefine( Cec_ManSim_t * p );
+extern int                  Cec_ManSimSimulateRound( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos );
+/*=== cecIso.c ============================================================*/
+extern int *                Cec_ManDetectIsomorphism( Gia_Man_t * p );
+/*=== cecMan.c ============================================================*/
+extern Cec_ManSat_t *       Cec_ManSatCreate( Gia_Man_t * pAig, Cec_ParSat_t * pPars );
+extern void                 Cec_ManSatPrintStats( Cec_ManSat_t * p );
+extern void                 Cec_ManSatStop( Cec_ManSat_t * p );
+extern Cec_ManPat_t *       Cec_ManPatStart();
+extern void                 Cec_ManPatPrintStats( Cec_ManPat_t * p );
+extern void                 Cec_ManPatStop( Cec_ManPat_t * p );
+extern Cec_ManSim_t *       Cec_ManSimStart( Gia_Man_t * pAig, Cec_ParSim_t *  pPars ); 
+extern void                 Cec_ManSimStop( Cec_ManSim_t * p );  
+extern Cec_ManFra_t *       Cec_ManFraStart( Gia_Man_t * pAig, Cec_ParFra_t *  pPars );  
+extern void                 Cec_ManFraStop( Cec_ManFra_t * p );
+/*=== cecPat.c ============================================================*/
+extern void                 Cec_ManPatSavePattern( Cec_ManPat_t *  pPat, Cec_ManSat_t *  p, Gia_Obj_t * pObj );
+extern Vec_Ptr_t *          Cec_ManPatCollectPatterns( Cec_ManPat_t *  pMan, int nInputs, int nWords );
+extern Vec_Ptr_t *          Cec_ManPatPackPatterns( Vec_Int_t * vCexStore, int nInputs, int nRegs, int nWordsInit );
+/*=== cecSeq.c ============================================================*/
+extern int                  Cec_ManSeqResimulate( Cec_ManSim_t * p, Vec_Ptr_t * vInfo );
+extern int                  Cec_ManSeqResimulateInfo( Gia_Man_t * pAig, Vec_Ptr_t * vSimInfo, Abc_Cex_t * pBestState, int fCheckMiter );
+extern void                 Cec_ManSeqDeriveInfoInitRandom( Vec_Ptr_t * vInfo, Gia_Man_t * pAig, Abc_Cex_t * pCex );
+extern int                  Cec_ManCountNonConstOutputs( Gia_Man_t * pAig );
+extern int                  Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig );
+/*=== cecSolve.c ============================================================*/
+extern int                  Cec_ObjSatVarValue( Cec_ManSat_t * p, Gia_Obj_t * pObj );
+extern void                 Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars );
+extern Vec_Str_t *          Cec_ManSatSolveSeq( Vec_Ptr_t * vPatts, Gia_Man_t * pAig, Cec_ParSat_t * pPars, int nRegs, int * pnPats );
+extern Vec_Int_t *          Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Str_t ** pvStatus );
+extern int                  Cec_ManSatCheckNode( Cec_ManSat_t * p, Gia_Obj_t * pObj );
+extern int                  Cec_ManSatCheckNodeTwo( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 );
+extern void                 Cec_ManSavePattern( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 );
+extern Vec_Int_t *          Cec_ManSatReadCex( Cec_ManSat_t * p );
+/*=== ceFraeep.c ============================================================*/
+extern Gia_Man_t *          Cec_ManFraSpecReduction( Cec_ManFra_t * p );
+extern int                  Cec_ManFraClassesUpdate( Cec_ManFra_t * p, Cec_ManSim_t * pSim, Cec_ManPat_t * pPat, Gia_Man_t * pNew );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/cec/cecIso.c b/abc-build/src/proof/cec/cecIso.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/cecIso.c
@@ -0,0 +1,375 @@
+/**CFile****************************************************************
+
+  FileName    [cecIso.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Combinational equivalence checking.]
+
+  Synopsis    [Detection of structural isomorphism.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cecIso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline unsigned * Cec_ManIsoInfo( unsigned * pStore, int nWords, int Id ) { return pStore + nWords * Id; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes simulation info for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManIsoSimulate( Gia_Obj_t * pObj, int Id, unsigned * pStore, int nWords )
+{
+    unsigned * pInfo  = Cec_ManIsoInfo( pStore, nWords, Id );
+    unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Gia_ObjFaninId0(pObj, Id) );
+    unsigned * pInfo1 = Cec_ManIsoInfo( pStore, nWords, Gia_ObjFaninId1(pObj, Id) );
+    int w;
+    if ( Gia_ObjFaninC0(pObj) )
+    {
+        if (  Gia_ObjFaninC1(pObj) )
+            for ( w = 0; w < nWords; w++ )
+                pInfo[w] = ~(pInfo0[w] | pInfo1[w]);
+        else 
+            for ( w = 0; w < nWords; w++ )
+                pInfo[w] = ~pInfo0[w] & pInfo1[w];
+    }
+    else 
+    {
+        if (  Gia_ObjFaninC1(pObj) )
+            for ( w = 0; w < nWords; w++ )
+                pInfo[w] = pInfo0[w] & ~pInfo1[w];
+        else 
+            for ( w = 0; w < nWords; w++ )
+                pInfo[w] = pInfo0[w] & pInfo1[w];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Copies simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManIsoCopy( int IdDest, int IdSour, unsigned * pStore, int nWords )
+{
+    unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, IdDest );
+    unsigned * pInfo1 = Cec_ManIsoInfo( pStore, nWords, IdSour );
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        pInfo0[w] = pInfo1[w];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares simulation info of two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManIsoEqual( int Id0, int Id1, unsigned * pStore, int nWords )
+{
+    unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Id0 );
+    unsigned * pInfo1 = Cec_ManIsoInfo( pStore, nWords, Id1 );
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        if ( pInfo0[w] != pInfo1[w] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generates random simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManIsoRandom( int Id, unsigned * pStore, int nWords )
+{
+    unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Id );
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        pInfo0[w] = Gia_ManRandom( 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash key of the simuation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManIsoHashKey( int Id, unsigned * pStore, int nWords, int nTableSize )
+{
+    static int s_Primes[16] = { 
+        1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, 
+        4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 };
+    unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Id );
+    unsigned uHash = 0;
+    int i;
+    for ( i = 0; i < nWords; i++ )
+        uHash ^= pInfo0[i] * s_Primes[i & 0xf];
+    return (int)(uHash % nTableSize);
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds node to the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManIsoTableAdd( Gia_Man_t * p, int Id, unsigned * pStore, int nWords, int * pTable, int nTableSize )
+{
+    Gia_Obj_t * pTemp;
+    int Key, Ent, Color = Gia_ObjColors( p, Id );
+    assert( Color == 1 || Color == 2 );
+    Key = Gia_ManIsoHashKey( Id, pStore, nWords, nTableSize );
+    for ( Ent = pTable[Key],  pTemp = (Ent ?  Gia_ManObj(p, Ent) : NULL);  pTemp;
+          Ent = pTemp->Value, pTemp = (Ent ?  Gia_ManObj(p, Ent) : NULL) )
+    {
+        if ( Gia_ObjColors( p, Ent ) != Color )
+            continue;
+        if ( !Gia_ManIsoEqual( Id, Ent, pStore, nWords ) )
+            continue;
+        // found node with the same color and signature - mark it and do not add new node
+        pTemp->fMark0 = 1;
+        return;
+    }
+    // did not find the node with the same color and signature - add new node
+    pTemp = Gia_ManObj( p, Id );
+    assert( pTemp->Value == 0 );
+    assert( pTemp->fMark0 == 0 );
+    pTemp->Value = pTable[Key];
+    pTable[Key] = Id;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Extracts equivalence class candidates from one bin.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Gia_ManIsoExtractClasses( Gia_Man_t * p, int Bin, unsigned * pStore, int nWords, Vec_Int_t * vNodesA, Vec_Int_t * vNodesB )
+{
+    Gia_Obj_t * pTemp;
+    int Ent;
+    Vec_IntClear( vNodesA );
+    Vec_IntClear( vNodesB );
+    for ( Ent = Bin,          pTemp = (Ent ?  Gia_ManObj(p, Ent) : NULL);  pTemp;
+          Ent = pTemp->Value, pTemp = (Ent ?  Gia_ManObj(p, Ent) : NULL) )
+    {
+        if ( pTemp->fMark0 )
+        {
+            pTemp->fMark0 = 0;
+            continue;
+        }
+        if ( Gia_ObjColors( p, Ent ) == 1 )
+            Vec_IntPush( vNodesA, Ent );
+        else
+            Vec_IntPush( vNodesB, Ent );
+    }
+    return Vec_IntSize(vNodesA) > 0 && Vec_IntSize(vNodesB) > 0;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Matches nodes in the extacted classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Gia_ManIsoMatchNodes( int * pIso, unsigned * pStore, int nWords, Vec_Int_t * vNodesA, Vec_Int_t * vNodesB )
+{
+    int k0, k1, IdA, IdB;
+    Vec_IntForEachEntry( vNodesA, IdA, k0 )
+    Vec_IntForEachEntry( vNodesB, IdB, k1 )
+    {
+        if ( Gia_ManIsoEqual( IdA, IdB, pStore, nWords ) )
+        {
+            assert( pIso[IdA] == 0 );
+            assert( pIso[IdB] == 0 );
+            assert( IdA != IdB );
+            pIso[IdA] = IdB;
+            pIso[IdB] = IdA;
+            continue;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms iso into equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManTransformClasses( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    assert( p->pReprs && p->pNexts && p->pIso );
+    memset( p->pReprs, 0, sizeof(int) * Gia_ManObjNum(p) );
+    memset( p->pNexts, 0, sizeof(int) * Gia_ManObjNum(p) );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        p->pReprs[i].iRepr = GIA_VOID;
+        if ( p->pIso[i] && p->pIso[i] < i )
+        {
+            p->pReprs[i].iRepr = p->pIso[i];
+            p->pNexts[p->pIso[i]] = i;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds node correspondences in the miter.]
+
+  Description [Assumes that the colors are assigned.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Cec_ManDetectIsomorphism( Gia_Man_t * p )
+{
+    int nWords = 2;
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vNodesA, * vNodesB;
+    unsigned * pStore, Counter;
+    int i, * pIso, * pTable, nTableSize;
+    // start equivalence classes
+    pIso = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    Gia_ManForEachObj( p, pObj, i )
+    {
+        if ( Gia_ObjIsCo(pObj) )
+        {
+            assert( Gia_ObjColors(p, i) == 0 );
+            continue;
+        }
+        assert( Gia_ObjColors(p, i) );
+        if ( Gia_ObjColors(p, i) == 3 )
+            pIso[i] = i;
+    }
+    // start simulation info
+    pStore = ABC_ALLOC( unsigned, Gia_ManObjNum(p) * nWords );
+    // simulate and create table
+    nTableSize = Abc_PrimeCudd( 100 + Gia_ManObjNum(p)/2 );
+    pTable = ABC_CALLOC( int, nTableSize );
+    Gia_ManCleanValue( p );
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        if ( Gia_ObjIsCo(pObj) )
+            continue;
+        if ( pIso[i] == 0 ) // simulate
+            Gia_ManIsoSimulate( pObj, i, pStore, nWords );
+        else if ( pIso[i] < i ) // copy
+            Gia_ManIsoCopy( i, pIso[i], pStore, nWords );
+        else // generate
+            Gia_ManIsoRandom( i, pStore, nWords );
+        if ( pIso[i] == 0 )
+            Gia_ManIsoTableAdd( p, i, pStore, nWords, pTable, nTableSize );
+    }
+    // create equivalence classes
+    vNodesA = Vec_IntAlloc( 100 );
+    vNodesB = Vec_IntAlloc( 100 );
+    for ( i = 0; i < nTableSize; i++ )
+        if ( Gia_ManIsoExtractClasses( p, pTable[i], pStore, nWords, vNodesA, vNodesB ) )
+            Gia_ManIsoMatchNodes( pIso, pStore, nWords, vNodesA, vNodesB );
+    Vec_IntFree( vNodesA );
+    Vec_IntFree( vNodesB );
+    // collect info
+    Counter = 0;
+    Gia_ManForEachObj1( p, pObj, i )
+    {
+        Counter += (pIso[i] && pIso[i] < i);
+/*
+        if ( pIso[i] && pIso[i] < i )
+        {
+            if ( (Gia_ObjIsHead(p,pIso[i]) && Gia_ObjRepr(p,i)==pIso[i]) || 
+                 (Gia_ObjIsClass(p,pIso[i]) && Gia_ObjRepr(p,i)==Gia_ObjRepr(p,pIso[i])) )
+                 Abc_Print( 1, "1" );
+            else
+                Abc_Print( 1, "0" );
+        }
+*/
+    }
+    Abc_Print( 1, "Computed %d pairs of structurally equivalent nodes.\n", Counter );
+//    p->pIso = pIso;
+//    Cec_ManTransformClasses( p );
+
+    ABC_FREE( pTable );
+    ABC_FREE( pStore );
+    return pIso;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/cec/cecMan.c b/abc-build/src/proof/cec/cecMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/cecMan.c
@@ -0,0 +1,297 @@
+/**CFile****************************************************************
+
+  FileName    [cecMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Combinational equivalence checking.]
+
+  Synopsis    [Manager procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cecMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cec_ManSat_t * Cec_ManSatCreate( Gia_Man_t * pAig, Cec_ParSat_t * pPars )
+{
+    Cec_ManSat_t * p;
+    // create interpolation manager
+    p = ABC_ALLOC( Cec_ManSat_t, 1 );
+    memset( p, 0, sizeof(Cec_ManSat_t) );
+    p->pPars        = pPars;
+    p->pAig         = pAig;
+    // SAT solving
+    p->nSatVars     = 1;
+    p->pSatVars     = ABC_CALLOC( int, Gia_ManObjNum(pAig) );
+    p->vUsedNodes   = Vec_PtrAlloc( 1000 );
+    p->vFanins      = Vec_PtrAlloc( 100 );
+    p->vCex         = Vec_IntAlloc( 100 );
+    p->vVisits      = Vec_IntAlloc( 100 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints statistics of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSatPrintStats( Cec_ManSat_t * p )
+{
+    Abc_Print( 1, "CO = %8d  ", Gia_ManCoNum(p->pAig) );
+    Abc_Print( 1, "AND = %8d  ", Gia_ManAndNum(p->pAig) );
+    Abc_Print( 1, "Conf = %5d  ", p->pPars->nBTLimit );
+    Abc_Print( 1, "MinVar = %5d  ", p->pPars->nSatVarMax );
+    Abc_Print( 1, "MinCalls = %5d\n", p->pPars->nCallsRecycle );
+    Abc_Print( 1, "Unsat calls %6d  (%6.2f %%)   Ave conf = %8.1f   ", 
+        p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal : 0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 );
+    Abc_PrintTimeP( 1, "Time", p->timeSatUnsat, p->timeTotal );
+    Abc_Print( 1, "Sat   calls %6d  (%6.2f %%)   Ave conf = %8.1f   ", 
+        p->nSatSat,   p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal : 0.0,   p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 );
+    Abc_PrintTimeP( 1, "Time", p->timeSatSat,   p->timeTotal );
+    Abc_Print( 1, "Undef calls %6d  (%6.2f %%)   Ave conf = %8.1f   ", 
+        p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal : 0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 );
+    Abc_PrintTimeP( 1, "Time", p->timeSatUndec, p->timeTotal );
+    Abc_PrintTime( 1, "Total time", p->timeTotal );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSatStop( Cec_ManSat_t * p )
+{
+    if ( p->pSat )
+        sat_solver_delete( p->pSat );
+    Vec_IntFree( p->vCex );
+    Vec_IntFree( p->vVisits );
+    Vec_PtrFree( p->vUsedNodes );
+    Vec_PtrFree( p->vFanins );
+    ABC_FREE( p->pSatVars );
+    ABC_FREE( p );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cec_ManPat_t * Cec_ManPatStart()  
+{ 
+    Cec_ManPat_t * p;
+    p = ABC_CALLOC( Cec_ManPat_t, 1 );
+    p->vStorage  = Vec_StrAlloc( 1<<20 );
+    p->vPattern1 = Vec_IntAlloc( 1000 );
+    p->vPattern2 = Vec_IntAlloc( 1000 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManPatPrintStats( Cec_ManPat_t * p )  
+{ 
+    Abc_Print( 1, "Latest: P = %8d.  L = %10d.  Lm = %10d. Ave = %6.1f. MEM =%6.2f MB\n", 
+        p->nPats, p->nPatLits, p->nPatLitsMin, 1.0 * p->nPatLitsMin/p->nPats, 
+        1.0*(Vec_StrSize(p->vStorage)-p->iStart)/(1<<20) );
+    Abc_Print( 1, "Total:  P = %8d.  L = %10d.  Lm = %10d. Ave = %6.1f. MEM =%6.2f MB\n", 
+        p->nPatsAll, p->nPatLitsAll, p->nPatLitsMinAll, 1.0 * p->nPatLitsMinAll/p->nPatsAll, 
+        1.0*Vec_StrSize(p->vStorage)/(1<<20) );
+    Abc_PrintTimeP( 1, "Finding  ", p->timeFind,   p->timeTotal );
+    Abc_PrintTimeP( 1, "Shrinking", p->timeShrink, p->timeTotal );
+    Abc_PrintTimeP( 1, "Verifying", p->timeVerify, p->timeTotal );
+    Abc_PrintTimeP( 1, "Sorting  ", p->timeSort,   p->timeTotal );
+    Abc_PrintTimeP( 1, "Packing  ", p->timePack,   p->timeTotal );
+    Abc_PrintTime( 1, "TOTAL    ",  p->timeTotal );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManPatStop( Cec_ManPat_t * p )  
+{
+    Vec_StrFree( p->vStorage );
+    Vec_IntFree( p->vPattern1 );
+    Vec_IntFree( p->vPattern2 );
+    ABC_FREE( p );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cec_ManSim_t * Cec_ManSimStart( Gia_Man_t * pAig, Cec_ParSim_t *  pPars )  
+{ 
+    Cec_ManSim_t * p;
+    p = ABC_ALLOC( Cec_ManSim_t, 1 );
+    memset( p, 0, sizeof(Cec_ManSim_t) );
+    p->pAig  = pAig;
+    p->pPars = pPars;
+    p->nWords = pPars->nWords;
+    p->pSimInfo = ABC_CALLOC( int, Gia_ManObjNum(pAig) );
+    p->vClassOld  = Vec_IntAlloc( 1000 );
+    p->vClassNew  = Vec_IntAlloc( 1000 );
+    p->vClassTemp = Vec_IntAlloc( 1000 );
+    p->vRefinedC  = Vec_IntAlloc( 10000 );
+    p->vCiSimInfo = Vec_PtrAllocSimInfo( Gia_ManCiNum(p->pAig), pPars->nWords );
+    if ( pPars->fCheckMiter || Gia_ManRegNum(p->pAig) )
+    {
+        p->vCoSimInfo = Vec_PtrAllocSimInfo( Gia_ManCoNum(p->pAig), pPars->nWords );
+        Vec_PtrCleanSimInfo( p->vCoSimInfo, 0, pPars->nWords );
+    }
+    p->iOut = -1;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSimStop( Cec_ManSim_t * p )  
+{
+    Vec_IntFree( p->vClassOld );
+    Vec_IntFree( p->vClassNew );
+    Vec_IntFree( p->vClassTemp );
+    Vec_IntFree( p->vRefinedC );
+    if ( p->vCiSimInfo ) 
+        Vec_PtrFree( p->vCiSimInfo );
+    if ( p->vCoSimInfo ) 
+        Vec_PtrFree( p->vCoSimInfo );
+    ABC_FREE( p->pScores );
+    ABC_FREE( p->pCexComb );
+    ABC_FREE( p->pCexes );
+    ABC_FREE( p->pMems );
+    ABC_FREE( p->pSimInfo );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cec_ManFra_t * Cec_ManFraStart( Gia_Man_t * pAig, Cec_ParFra_t *  pPars )  
+{ 
+    Cec_ManFra_t * p;
+    p = ABC_ALLOC( Cec_ManFra_t, 1 );
+    memset( p, 0, sizeof(Cec_ManFra_t) );
+    p->pAig  = pAig;
+    p->pPars = pPars;
+    p->vXorNodes  = Vec_IntAlloc( 1000 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManFraStop( Cec_ManFra_t * p )  
+{
+    Vec_IntFree( p->vXorNodes );
+    ABC_FREE( p );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/cec/cecPat.c b/abc-build/src/proof/cec/cecPat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/cecPat.c
@@ -0,0 +1,570 @@
+/**CFile****************************************************************
+
+  FileName    [cecPat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Combinational equivalence checking.]
+
+  Synopsis    [Simulation pattern manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cecPat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cec_ManPatStoreNum( Cec_ManPat_t * p, int Num )
+{
+    unsigned x = (unsigned)Num;
+    assert( Num >= 0 );
+    while ( x & ~0x7f )
+    {
+        Vec_StrPush( p->vStorage, (char)((x & 0x7f) | 0x80) );
+        x >>= 7;
+    }
+    Vec_StrPush( p->vStorage, (char)x );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cec_ManPatRestoreNum( Cec_ManPat_t * p )
+{
+    int ch, i, x = 0;
+    for ( i = 0; (ch = Vec_StrEntry(p->vStorage, p->iStart++)) & 0x80; i++ )
+        x |= (ch & 0x7f) << (7 * i);
+    return x | (ch << (7 * i));
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cec_ManPatStore( Cec_ManPat_t * p, Vec_Int_t * vPat )
+{
+    int i, Number, NumberPrev;
+    assert( Vec_IntSize(vPat) > 0 );
+    Cec_ManPatStoreNum( p, Vec_IntSize(vPat) );
+    NumberPrev = Vec_IntEntry( vPat, 0 );
+    Cec_ManPatStoreNum( p, NumberPrev );
+    Vec_IntForEachEntryStart( vPat, Number, i, 1 )
+    {
+        assert( NumberPrev < Number );
+        Cec_ManPatStoreNum( p, Number - NumberPrev );
+        NumberPrev = Number;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cec_ManPatRestore( Cec_ManPat_t * p, Vec_Int_t * vPat )
+{
+    int i, Size, Number;
+    Vec_IntClear( vPat );
+    Size = Cec_ManPatRestoreNum( p );
+    Number = Cec_ManPatRestoreNum( p );
+    Vec_IntPush( vPat, Number );
+    for ( i = 1; i < Size; i++ )
+    {
+        Number += Cec_ManPatRestoreNum( p );
+        Vec_IntPush( vPat, Number );
+    }
+    assert( Vec_IntSize(vPat) == Size );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives satisfying assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManPatComputePattern_rec( Cec_ManSat_t * pSat, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    int Counter = 0;
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return 0;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+    {
+        pObj->fMark1 = Cec_ObjSatVarValue( pSat, pObj );
+        return 1;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Counter += Cec_ManPatComputePattern_rec( pSat, p, Gia_ObjFanin0(pObj) );
+    Counter += Cec_ManPatComputePattern_rec( pSat, p, Gia_ObjFanin1(pObj) );
+    pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) & 
+                   (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj));
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives satisfying assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManPatComputePattern1_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPat )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+    {
+        Vec_IntPush( vPat, Abc_Var2Lit( Gia_ObjCioId(pObj), pObj->fMark1==0 ) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    if ( pObj->fMark1 == 1 )
+    {
+        Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin0(pObj), vPat );
+        Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin1(pObj), vPat );
+    }
+    else
+    {
+        assert( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 0 ||
+                (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)) == 0 );
+        if ( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 0 )
+            Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin0(pObj), vPat );
+        else
+            Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin1(pObj), vPat );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives satisfying assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManPatComputePattern2_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPat )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+    {
+        Vec_IntPush( vPat, Abc_Var2Lit( Gia_ObjCioId(pObj), pObj->fMark1==0 ) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    if ( pObj->fMark1 == 1 )
+    {
+        Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin0(pObj), vPat );
+        Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin1(pObj), vPat );
+    }
+    else
+    {
+        assert( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 0 ||
+                (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)) == 0 );
+        if ( (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)) == 0 )
+            Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin1(pObj), vPat );
+        else
+            Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin0(pObj), vPat );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives satisfying assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManPatComputePattern3_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    int Value0, Value1, Value;
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return (pObj->fMark1 << 1) | pObj->fMark0;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+    {
+        pObj->fMark0 = 1;
+        pObj->fMark1 = 1;
+        return GIA_UND;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Value0 = Cec_ManPatComputePattern3_rec( p, Gia_ObjFanin0(pObj) );
+    Value1 = Cec_ManPatComputePattern3_rec( p, Gia_ObjFanin1(pObj) );
+    Value = Gia_XsimAndCond( Value0, Gia_ObjFaninC0(pObj), Value1, Gia_ObjFaninC1(pObj) );
+    pObj->fMark0 =  (Value & 1);
+    pObj->fMark1 = ((Value >> 1) & 1);
+    return Value;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives satisfying assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManPatVerifyPattern( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPat )
+{
+    Gia_Obj_t * pTemp;
+    int i, Value;
+    Gia_ManIncrementTravId( p );
+    Vec_IntForEachEntry( vPat, Value, i )
+    {
+        pTemp = Gia_ManCi( p, Abc_Lit2Var(Value) );
+//        assert( Abc_LitIsCompl(Value) != (int)pTemp->fMark1 );
+        if ( pTemp->fMark1 )
+        {
+            pTemp->fMark0 = 0;
+            pTemp->fMark1 = 1;
+        }
+        else
+        {
+            pTemp->fMark0 = 1;
+            pTemp->fMark1 = 0;
+        }
+        Gia_ObjSetTravIdCurrent( p, pTemp );
+    }
+    Value = Cec_ManPatComputePattern3_rec( p, Gia_ObjFanin0(pObj) );
+    Value = Gia_XsimNotCond( Value, Gia_ObjFaninC0(pObj) );
+    if ( Value != GIA_ONE )
+        Abc_Print( 1, "Cec_ManPatVerifyPattern(): Verification failed.\n" );
+    assert( Value == GIA_ONE );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManPatComputePattern4_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    pObj->fMark0 = 0;
+    if ( Gia_ObjIsCi(pObj) )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    Cec_ManPatComputePattern4_rec( p, Gia_ObjFanin0(pObj) );
+    Cec_ManPatComputePattern4_rec( p, Gia_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManPatCleanMark0( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    assert( Gia_ObjIsCo(pObj) );
+    Gia_ManIncrementTravId( p );
+    Cec_ManPatComputePattern4_rec( p, Gia_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManPatSavePattern( Cec_ManPat_t * pMan, Cec_ManSat_t *  p, Gia_Obj_t * pObj )
+{
+    Vec_Int_t * vPat;
+    int nPatLits;
+    abctime clk, clkTotal = Abc_Clock();
+    assert( Gia_ObjIsCo(pObj) );
+    pMan->nPats++;
+    pMan->nPatsAll++;
+    // compute values in the cone of influence
+clk = Abc_Clock();
+    Gia_ManIncrementTravId( p->pAig );
+    nPatLits = Cec_ManPatComputePattern_rec( p, p->pAig, Gia_ObjFanin0(pObj) );
+    assert( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 1 );
+    pMan->nPatLits += nPatLits;
+    pMan->nPatLitsAll += nPatLits;
+pMan->timeFind += Abc_Clock() - clk;
+    // compute sensitizing path
+clk = Abc_Clock();
+    Vec_IntClear( pMan->vPattern1 );
+    Gia_ManIncrementTravId( p->pAig );
+    Cec_ManPatComputePattern1_rec( p->pAig, Gia_ObjFanin0(pObj), pMan->vPattern1 );
+    // compute sensitizing path
+    Vec_IntClear( pMan->vPattern2 );
+    Gia_ManIncrementTravId( p->pAig );
+    Cec_ManPatComputePattern2_rec( p->pAig, Gia_ObjFanin0(pObj), pMan->vPattern2 );
+    // compare patterns
+    vPat = Vec_IntSize(pMan->vPattern1) < Vec_IntSize(pMan->vPattern2) ? pMan->vPattern1 : pMan->vPattern2;
+    pMan->nPatLitsMin += Vec_IntSize(vPat);
+    pMan->nPatLitsMinAll += Vec_IntSize(vPat);
+pMan->timeShrink += Abc_Clock() - clk;
+    // verify pattern using ternary simulation
+clk = Abc_Clock();
+    Cec_ManPatVerifyPattern( p->pAig, pObj, vPat );
+pMan->timeVerify += Abc_Clock() - clk;
+    // sort pattern
+clk = Abc_Clock();
+    Vec_IntSort( vPat, 0 );
+pMan->timeSort += Abc_Clock() - clk;
+    // save pattern
+    Cec_ManPatStore( pMan, vPat );
+    pMan->timeTotal += Abc_Clock() - clkTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Packs patterns into array of simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+*************************************`**********************************/
+int Cec_ManPatCollectTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * pLits, int nLits )
+{
+    unsigned * pInfo, * pPres;
+    int i;
+    for ( i = 0; i < nLits; i++ )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i]));
+        pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i]));
+        if ( Abc_InfoHasBit( pPres, iBit ) && 
+             Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) )
+             return 0;
+    }
+    for ( i = 0; i < nLits; i++ )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i]));
+        pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i]));
+        Abc_InfoSetBit( pPres, iBit );
+        if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) )
+            Abc_InfoXorBit( pInfo, iBit );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Packs patterns into array of simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Cec_ManPatCollectPatterns( Cec_ManPat_t *  pMan, int nInputs, int nWordsInit )
+{
+    Vec_Int_t * vPat = pMan->vPattern1;
+    Vec_Ptr_t * vInfo, * vPres;
+    int k, kMax = -1, nPatterns = 0;
+    int iStartOld = pMan->iStart;
+    int nWords = nWordsInit;
+    int nBits = 32 * nWords;
+    abctime clk = Abc_Clock();
+    vInfo = Vec_PtrAllocSimInfo( nInputs, nWords );
+    Gia_ManRandomInfo( vInfo, 0, 0, nWords );
+    vPres = Vec_PtrAllocSimInfo( nInputs, nWords );
+    Vec_PtrCleanSimInfo( vPres, 0, nWords );
+    while ( pMan->iStart < Vec_StrSize(pMan->vStorage) )
+    {
+        nPatterns++;
+        Cec_ManPatRestore( pMan, vPat );
+        for ( k = 1; k < nBits; k++, k += ((k % (32 * nWordsInit)) == 0) )
+            if ( Cec_ManPatCollectTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) )
+                break;
+        kMax = Abc_MaxInt( kMax, k );
+        if ( k == nBits-1 )
+        {
+            Vec_PtrReallocSimInfo( vInfo );
+            Gia_ManRandomInfo( vInfo, 0, nWords, 2*nWords );
+            Vec_PtrReallocSimInfo( vPres );
+            Vec_PtrCleanSimInfo( vPres, nWords, 2*nWords );
+            nWords *= 2;
+            nBits *= 2;
+        }
+    }
+    Vec_PtrFree( vPres );
+    pMan->nSeries = Vec_PtrReadWordsSimInfo(vInfo) / nWordsInit;
+    pMan->timePack += Abc_Clock() - clk;
+    pMan->timeTotal += Abc_Clock() - clk;
+    pMan->iStart = iStartOld;
+    if ( pMan->fVerbose )
+    {
+        Abc_Print( 1, "Total = %5d. Max used = %5d. Full = %5d. Series = %d. ", 
+            nPatterns, kMax, nWordsInit*32, pMan->nSeries );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+        Cec_ManPatPrintStats( pMan );
+    }
+    return vInfo;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Packs patterns into array of simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Cec_ManPatPackPatterns( Vec_Int_t * vCexStore, int nInputs, int nRegs, int nWordsInit )
+{
+    Vec_Int_t * vPat;
+    Vec_Ptr_t * vInfo, * vPres;
+    int k, nSize, iStart, kMax = 0, nPatterns = 0;
+    int nWords = nWordsInit;
+    int nBits = 32 * nWords;
+//    int RetValue;
+    assert( nRegs <= nInputs );
+    vPat  = Vec_IntAlloc( 100 );
+
+    vInfo = Vec_PtrAllocSimInfo( nInputs, nWords );
+    Vec_PtrCleanSimInfo( vInfo, 0, nWords );
+    Gia_ManRandomInfo( vInfo, nRegs, 0, nWords );
+
+    vPres = Vec_PtrAllocSimInfo( nInputs, nWords );
+    Vec_PtrCleanSimInfo( vPres, 0, nWords );
+    iStart = 0;
+    while ( iStart < Vec_IntSize(vCexStore) )
+    {
+        nPatterns++;
+        // skip the output number
+        iStart++;
+        // get the number of items
+        nSize = Vec_IntEntry( vCexStore, iStart++ );
+        if ( nSize <= 0 )
+            continue;
+        // extract pattern
+        Vec_IntClear( vPat );
+        for ( k = 0; k < nSize; k++ )
+            Vec_IntPush( vPat, Vec_IntEntry( vCexStore, iStart++ ) );
+        // add pattern to storage
+        for ( k = 1; k < nBits; k++, k += ((k % (32 * nWordsInit)) == 0) )
+            if ( Cec_ManPatCollectTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) )
+                break;
+
+//        k = kMax + 1;
+//        RetValue = Cec_ManPatCollectTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) );
+//        assert( RetValue == 1 );
+
+        kMax = Abc_MaxInt( kMax, k );
+        if ( k == nBits-1 )
+        {
+            Vec_PtrReallocSimInfo( vInfo );
+            Vec_PtrCleanSimInfo( vInfo, nWords, 2*nWords );
+            Gia_ManRandomInfo( vInfo, nRegs, nWords, 2*nWords );
+
+            Vec_PtrReallocSimInfo( vPres );
+            Vec_PtrCleanSimInfo( vPres, nWords, 2*nWords );
+            nWords *= 2;
+            nBits *= 2;
+        }
+    }
+//    Abc_Print( 1, "packed %d patterns into %d vectors (out of %d)\n", nPatterns, kMax, nBits );
+    Vec_PtrFree( vPres );
+    Vec_IntFree( vPat );
+    return vInfo;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/cec/cecSeq.c b/abc-build/src/proof/cec/cecSeq.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/cecSeq.c
@@ -0,0 +1,449 @@
+/**CFile****************************************************************
+
+  FileName    [cecSeq.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Combinational equivalence checking.]
+
+  Synopsis    [Refinement of sequential equivalence classes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cecSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Sets register values from the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSeqDeriveInfoFromCex( Vec_Ptr_t * vInfo, Gia_Man_t * pAig, Abc_Cex_t * pCex )
+{
+    unsigned * pInfo;
+    int k, i, w, nWords;
+    assert( pCex->nBits == pCex->nRegs + pCex->nPis * (pCex->iFrame + 1) );
+    assert( pCex->nBits - pCex->nRegs + Gia_ManRegNum(pAig) <= Vec_PtrSize(vInfo) );
+    nWords = Vec_PtrReadWordsSimInfo( vInfo );
+/*
+    // user register values
+    assert( pCex->nRegs == Gia_ManRegNum(pAig) );
+    for ( k = 0; k < pCex->nRegs; k++ )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry( vInfo, k );
+        for ( w = 0; w < nWords; w++ )
+            pInfo[w] = Abc_InfoHasBit( pCex->pData, k )? ~0 : 0;
+    }
+*/
+    // print warning about register values
+    for ( k = 0; k < pCex->nRegs; k++ )
+        if ( Abc_InfoHasBit( pCex->pData, k ) )
+            break;
+    if ( k < pCex->nRegs )
+        Abc_Print( 0, "The CEX has flop values different from 0, but they are currently not used by \"resim\".\n" );
+
+    // assign zero register values
+    for ( k = 0; k < Gia_ManRegNum(pAig); k++ )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry( vInfo, k );
+        for ( w = 0; w < nWords; w++ )
+            pInfo[w] = 0;
+    }
+    for ( i = pCex->nRegs; i < pCex->nBits; i++ )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry( vInfo, k++ );
+        for ( w = 0; w < nWords; w++ )
+            pInfo[w] = Gia_ManRandom(0);
+        // set simulation pattern and make sure it is second (first will be erased during simulation)
+        pInfo[0] = (pInfo[0] << 1) | Abc_InfoHasBit( pCex->pData, i ); 
+        pInfo[0] <<= 1;
+    }
+    for ( ; k < Vec_PtrSize(vInfo); k++ )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry( vInfo, k );
+        for ( w = 0; w < nWords; w++ )
+            pInfo[w] = Gia_ManRandom(0);
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets register values from the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSeqDeriveInfoInitRandom( Vec_Ptr_t * vInfo, Gia_Man_t * pAig, Abc_Cex_t * pCex )
+{
+    unsigned * pInfo;
+    int k, w, nWords;
+    nWords = Vec_PtrReadWordsSimInfo( vInfo );
+    assert( pCex == NULL || Gia_ManRegNum(pAig) == pCex->nRegs );
+    assert( Gia_ManRegNum(pAig) <= Vec_PtrSize(vInfo) );
+    for ( k = 0; k < Gia_ManRegNum(pAig); k++ )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry( vInfo, k );
+        for ( w = 0; w < nWords; w++ )
+            pInfo[w] = (pCex && Abc_InfoHasBit(pCex->pData, k))? ~0 : 0;
+    }
+
+    for ( ; k < Vec_PtrSize(vInfo); k++ )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry( vInfo, k );
+        for ( w = 0; w < nWords; w++ )
+            pInfo[w] = Gia_ManRandom( 0 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulates the classes using sequential simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSeqResimulate( Cec_ManSim_t * p, Vec_Ptr_t * vInfo )
+{
+    unsigned * pInfo0, * pInfo1;
+    int f, i, k, w;
+//    assert( Gia_ManRegNum(p->pAig) > 0 );
+    assert( Vec_PtrSize(vInfo) == Gia_ManRegNum(p->pAig) + Gia_ManPiNum(p->pAig) * p->pPars->nFrames );
+    for ( k = 0; k < Gia_ManRegNum(p->pAig); k++ )
+    {
+        pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, k );
+        pInfo1 = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, Gia_ManPoNum(p->pAig) + k );
+        for ( w = 0; w < p->nWords; w++ )
+            pInfo1[w] = pInfo0[w];
+    }
+    for ( f = 0; f < p->pPars->nFrames; f++ )
+    {
+        for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ )
+        {
+            pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, k++ );
+            pInfo1 = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, i );
+            for ( w = 0; w < p->nWords; w++ )
+                pInfo1[w] = pInfo0[w];
+        }
+        for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ )
+        {
+            pInfo0 = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, Gia_ManPoNum(p->pAig) + i );
+            pInfo1 = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, Gia_ManPiNum(p->pAig) + i );
+            for ( w = 0; w < p->nWords; w++ )
+                pInfo1[w] = pInfo0[w];
+        }
+        if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) )
+            return 1;
+    }
+    assert( k == Vec_PtrSize(vInfo) );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulates information to refine equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSeqResimulateInfo( Gia_Man_t * pAig, Vec_Ptr_t * vSimInfo, Abc_Cex_t * pBestState, int fCheckMiter )
+{
+    Cec_ParSim_t ParsSim, * pParsSim = &ParsSim;
+    Cec_ManSim_t * pSim;
+    int RetValue;//, clkTotal = Abc_Clock();
+    assert( (Vec_PtrSize(vSimInfo) - Gia_ManRegNum(pAig)) % Gia_ManPiNum(pAig) == 0 );
+    Cec_ManSimSetDefaultParams( pParsSim );
+    pParsSim->nFrames = (Vec_PtrSize(vSimInfo) - Gia_ManRegNum(pAig)) / Gia_ManPiNum(pAig);
+    pParsSim->nWords  = Vec_PtrReadWordsSimInfo( vSimInfo );
+    pParsSim->fCheckMiter = fCheckMiter;
+    Gia_ManCreateValueRefs( pAig );
+    pSim = Cec_ManSimStart( pAig, pParsSim );
+    if ( pBestState )
+        pSim->pBestState = pBestState;
+    RetValue = Cec_ManSeqResimulate( pSim, vSimInfo );
+    pSim->pBestState = NULL;
+    Cec_ManSimStop( pSim );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resimuates one counter-example to refine equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSeqResimulateCounter( Gia_Man_t * pAig, Cec_ParSim_t * pPars, Abc_Cex_t * pCex )
+{
+    Vec_Ptr_t * vSimInfo;
+    int RetValue;
+    abctime clkTotal = Abc_Clock();
+    if ( pCex == NULL )
+    {
+        Abc_Print( 1, "Cec_ManSeqResimulateCounter(): Counter-example is not available.\n" );
+        return -1;
+    }
+    if ( pAig->pReprs == NULL )
+    {
+        Abc_Print( 1, "Cec_ManSeqResimulateCounter(): Equivalence classes are not available.\n" );
+        return -1;
+    }
+    if ( Gia_ManRegNum(pAig) == 0 )
+    {
+        Abc_Print( 1, "Cec_ManSeqResimulateCounter(): Not a sequential AIG.\n" );
+        return -1;
+    }
+//    if ( Gia_ManRegNum(pAig) != pCex->nRegs || Gia_ManPiNum(pAig) != pCex->nPis )
+    if ( Gia_ManPiNum(pAig) != pCex->nPis )
+    {
+        Abc_Print( 1, "Cec_ManSeqResimulateCounter(): The number of PIs in the AIG and the counter-example differ.\n" );
+        return -1;
+    }
+    if ( pPars->fVerbose )
+        Abc_Print( 1, "Resimulating %d timeframes.\n", pPars->nFrames + pCex->iFrame + 1 );
+    Gia_ManRandom( 1 );
+    vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pAig) + 
+        Gia_ManPiNum(pAig) * (pPars->nFrames + pCex->iFrame + 1), 1 );
+    Cec_ManSeqDeriveInfoFromCex( vSimInfo, pAig, pCex );
+    if ( pPars->fVerbose )
+        Gia_ManEquivPrintClasses( pAig, 0, 0 );
+    RetValue = Cec_ManSeqResimulateInfo( pAig, vSimInfo, NULL, pPars->fCheckMiter );
+    if ( pPars->fVerbose )
+        Gia_ManEquivPrintClasses( pAig, 0, 0 );
+    Vec_PtrFree( vSimInfo );
+    if ( pPars->fVerbose )
+        ABC_PRT( "Time", Abc_Clock() - clkTotal );
+//    if ( RetValue && pPars->fCheckMiter )
+//        Abc_Print( 1, "Cec_ManSeqResimulateCounter(): An output of the miter is asserted!\n" );
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of POs that are not const0 cands.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManCountNonConstOutputs( Gia_Man_t * pAig )
+{
+    Gia_Obj_t * pObj;
+    int i, Counter = 0;
+    if ( pAig->pReprs == NULL )
+        return -1;
+    Gia_ManForEachPo( pAig, pObj, i )
+        if ( !Gia_ObjIsConst( pAig, Gia_ObjFaninId0p(pAig, pObj) ) )
+            Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of POs that are not const0 cands.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig )
+{
+    Gia_Obj_t * pObj;
+    int i, RetValue = 0;
+    if ( pAig->pReprs == NULL )
+        return 0;
+    // label internal nodes driving POs
+    Gia_ManForEachPo( pAig, pObj, i )
+        Gia_ObjFanin0(pObj)->fMark0 = 1;
+    // check if there are non-labled equivs
+    Gia_ManForEachObj( pAig, pObj, i )
+        if ( Gia_ObjIsCand(pObj) && !pObj->fMark0 && Gia_ObjRepr(pAig, i) != GIA_VOID )
+        {
+            RetValue = 1;
+            break;
+        }
+    // clean internal nodes driving POs
+    Gia_ManForEachPo( pAig, pObj, i )
+        Gia_ObjFanin0(pObj)->fMark0 = 0;
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs semiformal refinement of equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSeqSemiformal( Gia_Man_t * pAig, Cec_ParSmf_t * pPars )
+{ 
+    int nAddFrames = 16; // additional timeframes to simulate
+    int nCountNoRef = 0;
+    int nFramesReal;
+    Cec_ParSat_t ParsSat, * pParsSat = &ParsSat;
+    Vec_Ptr_t * vSimInfo; 
+    Vec_Str_t * vStatus;
+    Abc_Cex_t * pState;
+    Gia_Man_t * pSrm, * pReduce, * pAux;
+    int r, nPats, RetValue = 0;
+    if ( pAig->pReprs == NULL )
+    { 
+        Abc_Print( 1, "Cec_ManSeqSemiformal(): Equivalence classes are not available.\n" );
+        return -1;
+    }
+    if ( Gia_ManRegNum(pAig) == 0 )
+    {
+        Abc_Print( 1, "Cec_ManSeqSemiformal(): Not a sequential AIG.\n" );
+        return -1;
+    }
+    Gia_ManRandom( 1 );
+    // prepare starting pattern
+    pState = Abc_CexAlloc( Gia_ManRegNum(pAig), 0, 0 );
+    pState->iFrame = -1;
+    pState->iPo = -1;
+    // prepare SAT solving
+    Cec_ManSatSetDefaultParams( pParsSat );
+    pParsSat->nBTLimit = pPars->nBTLimit;
+    pParsSat->fVerbose = pPars->fVerbose;
+    if ( pParsSat->fVerbose )
+    {
+        Abc_Print( 1, "Starting: " );
+        Gia_ManEquivPrintClasses( pAig, 0, 0 );
+    }
+    // perform the given number of BMC rounds
+    Gia_ManCleanMark0( pAig );
+    for ( r = 0; r < pPars->nRounds; r++ )
+    {
+        if ( !Cec_ManCheckNonTrivialCands(pAig) )
+        {
+            Abc_Print( 1, "Cec_ManSeqSemiformal: There are only trivial equiv candidates left (PO drivers). Quitting.\n" );
+            break;
+        }
+//        Abc_CexPrint( pState );
+        // derive speculatively reduced model
+//        pSrm = Gia_ManSpecReduceInit( pAig, pState, pPars->nFrames, pPars->fDualOut );
+        pSrm = Gia_ManSpecReduceInitFrames( pAig, pState, pPars->nFrames, &nFramesReal, pPars->fDualOut, pPars->nMinOutputs );
+        if ( pSrm == NULL )
+        {
+            Abc_Print( 1, "Quitting refinement because miter could not be unrolled.\n" );
+            break;
+        }
+        assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManPiNum(pSrm) == (Gia_ManPiNum(pAig) * nFramesReal) );
+        if ( pPars->fVerbose )
+            Abc_Print( 1, "Unrolled for %d frames.\n", nFramesReal );
+        // allocate room for simulation info
+        vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pAig) + 
+            Gia_ManPiNum(pAig) * (nFramesReal + nAddFrames), pPars->nWords );
+        Cec_ManSeqDeriveInfoInitRandom( vSimInfo, pAig, pState );
+        // fill in simulation info with counter-examples
+        vStatus = Cec_ManSatSolveSeq( vSimInfo, pSrm, pParsSat, Gia_ManRegNum(pAig), &nPats );
+        Vec_StrFree( vStatus );
+        Gia_ManStop( pSrm );
+        // resimulate and refine the classes
+        RetValue = Cec_ManSeqResimulateInfo( pAig, vSimInfo, pState, pPars->fCheckMiter );
+        Vec_PtrFree( vSimInfo );
+        assert( pState->iPo >= 0 ); // hit counter
+        pState->iPo = -1;
+        if ( pPars->fVerbose )
+        {
+            Abc_Print( 1, "BMC = %3d ", nPats );
+            Gia_ManEquivPrintClasses( pAig, 0, 0 );
+        }
+
+        // write equivalence classes
+        Gia_AigerWrite( pAig, "gore.aig", 0, 0 );
+        // reduce the model
+        pReduce = Gia_ManSpecReduce( pAig, 0, 0, 1, 0, 0 );
+        if ( pReduce )
+        {
+            pReduce = Gia_ManSeqStructSweep( pAux = pReduce, 1, 1, 0 );
+            Gia_ManStop( pAux );
+            Gia_AigerWrite( pReduce, "gsrm.aig", 0, 0 );
+//            Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", "gsrm.aig" );
+//          Gia_ManPrintStatsShort( pReduce );
+            Gia_ManStop( pReduce );
+        }
+
+        if ( RetValue )
+        {
+            Abc_Print( 1, "Cec_ManSeqSemiformal(): An output of the miter is asserted. Refinement stopped.\n" );
+            break;
+        }
+        // decide when to stop
+        if ( nPats > 0 )
+            nCountNoRef = 0;
+        else if ( ++nCountNoRef == pPars->nNonRefines )
+            break;
+    }
+    ABC_FREE( pState );
+    if ( pPars->fCheckMiter )
+    {
+        int nNonConsts = Cec_ManCountNonConstOutputs( pAig );
+        if ( nNonConsts )
+            Abc_Print( 1, "The number of POs that are not const-0 candidates = %d.\n", nNonConsts );
+    }
+    return RetValue;
+}
+
+//&r s13207.aig; &ps; &equiv; &ps; &semi -R 2 -vm
+//&r bug/50/temp.aig; &ps; &equiv -smv; &semi -v
+//r mentor/1_05c.blif; st; &get; &ps; &equiv -smv; &semi -mv
+//&r bug/50/hdl1.aig; &ps; &equiv -smv; &semi -mv; &srm; &r gsrm.aig; &ps
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/cec/cecSim.c b/abc-build/src/proof/cec/cecSim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/cecSim.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+  FileName    [cecSim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Combinational equivalence checking.]
+
+  Synopsis    [Simulation manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cecSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/cec/cecSolve.c b/abc-build/src/proof/cec/cecSolve.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/cecSolve.c
@@ -0,0 +1,1028 @@
+/**CFile****************************************************************
+
+  FileName    [cecSolve.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Combinational equivalence checking.]
+
+  Synopsis    [Performs one round of SAT solving.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cecSolve.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int  Cec_ObjSatNum( Cec_ManSat_t * p, Gia_Obj_t * pObj )             { return p->pSatVars[Gia_ObjId(p->pAig,pObj)]; }
+static inline void Cec_ObjSetSatNum( Cec_ManSat_t * p, Gia_Obj_t * pObj, int Num ) { p->pSatVars[Gia_ObjId(p->pAig,pObj)] = Num;  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns value of the SAT variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ObjSatVarValue( Cec_ManSat_t * p, Gia_Obj_t * pObj )             
+{ 
+    return sat_solver_var_value( p->pSat, Cec_ObjSatNum(p, pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Addes clauses to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_AddClausesMux( Cec_ManSat_t * p, Gia_Obj_t * pNode )
+{
+    Gia_Obj_t * pNodeI, * pNodeT, * pNodeE;
+    int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE;
+
+    assert( !Gia_IsComplement( pNode ) );
+    assert( Gia_ObjIsMuxType( pNode ) );
+    // get nodes (I = if, T = then, E = else)
+    pNodeI = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE );
+    // get the variable numbers
+    VarF = Cec_ObjSatNum(p,pNode);
+    VarI = Cec_ObjSatNum(p,pNodeI);
+    VarT = Cec_ObjSatNum(p,Gia_Regular(pNodeT));
+    VarE = Cec_ObjSatNum(p,Gia_Regular(pNodeE));
+    // get the complementation flags
+    fCompT = Gia_IsComplement(pNodeT);
+    fCompE = Gia_IsComplement(pNodeE);
+
+    // f = ITE(i, t, e)
+
+    // i' + t' + f
+    // i' + t  + f'
+    // i  + e' + f
+    // i  + e  + f'
+
+    // create four clauses
+    pLits[0] = toLitCond(VarI, 1);
+    pLits[1] = toLitCond(VarT, 1^fCompT);
+    pLits[2] = toLitCond(VarF, 0);
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( pNodeI->fPhase )               pLits[0] = lit_neg( pLits[0] );
+        if ( Gia_Regular(pNodeT)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarI, 1);
+    pLits[1] = toLitCond(VarT, 0^fCompT);
+    pLits[2] = toLitCond(VarF, 1);
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( pNodeI->fPhase )               pLits[0] = lit_neg( pLits[0] );
+        if ( Gia_Regular(pNodeT)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarI, 0);
+    pLits[1] = toLitCond(VarE, 1^fCompE);
+    pLits[2] = toLitCond(VarF, 0);
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( pNodeI->fPhase )               pLits[0] = lit_neg( pLits[0] );
+        if ( Gia_Regular(pNodeE)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarI, 0);
+    pLits[1] = toLitCond(VarE, 0^fCompE);
+    pLits[2] = toLitCond(VarF, 1);
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( pNodeI->fPhase )               pLits[0] = lit_neg( pLits[0] );
+        if ( Gia_Regular(pNodeE)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+
+    // two additional clauses
+    // t' & e' -> f'
+    // t  & e  -> f 
+
+    // t  + e   + f'
+    // t' + e'  + f 
+
+    if ( VarT == VarE )
+    {
+//        assert( fCompT == !fCompE );
+        return;
+    }
+
+    pLits[0] = toLitCond(VarT, 0^fCompT);
+    pLits[1] = toLitCond(VarE, 0^fCompE);
+    pLits[2] = toLitCond(VarF, 1);
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( Gia_Regular(pNodeT)->fPhase )  pLits[0] = lit_neg( pLits[0] );
+        if ( Gia_Regular(pNodeE)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarT, 1^fCompT);
+    pLits[1] = toLitCond(VarE, 1^fCompE);
+    pLits[2] = toLitCond(VarF, 0);
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( Gia_Regular(pNodeT)->fPhase )  pLits[0] = lit_neg( pLits[0] );
+        if ( Gia_Regular(pNodeE)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Addes clauses to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_AddClausesSuper( Cec_ManSat_t * p, Gia_Obj_t * pNode, Vec_Ptr_t * vSuper )
+{
+    Gia_Obj_t * pFanin;
+    int * pLits, nLits, RetValue, i;
+    assert( !Gia_IsComplement(pNode) );
+    assert( Gia_ObjIsAnd( pNode ) );
+    // create storage for literals
+    nLits = Vec_PtrSize(vSuper) + 1;
+    pLits = ABC_ALLOC( int, nLits );
+    // suppose AND-gate is A & B = C
+    // add !A => !C   or   A + !C
+    Vec_PtrForEachEntry( Gia_Obj_t *, vSuper, pFanin, i )
+    {
+        pLits[0] = toLitCond(Cec_ObjSatNum(p,Gia_Regular(pFanin)), Gia_IsComplement(pFanin));
+        pLits[1] = toLitCond(Cec_ObjSatNum(p,pNode), 1);
+        if ( p->pPars->fPolarFlip )
+        {
+            if ( Gia_Regular(pFanin)->fPhase )  pLits[0] = lit_neg( pLits[0] );
+            if ( pNode->fPhase )                pLits[1] = lit_neg( pLits[1] );
+        }
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+    }
+    // add A & B => C   or   !A + !B + C
+    Vec_PtrForEachEntry( Gia_Obj_t *, vSuper, pFanin, i )
+    {
+        pLits[i] = toLitCond(Cec_ObjSatNum(p,Gia_Regular(pFanin)), !Gia_IsComplement(pFanin));
+        if ( p->pPars->fPolarFlip )
+        {
+            if ( Gia_Regular(pFanin)->fPhase )  pLits[i] = lit_neg( pLits[i] );
+        }
+    }
+    pLits[nLits-1] = toLitCond(Cec_ObjSatNum(p,pNode), 0);
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( pNode->fPhase )  pLits[nLits-1] = lit_neg( pLits[nLits-1] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits );
+    assert( RetValue );
+    ABC_FREE( pLits );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_CollectSuper_rec( Gia_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes )
+{
+    // if the new node is complemented or a PI, another gate begins
+    if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) || 
+         (!fFirst && Gia_ObjValue(pObj) > 1) || 
+         (fUseMuxes && Gia_ObjIsMuxType(pObj)) )
+    {
+        Vec_PtrPushUnique( vSuper, pObj );
+        return;
+    }
+    // go through the branches
+    Cec_CollectSuper_rec( Gia_ObjChild0(pObj), vSuper, 0, fUseMuxes );
+    Cec_CollectSuper_rec( Gia_ObjChild1(pObj), vSuper, 0, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_CollectSuper( Gia_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper )
+{
+    assert( !Gia_IsComplement(pObj) );
+    assert( !Gia_ObjIsCi(pObj) );
+    Vec_PtrClear( vSuper );
+    Cec_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the solver clause database.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ObjAddToFrontier( Cec_ManSat_t * p, Gia_Obj_t * pObj, Vec_Ptr_t * vFrontier )
+{
+    assert( !Gia_IsComplement(pObj) );
+    if ( Cec_ObjSatNum(p,pObj) )
+        return;
+    assert( Cec_ObjSatNum(p,pObj) == 0 );
+    if ( Gia_ObjIsConst0(pObj) )
+        return;
+    Vec_PtrPush( p->vUsedNodes, pObj );
+    Cec_ObjSetSatNum( p, pObj, p->nSatVars++ );
+    if ( Gia_ObjIsAnd(pObj) )
+        Vec_PtrPush( vFrontier, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the solver clause database.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_CnfNodeAddToSolver( Cec_ManSat_t * p, Gia_Obj_t * pObj )
+{ 
+    Vec_Ptr_t * vFrontier;
+    Gia_Obj_t * pNode, * pFanin;
+    int i, k, fUseMuxes = 1;
+    // quit if CNF is ready
+    if ( Cec_ObjSatNum(p,pObj) )
+        return;
+    if ( Gia_ObjIsCi(pObj) )
+    {
+        Vec_PtrPush( p->vUsedNodes, pObj );
+        Cec_ObjSetSatNum( p, pObj, p->nSatVars++ );
+        sat_solver_setnvars( p->pSat, p->nSatVars );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    // start the frontier
+    vFrontier = Vec_PtrAlloc( 100 );
+    Cec_ObjAddToFrontier( p, pObj, vFrontier );
+    // explore nodes in the frontier
+    Vec_PtrForEachEntry( Gia_Obj_t *, vFrontier, pNode, i )
+    {
+        // create the supergate
+        assert( Cec_ObjSatNum(p,pNode) );
+        if ( fUseMuxes && Gia_ObjIsMuxType(pNode) )
+        {
+            Vec_PtrClear( p->vFanins );
+            Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin0( Gia_ObjFanin0(pNode) ) );
+            Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin0( Gia_ObjFanin1(pNode) ) );
+            Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin1( Gia_ObjFanin0(pNode) ) );
+            Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin1( Gia_ObjFanin1(pNode) ) );
+            Vec_PtrForEachEntry( Gia_Obj_t *, p->vFanins, pFanin, k )
+                Cec_ObjAddToFrontier( p, Gia_Regular(pFanin), vFrontier );
+            Cec_AddClausesMux( p, pNode );
+        }
+        else
+        {
+            Cec_CollectSuper( pNode, fUseMuxes, p->vFanins );
+            Vec_PtrForEachEntry( Gia_Obj_t *, p->vFanins, pFanin, k )
+                Cec_ObjAddToFrontier( p, Gia_Regular(pFanin), vFrontier );
+            Cec_AddClausesSuper( p, pNode, p->vFanins );
+        }
+        assert( Vec_PtrSize(p->vFanins) > 1 );
+    }
+    Vec_PtrFree( vFrontier );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSatSolverRecycle( Cec_ManSat_t * p )
+{
+    int Lit;
+    if ( p->pSat )
+    {
+        Gia_Obj_t * pObj;
+        int i;
+        Vec_PtrForEachEntry( Gia_Obj_t *, p->vUsedNodes, pObj, i )
+            Cec_ObjSetSatNum( p, pObj, 0 );
+        Vec_PtrClear( p->vUsedNodes );
+//        memset( p->pSatVars, 0, sizeof(int) * Gia_ManObjNumMax(p->pAigTotal) );
+        sat_solver_delete( p->pSat );
+    }
+    p->pSat = sat_solver_new();
+    sat_solver_setnvars( p->pSat, 1000 );
+    p->pSat->factors = ABC_CALLOC( double, p->pSat->cap );
+    // var 0 is not used
+    // var 1 is reserved for const0 node - add the clause
+    p->nSatVars = 1;
+//    p->nSatVars = 0;
+    Lit = toLitCond( p->nSatVars, 1 );
+//    if ( p->pPars->fPolarFlip ) // no need to normalize const0 node (bug fix by SS on 9/17/2012)
+//        Lit = lit_neg( Lit );
+    sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+    Cec_ObjSetSatNum( p, Gia_ManConst0(p->pAig), p->nSatVars++ );
+
+    p->nRecycles++;
+    p->nCallsSince = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets variable activities in the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_SetActivityFactors_rec( Cec_ManSat_t * p, Gia_Obj_t * pObj, int LevelMin, int LevelMax )
+{
+    float dActConeBumpMax = 20.0;
+    int iVar;
+    // skip visited variables
+    if ( Gia_ObjIsTravIdCurrent(p->pAig, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p->pAig, pObj);
+    // add the PI to the list
+    if ( Gia_ObjLevel(p->pAig, pObj) <= LevelMin || Gia_ObjIsCi(pObj) )
+        return;
+    // set the factor of this variable
+    // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pPars->dActConeBumpMax / ThisBump
+    if ( (iVar = Cec_ObjSatNum(p,pObj)) )
+    {
+        p->pSat->factors[iVar] = dActConeBumpMax * (Gia_ObjLevel(p->pAig, pObj) - LevelMin)/(LevelMax - LevelMin);
+        veci_push(&p->pSat->act_vars, iVar);
+    }
+    // explore the fanins
+    Cec_SetActivityFactors_rec( p, Gia_ObjFanin0(pObj), LevelMin, LevelMax );
+    Cec_SetActivityFactors_rec( p, Gia_ObjFanin1(pObj), LevelMin, LevelMax );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets variable activities in the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_SetActivityFactors( Cec_ManSat_t * p, Gia_Obj_t * pObj )
+{
+    float dActConeRatio = 0.5;
+    int LevelMin, LevelMax;
+    // reset the active variables
+    veci_resize(&p->pSat->act_vars, 0);
+    // prepare for traversal
+    Gia_ManIncrementTravId( p->pAig );
+    // determine the min and max level to visit
+    assert( dActConeRatio > 0 && dActConeRatio < 1 );
+    LevelMax = Gia_ObjLevel(p->pAig,pObj);
+    LevelMin = (int)(LevelMax * (1.0 - dActConeRatio));
+    // traverse
+    Cec_SetActivityFactors_rec( p, pObj, LevelMin, LevelMax );
+//Cec_PrintActivity( p );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Runs equivalence test for the two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSatCheckNode( Cec_ManSat_t * p, Gia_Obj_t * pObj )
+{
+    Gia_Obj_t * pObjR = Gia_Regular(pObj);
+    int nBTLimit = p->pPars->nBTLimit;
+    int Lit, RetValue, status, nConflicts;
+    abctime clk, clk2;
+
+    if ( pObj == Gia_ManConst0(p->pAig) )
+        return 1;
+    if ( pObj == Gia_ManConst1(p->pAig) )
+    {
+        assert( 0 );
+        return 0;
+    }
+
+    p->nCallsSince++;  // experiment with this!!!
+    p->nSatTotal++;
+    
+    // check if SAT solver needs recycling
+    if ( p->pSat == NULL || 
+        (p->pPars->nSatVarMax && 
+         p->nSatVars > p->pPars->nSatVarMax && 
+         p->nCallsSince > p->pPars->nCallsRecycle) )
+        Cec_ManSatSolverRecycle( p );
+
+    // if the nodes do not have SAT variables, allocate them
+clk2 = Abc_Clock();
+    Cec_CnfNodeAddToSolver( p, pObjR );
+//ABC_PRT( "cnf", Abc_Clock() - clk2 );
+//Abc_Print( 1, "%d \n", p->pSat->size );
+
+clk2 = Abc_Clock();
+//    Cec_SetActivityFactors( p, pObjR ); 
+//ABC_PRT( "act", Abc_Clock() - clk2 );
+
+    // propage unit clauses
+    if ( p->pSat->qtail != p->pSat->qhead )
+    {
+        status = sat_solver_simplify(p->pSat);
+        assert( status != 0 );
+        assert( p->pSat->qtail == p->pSat->qhead );
+    }
+
+    // solve under assumptions
+    // A = 1; B = 0     OR     A = 1; B = 1 
+    Lit = toLitCond( Cec_ObjSatNum(p,pObjR), Gia_IsComplement(pObj) );
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( pObjR->fPhase )  Lit = lit_neg( Lit );
+    }
+//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
+clk = Abc_Clock();
+    nConflicts = p->pSat->stats.conflicts;
+
+clk2 = Abc_Clock();
+    RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, 
+        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+//ABC_PRT( "sat", Abc_Clock() - clk2 );
+
+    if ( RetValue == l_False )
+    {
+p->timeSatUnsat += Abc_Clock() - clk;
+        Lit = lit_neg( Lit );
+        RetValue = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+        assert( RetValue );
+        p->nSatUnsat++;
+        p->nConfUnsat += p->pSat->stats.conflicts - nConflicts;       
+//Abc_Print( 1, "UNSAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts );
+        return 1;
+    }
+    else if ( RetValue == l_True )
+    {
+p->timeSatSat += Abc_Clock() - clk;
+        p->nSatSat++;
+        p->nConfSat += p->pSat->stats.conflicts - nConflicts;
+//Abc_Print( 1, "SAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts );
+        return 0;
+    }
+    else // if ( RetValue == l_Undef )
+    {
+p->timeSatUndec += Abc_Clock() - clk;
+        p->nSatUndec++;
+        p->nConfUndec += p->pSat->stats.conflicts - nConflicts;
+//Abc_Print( 1, "UNDEC after %d conflicts\n", p->pSat->stats.conflicts - nConflicts );
+        return -1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Runs equivalence test for the two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManSatCheckNodeTwo( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 )
+{
+    Gia_Obj_t * pObjR1 = Gia_Regular(pObj1);
+    Gia_Obj_t * pObjR2 = Gia_Regular(pObj2);
+    int nBTLimit = p->pPars->nBTLimit;
+    int Lits[2], RetValue, status, nConflicts;
+    abctime clk, clk2;
+
+    if ( pObj1 == Gia_ManConst0(p->pAig) || pObj2 == Gia_ManConst0(p->pAig) || pObj1 == Gia_Not(pObj2) )
+        return 1;
+    if ( pObj1 == Gia_ManConst1(p->pAig) && (pObj2 == NULL || pObj2 == Gia_ManConst1(p->pAig)) )
+    {
+        assert( 0 );
+        return 0;
+    }
+
+    p->nCallsSince++;  // experiment with this!!!
+    p->nSatTotal++;
+    
+    // check if SAT solver needs recycling
+    if ( p->pSat == NULL || 
+        (p->pPars->nSatVarMax && 
+         p->nSatVars > p->pPars->nSatVarMax && 
+         p->nCallsSince > p->pPars->nCallsRecycle) )
+        Cec_ManSatSolverRecycle( p );
+
+    // if the nodes do not have SAT variables, allocate them
+clk2 = Abc_Clock();
+    Cec_CnfNodeAddToSolver( p, pObjR1 );
+    Cec_CnfNodeAddToSolver( p, pObjR2 );
+//ABC_PRT( "cnf", Abc_Clock() - clk2 );
+//Abc_Print( 1, "%d \n", p->pSat->size );
+
+clk2 = Abc_Clock();
+//    Cec_SetActivityFactors( p, pObjR1 ); 
+//    Cec_SetActivityFactors( p, pObjR2 ); 
+//ABC_PRT( "act", Abc_Clock() - clk2 );
+
+    // propage unit clauses
+    if ( p->pSat->qtail != p->pSat->qhead )
+    {
+        status = sat_solver_simplify(p->pSat);
+        assert( status != 0 );
+        assert( p->pSat->qtail == p->pSat->qhead );
+    }
+
+    // solve under assumptions
+    // A = 1; B = 0     OR     A = 1; B = 1 
+    Lits[0] = toLitCond( Cec_ObjSatNum(p,pObjR1), Gia_IsComplement(pObj1) );
+    Lits[1] = toLitCond( Cec_ObjSatNum(p,pObjR2), Gia_IsComplement(pObj2) );
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( pObjR1->fPhase )  Lits[0] = lit_neg( Lits[0] );
+        if ( pObjR2->fPhase )  Lits[1] = lit_neg( Lits[1] );
+    }
+//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
+clk = Abc_Clock();
+    nConflicts = p->pSat->stats.conflicts;
+
+clk2 = Abc_Clock();
+    RetValue = sat_solver_solve( p->pSat, Lits, Lits + 2, 
+        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+//ABC_PRT( "sat", Abc_Clock() - clk2 );
+
+    if ( RetValue == l_False )
+    {
+p->timeSatUnsat += Abc_Clock() - clk;
+        Lits[0] = lit_neg( Lits[0] );
+        Lits[1] = lit_neg( Lits[1] );
+        RetValue = sat_solver_addclause( p->pSat, Lits, Lits + 2 );
+        assert( RetValue );
+        p->nSatUnsat++;
+        p->nConfUnsat += p->pSat->stats.conflicts - nConflicts;       
+//Abc_Print( 1, "UNSAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts );
+        return 1;
+    }
+    else if ( RetValue == l_True )
+    {
+p->timeSatSat += Abc_Clock() - clk;
+        p->nSatSat++;
+        p->nConfSat += p->pSat->stats.conflicts - nConflicts;
+//Abc_Print( 1, "SAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts );
+        return 0;
+    }
+    else // if ( RetValue == l_Undef )
+    {
+p->timeSatUndec += Abc_Clock() - clk;
+        p->nSatUndec++;
+        p->nConfUndec += p->pSat->stats.conflicts - nConflicts;
+//Abc_Print( 1, "UNDEC after %d conflicts\n", p->pSat->stats.conflicts - nConflicts );
+        return -1;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one round of solving for the POs of the AIG.]
+
+  Description [Labels the nodes that have been proved (pObj->fMark1) 
+  and returns the set of satisfying assignments.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars )
+{
+    Bar_Progress_t * pProgress = NULL;
+    Cec_ManSat_t * p;
+    Gia_Obj_t * pObj;
+    int i, status;
+    abctime clk = Abc_Clock(), clk2;
+    // reset the manager
+    if ( pPat )
+    {
+        pPat->iStart = Vec_StrSize(pPat->vStorage);
+        pPat->nPats = 0;
+        pPat->nPatLits = 0;
+        pPat->nPatLitsMin = 0;
+    } 
+    Gia_ManSetPhase( pAig );
+    Gia_ManLevelNum( pAig );
+    Gia_ManIncrementTravId( pAig );
+    p = Cec_ManSatCreate( pAig, pPars );
+    pProgress = Bar_ProgressStart( stdout, Gia_ManPoNum(pAig) );
+    Gia_ManForEachCo( pAig, pObj, i )
+    {
+        if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) )
+        {
+            pObj->fMark0 = 0;
+            pObj->fMark1 = 1;
+            continue;
+        }
+        Bar_ProgressUpdate( pProgress, i, "SAT..." );
+clk2 = Abc_Clock();
+        status = Cec_ManSatCheckNode( p, Gia_ObjChild0(pObj) );
+        pObj->fMark0 = (status == 0);
+        pObj->fMark1 = (status == 1);
+/*
+        if ( status == -1 )
+        {
+            Gia_Man_t * pTemp = Gia_ManDupDfsCone( pAig, pObj );
+            Gia_AigerWrite( pTemp, "gia_hard.aig", 0, 0 );
+            Gia_ManStop( pTemp );
+            Abc_Print( 1, "Dumping hard cone into file \"%s\".\n", "gia_hard.aig" );
+        }
+*/
+        if ( status != 0 )
+            continue;
+        // save the pattern
+        if ( pPat )
+        {
+            abctime clk3 = Abc_Clock();
+            Cec_ManPatSavePattern( pPat, p, pObj );
+            pPat->timeTotalSave += Abc_Clock() - clk3;
+        }
+        // quit if one of them is solved
+        if ( pPars->fCheckMiter )
+            break;
+    }
+    p->timeTotal = Abc_Clock() - clk;
+    Bar_ProgressStop( pProgress );
+    if ( pPars->fVerbose )
+        Cec_ManSatPrintStats( p );
+    Cec_ManSatStop( p );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the pattern stored.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Cec_ManSatReadCex( Cec_ManSat_t * pSat )
+{
+    return pSat->vCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Save values in the cone of influence.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSatSolveSeq_rec( Cec_ManSat_t * pSat, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Ptr_t * vInfo, int iPat, int nRegs )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+    {
+        unsigned * pInfo = (unsigned *)Vec_PtrEntry( vInfo, nRegs + Gia_ObjCioId(pObj) );
+        if ( Cec_ObjSatVarValue( pSat, pObj ) != Abc_InfoHasBit( pInfo, iPat ) )
+            Abc_InfoXorBit( pInfo, iPat );
+        pSat->nCexLits++;
+//        Vec_IntPush( pSat->vCex, Abc_Var2Lit( Gia_ObjCioId(pObj), !Cec_ObjSatVarValue(pSat, pObj) ) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Cec_ManSatSolveSeq_rec( pSat, p, Gia_ObjFanin0(pObj), vInfo, iPat, nRegs );
+    Cec_ManSatSolveSeq_rec( pSat, p, Gia_ObjFanin1(pObj), vInfo, iPat, nRegs );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one round of solving for the POs of the AIG.]
+
+  Description [Labels the nodes that have been proved (pObj->fMark1) 
+  and returns the set of satisfying assignments.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Cec_ManSatSolveSeq( Vec_Ptr_t * vPatts, Gia_Man_t * pAig, Cec_ParSat_t * pPars, int nRegs, int * pnPats )
+{
+    Bar_Progress_t * pProgress = NULL;
+    Vec_Str_t * vStatus;
+    Cec_ManSat_t * p;
+    Gia_Obj_t * pObj;
+    int iPat = 0, nPatsInit, nPats;
+    int i, status;
+    abctime clk = Abc_Clock();
+    nPatsInit = nPats = 32 * Vec_PtrReadWordsSimInfo(vPatts);
+    Gia_ManSetPhase( pAig );
+    Gia_ManLevelNum( pAig );
+    Gia_ManIncrementTravId( pAig );
+    p = Cec_ManSatCreate( pAig, pPars );
+    vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) );
+    pProgress = Bar_ProgressStart( stdout, Gia_ManPoNum(pAig) );
+    Gia_ManForEachCo( pAig, pObj, i )
+    {
+        Bar_ProgressUpdate( pProgress, i, "SAT..." );
+        if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) )
+        {
+            if ( Gia_ObjFaninC0(pObj) )
+            {
+//                Abc_Print( 1, "Constant 1 output of SRM!!!\n" );
+                Vec_StrPush( vStatus, 0 );
+            }
+            else
+            {
+//                Abc_Print( 1, "Constant 0 output of SRM!!!\n" );
+                Vec_StrPush( vStatus, 1 );
+            }
+            continue;
+        }
+        status = Cec_ManSatCheckNode( p, Gia_ObjChild0(pObj) );
+//Abc_Print( 1, "output %d   status = %d\n", i, status );
+        Vec_StrPush( vStatus, (char)status );
+        if ( status != 0 )
+            continue;
+        // resize storage
+        if ( iPat == nPats )
+        {
+            int nWords = Vec_PtrReadWordsSimInfo(vPatts);
+            Vec_PtrReallocSimInfo( vPatts );
+            Vec_PtrCleanSimInfo( vPatts, nWords, 2*nWords );
+            nPats = 32 * Vec_PtrReadWordsSimInfo(vPatts);
+        }
+        if ( iPat % nPatsInit == 0 )
+            iPat++;
+        // save the pattern
+        Gia_ManIncrementTravId( pAig );
+//        Vec_IntClear( p->vCex );
+        Cec_ManSatSolveSeq_rec( p, pAig, Gia_ObjFanin0(pObj), vPatts, iPat++, nRegs );
+//        Gia_SatVerifyPattern( pAig, pObj, p->vCex, p->vVisits );
+//        Cec_ManSatAddToStore( p->vCexStore, p->vCex );
+//        if ( iPat == nPats )
+//            break;
+        // quit if one of them is solved
+//        if ( pPars->fFirstStop )
+//            break;
+//        if ( iPat == 32 * 15 * 16 - 1 )
+//            break;
+    }
+    p->timeTotal = Abc_Clock() - clk;
+    Bar_ProgressStop( pProgress );
+    if ( pPars->fVerbose )
+        Cec_ManSatPrintStats( p );
+//    Abc_Print( 1, "Total number of cex literals = %d. (Ave = %d)\n", p->nCexLits, p->nCexLits/p->nSatSat );
+    Cec_ManSatStop( p );
+    if ( pnPats )
+        *pnPats = iPat-1;
+    return vStatus;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Save values in the cone of influence.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out )
+{
+    int i, Entry;
+    Vec_IntPush( vCexStore, Out );
+    if ( vCex == NULL ) // timeout
+    {
+        Vec_IntPush( vCexStore, -1 );
+        return;
+    }
+    // write the counter-example
+    Vec_IntPush( vCexStore, Vec_IntSize(vCex) );
+    Vec_IntForEachEntry( vCex, Entry, i )
+        Vec_IntPush( vCexStore, Entry );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Save values in the cone of influence.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSatSolveMiter_rec( Cec_ManSat_t * pSat, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+    {
+        pSat->nCexLits++;
+        Vec_IntPush( pSat->vCex, Abc_Var2Lit( Gia_ObjCioId(pObj), !Cec_ObjSatVarValue(pSat, pObj) ) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Cec_ManSatSolveMiter_rec( pSat, p, Gia_ObjFanin0(pObj) );
+    Cec_ManSatSolveMiter_rec( pSat, p, Gia_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Save patterns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManSavePattern( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 )
+{
+    Vec_IntClear( p->vCex );
+    Gia_ManIncrementTravId( p->pAig );
+    Cec_ManSatSolveMiter_rec( p, p->pAig, Gia_Regular(pObj1) );
+    if ( pObj2 )
+    Cec_ManSatSolveMiter_rec( p, p->pAig, Gia_Regular(pObj2) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one round of solving for the POs of the AIG.]
+
+  Description [Labels the nodes that have been proved (pObj->fMark1) 
+  and returns the set of satisfying assignments.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Str_t ** pvStatus )
+{
+    Bar_Progress_t * pProgress = NULL;
+    Vec_Int_t * vCexStore;
+    Vec_Str_t * vStatus;
+    Cec_ManSat_t * p;
+    Gia_Obj_t * pObj;
+    int i, status;
+    abctime clk = Abc_Clock();
+    // prepare AIG
+    Gia_ManSetPhase( pAig );
+    Gia_ManLevelNum( pAig );
+    Gia_ManIncrementTravId( pAig );
+    // create resulting data-structures
+    vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) );
+    vCexStore = Vec_IntAlloc( 10000 );
+    // perform solving
+    p = Cec_ManSatCreate( pAig, pPars );
+    pProgress = Bar_ProgressStart( stdout, Gia_ManPoNum(pAig) );
+    Gia_ManForEachCo( pAig, pObj, i )
+    {
+        Vec_IntClear( p->vCex );
+        Bar_ProgressUpdate( pProgress, i, "SAT..." );
+        if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) )
+        {
+            if ( Gia_ObjFaninC0(pObj) )
+            {
+//                Abc_Print( 1, "Constant 1 output of SRM!!!\n" );
+                Cec_ManSatAddToStore( vCexStore, p->vCex, i ); // trivial counter-example
+                Vec_StrPush( vStatus, 0 );
+            }
+            else
+            {
+//                Abc_Print( 1, "Constant 0 output of SRM!!!\n" );
+                Vec_StrPush( vStatus, 1 );
+            }
+            continue;
+        }
+        status = Cec_ManSatCheckNode( p, Gia_ObjChild0(pObj) );
+        Vec_StrPush( vStatus, (char)status );
+        if ( status == -1 )
+        {
+            Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout
+            continue;
+        }
+        if ( status == 1 )
+            continue;
+        assert( status == 0 );
+        // save the pattern
+//        Gia_ManIncrementTravId( pAig );
+//        Cec_ManSatSolveMiter_rec( p, pAig, Gia_ObjFanin0(pObj) );
+        Cec_ManSavePattern( p, Gia_ObjFanin0(pObj), NULL );
+//        Gia_SatVerifyPattern( pAig, pObj, p->vCex, p->vVisits );
+        Cec_ManSatAddToStore( vCexStore, p->vCex, i );
+    }
+    p->timeTotal = Abc_Clock() - clk;
+    Bar_ProgressStop( pProgress );
+//    if ( pPars->fVerbose )
+//        Cec_ManSatPrintStats( p );
+    Cec_ManSatStop( p );
+    *pvStatus = vStatus;
+    return vCexStore;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/cec/cecSplit.c b/abc-build/src/proof/cec/cecSplit.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/cecSplit.c
@@ -0,0 +1,834 @@
+/**CFile****************************************************************
+
+  FileName    [cecSplit.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Combinational equivalence checking.]
+
+  Synopsis    [Cofactoring for combinational miters.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cecSplit.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <math.h>
+#include "aig/gia/gia.h"
+#include "aig/gia/giaAig.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver.h"
+#include "misc/util/utilTruth.h"
+//#include "bdd/cudd/cuddInt.h"
+
+#ifdef ABC_USE_PTHREADS
+
+#ifdef _WIN32
+#include "../lib/pthread.h"
+#else
+#include <pthread.h>
+#include <unistd.h>
+#endif
+
+#endif
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+#if 0 // BDD code
+
+/**Function*************************************************************
+
+  Synopsis    [Permute primary inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdManager * Gia_ManBuildBdd( Gia_Man_t * p, Vec_Ptr_t ** pvNodes, int nSkip )
+{
+    abctime clk = Abc_Clock();
+    DdManager * dd;
+    DdNode * bBdd, * bBdd0, * bBdd1;
+    Vec_Ptr_t * vNodes;
+    Gia_Obj_t * pObj;
+    int i;
+    vNodes = Vec_PtrStart( Gia_ManObjNum(p) );
+    dd = Cudd_Init( Gia_ManPiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+//    Cudd_AutodynEnable( dd,  CUDD_REORDER_SYMM_SIFT );
+    bBdd = Cudd_ReadLogicZero(dd); Cudd_Ref( bBdd );
+    Vec_PtrWriteEntry( vNodes, 0, bBdd );  
+    Gia_ManForEachPi( p, pObj, i )
+    {
+        bBdd = i > nSkip ? Cudd_bddIthVar(dd, i) : Cudd_ReadLogicZero(dd); Cudd_Ref( bBdd );
+        Vec_PtrWriteEntry( vNodes, Gia_ObjId(p, pObj), bBdd );
+    }
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        bBdd0 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(vNodes, Gia_ObjFaninId0(pObj, i)), Gia_ObjFaninC0(pObj) );
+        bBdd1 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(vNodes, Gia_ObjFaninId1(pObj, i)), Gia_ObjFaninC1(pObj) );
+        bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd );
+        Vec_PtrWriteEntry( vNodes, Gia_ObjId(p, pObj), bBdd );
+        if ( i % 10 == 0 )
+            printf( "%d ", i );
+//        if ( i == 3000 )
+//            break;
+    }
+    printf( "\n" );
+    Gia_ManForEachPo( p, pObj, i )
+    {
+        bBdd = Cudd_NotCond( (DdNode *)Vec_PtrEntry(vNodes, Gia_ObjFaninId0(pObj, Gia_ObjId(p, pObj))), Gia_ObjFaninC0(pObj) );  Cudd_Ref( bBdd );
+        Vec_PtrWriteEntry( vNodes, Gia_ObjId(p, pObj), bBdd );
+    }
+    if ( bBdd == Cudd_ReadLogicZero(dd) )
+        printf( "Equivalent!\n" );
+    else
+        printf( "Not tquivalent!\n" );
+    if ( pvNodes )
+        *pvNodes = vNodes;
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return dd;
+}
+void Gia_ManDerefBdd( DdManager * dd, Vec_Ptr_t * vNodes )
+{
+    DdNode * bBdd;
+    int i;
+    Vec_PtrForEachEntry( DdNode *, vNodes, bBdd, i )
+        if ( bBdd )
+            Cudd_RecursiveDeref( dd, bBdd );
+    if ( Cudd_CheckZeroRef(dd) > 0 )
+        printf( "The number of referenced nodes = %d\n", Cudd_CheckZeroRef(dd) );
+    Cudd_PrintInfo( dd, stdout );
+    Cudd_Quit( dd );
+}
+void Gia_ManBuildBddTest( Gia_Man_t * p )
+{
+    Vec_Ptr_t * vNodes;
+    DdManager * dd = Gia_ManBuildBdd( p, &vNodes, 50 );
+    Gia_ManDerefBdd( dd, vNodes );
+}
+
+#endif // BDD code
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_GiaSplitExplore( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj, * pFan0, * pFan1;
+    int i, Counter = 0;
+    assert( p->pMuxes == NULL );
+    ABC_FREE( p->pRefs );
+    Gia_ManCreateRefs( p ); 
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        if ( !Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) )
+            continue;
+        if ( Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) > 1 && 
+             Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) > 1 )
+             continue;
+        printf( "%5d : ", Counter++ );
+        printf( "%2d %2d    ", Gia_ObjRefNum(p, Gia_Regular(pFan0)),  Gia_ObjRefNum(p, Gia_Regular(pFan1)) );
+        printf( "%2d %2d  \n", Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)), Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find cofactoring variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Gia_PermuteSpecialOrder( Gia_Man_t * p )
+{
+    Vec_Int_t * vPerm;
+    Gia_Obj_t * pObj;
+    int i, * pOrder;
+    Gia_ManCreateRefs( p );
+    vPerm = Vec_IntAlloc( Gia_ManPiNum(p) );
+    Gia_ManForEachPi( p, pObj, i )
+        Vec_IntPush( vPerm, Gia_ObjRefNum(p, pObj) );
+    pOrder = Abc_QuickSortCost( Vec_IntArray(vPerm), Vec_IntSize(vPerm), 1 );
+    Vec_IntFree( vPerm );
+    return pOrder;
+}
+Gia_Man_t * Gia_PermuteSpecial( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Vec_Int_t * vPerm;
+    int * pOrder = Gia_PermuteSpecialOrder( p );
+    vPerm = Vec_IntAllocArray( pOrder, Gia_ManPiNum(p) );
+    pNew = Gia_ManDupPerm( p, vPerm );
+    Vec_IntFree( vPerm );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find cofactoring variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_SplitCofVar2( Gia_Man_t * p, int * pnFanouts, int * pnCost )
+{
+    Gia_Obj_t * pObj;
+    int i, iBest = -1, CostBest = -1;
+    if ( p->pRefs == NULL )
+        Gia_ManCreateRefs( p );
+    Gia_ManForEachPi( p, pObj, i )
+        if ( CostBest < Gia_ObjRefNum(p, pObj) )
+            iBest = i, CostBest = Gia_ObjRefNum(p, pObj);
+    assert( iBest >= 0 );
+    *pnFanouts = Gia_ObjRefNum(p, Gia_ManPi(p, iBest));
+    *pnCost = -1;
+    return iBest;
+}
+int Gia_SplitCofVar( Gia_Man_t * p, int LookAhead, int * pnFanouts, int * pnCost )
+{
+    Gia_Man_t * pPart;
+    int Cost0, Cost1, CostBest = ABC_INFINITY;
+    int * pOrder, i, iBest = -1;
+    if ( LookAhead == 1 )
+        return Gia_SplitCofVar2( p, pnFanouts, pnCost );
+    pOrder = Gia_PermuteSpecialOrder( p );
+    LookAhead = Abc_MinInt( LookAhead, Gia_ManPiNum(p) );
+    for ( i = 0; i < LookAhead; i++ )
+    {
+        pPart = Gia_ManDupCofactorVar( p, pOrder[i], 0 );
+        Cost0 = Gia_ManAndNum(pPart);
+        Gia_ManStop( pPart );
+
+        pPart = Gia_ManDupCofactorVar( p, pOrder[i], 1 );
+        Cost1 = Gia_ManAndNum(pPart);
+        Gia_ManStop( pPart );
+
+        if ( CostBest > Cost0 + Cost1 )
+            CostBest = Cost0 + Cost1, iBest = pOrder[i];
+
+/*
+        pPart = Gia_ManDupExist( p, pOrder[i] );
+        printf( "%2d : Var = %4d  Refs = %3d  %6d %6d -> %6d    %6d -> %6d\n", 
+            i, pOrder[i], Gia_ObjRefNum(p, Gia_ManPi(p, pOrder[i])), 
+            Cost0, Cost1, Cost0+Cost1, Gia_ManAndNum(p), Gia_ManAndNum(pPart) );
+        Gia_ManStop( pPart );
+
+        printf( "%2d : Var = %4d  Refs = %3d  %6d %6d -> %6d\n", 
+            i, pOrder[i], Gia_ObjRefNum(p, Gia_ManPi(p, pOrder[i])), 
+            Cost0, Cost1, Cost0+Cost1 );
+*/
+    }
+    ABC_FREE( pOrder );
+    assert( iBest >= 0 );
+    *pnFanouts = Gia_ObjRefNum(p, Gia_ManPi(p, iBest));
+    *pnCost = CostBest;
+    return iBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Cec_SplitDeriveModel( Gia_Man_t * p, Cnf_Dat_t * pCnf, sat_solver * pSat )
+{
+    Abc_Cex_t * pCex;
+    Gia_Obj_t * pObj;
+    int i, iLit, * pModel;
+    pModel = ABC_CALLOC( int, Gia_ManPiNum(p) );
+    Gia_ManForEachPi( p, pObj, i )
+        pModel[i] = sat_solver_var_value(pSat, pCnf->pVarNums[Gia_ObjId(p, pObj)]);
+    if ( p->vCofVars )
+        Vec_IntForEachEntry( p->vCofVars, iLit, i )
+            pModel[Abc_Lit2Var(iLit)] = !Abc_LitIsCompl(iLit);
+    pCex = Abc_CexCreate( 0, Gia_ManPiNum(p), pModel, 0, 0, 0 );
+    ABC_FREE( pModel );
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Cnf_Dat_t * Cec_GiaDeriveGiaRemapped( Gia_Man_t * p )
+{
+    Cnf_Dat_t * pCnf;
+    Aig_Man_t * pAig = Gia_ManToAigSimple( p );
+    pAig->nRegs = 0;
+    pCnf = Cnf_Derive( pAig, 0 );//Aig_ManCoNum(pAig) );
+    Aig_ManStop( pAig );
+    return pCnf;
+}
+static inline sat_solver * Cec_GiaDeriveSolver( Gia_Man_t * p, Cnf_Dat_t * pCnf, int nTimeOut )
+{
+    sat_solver * pSat;
+    int i;
+    pSat = sat_solver_new();
+    sat_solver_setnvars( pSat, pCnf->nVars );
+    for ( i = 0; i < pCnf->nClauses; i++ )
+        if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
+        {
+            // the problem is UNSAT
+            sat_solver_delete( pSat );
+            return NULL;
+        }
+    sat_solver_set_runtime_limit( pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 );
+    return pSat;
+}
+static inline int Cnf_GiaSolveOne( Gia_Man_t * p, Cnf_Dat_t * pCnf, int nTimeOut, int * pnVars, int * pnConfs )
+{
+    int status;
+    sat_solver * pSat = Cec_GiaDeriveSolver( p, pCnf, nTimeOut );
+    if ( pSat == NULL )
+    {
+        *pnVars = 0;
+        *pnConfs = 0;
+        return 1;
+    }
+    status   = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    *pnVars  = sat_solver_nvars( pSat );
+    *pnConfs = sat_solver_nconflicts( pSat );
+    if ( status == l_True )
+        p->pCexComb = Cec_SplitDeriveModel( p, pCnf, pSat );
+    sat_solver_delete( pSat );
+    if ( status == l_Undef )
+        return -1;
+    if ( status == l_False )
+        return 1;
+    return 0;
+}
+static inline void Cec_GiaSplitClean( Vec_Ptr_t * vStack )
+{
+    Gia_Man_t * pNew;
+    int i;
+    Vec_PtrForEachEntry( Gia_Man_t *, vStack, pNew, i )
+        Gia_ManStop( pNew );
+    Vec_PtrFree( vStack );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_GiaSplitPrint( int nIter, int Depth, int nVars, int nConfs, int fStatus, double Prog, abctime clk )
+{
+    printf( "%4d : ",             nIter );
+    printf( "Depth =%3d  ",       Depth );
+    printf( "SatVar =%7d  ",      nVars );
+    printf( "SatConf =%7d   ",    nConfs );
+    printf( "%s   ",              fStatus ? (fStatus == 1 ? "UNSAT    " : "UNDECIDED") : "SAT      " );
+    printf( "Solved %8.4f %%   ", 100*Prog );
+    Abc_PrintTime( 1, "Time", clk );
+    //ABC_PRTr( "Time", Abc_Clock()-clk );
+    fflush( stdout );
+}
+void Cec_GiaSplitPrintRefs( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    if ( p->pRefs == NULL )
+        Gia_ManCreateRefs( p ); 
+    Gia_ManForEachPi( p, pObj, i )
+        printf( "%d ", Gia_ObjRefNum(p, pObj) );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_GiaSplitTest2( Gia_Man_t * p, int nProcs, int nTimeOut, int nIterMax, int LookAhead, int fVerbose, int fVeryVerbose )
+{
+    abctime clkTotal = Abc_Clock();
+    Vec_Ptr_t * vStack;
+    Cnf_Dat_t * pCnf;
+    int nSatVars, nSatConfs;
+    int nIter, status, RetValue = -1;
+    double Progress = 0;
+    // check the problem
+    pCnf = Cec_GiaDeriveGiaRemapped( p );
+    status = Cnf_GiaSolveOne( p, pCnf, nTimeOut, &nSatVars, &nSatConfs );
+    Cnf_DataFree( pCnf );
+    if ( fVerbose )
+        Cec_GiaSplitPrint( 0, 0, nSatVars, nSatConfs, status, Progress, Abc_Clock() - clkTotal );
+    if ( status == 0 )
+    {
+        printf( "The problem is SAT without cofactoring.\n" );
+        return 0;
+    }
+    if ( status == 1 )
+    {
+        printf( "The problem is UNSAT without cofactoring.\n" );
+        return 1;
+    }
+    assert( status == -1 );
+    // create local copy
+    vStack = Vec_PtrAlloc( 1000 );
+    Vec_PtrPush( vStack, Gia_ManDup(p) );
+    // start with the current problem
+    for ( nIter = 1; Vec_PtrSize(vStack) > 0; nIter++ )
+    {
+        // get the last AIG
+        Gia_Man_t * pLast = (Gia_Man_t *)Vec_PtrPop( vStack );
+        // determine cofactoring variable
+        int Depth = 1 + (pLast->vCofVars ? Vec_IntSize(pLast->vCofVars) : 0);
+        int nFanouts, Cost, iVar  = Gia_SplitCofVar( pLast, LookAhead, &nFanouts, &Cost );
+        // cofactor
+        Gia_Man_t * pPart = Gia_ManDupCofactorVar( pLast, iVar, 0 );
+        if ( pLast->vCofVars == NULL )
+            pLast->vCofVars = Vec_IntAlloc( 100 );
+        // print results
+        if ( fVeryVerbose )
+        {
+//            Cec_GiaSplitPrintRefs( pLast );
+            printf( "Var = %5d. Fanouts = %5d. Cost = %8d.  AndBefore = %6d.  AndAfter = %6d.\n", 
+                iVar, nFanouts, Cost, Gia_ManAndNum(pLast), Gia_ManAndNum(pPart) );
+//            Cec_GiaSplitPrintRefs( pPart );
+        }
+        // create variable
+        pPart->vCofVars = Vec_IntAlloc( Vec_IntSize(pLast->vCofVars) + 1 );
+        Vec_IntAppend( pPart->vCofVars, pLast->vCofVars );
+        Vec_IntPush( pPart->vCofVars, Abc_Var2Lit(iVar, 1) );
+        // solve the problem
+        pCnf = Cec_GiaDeriveGiaRemapped( pPart );
+        status = Cnf_GiaSolveOne( pPart, pCnf, nTimeOut, &nSatVars, &nSatConfs );
+        Cnf_DataFree( pCnf );
+        if ( status == 1 )
+            Progress += 1.0 / pow(2, Depth);
+        if ( fVerbose ) 
+            Cec_GiaSplitPrint( nIter, Depth, nSatVars, nSatConfs, status, Progress, Abc_Clock() - clkTotal );
+        if ( status == 0 ) // SAT
+        {
+            p->pCexComb = pPart->pCexComb;  pPart->pCexComb = NULL;
+            Gia_ManStop( pLast );
+            Gia_ManStop( pPart );
+            RetValue = 0;
+            break;
+        }
+        if ( status == 1 ) // UNSAT
+            Gia_ManStop( pPart );
+        else               // UNDEC
+            Vec_PtrPush( vStack, pPart );
+        // cofactor
+        pPart = Gia_ManDupCofactorVar( pLast, iVar, 1 );
+        // create variable
+        pPart->vCofVars = Vec_IntAlloc( Vec_IntSize(pLast->vCofVars) + 1 );
+        Vec_IntAppend( pPart->vCofVars, pLast->vCofVars );
+        Vec_IntPush( pPart->vCofVars, Abc_Var2Lit(iVar, 0) );
+        Gia_ManStop( pLast );
+        // solve the problem
+        pCnf = Cec_GiaDeriveGiaRemapped( pPart );
+        status = Cnf_GiaSolveOne( pPart, pCnf, nTimeOut, &nSatVars, &nSatConfs );
+        Cnf_DataFree( pCnf );
+        if ( status == 1 )
+            Progress += 1.0 / pow(2, Depth);
+        if ( fVerbose )
+            Cec_GiaSplitPrint( nIter, Depth, nSatVars, nSatConfs, status, Progress, Abc_Clock() - clkTotal );
+        if ( status == 0 ) // SAT
+        {
+            p->pCexComb = pPart->pCexComb;  pPart->pCexComb = NULL;
+            Gia_ManStop( pPart );
+            RetValue = 0;
+            break;
+        }
+        if ( status == 1 ) // UNSAT
+            Gia_ManStop( pPart );
+        else               // UNDEC
+            Vec_PtrPush( vStack, pPart );
+        if ( nIterMax && nIter >= nIterMax )
+            break;
+    }
+    if ( Vec_PtrSize(vStack) == 0 )
+        RetValue = 1;
+    // finish
+    Cec_GiaSplitClean( vStack );
+    if ( RetValue == 0 )
+        printf( "Problem is SAT " );
+    else if ( RetValue == 1 )
+        printf( "Problem is UNSAT " );
+    else if ( RetValue == -1 )
+        printf( "Problem is UNDECIDED " );
+    else assert( 0 );
+    printf( "after %d case-splits.  ", nIter );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+    fflush( stdout );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+#ifdef ABC_USE_PTHREADS
+
+#define PAR_THR_MAX 100
+typedef struct Par_ThData_t_
+{
+    Gia_Man_t * p;
+    Cnf_Dat_t * pCnf;
+    int         iThread;
+    int         nTimeOut;
+    int         fWorking;
+    int         Result;
+    int         nVars;
+    int         nConfs;
+} Par_ThData_t;
+void * Cec_GiaSplitWorkerThread( void * pArg )
+{
+    Par_ThData_t * pThData = (Par_ThData_t *)pArg;
+    volatile int * pPlace = &pThData->fWorking;
+    while ( 1 )
+    {
+        while ( *pPlace == 0 );
+        assert( pThData->fWorking );
+        if ( pThData->p == NULL )
+        {
+	        pthread_exit( NULL );
+            assert( 0 );
+            return NULL;
+        }
+        pThData->Result = Cnf_GiaSolveOne( pThData->p, pThData->pCnf, pThData->nTimeOut, &pThData->nVars, &pThData->nConfs );
+        pThData->fWorking = 0;
+    }
+	assert( 0 );
+	return NULL;
+}
+int Cec_GiaSplitTestInt( Gia_Man_t * p, int nProcs, int nTimeOut, int nIterMax, int LookAhead, int fVerbose, int fVeryVerbose )
+{
+    abctime clkTotal = Abc_Clock();
+    Par_ThData_t ThData[PAR_THR_MAX];
+	pthread_t WorkerThread[PAR_THR_MAX];
+    Vec_Ptr_t * vStack;
+    Cnf_Dat_t * pCnf;
+    double Progress = 0;
+    int i, status, nSatVars, nSatConfs;
+    int nIter = 0, RetValue = -1, fWorkToDo = 1;
+    Abc_CexFreeP( &p->pCexComb );
+    if ( fVerbose )
+        printf( "Solving CEC problem by cofactoring with the following parameters:\n" );
+    if ( fVerbose )
+        printf( "Processes = %d   TimeOut = %d sec   MaxIter = %d   LookAhead = %d   Verbose = %d.\n", nProcs, nTimeOut, nIterMax, LookAhead, fVerbose );
+    fflush( stdout );
+    if ( nProcs == 1 )
+        return Cec_GiaSplitTest2( p, nProcs, nTimeOut, nIterMax, LookAhead, fVerbose, fVeryVerbose );
+    // subtract manager thread
+    nProcs--;
+    assert( nProcs >= 1 && nProcs <= PAR_THR_MAX );
+    // check the problem
+    pCnf = Cec_GiaDeriveGiaRemapped( p );
+    status = Cnf_GiaSolveOne( p, pCnf, nTimeOut, &nSatVars, &nSatConfs );
+    Cnf_DataFree( pCnf );
+    if ( fVerbose && status != -1 )
+        Cec_GiaSplitPrint( 0, 0, nSatVars, nSatConfs, status, Progress, Abc_Clock() - clkTotal );
+    if ( status == 0 )
+    {
+        printf( "The problem is SAT without cofactoring.\n" );
+        return 0;
+    }
+    if ( status == 1 )
+    {
+        printf( "The problem is UNSAT without cofactoring.\n" );
+        return 1;
+    }
+    assert( status == -1 );
+    // create local copy
+    vStack = Vec_PtrAlloc( 1000 );
+    Vec_PtrPush( vStack, Gia_ManDup(p) );
+    // start threads
+    for ( i = 0; i < nProcs; i++ )
+    {
+        ThData[i].p        = NULL;
+        ThData[i].pCnf     = NULL;
+        ThData[i].iThread  = i;
+        ThData[i].nTimeOut = nTimeOut;
+        ThData[i].fWorking = 0;
+        ThData[i].Result   = -1;
+        ThData[i].nVars    = -1;
+        ThData[i].nConfs   = -1;
+        status = pthread_create( WorkerThread + i, NULL,Cec_GiaSplitWorkerThread, (void *)(ThData + i) );  assert( status == 0 );
+    }
+    // look at the threads
+    while ( fWorkToDo )
+    {
+        fWorkToDo = (int)(Vec_PtrSize(vStack) > 0);
+        for ( i = 0; i < nProcs; i++ )
+        {
+            // check if this thread is working
+            if ( ThData[i].fWorking )
+            {
+                fWorkToDo = 1;
+                continue;
+            }
+            // check if this thread has recently finished
+            if ( ThData[i].p != NULL )
+            {
+                Gia_Man_t * pLast = ThData[i].p;
+                int Depth = pLast->vCofVars ? Vec_IntSize(pLast->vCofVars) : 0;
+                if ( pLast->vCofVars == NULL )
+                    pLast->vCofVars = Vec_IntAlloc( 100 );
+                if ( fVerbose )
+                    Cec_GiaSplitPrint( i+1, Depth, ThData[i].nVars, ThData[i].nConfs, ThData[i].Result, Progress, Abc_Clock() - clkTotal );
+                if ( ThData[i].Result == 0 ) // SAT
+                {
+                    p->pCexComb = pLast->pCexComb;  pLast->pCexComb = NULL;
+                    RetValue = 0;
+                    goto finish;
+                }
+                if ( ThData[i].Result == -1 ) // UNDEC
+                {
+                    // determine cofactoring variable
+                    int nFanouts, Cost, iVar = Gia_SplitCofVar( pLast, LookAhead, &nFanouts, &Cost );
+                    // cofactor
+                    Gia_Man_t * pPart = Gia_ManDupCofactorVar( pLast, iVar, 0 );
+                    pPart->vCofVars = Vec_IntAlloc( Vec_IntSize(pLast->vCofVars) + 1 );
+                    Vec_IntAppend( pPart->vCofVars, pLast->vCofVars );
+                    Vec_IntPush( pPart->vCofVars, Abc_Var2Lit(iVar, 1) );
+                    Vec_PtrPush( vStack, pPart );
+                    // print results
+                    if ( fVeryVerbose )
+                    {
+//                        Cec_GiaSplitPrintRefs( pLast );
+                        printf( "Var = %5d. Fanouts = %5d. Cost = %8d.  AndBefore = %6d.  AndAfter = %6d.\n", 
+                            iVar, nFanouts, Cost, Gia_ManAndNum(pLast), Gia_ManAndNum(pPart) );
+//                        Cec_GiaSplitPrintRefs( pPart );
+                    }
+                    // cofactor
+                    pPart = Gia_ManDupCofactorVar( pLast, iVar, 1 );
+                    pPart->vCofVars = Vec_IntAlloc( Vec_IntSize(pLast->vCofVars) + 1 );
+                    Vec_IntAppend( pPart->vCofVars, pLast->vCofVars );
+                    Vec_IntPush( pPart->vCofVars, Abc_Var2Lit(iVar, 1) );
+                    Vec_PtrPush( vStack, pPart );
+                    // keep working
+                    fWorkToDo = 1;
+                    nIter++;
+                }
+                else
+                    Progress += 1.0 / pow(2, Depth);
+                Gia_ManStopP( &ThData[i].p );
+                if ( ThData[i].pCnf == NULL )
+                    continue;
+                Cnf_DataFree( ThData[i].pCnf );
+                ThData[i].pCnf = NULL;
+            }
+            if ( Vec_PtrSize(vStack) == 0 )
+                continue;
+            // start a new thread
+            assert( ThData[i].p == NULL );
+            ThData[i].p = Vec_PtrPop( vStack );
+            ThData[i].pCnf = Cec_GiaDeriveGiaRemapped( ThData[i].p );
+            ThData[i].fWorking = 1;
+        }
+        if ( nIterMax && nIter >= nIterMax )
+            break;
+    }
+    if ( !fWorkToDo )
+        RetValue = 1;
+finish:
+    // wait till threads finish
+    for ( i = 0; i < nProcs; i++ )
+        if ( ThData[i].fWorking )
+            i = 0;
+    // stop threads
+    for ( i = 0; i < nProcs; i++ )
+    {
+        assert( !ThData[i].fWorking );
+        // cleanup
+        Gia_ManStopP( &ThData[i].p );
+        if ( ThData[i].pCnf == NULL )
+            continue;
+        Cnf_DataFree( ThData[i].pCnf );
+        ThData[i].pCnf = NULL;
+        // stop
+        ThData[i].p = NULL;
+        ThData[i].fWorking = 1;
+    }
+    // finish
+    Cec_GiaSplitClean( vStack );
+    if ( RetValue == 0 )
+        printf( "Problem is SAT " );
+    else if ( RetValue == 1 )
+        printf( "Problem is UNSAT " );
+    else if ( RetValue == -1 )
+        printf( "Problem is UNDECIDED " );
+    else assert( 0 );
+    printf( "after %d case-splits.  ", nIter );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+    fflush( stdout );
+    return RetValue;
+}
+int Cec_GiaSplitTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nIterMax, int LookAhead, int fVerbose, int fVeryVerbose )
+{
+    Abc_Cex_t * pCex = NULL;
+    Gia_Man_t * pOne;
+    Gia_Obj_t * pObj;
+    int i, RetValue1, fOneUndef = 0, RetValue = -1;
+    Abc_CexFreeP( &p->pCexComb );
+    Gia_ManForEachPo( p, pObj, i )
+    {
+        pOne = Gia_ManDupOutputGroup( p, i, i+1 );
+        if ( fVerbose )
+            printf( "\nSolving output %d:\n", i );
+        RetValue1 = Cec_GiaSplitTestInt( pOne, nProcs, nTimeOut, nIterMax, LookAhead,  fVerbose, fVeryVerbose );
+        Gia_ManStop( pOne );
+        // collect the result
+        if ( RetValue1 == 0 && RetValue == -1 )
+        {
+            pCex = pOne->pCexComb; pOne->pCexComb = NULL;
+            pCex->iPo = i;
+            RetValue = 0;
+        }
+        if ( RetValue1 == -1 )
+            fOneUndef = 1;
+    }
+    if ( RetValue == -1 )
+        RetValue = fOneUndef ? -1 : 1;
+    else
+        p->pCexComb = pCex;
+    return RetValue;
+}
+#endif
+
+/**Function*************************************************************
+
+  Synopsis    [Print stats about cofactoring variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_GiaPrintCofStats( Gia_Man_t * p )
+{
+    Gia_Man_t * pCof0, * pCof1;
+    Gia_Obj_t * pObj, * pFan0, * pFan1, * pCtrl;
+    Vec_Int_t * vMarks;
+    int i, Count = 0;
+    vMarks = Vec_IntStart( Gia_ManObjNum(p) );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        if ( !Gia_ObjIsMuxType(pObj) )
+            continue;
+        if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) )
+            continue;
+        pCtrl = Gia_ObjRecognizeMux( pObj, &pFan1, &pFan0 );
+        pCtrl = Gia_Regular(pCtrl);
+        Vec_IntAddToEntry( vMarks, Gia_ObjId(p, pCtrl), 1 );
+    }
+    printf( "The AIG with %d candidate nodes (PI+AND) has %d unique MUX control drivers:\n", 
+        Gia_ManCandNum(p), Vec_IntCountPositive(vMarks) );
+    Gia_ManLevelNum( p );
+    Gia_ManForEachCand( p, pObj, i )
+    {
+        if ( !Vec_IntEntry(vMarks, i) )
+            continue;
+        pCof0 = Gia_ManDupCofactorObj( p, i, 0 );
+        pCof1 = Gia_ManDupCofactorObj( p, i, 1 );
+        printf( "%6d :   ",          Count++ );
+        printf( "Obj = %6d   ",      i );
+        printf( "MUX refs = %5d   ", Vec_IntEntry(vMarks, i) );
+        printf( "Level = %5d   ",    Gia_ObjLevelId(p, i) );
+        printf( "Cof0 = %7d   ",     Gia_ManAndNum(pCof0) );
+        printf( "Cof1 = %7d   ",     Gia_ManAndNum(pCof1) );
+        printf( "\n" );
+        Gia_ManStop( pCof0 );
+        Gia_ManStop( pCof1 );
+    }
+    Vec_IntFree( vMarks );
+}
+void Cec_GiaPrintCofStats2( Gia_Man_t * p )
+{
+    Gia_Man_t * pCof0, * pCof1;
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManLevelNum( p );
+    Gia_ManCreateRefs( p );
+    Gia_ManForEachPi( p, pObj, i )
+    {
+        pCof0 = Gia_ManDupCofactorVar( p, i, 0 );
+        pCof1 = Gia_ManDupCofactorVar( p, i, 1 );
+        printf( "PI %5d :   ",   i );
+        printf( "Refs = %5d   ", Gia_ObjRefNum(p, pObj) );
+        printf( "Cof0 = %7d   ", Gia_ManAndNum(pCof0) );
+        printf( "Cof1 = %7d   ", Gia_ManAndNum(pCof1) );
+        printf( "\n" );
+        Gia_ManStop( pCof0 );
+        Gia_ManStop( pCof1 );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/cec/cecSweep.c b/abc-build/src/proof/cec/cecSweep.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/cecSweep.c
@@ -0,0 +1,301 @@
+/**CFile****************************************************************
+
+  FileName    [cecSweep.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Combinational equivalence checking.]
+
+  Synopsis    [SAT sweeping manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cecSweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs limited speculative reduction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Cec_ManFraSpecReduction( Cec_ManFra_t * p )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pRepr = NULL;
+    int iRes0, iRes1, iRepr, iNode, iMiter;
+    int i, fCompl, * piCopies, * pDepths;
+    Gia_ManSetPhase( p->pAig );
+    Vec_IntClear( p->vXorNodes );
+    if ( p->pPars->nLevelMax )
+        Gia_ManLevelNum( p->pAig );
+    pNew = Gia_ManStart( Gia_ManObjNum(p->pAig) );
+    pNew->pName = Abc_UtilStrsav( p->pAig->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pAig->pName );
+    Gia_ManHashAlloc( pNew );
+    piCopies = ABC_FALLOC( int, Gia_ManObjNum(p->pAig) );
+    pDepths  = ABC_CALLOC( int, Gia_ManObjNum(p->pAig) );
+    piCopies[0] = 0;
+    Gia_ManForEachObj1( p->pAig, pObj, i )
+    {
+        if ( Gia_ObjIsCi(pObj) ) 
+        {
+            piCopies[i] = Gia_ManAppendCi( pNew );
+            continue;
+        }
+        if ( Gia_ObjIsCo(pObj) ) 
+            continue;
+        if ( piCopies[Gia_ObjFaninId0(pObj,i)] == -1 ||
+             piCopies[Gia_ObjFaninId1(pObj,i)] == -1 )
+             continue;
+        iRes0 = Abc_LitNotCond( piCopies[Gia_ObjFaninId0(pObj,i)], Gia_ObjFaninC0(pObj) );
+        iRes1 = Abc_LitNotCond( piCopies[Gia_ObjFaninId1(pObj,i)], Gia_ObjFaninC1(pObj) );
+        iNode = piCopies[i] = Gia_ManHashAnd( pNew, iRes0, iRes1 );
+        pDepths[i] = Abc_MaxInt( pDepths[Gia_ObjFaninId0(pObj,i)], pDepths[Gia_ObjFaninId1(pObj,i)] );
+        if ( Gia_ObjRepr(p->pAig, i) == GIA_VOID || Gia_ObjFailed(p->pAig, i) )
+            continue;
+        assert( Gia_ObjRepr(p->pAig, i) < i );
+        iRepr = piCopies[Gia_ObjRepr(p->pAig, i)];
+        if ( iRepr == -1 )
+            continue;
+        if ( Abc_LitRegular(iNode) == Abc_LitRegular(iRepr) )
+            continue;
+        if ( p->pPars->nLevelMax && 
+            (Gia_ObjLevel(p->pAig, pObj)  > p->pPars->nLevelMax || 
+             Gia_ObjLevel(p->pAig, pRepr) > p->pPars->nLevelMax) )
+            continue;
+        if ( p->pPars->fDualOut )
+        {
+//            if ( i % 1000 == 0 && Gia_ObjRepr(p->pAig, i) )
+//                Gia_ManEquivPrintOne( p->pAig, Gia_ObjRepr(p->pAig, i), 0 );
+            if ( p->pPars->fColorDiff )
+            {
+                if ( !Gia_ObjDiffColors( p->pAig, Gia_ObjRepr(p->pAig, i), i ) )
+                    continue;
+            }
+            else
+            {
+                if ( !Gia_ObjDiffColors2( p->pAig, Gia_ObjRepr(p->pAig, i), i ) )
+                    continue;
+            }
+        }
+        pRepr = Gia_ManObj( p->pAig, Gia_ObjRepr(p->pAig, i) );
+        fCompl = Gia_ObjPhaseReal(pObj) ^ Gia_ObjPhaseReal(pRepr);
+        piCopies[i] = Abc_LitNotCond( iRepr, fCompl );
+        if ( Gia_ObjProved(p->pAig, i) )
+            continue;
+        // produce speculative miter
+        iMiter = Gia_ManHashXor( pNew, iNode, piCopies[i] );
+        Gia_ManAppendCo( pNew, iMiter );
+        Vec_IntPush( p->vXorNodes, Gia_ObjRepr(p->pAig, i) );
+        Vec_IntPush( p->vXorNodes, i );
+        // add to the depth of this node
+        pDepths[i] = 1 + Abc_MaxInt( pDepths[i], pDepths[Gia_ObjRepr(p->pAig, i)] );
+        if ( p->pPars->nDepthMax && pDepths[i] >= p->pPars->nDepthMax )
+            piCopies[i] = -1;
+    }
+    ABC_FREE( piCopies );
+    ABC_FREE( pDepths );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, 0 );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManFraClassesUpdate_rec( Gia_Obj_t * pObj )
+{
+    int Result;
+    if ( pObj->fMark0 )
+        return 1;
+    if ( Gia_ObjIsCi(pObj) || Gia_ObjIsConst0(pObj) )
+        return 0;
+    Result = (Cec_ManFraClassesUpdate_rec( Gia_ObjFanin0(pObj) ) |
+              Cec_ManFraClassesUpdate_rec( Gia_ObjFanin1(pObj) ));
+    return pObj->fMark0 = Result;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates simulation info for this round.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_ManFraCreateInfo( Cec_ManSim_t * p, Vec_Ptr_t * vCiInfo, Vec_Ptr_t * vInfo, int nSeries )
+{
+    unsigned * pRes0, * pRes1;
+    int i, w;
+    for ( i = 0; i < Gia_ManCiNum(p->pAig); i++ )
+    {
+        pRes0 = (unsigned *)Vec_PtrEntry( vCiInfo, i );
+        pRes1 = (unsigned *)Vec_PtrEntry( vInfo, i );
+        pRes1 += p->nWords * nSeries;
+        for ( w = 0; w < p->nWords; w++ )
+            pRes0[w] = pRes1[w];
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates equivalence classes using the patterns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_ManFraClassesUpdate( Cec_ManFra_t * p, Cec_ManSim_t * pSim, Cec_ManPat_t * pPat, Gia_Man_t * pNew )
+{
+    Vec_Ptr_t * vInfo;
+    Gia_Obj_t * pObj, * pObjOld, * pReprOld;
+    int i, k, iRepr, iNode;
+    abctime clk;
+clk = Abc_Clock();
+    vInfo = Cec_ManPatCollectPatterns( pPat, Gia_ManCiNum(p->pAig), pSim->nWords );
+p->timePat += Abc_Clock() - clk;
+clk = Abc_Clock();
+    if ( vInfo != NULL )
+    {
+        Gia_ManCreateValueRefs( p->pAig );
+        for ( i = 0; i < pPat->nSeries; i++ )
+        {
+            Cec_ManFraCreateInfo( pSim, pSim->vCiSimInfo, vInfo, i );
+            if ( Cec_ManSimSimulateRound( pSim, pSim->vCiSimInfo, pSim->vCoSimInfo ) )
+            {
+                Vec_PtrFree( vInfo );
+                return 1;
+            }
+        }
+        Vec_PtrFree( vInfo );
+    }
+p->timeSim += Abc_Clock() - clk;
+    assert( Vec_IntSize(p->vXorNodes) == 2*Gia_ManCoNum(pNew) );
+    // mark the transitive fanout of failed nodes
+    if ( p->pPars->nDepthMax != 1 )
+    {
+        Gia_ManCleanMark0( p->pAig );
+        Gia_ManCleanMark1( p->pAig );
+        Gia_ManForEachCo( pNew, pObj, k )
+        {
+            iRepr = Vec_IntEntry( p->vXorNodes, 2*k );
+            iNode = Vec_IntEntry( p->vXorNodes, 2*k+1 );
+            if ( pObj->fMark0 == 0 && pObj->fMark1 == 1 ) // proved
+                continue;
+//            Gia_ManObj(p->pAig, iRepr)->fMark0 = 1;
+            Gia_ManObj(p->pAig, iNode)->fMark0 = 1;
+        }
+        // mark the nodes reachable through the failed nodes
+        Gia_ManForEachAnd( p->pAig, pObjOld, k )
+            pObjOld->fMark0 |= (Gia_ObjFanin0(pObjOld)->fMark0 | Gia_ObjFanin1(pObjOld)->fMark0);
+        // unmark the disproved nodes
+        Gia_ManForEachCo( pNew, pObj, k )
+        {
+            iRepr = Vec_IntEntry( p->vXorNodes, 2*k );
+            iNode = Vec_IntEntry( p->vXorNodes, 2*k+1 );
+            if ( pObj->fMark0 == 0 && pObj->fMark1 == 1 ) // proved
+                continue; 
+            pObjOld = Gia_ManObj(p->pAig, iNode);
+            assert( pObjOld->fMark0 == 1 );
+            if ( Gia_ObjFanin0(pObjOld)->fMark0 == 0 && Gia_ObjFanin1(pObjOld)->fMark0 == 0 )
+                pObjOld->fMark1 = 1;
+        }
+        // clean marks
+        Gia_ManForEachAnd( p->pAig, pObjOld, k )
+            if ( pObjOld->fMark1 )
+            {
+                pObjOld->fMark0 = 0;
+                pObjOld->fMark1 = 0;
+            }
+    }
+    // set the results
+    p->nAllProved = p->nAllDisproved = p->nAllFailed = 0;
+    Gia_ManForEachCo( pNew, pObj, k )
+    {
+        iRepr = Vec_IntEntry( p->vXorNodes, 2*k );
+        iNode = Vec_IntEntry( p->vXorNodes, 2*k+1 );
+        pReprOld = Gia_ManObj(p->pAig, iRepr);
+        pObjOld = Gia_ManObj(p->pAig, iNode);
+        if ( pObj->fMark1 )
+        { // proved
+            assert( pObj->fMark0 == 0 );
+            assert( !Gia_ObjProved(p->pAig, iNode) );
+            if ( pReprOld->fMark0 == 0 && pObjOld->fMark0 == 0 )
+//            if ( pObjOld->fMark0 == 0 )
+            {
+                assert( iRepr == Gia_ObjRepr(p->pAig, iNode) );
+                Gia_ObjSetProved( p->pAig, iNode );
+                p->nAllProved++;
+            }
+        }
+        else if ( pObj->fMark0 )
+        { // disproved
+            assert( pObj->fMark1 == 0 );
+            if ( pReprOld->fMark0 == 0 && pObjOld->fMark0 == 0 )
+//            if ( pObjOld->fMark0 == 0 )
+            {
+                if ( iRepr == Gia_ObjRepr(p->pAig, iNode) )
+                    Abc_Print( 1, "Cec_ManFraClassesUpdate(): Error! Node is not refined!\n" );
+                p->nAllDisproved++;
+            }
+        }
+        else
+        { // failed
+            assert( pObj->fMark0 == 0 );
+            assert( pObj->fMark1 == 0 );
+            assert( !Gia_ObjFailed(p->pAig, iNode) );
+            assert( !Gia_ObjProved(p->pAig, iNode) );
+            Gia_ObjSetFailed( p->pAig, iNode );
+            p->nAllFailed++;
+        }
+    } 
+    return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/cec/cecSynth.c b/abc-build/src/proof/cec/cecSynth.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/cecSynth.c
@@ -0,0 +1,381 @@
+/**CFile****************************************************************
+
+  FileName    [cecSynth.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Combinational equivalence checking.]
+
+  Synopsis    [Partitioned sequential synthesis.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: cecSynth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Populate sequential synthesis parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cec_SeqSynthesisSetDefaultParams( Cec_ParSeq_t * p )
+{
+    memset( p, 0, sizeof(Cec_ParSeq_t) );
+    p->fUseLcorr    =    0;  // enables latch correspondence
+    p->fUseScorr    =    0;  // enables signal correspondence
+    p->nBTLimit     = 1000;  // (scorr/lcorr) conflict limit at a node
+    p->nFrames      =    1;  // (scorr only) the number of timeframes
+    p->nLevelMax    =   -1;  // (scorr only) the max number of levels
+    p->fConsts      =    1;  // (scl only) merging constants
+    p->fEquivs      =    1;  // (scl only) merging equivalences
+    p->fUseMiniSat  =    0;  // enables MiniSat in lcorr/scorr
+    p->nMinDomSize  =  100;  // the size of minimum clock domain
+    p->fVeryVerbose =    0;  // verbose stats
+    p->fVerbose     =    0;  // verbose stats
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_SeqReadMinDomSize( Cec_ParSeq_t * p )
+{
+    return p->nMinDomSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_SeqReadVerbose( Cec_ParSeq_t * p )
+{
+    return p->fVerbose;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes partitioning of registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManRegCreatePart( Gia_Man_t * p, Vec_Int_t * vPart, int * pnCountPis, int * pnCountRegs, int ** ppMapBack )
+{
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vNodes, * vRoots;
+    int i, iOut, nCountPis, nCountRegs;
+    int * pMapBack;
+    // collect/mark nodes/PIs in the DFS order from the roots
+    Gia_ManIncrementTravId( p );
+    vRoots  = Vec_IntAlloc( Vec_IntSize(vPart) );
+    Vec_IntForEachEntry( vPart, iOut, i )
+        Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ManCo(p, Gia_ManPoNum(p)+iOut)) );
+    vNodes = Gia_ManCollectNodesCis( p, Vec_IntArray(vRoots), Vec_IntSize(vRoots) );
+    Vec_IntFree( vRoots );
+    // unmark register outputs
+    Vec_IntForEachEntry( vPart, iOut, i )
+        Gia_ObjSetTravIdPrevious( p, Gia_ManCi(p, Gia_ManPiNum(p)+iOut) );
+    // count pure PIs
+    nCountPis = nCountRegs = 0;
+    Gia_ManForEachPi( p, pObj, i )
+        nCountPis += Gia_ObjIsTravIdCurrent(p, pObj);
+    // count outputs of other registers
+    Gia_ManForEachRo( p, pObj, i )
+        nCountRegs += Gia_ObjIsTravIdCurrent(p, pObj); // should be !Gia_... ???
+    if ( pnCountPis )
+        *pnCountPis = nCountPis;
+    if ( pnCountRegs )
+        *pnCountRegs = nCountRegs;
+    // clean old manager
+    Gia_ManFillValue(p);
+    Gia_ManConst0(p)->Value = 0;
+    // create the new manager
+    pNew = Gia_ManStart( Vec_IntSize(vNodes) );
+    // create the PIs
+    Gia_ManForEachCi( p, pObj, i )
+        if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+            pObj->Value = Gia_ManAppendCi(pNew);
+    // add variables for the register outputs
+    // create fake POs to hold the register outputs
+    Vec_IntForEachEntry( vPart, iOut, i )
+    {
+        pObj = Gia_ManCi(p, Gia_ManPiNum(p)+iOut);
+        pObj->Value = Gia_ManAppendCi(pNew);
+        Gia_ManAppendCo( pNew, pObj->Value );
+        Gia_ObjSetTravIdCurrent( p, pObj ); // added
+    }
+    // create the nodes
+    Gia_ManForEachObjVec( vNodes, p, pObj, i )
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    // add real POs for the registers
+    Vec_IntForEachEntry( vPart, iOut, i )
+    {
+        pObj = Gia_ManCo( p, Gia_ManPoNum(p)+iOut );
+        Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    }
+    Gia_ManSetRegNum( pNew, Vec_IntSize(vPart) );
+    // create map
+    if ( ppMapBack )
+    {
+        pMapBack = ABC_FALLOC( int, Gia_ManObjNum(pNew) );
+        // map constant nodes
+        pMapBack[0] = 0;
+        // logic cones of register outputs
+        Gia_ManForEachObjVec( vNodes, p, pObj, i )
+        {
+//            pObjNew = Aig_Regular(pObj->pData);
+//            pMapBack[pObjNew->Id] = pObj->Id;
+            assert( Abc_Lit2Var(Gia_ObjValue(pObj)) >= 0 );
+            assert( Abc_Lit2Var(Gia_ObjValue(pObj)) < Gia_ManObjNum(pNew) );
+            pMapBack[ Abc_Lit2Var(Gia_ObjValue(pObj)) ] = Gia_ObjId(p, pObj);
+        }
+        // map register outputs
+        Vec_IntForEachEntry( vPart, iOut, i )
+        {
+            pObj = Gia_ManCi(p, Gia_ManPiNum(p)+iOut);
+//            pObjNew = pObj->pData;
+//            pMapBack[pObjNew->Id] = pObj->Id;
+            assert( Abc_Lit2Var(Gia_ObjValue(pObj)) >= 0 );
+            assert( Abc_Lit2Var(Gia_ObjValue(pObj)) < Gia_ManObjNum(pNew) );
+            pMapBack[ Abc_Lit2Var(Gia_ObjValue(pObj)) ] = Gia_ObjId(p, pObj);
+        }
+        *ppMapBack = pMapBack;
+    }
+    Vec_IntFree( vNodes );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_TransferMappedClasses( Gia_Man_t * pPart, int * pMapBack, int * pReprs )
+{
+    Gia_Obj_t * pObj;
+    int i, Id1, Id2, nClasses;
+    if ( pPart->pReprs == NULL ) 
+        return 0;
+    nClasses = 0;
+    Gia_ManForEachObj( pPart, pObj, i )
+    {
+        if ( Gia_ObjRepr(pPart, i) == GIA_VOID )
+            continue;
+        assert( i                     < Gia_ManObjNum(pPart) );
+        assert( Gia_ObjRepr(pPart, i) < Gia_ManObjNum(pPart) );
+        Id1 = pMapBack[ i ];
+        Id2 = pMapBack[ Gia_ObjRepr(pPart, i) ];
+        if ( Id1 == Id2 )
+            continue;
+        if ( Id1 < Id2 )
+            pReprs[Id2] = Id1;
+        else
+            pReprs[Id1] = Id2;
+        nClasses++;
+    }
+    return nClasses;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManFindRepr_rec( int * pReprs, int Id )
+{
+    if ( pReprs[Id] == 0 )
+        return 0;
+    if ( pReprs[Id] == ~0 )
+        return Id;
+    return Gia_ManFindRepr_rec( pReprs, pReprs[Id] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Normalizes equivalences.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManNormalizeEquivalences( Gia_Man_t * p, int * pReprs )
+{
+    int i, iRepr;
+    assert( p->pReprs == NULL );
+    assert( p->pNexts == NULL );
+    p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) );
+    for ( i = 0; i < Gia_ManObjNum(p); i++ )
+        Gia_ObjSetRepr( p, i, GIA_VOID );
+    for ( i = 0; i < Gia_ManObjNum(p); i++ )
+    {
+        if ( pReprs[i] == ~0 )
+            continue;
+        iRepr = Gia_ManFindRepr_rec( pReprs, i );
+        Gia_ObjSetRepr( p, i, iRepr );
+    }
+    p->pNexts = Gia_ManDeriveNexts( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Partitioned sequential synthesis.]
+
+  Description [Returns AIG annotated with equivalence classes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cec_SequentialSynthesisPart( Gia_Man_t * p, Cec_ParSeq_t * pPars )
+{
+    int fPrintParts = 0;
+    char Buffer[100];
+    Gia_Man_t * pTemp;
+    Vec_Ptr_t * vParts = (Vec_Ptr_t *)p->vClockDoms;
+    Vec_Int_t * vPart;
+    int * pMapBack, * pReprs;
+    int i, nCountPis, nCountRegs;
+    int nClasses;
+    abctime clk = Abc_Clock();
+
+    // save parameters
+    if ( fPrintParts )
+    {
+        // print partitions
+        Abc_Print( 1, "The following clock domains are used:\n" );
+        Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i )
+        {
+            pTemp = Gia_ManRegCreatePart( p, vPart, &nCountPis, &nCountRegs, NULL );
+            sprintf( Buffer, "part%03d.aig", i );
+            Gia_AigerWrite( pTemp, Buffer, 0, 0 );
+            Abc_Print( 1, "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n", 
+                i, Vec_IntSize(vPart), Gia_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Gia_ManAndNum(pTemp) );
+            Gia_ManStop( pTemp );
+        }
+    }
+
+    // perform sequential synthesis for clock domains
+    pReprs = ABC_FALLOC( int, Gia_ManObjNum(p) );
+    Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i )
+    {
+        pTemp = Gia_ManRegCreatePart( p, vPart, &nCountPis, &nCountRegs, &pMapBack );
+        if ( nCountPis > 0 ) 
+        {
+            if ( pPars->fUseScorr )
+            {
+                Cec_ParCor_t CorPars, * pCorPars = &CorPars;
+                Cec_ManCorSetDefaultParams( pCorPars );
+                pCorPars->nBTLimit   = pPars->nBTLimit;
+                pCorPars->nLevelMax  = pPars->nLevelMax;
+                pCorPars->fVerbose   = pPars->fVeryVerbose;
+                pCorPars->fUseCSat   = 1;
+                Cec_ManLSCorrespondenceClasses( pTemp, pCorPars );
+            }
+            else if ( pPars->fUseLcorr )
+            {
+                Cec_ParCor_t CorPars, * pCorPars = &CorPars;
+                Cec_ManCorSetDefaultParams( pCorPars );
+                pCorPars->fLatchCorr = 1;
+                pCorPars->nBTLimit   = pPars->nBTLimit;
+                pCorPars->fVerbose   = pPars->fVeryVerbose;
+                pCorPars->fUseCSat   = 1;
+                Cec_ManLSCorrespondenceClasses( pTemp, pCorPars );
+            }
+            else
+            {
+//                pNew = Gia_ManSeqStructSweep( pTemp, pPars->fConsts, pPars->fEquivs, pPars->fVerbose );
+//                Gia_ManStop( pNew );
+                Gia_ManSeqCleanupClasses( pTemp, pPars->fConsts, pPars->fEquivs, pPars->fVerbose );
+            }
+//Abc_Print( 1, "Part equivalences = %d.\n", Gia_ManEquivCountLitsAll(pTemp) );
+            nClasses = Gia_TransferMappedClasses( pTemp, pMapBack, pReprs );
+            if ( pPars->fVerbose )
+            {
+                Abc_Print( 1, "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. Cl = %5d.\n", 
+                    i, Vec_IntSize(vPart), Gia_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Gia_ManAndNum(pTemp), nClasses );
+            }
+        }
+        Gia_ManStop( pTemp );
+        ABC_FREE( pMapBack );
+    }
+
+    // generate resulting equivalences
+    Gia_ManNormalizeEquivalences( p, pReprs );
+//Abc_Print( 1, "Total equivalences = %d.\n", Gia_ManEquivCountLitsAll(p) );
+    ABC_FREE( pReprs );
+    if ( pPars->fVerbose )
+    {
+        Abc_PrintTime( 1, "Total time", Abc_Clock() - clk );
+    }
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/cec/module.make b/abc-build/src/proof/cec/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/cec/module.make
@@ -0,0 +1,13 @@
+SRC +=	src/proof/cec/cecCec.c \
+	src/proof/cec/cecChoice.c \
+	src/proof/cec/cecClass.c \
+	src/proof/cec/cecCore.c \
+	src/proof/cec/cecCorr.c \
+	src/proof/cec/cecIso.c \
+	src/proof/cec/cecMan.c \
+	src/proof/cec/cecPat.c \
+	src/proof/cec/cecSeq.c \
+	src/proof/cec/cecSolve.c \
+	src/proof/cec/cecSplit.c \
+	src/proof/cec/cecSynth.c \
+	src/proof/cec/cecSweep.c
diff --git a/abc-build/src/proof/dch/dch.h b/abc-build/src/proof/dch/dch.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/dch/dch.h
@@ -0,0 +1,91 @@
+/**CFile****************************************************************
+
+  FileName    [dch.h] 
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Choice computation for tech-mapping.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: dch.h,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__dch__dch_h
+#define ABC__aig__dch__dch_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// choicing parameters
+typedef struct Dch_Pars_t_ Dch_Pars_t;
+struct Dch_Pars_t_
+{
+    int              nWords;        // the number of simulation words
+    int              nBTLimit;      // conflict limit at a node
+    int              nSatVarMax;    // the max number of SAT variables
+    int              fSynthesis;    // set to 1 to perform synthesis
+    int              fPolarFlip;    // uses polarity adjustment
+    int              fSimulateTfo;  // uses simulation of TFO classes
+    int              fPower;        // uses power-aware rewriting
+    int              fUseGia;       // uses GIA package 
+    int              fUseCSat;      // uses circuit-based solver
+    int              fLightSynth;   // uses lighter version of synthesis
+    int              fSkipRedSupp;  // skip choices with redundant support vars
+    int              fVerbose;      // verbose stats
+    abctime          timeSynth;     // synthesis runtime
+    int              nNodesAhead;   // the lookahead in terms of nodes
+    int              nCallsRecycle; // calls to perform before recycling SAT solver
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== dchAig.c ==========================================================*/
+extern Aig_Man_t *   Dch_DeriveTotalAig( Vec_Ptr_t * vAigs );
+/*=== dchCore.c ==========================================================*/
+extern void          Dch_ManSetDefaultParams( Dch_Pars_t * p );
+extern int           Dch_ManReadVerbose( Dch_Pars_t * p );
+extern Aig_Man_t *   Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars );
+extern void          Dch_ComputeEquivalences( Aig_Man_t * pAig, Dch_Pars_t * pPars );
+/*=== dchScript.c ==========================================================*/
+extern Aig_Man_t *   Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars );
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/dch/dchAig.c b/abc-build/src/proof/dch/dchAig.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/dch/dchAig.c
@@ -0,0 +1,119 @@
+/**CFile****************************************************************
+
+  FileName    [dchAig.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Choice computation for tech-mapping.]
+
+  Synopsis    [AIG manipulation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: dchAig.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the cumulative AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_DeriveTotalAig_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    if ( pObj->pData )
+        return;
+    Dch_DeriveTotalAig_rec( p, Aig_ObjFanin0(pObj) );
+    Dch_DeriveTotalAig_rec( p, Aig_ObjFanin1(pObj) );
+    pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the cumulative AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs )
+{
+    Aig_Man_t * pAig, * pAig2, * pAigTotal;
+    Aig_Obj_t * pObj, * pObjPi, * pObjPo;
+    int i, k, nNodes;
+    assert( Vec_PtrSize(vAigs) > 0 );
+    // make sure they have the same number of PIs/POs
+    nNodes = 0;
+    pAig = (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 );
+    Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, i )
+    {
+        assert( Aig_ManCiNum(pAig) == Aig_ManCiNum(pAig2) );
+        assert( Aig_ManCoNum(pAig) == Aig_ManCoNum(pAig2) );
+        nNodes += Aig_ManNodeNum(pAig2);
+        Aig_ManCleanData( pAig2 );
+    }
+    // map constant nodes
+    pAigTotal = Aig_ManStart( nNodes );
+    Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, k )
+        Aig_ManConst1(pAig2)->pData = Aig_ManConst1(pAigTotal);
+    // map primary inputs
+    Aig_ManForEachCi( pAig, pObj, i )
+    {
+        pObjPi = Aig_ObjCreateCi( pAigTotal );
+        Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, k )
+            Aig_ManCi( pAig2, i )->pData = pObjPi;
+    }
+    // construct the AIG in the order of POs
+    Aig_ManForEachCo( pAig, pObj, i )
+    {
+        Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, k )
+        {
+            pObjPo = Aig_ManCo( pAig2, i );
+            Dch_DeriveTotalAig_rec( pAigTotal, Aig_ObjFanin0(pObjPo) );
+        }
+        Aig_ObjCreateCo( pAigTotal, Aig_ObjChild0Copy(pObj) );
+    }
+/*
+    // mark the cone of the first AIG
+    Aig_ManIncrementTravId( pAigTotal );
+    Aig_ManForEachObj( pAig, pObj, i )
+        if ( pObj->pData ) 
+            Aig_ObjSetTravIdCurrent( pAigTotal, pObj->pData );
+*/
+    // cleanup should not be done
+    return pAigTotal;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/dch/dchChoice.c b/abc-build/src/proof/dch/dchChoice.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/dch/dchChoice.c
@@ -0,0 +1,545 @@
+/**CFile****************************************************************
+
+  FileName    [dchChoice.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Choice computation for tech-mapping.]
+
+  Synopsis    [Contrustion of choices.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: dchChoice.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Counts support nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dch_ObjCountSupp_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    int Count;
+    if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
+        return 0;
+    Aig_ObjSetTravIdCurrent( p, pObj );
+    if ( Aig_ObjIsCi(pObj) )
+        return 1;
+    assert( Aig_ObjIsNode(pObj) );
+    Count  = Dch_ObjCountSupp_rec( p, Aig_ObjFanin0(pObj) );
+    Count += Dch_ObjCountSupp_rec( p, Aig_ObjFanin1(pObj) );
+    return Count;
+}
+int Dch_ObjCountSupp( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_ManIncrementTravId( p );
+    return Dch_ObjCountSupp_rec( p, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of representatives.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dch_DeriveChoiceCountReprs( Aig_Man_t * pAig )
+{
+    Aig_Obj_t * pObj, * pRepr;
+    int i, nReprs = 0;
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+        pRepr = Aig_ObjRepr( pAig, pObj );
+        if ( pRepr == NULL )
+            continue;
+        assert( pRepr->Id < pObj->Id );
+        nReprs++;
+    }
+    return nReprs;
+}
+int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig )
+{
+    Aig_Obj_t * pObj, * pEquiv;
+    int i, nEquivs = 0;
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+        pEquiv = Aig_ObjEquiv( pAig, pObj );
+        if ( pEquiv == NULL )
+            continue;
+        assert( pEquiv->Id < pObj->Id );
+        nEquivs++;
+    }
+    return nEquivs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the TFI of the node.]
+
+  Description [Returns 1 if there is a CI not marked with previous ID.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dch_ObjMarkTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    int RetValue;
+    if ( pObj == NULL )
+        return 0;
+    if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
+        return 0;
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        RetValue = !Aig_ObjIsTravIdPrevious( p, pObj );
+        Aig_ObjSetTravIdCurrent( p, pObj );
+        return RetValue;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    Aig_ObjSetTravIdCurrent( p, pObj );
+    RetValue  = Dch_ObjMarkTfi_rec( p, Aig_ObjFanin0(pObj) );
+    RetValue += Dch_ObjMarkTfi_rec( p, Aig_ObjFanin1(pObj) );
+//    RetValue += Dch_ObjMarkTfi_rec( p, Aig_ObjEquiv(p, pObj) );
+    return (RetValue > 0);
+}
+int Dch_ObjCheckSuppRed( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr )
+{
+    // mark support of the representative node (pRepr)
+    Aig_ManIncrementTravId( p );
+    Dch_ObjMarkTfi_rec( p, pRepr );
+    // detect if the new node (pObj) depends on additional variables
+    Aig_ManIncrementTravId( p );
+    if ( Dch_ObjMarkTfi_rec( p, pObj ) )
+        return 1;//, printf( "1" );
+    // detect if the representative node (pRepr) depends on additional variables
+    Aig_ManIncrementTravId( p );
+    if ( Dch_ObjMarkTfi_rec( p, pRepr ) )
+        return 1;//, printf( "2" );
+    // skip the choice if this is what is happening
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Make sure reprsentative nodes do not have representatives.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Aig_ManCheckReprs( Aig_Man_t * p )
+{
+    int fPrintConst = 0;
+    Aig_Obj_t * pObj;
+    int i, fProb = 0;
+    int Class0 = 0, ClassCi = 0;
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( Aig_ObjRepr(p, pObj) == NULL )
+            continue;
+        if ( !Aig_ObjIsNode(pObj) )
+            printf( "Obj %d is not an AND but it has a repr %d.\n", i, Aig_ObjId(Aig_ObjRepr(p, pObj)) ), fProb = 1;
+        else if ( Aig_ObjRepr(p, Aig_ObjRepr(p, pObj)) )
+            printf( "Obj %d has repr %d with a repr %d.\n", i, Aig_ObjId(Aig_ObjRepr(p, pObj)), Aig_ObjId(Aig_ObjRepr(p, Aig_ObjRepr(p, pObj))) ), fProb = 1;
+    }
+    if ( !fProb )
+        printf( "Representive verification successful.\n" );
+    else
+        printf( "Representive verification FAILED.\n" );
+    if ( !fPrintConst )
+        return;
+    // count how many representatives are const0 or a CI
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( Aig_ObjRepr(p, pObj) == Aig_ManConst1(p) )
+            Class0++;
+        if ( Aig_ObjRepr(p, pObj) && Aig_ObjIsCi(Aig_ObjRepr(p, pObj)) )
+            ClassCi++;
+    }
+    printf( "Const0 nodes = %d.  ConstCI nodes = %d.\n", Class0, ClassCi );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verify correctness of choices.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_CheckChoices( Aig_Man_t * p, int fSkipRedSupps )
+{
+    Aig_Obj_t * pObj;
+    int i, fProb = 0;
+    Aig_ManCleanMarkA( p );
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        if ( p->pEquivs[i] != NULL )
+        {
+            if ( pObj->fMarkA == 1 )
+                printf( "node %d participates in more than one choice class\n", i ), fProb = 1;
+            pObj->fMarkA = 1;
+            // check redundancy
+            if ( fSkipRedSupps && Dch_ObjCheckSuppRed( p, pObj, p->pEquivs[i]) )
+                printf( "node %d and repr %d have diff supports\n", pObj->Id, p->pEquivs[i]->Id );
+            // consider the next one
+            pObj = p->pEquivs[i];
+            if ( p->pEquivs[Aig_ObjId(pObj)] == NULL )
+            {
+                if ( pObj->fMarkA == 1 )
+                    printf( "repr %d has final node %d participates in more than one choice class\n", i, pObj->Id ), fProb = 1;
+                pObj->fMarkA = 1;
+            }
+            // consider the non-head ones
+            if ( pObj->nRefs > 0 )
+                printf( "node %d belonging to choice has fanout %d\n", pObj->Id, pObj->nRefs );
+        }
+        if ( p->pReprs && p->pReprs[i] != NULL )
+        {
+            if ( pObj->nRefs > 0 )
+                printf( "node %d has representative %d and fanout count %d\n", pObj->Id, p->pReprs[i]->Id, pObj->nRefs ), fProb = 1;
+        }
+    }
+    Aig_ManCleanMarkA( p );
+    if ( !fProb )
+        printf( "Verification of choice AIG succeeded.\n" );
+    else
+        printf( "Verification of choice AIG FAILED.\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks for combinational loops in the AIG.]
+
+  Description [Returns 1 if combinational loop is detected.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManCheckAcyclic_rec( Aig_Man_t * p, Aig_Obj_t * pNode, int fVerbose )
+{
+    Aig_Obj_t * pFanin;
+    int fAcyclic;
+    if ( Aig_ObjIsCi(pNode) || Aig_ObjIsConst1(pNode) )
+        return 1;
+    assert( Aig_ObjIsNode(pNode) );
+    // make sure the node is not visited
+    assert( !Aig_ObjIsTravIdPrevious(p, pNode) );
+    // check if the node is part of the combinational loop
+    if ( Aig_ObjIsTravIdCurrent(p, pNode) )
+    {
+        if ( fVerbose )
+            Abc_Print( 1, "Network \"%s\" contains combinational loop!\n", p->pSpec? p->pSpec : NULL );
+        if ( fVerbose )
+        Abc_Print( 1, "Node \"%d\" is encountered twice on the following path to the COs:\n", Aig_ObjId(pNode) );
+        return 0;
+    }
+    // mark this node as a node on the current path
+    Aig_ObjSetTravIdCurrent( p, pNode );
+
+    // visit the transitive fanin
+    pFanin = Aig_ObjFanin0(pNode);
+    // check if the fanin is visited
+    if ( !Aig_ObjIsTravIdPrevious(p, pFanin) ) 
+    {
+        // traverse the fanin's cone searching for the loop
+        if ( !(fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) )
+        {
+            // return as soon as the loop is detected
+            if ( fVerbose )
+            Abc_Print( 1, " %d ->", Aig_ObjId(pFanin) );
+            return 0;
+        }
+    }
+
+    // visit the transitive fanin
+    pFanin = Aig_ObjFanin1(pNode);
+    // check if the fanin is visited
+    if ( !Aig_ObjIsTravIdPrevious(p, pFanin) ) 
+    {
+        // traverse the fanin's cone searching for the loop
+        if ( !(fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) )
+        {
+            // return as soon as the loop is detected
+            if ( fVerbose )
+            Abc_Print( 1, " %d ->", Aig_ObjId(pFanin) );
+            return 0;
+        }
+    }
+
+    // visit choices
+    if ( Aig_ObjRepr(p, pNode) == NULL && Aig_ObjEquiv(p, pNode) != NULL )
+    {
+        for ( pFanin = Aig_ObjEquiv(p, pNode); pFanin; pFanin = Aig_ObjEquiv(p, pFanin) )
+        {
+            // check if the fanin is visited
+            if ( Aig_ObjIsTravIdPrevious(p, pFanin) ) 
+                continue;
+            // traverse the fanin's cone searching for the loop
+            if ( (fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) )
+                continue;
+            // return as soon as the loop is detected
+            if ( fVerbose )
+            Abc_Print( 1, " %d", Aig_ObjId(pFanin) );
+            if ( fVerbose )
+            Abc_Print( 1, " (choice of %d) -> ", Aig_ObjId(pNode) );
+            return 0;
+        }
+    }
+    // mark this node as a visited node
+    Aig_ObjSetTravIdPrevious( p, pNode );
+    return 1;
+}
+int Aig_ManCheckAcyclic( Aig_Man_t * p, int fVerbose )
+{
+    Aig_Obj_t * pNode;
+    int fAcyclic;
+    int i;
+    // set the traversal ID for this DFS ordering
+    Aig_ManIncrementTravId( p );   
+    Aig_ManIncrementTravId( p );   
+    // pNode->TravId == pNet->nTravIds      means "pNode is on the path"
+    // pNode->TravId == pNet->nTravIds - 1  means "pNode is visited but is not on the path"
+    // pNode->TravId <  pNet->nTravIds - 1  means "pNode is not visited"
+    // traverse the network to detect cycles
+    fAcyclic = 1;
+    Aig_ManForEachCo( p, pNode, i )
+    {
+        pNode = Aig_ObjFanin0(pNode);
+        if ( Aig_ObjIsTravIdPrevious(p, pNode) )
+            continue;
+        // traverse the output logic cone
+        if ( (fAcyclic = Aig_ManCheckAcyclic_rec(p, pNode, fVerbose)) )
+            continue;
+        // stop as soon as the first loop is detected
+        if ( fVerbose )
+        Abc_Print( 1, " CO %d\n", i );
+        break;
+    }
+    return fAcyclic;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the choice node of pRepr is in the TFI of pObj.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dch_ObjCheckTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    // check the trivial cases
+    if ( pObj == NULL )
+        return 0;
+    if ( Aig_ObjIsCi(pObj) )
+        return 0;
+    if ( pObj->fMarkA )
+        return 1;
+    // skip the visited node
+    if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
+        return 0;
+    Aig_ObjSetTravIdCurrent( p, pObj );
+    // check the children
+    if ( Dch_ObjCheckTfi_rec( p, Aig_ObjFanin0(pObj) ) )
+        return 1;
+    if ( Dch_ObjCheckTfi_rec( p, Aig_ObjFanin1(pObj) ) )
+        return 1;
+    // check equivalent nodes
+    return Dch_ObjCheckTfi_rec( p, Aig_ObjEquiv(p, pObj) );
+}
+int Dch_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr )
+{
+    Aig_Obj_t * pTemp;
+    int RetValue;
+    assert( !Aig_IsComplement(pObj) );
+    assert( !Aig_IsComplement(pRepr) );
+    // mark nodes of the choice node
+    for ( pTemp = pRepr; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) )
+        pTemp->fMarkA = 1;
+    // traverse the new node
+    Aig_ManIncrementTravId( p );
+    RetValue = Dch_ObjCheckTfi_rec( p, pObj );
+    // unmark nodes of the choice node
+    for ( pTemp = pRepr; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) )
+        pTemp->fMarkA = 0;
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns representatives of fanin in approapriate polarity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Aig_Obj_t * Aig_ObjGetRepr( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pRepr;
+    if ( (pRepr = Aig_ObjRepr(p, Aig_Regular(pObj))) )
+        return Aig_NotCond( pRepr, Aig_Regular(pObj)->fPhase ^ pRepr->fPhase ^ Aig_IsComplement(pObj) );
+    return pObj;
+}
+static inline Aig_Obj_t * Aig_ObjChild0CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild0Copy(pObj) ); }
+static inline Aig_Obj_t * Aig_ObjChild1CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild1Copy(pObj) ); }
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the AIG with choices from representatives.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_DeriveChoiceAigNode( Aig_Man_t * pAigNew, Aig_Man_t * pAigOld, Aig_Obj_t * pObj, int fSkipRedSupps )
+{
+    Aig_Obj_t * pRepr, * pObjNew, * pReprNew;
+    assert( !Aig_IsComplement(pObj) );
+    // get the representative
+    pRepr = Aig_ObjRepr( pAigOld, pObj );
+    if ( pRepr != NULL && (Aig_ObjIsConst1(pRepr) || Aig_ObjIsCi(pRepr)) )
+    {
+        assert( pRepr->pData != NULL );
+        pObj->pData = Aig_NotCond( (Aig_Obj_t *)pRepr->pData, pObj->fPhase ^ pRepr->fPhase );
+        return;
+    }
+    // get the new node
+    pObjNew = Aig_And( pAigNew, 
+        Aig_ObjChild0CopyRepr(pAigNew, pObj), 
+        Aig_ObjChild1CopyRepr(pAigNew, pObj) );
+    pObjNew = Aig_ObjGetRepr( pAigNew, pObjNew );
+//    assert( Aig_ObjRepr( pAigNew, pObjNew ) == NULL );
+    // assign the copy
+    assert( pObj->pData == NULL );
+    pObj->pData = pObjNew;
+    // skip those without reprs
+    if ( pRepr == NULL )
+        return;
+    assert( pRepr->Id < pObj->Id );
+    assert( Aig_ObjIsNode(pRepr) );
+    // get the corresponding new nodes
+    pObjNew  = Aig_Regular((Aig_Obj_t *)pObj->pData);
+    pReprNew = Aig_Regular((Aig_Obj_t *)pRepr->pData);
+    // skip earlier nodes
+    if ( pReprNew->Id >= pObjNew->Id )
+        return;
+    assert( pReprNew->Id < pObjNew->Id );
+    // set the representatives
+    Aig_ObjSetRepr( pAigNew, pObjNew, pReprNew );
+    // skip used nodes
+    if ( pObjNew->nRefs > 0 )
+        return;
+    assert( pObjNew->nRefs == 0 );
+    // skip choices that can lead to combo loops
+    if ( Dch_ObjCheckTfi( pAigNew, pObjNew, pReprNew ) )
+        return;
+    // don't add choice if structural support of pObjNew and pReprNew differ
+    if ( fSkipRedSupps && Dch_ObjCheckSuppRed(pAigNew, pObjNew, pReprNew) )
+        return;
+    // add choice to the end of the list
+    while ( pAigNew->pEquivs[pReprNew->Id] != NULL )
+        pReprNew = pAigNew->pEquivs[pReprNew->Id];
+    assert( pAigNew->pEquivs[pReprNew->Id] == NULL );
+    pAigNew->pEquivs[pReprNew->Id] = pObjNew;
+}
+Aig_Man_t * Dch_DeriveChoiceAigInt( Aig_Man_t * pAig, int fSkipRedSupps )
+{
+    Aig_Man_t * pChoices;
+    Aig_Obj_t * pObj;
+    int i;
+    // start recording equivalences
+    pChoices = Aig_ManStart( Aig_ManObjNumMax(pAig) );
+    pChoices->pEquivs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
+    pChoices->pReprs  = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
+    // map constants and PIs
+    Aig_ManCleanData( pAig );
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1(pChoices);
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pChoices );
+    // construct choices for the internal nodes
+    assert( pAig->pReprs != NULL );
+    Aig_ManForEachNode( pAig, pObj, i ) 
+        Dch_DeriveChoiceAigNode( pChoices, pAig, pObj, fSkipRedSupps );
+    Aig_ManForEachCo( pAig, pObj, i )
+        Aig_ObjCreateCo( pChoices, Aig_ObjChild0CopyRepr(pChoices, pObj) );
+    Aig_ManSetRegNum( pChoices, Aig_ManRegNum(pAig) );
+    return pChoices;
+}
+Aig_Man_t * Dch_DeriveChoiceAig( Aig_Man_t * pAig, int fSkipRedSupps )
+{
+    int fCheck = 0;
+    Aig_Man_t * pChoices, * pTemp;
+    // verify
+    if ( fCheck )
+        Aig_ManCheckReprs( pAig ); 
+    // compute choices
+    pChoices = Dch_DeriveChoiceAigInt( pAig, fSkipRedSupps );
+    ABC_FREE( pChoices->pReprs );
+    // verify
+    if ( fCheck )
+        Dch_CheckChoices( pChoices, fSkipRedSupps ); 
+    // find correct topo order with choices
+    pChoices = Aig_ManDupDfs( pTemp = pChoices );
+    Aig_ManStop( pTemp );
+    // verify
+    if ( fCheck )
+        Dch_CheckChoices( pChoices, fSkipRedSupps ); 
+    return pChoices;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/dch/dchClass.c b/abc-build/src/proof/dch/dchClass.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/dch/dchClass.c
@@ -0,0 +1,611 @@
+/**CFile****************************************************************
+
+  FileName    [dchClass.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Choice computation for tech-mapping.]
+
+  Synopsis    [Representation of candidate equivalence classes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: dchClass.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+    The candidate equivalence classes are stored as a vector of pointers 
+    to the array of pointers to the nodes in each class.
+    The first node of the class is its representative node.
+    The representative has the smallest topological order among the class nodes.
+    The nodes inside each class are ordered according to their topological order.
+    The classes are ordered according to the topo order of their representatives.
+*/
+
+// internal representation of candidate equivalence classes
+struct Dch_Cla_t_
+{
+    // class information
+    Aig_Man_t *      pAig;             // original AIG manager
+    Aig_Obj_t ***    pId2Class;        // non-const classes by ID of repr node
+    int *            pClassSizes;      // sizes of each equivalence class
+    // statistics
+    int              nClasses;         // the total number of non-const classes
+    int              nCands1;          // the total number of const candidates
+    int              nLits;            // the number of literals in all classes
+    // memory
+    Aig_Obj_t **     pMemClasses;      // memory allocated for equivalence classes
+    Aig_Obj_t **     pMemClassesFree;  // memory allocated for equivalence classes to be used
+    // temporary data
+    Vec_Ptr_t *      vClassOld;        // old equivalence class after splitting
+    Vec_Ptr_t *      vClassNew;        // new equivalence class(es) after splitting
+    // procedures used for class refinement
+    void *           pManData;
+    unsigned (*pFuncNodeHash) (void *,Aig_Obj_t *);              // returns hash key of the node
+    int (*pFuncNodeIsConst)   (void *,Aig_Obj_t *);              // returns 1 if the node is a constant
+    int (*pFuncNodesAreEqual) (void *,Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement
+};
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline Aig_Obj_t *  Dch_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj )                       { return ppNexts[pObj->Id];  }
+static inline void         Dch_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; }
+
+// iterator through the equivalence classes
+#define Dch_ManForEachClass( p, ppClass, i )                 \
+    for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ )        \
+        if ( ((ppClass) = p->pId2Class[i]) == NULL ) {} else
+// iterator through the nodes in one class
+#define Dch_ClassForEachNode( p, pRepr, pNode, i )           \
+    for ( i = 0; i < p->pClassSizes[pRepr->Id]; i++ )        \
+        if ( ((pNode) = p->pId2Class[pRepr->Id][i]) == NULL ) {} else
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates one equivalence class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Dch_ObjAddClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Aig_Obj_t ** pClass, int nSize ) 
+{
+    assert( p->pId2Class[pRepr->Id] == NULL );
+    p->pId2Class[pRepr->Id] = pClass; 
+    assert( p->pClassSizes[pRepr->Id] == 0 );
+    assert( nSize > 1 );
+    p->pClassSizes[pRepr->Id] = nSize;
+    p->nClasses++;
+    p->nLits += nSize - 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes one equivalence class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Aig_Obj_t ** Dch_ObjRemoveClass( Dch_Cla_t * p, Aig_Obj_t * pRepr ) 
+{
+    Aig_Obj_t ** pClass = p->pId2Class[pRepr->Id];
+    int nSize;
+    assert( pClass != NULL );
+    p->pId2Class[pRepr->Id] = NULL; 
+    nSize = p->pClassSizes[pRepr->Id];
+    assert( nSize > 1 );
+    p->nClasses--;
+    p->nLits -= nSize - 1;
+    p->pClassSizes[pRepr->Id] = 0;
+    return pClass;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts representation of equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dch_Cla_t * Dch_ClassesStart( Aig_Man_t * pAig )
+{
+    Dch_Cla_t * p;
+    p = ABC_ALLOC( Dch_Cla_t, 1 );
+    memset( p, 0, sizeof(Dch_Cla_t) );
+    p->pAig         = pAig;
+    p->pId2Class    = ABC_CALLOC( Aig_Obj_t **, Aig_ManObjNumMax(pAig) );
+    p->pClassSizes  = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+    p->vClassOld    = Vec_PtrAlloc( 100 );
+    p->vClassNew    = Vec_PtrAlloc( 100 );
+    assert( pAig->pReprs == NULL );
+    Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts representation of equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ClassesSetData( Dch_Cla_t * p, void * pManData, 
+    unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *),               // returns hash key of the node
+    int (*pFuncNodeIsConst)(void *,Aig_Obj_t *),                 // returns 1 if the node is a constant
+    int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ) // returns 1 if nodes are equal up to a complement
+{
+    p->pManData           = pManData;
+    p->pFuncNodeHash      = pFuncNodeHash;
+    p->pFuncNodeIsConst   = pFuncNodeIsConst;
+    p->pFuncNodesAreEqual = pFuncNodesAreEqual;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop representation of equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ClassesStop( Dch_Cla_t * p )
+{
+    if ( p->vClassNew )    Vec_PtrFree( p->vClassNew );
+    if ( p->vClassOld )    Vec_PtrFree( p->vClassOld );
+    ABC_FREE( p->pId2Class );
+    ABC_FREE( p->pClassSizes );
+    ABC_FREE( p->pMemClasses );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop representation of equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dch_ClassesLitNum( Dch_Cla_t * p )
+{
+    return p->nLits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop representation of equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t ** Dch_ClassesReadClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize )
+{
+    assert( p->pId2Class[pRepr->Id] != NULL );
+    assert( p->pClassSizes[pRepr->Id] > 1 );
+    *pnSize = p->pClassSizes[pRepr->Id];
+    return p->pId2Class[pRepr->Id];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks candidate equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ClassesCheck( Dch_Cla_t * p )
+{
+    Aig_Obj_t * pObj, * pPrev, ** ppClass;
+    int i, k, nLits, nClasses, nCands1;
+    nClasses = nLits = 0;
+    Dch_ManForEachClass( p, ppClass, k )
+    {
+        pPrev = NULL;
+        Dch_ClassForEachNode( p, ppClass[0], pObj, i )
+        {
+            if ( i == 0 )
+                assert( Aig_ObjRepr(p->pAig, pObj) == NULL );
+            else
+            {
+                assert( Aig_ObjRepr(p->pAig, pObj) == ppClass[0] );
+                assert( pPrev->Id < pObj->Id );
+                nLits++;
+            }
+            pPrev = pObj;
+        }
+        nClasses++;
+    }
+    nCands1 = 0;
+    Aig_ManForEachObj( p->pAig, pObj, i )
+        nCands1 += Dch_ObjIsConst1Cand( p->pAig, pObj );
+    assert( p->nLits == nLits );
+    assert( p->nCands1 == nCands1 );
+    assert( p->nClasses == nClasses );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints simulation classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ClassesPrintOne( Dch_Cla_t * p, Aig_Obj_t * pRepr )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Abc_Print( 1, "{ " );
+    Dch_ClassForEachNode( p, pRepr, pObj, i )
+        Abc_Print( 1, "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) );
+    Abc_Print( 1, "}\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints simulation classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ClassesPrint( Dch_Cla_t * p, int fVeryVerbose )
+{
+    Aig_Obj_t ** ppClass;
+    Aig_Obj_t * pObj;
+    int i;
+    Abc_Print( 1, "Equivalence classes: Const1 = %5d. Class = %5d. Lit = %5d.\n", 
+        p->nCands1, p->nClasses, p->nLits );
+    if ( !fVeryVerbose )
+        return;
+    Abc_Print( 1, "Constants { " );
+    Aig_ManForEachObj( p->pAig, pObj, i )
+        if ( Dch_ObjIsConst1Cand( p->pAig, pObj ) )
+            Abc_Print( 1, "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) );
+    Abc_Print( 1, "}\n" );
+    Dch_ManForEachClass( p, ppClass, i )
+    {
+        Abc_Print( 1, "%3d (%3d) : ", i, p->pClassSizes[i] );
+        Dch_ClassesPrintOne( p, ppClass[0] );
+    }
+    Abc_Print( 1, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates initial simulation classes.]
+
+  Description [Assumes that simulation info is assigned.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ClassesPrepare( Dch_Cla_t * p, int fLatchCorr, int nMaxLevs )
+{
+    Aig_Obj_t ** ppTable, ** ppNexts, ** ppClassNew;
+    Aig_Obj_t * pObj, * pTemp, * pRepr;
+    int i, k, nTableSize, nNodes, iEntry, nEntries, nEntries2;
+
+    // allocate the hash table hashing simulation info into nodes
+    nTableSize = Abc_PrimeCudd( Aig_ManObjNumMax(p->pAig)/4 );
+    ppTable = ABC_CALLOC( Aig_Obj_t *, nTableSize ); 
+    ppNexts = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) ); 
+
+    // add all the nodes to the hash table
+    nEntries = 0;
+    Aig_ManForEachObj( p->pAig, pObj, i )
+    {
+        if ( fLatchCorr )
+        {
+            if ( !Aig_ObjIsCi(pObj) )
+                continue;
+        }
+        else
+        {
+            if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
+                continue;
+            // skip the node with more that the given number of levels
+            if ( nMaxLevs && (int)pObj->Level >= nMaxLevs )
+                continue;
+        }
+        // check if the node belongs to the class of constant 1
+        if ( p->pFuncNodeIsConst( p->pManData, pObj ) )
+        {
+            Dch_ObjSetConst1Cand( p->pAig, pObj );
+            p->nCands1++;
+            continue;
+        }
+        // hash the node by its simulation info
+        iEntry = p->pFuncNodeHash( p->pManData, pObj ) % nTableSize;
+        // add the node to the class
+        if ( ppTable[iEntry] == NULL )
+            ppTable[iEntry] = pObj;
+        else
+        {
+            // set the representative of this node
+            pRepr = ppTable[iEntry];
+            Aig_ObjSetRepr( p->pAig, pObj, pRepr );
+            // add node to the table
+            if ( Dch_ObjNext( ppNexts, pRepr ) == NULL )
+            { // this will be the second entry
+                p->pClassSizes[pRepr->Id]++;
+                nEntries++;
+            }
+            // add the entry to the list
+            Dch_ObjSetNext( ppNexts, pObj, Dch_ObjNext( ppNexts, pRepr ) );
+            Dch_ObjSetNext( ppNexts, pRepr, pObj );
+            p->pClassSizes[pRepr->Id]++;
+            nEntries++;
+        }
+    }
+
+    // allocate room for classes
+    p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, nEntries + p->nCands1 );
+    p->pMemClassesFree = p->pMemClasses + nEntries;
+ 
+    // copy the entries into storage in the topological order
+    nEntries2 = 0;
+    Aig_ManForEachObj( p->pAig, pObj, i )
+    {
+        if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
+            continue;
+        nNodes = p->pClassSizes[pObj->Id];
+        // skip the nodes that are not representatives of non-trivial classes
+        if ( nNodes == 0 )
+            continue;
+        assert( nNodes > 1 );
+        // add the nodes to the class in the topological order
+        ppClassNew = p->pMemClasses + nEntries2;
+        ppClassNew[0] = pObj;
+        for ( pTemp = Dch_ObjNext(ppNexts, pObj), k = 1; pTemp; 
+              pTemp = Dch_ObjNext(ppNexts, pTemp), k++ )
+        {
+            ppClassNew[nNodes-k] = pTemp;
+        }
+        // add the class of nodes
+        p->pClassSizes[pObj->Id] = 0;
+        Dch_ObjAddClass( p, pObj, ppClassNew, nNodes );
+        // increment the number of entries
+        nEntries2 += nNodes;
+    }
+    assert( nEntries == nEntries2 );
+    ABC_FREE( ppTable );
+    ABC_FREE( ppNexts );
+    // now it is time to refine the classes
+    Dch_ClassesRefine( p );
+    Dch_ClassesCheck( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Iteratively refines the classes after simulation.]
+
+  Description [Returns the number of refinements performed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dch_ClassesRefineOneClass( Dch_Cla_t * p, Aig_Obj_t * pReprOld, int fRecursive )
+{
+    Aig_Obj_t ** pClassOld, ** pClassNew;
+    Aig_Obj_t * pObj, * pReprNew;
+    int i;
+
+    // split the class
+    Vec_PtrClear( p->vClassOld );
+    Vec_PtrClear( p->vClassNew );
+    Dch_ClassForEachNode( p, pReprOld, pObj, i )
+        if ( p->pFuncNodesAreEqual(p->pManData, pReprOld, pObj) )
+            Vec_PtrPush( p->vClassOld, pObj );
+        else
+            Vec_PtrPush( p->vClassNew, pObj );
+    // check if splitting happened
+    if ( Vec_PtrSize(p->vClassNew) == 0 )
+        return 0;
+
+    // get the new representative
+    pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 );
+    assert( Vec_PtrSize(p->vClassOld) > 0 );
+    assert( Vec_PtrSize(p->vClassNew) > 0 );
+
+    // create old class
+    pClassOld = Dch_ObjRemoveClass( p, pReprOld );
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i )
+    {
+        pClassOld[i] = pObj;
+        Aig_ObjSetRepr( p->pAig, pObj, i? pReprOld : NULL );
+    }
+    // create new class
+    pClassNew = pClassOld + i;
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+    {
+        pClassNew[i] = pObj;
+        Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL );
+    }
+
+    // put classes back
+    if ( Vec_PtrSize(p->vClassOld) > 1 )
+        Dch_ObjAddClass( p, pReprOld, pClassOld, Vec_PtrSize(p->vClassOld) );
+    if ( Vec_PtrSize(p->vClassNew) > 1 )
+        Dch_ObjAddClass( p, pReprNew, pClassNew, Vec_PtrSize(p->vClassNew) );
+
+    // check if the class should be recursively refined
+    if ( fRecursive && Vec_PtrSize(p->vClassNew) > 1 )
+        return 1 + Dch_ClassesRefineOneClass( p, pReprNew, 1 );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines the classes after simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dch_ClassesRefine( Dch_Cla_t * p )
+{
+    Aig_Obj_t ** ppClass;
+    int i, nRefis = 0;
+    Dch_ManForEachClass( p, ppClass, i )
+        nRefis += Dch_ClassesRefineOneClass( p, ppClass[0], 0 );
+    return nRefis;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns equivalence class of the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ClassesCollectOneClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vRoots )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Vec_PtrClear( vRoots );
+    Dch_ClassForEachNode( p, pRepr, pObj, i )
+        Vec_PtrPush( vRoots, pObj );
+    assert( Vec_PtrSize(vRoots) > 1 ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns equivalence class of the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ClassesCollectConst1Group( Dch_Cla_t * p, Aig_Obj_t * pObj, int nNodes, Vec_Ptr_t * vRoots )
+{
+    int i, Limit;
+    Vec_PtrClear( vRoots );
+    Limit = Abc_MinInt( pObj->Id + nNodes, Aig_ManObjNumMax(p->pAig) );
+    for ( i = pObj->Id; i < Limit; i++ )
+    {
+        pObj = Aig_ManObj( p->pAig, i );
+        if ( pObj && Dch_ObjIsConst1Cand( p->pAig, pObj ) )
+            Vec_PtrPush( vRoots, pObj );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refine the group of constant 1 nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dch_ClassesRefineConst1Group( Dch_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive )
+{
+    Aig_Obj_t * pObj, * pReprNew, ** ppClassNew;
+    int i;
+    if ( Vec_PtrSize(vRoots) == 0 )
+        return 0;
+    // collect the nodes to be refined
+    Vec_PtrClear( p->vClassNew );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i )
+        if ( !p->pFuncNodeIsConst( p->pManData, pObj ) )
+            Vec_PtrPush( p->vClassNew, pObj );
+    // check if there is a new class
+    if ( Vec_PtrSize(p->vClassNew) == 0 )
+        return 0;
+    p->nCands1 -= Vec_PtrSize(p->vClassNew);
+    pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 );
+    Aig_ObjSetRepr( p->pAig, pReprNew, NULL );
+    if ( Vec_PtrSize(p->vClassNew) == 1 )
+        return 1;
+    // create a new class composed of these nodes
+    ppClassNew = p->pMemClassesFree;
+    p->pMemClassesFree += Vec_PtrSize(p->vClassNew);
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+    {
+        ppClassNew[i] = pObj;
+        Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL );
+    }
+    Dch_ObjAddClass( p, pReprNew, ppClassNew, Vec_PtrSize(p->vClassNew) );
+    // refine them recursively
+    if ( fRecursive )
+        return 1 + Dch_ClassesRefineOneClass( p, pReprNew, 1 );
+    return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/dch/dchCnf.c b/abc-build/src/proof/dch/dchCnf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/dch/dchCnf.c
@@ -0,0 +1,334 @@
+/**CFile****************************************************************
+
+  FileName    [dchCnf.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Choice computation for tech-mapping.]
+
+  Synopsis    [Computation of CNF.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: dchCnf.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Addes clauses to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_AddClausesMux( Dch_Man_t * p, Aig_Obj_t * pNode )
+{
+    Aig_Obj_t * pNodeI, * pNodeT, * pNodeE;
+    int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE;
+
+    assert( !Aig_IsComplement( pNode ) );
+    assert( Aig_ObjIsMuxType( pNode ) );
+    // get nodes (I = if, T = then, E = else)
+    pNodeI = Aig_ObjRecognizeMux( pNode, &pNodeT, &pNodeE );
+    // get the variable numbers
+    VarF = Dch_ObjSatNum(p,pNode);
+    VarI = Dch_ObjSatNum(p,pNodeI);
+    VarT = Dch_ObjSatNum(p,Aig_Regular(pNodeT));
+    VarE = Dch_ObjSatNum(p,Aig_Regular(pNodeE));
+    // get the complementation flags
+    fCompT = Aig_IsComplement(pNodeT);
+    fCompE = Aig_IsComplement(pNodeE);
+
+    // f = ITE(i, t, e)
+
+    // i' + t' + f
+    // i' + t  + f'
+    // i  + e' + f
+    // i  + e  + f'
+
+    // create four clauses
+    pLits[0] = toLitCond(VarI, 1);
+    pLits[1] = toLitCond(VarT, 1^fCompT);
+    pLits[2] = toLitCond(VarF, 0);
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( pNodeI->fPhase )               pLits[0] = lit_neg( pLits[0] );
+        if ( Aig_Regular(pNodeT)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarI, 1);
+    pLits[1] = toLitCond(VarT, 0^fCompT);
+    pLits[2] = toLitCond(VarF, 1);
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( pNodeI->fPhase )               pLits[0] = lit_neg( pLits[0] );
+        if ( Aig_Regular(pNodeT)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarI, 0);
+    pLits[1] = toLitCond(VarE, 1^fCompE);
+    pLits[2] = toLitCond(VarF, 0);
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( pNodeI->fPhase )               pLits[0] = lit_neg( pLits[0] );
+        if ( Aig_Regular(pNodeE)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarI, 0);
+    pLits[1] = toLitCond(VarE, 0^fCompE);
+    pLits[2] = toLitCond(VarF, 1);
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( pNodeI->fPhase )               pLits[0] = lit_neg( pLits[0] );
+        if ( Aig_Regular(pNodeE)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+
+    // two additional clauses
+    // t' & e' -> f'
+    // t  & e  -> f 
+
+    // t  + e   + f'
+    // t' + e'  + f 
+
+    if ( VarT == VarE )
+    {
+//        assert( fCompT == !fCompE );
+        return;
+    }
+
+    pLits[0] = toLitCond(VarT, 0^fCompT);
+    pLits[1] = toLitCond(VarE, 0^fCompE);
+    pLits[2] = toLitCond(VarF, 1);
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( Aig_Regular(pNodeT)->fPhase )  pLits[0] = lit_neg( pLits[0] );
+        if ( Aig_Regular(pNodeE)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarT, 1^fCompT);
+    pLits[1] = toLitCond(VarE, 1^fCompE);
+    pLits[2] = toLitCond(VarF, 0);
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( Aig_Regular(pNodeT)->fPhase )  pLits[0] = lit_neg( pLits[0] );
+        if ( Aig_Regular(pNodeE)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Addes clauses to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_AddClausesSuper( Dch_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vSuper )
+{
+    Aig_Obj_t * pFanin;
+    int * pLits, nLits, RetValue, i;
+    assert( !Aig_IsComplement(pNode) );
+    assert( Aig_ObjIsNode( pNode ) );
+    // create storage for literals
+    nLits = Vec_PtrSize(vSuper) + 1;
+    pLits = ABC_ALLOC( int, nLits );
+    // suppose AND-gate is A & B = C
+    // add !A => !C   or   A + !C
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i )
+    {
+        pLits[0] = toLitCond(Dch_ObjSatNum(p,Aig_Regular(pFanin)), Aig_IsComplement(pFanin));
+        pLits[1] = toLitCond(Dch_ObjSatNum(p,pNode), 1);
+        if ( p->pPars->fPolarFlip )
+        {
+            if ( Aig_Regular(pFanin)->fPhase )  pLits[0] = lit_neg( pLits[0] );
+            if ( pNode->fPhase )                pLits[1] = lit_neg( pLits[1] );
+        }
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+    }
+    // add A & B => C   or   !A + !B + C
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i )
+    {
+        pLits[i] = toLitCond(Dch_ObjSatNum(p,Aig_Regular(pFanin)), !Aig_IsComplement(pFanin));
+        if ( p->pPars->fPolarFlip )
+        {
+            if ( Aig_Regular(pFanin)->fPhase )  pLits[i] = lit_neg( pLits[i] );
+        }
+    }
+    pLits[nLits-1] = toLitCond(Dch_ObjSatNum(p,pNode), 0);
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( pNode->fPhase )  pLits[nLits-1] = lit_neg( pLits[nLits-1] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits );
+    assert( RetValue );
+    ABC_FREE( pLits );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_CollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes )
+{
+    // if the new node is complemented or a PI, another gate begins
+    if ( Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) || 
+         (!fFirst && Aig_ObjRefs(pObj) > 1) || 
+         (fUseMuxes && Aig_ObjIsMuxType(pObj)) )
+    {
+        Vec_PtrPushUnique( vSuper, pObj );
+        return;
+    }
+    // go through the branches
+    Dch_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes );
+    Dch_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper )
+{
+    assert( !Aig_IsComplement(pObj) );
+    assert( !Aig_ObjIsCi(pObj) );
+    Vec_PtrClear( vSuper );
+    Dch_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the solver clause database.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ObjAddToFrontier( Dch_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier )
+{
+    assert( !Aig_IsComplement(pObj) );
+    if ( Dch_ObjSatNum(p,pObj) )
+        return;
+    assert( Dch_ObjSatNum(p,pObj) == 0 );
+    if ( Aig_ObjIsConst1(pObj) )
+        return;
+    Vec_PtrPush( p->vUsedNodes, pObj );
+    Dch_ObjSetSatNum( p, pObj, p->nSatVars++ );
+    if ( Aig_ObjIsNode(pObj) )
+        Vec_PtrPush( vFrontier, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the solver clause database.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_CnfNodeAddToSolver( Dch_Man_t * p, Aig_Obj_t * pObj )
+{ 
+    Vec_Ptr_t * vFrontier;
+    Aig_Obj_t * pNode, * pFanin;
+    int i, k, fUseMuxes = 1;
+    // quit if CNF is ready
+    if ( Dch_ObjSatNum(p,pObj) )
+        return;
+    // start the frontier
+    vFrontier = Vec_PtrAlloc( 100 );
+    Dch_ObjAddToFrontier( p, pObj, vFrontier );
+    // explore nodes in the frontier
+    Vec_PtrForEachEntry( Aig_Obj_t *, vFrontier, pNode, i )
+    {
+        // create the supergate
+        assert( Dch_ObjSatNum(p,pNode) );
+        if ( fUseMuxes && Aig_ObjIsMuxType(pNode) )
+        {
+            Vec_PtrClear( p->vFanins );
+            Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) );
+            Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) );
+            Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) );
+            Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) );
+            Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k )
+                Dch_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier );
+            Dch_AddClausesMux( p, pNode );
+        }
+        else
+        {
+            Dch_CollectSuper( pNode, fUseMuxes, p->vFanins );
+            Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k )
+                Dch_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier );
+            Dch_AddClausesSuper( p, pNode, p->vFanins );
+        }
+        assert( Vec_PtrSize(p->vFanins) > 1 );
+    }
+    Vec_PtrFree( vFrontier );
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/dch/dchCore.c b/abc-build/src/proof/dch/dchCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/dch/dchCore.c
@@ -0,0 +1,161 @@
+/**CFile****************************************************************
+
+  FileName    [dchCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Choice computation for tech-mapping.]
+
+  Synopsis    [The core procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: dchCore.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ManSetDefaultParams( Dch_Pars_t * p )
+{
+    memset( p, 0, sizeof(Dch_Pars_t) );
+    p->nWords         =     8;  // the number of simulation words
+    p->nBTLimit       =  1000;  // conflict limit at a node
+    p->nSatVarMax     =  5000;  // the max number of SAT variables
+    p->fSynthesis     =     1;  // derives three snapshots
+    p->fPolarFlip     =     1;  // uses polarity adjustment
+    p->fSimulateTfo   =     1;  // simulate TFO
+    p->fPower         =     0;  // power-aware rewriting
+    p->fLightSynth    =     0;  // uses lighter version of synthesis
+    p->fSkipRedSupp   =     0;  // skips choices with redundant structural support
+    p->fVerbose       =     0;  // verbose stats
+    p->nNodesAhead    =  1000;  // the lookahead in terms of nodes
+    p->nCallsRecycle  =   100;  // calls to perform before recycling SAT solver
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns verbose parameter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dch_ManReadVerbose( Dch_Pars_t * p )
+{
+    return p->fVerbose;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs computation of AIGs with choices.]
+
+  Description [Takes several AIGs and performs choicing.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars )
+{
+    Dch_Man_t * p;
+    Aig_Man_t * pResult;
+    abctime clk, clkTotal = Abc_Clock();
+    // reset random numbers
+    Aig_ManRandom(1);
+    // start the choicing manager
+    p = Dch_ManCreate( pAig, pPars );
+    // compute candidate equivalence classes
+clk = Abc_Clock(); 
+    p->ppClasses = Dch_CreateCandEquivClasses( pAig, pPars->nWords, pPars->fVerbose );
+p->timeSimInit = Abc_Clock() - clk;
+//    Dch_ClassesPrint( p->ppClasses, 0 );
+    p->nLits = Dch_ClassesLitNum( p->ppClasses );
+    // perform SAT sweeping
+    Dch_ManSweep( p );
+    // free memory ahead of time
+p->timeTotal = Abc_Clock() - clkTotal;
+    Dch_ManStop( p );
+    // create choices
+    ABC_FREE( pAig->pTable );
+    pResult = Dch_DeriveChoiceAig( pAig, pPars->fSkipRedSupp );
+    // count the number of representatives
+    if ( pPars->fVerbose ) 
+        Abc_Print( 1, "STATS:  Ands:%8d  ->%8d.  Reprs:%7d  ->%7d.  Choices =%7d.\n", 
+               Aig_ManNodeNum(pAig), 
+               Aig_ManNodeNum(pResult), 
+               Dch_DeriveChoiceCountReprs( pAig ),
+               Dch_DeriveChoiceCountEquivs( pResult ),
+               Aig_ManChoiceNum( pResult ) );
+    return pResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs computation of AIGs with choices.]
+
+  Description [Takes several AIGs and performs choicing.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ComputeEquivalences( Aig_Man_t * pAig, Dch_Pars_t * pPars )
+{
+    Dch_Man_t * p;
+    abctime clk, clkTotal = Abc_Clock();
+    // reset random numbers
+    Aig_ManRandom(1);
+    // start the choicing manager
+    p = Dch_ManCreate( pAig, pPars );
+    // compute candidate equivalence classes
+clk = Abc_Clock(); 
+    p->ppClasses = Dch_CreateCandEquivClasses( pAig, pPars->nWords, pPars->fVerbose );
+p->timeSimInit = Abc_Clock() - clk;
+//    Dch_ClassesPrint( p->ppClasses, 0 );
+    p->nLits = Dch_ClassesLitNum( p->ppClasses );
+    // perform SAT sweeping
+    Dch_ManSweep( p );
+    // free memory ahead of time
+p->timeTotal = Abc_Clock() - clkTotal;
+    Dch_ManStop( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/dch/dchInt.h b/abc-build/src/proof/dch/dchInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/dch/dchInt.h
@@ -0,0 +1,170 @@
+/**CFile****************************************************************
+
+  FileName    [dchInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Choice computation for tech-mapping.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: dchInt.h,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__dch__dchInt_h
+#define ABC__aig__dch__dchInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "aig/aig/aig.h"
+#include "sat/bsat/satSolver.h"
+#include "dch.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// equivalence classes
+typedef struct Dch_Cla_t_ Dch_Cla_t;
+
+// choicing manager
+typedef struct Dch_Man_t_ Dch_Man_t;
+struct Dch_Man_t_
+{
+    // parameters
+    Dch_Pars_t *     pPars;          // choicing parameters
+    // AIGs used in the package
+//    Vec_Ptr_t *      vAigs;          // user-given AIGs
+    Aig_Man_t *      pAigTotal;      // intermediate AIG
+    Aig_Man_t *      pAigFraig;      // final AIG
+    // equivalence classes
+    Dch_Cla_t *      ppClasses;      // equivalence classes of nodes
+    Aig_Obj_t **     pReprsProved;   // equivalences proved
+    // SAT solving
+    sat_solver *     pSat;           // recyclable SAT solver
+    int              nSatVars;       // the counter of SAT variables
+    int *            pSatVars;       // mapping of each node into its SAT var
+    Vec_Ptr_t *      vUsedNodes;     // nodes whose SAT vars are assigned
+    int              nRecycles;      // the number of times SAT solver was recycled
+    int              nCallsSince;    // the number of calls since the last recycle
+    Vec_Ptr_t *      vFanins;        // fanins of the CNF node
+    Vec_Ptr_t *      vSimRoots;      // the roots of cand const 1 nodes to simulate
+    Vec_Ptr_t *      vSimClasses;    // the roots of cand equiv classes to simulate
+    // solver cone size
+    int              nConeThis;
+    int              nConeMax;
+    // SAT calls statistics
+    int              nSatCalls;      // the number of SAT calls
+    int              nSatProof;      // the number of proofs
+    int              nSatFailsReal;  // the number of timeouts
+    int              nSatCallsUnsat; // the number of unsat SAT calls
+    int              nSatCallsSat;   // the number of sat SAT calls
+    // choice node statistics
+    int              nLits;          // the number of lits in the cand equiv classes
+    int              nReprs;         // the number of proved equivalent pairs
+    int              nEquivs;        // the number of final equivalences
+    int              nChoices;       // the number of final choice nodes
+    // runtime stats
+    abctime          timeSimInit;    // simulation and class computation
+    abctime          timeSimSat;     // simulation of the counter-examples
+    abctime          timeSat;        // solving SAT
+    abctime          timeSatSat;     // sat
+    abctime          timeSatUnsat;   // unsat
+    abctime          timeSatUndec;   // undecided
+    abctime          timeChoice;     // choice computation
+    abctime          timeOther;      // other runtime
+    abctime          timeTotal;      // total runtime
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int  Dch_ObjSatNum( Dch_Man_t * p, Aig_Obj_t * pObj )             { return p->pSatVars[pObj->Id]; }
+static inline void Dch_ObjSetSatNum( Dch_Man_t * p, Aig_Obj_t * pObj, int Num ) { p->pSatVars[pObj->Id] = Num;  }
+
+static inline Aig_Obj_t * Dch_ObjFraig( Aig_Obj_t * pObj )                       { return (Aig_Obj_t *)pObj->pData;  }
+static inline void        Dch_ObjSetFraig( Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { pObj->pData = pNode; }
+
+static inline int  Dch_ObjIsConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) 
+{
+    return Aig_ObjRepr(pAig, pObj) == Aig_ManConst1(pAig);
+}
+static inline void Dch_ObjSetConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) 
+{
+    assert( !Dch_ObjIsConst1Cand( pAig, pObj ) );
+    Aig_ObjSetRepr( pAig, pObj, Aig_ManConst1(pAig) );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== dchAig.c ===================================================*/
+/*=== dchChoice.c ===================================================*/
+extern int           Dch_DeriveChoiceCountReprs( Aig_Man_t * pAig );
+extern int           Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig );
+extern Aig_Man_t *   Dch_DeriveChoiceAig( Aig_Man_t * pAig, int fSkipRedSupps );
+/*=== dchClass.c =================================================*/
+extern Dch_Cla_t *   Dch_ClassesStart( Aig_Man_t * pAig );
+extern void          Dch_ClassesSetData( Dch_Cla_t * p, void * pManData,
+                         unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *),
+                         int (*pFuncNodeIsConst)(void *,Aig_Obj_t *),
+                         int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) );
+extern void          Dch_ClassesStop( Dch_Cla_t * p );
+extern int           Dch_ClassesLitNum( Dch_Cla_t * p );
+extern Aig_Obj_t **  Dch_ClassesReadClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize );
+extern void          Dch_ClassesPrint( Dch_Cla_t * p, int fVeryVerbose );
+extern void          Dch_ClassesPrepare( Dch_Cla_t * p, int fLatchCorr, int nMaxLevs );
+extern int           Dch_ClassesRefine( Dch_Cla_t * p );
+extern int           Dch_ClassesRefineOneClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, int fRecursive );
+extern void          Dch_ClassesCollectOneClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vRoots );
+extern void          Dch_ClassesCollectConst1Group( Dch_Cla_t * p, Aig_Obj_t * pObj, int nNodes, Vec_Ptr_t * vRoots );
+extern int           Dch_ClassesRefineConst1Group( Dch_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive );
+/*=== dchCnf.c ===================================================*/
+extern void          Dch_CnfNodeAddToSolver( Dch_Man_t * p, Aig_Obj_t * pObj );
+/*=== dchMan.c ===================================================*/
+extern Dch_Man_t *   Dch_ManCreate( Aig_Man_t * pAig, Dch_Pars_t * pPars );
+extern void          Dch_ManStop( Dch_Man_t * p );
+extern void          Dch_ManSatSolverRecycle( Dch_Man_t * p );
+/*=== dchSat.c ===================================================*/
+extern int           Dch_NodesAreEquiv( Dch_Man_t * p, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 );
+/*=== dchSim.c ===================================================*/
+extern Dch_Cla_t *   Dch_CreateCandEquivClasses( Aig_Man_t * pAig, int nWords, int fVerbose );
+/*=== dchSimSat.c ===================================================*/
+extern void          Dch_ManResimulateCex( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr );
+extern void          Dch_ManResimulateCex2( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr );
+/*=== dchSweep.c ===================================================*/
+extern void          Dch_ManSweep( Dch_Man_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/dch/dchMan.c b/abc-build/src/proof/dch/dchMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/dch/dchMan.c
@@ -0,0 +1,191 @@
+/**CFile****************************************************************
+
+  FileName    [dchMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Choice computation for tech-mapping.]
+
+  Synopsis    [Calls to the SAT solver.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: dchMan.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dch_Man_t * Dch_ManCreate( Aig_Man_t * pAig, Dch_Pars_t * pPars )
+{
+    Dch_Man_t * p;
+    // create interpolation manager
+    p = ABC_ALLOC( Dch_Man_t, 1 );
+    memset( p, 0, sizeof(Dch_Man_t) );
+    p->pPars        = pPars;
+    p->pAigTotal    = pAig; //Dch_DeriveTotalAig( vAigs );
+    Aig_ManFanoutStart( p->pAigTotal );
+    // SAT solving
+    p->nSatVars     = 1;
+    p->pSatVars     = ABC_CALLOC( int, Aig_ManObjNumMax(p->pAigTotal) );
+    p->vUsedNodes   = Vec_PtrAlloc( 1000 );
+    p->vFanins      = Vec_PtrAlloc( 100 );
+    p->vSimRoots    = Vec_PtrAlloc( 1000 );
+    p->vSimClasses  = Vec_PtrAlloc( 1000 );
+    // equivalences proved
+    p->pReprsProved = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAigTotal) );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ManPrintStats( Dch_Man_t * p )
+{
+    int nNodeNum = Aig_ManNodeNum(p->pAigTotal) / 3;
+    Abc_Print( 1, "Parameters: Sim words = %d. Conf limit = %d. SAT var max = %d.\n", 
+        p->pPars->nWords, p->pPars->nBTLimit, p->pPars->nSatVarMax );
+    Abc_Print( 1, "AIG nodes : Total = %6d. Dangling = %6d. Main = %6d. (%6.2f %%)\n", 
+        Aig_ManNodeNum(p->pAigTotal), 
+        Aig_ManNodeNum(p->pAigTotal)-nNodeNum,
+        nNodeNum,
+        100.0 * nNodeNum/Aig_ManNodeNum(p->pAigTotal) );
+    Abc_Print( 1, "SAT solver: Vars = %d. Max cone = %d. Recycles = %d.\n", 
+        p->nSatVars, p->nConeMax, p->nRecycles );
+    Abc_Print( 1, "SAT calls : All = %6d. Unsat = %6d. Sat = %6d. Fail = %6d.\n", 
+        p->nSatCalls, p->nSatCalls-p->nSatCallsSat-p->nSatFailsReal, 
+        p->nSatCallsSat, p->nSatFailsReal );
+    Abc_Print( 1, "Choices   : Lits = %6d. Reprs = %5d. Equivs = %5d. Choices = %5d.\n", 
+        p->nLits, p->nReprs, p->nEquivs, p->nChoices );
+    Abc_Print( 1, "Choicing runtime statistics:\n" );
+    p->timeOther = p->timeTotal-p->timeSimInit-p->timeSimSat-p->timeSat-p->timeChoice;
+    Abc_PrintTimeP( 1, "Sim init   ", p->timeSimInit,  p->timeTotal );
+    Abc_PrintTimeP( 1, "Sim SAT    ", p->timeSimSat,   p->timeTotal );
+    Abc_PrintTimeP( 1, "SAT solving", p->timeSat,      p->timeTotal );
+    Abc_PrintTimeP( 1, "  sat      ", p->timeSatSat,   p->timeTotal );
+    Abc_PrintTimeP( 1, "  unsat    ", p->timeSatUnsat, p->timeTotal );
+    Abc_PrintTimeP( 1, "  undecided", p->timeSatUndec, p->timeTotal );
+    Abc_PrintTimeP( 1, "Choice     ", p->timeChoice,   p->timeTotal );
+    Abc_PrintTimeP( 1, "Other      ", p->timeOther,    p->timeTotal );
+    Abc_PrintTimeP( 1, "TOTAL      ", p->timeTotal,    p->timeTotal );
+    if ( p->pPars->timeSynth )
+    {
+    Abc_PrintTime( 1, "Synthesis  ", p->pPars->timeSynth );
+    }
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ManStop( Dch_Man_t * p )
+{
+    Aig_ManFanoutStop( p->pAigTotal );
+    if ( p->pPars->fVerbose )
+        Dch_ManPrintStats( p );
+    if ( p->pAigFraig )
+        Aig_ManStop( p->pAigFraig );
+    if ( p->ppClasses )
+        Dch_ClassesStop( p->ppClasses );
+    if ( p->pSat )
+        sat_solver_delete( p->pSat );
+    Vec_PtrFree( p->vUsedNodes );
+    Vec_PtrFree( p->vFanins );
+    Vec_PtrFree( p->vSimRoots );
+    Vec_PtrFree( p->vSimClasses );
+    ABC_FREE( p->pReprsProved );
+    ABC_FREE( p->pSatVars );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ManSatSolverRecycle( Dch_Man_t * p )
+{
+    int Lit;
+    if ( p->pSat )
+    {
+        Aig_Obj_t * pObj;
+        int i;
+        Vec_PtrForEachEntry( Aig_Obj_t *, p->vUsedNodes, pObj, i )
+            Dch_ObjSetSatNum( p, pObj, 0 );
+        Vec_PtrClear( p->vUsedNodes );
+//        memset( p->pSatVars, 0, sizeof(int) * Aig_ManObjNumMax(p->pAigTotal) );
+        sat_solver_delete( p->pSat );
+    }
+    p->pSat = sat_solver_new();
+    sat_solver_setnvars( p->pSat, 1000 );
+    // var 0 is not used
+    // var 1 is reserved for const1 node - add the clause
+    p->nSatVars = 1;
+//    p->nSatVars = 0;
+    Lit = toLit( p->nSatVars );
+    if ( p->pPars->fPolarFlip )
+        Lit = lit_neg( Lit );
+    sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+    Dch_ObjSetSatNum( p, Aig_ManConst1(p->pAigFraig), p->nSatVars++ );
+
+    p->nRecycles++;
+    p->nCallsSince = 0;
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/dch/dchSat.c b/abc-build/src/proof/dch/dchSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/dch/dchSat.c
@@ -0,0 +1,167 @@
+/**CFile****************************************************************
+
+  FileName    [dchSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Choice computation for tech-mapping.]
+
+  Synopsis    [Calls to the SAT solver.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: dchSat.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Runs equivalence test for the two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dch_NodesAreEquiv( Dch_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew )
+{
+    int nBTLimit = p->pPars->nBTLimit;
+    int pLits[2], RetValue, RetValue1, status;
+    abctime clk;
+    p->nSatCalls++;
+
+    // sanity checks
+    assert( !Aig_IsComplement(pNew) );
+    assert( !Aig_IsComplement(pOld) );
+    assert( pNew != pOld );
+
+    p->nCallsSince++;  // experiment with this!!!
+    
+    // check if SAT solver needs recycling
+    if ( p->pSat == NULL || 
+        (p->pPars->nSatVarMax && 
+         p->nSatVars > p->pPars->nSatVarMax && 
+         p->nCallsSince > p->pPars->nCallsRecycle) )
+        Dch_ManSatSolverRecycle( p );
+
+    // if the nodes do not have SAT variables, allocate them
+    Dch_CnfNodeAddToSolver( p, pOld );
+    Dch_CnfNodeAddToSolver( p, pNew );
+
+    // propage unit clauses
+    if ( p->pSat->qtail != p->pSat->qhead )
+    {
+        status = sat_solver_simplify(p->pSat);
+        assert( status != 0 );
+        assert( p->pSat->qtail == p->pSat->qhead );
+    }
+
+    // solve under assumptions
+    // A = 1; B = 0     OR     A = 1; B = 1 
+    pLits[0] = toLitCond( Dch_ObjSatNum(p,pOld), 0 );
+    pLits[1] = toLitCond( Dch_ObjSatNum(p,pNew), pOld->fPhase == pNew->fPhase );
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( pOld->fPhase )  pLits[0] = lit_neg( pLits[0] );
+        if ( pNew->fPhase )  pLits[1] = lit_neg( pLits[1] );
+    }
+//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
+clk = Abc_Clock();
+    RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, 
+        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+p->timeSat += Abc_Clock() - clk;
+    if ( RetValue1 == l_False )
+    {
+p->timeSatUnsat += Abc_Clock() - clk;
+        pLits[0] = lit_neg( pLits[0] );
+        pLits[1] = lit_neg( pLits[1] );
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+        p->nSatCallsUnsat++;
+    }
+    else if ( RetValue1 == l_True )
+    {
+p->timeSatSat += Abc_Clock() - clk;
+        p->nSatCallsSat++;
+        return 0;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+p->timeSatUndec += Abc_Clock() - clk;
+        p->nSatFailsReal++;
+        return -1;
+    }
+
+    // if the old node was constant 0, we already know the answer
+    if ( pOld == Aig_ManConst1(p->pAigFraig) )
+    {
+        p->nSatProof++;
+        return 1;
+    }
+
+    // solve under assumptions
+    // A = 0; B = 1     OR     A = 0; B = 0 
+    pLits[0] = toLitCond( Dch_ObjSatNum(p,pOld), 1 );
+    pLits[1] = toLitCond( Dch_ObjSatNum(p,pNew), pOld->fPhase ^ pNew->fPhase );
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( pOld->fPhase )  pLits[0] = lit_neg( pLits[0] );
+        if ( pNew->fPhase )  pLits[1] = lit_neg( pLits[1] );
+    }
+clk = Abc_Clock();
+    RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, 
+        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+p->timeSat += Abc_Clock() - clk;
+    if ( RetValue1 == l_False )
+    {
+p->timeSatUnsat += Abc_Clock() - clk;
+        pLits[0] = lit_neg( pLits[0] );
+        pLits[1] = lit_neg( pLits[1] );
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+        p->nSatCallsUnsat++;
+    }
+    else if ( RetValue1 == l_True )
+    {
+p->timeSatSat += Abc_Clock() - clk;
+        p->nSatCallsSat++;
+        return 0;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+p->timeSatUndec += Abc_Clock() - clk;
+        p->nSatFailsReal++;
+        return -1;
+    }
+    // return SAT proof
+    p->nSatProof++;
+    return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/dch/dchSim.c b/abc-build/src/proof/dch/dchSim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/dch/dchSim.c
@@ -0,0 +1,297 @@
+/**CFile****************************************************************
+
+  FileName    [dchSim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Choice computation for tech-mapping.]
+
+  Synopsis    [Performs random simulation at the beginning.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: dchSim.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline unsigned * Dch_ObjSim( Vec_Ptr_t * vSims, Aig_Obj_t * pObj )
+{ 
+    return (unsigned *)Vec_PtrEntry( vSims, pObj->Id ); 
+}
+static inline unsigned Dch_ObjRandomSim()    
+{ 
+    return Aig_ManRandom(0);               
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node appears to be constant 1 candidate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dch_NodeIsConstCex( void * p, Aig_Obj_t * pObj )
+{
+    return pObj->fPhase == pObj->fMarkB;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the nodes appear equal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dch_NodesAreEqualCex( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+    return (pObj0->fPhase == pObj1->fPhase) == (pObj0->fMarkB == pObj1->fMarkB);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash value of the node using its simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Dch_NodeHash( void * p, Aig_Obj_t * pObj )
+{
+    Vec_Ptr_t * vSims = (Vec_Ptr_t *)p;
+    static int s_FPrimes[128] = { 
+        1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 
+        1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 
+        2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 
+        2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 
+        3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 
+        3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 
+        4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 
+        4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 
+        5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 
+        6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 
+        6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 
+        7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 
+        8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+    };
+    unsigned * pSim;
+    unsigned uHash;
+    int k, nWords;
+    nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0);
+    uHash = 0;
+    pSim  = Dch_ObjSim( vSims, pObj );
+    if ( pObj->fPhase )
+    {
+        for ( k = 0; k < nWords; k++ )
+            uHash ^= ~pSim[k] * s_FPrimes[k & 0x7F];
+    }
+    else
+    {
+        for ( k = 0; k < nWords; k++ )
+            uHash ^= pSim[k] * s_FPrimes[k & 0x7F];
+    }
+    return uHash;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation info is composed of all zeros.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dch_NodeIsConst( void * p, Aig_Obj_t * pObj )
+{
+    Vec_Ptr_t * vSims = (Vec_Ptr_t *)p;
+    unsigned * pSim;
+    int k, nWords;
+    nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0);
+    pSim  = Dch_ObjSim( vSims, pObj );
+    if ( pObj->fPhase )
+    {
+        for ( k = 0; k < nWords; k++ )
+            if ( ~pSim[k] )
+                return 0;
+    }
+    else
+    {
+        for ( k = 0; k < nWords; k++ )
+            if ( pSim[k] )
+                return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation infos are equal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Dch_NodesAreEqual( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+    Vec_Ptr_t * vSims = (Vec_Ptr_t *)p;
+    unsigned * pSim0, * pSim1;
+    int k, nWords;
+    nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0);
+    pSim0 = Dch_ObjSim( vSims, pObj0 );
+    pSim1 = Dch_ObjSim( vSims, pObj1 );
+    if ( pObj0->fPhase != pObj1->fPhase )
+    {
+        for ( k = 0; k < nWords; k++ )
+            if ( pSim0[k] != ~pSim1[k] )
+                return 0;
+    }
+    else
+    {
+        for ( k = 0; k < nWords; k++ )
+            if ( pSim0[k] != pSim1[k] )
+                return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform random simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_PerformRandomSimulation( Aig_Man_t * pAig, Vec_Ptr_t * vSims )
+{
+    unsigned * pSim, * pSim0, * pSim1;
+    Aig_Obj_t * pObj;
+    int i, k, nWords;
+    nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0);
+
+    // assign const 1 sim info
+    pObj = Aig_ManConst1(pAig);
+    pSim = Dch_ObjSim( vSims, pObj );
+    memset( pSim, 0xff, sizeof(unsigned) * nWords );
+
+    // assign primary input random sim info
+    Aig_ManForEachCi( pAig, pObj, i )
+    {
+        pSim = Dch_ObjSim( vSims, pObj );
+        for ( k = 0; k < nWords; k++ )
+            pSim[k] = Dch_ObjRandomSim();
+        pSim[0] <<= 1;
+    }
+
+    // simulate AIG in the topological order
+    Aig_ManForEachNode( pAig, pObj, i )
+    {
+        pSim0 = Dch_ObjSim( vSims, Aig_ObjFanin0(pObj) ); 
+        pSim1 = Dch_ObjSim( vSims, Aig_ObjFanin1(pObj) ); 
+        pSim  = Dch_ObjSim( vSims, pObj );
+
+        if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) // both are compls
+        {
+            for ( k = 0; k < nWords; k++ )
+                pSim[k] = ~pSim0[k] & ~pSim1[k];
+        }
+        else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) // first one is compl
+        {
+            for ( k = 0; k < nWords; k++ )
+                pSim[k] = ~pSim0[k] & pSim1[k];
+        }
+        else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) // second one is compl
+        {
+            for ( k = 0; k < nWords; k++ )
+                pSim[k] = pSim0[k] & ~pSim1[k];
+        }
+        else // if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) // none is compl
+        {
+            for ( k = 0; k < nWords; k++ )
+                pSim[k] = pSim0[k] & pSim1[k];
+        }
+    }
+    // get simulation information for primary outputs
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives candidate equivalence classes of AIG nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dch_Cla_t * Dch_CreateCandEquivClasses( Aig_Man_t * pAig, int nWords, int fVerbose )
+{
+    Dch_Cla_t * pClasses;
+    Vec_Ptr_t * vSims;
+    int i;
+    // allocate simulation information
+    vSims = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(pAig), nWords );
+    // run random simulation from the primary inputs
+    Dch_PerformRandomSimulation( pAig, vSims );
+    // start storage for equivalence classes
+    pClasses = Dch_ClassesStart( pAig );
+    Dch_ClassesSetData( pClasses, vSims, Dch_NodeHash, Dch_NodeIsConst, Dch_NodesAreEqual );
+    // hash nodes by sim info
+    Dch_ClassesPrepare( pClasses, 0, 0 );
+    // iterate random simulation
+    for ( i = 0; i < 7; i++ )
+    {
+        Dch_PerformRandomSimulation( pAig, vSims );
+        Dch_ClassesRefine( pClasses );
+    }
+    // clean up and return
+    Vec_PtrFree( vSims );
+    // prepare class refinement procedures
+    Dch_ClassesSetData( pClasses, NULL, NULL, Dch_NodeIsConstCex, Dch_NodesAreEqualCex );
+    return pClasses;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/dch/dchSimSat.c b/abc-build/src/proof/dch/dchSimSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/dch/dchSimSat.c
@@ -0,0 +1,260 @@
+/**CFile****************************************************************
+
+  FileName    [dchSimSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Choice computation for tech-mapping.]
+
+  Synopsis    [Performs resimulation using counter-examples.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: dchSimSat.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes in the reverse DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ManCollectTfoCands_rec( Dch_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pFanout, * pRepr;
+    int iFanout = -1, i;
+    assert( !Aig_IsComplement(pObj) );
+    if ( Aig_ObjIsTravIdCurrent(p->pAigTotal, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p->pAigTotal, pObj);
+    // traverse the fanouts
+    Aig_ObjForEachFanout( p->pAigTotal, pObj, pFanout, iFanout, i )
+        Dch_ManCollectTfoCands_rec( p, pFanout );
+    // check if the given node has a representative
+    pRepr = Aig_ObjRepr( p->pAigTotal, pObj );
+    if ( pRepr == NULL )
+        return;
+    // pRepr is the constant 1 node
+    if ( pRepr == Aig_ManConst1(p->pAigTotal) )
+    {
+        Vec_PtrPush( p->vSimRoots, pObj );
+        return;
+    }
+    // pRepr is the representative of an equivalence class
+    if ( pRepr->fMarkA )
+        return;
+    pRepr->fMarkA = 1;
+    Vec_PtrPush( p->vSimClasses, pRepr );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect equivalence classes and const1 cands in the TFO.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+void Dch_ManCollectTfoCands( Dch_Man_t * p, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Vec_PtrClear( p->vSimRoots );
+    Vec_PtrClear( p->vSimClasses );
+    Aig_ManIncrementTravId( p->pAigTotal );
+    Aig_ObjSetTravIdCurrent( p->pAigTotal, Aig_ManConst1(p->pAigTotal) );    
+    Dch_ManCollectTfoCands_rec( p, pObj1 );
+    Dch_ManCollectTfoCands_rec( p, pObj2 );
+    Vec_PtrSort( p->vSimRoots, (int (*)(void))Aig_ObjCompareIdIncrease );
+    Vec_PtrSort( p->vSimClasses, (int (*)(void))Aig_ObjCompareIdIncrease );
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimClasses, pObj, i )
+        pObj->fMarkA = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulates the cone of influence of the solved nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+void Dch_ManResimulateSolved_rec( Dch_Man_t * p, Aig_Obj_t * pObj )
+{
+    if ( Aig_ObjIsTravIdCurrent(p->pAigTotal, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p->pAigTotal, pObj);
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        Aig_Obj_t * pObjFraig;
+        int nVarNum;
+        pObjFraig = Dch_ObjFraig( pObj );
+        assert( !Aig_IsComplement(pObjFraig) );
+        nVarNum = Dch_ObjSatNum( p, pObjFraig );
+        // get the value from the SAT solver
+        // (account for the fact that some vars may be minimized away)
+        pObj->fMarkB = !nVarNum? 0 : sat_solver_var_value( p->pSat, nVarNum );
+//        pObj->fMarkB = !nVarNum? Aig_ManRandom(0) & 1 : sat_solver_var_value( p->pSat, nVarNum );
+        return;
+    }
+    Dch_ManResimulateSolved_rec( p, Aig_ObjFanin0(pObj) );
+    Dch_ManResimulateSolved_rec( p, Aig_ObjFanin1(pObj) );
+    pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+                 & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+    // count the cone size
+    if ( Dch_ObjSatNum( p, Aig_Regular(Dch_ObjFraig(pObj)) ) > 0 )
+        p->nConeThis++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulates the cone of influence of the other nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ManResimulateOther_rec( Dch_Man_t * p, Aig_Obj_t * pObj )
+{
+    if ( Aig_ObjIsTravIdCurrent(p->pAigTotal, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p->pAigTotal, pObj);
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        // set random value
+        pObj->fMarkB = Aig_ManRandom(0) & 1;
+        return;
+    }
+    Dch_ManResimulateOther_rec( p, Aig_ObjFanin0(pObj) );
+    Dch_ManResimulateOther_rec( p, Aig_ObjFanin1(pObj) );
+    pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+                 & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Handle the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ManResimulateCex( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr )
+{
+    Aig_Obj_t * pRoot, ** ppClass;
+    int i, k, nSize, RetValue1, RetValue2;
+    abctime clk = Abc_Clock();
+    // get the equivalence classes
+    Dch_ManCollectTfoCands( p, pObj, pRepr );
+    // resimulate the cone of influence of the solved nodes
+    p->nConeThis = 0;
+    Aig_ManIncrementTravId( p->pAigTotal );
+    Aig_ObjSetTravIdCurrent( p->pAigTotal, Aig_ManConst1(p->pAigTotal) );
+    Dch_ManResimulateSolved_rec( p, pObj );
+    Dch_ManResimulateSolved_rec( p, pRepr );
+    p->nConeMax = Abc_MaxInt( p->nConeMax, p->nConeThis );
+    // resimulate the cone of influence of the other nodes
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimRoots, pRoot, i )
+        Dch_ManResimulateOther_rec( p, pRoot );
+    // refine these nodes
+    RetValue1 = Dch_ClassesRefineConst1Group( p->ppClasses, p->vSimRoots, 0 );
+    // resimulate the cone of influence of the cand classes
+    RetValue2 = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimClasses, pRoot, i )
+    {
+        ppClass = Dch_ClassesReadClass( p->ppClasses, pRoot, &nSize );
+        for ( k = 0; k < nSize; k++ )
+            Dch_ManResimulateOther_rec( p, ppClass[k] );
+        // refine this class
+        RetValue2 += Dch_ClassesRefineOneClass( p->ppClasses, pRoot, 0 );
+    }
+    // make sure refinement happened
+    if ( Aig_ObjIsConst1(pRepr) )
+        assert( RetValue1 );
+    else
+        assert( RetValue2 );
+p->timeSimSat += Abc_Clock() - clk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Handle the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ManResimulateCex2( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr )
+{
+    Aig_Obj_t * pRoot;
+    int i, RetValue;
+    abctime clk = Abc_Clock();
+    // get the equivalence class
+    if ( Dch_ObjIsConst1Cand(p->pAigTotal, pObj) )
+        Dch_ClassesCollectConst1Group( p->ppClasses, pObj, 500, p->vSimRoots );
+    else
+        Dch_ClassesCollectOneClass( p->ppClasses, pRepr, p->vSimRoots );
+    // resimulate the cone of influence of the solved nodes
+    p->nConeThis = 0;
+    Aig_ManIncrementTravId( p->pAigTotal );
+    Aig_ObjSetTravIdCurrent( p->pAigTotal, Aig_ManConst1(p->pAigTotal) );
+    Dch_ManResimulateSolved_rec( p, pObj );
+    Dch_ManResimulateSolved_rec( p, pRepr );
+    p->nConeMax = Abc_MaxInt( p->nConeMax, p->nConeThis );
+    // resimulate the cone of influence of the other nodes
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimRoots, pRoot, i )
+        Dch_ManResimulateOther_rec( p, pRoot );
+    // refine this class
+    if ( Dch_ObjIsConst1Cand(p->pAigTotal, pObj) )
+        RetValue = Dch_ClassesRefineConst1Group( p->ppClasses, p->vSimRoots, 0 );
+    else
+        RetValue = Dch_ClassesRefineOneClass( p->ppClasses, pRepr, 0 );
+    assert( RetValue );
+p->timeSimSat += Abc_Clock() - clk;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/dch/dchSweep.c b/abc-build/src/proof/dch/dchSweep.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/dch/dchSweep.c
@@ -0,0 +1,146 @@
+/**CFile****************************************************************
+
+  FileName    [dchSweep.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Choice computation for tech-mapping.]
+
+  Synopsis    [One round of SAT sweeping.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: dchSweep.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+#include "misc/bar/bar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline Aig_Obj_t * Dch_ObjChild0Fra( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Dch_ObjFraig(Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj)) : NULL;  }
+static inline Aig_Obj_t * Dch_ObjChild1Fra( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Dch_ObjFraig(Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj)) : NULL;  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for one node.]
+
+  Description [Returns the fraiged node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ManSweepNode( Dch_Man_t * p, Aig_Obj_t * pObj )
+{ 
+    Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig;
+    int RetValue;
+    // get representative of this class
+    pObjRepr = Aig_ObjRepr( p->pAigTotal, pObj );
+    if ( pObjRepr == NULL )
+        return;
+    // get the fraiged node
+    pObjFraig = Dch_ObjFraig( pObj );
+    if ( pObjFraig == NULL )
+        return;
+    // get the fraiged representative
+    pObjReprFraig = Dch_ObjFraig( pObjRepr );
+    if ( pObjReprFraig == NULL )
+        return;
+    // if the fraiged nodes are the same, return
+    if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) )
+    {
+        // remember the proved equivalence
+        p->pReprsProved[ pObj->Id ] = pObjRepr;
+        return;
+    }
+    assert( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pAigFraig) );
+    RetValue = Dch_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) );
+    if ( RetValue == -1 ) // timed out
+    {
+        Dch_ObjSetFraig( pObj, NULL );
+        return;
+    }
+    if ( RetValue == 1 )  // proved equivalent
+    {
+        pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase );
+        Dch_ObjSetFraig( pObj, pObjFraig2 );
+        // remember the proved equivalence
+        p->pReprsProved[ pObj->Id ] = pObjRepr;
+        return;
+    }
+    // disproved the equivalence
+    if ( p->pPars->fSimulateTfo )
+        Dch_ManResimulateCex( p, pObj, pObjRepr );
+    else
+        Dch_ManResimulateCex2( p, pObj, pObjRepr );
+    assert( Aig_ObjRepr( p->pAigTotal, pObj ) != pObjRepr );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Dch_ManSweep( Dch_Man_t * p )
+{
+    Bar_Progress_t * pProgress = NULL;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i;
+    // map constants and PIs
+    p->pAigFraig = Aig_ManStart( Aig_ManObjNumMax(p->pAigTotal) );
+    Aig_ManCleanData( p->pAigTotal );
+    Aig_ManConst1(p->pAigTotal)->pData = Aig_ManConst1(p->pAigFraig);
+    Aig_ManForEachCi( p->pAigTotal, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( p->pAigFraig );
+    // sweep internal nodes
+    pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAigTotal) );
+    Aig_ManForEachNode( p->pAigTotal, pObj, i )
+    {
+        Bar_ProgressUpdate( pProgress, i, NULL );
+        if ( Dch_ObjFraig(Aig_ObjFanin0(pObj)) == NULL || 
+             Dch_ObjFraig(Aig_ObjFanin1(pObj)) == NULL )
+            continue;
+        pObjNew = Aig_And( p->pAigFraig, Dch_ObjChild0Fra(pObj), Dch_ObjChild1Fra(pObj) );
+        if ( pObjNew == NULL )
+            continue;
+        Dch_ObjSetFraig( pObj, pObjNew );
+        Dch_ManSweepNode( p, pObj );
+    }
+    Bar_ProgressStop( pProgress );
+    // update the representatives of the nodes (makes classes invalid)
+    ABC_FREE( p->pAigTotal->pReprs );
+    p->pAigTotal->pReprs = p->pReprsProved;
+    p->pReprsProved = NULL;
+    // clean the mark
+    Aig_ManCleanMarkB( p->pAigTotal );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/dch/module.make b/abc-build/src/proof/dch/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/dch/module.make
@@ -0,0 +1,10 @@
+SRC +=	src/proof/dch/dchAig.c \
+	src/proof/dch/dchChoice.c \
+	src/proof/dch/dchClass.c \
+	src/proof/dch/dchCnf.c \
+	src/proof/dch/dchCore.c \
+	src/proof/dch/dchMan.c \
+	src/proof/dch/dchSat.c \
+	src/proof/dch/dchSim.c \
+	src/proof/dch/dchSimSat.c \
+	src/proof/dch/dchSweep.c
diff --git a/abc-build/src/proof/fra/fra.h b/abc-build/src/proof/fra/fra.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fra.h
@@ -0,0 +1,389 @@
+/**CFile****************************************************************
+
+  FileName    [fra.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [[New FRAIG package.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fra.h,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__fra__fra_h
+#define ABC__aig__fra__fra_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+#include "aig/aig/aig.h"
+#include "opt/dar/dar.h"
+#include "sat/bsat/satSolver.h"
+#include "aig/ioa/ioa.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Fra_Par_t_   Fra_Par_t;
+typedef struct Fra_Ssw_t_   Fra_Ssw_t;
+typedef struct Fra_Sec_t_   Fra_Sec_t;
+typedef struct Fra_Man_t_   Fra_Man_t;
+typedef struct Fra_Cla_t_   Fra_Cla_t;
+typedef struct Fra_Sml_t_   Fra_Sml_t;
+typedef struct Fra_Bmc_t_   Fra_Bmc_t;
+
+// FRAIG parameters
+struct Fra_Par_t_
+{
+    int              nSimWords;         // the number of words in the simulation info
+    double           dSimSatur;         // the ratio of refined classes when saturation is reached
+    int              fPatScores;        // enables simulation pattern scoring
+    int              MaxScore;          // max score after which resimulation is used
+    double           dActConeRatio;     // the ratio of cone to be bumped
+    double           dActConeBumpMax;   // the largest bump in activity
+    int              fChoicing;         // enables choicing
+    int              fSpeculate;        // use speculative reduction
+    int              fProve;            // prove the miter outputs
+    int              fVerbose;          // verbose output
+    int              fDoSparse;         // skip sparse functions
+    int              fConeBias;         // bias variables in the cone (good for unsat runs)
+    int              nBTLimitNode;      // conflict limit at a node
+    int              nBTLimitMiter;     // conflict limit at an output
+    int              nLevelMax;         // the max level to consider seriously
+    int              nFramesP;          // the number of timeframes to in the prefix
+    int              nFramesK;          // the number of timeframes to unroll
+    int              nMaxImps;          // the maximum number of implications to consider
+    int              nMaxLevs;          // the maximum number of levels to consider
+    int              fRewrite;          // use rewriting for constraint reduction
+    int              fLatchCorr;        // computes latch correspondence only
+    int              fUseImps;          // use implications
+    int              fUse1Hot;          // use one-hotness conditions
+    int              fWriteImps;        // record implications
+    int              fDontShowBar;      // does not show progressbar during fraiging
+};
+
+// seq SAT sweeping parameters
+struct Fra_Ssw_t_
+{
+    int              nPartSize;         // size of the partition
+    int              nOverSize;         // size of the overlap between partitions
+    int              nFramesP;          // number of frames in the prefix
+    int              nFramesK;          // number of frames for induction (1=simple) 
+    int              nMaxImps;          // max implications to consider
+    int              nMaxLevs;          // max levels to consider
+    int              nMinDomSize;       // min clock domain considered for optimization
+    int              fUseImps;          // use implications  
+    int              fRewrite;          // enable rewriting of the specualatively reduced model
+    int              fFraiging;         // enable comb SAT sweeping as preprocessing 
+    int              fLatchCorr;        // perform register correspondence
+    int              fWriteImps;        // write implications into a file
+    int              fUse1Hot;          // use one-hotness constraints
+    int              fVerbose;          // enable verbose output 
+    int              fSilent;           // disable any output 
+    int              nIters;            // the number of iterations performed
+    float            TimeLimit;         // the runtime budget for this call
+};
+
+// SEC parametesr
+struct Fra_Sec_t_
+{
+    int              fTryComb;          // try CEC call as a preprocessing step
+    int              fTryBmc;           // try BMC call as a preprocessing step 
+    int              nFramesMax;        // the max number of frames used for induction
+    int              nBTLimit;          // the conflict limit at a node
+    int              nBTLimitGlobal;    // the global conflict limit
+    int              nBTLimitInter;     // the conflict limit for interpolation
+    int              nBddVarsMax;       // the state space limit for BDD reachability
+    int              nBddMax;           // the max number of BDD nodes
+    int              nBddIterMax;       // the limit on the number of BDD iterations
+    int              nPdrTimeout;       // the timeout for PDR in the end
+    int              fPhaseAbstract;    // enables phase abstraction
+    int              fRetimeFirst;      // enables most-forward retiming at the beginning
+    int              fRetimeRegs;       // enables min-register retiming at the beginning
+    int              fFraiging;         // enables fraiging at the beginning
+    int              fInduction;        // enable the use of induction
+    int              fInterpolation;    // enables interpolation
+    int              fInterSeparate;    // enables interpolation for each outputs separately
+    int              fReachability;     // enables BDD based reachability
+    int              fReorderImage;     // enables BDD reordering during image computation
+    int              fStopOnFirstFail;  // enables stopping after first output of a miter has failed to prove
+    int              fUseNewProver;     // the new prover
+    int              fUsePdr;           // the PDR
+    int              fSilent;           // disables all output
+    int              fVerbose;          // enables verbose reporting of statistics
+    int              fVeryVerbose;      // enables very verbose reporting  
+    int              TimeLimit;         // enables the timeout
+    int              fReadUnsolved;     // inserts the unsolved model back
+    int              nSMnumber;         // the number of model written
+    // internal parameters
+    int              fRecursive;        // set to 1 when SEC is called recursively
+    int              fReportSolution;   // enables report solution in a special form
+};
+
+// FRAIG equivalence classes
+struct Fra_Cla_t_
+{
+    Aig_Man_t *      pAig;              // the original AIG manager
+    Aig_Obj_t **     pMemRepr;          // pointers to representatives of each node
+    Vec_Ptr_t *      vClasses;          // equivalence classes
+    Vec_Ptr_t *      vClasses1;         // equivalence class of Const1 node
+    Vec_Ptr_t *      vClassesTemp;      // temporary storage for new classes
+    Aig_Obj_t **     pMemClasses;       // memory allocated for equivalence classes
+    Aig_Obj_t **     pMemClassesFree;   // memory allocated for equivalence classes to be used
+    Vec_Ptr_t *      vClassOld;         // old equivalence class after splitting
+    Vec_Ptr_t *      vClassNew;         // new equivalence class(es) after splitting
+    int              nPairs;            // the number of pairs of nodes
+    int              fRefinement;       // set to 1 when refinement has happened
+    Vec_Int_t *      vImps;             // implications
+    // procedures used for class refinement
+    int (*pFuncNodeHash)     (Aig_Obj_t *, int);         // returns has key of the node
+    int (*pFuncNodeIsConst)  (Aig_Obj_t *);              // returns 1 if the node is a constant
+    int (*pFuncNodesAreEqual)(Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement
+};
+
+// simulation manager
+struct Fra_Sml_t_
+{
+    Aig_Man_t *      pAig;              // the original AIG manager
+    int              nPref;             // the number of times frames in the prefix
+    int              nFrames;           // the number of times frames 
+    int              nWordsFrame;       // the number of words in each time frame
+    int              nWordsTotal;       // the total number of words at a node
+    int              nWordsPref;        // the number of word in the prefix
+    int              fNonConstOut;      // have seen a non-const-0 output during simulation
+    int              nSimRounds;        // statistics
+    int              timeSim;           // statistics
+    unsigned         pData[0];          // simulation data for the nodes
+};
+
+// FRAIG manager
+struct Fra_Man_t_
+{
+    // high-level data    
+    Fra_Par_t *      pPars;             // parameters governing fraiging
+    // AIG managers
+    Aig_Man_t *      pManAig;           // the starting AIG manager
+    Aig_Man_t *      pManFraig;         // the final AIG manager
+    // mapping AIG into FRAIG
+    int              nFramesAll;        // the number of timeframes used
+    Aig_Obj_t **     pMemFraig;         // memory allocated for points to the fraig nodes
+    int              nSizeAlloc;        // allocated size of the arrays for timeframe nodes
+    // equivalence classes 
+    Fra_Cla_t *      pCla;              // representation of (candidate) equivalent nodes
+    // simulation info
+    Fra_Sml_t *      pSml;              // simulation manager
+    // bounded model checking manager
+    Fra_Bmc_t *      pBmc;
+    // counter example storage
+    int              nPatWords;         // the number of words in the counter example
+    unsigned *       pPatWords;         // the counter example
+    Vec_Int_t *      vCex;
+    // one-hotness conditions
+    Vec_Int_t *      vOneHots;          
+    // satisfiability solving
+    sat_solver *     pSat;              // SAT solver
+    int              nSatVars;          // the number of variables currently used
+    Vec_Ptr_t *      vPiVars;           // the PIs of the cone used 
+    ABC_INT64_T           nBTLimitGlobal;    // resource limit
+    ABC_INT64_T           nInsLimitGlobal;   // resource limit
+    Vec_Ptr_t **     pMemFanins;        // the arrays of fanins for some FRAIG nodes
+    int *            pMemSatNums;       // the array of SAT numbers for some FRAIG nodes
+    int              nMemAlloc;         // allocated size of the arrays for FRAIG varnums and fanins
+    Vec_Ptr_t *      vTimeouts;         // the nodes, for which equivalence checking timed out
+    // statistics
+    int              nSimRounds;
+    int              nNodesMiter;
+    int              nLitsBeg;
+    int              nLitsEnd;
+    int              nNodesBeg;
+    int              nNodesEnd;
+    int              nRegsBeg;
+    int              nRegsEnd;
+    int              nSatCalls;
+    int              nSatCallsSat;
+    int              nSatCallsUnsat;
+    int              nSatProof;
+    int              nSatFails;
+    int              nSatFailsReal;
+    int              nSpeculs;   
+    int              nChoices;
+    int              nChoicesFake;
+    int              nSatCallsRecent;
+    int              nSatCallsSkipped;
+    // runtime
+    abctime          timeSim;
+    abctime          timeTrav;
+    abctime          timeRwr;
+    abctime          timeSat;
+    abctime          timeSatUnsat;
+    abctime          timeSatSat;
+    abctime          timeSatFail;
+    abctime          timeRef;
+    abctime          timeTotal;
+    abctime          time1;
+    abctime          time2;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline unsigned *   Fra_ObjSim( Fra_Sml_t * p, int Id )                           { return p->pData + p->nWordsTotal * Id; }
+static inline unsigned     Fra_ObjRandomSim()                                            { return Aig_ManRandom(0);               }
+
+static inline Aig_Obj_t *  Fra_ObjFraig( Aig_Obj_t * pObj, int i )                       { return ((Fra_Man_t *)pObj->pData)->pMemFraig[((Fra_Man_t *)pObj->pData)->nFramesAll*pObj->Id + i];  }
+static inline void         Fra_ObjSetFraig( Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pMemFraig[((Fra_Man_t *)pObj->pData)->nFramesAll*pObj->Id + i] = pNode; }
+
+static inline Vec_Ptr_t *  Fra_ObjFaninVec( Aig_Obj_t * pObj )                           { return ((Fra_Man_t *)pObj->pData)->pMemFanins[pObj->Id];      }
+static inline void         Fra_ObjSetFaninVec( Aig_Obj_t * pObj, Vec_Ptr_t * vFanins )   { ((Fra_Man_t *)pObj->pData)->pMemFanins[pObj->Id] = vFanins;   }
+
+static inline int          Fra_ObjSatNum( Aig_Obj_t * pObj )                             { return ((Fra_Man_t *)pObj->pData)->pMemSatNums[pObj->Id];     }
+static inline void         Fra_ObjSetSatNum( Aig_Obj_t * pObj, int Num )                 { ((Fra_Man_t *)pObj->pData)->pMemSatNums[pObj->Id] = Num;      }
+
+static inline Aig_Obj_t *  Fra_ClassObjRepr( Aig_Obj_t * pObj )                          { return ((Fra_Man_t *)pObj->pData)->pCla->pMemRepr[pObj->Id];  }
+static inline void         Fra_ClassObjSetRepr( Aig_Obj_t * pObj, Aig_Obj_t * pNode )    { ((Fra_Man_t *)pObj->pData)->pCla->pMemRepr[pObj->Id] = pNode; }
+
+static inline Aig_Obj_t *  Fra_ObjChild0Fra( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Fra_ObjFraig(Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL;  }
+static inline Aig_Obj_t *  Fra_ObjChild1Fra( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Fra_ObjFraig(Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL;  }
+
+static inline int          Fra_ImpLeft( int Imp )                                        { return Imp & 0xFFFF;         }
+static inline int          Fra_ImpRight( int Imp )                                       { return Imp >> 16;            }
+static inline int          Fra_ImpCreate( int Left, int Right )                          { return (Right << 16) | Left; }
+
+////////////////////////////////////////////////////////////////////////
+///                         ITERATORS                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== fraCec.c ========================================================*/
+extern int                 Fra_FraigSat( Aig_Man_t * pMan, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose );
+extern int                 Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose );
+extern int                 Fra_FraigCecPartitioned( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, int fVerbose );
+/*=== fraClass.c ========================================================*/
+extern int                 Fra_BmcNodeIsConst( Aig_Obj_t * pObj );
+extern int                 Fra_BmcNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 );
+extern void                Fra_BmcStop( Fra_Bmc_t * p );
+extern void                Fra_BmcPerform( Fra_Man_t * p, int nPref, int nDepth );
+extern void                Fra_BmcPerformSimple( Aig_Man_t * pAig, int nFrames, int nBTLimit, int fRewrite, int fVerbose );
+/*=== fraClass.c ========================================================*/
+extern Fra_Cla_t *         Fra_ClassesStart( Aig_Man_t * pAig );
+extern void                Fra_ClassesStop( Fra_Cla_t * p );
+extern void                Fra_ClassesCopyReprs( Fra_Cla_t * p, Vec_Ptr_t * vFailed );
+extern void                Fra_ClassesPrint( Fra_Cla_t * p, int fVeryVerbose );
+extern void                Fra_ClassesPrepare( Fra_Cla_t * p, int fLatchCorr, int nMaxLevs );
+extern int                 Fra_ClassesRefine( Fra_Cla_t * p );
+extern int                 Fra_ClassesRefine1( Fra_Cla_t * p, int fRefineNewClass, int * pSkipped );
+extern int                 Fra_ClassesCountLits( Fra_Cla_t * p );
+extern int                 Fra_ClassesCountPairs( Fra_Cla_t * p );
+extern void                Fra_ClassesTest( Fra_Cla_t * p, int Id1, int Id2 );
+extern void                Fra_ClassesLatchCorr( Fra_Man_t * p );
+extern void                Fra_ClassesPostprocess( Fra_Cla_t * p );
+extern void                Fra_ClassesSelectRepr( Fra_Cla_t * p );
+extern Aig_Man_t *         Fra_ClassesDeriveAig( Fra_Cla_t * p, int nFramesK );
+/*=== fraCnf.c ========================================================*/
+extern void                Fra_CnfNodeAddToSolver( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew );
+/*=== fraCore.c ========================================================*/
+extern void                Fra_FraigSweep( Fra_Man_t * pManAig );
+extern int                 Fra_FraigMiterStatus( Aig_Man_t * p );
+extern int                 Fra_FraigMiterAssertedOutput( Aig_Man_t * p );
+extern Aig_Man_t *         Fra_FraigPerform( Aig_Man_t * pManAig, Fra_Par_t * pPars );
+extern Aig_Man_t *         Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax, int nLevelMax );
+extern Aig_Man_t *         Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax, int fProve );
+/*=== fraHot.c ========================================================*/
+extern Vec_Int_t *         Fra_OneHotCompute( Fra_Man_t * p, Fra_Sml_t * pSim );
+extern void                Fra_OneHotAssume( Fra_Man_t * p, Vec_Int_t * vOneHots );
+extern void                Fra_OneHotCheck( Fra_Man_t * p, Vec_Int_t * vOneHots );
+extern int                 Fra_OneHotRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vOneHots );
+extern int                 Fra_OneHotCount( Fra_Man_t * p, Vec_Int_t * vOneHots );
+extern void                Fra_OneHotEstimateCoverage( Fra_Man_t * p, Vec_Int_t * vOneHots );
+extern Aig_Man_t *         Fra_OneHotCreateExdc( Fra_Man_t * p, Vec_Int_t * vOneHots );
+extern void                Fra_OneHotAddKnownConstraint( Fra_Man_t * p, Vec_Ptr_t * vOnehots );
+/*=== fraImp.c ========================================================*/
+extern Vec_Int_t *         Fra_ImpDerive( Fra_Man_t * p, int nImpMaxLimit, int nImpUseLimit, int fLatchCorr );
+extern void                Fra_ImpAddToSolver( Fra_Man_t * p, Vec_Int_t * vImps, int * pSatVarNums );
+extern int                 Fra_ImpCheckForNode( Fra_Man_t * p, Vec_Int_t * vImps, Aig_Obj_t * pNode, int Pos );
+extern int                 Fra_ImpRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vImps );
+extern void                Fra_ImpCompactArray( Vec_Int_t * vImps );
+extern double              Fra_ImpComputeStateSpaceRatio( Fra_Man_t * p );
+extern int                 Fra_ImpVerifyUsingSimulation( Fra_Man_t * p );
+extern void                Fra_ImpRecordInManager( Fra_Man_t * p, Aig_Man_t * pNew );
+/*=== fraInd.c ========================================================*/
+extern Aig_Man_t *         Fra_FraigInduction( Aig_Man_t * p, Fra_Ssw_t * pPars );
+/*=== fraIndVer.c =====================================================*/
+extern int                 Fra_InvariantVerify( Aig_Man_t * p, int nFrames, Vec_Int_t * vClauses, Vec_Int_t * vLits );
+/*=== fraLcr.c ========================================================*/
+extern Aig_Man_t *         Fra_FraigLatchCorrespondence( Aig_Man_t * pAig, int nFramesP, int nConfMax, int fProve, int fVerbose, int * pnIter, float TimeLimit );
+/*=== fraMan.c ========================================================*/
+extern void                Fra_ParamsDefault( Fra_Par_t * pParams );
+extern void                Fra_ParamsDefaultSeq( Fra_Par_t * pParams );
+extern Fra_Man_t *         Fra_ManStart( Aig_Man_t * pManAig, Fra_Par_t * pParams );
+extern void                Fra_ManClean( Fra_Man_t * p, int nNodesMax );
+extern Aig_Man_t *         Fra_ManPrepareComb( Fra_Man_t * p );
+extern void                Fra_ManFinalizeComb( Fra_Man_t * p );
+extern void                Fra_ManStop( Fra_Man_t * p );
+extern void                Fra_ManPrint( Fra_Man_t * p );
+/*=== fraSat.c ========================================================*/
+extern int                 Fra_NodesAreEquiv( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew );
+extern int                 Fra_NodesAreImp( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew, int fComplL, int fComplR );
+extern int                 Fra_NodesAreClause( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew, int fComplL, int fComplR );
+extern int                 Fra_NodeIsConst( Fra_Man_t * p, Aig_Obj_t * pNew );
+/*=== fraSec.c ========================================================*/
+extern void                Fra_SecSetDefaultParams( Fra_Sec_t * p );
+extern int                 Fra_FraigSec( Aig_Man_t * p, Fra_Sec_t * pParSec, Aig_Man_t ** ppResult );
+/*=== fraSim.c ========================================================*/
+extern int                 Fra_SmlNodeHash( Aig_Obj_t * pObj, int nTableSize );
+extern int                 Fra_SmlNodeIsConst( Aig_Obj_t * pObj );
+extern int                 Fra_SmlNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 );
+extern int                 Fra_SmlNodeNotEquWeight( Fra_Sml_t * p, int Left, int Right );
+extern int                 Fra_SmlNodeCountOnes( Fra_Sml_t * p, Aig_Obj_t * pObj );
+extern int                 Fra_SmlCheckOutput( Fra_Man_t * p );
+extern void                Fra_SmlSavePattern( Fra_Man_t * p );
+extern void                Fra_SmlSimulate( Fra_Man_t * p, int fInit );
+extern void                Fra_SmlResimulate( Fra_Man_t * p );
+extern Fra_Sml_t *         Fra_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame );
+extern void                Fra_SmlStop( Fra_Sml_t * p );
+extern Fra_Sml_t *         Fra_SmlSimulateComb( Aig_Man_t * pAig, int nWords, int fCheckMiter );
+extern Fra_Sml_t *         Fra_SmlSimulateCombGiven( Aig_Man_t * pAig, char * pFileName, int fCheckMiter, int fVerbose );
+extern Fra_Sml_t *         Fra_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords, int fCheckMiter );
+extern Abc_Cex_t *         Fra_SmlGetCounterExample( Fra_Sml_t * p );
+extern Abc_Cex_t *         Fra_SmlCopyCounterExample( Aig_Man_t * pAig, Aig_Man_t * pFrames, int * pModel );
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/fra/fraBmc.c b/abc-build/src/proof/fra/fraBmc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fraBmc.c
@@ -0,0 +1,453 @@
+/**CFile****************************************************************
+
+  FileName    [fraBmc.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    [Bounded model checking.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fraBmc.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// simulation manager
+struct Fra_Bmc_t_
+{
+    // parameters
+    int              nPref;             // the size of the prefix
+    int              nDepth;            // the depth of the frames
+    int              nFramesAll;        // the total number of timeframes
+    // implications to be filtered
+    Vec_Int_t *      vImps;
+    // AIG managers
+    Aig_Man_t *      pAig;              // the original AIG manager
+    Aig_Man_t *      pAigFrames;        // initialized timeframes
+    Aig_Man_t *      pAigFraig;         // the fraiged initialized timeframes
+    // mapping of nodes
+    Aig_Obj_t **     pObjToFrames;      // mapping of the original node into frames
+    Aig_Obj_t **     pObjToFraig;       // mapping of the frames node into fraig
+};
+
+static inline Aig_Obj_t *  Bmc_ObjFrames( Aig_Obj_t * pObj, int i )                       { return ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFrames[((Fra_Man_t *)pObj->pData)->pBmc->nFramesAll*pObj->Id + i];  }
+static inline void         Bmc_ObjSetFrames( Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFrames[((Fra_Man_t *)pObj->pData)->pBmc->nFramesAll*pObj->Id + i] = pNode; }
+
+static inline Aig_Obj_t *  Bmc_ObjFraig( Aig_Obj_t * pObj )                               { return ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFraig[pObj->Id];  }
+static inline void         Bmc_ObjSetFraig( Aig_Obj_t * pObj, Aig_Obj_t * pNode )         { ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFraig[pObj->Id] = pNode; }
+
+static inline Aig_Obj_t *  Bmc_ObjChild0Frames( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Bmc_ObjFrames(Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL;  }
+static inline Aig_Obj_t *  Bmc_ObjChild1Frames( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Bmc_ObjFrames(Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL;  }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the nodes are equivalent.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_BmcNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+    Fra_Man_t * p = (Fra_Man_t *)pObj0->pData;
+    Aig_Obj_t * pObjFrames0, * pObjFrames1;
+    Aig_Obj_t * pObjFraig0, * pObjFraig1;
+    int i;
+    for ( i = p->pBmc->nPref; i < p->pBmc->nFramesAll; i++ )
+    {
+        pObjFrames0 = Aig_Regular( Bmc_ObjFrames(pObj0, i) );
+        pObjFrames1 = Aig_Regular( Bmc_ObjFrames(pObj1, i) );
+        if ( pObjFrames0 == pObjFrames1 )
+            continue;
+        pObjFraig0 = Aig_Regular( Bmc_ObjFraig(pObjFrames0) );
+        pObjFraig1 = Aig_Regular( Bmc_ObjFraig(pObjFrames1) );
+        if ( pObjFraig0 != pObjFraig1 )
+            return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node is costant.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_BmcNodeIsConst( Aig_Obj_t * pObj )
+{
+    Fra_Man_t * p = (Fra_Man_t *)pObj->pData;
+    return Fra_BmcNodesAreEqual( pObj, Aig_ManConst1(p->pManAig) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines implications using BMC.]
+
+  Description [The input is the combinational FRAIG manager,
+  which is used to FRAIG the timeframes. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_BmcFilterImplications( Fra_Man_t * p, Fra_Bmc_t * pBmc )
+{
+    Aig_Obj_t * pLeft, * pRight;
+    Aig_Obj_t * pLeftT, * pRightT;
+    Aig_Obj_t * pLeftF, * pRightF;
+    int i, f, Imp, Left, Right;
+    int fComplL, fComplR;
+    assert( p->nFramesAll == 1 );
+    assert( p->pManAig == pBmc->pAigFrames );
+    Vec_IntForEachEntry( pBmc->vImps, Imp, i )
+    {
+        if ( Imp == 0 )
+            continue;
+        Left  = Fra_ImpLeft(Imp);
+        Right = Fra_ImpRight(Imp);
+        // get the corresponding nodes
+        pLeft  = Aig_ManObj( pBmc->pAig, Left );
+        pRight = Aig_ManObj( pBmc->pAig, Right );
+        // iterate through the timeframes
+        for ( f = pBmc->nPref; f < pBmc->nFramesAll; f++ )
+        {
+            // get timeframe nodes
+            pLeftT  = Bmc_ObjFrames( pLeft, f );
+            pRightT = Bmc_ObjFrames( pRight, f );
+            // get the corresponding FRAIG nodes
+            pLeftF  = Fra_ObjFraig( Aig_Regular(pLeftT), 0 );
+            pRightF = Fra_ObjFraig( Aig_Regular(pRightT), 0 );
+            // get the complemented attributes
+            fComplL = pLeft->fPhase ^ Aig_IsComplement(pLeftF) ^ Aig_IsComplement(pLeftT);
+            fComplR = pRight->fPhase ^ Aig_IsComplement(pRightF) ^ Aig_IsComplement(pRightT);
+            // check equality
+            if ( Aig_Regular(pLeftF) == Aig_Regular(pRightF) )
+            {
+                if ( fComplL == fComplR ) // x => x  - always true
+                    continue;
+                assert( fComplL != fComplR );
+                // consider 4 possibilities:
+                // NOT(1) => 1    or   0 => 1  - always true
+                // 1 => NOT(1)    or   1 => 0  - never true
+                // NOT(x) => x    or   x       - not always true
+                // x => NOT(x)    or   NOT(x)  - not always true
+                if ( Aig_ObjIsConst1(Aig_Regular(pLeftF)) && fComplL ) // proved implication
+                    continue;
+                // disproved implication
+                Vec_IntWriteEntry( pBmc->vImps, i, 0 ); 
+                break;
+            }
+            // check the implication 
+            if ( Fra_NodesAreImp( p, Aig_Regular(pLeftF), Aig_Regular(pRightF), fComplL, fComplR ) != 1 )
+            {
+                Vec_IntWriteEntry( pBmc->vImps, i, 0 );
+                break;
+            }
+        }
+    }
+    Fra_ImpCompactArray( pBmc->vImps );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the BMC manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fra_Bmc_t * Fra_BmcStart( Aig_Man_t * pAig, int nPref, int nDepth )
+{
+    Fra_Bmc_t * p;
+    p = ABC_ALLOC( Fra_Bmc_t, 1 );
+    memset( p, 0, sizeof(Fra_Bmc_t) );
+    p->pAig = pAig;
+    p->nPref = nPref;
+    p->nDepth = nDepth;
+    p->nFramesAll = nPref + nDepth;
+    p->pObjToFrames  = ABC_ALLOC( Aig_Obj_t *, p->nFramesAll * Aig_ManObjNumMax(pAig) );
+    memset( p->pObjToFrames, 0, sizeof(Aig_Obj_t *) * p->nFramesAll * Aig_ManObjNumMax(pAig) );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the BMC manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_BmcStop( Fra_Bmc_t * p )
+{
+    Aig_ManStop( p->pAigFrames );
+    if ( p->pAigFraig )
+        Aig_ManStop( p->pAigFraig );
+    ABC_FREE( p->pObjToFrames );
+    ABC_FREE( p->pObjToFraig );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs initialized timeframes of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Fra_BmcFrames( Fra_Bmc_t * p, int fKeepPos )
+{
+    Aig_Man_t * pAigFrames;
+    Aig_Obj_t * pObj, * pObjNew;
+    Aig_Obj_t ** pLatches;
+    int i, k, f;
+
+    // start the fraig package
+    pAigFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->nFramesAll );
+    pAigFrames->pName = Abc_UtilStrsav( p->pAig->pName );
+    pAigFrames->pSpec = Abc_UtilStrsav( p->pAig->pSpec );
+    // create PI nodes for the frames
+    for ( f = 0; f < p->nFramesAll; f++ )
+        Bmc_ObjSetFrames( Aig_ManConst1(p->pAig), f, Aig_ManConst1(pAigFrames) );
+    for ( f = 0; f < p->nFramesAll; f++ )
+        Aig_ManForEachPiSeq( p->pAig, pObj, i )
+            Bmc_ObjSetFrames( pObj, f, Aig_ObjCreateCi(pAigFrames) );
+    // set initial state for the latches
+    Aig_ManForEachLoSeq( p->pAig, pObj, i )
+        Bmc_ObjSetFrames( pObj, 0, Aig_ManConst0(pAigFrames) );
+
+    // add timeframes
+    pLatches = ABC_ALLOC( Aig_Obj_t *, Aig_ManRegNum(p->pAig) );
+    for ( f = 0; f < p->nFramesAll; f++ )
+    {
+        // add internal nodes of this frame
+        Aig_ManForEachNode( p->pAig, pObj, i )
+        {
+            pObjNew = Aig_And( pAigFrames, Bmc_ObjChild0Frames(pObj,f), Bmc_ObjChild1Frames(pObj,f) );
+            Bmc_ObjSetFrames( pObj, f, pObjNew );
+        }
+        if ( f == p->nFramesAll - 1 )
+            break;
+        // save the latch input values
+        k = 0;
+        Aig_ManForEachLiSeq( p->pAig, pObj, i )
+            pLatches[k++] = Bmc_ObjChild0Frames(pObj,f);
+        assert( k == Aig_ManRegNum(p->pAig) );
+        // insert them to the latch output values
+        k = 0;
+        Aig_ManForEachLoSeq( p->pAig, pObj, i )
+            Bmc_ObjSetFrames( pObj, f+1, pLatches[k++] );
+        assert( k == Aig_ManRegNum(p->pAig) );
+    }
+    ABC_FREE( pLatches );
+    if ( fKeepPos )
+    {
+        for ( f = 0; f < p->nFramesAll; f++ )
+            Aig_ManForEachPoSeq( p->pAig, pObj, i )
+                Aig_ObjCreateCo( pAigFrames, Bmc_ObjChild0Frames(pObj,f) );
+        Aig_ManCleanup( pAigFrames );
+    }
+    else
+    {
+        // add POs to all the dangling nodes
+        Aig_ManForEachObj( pAigFrames, pObjNew, i )
+            if ( Aig_ObjIsNode(pObjNew) && pObjNew->nRefs == 0 )
+                Aig_ObjCreateCo( pAigFrames, pObjNew );
+    }
+    // return the new manager
+    return pAigFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BMC for the given AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_BmcPerform( Fra_Man_t * p, int nPref, int nDepth )
+{
+    Aig_Obj_t * pObj;
+    int i, nImpsOld = 0;
+    abctime clk = Abc_Clock();
+    assert( p->pBmc == NULL );
+    // derive and fraig the frames
+    p->pBmc = Fra_BmcStart( p->pManAig, nPref, nDepth );
+    p->pBmc->pAigFrames = Fra_BmcFrames( p->pBmc, 0 );
+    // if implications are present, configure the AIG manager to check them
+    if ( p->pCla->vImps )
+    {
+        p->pBmc->pAigFrames->pImpFunc = (void (*) (void*, void*))Fra_BmcFilterImplications;
+        p->pBmc->pAigFrames->pImpData = p->pBmc;
+        p->pBmc->vImps = p->pCla->vImps;
+        nImpsOld = Vec_IntSize(p->pCla->vImps);
+    } 
+    p->pBmc->pAigFraig = Fra_FraigEquivence( p->pBmc->pAigFrames, 1000000, 0 );
+    p->pBmc->pObjToFraig = p->pBmc->pAigFrames->pObjCopies;
+    p->pBmc->pAigFrames->pObjCopies = NULL;
+    // annotate frames nodes with pointers to the manager
+    Aig_ManForEachObj( p->pBmc->pAigFrames, pObj, i )
+        pObj->pData = p;
+    // report the results
+    if ( p->pPars->fVerbose )
+    {
+        printf( "Original AIG = %d. Init %d frames = %d. Fraig = %d.  ", 
+            Aig_ManNodeNum(p->pBmc->pAig), p->pBmc->nFramesAll, 
+            Aig_ManNodeNum(p->pBmc->pAigFrames), Aig_ManNodeNum(p->pBmc->pAigFraig) );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+        printf( "Before BMC: " );  
+//        Fra_ClassesPrint( p->pCla, 0 );
+        printf( "Const = %5d. Class = %5d. Lit = %5d. ", 
+            Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) );
+        if ( p->pCla->vImps )
+            printf( "Imp = %5d. ", nImpsOld );
+        printf( "\n" );
+    }
+    // refine the classes
+    p->pCla->pFuncNodeIsConst   = Fra_BmcNodeIsConst;
+    p->pCla->pFuncNodesAreEqual = Fra_BmcNodesAreEqual;
+    Fra_ClassesRefine( p->pCla );
+    Fra_ClassesRefine1( p->pCla, 1, NULL );
+    p->pCla->pFuncNodeIsConst   = Fra_SmlNodeIsConst;
+    p->pCla->pFuncNodesAreEqual = Fra_SmlNodesAreEqual;
+    // report the results
+    if ( p->pPars->fVerbose )
+    {
+        printf( "After  BMC: " );  
+//        Fra_ClassesPrint( p->pCla, 0 );
+        printf( "Const = %5d. Class = %5d. Lit = %5d. ", 
+            Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) );
+        if ( p->pCla->vImps )
+            printf( "Imp = %5d. ", Vec_IntSize(p->pCla->vImps) );
+        printf( "\n" );
+    }
+    // free the BMC manager
+    Fra_BmcStop( p->pBmc );  
+    p->pBmc = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BMC for the given AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_BmcPerformSimple( Aig_Man_t * pAig, int nFrames, int nBTLimit, int fRewrite, int fVerbose )
+{
+    extern Fra_Man_t * Fra_LcrAigPrepare( Aig_Man_t * pAig );
+    Fra_Man_t * pTemp;
+    Fra_Bmc_t * pBmc;
+    Aig_Man_t * pAigTemp;
+    abctime clk;
+    int iOutput;
+    // derive and fraig the frames
+    clk = Abc_Clock();
+    pBmc = Fra_BmcStart( pAig, 0, nFrames );
+    pTemp = Fra_LcrAigPrepare( pAig );
+    pTemp->pBmc = pBmc;
+    pBmc->pAigFrames = Fra_BmcFrames( pBmc, 1 );
+    if ( fVerbose )
+    {
+        printf( "AIG:  PI/PO/Reg = %d/%d/%d.  Node = %6d. Lev = %5d.\n", 
+            Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig), Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig), Aig_ManRegNum(pAig),
+            Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) );
+        printf( "Time-frames (%d):  PI/PO = %d/%d.  Node = %6d. Lev = %5d.  ", 
+            nFrames, Aig_ManCiNum(pBmc->pAigFrames), Aig_ManCoNum(pBmc->pAigFrames), 
+            Aig_ManNodeNum(pBmc->pAigFrames), Aig_ManLevelNum(pBmc->pAigFrames) );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    if ( fRewrite )
+    {
+        clk = Abc_Clock();
+        pBmc->pAigFrames = Dar_ManRwsat( pAigTemp = pBmc->pAigFrames, 1, 0 );
+        Aig_ManStop( pAigTemp );
+        if ( fVerbose )
+        {
+            printf( "Time-frames after rewriting:  Node = %6d. Lev = %5d.  ", 
+                Aig_ManNodeNum(pBmc->pAigFrames), Aig_ManLevelNum(pBmc->pAigFrames) );
+            ABC_PRT( "Time", Abc_Clock() - clk );
+        }
+    }
+    clk = Abc_Clock();
+    iOutput = Fra_FraigMiterAssertedOutput( pBmc->pAigFrames );
+    if ( iOutput >= 0 )
+        pAig->pSeqModel = Abc_CexMakeTriv( Aig_ManRegNum(pAig), Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig), Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig), iOutput );
+    else
+    {
+        pBmc->pAigFraig = Fra_FraigEquivence( pBmc->pAigFrames, nBTLimit, 1 );
+        iOutput = Fra_FraigMiterAssertedOutput( pBmc->pAigFraig );
+        if ( pBmc->pAigFraig->pData )
+        {
+            pAig->pSeqModel = Fra_SmlCopyCounterExample( pAig, pBmc->pAigFrames, (int *)pBmc->pAigFraig->pData );
+            ABC_FREE( pBmc->pAigFraig->pData );
+        }
+        else if ( iOutput >= 0 )
+            pAig->pSeqModel = Abc_CexMakeTriv( Aig_ManRegNum(pAig), Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig), Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig), iOutput );
+    }
+    if ( fVerbose )
+    {
+        printf( "Fraiged init frames: Node = %6d. Lev = %5d.  ", 
+            pBmc->pAigFraig? Aig_ManNodeNum(pBmc->pAigFraig) : -1,
+            pBmc->pAigFraig? Aig_ManLevelNum(pBmc->pAigFraig) : -1 );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    Fra_BmcStop( pBmc );  
+    ABC_FREE( pTemp );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/fraCec.c b/abc-build/src/proof/fra/fraCec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fraCec.c
@@ -0,0 +1,574 @@
+/**CFile****************************************************************
+
+  FileName    [fraCec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    [CEC engined based on fraiging.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fraCec.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver2.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_FraigSat( Aig_Man_t * pMan, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose )
+{
+    if ( fNewSolver )
+    {
+        extern void * Cnf_DataWriteIntoSolver2( Cnf_Dat_t * p, int nFrames, int fInit );
+        extern int    Cnf_DataWriteOrClause2( void * pSat, Cnf_Dat_t * pCnf );
+
+        sat_solver2 * pSat;
+        Cnf_Dat_t * pCnf;
+        int status, RetValue;
+        abctime clk = Abc_Clock();
+        Vec_Int_t * vCiIds;
+
+        assert( Aig_ManRegNum(pMan) == 0 );
+        pMan->pData = NULL;
+
+        // derive CNF
+        pCnf = Cnf_Derive( pMan, Aig_ManCoNum(pMan) );
+    //    pCnf = Cnf_DeriveSimple( pMan, Aig_ManCoNum(pMan) );
+
+        if ( fFlipBits ) 
+            Cnf_DataTranformPolarity( pCnf, 0 );
+
+        if ( fVerbose )
+        {
+            printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals );
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+        }
+
+        // convert into SAT solver
+        pSat = (sat_solver2 *)Cnf_DataWriteIntoSolver2( pCnf, 1, 0 );
+        if ( pSat == NULL )
+        {
+            Cnf_DataFree( pCnf );
+            return 1;
+        }
+
+        if ( fAndOuts )
+        {
+            // assert each output independently
+            if ( !Cnf_DataWriteAndClauses( pSat, pCnf ) )
+            {
+                sat_solver2_delete( pSat );
+                Cnf_DataFree( pCnf );
+                return 1;
+            }
+        }
+        else
+        {
+            // add the OR clause for the outputs
+            if ( !Cnf_DataWriteOrClause2( pSat, pCnf ) )
+            {
+                sat_solver2_delete( pSat );
+                Cnf_DataFree( pCnf );
+                return 1;
+            }
+        }
+        vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan );
+        Cnf_DataFree( pCnf );
+
+
+        printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver2_nvars(pSat), sat_solver2_nclauses(pSat) );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+
+        // simplify the problem
+        clk = Abc_Clock();
+        status = sat_solver2_simplify(pSat);
+//        printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver2_nvars(pSat), sat_solver2_nclauses(pSat) );
+//        ABC_PRT( "Time", Abc_Clock() - clk );
+        if ( status == 0 )
+        {
+            Vec_IntFree( vCiIds );
+            sat_solver2_delete( pSat );
+    //        printf( "The problem is UNSATISFIABLE after simplification.\n" );
+            return 1;
+        }
+
+        // solve the miter
+        clk = Abc_Clock();
+        if ( fVerbose )
+            pSat->verbosity = 1;
+        status = sat_solver2_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        if ( status == l_Undef )
+        {
+    //        printf( "The problem timed out.\n" );
+            RetValue = -1;
+        }
+        else if ( status == l_True )
+        {
+    //        printf( "The problem is SATISFIABLE.\n" );
+            RetValue = 0;
+        }
+        else if ( status == l_False )
+        {
+    //        printf( "The problem is UNSATISFIABLE.\n" );
+            RetValue = 1;
+        }
+        else
+            assert( 0 );
+
+    //    Abc_Print( 1, "The number of conflicts = %6d.  ", (int)pSat->stats.conflicts );
+    //    Abc_PrintTime( 1, "Solving time", Abc_Clock() - clk );
+ 
+        // if the problem is SAT, get the counterexample
+        if ( status == l_True )
+        {
+            pMan->pData = Sat_Solver2GetModel( pSat, vCiIds->pArray, vCiIds->nSize );
+        }
+        // free the sat_solver2
+        if ( fVerbose )
+            Sat_Solver2PrintStats( stdout, pSat );
+    //sat_solver2_store_write( pSat, "trace.cnf" );
+    //sat_solver2_store_free( pSat );
+        sat_solver2_delete( pSat );
+        Vec_IntFree( vCiIds );
+        return RetValue;
+    }
+    else
+    {
+        sat_solver * pSat;
+        Cnf_Dat_t * pCnf;
+        int status, RetValue;
+        abctime clk = Abc_Clock();
+        Vec_Int_t * vCiIds;
+
+        assert( Aig_ManRegNum(pMan) == 0 );
+        pMan->pData = NULL;
+
+        // derive CNF
+        pCnf = Cnf_Derive( pMan, Aig_ManCoNum(pMan) );
+    //    pCnf = Cnf_DeriveSimple( pMan, Aig_ManCoNum(pMan) );
+
+        if ( fFlipBits ) 
+            Cnf_DataTranformPolarity( pCnf, 0 );
+
+        if ( fVerbose )
+        {
+            printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals );
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+        }
+
+        // convert into SAT solver
+        pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+        if ( pSat == NULL )
+        {
+            Cnf_DataFree( pCnf );
+            return 1;
+        }
+
+        if ( nLearnedStart )
+            pSat->nLearntStart = nLearnedStart;
+        if ( nLearnedDelta )
+            pSat->nLearntDelta = nLearnedDelta;
+        if ( nLearnedPerce )
+            pSat->nLearntRatio = nLearnedPerce;
+        if ( fVerbose )
+            pSat->fVerbose = fVerbose;
+
+        if ( fAndOuts )
+        {
+            // assert each output independently
+            if ( !Cnf_DataWriteAndClauses( pSat, pCnf ) )
+            {
+                sat_solver_delete( pSat );
+                Cnf_DataFree( pCnf );
+                return 1;
+            }
+        }
+        else
+        {
+            // add the OR clause for the outputs
+            if ( !Cnf_DataWriteOrClause( pSat, pCnf ) )
+            {
+                sat_solver_delete( pSat );
+                Cnf_DataFree( pCnf );
+                return 1;
+            }
+        }
+        vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan );
+        Cnf_DataFree( pCnf );
+
+
+    //    printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
+    //    ABC_PRT( "Time", Abc_Clock() - clk );
+
+        // simplify the problem
+        clk = Abc_Clock();
+        status = sat_solver_simplify(pSat);
+    //    printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
+    //    ABC_PRT( "Time", Abc_Clock() - clk );
+        if ( status == 0 )
+        {
+            Vec_IntFree( vCiIds );
+            sat_solver_delete( pSat );
+    //        printf( "The problem is UNSATISFIABLE after simplification.\n" );
+            return 1;
+        }
+
+        // solve the miter
+        clk = Abc_Clock();
+//        if ( fVerbose )
+//            pSat->verbosity = 1;
+        status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        if ( status == l_Undef )
+        {
+    //        printf( "The problem timed out.\n" );
+            RetValue = -1;
+        }
+        else if ( status == l_True )
+        {
+    //        printf( "The problem is SATISFIABLE.\n" );
+            RetValue = 0;
+        }
+        else if ( status == l_False )
+        {
+    //        printf( "The problem is UNSATISFIABLE.\n" );
+            RetValue = 1;
+        }
+        else
+            assert( 0 );
+
+    //    Abc_Print( 1, "The number of conflicts = %6d.  ", (int)pSat->stats.conflicts );
+    //    Abc_PrintTime( 1, "Solving time", Abc_Clock() - clk );
+ 
+        // if the problem is SAT, get the counterexample
+        if ( status == l_True )
+        {
+            pMan->pData = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize );
+        }
+        // free the sat_solver
+        if ( fVerbose )
+            Sat_SolverPrintStats( stdout, pSat );
+    //sat_solver_store_write( pSat, "trace.cnf" );
+    //sat_solver_store_free( pSat );
+        sat_solver_delete( pSat );
+        Vec_IntFree( vCiIds );
+        return RetValue;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recognizes what nodes are inputs of the EXOR.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManCountXors( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pFan0, * pFan1;
+    int i, Counter = 0;
+    Aig_ManForEachNode( p, pObj, i )
+        if ( Aig_ObjIsMuxType(pObj) && Aig_ObjRecognizeExor(pObj, &pFan0, &pFan1) )
+            Counter++;
+    return Counter;
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose )
+{
+    int nBTLimitStart =        300;   // starting SAT run
+    int nBTLimitFirst =          2;   // first fraiging iteration
+    int nBTLimitLast  = nConfLimit;   // the last-gasp SAT run
+
+    Fra_Par_t Params, * pParams = &Params;
+    Aig_Man_t * pAig = *ppAig, * pTemp;
+    int i, RetValue;
+    abctime clk;
+
+    // report the original miter
+    if ( fVerbose )
+    {
+        printf( "Original miter:   Nodes = %6d.\n", Aig_ManNodeNum(pAig) );
+    }
+    RetValue = Fra_FraigMiterStatus( pAig );
+//    assert( RetValue == -1 );
+    if ( RetValue == 0 )
+    {
+        pAig->pData = ABC_ALLOC( int, Aig_ManCiNum(pAig) );
+        memset( pAig->pData, 0, sizeof(int) * Aig_ManCiNum(pAig) );
+        return RetValue;
+    }
+
+    // if SAT only, solve without iteration
+clk = Abc_Clock();
+    RetValue = Fra_FraigSat( pAig, (ABC_INT64_T)2*nBTLimitStart, (ABC_INT64_T)0, 0, 0, 0, 1, 0, 0, 0 );
+    if ( fVerbose )
+    {
+        printf( "Initial SAT:      Nodes = %6d.  ", Aig_ManNodeNum(pAig) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    if ( RetValue >= 0 )
+        return RetValue;
+
+    // duplicate the AIG
+clk = Abc_Clock();
+    pAig = Dar_ManRwsat( pTemp = pAig, 1, 0 );
+    Aig_ManStop( pTemp );
+    if ( fVerbose )
+    {
+        printf( "Rewriting:        Nodes = %6d.  ", Aig_ManNodeNum(pAig) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+
+    // perform the loop
+    Fra_ParamsDefault( pParams );
+    pParams->nBTLimitNode = nBTLimitFirst;
+    pParams->nBTLimitMiter = nBTLimitStart;
+    pParams->fDontShowBar = 1;
+    pParams->fProve = 1;
+    for ( i = 0; i < 6; i++ )
+    {
+//printf( "Running fraiging with %d BTnode and %d BTmiter.\n", pParams->nBTLimitNode, pParams->nBTLimitMiter );
+        // try XOR balancing
+        if ( Aig_ManCountXors(pAig) * 30 > Aig_ManNodeNum(pAig) + 300 )
+        {
+clk = Abc_Clock();
+            pAig = Dar_ManBalanceXor( pTemp = pAig, 1, 0, 0 );
+            Aig_ManStop( pTemp );
+            if ( fVerbose )
+            {
+                printf( "Balance-X:        Nodes = %6d.  ", Aig_ManNodeNum(pAig) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+            } 
+        }
+
+        // run fraiging
+clk = Abc_Clock();
+        pAig = Fra_FraigPerform( pTemp = pAig, pParams );
+        Aig_ManStop( pTemp );
+        if ( fVerbose )
+        {
+            printf( "Fraiging (i=%d):   Nodes = %6d.  ", i+1, Aig_ManNodeNum(pAig) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+        }
+
+        // check the miter status
+        RetValue = Fra_FraigMiterStatus( pAig );
+        if ( RetValue >= 0 )
+            break;
+
+        // perform rewriting
+clk = Abc_Clock();
+        pAig = Dar_ManRewriteDefault( pTemp = pAig );
+        Aig_ManStop( pTemp );
+        if ( fVerbose )
+        {
+            printf( "Rewriting:        Nodes = %6d.  ", Aig_ManNodeNum(pAig) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+        } 
+
+        // check the miter status
+        RetValue = Fra_FraigMiterStatus( pAig );
+        if ( RetValue >= 0 )
+            break;
+        // try simulation
+
+        // set the parameters for the next run
+        pParams->nBTLimitNode = 8 * pParams->nBTLimitNode;
+        pParams->nBTLimitMiter = 2 * pParams->nBTLimitMiter;
+    }
+
+    // if still unsolved try last gasp
+    if ( RetValue == -1 )
+    {
+clk = Abc_Clock();
+        RetValue = Fra_FraigSat( pAig, (ABC_INT64_T)nBTLimitLast, (ABC_INT64_T)0, 0, 0, 0, 1, 0, 0, 0 );
+        if ( fVerbose )
+        {
+            printf( "Final SAT:        Nodes = %6d.  ", Aig_ManNodeNum(pAig) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+        }
+    }
+
+    *ppAig = pAig;
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_FraigCecPartitioned( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, int fVerbose )
+{
+    Aig_Man_t * pAig;
+    Vec_Ptr_t * vParts;
+    int i, RetValue = 1, nOutputs;
+    // create partitions
+    vParts = Aig_ManMiterPartitioned( pMan1, pMan2, nPartSize, fSmart );
+    // solve the partitions
+    nOutputs = -1;
+    Vec_PtrForEachEntry( Aig_Man_t *, vParts, pAig, i )
+    {
+        nOutputs++;
+        if ( fVerbose )
+        {
+            printf( "Verifying part %4d  (out of %4d)  PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", 
+                i+1, Vec_PtrSize(vParts), Aig_ManCiNum(pAig), Aig_ManCoNum(pAig), 
+                Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) );
+            fflush( stdout );
+        }
+        RetValue = Fra_FraigMiterStatus( pAig );
+        if ( RetValue == 1 )
+            continue;
+        if ( RetValue == 0 )
+            break;
+        RetValue = Fra_FraigCec( &pAig, nConfLimit, 0 );
+        Vec_PtrWriteEntry( vParts, i, pAig );
+        if ( RetValue == 1 )
+            continue;
+        if ( RetValue == 0 )
+            break;
+        break;
+    }
+    // clear the result
+    if ( fVerbose )
+    {
+        printf( "                                                                                          \r" );
+        fflush( stdout );
+    }
+    // report the timeout
+    if ( RetValue == -1 )
+    {
+        printf( "Timed out after verifying %d partitions (out of %d).\n", nOutputs, Vec_PtrSize(vParts) );
+        fflush( stdout );
+    }
+    // free intermediate results
+    Vec_PtrForEachEntry( Aig_Man_t *, vParts, pAig, i )
+        Aig_ManStop( pAig );
+    Vec_PtrFree( vParts );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_FraigCecTop( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, int fVerbose )
+{
+    Aig_Man_t * pTemp;
+    //Abc_NtkDarCec( pNtk1, pNtk2, fPartition, fVerbose );
+    int RetValue;
+    abctime clkTotal = Abc_Clock();
+
+    if ( Aig_ManCiNum(pMan1) != Aig_ManCiNum(pMan1) )
+    {
+        printf( "Abc_CommandAbc8Cec(): Miters have different number of PIs.\n" );
+        return 0;
+    }
+    if ( Aig_ManCoNum(pMan1) != Aig_ManCoNum(pMan1) )
+    {
+        printf( "Abc_CommandAbc8Cec(): Miters have different number of POs.\n" );
+        return 0;
+    }
+    assert( Aig_ManCiNum(pMan1) == Aig_ManCiNum(pMan1) );
+    assert( Aig_ManCoNum(pMan1) == Aig_ManCoNum(pMan1) );
+
+    // make sure that the first miter has more nodes
+    if ( Aig_ManNodeNum(pMan1) < Aig_ManNodeNum(pMan2) )
+    {
+        pTemp = pMan1;
+        pMan1 = pMan2;
+        pMan2 = pTemp;
+    }
+    assert( Aig_ManNodeNum(pMan1) >= Aig_ManNodeNum(pMan2) );
+
+    if ( nPartSize )
+        RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, nConfLimit, nPartSize, fSmart, fVerbose );
+    else // no partitioning
+        RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, nConfLimit, Aig_ManCoNum(pMan1), 0, fVerbose );
+
+    // report the miter
+    if ( RetValue == 1 )
+    {
+        printf( "Networks are equivalent.   " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+    }
+    else if ( RetValue == 0 )
+    {
+        printf( "Networks are NOT EQUIVALENT.   " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+    }
+    else
+    {
+        printf( "Networks are UNDECIDED.   " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+    }
+    fflush( stdout );
+    return RetValue;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/fraClass.c b/abc-build/src/proof/fra/fraClass.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fraClass.c
@@ -0,0 +1,862 @@
+/**CFile****************************************************************
+
+  FileName    [fraClass.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fraClass.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+    The candidate equivalence classes are stored as a vector of pointers 
+    to the array of pointers to the nodes in each class.
+    The first node of the class is its representative node.
+    The representative has the smallest topological order among the class nodes.
+    The nodes inside each class are ordered according to their topological order.
+    The classes are ordered according to the topological order of their representatives.
+    The array of pointers to the class nodes is terminated with a NULL pointer.
+    To enable dynamic addition of new classes (during class refinement),
+    each array has at least as many NULLs in the end, as there are nodes in the class.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline Aig_Obj_t *  Fra_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj )                       { return ppNexts[pObj->Id];  }
+static inline void         Fra_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts representation of equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fra_Cla_t * Fra_ClassesStart( Aig_Man_t * pAig )
+{
+    Fra_Cla_t * p;
+    p = ABC_ALLOC( Fra_Cla_t, 1 );
+    memset( p, 0, sizeof(Fra_Cla_t) );
+    p->pAig = pAig;
+    p->pMemRepr  = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
+    memset( p->pMemRepr, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pAig) );
+    p->vClasses     = Vec_PtrAlloc( 100 );
+    p->vClasses1    = Vec_PtrAlloc( 100 );
+    p->vClassesTemp = Vec_PtrAlloc( 100 );
+    p->vClassOld    = Vec_PtrAlloc( 100 );
+    p->vClassNew    = Vec_PtrAlloc( 100 );
+    p->pFuncNodeHash      = Fra_SmlNodeHash;
+    p->pFuncNodeIsConst   = Fra_SmlNodeIsConst;
+    p->pFuncNodesAreEqual = Fra_SmlNodesAreEqual;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop representation of equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClassesStop( Fra_Cla_t * p )
+{
+    ABC_FREE( p->pMemClasses );
+    ABC_FREE( p->pMemRepr );
+    if ( p->vClassesTemp ) Vec_PtrFree( p->vClassesTemp );
+    if ( p->vClassNew )    Vec_PtrFree( p->vClassNew );
+    if ( p->vClassOld )    Vec_PtrFree( p->vClassOld );
+    if ( p->vClasses1 )    Vec_PtrFree( p->vClasses1 );
+    if ( p->vClasses )     Vec_PtrFree( p->vClasses );
+    if ( p->vImps )        Vec_IntFree( p->vImps );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts representation of equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClassesCopyReprs( Fra_Cla_t * p, Vec_Ptr_t * vFailed )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManReprStart( p->pAig, Aig_ManObjNumMax(p->pAig) );
+    memmove( p->pAig->pReprs, p->pMemRepr, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p->pAig) );
+    if ( Vec_PtrSize(p->vClasses1) == 0 && Vec_PtrSize(p->vClasses) == 0 )
+    {
+        Aig_ManForEachObj( p->pAig, pObj, i )
+        {
+            if ( p->pAig->pReprs[i] != NULL )
+                printf( "Classes are not cleared!\n" );
+            assert( p->pAig->pReprs[i] == NULL );
+        }
+    }
+    if ( vFailed )
+        Vec_PtrForEachEntry( Aig_Obj_t *, vFailed, pObj, i )
+            p->pAig->pReprs[pObj->Id] = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints simulation classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClassCount( Aig_Obj_t ** pClass )
+{
+    Aig_Obj_t * pTemp;
+    int i;
+    for ( i = 0; (pTemp = pClass[i]); i++ );
+    return i;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of literals.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClassesCountLits( Fra_Cla_t * p )
+{
+    Aig_Obj_t ** pClass;
+    int i, nNodes, nLits = 0;
+    nLits = Vec_PtrSize( p->vClasses1 );
+    Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i )
+    {
+        nNodes = Fra_ClassCount( pClass );
+        assert( nNodes > 1 );
+        nLits += nNodes - 1;
+    }
+    return nLits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of pairs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClassesCountPairs( Fra_Cla_t * p )
+{
+    Aig_Obj_t ** pClass;
+    int i, nNodes, nPairs = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i )
+    {
+        nNodes = Fra_ClassCount( pClass );
+        assert( nNodes > 1 );
+        nPairs += nNodes * (nNodes - 1) / 2;
+    }
+    return nPairs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints simulation classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_PrintClass( Fra_Cla_t * p, Aig_Obj_t ** pClass )
+{
+    Aig_Obj_t * pTemp;
+    int i;
+    for ( i = 1; (pTemp = pClass[i]); i++ )
+        assert( Fra_ClassObjRepr(pTemp) == pClass[0] );
+    printf( "{ " );
+    for ( i = 0; (pTemp = pClass[i]); i++ )
+        printf( "%d(%d,%d) ", pTemp->Id, pTemp->Level, Aig_SupportSize(p->pAig,pTemp) );
+    printf( "}\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints simulation classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClassesPrint( Fra_Cla_t * p, int fVeryVerbose )
+{
+    Aig_Obj_t ** pClass;
+    Aig_Obj_t * pObj;
+    int i;
+
+    printf( "Const = %5d. Class = %5d. Lit = %5d. ", 
+        Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses), Fra_ClassesCountLits(p) );
+    if ( p->vImps && Vec_IntSize(p->vImps) > 0 )
+        printf( "Imp = %5d. ", Vec_IntSize(p->vImps) );
+    printf( "\n" );
+
+    if ( fVeryVerbose )
+    {
+        Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i )
+            assert( Fra_ClassObjRepr(pObj) == Aig_ManConst1(p->pAig) );
+        printf( "Constants { " );
+        Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i )
+            printf( "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) );
+        printf( "}\n" );
+        Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i )
+        {
+            printf( "%3d (%3d) : ", i, Fra_ClassCount(pClass) );
+            Fra_PrintClass( p, pClass );
+        }
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates initial simulation classes.]
+
+  Description [Assumes that simulation info is assigned.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClassesPrepare( Fra_Cla_t * p, int fLatchCorr, int nMaxLevs )
+{
+    Aig_Obj_t ** ppTable, ** ppNexts;
+    Aig_Obj_t * pObj, * pTemp;
+    int i, k, nTableSize, nEntries, nNodes, iEntry;
+
+    // allocate the hash table hashing simulation info into nodes
+    nTableSize = Abc_PrimeCudd( Aig_ManObjNumMax(p->pAig) );
+    ppTable = ABC_FALLOC( Aig_Obj_t *, nTableSize ); 
+    ppNexts = ABC_FALLOC( Aig_Obj_t *, nTableSize ); 
+    memset( ppTable, 0, sizeof(Aig_Obj_t *) * nTableSize );
+
+    // add all the nodes to the hash table
+    Vec_PtrClear( p->vClasses1 );
+    Aig_ManForEachObj( p->pAig, pObj, i )
+    {
+        if ( fLatchCorr )
+        {
+            if ( !Aig_ObjIsCi(pObj) )
+                continue;
+        }
+        else
+        {
+            if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
+                continue;
+            // skip the node with more that the given number of levels
+            if ( nMaxLevs && (int)pObj->Level > nMaxLevs )
+                continue;
+        }
+        // hash the node by its simulation info
+        iEntry = p->pFuncNodeHash( pObj, nTableSize );
+        // check if the node belongs to the class of constant 1
+        if ( p->pFuncNodeIsConst( pObj ) )
+        {
+            Vec_PtrPush( p->vClasses1, pObj );
+            Fra_ClassObjSetRepr( pObj, Aig_ManConst1(p->pAig) );
+            continue;
+        }
+        // add the node to the class
+        if ( ppTable[iEntry] == NULL )
+        {
+            ppTable[iEntry] = pObj;
+            Fra_ObjSetNext( ppNexts, pObj, pObj );
+        }
+        else
+        {
+            Fra_ObjSetNext( ppNexts, pObj, Fra_ObjNext(ppNexts,ppTable[iEntry]) );
+            Fra_ObjSetNext( ppNexts, ppTable[iEntry], pObj );
+        }
+    }
+
+    // count the total number of nodes in the non-trivial classes
+    // mark the representative nodes of each equivalence class
+    nEntries = 0;
+    for ( i = 0; i < nTableSize; i++ )
+        if ( ppTable[i] && ppTable[i] != Fra_ObjNext(ppNexts, ppTable[i]) )
+        {
+            for ( pTemp = Fra_ObjNext(ppNexts, ppTable[i]), k = 1; 
+                  pTemp != ppTable[i]; 
+                  pTemp = Fra_ObjNext(ppNexts, pTemp), k++ );
+            assert( k > 1 );
+            nEntries += k;
+            // mark the node
+            assert( ppTable[i]->fMarkA == 0 );
+            ppTable[i]->fMarkA = 1;
+        }
+
+    // allocate room for classes
+    p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, 2*(nEntries + Vec_PtrSize(p->vClasses1)) );
+    p->pMemClassesFree = p->pMemClasses + 2*nEntries;
+ 
+    // copy the entries into storage in the topological order
+    Vec_PtrClear( p->vClasses );
+    nEntries = 0;
+    Aig_ManForEachObj( p->pAig, pObj, i )
+    {
+        if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
+            continue;
+        // skip the nodes that are not representatives of non-trivial classes
+        if ( pObj->fMarkA == 0 )
+            continue;
+        pObj->fMarkA = 0;
+        // add the class of nodes
+        Vec_PtrPush( p->vClasses, p->pMemClasses + 2*nEntries );
+        // count the number of entries in this class
+        for ( pTemp = Fra_ObjNext(ppNexts, pObj), k = 1; 
+              pTemp != pObj; 
+              pTemp = Fra_ObjNext(ppNexts, pTemp), k++ );
+        nNodes = k;
+        assert( nNodes > 1 );
+        // add the nodes to the class in the topological order
+        p->pMemClasses[2*nEntries] = pObj;
+        for ( pTemp = Fra_ObjNext(ppNexts, pObj), k = 1; 
+              pTemp != pObj; 
+              pTemp = Fra_ObjNext(ppNexts, pTemp), k++ )
+        {
+            p->pMemClasses[2*nEntries+nNodes-k] = pTemp;
+            Fra_ClassObjSetRepr( pTemp, pObj );
+        }
+        // add as many empty entries
+        p->pMemClasses[2*nEntries + nNodes] = NULL;
+        // increment the number of entries
+        nEntries += k;
+    }
+    ABC_FREE( ppTable );
+    ABC_FREE( ppNexts );
+    // now it is time to refine the classes
+    Fra_ClassesRefine( p );
+//    Fra_ClassesPrint( p, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines one class using simulation info.]
+
+  Description [Returns the new class if refinement happened.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t ** Fra_RefineClassOne( Fra_Cla_t * p, Aig_Obj_t ** ppClass )
+{
+    Aig_Obj_t * pObj, ** ppThis;
+    int i;
+    assert( ppClass[0] != NULL && ppClass[1] != NULL );
+
+    // check if the class is going to be refined
+    for ( ppThis = ppClass + 1; (pObj = *ppThis); ppThis++ )        
+        if ( !p->pFuncNodesAreEqual(ppClass[0], pObj) )
+            break;
+    if ( pObj == NULL )
+        return NULL;
+    // split the class
+    Vec_PtrClear( p->vClassOld );
+    Vec_PtrClear( p->vClassNew );
+    Vec_PtrPush( p->vClassOld, ppClass[0] );
+    for ( ppThis = ppClass + 1; (pObj = *ppThis); ppThis++ )        
+        if ( p->pFuncNodesAreEqual(ppClass[0], pObj) )
+            Vec_PtrPush( p->vClassOld, pObj );
+        else
+            Vec_PtrPush( p->vClassNew, pObj );
+/*
+    printf( "Refining class (" );
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i )
+        printf( "%d,", pObj->Id );
+    printf( ") + (" );
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+        printf( "%d,", pObj->Id );
+    printf( ")\n" );
+*/
+    // put the nodes back into the class memory
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i )
+    {
+        ppClass[i] = pObj;
+        ppClass[Vec_PtrSize(p->vClassOld)+i] = NULL;
+        Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL );
+    }
+    ppClass += 2*Vec_PtrSize(p->vClassOld);
+    // put the new nodes into the class memory
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+    {
+        ppClass[i] = pObj;
+        ppClass[Vec_PtrSize(p->vClassNew)+i] = NULL;
+        Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL );
+    }
+    return ppClass;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Iteratively refines the classes after simulation.]
+
+  Description [Returns the number of refinements performed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_RefineClassLastIter( Fra_Cla_t * p, Vec_Ptr_t * vClasses )
+{
+    Aig_Obj_t ** pClass, ** pClass2;
+    int nRefis;
+    pClass = (Aig_Obj_t **)Vec_PtrEntryLast( vClasses );
+    for ( nRefis = 0; (pClass2 = Fra_RefineClassOne( p, pClass )); nRefis++ )
+    {
+        // if the original class is trivial, remove it
+        if ( pClass[1] == NULL )
+            Vec_PtrPop( vClasses );
+        // if the new class is trivial, stop
+        if ( pClass2[1] == NULL )
+        {
+            nRefis++;
+            break;
+        }
+        // othewise, add the class and continue
+        assert( pClass2[0] != NULL );
+        Vec_PtrPush( vClasses, pClass2 );
+        pClass = pClass2;
+    }
+    return nRefis;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines the classes after simulation.]
+
+  Description [Assumes that simulation info is assigned. Returns the
+  number of classes refined.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClassesRefine( Fra_Cla_t * p )
+{
+    Vec_Ptr_t * vTemp;
+    Aig_Obj_t ** pClass;
+    int i, nRefis;
+    // refine the classes
+    nRefis = 0;
+    Vec_PtrClear( p->vClassesTemp );
+    Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i )
+    {
+        // add the class to the new array
+        assert( pClass[0] != NULL );
+        Vec_PtrPush( p->vClassesTemp, pClass );
+        // refine the class iteratively
+        nRefis += Fra_RefineClassLastIter( p, p->vClassesTemp );
+    }
+    // exchange the class representation
+    vTemp = p->vClassesTemp;
+    p->vClassesTemp = p->vClasses;
+    p->vClasses = vTemp;
+    return nRefis;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines constant 1 equivalence class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClassesRefine1( Fra_Cla_t * p, int fRefineNewClass, int * pSkipped )
+{
+    Aig_Obj_t * pObj, ** ppClass;
+    int i, k, nRefis = 1;
+    // check if there is anything to refine
+    if ( Vec_PtrSize(p->vClasses1) == 0 )
+        return 0;
+    // make sure constant 1 class contains only non-constant nodes
+    assert( Vec_PtrEntry(p->vClasses1,0) != Aig_ManConst1(p->pAig) );
+    // collect all the nodes to be refined
+    k = 0;
+    Vec_PtrClear( p->vClassNew );
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i )
+    {
+        if ( p->pFuncNodeIsConst( pObj ) )
+            Vec_PtrWriteEntry( p->vClasses1, k++, pObj );
+        else 
+            Vec_PtrPush( p->vClassNew, pObj );
+    }
+    Vec_PtrShrink( p->vClasses1, k );
+    if ( Vec_PtrSize(p->vClassNew) == 0 )
+        return 0;
+/*
+    printf( "Refined const-1 class: {" );
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+        printf( " %d", pObj->Id );
+    printf( " }\n" );
+*/
+    if ( Vec_PtrSize(p->vClassNew) == 1 )
+    {
+        Fra_ClassObjSetRepr( (Aig_Obj_t *)Vec_PtrEntry(p->vClassNew,0), NULL );
+        return 1;
+    }
+    // create a new class composed of these nodes
+    ppClass = p->pMemClassesFree;
+    p->pMemClassesFree += 2 * Vec_PtrSize(p->vClassNew);
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+    {
+        ppClass[i] = pObj;
+        ppClass[Vec_PtrSize(p->vClassNew)+i] = NULL;
+        Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL );
+    }
+    assert( ppClass[0] != NULL );
+    Vec_PtrPush( p->vClasses, ppClass );
+    // iteratively refine this class
+    if ( fRefineNewClass )
+        nRefis += Fra_RefineClassLastIter( p, p->vClasses );
+    else if ( pSkipped )
+        (*pSkipped)++;
+    return nRefis;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts representation of equivalence classes with one class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClassesTest( Fra_Cla_t * p, int Id1, int Id2 )
+{
+    Aig_Obj_t ** pClass;
+    p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, 4 );
+    pClass = p->pMemClasses;
+    assert( Id1 < Id2 );
+    pClass[0] = Aig_ManObj( p->pAig, Id1 );
+    pClass[1] = Aig_ManObj( p->pAig, Id2 );
+    pClass[2] = NULL;
+    pClass[3] = NULL;
+    Fra_ClassObjSetRepr( pClass[1], pClass[0] );
+    Vec_PtrPush( p->vClasses, pClass );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates latch correspondence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClassesLatchCorr( Fra_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, nEntries = 0;
+    Vec_PtrClear( p->pCla->vClasses1 );
+    Aig_ManForEachLoSeq( p->pManAig, pObj, i )
+    {
+        Vec_PtrPush( p->pCla->vClasses1, pObj );
+        Fra_ClassObjSetRepr( pObj, Aig_ManConst1(p->pManAig) );
+    }
+    // allocate room for classes
+    p->pCla->pMemClasses = ABC_ALLOC( Aig_Obj_t *, 2*(nEntries + Vec_PtrSize(p->pCla->vClasses1)) );
+    p->pCla->pMemClassesFree = p->pCla->pMemClasses + 2*nEntries;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Postprocesses the classes by removing half of the less useful.]
+
+  Description []
+               
+  SideEffects [] 
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClassesPostprocess( Fra_Cla_t * p )
+{
+    int Ratio = 2;
+    Fra_Sml_t * pComb;
+    Aig_Obj_t * pObj, * pRepr, ** ppClass;
+    int * pWeights, WeightMax = 0, i, k, c;
+    // perform combinational simulation
+    pComb = Fra_SmlSimulateComb( p->pAig, 32, 0 );
+    // compute the weight of each node in the classes
+    pWeights = ABC_ALLOC( int, Aig_ManObjNumMax(p->pAig) );
+    memset( pWeights, 0, sizeof(int) * Aig_ManObjNumMax(p->pAig) );
+    Aig_ManForEachObj( p->pAig, pObj, i )
+    { 
+        pRepr = Fra_ClassObjRepr( pObj );
+        if ( pRepr == NULL )
+            continue;
+        pWeights[i] = Fra_SmlNodeNotEquWeight( pComb, pRepr->Id, pObj->Id );
+        WeightMax = Abc_MaxInt( WeightMax, pWeights[i] );
+    }
+    Fra_SmlStop( pComb );
+    printf( "Before: Const = %6d. Class = %6d.  ", Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses) );
+    // remove nodes from classes whose weight is less than WeightMax/Ratio
+    k = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i )
+    {
+        if ( pWeights[pObj->Id] >= WeightMax/Ratio )
+            Vec_PtrWriteEntry( p->vClasses1, k++, pObj );
+        else
+            Fra_ClassObjSetRepr( pObj, NULL );
+    }
+    Vec_PtrShrink( p->vClasses1, k );
+    // in each class, compact the nodes
+    Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, ppClass, i )
+    {
+        k = 1;
+        for ( c = 1; ppClass[c]; c++ )
+        {
+            if ( pWeights[ppClass[c]->Id] >= WeightMax/Ratio )
+                ppClass[k++] = ppClass[c];
+            else
+                Fra_ClassObjSetRepr( ppClass[c], NULL );
+        }
+        ppClass[k] = NULL;
+    }
+    // remove classes with only repr
+    k = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, ppClass, i )
+        if ( ppClass[1] != NULL )
+            Vec_PtrWriteEntry( p->vClasses, k++, ppClass );
+    Vec_PtrShrink( p->vClasses, k );
+    printf( "After: Const = %6d. Class = %6d. \n", Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses) );
+    ABC_FREE( pWeights );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Postprocesses the classes by selecting representative lowest in top order.]
+
+  Description []
+               
+  SideEffects [] 
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClassesSelectRepr( Fra_Cla_t * p )
+{
+    Aig_Obj_t ** pClass, * pNodeMin;
+    int i, c, cMinSupp, nSuppSizeMin, nSuppSizeCur;
+    // reassign representatives in each class
+    Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i )
+    {
+        // collect support sizes and find the min-support node
+        cMinSupp = -1;
+        pNodeMin = NULL;
+        nSuppSizeMin = ABC_INFINITY;
+        for ( c = 0; pClass[c]; c++ )
+        {
+            nSuppSizeCur = Aig_SupportSize( p->pAig, pClass[c] );
+//            nSuppSizeCur = 1;
+            if ( nSuppSizeMin > nSuppSizeCur || 
+                (nSuppSizeMin == nSuppSizeCur && pNodeMin->Level > pClass[c]->Level) )
+            {
+                nSuppSizeMin = nSuppSizeCur;
+                pNodeMin = pClass[c];
+                cMinSupp = c; 
+            }
+        }
+        // skip the case when the repr did not change
+        if ( cMinSupp == 0 )
+            continue;
+        // make the new node the representative of the class
+        pClass[cMinSupp] = pClass[0];
+        pClass[0] = pNodeMin;
+        // set the representative
+        for ( c = 0; pClass[c]; c++ )
+            Fra_ClassObjSetRepr( pClass[c], c? pClass[0] : NULL );
+    }
+}
+
+
+
+static inline Aig_Obj_t * Fra_ObjEqu( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj )                       { return ppEquivs[pObj->Id];  }
+static inline void        Fra_ObjSetEqu( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { ppEquivs[pObj->Id] = pNode; }
+
+static inline Aig_Obj_t * Fra_ObjChild0Equ( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj ) { return Aig_NotCond(Fra_ObjEqu(ppEquivs,Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj));  }
+static inline Aig_Obj_t * Fra_ObjChild1Equ( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj ) { return Aig_NotCond(Fra_ObjEqu(ppEquivs,Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj));  }
+
+/**Function*************************************************************
+
+  Synopsis    [Add the node and its constraints to the new AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fra_ClassesDeriveNode( Aig_Man_t * pManFraig, Aig_Obj_t * pObj, Aig_Obj_t ** ppEquivs )
+{
+    Aig_Obj_t * pObjNew, * pObjRepr, * pObjReprNew, * pMiter;//, * pObjNew2;
+    // skip nodes without representative
+    if ( (pObjRepr = Fra_ClassObjRepr(pObj)) == NULL )
+        return;
+    assert( pObjRepr->Id < pObj->Id );
+    // get the new node 
+    pObjNew = Fra_ObjEqu( ppEquivs, pObj );
+    // get the new node of the representative
+    pObjReprNew = Fra_ObjEqu( ppEquivs, pObjRepr );
+    // if this is the same node, no need to add constraints
+    if ( Aig_Regular(pObjNew) == Aig_Regular(pObjReprNew) )
+        return;
+    // these are different nodes - perform speculative reduction
+//    pObjNew2 = Aig_NotCond( pObjReprNew, pObj->fPhase ^ pObjRepr->fPhase );
+    // set the new node
+//    Fra_ObjSetEqu( ppEquivs, pObj, pObjNew2 );
+    // add the constraint
+    pMiter = Aig_Exor( pManFraig, Aig_Regular(pObjNew), Aig_Regular(pObjReprNew) );
+    pMiter = Aig_NotCond( pMiter, Aig_Regular(pMiter)->fPhase ^ Aig_IsComplement(pMiter) );
+    pMiter = Aig_Not( pMiter );
+    Aig_ObjCreateCo( pManFraig, pMiter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives AIG for the partitioned problem.]
+
+  Description []
+               
+  SideEffects [] 
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Fra_ClassesDeriveAig( Fra_Cla_t * p, int nFramesK )
+{
+    Aig_Man_t * pManFraig;
+    Aig_Obj_t * pObj, * pObjNew;
+    Aig_Obj_t ** pLatches, ** ppEquivs;
+    int i, k, f, nFramesAll = nFramesK + 1;
+    assert( Aig_ManRegNum(p->pAig) > 0 );
+    assert( Aig_ManRegNum(p->pAig) < Aig_ManCiNum(p->pAig) );
+    assert( nFramesK > 0 );
+    // start the fraig package
+    pManFraig = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * nFramesAll );
+    pManFraig->pName = Abc_UtilStrsav( p->pAig->pName );
+    pManFraig->pSpec = Abc_UtilStrsav( p->pAig->pSpec );
+    // allocate place for the node mapping
+    ppEquivs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) );
+    Fra_ObjSetEqu( ppEquivs, Aig_ManConst1(p->pAig), Aig_ManConst1(pManFraig) );
+    // create latches for the first frame
+    Aig_ManForEachLoSeq( p->pAig, pObj, i )
+        Fra_ObjSetEqu( ppEquivs, pObj, Aig_ObjCreateCi(pManFraig) );
+    // add timeframes
+    pLatches = ABC_ALLOC( Aig_Obj_t *, Aig_ManRegNum(p->pAig) );
+    for ( f = 0; f < nFramesAll; f++ )
+    {
+        // create PIs for this frame
+        Aig_ManForEachPiSeq( p->pAig, pObj, i )
+            Fra_ObjSetEqu( ppEquivs, pObj, Aig_ObjCreateCi(pManFraig) );
+        // set the constraints on the latch outputs
+        Aig_ManForEachLoSeq( p->pAig, pObj, i )
+            Fra_ClassesDeriveNode( pManFraig, pObj, ppEquivs );
+        // add internal nodes of this frame
+        Aig_ManForEachNode( p->pAig, pObj, i )
+        {
+            pObjNew = Aig_And( pManFraig, Fra_ObjChild0Equ(ppEquivs, pObj), Fra_ObjChild1Equ(ppEquivs, pObj) );
+            Fra_ObjSetEqu( ppEquivs, pObj, pObjNew );
+            Fra_ClassesDeriveNode( pManFraig, pObj, ppEquivs );
+        }
+        if ( f == nFramesAll - 1 )
+            break;
+        if ( f == nFramesAll - 2 )
+            pManFraig->nAsserts = Aig_ManCoNum(pManFraig);
+        // save the latch input values
+        k = 0;
+        Aig_ManForEachLiSeq( p->pAig, pObj, i )
+            pLatches[k++] = Fra_ObjChild0Equ( ppEquivs, pObj );
+        // insert them to the latch output values
+        k = 0;
+        Aig_ManForEachLoSeq( p->pAig, pObj, i )
+            Fra_ObjSetEqu( ppEquivs, pObj, pLatches[k++] );
+    }
+    ABC_FREE( pLatches );
+    ABC_FREE( ppEquivs );
+    // mark the asserts
+    assert( Aig_ManCoNum(pManFraig) % nFramesAll == 0 );
+printf( "Assert miters = %6d. Output miters = %6d.\n", 
+       pManFraig->nAsserts, Aig_ManCoNum(pManFraig) - pManFraig->nAsserts );
+    // remove dangling nodes
+    Aig_ManCleanup( pManFraig );
+    return pManFraig;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/fraClau.c b/abc-build/src/proof/fra/fraClau.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fraClau.c
@@ -0,0 +1,745 @@
+/**CFile****************************************************************
+
+  FileName    [fraClau.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    [Induction with clause strengthening.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fraClau.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+    This code is inspired by the paper: Aaron Bradley and Zohar Manna, 
+    "Checking safety by inductive generalization of counterexamples to 
+    induction", FMCAD '07.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Cla_Man_t_    Cla_Man_t;
+struct Cla_Man_t_
+{
+    // SAT solvers
+    sat_solver *     pSatMain;
+    sat_solver *     pSatTest;
+    sat_solver *     pSatBmc;
+    // CNF for the test solver
+//    Cnf_Dat_t *      pCnfTest;
+    // SAT variables
+    Vec_Int_t *      vSatVarsMainCs;
+    Vec_Int_t *      vSatVarsTestCs;
+    Vec_Int_t *      vSatVarsTestNs;
+    Vec_Int_t *      vSatVarsBmcNs;
+    // helper variables
+    int              nSatVarsTestBeg;
+    int              nSatVarsTestCur;
+    // counter-examples
+    Vec_Int_t *      vCexMain0;
+    Vec_Int_t *      vCexMain;
+    Vec_Int_t *      vCexTest;
+    Vec_Int_t *      vCexBase;
+    Vec_Int_t *      vCexAssm;
+    Vec_Int_t *      vCexBmc;
+    // mapping of CS into NS var numbers
+    int *            pMapCsMainToCsTest; 
+    int *            pMapCsTestToCsMain; 
+    int *            pMapCsTestToNsTest; 
+    int *            pMapCsTestToNsBmc;  
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Saves variables corresponding to latch outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Fra_ClauSaveLatchVars( Aig_Man_t * pMan, Cnf_Dat_t * pCnf, int fCsVars )
+{
+    Vec_Int_t * vVars;
+    Aig_Obj_t * pObjLo, * pObjLi;
+    int i;
+    vVars = Vec_IntAlloc( Aig_ManRegNum(pMan) );
+    Aig_ManForEachLiLoSeq( pMan, pObjLi, pObjLo, i )
+        Vec_IntPush( vVars, pCnf->pVarNums[fCsVars? pObjLo->Id : pObjLi->Id] );
+    return vVars;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Saves variables corresponding to latch outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Fra_ClauSaveOutputVars( Aig_Man_t * pMan, Cnf_Dat_t * pCnf )
+{
+    Vec_Int_t * vVars;
+    Aig_Obj_t * pObj;
+    int i;
+    vVars = Vec_IntAlloc( Aig_ManCoNum(pMan) );
+    Aig_ManForEachCo( pMan, pObj, i )
+        Vec_IntPush( vVars, pCnf->pVarNums[pObj->Id] );
+    return vVars;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Saves variables corresponding to latch outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Fra_ClauSaveInputVars( Aig_Man_t * pMan, Cnf_Dat_t * pCnf, int nStarting )
+{
+    Vec_Int_t * vVars;
+    Aig_Obj_t * pObj;
+    int i;
+    vVars = Vec_IntAlloc( Aig_ManCiNum(pMan) - nStarting );
+    Aig_ManForEachCi( pMan, pObj, i )
+    {
+        if ( i < nStarting )
+            continue;
+        Vec_IntPush( vVars, pCnf->pVarNums[pObj->Id] );
+    }
+    return vVars;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Saves variables corresponding to latch outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Fra_ClauCreateMapping( Vec_Int_t * vSatVarsFrom, Vec_Int_t * vSatVarsTo, int nVarsMax )
+{
+    int * pMapping, Var, i;
+    assert( Vec_IntSize(vSatVarsFrom) == Vec_IntSize(vSatVarsTo) );
+    pMapping = ABC_ALLOC( int, nVarsMax );
+    for ( i = 0; i < nVarsMax; i++ )
+        pMapping[i] = -1;
+    Vec_IntForEachEntry( vSatVarsFrom, Var, i )
+        pMapping[Var] = Vec_IntEntry(vSatVarsTo,i);
+    return pMapping;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClauStop( Cla_Man_t * p )
+{
+    ABC_FREE( p->pMapCsMainToCsTest );
+    ABC_FREE( p->pMapCsTestToCsMain );
+    ABC_FREE( p->pMapCsTestToNsTest );
+    ABC_FREE( p->pMapCsTestToNsBmc  );
+    Vec_IntFree( p->vSatVarsMainCs );
+    Vec_IntFree( p->vSatVarsTestCs );
+    Vec_IntFree( p->vSatVarsTestNs );
+    Vec_IntFree( p->vSatVarsBmcNs );
+    Vec_IntFree( p->vCexMain0 );
+    Vec_IntFree( p->vCexMain );
+    Vec_IntFree( p->vCexTest );
+    Vec_IntFree( p->vCexBase );
+    Vec_IntFree( p->vCexAssm );
+    Vec_IntFree( p->vCexBmc  );
+    if ( p->pSatMain ) sat_solver_delete( p->pSatMain );
+    if ( p->pSatTest ) sat_solver_delete( p->pSatTest );
+    if ( p->pSatBmc )  sat_solver_delete( p->pSatBmc );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Takes the AIG with the single output to be checked.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cla_Man_t * Fra_ClauStart( Aig_Man_t * pMan )
+{
+    Cla_Man_t * p;
+    Cnf_Dat_t * pCnfMain;
+    Cnf_Dat_t * pCnfTest;
+    Cnf_Dat_t * pCnfBmc;
+    Aig_Man_t * pFramesMain;
+    Aig_Man_t * pFramesTest;
+    Aig_Man_t * pFramesBmc;
+    assert( Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) == 1 );
+
+    // start the manager
+    p = ABC_ALLOC( Cla_Man_t, 1 );
+    memset( p, 0, sizeof(Cla_Man_t) );
+    p->vCexMain0 = Vec_IntAlloc( Aig_ManRegNum(pMan) );
+    p->vCexMain  = Vec_IntAlloc( Aig_ManRegNum(pMan) );
+    p->vCexTest  = Vec_IntAlloc( Aig_ManRegNum(pMan) );
+    p->vCexBase  = Vec_IntAlloc( Aig_ManRegNum(pMan) );
+    p->vCexAssm  = Vec_IntAlloc( Aig_ManRegNum(pMan) );
+    p->vCexBmc   = Vec_IntAlloc( Aig_ManRegNum(pMan) );
+
+    // derive two timeframes to be checked
+    pFramesMain = Aig_ManFrames( pMan, 2, 0, 1, 0, 0, NULL ); // nFrames, fInit, fOuts, fRegs
+//Aig_ManShow( pFramesMain, 0, NULL );
+    assert( Aig_ManCoNum(pFramesMain) == 2 );
+    Aig_ObjChild0Flip( Aig_ManCo(pFramesMain, 0) ); // complement the first output
+    pCnfMain = Cnf_DeriveSimple( pFramesMain, 0 );
+//Cnf_DataWriteIntoFile( pCnfMain, "temp.cnf", 1 );
+    p->pSatMain = (sat_solver *)Cnf_DataWriteIntoSolver( pCnfMain, 1, 0 );
+/*
+    {
+        int i;
+        Aig_Obj_t * pObj;
+        Aig_ManForEachObj( pFramesMain, pObj, i )
+            printf( "%d -> %d  \n", pObj->Id, pCnfMain->pVarNums[pObj->Id] );
+        printf( "\n" );
+    }
+*/
+
+    // derive one timeframe to be checked
+    pFramesTest = Aig_ManFrames( pMan, 1, 0, 0, 1, 0, NULL );
+    assert( Aig_ManCoNum(pFramesTest) == Aig_ManRegNum(pMan) );
+    pCnfTest = Cnf_DeriveSimple( pFramesTest, Aig_ManRegNum(pMan) );
+    p->pSatTest = (sat_solver *)Cnf_DataWriteIntoSolver( pCnfTest, 1, 0 );
+    p->nSatVarsTestBeg = p->nSatVarsTestCur = sat_solver_nvars( p->pSatTest );
+
+    // derive one timeframe to be checked for BMC
+    pFramesBmc = Aig_ManFrames( pMan, 1, 1, 0, 1, 0, NULL );
+//Aig_ManShow( pFramesBmc, 0, NULL );
+    assert( Aig_ManCoNum(pFramesBmc) == Aig_ManRegNum(pMan) );
+    pCnfBmc = Cnf_DeriveSimple( pFramesBmc, Aig_ManRegNum(pMan) );
+    p->pSatBmc = (sat_solver *)Cnf_DataWriteIntoSolver( pCnfBmc, 1, 0 );
+
+    // create variable sets
+    p->vSatVarsMainCs = Fra_ClauSaveInputVars( pFramesMain, pCnfMain, 2 * (Aig_ManCiNum(pMan)-Aig_ManRegNum(pMan)) );
+    p->vSatVarsTestCs = Fra_ClauSaveLatchVars( pFramesTest, pCnfTest, 1 );
+    p->vSatVarsTestNs = Fra_ClauSaveLatchVars( pFramesTest, pCnfTest, 0 );
+    p->vSatVarsBmcNs  = Fra_ClauSaveOutputVars( pFramesBmc, pCnfBmc );
+    assert( Vec_IntSize(p->vSatVarsTestCs) == Vec_IntSize(p->vSatVarsMainCs) );
+    assert( Vec_IntSize(p->vSatVarsTestCs) == Vec_IntSize(p->vSatVarsBmcNs) );
+
+    // create mapping of CS into NS vars
+    p->pMapCsMainToCsTest = Fra_ClauCreateMapping( p->vSatVarsMainCs, p->vSatVarsTestCs, Aig_ManObjNumMax(pFramesMain) );
+    p->pMapCsTestToCsMain = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsMainCs, Aig_ManObjNumMax(pFramesTest) );
+    p->pMapCsTestToNsTest = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsTestNs, Aig_ManObjNumMax(pFramesTest) );
+    p->pMapCsTestToNsBmc  = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsBmcNs,  Aig_ManObjNumMax(pFramesTest) );
+
+    // cleanup
+    Cnf_DataFree( pCnfMain );
+    Cnf_DataFree( pCnfTest );
+    Cnf_DataFree( pCnfBmc );
+    Aig_ManStop( pFramesMain );
+    Aig_ManStop( pFramesTest );
+    Aig_ManStop( pFramesBmc );
+    if ( p->pSatMain == NULL || p->pSatTest == NULL || p->pSatBmc == NULL )
+    {
+        Fra_ClauStop( p );
+        return NULL;
+    }
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Splits off second half and returns it as a new vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Vec_Int_t * Vec_IntSplitHalf( Vec_Int_t * vVec )
+{
+    Vec_Int_t * vPart;
+    int Entry, i;
+    assert( Vec_IntSize(vVec) > 1 );
+    vPart = Vec_IntAlloc( Vec_IntSize(vVec) / 2 + 1 );
+    Vec_IntForEachEntryStart( vVec, Entry, i, Vec_IntSize(vVec) / 2 )
+        Vec_IntPush( vPart, Entry );
+    Vec_IntShrink( vVec, Vec_IntSize(vVec) / 2 );
+    return vPart;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Complements all literals in the clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Vec_IntComplement( Vec_Int_t * vVec )
+{
+    int i;
+    for ( i = 0; i < Vec_IntSize(vVec); i++ )
+        vVec->pArray[i] = lit_neg( vVec->pArray[i] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the property holds. Returns counter-example if not.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClauCheckProperty( Cla_Man_t * p, Vec_Int_t * vCex )
+{
+    int nBTLimit = 0;
+    int RetValue, iVar, i;
+    sat_solver_act_var_clear( p->pSatMain );
+    RetValue = sat_solver_solve( p->pSatMain, NULL, NULL, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    Vec_IntClear( vCex );
+    if ( RetValue == l_False )
+        return 1;
+    assert( RetValue == l_True );
+    Vec_IntForEachEntry( p->vSatVarsMainCs, iVar, i )
+        Vec_IntPush( vCex, sat_solver_var_literal(p->pSatMain, iVar) );
+/*
+    {
+        int i;
+        for (i = 0; i < p->pSatMain->size; i++)
+            printf( "%d=%d ", i, p->pSatMain->model.ptr[i] == l_True );
+        printf( "\n" );
+    }
+*/
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the clause holds using BMC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClauCheckBmc( Cla_Man_t * p, Vec_Int_t * vClause )
+{
+    int nBTLimit = 0;
+    int RetValue;
+    RetValue = sat_solver_solve( p->pSatBmc, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause), 
+        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( RetValue == l_False )
+        return 1;
+    assert( RetValue == l_True );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Lifts the clause to depend on NS variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClauRemapClause( int * pMap, Vec_Int_t * vClause, Vec_Int_t * vRemapped, int fInv )
+{
+    int iLit, i;
+    Vec_IntClear( vRemapped );
+    Vec_IntForEachEntry( vClause, iLit, i )
+    {
+        assert( pMap[lit_var(iLit)] >= 0 );
+        iLit = toLitCond( pMap[lit_var(iLit)], lit_sign(iLit) ^ fInv );
+        Vec_IntPush( vRemapped, iLit );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the clause holds. Returns counter example if not.]
+
+  Description [Uses test SAT solver.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClauCheckClause( Cla_Man_t * p, Vec_Int_t * vClause, Vec_Int_t * vCex )
+{
+    int nBTLimit = 0;
+    int RetValue, iVar, i;
+    // complement literals
+    Vec_IntPush( vClause, toLit( p->nSatVarsTestCur++ ) ); // helper positive
+    Vec_IntComplement( vClause ); // helper negative (the clause is C v h')
+    // add the clause
+    RetValue = sat_solver_addclause( p->pSatTest, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause) );
+    assert( RetValue == 1 );
+    // complement all literals
+    Vec_IntPop( vClause );  // helper removed
+    Vec_IntComplement( vClause ); 
+    // create the assumption in terms of NS variables
+    Fra_ClauRemapClause( p->pMapCsTestToNsTest, vClause, p->vCexAssm, 0 );
+    // add helper literals
+    for ( i = p->nSatVarsTestBeg; i < p->nSatVarsTestCur - 1; i++ )
+        Vec_IntPush( p->vCexAssm, toLitCond(i,1) ); // other helpers negative
+    Vec_IntPush( p->vCexAssm, toLitCond(i,0) ); // positive helper
+    // try to solve
+    RetValue = sat_solver_solve( p->pSatTest, Vec_IntArray(p->vCexAssm), Vec_IntArray(p->vCexAssm) + Vec_IntSize(p->vCexAssm), 
+        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( vCex )
+        Vec_IntClear( vCex );
+    if ( RetValue == l_False )
+        return 1;
+    assert( RetValue == l_True );
+    if ( vCex )
+    {
+        Vec_IntForEachEntry( p->vSatVarsTestCs, iVar, i )
+            Vec_IntPush( vCex, sat_solver_var_literal(p->pSatTest, iVar) );
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces the counter-example by removing complemented literals.]
+
+  Description [Removes literals from vMain that differ from those in the  
+  counter-example (vNew). Relies on the fact that the PI variables are
+  assigned in the increasing order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClauReduceClause( Vec_Int_t * vMain, Vec_Int_t * vNew )
+{
+    int LitM, LitN, VarM, VarN, i, j, k;
+    assert( Vec_IntSize(vMain) <= Vec_IntSize(vNew) );
+    for ( i = j = k = 0; i < Vec_IntSize(vMain) && j < Vec_IntSize(vNew); )
+    {
+        LitM = Vec_IntEntry( vMain, i );
+        LitN = Vec_IntEntry( vNew, j );
+        VarM = lit_var( LitM );
+        VarN = lit_var( LitN );
+        if ( VarM < VarN )
+        {
+            assert( 0 );
+        }
+        else if ( VarM > VarN )
+        {
+            j++;
+        }
+        else // if ( VarM == VarN )
+        {
+            i++;
+            j++;
+            if ( LitM == LitN )
+                Vec_IntWriteEntry( vMain, k++, LitM );
+        }
+    }
+    assert( i == Vec_IntSize(vMain) );
+    Vec_IntShrink( vMain, k );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the minimal invariant that holds.]
+
+  Description [On entrace, vBasis does not hold, vBasis+vExtra holds but
+  is not minimal. On exit, vBasis is unchanged, vBasis+vExtra is minimal.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClauMinimizeClause_rec( Cla_Man_t * p, Vec_Int_t * vBasis, Vec_Int_t * vExtra )
+{
+    Vec_Int_t * vExtra2;
+    int nSizeOld;
+    if ( Vec_IntSize(vExtra) == 1 )
+        return;
+    nSizeOld = Vec_IntSize( vBasis );
+    vExtra2 = Vec_IntSplitHalf( vExtra );
+
+    // try the first half
+    Vec_IntAppend( vBasis, vExtra );
+    if ( Fra_ClauCheckClause( p, vBasis, NULL ) )
+    {
+        Vec_IntShrink( vBasis, nSizeOld );
+        Fra_ClauMinimizeClause_rec( p, vBasis, vExtra );
+        return;
+    }
+    Vec_IntShrink( vBasis, nSizeOld );
+
+    // try the second half
+    Vec_IntAppend( vBasis, vExtra2 );
+    if ( Fra_ClauCheckClause( p, vBasis, NULL ) )
+    {
+        Vec_IntShrink( vBasis, nSizeOld );
+        Fra_ClauMinimizeClause_rec( p, vBasis, vExtra2 );
+        return;
+    }
+//    Vec_IntShrink( vBasis, nSizeOld );
+
+    // find the smallest with the second half added
+    Fra_ClauMinimizeClause_rec( p, vBasis, vExtra );
+    Vec_IntShrink( vBasis, nSizeOld );
+    Vec_IntAppend( vBasis, vExtra );
+    // find the smallest with the second half added
+    Fra_ClauMinimizeClause_rec( p, vBasis, vExtra2 );
+    Vec_IntShrink( vBasis, nSizeOld );
+    Vec_IntAppend( vExtra, vExtra2 );
+    Vec_IntFree( vExtra2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Minimizes the clauses using a simple method.]
+
+  Description [The input and output clause are in vExtra.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClauMinimizeClause( Cla_Man_t * p, Vec_Int_t * vBasis, Vec_Int_t * vExtra )
+{
+    int iLit, iLit2, i, k;
+    Vec_IntForEachEntryReverse( vExtra, iLit, i )
+    {
+        // copy literals without the given one
+        Vec_IntClear( vBasis );
+        Vec_IntForEachEntry( vExtra, iLit2, k )
+            if ( k != i )
+                Vec_IntPush( vBasis, iLit2 );
+        // try whether it is inductive
+        if ( !Fra_ClauCheckClause( p, vBasis, NULL ) )
+            continue;
+        // the clause is inductive
+        // remove the literal
+        for ( k = i; k < Vec_IntSize(vExtra)-1; k++ )
+            Vec_IntWriteEntry( vExtra, k, Vec_IntEntry(vExtra,k+1) );
+        Vec_IntShrink( vExtra, Vec_IntSize(vExtra)-1 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClauPrintClause( Vec_Int_t * vSatCsVars, Vec_Int_t * vCex )
+{
+    int LitM, VarM, VarN, i, j, k;
+    assert( Vec_IntSize(vCex) <= Vec_IntSize(vSatCsVars) );
+    for ( i = j = k = 0; i < Vec_IntSize(vCex) && j < Vec_IntSize(vSatCsVars); )
+    {
+        LitM = Vec_IntEntry( vCex, i );
+        VarM = lit_var( LitM );
+        VarN = Vec_IntEntry( vSatCsVars, j );
+        if ( VarM < VarN )
+        {
+            assert( 0 );
+        }
+        else if ( VarM > VarN )
+        {
+            j++;
+            printf( "-" );
+        }
+        else // if ( VarM == VarN )
+        {
+            i++;
+            j++;
+            printf( "%d", !lit_sign(LitM) );
+        }
+    }
+    assert( i == Vec_IntSize(vCex) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Takes the AIG with the single output to be checked.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_Clau( Aig_Man_t * pMan, int nIters, int fVerbose, int fVeryVerbose )
+{
+    Cla_Man_t * p;
+    int Iter, RetValue, fFailed, i;
+    assert( Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) == 1 );
+    // create the manager
+    p = Fra_ClauStart( pMan );
+    if ( p == NULL )
+    {
+        printf( "The property is trivially inductive.\n" );
+        return 1;
+    }
+    // generate counter-examples and expand them
+    for ( Iter = 0; !Fra_ClauCheckProperty( p, p->vCexMain0 ) && Iter < nIters; Iter++ )
+    {
+        if ( fVerbose )
+            printf( "%4d : ", Iter );
+        // remap clause into the test manager
+        Fra_ClauRemapClause( p->pMapCsMainToCsTest, p->vCexMain0, p->vCexMain, 0 );
+        if ( fVerbose && fVeryVerbose )
+            Fra_ClauPrintClause( p->vSatVarsTestCs, p->vCexMain );
+        // the main counter-example is in p->vCexMain
+        // intermediate counter-examples are in p->vCexTest
+        // generate the reduced counter-example to the inductive property
+        fFailed = 0;
+        for ( i = 0; !Fra_ClauCheckClause( p, p->vCexMain, p->vCexTest ); i++ )
+        {
+            Fra_ClauReduceClause( p->vCexMain, p->vCexTest );
+            Fra_ClauRemapClause( p->pMapCsTestToNsBmc, p->vCexMain, p->vCexBmc, 0 );
+
+//            if ( !Fra_ClauCheckBmc(p, p->vCexBmc) )
+            if ( Vec_IntSize(p->vCexMain) < 1 )
+            {
+                Vec_IntComplement( p->vCexMain0 ); 
+                RetValue = sat_solver_addclause( p->pSatMain, Vec_IntArray(p->vCexMain0), Vec_IntArray(p->vCexMain0) + Vec_IntSize(p->vCexMain0) );
+                if ( RetValue == 0 )
+                {
+                    printf( "\nProperty is proved after %d iterations.\n", Iter+1 );
+                    return 0;
+                }
+                fFailed = 1;
+                break;
+            }
+        }
+        if ( fFailed )
+        {
+            if ( fVerbose )
+                printf( " Reducing failed after %d iterations (BMC failed).\n", i );
+            continue;
+        }
+        if ( Vec_IntSize(p->vCexMain) == 0 )
+        {
+            if ( fVerbose )
+                printf( " Reducing failed after %d iterations (nothing left).\n", i );
+            continue;
+        }
+        if ( fVerbose )
+            printf( "  " );
+        if ( fVerbose && fVeryVerbose )
+            Fra_ClauPrintClause( p->vSatVarsTestCs, p->vCexMain );
+        if ( fVerbose )
+            printf( " LitsInd = %3d.  ", Vec_IntSize(p->vCexMain) );
+        // minimize the inductive property
+        Vec_IntClear( p->vCexBase );
+        if ( Vec_IntSize(p->vCexMain) > 1 )
+//        Fra_ClauMinimizeClause_rec( p, p->vCexBase, p->vCexMain );
+            Fra_ClauMinimizeClause( p, p->vCexBase, p->vCexMain );
+        assert( Vec_IntSize(p->vCexMain) > 0 );
+        if ( fVerbose && fVeryVerbose )
+            Fra_ClauPrintClause( p->vSatVarsTestCs, p->vCexMain );
+        if ( fVerbose )
+            printf( " LitsRed = %3d.  ", Vec_IntSize(p->vCexMain) );
+        if ( fVerbose )
+            printf( "\n" );
+        // add the clause to the solver
+        Fra_ClauRemapClause( p->pMapCsTestToCsMain, p->vCexMain, p->vCexAssm, 1 );
+        RetValue = sat_solver_addclause( p->pSatMain, Vec_IntArray(p->vCexAssm), Vec_IntArray(p->vCexAssm) + Vec_IntSize(p->vCexAssm) );
+        if ( RetValue == 0 )
+        {
+            Iter++;
+            break;
+        }
+        if ( p->pSatMain->qtail != p->pSatMain->qhead )
+        {
+            RetValue = sat_solver_simplify(p->pSatMain);
+            assert( RetValue != 0 );
+            assert( p->pSatMain->qtail == p->pSatMain->qhead );
+        }
+    }
+
+    // report the results
+    if ( Iter == nIters )
+    {
+        printf( "Property is not proved after %d iterations.\n", nIters );
+        return 0;
+    }
+    printf( "Property is proved after %d iterations.\n", Iter );
+    Fra_ClauStop( p );
+    return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/fraClaus.c b/abc-build/src/proof/fra/fraClaus.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fraClaus.c
@@ -0,0 +1,1877 @@
+/**CFile****************************************************************
+
+  FileName    [fraClaus.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    [Induction with clause strengthening.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fraClau.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Clu_Man_t_    Clu_Man_t;
+struct Clu_Man_t_
+{
+    // parameters
+    int              nFrames;        // the K of the K-step induction
+    int              nPref;          // the number of timeframes to skip  
+    int              nClausesMax;    // the max number of 4-clauses to consider
+    int              nLutSize;       // the max cut size
+    int              nLevels;        // the number of levels for cut computation
+    int              nCutsMax;       // the maximum number of cuts to compute at a node
+    int              nBatches;       // the number of clause batches to use
+    int              fStepUp;        // increase cut size for each batch
+    int              fTarget;        // tries to prove the property
+    int              fVerbose;       
+    int              fVeryVerbose;
+    // internal parameters
+    int              nSimWords;      // the number of simulation words
+    int              nSimWordsPref;  // the number of simulation words in the prefix
+    int              nSimFrames;     // the number of frames to simulate 
+    int              nBTLimit;       // the largest number of backtracks (0 = infinite)
+    // the network 
+    Aig_Man_t *      pAig;
+    // SAT solvers
+    sat_solver *     pSatMain;
+    sat_solver *     pSatBmc;
+    // CNF for the test solver
+    Cnf_Dat_t *      pCnf;
+    int              fFail;
+    int              fFiltering; 
+    int              fNothingNew;
+    // clauses
+    Vec_Int_t *      vLits;
+    Vec_Int_t *      vClauses;
+    Vec_Int_t *      vCosts;
+    int              nClauses;
+    int              nCuts;
+    int              nOneHots;
+    int              nOneHotsProven;
+    // clauses proven
+    Vec_Int_t *      vLitsProven;
+    Vec_Int_t *      vClausesProven;
+    // counter-examples
+    Vec_Ptr_t *      vCexes;
+    int              nCexes;
+    int              nCexesAlloc;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Runs the SAT solver on the problem.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClausRunBmc( Clu_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int Lits[2], nLitsTot, RetValue, i;
+    // set the output literals
+    nLitsTot = 2 * p->pCnf->nVars;
+    pObj = Aig_ManCo(p->pAig, 0);
+    for ( i = 0; i < p->nPref + p->nFrames; i++ )
+    {
+        Lits[0] = i * nLitsTot + toLitCond( p->pCnf->pVarNums[pObj->Id], 0 ); 
+        RetValue = sat_solver_solve( p->pSatBmc, Lits, Lits + 1, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        if ( RetValue != l_False )
+            return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Runs the SAT solver on the problem.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClausRunSat( Clu_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int * pLits;
+    int i, RetValue;
+    pLits = ABC_ALLOC( int, p->nFrames + 1 );
+    // set the output literals
+    pObj = Aig_ManCo(p->pAig, 0);
+    for ( i = 0; i <= p->nFrames; i++ )
+        pLits[i] = i * 2 * p->pCnf->nVars + toLitCond( p->pCnf->pVarNums[pObj->Id], i != p->nFrames ); 
+    // try to solve the problem
+    RetValue = sat_solver_solve( p->pSatMain, pLits, pLits + p->nFrames + 1, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    ABC_FREE( pLits );
+    if ( RetValue == l_False )
+        return 1;
+    // get the counter-example
+    assert( RetValue == l_True );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Runs the SAT solver on the problem.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClausRunSat0( Clu_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int Lits[2], RetValue;
+    pObj = Aig_ManCo(p->pAig, 0);
+    Lits[0] = toLitCond( p->pCnf->pVarNums[pObj->Id], 0 ); 
+    RetValue = sat_solver_solve( p->pSatMain, Lits, Lits + 1, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( RetValue == l_False )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Return combinations appearing in the cut.]
+
+  Description [This procedure is taken from "Hacker's Delight" by H.S.Warren.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void transpose32a( unsigned a[32] ) 
+{
+    int j, k;
+    unsigned long m, t;
+    for ( j = 16, m = 0x0000FFFF; j; j >>= 1, m ^= m << j ) 
+    {
+        for ( k = 0; k < 32; k = ((k | j) + 1) & ~j ) 
+        {
+            t = (a[k] ^ (a[k|j] >> j)) & m;
+            a[k] ^= t;
+            a[k|j] ^= (t << j);
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Return combinations appearing in the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClausProcessClausesCut( Clu_Man_t * p, Fra_Sml_t * pSimMan, Dar_Cut_t * pCut, int * pScores )
+{
+    unsigned Matrix[32];
+    unsigned * pSims[16], uWord;
+    int nSeries, i, k, j;
+    int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref;
+    // compute parameters
+    assert( pCut->nLeaves > 1 && pCut->nLeaves < 5 );
+    assert( nWordsForSim % 8 == 0 );
+    // get parameters
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        pSims[i] = Fra_ObjSim( pSimMan, pCut->pLeaves[i] ) + p->nSimWordsPref;
+    // add combinational patterns
+    memset( pScores, 0, sizeof(int) * 16 );
+    nSeries = nWordsForSim / 8;
+    for ( i = 0; i < nSeries; i++ )
+    {
+        memset( Matrix, 0, sizeof(unsigned) * 32 );
+        for ( k = 0; k < 8; k++ )
+            for ( j = 0; j < (int)pCut->nLeaves; j++ )
+                Matrix[31-(k*4+j)] = pSims[j][i*8+k];
+        transpose32a( Matrix );
+        for ( k = 0; k < 32; k++ )
+            for ( j = 0, uWord = Matrix[k]; j < 8; j++, uWord >>= 4 )
+                pScores[uWord & 0xF]++;
+    }
+    // collect patterns
+    uWord = 0;
+    for ( i = 0; i < 16; i++ )
+        if ( pScores[i] )
+            uWord |= (1 << i);
+//    Extra_PrintBinary( stdout, &uWord, 16 ); printf( "\n" );
+    return (int)uWord;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Return combinations appearing in the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClausProcessClausesCut2( Clu_Man_t * p, Fra_Sml_t * pSimMan, Dar_Cut_t * pCut, int * pScores )
+{
+    unsigned * pSims[16], uWord;
+    int iMint, i, k, b;
+    int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref;
+    // compute parameters
+    assert( pCut->nLeaves > 1 && pCut->nLeaves < 5 );
+    assert( nWordsForSim % 8 == 0 );
+    // get parameters
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        pSims[i] = Fra_ObjSim( pSimMan, pCut->pLeaves[i] ) + p->nSimWordsPref;
+    // add combinational patterns
+    memset( pScores, 0, sizeof(int) * 16 );
+    for ( i = 0; i < nWordsForSim; i++ )
+        for ( k = 0; k < 32; k++ )
+        {
+            iMint = 0;
+            for ( b = 0; b < (int)pCut->nLeaves; b++ )
+                if ( pSims[b][i] & (1 << k) )
+                    iMint |= (1 << b);
+            pScores[iMint]++;
+        }
+    // collect patterns
+    uWord = 0;
+    for ( i = 0; i < 16; i++ )
+        if ( pScores[i] )
+            uWord |= (1 << i);
+//    Extra_PrintBinary( stdout, &uWord, 16 ); printf( "\n" );
+    return (int)uWord;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Return the number of combinations appearing in the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClausProcessClausesCut3( Clu_Man_t * p, Fra_Sml_t * pSimMan, Aig_Cut_t * pCut, int * pScores )
+{
+    unsigned Matrix[32];
+    unsigned * pSims[16], uWord;
+    int iMint, i, j, k, b, nMints, nSeries;
+    int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref;
+
+    // compute parameters
+    assert( pCut->nFanins > 1 && pCut->nFanins < 17 );
+    assert( nWordsForSim % 8 == 0 );
+    // get parameters
+    for ( i = 0; i < (int)pCut->nFanins; i++ )
+        pSims[i] = Fra_ObjSim( pSimMan, pCut->pFanins[i] ) + p->nSimWordsPref;
+    // add combinational patterns
+    nMints = (1 << pCut->nFanins);
+    memset( pScores, 0, sizeof(int) * nMints );
+
+    if ( pCut->nLeafMax == 4 )
+    {
+        // convert the simulation patterns
+        nSeries = nWordsForSim / 8;
+        for ( i = 0; i < nSeries; i++ )
+        {
+            memset( Matrix, 0, sizeof(unsigned) * 32 );
+            for ( k = 0; k < 8; k++ )
+                for ( j = 0; j < (int)pCut->nFanins; j++ )
+                    Matrix[31-(k*4+j)] = pSims[j][i*8+k];
+            transpose32a( Matrix );
+            for ( k = 0; k < 32; k++ )
+                for ( j = 0, uWord = Matrix[k]; j < 8; j++, uWord >>= 4 )
+                    pScores[uWord & 0xF]++;
+        }
+    }
+    else
+    {
+        // go through the simulation patterns
+        for ( i = 0; i < nWordsForSim; i++ )
+            for ( k = 0; k < 32; k++ )
+            {
+                iMint = 0;
+                for ( b = 0; b < (int)pCut->nFanins; b++ )
+                    if ( pSims[b][i] & (1 << k) )
+                        iMint |= (1 << b);
+                pScores[iMint]++;
+            }
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the cut-off cost.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClausSelectClauses( Clu_Man_t * p )
+{
+    int * pCostCount, nClauCount, Cost, CostMax, i, c;
+    assert( Vec_IntSize(p->vClauses) > p->nClausesMax );   
+    // count how many implications have each cost
+    CostMax = p->nSimWords * 32 + 1;
+    pCostCount = ABC_ALLOC( int, CostMax );
+    memset( pCostCount, 0, sizeof(int) * CostMax );
+    Vec_IntForEachEntry( p->vCosts, Cost, i )
+    {
+        if ( Cost == -1 )
+            continue;
+        assert( Cost < CostMax );
+        pCostCount[ Cost ]++;
+    }
+    assert( pCostCount[0] == 0 );
+    // select the bound on the cost (above this bound, implication will be included)
+    nClauCount = 0;
+    for ( c = CostMax - 1; c > 0; c-- )
+    {
+        assert( pCostCount[c] >= 0 );
+        nClauCount += pCostCount[c];
+        if ( nClauCount >= p->nClausesMax )
+            break;
+    }
+    // collect implications with the given costs
+    nClauCount = 0;
+    Vec_IntForEachEntry( p->vCosts, Cost, i )
+    {
+        if ( Cost >= c && nClauCount < p->nClausesMax )
+        {
+            nClauCount++;
+            continue;
+        }
+        Vec_IntWriteEntry( p->vCosts, i, -1 );
+    }
+    ABC_FREE( pCostCount );
+    p->nClauses = nClauCount;
+if ( p->fVerbose )
+printf( "Selected %d clauses. Cost range: [%d < %d < %d]\n", nClauCount, 1, c, CostMax );
+    return c;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Processes the clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClausRecordClause( Clu_Man_t * p, Dar_Cut_t * pCut, int iMint, int Cost )
+{
+    int i;
+    for ( i = 0; i < (int)pCut->nLeaves; i++ )
+        Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pCut->pLeaves[i]], (iMint&(1<<i)) ) );
+    Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
+    Vec_IntPush( p->vCosts, Cost );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Processes the clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClausRecordClause2( Clu_Man_t * p, Aig_Cut_t * pCut, int iMint, int Cost )
+{
+    int i;
+    for ( i = 0; i < (int)pCut->nFanins; i++ )
+        Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pCut->pFanins[i]], (iMint&(1<<i)) ) );
+    Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
+    Vec_IntPush( p->vCosts, Cost );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation info is composed of all zeros.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClausSmlNodeIsConst( Fra_Sml_t * pSeq, Aig_Obj_t * pObj )
+{
+    unsigned * pSims;
+    int i;
+    pSims = Fra_ObjSim(pSeq, pObj->Id);
+    for ( i = pSeq->nWordsPref; i < pSeq->nWordsTotal; i++ )
+        if ( pSims[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if implications holds.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClausSmlNodesAreImp( Fra_Sml_t * pSeq, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 )
+{
+    unsigned * pSimL, * pSimR;
+    int k;
+    pSimL = Fra_ObjSim(pSeq, pObj1->Id);
+    pSimR = Fra_ObjSim(pSeq, pObj2->Id);
+    for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ )
+        if ( pSimL[k] & ~pSimR[k] ) // !(Obj1 -> Obj2)
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if implications holds.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClausSmlNodesAreImpC( Fra_Sml_t * pSeq, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 )
+{
+    unsigned * pSimL, * pSimR;
+    int k;
+    pSimL = Fra_ObjSim(pSeq, pObj1->Id);
+    pSimR = Fra_ObjSim(pSeq, pObj2->Id);
+    for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ )
+        if ( pSimL[k] & pSimR[k] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Processes the clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClausCollectLatchClauses( Clu_Man_t * p, Fra_Sml_t * pSeq )
+{
+    Aig_Obj_t * pObj1, * pObj2;
+    unsigned * pSims1, * pSims2;
+    int CostMax, i, k, nCountConst, nCountImps;
+
+    nCountConst = nCountImps = 0;
+    CostMax = p->nSimWords * 32;
+/*
+    // add the property
+    {
+        Aig_Obj_t * pObj;
+        int Lits[1];
+        pObj = Aig_ManCo( p->pAig, 0 );
+        Lits[0] = toLitCond( p->pCnf->pVarNums[pObj->Id], 1 ); 
+        Vec_IntPush( p->vLits, Lits[0] );
+        Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
+        Vec_IntPush( p->vCosts, CostMax );
+        nCountConst++;
+//        printf( "Added the target property to the set of clauses to be inductively checked.\n" );
+    }
+*/
+
+    pSeq->nWordsPref = p->nSimWordsPref;
+    Aig_ManForEachLoSeq( p->pAig, pObj1, i )
+    {
+        pSims1 = Fra_ObjSim( pSeq, pObj1->Id );
+        if ( Fra_ClausSmlNodeIsConst( pSeq, pObj1 ) )
+        {
+            Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) );
+            Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
+            Vec_IntPush( p->vCosts, CostMax );
+            nCountConst++;
+            continue;
+        }
+        Aig_ManForEachLoSeq( p->pAig, pObj2, k )
+        {
+            pSims2 = Fra_ObjSim( pSeq, pObj2->Id );
+            if ( Fra_ClausSmlNodesAreImp( pSeq, pObj1, pObj2 ) )
+            {
+                Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) );
+                Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 0 ) );
+                Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
+                Vec_IntPush( p->vCosts, CostMax );
+                nCountImps++;
+                continue;
+            }
+            if ( Fra_ClausSmlNodesAreImp( pSeq, pObj2, pObj1 ) )
+            {
+                Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 1 ) );
+                Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 0 ) );
+                Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
+                Vec_IntPush( p->vCosts, CostMax );
+                nCountImps++;
+                continue;
+            }
+            if ( Fra_ClausSmlNodesAreImpC( pSeq, pObj1, pObj2 ) )
+            {
+                Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) );
+                Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 1 ) );
+                Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
+                Vec_IntPush( p->vCosts, CostMax );
+                nCountImps++;
+                continue;
+            }
+        }
+        if ( nCountConst + nCountImps > p->nClausesMax / 2 )
+            break;
+    }
+    pSeq->nWordsPref = 0;
+    if ( p->fVerbose )
+    printf( "Collected %d register constants and %d one-hotness implications.\n", nCountConst, nCountImps );
+    p->nOneHots = nCountConst + nCountImps;
+    p->nOneHotsProven = 0;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Processes the clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClausProcessClauses( Clu_Man_t * p, int fRefs )
+{
+    Aig_MmFixed_t * pMemCuts;
+//    Aig_ManCut_t * pManCut;
+    Fra_Sml_t * pComb, * pSeq;
+    Aig_Obj_t * pObj;
+    Dar_Cut_t * pCut;
+    int Scores[16], uScores, i, k, j, nCuts = 0;
+    abctime clk;
+
+    // simulate the AIG
+clk = Abc_Clock();
+//    srand( 0xAABBAABB );
+    Aig_ManRandom(1);
+    pSeq = Fra_SmlSimulateSeq( p->pAig, 0, p->nPref + p->nSimFrames, p->nSimWords/p->nSimFrames, 1 );
+    if ( p->fTarget && pSeq->fNonConstOut )
+    {
+        printf( "Property failed after sequential simulation!\n" );
+        Fra_SmlStop( pSeq );
+        return 0;
+    }
+if ( p->fVerbose )
+{
+ABC_PRT( "Sim-seq", Abc_Clock() - clk );
+}
+
+
+clk = Abc_Clock();
+    if ( fRefs )
+    {
+    Fra_ClausCollectLatchClauses( p, pSeq );
+if ( p->fVerbose )
+{
+ABC_PRT( "Lat-cla", Abc_Clock() - clk );
+}
+    }
+
+
+    // generate cuts for all nodes, assign cost, and find best cuts
+clk = Abc_Clock();
+    pMemCuts = Dar_ManComputeCuts( p->pAig, 10, 0, 1 );
+//    pManCut = Aig_ComputeCuts( p->pAig, 10, 4, 0, 1 );
+if ( p->fVerbose )
+{
+ABC_PRT( "Cuts   ", Abc_Clock() - clk );
+}
+
+    // collect sequential info for each cut
+clk = Abc_Clock();
+    Aig_ManForEachNode( p->pAig, pObj, i )
+        Dar_ObjForEachCut( pObj, pCut, k )
+            if ( pCut->nLeaves > 1 )
+            {
+                pCut->uTruth = Fra_ClausProcessClausesCut( p, pSeq, pCut, Scores );
+//                uScores = Fra_ClausProcessClausesCut2( p, pSeq, pCut, Scores );
+//                if ( uScores != pCut->uTruth )
+//                {
+//                    int x = 0;
+//                }
+            }
+if ( p->fVerbose )
+{
+ABC_PRT( "Infoseq", Abc_Clock() - clk );
+}
+    Fra_SmlStop( pSeq );
+
+    // perform combinational simulation
+clk = Abc_Clock();
+//    srand( 0xAABBAABB );
+    Aig_ManRandom(1);
+    pComb = Fra_SmlSimulateComb( p->pAig, p->nSimWords + p->nSimWordsPref, 0 );
+if ( p->fVerbose )
+{
+ABC_PRT( "Sim-cmb", Abc_Clock() - clk );
+}
+
+    // collect combinational info for each cut
+clk = Abc_Clock();
+    Aig_ManForEachNode( p->pAig, pObj, i )
+        Dar_ObjForEachCut( pObj, pCut, k )
+            if ( pCut->nLeaves > 1 )
+            {
+                nCuts++;
+                uScores = Fra_ClausProcessClausesCut( p, pComb, pCut, Scores );
+                uScores &= ~pCut->uTruth; pCut->uTruth = 0;
+                if ( uScores == 0 )
+                    continue;
+                // write the clauses
+                for ( j = 0; j < (1<<pCut->nLeaves); j++ )
+                    if ( uScores & (1 << j) )
+                        Fra_ClausRecordClause( p, pCut, j, Scores[j] );
+
+            }
+    Fra_SmlStop( pComb );
+    Aig_MmFixedStop( pMemCuts, 0 );
+//    Aig_ManCutStop( pManCut );
+if ( p->fVerbose )
+{
+ABC_PRT( "Infocmb", Abc_Clock() - clk );
+}
+
+    if ( p->fVerbose )
+    printf( "Node = %5d. Non-triv cuts = %7d. Clauses = %6d. Clause per cut = %6.2f.\n", 
+        Aig_ManNodeNum(p->pAig), nCuts, Vec_IntSize(p->vClauses), 1.0*Vec_IntSize(p->vClauses)/nCuts );
+
+    if ( Vec_IntSize(p->vClauses) > p->nClausesMax )
+        Fra_ClausSelectClauses( p );
+    else
+        p->nClauses = Vec_IntSize( p->vClauses );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Processes the clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClausProcessClauses2( Clu_Man_t * p, int fRefs )
+{
+//    Aig_MmFixed_t * pMemCuts;
+    Aig_ManCut_t * pManCut;
+    Fra_Sml_t * pComb, * pSeq;
+    Aig_Obj_t * pObj;
+    Aig_Cut_t * pCut;
+    int i, k, j, nCuts = 0;
+    abctime clk;
+    int ScoresSeq[1<<12], ScoresComb[1<<12];
+    assert( p->nLutSize < 13 );
+
+    // simulate the AIG
+clk = Abc_Clock();
+//    srand( 0xAABBAABB );
+    Aig_ManRandom(1);
+    pSeq = Fra_SmlSimulateSeq( p->pAig, 0, p->nPref + p->nSimFrames, p->nSimWords/p->nSimFrames, 1  );
+    if ( p->fTarget && pSeq->fNonConstOut )
+    {
+        printf( "Property failed after sequential simulation!\n" );
+        Fra_SmlStop( pSeq );
+        return 0;
+    }
+if ( p->fVerbose )
+{
+//ABC_PRT( "Sim-seq", Abc_Clock() - clk );
+}
+
+    // perform combinational simulation
+clk = Abc_Clock();
+//    srand( 0xAABBAABB );
+    Aig_ManRandom(1);
+    pComb = Fra_SmlSimulateComb( p->pAig, p->nSimWords + p->nSimWordsPref, 0 );
+if ( p->fVerbose )
+{
+//ABC_PRT( "Sim-cmb", Abc_Clock() - clk );
+}
+
+
+clk = Abc_Clock();
+    if ( fRefs )
+    {
+    Fra_ClausCollectLatchClauses( p, pSeq );
+if ( p->fVerbose )
+{
+//ABC_PRT( "Lat-cla", Abc_Clock() - clk );
+}
+    }
+
+
+    // generate cuts for all nodes, assign cost, and find best cuts
+clk = Abc_Clock();
+//    pMemCuts = Dar_ManComputeCuts( p->pAig, 10, 0, 1 );
+    pManCut = Aig_ComputeCuts( p->pAig, p->nCutsMax, p->nLutSize, 0, p->fVerbose );
+if ( p->fVerbose )
+{
+//ABC_PRT( "Cuts   ", Abc_Clock() - clk );
+}
+
+    // collect combinational info for each cut
+clk = Abc_Clock();
+    Aig_ManForEachNode( p->pAig, pObj, i )
+    {
+        if ( pObj->Level > (unsigned)p->nLevels )
+            continue;
+        Aig_ObjForEachCut( pManCut, pObj, pCut, k )
+            if ( pCut->nFanins > 1 )
+            {
+                nCuts++;
+                Fra_ClausProcessClausesCut3( p, pSeq, pCut, ScoresSeq );
+                Fra_ClausProcessClausesCut3( p, pComb, pCut, ScoresComb );
+                // write the clauses
+                for ( j = 0; j < (1<<pCut->nFanins); j++ )
+                    if ( ScoresComb[j] != 0 && ScoresSeq[j] == 0 )
+                        Fra_ClausRecordClause2( p, pCut, j, ScoresComb[j] );
+
+            }
+    }
+    Fra_SmlStop( pSeq );
+    Fra_SmlStop( pComb );
+    p->nCuts = nCuts;
+//    Aig_MmFixedStop( pMemCuts, 0 );
+    Aig_ManCutStop( pManCut );
+    p->pAig->pManCuts = NULL;
+
+    if ( p->fVerbose )
+    {
+    printf( "Node = %5d. Cuts = %7d. Clauses = %6d. Clause/cut = %6.2f.\n", 
+        Aig_ManNodeNum(p->pAig), nCuts, Vec_IntSize(p->vClauses), 1.0*Vec_IntSize(p->vClauses)/nCuts );
+    ABC_PRT( "Processing sim-info to find candidate clauses (unoptimized)", Abc_Clock() - clk );
+    }
+
+    // filter out clauses that are contained in the already proven clauses
+    assert( p->nClauses == 0 );
+    p->nClauses = Vec_IntSize( p->vClauses );
+    if ( Vec_IntSize( p->vClausesProven ) > 0 )
+    {
+        int RetValue, k, Beg;
+        int End = -1; // Suppress "might be used uninitialized"
+        int * pStart;
+        // reset the solver
+        if ( p->pSatMain )  sat_solver_delete( p->pSatMain );
+        p->pSatMain = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 );
+        if ( p->pSatMain == NULL )
+        {
+            printf( "Error: Main solver is unsat.\n" );
+            return -1;
+        }  
+
+        // add the proven clauses
+        Beg = 0;
+        pStart = Vec_IntArray(p->vLitsProven);
+        Vec_IntForEachEntry( p->vClausesProven, End, i )
+        {
+            assert( End - Beg <= p->nLutSize );
+            // add the clause to all timeframes
+            RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End );
+            if ( RetValue == 0 )
+            {
+                printf( "Error: Solver is UNSAT after adding assumption clauses.\n" );
+                return -1;
+            }
+            Beg = End;
+        }
+        assert( End == Vec_IntSize(p->vLitsProven) );
+
+        // check the clauses
+        Beg = 0;
+        pStart = Vec_IntArray(p->vLits);
+        Vec_IntForEachEntry( p->vClauses, End, i )
+        {
+            assert( Vec_IntEntry( p->vCosts, i ) >= 0 );
+            assert( End - Beg <= p->nLutSize );
+            // check the clause
+            for ( k = Beg; k < End; k++ )
+                pStart[k] = lit_neg( pStart[k] );
+            RetValue = sat_solver_solve( p->pSatMain, pStart + Beg, pStart + End, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+            for ( k = Beg; k < End; k++ )
+                pStart[k] = lit_neg( pStart[k] );
+            // the clause holds
+            if ( RetValue == l_False )
+            {
+                Vec_IntWriteEntry( p->vCosts, i, -1 );
+                p->nClauses--;
+            }
+            Beg = End;
+        }
+        assert( End == Vec_IntSize(p->vLits) );
+        if ( p->fVerbose )
+        printf( "Already proved clauses filtered out %d candidate clauses (out of %d).\n", 
+            Vec_IntSize(p->vClauses) - p->nClauses, Vec_IntSize(p->vClauses) );
+    }
+
+    p->fFiltering = 0;
+    if ( p->nClauses > p->nClausesMax )
+    {
+        Fra_ClausSelectClauses( p );
+        p->fFiltering = 1;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts AIG into the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClausBmcClauses( Clu_Man_t * p )
+{
+    int * pStart, nLitsTot, RetValue, Beg, End, Counter, i, k, f;
+/*
+    for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
+        printf( "%d ", p->vLits->pArray[i] );
+    printf( "\n" );
+*/
+    // add the clauses
+    Counter = 0;
+    // skip through the prefix variables
+    if ( p->nPref )
+    {
+        nLitsTot = p->nPref * 2 * p->pCnf->nVars;
+        for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
+            p->vLits->pArray[i] += nLitsTot;
+    }
+    // go through the timeframes
+    nLitsTot = 2 * p->pCnf->nVars;
+    pStart = Vec_IntArray(p->vLits);
+    for ( f = 0; f < p->nFrames; f++ )
+    {
+        Beg = 0;
+        Vec_IntForEachEntry( p->vClauses, End, i )
+        {
+            if ( Vec_IntEntry( p->vCosts, i ) == -1 )
+            {
+                Beg = End;
+                continue;
+            }
+            assert( Vec_IntEntry( p->vCosts, i ) > 0 );
+            assert( End - Beg <= p->nLutSize );
+
+            for ( k = Beg; k < End; k++ )
+                pStart[k] = lit_neg( pStart[k] );
+            RetValue = sat_solver_solve( p->pSatBmc, pStart + Beg, pStart + End, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+            for ( k = Beg; k < End; k++ )
+                pStart[k] = lit_neg( pStart[k] );
+
+            if ( RetValue != l_False )
+            {
+                Beg = End;
+                Vec_IntWriteEntry( p->vCosts, i, -1 );
+                Counter++;
+                continue;
+            }
+/*
+            // add the clause
+            RetValue = sat_solver_addclause( p->pSatBmc, pStart + Beg, pStart + End );
+    //        assert( RetValue == 1 );
+            if ( RetValue == 0 )
+            {
+                printf( "Error: Solver is UNSAT after adding BMC clauses.\n" );
+                return -1;
+            }
+*/
+            Beg = End;
+
+            // simplify the solver
+            if ( p->pSatBmc->qtail != p->pSatBmc->qhead )
+            {
+                RetValue = sat_solver_simplify(p->pSatBmc);
+                assert( RetValue != 0 );
+                assert( p->pSatBmc->qtail == p->pSatBmc->qhead );
+            }
+        }
+        // increment literals
+        for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
+            p->vLits->pArray[i] += nLitsTot;
+    }
+
+    // return clauses back to normal
+    nLitsTot = (p->nPref + p->nFrames) * nLitsTot;
+    for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
+        p->vLits->pArray[i] -= nLitsTot;
+/*
+    for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
+        printf( "%d ", p->vLits->pArray[i] );
+    printf( "\n" );
+*/
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClausSimInfoClean( Clu_Man_t * p )
+{
+    assert( p->pCnf->nVars <= Vec_PtrSize(p->vCexes) );
+    Vec_PtrCleanSimInfo( p->vCexes, 0, p->nCexesAlloc/32 );
+    p->nCexes = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reallocs simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClausSimInfoRealloc( Clu_Man_t * p )
+{
+    assert( p->nCexes == p->nCexesAlloc );
+    Vec_PtrReallocSimInfo( p->vCexes );
+    Vec_PtrCleanSimInfo( p->vCexes, p->nCexesAlloc/32, 2 * p->nCexesAlloc/32 );
+    p->nCexesAlloc *= 2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClausSimInfoRecord( Clu_Man_t * p, int * pModel )
+{
+    int i;
+    if ( p->nCexes == p->nCexesAlloc )
+        Fra_ClausSimInfoRealloc( p );
+    assert( p->nCexes < p->nCexesAlloc );
+    for ( i = 0; i < p->pCnf->nVars; i++ )
+    {
+        if ( pModel[i] == l_True )
+        {
+            assert( Abc_InfoHasBit( (unsigned *)Vec_PtrEntry(p->vCexes, i), p->nCexes ) == 0 );
+            Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(p->vCexes, i), p->nCexes );
+        }
+    }
+    p->nCexes++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Uses the simulation info.]
+
+  Description [Returns 1 if the simulation info disproved the clause.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClausSimInfoCheck( Clu_Man_t * p, int * pLits, int nLits )
+{
+    unsigned * pSims[16], uWord;
+    int nWords, iVar, i, w;
+    for ( i = 0; i < nLits; i++ )
+    {
+        iVar = lit_var(pLits[i]) - p->nFrames * p->pCnf->nVars;
+        assert( iVar > 0 && iVar < p->pCnf->nVars );
+        pSims[i] = (unsigned *)Vec_PtrEntry( p->vCexes, iVar );
+    }
+    nWords = p->nCexes / 32;
+    for ( w = 0; w < nWords; w++ )
+    {
+        uWord = ~(unsigned)0;
+        for ( i = 0; i < nLits; i++ )
+            uWord &= (lit_sign(pLits[i])? pSims[i][w] : ~pSims[i][w]);
+        if ( uWord )
+            return 1;
+    }
+    if ( p->nCexes % 32 )
+    {
+        uWord = ~(unsigned)0;
+        for ( i = 0; i < nLits; i++ )
+            uWord &= (lit_sign(pLits[i])? pSims[i][w] : ~pSims[i][w]);
+        if ( uWord & Abc_InfoMask( p->nCexes % 32 ) )
+            return 1;
+    }
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Converts AIG into the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ClausInductiveClauses( Clu_Man_t * p )
+{
+//    Aig_Obj_t * pObjLi, * pObjLo;
+    int * pStart, nLitsTot, RetValue, Beg, End, Counter, i, k, f, fFlag;//, Lits[2];
+    p->fFail = 0;
+
+    // reset the solver
+    if ( p->pSatMain )  sat_solver_delete( p->pSatMain );
+    p->pSatMain = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, p->nFrames+1, 0 );
+    if ( p->pSatMain == NULL )
+    {
+        printf( "Error: Main solver is unsat.\n" );
+        return -1;
+    }  
+    Fra_ClausSimInfoClean( p );
+
+/*
+    // check if the property holds
+    if ( Fra_ClausRunSat0( p ) )
+        printf( "Property holds without strengthening.\n" );
+    else
+        printf( "Property does not hold without strengthening.\n" );
+*/
+/*
+    // add constant registers
+    Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i )  
+        if ( Aig_ObjFanin0(pObjLi) == Aig_ManConst1(p->pAig) )
+        {
+            for ( k = 0; k < p->nFrames; k++ )
+            {
+                Lits[0] = k * 2 * p->pCnf->nVars + toLitCond( p->pCnf->pVarNums[pObjLo->Id], Aig_ObjFaninC0(pObjLi) ); 
+                RetValue = sat_solver_addclause( p->pSatMain, Lits, Lits + 1 );
+                if ( RetValue == 0 )
+                {
+                    printf( "Error: Solver is UNSAT after adding constant-register clauses.\n" );
+                    return -1;
+                }
+            }
+        }
+*/
+
+
+    // add the proven clauses
+    nLitsTot = 2 * p->pCnf->nVars;
+    pStart = Vec_IntArray(p->vLitsProven);
+    for ( f = 0; f < p->nFrames; f++ )
+    {
+        Beg = 0;
+        Vec_IntForEachEntry( p->vClausesProven, End, i )
+        {
+            assert( End - Beg <= p->nLutSize );
+            // add the clause to all timeframes
+            RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End );
+            if ( RetValue == 0 )
+            {
+                printf( "Error: Solver is UNSAT after adding assumption clauses.\n" );
+                return -1;
+            }
+            Beg = End;
+        }
+        // increment literals
+        for ( i = 0; i < Vec_IntSize(p->vLitsProven); i++ )
+            p->vLitsProven->pArray[i] += nLitsTot;
+    }
+    // return clauses back to normal
+    nLitsTot = (p->nFrames) * nLitsTot;
+    for ( i = 0; i < Vec_IntSize(p->vLitsProven); i++ )
+        p->vLitsProven->pArray[i] -= nLitsTot;
+
+/*
+    // add the proven clauses
+    nLitsTot = 2 * p->pCnf->nVars;
+    pStart = Vec_IntArray(p->vLitsProven);
+    Beg = 0;
+    Vec_IntForEachEntry( p->vClausesProven, End, i )
+    {
+        assert( End - Beg <= p->nLutSize );
+        // add the clause to all timeframes
+        RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End );
+        if ( RetValue == 0 )
+        {
+            printf( "Error: Solver is UNSAT after adding assumption clauses.\n" );
+            return -1;
+        }
+        Beg = End;
+    }
+*/
+    
+    // add the clauses
+    nLitsTot = 2 * p->pCnf->nVars;
+    pStart = Vec_IntArray(p->vLits);
+    for ( f = 0; f < p->nFrames; f++ )
+    {
+        Beg = 0;
+        Vec_IntForEachEntry( p->vClauses, End, i )
+        {
+            if ( Vec_IntEntry( p->vCosts, i ) == -1 )
+            {
+                Beg = End;
+                continue;
+            }
+            assert( Vec_IntEntry( p->vCosts, i ) > 0 );
+            assert( End - Beg <= p->nLutSize );
+            // add the clause to all timeframes
+            RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End );
+            if ( RetValue == 0 )
+            {
+                printf( "Error: Solver is UNSAT after adding assumption clauses.\n" );
+                return -1;
+            }
+            Beg = End;
+        }
+        // increment literals
+        for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
+            p->vLits->pArray[i] += nLitsTot;
+    }
+
+    // simplify the solver
+    if ( p->pSatMain->qtail != p->pSatMain->qhead )
+    {
+        RetValue = sat_solver_simplify(p->pSatMain);
+        assert( RetValue != 0 );
+        assert( p->pSatMain->qtail == p->pSatMain->qhead );
+    }
+  
+    // check if the property holds
+    if ( p->fTarget )
+    {
+        if ( Fra_ClausRunSat0( p ) )
+        {
+            if ( p->fVerbose )
+            printf( " Property holds.  " );
+        }
+        else
+        {
+            if ( p->fVerbose )
+            printf( " Property fails.  " );
+    //        return -2;
+            p->fFail = 1;
+        }
+    }
+
+/*
+    // add the property for the first K frames
+    for ( i = 0; i < p->nFrames; i++ )
+    {
+        Aig_Obj_t * pObj;
+        int Lits[2];
+        // set the output literals
+        pObj = Aig_ManCo(p->pAig, 0);
+        Lits[0] = i * nLitsTot + toLitCond( p->pCnf->pVarNums[pObj->Id], 1 ); 
+        // add the clause
+        RetValue = sat_solver_addclause( p->pSatMain, Lits, Lits + 1 );
+//        assert( RetValue == 1 );
+        if ( RetValue == 0 )
+        {
+            printf( "Error: Solver is UNSAT after adding property for the first K frames.\n" );
+            return -1;
+        }
+    }
+*/
+
+    // simplify the solver
+    if ( p->pSatMain->qtail != p->pSatMain->qhead )
+    {
+        RetValue = sat_solver_simplify(p->pSatMain);
+        assert( RetValue != 0 );
+        assert( p->pSatMain->qtail == p->pSatMain->qhead );
+    }
+
+
+    // check the clause in the last timeframe
+    Beg = 0;
+    Counter = 0;
+    Vec_IntForEachEntry( p->vClauses, End, i )
+    {
+        if ( Vec_IntEntry( p->vCosts, i ) == -1 )
+        {
+            Beg = End;
+            continue;
+        }
+        assert( Vec_IntEntry( p->vCosts, i ) > 0 );
+        assert( End - Beg <= p->nLutSize );
+
+        if ( Fra_ClausSimInfoCheck(p, pStart + Beg, End - Beg) )
+        {
+            fFlag = 1;
+//            printf( "s-" );
+
+            Beg = End;
+            Vec_IntWriteEntry( p->vCosts, i, -1 );
+            Counter++;
+            continue;
+        }
+        else
+        {
+            fFlag = 0;
+//            printf( "s?" );
+        }
+
+        for ( k = Beg; k < End; k++ )
+            pStart[k] = lit_neg( pStart[k] );
+        RetValue = sat_solver_solve( p->pSatMain, pStart + Beg, pStart + End, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        for ( k = Beg; k < End; k++ )
+            pStart[k] = lit_neg( pStart[k] );
+
+        // the problem is not solved
+        if ( RetValue != l_False )
+        {
+//            printf( "S- " );
+//            Fra_ClausSimInfoRecord( p, (int*)p->pSatMain->model.ptr + p->nFrames * p->pCnf->nVars );
+            Fra_ClausSimInfoRecord( p, (int*)p->pSatMain->model + p->nFrames * p->pCnf->nVars );
+//            RetValue = Fra_ClausSimInfoCheck(p, pStart + Beg, End - Beg);
+//            assert( RetValue );
+
+            Beg = End;
+            Vec_IntWriteEntry( p->vCosts, i, -1 );
+            Counter++;
+            continue;
+        }
+//        printf( "S+ " );
+//        assert( !fFlag );
+
+/*
+        // add the clause
+        RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End );
+//        assert( RetValue == 1 );
+        if ( RetValue == 0 )
+        {
+            printf( "Error: Solver is UNSAT after adding proved clauses.\n" );
+            return -1;
+        }
+*/
+        Beg = End;
+
+        // simplify the solver
+        if ( p->pSatMain->qtail != p->pSatMain->qhead )
+        {
+            RetValue = sat_solver_simplify(p->pSatMain);
+            assert( RetValue != 0 );
+            assert( p->pSatMain->qtail == p->pSatMain->qhead );
+        }
+    }
+
+    // return clauses back to normal
+    nLitsTot = p->nFrames * nLitsTot;
+    for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
+        p->vLits->pArray[i] -= nLitsTot;
+
+//    if ( fFail )
+//        return -2;
+    return Counter;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Converts AIG into the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Clu_Man_t * Fra_ClausAlloc( Aig_Man_t * pAig, int nFrames, int nPref, int nClausesMax, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fTarget, int fVerbose, int fVeryVerbose )
+{
+    Clu_Man_t * p;
+    p = ABC_ALLOC( Clu_Man_t, 1 );
+    memset( p, 0, sizeof(Clu_Man_t) );
+    p->pAig          = pAig;
+    p->nFrames       = nFrames;
+    p->nPref         = nPref;
+    p->nClausesMax   = nClausesMax;
+    p->nLutSize      = nLutSize;
+    p->nLevels       = nLevels;
+    p->nCutsMax      = nCutsMax;
+    p->nBatches      = nBatches;
+    p->fStepUp       = fStepUp;
+    p->fTarget       = fTarget;
+    p->fVerbose      = fVerbose;
+    p->fVeryVerbose  = fVeryVerbose;
+    p->nSimWords     = 512;//1024;//64;
+    p->nSimFrames    = 32;//8;//32;
+    p->nSimWordsPref = p->nPref*p->nSimWords/p->nSimFrames;
+
+    p->vLits         = Vec_IntAlloc( 1<<14 );
+    p->vClauses      = Vec_IntAlloc( 1<<12 );
+    p->vCosts        = Vec_IntAlloc( 1<<12 );
+
+    p->vLitsProven   = Vec_IntAlloc( 1<<14 );
+    p->vClausesProven= Vec_IntAlloc( 1<<12 );
+
+    p->nCexesAlloc   = 1024;
+    p->vCexes        = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p->pAig)+1, p->nCexesAlloc/32 );
+    Vec_PtrCleanSimInfo( p->vCexes, 0, p->nCexesAlloc/32 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts AIG into the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClausFree( Clu_Man_t * p )
+{
+    if ( p->vCexes )    Vec_PtrFree( p->vCexes );
+    if ( p->vLits )     Vec_IntFree( p->vLits );
+    if ( p->vClauses )  Vec_IntFree( p->vClauses );
+    if ( p->vLitsProven )     Vec_IntFree( p->vLitsProven );
+    if ( p->vClausesProven )  Vec_IntFree( p->vClausesProven );
+    if ( p->vCosts )    Vec_IntFree( p->vCosts );
+    if ( p->pCnf )      Cnf_DataFree( p->pCnf );
+    if ( p->pSatMain )  sat_solver_delete( p->pSatMain );
+    if ( p->pSatBmc )   sat_solver_delete( p->pSatBmc );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Converts AIG into the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClausAddToStorage( Clu_Man_t * p )
+{
+    int * pStart; 
+    int Beg, End, Counter, i, k;
+    Beg = 0;
+    Counter = 0;
+    pStart = Vec_IntArray( p->vLits );
+    Vec_IntForEachEntry( p->vClauses, End, i )
+    {
+        if ( Vec_IntEntry( p->vCosts, i ) == -1 )
+        {
+            Beg = End;
+            continue;
+        }
+        assert( Vec_IntEntry( p->vCosts, i ) > 0 );
+        assert( End - Beg <= p->nLutSize );
+        for ( k = Beg; k < End; k++ )
+            Vec_IntPush( p->vLitsProven, pStart[k] );
+        Vec_IntPush( p->vClausesProven, Vec_IntSize(p->vLitsProven) );
+        Beg = End;
+        Counter++;
+
+        if ( i < p->nOneHots )
+            p->nOneHotsProven++;
+    }
+    if ( p->fVerbose )
+    printf( "Added to storage %d proved clauses (including %d one-hot clauses)\n", Counter, p->nOneHotsProven );
+
+    Vec_IntClear( p->vClauses );
+    Vec_IntClear( p->vLits );
+    Vec_IntClear( p->vCosts );
+    p->nClauses = 0;
+
+    p->fNothingNew = (int)(Counter == 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts AIG into the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClausPrintIndClauses( Clu_Man_t * p )
+{
+    int Counters[9] = {0};
+    int * pStart; 
+    int Beg, End, i;
+    Beg = 0;
+    pStart = Vec_IntArray( p->vLitsProven );
+    Vec_IntForEachEntry( p->vClausesProven, End, i )
+    {
+        if ( End - Beg >= 8 )
+            Counters[8]++;
+        else
+            Counters[End - Beg]++;
+//printf( "%d ", End-Beg );
+        Beg = End;
+    }
+    printf( "SUMMARY: Total proved clauses = %d. ", Vec_IntSize(p->vClausesProven) );
+    printf( "Clause per lit: " );
+    for ( i = 0; i < 8; i++ )
+        if ( Counters[i] )
+            printf( "%d=%d ", i, Counters[i] );
+    if ( Counters[8] )
+            printf( ">7=%d ", Counters[8] );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the clauses into an AIGER file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Fra_ClausGetLiteral( Clu_Man_t * p, int * pVar2Id, int Lit )
+{
+    Aig_Obj_t * pLiteral;
+    int NodeId = pVar2Id[ lit_var(Lit) ];
+    assert( NodeId >= 0 );
+    pLiteral = (Aig_Obj_t *)Aig_ManObj( p->pAig, NodeId )->pData;
+    return Aig_NotCond( pLiteral, lit_sign(Lit) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the clauses into an AIGER file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClausWriteIndClauses( Clu_Man_t * p )
+{ 
+    extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact );
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pClause, * pLiteral;
+    char * pName;
+    int * pStart, * pVar2Id; 
+    int Beg, End, i, k;
+    // create mapping from SAT vars to node IDs
+    pVar2Id = ABC_ALLOC( int, p->pCnf->nVars );
+    memset( pVar2Id, 0xFF, sizeof(int) * p->pCnf->nVars );
+    for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ )
+        if ( p->pCnf->pVarNums[i] >= 0 )
+        {
+            assert( p->pCnf->pVarNums[i] < p->pCnf->nVars );
+            pVar2Id[ p->pCnf->pVarNums[i] ] = i;
+        }
+    // start the manager
+    pNew = Aig_ManDupWithoutPos( p->pAig );
+    // add the clauses
+    Beg = 0;
+    pStart = Vec_IntArray( p->vLitsProven );
+    Vec_IntForEachEntry( p->vClausesProven, End, i )
+    {
+        pClause = Fra_ClausGetLiteral( p, pVar2Id, pStart[Beg] );
+        for ( k = Beg + 1; k < End; k++ )
+        {
+            pLiteral = Fra_ClausGetLiteral( p, pVar2Id, pStart[k] );
+            pClause = Aig_Or( pNew, pClause, pLiteral );
+        }
+        Aig_ObjCreateCo( pNew, pClause );
+        Beg = End;
+    }
+    ABC_FREE( pVar2Id );
+    Aig_ManCleanup( pNew );
+    pName = Ioa_FileNameGenericAppend( p->pAig->pName, "_care.aig" );
+    printf( "Care one-hotness clauses will be written into file \"%s\".\n", pName );
+    Ioa_WriteAiger( pNew, pName, 0, 1 );
+    Aig_ManStop( pNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the clause holds using the given simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClausEstimateCoverageOne( Fra_Sml_t * pSim, int * pLits, int nLits, int * pVar2Id, unsigned * pResult )
+{
+    unsigned * pSims[16];
+    int iVar, i, w;
+    for ( i = 0; i < nLits; i++ )
+    {
+        iVar = lit_var(pLits[i]);
+        pSims[i] = Fra_ObjSim( pSim, pVar2Id[iVar] );
+    }
+    for ( w = 0; w < pSim->nWordsTotal; w++ )
+    {
+        pResult[w] = ~(unsigned)0;
+        for ( i = 0; i < nLits; i++ )
+            pResult[w] &= (lit_sign(pLits[i])? pSims[i][w] : ~pSims[i][w]);
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Estimates the coverage of state space by clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClausEstimateCoverage( Clu_Man_t * p )
+{
+    int nCombSimWords = (1<<11);
+    Fra_Sml_t * pComb;
+    unsigned * pResultTot, * pResultOne;
+    int nCovered, Beg, End, i, w;
+    int * pStart, * pVar2Id; 
+    abctime clk = Abc_Clock();
+    // simulate the circuit with nCombSimWords * 32 = 64K patterns
+//    srand( 0xAABBAABB );
+    Aig_ManRandom(1);
+    pComb = Fra_SmlSimulateComb( p->pAig, nCombSimWords, 0 );
+    // create mapping from SAT vars to node IDs
+    pVar2Id = ABC_ALLOC( int, p->pCnf->nVars );
+    memset( pVar2Id, 0, sizeof(int) * p->pCnf->nVars );
+    for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ )
+        if ( p->pCnf->pVarNums[i] >= 0 )
+        {
+            assert( p->pCnf->pVarNums[i] < p->pCnf->nVars );
+            pVar2Id[ p->pCnf->pVarNums[i] ] = i;
+        }
+    // get storage for one assignment and all assignments
+    assert( Aig_ManCoNum(p->pAig) > 2 );
+    pResultOne = Fra_ObjSim( pComb, Aig_ManCo(p->pAig, 0)->Id );
+    pResultTot = Fra_ObjSim( pComb, Aig_ManCo(p->pAig, 1)->Id );
+    // start the OR of don't-cares
+    for ( w = 0; w < nCombSimWords; w++ )
+        pResultTot[w] = 0;
+    // check clauses
+    Beg = 0;
+    pStart = Vec_IntArray( p->vLitsProven );
+    Vec_IntForEachEntry( p->vClausesProven, End, i )
+    {
+        Fra_ClausEstimateCoverageOne( pComb, pStart + Beg, End-Beg, pVar2Id, pResultOne );
+        Beg = End;
+        for ( w = 0; w < nCombSimWords; w++ )
+            pResultTot[w] |= pResultOne[w];
+    }
+    // count the total number of patterns contained in the don't-care
+    nCovered = 0;
+    for ( w = 0; w < nCombSimWords; w++ )
+        nCovered += Aig_WordCountOnes( pResultTot[w] );
+    Fra_SmlStop( pComb );
+    ABC_FREE( pVar2Id );
+    // print the result
+    printf( "Care states ratio = %f. ", 1.0 * (nCombSimWords * 32 - nCovered) / (nCombSimWords * 32) );
+    printf( "(%d out of %d patterns)  ", nCombSimWords * 32 - nCovered, nCombSimWords * 32 );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Converts AIG into the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_Claus( Aig_Man_t * pAig, int nFrames, int nPref, int nClausesMax, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRefs, int fTarget, int fVerbose, int fVeryVerbose )
+{
+    Clu_Man_t * p;
+    abctime clk, clkTotal = Abc_Clock(), clkInd;
+    int b, Iter, Counter, nPrefOld;
+    int nClausesBeg = 0;
+
+    // create the manager
+    p = Fra_ClausAlloc( pAig, nFrames, nPref, nClausesMax, nLutSize, nLevels, nCutsMax, nBatches, fStepUp, fTarget, fVerbose, fVeryVerbose );
+if ( p->fVerbose )
+{
+    printf( "PARAMETERS: Frames = %d. Pref = %d. Clauses max = %d. Cut size = %d.\n", nFrames, nPref, nClausesMax, nLutSize );
+    printf( "Level max = %d. Cuts max = %d. Batches = %d. Increment cut size = %s.\n", nLevels, nCutsMax, nBatches, fStepUp? "yes":"no" );
+//ABC_PRT( "Sim-seq", Abc_Clock() - clk );
+}
+
+    assert( !p->fTarget || Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig) == 1 );
+
+clk = Abc_Clock();
+    // derive CNF
+//    if ( p->fTarget )
+//        p->pAig->nRegs++;
+    p->pCnf = Cnf_DeriveSimple( p->pAig, Aig_ManCoNum(p->pAig) );
+//    if ( p->fTarget )
+//        p->pAig->nRegs--;
+if ( fVerbose )
+{
+//ABC_PRT( "CNF    ", Abc_Clock() - clk );
+}
+
+    // check BMC
+clk = Abc_Clock();
+    p->pSatBmc = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, p->nPref + p->nFrames, 1 );
+    if ( p->pSatBmc == NULL )
+    {
+        printf( "Error: BMC solver is unsat.\n" );
+        Fra_ClausFree( p );
+        return 1;
+    } 
+    if ( p->fTarget && !Fra_ClausRunBmc( p ) )
+    {
+        printf( "Problem fails the base case after %d frame expansion.\n", p->nPref + p->nFrames );
+        Fra_ClausFree( p );
+        return 1;
+    }
+if ( fVerbose )
+{
+//ABC_PRT( "SAT-bmc", Abc_Clock() - clk );
+}
+
+    // start the SAT solver
+clk = Abc_Clock();
+    p->pSatMain = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, p->nFrames+1, 0 );
+    if ( p->pSatMain == NULL )
+    {
+        printf( "Error: Main solver is unsat.\n" );
+        Fra_ClausFree( p );
+        return 1;
+    } 
+
+
+    for ( b = 0; b < p->nBatches; b++ )
+    {
+//        if ( fVerbose )
+        printf( "*** BATCH %d:  ", b+1 );
+        if ( b && p->nLutSize < 12 && (!p->fFiltering || p->fNothingNew || p->fStepUp) )
+            p->nLutSize++;
+        printf( "Using %d-cuts.\n", p->nLutSize );
+
+        // try solving without additional clauses
+        if ( p->fTarget && Fra_ClausRunSat( p ) )
+        {
+            printf( "Problem is inductive without strengthening.\n" );
+            Fra_ClausFree( p );
+            return 1;
+        }
+        if ( fVerbose )
+        {
+//        ABC_PRT( "SAT-ind", Abc_Clock() - clk );
+        }
+ 
+        // collect the candidate inductive clauses using 4-cuts
+        clk = Abc_Clock();
+        nPrefOld = p->nPref; p->nPref = 0; p->nSimWordsPref = 0;
+    //    Fra_ClausProcessClauses( p, fRefs );
+        Fra_ClausProcessClauses2( p, fRefs );
+        p->nPref = nPrefOld;
+        p->nSimWordsPref = p->nPref*p->nSimWords/p->nSimFrames;
+        nClausesBeg = p->nClauses;
+
+    //ABC_PRT( "Clauses", Abc_Clock() - clk );
+
+
+        // check clauses using BMC
+        if ( fBmc ) 
+        {
+            clk = Abc_Clock();
+            Counter = Fra_ClausBmcClauses( p );
+            p->nClauses -= Counter;
+            if ( fVerbose )
+            {
+                printf( "BMC disproved %d clauses.  ", Counter );
+                ABC_PRT( "Time", Abc_Clock() - clk );
+            }
+        }
+
+
+        // prove clauses inductively
+        clkInd = clk = Abc_Clock();
+        Counter = 1;
+        for ( Iter = 0; Counter > 0; Iter++ )
+        {
+            if ( fVerbose )
+            printf( "Iter %3d : Begin = %5d. ", Iter, p->nClauses );
+            Counter = Fra_ClausInductiveClauses( p );
+            if ( Counter > 0 )
+               p->nClauses -= Counter;
+            if ( fVerbose )
+            {
+            printf( "End = %5d. Exs = %5d.  ", p->nClauses, p->nCexes );
+    //        printf( "\n" );
+            ABC_PRT( "Time", Abc_Clock() - clk );
+            }
+            clk = Abc_Clock();
+        }
+        // add proved clauses to storage
+        Fra_ClausAddToStorage( p );
+        // report the results
+        if ( p->fTarget )
+        {
+            if ( Counter == -1 )
+                printf( "Fra_Claus(): Internal error.  " );
+            else if ( p->fFail )
+                printf( "Property FAILS during refinement.  " );
+            else
+                printf( "Property HOLDS inductively after strengthening.  " );
+            ABC_PRT( "Time  ", Abc_Clock() - clkTotal );
+            if ( !p->fFail )
+                break;
+        }
+        else
+        {
+            printf( "Finished proving inductive clauses. " );
+            ABC_PRT( "Time  ", Abc_Clock() - clkTotal );
+        }
+    }
+
+    // verify the computed interpolant
+    Fra_InvariantVerify( pAig, nFrames, p->vClausesProven, p->vLitsProven );
+//    printf( "THIS COMMAND IS KNOWN TO HAVE A BUG!\n" );
+
+//    if ( !p->fTarget && p->fVerbose )
+    if ( p->fVerbose )
+    {
+        Fra_ClausPrintIndClauses( p );
+        Fra_ClausEstimateCoverage( p );
+    }
+
+    if ( !p->fTarget )
+    {
+        Fra_ClausWriteIndClauses( p );
+    }
+/*
+    // print the statistic into a file
+    {
+        FILE * pTable;
+        assert( p->nBatches == 1 );
+        pTable = fopen( "stats.txt", "a+" );
+        fprintf( pTable, "%s ",  pAig->pName );
+        fprintf( pTable, "%d ",  Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig) );
+        fprintf( pTable, "%d ",  Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig) );
+        fprintf( pTable, "%d ",  Aig_ManRegNum(pAig) );
+        fprintf( pTable, "%d ",  Aig_ManNodeNum(pAig) );
+        fprintf( pTable, "%d ",  p->nCuts );
+        fprintf( pTable, "%d ",  nClausesBeg );
+        fprintf( pTable, "%d ",  p->nClauses );
+        fprintf( pTable, "%d ",  Iter );
+        fprintf( pTable, "%.2f ", (float)(clkInd-clkTotal)/(float)(CLOCKS_PER_SEC) );
+        fprintf( pTable, "%.2f ", (float)(Abc_Clock()-clkInd)/(float)(CLOCKS_PER_SEC) );
+        fprintf( pTable, "%.2f ", (float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC) );
+        fprintf( pTable, "\n" );
+        fclose( pTable );
+    }
+*/
+    // clean the manager
+    Fra_ClausFree( p );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/fraCnf.c b/abc-build/src/proof/fra/fraCnf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fraCnf.c
@@ -0,0 +1,289 @@
+/**CFile****************************************************************
+
+  FileName    [fraCnf.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fraCnf.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    [Addes clauses to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_AddClausesMux( Fra_Man_t * p, Aig_Obj_t * pNode )
+{
+    Aig_Obj_t * pNodeI, * pNodeT, * pNodeE;
+    int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE;
+
+    assert( !Aig_IsComplement( pNode ) );
+    assert( Aig_ObjIsMuxType( pNode ) );
+    // get nodes (I = if, T = then, E = else)
+    pNodeI = Aig_ObjRecognizeMux( pNode, &pNodeT, &pNodeE );
+    // get the variable numbers
+    VarF = Fra_ObjSatNum(pNode);
+    VarI = Fra_ObjSatNum(pNodeI);
+    VarT = Fra_ObjSatNum(Aig_Regular(pNodeT));
+    VarE = Fra_ObjSatNum(Aig_Regular(pNodeE));
+    // get the complementation flags
+    fCompT = Aig_IsComplement(pNodeT);
+    fCompE = Aig_IsComplement(pNodeE);
+
+    // f = ITE(i, t, e)
+
+    // i' + t' + f
+    // i' + t  + f'
+    // i  + e' + f
+    // i  + e  + f'
+
+    // create four clauses
+    pLits[0] = toLitCond(VarI, 1);
+    pLits[1] = toLitCond(VarT, 1^fCompT);
+    pLits[2] = toLitCond(VarF, 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarI, 1);
+    pLits[1] = toLitCond(VarT, 0^fCompT);
+    pLits[2] = toLitCond(VarF, 1);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarI, 0);
+    pLits[1] = toLitCond(VarE, 1^fCompE);
+    pLits[2] = toLitCond(VarF, 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarI, 0);
+    pLits[1] = toLitCond(VarE, 0^fCompE);
+    pLits[2] = toLitCond(VarF, 1);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+
+    // two additional clauses
+    // t' & e' -> f'
+    // t  & e  -> f 
+
+    // t  + e   + f'
+    // t' + e'  + f 
+
+    if ( VarT == VarE )
+    {
+//        assert( fCompT == !fCompE );
+        return;
+    }
+
+    pLits[0] = toLitCond(VarT, 0^fCompT);
+    pLits[1] = toLitCond(VarE, 0^fCompE);
+    pLits[2] = toLitCond(VarF, 1);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarT, 1^fCompT);
+    pLits[1] = toLitCond(VarE, 1^fCompE);
+    pLits[2] = toLitCond(VarF, 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Addes clauses to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_AddClausesSuper( Fra_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vSuper )
+{
+    Aig_Obj_t * pFanin;
+    int * pLits, nLits, RetValue, i;
+    assert( !Aig_IsComplement(pNode) );
+    assert( Aig_ObjIsNode( pNode ) );
+    // create storage for literals
+    nLits = Vec_PtrSize(vSuper) + 1;
+    pLits = ABC_ALLOC( int, nLits );
+    // suppose AND-gate is A & B = C
+    // add !A => !C   or   A + !C
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i )
+    {
+        pLits[0] = toLitCond(Fra_ObjSatNum(Aig_Regular(pFanin)), Aig_IsComplement(pFanin));
+        pLits[1] = toLitCond(Fra_ObjSatNum(pNode), 1);
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+    }
+    // add A & B => C   or   !A + !B + C
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i )
+        pLits[i] = toLitCond(Fra_ObjSatNum(Aig_Regular(pFanin)), !Aig_IsComplement(pFanin));
+    pLits[nLits-1] = toLitCond(Fra_ObjSatNum(pNode), 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits );
+    assert( RetValue );
+    ABC_FREE( pLits );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_CollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes )
+{
+    // if the new node is complemented or a PI, another gate begins
+    if ( Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) || (!fFirst && Aig_ObjRefs(pObj) > 1) || 
+         (fUseMuxes && Aig_ObjIsMuxType(pObj)) )
+    {
+        Vec_PtrPushUnique( vSuper, pObj );
+        return;
+    }
+    // go through the branches
+    Fra_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes );
+    Fra_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Fra_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes )
+{
+    Vec_Ptr_t * vSuper;
+    assert( !Aig_IsComplement(pObj) );
+    assert( !Aig_ObjIsCi(pObj) );
+    vSuper = Vec_PtrAlloc( 4 );
+    Fra_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes );
+    return vSuper;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the solver clause database.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ObjAddToFrontier( Fra_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier )
+{
+    assert( !Aig_IsComplement(pObj) );
+    if ( Fra_ObjSatNum(pObj) )
+        return;
+    assert( Fra_ObjSatNum(pObj) == 0 );
+    assert( Fra_ObjFaninVec(pObj) == NULL );
+    if ( Aig_ObjIsConst1(pObj) )
+        return;
+    Fra_ObjSetSatNum( pObj, p->nSatVars++ );
+    if ( Aig_ObjIsNode(pObj) )
+        Vec_PtrPush( vFrontier, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the solver clause database.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_CnfNodeAddToSolver( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew )
+{ 
+    Vec_Ptr_t * vFrontier, * vFanins;
+    Aig_Obj_t * pNode, * pFanin;
+    int i, k, fUseMuxes = 1;
+    assert( pOld || pNew );
+    // quit if CNF is ready
+    if ( (!pOld || Fra_ObjFaninVec(pOld)) && (!pNew || Fra_ObjFaninVec(pNew)) )
+        return;
+    // start the frontier
+    vFrontier = Vec_PtrAlloc( 100 );
+    if ( pOld ) Fra_ObjAddToFrontier( p, pOld, vFrontier );
+    if ( pNew ) Fra_ObjAddToFrontier( p, pNew, vFrontier );
+    // explore nodes in the frontier
+    Vec_PtrForEachEntry( Aig_Obj_t *, vFrontier, pNode, i )
+    {
+        // create the supergate
+        assert( Fra_ObjSatNum(pNode) );
+        assert( Fra_ObjFaninVec(pNode) == NULL );
+        if ( fUseMuxes && Aig_ObjIsMuxType(pNode) )
+        {
+            vFanins = Vec_PtrAlloc( 4 );
+            Vec_PtrPushUnique( vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) );
+            Vec_PtrPushUnique( vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) );
+            Vec_PtrPushUnique( vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) );
+            Vec_PtrPushUnique( vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) );
+            Vec_PtrForEachEntry( Aig_Obj_t *, vFanins, pFanin, k )
+                Fra_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier );
+            Fra_AddClausesMux( p, pNode );
+        }
+        else
+        {
+            vFanins = Fra_CollectSuper( pNode, fUseMuxes );
+            Vec_PtrForEachEntry( Aig_Obj_t *, vFanins, pFanin, k )
+                Fra_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier );
+            Fra_AddClausesSuper( p, pNode, vFanins );
+        }
+        assert( Vec_PtrSize(vFanins) > 1 );
+        Fra_ObjSetFaninVec( pNode, vFanins );
+    }
+    Vec_PtrFree( vFrontier );
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/fraCore.c b/abc-build/src/proof/fra/fraCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fraCore.c
@@ -0,0 +1,490 @@
+/**CFile****************************************************************
+
+  FileName    [fraCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fraCore.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+/* 
+    Speculating reduction in the sequential case leads to an interesting 
+    situation when a counter-ex may not refine any classes. This happens
+    for non-constant equivalence classes. In such cases the representative
+    of the class (proved by simulation to be non-constant) may be reduced 
+    to a constant during the speculative reduction. The fraig-representative 
+    of this representative node is a constant node, even though this is a 
+    non-constant class. Experiments have shown that this situation happens 
+    very often at the beginning of the refinement iteration when there are 
+    many spurious candidate equivalence classes (especially if heavy-duty 
+    simulatation of BMC was node used at the beginning). As a result, the 
+    SAT solver run may return a counter-ex that  distinguishes the given 
+    representative node from the constant-1 node but this counter-ex
+    does not distinguish the nodes in the non-costant class... This is why 
+    there is no check of refinement after a counter-ex in the sequential case.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reports the status of the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_FraigMiterStatus( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pChild;
+    int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0;
+    if ( p->pData )
+        return 0;
+    Aig_ManForEachPoSeq( p, pObj, i )
+    {
+        pChild = Aig_ObjChild0(pObj);
+        // check if the output is constant 0
+        if ( pChild == Aig_ManConst0(p) )
+        {
+            CountConst0++;
+            continue;
+        }
+        // check if the output is constant 1
+        if ( pChild == Aig_ManConst1(p) )
+        {
+            CountNonConst0++;
+            continue;
+        }
+        // check if the output is a primary input
+        if ( Aig_ObjIsCi(Aig_Regular(pChild)) && Aig_ObjCioId(Aig_Regular(pChild)) < p->nTruePis )
+        {
+            CountNonConst0++;
+            continue;
+        }
+        // check if the output can be not constant 0
+        if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) )
+        {
+            CountNonConst0++;
+            continue;
+        }
+        CountUndecided++;
+    }
+/*
+    if ( p->pParams->fVerbose )
+    {
+        printf( "Miter has %d outputs. ", Aig_ManCoNum(p->pManAig) );
+        printf( "Const0 = %d.  ", CountConst0 );
+        printf( "NonConst0 = %d.  ", CountNonConst0 );
+        printf( "Undecided = %d.  ", CountUndecided );
+        printf( "\n" );
+    }
+*/
+    if ( CountNonConst0 )
+        return 0;
+    if ( CountUndecided )
+        return -1;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports the status of the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_FraigMiterAssertedOutput( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pChild;
+    int i;
+    Aig_ManForEachPoSeq( p, pObj, i )
+    {
+        pChild = Aig_ObjChild0(pObj);
+        // check if the output is constant 0
+        if ( pChild == Aig_ManConst0(p) )
+            continue;
+        // check if the output is constant 1
+        if ( pChild == Aig_ManConst1(p) )
+            return i;
+        // check if the output can be not constant 0
+        if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) )
+            return i;
+    }
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write speculative miter for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fra_FraigNodeSpeculate( Fra_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pObjFraig, Aig_Obj_t * pObjReprFraig )
+{ 
+    static int Counter = 0;
+    char FileName[20];
+    Aig_Man_t * pTemp;
+    Aig_Obj_t * pNode;
+    int i;
+    // create manager with the logic for these two nodes
+    pTemp = Aig_ManExtractMiter( p->pManFraig, pObjFraig, pObjReprFraig );
+    // dump the logic into a file
+    sprintf( FileName, "aig\\%03d.blif", ++Counter );
+    Aig_ManDumpBlif( pTemp, FileName, NULL, NULL );
+    printf( "Speculation cone with %d nodes was written into file \"%s\".\n", Aig_ManNodeNum(pTemp), FileName );
+    // clean up
+    Aig_ManStop( pTemp );
+    Aig_ManForEachObj( p->pManFraig, pNode, i )
+        pNode->pData = p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the generated counter-ex.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_FraigVerifyCounterEx( Fra_Man_t * p, Vec_Int_t * vCex )
+{
+    Aig_Obj_t * pObj, ** ppClass;
+    int i, c;
+    assert( Aig_ManCiNum(p->pManAig) == Vec_IntSize(vCex) );
+    // make sure the input pattern is not used
+    Aig_ManForEachObj( p->pManAig, pObj, i )
+        assert( !pObj->fMarkB );
+    // simulate the cex through the AIG
+    Aig_ManConst1(p->pManAig)->fMarkB = 1;
+    Aig_ManForEachCi( p->pManAig, pObj, i )
+        pObj->fMarkB = Vec_IntEntry(vCex, i);
+    Aig_ManForEachNode( p->pManAig, pObj, i )
+        pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & 
+                       (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj));
+    Aig_ManForEachCo( p->pManAig, pObj, i )
+        pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj);
+    // check if the classes hold
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->pCla->vClasses1, pObj, i )
+    {
+        if ( pObj->fPhase != pObj->fMarkB )
+            printf( "The node %d is not constant under cex!\n", pObj->Id );
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t **, p->pCla->vClasses, ppClass, i )
+    {
+        for ( c = 1; ppClass[c]; c++ )
+            if ( (ppClass[0]->fPhase ^ ppClass[c]->fPhase) != (ppClass[0]->fMarkB ^ ppClass[c]->fMarkB) )
+                printf( "The nodes %d and %d are not equal under cex!\n", ppClass[0]->Id, ppClass[c]->Id );
+//        for ( c = 0; ppClass[c]; c++ )
+//            if ( Fra_ObjFraig(ppClass[c],p->pPars->nFramesK) == Aig_ManConst1(p->pManFraig) )
+//                printf( "A member of non-constant class has a constant repr!\n" );
+    }
+    // clean the simulation pattern
+    Aig_ManForEachObj( p->pManAig, pObj, i )
+        pObj->fMarkB = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for one node.]
+
+  Description [Returns the fraiged node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fra_FraigNode( Fra_Man_t * p, Aig_Obj_t * pObj )
+{ 
+    Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig;
+    int RetValue;
+    assert( !Aig_IsComplement(pObj) );
+    // get representative of this class
+    pObjRepr = Fra_ClassObjRepr( pObj );
+    if ( pObjRepr == NULL || // this is a unique node
+       (!p->pPars->fDoSparse && pObjRepr == Aig_ManConst1(p->pManAig)) ) // this is a sparse node
+        return;
+    // get the fraiged node
+    pObjFraig = Fra_ObjFraig( pObj, p->pPars->nFramesK );
+    // get the fraiged representative
+    pObjReprFraig = Fra_ObjFraig( pObjRepr, p->pPars->nFramesK );
+    // if the fraiged nodes are the same, return
+    if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) )
+    {
+        p->nSatCallsSkipped++;
+        return;
+    }
+    assert( p->pPars->nFramesK || Aig_Regular(pObjFraig) != Aig_ManConst1(p->pManFraig) );
+    // if they are proved different, the c-ex will be in p->pPatWords
+    RetValue = Fra_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) );
+    if ( RetValue == 1 )  // proved equivalent
+    {
+//        if ( p->pPars->fChoicing )
+//            Aig_ObjCreateRepr( p->pManFraig, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) );
+        // the nodes proved equal
+        pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase );
+        Fra_ObjSetFraig( pObj, p->pPars->nFramesK, pObjFraig2 );
+        return;
+    }
+    if ( RetValue == -1 ) // failed
+    {
+        if ( p->vTimeouts == NULL )
+            p->vTimeouts = Vec_PtrAlloc( 100 );
+        Vec_PtrPush( p->vTimeouts, pObj );
+        if ( !p->pPars->fSpeculate )
+            return;
+        assert( 0 );
+        // speculate
+        p->nSpeculs++;
+        pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase );
+        Fra_ObjSetFraig( pObj, p->pPars->nFramesK, pObjFraig2 );
+        Fra_FraigNodeSpeculate( p, pObj, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) );
+        return;
+    }
+    // disprove the nodes
+    p->pCla->fRefinement = 1;
+    // if we do not include the node into those disproved, we may end up 
+    // merging this node with another representative, for which proof has timed out
+    if ( p->vTimeouts )
+        Vec_PtrPush( p->vTimeouts, pObj );
+    // verify that the counter-example satisfies all the constraints
+//    if ( p->vCex )
+//        Fra_FraigVerifyCounterEx( p, p->vCex );
+    // simulate the counter-example and return the Fraig node
+    Fra_SmlResimulate( p );
+    if ( p->pManFraig->pData )
+        return;
+    if ( !p->pPars->nFramesK && Fra_ClassObjRepr(pObj) == pObjRepr )
+        printf( "Fra_FraigNode(): Error in class refinement!\n" );
+    assert( p->pPars->nFramesK || Fra_ClassObjRepr(pObj) != pObjRepr );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_FraigSweep( Fra_Man_t * p )
+{
+//    Bar_Progress_t * pProgress = NULL;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i, Pos = 0;
+    int nBTracksOld;
+    // fraig latch outputs
+    Aig_ManForEachLoSeq( p->pManAig, pObj, i )
+    {
+        Fra_FraigNode( p, pObj );
+        if ( p->pPars->fUseImps )
+            Pos = Fra_ImpCheckForNode( p, p->pCla->vImps, pObj, Pos );
+    }
+    if ( p->pPars->fLatchCorr )
+        return;
+    // fraig internal nodes
+//    if ( !p->pPars->fDontShowBar )
+//        pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pManAig) );
+    nBTracksOld = p->pPars->nBTLimitNode;
+    Aig_ManForEachNode( p->pManAig, pObj, i )
+    {
+//        if ( pProgress )
+//            Bar_ProgressUpdate( pProgress, i, NULL );
+        // derive and remember the new fraig node
+        pObjNew = Aig_And( p->pManFraig, Fra_ObjChild0Fra(pObj,p->pPars->nFramesK), Fra_ObjChild1Fra(pObj,p->pPars->nFramesK) );
+        Fra_ObjSetFraig( pObj, p->pPars->nFramesK, pObjNew );
+        Aig_Regular(pObjNew)->pData = p;
+        // quit if simulation detected a counter-example for a PO
+        if ( p->pManFraig->pData )
+            continue;
+//        if ( Aig_SupportSize(p->pManAig,pObj) > 16 )
+//            continue;
+        // perform fraiging
+        if ( p->pPars->nLevelMax && (int)pObj->Level > p->pPars->nLevelMax )
+            p->pPars->nBTLimitNode = 5;
+        Fra_FraigNode( p, pObj );
+        if ( p->pPars->nLevelMax && (int)pObj->Level > p->pPars->nLevelMax )
+            p->pPars->nBTLimitNode = nBTracksOld;
+        // check implications
+        if ( p->pPars->fUseImps )
+            Pos = Fra_ImpCheckForNode( p, p->pCla->vImps, pObj, Pos );
+    }
+//    if ( pProgress )
+//        Bar_ProgressStop( pProgress );
+    // try to prove the outputs of the miter
+    p->nNodesMiter = Aig_ManNodeNum(p->pManFraig);
+//    Fra_MiterStatus( p->pManFraig );
+//    if ( p->pPars->fProve && p->pManFraig->pData == NULL )
+//        Fra_MiterProve( p );
+    // compress implications after processing all of them
+    if ( p->pPars->fUseImps )
+        Fra_ImpCompactArray( p->pCla->vImps );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Fra_FraigPerform( Aig_Man_t * pManAig, Fra_Par_t * pPars )
+{
+    Fra_Man_t * p;
+    Aig_Man_t * pManAigNew;
+    abctime clk;
+    if ( Aig_ManNodeNum(pManAig) == 0 )
+        return Aig_ManDupOrdered(pManAig);
+clk = Abc_Clock();
+    p = Fra_ManStart( pManAig, pPars );
+    p->pManFraig = Fra_ManPrepareComb( p );
+    p->pSml = Fra_SmlStart( pManAig, 0, 1, pPars->nSimWords );
+    Fra_SmlSimulate( p, 0 );
+//    if ( p->pPars->fChoicing )
+//        Aig_ManReprStart( p->pManFraig, Aig_ManObjNumMax(p->pManAig) );
+    // collect initial states
+    p->nLitsBeg  = Fra_ClassesCountLits( p->pCla );
+    p->nNodesBeg = Aig_ManNodeNum(pManAig);
+    p->nRegsBeg  = Aig_ManRegNum(pManAig);
+    // perform fraig sweep
+if ( p->pPars->fVerbose )
+Fra_ClassesPrint( p->pCla, 1 );
+    Fra_FraigSweep( p );
+    // call back the procedure to check implications
+    if ( pManAig->pImpFunc )
+        pManAig->pImpFunc( p, pManAig->pImpData );
+    // no need to filter one-hot clauses because they satisfy base case by construction
+    // finalize the fraiged manager
+    Fra_ManFinalizeComb( p );
+    if ( p->pPars->fChoicing )
+    { 
+abctime clk2 = Abc_Clock();
+        Fra_ClassesCopyReprs( p->pCla, p->vTimeouts );
+        pManAigNew = Aig_ManDupRepr( p->pManAig, 1 );
+        Aig_ManReprStart( pManAigNew, Aig_ManObjNumMax(pManAigNew) );
+        Aig_ManTransferRepr( pManAigNew, p->pManAig );
+        Aig_ManMarkValidChoices( pManAigNew );
+        Aig_ManStop( p->pManFraig );
+        p->pManFraig = NULL;
+p->timeTrav += Abc_Clock() - clk2;
+    }
+    else
+    {
+        Fra_ClassesCopyReprs( p->pCla, p->vTimeouts );
+        Aig_ManCleanup( p->pManFraig );
+        pManAigNew = p->pManFraig;
+        p->pManFraig = NULL;
+    }
+p->timeTotal = Abc_Clock() - clk;
+    // collect final stats
+    p->nLitsEnd  = Fra_ClassesCountLits( p->pCla );
+    p->nNodesEnd = Aig_ManNodeNum(pManAigNew);
+    p->nRegsEnd  = Aig_ManRegNum(pManAigNew);
+    Fra_ManStop( p );
+    return pManAigNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs choicing of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax, int nLevelMax )
+{
+    Fra_Par_t Pars, * pPars = &Pars; 
+    Fra_ParamsDefault( pPars );
+    pPars->nBTLimitNode = nConfMax;
+    pPars->fChoicing    = 1;
+    pPars->fDoSparse    = 1;
+    pPars->fSpeculate   = 0;
+    pPars->fProve       = 0;
+    pPars->fVerbose     = 0;
+    pPars->fDontShowBar = 1;
+    pPars->nLevelMax    = nLevelMax;
+    return Fra_FraigPerform( pManAig, pPars );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax, int fProve )
+{
+    Aig_Man_t * pFraig;
+    Fra_Par_t Pars, * pPars = &Pars; 
+    Fra_ParamsDefault( pPars );
+    pPars->nBTLimitNode = nConfMax;
+    pPars->fChoicing    = 0;
+    pPars->fDoSparse    = 1;
+    pPars->fSpeculate   = 0;
+    pPars->fProve       = fProve;
+    pPars->fVerbose     = 0;
+    pPars->fDontShowBar = 1;
+    pFraig = Fra_FraigPerform( pManAig, pPars );
+    return pFraig;
+} 
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/fraHot.c b/abc-build/src/proof/fra/fraHot.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fraHot.c
@@ -0,0 +1,476 @@
+/**CFile****************************************************************
+
+  FileName    [fraHot.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    [Computing and using one-hotness conditions.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fraHot.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int  Fra_RegToLit( int n, int c )   { return c? -n-1 : n+1;       }
+static inline int  Fra_LitReg( int n )            { return (n>0)? n-1 : -n-1;   }
+static inline int  Fra_LitSign( int n )           { return (n<0);               }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation info is composed of all zeros.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_OneHotNodeIsConst( Fra_Sml_t * pSeq, Aig_Obj_t * pObj )
+{
+    unsigned * pSims;
+    int i;
+    pSims = Fra_ObjSim(pSeq, pObj->Id);
+    for ( i = pSeq->nWordsPref; i < pSeq->nWordsTotal; i++ )
+        if ( pSims[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation infos are equal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_OneHotNodesAreEqual( Fra_Sml_t * pSeq, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+    unsigned * pSims0, * pSims1;
+    int i;
+    pSims0 = Fra_ObjSim(pSeq, pObj0->Id);
+    pSims1 = Fra_ObjSim(pSeq, pObj1->Id);
+    for ( i = pSeq->nWordsPref; i < pSeq->nWordsTotal; i++ )
+        if ( pSims0[i] != pSims1[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if implications holds.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_OneHotNodesAreClause( Fra_Sml_t * pSeq, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2, int fCompl1, int fCompl2 )
+{
+    unsigned * pSim1, * pSim2;
+    int k;
+    pSim1 = Fra_ObjSim(pSeq, pObj1->Id);
+    pSim2 = Fra_ObjSim(pSeq, pObj2->Id);
+    if ( fCompl1 && fCompl2 )
+    {
+        for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ )
+            if ( pSim1[k] & pSim2[k] )
+                return 0;
+    }
+    else if ( fCompl1 )
+    {
+        for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ )
+            if ( pSim1[k] & ~pSim2[k] )
+                return 0;
+    }
+    else if ( fCompl2 )
+    {
+        for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ )
+            if ( ~pSim1[k] & pSim2[k] )
+                return 0;
+    }
+    else
+        assert( 0 );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes one-hot implications.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Fra_OneHotCompute( Fra_Man_t * p, Fra_Sml_t * pSim )
+{
+    int fSkipConstEqu = 1;
+    Vec_Int_t * vOneHots;
+    Aig_Obj_t * pObj1, * pObj2;
+    int i, k;
+    int nTruePis = Aig_ManCiNum(pSim->pAig) - Aig_ManRegNum(pSim->pAig);
+    assert( pSim->pAig == p->pManAig );
+    vOneHots = Vec_IntAlloc( 100 );
+    Aig_ManForEachLoSeq( pSim->pAig, pObj1, i )
+    {
+        if ( fSkipConstEqu && Fra_OneHotNodeIsConst(pSim, pObj1) )
+            continue;
+        assert( i-nTruePis >= 0 );
+//        Aig_ManForEachLoSeq( pSim->pAig, pObj2, k )
+//        Vec_PtrForEachEntryStart( Aig_Obj_t *, pSim->pAig->vPis, pObj2, k, Aig_ManCiNum(p)-Aig_ManRegNum(p) )
+        Vec_PtrForEachEntryStart( Aig_Obj_t *, pSim->pAig->vCis, pObj2, k, i+1 )
+        {
+            if ( fSkipConstEqu && Fra_OneHotNodeIsConst(pSim, pObj2) )
+                continue;
+            if ( fSkipConstEqu && Fra_OneHotNodesAreEqual( pSim, pObj1, pObj2 ) )
+                continue;
+            assert( k-nTruePis >= 0 );
+            if ( Fra_OneHotNodesAreClause( pSim, pObj1, pObj2, 1, 1 ) )
+            {
+                Vec_IntPush( vOneHots, Fra_RegToLit(i-nTruePis, 1) );
+                Vec_IntPush( vOneHots, Fra_RegToLit(k-nTruePis, 1) );
+                continue;
+            }
+            if ( Fra_OneHotNodesAreClause( pSim, pObj1, pObj2, 0, 1 ) )
+            {
+                Vec_IntPush( vOneHots, Fra_RegToLit(i-nTruePis, 0) );
+                Vec_IntPush( vOneHots, Fra_RegToLit(k-nTruePis, 1) );
+                continue;
+            }
+            if ( Fra_OneHotNodesAreClause( pSim, pObj1, pObj2, 1, 0 ) )
+            {
+                Vec_IntPush( vOneHots, Fra_RegToLit(i-nTruePis, 1) );
+                Vec_IntPush( vOneHots, Fra_RegToLit(k-nTruePis, 0) );
+                continue;
+            }
+        }
+    }
+    return vOneHots;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assumes one-hot implications in the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+**********************************************************************/
+void Fra_OneHotAssume( Fra_Man_t * p, Vec_Int_t * vOneHots )
+{
+    Aig_Obj_t * pObj1, * pObj2;
+    int i, Out1, Out2, pLits[2];
+    int nPiNum = Aig_ManCiNum(p->pManFraig) - Aig_ManRegNum(p->pManFraig);
+    assert( p->pPars->nFramesK == 1 ); // add to only one frame
+    for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 )
+    {
+        Out1 = Vec_IntEntry( vOneHots, i );
+        Out2 = Vec_IntEntry( vOneHots, i+1 );
+        if ( Out1 == 0 && Out2 == 0 )
+            continue;
+        pObj1 = Aig_ManCi( p->pManFraig, nPiNum + Fra_LitReg(Out1) );
+        pObj2 = Aig_ManCi( p->pManFraig, nPiNum + Fra_LitReg(Out2) );
+        pLits[0] = toLitCond( Fra_ObjSatNum(pObj1), Fra_LitSign(Out1) );
+        pLits[1] = toLitCond( Fra_ObjSatNum(pObj2), Fra_LitSign(Out2) );
+        // add constraint to solver
+        if ( !sat_solver_addclause( p->pSat, pLits, pLits + 2 ) )
+        {
+            printf( "Fra_OneHotAssume(): Adding clause makes SAT solver unsat.\n" );
+            sat_solver_delete( p->pSat );
+            p->pSat = NULL;
+            return;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks one-hot implications.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+**********************************************************************/
+void Fra_OneHotCheck( Fra_Man_t * p, Vec_Int_t * vOneHots )
+{
+    Aig_Obj_t * pObj1, * pObj2;
+    int RetValue, i, Out1, Out2;
+    int nTruePos = Aig_ManCoNum(p->pManFraig) - Aig_ManRegNum(p->pManFraig);
+    for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 )
+    {
+        Out1 = Vec_IntEntry( vOneHots, i );
+        Out2 = Vec_IntEntry( vOneHots, i+1 );
+        if ( Out1 == 0 && Out2 == 0 )
+            continue;
+        pObj1 = Aig_ManCo( p->pManFraig, nTruePos + Fra_LitReg(Out1) );
+        pObj2 = Aig_ManCo( p->pManFraig, nTruePos + Fra_LitReg(Out2) );
+        RetValue = Fra_NodesAreClause( p, pObj1, pObj2, Fra_LitSign(Out1), Fra_LitSign(Out2) );
+        if ( RetValue != 1 )
+        {
+            p->pCla->fRefinement = 1;
+            if ( RetValue == 0 )
+                Fra_SmlResimulate( p );
+            if ( Vec_IntEntry(vOneHots, i) != 0 )
+                printf( "Fra_OneHotCheck(): Clause is not refined!\n" );
+            assert( Vec_IntEntry(vOneHots, i) == 0 );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes those implications that no longer hold.]
+
+  Description [Returns 1 if refinement has happened.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_OneHotRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vOneHots )
+{
+    Aig_Obj_t * pObj1, * pObj2;
+    int i, Out1, Out2, RetValue = 0;
+    int nPiNum = Aig_ManCiNum(p->pManAig) - Aig_ManRegNum(p->pManAig);
+    assert( p->pSml->pAig == p->pManAig );
+    for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 )
+    {
+        Out1 = Vec_IntEntry( vOneHots, i );
+        Out2 = Vec_IntEntry( vOneHots, i+1 );
+        if ( Out1 == 0 && Out2 == 0 )
+            continue;
+        // get the corresponding nodes
+        pObj1 = Aig_ManCi( p->pManAig, nPiNum + Fra_LitReg(Out1) );
+        pObj2 = Aig_ManCi( p->pManAig, nPiNum + Fra_LitReg(Out2) );
+        // check if implication holds using this simulation info
+        if ( !Fra_OneHotNodesAreClause( p->pSml, pObj1, pObj2, Fra_LitSign(Out1), Fra_LitSign(Out2) ) )
+        {
+            Vec_IntWriteEntry( vOneHots, i, 0 );
+            Vec_IntWriteEntry( vOneHots, i+1, 0 );
+            RetValue = 1;
+        }
+    }
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes those implications that no longer hold.]
+
+  Description [Returns 1 if refinement has happened.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_OneHotCount( Fra_Man_t * p, Vec_Int_t * vOneHots )
+{
+    int i, Out1, Out2, Counter = 0;
+    for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 )
+    {
+        Out1 = Vec_IntEntry( vOneHots, i );
+        Out2 = Vec_IntEntry( vOneHots, i+1 );
+        if ( Out1 == 0 && Out2 == 0 )
+            continue;
+        Counter++;
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Estimates the coverage of state space by clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_OneHotEstimateCoverage( Fra_Man_t * p, Vec_Int_t * vOneHots )
+{
+    int nSimWords = (1<<14);
+    int nRegs = Aig_ManRegNum(p->pManAig);
+    Vec_Ptr_t * vSimInfo;
+    unsigned * pSim1, * pSim2, * pSimTot;
+    int i, w, Out1, Out2, nCovered, Counter = 0;
+    abctime clk = Abc_Clock();
+
+    // generate random sim-info at register outputs
+    vSimInfo = Vec_PtrAllocSimInfo( nRegs + 1, nSimWords );
+//    srand( 0xAABBAABB );
+    Aig_ManRandom(1);
+    for ( i = 0; i < nRegs; i++ )
+    {
+        pSim1 = (unsigned *)Vec_PtrEntry( vSimInfo, i );
+        for ( w = 0; w < nSimWords; w++ )
+            pSim1[w] = Fra_ObjRandomSim();
+    }
+    pSimTot = (unsigned *)Vec_PtrEntry( vSimInfo, nRegs );
+
+    // collect simulation info
+    memset( pSimTot, 0, sizeof(unsigned) * nSimWords );
+    for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 )
+    {
+        Out1 = Vec_IntEntry( vOneHots, i );
+        Out2 = Vec_IntEntry( vOneHots, i+1 );
+        if ( Out1 == 0 && Out2 == 0 )
+            continue;
+//printf( "(%c%d,%c%d) ", 
+//Fra_LitSign(Out1)? '-': '+', Fra_LitReg(Out1), 
+//Fra_LitSign(Out2)? '-': '+', Fra_LitReg(Out2) ); 
+        Counter++;
+        pSim1 = (unsigned *)Vec_PtrEntry( vSimInfo, Fra_LitReg(Out1) );
+        pSim2 = (unsigned *)Vec_PtrEntry( vSimInfo, Fra_LitReg(Out2) );
+        if ( Fra_LitSign(Out1) && Fra_LitSign(Out2) )
+            for ( w = 0; w < nSimWords; w++ )
+                pSimTot[w] |=  pSim1[w] &  pSim2[w];
+        else if ( Fra_LitSign(Out1) )
+            for ( w = 0; w < nSimWords; w++ )
+                pSimTot[w] |=  pSim1[w] & ~pSim2[w];
+        else if ( Fra_LitSign(Out2) )
+            for ( w = 0; w < nSimWords; w++ )
+                pSimTot[w] |= ~pSim1[w] &  pSim2[w];
+        else
+            assert( 0 );
+    }
+//printf( "\n" );
+    // count the total number of patterns contained in the don't-care
+    nCovered = 0;
+    for ( w = 0; w < nSimWords; w++ )
+        nCovered += Aig_WordCountOnes( pSimTot[w] );
+    Vec_PtrFree( vSimInfo );
+    // print the result
+    printf( "Care states ratio = %f. ", 1.0 * (nSimWords * 32 - nCovered) / (nSimWords * 32) );
+    printf( "(%d out of %d patterns)  ", nSimWords * 32 - nCovered, nSimWords * 32 );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates one-hotness EXDC.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Fra_OneHotCreateExdc( Fra_Man_t * p, Vec_Int_t * vOneHots )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj1, * pObj2, * pObj;
+    int i, Out1, Out2, nTruePis;
+    pNew = Aig_ManStart( Vec_IntSize(vOneHots)/2 );
+//    for ( i = 0; i < Aig_ManRegNum(p->pManAig); i++ )
+//        Aig_ObjCreateCi(pNew);
+    Aig_ManForEachCi( p->pManAig, pObj, i )
+        Aig_ObjCreateCi(pNew);
+    nTruePis = Aig_ManCiNum(p->pManAig) - Aig_ManRegNum(p->pManAig);
+    for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 )
+    {
+        Out1 = Vec_IntEntry( vOneHots, i );
+        Out2 = Vec_IntEntry( vOneHots, i+1 );
+        if ( Out1 == 0 && Out2 == 0 )
+            continue;
+        pObj1 = Aig_ManCi( pNew, nTruePis + Fra_LitReg(Out1) );
+        pObj2 = Aig_ManCi( pNew, nTruePis + Fra_LitReg(Out2) );
+        pObj1 = Aig_NotCond( pObj1, Fra_LitSign(Out1) );
+        pObj2 = Aig_NotCond( pObj2, Fra_LitSign(Out2) );
+        pObj  = Aig_Or( pNew, pObj1, pObj2 );
+        Aig_ObjCreateCo( pNew, pObj );
+    }
+    Aig_ManCleanup(pNew);
+//    printf( "Created AIG with %d nodes and %d outputs.\n", Aig_ManNodeNum(pNew), Aig_ManCoNum(pNew) );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Assumes one-hot implications in the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+**********************************************************************/
+void Fra_OneHotAddKnownConstraint( Fra_Man_t * p, Vec_Ptr_t * vOnehots )
+{
+    Vec_Int_t * vGroup;
+    Aig_Obj_t * pObj1, * pObj2;
+    int k, i, j, Out1, Out2, pLits[2];
+    //
+    // these constrants should be added to different timeframes!
+    // (also note that PIs follow first - then registers)
+    //
+    Vec_PtrForEachEntry( Vec_Int_t *, vOnehots, vGroup, k )
+    {
+        Vec_IntForEachEntry( vGroup, Out1, i )
+        Vec_IntForEachEntryStart( vGroup, Out2, j, i+1 )
+        {
+            pObj1 = Aig_ManCi( p->pManFraig, Out1 );
+            pObj2 = Aig_ManCi( p->pManFraig, Out2 );
+            pLits[0] = toLitCond( Fra_ObjSatNum(pObj1), 1 );
+            pLits[1] = toLitCond( Fra_ObjSatNum(pObj2), 1 );
+            // add constraint to solver
+            if ( !sat_solver_addclause( p->pSat, pLits, pLits + 2 ) )
+            {
+                printf( "Fra_OneHotAddKnownConstraint(): Adding clause makes SAT solver unsat.\n" );
+                sat_solver_delete( p->pSat );
+                p->pSat = NULL;
+                return;
+            }
+        }
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/fraImp.c b/abc-build/src/proof/fra/fraImp.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fraImp.c
@@ -0,0 +1,732 @@
+/**CFile****************************************************************
+
+  FileName    [fraImp.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    [Detecting and proving implications.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fraImp.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of 1s in each siminfo of each node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Fra_SmlCountOnesOne( Fra_Sml_t * p, int Node )
+{
+    unsigned * pSim;
+    int k, Counter = 0;
+    pSim = Fra_ObjSim( p, Node );
+    for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+        Counter += Aig_WordCountOnes( pSim[k] );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of 1s in each siminfo of each node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int * Fra_SmlCountOnes( Fra_Sml_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, * pnBits; 
+    pnBits = ABC_ALLOC( int, Aig_ManObjNumMax(p->pAig) );  
+    memset( pnBits, 0, sizeof(int) * Aig_ManObjNumMax(p->pAig) );
+    Aig_ManForEachObj( p->pAig, pObj, i )
+        pnBits[i] = Fra_SmlCountOnesOne( p, i );
+    return pnBits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if implications holds.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Sml_NodeCheckImp( Fra_Sml_t * p, int Left, int Right )
+{
+    unsigned * pSimL, * pSimR;
+    int k;
+    pSimL = Fra_ObjSim( p, Left );
+    pSimR = Fra_ObjSim( p, Right );
+    for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+        if ( pSimL[k] & ~pSimR[k] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of 1s in the complement of the implication.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Sml_NodeNotImpWeight( Fra_Sml_t * p, int Left, int Right )
+{
+    unsigned * pSimL, * pSimR;
+    int k, Counter = 0;
+    pSimL = Fra_ObjSim( p, Left );
+    pSimR = Fra_ObjSim( p, Right );
+    for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+        Counter += Aig_WordCountOnes( pSimL[k] & ~pSimR[k] );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the complement of the implication.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Sml_NodeSaveNotImpPatterns( Fra_Sml_t * p, int Left, int Right, unsigned * pResult )
+{
+    unsigned * pSimL, * pSimR;
+    int k;
+    pSimL = Fra_ObjSim( p, Left );
+    pSimR = Fra_ObjSim( p, Right );
+    for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+        pResult[k] |= pSimL[k] & ~pSimR[k];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of nodes sorted by the number of 1s.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Fra_SmlSortUsingOnes( Fra_Sml_t * p, int fLatchCorr )
+{
+    Aig_Obj_t * pObj;
+    Vec_Ptr_t * vNodes;
+    int i, nNodes, nTotal, nBits, * pnNodes, * pnBits, * pMemory;
+    assert( p->nWordsTotal > 0 );
+    // count 1s in each node's siminfo
+    pnBits = Fra_SmlCountOnes( p );
+    // count number of nodes having that many 1s
+    nNodes = 0;
+    nBits = p->nWordsTotal * 32;
+    pnNodes = ABC_ALLOC( int, nBits + 1 );
+    memset( pnNodes, 0, sizeof(int) * (nBits + 1) );
+    Aig_ManForEachObj( p->pAig, pObj, i )
+    {
+        if ( i == 0 ) continue;
+        // skip non-PI and non-internal nodes
+        if ( fLatchCorr )
+        {
+            if ( !Aig_ObjIsCi(pObj) )
+                continue;
+        }
+        else
+        {
+            if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
+                continue;
+        }
+        // skip nodes participating in the classes
+//        if ( Fra_ClassObjRepr(pObj) )
+//            continue;
+        assert( pnBits[i] <= nBits ); // "<" because of normalized info
+        pnNodes[pnBits[i]]++;
+        nNodes++;
+    }
+    // allocate memory for all the nodes
+    pMemory = ABC_ALLOC( int, nNodes + nBits + 1 );  
+    // markup the memory for each node
+    vNodes = Vec_PtrAlloc( nBits + 1 );
+    Vec_PtrPush( vNodes, pMemory );
+    for ( i = 1; i <= nBits; i++ )
+    {
+        pMemory += pnNodes[i-1] + 1;
+        Vec_PtrPush( vNodes, pMemory );
+    }
+    // add the nodes
+    memset( pnNodes, 0, sizeof(int) * (nBits + 1) );
+    Aig_ManForEachObj( p->pAig, pObj, i )
+    {
+        if ( i == 0 ) continue;
+        // skip non-PI and non-internal nodes
+        if ( fLatchCorr )
+        {
+            if ( !Aig_ObjIsCi(pObj) )
+                continue;
+        }
+        else
+        {
+            if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
+                continue;
+        }
+        // skip nodes participating in the classes
+//        if ( Fra_ClassObjRepr(pObj) )
+//            continue;
+        pMemory = (int *)Vec_PtrEntry( vNodes, pnBits[i] );
+        pMemory[ pnNodes[pnBits[i]]++ ] = i;
+    }
+    // add 0s in the end
+    nTotal = 0;
+    Vec_PtrForEachEntry( int *, vNodes, pMemory, i )
+    {
+        pMemory[ pnNodes[i]++ ] = 0;
+        nTotal += pnNodes[i];
+    }
+    assert( nTotal == nNodes + nBits + 1 );
+    ABC_FREE( pnNodes );
+    ABC_FREE( pnBits );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of implications with the highest cost.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Fra_SmlSelectMaxCost( Vec_Int_t * vImps, int * pCosts, int nCostMax, int nImpLimit, int * pCostRange )
+{
+    Vec_Int_t * vImpsNew;
+    int * pCostCount, nImpCount, Imp, i, c;
+    assert( Vec_IntSize(vImps) >= nImpLimit );
+    // count how many implications have each cost
+    pCostCount = ABC_ALLOC( int, nCostMax + 1 );
+    memset( pCostCount, 0, sizeof(int) * (nCostMax + 1) );
+    for ( i = 0; i < Vec_IntSize(vImps); i++ )
+    {
+        assert( pCosts[i] <= nCostMax );
+        pCostCount[ pCosts[i] ]++;
+    }
+    assert( pCostCount[0] == 0 );
+    // select the bound on the cost (above this bound, implication will be included)
+    nImpCount = 0;
+    for ( c = nCostMax; c > 0; c-- )
+    {
+        nImpCount += pCostCount[c];
+        if ( nImpCount >= nImpLimit )
+            break;
+    }
+//    printf( "Cost range >= %d.\n", c );
+    // collect implications with the given costs
+    vImpsNew = Vec_IntAlloc( nImpLimit );
+    Vec_IntForEachEntry( vImps, Imp, i )
+    {
+        if ( pCosts[i] < c )
+            continue;
+        Vec_IntPush( vImpsNew, Imp );
+        if ( Vec_IntSize( vImpsNew ) == nImpLimit )
+            break;
+    }
+    ABC_FREE( pCostCount );
+    if ( pCostRange )
+        *pCostRange = c;
+    return vImpsNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares two implications using their largest ID.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sml_CompareMaxId( unsigned short * pImp1, unsigned short * pImp2 )
+{
+    int Max1 = Abc_MaxInt( pImp1[0], pImp1[1] );
+    int Max2 = Abc_MaxInt( pImp2[0], pImp2[1] );
+    if ( Max1 < Max2 )
+        return -1;
+    if ( Max1 > Max2  )
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives implication candidates.]
+
+  Description [Implication candidates have the property that 
+  (1) they hold using sequential simulation information
+  (2) they do not hold using combinational simulation information
+  (3) they have as high expressive power as possible (heuristically)
+      that is, they are easy to disprove combinationally
+      meaning they cover relatively larger sequential subspace.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Fra_ImpDerive( Fra_Man_t * p, int nImpMaxLimit, int nImpUseLimit, int fLatchCorr )
+{
+    int nSimWords = 64;
+    Fra_Sml_t * pSeq, * pComb;
+    Vec_Int_t * vImps, * vTemp;
+    Vec_Ptr_t * vNodes;
+    int * pImpCosts, * pNodesI, * pNodesK;
+    int nImpsTotal = 0, nImpsTried = 0, nImpsNonSeq = 0, nImpsComb = 0, nImpsCollected = 0;
+    int CostMin = ABC_INFINITY, CostMax = 0;
+    int i, k, Imp, CostRange;
+    abctime clk = Abc_Clock();
+    assert( Aig_ManObjNumMax(p->pManAig) < (1 << 15) );
+    assert( nImpMaxLimit > 0 && nImpUseLimit > 0 && nImpUseLimit <= nImpMaxLimit );
+    // normalize both managers
+    pComb = Fra_SmlSimulateComb( p->pManAig, nSimWords, 0 );
+    pSeq = Fra_SmlSimulateSeq( p->pManAig, p->pPars->nFramesP, nSimWords, 1, 1 );
+    // get the nodes sorted by the number of 1s
+    vNodes = Fra_SmlSortUsingOnes( pSeq, fLatchCorr );
+    // count the total number of implications
+    for ( k = nSimWords * 32; k > 0; k-- )
+    for ( i = k - 1; i > 0; i-- )
+    for ( pNodesI = (int *)Vec_PtrEntry( vNodes, i ); *pNodesI; pNodesI++ )
+    for ( pNodesK = (int *)Vec_PtrEntry( vNodes, k ); *pNodesK; pNodesK++ )
+        nImpsTotal++;
+
+    // compute implications and their costs
+    pImpCosts = ABC_ALLOC( int, nImpMaxLimit );
+    vImps = Vec_IntAlloc( nImpMaxLimit );
+    for ( k = pSeq->nWordsTotal * 32; k > 0; k-- )
+        for ( i = k - 1; i > 0; i-- )
+        {
+            // HERE WE ARE MISSING SOME POTENTIAL IMPLICATIONS (with complement!)
+
+            for ( pNodesI = (int *)Vec_PtrEntry( vNodes, i ); *pNodesI; pNodesI++ )
+            for ( pNodesK = (int *)Vec_PtrEntry( vNodes, k ); *pNodesK; pNodesK++ )
+            {
+                nImpsTried++;
+                if ( !Sml_NodeCheckImp(pSeq, *pNodesI, *pNodesK) )
+                {
+                    nImpsNonSeq++;
+                    continue;
+                }
+                if ( Sml_NodeCheckImp(pComb, *pNodesI, *pNodesK) )
+                {
+                    nImpsComb++;
+                    continue;
+                }
+                nImpsCollected++;
+                Imp = Fra_ImpCreate( *pNodesI, *pNodesK );
+                pImpCosts[ Vec_IntSize(vImps) ] = Sml_NodeNotImpWeight(pComb, *pNodesI, *pNodesK);
+                CostMin = Abc_MinInt( CostMin, pImpCosts[ Vec_IntSize(vImps) ] );
+                CostMax = Abc_MaxInt( CostMax, pImpCosts[ Vec_IntSize(vImps) ] );
+                Vec_IntPush( vImps, Imp );
+                if ( Vec_IntSize(vImps) == nImpMaxLimit )
+                    goto finish;
+            } 
+        }
+finish:
+    Fra_SmlStop( pComb );
+    Fra_SmlStop( pSeq );
+
+    // select implications with the highest cost
+    CostRange = CostMin;
+    if ( Vec_IntSize(vImps) > nImpUseLimit )
+    {
+        vImps = Fra_SmlSelectMaxCost( vTemp = vImps, pImpCosts, nSimWords * 32, nImpUseLimit, &CostRange );
+        Vec_IntFree( vTemp );  
+    }
+
+    // dealloc
+    ABC_FREE( pImpCosts ); 
+	{
+	void * pTemp = Vec_PtrEntry(vNodes, 0);
+	ABC_FREE( pTemp );
+	}
+    Vec_PtrFree( vNodes );
+    // reorder implications topologically
+    qsort( (void *)Vec_IntArray(vImps), Vec_IntSize(vImps), sizeof(int), 
+            (int (*)(const void *, const void *)) Sml_CompareMaxId );
+if ( p->pPars->fVerbose )
+{
+printf( "Implications: All = %d. Try = %d. NonSeq = %d. Comb = %d. Res = %d.\n", 
+    nImpsTotal, nImpsTried, nImpsNonSeq, nImpsComb, nImpsCollected );
+printf( "Implication weight: Min = %d. Pivot = %d. Max = %d.   ", 
+       CostMin, CostRange, CostMax );
+ABC_PRT( "Time", Abc_Clock() - clk );
+}
+    return vImps;
+}
+
+
+// the following three procedures are called to 
+// - add implications to the SAT solver
+// - check implications using the SAT solver
+// - refine implications using after a cex is generated
+
+/**Function*************************************************************
+
+  Synopsis    [Add implication clauses to the SAT solver.]
+
+  Description [Note that implications should be checked in the first frame!]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ImpAddToSolver( Fra_Man_t * p, Vec_Int_t * vImps, int * pSatVarNums )
+{
+    sat_solver * pSat = p->pSat;
+    Aig_Obj_t * pLeft, * pRight;
+    Aig_Obj_t * pLeftF, * pRightF;
+    int pLits[2], Imp, Left, Right, i, f, status;
+    int fComplL, fComplR;
+    Vec_IntForEachEntry( vImps, Imp, i )
+    {
+        // get the corresponding nodes
+        pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) );
+        pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) );
+        // check if all the nodes are present
+        for ( f = 0; f < p->pPars->nFramesK; f++ )
+        {
+            // map these info fraig
+            pLeftF = Fra_ObjFraig( pLeft, f );
+            pRightF = Fra_ObjFraig( pRight, f );
+            if ( Aig_ObjIsNone(Aig_Regular(pLeftF)) || Aig_ObjIsNone(Aig_Regular(pRightF)) )
+            {
+                Vec_IntWriteEntry( vImps, i, 0 );
+                break;
+            }
+        } 
+        if ( f < p->pPars->nFramesK )
+            continue;
+        // add constraints in each timeframe
+        for ( f = 0; f < p->pPars->nFramesK; f++ )
+        {
+            // map these info fraig
+            pLeftF = Fra_ObjFraig( pLeft, f );
+            pRightF = Fra_ObjFraig( pRight, f );
+            // get the corresponding SAT numbers
+            Left = pSatVarNums[ Aig_Regular(pLeftF)->Id ];
+            Right = pSatVarNums[ Aig_Regular(pRightF)->Id ];
+            assert( Left > 0  && Left < p->nSatVars );
+            assert( Right > 0 && Right < p->nSatVars );
+            // get the complemented attributes
+            fComplL = pLeft->fPhase ^ Aig_IsComplement(pLeftF);
+            fComplR = pRight->fPhase ^ Aig_IsComplement(pRightF);
+            // get the constraint
+            // L => R      L' v R     (complement = L & R')
+            pLits[0] = 2 * Left  + !fComplL;
+            pLits[1] = 2 * Right +  fComplR;
+            // add constraint to solver
+            if ( !sat_solver_addclause( pSat, pLits, pLits + 2 ) )
+            {
+                sat_solver_delete( pSat );
+                p->pSat = NULL;
+                return;
+            }
+        }
+    }
+    status = sat_solver_simplify(pSat);
+    if ( status == 0 )
+    {
+        sat_solver_delete( pSat );
+        p->pSat = NULL;
+    }
+//    printf( "Total imps = %d. ", Vec_IntSize(vImps) );
+    Fra_ImpCompactArray( vImps );
+//    printf( "Valid imps = %d. \n", Vec_IntSize(vImps) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check implications for the node (if they are present).]
+
+  Description [Returns the new position in the array.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ImpCheckForNode( Fra_Man_t * p, Vec_Int_t * vImps, Aig_Obj_t * pNode, int Pos )
+{
+    Aig_Obj_t * pLeft, * pRight;
+    Aig_Obj_t * pLeftF, * pRightF;
+    int i, Imp, Left, Right, Max, RetValue;
+    int fComplL, fComplR;
+    Vec_IntForEachEntryStart( vImps, Imp, i, Pos )
+    {
+        if ( Imp == 0 )
+            continue;
+        Left = Fra_ImpLeft(Imp);
+        Right = Fra_ImpRight(Imp);
+        Max = Abc_MaxInt( Left, Right );
+        assert( Max >= pNode->Id );
+        if ( Max > pNode->Id )
+            return i;
+        // get the corresponding nodes
+        pLeft  = Aig_ManObj( p->pManAig, Left );
+        pRight = Aig_ManObj( p->pManAig, Right );
+        // get the corresponding FRAIG nodes
+        pLeftF  = Fra_ObjFraig( pLeft, p->pPars->nFramesK );
+        pRightF = Fra_ObjFraig( pRight, p->pPars->nFramesK );
+        // get the complemented attributes
+        fComplL = pLeft->fPhase ^ Aig_IsComplement(pLeftF);
+        fComplR = pRight->fPhase ^ Aig_IsComplement(pRightF);
+        // check equality
+        if ( Aig_Regular(pLeftF) == Aig_Regular(pRightF) )
+        {
+            if ( fComplL == fComplR ) // x => x  - always true
+                continue;
+            assert( fComplL != fComplR );
+            // consider 4 possibilities:
+            // NOT(1) => 1    or   0 => 1  - always true
+            // 1 => NOT(1)    or   1 => 0  - never true
+            // NOT(x) => x    or   x       - not always true
+            // x => NOT(x)    or   NOT(x)  - not always true
+            if ( Aig_ObjIsConst1(Aig_Regular(pLeftF)) && fComplL ) // proved implication
+                continue;
+            // disproved implication
+            p->pCla->fRefinement = 1;
+            Vec_IntWriteEntry( vImps, i, 0 );
+            continue;
+        }
+        // check the implication 
+        // - if true, a clause is added
+        // - if false, a cex is simulated
+        // make sure the implication is refined
+        RetValue = Fra_NodesAreImp( p, Aig_Regular(pLeftF), Aig_Regular(pRightF), fComplL, fComplR );
+        if ( RetValue != 1 )
+        {
+            p->pCla->fRefinement = 1;
+            if ( RetValue == 0 )
+                Fra_SmlResimulate( p );
+            if ( Vec_IntEntry(vImps, i) != 0 )
+                printf( "Fra_ImpCheckForNode(): Implication is not refined!\n" );
+            assert( Vec_IntEntry(vImps, i) == 0 );
+        }
+    }
+    return i;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes those implications that no longer hold.]
+
+  Description [Returns 1 if refinement has happened.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ImpRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vImps )
+{
+    Aig_Obj_t * pLeft, * pRight;
+    int Imp, i, RetValue = 0;
+    Vec_IntForEachEntry( vImps, Imp, i )
+    {
+        if ( Imp == 0 )
+            continue;
+        // get the corresponding nodes
+        pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) );
+        pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) );
+        // check if implication holds using this simulation info
+        if ( !Sml_NodeCheckImp(p->pSml, pLeft->Id, pRight->Id) )
+        {
+            Vec_IntWriteEntry( vImps, i, 0 );
+            RetValue = 1;
+        }
+    }
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes empty implications.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ImpCompactArray( Vec_Int_t * vImps )
+{
+    int i, k, Imp;
+    k = 0;
+    Vec_IntForEachEntry( vImps, Imp, i )
+        if ( Imp )
+            Vec_IntWriteEntry( vImps, k++, Imp );
+    Vec_IntShrink( vImps, k );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determines the ratio of the state space by computed implications.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+double Fra_ImpComputeStateSpaceRatio( Fra_Man_t * p )
+{
+    int nSimWords = 64;
+    Fra_Sml_t * pComb;
+    unsigned * pResult;
+    double Ratio = 0.0;
+    int Left, Right, Imp, i;
+    if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 )
+        return Ratio;
+    // simulate the AIG manager with combinational patterns
+    pComb = Fra_SmlSimulateComb( p->pManAig, nSimWords, 0 );
+    // go through the implications and collect where they do not hold
+    pResult = Fra_ObjSim( pComb, 0 );
+    assert( pResult[0] == 0 );
+    Vec_IntForEachEntry( p->pCla->vImps, Imp, i )
+    {
+        Left = Fra_ImpLeft(Imp);
+        Right = Fra_ImpRight(Imp);
+        Sml_NodeSaveNotImpPatterns( pComb, Left, Right, pResult );
+    }
+    // count the number of ones in this area
+    Ratio = 100.0 * Fra_SmlCountOnesOne( pComb, 0 ) / (32*(pComb->nWordsTotal-pComb->nWordsPref));
+    Fra_SmlStop( pComb );
+    return Ratio;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of failed implications.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_ImpVerifyUsingSimulation( Fra_Man_t * p )
+{
+    int nFrames = 2000;
+    int nSimWords = 8;
+    Fra_Sml_t * pSeq;
+    char * pfFails;
+    int Left, Right, Imp, i, Counter;
+    if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 )
+        return 0;
+    // simulate the AIG manager with combinational patterns
+    pSeq = Fra_SmlSimulateSeq( p->pManAig, p->pPars->nFramesP, nFrames, nSimWords, 1  );
+    // go through the implications and check how many of them do not hold
+    pfFails = ABC_ALLOC( char, Vec_IntSize(p->pCla->vImps) );
+    memset( pfFails, 0, sizeof(char) * Vec_IntSize(p->pCla->vImps) );
+    Vec_IntForEachEntry( p->pCla->vImps, Imp, i )
+    {
+        Left = Fra_ImpLeft(Imp);
+        Right = Fra_ImpRight(Imp);
+        pfFails[i] = !Sml_NodeCheckImp( pSeq, Left, Right );
+    }
+    // count how many has failed
+    Counter = 0;
+    for ( i = 0; i < Vec_IntSize(p->pCla->vImps); i++ )
+        Counter += pfFails[i];
+    ABC_FREE( pfFails );
+    Fra_SmlStop( pSeq );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Record proven implications in the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ImpRecordInManager( Fra_Man_t * p, Aig_Man_t * pNew )
+{
+    Aig_Obj_t * pLeft, * pRight, * pMiter;
+    int nPosOld, Imp, i;
+    if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 )
+        return;
+    // go through the implication
+    nPosOld = Aig_ManCoNum(pNew);
+    Vec_IntForEachEntry( p->pCla->vImps, Imp, i )
+    {
+        pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) );
+        pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) );
+        // record the implication: L' + R
+        pMiter = Aig_Or( pNew, 
+            Aig_NotCond((Aig_Obj_t *)pLeft->pData, !pLeft->fPhase), 
+            Aig_NotCond((Aig_Obj_t *)pRight->pData, pRight->fPhase) ); 
+        Aig_ObjCreateCo( pNew, pMiter );
+    }
+    pNew->nAsserts = Aig_ManCoNum(pNew) - nPosOld;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/fraInd.c b/abc-build/src/proof/fra/fraInd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fraInd.c
@@ -0,0 +1,712 @@
+/**CFile****************************************************************
+
+  FileName    [fraInd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    [Inductive prover.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fraInd.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+#include "sat/cnf/cnf.h"
+#include "opt/dar/dar.h"
+#include "aig/saig/saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs AIG rewriting on the constraint manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_FraigInductionRewrite( Fra_Man_t * p )
+{
+    Aig_Man_t * pTemp;
+    Aig_Obj_t * pObj, * pObjPo;
+    int nTruePis, k, i;
+    abctime clk = Abc_Clock();
+    // perform AIG rewriting on the speculated frames
+//    pTemp = Dar_ManRwsat( pTemp, 1, 0 );
+    pTemp = Dar_ManRewriteDefault( p->pManFraig );
+//    printf( "Before = %6d.  After = %6d.\n", Aig_ManNodeNum(p->pManFraig), Aig_ManNodeNum(pTemp) ); 
+//Aig_ManDumpBlif( p->pManFraig, "1.blif", NULL, NULL );
+//Aig_ManDumpBlif( pTemp, "2.blif", NULL, NULL );
+//    Fra_FramesWriteCone( pTemp );
+//    Aig_ManStop( pTemp );
+    // transfer PI/register pointers
+    assert( p->pManFraig->nRegs == pTemp->nRegs );
+    assert( p->pManFraig->nAsserts == pTemp->nAsserts );
+    nTruePis = Aig_ManCiNum(p->pManAig) - Aig_ManRegNum(p->pManAig);
+    memset( p->pMemFraig, 0, sizeof(Aig_Obj_t *) * p->nSizeAlloc * p->nFramesAll );
+    Fra_ObjSetFraig( Aig_ManConst1(p->pManAig), p->pPars->nFramesK, Aig_ManConst1(pTemp) );
+    Aig_ManForEachPiSeq( p->pManAig, pObj, i )
+        Fra_ObjSetFraig( pObj, p->pPars->nFramesK, Aig_ManCi(pTemp,nTruePis*p->pPars->nFramesK+i) );
+    k = 0;
+    assert( Aig_ManRegNum(p->pManAig) == Aig_ManCoNum(pTemp) - pTemp->nAsserts );
+    Aig_ManForEachLoSeq( p->pManAig, pObj, i )
+    {
+        pObjPo = Aig_ManCo(pTemp, pTemp->nAsserts + k++);
+        Fra_ObjSetFraig( pObj, p->pPars->nFramesK, Aig_ObjChild0(pObjPo) );
+    }
+    // exchange
+    Aig_ManStop( p->pManFraig );
+    p->pManFraig = pTemp;
+p->timeRwr += Abc_Clock() - clk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs speculative reduction for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Fra_FramesConstrainNode( Aig_Man_t * pManFraig, Aig_Obj_t * pObj, int iFrame )
+{
+    Aig_Obj_t * pObjNew, * pObjNew2, * pObjRepr, * pObjReprNew, * pMiter;
+    // skip nodes without representative
+    if ( (pObjRepr = Fra_ClassObjRepr(pObj)) == NULL )
+        return;
+    assert( pObjRepr->Id < pObj->Id );
+    // get the new node 
+    pObjNew = Fra_ObjFraig( pObj, iFrame );
+    // get the new node of the representative
+    pObjReprNew = Fra_ObjFraig( pObjRepr, iFrame );
+    // if this is the same node, no need to add constraints
+    if ( Aig_Regular(pObjNew) == Aig_Regular(pObjReprNew) )
+        return;
+    // these are different nodes - perform speculative reduction
+    pObjNew2 = Aig_NotCond( pObjReprNew, pObj->fPhase ^ pObjRepr->fPhase );
+    // set the new node
+    Fra_ObjSetFraig( pObj, iFrame, pObjNew2 );
+    // add the constraint
+    pMiter = Aig_Exor( pManFraig, pObjNew, pObjReprNew );
+    pMiter = Aig_NotCond( pMiter, !Aig_ObjPhaseReal(pMiter) );
+    assert( Aig_ObjPhaseReal(pMiter) == 1 );
+    Aig_ObjCreateCo( pManFraig, pMiter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the inductive case with speculative reduction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Fra_FramesWithClasses( Fra_Man_t * p )
+{
+    Aig_Man_t * pManFraig;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew;
+    int i, k, f;
+    assert( p->pManFraig == NULL );
+    assert( Aig_ManRegNum(p->pManAig) > 0 );
+    assert( Aig_ManRegNum(p->pManAig) < Aig_ManCiNum(p->pManAig) );
+
+    // start the fraig package
+    pManFraig = Aig_ManStart( Aig_ManObjNumMax(p->pManAig) * p->nFramesAll );
+    pManFraig->pName = Abc_UtilStrsav( p->pManAig->pName );
+    pManFraig->pSpec = Abc_UtilStrsav( p->pManAig->pSpec );
+    pManFraig->nRegs = p->pManAig->nRegs;
+    // create PI nodes for the frames
+    for ( f = 0; f < p->nFramesAll; f++ )
+        Fra_ObjSetFraig( Aig_ManConst1(p->pManAig), f, Aig_ManConst1(pManFraig) );
+    for ( f = 0; f < p->nFramesAll; f++ )
+        Aig_ManForEachPiSeq( p->pManAig, pObj, i )
+            Fra_ObjSetFraig( pObj, f, Aig_ObjCreateCi(pManFraig) );
+    // create latches for the first frame
+    Aig_ManForEachLoSeq( p->pManAig, pObj, i )
+        Fra_ObjSetFraig( pObj, 0, Aig_ObjCreateCi(pManFraig) );
+
+    // add timeframes
+//    pManFraig->fAddStrash = 1;
+    for ( f = 0; f < p->nFramesAll - 1; f++ )
+    {
+        // set the constraints on the latch outputs
+        Aig_ManForEachLoSeq( p->pManAig, pObj, i )
+            Fra_FramesConstrainNode( pManFraig, pObj, f );
+        // add internal nodes of this frame
+        Aig_ManForEachNode( p->pManAig, pObj, i )
+        {
+            pObjNew = Aig_And( pManFraig, Fra_ObjChild0Fra(pObj,f), Fra_ObjChild1Fra(pObj,f) );
+            Fra_ObjSetFraig( pObj, f, pObjNew );
+            Fra_FramesConstrainNode( pManFraig, pObj, f );
+        }
+        // transfer latch input to the latch outputs 
+        Aig_ManForEachLiLoSeq( p->pManAig, pObjLi, pObjLo, k )
+            Fra_ObjSetFraig( pObjLo, f+1, Fra_ObjChild0Fra(pObjLi,f) );
+    }
+//    pManFraig->fAddStrash = 0;
+    // mark the asserts
+    pManFraig->nAsserts = Aig_ManCoNum(pManFraig);
+    // add the POs for the latch outputs of the last frame
+    Aig_ManForEachLoSeq( p->pManAig, pObj, i )
+        Aig_ObjCreateCo( pManFraig, Fra_ObjFraig(pObj,p->nFramesAll-1) );
+
+    // remove dangling nodes
+    Aig_ManCleanup( pManFraig );
+    // make sure the satisfying assignment is node assigned
+    assert( pManFraig->pData == NULL );
+    return pManFraig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the inductive case with speculative reduction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_FramesAddMore( Aig_Man_t * p, int nFrames )
+{
+    Aig_Obj_t * pObj, ** pLatches;
+    int i, k, f, nNodesOld;
+    // set copy pointer of each object to point to itself
+    Aig_ManForEachObj( p, pObj, i )
+        pObj->pData = pObj;
+    // iterate and add objects
+    nNodesOld = Aig_ManObjNumMax(p);
+    pLatches = ABC_ALLOC( Aig_Obj_t *, Aig_ManRegNum(p) );
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // clean latch inputs and outputs
+        Aig_ManForEachLiSeq( p, pObj, i )
+            pObj->pData = NULL;
+        Aig_ManForEachLoSeq( p, pObj, i )
+            pObj->pData = NULL;
+        // save the latch input values
+        k = 0;
+        Aig_ManForEachLiSeq( p, pObj, i )
+        {
+            if ( Aig_ObjFanin0(pObj)->pData )
+                pLatches[k++] = Aig_ObjChild0Copy(pObj);
+            else
+                pLatches[k++] = NULL;
+        }
+        // insert them as the latch output values
+        k = 0;
+        Aig_ManForEachLoSeq( p, pObj, i )
+            pObj->pData = pLatches[k++];
+        // create the next time frame of nodes
+        Aig_ManForEachNode( p, pObj, i )
+        {
+            if ( i > nNodesOld )
+                break;
+            if ( Aig_ObjFanin0(pObj)->pData && Aig_ObjFanin1(pObj)->pData )
+                pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+            else
+                pObj->pData = NULL;
+        }
+    }
+    ABC_FREE( pLatches );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs partitioned sequential SAT sweepingG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Fra_FraigInductionPart( Aig_Man_t * pAig, Fra_Ssw_t * pPars )
+{
+    int fPrintParts = 0;
+    char Buffer[100];
+    Aig_Man_t * pTemp, * pNew;
+    Vec_Ptr_t * vResult;
+    Vec_Int_t * vPart;
+    int * pMapBack;
+    int i, nCountPis, nCountRegs;
+    int nClasses, nPartSize, fVerbose;
+    abctime clk = Abc_Clock();
+
+    // save parameters
+    nPartSize = pPars->nPartSize; pPars->nPartSize = 0;
+    fVerbose  = pPars->fVerbose;  pPars->fVerbose = 0;
+    // generate partitions
+    if ( pAig->vClockDoms )
+    {
+        // divide large clock domains into separate partitions
+        vResult = Vec_PtrAlloc( 100 );
+        Vec_PtrForEachEntry( Vec_Int_t *, (Vec_Ptr_t *)pAig->vClockDoms, vPart, i )
+        {
+            if ( nPartSize && Vec_IntSize(vPart) > nPartSize )
+                Aig_ManPartDivide( vResult, vPart, nPartSize, pPars->nOverSize );
+            else
+                Vec_PtrPush( vResult, Vec_IntDup(vPart) );
+        }
+    }
+    else
+        vResult = Aig_ManRegPartitionSimple( pAig, nPartSize, pPars->nOverSize );
+//    vResult = Aig_ManPartitionSmartRegisters( pAig, nPartSize, 0 ); 
+//    vResult = Aig_ManRegPartitionSmart( pAig, nPartSize );
+    if ( fPrintParts )
+    {
+        // print partitions
+        printf( "Simple partitioning. %d partitions are saved:\n", Vec_PtrSize(vResult) );
+        Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i )
+        {
+            sprintf( Buffer, "part%03d.aig", i );
+            pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, NULL );
+            Ioa_WriteAiger( pTemp, Buffer, 0, 0 );
+            printf( "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n", 
+                i, Vec_IntSize(vPart), Aig_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp) );
+            Aig_ManStop( pTemp );
+        }
+    }
+
+    // perform SSW with partitions
+    Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) );
+    Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i )
+    {
+        pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, &pMapBack );
+        // create the projection of 1-hot registers
+        if ( pAig->vOnehots )
+            pTemp->vOnehots = Aig_ManRegProjectOnehots( pAig, pTemp, pAig->vOnehots, fVerbose );
+        // run SSW
+        pNew = Fra_FraigInduction( pTemp, pPars );
+        nClasses = Aig_TransferMappedClasses( pAig, pTemp, pMapBack );
+        if ( fVerbose )
+            printf( "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. It = %3d. Cl = %5d.\n", 
+                i, Vec_IntSize(vPart), Aig_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp), pPars->nIters, nClasses );
+        Aig_ManStop( pNew );
+        Aig_ManStop( pTemp );
+        ABC_FREE( pMapBack );
+    }
+    // remap the AIG
+    pNew = Aig_ManDupRepr( pAig, 0 );
+    Aig_ManSeqCleanup( pNew );
+//    Aig_ManPrintStats( pAig );
+//    Aig_ManPrintStats( pNew );
+    Vec_VecFree( (Vec_Vec_t *)vResult );
+    pPars->nPartSize = nPartSize;
+    pPars->fVerbose = fVerbose;
+    if ( fVerbose )
+    {
+        ABC_PRT( "Total time", Abc_Clock() - clk );
+    }
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs sequential SAT sweeping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Fra_FraigInduction( Aig_Man_t * pManAig, Fra_Ssw_t * pParams )
+{
+    int fUseSimpleCnf = 0;
+    int fUseOldSimulation = 0;
+    // other paramaters affecting performance
+    // - presence of FRAIGing in Abc_NtkDarSeqSweep()
+    // - using distance-1 patterns in Fra_SmlAssignDist1()
+    // - the number of simulation patterns
+    // - the number of BMC frames
+
+    Fra_Man_t * p;
+    Fra_Par_t Pars, * pPars = &Pars; 
+    Aig_Obj_t * pObj;
+    Cnf_Dat_t * pCnf;
+    Aig_Man_t * pManAigNew = NULL;
+    int nNodesBeg, nRegsBeg;
+    int nIter = -1; // Suppress "might be used uninitialized"
+    int i;
+    abctime clk = Abc_Clock(), clk2;
+    abctime TimeToStop = pParams->TimeLimit ? pParams->TimeLimit * CLOCKS_PER_SEC + Abc_Clock() : 0;
+
+    if ( Aig_ManNodeNum(pManAig) == 0 )
+    {
+        pParams->nIters = 0;
+        // Ntl_ManFinalize() needs the following to satisfy an assertion
+        Aig_ManReprStart(pManAig,Aig_ManObjNumMax(pManAig));
+        return Aig_ManDupOrdered(pManAig);
+    }
+    assert( Aig_ManRegNum(pManAig) > 0 );
+    assert( pParams->nFramesK > 0 );
+//Aig_ManShow( pManAig, 0, NULL );
+
+    if ( pParams->fWriteImps && pParams->nPartSize > 0 )
+    {
+        pParams->nPartSize = 0;
+        printf( "Partitioning was disabled to allow implication writing.\n" );
+    }
+    // perform partitioning
+    if ( (pParams->nPartSize > 0 && pParams->nPartSize < Aig_ManRegNum(pManAig))
+         || (pManAig->vClockDoms && Vec_VecSize(pManAig->vClockDoms) > 0)  )
+        return Fra_FraigInductionPart( pManAig, pParams );
+ 
+    nNodesBeg = Aig_ManNodeNum(pManAig);
+    nRegsBeg  = Aig_ManRegNum(pManAig);
+
+    // enhance the AIG by adding timeframes
+//    Fra_FramesAddMore( pManAig, 3 );
+
+    // get parameters
+    Fra_ParamsDefaultSeq( pPars );
+    pPars->nFramesP   = pParams->nFramesP;
+    pPars->nFramesK   = pParams->nFramesK;
+    pPars->nMaxImps   = pParams->nMaxImps;
+    pPars->nMaxLevs   = pParams->nMaxLevs;
+    pPars->fVerbose   = pParams->fVerbose;
+    pPars->fRewrite   = pParams->fRewrite;
+    pPars->fLatchCorr = pParams->fLatchCorr;
+    pPars->fUseImps   = pParams->fUseImps;
+    pPars->fWriteImps = pParams->fWriteImps;
+    pPars->fUse1Hot   = pParams->fUse1Hot;
+
+    assert( !(pPars->nFramesP > 0 && pPars->fUse1Hot) );
+    assert( !(pPars->nFramesK > 1 && pPars->fUse1Hot) );
+ 
+    // start the fraig manager for this run
+    p = Fra_ManStart( pManAig, pPars );
+    p->pPars->nBTLimitNode = 0;
+    // derive and refine e-classes using K initialized frames
+    if ( fUseOldSimulation )
+    {
+        if ( pPars->nFramesP > 0 )
+        {
+            pPars->nFramesP = 0;
+            printf( "Fra_FraigInduction(): Prefix cannot be used.\n" );
+        }
+        p->pSml = Fra_SmlStart( pManAig, 0, pPars->nFramesK + 1, pPars->nSimWords );
+        Fra_SmlSimulate( p, 1 );
+    }
+    else
+    {
+        // bug:  r iscas/blif/s5378.blif    ; st; ssw -v
+        // bug:  r iscas/blif/s1238.blif    ; st; ssw -v
+        // refine the classes with more simulation rounds
+if ( pPars->fVerbose )
+printf( "Simulating %d AIG nodes for %d cycles ... ", Aig_ManNodeNum(pManAig), pPars->nFramesP + 32 );
+        p->pSml = Fra_SmlSimulateSeq( pManAig, pPars->nFramesP, 32, 1, 1  ); //pPars->nFramesK + 1, 1 );  
+if ( pPars->fVerbose ) 
+{
+ABC_PRT( "Time", Abc_Clock() - clk );
+}
+        Fra_ClassesPrepare( p->pCla, p->pPars->fLatchCorr, p->pPars->nMaxLevs );
+//        Fra_ClassesPostprocess( p->pCla );
+        // compute one-hotness conditions
+        if ( p->pPars->fUse1Hot )
+            p->vOneHots = Fra_OneHotCompute( p, p->pSml );
+        // allocate new simulation manager for simulating counter-examples
+        Fra_SmlStop( p->pSml );
+        p->pSml = Fra_SmlStart( pManAig, 0, pPars->nFramesK + 1, pPars->nSimWords );
+    }
+
+    // select the most expressive implications
+    if ( pPars->fUseImps )
+        p->pCla->vImps = Fra_ImpDerive( p, 5000000, pPars->nMaxImps, pPars->fLatchCorr );
+
+    if ( pParams->TimeLimit != 0.0 && Abc_Clock() > TimeToStop )
+    {
+        if ( !pParams->fSilent )
+            printf( "Fra_FraigInduction(): Runtime limit exceeded.\n" );
+        goto finish;
+    }
+
+    // perform BMC (for the min number of frames)
+    Fra_BmcPerform( p, pPars->nFramesP, pPars->nFramesK+1 ); // +1 is needed to prevent non-refinement
+//Fra_ClassesPrint( p->pCla, 1 );
+//    if ( p->vCex == NULL )
+//        p->vCex = Vec_IntAlloc( 1000 );
+
+    p->nLitsBeg  = Fra_ClassesCountLits( p->pCla );
+    p->nNodesBeg = nNodesBeg; // Aig_ManNodeNum(pManAig);
+    p->nRegsBeg  = nRegsBeg; // Aig_ManRegNum(pManAig);
+
+    // dump AIG of the timeframes
+//    pManAigNew = Fra_ClassesDeriveAig( p->pCla, pPars->nFramesK );
+//    Aig_ManDumpBlif( pManAigNew, "frame_aig.blif", NULL, NULL );
+//    Fra_ManPartitionTest2( pManAigNew );
+//    Aig_ManStop( pManAigNew );
+ 
+    // iterate the inductive case
+    p->pCla->fRefinement = 1;
+    for ( nIter = 0; p->pCla->fRefinement; nIter++ )
+    {
+        int nLitsOld = Fra_ClassesCountLits(p->pCla);
+        int nImpsOld = p->pCla->vImps? Vec_IntSize(p->pCla->vImps) : 0;
+        int nHotsOld = p->vOneHots? Fra_OneHotCount(p, p->vOneHots) : 0;
+        abctime clk3 = Abc_Clock();
+
+        if ( pParams->TimeLimit != 0.0 && Abc_Clock() > TimeToStop )
+        {
+            if ( !pParams->fSilent )
+                printf( "Fra_FraigInduction(): Runtime limit exceeded.\n" );
+            goto finish;
+        }
+
+        // mark the classes as non-refined
+        p->pCla->fRefinement = 0;
+        // derive non-init K-timeframes while implementing e-classes
+clk2 = Abc_Clock();
+        p->pManFraig = Fra_FramesWithClasses( p );
+p->timeTrav += Abc_Clock() - clk2;
+//Aig_ManDumpBlif( p->pManFraig, "testaig.blif", NULL, NULL );
+
+        // perform AIG rewriting
+        if ( p->pPars->fRewrite )
+            Fra_FraigInductionRewrite( p );
+
+        // convert the manager to SAT solver (the last nLatches outputs are inputs)
+        if ( fUseSimpleCnf || pPars->fUseImps )
+            pCnf = Cnf_DeriveSimple( p->pManFraig, Aig_ManRegNum(p->pManFraig) );
+        else
+            pCnf = Cnf_Derive( p->pManFraig, Aig_ManRegNum(p->pManFraig) );
+//        Cnf_DataTranformPolarity( pCnf, 0 );
+//Cnf_DataWriteIntoFile( pCnf, "temp.cnf", 1 );
+
+        p->pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+        p->nSatVars = pCnf->nVars;
+        assert( p->pSat != NULL );
+        if ( p->pSat == NULL )
+            printf( "Fra_FraigInduction(): Computed CNF is not valid.\n" );
+        if ( pPars->fUseImps )
+        {
+            Fra_ImpAddToSolver( p, p->pCla->vImps, pCnf->pVarNums );
+            if ( p->pSat == NULL )
+                printf( "Fra_FraigInduction(): Adding implicationsn to CNF led to a conflict.\n" );
+        }
+
+        // set the pointers to the manager
+        Aig_ManForEachObj( p->pManFraig, pObj, i )
+            pObj->pData = p;
+
+        // prepare solver for fraiging the last timeframe
+        Fra_ManClean( p, Aig_ManObjNumMax(p->pManFraig) + Aig_ManNodeNum(p->pManAig) );
+
+        // transfer PI/LO variable numbers
+        Aig_ManForEachObj( p->pManFraig, pObj, i )
+        {
+            if ( pCnf->pVarNums[pObj->Id] == -1 )
+                continue;
+            Fra_ObjSetSatNum( pObj, pCnf->pVarNums[pObj->Id] );
+            Fra_ObjSetFaninVec( pObj, (Vec_Ptr_t *)1 );
+        }
+        Cnf_DataFree( pCnf );
+
+        // add one-hotness clauses
+        if ( p->pPars->fUse1Hot )
+            Fra_OneHotAssume( p, p->vOneHots );
+//        if ( p->pManAig->vOnehots )
+//            Fra_OneHotAddKnownConstraint( p, p->pManAig->vOnehots );
+ 
+        // report the intermediate results
+        if ( pPars->fVerbose )
+        {
+            printf( "%3d : C = %6d. Cl = %6d.  L = %6d. LR = %6d.  ", 
+                nIter, Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), 
+                Fra_ClassesCountLits(p->pCla), p->pManFraig->nAsserts );
+            if ( p->pCla->vImps )
+                printf( "I = %6d. ", Vec_IntSize(p->pCla->vImps) );
+            if ( p->pPars->fUse1Hot )
+                printf( "1h = %6d. ", Fra_OneHotCount(p, p->vOneHots) );
+            printf( "NR = %6d. ", Aig_ManNodeNum(p->pManFraig) );
+//            printf( "\n" );
+        } 
+
+        // perform sweeping
+        p->nSatCallsRecent = 0;
+        p->nSatCallsSkipped = 0;
+clk2 = Abc_Clock();
+        if ( p->pPars->fUse1Hot )
+            Fra_OneHotCheck( p, p->vOneHots );
+        Fra_FraigSweep( p );
+        if ( pPars->fVerbose )
+        {
+            ABC_PRT( "T", Abc_Clock() - clk3 );
+        } 
+
+//        Sat_SolverPrintStats( stdout, p->pSat );
+        // remove FRAIG and SAT solver
+        Aig_ManStop( p->pManFraig );   p->pManFraig = NULL;
+//        printf( "Vars = %d. Clauses = %d. Learnts = %d.\n", p->pSat->size, p->pSat->clauses.size, p->pSat->learnts.size );
+        sat_solver_delete( p->pSat );  p->pSat = NULL; 
+        memset( p->pMemFraig, 0, sizeof(Aig_Obj_t *) * p->nSizeAlloc * p->nFramesAll );
+//        printf( "Recent SAT called = %d. Skipped = %d.\n", p->nSatCallsRecent, p->nSatCallsSkipped );
+        assert( p->vTimeouts == NULL );
+        if ( p->vTimeouts )
+           printf( "Fra_FraigInduction(): SAT solver timed out!\n" );
+        // check if refinement has happened
+//        p->pCla->fRefinement = (int)(nLitsOld != Fra_ClassesCountLits(p->pCla));
+        if ( p->pCla->fRefinement && 
+            nLitsOld == Fra_ClassesCountLits(p->pCla) && 
+            nImpsOld == (p->pCla->vImps? Vec_IntSize(p->pCla->vImps) : 0) && 
+            nHotsOld == (p->vOneHots? Fra_OneHotCount(p, p->vOneHots) : 0) )
+        {
+            printf( "Fra_FraigInduction(): Internal error. The result may not verify.\n" );
+            break;
+        }
+    }
+/*
+    // verify implications using simulation
+    if ( p->pCla->vImps && Vec_IntSize(p->pCla->vImps) )
+    {
+        int Temp;
+        abctime clk = Abc_Clock();
+        if ( Temp = Fra_ImpVerifyUsingSimulation( p ) )
+            printf( "Implications failing the simulation test = %d (out of %d).  ", Temp, Vec_IntSize(p->pCla->vImps) );
+        else
+            printf( "All %d implications have passed the simulation test.  ", Vec_IntSize(p->pCla->vImps) );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+*/
+
+    // move the classes into representatives and reduce AIG
+clk2 = Abc_Clock();
+    if ( p->pPars->fWriteImps && p->vOneHots && Fra_OneHotCount(p, p->vOneHots) )
+    {
+        extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact );
+        Aig_Man_t * pNew;
+        char * pFileName = Ioa_FileNameGenericAppend( p->pManAig->pName, "_care.aig" );
+        printf( "Care one-hotness clauses will be written into file \"%s\".\n", pFileName );
+        pManAigNew = Aig_ManDupOrdered( pManAig );
+        pNew = Fra_OneHotCreateExdc( p, p->vOneHots );
+        Ioa_WriteAiger( pNew, pFileName, 0, 1 );
+        Aig_ManStop( pNew );
+    }
+    else 
+    {
+    //    Fra_ClassesPrint( p->pCla, 1 );
+        Fra_ClassesSelectRepr( p->pCla );
+        Fra_ClassesCopyReprs( p->pCla, p->vTimeouts );
+        pManAigNew = Aig_ManDupRepr( pManAig, 0 );
+    }
+    // add implications to the manager
+//    if ( fWriteImps && p->pCla->vImps && Vec_IntSize(p->pCla->vImps) )
+//        Fra_ImpRecordInManager( p, pManAigNew );
+    // cleanup the new manager
+    Aig_ManSeqCleanup( pManAigNew );
+    // remove pointers to the dead nodes
+//    Aig_ManForEachObj( pManAig, pObj, i )
+//        if ( pObj->pData && Aig_ObjIsNone(pObj->pData) )
+//            pObj->pData = NULL;
+//    Aig_ManCountMergeRegs( pManAigNew );
+p->timeTrav += Abc_Clock() - clk2;
+p->timeTotal = Abc_Clock() - clk;
+    // get the final stats
+    p->nLitsEnd  = Fra_ClassesCountLits( p->pCla );
+    p->nNodesEnd = Aig_ManNodeNum(pManAigNew);
+    p->nRegsEnd  = Aig_ManRegNum(pManAigNew);
+    // free the manager
+finish:
+    Fra_ManStop( p );
+    // check the output
+//    if ( Aig_ManCoNum(pManAigNew) - Aig_ManRegNum(pManAigNew) == 1 )
+//        if ( Aig_ObjChild0( Aig_ManCo(pManAigNew,0) ) == Aig_ManConst0(pManAigNew) )
+//            printf( "Proved output constant 0.\n" );
+    pParams->nIters = nIter;
+    return pManAigNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Outputs a set of pairs of equivalent nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_FraigInductionTest( char * pFileName, Fra_Ssw_t * pParams )
+{
+    FILE * pFile;
+    char * pFilePairs;
+    Aig_Man_t * pMan, * pNew;
+    Aig_Obj_t * pObj, * pRepr;
+    int * pNum2Id;
+    int i, Counter = 0;
+    pMan = Saig_ManReadBlif( pFileName );
+    if ( pMan == NULL )
+        return 0;
+    // perform seq SAT sweeping
+    pNew = Fra_FraigInduction( pMan, pParams );
+    if ( pNew == NULL )
+    {
+        Aig_ManStop( pMan );
+        return 0;
+    }
+    if ( pParams->fVerbose )
+    {
+        printf( "Original AIG: " );
+        Aig_ManPrintStats( pMan );
+        printf( "Reduced  AIG: " );
+        Aig_ManPrintStats( pNew );
+    }
+    Aig_ManStop( pNew );
+    pNum2Id = (int *)pMan->pData;
+    // write the output file
+    pFilePairs = Aig_FileNameGenericAppend( pFileName, ".pairs" );
+    pFile = fopen( pFilePairs, "w" );
+    Aig_ManForEachObj( pMan, pObj, i )
+        if ( (pRepr = pMan->pReprs[pObj->Id]) )
+        {
+            fprintf( pFile, "%d %d %c\n", pNum2Id[pObj->Id], pNum2Id[pRepr->Id], (Aig_ObjPhase(pObj) ^ Aig_ObjPhase(pRepr))? '-' : '+' );
+            Counter++;
+        }
+    fclose( pFile );
+    if ( pParams->fVerbose )
+    {
+        printf( "Result: %d pairs of seq equiv nodes are written into file \"%s\".\n", Counter, pFilePairs );
+    }
+    Aig_ManStop( pMan );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/fraIndVer.c b/abc-build/src/proof/fra/fraIndVer.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fraIndVer.c
@@ -0,0 +1,166 @@
+/**CFile****************************************************************
+
+  FileName    [fraIndVer.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    [Verification of the inductive invariant.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fraIndVer.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+#include "sat/cnf/cnf.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the inductive invariant.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_InvariantVerify( Aig_Man_t * pAig, int nFrames, Vec_Int_t * vClauses, Vec_Int_t * vLits )
+{
+    Cnf_Dat_t * pCnf;
+    sat_solver * pSat;
+    int * pStart;
+    int RetValue, Beg, End, i, k;
+    int CounterBase = 0, CounterInd = 0;
+    abctime clk = Abc_Clock();
+
+    if ( nFrames != 1 )
+    {
+        printf( "Invariant verification: Can only verify for K = 1\n" );
+        return 1;
+    }
+
+    // derive CNF
+    pCnf = Cnf_DeriveSimple( pAig, Aig_ManCoNum(pAig) );
+/*
+    // add the property
+    {
+        Aig_Obj_t * pObj;
+        int Lits[1];
+
+        pObj = Aig_ManCo( pAig, 0 );
+        Lits[0] = toLitCond( pCnf->pVarNums[pObj->Id], 1 ); 
+
+        Vec_IntPush( vLits, Lits[0] );
+        Vec_IntPush( vClauses, Vec_IntSize(vLits) );
+        printf( "Added the target property to the set of clauses to be inductively checked.\n" );
+    }
+*/
+    // derive initialized frames for the base case
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, nFrames, 1 );
+    // check clauses in the base case
+    Beg = 0;
+    pStart = Vec_IntArray( vLits );
+    Vec_IntForEachEntry( vClauses, End, i )
+    {
+        // complement the literals
+        for ( k = Beg; k < End; k++ )
+            pStart[k] = lit_neg(pStart[k]);
+        RetValue = sat_solver_solve( pSat, pStart + Beg, pStart + End, 0, 0, 0, 0 );
+        for ( k = Beg; k < End; k++ )
+            pStart[k] = lit_neg(pStart[k]);
+        Beg = End;
+        if ( RetValue == l_False )
+            continue;
+//        printf( "Clause %d failed the base case.\n", i );
+        CounterBase++;
+    }
+    sat_solver_delete( pSat );
+
+    // derive initialized frames for the base case
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, nFrames + 1, 0 );
+    assert( pSat->size == 2 * pCnf->nVars );
+    // add clauses to the first frame
+    Beg = 0;
+    pStart = Vec_IntArray( vLits );
+    Vec_IntForEachEntry( vClauses, End, i )
+    {
+        RetValue = sat_solver_addclause( pSat, pStart + Beg, pStart + End );
+        Beg = End;
+        if ( RetValue == 0 )
+        {
+            Cnf_DataFree( pCnf );
+            sat_solver_delete( pSat );
+            printf( "Invariant verification: SAT solver is unsat after adding a clause.\n" );
+            return 0;
+        }
+    }
+    // simplify the solver
+    if ( pSat->qtail != pSat->qhead )
+    {
+        RetValue = sat_solver_simplify(pSat);
+        assert( RetValue != 0 );
+        assert( pSat->qtail == pSat->qhead );
+    }
+
+    // check clauses in the base case
+    Beg = 0;
+    pStart = Vec_IntArray( vLits );
+    Vec_IntForEachEntry( vClauses, End, i )
+    {
+        // complement the literals
+        for ( k = Beg; k < End; k++ )
+        {
+            pStart[k] += 2 * pCnf->nVars;
+            pStart[k] = lit_neg(pStart[k]);
+        }
+        RetValue = sat_solver_solve( pSat, pStart + Beg, pStart + End, 0, 0, 0, 0 );
+        for ( k = Beg; k < End; k++ )
+        {
+            pStart[k] = lit_neg(pStart[k]);
+            pStart[k] -= 2 * pCnf->nVars;
+        }
+        Beg = End;
+        if ( RetValue == l_False )
+            continue;
+//        printf( "Clause %d failed the inductive case.\n", i );
+        CounterInd++;
+    }
+    sat_solver_delete( pSat );
+    Cnf_DataFree( pCnf );
+    if ( CounterBase )
+        printf( "Invariant verification: %d clauses (out of %d) FAILED the base case.\n", CounterBase, Vec_IntSize(vClauses) );
+    if ( CounterInd )
+        printf( "Invariant verification: %d clauses (out of %d) FAILED the inductive case.\n", CounterInd, Vec_IntSize(vClauses) );
+    if ( CounterBase || CounterInd )
+        return 0;
+    printf( "Invariant verification: %d clauses verified correctly.  ", Vec_IntSize(vClauses) );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/fraLcr.c b/abc-build/src/proof/fra/fraLcr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fraLcr.c
@@ -0,0 +1,708 @@
+/**CFile****************************************************************
+
+  FileName    [fraLcorr.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    [Latch correspondence computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fraLcorr.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Fra_Lcr_t_    Fra_Lcr_t;
+struct Fra_Lcr_t_
+{
+    // original AIG
+    Aig_Man_t *      pAig;
+    // equivalence class representation
+    Fra_Cla_t *      pCla;       
+    // partitioning information
+    Vec_Ptr_t *      vParts;        // output partitions
+    int *            pInToOutPart;  // mapping of PI num into PO partition num
+    int *            pInToOutNum;   // mapping of PI num into the num of this PO in the partition
+    // AIGs for the partitions
+    Vec_Ptr_t *      vFraigs;
+    // other variables
+    int              fRefining; 
+    // parameters
+    int              nFramesP;
+    int              fVerbose;
+    // statistics
+    int              nIters;
+    int              nLitsBeg;
+    int              nLitsEnd;
+    int              nNodesBeg;
+    int              nNodesEnd;
+    int              nRegsBeg;
+    int              nRegsEnd;
+    // runtime
+    abctime          timeSim;
+    abctime          timePart;
+    abctime          timeTrav;
+    abctime          timeFraig;
+    abctime          timeUpdate;
+    abctime          timeTotal;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the retiming manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fra_Lcr_t * Lcr_ManAlloc( Aig_Man_t * pAig )
+{
+    Fra_Lcr_t * p;
+    p = ABC_ALLOC( Fra_Lcr_t, 1 );
+    memset( p, 0, sizeof(Fra_Lcr_t) );
+    p->pAig = pAig;
+    p->pInToOutPart = ABC_ALLOC( int, Aig_ManCiNum(pAig) );
+    memset( p->pInToOutPart, 0, sizeof(int) * Aig_ManCiNum(pAig) );
+    p->pInToOutNum = ABC_ALLOC( int, Aig_ManCiNum(pAig) );
+    memset( p->pInToOutNum, 0, sizeof(int) * Aig_ManCiNum(pAig) );
+    p->vFraigs = Vec_PtrAlloc( 1000 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats for the fraiging manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lcr_ManPrint( Fra_Lcr_t * p )
+{
+    printf( "Iterations = %d.  LitBeg = %d.  LitEnd = %d. (%6.2f %%).\n", 
+        p->nIters, p->nLitsBeg, p->nLitsEnd, 100.0*p->nLitsEnd/p->nLitsBeg );
+    printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%).  RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", 
+        p->nNodesBeg, p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg, 
+        p->nRegsBeg, p->nRegsEnd, 100.0*(p->nRegsBeg-p->nRegsEnd)/p->nRegsBeg );
+    ABC_PRT( "AIG simulation  ", p->timeSim  );
+    ABC_PRT( "AIG partitioning", p->timePart );
+    ABC_PRT( "AIG rebuiding   ", p->timeTrav );
+    ABC_PRT( "FRAIGing        ", p->timeFraig );
+    ABC_PRT( "AIG updating    ", p->timeUpdate );
+    ABC_PRT( "TOTAL RUNTIME   ", p->timeTotal );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the retiming manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Lcr_ManFree( Fra_Lcr_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    if ( p->fVerbose )
+        Lcr_ManPrint( p );
+    Aig_ManForEachCi( p->pAig, pObj, i )
+        pObj->pNext = NULL;
+    Vec_PtrFree( p->vFraigs );
+    if ( p->pCla  )     Fra_ClassesStop( p->pCla );
+    if ( p->vParts  )   Vec_VecFree( (Vec_Vec_t *)p->vParts );
+    ABC_FREE( p->pInToOutPart );
+    ABC_FREE( p->pInToOutNum );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepare the AIG for class computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fra_Man_t * Fra_LcrAigPrepare( Aig_Man_t * pAig )
+{
+    Fra_Man_t * p;
+    Aig_Obj_t * pObj;
+    int i;
+    p = ABC_ALLOC( Fra_Man_t, 1 );
+    memset( p, 0, sizeof(Fra_Man_t) );
+//    Aig_ManForEachCi( pAig, pObj, i )
+    Aig_ManForEachObj( pAig, pObj, i )
+        pObj->pData = p;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepare the AIG for class computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_LcrAigPrepareTwo( Aig_Man_t * pAig, Fra_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->pData = p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares two nodes for equivalence after partitioned fraiging.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_LcrNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+    Fra_Man_t * pTemp = (Fra_Man_t *)pObj0->pData;
+    Fra_Lcr_t * pLcr = (Fra_Lcr_t *)pTemp->pBmc;
+    Aig_Man_t * pFraig;
+    Aig_Obj_t * pOut0, * pOut1;
+    int nPart0, nPart1;
+    assert( Aig_ObjIsCi(pObj0) );
+    assert( Aig_ObjIsCi(pObj1) );
+    // find the partition to which these nodes belong
+    nPart0 = pLcr->pInToOutPart[(long)pObj0->pNext];
+    nPart1 = pLcr->pInToOutPart[(long)pObj1->pNext];
+    // if this is the result of refinement of the class created const-1 nodes
+    // the nodes may end up in different partions - we assume them equivalent
+    if ( nPart0 != nPart1 )
+    {
+        assert( 0 );
+        return 1;
+    }
+    assert( nPart0 == nPart1 );
+    pFraig = (Aig_Man_t *)Vec_PtrEntry( pLcr->vFraigs, nPart0 );
+    // get the fraig outputs
+    pOut0 = Aig_ManCo( pFraig, pLcr->pInToOutNum[(long)pObj0->pNext] );
+    pOut1 = Aig_ManCo( pFraig, pLcr->pInToOutNum[(long)pObj1->pNext] );
+    return Aig_ObjFanin0(pOut0) == Aig_ObjFanin0(pOut1);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares the node with a constant after partioned fraiging.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_LcrNodeIsConst( Aig_Obj_t * pObj )
+{
+    Fra_Man_t * pTemp = (Fra_Man_t *)pObj->pData;
+    Fra_Lcr_t * pLcr = (Fra_Lcr_t *)pTemp->pBmc;
+    Aig_Man_t * pFraig;
+    Aig_Obj_t * pOut;
+    int nPart;
+    assert( Aig_ObjIsCi(pObj) );
+    // find the partition to which these nodes belong
+    nPart = pLcr->pInToOutPart[(long)pObj->pNext];
+    pFraig = (Aig_Man_t *)Vec_PtrEntry( pLcr->vFraigs, nPart );
+    // get the fraig outputs
+    pOut = Aig_ManCo( pFraig, pLcr->pInToOutNum[(long)pObj->pNext] );
+    return Aig_ObjFanin0(pOut) == Aig_ManConst1(pFraig);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the AIG manager recursively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Fra_LcrManDup_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pObjNew;
+    if ( pObj->pData )
+        return (Aig_Obj_t *)pObj->pData;
+    Fra_LcrManDup_rec( pNew, p, Aig_ObjFanin0(pObj) );
+    if ( Aig_ObjIsBuf(pObj) )
+        return (Aig_Obj_t *)(pObj->pData = Aig_ObjChild0Copy(pObj));
+    Fra_LcrManDup_rec( pNew, p, Aig_ObjFanin1(pObj) );
+    pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) );
+    return (Aig_Obj_t *)(pObj->pData = pObjNew);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Give the AIG and classes, reduces AIG for partitioning.]
+
+  Description [Ignores registers that are not in the classes. 
+  Places candidate equivalent classes of registers into single outputs 
+  (for ease of partitioning). The resulting combinational AIG contains 
+  outputs in the same order as equivalence classes of registers, 
+  followed by constant-1 registers. Preserves the set of all inputs.
+  Complemented attributes of the outputs do not matter because we need 
+  then only for collecting the structural info.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Fra_LcrDeriveAigForPartitioning( Fra_Lcr_t * pLcr )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjPo, * pObjNew, ** ppClass, * pMiter;
+    int i, c, Offset;
+    // remember the numbers of the inputs of the original AIG
+    Aig_ManForEachCi( pLcr->pAig, pObj, i )
+    {
+        pObj->pData = pLcr;
+        pObj->pNext = (Aig_Obj_t *)(long)i;
+    }
+    // compute the LO/LI offset
+    Offset = Aig_ManCoNum(pLcr->pAig) - Aig_ManCiNum(pLcr->pAig);
+    // create the PIs
+    Aig_ManCleanData( pLcr->pAig );
+    pNew = Aig_ManStartFrom( pLcr->pAig );
+    // go over the equivalence classes
+    Vec_PtrForEachEntry( Aig_Obj_t **, pLcr->pCla->vClasses, ppClass, i )
+    {
+        pMiter = Aig_ManConst0(pNew);
+        for ( c = 0; ppClass[c]; c++ )
+        {
+            assert( Aig_ObjIsCi(ppClass[c]) );
+            pObjPo  = Aig_ManCo( pLcr->pAig, Offset+(long)ppClass[c]->pNext );
+            pObjNew = Fra_LcrManDup_rec( pNew, pLcr->pAig, Aig_ObjFanin0(pObjPo) );
+            pMiter  = Aig_Exor( pNew, pMiter, pObjNew );
+        }
+        Aig_ObjCreateCo( pNew, pMiter );
+    }
+    // go over the constant candidates
+    Vec_PtrForEachEntry( Aig_Obj_t *, pLcr->pCla->vClasses1, pObj, i )
+    {
+        assert( Aig_ObjIsCi(pObj) );
+        pObjPo = Aig_ManCo( pLcr->pAig, Offset+(long)pObj->pNext );
+        pMiter = Fra_LcrManDup_rec( pNew, pLcr->pAig, Aig_ObjFanin0(pObjPo) );
+        Aig_ObjCreateCo( pNew, pMiter );
+    }
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Remaps partitions into the inputs of original AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_LcrRemapPartitions( Vec_Ptr_t * vParts, Fra_Cla_t * pCla, int * pInToOutPart, int * pInToOutNum )
+{
+    Vec_Int_t * vOne, * vOneNew;
+    Aig_Obj_t ** ppClass, * pObjPi;
+    int Out, Offset, i, k, c;
+    // compute the LO/LI offset
+    Offset = Aig_ManCoNum(pCla->pAig) - Aig_ManCiNum(pCla->pAig);
+    Vec_PtrForEachEntry( Vec_Int_t *, vParts, vOne, i )
+    {
+        vOneNew = Vec_IntAlloc( Vec_IntSize(vOne) );
+        Vec_IntForEachEntry( vOne, Out, k )
+        {
+            if ( Out < Vec_PtrSize(pCla->vClasses) )
+            {
+                ppClass = (Aig_Obj_t **)Vec_PtrEntry( pCla->vClasses, Out );
+                for ( c = 0; ppClass[c]; c++ )
+                {
+                    pInToOutPart[(long)ppClass[c]->pNext] = i;
+                    pInToOutNum[(long)ppClass[c]->pNext] = Vec_IntSize(vOneNew);
+                    Vec_IntPush( vOneNew, Offset+(long)ppClass[c]->pNext );
+                }
+            }
+            else
+            {
+                pObjPi = (Aig_Obj_t *)Vec_PtrEntry( pCla->vClasses1, Out - Vec_PtrSize(pCla->vClasses) );
+                pInToOutPart[(long)pObjPi->pNext] = i;
+                pInToOutNum[(long)pObjPi->pNext] = Vec_IntSize(vOneNew);
+                Vec_IntPush( vOneNew, Offset+(long)pObjPi->pNext );
+            }
+        }
+        // replace the class
+        Vec_PtrWriteEntry( vParts, i, vOneNew );
+        Vec_IntFree( vOne );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates AIG of one partition with speculative reduction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Fra_LcrCreatePart_rec( Fra_Cla_t * pCla, Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    assert( !Aig_IsComplement(pObj) );
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return (Aig_Obj_t *)pObj->pData;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Aig_ObjIsCi(pObj) )
+    {
+//        Aig_Obj_t * pRepr = Fra_ClassObjRepr(pObj);
+        Aig_Obj_t * pRepr = pCla->pMemRepr[pObj->Id];
+        if ( pRepr == NULL )
+            pObj->pData = Aig_ObjCreateCi( pNew );
+        else
+        {
+            pObj->pData = Fra_LcrCreatePart_rec( pCla, pNew, p, pRepr );
+            pObj->pData = Aig_NotCond( (Aig_Obj_t *)pObj->pData, pRepr->fPhase ^ pObj->fPhase );
+        }
+        return (Aig_Obj_t *)pObj->pData;
+    }
+    Fra_LcrCreatePart_rec( pCla, pNew, p, Aig_ObjFanin0(pObj) );
+    Fra_LcrCreatePart_rec( pCla, pNew, p, Aig_ObjFanin1(pObj) );
+    return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates AIG of one partition with speculative reduction.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Fra_LcrCreatePart( Fra_Lcr_t * p, Vec_Int_t * vPart )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjNew;
+    int Out, i;
+    // create new AIG for this partition
+    pNew = Aig_ManStartFrom( p->pAig );
+    Aig_ManIncrementTravId( p->pAig );
+    Aig_ObjSetTravIdCurrent( p->pAig, Aig_ManConst1(p->pAig) );
+    Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew);
+    Vec_IntForEachEntry( vPart, Out, i )
+    {
+        pObj = Aig_ManCo( p->pAig, Out );
+        if ( pObj->fMarkA )
+        {
+            pObjNew = Fra_LcrCreatePart_rec( p->pCla, pNew, p->pAig, Aig_ObjFanin0(pObj) );
+            pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) );
+        }
+        else
+            pObjNew = Aig_ManConst1( pNew );
+        Aig_ObjCreateCo( pNew, pObjNew ); 
+    }
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the nodes belonging to the equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClassNodesMark( Fra_Lcr_t * p )
+{
+    Aig_Obj_t * pObj, ** ppClass;
+    int i, c, Offset;
+    // compute the LO/LI offset
+    Offset = Aig_ManCoNum(p->pCla->pAig) - Aig_ManCiNum(p->pCla->pAig);
+    // mark the nodes remaining in the classes
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->pCla->vClasses1, pObj, i )
+    {
+        pObj = Aig_ManCo( p->pCla->pAig, Offset+(long)pObj->pNext );
+        pObj->fMarkA = 1;
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t **, p->pCla->vClasses, ppClass, i )
+    {
+        for ( c = 0; ppClass[c]; c++ )
+        {
+            pObj = Aig_ManCo( p->pCla->pAig, Offset+(long)ppClass[c]->pNext );
+            pObj->fMarkA = 1;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Unmarks the nodes belonging to the equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ClassNodesUnmark( Fra_Lcr_t * p )
+{
+    Aig_Obj_t * pObj, ** ppClass;
+    int i, c, Offset;
+    // compute the LO/LI offset
+    Offset = Aig_ManCoNum(p->pCla->pAig) - Aig_ManCiNum(p->pCla->pAig);
+    // mark the nodes remaining in the classes
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->pCla->vClasses1, pObj, i )
+    {
+        pObj = Aig_ManCo( p->pCla->pAig, Offset+(long)pObj->pNext );
+        pObj->fMarkA = 0;
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t **, p->pCla->vClasses, ppClass, i )
+    {
+        for ( c = 0; ppClass[c]; c++ )
+        {
+            pObj = Aig_ManCo( p->pCla->pAig, Offset+(long)ppClass[c]->pNext );
+            pObj->fMarkA = 0;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs choicing of the AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Fra_FraigLatchCorrespondence( Aig_Man_t * pAig, int nFramesP, int nConfMax, int fProve, int fVerbose, int * pnIter, float TimeLimit )
+{
+    int nPartSize    = 200;
+    int fReprSelect  = 0;
+    Fra_Lcr_t * p;
+    Fra_Sml_t * pSml;
+    Fra_Man_t * pTemp;
+    Aig_Man_t * pAigPart, * pAigTemp, * pAigNew = NULL;
+    Vec_Int_t * vPart;
+    int i, nIter;
+    abctime timeSim, clk2, clk3, clk = Abc_Clock();
+    abctime TimeToStop = TimeLimit ? TimeLimit * CLOCKS_PER_SEC + Abc_Clock() : 0;
+    if ( Aig_ManNodeNum(pAig) == 0 )
+    {
+        if ( pnIter ) *pnIter = 0;
+        // Ntl_ManFinalize() requires the following to satisfy an assertion.
+        Aig_ManReprStart(pAig,Aig_ManObjNumMax(pAig));
+        return Aig_ManDupOrdered(pAig);
+    }
+    assert( Aig_ManRegNum(pAig) > 0 ); 
+
+    // simulate the AIG 
+clk2 = Abc_Clock();
+if ( fVerbose )
+printf( "Simulating AIG with %d nodes for %d cycles ...  ", Aig_ManNodeNum(pAig), nFramesP + 32 );
+    pSml = Fra_SmlSimulateSeq( pAig, nFramesP, 32, 1, 1  ); 
+if ( fVerbose ) 
+{
+ABC_PRT( "Time", Abc_Clock() - clk2 );
+}
+timeSim = Abc_Clock() - clk2;
+
+    // check if simulation discovered non-constant-0 POs
+    if ( fProve && pSml->fNonConstOut )
+    {
+        pAig->pSeqModel = Fra_SmlGetCounterExample( pSml );
+        Fra_SmlStop( pSml );
+        return NULL;
+    }
+
+    // start the manager
+    p = Lcr_ManAlloc( pAig );
+    p->nFramesP = nFramesP;
+    p->fVerbose = fVerbose;
+    p->timeSim += timeSim;
+
+    pTemp = Fra_LcrAigPrepare( pAig );
+    pTemp->pBmc = (Fra_Bmc_t *)p;
+    pTemp->pSml = pSml;
+
+    // get preliminary info about equivalence classes
+    pTemp->pCla = p->pCla = Fra_ClassesStart( p->pAig );
+    Fra_ClassesPrepare( p->pCla, 1, 0 );
+    p->pCla->pFuncNodeIsConst   = Fra_LcrNodeIsConst;
+    p->pCla->pFuncNodesAreEqual = Fra_LcrNodesAreEqual;
+    Fra_SmlStop( pTemp->pSml );
+
+    // partition the AIG for latch correspondence computation
+clk2 = Abc_Clock();
+if ( fVerbose )
+printf( "Partitioning AIG ...  " );
+    pAigPart = Fra_LcrDeriveAigForPartitioning( p );
+    p->vParts = (Vec_Ptr_t *)Aig_ManPartitionSmart( pAigPart, nPartSize, 0, NULL );
+    Fra_LcrRemapPartitions( p->vParts, p->pCla, p->pInToOutPart, p->pInToOutNum );
+    Aig_ManStop( pAigPart );
+if ( fVerbose ) 
+{
+ABC_PRT( "Time", Abc_Clock() - clk2 );
+p->timePart += Abc_Clock() - clk2;
+}
+
+    // get the initial stats
+    p->nLitsBeg  = Fra_ClassesCountLits( p->pCla );
+    p->nNodesBeg = Aig_ManNodeNum(p->pAig);
+    p->nRegsBeg  = Aig_ManRegNum(p->pAig);
+
+    // perforn interative reduction of the partitions
+    p->fRefining = 1;
+    for ( nIter = 0; p->fRefining; nIter++ )
+    {
+        p->fRefining = 0;
+        clk3 = Abc_Clock();
+        // derive AIGs for each partition
+        Fra_ClassNodesMark( p );
+        Vec_PtrClear( p->vFraigs );
+        Vec_PtrForEachEntry( Vec_Int_t *, p->vParts, vPart, i )
+        {
+            if ( TimeLimit != 0.0 && Abc_Clock() > TimeToStop )
+            {
+                Vec_PtrForEachEntry( Aig_Man_t *, p->vFraigs, pAigPart, i )
+                    Aig_ManStop( pAigPart );
+                Aig_ManCleanMarkA( pAig );
+                Aig_ManCleanMarkB( pAig );
+                printf( "Fra_FraigLatchCorrespondence(): Runtime limit exceeded.\n" );
+                goto finish;
+            }
+clk2 = Abc_Clock();
+            pAigPart = Fra_LcrCreatePart( p, vPart );
+p->timeTrav += Abc_Clock() - clk2;
+clk2 = Abc_Clock();
+            pAigTemp  = Fra_FraigEquivence( pAigPart, nConfMax, 0 );
+p->timeFraig += Abc_Clock() - clk2;
+            Vec_PtrPush( p->vFraigs, pAigTemp );
+/*
+            {
+                char Name[1000];
+                sprintf( Name, "part%04d.blif", i );
+                Aig_ManDumpBlif( pAigPart, Name, NULL, NULL );
+            }
+printf( "Finished part %4d (out of %4d).  ", i, Vec_PtrSize(p->vParts) );
+ABC_PRT( "Time", Abc_Clock() - clk3 );
+*/
+
+            Aig_ManStop( pAigPart );
+        }
+        Fra_ClassNodesUnmark( p );
+        // report the intermediate results
+        if ( fVerbose )
+        {
+            printf( "%3d : Const = %6d. Class = %6d.  L = %6d. Part = %3d.  ", 
+                nIter, Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), 
+                Fra_ClassesCountLits(p->pCla), Vec_PtrSize(p->vParts) );
+            ABC_PRT( "T", Abc_Clock() - clk3 );
+        }
+        // refine the classes
+        Fra_LcrAigPrepareTwo( p->pAig, pTemp );
+        if ( Fra_ClassesRefine( p->pCla ) )
+            p->fRefining = 1;
+        if ( Fra_ClassesRefine1( p->pCla, 0, NULL ) )
+            p->fRefining = 1;
+        // clean the fraigs
+        Vec_PtrForEachEntry( Aig_Man_t *, p->vFraigs, pAigPart, i )
+            Aig_ManStop( pAigPart );
+
+        // repartition if needed
+        if ( 1 )
+        {
+clk2 = Abc_Clock();
+            Vec_VecFree( (Vec_Vec_t *)p->vParts );
+            pAigPart = Fra_LcrDeriveAigForPartitioning( p );
+            p->vParts = (Vec_Ptr_t *)Aig_ManPartitionSmart( pAigPart, nPartSize, 0, NULL );
+            Fra_LcrRemapPartitions( p->vParts, p->pCla, p->pInToOutPart, p->pInToOutNum );
+            Aig_ManStop( pAigPart );
+p->timePart += Abc_Clock() - clk2;
+        }
+    }
+    p->nIters = nIter;
+
+    // move the classes into representatives and reduce AIG
+clk2 = Abc_Clock();
+//    Fra_ClassesPrint( p->pCla, 1 );
+    if ( fReprSelect )
+        Fra_ClassesSelectRepr( p->pCla );
+    Fra_ClassesCopyReprs( p->pCla, NULL );
+    pAigNew = Aig_ManDupRepr( p->pAig, 0 );
+    Aig_ManSeqCleanup( pAigNew );
+//    Aig_ManCountMergeRegs( pAigNew );
+p->timeUpdate += Abc_Clock() - clk2;
+p->timeTotal = Abc_Clock() - clk;
+    // get the final stats
+    p->nLitsEnd  = Fra_ClassesCountLits( p->pCla );
+    p->nNodesEnd = Aig_ManNodeNum(pAigNew);
+    p->nRegsEnd  = Aig_ManRegNum(pAigNew);
+finish:
+    ABC_FREE( pTemp );
+    Lcr_ManFree( p );
+    if ( pnIter ) *pnIter = nIter;
+    return pAigNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/fraMan.c b/abc-build/src/proof/fra/fraMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fraMan.c
@@ -0,0 +1,314 @@
+/**CFile****************************************************************
+
+  FileName    [fraMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    [Starts the FRAIG manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fraMan.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the default solving parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ParamsDefault( Fra_Par_t * pPars )
+{
+    memset( pPars, 0, sizeof(Fra_Par_t) );
+    pPars->nSimWords        =       32;  // the number of words in the simulation info
+    pPars->dSimSatur        =    0.005;  // the ratio of refined classes when saturation is reached
+    pPars->fPatScores       =        0;  // enables simulation pattern scoring
+    pPars->MaxScore         =       25;  // max score after which resimulation is used
+    pPars->fDoSparse        =        1;  // skips sparse functions
+//    pPars->dActConeRatio    =     0.05;  // the ratio of cone to be bumped
+//    pPars->dActConeBumpMax  =      5.0;  // the largest bump of activity
+    pPars->dActConeRatio    =      0.3;  // the ratio of cone to be bumped
+    pPars->dActConeBumpMax  =     10.0;  // the largest bump of activity
+    pPars->nBTLimitNode     =      100;  // conflict limit at a node
+    pPars->nBTLimitMiter    =   500000;  // conflict limit at an output
+    pPars->nFramesK         =        0;  // the number of timeframes to unroll
+    pPars->fConeBias        =        1;
+    pPars->fRewrite         =        0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the default solving parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ParamsDefaultSeq( Fra_Par_t * pPars )
+{
+    memset( pPars, 0, sizeof(Fra_Par_t) );
+    pPars->nSimWords        =        1;  // the number of words in the simulation info
+    pPars->dSimSatur        =    0.005;  // the ratio of refined classes when saturation is reached
+    pPars->fPatScores       =        0;  // enables simulation pattern scoring
+    pPars->MaxScore         =       25;  // max score after which resimulation is used
+    pPars->fDoSparse        =        1;  // skips sparse functions
+    pPars->dActConeRatio    =      0.3;  // the ratio of cone to be bumped
+    pPars->dActConeBumpMax  =     10.0;  // the largest bump of activity
+    pPars->nBTLimitNode     = 10000000;  // conflict limit at a node
+    pPars->nBTLimitMiter    =   500000;  // conflict limit at an output
+    pPars->nFramesK         =        1;  // the number of timeframes to unroll
+    pPars->fConeBias        =        0;
+    pPars->fRewrite         =        0;
+    pPars->fLatchCorr       =        0;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the fraiging manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fra_Man_t * Fra_ManStart( Aig_Man_t * pManAig, Fra_Par_t * pPars )
+{
+    Fra_Man_t * p;
+    Aig_Obj_t * pObj;
+    int i;
+    // allocate the fraiging manager
+    p = ABC_ALLOC( Fra_Man_t, 1 );
+    memset( p, 0, sizeof(Fra_Man_t) );
+    p->pPars      = pPars;
+    p->pManAig    = pManAig;
+    p->nSizeAlloc = Aig_ManObjNumMax( pManAig );
+    p->nFramesAll = pPars->nFramesK + 1;
+    // allocate storage for sim pattern
+    p->nPatWords  = Abc_BitWordNum( (Aig_ManCiNum(pManAig) - Aig_ManRegNum(pManAig)) * p->nFramesAll + Aig_ManRegNum(pManAig) );
+    p->pPatWords  = ABC_ALLOC( unsigned, p->nPatWords ); 
+    p->vPiVars    = Vec_PtrAlloc( 100 );
+    // equivalence classes
+    p->pCla       = Fra_ClassesStart( pManAig );
+    // allocate other members
+    p->pMemFraig  = ABC_ALLOC( Aig_Obj_t *, p->nSizeAlloc * p->nFramesAll );
+    memset( p->pMemFraig, 0, sizeof(Aig_Obj_t *) * p->nSizeAlloc * p->nFramesAll );
+    // set random number generator
+//    srand( 0xABCABC );
+    Aig_ManRandom(1);
+    // set the pointer to the manager
+    Aig_ManForEachObj( p->pManAig, pObj, i )
+        pObj->pData = p;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the fraiging manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ManClean( Fra_Man_t * p, int nNodesMax )
+{
+    int i;
+    // remove old arrays
+    for ( i = 0; i < p->nMemAlloc; i++ )
+        if ( p->pMemFanins[i] && p->pMemFanins[i] != (void *)1 )
+            Vec_PtrFree( p->pMemFanins[i] );
+    // realloc for the new size
+    if ( p->nMemAlloc < nNodesMax )
+    {
+        int nMemAllocNew = nNodesMax + 5000;
+        p->pMemFanins = ABC_REALLOC( Vec_Ptr_t *, p->pMemFanins, nMemAllocNew );
+        p->pMemSatNums = ABC_REALLOC( int, p->pMemSatNums, nMemAllocNew );
+        p->nMemAlloc = nMemAllocNew;
+    }
+    // prepare for the new run
+    memset( p->pMemFanins, 0, sizeof(Vec_Ptr_t *) * p->nMemAlloc );
+    memset( p->pMemSatNums, 0, sizeof(int) * p->nMemAlloc );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the new manager to begin fraiging.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Fra_ManPrepareComb( Fra_Man_t * p )
+{
+    Aig_Man_t * pManFraig;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( p->pManFraig == NULL );
+    // start the fraig package
+    pManFraig = Aig_ManStart( Aig_ManObjNumMax(p->pManAig) );
+    pManFraig->pName = Abc_UtilStrsav( p->pManAig->pName );
+    pManFraig->pSpec = Abc_UtilStrsav( p->pManAig->pSpec );
+    pManFraig->nRegs    = p->pManAig->nRegs;
+    pManFraig->nAsserts = p->pManAig->nAsserts;
+    // set the pointers to the available fraig nodes
+    Fra_ObjSetFraig( Aig_ManConst1(p->pManAig), 0, Aig_ManConst1(pManFraig) );
+    Aig_ManForEachCi( p->pManAig, pObj, i )
+        Fra_ObjSetFraig( pObj, 0, Aig_ObjCreateCi(pManFraig) );
+    // set the pointers to the manager
+    Aig_ManForEachObj( pManFraig, pObj, i )
+        pObj->pData = p;
+    // allocate memory for mapping FRAIG nodes into SAT numbers and fanins
+    p->nMemAlloc = p->nSizeAlloc;
+    p->pMemFanins = ABC_ALLOC( Vec_Ptr_t *, p->nMemAlloc );
+    memset( p->pMemFanins, 0, sizeof(Vec_Ptr_t *) * p->nMemAlloc );
+    p->pMemSatNums = ABC_ALLOC( int, p->nMemAlloc );
+    memset( p->pMemSatNums, 0, sizeof(int) * p->nMemAlloc );
+    // make sure the satisfying assignment is node assigned
+    assert( pManFraig->pData == NULL );
+    return pManFraig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finalizes the combinational miter after fraiging.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ManFinalizeComb( Fra_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    // add the POs
+    Aig_ManForEachCo( p->pManAig, pObj, i )
+        Aig_ObjCreateCo( p->pManFraig, Fra_ObjChild0Fra(pObj,0) );
+    // postprocess
+    Aig_ManCleanMarkB( p->pManFraig );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the fraiging manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ManStop( Fra_Man_t * p )
+{
+    if ( p->pPars->fVerbose )
+        Fra_ManPrint( p );
+    // save mapping from original nodes into FRAIG nodes
+    if ( p->pManAig )
+    {
+        if ( p->pManAig->pObjCopies )
+            ABC_FREE( p->pManAig->pObjCopies );
+        p->pManAig->pObjCopies = p->pMemFraig;
+        p->pMemFraig = NULL;
+    }
+    Fra_ManClean( p, 0 );
+    if ( p->vTimeouts ) Vec_PtrFree( p->vTimeouts );
+    if ( p->vPiVars )   Vec_PtrFree( p->vPiVars );
+    if ( p->pSat )      sat_solver_delete( p->pSat );
+    if ( p->pCla  )     Fra_ClassesStop( p->pCla );
+    if ( p->pSml )      Fra_SmlStop( p->pSml );
+    if ( p->vCex )      Vec_IntFree( p->vCex );
+    if ( p->vOneHots )  Vec_IntFree( p->vOneHots );
+    ABC_FREE( p->pMemFraig );
+    ABC_FREE( p->pMemFanins );
+    ABC_FREE( p->pMemSatNums );
+    ABC_FREE( p->pPatWords );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats for the fraiging manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ManPrint( Fra_Man_t * p )
+{
+    double nMemory = 1.0*Aig_ManObjNumMax(p->pManAig)*(p->pSml->nWordsTotal*sizeof(unsigned)+6*sizeof(void*))/(1<<20);
+    printf( "SimWord = %d. Round = %d.  Mem = %0.2f MB.  LitBeg = %d.  LitEnd = %d. (%6.2f %%).\n", 
+        p->pPars->nSimWords, p->pSml->nSimRounds, nMemory, p->nLitsBeg, p->nLitsEnd, 100.0*p->nLitsEnd/(p->nLitsBeg?p->nLitsBeg:1) );
+    printf( "Proof = %d. Cex = %d. Fail = %d. FailReal = %d. C-lim = %d. ImpRatio = %6.2f %%\n", 
+        p->nSatProof, p->nSatCallsSat, p->nSatFails, p->nSatFailsReal, p->pPars->nBTLimitNode, Fra_ImpComputeStateSpaceRatio(p) );
+    printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%).  RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", 
+        p->nNodesBeg, p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/(p->nNodesBeg?p->nNodesBeg:1), 
+        p->nRegsBeg, p->nRegsEnd, 100.0*(p->nRegsBeg-p->nRegsEnd)/(p->nRegsBeg?p->nRegsBeg:1) );
+    if ( p->pSat )             Sat_SolverPrintStats( stdout, p->pSat );
+    if ( p->pPars->fUse1Hot )  Fra_OneHotEstimateCoverage( p, p->vOneHots );
+    ABC_PRT( "AIG simulation  ", p->pSml->timeSim  );
+    ABC_PRT( "AIG traversal   ", p->timeTrav );
+    if ( p->timeRwr )
+    {
+    ABC_PRT( "AIG rewriting   ", p->timeRwr  );
+    }
+    ABC_PRT( "SAT solving     ", p->timeSat  );
+    ABC_PRT( "    Unsat       ", p->timeSatUnsat );
+    ABC_PRT( "    Sat         ", p->timeSatSat   );
+    ABC_PRT( "    Fail        ", p->timeSatFail  );
+    ABC_PRT( "Class refining  ", p->timeRef   );
+    ABC_PRT( "TOTAL RUNTIME   ", p->timeTotal );
+    if ( p->time1 ) { ABC_PRT( "time1           ", p->time1 ); }
+    if ( p->nSpeculs )
+    printf( "Speculations = %d.\n", p->nSpeculs );
+    fflush( stdout );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/fraPart.c b/abc-build/src/proof/fra/fraPart.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fraPart.c
@@ -0,0 +1,269 @@
+/**CFile****************************************************************
+
+  FileName    [fraPart.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    [Partitioning for induction.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fraPart.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ManPartitionTest( Aig_Man_t * p, int nComLim )
+{
+//    Bar_Progress_t * pProgress;
+    Vec_Vec_t * vSupps, * vSuppsIn;
+    Vec_Ptr_t * vSuppsNew;
+    Vec_Int_t * vSupNew, * vSup, * vSup2, * vTemp;//, * vSupIn;
+    Vec_Int_t * vOverNew, * vQuantNew;
+    Aig_Obj_t * pObj;
+    int i, k, nCommon, CountOver, CountQuant;
+    int nTotalSupp, nTotalSupp2, Entry, Largest;//, iVar;
+    double Ratio, R;
+    abctime clk;
+
+    nTotalSupp = 0;
+    nTotalSupp2 = 0;
+    Ratio = 0.0;
+ 
+    // compute supports
+clk = Abc_Clock();
+    vSupps = (Vec_Vec_t *)Aig_ManSupports( p );
+ABC_PRT( "Supports", Abc_Clock() - clk );
+    // remove last entry
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        vSup = Vec_VecEntryInt( vSupps, i );
+        Vec_IntPop( vSup );
+        // remember support
+//        pObj->pNext = (Aig_Obj_t *)vSup;
+    }
+
+    // create reverse supports
+clk = Abc_Clock();
+    vSuppsIn = Vec_VecStart( Aig_ManCiNum(p) );
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        vSup = Vec_VecEntryInt( vSupps, i );
+        Vec_IntForEachEntry( vSup, Entry, k )
+            Vec_VecPush( vSuppsIn, Entry, (void *)(ABC_PTRUINT_T)i );
+    }
+ABC_PRT( "Inverse ", Abc_Clock() - clk );
+
+clk = Abc_Clock();
+    // compute extended supports
+    Largest = 0;
+    vSuppsNew = Vec_PtrAlloc( Aig_ManCoNum(p) );
+    vOverNew  = Vec_IntAlloc( Aig_ManCoNum(p) );
+    vQuantNew = Vec_IntAlloc( Aig_ManCoNum(p) );
+//    pProgress = Bar_ProgressStart( stdout, Aig_ManCoNum(p) );
+    Aig_ManForEachCo( p, pObj, i )
+    {
+//        Bar_ProgressUpdate( pProgress, i, NULL );
+        // get old supports
+        vSup = Vec_VecEntryInt( vSupps, i );
+        if ( Vec_IntSize(vSup) < 2 )
+            continue;
+        // compute new supports
+        CountOver = CountQuant = 0;
+        vSupNew = Vec_IntDup( vSup );
+        // go through the nodes where the first var appears
+        Aig_ManForEachCo( p, pObj, k )
+//        iVar = Vec_IntEntry( vSup, 0 );
+//        vSupIn = Vec_VecEntry( vSuppsIn, iVar );
+//        Vec_IntForEachEntry( vSupIn, Entry, k )
+        {
+//            pObj = Aig_ManObj( p, Entry );
+            // get support of this output
+//            vSup2 = (Vec_Int_t *)pObj->pNext;
+            vSup2 = Vec_VecEntryInt( vSupps, k );
+            // count the number of common vars
+            nCommon = Vec_IntTwoCountCommon(vSup, vSup2);
+            if ( nCommon < 2 )
+                continue;
+            if ( nCommon > nComLim )
+            {
+                vSupNew = Vec_IntTwoMerge( vTemp = vSupNew, vSup2 );
+                Vec_IntFree( vTemp );
+                CountOver++;
+            }
+            else
+                CountQuant++;
+        }
+        // save the results
+        Vec_PtrPush( vSuppsNew, vSupNew );
+        Vec_IntPush( vOverNew, CountOver );
+        Vec_IntPush( vQuantNew, CountQuant );
+
+        if ( Largest < Vec_IntSize(vSupNew) )
+            Largest = Vec_IntSize(vSupNew);
+
+        nTotalSupp  += Vec_IntSize(vSup);
+        nTotalSupp2 += Vec_IntSize(vSupNew);
+        if ( Vec_IntSize(vSup) )
+            R = Vec_IntSize(vSupNew) / Vec_IntSize(vSup);
+        else
+            R = 0;
+        Ratio += R;
+
+        if ( R < 5.0 )
+            continue;
+
+        printf( "%6d : ", i );
+        printf( "S = %5d. ", Vec_IntSize(vSup) );
+        printf( "SNew = %5d. ", Vec_IntSize(vSupNew) );
+        printf( "R = %7.2f. ", R );
+        printf( "Over = %5d. ", CountOver );
+        printf( "Quant = %5d. ", CountQuant );
+        printf( "\n" );
+/*
+        Vec_IntForEachEntry( vSupNew, Entry, k )
+            printf( "%d ", Entry );
+        printf( "\n" );
+*/
+    }
+//    Bar_ProgressStop( pProgress );
+ABC_PRT( "Scanning", Abc_Clock() - clk );
+
+    // print cumulative statistics
+    printf( "PIs = %6d. POs = %6d. Lim = %3d.   AveS = %3d. SN = %3d. R = %4.2f Max = %5d.\n",
+        Aig_ManCiNum(p), Aig_ManCoNum(p), nComLim,
+        nTotalSupp/Aig_ManCoNum(p), nTotalSupp2/Aig_ManCoNum(p),
+        Ratio/Aig_ManCoNum(p), Largest );
+
+    Vec_VecFree( vSupps );
+    Vec_VecFree( vSuppsIn );
+    Vec_VecFree( (Vec_Vec_t *)vSuppsNew );
+    Vec_IntFree( vOverNew );
+    Vec_IntFree( vQuantNew );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_ManPartitionTest2( Aig_Man_t * p )
+{
+    Vec_Vec_t * vSupps, * vSuppsIn;
+    Vec_Int_t * vSup, * vSup2, * vSup3;
+    Aig_Obj_t * pObj;
+    int Entry, Entry2, Entry3, Counter;
+    int i, k, m, n;
+    abctime clk;
+    char * pSupp;
+ 
+    // compute supports
+clk = Abc_Clock();
+    vSupps = (Vec_Vec_t *)Aig_ManSupports( p );
+ABC_PRT( "Supports", Abc_Clock() - clk );
+    // remove last entry
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        vSup = Vec_VecEntryInt( vSupps, i );
+        Vec_IntPop( vSup );
+        // remember support
+//        pObj->pNext = (Aig_Obj_t *)vSup;
+    }
+
+    // create reverse supports
+clk = Abc_Clock();
+    vSuppsIn = Vec_VecStart( Aig_ManCiNum(p) );
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        if ( i == p->nAsserts )
+            break;
+        vSup = Vec_VecEntryInt( vSupps, i );
+        Vec_IntForEachEntry( vSup, Entry, k )
+            Vec_VecPush( vSuppsIn, Entry, (void *)(ABC_PTRUINT_T)i );
+    }
+ABC_PRT( "Inverse ", Abc_Clock() - clk );
+
+    // create affective supports
+clk = Abc_Clock();
+    pSupp = ABC_ALLOC( char, Aig_ManCiNum(p) );
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        if ( i % 50 != 0 )
+            continue;
+        vSup = Vec_VecEntryInt( vSupps, i );
+        memset( pSupp, 0, sizeof(char) * Aig_ManCiNum(p) );
+        // go through each input of this output
+        Vec_IntForEachEntry( vSup, Entry, k )
+        {
+            pSupp[Entry] = 1;
+            vSup2 = Vec_VecEntryInt( vSuppsIn, Entry );
+            // go though each assert of this input
+            Vec_IntForEachEntry( vSup2, Entry2, m )
+            {
+                vSup3 = Vec_VecEntryInt( vSupps, Entry2 );
+                // go through each input of this assert
+                Vec_IntForEachEntry( vSup3, Entry3, n )
+                {
+                    pSupp[Entry3] = 1;
+                }
+            }
+        }
+        // count the entries
+        Counter = 0;
+        for ( m = 0; m < Aig_ManCiNum(p); m++ )
+            Counter += pSupp[m];
+        printf( "%d(%d) ", Vec_IntSize(vSup), Counter );
+    }
+    printf( "\n" );
+ABC_PRT( "Extension ", Abc_Clock() - clk );
+
+    ABC_FREE( pSupp );
+    Vec_VecFree( vSupps );
+    Vec_VecFree( vSuppsIn );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/fraSat.c b/abc-build/src/proof/fra/fraSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fraSat.c
@@ -0,0 +1,571 @@
+/**CFile****************************************************************
+
+  FileName    [fraSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fraSat.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <math.h>
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Fra_SetActivityFactors( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Runs equivalence test for the two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_NodesAreEquiv( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew )
+{
+    int pLits[4], RetValue, RetValue1, nBTLimit;
+    abctime clk;//, clk2 = Abc_Clock();
+    int status;
+
+    // make sure the nodes are not complemented
+    assert( !Aig_IsComplement(pNew) );
+    assert( !Aig_IsComplement(pOld) );
+    assert( pNew != pOld );
+
+    // if at least one of the nodes is a failed node, perform adjustments:
+    // if the backtrack limit is small, simply skip this node
+    // if the backtrack limit is > 10, take the quare root of the limit
+    nBTLimit = p->pPars->nBTLimitNode;
+    if ( !p->pPars->fSpeculate && p->pPars->nFramesK == 0 && (nBTLimit > 0 && (pOld->fMarkB || pNew->fMarkB)) )
+    {
+        p->nSatFails++;
+        // fail immediately
+//        return -1;
+        if ( nBTLimit <= 10 )
+            return -1;
+        nBTLimit = (int)pow(nBTLimit, 0.7);
+    }
+
+    p->nSatCalls++;
+    p->nSatCallsRecent++;
+
+    // make sure the solver is allocated and has enough variables
+    if ( p->pSat == NULL )
+    {
+        p->pSat = sat_solver_new();
+        p->nSatVars = 1;
+        sat_solver_setnvars( p->pSat, 1000 );
+        // var 0 is reserved for const1 node - add the clause
+        pLits[0] = toLit( 0 );
+        sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+    }
+
+    // if the nodes do not have SAT variables, allocate them
+    Fra_CnfNodeAddToSolver( p, pOld, pNew );
+
+    if ( p->pSat->qtail != p->pSat->qhead )
+    {
+        status = sat_solver_simplify(p->pSat);
+        assert( status != 0 );
+        assert( p->pSat->qtail == p->pSat->qhead );
+    }
+
+    // prepare variable activity
+    if ( p->pPars->fConeBias )
+        Fra_SetActivityFactors( p, pOld, pNew ); 
+
+    // solve under assumptions
+    // A = 1; B = 0     OR     A = 1; B = 1 
+clk = Abc_Clock();
+    pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 0 );
+    pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase );
+//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
+    RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, 
+        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, 
+        p->nBTLimitGlobal, p->nInsLimitGlobal );
+p->timeSat += Abc_Clock() - clk;
+    if ( RetValue1 == l_False )
+    {
+p->timeSatUnsat += Abc_Clock() - clk;
+        pLits[0] = lit_neg( pLits[0] );
+        pLits[1] = lit_neg( pLits[1] );
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+        // continue solving the other implication
+        p->nSatCallsUnsat++;
+    }
+    else if ( RetValue1 == l_True )
+    {
+p->timeSatSat += Abc_Clock() - clk;
+        Fra_SmlSavePattern( p );
+        p->nSatCallsSat++;
+        return 0;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+p->timeSatFail += Abc_Clock() - clk;
+        // mark the node as the failed node
+        if ( pOld != p->pManFraig->pConst1 ) 
+            pOld->fMarkB = 1;
+        pNew->fMarkB = 1;
+        p->nSatFailsReal++;
+        return -1;
+    }
+
+    // if the old node was constant 0, we already know the answer
+    if ( pOld == p->pManFraig->pConst1 )
+    {
+        p->nSatProof++;
+        return 1;
+    }
+
+    // solve under assumptions
+    // A = 0; B = 1     OR     A = 0; B = 0 
+clk = Abc_Clock();
+    pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 1 );
+    pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase ^ pNew->fPhase );
+    RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, 
+        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, 
+        p->nBTLimitGlobal, p->nInsLimitGlobal );
+p->timeSat += Abc_Clock() - clk;
+    if ( RetValue1 == l_False )
+    {
+p->timeSatUnsat += Abc_Clock() - clk;
+        pLits[0] = lit_neg( pLits[0] );
+        pLits[1] = lit_neg( pLits[1] );
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+        p->nSatCallsUnsat++;
+    }
+    else if ( RetValue1 == l_True )
+    {
+p->timeSatSat += Abc_Clock() - clk;
+        Fra_SmlSavePattern( p );
+        p->nSatCallsSat++;
+        return 0;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+p->timeSatFail += Abc_Clock() - clk;
+        // mark the node as the failed node
+        pOld->fMarkB = 1;
+        pNew->fMarkB = 1;
+        p->nSatFailsReal++;
+        return -1;
+    }
+/*
+    // check BDD proof
+    {
+        int RetVal;
+        ABC_PRT( "Sat", Abc_Clock() - clk2 );
+        clk2 = Abc_Clock();
+        RetVal = Fra_NodesAreEquivBdd( pOld, pNew );
+//        printf( "%d ", RetVal );
+        assert( RetVal );
+        ABC_PRT( "Bdd", Abc_Clock() - clk2 );
+        printf( "\n" );
+    }
+*/
+    // return SAT proof
+    p->nSatProof++;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Runs the result of test for pObj => pNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_NodesAreImp( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew, int fComplL, int fComplR )
+{
+    int pLits[4], RetValue, RetValue1, nBTLimit;
+    abctime clk;//, clk2 = Abc_Clock();
+    int status;
+
+    // make sure the nodes are not complemented
+    assert( !Aig_IsComplement(pNew) );
+    assert( !Aig_IsComplement(pOld) );
+    assert( pNew != pOld );
+
+    // if at least one of the nodes is a failed node, perform adjustments:
+    // if the backtrack limit is small, simply skip this node
+    // if the backtrack limit is > 10, take the quare root of the limit
+    nBTLimit = p->pPars->nBTLimitNode;
+/*
+    if ( !p->pPars->fSpeculate && p->pPars->nFramesK == 0 && (nBTLimit > 0 && (pOld->fMarkB || pNew->fMarkB)) )
+    {
+        p->nSatFails++;
+        // fail immediately
+//        return -1;
+        if ( nBTLimit <= 10 )
+            return -1;
+        nBTLimit = (int)pow(nBTLimit, 0.7);
+    }
+*/
+    p->nSatCalls++;
+
+    // make sure the solver is allocated and has enough variables
+    if ( p->pSat == NULL )
+    {
+        p->pSat = sat_solver_new();
+        p->nSatVars = 1;
+        sat_solver_setnvars( p->pSat, 1000 );
+        // var 0 is reserved for const1 node - add the clause
+        pLits[0] = toLit( 0 );
+        sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+    }
+
+    // if the nodes do not have SAT variables, allocate them
+    Fra_CnfNodeAddToSolver( p, pOld, pNew );
+
+    if ( p->pSat->qtail != p->pSat->qhead )
+    {
+        status = sat_solver_simplify(p->pSat);
+        assert( status != 0 );
+        assert( p->pSat->qtail == p->pSat->qhead );
+    }
+
+    // prepare variable activity
+    if ( p->pPars->fConeBias )
+        Fra_SetActivityFactors( p, pOld, pNew ); 
+
+    // solve under assumptions
+    // A = 1; B = 0     OR     A = 1; B = 1 
+clk = Abc_Clock();
+//    pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 0 );
+//    pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase );
+    pLits[0] = toLitCond( Fra_ObjSatNum(pOld),  fComplL );
+    pLits[1] = toLitCond( Fra_ObjSatNum(pNew), !fComplR );
+//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
+    RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, 
+        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, 
+        p->nBTLimitGlobal, p->nInsLimitGlobal );
+p->timeSat += Abc_Clock() - clk;
+    if ( RetValue1 == l_False )
+    {
+p->timeSatUnsat += Abc_Clock() - clk;
+        pLits[0] = lit_neg( pLits[0] );
+        pLits[1] = lit_neg( pLits[1] );
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+        // continue solving the other implication
+        p->nSatCallsUnsat++;
+    }
+    else if ( RetValue1 == l_True )
+    {
+p->timeSatSat += Abc_Clock() - clk;
+        Fra_SmlSavePattern( p );
+        p->nSatCallsSat++;
+        return 0;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+p->timeSatFail += Abc_Clock() - clk;
+        // mark the node as the failed node
+        if ( pOld != p->pManFraig->pConst1 ) 
+            pOld->fMarkB = 1;
+        pNew->fMarkB = 1;
+        p->nSatFailsReal++;
+        return -1;
+    }
+    // return SAT proof
+    p->nSatProof++;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Runs the result of test for pObj => pNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_NodesAreClause( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew, int fComplL, int fComplR )
+{
+    int pLits[4], RetValue, RetValue1, nBTLimit;
+    abctime clk;//, clk2 = Abc_Clock();
+    int status;
+
+    // make sure the nodes are not complemented
+    assert( !Aig_IsComplement(pNew) );
+    assert( !Aig_IsComplement(pOld) );
+    assert( pNew != pOld );
+
+    // if at least one of the nodes is a failed node, perform adjustments:
+    // if the backtrack limit is small, simply skip this node
+    // if the backtrack limit is > 10, take the quare root of the limit
+    nBTLimit = p->pPars->nBTLimitNode;
+/*
+    if ( !p->pPars->fSpeculate && p->pPars->nFramesK == 0 && (nBTLimit > 0 && (pOld->fMarkB || pNew->fMarkB)) )
+    {
+        p->nSatFails++;
+        // fail immediately
+//        return -1;
+        if ( nBTLimit <= 10 )
+            return -1;
+        nBTLimit = (int)pow(nBTLimit, 0.7);
+    }
+*/
+    p->nSatCalls++;
+
+    // make sure the solver is allocated and has enough variables
+    if ( p->pSat == NULL )
+    {
+        p->pSat = sat_solver_new();
+        p->nSatVars = 1;
+        sat_solver_setnvars( p->pSat, 1000 );
+        // var 0 is reserved for const1 node - add the clause
+        pLits[0] = toLit( 0 );
+        sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+    }
+
+    // if the nodes do not have SAT variables, allocate them
+    Fra_CnfNodeAddToSolver( p, pOld, pNew );
+
+    if ( p->pSat->qtail != p->pSat->qhead )
+    {
+        status = sat_solver_simplify(p->pSat);
+        assert( status != 0 );
+        assert( p->pSat->qtail == p->pSat->qhead );
+    }
+
+    // prepare variable activity
+    if ( p->pPars->fConeBias )
+        Fra_SetActivityFactors( p, pOld, pNew ); 
+
+    // solve under assumptions
+    // A = 1; B = 0     OR     A = 1; B = 1 
+clk = Abc_Clock();
+//    pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 0 );
+//    pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase );
+    pLits[0] = toLitCond( Fra_ObjSatNum(pOld), !fComplL );
+    pLits[1] = toLitCond( Fra_ObjSatNum(pNew), !fComplR );
+//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
+    RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, 
+        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, 
+        p->nBTLimitGlobal, p->nInsLimitGlobal );
+p->timeSat += Abc_Clock() - clk;
+    if ( RetValue1 == l_False )
+    {
+p->timeSatUnsat += Abc_Clock() - clk;
+        pLits[0] = lit_neg( pLits[0] );
+        pLits[1] = lit_neg( pLits[1] );
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+        // continue solving the other implication
+        p->nSatCallsUnsat++;
+    }
+    else if ( RetValue1 == l_True )
+    {
+p->timeSatSat += Abc_Clock() - clk;
+        Fra_SmlSavePattern( p );
+        p->nSatCallsSat++;
+        return 0;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+p->timeSatFail += Abc_Clock() - clk;
+        // mark the node as the failed node
+        if ( pOld != p->pManFraig->pConst1 ) 
+            pOld->fMarkB = 1;
+        pNew->fMarkB = 1;
+        p->nSatFailsReal++;
+        return -1;
+    }
+    // return SAT proof
+    p->nSatProof++;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Runs equivalence test for one node.]
+
+  Description [Returns the fraiged node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_NodeIsConst( Fra_Man_t * p, Aig_Obj_t * pNew )
+{
+    int pLits[2], RetValue1, RetValue;
+    abctime clk;
+
+    // make sure the nodes are not complemented
+    assert( !Aig_IsComplement(pNew) );
+    assert( pNew != p->pManFraig->pConst1 );
+    p->nSatCalls++;
+
+    // make sure the solver is allocated and has enough variables
+    if ( p->pSat == NULL )
+    {
+        p->pSat = sat_solver_new();
+        p->nSatVars = 1;
+        sat_solver_setnvars( p->pSat, 1000 );
+        // var 0 is reserved for const1 node - add the clause
+        pLits[0] = toLit( 0 );
+        sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+    }
+
+    // if the nodes do not have SAT variables, allocate them
+    Fra_CnfNodeAddToSolver( p, NULL, pNew );
+
+    // prepare variable activity
+    if ( p->pPars->fConeBias )
+        Fra_SetActivityFactors( p, NULL, pNew ); 
+
+    // solve under assumptions
+clk = Abc_Clock();
+    pLits[0] = toLitCond( Fra_ObjSatNum(pNew), pNew->fPhase );
+    RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 1, 
+        (ABC_INT64_T)p->pPars->nBTLimitMiter, (ABC_INT64_T)0, 
+        p->nBTLimitGlobal, p->nInsLimitGlobal );
+p->timeSat += Abc_Clock() - clk;
+    if ( RetValue1 == l_False )
+    {
+p->timeSatUnsat += Abc_Clock() - clk;
+        pLits[0] = lit_neg( pLits[0] );
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+        assert( RetValue );
+        // continue solving the other implication
+        p->nSatCallsUnsat++;
+    }
+    else if ( RetValue1 == l_True )
+    {
+p->timeSatSat += Abc_Clock() - clk;
+        if ( p->pPatWords )
+            Fra_SmlSavePattern( p );
+        p->nSatCallsSat++;
+        return 0;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+p->timeSatFail += Abc_Clock() - clk;
+        // mark the node as the failed node
+        pNew->fMarkB = 1;
+        p->nSatFailsReal++;
+        return -1;
+    }
+
+    // return SAT proof
+    p->nSatProof++;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets variable activities in the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_SetActivityFactors_rec( Fra_Man_t * p, Aig_Obj_t * pObj, int LevelMin, int LevelMax )
+{
+    Vec_Ptr_t * vFanins;
+    Aig_Obj_t * pFanin;
+    int i, Counter = 0;
+    assert( !Aig_IsComplement(pObj) );
+    assert( Fra_ObjSatNum(pObj) );
+    // skip visited variables
+    if ( Aig_ObjIsTravIdCurrent(p->pManFraig, pObj) )
+        return 0;
+    Aig_ObjSetTravIdCurrent(p->pManFraig, pObj);
+    // add the PI to the list
+    if ( pObj->Level <= (unsigned)LevelMin || Aig_ObjIsCi(pObj) )
+        return 0;
+    // set the factor of this variable
+    // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pPars->dActConeBumpMax / ThisBump
+    if ( p->pSat->factors == NULL )
+        p->pSat->factors = ABC_CALLOC( double, p->pSat->cap );
+    p->pSat->factors[Fra_ObjSatNum(pObj)] = p->pPars->dActConeBumpMax * (pObj->Level - LevelMin)/(LevelMax - LevelMin);
+    veci_push(&p->pSat->act_vars, Fra_ObjSatNum(pObj));
+    // explore the fanins
+    vFanins = Fra_ObjFaninVec( pObj );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vFanins, pFanin, i )
+        Counter += Fra_SetActivityFactors_rec( p, Aig_Regular(pFanin), LevelMin, LevelMax );
+    return 1 + Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets variable activities in the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_SetActivityFactors( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew )
+{
+    int LevelMin, LevelMax;
+    abctime clk;
+    assert( pOld || pNew );
+clk = Abc_Clock(); 
+    // reset the active variables
+    veci_resize(&p->pSat->act_vars, 0);
+    // prepare for traversal
+    Aig_ManIncrementTravId( p->pManFraig );
+    // determine the min and max level to visit
+    assert( p->pPars->dActConeRatio > 0 && p->pPars->dActConeRatio < 1 );
+    LevelMax = Abc_MaxInt( (pNew ? pNew->Level : 0), (pOld ? pOld->Level : 0) );
+    LevelMin = (int)(LevelMax * (1.0 - p->pPars->dActConeRatio));
+    // traverse
+    if ( pOld && !Aig_ObjIsConst1(pOld) )
+        Fra_SetActivityFactors_rec( p, pOld, LevelMin, LevelMax );
+    if ( pNew && !Aig_ObjIsConst1(pNew) )
+        Fra_SetActivityFactors_rec( p, pNew, LevelMin, LevelMax );
+//Fra_PrintActivity( p );
+p->timeTrav += Abc_Clock() - clk;
+    return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/fraSec.c b/abc-build/src/proof/fra/fraSec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fraSec.c
@@ -0,0 +1,693 @@
+/**CFile****************************************************************
+
+  FileName    [fraSec.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    [Performs SEC based on seq sweeping.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fraSec.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+#include "aig/ioa/ioa.h"
+#include "proof/int/int.h"
+#include "proof/ssw/ssw.h"
+#include "aig/saig/saig.h"
+#include "proof/bbr/bbr.h"
+#include "proof/pdr/pdr.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SecSetDefaultParams( Fra_Sec_t * p )
+{
+    memset( p, 0, sizeof(Fra_Sec_t) );
+    p->fTryComb          =       1;  // try CEC call as a preprocessing step
+    p->fTryBmc           =       1;  // try BMC call as a preprocessing step 
+    p->nFramesMax        =       4;  // the max number of frames used for induction
+    p->nBTLimit          =    1000;  // conflict limit at a node during induction 
+    p->nBTLimitGlobal    = 5000000;  // global conflict limit during induction
+    p->nBTLimitInter     =   10000;  // conflict limit during interpolation
+    p->nBddVarsMax       =     150;  // the limit on the number of registers in BDD reachability
+    p->nBddMax           =   50000;  // the limit on the number of BDD nodes 
+    p->nBddIterMax       = 1000000;  // the limit on the number of BDD iterations
+    p->fPhaseAbstract    =       0;  // enables phase abstraction
+    p->fRetimeFirst      =       1;  // enables most-forward retiming at the beginning
+    p->fRetimeRegs       =       1;  // enables min-register retiming at the beginning
+    p->fFraiging         =       1;  // enables fraiging at the beginning
+    p->fInduction        =       1;  // enables the use of induction (signal correspondence)
+    p->fInterpolation    =       1;  // enables interpolation
+    p->fInterSeparate    =       0;  // enables interpolation for each outputs separately
+    p->fReachability     =       1;  // enables BDD based reachability
+    p->fReorderImage     =       1;  // enables variable reordering during image computation
+    p->fStopOnFirstFail  =       1;  // enables stopping after first output of a miter has failed to prove
+    p->fUseNewProver     =       0;  // enables new prover
+    p->fUsePdr           =       1;  // enables PDR
+    p->nPdrTimeout       =      60;  // enabled PDR timeout
+    p->fSilent           =       0;  // disables all output
+    p->fVerbose          =       0;  // enables verbose reporting of statistics
+    p->fVeryVerbose      =       0;  // enables very verbose reporting  
+    p->TimeLimit         =       0;  // enables the timeout
+    // internal parameters
+    p->fReportSolution   =       0;  // enables specialized format for reporting solution
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_FraigSec( Aig_Man_t * p, Fra_Sec_t * pParSec, Aig_Man_t ** ppResult )
+{
+    Ssw_Pars_t Pars2, * pPars2 = &Pars2;
+    Fra_Ssw_t Pars, * pPars = &Pars;
+    Fra_Sml_t * pSml;
+    Aig_Man_t * pNew, * pTemp;
+    int nFrames, RetValue, nIter;
+    abctime clk, clkTotal = Abc_Clock();
+    int TimeOut = 0;
+    int fLatchCorr = 0;
+    float TimeLeft = 0.0;
+    pParSec->nSMnumber = -1;
+
+    // try the miter before solving
+    pNew = Aig_ManDupSimple( p );
+    RetValue = Fra_FraigMiterStatus( pNew );
+    if ( RetValue >= 0 )
+        goto finish;
+
+    // prepare parameters
+    memset( pPars, 0, sizeof(Fra_Ssw_t) );
+    pPars->fLatchCorr  = fLatchCorr;
+    pPars->fVerbose = pParSec->fVeryVerbose;
+    if ( pParSec->fVerbose )
+    {
+        printf( "Original miter:       Latches = %5d. Nodes = %6d.\n", 
+            Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+    }
+//Aig_ManDumpBlif( pNew, "after.blif", NULL, NULL );
+
+    // perform sequential cleanup
+clk = Abc_Clock();
+    if ( pNew->nRegs )
+    pNew = Aig_ManReduceLaches( pNew, 0 );
+    if ( pNew->nRegs )
+    pNew = Aig_ManConstReduce( pNew, 0, -1, -1, 0, 0 );
+    if ( pParSec->fVerbose )
+    {
+        printf( "Sequential cleanup:   Latches = %5d. Nodes = %6d. ", 
+            Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    RetValue = Fra_FraigMiterStatus( pNew );
+    if ( RetValue >= 0 )
+        goto finish;
+
+    // perform phase abstraction
+clk = Abc_Clock();
+    if ( pParSec->fPhaseAbstract )
+    {
+        extern Aig_Man_t * Saig_ManPhaseAbstractAuto( Aig_Man_t * p, int fVerbose );
+        pNew->nTruePis = Aig_ManCiNum(pNew) - Aig_ManRegNum(pNew); 
+        pNew->nTruePos = Aig_ManCoNum(pNew) - Aig_ManRegNum(pNew); 
+        pNew = Saig_ManPhaseAbstractAuto( pTemp = pNew, 0 );
+        Aig_ManStop( pTemp );
+        if ( pParSec->fVerbose )
+        {
+            printf( "Phase abstraction:    Latches = %5d. Nodes = %6d. ", 
+                Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+        }
+    }
+
+    // perform forward retiming
+    if ( pParSec->fRetimeFirst && pNew->nRegs )
+    {
+clk = Abc_Clock();
+//    pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 );
+    pNew = Saig_ManRetimeForward( pTemp = pNew, 100, 0 );
+    Aig_ManStop( pTemp );
+    if ( pParSec->fVerbose )
+    {
+        printf( "Forward retiming:     Latches = %5d. Nodes = %6d. ", 
+            Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    }
+     
+    // run latch correspondence
+clk = Abc_Clock();
+    if ( pNew->nRegs )
+    {
+    pNew = Aig_ManDupOrdered( pTemp = pNew );
+//    pNew = Aig_ManDupDfs( pTemp = pNew );
+    Aig_ManStop( pTemp );
+/*
+    if ( RetValue == -1 && pParSec->TimeLimit )
+    {
+        TimeLeft = (float)pParSec->TimeLimit - ((float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC));
+        TimeLeft = Abc_MaxInt( TimeLeft, 0.0 );
+        if ( TimeLeft == 0.0 )
+        {
+            if ( !pParSec->fSilent )
+                printf( "Runtime limit exceeded.\n" );
+            RetValue = -1;
+            TimeOut = 1;
+            goto finish;
+        }
+    }
+*/
+
+//    pNew = Fra_FraigLatchCorrespondence( pTemp = pNew, 0, 1000, 1, pParSec->fVeryVerbose, &nIter, TimeLeft );
+//Aig_ManDumpBlif( pNew, "ex.blif", NULL, NULL );
+    Ssw_ManSetDefaultParamsLcorr( pPars2 );
+    pNew = Ssw_LatchCorrespondence( pTemp = pNew, pPars2 );
+    nIter = pPars2->nIters;
+
+    // prepare parameters for scorr
+    Ssw_ManSetDefaultParams( pPars2 );
+
+    if ( pTemp->pSeqModel )
+    {
+        if ( !Saig_ManVerifyCex( pTemp, pTemp->pSeqModel ) )
+            printf( "Fra_FraigSec(): Counter-example verification has FAILED.\n" );
+        if ( Saig_ManPiNum(p) != Saig_ManPiNum(pTemp) )
+            printf( "The counter-example is invalid because of phase abstraction.\n" );
+        else
+        {
+        ABC_FREE( p->pSeqModel );
+        p->pSeqModel = Abc_CexDup( pTemp->pSeqModel, Aig_ManRegNum(p) );
+        ABC_FREE( pTemp->pSeqModel );
+        }
+    }
+    if ( pNew == NULL )
+    {
+        if ( p->pSeqModel )
+        {
+            RetValue = 0;
+            if ( !pParSec->fSilent )
+            {
+                printf( "Networks are NOT EQUIVALENT after simulation.   " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+            }
+            if ( pParSec->fReportSolution && !pParSec->fRecursive )
+            {
+            printf( "SOLUTION: FAIL       " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+            }
+            Aig_ManStop( pTemp );
+            return RetValue;
+        }
+        pNew = pTemp;
+        RetValue = -1;
+        TimeOut = 1;
+        goto finish;
+    }
+    Aig_ManStop( pTemp );
+
+    if ( pParSec->fVerbose )
+    {
+        printf( "Latch-corr (I=%3d):   Latches = %5d. Nodes = %6d. ", 
+            nIter, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    }
+/*
+    if ( RetValue == -1 && pParSec->TimeLimit )
+    {
+        TimeLeft = (float)pParSec->TimeLimit - ((float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC));
+        TimeLeft = Abc_MaxInt( TimeLeft, 0.0 );
+        if ( TimeLeft == 0.0 )
+        {
+            if ( !pParSec->fSilent )
+                printf( "Runtime limit exceeded.\n" );
+            RetValue = -1;
+            TimeOut = 1;
+            goto finish;
+        }
+    }
+*/
+    // perform fraiging
+    if ( pParSec->fFraiging )
+    {
+clk = Abc_Clock();
+    pNew = Fra_FraigEquivence( pTemp = pNew, 100, 0 );
+    Aig_ManStop( pTemp );
+    if ( pParSec->fVerbose )
+    {
+        printf( "Fraiging:             Latches = %5d. Nodes = %6d. ", 
+            Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    }
+
+    if ( pNew->nRegs == 0 )
+        RetValue = Fra_FraigCec( &pNew, 100000, 0 );
+
+    RetValue = Fra_FraigMiterStatus( pNew );
+    if ( RetValue >= 0 )
+        goto finish;
+/*
+    if ( RetValue == -1 && pParSec->TimeLimit )
+    {
+        TimeLeft = (float)pParSec->TimeLimit - ((float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC));
+        TimeLeft = Abc_MaxInt( TimeLeft, 0.0 );
+        if ( TimeLeft == 0.0 )
+        {
+            if ( !pParSec->fSilent )
+                printf( "Runtime limit exceeded.\n" );
+            RetValue = -1;
+            TimeOut = 1;
+            goto finish;
+        }
+    }
+*/
+    // perform min-area retiming
+    if ( pParSec->fRetimeRegs && pNew->nRegs )
+    {
+//    extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose );
+clk = Abc_Clock();
+    pNew->nTruePis = Aig_ManCiNum(pNew) - Aig_ManRegNum(pNew); 
+    pNew->nTruePos = Aig_ManCoNum(pNew) - Aig_ManRegNum(pNew); 
+//        pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 );
+    pNew = Saig_ManRetimeMinArea( pTemp = pNew, 1000, 0, 0, 1, 0 );
+    Aig_ManStop( pTemp );
+    pNew = Aig_ManDupOrdered( pTemp = pNew );
+    Aig_ManStop( pTemp );
+    if ( pParSec->fVerbose )
+    {
+    printf( "Min-reg retiming:     Latches = %5d. Nodes = %6d. ", 
+        Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    }
+
+    // perform seq sweeping while increasing the number of frames
+    RetValue = Fra_FraigMiterStatus( pNew );
+    if ( RetValue == -1 && pParSec->fInduction )
+    for ( nFrames = 1; nFrames <= pParSec->nFramesMax; nFrames *= 2 )
+    {
+/*
+        if ( RetValue == -1 && pParSec->TimeLimit )
+        {
+            TimeLeft = (float)pParSec->TimeLimit - ((float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC));
+            TimeLeft = Abc_MaxInt( TimeLeft, 0.0 );
+            if ( TimeLeft == 0.0 )
+            {
+                if ( !pParSec->fSilent )
+                    printf( "Runtime limit exceeded.\n" );
+                RetValue = -1;
+                TimeOut = 1;
+                goto finish;
+            }
+        }
+*/ 
+
+clk = Abc_Clock();
+        pPars->nFramesK = nFrames;
+        pPars->TimeLimit = TimeLeft;
+        pPars->fSilent = pParSec->fSilent;
+//        pNew = Fra_FraigInduction( pTemp = pNew, pPars );
+
+        pPars2->nFramesK = nFrames;
+        pPars2->nBTLimit = pParSec->nBTLimit;
+        pPars2->nBTLimitGlobal = pParSec->nBTLimitGlobal;
+//        pPars2->nBTLimit = 1000 * nFrames;
+
+        if ( RetValue == -1 && pPars2->nConflicts > pPars2->nBTLimitGlobal )
+        {
+            if ( !pParSec->fSilent )
+                printf( "Global conflict limit (%d) exceeded.\n", pPars2->nBTLimitGlobal );
+            RetValue = -1;
+            TimeOut = 1;
+            goto finish;
+        }
+
+        Aig_ManSetRegNum( pNew, pNew->nRegs );
+//        pNew = Ssw_SignalCorrespondence( pTemp = pNew, pPars2 );
+        if ( Aig_ManRegNum(pNew) > 0 )
+            pNew = Ssw_SignalCorrespondence( pTemp = pNew, pPars2 );
+        else
+            pNew = Aig_ManDupSimpleDfs( pTemp = pNew );
+
+        if ( pNew == NULL )
+        {
+            pNew = pTemp;
+            RetValue = -1;
+            TimeOut = 1;
+            goto finish;
+        }
+
+//        printf( "Total conflicts = %d.\n", pPars2->nConflicts );
+
+        Aig_ManStop( pTemp );
+        RetValue = Fra_FraigMiterStatus( pNew );
+        if ( pParSec->fVerbose )
+        { 
+            printf( "K-step (K=%2d,I=%3d):  Latches = %5d. Nodes = %6d. ", 
+                nFrames, pPars2->nIters, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+        }
+        if ( RetValue != -1 )
+            break;
+
+        // perform retiming
+//        if ( pParSec->fRetimeFirst && pNew->nRegs )
+        if ( pNew->nRegs )
+        {
+//        extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose );
+clk = Abc_Clock();
+        pNew->nTruePis = Aig_ManCiNum(pNew) - Aig_ManRegNum(pNew); 
+        pNew->nTruePos = Aig_ManCoNum(pNew) - Aig_ManRegNum(pNew); 
+//        pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 );
+        pNew = Saig_ManRetimeMinArea( pTemp = pNew, 1000, 0, 0, 1, 0 );
+        Aig_ManStop( pTemp );
+        pNew = Aig_ManDupOrdered( pTemp = pNew );
+        Aig_ManStop( pTemp );
+        if ( pParSec->fVerbose )
+        {
+            printf( "Min-reg retiming:     Latches = %5d. Nodes = %6d. ", 
+                Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+        }
+        }  
+
+        if ( pNew->nRegs )
+            pNew = Aig_ManConstReduce( pNew, 0, -1, -1, 0, 0 );
+
+        // perform rewriting
+clk = Abc_Clock();
+        pNew = Aig_ManDupOrdered( pTemp = pNew );
+        Aig_ManStop( pTemp );
+//        pNew = Dar_ManRewriteDefault( pTemp = pNew );
+        pNew = Dar_ManCompress2( pTemp = pNew, 1, 0, 1, 0, 0 ); 
+        Aig_ManStop( pTemp );
+        if ( pParSec->fVerbose )
+        {
+            printf( "Rewriting:            Latches = %5d. Nodes = %6d. ", 
+                Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+        } 
+
+        // perform sequential simulation
+        if ( pNew->nRegs )
+        {
+clk = Abc_Clock();
+        pSml = Fra_SmlSimulateSeq( pNew, 0, 128 * nFrames, 1 + 16/(1+Aig_ManNodeNum(pNew)/1000), 1  ); 
+        if ( pParSec->fVerbose )
+        {
+            printf( "Seq simulation  :     Latches = %5d. Nodes = %6d. ", 
+                Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", Abc_Clock() - clk );
+        }
+        if ( pSml->fNonConstOut )
+        {
+            pNew->pSeqModel = Fra_SmlGetCounterExample( pSml );
+            // transfer to the original manager
+            if ( Saig_ManPiNum(p) != Saig_ManPiNum(pNew) )
+                printf( "The counter-example is invalid because of phase abstraction.\n" );
+            else
+            {
+            ABC_FREE( p->pSeqModel );
+            p->pSeqModel = Abc_CexDup( pNew->pSeqModel, Aig_ManRegNum(p) );
+            ABC_FREE( pNew->pSeqModel );
+            }
+
+            Fra_SmlStop( pSml );
+            Aig_ManStop( pNew );
+            RetValue = 0;
+            if ( !pParSec->fSilent )
+            {
+                printf( "Networks are NOT EQUIVALENT after simulation.   " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+            }
+            if ( pParSec->fReportSolution && !pParSec->fRecursive )
+            {
+            printf( "SOLUTION: FAIL       " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+            }
+            return RetValue;
+        }
+        Fra_SmlStop( pSml );
+        }
+    }
+
+    // get the miter status
+    RetValue = Fra_FraigMiterStatus( pNew );
+
+    // try interplation
+clk = Abc_Clock();
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(pNew) );
+    if ( pParSec->fInterpolation && RetValue == -1 && Aig_ManRegNum(pNew) > 0 )
+    {
+        Inter_ManParams_t Pars, * pPars = &Pars;
+        int Depth;
+        ABC_FREE( pNew->pSeqModel );
+        Inter_ManSetDefaultParams( pPars );
+//        pPars->nBTLimit = 100;
+        pPars->nBTLimit = pParSec->nBTLimitInter;
+        pPars->fVerbose = pParSec->fVeryVerbose;
+        if ( Saig_ManPoNum(pNew) == 1 )
+        {
+            RetValue = Inter_ManPerformInterpolation( pNew, pPars, &Depth );
+        }
+        else if ( pParSec->fInterSeparate )
+        {
+            Abc_Cex_t * pCex = NULL;
+            Aig_Man_t * pTemp, * pAux;
+            Aig_Obj_t * pObjPo;
+            int i, Counter = 0;
+            Saig_ManForEachPo( pNew, pObjPo, i )
+            { 
+                if ( Aig_ObjFanin0(pObjPo) == Aig_ManConst1(pNew) )
+                    continue;
+                if ( pPars->fVerbose )
+                    printf( "Solving output %2d (out of %2d):\n", i, Saig_ManPoNum(pNew) );
+                pTemp = Aig_ManDupOneOutput( pNew, i, 1 );
+                pTemp = Aig_ManScl( pAux = pTemp, 1, 1, 0, -1, -1, 0, 0 );
+                Aig_ManStop( pAux );
+                if ( Saig_ManRegNum(pTemp) > 0 )
+                {
+                    RetValue = Inter_ManPerformInterpolation( pTemp, pPars, &Depth );
+                    if ( pTemp->pSeqModel )
+                    {
+                        pCex = p->pSeqModel = Abc_CexDup( pTemp->pSeqModel, Aig_ManRegNum(p) );
+                        pCex->iPo = i;
+                        Aig_ManStop( pTemp );
+                        break;
+                    }
+                    // if solved, remove the output
+                    if ( RetValue == 1 )
+                    {
+                        Aig_ObjPatchFanin0( pNew, pObjPo, Aig_ManConst0(pNew) );
+    //                    printf( "Output %3d : Solved ", i );
+                    }
+                    else
+                    {
+                        Counter++;
+    //                    printf( "Output %3d : Undec  ", i );
+                    }
+                }
+                else
+                    Counter++;
+//                Aig_ManPrintStats( pTemp );
+                Aig_ManStop( pTemp );
+                printf( "Solving output %3d (out of %3d) using interpolation.\r", i, Saig_ManPoNum(pNew) );
+            }
+            Aig_ManCleanup( pNew );
+            if ( pCex == NULL )
+            {
+                printf( "Interpolation left %d (out of %d) outputs unsolved              \n", Counter, Saig_ManPoNum(pNew) );
+                if ( Counter )
+                    RetValue = -1;
+            }
+            pNew = Aig_ManDupUnsolvedOutputs( pTemp = pNew, 1 );
+            Aig_ManStop( pTemp );
+            pNew = Aig_ManScl( pTemp = pNew, 1, 1, 0, -1, -1, 0, 0 );
+            Aig_ManStop( pTemp );
+        }
+        else
+        {
+            Aig_Man_t * pNewOrpos = Saig_ManDupOrpos( pNew );
+            RetValue = Inter_ManPerformInterpolation( pNewOrpos, pPars, &Depth );
+            if ( pNewOrpos->pSeqModel )
+            {
+                Abc_Cex_t * pCex;
+                pCex = pNew->pSeqModel = pNewOrpos->pSeqModel; pNewOrpos->pSeqModel = NULL;
+                pCex->iPo = Saig_ManFindFailedPoCex( pNew, pNew->pSeqModel );
+            }
+            Aig_ManStop( pNewOrpos );
+        }
+
+        if ( pParSec->fVerbose )
+        {
+        if ( RetValue == 1 )
+            printf( "Property proved using interpolation.  " );
+        else if ( RetValue == 0 )
+            printf( "Property DISPROVED in frame %d using interpolation.  ", Depth );
+        else if ( RetValue == -1 )
+            printf( "Property UNDECIDED after interpolation.  " );
+        else
+            assert( 0 ); 
+ABC_PRT( "Time", Abc_Clock() - clk );
+        }
+    }
+
+    // try reachability analysis
+    if ( pParSec->fReachability && RetValue == -1 && Aig_ManRegNum(pNew) > 0 && Aig_ManRegNum(pNew) < pParSec->nBddVarsMax )
+    {
+        Saig_ParBbr_t Pars, * pPars = &Pars;
+        Bbr_ManSetDefaultParams( pPars );
+        pPars->TimeLimit     = 0;
+        pPars->nBddMax       = pParSec->nBddMax;
+        pPars->nIterMax      = pParSec->nBddIterMax;
+        pPars->fPartition    = 1;
+        pPars->fReorder      = 1;
+        pPars->fReorderImage = 1;
+        pPars->fVerbose      = 0;
+        pPars->fSilent       = pParSec->fSilent;
+        pNew->nTruePis = Aig_ManCiNum(pNew) - Aig_ManRegNum(pNew); 
+        pNew->nTruePos = Aig_ManCoNum(pNew) - Aig_ManRegNum(pNew); 
+        RetValue = Aig_ManVerifyUsingBdds( pNew, pPars );
+    }
+
+    // try PDR
+    if ( pParSec->fUsePdr && RetValue == -1 && Aig_ManRegNum(pNew) > 0 )
+    {
+        Pdr_Par_t Pars, * pPars = &Pars;
+        Pdr_ManSetDefaultParams( pPars );
+        pPars->nTimeOut = pParSec->nPdrTimeout;
+        pPars->fVerbose = pParSec->fVerbose;
+        if ( pParSec->fVerbose )
+            printf( "Running property directed reachability...\n" );
+        RetValue = Pdr_ManSolve( pNew, pPars );
+        if ( pNew->pSeqModel )
+            pNew->pSeqModel->iPo = Saig_ManFindFailedPoCex( pNew, pNew->pSeqModel );
+    }
+
+finish:
+    // report the miter
+    if ( RetValue == 1 )
+    {
+        if ( !pParSec->fSilent )
+        {
+            printf( "Networks are equivalent.   " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+        }
+        if ( pParSec->fReportSolution && !pParSec->fRecursive )
+        {
+        printf( "SOLUTION: PASS       " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+        }
+    }
+    else if ( RetValue == 0 )
+    {
+        if ( pNew->pSeqModel == NULL )
+        {
+            int i;
+            // if the CEX is not derives, it is because tricial CEX should be assumed
+            pNew->pSeqModel = Abc_CexAlloc( Aig_ManRegNum(pNew), pNew->nTruePis, 1 );
+            // if the CEX does not work, we need to change PIs to 1 because 
+            // the only way it can happen is when a PO is equal to a PI...
+            if ( Saig_ManFindFailedPoCex( pNew, pNew->pSeqModel ) == -1 )
+                for ( i = 0; i < pNew->nTruePis; i++ )
+                    Abc_InfoSetBit( pNew->pSeqModel->pData, i );
+        }
+        if ( !pParSec->fSilent )
+        {
+            printf( "Networks are NOT EQUIVALENT.   " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+        }
+        if ( pParSec->fReportSolution && !pParSec->fRecursive )
+        {
+        printf( "SOLUTION: FAIL       " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+        }
+    }
+    else 
+    {
+        ///////////////////////////////////
+        // save intermediate result
+        extern void Abc_FrameSetSave1( void * pAig );
+        Abc_FrameSetSave1( Aig_ManDupSimple(pNew) );
+        ///////////////////////////////////
+        if ( !pParSec->fSilent )
+        {
+            printf( "Networks are UNDECIDED.   " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+        }
+        if ( pParSec->fReportSolution && !pParSec->fRecursive )
+        {
+        printf( "SOLUTION: UNDECIDED  " );
+ABC_PRT( "Time", Abc_Clock() - clkTotal );
+        }
+        if ( !TimeOut && !pParSec->fSilent )
+        {
+            static int Counter = 1;
+            char pFileName[1000];
+            pParSec->nSMnumber = Counter;
+            sprintf( pFileName, "sm%02d.aig", Counter++ );
+            Ioa_WriteAiger( pNew, pFileName, 0, 0 );
+            printf( "The unsolved reduced miter is written into file \"%s\".\n", pFileName );
+        }
+    }
+    if ( pNew->pSeqModel )
+    {
+        if ( Saig_ManPiNum(p) != Saig_ManPiNum(pNew) )
+            printf( "The counter-example is invalid because of phase abstraction.\n" );
+        else
+        {
+        ABC_FREE( p->pSeqModel );
+        p->pSeqModel = Abc_CexDup( pNew->pSeqModel, Aig_ManRegNum(p) );
+        ABC_FREE( pNew->pSeqModel );
+        }
+    }
+    if ( ppResult != NULL )
+        *ppResult = Aig_ManDupSimpleDfs( pNew );
+    if ( pNew )
+        Aig_ManStop( pNew );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/fraSim.c b/abc-build/src/proof/fra/fraSim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fraSim.c
@@ -0,0 +1,1173 @@
+/**CFile****************************************************************
+
+  FileName    [fraSim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fraSim.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+#include "aig/saig/saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash value of the node using its simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_SmlNodeHash( Aig_Obj_t * pObj, int nTableSize )
+{
+    Fra_Man_t * p = (Fra_Man_t *)pObj->pData;
+    static int s_FPrimes[128] = { 
+        1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 
+        1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 
+        2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 
+        2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 
+        3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 
+        3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 
+        4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 
+        4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 
+        5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 
+        6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 
+        6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 
+        7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 
+        8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+    };
+    unsigned * pSims;
+    unsigned uHash;
+    int i;
+//    assert( p->pSml->nWordsTotal <= 128 );
+    uHash = 0;
+    pSims = Fra_ObjSim(p->pSml, pObj->Id);
+    for ( i = p->pSml->nWordsPref; i < p->pSml->nWordsTotal; i++ )
+        uHash ^= pSims[i] * s_FPrimes[i & 0x7F];
+    return uHash % nTableSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation info is composed of all zeros.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_SmlNodeIsConst( Aig_Obj_t * pObj )
+{
+    Fra_Man_t * p = (Fra_Man_t *)pObj->pData;
+    unsigned * pSims;
+    int i;
+    pSims = Fra_ObjSim(p->pSml, pObj->Id);
+    for ( i = p->pSml->nWordsPref; i < p->pSml->nWordsTotal; i++ )
+        if ( pSims[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation infos are equal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_SmlNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+    Fra_Man_t * p = (Fra_Man_t *)pObj0->pData;
+    unsigned * pSims0, * pSims1;
+    int i;
+    pSims0 = Fra_ObjSim(p->pSml, pObj0->Id);
+    pSims1 = Fra_ObjSim(p->pSml, pObj1->Id);
+    for ( i = p->pSml->nWordsPref; i < p->pSml->nWordsTotal; i++ )
+        if ( pSims0[i] != pSims1[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of 1s in the XOR of simulation data.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_SmlNodeNotEquWeight( Fra_Sml_t * p, int Left, int Right )
+{
+    unsigned * pSimL, * pSimR;
+    int k, Counter = 0;
+    pSimL = Fra_ObjSim( p, Left );
+    pSimR = Fra_ObjSim( p, Right );
+    for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+        Counter += Aig_WordCountOnes( pSimL[k] ^ pSimR[k] );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation info is composed of all zeros.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_SmlNodeIsZero( Fra_Sml_t * p, Aig_Obj_t * pObj )
+{
+    unsigned * pSims;
+    int i;
+    pSims = Fra_ObjSim(p, pObj->Id);
+    for ( i = p->nWordsPref; i < p->nWordsTotal; i++ )
+        if ( pSims[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of one's in the patten of the output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_SmlNodeCountOnes( Fra_Sml_t * p, Aig_Obj_t * pObj )
+{
+    unsigned * pSims;
+    int i, Counter = 0;
+    pSims = Fra_ObjSim(p, pObj->Id);
+    for ( i = 0; i < p->nWordsTotal; i++ )
+        Counter += Aig_WordCountOnes( pSims[i] );
+    return Counter;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Generated const 0 pattern.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SmlSavePattern0( Fra_Man_t * p, int fInit )
+{
+    memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [[Generated const 1 pattern.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SmlSavePattern1( Fra_Man_t * p, int fInit )
+{
+    Aig_Obj_t * pObj;
+    int i, k, nTruePis;
+    memset( p->pPatWords, 0xff, sizeof(unsigned) * p->nPatWords );
+    if ( !fInit )
+        return;
+    // clear the state bits to correspond to all-0 initial state
+    nTruePis = Aig_ManCiNum(p->pManAig) - Aig_ManRegNum(p->pManAig);
+    k = 0;
+    Aig_ManForEachLoSeq( p->pManAig, pObj, i )
+        Abc_InfoXorBit( p->pPatWords, nTruePis * p->nFramesAll + k++ );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Copy pattern from the solver into the internal storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SmlSavePattern( Fra_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+    Aig_ManForEachCi( p->pManFraig, pObj, i )
+//        if ( p->pSat->model.ptr[Fra_ObjSatNum(pObj)] == l_True )
+        if ( sat_solver_var_value(p->pSat, Fra_ObjSatNum(pObj)) )
+            Abc_InfoSetBit( p->pPatWords, i );
+
+    if ( p->vCex )
+    {
+        Vec_IntClear( p->vCex );
+        for ( i = 0; i < Aig_ManCiNum(p->pManAig) - Aig_ManRegNum(p->pManAig); i++ )
+            Vec_IntPush( p->vCex, Abc_InfoHasBit( p->pPatWords, i ) );
+        for ( i = Aig_ManCiNum(p->pManFraig) - Aig_ManRegNum(p->pManFraig); i < Aig_ManCiNum(p->pManFraig); i++ )
+            Vec_IntPush( p->vCex, Abc_InfoHasBit( p->pPatWords, i ) );
+    }
+
+/*
+    printf( "Pattern: " );
+    Aig_ManForEachCi( p->pManFraig, pObj, i )
+        printf( "%d", Abc_InfoHasBit( p->pPatWords, i ) );
+    printf( "\n" );
+*/
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the counter-example from the successful pattern.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SmlCheckOutputSavePattern( Fra_Man_t * p, Aig_Obj_t * pObjPo )
+{ 
+    Aig_Obj_t * pFanin, * pObjPi;
+    unsigned * pSims;
+    int i, k, BestPat, * pModel;
+    // find the word of the pattern
+    pFanin = Aig_ObjFanin0(pObjPo);
+    pSims = Fra_ObjSim(p->pSml, pFanin->Id);
+    for ( i = 0; i < p->pSml->nWordsTotal; i++ )
+        if ( pSims[i] )
+            break;
+    assert( i < p->pSml->nWordsTotal );
+    // find the bit of the pattern
+    for ( k = 0; k < 32; k++ )
+        if ( pSims[i] & (1 << k) )
+            break;
+    assert( k < 32 );
+    // determine the best pattern
+    BestPat = i * 32 + k;
+    // fill in the counter-example data
+    pModel = ABC_ALLOC( int, Aig_ManCiNum(p->pManFraig)+1 );
+    Aig_ManForEachCi( p->pManAig, pObjPi, i )
+    {
+        pModel[i] = Abc_InfoHasBit(Fra_ObjSim(p->pSml, pObjPi->Id), BestPat);
+//        printf( "%d", pModel[i] );
+    }
+    pModel[Aig_ManCiNum(p->pManAig)] = pObjPo->Id;
+//    printf( "\n" );
+    // set the model
+    assert( p->pManFraig->pData == NULL );
+    p->pManFraig->pData = pModel;
+    return;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the one of the output is already non-constant 0.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_SmlCheckOutput( Fra_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    // make sure the reference simulation pattern does not detect the bug
+    pObj = Aig_ManCo( p->pManAig, 0 );
+    assert( Aig_ObjFanin0(pObj)->fPhase == (unsigned)Aig_ObjFaninC0(pObj) ); 
+    Aig_ManForEachCo( p->pManAig, pObj, i )
+    {
+        if ( !Fra_SmlNodeIsConst( Aig_ObjFanin0(pObj) ) )
+        {
+            // create the counter-example from this pattern
+            Fra_SmlCheckOutputSavePattern( p, pObj );
+            return 1;
+        }
+    }
+    return 0;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns random patterns to the PI node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SmlAssignRandom( Fra_Sml_t * p, Aig_Obj_t * pObj )
+{
+    unsigned * pSims;
+    int i;
+    assert( Aig_ObjIsCi(pObj) );
+    pSims = Fra_ObjSim( p, pObj->Id );
+    for ( i = 0; i < p->nWordsTotal; i++ )
+        pSims[i] = Fra_ObjRandomSim();
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns constant patterns to the PI node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SmlAssignConst( Fra_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame )
+{
+    unsigned * pSims;
+    int i;
+    assert( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) );
+    pSims = Fra_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame;
+    for ( i = 0; i < p->nWordsFrame; i++ )
+        pSims[i] = fConst1? ~(unsigned)0 : 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assings random simulation info for the PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SmlInitialize( Fra_Sml_t * p, int fInit )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    if ( fInit )
+    {
+        assert( Aig_ManRegNum(p->pAig) > 0 );
+        assert( Aig_ManRegNum(p->pAig) < Aig_ManCiNum(p->pAig) );
+        // assign random info for primary inputs
+        Aig_ManForEachPiSeq( p->pAig, pObj, i )
+            Fra_SmlAssignRandom( p, pObj );
+        // assign the initial state for the latches
+        Aig_ManForEachLoSeq( p->pAig, pObj, i )
+            Fra_SmlAssignConst( p, pObj, 0, 0 );
+    }
+    else
+    {
+        Aig_ManForEachCi( p->pAig, pObj, i )
+            Fra_SmlAssignRandom( p, pObj );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assings distance-1 simulation info for the PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SmlAssignDist1( Fra_Sml_t * p, unsigned * pPat )
+{
+    Aig_Obj_t * pObj;
+    int f, i, k, Limit, nTruePis;
+    assert( p->nFrames > 0 );
+    if ( p->nFrames == 1 )
+    {
+        // copy the PI info 
+        Aig_ManForEachCi( p->pAig, pObj, i )
+            Fra_SmlAssignConst( p, pObj, Abc_InfoHasBit(pPat, i), 0 );
+        // flip one bit
+        Limit = Abc_MinInt( Aig_ManCiNum(p->pAig), p->nWordsTotal * 32 - 1 );
+        for ( i = 0; i < Limit; i++ )
+            Abc_InfoXorBit( Fra_ObjSim( p, Aig_ManCi(p->pAig,i)->Id ), i+1 );
+    }
+    else
+    {
+        int fUseDist1 = 0;
+
+        // copy the PI info for each frame
+        nTruePis = Aig_ManCiNum(p->pAig) - Aig_ManRegNum(p->pAig);
+        for ( f = 0; f < p->nFrames; f++ )
+            Aig_ManForEachPiSeq( p->pAig, pObj, i )
+                Fra_SmlAssignConst( p, pObj, Abc_InfoHasBit(pPat, nTruePis * f + i), f );
+        // copy the latch info 
+        k = 0;
+        Aig_ManForEachLoSeq( p->pAig, pObj, i )
+            Fra_SmlAssignConst( p, pObj, Abc_InfoHasBit(pPat, nTruePis * p->nFrames + k++), 0 );
+//        assert( p->pManFraig == NULL || nTruePis * p->nFrames + k == Aig_ManCiNum(p->pManFraig) );
+
+        // flip one bit of the last frame
+        if ( fUseDist1 ) //&& p->nFrames == 2 )
+        {
+            Limit = Abc_MinInt( nTruePis, p->nWordsFrame * 32 - 1 );
+            for ( i = 0; i < Limit; i++ )
+                Abc_InfoXorBit( Fra_ObjSim( p, Aig_ManCi(p->pAig, i)->Id ) + p->nWordsFrame*(p->nFrames-1), i+1 );
+        }
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SmlNodeSimulate( Fra_Sml_t * p, Aig_Obj_t * pObj, int iFrame )
+{
+    unsigned * pSims, * pSims0, * pSims1;
+    int fCompl, fCompl0, fCompl1, i;
+    assert( !Aig_IsComplement(pObj) );
+    assert( Aig_ObjIsNode(pObj) );
+    assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal );
+    // get hold of the simulation information
+    pSims  = Fra_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame;
+    pSims0 = Fra_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame;
+    pSims1 = Fra_ObjSim(p, Aig_ObjFanin1(pObj)->Id) + p->nWordsFrame * iFrame;
+    // get complemented attributes of the children using their random info
+    fCompl  = pObj->fPhase;
+    fCompl0 = Aig_ObjPhaseReal(Aig_ObjChild0(pObj));
+    fCompl1 = Aig_ObjPhaseReal(Aig_ObjChild1(pObj));
+    // simulate
+    if ( fCompl0 && fCompl1 )
+    {
+        if ( fCompl )
+            for ( i = 0; i < p->nWordsFrame; i++ )
+                pSims[i] = (pSims0[i] | pSims1[i]);
+        else
+            for ( i = 0; i < p->nWordsFrame; i++ )
+                pSims[i] = ~(pSims0[i] | pSims1[i]);
+    }
+    else if ( fCompl0 && !fCompl1 )
+    {
+        if ( fCompl )
+            for ( i = 0; i < p->nWordsFrame; i++ )
+                pSims[i] = (pSims0[i] | ~pSims1[i]);
+        else
+            for ( i = 0; i < p->nWordsFrame; i++ )
+                pSims[i] = (~pSims0[i] & pSims1[i]);
+    }
+    else if ( !fCompl0 && fCompl1 )
+    {
+        if ( fCompl )
+            for ( i = 0; i < p->nWordsFrame; i++ )
+                pSims[i] = (~pSims0[i] | pSims1[i]);
+        else
+            for ( i = 0; i < p->nWordsFrame; i++ )
+                pSims[i] = (pSims0[i] & ~pSims1[i]);
+    }
+    else // if ( !fCompl0 && !fCompl1 )
+    {
+        if ( fCompl )
+            for ( i = 0; i < p->nWordsFrame; i++ )
+                pSims[i] = ~(pSims0[i] & pSims1[i]);
+        else
+            for ( i = 0; i < p->nWordsFrame; i++ )
+                pSims[i] = (pSims0[i] & pSims1[i]);
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_SmlNodesCompareInFrame( Fra_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int iFrame0, int iFrame1 )
+{
+    unsigned * pSims0, * pSims1;
+    int i;
+    assert( !Aig_IsComplement(pObj0) );
+    assert( !Aig_IsComplement(pObj1) );
+    assert( iFrame0 == 0 || p->nWordsFrame < p->nWordsTotal );
+    assert( iFrame1 == 0 || p->nWordsFrame < p->nWordsTotal );
+    // get hold of the simulation information
+    pSims0  = Fra_ObjSim(p, pObj0->Id) + p->nWordsFrame * iFrame0;
+    pSims1  = Fra_ObjSim(p, pObj1->Id) + p->nWordsFrame * iFrame1;
+    // compare
+    for ( i = 0; i < p->nWordsFrame; i++ )
+        if ( pSims0[i] != pSims1[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SmlNodeCopyFanin( Fra_Sml_t * p, Aig_Obj_t * pObj, int iFrame )
+{
+    unsigned * pSims, * pSims0;
+    int fCompl, fCompl0, i;
+    assert( !Aig_IsComplement(pObj) );
+    assert( Aig_ObjIsCo(pObj) );
+    assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal );
+    // get hold of the simulation information
+    pSims  = Fra_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame;
+    pSims0 = Fra_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame;
+    // get complemented attributes of the children using their random info
+    fCompl  = pObj->fPhase;
+    fCompl0 = Aig_ObjPhaseReal(Aig_ObjChild0(pObj));
+    // copy information as it is
+//    if ( Aig_ObjFaninC0(pObj) )
+    if ( fCompl0 )
+        for ( i = 0; i < p->nWordsFrame; i++ )
+            pSims[i] = ~pSims0[i];
+    else
+        for ( i = 0; i < p->nWordsFrame; i++ )
+            pSims[i] = pSims0[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SmlNodeTransferNext( Fra_Sml_t * p, Aig_Obj_t * pOut, Aig_Obj_t * pIn, int iFrame )
+{
+    unsigned * pSims0, * pSims1;
+    int i;
+    assert( !Aig_IsComplement(pOut) );
+    assert( !Aig_IsComplement(pIn) );
+    assert( Aig_ObjIsCo(pOut) );
+    assert( Aig_ObjIsCi(pIn) );
+    assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal );
+    // get hold of the simulation information
+    pSims0 = Fra_ObjSim(p, pOut->Id) + p->nWordsFrame * iFrame;
+    pSims1 = Fra_ObjSim(p, pIn->Id) + p->nWordsFrame * (iFrame+1);
+    // copy information as it is
+    for ( i = 0; i < p->nWordsFrame; i++ )
+        pSims1[i] = pSims0[i];
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Check if any of the POs becomes non-constant.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fra_SmlCheckNonConstOutputs( Fra_Sml_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachPoSeq( p->pAig, pObj, i )
+        if ( !Fra_SmlNodeIsZero(p, pObj) )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates AIG manager.]
+
+  Description [Assumes that the PI simulation info is attached.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SmlSimulateOne( Fra_Sml_t * p )
+{
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int f, i;
+    abctime clk;
+clk = Abc_Clock();
+    for ( f = 0; f < p->nFrames; f++ )
+    {
+        // simulate the nodes
+        Aig_ManForEachNode( p->pAig, pObj, i )
+            Fra_SmlNodeSimulate( p, pObj, f );
+        // copy simulation info into outputs
+        Aig_ManForEachPoSeq( p->pAig, pObj, i )
+            Fra_SmlNodeCopyFanin( p, pObj, f );
+        // quit if this is the last timeframe
+        if ( f == p->nFrames - 1 )
+            break;
+        // copy simulation info into outputs
+        Aig_ManForEachLiSeq( p->pAig, pObj, i )
+            Fra_SmlNodeCopyFanin( p, pObj, f );
+        // copy simulation info into the inputs
+        Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i )
+            Fra_SmlNodeTransferNext( p, pObjLi, pObjLo, f );
+    }
+p->timeSim += Abc_Clock() - clk;
+p->nSimRounds++;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulates fraiging manager after finding a counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SmlResimulate( Fra_Man_t * p )
+{
+    int nChanges;
+    abctime clk;
+    Fra_SmlAssignDist1( p->pSml, p->pPatWords );
+    Fra_SmlSimulateOne( p->pSml );
+//    if ( p->pPars->fPatScores )
+//        Fra_CleanPatScores( p );
+    if ( p->pPars->fProve && Fra_SmlCheckOutput(p) )
+        return;
+clk = Abc_Clock();
+    nChanges = Fra_ClassesRefine( p->pCla );
+    nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL );
+    if ( p->pCla->vImps )
+        nChanges += Fra_ImpRefineUsingCex( p, p->pCla->vImps );
+    if ( p->vOneHots )
+        nChanges += Fra_OneHotRefineUsingCex( p, p->vOneHots );
+p->timeRef += Abc_Clock() - clk;
+    if ( !p->pPars->nFramesK && nChanges < 1 )
+        printf( "Error: A counter-example did not refine classes!\n" );
+//    assert( nChanges >= 1 );
+//printf( "Refined classes = %5d.   Changes = %4d.\n", Vec_PtrSize(p->vClasses), nChanges );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs simulation of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SmlSimulate( Fra_Man_t * p, int fInit )
+{
+    int fVerbose = 0;
+    int nChanges, nClasses;
+    abctime clk;
+    assert( !fInit || Aig_ManRegNum(p->pManAig) );
+    // start the classes
+    Fra_SmlInitialize( p->pSml, fInit );
+    Fra_SmlSimulateOne( p->pSml );
+    if ( p->pPars->fProve && Fra_SmlCheckOutput(p) )
+        return;
+    Fra_ClassesPrepare( p->pCla, p->pPars->fLatchCorr, 0 );
+//    Fra_ClassesPrint( p->pCla, 0 );
+if ( fVerbose )
+printf( "Starting classes = %5d.   Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) );
+
+//return;
+
+    // refine classes by walking 0/1 patterns
+    Fra_SmlSavePattern0( p, fInit );
+    Fra_SmlAssignDist1( p->pSml, p->pPatWords );
+    Fra_SmlSimulateOne( p->pSml );
+    if ( p->pPars->fProve && Fra_SmlCheckOutput(p) )
+        return;
+clk = Abc_Clock();
+    nChanges = Fra_ClassesRefine( p->pCla );
+    nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL );
+p->timeRef += Abc_Clock() - clk;
+if ( fVerbose )
+printf( "Refined classes  = %5d.   Changes = %4d.   Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), nChanges, Fra_ClassesCountLits(p->pCla) );
+    Fra_SmlSavePattern1( p, fInit );
+    Fra_SmlAssignDist1( p->pSml, p->pPatWords );
+    Fra_SmlSimulateOne( p->pSml );
+    if ( p->pPars->fProve && Fra_SmlCheckOutput(p) )
+        return;
+clk = Abc_Clock();
+    nChanges = Fra_ClassesRefine( p->pCla );
+    nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL );
+p->timeRef += Abc_Clock() - clk;
+
+if ( fVerbose )
+printf( "Refined classes  = %5d.   Changes = %4d.   Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), nChanges, Fra_ClassesCountLits(p->pCla) );
+    // refine classes by random simulation
+    do {
+        Fra_SmlInitialize( p->pSml, fInit );
+        Fra_SmlSimulateOne( p->pSml );
+        nClasses = Vec_PtrSize(p->pCla->vClasses);
+        if ( p->pPars->fProve && Fra_SmlCheckOutput(p) )
+            return;
+clk = Abc_Clock();
+        nChanges = Fra_ClassesRefine( p->pCla );
+        nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL );
+p->timeRef += Abc_Clock() - clk;
+if ( fVerbose )
+printf( "Refined classes  = %5d.   Changes = %4d.   Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), nChanges, Fra_ClassesCountLits(p->pCla) );
+    } while ( (double)nChanges / nClasses > p->pPars->dSimSatur );
+
+//    if ( p->pPars->fVerbose )
+//    printf( "Consts = %6d. Classes = %6d. Literals = %6d.\n", 
+//        Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) );
+//    Fra_ClassesPrint( p->pCla, 0 );
+}
+ 
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fra_Sml_t * Fra_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame )
+{
+    Fra_Sml_t * p;
+    p = (Fra_Sml_t *)ABC_ALLOC( char, sizeof(Fra_Sml_t) + sizeof(unsigned) * Aig_ManObjNumMax(pAig) * (nPref + nFrames) * nWordsFrame );
+    memset( p, 0, sizeof(Fra_Sml_t) + sizeof(unsigned) * (nPref + nFrames) * nWordsFrame );
+    p->pAig        = pAig;
+    p->nPref       = nPref;
+    p->nFrames     = nPref + nFrames;
+    p->nWordsFrame = nWordsFrame;
+    p->nWordsTotal = (nPref + nFrames) * nWordsFrame;
+    p->nWordsPref  = nPref * nWordsFrame;
+    // constant 1 is initialized to 0 because we store values modulus phase (pObj->fPhase)
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates simulation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SmlStop( Fra_Sml_t * p )
+{
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs simulation of the uninitialized circuit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fra_Sml_t * Fra_SmlSimulateComb( Aig_Man_t * pAig, int nWords, int fCheckMiter )
+{
+    Fra_Sml_t * p;
+    p = Fra_SmlStart( pAig, 0, 1, nWords );
+    Fra_SmlInitialize( p, 0 );
+    Fra_SmlSimulateOne( p );
+    if ( fCheckMiter )
+        p->fNonConstOut = Fra_SmlCheckNonConstOutputs( p );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads simulation patterns from file.]
+
+  Description [Each pattern contains the given number (nInputs) of binary digits.
+  No other symbols (except spaces and line endings) are allowed in the file.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Str_t * Fra_SmlSimulateReadFile( char * pFileName )
+{
+    Vec_Str_t * vRes;
+    FILE * pFile;
+    int c;
+    pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\" with simulation patterns.\n", pFileName );
+        return NULL;
+    }
+    vRes = Vec_StrAlloc( 1000 );
+    while ( (c = fgetc(pFile)) != EOF )
+    {
+        if ( c == '0' || c == '1' )
+            Vec_StrPush( vRes, (char)(c - '0') );
+        else if ( c != ' ' && c != '\r' && c != '\n' && c != '\t' )
+        {
+            printf( "File \"%s\" contains symbol (%c) other than \'0\' or \'1\'.\n", pFileName, (char)c );
+            Vec_StrFreeP( &vRes );
+            break;
+        }
+    }
+    fclose( pFile );
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns simulation patters derived from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SmlInitializeGiven( Fra_Sml_t * p, Vec_Str_t * vSimInfo )
+{
+    Aig_Obj_t * pObj;
+    unsigned * pSims;
+    int i, k, nPats = Vec_StrSize(vSimInfo) / Aig_ManCiNum(p->pAig);
+    int nPatsPadded = p->nWordsTotal * 32;
+    assert( Aig_ManRegNum(p->pAig) == 0 );
+    assert( Vec_StrSize(vSimInfo) % Aig_ManCiNum(p->pAig) == 0 );
+    assert( nPats <= nPatsPadded );
+    Aig_ManForEachCi( p->pAig, pObj, i )
+    {
+        pSims = Fra_ObjSim( p, pObj->Id );
+        // clean data
+        for ( k = 0; k < p->nWordsTotal; k++ )
+            pSims[k] = 0;
+        // load patterns
+        for ( k = 0; k < nPats; k++ )
+            if ( Vec_StrEntry(vSimInfo, k * Aig_ManCiNum(p->pAig) + i) )
+                Abc_InfoSetBit( pSims, k );
+        // pad the remaining bits with the value of the last pattern
+        for ( ; k < nPatsPadded; k++ )
+            if ( Vec_StrEntry(vSimInfo, (nPats-1) * Aig_ManCiNum(p->pAig) + i) )
+                Abc_InfoSetBit( pSims, k );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints output values.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fra_SmlPrintOutputs( Fra_Sml_t * p, int nPatterns )
+{
+    Aig_Obj_t * pObj;
+    unsigned * pSims;
+    int i, k;
+    for ( k = 0; k < nPatterns; k++ )
+    {
+        Aig_ManForEachCo( p->pAig, pObj, i )
+        {
+            pSims = Fra_ObjSim( p, pObj->Id );
+            printf( "%d", Abc_InfoHasBit( pSims, k ) );
+        }
+        printf( "\n" );               ;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns simulation patters derived from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fra_Sml_t * Fra_SmlSimulateCombGiven( Aig_Man_t * pAig, char * pFileName, int fCheckMiter, int fVerbose )
+{
+    Vec_Str_t * vSimInfo;
+    Fra_Sml_t * p;
+    int nPatterns;
+    assert( Aig_ManRegNum(pAig) == 0 );
+    // read comb patterns from file
+    vSimInfo = Fra_SmlSimulateReadFile( pFileName );
+    if ( vSimInfo == NULL )
+        return NULL;
+    if ( Vec_StrSize(vSimInfo) % Aig_ManCiNum(pAig) != 0 )
+    {
+        printf( "File \"%s\": The number of binary digits (%d) is not divisible by the number of primary inputs (%d).\n", 
+            pFileName, Vec_StrSize(vSimInfo), Aig_ManCiNum(pAig) );
+        Vec_StrFree( vSimInfo );
+        return NULL;
+    }
+    p = Fra_SmlStart( pAig, 0, 1, Abc_BitWordNum(Vec_StrSize(vSimInfo) / Aig_ManCiNum(pAig)) );
+    Fra_SmlInitializeGiven( p, vSimInfo );
+    nPatterns = Vec_StrSize(vSimInfo) / Aig_ManCiNum(pAig);
+    Vec_StrFree( vSimInfo );
+    Fra_SmlSimulateOne( p );
+    if ( fCheckMiter )
+        p->fNonConstOut = Fra_SmlCheckNonConstOutputs( p );
+    if ( fVerbose )
+        Fra_SmlPrintOutputs( p, nPatterns );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs simulation of the initialized circuit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fra_Sml_t * Fra_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords, int fCheckMiter )
+{
+    Fra_Sml_t * p;
+    p = Fra_SmlStart( pAig, nPref, nFrames, nWords );
+    Fra_SmlInitialize( p, 1 );
+    Fra_SmlSimulateOne( p );
+    if ( fCheckMiter )
+        p->fNonConstOut = Fra_SmlCheckNonConstOutputs( p );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates sequential counter-example from the simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Fra_SmlGetCounterExample( Fra_Sml_t * p )
+{
+    Abc_Cex_t * pCex;
+    Aig_Obj_t * pObj;
+    unsigned * pSims;
+    int iPo, iFrame, iBit, i, k;
+
+    // make sure the simulation manager has it
+    assert( p->fNonConstOut );
+
+    // find the first output that failed
+    iPo = -1;
+    iBit = -1;
+    iFrame = -1;
+    Aig_ManForEachPoSeq( p->pAig, pObj, iPo )
+    {
+        if ( Fra_SmlNodeIsZero(p, pObj) )
+            continue;
+        pSims = Fra_ObjSim( p, pObj->Id );
+        for ( i = p->nWordsPref; i < p->nWordsTotal; i++ )
+            if ( pSims[i] )
+            {
+                iFrame = i / p->nWordsFrame;
+                iBit = 32 * (i % p->nWordsFrame) + Aig_WordFindFirstBit( pSims[i] );
+                break;
+            }
+        break;
+    }
+    assert( iPo < Aig_ManCoNum(p->pAig)-Aig_ManRegNum(p->pAig) );
+    assert( iFrame < p->nFrames );
+    assert( iBit < 32 * p->nWordsFrame );
+
+    // allocate the counter example
+    pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Aig_ManCiNum(p->pAig) - Aig_ManRegNum(p->pAig), iFrame + 1 );
+    pCex->iPo    = iPo;
+    pCex->iFrame = iFrame;
+
+    // copy the bit data
+    Aig_ManForEachLoSeq( p->pAig, pObj, k )
+    {
+        pSims = Fra_ObjSim( p, pObj->Id );
+        if ( Abc_InfoHasBit( pSims, iBit ) )
+            Abc_InfoSetBit( pCex->pData, k );
+    }
+    for ( i = 0; i <= iFrame; i++ )
+    {
+        Aig_ManForEachPiSeq( p->pAig, pObj, k )
+        {
+            pSims = Fra_ObjSim( p, pObj->Id );
+            if ( Abc_InfoHasBit( pSims, 32 * p->nWordsFrame * i + iBit ) )
+                Abc_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * i + k );
+        }
+    }
+    // verify the counter example
+    if ( !Saig_ManVerifyCex( p->pAig, pCex ) )
+    {
+        printf( "Fra_SmlGetCounterExample(): Counter-example is invalid.\n" );
+        Abc_CexFree( pCex );
+        pCex = NULL;
+    }
+    return pCex;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Generates seq counter-example from the combinational one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Fra_SmlCopyCounterExample( Aig_Man_t * pAig, Aig_Man_t * pFrames, int * pModel )
+{
+    Abc_Cex_t * pCex;
+    Aig_Obj_t * pObj;
+    int i, nFrames, nTruePis, nTruePos, iPo, iFrame;
+    // get the number of frames
+    assert( Aig_ManRegNum(pAig) > 0 );
+    assert( Aig_ManRegNum(pFrames) == 0 );
+    nTruePis = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig);
+    nTruePos = Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig);
+    nFrames = Aig_ManCiNum(pFrames) / nTruePis;
+    assert( nTruePis * nFrames == Aig_ManCiNum(pFrames) );
+    assert( nTruePos * nFrames == Aig_ManCoNum(pFrames) );
+    // find the PO that failed
+    iPo = -1;
+    iFrame = -1;
+    Aig_ManForEachCo( pFrames, pObj, i )
+        if ( pObj->Id == pModel[Aig_ManCiNum(pFrames)] )
+        {
+            iPo = i % nTruePos;
+            iFrame = i / nTruePos;
+            break;
+        }
+    assert( iPo >= 0 );
+    // allocate the counter example
+    pCex = Abc_CexAlloc( Aig_ManRegNum(pAig), nTruePis, iFrame + 1 );
+    pCex->iPo    = iPo;
+    pCex->iFrame = iFrame;
+
+    // copy the bit data
+    for ( i = 0; i < Aig_ManCiNum(pFrames); i++ )
+    {
+        if ( pModel[i] )
+            Abc_InfoSetBit( pCex->pData, pCex->nRegs + i );
+        if ( pCex->nRegs + i == pCex->nBits - 1 )
+            break;
+    }
+
+    // verify the counter example
+    if ( !Saig_ManVerifyCex( pAig, pCex ) )
+    {
+        printf( "Fra_SmlGetCounterExample(): Counter-example is invalid.\n" );
+        Abc_CexFree( pCex );
+        pCex = NULL;
+    }
+    return pCex;
+
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/fra_.c b/abc-build/src/proof/fra/fra_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/fra_.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+  FileName    [fra_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [New FRAIG package.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 30, 2007.]
+
+  Revision    [$Id: fra_.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fra/module.make b/abc-build/src/proof/fra/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fra/module.make
@@ -0,0 +1,17 @@
+SRC +=	src/proof/fra/fraBmc.c \
+	src/proof/fra/fraCec.c \
+	src/proof/fra/fraClass.c \
+	src/proof/fra/fraClau.c \
+	src/proof/fra/fraClaus.c \
+	src/proof/fra/fraCnf.c \
+	src/proof/fra/fraCore.c \
+	src/proof/fra/fraHot.c \
+	src/proof/fra/fraImp.c \
+	src/proof/fra/fraInd.c \
+	src/proof/fra/fraIndVer.c \
+	src/proof/fra/fraLcr.c \
+	src/proof/fra/fraMan.c \
+	src/proof/fra/fraPart.c \
+	src/proof/fra/fraSat.c \
+	src/proof/fra/fraSec.c \
+	src/proof/fra/fraSim.c
diff --git a/abc-build/src/proof/fraig/fraig.h b/abc-build/src/proof/fraig/fraig.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fraig/fraig.h
@@ -0,0 +1,257 @@
+/**CFile****************************************************************
+
+  FileName    [fraig.h]
+
+  PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+  Synopsis    [External declarations of the FRAIG package.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - October 1, 2004]
+
+  Revision    [$Id: fraig.h,v 1.18 2005/07/08 01:01:30 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__sat__fraig__fraig_h
+#define ABC__sat__fraig__fraig_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Fraig_ManStruct_t_         Fraig_Man_t;
+typedef struct Fraig_NodeStruct_t_        Fraig_Node_t;
+typedef struct Fraig_NodeVecStruct_t_     Fraig_NodeVec_t;
+typedef struct Fraig_HashTableStruct_t_   Fraig_HashTable_t;
+typedef struct Fraig_ParamsStruct_t_      Fraig_Params_t;
+typedef struct Fraig_PatternsStruct_t_    Fraig_Patterns_t;
+typedef struct Prove_ParamsStruct_t_      Prove_Params_t;
+
+struct Fraig_ParamsStruct_t_
+{
+    int  nPatsRand;     // the number of words of random simulation info
+    int  nPatsDyna;     // the number of words of dynamic simulation info
+    int  nBTLimit;      // the max number of backtracks to perform
+    int  nSeconds;      // the timeout for the final proof
+    int  fFuncRed;      // performs only one level hashing
+    int  fFeedBack;     // enables solver feedback
+    int  fDist1Pats;    // enables distance-1 patterns
+    int  fDoSparse;     // performs equiv tests for sparse functions 
+    int  fChoicing;     // enables recording structural choices
+    int  fTryProve;     // tries to solve the final miter
+    int  fVerbose;      // the verbosiness flag
+    int  fVerboseP;     // the verbosiness flag (for proof reporting)
+    int  fInternal;     // is set to 1 for internal fraig calls
+    int  nConfLimit;    // the limit on the number of conflicts
+    ABC_INT64_T nInspLimit;  // the limit on the number of inspections
+};
+
+struct Prove_ParamsStruct_t_
+{
+    // general parameters
+    int     fUseFraiging;          // enables fraiging
+    int     fUseRewriting;         // enables rewriting
+    int     fUseBdds;              // enables BDD construction when other methods fail
+    int     fVerbose;              // prints verbose stats
+    // iterations
+    int     nItersMax;             // the number of iterations
+    // mitering 
+    int     nMiteringLimitStart;   // starting mitering limit
+    float   nMiteringLimitMulti;   // multiplicative coefficient to increase the limit in each iteration
+    // rewriting 
+    int     nRewritingLimitStart;  // the number of rewriting iterations
+    float   nRewritingLimitMulti;  // multiplicative coefficient to increase the limit in each iteration
+    // fraiging 
+    int     nFraigingLimitStart;   // starting backtrack(conflict) limit
+    float   nFraigingLimitMulti;   // multiplicative coefficient to increase the limit in each iteration
+    // last-gasp BDD construction
+    int     nBddSizeLimit;         // the number of BDD nodes when construction is aborted
+    int     fBddReorder;           // enables dynamic BDD variable reordering
+    // last-gasp mitering
+    int     nMiteringLimitLast;    // final mitering limit
+    // global SAT solver limits
+    ABC_INT64_T  nTotalBacktrackLimit;  // global limit on the number of backtracks
+    ABC_INT64_T  nTotalInspectLimit;    // global limit on the number of clause inspects
+    // global resources applied
+    ABC_INT64_T  nTotalBacktracksMade;  // the total number of backtracks made
+    ABC_INT64_T  nTotalInspectsMade;    // the total number of inspects made
+};
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+ 
+// macros working with complemented attributes of the nodes
+#define Fraig_IsComplement(p)    (((int)((ABC_PTRUINT_T) (p) & 01)))
+#define Fraig_Regular(p)         ((Fraig_Node_t *)((ABC_PTRUINT_T)(p) & ~01)) 
+#define Fraig_Not(p)             ((Fraig_Node_t *)((ABC_PTRUINT_T)(p) ^ 01)) 
+#define Fraig_NotCond(p,c)       ((Fraig_Node_t *)((ABC_PTRUINT_T)(p) ^ (c)))
+
+// these are currently not used
+#define Fraig_Ref(p)              
+#define Fraig_Deref(p)            
+#define Fraig_RecursiveDeref(p,c)
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== fraigApi.c =============================================================*/
+extern Fraig_NodeVec_t *   Fraig_ManReadVecInputs( Fraig_Man_t * p );
+extern Fraig_NodeVec_t *   Fraig_ManReadVecOutputs( Fraig_Man_t * p );    
+extern Fraig_NodeVec_t *   Fraig_ManReadVecNodes( Fraig_Man_t * p );      
+extern Fraig_Node_t **     Fraig_ManReadInputs ( Fraig_Man_t * p );       
+extern Fraig_Node_t **     Fraig_ManReadOutputs( Fraig_Man_t * p );       
+extern Fraig_Node_t **     Fraig_ManReadNodes( Fraig_Man_t * p );         
+extern int                 Fraig_ManReadInputNum ( Fraig_Man_t * p );     
+extern int                 Fraig_ManReadOutputNum( Fraig_Man_t * p );     
+extern int                 Fraig_ManReadNodeNum( Fraig_Man_t * p );       
+extern Fraig_Node_t *      Fraig_ManReadConst1 ( Fraig_Man_t * p );       
+extern Fraig_Node_t *      Fraig_ManReadIthVar( Fraig_Man_t * p, int i ); 
+extern Fraig_Node_t *      Fraig_ManReadIthNode( Fraig_Man_t * p, int i );
+extern char **             Fraig_ManReadInputNames( Fraig_Man_t * p );    
+extern char **             Fraig_ManReadOutputNames( Fraig_Man_t * p );   
+extern char *              Fraig_ManReadVarsInt( Fraig_Man_t * p );       
+extern char *              Fraig_ManReadSat( Fraig_Man_t * p );           
+extern int                 Fraig_ManReadFuncRed( Fraig_Man_t * p );       
+extern int                 Fraig_ManReadFeedBack( Fraig_Man_t * p );      
+extern int                 Fraig_ManReadDoSparse( Fraig_Man_t * p );      
+extern int                 Fraig_ManReadChoicing( Fraig_Man_t * p );      
+extern int                 Fraig_ManReadVerbose( Fraig_Man_t * p );       
+extern int *               Fraig_ManReadModel( Fraig_Man_t * p );
+extern int                 Fraig_ManReadPatternNumRandom( Fraig_Man_t * p );
+extern int                 Fraig_ManReadPatternNumDynamic( Fraig_Man_t * p );
+extern int                 Fraig_ManReadPatternNumDynamicFiltered( Fraig_Man_t * p );
+extern int                 Fraig_ManReadSatFails( Fraig_Man_t * p );      
+extern int                 Fraig_ManReadConflicts( Fraig_Man_t * p );      
+extern int                 Fraig_ManReadInspects( Fraig_Man_t * p );      
+
+extern void                Fraig_ManSetFuncRed( Fraig_Man_t * p, int fFuncRed );        
+extern void                Fraig_ManSetFeedBack( Fraig_Man_t * p, int fFeedBack );      
+extern void                Fraig_ManSetDoSparse( Fraig_Man_t * p, int fDoSparse );      
+extern void                Fraig_ManSetChoicing( Fraig_Man_t * p, int fChoicing ); 
+extern void                Fraig_ManSetTryProve( Fraig_Man_t * p, int fTryProve );
+extern void                Fraig_ManSetVerbose( Fraig_Man_t * p, int fVerbose );        
+extern void                Fraig_ManSetOutputNames( Fraig_Man_t * p, char ** ppNames ); 
+extern void                Fraig_ManSetInputNames( Fraig_Man_t * p, char ** ppNames );  
+extern void                Fraig_ManSetPo( Fraig_Man_t * p, Fraig_Node_t * pNode );
+
+extern Fraig_Node_t *      Fraig_NodeReadData0( Fraig_Node_t * p );                     
+extern Fraig_Node_t *      Fraig_NodeReadData1( Fraig_Node_t * p );                     
+extern int                 Fraig_NodeReadNum( Fraig_Node_t * p );                       
+extern Fraig_Node_t *      Fraig_NodeReadOne( Fraig_Node_t * p );                       
+extern Fraig_Node_t *      Fraig_NodeReadTwo( Fraig_Node_t * p );                       
+extern Fraig_Node_t *      Fraig_NodeReadNextE( Fraig_Node_t * p );                     
+extern Fraig_Node_t *      Fraig_NodeReadRepr( Fraig_Node_t * p );                      
+extern int                 Fraig_NodeReadNumRefs( Fraig_Node_t * p );                   
+extern int                 Fraig_NodeReadNumFanouts( Fraig_Node_t * p );                
+extern int                 Fraig_NodeReadSimInv( Fraig_Node_t * p );                    
+extern int                 Fraig_NodeReadNumOnes( Fraig_Node_t * p );
+extern unsigned *          Fraig_NodeReadPatternsRandom( Fraig_Node_t * p );
+extern unsigned *          Fraig_NodeReadPatternsDynamic( Fraig_Node_t * p );
+
+extern void                Fraig_NodeSetData0( Fraig_Node_t * p, Fraig_Node_t * pData );
+extern void                Fraig_NodeSetData1( Fraig_Node_t * p, Fraig_Node_t * pData );
+
+extern int                 Fraig_NodeIsConst( Fraig_Node_t * p );
+extern int                 Fraig_NodeIsVar( Fraig_Node_t * p );
+extern int                 Fraig_NodeIsAnd( Fraig_Node_t * p );
+extern int                 Fraig_NodeComparePhase( Fraig_Node_t * p1, Fraig_Node_t * p2 );
+
+extern Fraig_Node_t *      Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 );
+extern Fraig_Node_t *      Fraig_NodeAnd( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 );
+extern Fraig_Node_t *      Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 );
+extern Fraig_Node_t *      Fraig_NodeExor( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 );
+extern Fraig_Node_t *      Fraig_NodeMux( Fraig_Man_t * p, Fraig_Node_t * pNode, Fraig_Node_t * pNodeT, Fraig_Node_t * pNodeE );
+extern void                Fraig_NodeSetChoice( Fraig_Man_t * pMan, Fraig_Node_t * pNodeOld, Fraig_Node_t * pNodeNew );
+
+/*=== fraigMan.c =============================================================*/
+extern void                Prove_ParamsSetDefault( Prove_Params_t * pParams );
+extern void                Fraig_ParamsSetDefault( Fraig_Params_t * pParams );
+extern void                Fraig_ParamsSetDefaultFull( Fraig_Params_t * pParams );
+extern Fraig_Man_t *       Fraig_ManCreate( Fraig_Params_t * pParams );
+extern void                Fraig_ManFree( Fraig_Man_t * pMan );
+extern void                Fraig_ManPrintStats( Fraig_Man_t * p );
+extern Fraig_NodeVec_t *   Fraig_ManGetSimInfo( Fraig_Man_t * p );
+extern int                 Fraig_ManCheckClauseUsingSimInfo( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 );
+extern void                Fraig_ManAddClause( Fraig_Man_t * p, Fraig_Node_t ** ppNodes, int nNodes );
+
+/*=== fraigDfs.c =============================================================*/
+extern Fraig_NodeVec_t *   Fraig_Dfs( Fraig_Man_t * pMan, int fEquiv );
+extern Fraig_NodeVec_t *   Fraig_DfsOne( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fEquiv );
+extern Fraig_NodeVec_t *   Fraig_DfsNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppNodes, int nNodes, int fEquiv );
+extern Fraig_NodeVec_t *   Fraig_DfsReverse( Fraig_Man_t * pMan );
+extern int                 Fraig_CountNodes( Fraig_Man_t * pMan, int fEquiv );
+extern int                 Fraig_CheckTfi( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+extern int                 Fraig_CountLevels( Fraig_Man_t * pMan );
+
+/*=== fraigSat.c =============================================================*/
+extern int                 Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit, int nTimeLimit );
+extern int                 Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit, int nTimeLimit );
+extern void                Fraig_ManProveMiter( Fraig_Man_t * p );
+extern int                 Fraig_ManCheckMiter( Fraig_Man_t * p );
+extern int                 Fraig_ManCheckClauseUsingSat( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit );
+
+/*=== fraigVec.c ===============================================================*/
+extern Fraig_NodeVec_t *   Fraig_NodeVecAlloc( int nCap );
+extern void                Fraig_NodeVecFree( Fraig_NodeVec_t * p );
+extern Fraig_NodeVec_t *   Fraig_NodeVecDup( Fraig_NodeVec_t * p );
+extern Fraig_Node_t **     Fraig_NodeVecReadArray( Fraig_NodeVec_t * p );
+extern int                 Fraig_NodeVecReadSize( Fraig_NodeVec_t * p );
+extern void                Fraig_NodeVecGrow( Fraig_NodeVec_t * p, int nCapMin );
+extern void                Fraig_NodeVecShrink( Fraig_NodeVec_t * p, int nSizeNew );
+extern void                Fraig_NodeVecClear( Fraig_NodeVec_t * p );
+extern void                Fraig_NodeVecPush( Fraig_NodeVec_t * p, Fraig_Node_t * Entry );
+extern int                 Fraig_NodeVecPushUnique( Fraig_NodeVec_t * p, Fraig_Node_t * Entry );
+extern void                Fraig_NodeVecPushOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode );
+extern int                 Fraig_NodeVecPushUniqueOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode );
+extern void                Fraig_NodeVecPushOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode );
+extern int                 Fraig_NodeVecPushUniqueOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode );
+extern Fraig_Node_t *      Fraig_NodeVecPop( Fraig_NodeVec_t * p );
+extern void                Fraig_NodeVecRemove( Fraig_NodeVec_t * p, Fraig_Node_t * Entry );
+extern void                Fraig_NodeVecWriteEntry( Fraig_NodeVec_t * p, int i, Fraig_Node_t * Entry );
+extern Fraig_Node_t *      Fraig_NodeVecReadEntry( Fraig_NodeVec_t * p, int i );
+extern void                Fraig_NodeVecSortByLevel( Fraig_NodeVec_t * p, int fIncreasing );
+extern void                Fraig_NodeVecSortByNumber( Fraig_NodeVec_t * p );
+
+/*=== fraigUtil.c ===============================================================*/
+extern void                Fraig_ManMarkRealFanouts( Fraig_Man_t * p );
+extern int                 Fraig_ManCheckConsistency( Fraig_Man_t * p );
+extern int                 Fraig_GetMaxLevel( Fraig_Man_t * pMan );
+extern void                Fraig_ManReportChoices( Fraig_Man_t * pMan );
+extern void                Fraig_MappingSetChoiceLevels( Fraig_Man_t * pMan, int fMaximum );
+extern Fraig_NodeVec_t *   Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux );
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+ 
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
diff --git a/abc-build/src/proof/fraig/fraigApi.c b/abc-build/src/proof/fraig/fraigApi.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fraig/fraigApi.c
@@ -0,0 +1,299 @@
+/**CFile****************************************************************
+
+  FileName    [fraigApi.c]
+
+  PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+  Synopsis    [Access APIs for the FRAIG manager and node.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - October 1, 2004]
+
+  Revision    [$Id: fraigApi.c,v 1.2 2005/07/08 01:01:30 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Access functions to read the data members of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_ManReadVecInputs( Fraig_Man_t * p )                   { return p->vInputs;            }
+Fraig_NodeVec_t * Fraig_ManReadVecOutputs( Fraig_Man_t * p )                  { return p->vOutputs;           }
+Fraig_NodeVec_t * Fraig_ManReadVecNodes( Fraig_Man_t * p )                    { return p->vNodes;             }
+Fraig_Node_t **   Fraig_ManReadInputs ( Fraig_Man_t * p )                     { return p->vInputs->pArray;    }
+Fraig_Node_t **   Fraig_ManReadOutputs( Fraig_Man_t * p )                     { return p->vOutputs->pArray;   }
+Fraig_Node_t **   Fraig_ManReadNodes( Fraig_Man_t * p )                       { return p->vNodes->pArray;     }
+int               Fraig_ManReadInputNum ( Fraig_Man_t * p )                   { return p->vInputs->nSize;     }
+int               Fraig_ManReadOutputNum( Fraig_Man_t * p )                   { return p->vOutputs->nSize;    }
+int               Fraig_ManReadNodeNum( Fraig_Man_t * p )                     { return p->vNodes->nSize;      }
+Fraig_Node_t *    Fraig_ManReadConst1 ( Fraig_Man_t * p )                     { return p->pConst1;            }
+Fraig_Node_t *    Fraig_ManReadIthNode( Fraig_Man_t * p, int i )              { assert ( i < p->vNodes->nSize  ); return p->vNodes->pArray[i];  }
+char **           Fraig_ManReadInputNames( Fraig_Man_t * p )                  { return p->ppInputNames;       }
+char **           Fraig_ManReadOutputNames( Fraig_Man_t * p )                 { return p->ppOutputNames;      }
+char *            Fraig_ManReadVarsInt( Fraig_Man_t * p )                     { return (char *)p->vVarsInt;   }
+char *            Fraig_ManReadSat( Fraig_Man_t * p )                         { return (char *)p->pSat;       }
+int               Fraig_ManReadFuncRed( Fraig_Man_t * p )                     { return p->fFuncRed;   }
+int               Fraig_ManReadFeedBack( Fraig_Man_t * p )                    { return p->fFeedBack;  }
+int               Fraig_ManReadDoSparse( Fraig_Man_t * p )                    { return p->fDoSparse;  }
+int               Fraig_ManReadChoicing( Fraig_Man_t * p )                    { return p->fChoicing;  }
+int               Fraig_ManReadVerbose( Fraig_Man_t * p )                     { return p->fVerbose;   }
+int *             Fraig_ManReadModel( Fraig_Man_t * p )                       { return p->pModel;     }
+// returns the number of patterns used for random simulation (this number is fixed for the FRAIG run)
+int               Fraig_ManReadPatternNumRandom( Fraig_Man_t * p )            { return p->nWordsRand * 32;  }
+// returns the number of dynamic patterns accumulated at runtime (include SAT solver counter-examples and distance-1 patterns derived from them)
+int               Fraig_ManReadPatternNumDynamic( Fraig_Man_t * p )           { return p->iWordStart * 32;  }
+// returns the number of dynamic patterns proved useful to distinquish some FRAIG nodes (this number is more than 0 after the first garbage collection of patterns)
+int               Fraig_ManReadPatternNumDynamicFiltered( Fraig_Man_t * p )   { return p->iPatsPerm;        }
+// returns the number of times FRAIG package timed out
+int               Fraig_ManReadSatFails( Fraig_Man_t * p )                    { return p->nSatFailsReal;    }      
+// returns the number of conflicts in the SAT solver
+int               Fraig_ManReadConflicts( Fraig_Man_t * p )                   { return p->pSat? Msat_SolverReadBackTracks(p->pSat) : 0; }      
+// returns the number of inspections in the SAT solver
+int               Fraig_ManReadInspects( Fraig_Man_t * p )                    { return p->pSat? Msat_SolverReadInspects(p->pSat) : 0;   }            
+
+/**Function*************************************************************
+
+  Synopsis    [Access functions to set the data members of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void            Fraig_ManSetFuncRed( Fraig_Man_t * p, int fFuncRed )        { p->fFuncRed  = fFuncRed;  }
+void            Fraig_ManSetFeedBack( Fraig_Man_t * p, int fFeedBack )      { p->fFeedBack = fFeedBack; }
+void            Fraig_ManSetDoSparse( Fraig_Man_t * p, int fDoSparse )      { p->fDoSparse = fDoSparse; }
+void            Fraig_ManSetChoicing( Fraig_Man_t * p, int fChoicing )      { p->fChoicing = fChoicing; }
+void            Fraig_ManSetTryProve( Fraig_Man_t * p, int fTryProve )      { p->fTryProve = fTryProve; }
+void            Fraig_ManSetVerbose( Fraig_Man_t * p, int fVerbose )        { p->fVerbose  = fVerbose;  }
+void            Fraig_ManSetOutputNames( Fraig_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames; }
+void            Fraig_ManSetInputNames( Fraig_Man_t * p, char ** ppNames )  { p->ppInputNames  = ppNames; }
+
+/**Function*************************************************************
+
+  Synopsis    [Access functions to read the data members of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Node_t *  Fraig_NodeReadData0( Fraig_Node_t * p )                   { return p->pData0;    }
+Fraig_Node_t *  Fraig_NodeReadData1( Fraig_Node_t * p )                   { return p->pData1;    }
+int             Fraig_NodeReadNum( Fraig_Node_t * p )                     { return p->Num;       }
+Fraig_Node_t *  Fraig_NodeReadOne( Fraig_Node_t * p )                     { assert (!Fraig_IsComplement(p)); return p->p1; }
+Fraig_Node_t *  Fraig_NodeReadTwo( Fraig_Node_t * p )                     { assert (!Fraig_IsComplement(p)); return p->p2; }
+Fraig_Node_t *  Fraig_NodeReadNextE( Fraig_Node_t * p )                   { return p->pNextE;    }
+Fraig_Node_t *  Fraig_NodeReadRepr( Fraig_Node_t * p )                    { return p->pRepr;     }
+int             Fraig_NodeReadNumRefs( Fraig_Node_t * p )                 { return p->nRefs;     }
+int             Fraig_NodeReadNumFanouts( Fraig_Node_t * p )              { return p->nFanouts;  }
+int             Fraig_NodeReadSimInv( Fraig_Node_t * p )                  { return p->fInv;      }
+int             Fraig_NodeReadNumOnes( Fraig_Node_t * p )                 { return p->nOnes;     }
+// returns the pointer to the random simulation patterns (their number is returned by Fraig_ManReadPatternNumRandom)
+// memory pointed to by this and the following procedure is maintained by the FRAIG package and exists as long as the package runs
+unsigned *      Fraig_NodeReadPatternsRandom( Fraig_Node_t * p )          { return p->puSimR;    }
+// returns the pointer to the dynamic simulation patterns (their number is returned by Fraig_ManReadPatternNumDynamic or Fraig_ManReadPatternNumDynamicFiltered)
+// if the number of patterns is not evenly divisible by 32, the patterns beyond the given number contain garbage
+unsigned *      Fraig_NodeReadPatternsDynamic( Fraig_Node_t * p )         { return p->puSimD;    }
+
+/**Function*************************************************************
+
+  Synopsis    [Access functions to set the data members of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void            Fraig_NodeSetData0( Fraig_Node_t * p, Fraig_Node_t * pData )      { p->pData0  = pData;  }
+void            Fraig_NodeSetData1( Fraig_Node_t * p, Fraig_Node_t * pData )      { p->pData1  = pData;  }
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the type of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int             Fraig_NodeIsConst( Fraig_Node_t * p )    {  return (Fraig_Regular(p))->Num   == 0;  }
+int             Fraig_NodeIsVar( Fraig_Node_t * p )      {  return (Fraig_Regular(p))->NumPi >= 0;  }
+int             Fraig_NodeIsAnd( Fraig_Node_t * p )      {  return (Fraig_Regular(p))->NumPi <  0 && (Fraig_Regular(p))->Num > 0;  }
+int             Fraig_NodeComparePhase( Fraig_Node_t * p1, Fraig_Node_t * p2 ) { assert( !Fraig_IsComplement(p1) ); assert( !Fraig_IsComplement(p2) ); return p1->fInv ^ p2->fInv; }
+
+/**Function*************************************************************
+
+  Synopsis    [Returns a new primary input node.]
+
+  Description [If the node with this number does not exist, 
+  create a new PI node with this number.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_ManReadIthVar( Fraig_Man_t * p, int i )
+{
+    int k;
+    if ( i < 0 )
+    {
+        printf( "Requesting a PI with a negative number\n" );
+        return NULL;
+    }
+    // create the PIs to fill in the interval
+    if ( i >= p->vInputs->nSize )
+        for ( k = p->vInputs->nSize; k <= i; k++ )
+            Fraig_NodeCreatePi( p ); 
+    return p->vInputs->pArray[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new PO node.]
+
+  Description [This procedure may take a complemented node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_ManSetPo( Fraig_Man_t * p, Fraig_Node_t * pNode )
+{
+    // internal node may be a PO two times
+    Fraig_Regular(pNode)->fNodePo = 1;
+    Fraig_NodeVecPush( p->vOutputs, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perfoms the AND operation with functional hashing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeAnd( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 )
+{
+    return Fraig_NodeAndCanon( p, p1, p2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perfoms the OR operation with functional hashing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 )
+{
+    return Fraig_Not( Fraig_NodeAndCanon( p, Fraig_Not(p1), Fraig_Not(p2) ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perfoms the EXOR operation with functional hashing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeExor( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 )
+{
+    return Fraig_NodeMux( p, p1, Fraig_Not(p2), p2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perfoms the MUX operation with functional hashing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeMux( Fraig_Man_t * p, Fraig_Node_t * pC, Fraig_Node_t * pT, Fraig_Node_t * pE )
+{
+    Fraig_Node_t * pAnd1, * pAnd2, * pRes;
+    pAnd1 = Fraig_NodeAndCanon( p, pC,          pT );     Fraig_Ref( pAnd1 );
+    pAnd2 = Fraig_NodeAndCanon( p, Fraig_Not(pC), pE );   Fraig_Ref( pAnd2 );
+    pRes  = Fraig_NodeOr( p, pAnd1, pAnd2 ); 
+    Fraig_RecursiveDeref( p, pAnd1 );
+    Fraig_RecursiveDeref( p, pAnd2 );
+    Fraig_Deref( pRes );
+    return pRes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the node to be equivalent to the given one.]
+
+  Description [This procedure is a work-around for the equivalence check.
+  Does not verify the equivalence. Use at the user's risk.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeSetChoice( Fraig_Man_t * pMan, Fraig_Node_t * pNodeOld, Fraig_Node_t * pNodeNew )
+{
+//    assert( pMan->fChoicing );
+    pNodeNew->pNextE = pNodeOld->pNextE;
+    pNodeOld->pNextE = pNodeNew;
+    pNodeNew->pRepr  = pNodeOld;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fraig/fraigCanon.c b/abc-build/src/proof/fraig/fraigCanon.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fraig/fraigCanon.c
@@ -0,0 +1,223 @@
+/**CFile****************************************************************
+
+  FileName    [fraigCanon.c]
+
+  PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+  Synopsis    [AND-node creation and elementary AND-operation.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - October 1, 2004]
+
+  Revision    [$Id: fraigCanon.c,v 1.4 2005/07/08 01:01:31 alanmi Exp $]
+
+***********************************************************************/
+
+#include <limits.h>
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [The internal AND operation for the two FRAIG nodes.]
+
+  Description [This procedure is the core of the FRAIG package, because
+  it performs the two-step canonicization of FRAIG nodes. The first step
+  involves the lookup in the structural hash table (which hashes two ANDs 
+  into a node that has them as fanins, if such a node exists). If the node 
+  is not found in the structural hash table, an attempt is made to find a 
+  functionally equivalent node in another hash table (which hashes the 
+  simulation info into the nodes, which has this simulation info). Some 
+  tricks used on the way are described in the comments to the code and
+  in the paper "FRAIGs: Functionally reduced AND-INV graphs".]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 )
+{
+    Fraig_Node_t * pNodeNew, * pNodeOld, * pNodeRepr;
+    int fUseSatCheck;
+//    int RetValue;
+
+    // check for trivial cases
+    if ( p1 == p2 )
+        return p1;
+    if ( p1 == Fraig_Not(p2) )
+        return Fraig_Not(pMan->pConst1);
+    if ( Fraig_NodeIsConst(p1) )
+    {
+        if ( p1 == pMan->pConst1 )
+            return p2;
+        return Fraig_Not(pMan->pConst1);
+    }
+    if ( Fraig_NodeIsConst(p2) )
+    {
+        if ( p2 == pMan->pConst1 )
+            return p1;
+        return Fraig_Not(pMan->pConst1);
+    }
+/*
+    // check for less trivial cases
+    if ( Fraig_IsComplement(p1) )
+    {
+        if ( RetValue = Fraig_NodeIsInSupergate( Fraig_Regular(p1), p2 ) )
+        {
+            if ( RetValue == -1 )
+                pMan->nImplies0++;
+            else
+                pMan->nImplies1++;
+
+            if ( RetValue == -1 )
+                return p2;
+        }
+    }
+    else
+    {
+        if ( RetValue = Fraig_NodeIsInSupergate( p1, p2 ) )
+        {
+            if ( RetValue == 1 )
+                pMan->nSimplifies1++;
+            else
+                pMan->nSimplifies0++;
+
+            if ( RetValue == 1 )
+                return p1;
+            return Fraig_Not(pMan->pConst1);
+        }
+    }
+ 
+    if ( Fraig_IsComplement(p2) )
+    {
+        if ( RetValue = Fraig_NodeIsInSupergate( Fraig_Regular(p2), p1 ) )
+        {
+            if ( RetValue == -1 )
+                pMan->nImplies0++;
+            else
+                pMan->nImplies1++;
+
+            if ( RetValue == -1 )
+                return p1;
+        }
+    }
+    else
+    {
+        if ( RetValue = Fraig_NodeIsInSupergate( p2, p1 ) )
+        {
+            if ( RetValue == 1 )
+                pMan->nSimplifies1++;
+            else
+                pMan->nSimplifies0++;
+
+            if ( RetValue == 1 )
+                return p2;
+            return Fraig_Not(pMan->pConst1);
+        }
+    }
+*/
+    // perform level-one structural hashing
+    if ( Fraig_HashTableLookupS( pMan, p1, p2, &pNodeNew ) ) // the node with these children is found
+    {
+        // if the existent node is part of the cone of unused logic
+        // (that is logic feeding the node which is equivalent to the given node)
+        // return the canonical representative of this node
+        // determine the phase of the given node, with respect to its canonical form
+        pNodeRepr = Fraig_Regular(pNodeNew)->pRepr;
+        if ( pMan->fFuncRed && pNodeRepr )
+            return Fraig_NotCond( pNodeRepr, Fraig_IsComplement(pNodeNew) ^ Fraig_NodeComparePhase(Fraig_Regular(pNodeNew), pNodeRepr) );
+        // otherwise, the node is itself a canonical representative, return it
+        return pNodeNew;
+    }
+    // the same node is not found, but the new one is created
+
+    // if one level hashing is requested (without functionality hashing), return
+    if ( !pMan->fFuncRed )
+        return pNodeNew;
+
+    // check if the new node is unique using the simulation info
+    if ( pNodeNew->nOnes == 0 || pNodeNew->nOnes == (unsigned)pMan->nWordsRand * 32 )
+    {
+        pMan->nSatZeros++;
+        if ( !pMan->fDoSparse ) // if we do not do sparse functions, skip
+            return pNodeNew;
+        // check the sparse function simulation hash table
+        pNodeOld = Fraig_HashTableLookupF0( pMan, pNodeNew );
+        if ( pNodeOld == NULL ) // the node is unique (it is added to the table)
+            return pNodeNew;
+    }
+    else
+    {
+        // check the simulation hash table
+        pNodeOld = Fraig_HashTableLookupF( pMan, pNodeNew );
+        if ( pNodeOld == NULL ) // the node is unique
+            return pNodeNew;
+    }
+    assert( pNodeOld->pRepr == 0 );
+    // there is another node which looks the same according to simulation
+
+    // use SAT to resolve the ambiguity
+    fUseSatCheck = (pMan->nInspLimit == 0 || Fraig_ManReadInspects(pMan) < pMan->nInspLimit); 
+    if ( fUseSatCheck && Fraig_NodeIsEquivalent( pMan, pNodeOld, pNodeNew, pMan->nBTLimit, 1000000 ) )
+    {
+        // set the node to be equivalent with this node
+        // to prevent loops, only set if the old node is not in the TFI of the new node
+        // the loop may happen in the following case: suppose 
+        // NodeC = AND(NodeA, NodeB) and at the same time NodeA => NodeB
+        // in this case, NodeA and NodeC are functionally equivalent
+        // however, NodeA is a fanin of node NodeC (this leads to the loop)
+        // add the node to the list of equivalent nodes or dereference it
+        if ( pMan->fChoicing && !Fraig_CheckTfi( pMan, pNodeOld, pNodeNew ) )
+        { 
+            // if the old node is not in the TFI of the new node and choicing 
+            // is enabled, add the new node to the list of equivalent ones
+            pNodeNew->pNextE = pNodeOld->pNextE;
+            pNodeOld->pNextE = pNodeNew;
+        }
+        // set the canonical representative of this node
+        pNodeNew->pRepr = pNodeOld;
+        // return the equivalent node
+        return Fraig_NotCond( pNodeOld, Fraig_NodeComparePhase(pNodeOld, pNodeNew) );
+    }
+
+    // now we add another member to this simulation class
+    if ( pNodeNew->nOnes == 0 || pNodeNew->nOnes == (unsigned)pMan->nWordsRand * 32 )
+    {
+        Fraig_Node_t * pNodeTemp;
+        assert( pMan->fDoSparse );
+        pNodeTemp = Fraig_HashTableLookupF0( pMan, pNodeNew );
+//        assert( pNodeTemp == NULL );
+//        Fraig_HashTableInsertF0( pMan, pNodeNew );
+    }
+    else
+    {
+        pNodeNew->pNextD = pNodeOld->pNextD;
+        pNodeOld->pNextD = pNodeNew;
+    }
+    // return the new node
+    assert( pNodeNew->pRepr == 0 );
+    return pNodeNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fraig/fraigChoice.c b/abc-build/src/proof/fraig/fraigChoice.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fraig/fraigChoice.c
@@ -0,0 +1,246 @@
+/**CFile****************************************************************
+
+  FileName    [fraigTrans.c]
+
+  PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+  Synopsis    [Adds the additive and distributive choices to the AIG.]
+
+  Author      [MVSIS Group]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - February 1, 2003.]
+
+  Revision    [$Id: fraigTrans.c,v 1.1 2005/02/28 05:34:34 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Adds choice nodes based on associativity.]
+
+  Description [Make nLimit big AND gates and add all decompositions
+               to the Fraig.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_ManAddChoices( Fraig_Man_t * pMan, int fVerbose, int nLimit )
+{
+//    ProgressBar * pProgress;
+    char Buffer[100];
+    abctime clkTotal = Abc_Clock();
+    int i, nNodesBefore, nNodesAfter, nInputs, nMaxNodes;
+    int /*nMaxLevel,*/ nDistributive;
+    Fraig_Node_t *pNode, *pRepr;
+    Fraig_Node_t *pX, *pA, *pB, *pC, /* *pD,*/ *pN, /* *pQ, *pR,*/ *pT;
+    int fShortCut = 0;
+
+    nDistributive = 0;
+
+//    Fraig_ManSetApprox( pMan, 1 );
+
+    // NO functional reduction
+    if (fShortCut) Fraig_ManSetFuncRed( pMan, 0 );
+
+    // First we mark critical functions i.e. compute those
+    // nodes which lie on the critical path. Note that this
+    // doesn't update the required times on any choice nodes
+    // which are not the representatives
+/*
+    nMaxLevel = Fraig_GetMaxLevel( pMan );
+    for ( i = 0; i < pMan->nOutputs; i++ )
+    {
+        Fraig_SetNodeRequired( pMan, pMan->pOutputs[i], nMaxLevel );
+    }
+*/
+    nNodesBefore = Fraig_ManReadNodeNum( pMan );
+    nInputs      = Fraig_ManReadInputNum( pMan );
+    nMaxNodes    = nInputs + nLimit * ( nNodesBefore - nInputs );
+
+    printf ("Limit = %d, Before = %d\n", nMaxNodes, nNodesBefore );
+
+    if (0) 
+    {
+        char buffer[128];
+        sprintf (buffer, "test" );
+//        Fraig_MappingShow( pMan, buffer );
+    }
+
+//    pProgress = Extra_ProgressBarStart( stdout, nMaxNodes );
+Fraig_ManCheckConsistency( pMan );
+
+    for ( i = nInputs+1; (i < Fraig_ManReadNodeNum( pMan )) 
+            && (nMaxNodes > Fraig_ManReadNodeNum( pMan )); ++i )
+    {
+//        if ( i == nNodesBefore )
+//            break;
+
+        pNode = Fraig_ManReadIthNode( pMan, i );
+        assert ( pNode );
+
+        pRepr = pNode->pRepr ? pNode->pRepr : pNode;
+        //printf ("Slack: %d\n", Fraig_NodeReadSlack( pRepr ));
+        
+        // All the new associative choices we add will have huge slack
+        // since we do not redo timing, and timing doesnt handle choices
+        // well anyway. However every newly added node is a choice of an
+        // existing critical node, so they are considered critical.
+//        if ( (Fraig_NodeReadSlack( pRepr ) > 3) && (i < nNodesBefore)  )     
+//            continue;
+
+//        if ( pNode->pRepr )
+//            continue;
+
+        // Try ((ab)c), x = ab -> (a(bc)) and (b(ac))
+        pX = Fraig_NodeReadOne(pNode);
+        pC = Fraig_NodeReadTwo(pNode);
+        if (Fraig_NodeIsAnd(pX) && !Fraig_IsComplement(pX))
+        {
+            pA = Fraig_NodeReadOne(Fraig_Regular(pX));
+            pB = Fraig_NodeReadTwo(Fraig_Regular(pX));
+
+//            pA = Fraig_NodeGetRepr( pA );
+//            pB = Fraig_NodeGetRepr( pB );
+//            pC = Fraig_NodeGetRepr( pC );
+
+            if (fShortCut) 
+            {
+                pT = Fraig_NodeAnd(pMan, pB, pC);
+                if ( !pT->pRepr )
+                {
+                    pN = Fraig_NodeAnd(pMan, pA, pT);
+//                    Fraig_NodeAddChoice( pMan, pNode, pN );
+                }
+            }
+            else
+                pN = Fraig_NodeAnd(pMan, pA, Fraig_NodeAnd(pMan, pB, pC));
+            // assert ( Fraig_NodesEqual(pN, pNode) );
+
+
+            if (fShortCut) 
+            {
+                pT = Fraig_NodeAnd(pMan, pA, pC);
+                if ( !pT->pRepr )
+                {
+                    pN = Fraig_NodeAnd(pMan, pB, pT);
+//                    Fraig_NodeAddChoice( pMan, pNode, pN );
+                }
+            }
+            else
+                pN = Fraig_NodeAnd(pMan, pB, Fraig_NodeAnd(pMan, pA, pC));
+            // assert ( Fraig_NodesEqual(pN, pNode) );
+        }
+
+
+        // Try (a(bc)), x = bc -> ((ab)c) and ((ac)b)
+        pA = Fraig_NodeReadOne(pNode);
+        pX = Fraig_NodeReadTwo(pNode);
+        if (Fraig_NodeIsAnd(pX) && !Fraig_IsComplement(pX))
+        {
+            pB = Fraig_NodeReadOne(Fraig_Regular(pX));
+            pC = Fraig_NodeReadTwo(Fraig_Regular(pX));
+
+//            pA = Fraig_NodeGetRepr( pA );
+//            pB = Fraig_NodeGetRepr( pB );
+//            pC = Fraig_NodeGetRepr( pC );
+
+            if (fShortCut) 
+            {
+                pT = Fraig_NodeAnd(pMan, pA, pB);
+                if ( !pT->pRepr )
+                {
+                    pN = Fraig_NodeAnd(pMan, pC, pT);
+//                    Fraig_NodeAddChoice( pMan, pNode, pN );
+                }
+            }
+            else
+                pN = Fraig_NodeAnd(pMan, Fraig_NodeAnd(pMan, pA, pB), pC);
+            // assert ( Fraig_NodesEqual(pN, pNode) );
+
+            if (fShortCut) 
+            {
+                pT = Fraig_NodeAnd(pMan, pA, pC);
+                if ( !pT->pRepr )
+                {
+                    pN = Fraig_NodeAnd(pMan, pB, pT);
+//                    Fraig_NodeAddChoice( pMan, pNode, pN );
+                }
+            }
+            else
+                pN = Fraig_NodeAnd(pMan, Fraig_NodeAnd(pMan, pA, pC), pB);
+            // assert ( Fraig_NodesEqual(pN, pNode) );
+        }
+
+
+/*
+        // Try distributive transform
+        pQ = Fraig_NodeReadOne(pNode);
+        pR = Fraig_NodeReadTwo(pNode);
+        if ( (Fraig_IsComplement(pQ) && Fraig_NodeIsAnd(pQ))
+             && (Fraig_IsComplement(pR) && Fraig_NodeIsAnd(pR)) )
+        {
+            pA = Fraig_NodeReadOne(Fraig_Regular(pQ));
+            pB = Fraig_NodeReadTwo(Fraig_Regular(pQ));
+            pC = Fraig_NodeReadOne(Fraig_Regular(pR));
+            pD = Fraig_NodeReadTwo(Fraig_Regular(pR));
+
+            // Now detect the !(xy + xz) pattern, store 
+            // x in pA, y in pB and z in pC and set pD = 0 to indicate
+            // pattern was found
+            assert (pD != 0);
+            if (pA == pC) { pC = pD;                   pD = 0; } 
+            if (pA == pD) {                            pD = 0; } 
+            if (pB == pC) { pB = pA; pA = pC; pC = pD; pD = 0; }
+            if (pB == pD) { pB = pA; pA = pD;          pD = 0; }
+            if (pD == 0)
+            {
+                nDistributive++;
+                pN = Fraig_Not(Fraig_NodeAnd(pMan, pA, 
+                        Fraig_NodeOr(pMan, pB, pC)));
+                if (fShortCut) Fraig_NodeAddChoice( pMan, pNode, pN );
+                // assert ( Fraig_NodesEqual(pN, pNode) );
+            }
+        }
+*/            
+        if ( i % 1000 == 0 )
+        {
+            sprintf( Buffer, "Adding choice %6d...", i - nNodesBefore );
+//            Extra_ProgressBarUpdate( pProgress, i, Buffer );
+        }
+    }
+
+//    Extra_ProgressBarStop( pProgress );
+
+Fraig_ManCheckConsistency( pMan );
+
+    nNodesAfter = Fraig_ManReadNodeNum( pMan );
+    printf ( "Nodes before = %6d. Nodes with associative choices = %6d. Increase = %4.2f %%.\n", 
+            nNodesBefore, nNodesAfter, ((float)(nNodesAfter - nNodesBefore)) * 100.0/(nNodesBefore - nInputs) );
+    printf ( "Distributive = %d\n", nDistributive );
+
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fraig/fraigFanout.c b/abc-build/src/proof/fraig/fraigFanout.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fraig/fraigFanout.c
@@ -0,0 +1,180 @@
+/**CFile****************************************************************
+
+  FileName    [fraigFanout.c]
+
+  PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+  Synopsis    [Procedures to manipulate fanouts of the FRAIG nodes.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - October 1, 2004]
+
+  Revision    [$Id: fraigFanout.c,v 1.5 2005/07/08 01:01:31 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+#ifdef FRAIG_ENABLE_FANOUTS
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Add the fanout to the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeAddFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanout )
+{
+    Fraig_Node_t * pPivot;
+
+    // pFanins is a fanin of pFanout
+    assert( !Fraig_IsComplement(pFanin) );
+    assert( !Fraig_IsComplement(pFanout) );
+    assert( Fraig_Regular(pFanout->p1) == pFanin || Fraig_Regular(pFanout->p2) == pFanin );
+
+    pPivot = pFanin->pFanPivot;
+    if ( pPivot == NULL )
+    {
+        pFanin->pFanPivot = pFanout;
+        return;
+    }
+
+    if ( Fraig_Regular(pPivot->p1) == pFanin )
+    {
+        if ( Fraig_Regular(pFanout->p1) == pFanin )
+        {
+            pFanout->pFanFanin1 = pPivot->pFanFanin1;
+            pPivot->pFanFanin1  = pFanout;
+        }
+        else // if ( Fraig_Regular(pFanout->p2) == pFanin )
+        {
+            pFanout->pFanFanin2 = pPivot->pFanFanin1;
+            pPivot->pFanFanin1  = pFanout;
+        }
+    }
+    else // if ( Fraig_Regular(pPivot->p2) == pFanin )
+    {
+        assert( Fraig_Regular(pPivot->p2) == pFanin );
+        if ( Fraig_Regular(pFanout->p1) == pFanin )
+        {
+            pFanout->pFanFanin1 = pPivot->pFanFanin2;
+            pPivot->pFanFanin2  = pFanout;
+        }
+        else // if ( Fraig_Regular(pFanout->p2) == pFanin )
+        {
+            pFanout->pFanFanin2 = pPivot->pFanFanin2;
+            pPivot->pFanFanin2  = pFanout;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add the fanout to the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeRemoveFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanoutToRemove )
+{
+    Fraig_Node_t * pFanout, * pFanout2, ** ppFanList;
+    // start the linked list of fanouts
+    ppFanList = &pFanin->pFanPivot; 
+    // go through the fanouts
+    Fraig_NodeForEachFanoutSafe( pFanin, pFanout, pFanout2 )
+    {
+        // skip the fanout-to-remove
+        if ( pFanout == pFanoutToRemove )
+            continue;
+        // add useful fanouts to the list
+        *ppFanList = pFanout;
+        ppFanList = Fraig_NodeReadNextFanoutPlace( pFanin, pFanout );
+    }
+    *ppFanList = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers fanout to a different node.]
+
+  Description [Assumes that the other node currently has no fanouts.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeTransferFanout( Fraig_Node_t * pNodeFrom, Fraig_Node_t * pNodeTo )
+{
+    Fraig_Node_t * pFanout;
+    assert( pNodeTo->pFanPivot == NULL );
+    assert( pNodeTo->pFanFanin1 == NULL );
+    assert( pNodeTo->pFanFanin2 == NULL );
+    // go through the fanouts and update their fanins
+    Fraig_NodeForEachFanout( pNodeFrom, pFanout )
+    {
+        if ( Fraig_Regular(pFanout->p1) == pNodeFrom )
+            pFanout->p1 = Fraig_NotCond( pNodeTo, Fraig_IsComplement(pFanout->p1) );
+        else if ( Fraig_Regular(pFanout->p2) == pNodeFrom )
+            pFanout->p2 = Fraig_NotCond( pNodeTo, Fraig_IsComplement(pFanout->p2) );            
+    }
+    // move the pointers
+    pNodeTo->pFanPivot  = pNodeFrom->pFanPivot;  
+    pNodeTo->pFanFanin1 = pNodeFrom->pFanFanin1; 
+    pNodeTo->pFanFanin2 = pNodeFrom->pFanFanin2;
+    pNodeFrom->pFanPivot  = NULL; 
+    pNodeFrom->pFanFanin1 = NULL; 
+    pNodeFrom->pFanFanin2 = NULL;  
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of fanouts of a node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeGetFanoutNum( Fraig_Node_t * pNode )
+{
+    Fraig_Node_t * pFanout;
+    int Counter = 0;
+    Fraig_NodeForEachFanout( pNode, pFanout )
+        Counter++;
+    return Counter;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fraig/fraigFeed.c b/abc-build/src/proof/fraig/fraigFeed.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fraig/fraigFeed.c
@@ -0,0 +1,914 @@
+/**CFile****************************************************************
+
+  FileName    [fraigFeed.c]
+
+  PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+  Synopsis    [Procedures to support the solver feedback.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - October 1, 2004]
+
+  Revision    [$Id: fraigFeed.c,v 1.8 2005/07/08 01:01:31 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int   Fraig_FeedBackPrepare( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars );
+static int   Fraig_FeedBackInsert( Fraig_Man_t * p, int nVarsPi );
+static void  Fraig_FeedBackVerify( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+
+static void  Fraig_FeedBackCovering( Fraig_Man_t * p, Msat_IntVec_t * vPats );
+static       Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * pMan );
+static int   Fraig_GetSmallestColumn( int * pHits, int nHits );
+static int   Fraig_GetHittingPattern( unsigned * pSims, int nWords );
+static void  Fraig_CancelCoveredColumns( Fraig_NodeVec_t * vColumns, int * pHits, int iPat );
+static void  Fraig_FeedBackCheckTable( Fraig_Man_t * p );
+static void  Fraig_FeedBackCheckTableF0( Fraig_Man_t * p );
+static void  Fraig_ReallocateSimulationInfo( Fraig_Man_t * p );
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Initializes the feedback information.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_FeedBackInit( Fraig_Man_t * p )
+{
+    p->vCones    = Fraig_NodeVecAlloc( 500 );
+    p->vPatsReal = Msat_IntVecAlloc( 1000 ); 
+    p->pSimsReal = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims );
+    memset( p->pSimsReal, 0, sizeof(unsigned) * p->nWordsDyna );
+    p->pSimsTemp = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims );
+    p->pSimsDiff = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Processes the feedback from teh solver.]
+
+  Description [Array pModel gives the value of each variable in the SAT 
+  solver. Array vVars is the array of integer numbers of variables
+  involves in this conflict.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_FeedBack( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars, Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+    int nVarsPi, nWords;
+    int i;
+    abctime clk = Abc_Clock();
+
+    // get the number of PI vars in the feedback (also sets the PI values)
+    nVarsPi = Fraig_FeedBackPrepare( p, pModel, vVars );
+
+    // set the PI values
+    nWords = Fraig_FeedBackInsert( p, nVarsPi );
+    assert( p->iWordStart + nWords <= p->nWordsDyna );
+
+    // resimulates the words from p->iWordStart to iWordStop
+    for ( i = 1; i < p->vNodes->nSize; i++ )
+        if ( Fraig_NodeIsAnd(p->vNodes->pArray[i]) )
+            Fraig_NodeSimulate( p->vNodes->pArray[i], p->iWordStart, p->iWordStart + nWords, 0 );
+
+    if ( p->fDoSparse )
+        Fraig_TableRehashF0( p, 0 );
+
+    if ( !p->fChoicing )
+    Fraig_FeedBackVerify( p, pOld, pNew );
+
+    // if there is no room left, compress the patterns
+    if ( p->iWordStart + nWords == p->nWordsDyna )
+        p->iWordStart = Fraig_FeedBackCompress( p );
+    else  // otherwise, update the starting word
+        p->iWordStart += nWords;
+
+p->timeFeed += Abc_Clock() - clk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Get the number and values of the PI variables.]
+
+  Description [Returns the number of PI variables involved in this feedback.
+  Fills in the internal presence and value data for the primary inputs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_FeedBackPrepare( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars )
+{
+    Fraig_Node_t * pNode;
+    int i, nVars, nVarsPis, * pVars;
+
+    // clean the presence flag for all PIs
+    for ( i = 0; i < p->vInputs->nSize; i++ )
+    {
+        pNode = p->vInputs->pArray[i];
+        pNode->fFeedUse = 0;
+    }
+
+    // get the variables involved in the feedback
+    nVars = Msat_IntVecReadSize(vVars);
+    pVars = Msat_IntVecReadArray(vVars);
+
+    // set the values for the present variables
+    nVarsPis = 0;
+    for ( i = 0; i < nVars; i++ )
+    {
+        pNode = p->vNodes->pArray[ pVars[i] ];
+        if ( !Fraig_NodeIsVar(pNode) )
+            continue;
+        // set its value
+        pNode->fFeedUse = 1;
+        pNode->fFeedVal = !MSAT_LITSIGN(pModel[pVars[i]]);
+        nVarsPis++;
+    }
+    return nVarsPis;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the new simulation patterns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_FeedBackInsert( Fraig_Man_t * p, int nVarsPi )
+{
+    Fraig_Node_t * pNode;
+    int nWords, iPatFlip, nPatFlipLimit, i, w;
+    int fUseNoPats = 0;
+    int fUse2Pats = 0;
+
+    // get the number of words 
+    if ( fUse2Pats )
+        nWords = FRAIG_NUM_WORDS( 2 * nVarsPi + 1 );
+    else if ( fUseNoPats )
+        nWords = 1;
+    else
+        nWords = FRAIG_NUM_WORDS( nVarsPi + 1 );
+    // update the number of words if they do not fit into the simulation info
+    if ( nWords > p->nWordsDyna - p->iWordStart )
+        nWords = p->nWordsDyna - p->iWordStart; 
+    // determine the bound on the flipping bit
+    nPatFlipLimit = nWords * 32 - 2;
+
+    // mark the real pattern
+    Msat_IntVecPush( p->vPatsReal, p->iWordStart * 32 ); 
+    // record the real pattern
+    Fraig_BitStringSetBit( p->pSimsReal, p->iWordStart * 32 );
+
+    // set the values at the PIs
+    iPatFlip = 1;
+    for ( i = 0; i < p->vInputs->nSize; i++ )
+    {
+        pNode = p->vInputs->pArray[i];
+        for ( w = p->iWordStart; w < p->iWordStart + nWords; w++ )
+            if ( !pNode->fFeedUse )
+                pNode->puSimD[w] = FRAIG_RANDOM_UNSIGNED;
+            else if ( pNode->fFeedVal )
+                pNode->puSimD[w] = FRAIG_FULL;
+            else // if ( !pNode->fFeedVal )
+                pNode->puSimD[w] = 0;
+
+        if ( fUse2Pats )
+        {
+            // flip two patterns
+            if ( pNode->fFeedUse && 2 * iPatFlip < nPatFlipLimit )
+            {
+                Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip - 1 );
+                Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip     );
+                Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip + 1 );
+                iPatFlip++;
+            }
+        }
+        else if ( fUseNoPats )
+        {
+        }
+        else
+        {
+            // flip the diagonal
+            if ( pNode->fFeedUse && iPatFlip < nPatFlipLimit )
+            {
+                Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, iPatFlip );
+                iPatFlip++;
+    //            Extra_PrintBinary( stdout, &pNode->puSimD, 45 ); printf( "\n" );
+            }
+        }
+        // clean the use mask
+        pNode->fFeedUse = 0;
+
+        // add the info to the D hash value of the PIs
+        for ( w = p->iWordStart; w < p->iWordStart + nWords; w++ )
+            pNode->uHashD ^= pNode->puSimD[w] * s_FraigPrimes[w];
+
+    }
+    return nWords;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks that the SAT solver pattern indeed distinquishes the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_FeedBackVerify( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+    int fValue1, fValue2, iPat;
+    iPat   = Msat_IntVecReadEntry( p->vPatsReal, Msat_IntVecReadSize(p->vPatsReal)-1 );
+    fValue1 = (Fraig_BitStringHasBit( pOld->puSimD, iPat ));
+    fValue2 = (Fraig_BitStringHasBit( pNew->puSimD, iPat ));
+/*
+Fraig_PrintNode( p, pOld );
+printf( "\n" );
+Fraig_PrintNode( p, pNew );
+printf( "\n" );
+*/
+//    assert( fValue1 != fValue2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compress the simulation patterns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_FeedBackCompress( Fraig_Man_t * p )
+{
+    unsigned * pSims;
+    unsigned uHash;
+    int i, w, t, nPats, * pPats;
+    int fPerformChecks = (p->nBTLimit == -1);
+
+    // solve the covering problem
+    if ( fPerformChecks )
+    {
+        Fraig_FeedBackCheckTable( p );
+        if ( p->fDoSparse ) 
+            Fraig_FeedBackCheckTableF0( p );
+    }
+
+    // solve the covering problem
+    Fraig_FeedBackCovering( p, p->vPatsReal );
+
+
+    // get the number of additional patterns
+    nPats = Msat_IntVecReadSize( p->vPatsReal );
+    pPats = Msat_IntVecReadArray( p->vPatsReal );
+    // get the new starting word
+    p->iWordStart = FRAIG_NUM_WORDS( p->iPatsPerm + nPats );
+
+    // set the simulation info for the PIs
+    for ( i = 0; i < p->vInputs->nSize; i++ )
+    {
+        // get hold of the simulation info for this PI
+        pSims = p->vInputs->pArray[i]->puSimD;
+        // clean the storage for the new patterns
+        for ( w = p->iWordPerm; w < p->iWordStart; w++ )
+            p->pSimsTemp[w] = 0;
+        // set the patterns
+        for ( t = 0; t < nPats; t++ )
+            if ( Fraig_BitStringHasBit( pSims, pPats[t] ) )
+            {
+                // check if this pattern falls into temporary storage
+                if ( p->iPatsPerm + t < p->iWordPerm * 32 )
+                    Fraig_BitStringSetBit( pSims, p->iPatsPerm + t );
+                else
+                    Fraig_BitStringSetBit( p->pSimsTemp, p->iPatsPerm + t );
+            }
+        // copy the pattern 
+        for ( w = p->iWordPerm; w < p->iWordStart; w++ )
+            pSims[w] = p->pSimsTemp[w];
+        // recompute the hashing info
+        uHash = 0;
+        for ( w = 0; w < p->iWordStart; w++ )
+            uHash ^= pSims[w] * s_FraigPrimes[w];
+        p->vInputs->pArray[i]->uHashD = uHash;
+    }
+
+    // update info about the permanently stored patterns
+    p->iWordPerm = p->iWordStart;
+    p->iPatsPerm += nPats;
+    assert( p->iWordPerm == FRAIG_NUM_WORDS( p->iPatsPerm ) );
+
+    // resimulate and recompute the hash values
+    for ( i = 1; i < p->vNodes->nSize; i++ )
+        if ( Fraig_NodeIsAnd(p->vNodes->pArray[i]) )
+        {
+            p->vNodes->pArray[i]->uHashD = 0;
+            Fraig_NodeSimulate( p->vNodes->pArray[i], 0, p->iWordPerm, 0 );
+        }
+
+    // double-check that the nodes are still distinguished
+    if ( fPerformChecks )
+        Fraig_FeedBackCheckTable( p );
+
+    // rehash the values in the F0 table
+    if ( p->fDoSparse ) 
+    {
+        Fraig_TableRehashF0( p, 0 );
+        if ( fPerformChecks )
+            Fraig_FeedBackCheckTableF0( p );
+    }
+
+    // check if we need to resize the simulation info
+    // if less than FRAIG_WORDS_STORE words are left, reallocate simulation info
+    if ( p->iWordPerm + FRAIG_WORDS_STORE > p->nWordsDyna )
+        Fraig_ReallocateSimulationInfo( p );
+
+    // set the real patterns
+    Msat_IntVecClear( p->vPatsReal );
+    memset( p->pSimsReal, 0, sizeof(unsigned)*p->nWordsDyna );
+    for ( w = 0; w < p->iWordPerm; w++ )
+        p->pSimsReal[w] = FRAIG_FULL;
+    if ( p->iPatsPerm % 32 > 0 )
+        p->pSimsReal[p->iWordPerm-1] = FRAIG_MASK( p->iPatsPerm % 32 );
+//    printf( "The number of permanent words = %d.\n", p->iWordPerm );
+    return p->iWordStart;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the correctness of the functional simulation table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_FeedBackCovering( Fraig_Man_t * p, Msat_IntVec_t * vPats )
+{
+    Fraig_NodeVec_t * vColumns;
+    unsigned * pSims;
+    int * pHits, iPat, iCol, i;
+    int nOnesTotal, nSolStarting;
+    int fVeryVerbose = 0;
+
+    // collect the pairs to be distinguished
+    vColumns = Fraig_FeedBackCoveringStart( p );
+    // collect the number of 1s in each simulation vector
+    nOnesTotal = 0;
+    pHits = ABC_ALLOC( int, vColumns->nSize );
+    for ( i = 0; i < vColumns->nSize; i++ )
+    {
+        pSims = (unsigned *)vColumns->pArray[i];
+        pHits[i] = Fraig_BitStringCountOnes( pSims, p->iWordStart );
+        nOnesTotal += pHits[i];
+//        assert( pHits[i] > 0 );
+    }
+ 
+    // go through the patterns
+    nSolStarting = Msat_IntVecReadSize(vPats);
+    while ( (iCol = Fraig_GetSmallestColumn( pHits, vColumns->nSize )) != -1 )
+    {
+        // find the pattern, which hits this column
+        iPat = Fraig_GetHittingPattern( (unsigned *)vColumns->pArray[iCol], p->iWordStart );
+        // cancel the columns covered by this pattern
+        Fraig_CancelCoveredColumns( vColumns, pHits, iPat );
+        // save the pattern
+        Msat_IntVecPush( vPats, iPat );
+    }
+
+    // free the set of columns
+    for ( i = 0; i < vColumns->nSize; i++ )
+        Fraig_MemFixedEntryRecycle( p->mmSims, (char *)vColumns->pArray[i] );
+
+    // print stats related to the covering problem
+    if ( p->fVerbose && fVeryVerbose )
+    {
+        printf( "%3d\\%3d\\%3d   ",     p->nWordsRand, p->nWordsDyna, p->iWordPerm );
+        printf( "Col (pairs) = %5d.  ", vColumns->nSize );
+        printf( "Row (pats) = %5d.  ",  p->iWordStart * 32 );
+        printf( "Dns = %6.2f %%.  ",    vColumns->nSize==0? 0.0 : 100.0 * nOnesTotal / vColumns->nSize / p->iWordStart / 32 );
+        printf( "Sol = %3d (%3d).  ",   Msat_IntVecReadSize(vPats), nSolStarting );
+        printf( "\n" );
+    }
+    Fraig_NodeVecFree( vColumns );
+    ABC_FREE( pHits );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the correctness of the functional simulation table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * p )
+{
+    Fraig_NodeVec_t * vColumns;
+    Fraig_HashTable_t * pT = p->pTableF;
+    Fraig_Node_t * pEntF, * pEntD;
+    unsigned * pSims;
+    unsigned * pUnsigned1, * pUnsigned2;
+    int i, k, m, w;//, nOnes;
+
+    // start the set of columns
+    vColumns = Fraig_NodeVecAlloc( 100 );
+
+    // go through the pairs of nodes to be distinguished
+    for ( i = 0; i < pT->nBins; i++ )
+    Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF )
+    {
+        p->vCones->nSize = 0;
+        Fraig_TableBinForEachEntryD( pEntF, pEntD )
+            Fraig_NodeVecPush( p->vCones, pEntD );
+        if ( p->vCones->nSize == 1 )
+            continue;
+        //////////////////////////////// bug fix by alanmi, September 14, 2006
+        if ( p->vCones->nSize > 20 ) 
+            continue;
+        ////////////////////////////////
+
+        for ( k = 0; k < p->vCones->nSize; k++ )
+            for ( m = k+1; m < p->vCones->nSize; m++ )
+            {
+                if ( !Fraig_CompareSimInfoUnderMask( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0, p->pSimsReal ) )
+                    continue;
+
+                // primary simulation patterns (counter-examples) cannot distinguish this pair
+                // get memory to store the feasible simulation patterns
+                pSims = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims );
+                // find the pattern that distinguish this column, exept the primary ones
+                pUnsigned1 = p->vCones->pArray[k]->puSimD;
+                pUnsigned2 = p->vCones->pArray[m]->puSimD;
+                for ( w = 0; w < p->iWordStart; w++ )
+                    pSims[w] = (pUnsigned1[w] ^ pUnsigned2[w]) & ~p->pSimsReal[w];
+                // store the pattern
+                Fraig_NodeVecPush( vColumns, (Fraig_Node_t *)pSims );
+//                nOnes = Fraig_BitStringCountOnes(pSims, p->iWordStart);
+//                assert( nOnes > 0 );
+            }      
+    }
+
+    // if the flag is not set, do not consider sparse nodes in p->pTableF0
+    if ( !p->fDoSparse )
+        return vColumns;
+
+    // recalculate their hash values based on p->pSimsReal
+    pT = p->pTableF0;
+    for ( i = 0; i < pT->nBins; i++ )
+    Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF )
+    {
+        pSims = pEntF->puSimD;
+        pEntF->uHashD = 0;
+        for ( w = 0; w < p->iWordStart; w++ )
+            pEntF->uHashD ^= (pSims[w] & p->pSimsReal[w]) * s_FraigPrimes[w];
+    }
+
+    // rehash the table using these values
+    Fraig_TableRehashF0( p, 1 );
+
+    // collect the classes of equivalent node pairs
+    for ( i = 0; i < pT->nBins; i++ )
+    Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF )
+    {
+        p->vCones->nSize = 0;
+        Fraig_TableBinForEachEntryD( pEntF, pEntD )
+            Fraig_NodeVecPush( p->vCones, pEntD );
+        if ( p->vCones->nSize == 1 )
+            continue;
+
+        // primary simulation patterns (counter-examples) cannot distinguish all these pairs
+        for ( k = 0; k < p->vCones->nSize; k++ )
+            for ( m = k+1; m < p->vCones->nSize; m++ )
+            {
+                // get memory to store the feasible simulation patterns
+                pSims = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims );
+                // find the patterns that are not distinquished
+                pUnsigned1 = p->vCones->pArray[k]->puSimD;
+                pUnsigned2 = p->vCones->pArray[m]->puSimD;
+                for ( w = 0; w < p->iWordStart; w++ )
+                    pSims[w] = (pUnsigned1[w] ^ pUnsigned2[w]) & ~p->pSimsReal[w];
+                // store the pattern
+                Fraig_NodeVecPush( vColumns, (Fraig_Node_t *)pSims );
+//                nOnes = Fraig_BitStringCountOnes(pSims, p->iWordStart);
+//                assert( nOnes > 0 );
+            }      
+    }
+    return vColumns;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Selects the column, which has the smallest number of hits.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_GetSmallestColumn( int * pHits, int nHits )
+{
+    int i, iColMin = -1, nHitsMin = 1000000;
+    for ( i = 0; i < nHits; i++ )
+    {
+        // skip covered columns
+        if ( pHits[i] == 0 )
+            continue;
+        // take the column if it can only be covered by one pattern
+        if ( pHits[i] == 1 )
+            return i;
+        // find the column, which requires the smallest number of patterns
+        if ( nHitsMin > pHits[i] )
+        {
+            nHitsMin = pHits[i];
+            iColMin = i;
+        }
+    }
+    return iColMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Select the pattern, which hits this column.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_GetHittingPattern( unsigned * pSims, int nWords )
+{
+    int i, b;
+    for ( i = 0; i < nWords; i++ )
+    {
+        if ( pSims[i] == 0 )
+            continue;
+        for ( b = 0; b < 32; b++ )
+            if ( pSims[i] & (1 << b) )
+                return i * 32 + b;
+    }
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cancel covered patterns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_CancelCoveredColumns( Fraig_NodeVec_t * vColumns, int * pHits, int iPat )
+{
+    unsigned * pSims;
+    int i;
+    for ( i = 0; i < vColumns->nSize; i++ )
+    {
+        pSims = (unsigned *)vColumns->pArray[i];
+        if ( Fraig_BitStringHasBit( pSims, iPat ) )
+            pHits[i] = 0;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the correctness of the functional simulation table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_FeedBackCheckTable( Fraig_Man_t * p )
+{
+    Fraig_HashTable_t * pT = p->pTableF;
+    Fraig_Node_t * pEntF, * pEntD;
+    int i, k, m, nPairs;
+
+    nPairs = 0;
+    for ( i = 0; i < pT->nBins; i++ )
+    Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF )
+    {
+        p->vCones->nSize = 0;
+        Fraig_TableBinForEachEntryD( pEntF, pEntD )
+            Fraig_NodeVecPush( p->vCones, pEntD );
+        if ( p->vCones->nSize == 1 )
+            continue;
+        for ( k = 0; k < p->vCones->nSize; k++ )
+            for ( m = k+1; m < p->vCones->nSize; m++ )
+            {
+                if ( Fraig_CompareSimInfo( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0 ) )
+                    printf( "Nodes %d and %d have the same D simulation info.\n", 
+                        p->vCones->pArray[k]->Num, p->vCones->pArray[m]->Num );
+                nPairs++;
+            }   
+    }
+//    printf( "\nThe total of %d node pairs have been verified.\n", nPairs );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the correctness of the functional simulation table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_FeedBackCheckTableF0( Fraig_Man_t * p )
+{
+    Fraig_HashTable_t * pT = p->pTableF0;
+    Fraig_Node_t * pEntF;
+    int i, k, m, nPairs;
+
+    nPairs = 0;
+    for ( i = 0; i < pT->nBins; i++ )
+    {
+        p->vCones->nSize = 0;
+        Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF )
+            Fraig_NodeVecPush( p->vCones, pEntF );
+        if ( p->vCones->nSize == 1 )
+            continue;
+        for ( k = 0; k < p->vCones->nSize; k++ )
+            for ( m = k+1; m < p->vCones->nSize; m++ )
+            {
+                if ( Fraig_CompareSimInfo( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0 ) )
+                    printf( "Nodes %d and %d have the same D simulation info.\n", 
+                        p->vCones->pArray[k]->Num, p->vCones->pArray[m]->Num );
+                nPairs++;
+            }   
+    }
+//    printf( "\nThe total of %d node pairs have been verified.\n", nPairs );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Doubles the size of simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_ReallocateSimulationInfo( Fraig_Man_t * p )
+{
+    Fraig_MemFixed_t * mmSimsNew;        // new memory manager for simulation info
+    Fraig_Node_t * pNode;
+    unsigned * pSimsNew;
+    unsigned uSignOld;
+    int i;
+
+    // allocate a new memory manager
+    p->nWordsDyna *= 2;
+    mmSimsNew = Fraig_MemFixedStart( sizeof(unsigned) * (p->nWordsRand + p->nWordsDyna) );
+
+    // set the new data for the constant node
+    pNode = p->pConst1;
+    pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew );
+    pNode->puSimD = pNode->puSimR + p->nWordsRand;
+    memset( pNode->puSimR, 0, sizeof(unsigned) * p->nWordsRand );
+    memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna );
+
+    // copy the simulation info of the PIs
+    for ( i = 0; i < p->vInputs->nSize; i++ )
+    {
+        pNode = p->vInputs->pArray[i];
+        // copy the simulation info
+        pSimsNew = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew );
+        memmove( pSimsNew, pNode->puSimR, sizeof(unsigned) * (p->nWordsRand + p->iWordStart) );
+        // attach the new info
+        pNode->puSimR = pSimsNew;
+        pNode->puSimD = pNode->puSimR + p->nWordsRand;
+        // signatures remain without changes
+    }
+
+    // replace the manager to free up some memory
+    Fraig_MemFixedStop( p->mmSims, 0 );
+    p->mmSims = mmSimsNew;
+
+    // resimulate the internal nodes (this should lead to the same signatures)
+    for ( i = 1; i < p->vNodes->nSize; i++ )
+    {
+        pNode = p->vNodes->pArray[i];
+        if ( !Fraig_NodeIsAnd(pNode) )
+            continue;
+        // allocate memory for the simulation info
+        pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew );
+        pNode->puSimD = pNode->puSimR + p->nWordsRand;
+        // derive random simulation info
+        uSignOld = pNode->uHashR;
+        pNode->uHashR = 0;
+        Fraig_NodeSimulate( pNode, 0, p->nWordsRand, 1 );
+        assert( uSignOld == pNode->uHashR );
+        // derive dynamic simulation info
+        uSignOld = pNode->uHashD;
+        pNode->uHashD = 0;
+        Fraig_NodeSimulate( pNode, 0, p->iWordStart, 0 );
+        assert( uSignOld == pNode->uHashD );
+    }
+
+    // realloc temporary storage
+    p->pSimsReal = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew );
+    memset( p->pSimsReal, 0, sizeof(unsigned) * p->nWordsDyna );
+    p->pSimsTemp = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew );
+    p->pSimsDiff = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Generated trivial counter example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Fraig_ManAllocCounterExample( Fraig_Man_t * p )
+{
+    int * pModel;
+    pModel = ABC_ALLOC( int, p->vInputs->nSize );
+    memset( pModel, 0, sizeof(int) * p->vInputs->nSize );
+    return pModel;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Saves the counter example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_ManSimulateBitNode_rec( Fraig_Man_t * p, Fraig_Node_t * pNode )
+{
+    int Value0, Value1;
+    if ( Fraig_NodeIsTravIdCurrent( p, pNode ) )
+        return pNode->fMark3;
+    Fraig_NodeSetTravIdCurrent( p, pNode );
+    Value0 = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode->p1) );
+    Value1 = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode->p2) );
+    Value0 ^= Fraig_IsComplement(pNode->p1);
+    Value1 ^= Fraig_IsComplement(pNode->p2);
+    pNode->fMark3 = Value0 & Value1;
+    return pNode->fMark3;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one bit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_ManSimulateBitNode( Fraig_Man_t * p, Fraig_Node_t * pNode, int * pModel )
+{
+    int fCompl, RetValue, i;
+    // set the PI values
+    Fraig_ManIncrementTravId( p );
+    for ( i = 0; i < p->vInputs->nSize; i++ )
+    {
+        Fraig_NodeSetTravIdCurrent( p, p->vInputs->pArray[i] );
+        p->vInputs->pArray[i]->fMark3 = pModel[i];
+    }
+    // perform the traversal
+    fCompl = Fraig_IsComplement(pNode);
+    RetValue = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode) );
+    return fCompl ^ RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Saves the counter example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Fraig_ManSaveCounterExample( Fraig_Man_t * p, Fraig_Node_t * pNode )
+{
+    int * pModel;
+    int iPattern;
+    int i, fCompl;
+
+    // the node can be complemented
+    fCompl = Fraig_IsComplement(pNode);
+    // because we compare with constant 0, p->pConst1 should also be complemented
+    fCompl = !fCompl;
+
+    // derive the model
+    pModel = Fraig_ManAllocCounterExample( p );
+    iPattern = Fraig_FindFirstDiff( p->pConst1, Fraig_Regular(pNode), fCompl, p->nWordsRand, 1 );
+    if ( iPattern >= 0 )
+    {
+        for ( i = 0; i < p->vInputs->nSize; i++ )
+            if ( Fraig_BitStringHasBit( p->vInputs->pArray[i]->puSimR, iPattern ) )
+                pModel[i] = 1;
+/*
+printf( "SAT solver's pattern:\n" );
+for ( i = 0; i < p->vInputs->nSize; i++ )
+    printf( "%d", pModel[i] );
+printf( "\n" );
+*/
+        assert( Fraig_ManSimulateBitNode( p, pNode, pModel ) );
+        return pModel;
+    }
+    iPattern = Fraig_FindFirstDiff( p->pConst1, Fraig_Regular(pNode), fCompl, p->iWordStart, 0 );
+    if ( iPattern >= 0 )
+    {
+        for ( i = 0; i < p->vInputs->nSize; i++ )
+            if ( Fraig_BitStringHasBit( p->vInputs->pArray[i]->puSimD, iPattern ) )
+                pModel[i] = 1;
+/*
+printf( "SAT solver's pattern:\n" );
+for ( i = 0; i < p->vInputs->nSize; i++ )
+    printf( "%d", pModel[i] );
+printf( "\n" );
+*/
+        assert( Fraig_ManSimulateBitNode( p, pNode, pModel ) );
+        return pModel;
+    }
+    ABC_FREE( pModel );
+    return NULL;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fraig/fraigInt.h b/abc-build/src/proof/fraig/fraigInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fraig/fraigInt.h
@@ -0,0 +1,436 @@
+/**CFile****************************************************************
+
+  FileName    [fraigInt.h]
+
+  PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+  Synopsis    [Internal declarations of the FRAIG package.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - October 1, 2004]
+
+  Revision    [$Id: fraigInt.h,v 1.15 2005/07/08 01:01:31 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__sat__fraig__fraigInt_h
+#define ABC__sat__fraig__fraigInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/util/abc_global.h"
+#include "fraig.h"
+#include "sat/msat/msat.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+ 
+/*
+    The AIG node policy:
+    - Each node has its main number (pNode->Num)
+      This is the number of this node in the array of all nodes and its SAT variable number
+    - The PI nodes are stored along with other nodes
+      Additionally, PI nodes have a PI number, by which they are stored in the PI node array
+    - The constant node is has number 0 and is also stored in the array
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+ 
+// enable this macro to support the fanouts
+#define FRAIG_ENABLE_FANOUTS
+#define FRAIG_PATTERNS_RANDOM   2048   // should not be less than 128 and more than 32768 (2^15)
+#define FRAIG_PATTERNS_DYNAMIC  2048   // should not be less than 256 and more than 32768 (2^15)
+#define FRAIG_MAX_PRIMES        1024   // the maximum number of primes used for hashing
+
+// this parameter determines when simulation info is extended
+// it will be extended when the free storage in the dynamic simulation
+// info is less or equal to this number of words (FRAIG_WORDS_STORE)
+// this is done because if the free storage for dynamic simulation info 
+// is not sufficient, computation becomes inefficient 
+#define FRAIG_WORDS_STORE           5   
+
+// the bit masks
+#define FRAIG_MASK(n)             ((~((unsigned)0)) >> (32-(n)))
+#define FRAIG_FULL                 (~((unsigned)0))
+#define FRAIG_NUM_WORDS(n)         (((n)>>5) + (((n)&31) > 0))
+
+// generating random unsigned (#define RAND_MAX 0x7fff)
+//#define FRAIG_RANDOM_UNSIGNED   ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand()))
+#define FRAIG_RANDOM_UNSIGNED  Aig_ManRandom(0)
+
+// macros to get hold of the bits in a bit string
+#define Fraig_BitStringSetBit(p,i)  ((p)[(i)>>5] |= (1<<((i) & 31)))
+#define Fraig_BitStringXorBit(p,i)  ((p)[(i)>>5] ^= (1<<((i) & 31)))
+#define Fraig_BitStringHasBit(p,i) (((p)[(i)>>5]  & (1<<((i) & 31))) > 0)
+
+// macros to get hold of the bits in the support info
+//#define Fraig_NodeSetVarStr(p,i)      (Fraig_Regular(p)->pSuppStr[((i)%FRAIG_SUPP_SIGN)>>5] |= (1<<(((i)%FRAIG_SUPP_SIGN) & 31)))
+//#define Fraig_NodeHasVarStr(p,i)     ((Fraig_Regular(p)->pSuppStr[((i)%FRAIG_SUPP_SIGN)>>5]  & (1<<(((i)%FRAIG_SUPP_SIGN) & 31))) > 0)
+#define Fraig_NodeSetVarStr(p,i)     Fraig_BitStringSetBit(Fraig_Regular(p)->pSuppStr,i)
+#define Fraig_NodeHasVarStr(p,i)     Fraig_BitStringHasBit(Fraig_Regular(p)->pSuppStr,i)
+
+// copied from "extra.h" for stand-aloneness
+#define Fraig_PrintTime(a,t)      printf( "%s = ", (a) ); printf( "%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC) )
+
+#define Fraig_HashKey2(a,b,TSIZE) (((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b) * 12582917) % TSIZE)
+//#define Fraig_HashKey2(a,b,TSIZE) (( ((unsigned)(a)->Num * 19) ^ ((unsigned)(b)->Num * 1999) ) % TSIZE)
+//#define Fraig_HashKey2(a,b,TSIZE) ( ((unsigned)((a)->Num + (b)->Num) * ((a)->Num + (b)->Num + 1) / 2) % TSIZE)
+// the other two hash functions give bad distribution of hash chain lengths (not clear why)
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Fraig_MemFixed_t_    Fraig_MemFixed_t;    
+
+// the mapping manager
+struct Fraig_ManStruct_t_
+{
+    // the AIG nodes
+    Fraig_NodeVec_t *     vInputs;       // the array of primary inputs
+    Fraig_NodeVec_t *     vNodes;        // the array of all nodes, including primary inputs
+    Fraig_NodeVec_t *     vOutputs;      // the array of primary outputs (some internal nodes)
+    Fraig_Node_t *        pConst1;       // the pointer to the constant node (vNodes->pArray[0])
+
+    // info about the original circuit
+    char **               ppInputNames;  // the primary input names
+    char **               ppOutputNames; // the primary output names
+
+    // various hash-tables
+    Fraig_HashTable_t *   pTableS;       // hashing by structure
+    Fraig_HashTable_t *   pTableF;       // hashing by simulation info
+    Fraig_HashTable_t *   pTableF0;      // hashing by simulation info (sparse functions)
+
+    // parameters
+    int                   nWordsRand;    // the number of words of random simulation info
+    int                   nWordsDyna;    // the number of words of dynamic simulation info
+    int                   nBTLimit;      // the max number of backtracks to perform
+    int                   nSeconds;      // the runtime limit for the miter proof
+    int                   fFuncRed;      // performs only one level hashing
+    int                   fFeedBack;     // enables solver feedback
+    int                   fDist1Pats;    // enables solver feedback
+    int                   fDoSparse;     // performs equiv tests for sparse functions 
+    int                   fChoicing;     // enables recording structural choices
+    int                   fTryProve;     // tries to solve the final miter
+    int                   fVerbose;      // the verbosiness flag
+    int                   fVerboseP;     // the verbosiness flag
+    ABC_INT64_T                nInspLimit;    // the inspection limit
+
+    int                   nTravIds;      // the traversal counter
+    int                   nTravIds2;     // the traversal counter
+
+    // info related to the solver feedback
+    int                   iWordStart;    // the first word to use for simulation
+    int                   iWordPerm;     // the number of words stored permanently
+    int                   iPatsPerm;     // the number of patterns stored permanently
+    Fraig_NodeVec_t *     vCones;        // the temporary array of internal variables
+    Msat_IntVec_t *       vPatsReal;     // the array of real pattern numbers
+    unsigned *            pSimsReal;     // used for simulation patterns
+    unsigned *            pSimsDiff;     // used for simulation patterns
+    unsigned *            pSimsTemp;     // used for simulation patterns
+
+    // the support information
+    int                   nSuppWords;
+    unsigned **           pSuppS;
+    unsigned **           pSuppF;
+
+    // the memory managers
+    Fraig_MemFixed_t *    mmNodes;       // the memory manager for nodes
+    Fraig_MemFixed_t *    mmSims;        // the memory manager for simulation info
+
+    // solving the SAT problem
+    Msat_Solver_t *       pSat;          // the SAT solver
+    Msat_IntVec_t *       vProj;         // the temporary array of projection vars 
+    int                   nSatNums;      // the counter of SAT variables
+    int *                 pModel;        // the assignment, which satisfies the miter
+    // these arrays belong to the solver
+    Msat_IntVec_t *       vVarsInt;      // the temporary array of variables
+    Msat_ClauseVec_t *    vAdjacents;    // the temporary storage for connectivity
+    Msat_IntVec_t *       vVarsUsed;     // the array marking vars appearing in the cone
+
+    // various statistic variables
+    int                   nSatCalls;     // the number of times equivalence checking was called
+    int                   nSatProof;     // the number of times a proof was found
+    int                   nSatCounter;   // the number of times a counter example was found
+    int                   nSatFails;     // the number of times the SAT solver failed to complete due to resource limit or prediction
+    int                   nSatFailsReal; // the number of times the SAT solver failed to complete due to resource limit
+
+    int                   nSatCallsImp;  // the number of times equivalence checking was called
+    int                   nSatProofImp;  // the number of times a proof was found
+    int                   nSatCounterImp;// the number of times a counter example was found
+    int                   nSatFailsImp;  // the number of times the SAT solver failed to complete
+
+    int                   nSatZeros;     // the number of times the simulation vector is zero
+    int                   nSatSupps;     // the number of times the support info was useful
+    int                   nRefErrors;    // the number of ref counting errors
+    int                   nImplies;      // the number of implication cases
+    int                   nSatImpls;     // the number of implication SAT calls
+    int                   nVarsClauses;  // the number of variables with clauses
+    int                   nSimplifies0;
+    int                   nSimplifies1;
+    int                   nImplies0;
+    int                   nImplies1;
+
+    // runtime statistics
+    abctime               timeToAig;     // time to transfer to the mapping structure
+    abctime               timeSims;      // time to compute k-feasible cuts
+    abctime               timeTrav;      // time to traverse the network
+    abctime               timeFeed;      // time for solver feedback (recording and resimulating)
+    abctime               timeImply;     // time to analyze implications
+    abctime               timeSat;       // time to compute the truth table for each cut
+    abctime               timeToNet;     // time to transfer back to the network
+    abctime               timeTotal;     // the total mapping time
+    abctime               time1;         // time to perform one task
+    abctime               time2;         // time to perform another task
+    abctime               time3;         // time to perform another task
+    abctime               time4;         // time to perform another task
+};
+
+// the mapping node
+struct Fraig_NodeStruct_t_ 
+{
+    // various numbers associated with the node
+    int                   Num;           // the unique number (SAT var number) of this node 
+    int                   NumPi;         // if the node is a PI, this is its variable number
+    int                   Level;         // the level of the node
+    int                   nRefs;         // the number of references of the node
+    int                   TravId;        // the traversal ID (use to avoid cleaning marks)
+    int                   TravId2;       // the traversal ID (use to avoid cleaning marks)
+
+    // general information about the node
+    unsigned              fInv     :  1; // the mark to show that simulation info is complemented
+    unsigned              fNodePo  :  1; // the mark used for primary outputs
+    unsigned              fClauses :  1; // the clauses for this node are loaded
+    unsigned              fMark0   :  1; // the mark used for traversals
+    unsigned              fMark1   :  1; // the mark used for traversals
+    unsigned              fMark2   :  1; // the mark used for traversals
+    unsigned              fMark3   :  1; // the mark used for traversals
+    unsigned              fFeedUse :  1; // the presence of the variable in the feedback
+    unsigned              fFeedVal :  1; // the value of the variable in the feedback
+    unsigned              fFailTfo :  1; // the node is in the TFO of the failed SAT run
+    unsigned              nFanouts :  2; // the indicator of fanouts (none, one, or many)
+    unsigned              nOnes    : 20; // the number of 1's in the random sim info
+ 
+    // the children of the node
+    Fraig_Node_t *        p1;            // the first child
+    Fraig_Node_t *        p2;            // the second child
+    Fraig_NodeVec_t *     vFanins;       // the fanins of the supergate rooted at this node
+//    Fraig_NodeVec_t *     vFanouts;      // the fanouts of the supergate rooted at this node
+
+    // various linked lists
+    Fraig_Node_t *        pNextS;        // the next node in the structural hash table
+    Fraig_Node_t *        pNextF;        // the next node in the functional (simulation) hash table
+    Fraig_Node_t *        pNextD;        // the next node in the list of nodes based on dynamic simulation
+    Fraig_Node_t *        pNextE;        // the next structural choice (functionally-equivalent node)
+    Fraig_Node_t *        pRepr;         // the canonical functional representative of the node
+
+    // simulation data
+    unsigned              uHashR;        // the hash value for random information
+    unsigned              uHashD;        // the hash value for dynamic information 
+    unsigned *            puSimR;        // the simulation information (random)
+    unsigned *            puSimD;        // the simulation information (dynamic)
+
+    // misc information  
+    Fraig_Node_t *        pData0;        // temporary storage for the corresponding network node
+    Fraig_Node_t *        pData1;        // temporary storage for the corresponding network node
+
+#ifdef FRAIG_ENABLE_FANOUTS
+    // representation of node's fanouts
+    Fraig_Node_t *        pFanPivot;     // the first fanout of this node
+    Fraig_Node_t *        pFanFanin1;    // the next fanout of p1
+    Fraig_Node_t *        pFanFanin2;    // the next fanout of p2
+#endif
+}; 
+
+// the vector of nodes
+struct Fraig_NodeVecStruct_t_
+{
+    int                   nCap;          // the number of allocated entries
+    int                   nSize;         // the number of entries in the array
+    Fraig_Node_t **       pArray;        // the array of nodes
+};
+
+// the hash table 
+struct Fraig_HashTableStruct_t_
+{
+    Fraig_Node_t **       pBins;         // the table bins
+    int                   nBins;         // the size of the table
+    int                   nEntries;      // the total number of entries in the table
+};
+
+// getting hold of the next fanout of the node
+#define Fraig_NodeReadNextFanout( pNode, pFanout )                \
+    ( ( pFanout == NULL )? NULL :                                 \
+        ((Fraig_Regular((pFanout)->p1) == (pNode))?               \
+             (pFanout)->pFanFanin1 : (pFanout)->pFanFanin2) )
+// getting hold of the place where the next fanout will be attached
+#define Fraig_NodeReadNextFanoutPlace( pNode, pFanout )           \
+    ( (Fraig_Regular((pFanout)->p1) == (pNode))?                  \
+         &(pFanout)->pFanFanin1 : &(pFanout)->pFanFanin2 )
+// iterator through the fanouts of the node
+#define Fraig_NodeForEachFanout( pNode, pFanout )                 \
+    for ( pFanout = (pNode)->pFanPivot; pFanout;                  \
+          pFanout = Fraig_NodeReadNextFanout(pNode, pFanout) )
+// safe iterator through the fanouts of the node
+#define Fraig_NodeForEachFanoutSafe( pNode, pFanout, pFanout2 )   \
+    for ( pFanout  = (pNode)->pFanPivot,                          \
+          pFanout2 = Fraig_NodeReadNextFanout(pNode, pFanout);    \
+          pFanout;                                                \
+          pFanout  = pFanout2,                                    \
+          pFanout2 = Fraig_NodeReadNextFanout(pNode, pFanout) )
+
+// iterators through the entries in the linked lists of nodes
+// the list of nodes in the structural hash table
+#define Fraig_TableBinForEachEntryS( pBin, pEnt )                 \
+    for ( pEnt = pBin;                                            \
+          pEnt;                                                   \
+          pEnt = pEnt->pNextS )
+#define Fraig_TableBinForEachEntrySafeS( pBin, pEnt, pEnt2 )      \
+    for ( pEnt = pBin,                                            \
+          pEnt2 = pEnt? pEnt->pNextS: NULL;                       \
+          pEnt;                                                   \
+          pEnt = pEnt2,                                           \
+          pEnt2 = pEnt? pEnt->pNextS: NULL )
+// the list of nodes in the functional (simulation) hash table
+#define Fraig_TableBinForEachEntryF( pBin, pEnt )                 \
+    for ( pEnt = pBin;                                            \
+          pEnt;                                                   \
+          pEnt = pEnt->pNextF )
+#define Fraig_TableBinForEachEntrySafeF( pBin, pEnt, pEnt2 )      \
+    for ( pEnt = pBin,                                            \
+          pEnt2 = pEnt? pEnt->pNextF: NULL;                       \
+          pEnt;                                                   \
+          pEnt = pEnt2,                                           \
+          pEnt2 = pEnt? pEnt->pNextF: NULL )
+// the list of nodes with the same simulation and different functionality
+#define Fraig_TableBinForEachEntryD( pBin, pEnt )                 \
+    for ( pEnt = pBin;                                            \
+          pEnt;                                                   \
+          pEnt = pEnt->pNextD )
+#define Fraig_TableBinForEachEntrySafeD( pBin, pEnt, pEnt2 )      \
+    for ( pEnt = pBin,                                            \
+          pEnt2 = pEnt? pEnt->pNextD: NULL;                       \
+          pEnt;                                                   \
+          pEnt = pEnt2,                                           \
+          pEnt2 = pEnt? pEnt->pNextD: NULL )
+// the list of nodes with the same functionality 
+#define Fraig_TableBinForEachEntryE( pBin, pEnt )                 \
+    for ( pEnt = pBin;                                            \
+          pEnt;                                                   \
+          pEnt = pEnt->pNextE )
+#define Fraig_TableBinForEachEntrySafeE( pBin, pEnt, pEnt2 )      \
+    for ( pEnt = pBin,                                            \
+          pEnt2 = pEnt? pEnt->pNextE: NULL;                       \
+          pEnt;                                                   \
+          pEnt = pEnt2,                                           \
+          pEnt2 = pEnt? pEnt->pNextE: NULL )
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+// random number generator imported from another package
+extern unsigned            Aig_ManRandom( int fReset );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== fraigCanon.c =============================================================*/
+extern Fraig_Node_t *      Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 );
+/*=== fraigFanout.c =============================================================*/
+extern void                Fraig_NodeAddFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanout );
+extern void                Fraig_NodeRemoveFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanoutToRemove );
+extern int                 Fraig_NodeGetFanoutNum( Fraig_Node_t * pNode );
+/*=== fraigFeed.c =============================================================*/
+extern void                Fraig_FeedBackInit( Fraig_Man_t * p );
+extern void                Fraig_FeedBack( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars, Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+extern void                Fraig_FeedBackTest( Fraig_Man_t * p );
+extern int                 Fraig_FeedBackCompress( Fraig_Man_t * p );
+extern int *               Fraig_ManAllocCounterExample( Fraig_Man_t * p );
+extern int *               Fraig_ManSaveCounterExample( Fraig_Man_t * p, Fraig_Node_t * pNode );
+/*=== fraigMan.c =============================================================*/
+extern void                Fraig_ManCreateSolver( Fraig_Man_t * p );
+/*=== fraigMem.c =============================================================*/
+extern Fraig_MemFixed_t *  Fraig_MemFixedStart( int nEntrySize );
+extern void                Fraig_MemFixedStop( Fraig_MemFixed_t * p, int fVerbose );
+extern char *              Fraig_MemFixedEntryFetch( Fraig_MemFixed_t * p );
+extern void                Fraig_MemFixedEntryRecycle( Fraig_MemFixed_t * p, char * pEntry );
+extern void                Fraig_MemFixedRestart( Fraig_MemFixed_t * p );
+extern int                 Fraig_MemFixedReadMemUsage( Fraig_MemFixed_t * p );
+/*=== fraigNode.c =============================================================*/
+extern Fraig_Node_t *      Fraig_NodeCreateConst( Fraig_Man_t * p );
+extern Fraig_Node_t *      Fraig_NodeCreatePi( Fraig_Man_t * p );
+extern Fraig_Node_t *      Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 );
+extern void                Fraig_NodeSimulate( Fraig_Node_t * pNode, int iWordStart, int iWordStop, int fUseRand );
+/*=== fraigPrime.c =============================================================*/
+extern int                 s_FraigPrimes[FRAIG_MAX_PRIMES];
+/*=== fraigSat.c ===============================================================*/
+extern int                 Fraig_NodeIsImplication( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit );
+/*=== fraigTable.c =============================================================*/
+extern Fraig_HashTable_t * Fraig_HashTableCreate( int nSize );
+extern void                Fraig_HashTableFree( Fraig_HashTable_t * p );
+extern int                 Fraig_HashTableLookupS( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2, Fraig_Node_t ** ppNodeRes );
+extern Fraig_Node_t *      Fraig_HashTableLookupF( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+extern Fraig_Node_t *      Fraig_HashTableLookupF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+extern void                Fraig_HashTableInsertF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+extern int                 Fraig_CompareSimInfo( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand );
+extern int                 Fraig_CompareSimInfoUnderMask( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask );
+extern int                 Fraig_FindFirstDiff( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int fCompl, int iWordLast, int fUseRand );
+extern void                Fraig_CollectXors( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask );
+extern void                Fraig_TablePrintStatsS( Fraig_Man_t * pMan );
+extern void                Fraig_TablePrintStatsF( Fraig_Man_t * pMan );
+extern void                Fraig_TablePrintStatsF0( Fraig_Man_t * pMan );
+extern int                 Fraig_TableRehashF0( Fraig_Man_t * pMan, int fLinkEquiv );
+/*=== fraigUtil.c ===============================================================*/
+extern int                 Fraig_NodeCountPis( Msat_IntVec_t * vVars, int nVarsPi );
+extern int                 Fraig_NodeCountSuppVars( Fraig_Man_t * p, Fraig_Node_t * pNode, int fSuppStr );
+extern int                 Fraig_NodesCompareSupps( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+extern int                 Fraig_NodeAndSimpleCase_rec( Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+extern int                 Fraig_NodeIsExorType( Fraig_Node_t * pNode );
+extern void                Fraig_ManSelectBestChoice( Fraig_Man_t * p );
+extern int                 Fraig_BitStringCountOnes( unsigned * pString, int nWords );
+extern void                Fraig_PrintBinary( FILE * pFile, unsigned * pSign, int nBits );
+extern int                 Fraig_NodeIsExorType( Fraig_Node_t * pNode );
+extern int                 Fraig_NodeIsExor( Fraig_Node_t * pNode );
+extern int                 Fraig_NodeIsMuxType( Fraig_Node_t * pNode );
+extern Fraig_Node_t *      Fraig_NodeRecognizeMux( Fraig_Node_t * pNode, Fraig_Node_t ** ppNodeT, Fraig_Node_t ** ppNodeE );
+extern int                 Fraig_ManCountExors( Fraig_Man_t * pMan );
+extern int                 Fraig_ManCountMuxes( Fraig_Man_t * pMan );
+extern int                 Fraig_NodeSimsContained( Fraig_Man_t * pMan, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 );
+extern int                 Fraig_NodeIsInSupergate( Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+extern Fraig_NodeVec_t *   Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux );
+extern int                 Fraig_CountPis( Fraig_Man_t * p, Msat_IntVec_t * vVarNums );
+extern void                Fraig_ManIncrementTravId( Fraig_Man_t * pMan );
+extern void                Fraig_NodeSetTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+extern int                 Fraig_NodeIsTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+extern int                 Fraig_NodeIsTravIdPrevious( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+/*=== fraigVec.c ===============================================================*/
+extern void                Fraig_NodeVecSortByRefCount( Fraig_NodeVec_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/proof/fraig/fraigMan.c b/abc-build/src/proof/fraig/fraigMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fraig/fraigMan.c
@@ -0,0 +1,546 @@
+/**CFile****************************************************************
+
+  FileName    [fraigMan.c]
+
+  PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+  Synopsis    [Implementation of the FRAIG manager.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - October 1, 2004]
+
+  Revision    [$Id: fraigMan.c,v 1.11 2005/07/08 01:01:31 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+abctime timeSelect;
+abctime timeAssign;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the default parameters of the package.]
+
+  Description [This set of parameters is tuned for equivalence checking.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Prove_ParamsSetDefault( Prove_Params_t * pParams )
+{
+    // clean the parameter structure 
+    memset( pParams, 0, sizeof(Prove_Params_t) );
+    // general parameters
+    pParams->fUseFraiging         = 1;       // enables fraiging
+    pParams->fUseRewriting        = 1;       // enables rewriting
+    pParams->fUseBdds             = 0;       // enables BDD construction when other methods fail
+    pParams->fVerbose             = 0;       // prints verbose stats
+    // iterations
+    pParams->nItersMax            = 6;       // the number of iterations
+    // mitering 
+    pParams->nMiteringLimitStart  = 5000;    // starting mitering limit
+    pParams->nMiteringLimitMulti  = 2.0;     // multiplicative coefficient to increase the limit in each iteration
+    // rewriting (currently not used)
+    pParams->nRewritingLimitStart = 3;       // the number of rewriting iterations
+    pParams->nRewritingLimitMulti = 1.0;     // multiplicative coefficient to increase the limit in each iteration
+    // fraiging 
+    pParams->nFraigingLimitStart  = 2;       // starting backtrack(conflict) limit
+    pParams->nFraigingLimitMulti  = 8.0;     // multiplicative coefficient to increase the limit in each iteration
+    // last-gasp BDD construction
+    pParams->nBddSizeLimit        = 1000000; // the number of BDD nodes when construction is aborted
+    pParams->fBddReorder          = 1;       // enables dynamic BDD variable reordering
+    // last-gasp mitering
+//    pParams->nMiteringLimitLast   = 1000000; // final mitering limit
+    pParams->nMiteringLimitLast   = 0;       // final mitering limit
+    // global SAT solver limits
+    pParams->nTotalBacktrackLimit = 0;       // global limit on the number of backtracks
+    pParams->nTotalInspectLimit   = 0;       // global limit on the number of clause inspects
+//    pParams->nTotalInspectLimit   = 100000000;  // global limit on the number of clause inspects
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints out the current values of CEC engine parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Prove_ParamsPrint( Prove_Params_t * pParams )
+{
+    printf( "CEC enging parameters:\n" );
+    printf( "Fraiging enabled: %s\n", pParams->fUseFraiging? "yes":"no" );
+    printf( "Rewriting enabled: %s\n", pParams->fUseRewriting? "yes":"no" );
+    printf( "BDD construction enabled: %s\n", pParams->fUseBdds? "yes":"no" );
+    printf( "Verbose output enabled: %s\n", pParams->fVerbose? "yes":"no" );
+    printf( "Solver iterations: %d\n", pParams->nItersMax );
+    printf( "Starting mitering limit: %d\n", pParams->nMiteringLimitStart );
+    printf( "Multiplicative coeficient for mitering: %.2f\n", pParams->nMiteringLimitMulti );
+    printf( "Starting number of rewriting iterations: %d\n", pParams->nRewritingLimitStart );
+    printf( "Multiplicative coeficient for rewriting: %.2f\n", pParams->nRewritingLimitMulti );
+    printf( "Starting number of conflicts in fraiging: %.2f\n", pParams->nFraigingLimitMulti );
+    printf( "Multiplicative coeficient for fraiging: %.2f\n", pParams->nRewritingLimitMulti );
+    printf( "BDD size limit for bailing out: %d\n", pParams->nBddSizeLimit );
+    printf( "BDD reordering enabled: %s\n", pParams->fBddReorder? "yes":"no" );
+    printf( "Last-gasp mitering limit: %d\n", pParams->nMiteringLimitLast );
+    printf( "Total conflict limit: %d\n", (int)pParams->nTotalBacktrackLimit );
+    printf( "Total inspection limit: %d\n", (int)pParams->nTotalInspectLimit );
+    printf( "Parameter dump complete.\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the default parameters of the package.]
+
+  Description [This set of parameters is tuned for equivalence checking.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_ParamsSetDefault( Fraig_Params_t * pParams )
+{
+    memset( pParams, 0, sizeof(Fraig_Params_t) );
+    pParams->nPatsRand  = FRAIG_PATTERNS_RANDOM;  // the number of words of random simulation info
+    pParams->nPatsDyna  = FRAIG_PATTERNS_DYNAMIC; // the number of words of dynamic simulation info
+    pParams->nBTLimit   = 99;                     // the max number of backtracks to perform
+    pParams->nSeconds   = 20;                     // the max number of seconds to solve the miter
+    pParams->fFuncRed   =  1;                     // performs only one level hashing
+    pParams->fFeedBack  =  1;                     // enables solver feedback
+    pParams->fDist1Pats =  1;                     // enables distance-1 patterns
+    pParams->fDoSparse  =  0;                     // performs equiv tests for sparse functions 
+    pParams->fChoicing  =  0;                     // enables recording structural choices
+    pParams->fTryProve  =  1;                     // tries to solve the final miter
+    pParams->fVerbose   =  0;                     // the verbosiness flag
+    pParams->fVerboseP  =  0;                     // the verbose flag for reporting the proof
+    pParams->fInternal  =  0;                     // the flag indicates the internal run 
+    pParams->nConfLimit =  0;                     // the limit on the number of conflicts
+    pParams->nInspLimit =  0;                     // the limit on the number of inspections
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the default parameters of the package.]
+
+  Description [This set of parameters is tuned for complete FRAIGing.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_ParamsSetDefaultFull( Fraig_Params_t * pParams )
+{
+    memset( pParams, 0, sizeof(Fraig_Params_t) );
+    pParams->nPatsRand  = FRAIG_PATTERNS_RANDOM;  // the number of words of random simulation info
+    pParams->nPatsDyna  = FRAIG_PATTERNS_DYNAMIC; // the number of words of dynamic simulation info
+    pParams->nBTLimit   = -1;                     // the max number of backtracks to perform
+    pParams->nSeconds   = 20;                     // the max number of seconds to solve the miter
+    pParams->fFuncRed   =  1;                     // performs only one level hashing
+    pParams->fFeedBack  =  1;                     // enables solver feedback
+    pParams->fDist1Pats =  1;                     // enables distance-1 patterns
+    pParams->fDoSparse  =  1;                     // performs equiv tests for sparse functions 
+    pParams->fChoicing  =  0;                     // enables recording structural choices
+    pParams->fTryProve  =  0;                     // tries to solve the final miter
+    pParams->fVerbose   =  0;                     // the verbosiness flag
+    pParams->fVerboseP  =  0;                     // the verbose flag for reporting the proof
+    pParams->fInternal  =  0;                     // the flag indicates the internal run 
+    pParams->nConfLimit =  0;                     // the limit on the number of conflicts
+    pParams->nInspLimit =  0;                     // the limit on the number of inspections
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the new FRAIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams )
+{
+    Fraig_Params_t Params;
+    Fraig_Man_t * p;
+
+    // set the random seed for simulation
+//    srand( 0xFEEDDEAF );
+//    srand( 0xDEADCAFE );
+    Aig_ManRandom( 1 );
+
+    // set parameters for equivalence checking
+    if ( pParams == NULL )
+        Fraig_ParamsSetDefault( pParams = &Params );
+    // adjust the amount of simulation info
+    if ( pParams->nPatsRand < 128 )
+        pParams->nPatsRand = 128;
+    if ( pParams->nPatsRand > 32768 )
+        pParams->nPatsRand = 32768;
+    if ( pParams->nPatsDyna < 128 )
+        pParams->nPatsDyna = 128;
+    if ( pParams->nPatsDyna > 32768 )
+        pParams->nPatsDyna = 32768;
+    // if reduction is not performed, allocate minimum simulation info
+    if ( !pParams->fFuncRed )
+        pParams->nPatsRand = pParams->nPatsDyna = 128;
+
+    // start the manager
+    p = ABC_ALLOC( Fraig_Man_t, 1 );
+    memset( p, 0, sizeof(Fraig_Man_t) );
+
+    // set the default parameters
+    p->nWordsRand = FRAIG_NUM_WORDS( pParams->nPatsRand );  // the number of words of random simulation info
+    p->nWordsDyna = FRAIG_NUM_WORDS( pParams->nPatsDyna );  // the number of patterns for dynamic simulation info
+    p->nBTLimit   = pParams->nBTLimit;    // -1 means infinite backtrack limit
+    p->nSeconds   = pParams->nSeconds;    // the timeout for the final miter
+    p->fFuncRed   = pParams->fFuncRed;    // enables functional reduction (otherwise, only one-level hashing is performed)
+    p->fFeedBack  = pParams->fFeedBack;   // enables solver feedback (the use of counter-examples in simulation)
+    p->fDist1Pats = pParams->fDist1Pats;  // enables solver feedback (the use of counter-examples in simulation)
+    p->fDoSparse  = pParams->fDoSparse;   // performs equivalence checking for sparse functions (whose sim-info is 0)
+    p->fChoicing  = pParams->fChoicing;   // disable accumulation of structural choices (keeps only the first choice)
+    p->fTryProve  = pParams->fTryProve;   // disable accumulation of structural choices (keeps only the first choice)
+    p->fVerbose   = pParams->fVerbose;    // disable verbose output
+    p->fVerboseP  = pParams->fVerboseP;   // disable verbose output
+    p->nInspLimit = pParams->nInspLimit;  // the limit on the number of inspections
+
+    // start memory managers
+    p->mmNodes    = Fraig_MemFixedStart( sizeof(Fraig_Node_t) );
+    p->mmSims     = Fraig_MemFixedStart( sizeof(unsigned) * (p->nWordsRand + p->nWordsDyna) );
+    // allocate node arrays
+    p->vInputs    = Fraig_NodeVecAlloc( 1000 );    // the array of primary inputs
+    p->vOutputs   = Fraig_NodeVecAlloc( 1000 );    // the array of primary outputs
+    p->vNodes     = Fraig_NodeVecAlloc( 1000 );    // the array of internal nodes
+    // start the tables
+    p->pTableS    = Fraig_HashTableCreate( 1000 ); // hashing by structure
+    p->pTableF    = Fraig_HashTableCreate( 1000 ); // hashing by function
+    p->pTableF0   = Fraig_HashTableCreate( 1000 ); // hashing by function (for sparse functions)
+    // create the constant node
+    p->pConst1    = Fraig_NodeCreateConst( p );
+    // initialize SAT solver feedback data structures
+    Fraig_FeedBackInit( p );
+    // initialize other variables
+    p->vProj      = Msat_IntVecAlloc( 10 ); 
+    p->nTravIds   = 1;
+    p->nTravIds2  = 1;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the mapping manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_ManFree( Fraig_Man_t * p )
+{
+    int i;
+    if ( p->fVerbose )   
+    {
+        if ( p->fChoicing ) Fraig_ManReportChoices( p );
+        Fraig_ManPrintStats( p );
+//        Fraig_TablePrintStatsS( p );
+//        Fraig_TablePrintStatsF( p );
+//        Fraig_TablePrintStatsF0( p );
+    }
+ 
+    for ( i = 0; i < p->vNodes->nSize; i++ )
+        if ( p->vNodes->pArray[i]->vFanins )
+        {
+            Fraig_NodeVecFree( p->vNodes->pArray[i]->vFanins );
+            p->vNodes->pArray[i]->vFanins = NULL;
+        }
+
+    if ( p->vInputs )    Fraig_NodeVecFree( p->vInputs );
+    if ( p->vNodes )     Fraig_NodeVecFree( p->vNodes );
+    if ( p->vOutputs )   Fraig_NodeVecFree( p->vOutputs );
+
+    if ( p->pTableS )    Fraig_HashTableFree( p->pTableS );
+    if ( p->pTableF )    Fraig_HashTableFree( p->pTableF );
+    if ( p->pTableF0 )   Fraig_HashTableFree( p->pTableF0 );
+
+    if ( p->pSat )       Msat_SolverFree( p->pSat );
+    if ( p->vProj )      Msat_IntVecFree( p->vProj );
+    if ( p->vCones )     Fraig_NodeVecFree( p->vCones );
+    if ( p->vPatsReal )  Msat_IntVecFree( p->vPatsReal );
+    if ( p->pModel )     ABC_FREE( p->pModel );
+
+    Fraig_MemFixedStop( p->mmNodes, 0 );
+    Fraig_MemFixedStop( p->mmSims, 0 );
+
+    if ( p->pSuppS )
+    {
+        ABC_FREE( p->pSuppS[0] );
+        ABC_FREE( p->pSuppS );
+    }
+    if ( p->pSuppF )
+    {
+        ABC_FREE( p->pSuppF[0] );
+        ABC_FREE( p->pSuppF );
+    }
+
+    ABC_FREE( p->ppOutputNames );
+    ABC_FREE( p->ppInputNames );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the SAT solver to run on the two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_ManCreateSolver( Fraig_Man_t * p )
+{
+    extern abctime timeSelect;
+    extern abctime timeAssign;
+    assert( p->pSat == NULL );
+    // allocate data for SAT solving
+    p->pSat       = Msat_SolverAlloc( 500, 1, 1, 1, 1, 0 );
+    p->vVarsInt   = Msat_SolverReadConeVars( p->pSat );   
+    p->vAdjacents = Msat_SolverReadAdjacents( p->pSat );
+    p->vVarsUsed  = Msat_SolverReadVarsUsed( p->pSat );
+    timeSelect = 0;
+    timeAssign = 0;
+}
+
+ 
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the mapping manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_ManPrintStats( Fraig_Man_t * p )
+{
+    double nMemory;
+    nMemory = ((double)(p->vInputs->nSize + p->vNodes->nSize) * 
+        (sizeof(Fraig_Node_t) + sizeof(unsigned)*(p->nWordsRand + p->nWordsDyna) /*+ p->nSuppWords*sizeof(unsigned)*/))/(1<<20);
+    printf( "Words: Random = %d. Dynamic = %d. Used = %d. Memory = %0.2f MB.\n", 
+        p->nWordsRand, p->nWordsDyna, p->iWordPerm, nMemory );
+    printf( "Proof = %d. Counter-example = %d. Fail = %d. FailReal = %d. Zero = %d.\n", 
+        p->nSatProof, p->nSatCounter, p->nSatFails, p->nSatFailsReal, p->nSatZeros );
+    printf( "Nodes: Final = %d. Total = %d. Mux = %d. (Exor = %d.) ClaVars = %d.\n", 
+        Fraig_CountNodes(p,0), p->vNodes->nSize, Fraig_ManCountMuxes(p), Fraig_ManCountExors(p), p->nVarsClauses );
+    if ( p->pSat ) Msat_SolverPrintStats( p->pSat );
+    Fraig_PrintTime( "AIG simulation  ", p->timeSims  );
+    Fraig_PrintTime( "AIG traversal   ", p->timeTrav  );
+    Fraig_PrintTime( "Solver feedback ", p->timeFeed  );
+    Fraig_PrintTime( "SAT solving     ", p->timeSat   );
+    Fraig_PrintTime( "Network update  ", p->timeToNet );
+    Fraig_PrintTime( "TOTAL RUNTIME   ", p->timeTotal );
+    if ( p->time1 > 0 ) { Fraig_PrintTime( "time1", p->time1 ); }
+    if ( p->time2 > 0 ) { Fraig_PrintTime( "time2", p->time2 ); }
+    if ( p->time3 > 0 ) { Fraig_PrintTime( "time3", p->time3 ); }
+    if ( p->time4 > 0 ) { Fraig_PrintTime( "time4", p->time4 ); }
+//    ABC_PRT( "Selection ", timeSelect );
+//    ABC_PRT( "Assignment", timeAssign );
+    fflush( stdout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates simulation information for all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_UtilInfoAlloc( int nSize, int nWords, int fClean )
+{
+    Fraig_NodeVec_t * vInfo;
+    unsigned * pUnsigned;
+    int i;
+    assert( nSize > 0 && nWords > 0 );
+    vInfo = Fraig_NodeVecAlloc( nSize );
+    pUnsigned = ABC_ALLOC( unsigned, nSize * nWords );
+    vInfo->pArray[0] = (Fraig_Node_t *)pUnsigned;
+    if ( fClean )
+        memset( pUnsigned, 0, sizeof(unsigned) * nSize * nWords );
+    for ( i = 1; i < nSize; i++ )
+        vInfo->pArray[i] = (Fraig_Node_t *)(((unsigned *)vInfo->pArray[i-1]) + nWords);
+    vInfo->nSize = nSize;
+    return vInfo;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns simulation info of all nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_ManGetSimInfo( Fraig_Man_t * p )
+{
+    Fraig_NodeVec_t * vInfo;
+    Fraig_Node_t * pNode;
+    unsigned * pUnsigned;
+    int nRandom, nDynamic;
+    int i, k, nWords;
+
+    nRandom  = Fraig_ManReadPatternNumRandom( p );
+    nDynamic = Fraig_ManReadPatternNumDynamic( p );
+    nWords = nRandom / 32 + nDynamic / 32;
+
+    vInfo = Fraig_UtilInfoAlloc( p->vNodes->nSize, nWords, 0 );
+    for ( i = 0; i < p->vNodes->nSize; i++ )
+    {
+        pNode = p->vNodes->pArray[i];
+        assert( i == pNode->Num );
+        pUnsigned = (unsigned *)vInfo->pArray[i];
+        for ( k = 0; k < nRandom / 32; k++ )
+            pUnsigned[k] = pNode->puSimR[k];
+        for ( k = 0; k < nDynamic / 32; k++ )
+            pUnsigned[nRandom / 32 + k] = pNode->puSimD[k];
+    }
+    return vInfo;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if A v B is always true based on the siminfo.]
+
+  Description [A v B is always true iff A' * B' is always false.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_ManCheckClauseUsingSimInfo( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 )
+{
+    int fCompl1, fCompl2, i;
+
+    fCompl1 = 1 ^ Fraig_IsComplement(pNode1) ^ Fraig_Regular(pNode1)->fInv;
+    fCompl2 = 1 ^ Fraig_IsComplement(pNode2) ^ Fraig_Regular(pNode2)->fInv;
+
+    pNode1 = Fraig_Regular(pNode1);
+    pNode2 = Fraig_Regular(pNode2);
+    assert( pNode1 != pNode2 );
+    
+    // check the simulation info
+    if ( fCompl1 && fCompl2 )
+    {
+        for ( i = 0; i < p->nWordsRand; i++ )
+            if ( ~pNode1->puSimR[i] & ~pNode2->puSimR[i] )
+                return 0;
+        for ( i = 0; i < p->iWordStart; i++ )
+            if ( ~pNode1->puSimD[i] & ~pNode2->puSimD[i] )
+                return 0;
+        return 1;
+    }
+    if ( !fCompl1 && fCompl2 )
+    {
+        for ( i = 0; i < p->nWordsRand; i++ )
+            if ( pNode1->puSimR[i] & ~pNode2->puSimR[i] )
+                return 0;
+        for ( i = 0; i < p->iWordStart; i++ )
+            if ( pNode1->puSimD[i] & ~pNode2->puSimD[i] )
+                return 0;
+        return 1;
+    }
+    if ( fCompl1 && !fCompl2 )
+    {
+        for ( i = 0; i < p->nWordsRand; i++ )
+            if ( ~pNode1->puSimR[i] & pNode2->puSimR[i] )
+                return 0;
+        for ( i = 0; i < p->iWordStart; i++ )
+            if ( ~pNode1->puSimD[i] & pNode2->puSimD[i] )
+                return 0;
+        return 1;
+    }
+//    if ( fCompl1 && fCompl2 )
+    {
+        for ( i = 0; i < p->nWordsRand; i++ )
+            if ( pNode1->puSimR[i] & pNode2->puSimR[i] )
+                return 0;
+        for ( i = 0; i < p->iWordStart; i++ )
+            if ( pNode1->puSimD[i] & pNode2->puSimD[i] )
+                return 0;
+        return 1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds clauses to the solver.]
+
+  Description [This procedure is used to add external clauses to the solver.
+  The clauses are given by sets of nodes. Each node stands for one literal.
+  If the node is complemented, the literal is negated.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_ManAddClause( Fraig_Man_t * p, Fraig_Node_t ** ppNodes, int nNodes )
+{
+    Fraig_Node_t * pNode;
+    int i, fComp, RetValue;
+    if ( p->pSat == NULL )
+        Fraig_ManCreateSolver( p );
+    // create four clauses
+    Msat_IntVecClear( p->vProj );
+    for ( i = 0; i < nNodes; i++ )
+    {
+        pNode = Fraig_Regular(ppNodes[i]);
+        fComp = Fraig_IsComplement(ppNodes[i]);
+        Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) );
+//        printf( "%d(%d) ", pNode->Num, fComp );
+    }
+//    printf( "\n" );
+    RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+    assert( RetValue );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fraig/fraigMem.c b/abc-build/src/proof/fraig/fraigMem.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fraig/fraigMem.c
@@ -0,0 +1,251 @@
+/**CFile****************************************************************
+
+  FileName    [fraigMem.c]
+
+  PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+  Synopsis    [Fixed-size-entry memory manager for the FRAIG package.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - October 1, 2004]
+
+  Revision    [$Id: fraigMem.c,v 1.4 2005/07/08 01:01:31 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+struct Fraig_MemFixed_t_
+{
+    // information about individual entries
+    int           nEntrySize;    // the size of one entry
+    int           nEntriesAlloc; // the total number of entries allocated
+    int           nEntriesUsed;  // the number of entries in use
+    int           nEntriesMax;   // the max number of entries in use
+    char *        pEntriesFree;  // the linked list of free entries
+
+    // this is where the memory is stored
+    int           nChunkSize;    // the size of one chunk
+    int           nChunksAlloc;  // the maximum number of memory chunks 
+    int           nChunks;       // the current number of memory chunks 
+    char **       pChunks;       // the allocated memory
+
+    // statistics
+    int           nMemoryUsed;   // memory used in the allocated entries
+    int           nMemoryAlloc;  // memory allocated
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the internal memory manager.]
+
+  Description [Can only work with entry size at least 4 byte long.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_MemFixed_t * Fraig_MemFixedStart( int nEntrySize )
+{
+    Fraig_MemFixed_t * p;
+
+    p = ABC_ALLOC( Fraig_MemFixed_t, 1 );
+    memset( p, 0, sizeof(Fraig_MemFixed_t) );
+
+    p->nEntrySize    = nEntrySize;
+    p->nEntriesAlloc = 0;
+    p->nEntriesUsed  = 0;
+    p->pEntriesFree  = NULL;
+
+    if ( nEntrySize * (1 << 10) < (1<<16) )
+        p->nChunkSize = (1 << 10);
+    else
+        p->nChunkSize = (1<<16) / nEntrySize;
+    if ( p->nChunkSize < 8 )
+        p->nChunkSize = 8;
+
+    p->nChunksAlloc  = 64;
+    p->nChunks       = 0;
+    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
+
+    p->nMemoryUsed   = 0;
+    p->nMemoryAlloc  = 0;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the internal memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_MemFixedStop( Fraig_MemFixed_t * p, int fVerbose )
+{
+    int i;
+    if ( p == NULL )
+        return;
+    if ( fVerbose )
+    {
+        printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n",
+            p->nEntrySize, p->nChunkSize, p->nChunks );
+        printf( "   Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n",
+            p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc );
+    }
+    for ( i = 0; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    ABC_FREE( p->pChunks );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Extracts one entry from the memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Fraig_MemFixedEntryFetch( Fraig_MemFixed_t * p )
+{
+    char * pTemp;
+    int i;
+
+    // check if there are still free entries
+    if ( p->nEntriesUsed == p->nEntriesAlloc )
+    { // need to allocate more entries
+        assert( p->pEntriesFree == NULL );
+        if ( p->nChunks == p->nChunksAlloc )
+        {
+            p->nChunksAlloc *= 2;
+            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
+        }
+        p->pEntriesFree = ABC_ALLOC( char, p->nEntrySize * p->nChunkSize );
+        p->nMemoryAlloc += p->nEntrySize * p->nChunkSize;
+        // transform these entries into a linked list
+        pTemp = p->pEntriesFree;
+        for ( i = 1; i < p->nChunkSize; i++ )
+        {
+            *((char **)pTemp) = pTemp + p->nEntrySize;
+            pTemp += p->nEntrySize;
+        }
+        // set the last link
+        *((char **)pTemp) = NULL;
+        // add the chunk to the chunk storage
+        p->pChunks[ p->nChunks++ ] = p->pEntriesFree;
+        // add to the number of entries allocated
+        p->nEntriesAlloc += p->nChunkSize;
+    }
+    // incrememt the counter of used entries
+    p->nEntriesUsed++;
+    if ( p->nEntriesMax < p->nEntriesUsed )
+        p->nEntriesMax = p->nEntriesUsed;
+    // return the first entry in the free entry list
+    pTemp = p->pEntriesFree;
+    p->pEntriesFree = *((char **)pTemp);
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns one entry into the memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_MemFixedEntryRecycle( Fraig_MemFixed_t * p, char * pEntry )
+{
+    // decrement the counter of used entries
+    p->nEntriesUsed--;
+    // add the entry to the linked list of free entries
+    *((char **)pEntry) = p->pEntriesFree;
+    p->pEntriesFree = pEntry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees all associated memory and resets the manager.]
+
+  Description [Relocates all the memory except the first chunk.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_MemFixedRestart( Fraig_MemFixed_t * p )
+{
+    int i;
+    char * pTemp;
+
+    // deallocate all chunks except the first one
+    for ( i = 1; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    p->nChunks = 1;
+    // transform these entries into a linked list
+    pTemp = p->pChunks[0];
+    for ( i = 1; i < p->nChunkSize; i++ )
+    {
+        *((char **)pTemp) = pTemp + p->nEntrySize;
+        pTemp += p->nEntrySize;
+    }
+    // set the last link
+    *((char **)pTemp) = NULL;
+    // set the free entry list
+    p->pEntriesFree  = p->pChunks[0];
+    // set the correct statistics
+    p->nMemoryAlloc  = p->nEntrySize * p->nChunkSize;
+    p->nMemoryUsed   = 0;
+    p->nEntriesAlloc = p->nChunkSize;
+    p->nEntriesUsed  = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports the memory usage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_MemFixedReadMemUsage( Fraig_MemFixed_t * p )
+{
+    return p->nMemoryAlloc;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fraig/fraigNode.c b/abc-build/src/proof/fraig/fraigNode.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fraig/fraigNode.c
@@ -0,0 +1,319 @@
+/**CFile****************************************************************
+
+  FileName    [fraigNode.c]
+
+  PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+  Synopsis    [Implementation of the FRAIG node.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - October 1, 2004]
+
+  Revision    [$Id: fraigNode.c,v 1.3 2005/07/08 01:01:32 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// returns the complemented attribute of the node
+#define Fraig_NodeIsSimComplement(p) (Fraig_IsComplement(p)? !(Fraig_Regular(p)->fInv) : (p)->fInv)
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the constant 1 node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeCreateConst( Fraig_Man_t * p )
+{
+    Fraig_Node_t * pNode;
+
+    // create the node
+    pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes );
+    memset( pNode, 0, sizeof(Fraig_Node_t) );
+
+    // assign the number and add to the array of nodes
+    pNode->Num   = p->vNodes->nSize;
+    Fraig_NodeVecPush( p->vNodes,  pNode );
+    pNode->NumPi = -1;  // this is not a PI, so its number is -1
+    pNode->Level =  0;  // just like a PI, it has 0 level
+    pNode->nRefs =  1;  // it is a persistent node, which comes referenced
+    pNode->fInv  =  1;  // the simulation info is complemented
+
+    // create the simulation info
+    pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims );
+    pNode->puSimD = pNode->puSimR + p->nWordsRand;
+    memset( pNode->puSimR, 0, sizeof(unsigned) * p->nWordsRand );
+    memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna );
+
+    // count the number of ones in the simulation vector
+    pNode->nOnes = p->nWordsRand * sizeof(unsigned) * 8;
+
+    // insert it into the hash table
+    Fraig_HashTableLookupF0( p, pNode );
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a primary input node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeCreatePi( Fraig_Man_t * p )
+{
+    Fraig_Node_t * pNode, * pNodeRes;
+    int i;
+    abctime clk;
+
+    // create the node
+    pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes );
+    memset( pNode, 0, sizeof(Fraig_Node_t) );
+    pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims );
+    pNode->puSimD = pNode->puSimR + p->nWordsRand;
+    memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna );
+
+    // assign the number and add to the array of nodes
+    pNode->Num   = p->vNodes->nSize;
+    Fraig_NodeVecPush( p->vNodes,  pNode );
+
+    // assign the PI number and add to the array of primary inputs
+    pNode->NumPi = p->vInputs->nSize;   
+    Fraig_NodeVecPush( p->vInputs, pNode );
+
+    pNode->Level =  0;  // PI has 0 level
+    pNode->nRefs =  1;  // it is a persistent node, which comes referenced
+    pNode->fInv  =  0;  // the simulation info of the PI is not complemented
+
+    // derive the simulation info for the new node
+clk = Abc_Clock();
+    // set the random simulation info for the primary input
+    pNode->uHashR = 0;
+    for ( i = 0; i < p->nWordsRand; i++ )
+    {
+        // generate the simulation info
+        pNode->puSimR[i] = FRAIG_RANDOM_UNSIGNED;
+        // for reasons that take very long to explain, it makes sense to have (0000000...) 
+        // pattern in the set (this helps if we need to return the counter-examples)
+        if ( i == 0 )
+            pNode->puSimR[i] <<= 1;
+        // compute the hash key
+        pNode->uHashR ^= pNode->puSimR[i] * s_FraigPrimes[i];
+    }
+    // count the number of ones in the simulation vector
+    pNode->nOnes = Fraig_BitStringCountOnes( pNode->puSimR, p->nWordsRand );
+
+    // set the systematic simulation info for the primary input
+    pNode->uHashD = 0;
+    for ( i = 0; i < p->iWordStart; i++ )
+    {
+        // generate the simulation info
+        pNode->puSimD[i] = FRAIG_RANDOM_UNSIGNED;
+        // compute the hash key
+        pNode->uHashD ^= pNode->puSimD[i] * s_FraigPrimes[i];
+    }
+p->timeSims += Abc_Clock() - clk;
+
+    // insert it into the hash table
+    pNodeRes = Fraig_HashTableLookupF( p, pNode );
+    assert( pNodeRes == NULL );
+    // add to the runtime of simulation
+    return pNode;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new node.]
+
+  Description [This procedure should be called to create the constant
+  node and the PI nodes first.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 )
+{
+    Fraig_Node_t * pNode;
+    abctime clk;
+
+    // create the node
+    pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes );
+    memset( pNode, 0, sizeof(Fraig_Node_t) );
+
+    // assign the children
+    pNode->p1  = p1;  Fraig_Ref(p1);  Fraig_Regular(p1)->nRefs++;
+    pNode->p2  = p2;  Fraig_Ref(p2);  Fraig_Regular(p2)->nRefs++;
+
+    // assign the number and add to the array of nodes
+    pNode->Num = p->vNodes->nSize;
+    Fraig_NodeVecPush( p->vNodes,  pNode );
+
+    // assign the PI number
+    pNode->NumPi = -1;
+
+    // compute the level of this node
+    pNode->Level = 1 + Abc_MaxInt(Fraig_Regular(p1)->Level, Fraig_Regular(p2)->Level);
+    pNode->fInv  = Fraig_NodeIsSimComplement(p1) & Fraig_NodeIsSimComplement(p2);
+    pNode->fFailTfo = Fraig_Regular(p1)->fFailTfo | Fraig_Regular(p2)->fFailTfo;
+
+    // derive the simulation info 
+clk = Abc_Clock();
+    // allocate memory for the simulation info
+    pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims );
+    pNode->puSimD = pNode->puSimR + p->nWordsRand;
+    // derive random simulation info
+    pNode->uHashR = 0;
+    Fraig_NodeSimulate( pNode, 0, p->nWordsRand, 1 );
+    // derive dynamic simulation info
+    pNode->uHashD = 0;
+    Fraig_NodeSimulate( pNode, 0, p->iWordStart, 0 );
+    // count the number of ones in the random simulation info
+    pNode->nOnes = Fraig_BitStringCountOnes( pNode->puSimR, p->nWordsRand );
+    if ( pNode->fInv )
+        pNode->nOnes = p->nWordsRand * 32 - pNode->nOnes;
+    // add to the runtime of simulation
+p->timeSims += Abc_Clock() - clk;
+
+#ifdef FRAIG_ENABLE_FANOUTS
+    // create the fanout info
+    Fraig_NodeAddFaninFanout( Fraig_Regular(p1), pNode );
+    Fraig_NodeAddFaninFanout( Fraig_Regular(p2), pNode );
+#endif
+    return pNode;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates the node.]
+
+  Description [Simulates the random or dynamic simulation info through 
+  the node. Uses phases of the children to determine their real simulation
+  info. Uses phase of the node to determine the way its simulation info 
+  is stored. The resulting info is guaranteed to be 0 for the first pattern.]
+  
+  SideEffects [This procedure modified the hash value of the simulation info.]
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeSimulate( Fraig_Node_t * pNode, int iWordStart, int iWordStop, int fUseRand )
+{
+    unsigned * pSims, * pSims1, * pSims2;
+    unsigned uHash;
+    int fCompl, fCompl1, fCompl2, i;
+
+    assert( !Fraig_IsComplement(pNode) );
+
+    // get hold of the simulation information
+    pSims  = fUseRand? pNode->puSimR                    : pNode->puSimD;
+    pSims1 = fUseRand? Fraig_Regular(pNode->p1)->puSimR : Fraig_Regular(pNode->p1)->puSimD;
+    pSims2 = fUseRand? Fraig_Regular(pNode->p2)->puSimR : Fraig_Regular(pNode->p2)->puSimD;
+
+    // get complemented attributes of the children using their random info
+    fCompl  = pNode->fInv;
+    fCompl1 = Fraig_NodeIsSimComplement(pNode->p1);
+    fCompl2 = Fraig_NodeIsSimComplement(pNode->p2);
+
+    // simulate
+    uHash = 0;
+    if ( fCompl1 && fCompl2 )
+    {
+        if ( fCompl )
+            for ( i = iWordStart; i < iWordStop; i++ )
+            {
+                pSims[i] = (pSims1[i] | pSims2[i]);
+                uHash ^= pSims[i] * s_FraigPrimes[i];
+            }
+        else
+            for ( i = iWordStart; i < iWordStop; i++ )
+            {
+                pSims[i] = ~(pSims1[i] | pSims2[i]);
+                uHash ^= pSims[i] * s_FraigPrimes[i];
+            }
+    }
+    else if ( fCompl1 && !fCompl2 )
+    {
+        if ( fCompl )
+            for ( i = iWordStart; i < iWordStop; i++ )
+            {
+                pSims[i] = (pSims1[i] | ~pSims2[i]);
+                uHash ^= pSims[i] * s_FraigPrimes[i];
+            }
+        else
+            for ( i = iWordStart; i < iWordStop; i++ )
+            {
+                pSims[i] = (~pSims1[i] & pSims2[i]);
+                uHash ^= pSims[i] * s_FraigPrimes[i];
+            }
+    }
+    else if ( !fCompl1 && fCompl2 )
+    {
+        if ( fCompl )
+            for ( i = iWordStart; i < iWordStop; i++ )
+            {
+                pSims[i] = (~pSims1[i] | pSims2[i]);
+                uHash ^= pSims[i] * s_FraigPrimes[i];
+            }
+        else
+            for ( i = iWordStart; i < iWordStop; i++ )
+            {
+                pSims[i] = (pSims1[i] & ~pSims2[i]);
+                uHash ^= pSims[i] * s_FraigPrimes[i];
+            }
+    }
+    else // if ( !fCompl1 && !fCompl2 )
+    {
+        if ( fCompl )
+            for ( i = iWordStart; i < iWordStop; i++ )
+            {
+                pSims[i] = ~(pSims1[i] & pSims2[i]);
+                uHash ^= pSims[i] * s_FraigPrimes[i];
+            }
+        else
+            for ( i = iWordStart; i < iWordStop; i++ )
+            {
+                pSims[i] = (pSims1[i] & pSims2[i]);
+                uHash ^= pSims[i] * s_FraigPrimes[i];
+            }
+    }
+
+    if ( fUseRand )
+        pNode->uHashR ^= uHash;
+    else
+        pNode->uHashD ^= uHash;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fraig/fraigPrime.c b/abc-build/src/proof/fraig/fraigPrime.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fraig/fraigPrime.c
@@ -0,0 +1,113 @@
+/**CFile****************************************************************
+
+  FileName    [fraigPrime.c]
+
+  PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+  Synopsis    [The table of the first 1000 primes.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - October 1, 2004]
+
+  Revision    [$Id: fraigPrime.c,v 1.4 2005/07/08 01:01:32 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// The 1,024 smallest prime numbers used to compute the hash value
+// http://www.math.utah.edu/~alfeld/math/primelist.html
+int s_FraigPrimes[FRAIG_MAX_PRIMES] = { 2, 3, 5, 
+7, 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, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 
+641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 
+757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 
+881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 
+1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 
+1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 
+1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 
+1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 
+1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 
+1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 
+1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 
+1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 
+1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 
+1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 
+2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 
+2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 
+2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 
+2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 
+2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 
+2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 
+2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 
+2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 
+2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 
+3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 
+3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 
+3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 
+3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 
+3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 
+3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 
+3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 
+3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 
+3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 
+4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 
+4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 
+4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 
+4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 
+4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 
+4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 
+4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 
+4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 
+5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 
+5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 
+5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 
+5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 
+5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 
+5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 
+5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 
+5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 
+6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 
+6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 
+6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 
+6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 
+6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 
+6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 
+6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 
+6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 
+6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 
+7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 
+7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 
+7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 
+7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 
+7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 
+7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 
+7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 
+8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, 
+8147, 8161 };
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fraig/fraigSat.c b/abc-build/src/proof/fraig/fraigSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fraig/fraigSat.c
@@ -0,0 +1,1463 @@
+/**CFile****************************************************************
+
+  FileName    [fraigSat.c]
+
+  PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+  Synopsis    [Proving functional equivalence using SAT.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - October 1, 2004]
+
+  Revision    [$Id: fraigSat.c,v 1.10 2005/07/08 01:01:32 alanmi Exp $]
+
+***********************************************************************/
+
+#include <math.h>
+#include "fraigInt.h"
+#include "sat/msat/msatInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+static void Fraig_SetupAdjacent( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars );
+static void Fraig_SetupAdjacentMark( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars );
+static void Fraig_PrepareCones( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+static void Fraig_PrepareCones_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+
+static void Fraig_SupergateAddClauses( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper );
+static void Fraig_SupergateAddClausesExor( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+static void Fraig_SupergateAddClausesMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+//static void Fraig_DetectFanoutFreeCone( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+static void Fraig_DetectFanoutFreeConeMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+static void Fraig_SetActivity( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+
+// The lesson learned seems to be that variable should be in reverse topological order
+// from the output of the miter. The ordering of adjacency lists is very important.
+// The best way seems to be fanins followed by fanouts. Slight changes to this order
+// leads to big degradation in quality.
+
+static int nMuxes;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Checks equivalence of two nodes.]
+
+  Description [Returns 1 iff the nodes are equivalent.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit, int nTimeLimit )
+{
+    if ( pNode1 == pNode2 )
+        return 1;
+    if ( pNode1 == Fraig_Not(pNode2) )
+        return 0;
+    return Fraig_NodeIsEquivalent( p, Fraig_Regular(pNode1), Fraig_Regular(pNode2), nBTLimit, nTimeLimit );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tries to prove the final miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_ManProveMiter( Fraig_Man_t * p )
+{
+    Fraig_Node_t * pNode;
+    int i;
+    abctime clk;
+
+    if ( !p->fTryProve )
+        return;
+ 
+    clk = Abc_Clock();
+    // consider all outputs of the multi-output miter
+    for ( i = 0; i < p->vOutputs->nSize; i++ )
+    {
+        pNode = Fraig_Regular(p->vOutputs->pArray[i]);
+        // skip already constant nodes
+        if ( pNode == p->pConst1 )
+            continue;
+        // skip nodes that are different according to simulation
+        if ( !Fraig_CompareSimInfo( pNode, p->pConst1, p->nWordsRand, 1 ) )
+            continue;
+        if ( Fraig_NodeIsEquivalent( p, p->pConst1, pNode, -1, p->nSeconds ) )
+        {
+            if ( Fraig_IsComplement(p->vOutputs->pArray[i]) ^ Fraig_NodeComparePhase(p->pConst1, pNode) )
+                p->vOutputs->pArray[i] = Fraig_Not(p->pConst1);
+            else
+                p->vOutputs->pArray[i] = p->pConst1;
+        }
+    }
+    if ( p->fVerboseP ) 
+    {
+//        ABC_PRT( "Final miter proof time", Abc_Clock() - clk );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the miter is unsat; 0 if sat; -1 if undecided.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_ManCheckMiter( Fraig_Man_t * p )
+{
+    Fraig_Node_t * pNode;
+    int i;
+    ABC_FREE( p->pModel );
+    for ( i = 0; i < p->vOutputs->nSize; i++ )
+    {
+        // get the output node (it can be complemented!)
+        pNode = p->vOutputs->pArray[i];
+        // if the miter is constant 0, the problem is UNSAT
+        if ( pNode == Fraig_Not(p->pConst1) )
+            continue;
+        // consider the special case when the miter is constant 1
+        if ( pNode == p->pConst1 )
+        {
+            // in this case, any counter example will do to distinquish it from constant 0
+            // here we pick the counter example composed of all zeros
+            p->pModel = Fraig_ManAllocCounterExample( p );
+            return 0;
+        }
+        // save the counter example
+        p->pModel = Fraig_ManSaveCounterExample( p, pNode );
+        // if the model is not found, return undecided
+        if ( p->pModel == NULL )
+            return -1;
+        else
+            return 0;
+    }
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pOld is in the TFI of pNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_MarkTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+    // skip the visited node
+    if ( pNode->TravId == pMan->nTravIds )
+        return 0;
+    pNode->TravId = pMan->nTravIds;
+    // skip the PI node
+    if ( pNode->NumPi >= 0 )
+        return 1;
+    // check the children
+    return Fraig_MarkTfi_rec( pMan, Fraig_Regular(pNode->p1) ) +
+           Fraig_MarkTfi_rec( pMan, Fraig_Regular(pNode->p2) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pOld is in the TFI of pNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_MarkTfi2_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+    // skip the visited node
+    if ( pNode->TravId == pMan->nTravIds )
+        return 0;
+    // skip the boundary node
+    if ( pNode->TravId == pMan->nTravIds-1 )
+    {
+        pNode->TravId = pMan->nTravIds;
+        return 1;
+    }
+    pNode->TravId = pMan->nTravIds;
+    // skip the PI node
+    if ( pNode->NumPi >= 0 )
+        return 1;
+    // check the children
+    return Fraig_MarkTfi2_rec( pMan, Fraig_Regular(pNode->p1) ) +
+           Fraig_MarkTfi2_rec( pMan, Fraig_Regular(pNode->p2) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pOld is in the TFI of pNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_MarkTfi3_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+    // skip the visited node
+    if ( pNode->TravId == pMan->nTravIds )
+        return 1;
+    // skip the boundary node
+    if ( pNode->TravId == pMan->nTravIds-1 )
+    {
+        pNode->TravId = pMan->nTravIds;
+        return 1;
+    }
+    pNode->TravId = pMan->nTravIds;
+    // skip the PI node
+    if ( pNode->NumPi >= 0 )
+        return 0;
+    // check the children
+    return Fraig_MarkTfi3_rec( pMan, Fraig_Regular(pNode->p1) ) *
+           Fraig_MarkTfi3_rec( pMan, Fraig_Regular(pNode->p2) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_VarsStudy( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+    int NumPis, NumCut, fContain;
+
+    // mark the TFI of pNew
+    p->nTravIds++;
+    NumPis = Fraig_MarkTfi_rec( p, pNew );
+    printf( "(%d)(%d,%d):", NumPis, pOld->Level, pNew->Level );
+
+    // check if the old is in the TFI
+    if ( pOld->TravId == p->nTravIds )
+    {
+        printf( "* " );
+        return;
+    }
+
+    // count the boundary of nodes in pOld
+    p->nTravIds++;
+    NumCut = Fraig_MarkTfi2_rec( p, pOld );
+    printf( "%d", NumCut );
+
+    // check if the new is contained in the old's support
+    p->nTravIds++;
+    fContain = Fraig_MarkTfi3_rec( p, pNew );
+    printf( "%c ", fContain? '+':'-' );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks whether two nodes are functinally equivalent.]
+
+  Description [The flag (fComp) tells whether the nodes to be checked
+  are in the opposite polarity. The second flag (fSkipZeros) tells whether
+  the checking should be performed if the simulation vectors are zeros.
+  Returns 1 if the nodes are equivalent; 0 othewise.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit, int nTimeLimit )
+{
+    int RetValue, RetValue1, i, fComp;
+    abctime clk;
+    int fVerbose = 0;
+    int fSwitch = 0;
+
+    // make sure the nodes are not complemented
+    assert( !Fraig_IsComplement(pNew) );
+    assert( !Fraig_IsComplement(pOld) );
+    assert( pNew != pOld );
+
+    // if at least one of the nodes is a failed node, perform adjustments:
+    // if the backtrack limit is small, simply skip this node
+    // if the backtrack limit is > 10, take the quare root of the limit
+    if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) )
+    {
+        p->nSatFails++;
+//            return 0;
+//        if ( nBTLimit > 10 )
+//            nBTLimit /= 10;
+        if ( nBTLimit <= 10 )
+            return 0;
+        nBTLimit = (int)sqrt((double)nBTLimit);
+//        fSwitch = 1;
+    }
+
+    p->nSatCalls++;
+
+    // make sure the solver is allocated and has enough variables
+    if ( p->pSat == NULL )
+        Fraig_ManCreateSolver( p );
+    // make sure the SAT solver has enough variables
+    for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ )
+        Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level );
+
+
+ 
+/*
+    {
+        Fraig_Node_t * ppNodes[2] = { pOld, pNew };
+        extern void Fraig_MappingShowNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppRoots, int nRoots, char * pFileName );
+        Fraig_MappingShowNodes( p, ppNodes, 2, "temp_aig" );
+    }
+*/
+
+    nMuxes = 0;
+
+
+    // get the logic cone
+clk = Abc_Clock();
+//    Fraig_VarsStudy( p, pOld, pNew );
+    Fraig_OrderVariables( p, pOld, pNew );
+//    Fraig_PrepareCones( p, pOld, pNew );
+p->timeTrav += Abc_Clock() - clk;
+
+//    printf( "The number of MUXes detected = %d (%5.2f %% of logic).  ", nMuxes, 300.0*nMuxes/(p->vNodes->nSize - p->vInputs->nSize) );
+//    ABC_PRT( "Time", Abc_Clock() - clk );
+
+if ( fVerbose )
+    printf( "%d(%d) - ", Fraig_CountPis(p,p->vVarsInt), Msat_IntVecReadSize(p->vVarsInt) );
+
+
+    // prepare variable activity
+    Fraig_SetActivity( p, pOld, pNew );
+
+    // get the complemented attribute
+    fComp = Fraig_NodeComparePhase( pOld, pNew );
+//Msat_SolverPrintClauses( p->pSat );
+
+    ////////////////////////////////////////////
+    // prepare the solver to run incrementally on these variables
+//clk = Abc_Clock();
+    Msat_SolverPrepare( p->pSat, p->vVarsInt );
+//p->time3 += Abc_Clock() - clk;
+
+
+    // solve under assumptions
+    // A = 1; B = 0     OR     A = 1; B = 1 
+    Msat_IntVecClear( p->vProj );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) );
+
+//Msat_SolverWriteDimacs( p->pSat, "temp_fraig.cnf" );
+
+    // run the solver
+clk = Abc_Clock();
+    RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, nTimeLimit );
+p->timeSat += Abc_Clock() - clk;
+
+    if ( RetValue1 == MSAT_FALSE )
+    {
+//p->time1 += Abc_Clock() - clk;
+
+if ( fVerbose )
+{
+//    printf( "unsat  %d  ", Msat_SolverReadBackTracks(p->pSat) );
+//ABC_PRT( "time", Abc_Clock() - clk );
+}
+
+        // add the clause
+        Msat_IntVecClear( p->vProj );
+        Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) );
+        Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) );
+        RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+        assert( RetValue );
+        // continue solving the other implication
+    }
+    else if ( RetValue1 == MSAT_TRUE )
+    {
+//p->time2 += Abc_Clock() - clk;
+
+if ( fVerbose )
+{
+//    printf( "sat  %d  ", Msat_SolverReadBackTracks(p->pSat) );
+//ABC_PRT( "time", Abc_Clock() - clk );
+}
+
+        // record the counter example
+        Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew );
+
+//        if ( pOld->fFailTfo || pNew->fFailTfo )
+//            printf( "*" );
+//        printf( "s(%d)", pNew->Level );
+        if ( fSwitch )
+             printf( "s(%d)", pNew->Level );
+        p->nSatCounter++;
+        return 0;
+    }
+    else // if ( RetValue1 == MSAT_UNKNOWN )
+    {
+p->time3 += Abc_Clock() - clk;
+
+//        if ( pOld->fFailTfo || pNew->fFailTfo )
+//            printf( "*" );
+//        printf( "T(%d)", pNew->Level );
+
+        // mark the node as the failed node
+        if ( pOld != p->pConst1 ) 
+            pOld->fFailTfo = 1;
+        pNew->fFailTfo = 1;
+//        p->nSatFails++;
+        if ( fSwitch )
+             printf( "T(%d)", pNew->Level );
+        p->nSatFailsReal++;
+        return 0;
+    }
+
+    // if the old node was constant 0, we already know the answer
+    if ( pOld == p->pConst1 )
+        return 1;
+
+    ////////////////////////////////////////////
+    // prepare the solver to run incrementally 
+//clk = Abc_Clock();
+    Msat_SolverPrepare( p->pSat, p->vVarsInt );
+//p->time3 += Abc_Clock() - clk;
+    // solve under assumptions
+    // A = 0; B = 1     OR     A = 0; B = 0 
+    Msat_IntVecClear( p->vProj );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) );
+    // run the solver
+clk = Abc_Clock();
+    RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, nTimeLimit );
+p->timeSat += Abc_Clock() - clk;
+
+    if ( RetValue1 == MSAT_FALSE )
+    {
+//p->time1 += Abc_Clock() - clk;
+
+if ( fVerbose )
+{
+//    printf( "unsat  %d  ", Msat_SolverReadBackTracks(p->pSat) );
+//ABC_PRT( "time", Abc_Clock() - clk );
+}
+
+        // add the clause
+        Msat_IntVecClear( p->vProj );
+        Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) );
+        Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) );
+        RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+        assert( RetValue );
+        // continue solving the other implication
+    }
+    else if ( RetValue1 == MSAT_TRUE )
+    {
+//p->time2 += Abc_Clock() - clk;
+
+if ( fVerbose )
+{
+//    printf( "sat  %d  ", Msat_SolverReadBackTracks(p->pSat) );
+//ABC_PRT( "time", Abc_Clock() - clk );
+}
+
+        // record the counter example
+        Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew );
+        p->nSatCounter++;
+
+//        if ( pOld->fFailTfo || pNew->fFailTfo )
+//            printf( "*" );
+//        printf( "s(%d)", pNew->Level );
+        if ( fSwitch )
+             printf( "s(%d)", pNew->Level );
+        return 0;
+    }
+    else // if ( RetValue1 == MSAT_UNKNOWN )
+    {
+p->time3 += Abc_Clock() - clk;
+
+//        if ( pOld->fFailTfo || pNew->fFailTfo )
+//            printf( "*" );
+//        printf( "T(%d)", pNew->Level );
+        if ( fSwitch )
+             printf( "T(%d)", pNew->Level );
+
+        // mark the node as the failed node
+        pOld->fFailTfo = 1;
+        pNew->fFailTfo = 1;
+//        p->nSatFails++;
+        p->nSatFailsReal++;
+        return 0;
+    }
+
+    // return SAT proof
+    p->nSatProof++;
+
+//    if ( pOld->fFailTfo || pNew->fFailTfo )
+//        printf( "*" );
+//    printf( "u(%d)", pNew->Level );
+
+    if ( fSwitch )
+         printf( "u(%d)", pNew->Level );
+
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks whether pOld => pNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeIsImplication( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit )
+{
+    int RetValue, RetValue1, i, fComp;
+    abctime clk;
+    int fVerbose = 0;
+
+    // make sure the nodes are not complemented
+    assert( !Fraig_IsComplement(pNew) );
+    assert( !Fraig_IsComplement(pOld) );
+    assert( pNew != pOld );
+
+    p->nSatCallsImp++;
+
+    // make sure the solver is allocated and has enough variables
+    if ( p->pSat == NULL )
+        Fraig_ManCreateSolver( p );
+    // make sure the SAT solver has enough variables
+    for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ )
+        Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level );
+
+   // get the logic cone
+clk = Abc_Clock();
+    Fraig_OrderVariables( p, pOld, pNew );
+//    Fraig_PrepareCones( p, pOld, pNew );
+p->timeTrav += Abc_Clock() - clk;
+
+if ( fVerbose )
+    printf( "%d(%d) - ", Fraig_CountPis(p,p->vVarsInt), Msat_IntVecReadSize(p->vVarsInt) );
+
+
+    // get the complemented attribute
+    fComp = Fraig_NodeComparePhase( pOld, pNew );
+//Msat_SolverPrintClauses( p->pSat );
+
+    ////////////////////////////////////////////
+    // prepare the solver to run incrementally on these variables
+//clk = Abc_Clock();
+    Msat_SolverPrepare( p->pSat, p->vVarsInt );
+//p->time3 += Abc_Clock() - clk;
+
+    // solve under assumptions
+    // A = 1; B = 0     OR     A = 1; B = 1 
+    Msat_IntVecClear( p->vProj );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) );
+    // run the solver
+clk = Abc_Clock();
+    RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, 1000000 );
+p->timeSat += Abc_Clock() - clk;
+
+    if ( RetValue1 == MSAT_FALSE )
+    {
+//p->time1 += Abc_Clock() - clk;
+
+if ( fVerbose )
+{
+//    printf( "unsat  %d  ", Msat_SolverReadBackTracks(p->pSat) );
+//ABC_PRT( "time", Abc_Clock() - clk );
+}
+
+        // add the clause
+        Msat_IntVecClear( p->vProj );
+        Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) );
+        Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) );
+        RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+        assert( RetValue );
+//        p->nSatProofImp++;
+        return 1;
+    }
+    else if ( RetValue1 == MSAT_TRUE )
+    {
+//p->time2 += Abc_Clock() - clk;
+
+if ( fVerbose )
+{
+//    printf( "sat  %d  ", Msat_SolverReadBackTracks(p->pSat) );
+//ABC_PRT( "time", Abc_Clock() - clk );
+}
+        // record the counter example
+        Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew );
+        p->nSatCounterImp++;
+        return 0;
+    }
+    else // if ( RetValue1 == MSAT_UNKNOWN )
+    {
+p->time3 += Abc_Clock() - clk;
+        p->nSatFailsImp++;
+        return 0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the SAT solver to run on the two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_ManCheckClauseUsingSat( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit )
+{
+    Fraig_Node_t * pNode1R, * pNode2R;
+    int RetValue, RetValue1, i;
+    abctime clk;
+    int fVerbose = 0;
+
+    pNode1R = Fraig_Regular(pNode1);
+    pNode2R = Fraig_Regular(pNode2);
+    assert( pNode1R != pNode2R );
+
+    // make sure the solver is allocated and has enough variables
+    if ( p->pSat == NULL )
+        Fraig_ManCreateSolver( p );
+    // make sure the SAT solver has enough variables
+    for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ )
+        Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level );
+
+   // get the logic cone
+clk = Abc_Clock();
+    Fraig_OrderVariables( p, pNode1R, pNode2R );
+//    Fraig_PrepareCones( p, pNode1R, pNode2R );
+p->timeTrav += Abc_Clock() - clk;
+
+    ////////////////////////////////////////////
+    // prepare the solver to run incrementally on these variables
+//clk = Abc_Clock();
+    Msat_SolverPrepare( p->pSat, p->vVarsInt );
+//p->time3 += Abc_Clock() - clk;
+
+    // solve under assumptions
+    // A = 1; B = 0     OR     A = 1; B = 1 
+    Msat_IntVecClear( p->vProj );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1R->Num, !Fraig_IsComplement(pNode1)) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2R->Num, !Fraig_IsComplement(pNode2)) );
+    // run the solver
+clk = Abc_Clock();
+    RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, 1000000 );
+p->timeSat += Abc_Clock() - clk;
+
+    if ( RetValue1 == MSAT_FALSE )
+    {
+//p->time1 += Abc_Clock() - clk;
+
+if ( fVerbose )
+{
+//    printf( "unsat  %d  ", Msat_SolverReadBackTracks(p->pSat) );
+//ABC_PRT( "time", Abc_Clock() - clk );
+}
+
+        // add the clause
+        Msat_IntVecClear( p->vProj );
+        Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1R->Num, Fraig_IsComplement(pNode1)) );
+        Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2R->Num, Fraig_IsComplement(pNode2)) );
+        RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+        assert( RetValue );
+//        p->nSatProofImp++;
+        return 1;
+    }
+    else if ( RetValue1 == MSAT_TRUE )
+    {
+//p->time2 += Abc_Clock() - clk;
+
+if ( fVerbose )
+{
+//    printf( "sat  %d  ", Msat_SolverReadBackTracks(p->pSat) );
+//ABC_PRT( "time", Abc_Clock() - clk );
+}
+        // record the counter example
+//        Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pNode1R, pNode2R );
+        p->nSatCounterImp++;
+        return 0;
+    }
+    else // if ( RetValue1 == MSAT_UNKNOWN )
+    {
+p->time3 += Abc_Clock() - clk;
+        p->nSatFailsImp++;
+        return 0;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the SAT solver to run on the two nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_PrepareCones( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+//    Msat_IntVec_t * vAdjs;
+//    int * pVars, nVars, i, k;
+    int nVarsAlloc;
+
+    assert( pOld != pNew );
+    assert( !Fraig_IsComplement(pOld) );
+    assert( !Fraig_IsComplement(pNew) );
+    // clean the variables
+    nVarsAlloc = Msat_IntVecReadSize(pMan->vVarsUsed);
+    Msat_IntVecFill( pMan->vVarsUsed, nVarsAlloc, 0 );
+    Msat_IntVecClear( pMan->vVarsInt );
+
+    pMan->nTravIds++;
+    Fraig_PrepareCones_rec( pMan, pNew );
+    Fraig_PrepareCones_rec( pMan, pOld );
+
+
+/*
+    nVars = Msat_IntVecReadSize( pMan->vVarsInt );
+    pVars = Msat_IntVecReadArray( pMan->vVarsInt );
+    for ( i = 0; i < nVars; i++ )
+    {
+        // process its connections
+        vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] );
+        printf( "%d=%d { ", pVars[i], Msat_IntVecReadSize(vAdjs) );
+        for ( k = 0; k < Msat_IntVecReadSize(vAdjs); k++ )
+            printf( "%d ", Msat_IntVecReadEntry(vAdjs,k) );
+        printf( "}\n" );
+
+    }
+    i = 0;
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Traverses the cone, collects the numbers and adds the clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_PrepareCones_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+    Fraig_Node_t * pFanin;
+    Msat_IntVec_t * vAdjs;
+    int fUseMuxes = 1, i;
+    int fItIsTime;
+
+    // skip if the node is aleady visited
+    assert( !Fraig_IsComplement(pNode) );
+    if ( pNode->TravId == pMan->nTravIds )
+        return;
+    pNode->TravId = pMan->nTravIds;
+
+    // collect the node's number (closer to reverse topological order)
+    Msat_IntVecPush( pMan->vVarsInt, pNode->Num );
+    Msat_IntVecWriteEntry( pMan->vVarsUsed, pNode->Num, 1 );
+    if ( !Fraig_NodeIsAnd( pNode ) )
+        return;
+
+    // if the node does not have fanins, create them
+    fItIsTime = 0;
+    if ( pNode->vFanins == NULL )
+    {
+        fItIsTime = 1;
+        // create the fanins of the supergate
+        assert( pNode->fClauses == 0 );
+        if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) )
+        {
+            pNode->vFanins = Fraig_NodeVecAlloc( 4 );
+            Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) );
+            Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) );
+            Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) );
+            Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) );
+            Fraig_SupergateAddClausesMux( pMan, pNode );
+        }
+        else
+        {
+            pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes );
+            Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins );
+        }
+        assert( pNode->vFanins->nSize > 1 );
+        pNode->fClauses = 1;
+        pMan->nVarsClauses++;
+
+        // add fanins
+        vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pNode->Num );
+        assert( Msat_IntVecReadSize( vAdjs ) == 0 );
+        for ( i = 0; i < pNode->vFanins->nSize; i++ )
+        {
+            pFanin = Fraig_Regular(pNode->vFanins->pArray[i]);
+            Msat_IntVecPush( vAdjs, pFanin->Num );
+        }
+    }
+
+    // recursively visit the fanins
+    for ( i = 0; i < pNode->vFanins->nSize; i++ )
+        Fraig_PrepareCones_rec( pMan, Fraig_Regular(pNode->vFanins->pArray[i]) );
+
+    if ( fItIsTime )
+    {
+        // recursively visit the fanins
+        for ( i = 0; i < pNode->vFanins->nSize; i++ )
+        {
+            pFanin = Fraig_Regular(pNode->vFanins->pArray[i]);
+            vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num );
+            Msat_IntVecPush( vAdjs, pNode->Num );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect variables using their proximity from the nodes.]
+
+  Description [This procedure creates a variable order based on collecting
+  first the nodes that are the closest to the given two target nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+    Fraig_Node_t * pNode, * pFanin;
+    int i, k, Number, fUseMuxes = 1;
+    int nVarsAlloc;
+
+    assert( pOld != pNew );
+    assert( !Fraig_IsComplement(pOld) );
+    assert( !Fraig_IsComplement(pNew) );
+
+    pMan->nTravIds++;
+
+    // clean the variables
+    nVarsAlloc = Msat_IntVecReadSize(pMan->vVarsUsed);
+    Msat_IntVecFill( pMan->vVarsUsed, nVarsAlloc, 0 );
+    Msat_IntVecClear( pMan->vVarsInt );
+
+    // add the first node
+    Msat_IntVecPush( pMan->vVarsInt, pOld->Num );
+    Msat_IntVecWriteEntry( pMan->vVarsUsed, pOld->Num, 1 );
+    pOld->TravId = pMan->nTravIds;
+
+    // add the second node
+    Msat_IntVecPush( pMan->vVarsInt, pNew->Num );
+    Msat_IntVecWriteEntry( pMan->vVarsUsed, pNew->Num, 1 );
+    pNew->TravId = pMan->nTravIds;
+
+    // create the variable order
+    for ( i = 0; i < Msat_IntVecReadSize(pMan->vVarsInt); i++ )
+    {
+        // get the new node on the frontier
+        Number = Msat_IntVecReadEntry(pMan->vVarsInt, i);
+        pNode = pMan->vNodes->pArray[Number];
+        if ( !Fraig_NodeIsAnd(pNode) )
+            continue;
+
+        // if the node does not have fanins, create them
+        if ( pNode->vFanins == NULL )
+        {
+            // create the fanins of the supergate
+            assert( pNode->fClauses == 0 );
+            // detecting a fanout-free cone (experiment only)
+//            Fraig_DetectFanoutFreeCone( pMan, pNode );
+
+            if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) )
+            {
+                pNode->vFanins = Fraig_NodeVecAlloc( 4 );
+                Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) );
+                Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) );
+                Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) );
+                Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) );
+                Fraig_SupergateAddClausesMux( pMan, pNode );
+//                Fraig_DetectFanoutFreeConeMux( pMan, pNode );
+
+                nMuxes++;
+            }
+            else
+            {
+                pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes );
+                Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins );
+            }
+            assert( pNode->vFanins->nSize > 1 );
+            pNode->fClauses = 1;
+            pMan->nVarsClauses++;
+
+            pNode->fMark2 = 1; // goes together with Fraig_SetupAdjacentMark()
+        }
+
+        // explore the implication fanins of pNode
+        for ( k = 0; k < pNode->vFanins->nSize; k++ )
+        {
+            pFanin = Fraig_Regular(pNode->vFanins->pArray[k]);
+            if ( pFanin->TravId == pMan->nTravIds ) // already collected
+                continue;
+            // collect and mark
+            Msat_IntVecPush( pMan->vVarsInt, pFanin->Num );
+            Msat_IntVecWriteEntry( pMan->vVarsUsed, pFanin->Num, 1 );
+            pFanin->TravId = pMan->nTravIds;
+        }
+    }
+
+    // set up the adjacent variable information
+//    Fraig_SetupAdjacent( pMan, pMan->vVarsInt );
+    Fraig_SetupAdjacentMark( pMan, pMan->vVarsInt );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Set up the adjacent variable information.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_SetupAdjacent( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars )
+{
+    Fraig_Node_t * pNode, * pFanin;
+    Msat_IntVec_t * vAdjs;
+    int * pVars, nVars, i, k;
+
+    // clean the adjacents for the variables
+    nVars = Msat_IntVecReadSize( vConeVars );
+    pVars = Msat_IntVecReadArray( vConeVars );
+    for ( i = 0; i < nVars; i++ )
+    {
+        // process its connections
+        vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] );
+        Msat_IntVecClear( vAdjs );
+
+        pNode = pMan->vNodes->pArray[pVars[i]];
+        if ( !Fraig_NodeIsAnd(pNode) )
+            continue;
+
+        // add fanins
+        vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] );
+        for ( k = 0; k < pNode->vFanins->nSize; k++ )
+//        for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- )
+        {
+            pFanin = Fraig_Regular(pNode->vFanins->pArray[k]);
+            Msat_IntVecPush( vAdjs, pFanin->Num );
+//            Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num );
+        }
+    }
+    // add the fanouts
+    for ( i = 0; i < nVars; i++ )
+    {
+        pNode = pMan->vNodes->pArray[pVars[i]];
+        if ( !Fraig_NodeIsAnd(pNode) )
+            continue;
+
+        // add the edges
+        for ( k = 0; k < pNode->vFanins->nSize; k++ )
+//        for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- )
+        {
+            pFanin = Fraig_Regular(pNode->vFanins->pArray[k]);
+            vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num );
+            Msat_IntVecPush( vAdjs, pNode->Num );
+//            Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num );
+        }
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Set up the adjacent variable information.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_SetupAdjacentMark( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars )
+{
+    Fraig_Node_t * pNode, * pFanin;
+    Msat_IntVec_t * vAdjs;
+    int * pVars, nVars, i, k;
+
+    // clean the adjacents for the variables
+    nVars = Msat_IntVecReadSize( vConeVars );
+    pVars = Msat_IntVecReadArray( vConeVars );
+    for ( i = 0; i < nVars; i++ )
+    {
+        pNode = pMan->vNodes->pArray[pVars[i]];
+        if ( pNode->fMark2 == 0 )
+            continue;
+//        pNode->fMark2 = 0;
+
+        // process its connections
+//        vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] );
+//        Msat_IntVecClear( vAdjs );
+
+        if ( !Fraig_NodeIsAnd(pNode) )
+            continue;
+
+        // add fanins
+        vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] );
+        for ( k = 0; k < pNode->vFanins->nSize; k++ )
+//        for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- )
+        {
+            pFanin = Fraig_Regular(pNode->vFanins->pArray[k]);
+            Msat_IntVecPush( vAdjs, pFanin->Num );
+//            Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num );
+        }
+    }
+    // add the fanouts
+    for ( i = 0; i < nVars; i++ )
+    {
+        pNode = pMan->vNodes->pArray[pVars[i]];
+        if ( pNode->fMark2 == 0 )
+            continue;
+        pNode->fMark2 = 0;
+
+        if ( !Fraig_NodeIsAnd(pNode) )
+            continue;
+
+        // add the edges
+        for ( k = 0; k < pNode->vFanins->nSize; k++ )
+//        for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- )
+        {
+            pFanin = Fraig_Regular(pNode->vFanins->pArray[k]);
+            vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num );
+            Msat_IntVecPush( vAdjs, pNode->Num );
+//            Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num );
+        }
+    }
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Adds clauses to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_SupergateAddClauses( Fraig_Man_t * p, Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper )
+{
+    int fComp1, RetValue, nVars, Var, Var1, i;
+
+    assert( Fraig_NodeIsAnd( pNode ) );
+    nVars = Msat_SolverReadVarNum(p->pSat);
+
+    Var = pNode->Num;
+    assert( Var  < nVars ); 
+    for ( i = 0; i < vSuper->nSize; i++ )
+    {
+        // get the predecessor nodes
+        // get the complemented attributes of the nodes
+        fComp1 = Fraig_IsComplement(vSuper->pArray[i]);
+        // determine the variable numbers
+        Var1 = Fraig_Regular(vSuper->pArray[i])->Num;
+        // check that the variables are in the SAT manager
+        assert( Var1 < nVars );
+
+        // suppose the AND-gate is A * B = C
+        // add !A => !C   or   A + !C
+    //  fprintf( pFile, "%d %d 0%c", Var1, -Var, 10 );
+        Msat_IntVecClear( p->vProj );
+        Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var1, fComp1) );
+        Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var,  1) );
+        RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+        assert( RetValue );
+    }
+
+    // add A & B => C   or   !A + !B + C
+//  fprintf( pFile, "%d %d %d 0%c", -Var1, -Var2, Var, 10 );
+    Msat_IntVecClear( p->vProj );
+    for ( i = 0; i < vSuper->nSize; i++ )
+    {
+        // get the predecessor nodes
+        // get the complemented attributes of the nodes
+        fComp1 = Fraig_IsComplement(vSuper->pArray[i]);
+        // determine the variable numbers
+        Var1 = Fraig_Regular(vSuper->pArray[i])->Num;
+
+        // add this variable to the array
+        Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var1, !fComp1) );
+    }
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var, 0) );
+    RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+    assert( RetValue );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds clauses to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_SupergateAddClausesExor( Fraig_Man_t * p, Fraig_Node_t * pNode )
+{
+    Fraig_Node_t * pNode1, * pNode2;
+    int fComp, RetValue;
+
+    assert( !Fraig_IsComplement( pNode ) );
+    assert( Fraig_NodeIsExorType( pNode ) );
+    // get nodes
+    pNode1 = Fraig_Regular(Fraig_Regular(pNode->p1)->p1);
+    pNode2 = Fraig_Regular(Fraig_Regular(pNode->p1)->p2);
+    // get the complemented attribute of the EXOR/NEXOR gate
+    fComp = Fraig_NodeIsExor( pNode ); // 1 if EXOR, 0 if NEXOR
+
+    // create four clauses
+    Msat_IntVecClear( p->vProj );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num,   fComp) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num,  fComp) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num,  fComp) );
+    RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+    assert( RetValue );
+    Msat_IntVecClear( p->vProj );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num,   fComp) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, !fComp) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, !fComp) );
+    RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+    assert( RetValue );
+    Msat_IntVecClear( p->vProj );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num,  !fComp) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num,  fComp) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, !fComp) );
+    RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+    assert( RetValue );
+    Msat_IntVecClear( p->vProj );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num,  !fComp) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, !fComp) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num,  fComp) );
+    RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+    assert( RetValue );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds clauses to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_SupergateAddClausesMux( Fraig_Man_t * p, Fraig_Node_t * pNode )
+{
+    Fraig_Node_t * pNodeI, * pNodeT, * pNodeE;
+    int RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE;
+
+    assert( !Fraig_IsComplement( pNode ) );
+    assert( Fraig_NodeIsMuxType( pNode ) );
+    // get nodes (I = if, T = then, E = else)
+    pNodeI = Fraig_NodeRecognizeMux( pNode, &pNodeT, &pNodeE );
+    // get the variable numbers
+    VarF = pNode->Num;
+    VarI = pNodeI->Num;
+    VarT = Fraig_Regular(pNodeT)->Num;
+    VarE = Fraig_Regular(pNodeE)->Num;
+    // get the complementation flags
+    fCompT = Fraig_IsComplement(pNodeT);
+    fCompE = Fraig_IsComplement(pNodeE);
+
+    // f = ITE(i, t, e)
+
+    // i' + t' + f
+    // i' + t  + f'
+    // i  + e' + f
+    // i  + e  + f'
+
+    // create four clauses
+    Msat_IntVecClear( p->vProj );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI,  1) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT,  1^fCompT) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF,  0) );
+    RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+    assert( RetValue );
+    Msat_IntVecClear( p->vProj );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI,  1) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT,  0^fCompT) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF,  1) );
+    RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+    assert( RetValue );
+    Msat_IntVecClear( p->vProj );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI,  0) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE,  1^fCompE) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF,  0) );
+    RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+    assert( RetValue );
+    Msat_IntVecClear( p->vProj );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI,  0) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE,  0^fCompE) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF,  1) );
+    RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+    assert( RetValue );
+
+    // two additional clauses
+    // t' & e' -> f'
+    // t  & e  -> f 
+
+    // t  + e   + f'
+    // t' + e'  + f 
+
+    if ( VarT == VarE )
+    {
+//        assert( fCompT == !fCompE );
+        return;
+    }
+
+    Msat_IntVecClear( p->vProj );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT,  0^fCompT) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE,  0^fCompE) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF,  1) );
+    RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+    assert( RetValue );
+    Msat_IntVecClear( p->vProj );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT,  1^fCompT) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE,  1^fCompE) );
+    Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF,  0) );
+    RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+    assert( RetValue );
+
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_DetectFanoutFreeCone_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, Fraig_NodeVec_t * vInside, int fFirst )
+{
+    // make the pointer regular
+    pNode = Fraig_Regular(pNode);
+    // if the new node is complemented or a PI, another gate begins
+    if ( (!fFirst && pNode->nRefs > 1) || Fraig_NodeIsVar(pNode) )
+    {
+        Fraig_NodeVecPushUnique( vSuper, pNode );
+        return;
+    }
+    // go through the branches
+    Fraig_DetectFanoutFreeCone_rec( pNode->p1, vSuper, vInside, 0 );
+    Fraig_DetectFanoutFreeCone_rec( pNode->p2, vSuper, vInside, 0 );
+    // add the node
+    Fraig_NodeVecPushUnique( vInside, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+void Fraig_DetectFanoutFreeCone( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+    Fraig_NodeVec_t * vFanins;
+    Fraig_NodeVec_t * vInside;
+    int nCubes;
+    extern int Fraig_CutSopCountCubes( Fraig_Man_t * pMan, Fraig_NodeVec_t * vFanins, Fraig_NodeVec_t * vInside );
+
+    vFanins = Fraig_NodeVecAlloc( 8 );
+    vInside = Fraig_NodeVecAlloc( 8 );
+
+    Fraig_DetectFanoutFreeCone_rec( pNode, vFanins, vInside, 1 );
+    assert( vInside->pArray[vInside->nSize-1] == pNode );
+
+    nCubes = Fraig_CutSopCountCubes( pMan, vFanins, vInside );
+
+printf( "%d(%d)", vFanins->nSize, nCubes );
+    Fraig_NodeVecFree( vFanins );
+    Fraig_NodeVecFree( vInside );
+}
+*/
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_DetectFanoutFreeConeMux_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, Fraig_NodeVec_t * vInside, int fFirst )
+{
+    // make the pointer regular
+    pNode = Fraig_Regular(pNode);
+    // if the new node is complemented or a PI, another gate begins
+    if ( (!fFirst && pNode->nRefs > 1) || Fraig_NodeIsVar(pNode) || !Fraig_NodeIsMuxType(pNode) )
+    {
+        Fraig_NodeVecPushUnique( vSuper, pNode );
+        return;
+    }
+    // go through the branches
+    Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p1)->p1, vSuper, vInside, 0 );
+    Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p1)->p2, vSuper, vInside, 0 );
+    Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p2)->p1, vSuper, vInside, 0 );
+    Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p2)->p2, vSuper, vInside, 0 );
+    // add the node
+    Fraig_NodeVecPushUnique( vInside, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_DetectFanoutFreeConeMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+    Fraig_NodeVec_t * vFanins;
+    Fraig_NodeVec_t * vInside;
+    int nCubes;
+    extern int Fraig_CutSopCountCubes( Fraig_Man_t * pMan, Fraig_NodeVec_t * vFanins, Fraig_NodeVec_t * vInside );
+
+    vFanins = Fraig_NodeVecAlloc( 8 );
+    vInside = Fraig_NodeVecAlloc( 8 );
+
+    Fraig_DetectFanoutFreeConeMux_rec( pNode, vFanins, vInside, 1 );
+    assert( vInside->pArray[vInside->nSize-1] == pNode );
+
+//    nCubes = Fraig_CutSopCountCubes( pMan, vFanins, vInside );
+    nCubes = 0;
+
+printf( "%d(%d)", vFanins->nSize, nCubes );
+    Fraig_NodeVecFree( vFanins );
+    Fraig_NodeVecFree( vInside );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collect variables using their proximity from the nodes.]
+
+  Description [This procedure creates a variable order based on collecting
+  first the nodes that are the closest to the given two target nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_SetActivity( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+    Fraig_Node_t * pNode;
+    int i, Number, MaxLevel;
+    float * pFactors = Msat_SolverReadFactors(pMan->pSat);
+    if ( pFactors == NULL )
+        return;
+    MaxLevel = Abc_MaxInt( pOld->Level, pNew->Level );
+    // create the variable order
+    for ( i = 0; i < Msat_IntVecReadSize(pMan->vVarsInt); i++ )
+    {
+        // get the new node on the frontier
+        Number = Msat_IntVecReadEntry(pMan->vVarsInt, i);
+        pNode = pMan->vNodes->pArray[Number];
+        pFactors[pNode->Num] = (float)pow( 0.97, MaxLevel - pNode->Level );
+//        if ( pNode->Num % 50 == 0 )
+//        printf( "(%d) %.2f  ", MaxLevel - pNode->Level, pFactors[pNode->Num] );
+    }
+//    printf( "\n" );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fraig/fraigTable.c b/abc-build/src/proof/fraig/fraigTable.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fraig/fraigTable.c
@@ -0,0 +1,664 @@
+/**CFile****************************************************************
+
+  FileName    [fraigTable.c]
+
+  PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+  Synopsis    [Structural and functional hash tables.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - October 1, 2004]
+
+  Revision    [$Id: fraigTable.c,v 1.7 2005/07/08 01:01:34 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Fraig_TableResizeS( Fraig_HashTable_t * p );
+static void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_HashTable_t * Fraig_HashTableCreate( int nSize )
+{
+    Fraig_HashTable_t * p;
+    // allocate the table
+    p = ABC_ALLOC( Fraig_HashTable_t, 1 );
+    memset( p, 0, sizeof(Fraig_HashTable_t) );
+    // allocate and clean the bins
+    p->nBins = Abc_PrimeCudd(nSize);
+    p->pBins = ABC_ALLOC( Fraig_Node_t *, p->nBins );
+    memset( p->pBins, 0, sizeof(Fraig_Node_t *) * p->nBins );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the supergate hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_HashTableFree( Fraig_HashTable_t * p )
+{
+    ABC_FREE( p->pBins );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Looks up an entry in the structural hash table.]
+
+  Description [If the entry with the same children does not exists, 
+  creates it, inserts it into the table, and returns 0. If the entry 
+  with the same children exists, finds it, and return 1. In both cases, 
+  the new/old entry is returned in ppNodeRes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_HashTableLookupS( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2, Fraig_Node_t ** ppNodeRes )
+{
+    Fraig_HashTable_t * p = pMan->pTableS;
+    Fraig_Node_t * pEnt;
+    unsigned Key;
+
+    // order the arguments
+    if ( Fraig_Regular(p1)->Num > Fraig_Regular(p2)->Num )
+        pEnt = p1, p1 = p2, p2 = pEnt;
+
+    Key = Fraig_HashKey2( p1, p2, p->nBins );
+    Fraig_TableBinForEachEntryS( p->pBins[Key], pEnt )
+        if ( pEnt->p1 == p1 && pEnt->p2 == p2 )
+        {
+            *ppNodeRes = pEnt;
+            return 1;
+        }
+    // check if it is a good time for table resizing
+    if ( p->nEntries >= 2 * p->nBins )
+    {
+        Fraig_TableResizeS( p );
+        Key = Fraig_HashKey2( p1, p2, p->nBins );
+    }
+    // create the new node
+    pEnt = Fraig_NodeCreate( pMan, p1, p2 );
+    // add the node to the corresponding linked list in the table
+    pEnt->pNextS = p->pBins[Key];
+    p->pBins[Key] = pEnt;
+    *ppNodeRes = pEnt;
+    p->nEntries++;
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Insert the entry in the functional hash table.]
+
+  Description [If the entry with the same key exists, return it right away.  
+  If the entry with the same key does not exists, inserts it and returns NULL. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_HashTableLookupF( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+    Fraig_HashTable_t * p = pMan->pTableF;
+    Fraig_Node_t * pEnt, * pEntD;
+    unsigned Key;
+
+    // go through the hash table entries
+    Key = pNode->uHashR % p->nBins;
+    Fraig_TableBinForEachEntryF( p->pBins[Key], pEnt )
+    {
+        // if their simulation info differs, skip
+        if ( !Fraig_CompareSimInfo( pNode, pEnt, pMan->nWordsRand, 1 ) )
+            continue;
+        // equivalent up to the complement
+        Fraig_TableBinForEachEntryD( pEnt, pEntD )
+        {
+            // if their simulation info differs, skip
+            if ( !Fraig_CompareSimInfo( pNode, pEntD, pMan->iWordStart, 0 ) )
+                continue;
+            // found a simulation-equivalent node
+            return pEntD; 
+        }
+        // did not find a simulation equivalent node
+        // add the node to the corresponding linked list
+        pNode->pNextD = pEnt->pNextD;
+        pEnt->pNextD  = pNode;
+        // return NULL, because there is no functional equivalence in this case
+        return NULL;
+    }
+
+    // check if it is a good time for table resizing
+    if ( p->nEntries >= 2 * p->nBins )
+    {
+        Fraig_TableResizeF( p, 1 );
+        Key = pNode->uHashR % p->nBins;
+    }
+
+    // add the node to the corresponding linked list in the table
+    pNode->pNextF = p->pBins[Key];
+    p->pBins[Key] = pNode;
+    p->nEntries++;
+    // return NULL, because there is no functional equivalence in this case
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Insert the entry in the functional hash table.]
+
+  Description [If the entry with the same key exists, return it right away.  
+  If the entry with the same key does not exists, inserts it and returns NULL. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_HashTableLookupF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+    Fraig_HashTable_t * p = pMan->pTableF0;
+    Fraig_Node_t * pEnt;
+    unsigned Key;
+
+    // go through the hash table entries
+    Key = pNode->uHashD % p->nBins;
+    Fraig_TableBinForEachEntryF( p->pBins[Key], pEnt )
+    {
+        // if their simulation info differs, skip
+        if ( !Fraig_CompareSimInfo( pNode, pEnt, pMan->iWordStart, 0 ) )
+            continue;
+        // found a simulation-equivalent node
+        return pEnt; 
+    }
+
+    // check if it is a good time for table resizing
+    if ( p->nEntries >= 2 * p->nBins )
+    {
+        Fraig_TableResizeF( p, 0 );
+        Key = pNode->uHashD % p->nBins;
+    }
+
+    // add the node to the corresponding linked list in the table
+    pNode->pNextF = p->pBins[Key];
+    p->pBins[Key] = pNode;
+    p->nEntries++;
+    // return NULL, because there is no functional equivalence in this case
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Insert the entry in the functional hash table.]
+
+  Description [Unconditionally add the node to the corresponding 
+  linked list in the table.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_HashTableInsertF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+    Fraig_HashTable_t * p = pMan->pTableF0;
+    unsigned Key = pNode->uHashD % p->nBins;
+
+    pNode->pNextF = p->pBins[Key];
+    p->pBins[Key] = pNode;
+    p->nEntries++;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_TableResizeS( Fraig_HashTable_t * p )
+{
+    Fraig_Node_t ** pBinsNew;
+    Fraig_Node_t * pEnt, * pEnt2;
+    int nBinsNew, Counter, i;
+    abctime clk;
+    unsigned Key;
+
+clk = Abc_Clock();
+    // get the new table size
+    nBinsNew = Abc_PrimeCudd(2 * p->nBins); 
+    // allocate a new array
+    pBinsNew = ABC_ALLOC( Fraig_Node_t *, nBinsNew );
+    memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * nBinsNew );
+    // rehash the entries from the old table
+    Counter = 0;
+    for ( i = 0; i < p->nBins; i++ )
+        Fraig_TableBinForEachEntrySafeS( p->pBins[i], pEnt, pEnt2 )
+        {
+            Key = Fraig_HashKey2( pEnt->p1, pEnt->p2, nBinsNew );
+            pEnt->pNextS = pBinsNew[Key];
+            pBinsNew[Key] = pEnt;
+            Counter++;
+        }
+    assert( Counter == p->nEntries );
+//    printf( "Increasing the structural table size from %6d to %6d. ", p->nBins, nBinsNew );
+//    ABC_PRT( "Time", Abc_Clock() - clk );
+    // replace the table and the parameters
+    ABC_FREE( p->pBins );
+    p->pBins = pBinsNew;
+    p->nBins = nBinsNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR )
+{
+    Fraig_Node_t ** pBinsNew;
+    Fraig_Node_t * pEnt, * pEnt2;
+    int nBinsNew, Counter, i;
+    abctime clk;
+    unsigned Key;
+
+clk = Abc_Clock();
+    // get the new table size
+    nBinsNew = Abc_PrimeCudd(2 * p->nBins); 
+    // allocate a new array
+    pBinsNew = ABC_ALLOC( Fraig_Node_t *, nBinsNew );
+    memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * nBinsNew );
+    // rehash the entries from the old table
+    Counter = 0;
+    for ( i = 0; i < p->nBins; i++ )
+        Fraig_TableBinForEachEntrySafeF( p->pBins[i], pEnt, pEnt2 )
+        {
+            if ( fUseSimR )
+                Key = pEnt->uHashR % nBinsNew;
+            else
+                Key = pEnt->uHashD % nBinsNew;
+            pEnt->pNextF = pBinsNew[Key];
+            pBinsNew[Key] = pEnt;
+            Counter++;
+        }
+    assert( Counter == p->nEntries );
+//    printf( "Increasing the functional table size from %6d to %6d. ", p->nBins, nBinsNew );
+//    ABC_PRT( "Time", Abc_Clock() - clk );
+    // replace the table and the parameters
+    ABC_FREE( p->pBins );
+    p->pBins = pBinsNew;
+    p->nBins = nBinsNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compares two pieces of simulation info.]
+
+  Description [Returns 1 if they are equal.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_CompareSimInfo( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand )
+{
+    int i;
+    assert( !Fraig_IsComplement(pNode1) );
+    assert( !Fraig_IsComplement(pNode2) );
+    if ( fUseRand )
+    {
+        // if their signatures differ, skip
+        if ( pNode1->uHashR != pNode2->uHashR )
+            return 0;
+        // check the simulation info
+        for ( i = 0; i < iWordLast; i++ )
+            if ( pNode1->puSimR[i] != pNode2->puSimR[i] )
+                return 0;
+    }
+    else
+    {
+        // if their signatures differ, skip
+        if ( pNode1->uHashD != pNode2->uHashD )
+            return 0;
+        // check the simulation info
+        for ( i = 0; i < iWordLast; i++ )
+            if ( pNode1->puSimD[i] != pNode2->puSimD[i] )
+                return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find the number of the different pattern.]
+
+  Description [Returns -1 if there is no such pattern]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_FindFirstDiff( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int fCompl, int iWordLast, int fUseRand )
+{
+    int i, v;
+    assert( !Fraig_IsComplement(pNode1) );
+    assert( !Fraig_IsComplement(pNode2) );
+    // take into account possible internal complementation
+    fCompl ^= pNode1->fInv;
+    fCompl ^= pNode2->fInv;
+    // find the pattern
+    if ( fCompl )
+    {
+        if ( fUseRand )
+        {
+            for ( i = 0; i < iWordLast; i++ )
+                if ( pNode1->puSimR[i] != ~pNode2->puSimR[i] )
+                    for ( v = 0; v < 32; v++ )
+                        if ( (pNode1->puSimR[i] ^ ~pNode2->puSimR[i]) & (1 << v) )
+                            return i * 32 + v;
+        }
+        else
+        {
+            for ( i = 0; i < iWordLast; i++ )
+                if ( pNode1->puSimD[i] !=  ~pNode2->puSimD[i] )
+                    for ( v = 0; v < 32; v++ )
+                        if ( (pNode1->puSimD[i] ^ ~pNode2->puSimD[i]) & (1 << v) )
+                            return i * 32 + v;
+        }
+    }
+    else
+    {
+        if ( fUseRand )
+        {
+            for ( i = 0; i < iWordLast; i++ )
+                if ( pNode1->puSimR[i] != pNode2->puSimR[i] )
+                    for ( v = 0; v < 32; v++ )
+                        if ( (pNode1->puSimR[i] ^ pNode2->puSimR[i]) & (1 << v) )
+                            return i * 32 + v;
+        }
+        else
+        {
+            for ( i = 0; i < iWordLast; i++ )
+                if ( pNode1->puSimD[i] !=  pNode2->puSimD[i] )
+                    for ( v = 0; v < 32; v++ )
+                        if ( (pNode1->puSimD[i] ^ pNode2->puSimD[i]) & (1 << v) )
+                            return i * 32 + v;
+        }
+    }
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares two pieces of simulation info.]
+
+  Description [Returns 1 if they are equal.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_CompareSimInfoUnderMask( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask )
+{
+    unsigned * pSims1, * pSims2;
+    int i;
+    assert( !Fraig_IsComplement(pNode1) );
+    assert( !Fraig_IsComplement(pNode2) );
+    // get hold of simulation info
+    pSims1 = fUseRand? pNode1->puSimR : pNode1->puSimD;
+    pSims2 = fUseRand? pNode2->puSimR : pNode2->puSimD;    
+    // check the simulation info
+    for ( i = 0; i < iWordLast; i++ )
+        if ( (pSims1[i] & puMask[i]) != (pSims2[i] & puMask[i]) )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compares two pieces of simulation info.]
+
+  Description [Returns 1 if they are equal.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_CollectXors( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask )
+{
+    unsigned * pSims1, * pSims2;
+    int i;
+    assert( !Fraig_IsComplement(pNode1) );
+    assert( !Fraig_IsComplement(pNode2) );
+    // get hold of simulation info
+    pSims1 = fUseRand? pNode1->puSimR : pNode1->puSimD;
+    pSims2 = fUseRand? pNode2->puSimR : pNode2->puSimD;    
+    // check the simulation info
+    for ( i = 0; i < iWordLast; i++ )
+        puMask[i] = ( pSims1[i] ^ pSims2[i] );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats of the structural table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_TablePrintStatsS( Fraig_Man_t * pMan )
+{
+    Fraig_HashTable_t * pT = pMan->pTableS;
+    Fraig_Node_t * pNode;
+    int i, Counter;
+
+    printf( "Structural table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries );
+    for ( i = 0; i < pT->nBins; i++ )
+    {
+        Counter = 0;
+        Fraig_TableBinForEachEntryS( pT->pBins[i], pNode )
+            Counter++;
+        if ( Counter > 1 )
+        {
+            printf( "%d ", Counter );
+            if ( Counter > 50 )
+                printf( "{%d} ", i );
+        }
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats of the structural table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_TablePrintStatsF( Fraig_Man_t * pMan )
+{
+    Fraig_HashTable_t * pT = pMan->pTableF;
+    Fraig_Node_t * pNode;
+    int i, Counter;
+
+    printf( "Functional table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries );
+    for ( i = 0; i < pT->nBins; i++ )
+    {
+        Counter = 0;
+        Fraig_TableBinForEachEntryF( pT->pBins[i], pNode )
+            Counter++;
+        if ( Counter > 1 )
+            printf( "{%d} ", Counter );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats of the structural table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_TablePrintStatsF0( Fraig_Man_t * pMan )
+{
+    Fraig_HashTable_t * pT = pMan->pTableF0;
+    Fraig_Node_t * pNode;
+    int i, Counter;
+
+    printf( "Zero-node table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries );
+    for ( i = 0; i < pT->nBins; i++ )
+    {
+        Counter = 0;
+        Fraig_TableBinForEachEntryF( pT->pBins[i], pNode )
+            Counter++;
+        if ( Counter == 0 )
+            continue;
+/*
+        printf( "\nBin = %4d :  Number of entries = %4d\n", i, Counter );
+        Fraig_TableBinForEachEntryF( pT->pBins[i], pNode )
+            printf( "Node %5d. Hash = %10d.\n", pNode->Num, pNode->uHashD );
+*/
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Rehashes the table after the simulation info has changed.]
+
+  Description [Assumes that the hash values have been updated after performing
+  additional simulation. Rehashes the table using the new hash values. 
+  Uses pNextF to link the entries in the bins. Uses pNextD to link the entries 
+  with identical hash values. Returns 1 if the identical entries have been found.
+  Note that identical hash values may mean that the simulation data is different.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_TableRehashF0( Fraig_Man_t * pMan, int fLinkEquiv )
+{
+    Fraig_HashTable_t * pT = pMan->pTableF0;
+    Fraig_Node_t ** pBinsNew;
+    Fraig_Node_t * pEntF, * pEntF2, * pEnt, * pEntD2, * pEntN;
+    int ReturnValue, Counter, i;
+    unsigned Key;
+
+    // allocate a new array of bins
+    pBinsNew = ABC_ALLOC( Fraig_Node_t *, pT->nBins );
+    memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * pT->nBins );
+
+    // rehash the entries in the table
+    // go through all the nodes in the F-lists (and possible in D-lists, if used)
+    Counter = 0;
+    ReturnValue = 0;
+    for ( i = 0; i < pT->nBins; i++ )
+        Fraig_TableBinForEachEntrySafeF( pT->pBins[i], pEntF, pEntF2 )
+        Fraig_TableBinForEachEntrySafeD( pEntF, pEnt, pEntD2 )
+        {
+            // decide where to put entry pEnt
+            Key = pEnt->uHashD % pT->nBins;
+            if ( fLinkEquiv )
+            {
+                // go through the entries in the new bin
+                Fraig_TableBinForEachEntryF( pBinsNew[Key], pEntN )
+                {
+                    // if they have different values skip
+                    if ( pEnt->uHashD != pEntN->uHashD )
+                        continue;
+                    // they have the same hash value, add pEnt to the D-list pEnt3
+                    pEnt->pNextD  = pEntN->pNextD;
+                    pEntN->pNextD = pEnt;
+                    ReturnValue = 1;
+                    Counter++;
+                    break;
+                }
+                if ( pEntN != NULL ) // already linked
+                    continue;
+                // we did not find equal entry
+            }
+            // link the new entry
+            pEnt->pNextF  = pBinsNew[Key];
+            pBinsNew[Key] = pEnt;
+            pEnt->pNextD  = NULL;
+            Counter++;
+        }
+    assert( Counter == pT->nEntries );
+    // replace the table and the parameters
+    ABC_FREE( pT->pBins );
+    pT->pBins = pBinsNew;
+    return ReturnValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fraig/fraigUtil.c b/abc-build/src/proof/fraig/fraigUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fraig/fraigUtil.c
@@ -0,0 +1,1039 @@
+/**CFile****************************************************************
+
+  FileName    [fraigUtil.c]
+
+  PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+  Synopsis    [Various utilities.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - October 1, 2004]
+
+  Revision    [$Id: fraigUtil.c,v 1.15 2005/07/08 01:01:34 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+#include <limits.h>
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int bit_count[256] = {
+  0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+  1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+  1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+  2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+  1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+  2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+  2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+  3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
+
+static void Fraig_Dfs_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vNodes, int fEquiv );
+static int  Fraig_CheckTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_Node_t * pOld );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the DFS ordering of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_Dfs( Fraig_Man_t * pMan, int fEquiv )
+{
+    Fraig_NodeVec_t * vNodes;
+    int i;
+    pMan->nTravIds++;
+    vNodes = Fraig_NodeVecAlloc( 100 );
+    for ( i = 0; i < pMan->vOutputs->nSize; i++ )
+        Fraig_Dfs_rec( pMan, Fraig_Regular(pMan->vOutputs->pArray[i]), vNodes, fEquiv );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the DFS ordering of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_DfsOne( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fEquiv )
+{
+    Fraig_NodeVec_t * vNodes;
+    pMan->nTravIds++;
+    vNodes = Fraig_NodeVecAlloc( 100 );
+    Fraig_Dfs_rec( pMan, Fraig_Regular(pNode), vNodes, fEquiv );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the DFS ordering of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_DfsNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppNodes, int nNodes, int fEquiv )
+{
+    Fraig_NodeVec_t * vNodes;
+    int i;
+    pMan->nTravIds++;
+    vNodes = Fraig_NodeVecAlloc( 100 );
+    for ( i = 0; i < nNodes; i++ )
+        Fraig_Dfs_rec( pMan, Fraig_Regular(ppNodes[i]), vNodes, fEquiv );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively computes the DFS ordering of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_Dfs_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vNodes, int fEquiv )
+{
+    assert( !Fraig_IsComplement(pNode) );
+    // skip the visited node
+    if ( pNode->TravId == pMan->nTravIds )
+        return;
+    pNode->TravId = pMan->nTravIds;
+    // visit the transitive fanin
+    if ( Fraig_NodeIsAnd(pNode) )
+    {
+        Fraig_Dfs_rec( pMan, Fraig_Regular(pNode->p1), vNodes, fEquiv );
+        Fraig_Dfs_rec( pMan, Fraig_Regular(pNode->p2), vNodes, fEquiv );
+    }
+    if ( fEquiv && pNode->pNextE )
+        Fraig_Dfs_rec( pMan, pNode->pNextE, vNodes, fEquiv );
+    // save the node
+    Fraig_NodeVecPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the DFS ordering of the nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_CountNodes( Fraig_Man_t * pMan, int fEquiv )
+{
+    Fraig_NodeVec_t * vNodes;
+    int RetValue;
+    vNodes = Fraig_Dfs( pMan, fEquiv );
+    RetValue = vNodes->nSize;
+    Fraig_NodeVecFree( vNodes );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pOld is in the TFI of pNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_CheckTfi( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+    assert( !Fraig_IsComplement(pOld) );
+    assert( !Fraig_IsComplement(pNew) );
+    pMan->nTravIds++;
+    return Fraig_CheckTfi_rec( pMan, pNew, pOld );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pOld is in the TFI of pNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_CheckTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_Node_t * pOld )
+{
+    // check the trivial cases
+    if ( pNode == NULL )
+        return 0;
+    if ( pNode->Num < pOld->Num && !pMan->fChoicing )
+        return 0;
+    if ( pNode == pOld )
+        return 1;
+    // skip the visited node
+    if ( pNode->TravId == pMan->nTravIds )
+        return 0;
+    pNode->TravId = pMan->nTravIds;
+    // check the children
+    if ( Fraig_CheckTfi_rec( pMan, Fraig_Regular(pNode->p1), pOld ) )
+        return 1;
+    if ( Fraig_CheckTfi_rec( pMan, Fraig_Regular(pNode->p2), pOld ) )
+        return 1;
+    // check equivalent nodes
+    return Fraig_CheckTfi_rec( pMan, pNode->pNextE, pOld );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if pOld is in the TFI of pNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_CheckTfi2( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+    Fraig_NodeVec_t * vNodes;
+    int RetValue;
+    vNodes = Fraig_DfsOne( pMan, pNew, 1 );
+    RetValue = (pOld->TravId == pMan->nTravIds);
+    Fraig_NodeVecFree( vNodes );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the number of fanouts (none, one, or many).]
+
+  Description [This procedure collects the nodes reachable from
+  the POs of the AIG and sets the type of fanout counter (none, one,
+  or many) for each node. This procedure is useful to determine
+  fanout-free cones of AND-nodes, which is helpful for rebalancing
+  the AIG (see procedure Fraig_ManRebalance, or something like that).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_ManMarkRealFanouts( Fraig_Man_t * p )
+{
+    Fraig_NodeVec_t * vNodes;
+    Fraig_Node_t * pNodeR;
+    int i;
+    // collect the nodes reachable
+    vNodes = Fraig_Dfs( p, 0 );
+    // clean the fanouts field
+    for ( i = 0; i < vNodes->nSize; i++ )
+    {
+        vNodes->pArray[i]->nFanouts = 0;
+        vNodes->pArray[i]->pData0 = NULL;
+    }
+    // mark reachable nodes by setting the two-bit counter pNode->nFans
+    for ( i = 0; i < vNodes->nSize; i++ )
+    {
+        pNodeR = Fraig_Regular(vNodes->pArray[i]->p1);
+        if ( pNodeR && ++pNodeR->nFanouts == 3 )
+            pNodeR->nFanouts = 2;
+        pNodeR = Fraig_Regular(vNodes->pArray[i]->p2);
+        if ( pNodeR && ++pNodeR->nFanouts == 3 )
+            pNodeR->nFanouts = 2;
+    }
+    Fraig_NodeVecFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the constant 1 node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_BitStringCountOnes( unsigned * pString, int nWords )
+{
+    unsigned char * pSuppBytes = (unsigned char *)pString;
+    int i, nOnes, nBytes = sizeof(unsigned) * nWords;
+    // count the number of ones in the simulation vector
+    for ( i = nOnes = 0; i < nBytes; i++ )
+        nOnes += bit_count[pSuppBytes[i]];
+    return nOnes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verify one useful property.]
+
+  Description [This procedure verifies one useful property. After 
+  the FRAIG construction with choice nodes is over, each primary node 
+  should have fanins that are primary nodes. The primary nodes is the 
+  one that does not have pNode->pRepr set to point to another node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_ManCheckConsistency( Fraig_Man_t * p )
+{
+    Fraig_Node_t * pNode;
+    Fraig_NodeVec_t * pVec;
+    int i;
+    pVec = Fraig_Dfs( p, 0 );
+    for ( i = 0; i < pVec->nSize; i++ )
+    {
+        pNode = pVec->pArray[i];
+        if ( Fraig_NodeIsVar(pNode) )
+        {
+            if ( pNode->pRepr )
+                printf( "Primary input %d is a secondary node.\n", pNode->Num );
+        }
+        else if ( Fraig_NodeIsConst(pNode) )
+        {
+            if ( pNode->pRepr )
+                printf( "Constant 1 %d is a secondary node.\n", pNode->Num );
+        }
+        else
+        {
+            if ( pNode->pRepr )
+                printf( "Internal node %d is a secondary node.\n", pNode->Num );
+            if ( Fraig_Regular(pNode->p1)->pRepr )
+                printf( "Internal node %d has first fanin %d that is a secondary node.\n", 
+                    pNode->Num, Fraig_Regular(pNode->p1)->Num );
+            if ( Fraig_Regular(pNode->p2)->pRepr )
+                printf( "Internal node %d has second fanin %d that is a secondary node.\n", 
+                    pNode->Num, Fraig_Regular(pNode->p2)->Num );
+        }
+    }
+    Fraig_NodeVecFree( pVec );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_PrintNode( Fraig_Man_t * p, Fraig_Node_t * pNode )
+{
+    Fraig_NodeVec_t * vNodes;
+    Fraig_Node_t * pTemp;
+    int fCompl1, fCompl2, i;
+
+    vNodes = Fraig_DfsOne( p, pNode, 0 );
+    for ( i = 0; i < vNodes->nSize; i++ )
+    {
+        pTemp = vNodes->pArray[i];
+        if ( Fraig_NodeIsVar(pTemp) )
+        {
+            printf( "%3d : PI          ", pTemp->Num );
+            Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimR, 20 );
+            printf( "   " );
+            Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimD, 20 );
+            printf( "  %d\n", pTemp->fInv );
+            continue;
+        }
+
+        fCompl1 = Fraig_IsComplement(pTemp->p1);
+        fCompl2 = Fraig_IsComplement(pTemp->p2);
+        printf( "%3d : %c%3d %c%3d   ", pTemp->Num,
+            (fCompl1? '-':'+'), Fraig_Regular(pTemp->p1)->Num,
+            (fCompl2? '-':'+'), Fraig_Regular(pTemp->p2)->Num );
+        Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimR, 20 );
+        printf( "   " );
+        Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimD, 20 );
+        printf( "  %d\n", pTemp->fInv );
+    }
+    Fraig_NodeVecFree( vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the bit string.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_PrintBinary( FILE * pFile, unsigned * pSign, int nBits )
+{
+    int Remainder, nWords;
+    int w, i;
+
+    Remainder = (nBits%(sizeof(unsigned)*8));
+    nWords    = (nBits/(sizeof(unsigned)*8)) + (Remainder>0);
+
+    for ( w = nWords-1; w >= 0; w-- )
+        for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- )
+            fprintf( pFile, "%c", '0' + (int)((pSign[w] & (1<<i)) > 0) );
+
+//  fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets up the mask.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_GetMaxLevel( Fraig_Man_t * pMan )
+{
+    int nLevelMax, i;
+    nLevelMax = 0;
+    for ( i = 0; i < pMan->vOutputs->nSize; i++ )
+        nLevelMax = nLevelMax > Fraig_Regular(pMan->vOutputs->pArray[i])->Level? 
+                nLevelMax : Fraig_Regular(pMan->vOutputs->pArray[i])->Level;
+    return nLevelMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Analyses choice nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_MappingUpdateLevel_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fMaximum )
+{
+    Fraig_Node_t * pTemp;
+    int Level1, Level2, LevelE;
+    assert( !Fraig_IsComplement(pNode) );
+    if ( !Fraig_NodeIsAnd(pNode) )
+        return pNode->Level;
+    // skip the visited node
+    if ( pNode->TravId == pMan->nTravIds )
+        return pNode->Level;
+    pNode->TravId = pMan->nTravIds;
+    // compute levels of the children nodes
+    Level1 = Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pNode->p1), fMaximum );
+    Level2 = Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pNode->p2), fMaximum );
+    pNode->Level = 1 + Abc_MaxInt( Level1, Level2 );
+    if ( pNode->pNextE )
+    {
+        LevelE = Fraig_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum );
+        if ( fMaximum )
+        {
+            if ( pNode->Level < LevelE )
+                pNode->Level = LevelE;
+        }
+        else
+        {
+            if ( pNode->Level > LevelE )
+                pNode->Level = LevelE;
+        }
+        // set the level of all equivalent nodes to be the same minimum
+        if ( pNode->pRepr == NULL ) // the primary node
+            for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE )
+                pTemp->Level = pNode->Level;
+    }
+    return pNode->Level;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resets the levels of the nodes in the choice graph.]
+
+  Description [Makes the level of the choice nodes to be equal to the
+  maximum of the level of the nodes in the equivalence class. This way
+  sorting by level leads to the reverse topological order, which is
+  needed for the required time computation.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_MappingSetChoiceLevels( Fraig_Man_t * pMan, int fMaximum )
+{
+    int i;
+    pMan->nTravIds++;
+    for ( i = 0; i < pMan->vOutputs->nSize; i++ )
+        Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pMan->vOutputs->pArray[i]), fMaximum );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports statistics on choice nodes.]
+
+  Description [The number of choice nodes is the number of primary nodes,
+  which has pNextE set to a pointer. The number of choices is the number
+  of entries in the equivalent-node lists of the primary nodes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_ManReportChoices( Fraig_Man_t * pMan )
+{
+    Fraig_Node_t * pNode, * pTemp;
+    int nChoiceNodes, nChoices;
+    int i, LevelMax1, LevelMax2;
+
+    // report the number of levels
+    LevelMax1 = Fraig_GetMaxLevel( pMan );
+    Fraig_MappingSetChoiceLevels( pMan, 0 );
+    LevelMax2 = Fraig_GetMaxLevel( pMan );
+
+    // report statistics about choices
+    nChoiceNodes = nChoices = 0;
+    for ( i = 0; i < pMan->vNodes->nSize; i++ )
+    {
+        pNode = pMan->vNodes->pArray[i];
+        if ( pNode->pRepr == NULL && pNode->pNextE != NULL )
+        { // this is a choice node = the primary node that has equivalent nodes
+            nChoiceNodes++;
+            for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE )
+                nChoices++;
+        }
+    }
+    printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 );
+    printf( "Choice stats:  Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node is the root of EXOR/NEXOR gate.]
+
+  Description [The node can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeIsExorType( Fraig_Node_t * pNode )
+{
+    Fraig_Node_t * pNode1, * pNode2;
+    // make the node regular (it does not matter for EXOR/NEXOR)
+    pNode = Fraig_Regular(pNode);
+    // if the node or its children are not ANDs or not compl, this cannot be EXOR type
+    if ( !Fraig_NodeIsAnd(pNode) )
+        return 0;
+    if ( !Fraig_NodeIsAnd(pNode->p1) || !Fraig_IsComplement(pNode->p1) )
+        return 0;
+    if ( !Fraig_NodeIsAnd(pNode->p2) || !Fraig_IsComplement(pNode->p2) )
+        return 0;
+
+    // get children
+    pNode1 = Fraig_Regular(pNode->p1);
+    pNode2 = Fraig_Regular(pNode->p2);
+    assert( pNode1->Num < pNode2->Num );
+
+    // compare grandchildren
+    return pNode1->p1 == Fraig_Not(pNode2->p1) && pNode1->p2 == Fraig_Not(pNode2->p2);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node is the root of MUX or EXOR/NEXOR.]
+
+  Description [The node can be complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeIsMuxType( Fraig_Node_t * pNode )
+{
+    Fraig_Node_t * pNode1, * pNode2;
+
+    // make the node regular (it does not matter for EXOR/NEXOR)
+    pNode = Fraig_Regular(pNode);
+    // if the node or its children are not ANDs or not compl, this cannot be EXOR type
+    if ( !Fraig_NodeIsAnd(pNode) )
+        return 0;
+    if ( !Fraig_NodeIsAnd(pNode->p1) || !Fraig_IsComplement(pNode->p1) )
+        return 0;
+    if ( !Fraig_NodeIsAnd(pNode->p2) || !Fraig_IsComplement(pNode->p2) )
+        return 0;
+
+    // get children
+    pNode1 = Fraig_Regular(pNode->p1);
+    pNode2 = Fraig_Regular(pNode->p2);
+    assert( pNode1->Num < pNode2->Num );
+
+    // compare grandchildren
+    // node is an EXOR/NEXOR
+    if ( pNode1->p1 == Fraig_Not(pNode2->p1) && pNode1->p2 == Fraig_Not(pNode2->p2) )
+        return 1; 
+
+    // otherwise the node is MUX iff it has a pair of equal grandchildren
+    return pNode1->p1 == Fraig_Not(pNode2->p1) || 
+           pNode1->p1 == Fraig_Not(pNode2->p2) ||
+           pNode1->p2 == Fraig_Not(pNode2->p1) ||
+           pNode1->p2 == Fraig_Not(pNode2->p2);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node is EXOR, 0 if it is NEXOR.]
+
+  Description [The node should be EXOR type and not complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeIsExor( Fraig_Node_t * pNode )
+{
+    Fraig_Node_t * pNode1;
+    assert( !Fraig_IsComplement(pNode) );
+    assert( Fraig_NodeIsExorType(pNode) );
+    assert( Fraig_IsComplement(pNode->p1) );
+    // get children
+    pNode1 = Fraig_Regular(pNode->p1);
+    return Fraig_IsComplement(pNode1->p1) == Fraig_IsComplement(pNode1->p2);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recognizes what nodes are control and data inputs of a MUX.]
+
+  Description [If the node is a MUX, returns the control variable C.
+  Assigns nodes T and E to be the then and else variables of the MUX. 
+  Node C is never complemented. Nodes T and E can be complemented.
+  This function also recognizes EXOR/NEXOR gates as MUXes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeRecognizeMux( Fraig_Node_t * pNode, Fraig_Node_t ** ppNodeT, Fraig_Node_t ** ppNodeE )
+{
+    Fraig_Node_t * pNode1, * pNode2;
+    assert( !Fraig_IsComplement(pNode) );
+    assert( Fraig_NodeIsMuxType(pNode) );
+    // get children
+    pNode1 = Fraig_Regular(pNode->p1);
+    pNode2 = Fraig_Regular(pNode->p2);
+    // find the control variable
+    if ( pNode1->p1 == Fraig_Not(pNode2->p1) )
+    {
+        if ( Fraig_IsComplement(pNode1->p1) )
+        { // pNode2->p1 is positive phase of C
+            *ppNodeT = Fraig_Not(pNode2->p2);
+            *ppNodeE = Fraig_Not(pNode1->p2);
+            return pNode2->p1;
+        }
+        else
+        { // pNode1->p1 is positive phase of C
+            *ppNodeT = Fraig_Not(pNode1->p2);
+            *ppNodeE = Fraig_Not(pNode2->p2);
+            return pNode1->p1;
+        }
+    }
+    else if ( pNode1->p1 == Fraig_Not(pNode2->p2) )
+    {
+        if ( Fraig_IsComplement(pNode1->p1) )
+        { // pNode2->p2 is positive phase of C
+            *ppNodeT = Fraig_Not(pNode2->p1);
+            *ppNodeE = Fraig_Not(pNode1->p2);
+            return pNode2->p2;
+        }
+        else
+        { // pNode1->p1 is positive phase of C
+            *ppNodeT = Fraig_Not(pNode1->p2);
+            *ppNodeE = Fraig_Not(pNode2->p1);
+            return pNode1->p1;
+        }
+    }
+    else if ( pNode1->p2 == Fraig_Not(pNode2->p1) )
+    {
+        if ( Fraig_IsComplement(pNode1->p2) )
+        { // pNode2->p1 is positive phase of C
+            *ppNodeT = Fraig_Not(pNode2->p2);
+            *ppNodeE = Fraig_Not(pNode1->p1);
+            return pNode2->p1;
+        }
+        else
+        { // pNode1->p2 is positive phase of C
+            *ppNodeT = Fraig_Not(pNode1->p1);
+            *ppNodeE = Fraig_Not(pNode2->p2);
+            return pNode1->p2;
+        }
+    }
+    else if ( pNode1->p2 == Fraig_Not(pNode2->p2) )
+    {
+        if ( Fraig_IsComplement(pNode1->p2) )
+        { // pNode2->p2 is positive phase of C
+            *ppNodeT = Fraig_Not(pNode2->p1);
+            *ppNodeE = Fraig_Not(pNode1->p1);
+            return pNode2->p2;
+        }
+        else
+        { // pNode1->p2 is positive phase of C
+            *ppNodeT = Fraig_Not(pNode1->p1);
+            *ppNodeE = Fraig_Not(pNode2->p1);
+            return pNode1->p2;
+        }
+    }
+    assert( 0 ); // this is not MUX
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of EXOR type nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_ManCountExors( Fraig_Man_t * pMan )
+{
+    int i, nExors;
+    nExors = 0;
+    for ( i = 0; i < pMan->vNodes->nSize; i++ )
+        nExors += Fraig_NodeIsExorType( pMan->vNodes->pArray[i] );
+    return nExors;
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of EXOR type nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_ManCountMuxes( Fraig_Man_t * pMan )
+{
+    int i, nMuxes;
+    nMuxes = 0;
+    for ( i = 0; i < pMan->vNodes->nSize; i++ )
+        nMuxes += Fraig_NodeIsMuxType( pMan->vNodes->pArray[i] );
+    return nMuxes;
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if siminfo of Node1 is contained in siminfo of Node2.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeSimsContained( Fraig_Man_t * pMan, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 )
+{
+    unsigned * pUnsigned1, * pUnsigned2;
+    int i;
+
+    // compare random siminfo
+    pUnsigned1 = pNode1->puSimR;
+    pUnsigned2 = pNode2->puSimR;
+    for ( i = 0; i < pMan->nWordsRand; i++ )
+        if ( pUnsigned1[i] & ~pUnsigned2[i] )
+            return 0;
+
+    // compare systematic siminfo
+    pUnsigned1 = pNode1->puSimD;
+    pUnsigned2 = pNode2->puSimD;
+    for ( i = 0; i < pMan->iWordStart; i++ )
+        if ( pUnsigned1[i] & ~pUnsigned2[i] )
+            return 0;
+
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of PI variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_CountPis( Fraig_Man_t * p, Msat_IntVec_t * vVarNums )
+{
+    int * pVars, nVars, i, Counter;
+
+    nVars = Msat_IntVecReadSize(vVarNums);
+    pVars = Msat_IntVecReadArray(vVarNums);
+    Counter = 0;
+    for ( i = 0; i < nVars; i++ )
+        Counter += Fraig_NodeIsVar( p->vNodes->pArray[pVars[i]] );
+    return Counter;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of EXOR type nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_ManPrintRefs( Fraig_Man_t * pMan )
+{
+    Fraig_NodeVec_t * vPivots;
+    Fraig_Node_t * pNode, * pNode2;
+    int i, k, Counter, nProved;
+    abctime clk;
+
+    vPivots = Fraig_NodeVecAlloc( 1000 );
+    for ( i = 0; i < pMan->vNodes->nSize; i++ )
+    {
+        pNode = pMan->vNodes->pArray[i];
+
+        if ( pNode->nOnes == 0 || pNode->nOnes == (unsigned)pMan->nWordsRand * 32 )
+            continue;
+
+        if ( pNode->nRefs > 5 )
+        {
+            Fraig_NodeVecPush( vPivots, pNode );
+//            printf( "Node %6d : nRefs = %2d   Level = %3d.\n", pNode->Num, pNode->nRefs, pNode->Level );
+        }
+    }
+    printf( "Total nodes = %d. Referenced nodes = %d.\n", pMan->vNodes->nSize, vPivots->nSize );
+
+clk = Abc_Clock();
+    // count implications
+    Counter = nProved = 0;
+    for ( i = 0; i < vPivots->nSize; i++ )
+        for ( k = i+1; k < vPivots->nSize; k++ )
+        {
+            pNode  = vPivots->pArray[i];
+            pNode2 = vPivots->pArray[k];
+            if ( Fraig_NodeSimsContained( pMan, pNode, pNode2 ) )
+            {
+                if ( Fraig_NodeIsImplication( pMan, pNode, pNode2, -1 ) )
+                    nProved++;
+                Counter++;
+            }
+            else if ( Fraig_NodeSimsContained( pMan, pNode2, pNode ) )
+            {
+                if ( Fraig_NodeIsImplication( pMan, pNode2, pNode, -1 ) )
+                    nProved++;
+                Counter++;
+            }
+        }
+    printf( "Number of candidate pairs = %d.  Proved = %d.\n", Counter, nProved );
+//ABC_PRT( "Time", Abc_Clock() - clk );
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if pNew exists among the implication fanins of pOld.]
+
+  Description [If pNew is an implication fanin of pOld, returns 1. 
+  If Fraig_Not(pNew) is an implication fanin of pOld, return -1.
+  Otherwise returns 0.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeIsInSupergate( Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+    int RetValue1, RetValue2;
+    if ( Fraig_Regular(pOld) == Fraig_Regular(pNew) )
+        return (pOld == pNew)? 1 : -1;
+    if ( Fraig_IsComplement(pOld) || Fraig_NodeIsVar(pOld) )
+        return 0;
+    RetValue1 = Fraig_NodeIsInSupergate( pOld->p1, pNew );
+    RetValue2 = Fraig_NodeIsInSupergate( pOld->p2, pNew );
+    if ( RetValue1 == -1 || RetValue2 == -1 )
+        return -1;
+    if ( RetValue1 ==  1 || RetValue2 ==  1 )
+        return 1;
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_CollectSupergate_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, int fFirst, int fStopAtMux )
+{
+    // if the new node is complemented or a PI, another gate begins
+//    if ( Fraig_IsComplement(pNode) || Fraig_NodeIsVar(pNode) || Fraig_NodeIsMuxType(pNode) )
+    if ( (!fFirst && Fraig_Regular(pNode)->nRefs > 1) || 
+          Fraig_IsComplement(pNode) || Fraig_NodeIsVar(pNode) || 
+          (fStopAtMux && Fraig_NodeIsMuxType(pNode)) )
+    {
+        Fraig_NodeVecPushUnique( vSuper, pNode );
+        return;
+    }
+    // go through the branches
+    Fraig_CollectSupergate_rec( pNode->p1, vSuper, 0, fStopAtMux );
+    Fraig_CollectSupergate_rec( pNode->p2, vSuper, 0, fStopAtMux );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux )
+{
+    Fraig_NodeVec_t * vSuper;
+    vSuper = Fraig_NodeVecAlloc( 8 );
+    Fraig_CollectSupergate_rec( pNode, vSuper, 1, fStopAtMux );
+    return vSuper;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_ManIncrementTravId( Fraig_Man_t * pMan )
+{
+    pMan->nTravIds2++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeSetTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+    pNode->TravId2 = pMan->nTravIds2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeIsTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+    return pNode->TravId2 == pMan->nTravIds2;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeIsTravIdPrevious( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+    return pNode->TravId2 == pMan->nTravIds2 - 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fraig/fraigVec.c b/abc-build/src/proof/fraig/fraigVec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fraig/fraigVec.c
@@ -0,0 +1,550 @@
+/**CFile****************************************************************
+
+  FileName    [fraigVec.c]
+
+  PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+  Synopsis    [Vector of FRAIG nodes.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 2.0. Started - October 1, 2004]
+
+  Revision    [$Id: fraigVec.c,v 1.7 2005/07/08 01:01:34 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_NodeVecAlloc( int nCap )
+{
+    Fraig_NodeVec_t * p;
+    p = ABC_ALLOC( Fraig_NodeVec_t, 1 );
+    if ( nCap > 0 && nCap < 8 )
+        nCap = 8;
+    p->nSize  = 0;
+    p->nCap   = nCap;
+    p->pArray = p->nCap? ABC_ALLOC( Fraig_Node_t *, p->nCap ) : NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeVecFree( Fraig_NodeVec_t * p )
+{
+    ABC_FREE( p->pArray );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the integer array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_NodeVecDup( Fraig_NodeVec_t * pVec )
+{
+    Fraig_NodeVec_t * p;
+    p = ABC_ALLOC( Fraig_NodeVec_t, 1 );
+    p->nSize  = pVec->nSize;
+    p->nCap   = pVec->nCap;
+    p->pArray = p->nCap? ABC_ALLOC( Fraig_Node_t *, p->nCap ) : NULL;
+    memcpy( p->pArray, pVec->pArray, sizeof(Fraig_Node_t *) * pVec->nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Node_t ** Fraig_NodeVecReadArray( Fraig_NodeVec_t * p )
+{
+    return p->pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeVecReadSize( Fraig_NodeVec_t * p )
+{
+    return p->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the vector to the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeVecGrow( Fraig_NodeVec_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pArray = ABC_REALLOC( Fraig_Node_t *, p->pArray, nCapMin ); 
+    p->nCap   = nCapMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeVecShrink( Fraig_NodeVec_t * p, int nSizeNew )
+{
+    assert( p->nSize >= nSizeNew );
+    p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeVecClear( Fraig_NodeVec_t * p )
+{
+    p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeVecPush( Fraig_NodeVec_t * p, Fraig_Node_t * Entry )
+{
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Fraig_NodeVecGrow( p, 16 );
+        else
+            Fraig_NodeVecGrow( p, 2 * p->nCap );
+    }
+    p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add the element while ensuring uniqueness.]
+
+  Description [Returns 1 if the element was found, and 0 if it was new. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeVecPushUnique( Fraig_NodeVec_t * p, Fraig_Node_t * Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            return 1;
+    Fraig_NodeVecPush( p, Entry );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts a new node in the order by arrival times.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeVecPushOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode )
+{
+    Fraig_Node_t * pNode1, * pNode2;
+    int i;
+    Fraig_NodeVecPush( p, pNode );
+    // find the p of the node
+    for ( i = p->nSize-1; i > 0; i-- )
+    {
+        pNode1 = p->pArray[i  ];
+        pNode2 = p->pArray[i-1];
+        if ( pNode1 >= pNode2 )
+            break;
+        p->pArray[i  ] = pNode2;
+        p->pArray[i-1] = pNode1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add the element while ensuring uniqueness in the order.]
+
+  Description [Returns 1 if the element was found, and 0 if it was new. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeVecPushUniqueOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == pNode )
+            return 1;
+    Fraig_NodeVecPushOrder( p, pNode );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts a new node in the order by arrival times.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeVecPushOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode )
+{
+    Fraig_Node_t * pNode1, * pNode2;
+    int i;
+    Fraig_NodeVecPush( p, pNode );
+    // find the p of the node
+    for ( i = p->nSize-1; i > 0; i-- )
+    {
+        pNode1 = p->pArray[i  ];
+        pNode2 = p->pArray[i-1];
+        if ( Fraig_Regular(pNode1)->Level <= Fraig_Regular(pNode2)->Level )
+            break;
+        p->pArray[i  ] = pNode2;
+        p->pArray[i-1] = pNode1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add the element while ensuring uniqueness in the order.]
+
+  Description [Returns 1 if the element was found, and 0 if it was new. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeVecPushUniqueOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == pNode )
+            return 1;
+    Fraig_NodeVecPushOrderByLevel( p, pNode );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeVecPop( Fraig_NodeVec_t * p )
+{
+    return p->pArray[--p->nSize];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeVecRemove( Fraig_NodeVec_t * p, Fraig_Node_t * Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            break;
+    assert( i < p->nSize );
+    for ( i++; i < p->nSize; i++ )
+        p->pArray[i-1] = p->pArray[i];
+    p->nSize--;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeVecWriteEntry( Fraig_NodeVec_t * p, int i, Fraig_Node_t * Entry )
+{
+    assert( i >= 0 && i < p->nSize );
+    p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeVecReadEntry( Fraig_NodeVec_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeVecCompareLevelsIncreasing( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 )
+{
+    int Level1 = Fraig_Regular(*pp1)->Level;
+    int Level2 = Fraig_Regular(*pp2)->Level;
+    if ( Level1 < Level2 )
+        return -1;
+    if ( Level1 > Level2 )
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeVecCompareLevelsDecreasing( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 )
+{
+    int Level1 = Fraig_Regular(*pp1)->Level;
+    int Level2 = Fraig_Regular(*pp2)->Level;
+    if ( Level1 > Level2 )
+        return -1;
+    if ( Level1 < Level2 )
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeVecCompareNumbers( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 )
+{
+    int Num1 = Fraig_Regular(*pp1)->Num;
+    int Num2 = Fraig_Regular(*pp2)->Num;
+    if ( Num1 < Num2 )
+        return -1;
+    if ( Num1 > Num2 )
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Fraig_NodeVecCompareRefCounts( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 )
+{
+    int nRefs1 = Fraig_Regular(*pp1)->nRefs;
+    int nRefs2 = Fraig_Regular(*pp2)->nRefs;
+
+    if ( nRefs1 < nRefs2 )
+        return -1;
+    if ( nRefs1 > nRefs2 )
+        return 1;
+
+    nRefs1 = Fraig_Regular(*pp1)->Level;
+    nRefs2 = Fraig_Regular(*pp2)->Level;
+
+    if ( nRefs1 < nRefs2 )
+        return -1;
+    if ( nRefs1 > nRefs2 )
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting the entries by their integer value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeVecSortByLevel( Fraig_NodeVec_t * p, int fIncreasing )
+{
+    if ( fIncreasing )
+        qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), 
+                (int (*)(const void *, const void *)) Fraig_NodeVecCompareLevelsIncreasing );
+    else 
+        qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), 
+                (int (*)(const void *, const void *)) Fraig_NodeVecCompareLevelsDecreasing );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting the entries by their integer value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeVecSortByNumber( Fraig_NodeVec_t * p )
+{
+    qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), 
+            (int (*)(const void *, const void *)) Fraig_NodeVecCompareNumbers );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting the entries by their integer value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Fraig_NodeVecSortByRefCount( Fraig_NodeVec_t * p )
+{
+    qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), 
+            (int (*)(const void *, const void *)) Fraig_NodeVecCompareRefCounts );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/fraig/module.make b/abc-build/src/proof/fraig/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/fraig/module.make
@@ -0,0 +1,12 @@
+SRC +=  src/proof/fraig/fraigApi.c \
+	src/proof/fraig/fraigCanon.c \
+	src/proof/fraig/fraigFanout.c \
+	src/proof/fraig/fraigFeed.c \
+	src/proof/fraig/fraigMan.c \
+	src/proof/fraig/fraigMem.c \
+	src/proof/fraig/fraigNode.c \
+	src/proof/fraig/fraigPrime.c \
+	src/proof/fraig/fraigSat.c \
+	src/proof/fraig/fraigTable.c \
+	src/proof/fraig/fraigUtil.c \
+	src/proof/fraig/fraigVec.c
diff --git a/abc-build/src/proof/int/int.h b/abc-build/src/proof/int/int.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int/int.h
@@ -0,0 +1,96 @@
+/**CFile****************************************************************
+
+  FileName    [int.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 24, 2008.]
+
+  Revision    [$Id: int.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__int__int_h
+#define ABC__aig__int__int_h
+
+
+/* 
+    The interpolation algorithm implemented here was introduced in the paper:
+    K. L. McMillan. Interpolation and SAT-based model checking. CAV03, pp. 1-13.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// simulation manager
+typedef struct Inter_ManParams_t_ Inter_ManParams_t;
+struct Inter_ManParams_t_
+{
+    int  nBTLimit;      // limit on the number of conflicts
+    int  nFramesMax;    // the max number timeframes to unroll
+    int  nSecLimit;     // time limit in seconds
+    int  nFramesK;      // the number of timeframes to use in induction
+    int  fRewrite;      // use additional rewriting to simplify timeframes
+    int  fTransLoop;    // add transition into the init state under new PI var
+    int  fUsePudlak;    // use Pudluk interpolation procedure
+    int  fUseOther;     // use other undisclosed option
+    int  fUseMiniSat;   // use MiniSat-1.14p instead of internal proof engine
+    int  fCheckKstep;   // check using K-step induction
+    int  fUseBias;      // bias decisions to global variables
+    int  fUseBackward;  // perform backward interpolation
+    int  fUseSeparate;  // solve each output separately
+    int  fUseTwoFrames; // create the OR of two last timeframes
+    int  fDropSatOuts;  // replace by 1 the solved outputs
+    int  fDropInvar;    // dump inductive invariant into file
+    int  fVerbose;      // print verbose statistics
+    int  iFrameMax;     // the time frame reached
+    char * pFileName;   // file name to dump interpolant
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== intCore.c ==========================================================*/
+extern void       Inter_ManSetDefaultParams( Inter_ManParams_t * p );
+extern int        Inter_ManPerformInterpolation( Aig_Man_t * pAig, Inter_ManParams_t * pPars, int * piFrame );
+
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/int/intCheck.c b/abc-build/src/proof/int/intCheck.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int/intCheck.c
@@ -0,0 +1,305 @@
+/**CFile****************************************************************
+
+  FileName    [intCheck.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [Procedures to perform incremental inductive check.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 24, 2008.]
+
+  Revision    [$Id: intCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// checking manager
+struct Inter_Check_t_
+{
+    int           nFramesK;     // the number of timeframes (K=1 for simple induction)
+    int           nVars;        // the current number of variables in the solver
+    Aig_Man_t *   pFrames;      // unrolled timeframes
+    Cnf_Dat_t *   pCnf;         // CNF of unrolled timeframes 
+    sat_solver *  pSat;         // SAT solver 
+    Vec_Int_t *   vOrLits;      // OR vars in each time frame (total number is the number nFrames)
+    Vec_Int_t *   vAndLits;     // AND vars in the last timeframe (total number is the number of interpolants)
+    Vec_Int_t *   vAssLits;     // assumptions (the union of the two)
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Create timeframes of the manager for interpolation.]
+
+  Description [The resulting manager is combinational. The primary inputs
+  corresponding to register outputs are ordered first.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManUnrollFrames( Aig_Man_t * pAig, int nFrames )
+{
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i, f;
+    assert( Saig_ManRegNum(pAig) > 0 );
+    pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames );
+    // map the constant node
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames );
+    // create variables for register outputs
+    Saig_ManForEachLo( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pFrames );
+    // add timeframes
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // create PI nodes for this frame
+        Saig_ManForEachPi( pAig, pObj, i )
+            pObj->pData = Aig_ObjCreateCi( pFrames );
+        // add internal nodes of this frame
+        Aig_ManForEachNode( pAig, pObj, i )
+            pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+        // save register inputs
+        Saig_ManForEachLi( pAig, pObj, i )
+            pObj->pData = Aig_ObjChild0Copy(pObj);
+        // transfer to register outputs
+        Saig_ManForEachLiLo(  pAig, pObjLi, pObjLo, i )
+        {
+            pObjLo->pData = pObjLi->pData;
+            Aig_ObjCreateCo( pFrames, (Aig_Obj_t *)pObjLo->pData );
+        }
+    }
+    Aig_ManCleanup( pFrames );
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default values of interpolation parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Inter_Check_t * Inter_CheckStart( Aig_Man_t * pTrans, int nFramesK )
+{
+    Inter_Check_t * p;
+    // create solver
+    p = ABC_CALLOC( Inter_Check_t, 1 );
+    p->vOrLits  = Vec_IntAlloc( 100 );
+    p->vAndLits = Vec_IntAlloc( 100 );
+    p->vAssLits = Vec_IntAlloc( 100 );
+    // generate the timeframes 
+    p->pFrames = Inter_ManUnrollFrames( pTrans, nFramesK );
+    assert( Aig_ManCiNum(p->pFrames) == nFramesK * Saig_ManPiNum(pTrans) + Saig_ManRegNum(pTrans) );
+    assert( Aig_ManCoNum(p->pFrames) == nFramesK * Saig_ManRegNum(pTrans) );
+    // convert to CNF
+    p->pCnf = Cnf_Derive( p->pFrames, Aig_ManCoNum(p->pFrames) ); 
+    p->pSat = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 );
+    // assign parameters
+    p->nFramesK = nFramesK;
+    p->nVars    = p->pCnf->nVars;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default values of interpolation parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Inter_CheckStop( Inter_Check_t * p )
+{
+    if ( p == NULL )
+        return;
+    Vec_IntFree( p->vOrLits );
+    Vec_IntFree( p->vAndLits );
+    Vec_IntFree( p->vAssLits );
+    Cnf_DataFree( p->pCnf );
+    Aig_ManStop( p->pFrames );
+    sat_solver_delete( p->pSat );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates one OR-gate: A + B = C.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Inter_CheckAddOrGate( Inter_Check_t * p, int iVarA, int iVarB, int iVarC )
+{
+    int RetValue, pLits[3];
+    // add A => C   or   !A + C
+    pLits[0] = toLitCond(iVarA, 1);
+    pLits[1] = toLitCond(iVarC, 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+    assert( RetValue );
+    // add B => C   or   !B + C
+    pLits[0] = toLitCond(iVarB, 1);
+    pLits[1] = toLitCond(iVarC, 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+    assert( RetValue );
+    // add !A & !B => !C  or A + B + !C
+    pLits[0] = toLitCond(iVarA, 0);
+    pLits[1] = toLitCond(iVarB, 0);
+    pLits[2] = toLitCond(iVarC, 1);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates equality: A = B.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Inter_CheckAddEqual( Inter_Check_t * p, int iVarA, int iVarB )
+{
+    int RetValue, pLits[3];
+    // add A => B   or   !A + B
+    pLits[0] = toLitCond(iVarA, 1);
+    pLits[1] = toLitCond(iVarB, 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+    assert( RetValue );
+    // add B => A   or   !B + A
+    pLits[0] = toLitCond(iVarB, 1);
+    pLits[1] = toLitCond(iVarA, 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+    assert( RetValue );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform the checking.]
+
+  Description [Returns 1 if the check has passed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Inter_CheckPerform( Inter_Check_t * p, Cnf_Dat_t * pCnfInt, abctime nTimeNewOut )
+{
+    Aig_Obj_t * pObj, * pObj2;
+    int i, f, VarA, VarB, RetValue, Entry, status;
+    int nRegs = Aig_ManCiNum(pCnfInt->pMan);
+    assert( Aig_ManCoNum(p->pCnf->pMan) == p->nFramesK * nRegs );
+    assert( Aig_ManCoNum(pCnfInt->pMan) == 1 );
+
+    // set runtime limit
+    if ( nTimeNewOut )
+        sat_solver_set_runtime_limit( p->pSat, nTimeNewOut );
+
+    // add clauses to the SAT solver
+    Cnf_DataLift( pCnfInt, p->nVars );
+    for ( f = 0; f <= p->nFramesK; f++ )
+    {
+        // add clauses to the solver
+        for ( i = 0; i < pCnfInt->nClauses; i++ )
+        {
+            RetValue = sat_solver_addclause( p->pSat, pCnfInt->pClauses[i], pCnfInt->pClauses[i+1] );
+            assert( RetValue );
+        }
+        // add equality clauses for the flop variables
+        Aig_ManForEachCi( pCnfInt->pMan, pObj, i )
+        {
+            pObj2 = f ? Aig_ManCo(p->pFrames, i + (f-1) * nRegs) : Aig_ManCi(p->pFrames, i);
+            Inter_CheckAddEqual( p, pCnfInt->pVarNums[pObj->Id], p->pCnf->pVarNums[pObj2->Id] );
+        }
+        // add final clauses
+        if ( f < p->nFramesK )
+        {
+            if ( f == Vec_IntSize(p->vOrLits) ) // find time here
+            {
+                // add literal to this frame
+                VarB = pCnfInt->pVarNums[ Aig_ManCo(pCnfInt->pMan, 0)->Id ];
+                Vec_IntPush( p->vOrLits, VarB );
+            }
+            else
+            {
+                // add OR gate for this frame
+                VarA = Vec_IntEntry( p->vOrLits, f );
+                VarB = pCnfInt->pVarNums[ Aig_ManCo(pCnfInt->pMan, 0)->Id ];
+                Inter_CheckAddOrGate( p, VarA, VarB, p->nVars + pCnfInt->nVars );
+                Vec_IntWriteEntry( p->vOrLits, f, p->nVars + pCnfInt->nVars ); // using var ID!
+            }
+        }
+        else
+        {
+            // add AND gate for this frame
+            VarB = pCnfInt->pVarNums[ Aig_ManCo(pCnfInt->pMan, 0)->Id ];
+            Vec_IntPush( p->vAndLits, VarB );
+        }
+        // update variable IDs
+        Cnf_DataLift( pCnfInt, pCnfInt->nVars + 1 );
+        p->nVars += pCnfInt->nVars + 1;
+    }
+    Cnf_DataLift( pCnfInt, -p->nVars );
+    assert( Vec_IntSize(p->vOrLits) == p->nFramesK );
+
+    // collect the assumption literals
+    Vec_IntClear( p->vAssLits );
+    Vec_IntForEachEntry( p->vOrLits, Entry, i )
+        Vec_IntPush( p->vAssLits, toLitCond(Entry, 0) );
+    Vec_IntForEachEntry( p->vAndLits, Entry, i )
+        Vec_IntPush( p->vAssLits, toLitCond(Entry, 1) );
+/*
+    if ( pCnfInt->nLiterals == 3635 )
+    {
+        int s = 0;
+    }
+*/
+    // call the SAT solver
+    status = sat_solver_solve( p->pSat, Vec_IntArray(p->vAssLits), 
+        Vec_IntArray(p->vAssLits) + Vec_IntSize(p->vAssLits), 
+        (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+
+    return status == l_False;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/int/intContain.c b/abc-build/src/proof/int/intContain.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int/intContain.c
@@ -0,0 +1,341 @@
+/**CFile****************************************************************
+
+  FileName    [intContain.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [Interpolant containment checking.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 24, 2008.]
+
+  Revision    [$Id: intContain.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+#include "proof/fra/fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Inter_ManCheckUniqueness( Aig_Man_t * p, sat_solver * pSat, Cnf_Dat_t * pCnf, int nFrames );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Checks constainment of two interpolants.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Inter_ManCheckContainment( Aig_Man_t * pNew, Aig_Man_t * pOld )
+{
+    Aig_Man_t * pMiter, * pAigTemp;
+    int RetValue;
+    pMiter = Aig_ManCreateMiter( pNew, pOld, 1 );
+//    pMiter = Dar_ManRwsat( pAigTemp = pMiter, 1, 0 );
+//    Aig_ManStop( pAigTemp );
+    RetValue = Fra_FraigMiterStatus( pMiter );
+    if ( RetValue == -1 )
+    {
+        pAigTemp = Fra_FraigEquivence( pMiter, 1000000, 1 );
+        RetValue = Fra_FraigMiterStatus( pAigTemp );
+        Aig_ManStop( pAigTemp );
+//        RetValue = Fra_FraigSat( pMiter, 1000000, 0, 0, 0, 0, 0, 0 );
+    }
+    assert( RetValue != -1 );
+    Aig_ManStop( pMiter );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks constainment of two interpolants.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Inter_ManCheckEquivalence( Aig_Man_t * pNew, Aig_Man_t * pOld )
+{
+    Aig_Man_t * pMiter, * pAigTemp;
+    int RetValue;
+    pMiter = Aig_ManCreateMiter( pNew, pOld, 0 );
+//    pMiter = Dar_ManRwsat( pAigTemp = pMiter, 1, 0 );
+//    Aig_ManStop( pAigTemp );
+    RetValue = Fra_FraigMiterStatus( pMiter );
+    if ( RetValue == -1 )
+    {
+        pAigTemp = Fra_FraigEquivence( pMiter, 1000000, 1 );
+        RetValue = Fra_FraigMiterStatus( pAigTemp );
+        Aig_ManStop( pAigTemp );
+//        RetValue = Fra_FraigSat( pMiter, 1000000, 0, 0, 0, 0, 0, 0 );
+    }
+    assert( RetValue != -1 );
+    Aig_ManStop( pMiter );
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Create timeframes of the manager for interpolation.]
+
+  Description [The resulting manager is combinational. The primary inputs
+  corresponding to register outputs are ordered first.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManFramesLatches( Aig_Man_t * pAig, int nFrames, Vec_Ptr_t ** pvMapReg )
+{
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i, f;
+    assert( Saig_ManRegNum(pAig) > 0 );
+    pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames );
+    // map the constant node
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames );
+    // create variables for register outputs
+    *pvMapReg = Vec_PtrAlloc( (nFrames+1) * Saig_ManRegNum(pAig) );
+    Saig_ManForEachLo( pAig, pObj, i )
+    {
+        pObj->pData = Aig_ObjCreateCi( pFrames );
+        Vec_PtrPush( *pvMapReg, pObj->pData );
+    }
+    // add timeframes
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // create PI nodes for this frame
+        Saig_ManForEachPi( pAig, pObj, i )
+            pObj->pData = Aig_ObjCreateCi( pFrames );
+        // add internal nodes of this frame
+        Aig_ManForEachNode( pAig, pObj, i )
+            pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+        // save register inputs
+        Saig_ManForEachLi( pAig, pObj, i )
+            pObj->pData = Aig_ObjChild0Copy(pObj);
+        // transfer to register outputs
+        Saig_ManForEachLiLo(  pAig, pObjLi, pObjLo, i )
+        {
+            pObjLo->pData = pObjLi->pData;
+            Vec_PtrPush( *pvMapReg, pObjLo->pData );
+        }
+    }
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates AIG while mapping PIs into the given array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Inter_ManAppendCone( Aig_Man_t * pOld, Aig_Man_t * pNew, Aig_Obj_t ** ppNewPis, int fCompl )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    assert( Aig_ManCoNum(pOld) == 1 );
+    // create the PIs
+    Aig_ManCleanData( pOld );
+    Aig_ManConst1(pOld)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( pOld, pObj, i )
+        pObj->pData = ppNewPis[i];
+    // duplicate internal nodes
+    Aig_ManForEachNode( pOld, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // add one PO to new
+    pObj = Aig_ManCo( pOld, 0 );
+    Aig_ObjCreateCo( pNew, Aig_NotCond( Aig_ObjChild0Copy(pObj), fCompl ) );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks constainment of two interpolants inductively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Inter_ManCheckInductiveContainment( Aig_Man_t * pTrans, Aig_Man_t * pInter, int nSteps, int fBackward )
+{
+    Aig_Man_t * pFrames;
+    Aig_Obj_t ** ppNodes;
+    Vec_Ptr_t * vMapRegs;
+    Cnf_Dat_t * pCnf;
+    sat_solver * pSat;
+    int f, nRegs, status;
+    nRegs = Saig_ManRegNum(pTrans);
+    assert( nRegs > 0 );
+    // generate the timeframes 
+    pFrames = Inter_ManFramesLatches( pTrans, nSteps, &vMapRegs );
+    assert( Vec_PtrSize(vMapRegs) == (nSteps + 1) * nRegs );
+    // add main constraints to the timeframes
+    ppNodes = (Aig_Obj_t **)Vec_PtrArray(vMapRegs);
+    if ( !fBackward )
+    { 
+        // forward inductive check: p -> p -> ... -> !p
+        for ( f = 0; f < nSteps; f++ )
+            Inter_ManAppendCone( pInter, pFrames, ppNodes + f * nRegs, 0 );
+        Inter_ManAppendCone( pInter, pFrames, ppNodes + f * nRegs, 1 );
+    }
+    else
+    {
+        // backward inductive check: p -> !p -> ... -> !p
+        Inter_ManAppendCone( pInter, pFrames, ppNodes + 0 * nRegs, 1 );
+        for ( f = 1; f <= nSteps; f++ )
+            Inter_ManAppendCone( pInter, pFrames, ppNodes + f * nRegs, 0 );
+    }
+    Vec_PtrFree( vMapRegs );
+    Aig_ManCleanup( pFrames );
+
+    // convert to CNF
+    pCnf = Cnf_Derive( pFrames, 0 ); 
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+//    Cnf_DataFree( pCnf );
+//    Aig_ManStop( pFrames );
+
+    if ( pSat == NULL )
+    {
+        Cnf_DataFree( pCnf );
+        Aig_ManStop( pFrames );
+        return 1;
+    }
+
+     // solve the problem
+    status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+
+//    Inter_ManCheckUniqueness( pTrans, pSat, pCnf, nSteps );
+
+    Cnf_DataFree( pCnf );
+    Aig_ManStop( pFrames );
+
+    sat_solver_delete( pSat );
+    return status == l_False;
+}
+ABC_NAMESPACE_IMPL_END
+
+#include "proof/fra/fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/**Function*************************************************************
+
+  Synopsis    [Check if cex satisfies uniqueness constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Inter_ManCheckUniqueness( Aig_Man_t * p, sat_solver * pSat, Cnf_Dat_t * pCnf, int nFrames )
+{
+    extern int Fra_SmlNodesCompareInFrame( Fra_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int iFrame0, int iFrame1 );
+    extern void Fra_SmlAssignConst( Fra_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame );
+    extern void Fra_SmlSimulateOne( Fra_Sml_t * p );
+
+    Fra_Sml_t * pSml;
+    Vec_Int_t * vPis;
+    Aig_Obj_t * pObj, * pObj0;
+    int i, k, v, iBit, * pCounterEx;
+    int Counter;
+    if ( nFrames == 1 )
+        return 1;
+//    if ( pSat->model.size == 0 )
+    
+    // possible consequences here!!!
+    assert( 0 );
+
+    if ( sat_solver_nvars(pSat) == 0 )
+        return 1;
+//    assert( Saig_ManPoNum(p) == 1 );
+    assert( Aig_ManRegNum(p) > 0 );
+    assert( Aig_ManRegNum(p) < Aig_ManCiNum(p) );
+
+    // get the counter-example
+    vPis = Vec_IntAlloc( 100 );
+    Aig_ManForEachCi( pCnf->pMan, pObj, k )
+        Vec_IntPush( vPis, pCnf->pVarNums[Aig_ObjId(pObj)] );
+    assert( Vec_IntSize(vPis) == Aig_ManRegNum(p) + nFrames * Saig_ManPiNum(p) );
+    pCounterEx = Sat_SolverGetModel( pSat, vPis->pArray, vPis->nSize );
+    Vec_IntFree( vPis );
+
+    // start a new sequential simulator
+    pSml = Fra_SmlStart( p, 0, nFrames, 1 );
+    // assign simulation info for the registers
+    iBit = 0;
+    Aig_ManForEachLoSeq( p, pObj, i )
+        Fra_SmlAssignConst( pSml, pObj, pCounterEx[iBit++], 0 );
+    // assign simulation info for the primary inputs
+    for ( i = 0; i < nFrames; i++ )
+        Aig_ManForEachPiSeq( p, pObj, k )
+            Fra_SmlAssignConst( pSml, pObj, pCounterEx[iBit++], i );
+    assert( iBit == Aig_ManCiNum(pCnf->pMan) );
+    // run simulation
+    Fra_SmlSimulateOne( pSml );
+
+    // check if the given output has failed
+//    RetValue = !Fra_SmlNodeIsZero( pSml, Aig_ManCo(pAig, 0) );
+//    assert( RetValue );
+
+    // check values at the internal nodes
+    Counter = 0;
+    for ( i = 0; i < nFrames; i++ )
+    for ( k = i+1; k < nFrames; k++ )
+    {
+        for ( v = 0; v < Aig_ManRegNum(p); v++ )
+        {
+            pObj0 = Aig_ManLo(p, v);
+            if ( !Fra_SmlNodesCompareInFrame( pSml, pObj0, pObj0, i, k ) )
+                break;
+        }
+        if ( v == Aig_ManRegNum(p) )
+            Counter++;
+    }
+    printf( "Uniquness does not hold in %d frames.\n", Counter );
+
+    Fra_SmlStop( pSml );
+    ABC_FREE( pCounterEx );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/int/intCore.c b/abc-build/src/proof/int/intCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int/intCore.c
@@ -0,0 +1,412 @@
+/**CFile****************************************************************
+
+  FileName    [intCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [Core procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 24, 2008.]
+
+  Revision    [$Id: intCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+#include "sat/bmc/bmc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////`
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default values of interpolation parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Inter_ManSetDefaultParams( Inter_ManParams_t * p )
+{ 
+    memset( p, 0, sizeof(Inter_ManParams_t) );
+    p->nBTLimit      = 0;     // limit on the number of conflicts
+    p->nFramesMax    = 0;     // the max number timeframes to unroll
+    p->nSecLimit     = 0;     // time limit in seconds
+    p->nFramesK      = 1;     // the number of timeframes to use in induction
+    p->fRewrite      = 0;     // use additional rewriting to simplify timeframes
+    p->fTransLoop    = 0;     // add transition into the init state under new PI var
+    p->fUsePudlak    = 0;     // use Pudluk interpolation procedure
+    p->fUseOther     = 0;     // use other undisclosed option
+    p->fUseMiniSat   = 0;     // use MiniSat-1.14p instead of internal proof engine
+    p->fCheckKstep   = 1;     // check using K-step induction
+    p->fUseBias      = 0;     // bias decisions to global variables
+    p->fUseBackward  = 0;     // perform backward interpolation
+    p->fUseSeparate  = 0;     // solve each output separately
+    p->fUseTwoFrames = 0;     // create OR of two last timeframes
+    p->fDropSatOuts  = 0;     // replace by 1 the solved outputs
+    p->fVerbose      = 0;     // print verbose statistics
+    p->iFrameMax     =-1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Interplates while the number of conflicts is not exceeded.]
+
+  Description [Returns 1 if proven. 0 if failed. -1 if undecided.]
+               
+  SideEffects [Does not check the property in 0-th frame.]
+
+  SeeAlso     []
+
+***********************************************************************/
+int Inter_ManPerformInterpolation( Aig_Man_t * pAig, Inter_ManParams_t * pPars, int * piFrame )
+{
+    extern int Inter_ManCheckInductiveContainment( Aig_Man_t * pTrans, Aig_Man_t * pInter, int nSteps, int fBackward );
+    Inter_Man_t * p;
+    Inter_Check_t * pCheck = NULL;
+    Aig_Man_t * pAigTemp;
+    int s, i, RetValue, Status;
+    abctime clk, clk2, clkTotal = Abc_Clock(), timeTemp = 0;
+    abctime nTimeNewOut = pPars->nSecLimit ? pPars->nSecLimit * CLOCKS_PER_SEC + Abc_Clock() : 0;
+
+    // enable ORing of the interpolants, if containment check is performed inductively with K > 1
+    if ( pPars->nFramesK > 1 )
+        pPars->fTransLoop = 1;
+
+    // sanity checks
+    assert( Saig_ManRegNum(pAig) > 0 );
+    assert( Saig_ManPiNum(pAig) > 0 );
+    assert( Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) == 1 );
+    if ( pPars->fVerbose && Saig_ManConstrNum(pAig) )
+        printf( "Performing interpolation with %d constraints...\n", Saig_ManConstrNum(pAig) );
+
+    if ( Inter_ManCheckInitialState(pAig) )
+    {
+        *piFrame = -1;
+        printf( "Property trivially fails in the initial state.\n" );
+        return 0;
+    }
+/*
+    if ( Inter_ManCheckAllStates(pAig) )
+    {
+        printf( "Property trivially holds in all states.\n" );
+        return 1;
+    }
+*/
+    // create interpolation manager
+    // can perform SAT sweeping and/or rewriting of this AIG...
+    p = Inter_ManCreate( pAig, pPars );
+    if ( pPars->fTransLoop )
+        p->pAigTrans = Inter_ManStartOneOutput( pAig, 0 );
+    else
+        p->pAigTrans = Inter_ManStartDuplicated( pAig );
+    // derive CNF for the transformed AIG
+clk = Abc_Clock();
+    p->pCnfAig = Cnf_Derive( p->pAigTrans, Aig_ManRegNum(p->pAigTrans) ); 
+p->timeCnf += Abc_Clock() - clk;    
+    if ( pPars->fVerbose )
+    { 
+        printf( "AIG: PI/PO/Reg = %d/%d/%d. And = %d. Lev = %d.  CNF: Var/Cla = %d/%d.\n",
+            Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig), 
+            Aig_ManAndNum(pAig), Aig_ManLevelNum(pAig),
+            p->pCnfAig->nVars, p->pCnfAig->nClauses );
+    }
+ 
+    // derive interpolant
+    *piFrame = -1;
+    p->nFrames = 1;
+    for ( s = 0; ; s++ )
+    {
+        Cnf_Dat_t * pCnfInter2;
+
+clk2 = Abc_Clock();
+        // initial state
+        if ( pPars->fUseBackward )
+            p->pInter = Inter_ManStartOneOutput( pAig, 1 );
+        else
+            p->pInter = Inter_ManStartInitState( Aig_ManRegNum(pAig) );
+        assert( Aig_ManCoNum(p->pInter) == 1 );
+clk = Abc_Clock();
+        p->pCnfInter = Cnf_Derive( p->pInter, 0 );  
+p->timeCnf += Abc_Clock() - clk;    
+        // timeframes
+        p->pFrames = Inter_ManFramesInter( pAig, p->nFrames, pPars->fUseBackward, pPars->fUseTwoFrames );
+clk = Abc_Clock();
+        if ( pPars->fRewrite )
+        {
+            p->pFrames = Dar_ManRwsat( pAigTemp = p->pFrames, 1, 0 );
+            Aig_ManStop( pAigTemp );
+//        p->pFrames = Fra_FraigEquivence( pAigTemp = p->pFrames, 100, 0 );
+//        Aig_ManStop( pAigTemp );
+        }
+p->timeRwr += Abc_Clock() - clk;
+        // can also do SAT sweeping on the timeframes...
+clk = Abc_Clock();
+        if ( pPars->fUseBackward )
+            p->pCnfFrames = Cnf_Derive( p->pFrames, Aig_ManCoNum(p->pFrames) );  
+        else
+//            p->pCnfFrames = Cnf_Derive( p->pFrames, 0 );  
+            p->pCnfFrames = Cnf_DeriveSimple( p->pFrames, 0 );  
+p->timeCnf += Abc_Clock() - clk;    
+        // report statistics
+        if ( pPars->fVerbose )
+        {
+            printf( "Step = %2d. Frames = 1 + %d. And = %5d. Lev = %5d.  ", 
+                s+1, p->nFrames, Aig_ManNodeNum(p->pFrames), Aig_ManLevelNum(p->pFrames) );
+            ABC_PRT( "Time", Abc_Clock() - clk2 );
+        }
+
+
+        //////////////////////////////////////////
+        // start containment checking
+        if ( !(pPars->fTransLoop || pPars->fUseBackward || pPars->nFramesK > 1) )
+        {
+            pCheck = Inter_CheckStart( p->pAigTrans, pPars->nFramesK );
+            // try new containment check for the initial state
+clk = Abc_Clock();
+            pCnfInter2 = Cnf_Derive( p->pInter, 1 );  
+p->timeCnf += Abc_Clock() - clk;    
+clk = Abc_Clock();
+            RetValue = Inter_CheckPerform( pCheck, pCnfInter2, nTimeNewOut );
+p->timeEqu += Abc_Clock() - clk;
+//            assert( RetValue == 0 );
+            Cnf_DataFree( pCnfInter2 );
+            if ( p->vInters )
+                Vec_PtrPush( p->vInters, Aig_ManDupSimple(p->pInter) );
+        }
+        //////////////////////////////////////////
+
+        // iterate the interpolation procedure
+        for ( i = 0; ; i++ )
+        {
+            if ( pPars->nFramesMax && p->nFrames + i >= pPars->nFramesMax )
+            { 
+                if ( pPars->fVerbose )
+                    printf( "Reached limit (%d) on the number of timeframes.\n", pPars->nFramesMax );
+                p->timeTotal = Abc_Clock() - clkTotal;
+                Inter_ManStop( p, 0 );
+                Inter_CheckStop( pCheck );
+                return -1;
+            }
+
+            // perform interpolation
+            clk = Abc_Clock();
+#ifdef ABC_USE_LIBRARIES
+            if ( pPars->fUseMiniSat )
+            {
+                assert( !pPars->fUseBackward );
+                RetValue = Inter_ManPerformOneStepM114p( p, pPars->fUsePudlak, pPars->fUseOther );
+            }
+            else 
+#endif
+                RetValue = Inter_ManPerformOneStep( p, pPars->fUseBias, pPars->fUseBackward, nTimeNewOut );
+
+            if ( pPars->fVerbose )
+            {
+                printf( "   I = %2d. Bmc =%3d. IntAnd =%6d. IntLev =%5d. Conf =%6d.  ", 
+                    i+1, i + 1 + p->nFrames, Aig_ManNodeNum(p->pInter), Aig_ManLevelNum(p->pInter), p->nConfCur );
+                ABC_PRT( "Time", Abc_Clock() - clk );
+            }
+            // remember the number of timeframes completed
+            pPars->iFrameMax = i - 1 + p->nFrames;
+            if ( RetValue == 0 ) // found a (spurious?) counter-example
+            {
+                if ( i == 0 ) // real counterexample
+                {
+                    if ( pPars->fVerbose )
+                        printf( "Found a real counterexample in frame %d.\n", p->nFrames );
+                    p->timeTotal = Abc_Clock() - clkTotal;
+                    *piFrame = p->nFrames;
+//                    pAig->pSeqModel = (Abc_Cex_t *)Inter_ManGetCounterExample( pAig, p->nFrames+1, pPars->fVerbose );
+                    {
+                        int RetValue;
+                        Saig_ParBmc_t ParsBmc, * pParsBmc = &ParsBmc;
+                        Saig_ParBmcSetDefaultParams( pParsBmc );
+                        pParsBmc->nConfLimit = 100000000;
+                        pParsBmc->nStart     = p->nFrames;
+                        pParsBmc->fVerbose   = pPars->fVerbose;
+                        RetValue = Saig_ManBmcScalable( pAig, pParsBmc );
+                        if ( RetValue == 1 )
+                            printf( "Error: The problem should be SAT but it is UNSAT.\n" );
+                        else if ( RetValue == -1 )
+                            printf( "Error: The problem timed out.\n" );
+                    }
+                    Inter_ManStop( p, 0 );
+                    Inter_CheckStop( pCheck );
+                    return 0;
+                }
+                // likely spurious counter-example
+                p->nFrames += i;
+                Inter_ManClean( p ); 
+                break;
+            }
+            else if ( RetValue == -1 ) 
+            {
+                if ( pPars->nSecLimit && Abc_Clock() > nTimeNewOut ) // timed out
+                {
+                    if ( pPars->fVerbose )
+                        printf( "Reached timeout (%d seconds).\n",  pPars->nSecLimit );
+                }
+                else
+                {
+                    assert( p->nConfCur >= p->nConfLimit );
+                    if ( pPars->fVerbose )
+                        printf( "Reached limit (%d) on the number of conflicts.\n", p->nConfLimit );
+                }
+                p->timeTotal = Abc_Clock() - clkTotal;
+                Inter_ManStop( p, 0 );
+                Inter_CheckStop( pCheck );
+                return -1;
+            }
+            assert( RetValue == 1 ); // found new interpolant
+            // compress the interpolant
+clk = Abc_Clock();
+            if ( p->pInterNew )
+            {
+                // save the timeout value
+                p->pInterNew->Time2Quit = nTimeNewOut;
+//                Ioa_WriteAiger( p->pInterNew, "interpol.aig", 0, 0 );
+                p->pInterNew = Dar_ManRwsat( pAigTemp = p->pInterNew, 1, 0 );
+//                p->pInterNew = Dar_ManRwsat( pAigTemp = p->pInterNew, 0, 0 );
+                Aig_ManStop( pAigTemp );
+                if ( p->pInterNew == NULL )
+                {
+                    printf( "Reached timeout (%d seconds) during rewriting.\n",  pPars->nSecLimit );
+                    p->timeTotal = Abc_Clock() - clkTotal;
+                    Inter_ManStop( p, 1 );
+                    Inter_CheckStop( pCheck );
+                    return -1;
+                }
+            }
+p->timeRwr += Abc_Clock() - clk;
+
+            // check if interpolant is trivial
+            if ( p->pInterNew == NULL || Aig_ObjChild0(Aig_ManCo(p->pInterNew,0)) == Aig_ManConst0(p->pInterNew) )
+            { 
+//                printf( "interpolant is constant 0\n" );
+                if ( pPars->fVerbose )
+                    printf( "The problem is trivially true for all states.\n" );
+                p->timeTotal = Abc_Clock() - clkTotal;
+                Inter_ManStop( p, 1 );
+                Inter_CheckStop( pCheck );
+                return 1;
+            }
+
+            // check containment of interpolants
+clk = Abc_Clock();
+            if ( pPars->fCheckKstep ) // k-step unique-state induction
+            {
+                if ( Aig_ManCiNum(p->pInterNew) == Aig_ManCiNum(p->pInter) )
+                {
+                    if ( pPars->fTransLoop || pPars->fUseBackward || pPars->nFramesK > 1 )
+                    {
+clk2 = Abc_Clock();
+                        Status = Inter_ManCheckInductiveContainment( p->pAigTrans, p->pInterNew, Abc_MinInt(i + 1, pPars->nFramesK), pPars->fUseBackward );
+timeTemp = Abc_Clock() - clk2;
+                    }
+                    else
+                    {   // new containment check
+clk2 = Abc_Clock();
+                        pCnfInter2 = Cnf_Derive( p->pInterNew, 1 );  
+p->timeCnf += Abc_Clock() - clk2;
+timeTemp = Abc_Clock() - clk2;
+            
+                        Status = Inter_CheckPerform( pCheck, pCnfInter2, nTimeNewOut );
+                        Cnf_DataFree( pCnfInter2 );
+                        if ( p->vInters )
+                            Vec_PtrPush( p->vInters, Aig_ManDupSimple(p->pInterNew) );
+                    }
+                }
+                else
+                    Status = 0;
+            }
+            else // combinational containment
+            {
+                if ( Aig_ManCiNum(p->pInterNew) == Aig_ManCiNum(p->pInter) )
+                    Status = Inter_ManCheckContainment( p->pInterNew, p->pInter );
+                else
+                    Status = 0;
+            }
+p->timeEqu += Abc_Clock() - clk - timeTemp;
+            if ( Status ) // contained
+            {
+                if ( pPars->fVerbose )
+                    printf( "Proved containment of interpolants.\n" );
+                p->timeTotal = Abc_Clock() - clkTotal;
+                Inter_ManStop( p, 1 );
+                Inter_CheckStop( pCheck );
+                return 1;
+            }
+            if ( pPars->nSecLimit && Abc_Clock() > nTimeNewOut )
+            {
+                printf( "Reached timeout (%d seconds).\n",  pPars->nSecLimit );
+                p->timeTotal = Abc_Clock() - clkTotal;
+                Inter_ManStop( p, 1 );
+                Inter_CheckStop( pCheck );
+                return -1;
+            }
+            // save interpolant and convert it into CNF
+            if ( pPars->fTransLoop )
+            {
+                Aig_ManStop( p->pInter );
+                p->pInter = p->pInterNew; 
+            }
+            else
+            {
+                if ( pPars->fUseBackward )
+                {
+                    p->pInter = Aig_ManCreateMiter( pAigTemp = p->pInter, p->pInterNew, 2 );
+                    Aig_ManStop( pAigTemp );
+                    Aig_ManStop( p->pInterNew );
+                    // compress the interpolant
+clk = Abc_Clock();
+                    p->pInter = Dar_ManRwsat( pAigTemp = p->pInter, 1, 0 );
+                    Aig_ManStop( pAigTemp );
+p->timeRwr += Abc_Clock() - clk;
+                }
+                else // forward with the new containment checking (using only the frontier)
+                {
+                    Aig_ManStop( p->pInter );
+                    p->pInter = p->pInterNew; 
+                }
+            }
+            p->pInterNew = NULL;
+            Cnf_DataFree( p->pCnfInter );
+clk = Abc_Clock();
+            p->pCnfInter = Cnf_Derive( p->pInter, 0 );  
+p->timeCnf += Abc_Clock() - clk;
+        }
+
+        // start containment checking
+        Inter_CheckStop( pCheck );
+    }
+    assert( 0 );
+    return RetValue;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/int/intCtrex.c b/abc-build/src/proof/int/intCtrex.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int/intCtrex.c
@@ -0,0 +1,168 @@
+/**CFile****************************************************************
+
+  FileName    [intCtrex.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [Counter-example generation after disproving the property.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 24, 2008.]
+
+  Revision    [$Id: intCtrex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+#include "proof/ssw/ssw.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Unroll the circuit the given number of timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManFramesBmc( Aig_Man_t * pAig, int nFrames )
+{
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i, f;
+    assert( Saig_ManRegNum(pAig) > 0 );
+    assert( Saig_ManPoNum(pAig) == 1 );
+    pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames );
+    // map the constant node
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames );
+    // create variables for register outputs
+    Saig_ManForEachLo( pAig, pObj, i )
+        pObj->pData = Aig_ManConst0( pFrames );
+    // add timeframes
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // create PI nodes for this frame
+        Saig_ManForEachPi( pAig, pObj, i )
+            pObj->pData = Aig_ObjCreateCi( pFrames );
+        // add internal nodes of this frame
+        Aig_ManForEachNode( pAig, pObj, i )
+            pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+        if ( f == nFrames - 1 )
+            break;
+        // transfer to register outputs
+        Saig_ManForEachLiLo(  pAig, pObjLi, pObjLo, i )
+            pObjLi->pData = Aig_ObjChild0Copy(pObjLi);
+        // transfer to register outputs
+        Saig_ManForEachLiLo(  pAig, pObjLi, pObjLo, i )
+            pObjLo->pData = pObjLi->pData;
+    }
+    // create POs for the output of the last frame
+    pObj = Aig_ManCo( pAig, 0 );
+    Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) );
+    Aig_ManCleanup( pFrames );
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Run the SAT solver on the unrolled instance.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Inter_ManGetCounterExample( Aig_Man_t * pAig, int nFrames, int fVerbose )
+{
+    int nConfLimit = 1000000;
+    Abc_Cex_t * pCtrex = NULL;
+    Aig_Man_t * pFrames;
+    sat_solver * pSat;
+    Cnf_Dat_t * pCnf;
+    int status;
+    abctime clk = Abc_Clock();
+    Vec_Int_t * vCiIds;
+    // create timeframes
+    assert( Saig_ManPoNum(pAig) == 1 );
+    pFrames = Inter_ManFramesBmc( pAig, nFrames );
+    // derive CNF
+    pCnf = Cnf_Derive( pFrames, 0 );
+    Cnf_DataTranformPolarity( pCnf, 0 );
+    vCiIds = Cnf_DataCollectPiSatNums( pCnf, pFrames );
+    Aig_ManStop( pFrames );
+    // convert into SAT solver
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+    Cnf_DataFree( pCnf );
+    if ( pSat == NULL )
+    {
+        printf( "Counter-example generation in command \"int\" has failed.\n" );
+        printf( "Use command \"bmc2\" to produce a valid counter-example.\n" );
+        Vec_IntFree( vCiIds );
+        return NULL;
+    }
+    // simplify the problem
+    status = sat_solver_simplify(pSat);
+    if ( status == 0 )
+    {
+        Vec_IntFree( vCiIds );
+        sat_solver_delete( pSat );
+        return NULL;
+    }
+    // solve the miter
+    status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    // if the problem is SAT, get the counterexample
+    if ( status == l_True )
+    {
+        int i, * pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize );
+        pCtrex = Abc_CexAlloc( Saig_ManRegNum(pAig), Saig_ManPiNum(pAig), nFrames );
+        pCtrex->iFrame = nFrames - 1;
+        pCtrex->iPo = 0;
+        for ( i = 0; i < Vec_IntSize(vCiIds); i++ )
+            if ( pModel[i] )
+                Abc_InfoSetBit( pCtrex->pData, Saig_ManRegNum(pAig) + i );
+        ABC_FREE( pModel );
+    }
+    // free the sat_solver
+    sat_solver_delete( pSat );
+    Vec_IntFree( vCiIds );
+    // verify counter-example
+    status = Saig_ManVerifyCex( pAig, pCtrex );
+    if ( status == 0 )
+        printf( "Inter_ManGetCounterExample(): Counter-example verification has FAILED.\n" );
+    // report the results
+    if ( fVerbose )
+    {
+        ABC_PRT( "Total ctrex generation time", Abc_Clock() - clk );
+    }
+    return pCtrex;
+
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/int/intDup.c b/abc-build/src/proof/int/intDup.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int/intDup.c
@@ -0,0 +1,184 @@
+/**CFile****************************************************************
+
+  FileName    [intDup.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [Specialized AIG duplication procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 24, 2008.]
+
+  Revision    [$Id: intDup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Create trivial AIG manager for the init state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManStartInitState( int nRegs )
+{
+    Aig_Man_t * p;
+    Aig_Obj_t * pRes;
+    Aig_Obj_t ** ppInputs;
+    int i;
+    assert( nRegs > 0 );
+    ppInputs = ABC_ALLOC( Aig_Obj_t *, nRegs );
+    p = Aig_ManStart( nRegs );
+    for ( i = 0; i < nRegs; i++ )
+        ppInputs[i] = Aig_Not( Aig_ObjCreateCi(p) );
+    pRes = Aig_Multi( p, ppInputs, nRegs, AIG_OBJ_AND );
+    Aig_ObjCreateCo( p, pRes );
+    ABC_FREE( ppInputs );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicate the AIG w/o POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManStartDuplicated( Aig_Man_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( Aig_ManRegNum(p) > 0 );
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    // set registers
+    pNew->nTruePis = p->nTruePis;
+    pNew->nTruePos = Saig_ManConstrNum(p);
+    pNew->nRegs    = p->nRegs;
+    // duplicate internal nodes
+    Aig_ManForEachNode( p, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+
+    // create constraint outputs
+    Saig_ManForEachPo( p, pObj, i )
+    {
+        if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) )
+            continue;
+        Aig_ObjCreateCo( pNew, Aig_Not( Aig_ObjChild0Copy(pObj) ) );
+    }
+
+    // create register inputs with MUXes
+    Saig_ManForEachLi( p, pObj, i )
+        Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    Aig_ManCleanup( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicate the AIG w/o POs and transforms to transit into init state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManStartOneOutput( Aig_Man_t * p, int fAddFirstPo )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    Aig_Obj_t * pCtrl = NULL; // Suppress "might be used uninitialized"
+    int i;
+    assert( Aig_ManRegNum(p) > 0 );
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+    {
+        if ( i == Saig_ManPiNum(p) )
+            pCtrl = Aig_ObjCreateCi( pNew );
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    }
+    // set registers
+    pNew->nRegs    = fAddFirstPo? 0 : p->nRegs;
+    pNew->nTruePis = fAddFirstPo? Aig_ManCiNum(p) + 1 : p->nTruePis + 1;
+    pNew->nTruePos = fAddFirstPo + Saig_ManConstrNum(p);
+    // duplicate internal nodes
+    Aig_ManForEachNode( p, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+
+    // create constraint outputs
+    Saig_ManForEachPo( p, pObj, i )
+    {
+        if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) )
+            continue;
+        Aig_ObjCreateCo( pNew, Aig_Not( Aig_ObjChild0Copy(pObj) ) );
+    }
+
+    // add the PO
+    if ( fAddFirstPo )
+    {
+        pObj = Aig_ManCo( p, 0 );
+        Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    }
+    else
+    {
+        // create register inputs with MUXes
+        Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
+        {
+            pObj = Aig_Mux( pNew, pCtrl, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) );
+    //        pObj = Aig_Mux( pNew, pCtrl, Aig_ManConst0(pNew), Aig_ObjChild0Copy(pObjLi) );
+            Aig_ObjCreateCo( pNew, pObj );
+        }
+    }
+    Aig_ManCleanup( pNew );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/int/intFrames.c b/abc-build/src/proof/int/intFrames.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int/intFrames.c
@@ -0,0 +1,124 @@
+/**CFile****************************************************************
+
+  FileName    [intFrames.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [Sequential AIG unrolling for interpolation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 24, 2008.]
+
+  Revision    [$Id: intFrames.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Create timeframes of the manager for interpolation.]
+
+  Description [The resulting manager is combinational. The primary inputs
+  corresponding to register outputs are ordered first. The only POs of the 
+  manager is the property output of the last timeframe.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManFramesInter( Aig_Man_t * pAig, int nFrames, int fAddRegOuts, int fUseTwoFrames )
+{
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    Aig_Obj_t * pLastPo = NULL;
+    int i, f;
+    assert( Saig_ManRegNum(pAig) > 0 );
+    assert( Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) == 1 );
+    pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames );
+    // map the constant node
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames );
+    // create variables for register outputs
+    if ( fAddRegOuts )
+    {
+        Saig_ManForEachLo( pAig, pObj, i )
+            pObj->pData = Aig_ManConst0( pFrames );
+    }
+    else
+    {
+        Saig_ManForEachLo( pAig, pObj, i )
+            pObj->pData = Aig_ObjCreateCi( pFrames );
+    }
+    // add timeframes
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // create PI nodes for this frame
+        Saig_ManForEachPi( pAig, pObj, i )
+            pObj->pData = Aig_ObjCreateCi( pFrames );
+        // add internal nodes of this frame
+        Aig_ManForEachNode( pAig, pObj, i )
+            pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+        // add outputs for constraints
+        Saig_ManForEachPo( pAig, pObj, i )
+        {
+            if ( i < Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) )
+                continue;
+            Aig_ObjCreateCo( pFrames, Aig_Not( Aig_ObjChild0Copy(pObj) ) );
+        }
+        if ( f == nFrames - 1 )
+            break;
+        // remember the last PO
+        pObj = Aig_ManCo( pAig, 0 );
+        pLastPo = Aig_ObjChild0Copy(pObj);
+        // save register inputs
+        Saig_ManForEachLi( pAig, pObj, i )
+            pObj->pData = Aig_ObjChild0Copy(pObj);
+        // transfer to register outputs
+        Saig_ManForEachLiLo(  pAig, pObjLi, pObjLo, i )
+            pObjLo->pData = pObjLi->pData;
+    }
+    // create POs for each register output
+    if ( fAddRegOuts )
+    {
+        Saig_ManForEachLi( pAig, pObj, i )
+            Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) );
+    }
+    // create the only PO of the manager
+    else
+    {
+        pObj = Aig_ManCo( pAig, 0 );
+        // add the last PO
+        if ( pLastPo == NULL || !fUseTwoFrames )
+            pLastPo = Aig_ObjChild0Copy(pObj);
+        else
+            pLastPo = Aig_Or( pFrames, pLastPo, Aig_ObjChild0Copy(pObj) );
+        Aig_ObjCreateCo( pFrames, pLastPo );
+    }
+    Aig_ManCleanup( pFrames );
+    return pFrames;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/int/intInt.h b/abc-build/src/proof/int/intInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int/intInt.h
@@ -0,0 +1,143 @@
+/**CFile****************************************************************
+
+  FileName    [intInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 24, 2008.]
+
+  Revision    [$Id: intInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__int__intInt_h
+#define ABC__aig__int__intInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "aig/saig/saig.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver.h"
+#include "sat/bsat/satStore.h"
+#include "int.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// interpolation manager
+typedef struct Inter_Man_t_ Inter_Man_t;
+struct Inter_Man_t_
+{
+    // AIG manager
+    Aig_Man_t *      pAig;         // the original AIG manager
+    Aig_Man_t *      pAigTrans;    // the transformed original AIG manager
+    Cnf_Dat_t *      pCnfAig;      // CNF for the original manager
+    // interpolant
+    Aig_Man_t *      pInter;       // the current interpolant
+    Cnf_Dat_t *      pCnfInter;    // CNF for the current interplant
+    // timeframes
+    Aig_Man_t *      pFrames;      // the timeframes      
+    Cnf_Dat_t *      pCnfFrames;   // CNF for the timeframes 
+    // other data
+    Vec_Int_t *      vVarsAB;      // the variables participating in 
+    // temporary place for the new interpolant
+    Aig_Man_t *      pInterNew;
+    Vec_Ptr_t *      vInters;
+    // parameters
+    int              nFrames;      // the number of timeframes
+    int              nConfCur;     // the current number of conflicts
+    int              nConfLimit;   // the limit on the number of conflicts
+    int              fVerbose;     // the verbosiness flag
+    char *           pFileName;
+    // runtime
+    abctime          timeRwr;
+    abctime          timeCnf;
+    abctime          timeSat;
+    abctime          timeInt;
+    abctime          timeEqu;
+    abctime          timeOther;
+    abctime          timeTotal;
+};
+
+// containment checking manager
+typedef struct Inter_Check_t_ Inter_Check_t;
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== intCheck.c ============================================================*/
+extern Inter_Check_t * Inter_CheckStart( Aig_Man_t * pTrans, int nFramesK );
+extern void            Inter_CheckStop( Inter_Check_t * p );
+extern int             Inter_CheckPerform( Inter_Check_t * p, Cnf_Dat_t * pCnf, abctime nTimeNewOut );
+
+/*=== intContain.c ============================================================*/
+extern int             Inter_ManCheckContainment( Aig_Man_t * pNew, Aig_Man_t * pOld );
+extern int             Inter_ManCheckEquivalence( Aig_Man_t * pNew, Aig_Man_t * pOld );
+extern int             Inter_ManCheckInductiveContainment( Aig_Man_t * pTrans, Aig_Man_t * pInter, int nSteps, int fBackward );
+
+/*=== intCtrex.c ============================================================*/
+extern void *          Inter_ManGetCounterExample( Aig_Man_t * pAig, int nFrames, int fVerbose );
+
+/*=== intDup.c ============================================================*/
+extern Aig_Man_t *     Inter_ManStartInitState( int nRegs );
+extern Aig_Man_t *     Inter_ManStartDuplicated( Aig_Man_t * p );
+extern Aig_Man_t *     Inter_ManStartOneOutput( Aig_Man_t * p, int fAddFirstPo );
+
+/*=== intFrames.c ============================================================*/
+extern Aig_Man_t *     Inter_ManFramesInter( Aig_Man_t * pAig, int nFrames, int fAddRegOuts, int fUseTwoFrames );
+
+/*=== intMan.c ============================================================*/
+extern Inter_Man_t *   Inter_ManCreate( Aig_Man_t * pAig, Inter_ManParams_t * pPars );
+extern void            Inter_ManClean( Inter_Man_t * p );
+extern void            Inter_ManStop( Inter_Man_t * p, int fProved );
+
+/*=== intM114.c ============================================================*/
+extern int             Inter_ManPerformOneStep( Inter_Man_t * p, int fUseBias, int fUseBackward, abctime nTimeNewOut );
+
+/*=== intM114p.c ============================================================*/
+#ifdef ABC_USE_LIBRARIES
+extern int             Inter_ManPerformOneStepM114p( Inter_Man_t * p, int fUsePudlak, int fUseOther );
+#endif
+
+/*=== intUtil.c ============================================================*/
+extern int             Inter_ManCheckInitialState( Aig_Man_t * p );
+extern int             Inter_ManCheckAllStates( Aig_Man_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/int/intInter.c b/abc-build/src/proof/int/intInter.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int/intInter.c
@@ -0,0 +1,145 @@
+/**CFile****************************************************************
+
+  FileName    [intInter.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [Experimental procedures to derive and compare interpolants.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 24, 2008.]
+
+  Revision    [$Id: intInter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManDupExpand( Aig_Man_t * pInter, Aig_Man_t * pOther )
+{
+    Aig_Man_t * pInterC;
+    assert( Aig_ManCiNum(pInter) <= Aig_ManCiNum(pOther) );
+    pInterC = Aig_ManDupSimple( pInter );
+    Aig_IthVar( pInterC, Aig_ManCiNum(pOther)-1 );
+    assert( Aig_ManCiNum(pInterC) == Aig_ManCiNum(pOther) );
+    return pInterC;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Inter_ManVerifyInterpolant1( Inta_Man_t * pMan, Sto_Man_t * pCnf, Aig_Man_t * pInter )
+{
+    extern Aig_Man_t * Inta_ManDeriveClauses( Inta_Man_t * pMan, Sto_Man_t * pCnf, int fClausesA );
+    Aig_Man_t * pLower, * pUpper, * pInterC;
+    int RetValue1, RetValue2;
+
+    pLower = Inta_ManDeriveClauses( pMan, pCnf, 1 );
+    pUpper = Inta_ManDeriveClauses( pMan, pCnf, 0 );
+    Aig_ManFlipFirstPo( pUpper );
+
+    pInterC = Inter_ManDupExpand( pInter, pLower );
+    RetValue1 = Inter_ManCheckContainment( pLower, pInterC );
+    Aig_ManStop( pInterC );
+
+    pInterC = Inter_ManDupExpand( pInter, pUpper );
+    RetValue2 = Inter_ManCheckContainment( pInterC, pUpper );
+    Aig_ManStop( pInterC );
+    
+    if ( RetValue1 && RetValue2 )
+        printf( "Im is correct.\n" );
+    if ( !RetValue1 )
+        printf( "Property A => Im fails.\n" );
+    if ( !RetValue2 )
+        printf( "Property Im => !B fails.\n" );
+
+    Aig_ManStop( pLower );
+    Aig_ManStop( pUpper );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Inter_ManVerifyInterpolant2( Intb_Man_t * pMan, Sto_Man_t * pCnf, Aig_Man_t * pInter )
+{
+    extern Aig_Man_t * Intb_ManDeriveClauses( Intb_Man_t * pMan, Sto_Man_t * pCnf, int fClausesA );
+    Aig_Man_t * pLower, * pUpper, * pInterC;
+    int RetValue1, RetValue2;
+
+    pLower = Intb_ManDeriveClauses( pMan, pCnf, 1 );
+    pUpper = Intb_ManDeriveClauses( pMan, pCnf, 0 );
+    Aig_ManFlipFirstPo( pUpper );
+
+    pInterC = Inter_ManDupExpand( pInter, pLower );
+//Aig_ManPrintStats( pLower );
+//Aig_ManPrintStats( pUpper );
+//Aig_ManPrintStats( pInterC );
+//Aig_ManDumpBlif( pInterC, "inter_c.blif", NULL, NULL );
+    RetValue1 = Inter_ManCheckContainment( pLower, pInterC );
+    Aig_ManStop( pInterC );
+
+    pInterC = Inter_ManDupExpand( pInter, pUpper );
+    RetValue2 = Inter_ManCheckContainment( pInterC, pUpper );
+    Aig_ManStop( pInterC );
+    
+    if ( RetValue1 && RetValue2 )
+        printf( "Ip is correct.\n" );
+    if ( !RetValue1 )
+        printf( "Property A => Ip fails.\n" );
+    if ( !RetValue2 )
+        printf( "Property Ip => !B fails.\n" );
+
+    Aig_ManStop( pLower );
+    Aig_ManStop( pUpper );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/int/intM114.c b/abc-build/src/proof/int/intM114.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int/intM114.c
@@ -0,0 +1,323 @@
+/**CFile****************************************************************
+
+  FileName    [intM114.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [Intepolation using ABC's proof generator added to MiniSat-1.14c.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 24, 2008.]
+
+  Revision    [$Id: intM114.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the SAT solver for one interpolation run.]
+
+  Description [pInter is the previous interpolant. pAig is one time frame.
+  pFrames is the unrolled time frames.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+sat_solver * Inter_ManDeriveSatSolver( 
+    Aig_Man_t * pInter, Cnf_Dat_t * pCnfInter, 
+    Aig_Man_t * pAig, Cnf_Dat_t * pCnfAig, 
+    Aig_Man_t * pFrames, Cnf_Dat_t * pCnfFrames, 
+    Vec_Int_t * vVarsAB, int fUseBackward )
+{
+    sat_solver * pSat;
+    Aig_Obj_t * pObj, * pObj2;
+    int i, Lits[2];
+
+//Aig_ManDumpBlif( pInter,  "out_inter.blif", NULL, NULL );
+//Aig_ManDumpBlif( pAig,    "out_aig.blif", NULL, NULL );
+//Aig_ManDumpBlif( pFrames, "out_frames.blif", NULL, NULL );
+
+    // sanity checks
+    assert( Aig_ManRegNum(pInter) == 0 );
+    assert( Aig_ManRegNum(pAig) > 0 );
+    assert( Aig_ManRegNum(pFrames) == 0 );
+    assert( Aig_ManCoNum(pInter) == 1 );
+    assert( Aig_ManCoNum(pFrames) == fUseBackward? Saig_ManRegNum(pAig) : 1 );
+    assert( fUseBackward || Aig_ManCiNum(pInter) == Aig_ManRegNum(pAig) );
+//    assert( (Aig_ManCiNum(pFrames) - Aig_ManRegNum(pAig)) % Saig_ManPiNum(pAig) == 0 );
+
+    // prepare CNFs
+    Cnf_DataLift( pCnfAig,   pCnfFrames->nVars );
+    Cnf_DataLift( pCnfInter, pCnfFrames->nVars + pCnfAig->nVars );
+
+    // start the solver
+    pSat = sat_solver_new();
+    sat_solver_store_alloc( pSat );
+    sat_solver_setnvars( pSat, pCnfInter->nVars + pCnfAig->nVars + pCnfFrames->nVars );
+
+    // add clauses of A
+    // interpolant
+    for ( i = 0; i < pCnfInter->nClauses; i++ )
+    {
+        if ( !sat_solver_addclause( pSat, pCnfInter->pClauses[i], pCnfInter->pClauses[i+1] ) )
+        {
+            sat_solver_delete( pSat );
+            // return clauses to the original state
+            Cnf_DataLift( pCnfAig, -pCnfFrames->nVars );
+            Cnf_DataLift( pCnfInter, -pCnfFrames->nVars -pCnfAig->nVars );
+            return NULL;
+        }
+    }
+    // connector clauses
+    if ( fUseBackward )
+    {
+        Saig_ManForEachLi( pAig, pObj2, i )
+        {
+            if ( Saig_ManRegNum(pAig) == Aig_ManCiNum(pInter) )
+                pObj = Aig_ManCi( pInter, i );
+            else
+            {
+                assert( Aig_ManCiNum(pAig) == Aig_ManCiNum(pInter) );
+                pObj = Aig_ManCi( pInter, Aig_ManCiNum(pAig)-Saig_ManRegNum(pAig) + i );
+            }
+
+            Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 0 );
+            Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 );
+            if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+                assert( 0 );
+            Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 1 );
+            Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 );
+            if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+                assert( 0 );
+        }
+    }
+    else
+    {
+        Aig_ManForEachCi( pInter, pObj, i )
+        {
+            pObj2 = Saig_ManLo( pAig, i );
+
+            Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 0 );
+            Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 );
+            if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+                assert( 0 );
+            Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 1 );
+            Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 );
+            if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+                assert( 0 );
+        }
+    }
+    // one timeframe
+    for ( i = 0; i < pCnfAig->nClauses; i++ )
+    {
+        if ( !sat_solver_addclause( pSat, pCnfAig->pClauses[i], pCnfAig->pClauses[i+1] ) )
+            assert( 0 );
+    }
+    // connector clauses
+    Vec_IntClear( vVarsAB );
+    if ( fUseBackward )
+    {
+        Aig_ManForEachCo( pFrames, pObj, i )
+        {
+            assert( pCnfFrames->pVarNums[pObj->Id] >= 0 );
+            Vec_IntPush( vVarsAB, pCnfFrames->pVarNums[pObj->Id] );
+
+            pObj2 = Saig_ManLo( pAig, i );
+            Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 0 );
+            Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 );
+            if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+                assert( 0 );
+            Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 1 );
+            Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 );
+            if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+                assert( 0 );
+        }
+    }
+    else
+    {
+        Aig_ManForEachCi( pFrames, pObj, i )
+        {
+            if ( i == Aig_ManRegNum(pAig) )
+                break;
+            Vec_IntPush( vVarsAB, pCnfFrames->pVarNums[pObj->Id] );
+
+            pObj2 = Saig_ManLi( pAig, i );
+            Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 0 );
+            Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 );
+            if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+                assert( 0 );
+            Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 1 );
+            Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 );
+            if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+                assert( 0 );
+        }
+    }
+    // add clauses of B
+    sat_solver_store_mark_clauses_a( pSat );
+    for ( i = 0; i < pCnfFrames->nClauses; i++ )
+    {
+        if ( !sat_solver_addclause( pSat, pCnfFrames->pClauses[i], pCnfFrames->pClauses[i+1] ) )
+        {
+            pSat->fSolved = 1;
+            break;
+        }
+    }
+    sat_solver_store_mark_roots( pSat );
+    // return clauses to the original state
+    Cnf_DataLift( pCnfAig, -pCnfFrames->nVars );
+    Cnf_DataLift( pCnfInter, -pCnfFrames->nVars -pCnfAig->nVars );
+    return pSat;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one SAT run with interpolation.]
+
+  Description [Returns 1 if proven. 0 if failed. -1 if undecided.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Inter_ManPerformOneStep( Inter_Man_t * p, int fUseBias, int fUseBackward, abctime nTimeNewOut )
+{
+    sat_solver * pSat;
+    void * pSatCnf = NULL;
+    Inta_Man_t * pManInterA; 
+//    Intb_Man_t * pManInterB; 
+    int * pGlobalVars;
+    int status, RetValue;
+    int i, Var;
+    abctime clk;
+//    assert( p->pInterNew == NULL );
+
+    // derive the SAT solver
+    pSat = Inter_ManDeriveSatSolver( p->pInter, p->pCnfInter, p->pAigTrans, p->pCnfAig, p->pFrames, p->pCnfFrames, p->vVarsAB, fUseBackward );
+    if ( pSat == NULL )
+    {
+        p->pInterNew = NULL;
+        return 1;
+    }
+
+    // set runtime limit
+    if ( nTimeNewOut )
+        sat_solver_set_runtime_limit( pSat, nTimeNewOut );
+
+    // collect global variables
+    pGlobalVars = ABC_CALLOC( int, sat_solver_nvars(pSat) );
+    Vec_IntForEachEntry( p->vVarsAB, Var, i )
+        pGlobalVars[Var] = 1;
+    pSat->pGlobalVars = fUseBias? pGlobalVars : NULL;
+
+    // solve the problem
+clk = Abc_Clock();
+    status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)p->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    p->nConfCur = pSat->stats.conflicts;
+p->timeSat += Abc_Clock() - clk;
+
+    pSat->pGlobalVars = NULL;
+    ABC_FREE( pGlobalVars );
+    if ( status == l_False )
+    {
+        pSatCnf = sat_solver_store_release( pSat );
+        RetValue = 1;
+    }
+    else if ( status == l_True )
+    {
+        RetValue = 0;
+    } 
+    else
+    {
+        RetValue = -1;
+    }
+    sat_solver_delete( pSat );
+    if ( pSatCnf == NULL )
+        return RetValue;
+
+    // create the resulting manager
+clk = Abc_Clock();
+/*
+    if ( !fUseIp )
+    {
+        pManInterA = Inta_ManAlloc();
+        p->pInterNew = Inta_ManInterpolate( pManInterA, pSatCnf, p->vVarsAB, 0 );
+        Inta_ManFree( pManInterA );
+    }
+    else
+    {
+        Aig_Man_t * pInterNew2;
+        int RetValue;
+
+        pManInterA = Inta_ManAlloc();
+        p->pInterNew = Inta_ManInterpolate( pManInterA, pSatCnf, p->vVarsAB, 0 );
+//        Inter_ManVerifyInterpolant1( pManInterA, pSatCnf, p->pInterNew );
+        Inta_ManFree( pManInterA );
+
+        pManInterB = Intb_ManAlloc();
+        pInterNew2 = Intb_ManInterpolate( pManInterB, pSatCnf, p->vVarsAB, 0 );
+        Inter_ManVerifyInterpolant2( pManInterB, pSatCnf, pInterNew2 );
+        Intb_ManFree( pManInterB );
+
+        // check relationship
+        RetValue = Inter_ManCheckEquivalence( pInterNew2, p->pInterNew );
+        if ( RetValue )
+            printf( "Equivalence \"Ip == Im\" holds\n" );
+        else
+        {
+//            printf( "Equivalence \"Ip == Im\" does not hold\n" );
+            RetValue = Inter_ManCheckContainment( pInterNew2, p->pInterNew );
+            if ( RetValue )
+                printf( "Containment \"Ip -> Im\" holds\n" );
+            else
+                printf( "Containment \"Ip -> Im\" does not hold\n" );
+
+            RetValue = Inter_ManCheckContainment( p->pInterNew, pInterNew2 );
+            if ( RetValue )
+                printf( "Containment \"Im -> Ip\" holds\n" );
+            else
+                printf( "Containment \"Im -> Ip\" does not hold\n" );
+        }
+
+        Aig_ManStop( pInterNew2 );
+    }
+*/
+
+    pManInterA = Inta_ManAlloc();
+    p->pInterNew = (Aig_Man_t *)Inta_ManInterpolate( pManInterA, (Sto_Man_t *)pSatCnf, nTimeNewOut, p->vVarsAB, 0 );
+    Inta_ManFree( pManInterA );
+
+p->timeInt += Abc_Clock() - clk;
+    Sto_ManFree( (Sto_Man_t *)pSatCnf );
+    if ( p->pInterNew == NULL )
+        RetValue = -1;
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/int/intM114p.c b/abc-build/src/proof/int/intM114p.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int/intM114p.c
@@ -0,0 +1,443 @@
+/**CFile****************************************************************
+
+  FileName    [intM114p.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [Intepolation using interfaced to MiniSat-1.14p.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 24, 2008.]
+
+  Revision    [$Id: intM114p.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+#include "sat/psat/m114p.h"
+
+#ifdef ABC_USE_LIBRARIES
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the SAT solver for one interpolation run.]
+
+  Description [pInter is the previous interpolant. pAig is one time frame.
+  pFrames is the unrolled time frames.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+M114p_Solver_t Inter_ManDeriveSatSolverM114p( 
+    Aig_Man_t * pInter, Cnf_Dat_t * pCnfInter, 
+    Aig_Man_t * pAig, Cnf_Dat_t * pCnfAig, 
+    Aig_Man_t * pFrames, Cnf_Dat_t * pCnfFrames, 
+    Vec_Int_t ** pvMapRoots, Vec_Int_t ** pvMapVars )
+{
+    M114p_Solver_t pSat;
+    Aig_Obj_t * pObj, * pObj2;
+    int i, Lits[2];
+
+    // sanity checks
+    assert( Aig_ManRegNum(pInter) == 0 );
+    assert( Aig_ManRegNum(pAig) > 0 );
+    assert( Aig_ManRegNum(pFrames) == 0 );
+    assert( Aig_ManCoNum(pInter) == 1 );
+    assert( Aig_ManCoNum(pFrames) == 1 );
+    assert( Aig_ManCiNum(pInter) == Aig_ManRegNum(pAig) );
+//    assert( (Aig_ManCiNum(pFrames) - Aig_ManRegNum(pAig)) % Saig_ManPiNum(pAig) == 0 );
+
+    // prepare CNFs
+    Cnf_DataLift( pCnfAig,   pCnfFrames->nVars );
+    Cnf_DataLift( pCnfInter, pCnfFrames->nVars + pCnfAig->nVars );
+
+    *pvMapRoots = Vec_IntAlloc( 10000 );
+    *pvMapVars = Vec_IntAlloc( 0 );
+    Vec_IntFill( *pvMapVars, pCnfInter->nVars + pCnfAig->nVars + pCnfFrames->nVars, -1 );
+    for ( i = 0; i < pCnfFrames->nVars; i++ )
+        Vec_IntWriteEntry( *pvMapVars, i, -2 );
+
+    // start the solver
+    pSat = M114p_SolverNew( 1 );
+    M114p_SolverSetVarNum( pSat, pCnfInter->nVars + pCnfAig->nVars + pCnfFrames->nVars );
+
+    // add clauses of A
+    // interpolant
+    for ( i = 0; i < pCnfInter->nClauses; i++ )
+    {
+        Vec_IntPush( *pvMapRoots, 0 );
+        if ( !M114p_SolverAddClause( pSat, pCnfInter->pClauses[i], pCnfInter->pClauses[i+1] ) )
+            assert( 0 );
+    }
+    // connector clauses
+    Aig_ManForEachCi( pInter, pObj, i )
+    {
+        pObj2 = Saig_ManLo( pAig, i );
+        Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 0 );
+        Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 );
+        Vec_IntPush( *pvMapRoots, 0 );
+        if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) )
+            assert( 0 );
+        Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 1 );
+        Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 );
+        Vec_IntPush( *pvMapRoots, 0 );
+        if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) )
+            assert( 0 );
+    }
+    // one timeframe
+    for ( i = 0; i < pCnfAig->nClauses; i++ )
+    {
+        Vec_IntPush( *pvMapRoots, 0 );
+        if ( !M114p_SolverAddClause( pSat, pCnfAig->pClauses[i], pCnfAig->pClauses[i+1] ) )
+            assert( 0 );
+    }
+    // connector clauses
+    Aig_ManForEachCi( pFrames, pObj, i )
+    { 
+        if ( i == Aig_ManRegNum(pAig) )
+            break;
+//        Vec_IntPush( vVarsAB, pCnfFrames->pVarNums[pObj->Id] );
+        Vec_IntWriteEntry( *pvMapVars, pCnfFrames->pVarNums[pObj->Id], i );
+
+        pObj2 = Saig_ManLi( pAig, i );
+        Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 0 );
+        Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 );
+        Vec_IntPush( *pvMapRoots, 0 );
+        if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) )
+            assert( 0 );
+        Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 1 );
+        Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 );
+        Vec_IntPush( *pvMapRoots, 0 );
+        if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) )
+            assert( 0 );
+    }
+    // add clauses of B
+    for ( i = 0; i < pCnfFrames->nClauses; i++ )
+    {
+        Vec_IntPush( *pvMapRoots, 1 );
+        if ( !M114p_SolverAddClause( pSat, pCnfFrames->pClauses[i], pCnfFrames->pClauses[i+1] ) )
+        {
+//            assert( 0 );
+            break;
+        }
+    }
+    // return clauses to the original state
+    Cnf_DataLift( pCnfAig, -pCnfFrames->nVars );
+    Cnf_DataLift( pCnfInter, -pCnfFrames->nVars -pCnfAig->nVars );
+    return pSat;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one resolution step.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Inter_ManResolveM114p( Vec_Int_t * vResolvent, int * pLits, int nLits, int iVar )
+{
+    int i, k, iLit = -1, fFound = 0;
+    // find the variable in the clause
+    for ( i = 0; i < vResolvent->nSize; i++ )
+        if ( lit_var(vResolvent->pArray[i]) == iVar )
+        {
+            iLit = vResolvent->pArray[i];
+            vResolvent->pArray[i] = vResolvent->pArray[--vResolvent->nSize];
+            break;
+        }
+    assert( iLit != -1 );
+    // add other variables
+    for ( i = 0; i < nLits; i++ )
+    {
+        if ( lit_var(pLits[i]) == iVar )
+        {
+            assert( iLit == lit_neg(pLits[i]) );
+            fFound = 1;
+            continue;
+        }
+        // check if this literal appears
+        for ( k = 0; k < vResolvent->nSize; k++ )
+            if ( vResolvent->pArray[k] == pLits[i] )
+                break;
+        if ( k < vResolvent->nSize )
+            continue;
+        // add this literal
+        Vec_IntPush( vResolvent, pLits[i] );
+    }
+    assert( fFound );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes interpolant using MiniSat-1.14p.]
+
+  Description [Assumes that the solver returned UNSAT and proof
+  logging was enabled. Array vMapRoots maps number of each root clause 
+  into 0 (clause of A) or 1 (clause of B). Array vMapVars maps each SAT
+  solver variable into -1 (var of A), -2 (var of B), and <num> (var of C),
+  where <num> is the var's 0-based number in the ordering of C variables.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManInterpolateM114pPudlak( M114p_Solver_t s, Vec_Int_t * vMapRoots, Vec_Int_t * vMapVars )
+{
+    Aig_Man_t * p;
+    Aig_Obj_t * pInter, * pInter2, * pVar;
+    Vec_Ptr_t * vInters;
+    Vec_Int_t * vLiterals, * vClauses, * vResolvent;
+    int * pLitsNext, nLitsNext, nOffset, iLit;
+    int * pLits, * pClauses, * pVars;
+    int nLits, nVars, i, k, v, iVar;
+    assert( M114p_SolverProofIsReady(s) );
+    vInters = Vec_PtrAlloc( 1000 );
+
+    vLiterals = Vec_IntAlloc( 10000 );
+    vClauses = Vec_IntAlloc( 1000 );
+    vResolvent = Vec_IntAlloc( 100 );
+
+    // create elementary variables
+    p = Aig_ManStart( 10000 );
+    Vec_IntForEachEntry( vMapVars, iVar, i )
+        if ( iVar >= 0 )
+            Aig_IthVar(p, iVar);
+    // process root clauses
+    M114p_SolverForEachRoot( s, &pLits, nLits, i )
+    {
+        if ( Vec_IntEntry(vMapRoots, i) == 1 ) // clause of B
+            pInter = Aig_ManConst1(p);
+        else // clause of A
+            pInter = Aig_ManConst0(p);
+        Vec_PtrPush( vInters, pInter );
+
+        // save the root clause
+        Vec_IntPush( vClauses, Vec_IntSize(vLiterals) );
+        Vec_IntPush( vLiterals, nLits );
+        for ( v = 0; v < nLits; v++ )
+            Vec_IntPush( vLiterals, pLits[v] );
+    }
+    assert( Vec_PtrSize(vInters) == Vec_IntSize(vMapRoots) );
+
+    // process learned clauses
+    M114p_SolverForEachChain( s, &pClauses, &pVars, nVars, i )
+    {
+        pInter = Vec_PtrEntry( vInters, pClauses[0] );
+
+        // initialize the resolvent
+        nOffset = Vec_IntEntry( vClauses, pClauses[0] );
+        nLitsNext = Vec_IntEntry( vLiterals, nOffset );
+        pLitsNext = Vec_IntArray(vLiterals) + nOffset + 1;
+        Vec_IntClear( vResolvent );
+        for ( v = 0; v < nLitsNext; v++ )
+            Vec_IntPush( vResolvent, pLitsNext[v] );
+
+        for ( k = 0; k < nVars; k++ )
+        {
+            iVar = Vec_IntEntry( vMapVars, pVars[k] );
+            pInter2 = Vec_PtrEntry( vInters, pClauses[k+1] );
+
+            // resolve it with the next clause
+            nOffset = Vec_IntEntry( vClauses, pClauses[k+1] );
+            nLitsNext = Vec_IntEntry( vLiterals, nOffset );
+            pLitsNext = Vec_IntArray(vLiterals) + nOffset + 1;
+            Inter_ManResolveM114p( vResolvent, pLitsNext, nLitsNext, pVars[k] );
+
+            if ( iVar == -1 ) // var of A
+                pInter = Aig_Or( p, pInter, pInter2 );
+            else if ( iVar == -2 ) // var of B
+                pInter = Aig_And( p, pInter, pInter2 );
+            else // var of C
+            {
+                // check polarity of the pivot variable in the clause
+                for ( v = 0; v < nLitsNext; v++ )
+                    if ( lit_var(pLitsNext[v]) == pVars[k] )
+                        break;
+                assert( v < nLitsNext );
+                pVar = Aig_NotCond( Aig_IthVar(p, iVar), lit_sign(pLitsNext[v]) );
+                pInter = Aig_Mux( p, pVar, pInter, pInter2 );
+            }
+        }
+        Vec_PtrPush( vInters, pInter );
+
+        // store the resulting clause
+        Vec_IntPush( vClauses, Vec_IntSize(vLiterals) );
+        Vec_IntPush( vLiterals, Vec_IntSize(vResolvent) );
+        Vec_IntForEachEntry( vResolvent, iLit, v )
+            Vec_IntPush( vLiterals, iLit );
+    }
+    assert( Vec_PtrSize(vInters) == M114p_SolverProofClauseNum(s) );
+    assert( Vec_IntSize(vResolvent) == 0 ); // the empty clause
+    Vec_PtrFree( vInters );
+    Vec_IntFree( vLiterals );
+    Vec_IntFree( vClauses );
+    Vec_IntFree( vResolvent );
+    Aig_ObjCreateCo( p, pInter );
+    Aig_ManCleanup( p );
+    return p;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes interpolant using MiniSat-1.14p.]
+
+  Description [Assumes that the solver returned UNSAT and proof
+  logging was enabled. Array vMapRoots maps number of each root clause 
+  into 0 (clause of A) or 1 (clause of B). Array vMapVars maps each SAT
+  solver variable into -1 (var of A), -2 (var of B), and <num> (var of C),
+  where <num> is the var's 0-based number in the ordering of C variables.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManpInterpolateM114( M114p_Solver_t s, Vec_Int_t * vMapRoots, Vec_Int_t * vMapVars )
+{
+    Aig_Man_t * p;
+    Aig_Obj_t * pInter, * pInter2, * pVar;
+    Vec_Ptr_t * vInters;
+    int * pLits, * pClauses, * pVars;
+    int nLits, nVars, i, k, iVar;
+    int nClauses;
+
+    nClauses = M114p_SolverProofClauseNum(s);
+
+    assert( M114p_SolverProofIsReady(s) );
+
+    vInters = Vec_PtrAlloc( 1000 );
+    // process root clauses
+    p = Aig_ManStart( 10000 );
+    M114p_SolverForEachRoot( s, &pLits, nLits, i )
+    {
+        if ( Vec_IntEntry(vMapRoots, i) == 1 ) // clause of B
+            pInter = Aig_ManConst1(p);
+        else // clause of A
+        {
+            pInter = Aig_ManConst0(p);
+            for ( k = 0; k < nLits; k++ )
+            {
+                iVar = Vec_IntEntry( vMapVars, lit_var(pLits[k]) );
+                if ( iVar < 0 ) // var of A or B
+                    continue;
+                // this is a variable of C
+                pVar = Aig_NotCond( Aig_IthVar(p, iVar), lit_sign(pLits[k]) );
+                pInter = Aig_Or( p, pInter, pVar );
+            }
+        }
+        Vec_PtrPush( vInters, pInter );
+    } 
+//    assert( Vec_PtrSize(vInters) == Vec_IntSize(vMapRoots) );
+
+    // process learned clauses
+    M114p_SolverForEachChain( s, &pClauses, &pVars, nVars, i )
+    {
+        pInter = Vec_PtrEntry( vInters, pClauses[0] );
+        for ( k = 0; k < nVars; k++ )
+        {
+            iVar = Vec_IntEntry( vMapVars, pVars[k] );
+            pInter2 = Vec_PtrEntry( vInters, pClauses[k+1] );
+            if ( iVar == -1 ) // var of A
+                pInter = Aig_Or( p, pInter, pInter2 );
+            else // var of B or C
+                pInter = Aig_And( p, pInter, pInter2 );
+        }
+        Vec_PtrPush( vInters, pInter );
+    }
+
+    assert( Vec_PtrSize(vInters) == M114p_SolverProofClauseNum(s) );
+    Vec_PtrFree( vInters );
+    Aig_ObjCreateCo( p, pInter );
+    Aig_ManCleanup( p );
+    assert( Aig_ManCheck(p) );
+    return p;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one SAT run with interpolation.]
+
+  Description [Returns 1 if proven. 0 if failed. -1 if undecided.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Inter_ManPerformOneStepM114p( Inter_Man_t * p, int fUsePudlak, int fUseOther )
+{
+    M114p_Solver_t pSat;
+    Vec_Int_t * vMapRoots, * vMapVars;
+    clock_t clk;
+    int status, RetValue;
+    assert( p->pInterNew == NULL );
+    // derive the SAT solver
+    pSat = Inter_ManDeriveSatSolverM114p( p->pInter, p->pCnfInter, 
+        p->pAigTrans, p->pCnfAig, p->pFrames, p->pCnfFrames, 
+        &vMapRoots, &vMapVars );
+    // solve the problem
+clk = clock();
+    status = M114p_SolverSolve( pSat, NULL, NULL, 0 );
+    p->nConfCur = M114p_SolverGetConflictNum( pSat );
+p->timeSat += clock() - clk;
+    if ( status == 0 )
+    {
+        RetValue = 1;
+//        Inter_ManpInterpolateM114Report( pSat, vMapRoots, vMapVars );
+
+clk = clock();
+        if ( fUsePudlak )
+            p->pInterNew = Inter_ManInterpolateM114pPudlak( pSat, vMapRoots, vMapVars );
+        else
+            p->pInterNew = Inter_ManpInterpolateM114( pSat, vMapRoots, vMapVars );
+p->timeInt += clock() - clk;
+    }
+    else if ( status == 1 )
+    {
+        RetValue = 0;
+    }
+    else
+    {
+        RetValue = -1;
+    }
+    M114p_SolverDelete( pSat );
+    Vec_IntFree( vMapRoots );
+    Vec_IntFree( vMapVars );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
+#endif
+
+
diff --git a/abc-build/src/proof/int/intMan.c b/abc-build/src/proof/int/intMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int/intMan.c
@@ -0,0 +1,165 @@
+/**CFile****************************************************************
+
+  FileName    [intMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [Interpolation manager procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 24, 2008.]
+
+  Revision    [$Id: intMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+#include "aig/ioa/ioa.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the interpolation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Inter_Man_t * Inter_ManCreate( Aig_Man_t * pAig, Inter_ManParams_t * pPars )
+{
+    Inter_Man_t * p;
+    // create interpolation manager
+    p = ABC_ALLOC( Inter_Man_t, 1 );
+    memset( p, 0, sizeof(Inter_Man_t) );
+    p->vVarsAB = Vec_IntAlloc( Aig_ManRegNum(pAig) );
+    p->nConfLimit = pPars->nBTLimit;
+    p->fVerbose = pPars->fVerbose;
+    p->pFileName = pPars->pFileName;
+    p->pAig = pAig;
+    if ( pPars->fDropInvar )
+        p->vInters = Vec_PtrAlloc( 100 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the interpolation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Inter_ManClean( Inter_Man_t * p )
+{
+    if ( p->vInters )
+    {
+        Aig_Man_t * pMan;
+        int i;
+        Vec_PtrForEachEntry( Aig_Man_t *, p->vInters, pMan, i )
+            Aig_ManStop( pMan );
+        Vec_PtrClear( p->vInters );
+    }
+    if ( p->pCnfInter )
+        Cnf_DataFree( p->pCnfInter );
+    if ( p->pCnfFrames )
+        Cnf_DataFree( p->pCnfFrames );
+    if ( p->pInter )
+        Aig_ManStop( p->pInter );
+    if ( p->pFrames )
+        Aig_ManStop( p->pFrames );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes interpolant into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Inter_ManInterDump( Inter_Man_t * p, int fProved )
+{
+    char * pFileName = p->pFileName ? p->pFileName : (char *)"invar.aig";
+    Aig_Man_t * pMan;
+    pMan = Aig_ManDupArray( p->vInters );
+    Ioa_WriteAiger( pMan, pFileName, 0, 0 );
+    Aig_ManStop( pMan );
+    if ( fProved )
+        printf( "Inductive invariant is dumped into file \"%s\".\n", pFileName );
+    else
+        printf( "Interpolants are dumped into file \"%s\".\n", pFileName );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the interpolation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Inter_ManStop( Inter_Man_t * p, int fProved )
+{
+    if ( p->fVerbose )
+    {
+        p->timeOther = p->timeTotal-p->timeRwr-p->timeCnf-p->timeSat-p->timeInt-p->timeEqu;
+        printf( "Runtime statistics:\n" );
+        ABC_PRTP( "Rewriting  ", p->timeRwr,   p->timeTotal );
+        ABC_PRTP( "CNF mapping", p->timeCnf,   p->timeTotal );
+        ABC_PRTP( "SAT solving", p->timeSat,   p->timeTotal );
+        ABC_PRTP( "Interpol   ", p->timeInt,   p->timeTotal );
+        ABC_PRTP( "Containment", p->timeEqu,   p->timeTotal );
+        ABC_PRTP( "Other      ", p->timeOther, p->timeTotal );
+        ABC_PRTP( "TOTAL      ", p->timeTotal, p->timeTotal );
+    }
+
+    if ( p->vInters )
+        Inter_ManInterDump( p, fProved );
+
+    if ( p->pCnfAig )
+        Cnf_DataFree( p->pCnfAig );
+    if ( p->pAigTrans )
+        Aig_ManStop( p->pAigTrans );
+    if ( p->pInterNew )
+        Aig_ManStop( p->pInterNew );
+    Inter_ManClean( p );
+    Vec_PtrFreeP( &p->vInters );
+    Vec_IntFreeP( &p->vVarsAB );
+    ABC_FREE( p );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/int/intUtil.c b/abc-build/src/proof/int/intUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int/intUtil.c
@@ -0,0 +1,108 @@
+/**CFile****************************************************************
+
+  FileName    [intUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [Various interpolation utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 24, 2008.]
+
+  Revision    [$Id: intUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the property fails in the initial state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Inter_ManCheckInitialState( Aig_Man_t * p )
+{
+    Cnf_Dat_t * pCnf;
+    Aig_Obj_t * pObj;
+    sat_solver * pSat;
+    int i, status;
+    abctime clk = Abc_Clock();
+    pCnf = Cnf_Derive( p, Saig_ManRegNum(p) ); 
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 1 );
+    if ( pSat == NULL )
+    {
+        Cnf_DataFree( pCnf );
+        return 0;
+    }
+    status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    if ( status == l_True )
+    {
+        p->pSeqModel = Abc_CexAlloc( Aig_ManRegNum(p), Saig_ManPiNum(p), 1 );
+        Saig_ManForEachPi( p, pObj, i )
+            if ( sat_solver_var_value( pSat, pCnf->pVarNums[Aig_ObjId(pObj)] ) )
+                Abc_InfoSetBit( p->pSeqModel->pData, Aig_ManRegNum(p) + i );
+    }
+    Cnf_DataFree( pCnf );
+    sat_solver_delete( pSat );
+    return status == l_True;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the property holds in all states.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Inter_ManCheckAllStates( Aig_Man_t * p )
+{
+    Cnf_Dat_t * pCnf;
+    sat_solver * pSat;
+    int status;
+    abctime clk = Abc_Clock();
+    pCnf = Cnf_Derive( p, Saig_ManRegNum(p) ); 
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+    Cnf_DataFree( pCnf );
+    if ( pSat == NULL )
+        return 1;
+    status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    sat_solver_delete( pSat );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    return status == l_False;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/int/module.make b/abc-build/src/proof/int/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int/module.make
@@ -0,0 +1,10 @@
+SRC +=	src/proof/int/intCheck.c \
+	src/proof/int/intContain.c \
+	src/proof/int/intCore.c \
+	src/proof/int/intCtrex.c \
+	src/proof/int/intDup.c \
+	src/proof/int/intFrames.c \
+	src/proof/int/intInter.c \
+	src/proof/int/intM114.c \
+	src/proof/int/intMan.c \
+	src/proof/int/intUtil.c
diff --git a/abc-build/src/proof/int2/int2.h b/abc-build/src/proof/int2/int2.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int2/int2.h
@@ -0,0 +1,90 @@
+/**CFile****************************************************************
+
+  FileName    [int2.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 1, 2013.]
+
+  Revision    [$Id: int2.h,v 1.00 2013/12/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__int2__int_h
+#define ABC__aig__int2__int_h
+
+
+/* 
+    The interpolation algorithm implemented here was introduced in the papers:
+    K. L. McMillan. Interpolation and SAT-based model checking. CAV03, pp. 1-13.
+    C.-Y. Wu et al. A CEX-Guided Interpolant Generation Algorithm for 
+    SAT-based Model Checking. DAC'13.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// simulation manager
+typedef struct Int2_ManPars_t_ Int2_ManPars_t;
+struct Int2_ManPars_t_
+{
+    int     nBTLimit;       // limit on the number of conflicts
+    int     nFramesS;       // the starting number timeframes
+    int     nFramesMax;     // the max number timeframes to unroll
+    int     nSecLimit;      // time limit in seconds
+    int     nFramesK;       // the number of timeframes to use in induction
+    int     fRewrite;       // use additional rewriting to simplify timeframes
+    int     fTransLoop;     // add transition into the init state under new PI var
+    int     fDropInvar;     // dump inductive invariant into file
+    int     fVerbose;       // print verbose statistics
+    int     iFrameMax;      // the time frame reached
+    char *  pFileName;      // file name to dump interpolant
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== intCore.c ==========================================================*/
+extern void       Int2_ManSetDefaultParams( Int2_ManPars_t * p );
+extern int        Int2_ManPerformInterpolation( Gia_Man_t * p, Int2_ManPars_t * pPars );
+
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/int2/int2Bmc.c b/abc-build/src/proof/int2/int2Bmc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int2/int2Bmc.c
@@ -0,0 +1,355 @@
+/**CFile****************************************************************
+
+  FileName    [int2Bmc.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [BMC used inside IMC.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 1, 2013.]
+
+  Revision    [$Id: int2Bmc.c,v 1.00 2013/12/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "int2Int.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    [Trasnforms AIG to transition into the init state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Int2_ManDupInit( Gia_Man_t * p, int fVerbose )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pObjRi, * pObjRo;
+    int i, iCtrl;
+    assert( Gia_ManRegNum(p) > 0 );
+    pNew = Gia_ManStart( 10000 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+    {
+        if ( i == Gia_ManPiNum(p) )
+            iCtrl = Gia_ManAppendCi( pNew );
+        pObj->Value = Gia_ManAppendCi( pNew );
+    }
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachPo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManForEachRiRo( p, pObjRi, pObjRo, i )
+        Gia_ManAppendCo( pNew, Gia_ManHashMux( pNew, iCtrl, pObjRo->Value, Gia_ObjFanin0Copy(pObjRi) ) );
+    Gia_ManHashStop( pNew );
+    Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+    // remove dangling
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    if ( fVerbose )
+        printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", 
+            Gia_ManAndNum(pTemp), Gia_ManAndNum(pNew) );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if AIG has transition into init state.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Int2_ManCheckInit( Gia_Man_t * p )
+{
+    sat_solver * pSat;
+    Cnf_Dat_t * pCnf;
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vLits;
+    int i, Lit, RetValue = 0;
+    assert( Gia_ManRegNum(p) > 0 );
+    pNew = Jf_ManDeriveCnf( p, 0 );  
+    pCnf = (Cnf_Dat_t *)pNew->pData; pNew->pData = NULL;
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+    if ( pSat != NULL )
+    {
+        vLits = Vec_IntAlloc( Gia_ManRegNum(p) );
+        Gia_ManForEachRi( pNew, pObj, i )
+        {
+            Lit = pCnf->pVarNums[ Gia_ObjId(pNew, Gia_ObjFanin0(pObj)) ];
+            Lit = Abc_Var2Lit( Lit, Gia_ObjFaninC0(pObj) );
+            Vec_IntPush( vLits, Abc_LitNot(Lit) );
+        }
+        if ( sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 ) == l_True )
+            RetValue = 1;
+        Vec_IntFree( vLits );
+        sat_solver_delete( pSat );
+    }
+    Cnf_DataFree( pCnf );
+    Gia_ManStop( pNew );
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the BMC instance in the SAT solver.]
+
+  Description [The PIs are mapped in the natural order. The flop inputs
+  are the last Gia_ManRegNum(p) variables of resulting SAT solver.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Int2_ManFrameInit( Gia_Man_t * p, int nFrames, int fVerbose )
+{
+    Gia_Man_t * pFrames, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, f;
+    pFrames = Gia_ManStart( 10000 );
+    pFrames->pName = Abc_UtilStrsav( p->pName );
+    pFrames->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    // perform structural hashing
+    Gia_ManHashAlloc( pFrames );
+    for ( f = 0; f < nFrames; f++ )
+    {
+        Gia_ManForEachPi( p, pObj, i )
+            pObj->Value = Gia_ManAppendCi( pFrames );
+        Gia_ManForEachRo( p, pObj, i )
+            pObj->Value = f ? Gia_ObjRoToRi(p, pObj)->Value : 0;
+        Gia_ManForEachAnd( p, pObj, i )
+            pObj->Value = Gia_ManHashAnd( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        Gia_ManForEachRi( p, pObj, i )
+            pObj->Value = Gia_ObjFanin0Copy(pObj);
+    }
+    Gia_ManHashStop( pFrames );
+    // create flop inputs
+    Gia_ManForEachRi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pFrames, Gia_ObjFanin0Copy(pObj) );
+    // remove dangling
+    pFrames = Gia_ManCleanup( pTemp = pFrames );
+    if ( fVerbose )
+        printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", 
+            Gia_ManAndNum(pTemp), Gia_ManAndNum(pFrames) );
+    Gia_ManStop( pTemp );
+    return pFrames;
+}
+sat_solver * Int2_ManSetupBmcSolver( Gia_Man_t * p, int nFrames )
+{
+    Gia_Man_t * pFrames, * pTemp;
+    Cnf_Dat_t * pCnf;
+    sat_solver * pSat;
+    // unfold for the given number of timeframes
+    pFrames = Int2_ManFrameInit( p, nFrames, 1 );
+    assert( Gia_ManRegNum(pFrames) == 0 );
+    // derive CNF for the timeframes
+    pFrames = Jf_ManDeriveCnf( pTemp = pFrames, 0 );  Gia_ManStop( pTemp );
+    pCnf = (Cnf_Dat_t *)pFrames->pData; pFrames->pData = NULL;
+    // create SAT solver
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+    if ( pSat != NULL )
+    {
+        Gia_Obj_t * pObj;
+        int i, nVars = sat_solver_nvars( pSat );
+        sat_solver_setnvars( pSat, nVars + Gia_ManPoNum(pFrames) );
+        // add clauses for the POs
+        Gia_ManForEachCo( pFrames, pObj, i )
+            sat_solver_add_buffer( pSat, nVars + i, pCnf->pVarNums[Gia_ObjId(pFrames, Gia_ObjFanin0(pObj))], Gia_ObjFaninC0(pObj) );
+    }
+    Cnf_DataFree( pCnf );
+    Gia_ManStop( pFrames );
+    return pSat;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Int2_ManCheckFrames( Int2_Man_t * p, int iFrame, int iObj )
+{
+    Vec_Int_t * vMapFrame = (Vec_Int_t *)Vec_PtrEntry(p->vMapFrames, iFrame);
+    return Vec_IntEntry(vMapFrame, iObj);
+}
+static inline void Int2_ManWriteFrames( Int2_Man_t * p, int iFrame, int iObj, int iRes )
+{
+    Vec_Int_t * vMapFrame = (Vec_Int_t *)Vec_PtrEntry(p->vMapFrames, iFrame);
+    assert( Vec_IntEntry(vMapFrame, iObj) == -1 );
+    Vec_IntWriteEntry( vMapFrame, iObj, iRes );
+}
+void Int2_ManCreateFrames( Int2_Man_t * p, int iFrame, Vec_Int_t * vPrefCos )
+{
+    Gia_Obj_t * pObj;
+    int i, Entry, iLit;
+    // create storage room for unfolded IDs
+    for ( i = Vec_PtrSize(p->vMapFrames); i <= iFrame; i++ )
+        Vec_PtrPush( p->vMapFrames, Vec_IntStartFull( Gia_ManObjNum(p->pGia) ) );
+    assert( Vec_PtrSize(p->vMapFrames) == iFrame + 1 );
+    // create constant 0 node
+    if ( f == 0 )
+    {
+        iLit = 1;
+        Int2_ManWriteFrames( p, iFrame, iObj, 0 );
+        sat_solver_addclause( p->pGiaPref, &iLit, &iLit + 1 );
+    }
+    // start the stack
+    Vec_IntClear( p->vStack );
+    Vec_IntForEachEntry( vPrefCos, Entry, i )
+    {
+        pObj = Gia_ManCo( p->pGia, Entry );
+        Vec_IntPush( p->vStack, iFrame );
+        Vec_IntPush( p->vStack, Gia_ObjId(p->pGia, pObj) );
+    }
+    // construct unfolded AIG
+    while ( Vec_IntSize(p->vStack) > 0 )
+    {
+        int iObj   = Vec_IntPop(p->vStack);
+        int iFrame = Vec_IntPop(p->vStack);
+        if ( Int2_ManCheckFrames(p, iFrame, iObj) >= 0 )
+            continue;
+        pObj = Gia_ManObj( p->pGia, iObj );
+        if ( Gia_ObjIsPi(p->pGia, pObj) )
+            Int2_ManWriteFrames( p, iFrame, iObj, Gia_ManAppendCi(p->pFrames) );
+        else if ( iFrame == 0 && Gia_ObjIsRo(p->pGia, iObj) )
+            Int2_ManWriteFrames( p, iFrame, iObj, 0 );
+        else if ( Gia_ObjIsRo(p->pGia, iObj) )
+        {
+            int iObjF = Gia_ObjId( p->pGia, Gia_ObjRoToRi(p->pGia, pObj) );
+            int iLit = Int2_ManCheckFrames( p, iFrame-1, iObjF );
+            if ( iLit >= 0 )
+                Int2_ManWriteFrames( p, iFrame, iObj, iLit );
+            else
+            {
+                Vec_IntPush( p->vStack, iFrame );
+                Vec_IntPush( p->vStack, iObj );
+                Vec_IntPush( p->vStack, iFrame-1 );
+                Vec_IntPush( p->vStack, iObjF );
+            }
+        }
+        else if ( Gia_ObjIsCo(pObj) )
+        {
+            int iObjF = Gia_ObjFaninId0(p->pGia, iObj) );
+            int iLit = Int2_ManCheckFrames( p, iFrame, iObjF );
+            if ( iLit >= 0 )
+                Int2_ManWriteFrames( p, iFrame, iObj, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) );
+            else
+            {
+                Vec_IntPush( p->vStack, iFrame );
+                Vec_IntPush( p->vStack, iObj );
+                Vec_IntPush( p->vStack, iFrame );
+                Vec_IntPush( p->vStack, iObjF );
+            }
+        }
+        else if ( Gia_ObjIsAnd(pObj) )
+        {
+            int iObjF0 = Gia_ObjFaninId0(p->pGia, iObj) );
+            int iLit0 = Int2_ManCheckFrames( p, iFrame, iObjF0 );
+            int iObjF1 = Gia_ObjFaninId1(p->pGia, iObj) );
+            int iLit1 = Int2_ManCheckFrames( p, iFrame, iObjF1 );
+            if ( iLit0 >= 0 && iLit1 >= 0 )
+            {
+                Entry = Gia_ManObjNum(pFrames);
+                iLit = Gia_ManHashAnd(pFrames, iLit0, iLit1);
+                Int2_ManWriteFrames( p, iFrame, iObj, iLit );
+                if ( Entry < Gia_ManObjNum(pFrames) )
+                {
+                    assert( !Abc_LitIsCompl(iLit) );
+                    sat_solver_add_and( p->pGiaPref, Abc_Lit2Var(iLit), Abc_Lit2Var(iLit0), Abc_Lit2Var(iLit1), Abc_LitIsCompl(iLit0), Abc_LitIsCompl(iLit1), 0 ); 
+                }
+            }
+            else
+            {
+                Vec_IntPush( p->vStack, iFrame );
+                Vec_IntPush( p->vStack, iObj );
+                if ( iLit0 < 0 )
+                {
+                    Vec_IntPush( p->vStack, iFrame );
+                    Vec_IntPush( p->vStack, iObjF0 );
+                }
+                if ( iLit1 < 0 )
+                {
+                    Vec_IntPush( p->vStack, iFrame );
+                    Vec_IntPush( p->vStack, iObjF1 );
+                }
+            }
+        }
+        else assert( 0 );
+    }
+}
+int Int2_ManCheckBmc( Int2_Man_t * p, Vec_Int_t * vCube )
+{
+    int status;
+    if ( vCube == NULL )
+    {
+        Gia_Obj_t * pObj;
+        int i, iLit;
+        Gia_ManForEachPo( p->pGia, pObj, i )
+        {
+            iLit = Int2_ManCheckFrames( p, 0, Gia_ObjId(p->pGia, pObj) );
+            if ( iLit == 0 )
+                continue;
+            if ( iLit == 1 )
+                return 0;
+            status = sat_solver_solve( p->pSatPref, &iLit, &iLit + 1, 0, 0, 0, 0 );
+            if ( status == l_False )
+                continue;
+            if ( status == l_True )
+                return 0;
+            return -1;
+        }
+        return 1;
+    }
+    status = sat_solver_solve( p->pSatPref, Vec_IntArray(vCube), Vec_IntArray(vCube) + Vec_IntSize(vCube), 0, 0, 0, 0 );
+    if ( status == l_False )
+        return 1;
+    if ( status == l_True )
+        return 0;
+    return -1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/int2/int2Core.c b/abc-build/src/proof/int2/int2Core.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int2/int2Core.c
@@ -0,0 +1,335 @@
+/**CFile****************************************************************
+
+  FileName    [int2Core.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [Core procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 1, 2013.]
+
+  Revision    [$Id: int2Core.c,v 1.00 2013/12/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "int2Int.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default values of interpolation parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Int2_ManSetDefaultParams( Int2_ManPars_t * p )
+{ 
+    memset( p, 0, sizeof(Int2_ManPars_t) );
+    p->nBTLimit      =  0;     // limit on the number of conflicts
+    p->nFramesS      =  1;     // the starting number timeframes
+    p->nFramesMax    =  0;     // the max number timeframes to unroll
+    p->nSecLimit     =  0;     // time limit in seconds
+    p->nFramesK      =  1;     // the number of timeframes to use in induction
+    p->fRewrite      =  0;     // use additional rewriting to simplify timeframes
+    p->fTransLoop    =  0;     // add transition into the init state under new PI var
+    p->fDropInvar    =  0;     // dump inductive invariant into file
+    p->fVerbose      =  0;     // print verbose statistics
+    p->iFrameMax     = -1;
+}
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Int2_ManUnroll( Gia_Man_t * p, int nFrames )
+{
+    Gia_Man_t * pFrames, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, f;
+    assert( Gia_ManRegNum(pAig) > 0 );
+    pFrames = Gia_ManStart( Gia_ManObjNum(pAig) );
+    pFrames->pName = Abc_UtilStrsav( pAig->pName );
+    pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec );
+    Gia_ManHashAlloc( pFrames );
+    Gia_ManConst0(pAig)->Value = 0;
+    for ( f = 0; f < nFrames; f++ )
+    {
+        Gia_ManForEachRo( pAig, pObj, i )
+            pObj->Value = f ? Gia_ObjRoToRi( pAig, pObj )->Value : 0;
+        Gia_ManForEachPi( pAig, pObj, i )
+            pObj->Value = Gia_ManAppendCi( pFrames );
+        Gia_ManForEachAnd( pAig, pObj, i )
+            pObj->Value = Gia_ManHashAnd( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        Gia_ManForEachRi( pAig, pObj, i )
+            pObj->Value = Gia_ObjFanin0Copy(pObj);
+    }
+    Gia_ManForEachRi( pAig, pObj, i )
+        Gia_ManAppendCo( pFrames, pObj->Value );
+    Gia_ManHashStop( pFrames );
+    pFrames = Gia_ManCleanup( pTemp = pFrames );
+    Gia_ManStop( pTemp );
+    return pFrames;
+}
+sat_solver * Int2_ManPreparePrefix( Gia_Man_t * p, int f, Vec_Int_t ** pvCiMap )
+{
+    Gia_Man_t * pPref, * pNew;
+    sat_solver * pSat;
+    // create subset of the timeframe
+    pPref = Int2_ManUnroll( p, f );
+    // create SAT solver
+    pNew = Jf_ManDeriveCnf( pPref, 0 );  
+    pCnf = (Cnf_Dat_t *)pPref->pData; pPref->pData = NULL;
+    Gia_ManStop( pPref );
+    // derive the SAT solver
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+    // collect indexes of CO variables
+    *pvCiMap = Vec_IntAlloc( 100 );
+    Gia_ManForEachPo( pNew, pObj, i )     
+        Vec_IntPush( *pvCiMap, pCnf->pVarNums[ Gia_ObjId(pNew, pObj) ] );
+    // cleanup
+    Cnf_DataFree( pCnf );
+    Gia_ManStop( pNew );
+    return pSat;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+sat_solver * Int2_ManPrepareSuffix( Gia_Man_t * p, Vec_Int_t * vImageOne, Vec_Int_t * vImagesAll, Vec_Int_t ** pvCoMap, Gia_Man_t ** ppSuff )
+{
+    Gia_Man_t * pSuff, * pNew;
+    Gia_Obj_t * pObj;
+    Cnf_Dat_t * pCnf;
+    sat_solver * pSat;
+    Vec_Int_t * vLits;
+    int i, Lit, Limit;
+    // create subset of the timeframe
+    pSuff = Int2_ManProbToGia( p, vImageOne );
+    assert( Gia_ManPiNum(pSuff) == Gia_ManCiNum(p) );
+    // create SAT solver
+    pNew = Jf_ManDeriveCnf( pSuff, 0 );  
+    pCnf = (Cnf_Dat_t *)pSuff->pData; pSuff->pData = NULL;
+    Gia_ManStop( pSuff );
+    // derive the SAT solver
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+    // create new constraints
+    vLits = Vec_IntAlloc( 1000 );
+    Vec_IntForEachEntryStart( vImagesAll, Limit, i, 1 )
+    {
+        Vec_IntClear( vLits );
+        for ( k = 0; k < Limit; k++ )
+        {
+            i++;
+            Lit = Vec_IntEntry( vSop, i + k );
+            Vec_IntPush( vLits, Abc_LitNot(Lit) );
+        }
+        if ( !sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) )  )  // UNSAT
+        {
+            Vec_IntFree( vLits );
+            Cnf_DataFree( pCnf );
+            Gia_ManStop( pNew );
+            *pvCoMap = NULL;
+            return NULL;
+        }
+    }
+    Vec_IntFree( vLits );
+    // collect indexes of CO variables
+    *pvCoMap = Vec_IntAlloc( 100 );
+    Gia_ManForEachRo( p, pObj, i )     
+    {
+        pObj = Gia_ManPi( pNew, i + Gia_ManPiNum(p) );
+        Vec_IntPush( *pvCoMap, pCnf->pVarNums[ Gia_ObjId(pNew, pObj) ] );
+    }
+    // cleanup
+    Cnf_DataFree( pCnf );
+    if ( ppSuff )
+        *ppSuff = pNew;
+    else
+        Gia_ManStop( pNew );
+    return pSat;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the cube cover and status.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Int2_ManComputePreimage( Gia_Man_t * pSuff, sat_solver * pSatPref, sat_solver * pSatSuff, Vec_Int_t * vCiMap, Vec_Int_t * vCoMap, Vec_Int_t * vPrio )
+{
+    int i, iVar, status;
+    Vec_IntClear( p->vImage );
+    while ( 1 )
+    {
+        // run suffix solver
+        status = sat_solver_solve( p->pSatSuff, NULL, NULL, 0, 0, 0, 0 );
+        if ( status == l_Undef )
+            return NULL; // timeout
+        if ( status == l_False )
+            return INT2_COMPUTED;
+        assert( status == l_True );
+        // collect assignment
+        Vec_IntClear( p->vAssign );
+        Vec_IntForEachEntry( p->vCiMap, iVar, i )
+            Vec_IntPush( p->vAssign, sat_solver_var_value(p->pSatSuff, iVar) );
+        // derive initial cube
+        vCube = Int2_ManRefineCube( p->pSuff, p->vAssign, p->vPrio );
+        // expend the cube using prefix
+        status = sat_solver_solve( p->pSatPref, Vec_IntArray(vCube), Vec_IntArray(vCube) + Vec_IntSize(vCube), 0, 0, 0, 0 );
+        if ( status == l_False )
+        {
+            int k, nCoreLits, * pCoreLits;
+            nCoreLits = sat_solver_final( p->pSatPref, &pCoreLits );
+            // create cube
+            Vec_IntClear( vCube );
+            Vec_IntPush( vImage, nCoreLits );
+            for ( k = 0; k < nCoreLits; k++ )
+            {
+                Vec_IntPush( vCube, pCoreLits[k] );
+                Vec_IntPush( vImage, pCoreLits[k] );
+            }
+            // add cube to the solver
+            if ( !sat_solver_addclause( p->pSatSuff, Vec_IntArray(vCube), Vec_IntArray(vCube) + Vec_IntSize(vCube) ) )
+            {
+                Vec_IntFree( vCube );
+                return INT2_COMPUTED;
+            }
+        }
+        Vec_IntFree( vCube );
+        if ( status == l_Undef )
+            return INT2_TIME_OUT;
+        if ( status == l_True )
+            return INT2_FALSE_NEG;
+        assert( status == l_False );
+        continue;
+    }
+    return p->vImage;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Interpolates while the number of conflicts is not exceeded.]
+
+  Description [Returns 1 if proven. 0 if failed. -1 if undecided.]
+               
+  SideEffects [Does not check the property in 0-th frame.]
+
+  SeeAlso     []
+
+***********************************************************************/
+int Int2_ManPerformInterpolation( Gia_Man_t * pInit, Int2_ManPars_t * pPars )
+{
+    Int2_Man_t * p;
+    int f, i, RetValue = -1;
+    abctime clk, clkTotal = Abc_Clock(), timeTemp = 0;
+    abctime nTimeToStop = pPars->nSecLimit ? pPars->nSecLimit * CLOCKS_PER_SEC + Abc_Clock() : 0;
+
+    // sanity checks
+    assert( Gia_ManPiNum(pInit) > 0 );
+    assert( Gia_ManPoNum(pInit) > 0 );
+    assert( Gia_ManRegNum(pInit) > 0 );
+
+    // create manager
+    p = Int2_ManCreate( pInit, pPars );
+
+    // create SAT solver
+    p->pSatPref = sat_solver_new();
+    sat_solver_setnvars( p->pSatPref, 1000 );
+    sat_solver_set_runtime_limit( p->pSatPref, nTimeToStop );
+
+    // check outputs in the first frame
+    for ( i = 0; i < Gia_ManPoNum(pInit); i++ )
+        Vec_IntPush( p->vPrefCos, i );
+    Int2_ManCreateFrames( p, 0, p->vPrefCos );
+    RetValue = Int2_ManCheckBmc( p, NULL );
+    if ( RetValue != 1 )
+        return RetValue;
+
+    // create original image
+    for ( f = pPars->nFramesS; f < p->nFramesMax; f++ )
+    {
+        for ( i = 0; i < p->nFramesMax; i++ )
+        {
+            p->pSatSuff = Int2_ManPrepareSuffix( p, vImageOne. vImagesAll, &vCoMap, &pGiaSuff );
+            sat_solver_set_runtime_limit( p->pSatSuff, nTimeToStop );
+            Vec_IntFreeP( &vImageOne );
+            vImageOne = Int2_ManComputePreimage( pGiaSuff, p->pSatPref, p->pSatSuff, vCiMap, vCoMap );
+            Vec_IntFree( vCoMap );
+            Gia_ManStop( pGiaSuff );
+            if ( nTimeToStop && Abc_Clock() > nTimeToStop )
+                return -1;
+            if ( vImageOne == NULL )
+            {
+                if ( i == 0 )
+                {
+                    printf( "Satisfiable in frame %d.\n", f );
+                    Vec_IntFree( vCiMap );
+                    sat_solver_delete( p->pSatPref ); p->pSatPref = NULL;
+                    return 0;
+                }
+                f += i;
+                break;
+            }
+            Vec_IntAppend( vImagesAll, vImageOne );
+            sat_solver_delete( p->pSatSuff ); p->pSatSuff = NULL;
+        }
+        Vec_IntFree( vCiMap );
+        sat_solver_delete( p->pSatPref ); p->pSatPref = NULL;
+    }
+    Abc_PrintTime( "Time", Abc_Clock() - clk );
+
+
+p->timeSatPref += Abc_Clock() - clk;
+
+    Int2_ManStop( p );
+    return RetValue;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/int2/int2Int.h b/abc-build/src/proof/int2/int2Int.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int2/int2Int.h
@@ -0,0 +1,164 @@
+/**CFile****************************************************************
+
+  FileName    [int2Int.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 1, 2013.]
+
+  Revision    [$Id: int2Int.h,v 1.00 2013/12/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__Gia__int2__intInt_h
+#define ABC__Gia__int2__intInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "aig/gia/gia.h"
+#include "sat/bsat/satSolver.h"
+#include "sat/cnf/cnf.h"
+#include "int2.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// interpolation manager
+typedef struct Int2_Man_t_ Int2_Man_t;
+struct Int2_Man_t_
+{
+    // parameters
+    Int2_ManPars_t * pPars;        // parameters
+    // GIA managers
+    Gia_Man_t *      pGia;         // original manager
+    Gia_Man_t *      pGiaPref;     // prefix manager
+    Gia_Man_t *      pGiaSuff;     // suffix manager
+    // subset of the manager
+    Vec_Int_t *      vSuffCis;     // suffix CIs
+    Vec_Int_t *      vSuffCos;     // suffix COs
+    Vec_Int_t *      vPrefCos;     // suffix POs
+    Vec_Int_t *      vStack;       // temporary stack
+    // preimages
+    Vec_Int_t *      vImageOne;    // latest preimage
+    Vec_Int_t *      vImagesAll;   // cumulative preimage
+    // variable maps
+    Vec_Ptr_t *      vMapFrames;   // mapping of GIA IDs into frame IDs
+    Vec_Int_t *      vMapPref;     // mapping of flop inputs into SAT variables
+    Vec_Int_t *      vMapSuff;     // mapping of flop outputs into SAT variables
+    // initial minimization
+    Vec_Int_t *      vAssign;      // assignment of PIs in pGiaSuff
+    Vec_Int_t *      vPrio;        // priority of PIs in pGiaSuff
+    // SAT solving
+    sat_solver *     pSatPref;     // prefix solver
+    sat_solver *     pSatSuff;     // suffix solver
+    // runtime
+    abctime          timeSatPref;
+    abctime          timeSatSuff;
+    abctime          timeOther;
+    abctime          timeTotal;
+};
+
+static inline Int2_Man_t * Int2_ManCreate( Gia_Man_t * pGia, Int2_ManPars_t * pPars )
+{
+    Int2_Man_t * p;
+    p = ABC_CALLOC( Int2_Man_t, 1 );
+    p->pPars       = pPars;
+    p->pGia        = pGia;
+    p->pGiaPref    = Gia_ManStart( 10000 );
+    // perform structural hashing
+    Gia_ManHashAlloc( pFrames );
+    // subset of the manager
+    p->vSuffCis    = Vec_IntAlloc( Gia_ManCiNum(pGia) );
+    p->vSuffCos    = Vec_IntAlloc( Gia_ManCoNum(pGia) );
+    p->vPrefCos    = Vec_IntAlloc( Gia_ManCoNum(pGia) );
+    p->vStack      = Vec_IntAlloc( 10000 );
+    // preimages
+    p->vImageOne   = Vec_IntAlloc( 1000 );
+    p->vImagesAll  = Vec_IntAlloc( 1000 );
+    // variable maps
+    p->vMapFrames  = Vec_PtrAlloc( 100 );
+    p->vMapPref    = Vec_IntAlloc( Gia_ManRegNum(pGia) );
+    p->vMapSuff    = Vec_IntAlloc( Gia_ManRegNum(pGia) );
+    // initial minimization
+    p->vAssign     = Vec_IntAlloc( Gia_ManCiNum(pGia) );
+    p->vPrio       = Vec_IntAlloc( Gia_ManCiNum(pGia) );
+    return p;
+}
+static inline void Int2_ManStop( Int2_Man_t * p )
+{
+    // GIA managers
+    Gia_ManStopP( &p->pGiaPref );
+    Gia_ManStopP( &p->pGiaSuff );
+    // subset of the manager
+    Vec_IntFreeP( &p->vSuffCis );
+    Vec_IntFreeP( &p->vSuffCos );
+    Vec_IntFreeP( &p->vPrefCos );
+    Vec_IntFreeP( &p->vStack );
+    // preimages
+    Vec_IntFreeP( &p->vImageOne );
+    Vec_IntFreeP( &p->vImagesAll );
+    // variable maps
+    Vec_VecFree( (Vec_Vec_t *)p->vMapFrames );
+    Vec_IntFreeP( &p->vMapPref );
+    Vec_IntFreeP( &p->vMapSuff );
+    // initial minimization
+    Vec_IntFreeP( &p->vAssign );
+    Vec_IntFreeP( &p->vPrio );
+    // SAT solving
+    if ( p->pSatPref )
+        sat_solver_delete( p->pSatPref );
+    if ( p->timeSatSuff )
+        sat_solver_delete( p->pSatSuff );
+    ABC_FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== int2Bmc.c =============================================================*/
+extern int           Int2_ManCheckInit( Gia_Man_t * p );
+extern Gia_Man_t *   Int2_ManDupInit( Gia_Man_t * p, int fVerbose );
+extern sat_solver *  Int2_ManSetupBmcSolver( Gia_Man_t * p, int nFrames );
+extern void          Int2_ManCreateFrames( Int2_Man_t * p, int iFrame, Vec_Int_t * vPrefCos );
+extern int           Int2_ManCheckBmc( Int2_Man_t * p, Vec_Int_t * vCube );
+
+/*=== int2Refine.c =============================================================*/
+extern Vec_Int_t *   Int2_ManRefineCube( Gia_Man_t * p, Vec_Int_t * vAssign, Vec_Int_t * vPrio );
+
+/*=== int2Util.c ============================================================*/
+extern Gia_Man_t *   Int2_ManProbToGia( Gia_Man_t * p, Vec_Int_t * vSop );
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/int2/int2Refine.c b/abc-build/src/proof/int2/int2Refine.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int2/int2Refine.c
@@ -0,0 +1,154 @@
+/**CFile****************************************************************
+
+  FileName    [int2Refine.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [Various utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 1, 2013.]
+
+  Revision    [$Id: int2Refine.c,v 1.00 2013/12/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "int2Int.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Int2_ManJustify_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSelect )
+{ 
+    if ( pObj->fMark1 )
+        return;
+    pObj->fMark1 = 1;
+    if ( Gia_ObjIsPi(p, pObj) )
+        return;
+    if ( Gia_ObjIsCo(pObj) )
+    {
+        Vec_IntPush( vSelect, Gia_ObjCioId(pObj) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    if ( pObj->Value == 1 )
+    {
+        if ( Gia_ObjFanin0(pObj)->Value < ABC_INFINITY )
+            Int2_ManJustify_rec( p, Gia_ObjFanin0(pObj), vSelect );
+        if ( Gia_ObjFanin1(pObj)->Value < ABC_INFINITY )
+            Int2_ManJustify_rec( p, Gia_ObjFanin1(pObj), vSelect );
+        return;
+    }
+    if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 && (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)) == 0 )
+    {
+        if ( Gia_ObjFanin0(pObj)->fMark0 <= Gia_ObjFanin1(pObj)->fMark0 ) // choice
+        {
+            if ( Gia_ObjFanin0(pObj)->Value < ABC_INFINITY )
+                Int2_ManJustify_rec( p, Gia_ObjFanin0(pObj), vSelect );
+        }
+        else
+        {
+            if ( Gia_ObjFanin1(pObj)->Value < ABC_INFINITY )
+                Int2_ManJustify_rec( p, Gia_ObjFanin1(pObj), vSelect );
+        }
+    }
+    else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 )
+    {
+        if ( Gia_ObjFanin0(pObj)->Value < ABC_INFINITY )
+            Int2_ManJustify_rec( p, Gia_ObjFanin0(pObj), vSelect );
+    }
+    else if ( (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)) == 0 )
+    {
+        if ( Gia_ObjFanin1(pObj)->Value < ABC_INFINITY )
+            Int2_ManJustify_rec( p, Gia_ObjFanin1(pObj), vSelect );
+    }
+    else assert( 0 );
+ }
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the reduced set of flop variables.]
+
+  Description [Given is a single-output seq AIG manager and an assignment 
+  of its CIs.  Returned is a subset of flops that justifies the output.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Int2_ManRefineCube( Gia_Man_t * p, Vec_Int_t * vAssign, Vec_Int_t * vPrio )
+{
+    Vec_Int_t * vSubset;
+    Gia_Obj_t * pObj;
+    int i;
+    // set values and prios
+    assert( Gia_ManRegNum(p) > 0 );
+    assert( Vec_IntSize(vAssign) == Vec_IntSize(vPrio) );
+    Gia_ManConst0(p)->fMark0 = 0;
+    Gia_ManConst0(p)->fMark1 = 0;
+    Gia_ManConst0(p)->Value = ABC_INFINITY;
+    Gia_ManForEachCi( p, pObj, i )
+    {
+        pObj->fMark0 = Vec_IntEntry(vAssign, i);
+        pObj->fMark1 = 0;
+        pObj->Value  = Vec_IntEntry(vPrio, i);        
+    }
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+        pObj->fMark1 = 0;
+        if ( pObj->fMark0 == 1 )
+            pObj->Value = Abc_MaxInt( Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value );
+        else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 && (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)) == 0 )
+            pObj->Value = Abc_MinInt( Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); // choice
+        else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 )
+            pObj->Value = Gia_ObjFanin0(pObj)->Value;
+        else 
+            pObj->Value = Gia_ObjFanin1(pObj)->Value;
+    }
+    pObj = Gia_ManPo( p, 0 );
+    pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj));
+    pObj->fMark1 = 0;
+    pObj->Value  = Gia_ObjFanin0(pObj)->Value;
+    assert( pObj->fMark0 == 1 );
+    assert( pObj->Value < ABC_INFINITY );
+    // select subset
+    vSubset = Vec_IntAlloc( 100 );
+    Int2_ManJustify_rec( p, Gia_ObjFanin0(pObj), vSubset );
+    return vSubset;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/int2/int2Util.c b/abc-build/src/proof/int2/int2Util.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int2/int2Util.c
@@ -0,0 +1,152 @@
+/**CFile****************************************************************
+
+  FileName    [int2Util.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Interpolation engine.]
+
+  Synopsis    [Various utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - Dec 1, 2013.]
+
+  Revision    [$Id: int2Util.c,v 1.00 2013/12/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "int2Int.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Int2_ManComputeCoPres( Vec_Int_t * vSop, int nRegs )
+{
+    Vec_Int_t * vCoPres, * vMap;
+    vCoPres = Vec_IntAlloc( 100 );
+    if ( vSop == NULL )
+        Vec_IntPush( vCoPres, 0 );
+    else
+    {
+        int i, k, Limit;
+        vMap = Vec_IntStart( nRegs );
+        Vec_IntForEachEntryStart( vSop, Limit, i, 1 )
+        {
+            for ( k = 0; k < Limit; k++ )
+            {
+                i++;
+                assert( Vec_IntEntry(vSop, i + k) < 2 * nRegs );
+                Vec_IntWriteEntry( vMap, Abc_Lit2Var(Vec_IntEntry(vSop, i + k)), 1 );
+            }
+        }
+        Vec_IntForEachEntry( vMap, Limit, i )
+            if ( Limit )
+                Vec_IntPush( vCoPres, i+1 );
+        Vec_IntFree( vMap );
+    }
+    return vCoPres;
+}
+
+void Int2_ManCollectInternal_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes )
+{
+    if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Gia_ObjSetTravIdCurrent(p, pObj);
+    if ( Gia_ObjIsCi(pObj) )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    Int2_ManCollectInternal_rec( p, Gia_ObjFanin0(pObj), vNodes );
+    Int2_ManCollectInternal_rec( p, Gia_ObjFanin1(pObj), vNodes );
+    Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+}
+Vec_Int_t * Int2_ManCollectInternal( Gia_Man_t * p, Vec_Int_t * vCoPres )
+{
+    Vec_Int_t * vNodes;
+    Gia_Obj_t * pObj;
+    int i, Entry;
+    Gia_ManIncrementTravId( p );
+    Gia_ObjSetTravIdCurrent(p, Gia_ManConst0(p));
+    Gia_ManForEachCi( p, pObj, i )
+        Gia_ObjSetTravIdCurrent(p, pObj);
+    vNodes = Vec_IntAlloc( 1000 );
+    Vec_IntForEachEntry( vCoPres, Entry, i )
+        Int2_ManCollectInternal_rec( p, Gia_ObjFanin0(Gia_ManCo(p, Entry)), vNodes );
+    return vNodes;
+}
+Gia_Man_t * Int2_ManProbToGia( Gia_Man_t * p, Vec_Int_t * vSop )
+{
+    Vec_Int_t * vCoPres, * vNodes;
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, k, Entry, Limit;
+    int Lit, Cube, Sop;
+    assert( Gia_ManPoNum(p) == 1 );
+    // collect COs and ANDs
+    vCoPres = Int2_ManComputeCoPres( vSop, Gia_ManRegNum(p) );
+    vNodes = Int2_ManCollectInternal( p, vCoPres );
+    // create new manager
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi(pNew);
+    Gia_ManHashAlloc( pNew );
+    Gia_ManForEachObjVec( vNodes, p, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Vec_IntForEachEntry( vCoPres, Entry, i )
+    {
+        pObj = Gia_ManCo(p, Entry);
+        pObj->Value = Gia_ObjFanin0Copy( pObj );
+    }
+    // create additional cubes
+    Sop = 0;
+    Vec_IntForEachEntryStart( vSop, Limit, i, 1 )
+    {
+        Cube = 1;
+        for ( k = 0; k < Limit; k++ )
+        {
+            i++;
+            Lit = Vec_IntEntry( vSop, i + k );
+            pObj = Gia_ManRi( p, Abc_Lit2Var(Lit) );
+            Cube = Gia_ManHashAnd( pNew, Cube, Abc_LitNotCond(pObj->Value, Abc_LitIsCompl(Lit)) );
+        }
+        Sop = Gia_ManHashOr( pNew, Sop, Cube );
+    }
+    Gia_ManAppendCo( pNew, Sop );
+    Gia_ManHashStop( pNew );
+    // cleanup
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/int2/module.make b/abc-build/src/proof/int2/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/int2/module.make
@@ -0,0 +1,4 @@
+SRC +=	src/proof/int2/int2Bmc.c \
+	src/proof/int2/int2Core.c \
+	src/proof/int2/int2Refine.c \
+	src/proof/int2/int2Util.c
diff --git a/abc-build/src/proof/live/arenaViolation.c b/abc-build/src/proof/live/arenaViolation.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/live/arenaViolation.c
@@ -0,0 +1,549 @@
+/**CFile****************************************************************
+
+  FileName    [arenaViolation.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Liveness property checking.]
+
+  Synopsis    [module for addition of arena violator detector
+		induced by stabilizing constraints]
+
+  Author      [Sayak Ray]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 31, 2012.]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include "base/main/main.h"
+#include "aig/aig/aig.h"
+#include "aig/saig/saig.h"
+#include <string.h>
+#include "base/main/mainInt.h"
+#include "proof/pdr/pdr.h"
+
+//#define DISJUNCTIVE_CONSTRAINT_ENABLE_MODE
+#define BARRIER_MONOTONE_TEST
+
+ABC_NAMESPACE_IMPL_START
+
+Vec_Ptr_t * createArenaLO( Aig_Man_t *pAigNew, Vec_Ptr_t *vBarriers )
+{
+	Vec_Ptr_t *vArenaLO;
+	int barrierCount;
+	Aig_Obj_t *pObj;
+	int i;
+
+	if( vBarriers == NULL )
+		return NULL;
+
+	barrierCount = Vec_PtrSize(vBarriers);
+	if( barrierCount <= 0 )
+		return NULL;
+
+	vArenaLO = Vec_PtrAlloc(barrierCount);	
+	for( i=0; i<barrierCount; i++ )
+	{
+		pObj = Aig_ObjCreateCi( pAigNew );
+		Vec_PtrPush( vArenaLO, pObj );
+	}
+
+	return vArenaLO;
+}
+
+Vec_Ptr_t * createArenaLi( Aig_Man_t *pAigNew, Vec_Ptr_t *vBarriers, Vec_Ptr_t *vArenaSignal )
+{
+	Vec_Ptr_t *vArenaLi;
+	int barrierCount;
+	int i;
+	Aig_Obj_t *pObj, *pObjDriver;
+
+	if( vBarriers == NULL )
+		return NULL;
+
+	barrierCount = Vec_PtrSize(vBarriers);
+	if( barrierCount <= 0 )
+		return NULL;
+
+	vArenaLi = Vec_PtrAlloc(barrierCount);	
+	for( i=0; i<barrierCount; i++ )
+	{
+		pObjDriver = (Aig_Obj_t *)Vec_PtrEntry( vArenaSignal, i );
+		pObj = Aig_ObjCreateCo( pAigNew, pObjDriver );
+		Vec_PtrPush( vArenaLi, pObj );
+	}
+
+	return vArenaLi;
+}
+
+Vec_Ptr_t *createMonotoneBarrierLO( Aig_Man_t *pAigNew, Vec_Ptr_t *vBarriers )
+{
+	Vec_Ptr_t *vMonotoneLO;
+	int barrierCount;
+	Aig_Obj_t *pObj;
+	int i;
+
+	if( vBarriers == NULL )
+		return NULL;
+
+	barrierCount = Vec_PtrSize(vBarriers);
+	if( barrierCount <= 0 )
+		return NULL;
+
+	vMonotoneLO = Vec_PtrAlloc(barrierCount);	
+	for( i=0; i<barrierCount; i++ )
+	{
+		pObj = Aig_ObjCreateCi( pAigNew );
+		Vec_PtrPush( vMonotoneLO, pObj );
+	}
+
+	return vMonotoneLO;
+}
+
+Aig_Obj_t *driverToPoNew( Aig_Man_t *pAig, Aig_Obj_t *pObjPo )
+{
+	Aig_Obj_t *poDriverOld;
+	Aig_Obj_t *poDriverNew;	
+	
+	//Aig_ObjPrint( pAig, pObjPo );
+	//printf("\n");
+
+	assert( Aig_ObjIsCo(pObjPo) );
+	poDriverOld = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo));
+	assert( !Aig_ObjIsCo(poDriverOld) );
+	poDriverNew = !Aig_IsComplement(poDriverOld)? 
+			(Aig_Obj_t *)(Aig_Regular(poDriverOld)->pData) : 
+			Aig_Not((Aig_Obj_t *)(Aig_Regular(poDriverOld)->pData));
+	//assert( !Aig_ObjIsCo(poDriverNew) );
+	return poDriverNew;
+}
+
+Vec_Ptr_t *collectBarrierDisjunctions(Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Vec_Ptr_t *vBarriers)
+{
+	int barrierCount, i, j, jElem;
+	Vec_Int_t *vIthBarrier;
+	Aig_Obj_t *pObjBarrier, *pObjCurr, *pObjTargetPoOld;
+	Vec_Ptr_t *vNewBarrierSignals;
+
+	if( vBarriers == NULL )
+		return NULL;
+	barrierCount = Vec_PtrSize( vBarriers );
+	if( barrierCount <= 0 )
+		return NULL;
+
+	vNewBarrierSignals = Vec_PtrAlloc( barrierCount );
+
+	for( i=0; i<barrierCount; i++ )
+	{
+		vIthBarrier = (Vec_Int_t *)Vec_PtrEntry( vBarriers, i );
+		assert( Vec_IntSize( vIthBarrier ) >= 1 );
+		pObjBarrier = Aig_Not(Aig_ManConst1(pAigNew));
+		Vec_IntForEachEntry( vIthBarrier, jElem, j )
+		{
+			pObjTargetPoOld = Aig_ManCo( pAigOld, jElem );
+			//Aig_ObjPrint( pAigOld, pObjTargetPoOld );
+			//printf("\n");
+			pObjCurr = driverToPoNew( pAigOld, pObjTargetPoOld );
+			pObjBarrier = Aig_Or( pAigNew, pObjCurr, pObjBarrier );
+		}
+		assert( pObjBarrier );
+		Vec_PtrPush(vNewBarrierSignals, pObjBarrier);
+	}
+	assert( Vec_PtrSize( vNewBarrierSignals ) == barrierCount );
+
+	return vNewBarrierSignals;
+}
+
+Aig_Obj_t *Aig_Xor( Aig_Man_t *pAig, Aig_Obj_t *pObj1, Aig_Obj_t *pObj2 )
+{
+	return Aig_Or( pAig, Aig_And( pAig, pObj1, Aig_Not(pObj2) ), Aig_And( pAig, Aig_Not(pObj1), pObj2 ) );
+}
+
+Aig_Obj_t *createArenaViolation(
+		Aig_Man_t *pAigOld,
+		Aig_Man_t *pAigNew, 
+		Aig_Obj_t *pWindowBegins, 
+		Aig_Obj_t *pWithinWindow, 
+		Vec_Ptr_t *vMasterBarriers, 
+		Vec_Ptr_t *vBarrierLo,
+		Vec_Ptr_t *vBarrierLiDriver,
+		Vec_Ptr_t *vMonotoneDisjunctionNodes
+		)
+{
+	Aig_Obj_t *pWindowBeginsLocal = pWindowBegins;
+	Aig_Obj_t *pWithinWindowLocal = pWithinWindow;
+	int i;
+	Aig_Obj_t *pObj, *pObjAnd1, *pObjOr1, *pObjAnd2, *pObjBarrierLo, *pObjBarrierSwitch, *pObjArenaViolation;
+	Vec_Ptr_t *vBarrierSignals;
+
+	assert( vBarrierLiDriver != NULL );
+	assert( vMonotoneDisjunctionNodes != NULL );
+
+	pObjArenaViolation = Aig_Not(Aig_ManConst1( pAigNew ));
+
+	vBarrierSignals = collectBarrierDisjunctions(pAigOld, pAigNew, vMasterBarriers);
+	assert( vBarrierSignals != NULL );
+
+	assert( Vec_PtrSize( vMonotoneDisjunctionNodes ) == 0 );
+	Vec_PtrForEachEntry( Aig_Obj_t *, vBarrierSignals, pObj, i )
+		Vec_PtrPush( vMonotoneDisjunctionNodes, pObj );
+	assert( Vec_PtrSize( vMonotoneDisjunctionNodes ) == Vec_PtrSize( vMasterBarriers ) );
+
+	Vec_PtrForEachEntry( Aig_Obj_t *, vBarrierSignals, pObj, i )
+	{
+		//pObjNew = driverToPoNew( pAigOld, pObj );
+		pObjAnd1 = Aig_And(pAigNew, pObj, pWindowBeginsLocal);
+		pObjBarrierLo = (Aig_Obj_t *)Vec_PtrEntry( vBarrierLo, i );
+		pObjOr1 = Aig_Or(pAigNew, pObjAnd1, pObjBarrierLo);
+		Vec_PtrPush( vBarrierLiDriver, pObjOr1 );
+
+		pObjBarrierSwitch = Aig_Xor( pAigNew, pObj, pObjBarrierLo );
+		pObjAnd2 = Aig_And( pAigNew, pObjBarrierSwitch, pWithinWindowLocal );
+		pObjArenaViolation = Aig_Or( pAigNew, pObjAnd2, pObjArenaViolation );
+	}
+
+	Vec_PtrFree(vBarrierSignals);
+	return pObjArenaViolation;
+}
+
+Aig_Obj_t *createConstrained0LiveConeWithDSC( Aig_Man_t *pNewAig, Vec_Ptr_t *signalList )
+{
+	Aig_Obj_t *pConsequent, *pConsequentCopy, *pAntecedent, *p0LiveCone, *pObj;
+	int i, numSigAntecedent;
+	
+	numSigAntecedent = Vec_PtrSize( signalList ) - 1;
+
+	pAntecedent = Aig_ManConst1( pNewAig );
+	pConsequent = (Aig_Obj_t *)Vec_PtrEntry( signalList, numSigAntecedent );
+	pConsequentCopy = Aig_NotCond( (Aig_Obj_t *)(Aig_Regular(pConsequent)->pData), Aig_IsComplement( pConsequent ) );
+
+	for(i=0; i<numSigAntecedent; i++ )
+	{
+		pObj = (Aig_Obj_t *)Vec_PtrEntry( signalList, i );
+		assert( Aig_Regular(pObj)->pData );
+		pAntecedent = Aig_And( pNewAig, pAntecedent, Aig_NotCond((Aig_Obj_t *)(Aig_Regular(pObj)->pData), Aig_IsComplement(pObj)) );
+	}
+
+	p0LiveCone = Aig_Or( pNewAig, Aig_Not(pAntecedent), pConsequentCopy );
+
+	return p0LiveCone;
+}
+
+Vec_Ptr_t *collectCSSignalsWithDSC( Abc_Ntk_t *pNtk, Aig_Man_t *pAig )
+{
+	int i;
+	Aig_Obj_t *pObj, *pConsequent = NULL;
+	Vec_Ptr_t *vNodeArray;
+
+	vNodeArray = Vec_PtrAlloc(1);
+
+	Saig_ManForEachPo( pAig, pObj, i )
+	{
+		if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "csLiveConst_" ) != NULL )
+			Vec_PtrPush( vNodeArray, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj)) );	
+		else if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "csLiveTarget_" ) != NULL )
+			pConsequent = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj));
+	}
+	assert( pConsequent );
+	Vec_PtrPush( vNodeArray, pConsequent );	
+	return vNodeArray;
+}
+
+int collectWindowBeginSignalWithDSC( Abc_Ntk_t *pNtk, Aig_Man_t *pAig )
+{
+	int i;
+	Aig_Obj_t *pObj;
+
+	Saig_ManForEachPo( pAig, pObj, i )
+	{
+		if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "windowBegins_" ) != NULL )
+		{
+			return i;			
+		}
+	}
+	
+	return -1;
+}
+
+int collectWithinWindowSignalWithDSC( Abc_Ntk_t *pNtk, Aig_Man_t *pAig )
+{
+	int i;
+	Aig_Obj_t *pObj;
+
+	Saig_ManForEachPo( pAig, pObj, i )
+	{
+		if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "withinWindow_" ) != NULL )
+			return i;			
+	}
+	
+	return -1;
+}
+
+int collectPendingSignalWithDSC( Abc_Ntk_t *pNtk, Aig_Man_t *pAig )
+{
+	int i;
+	Aig_Obj_t *pObj;
+
+	Saig_ManForEachPo( pAig, pObj, i )
+	{
+		if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "pendingSignal" ) != NULL )
+			return i;			
+	}
+	
+	return -1;
+}
+
+Aig_Obj_t *createAndGateForMonotonicityVerification(
+				Aig_Man_t *pNewAig,
+				Vec_Ptr_t *vDisjunctionSignals,
+				Vec_Ptr_t *vDisjunctionLo,
+				Aig_Obj_t *pendingLo,
+				Aig_Obj_t *pendingSignal
+				)
+{
+	Aig_Obj_t *pObjBigAnd, *pObj, *pObjLo, *pObjImply;
+	Aig_Obj_t *pObjPendingAndPendingLo;
+	int i;
+
+	pObjBigAnd = Aig_ManConst1( pNewAig );
+	pObjPendingAndPendingLo = Aig_And( pNewAig, pendingLo, pendingSignal );
+	Vec_PtrForEachEntry( Aig_Obj_t *, vDisjunctionSignals, pObj, i )
+	{
+		pObjLo = (Aig_Obj_t *)Vec_PtrEntry( vDisjunctionLo, i );	
+		pObjImply = Aig_Or( pNewAig, Aig_Not(Aig_And( pNewAig, pObjPendingAndPendingLo, pObjLo)),
+					pObj );
+		pObjBigAnd = Aig_And( pNewAig, pObjBigAnd, pObjImply );
+	}
+	return pObjBigAnd;
+}
+
+Aig_Man_t *createNewAigWith0LivePoWithDSC( Aig_Man_t *pAig, Vec_Ptr_t *signalList, int *index0Live, int windowBeginIndex, int withinWindowIndex, int pendingSignalIndex, Vec_Ptr_t *vBarriers )
+{
+	Aig_Man_t *pNewAig;
+	Aig_Obj_t *pObj, *pObjNewPoDriver;
+	int i;
+	int loCopied = 0, loCreated = 0, liCopied = 0, liCreated = 0;
+	Aig_Obj_t *pObjWindowBeginsNew, *pObjWithinWindowNew, *pObjArenaViolation, *pObjTarget, *pObjArenaViolationLiDriver;
+	Aig_Obj_t *pObjNewPoDriverArenaViolated, *pObjArenaViolationLo;
+	Vec_Ptr_t *vBarrierLo, *vBarrierLiDriver, *vBarrierLi;
+	Vec_Ptr_t *vMonotoneNodes;
+
+#ifdef BARRIER_MONOTONE_TEST
+	Aig_Obj_t *pObjPendingSignal;
+	Aig_Obj_t *pObjPendingFlopLo;
+	Vec_Ptr_t *vMonotoneBarrierLo;
+	Aig_Obj_t *pObjPendingAndPendingSignal, *pObjMonotoneAnd, *pObjCurrMonotoneLo;
+#endif
+
+	//assert( Vec_PtrSize( signalList ) > 1 );
+
+	//****************************************************************
+	// Step1: create the new manager
+	// Note: The new manager is created with "2 * Aig_ManObjNumMax(p)"
+	// nodes, but this selection is arbitrary - need to be justified
+	//****************************************************************
+	pNewAig = Aig_ManStart( Aig_ManObjNumMax(pAig) );
+	pNewAig->pName = (char *)malloc( strlen( pAig->pName ) + strlen("_0Live") + 1 );
+	sprintf(pNewAig->pName, "%s_%s", pAig->pName, "0Live");
+    	pNewAig->pSpec = NULL;
+
+	//****************************************************************
+	// Step 2: map constant nodes
+	//****************************************************************
+    	pObj = Aig_ManConst1( pAig );
+    	pObj->pData = Aig_ManConst1( pNewAig );
+
+	//****************************************************************
+    	// Step 3: create true PIs
+	//****************************************************************
+    	Saig_ManForEachPi( pAig, pObj, i )
+	{
+		pObj->pData = Aig_ObjCreateCi( pNewAig );
+	}
+
+	//****************************************************************
+	// Step 4: create register outputs
+	//****************************************************************
+    	Saig_ManForEachLo( pAig, pObj, i )
+    	{
+		loCopied++;
+		pObj->pData = Aig_ObjCreateCi( pNewAig );
+    	}
+
+	//****************************************************************
+	// Step 4.a: create register outputs for the barrier flops
+	//****************************************************************
+	vBarrierLo = createArenaLO( pNewAig, vBarriers );
+	loCreated = Vec_PtrSize(vBarrierLo);
+
+	//****************************************************************
+	// Step 4.b: create register output for arenaViolationFlop
+	//****************************************************************
+	pObjArenaViolationLo = Aig_ObjCreateCi( pNewAig );
+	loCreated++;
+
+#ifdef BARRIER_MONOTONE_TEST
+	//****************************************************************
+	// Step 4.c: create register output for pendingFlop
+	//****************************************************************
+	pObjPendingFlopLo = Aig_ObjCreateCi( pNewAig );
+	loCreated++;
+
+	//****************************************************************
+	// Step 4.d: create register outputs for the barrier flops
+	// for asserting monotonicity
+	//****************************************************************
+	vMonotoneBarrierLo = createMonotoneBarrierLO( pNewAig, vBarriers );
+	loCreated = loCreated + Vec_PtrSize(vMonotoneBarrierLo);
+#endif
+
+	//********************************************************************
+	// Step 5: create internal nodes
+	//********************************************************************
+    	Aig_ManForEachNode( pAig, pObj, i )
+	{
+		pObj->pData = Aig_And( pNewAig, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+	}
+
+	//********************************************************************
+	// Step 5.a: create internal nodes corresponding to arenaViolation
+	//********************************************************************
+	pObjTarget = Aig_ManCo( pAig, windowBeginIndex );
+	pObjWindowBeginsNew = driverToPoNew( pAig, pObjTarget );
+
+	pObjTarget = Aig_ManCo( pAig, withinWindowIndex );
+	pObjWithinWindowNew = driverToPoNew( pAig, pObjTarget );
+
+	vBarrierLiDriver = Vec_PtrAlloc( Vec_PtrSize(vBarriers) );
+	vMonotoneNodes = Vec_PtrAlloc( Vec_PtrSize(vBarriers) );
+
+	pObjArenaViolation = createArenaViolation( pAig, pNewAig, 
+				pObjWindowBeginsNew, pObjWithinWindowNew, 
+				vBarriers, vBarrierLo, vBarrierLiDriver, vMonotoneNodes ); 
+	assert( Vec_PtrSize(vMonotoneNodes) == Vec_PtrSize(vBarriers) );
+
+#ifdef ARENA_VIOLATION_CONSTRAINT
+
+#endif
+
+	pObjArenaViolationLiDriver = Aig_Or( pNewAig, pObjArenaViolation, pObjArenaViolationLo );
+
+#ifdef BARRIER_MONOTONE_TEST
+	//********************************************************************
+	// Step 5.b: Create internal nodes for monotone testing
+	//********************************************************************
+
+	pObjTarget = Aig_ManCo( pAig, pendingSignalIndex );
+	pObjPendingSignal = driverToPoNew( pAig, pObjTarget );
+	
+	pObjPendingAndPendingSignal = Aig_And( pNewAig, pObjPendingSignal, pObjPendingFlopLo );
+	pObjMonotoneAnd = Aig_ManConst1( pNewAig );
+	Vec_PtrForEachEntry( Aig_Obj_t *, vMonotoneNodes, pObj, i )
+	{
+		pObjCurrMonotoneLo = (Aig_Obj_t *)Vec_PtrEntry(vMonotoneBarrierLo, i);
+		pObjMonotoneAnd = Aig_And( pNewAig, pObjMonotoneAnd,
+			Aig_Or( pNewAig, 
+			Aig_Not(Aig_And(pNewAig, pObjPendingAndPendingSignal, pObjCurrMonotoneLo)),
+			pObj ) );
+	}
+#endif
+
+	//********************************************************************
+	// Step 6: create primary outputs
+	//********************************************************************
+
+	Saig_ManForEachPo( pAig, pObj, i )
+	{
+		pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); 
+	}
+
+	pObjNewPoDriver = createConstrained0LiveConeWithDSC( pNewAig, signalList );
+	pObjNewPoDriverArenaViolated = Aig_Or( pNewAig, pObjNewPoDriver, pObjArenaViolationLo );
+#ifdef BARRIER_MONOTONE_TEST
+	pObjNewPoDriverArenaViolated = Aig_And( pNewAig, pObjNewPoDriverArenaViolated, pObjMonotoneAnd );
+#endif
+	Aig_ObjCreateCo( pNewAig, pObjNewPoDriverArenaViolated );
+
+	*index0Live = i;
+
+	//********************************************************************
+	// Step 7: create register inputs
+	//********************************************************************
+
+	Saig_ManForEachLi( pAig, pObj, i )
+	{
+		liCopied++;
+		pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) );
+	}
+
+	//********************************************************************
+	// Step 7.a: create register inputs for barrier flops
+	//********************************************************************
+	assert( Vec_PtrSize(vBarrierLiDriver) == Vec_PtrSize(vBarriers) );
+	vBarrierLi = createArenaLi( pNewAig, vBarriers, vBarrierLiDriver );
+	liCreated = Vec_PtrSize( vBarrierLi );
+
+	//********************************************************************
+	// Step 7.b: create register inputs for arenaViolation flop
+	//********************************************************************
+	Aig_ObjCreateCo( pNewAig, pObjArenaViolationLiDriver );
+	liCreated++;
+
+#ifdef BARRIER_MONOTONE_TEST
+	//****************************************************************
+	// Step 7.c: create register input for pendingFlop
+	//****************************************************************
+	Aig_ObjCreateCo( pNewAig, pObjPendingSignal);
+	liCreated++;
+
+	//********************************************************************
+	// Step 7.d: create register inputs for the barrier flops
+	// for asserting monotonicity
+	//********************************************************************
+	Vec_PtrForEachEntry( Aig_Obj_t *, vMonotoneNodes, pObj, i )
+	{
+		Aig_ObjCreateCo( pNewAig, pObj );
+		liCreated++;
+	}
+#endif
+
+	assert(loCopied + loCreated == liCopied + liCreated);
+	//next step should be changed
+	Aig_ManSetRegNum( pNewAig, loCopied + loCreated );
+	Aig_ManCleanup( pNewAig );
+
+	assert( Aig_ManCheck( pNewAig ) );
+
+	Vec_PtrFree(vBarrierLo);
+	Vec_PtrFree(vMonotoneBarrierLo);
+	Vec_PtrFree(vBarrierLiDriver);
+	Vec_PtrFree(vBarrierLi);
+	Vec_PtrFree(vMonotoneNodes);
+
+	return pNewAig;
+}
+
+Aig_Man_t *generateWorkingAigWithDSC( Aig_Man_t *pAig, Abc_Ntk_t *pNtk, int *pIndex0Live, Vec_Ptr_t *vMasterBarriers )
+{
+	Vec_Ptr_t *vSignalVector;
+	Aig_Man_t *pAigNew;
+	int pObjWithinWindow;
+	int pObjWindowBegin;
+	int pObjPendingSignal;
+
+	vSignalVector = collectCSSignalsWithDSC( pNtk, pAig );	
+
+	pObjWindowBegin = collectWindowBeginSignalWithDSC( pNtk, pAig );
+	pObjWithinWindow = collectWithinWindowSignalWithDSC( pNtk, pAig );
+	pObjPendingSignal = collectPendingSignalWithDSC( pNtk, pAig );
+
+	pAigNew = createNewAigWith0LivePoWithDSC( pAig, vSignalVector, pIndex0Live, pObjWindowBegin, pObjWithinWindow, pObjPendingSignal, vMasterBarriers );
+	Vec_PtrFree(vSignalVector);
+
+	return pAigNew;
+}
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/live/combination.c b/abc-build/src/proof/live/combination.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/live/combination.c
@@ -0,0 +1,463 @@
+#include <stdio.h>
+#include "base/main/main.h"
+#include "aig/aig/aig.h"
+#include "aig/saig/saig.h"
+#include <string.h>
+#include "base/main/mainInt.h"
+#include "proof/pdr/pdr.h"
+#include <time.h>
+
+ABC_NAMESPACE_IMPL_START
+
+long countCombination(long n, long k)
+{
+	assert( n >= k );
+	if( n == k ) return 1;
+	if( k == 1 ) return n;
+	return countCombination( n-1, k-1 ) + countCombination( n-1, k );
+}	
+
+void listCombination(int n, int t)
+{
+	Vec_Int_t *vC;
+	int i, j, combCounter = 0;
+
+	//Initialization
+	vC = Vec_IntAlloc(t+3);
+	for(i=-1; i<t; i++)
+		Vec_IntPush( vC, i );
+	Vec_IntPush( vC, n );
+	Vec_IntPush( vC, 0 );
+
+	while(1)
+	{
+		//visit combination
+		printf("Comb-%3d : ", ++combCounter);
+		for( i=t; i>0; i--)
+			printf("vC[%d] = %d ", i, Vec_IntEntry(vC, i));
+		printf("\n");
+
+		j = 1;
+		while( Vec_IntEntry( vC, j ) + 1 == Vec_IntEntry( vC, j+1 ) )
+		{
+			//printf("\nGochon = %d, %d\n", Vec_IntEntry( vC, j ) + 1, Vec_IntEntry( vC, j+1 ));
+			Vec_IntWriteEntry( vC, j, j-1 );
+			j = j + 1;
+		}
+		if( j > t ) break;
+		Vec_IntWriteEntry( vC, j, Vec_IntEntry( vC, j ) + 1 );
+	}
+	
+	Vec_IntFree(vC);	
+}
+
+int generateCombinatorialStabil( Aig_Man_t *pAigNew, Aig_Man_t *pAigOld, 
+				Vec_Int_t *vCandidateMonotoneSignals_,
+				Vec_Ptr_t *vDisj_nCk_,
+				int combN, int combK )
+{
+	Aig_Obj_t *pObjMonoCand, *pObj;
+	int targetPoIndex;
+
+	//Knuth's Data Strcuture
+	int totalCombination_KNUTH = 0;
+	Vec_Int_t *vC_KNUTH;
+	int i_KNUTH, j_KNUTH;
+
+	//Knuth's Data Structure Initialization
+	vC_KNUTH = Vec_IntAlloc(combK+3);
+	for(i_KNUTH=-1; i_KNUTH<combK; i_KNUTH++)
+		Vec_IntPush( vC_KNUTH, i_KNUTH );
+	Vec_IntPush( vC_KNUTH, combN );
+	Vec_IntPush( vC_KNUTH, 0 );
+
+	while(1)
+	{
+		totalCombination_KNUTH++;
+		pObjMonoCand = Aig_Not(Aig_ManConst1(pAigNew));
+		for( i_KNUTH=combK; i_KNUTH>0; i_KNUTH--)
+		{
+			targetPoIndex = Vec_IntEntry( vCandidateMonotoneSignals_, Vec_IntEntry(vC_KNUTH, i_KNUTH));
+			pObj = Aig_ObjChild0Copy(Aig_ManCo( pAigOld, targetPoIndex ));
+			pObjMonoCand = Aig_Or( pAigNew, pObj, pObjMonoCand );
+		}
+		Vec_PtrPush(vDisj_nCk_, pObjMonoCand );
+
+		j_KNUTH = 1;
+		while( Vec_IntEntry( vC_KNUTH, j_KNUTH ) + 1 == Vec_IntEntry( vC_KNUTH, j_KNUTH+1 ) )
+		{
+			Vec_IntWriteEntry( vC_KNUTH, j_KNUTH, j_KNUTH-1 );
+			j_KNUTH = j_KNUTH + 1;
+		}
+		if( j_KNUTH > combK ) break;
+		Vec_IntWriteEntry( vC_KNUTH, j_KNUTH, Vec_IntEntry( vC_KNUTH, j_KNUTH ) + 1 );
+	}
+
+	Vec_IntFree(vC_KNUTH);
+
+	return totalCombination_KNUTH;
+}
+
+int generateCombinatorialStabilExhaust( Aig_Man_t *pAigNew, Aig_Man_t *pAigOld, 
+				Vec_Ptr_t *vDisj_nCk_,
+				int combN, int combK )
+{
+	Aig_Obj_t *pObjMonoCand, *pObj;
+	int targetPoIndex;
+
+	//Knuth's Data Strcuture
+	int totalCombination_KNUTH = 0;
+	Vec_Int_t *vC_KNUTH;
+	int i_KNUTH, j_KNUTH;
+
+	//Knuth's Data Structure Initialization
+	vC_KNUTH = Vec_IntAlloc(combK+3);
+	for(i_KNUTH=-1; i_KNUTH<combK; i_KNUTH++)
+		Vec_IntPush( vC_KNUTH, i_KNUTH );
+	Vec_IntPush( vC_KNUTH, combN );
+	Vec_IntPush( vC_KNUTH, 0 );
+
+	while(1)
+	{
+		totalCombination_KNUTH++;
+		pObjMonoCand = Aig_Not(Aig_ManConst1(pAigNew));
+		for( i_KNUTH=combK; i_KNUTH>0; i_KNUTH--)
+		{
+			//targetPoIndex = Vec_IntEntry( vCandidateMonotoneSignals_, Vec_IntEntry(vC_KNUTH, i_KNUTH));
+			targetPoIndex = Vec_IntEntry(vC_KNUTH, i_KNUTH);
+			pObj = (Aig_Obj_t *)(Aig_ManLo( pAigOld, targetPoIndex )->pData);
+			pObjMonoCand = Aig_Or( pAigNew, pObj, pObjMonoCand );
+		}
+		Vec_PtrPush(vDisj_nCk_, pObjMonoCand );
+
+		j_KNUTH = 1;
+		while( Vec_IntEntry( vC_KNUTH, j_KNUTH ) + 1 == Vec_IntEntry( vC_KNUTH, j_KNUTH+1 ) )
+		{
+			Vec_IntWriteEntry( vC_KNUTH, j_KNUTH, j_KNUTH-1 );
+			j_KNUTH = j_KNUTH + 1;
+		}
+		if( j_KNUTH > combK ) break;
+		Vec_IntWriteEntry( vC_KNUTH, j_KNUTH, Vec_IntEntry( vC_KNUTH, j_KNUTH ) + 1 );
+	}
+
+	Vec_IntFree(vC_KNUTH);
+
+	return totalCombination_KNUTH;
+}
+
+Aig_Man_t *generateDisjunctiveTester( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, int combN, int combK )
+{
+	//AIG creation related data structure
+	Aig_Man_t *pNewAig;
+	int piCopied = 0, loCopied = 0, loCreated = 0, liCopied = 0, liCreated = 0, poCopied = 0;
+	//int i, iElem, nRegCount, hintSingalBeginningMarker, hintSingalEndMarker;
+	int i, nRegCount, hintSingalBeginningMarker, hintSingalEndMarker;
+	int combN_internal, combK_internal; //, targetPoIndex;
+	long longI, lCombinationCount;
+	//Aig_Obj_t *pObj, *pObjMonoCand, *pObjLO_nCk, *pObjDisj_nCk;
+	Aig_Obj_t *pObj, *pObjLO_nCk, *pObjDisj_nCk;
+	Vec_Ptr_t *vLO_nCk, *vPODriver_nCk, *vDisj_nCk;
+	Vec_Int_t *vCandidateMonotoneSignals;
+
+	extern Vec_Int_t *findHintOutputs(Abc_Ntk_t *pNtk);
+	
+	//Knuth's Data Strcuture
+	//Vec_Int_t *vC_KNUTH;
+	//int i_KNUTH, j_KNUTH, combCounter_KNUTH = 0;
+
+	//Collecting target HINT signals
+	vCandidateMonotoneSignals = findHintOutputs(pNtk);
+	if( vCandidateMonotoneSignals == NULL )
+	{
+		printf("\nTraget Signal Set is Empty: Duplicating given AIG\n");
+		combN_internal = 0;
+	}
+	else
+	{
+		//Vec_IntForEachEntry( vCandidateMonotoneSignals, iElem, i )
+		//	printf("Po[%d] = %s\n", iElem, Abc_ObjName( Abc_NtkPo(pNtk, iElem) ) );
+		hintSingalBeginningMarker = Vec_IntEntry( vCandidateMonotoneSignals, 0 );
+		hintSingalEndMarker = Vec_IntEntry( vCandidateMonotoneSignals, Vec_IntSize(vCandidateMonotoneSignals) - 1 );
+		combN_internal = hintSingalEndMarker - hintSingalBeginningMarker + 1;
+	}
+
+	//combK_internal = combK;
+
+	//Knuth's Data Structure Initialization
+	//vC_KNUTH = Vec_IntAlloc(combK_internal+3);
+	//for(i_KNUTH=-1; i_KNUTH<combK_internal; i_KNUTH++)
+	//	Vec_IntPush( vC_KNUTH, i_KNUTH );
+	//Vec_IntPush( vC_KNUTH, combN_internal );
+	//Vec_IntPush( vC_KNUTH, 0 );
+
+	//Standard AIG duplication begins
+	//Standard AIG Manager Creation
+	pNewAig = Aig_ManStart( Aig_ManObjNumMax(pAig) );
+	pNewAig->pName = (char *)malloc( strlen( pAig->pName ) + strlen("_nCk") + 1 );
+	sprintf(pNewAig->pName, "%s_%s", pAig->pName, "nCk");
+    	pNewAig->pSpec = NULL;
+
+	//Standard Mapping of Constant Nodes
+	pObj = Aig_ManConst1( pAig );
+    	pObj->pData = Aig_ManConst1( pNewAig );
+
+	//Standard AIG PI duplication
+	Saig_ManForEachPi( pAig, pObj, i )
+	{
+		piCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNewAig);
+	}
+
+	//Standard AIG LO duplication
+	Saig_ManForEachLo( pAig, pObj, i )
+    	{
+		loCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNewAig);
+    	}
+
+	//nCk LO creation
+	lCombinationCount = 0;
+	for(combK_internal=1; combK_internal<=combK; combK_internal++)
+		lCombinationCount += countCombination( combN_internal, combK_internal );
+	assert( lCombinationCount > 0 );
+	vLO_nCk = Vec_PtrAlloc(lCombinationCount);
+	for( longI = 0; longI < lCombinationCount; longI++ )
+	{
+		loCreated++;
+		pObj = Aig_ObjCreateCi(pNewAig);
+		Vec_PtrPush( vLO_nCk, pObj );
+	}
+
+	//Standard Node duplication
+	Aig_ManForEachNode( pAig, pObj, i )
+	{
+		pObj->pData = Aig_And( pNewAig, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+	}
+	
+	//nCk specific logic creation (i.e. nCk number of OR gates)
+	vDisj_nCk = Vec_PtrAlloc(lCombinationCount);
+
+	
+
+	//while(1)
+	//{
+	//	//visit combination
+	//	//printf("Comb-%3d : ", ++combCounter_KNUTH);
+	//	pObjMonoCand = Aig_Not(Aig_ManConst1(pNewAig));
+	//	for( i_KNUTH=combK_internal; i_KNUTH>0; i_KNUTH--)
+	//	{
+	//		//printf("vC[%d] = %d ", i_KNUTH, Vec_IntEntry(vC_KNUTH, i_KNUTH));
+	//		targetPoIndex = Vec_IntEntry( vCandidateMonotoneSignals, Vec_IntEntry(vC_KNUTH, i_KNUTH));
+	//		pObj = Aig_ObjChild0Copy(Aig_ManCo( pAig, targetPoIndex ));
+	//		pObjMonoCand = Aig_Or( pNewAig, pObj, pObjMonoCand );
+	//	}
+	//	Vec_PtrPush(vDisj_nCk, pObjMonoCand );
+	//	//printf("\n");
+
+	//	j_KNUTH = 1;
+	//	while( Vec_IntEntry( vC_KNUTH, j_KNUTH ) + 1 == Vec_IntEntry( vC_KNUTH, j_KNUTH+1 ) )
+	//	{
+	//		Vec_IntWriteEntry( vC_KNUTH, j_KNUTH, j_KNUTH-1 );
+	//		j_KNUTH = j_KNUTH + 1;
+	//	}
+	//	if( j_KNUTH > combK_internal ) break;
+	//	Vec_IntWriteEntry( vC_KNUTH, j_KNUTH, Vec_IntEntry( vC_KNUTH, j_KNUTH ) + 1 );
+	//}
+	for( combK_internal=1; combK_internal<=combK; combK_internal++ )
+		generateCombinatorialStabil( pNewAig, pAig, vCandidateMonotoneSignals,
+				vDisj_nCk, combN_internal, combK_internal );
+
+
+	//creation of implication logic
+	vPODriver_nCk = Vec_PtrAlloc(lCombinationCount);
+	for( longI = 0; longI < lCombinationCount; longI++ )
+	{
+		pObjLO_nCk = (Aig_Obj_t *)(Vec_PtrEntry( vLO_nCk, longI ));
+		pObjDisj_nCk = (Aig_Obj_t *)(Vec_PtrEntry( vDisj_nCk, longI ));
+
+		pObj = Aig_Or( pNewAig, Aig_Not(pObjDisj_nCk), pObjLO_nCk);
+		Vec_PtrPush(vPODriver_nCk, pObj);
+	}
+	
+	//Standard PO duplication
+	Saig_ManForEachPo( pAig, pObj, i )
+	{
+		poCopied++;
+		pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); 
+	}
+
+	//nCk specific PO creation
+	for( longI = 0; longI < lCombinationCount; longI++ )
+	{
+		Aig_ObjCreateCo( pNewAig, (Aig_Obj_t *)(Vec_PtrEntry( vPODriver_nCk, longI )) );
+	}
+
+	//Standard LI duplication
+	Saig_ManForEachLi( pAig, pObj, i )
+	{
+		liCopied++;
+		Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) );
+	}
+
+	//nCk specific LI creation
+	for( longI = 0; longI < lCombinationCount; longI++ )
+	{
+		liCreated++;
+		Aig_ObjCreateCo( pNewAig, (Aig_Obj_t *)(Vec_PtrEntry( vPODriver_nCk, longI )) );
+	}
+
+	//clean-up, book-keeping
+	assert( liCopied + liCreated == loCopied + loCreated );	
+	nRegCount = loCopied + loCreated;
+
+	Aig_ManSetRegNum( pNewAig, nRegCount );
+	Aig_ManCleanup( pNewAig );
+	assert( Aig_ManCheck( pNewAig ) );
+	
+	//Vec_IntFree(vC_KNUTH);	
+	return pNewAig;
+}
+
+Aig_Man_t *generateGeneralDisjunctiveTester( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, int combK )
+{
+	//AIG creation related data structure
+	Aig_Man_t *pNewAig;
+	int piCopied = 0, loCopied = 0, loCreated = 0, liCopied = 0, liCreated = 0, poCopied = 0;
+	//int i, iElem, nRegCount, hintSingalBeginningMarker, hintSingalEndMarker;
+	int i, nRegCount;
+	int combN_internal, combK_internal; //, targetPoIndex;
+	long longI, lCombinationCount;
+	//Aig_Obj_t *pObj, *pObjMonoCand, *pObjLO_nCk, *pObjDisj_nCk;
+	Aig_Obj_t *pObj, *pObjLO_nCk, *pObjDisj_nCk;
+	Vec_Ptr_t *vLO_nCk, *vPODriver_nCk, *vDisj_nCk;
+
+	extern Vec_Int_t *findHintOutputs(Abc_Ntk_t *pNtk);
+	
+	//Knuth's Data Strcuture
+	//Vec_Int_t *vC_KNUTH;
+	//int i_KNUTH, j_KNUTH, combCounter_KNUTH = 0;
+
+	//Collecting target HINT signals
+	//vCandidateMonotoneSignals = findHintOutputs(pNtk);
+	//if( vCandidateMonotoneSignals == NULL )
+	//{
+	//	printf("\nTraget Signal Set is Empty: Duplicating given AIG\n");
+	//	combN_internal = 0;
+	//}
+	//else
+	//{
+		//Vec_IntForEachEntry( vCandidateMonotoneSignals, iElem, i )
+		//	printf("Po[%d] = %s\n", iElem, Abc_ObjName( Abc_NtkPo(pNtk, iElem) ) );
+	//	hintSingalBeginningMarker = Vec_IntEntry( vCandidateMonotoneSignals, 0 );
+	//	hintSingalEndMarker = Vec_IntEntry( vCandidateMonotoneSignals, Vec_IntSize(vCandidateMonotoneSignals) - 1 );
+	//	combN_internal = hintSingalEndMarker - hintSingalBeginningMarker + 1;
+	//}
+
+	combN_internal = Aig_ManRegNum(pAig);
+
+	pNewAig = Aig_ManStart( Aig_ManObjNumMax(pAig) );
+	pNewAig->pName = (char *)malloc( strlen( pAig->pName ) + strlen("_nCk") + 1 );
+	sprintf(pNewAig->pName, "%s_%s", pAig->pName, "nCk");
+    	pNewAig->pSpec = NULL;
+
+	//Standard Mapping of Constant Nodes
+	pObj = Aig_ManConst1( pAig );
+    	pObj->pData = Aig_ManConst1( pNewAig );
+
+	//Standard AIG PI duplication
+	Saig_ManForEachPi( pAig, pObj, i )
+	{
+		piCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNewAig);
+	}
+
+	//Standard AIG LO duplication
+	Saig_ManForEachLo( pAig, pObj, i )
+    	{
+		loCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNewAig);
+    	}
+
+	//nCk LO creation
+	lCombinationCount = 0;
+	for(combK_internal=1; combK_internal<=combK; combK_internal++)
+		lCombinationCount += countCombination( combN_internal, combK_internal );
+	assert( lCombinationCount > 0 );
+	vLO_nCk = Vec_PtrAlloc(lCombinationCount);
+	for( longI = 0; longI < lCombinationCount; longI++ )
+	{
+		loCreated++;
+		pObj = Aig_ObjCreateCi(pNewAig);
+		Vec_PtrPush( vLO_nCk, pObj );
+	}
+
+	//Standard Node duplication
+	Aig_ManForEachNode( pAig, pObj, i )
+	{
+		pObj->pData = Aig_And( pNewAig, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+	}
+	
+	//nCk specific logic creation (i.e. nCk number of OR gates)
+	vDisj_nCk = Vec_PtrAlloc(lCombinationCount);
+
+	for( combK_internal=1; combK_internal<=combK; combK_internal++ )
+	{
+		generateCombinatorialStabilExhaust( pNewAig, pAig,
+				vDisj_nCk, combN_internal, combK_internal );
+	}
+
+
+	//creation of implication logic
+	vPODriver_nCk = Vec_PtrAlloc(lCombinationCount);
+	for( longI = 0; longI < lCombinationCount; longI++ )
+	{
+		pObjLO_nCk = (Aig_Obj_t *)(Vec_PtrEntry( vLO_nCk, longI ));
+		pObjDisj_nCk = (Aig_Obj_t *)(Vec_PtrEntry( vDisj_nCk, longI ));
+
+		pObj = Aig_Or( pNewAig, Aig_Not(pObjDisj_nCk), pObjLO_nCk);
+		Vec_PtrPush(vPODriver_nCk, pObj);
+	}
+	
+	//Standard PO duplication
+	Saig_ManForEachPo( pAig, pObj, i )
+	{
+		poCopied++;
+		pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); 
+	}
+
+	//nCk specific PO creation
+	for( longI = 0; longI < lCombinationCount; longI++ )
+	{
+		Aig_ObjCreateCo( pNewAig, (Aig_Obj_t *)(Vec_PtrEntry( vPODriver_nCk, longI )) );
+	}
+
+	//Standard LI duplication
+	Saig_ManForEachLi( pAig, pObj, i )
+	{
+		liCopied++;
+		Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) );
+	}
+
+	//nCk specific LI creation
+	for( longI = 0; longI < lCombinationCount; longI++ )
+	{
+		liCreated++;
+		Aig_ObjCreateCo( pNewAig, (Aig_Obj_t *)(Vec_PtrEntry( vPODriver_nCk, longI )) );
+	}
+
+	//clean-up, book-keeping
+	assert( liCopied + liCreated == loCopied + loCreated );	
+	nRegCount = loCopied + loCreated;
+
+	Aig_ManSetRegNum( pNewAig, nRegCount );
+	Aig_ManCleanup( pNewAig );
+	assert( Aig_ManCheck( pNewAig ) );
+	
+	Vec_PtrFree(vLO_nCk);
+	Vec_PtrFree(vPODriver_nCk);
+	Vec_PtrFree(vDisj_nCk);
+	//Vec_IntFree(vC_KNUTH);	
+	return pNewAig;
+}
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/live/disjunctiveMonotone.c b/abc-build/src/proof/live/disjunctiveMonotone.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/live/disjunctiveMonotone.c
@@ -0,0 +1,757 @@
+/**CFile****************************************************************
+
+  FileName    [disjunctiveMonotone.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Liveness property checking.]
+
+  Synopsis    [Constraint analysis module for the k-Liveness algorithm
+		invented by Koen Classen, Niklas Sorensson.]
+
+  Author      [Sayak Ray]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 31, 2012.]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include "base/main/main.h"
+#include "aig/aig/aig.h"
+#include "aig/saig/saig.h"
+#include <string.h>
+#include "base/main/mainInt.h"
+#include "proof/pdr/pdr.h"
+#include <time.h>
+
+ABC_NAMESPACE_IMPL_START
+
+struct aigPoIndices
+{
+	int attrPendingSignalIndex;
+	int attrHintSingalBeginningMarker;
+	int attrHintSingalEndMarker;
+	int attrSafetyInvarIndex;
+};
+
+extern struct aigPoIndices *allocAigPoIndices();
+extern void deallocAigPoIndices(struct aigPoIndices *toBeDeletedAigPoIndices);
+extern int collectSafetyInvariantPOIndex(Abc_Ntk_t *pNtk);
+
+struct antecedentConsequentVectorsStruct
+{
+	Vec_Int_t *attrAntecedents;
+	Vec_Int_t *attrConsequentCandidates;
+};
+
+struct antecedentConsequentVectorsStruct *allocAntecedentConsequentVectorsStruct()
+{
+	struct antecedentConsequentVectorsStruct *newStructure;
+
+	newStructure = (struct antecedentConsequentVectorsStruct *)malloc(sizeof (struct antecedentConsequentVectorsStruct));
+
+	newStructure->attrAntecedents = NULL;
+	newStructure->attrConsequentCandidates = NULL;
+		
+	assert( newStructure != NULL );
+	return newStructure;
+}
+
+void deallocAntecedentConsequentVectorsStruct(struct antecedentConsequentVectorsStruct *toBeDeleted)
+{
+	assert( toBeDeleted != NULL );
+	if(toBeDeleted->attrAntecedents) 
+		Vec_IntFree( toBeDeleted->attrAntecedents );
+	if(toBeDeleted->attrConsequentCandidates)
+		Vec_IntFree( toBeDeleted->attrConsequentCandidates );
+	free( toBeDeleted );
+}
+
+Aig_Man_t *createDisjunctiveMonotoneTester(Aig_Man_t *pAig, struct aigPoIndices *aigPoIndicesArg, 
+					struct antecedentConsequentVectorsStruct *anteConseVectors, int *startMonotonePropPo)
+{
+	Aig_Man_t *pNewAig;
+	int iElem, i, nRegCount;
+	int piCopied = 0, liCopied = 0, liCreated = 0, loCopied = 0, loCreated = 0;
+	int poCopied = 0, poCreated = 0;
+	Aig_Obj_t *pObj, *pObjPo, *pObjDriver, *pObjDriverNew, *pObjPendingDriverNew, *pObjPendingAndNextPending;
+	Aig_Obj_t *pPendingFlop, *pObjConseCandFlop, *pObjSafetyInvariantPoDriver;
+	//Vec_Ptr_t *vHintMonotoneLocalDriverNew;
+	Vec_Ptr_t *vConseCandFlopOutput;
+	//Vec_Ptr_t *vHintMonotoneLocalProp;
+
+	Aig_Obj_t *pObjAnteDisjunction, *pObjConsecDriver, *pObjConsecDriverNew, *pObjCandMonotone, *pObjPrevCandMonotone, *pObjMonotonePropDriver;
+	Vec_Ptr_t *vCandMonotoneProp;
+	Vec_Ptr_t *vCandMonotoneFlopInput;
+
+	int pendingSignalIndexLocal = aigPoIndicesArg->attrPendingSignalIndex;
+
+	Vec_Int_t *vAntecedentsLocal = anteConseVectors->attrAntecedents;
+	Vec_Int_t *vConsequentCandidatesLocal = anteConseVectors->attrConsequentCandidates;
+
+	if( vConsequentCandidatesLocal == NULL )
+		return NULL; //no candidates for consequent is provided, hence no need to generate a new AIG
+
+	
+	//****************************************************************
+	// Step1: create the new manager
+	// Note: The new manager is created with "2 * Aig_ManObjNumMax(p)"
+	// nodes, but this selection is arbitrary - need to be justified
+	//****************************************************************
+	pNewAig = Aig_ManStart( Aig_ManObjNumMax(pAig) );
+	pNewAig->pName = (char *)malloc( strlen( pAig->pName ) + strlen("_monotone") + 2 );
+	sprintf(pNewAig->pName, "%s_%s", pAig->pName, "monotone");
+    	pNewAig->pSpec = NULL;
+
+	//****************************************************************
+	// Step 2: map constant nodes
+	//****************************************************************
+    	pObj = Aig_ManConst1( pAig );
+    	pObj->pData = Aig_ManConst1( pNewAig );
+
+	//****************************************************************
+    	// Step 3: create true PIs
+	//****************************************************************
+    	Saig_ManForEachPi( pAig, pObj, i )
+	{
+		piCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNewAig);
+	}
+
+	//****************************************************************
+	// Step 5: create register outputs
+	//****************************************************************
+    	Saig_ManForEachLo( pAig, pObj, i )
+    	{
+		loCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNewAig);
+    	}
+
+	//****************************************************************
+	// Step 6: create "D" register output for PENDING flop 
+	//****************************************************************
+	loCreated++;
+	pPendingFlop = Aig_ObjCreateCi( pNewAig );
+
+	//****************************************************************
+	// Step 6.a: create "D" register output for HINT_MONOTONE flop 
+	//****************************************************************
+	vConseCandFlopOutput = Vec_PtrAlloc(Vec_IntSize(vConsequentCandidatesLocal));
+	Vec_IntForEachEntry( vConsequentCandidatesLocal, iElem, i )
+	{
+		loCreated++;
+		pObjConseCandFlop = Aig_ObjCreateCi( pNewAig );
+		Vec_PtrPush( vConseCandFlopOutput, pObjConseCandFlop );
+	}
+
+	nRegCount = loCreated + loCopied;
+
+	//********************************************************************
+	// Step 7: create internal nodes
+	//********************************************************************
+    	Aig_ManForEachNode( pAig, pObj, i )
+	{
+		pObj->pData = Aig_And( pNewAig, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+	}
+	
+	//********************************************************************
+	// Step 8: mapping appropriate new flop drivers 
+	//********************************************************************
+
+	if( aigPoIndicesArg->attrSafetyInvarIndex != -1 )
+	{
+		pObjPo = Aig_ManCo( pAig, aigPoIndicesArg->attrSafetyInvarIndex );
+		pObjDriver = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo));
+		pObjDriverNew = !Aig_IsComplement(pObjDriver)? 
+				(Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData) : 
+				Aig_Not((Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData));
+		pObjSafetyInvariantPoDriver = pObjDriverNew;
+	}
+	else
+		pObjSafetyInvariantPoDriver = Aig_ManConst1(pNewAig);
+
+	pObjPo = Aig_ManCo( pAig, pendingSignalIndexLocal );
+	pObjDriver = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo));
+	pObjPendingDriverNew = !Aig_IsComplement(pObjDriver)? 
+				(Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData) : 
+				Aig_Not((Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData));
+
+	pObjPendingAndNextPending = Aig_And( pNewAig, pObjPendingDriverNew, pPendingFlop );
+
+	pObjAnteDisjunction = Aig_Not(Aig_ManConst1( pNewAig ));
+	if( vAntecedentsLocal )
+	{
+		Vec_IntForEachEntry( vAntecedentsLocal, iElem, i )
+		{
+			pObjPo = Aig_ManCo( pAig, iElem );
+			pObjDriver = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo));
+			pObjDriverNew = !Aig_IsComplement(pObjDriver)? 
+					(Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData) : 
+					Aig_Not((Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData));
+
+			pObjAnteDisjunction = Aig_Or( pNewAig, pObjDriverNew, pObjAnteDisjunction );
+		}
+	}
+
+	vCandMonotoneProp = Vec_PtrAlloc( Vec_IntSize(vConsequentCandidatesLocal) );
+	vCandMonotoneFlopInput = Vec_PtrAlloc( Vec_IntSize(vConsequentCandidatesLocal) );
+	Vec_IntForEachEntry( vConsequentCandidatesLocal, iElem, i )
+	{
+		pObjPo = Aig_ManCo( pAig, iElem );
+		pObjConsecDriver = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo));
+		pObjConsecDriverNew = !Aig_IsComplement(pObjConsecDriver)? 
+					(Aig_Obj_t *)(Aig_Regular(pObjConsecDriver)->pData) : 
+					Aig_Not((Aig_Obj_t *)(Aig_Regular(pObjConsecDriver)->pData));
+
+		pObjCandMonotone = Aig_Or( pNewAig, pObjConsecDriverNew, pObjAnteDisjunction );
+		pObjPrevCandMonotone = (Aig_Obj_t *)(Vec_PtrEntry( vConseCandFlopOutput, i ));
+		pObjMonotonePropDriver = Aig_Or( pNewAig, Aig_Not( Aig_And( pNewAig, pObjPendingAndNextPending, pObjPrevCandMonotone ) ), 
+						pObjCandMonotone );
+
+		//Conjunting safety invar
+		pObjMonotonePropDriver = Aig_And( pNewAig, pObjMonotonePropDriver, pObjSafetyInvariantPoDriver );
+						
+		Vec_PtrPush( vCandMonotoneFlopInput, pObjCandMonotone );
+		Vec_PtrPush( vCandMonotoneProp, pObjMonotonePropDriver );
+	}
+
+	//********************************************************************
+	// Step 9: create primary outputs 
+	//********************************************************************
+	Saig_ManForEachPo( pAig, pObj, i )
+	{
+		poCopied++;
+		pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); 
+	}
+
+	*startMonotonePropPo = i;
+	Vec_PtrForEachEntry( Aig_Obj_t *, vCandMonotoneProp, pObj, i )
+	{
+		poCreated++;
+		pObjPo = Aig_ObjCreateCo( pNewAig, pObj ); 
+	}
+
+	//********************************************************************
+	// Step 9: create latch inputs 
+	//********************************************************************
+
+	Saig_ManForEachLi( pAig, pObj, i )
+	{
+		liCopied++;
+		Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) );
+	}
+	
+	//********************************************************************
+	// Step 9.a: create latch input for PENDING_FLOP
+	//********************************************************************
+
+	liCreated++;
+	Aig_ObjCreateCo( pNewAig, pObjPendingDriverNew );
+
+	//********************************************************************
+	// Step 9.b: create latch input for MONOTONE_FLOP
+	//********************************************************************
+
+	Vec_PtrForEachEntry( Aig_Obj_t *, vCandMonotoneFlopInput, pObj, i )
+	{
+		liCreated++;
+		Aig_ObjCreateCo( pNewAig, pObj );
+	}
+
+	Aig_ManSetRegNum( pNewAig, nRegCount );
+	Aig_ManCleanup( pNewAig );
+	
+	assert( Aig_ManCheck( pNewAig ) );
+	assert( loCopied + loCreated == liCopied + liCreated );
+
+	Vec_PtrFree(vConseCandFlopOutput);
+	Vec_PtrFree(vCandMonotoneProp);
+	Vec_PtrFree(vCandMonotoneFlopInput);
+	return pNewAig;
+}
+
+Vec_Int_t *findNewDisjunctiveMonotone( Aig_Man_t *pAig, struct aigPoIndices *aigPoIndicesArg, struct antecedentConsequentVectorsStruct *anteConseVectors )
+{
+	Aig_Man_t *pAigNew;
+	Aig_Obj_t *pObjTargetPo;
+	int poMarker;
+	//int i, RetValue, poSerialNum;
+	int i, poSerialNum;
+	Pdr_Par_t Pars, * pPars = &Pars;
+	//Abc_Cex_t * pCex = NULL;
+	Vec_Int_t *vMonotoneIndex;
+	//char fileName[20];
+	Abc_Cex_t * cexElem;
+
+	int pendingSignalIndexLocal = aigPoIndicesArg->attrPendingSignalIndex;
+
+	pAigNew = createDisjunctiveMonotoneTester(pAig, aigPoIndicesArg, anteConseVectors, &poMarker );
+
+	//printf("enter an integer : ");
+	//waitForInteger = getchar();
+	//putchar(waitForInteger);
+
+	vMonotoneIndex = Vec_IntAlloc(0);
+
+	for( i=0; i<Saig_ManPoNum(pAigNew); i++ )
+	{
+		pObjTargetPo = Aig_ManCo( pAigNew, i );
+		Aig_ObjChild0Flip( pObjTargetPo );
+	}
+
+	Pdr_ManSetDefaultParams( pPars );
+	pPars->fVerbose = 0;
+	pPars->fNotVerbose = 1;
+	pPars->fSolveAll = 1;
+	pAigNew->vSeqModelVec = NULL;
+	Pdr_ManSolve( pAigNew, pPars );	
+
+	if( pAigNew->vSeqModelVec )
+	{
+		Vec_PtrForEachEntry( Abc_Cex_t *, pAigNew->vSeqModelVec, cexElem, i )
+		{
+			if( cexElem == NULL  && i >= pendingSignalIndexLocal + 1)
+			{
+				poSerialNum = i - (pendingSignalIndexLocal + 1);
+				Vec_IntPush( vMonotoneIndex, Vec_IntEntry( anteConseVectors->attrConsequentCandidates, poSerialNum ));
+			}
+		}
+	}
+	for( i=0; i<Saig_ManPoNum(pAigNew); i++ )
+	{
+		pObjTargetPo = Aig_ManCo( pAigNew, i );
+		Aig_ObjChild0Flip( pObjTargetPo );
+	}
+	
+	//if(pAigNew->vSeqModelVec)
+	//	Vec_PtrFree(pAigNew->vSeqModelVec);
+
+	Aig_ManStop(pAigNew);
+	
+	if( Vec_IntSize( vMonotoneIndex ) > 0 )
+	{
+		return vMonotoneIndex;
+	}
+	else
+	{
+		Vec_IntFree(vMonotoneIndex);
+		return NULL;
+	}
+}
+
+Vec_Int_t *updateAnteConseVectors(struct antecedentConsequentVectorsStruct *anteConse )
+{
+	Vec_Int_t *vCandMonotone;
+	int iElem, i;
+
+	//if( vKnownMonotone == NULL || Vec_IntSize(vKnownMonotone) <= 0 )
+	//	return vHintMonotone;
+	if( anteConse->attrAntecedents == NULL  || Vec_IntSize(anteConse->attrAntecedents) <= 0 )
+		return anteConse->attrConsequentCandidates;
+	vCandMonotone = Vec_IntAlloc(0);
+	Vec_IntForEachEntry( anteConse->attrConsequentCandidates, iElem, i )
+	{
+		if( Vec_IntFind( anteConse->attrAntecedents, iElem ) == -1 )
+			Vec_IntPush( vCandMonotone, iElem );
+	}
+	
+	return vCandMonotone;
+}
+
+Vec_Int_t *vectorDifference(Vec_Int_t *A, Vec_Int_t *B)
+{
+	Vec_Int_t *C;
+	int iElem, i;
+
+	C = Vec_IntAlloc(0);
+	Vec_IntForEachEntry( A, iElem, i )
+	{
+		if( Vec_IntFind( B, iElem ) == -1 )
+		{
+			Vec_IntPush( C, iElem );
+		}
+	}
+
+	return C;
+}
+
+Vec_Int_t *createSingletonIntVector( int iElem )
+{
+	Vec_Int_t *myVec = Vec_IntAlloc(1);
+	
+	Vec_IntPush(myVec, iElem);
+	return myVec;
+}
+
+#if 0
+Vec_Ptr_t *generateDisjuntiveMonotone_rec()
+{
+	nextLevelSignals = ;
+	if level is not exhausted
+	for all x \in nextLevelSignals
+	{
+		append x in currAntecendent
+		recond it as a monotone predicate
+		resurse with level - 1 
+	}
+}
+#endif
+
+#if 0
+Vec_Ptr_t *generateDisjuntiveMonotoneLevels(Aig_Man_t *pAig, 
+			struct aigPoIndices *aigPoIndicesInstance, 
+			struct antecedentConsequentVectorsStruct *anteConsecInstanceOrig,
+			int level )
+{
+	Vec_Int_t *firstLevelMonotone;
+	Vec_Int_t *currVecInt;
+	Vec_Ptr_t *hierarchyList;
+	int iElem, i;
+
+	assert( level >= 1 );
+	firstLevelMonotone = findNewDisjunctiveMonotone( pAig, aigPoIndicesInstance, anteConsecInstance );
+	if( firstLevelMonotone == NULL || Vec_IntSize(firstLevelMonotone) <= 0 )
+		return NULL;
+	
+	hierarchyList = Vec_PtrAlloc(Vec_IntSize(firstLevelMonotone));
+	
+	Vec_IntForEachEntry( firstLevelMonotone, iElem, i )
+	{
+		currVecInt = createSingletonIntVector( iElem );
+		Vec_PtrPush( hierarchyList, currVecInt );
+	}
+
+	if( level > 1 )
+	{
+		Vec_IntForEachEntry( firstLevelMonotone, iElem, i )
+		{
+			currVecInt = (Vec_Int_t *)Vec_PtrEntry( hierarchyList, i );
+			
+			
+		}
+	}
+
+	return hierarchyList;
+}
+#endif
+
+int Vec_IntPushUniqueLocal( Vec_Int_t * p, int Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            return 1;
+    Vec_IntPush( p, Entry );
+    return 0;
+}
+
+Vec_Ptr_t *findNextLevelDisjunctiveMonotone( 
+		Aig_Man_t *pAig, 
+		struct aigPoIndices *aigPoIndicesInstance, 
+		struct antecedentConsequentVectorsStruct *anteConsecInstance, 
+		Vec_Ptr_t *previousMonotoneVectors )
+{
+	Vec_Ptr_t *newLevelPtrVec;
+	Vec_Int_t *vElem, *vNewDisjunctVector, *newDisjunction;
+	int i, j, iElem;
+	struct antecedentConsequentVectorsStruct *anteConsecInstanceLocal;
+	Vec_Int_t *vUnionPrevMonotoneVector, *vDiffVector;
+
+	newLevelPtrVec = Vec_PtrAlloc(0);
+	vUnionPrevMonotoneVector = Vec_IntAlloc(0);
+	Vec_PtrForEachEntry(Vec_Int_t *, previousMonotoneVectors, vElem, i)
+		Vec_IntForEachEntry( vElem, iElem, j )
+			Vec_IntPushUniqueLocal( vUnionPrevMonotoneVector, iElem );
+
+	Vec_PtrForEachEntry(Vec_Int_t *, previousMonotoneVectors, vElem, i)
+	{
+		anteConsecInstanceLocal = allocAntecedentConsequentVectorsStruct();
+
+		anteConsecInstanceLocal->attrAntecedents = Vec_IntDup(vElem);	
+		vDiffVector = vectorDifference( anteConsecInstance->attrConsequentCandidates, vUnionPrevMonotoneVector);
+		anteConsecInstanceLocal->attrConsequentCandidates = vDiffVector;
+		assert( vDiffVector );
+
+		//printf("Calling target function %d\n", i);
+		vNewDisjunctVector = findNewDisjunctiveMonotone( pAig, aigPoIndicesInstance, anteConsecInstanceLocal );
+
+		if( vNewDisjunctVector )
+		{
+			Vec_IntForEachEntry(vNewDisjunctVector, iElem, j)
+			{
+				newDisjunction = Vec_IntDup(vElem);
+				Vec_IntPush( newDisjunction, iElem );
+				Vec_PtrPush( newLevelPtrVec, newDisjunction );
+			}
+			Vec_IntFree(vNewDisjunctVector);
+		}
+		deallocAntecedentConsequentVectorsStruct( anteConsecInstanceLocal );
+	}
+
+	Vec_IntFree(vUnionPrevMonotoneVector);
+
+	return newLevelPtrVec;
+}
+
+void printAllIntVectors(Vec_Ptr_t *vDisjunctions, Abc_Ntk_t *pNtk, char *fileName)
+{
+	Vec_Int_t *vElem;
+	int i, j, iElem;
+	char *name, *hintSubStr;
+	FILE *fp;
+
+	fp = fopen( fileName, "a" );
+
+	Vec_PtrForEachEntry(Vec_Int_t *, vDisjunctions, vElem, i)
+	{	
+		fprintf(fp, "( ");
+		Vec_IntForEachEntry( vElem, iElem, j )
+		{
+			name = Abc_ObjName( Abc_NtkPo(pNtk, iElem));
+			hintSubStr = strstr( name, "hint");
+			assert( hintSubStr );
+			fprintf(fp, "%s", hintSubStr);
+			if( j < Vec_IntSize(vElem) - 1 )
+			{
+				fprintf(fp, " || ");
+			}
+			else
+			{
+				fprintf(fp, " )\n");
+			}
+		}
+	}
+	fclose(fp);
+}
+
+void printAllIntVectorsStabil(Vec_Ptr_t *vDisjunctions, Abc_Ntk_t *pNtk, char *fileName)
+{
+	Vec_Int_t *vElem;
+	int i, j, iElem;
+	char *name, *hintSubStr;
+	FILE *fp;
+
+	fp = fopen( fileName, "a" );
+
+	Vec_PtrForEachEntry(Vec_Int_t *, vDisjunctions, vElem, i)
+	{	
+		printf("INT[%d] : ( ", i);
+		fprintf(fp, "( ");
+		Vec_IntForEachEntry( vElem, iElem, j )
+		{
+			name = Abc_ObjName( Abc_NtkPo(pNtk, iElem));
+			hintSubStr = strstr( name, "csLevel1Stabil");
+			assert( hintSubStr );
+			printf("%s", hintSubStr);
+			fprintf(fp, "%s", hintSubStr);
+			if( j < Vec_IntSize(vElem) - 1 )
+			{
+				printf(" || ");
+				fprintf(fp, " || ");
+			}
+			else
+			{
+				printf(" )\n");
+				fprintf(fp, " )\n");
+			}
+		}
+		//printf(")\n");
+	}
+	fclose(fp);
+}
+
+
+void appendVecToMasterVecInt(Vec_Ptr_t *masterVec, Vec_Ptr_t *candVec )
+{
+	int i;
+	Vec_Int_t *vCand;
+	Vec_Int_t *vNewIntVec;
+
+	assert(masterVec != NULL);
+	assert(candVec != NULL);
+	Vec_PtrForEachEntry( Vec_Int_t *, candVec, vCand, i )
+	{
+		vNewIntVec = Vec_IntDup(vCand);	
+		Vec_PtrPush(masterVec, vNewIntVec);
+	}
+}
+
+void deallocateVecOfIntVec( Vec_Ptr_t *vecOfIntVec )
+{
+	Vec_Int_t *vInt;
+	int i;
+
+	if( vecOfIntVec )
+	{
+		Vec_PtrForEachEntry( Vec_Int_t *, vecOfIntVec, vInt, i )
+		{
+			Vec_IntFree( vInt );
+		}
+		Vec_PtrFree(vecOfIntVec);
+	}	
+}
+
+Vec_Ptr_t *findDisjunctiveMonotoneSignals( Abc_Ntk_t *pNtk )
+{
+	Aig_Man_t *pAig;
+	Vec_Int_t *vCandidateMonotoneSignals;
+	Vec_Int_t *vKnownMonotoneSignals;
+	//Vec_Int_t *vKnownMonotoneSignalsRoundTwo;
+	//Vec_Int_t *vOldConsequentVector;
+	//Vec_Int_t *vRemainingConsecVector;
+	int i;
+	int iElem;
+	int pendingSignalIndex;
+	Abc_Ntk_t *pNtkTemp;
+	int hintSingalBeginningMarker;
+	int hintSingalEndMarker;
+	struct aigPoIndices *aigPoIndicesInstance;
+	//struct monotoneVectorsStruct *monotoneVectorsInstance;
+	struct antecedentConsequentVectorsStruct *anteConsecInstance;
+	//Aig_Obj_t *safetyDriverNew;
+	Vec_Int_t *newIntVec;
+	Vec_Ptr_t *levelOneMonotne, *levelTwoMonotne;
+	//Vec_Ptr_t *levelThreeMonotne;
+
+	Vec_Ptr_t *vMasterDisjunctions;
+
+	extern int findPendingSignal(Abc_Ntk_t *pNtk);
+	extern Vec_Int_t *findHintOutputs(Abc_Ntk_t *pNtk);	
+	extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+
+	//system("rm monotone.dat");
+	
+	/*******************************************/	
+	//Finding the PO index of the pending signal 
+	/*******************************************/	
+	pendingSignalIndex = findPendingSignal(pNtk);
+	if( pendingSignalIndex == -1 )
+	{
+		printf("\nNo Pending Signal Found\n");
+		return NULL;
+	}
+	//else
+		//printf("Po[%d] = %s\n", pendingSignalIndex, Abc_ObjName( Abc_NtkPo(pNtk, pendingSignalIndex) ) );
+
+	/*******************************************/	
+	//Finding the PO indices of all hint signals
+	/*******************************************/	
+	vCandidateMonotoneSignals = findHintOutputs(pNtk);
+	if( vCandidateMonotoneSignals == NULL )
+		return NULL;
+	else
+	{
+		//Vec_IntForEachEntry( vCandidateMonotoneSignals, iElem, i )
+		//	printf("Po[%d] = %s\n", iElem, Abc_ObjName( Abc_NtkPo(pNtk, iElem) ) );
+		hintSingalBeginningMarker = Vec_IntEntry( vCandidateMonotoneSignals, 0 );
+		hintSingalEndMarker = Vec_IntEntry( vCandidateMonotoneSignals, Vec_IntSize(vCandidateMonotoneSignals) - 1 );
+	}
+
+	/**********************************************/
+	//Allocating "struct" with necessary parameters
+	/**********************************************/
+	aigPoIndicesInstance = allocAigPoIndices();
+	aigPoIndicesInstance->attrPendingSignalIndex = pendingSignalIndex;
+	aigPoIndicesInstance->attrHintSingalBeginningMarker = hintSingalBeginningMarker;
+	aigPoIndicesInstance->attrHintSingalEndMarker = hintSingalEndMarker;
+	aigPoIndicesInstance->attrSafetyInvarIndex = collectSafetyInvariantPOIndex(pNtk);
+
+	/****************************************************/
+	//Allocating "struct" with necessary monotone vectors
+	/****************************************************/
+	anteConsecInstance = allocAntecedentConsequentVectorsStruct();
+	anteConsecInstance->attrAntecedents = NULL;
+	anteConsecInstance->attrConsequentCandidates = vCandidateMonotoneSignals;
+
+	/*******************************************/	
+	//Generate AIG from Ntk
+	/*******************************************/	
+	if( !Abc_NtkIsStrash( pNtk ) )
+	{
+		pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+		pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
+	}
+	else
+	{
+		pAig = Abc_NtkToDar( pNtk, 0, 1 );
+		pNtkTemp = pNtk;
+	}
+
+	/*******************************************/	
+	//finding LEVEL 1 monotone signals
+	/*******************************************/	
+	//printf("Calling target function outside loop\n");
+	vKnownMonotoneSignals = findNewDisjunctiveMonotone( pAig, aigPoIndicesInstance, anteConsecInstance );
+	levelOneMonotne = Vec_PtrAlloc(0);
+	Vec_IntForEachEntry( vKnownMonotoneSignals, iElem, i )
+	{
+		newIntVec = createSingletonIntVector( iElem );
+		Vec_PtrPush( levelOneMonotne, newIntVec );
+		//printf("Monotone Po[%d] = %s\n", iElem, Abc_ObjName( Abc_NtkPo(pNtk, iElem) ) );
+	}
+	//printAllIntVectors( levelOneMonotne, pNtk, "monotone.dat" );
+
+	vMasterDisjunctions = Vec_PtrAlloc( Vec_PtrSize( levelOneMonotne ));
+	appendVecToMasterVecInt(vMasterDisjunctions, levelOneMonotne );
+
+	/*******************************************/	
+	//finding LEVEL >1 monotone signals
+	/*******************************************/	
+	#if 0
+	if( vKnownMonotoneSignals )
+	{
+		Vec_IntForEachEntry( vKnownMonotoneSignals, iElem, i )
+		{
+			printf("\n**************************************************************\n");
+			printf("Exploring Second Layer : Reference Po[%d] = %s", iElem, Abc_ObjName( Abc_NtkPo(pNtk, iElem) ));
+			printf("\n**************************************************************\n");
+			anteConsecInstance->attrAntecedents = createSingletonIntVector( iElem );
+			vOldConsequentVector = anteConsecInstance->attrConsequentCandidates;
+			vRemainingConsecVector = updateAnteConseVectors(anteConsecInstance);
+			if( anteConsecInstance->attrConsequentCandidates != vRemainingConsecVector )
+			{
+				anteConsecInstance->attrConsequentCandidates = vRemainingConsecVector;
+			}
+			vKnownMonotoneSignalsRoundTwo = findNewDisjunctiveMonotone( pAig, aigPoIndicesInstance, anteConsecInstance );
+			Vec_IntForEachEntry( vKnownMonotoneSignalsRoundTwo, iElemTwo, iTwo )
+			{
+				printf("Monotone Po[%d] = %s, (%d, %d)\n", iElemTwo, Abc_ObjName( Abc_NtkPo(pNtk, iElemTwo) ), iElem, iElemTwo );
+			}
+			Vec_IntFree(vKnownMonotoneSignalsRoundTwo);
+			Vec_IntFree(anteConsecInstance->attrAntecedents);
+			if(anteConsecInstance->attrConsequentCandidates != vOldConsequentVector)
+			{
+				Vec_IntFree(anteConsecInstance->attrConsequentCandidates);
+				anteConsecInstance->attrConsequentCandidates = vOldConsequentVector;
+			}
+		}
+	}
+	#endif 
+
+#if 1
+	levelTwoMonotne = findNextLevelDisjunctiveMonotone( pAig, aigPoIndicesInstance, anteConsecInstance, levelOneMonotne );
+	//printAllIntVectors( levelTwoMonotne, pNtk, "monotone.dat" );
+	appendVecToMasterVecInt(vMasterDisjunctions, levelTwoMonotne );
+#endif
+
+	//levelThreeMonotne = findNextLevelDisjunctiveMonotone( pAig, aigPoIndicesInstance, anteConsecInstance, levelTwoMonotne );
+	//printAllIntVectors( levelThreeMonotne );
+	//printAllIntVectors( levelTwoMonotne, pNtk, "monotone.dat" );
+	//appendVecToMasterVecInt(vMasterDisjunctions, levelThreeMonotne );
+
+	deallocAigPoIndices(aigPoIndicesInstance);
+	deallocAntecedentConsequentVectorsStruct(anteConsecInstance);
+	//deallocPointersToMonotoneVectors(monotoneVectorsInstance);
+
+	deallocateVecOfIntVec( levelOneMonotne );
+	deallocateVecOfIntVec( levelTwoMonotne );
+
+	Aig_ManStop(pAig);
+	Vec_IntFree(vKnownMonotoneSignals);
+
+	return vMasterDisjunctions;
+}
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/live/kLiveConstraints.c b/abc-build/src/proof/live/kLiveConstraints.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/live/kLiveConstraints.c
@@ -0,0 +1,177 @@
+/**CFile****************************************************************
+
+  FileName    [kLiveConstraints.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Liveness property checking.]
+
+  Synopsis    [Constraint analysis module for the k-Liveness algorithm
+		invented by Koen Classen, Niklas Sorensson.]
+
+  Author      [Sayak Ray]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 31, 2012.]
+
+  Revision    [$Id: liveness.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include "base/main/main.h"
+#include "aig/aig/aig.h"
+#include "aig/saig/saig.h"
+#include <string.h>
+#include "base/main/mainInt.h"
+#include "proof/pdr/pdr.h"
+
+ABC_NAMESPACE_IMPL_START
+
+Aig_Obj_t *createConstrained0LiveCone( Aig_Man_t *pNewAig, Vec_Ptr_t *signalList )
+{
+	Aig_Obj_t *pConsequent, *pConsequentCopy, *pAntecedent, *p0LiveCone, *pObj;
+	int i, numSigAntecedent;
+	
+	numSigAntecedent = Vec_PtrSize( signalList ) - 1;
+
+	pAntecedent = Aig_ManConst1( pNewAig );
+	pConsequent = (Aig_Obj_t *)Vec_PtrEntry( signalList, numSigAntecedent );
+	pConsequentCopy = Aig_NotCond( (Aig_Obj_t *)(Aig_Regular(pConsequent)->pData), Aig_IsComplement( pConsequent ) );
+
+	for(i=0; i<numSigAntecedent; i++ )
+	{
+		pObj = (Aig_Obj_t *)Vec_PtrEntry( signalList, i );
+		assert( Aig_Regular(pObj)->pData );
+		pAntecedent = Aig_And( pNewAig, pAntecedent, Aig_NotCond((Aig_Obj_t *)(Aig_Regular(pObj)->pData), Aig_IsComplement(pObj)) );
+	}
+
+	p0LiveCone = Aig_Or( pNewAig, Aig_Not(pAntecedent), pConsequentCopy );
+
+	return p0LiveCone;
+}
+
+Vec_Ptr_t *collectCSSignals( Abc_Ntk_t *pNtk, Aig_Man_t *pAig )
+{
+	int i;
+	Aig_Obj_t *pObj, *pConsequent = NULL;
+	Vec_Ptr_t *vNodeArray;
+
+	vNodeArray = Vec_PtrAlloc(1);
+
+	Saig_ManForEachPo( pAig, pObj, i )
+	{
+		if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "csLiveConst_" ) != NULL )
+			Vec_PtrPush( vNodeArray, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj)) );	
+		else if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "csLiveTarget_" ) != NULL )
+			pConsequent = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj));
+	}
+	assert( pConsequent );
+	Vec_PtrPush( vNodeArray, pConsequent );	
+	return vNodeArray;
+}
+
+Aig_Man_t *createNewAigWith0LivePo( Aig_Man_t *pAig, Vec_Ptr_t *signalList, int *index0Live )
+{
+	Aig_Man_t *pNewAig;
+	Aig_Obj_t *pObj, *pObjNewPoDriver;
+	int i;
+
+	//assert( Vec_PtrSize( signalList ) > 1 );
+
+	//****************************************************************
+	// Step1: create the new manager
+	// Note: The new manager is created with "2 * Aig_ManObjNumMax(p)"
+	// nodes, but this selection is arbitrary - need to be justified
+	//****************************************************************
+	pNewAig = Aig_ManStart( Aig_ManObjNumMax(pAig) );
+	pNewAig->pName = (char *)malloc( strlen( pAig->pName ) + strlen("_0Live") + 1 );
+	sprintf(pNewAig->pName, "%s_%s", pAig->pName, "0Live");
+    	pNewAig->pSpec = NULL;
+
+	//****************************************************************
+	// Step 2: map constant nodes
+	//****************************************************************
+    	pObj = Aig_ManConst1( pAig );
+    	pObj->pData = Aig_ManConst1( pNewAig );
+
+	//****************************************************************
+    	// Step 3: create true PIs
+	//****************************************************************
+    	Saig_ManForEachPi( pAig, pObj, i )
+	{
+		pObj->pData = Aig_ObjCreateCi( pNewAig );
+	}
+
+	//****************************************************************
+	// Step 5: create register outputs
+	//****************************************************************
+    	Saig_ManForEachLo( pAig, pObj, i )
+    	{
+		pObj->pData = Aig_ObjCreateCi( pNewAig );
+    	}
+
+	//********************************************************************
+	// Step 7: create internal nodes
+	//********************************************************************
+    	Aig_ManForEachNode( pAig, pObj, i )
+	{
+		pObj->pData = Aig_And( pNewAig, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+	}
+
+	Saig_ManForEachPo( pAig, pObj, i )
+	{
+		pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); 
+	}
+
+	pObjNewPoDriver = createConstrained0LiveCone( pNewAig, signalList );
+	Aig_ObjCreateCo( pNewAig, pObjNewPoDriver );
+	*index0Live = i;
+
+	Saig_ManForEachLi( pAig, pObj, i )
+	{
+		pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) );
+	}
+
+	Aig_ManSetRegNum( pNewAig, Aig_ManRegNum(pAig) );
+	Aig_ManCleanup( pNewAig );
+
+	assert( Aig_ManCheck( pNewAig ) );
+	return pNewAig;
+}
+
+Vec_Ptr_t *checkMonotoneSignal()
+{
+	return NULL;
+}
+
+Vec_Ptr_t *gatherMonotoneSignals(Aig_Man_t *pAig)
+{
+	int i;
+	Aig_Obj_t *pObj;
+
+	Aig_ManForEachNode( pAig, pObj, i )
+	{
+		Aig_ObjPrint( pAig, pObj );
+		printf("\n");
+	}
+	
+	return NULL;
+}
+
+Aig_Man_t *generateWorkingAig( Aig_Man_t *pAig, Abc_Ntk_t *pNtk, int *pIndex0Live )
+{
+	Vec_Ptr_t *vSignalVector;
+	Aig_Man_t *pAigNew;
+
+	vSignalVector = collectCSSignals( pNtk, pAig );	
+	assert(vSignalVector);
+	pAigNew = createNewAigWith0LivePo( pAig, vSignalVector, pIndex0Live );
+	Vec_PtrFree(vSignalVector);
+
+	return pAigNew;
+}
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/live/kliveness.c b/abc-build/src/proof/live/kliveness.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/live/kliveness.c
@@ -0,0 +1,816 @@
+/**CFile****************************************************************
+
+  FileName    [kliveness.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Liveness property checking.]
+
+  Synopsis    	[Main implementation module of the algorithm k-Liveness	] 
+	      	[invented by Koen Claessen, Niklas Sorensson. Implements]
+	      	[the code for 'kcs'. 'kcs' pre-processes based on switch]
+		[and then runs the (absorber circuit >> pdr) loop  ]
+
+  Author      [Sayak Ray]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 31, 2012.]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include "base/main/main.h"
+#include "aig/aig/aig.h"
+#include "aig/saig/saig.h"
+#include <string.h>
+#include "base/main/mainInt.h"
+#include "proof/pdr/pdr.h"
+#include <time.h>
+
+//#define WITHOUT_CONSTRAINTS
+
+ABC_NAMESPACE_IMPL_START
+
+/***************** Declaration of standard ABC related functions ********************/
+extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan );
+extern Abc_Ntk_t * Abc_NtkMakeOnePo( Abc_Ntk_t * pNtk, int Output, int nRange );
+extern void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName, Vec_Ptr_t * vPiNames, Vec_Ptr_t * vPoNames );
+/***********************************************************************************/
+
+/***************** Declaration of kLiveness related functions **********************/
+//function defined in kLiveConstraints.c
+extern Aig_Man_t *generateWorkingAig( Aig_Man_t *pAig, Abc_Ntk_t *pNtk, int *pIndex0Live );
+
+//function defined in arenaViolation.c
+extern Aig_Man_t *generateWorkingAigWithDSC( Aig_Man_t *pAig, Abc_Ntk_t *pNtk, int *pIndex0Live, Vec_Ptr_t *vMasterBarriers );
+
+//function defined in disjunctiveMonotone.c
+extern Vec_Ptr_t *findDisjunctiveMonotoneSignals( Abc_Ntk_t *pNtk );
+extern Vec_Int_t *createSingletonIntVector( int i );
+/***********************************************************************************/
+extern Aig_Man_t *generateDisjunctiveTester( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, int combN, int combK );
+extern Aig_Man_t *generateGeneralDisjunctiveTester( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, int combK );
+
+//Definition of some macros pertaining to modes/switches
+#define SIMPLE_kCS 0
+#define kCS_WITH_SAFETY_INVARIANTS 1
+#define kCS_WITH_DISCOVER_MONOTONE_SIGNALS 2
+#define kCS_WITH_SAFETY_AND_DCS_INVARIANTS 3
+#define kCS_WITH_SAFETY_AND_USER_GIVEN_DCS_INVARIANTS 4
+
+//unused function
+#if 0
+Aig_Obj_t *readTargetPinSignal(Aig_Man_t *pAig, Abc_Ntk_t *pNtk)
+{
+	Aig_Obj_t *pObj;
+	int i;
+
+	Saig_ManForEachPo( pAig, pObj, i )
+	{
+		if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "0Liveness_" ) != NULL  )
+		{
+			//return Aig_ObjFanin0(pObj);
+			return Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj));
+		}
+	}	
+
+	return NULL;
+}
+#endif
+
+Aig_Obj_t *readLiveSignal_0( Aig_Man_t *pAig, int liveIndex_0 )
+{
+	Aig_Obj_t *pObj;
+
+	pObj = Aig_ManCo( pAig, liveIndex_0 );
+	return Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj));
+}
+
+Aig_Obj_t *readLiveSignal_k( Aig_Man_t *pAig, int liveIndex_k )
+{
+	Aig_Obj_t *pObj;
+
+	pObj = Aig_ManCo( pAig, liveIndex_k );
+	return Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj));
+}
+
+//unused funtion
+#if 0
+Aig_Obj_t *readTargetPoutSignal(Aig_Man_t *pAig, Abc_Ntk_t *pNtk, int nonFirstIteration)
+{
+	Aig_Obj_t *pObj;
+	int i;
+
+	if( nonFirstIteration == 0 )
+		return NULL;
+	else
+		Saig_ManForEachPo( pAig, pObj, i )
+		{
+			if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "kLiveness_" ) != NULL  )
+			{
+				//return Aig_ObjFanin0(pObj);
+				return Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj));
+			}
+		}	
+
+	return NULL;
+}
+#endif
+
+//unused function
+#if 0
+void updateNewNetworkNameManager_kCS( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, Vec_Ptr_t *vPiNames, 
+			Vec_Ptr_t *vLoNames, Vec_Ptr_t *vPoNames, Vec_Ptr_t *vLiNames )
+{
+	Aig_Obj_t *pObj;
+	Abc_Obj_t *pNode;
+	int i, ntkObjId;
+
+	pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum( pNtk ) );
+
+	if( vPiNames )
+	{
+		Saig_ManForEachPi( pAig, pObj, i )
+		{
+			ntkObjId = Abc_NtkCi( pNtk, i )->Id;
+			Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vPiNames, i), NULL );
+		}
+	}
+	if( vLoNames )
+	{
+		Saig_ManForEachLo( pAig, pObj, i )
+		{
+			ntkObjId = Abc_NtkCi( pNtk, Saig_ManPiNum( pAig ) + i )->Id;
+			Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vLoNames, i), NULL );
+		}
+	}
+
+	if( vPoNames )
+	{
+		Saig_ManForEachPo( pAig, pObj, i )
+		{
+			ntkObjId = Abc_NtkCo( pNtk, i )->Id;
+			Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vPoNames, i), NULL );	
+		}
+	}
+
+	if( vLiNames )
+	{
+		Saig_ManForEachLi( pAig, pObj, i )
+		{
+			ntkObjId = Abc_NtkCo( pNtk, Saig_ManPoNum( pAig ) + i )->Id;
+			Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vLiNames, i), NULL );
+		}
+	}
+
+    // assign latch input names
+	Abc_NtkForEachLatch(pNtk, pNode, i)
+        if ( Nm_ManFindNameById(pNtk->pManName, Abc_ObjFanin0(pNode)->Id) == NULL )
+            Abc_ObjAssignName( Abc_ObjFanin0(pNode), Abc_ObjName(Abc_ObjFanin0(pNode)), NULL );
+}
+#endif
+
+Aig_Man_t *introduceAbsorberLogic( Aig_Man_t *pAig, int *pLiveIndex_0, int *pLiveIndex_k, int nonFirstIteration )
+{
+	Aig_Man_t *pNewAig;
+	Aig_Obj_t *pObj, *pObjAbsorberLo, *pPInNewArg, *pPOutNewArg;
+	Aig_Obj_t *pPIn = NULL, *pPOut = NULL, *pPOutCo = NULL;
+	Aig_Obj_t *pFirstAbsorberOr, *pSecondAbsorberOr;
+	int i;
+	int piCopied = 0, loCreated = 0, loCopied = 0, liCreated = 0, liCopied = 0; 
+	int nRegCount;
+
+	assert(*pLiveIndex_0 != -1);
+	if(nonFirstIteration == 0)
+		assert( *pLiveIndex_k == -1 );
+	else
+		assert( *pLiveIndex_k != -1  );
+
+	//****************************************************************
+	// Step1: create the new manager
+	// Note: The new manager is created with "2 * Aig_ManObjNumMax(p)"
+	// nodes, but this selection is arbitrary - need to be justified
+	//****************************************************************
+	pNewAig = Aig_ManStart( Aig_ManObjNumMax(pAig) );
+	pNewAig->pName = (char *)malloc( strlen( pAig->pName ) + strlen("_kCS") + 1 );
+	sprintf(pNewAig->pName, "%s_%s", pAig->pName, "kCS");
+    	pNewAig->pSpec = NULL;
+
+	//****************************************************************
+	// reading the signal pIn, and pOut
+	//****************************************************************
+
+	pPIn = readLiveSignal_0( pAig, *pLiveIndex_0 );
+	if( *pLiveIndex_k == -1 )
+		pPOut = NULL;
+	else
+		pPOut = readLiveSignal_k( pAig, *pLiveIndex_k );
+    
+	//****************************************************************
+	// Step 2: map constant nodes
+	//****************************************************************
+    	pObj = Aig_ManConst1( pAig );
+    	pObj->pData = Aig_ManConst1( pNewAig );
+
+	//****************************************************************
+    	// Step 3: create true PIs
+	//****************************************************************
+    	Saig_ManForEachPi( pAig, pObj, i )
+	{
+		piCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNewAig);
+	}
+
+	//****************************************************************
+	// Step 5: create register outputs
+	//****************************************************************
+    	Saig_ManForEachLo( pAig, pObj, i )
+    	{
+		loCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNewAig);
+    	}
+
+	//****************************************************************
+	// Step 6: create "D" register output for the ABSORBER logic
+	//****************************************************************
+	loCreated++;
+	pObjAbsorberLo = Aig_ObjCreateCi( pNewAig );
+
+	nRegCount = loCreated + loCopied;
+
+	//********************************************************************
+	// Step 7: create internal nodes
+	//********************************************************************
+    	Aig_ManForEachNode( pAig, pObj, i )
+	{
+		pObj->pData = Aig_And( pNewAig, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+	}
+
+	//****************************************************************
+	// Step 8: create the two OR gates of the OBSERVER logic
+	//****************************************************************
+	if( nonFirstIteration == 0 )
+	{
+		assert(pPIn);
+		
+		pPInNewArg = !Aig_IsComplement(pPIn)? 
+				(Aig_Obj_t *)((Aig_Regular(pPIn))->pData) : 
+				Aig_Not((Aig_Obj_t *)((Aig_Regular(pPIn))->pData));
+
+		pFirstAbsorberOr = Aig_Or( pNewAig, Aig_Not(pPInNewArg), pObjAbsorberLo );
+		pSecondAbsorberOr = Aig_Or( pNewAig, pPInNewArg, Aig_Not(pObjAbsorberLo) );
+	}
+	else
+	{
+		assert( pPOut );
+
+		pPInNewArg = !Aig_IsComplement(pPIn)? 
+				(Aig_Obj_t *)((Aig_Regular(pPIn))->pData) : 
+				Aig_Not((Aig_Obj_t *)((Aig_Regular(pPIn))->pData));
+		pPOutNewArg = !Aig_IsComplement(pPOut)? 
+				(Aig_Obj_t *)((Aig_Regular(pPOut))->pData) : 
+				Aig_Not((Aig_Obj_t *)((Aig_Regular(pPOut))->pData));
+		
+		pFirstAbsorberOr = Aig_Or( pNewAig, Aig_Not(pPOutNewArg), pObjAbsorberLo );
+		pSecondAbsorberOr = Aig_Or( pNewAig, pPInNewArg, Aig_Not(pObjAbsorberLo) );
+	}	
+	
+	//********************************************************************
+	// Step 9: create primary outputs 
+	//********************************************************************
+	Saig_ManForEachPo( pAig, pObj, i )
+	{
+		pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); 
+		if( i == *pLiveIndex_k )
+			pPOutCo = (Aig_Obj_t *)(pObj->pData);
+	}
+
+	//create new po
+	if( nonFirstIteration == 0 )
+	{
+		assert(pPOutCo == NULL);
+		pPOutCo = Aig_ObjCreateCo( pNewAig, pSecondAbsorberOr ); 	
+
+		*pLiveIndex_k = i;
+	}	
+	else
+	{
+		assert( pPOutCo != NULL );
+		//pPOutCo = Aig_ObjCreateCo( pNewAig, pSecondAbsorberOr ); 	
+		//*pLiveIndex_k = Saig_ManPoNum(pAig);
+
+		Aig_ObjPatchFanin0( pNewAig, pPOutCo, pSecondAbsorberOr );
+	}
+
+	Saig_ManForEachLi( pAig, pObj, i )
+	{
+		liCopied++;
+		Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) );
+	}
+
+	//create new li
+	liCreated++;
+	Aig_ObjCreateCo( pNewAig, pFirstAbsorberOr );
+
+	Aig_ManSetRegNum( pNewAig, nRegCount );
+	Aig_ManCleanup( pNewAig );
+	
+	assert( Aig_ManCheck( pNewAig ) );
+
+	assert( *pLiveIndex_k != - 1);
+	return pNewAig;
+}
+
+void modifyAigToApplySafetyInvar(Aig_Man_t *pAig, int csTarget, int safetyInvarPO)
+{
+	Aig_Obj_t *pObjPOSafetyInvar, *pObjSafetyInvar;
+	Aig_Obj_t *pObjPOCSTarget, *pObjCSTarget;
+	Aig_Obj_t *pObjCSTargetNew;
+
+	pObjPOSafetyInvar = Aig_ManCo( pAig, safetyInvarPO );
+	pObjSafetyInvar =  Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPOSafetyInvar), Aig_ObjFaninC0(pObjPOSafetyInvar));	
+	pObjPOCSTarget = Aig_ManCo( pAig, csTarget );
+	pObjCSTarget = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPOCSTarget), Aig_ObjFaninC0(pObjPOCSTarget));	
+
+	pObjCSTargetNew = Aig_And( pAig, pObjSafetyInvar, pObjCSTarget );
+	Aig_ObjPatchFanin0( pAig, pObjPOCSTarget, pObjCSTargetNew );
+}
+
+int flipConePdr( Aig_Man_t *pAig, int directive, int targetCSPropertyIndex, int safetyInvariantPOIndex, int absorberCount )
+{
+	int RetValue, i;
+	Aig_Obj_t *pObjTargetPo;
+	Aig_Man_t *pAigDupl;
+	Pdr_Par_t Pars, * pPars = &Pars;
+	Abc_Cex_t * pCex = NULL;
+
+	char *fileName;
+	
+	fileName = (char *)malloc(sizeof(char) * 50);
+	sprintf(fileName, "%s_%d.%s", "kLive", absorberCount, "blif" );
+
+	if( directive == kCS_WITH_SAFETY_INVARIANTS || directive == kCS_WITH_SAFETY_AND_DCS_INVARIANTS || directive == kCS_WITH_SAFETY_AND_USER_GIVEN_DCS_INVARIANTS )
+	{
+		assert( safetyInvariantPOIndex != -1 );
+		modifyAigToApplySafetyInvar(pAig, targetCSPropertyIndex, safetyInvariantPOIndex);
+	}
+
+	pAigDupl = pAig;
+	pAig = Aig_ManDupSimple( pAigDupl );
+
+	for( i=0; i<Saig_ManPoNum(pAig); i++ )
+	{
+		pObjTargetPo = Aig_ManCo( pAig, i );
+		Aig_ObjChild0Flip( pObjTargetPo );
+	}
+
+	Pdr_ManSetDefaultParams( pPars );
+	pPars->fVerbose = 1;
+	pPars->fNotVerbose = 1;
+	pPars->fSolveAll = 1;
+	pAig->vSeqModelVec = NULL;
+
+	Aig_ManCleanup( pAig );
+	assert( Aig_ManCheck( pAig ) );
+
+	Pdr_ManSolve( pAig, pPars );	
+
+	if( pAig->vSeqModelVec )
+	{
+		pCex = (Abc_Cex_t *)Vec_PtrEntry( pAig->vSeqModelVec, targetCSPropertyIndex );
+		if( pCex == NULL )
+		{
+			RetValue = 1;
+		}
+		else
+			RetValue = 0;
+	}
+	else
+	{
+		RetValue = -1;
+		exit(0);
+	}
+
+	free(fileName);
+
+	for( i=0; i<Saig_ManPoNum(pAig); i++ )
+	{
+		pObjTargetPo = Aig_ManCo( pAig, i );
+		Aig_ObjChild0Flip( pObjTargetPo );
+	}
+	
+	Aig_ManStop( pAig );
+	return RetValue;
+}
+
+//unused function
+#if 0
+int read0LiveIndex( Abc_Ntk_t *pNtk )
+{
+	Abc_Obj_t *pObj;
+	int i;
+
+	Abc_NtkForEachPo( pNtk, pObj, i )
+	{
+		if( strstr( Abc_ObjName( pObj ), "0Liveness_" ) != NULL )
+			return i;
+	}		
+
+	return -1;
+}
+#endif
+
+int collectSafetyInvariantPOIndex(Abc_Ntk_t *pNtk)
+{
+	Abc_Obj_t *pObj;
+	int i;
+
+	Abc_NtkForEachPo( pNtk, pObj, i )
+	{
+		if( strstr( Abc_ObjName( pObj ), "csSafetyInvar_" ) != NULL )
+			return i;
+	}		
+
+	return -1;
+}
+
+Vec_Ptr_t *collectUserGivenDisjunctiveMonotoneSignals( Abc_Ntk_t *pNtk )
+{
+	Abc_Obj_t *pObj;
+	int i;
+	Vec_Ptr_t *monotoneVector;
+	Vec_Int_t *newIntVector;
+
+	monotoneVector = Vec_PtrAlloc(0);	
+	Abc_NtkForEachPo( pNtk, pObj, i )
+	{
+		if( strstr( Abc_ObjName( pObj ), "csLevel1Stabil_" ) != NULL )
+		{
+			newIntVector = createSingletonIntVector(i);
+			Vec_PtrPush(monotoneVector, newIntVector);
+		}
+	}
+
+	if( Vec_PtrSize(monotoneVector) > 0 )
+		return monotoneVector;
+	else
+		return NULL;
+
+}
+
+void deallocateMasterBarrierDisjunctInt(Vec_Ptr_t *vMasterBarrierDisjunctsArg)
+{
+	Vec_Int_t *vInt;
+	int i;
+
+	if(vMasterBarrierDisjunctsArg)
+	{
+		Vec_PtrForEachEntry(Vec_Int_t *, vMasterBarrierDisjunctsArg, vInt, i)
+		{	
+			Vec_IntFree(vInt);
+		}
+		Vec_PtrFree(vMasterBarrierDisjunctsArg);
+	}
+}
+
+void deallocateMasterBarrierDisjunctVecPtrVecInt(Vec_Ptr_t *vMasterBarrierDisjunctsArg)
+{
+	Vec_Int_t *vInt;
+	Vec_Ptr_t *vPtr;
+	int i, j, k, iElem;
+
+	if(vMasterBarrierDisjunctsArg)
+	{
+		Vec_PtrForEachEntry(Vec_Ptr_t *, vMasterBarrierDisjunctsArg, vPtr, i)
+		{	
+			assert(vPtr);
+			Vec_PtrForEachEntry( Vec_Int_t *, vPtr, vInt, j )
+			{
+				//Vec_IntFree(vInt);
+				Vec_IntForEachEntry( vInt, iElem, k )
+					printf("%d - ", iElem);
+				//printf("Chung Chang j = %d\n", j);
+			}
+			Vec_PtrFree(vPtr);
+		}
+		Vec_PtrFree(vMasterBarrierDisjunctsArg);
+	}
+}
+
+Vec_Ptr_t *getVecOfVecFairness(FILE *fp)
+{
+	Vec_Ptr_t *masterVector = Vec_PtrAlloc(0);
+	//Vec_Ptr_t *currSignalVector;
+	char stringBuffer[100];
+	//int i;
+	
+	while(fgets(stringBuffer, 50, fp))
+	{
+		if(strstr(stringBuffer, ":"))
+		{
+
+		}
+		else
+		{
+				
+		}
+	}
+
+	return masterVector;
+}
+
+
+int Abc_CommandCS_kLiveness( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    	Abc_Ntk_t * pNtk, * pNtkTemp;
+	Aig_Man_t * pAig, *pAigCS, *pAigCSNew;
+	int absorberCount;
+	int absorberLimit = 500;
+	int RetValue;
+	int liveIndex_0 = -1, liveIndex_k = -1;
+	int fVerbose = 1;
+	int directive = -1;
+	int c;
+	int safetyInvariantPO = -1;
+	abctime beginTime, endTime;
+	double time_spent;
+	Vec_Ptr_t *vMasterBarrierDisjuncts = NULL;
+	Aig_Man_t *pWorkingAig;
+	//FILE *fp;
+
+	pNtk = Abc_FrameReadNtk(pAbc);
+
+	//fp = fopen("propFile.txt", "r");
+	//if( fp )
+	//	getVecOfVecFairness(fp);
+	//exit(0);
+
+	/*************************************************
+	Extraction of Command Line Argument	
+	*************************************************/
+	if( argc == 1 )
+	{
+		assert( directive == -1 );
+		directive = SIMPLE_kCS;
+	}
+	else
+	{
+		Extra_UtilGetoptReset();
+		while ( ( c = Extra_UtilGetopt( argc, argv, "cmCgh" ) ) != EOF )
+		{
+			switch( c )
+			{
+			case 'c':
+				directive = kCS_WITH_SAFETY_INVARIANTS; 
+				break;
+			case 'm':
+				directive = kCS_WITH_DISCOVER_MONOTONE_SIGNALS; 
+				break;
+			case 'C':
+				directive = kCS_WITH_SAFETY_AND_DCS_INVARIANTS;
+				break;
+			case 'g':
+				directive = kCS_WITH_SAFETY_AND_USER_GIVEN_DCS_INVARIANTS;
+				break;
+			case 'h':
+				goto usage;
+				break;
+			default:
+				goto usage;
+			}
+		}
+	}
+	/*************************************************
+	Extraction of Command Line Argument Ends	
+	*************************************************/
+
+	if( !Abc_NtkIsStrash( pNtk ) )
+	{
+		printf("The input network was not strashed, strashing....\n");
+		pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+		pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
+	}
+	else
+	{
+		pAig = Abc_NtkToDar( pNtk, 0, 1 );
+		pNtkTemp = pNtk;
+	}
+
+	if( directive == kCS_WITH_SAFETY_INVARIANTS )
+	{
+		safetyInvariantPO = collectSafetyInvariantPOIndex(pNtkTemp);			
+		assert( safetyInvariantPO != -1 );
+	}
+
+	if(directive == kCS_WITH_DISCOVER_MONOTONE_SIGNALS)
+	{
+		beginTime = Abc_Clock();
+		vMasterBarrierDisjuncts = findDisjunctiveMonotoneSignals( pNtk );
+		endTime = Abc_Clock();
+		time_spent = (double)(endTime - beginTime)/CLOCKS_PER_SEC;
+		printf("pre-processing time = %f\n",time_spent); 
+		return 0;
+	}
+
+	if(directive == kCS_WITH_SAFETY_AND_DCS_INVARIANTS)
+	{
+		safetyInvariantPO = collectSafetyInvariantPOIndex(pNtkTemp);			
+		assert( safetyInvariantPO != -1 );
+
+		beginTime = Abc_Clock();
+		vMasterBarrierDisjuncts = findDisjunctiveMonotoneSignals( pNtk );
+		endTime = Abc_Clock();
+		time_spent = (double)(endTime - beginTime)/CLOCKS_PER_SEC;
+		printf("pre-processing time = %f\n",time_spent); 
+
+		assert( vMasterBarrierDisjuncts != NULL );
+		assert( Vec_PtrSize(vMasterBarrierDisjuncts) > 0 );
+	}
+
+	if(directive == kCS_WITH_SAFETY_AND_USER_GIVEN_DCS_INVARIANTS)
+	{
+		safetyInvariantPO = collectSafetyInvariantPOIndex(pNtkTemp);			
+		assert( safetyInvariantPO != -1 );
+
+		beginTime = Abc_Clock();
+		vMasterBarrierDisjuncts = collectUserGivenDisjunctiveMonotoneSignals( pNtk );
+		endTime = Abc_Clock();
+		time_spent = (double)(endTime - beginTime)/CLOCKS_PER_SEC;
+		printf("pre-processing time = %f\n",time_spent); 
+
+		assert( vMasterBarrierDisjuncts != NULL );
+		assert( Vec_PtrSize(vMasterBarrierDisjuncts) > 0 );
+	}
+
+	if(directive == kCS_WITH_SAFETY_AND_DCS_INVARIANTS || directive == kCS_WITH_SAFETY_AND_USER_GIVEN_DCS_INVARIANTS)
+	{
+		assert( vMasterBarrierDisjuncts != NULL );
+		pWorkingAig = generateWorkingAigWithDSC( pAig, pNtk, &liveIndex_0, vMasterBarrierDisjuncts );
+		pAigCS = introduceAbsorberLogic(pWorkingAig, &liveIndex_0, &liveIndex_k, 0);
+	}
+	else
+	{
+		pWorkingAig = generateWorkingAig( pAig, pNtk, &liveIndex_0 );
+		pAigCS = introduceAbsorberLogic(pWorkingAig, &liveIndex_0, &liveIndex_k, 0);
+	}
+
+	Aig_ManStop(pWorkingAig);
+
+	for( absorberCount=1; absorberCount<absorberLimit; absorberCount++ )
+	{
+		//printf( "\nindex of the liveness output = %d\n", liveIndex_k );
+		RetValue = flipConePdr( pAigCS, directive, liveIndex_k, safetyInvariantPO, absorberCount );
+
+		if ( RetValue == 1 )
+		{
+        		Abc_Print( 1, "k = %d, Property proved\n", absorberCount );
+			break;
+		}
+    		else if ( RetValue == 0 )
+		{
+			if( fVerbose )
+			{
+				Abc_Print( 1, "k = %d, Property DISPROVED\n", absorberCount );
+			}
+		}
+    		else if ( RetValue == -1 )
+		{
+        		Abc_Print( 1, "Property UNDECIDED with k = %d.\n", absorberCount );
+		}
+    		else
+        		assert( 0 );
+
+		pAigCSNew = introduceAbsorberLogic(pAigCS, &liveIndex_0, &liveIndex_k, absorberCount);
+		Aig_ManStop(pAigCS);
+		pAigCS = pAigCSNew;
+	}
+
+	Aig_ManStop(pAigCS);
+	Aig_ManStop(pAig);
+
+	if(directive == kCS_WITH_SAFETY_AND_USER_GIVEN_DCS_INVARIANTS)
+	{
+		deallocateMasterBarrierDisjunctInt(vMasterBarrierDisjuncts);
+	}
+	else
+	{
+		//if(vMasterBarrierDisjuncts)
+		//	Vec_PtrFree(vMasterBarrierDisjuncts);
+		//deallocateMasterBarrierDisjunctVecPtrVecInt(vMasterBarrierDisjuncts);
+		deallocateMasterBarrierDisjunctInt(vMasterBarrierDisjuncts);
+	}
+	return 0;
+
+	usage:
+		fprintf( stdout, "usage: kcs [-cmgCh]\n" );
+    		fprintf( stdout, "\timplements Claessen-Sorensson's k-Liveness algorithm\n" );
+		fprintf( stdout, "\t-c : verification with constraints, looks for POs prefixed with csSafetyInvar_\n");
+		fprintf( stdout, "\t-m : discovers monotone signals\n");
+    		fprintf( stdout, "\t-g : verification with user-supplied barriers, looks for POs prefixed with csLevel1Stabil_\n");
+		fprintf( stdout, "\t-C : verification with discovered monotone signals\n");
+		fprintf( stdout, "\t-h : print usage\n");
+    		return 1;
+
+}
+
+int Abc_CommandNChooseK( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+	Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkCombStabil;
+	Aig_Man_t * pAig, *pAigCombStabil;
+	int directive = -1;
+	int c;
+	int parameterizedCombK;
+
+	pNtk = Abc_FrameReadNtk(pAbc);
+
+
+	/*************************************************
+	Extraction of Command Line Argument	
+	*************************************************/
+	if( argc == 1 )
+	{
+		assert( directive == -1 );
+		directive = SIMPLE_kCS;
+	}
+	else
+	{
+		Extra_UtilGetoptReset();
+		while ( ( c = Extra_UtilGetopt( argc, argv, "cmCgh" ) ) != EOF )
+		{
+			switch( c )
+			{
+			case 'c':
+				directive = kCS_WITH_SAFETY_INVARIANTS; 
+				break;
+			case 'm':
+				directive = kCS_WITH_DISCOVER_MONOTONE_SIGNALS; 
+				break;
+			case 'C':
+				directive = kCS_WITH_SAFETY_AND_DCS_INVARIANTS;
+				break;
+			case 'g':
+				directive = kCS_WITH_SAFETY_AND_USER_GIVEN_DCS_INVARIANTS;
+				break;
+			case 'h':
+				goto usage;
+				break;
+			default:
+				goto usage;
+			}
+		}
+	}
+	/*************************************************
+	Extraction of Command Line Argument Ends	
+	*************************************************/
+
+	if( !Abc_NtkIsStrash( pNtk ) )
+	{
+		printf("The input network was not strashed, strashing....\n");
+		pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+		pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
+	}
+	else
+	{
+		pAig = Abc_NtkToDar( pNtk, 0, 1 );
+		pNtkTemp = pNtk;
+	}
+
+/**********************Code for generation of nCk outputs**/
+	//combCount = countCombination(1000, 3);
+	//pAigCombStabil = generateDisjunctiveTester( pNtk, pAig, 7, 2 );
+	printf("Enter parameterizedCombK = " );
+	if( scanf("%d", &parameterizedCombK) != 1 )
+	{
+		printf("\nFailed to read integer!\n");
+		return 0;
+	}
+	printf("\n");
+
+	pAigCombStabil = generateGeneralDisjunctiveTester( pNtk, pAig, parameterizedCombK );
+	Aig_ManPrintStats(pAigCombStabil);
+	pNtkCombStabil = Abc_NtkFromAigPhase( pAigCombStabil );
+	pNtkCombStabil->pName = Abc_UtilStrsav( pAigCombStabil->pName );
+	if ( !Abc_NtkCheck( pNtkCombStabil ) )
+	        fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" );
+	Abc_FrameSetCurrentNetwork( pAbc, pNtkCombStabil );
+
+	Aig_ManStop( pAigCombStabil );
+	Aig_ManStop( pAig );
+
+	return 1;
+	//printf("\ncombCount = %d\n", combCount);
+	//exit(0);
+/**********************************************************/
+
+	usage:
+		fprintf( stdout, "usage: nck [-cmgCh]\n" );
+    		fprintf( stdout, "\tgenerates combinatorial signals for stabilization\n" );
+		fprintf( stdout, "\t-h : print usage\n");
+    		return 1;
+
+}
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/live/liveness.c b/abc-build/src/proof/live/liveness.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/live/liveness.c
@@ -0,0 +1,2575 @@
+/**CFile****************************************************************
+
+  FileName    [liveness.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Liveness property checking.]
+
+  Synopsis    [Main implementation module.]
+
+  Author      [Sayak Ray]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2009.]
+
+  Revision    [$Id: liveness.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include "base/main/main.h"
+#include "aig/aig/aig.h"
+#include "aig/saig/saig.h"
+#include <string.h>
+#include "base/main/mainInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+#define PROPAGATE_NAMES
+#define MULTIPLE_LTL_FORMULA
+#define ALLOW_SAFETY_PROPERTIES
+
+#define FULL_BIERE_MODE 0
+#define IGNORE_LIVENESS_KEEP_SAFETY_MODE 1
+#define IGNORE_SAFETY_KEEP_LIVENESS_MODE 2
+#define IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE 3
+#define FULL_BIERE_ONE_LOOP_MODE 4
+//#define DUPLICATE_CKT_DEBUG
+
+extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan );
+//char *strdup(const char *string);
+
+//******************************************
+//external functions defined in ltl_parser.c
+//******************************************
+typedef struct ltlNode_t ltlNode;
+extern ltlNode *readLtlFormula( char *formula );
+extern void traverseAbstractSyntaxTree( ltlNode *node );
+extern ltlNode *parseFormulaCreateAST( char *inputFormula );
+extern int isWellFormed( ltlNode *topNode );
+extern int checkSignalNameExistence( Abc_Ntk_t *pNtk, ltlNode *topASTNode );
+extern void populateBoolWithAigNodePtr( Abc_Ntk_t *pNtk, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, ltlNode *topASTNode );
+extern int checkAllBoolHaveAIGPointer( ltlNode *topASTNode );
+extern void populateAigPointerUnitGF( Aig_Man_t *pAigNew, ltlNode *topASTNode, Vec_Ptr_t *vSignal, Vec_Vec_t *vAigGFMap );
+extern void setAIGNodePtrOfGloballyNode( ltlNode *astNode, Aig_Obj_t *pObjLo );
+extern Aig_Obj_t *buildLogicFromLTLNode( Aig_Man_t *pAig, ltlNode *pLtlNode );
+extern Aig_Obj_t *retriveAIGPointerFromLTLNode( ltlNode *astNode );
+extern void traverseAbstractSyntaxTree_postFix( ltlNode *node );
+//**********************************
+//external function declaration ends
+//**********************************
+
+ 
+/*******************************************************************
+LAYOUT OF PI VECTOR:
+
++------------------------------------------------------------------------------------------------------------------------------------+
+| TRUE ORIGINAL PI (n) | SAVE(PI) (1) | ORIGINAL LO (k) | SAVED(LO) (1) | SHADOW_ORIGINAL LO (k) | LIVENESS LO (l) | FAIRNESS LO (f) |
++------------------------------------------------------------------------------------------------------------------------------------+
+<------------True PI----------------->|<----------------------------LO--------------------------------------------------------------->
+
+LAYOUT OF PO VECTOR:
+
++-----------------------------------------------------------------------------------------------------------+
+| SOLE PO (1) | ORIGINAL LI (k) | SAVED LI (1) | SHADOW_ORIGINAL LI (k) | LIVENESS LI (l) | FAIRNESS LI (f) |
++-----------------------------------------------------------------------------------------------------------+
+<--True PO--->|<--------------------------------------LI---------------------------------------------------->
+
+********************************************************************/
+
+
+static int nodeName_starts_with( Abc_Obj_t *pNode, const char *prefix )
+{
+	if( strstr( Abc_ObjName( pNode ), prefix ) == Abc_ObjName( pNode ) )
+		return 1;
+	else
+		return 0;
+}
+
+void printVecPtrOfString( Vec_Ptr_t *vec )
+{
+	int i;
+
+	for( i=0; i< Vec_PtrSize( vec ); i++ )
+	{
+		printf("vec[%d] = %s\n", i, (char *)Vec_PtrEntry(vec, i) );
+	}
+}
+
+int getPoIndex( Aig_Man_t *pAig, Aig_Obj_t *pPivot )
+{
+	int i;
+	Aig_Obj_t *pObj;
+
+	Saig_ManForEachPo( pAig, pObj, i )
+	{
+		if( pObj == pPivot )
+			return i;
+	}
+	return -1;
+}
+
+char * retrieveTruePiName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot )
+{
+	Aig_Obj_t *pObjOld, *pObj;
+	Abc_Obj_t *pNode;
+	int index;
+
+	assert( Saig_ObjIsPi( pAigNew, pObjPivot ) );
+	Aig_ManForEachCi( pAigNew, pObj, index )
+		if( pObj == pObjPivot )
+			break;
+	assert( index < Aig_ManCiNum( pAigNew ) - Aig_ManRegNum( pAigNew ) );
+	if( index == Saig_ManPiNum( pAigNew ) - 1 )
+		return "SAVE_BIERE";
+	else
+	{
+		pObjOld = Aig_ManCi( pAigOld, index );
+		pNode = Abc_NtkPi( pNtkOld, index );
+		assert( pObjOld->pData == pObjPivot );
+		return Abc_ObjName( pNode );
+	}
+}
+
+char * retrieveLOName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot, Vec_Ptr_t *vLive, Vec_Ptr_t * vFair )
+{
+	Aig_Obj_t *pObjOld, *pObj;
+	Abc_Obj_t *pNode;
+	int index, oldIndex, originalLatchNum = Saig_ManRegNum(pAigOld), strMatch, i;
+	char *dummyStr = (char *)malloc( sizeof(char) * 50 );
+
+	assert( Saig_ObjIsLo( pAigNew, pObjPivot ) );
+	Saig_ManForEachLo( pAigNew, pObj, index )
+		if( pObj == pObjPivot )
+			break;
+	if( index < originalLatchNum )
+	{
+		oldIndex = Saig_ManPiNum( pAigOld ) + index;
+		pObjOld = Aig_ManCi( pAigOld, oldIndex );
+		pNode = Abc_NtkCi( pNtkOld, oldIndex );
+		assert( pObjOld->pData == pObjPivot );
+		return Abc_ObjName( pNode );
+	}
+	else if( index == originalLatchNum )
+		return "SAVED_LO";
+	else if( index > originalLatchNum && index < 2 * originalLatchNum + 1 )
+	{
+		oldIndex = Saig_ManPiNum( pAigOld ) + index - originalLatchNum - 1;
+		pObjOld = Aig_ManCi( pAigOld, oldIndex );
+		pNode = Abc_NtkCi( pNtkOld, oldIndex );
+		sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "SHADOW");
+		return dummyStr;
+	}
+	else if( index >= 2 * originalLatchNum + 1 && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) )
+	{
+		oldIndex = index - 2 * originalLatchNum - 1;
+		strMatch = 0;
+		dummyStr[0] = '\0';
+		Saig_ManForEachPo( pAigOld, pObj, i )
+		{
+			pNode = Abc_NtkPo( pNtkOld, i );
+			//if( strstr( Abc_ObjName( pNode ), "assert_fair" ) != NULL )
+			if(	nodeName_starts_with( pNode, "assert_fair" ) )
+			{
+				if( strMatch == oldIndex )
+				{
+					sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "LIVENESS");
+					//return dummyStr;
+					break;
+				}
+				else
+					strMatch++;
+			}
+		}
+		assert( dummyStr[0] != '\0' );
+		return dummyStr;
+	}
+	else if( index >= 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) )
+	{
+		oldIndex = index - 2 * originalLatchNum - 1 - Vec_PtrSize( vLive );
+		strMatch = 0;
+		dummyStr[0] = '\0';
+		Saig_ManForEachPo( pAigOld, pObj, i )
+		{
+			pNode = Abc_NtkPo( pNtkOld, i );
+			//if( strstr( Abc_ObjName( pNode ), "assume_fair" ) != NULL )
+			if(	nodeName_starts_with( pNode, "assume_fair" ) )
+			{
+				if( strMatch == oldIndex )
+				{
+					sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "FAIRNESS");
+					//return dummyStr;
+					break;
+				}
+				else
+					strMatch++;
+			}
+		}
+		assert( dummyStr[0] != '\0' );
+		return dummyStr;
+	}
+	else
+		return "UNKNOWN";
+}
+
+Vec_Ptr_t *vecPis, *vecPiNames;
+Vec_Ptr_t *vecLos, *vecLoNames;
+
+
+int Aig_ManCiCleanupBiere( Aig_Man_t * p )
+{
+    int nPisOld = Aig_ManCiNum(p);
+	
+    p->nObjs[AIG_OBJ_CI] = Vec_PtrSize( p->vCis );
+    if ( Aig_ManRegNum(p) )
+        p->nTruePis = Aig_ManCiNum(p) - Aig_ManRegNum(p);
+	
+    return nPisOld - Aig_ManCiNum(p);
+}
+
+
+int Aig_ManCoCleanupBiere( Aig_Man_t * p )
+{
+    int nPosOld = Aig_ManCoNum(p);
+
+    p->nObjs[AIG_OBJ_CO] = Vec_PtrSize( p->vCos );
+    if ( Aig_ManRegNum(p) )
+        p->nTruePos = Aig_ManCoNum(p) - Aig_ManRegNum(p);
+    return nPosOld - Aig_ManCoNum(p);
+}
+
+Aig_Man_t * LivenessToSafetyTransformation( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, 
+										   Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety )
+{
+	Aig_Man_t * pNew;
+	int i, nRegCount;
+	Aig_Obj_t * pObjSavePi = NULL;
+	Aig_Obj_t *pObjSavedLo = NULL, *pObjSavedLi = NULL;
+	Aig_Obj_t *pObj, *pMatch;
+	Aig_Obj_t *pObjSaveOrSaved = NULL, *pObjSaveAndNotSaved = NULL, *pObjSavedLoAndEquality;
+	Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver;
+	Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc;
+	Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate;
+	Aig_Obj_t *pObjSafetyPropertyOutput = NULL;
+	Aig_Obj_t *pObjOriginalSafetyPropertyOutput;
+	Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety;
+	char *nodeName;
+	int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, liveLatch = 0, fairLatch = 0;
+	
+	vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
+	vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
+
+	vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
+	vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
+
+	//****************************************************************
+	// Step1: create the new manager
+	// Note: The new manager is created with "2 * Aig_ManObjNumMax(p)"
+	// nodes, but this selection is arbitrary - need to be justified
+	//****************************************************************
+	pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) );
+	pNew->pName = (char *)malloc( strlen( pNtk->pName ) + strlen("_l2s") + 1 );
+	sprintf(pNew->pName, "%s_%s", pNtk->pName, "l2s");
+    pNew->pSpec = NULL;
+    
+	//****************************************************************
+	// Step 2: map constant nodes
+	//****************************************************************
+    pObj = Aig_ManConst1( p );
+    pObj->pData = Aig_ManConst1( pNew );
+
+	//****************************************************************
+    // Step 3: create true PIs
+	//****************************************************************
+    Saig_ManForEachPi( p, pObj, i )
+	{
+		piCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNew);
+		Vec_PtrPush( vecPis, pObj->pData );
+		nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) ));
+		Vec_PtrPush( vecPiNames, nodeName );
+	}
+
+	//****************************************************************
+	// Step 4: create the special Pi corresponding to SAVE
+	//****************************************************************
+	if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+	{
+		pObjSavePi = Aig_ObjCreateCi( pNew );
+		nodeName = "SAVE_BIERE",
+		Vec_PtrPush( vecPiNames, nodeName );
+	}
+		
+	//****************************************************************
+	// Step 5: create register outputs
+	//****************************************************************
+    Saig_ManForEachLo( p, pObj, i )
+    {
+		loCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNew);
+		Vec_PtrPush( vecLos, pObj->pData );
+		nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ));
+		Vec_PtrPush( vecLoNames, nodeName );
+    }
+
+	//****************************************************************
+	// Step 6: create "saved" register output
+	//****************************************************************
+	if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+	{
+		loCreated++;
+		pObjSavedLo = Aig_ObjCreateCi( pNew );
+		Vec_PtrPush( vecLos, pObjSavedLo );
+		nodeName = "SAVED_LO";
+		Vec_PtrPush( vecLoNames, nodeName );
+	}
+
+	//****************************************************************
+	// Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi
+	//****************************************************************
+	if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+	{
+		pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo );
+		pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) );
+	}
+
+	//********************************************************************
+	// Step 8: create internal nodes
+	//********************************************************************
+    Aig_ManForEachNode( p, pObj, i )
+	{
+		pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+	}
+
+	
+	//********************************************************************
+	// Step 8.x : create PO for each safety assertions
+	// NOTE : Here the output is purposely inverted as it will be thrown to 
+	// dprove
+	//********************************************************************
+	if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+	{
+		if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 )
+		{
+			pObjAndAcc = Aig_ManConst1( pNew );
+			Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+			{
+				pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+				pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+			}
+			pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_Not(pObjAndAcc) );
+		}
+		else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 )
+		{
+			pObjAndAcc = Aig_ManConst1( pNew );
+			Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+			{
+				pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+				pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+			}
+			collectiveAssertSafety = pObjAndAcc;
+
+			pObjAndAcc = Aig_ManConst1( pNew );
+			Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i )
+			{
+				pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+				pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+			}
+			collectiveAssumeSafety = pObjAndAcc;
+			pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) );
+		}
+		else
+		{
+			printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n");
+			pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_Not( Aig_ManConst1(pNew) ) );
+		}
+	}
+
+	//********************************************************************
+	// Step 9: create the safety property output gate for the liveness properties
+	// discuss with Sat/Alan for an alternative implementation
+	//********************************************************************
+	if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+	{
+		pObjSafetyPropertyOutput = Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData );
+	}
+
+	// create register inputs for the original registers
+	nRegCount = 0;
+	
+	Saig_ManForEachLo( p, pObj, i )
+	{
+		pMatch = Saig_ObjLoToLi( p, pObj );
+		Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) );
+		nRegCount++;
+		liCopied++;
+	}
+
+	// create register input corresponding to the register "saved"
+	if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+	{
+		#ifndef DUPLICATE_CKT_DEBUG
+			pObjSavedLi = Aig_ObjCreateCo( pNew, pObjSaveOrSaved );
+			nRegCount++;
+			liCreated++;
+
+			//Changed on October 13, 2009
+			//pObjAndAcc = NULL;
+			pObjAndAcc = Aig_ManConst1( pNew );
+
+	// create the family of shadow registers, then create the cascade of Xnor and And gates for the comparator 
+			Saig_ManForEachLo( p, pObj, i )
+			{
+				pObjShadowLo = Aig_ObjCreateCi( pNew );
+
+				#ifdef PROPAGATE_NAMES
+					Vec_PtrPush( vecLos, pObjShadowLo );
+					nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ) + 10 );
+					sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "SHADOW" );
+					
+					Vec_PtrPush( vecLoNames, nodeName );
+				#endif
+
+				pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
+				pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver );
+				nRegCount++;
+				loCreated++; liCreated++;
+		
+				pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
+				pObjXnor = Aig_Not( pObjXor );
+				
+				pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc );
+			}
+
+			// create the AND gate whose output will be the signal "looped"
+			pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc );
+
+			// create the master AND gate and corresponding AND and OR logic for the liveness properties
+			pObjAndAcc = Aig_ManConst1( pNew );
+			if( vLive == NULL || Vec_PtrSize( vLive ) == 0 )
+			{
+				printf("Circuit without any liveness property\n");
+			}
+			else
+			{
+				Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i )
+				{
+					liveLatch++;
+					pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+					pObjShadowLo = Aig_ObjCreateCi( pNew );
+
+					#ifdef PROPAGATE_NAMES
+						Vec_PtrPush( vecLos, pObjShadowLo );
+						nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 );
+						sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" );
+						Vec_PtrPush( vecLoNames, nodeName );
+					#endif
+
+					pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
+					pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver );
+					nRegCount++;
+					loCreated++; liCreated++;
+			
+					pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc );
+				}
+			}
+
+			pObjLive = pObjAndAcc;
+				
+			pObjAndAcc = Aig_ManConst1( pNew );
+			if( vFair == NULL || Vec_PtrSize( vFair ) == 0 )
+				printf("Circuit without any fairness property\n");
+			else
+			{
+				Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i )
+				{
+					fairLatch++;
+					pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+					pObjShadowLo = Aig_ObjCreateCi( pNew );
+
+					#ifdef PROPAGATE_NAMES
+						Vec_PtrPush( vecLos, pObjShadowLo );
+						nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 );
+						sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "FAIRNESS" );
+						Vec_PtrPush( vecLoNames, nodeName );
+					#endif
+
+					pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
+					pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver );
+					nRegCount++;
+					loCreated++; liCreated++;
+			
+					pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc );
+				}
+			}
+
+			pObjFair = pObjAndAcc;
+				
+			//pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) );
+			//Following is the actual Biere translation
+			pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) );
+
+			Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate );
+		#endif
+	}
+
+	Aig_ManSetRegNum( pNew, nRegCount );
+
+	Aig_ManCiCleanupBiere( pNew );
+	Aig_ManCoCleanupBiere( pNew );
+	
+	Aig_ManCleanup( pNew );
+	
+	assert( Aig_ManCheck( pNew ) );
+	
+	if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+	{
+			assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vCos, Saig_ManPoNum(pNew)+Aig_ObjCioId(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi);
+			assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) );
+			assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch );
+	}
+
+	return pNew;
+}
+
+
+
+
+
+Aig_Man_t * LivenessToSafetyTransformationAbs( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Int_t *vFlops, 
+										   Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety )
+{
+	Aig_Man_t * pNew;
+	int i, nRegCount, iEntry;
+	Aig_Obj_t * pObjSavePi = NULL;
+	Aig_Obj_t *pObjSavedLi = NULL, *pObjSavedLo = NULL;
+	Aig_Obj_t *pObj, *pMatch;
+	Aig_Obj_t *pObjSavedLoAndEquality, *pObjSaveOrSaved = NULL, *pObjSaveAndNotSaved = NULL;
+	Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver;
+	Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc;
+	Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate;
+	Aig_Obj_t *pObjSafetyPropertyOutput = NULL;
+	Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety;
+	char *nodeName;
+	int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, liveLatch = 0, fairLatch = 0;//, piVecIndex = 0;
+	
+	vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
+	vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
+
+	vecLos = Vec_PtrAlloc( Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
+	vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
+
+	//****************************************************************
+	// Step1: create the new manager
+	// Note: The new manager is created with "2 * Aig_ManObjNumMax(p)"
+	// nodes, but this selection is arbitrary - need to be justified
+	//****************************************************************
+	pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) );
+	pNew->pName = (char *)malloc( strlen( pNtk->pName ) + strlen("_l2s") + 1 );
+	sprintf(pNew->pName, "%s_%s", pNtk->pName, "l2s");
+    pNew->pSpec = NULL;
+    
+	//****************************************************************
+	// Step 2: map constant nodes
+	//****************************************************************
+    pObj = Aig_ManConst1( p );
+    pObj->pData = Aig_ManConst1( pNew );
+
+	//****************************************************************
+    // Step 3: create true PIs
+	//****************************************************************
+    Saig_ManForEachPi( p, pObj, i )
+	{
+		piCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNew);
+		Vec_PtrPush( vecPis, pObj->pData );
+		nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) ));
+		Vec_PtrPush( vecPiNames, nodeName );
+	}
+
+	//****************************************************************
+	// Step 4: create the special Pi corresponding to SAVE
+	//****************************************************************
+	if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+	{
+		pObjSavePi = Aig_ObjCreateCi( pNew );
+		nodeName = "SAVE_BIERE",
+		Vec_PtrPush( vecPiNames, nodeName );
+	}
+		
+	//****************************************************************
+	// Step 5: create register outputs
+	//****************************************************************
+    Saig_ManForEachLo( p, pObj, i )
+	{
+		loCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNew);
+		Vec_PtrPush( vecLos, pObj->pData );
+		nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ));
+		Vec_PtrPush( vecLoNames, nodeName );
+    }
+
+	//****************************************************************
+	// Step 6: create "saved" register output
+	//****************************************************************
+	if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+	{
+		loCreated++;
+		pObjSavedLo = Aig_ObjCreateCi( pNew );
+		Vec_PtrPush( vecLos, pObjSavedLo );
+		nodeName = "SAVED_LO";
+		Vec_PtrPush( vecLoNames, nodeName );
+	}
+
+	//****************************************************************
+	// Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi
+	//****************************************************************
+	if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+	{
+		pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo );
+		pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) );
+	}
+
+	//********************************************************************
+	// Step 8: create internal nodes
+	//********************************************************************
+    Aig_ManForEachNode( p, pObj, i )
+	{
+		pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+	}
+
+	
+	//********************************************************************
+	// Step 8.x : create PO for each safety assertions
+	// NOTE : Here the output is purposely inverted as it will be thrown to 
+	// dprove
+	//********************************************************************
+	if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+	{
+		if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 )
+		{
+			pObjAndAcc = Aig_ManConst1( pNew );
+			Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+			{
+				pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+				pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+			}
+			Aig_ObjCreateCo( pNew, Aig_Not(pObjAndAcc) );
+		}
+		else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 )
+		{
+			pObjAndAcc = Aig_ManConst1( pNew );
+			Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+			{
+				pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+				pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+			}
+			collectiveAssertSafety = pObjAndAcc;
+
+			pObjAndAcc = Aig_ManConst1( pNew );
+			Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i )
+			{
+				pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+				pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+			}
+			collectiveAssumeSafety = pObjAndAcc;
+			Aig_ObjCreateCo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) );
+		}
+		else
+		{
+			printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n");
+			Aig_ObjCreateCo( pNew, Aig_Not( Aig_ManConst1(pNew) ) );
+		}
+	}
+
+	//********************************************************************
+	// Step 9: create the safety property output gate for the liveness properties
+	// discuss with Sat/Alan for an alternative implementation
+	//********************************************************************
+	if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+	{
+		pObjSafetyPropertyOutput = Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData );
+	}
+
+	// create register inputs for the original registers
+	nRegCount = 0;
+	
+	Saig_ManForEachLo( p, pObj, i )
+	{
+		pMatch = Saig_ObjLoToLi( p, pObj );
+		Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) );
+		nRegCount++;
+		liCopied++;
+	}
+
+	// create register input corresponding to the register "saved"
+	if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+	{
+		#ifndef DUPLICATE_CKT_DEBUG
+			pObjSavedLi = Aig_ObjCreateCo( pNew, pObjSaveOrSaved );
+			nRegCount++;
+			liCreated++;
+
+			//Changed on October 13, 2009
+			//pObjAndAcc = NULL;
+			pObjAndAcc = Aig_ManConst1( pNew );
+
+	// create the family of shadow registers, then create the cascade of Xnor and And gates for the comparator 
+			//Saig_ManForEachLo( p, pObj, i )
+			Saig_ManForEachLo( p, pObj, i )
+			{
+				printf("Flop[%d] = %s\n", i, Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) );
+			}
+			Vec_IntForEachEntry( vFlops, iEntry, i )
+			{
+				pObjShadowLo = Aig_ObjCreateCi( pNew );
+				pObj = Aig_ManLo( p, iEntry );
+
+				#ifdef PROPAGATE_NAMES
+					Vec_PtrPush( vecLos, pObjShadowLo );
+					nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + iEntry ) ) ) + 10 );
+					sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + iEntry ) ), "SHADOW" );
+					printf("Flop copied [%d] = %s\n", iEntry, nodeName );
+					Vec_PtrPush( vecLoNames, nodeName );
+				#endif
+
+				pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
+				pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver );
+				nRegCount++;
+				loCreated++; liCreated++;
+		
+				pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
+				pObjXnor = Aig_Not( pObjXor );
+				
+				pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc );
+			}
+
+			// create the AND gate whose output will be the signal "looped"
+			pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc );
+
+			// create the master AND gate and corresponding AND and OR logic for the liveness properties
+			pObjAndAcc = Aig_ManConst1( pNew );
+			if( vLive == NULL || Vec_PtrSize( vLive ) == 0 )
+			{
+				printf("Circuit without any liveness property\n");
+			}
+			else
+			{
+				Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i )
+				{
+					liveLatch++;
+					pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+					pObjShadowLo = Aig_ObjCreateCi( pNew );
+
+					#ifdef PROPAGATE_NAMES
+						Vec_PtrPush( vecLos, pObjShadowLo );
+						nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 );
+						sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" );
+						Vec_PtrPush( vecLoNames, nodeName );
+					#endif
+
+					pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
+					pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver );
+					nRegCount++;
+					loCreated++; liCreated++;
+			
+					pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc );
+				}
+			}
+
+			pObjLive = pObjAndAcc;
+				
+			pObjAndAcc = Aig_ManConst1( pNew );
+			if( vFair == NULL || Vec_PtrSize( vFair ) == 0 )
+				printf("Circuit without any fairness property\n");
+			else
+			{
+				Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i )
+				{
+					fairLatch++;
+					pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+					pObjShadowLo = Aig_ObjCreateCi( pNew );
+
+					#ifdef PROPAGATE_NAMES
+						Vec_PtrPush( vecLos, pObjShadowLo );
+						nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 );
+						sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "FAIRNESS" );
+						Vec_PtrPush( vecLoNames, nodeName );
+					#endif
+
+					pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
+					pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver );
+					nRegCount++;
+					loCreated++; liCreated++;
+			
+					pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc );
+				}
+			}
+
+			pObjFair = pObjAndAcc;
+				
+			//pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) );
+			//Following is the actual Biere translation
+			pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) );
+
+			Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate );
+		#endif
+	}
+
+	Aig_ManSetRegNum( pNew, nRegCount );
+
+	Aig_ManCiCleanupBiere( pNew );
+	Aig_ManCoCleanupBiere( pNew );
+	
+	Aig_ManCleanup( pNew );
+	
+	assert( Aig_ManCheck( pNew ) );
+	
+	if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+	{
+			assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vCos, Saig_ManPoNum(pNew)+Aig_ObjCioId(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi);
+			assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) );
+			assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + liveLatch + fairLatch );
+	}
+
+	return pNew;
+}
+
+
+
+Aig_Man_t * LivenessToSafetyTransformationOneStepLoop( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, 
+													  Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety )
+{
+	Aig_Man_t * pNew;
+	int i, nRegCount;
+	Aig_Obj_t * pObjSavePi = NULL;
+	Aig_Obj_t *pObj, *pMatch;
+	Aig_Obj_t *pObjSavedLoAndEquality;
+	Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc, *pObjAndAccDummy;
+	Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate;
+	Aig_Obj_t *pObjSafetyPropertyOutput = NULL;
+	Aig_Obj_t *pDriverImage;
+	Aig_Obj_t *pObjCorrespondingLi;
+	Aig_Obj_t *pArgument;
+	Aig_Obj_t *collectiveAssertSafety, *collectiveAssumeSafety;
+
+	char *nodeName;
+	int piCopied = 0, liCopied = 0, loCopied = 0;//, liCreated = 0, loCreated = 0, piVecIndex = 0;
+
+	if( Aig_ManRegNum( p ) == 0 )
+	{
+		printf("The input AIG contains no register, returning the original AIG as it is\n");
+		return p;
+	}
+
+	vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
+	vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
+
+	vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
+	vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
+
+	//****************************************************************
+	// Step1: create the new manager
+	// Note: The new manager is created with "2 * Aig_ManObjNumMax(p)"
+	// nodes, but this selection is arbitrary - need to be justified
+	//****************************************************************
+	pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) );
+	pNew->pName = Abc_UtilStrsav( "live2safe" );
+    pNew->pSpec = NULL;
+    
+	//****************************************************************
+	// Step 2: map constant nodes
+	//****************************************************************
+    pObj = Aig_ManConst1( p );
+    pObj->pData = Aig_ManConst1( pNew );
+
+	//****************************************************************
+    // Step 3: create true PIs
+	//****************************************************************
+    Saig_ManForEachPi( p, pObj, i )
+	{
+		piCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNew);
+		Vec_PtrPush( vecPis, pObj->pData );
+		nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) ));
+		Vec_PtrPush( vecPiNames, nodeName );
+	}
+
+	//****************************************************************
+	// Step 4: create the special Pi corresponding to SAVE
+	//****************************************************************
+	if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE )
+	{
+		pObjSavePi = Aig_ObjCreateCi( pNew );
+		nodeName = "SAVE_BIERE",
+		Vec_PtrPush( vecPiNames, nodeName );
+	}
+			
+	//****************************************************************
+	// Step 5: create register outputs
+	//****************************************************************
+    Saig_ManForEachLo( p, pObj, i )
+    {
+		loCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNew);
+		Vec_PtrPush( vecLos, pObj->pData );
+		nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ));
+		Vec_PtrPush( vecLoNames, nodeName );
+    }
+
+	//****************************************************************
+	// Step 6: create "saved" register output
+	//****************************************************************
+
+#if 0
+	loCreated++;
+	pObjSavedLo = Aig_ObjCreateCi( pNew );
+	Vec_PtrPush( vecLos, pObjSavedLo );
+	nodeName = "SAVED_LO";
+	Vec_PtrPush( vecLoNames, nodeName );
+#endif
+
+	//****************************************************************
+	// Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi
+	//****************************************************************
+#if 0
+	pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo );
+	pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) );
+#endif
+
+	//********************************************************************
+	// Step 8: create internal nodes
+	//********************************************************************
+    Aig_ManForEachNode( p, pObj, i )
+	{
+		pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+	}
+
+#if 0
+	//********************************************************************
+	// Step 8.x : create PO for each safety assertions
+	//********************************************************************
+	Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+	{
+		pObj->pData = Aig_ObjCreateCo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) );
+	}
+#endif
+
+	if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+	{
+		if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 )
+		{
+			pObjAndAcc = NULL;
+			Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+			{
+				//pObj->pData = Aig_ObjCreateCo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) );
+				pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+				if( pObjAndAcc == NULL )
+					pObjAndAcc = pArgument;
+				else
+				{
+					pObjAndAccDummy = pObjAndAcc;
+					pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy );
+				}
+			}
+			Aig_ObjCreateCo( pNew, Aig_Not(pObjAndAcc) );
+		}
+		else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 )
+		{
+			pObjAndAcc = NULL;
+			Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+			{
+				//pObj->pData = Aig_ObjCreateCo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) );
+				pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+				if( pObjAndAcc == NULL )
+					pObjAndAcc = pArgument;
+				else
+				{
+					pObjAndAccDummy = pObjAndAcc;
+					pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy );
+				}
+			}
+			collectiveAssertSafety = pObjAndAcc;
+			pObjAndAcc = NULL;
+			Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i )
+			{
+				//pObj->pData = Aig_ObjCreateCo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) );
+				pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+				if( pObjAndAcc == NULL )
+					pObjAndAcc = pArgument;
+				else
+				{
+					pObjAndAccDummy = pObjAndAcc;
+					pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy );
+				}
+			}
+			collectiveAssumeSafety = pObjAndAcc;
+			Aig_ObjCreateCo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) );
+		}
+		else
+			printf("No safety property is specified, hence no safety gate is created\n");
+	}
+
+	//********************************************************************
+	// Step 9: create the safety property output gate
+	// create the safety property output gate, this will be the sole true PO 
+	// of the whole circuit, discuss with Sat/Alan for an alternative implementation
+	//********************************************************************
+
+	if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE )
+	{
+		pObjSafetyPropertyOutput = Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData );
+	}
+
+	// create register inputs for the original registers
+    nRegCount = 0;
+	
+	Saig_ManForEachLo( p, pObj, i )
+    {
+		pMatch = Saig_ObjLoToLi( p, pObj );
+        //Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pMatch) );
+		Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) );
+        nRegCount++;
+		liCopied++;
+    }
+
+#if 0
+	// create register input corresponding to the register "saved"
+	pObjSavedLi = Aig_ObjCreateCo( pNew, pObjSaveOrSaved );
+	nRegCount++;
+	liCreated++;7
+#endif
+
+	pObjAndAcc = NULL;
+
+	//****************************************************************************************************
+	//For detection of loop of length 1 we do not need any shadow register, we only need equality detector
+	//between Lo_j and Li_j and then a cascade of AND gates
+	//****************************************************************************************************
+
+	if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE )
+	{
+		Saig_ManForEachLo( p, pObj, i )
+		{
+			pObjCorrespondingLi = Saig_ObjLoToLi( p, pObj );
+		
+			pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData,  Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0( pObjCorrespondingLi )->pData, Aig_ObjFaninC0( pObjCorrespondingLi ) ) );
+			pObjXnor = Aig_Not( pObjXor );
+		
+			if( pObjAndAcc == NULL )
+				pObjAndAcc = pObjXnor;
+			else
+			{
+				pObjAndAccDummy = pObjAndAcc;
+				pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAccDummy );
+			}
+		}
+
+		// create the AND gate whose output will be the signal "looped"
+		pObjSavedLoAndEquality = Aig_And( pNew, pObjSavePi, pObjAndAcc );
+	
+		// create the master AND gate and corresponding AND and OR logic for the liveness properties
+		pObjAndAcc = NULL;
+		if( vLive == NULL || Vec_PtrSize( vLive ) == 0 )
+			printf("Circuit without any liveness property\n");
+		else
+		{
+			Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i )
+			{
+				pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+				if( pObjAndAcc == NULL )
+					pObjAndAcc = pDriverImage;
+				else
+				{
+					pObjAndAccDummy = pObjAndAcc;
+					pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy );
+				}
+			}
+		}
+
+		if( pObjAndAcc != NULL )
+			pObjLive = pObjAndAcc;
+		else
+			pObjLive = Aig_ManConst1( pNew );
+	
+		// create the master AND gate and corresponding AND and OR logic for the fairness properties
+		pObjAndAcc = NULL;
+		if( vFair == NULL || Vec_PtrSize( vFair ) == 0 )
+			printf("Circuit without any fairness property\n");
+		else
+		{
+			Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i )
+			{
+				pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+				if( pObjAndAcc == NULL )
+					pObjAndAcc = pDriverImage;
+				else
+				{
+					pObjAndAccDummy = pObjAndAcc;
+					pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy );
+				}
+			}
+		}
+
+		if( pObjAndAcc != NULL )
+			pObjFair = pObjAndAcc;
+		else
+			pObjFair = Aig_ManConst1( pNew );
+	
+		pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) );
+	
+		Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate );
+	}
+
+	Aig_ManSetRegNum( pNew, nRegCount );
+
+	//printf("\nSaig_ManPiNum = %d, Reg Num = %d, before everything, before Pi cleanup\n", Vec_PtrSize( pNew->vPis ), pNew->nRegs );
+
+	Aig_ManCiCleanupBiere( pNew );
+	Aig_ManCoCleanupBiere( pNew );
+
+	Aig_ManCleanup( pNew );
+	
+	assert( Aig_ManCheck( pNew ) );
+	
+	return pNew;
+}
+
+
+
+Vec_Ptr_t * populateLivenessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig )
+{
+	Abc_Obj_t * pNode;
+	int i, liveCounter = 0;
+	Vec_Ptr_t * vLive;
+
+	vLive = Vec_PtrAlloc( 100 );
+	Abc_NtkForEachPo( pNtk, pNode, i )
+		//if( strstr( Abc_ObjName( pNode ), "assert_fair") != NULL )
+		if( nodeName_starts_with( pNode, "assert_fair" ) )
+		{
+			Vec_PtrPush( vLive, Aig_ManCo( pAig, i ) );
+			liveCounter++;
+		}
+	printf("Number of liveness property found = %d\n", liveCounter);
+	return vLive;
+}
+
+Vec_Ptr_t * populateFairnessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig )
+{
+	Abc_Obj_t * pNode;
+	int i, fairCounter = 0;
+	Vec_Ptr_t * vFair;
+
+	vFair = Vec_PtrAlloc( 100 );
+	Abc_NtkForEachPo( pNtk, pNode, i )
+		//if( strstr( Abc_ObjName( pNode ), "assume_fair") != NULL )
+		if( nodeName_starts_with( pNode, "assume_fair" ) )
+		{
+			Vec_PtrPush( vFair, Aig_ManCo( pAig, i ) );
+			fairCounter++;
+		}
+	printf("Number of fairness property found = %d\n", fairCounter);
+	return vFair;
+}
+
+Vec_Ptr_t * populateSafetyAssertionVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig )
+{
+	Abc_Obj_t * pNode;
+	int i, assertSafetyCounter = 0;
+	Vec_Ptr_t * vAssertSafety;
+
+	vAssertSafety = Vec_PtrAlloc( 100 );
+	Abc_NtkForEachPo( pNtk, pNode, i )
+		//if( strstr( Abc_ObjName( pNode ), "Assert") != NULL )
+		if( nodeName_starts_with( pNode, "assert_safety" ) || nodeName_starts_with( pNode, "Assert" ))
+		{
+			Vec_PtrPush( vAssertSafety, Aig_ManCo( pAig, i ) );
+			assertSafetyCounter++;
+		}
+	printf("Number of safety property found = %d\n", assertSafetyCounter);
+	return vAssertSafety;
+}
+
+Vec_Ptr_t * populateSafetyAssumptionVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig )
+{
+	Abc_Obj_t * pNode;
+	int i, assumeSafetyCounter = 0;
+	Vec_Ptr_t * vAssumeSafety;
+
+	vAssumeSafety = Vec_PtrAlloc( 100 );
+	Abc_NtkForEachPo( pNtk, pNode, i )
+		//if( strstr( Abc_ObjName( pNode ), "Assert") != NULL )
+		if( nodeName_starts_with( pNode, "assume_safety" ) || nodeName_starts_with( pNode, "Assume" ))
+		{
+			Vec_PtrPush( vAssumeSafety, Aig_ManCo( pAig, i ) );
+			assumeSafetyCounter++;
+		}
+	printf("Number of assume_safety property found = %d\n", assumeSafetyCounter);
+	return vAssumeSafety;
+}
+
+void updateNewNetworkNameManager( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, Vec_Ptr_t *vPiNames, Vec_Ptr_t *vLoNames )
+{
+	Aig_Obj_t *pObj;
+	Abc_Obj_t *pNode;
+	int i, ntkObjId;
+
+	pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum( pNtk ) );
+
+	if( vPiNames )
+	{
+		Saig_ManForEachPi( pAig, pObj, i )
+		{
+			ntkObjId = Abc_NtkCi( pNtk, i )->Id;
+			//printf("Pi %d, Saved Name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vPiNames, i), NULL ), ntkObjId);  
+			Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vPiNames, i), NULL );
+		}
+	}
+	if( vLoNames )
+	{
+		Saig_ManForEachLo( pAig, pObj, i )
+		{
+			ntkObjId = Abc_NtkCi( pNtk, Saig_ManPiNum( pAig ) + i )->Id;
+			//printf("Lo %d, Saved name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vLoNames, i), NULL ), ntkObjId);  
+			Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vLoNames, i), NULL );
+		}
+	}
+
+	Abc_NtkForEachPo(pNtk, pNode, i)
+	{
+		Abc_ObjAssignName(pNode, "assert_safety_", Abc_ObjName(pNode) );
+	}
+
+    // assign latch input names
+	Abc_NtkForEachLatch(pNtk, pNode, i)
+        if ( Nm_ManFindNameById(pNtk->pManName, Abc_ObjFanin0(pNode)->Id) == NULL )
+            Abc_ObjAssignName( Abc_ObjFanin0(pNode), Abc_ObjName(Abc_ObjFanin0(pNode)), NULL );
+}
+
+
+int Abc_CommandAbcLivenessToSafety( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+	FILE * pOut, * pErr;
+    Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld;
+	Aig_Man_t * pAig, *pAigNew = NULL;
+	int c;
+	Vec_Ptr_t * vLive, * vFair, *vAssertSafety, *vAssumeSafety;
+	int directive = -1;
+		        
+	pNtk = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+	if( argc == 1 )
+	{
+		assert( directive == -1 );
+		directive = FULL_BIERE_MODE;
+	}
+	else
+	{
+		Extra_UtilGetoptReset();
+		while ( ( c = Extra_UtilGetopt( argc, argv, "1slh" ) ) != EOF )
+		{
+			switch( c )
+			{
+			case '1': 
+				if( directive == -1 )
+					directive = FULL_BIERE_ONE_LOOP_MODE;
+				else
+				{
+					assert( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE || directive == IGNORE_SAFETY_KEEP_LIVENESS_MODE );
+					if( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+						directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+					else
+						directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE;
+				}
+				break;
+			case 's':
+				if( directive == -1 )
+					directive = IGNORE_SAFETY_KEEP_LIVENESS_MODE;
+				else
+				{
+					if( directive != FULL_BIERE_ONE_LOOP_MODE )
+						goto usage;
+					assert(directive == FULL_BIERE_ONE_LOOP_MODE);
+					directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE;
+				}
+				break;
+			case 'l':
+				if( directive == -1 )
+					directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+				else
+				{
+					if( directive != FULL_BIERE_ONE_LOOP_MODE )
+						goto usage;
+					assert(directive == FULL_BIERE_ONE_LOOP_MODE);
+					directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+				}
+				break;
+			case 'h':
+				goto usage;
+			default:
+				goto usage;
+			}
+		}
+	}
+
+	if ( pNtk == NULL )
+	{
+		fprintf( pErr, "Empty network.\n" );
+		return 1;
+	}
+	if( !Abc_NtkIsStrash( pNtk ) )
+	{
+		printf("The input network was not strashed, strashing....\n");
+		pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+		pNtkOld = pNtkTemp;
+		pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
+		vLive = populateLivenessVector( pNtk, pAig );
+		vFair = populateFairnessVector( pNtk, pAig );
+		vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+		vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+	}
+	else
+	{
+		pAig = Abc_NtkToDar( pNtk, 0, 1 );
+		pNtkOld = pNtk;
+		vLive = populateLivenessVector( pNtk, pAig );
+		vFair = populateFairnessVector( pNtk, pAig );
+		vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+		vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+	}
+
+	switch( directive )
+	{
+	case FULL_BIERE_MODE:
+		//if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 )
+		//{
+		//	printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n");
+		//	return 1;
+		//}
+		//else
+		//{
+			pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n");
+			break;
+		//}
+	case FULL_BIERE_ONE_LOOP_MODE:
+		//if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 )
+		//{
+		//	printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n");
+		//	return 1;
+		//}
+		//else
+		//{
+			pAigNew = LivenessToSafetyTransformationOneStepLoop( FULL_BIERE_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n");
+			break;
+		//}
+	case IGNORE_LIVENESS_KEEP_SAFETY_MODE:
+		//if( Vec_PtrSize(vAssertSafety) == 0 )
+		//{	
+		//	printf("Input circuit has NO safety property, original network is not disturbed\n");
+		//	return 1;
+		//}
+		//else
+		//{
+			pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("A new circuit is produced with\n\t1 PO - only for safety property; liveness properties are ignored, if any.\n\tno additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n");
+			break;
+		//}
+	case IGNORE_SAFETY_KEEP_LIVENESS_MODE:
+		//if( Vec_PtrSize(vLive) == 0 )
+		//{	
+		//	printf("Input circuit has NO liveness property, original network is not disturbed\n");
+		//	return 1;
+		//}
+		//else
+		//{
+			pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("A new circuit is produced with\n\t1 PO - only for liveness property; safety properties are ignored, if any.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n");
+			break;
+		//}
+	case IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE:
+		//if( Vec_PtrSize(vLive) == 0 )
+		//{
+		//	printf("Input circuit has NO liveness property, original network is not disturbed\n");
+		//	return 1;
+		//}
+		//else
+		//{
+			pAigNew = LivenessToSafetyTransformationOneStepLoop( IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nShadow registers are not created\n");
+			break;
+		//}
+	}
+
+#if 0
+	if( argc == 1 )
+	{
+		pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+		if( Aig_ManRegNum(pAigNew) != 0 )
+			printf("New circuit is produced considering all safety, liveness and fairness outputs.\nBiere's logic is created\n");
+	}
+	else 
+	{
+		Extra_UtilGetoptReset();
+		c = Extra_UtilGetopt( argc, argv, "1lsh" );
+		if( c == '1' )
+		{
+			if ( pNtk == NULL )
+			{
+				fprintf( pErr, "Empty network.\n" );
+				return 1;
+			}
+			if( !Abc_NtkIsStrash( pNtk ) )
+			{
+				printf("The input network was not strashed, strashing....\n");
+				pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+				pNtkOld = pNtkTemp;
+				pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
+				vLive = populateLivenessVector( pNtk, pAig );
+				vFair = populateFairnessVector( pNtk, pAig );
+				vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+				vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+			}
+			else
+			{
+				pAig = Abc_NtkToDar( pNtk, 0, 1 );
+				pNtkOld = pNtk;
+				vLive = populateLivenessVector( pNtk, pAig );
+				vFair = populateFairnessVector( pNtk, pAig );
+				vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+				vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+			}
+			pAigNew = LivenessToSafetyTransformationOneStepLoop( pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+		}
+		else if( c == 'l' )
+		{
+			if ( pNtk == NULL )
+			{
+				fprintf( pErr, "Empty network.\n" );
+				return 1;
+			}
+			if( !Abc_NtkIsStrash( pNtk ) )
+			{
+				printf("The input network was not strashed, strashing....\n");
+				pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+				pNtkOld = pNtkTemp;
+				pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
+				vLive = populateLivenessVector( pNtk, pAig );
+				vFair = populateFairnessVector( pNtk, pAig );
+				vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+				vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+			}
+			else
+			{
+				pAig = Abc_NtkToDar( pNtk, 0, 1 );
+				pNtkOld = pNtk;
+				vLive = populateLivenessVector( pNtk, pAig );
+				vFair = populateFairnessVector( pNtk, pAig );
+				vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+				vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+			}
+			pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("New circuit is produced ignoring liveness outputs!\nOnly safety outputs are kept.\nBiere's logic is not created\n");
+		}
+		else if( c == 's' )
+		{
+			if ( pNtk == NULL )
+			{
+				fprintf( pErr, "Empty network.\n" );
+				return 1;
+			}
+			
+			if( !Abc_NtkIsStrash( pNtk ) )
+			{
+				printf("The input network was not strashed, strashing....\n");
+				pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+				pNtkOld = pNtkTemp;
+				pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
+				vLive = populateLivenessVector( pNtk, pAig );
+				vFair = populateFairnessVector( pNtk, pAig );
+				vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+				vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+			}
+			else
+			{
+				pAig = Abc_NtkToDar( pNtk, 0, 1 );
+				pNtkOld = pNtk;
+				vLive = populateLivenessVector( pNtk, pAig );
+				vFair = populateFairnessVector( pNtk, pAig );
+				vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+				vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+			}
+			pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nBiere's logic is created\n");
+		}
+		else if( c == 'h' )
+			goto usage;
+		else
+			goto usage;
+	}
+#endif
+	
+#if 0
+	Aig_ManPrintStats( pAigNew );
+	printf("\nDetail statistics*************************************\n");
+	printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAigNew ));
+	printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAigNew ));
+	printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAigNew ) - Saig_ManPiNum( pAigNew ));
+	printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAigNew ) - Saig_ManPoNum( pAigNew ));
+	printf("Numer of registers = %d\n", Saig_ManRegNum( pAigNew ) );
+	printf("\n*******************************************************\n");
+#endif
+
+	pNtkNew = Abc_NtkFromAigPhase( pAigNew );
+	pNtkNew->pName = Abc_UtilStrsav( pAigNew->pName );
+	
+	if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" );
+	
+	updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames, vecLoNames );
+	Abc_FrameSetCurrentNetwork( pAbc, pNtkNew );
+
+#if 0
+#ifndef DUPLICATE_CKT_DEBUG
+	Saig_ManForEachPi( pAigNew, pObj, i )
+		assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 );
+		//printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) );
+
+	Saig_ManForEachLo( pAigNew, pObj, i )
+		assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 );
+#endif	
+#endif
+		
+	return 0;
+
+usage:
+    fprintf( stdout, "usage: l2s [-1lsh]\n" );
+    fprintf( stdout, "\t         performs Armin Biere's live-to-safe transformation\n" );
+	fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n");
+	fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n");
+    fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n");
+	fprintf( stdout, "\t-h : print command usage\n");
+    return 1;
+}
+
+Vec_Int_t * prepareFlopVector( Aig_Man_t * pAig, int vectorLength )
+{
+	Vec_Int_t *vFlops;
+	int i;
+
+	vFlops = Vec_IntAlloc( vectorLength );
+
+	for( i=0; i<vectorLength; i++ )
+		Vec_IntPush( vFlops, i );
+
+#if 0
+	Vec_IntPush( vFlops, 19 );
+	Vec_IntPush( vFlops, 20 );
+	Vec_IntPush( vFlops, 23 );
+	Vec_IntPush( vFlops, 24 );
+	//Vec_IntPush( vFlops, 2 );
+	//Vec_IntPush( vFlops, 3 );
+	//Vec_IntPush( vFlops, 4 );
+	//Vec_IntPush( vFlops, 5 );
+	//Vec_IntPush( vFlops, 8 );
+	//Vec_IntPush( vFlops, 9 );
+	//Vec_IntPush( vFlops, 10 );
+	//Vec_IntPush( vFlops, 11 );
+	//Vec_IntPush( vFlops, 0 );
+	//Vec_IntPush( vFlops, 0 );
+#endif
+
+	return vFlops;
+}
+
+int Abc_CommandAbcLivenessToSafetyAbstraction( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+	FILE * pOut, * pErr;
+    Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld;
+	Aig_Man_t * pAig, *pAigNew = NULL;
+	int c;
+	Vec_Ptr_t * vLive, * vFair, *vAssertSafety, *vAssumeSafety;
+	int directive = -1;
+	Vec_Int_t * vFlops;
+		        
+	pNtk = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+	if( argc == 1 )
+	{
+		assert( directive == -1 );
+		directive = FULL_BIERE_MODE;
+	}
+	else
+	{
+		Extra_UtilGetoptReset();
+		while ( ( c = Extra_UtilGetopt( argc, argv, "1slh" ) ) != EOF )
+		{
+			switch( c )
+			{
+			case '1': 
+				if( directive == -1 )
+					directive = FULL_BIERE_ONE_LOOP_MODE;
+				else
+				{
+					assert( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE || directive == IGNORE_SAFETY_KEEP_LIVENESS_MODE );
+					if( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+						directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+					else
+						directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE;
+				}
+				break;
+			case 's':
+				if( directive == -1 )
+					directive = IGNORE_SAFETY_KEEP_LIVENESS_MODE;
+				else
+				{
+					if( directive != FULL_BIERE_ONE_LOOP_MODE )
+						goto usage;
+					assert(directive == FULL_BIERE_ONE_LOOP_MODE);
+					directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE;
+				}
+				break;
+			case 'l':
+				if( directive == -1 )
+					directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+				else
+				{
+					if( directive != FULL_BIERE_ONE_LOOP_MODE )
+						goto usage;
+					assert(directive == FULL_BIERE_ONE_LOOP_MODE);
+					directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+				}
+				break;
+			case 'h':
+				goto usage;
+			default:
+				goto usage;
+			}
+		}
+	}
+
+	if ( pNtk == NULL )
+	{
+		fprintf( pErr, "Empty network.\n" );
+		return 1;
+	}
+	if( !Abc_NtkIsStrash( pNtk ) )
+	{
+		printf("The input network was not strashed, strashing....\n");
+		pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+		pNtkOld = pNtkTemp;
+		pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
+		vLive = populateLivenessVector( pNtk, pAig );
+		vFair = populateFairnessVector( pNtk, pAig );
+		vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+		vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+	}
+	else
+	{
+		pAig = Abc_NtkToDar( pNtk, 0, 1 );
+		pNtkOld = pNtk;
+		vLive = populateLivenessVector( pNtk, pAig );
+		vFair = populateFairnessVector( pNtk, pAig );
+		vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+		vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+	}
+
+	vFlops = prepareFlopVector( pAig, Aig_ManRegNum(pAig)%2 == 0? Aig_ManRegNum(pAig)/2 : (Aig_ManRegNum(pAig)-1)/2);
+
+	//vFlops = prepareFlopVector( pAig, 100 );
+
+	switch( directive )
+	{
+	case FULL_BIERE_MODE:
+		//if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 )
+		//{
+		//	printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n");
+		//	return 1;
+		//}
+		//else
+		//{
+			pAigNew = LivenessToSafetyTransformationAbs( FULL_BIERE_MODE, pNtk, pAig, vFlops, vLive, vFair, vAssertSafety, vAssumeSafety );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n");
+			break;
+		//}
+	case FULL_BIERE_ONE_LOOP_MODE:
+		//if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 )
+		//{
+		//	printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n");
+		//	return 1;
+		//}
+		//else
+		//{
+			pAigNew = LivenessToSafetyTransformationOneStepLoop( FULL_BIERE_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n");
+			break;
+		//}
+	case IGNORE_LIVENESS_KEEP_SAFETY_MODE:
+		//if( Vec_PtrSize(vAssertSafety) == 0 )
+		//{	
+		//	printf("Input circuit has NO safety property, original network is not disturbed\n");
+		//	return 1;
+		//}
+		//else
+		//{
+			pAigNew = LivenessToSafetyTransformationAbs( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vFlops, vLive, vFair, vAssertSafety, vAssumeSafety );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("A new circuit is produced with\n\t1 PO - only for safety property; liveness properties are ignored, if any.\n\tno additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n");
+			break;
+		//}
+	case IGNORE_SAFETY_KEEP_LIVENESS_MODE:
+		//if( Vec_PtrSize(vLive) == 0 )
+		//{	
+		//	printf("Input circuit has NO liveness property, original network is not disturbed\n");
+		//	return 1;
+		//}
+		//else
+		//{
+			pAigNew = LivenessToSafetyTransformationAbs( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vFlops, vLive, vFair, vAssertSafety, vAssumeSafety );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("A new circuit is produced with\n\t1 PO - only for liveness property; safety properties are ignored, if any.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n");
+			break;
+		//}
+	case IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE:
+		//if( Vec_PtrSize(vLive) == 0 )
+		//{
+		//	printf("Input circuit has NO liveness property, original network is not disturbed\n");
+		//	return 1;
+		//}
+		//else
+		//{
+			pAigNew = LivenessToSafetyTransformationOneStepLoop( IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nShadow registers are not created\n");
+			break;
+		//}
+	}
+
+	pNtkNew = Abc_NtkFromAigPhase( pAigNew );
+	pNtkNew->pName = Abc_UtilStrsav( pAigNew->pName );
+	
+	if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" );
+	
+	updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames,vecLoNames );
+	Abc_FrameSetCurrentNetwork( pAbc, pNtkNew );
+
+#if 0
+#ifndef DUPLICATE_CKT_DEBUG
+	Saig_ManForEachPi( pAigNew, pObj, i )
+		assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 );
+		//printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) );
+
+	Saig_ManForEachLo( pAigNew, pObj, i )
+		assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 );
+#endif	
+#endif
+		
+	return 0;
+
+usage:
+    fprintf( stdout, "usage: l2s [-1lsh]\n" );
+    fprintf( stdout, "\t         performs Armin Biere's live-to-safe transformation\n" );
+	fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n");
+	fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n");
+    fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n");
+	fprintf( stdout, "\t-h : print command usage\n");
+    return 1;
+}
+
+Aig_Man_t * LivenessToSafetyTransformationWithLTL( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, 
+										   Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety,
+										   int *numLtlProcessed, Vec_Ptr_t *ltlBuffer )
+{
+	Aig_Man_t * pNew;
+	int i, ii, iii, nRegCount;
+	Aig_Obj_t * pObjSavePi = NULL;
+	Aig_Obj_t *pObjSavedLo = NULL, *pObjSavedLi = NULL;
+	Aig_Obj_t *pObj, *pMatch;
+	Aig_Obj_t *pObjSaveOrSaved = NULL, *pObjSaveAndNotSaved = NULL, *pObjSavedLoAndEquality;
+	Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver;
+	Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc;
+	Aig_Obj_t *pObjLive, *pObjSafetyGate;
+	Aig_Obj_t *pObjSafetyPropertyOutput;
+	Aig_Obj_t *pObjOriginalSafetyPropertyOutput;
+	Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety;
+	Aig_Obj_t *pNegatedSafetyConjunction = NULL;
+	Aig_Obj_t *pObjSafetyAndLiveToSafety;
+	char *nodeName, *pFormula;
+	int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, liveLatch = 0;//, piVecIndex = 0, fairLatch = 0;
+	Vec_Ptr_t *vSignal, *vTopASTNodeArray = NULL;
+	ltlNode *pEnrtyGLOBALLY;
+	ltlNode *topNodeOfAST, *tempTopASTNode;
+	Vec_Vec_t *vAigGFMap;
+	Vec_Ptr_t *vSignalMemory, *vGFFlopMemory, *vPoForLtlProps = NULL;
+	Vec_Ptr_t *vecInputLtlFormulae;
+	
+	vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
+	vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
+
+	vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
+	vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
+
+	//****************************************************************
+	//step0: Parsing the LTL formula
+	//****************************************************************
+	//Vec_PtrForEachEntry( char *, pNtk->vLtlProperties, pFormula, i )
+	//	printf("\ninput LTL formula [%d] = %s\n", i, pFormula );
+
+
+#ifdef MULTIPLE_LTL_FORMULA
+
+
+	//***************************************************************************
+	//Reading input LTL formulae from Ntk data-structure and creating 
+	//AST for them, Steps involved: 
+	//		parsing -> AST creation -> well-formedness check -> signal name check
+	//***************************************************************************
+
+	//resetting numLtlProcessed
+	*numLtlProcessed = 0;
+	
+	if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+	{
+		//if( ltlBuffer )
+		vecInputLtlFormulae = ltlBuffer;
+		//vecInputLtlFormulae = pNtk->vLtlProperties;
+		if( vecInputLtlFormulae )
+		{
+			vTopASTNodeArray = Vec_PtrAlloc( Vec_PtrSize( vecInputLtlFormulae ) );
+			printf("\n");
+			Vec_PtrForEachEntry( char *, vecInputLtlFormulae, pFormula, i )
+			{
+				tempTopASTNode = parseFormulaCreateAST( pFormula );
+				//traverseAbstractSyntaxTree_postFix( tempTopASTNode );
+				if( tempTopASTNode )
+				{
+					printf("Formula %d: AST is created, ", i+1);
+					if( isWellFormed( tempTopASTNode ) )
+						printf("Well-formedness check PASSED, ");
+					else
+					{
+						printf("Well-formedness check FAILED!!\n");
+						printf("AST will be ignored for formula %d, no extra logic will be added for this formula\n", i+1 );
+						//do memory management to free the created AST
+						continue;
+					}
+					if( checkSignalNameExistence( pNtk, tempTopASTNode ) )
+						printf("Signal check PASSED\n");
+					else
+					{
+						printf("Signal check FAILED!!");
+						printf("AST will be ignored for formula %d, no extra logic will be added for this formula\n", i+1 );
+						//do memory management to free the created AST
+						continue;
+					}
+					Vec_PtrPush( vTopASTNodeArray, tempTopASTNode );
+					(*numLtlProcessed)++;
+				}
+				else
+					printf("\nNo AST has been created for formula %d, no extra logic will be added\n", i+1 );
+			}
+		}
+		printf("\n");
+		if( Vec_PtrSize( vTopASTNodeArray ) == 0 )
+		{
+			//printf("\nNo AST has been created for any formula; hence the circuit is left untouched\n");
+			printf("\nCurrently aborting, need to take care when Vec_PtrSize( vTopASTNodeArray ) == 0\n");
+			exit(0);
+		}
+	}
+
+		//****************************************************************
+		// Step1: create the new manager
+		// Note: The new manager is created with "2 * Aig_ManObjNumMax(p)"
+		// nodes, but this selection is arbitrary - need to be justified
+		//****************************************************************
+		pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) );
+		pNew->pName = (char *)malloc( strlen( pNtk->pName ) + strlen("_l3s") + 1 );
+		sprintf(pNew->pName, "%s_%s", pNtk->pName, "l3s");
+		pNew->pSpec = NULL;
+    
+		//****************************************************************
+		// Step 2: map constant nodes
+		//****************************************************************
+		pObj = Aig_ManConst1( p );
+		pObj->pData = Aig_ManConst1( pNew );
+
+		//****************************************************************
+		// Step 3: create true PIs
+		//****************************************************************
+		Saig_ManForEachPi( p, pObj, i )
+		{
+			piCopied++;
+			pObj->pData = Aig_ObjCreateCi(pNew);
+			Vec_PtrPush( vecPis, pObj->pData );
+			nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) ));
+			Vec_PtrPush( vecPiNames, nodeName );
+		}
+
+		//****************************************************************
+		// Step 4: create the special Pi corresponding to SAVE
+		//****************************************************************
+		if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+		{
+			pObjSavePi = Aig_ObjCreateCi( pNew );
+			nodeName = "SAVE_BIERE",
+			Vec_PtrPush( vecPiNames, nodeName );
+		}
+		
+		//****************************************************************
+		// Step 5: create register outputs
+		//****************************************************************
+		Saig_ManForEachLo( p, pObj, i )
+		{
+			loCopied++;
+			pObj->pData = Aig_ObjCreateCi(pNew);
+			Vec_PtrPush( vecLos, pObj->pData );
+			nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ));
+			Vec_PtrPush( vecLoNames, nodeName );
+		}
+
+		//****************************************************************
+		// Step 6: create "saved" register output
+		//****************************************************************
+		if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+		{
+			loCreated++;
+			pObjSavedLo = Aig_ObjCreateCi( pNew );
+			Vec_PtrPush( vecLos, pObjSavedLo );
+			nodeName = "SAVED_LO";
+			Vec_PtrPush( vecLoNames, nodeName );
+		}
+
+		//****************************************************************
+		// Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi
+		//****************************************************************
+		if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+		{
+			pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo );
+			pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) );
+		}
+
+		//********************************************************************
+		// Step 8: create internal nodes
+		//********************************************************************
+		Aig_ManForEachNode( p, pObj, i )
+		{
+			pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+		}
+
+		
+		//********************************************************************
+		// Step 8.x : create PO for each safety assertions
+		// NOTE : Here the output is purposely inverted as it will be thrown to 
+		// dprove
+		//********************************************************************
+		assert( pNegatedSafetyConjunction == NULL );
+		if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE)
+		{
+			if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 )
+			{
+				pObjAndAcc = Aig_ManConst1( pNew );
+				Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+				{
+					pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+					pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+				}
+				pNegatedSafetyConjunction = Aig_Not(pObjAndAcc);
+				if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+					pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_Not(pObjAndAcc) );
+			}
+			else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 )
+			{
+				pObjAndAcc = Aig_ManConst1( pNew );
+				Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+				{
+					pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+					pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+				}
+				collectiveAssertSafety = pObjAndAcc;
+
+				pObjAndAcc = Aig_ManConst1( pNew );
+				Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i )
+				{
+					pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+					pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+				}
+				collectiveAssumeSafety = pObjAndAcc;
+				pNegatedSafetyConjunction =  Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety );
+				if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+					pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) );
+			}
+			else
+			{
+				printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n");
+				pNegatedSafetyConjunction = Aig_Not( Aig_ManConst1(pNew) );
+				if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+					pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_Not( Aig_ManConst1(pNew) ) );
+			}
+		}
+		assert( pNegatedSafetyConjunction != NULL );
+
+		//********************************************************************
+		// Step 9: create the safety property output gate for the liveness properties
+		// discuss with Sat/Alan for an alternative implementation
+		//********************************************************************
+		if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+		{
+			vPoForLtlProps = Vec_PtrAlloc( Vec_PtrSize( vTopASTNodeArray ) );
+			if( Vec_PtrSize( vTopASTNodeArray ) )
+			{
+				//no effective AST for any input LTL property
+				//must do something graceful
+			}
+			for( i=0; i<Vec_PtrSize( vTopASTNodeArray ); i++ )
+			{
+				pObjSafetyPropertyOutput = Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData );
+				Vec_PtrPush( vPoForLtlProps, pObjSafetyPropertyOutput );
+			}
+		}
+
+		//*************************************************************************************
+		// Step 10: Placeholder PO's were created for Liveness property outputs in the
+		// last step. FYI, # of new liveness property outputs = # of LTL properties in the circuit
+		// It is time for creation of loop LI's and other stuff
+		// Now creating register inputs for the original flops
+		//*************************************************************************************
+		nRegCount = 0;
+		
+		Saig_ManForEachLo( p, pObj, i )
+		{
+			pMatch = Saig_ObjLoToLi( p, pObj );
+			Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) );
+			nRegCount++;
+			liCopied++;
+		}
+
+		//*************************************************************************************
+		// Step 11: create register input corresponding to the register "saved"
+		//*************************************************************************************
+		if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+		{
+			#ifndef DUPLICATE_CKT_DEBUG
+				pObjSavedLi = Aig_ObjCreateCo( pNew, pObjSaveOrSaved );
+				nRegCount++;
+				liCreated++;
+
+				pObjAndAcc = Aig_ManConst1( pNew );
+
+				//*************************************************************************************
+				// Step 11: create the family of shadow registers, then create the cascade of Xnor 
+				// and And gates for the comparator 
+				//*************************************************************************************
+				Saig_ManForEachLo( p, pObj, i )
+				{
+				//printf("\nKEMON RENDY = %s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i )) );
+				//top|route0_target0_queue_with_credit0_queue0
+				//top|route0_master0_queue2
+				//	if( strcmp(  Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[0]" ) == 0 
+				//			|| strcmp(  Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[1]" ) == 0 || strcmp(  Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[2]" ) == 0 )
+					{		
+						pObjShadowLo = Aig_ObjCreateCi( pNew );
+
+					#ifdef PROPAGATE_NAMES
+						Vec_PtrPush( vecLos, pObjShadowLo );
+						nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ) + 10 );
+						sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "SHADOW" );
+						
+						Vec_PtrPush( vecLoNames, nodeName );
+					#endif
+
+						pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
+						pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver );
+						nRegCount++;
+						loCreated++; liCreated++;
+			
+						pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
+						pObjXnor = Aig_Not( pObjXor );
+					
+						pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc );
+					}
+				}
+
+				// create the AND gate whose output will be the signal "looped"
+				pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc );
+
+				// create the master AND gate and corresponding AND and OR logic for the liveness properties
+				
+				//*************************************************************************************
+				// Step 11: logic for LTL properties:- (looped & ~theta) where theta is the input ltl 
+				// property
+				// Description of some data-structure:
+				//-------------------------------------------------------------------------------------
+				// Name          | Type            | Purpose
+				//-------------------------------------------------------------------------------------
+				// vSignalMemory | Vec_Ptr_t *     | A vector across all ASTs of the LTL properties
+				//				 |				   | It remembers if OR+Latch for GF node has already been
+				//				 |				   | created for a particular signal.
+				//               |                 |
+				// vGFFlopMemory | Vec_Ptr_t *     | A vector across all ASTs of the LTL properties
+				//				 |                 | remembers if OR+Latch of a GF node has already been created
+				//				 |                 |
+				// vSignal		 | Vec_Ptr_t *     | vector for each AST; contains pointers from GF nodes
+				//               |                 | to AIG signals
+				//				 |				   |
+				// vAigGFMap	 | Vec_Vec_t *     | vAigGFMap[ index ] = vector of GF nodes pointing to
+				//               |                 | the same AIG node; "index" is the index of that
+				//               |                 | AIG node in the vector vSignal
+				//*************************************************************************************
+				
+				vSignalMemory = Vec_PtrAlloc(10);
+				vGFFlopMemory = Vec_PtrAlloc(10);
+
+				Vec_PtrForEachEntry( ltlNode *, vTopASTNodeArray, topNodeOfAST, iii )
+				{
+									vSignal = Vec_PtrAlloc( 10 );
+									vAigGFMap = Vec_VecAlloc( 10 );
+									
+									//*************************************************************************************
+									//Step 11a: for the current AST, find out the leaf level Boolean signal pointers from 
+									// the NEW aig.
+									//*************************************************************************************
+									populateBoolWithAigNodePtr( pNtk, p, pNew, topNodeOfAST );
+									assert( checkAllBoolHaveAIGPointer( topNodeOfAST ) );
+
+									//*************************************************************************************
+									//Step 11b: for each GF node, compute the pointer in AIG that it should point to
+									// In particular, if the subtree below GF is some Boolean crown (including the case
+									// of simple negation, create new logic and populate the AIG pointer in GF node
+									// accordingly
+									//*************************************************************************************
+									populateAigPointerUnitGF( pNew, topNodeOfAST, vSignal, vAigGFMap );
+									
+									//*************************************************************************************
+									//Step 11c: everything below GF are computed. Now, it is time to create logic for individual 
+									// GF nodes (i.e. the OR gate and the latch and the Boolean crown of the AST
+									//*************************************************************************************
+									Vec_PtrForEachEntry( Aig_Obj_t *, vSignal, pObj, i )
+									{
+										//*********************************************************
+										// Step 11c.1: if the OR+Latch of the particular signal is
+										// not already created, create it. It may have already been 
+										// created from another property, so check it before creation
+										//*********************************************************
+										if( Vec_PtrFind( vSignalMemory, pObj ) == -1 )
+										{
+											liveLatch++;
+
+											pDriverImage = pObj;
+											pObjShadowLo = Aig_ObjCreateCi( pNew );
+											pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
+											pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver );
+
+											nRegCount++;
+											loCreated++; liCreated++;
+
+											Vec_PtrPush( vSignalMemory, pObj );
+											Vec_PtrPush( vGFFlopMemory, pObjShadowLo );
+
+											#if 1
+											#ifdef PROPAGATE_NAMES
+												Vec_PtrPush( vecLos, pObjShadowLo );
+												//nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 );
+												//sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" );
+												nodeName = (char *)malloc( 20 );
+												sprintf( nodeName, "n%d__%s", Aig_ObjId(pObjShadowLo), "GF_flop" );
+												Vec_PtrPush( vecLoNames, nodeName );
+											#endif
+											#endif
+										}
+										else
+											pObjShadowLo = (Aig_Obj_t *)Vec_PtrEntry( vGFFlopMemory, Vec_PtrFind( vSignalMemory, pObj ) );
+																				
+										Vec_VecForEachEntryLevel( ltlNode *, vAigGFMap, pEnrtyGLOBALLY, ii, i )
+											setAIGNodePtrOfGloballyNode( pEnrtyGLOBALLY, pObjShadowLo);
+											
+
+										//#ifdef PROPAGATE_NAMES
+										//	Vec_PtrPush( vecLos, pObjShadowLo );
+										//	nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 );
+										//	sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" );
+										//	Vec_PtrPush( vecLoNames, nodeName );
+										//#endif
+										
+									}
+									
+									//*********************************************************
+									//Step 11c.2: creating the Boolean crown
+									//*********************************************************
+									buildLogicFromLTLNode( pNew, topNodeOfAST );
+
+									//*********************************************************
+									//Step 11c.3: creating logic for (looped & ~theta) and patching
+									// it with the proper PO
+									//Note: if ALLOW_SAFETY_PROPERTIES is defined then the final AND
+									//gate is a conjunction of safety & liveness, i.e. SAFETY & (looped => theta)
+									//since ABC convention demands a NOT gate at the end, the property logic 
+									//becomes !( SAFETY & (looped => theta) ) = !SAFETY + (looped & !theta)
+									//*********************************************************
+									pObjLive = retriveAIGPointerFromLTLNode( topNodeOfAST );
+									pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_Not(pObjLive) );
+									#ifdef ALLOW_SAFETY_PROPERTIES
+										printf("liveness output is conjoined with safety assertions\n");
+										pObjSafetyAndLiveToSafety = Aig_Or( pNew, pObjSafetyGate, pNegatedSafetyConjunction );
+										pObjSafetyPropertyOutput = (Aig_Obj_t *)Vec_PtrEntry( vPoForLtlProps, iii );
+										Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyAndLiveToSafety );
+									#else
+										pObjSafetyPropertyOutput = Vec_PtrEntry( vPoForLtlProps, iii );
+										Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate );
+									#endif
+									//refreshing vSignal and vAigGFMap arrays
+									Vec_PtrFree( vSignal );
+									Vec_VecFree( vAigGFMap );
+				}
+								
+			#endif
+		}
+#endif
+
+	Aig_ManSetRegNum( pNew, nRegCount );
+
+	Aig_ManCiCleanupBiere( pNew );
+	Aig_ManCoCleanupBiere( pNew );
+	
+	Aig_ManCleanup( pNew );
+	
+	assert( Aig_ManCheck( pNew ) );
+	
+	if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+	{
+			assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vCos, Saig_ManPoNum(pNew)+Aig_ObjCioId(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi);
+			assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) );
+			//assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch );
+	}
+
+
+	return pNew;
+}
+
+int Abc_CommandAbcLivenessToSafetyWithLTL( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+	FILE * pOut, * pErr;
+    Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld;
+	Aig_Man_t * pAig, *pAigNew = NULL;
+	int c;
+	Vec_Ptr_t * vLive, * vFair, *vAssertSafety, *vAssumeSafety;
+	int directive = -1;
+//	char *ltfFormulaString = NULL;
+	int numOfLtlPropOutput;//, LTL_FLAG = 0;
+	Vec_Ptr_t *ltlBuffer;
+		        
+	pNtk = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+	if( argc == 1 )
+	{
+		assert( directive == -1 );
+		directive = FULL_BIERE_MODE;
+	}
+	else
+	{
+		Extra_UtilGetoptReset();
+		while ( ( c = Extra_UtilGetopt( argc, argv, "1slhf" ) ) != EOF )
+		{
+			switch( c )
+			{
+			case '1': 
+				if( directive == -1 )
+					directive = FULL_BIERE_ONE_LOOP_MODE;
+				else
+				{
+					assert( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE || directive == IGNORE_SAFETY_KEEP_LIVENESS_MODE );
+					if( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+						directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+					else
+						directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE;
+				}
+				break;
+			case 's':
+				if( directive == -1 )
+					directive = IGNORE_SAFETY_KEEP_LIVENESS_MODE;
+				else
+				{
+					if( directive != FULL_BIERE_ONE_LOOP_MODE )
+						goto usage;
+					assert(directive == FULL_BIERE_ONE_LOOP_MODE);
+					directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE;
+				}
+				break;
+			case 'l':
+				if( directive == -1 )
+					directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+				else
+				{
+					if( directive != FULL_BIERE_ONE_LOOP_MODE )
+						goto usage;
+					assert(directive == FULL_BIERE_ONE_LOOP_MODE);
+					directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+				}
+				break;
+			case 'f':
+				//assert( argc >= 3 );
+				//vecLtlFormula = Vec_PtrAlloc( argc - 2 );
+				//if( argc >= 3 )
+				//{
+				//	for( t=3; t<=argc; t++ )
+				//	{
+				//		printf("argv[%d] = %s\n", t-1, argv[t-1]);
+				//		Vec_PtrPush( vecLtlFormula, argv[t-1] );
+				//	}
+				//}
+				//printf("argv[argc] = %s\n", argv[argc-1]);
+				//ltfFormulaString = argv[2];
+				
+				//LTL_FLAG = 1;
+				printf("\nILLEGAL FLAG: aborting....\n");
+				exit(0);
+				break;
+			case 'h':
+				goto usage;
+			default:
+				goto usage;
+			}
+		}
+	}
+
+	if ( pNtk == NULL )
+	{
+		fprintf( pErr, "Empty network.\n" );
+		return 1;
+	}
+	if( !Abc_NtkIsStrash( pNtk ) )
+	{
+		printf("The input network was not strashed, strashing....\n");
+		pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+		pNtkOld = pNtkTemp;
+		pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
+		vLive = populateLivenessVector( pNtk, pAig );
+		vFair = populateFairnessVector( pNtk, pAig );
+		vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+		vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+	}
+	else
+	{
+		pAig = Abc_NtkToDar( pNtk, 0, 1 );
+		pNtkOld = pNtk;
+		vLive = populateLivenessVector( pNtk, pAig );
+		vFair = populateFairnessVector( pNtk, pAig );
+		vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+		vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+	}
+
+	if( pAbc->vLTLProperties_global != NULL )
+		ltlBuffer = pAbc->vLTLProperties_global;
+	else
+		ltlBuffer = NULL;
+
+	switch( directive )
+	{
+	case FULL_BIERE_MODE:
+			pAigNew = LivenessToSafetyTransformationWithLTL( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("A new circuit is produced with\n\t%d POs - one for safety and %d for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n", numOfLtlPropOutput+1, numOfLtlPropOutput);
+			break;
+		
+	case FULL_BIERE_ONE_LOOP_MODE:
+			pAigNew = LivenessToSafetyTransformationOneStepLoop( FULL_BIERE_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n");
+			break;
+		
+	case IGNORE_LIVENESS_KEEP_SAFETY_MODE:
+			pAigNew = LivenessToSafetyTransformationWithLTL( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer );
+			assert( numOfLtlPropOutput == 0 );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("A new circuit is produced with\n\t1 PO - only for safety property; liveness properties are ignored, if any.\n\tno additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n");
+			break;
+		
+	case IGNORE_SAFETY_KEEP_LIVENESS_MODE:
+			pAigNew = LivenessToSafetyTransformationWithLTL( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("A new circuit is produced with\n\t%d PO - only for liveness property; safety properties are ignored, if any.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n", numOfLtlPropOutput);
+			break;
+		
+	case IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE:
+			pAigNew = LivenessToSafetyTransformationOneStepLoop( IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nShadow registers are not created\n");
+			break;
+	}
+
+#if 0
+	if( argc == 1 )
+	{
+		pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+		if( Aig_ManRegNum(pAigNew) != 0 )
+			printf("New circuit is produced considering all safety, liveness and fairness outputs.\nBiere's logic is created\n");
+	}
+	else 
+	{
+		Extra_UtilGetoptReset();
+		c = Extra_UtilGetopt( argc, argv, "1lsh" );
+		if( c == '1' )
+		{
+			if ( pNtk == NULL )
+			{
+				fprintf( pErr, "Empty network.\n" );
+				return 1;
+			}
+			if( !Abc_NtkIsStrash( pNtk ) )
+			{
+				printf("The input network was not strashed, strashing....\n");
+				pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+				pNtkOld = pNtkTemp;
+				pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
+				vLive = populateLivenessVector( pNtk, pAig );
+				vFair = populateFairnessVector( pNtk, pAig );
+				vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+				vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+			}
+			else
+			{
+				pAig = Abc_NtkToDar( pNtk, 0, 1 );
+				pNtkOld = pNtk;
+				vLive = populateLivenessVector( pNtk, pAig );
+				vFair = populateFairnessVector( pNtk, pAig );
+				vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+				vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+			}
+			pAigNew = LivenessToSafetyTransformationOneStepLoop( pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+		}
+		else if( c == 'l' )
+		{
+			if ( pNtk == NULL )
+			{
+				fprintf( pErr, "Empty network.\n" );
+				return 1;
+			}
+			if( !Abc_NtkIsStrash( pNtk ) )
+			{
+				printf("The input network was not strashed, strashing....\n");
+				pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+				pNtkOld = pNtkTemp;
+				pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
+				vLive = populateLivenessVector( pNtk, pAig );
+				vFair = populateFairnessVector( pNtk, pAig );
+				vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+				vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+			}
+			else
+			{
+				pAig = Abc_NtkToDar( pNtk, 0, 1 );
+				pNtkOld = pNtk;
+				vLive = populateLivenessVector( pNtk, pAig );
+				vFair = populateFairnessVector( pNtk, pAig );
+				vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+				vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+			}
+			pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("New circuit is produced ignoring liveness outputs!\nOnly safety outputs are kept.\nBiere's logic is not created\n");
+		}
+		else if( c == 's' )
+		{
+			if ( pNtk == NULL )
+			{
+				fprintf( pErr, "Empty network.\n" );
+				return 1;
+			}
+			
+			if( !Abc_NtkIsStrash( pNtk ) )
+			{
+				printf("The input network was not strashed, strashing....\n");
+				pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+				pNtkOld = pNtkTemp;
+				pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
+				vLive = populateLivenessVector( pNtk, pAig );
+				vFair = populateFairnessVector( pNtk, pAig );
+				vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+				vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+			}
+			else
+			{
+				pAig = Abc_NtkToDar( pNtk, 0, 1 );
+				pNtkOld = pNtk;
+				vLive = populateLivenessVector( pNtk, pAig );
+				vFair = populateFairnessVector( pNtk, pAig );
+				vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+				vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+			}
+			pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+			if( Aig_ManRegNum(pAigNew) != 0 )
+				printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nBiere's logic is created\n");
+		}
+		else if( c == 'h' )
+			goto usage;
+		else
+			goto usage;
+	}
+#endif
+	
+#if 0
+	Aig_ManPrintStats( pAigNew );
+	printf("\nDetail statistics*************************************\n");
+	printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAigNew ));
+	printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAigNew ));
+	printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAigNew ) - Saig_ManPiNum( pAigNew ));
+	printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAigNew ) - Saig_ManPoNum( pAigNew ));
+	printf("Numer of registers = %d\n", Saig_ManRegNum( pAigNew ) );
+	printf("\n*******************************************************\n");
+#endif
+
+	pNtkNew = Abc_NtkFromAigPhase( pAigNew );
+	pNtkNew->pName = Abc_UtilStrsav( pAigNew->pName );
+	
+	if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" );
+	
+	updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames, vecLoNames );
+	Abc_FrameSetCurrentNetwork( pAbc, pNtkNew );
+
+#if 0
+#ifndef DUPLICATE_CKT_DEBUG
+	Saig_ManForEachPi( pAigNew, pObj, i )
+		assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 );
+		//printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) );
+
+	Saig_ManForEachLo( pAigNew, pObj, i )
+		assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 );
+#endif	
+#endif
+		
+	return 0;
+
+usage:
+    fprintf( stdout, "usage: l3s [-1lsh]\n" );
+    fprintf( stdout, "\t         performs Armin Biere's live-to-safe transformation\n" );
+	fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n");
+	fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n");
+    fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n");
+	fprintf( stdout, "\t-h : print command usage\n");
+    return 1;
+}
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/live/liveness_sim.c b/abc-build/src/proof/live/liveness_sim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/live/liveness_sim.c
@@ -0,0 +1,849 @@
+/**CFile****************************************************************
+
+  FileName    [liveness_sim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Liveness property checking.]
+
+  Synopsis    [Main implementation module.]
+
+  Author      [Sayak Ray]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2009.]
+
+  Revision    [$Id: liveness_sim.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include "base/main/main.h"
+#include "aig/aig/aig.h"
+#include "aig/saig/saig.h"
+#include <string.h>
+
+ABC_NAMESPACE_IMPL_START
+
+
+#define PROPAGATE_NAMES
+//#define DUPLICATE_CKT_DEBUG
+
+extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan );
+//char *strdup(const char *string);
+
+
+/*******************************************************************
+LAYOUT OF PI VECTOR:
+ 
++------------------------------------------------------------------------------------------------------------------------------------+
+| TRUE ORIGINAL PI (n) | SAVE(PI) (1) | ORIGINAL LO (k) | SAVED(LO) (1) | SHADOW_ORIGINAL LO (k) | LIVENESS LO (l) | FAIRNESS LO (f) |
++------------------------------------------------------------------------------------------------------------------------------------+
+<------------True PI----------------->|<----------------------------LO--------------------------------------------------------------->
+
+LAYOUT OF PO VECTOR:
+
++-----------------------------------------------------------------------------------------------------------+
+| SOLE PO (1) | ORIGINAL LI (k) | SAVED LI (1) | SHADOW_ORIGINAL LI (k) | LIVENESS LI (l) | FAIRNESS LI (f) |
++-----------------------------------------------------------------------------------------------------------+
+<--True PO--->|<--------------------------------------LI---------------------------------------------------->
+
+********************************************************************/
+
+static void printVecPtrOfString( Vec_Ptr_t *vec )
+{
+	int i;
+
+	for( i=0; i< Vec_PtrSize( vec ); i++ )
+	{
+		printf("vec[%d] = %s\n", i, (char *)Vec_PtrEntry(vec, i) );
+	}
+}
+
+static int getPoIndex( Aig_Man_t *pAig, Aig_Obj_t *pPivot )
+{
+	int i;
+	Aig_Obj_t *pObj;
+
+	Saig_ManForEachPo( pAig, pObj, i )
+	{
+		if( pObj == pPivot )
+			return i;
+	}
+	return -1;
+}
+
+static char * retrieveTruePiName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot )
+{
+	Aig_Obj_t *pObjOld, *pObj;
+	Abc_Obj_t *pNode;
+	int index;
+
+	assert( Saig_ObjIsPi( pAigNew, pObjPivot ) );
+	Aig_ManForEachCi( pAigNew, pObj, index )
+		if( pObj == pObjPivot )
+			break;
+	assert( index < Aig_ManCiNum( pAigNew ) - Aig_ManRegNum( pAigNew ) );
+	if( index == Saig_ManPiNum( pAigNew ) - 1 )
+		return "SAVE_BIERE";
+	else
+	{
+		pObjOld = Aig_ManCi( pAigOld, index );
+		pNode = Abc_NtkPi( pNtkOld, index );
+		assert( pObjOld->pData == pObjPivot );
+		return Abc_ObjName( pNode );
+	}
+}
+
+static char * retrieveLOName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot, Vec_Ptr_t *vLive, Vec_Ptr_t * vFair )
+{
+	Aig_Obj_t *pObjOld, *pObj;
+	Abc_Obj_t *pNode;
+	int index, oldIndex, originalLatchNum = Saig_ManRegNum(pAigOld), strMatch, i;
+	char *dummyStr = (char *)malloc( sizeof(char) * 50 );
+
+	assert( Saig_ObjIsLo( pAigNew, pObjPivot ) );
+	Saig_ManForEachLo( pAigNew, pObj, index )
+		if( pObj == pObjPivot )
+			break;
+	if( index < originalLatchNum )
+	{
+		oldIndex = Saig_ManPiNum( pAigOld ) + index;
+		pObjOld = Aig_ManCi( pAigOld, oldIndex );
+		pNode = Abc_NtkCi( pNtkOld, oldIndex );
+		assert( pObjOld->pData == pObjPivot );
+		return Abc_ObjName( pNode );
+	}
+	else if( index == originalLatchNum )
+		return "SAVED_LO";
+	else if( index > originalLatchNum && index < 2 * originalLatchNum + 1 )
+	{
+		oldIndex = Saig_ManPiNum( pAigOld ) + index - originalLatchNum - 1;
+		pObjOld = Aig_ManCi( pAigOld, oldIndex );
+		pNode = Abc_NtkCi( pNtkOld, oldIndex );
+		sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "SHADOW");
+		return dummyStr;
+	}
+	else if( index >= 2 * originalLatchNum + 1 && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) )
+	{
+		oldIndex = index - 2 * originalLatchNum - 1;
+		strMatch = 0;
+		Saig_ManForEachPo( pAigOld, pObj, i )
+		{
+			pNode = Abc_NtkPo( pNtkOld, i );
+			if( strstr( Abc_ObjName( pNode ), "assert_fair" ) != NULL )
+			{
+				if( strMatch == oldIndex )
+				{
+					sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "LIVENESS");
+					return dummyStr;
+				}
+				else
+					strMatch++;
+			}
+		}
+	}
+	else if( index >= 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) )
+	{
+		oldIndex = index - 2 * originalLatchNum - 1 - Vec_PtrSize( vLive );
+		strMatch = 0;
+		Saig_ManForEachPo( pAigOld, pObj, i )
+		{
+			pNode = Abc_NtkPo( pNtkOld, i );
+			if( strstr( Abc_ObjName( pNode ), "assume_fair" ) != NULL )
+			{
+				if( strMatch == oldIndex )
+				{
+					sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "FAIRNESS");
+					return dummyStr;
+				}
+				else
+					strMatch++;
+			}
+		}
+	}
+	else
+		return "UNKNOWN";
+    return NULL;
+}
+
+extern Vec_Ptr_t *vecPis, *vecPiNames;
+extern Vec_Ptr_t *vecLos, *vecLoNames;
+
+
+static int Aig_ManCiCleanupBiere( Aig_Man_t * p )
+{
+    int nPisOld = Aig_ManCiNum(p);
+	
+    p->nObjs[AIG_OBJ_CI] = Vec_PtrSize( p->vCis );
+    if ( Aig_ManRegNum(p) )
+        p->nTruePis = Aig_ManCiNum(p) - Aig_ManRegNum(p);
+	
+    return nPisOld - Aig_ManCiNum(p);
+}
+
+
+static int Aig_ManCoCleanupBiere( Aig_Man_t * p )
+{
+    int nPosOld = Aig_ManCoNum(p);
+
+    p->nObjs[AIG_OBJ_CO] = Vec_PtrSize( p->vCos );
+    if ( Aig_ManRegNum(p) )
+        p->nTruePos = Aig_ManCoNum(p) - Aig_ManRegNum(p);
+    return nPosOld - Aig_ManCoNum(p);
+}
+
+static Aig_Man_t * LivenessToSafetyTransformationSim( Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Ptr_t *vLive, Vec_Ptr_t *vFair )
+{
+	Aig_Man_t * pNew;
+	int i, nRegCount;
+	Aig_Obj_t * pObjSavePi;
+	Aig_Obj_t *pObjSavedLo, *pObjSavedLi;
+	Aig_Obj_t *pObj, *pMatch;
+	Aig_Obj_t *pObjSaveOrSaved, *pObjSavedLoAndEquality;
+	Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver;
+	Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc, *pObjAndAccDummy;
+	Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate;
+	Aig_Obj_t *pObjSafetyPropertyOutput;
+	Aig_Obj_t *pDriverImage;
+	char *nodeName;
+	int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, liveLatch = 0, fairLatch = 0;
+	
+	vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
+	vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
+
+	vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
+	vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
+
+#ifdef DUPLICATE_CKT_DEBUG
+	printf("\nCode is compiled in DEBUG mode, the input-output behavior will be the same as the original circuit\n");
+	printf("Press any key to continue...");
+	scanf("%c", &c);
+#endif
+
+	//****************************************************************
+	// Step1: create the new manager
+	// Note: The new manager is created with "2 * Aig_ManObjNumMax(p)"
+	// nodes, but this selection is arbitrary - need to be justified
+	//****************************************************************
+	pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) );
+	pNew->pName = Abc_UtilStrsav( "live2safe" );
+    pNew->pSpec = NULL;
+    
+	//****************************************************************
+	// Step 2: map constant nodes
+	//****************************************************************
+    pObj = Aig_ManConst1( p );
+    pObj->pData = Aig_ManConst1( pNew );
+
+	//****************************************************************
+    // Step 3: create true PIs
+	//****************************************************************
+    Saig_ManForEachPi( p, pObj, i )
+	{
+		piCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNew);
+		Vec_PtrPush( vecPis, pObj->pData );
+		nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) ));
+		Vec_PtrPush( vecPiNames, nodeName );
+	}
+
+	//****************************************************************
+	// Step 4: create the special Pi corresponding to SAVE
+	//****************************************************************
+#ifndef DUPLICATE_CKT_DEBUG
+	pObjSavePi = Aig_ObjCreateCi( pNew );
+	nodeName = Abc_UtilStrsav("SAVE_BIERE"),
+	Vec_PtrPush( vecPiNames, nodeName );
+#endif
+		
+	//****************************************************************
+	// Step 5: create register outputs
+	//****************************************************************
+    Saig_ManForEachLo( p, pObj, i )
+    {
+		loCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNew);
+		Vec_PtrPush( vecLos, pObj->pData );
+		nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ));
+		Vec_PtrPush( vecLoNames, nodeName );
+    }
+
+	//****************************************************************
+	// Step 6: create "saved" register output
+	//****************************************************************
+#ifndef DUPLICATE_CKT_DEBUG
+	loCreated++;
+	pObjSavedLo = Aig_ObjCreateCi( pNew );
+	Vec_PtrPush( vecLos, pObjSavedLo );
+	nodeName = Abc_UtilStrsav("SAVED_LO");
+	Vec_PtrPush( vecLoNames, nodeName );
+#endif
+
+	//****************************************************************
+	// Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi
+	//****************************************************************
+#ifndef DUPLICATE_CKT_DEBUG
+	pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo );
+	//pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) );
+#endif
+
+	//********************************************************************
+	// Step 8: create internal nodes
+	//********************************************************************
+    Aig_ManForEachNode( p, pObj, i )
+	{
+		pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+	}
+
+	//********************************************************************
+	// Step 9: create the safety property output gate
+	// create the safety property output gate, this will be the sole true PO 
+	// of the whole circuit, discuss with Sat/Alan for an alternative implementation
+	//********************************************************************
+#ifndef DUPLICATE_CKT_DEBUG
+	pObjSafetyPropertyOutput = Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData );
+#endif
+
+	//********************************************************************
+	// DEBUG: To recreate the same circuit, at least from the input and output
+	// behavior, we need to copy the original PO
+	//********************************************************************
+#ifdef DUPLICATE_CKT_DEBUG
+	Saig_ManForEachPo( p, pObj, i )
+	{
+		Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+	}
+#endif
+
+	// create register inputs for the original registers
+    nRegCount = 0;
+	
+	Saig_ManForEachLo( p, pObj, i )
+    {
+		pMatch = Saig_ObjLoToLi( p, pObj );
+        //Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pMatch) );
+		Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) );
+        nRegCount++;
+		liCopied++;
+    }
+
+	// create register input corresponding to the register "saved"
+#ifndef DUPLICATE_CKT_DEBUG
+	pObjSavedLi = Aig_ObjCreateCo( pNew, pObjSaveOrSaved );
+	nRegCount++;
+	liCreated++;
+
+	pObjAndAcc = NULL;
+
+	// create the family of shadow registers, then create the cascade of Xnor and And gates for the comparator 
+	Saig_ManForEachLo( p, pObj, i )
+	{
+		pObjShadowLo = Aig_ObjCreateCi( pNew );
+
+#ifdef PROPAGATE_NAMES
+		Vec_PtrPush( vecLos, pObjShadowLo );
+		nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ) + 10 );
+		sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "SHADOW" );
+		Vec_PtrPush( vecLoNames, nodeName );
+#endif
+
+		pObjShadowLiDriver = Aig_Mux( pNew, pObjSavePi, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
+		pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver );
+		nRegCount++;
+		loCreated++; liCreated++;
+		
+		pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
+		pObjXnor = Aig_Not( pObjXor );
+		if( pObjAndAcc == NULL )
+			pObjAndAcc = pObjXnor;
+		else
+		{
+			pObjAndAccDummy = pObjAndAcc;
+			pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAccDummy );
+		}
+	}
+
+	// create the AND gate whose output will be the signal "looped"
+	pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc );
+	
+	// create the master AND gate and corresponding AND and OR logic for the liveness properties
+	pObjAndAcc = NULL;
+	if( vLive == NULL || Vec_PtrSize( vLive ) == 0 )
+		printf("\nCircuit without any liveness property\n");
+	else
+	{
+		Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i )
+		{
+			//assert( Aig_ObjIsNode( Aig_ObjChild0( pObj ) ) );
+			//Aig_ObjPrint( pNew, pObj );
+			liveLatch++;
+			pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+			pObjShadowLo = Aig_ObjCreateCi( pNew );
+
+#ifdef PROPAGATE_NAMES
+		Vec_PtrPush( vecLos, pObjShadowLo );
+		nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 );
+		sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" );
+		Vec_PtrPush( vecLoNames, nodeName );
+#endif
+
+			pObjShadowLiDriver = Aig_Or( pNew, Aig_Mux(pNew, pObjSavePi, Aig_Not(Aig_ManConst1(pNew)), pObjShadowLo), 
+												Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
+			pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver );
+			nRegCount++;
+			loCreated++; liCreated++;
+			
+			if( pObjAndAcc == NULL )
+				pObjAndAcc = pObjShadowLo;
+			else
+			{
+				pObjAndAccDummy = pObjAndAcc;
+				pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAccDummy );
+			}
+		}
+	}
+
+	if( pObjAndAcc != NULL )
+		pObjLive = pObjAndAcc;
+	else
+		pObjLive = Aig_ManConst1( pNew );
+	
+	// create the master AND gate and corresponding AND and OR logic for the fairness properties
+	pObjAndAcc = NULL;
+	if( vFair == NULL || Vec_PtrSize( vFair ) == 0 )
+		printf("\nCircuit without any fairness property\n");
+	else
+	{
+		Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i )
+		{
+			fairLatch++;
+			//assert( Aig_ObjIsNode( Aig_ObjChild0( pObj ) ) );
+			pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+			pObjShadowLo = Aig_ObjCreateCi( pNew );
+
+#ifdef PROPAGATE_NAMES
+		Vec_PtrPush( vecLos, pObjShadowLo );
+		nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 );
+		sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "FAIRNESS" );
+		Vec_PtrPush( vecLoNames, nodeName );
+#endif
+
+			pObjShadowLiDriver = Aig_Or( pNew, Aig_Mux(pNew, pObjSavePi, Aig_Not(Aig_ManConst1(pNew)), pObjShadowLo), 
+									Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
+			pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver );
+			nRegCount++;
+			loCreated++; liCreated++;
+			
+			if( pObjAndAcc == NULL )
+				pObjAndAcc = pObjShadowLo;
+			else
+			{
+				pObjAndAccDummy = pObjAndAcc;
+				pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAccDummy );
+			}
+		}
+	}
+
+	if( pObjAndAcc != NULL )
+		pObjFair = pObjAndAcc;
+	else
+		pObjFair = Aig_ManConst1( pNew );
+	
+	//pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) );
+	pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) );
+	
+	Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate );
+#endif
+
+	Aig_ManSetRegNum( pNew, nRegCount );
+
+	Aig_ManCiCleanupBiere( pNew );
+	Aig_ManCoCleanupBiere( pNew );
+	
+	Aig_ManCleanup( pNew );
+	assert( Aig_ManCheck( pNew ) );
+	
+#ifndef DUPLICATE_CKT_DEBUG
+	assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vCos, Saig_ManPoNum(pNew)+Aig_ObjCioId(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi);
+	assert( Saig_ManPoNum( pNew ) == 1 );
+	assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) );
+	assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch );
+#endif
+
+	return pNew;
+}
+
+
+static Aig_Man_t * LivenessToSafetyTransformationOneStepLoopSim( Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Ptr_t *vLive, Vec_Ptr_t *vFair )
+{
+	Aig_Man_t * pNew;
+	int i, nRegCount;
+	Aig_Obj_t * pObjSavePi;
+	Aig_Obj_t *pObj, *pMatch;
+	Aig_Obj_t *pObjSavedLoAndEquality;
+	Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc, *pObjAndAccDummy;
+	Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate;
+	Aig_Obj_t *pObjSafetyPropertyOutput;
+	Aig_Obj_t *pDriverImage;
+	Aig_Obj_t *pObjCorrespondingLi;
+
+
+	char *nodeName;
+	int piCopied = 0, liCopied = 0, loCopied = 0;//, liCreated = 0, loCreated = 0, piVecIndex = 0;
+	
+	vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
+	vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
+
+	vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
+	vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
+
+	//****************************************************************
+	// Step1: create the new manager
+	// Note: The new manager is created with "2 * Aig_ManObjNumMax(p)"
+	// nodes, but this selection is arbitrary - need to be justified
+	//****************************************************************
+	pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) );
+	pNew->pName = Abc_UtilStrsav( "live2safe" );
+    pNew->pSpec = NULL;
+    
+	//****************************************************************
+	// Step 2: map constant nodes
+	//****************************************************************
+    pObj = Aig_ManConst1( p );
+    pObj->pData = Aig_ManConst1( pNew );
+
+	//****************************************************************
+    // Step 3: create true PIs
+	//****************************************************************
+    Saig_ManForEachPi( p, pObj, i )
+	{
+		piCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNew);
+		Vec_PtrPush( vecPis, pObj->pData );
+		nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) ));
+		Vec_PtrPush( vecPiNames, nodeName );
+	}
+
+	//****************************************************************
+	// Step 4: create the special Pi corresponding to SAVE
+	//****************************************************************
+	pObjSavePi = Aig_ObjCreateCi( pNew );
+	nodeName = "SAVE_BIERE",
+	Vec_PtrPush( vecPiNames, nodeName );
+		
+	//****************************************************************
+	// Step 5: create register outputs
+	//****************************************************************
+    Saig_ManForEachLo( p, pObj, i )
+    {
+		loCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNew);
+		Vec_PtrPush( vecLos, pObj->pData );
+		nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ));
+		Vec_PtrPush( vecLoNames, nodeName );
+    }
+
+	//****************************************************************
+	// Step 6: create "saved" register output
+	//****************************************************************
+
+#if 0
+	loCreated++;
+	pObjSavedLo = Aig_ObjCreateCi( pNew );
+	Vec_PtrPush( vecLos, pObjSavedLo );
+	nodeName = "SAVED_LO";
+	Vec_PtrPush( vecLoNames, nodeName );
+#endif
+
+	//****************************************************************
+	// Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi
+	//****************************************************************
+#if 0
+	pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo );
+	pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) );
+#endif
+
+	//********************************************************************
+	// Step 8: create internal nodes
+	//********************************************************************
+    Aig_ManForEachNode( p, pObj, i )
+	{
+		pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+	}
+
+	//********************************************************************
+	// Step 9: create the safety property output gate
+	// create the safety property output gate, this will be the sole true PO 
+	// of the whole circuit, discuss with Sat/Alan for an alternative implementation
+	//********************************************************************
+
+	pObjSafetyPropertyOutput = Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData );
+
+	// create register inputs for the original registers
+    nRegCount = 0;
+	
+	Saig_ManForEachLo( p, pObj, i )
+    {
+		pMatch = Saig_ObjLoToLi( p, pObj );
+        //Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pMatch) );
+		Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) );
+        nRegCount++;
+		liCopied++;
+    }
+
+#if 0
+	// create register input corresponding to the register "saved"
+	pObjSavedLi = Aig_ObjCreateCo( pNew, pObjSaveOrSaved );
+	nRegCount++;
+	liCreated++;
+#endif
+
+	pObjAndAcc = NULL;
+
+	//****************************************************************************************************
+	//For detection of loop of length 1 we do not need any shadow register, we only need equality detector
+	//between Lo_j and Li_j and then a cascade of AND gates
+	//****************************************************************************************************
+
+	Saig_ManForEachLo( p, pObj, i )
+	{
+		pObjCorrespondingLi = Saig_ObjLoToLi( p, pObj );
+		
+		pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData,  Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0( pObjCorrespondingLi )->pData, Aig_ObjFaninC0( pObjCorrespondingLi ) ) );
+		pObjXnor = Aig_Not( pObjXor );
+		
+		if( pObjAndAcc == NULL )
+			pObjAndAcc = pObjXnor;
+		else
+		{
+			pObjAndAccDummy = pObjAndAcc;
+			pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAccDummy );
+		}
+	}
+
+	// create the AND gate whose output will be the signal "looped"
+	pObjSavedLoAndEquality = Aig_And( pNew, pObjSavePi, pObjAndAcc );
+	
+	// create the master AND gate and corresponding AND and OR logic for the liveness properties
+	pObjAndAcc = NULL;
+	if( vLive == NULL || Vec_PtrSize( vLive ) == 0 )
+		printf("\nCircuit without any liveness property\n");
+	else
+	{
+		Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i )
+		{
+			pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+			if( pObjAndAcc == NULL )
+				pObjAndAcc = pDriverImage;
+			else
+			{
+				pObjAndAccDummy = pObjAndAcc;
+				pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy );
+			}
+		}
+	}
+
+	if( pObjAndAcc != NULL )
+		pObjLive = pObjAndAcc;
+	else
+		pObjLive = Aig_ManConst1( pNew );
+	
+	// create the master AND gate and corresponding AND and OR logic for the fairness properties
+	pObjAndAcc = NULL;
+	if( vFair == NULL || Vec_PtrSize( vFair ) == 0 )
+		printf("\nCircuit without any fairness property\n");
+	else
+	{
+		Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i )
+		{
+			pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+			if( pObjAndAcc == NULL )
+				pObjAndAcc = pDriverImage;
+			else
+			{
+				pObjAndAccDummy = pObjAndAcc;
+				pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy );
+			}
+		}
+	}
+
+	if( pObjAndAcc != NULL )
+		pObjFair = pObjAndAcc;
+	else
+		pObjFair = Aig_ManConst1( pNew );
+	
+	pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) );
+	
+	Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate );
+
+	Aig_ManSetRegNum( pNew, nRegCount );
+
+	printf("\nSaig_ManPiNum = %d, Reg Num = %d, before everything, before Pi cleanup\n", Vec_PtrSize( pNew->vCis ), pNew->nRegs );
+
+	Aig_ManCiCleanupBiere( pNew );
+	Aig_ManCoCleanupBiere( pNew );
+
+	Aig_ManCleanup( pNew );
+	
+	assert( Aig_ManCheck( pNew ) );
+	
+	return pNew;
+}
+
+
+
+static Vec_Ptr_t * populateLivenessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig )
+{
+	Abc_Obj_t * pNode;
+	int i, liveCounter = 0;
+	Vec_Ptr_t * vLive;
+
+	vLive = Vec_PtrAlloc( 100 );
+	Abc_NtkForEachPo( pNtk, pNode, i )
+		if( strstr( Abc_ObjName( pNode ), "assert_fair") != NULL )
+		{
+			Vec_PtrPush( vLive, Aig_ManCo( pAig, i ) );
+			liveCounter++;
+		}
+	printf("\nNumber of liveness property found = %d\n", liveCounter);
+	return vLive;
+}
+
+static Vec_Ptr_t * populateFairnessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig )
+{
+	Abc_Obj_t * pNode;
+	int i, fairCounter = 0;
+	Vec_Ptr_t * vFair;
+
+	vFair = Vec_PtrAlloc( 100 );
+	Abc_NtkForEachPo( pNtk, pNode, i )
+		if( strstr( Abc_ObjName( pNode ), "assume_fair") != NULL )
+		{
+			Vec_PtrPush( vFair, Aig_ManCo( pAig, i ) );
+			fairCounter++;
+		}
+	printf("\nNumber of fairness property found = %d\n", fairCounter);
+	return vFair;
+}
+
+static void updateNewNetworkNameManager( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, Vec_Ptr_t *vPiNames, Vec_Ptr_t *vLoNames )
+{
+	Aig_Obj_t *pObj;
+	int i, ntkObjId;
+
+	pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum( pNtk ) );
+
+	Saig_ManForEachPi( pAig, pObj, i )
+	{
+		ntkObjId = Abc_NtkCi( pNtk, i )->Id;
+		//printf("Pi %d, Saved Name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vPiNames, i), NULL ), ntkObjId);  
+		Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vPiNames, i), NULL );
+	}
+	Saig_ManForEachLo( pAig, pObj, i )
+	{
+		ntkObjId = Abc_NtkCi( pNtk, Saig_ManPiNum( pAig ) + i )->Id;
+		//printf("Lo %d, Saved name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vLoNames, i), NULL ), ntkObjId);  
+		Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vLoNames, i), NULL );
+	}
+}
+
+
+int Abc_CommandAbcLivenessToSafetySim( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+	FILE * pOut, * pErr;
+    Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld;
+	Aig_Man_t * pAig, *pAigNew;
+	int c;
+	Vec_Ptr_t * vLive, * vFair;
+		        
+	pNtk = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+	if ( pNtk == NULL )
+    {
+        fprintf( pErr, "Empty network.\n" );
+        return 1;
+    }
+
+	if( !Abc_NtkIsStrash( pNtk ) )
+	{
+		printf("\nThe input network was not strashed, strashing....\n");
+		pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+		pNtkOld = pNtkTemp;
+		pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
+		vLive = populateLivenessVector( pNtk, pAig );
+		vFair = populateFairnessVector( pNtk, pAig );
+	}
+	else
+	{
+		pAig = Abc_NtkToDar( pNtk, 0, 1 );
+		pNtkOld = pNtk;
+		vLive = populateLivenessVector( pNtk, pAig );
+		vFair = populateFairnessVector( pNtk, pAig );
+	}
+
+#if 0
+	Aig_ManPrintStats( pAig );
+	printf("\nDetail statistics*************************************\n");
+	printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAig ));
+	printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAig ));
+	printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAig ) - Saig_ManPiNum( pAig ));
+	printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAig ) - Saig_ManPoNum( pAig ));
+	printf("Numer of registers = %d\n", Saig_ManRegNum( pAig ) );
+	printf("\n*******************************************************\n");
+#endif
+
+	c = Extra_UtilGetopt( argc, argv, "1" );
+	if( c == '1' )
+		pAigNew = LivenessToSafetyTransformationOneStepLoopSim( pNtk, pAig, vLive, vFair );
+	else
+		pAigNew = LivenessToSafetyTransformationSim( pNtk, pAig, vLive, vFair );
+	
+#if 0
+	Aig_ManPrintStats( pAigNew );
+	printf("\nDetail statistics*************************************\n");
+	printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAigNew ));
+	printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAigNew ));
+	printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAigNew ) - Saig_ManPiNum( pAigNew ));
+	printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAigNew ) - Saig_ManPoNum( pAigNew ));
+	printf("Numer of registers = %d\n", Saig_ManRegNum( pAigNew ) );
+	printf("\n*******************************************************\n");
+#endif
+
+	pNtkNew = Abc_NtkFromAigPhase( pAigNew );
+
+	if ( !Abc_NtkCheck( pNtkNew ) )
+        fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" );
+	
+	updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames,vecLoNames );
+	Abc_FrameSetCurrentNetwork( pAbc, pNtkNew );
+
+	//Saig_ManForEachPi( pAigNew, pObj, i )
+	//	printf("Name of %d-th Pi = %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) );
+
+	//Saig_ManForEachLo( pAigNew, pObj, i )
+	//	printf("Name of %d-th Lo = %s\n", i, retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) );
+
+	//printVecPtrOfString( vecPiNames );
+	//printVecPtrOfString( vecLoNames );
+
+#if 0
+#ifndef DUPLICATE_CKT_DEBUG
+	Saig_ManForEachPi( pAigNew, pObj, i )
+		assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 );
+		//printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) );
+
+	Saig_ManForEachLo( pAigNew, pObj, i )
+		assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 );
+#endif	
+#endif
+		
+	return 0;
+
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/live/ltl_parser.c b/abc-build/src/proof/live/ltl_parser.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/live/ltl_parser.c
@@ -0,0 +1,839 @@
+/**CFile****************************************************************
+
+  FileName    [ltl_parser.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Liveness property checking.]
+
+  Synopsis    [LTL checker.]
+
+  Author      [Sayak Ray]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2009.]
+
+  Revision    [$Id: ltl_parser.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include "aig/aig/aig.h"
+#include "base/abc/abc.h"
+#include "base/main/mainInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+enum ltlToken { AND, OR, NOT, IMPLY, GLOBALLY, EVENTUALLY, NEXT, UNTIL, BOOL };
+enum ltlGrammerToken { OPERAND, LTL, BINOP, UOP };
+typedef enum ltlToken tokenType;
+typedef enum ltlGrammerToken ltlGrammerTokenType;
+
+struct ltlNode_t
+{
+	tokenType type;
+	char *name;
+	Aig_Obj_t *pObj;
+	struct ltlNode_t *left;
+	struct ltlNode_t *right;
+};
+
+typedef struct ltlNode_t ltlNode;
+
+ltlNode *generateTypedNode( tokenType new_type )
+//void generateTypedNode( ltlNode *new_node, tokenType new_type )
+{
+	ltlNode *new_node;
+
+	new_node = (ltlNode *)malloc( sizeof(ltlNode) );
+	if( new_node )
+	{
+		new_node->type = new_type;
+		new_node->pObj = NULL;
+		new_node->name = NULL;
+		new_node->left = NULL;
+		new_node->right = NULL;
+	}
+
+	return new_node;
+}
+
+Aig_Obj_t *buildLogicFromLTLNode_combinationalOnly( Aig_Man_t *pAig, ltlNode *pLtlNode );
+
+static inline int isNotVarNameSymbol( char c )
+{
+	return ( c == ' ' || c == '\t' || c == '\n' || c == ':' || c == '\0' );
+}
+
+void Abc_FrameCopyLTLDataBase( Abc_Frame_t *pAbc, Abc_Ntk_t * pNtk )
+{
+	char *pLtlFormula, *tempFormula;
+	int i;
+
+	if( pAbc->vLTLProperties_global != NULL )
+	{
+//		printf("Deleting exisitng LTL database from the frame\n");
+        Vec_PtrFree( pAbc->vLTLProperties_global );
+		pAbc->vLTLProperties_global = NULL;
+	}
+	pAbc->vLTLProperties_global = Vec_PtrAlloc(Vec_PtrSize(pNtk->vLtlProperties));
+	Vec_PtrForEachEntry( char *, pNtk->vLtlProperties, pLtlFormula, i )
+	{
+		tempFormula = (char *)malloc( sizeof(char)*(strlen(pLtlFormula)+1) );
+		sprintf( tempFormula, "%s", pLtlFormula );
+		Vec_PtrPush( pAbc->vLTLProperties_global, tempFormula );
+	}
+}
+
+char *getVarName( char *suffixFormula, int startLoc, int *endLocation )
+{
+	int i = startLoc, length;
+	char *name;
+
+	if( isNotVarNameSymbol( suffixFormula[startLoc] ) )
+		return NULL;
+
+	while( !isNotVarNameSymbol( suffixFormula[i] ) )
+		i++;
+	*endLocation = i;
+	length = i - startLoc;
+	name = (char *)malloc( sizeof(char) * (length + 1));
+	for( i=0; i<length; i++ )
+		name[i] = suffixFormula[i+startLoc];
+	name[i] = '\0';
+
+	return name;
+}
+
+
+int startOfSuffixString = 0;
+
+int isUnexpectedEOS( char *formula, int index )
+{
+	assert( formula );
+	if( index >= (int)strlen( formula ) )
+	{
+		printf("\nInvalid LTL formula: unexpected end of string..." );
+		return 1;
+	}
+	return 0;
+}
+
+int isTemporalOperator( char *formula, int index )
+{
+	if( !(isUnexpectedEOS( formula, index ) || formula[ index ] == 'G' || formula[ index ] == 'F' || formula[ index ] == 'U' || formula[ index ] == 'X') )
+	{
+		printf("\nInvalid LTL formula: expecting temporal operator at the position %d....\n", index);
+		return 0;
+	}
+	return 1;
+}
+
+ltlNode *readLtlFormula( char *formula )
+{
+	char ch;
+	char *varName;
+	int formulaLength, rememberEnd;
+	int i = startOfSuffixString;
+	ltlNode *curr_node, *temp_node_left, *temp_node_right;
+	char prevChar;
+	
+	formulaLength = strlen( formula );
+	if( isUnexpectedEOS( formula, startOfSuffixString ) )
+	{
+		printf("\nFAULTING POINT: formula = %s\nstartOfSuffixString = %d, formula[%d] = %c\n\n", formula, startOfSuffixString, startOfSuffixString - 1, formula[startOfSuffixString-1]);
+		return NULL;
+	}
+			
+	while( i < formulaLength )
+	{
+		ch = formula[i];
+
+		switch(ch){
+			case ' ':
+			case '\n':
+			case '\r':
+			case '\t':
+			case '\v':
+			case '\f':
+						i++;
+						startOfSuffixString = i;
+						break;
+			case ':':
+						i++;
+						if( !isTemporalOperator( formula, i ) )
+							return NULL;
+						startOfSuffixString = i;
+						break;
+			case 'G':
+						prevChar = formula[i-1];
+						if( prevChar == ':' ) //i.e. 'G' is a temporal operator
+						{
+							i++;
+							startOfSuffixString = i;
+							temp_node_left = readLtlFormula( formula );
+							if( temp_node_left == NULL )
+								return NULL;
+							else
+							{
+								curr_node = generateTypedNode(GLOBALLY);
+								curr_node->left = temp_node_left;
+								return curr_node;
+							}
+						}
+						else	//i.e. 'G' must be starting a variable name
+						{
+							varName = getVarName( formula, i, &rememberEnd );
+							if( !varName )
+							{
+								printf("\nInvalid LTL formula: expecting valid variable name token...aborting" );
+								return NULL;
+							}
+							curr_node = generateTypedNode(BOOL);
+							curr_node->name = varName;
+							i = rememberEnd;
+							startOfSuffixString = i;
+							return curr_node;
+						}
+			case 'F':
+						prevChar = formula[i-1];
+						if( prevChar == ':' ) //i.e. 'F' is a temporal operator
+						{
+							i++;
+							startOfSuffixString = i;
+							temp_node_left = readLtlFormula( formula );
+							if( temp_node_left == NULL )
+								return NULL;
+							else
+							{
+								curr_node = generateTypedNode(EVENTUALLY);
+								curr_node->left = temp_node_left;
+								return curr_node;
+							}
+						}
+						else //i.e. 'F' must be starting a variable name
+						{
+							varName = getVarName( formula, i, &rememberEnd );
+							if( !varName )
+							{
+								printf("\nInvalid LTL formula: expecting valid variable name token...aborting" );
+								return NULL;
+							}
+							curr_node = generateTypedNode(BOOL);
+							curr_node->name = varName;
+							i = rememberEnd;
+							startOfSuffixString = i;
+							return curr_node;
+						}	
+			case 'X':
+						prevChar = formula[i-1];
+						if( prevChar == ':' ) //i.e. 'X' is a temporal operator
+						{
+							i++;
+							startOfSuffixString = i;
+							temp_node_left = readLtlFormula( formula );
+							if( temp_node_left == NULL )
+								return NULL;
+							else
+							{
+								curr_node = generateTypedNode(NEXT);
+								curr_node->left = temp_node_left;
+								return curr_node;
+							}
+						}
+						else //i.e. 'X' must be starting a variable name
+						{
+							varName = getVarName( formula, i, &rememberEnd );
+							if( !varName )
+							{
+								printf("\nInvalid LTL formula: expecting valid variable name token...aborting" );
+								return NULL;
+							}
+							curr_node = generateTypedNode(BOOL);
+							curr_node->name = varName;
+							i = rememberEnd;
+							startOfSuffixString = i;
+							return curr_node;
+						}	
+			case 'U':
+						prevChar = formula[i-1];
+						if( prevChar == ':' ) //i.e. 'X' is a temporal operator
+						{
+							i++;
+							startOfSuffixString = i;
+							temp_node_left = readLtlFormula( formula );
+							if( temp_node_left == NULL )
+								return NULL;
+							temp_node_right = readLtlFormula( formula );
+							if( temp_node_right == NULL )
+							{
+								//need to do memory management: if right subtree is NULL then left
+								//subtree must be freed.
+								return NULL;
+							}
+							curr_node = generateTypedNode(UNTIL);
+							curr_node->left = temp_node_left;
+							curr_node->right = temp_node_right;
+							return curr_node;
+						}
+						else //i.e. 'U' must be starting a variable name
+						{
+							varName = getVarName( formula, i, &rememberEnd );
+							if( !varName )
+							{
+								printf("\nInvalid LTL formula: expecting valid variable name token...aborting" );
+								return NULL;
+							}
+							curr_node = generateTypedNode(BOOL);
+							curr_node->name = varName;
+							i = rememberEnd;
+							startOfSuffixString = i;
+							return curr_node;
+						}	
+			case '+':
+						i++;
+						startOfSuffixString = i;
+						temp_node_left = readLtlFormula( formula );
+						if( temp_node_left == NULL )
+							return NULL;
+						temp_node_right = readLtlFormula( formula );
+						if( temp_node_right == NULL )
+						{
+							//need to do memory management: if right subtree is NULL then left
+							//subtree must be freed.
+							return NULL;
+						}
+						curr_node = generateTypedNode(OR);
+						curr_node->left = temp_node_left;
+						curr_node->right = temp_node_right;
+						return curr_node;
+			case '&':
+						i++;
+						startOfSuffixString = i;
+						temp_node_left = readLtlFormula( formula );
+						if( temp_node_left == NULL )
+							return NULL;
+						temp_node_right = readLtlFormula( formula );
+						if( temp_node_right == NULL )
+						{
+							//need to do memory management: if right subtree is NULL then left
+							//subtree must be freed.
+							return NULL;
+						}
+						curr_node = generateTypedNode(AND);
+						curr_node->left = temp_node_left;
+						curr_node->right = temp_node_right;
+						return curr_node;
+			case '!':
+						i++;
+						startOfSuffixString = i;
+						temp_node_left = readLtlFormula( formula );
+						if( temp_node_left == NULL )
+							return NULL;
+						else
+						{
+							curr_node = generateTypedNode(NOT);
+							curr_node->left = temp_node_left;
+							return curr_node;
+						}
+			default:
+				varName = getVarName( formula, i, &rememberEnd );
+				if( !varName )
+				{
+					printf("\nInvalid LTL formula: expecting valid variable name token...aborting" );
+					return NULL;
+				}
+				curr_node = generateTypedNode(BOOL);
+				curr_node->name = varName;
+				i = rememberEnd;
+				startOfSuffixString = i;
+				return curr_node;
+		}
+	}
+	return NULL;
+}
+
+void resetGlobalVar()
+{
+	startOfSuffixString = 0;
+}
+
+ltlNode *parseFormulaCreateAST( char *inputFormula )
+{
+	ltlNode *temp;
+
+	temp = readLtlFormula( inputFormula );
+	//if( temp == NULL )
+	//	printf("\nAST creation failed for formula %s", inputFormula );
+	resetGlobalVar();
+	return temp;
+}
+
+void traverseAbstractSyntaxTree( ltlNode *node )
+{
+	switch(node->type){
+		case( AND ):
+			printf("& ");
+			assert( node->left != NULL );
+			assert( node->right != NULL );
+			traverseAbstractSyntaxTree( node->left );
+			traverseAbstractSyntaxTree( node->right );
+			return;
+		case( OR ):
+			printf("+ ");
+			assert( node->left != NULL );
+			assert( node->right != NULL );
+			traverseAbstractSyntaxTree( node->left );
+			traverseAbstractSyntaxTree( node->right );
+			return;
+		case( NOT ):
+			printf("~ ");
+			assert( node->left != NULL );
+			traverseAbstractSyntaxTree( node->left );
+			assert( node->right == NULL );
+			return;
+		case( GLOBALLY ):
+			printf("G ");
+			assert( node->left != NULL );
+			traverseAbstractSyntaxTree( node->left );
+			assert( node->right == NULL );
+			return;
+		case( EVENTUALLY ):
+			printf("F ");
+			assert( node->left != NULL );
+			traverseAbstractSyntaxTree( node->left );
+			assert( node->right == NULL );
+			return;
+		case( NEXT ):
+			printf("X ");
+			assert( node->left != NULL );
+			traverseAbstractSyntaxTree( node->left );
+			assert( node->right == NULL );
+			return;
+		case( UNTIL ):
+			printf("U ");
+			assert( node->left != NULL );
+			assert( node->right != NULL );
+			traverseAbstractSyntaxTree( node->left );
+			traverseAbstractSyntaxTree( node->right );
+			return;
+		case( BOOL ):
+			printf("%s ", node->name);
+			assert( node->left == NULL );
+			assert( node->right == NULL );
+			return;
+		default:
+			printf("\nUnsupported token type: Exiting execution\n");
+			exit(0);
+	}
+}
+
+void traverseAbstractSyntaxTree_postFix( ltlNode *node )
+{
+	switch(node->type){
+		case( AND ):
+			printf("( ");
+			assert( node->left != NULL );
+			assert( node->right != NULL );
+			traverseAbstractSyntaxTree_postFix( node->left );
+			printf("& ");
+			traverseAbstractSyntaxTree_postFix( node->right );
+			printf(") ");
+			return;
+		case( OR ):
+			printf("( ");
+			assert( node->left != NULL );
+			assert( node->right != NULL );
+			traverseAbstractSyntaxTree_postFix( node->left );
+			printf("+ ");
+			traverseAbstractSyntaxTree_postFix( node->right );
+			printf(") ");
+			return;
+		case( NOT ):
+			printf("~ ");
+			assert( node->left != NULL );
+			traverseAbstractSyntaxTree_postFix( node->left );
+			assert( node->right == NULL );
+			return;
+		case( GLOBALLY ):
+			printf("G ");
+			//printf("( ");
+			assert( node->left != NULL );
+			traverseAbstractSyntaxTree_postFix( node->left );
+			assert( node->right == NULL );
+			//printf(") ");
+			return;
+		case( EVENTUALLY ):
+			printf("F ");
+			//printf("( ");
+			assert( node->left != NULL );
+			traverseAbstractSyntaxTree_postFix( node->left );
+			assert( node->right == NULL );
+			//printf(") ");
+			return;
+		case( NEXT ):
+			printf("X ");
+			assert( node->left != NULL );
+			traverseAbstractSyntaxTree_postFix( node->left );
+			assert( node->right == NULL );
+			return;
+		case( UNTIL ):
+			printf("( ");
+			assert( node->left != NULL );
+			assert( node->right != NULL );
+			traverseAbstractSyntaxTree_postFix( node->left );
+			printf("U ");
+			traverseAbstractSyntaxTree_postFix( node->right );
+			printf(") ");
+			return;
+		case( BOOL ):
+			printf("%s ", node->name);
+			assert( node->left == NULL );
+			assert( node->right == NULL );
+			return;
+		default:
+			printf("\nUnsupported token type: Exiting execution\n");
+			exit(0);
+	}
+}
+
+void populateAigPointerUnitGF( Aig_Man_t *pAigNew, ltlNode *topASTNode, Vec_Ptr_t *vSignal, Vec_Vec_t *vAigGFMap )
+{
+	ltlNode *nextNode, *nextToNextNode;
+	int serialNumSignal;
+
+	switch( topASTNode->type ){
+		case AND:
+		case OR:
+		case IMPLY:
+			populateAigPointerUnitGF( pAigNew, topASTNode->left, vSignal, vAigGFMap );
+			populateAigPointerUnitGF( pAigNew, topASTNode->right, vSignal, vAigGFMap );
+			return;
+		case NOT:
+			populateAigPointerUnitGF( pAigNew, topASTNode->left, vSignal, vAigGFMap );
+			return;
+		case GLOBALLY:
+			nextNode = topASTNode->left;
+			assert( nextNode->type = EVENTUALLY );
+			nextToNextNode = nextNode->left;
+			if( nextToNextNode->type == BOOL )
+			{
+				assert( nextToNextNode->pObj );
+				serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj );
+				if( serialNumSignal == -1 )
+				{					
+					Vec_PtrPush( vSignal, nextToNextNode->pObj );
+					serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj );
+				}
+				//Vec_PtrPush( vGLOBALLY, topASTNode );
+				Vec_VecPush( vAigGFMap, serialNumSignal, topASTNode );
+			}
+			else
+			{
+				assert( nextToNextNode->pObj == NULL );
+				buildLogicFromLTLNode_combinationalOnly( pAigNew, nextToNextNode );
+				serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj );
+				if( serialNumSignal == -1 )
+				{
+					Vec_PtrPush( vSignal, nextToNextNode->pObj );
+					serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj );
+				}
+				//Vec_PtrPush( vGLOBALLY, topASTNode );
+				Vec_VecPush( vAigGFMap, serialNumSignal, topASTNode );
+			}
+			return;
+		case BOOL:
+			return;
+		default:
+			printf("\nINVALID situation: aborting...\n");
+			exit(0);
+	}
+}
+
+Aig_Obj_t *buildLogicFromLTLNode_combinationalOnly( Aig_Man_t *pAigNew, ltlNode *pLtlNode )
+{
+	Aig_Obj_t *leftAigObj, *rightAigObj;
+
+	if( pLtlNode->pObj != NULL )
+		return pLtlNode->pObj;
+	else
+	{
+		assert( pLtlNode->type != BOOL );
+		switch( pLtlNode->type ){
+			case AND:
+				assert( pLtlNode->left ); assert( pLtlNode->right );
+				leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left );
+				rightAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->right );
+				assert( leftAigObj ); assert( rightAigObj );
+				pLtlNode->pObj = Aig_And( pAigNew, leftAigObj, rightAigObj );
+				return pLtlNode->pObj;
+			case OR:
+				assert( pLtlNode->left ); assert( pLtlNode->right );
+				leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left );
+				rightAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->right );
+				assert( leftAigObj ); assert( rightAigObj );
+				pLtlNode->pObj = Aig_Or( pAigNew, leftAigObj, rightAigObj );
+				return pLtlNode->pObj;
+			case NOT:
+				assert( pLtlNode->left ); assert( pLtlNode->right == NULL ); 
+				leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left );
+				assert( leftAigObj );
+				pLtlNode->pObj = Aig_Not( leftAigObj );
+				return pLtlNode->pObj;
+			case GLOBALLY:
+			case EVENTUALLY:
+			case NEXT:
+			case UNTIL:
+				printf("FORBIDDEN node: ABORTING!!\n");
+				exit(0);
+			default:
+				printf("\nSerious ERROR: attempting to create AIG node from a temporal node\n");
+				exit(0);
+		}
+	}
+}
+
+Aig_Obj_t *buildLogicFromLTLNode( Aig_Man_t *pAig, ltlNode *pLtlNode )
+{
+	Aig_Obj_t *leftAigObj, *rightAigObj;
+
+	if( pLtlNode->pObj != NULL )
+		return pLtlNode->pObj;
+	else
+	{
+		assert( pLtlNode->type != BOOL );
+		switch( pLtlNode->type ){
+			case AND:
+				assert( pLtlNode->left ); assert( pLtlNode->right );
+				leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left );
+				rightAigObj = buildLogicFromLTLNode( pAig, pLtlNode->right );
+				assert( leftAigObj ); assert( rightAigObj );
+				pLtlNode->pObj = Aig_And( pAig, leftAigObj, rightAigObj );
+				return pLtlNode->pObj;
+			case OR:
+				assert( pLtlNode->left ); assert( pLtlNode->right );
+				leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left );
+				rightAigObj = buildLogicFromLTLNode( pAig, pLtlNode->right );
+				assert( leftAigObj ); assert( rightAigObj );
+				pLtlNode->pObj = Aig_Or( pAig, leftAigObj, rightAigObj );
+				return pLtlNode->pObj;
+			case NOT:
+				assert( pLtlNode->left ); assert( pLtlNode->right == NULL ); 
+				leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left );
+				assert( leftAigObj );
+				pLtlNode->pObj = Aig_Not( leftAigObj );
+				return pLtlNode->pObj;
+			case GLOBALLY:
+			case EVENTUALLY:
+			case NEXT:
+			case UNTIL:
+				printf("\nAttempting to create circuit with missing AIG pointer in a TEMPORAL node: ABORTING!!\n");
+				exit(0);
+			default:
+				printf("\nSerious ERROR: attempting to create AIG node from a temporal node\n");
+				exit(0);
+		}
+	}
+}
+
+int isNonTemporalSubformula( ltlNode *topNode )
+{
+	switch( topNode->type ){
+		case AND:
+		case OR:
+		case IMPLY:
+			return isNonTemporalSubformula( topNode->left) && isNonTemporalSubformula( topNode->right ) ;
+		case NOT:
+			assert( topNode->right == NULL );
+			return isNonTemporalSubformula( topNode->left );
+		case BOOL:
+			return 1;
+		default:
+			return 0;
+	}
+}
+
+int isWellFormed( ltlNode *topNode )
+{
+	ltlNode *nextNode;
+
+	switch( topNode->type ){
+		case AND:
+		case OR:
+		case IMPLY:
+			return isWellFormed( topNode->left) && isWellFormed( topNode->right ) ;
+		case NOT:
+			assert( topNode->right == NULL );
+			return isWellFormed( topNode->left );
+		case BOOL:
+			return 1;
+		case GLOBALLY:
+			nextNode = topNode->left;
+			assert( topNode->right == NULL );
+			if( nextNode->type != EVENTUALLY )
+				return 0;
+			else
+			{
+				assert( nextNode->right == NULL );
+				return isNonTemporalSubformula( nextNode->left );
+			}
+		default:
+			return 0;
+	}
+}
+
+int checkBooleanConstant( char *targetName )
+{
+	if( strcmp( targetName, "true" ) == 0 ) 
+		return 1;
+	if( strcmp( targetName, "false" ) == 0 )
+		return 0;
+	return -1;
+}
+
+int checkSignalNameExistence( Abc_Ntk_t *pNtk, ltlNode *topASTNode )
+{
+	char *targetName;
+	Abc_Obj_t * pNode;
+	int i;
+		
+	switch( topASTNode->type ){
+		case BOOL:
+			targetName = topASTNode->name;
+			//printf("\nTrying to match name %s\n", targetName);
+			if( checkBooleanConstant( targetName ) != -1 )
+				return 1;
+			Abc_NtkForEachPo( pNtk, pNode, i )
+			{
+				if( strcmp( Abc_ObjName( pNode ), targetName ) == 0 )
+				{
+					//printf("\nVariable name \"%s\" MATCHED\n", targetName);
+					return 1;
+				}
+			}
+			printf("\nVariable name \"%s\" not found in the PO name list\n", targetName);
+			return 0;
+		case AND:
+		case OR:
+		case IMPLY:
+		case UNTIL:
+			assert( topASTNode->left != NULL );
+			assert( topASTNode->right != NULL );
+			return checkSignalNameExistence( pNtk, topASTNode->left ) && checkSignalNameExistence( pNtk, topASTNode->right );
+			
+		case NOT:
+		case NEXT:
+		case GLOBALLY:
+		case EVENTUALLY:
+			assert( topASTNode->left != NULL );
+			assert( topASTNode->right == NULL );
+			return checkSignalNameExistence( pNtk, topASTNode->left );
+		default:
+			printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n");
+			exit(0);
+	}
+}
+
+void populateBoolWithAigNodePtr( Abc_Ntk_t *pNtk, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, ltlNode *topASTNode )
+{
+	char *targetName;
+	Abc_Obj_t * pNode;
+	int i;
+	Aig_Obj_t *pObj, *pDriverImage;
+	
+	switch( topASTNode->type ){
+		case BOOL:
+			targetName = topASTNode->name;
+			if( checkBooleanConstant( targetName ) == 1 )
+			{
+				topASTNode->pObj = Aig_ManConst1( pAigNew );
+				return;
+			}
+			if( checkBooleanConstant( targetName ) == 0 )
+			{
+				topASTNode->pObj = Aig_Not(topASTNode->pObj = Aig_ManConst1( pAigNew ));
+				return;
+			}
+			Abc_NtkForEachPo( pNtk, pNode, i )
+				if( strcmp( Abc_ObjName( pNode ), targetName ) == 0 )
+				{
+					pObj = Aig_ManCo( pAigOld, i );
+					assert( Aig_ObjIsCo( pObj ));
+					pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+					topASTNode->pObj = pDriverImage;
+					return;
+				}
+			assert(0);
+		case AND:
+		case OR:
+		case IMPLY:
+		case UNTIL:
+			assert( topASTNode->left != NULL );
+			assert( topASTNode->right != NULL );
+			populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->left );
+			populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->right );
+			return;
+		case NOT:
+		case NEXT:
+		case GLOBALLY:
+		case EVENTUALLY:
+			assert( topASTNode->left != NULL );
+			assert( topASTNode->right == NULL );
+			populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->left );
+			return;
+		default:
+			printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n");
+			exit(0);
+	}
+}
+
+int checkAllBoolHaveAIGPointer( ltlNode *topASTNode )
+{
+	
+	switch( topASTNode->type ){
+		case BOOL:
+			if( topASTNode->pObj != NULL )
+				return 1;
+			else
+			{
+				printf("\nfaulting PODMANDYO topASTNode->name = %s\n", topASTNode->name);
+				return 0;
+			}
+		case AND:
+		case OR:
+		case IMPLY:
+		case UNTIL:
+			assert( topASTNode->left != NULL );
+			assert( topASTNode->right != NULL );
+			return checkAllBoolHaveAIGPointer( topASTNode->left ) && checkAllBoolHaveAIGPointer( topASTNode->right );
+			
+		case NOT:
+		case NEXT:
+		case GLOBALLY:
+		case EVENTUALLY:
+			assert( topASTNode->left != NULL );
+			assert( topASTNode->right == NULL );
+			return checkAllBoolHaveAIGPointer( topASTNode->left );
+		default:
+			printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n");
+			exit(0);
+	}
+}
+
+void setAIGNodePtrOfGloballyNode( ltlNode *astNode, Aig_Obj_t *pObjLo )
+{
+	astNode->pObj = pObjLo;
+}
+			
+Aig_Obj_t *retriveAIGPointerFromLTLNode( ltlNode *astNode )
+{
+	return astNode->pObj;
+}
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/live/module.make b/abc-build/src/proof/live/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/live/module.make
@@ -0,0 +1,9 @@
+SRC +=  src/proof/live/liveness.c \
+	src/proof/live/liveness_sim.c \
+	src/proof/live/ltl_parser.c \
+	src/proof/live/kliveness.c \
+	src/proof/live/monotone.c \
+	src/proof/live/disjunctiveMonotone.c \
+	src/proof/live/arenaViolation.c \
+	src/proof/live/kLiveConstraints.c \
+	src/proof/live/combination.c
diff --git a/abc-build/src/proof/live/monotone.c b/abc-build/src/proof/live/monotone.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/live/monotone.c
@@ -0,0 +1,507 @@
+/**CFile****************************************************************
+
+  FileName    [kLiveConstraints.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Liveness property checking.]
+
+  Synopsis    [Constraint analysis module for the k-Liveness algorithm
+		invented by Koen Classen, Niklas Sorensson.]
+
+  Author      [Sayak Ray]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 31, 2012.]
+
+  Revision    [$Id: liveness.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include "base/main/main.h"
+#include "aig/aig/aig.h"
+#include "aig/saig/saig.h"
+#include <string.h>
+#include "base/main/mainInt.h"
+#include "proof/pdr/pdr.h"
+
+ABC_NAMESPACE_IMPL_START
+
+extern Aig_Man_t *Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+//extern Aig_Man_t *createDisjunctiveMonotoneTester(Aig_Man_t *pAig, struct aigPoIndices *aigPoIndicesArg, struct monotoneVectorsStruct *monotoneVectorArg, int *startMonotonePropPo);
+
+struct aigPoIndices
+{
+	int attrPendingSignalIndex;
+	int attrHintSingalBeginningMarker;
+	int attrHintSingalEndMarker;
+	int attrSafetyInvarIndex;
+};
+
+struct aigPoIndices *allocAigPoIndices()
+{
+	struct aigPoIndices *newAigPoIndices;
+
+	newAigPoIndices = (struct aigPoIndices *)malloc(sizeof (struct aigPoIndices));
+	newAigPoIndices->attrPendingSignalIndex = -1;
+	newAigPoIndices->attrHintSingalBeginningMarker = -1;
+	newAigPoIndices->attrHintSingalEndMarker = -1;
+	newAigPoIndices->attrSafetyInvarIndex = -1;
+
+	assert( newAigPoIndices != NULL );
+	return newAigPoIndices;
+}
+
+void deallocAigPoIndices(struct aigPoIndices *toBeDeletedAigPoIndices)
+{
+	assert(toBeDeletedAigPoIndices != NULL );
+	free(toBeDeletedAigPoIndices);
+}
+
+struct monotoneVectorsStruct
+{
+	Vec_Int_t *attrKnownMonotone;
+	Vec_Int_t *attrCandMonotone;
+	Vec_Int_t *attrHintMonotone;
+};
+
+struct monotoneVectorsStruct *allocPointersToMonotoneVectors()
+{
+	struct monotoneVectorsStruct *newPointersToMonotoneVectors;
+
+	newPointersToMonotoneVectors = (struct monotoneVectorsStruct *)malloc(sizeof (struct monotoneVectorsStruct));
+
+	newPointersToMonotoneVectors->attrKnownMonotone = NULL;
+	newPointersToMonotoneVectors->attrCandMonotone = NULL;
+	newPointersToMonotoneVectors->attrHintMonotone = NULL;
+		
+	assert( newPointersToMonotoneVectors != NULL );
+	return newPointersToMonotoneVectors;
+}
+
+void deallocPointersToMonotoneVectors(struct monotoneVectorsStruct *toBeDeleted)
+{
+	assert( toBeDeleted != NULL );
+	free( toBeDeleted );
+}
+
+Vec_Int_t *findHintOutputs(Abc_Ntk_t *pNtk)
+{
+	int i, numElementPush = 0;
+	Abc_Obj_t *pNode;
+	Vec_Int_t *vHintPoIntdex;
+
+	vHintPoIntdex = Vec_IntAlloc(0);
+	Abc_NtkForEachPo( pNtk, pNode, i )
+	{
+		if( strstr( Abc_ObjName( pNode ), "hint_" ) != NULL )
+		{
+			Vec_IntPush( vHintPoIntdex, i );
+			numElementPush++;
+		}
+	}	
+	
+	if( numElementPush == 0 )
+		return NULL;
+	else
+		return vHintPoIntdex;
+}
+
+int findPendingSignal(Abc_Ntk_t *pNtk)
+{
+	int i, pendingSignalIndex = -1;
+	Abc_Obj_t *pNode;
+
+	Abc_NtkForEachPo( pNtk, pNode, i )
+	{
+		if( strstr( Abc_ObjName( pNode ), "pendingSignal" ) != NULL )
+		{
+			pendingSignalIndex = i;
+			break;
+		}
+	}	
+	
+	return pendingSignalIndex;
+}
+
+int checkSanityOfKnownMonotone( Vec_Int_t *vKnownMonotone, Vec_Int_t *vCandMonotone, Vec_Int_t *vHintMonotone )
+{
+	int iElem, i;
+
+	Vec_IntForEachEntry( vKnownMonotone, iElem, i )
+		printf("%d ", iElem);
+	printf("\n");
+	Vec_IntForEachEntry( vCandMonotone, iElem, i )
+		printf("%d ", iElem);
+	printf("\n");
+	Vec_IntForEachEntry( vHintMonotone, iElem, i )
+		printf("%d ", iElem);
+	printf("\n");
+	return 1;
+}
+
+Aig_Man_t *createMonotoneTester(Aig_Man_t *pAig, struct aigPoIndices *aigPoIndicesArg, struct monotoneVectorsStruct *monotoneVectorArg, int *startMonotonePropPo)
+{
+	Aig_Man_t *pNewAig;
+	int iElem, i, nRegCount, oldPoNum, poSerialNum, iElemHint;
+	int piCopied = 0, liCopied = 0, liCreated = 0, loCopied = 0, loCreated = 0;
+	int poCopied = 0, poCreated = 0;
+	Aig_Obj_t *pObj, *pObjPo, *pObjDriver, *pObjDriverNew, *pObjPendingDriverNew, *pObjPendingAndNextPending;
+	Aig_Obj_t *pPendingFlop, *pHintSignalLo, *pHintMonotoneFlop, *pObjTemp1, *pObjTemp2, *pObjKnownMonotoneAnd;
+	Vec_Ptr_t *vHintMonotoneLocalDriverNew;
+	Vec_Ptr_t *vHintMonotoneLocalFlopOutput;
+	Vec_Ptr_t *vHintMonotoneLocalProp;
+
+	int pendingSignalIndexLocal = aigPoIndicesArg->attrPendingSignalIndex;
+	int hintSingalBeginningMarkerLocal = aigPoIndicesArg->attrHintSingalBeginningMarker;
+	//int hintSingalEndMarkerLocal = aigPoIndicesArg->attrHintSingalEndMarker;
+
+	Vec_Int_t *vKnownMonotoneLocal = monotoneVectorArg->attrKnownMonotone;
+	Vec_Int_t *vCandMonotoneLocal = monotoneVectorArg->attrCandMonotone;
+	Vec_Int_t *vHintMonotoneLocal = monotoneVectorArg->attrHintMonotone;
+	
+	//****************************************************************
+	// Step1: create the new manager
+	// Note: The new manager is created with "2 * Aig_ManObjNumMax(p)"
+	// nodes, but this selection is arbitrary - need to be justified
+	//****************************************************************
+	pNewAig = Aig_ManStart( Aig_ManObjNumMax(pAig) );
+	pNewAig->pName = (char *)malloc( strlen( pAig->pName ) + strlen("_monotone") + 1 );
+	sprintf(pNewAig->pName, "%s_%s", pAig->pName, "_monotone");
+    	pNewAig->pSpec = NULL;
+
+	//****************************************************************
+	// Step 2: map constant nodes
+	//****************************************************************
+    	pObj = Aig_ManConst1( pAig );
+    	pObj->pData = Aig_ManConst1( pNewAig );
+
+	//****************************************************************
+    	// Step 3: create true PIs
+	//****************************************************************
+    	Saig_ManForEachPi( pAig, pObj, i )
+	{
+		piCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNewAig);
+	}
+
+	//****************************************************************
+	// Step 5: create register outputs
+	//****************************************************************
+    	Saig_ManForEachLo( pAig, pObj, i )
+    	{
+		loCopied++;
+		pObj->pData = Aig_ObjCreateCi(pNewAig);
+    	}
+
+	//****************************************************************
+	// Step 6: create "D" register output for PENDING flop 
+	//****************************************************************
+	loCreated++;
+	pPendingFlop = Aig_ObjCreateCi( pNewAig );
+
+	//****************************************************************
+	// Step 6.a: create "D" register output for HINT_MONOTONE flop 
+	//****************************************************************
+	vHintMonotoneLocalFlopOutput = Vec_PtrAlloc(Vec_IntSize(vHintMonotoneLocal));
+	Vec_IntForEachEntry( vHintMonotoneLocal, iElem, i )
+	{
+		loCreated++;
+		pHintMonotoneFlop = Aig_ObjCreateCi( pNewAig );
+		Vec_PtrPush( vHintMonotoneLocalFlopOutput, pHintMonotoneFlop );
+	}
+
+	nRegCount = loCreated + loCopied;
+	printf("\nnRegCount = %d\n", nRegCount);
+
+	//********************************************************************
+	// Step 7: create internal nodes
+	//********************************************************************
+    	Aig_ManForEachNode( pAig, pObj, i )
+	{
+		pObj->pData = Aig_And( pNewAig, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+	}
+	
+	//********************************************************************
+	// Step 8: mapping appropriate new flop drivers 
+	//********************************************************************
+
+	pObjPo = Aig_ManCo( pAig, pendingSignalIndexLocal );
+	pObjDriver = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo));
+	pObjPendingDriverNew = !Aig_IsComplement(pObjDriver)? 
+				(Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData) : 
+				Aig_Not((Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData));
+
+	pObjPendingAndNextPending = Aig_And( pNewAig, pObjPendingDriverNew, pPendingFlop );
+
+	oldPoNum = Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig);
+	pObjKnownMonotoneAnd = Aig_ManConst1( pNewAig );
+	#if 1
+	if( vKnownMonotoneLocal )
+	{
+		assert( checkSanityOfKnownMonotone( vKnownMonotoneLocal, vCandMonotoneLocal, vHintMonotoneLocal ) );
+
+		Vec_IntForEachEntry( vKnownMonotoneLocal, iElemHint, i )
+		{
+			iElem = (iElemHint - hintSingalBeginningMarkerLocal) + 1 + pendingSignalIndexLocal;
+			printf("\nProcessing knownMonotone = %d\n", iElem);
+			pObjPo = Aig_ManCo( pAig, iElem );
+			pObjDriver = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo));
+			pObjDriverNew = !Aig_IsComplement(pObjDriver)? 
+					(Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData) : 
+					Aig_Not((Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData));
+			pHintSignalLo = (Aig_Obj_t *)Vec_PtrEntry(vHintMonotoneLocalFlopOutput, iElem - oldPoNum);
+			pObjTemp1 = Aig_Or( pNewAig, Aig_And(pNewAig, pObjDriverNew, pHintSignalLo), 
+						Aig_And(pNewAig, Aig_Not(pObjDriverNew), Aig_Not(pHintSignalLo)) );
+			
+			pObjKnownMonotoneAnd = Aig_And( pNewAig, pObjKnownMonotoneAnd, pObjTemp1 );
+		}
+		pObjPendingAndNextPending = Aig_And( pNewAig, pObjPendingAndNextPending, pObjKnownMonotoneAnd );
+	}
+	#endif
+
+	vHintMonotoneLocalDriverNew = Vec_PtrAlloc(Vec_IntSize(vHintMonotoneLocal));
+	vHintMonotoneLocalProp = Vec_PtrAlloc(Vec_IntSize(vHintMonotoneLocal));
+	Vec_IntForEachEntry( vHintMonotoneLocal, iElem, i )
+	{
+		pObjPo = Aig_ManCo( pAig, iElem );
+		pObjDriver = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo));
+		pObjDriverNew = !Aig_IsComplement(pObjDriver)? 
+				(Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData) : 
+				Aig_Not((Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData));
+
+		if( vKnownMonotoneLocal != NULL && Vec_IntFind( vKnownMonotoneLocal, iElem ) != -1 )
+		{
+			Vec_PtrPush(vHintMonotoneLocalDriverNew, pObjDriverNew);
+		}
+		else
+		{
+			poSerialNum = Vec_IntFind( vHintMonotoneLocal, iElem );
+			pHintSignalLo = (Aig_Obj_t *)Vec_PtrEntry(vHintMonotoneLocalFlopOutput, poSerialNum );
+			pObjTemp1 = Aig_And( pNewAig, pObjPendingAndNextPending, pHintSignalLo);
+			pObjTemp2 = Aig_Or( pNewAig, Aig_Not(pObjTemp1), pObjDriverNew );
+			//pObjTemp2 = Aig_Or( pNewAig, Aig_Not(pObjTemp1), Aig_ManConst1( pNewAig ));
+			//pObjTemp2 = Aig_ManConst1( pNewAig );
+			Vec_PtrPush(vHintMonotoneLocalDriverNew, pObjDriverNew);
+			Vec_PtrPush(vHintMonotoneLocalProp, pObjTemp2); 
+		}
+	}
+
+	//********************************************************************
+	// Step 9: create primary outputs 
+	//********************************************************************
+	Saig_ManForEachPo( pAig, pObj, i )
+	{
+		poCopied++;
+		pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); 
+	}
+
+	*startMonotonePropPo = i;
+	Vec_PtrForEachEntry( Aig_Obj_t *, vHintMonotoneLocalProp, pObj, i )
+	{
+		poCreated++;
+		pObjPo = Aig_ObjCreateCo( pNewAig, pObj ); 
+	}
+
+	//********************************************************************
+	// Step 9: create latch inputs 
+	//********************************************************************
+
+	Saig_ManForEachLi( pAig, pObj, i )
+	{
+		liCopied++;
+		Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) );
+	}
+	
+	//********************************************************************
+	// Step 9.a: create latch input for PENDING_FLOP
+	//********************************************************************
+
+	liCreated++;
+	Aig_ObjCreateCo( pNewAig, pObjPendingDriverNew );
+
+	//********************************************************************
+	// Step 9.b: create latch input for MONOTONE_FLOP
+	//********************************************************************
+
+	Vec_PtrForEachEntry( Aig_Obj_t *, vHintMonotoneLocalDriverNew, pObj, i )
+	{
+		liCreated++;
+		Aig_ObjCreateCo( pNewAig, pObj );
+	}
+
+	printf("\npoCopied = %d, poCreated = %d\n", poCopied, poCreated);
+	printf("\nliCreated++ = %d\n", liCreated );
+	Aig_ManSetRegNum( pNewAig, nRegCount );
+	Aig_ManCleanup( pNewAig );
+	
+	assert( Aig_ManCheck( pNewAig ) );
+	assert( loCopied + loCreated == liCopied + liCreated );
+
+	printf("\nSaig_ManPoNum = %d\n", Saig_ManPoNum(pNewAig));
+	return pNewAig;
+}
+
+
+Vec_Int_t *findNewMonotone( Aig_Man_t *pAig, struct aigPoIndices *aigPoIndicesArg, struct monotoneVectorsStruct *monotoneVectorArg )
+{
+	Aig_Man_t *pAigNew;
+	Aig_Obj_t *pObjTargetPo;
+	int poMarker, oldPoNum;
+	int i, RetValue;
+	Pdr_Par_t Pars, * pPars = &Pars;
+	Abc_Cex_t * pCex = NULL;
+	Vec_Int_t *vMonotoneIndex;
+
+	int pendingSignalIndexLocal = aigPoIndicesArg->attrPendingSignalIndex;
+	int hintSingalBeginningMarkerLocal = aigPoIndicesArg->attrHintSingalBeginningMarker;
+	//int hintSingalEndMarkerLocal = aigPoIndicesArg->attrHintSingalEndMarker;
+
+	//Vec_Int_t *vKnownMonotoneLocal = monotoneVectorArg->attrKnownMonotone;
+	//Vec_Int_t *vCandMonotoneLocal = monotoneVectorArg->attrCandMonotone;
+	//Vec_Int_t *vHintMonotoneLocal = monotoneVectorArg->attrHintMonotone;
+
+	pAigNew = createMonotoneTester(pAig, aigPoIndicesArg, monotoneVectorArg, &poMarker );
+	oldPoNum = Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig);
+
+	vMonotoneIndex = Vec_IntAlloc(0);
+	printf("\nSaig_ManPoNum(pAigNew) = %d, poMarker = %d\n", Saig_ManPoNum(pAigNew), poMarker);
+	for( i=poMarker; i<Saig_ManPoNum(pAigNew); i++ )
+	{
+		pObjTargetPo = Aig_ManCo( pAigNew, i );
+		Aig_ObjChild0Flip( pObjTargetPo );
+
+		Pdr_ManSetDefaultParams( pPars );
+		pCex = NULL;
+		pPars->fVerbose = 0;
+		//pPars->iOutput = i;
+		//RetValue = Pdr_ManSolve( pAigNew, pPars, &pCex );	
+		RetValue = Pdr_ManSolve( pAigNew, pPars );	
+		if( RetValue == 1 )
+		{
+			printf("\ni = %d, RetValue = %d : %s (Frame %d)\n", i - oldPoNum + hintSingalBeginningMarkerLocal, RetValue, "Property Proved", pCex? (pCex)->iFrame : -1 );
+			Vec_IntPush( vMonotoneIndex, i - (pendingSignalIndexLocal + 1) + hintSingalBeginningMarkerLocal);
+		}
+		Aig_ObjChild0Flip( pObjTargetPo );
+	}
+	
+	if( Vec_IntSize( vMonotoneIndex ) > 0 )
+		return vMonotoneIndex;
+	else
+		return NULL;
+}
+
+Vec_Int_t *findRemainingMonotoneCandidates(Vec_Int_t *vKnownMonotone, Vec_Int_t *vHintMonotone)
+{
+	Vec_Int_t *vCandMonotone;
+	int iElem, i;
+
+	if( vKnownMonotone == NULL || Vec_IntSize(vKnownMonotone) <= 0 )
+		return vHintMonotone;
+	vCandMonotone = Vec_IntAlloc(0);
+	Vec_IntForEachEntry( vHintMonotone, iElem, i )
+	{
+		if( Vec_IntFind( vKnownMonotone, iElem ) == -1 )
+			Vec_IntPush( vCandMonotone, iElem );
+	}
+	
+	return vCandMonotone;
+}
+
+Vec_Int_t *findMonotoneSignals( Abc_Ntk_t *pNtk )
+{
+	Aig_Man_t *pAig;
+	Vec_Int_t *vCandidateMonotoneSignals;
+	Vec_Int_t *vKnownMonotoneSignals;
+	//Vec_Int_t *vKnownMonotoneSignalsNew;
+	//Vec_Int_t *vRemainingCanMonotone;
+	int i, iElem;
+	int pendingSignalIndex;
+	Abc_Ntk_t *pNtkTemp;
+	int hintSingalBeginningMarker;
+	int hintSingalEndMarker;
+	struct aigPoIndices *aigPoIndicesInstance;
+	struct monotoneVectorsStruct *monotoneVectorsInstance;
+	
+	/*******************************************/	
+	//Finding the PO index of the pending signal 
+	/*******************************************/	
+	pendingSignalIndex = findPendingSignal(pNtk);
+	if( pendingSignalIndex == -1 )
+	{
+		printf("\nNo Pending Signal Found\n");
+		return NULL;
+	}
+	else
+		printf("Po[%d] = %s\n", pendingSignalIndex, Abc_ObjName( Abc_NtkPo(pNtk, pendingSignalIndex) ) );
+
+	/*******************************************/	
+	//Finding the PO indices of all hint signals
+	/*******************************************/	
+	vCandidateMonotoneSignals = findHintOutputs(pNtk);
+	if( vCandidateMonotoneSignals == NULL )
+		return NULL;
+	else
+	{
+		Vec_IntForEachEntry( vCandidateMonotoneSignals, iElem, i )
+			printf("Po[%d] = %s\n", iElem, Abc_ObjName( Abc_NtkPo(pNtk, iElem) ) );
+		hintSingalBeginningMarker = Vec_IntEntry( vCandidateMonotoneSignals, 0 );
+		hintSingalEndMarker = Vec_IntEntry( vCandidateMonotoneSignals, Vec_IntSize(vCandidateMonotoneSignals) - 1 );
+	}
+
+	/**********************************************/
+	//Allocating "struct" with necessary parameters
+	/**********************************************/
+	aigPoIndicesInstance = allocAigPoIndices();
+	aigPoIndicesInstance->attrPendingSignalIndex = pendingSignalIndex;
+	aigPoIndicesInstance->attrHintSingalBeginningMarker = hintSingalBeginningMarker;
+	aigPoIndicesInstance->attrHintSingalEndMarker = hintSingalEndMarker;
+
+	/****************************************************/
+	//Allocating "struct" with necessary monotone vectors
+	/****************************************************/
+	monotoneVectorsInstance = allocPointersToMonotoneVectors();
+	monotoneVectorsInstance->attrCandMonotone = vCandidateMonotoneSignals;
+	monotoneVectorsInstance->attrHintMonotone = vCandidateMonotoneSignals;
+
+	/*******************************************/	
+	//Generate AIG from Ntk
+	/*******************************************/	
+	if( !Abc_NtkIsStrash( pNtk ) )
+	{
+		pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+		pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
+	}
+	else
+	{
+		pAig = Abc_NtkToDar( pNtk, 0, 1 );
+		pNtkTemp = pNtk;
+	}
+
+	/*******************************************/	
+	//finding LEVEL 1 monotone signals
+	/*******************************************/	
+	vKnownMonotoneSignals = findNewMonotone( pAig, aigPoIndicesInstance, monotoneVectorsInstance );
+	monotoneVectorsInstance->attrKnownMonotone = vKnownMonotoneSignals;
+
+	/*******************************************/	
+	//finding LEVEL >1 monotone signals
+	/*******************************************/	
+	#if 0
+	if( vKnownMonotoneSignals )
+	{
+		printf("\nsize = %d\n", Vec_IntSize(vKnownMonotoneSignals) );
+		vRemainingCanMonotone = findRemainingMonotoneCandidates(vKnownMonotoneSignals, vCandidateMonotoneSignals);
+		monotoneVectorsInstance->attrCandMonotone = vRemainingCanMonotone; 
+		vKnownMonotoneSignalsNew = findNewMonotone( pAig, aigPoIndicesInstance, monotoneVectorsInstance );
+	}
+	#endif 
+
+	deallocAigPoIndices(aigPoIndicesInstance);
+	deallocPointersToMonotoneVectors(monotoneVectorsInstance);
+	return NULL;
+}
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/llb/llb.c b/abc-build/src/proof/llb/llb.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb.c
@@ -0,0 +1,52 @@
+/**CFile****************************************************************
+
+  FileName    [llb.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb.h b/abc-build/src/proof/llb/llb.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb.h
@@ -0,0 +1,96 @@
+/**CFile****************************************************************
+
+  FileName    [llb.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD-based reachability.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 8, 2010.]
+
+  Revision    [$Id: llb.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__llb__llb_h
+#define ABC__aig__llb__llb_h
+
+ 
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+  
+typedef struct Gia_ParLlb_t_ Gia_ParLlb_t;
+struct Gia_ParLlb_t_
+{
+    int         nBddMax;       // maximum BDD size
+    int         nIterMax;      // maximum iteration count
+    int         nClusterMax;   // maximum cluster size
+    int         nHintDepth;    // the number of times to cofactor
+    int         HintFirst;     // the number of first hint to use
+    int         fUseFlow;      // use flow computation
+    int         nVolumeMax;    // the largest volume
+    int         nVolumeMin;    // the smallest volume
+    int         nPartValue;    // partitioning value
+    int         fBackward;     // enable backward reachability
+    int         fReorder;      // enable dynamic variable reordering
+    int         fIndConstr;    // extract inductive constraints
+    int         fUsePivots;    // use internal pivot variables
+    int         fCluster;      // use partition clustering
+    int         fSchedule;     // use cluster scheduling
+    int         fDumpReached;  // dump reached states into a file
+    int         fVerbose;      // print verbose information
+    int         fVeryVerbose;  // print dependency matrices
+    int         fSilent;       // do not print any infomation
+    int         fSkipReach;    // skip reachability (preparation phase only)
+    int         fSkipOutCheck; // does not check the property output
+    int         TimeLimit;     // time limit for one reachability run
+    int         TimeLimitGlo;  // time limit for all reachability runs
+    // internal parameters
+    abctime     TimeTarget;    // the time to stop
+    int         iFrame;        // explored up to this frame
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== llbCore.c ==========================================================*/
+extern void     Llb_ManSetDefaultParams( Gia_ParLlb_t * pPars );
+/*=== llb4Nonlin.c ==========================================================*/
+extern int      Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/llb/llb1Cluster.c b/abc-build/src/proof/llb/llb1Cluster.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb1Cluster.c
@@ -0,0 +1,356 @@
+/**CFile****************************************************************
+
+  FileName    [llb1Cluster.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Clustering algorithm.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+ 
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb1Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManComputeCommonQuant( Llb_Mtr_t * p, int iCol1, int iCol2 )
+{
+    int iVar, Weight = 0;
+    for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ )
+    {
+        // count each removed variable as 2
+        if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 && p->pRowSums[iVar] == 2 )
+            Weight += 2;
+        // count each added variale as -1
+        else if ( (p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 0) || 
+                  (p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 1) )
+            Weight--;
+    }
+    return Weight;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManComputeBestQuant( Llb_Mtr_t * p )
+{
+    int i, k, WeightBest = -100000, WeightCur, RetValue = -1;
+    for ( i = 1; i < p->nCols-1; i++ )
+    for ( k = i+1; k < p->nCols-1; k++ )
+    {
+        if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax )
+            continue;
+        if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax )
+            continue;
+
+        WeightCur = Llb_ManComputeCommonQuant( p, i, k );
+        if ( WeightCur <= 0 )
+            continue;
+        if ( WeightBest < WeightCur )
+        {
+            WeightBest = WeightCur;
+            RetValue   = (i << 16) | k;
+        }
+    }
+//    printf( "Choosing best quant Weight %4d\n", WeightCur );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float ** Llb_ManComputeQuant( Llb_Mtr_t * p )
+{
+    float ** pCosts;
+    int i, k;
+    // alloc and clean
+    pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) );
+    for ( i = 0; i < p->nCols; i++ )
+    for ( k = 0; k < p->nCols; k++ )
+        pCosts[i][i] = 0.0;
+    // fill up
+    for ( i = 1; i < p->nCols-1; i++ )
+    for ( k = i+1; k < p->nCols-1; k++ )
+        pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonQuant( p, i, k );
+    return pCosts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Llb_ManComputeCommonAttr( Llb_Mtr_t * p, int iCol1, int iCol2 )
+{
+    int iVar, CountComm = 0, CountDiff = 0;
+    for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ )
+    {
+        if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 )
+            CountComm++;
+        else if ( p->pMatrix[iCol1][iVar] == 1 || p->pMatrix[iCol2][iVar] == 1 )
+            CountDiff++;
+    }
+/*
+    printf( "Attr cost for %4d and %4d:  %4d %4d (%5.2f)\n", 
+        iCol1, iCol2, 
+        CountDiff, CountComm, 
+        -1.0 * CountDiff / ( CountComm + CountDiff ) );
+*/
+    return -1.0 * CountDiff / ( CountComm + CountDiff );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManComputeBestAttr( Llb_Mtr_t * p )
+{
+    float WeightBest = -100000, WeightCur;
+    int i, k, RetValue = -1;
+    for ( i = 1; i < p->nCols-1; i++ )
+    for ( k = i+1; k < p->nCols-1; k++ )
+    {
+        if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax )
+            continue;
+        if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax )
+            continue;
+        WeightCur = Llb_ManComputeCommonAttr( p, i, k );
+        if ( WeightBest < WeightCur )
+        {
+            WeightBest = WeightCur;
+            RetValue   = (i << 16) | k;
+        }
+    }
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float ** Llb_ManComputeAttr( Llb_Mtr_t * p )
+{
+    float ** pCosts;
+    int i, k;
+    // alloc and clean
+    pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) );
+    for ( i = 0; i < p->nCols; i++ )
+    for ( k = 0; k < p->nCols; k++ )
+        pCosts[i][i] = 0.0;
+    // fill up
+    for ( i = 1; i < p->nCols-1; i++ )
+    for ( k = i+1; k < p->nCols-1; k++ )
+        pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonAttr( p, i, k );
+    return pCosts;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of variables that will be saved.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_MtrCombineSelectedColumns( Llb_Mtr_t * p, int iGrp1, int iGrp2 )
+{
+    int iVar;
+    assert( iGrp1 >= 1 && iGrp1 < p->nCols - 1 );
+    assert( iGrp2 >= 1 && iGrp2 < p->nCols - 1 );
+    assert( p->pColGrps[iGrp1] != NULL );
+    assert( p->pColGrps[iGrp2] != NULL );
+    for ( iVar = 0; iVar < p->nRows; iVar++ )
+    {
+        if ( p->pMatrix[iGrp1][iVar] == 1 && p->pMatrix[iGrp2][iVar] == 1 )
+            p->pRowSums[iVar]--;
+        if ( p->pMatrix[iGrp1][iVar] == 0 && p->pMatrix[iGrp2][iVar] == 1 )
+        {
+            p->pMatrix[iGrp1][iVar] = 1;
+            p->pColSums[iGrp1]++;
+        }
+        if ( p->pMatrix[iGrp2][iVar] == 1 )
+            p->pMatrix[iGrp2][iVar] = 0;
+    }
+    p->pColSums[iGrp2] = 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Combines one pair of columns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManClusterOne( Llb_Mtr_t * p, int iCol1, int iCol2 )
+{
+    int fVerbose = 0;
+    Llb_Grp_t * pGrp;
+    int iVar;
+
+    if ( fVerbose )
+    {
+        printf( "Combining %d and %d\n", iCol1, iCol2 );
+        for ( iVar = 0; iVar < p->nRows; iVar++ )
+        {
+            if ( p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 0 )
+                continue;
+            printf( "%3d : %c%c\n", iVar, 
+                p->pMatrix[iCol1][iVar]? '*':' ', 
+                p->pMatrix[iCol2][iVar]? '*':' ' );
+        }
+    }
+    pGrp = Llb_ManGroupsCombine( p->pColGrps[iCol1], p->pColGrps[iCol2] );
+    Llb_MtrCombineSelectedColumns( p, iCol1, iCol2 );
+    p->pColGrps[iCol1] = pGrp;
+    p->pColGrps[iCol2] = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes empty columns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManClusterCompress( Llb_Mtr_t * p )
+{
+    int i, k = 0;
+    for ( i = 0; i < p->nCols; i++ )
+    {
+        if ( p->pColGrps[i] == NULL )
+        {
+            assert( p->pColSums[i] == 0 );
+            assert( p->pMatrix[i] != NULL );
+            ABC_FREE( p->pMatrix[i] );
+            continue;
+        }
+        p->pMatrix[k]  = p->pMatrix[i];
+        p->pColGrps[k] = p->pColGrps[i];
+        p->pColSums[k] = p->pColSums[i];
+        k++;
+    }
+    p->nCols = k;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Combines one pair of columns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManCluster( Llb_Mtr_t * p )
+{
+    int RetValue;
+    do
+    {
+        do {
+            RetValue = Llb_ManComputeBestQuant( p );
+            if ( RetValue > 0 )
+                Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff );
+        }
+        while ( RetValue > 0 );
+
+        RetValue = Llb_ManComputeBestAttr( p );
+        if ( RetValue > 0 )
+            Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff );
+
+        Llb_MtrVerifyMatrix( p );
+    }
+    while ( RetValue > 0 );
+
+    Llb_ManClusterCompress( p );
+
+    Llb_MtrVerifyMatrix( p );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb1Constr.c b/abc-build/src/proof/llb/llb1Constr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb1Constr.c
@@ -0,0 +1,313 @@
+/**CFile****************************************************************
+
+  FileName    [llb1Constr.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Computing inductive constraints.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb1Constr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of constraint candidates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManCountEntries( Vec_Int_t * vCands )
+{
+    int i, Entry, Counter = 0;
+    Vec_IntForEachEntry( vCands, Entry, i )
+        Counter += ((Entry == 0) || (Entry == 1));
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of constraint candidates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands )
+{
+    int i, Entry;
+    if ( vCands == NULL )
+    {
+        printf( "There is no hints.\n" );
+        return;
+    }
+    Entry = Llb_ManCountEntries(vCands);
+    printf( "\n*** Using %d hint%s:\n", Entry, (Entry != 1 ? "s":"") );
+    Vec_IntForEachEntry( vCands, Entry, i )
+    {
+        if ( Entry != 0 && Entry != 1 )
+            continue;
+        printf( "%c", Entry ? '+' : '-' );
+        printf( "%-6d : ", i );
+        Aig_ObjPrint( p, Aig_ManObj(p, i) );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dereference BDD nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManDerefenceBdds( Aig_Man_t * p, DdManager * dd )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachObj( p, pObj, i )
+        Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of constraint candidates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_ManComputeIndCase_rec( Aig_Man_t * p, Aig_Obj_t * pObj, DdManager * dd, Vec_Ptr_t * vBdds )
+{
+    DdNode * bBdd0, * bBdd1;
+    DdNode * bFunc = (DdNode *)Vec_PtrEntry( vBdds, Aig_ObjId(pObj) );
+    if ( bFunc != NULL )
+        return bFunc;
+    assert( Aig_ObjIsNode(pObj) );
+    bBdd0 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin0(pObj), dd, vBdds ); 
+    bBdd1 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin1(pObj), dd, vBdds ); 
+    bBdd0 = Cudd_NotCond( bBdd0, Aig_ObjFaninC0(pObj) );
+    bBdd1 = Cudd_NotCond( bBdd1, Aig_ObjFaninC1(pObj) );
+    bFunc = Cudd_bddAnd( dd, bBdd0, bBdd1 );  Cudd_Ref( bFunc );
+    Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc );
+    return bFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of constraint candidates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManComputeIndCase( Aig_Man_t * p, DdManager * dd, Vec_Int_t * vNodes )
+{
+    Vec_Ptr_t * vBdds;
+    Aig_Obj_t * pObj;
+    DdNode * bFunc;
+    int i, Entry;
+    vBdds = Vec_PtrStart( Aig_ManObjNumMax(p) );
+    bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc );
+    Vec_PtrWriteEntry( vBdds, Aig_ObjId(Aig_ManConst1(p)), bFunc );
+    Saig_ManForEachPi( p, pObj, i )
+    {
+        bFunc = Cudd_bddIthVar( dd, Aig_ManCiNum(p) + i );  Cudd_Ref( bFunc );
+        Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc );
+    }
+    Saig_ManForEachLi( p, pObj, i )
+    {
+        bFunc = (DdNode *)pObj->pData;  Cudd_Ref( bFunc );
+        Vec_PtrWriteEntry( vBdds, Aig_ObjId(Saig_ObjLiToLo(p, pObj)), bFunc );
+    }
+    Vec_IntForEachEntry( vNodes, Entry, i )
+    { 
+        if ( Entry != 0 && Entry != 1 )
+            continue;
+        pObj = Aig_ManObj( p, i );
+        bFunc = Llb_ManComputeIndCase_rec( p, pObj, dd, vBdds );
+        if ( Entry == 0 )
+        {
+//            Extra_bddPrint( dd, Cudd_Not(pObj->pData) );  printf( "\n" );
+//            Extra_bddPrint( dd, Cudd_Not(bFunc) );        printf( "\n" );
+            if ( !Cudd_bddLeq( dd, Cudd_Not(pObj->pData), Cudd_Not(bFunc) ) )
+                Vec_IntWriteEntry( vNodes, i, -1 );
+        }
+        else if ( Entry == 1 )
+        {
+//            Extra_bddPrint( dd, pObj->pData );  printf( "\n" );
+//            Extra_bddPrint( dd, bFunc );        printf( "\n" );
+            if ( !Cudd_bddLeq( dd, (DdNode *)pObj->pData, bFunc ) )
+                Vec_IntWriteEntry( vNodes, i, -1 );
+        }
+    }
+    Vec_PtrForEachEntry( DdNode *, vBdds, bFunc, i )
+        if ( bFunc )
+            Cudd_RecursiveDeref( dd, bFunc );
+    Vec_PtrFree( vBdds );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of constraint candidates.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Llb_ManComputeBaseCase( Aig_Man_t * p, DdManager * dd )
+{
+    Vec_Int_t * vNodes;
+    Aig_Obj_t * pObj, * pRoot;
+    int i;
+    pRoot = Aig_ManCo( p, 0 );
+    vNodes = Vec_IntStartFull( Aig_ManObjNumMax(p) );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
+            continue;
+        if ( Cudd_bddLeq( dd, (DdNode *)pObj->pData, Cudd_Not(pRoot->pData) ) )
+            Vec_IntWriteEntry( vNodes, i, 1 );
+        else if ( Cudd_bddLeq( dd, Cudd_Not((DdNode *)pObj->pData), Cudd_Not(pRoot->pData) ) )
+            Vec_IntWriteEntry( vNodes, i, 0 );
+    }
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs global BDDs for each object in the AIG manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdManager * Llb_ManConstructGlobalBdds( Aig_Man_t * p )
+{
+    DdManager * dd;
+    DdNode * bBdd0, * bBdd1;
+    Aig_Obj_t * pObj;
+    int i;
+    dd = Cudd_Init( Aig_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    Cudd_AutodynEnable( dd,  CUDD_REORDER_SYMM_SIFT );
+    pObj = Aig_ManConst1(p);
+    pObj->pData = Cudd_ReadOne(dd);  Cudd_Ref( (DdNode *)pObj->pData );
+    Aig_ManForEachCi( p, pObj, i )
+    {
+        pObj->pData = Cudd_bddIthVar(dd, i);  Cudd_Ref( (DdNode *)pObj->pData );
+    }
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+        bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+        pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 );   Cudd_Ref( (DdNode *)pObj->pData );
+    }
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        pObj->pData = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );  Cudd_Ref( (DdNode *)pObj->pData );
+    }
+    return dd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives inductive constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p )
+{
+    DdManager * dd;
+    Vec_Int_t * vNodes;
+    if ( Saig_ManPoNum(p) != 1 )
+    {
+        printf( "The AIG has %d property outputs.\n", Saig_ManPoNum(p) );
+        return NULL;
+    }
+    assert( Saig_ManPoNum(p) == 1 );
+    dd = Llb_ManConstructGlobalBdds( p );
+    vNodes = Llb_ManComputeBaseCase( p, dd );
+    if ( Llb_ManCountEntries(vNodes) > 0 )
+        Llb_ManComputeIndCase( p, dd, vNodes );
+    if ( Llb_ManCountEntries(vNodes) == 0 )
+        Vec_IntFreeP( &vNodes );
+    Llb_ManDerefenceBdds( p, dd );
+    Extra_StopManager( dd );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tests derived constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManConstrTest( Aig_Man_t * p )
+{
+    Vec_Int_t * vNodes;
+    vNodes = Llb_ManDeriveConstraints( p );
+    Llb_ManPrintEntries( p, vNodes );
+    Vec_IntFreeP( &vNodes );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb1Core.c b/abc-build/src/proof/llb/llb1Core.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb1Core.c
@@ -0,0 +1,222 @@
+/**CFile****************************************************************
+
+  FileName    [llb1Core.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Top-level procedure.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb1Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+#include "aig/gia/gia.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManSetDefaultParams( Gia_ParLlb_t * p )
+{
+    memset( p, 0, sizeof(Gia_ParLlb_t) );
+    p->nBddMax       = 10000000;
+    p->nIterMax      = 10000000;
+    p->nClusterMax   =       20;
+    p->nHintDepth    =        0;
+    p->HintFirst     =        0;
+    p->fUseFlow      =        0;  // use flow 
+    p->nVolumeMax    =      100;  // max volume
+    p->nVolumeMin    =       30;  // min volume
+    p->nPartValue    =        5;  // partitioning value
+    p->fBackward     =        0;  // forward by default
+    p->fReorder      =        1;
+    p->fIndConstr    =        0;
+    p->fUsePivots    =        0;
+    p->fCluster      =        0;
+    p->fSchedule     =        0;
+    p->fDumpReached  =        0;
+    p->fVerbose      =        0;
+    p->fVeryVerbose  =        0;
+    p->fSilent       =        0;
+    p->TimeLimit     =        0;
+//    p->TimeLimit     =        0;
+    p->TimeLimitGlo  =        0;
+    p->TimeTarget    =        0;
+    p->iFrame        =       -1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints statistics about MFFCs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManPrintAig( Llb_Man_t * p )
+{
+    Abc_Print( 1, "pi =%3d  ",    Saig_ManPiNum(p->pAig) );
+    Abc_Print( 1, "po =%3d  ",    Saig_ManPoNum(p->pAig) );
+    Abc_Print( 1, "ff =%3d  ",    Saig_ManRegNum(p->pAig) );
+    Abc_Print( 1, "int =%5d  ",   Vec_IntSize(p->vVar2Obj)-Aig_ManCiNum(p->pAig)-Saig_ManRegNum(p->pAig) );
+    Abc_Print( 1, "var =%5d  ",   Vec_IntSize(p->vVar2Obj) );
+    Abc_Print( 1, "part =%5d  ",  Vec_PtrSize(p->vGroups)-2 );
+    Abc_Print( 1, "and =%5d  ",   Aig_ManNodeNum(p->pAig) );
+    Abc_Print( 1, "lev =%4d  ",   Aig_ManLevelNum(p->pAig) );
+//    Abc_Print( 1, "cut =%4d  ",   Llb_ManCrossCut(p->pAig) );
+    Abc_Print( 1, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo )
+{
+    Llb_Man_t * p = NULL; 
+    Aig_Man_t * pAig;
+    int RetValue = -1;
+    abctime clk = Abc_Clock();
+
+    if ( pPars->fIndConstr )
+    {
+        assert( vHints == NULL );
+        vHints = Llb_ManDeriveConstraints( pAigGlo );
+    }
+
+    // derive AIG for hints
+    if ( vHints == NULL )
+        pAig = Aig_ManDupSimple( pAigGlo );
+    else
+    {
+        if ( pPars->fVerbose )
+            Llb_ManPrintEntries( pAigGlo, vHints );
+        pAig = Aig_ManDupSimpleWithHints( pAigGlo, vHints );
+    }
+
+
+    if ( pPars->fUseFlow )
+    {
+//        p = Llb_ManStartFlow( pAigGlo, pAig, pPars );
+    }
+    else
+    {
+        p = Llb_ManStart( pAigGlo, pAig, pPars );
+        if ( pPars->fVerbose )
+        {
+            Llb_ManPrintAig( p );
+            printf( "Original matrix:          " );
+            Llb_MtrPrintMatrixStats( p->pMatrix );
+            if ( pPars->fVeryVerbose )
+                Llb_MtrPrint( p->pMatrix, 1 );
+        }
+        if ( pPars->fCluster )
+        {
+            Llb_ManCluster( p->pMatrix );
+            if ( pPars->fVerbose )
+            {
+                printf( "Matrix after clustering:  " );
+                Llb_MtrPrintMatrixStats( p->pMatrix );
+                if ( pPars->fVeryVerbose )
+                    Llb_MtrPrint( p->pMatrix, 1 );
+            }
+        }
+        if ( pPars->fSchedule )
+        {
+            Llb_MtrSchedule( p->pMatrix );
+            if ( pPars->fVerbose )
+            {
+                printf( "Matrix after scheduling:  " );
+                Llb_MtrPrintMatrixStats( p->pMatrix );
+                if ( pPars->fVeryVerbose )
+                    Llb_MtrPrint( p->pMatrix, 1 );
+            }
+        }
+    }
+    
+    if ( !p->pPars->fSkipReach ) 
+        RetValue = Llb_ManReachability( p, vHints, pddGlo );
+    Llb_ManStop( p );
+
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+
+    if ( pPars->fIndConstr )
+        Vec_IntFreeP( &vHints );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManModelCheckGia( Gia_Man_t * pGia, Gia_ParLlb_t * pPars )
+{
+    Gia_Man_t * pGia2;
+    Aig_Man_t * pAig;
+    int RetValue = -1;
+    pGia2 = Gia_ManDupDfs( pGia );
+    pAig  = Gia_ManToAigSimple( pGia2 );
+    Gia_ManStop( pGia2 );
+//Aig_ManShow( pAig, 0, NULL ); 
+
+    if ( pPars->nHintDepth == 0 )
+        RetValue = Llb_ManModelCheckAig( pAig, pPars, NULL, NULL );
+    else
+        RetValue = Llb_ManModelCheckAigWithHints( pAig, pPars );
+    pGia->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL;
+    Aig_ManStop( pAig );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb1Group.c b/abc-build/src/proof/llb/llb1Group.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb1Group.c
@@ -0,0 +1,474 @@
+/**CFile****************************************************************
+
+  FileName    [llb1Group.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Initial partition computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb1Group.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan )
+{
+    Llb_Grp_t * p;
+    p = ABC_CALLOC( Llb_Grp_t, 1 );
+    p->pMan   = pMan;
+    p->vIns   = Vec_PtrAlloc( 8 );
+    p->vOuts  = Vec_PtrAlloc( 8 );
+    p->Id     = Vec_PtrSize( pMan->vGroups );
+    Vec_PtrPush( pMan->vGroups, p );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManGroupStop( Llb_Grp_t * p )
+{
+    if ( p == NULL )
+        return;
+    Vec_PtrWriteEntry( p->pMan->vGroups, p->Id, NULL );
+    Vec_PtrFreeP( &p->vIns );
+    Vec_PtrFreeP( &p->vOuts );
+    Vec_PtrFreeP( &p->vNodes );
+    ABC_FREE( p );
+}
+
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManGroupCollect_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(pAig, pObj);
+    if ( Aig_ObjIsConst1(pObj) )
+        return;
+    if ( Aig_ObjIsCo(pObj) )
+    {
+        Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes );
+        return;
+    }
+    assert( Aig_ObjIsAnd(pObj) );
+    Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes );
+    Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin1(pObj), vNodes );
+    Vec_PtrPush( vNodes, pObj );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Collects the support of MFFC.]
+
+  Description [Returns the number of internal nodes in the MFFC.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManGroupCollect( Llb_Grp_t * pGroup )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i;
+    vNodes = Vec_PtrAlloc( 100 );
+    Aig_ManIncrementTravId( pGroup->pMan->pAig );
+    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+        Aig_ObjSetTravIdCurrent( pGroup->pMan->pAig, pObj );
+    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+        Aig_ObjSetTravIdPrevious( pGroup->pMan->pAig, pObj );
+    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+        Llb_ManGroupCollect_rec( pGroup->pMan->pAig, pObj, vNodes );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManGroupCreate_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vSupp )
+{ 
+    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(pAig, pObj);
+    if ( Aig_ObjIsConst1(pObj) )
+        return;
+    if ( pObj->fMarkA )
+    {
+        Vec_PtrPush( vSupp, pObj );
+        return;
+    }
+    assert( Aig_ObjIsAnd(pObj) );
+    Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin0(pObj), vSupp );
+    Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin1(pObj), vSupp );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupCreate( Llb_Man_t * pMan, Aig_Obj_t * pObj )
+{
+    Llb_Grp_t * p;
+    assert( pObj->fMarkA == 1 );
+    // derive group
+    p = Llb_ManGroupAlloc( pMan );
+    Vec_PtrPush( p->vOuts, pObj );
+    Aig_ManIncrementTravId( pMan->pAig );
+    if ( Aig_ObjIsCo(pObj) )
+        Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns );
+    else
+    {
+        Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns );
+        Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin1(pObj), p->vIns );
+    }
+    // derive internal objects
+    assert( p->vNodes == NULL );
+    p->vNodes = Llb_ManGroupCollect( p );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupCreateFirst( Llb_Man_t * pMan )
+{
+    Llb_Grp_t * p;
+    Aig_Obj_t * pObj;
+    int i;
+    p = Llb_ManGroupAlloc( pMan );
+    Saig_ManForEachLo( pMan->pAig, pObj, i )
+        Vec_PtrPush( p->vOuts, pObj );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupCreateLast( Llb_Man_t * pMan )
+{
+    Llb_Grp_t * p;
+    Aig_Obj_t * pObj;
+    int i;
+    p = Llb_ManGroupAlloc( pMan );
+    Saig_ManForEachLi( pMan->pAig, pObj, i )
+        Vec_PtrPush( p->vIns, pObj );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 )
+{
+    Llb_Grp_t * p;
+    Aig_Obj_t * pObj;
+    int i;
+    p = Llb_ManGroupAlloc( p1->pMan );
+    // create inputs
+    Vec_PtrForEachEntry( Aig_Obj_t *, p1->vIns, pObj, i )
+        Vec_PtrPush( p->vIns, pObj );
+    Vec_PtrForEachEntry( Aig_Obj_t *, p2->vIns, pObj, i )
+        Vec_PtrPushUnique( p->vIns, pObj );
+    // create outputs
+    Vec_PtrForEachEntry( Aig_Obj_t *, p1->vOuts, pObj, i )
+        Vec_PtrPush( p->vOuts, pObj );
+    Vec_PtrForEachEntry( Aig_Obj_t *, p2->vOuts, pObj, i )
+        Vec_PtrPushUnique( p->vOuts, pObj );
+
+    // derive internal objects
+    assert( p->vNodes == NULL );
+    p->vNodes = Llb_ManGroupCollect( p );
+    return p;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManGroupMarkNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    if ( Aig_ObjIsTravIdPrevious(p, pObj) )
+    {
+        Aig_ObjSetTravIdCurrent(p, pObj);
+        return;
+    }
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    assert( Aig_ObjIsNode(pObj) );
+    Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin0(pObj) );
+    Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates group from two cuts derived by the flow computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 )
+{
+    Llb_Grp_t * p;
+    Aig_Obj_t * pObj;
+    int i;
+    p = Llb_ManGroupAlloc( pMan );
+
+    // mark Cut1
+    Aig_ManIncrementTravId( pMan->pAig );
+    Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i )
+        Aig_ObjSetTravIdCurrent( pMan->pAig, pObj );
+    // collect unmarked Cut2
+    Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i )
+        if ( !Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) )
+            Vec_PtrPush( p->vOuts, pObj );
+
+    // mark nodes reachable from Cut2
+    Aig_ManIncrementTravId( pMan->pAig );
+    Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i )
+        Llb_ManGroupMarkNodes_rec( pMan->pAig, pObj );
+    // collect marked Cut1
+    Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i )
+        if ( Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) )
+            Vec_PtrPush( p->vIns, pObj );
+
+    // derive internal objects
+    assert( p->vNodes == NULL );
+    p->vNodes = Llb_ManGroupCollect( p );
+    return p;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManPrepareGroups( Llb_Man_t * pMan )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    assert( pMan->vGroups == NULL );
+    pMan->vGroups = Vec_PtrAlloc( 1000 );
+    Llb_ManGroupCreateFirst( pMan );
+    Aig_ManForEachNode( pMan->pAig, pObj, i )
+    {
+        if ( pObj->fMarkA )
+            Llb_ManGroupCreate( pMan, pObj );
+    }
+    Saig_ManForEachLi( pMan->pAig, pObj, i )
+    {
+        if ( pObj->fMarkA )
+            Llb_ManGroupCreate( pMan, pObj );
+    }
+    Llb_ManGroupCreateLast( pMan );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManPrintSpan( Llb_Man_t * p )
+{
+    Llb_Grp_t * pGroup;
+    Aig_Obj_t * pVar;
+    int i, k, Span = 0, SpanMax = 0;
+    Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i )
+    {
+        Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k )
+            if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i )
+                Span++;
+        Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k )
+            if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i )
+                Span++;
+
+        SpanMax = Abc_MaxInt( SpanMax, Span );
+printf( "%d ", Span );
+
+        Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k )
+            if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i )
+                Span--;
+        Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k )
+            if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i )
+                Span--;
+    }
+printf( "\n" );
+printf( "Max = %d\n", SpanMax );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManGroupHasVar( Llb_Man_t * p, int iGroup, int iVar )
+{
+    Llb_Grp_t * pGroup = (Llb_Grp_t *)Vec_PtrEntry( p->vGroups, iGroup );
+    Aig_Obj_t * pObj;
+    int i;
+    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+        if ( pObj->Id == iVar )
+            return 1;
+    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+        if ( pObj->Id == iVar )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManPrintHisto( Llb_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, k;
+    Aig_ManForEachObj( p->pAig, pObj, i )
+    {
+        if ( Vec_IntEntry(p->vObj2Var, i) < 0 )
+            continue;
+        printf( "%3d :", i );
+        for ( k = 0; k < Vec_IntEntry(p->vVarBegs, i); k++ )
+            printf( " " );
+        for (      ; k <= Vec_IntEntry(p->vVarEnds, i); k++ )
+            printf( "%c", Llb_ManGroupHasVar(p, k, i)? '*':'-' );
+        printf( "\n" );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb1Hint.c b/abc-build/src/proof/llb/llb1Hint.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb1Hint.c
@@ -0,0 +1,226 @@
+/**CFile****************************************************************
+
+  FileName    [llb1Hint.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Cofactors the circuit w.r.t. the high-fanout variables.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb1Hint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns CI index with the largest number of fanouts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManMaxFanoutCi( Aig_Man_t * pAig )
+{
+    Aig_Obj_t * pObj; 
+    int i, WeightMax = -ABC_INFINITY, iInput = -1;
+    Aig_ManForEachCi( pAig, pObj, i )
+        if ( WeightMax < Aig_ObjRefs(pObj) )
+        {
+            WeightMax = Aig_ObjRefs(pObj);
+            iInput = i;
+        }
+    assert( iInput >= 0 );
+    return iInput;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives AIG whose PI is substituted by a constant.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Llb_ManPerformHints( Aig_Man_t * pAig, int nHintDepth )
+{
+    Aig_Man_t * pNew, * pTemp;
+    int i, iInput;
+    pNew = Aig_ManDupDfs( pAig );
+    for ( i = 0; i < nHintDepth; i++ )
+    {
+        iInput = Llb_ManMaxFanoutCi( pNew );
+        Abc_Print( 1, "%d %3d\n", i, iInput );
+        pNew = Aig_ManDupCof( pTemp = pNew, iInput, 1 );
+        Aig_ManStop( pTemp );
+    }
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns CI index with the largest number of fanouts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Llb_ManCollectHighFanoutObjects( Aig_Man_t * pAig, int nCandMax, int fCisOnly )
+{
+    Vec_Int_t * vFanouts, * vResult;
+    Aig_Obj_t * pObj; 
+    int i, fChanges, PivotValue;
+//    int Entry;
+    // collect fanout counts
+    vFanouts = Vec_IntAlloc( 100 );
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+//        if ( !Aig_ObjIsCi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) )
+        if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) )
+            continue;
+        Vec_IntPush( vFanouts, Aig_ObjRefs(pObj) );
+    }
+    Vec_IntSort( vFanouts, 1 );
+    // pick the separator
+    nCandMax = Abc_MinInt( nCandMax, Vec_IntSize(vFanouts) - 1 );
+    PivotValue = Vec_IntEntry( vFanouts, nCandMax );
+    Vec_IntFree( vFanouts );
+    // collect obj satisfying the constraints
+    vResult = Vec_IntAlloc( 100 );
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+//        if ( !Aig_ObjIsCi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) )
+        if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) )
+            continue;
+        if ( Aig_ObjRefs(pObj) < PivotValue )
+            continue;
+        Vec_IntPush( vResult, Aig_ObjId(pObj) );
+    }
+    assert( Vec_IntSize(vResult) >= nCandMax );
+    // order in the decreasing order of fanouts
+    do
+    {
+        fChanges = 0;
+        for ( i = 0; i < Vec_IntSize(vResult) - 1; i++ )
+            if ( Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i))) < 
+                 Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i+1))) )
+            {
+                int Temp = Vec_IntEntry( vResult, i );
+                Vec_IntWriteEntry( vResult, i, Vec_IntEntry(vResult, i+1) );
+                Vec_IntWriteEntry( vResult, i+1, Temp );
+                fChanges = 1;
+            }
+    }
+    while ( fChanges );
+/*
+    Vec_IntForEachEntry( vResult, Entry, i )
+        printf( "%d ", Aig_ObjRefs(Aig_ManObj(pAig, Entry)) );
+printf( "\n" );
+*/
+    return vResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives AIG whose PI is substituted by a constant.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars )
+{
+    DdManager * ddGlo = NULL;
+    Vec_Int_t * vHints;
+    Vec_Int_t * vHFCands;
+    int i, Entry, RetValue = -1;
+    abctime clk = Abc_Clock();
+    assert( pPars->nHintDepth > 0 );
+/*
+    // perform reachability without hints
+    RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, NULL, NULL );
+    if ( RetValue >= 0 )
+        return RetValue;
+*/
+    // create hints representation
+    vHFCands = Llb_ManCollectHighFanoutObjects( pAigGlo, pPars->nHintDepth+pPars->HintFirst, 1 );
+    vHints   = Vec_IntStartFull( Aig_ManObjNumMax(pAigGlo) );
+    // add one hint at a time till the problem is solved
+    Vec_IntForEachEntryStart( vHFCands, Entry, i, pPars->HintFirst )
+    {
+        Vec_IntWriteEntry( vHints, Entry, 1 );   // change to 1 to start from zero cof!!!
+        // solve under hints
+        RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo );
+        if ( RetValue == 0 )
+            goto Finish;
+        if ( RetValue == 1 )
+            break;
+    }
+    if ( RetValue == -1 )
+        goto Finish;
+    // undo the hints one at a time
+    for ( ; i >= pPars->HintFirst; i-- )
+    {
+        Entry = Vec_IntEntry( vHFCands, i );
+        Vec_IntWriteEntry( vHints, Entry, -1 );        
+        // solve under relaxed hints
+        RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo );
+        if ( RetValue == 0 )
+            goto Finish;
+        if ( RetValue == 1 )
+            continue;
+        break;
+    }
+Finish:
+    if ( ddGlo )
+    {
+        if ( ddGlo->bFunc )
+            Cudd_RecursiveDeref( ddGlo, ddGlo->bFunc ); 
+        Extra_StopManager( ddGlo );
+    }
+    Vec_IntFreeP( &vHFCands );
+    Vec_IntFreeP( &vHints );
+    if ( pPars->fVerbose )
+        Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clk );
+    return RetValue;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb1Man.c b/abc-build/src/proof/llb/llb1Man.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb1Man.c
@@ -0,0 +1,218 @@
+/**CFile****************************************************************
+
+  FileName    [llb1Man.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Reachability manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb1Man.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManPrepareVarMap( Llb_Man_t * p )
+{
+    Aig_Obj_t * pObjLi, * pObjLo;
+    int i, iVarLi, iVarLo;
+    assert( p->vNs2Glo == NULL );
+    assert( p->vCs2Glo == NULL );
+    assert( p->vGlo2Cs == NULL );
+    assert( p->vGlo2Ns == NULL );
+    p->vNs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) );
+    p->vCs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) );
+    p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+    p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+    Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+    {
+        iVarLi = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLi));
+        iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo));
+        assert( iVarLi >= 0 && iVarLi < Vec_IntSize(p->vVar2Obj) );
+        assert( iVarLo >= 0 && iVarLo < Vec_IntSize(p->vVar2Obj) );
+        Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i );
+        Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i );
+        Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo );
+        Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi );
+    }
+    // add mapping of the PIs
+    Saig_ManForEachPi( p->pAig, pObjLo, i )
+    {
+        iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo));
+        Vec_IntWriteEntry( p->vCs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i );
+        Vec_IntWriteEntry( p->vNs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManPrepareVarLimits( Llb_Man_t * p )
+{
+    Llb_Grp_t * pGroup;
+    Aig_Obj_t * pVar;
+    int i, k;
+    assert( p->vVarBegs == NULL );
+    assert( p->vVarEnds == NULL );
+    p->vVarEnds = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); 
+    p->vVarBegs = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); 
+    Vec_IntFill( p->vVarBegs, Aig_ManObjNumMax(p->pAig), p->pMatrix->nCols );
+
+    for ( i = 0; i < p->pMatrix->nCols; i++ )
+    {
+        pGroup = p->pMatrix->pColGrps[i];
+
+        Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k )
+            if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i )
+                Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i );
+        Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k )
+            if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i )
+                Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i );
+
+        Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k )
+            if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i )
+                Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i );
+        Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k )
+            if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i )
+                Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManStop( Llb_Man_t * p )
+{
+    Llb_Grp_t * pGrp;
+    DdNode * bTemp;
+    int i;
+
+//    Vec_IntFreeP( &p->vMem );
+//    Vec_PtrFreeP( &p->vTops );
+//    Vec_PtrFreeP( &p->vBots );
+//    Vec_VecFreeP( (Vec_Vec_t **)&p->vCuts );
+
+    if ( p->pMatrix )
+        Llb_MtrFree( p->pMatrix );
+    Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGrp, i )
+        Llb_ManGroupStop( pGrp );
+    if ( p->dd )
+    {
+//        printf( "Manager dd\n" );
+        Extra_StopManager( p->dd );
+    }
+    if ( p->ddG )
+    {
+//        printf( "Manager ddG\n" );
+        if ( p->ddG->bFunc )
+            Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc ); 
+        Extra_StopManager( p->ddG );
+    }
+    if ( p->ddR )
+    {
+//        printf( "Manager ddR\n" );
+        if ( p->ddR->bFunc )
+            Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); 
+        Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i )
+            Cudd_RecursiveDeref( p->ddR, bTemp );
+        Extra_StopManager( p->ddR );
+    }
+    Aig_ManStop( p->pAig );
+    Vec_PtrFreeP( &p->vGroups );
+    Vec_IntFreeP( &p->vVar2Obj );
+    Vec_IntFreeP( &p->vObj2Var );
+    Vec_IntFreeP( &p->vVarBegs );
+    Vec_IntFreeP( &p->vVarEnds );
+    Vec_PtrFreeP( &p->vRings  );
+    Vec_IntFreeP( &p->vNs2Glo );
+    Vec_IntFreeP( &p->vCs2Glo );
+    Vec_IntFreeP( &p->vGlo2Cs );
+    Vec_IntFreeP( &p->vGlo2Ns );
+//    Vec_IntFreeP( &p->vHints );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+    Llb_Man_t * p;
+    Aig_ManCleanMarkA( pAig );
+    p = ABC_CALLOC( Llb_Man_t, 1 );
+    p->pAigGlo  = pAigGlo;
+    p->pPars    = pPars;
+    p->pAig     = pAig;
+    p->vVar2Obj = Llb_ManMarkPivotNodes( p->pAig, pPars->fUsePivots );
+    p->vObj2Var = Vec_IntInvert( p->vVar2Obj, -1 );
+    p->vRings   = Vec_PtrAlloc( 100 );
+    Llb_ManPrepareVarMap( p );
+    Llb_ManPrepareGroups( p );
+    Aig_ManCleanMarkA( pAig );
+    p->pMatrix = Llb_MtrCreate( p );
+    p->pMatrix->pMan = p;
+    return p;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb1Matrix.c b/abc-build/src/proof/llb/llb1Matrix.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb1Matrix.c
@@ -0,0 +1,430 @@
+/**CFile****************************************************************
+
+  FileName    [llb1Matrix.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Partition clustering as a matrix problem.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb1Matrix.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+//              0123              nCols
+//             +--------------------->  
+// pi        0 |  111             row0   pRowSums[0]  
+// pi        1 | 1     11         row1   pRowSums[1] 
+// pi        2 |   1  11          row2   pRowSums[2] 
+// CS          |1       1
+// CS          |1      111
+// CS          |111    111
+// int         |  11111           
+// int         |     111          
+// int         |       111        
+// int         |         111      
+// NS          |           11 11
+// NS          |            11 1
+// NS          |             111
+//       nRows |
+//             v    
+//              cccc   pColSums[0]
+//              oooo   pColSums[1]
+//              llll   pColSums[2]
+//              0123   pColSums[3]
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Verify columns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_MtrVerifyRowsAll( Llb_Mtr_t * p )
+{
+    int iRow, iCol, Counter;
+    for ( iCol = 0; iCol < p->nCols; iCol++ )
+    {
+        Counter = 0;
+        for ( iRow = 0; iRow < p->nRows; iRow++ )
+            if ( p->pMatrix[iCol][iRow] == 1 )
+                Counter++;
+        assert( Counter == p->pColSums[iCol] );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verify columns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_MtrVerifyColumnsAll( Llb_Mtr_t * p )
+{
+    int iRow, iCol, Counter;
+    for ( iRow = 0; iRow < p->nRows; iRow++ )
+    {
+        Counter = 0;
+        for ( iCol = 0; iCol < p->nCols; iCol++ )
+            if ( p->pMatrix[iCol][iRow] == 1 )
+                Counter++;
+        assert( Counter == p->pRowSums[iRow] );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verify columns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_MtrVerifyMatrix( Llb_Mtr_t * p )
+{
+    Llb_MtrVerifyRowsAll( p );
+    Llb_MtrVerifyColumnsAll( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sort variables in the order of removal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Llb_MtrFindVarOrder( Llb_Mtr_t * p )
+{
+    int * pOrder, * pLast;
+    int i, k, fChanges, Temp;
+    pOrder = ABC_CALLOC( int, p->nRows );
+    pLast  = ABC_CALLOC( int, p->nRows );
+    for ( i = 0; i < p->nRows; i++ )
+    {
+        pOrder[i] = i;
+        for ( k = p->nCols - 1; k >= 0; k-- )
+            if ( p->pMatrix[k][i] )
+            {
+                pLast[i] = k;
+                break;
+            }
+    }
+    do
+    {
+        fChanges = 0;
+        for ( i = 0; i < p->nRows - 1; i++ )
+            if ( pLast[i] > pLast[i+1] )
+            {
+                Temp = pOrder[i];
+                pOrder[i] = pOrder[i+1];
+                pOrder[i+1] = Temp;
+
+                Temp = pLast[i];
+                pLast[i] = pLast[i+1];
+                pLast[i+1] = Temp;
+
+                fChanges = 1;
+            }
+    }
+    while ( fChanges );
+    ABC_FREE( pLast );
+    return pOrder;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns type of a variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Llb_MtrVarName( Llb_Mtr_t * p, int iVar )
+{
+    static char Buffer[10];
+    if ( iVar < p->nPis )
+        strcpy( Buffer, "pi" );
+    else if ( iVar < p->nPis + p->nFfs )
+        strcpy( Buffer, "CS" );
+    else if ( iVar >= p->nRows - p->nFfs )
+        strcpy( Buffer, "NS" );
+    else 
+        strcpy( Buffer, "int" );
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates one column with vars in the array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder )
+{
+    int * pOrder = NULL;
+    int i, iRow, iCol;
+    if ( fOrder )
+        pOrder = Llb_MtrFindVarOrder( p );
+    for ( i = 0; i < p->nRows; i++ )
+    {
+        iRow = pOrder ? pOrder[i] : i;
+        printf( "%3d : ", iRow );
+        printf( "%3d ", p->pRowSums[iRow] );
+        printf( "%3s ", Llb_MtrVarName(p, iRow) );
+        for ( iCol = 0; iCol < p->nCols; iCol++ )
+            printf( "%c", p->pMatrix[iCol][iRow] ? '*' : ' ' );
+        printf( "\n" );
+    }
+    ABC_FREE( pOrder );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verify columns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p )
+{
+    int iVar, iGrp, iGrp1, iGrp2, Span = 0, nCutSize = 0, nCutSizeMax = 0;
+    int * pGrp1 = ABC_CALLOC( int, p->nRows ); 
+    int * pGrp2 = ABC_CALLOC( int, p->nRows ); 
+    for ( iVar = 0; iVar < p->nRows; iVar++ )
+    {
+        if ( p->pRowSums[iVar] == 0 )
+            continue;
+        for ( iGrp1 = 0; iGrp1 < p->nCols; iGrp1++ )
+            if ( p->pMatrix[iGrp1][iVar] == 1 )
+                break;
+        for ( iGrp2 = p->nCols - 1; iGrp2 >= 0; iGrp2-- )
+            if ( p->pMatrix[iGrp2][iVar] == 1 )
+                break;
+        assert( iGrp1 <= iGrp2 );
+        pGrp1[iVar] = iGrp1;
+        pGrp2[iVar] = iGrp2;
+        Span += iGrp2 - iGrp1;
+    }
+    // compute span
+    for ( iGrp = 0; iGrp < p->nCols; iGrp++ )
+    {
+        for ( iVar = 0; iVar < p->nRows; iVar++ )
+            if ( pGrp1[iVar] == iGrp )
+                nCutSize++;
+        if ( nCutSizeMax < nCutSize )
+            nCutSizeMax = nCutSize;
+        for ( iVar = 0; iVar < p->nRows; iVar++ )
+            if ( pGrp2[iVar] == iGrp )
+                nCutSize--;
+    }
+    ABC_FREE( pGrp1 );
+    ABC_FREE( pGrp2 );
+    printf( "[%4d x %4d]  Life-span =%6.2f  Max-cut =%5d\n", 
+        p->nCols, p->nRows, 1.0*Span/p->nRows, nCutSizeMax );
+    if ( nCutSize )
+        Abc_Print( -1, "Cut size is not zero (%d).\n", nCutSize );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the matrix representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Llb_Mtr_t * Llb_MtrAlloc( int nPis, int nFfs, int nCols, int nRows )
+{
+    Llb_Mtr_t * p;
+    int i;
+    p = ABC_CALLOC( Llb_Mtr_t, 1 );
+    p->nPis  = nPis;
+    p->nFfs  = nFfs;
+    p->nRows = nRows;
+    p->nCols = nCols;
+    p->pRowSums = ABC_CALLOC( int, nRows );
+    p->pColSums = ABC_CALLOC( int, nCols );
+    p->pColGrps = ABC_CALLOC( Llb_Grp_t *, nCols );
+    p->pMatrix  = ABC_CALLOC( char *, nCols );
+    for ( i = 0; i < nCols; i++ )
+        p->pMatrix[i] = ABC_CALLOC( char, nRows );
+    // partial product
+    p->pProdVars = ABC_CALLOC( char, nRows );  // variables in the partial product
+    p->pProdNums = ABC_CALLOC( int, nRows );   // var counts in the remaining partitions
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the matrix representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_MtrFree( Llb_Mtr_t * p )
+{
+    int i;
+    ABC_FREE( p->pProdVars );
+    ABC_FREE( p->pProdNums );
+    for ( i = 0; i < p->nCols; i++ )
+        ABC_FREE( p->pMatrix[i] );
+    ABC_FREE( p->pRowSums );
+    ABC_FREE( p->pColSums );
+    ABC_FREE( p->pMatrix );
+    ABC_FREE( p->pColGrps );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates one column with vars in the array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_MtrAddColumn( Llb_Mtr_t * p, Llb_Grp_t * pGrp )
+{
+    Aig_Obj_t * pVar;
+    int i, iRow, iCol = pGrp->Id;
+    assert( iCol >= 0 && iCol < p->nCols );
+    p->pColGrps[iCol] = pGrp;
+    Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vIns, pVar, i )
+    {
+        iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) );
+        assert( iRow >= 0 && iRow < p->nRows );
+        p->pMatrix[iCol][iRow] = 1;
+        p->pColSums[iCol]++;
+        p->pRowSums[iRow]++;
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vOuts, pVar, i )
+    {
+        iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) );
+        assert( iRow >= 0 && iRow < p->nRows );
+        p->pMatrix[iCol][iRow] = 1;
+        p->pColSums[iCol]++;
+        p->pRowSums[iRow]++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Matrix reduce.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_MtrRemoveSingletonRows( Llb_Mtr_t * p )
+{
+    int i, k;
+    for ( i = 0; i < p->nRows; i++ )
+        if ( p->pRowSums[i] < 2 )
+        {
+            p->pRowSums[i] = 0;
+            for ( k = 0; k < p->nCols; k++ )
+            {
+                if ( p->pMatrix[k][i] == 1 )
+                {
+                    p->pMatrix[k][i] = 0;
+                    p->pColSums[k]--;
+                }
+            }
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Matrix reduce.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p )
+{
+    Llb_Mtr_t * pMatrix;
+    Llb_Grp_t * pGroup;
+    int i;
+    pMatrix = Llb_MtrAlloc( Saig_ManPiNum(p->pAig), Saig_ManRegNum(p->pAig), 
+        Vec_PtrSize(p->vGroups), Vec_IntSize(p->vVar2Obj) );
+    Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i )
+        Llb_MtrAddColumn( pMatrix, pGroup );
+//    Llb_MtrRemoveSingletonRows( pMatrix );
+    return pMatrix;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb1Pivot.c b/abc-build/src/proof/llb/llb1Pivot.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb1Pivot.c
@@ -0,0 +1,254 @@
+/**CFile****************************************************************
+
+  FileName    [llb1Pivot.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Determining pivot variables.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb1Pivot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManTracePaths_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pPivot )
+{
+    Aig_Obj_t * pFanout;
+    int k, iFan = -1;
+    if ( Aig_ObjIsTravIdPrevious(p, pObj) )
+        return 0;
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return 1;
+    if ( Saig_ObjIsLi(p, pObj) )
+        return 0;
+    if ( Saig_ObjIsPo(p, pObj) )
+        return 0;
+    if ( pObj == pPivot )
+        return 1;
+    assert( Aig_ObjIsCand(pObj) );
+    Aig_ObjForEachFanout( p, pObj, pFanout, iFan, k )
+        if ( !Llb_ManTracePaths_rec( p, pFanout, pPivot ) )
+        {
+            Aig_ObjSetTravIdPrevious(p, pObj);
+            return 0;
+        }
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    Aig_ManIncrementTravId( p ); // prev = visited with path to LI  (value 0)
+    Aig_ManIncrementTravId( p ); // cur  = visited w/o  path to LI  (value 1)
+    Saig_ManForEachLo( p, pObj, i )
+        Counter += Llb_ManTracePaths_rec( p, pObj, pPivot );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManTestCuts( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, Count;
+    Aig_ManFanoutStart( p );
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        if ( Aig_ObjRefs(pObj) <= 1 )
+            continue;
+        Count = Llb_ManTracePaths( p, pObj );
+        printf( "Obj =%5d.  Lev =%3d.  Fanout =%5d.  Count = %3d.\n", 
+            i, Aig_ObjLevel(pObj), Aig_ObjRefs(pObj), Count );
+    }
+    Aig_ManFanoutStop( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManLabelLiCones_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    if ( pObj->fMarkB )
+        return;
+    pObj->fMarkB = 1;
+    assert( Aig_ObjIsNode(pObj) );
+    Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) );
+    Llb_ManLabelLiCones_rec( p, Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determine starting cut-points.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManLabelLiCones( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    // mark const and PIs
+    Aig_ManConst1(p)->fMarkB = 1;
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->fMarkB = 1;
+    // mark cones
+    Saig_ManForEachLi( p, pObj, i )
+        Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determine starting cut-points.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManMarkInternalPivots( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vMuxes;
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+
+    // remove refs due to MUXes
+    vMuxes = Aig_ManMuxesCollect( p );
+    Aig_ManMuxesDeref( p, vMuxes );
+
+    // mark nodes feeding into LIs
+    Aig_ManCleanMarkB( p );
+    Llb_ManLabelLiCones( p );
+
+    // mark internal nodes
+    Aig_ManFanoutStart( p );
+    Aig_ManForEachNode( p, pObj, i )
+        if ( pObj->fMarkB && pObj->nRefs > 1 )
+        {
+            if ( Llb_ManTracePaths(p, pObj) > 0 )
+                pObj->fMarkA = 1;
+            Counter++;
+        }
+    Aig_ManFanoutStop( p );
+//    printf( "TracePath tried = %d.\n", Counter );
+
+    // mark nodes feeding into LIs
+    Aig_ManCleanMarkB( p );
+
+    // add refs due to MUXes
+    Aig_ManMuxesRef( p, vMuxes );
+    Vec_PtrFree( vMuxes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determine starting cut-points.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal )
+{
+    Vec_Int_t * vVar2Obj;
+    Aig_Obj_t * pObj;
+    int i;
+    // mark inputs/outputs
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->fMarkA = 1;
+    Saig_ManForEachLi( p, pObj, i )
+        pObj->fMarkA = 1;
+
+    // mark internal pivot nodes
+    if ( fUseInternal )
+        Llb_ManMarkInternalPivots( p );
+
+    // assign variable numbers
+    Aig_ManConst1(p)->fMarkA = 0;
+    vVar2Obj = Vec_IntAlloc( 100 );
+    Aig_ManForEachCi( p, pObj, i )
+        Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) );
+    Aig_ManForEachNode( p, pObj, i )
+        if ( pObj->fMarkA )
+            Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) );
+    Saig_ManForEachLi( p, pObj, i )
+        Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) );
+    return vVar2Obj;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb1Reach.c b/abc-build/src/proof/llb/llb1Reach.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb1Reach.c
@@ -0,0 +1,904 @@
+/**CFile****************************************************************
+
+  FileName    [llb1Reach.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Reachability analysis.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb1Reach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+ 
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives global BDD for the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_ManConstructOutBdd( Aig_Man_t * pAig, Aig_Obj_t * pNode, DdManager * dd )
+{
+    DdNode * bBdd0, * bBdd1, * bFunc;
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj = NULL;
+    int i;
+    abctime TimeStop;
+    if ( Aig_ObjFanin0(pNode) == Aig_ManConst1(pAig) )
+        return Cudd_NotCond( Cudd_ReadOne(dd), Aig_ObjFaninC0(pNode) );
+    TimeStop = dd->TimeStop;  dd->TimeStop = 0;
+    vNodes = Aig_ManDfsNodes( pAig, &pNode, 1 );
+    assert( Vec_PtrSize(vNodes) > 0 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        if ( !Aig_ObjIsNode(pObj) )
+            continue;
+        bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+        bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+        pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 );  Cudd_Ref( (DdNode *)pObj->pData );
+    }
+    bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        if ( !Aig_ObjIsNode(pObj) )
+            continue;
+        Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+    }
+    Vec_PtrFree( vNodes );
+    if ( Aig_ObjIsCo(pNode) )
+        bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pNode) );
+    Cudd_Deref( bFunc );
+    dd->TimeStop = TimeStop;
+    return bFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives BDD for the group.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_ManConstructGroupBdd( Llb_Man_t * p, Llb_Grp_t * pGroup )
+{
+    Aig_Obj_t * pObj;
+    DdNode * bBdd0, * bBdd1, * bRes, * bXor, * bTemp;
+    int i, k;
+    Aig_ManConst1(p->pAig)->pData = Cudd_ReadOne( p->dd );
+    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+        pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i )
+    {
+        bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+        bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+//        pObj->pData = Extra_bddAndTime( p->dd, bBdd0, bBdd1, p->pPars->TimeTarget );  
+        pObj->pData = Cudd_bddAnd( p->dd, bBdd0, bBdd1 );  
+        if ( pObj->pData == NULL )
+        {
+            Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i )
+                if ( pObj->pData )
+                    Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData );
+            return NULL;
+        }
+        Cudd_Ref( (DdNode *)pObj->pData );
+    }
+    bRes = Cudd_ReadOne( p->dd );   Cudd_Ref( bRes );
+    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+    {
+        if ( Aig_ObjIsCo(pObj) )
+            bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+        else
+            bBdd0 = (DdNode *)pObj->pData;
+        bBdd1 = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+        bXor  = Cudd_bddXor( p->dd, bBdd0, bBdd1 );                  Cudd_Ref( bXor );
+//        bRes  = Extra_bddAndTime( p->dd, bTemp = bRes, Cudd_Not(bXor), p->pPars->TimeTarget );  
+        bRes  = Cudd_bddAnd( p->dd, bTemp = bRes, Cudd_Not(bXor) );  
+        if ( bRes == NULL )
+        {
+            Cudd_RecursiveDeref( p->dd, bTemp );
+            Cudd_RecursiveDeref( p->dd, bXor );
+            Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i )
+                if ( pObj->pData )
+                    Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData );
+            return NULL;
+        }        
+        Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+        Cudd_RecursiveDeref( p->dd, bXor );
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i )
+        Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData );
+    Cudd_Deref( bRes );
+    return bRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives quantification cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_ManConstructQuantCubeIntern( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace, int fBackward )
+{
+    Aig_Obj_t * pObj;
+    DdNode * bRes, * bTemp, * bVar;
+    int i, iGroupFirst, iGroupLast;
+    abctime TimeStop;
+    TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+    bRes = Cudd_ReadOne( p->dd );   Cudd_Ref( bRes );
+    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+    {
+        if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) )
+            continue;
+        iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj));
+        iGroupLast  = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj));
+        assert( iGroupFirst <= iGroupLast );
+        if ( iGroupFirst < iGroupLast )
+            continue;
+        bVar  = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+        bRes  = Cudd_bddAnd( p->dd, bTemp = bRes, bVar );  Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+    {
+        if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) )
+            continue;
+        iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj));
+        iGroupLast  = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj));
+        assert( iGroupFirst <= iGroupLast );
+        if ( iGroupFirst < iGroupLast )
+            continue;
+        bVar  = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+        bRes  = Cudd_bddAnd( p->dd, bTemp = bRes, bVar );  Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+    }
+    Cudd_Deref( bRes );
+    p->dd->TimeStop = TimeStop;
+    return bRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives quantification cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_ManConstructQuantCubeFwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace )
+{
+    Aig_Obj_t * pObj;
+    DdNode * bRes, * bTemp, * bVar;
+    int i, iGroupLast;
+    abctime TimeStop;
+    TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+    bRes = Cudd_ReadOne( p->dd );   Cudd_Ref( bRes );
+    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+    {
+        iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj));
+        assert( iGroupLast >= iGrpPlace );
+        if ( iGroupLast > iGrpPlace )
+            continue;
+        bVar  = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+        bRes  = Cudd_bddAnd( p->dd, bTemp = bRes, bVar );  Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+    {
+        iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj));
+        assert( iGroupLast >= iGrpPlace );
+        if ( iGroupLast > iGrpPlace )
+            continue;
+        bVar  = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+        bRes  = Cudd_bddAnd( p->dd, bTemp = bRes, bVar );  Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+    }
+    Cudd_Deref( bRes );
+    p->dd->TimeStop = TimeStop;
+    return bRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives quantification cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_ManConstructQuantCubeBwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace )
+{
+    Aig_Obj_t * pObj;
+    DdNode * bRes, * bTemp, * bVar;
+    int i, iGroupFirst;
+    abctime TimeStop;
+    TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+    bRes = Cudd_ReadOne( p->dd );   Cudd_Ref( bRes );
+    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+    {
+        if ( Saig_ObjIsPi(p->pAig, pObj) )
+            continue;
+        iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj));
+        assert( iGroupFirst <= iGrpPlace );
+        if ( iGroupFirst < iGrpPlace )
+            continue;
+        bVar  = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+        bRes  = Cudd_bddAnd( p->dd, bTemp = bRes, bVar );  Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+    {
+        if ( Saig_ObjIsPi(p->pAig, pObj) )
+            continue;
+        iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj));
+        assert( iGroupFirst <= iGrpPlace );
+        if ( iGroupFirst < iGrpPlace )
+            continue;
+        bVar  = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+        bRes  = Cudd_bddAnd( p->dd, bTemp = bRes, bVar );  Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+    }
+    Cudd_Deref( bRes );
+    p->dd->TimeStop = TimeStop;
+    return bRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_ManComputeInitState( Llb_Man_t * p, DdManager * dd )
+{
+    Aig_Obj_t * pObj;
+    DdNode * bRes, * bVar, * bTemp;
+    int i, iVar;
+    abctime TimeStop;
+    TimeStop = dd->TimeStop; dd->TimeStop = 0;
+    bRes = Cudd_ReadOne( dd );   Cudd_Ref( bRes );
+    Saig_ManForEachLo( p->pAig, pObj, i )
+    {
+        iVar  = (dd == p->ddG) ? i : Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj));
+        bVar  = Cudd_bddIthVar( dd, iVar );
+        bRes  = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) );  Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    Cudd_Deref( bRes );
+    dd->TimeStop = TimeStop;
+    return bRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_ManComputeImage( Llb_Man_t * p, DdNode * bInit, int fBackward )
+{
+    int fCheckSupport = 0;
+    Llb_Grp_t * pGroup;
+    DdNode * bImage, * bGroup, * bCube, * bTemp;
+    int k, Index;
+    bImage = bInit;  Cudd_Ref( bImage );
+    for ( k = 1; k < p->pMatrix->nCols-1; k++ )
+    {
+        if ( fBackward )
+            Index = p->pMatrix->nCols - 1 - k;
+        else
+            Index = k;
+
+        // compute group BDD
+        pGroup = p->pMatrix->pColGrps[Index];
+        bGroup = Llb_ManConstructGroupBdd( p, pGroup );
+        if ( bGroup == NULL )
+        {
+            Cudd_RecursiveDeref( p->dd, bImage );
+            return NULL;
+        }
+        Cudd_Ref( bGroup );
+        // quantify variables appearing only in this group
+        bCube  = Llb_ManConstructQuantCubeIntern( p, pGroup, Index, fBackward );       Cudd_Ref( bCube );
+        bGroup = Cudd_bddExistAbstract( p->dd, bTemp = bGroup, bCube );         
+        if ( bGroup == NULL )
+        {
+            Cudd_RecursiveDeref( p->dd, bTemp );
+            Cudd_RecursiveDeref( p->dd, bCube );
+            return NULL;
+        }
+        Cudd_Ref( bGroup );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+        Cudd_RecursiveDeref( p->dd, bCube );
+        // perform partial product
+        if ( fBackward )
+            bCube  = Llb_ManConstructQuantCubeBwd( p, pGroup, Index );
+        else
+            bCube  = Llb_ManConstructQuantCubeFwd( p, pGroup, Index );
+        Cudd_Ref( bCube );
+//        bImage = Extra_bddAndAbstractTime( p->dd, bTemp = bImage, bGroup, bCube, p->pPars->TimeTarget );   
+        bImage = Cudd_bddAndAbstract( p->dd, bTemp = bImage, bGroup, bCube );   
+        if ( bImage == NULL )
+        {
+            Cudd_RecursiveDeref( p->dd, bTemp );
+            Cudd_RecursiveDeref( p->dd, bGroup );
+            Cudd_RecursiveDeref( p->dd, bCube );
+            return NULL;
+        }
+        Cudd_Ref( bImage );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+        Cudd_RecursiveDeref( p->dd, bGroup );
+        Cudd_RecursiveDeref( p->dd, bCube );
+    }
+
+    // make sure image depends on next state vars
+    if ( fCheckSupport )
+    {
+        bCube = Cudd_Support( p->dd, bImage );    Cudd_Ref( bCube );
+        for ( bTemp = bCube; bTemp != p->dd->one; bTemp = cuddT(bTemp) )
+        {
+            int ObjId = Vec_IntEntry( p->vVar2Obj, bTemp->index );
+            Aig_Obj_t * pObj = Aig_ManObj( p->pAig, ObjId );
+            if ( !Saig_ObjIsLi(p->pAig, pObj) )
+                printf( "Var %d assigned to obj %d that is not LI\n", bTemp->index, ObjId );
+        }
+        Cudd_RecursiveDeref( p->dd, bCube );
+    }
+    Cudd_Deref( bImage );
+    return bImage;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_ManCreateConstraints( Llb_Man_t * p, Vec_Int_t * vHints, int fUseNsVars )
+{
+    DdNode * bConstr, * bFunc, * bTemp;
+    Aig_Obj_t * pObj;
+    int i, Entry;
+    abctime TimeStop;
+    if ( vHints == NULL )
+        return Cudd_ReadOne( p->dd );
+    TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+    assert( Aig_ManCiNum(p->pAig) == Aig_ManCiNum(p->pAigGlo) );
+    // assign const and PI nodes to the original AIG
+    Aig_ManCleanData( p->pAig );
+    Aig_ManConst1( p->pAig )->pData = Cudd_ReadOne( p->dd );
+    Saig_ManForEachPi( p->pAig, pObj, i )
+        pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var,Aig_ObjId(pObj)) );
+    Saig_ManForEachLo( p->pAig, pObj, i )
+    {
+        if ( fUseNsVars )
+            Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(Saig_ObjLoToLi(p->pAig, pObj)) );
+        else
+            Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(pObj) );
+        pObj->pData = Cudd_bddIthVar( p->dd, Entry );
+    }
+    // transfer them to the global AIG
+    Aig_ManCleanData( p->pAigGlo );
+    Aig_ManConst1( p->pAigGlo )->pData = Cudd_ReadOne( p->dd );
+    Aig_ManForEachCi( p->pAigGlo, pObj, i )
+        pObj->pData = Aig_ManCi(p->pAig, i)->pData;
+    // derive consraints
+    bConstr = Cudd_ReadOne( p->dd );   Cudd_Ref( bConstr );
+    Vec_IntForEachEntry( vHints, Entry, i )
+    {
+        if ( Entry != 0 && Entry != 1 )
+            continue;
+        bFunc = Llb_ManConstructOutBdd( p->pAigGlo, Aig_ManObj(p->pAigGlo, i), p->dd );  Cudd_Ref( bFunc );
+        bFunc = Cudd_NotCond( bFunc, Entry ); // restrict to not constraint
+        // make the product
+        bConstr = Cudd_bddAnd( p->dd, bTemp = bConstr, bFunc );                          Cudd_Ref( bConstr );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+        Cudd_RecursiveDeref( p->dd, bFunc );
+    }
+    Cudd_Deref( bConstr );
+    p->dd->TimeStop = TimeStop;
+    return bConstr;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform reachability with hints and returns reached states in ppGlo.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Llb_ManReachDeriveCex( Llb_Man_t * p )
+{
+    Abc_Cex_t * pCex;
+    Aig_Obj_t * pObj;
+    DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing;
+    int i, v, RetValue, nPiOffset;
+    char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) );
+    assert( Vec_PtrSize(p->vRings) > 0 );
+
+    p->dd->TimeStop  = 0;
+    p->ddR->TimeStop = 0;
+
+/*
+    Saig_ManForEachLo( p->pAig, pObj, i )
+        printf( "%d ", pObj->Id );
+    printf( "\n" );
+    Saig_ManForEachLi( p->pAig, pObj, i )
+        printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) );
+    printf( "\n" );
+*/
+    // allocate room for the counter-example
+    pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) );
+    pCex->iFrame = Vec_PtrSize(p->vRings) - 1;
+    pCex->iPo = -1;
+
+    // get the last cube
+    bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc );  Cudd_Ref( bOneCube );
+    RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+    Cudd_RecursiveDeref( p->ddR, bOneCube );
+    assert( RetValue );
+
+    // write PIs of counter-example
+    nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1);
+    Saig_ManForEachPi( p->pAig, pObj, i )
+        if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+            Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+    // write state in terms of NS variables
+    if ( Vec_PtrSize(p->vRings) > 1 )
+    {
+        bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues );   Cudd_Ref( bState );
+    }
+    // perform backward analysis
+    Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v )
+    { 
+        if ( v == Vec_PtrSize(p->vRings) - 1 )
+            continue;
+//Extra_bddPrintSupport( p->dd, bState );  printf( "\n" );
+//Extra_bddPrintSupport( p->dd, bRing );   printf( "\n" );
+        // compute the next states
+        bImage = Llb_ManComputeImage( p, bState, 1 ); 
+        assert( bImage != NULL );
+        Cudd_Ref( bImage );
+        Cudd_RecursiveDeref( p->dd, bState );
+//Extra_bddPrintSupport( p->dd, bImage );  printf( "\n" );
+
+        // move reached states into ring manager
+        bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) );    Cudd_Ref( bImage );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+//Extra_bddPrintSupport( p->ddR, bImage );  printf( "\n" );
+
+        // intersect with the previous set
+        bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing );                Cudd_Ref( bOneCube );
+        Cudd_RecursiveDeref( p->ddR, bImage );
+
+        // find any assignment of the BDD
+        RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+        Cudd_RecursiveDeref( p->ddR, bOneCube );
+        assert( RetValue );
+/*
+        for ( i = 0; i < p->ddR->size; i++ )
+            printf( "%d ", pValues[i] );
+        printf( "\n" );
+*/
+        // write PIs of counter-example
+        nPiOffset -= Saig_ManPiNum(p->pAig);
+        Saig_ManForEachPi( p->pAig, pObj, i )
+            if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+                Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+        // check that we get the init state
+        if ( v == 0 )
+        {
+            Saig_ManForEachLo( p->pAig, pObj, i )
+                assert( pValues[i] == 0 );
+            break;
+        }
+
+        // write state in terms of NS variables
+        bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues );   Cudd_Ref( bState );
+    }
+    assert( nPiOffset == Saig_ManRegNum(p->pAig) );
+    // update the output number
+//Abc_CexPrint( pCex );
+    RetValue = Saig_ManFindFailedPoCex( p->pAigGlo, pCex );
+    assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pAigGlo) ); // invalid CEX!!!
+    pCex->iPo = RetValue;
+    // cleanup
+    ABC_FREE( pValues );
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform reachability with hints and returns reached states in ppGlo.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo )
+{
+    int * pNs2Glo = Vec_IntArray( p->vNs2Glo );
+    int * pCs2Glo = Vec_IntArray( p->vCs2Glo );
+    int * pGlo2Cs = Vec_IntArray( p->vGlo2Cs );
+    DdNode * bCurrent, * bReached, * bNext, * bTemp, * bCube;
+    DdNode * bConstrCs, * bConstrNs;
+    abctime clk2, clk = Abc_Clock();
+    int nIters, nBddSize = 0;
+//    int nThreshold = 10000;
+
+    // compute time to stop
+    p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0;
+
+    // define variable limits
+    Llb_ManPrepareVarLimits( p );
+
+    // start the managers
+    assert( p->dd == NULL );
+    assert( p->ddG == NULL );
+    assert( p->ddR == NULL );
+    p->dd  = Cudd_Init( Vec_IntSize(p->vVar2Obj), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    p->ddR = Cudd_Init( Aig_ManCiNum(p->pAig),    0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    if ( pddGlo && *pddGlo )
+        p->ddG = *pddGlo, *pddGlo = NULL; 
+    else
+        p->ddG = Cudd_Init( Aig_ManRegNum(p->pAig),   0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+
+    if ( p->pPars->fReorder )
+    {
+        Cudd_AutodynEnable( p->dd,  CUDD_REORDER_SYMM_SIFT );
+        Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT );
+        Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT );
+    }
+    else
+    {
+        Cudd_AutodynDisable( p->dd );
+        Cudd_AutodynDisable( p->ddG );
+        Cudd_AutodynDisable( p->ddR );
+    }
+
+    // set the stop time parameter
+    p->dd->TimeStop  = p->pPars->TimeTarget;
+    p->ddG->TimeStop = p->pPars->TimeTarget;
+    p->ddR->TimeStop = p->pPars->TimeTarget;
+
+    // create bad state in the ring manager
+    p->ddR->bFunc  = Llb_BddComputeBad( p->pAigGlo, p->ddR, p->pPars->TimeTarget );          
+    if ( p->ddR->bFunc == NULL )
+    {
+        if ( !p->pPars->fSilent )
+            printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+        p->pPars->iFrame = -1;
+        return -1;
+    }
+    Cudd_Ref( p->ddR->bFunc );
+
+    // derive constraints
+    bConstrCs = Llb_ManCreateConstraints( p, vHints, 0 );   Cudd_Ref( bConstrCs );
+    bConstrNs = Llb_ManCreateConstraints( p, vHints, 1 );   Cudd_Ref( bConstrNs );
+//Extra_bddPrint( p->dd, bConstrCs ); printf( "\n" );
+//Extra_bddPrint( p->dd, bConstrNs ); printf( "\n" );
+
+    // perform reachability analysis
+    // compute the starting set of states
+    if ( p->ddG->bFunc )
+    {
+        bReached = p->ddG->bFunc; p->ddG->bFunc = NULL;
+        bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Cs );    Cudd_Ref( bCurrent );
+    }
+    else
+    {
+        bReached = Llb_ManComputeInitState( p, p->ddG );                         Cudd_Ref( bReached );
+        bCurrent = Llb_ManComputeInitState( p, p->dd  );                         Cudd_Ref( bCurrent );
+    }
+//Extra_bddPrintSupport( p->ddG, bReached ); printf( "\n" );
+//Extra_bddPrintSupport( p->dd,  bCurrent ); printf( "\n" );
+
+//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" );
+    for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ )
+    { 
+        clk2 = Abc_Clock();
+        // check the runtime limit
+        if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout during image computation (%d seconds).\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Cudd_RecursiveDeref( p->dd,  bCurrent );  bCurrent = NULL;
+            Cudd_RecursiveDeref( p->dd,  bConstrCs ); bConstrCs = NULL;
+            Cudd_RecursiveDeref( p->dd,  bConstrNs ); bConstrNs = NULL;
+            Cudd_RecursiveDeref( p->ddG, bReached );  bReached = NULL;
+            return -1;
+        }
+
+        // save the onion ring
+        bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pCs2Glo );
+        if ( bTemp == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during ring transfer.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Cudd_RecursiveDeref( p->dd,  bCurrent );  bCurrent = NULL;
+            Cudd_RecursiveDeref( p->dd,  bConstrCs ); bConstrCs = NULL;
+            Cudd_RecursiveDeref( p->dd,  bConstrNs ); bConstrNs = NULL;
+            Cudd_RecursiveDeref( p->ddG, bReached );  bReached = NULL;
+            return -1;
+        }
+        Cudd_Ref( bTemp );
+        Vec_PtrPush( p->vRings, bTemp );
+
+        // check it for bad states
+        if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) 
+        {
+            assert( p->pAigGlo->pSeqModel == NULL );
+            if ( !p->pPars->fBackward )
+                p->pAigGlo->pSeqModel = Llb_ManReachDeriveCex( p ); 
+            if ( !p->pPars->fSilent )
+            {
+                if ( !p->pPars->fBackward )
+                    Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.  ", p->pAigGlo->pSeqModel->iPo, p->pAigGlo->pName, p->pAigGlo->pName, nIters );
+                else
+                    Abc_Print( 1, "Output ??? of miter \"%s\" was asserted in frame %d (counter-example is not produced).  ", p->pAigGlo->pName, nIters );
+                Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+            }
+            p->pPars->iFrame = nIters - 1;
+            Cudd_RecursiveDeref( p->dd,  bCurrent );  bCurrent = NULL;
+            Cudd_RecursiveDeref( p->dd,  bConstrCs ); bConstrCs = NULL;
+            Cudd_RecursiveDeref( p->dd,  bConstrNs ); bConstrNs = NULL;
+            Cudd_RecursiveDeref( p->ddG, bReached );  bReached = NULL;
+            return 0; 
+        }
+
+        // restrict reachable states using constraints
+        if ( vHints )
+        {
+            bCurrent = Cudd_bddAnd( p->dd, bTemp = bCurrent, bConstrCs );                                Cudd_Ref( bCurrent );
+            Cudd_RecursiveDeref( p->dd, bTemp );
+        }
+
+        // quantify variables appearing only in the init state
+        bCube    = Llb_ManConstructQuantCubeIntern( p, (Llb_Grp_t *)Vec_PtrEntry(p->vGroups,0), 0, 0 );  Cudd_Ref( bCube );
+        bCurrent = Cudd_bddExistAbstract( p->dd, bTemp = bCurrent, bCube );                              Cudd_Ref( bCurrent );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+        Cudd_RecursiveDeref( p->dd, bCube );
+
+        // compute the next states
+        bNext = Llb_ManComputeImage( p, bCurrent, 0 );
+        if ( bNext == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Cudd_RecursiveDeref( p->dd,  bCurrent );   bCurrent = NULL;
+            Cudd_RecursiveDeref( p->dd,  bConstrCs );  bConstrCs = NULL;
+            Cudd_RecursiveDeref( p->dd,  bConstrNs );  bConstrNs = NULL;
+            Cudd_RecursiveDeref( p->ddG, bReached );   bReached = NULL;
+            return -1;
+        }
+        Cudd_Ref( bNext );
+        Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+
+        // restrict reachable states using constraints
+        if ( vHints )
+        {
+            bNext = Cudd_bddAnd( p->dd, bTemp = bNext, bConstrNs );                Cudd_Ref( bNext );
+            Cudd_RecursiveDeref( p->dd, bTemp );
+        }
+//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" );
+
+        // remap these states into the current state vars
+//        bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo );    Cudd_Ref( bNext );
+//        Cudd_RecursiveDeref( p->dd, bTemp );
+//        bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pNs2Glo, p->pPars->TimeTarget );    
+        bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo );    
+        if ( bNext == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Cudd_RecursiveDeref( p->dd,  bTemp );  
+            Cudd_RecursiveDeref( p->dd,  bConstrCs );  bConstrCs = NULL;
+            Cudd_RecursiveDeref( p->dd,  bConstrNs );  bConstrNs = NULL;
+            Cudd_RecursiveDeref( p->ddG, bReached );   bReached = NULL;
+            return -1;
+        }
+        Cudd_Ref( bNext );
+        Cudd_RecursiveDeref( p->dd, bTemp );  
+
+
+        // check if there are any new states
+        if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states
+        {
+            Cudd_RecursiveDeref( p->ddG,  bNext );     bNext = NULL;
+            break;
+        }
+
+        // check the BDD size
+        nBddSize = Cudd_DagSize(bNext);
+        if ( nBddSize > p->pPars->nBddMax )
+        {
+            Cudd_RecursiveDeref( p->ddG,  bNext );     bNext = NULL;
+            break;
+        }
+
+        // get the new states
+        bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) );
+        if ( bCurrent == NULL )
+        {
+            Cudd_RecursiveDeref( p->ddG,  bNext );        bNext = NULL;
+            Cudd_RecursiveDeref( p->ddG,  bReached );     bReached = NULL;
+            break;
+        }
+        Cudd_Ref( bCurrent );
+        // minimize the new states with the reached states
+//        bCurrent = Cudd_bddConstrain( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent );
+//        bCurrent = Cudd_bddRestrict( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) );  Cudd_Ref( bCurrent );
+//        Cudd_RecursiveDeref( p->ddG, bTemp );
+//printf( "Initial BDD =%7d. Constrained BDD =%7d.\n", Cudd_DagSize(bTemp), Cudd_DagSize(bCurrent) );
+
+        // remap these states into the current state vars
+//        bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs );   Cudd_Ref( bCurrent );
+//        Cudd_RecursiveDeref( p->ddG, bTemp );
+//        bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs, p->pPars->TimeTarget );    
+        bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs );    
+        if ( bCurrent == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Cudd_RecursiveDeref( p->ddG, bTemp );  
+            Cudd_RecursiveDeref( p->dd,  bConstrCs );  bConstrCs = NULL;
+            Cudd_RecursiveDeref( p->dd,  bConstrNs );  bConstrNs = NULL;
+            Cudd_RecursiveDeref( p->ddG, bReached );   bReached = NULL;
+            return -1;
+        }
+        Cudd_Ref( bCurrent );
+        Cudd_RecursiveDeref( p->ddG, bTemp ); 
+        
+
+        // add to the reached states
+        bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext );                       
+        if ( bReached == NULL )
+        {
+            Cudd_RecursiveDeref( p->ddG,  bTemp );     bTemp = NULL;
+            Cudd_RecursiveDeref( p->ddG,  bNext );     bNext = NULL;
+            break;
+        }
+        Cudd_Ref( bReached );
+        Cudd_RecursiveDeref( p->ddG, bTemp );
+        Cudd_RecursiveDeref( p->ddG, bNext );
+        bNext = NULL;
+
+        if ( p->pPars->fVerbose )
+        {
+            fprintf( stdout, "F =%5d : ",    nIters );
+            fprintf( stdout, "Im =%6d  ",    nBddSize );
+            fprintf( stdout, "(%4d %3d)   ", Cudd_ReadReorderings(p->dd),  Cudd_ReadGarbageCollections(p->dd) );
+            fprintf( stdout, "Rea =%6d  ",   Cudd_DagSize(bReached) );
+            fprintf( stdout, "(%4d%4d)   ",  Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) );
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 );
+        }
+/*
+        if ( p->pPars->fVerbose )
+        {
+            double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) );
+//            Extra_bddPrint( p->ddG, bReached );printf( "\n" );
+            fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+            fflush( stdout ); 
+        }
+*/
+    }
+    Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL;
+    Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL;
+    if ( bReached == NULL )
+    {
+        p->pPars->iFrame = nIters - 1;
+        return 0; // reachable
+    }
+//    assert( bCurrent == NULL );
+    if ( bCurrent )
+        Cudd_RecursiveDeref( p->dd, bCurrent );
+    // report the stats
+    if ( p->pPars->fVerbose )
+    {
+        double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) );
+        if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax )
+            fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters );
+        else
+            fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters );
+        fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+        fflush( stdout ); 
+    }
+    if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax )
+    {
+        if ( !p->pPars->fSilent )
+            printf( "Verified only for states reachable in %d frames.  ", nIters );
+        p->pPars->iFrame = p->pPars->nIterMax;
+        Cudd_RecursiveDeref( p->ddG, bReached );
+        return -1; // undecided
+    }
+    if ( pddGlo ) 
+    {
+        assert( p->ddG->bFunc == NULL );
+        p->ddG->bFunc = bReached; bReached = NULL;
+        assert( *pddGlo == NULL );
+        *pddGlo = p->ddG;  p->ddG = NULL;
+    }
+    else
+        Cudd_RecursiveDeref( p->ddG, bReached );
+    if ( !p->pPars->fSilent )
+        printf( "The miter is proved unreachable after %d iterations.  ", nIters );
+    p->pPars->iFrame = nIters - 1;
+    return 1; // unreachable
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb1Sched.c b/abc-build/src/proof/llb/llb1Sched.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb1Sched.c
@@ -0,0 +1,257 @@
+/**CFile****************************************************************
+
+  FileName    [llb1Sched.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Partition scheduling algorithm.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb1Sched.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Swaps two rows.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_MtrSwapColumns( Llb_Mtr_t * p, int iCol1, int iCol2 )
+{
+    Llb_Grp_t * pGemp;
+    char * pTemp;
+    int iTemp;
+    assert( iCol1 >= 0 && iCol1 < p->nCols );
+    assert( iCol2 >= 0 && iCol2 < p->nCols );
+    if ( iCol1 == iCol2 )
+        return;
+    assert( iCol1 != iCol2 );
+    // swap col groups
+    pGemp = p->pColGrps[iCol1];
+    p->pColGrps[iCol1] = p->pColGrps[iCol2];
+    p->pColGrps[iCol2] = pGemp;
+    // swap col vectors
+    pTemp = p->pMatrix[iCol1];
+    p->pMatrix[iCol1] = p->pMatrix[iCol2];
+    p->pMatrix[iCol2] = pTemp;
+    // swap col sums
+    iTemp = p->pColSums[iCol1];
+    p->pColSums[iCol1] = p->pColSums[iCol2];
+    p->pColSums[iCol2] = iTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find columns which brings as few vars as possible.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_MtrFindBestColumn( Llb_Mtr_t * p, int iGrpStart )
+{
+    int Cost, Cost2, CostBest = ABC_INFINITY, Cost2Best = ABC_INFINITY;
+    int WeightCur, WeightBest = -ABC_INFINITY, iGrp = -1, iGrpBest = -1;
+    int k, c, iVar, Counter;
+    // find partition that reduces partial product as much as possible
+    for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ )
+    { 
+        if ( p->pRowSums[iVar] < 2 )
+            continue;
+        // look at present variables that can be quantified
+        if ( !(p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1) )
+            continue;
+        // check that it appears in one partition only
+        Counter = 0;
+        for ( c = iGrpStart; c < p->nCols-1; c++ )
+            if ( p->pMatrix[c][iVar] == 1 )
+            {
+                iGrp = c;
+                Counter++;
+            }
+        assert( Counter == 1 );
+        if ( Counter != 1 )
+            Abc_Print( -1, "Llb_MtrFindBestColumn() Internal error!\n" );
+        // find weight of this column
+        WeightCur = 0;
+        for ( k = 0; k < p->nRows; k++ )
+        {
+            // increase weight if variable k will be quantified from partial product
+            if ( p->pProdVars[k] == 1 && p->pMatrix[iGrp][k] == 1 && p->pProdNums[k] == 1 ) 
+                WeightCur += 2;
+            // decrease weight if variable k will be added to partial product
+            if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 )
+                WeightCur--;
+        }
+        if ( WeightCur > 0 && WeightBest < WeightCur )
+        {
+            WeightBest = WeightCur;
+            iGrpBest   = iGrp;
+        }
+    }
+    if ( iGrpBest >= 0 )
+        return iGrpBest;
+    // could not find the group with any vars to quantify
+    // select the group that contains as few extra variables as possible
+    // if there is a tie, select variables that appear in less groups than others
+    for ( iGrp = iGrpStart; iGrp < p->nCols-1; iGrp++ )
+    {
+        Cost = Cost2 = 0;
+        for ( k = 0; k < p->nRows; k++ )
+            if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 )
+            {
+                Cost++;
+                Cost2 += p->pProdNums[k];
+            }
+        if ( CostBest >  Cost || 
+            (CostBest == Cost && Cost2 > Cost2Best) )
+        {
+            CostBest  = Cost;
+            Cost2Best = Cost2;
+            iGrpBest  = iGrp;
+        }
+    }
+    return iGrpBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of variables that will be saved.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_MtrUseSelectedColumn( Llb_Mtr_t * p, int iCol )
+{
+    int iVar;
+    assert( iCol >= 1 && iCol < p->nCols - 1 );
+    for ( iVar = 0; iVar < p->nRows; iVar++ )
+    {
+        if ( p->pMatrix[iCol][iVar] == 0 )
+            continue;
+        if ( p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1 )
+        {
+            p->pProdVars[iVar] = 0;
+            p->pProdNums[iVar] = 0;
+            continue;
+        }
+        if ( p->pProdVars[iVar] == 0 )
+        {
+            p->pProdVars[iVar] = 1;
+            p->pProdNums[iVar] = p->pRowSums[iVar];
+        }
+        p->pProdNums[iVar]--;
+        assert( p->pProdNums[iVar] >= 0 );
+        if ( p->pProdNums[iVar] < 0 )
+            Abc_Print( -1, "Llb_MtrUseSelectedColumn() Internal error!\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verify columns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_MtrVerifyColumns( Llb_Mtr_t * p, int iGrpStart )
+{
+    int iVar, iGrp, Counter;
+    for ( iVar = 0; iVar < p->nRows; iVar++ )
+    {
+        if ( p->pProdVars[iVar] == 0 )
+            continue;
+        Counter = 0;
+        for ( iGrp = iGrpStart; iGrp < p->nCols; iGrp++ )
+            if ( p->pMatrix[iGrp][iVar] == 1 )
+                Counter++;
+        assert( Counter == p->pProdNums[iVar] );
+        if ( Counter != p->pProdNums[iVar] )
+            Abc_Print( -1, "Llb_MtrVerifyColumns(): Internal error.\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Matrix reduce.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_MtrSchedule( Llb_Mtr_t * p )
+{
+    int iGrp, iGrpBest, i;
+    // start partial product
+    for ( i = 0; i < p->nRows; i++ )
+    {
+        if ( i >= p->nPis && i < p->nPis + p->nFfs )
+        {
+            p->pProdVars[i] = 1;
+            p->pProdNums[i] = p->pRowSums[i] - 1;
+        }
+        else 
+        {
+            p->pProdVars[i] = 0;
+            p->pProdNums[i] = p->pRowSums[i];
+        }
+    }
+    // order the partitions
+    Llb_MtrVerifyMatrix( p );
+    for ( iGrp = 1; iGrp < p->nCols-1; iGrp++ )
+    {
+        Llb_MtrVerifyColumns( p, iGrp );
+        iGrpBest = Llb_MtrFindBestColumn( p, iGrp );
+        Llb_MtrUseSelectedColumn( p, iGrpBest );
+        Llb_MtrSwapColumns( p, iGrp, iGrpBest );
+    }
+    Llb_MtrVerifyMatrix( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb2Bad.c b/abc-build/src/proof/llb/llb2Bad.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb2Bad.c
@@ -0,0 +1,138 @@
+/**CFile****************************************************************
+
+  FileName    [llb2Bad.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Computing bad states.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb2Bad.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    [Computes bad in working manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, abctime TimeOut )
+{
+    Vec_Ptr_t * vNodes;
+    DdNode * bBdd0, * bBdd1, * bTemp, * bResult;
+    Aig_Obj_t * pObj;
+    int i, k;
+    assert( Cudd_ReadSize(dd) == Aig_ManCiNum(pInit) );
+    // initialize elementary variables
+    Aig_ManConst1(pInit)->pData = Cudd_ReadOne( dd );
+    Saig_ManForEachLo( pInit, pObj, i )
+        pObj->pData = Cudd_bddIthVar( dd, i );
+    Saig_ManForEachPi( pInit, pObj, i )
+        pObj->pData = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i );
+    // compute internal nodes
+    vNodes = Aig_ManDfsNodes( pInit, (Aig_Obj_t **)Vec_PtrArray(pInit->vCos), Saig_ManPoNum(pInit) );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        if ( !Aig_ObjIsNode(pObj) )
+            continue;
+        bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+        bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+//        pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut );
+        pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 );
+        if ( pObj->pData == NULL )
+        {
+            Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i )
+                if ( pObj->pData )
+                    Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+            Vec_PtrFree( vNodes );
+            return NULL;
+        }
+        Cudd_Ref( (DdNode *)pObj->pData );
+    }
+    // quantify PIs of each PO
+    bResult = Cudd_ReadLogicZero( dd );  Cudd_Ref( bResult );
+    Saig_ManForEachPo( pInit, pObj, i )
+    {
+        bBdd0   = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+        bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 );     Cudd_Ref( bResult );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    // deref
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        if ( !Aig_ObjIsNode(pObj) )
+            continue;
+        Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+    }
+    Vec_PtrFree( vNodes );
+    Cudd_Deref( bResult );
+    return bResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc )
+{
+    DdNode * bVar, * bCube, * bTemp;
+    Aig_Obj_t * pObj;
+    int i;
+    abctime TimeStop;
+    assert( Cudd_ReadSize(dd) == Aig_ManCiNum(pInit) );
+    TimeStop = dd->TimeStop; dd->TimeStop = 0;
+    // create PI cube
+    bCube = Cudd_ReadOne( dd );  Cudd_Ref( bCube );
+    Saig_ManForEachPi( pInit, pObj, i )    {
+        bVar  = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i );
+        bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar );  Cudd_Ref( bCube );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    // quantify PI cube
+    bFunc = Cudd_bddExistAbstract( dd, bFunc, bCube );  Cudd_Ref( bFunc );
+    Cudd_RecursiveDeref( dd, bCube );
+    Cudd_Deref( bFunc );
+    dd->TimeStop = TimeStop;
+    return bFunc;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb2Core.c b/abc-build/src/proof/llb/llb2Core.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb2Core.c
@@ -0,0 +1,777 @@
+/**CFile****************************************************************
+
+  FileName    [llb2Core.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Core procedure.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb2Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Img_t_ Llb_Img_t;
+struct Llb_Img_t_
+{
+    Aig_Man_t *     pInit;          // AIG manager
+    Aig_Man_t *     pAig;           // AIG manager
+    Gia_ParLlb_t *  pPars;          // parameters
+
+    DdManager *     dd;             // BDD manager
+    DdManager *     ddG;            // BDD manager
+    DdManager *     ddR;            // BDD manager
+    Vec_Ptr_t *     vDdMans;        // BDD managers for each partition
+    Vec_Ptr_t *     vRings;         // onion rings in ddR
+
+    Vec_Int_t *     vDriRefs;       // driver references
+    Vec_Int_t *     vVarsCs;        // cur state variables
+    Vec_Int_t *     vVarsNs;        // next state variables
+
+    Vec_Int_t *     vCs2Glo;        // cur state variables into global variables
+    Vec_Int_t *     vNs2Glo;        // next state variables into global variables
+    Vec_Int_t *     vGlo2Cs;        // global variables into cur state variables
+    Vec_Int_t *     vGlo2Ns;        // global variables into next state variables
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes cube composed of given variables with given values.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues )
+{
+    DdNode * bRes, * bVar, * bTemp;
+    int i, iVar, Index;
+    abctime TimeStop;
+    TimeStop = dd->TimeStop; dd->TimeStop = 0;
+    bRes = Cudd_ReadOne( dd );   Cudd_Ref( bRes );
+    Vec_IntForEachEntry( vVars, Index, i )
+    {
+        iVar  = fUseVarIndex ? Index : i;
+        bVar  = Cudd_NotCond( Cudd_bddIthVar(dd, iVar), (int)(pValues == NULL || pValues[i] != 1) );
+        bRes  = Cudd_bddAnd( dd, bTemp = bRes, bVar );  Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    Cudd_Deref( bRes );
+    dd->TimeStop = TimeStop;
+    return bRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives counter-example by backward reachability.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Llb_CoreDeriveCex( Llb_Img_t * p )
+{
+    Abc_Cex_t * pCex;
+    Aig_Obj_t * pObj;
+    Vec_Ptr_t * vSupps, * vQuant0, * vQuant1;
+    DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing;
+    int i, v, RetValue, nPiOffset;
+    char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) );
+    assert( Vec_PtrSize(p->vRings) > 0 );
+
+    p->dd->TimeStop  = 0;
+    p->ddR->TimeStop = 0;
+
+    // get supports and quantified variables
+    Vec_PtrReverseOrder( p->vDdMans );
+    vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 1, 0 );
+    Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, 0 );
+    Vec_VecFree( (Vec_Vec_t *)vSupps );
+    Llb_ImgQuantifyReset( p->vDdMans );
+//    Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0 );
+
+    // allocate room for the counter-example
+    pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) );
+    pCex->iFrame = Vec_PtrSize(p->vRings) - 1;
+    pCex->iPo = -1;
+
+    // get the last cube
+    bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc );  Cudd_Ref( bOneCube );
+    RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+    Cudd_RecursiveDeref( p->ddR, bOneCube );
+    assert( RetValue );
+
+    // write PIs of counter-example
+    nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1);
+    Saig_ManForEachPi( p->pAig, pObj, i )
+        if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+            Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+    // write state in terms of NS variables
+    if ( Vec_PtrSize(p->vRings) > 1 )
+    {
+        bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues );   Cudd_Ref( bState );
+    }
+    // perform backward analysis
+    Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v )
+    { 
+        if ( v == Vec_PtrSize(p->vRings) - 1 )
+            continue;
+        // compute the next states
+        bImage = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bState, 
+            vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget, 1, 0, 0 );
+        assert( bImage != NULL );
+        Cudd_Ref( bImage );
+        Cudd_RecursiveDeref( p->dd, bState );
+//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" );
+
+        // move reached states into ring manager
+        bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) );    Cudd_Ref( bImage );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+
+        // intersect with the previous set
+        bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing );                Cudd_Ref( bOneCube );
+        Cudd_RecursiveDeref( p->ddR, bImage );
+
+        // find any assignment of the BDD
+        RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+        Cudd_RecursiveDeref( p->ddR, bOneCube );
+        assert( RetValue );
+
+        // write PIs of counter-example
+        nPiOffset -= Saig_ManPiNum(p->pAig);
+        Saig_ManForEachPi( p->pAig, pObj, i )
+            if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+                Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+        // check that we get the init state
+        if ( v == 0 )
+        {
+            Saig_ManForEachLo( p->pAig, pObj, i )
+                assert( pValues[i] == 0 );
+            break;
+        }
+
+        // write state in terms of NS variables
+        bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues );   Cudd_Ref( bState );
+    }
+    assert( nPiOffset == Saig_ManRegNum(p->pAig) );
+    // update the output number
+    RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex );
+    assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!!
+    pCex->iPo = RetValue;
+    // cleanup
+    ABC_FREE( pValues );
+    Vec_VecFree( (Vec_Vec_t *)vQuant0 );
+    Vec_VecFree( (Vec_Vec_t *)vQuant1 );
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_CoreReachability_int( Llb_Img_t * p, Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1 )
+{
+    int * pLoc2Glo  = p->pPars->fBackward? Vec_IntArray( p->vCs2Glo ) : Vec_IntArray( p->vNs2Glo );
+    int * pLoc2GloR = p->pPars->fBackward? Vec_IntArray( p->vNs2Glo ) : Vec_IntArray( p->vCs2Glo );
+    int * pGlo2Loc  = p->pPars->fBackward? Vec_IntArray( p->vGlo2Ns ) : Vec_IntArray( p->vGlo2Cs );
+    DdNode * bCurrent, * bReached, * bNext, * bTemp;
+    abctime clk2, clk = Abc_Clock();
+    int nIters, nBddSize;//, iOutFail = -1;
+/*
+    // compute time to stop
+    if ( p->pPars->TimeLimit )
+        p->pPars->TimeTarget = Abc_Clock() + p->pPars->TimeLimit * CLOCKS_PER_SEC;
+    else
+        p->pPars->TimeTarget = 0;
+*/
+
+    if ( Abc_Clock() > p->pPars->TimeTarget )
+    {
+        if ( !p->pPars->fSilent )
+            printf( "Reached timeout (%d seconds) before image computation.\n", p->pPars->TimeLimit );
+        p->pPars->iFrame = -1;
+        return -1;
+    }
+
+    // set the stop time parameter
+    p->dd->TimeStop  = p->pPars->TimeTarget;
+    p->ddG->TimeStop = p->pPars->TimeTarget;
+    p->ddR->TimeStop = p->pPars->TimeTarget;
+
+    // compute initial states
+    if ( p->pPars->fBackward )
+    {
+        // create init state in the global manager
+        bTemp = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget );   
+        if ( bTemp == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit );
+            p->pPars->iFrame = -1;
+            return -1;
+        }
+        Cudd_Ref( bTemp );
+        // create bad state in the ring manager
+        p->ddR->bFunc = Llb_CoreComputeCube( p->ddR, p->vVarsCs, 0, NULL );      Cudd_Ref( p->ddR->bFunc );
+        bCurrent = Llb_BddQuantifyPis( p->pInit, p->ddR, bTemp );                Cudd_Ref( bCurrent );
+        Cudd_RecursiveDeref( p->ddR, bTemp );
+        bReached = Cudd_bddTransfer( p->ddR, p->ddG, bCurrent );                 Cudd_Ref( bReached );
+        Cudd_RecursiveDeref( p->ddR, bCurrent );
+        // move init state to the working manager
+        bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Loc );   
+        if ( bCurrent == NULL )
+        {
+            Cudd_RecursiveDeref( p->ddG, bReached );
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during transfer 0.\n", p->pPars->TimeLimit );
+            p->pPars->iFrame = -1;
+            return -1;
+        }
+        Cudd_Ref( bCurrent );
+    }
+    else
+    {
+        // create bad state in the ring manager
+        p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget );  
+        if ( p->ddR->bFunc == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit );
+            p->pPars->iFrame = -1;
+            return -1;
+        }
+        Cudd_Ref( p->ddR->bFunc );
+        // create init state in the working and global manager
+        bCurrent = Llb_CoreComputeCube( p->dd,  p->vVarsCs, 1, NULL );           Cudd_Ref( bCurrent );
+        bReached = Llb_CoreComputeCube( p->ddG, p->vVarsCs, 0, NULL );           Cudd_Ref( bReached );
+//Extra_bddPrint( p->dd, bCurrent );  printf( "\n" );
+//Extra_bddPrint( p->ddG, bReached );  printf( "\n" );
+    }
+
+    // compute onion rings
+    for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ )
+    { 
+        clk2 = Abc_Clock();
+        // check the runtime limit
+        if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Cudd_RecursiveDeref( p->dd,  bCurrent );  bCurrent = NULL;
+            Cudd_RecursiveDeref( p->ddG, bReached );  bReached = NULL;
+            return -1;
+        }
+
+        // save the onion ring
+        bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pLoc2GloR );  
+        if ( bTemp == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Cudd_RecursiveDeref( p->dd,  bCurrent );  bCurrent = NULL;
+            Cudd_RecursiveDeref( p->ddG, bReached );  bReached = NULL;
+            return -1;
+        }
+        Cudd_Ref( bTemp );
+        Vec_PtrPush( p->vRings, bTemp );
+
+        // check it for bad states
+        if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) 
+        {
+            assert( p->pInit->pSeqModel == NULL );
+            if ( !p->pPars->fBackward )
+                p->pInit->pSeqModel = Llb_CoreDeriveCex( p ); 
+            Cudd_RecursiveDeref( p->dd,  bCurrent );  bCurrent = NULL;
+            Cudd_RecursiveDeref( p->ddG, bReached );  bReached = NULL;
+            if ( !p->pPars->fSilent )
+            {
+                if ( !p->pPars->fBackward )
+                    Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.  ", p->pInit->pSeqModel->iPo, p->pInit->pName, nIters );
+                else
+                    Abc_Print( 1, "Output ??? was asserted in frame %d (counter-example is not produced).  ", nIters );
+                Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+            }
+            p->pPars->iFrame = nIters - 1;
+            return 0;
+        }
+
+        // compute the next states
+        bNext = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bCurrent, 
+            vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget, 
+            p->pPars->fBackward, p->pPars->fReorder, p->pPars->fVeryVerbose );
+        if ( bNext == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Cudd_RecursiveDeref( p->dd,  bCurrent );   bCurrent = NULL;
+            Cudd_RecursiveDeref( p->ddG, bReached );   bReached = NULL;
+            return -1;
+        }
+        Cudd_Ref( bNext );
+        Cudd_RecursiveDeref( p->dd, bCurrent );        bCurrent = NULL;
+//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" );
+
+        // remap these states into the global manager
+//        bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo );    Cudd_Ref( bNext );
+//        Cudd_RecursiveDeref( p->dd, bTemp );
+
+//        bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pLoc2Glo, p->pPars->TimeTarget );    
+        bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo );    
+        if ( bNext == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Cudd_RecursiveDeref( p->dd,  bTemp );  
+            Cudd_RecursiveDeref( p->ddG, bReached );   bReached = NULL;
+            return -1;
+        }
+        Cudd_Ref( bNext );
+        Cudd_RecursiveDeref( p->dd, bTemp );  
+
+        nBddSize = Cudd_DagSize(bNext);
+        // check if there are any new states
+        if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states
+        {
+            Cudd_RecursiveDeref( p->ddG,  bNext );     bNext = NULL;
+            break;
+        }
+
+        // get the new states
+        bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) );                    
+        if ( bCurrent == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Cudd_RecursiveDeref( p->ddG, bNext );  
+            Cudd_RecursiveDeref( p->ddG, bReached );   bReached = NULL;
+            return -1;
+        }
+        Cudd_Ref( bCurrent );
+
+        // remap these states into the current state vars
+//        bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc );   Cudd_Ref( bCurrent );
+//        Cudd_RecursiveDeref( p->ddG, bTemp );
+
+//        bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc, p->pPars->TimeTarget );    
+        bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc );    
+        if ( bCurrent == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Cudd_RecursiveDeref( p->ddG, bTemp );  
+            Cudd_RecursiveDeref( p->ddG, bReached );   bReached = NULL;
+            return -1;
+        }
+        Cudd_Ref( bCurrent );
+        Cudd_RecursiveDeref( p->ddG, bTemp );
+
+        // add to the reached states
+        bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext );                       Cudd_Ref( bReached );
+        Cudd_RecursiveDeref( p->ddG, bTemp );
+        Cudd_RecursiveDeref( p->ddG, bNext );
+        bNext = NULL;
+
+        if ( p->pPars->fVeryVerbose )
+        {
+            double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) );
+//            Extra_bddPrint( p->ddG, bReached );printf( "\n" );
+            fprintf( stdout, "        Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+            fflush( stdout ); 
+        }
+        if ( p->pPars->fVerbose )
+        {
+            fprintf( stdout, "F =%3d : ",    nIters );
+            fprintf( stdout, "Image =%6d  ", nBddSize );
+            fprintf( stdout, "(%4d%4d)  ", 
+                Cudd_ReadReorderings(p->dd),  Cudd_ReadGarbageCollections(p->dd) );
+            fprintf( stdout, "Reach =%6d  ", Cudd_DagSize(bReached) );
+            fprintf( stdout, "(%4d%4d)  ", 
+                Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) );
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 );
+        }
+
+        // check timeframe limit
+        if ( nIters == p->pPars->nIterMax - 1 )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached limit on the number of timeframes (%d).\n",  p->pPars->nIterMax );
+            p->pPars->iFrame = nIters;
+            Cudd_RecursiveDeref( p->dd,  bCurrent );  bCurrent = NULL;
+            Cudd_RecursiveDeref( p->ddG, bReached );  bReached = NULL;
+            return -1;
+        }
+    }
+    if ( bReached == NULL )
+    {
+        p->pPars->iFrame = nIters - 1;
+        return 0; // reachable
+    }
+    if ( bCurrent )
+        Cudd_RecursiveDeref( p->dd, bCurrent );
+    // report the stats
+    if ( p->pPars->fVerbose )
+    {
+        double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) );
+        if ( nIters >= p->pPars->nIterMax )
+            fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters );
+        else
+            fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters );
+        fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+        fflush( stdout ); 
+    }
+    if ( p->pPars->fDumpReached )
+    {
+        Llb_ManDumpReached( p->ddG, bReached, p->pAig->pName, "reached.blif" );
+        printf( "Reached states with %d BDD nodes are dumpted into file \"reached.blif\".\n", Cudd_DagSize(bReached) );
+    }
+    Cudd_RecursiveDeref( p->ddG, bReached );
+    if ( nIters >= p->pPars->nIterMax )
+    {
+        if ( !p->pPars->fSilent )
+        {
+            printf( "Verified only for states reachable in %d frames.  ", nIters );
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+        }
+        p->pPars->iFrame = p->pPars->nIterMax;
+        return -1; // undecided
+    }
+    if ( !p->pPars->fSilent )
+    {
+        printf( "The miter is proved unreachable after %d iterations.  ", nIters );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    p->pPars->iFrame = nIters - 1;
+    return 1; // unreachable
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_CoreReachability( Llb_Img_t * p )
+{
+    Vec_Ptr_t * vSupps, * vQuant0, * vQuant1;
+    int RetValue;
+    // get supports and quantified variables
+    if ( p->pPars->fBackward )
+    {
+        Vec_PtrReverseOrder( p->vDdMans );
+        vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 0, p->pPars->fVeryVerbose );
+    }
+    else
+        vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsCs, p->vVarsNs, 0, p->pPars->fVeryVerbose );
+    Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, p->pPars->fVeryVerbose );
+    Vec_VecFree( (Vec_Vec_t *)vSupps );
+    // remove variables
+    Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0, p->pPars->fVeryVerbose );
+    // perform reachability
+    RetValue = Llb_CoreReachability_int( p, vQuant0, vQuant1 );
+    Vec_VecFree( (Vec_Vec_t *)vQuant0 );
+    Vec_VecFree( (Vec_Vec_t *)vQuant1 );
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_CoreConstructAll( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Int_t * vVarsNs, abctime TimeTarget )
+{
+    DdManager * dd;
+    Vec_Ptr_t * vDdMans;
+    Vec_Ptr_t * vLower, * vUpper = NULL;
+    int i;
+    vDdMans = Vec_PtrStart( Vec_PtrSize(vResult) );
+    Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i )
+    {
+        if ( i < Vec_PtrSize(vResult) - 1 )
+            dd = Llb_ImgPartition( p, vLower, vUpper, TimeTarget );
+        else
+            dd = Llb_DriverLastPartition( p, vVarsNs, TimeTarget );
+        if ( dd == NULL )
+        {
+            Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i )
+            {
+                if ( dd == NULL )
+                    continue;
+                if ( dd->bFunc )
+                    Cudd_RecursiveDeref( dd, dd->bFunc );
+                Extra_StopManager( dd );
+            }
+            Vec_PtrFree( vDdMans );
+            return NULL;
+        }
+        Vec_PtrWriteEntry( vDdMans, i, dd );
+        vUpper = vLower;
+    }
+    return vDdMans;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_CoreSetVarMaps( Llb_Img_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, iVarCs, iVarNs;
+    assert( p->vVarsCs != NULL );
+    assert( p->vVarsNs != NULL );
+    assert( p->vCs2Glo == NULL );
+    assert( p->vNs2Glo == NULL );
+    assert( p->vGlo2Cs == NULL );
+    assert( p->vGlo2Ns == NULL );
+    p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) );
+    p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) );
+    p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+    p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+    for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ )
+    {
+        iVarCs = Vec_IntEntry( p->vVarsCs, i );
+        iVarNs = Vec_IntEntry( p->vVarsNs, i );
+        assert( iVarCs >= 0 && iVarCs < Aig_ManObjNumMax(p->pAig) );
+        assert( iVarNs >= 0 && iVarNs < Aig_ManObjNumMax(p->pAig) );
+        Vec_IntWriteEntry( p->vCs2Glo, iVarCs, i );
+        Vec_IntWriteEntry( p->vNs2Glo, iVarNs, i );
+        Vec_IntWriteEntry( p->vGlo2Cs, i, iVarCs );
+        Vec_IntWriteEntry( p->vGlo2Ns, i, iVarNs );
+    }
+    // add mapping of the PIs
+    Saig_ManForEachPi( p->pAig, pObj, i )
+        Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Llb_Img_t * Llb_CoreStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t *  pPars )
+{
+    Llb_Img_t * p;
+    p = ABC_CALLOC( Llb_Img_t, 1 );
+    p->pInit = pInit;
+    p->pAig  = pAig;
+    p->pPars = pPars;
+    p->dd    = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    p->ddG   = Cudd_Init( Aig_ManRegNum(pAig),    0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    p->ddR   = Cudd_Init( Aig_ManCiNum(pAig),     0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    Cudd_AutodynEnable( p->dd,  CUDD_REORDER_SYMM_SIFT );
+    Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT );
+    Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT );
+    p->vRings = Vec_PtrAlloc( 100 );
+    p->vDriRefs = Llb_DriverCountRefs( pAig );
+    p->vVarsCs  = Llb_DriverCollectCs( pAig );
+    p->vVarsNs  = Llb_DriverCollectNs( pAig, p->vDriRefs );
+    Llb_CoreSetVarMaps( p );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_CoreStop( Llb_Img_t * p )
+{
+    DdManager * dd;
+    DdNode * bTemp;
+    int i;
+    if ( p->vDdMans )
+    Vec_PtrForEachEntry( DdManager *, p->vDdMans, dd, i )
+    {
+        if ( dd->bFunc )
+            Cudd_RecursiveDeref( dd, dd->bFunc );
+        if ( dd->bFunc2 )
+            Cudd_RecursiveDeref( dd, dd->bFunc2 );
+        Extra_StopManager( dd );
+    }
+    Vec_PtrFreeP( &p->vDdMans );
+    if ( p->ddR->bFunc )
+        Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc );
+    Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i )
+        Cudd_RecursiveDeref( p->ddR, bTemp );
+    Vec_PtrFree( p->vRings );
+    Extra_StopManager( p->dd );
+    Extra_StopManager( p->ddG );
+    Extra_StopManager( p->ddR );
+    Vec_IntFreeP( &p->vDriRefs );
+    Vec_IntFreeP( &p->vVarsCs );
+    Vec_IntFreeP( &p->vVarsNs );
+    Vec_IntFreeP( &p->vCs2Glo );
+    Vec_IntFreeP( &p->vNs2Glo );
+    Vec_IntFreeP( &p->vGlo2Cs );
+    Vec_IntFreeP( &p->vGlo2Ns );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, abctime TimeTarget )
+{
+    int RetValue;
+    Llb_Img_t * p;
+//    printf( "\n" );
+//    pPars->fVerbose = 1;
+    p = Llb_CoreStart( pInit, pAig, pPars );
+    p->vDdMans = Llb_CoreConstructAll( pAig, vResult, p->vVarsNs, TimeTarget );
+    if ( p->vDdMans == NULL )
+    {
+        if ( !pPars->fSilent )
+            printf( "Reached timeout (%d seconds) while deriving the partitions.\n", pPars->TimeLimit );
+        Llb_CoreStop( p );
+        return -1;
+    }
+    RetValue = Llb_CoreReachability( p );
+    Llb_CoreStop( p );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds balanced cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManReachMinCut( Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+    extern Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose );
+    Vec_Ptr_t * vResult;
+    Aig_Man_t * p;
+    int RetValue = -1;
+    abctime clk = Abc_Clock();
+
+    // compute time to stop
+    pPars->TimeTarget = pPars->TimeLimit ? pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0;
+
+    p = Aig_ManDupFlopsOnly( pAig );
+//Aig_ManShow( p, 0, NULL );
+    if ( pPars->fVerbose )
+    Aig_ManPrintStats( pAig );
+    if ( pPars->fVerbose )
+    Aig_ManPrintStats( p );
+    Aig_ManFanoutStart( p );
+
+    vResult = Llb_ManComputeCuts( p, pPars->nPartValue, pPars->fVerbose, pPars->fVeryVerbose );
+
+    if ( pPars->TimeLimit && Abc_Clock() > pPars->TimeTarget )
+    {
+        if ( !pPars->fSilent )
+            printf( "Reached timeout (%d seconds) after partitioning.\n", pPars->TimeLimit );
+
+        Vec_VecFree( (Vec_Vec_t *)vResult );
+        Aig_ManFanoutStop( p );
+        Aig_ManCleanMarkAB( p );
+        Aig_ManStop( p );
+        return RetValue;
+    }
+
+    if ( !pPars->fSkipReach )
+        RetValue = Llb_CoreExperiment( pAig, p, pPars, vResult, pPars->TimeTarget );
+
+    Vec_VecFree( (Vec_Vec_t *)vResult );
+    Aig_ManFanoutStop( p );
+    Aig_ManCleanMarkAB( p );
+    Aig_ManStop( p );
+
+    if ( RetValue == -1 )
+        Abc_PrintTime( 1, "Total runtime of the min-cut-based reachability engine", Abc_Clock() - clk );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb2Driver.c b/abc-build/src/proof/llb/llb2Driver.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb2Driver.c
@@ -0,0 +1,222 @@
+/**CFile****************************************************************
+
+  FileName    [llb2Driver.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Procedures working with flop drivers.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb2Driver.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// driver issue:arises when creating
+// - driver ref-counter array
+// - Ns2Glo maps
+// - final partition
+// - change-phase cube
+
+// LI variable is used when
+// - driver drives more than one LI
+// - driver is a PI
+// - driver is a constant
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of times each flop driver is referenced.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p )
+{
+    Vec_Int_t * vCounts;
+    Aig_Obj_t * pObj;
+    int i;
+    vCounts = Vec_IntStart( Aig_ManObjNumMax(p) );
+    Saig_ManForEachLi( p, pObj, i )
+        Vec_IntAddToEntry( vCounts, Aig_ObjFaninId0(pObj), 1 );
+    return vCounts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns array of NS variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs )
+{
+    Vec_Int_t * vVars;
+    Aig_Obj_t * pObj, * pDri;
+    int i;
+    vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) );
+    Saig_ManForEachLi( pAig, pObj, i )
+    {
+        pDri = Aig_ObjFanin0(pObj);
+        if ( Vec_IntEntry( vDriRefs, Aig_ObjId(pDri) ) != 1 || Saig_ObjIsPi(pAig, pDri) || Aig_ObjIsConst1(pDri) )
+            Vec_IntPush( vVars, Aig_ObjId(pObj) );
+        else
+            Vec_IntPush( vVars, Aig_ObjId(pDri) );
+    }
+    return vVars;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns array of CS variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Llb_DriverCollectCs( Aig_Man_t * pAig )
+{
+    Vec_Int_t * vVars;
+    Aig_Obj_t * pObj;
+    int i;
+    vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) );
+    Saig_ManForEachLo( pAig, pObj, i )
+        Vec_IntPush( vVars, Aig_ObjId(pObj) );
+    return vVars;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create cube for phase swapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd )
+{
+    DdNode * bCube, * bVar, * bTemp;
+    Aig_Obj_t * pObj;
+    int i;
+    abctime TimeStop;
+    TimeStop = dd->TimeStop; dd->TimeStop = 0;
+    bCube = Cudd_ReadOne( dd );  Cudd_Ref( bCube );
+    Saig_ManForEachLi( pAig, pObj, i )
+    {
+        assert( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) >= 1 );
+        if ( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) != 1 )
+            continue;
+        if ( !Aig_ObjFaninC0(pObj) )
+            continue;
+        bVar  = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) );
+        bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar );  Cudd_Ref( bCube );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    Cudd_Deref( bCube );
+    dd->TimeStop = TimeStop;
+    return bCube;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the last partition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, abctime TimeTarget )
+{
+//    int fVerbose = 1;
+    DdManager * dd;
+    DdNode * bVar1, * bVar2, * bProd, * bRes, * bTemp;
+    Aig_Obj_t * pObj;
+    int i;
+    dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+    dd->TimeStop = TimeTarget;
+    bRes = Cudd_ReadOne(dd);                                   Cudd_Ref( bRes );
+
+    // mark the duplicated flop inputs
+    Aig_ManForEachObjVec( vVarsNs, p, pObj, i )
+    {
+        if ( !Saig_ObjIsLi(p, pObj) )
+            continue;
+        bVar1 = Cudd_bddIthVar( dd, Aig_ObjId(pObj) );
+        bVar2 = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) );
+        if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) )
+            bVar2 = Cudd_ReadOne(dd);
+        bVar2 = Cudd_NotCond( bVar2, Aig_ObjFaninC0(pObj) );
+        bProd = Cudd_bddXnor( dd, bVar1, bVar2 );              Cudd_Ref( bProd );
+//        bRes  = Cudd_bddAnd( dd, bTemp = bRes, bProd );        Cudd_Ref( bRes );
+//        bRes  = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget );  
+        bRes  = Cudd_bddAnd( dd, bTemp = bRes, bProd );  
+        if ( bRes == NULL )
+        {
+            Cudd_RecursiveDeref( dd, bTemp );
+            Cudd_RecursiveDeref( dd, bProd );
+            return NULL;
+        }        
+        Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bProd );
+    }
+
+/*
+    Saig_ManForEachLi( p, pObj, i )
+        printf( "%d ", Aig_ObjId(pObj) );
+    printf( "\n" );
+    Saig_ManForEachLi( p, pObj, i )
+        printf( "%c%d ", Aig_ObjFaninC0(pObj)? '-':'+', Aig_ObjFaninId0(pObj) );
+    printf( "\n" );
+*/
+    Cudd_AutodynDisable( dd );
+//    Cudd_RecursiveDeref( dd, bRes );
+//    Extra_StopManager( dd );
+    dd->bFunc = bRes;
+    dd->TimeStop = 0;
+    return dd;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb2Dump.c b/abc-build/src/proof/llb/llb2Dump.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb2Dump.c
@@ -0,0 +1,104 @@
+/**CFile****************************************************************
+
+  FileName    [llb2Dump.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Dumps the BDD of reached states into a file.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb2Dump.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns a dummy name.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Llb_ManGetDummyName( char * pPrefix, int Num, int nDigits )
+{
+    static char Buffer[2000];
+    sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num );
+    return Buffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes reached state BDD into a BLIF file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName )
+{
+    FILE * pFile;
+    Vec_Ptr_t * vNamesIn, * vNamesOut;
+    char * pName;
+    int i, nDigits;
+    // reorder the BDD
+    Cudd_ReduceHeap( ddG, CUDD_REORDER_SYMM_SIFT, 1 );
+
+    // create input names
+    nDigits = Abc_Base10Log( Cudd_ReadSize(ddG) );
+    vNamesIn = Vec_PtrAlloc( Cudd_ReadSize(ddG) );
+    for ( i = 0; i < Cudd_ReadSize(ddG); i++ )
+    {
+        pName = Llb_ManGetDummyName( "ff", i, nDigits );
+        Vec_PtrPush( vNamesIn, Extra_UtilStrsav(pName) );
+    }
+    // create output names
+    vNamesOut = Vec_PtrAlloc( 1 );
+    Vec_PtrPush( vNamesOut, Extra_UtilStrsav("Reached") );
+
+    // write the file
+    pFile = fopen( pFileName, "wb" );
+    Cudd_DumpBlif( ddG, 1, &bReached, (char **)Vec_PtrArray(vNamesIn), (char **)Vec_PtrArray(vNamesOut), pModel, pFile, 0 );
+    fclose( pFile );
+
+    // cleanup
+    Vec_PtrForEachEntry( char *, vNamesIn, pName, i )
+        ABC_FREE( pName );
+    Vec_PtrForEachEntry( char *, vNamesOut, pName, i )
+        ABC_FREE( pName );
+    Vec_PtrFree( vNamesIn );
+    Vec_PtrFree( vNamesOut );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb2Flow.c b/abc-build/src/proof/llb/llb2Flow.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb2Flow.c
@@ -0,0 +1,1376 @@
+/**CFile****************************************************************
+
+  FileName    [llb2Flow.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Flow computation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb2Flow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int         Llb_ObjSetPath( Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { pObj->pData = (void *)pNext; return 1;  }
+static inline Aig_Obj_t * Llb_ObjGetPath( Aig_Obj_t * pObj )                    { return (Aig_Obj_t *)pObj->pData;        }
+static inline Aig_Obj_t * Llb_ObjGetFanoutPath( Aig_Man_t * p, Aig_Obj_t * pObj ) 
+{ 
+    Aig_Obj_t * pFanout;
+    int i, iFanout = -1;
+    assert( Llb_ObjGetPath(pObj) ); 
+    Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
+        if ( Llb_ObjGetPath(pFanout) == pObj )
+            return pFanout;
+    return NULL;
+}
+
+extern Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    [For each cut, returns PIs that can be quantified.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManCutSupps( Aig_Man_t * p, Vec_Ptr_t * vResult )
+{
+    Vec_Ptr_t * vSupps, * vOne, * vLower, * vUpper;
+    int i;
+    vSupps = Vec_PtrAlloc( 100 );
+    Vec_PtrPush( vSupps, Vec_PtrAlloc(0) );
+    vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 );
+    Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 )
+    {
+        vOne  = Llb_ManCutSupp( p, vLower, vUpper );
+        Vec_PtrPush( vSupps, vOne );
+        vLower = vUpper;
+    }
+    assert( Vec_PtrSize(vSupps) == Vec_PtrSize(vResult) );
+    return vSupps;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [For each cut, returns PIs that can be quantified.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManCutMap( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Ptr_t * vSupps )
+{
+    int fShowMatrix = 1;
+    Vec_Ptr_t * vMaps, * vOne;
+    Vec_Int_t * vMap, * vPrev, * vNext;
+    Aig_Obj_t * pObj;
+    int * piFirst, * piLast;
+    int i, k, CounterPlus, CounterMinus, Counter;
+
+    vMaps = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Vec_Ptr_t *, vResult, vOne, i )
+    {
+        vMap = Vec_IntStart( Aig_ManObjNumMax(p) );
+        Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k )
+        {
+            if ( !Saig_ObjIsPi(p, pObj) )
+                Vec_IntWriteEntry( vMap, pObj->Id, 1 );
+//            else
+//printf( "*" );
+//printf( "%d ", pObj->Id );
+        }
+        Vec_PtrPush( vMaps, vMap );
+//printf( "\n" );
+    }
+    Vec_PtrPush( vMaps, Vec_IntStart( Aig_ManObjNumMax(p) ) );
+    assert( Vec_PtrSize(vMaps) == Vec_PtrSize(vResult)+1 );
+
+    // collect the first and last PIs
+    piFirst = ABC_ALLOC( int, Saig_ManPiNum(p) );
+    piLast  = ABC_ALLOC( int, Saig_ManPiNum(p) );
+    Saig_ManForEachPi( p, pObj, i )
+        piFirst[i] = piLast[i] = -1;
+    Vec_PtrForEachEntry( Vec_Ptr_t *, vSupps, vOne, i )
+    {
+        Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k )
+        {
+            if ( !Saig_ObjIsPi(p, pObj) )
+                continue;
+            if ( piFirst[Aig_ObjCioId(pObj)] == -1 )
+                 piFirst[Aig_ObjCioId(pObj)] = i;
+            piLast[Aig_ObjCioId(pObj)] = i;
+        }
+    }
+    // PIs feeding into the flops should be extended to the last frame
+    Saig_ManForEachLi( p, pObj, i )
+    {
+        if ( !Saig_ObjIsPi(p, Aig_ObjFanin0(pObj)) )
+            continue;
+        piLast[Aig_ObjCioId(Aig_ObjFanin0(pObj))] = Vec_PtrSize(vMaps)-1;
+    }
+
+    // set the PI map
+    Saig_ManForEachPi( p, pObj, i )
+    {
+        if ( piFirst[i] == -1 )
+            continue;
+        if ( piFirst[i] == piLast[i] )
+        {
+            vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, piFirst[i] );
+            Vec_IntWriteEntry( vMap, pObj->Id, 2 );
+            continue;
+        }
+
+        // set support for all in between        
+        for ( k = piFirst[i]; k <= piLast[i]; k++ )
+        {
+            vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, k );
+            Vec_IntWriteEntry( vMap, pObj->Id, 1 );
+        }
+    }
+    ABC_FREE( piFirst );
+    ABC_FREE( piLast );
+
+
+    // find all that will appear here
+    Counter = Aig_ManRegNum(p);
+    printf( "%d ", Counter );
+    Vec_PtrForEachEntryStart( Vec_Int_t *, vMaps, vMap, i, 1 )
+    {
+        vPrev = (Vec_Int_t *)Vec_PtrEntry( vMaps, i-1 );
+        vNext = (i == Vec_PtrSize(vMaps)-1)? NULL: (Vec_Int_t *)Vec_PtrEntry( vMaps, i+1 );
+
+        CounterPlus = CounterMinus = 0;
+        Aig_ManForEachObj( p, pObj, k )
+        {
+            if ( Saig_ObjIsPi(p, pObj) )
+            {
+                if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 )
+                    CounterPlus++;
+                if ( Vec_IntEntry(vMap, k) == 1 && (vNext == NULL || Vec_IntEntry(vNext, k) == 0) )
+                    CounterMinus++;
+            }
+            else
+            {
+                if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 )
+                    CounterPlus++;
+                if ( Vec_IntEntry(vPrev, k) == 1 && Vec_IntEntry(vMap, k) == 0 )
+                    CounterMinus++;
+            }
+        }
+        Counter = Counter + CounterPlus - CounterMinus;
+        printf( "%d=%d ", i, Counter );
+    }
+    printf( "\n" );
+
+    if ( !fShowMatrix )
+        return vMaps;
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) )
+            continue;
+        Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k )
+            if ( Vec_IntEntry(vMap, i) )
+                break;
+        if ( k == Vec_PtrSize(vMaps) )
+            continue;
+        printf( "Obj = %4d : ", i );
+        if ( Saig_ObjIsPi(p,pObj) )
+            printf( "pi  " );
+        else if ( Saig_ObjIsLo(p,pObj) )
+            printf( "lo  " );
+        else if ( Aig_ObjIsNode(pObj) )
+            printf( "and " );
+
+        Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k )
+            printf( "%d", Vec_IntEntry(vMap, i) );
+        printf( "\n" );
+    }
+    return vMaps;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of PIs in the cut]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManCutPiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i )
+        if ( Saig_ObjIsPi(p,pObj) )
+            Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of LOs in the cut]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManCutLoNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i )
+        if ( Saig_ObjIsLo(p,pObj) )
+            Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of LIs in the cut]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManCutLiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut )
+{
+    Aig_Obj_t * pFanout;
+    Aig_Obj_t * pObj;
+    int i, k, iFanout = -1, Counter = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i )
+    {
+        if ( Aig_ObjIsCi(pObj) )
+            continue;
+        Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, k )
+        {
+            if ( Saig_ObjIsLi(p, pFanout) )
+            {
+                Counter++;
+                break;
+            }
+        }
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes volume of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManCutVolume_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return 0;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    assert( Aig_ObjIsNode(pObj) );
+    return 1 + Llb_ManCutVolume_rec(p, Aig_ObjFanin0(pObj)) + 
+        Llb_ManCutVolume_rec(p, Aig_ObjFanin1(pObj));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes volume of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManCutVolume( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    // mark the lower cut with the traversal ID
+    Aig_ManIncrementTravId(p);
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+        Aig_ObjSetTravIdCurrent( p, pObj );
+    // count the upper cut
+    Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+        Counter += Llb_ManCutVolume_rec( p, pObj );
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes volume of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    assert( Aig_ObjIsNode(pObj) );
+    Llb_ManCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes);
+    Llb_ManCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes);
+    Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes volume of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i;
+    // mark the lower cut with the traversal ID
+    Aig_ManIncrementTravId(p);
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+        Aig_ObjSetTravIdCurrent( p, pObj );
+    // count the upper cut
+    vNodes = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+        Llb_ManCutNodes_rec( p, pObj, vNodes );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes volume of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+    Vec_Ptr_t * vNodes, * vSupp;
+    Aig_Obj_t * pObj;
+    int i;
+    vNodes = Llb_ManCutNodes( p, vLower, vUpper );
+    // mark support of the nodes
+    Aig_ManIncrementTravId(p);
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        assert( Aig_ObjIsNode(pObj) );
+        Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin0(pObj) );
+        Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin1(pObj) );
+    }
+    Vec_PtrFree( vNodes );
+    // collect the support nodes
+    vSupp = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+        if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+            Vec_PtrPush( vSupp, pObj );
+    return vSupp;
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes volume of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+    Vec_Ptr_t * vRange;
+    Aig_Obj_t * pObj;
+    int i;
+    // mark the lower cut with the traversal ID
+    Aig_ManIncrementTravId(p);
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+        Aig_ObjSetTravIdCurrent( p, pObj );
+    // collect the upper ones that are not marked
+    vRange = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+        if ( !Aig_ObjIsTravIdCurrent(p, pObj) )
+            Vec_PtrPush( vRange, pObj );
+    return vRange;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the given cluster.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManCutPrint( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+    Vec_Ptr_t * vSupp, * vRange;
+    int Pis, Ffs, And;
+
+    Pis = Llb_ManCutPiNum(p, vLower);
+    Ffs = Llb_ManCutLoNum(p, vLower);
+    And = Vec_PtrSize(vLower) - Pis - Ffs;
+    printf( "Leaf: %3d=%3d+%3d+%3d  ",  Vec_PtrSize(vLower), Pis, Ffs, And );
+
+    Pis = Llb_ManCutPiNum(p, vUpper);
+    Ffs = Llb_ManCutLiNum(p, vUpper);
+    And = Vec_PtrSize(vUpper) - Pis - Ffs;
+    printf( "Root: %3d=%3d+%3d+%3d  ", Vec_PtrSize(vUpper), Pis, Ffs, And );
+
+    vSupp = Llb_ManCutSupp( p, vLower, vUpper );
+    Pis = Llb_ManCutPiNum(p, vSupp);
+    Ffs = Llb_ManCutLoNum(p, vSupp);
+    And = Vec_PtrSize(vSupp) - Pis - Ffs;
+    printf( "Supp: %3d=%3d+%3d+%3d  ", Vec_PtrSize(vSupp), Pis, Ffs, And );
+
+    vRange = Llb_ManCutRange( p, vLower, vUpper );
+    Pis = Llb_ManCutPiNum(p, vRange);
+    Ffs = Llb_ManCutLiNum(p, vRange);
+    And = Vec_PtrSize(vRange) - Pis - Ffs;
+    printf( "Range: %3d=%3d+%3d+%3d  ", Vec_PtrSize(vRange), Pis, Ffs, And );
+
+    printf( "S =%3d. V =%3d.\n", 
+        Vec_PtrSize(vSupp)+Vec_PtrSize(vRange), Llb_ManCutVolume(p, vLower, vUpper) );
+    Vec_PtrFree( vSupp );
+    Vec_PtrFree( vRange );
+/*   
+    {
+        Aig_Obj_t * pObj;
+        int i;
+        printf( "Lower: " );
+        Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+            printf( " %d", pObj->Id );
+        printf( "     " );
+        printf( "Upper: " );
+        Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+            printf( " %d", pObj->Id );
+        printf( "\n" );
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the given cluster.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManResultPrint( Aig_Man_t * p, Vec_Ptr_t * vResult )
+{
+    Vec_Ptr_t * vLower, * vUpper = NULL;
+    int i;
+    Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i )
+    {
+        if ( i < Vec_PtrSize(vResult) - 1 )
+            Llb_ManCutPrint( p, vLower, vUpper );
+        vUpper = vLower;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tries to find an augmenting path originating in this node.]
+
+  Description [This procedure works for directed graphs only!]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManFlowBwdPath2_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pFanout;
+    assert( Aig_ObjIsNode(pObj) || Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) );
+    // skip visited nodes
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return 0;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    // process node without flow
+    if ( !Llb_ObjGetPath(pObj) )
+    {
+        // start the path if we reached a terminal node
+        if ( pObj->fMarkA )
+            return Llb_ObjSetPath( pObj, (Aig_Obj_t *)1 );
+        // explore the fanins
+//        Abc_ObjForEachFanin( pObj, pFanin, i )
+//            if ( Abc_NtkMaxFlowBwdPath2_rec(pFanin) )
+//                return Abc_ObjSetPath( pObj, pFanin );
+        if ( Aig_ObjIsNode(pObj) )
+        {
+            if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ) )
+                return Llb_ObjSetPath( pObj, Aig_ObjFanin0(pObj) );
+            if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ) )
+                return Llb_ObjSetPath( pObj, Aig_ObjFanin1(pObj) );
+        }
+        return 0;
+    }
+    // pObj has flow - find the fanout with flow
+    pFanout = Llb_ObjGetFanoutPath( p, pObj );
+    if ( pFanout == NULL )
+        return 0;
+    // go through the fanins of the fanout with flow
+//    Abc_ObjForEachFanin( pFanout, pFanin, i )
+//        if ( Abc_NtkMaxFlowBwdPath2_rec( pFanin ) )
+//            return Abc_ObjSetPath( pFanout, pFanin );
+    assert( Aig_ObjIsNode(pFanout) );
+    if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pFanout) ) )
+        return Llb_ObjSetPath( pFanout, Aig_ObjFanin0(pFanout) );
+    if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pFanout) ) )
+        return Llb_ObjSetPath( pFanout, Aig_ObjFanin1(pFanout) );
+    // try the fanout
+    if ( Llb_ManFlowBwdPath2_rec( p, pFanout ) )
+        return Llb_ObjSetPath( pFanout, NULL );
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans markB.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManFlowLabelTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) )
+        return;
+    assert( Aig_ObjIsNode(pObj) );
+    Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin0(pObj) );
+    Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManFlowUpdateCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    // label the TFI of the cut nodes
+    Aig_ManIncrementTravId(p);
+    Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i )
+        Llb_ManFlowLabelTfi_rec( p, pObj );
+    // collect labeled fanins of non-labeled nodes
+    Vec_PtrClear( vMinCut );
+    Aig_ManIncrementTravId(p);
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( !Aig_ObjIsCo(pObj) && !Aig_ObjIsNode(pObj) )
+            continue;
+        if ( Aig_ObjIsTravIdCurrent(p, pObj) || Aig_ObjIsTravIdPrevious(p, pObj) )
+            continue;
+        if ( Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin0(pObj)) )
+        {
+            Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin0(pObj));
+            Vec_PtrPush( vMinCut, Aig_ObjFanin0(pObj) );
+        }
+        if ( Aig_ObjIsNode(pObj) && Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin1(pObj)) )
+        {
+            Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin1(pObj));
+            Vec_PtrPush( vMinCut, Aig_ObjFanin1(pObj) );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find minimum-volume minumum cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManFlowMinCut( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vMinCut;
+    Aig_Obj_t * pObj;
+    int i;
+    // collect the cut nodes
+    vMinCut = Vec_PtrAlloc( Aig_ManRegNum(p) );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        // node without flow is not a cut node
+        if ( !Llb_ObjGetPath(pObj) )
+            continue;
+        // unvisited node is below the cut
+        if ( !Aig_ObjIsTravIdCurrent(p, pObj) )
+            continue;
+        // add terminal with flow or node whose path is not visited
+        if ( pObj->fMarkA || !Aig_ObjIsTravIdCurrent( p, Llb_ObjGetPath(pObj) ) )
+            Vec_PtrPush( vMinCut, pObj );
+    }
+    return vMinCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the min-cut is indeed a cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManFlowVerifyCut_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    // skip visited nodes
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return 1;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    // visit the node
+    if ( Aig_ObjIsConst1(pObj) )
+        return 1;
+    if ( Aig_ObjIsCi(pObj) )
+        return 0;
+    // explore the fanins
+    assert( Aig_ObjIsNode(pObj) );
+    if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin0(pObj)) )
+        return 0;
+    if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin1(pObj)) )
+        return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the min-cut is indeed a cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_ManFlowVerifyCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    // mark the cut with the current traversal ID
+    Aig_ManIncrementTravId(p);
+    Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i )
+        Aig_ObjSetTravIdCurrent( p, pObj );
+    // search from the latches for a path to the COs/CIs
+    Saig_ManForEachLi( p, pObj, i )
+    {
+        if ( !Llb_ManFlowVerifyCut_rec( p, Aig_ObjFanin0(pObj) ) )
+            return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implementation of max-flow/min-cut computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow )
+{
+    Vec_Ptr_t * vMinCut;
+    Aig_Obj_t * pObj;
+    int Flow, FlowCur, RetValue, i;
+    // find the max-flow
+    Flow = 0;
+    Aig_ManCleanData( p );
+    Aig_ManIncrementTravId(p);
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i )
+    {
+        assert( !pObj->fMarkA && pObj->fMarkB );
+        if ( !Aig_ObjFanin0(pObj)->fMarkB )
+        {
+            FlowCur  = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) );
+            Flow    += FlowCur;
+            if ( FlowCur )
+                Aig_ManIncrementTravId(p);
+        }
+        if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB )
+        {
+            FlowCur  = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) );
+            Flow    += FlowCur;
+            if ( FlowCur )
+                Aig_ManIncrementTravId(p);
+        }
+    }
+    if ( pnFlow )
+        *pnFlow = Flow;
+
+    // mark the nodes reachable from the latches
+    Aig_ManIncrementTravId(p);
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i )
+    {
+        assert( !pObj->fMarkA && pObj->fMarkB );
+        if ( !Aig_ObjFanin0(pObj)->fMarkB )
+        {
+            RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) );
+            assert( RetValue == 0 );
+        }
+        if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB )
+        {
+            RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) );
+            assert( RetValue == 0 );
+        }
+    }
+
+    // find the min-cut with the smallest volume
+    vMinCut = Llb_ManFlowMinCut( p );
+    assert( Vec_PtrSize(vMinCut) == Flow );
+    // verify the cut
+    if ( !Llb_ManFlowVerifyCut(p, vMinCut) )
+        printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" );
+//    Llb_ManFlowPrintCut( p, vMinCut );
+    return vMinCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Implementation of max-flow/min-cut computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManFlowCompute( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vMinCut;
+    Aig_Obj_t * pObj;
+    int Flow, FlowCur, RetValue, i;
+    // find the max-flow
+    Flow = 0;
+    Aig_ManCleanData( p );
+    Aig_ManIncrementTravId(p);
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( !pObj->fMarkB )
+            continue;
+        assert( !pObj->fMarkA );
+        if ( !Aig_ObjFanin0(pObj)->fMarkB )
+        {
+//printf( "%d ", Aig_ObjFanin0(pObj)->Id );
+            FlowCur  = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) );
+            Flow    += FlowCur;
+            if ( FlowCur )
+                Aig_ManIncrementTravId(p);
+        }
+        if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB )
+        {
+//printf( "%d ", Aig_ObjFanin1(pObj)->Id );
+            FlowCur  = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) );
+            Flow    += FlowCur;
+            if ( FlowCur )
+                Aig_ManIncrementTravId(p);
+        }
+    }
+//printf( "\n" );
+
+    // mark the nodes reachable from the latches
+    Aig_ManIncrementTravId(p);
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( !pObj->fMarkB )
+            continue;
+        assert( !pObj->fMarkA );
+        if ( !Aig_ObjFanin0(pObj)->fMarkB )
+        {
+            RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) );
+            assert( RetValue == 0 );
+        }
+        if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB )
+        {
+            RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) );
+            assert( RetValue == 0 );
+        }
+    }
+    // find the min-cut with the smallest volume
+    vMinCut = Llb_ManFlowMinCut( p );
+    assert( Vec_PtrSize(vMinCut) == Flow );
+//printf( "%d ", Vec_PtrSize(vMinCut) );
+    Llb_ManFlowUpdateCut( p, vMinCut );
+//printf( "%d   ", Vec_PtrSize(vMinCut) );
+    // verify the cut
+    if ( !Llb_ManFlowVerifyCut(p, vMinCut) )
+        printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" );
+//    Llb_ManFlowPrintCut( p, vMinCut );
+    return vMinCut;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans markB.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManFlowCleanMarkB_rec( Aig_Obj_t * pObj )
+{
+    if ( pObj->fMarkB == 0 )
+        return;
+    pObj->fMarkB = 0;
+    assert( Aig_ObjIsNode(pObj) );
+    Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin0(pObj) );
+    Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans markB.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManFlowSetMarkA_rec( Aig_Obj_t * pObj )
+{
+    if ( pObj->fMarkA )
+        return;
+    pObj->fMarkA = 1;
+    if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) )
+        return;
+    assert( Aig_ObjIsNode(pObj) );
+    Llb_ManFlowSetMarkA_rec( Aig_ObjFanin0(pObj) );
+    Llb_ManFlowSetMarkA_rec( Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares flow computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManFlowPrepareCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    // reset marks
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        pObj->fMarkA = 0;
+        pObj->fMarkB = 1;
+    }
+    // clean PIs and const
+    Aig_ManConst1(p)->fMarkB = 0;
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->fMarkB = 0;
+    // clean upper cut
+//printf( "Upper: ");
+    Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+    {
+        Llb_ManFlowCleanMarkB_rec( pObj );
+//printf( "%d ", pObj->Id );
+    }
+//printf( "\n" );
+    // set lower cut
+//printf( "Lower: ");
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+    {
+//printf( "%d ", pObj->Id );
+        assert( pObj->fMarkB == 0 );
+        Llb_ManFlowSetMarkA_rec( pObj );
+    }
+//printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares flow computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManFlowUnmarkCone( Aig_Man_t * p, Vec_Ptr_t * vCone )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vCone, pObj, i )
+    {
+        assert( Aig_ObjIsNode(pObj) );
+        assert( pObj->fMarkB == 1 );
+        pObj->fMarkB = 0;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManFlowCollectAndMarkCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vCone )
+{
+    Aig_Obj_t * pFanout;
+    int i, iFanout = -1;
+    if ( Saig_ObjIsLi(p, pObj) )
+        return;
+    if ( pObj->fMarkB )
+        return;
+    if ( pObj->fMarkA == 0 )
+    {
+        assert( Aig_ObjIsNode(pObj) );
+        pObj->fMarkB = 1;
+        if ( Aig_ObjIsNode(pObj) )
+            Vec_PtrPush( vCone, pObj );
+    }
+    Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
+        Llb_ManFlowCollectAndMarkCone_rec( p, pFanout, vCone );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManFlowCollectAndMarkCone( Aig_Man_t * p, Vec_Ptr_t * vStarts, Vec_Ptr_t * vCone )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Vec_PtrClear( vCone );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vStarts, pObj, i )
+    {
+        assert( pObj->fMarkA && !pObj->fMarkB );
+        Llb_ManFlowCollectAndMarkCone_rec( p, pObj, vCone );
+    }
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds balanced cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManComputeCutLo( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vMinCut;
+    Aig_Obj_t * pObj;
+    int i;
+    vMinCut = Vec_PtrAlloc( 100 );
+    Aig_ManForEachCi( p, pObj, i )
+        Vec_PtrPush( vMinCut, pObj );
+    return vMinCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds balanced cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManComputeCutLi( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vMinCut;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( Saig_ManPoNum(p) == 0 );
+    vMinCut = Vec_PtrAlloc( 100 );
+    Aig_ManIncrementTravId(p);
+    Saig_ManForEachLi( p, pObj, i )
+    {
+        pObj = Aig_ObjFanin0(pObj);
+        if ( Aig_ObjIsConst1(pObj) )
+            continue;
+        if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+            continue;
+        Aig_ObjSetTravIdCurrent(p, pObj);
+        Vec_PtrPush( vMinCut, pObj );
+    }
+    return vMinCut;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds balanced cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManFlowGetObjSet( Aig_Man_t * p, Vec_Ptr_t * vLower, int iStart, int nSize, Vec_Ptr_t * vSet )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Vec_PtrClear( vSet );
+    for ( i = 0; i < nSize; i++ )
+    {
+        pObj = (Aig_Obj_t *)Vec_PtrEntry( vLower, (iStart + i) % Vec_PtrSize(vLower) );
+        Vec_PtrPush( vSet, pObj );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds balanced cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManFlowFindBestCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, int Num )
+{
+    int nVolMin = Aig_ManNodeNum(p) / Num / 2;
+    Vec_Ptr_t * vMinCut;
+    Vec_Ptr_t * vCone, * vSet;
+    Aig_Obj_t * pObj;
+    int i, s, Vol, VolLower, VolUpper, VolCmp;
+    int iBest = -1, iMinCut = ABC_INFINITY, iVolBest = 0;
+
+    Vol = Llb_ManCutVolume( p, vLower, vUpper );
+    assert( Vol > nVolMin );
+    VolCmp = Abc_MinInt( nVolMin, Vol - nVolMin );
+    vCone = Vec_PtrAlloc( 100 );
+    vSet  = Vec_PtrAlloc( 100 );
+    Llb_ManFlowPrepareCut( p, vLower, vUpper );
+    for ( s = 1; s < Aig_ManRegNum(p); s += 5 )
+    {
+        Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+        {
+            Llb_ManFlowGetObjSet( p, vLower, i, s, vSet );
+            Llb_ManFlowCollectAndMarkCone( p, vSet, vCone );
+            if ( Vec_PtrSize(vCone) == 0 )
+                continue;
+            vMinCut  = Llb_ManFlowCompute( p );
+            Llb_ManFlowUnmarkCone( p, vCone );
+
+            VolLower = Llb_ManCutVolume( p, vLower, vMinCut );
+            VolUpper = Llb_ManCutVolume( p, vMinCut, vUpper );
+            Vol = Abc_MinInt( VolLower, VolUpper );
+            if ( Vol >= VolCmp &&  (iMinCut == -1 || 
+                                    iMinCut >  Vec_PtrSize(vMinCut) || 
+                                   (iMinCut == Vec_PtrSize(vMinCut) && iVolBest < Vol)) )
+            {
+                iBest = i;
+                iMinCut = Vec_PtrSize(vMinCut);
+                iVolBest = Vol;
+            }
+            Vec_PtrFree( vMinCut );
+        }
+        if ( iBest >= 0 )
+            break;
+    }
+    if ( iBest == -1 )
+    {
+        // cleanup
+        Vec_PtrFree( vCone );
+        Vec_PtrFree( vSet );
+        return NULL;
+    }
+    // get the best cut
+    assert( iBest >= 0 );
+    Llb_ManFlowGetObjSet( p, vLower, iBest, s, vSet );
+    Llb_ManFlowCollectAndMarkCone( p, vSet, vCone );
+    vMinCut = Llb_ManFlowCompute( p );
+    Llb_ManFlowUnmarkCone( p, vCone );
+    // cleanup
+    Vec_PtrFree( vCone );
+    Vec_PtrFree( vSet );
+    return vMinCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds balanced cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose )
+{
+    int nVolMax = Aig_ManNodeNum(p) / Num;
+    Vec_Ptr_t * vResult, * vMinCut = NULL, * vLower, * vUpper;
+    int i, k, nVol;
+    abctime clk = Abc_Clock();
+    vResult = Vec_PtrAlloc( 100 );
+    Vec_PtrPush( vResult, Llb_ManComputeCutLo(p) );
+    Vec_PtrPush( vResult, Llb_ManComputeCutLi(p) );
+    while ( 1 ) 
+    {
+        // find a place to insert new cut
+        vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 );
+        Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 )
+        {
+            nVol = Llb_ManCutVolume( p, vLower, vUpper );
+            if ( nVol <= nVolMax )
+            {
+                vLower = vUpper;
+                continue;
+            }
+
+            if ( fVeryVerbose )
+            Llb_ManCutPrint( p, vLower,  vUpper );
+            vMinCut = Llb_ManFlowFindBestCut( p, vLower, vUpper, Num );
+            if ( vMinCut == NULL )
+            {
+                if ( fVeryVerbose )
+                printf( "Could not break the cut.\n" );
+                if ( fVeryVerbose )
+                printf( "\n" );
+                vLower = vUpper;
+                continue;
+            }
+
+            if ( fVeryVerbose )
+            Llb_ManCutPrint( p, vMinCut, vUpper );
+            if ( fVeryVerbose )
+            Llb_ManCutPrint( p, vLower,  vMinCut );
+            if ( fVeryVerbose )
+            printf( "\n" );
+
+            break;
+        }
+        if ( i == Vec_PtrSize(vResult) )
+            break;
+        // insert vMinCut before vUpper
+        Vec_PtrPush( vResult, NULL );
+        for ( k = Vec_PtrSize(vResult) - 1; k > i; k-- )
+            Vec_PtrWriteEntry( vResult, k, Vec_PtrEntry(vResult, k-1) );
+        Vec_PtrWriteEntry( vResult, i, vMinCut );
+    }
+    if ( fVerbose )
+    {
+        printf( "Finished computing %d partitions.  ", Vec_PtrSize(vResult) - 1 );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+        Llb_ManResultPrint( p, vResult );
+    }
+    return vResult;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_BddSetDefaultParams( Gia_ParLlb_t * p )
+{
+    memset( p, 0, sizeof(Gia_ParLlb_t) );
+    p->nBddMax       =  1000000;
+    p->nIterMax      = 10000000;
+    p->nClusterMax   =       20;
+    p->nHintDepth    =        0;
+    p->HintFirst     =        0;
+    p->fUseFlow      =        0;  // use flow 
+    p->nVolumeMax    =      100;  // max volume
+    p->nVolumeMin    =       30;  // min volume
+    p->fReorder      =        1;
+    p->fIndConstr    =        0;
+    p->fUsePivots    =        0;
+    p->fCluster      =        0;
+    p->fSchedule     =        0;
+    p->fVerbose      =        0;
+    p->fVeryVerbose  =        0;
+    p->fSilent       =        0;
+    p->TimeLimit     =        0;
+//    p->TimeLimit     =        0;
+    p->TimeLimitGlo  =        0;
+    p->TimeTarget    =        0;
+    p->iFrame        =       -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds balanced cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ManMinCutTest( Aig_Man_t * pAig, int Num )
+{
+    extern void Llb_BddConstructTest( Aig_Man_t * p, Vec_Ptr_t * vResult );
+    extern void Llb_BddExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, Vec_Ptr_t * vMaps );
+ 
+
+//    int fVerbose = 1;
+    Gia_ParLlb_t Pars, * pPars = &Pars;
+    Vec_Ptr_t * vResult;//, * vSupps, * vMaps;
+    Aig_Man_t * p;
+
+    Llb_BddSetDefaultParams( pPars );
+
+    p = Aig_ManDupFlopsOnly( pAig );
+//Aig_ManShow( p, 0, NULL );
+    Aig_ManPrintStats( pAig );
+    Aig_ManPrintStats( p );
+    Aig_ManFanoutStart( p );
+
+    vResult = Llb_ManComputeCuts( p, Num, 1, 0 );
+//    vSupps  = Llb_ManCutSupps( p, vResult );
+//    vMaps   = Llb_ManCutMap( p, vResult, vSupps );
+
+//    Llb_BddExperiment( pAig, p, pPars, vResult, vMaps );
+    Llb_CoreExperiment( pAig, p, pPars, vResult, 0 );
+
+//    Vec_VecFree( (Vec_Vec_t *)vMaps );
+//    Vec_VecFree( (Vec_Vec_t *)vSupps );
+    Vec_VecFree( (Vec_Vec_t *)vResult );
+
+    Aig_ManFanoutStop( p );
+    Aig_ManCleanMarkAB( p );
+    Aig_ManStop( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb2Image.c b/abc-build/src/proof/llb/llb2Image.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb2Image.c
@@ -0,0 +1,482 @@
+/**CFile****************************************************************
+
+  FileName    [llb2Image.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Computes image using partitioned structure.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb2Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper );
+extern Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes supports of the partitions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose )
+{
+    Vec_Ptr_t * vSupps;
+    Vec_Int_t * vOne;
+    Aig_Obj_t * pObj;
+    DdManager * dd;
+    DdNode * bSupp, * bTemp;
+    int i, Entry, nSize;
+    nSize  = Cudd_ReadSize( (DdManager *)Vec_PtrEntry( vDdMans, 0 ) );
+    vSupps = Vec_PtrAlloc( 100 );
+    // create initial
+    vOne = Vec_IntStart( nSize );
+    Vec_IntForEachEntry( vStart, Entry, i )
+        Vec_IntWriteEntry( vOne, Entry, 1 );
+    Vec_PtrPush( vSupps, vOne );
+    // create intermediate 
+    Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i )
+    {
+        vOne  = Vec_IntStart( nSize );
+        bSupp = Cudd_Support( dd, dd->bFunc );  Cudd_Ref( bSupp );
+        for ( bTemp = bSupp; bTemp != Cudd_ReadOne(dd); bTemp = cuddT(bTemp) )
+            Vec_IntWriteEntry( vOne, bTemp->index, 1 );
+        Cudd_RecursiveDeref( dd, bSupp );
+        Vec_PtrPush( vSupps, vOne );
+    }
+    // create final
+    vOne = Vec_IntStart( nSize );
+    Vec_IntForEachEntry( vStop, Entry, i )
+        Vec_IntWriteEntry( vOne, Entry, 1 );
+    if ( fAddPis )
+        Saig_ManForEachPi( p, pObj, i )
+            Vec_IntWriteEntry( vOne, Aig_ObjId(pObj), 1 );
+    Vec_PtrPush( vSupps, vOne );
+
+    // print supports
+    assert( nSize == Aig_ManObjNumMax(p) );
+    if ( !fVerbose )
+        return vSupps;
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        int k, Counter = 0;
+        Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k )
+            Counter += Vec_IntEntry(vOne, i);
+        if ( Counter == 0 ) 
+            continue;
+        printf( "Obj = %4d : ", i );
+        if ( Saig_ObjIsPi(p,pObj) )
+            printf( "pi  " );
+        else if ( Saig_ObjIsLo(p,pObj) )
+            printf( "lo  " );
+        else if ( Saig_ObjIsLi(p,pObj) )
+            printf( "li  " );
+        else if ( Aig_ObjIsNode(pObj) )
+            printf( "and " );
+        Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k )
+            printf( "%d", Vec_IntEntry(vOne, i) );
+        printf( "\n" );
+    }
+    return vSupps;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes quantification schedule.]
+
+  Description [Input array contains supports: 0=starting, ... intermediate...
+  N-1=final. Output arrays contain immediately quantifiable vars (vQuant0)
+  and vars that should be quantified after conjunction (vQuant1).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose )
+{
+    Vec_Int_t * vOne;
+    int nVarsAll, Counter, iSupp = -1, Entry, i, k;
+    // start quantification arrays
+    *pvQuant0 = Vec_PtrAlloc( Vec_PtrSize(vSupps) );
+    *pvQuant1 = Vec_PtrAlloc( Vec_PtrSize(vSupps) );
+    Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k )
+    {
+        Vec_PtrPush( *pvQuant0, Vec_IntAlloc(16) );
+        Vec_PtrPush( *pvQuant1, Vec_IntAlloc(16) );
+    }
+    // count how many times each var appears
+    nVarsAll = Vec_IntSize( (Vec_Int_t *)Vec_PtrEntry(vSupps, 0) );
+    for ( i = 0; i < nVarsAll; i++ )
+    {
+        Counter = 0;
+        Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k )
+            if ( Vec_IntEntry(vOne, i) )
+            {
+                iSupp = k;
+                Counter++;
+            }
+        if ( Counter == 0 )
+            continue;
+        if ( Counter == 1 )
+            Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, iSupp), i );
+        else // if ( Counter > 1 )
+            Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, iSupp), i );
+    }
+
+    if ( fVerbose )
+    for ( i = 0; i < Vec_PtrSize(vSupps); i++ )
+    {
+        printf( "%2d : Quant0 = ", i );
+        Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, i), Entry, k )
+            printf( "%d ", Entry );
+        printf( "\n" );
+    }
+
+    if ( fVerbose )
+    for ( i = 0; i < Vec_PtrSize(vSupps); i++ )
+    {
+        printf( "%2d : Quant1 = ", i );
+        Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, i), Entry, k )
+            printf( "%d ", Entry );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes one partition in a separate BDD manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdManager * Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, abctime TimeTarget )
+{
+    Vec_Ptr_t * vNodes, * vRange;
+    Aig_Obj_t * pObj;
+    DdManager * dd;
+    DdNode * bBdd0, * bBdd1, * bProd, * bRes, * bTemp;
+    int i;
+
+    dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    Cudd_AutodynEnable( dd,  CUDD_REORDER_SYMM_SIFT );
+    dd->TimeStop = TimeTarget;
+
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+        pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) );
+
+    vNodes = Llb_ManCutNodes( p, vLower, vUpper );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+        bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+//        pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 );   Cudd_Ref( (DdNode *)pObj->pData );
+//        pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeTarget );  
+        pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 );  
+        if ( pObj->pData == NULL )
+        {
+            Cudd_Quit( dd );
+            Vec_PtrFree( vNodes );
+            return NULL;
+        }
+        Cudd_Ref( (DdNode *)pObj->pData );
+    }
+
+    vRange = Llb_ManCutRange( p, vLower, vUpper );
+    bRes   = Cudd_ReadOne(dd);   Cudd_Ref( bRes );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vRange, pObj, i )
+    {
+        assert( Aig_ObjIsNode(pObj) );
+        bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData );   Cudd_Ref( bProd );
+//        bRes  = Cudd_bddAnd( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes );
+//        bRes  = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget );  
+        bRes  = Cudd_bddAnd( dd, bTemp = bRes, bProd );  
+        if ( bRes == NULL )
+        {
+            Cudd_Quit( dd );
+            Vec_PtrFree( vRange );
+            Vec_PtrFree( vNodes );
+            return NULL;
+        }        
+        Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bProd );
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+
+    Vec_PtrFree( vRange );
+    Vec_PtrFree( vNodes );
+    Cudd_AutodynDisable( dd );
+//    Cudd_RecursiveDeref( dd, bRes );
+//    Extra_StopManager( dd );
+    dd->bFunc = bRes;
+    dd->TimeStop = 0;
+    return dd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives positive cube composed of nodes IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_ImgComputeCube( Aig_Man_t * pAig, Vec_Int_t * vNodeIds, DdManager * dd )
+{
+    DdNode * bProd, * bTemp;
+    Aig_Obj_t * pObj;
+    int i;
+    abctime TimeStop;
+    TimeStop = dd->TimeStop; dd->TimeStop = 0;
+    bProd = Cudd_ReadOne(dd);   Cudd_Ref( bProd );
+    Aig_ManForEachObjVec( vNodeIds, pAig, pObj, i )
+    {
+        bProd  = Cudd_bddAnd( dd, bTemp = bProd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)) ); Cudd_Ref( bProd );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    Cudd_Deref( bProd );
+    dd->TimeStop = TimeStop;
+    return bProd;
+} 
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose )
+{
+    DdManager * dd;
+    DdNode * bProd, * bRes, * bTemp;
+    int i;
+    abctime clk = Abc_Clock();
+    Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i )
+    {
+        // remember unquantified ones
+        assert( dd->bFunc2 == NULL );
+        dd->bFunc2 = dd->bFunc;   Cudd_Ref( dd->bFunc2 );
+
+        Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+
+        bRes = dd->bFunc;
+        if ( fVerbose )
+            Abc_Print( 1, "Part %2d : Init =%5d. ", i, Cudd_DagSize(bRes) );
+        bProd = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, i+1), dd );   Cudd_Ref( bProd );
+        bRes  = Cudd_bddExistAbstract( dd, bTemp = bRes, bProd );                          Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bProd );
+        dd->bFunc = bRes;
+
+        Cudd_AutodynDisable( dd );
+
+        if ( fVerbose )
+            Abc_Print( 1, "Quant =%5d. ", Cudd_DagSize(bRes) );
+        Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+        if ( fVerbose ) 
+            Abc_Print( 1, "Reo = %5d. ", Cudd_DagSize(bRes) );
+        Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+        if ( fVerbose ) 
+            Abc_Print( 1, "Reo = %5d.  ", Cudd_DagSize(bRes) );
+        if ( fVerbose ) 
+            Abc_Print( 1, "Supp = %3d.  ", Cudd_SupportSize(dd, bRes) );
+        if ( fVerbose ) 
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans )
+{
+    DdManager * dd;
+    int i;
+    Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i )
+    {
+        assert( dd->bFunc2 != NULL );
+        Cudd_RecursiveDeref( dd, dd->bFunc );
+        dd->bFunc = dd->bFunc2;
+        dd->bFunc2 = NULL;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes image of the initial set of states.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit, 
+    Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs, 
+    abctime TimeTarget, int fBackward, int fReorder, int fVerbose )
+{
+//    int fCheckSupport = 0;
+    DdManager * ddPart;
+    DdNode * bImage, * bGroup, * bCube, * bTemp;
+    int i;
+    abctime clk, clk0 = Abc_Clock();
+
+    bImage = bInit;  Cudd_Ref( bImage );
+    if ( fBackward )
+    {
+        // change polarity
+        bCube  = Llb_DriverPhaseCube( pAig, vDriRefs, dd );                Cudd_Ref( bCube );
+        bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube );     Cudd_Ref( bImage );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bCube );
+    }
+    else
+    {
+        // quantify unique vriables
+        bCube  = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube );
+        bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube );                    
+        if ( bImage == NULL )
+        {
+            Cudd_RecursiveDeref( dd, bTemp );
+            Cudd_RecursiveDeref( dd, bCube );
+            return NULL;
+        }
+        Cudd_Ref( bImage );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bCube );
+    }
+    // perform image computation
+    Vec_PtrForEachEntry( DdManager *, vDdMans, ddPart, i )
+    {
+        clk = Abc_Clock();
+if ( fVerbose )
+printf( "   %2d : ", i );
+        // transfer the BDD from the group manager to the main manager
+        bGroup = Cudd_bddTransfer( ddPart, dd, ddPart->bFunc );                           
+        if ( bGroup == NULL )
+            return NULL;
+        Cudd_Ref( bGroup );
+if ( fVerbose )
+printf( "Pt0 =%6d. Pt1 =%6d. ", Cudd_DagSize(ddPart->bFunc), Cudd_DagSize(bGroup) );
+        // perform partial product
+        bCube  = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant1, i+1), dd ); Cudd_Ref( bCube );
+//        bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube );                
+//        bImage = Extra_bddAndAbstractTime( dd, bTemp = bImage, bGroup, bCube, TimeTarget );  
+        bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube );  
+        if ( bImage == NULL )
+        {
+            Cudd_RecursiveDeref( dd, bTemp );
+            Cudd_RecursiveDeref( dd, bCube );
+            Cudd_RecursiveDeref( dd, bGroup );
+            return NULL;
+        }
+        Cudd_Ref( bImage );
+
+if ( fVerbose )
+printf( "Im0 =%6d. Im1 =%6d. ", Cudd_DagSize(bTemp), Cudd_DagSize(bImage) );
+//printf("\n"); Extra_bddPrintSupport(dd, bImage); printf("\n");
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bCube );
+        Cudd_RecursiveDeref( dd, bGroup );
+
+//        Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+//        Abc_Print( 1, "Reo =%6d.  ", Cudd_DagSize(bImage) );
+
+if ( fVerbose )
+printf( "Supp =%3d. ", Cudd_SupportSize(dd, bImage) );
+if ( fVerbose )
+Abc_PrintTime( 1, "T", Abc_Clock() - clk );
+    }
+
+    if ( !fBackward )
+    {
+        // change polarity
+        bCube  = Llb_DriverPhaseCube( pAig, vDriRefs, dd );                Cudd_Ref( bCube );
+        bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube );     Cudd_Ref( bImage );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bCube );
+    }
+    else
+    {
+        // quantify unique vriables
+        bCube  = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube );
+        bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube );                    Cudd_Ref( bImage );
+        Cudd_RecursiveDeref( dd, bTemp );
+        Cudd_RecursiveDeref( dd, bCube );
+    }
+
+    if ( fReorder )
+    {
+    if ( fVerbose )
+    Abc_Print( 1, "        Reordering... Before =%5d. ", Cudd_DagSize(bImage) );
+    Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+    if ( fVerbose )
+    Abc_Print( 1, "After =%5d. ", Cudd_DagSize(bImage) );
+//    Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+//    Abc_Print( 1, "After =%5d.  ", Cudd_DagSize(bImage) );
+    if ( fVerbose )
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk0 );
+//    Abc_Print( 1, "\n" );
+    }
+
+    Cudd_Deref( bImage );
+    return bImage;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb3Image.c b/abc-build/src/proof/llb/llb3Image.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb3Image.c
@@ -0,0 +1,1095 @@
+/**CFile****************************************************************
+
+  FileName    [llb3Image.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Computes image using partitioned structure.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Var_t_ Llb_Var_t;
+struct Llb_Var_t_ 
+{
+    int           iVar;      // variable number
+    int           nScore;    // variable score
+    Vec_Int_t *   vParts;    // partitions
+};
+
+typedef struct Llb_Prt_t_ Llb_Prt_t;
+struct Llb_Prt_t_ 
+{
+    int           iPart;     // partition number
+    int           nSize;     // the number of BDD nodes
+    DdNode *      bFunc;     // the partition
+    Vec_Int_t *   vVars;     // support
+};
+
+typedef struct Llb_Mgr_t_ Llb_Mgr_t;
+struct Llb_Mgr_t_
+{
+    Aig_Man_t *   pAig;      // AIG manager
+    Vec_Ptr_t *   vLeaves;   // leaves in the AIG manager
+    Vec_Ptr_t *   vRoots;    // roots in the AIG manager
+    DdManager *   dd;        // working BDD manager
+    int *         pVars2Q;   // variables to quantify
+    // internal
+    Llb_Prt_t **  pParts;    // partitions
+    Llb_Var_t **  pVars;     // variables
+    int           iPartFree; // next free partition
+    int           nVars;     // the number of BDD variables
+    int           nSuppMax;  // maximum support size
+    // temporary
+    int *         pSupp;     // temporary support storage
+};
+
+static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i )   { return p->pVars[i];  }
+static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i )  { return p->pParts[i]; }
+
+// iterator over vars
+#define Llb_MgrForEachVar( p, pVar, i )     \
+    for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else
+// iterator over parts
+#define Llb_MgrForEachPart( p, pPart, i )   \
+    for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else
+
+// iterator over vars of one partition
+#define Llb_PartForEachVar( p, pPart, pVar, i )   \
+    for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ )
+// iterator over parts of one variable
+#define Llb_VarForEachPart( p, pVar, pPart, i )   \
+    for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ )
+
+// statistics
+abctime timeBuild, timeAndEx, timeOther;
+int nSuppMax;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Removes one variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_NonlinRemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar )
+{
+    assert( p->pVars[pVar->iVar] == pVar );
+    p->pVars[pVar->iVar] = NULL;
+    Vec_IntFree( pVar->vParts );
+    ABC_FREE( pVar );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes one partition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_NonlinRemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+    assert( p->pParts[pPart->iPart] == pPart );
+    p->pParts[pPart->iPart] = NULL;
+    Vec_IntFree( pPart->vVars );
+    Cudd_RecursiveDeref( p->dd, pPart->bFunc );
+    ABC_FREE( pPart );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create cube with singleton variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_NonlinCreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+    DdNode * bCube, * bTemp;
+    Llb_Var_t * pVar;
+    int i;
+    abctime TimeStop;
+    TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+    bCube = Cudd_ReadOne(p->dd);   Cudd_Ref( bCube );
+    Llb_PartForEachVar( p, pPart, pVar, i )
+    {
+        assert( Vec_IntSize(pVar->vParts) > 0 );
+        if ( Vec_IntSize(pVar->vParts) != 1 )
+            continue;
+        assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart );
+        bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) );    Cudd_Ref( bCube );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+    }
+    Cudd_Deref( bCube );
+    p->dd->TimeStop = TimeStop;
+    return bCube;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create cube of variables appearing only in two partitions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_NonlinCreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 )
+{
+    DdNode * bCube, * bTemp;
+    Llb_Var_t * pVar;
+    int i;
+    abctime TimeStop;
+    TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+    bCube = Cudd_ReadOne(p->dd);   Cudd_Ref( bCube );
+    Llb_PartForEachVar( p, pPart1, pVar, i )
+    {
+        assert( Vec_IntSize(pVar->vParts) > 0 );
+        if ( Vec_IntSize(pVar->vParts) != 2 )
+            continue;
+        if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) ||
+             (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) )
+        {
+            bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) );   Cudd_Ref( bCube );
+            Cudd_RecursiveDeref( p->dd, bTemp );
+        }
+    }
+    Cudd_Deref( bCube );
+    p->dd->TimeStop = TimeStop;
+    return bCube;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if partition has singleton variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_NonlinHasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+    Llb_Var_t * pVar;
+    int i;
+    Llb_PartForEachVar( p, pPart, pVar, i )
+        if ( Vec_IntSize(pVar->vParts) == 1 )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if partition has singleton variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_NonlinPrint( Llb_Mgr_t * p )
+{
+    Llb_Prt_t * pPart;
+    Llb_Var_t * pVar;
+    int i, k;
+    printf( "\n" );
+    Llb_MgrForEachVar( p, pVar, i )
+    {
+        printf( "Var %3d : ", i );
+        Llb_VarForEachPart( p, pVar, pPart, k )
+            printf( "%d ", pPart->iPart );
+        printf( "\n" );
+    }
+    Llb_MgrForEachPart( p, pPart, i )
+    {
+        printf( "Part %3d : ", i );
+        Llb_PartForEachVar( p, pPart, pVar, k )
+            printf( "%d ", pVar->iVar );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Quantifies singles belonging to one partition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_NonlinQuantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart, int fSubset )
+{
+    Llb_Var_t * pVar;
+    Llb_Prt_t * pTemp;
+    Vec_Ptr_t * vSingles;
+    DdNode * bCube, * bTemp;
+    int i, RetValue, nSizeNew;
+    if ( fSubset )
+    {        
+        int Length;
+//        int nSuppSize = Cudd_SupportSize( p->dd, pPart->bFunc );
+//        pPart->bFunc = Cudd_SubsetHeavyBranch( p->dd, bTemp = pPart->bFunc, nSuppSize, 3*pPart->nSize/4 );  Cudd_Ref( pPart->bFunc );
+        pPart->bFunc = Cudd_LargestCube( p->dd, bTemp = pPart->bFunc, &Length );  Cudd_Ref( pPart->bFunc );
+
+        printf( "Subsetting %3d : ", pPart->iPart );
+        printf( "(Supp =%3d  Node =%5d) -> ", Cudd_SupportSize(p->dd, bTemp),        Cudd_DagSize(bTemp) );
+        printf( "(Supp =%3d  Node =%5d)\n",   Cudd_SupportSize(p->dd, pPart->bFunc), Cudd_DagSize(pPart->bFunc) );
+
+        RetValue = (Cudd_DagSize(bTemp) == Cudd_DagSize(pPart->bFunc));
+
+        Cudd_RecursiveDeref( p->dd, bTemp );
+
+        if ( RetValue )
+            return 1;
+    }
+    else
+    {
+        // create cube to be quantified
+        bCube = Llb_NonlinCreateCube1( p, pPart );   Cudd_Ref( bCube );
+//        assert( !Cudd_IsConstant(bCube) );
+        // derive new function
+        pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube );  Cudd_Ref( pPart->bFunc );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+        Cudd_RecursiveDeref( p->dd, bCube );
+    }
+    // get support
+    vSingles = Vec_PtrAlloc( 0 );
+    nSizeNew = Cudd_DagSize(pPart->bFunc);
+    Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp );
+    Llb_PartForEachVar( p, pPart, pVar, i )
+        if ( p->pSupp[pVar->iVar] )
+        {
+            assert( Vec_IntSize(pVar->vParts) > 1 );
+            pVar->nScore -= pPart->nSize - nSizeNew;
+        }
+        else
+        {
+            RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart );
+            assert( RetValue );
+            pVar->nScore -= pPart->nSize;
+            if ( Vec_IntSize(pVar->vParts) == 0 )
+                Llb_NonlinRemoveVar( p, pVar );
+            else if ( Vec_IntSize(pVar->vParts) == 1 )
+                Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+        }
+
+    // update partition
+    pPart->nSize = nSizeNew;
+    Vec_IntClear( pPart->vVars );
+    for ( i = 0; i < p->nVars; i++ )
+        if ( p->pSupp[i] && p->pVars2Q[i] )
+            Vec_IntPush( pPart->vVars, i );
+    // remove other variables
+    Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i )
+        Llb_NonlinQuantify1( p, pTemp, 0 );
+    Vec_PtrFree( vSingles );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Quantifies singles belonging to one partition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_NonlinQuantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 )
+{
+    int fVerbose = 0;
+    Llb_Var_t * pVar;
+    Llb_Prt_t * pTemp;
+    Vec_Ptr_t * vSingles;
+    DdNode * bCube, * bFunc;
+    int i, RetValue, nSuppSize;
+//    int iPart1 = pPart1->iPart;
+//    int iPart2 = pPart2->iPart;
+
+    // create cube to be quantified
+    bCube = Llb_NonlinCreateCube2( p, pPart1, pPart2 );   Cudd_Ref( bCube );
+if ( fVerbose )
+{
+printf( "\n" );
+printf( "\n" );
+Llb_NonlinPrint( p );
+printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart );
+Extra_bddPrintSupport( p->dd, bCube );  printf( "\n" );
+}
+ 
+    // derive new function
+//    bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube );  Cudd_Ref( bFunc );
+/*
+    bFunc = Cudd_bddAndAbstractLimit( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, Limit );  
+    if ( bFunc == NULL )
+    {
+        int RetValue;
+        Cudd_RecursiveDeref( p->dd, bCube );
+        if ( pPart1->nSize < pPart2->nSize )
+            RetValue = Llb_NonlinQuantify1( p, pPart1, 1 );
+        else
+            RetValue = Llb_NonlinQuantify1( p, pPart2, 1 );
+        if ( RetValue )
+            Limit = Limit + 1000;
+        Llb_NonlinQuantify2( p, pPart1, pPart2 );
+        return 0;
+    }
+    Cudd_Ref( bFunc );
+*/
+
+//    bFunc = Extra_bddAndAbstractTime( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, TimeOut );  
+    bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube );  
+    if ( bFunc == NULL )
+    {
+        Cudd_RecursiveDeref( p->dd, bCube );
+        return 0;
+    }
+    Cudd_Ref( bFunc );
+    Cudd_RecursiveDeref( p->dd, bCube );
+
+    // create new partition
+    pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 );
+    pTemp->iPart = p->iPartFree++;
+    pTemp->nSize = Cudd_DagSize(bFunc);
+    pTemp->bFunc = bFunc;
+    pTemp->vVars = Vec_IntAlloc( 8 );
+    // update variables
+    Llb_PartForEachVar( p, pPart1, pVar, i )
+    {
+        RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart );
+        assert( RetValue );
+        pVar->nScore -= pPart1->nSize;
+    }
+    // update variables
+    Llb_PartForEachVar( p, pPart2, pVar, i )
+    {
+        RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart );
+        assert( RetValue );
+        pVar->nScore -= pPart2->nSize;
+    }
+    // add variables to the new partition
+    nSuppSize = 0;
+    Extra_SupportArray( p->dd, bFunc, p->pSupp );
+    for ( i = 0; i < p->nVars; i++ )
+    {
+        nSuppSize += p->pSupp[i];
+        if ( p->pSupp[i] && p->pVars2Q[i] )
+        {
+            pVar = Llb_MgrVar( p, i );
+            pVar->nScore += pTemp->nSize;
+            Vec_IntPush( pVar->vParts, pTemp->iPart );
+            Vec_IntPush( pTemp->vVars, i );
+        }
+    }
+    p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); 
+    // remove variables and collect partitions with singleton variables
+    vSingles = Vec_PtrAlloc( 0 );
+    Llb_PartForEachVar( p, pPart1, pVar, i )
+    {
+        if ( Vec_IntSize(pVar->vParts) == 0 )
+            Llb_NonlinRemoveVar( p, pVar );
+        else if ( Vec_IntSize(pVar->vParts) == 1 )
+        {
+            if ( fVerbose )
+                printf( "Adding partition %d because of var %d.\n", 
+                    Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar );
+            Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+        }
+    }
+    Llb_PartForEachVar( p, pPart2, pVar, i )
+    {
+        if ( pVar == NULL )
+            continue;
+        if ( Vec_IntSize(pVar->vParts) == 0 )
+            Llb_NonlinRemoveVar( p, pVar );
+        else if ( Vec_IntSize(pVar->vParts) == 1 )
+        {
+            if ( fVerbose )
+                printf( "Adding partition %d because of var %d.\n", 
+                    Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar );
+            Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+        }
+    }
+    // remove partitions
+    Llb_NonlinRemovePart( p, pPart1 );
+    Llb_NonlinRemovePart( p, pPart2 );
+    // remove other variables
+if ( fVerbose )
+Llb_NonlinPrint( p );
+    Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i )
+    {
+if ( fVerbose )
+printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart );
+        Llb_NonlinQuantify1( p, pTemp, 0 );
+    }
+if ( fVerbose )
+Llb_NonlinPrint( p );
+    Vec_PtrFree( vSingles );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes volume of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_NonlinCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Saig_ObjIsLi(p, pObj) )
+    {
+        Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes);
+        return;
+    }
+    if ( Aig_ObjIsConst1(pObj) )
+        return;
+    assert( Aig_ObjIsNode(pObj) );
+    Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes);
+    Llb_NonlinCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes);
+    Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes volume of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_NonlinCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i;
+    // mark the lower cut with the traversal ID
+    Aig_ManIncrementTravId(p);
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+        Aig_ObjSetTravIdCurrent( p, pObj );
+    // count the upper cut
+    vNodes = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+        Llb_NonlinCutNodes_rec( p, pObj, vNodes );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns array of BDDs for the roots in terms of the leaves.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_NonlinBuildBdds( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, DdManager * dd )
+{
+    Vec_Ptr_t * vNodes, * vResult;
+    Aig_Obj_t * pObj;
+    DdNode * bBdd0, * bBdd1, * bProd;
+    int i, k;
+
+    Aig_ManConst1(p)->pData = Cudd_ReadOne( dd );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+        pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) );
+
+    vNodes = Llb_NonlinCutNodes( p, vLower, vUpper );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+        bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+//        pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut );
+        pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 );
+        if ( pObj->pData == NULL )
+        {
+            Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i )
+                if ( pObj->pData )
+                    Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+            Vec_PtrFree( vNodes );
+            return NULL;
+        }
+        Cudd_Ref( (DdNode *)pObj->pData );
+    }
+
+    vResult = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+    {
+        if ( Aig_ObjIsNode(pObj) )
+        {
+            bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData );  Cudd_Ref( bProd );
+        }
+        else
+        {
+            assert( Saig_ObjIsLi(p, pObj) );
+            bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+            bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), bBdd0 );                  Cudd_Ref( bProd );
+        }
+        Vec_PtrPush( vResult, bProd );
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+
+    Vec_PtrFree( vNodes );
+    return vResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts non-linear quantification scheduling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_NonlinAddPair( Llb_Mgr_t * p, DdNode * bFunc, int iPart, int iVar )
+{
+    if ( p->pVars[iVar] == NULL )
+    {
+        p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 );
+        p->pVars[iVar]->iVar   = iVar;
+        p->pVars[iVar]->nScore = 0;
+        p->pVars[iVar]->vParts = Vec_IntAlloc( 8 );
+    }
+    Vec_IntPush( p->pVars[iVar]->vParts, iPart );
+    Vec_IntPush( p->pParts[iPart]->vVars, iVar );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts non-linear quantification scheduling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_NonlinAddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc )
+{
+    int k, nSuppSize;
+    assert( !Cudd_IsConstant(bFunc) );
+    // create partition
+    p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 );
+    p->pParts[i]->iPart = i;
+    p->pParts[i]->bFunc = bFunc;
+    p->pParts[i]->vVars = Vec_IntAlloc( 8 );
+    // add support dependencies
+    nSuppSize = 0;
+    Extra_SupportArray( p->dd, bFunc, p->pSupp );
+    for ( k = 0; k < p->nVars; k++ )
+    {
+        nSuppSize += p->pSupp[k];
+        if ( p->pSupp[k] && p->pVars2Q[k] )
+            Llb_NonlinAddPair( p, bFunc, i, k );
+    }
+    p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts non-linear quantification scheduling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_NonlinStart( Llb_Mgr_t * p )
+{
+    Vec_Ptr_t * vRootBdds;
+    DdNode * bFunc;
+    int i;
+    // create and collect BDDs
+    vRootBdds = Llb_NonlinBuildBdds( p->pAig, p->vLeaves, p->vRoots, p->dd ); // come referenced
+    if ( vRootBdds == NULL )
+        return 0;
+    // add pairs (refs are consumed inside)
+    Vec_PtrForEachEntry( DdNode *, vRootBdds, bFunc, i )
+        Llb_NonlinAddPartition( p, i, bFunc );
+    Vec_PtrFree( vRootBdds );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks that each var appears in at least one partition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+**********************************************************************/
+void Llb_NonlinCheckVars( Llb_Mgr_t * p )
+{
+    Llb_Var_t * pVar;
+    int i;
+    Llb_MgrForEachVar( p, pVar, i )
+        assert( Vec_IntSize(pVar->vParts) > 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find next partition to quantify]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_NonlinNextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 )
+{
+    Llb_Var_t * pVar, * pVarBest = NULL;
+    Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL;
+    int i;
+    Llb_NonlinCheckVars( p );
+    // find variable with minimum score
+    Llb_MgrForEachVar( p, pVar, i )
+        if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore )
+            pVarBest = pVar;
+    if ( pVarBest == NULL )
+        return 0;
+    // find two partitions with minimum size
+    Llb_VarForEachPart( p, pVarBest, pPart, i )
+    {
+        if ( pPart1Best == NULL )
+            pPart1Best = pPart;
+        else if ( pPart2Best == NULL )
+            pPart2Best = pPart;
+        else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize )
+        {
+            if ( pPart1Best->nSize > pPart2Best->nSize )
+                pPart1Best = pPart;
+            else
+                pPart2Best = pPart;
+        }
+    }
+    *ppPart1 = pPart1Best;
+    *ppPart2 = pPart2Best;
+    return 1; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reorders BDDs in the working manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_NonlinReorder( DdManager * dd, int fTwice, int fVerbose )
+{
+    abctime clk = Abc_Clock();
+    if ( fVerbose )
+        Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+    Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+    if ( fVerbose )
+        Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+    if ( fTwice )
+    {
+        Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+        if ( fVerbose )
+            Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+    }
+    if ( fVerbose )
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recomputes scores after variable reordering.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_NonlinRecomputeScores( Llb_Mgr_t * p )
+{
+    Llb_Prt_t * pPart;
+    Llb_Var_t * pVar;
+    int i, k;
+    Llb_MgrForEachPart( p, pPart, i )
+        pPart->nSize = Cudd_DagSize(pPart->bFunc);
+    Llb_MgrForEachVar( p, pVar, i )
+    {
+        pVar->nScore = 0;
+        Llb_VarForEachPart( p, pVar, pPart, k )
+            pVar->nScore += pPart->nSize;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recomputes scores after variable reordering.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_NonlinVerifyScores( Llb_Mgr_t * p )
+{
+    Llb_Prt_t * pPart;
+    Llb_Var_t * pVar;
+    int i, k, nScore;
+    Llb_MgrForEachPart( p, pPart, i )
+        assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) );
+    Llb_MgrForEachVar( p, pVar, i )
+    {
+        nScore = 0;
+        Llb_VarForEachPart( p, pVar, pPart, k )
+            nScore += pPart->nSize;
+        assert( nScore == pVar->nScore );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts non-linear quantification scheduling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Llb_Mgr_t * Llb_NonlinAlloc( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, DdManager * dd )
+{
+    Llb_Mgr_t * p;
+    p = ABC_CALLOC( Llb_Mgr_t, 1 );
+    p->pAig      = pAig;
+    p->vLeaves   = vLeaves;
+    p->vRoots    = vRoots;
+    p->dd        = dd;
+    p->pVars2Q   = pVars2Q;
+    p->nVars     = Cudd_ReadSize(dd);
+    p->iPartFree = Vec_PtrSize(vRoots);
+    p->pVars     = ABC_CALLOC( Llb_Var_t *, p->nVars );
+    p->pParts    = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 );
+    p->pSupp     = ABC_ALLOC( int, Cudd_ReadSize(dd) );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops non-linear quantification scheduling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_NonlinFree( Llb_Mgr_t * p )
+{
+    Llb_Prt_t * pPart;
+    Llb_Var_t * pVar;
+    int i;
+    Llb_MgrForEachVar( p, pVar, i )
+        Llb_NonlinRemoveVar( p, pVar );
+    Llb_MgrForEachPart( p, pPart, i )
+        Llb_NonlinRemovePart( p, pPart );
+    ABC_FREE( p->pVars );
+    ABC_FREE( p->pParts );
+    ABC_FREE( p->pSupp );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs image computation.]
+
+  Description [Computes image of BDDs (vFuncs).]
+               
+  SideEffects [BDDs in vFuncs are derefed inside. The result is refed.]
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, 
+    DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder )
+{
+    Llb_Prt_t * pPart, * pPart1, * pPart2;
+    Llb_Mgr_t * p;
+    DdNode * bFunc, * bTemp;
+    int i, nReorders, timeInside;
+    abctime clk = Abc_Clock(), clk2;
+    // start the manager
+    clk2 = Abc_Clock();
+    p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd );
+    if ( !Llb_NonlinStart( p ) )
+    {
+        Llb_NonlinFree( p );
+        return NULL;
+    }
+    // add partition
+    Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent );
+    // remove singles
+    Llb_MgrForEachPart( p, pPart, i )
+        if ( Llb_NonlinHasSingletonVars(p, pPart) )
+            Llb_NonlinQuantify1( p, pPart, 0 );
+    timeBuild += Abc_Clock() - clk2;
+    timeInside = Abc_Clock() - clk2;
+    // compute scores
+    Llb_NonlinRecomputeScores( p );
+    // save permutation
+    if ( pOrder )
+    memcpy( pOrder, dd->invperm, sizeof(int) * dd->size );
+    // iteratively quantify variables
+    while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) )
+    {
+        clk2 = Abc_Clock();
+        nReorders = Cudd_ReadReorderings(dd);
+        if ( !Llb_NonlinQuantify2( p, pPart1, pPart2 ) )
+        {
+            Llb_NonlinFree( p );
+            return NULL;
+        }
+        timeAndEx  += Abc_Clock() - clk2;
+        timeInside += Abc_Clock() - clk2;
+        if ( nReorders < Cudd_ReadReorderings(dd) )
+            Llb_NonlinRecomputeScores( p );
+//        else
+//            Llb_NonlinVerifyScores( p );
+    }
+    // load partitions
+    bFunc = Cudd_ReadOne(p->dd);   Cudd_Ref( bFunc );
+    Llb_MgrForEachPart( p, pPart, i )
+    {
+        bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc );   Cudd_Ref( bFunc );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+    }
+    nSuppMax = p->nSuppMax;
+    Llb_NonlinFree( p );
+    // reorder variables
+    if ( fReorder )
+        Llb_NonlinReorder( dd, 0, fVerbose );
+    timeOther += Abc_Clock() - clk - timeInside;
+    // return
+    Cudd_Deref( bFunc );
+    return bFunc;
+}
+
+
+
+static Llb_Mgr_t * p = NULL;
+
+/**Function*************************************************************
+
+  Synopsis    [Starts image computation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdManager * Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, abctime TimeTarget )
+{
+    DdManager * dd;
+    abctime clk = Abc_Clock();
+    assert( p == NULL );
+    // start a new manager (disable reordering)
+    dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    dd->TimeStop = TimeTarget;
+    Cudd_ShuffleHeap( dd, pOrder );
+//    if ( fFirst )
+        Cudd_AutodynEnable( dd,  CUDD_REORDER_SYMM_SIFT );
+    // start the manager
+    p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd );
+    if ( !Llb_NonlinStart( p ) )
+    {
+        Llb_NonlinFree( p );
+        p = NULL;
+        return NULL;
+    }
+    timeBuild += Abc_Clock() - clk;
+//    if ( !fFirst )
+//        Cudd_AutodynEnable( dd,  CUDD_REORDER_SYMM_SIFT );
+    return dd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs image computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder )
+{
+    Llb_Prt_t * pPart, * pPart1, * pPart2;
+    DdNode * bFunc, * bTemp;
+    int i, nReorders, timeInside = 0;
+    abctime clk = Abc_Clock(), clk2;
+
+    // add partition
+    Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent );
+    // remove singles
+    Llb_MgrForEachPart( p, pPart, i )
+        if ( Llb_NonlinHasSingletonVars(p, pPart) )
+            Llb_NonlinQuantify1( p, pPart, 0 );
+    // reorder
+    if ( fReorder )
+        Llb_NonlinReorder( p->dd, 0, 0 );
+    // save permutation
+    memcpy( pOrder, p->dd->invperm, sizeof(int) * p->dd->size );
+
+    // compute scores
+    Llb_NonlinRecomputeScores( p );
+    // iteratively quantify variables
+    while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) )
+    {
+        clk2 = Abc_Clock();
+        nReorders = Cudd_ReadReorderings(p->dd);
+        if ( !Llb_NonlinQuantify2( p, pPart1, pPart2 ) )
+        {
+            Llb_NonlinFree( p );
+            return NULL;
+        }
+        timeAndEx  += Abc_Clock() - clk2;
+        timeInside += Abc_Clock() - clk2;
+        if ( nReorders < Cudd_ReadReorderings(p->dd) )
+            Llb_NonlinRecomputeScores( p );
+//        else
+//            Llb_NonlinVerifyScores( p );
+    }
+    // load partitions
+    bFunc = Cudd_ReadOne(p->dd);   Cudd_Ref( bFunc );
+    Llb_MgrForEachPart( p, pPart, i )
+    {
+        bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc );
+        if ( bFunc == NULL )
+        {
+            Cudd_RecursiveDeref( p->dd, bTemp );
+            Llb_NonlinFree( p );
+            return NULL;
+        }
+        Cudd_Ref( bFunc );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+    }
+    nSuppMax = p->nSuppMax;
+    // reorder variables
+//    if ( fReorder )
+//        Llb_NonlinReorder( p->dd, 0, fVerbose );
+    // save permutation
+//    memcpy( pOrder, p->dd->invperm, sizeof(int) * Cudd_ReadSize(p->dd) );
+
+    timeOther += Abc_Clock() - clk - timeInside;
+    // return
+    Cudd_Deref( bFunc );
+    return bFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Quits image computation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_NonlinImageQuit()
+{
+    DdManager * dd;
+    if ( p == NULL )
+        return;
+    dd = p->dd;
+    Llb_NonlinFree( p );
+    if ( dd->bFunc )
+        Cudd_RecursiveDeref( dd, dd->bFunc );
+    Extra_StopManager( dd );
+//    Cudd_Quit ( dd );
+    p = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb3Nonlin.c b/abc-build/src/proof/llb/llb3Nonlin.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb3Nonlin.c
@@ -0,0 +1,872 @@
+/**CFile****************************************************************
+
+  FileName    [llb2Nonlin.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Non-linear quantification scheduling.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Mnn_t_ Llb_Mnn_t;
+struct Llb_Mnn_t_
+{
+    Aig_Man_t *     pInit;          // AIG manager
+    Aig_Man_t *     pAig;           // AIG manager
+    Gia_ParLlb_t *  pPars;          // parameters
+
+    DdManager *     dd;             // BDD manager
+    DdManager *     ddG;            // BDD manager
+    DdManager *     ddR;            // BDD manager
+    Vec_Ptr_t *     vRings;         // onion rings in ddR
+
+    Vec_Ptr_t *     vLeaves;        
+    Vec_Ptr_t *     vRoots;
+    int *           pVars2Q;
+    int *           pOrderL;
+    int *           pOrderL2;
+    int *           pOrderG;
+
+    Vec_Int_t *     vCs2Glo;        // cur state variables into global variables
+    Vec_Int_t *     vNs2Glo;        // next state variables into global variables
+    Vec_Int_t *     vGlo2Cs;        // global variables into cur state variables
+    Vec_Int_t *     vGlo2Ns;        // global variables into next state variables
+
+    int             ddLocReos;
+    int             ddLocGrbs;
+
+    abctime         timeImage;
+    abctime         timeTran1;
+    abctime         timeTran2;
+    abctime         timeGloba;
+    abctime         timeOther;
+    abctime         timeTotal;
+    abctime         timeReo;
+    abctime         timeReoG;
+
+};
+
+extern abctime timeBuild, timeAndEx, timeOther;
+extern int nSuppMax;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Finds variable whose 0-cofactor is the smallest.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_NonlinFindBestVar( DdManager * dd, DdNode * bFunc, Aig_Man_t * pAig )
+{
+    int fVerbose = 0;
+    Aig_Obj_t * pObj;
+    DdNode * bCof, * bVar;
+    int i, iVar, iVarBest = -1, iValue, iValueBest = ABC_INFINITY, Size0Best = -1;
+    int Size, Size0, Size1;
+    abctime clk = Abc_Clock();
+    Size = Cudd_DagSize(bFunc);
+//    printf( "Original = %6d.  SuppSize = %3d. Vars = %3d.\n", 
+//        Size = Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc), Aig_ManRegNum(pAig) );
+    Saig_ManForEachLo( pAig, pObj, i )
+    {
+        iVar = Aig_ObjId(pObj);
+
+if ( fVerbose )
+printf( "Var =%3d : ", iVar );
+        bVar = Cudd_bddIthVar(dd, iVar);
+
+        bCof = Cudd_bddAnd( dd, bFunc, Cudd_Not(bVar) );          Cudd_Ref( bCof );
+        Size0 = Cudd_DagSize(bCof);
+if ( fVerbose )
+printf( "Supp0 =%3d  ",  Cudd_SupportSize(dd, bCof) );
+if ( fVerbose )
+printf( "Size0 =%6d   ", Size0 );
+        Cudd_RecursiveDeref( dd, bCof );
+
+        bCof = Cudd_bddAnd( dd, bFunc, bVar );                    Cudd_Ref( bCof );
+        Size1 = Cudd_DagSize(bCof);
+if ( fVerbose )
+printf( "Supp1 =%3d  ",  Cudd_SupportSize(dd, bCof) );
+if ( fVerbose )
+printf( "Size1 =%6d   ", Size1 );
+        Cudd_RecursiveDeref( dd, bCof );
+
+        iValue = Abc_MaxInt(Size0, Size1) - Abc_MinInt(Size0, Size1) + Size0 + Size1 - Size;
+if ( fVerbose )
+printf( "D =%6d  ", Size0 + Size1 - Size );
+if ( fVerbose )
+printf( "B =%6d  ", Abc_MaxInt(Size0, Size1) - Abc_MinInt(Size0, Size1) );
+if ( fVerbose )
+printf( "S =%6d\n", iValue );
+        if ( Size0 > 1 && Size1 > 1 && iValueBest > iValue )
+        {
+            iValueBest = iValue;
+            iVarBest   = i;
+            Size0Best  = Size0;
+        }
+    }
+    printf( "BestVar = %4d/%4d.  Value =%6d.  Orig =%6d. Size0 =%6d. ", 
+        iVarBest, Aig_ObjId(Saig_ManLo(pAig,iVarBest)), iValueBest, Size, Size0Best );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return iVarBest;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds variable whose 0-cofactor is the smallest.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_NonlinTrySubsetting( DdManager * dd, DdNode * bFunc )
+{
+    DdNode * bNew;
+    printf( "Original = %6d.  SuppSize = %3d.    ", 
+        Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc) );
+    bNew = Cudd_SubsetHeavyBranch( dd, bFunc, Cudd_SupportSize(dd, bFunc), 1000 );  Cudd_Ref( bNew );
+    printf( "Result   = %6d.  SuppSize = %3d.\n", 
+        Cudd_DagSize(bNew), Cudd_SupportSize(dd, bNew) );
+    Cudd_RecursiveDeref( dd, bNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_NonlinPrepareVarMap( Llb_Mnn_t * p )
+{
+    Aig_Obj_t * pObjLi, * pObjLo, * pObj;
+    int i, iVarLi, iVarLo;
+    p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) );
+    p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) );
+    p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+    p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+    Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+    {
+        iVarLi = Aig_ObjId(pObjLi);
+        iVarLo = Aig_ObjId(pObjLo);
+        assert( iVarLi >= 0 && iVarLi < Aig_ManObjNumMax(p->pAig) );
+        assert( iVarLo >= 0 && iVarLo < Aig_ManObjNumMax(p->pAig) );
+        Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i );
+        Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i );
+        Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo );
+        Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi );
+    }
+    // add mapping of the PIs
+    Saig_ManForEachPi( p->pAig, pObj, i )
+    {
+        Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i );
+        Vec_IntWriteEntry( p->vNs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i );
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd )
+{
+    Aig_Obj_t * pObj;
+    DdNode * bRes, * bVar, * bTemp;
+    int i, iVar;
+    abctime TimeStop;
+    TimeStop = dd->TimeStop;  dd->TimeStop = 0;
+    bRes = Cudd_ReadOne( dd );   Cudd_Ref( bRes );
+    Saig_ManForEachLo( pAig, pObj, i )
+    {
+        iVar = (Cudd_ReadSize(dd) == Aig_ManRegNum(pAig)) ? i : Aig_ObjId(pObj);
+        bVar = Cudd_bddIthVar( dd, iVar );
+        bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) );  Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    Cudd_Deref( bRes );
+    dd->TimeStop = TimeStop;
+    return bRes;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives counter-example by backward reachability.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Llb_NonlinDeriveCex( Llb_Mnn_t * p )
+{
+    Abc_Cex_t * pCex;
+    Aig_Obj_t * pObj;
+    Vec_Int_t * vVarsNs;
+    DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing;
+    int i, v, RetValue, nPiOffset;
+    char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) );
+    assert( Vec_PtrSize(p->vRings) > 0 );
+
+    p->dd->TimeStop  = 0;
+    p->ddR->TimeStop = 0;
+
+    // update quantifiable vars
+    memset( p->pVars2Q, 0, sizeof(int) * Cudd_ReadSize(p->dd) );
+    vVarsNs = Vec_IntAlloc( Aig_ManRegNum(p->pAig) );
+    Saig_ManForEachLi( p->pAig, pObj, i )
+    {
+        p->pVars2Q[Aig_ObjId(pObj)] = 1;
+        Vec_IntPush( vVarsNs, Aig_ObjId(pObj) );
+    }
+/*
+    Saig_ManForEachLo( p->pAig, pObj, i )
+        printf( "%d ", pObj->Id );
+    printf( "\n" );
+    Saig_ManForEachLi( p->pAig, pObj, i )
+        printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) );
+    printf( "\n" );
+*/
+    // allocate room for the counter-example
+    pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) );
+    pCex->iFrame = Vec_PtrSize(p->vRings) - 1;
+    pCex->iPo = -1;
+
+    // get the last cube
+    bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc );  Cudd_Ref( bOneCube );
+    RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+    Cudd_RecursiveDeref( p->ddR, bOneCube );
+    assert( RetValue );
+
+    // write PIs of counter-example
+    nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1);
+    Saig_ManForEachPi( p->pAig, pObj, i )
+        if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+            Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+    // write state in terms of NS variables
+    if ( Vec_PtrSize(p->vRings) > 1 )
+    {
+        bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues );   Cudd_Ref( bState );
+    }
+    // perform backward analysis
+    Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v )
+    { 
+        if ( v == Vec_PtrSize(p->vRings) - 1 )
+            continue;
+//Extra_bddPrintSupport( p->dd, bState );  printf( "\n" );
+//Extra_bddPrintSupport( p->dd, bRing );   printf( "\n" );
+        // compute the next states
+        bImage = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bState, 
+            p->pPars->fReorder, p->pPars->fVeryVerbose, NULL ); // consumed reference
+        assert( bImage != NULL );
+        Cudd_Ref( bImage );
+//Extra_bddPrintSupport( p->dd, bImage );  printf( "\n" );
+
+        // move reached states into ring manager
+        bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) );    Cudd_Ref( bImage );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+
+        // intersect with the previous set
+        bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing );                Cudd_Ref( bOneCube );
+        Cudd_RecursiveDeref( p->ddR, bImage );
+
+        // find any assignment of the BDD
+        RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+        Cudd_RecursiveDeref( p->ddR, bOneCube );
+        assert( RetValue );
+
+        // write PIs of counter-example
+        nPiOffset -= Saig_ManPiNum(p->pAig);
+        Saig_ManForEachPi( p->pAig, pObj, i )
+            if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+                Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+        // check that we get the init state
+        if ( v == 0 )
+        {
+            Saig_ManForEachLo( p->pAig, pObj, i )
+                assert( pValues[i] == 0 );
+            break;
+        }
+
+        // write state in terms of NS variables
+        bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues );   Cudd_Ref( bState );
+    }
+    assert( nPiOffset == Saig_ManRegNum(p->pAig) );
+    // update the output number
+//Abc_CexPrint( pCex );
+    RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex );
+    assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!!
+    pCex->iPo = RetValue;
+    // cleanup
+    ABC_FREE( pValues );
+    Vec_IntFree( vVarsNs );
+    return pCex;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Perform reachability with hints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_NonlinReoHook( DdManager * dd, char * Type, void * Method )
+{
+    Aig_Man_t * pAig = (Aig_Man_t *)dd->bFunc;
+    Aig_Obj_t * pObj;
+    int i;
+    printf( "Order: " );
+    for ( i = 0; i < Cudd_ReadSize(dd); i++ )
+    {
+        pObj = Aig_ManObj( pAig, i );
+        if ( pObj == NULL )
+            continue;
+        if ( Saig_ObjIsPi(pAig, pObj) )
+            printf( "pi" );
+        else if ( Saig_ObjIsLo(pAig, pObj) )
+            printf( "lo" );
+        else if ( Saig_ObjIsPo(pAig, pObj) )
+            printf( "po" );
+        else if ( Saig_ObjIsLi(pAig, pObj) )
+            printf( "li" );
+        else continue;
+        printf( "%d=%d ", i, dd->perm[i] );
+    }
+    printf( "\n" );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform reachability with hints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_NonlinCompPerms( DdManager * dd, int * pVar2Lev )
+{
+    DdSubtable * pSubt;
+    int i, Sum = 0, Entry;
+    for ( i = 0; i < dd->size; i++ )
+    {
+        pSubt = &(dd->subtables[dd->perm[i]]);
+        if ( pSubt->keys == pSubt->dead + 1 )
+            continue;
+        Entry = Abc_MaxInt(dd->perm[i], pVar2Lev[i]) - Abc_MinInt(dd->perm[i], pVar2Lev[i]);
+        Sum += Entry;
+//printf( "%d-%d(%d) ", dd->perm[i], pV2L[i], Entry );
+    }
+    return Sum;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform reachability with hints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_NonlinReachability( Llb_Mnn_t * p )
+{ 
+    DdNode * bTemp, * bNext;
+    int nIters, nBddSize0, nBddSize = -1, NumCmp;//, Limit = p->pPars->nBddMax;
+    abctime clk2, clk3, clk = Abc_Clock();
+    assert( Aig_ManRegNum(p->pAig) > 0 );
+
+    // compute time to stop
+    p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0;
+
+    // set the stop time parameter
+    p->dd->TimeStop  = p->pPars->TimeTarget;
+    p->ddG->TimeStop = p->pPars->TimeTarget;
+    p->ddR->TimeStop = p->pPars->TimeTarget;
+
+    // set reordering hooks
+    assert( p->dd->bFunc == NULL );
+//    p->dd->bFunc = (DdNode *)p->pAig;
+//    Cudd_AddHook( p->dd, Llb_NonlinReoHook, CUDD_POST_REORDERING_HOOK );
+
+    // create bad state in the ring manager
+    p->ddR->bFunc  = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget );          
+    if ( p->ddR->bFunc == NULL )
+    {
+        if ( !p->pPars->fSilent )
+            printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+        p->pPars->iFrame = -1;
+        return -1;
+    }
+    Cudd_Ref( p->ddR->bFunc );
+    // compute the starting set of states
+    Cudd_Quit( p->dd );
+    p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 1, p->pPars->TimeTarget );
+    if ( p->dd == NULL )
+    {
+        if ( !p->pPars->fSilent )
+            printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+        p->pPars->iFrame = -1;
+        return -1;
+    }
+    p->dd->bFunc   = Llb_NonlinComputeInitState( p->pAig, p->dd );   Cudd_Ref( p->dd->bFunc );   // current
+    p->ddG->bFunc  = Llb_NonlinComputeInitState( p->pAig, p->ddG );  Cudd_Ref( p->ddG->bFunc );  // reached
+    p->ddG->bFunc2 = Llb_NonlinComputeInitState( p->pAig, p->ddG );  Cudd_Ref( p->ddG->bFunc2 ); // frontier 
+    for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ )
+    { 
+        // check the runtime limit
+        clk2 = Abc_Clock();
+        if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Llb_NonlinImageQuit();
+            return -1;
+        }
+
+        // save the onion ring
+        bTemp = Extra_TransferPermute( p->dd, p->ddR, p->dd->bFunc, Vec_IntArray(p->vCs2Glo) );
+        if ( bTemp == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during ring transfer.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Llb_NonlinImageQuit();
+            return -1;
+        }
+        Cudd_Ref( bTemp );
+        Vec_PtrPush( p->vRings, bTemp );
+
+        // check it for bad states
+        if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) 
+        {
+            assert( p->pInit->pSeqModel == NULL );
+            if ( !p->pPars->fBackward )
+                p->pInit->pSeqModel = Llb_NonlinDeriveCex( p ); 
+            if ( !p->pPars->fSilent )
+            {
+                if ( !p->pPars->fBackward )
+                    Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.  ", p->pInit->pSeqModel->iPo, nIters );
+                else
+                    Abc_Print( 1, "Output ??? was asserted in frame %d (counter-example is not produced).  ", nIters );
+                Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+            }
+            p->pPars->iFrame = nIters - 1;
+            Llb_NonlinImageQuit();
+            return 0;
+        }
+
+        // compute the next states
+        clk3 = Abc_Clock();
+        nBddSize0 = Cudd_DagSize( p->dd->bFunc );
+        bNext = Llb_NonlinImageCompute( p->dd->bFunc, p->pPars->fReorder, 0, 1, p->pOrderL ); // consumes ref   
+//        bNext = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bCurrent, 
+//            p->pPars->fReorder, p->pPars->fVeryVerbose, NULL, ABC_INFINITY, p->pPars->TimeTarget );
+        if ( bNext == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation in quantification.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Llb_NonlinImageQuit();
+            return -1;
+        }
+        Cudd_Ref( bNext );
+        nBddSize = Cudd_DagSize( bNext );
+        p->timeImage += Abc_Clock() - clk3;
+
+
+        // transfer to the state manager
+        clk3 = Abc_Clock();
+        Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 );
+        p->ddG->bFunc2 = Extra_TransferPermute( p->dd, p->ddG, bNext, Vec_IntArray(p->vNs2Glo) );    
+//        p->ddG->bFunc2 = Extra_bddAndPermute( p->ddG, Cudd_Not(p->ddG->bFunc), p->dd, bNext, Vec_IntArray(p->vNs2Glo) );    
+        if ( p->ddG->bFunc2 == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Cudd_RecursiveDeref( p->dd,  bNext );  
+            Llb_NonlinImageQuit();
+            return -1;
+        }
+        Cudd_Ref( p->ddG->bFunc2 );
+        Cudd_RecursiveDeref( p->dd, bNext );
+        p->timeTran1 += Abc_Clock() - clk3;
+
+        // save permutation
+        NumCmp = Llb_NonlinCompPerms( p->dd, p->pOrderL2 );
+        // save order before image computation
+        memcpy( p->pOrderL2, p->dd->perm, sizeof(int) * p->dd->size );
+        // update the image computation manager
+        p->timeReo   += Cudd_ReadReorderingTime(p->dd);
+        p->ddLocReos += Cudd_ReadReorderings(p->dd);
+        p->ddLocGrbs += Cudd_ReadGarbageCollections(p->dd);
+        Llb_NonlinImageQuit();
+        p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 0, p->pPars->TimeTarget );
+        if ( p->dd == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            return -1;
+        }
+        //Extra_TestAndPerm( p->ddG, Cudd_Not(p->ddG->bFunc), p->ddG->bFunc2 );    
+
+        // derive new states
+        clk3 = Abc_Clock();
+        p->ddG->bFunc2 = Cudd_bddAnd( p->ddG, bTemp = p->ddG->bFunc2, Cudd_Not(p->ddG->bFunc) );     
+        if ( p->ddG->bFunc2 == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Cudd_RecursiveDeref( p->ddG, bTemp );  
+            Llb_NonlinImageQuit();
+            return -1;
+        }
+        Cudd_Ref( p->ddG->bFunc2 );
+        Cudd_RecursiveDeref( p->ddG, bTemp );
+        p->timeGloba += Abc_Clock() - clk3;
+
+        if ( Cudd_IsConstant(p->ddG->bFunc2) )
+            break;
+        // add to the reached set
+        clk3 = Abc_Clock();
+        p->ddG->bFunc = Cudd_bddOr( p->ddG, bTemp = p->ddG->bFunc, p->ddG->bFunc2 );                 
+        if ( p->ddG->bFunc == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Cudd_RecursiveDeref( p->ddG, bTemp );  
+            Llb_NonlinImageQuit();
+            return -1;
+        }
+        Cudd_Ref( p->ddG->bFunc );
+        Cudd_RecursiveDeref( p->ddG, bTemp );
+        p->timeGloba += Abc_Clock() - clk3;
+
+        // reset permutation
+//        RetValue = Cudd_CheckZeroRef( dd );
+//        assert( RetValue == 0 );
+//        Cudd_ShuffleHeap( dd, pOrderG );
+
+        // move new states to the working manager
+        clk3 = Abc_Clock();
+        p->dd->bFunc = Extra_TransferPermute( p->ddG, p->dd, p->ddG->bFunc2, Vec_IntArray(p->vGlo2Cs) ); 
+        if ( p->dd->bFunc == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Llb_NonlinImageQuit();
+            return -1;
+        }
+        Cudd_Ref( p->dd->bFunc );
+        p->timeTran2 += Abc_Clock() - clk3;
+
+        // report the results
+        if ( p->pPars->fVerbose )
+        {
+            printf( "I =%3d : ",   nIters );
+            printf( "Fr =%7d ",    nBddSize0 );
+            printf( "Im =%7d  ",   nBddSize );
+            printf( "(%4d %4d)  ", p->ddLocReos, p->ddLocGrbs );
+            printf( "Rea =%6d  ",  Cudd_DagSize(p->ddG->bFunc) );
+            printf( "(%4d %4d)  ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) );
+            printf( "S =%4d ",     nSuppMax );
+            printf( "cL =%5d ",    NumCmp );
+            printf( "cG =%5d ",    Llb_NonlinCompPerms( p->ddG, p->pOrderG ) );
+            Abc_PrintTime( 1, "T", Abc_Clock() - clk2 );
+            memcpy( p->pOrderG, p->ddG->perm, sizeof(int) * p->ddG->size );
+        }
+/*
+        if ( pPars->fVerbose )
+        {
+            double nMints = Cudd_CountMinterm(ddG, bReached, Saig_ManRegNum(pAig) );
+//            Extra_bddPrint( ddG, bReached );printf( "\n" );
+            printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(pAig)) );
+            fflush( stdout ); 
+        }
+*/
+        if ( nIters == p->pPars->nIterMax - 1 )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached limit on the number of timeframes (%d).\n",  p->pPars->nIterMax );
+            p->pPars->iFrame = nIters;
+            Llb_NonlinImageQuit();
+            return -1;
+        }
+    }
+    Llb_NonlinImageQuit();
+    
+    // report the stats
+    if ( p->pPars->fVerbose )
+    {
+        double nMints = Cudd_CountMinterm(p->ddG, p->ddG->bFunc, Saig_ManRegNum(p->pAig) );
+        if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax )
+            printf( "Reachability analysis is stopped after %d frames.\n", nIters );
+        else
+            printf( "Reachability analysis completed after %d frames.\n", nIters );
+        printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+        fflush( stdout ); 
+    }
+    if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax )
+    {
+        if ( !p->pPars->fSilent )
+            printf( "Verified only for states reachable in %d frames.  ", nIters );
+        p->pPars->iFrame = p->pPars->nIterMax;
+        return -1; // undecided
+    }
+    // report
+    if ( !p->pPars->fSilent )
+        printf( "The miter is proved unreachable after %d iterations.  ", nIters );
+    p->pPars->iFrame = nIters - 1;
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return 1; // unreachable
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Llb_Mnn_t * Llb_MnnStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t *  pPars )
+{
+    Llb_Mnn_t * p;
+    Aig_Obj_t * pObj;
+    int i;
+    p = ABC_CALLOC( Llb_Mnn_t, 1 );
+    p->pInit = pInit;
+    p->pAig  = pAig;
+    p->pPars = pPars;
+    p->dd    = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    p->ddG   = Cudd_Init( Aig_ManRegNum(pAig),    0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    p->ddR   = Cudd_Init( Aig_ManCiNum(pAig),     0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    Cudd_AutodynEnable( p->dd,  CUDD_REORDER_SYMM_SIFT );
+    Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT );
+    Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT );
+    p->vRings = Vec_PtrAlloc( 100 );
+    // create leaves
+    p->vLeaves = Vec_PtrAlloc( Aig_ManCiNum(pAig) );
+    Aig_ManForEachCi( pAig, pObj, i )
+        Vec_PtrPush( p->vLeaves, pObj );
+    // create roots
+    p->vRoots = Vec_PtrAlloc( Aig_ManCoNum(pAig) );
+    Saig_ManForEachLi( pAig, pObj, i )
+        Vec_PtrPush( p->vRoots, pObj );
+    // variables to quantify
+    p->pOrderL = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+    p->pOrderL2= ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+    p->pOrderG = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+    p->pVars2Q = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+    Aig_ManForEachCi( pAig, pObj, i )
+        p->pVars2Q[Aig_ObjId(pObj)] = 1;
+    for ( i = 0; i < Aig_ManObjNumMax(pAig); i++ )
+        p->pOrderL[i] = p->pOrderL2[i] = p->pOrderG[i] = i;
+    Llb_NonlinPrepareVarMap( p ); 
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_MnnStop( Llb_Mnn_t * p )
+{
+    DdNode * bTemp;
+    int i;
+    if ( p->pPars->fVerbose ) 
+    {
+        p->timeOther = p->timeTotal - p->timeImage - p->timeTran1 - p->timeTran2 - p->timeGloba;
+        p->timeReoG  = Cudd_ReadReorderingTime(p->ddG);
+        ABC_PRTP( "Image    ", p->timeImage, p->timeTotal );
+        ABC_PRTP( "  build  ",    timeBuild, p->timeTotal );
+        ABC_PRTP( "  and-ex ",    timeAndEx, p->timeTotal );
+        ABC_PRTP( "  other  ",    timeOther, p->timeTotal );
+        ABC_PRTP( "Transfer1", p->timeTran1, p->timeTotal );
+        ABC_PRTP( "Transfer2", p->timeTran2, p->timeTotal );
+        ABC_PRTP( "Global   ", p->timeGloba, p->timeTotal );
+        ABC_PRTP( "Other    ", p->timeOther, p->timeTotal );
+        ABC_PRTP( "TOTAL    ", p->timeTotal, p->timeTotal );
+        ABC_PRTP( "  reo    ", p->timeReo,   p->timeTotal );
+        ABC_PRTP( "  reoG   ", p->timeReoG,  p->timeTotal );
+    }
+    if ( p->ddR->bFunc )
+        Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc );
+    Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i )
+        Cudd_RecursiveDeref( p->ddR, bTemp );
+    Vec_PtrFree( p->vRings );
+    if ( p->ddG->bFunc )
+        Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc );
+    if ( p->ddG->bFunc2 )
+        Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 );
+//    printf( "manager1\n" );
+//    Extra_StopManager( p->dd );
+//    printf( "manager2\n" );
+    Extra_StopManager( p->ddG );
+//    printf( "manager3\n" );
+    Extra_StopManager( p->ddR );
+    Vec_IntFreeP( &p->vCs2Glo );
+    Vec_IntFreeP( &p->vNs2Glo );
+    Vec_IntFreeP( &p->vGlo2Cs );
+    Vec_IntFreeP( &p->vGlo2Ns );
+    Vec_PtrFree( p->vLeaves );
+    Vec_PtrFree( p->vRoots );
+    ABC_FREE( p->pVars2Q );
+    ABC_FREE( p->pOrderL );
+    ABC_FREE( p->pOrderL2 );
+    ABC_FREE( p->pOrderG );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Finds balanced cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_NonlinExperiment( Aig_Man_t * pAig, int Num )
+{
+    Llb_Mnn_t * pMnn;
+    Gia_ParLlb_t Pars, * pPars = &Pars;
+    Aig_Man_t * p;
+    abctime clk = Abc_Clock();
+
+    Llb_ManSetDefaultParams( pPars );
+    pPars->fVerbose = 1;
+
+    p = Aig_ManDupFlopsOnly( pAig );
+//Aig_ManShow( p, 0, NULL );
+    Aig_ManPrintStats( pAig );
+    Aig_ManPrintStats( p );
+
+    pMnn = Llb_MnnStart( pAig, p, pPars );
+    Llb_NonlinReachability( pMnn );
+    pMnn->timeTotal = Abc_Clock() - clk;
+    Llb_MnnStop( pMnn );
+
+    Aig_ManStop( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds balanced cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_NonlinCoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+    Llb_Mnn_t * pMnn;
+    Aig_Man_t * p;
+    int RetValue = -1;
+
+    p = Aig_ManDupFlopsOnly( pAig );
+//Aig_ManShow( p, 0, NULL );
+    if ( pPars->fVerbose )
+    Aig_ManPrintStats( pAig );
+    if ( pPars->fVerbose )
+    Aig_ManPrintStats( p );
+
+    if ( !pPars->fSkipReach )
+    {
+        abctime clk = Abc_Clock();
+        pMnn = Llb_MnnStart( pAig, p, pPars );
+        RetValue = Llb_NonlinReachability( pMnn );
+        pMnn->timeTotal = Abc_Clock() - clk;
+        Llb_MnnStop( pMnn );
+    }
+
+    Aig_ManStop( p );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb4Cex.c b/abc-build/src/proof/llb/llb4Cex.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb4Cex.c
@@ -0,0 +1,320 @@
+/**CFile****************************************************************
+
+  FileName    [llb2Cex.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Non-linear quantification scheduling.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb2Cex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Translates a sequence of states into a counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose )
+{
+    Abc_Cex_t * pCex;
+    Cnf_Dat_t * pCnf;
+    Vec_Int_t * vAssumps;
+    sat_solver * pSat;
+    Aig_Obj_t * pObj;
+    unsigned * pNext, * pThis;
+    int i, k, iBit, status, nRegs;//, clk = Abc_Clock();
+/*
+    Vec_PtrForEachEntry( unsigned *, vStates, pNext, i )
+    {
+        printf( "%4d : ", i );
+        Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) );
+        printf( "\n" );
+    }
+*/
+    // derive SAT solver
+    nRegs = Aig_ManRegNum(pAig); pAig->nRegs = 0;
+    pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) );
+    pAig->nRegs = nRegs;
+//    Cnf_DataTranformPolarity( pCnf, 0 );
+    // convert into SAT solver
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+    if ( pSat == NULL )
+    {
+        printf( "Llb4_Nonlin4TransformCex(): Counter-example generation has failed.\n" );
+        Cnf_DataFree( pCnf );
+        return NULL;
+    }
+    // simplify the problem
+    status = sat_solver_simplify(pSat);
+    if ( status == 0 )
+    {
+        printf( "Llb4_Nonlin4TransformCex(): SAT solver is invalid.\n" );
+        sat_solver_delete( pSat );
+        Cnf_DataFree( pCnf );
+        return NULL;
+    }
+    // start the counter-example
+    pCex = Abc_CexAlloc( Saig_ManRegNum(pAig), Saig_ManPiNum(pAig), Vec_PtrSize(vStates) );
+    pCex->iFrame = Vec_PtrSize(vStates)-1;
+    pCex->iPo = -1;
+
+    // solve each time frame
+    iBit = Saig_ManRegNum(pAig);
+    pThis = (unsigned *)Vec_PtrEntry( vStates, 0 );
+    vAssumps = Vec_IntAlloc( 2 * Aig_ManRegNum(pAig) );
+    Vec_PtrForEachEntryStart( unsigned *, vStates, pNext, i, 1 )
+    {
+        // create assumptions
+        Vec_IntClear( vAssumps );
+        Saig_ManForEachLo( pAig, pObj, k )
+            Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pThis,k) ) );
+        Saig_ManForEachLi( pAig, pObj, k )
+            Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pNext,k) ) );
+        // solve SAT problem
+        status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), 
+            (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        // if the problem is SAT, get the counterexample
+        if ( status != l_True )
+        {
+            printf( "Llb4_Nonlin4TransformCex(): There is no transition between state %d and %d.\n", i-1, i );
+            Vec_IntFree( vAssumps );
+            sat_solver_delete( pSat );
+            Cnf_DataFree( pCnf );
+            ABC_FREE( pCex );
+            return NULL;
+        }
+        // get the assignment of PIs
+        Saig_ManForEachPi( pAig, pObj, k )
+            if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) )
+                Abc_InfoSetBit( pCex->pData, iBit + k );
+        // update the counter
+        iBit += Saig_ManPiNum(pAig);
+        pThis = pNext;
+    }
+
+    // add the last frame when the property fails
+    Vec_IntClear( vAssumps );
+    if ( iCexPo >= 0 )
+    {
+        Saig_ManForEachPo( pAig, pObj, k )
+            if ( k == iCexPo )
+                Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) );
+    }
+    else
+    {
+        Saig_ManForEachPo( pAig, pObj, k )
+            Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) );
+    }
+
+    // add clause
+    status = sat_solver_addclause( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps) );
+    if ( status == 0 )
+    {
+        printf( "Llb4_Nonlin4TransformCex(): The SAT solver is unsat after adding last clause.\n" );
+        Vec_IntFree( vAssumps );
+        sat_solver_delete( pSat );
+        Cnf_DataFree( pCnf );
+        ABC_FREE( pCex );
+        return NULL;
+    }
+    // create assumptions
+    Vec_IntClear( vAssumps );
+    Saig_ManForEachLo( pAig, pObj, k )
+        Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pThis,k) ) );
+    // solve the last frame
+    status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), 
+        (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( status != l_True )
+    {
+        printf( "Llb4_Nonlin4TransformCex(): There is no last transition that makes the property fail.\n" );
+        Vec_IntFree( vAssumps );
+        sat_solver_delete( pSat );
+        Cnf_DataFree( pCnf );
+        ABC_FREE( pCex );
+        return NULL;
+    }
+    // get the assignment of PIs
+    Saig_ManForEachPi( pAig, pObj, k )
+        if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) )
+            Abc_InfoSetBit( pCex->pData, iBit + k );
+    iBit += Saig_ManPiNum(pAig);
+    assert( iBit == pCex->nBits );
+
+    // free the sat_solver
+    Vec_IntFree( vAssumps );
+    sat_solver_delete( pSat );
+    Cnf_DataFree( pCnf );
+
+    // verify counter-example
+    status = Saig_ManFindFailedPoCex( pAig, pCex );
+    if ( status >= 0 && status < Saig_ManPoNum(pAig) )
+        pCex->iPo = status;
+    else
+    {
+        printf( "Llb4_Nonlin4TransformCex(): Counter-example verification has FAILED.\n" );
+        ABC_FREE( pCex );
+        return NULL;
+    }
+    // report the results
+//    if ( fVerbose )
+//       Abc_PrintTime( 1, "SAT-based cex generation time", Abc_Clock() - clk );
+    return pCex;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Resimulates the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb4_Nonlin4VerifyCex( Aig_Man_t * pAig, Abc_Cex_t * p )
+{
+    Vec_Ptr_t * vStates;
+    Aig_Obj_t * pObj, * pObjRi, * pObjRo;
+    int i, k, iBit = 0;
+    // create storage for states
+    vStates = Vec_PtrAllocSimInfo( p->iFrame+1, Abc_BitWordNum(Aig_ManRegNum(pAig)) );
+    Vec_PtrCleanSimInfo( vStates, 0, Abc_BitWordNum(Aig_ManRegNum(pAig)) );
+    // verify counter-example
+    Aig_ManCleanMarkB(pAig);
+    Aig_ManConst1(pAig)->fMarkB = 1;
+    Saig_ManForEachLo( pAig, pObj, i )
+        pObj->fMarkB = 0; //Abc_InfoHasBit(p->pData, iBit++);
+    // do not require equal flop count in the AIG and in the CEX
+    iBit = p->nRegs;
+    for ( i = 0; i <= p->iFrame; i++ )
+    {
+        // save current state
+        Saig_ManForEachLo( pAig, pObj, k )
+            if ( pObj->fMarkB )
+                Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(vStates, i), k );
+        // compute new state
+        Saig_ManForEachPi( pAig, pObj, k )
+            pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++);
+        Aig_ManForEachNode( pAig, pObj, k )
+            pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & 
+                           (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj));
+        Aig_ManForEachCo( pAig, pObj, k )
+            pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj);
+        if ( i == p->iFrame )
+            break;
+        Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k )
+            pObjRo->fMarkB = pObjRi->fMarkB;
+    }
+/*
+    {
+        unsigned * pNext;
+        Vec_PtrForEachEntry( unsigned *, vStates, pNext, i )
+        {
+            printf( "%4d : ", i );
+            Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) );
+            printf( "\n" );
+        }
+    }
+*/
+    assert( iBit == p->nBits );
+//    if ( Aig_ManCo(pAig, p->iPo)->fMarkB == 0 )
+//        Vec_PtrFreeP( &vStates );
+	for ( i = Saig_ManPoNum(pAig) - 1; i >= 0; i-- )
+	{
+        if ( Aig_ManCo(pAig, i)->fMarkB )
+        {
+            p->iPo = i;
+            break;
+        }
+	}
+    if ( i == -1 )
+        Vec_PtrFreeP( &vStates );
+    Aig_ManCleanMarkB(pAig);
+    return vStates;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Translates a sequence of states into a counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Llb4_Nonlin4NormalizeCex( Aig_Man_t * pAigOrg, Aig_Man_t * pAigRpm, Abc_Cex_t * pCexRpm )
+{
+    Abc_Cex_t * pCexOrg;
+    Vec_Ptr_t * vStates;
+    // check parameters of the AIG
+    if ( Saig_ManRegNum(pAigOrg) != Saig_ManRegNum(pAigRpm) )
+    {
+        printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the original and reparametrized AIGs do not agree.\n" );
+        return NULL;
+    }
+/*
+    if ( Saig_ManRegNum(pAigRpm) != pCexRpm->nRegs )
+    {
+        printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the reparametrized AIG and in the CEX do not agree.\n" );
+        return NULL;
+    }
+*/
+    if ( Saig_ManPiNum(pAigRpm) != pCexRpm->nPis )
+    {
+        printf( "Llb4_Nonlin4NormalizeCex(): The number of PIs in the reparametrized AIG and in the CEX do not agree.\n" );
+        return NULL;
+    }
+    // get the sequence of states
+    vStates = Llb4_Nonlin4VerifyCex( pAigRpm, pCexRpm );
+    if ( vStates == NULL )
+    {
+    	Abc_Print( 1, "Llb4_Nonlin4NormalizeCex(): The given CEX does not fail outputs of pAigRpm.\n" );
+        return NULL;
+    }
+    // derive updated counter-example
+    pCexOrg = Llb4_Nonlin4TransformCex( pAigOrg, vStates, pCexRpm->iPo, 0 );
+    Vec_PtrFree( vStates );
+    return pCexOrg;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb4Cluster.c b/abc-build/src/proof/llb/llb4Cluster.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb4Cluster.c
@@ -0,0 +1,452 @@
+/**CFile****************************************************************
+
+  FileName    [llb2Cluster.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Non-linear quantification scheduling.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb2Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Find good static variable ordering.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4FindOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter )
+{
+    Aig_Obj_t * pFanin0, * pFanin1;
+    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent( pAig, pObj );
+    assert( Llb_ObjBddVar(vOrder, pObj) < 0 );
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+        return;
+    }
+    // try fanins with higher level first
+    pFanin0 = Aig_ObjFanin0(pObj);
+    pFanin1 = Aig_ObjFanin1(pObj);
+//    if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) )
+    if ( pFanin0->Level > pFanin1->Level )
+    {
+        Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter );
+        Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter );
+    }
+    else
+    {
+        Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter );
+        Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter );
+    }
+    if ( pObj->fMarkA )
+        Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find good static variable ordering.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4FindOrder( Aig_Man_t * pAig, int * pCounter )
+{
+    Vec_Int_t * vNodes = NULL;
+    Vec_Int_t * vOrder;
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    // mark nodes to exclude:  AND with low level and CO drivers
+    Aig_ManCleanMarkA( pAig );
+    Aig_ManForEachNode( pAig, pObj, i )
+        if ( Aig_ObjLevel(pObj) > 3 )
+            pObj->fMarkA = 1;
+    Aig_ManForEachCo( pAig, pObj, i )
+        Aig_ObjFanin0(pObj)->fMarkA = 0;
+
+    // collect nodes in the order
+    vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) );
+    Aig_ManIncrementTravId( pAig );
+    Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) );
+//    Aig_ManForEachCo( pAig, pObj, i )
+    Saig_ManForEachLi( pAig, pObj, i )
+    {
+        Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+        Llb_Nonlin4FindOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter );
+    }
+    Aig_ManForEachCi( pAig, pObj, i )
+        if ( Llb_ObjBddVar(vOrder, pObj) < 0 )
+            Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+    Aig_ManCleanMarkA( pAig );
+    Vec_IntFreeP( &vNodes );
+//    assert( Counter == Aig_ManObjNum(pAig) - 1 );
+
+/*
+    Saig_ManForEachPi( pAig, pObj, i )
+        printf( "pi%d ", Llb_ObjBddVar(vOrder, pObj) );
+    printf( "\n" );
+    Saig_ManForEachLo( pAig, pObj, i )
+        printf( "lo%d ", Llb_ObjBddVar(vOrder, pObj) );
+    printf( "\n" );
+    Saig_ManForEachPo( pAig, pObj, i )
+        printf( "po%d ", Llb_ObjBddVar(vOrder, pObj) );
+    printf( "\n" );
+    Saig_ManForEachLi( pAig, pObj, i )
+        printf( "li%d ", Llb_ObjBddVar(vOrder, pObj) );
+    printf( "\n" );
+    Aig_ManForEachNode( pAig, pObj, i )
+        printf( "n%d ", Llb_ObjBddVar(vOrder, pObj) );
+    printf( "\n" );
+*/
+    if ( pCounter )
+        *pCounter = Counter;
+    return vOrder;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives BDDs for the partitions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4FindPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots )
+{
+    DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar;
+    if ( Aig_ObjIsConst1(pObj) )
+        return Cudd_ReadOne(dd); 
+    if ( Aig_ObjIsCi(pObj) )
+        return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+    if ( pObj->pData )
+        return (DdNode *)pObj->pData;
+    if ( Aig_ObjIsCo(pObj) )
+    {
+        bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) );
+        bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 );  Cudd_Ref( bPart );
+        Vec_PtrPush( vRoots, bPart );
+        return NULL;
+    }
+    bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) );
+    bBdd1 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) );
+    bBdd  = Cudd_bddAnd( dd, bBdd0, bBdd1 );   Cudd_Ref( bBdd );
+    if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+    {
+        vVar  = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+        bPart = Cudd_bddXnor( dd, vVar, bBdd );  Cudd_Ref( bPart );
+        Vec_PtrPush( vRoots, bPart );
+        Cudd_RecursiveDeref( dd, bBdd );
+        bBdd = vVar;  Cudd_Ref( vVar );
+    }
+    pObj->pData = bBdd;
+    return bBdd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives BDDs for the partitions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4FindPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fOutputs )
+{
+    Vec_Ptr_t * vRoots;
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManCleanData( pAig );
+    vRoots = Vec_PtrAlloc( 100 );
+    if ( fOutputs )
+    {
+        Saig_ManForEachPo( pAig, pObj, i )
+            Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots );
+    }
+    else
+    {
+        Saig_ManForEachLi( pAig, pObj, i )
+            Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots );
+    }
+    Aig_ManForEachNode( pAig, pObj, i )
+        if ( pObj->pData )
+            Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+    return vRoots;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates quantifiable variables for both types of traversal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4FindVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder )
+{
+    Vec_Int_t * vVars2Q;
+    Aig_Obj_t * pObj;
+    int i;
+    vVars2Q = Vec_IntAlloc( 0 );
+    Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 );
+    Saig_ManForEachLo( pAig, pObj, i )
+        Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 );
+//    Aig_ManForEachCo( pAig, pObj, i )
+    Saig_ManForEachLi( pAig, pObj, i )
+        Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 );
+    return vVars2Q;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates quantifiable variables for both types of traversal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_Nonlin4CountTerms( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, DdNode * bFunc, int fCo, int fFlop )
+{
+    DdNode * bSupp;
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    bSupp = Cudd_Support( dd, bFunc );  Cudd_Ref( bSupp );
+    if ( !fCo && !fFlop )
+    {
+        Saig_ManForEachPi( pAig, pObj, i )
+            if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+                Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) );
+    }
+    else if ( fCo && !fFlop )
+    {
+        Saig_ManForEachPo( pAig, pObj, i )
+            if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+                Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) );
+    }
+    else if ( !fCo && fFlop )
+    {
+        Saig_ManForEachLo( pAig, pObj, i )
+            if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+                Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) );
+    }
+    else if ( fCo && fFlop )
+    {
+        Saig_ManForEachLi( pAig, pObj, i )
+            if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+                Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) );
+    }
+    Cudd_RecursiveDeref( dd, bSupp );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates quantifiable variables for both types of traversal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4PrintGroups( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups )
+{
+    DdNode * bTemp;
+    int i, nSuppAll, nSuppPi, nSuppPo, nSuppLi, nSuppLo, nSuppAnd;
+    Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i )
+    {
+//Extra_bddPrintSupport(dd, bTemp);  printf("\n" );
+        nSuppAll = Cudd_SupportSize(dd,bTemp);
+        nSuppPi  = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 0);
+        nSuppPo  = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 0);
+        nSuppLi  = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 1);
+        nSuppLo  = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 1);
+        nSuppAnd = nSuppAll - (nSuppPi+nSuppPo+nSuppLi+nSuppLo);
+
+        if ( Cudd_DagSize(bTemp) <= 10 )
+            continue;
+
+        printf( "%4d : bdd =%6d  supp =%3d  ", i, Cudd_DagSize(bTemp), nSuppAll );
+        printf( "pi =%3d ",  nSuppPi );
+        printf( "po =%3d ",  nSuppPo );
+        printf( "lo =%3d ",  nSuppLo );
+        printf( "li =%3d ",  nSuppLi );
+        printf( "and =%3d",  nSuppAnd );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates quantifiable variables for both types of traversal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4PrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups )
+{
+    Aig_Obj_t * pObj;
+    int i, * pSupp;
+    int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0;
+
+    pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) );
+    Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp );
+
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+        if ( Llb_ObjBddVar(vOrder, pObj) < 0 )
+            continue;
+        // remove variables that do not participate
+        if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 )
+        {
+            if ( Aig_ObjIsNode(pObj) )
+                Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 );
+            continue;
+        }
+        nSuppAll++;
+        if ( Saig_ObjIsPi(pAig, pObj) )
+            nSuppPi++;
+        else if ( Saig_ObjIsLo(pAig, pObj) )
+            nSuppLo++;
+        else if ( Saig_ObjIsPo(pAig, pObj) )
+            nSuppPo++;
+        else if ( Saig_ObjIsLi(pAig, pObj) )
+            nSuppLi++;
+        else
+            nSuppAnd++;
+    }
+    ABC_FREE( pSupp );
+
+    printf( "Groups =%3d  ", Vec_PtrSize(vGroups) );
+    printf( "Variables: all =%4d ",  nSuppAll );
+    printf( "pi =%4d ",  nSuppPi );
+    printf( "po =%4d ",  nSuppPo );
+    printf( "lo =%4d ",  nSuppLo );
+    printf( "li =%4d ",  nSuppLi );
+    printf( "and =%4d",  nSuppAnd );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose )
+{
+    DdManager * dd;
+    Vec_Int_t * vOrder, * vVars2Q;
+    Vec_Ptr_t * vParts, * vGroups;
+    DdNode * bTemp;
+    int i, nVarNum;
+
+    // create the BDD manager
+    vOrder  = Llb_Nonlin4FindOrder( pAig, &nVarNum );
+    dd      = Cudd_Init( nVarNum, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+//    Cudd_AutodynEnable( dd,  CUDD_REORDER_SYMM_SIFT );
+
+    vVars2Q = Llb_Nonlin4FindVars2Q( dd, pAig, vOrder );
+    vParts  = Llb_Nonlin4FindPartitions( dd, pAig, vOrder, 0 );
+
+    vGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddMax );
+    Vec_IntFree( vVars2Q );
+
+    Vec_PtrForEachEntry( DdNode *, vParts, bTemp, i )
+        Cudd_RecursiveDeref( dd, bTemp );
+    Vec_PtrFree( vParts );
+
+
+//    if ( fVerbose )
+    Llb_Nonlin4PrintSuppProfile( dd, pAig, vOrder, vGroups );
+    if ( fVerbose )
+    printf( "Before reordering\n" );
+    if ( fVerbose )
+    Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups );
+
+//    Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 );
+//    printf( "After reordering\n" );
+//    Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups );
+
+    if ( pvOrder )
+        *pvOrder = vOrder;
+    else
+        Vec_IntFree( vOrder );
+
+    if ( pvGroups )
+        *pvGroups = vGroups;
+    else
+    {
+        Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i )
+            Cudd_RecursiveDeref( dd, bTemp );
+        Vec_PtrFree( vGroups );
+    }
+
+    if ( pdd )
+        *pdd = dd;
+    else
+        Extra_StopManager( dd );
+//    Cudd_Quit( dd );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb4Image.c b/abc-build/src/proof/llb/llb4Image.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb4Image.c
@@ -0,0 +1,863 @@
+/**CFile****************************************************************
+
+  FileName    [llb3Image.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Computes image using partitioned structure.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Var_t_ Llb_Var_t;
+struct Llb_Var_t_ 
+{
+    int           iVar;      // variable number
+    int           nScore;    // variable score
+    Vec_Int_t *   vParts;    // partitions
+};
+
+typedef struct Llb_Prt_t_ Llb_Prt_t;
+struct Llb_Prt_t_ 
+{
+    int           iPart;     // partition number
+    int           nSize;     // the number of BDD nodes
+    DdNode *      bFunc;     // the partition
+    Vec_Int_t *   vVars;     // support
+};
+
+typedef struct Llb_Mgr_t_ Llb_Mgr_t;
+struct Llb_Mgr_t_
+{
+    DdManager *   dd;        // working BDD manager
+    Vec_Int_t *   vVars2Q;   // variables to quantify
+    int           nSizeMax;  // maximum size of the cluster
+    // internal
+    Llb_Prt_t **  pParts;    // partitions
+    Llb_Var_t **  pVars;     // variables
+    int           iPartFree; // next free partition
+    int           nVars;     // the number of BDD variables
+    int           nSuppMax;  // maximum support size
+    // temporary
+    int *         pSupp;     // temporary support storage
+};
+
+static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i )   { return p->pVars[i];  }
+static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i )  { return p->pParts[i]; }
+
+// iterator over vars
+#define Llb_MgrForEachVar( p, pVar, i )     \
+    for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else
+// iterator over parts
+#define Llb_MgrForEachPart( p, pPart, i )   \
+    for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else
+
+// iterator over vars of one partition
+#define Llb_PartForEachVar( p, pPart, pVar, i )   \
+    for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ )
+// iterator over parts of one variable
+#define Llb_VarForEachPart( p, pVar, pPart, i )   \
+    for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ )
+
+// statistics
+//abctime timeBuild, timeAndEx, timeOther;
+//int nSuppMax;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Removes one variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4RemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar )
+{
+    assert( p->pVars[pVar->iVar] == pVar );
+    p->pVars[pVar->iVar] = NULL;
+    Vec_IntFree( pVar->vParts );
+    ABC_FREE( pVar );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes one partition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4RemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+//printf( "Removing %d\n", pPart->iPart );
+    assert( p->pParts[pPart->iPart] == pPart );
+    p->pParts[pPart->iPart] = NULL;
+    Vec_IntFree( pPart->vVars );
+    Cudd_RecursiveDeref( p->dd, pPart->bFunc );
+    ABC_FREE( pPart );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create cube with singleton variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4CreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+    DdNode * bCube, * bTemp;
+    Llb_Var_t * pVar;
+    int i;
+    abctime TimeStop;
+    TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+    bCube = Cudd_ReadOne(p->dd);   Cudd_Ref( bCube );
+    Llb_PartForEachVar( p, pPart, pVar, i )
+    {
+        assert( Vec_IntSize(pVar->vParts) > 0 );
+        if ( Vec_IntSize(pVar->vParts) != 1 )
+            continue;
+        assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart );
+        bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) );    Cudd_Ref( bCube );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+    }
+    Cudd_Deref( bCube );
+    p->dd->TimeStop = TimeStop;
+    return bCube;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create cube of variables appearing only in two partitions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4CreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 )
+{
+    DdNode * bCube, * bTemp;
+    Llb_Var_t * pVar;
+    int i;
+    abctime TimeStop;
+    TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+    bCube = Cudd_ReadOne(p->dd);   Cudd_Ref( bCube );
+    Llb_PartForEachVar( p, pPart1, pVar, i )
+    {
+        assert( Vec_IntSize(pVar->vParts) > 0 );
+        if ( Vec_IntSize(pVar->vParts) != 2 )
+            continue;
+        if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) ||
+             (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) )
+        {
+            bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) );   Cudd_Ref( bCube );
+            Cudd_RecursiveDeref( p->dd, bTemp );
+        }
+    }
+    Cudd_Deref( bCube );
+    p->dd->TimeStop = TimeStop;
+    return bCube;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if partition has singleton variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_Nonlin4HasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+    Llb_Var_t * pVar;
+    int i;
+    Llb_PartForEachVar( p, pPart, pVar, i )
+        if ( Vec_IntSize(pVar->vParts) == 1 )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if partition has singleton variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4Print( Llb_Mgr_t * p )
+{
+    Llb_Prt_t * pPart;
+    Llb_Var_t * pVar;
+    int i, k;
+    printf( "\n" );
+    Llb_MgrForEachVar( p, pVar, i )
+    {
+        printf( "Var %3d : ", i );
+        Llb_VarForEachPart( p, pVar, pPart, k )
+            printf( "%d ", pPart->iPart );
+        printf( "\n" );
+    }
+    Llb_MgrForEachPart( p, pPart, i )
+    {
+        printf( "Part %3d : ", i );
+        Llb_PartForEachVar( p, pPart, pVar, k )
+            printf( "%d ", pVar->iVar );
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Quantifies singles belonging to one partition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_Nonlin4Quantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+    Llb_Var_t * pVar;
+    Llb_Prt_t * pTemp;
+    Vec_Ptr_t * vSingles;
+    DdNode * bCube, * bTemp;
+    int i, RetValue, nSizeNew;
+    // create cube to be quantified
+    bCube = Llb_Nonlin4CreateCube1( p, pPart );   Cudd_Ref( bCube );
+//    assert( !Cudd_IsConstant(bCube) );
+    // derive new function
+    pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube );  Cudd_Ref( pPart->bFunc );
+    Cudd_RecursiveDeref( p->dd, bTemp );
+    Cudd_RecursiveDeref( p->dd, bCube );
+    // get support
+    vSingles = Vec_PtrAlloc( 0 );
+    nSizeNew = Cudd_DagSize(pPart->bFunc);
+    Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp );
+    Llb_PartForEachVar( p, pPart, pVar, i )
+        if ( p->pSupp[pVar->iVar] )
+        {
+            assert( Vec_IntSize(pVar->vParts) > 1 );
+            pVar->nScore -= pPart->nSize - nSizeNew;
+        }
+        else
+        {
+            RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart );
+            assert( RetValue );
+            pVar->nScore -= pPart->nSize;
+            if ( Vec_IntSize(pVar->vParts) == 0 )
+                Llb_Nonlin4RemoveVar( p, pVar );
+            else if ( Vec_IntSize(pVar->vParts) == 1 )
+                Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+        }
+
+    // update partition
+    pPart->nSize = nSizeNew;
+    Vec_IntClear( pPart->vVars );
+    for ( i = 0; i < p->nVars; i++ )
+        if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) )
+            Vec_IntPush( pPart->vVars, i );
+    // remove other variables
+    Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i )
+        Llb_Nonlin4Quantify1( p, pTemp );
+    Vec_PtrFree( vSingles );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Quantifies singles belonging to one partition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_Nonlin4Quantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 )
+{
+    int fVerbose = 0;
+    Llb_Var_t * pVar;
+    Llb_Prt_t * pTemp;
+    Vec_Ptr_t * vSingles;
+    DdNode * bCube, * bFunc;
+    int i, RetValue, nSuppSize;
+//    int iPart1 = pPart1->iPart;
+//    int iPart2 = pPart2->iPart;
+    int liveBeg, liveEnd;
+
+    // create cube to be quantified
+    bCube = Llb_Nonlin4CreateCube2( p, pPart1, pPart2 );   Cudd_Ref( bCube );
+
+//printf( "Quantifying  " ); Extra_bddPrintSupport( p->dd, bCube );  printf( "\n" );
+
+if ( fVerbose )
+{
+printf( "\n" );
+printf( "\n" );
+Llb_Nonlin4Print( p );
+printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart );
+Extra_bddPrintSupport( p->dd, bCube );  printf( "\n" );
+}
+liveBeg = p->dd->keys - p->dd->dead;
+    bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube );  
+liveEnd = p->dd->keys - p->dd->dead;
+//printf( "%d ", liveEnd-liveBeg );
+
+    if ( bFunc == NULL )
+    {
+        Cudd_RecursiveDeref( p->dd, bCube );
+        return 0;
+    }
+    Cudd_Ref( bFunc );
+    Cudd_RecursiveDeref( p->dd, bCube );
+
+//printf( "Creating part %d ", p->iPartFree ); Extra_bddPrintSupport( p->dd, bFunc );  printf( "\n" );
+
+//printf( "Creating %d\n", p->iPartFree );
+
+    // create new partition
+    pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 );
+    pTemp->iPart = p->iPartFree++;
+    pTemp->nSize = Cudd_DagSize(bFunc);
+    pTemp->bFunc = bFunc;
+    pTemp->vVars = Vec_IntAlloc( 8 );
+    // update variables
+    Llb_PartForEachVar( p, pPart1, pVar, i )
+    {
+        RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart );
+        assert( RetValue );
+        pVar->nScore -= pPart1->nSize;
+    }
+    // update variables
+    Llb_PartForEachVar( p, pPart2, pVar, i )
+    {
+        RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart );
+        assert( RetValue );
+        pVar->nScore -= pPart2->nSize;
+    }
+    // add variables to the new partition
+    nSuppSize = 0;
+    Extra_SupportArray( p->dd, bFunc, p->pSupp );
+    for ( i = 0; i < p->nVars; i++ )
+    {
+        nSuppSize += p->pSupp[i];
+        if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) )
+        {
+            pVar = Llb_MgrVar( p, i );
+            pVar->nScore += pTemp->nSize;
+            Vec_IntPush( pVar->vParts, pTemp->iPart );
+            Vec_IntPush( pTemp->vVars, i );
+        }
+    }
+    p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); 
+    // remove variables and collect partitions with singleton variables
+    vSingles = Vec_PtrAlloc( 0 );
+    Llb_PartForEachVar( p, pPart1, pVar, i )
+    {
+        if ( Vec_IntSize(pVar->vParts) == 0 )
+            Llb_Nonlin4RemoveVar( p, pVar );
+        else if ( Vec_IntSize(pVar->vParts) == 1 )
+        {
+            if ( fVerbose )
+                printf( "Adding partition %d because of var %d.\n", 
+                    Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar );
+            Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+        }
+    }
+    Llb_PartForEachVar( p, pPart2, pVar, i )
+    {
+        if ( pVar == NULL )
+            continue;
+        if ( Vec_IntSize(pVar->vParts) == 0 )
+            Llb_Nonlin4RemoveVar( p, pVar );
+        else if ( Vec_IntSize(pVar->vParts) == 1 )
+        {
+            if ( fVerbose )
+                printf( "Adding partition %d because of var %d.\n", 
+                    Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar );
+            Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+        }
+    }
+    // remove partitions
+    Llb_Nonlin4RemovePart( p, pPart1 );
+    Llb_Nonlin4RemovePart( p, pPart2 );
+    // remove other variables
+if ( fVerbose )
+Llb_Nonlin4Print( p );
+    Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i )
+    {
+if ( fVerbose )
+printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart );
+        Llb_Nonlin4Quantify1( p, pTemp );
+    }
+if ( fVerbose )
+Llb_Nonlin4Print( p );
+    Vec_PtrFree( vSingles );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes volume of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4CutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Saig_ObjIsLi(p, pObj) )
+    {
+        Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes);
+        return;
+    }
+    if ( Aig_ObjIsConst1(pObj) )
+        return;
+    assert( Aig_ObjIsNode(pObj) );
+    Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes);
+    Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes);
+    Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes volume of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4CutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i;
+    // mark the lower cut with the traversal ID
+    Aig_ManIncrementTravId(p);
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+        Aig_ObjSetTravIdCurrent( p, pObj );
+    // count the upper cut
+    vNodes = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+        Llb_Nonlin4CutNodes_rec( p, pObj, vNodes );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts non-linear quantification scheduling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4AddPair( Llb_Mgr_t * p, int iPart, int iVar )
+{
+    if ( p->pVars[iVar] == NULL )
+    {
+        p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 );
+        p->pVars[iVar]->iVar   = iVar;
+        p->pVars[iVar]->nScore = 0;
+        p->pVars[iVar]->vParts = Vec_IntAlloc( 8 );
+    }
+    Vec_IntPush( p->pVars[iVar]->vParts, iPart );
+    Vec_IntPush( p->pParts[iPart]->vVars, iVar );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts non-linear quantification scheduling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4AddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc )
+{
+    int k, nSuppSize;
+    assert( !Cudd_IsConstant(bFunc) );
+//printf( "Creating init %d\n", i );
+    // create partition
+    p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 );
+    p->pParts[i]->iPart = i;
+    p->pParts[i]->bFunc = bFunc;  Cudd_Ref( bFunc );
+    p->pParts[i]->vVars = Vec_IntAlloc( 8 );
+    // add support dependencies
+    nSuppSize = 0;
+    Extra_SupportArray( p->dd, bFunc, p->pSupp );
+    for ( k = 0; k < p->nVars; k++ )
+    {
+        nSuppSize += p->pSupp[k];
+        if ( p->pSupp[k] && Vec_IntEntry(p->vVars2Q, k) )
+            Llb_Nonlin4AddPair( p, i, k );
+    }
+    p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks that each var appears in at least one partition.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+**********************************************************************/
+void Llb_Nonlin4CheckVars( Llb_Mgr_t * p )
+{
+    Llb_Var_t * pVar;
+    int i;
+    Llb_MgrForEachVar( p, pVar, i )
+        assert( Vec_IntSize(pVar->vParts) > 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find next partition to quantify]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_Nonlin4NextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 )
+{
+    Llb_Var_t * pVar, * pVarBest = NULL;
+    Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL;
+    int i;
+    Llb_Nonlin4CheckVars( p );
+    // find variable with minimum score
+    Llb_MgrForEachVar( p, pVar, i )
+    {
+        if ( p->nSizeMax && pVar->nScore > p->nSizeMax )
+            continue;
+//        if ( pVarBest == NULL || Vec_IntSize(pVarBest->vParts) * pVarBest->nScore > Vec_IntSize(pVar->vParts) * pVar->nScore )
+        if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore )
+            pVarBest = pVar;
+//        printf( "%d ", pVar->nScore );
+    }
+//printf( "\n" );
+    if ( pVarBest == NULL )
+        return 0;
+    // find two partitions with minimum size
+    Llb_VarForEachPart( p, pVarBest, pPart, i )
+    {
+        if ( pPart1Best == NULL )
+            pPart1Best = pPart;
+        else if ( pPart2Best == NULL )
+            pPart2Best = pPart;
+        else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize )
+        {
+            if ( pPart1Best->nSize > pPart2Best->nSize )
+                pPart1Best = pPart;
+            else
+                pPart2Best = pPart;
+        }
+    }
+//printf( "Selecting %d and parts %d and %d\n", pVarBest->iVar, pPart1Best->nSize, pPart2Best->nSize );
+//Extra_bddPrintSupport( p->dd, pPart1Best->bFunc ); printf( "\n" );
+//Extra_bddPrintSupport( p->dd, pPart2Best->bFunc ); printf( "\n" );
+
+    *ppPart1 = pPart1Best;
+    *ppPart2 = pPart2Best;
+    return 1; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recomputes scores after variable reordering.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4RecomputeScores( Llb_Mgr_t * p )
+{
+    Llb_Prt_t * pPart;
+    Llb_Var_t * pVar;
+    int i, k;
+    Llb_MgrForEachPart( p, pPart, i )
+        pPart->nSize = Cudd_DagSize(pPart->bFunc);
+    Llb_MgrForEachVar( p, pVar, i )
+    {
+        pVar->nScore = 0;
+        Llb_VarForEachPart( p, pVar, pPart, k )
+            pVar->nScore += pPart->nSize;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recomputes scores after variable reordering.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4VerifyScores( Llb_Mgr_t * p )
+{
+    Llb_Prt_t * pPart;
+    Llb_Var_t * pVar;
+    int i, k, nScore;
+    Llb_MgrForEachPart( p, pPart, i )
+        assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) );
+    Llb_MgrForEachVar( p, pVar, i )
+    {
+        nScore = 0;
+        Llb_VarForEachPart( p, pVar, pPart, k )
+            nScore += pPart->nSize;
+        assert( nScore == pVar->nScore );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts non-linear quantification scheduling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Llb_Mgr_t * Llb_Nonlin4Alloc( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q, int nSizeMax )
+{
+    Llb_Mgr_t * p;
+    DdNode * bFunc;
+    int i;
+    p = ABC_CALLOC( Llb_Mgr_t, 1 );
+    p->dd        = dd;
+    p->nSizeMax  = nSizeMax;
+    p->vVars2Q   = vVars2Q;
+    p->nVars     = Cudd_ReadSize(dd);
+    p->iPartFree = Vec_PtrSize(vParts);
+    p->pVars     = ABC_CALLOC( Llb_Var_t *, p->nVars );
+    p->pParts    = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 );
+    p->pSupp     = ABC_ALLOC( int, Cudd_ReadSize(dd) );
+    // add pairs (refs are consumed inside)
+    Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i )
+        Llb_Nonlin4AddPartition( p, i, bFunc );
+    // add partition
+    if ( bCurrent )
+        Llb_Nonlin4AddPartition( p, p->iPartFree++, bCurrent );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops non-linear quantification scheduling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4Free( Llb_Mgr_t * p )
+{
+    Llb_Prt_t * pPart;
+    Llb_Var_t * pVar;
+    int i;
+    Llb_MgrForEachVar( p, pVar, i )
+        Llb_Nonlin4RemoveVar( p, pVar );
+    Llb_MgrForEachPart( p, pPart, i )
+        Llb_Nonlin4RemovePart( p, pPart );
+    ABC_FREE( p->pVars );
+    ABC_FREE( p->pParts );
+    ABC_FREE( p->pSupp );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q )
+{
+    Llb_Prt_t * pPart, * pPart1, * pPart2;
+    Llb_Mgr_t * p;
+    DdNode * bFunc, * bTemp;
+    int i, nReorders;
+    // start the manager
+    p = Llb_Nonlin4Alloc( dd, vParts, bCurrent, vVars2Q, 0 );
+    // remove singles
+    Llb_MgrForEachPart( p, pPart, i )
+        if ( Llb_Nonlin4HasSingletonVars(p, pPart) )
+            Llb_Nonlin4Quantify1( p, pPart );
+    // compute scores
+    Llb_Nonlin4RecomputeScores( p );
+    // iteratively quantify variables
+    while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) )
+    {
+        nReorders = Cudd_ReadReorderings(dd);
+        if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) )
+        {
+            Llb_Nonlin4Free( p );
+            return NULL;
+        }
+        if ( nReorders < Cudd_ReadReorderings(dd) )
+            Llb_Nonlin4RecomputeScores( p );
+//        else
+//            Llb_Nonlin4VerifyScores( p );
+    }
+    // load partitions
+    bFunc = Cudd_ReadOne(p->dd);   Cudd_Ref( bFunc );
+    Llb_MgrForEachPart( p, pPart, i )
+    {
+        bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc );   Cudd_Ref( bFunc );
+        Cudd_RecursiveDeref( p->dd, bTemp );
+    }
+//    nSuppMax = p->nSuppMax;
+    Llb_Nonlin4Free( p );
+//printf( "\n" );
+    // return
+    Cudd_Deref( bFunc );
+    return bFunc;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax )
+{
+    Vec_Ptr_t * vGroups;
+    Llb_Prt_t * pPart, * pPart1, * pPart2;
+    Llb_Mgr_t * p;
+    int i, nReorders;//, clk = Abc_Clock();
+    // start the manager
+    p = Llb_Nonlin4Alloc( dd, vParts, NULL, vVars2Q, nSizeMax );
+    // remove singles
+    Llb_MgrForEachPart( p, pPart, i )
+        if ( Llb_Nonlin4HasSingletonVars(p, pPart) )
+            Llb_Nonlin4Quantify1( p, pPart );
+    // compute scores
+    Llb_Nonlin4RecomputeScores( p );
+    // iteratively quantify variables
+    while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) )
+    {
+        nReorders = Cudd_ReadReorderings(dd);
+        if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) )
+        {
+            Llb_Nonlin4Free( p );
+            return NULL;
+        }
+        if ( nReorders < Cudd_ReadReorderings(dd) )
+            Llb_Nonlin4RecomputeScores( p );
+//        else
+//            Llb_Nonlin4VerifyScores( p );
+    }
+    // load partitions
+    vGroups = Vec_PtrAlloc( 1000 );
+    Llb_MgrForEachPart( p, pPart, i )
+    {
+//printf( "Iteration %d ", pPart->iPart );
+        if ( Cudd_IsConstant(pPart->bFunc) )
+        {
+//printf( "Constant\n" );
+            assert( !Cudd_IsComplement(pPart->bFunc) );
+            continue;
+        }
+//printf( "\n" );
+        Vec_PtrPush( vGroups, pPart->bFunc );
+        Cudd_Ref( pPart->bFunc );
+//printf( "Part %d  ", pPart->iPart );
+//Extra_bddPrintSupport( p->dd, pPart->bFunc ); printf( "\n" );
+    }
+    Llb_Nonlin4Free( p );
+//Abc_PrintTime( 1, "Reparametrization time", Abc_Clock() - clk );
+    return vGroups;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb4Map.c b/abc-build/src/proof/llb/llb4Map.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb4Map.c
@@ -0,0 +1,123 @@
+/**CFile****************************************************************
+
+  FileName    [llb2Map.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Non-linear quantification scheduling.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb2Map.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+#include "base/abc/abc.h"
+#include "map/if/if.h"
+
+ABC_NAMESPACE_IMPL_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns internal nodes used in the mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin )
+{
+    extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan );
+    extern If_Man_t *  Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
+    extern void        Gia_ManSetIfParsDefault( void * pPars );
+    If_Par_t Pars, * pPars = &Pars;
+    If_Man_t * pIfMan;
+    If_Obj_t * pAnd;
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pNode;
+    Vec_Int_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i;
+
+    // create ABC network
+    pNtk = Abc_NtkFromAigPhase( pAig );
+    assert( Abc_NtkIsStrash(pNtk) );
+
+    // derive mapping parameters
+    Gia_ManSetIfParsDefault( pPars );
+    pPars->nLutSize = nLutSize;
+
+    // get timing information
+    pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk);
+    pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk);
+
+    // perform LUT mapping
+    pIfMan = Abc_NtkToIf( pNtk, pPars );    
+    if ( pIfMan == NULL )
+    {
+        Abc_NtkDelete( pNtk );
+        return NULL;
+    }
+    if ( !If_ManPerformMapping( pIfMan ) )
+    {
+        Abc_NtkDelete( pNtk );
+        If_ManStop( pIfMan );
+        return NULL;
+    }
+
+    // mark nodes in the AIG used in the mapping
+    Aig_ManCleanMarkA( pAig );
+    Aig_ManForEachNode( pAig, pObj, i )
+    {
+        pNode = (Abc_Obj_t *)pObj->pData;
+        if ( pNode == NULL )
+            continue;
+        pAnd = (If_Obj_t *)pNode->pCopy;
+        if ( pAnd == NULL )
+            continue;
+        if ( pAnd->nRefs > 0 && (int)If_ObjCutBest(pAnd)->nLeaves >= nLutMin )
+            pObj->fMarkA = 1;
+    }
+    Abc_NtkDelete( pNtk );
+    If_ManStop( pIfMan );
+
+    // unmark flop drivers
+    Saig_ManForEachLi( pAig, pObj, i )
+        Aig_ObjFanin0(pObj)->fMarkA = 0;
+
+    // collect mapping
+    vNodes = Vec_IntAlloc( 100 );
+    Aig_ManForEachNode( pAig, pObj, i )
+        if ( pObj->fMarkA )
+            Vec_IntPush( vNodes, Aig_ObjId(pObj) );
+    Aig_ManCleanMarkA( pAig );
+    return vNodes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb4Nonlin.c b/abc-build/src/proof/llb/llb4Nonlin.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb4Nonlin.c
@@ -0,0 +1,1185 @@
+/**CFile****************************************************************
+
+  FileName    [llb2Nonlin.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Non-linear quantification scheduling.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+#include "base/abc/abc.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Mnx_t_ Llb_Mnx_t;
+struct Llb_Mnx_t_
+{
+    // user info
+    Aig_Man_t *     pAig;           // AIG manager
+    Gia_ParLlb_t *  pPars;          // parameters
+
+    // intermediate BDDs
+    DdManager *     dd;             // BDD manager
+    DdNode *        bBad;           // bad states in terms of CIs
+    DdNode *        bReached;       // reached states 
+    DdNode *        bCurrent;       // from states
+    DdNode *        bNext;          // to states
+    Vec_Ptr_t *     vRings;         // onion rings in ddR
+    Vec_Ptr_t *     vRoots;         // BDDs for partitions
+
+    // structural info
+    Vec_Int_t *     vOrder;         // for each object ID, its BDD variable number or -1
+    Vec_Int_t *     vVars2Q;        // 1 if variable is quantifiable; 0 othervise
+
+    abctime         timeImage;
+    abctime         timeRemap;
+    abctime         timeReo;
+    abctime         timeOther;
+    abctime         timeTotal;
+};
+
+//extern int timeBuild, timeAndEx, timeOther;
+//extern int nSuppMax;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    [Computes bad in working manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4ComputeBad( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder )
+{
+    Vec_Ptr_t * vNodes;
+    DdNode * bBdd, * bBdd0, * bBdd1, * bTemp, * bResult, * bCube;
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManCleanData( pAig );
+    // assign elementary variables
+    Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd); 
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+    // compute internal nodes
+    vNodes = Aig_ManDfsNodes( pAig, (Aig_Obj_t **)Vec_PtrArray(pAig->vCos), Saig_ManPoNum(pAig) );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        if ( !Aig_ObjIsNode(pObj) )
+            continue;
+        bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+        bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+        bBdd  = Cudd_bddAnd( dd, bBdd0, bBdd1 );
+        if ( bBdd == NULL )
+        {
+            Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+                if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL )
+                    Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+            Vec_PtrFree( vNodes );
+            return NULL;
+        }
+        Cudd_Ref( bBdd );
+        pObj->pData = bBdd;
+    }
+    // quantify PIs of each PO
+    bResult = Cudd_ReadLogicZero( dd );  Cudd_Ref( bResult );
+    Saig_ManForEachPo( pAig, pObj, i )
+    {
+        bBdd0   = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+        bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 );     
+        if ( bResult == NULL )
+        {
+            Cudd_RecursiveDeref( dd, bTemp );
+            break;
+        }
+        Cudd_Ref( bResult );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    // deref
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL )
+            Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+    Vec_PtrFree( vNodes );
+    if ( bResult )
+    {
+        bCube = Cudd_ReadOne(dd);  Cudd_Ref( bCube );
+        Saig_ManForEachPi( pAig, pObj, i )
+        {
+            bCube = Cudd_bddAnd( dd, bTemp = bCube, (DdNode *)pObj->pData );  
+            if ( bCube == NULL )
+            {
+                Cudd_RecursiveDeref( dd, bTemp );
+                Cudd_RecursiveDeref( dd, bResult );
+                bResult = NULL;
+                break;
+            }
+            Cudd_Ref( bCube );
+            Cudd_RecursiveDeref( dd, bTemp );
+        }
+        if ( bResult != NULL )
+        {
+            bResult = Cudd_bddExistAbstract( dd, bTemp = bResult, bCube );  Cudd_Ref( bResult );
+            Cudd_RecursiveDeref( dd, bTemp );
+            Cudd_RecursiveDeref( dd, bCube );
+            Cudd_Deref( bResult );
+        }
+    }
+//if ( bResult )
+//printf( "Bad state = %d.\n", Cudd_DagSize(bResult) );
+    return bResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives BDDs for the partitions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4DerivePartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder )
+{
+    Vec_Ptr_t * vRoots;
+    Aig_Obj_t * pObj;
+    DdNode * bBdd, * bBdd0, * bBdd1, * bPart;
+    int i;
+    Aig_ManCleanData( pAig );
+    // assign elementary variables
+    Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd); 
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+    Aig_ManForEachNode( pAig, pObj, i )
+        if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+        {
+            pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+            Cudd_Ref( (DdNode *)pObj->pData );
+        }
+    Saig_ManForEachLi( pAig, pObj, i )
+        pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+    // compute intermediate BDDs
+    vRoots = Vec_PtrAlloc( 100 );
+    Aig_ManForEachNode( pAig, pObj, i )
+    {
+        bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+        bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+        bBdd  = Cudd_bddAnd( dd, bBdd0, bBdd1 );
+        if ( bBdd == NULL )
+            goto finish;
+        Cudd_Ref( bBdd );
+        if ( pObj->pData == NULL )
+        {
+            pObj->pData = bBdd;
+            continue;
+        }
+        // create new partition
+        bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd );  
+        if ( bPart == NULL )
+            goto finish;
+        Cudd_Ref( bPart );
+        Cudd_RecursiveDeref( dd, bBdd );
+        Vec_PtrPush( vRoots, bPart );
+//printf( "%d ", Cudd_DagSize(bPart) );
+    }
+    // compute register output BDDs
+    Saig_ManForEachLi( pAig, pObj, i )
+    {
+        bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+        bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd0 );  
+        if ( bPart == NULL )
+            goto finish;
+        Cudd_Ref( bPart );
+        Vec_PtrPush( vRoots, bPart );
+//printf( "%d ", Cudd_DagSize(bPart) );
+    }
+//printf( "\n" );
+    Aig_ManForEachNode( pAig, pObj, i )
+        Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+    return vRoots;
+    // early termination
+finish:
+    Aig_ManForEachNode( pAig, pObj, i )
+        if ( pObj->pData )
+            Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+    Vec_PtrForEachEntry( DdNode *, vRoots, bPart, i )
+        Cudd_RecursiveDeref( dd, bPart );
+    Vec_PtrFree( vRoots );
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find simple variable ordering.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4CreateOrderSimple( Aig_Man_t * pAig )
+{
+    Vec_Int_t * vOrder;
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) );
+    Aig_ManForEachCi( pAig, pObj, i )
+        Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+    Saig_ManForEachLi( pAig, pObj, i )
+        Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+    return vOrder;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find good static variable ordering.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4CreateOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter )
+{
+    Aig_Obj_t * pFanin0, * pFanin1;
+    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent( pAig, pObj );
+    assert( Llb_ObjBddVar(vOrder, pObj) < 0 );
+    if ( Aig_ObjIsCi(pObj) )
+    {
+//        if ( Saig_ObjIsLo(pAig, pObj) )
+//            Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), (*pCounter)++ );
+        Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+        return;
+    }
+    // try fanins with higher level first
+    pFanin0 = Aig_ObjFanin0(pObj);
+    pFanin1 = Aig_ObjFanin1(pObj);
+//    if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) )
+    if ( pFanin0->Level > pFanin1->Level )
+    {
+        Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter );
+        Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter );
+    }
+    else
+    {
+        Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter );
+        Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter );
+    }
+    if ( pObj->fMarkA )
+        Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect nodes with the given fanout count.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4CollectHighRefNodes( Aig_Man_t * pAig, int nFans )
+{
+    Vec_Int_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManCleanMarkA( pAig );
+    Aig_ManForEachNode( pAig, pObj, i )
+        if ( Aig_ObjRefs(pObj) >= nFans )
+            pObj->fMarkA = 1;
+    // unmark flop drivers
+    Saig_ManForEachLi( pAig, pObj, i )
+        Aig_ObjFanin0(pObj)->fMarkA = 0;
+    // collect mapping
+    vNodes = Vec_IntAlloc( 100 );
+    Aig_ManForEachNode( pAig, pObj, i )
+        if ( pObj->fMarkA )
+            Vec_IntPush( vNodes, Aig_ObjId(pObj) );
+    Aig_ManCleanMarkA( pAig );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find good static variable ordering.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4CreateOrder( Aig_Man_t * pAig )
+{
+    Vec_Int_t * vNodes = NULL;
+    Vec_Int_t * vOrder;
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+/*
+    // mark internal nodes to be used
+    Aig_ManCleanMarkA( pAig );
+    vNodes = Llb_Nonlin4CollectHighRefNodes( pAig, 4 );
+    Aig_ManForEachObjVec( vNodes, pAig, pObj, i )
+        pObj->fMarkA = 1;
+printf( "Techmapping added %d pivots.\n", Vec_IntSize(vNodes) );
+*/
+    // collect nodes in the order
+    vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) );
+    Aig_ManIncrementTravId( pAig );
+    Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) );
+    Saig_ManForEachLi( pAig, pObj, i )
+    {
+        Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+        Llb_Nonlin4CreateOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter );
+    }
+    Aig_ManForEachCi( pAig, pObj, i )
+        if ( Llb_ObjBddVar(vOrder, pObj) < 0 )
+        {
+//            if ( Saig_ObjIsLo(pAig, pObj) )
+//                Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), Counter++ );
+            Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+        }
+    assert( Counter <= Aig_ManCiNum(pAig) + Aig_ManRegNum(pAig) + (vNodes?Vec_IntSize(vNodes):0) );
+    Aig_ManCleanMarkA( pAig );
+    Vec_IntFreeP( &vNodes );
+    return vOrder;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates quantifiable varaibles for both types of traversal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4CreateVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward )
+{
+    Vec_Int_t * vVars2Q;
+    Aig_Obj_t * pObjLi, * pObjLo;
+    int i;
+    vVars2Q = Vec_IntAlloc( 0 );
+    Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 );
+    Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+        Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, fBackward ? pObjLo : pObjLi), 0 );
+    return vVars2Q;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute initial state in terms of current state variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4SetupVarMap( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder )
+{
+    DdNode ** pVarsX, ** pVarsY;
+    Aig_Obj_t * pObjLo, * pObjLi;
+    int i;
+    pVarsX = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) );
+    pVarsY = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) );
+    Saig_ManForEachLiLo( pAig, pObjLo, pObjLi, i )
+    {
+        assert( Llb_ObjBddVar(vOrder, pObjLo) >= 0 );
+        assert( Llb_ObjBddVar(vOrder, pObjLi) >= 0 );
+        pVarsX[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLo) );
+        pVarsY[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) );
+    }
+    Cudd_SetVarMap( dd, pVarsX, pVarsY, Aig_ManRegNum(pAig) );
+    ABC_FREE( pVarsX );
+    ABC_FREE( pVarsY );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute initial state in terms of current state variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4ComputeInitState( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward )
+{
+    Aig_Obj_t * pObjLi, * pObjLo;
+    DdNode * bRes, * bVar, * bTemp;
+    int i;
+    abctime TimeStop;
+    TimeStop = dd->TimeStop;  dd->TimeStop = 0;
+    bRes = Cudd_ReadOne( dd );   Cudd_Ref( bRes );
+    Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+    {
+        bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo) );
+        bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) );  Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    Cudd_Deref( bRes );
+    dd->TimeStop = TimeStop;
+    return bRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute initial state in terms of current state variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4ComputeCube( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, char * pValues, int Flag )
+{
+    Aig_Obj_t * pObjLo, * pObjLi, * pObjTemp;
+    DdNode * bRes, * bVar, * bTemp;
+    int i;
+    abctime TimeStop;
+    TimeStop = dd->TimeStop;  dd->TimeStop = 0;
+    bRes = Cudd_ReadOne( dd );   Cudd_Ref( bRes );
+    Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+    {
+        if ( Flag )
+            pObjTemp = pObjLo, pObjLo = pObjLi, pObjLi = pObjTemp;
+        // get the correspoding flop input variable
+        bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) );
+        if ( pValues[Llb_ObjBddVar(vOrder, pObjLo)] != 1 )
+            bVar = Cudd_Not(bVar);
+        // create cube
+        bRes = Cudd_bddAnd( dd, bTemp = bRes, bVar );  Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    Cudd_Deref( bRes );
+    dd->TimeStop = TimeStop;
+    return bRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute initial state in terms of current state variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4RecordState( Aig_Man_t * pAig, Vec_Int_t * vOrder, unsigned * pState, char * pValues, int fBackward )
+{
+    Aig_Obj_t * pObjLo, * pObjLi;
+    int i;
+    Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+        if ( pValues[Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo)] == 1 )
+            Abc_InfoSetBit( pState, i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Multiply every partition by the cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4Multiply( DdManager * dd, DdNode * bCube, Vec_Ptr_t * vParts )
+{
+    Vec_Ptr_t * vNew;
+    DdNode * bTemp, * bFunc;
+    int i;
+    vNew = Vec_PtrAlloc( Vec_PtrSize(vParts) );
+    Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i )
+    {
+        bTemp = Cudd_bddAnd( dd, bFunc, bCube );  Cudd_Ref( bTemp );
+        Vec_PtrPush( vNew, bTemp );
+    }
+    return vNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Multiply every partition by the cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4Deref( DdManager * dd, Vec_Ptr_t * vParts )
+{
+    DdNode * bFunc;
+    int i;
+    Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i )
+        Cudd_RecursiveDeref( dd, bFunc );
+    Vec_PtrFree( vParts );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives counter-example by backward reachability.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4DeriveCex( Llb_Mnx_t * p, int fBackward, int fVerbose )
+{
+    Vec_Int_t * vVars2Q;
+    Vec_Ptr_t * vStates, * vRootsNew;
+    Aig_Obj_t * pObj;
+    DdNode * bState = NULL, * bImage, * bOneCube, * bRing;
+    int i, v, RetValue;//, clk = Abc_Clock();
+    char * pValues;
+    assert( Vec_PtrSize(p->vRings) > 0 );
+    // disable the timeout
+    p->dd->TimeStop  = 0;
+
+    // start the state set
+    vStates = Vec_PtrAllocSimInfo( Vec_PtrSize(p->vRings), Abc_BitWordNum(Aig_ManRegNum(p->pAig)) );
+    Vec_PtrCleanSimInfo( vStates, 0, Abc_BitWordNum(Aig_ManRegNum(p->pAig)) );
+    if ( fBackward )
+        Vec_PtrReverseOrder( vStates );
+
+    // get the last cube
+    pValues = ABC_ALLOC( char, Cudd_ReadSize(p->dd) );
+    bOneCube = Cudd_bddIntersect( p->dd, (DdNode *)Vec_PtrEntryLast(p->vRings), p->bBad );  Cudd_Ref( bOneCube );
+    RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues );
+    Cudd_RecursiveDeref( p->dd, bOneCube );
+    assert( RetValue );
+
+    // record the cube
+    Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntryLast(vStates), pValues, fBackward );
+
+    // write state in terms of NS variables
+    if ( Vec_PtrSize(p->vRings) > 1 )
+    {
+        bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward );   Cudd_Ref( bState );
+    }
+    // perform backward analysis
+    vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, p->pAig, p->vOrder, !fBackward );
+    Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v )
+    { 
+        if ( v == Vec_PtrSize(p->vRings) - 1 )
+            continue;
+
+        // preprocess partitions
+        vRootsNew = Llb_Nonlin4Multiply( p->dd, bState, p->vRoots );
+        Cudd_RecursiveDeref( p->dd, bState );
+
+        // compute the next states
+        bImage = Llb_Nonlin4Image( p->dd, vRootsNew, NULL, vVars2Q ); Cudd_Ref( bImage );
+        Llb_Nonlin4Deref( p->dd, vRootsNew );
+
+        // intersect with the previous set
+        bOneCube = Cudd_bddIntersect( p->dd, bImage, bRing );  Cudd_Ref( bOneCube );
+        Cudd_RecursiveDeref( p->dd, bImage );
+
+        // find any assignment of the BDD
+        RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues );
+        Cudd_RecursiveDeref( p->dd, bOneCube );
+        assert( RetValue );
+
+        // record the cube
+        Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntry(vStates, v), pValues, fBackward );
+
+        // check that we get the init state
+        if ( v == 0 )
+        {
+            Saig_ManForEachLo( p->pAig, pObj, i )
+                assert( fBackward || pValues[Llb_ObjBddVar(p->vOrder, pObj)] == 0 );
+            break;
+        } 
+
+        // write state in terms of NS variables
+        bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward );   Cudd_Ref( bState );
+    }
+    Vec_IntFree( vVars2Q );
+    ABC_FREE( pValues );
+    if ( fBackward )
+        Vec_PtrReverseOrder( vStates );
+//    if ( fVerbose )
+//        Abc_PrintTime( 1, "BDD-based cex generation time", Abc_Clock() - clk );
+    return vStates;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Perform reachability with hints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_Nonlin4Reachability( Llb_Mnx_t * p )
+{ 
+    DdNode * bAux;
+    int nIters, nBddSizeFr = 0, nBddSizeTo = 0, nBddSizeTo2 = 0;
+    abctime clkTemp, clkIter, clk = Abc_Clock();
+    assert( Aig_ManRegNum(p->pAig) > 0 );
+
+    if ( p->pPars->fBackward )
+    {
+        // create bad state in the ring manager
+        if ( !p->pPars->fSkipOutCheck )
+        {
+            p->bBad = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward );  Cudd_Ref( p->bBad );
+        }
+        // create init state
+        if ( p->pPars->fCluster )
+            p->bCurrent = p->dd->bFunc, p->dd->bFunc = NULL; 
+        else
+        {
+            p->bCurrent = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder );          
+            if ( p->bCurrent == NULL )
+            {
+                if ( !p->pPars->fSilent )
+                    printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+                p->pPars->iFrame = -1;
+                return -1;
+            }
+            Cudd_Ref( p->bCurrent );
+        }
+        // remap into the next states
+        p->bCurrent = Cudd_bddVarMap( p->dd, bAux = p->bCurrent );
+        if ( p->bCurrent == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during remapping bad states.\n",  p->pPars->TimeLimit );
+            Cudd_RecursiveDeref( p->dd, bAux );
+            p->pPars->iFrame = -1;
+            return -1;
+        }
+        Cudd_Ref( p->bCurrent );
+        Cudd_RecursiveDeref( p->dd, bAux );
+    }
+    else
+    {
+        // create bad state in the ring manager
+        if ( !p->pPars->fSkipOutCheck )
+        {
+            if ( p->pPars->fCluster )
+                p->bBad = p->dd->bFunc, p->dd->bFunc = NULL; 
+            else
+            {
+                p->bBad = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder );          
+                if ( p->bBad == NULL )
+                {
+                    if ( !p->pPars->fSilent )
+                        printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+                    p->pPars->iFrame = -1;
+                    return -1;
+                }
+                Cudd_Ref( p->bBad );
+            }
+        }
+        else if ( p->dd->bFunc )
+            Cudd_RecursiveDeref( p->dd, p->dd->bFunc ), p->dd->bFunc = NULL;
+        // compute the starting set of states
+        p->bCurrent = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward );  Cudd_Ref( p->bCurrent );
+    }
+    // perform iterations
+    p->bReached = p->bCurrent; Cudd_Ref( p->bReached );
+    for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ )
+    { 
+        clkIter = Abc_Clock();
+        // check the runtime limit
+        if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            return -1;
+        }
+
+        // save the onion ring
+        Vec_PtrPush( p->vRings, p->bCurrent );   Cudd_Ref( p->bCurrent );
+
+        // check it for bad states
+        if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->dd, p->bCurrent, Cudd_Not(p->bBad) ) ) 
+        {
+            Vec_Ptr_t * vStates;
+            assert( p->pAig->pSeqModel == NULL );
+            vStates = Llb_Nonlin4DeriveCex( p, p->pPars->fBackward, p->pPars->fVerbose ); 
+            p->pAig->pSeqModel = Llb4_Nonlin4TransformCex( p->pAig, vStates, -1, p->pPars->fVerbose );
+            Vec_PtrFreeP( &vStates );
+            if ( !p->pPars->fSilent )
+            {
+                Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.  ", p->pAig->pSeqModel->iPo, p->pAig->pName, nIters );
+                Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+            }
+            p->pPars->iFrame = nIters - 1;
+            return 0;
+        }
+
+        // compute the next states
+        clkTemp = Abc_Clock();
+        p->bNext = Llb_Nonlin4Image( p->dd, p->vRoots, p->bCurrent, p->vVars2Q );
+        if ( p->bNext == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation in quantification.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            return -1;
+        }
+        Cudd_Ref( p->bNext );
+        p->timeImage += Abc_Clock() - clkTemp;
+
+        // remap into current states
+        clkTemp = Abc_Clock();
+        p->bNext = Cudd_bddVarMap( p->dd, bAux = p->bNext );
+        if ( p->bNext == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during remapping next states.\n",  p->pPars->TimeLimit );
+            Cudd_RecursiveDeref( p->dd, bAux );
+            p->pPars->iFrame = nIters - 1;
+            return -1;
+        }
+        Cudd_Ref( p->bNext );
+        Cudd_RecursiveDeref( p->dd, bAux );
+        p->timeRemap += Abc_Clock() - clkTemp;
+
+        // collect statistics
+        if ( p->pPars->fVerbose )
+        {
+            nBddSizeFr  = Cudd_DagSize( p->bCurrent );
+            nBddSizeTo  = Cudd_DagSize( bAux );
+            nBddSizeTo2 = Cudd_DagSize( p->bNext );
+        }
+        Cudd_RecursiveDeref( p->dd, p->bCurrent ); p->bCurrent = NULL;
+
+        // derive new states
+        p->bCurrent = Cudd_bddAnd( p->dd, p->bNext, Cudd_Not(p->bReached) );     
+        if ( p->bCurrent == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            return -1;
+        }
+        Cudd_Ref( p->bCurrent );
+        Cudd_RecursiveDeref( p->dd, p->bNext ); p->bNext = NULL;
+        if ( Cudd_IsConstant(p->bCurrent) )
+            break;
+/*
+        // reduce BDD size using constrain // Cudd_bddRestrict
+        p->bCurrent = Cudd_bddRestrict( p->dd, bAux = p->bCurrent, Cudd_Not(p->bReached) );   
+        Cudd_Ref( p->bCurrent );
+printf( "Before = %d.  After = %d.\n", Cudd_DagSize(bAux), Cudd_DagSize(p->bCurrent) );
+        Cudd_RecursiveDeref( p->dd, bAux );
+*/
+
+        // add to the reached set
+        p->bReached = Cudd_bddOr( p->dd, bAux = p->bReached, p->bCurrent );                 
+        if ( p->bReached == NULL )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n",  p->pPars->TimeLimit );
+            p->pPars->iFrame = nIters - 1;
+            Cudd_RecursiveDeref( p->dd, bAux );  
+            return -1;
+        }
+        Cudd_Ref( p->bReached );
+        Cudd_RecursiveDeref( p->dd, bAux );  
+
+
+        // report the results
+        if ( p->pPars->fVerbose )
+        {
+            printf( "I =%5d : ",   nIters );
+            printf( "Fr =%7d  ",   nBddSizeFr );
+            printf( "ImNs =%7d  ", nBddSizeTo );
+            printf( "ImCs =%7d  ", nBddSizeTo2 );
+            printf( "Rea =%7d   ", Cudd_DagSize(p->bReached) );
+            printf( "(%4d %4d)  ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) );
+            Abc_PrintTime( 1, "T", Abc_Clock() - clkIter );
+        }
+/*
+        if ( pPars->fVerbose )
+        {
+            double nMints = Cudd_CountMinterm(p->dd, bReached, Saig_ManRegNum(p->pAig) );
+//            Extra_bddPrint( p->dd, bReached );printf( "\n" );
+            printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+            fflush( stdout ); 
+        }
+*/
+        if ( nIters == p->pPars->nIterMax - 1 )
+        {
+            if ( !p->pPars->fSilent )
+                printf( "Reached limit on the number of timeframes (%d).\n",  p->pPars->nIterMax );
+            p->pPars->iFrame = nIters;
+            return -1;
+        }
+    }
+    
+    // report the stats
+    if ( p->pPars->fVerbose )
+    {
+        double nMints = Cudd_CountMinterm(p->dd, p->bReached, Saig_ManRegNum(p->pAig) );
+        if ( p->bCurrent && Cudd_IsConstant(p->bCurrent) )
+            printf( "Reachability analysis completed after %d frames.\n", nIters );
+        else
+            printf( "Reachability analysis is stopped after %d frames.\n", nIters );
+        printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+        fflush( stdout ); 
+    }
+    if ( p->bCurrent == NULL || !Cudd_IsConstant(p->bCurrent) )
+    {
+        if ( !p->pPars->fSilent )
+            printf( "Verified only for states reachable in %d frames.  ", nIters );
+        p->pPars->iFrame = p->pPars->nIterMax;
+        return -1; // undecided
+    }
+    // report
+    if ( !p->pPars->fSilent )
+        printf( "The miter is proved unreachable after %d iterations.  ", nIters );
+    if ( !p->pPars->fSilent )
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    p->pPars->iFrame = nIters - 1;
+    return 1; // unreachable
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reorders BDDs in the working manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4Reorder( DdManager * dd, int fTwice, int fVerbose )
+{
+    abctime clk = Abc_Clock();
+    if ( fVerbose )
+        Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+    Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+    if ( fVerbose )
+        Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+    if ( fTwice )
+    {
+        Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+        if ( fVerbose )
+            Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+    }
+    if ( fVerbose )
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Llb_Mnx_t * Llb_MnxStart( Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+    Llb_Mnx_t * p;
+
+    p = ABC_CALLOC( Llb_Mnx_t, 1 );
+    p->pAig    = pAig;
+    p->pPars   = pPars;
+
+    // compute time to stop
+    p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0;
+
+    if ( pPars->fCluster )
+    {
+//        Llb_Nonlin4Cluster( p->pAig, &p->dd, &p->vOrder, &p->vRoots, pPars->nBddMax, pPars->fVerbose );
+//        Cudd_AutodynEnable( p->dd,  CUDD_REORDER_SYMM_SIFT );
+        Llb4_Nonlin4Sweep( p->pAig, pPars->nBddMax, pPars->nClusterMax, &p->dd, &p->vOrder, &p->vRoots, pPars->fVerbose );
+		// set the stop time parameter
+		p->dd->TimeStop  = p->pPars->TimeTarget;
+    }
+    else
+    {
+//    p->vOrder  = Llb_Nonlin4CreateOrderSimple( pAig );
+        p->vOrder  = Llb_Nonlin4CreateOrder( pAig );
+        p->dd      = Cudd_Init( Vec_IntCountPositive(p->vOrder) + 1, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+        Cudd_AutodynEnable( p->dd,  CUDD_REORDER_SYMM_SIFT );
+        Cudd_SetMaxGrowth( p->dd, 1.05 );
+		// set the stop time parameter
+		p->dd->TimeStop  = p->pPars->TimeTarget;
+        p->vRoots  = Llb_Nonlin4DerivePartitions( p->dd, pAig, p->vOrder );
+    }
+
+    Llb_Nonlin4SetupVarMap( p->dd, pAig, p->vOrder );
+    p->vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, pAig, p->vOrder, p->pPars->fBackward );
+    p->vRings  = Vec_PtrAlloc( 100 );
+
+    if ( pPars->fReorder )
+        Llb_Nonlin4Reorder( p->dd, 0, 1 );
+    return p;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_MnxStop( Llb_Mnx_t * p )
+{
+    DdNode * bTemp;
+    int i;
+    if ( p->pPars->fVerbose ) 
+    {
+        p->timeReo = Cudd_ReadReorderingTime(p->dd);
+        p->timeOther = p->timeTotal - p->timeImage - p->timeRemap;
+        ABC_PRTP( "Image    ", p->timeImage, p->timeTotal );
+        ABC_PRTP( "Remap    ", p->timeRemap, p->timeTotal );
+        ABC_PRTP( "Other    ", p->timeOther, p->timeTotal );
+        ABC_PRTP( "TOTAL    ", p->timeTotal, p->timeTotal );
+        ABC_PRTP( "  reo    ", p->timeReo,   p->timeTotal );
+    }
+    // remove BDDs
+    if ( p->bBad )
+        Cudd_RecursiveDeref( p->dd, p->bBad );
+    if ( p->bReached )
+        Cudd_RecursiveDeref( p->dd, p->bReached );
+    if ( p->bCurrent )
+        Cudd_RecursiveDeref( p->dd, p->bCurrent );
+    if ( p->bNext )
+        Cudd_RecursiveDeref( p->dd, p->bNext );
+	if ( p->vRings )
+    Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i )
+        Cudd_RecursiveDeref( p->dd, bTemp );
+	if ( p->vRoots )
+    Vec_PtrForEachEntry( DdNode *, p->vRoots, bTemp, i )
+        Cudd_RecursiveDeref( p->dd, bTemp );
+    // remove arrays
+    Vec_PtrFreeP( &p->vRings );
+    Vec_PtrFreeP( &p->vRoots );
+//Cudd_PrintInfo( p->dd, stdout );
+    Extra_StopManager( p->dd );
+    Vec_IntFreeP( &p->vOrder );
+    Vec_IntFreeP( &p->vVars2Q );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_MnxCheckNextStateVars( Llb_Mnx_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter0 = 0, Counter1 = 0;
+    Saig_ManForEachLi( p->pAig, pObj, i )
+        if ( Saig_ObjIsLo(p->pAig, Aig_ObjFanin0(pObj)) )
+        {
+            if ( Aig_ObjFaninC0(pObj) )
+                Counter0++;
+            else
+                Counter1++;
+        }
+    printf( "Total = %d.  Direct LO = %d. Compl LO = %d.\n", Aig_ManRegNum(p->pAig), Counter1, Counter0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds balanced cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+    Llb_Mnx_t * pMnn;
+    int RetValue = -1;
+    if ( pPars->fVerbose )
+    Aig_ManPrintStats( pAig );
+    if ( pPars->fCluster && Aig_ManObjNum(pAig) >= (1 << 15) )
+    {
+        printf( "The number of objects is more than 2^15.  Clustering cannot be used.\n" );
+        return RetValue;
+    }
+    {
+        abctime clk = Abc_Clock();
+        pMnn = Llb_MnxStart( pAig, pPars );
+//Llb_MnxCheckNextStateVars( pMnn );
+        if ( !pPars->fSkipReach )
+            RetValue = Llb_Nonlin4Reachability( pMnn );
+        pMnn->timeTotal = Abc_Clock() - clk;
+        Llb_MnxStop( pMnn );
+    }
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Takes an AIG and returns an AIG representing reachable states.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Llb_ReachableStates( Aig_Man_t * pAig )
+{
+    extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+    Vec_Int_t * vPermute;
+    Vec_Ptr_t * vNames;
+    Gia_ParLlb_t Pars, * pPars = &Pars;
+    DdManager * dd;
+    DdNode * bReached;
+    Llb_Mnx_t * pMnn;
+    Abc_Ntk_t * pNtk, * pNtkMuxes;
+    Aig_Obj_t * pObj;
+    int i, RetValue;
+    abctime clk = Abc_Clock();
+
+    // create parameters
+    Llb_ManSetDefaultParams( pPars );
+    pPars->fSkipOutCheck = 1;
+    pPars->fCluster      = 0;
+    pPars->fReorder      = 0;
+    pPars->fSilent       = 1;
+    pPars->nBddMax       = 100;
+    pPars->nClusterMax   = 500;
+
+    // run reachability
+    pMnn = Llb_MnxStart( pAig, pPars );
+    RetValue = Llb_Nonlin4Reachability( pMnn );
+    assert( RetValue == 1 );
+
+    // print BDD
+//    Extra_bddPrint( pMnn->dd, pMnn->bReached ); 
+//    Extra_bddPrintSupport( pMnn->dd, pMnn->bReached ); 
+//    printf( "\n" );
+
+    // collect flop output variables
+    vPermute = Vec_IntStartFull( Cudd_ReadSize(pMnn->dd) );
+    Saig_ManForEachLo( pAig, pObj, i )
+        Vec_IntWriteEntry( vPermute, Llb_ObjBddVar(pMnn->vOrder, pObj), i );
+
+    // transfer the reached state BDD into the new manager
+    dd = Cudd_Init( Saig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    Cudd_AutodynEnable( dd,  CUDD_REORDER_SYMM_SIFT );
+    bReached = Extra_TransferPermute( pMnn->dd, dd, pMnn->bReached, Vec_IntArray(vPermute) );  Cudd_Ref( bReached );
+    Vec_IntFree( vPermute );
+    assert( Cudd_ReadSize(dd) == Saig_ManRegNum(pAig) );
+
+    // quit reachability engine
+    pMnn->timeTotal = Abc_Clock() - clk;
+    Llb_MnxStop( pMnn );
+
+    // derive the network
+    vNames = Abc_NodeGetFakeNames( Saig_ManRegNum(pAig) );
+    pNtk = Abc_NtkDeriveFromBdd( dd, bReached, "reached", vNames );
+    Abc_NodeFreeNames( vNames );
+    Cudd_RecursiveDeref( dd, bReached );
+    Cudd_Quit( dd );
+
+    // convert
+    pNtkMuxes = Abc_NtkBddToMuxes( pNtk );
+    Abc_NtkDelete( pNtk );
+    pNtk = Abc_NtkStrash( pNtkMuxes, 0, 1, 0 );
+    Abc_NtkDelete( pNtkMuxes );
+    pAig = Abc_NtkToDar( pNtk, 0, 0 );
+    Abc_NtkDelete( pNtk );
+    return pAig;
+}
+Gia_Man_t * Llb_ReachableStatesGia( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Aig_Man_t * pAig, * pReached;
+    pAig = Gia_ManToAigSimple( p );
+    pReached = Llb_ReachableStates( pAig );
+    Aig_ManStop( pAig );
+    pNew = Gia_ManFromAigSimple( pReached );
+    Aig_ManStop( pReached );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llb4Sweep.c b/abc-build/src/proof/llb/llb4Sweep.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llb4Sweep.c
@@ -0,0 +1,589 @@
+/**CFile****************************************************************
+
+  FileName    [llb2Sweep.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD based reachability.]
+
+  Synopsis    [Non-linear quantification scheduling.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: llb2Sweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Find good static variable ordering.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4SweepOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter, int fSaveAll )
+{
+    Aig_Obj_t * pFanin0, * pFanin1;
+    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent( pAig, pObj );
+    assert( Llb_ObjBddVar(vOrder, pObj) < 0 );
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+        return;
+    }
+    // try fanins with higher level first
+    pFanin0 = Aig_ObjFanin0(pObj);
+    pFanin1 = Aig_ObjFanin1(pObj);
+//    if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) )
+    if ( pFanin0->Level > pFanin1->Level )
+    {
+        Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll );
+        Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll );
+    }
+    else
+    {
+        Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll );
+        Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll );
+    }
+    if ( fSaveAll || pObj->fMarkA )
+        Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Find good static variable ordering.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4SweepOrder( Aig_Man_t * pAig, int * pCounter, int fSaveAll )
+{
+    Vec_Int_t * vOrder;
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    // collect nodes in the order
+    vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) );
+    Aig_ManIncrementTravId( pAig );
+    Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) );
+    Aig_ManForEachCo( pAig, pObj, i )
+    {
+        Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+        Llb_Nonlin4SweepOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter, fSaveAll );
+    }
+    Aig_ManForEachCi( pAig, pObj, i )
+        if ( Llb_ObjBddVar(vOrder, pObj) < 0 )
+            Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+//    assert( Counter == Aig_ManObjNum(pAig) - 1 ); // no dangling nodes
+    if ( pCounter )
+        *pCounter = Counter - Aig_ManCiNum(pAig) - Aig_ManCoNum(pAig);
+    return vOrder;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD sweep on the netlist.]
+
+  Description [Returns AIG with internal cut points labeled with fMarkA.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Llb4_Nonlin4SweepCutpoints( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nBddLimit, int fVerbose )
+{
+    DdManager * dd;
+    DdNode * bFunc0, * bFunc1, * bFunc;
+    Aig_Obj_t * pObj;
+    int i, Counter = 0, Counter1 = 0;
+    dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    // assign elementary variables
+    Aig_ManCleanData( pAig );
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+    // sweep internal nodes
+    Aig_ManForEachNode( pAig, pObj, i )
+    {
+/*
+        if ( pObj->nRefs >= 4 )
+        {
+            bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );  Cudd_Ref( bFunc );
+            pObj->pData = bFunc;
+            Counter1++;
+            continue;
+        }
+*/
+        bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+        bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+        bFunc  = Cudd_bddAnd( dd, bFunc0, bFunc1 );  Cudd_Ref( bFunc );
+        if ( Cudd_DagSize(bFunc) > nBddLimit )
+        {
+//            if ( fVerbose )
+//                printf( "Node %5d : Beg =%5d. ", i, Cudd_DagSize(bFunc) );
+
+            // add cutpoint at a larger one
+            Cudd_RecursiveDeref( dd, bFunc );
+            if ( Cudd_DagSize(bFunc0) >= Cudd_DagSize(bFunc1) )
+            {
+                Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin0(pObj)->pData );
+                bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin0(pObj)) );
+                Aig_ObjFanin0(pObj)->pData = bFunc;  Cudd_Ref( bFunc );
+                Aig_ObjFanin0(pObj)->fMarkA = 1;
+
+//                if ( fVerbose )
+//                    printf( "Ref =%3d  ", Aig_ObjFanin0(pObj)->nRefs );
+            }
+            else
+            {
+                Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin1(pObj)->pData );
+                bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin1(pObj)) );
+                Aig_ObjFanin1(pObj)->pData = bFunc;  Cudd_Ref( bFunc );
+                Aig_ObjFanin1(pObj)->fMarkA = 1;
+
+//                if ( fVerbose )
+//                    printf( "Ref =%3d  ", Aig_ObjFanin1(pObj)->nRefs );
+            }
+            // perform new operation
+            bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+            bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+            bFunc  = Cudd_bddAnd( dd, bFunc0, bFunc1 );  Cudd_Ref( bFunc );
+//            assert( Cudd_DagSize(bFunc) <= nBddLimit );
+
+//            if ( fVerbose )
+//                printf( "End =%5d.\n", Cudd_DagSize(bFunc) );
+            Counter++;
+        }
+        pObj->pData = bFunc;
+//printf( "%d ", Cudd_DagSize(bFunc) );
+    }
+//printf( "\n" );
+    // clean up
+    Aig_ManForEachNode( pAig, pObj, i )
+        Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+    Extra_StopManager( dd );
+//    Aig_ManCleanMarkA( pAig );
+    if ( fVerbose )
+    printf( "Added %d cut points.  Used %d high fanout points.\n", Counter, Counter1 );
+    return Counter + Counter1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives BDDs for the partitions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4SweepPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots )
+{
+    DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar;
+    if ( Aig_ObjIsConst1(pObj) )
+        return Cudd_ReadOne(dd); 
+    if ( Aig_ObjIsCi(pObj) )
+        return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+    if ( pObj->pData )
+        return (DdNode *)pObj->pData;
+    if ( Aig_ObjIsCo(pObj) )
+    {
+        bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) );
+        bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 );  Cudd_Ref( bPart );
+        Vec_PtrPush( vRoots, bPart );
+        return NULL;
+    }
+    bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) );
+    bBdd1 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) );
+    bBdd  = Cudd_bddAnd( dd, bBdd0, bBdd1 );   Cudd_Ref( bBdd );
+    if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+    {
+        vVar  = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+        bPart = Cudd_bddXnor( dd, vVar, bBdd );  Cudd_Ref( bPart );
+        Vec_PtrPush( vRoots, bPart );
+        Cudd_RecursiveDeref( dd, bBdd );
+        bBdd = vVar;  Cudd_Ref( vVar );
+    }
+    pObj->pData = bBdd;
+    return bBdd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives BDDs for the partitions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4SweepPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fTransition )
+{
+    Vec_Ptr_t * vRoots;
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManCleanData( pAig );
+    vRoots = Vec_PtrAlloc( 100 );
+    if ( fTransition )
+    {
+        Saig_ManForEachLi( pAig, pObj, i )
+            Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots );
+    }
+    else
+    {
+        Saig_ManForEachPo( pAig, pObj, i )
+            Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots );
+    }
+    Aig_ManForEachNode( pAig, pObj, i )
+        if ( pObj->pData )
+            Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+    return vRoots;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Get bad state monitor.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdNode * Llb4_Nonlin4SweepBadMonitor( Aig_Man_t * pAig, Vec_Int_t * vOrder, DdManager * dd )
+{
+    Aig_Obj_t * pObj;
+    DdNode * bRes, * bVar, * bTemp;
+    int i;
+    abctime TimeStop;
+    TimeStop = dd->TimeStop;  dd->TimeStop = 0;
+    bRes = Cudd_ReadOne( dd );   Cudd_Ref( bRes );
+    Saig_ManForEachPo( pAig, pObj, i )
+    {
+        bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+        bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) );  Cudd_Ref( bRes );
+        Cudd_RecursiveDeref( dd, bTemp );
+    }
+    Cudd_Deref( bRes );
+    dd->TimeStop = TimeStop;
+    return Cudd_Not(bRes);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates quantifiable variables for both types of traversal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4SweepVars2Q( Aig_Man_t * pAig, Vec_Int_t * vOrder, int fAddLis )
+{
+    Vec_Int_t * vVars2Q;
+    Aig_Obj_t * pObj;
+    int i;
+    vVars2Q = Vec_IntAlloc( 0 );
+    Vec_IntFill( vVars2Q, Aig_ManObjNumMax(pAig), 1 );
+    // add flop outputs
+    Saig_ManForEachLo( pAig, pObj, i )
+        Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 );
+    // add flop inputs
+    if ( fAddLis )
+    Saig_ManForEachLi( pAig, pObj, i )
+        Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 );
+    return vVars2Q;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Multiply every partition by the cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4SweepDeref( DdManager * dd, Vec_Ptr_t * vParts )
+{
+    DdNode * bFunc;
+    int i;
+    Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i )
+        Cudd_RecursiveDeref( dd, bFunc );
+    Vec_PtrFree( vParts );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Multiply every partition by the cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4SweepPrint( Vec_Ptr_t * vFuncs )
+{
+    DdNode * bFunc;
+    int i;
+    printf( "(%d) ", Vec_PtrSize(vFuncs) );
+    Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i )
+        printf( "%d ", Cudd_DagSize(bFunc) );
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes bad states.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdManager * Llb4_Nonlin4SweepBadStates( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars )
+{
+    DdManager * dd;
+    Vec_Ptr_t * vParts;
+    Vec_Int_t * vVars2Q;
+    DdNode * bMonitor, * bImage;
+    // get quantifiable variables
+    vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 0 );
+    // start BDD manager and create partitions 
+    dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 0 );
+//printf( "Outputs: " );
+//Llb_Nonlin4SweepPrint( vParts );
+    // compute image of the partitions
+    bMonitor = Llb4_Nonlin4SweepBadMonitor( pAig, vOrder, dd );  Cudd_Ref( bMonitor );
+    Cudd_AutodynEnable( dd,  CUDD_REORDER_SYMM_SIFT );
+    bImage = Llb_Nonlin4Image( dd, vParts, bMonitor, vVars2Q );  Cudd_Ref( bImage );
+    Cudd_RecursiveDeref( dd, bMonitor );
+    Llb_Nonlin4SweepDeref( dd, vParts );
+    Vec_IntFree( vVars2Q );
+    // save image and return
+    dd->bFunc = bImage;
+    return dd;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes clusters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+DdManager * Llb4_Nonlin4SweepGroups( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars, Vec_Ptr_t ** pvGroups, int nBddLimitClp, int fVerbose )
+{
+    DdManager * dd;
+    Vec_Ptr_t * vParts;
+    Vec_Int_t * vVars2Q;
+    // get quantifiable variables
+    vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 1 );
+    // start BDD manager and create partitions 
+    dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+    vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 1 );
+//printf( "Transitions: " );
+//Llb_Nonlin4SweepPrint( vParts );
+    // compute image of the partitions
+
+    Cudd_AutodynEnable( dd,  CUDD_REORDER_SYMM_SIFT );
+    *pvGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddLimitClp );
+    Llb_Nonlin4SweepDeref( dd, vParts );
+//    *pvGroups = vParts;
+
+if ( fVerbose )
+{
+printf( "Groups: " );
+Llb_Nonlin4SweepPrint( *pvGroups );
+}
+
+    Vec_IntFree( vVars2Q );
+    return dd;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates quantifiable variables for both types of traversal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb_Nonlin4SweepPrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups, int fVerbose )
+{
+    Aig_Obj_t * pObj;
+    int i, * pSupp;
+    int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0;
+
+    pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) );
+    Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp );
+
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+        if ( Llb_ObjBddVar(vOrder, pObj) < 0 )
+            continue;
+        // remove variables that do not participate
+        if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 )
+        {
+            if ( Aig_ObjIsNode(pObj) )
+                Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 );
+            continue;
+        }
+        nSuppAll++;
+        if ( Saig_ObjIsPi(pAig, pObj) )
+            nSuppPi++;
+        else if ( Saig_ObjIsLo(pAig, pObj) )
+            nSuppLo++;
+        else if ( Saig_ObjIsPo(pAig, pObj) )
+            nSuppPo++;
+        else if ( Saig_ObjIsLi(pAig, pObj) )
+            nSuppLi++;
+        else
+            nSuppAnd++;
+    }
+    ABC_FREE( pSupp );
+
+    if ( fVerbose )
+    {
+    printf( "Groups =%3d  ", Vec_PtrSize(vGroups) );
+    printf( "Variables: all =%4d ",  nSuppAll );
+    printf( "pi =%4d ",  nSuppPi );
+    printf( "po =%4d ",  nSuppPo );
+    printf( "lo =%4d ",  nSuppLo );
+    printf( "li =%4d ",  nSuppLi );
+    printf( "and =%4d",  nSuppAnd );
+    printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD sweep on the netlist.]
+
+  Description [Returns BDD manager, ordering, clusters, and bad states 
+  inside dd->bFunc.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose )
+{
+    DdManager * ddBad, * ddWork;
+    Vec_Ptr_t * vGroups;
+    Vec_Int_t * vOrder;
+    int Counter, nCutPoints;
+
+    // get the original ordering
+    Aig_ManCleanMarkA( pAig );
+    vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 1 );
+    assert( Counter == Aig_ManNodeNum(pAig) );
+    // mark the nodes
+    nCutPoints = Llb4_Nonlin4SweepCutpoints( pAig, vOrder, nSweepMax, fVerbose );
+    Vec_IntFree( vOrder );
+    // get better ordering
+    vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 0 );
+    assert( Counter == nCutPoints );
+    Aig_ManCleanMarkA( pAig );
+    // compute the BAD states
+    ddBad = Llb4_Nonlin4SweepBadStates( pAig, vOrder, nCutPoints + Aig_ManCiNum(pAig) + Aig_ManCoNum(pAig) );
+    // compute the clusters
+    ddWork = Llb4_Nonlin4SweepGroups( pAig, vOrder, nCutPoints + Aig_ManCiNum(pAig) + Aig_ManCoNum(pAig), &vGroups, nClusterMax, fVerbose );
+    // transfer the result from the Bad manager
+//printf( "Bad before = %d.\n", Cudd_DagSize(ddBad->bFunc) );
+    ddWork->bFunc = Cudd_bddTransfer( ddBad, ddWork, ddBad->bFunc );   Cudd_Ref( ddWork->bFunc );
+    Cudd_RecursiveDeref( ddBad, ddBad->bFunc );  ddBad->bFunc = NULL;
+    Extra_StopManager( ddBad );
+    // update ordering to exclude quantified variables
+//printf( "Bad after = %d.\n", Cudd_DagSize(ddWork->bFunc) );
+
+    Llb_Nonlin4SweepPrintSuppProfile( ddWork, pAig, vOrder, vGroups, fVerbose );
+
+    // return the result
+    *pdd = ddWork;
+    *pvOrder = vOrder;
+    *pvGroups = vGroups;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BDD sweep on the netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Llb4_Nonlin4SweepExperiment( Aig_Man_t * pAig )
+{
+    DdManager * dd;
+    Vec_Int_t * vOrder;
+    Vec_Ptr_t * vGroups;
+    Llb4_Nonlin4Sweep( pAig, 100, 500, &dd, &vOrder, &vGroups, 1 );
+
+    Llb_Nonlin4SweepDeref( dd, vGroups );
+
+    Cudd_RecursiveDeref( dd, dd->bFunc );
+    Extra_StopManager( dd );
+    Vec_IntFree( vOrder );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/llb/llbInt.h b/abc-build/src/proof/llb/llbInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/llbInt.h
@@ -0,0 +1,211 @@
+/**CFile****************************************************************
+
+  FileName    [llbInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [BDD-based reachability.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - May 8, 2010.]
+
+  Revision    [$Id: llbInt.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__llb__llbInt_h
+#define ABC__aig__llb__llbInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "aig/aig/aig.h"
+#include "aig/saig/saig.h"
+#include "proof/ssw/ssw.h"
+#include "misc/extra/extraBdd.h"
+#include "llb.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Man_t_ Llb_Man_t;
+typedef struct Llb_Mtr_t_ Llb_Mtr_t;
+typedef struct Llb_Grp_t_ Llb_Grp_t;
+
+struct Llb_Man_t_
+{
+    Gia_ParLlb_t *  pPars;          // parameters
+    Aig_Man_t *     pAigGlo;        // initial AIG manager (owned by the caller)
+    Aig_Man_t *     pAig;           // derived AIG manager (created in this package)
+    DdManager *     dd;             // BDD manager
+    DdManager *     ddG;            // BDD manager
+    DdManager *     ddR;            // BDD manager
+    Vec_Int_t *     vObj2Var;       // mapping AIG ObjId into BDD var index
+    Vec_Int_t *     vVar2Obj;       // mapping BDD var index into AIG ObjId
+    Vec_Ptr_t *     vGroups;        // group Id into group pointer
+    Llb_Mtr_t *     pMatrix;        // dependency matrix
+    // image computation
+    Vec_Ptr_t *     vRings;         // onion rings
+    Vec_Int_t *     vVarBegs;       // the first group where the var appears  
+    Vec_Int_t *     vVarEnds;       // the last group where the var appears 
+    // variable mapping
+    Vec_Int_t *     vNs2Glo;        // next state variables into global variables
+    Vec_Int_t *     vCs2Glo;        // next state variables into global variables
+    Vec_Int_t *     vGlo2Cs;        // global variables into current state variables
+    Vec_Int_t *     vGlo2Ns;        // global variables into current state variables
+    // flow computation
+//    Vec_Int_t *     vMem;
+//    Vec_Ptr_t *     vTops;
+//    Vec_Ptr_t *     vBots;
+//    Vec_Ptr_t *     vCuts;
+};
+
+struct Llb_Mtr_t_
+{
+    int             nPis;           // number of primary inputs
+    int             nFfs;           // number of flip-flops
+    int             nRows;          // number of rows
+    int             nCols;          // number of columns
+    int *           pColSums;       // sum of values in a column
+    Llb_Grp_t **    pColGrps;       // group structure for each col
+    int *           pRowSums;       // sum of values in a row
+    char **         pMatrix;        // dependency matrix
+    Llb_Man_t *     pMan;           // manager
+    // partial product
+    char *          pProdVars;      // variables in the partial product
+    int *           pProdNums;      // var counts in the remaining partitions
+};
+
+struct Llb_Grp_t_
+{
+    int             Id;             // group ID
+    Vec_Ptr_t *     vIns;           // input AIG objs
+    Vec_Ptr_t *     vOuts;          // output AIG objs
+    Vec_Ptr_t *     vNodes;         // internal AIG objs
+    Llb_Man_t *     pMan;           // manager
+    Llb_Grp_t *     pPrev;          // previous group
+    Llb_Grp_t *     pNext;          // next group
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Llb_ObjBddVar( Vec_Int_t * vOrder, Aig_Obj_t * pObj ) { return Vec_IntEntry(vOrder, Aig_ObjId(pObj)); }
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== llbConstr.c ======================================================*/
+extern Vec_Int_t *     Llb_ManDeriveConstraints( Aig_Man_t * p );
+extern void            Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands );
+/*=== llbCore.c ======================================================*/
+extern int             Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo );
+/*=== llbCluster.c ======================================================*/
+extern void            Llb_ManCluster( Llb_Mtr_t * p );
+/*=== llbDump.c ======================================================*/
+extern void            Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName );
+/*=== llbFlow.c ======================================================*/
+extern Vec_Ptr_t *     Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow );
+/*=== llbHint.c ======================================================*/
+extern int             Llb_ManReachabilityWithHints( Llb_Man_t * p );
+extern int             Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars );
+/*=== llbMan.c =======================================================*/
+extern void            Llb_ManPrepareVarMap( Llb_Man_t * p );
+extern Llb_Man_t *     Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t *  pPars );
+extern void            Llb_ManStop( Llb_Man_t * p );
+/*=== llbMatrix.c ====================================================*/
+extern void            Llb_MtrVerifyMatrix( Llb_Mtr_t * p );
+extern Llb_Mtr_t *     Llb_MtrCreate( Llb_Man_t * p );
+extern void            Llb_MtrFree( Llb_Mtr_t * p );
+extern void            Llb_MtrPrint( Llb_Mtr_t * p, int fOrder );
+extern void            Llb_MtrPrintMatrixStats( Llb_Mtr_t * p ); 
+/*=== llbPart.c ======================================================*/
+extern Llb_Grp_t *     Llb_ManGroupAlloc( Llb_Man_t * pMan );
+extern void            Llb_ManGroupStop( Llb_Grp_t * p );
+extern void            Llb_ManPrepareGroups( Llb_Man_t * pMan );
+extern Llb_Grp_t *     Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 );
+extern Llb_Grp_t *     Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 );
+extern void            Llb_ManPrepareVarLimits( Llb_Man_t * p );
+/*=== llbPivot.c =====================================================*/
+extern int             Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot );
+extern Vec_Int_t *     Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal );
+/*=== llbReach.c =====================================================*/
+extern int             Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo );
+/*=== llbSched.c =====================================================*/
+extern void            Llb_MtrSchedule( Llb_Mtr_t * p );
+
+/*=== llb2Bad.c ======================================================*/
+extern DdNode *        Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, abctime TimeOut );
+extern DdNode *        Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc );
+/*=== llb2Core.c ======================================================*/
+extern DdNode *        Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues );
+extern int             Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, abctime TimeTarget ); 
+/*=== llb2Driver.c ======================================================*/
+extern Vec_Int_t *     Llb_DriverCountRefs( Aig_Man_t * p );
+extern Vec_Int_t *     Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs );
+extern Vec_Int_t *     Llb_DriverCollectCs( Aig_Man_t * pAig );
+extern DdNode *        Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd );
+extern DdManager *     Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, abctime TimeTarget );
+/*=== llb2Image.c ======================================================*/
+extern Vec_Ptr_t *     Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose );
+extern void            Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose );
+extern DdManager *     Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, abctime TimeTarget );
+extern void            Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose );
+extern void            Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans );
+extern DdNode *        Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit, 
+                           Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs, 
+                           abctime TimeTarget, int fBackward, int fReorder, int fVerbose );
+
+extern DdManager *     Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, abctime TimeTarget );
+extern DdNode *        Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder );
+extern void            Llb_NonlinImageQuit();
+
+/*=== llb3Image.c =======================================================*/
+extern DdNode *        Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, 
+                           DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder );
+/*=== llb3Nonlin.c ======================================================*/
+extern DdNode *        Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd );
+
+
+/*=== llb4Cex.c =======================================================*/
+extern Abc_Cex_t *     Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose );
+/*=== llb4Cluster.c =======================================================*/
+//extern void            Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose );
+/*=== llb4Image.c =======================================================*/
+extern DdNode *        Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q );
+extern Vec_Ptr_t *     Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax );
+/*=== llb4Map.c =========================================================*/
+//extern Vec_Int_t *     Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin );
+/*=== llb4Nonlin.c ======================================================*/
+//extern int             Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars );
+/*=== llb4Sweep.c ======================================================*/
+extern void            Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose );
+ 
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/llb/module.make b/abc-build/src/proof/llb/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/llb/module.make
@@ -0,0 +1,22 @@
+SRC +=	src/proof/llb/llb1Cluster.c \
+	src/proof/llb/llb1Constr.c \
+	src/proof/llb/llb1Core.c \
+	src/proof/llb/llb1Group.c \
+	src/proof/llb/llb1Hint.c \
+	src/proof/llb/llb1Man.c \
+	src/proof/llb/llb1Matrix.c \
+	src/proof/llb/llb1Pivot.c \
+	src/proof/llb/llb1Reach.c \
+	src/proof/llb/llb1Sched.c \
+	src/proof/llb/llb2Bad.c \
+	src/proof/llb/llb2Core.c \
+	src/proof/llb/llb2Driver.c \
+	src/proof/llb/llb2Dump.c \
+	src/proof/llb/llb2Flow.c \
+	src/proof/llb/llb2Image.c \
+	src/proof/llb/llb3Image.c \
+	src/proof/llb/llb3Nonlin.c \
+	src/proof/llb/llb4Cex.c \
+	src/proof/llb/llb4Image.c \
+	src/proof/llb/llb4Nonlin.c \
+	src/proof/llb/llb4Sweep.c
diff --git a/abc-build/src/proof/pdr/module.make b/abc-build/src/proof/pdr/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/pdr/module.make
@@ -0,0 +1,7 @@
+SRC +=	src/proof/pdr/pdrCnf.c \
+	src/proof/pdr/pdrCore.c \
+	src/proof/pdr/pdrInv.c \
+	src/proof/pdr/pdrMan.c \
+	src/proof/pdr/pdrSat.c \
+	src/proof/pdr/pdrTsim.c \
+	src/proof/pdr/pdrUtil.c 
diff --git a/abc-build/src/proof/pdr/pdr.c b/abc-build/src/proof/pdr/pdr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/pdr/pdr.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+  FileName    [pdr.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Netlist representation.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 20, 2010.]
+
+  Revision    [$Id: pdr.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "pdrInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/pdr/pdr.h b/abc-build/src/proof/pdr/pdr.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/pdr/pdr.h
@@ -0,0 +1,97 @@
+/**CFile****************************************************************
+
+  FileName    [pdr.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Property driven reachability.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 20, 2010.]
+
+  Revision    [$Id: pdr.h,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__sat__pdr__pdr_h
+#define ABC__sat__pdr__pdr_h
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Pdr_Par_t_ Pdr_Par_t;
+struct Pdr_Par_t_
+{
+//    int iOutput;          // zero-based number of primary output to solve
+    int nRecycle;         // limit on vars for recycling
+    int nFrameMax;        // limit on frame count
+    int nConfLimit;       // limit on SAT solver conflicts
+    int nRestLimit;       // limit on the number of proof-obligations
+    int nTimeOut;         // timeout in seconds
+    int nTimeOutGap;      // approximate timeout in seconds since the last change
+    int nTimeOutOne;      // approximate timeout in seconds per one output
+    int fTwoRounds;       // use two rounds for generalization
+    int fMonoCnf;         // monolythic CNF
+    int fDumpInv;         // dump inductive invariant
+    int fShortest;        // forces bug traces to be shortest
+    int fShiftStart;      // allows clause pushing to start from an intermediate frame
+    int fReuseProofOblig; // reuses proof-obligationgs in the last timeframe
+    int fSkipGeneral;     // skips expensive generalization step
+    int fVerbose;         // verbose output`
+    int fVeryVerbose;     // very verbose output
+    int fNotVerbose;      // not printing line by line progress
+    int fSilent;          // totally silent execution
+    int fSolveAll;        // do not stop when found a SAT output
+    int fStoreCex;        // enable storing counter-examples in MO mode
+    int fUseBridge;       // use bridge interface
+    int nFailOuts;        // the number of failed outputs
+    int nDropOuts;        // the number of timed out outputs
+    int nProveOuts;       // the number of proved outputs
+    int iFrame;           // explored up to this frame
+    int RunId;            // PDR id in this run 
+    int(*pFuncStop)(int); // callback to terminate
+    int(*pFuncOnFail)(int,Abc_Cex_t*); // called for a failed output in MO mode
+    abctime timeLastSolved; // the time when the last output was solved
+    Vec_Int_t * vOutMap;  // in the multi-output mode, contains status for each PO (0 = sat; 1 = unsat; negative = undecided)
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== pdrCore.c ==========================================================*/
+extern void               Pdr_ManSetDefaultParams( Pdr_Par_t * pPars );
+extern int                Pdr_ManSolve( Aig_Man_t * p, Pdr_Par_t * pPars );
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/pdr/pdrClass.c b/abc-build/src/proof/pdr/pdrClass.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/pdr/pdrClass.c
@@ -0,0 +1,223 @@
+/**CFile****************************************************************
+
+  FileName    [pdrClass.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Property driven reachability.]
+
+  Synopsis    [Equivalence classes of register outputs.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 20, 2010.]
+
+  Revision    [$Id: pdrClass.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "pdrInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs duplication with the variable map.]
+
+  Description [Var map contains -1 if const0 and <reg_num> otherwise.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Pdr_ManRehashWithMap( Aig_Man_t * pAig, Vec_Int_t * vMap )
+{
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj;
+    int i, iReg;
+    assert( Vec_IntSize(vMap) == Aig_ManRegNum(pAig) );
+    // start the fraig package
+    pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) );
+    pFrames->pName = Abc_UtilStrsav( pAig->pName );
+    pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec );
+    // create CI mapping
+    Aig_ManCleanData( pAig );
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1(pFrames);
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi(pFrames);
+    Saig_ManForEachLo( pAig, pObj, i )
+    {
+        iReg = Vec_IntEntry(vMap, i);
+        if ( iReg == -1 )
+            pObj->pData = Aig_ManConst0(pFrames);
+        else
+            pObj->pData = Saig_ManLo(pAig, iReg)->pData;
+    }
+    // add internal nodes of this frame
+    Aig_ManForEachNode( pAig, pObj, i )
+        pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // add output nodes
+    Aig_ManForEachCo( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) );
+    // finish off
+    Aig_ManCleanup( pFrames );
+    Aig_ManSetRegNum( pFrames, Aig_ManRegNum(pAig) );
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates mapping of registers.]
+
+  Description [Var map contains -1 if const0 and <reg_num> otherwise.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Pdr_ManCreateMap( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    Vec_Int_t * vMap;
+    int * pLit2Id, Lit, i;
+    pLit2Id = ABC_ALLOC( int, Aig_ManObjNumMax(p) * 2 );
+    for ( i = 0; i < Aig_ManObjNumMax(p) * 2; i++ )
+        pLit2Id[i] = -1;
+    vMap = Vec_IntAlloc( Aig_ManRegNum(p) );
+    Saig_ManForEachLi( p, pObj, i )
+    {
+        if ( Aig_ObjChild0(pObj) == Aig_ManConst0(p) )
+        {
+            Vec_IntPush( vMap, -1 );
+            continue;
+        }
+        Lit = 2 * Aig_ObjFaninId0(pObj) + Aig_ObjFaninC0(pObj);
+        if ( pLit2Id[Lit] < 0 ) // the first time
+            pLit2Id[Lit] = i;
+        Vec_IntPush( vMap, pLit2Id[Lit] );
+    }
+    ABC_FREE( pLit2Id );
+    return vMap;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts reduced registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ManCountMap( Vec_Int_t * vMap )
+{
+    int i, Entry, Counter = 0;
+    Vec_IntForEachEntry( vMap, Entry, i )
+        if ( Entry != i )
+            Counter++;
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts reduced registers.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_ManPrintMap( Vec_Int_t * vMap )
+{
+    Vec_Int_t * vMarks;
+    int f, i, iClass, Entry, Counter = 0;
+    Abc_Print( 1, "    Consts: " );
+    Vec_IntForEachEntry( vMap, Entry, i )
+        if ( Entry == -1 )
+            Abc_Print( 1, "%d ", i );
+    Abc_Print( 1, "\n" );
+    vMarks = Vec_IntAlloc( 100 );
+    Vec_IntForEachEntry( vMap, iClass, f )
+    {
+        if ( iClass == -1 )
+            continue;
+        if ( iClass == f )
+            continue;
+        // check previous classes
+        if ( Vec_IntFind( vMarks, iClass ) >= 0 )
+            continue;
+        Vec_IntPush( vMarks, iClass );
+        // print class
+        Abc_Print( 1, "    Class %d : ", iClass );
+        Vec_IntForEachEntry( vMap, Entry, i )
+            if ( Entry == iClass )
+                Abc_Print( 1, "%d ", i );
+        Abc_Print( 1, "\n" );
+    }
+    Vec_IntFree( vMarks );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_ManEquivClasses( Aig_Man_t * pAig )
+{
+    Vec_Int_t * vMap;
+    Aig_Man_t * pTemp;
+    int f, nFrames = 100;
+    assert( Saig_ManRegNum(pAig) > 0 );
+    // start the map
+    vMap = Vec_IntAlloc( 0 );
+    Vec_IntFill( vMap, Aig_ManRegNum(pAig), -1 );
+    // iterate and print changes
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // implement variable map
+        pTemp = Pdr_ManRehashWithMap( pAig, vMap );
+        // report the result
+        Abc_Print( 1, "F =%4d : Total = %6d. Nodes = %6d. RedRegs = %6d. Prop = %s\n", 
+            f+1, Aig_ManNodeNum(pAig), Aig_ManNodeNum(pTemp), Pdr_ManCountMap(vMap), 
+            Aig_ObjChild0(Aig_ManCo(pTemp,0)) == Aig_ManConst0(pTemp) ? "proof" : "unknown" );
+        // recreate the map
+        Pdr_ManPrintMap( vMap );
+        Vec_IntFree( vMap );
+        vMap = Pdr_ManCreateMap( pTemp );
+        Aig_ManStop( pTemp );
+        if ( Pdr_ManCountMap(vMap) == 0 )
+            break;
+    }
+    Vec_IntFree( vMap );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/pdr/pdrCnf.c b/abc-build/src/proof/pdr/pdrCnf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/pdr/pdrCnf.c
@@ -0,0 +1,451 @@
+/**CFile****************************************************************
+
+  FileName    [pdrCnf.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Property driven reachability.]
+
+  Synopsis    [CNF computation on demand.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 20, 2010.]
+
+  Revision    [$Id: pdrCnf.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "pdrInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+/*
+    The CNF (p->pCnf2) is expressed in terms of object IDs.
+    Each node in the CNF is marked if it has clauses (p->pCnf2->pObj2Count[Id] > 0).
+    Each node in the CNF has the first clause (p->pCnf2->pObj2Clause) 
+    and the number of clauses (p->pCnf2->pObj2Count).
+    Each node used in a CNF of any timeframe has its SAT var recorded.
+    Each frame has a reserve mapping of SAT variables into ObjIds.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns SAT variable of the given object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Pdr_ObjSatVar1( Pdr_Man_t * p, int k, Aig_Obj_t * pObj )
+{
+    return p->pCnf1->pVarNums[ Aig_ObjId(pObj) ];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns SAT variable of the given object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+//#define USE_PG
+#ifdef USE_PG
+static inline int Pdr_ObjSatVar2FindOrAdd( Pdr_Man_t * p, int k, Aig_Obj_t * pObj )
+{ 
+    Vec_Int_t * vId2Vars = p->pvId2Vars + Aig_ObjId(pObj);
+    assert( p->pCnf2->pObj2Count[Aig_ObjId(pObj)] >= 0 );
+    if ( Vec_IntSize(vId2Vars) == 0 )
+        Vec_IntGrow(vId2Vars, 2 * k + 1);
+    if ( Vec_IntGetEntry(vId2Vars, k) == 0 )
+    {
+        sat_solver * pSat = Pdr_ManSolver(p, k);
+        Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(&p->vVar2Ids, k);
+        int iVarNew = Vec_IntSize( vVar2Ids );
+        assert( iVarNew > 0 );
+        Vec_IntPush( vVar2Ids, Aig_ObjId(pObj) );
+        Vec_IntWriteEntry( vId2Vars, k, iVarNew << 2 );
+        sat_solver_setnvars( pSat, iVarNew + 1 );
+        if ( k == 0 && Saig_ObjIsLo(p->pAig, pObj) ) // initialize the register output
+        {
+            int Lit = toLitCond( iVarNew, 1 );
+            int RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
+            assert( RetValue == 1 );
+            (void) RetValue;
+            sat_solver_compress( pSat );
+        }
+    }
+    return Vec_IntEntry( vId2Vars, k );
+}
+int Pdr_ObjSatVar2( Pdr_Man_t * p, int k, Aig_Obj_t * pObj, int Level, int Pol )
+{
+    Vec_Int_t * vLits;
+    sat_solver * pSat;
+    Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(&p->vVar2Ids, k);
+    int nVarCount = Vec_IntSize(vVar2Ids);
+    int iVarThis  = Pdr_ObjSatVar2FindOrAdd( p, k, pObj );
+    int * pLit, i, iVar, iClaBeg, iClaEnd, RetValue;
+    int PolPres = (iVarThis & 3);
+    iVarThis >>= 2;
+    if ( Aig_ObjIsCi(pObj) )
+        return iVarThis;
+//    Pol = 3;
+//    if ( nVarCount != Vec_IntSize(vVar2Ids) || (Pol & ~PolPres) )
+    if ( (Pol & ~PolPres) )
+    {
+        *Vec_IntEntryP( p->pvId2Vars + Aig_ObjId(pObj), k ) |= Pol;
+        iClaBeg = p->pCnf2->pObj2Clause[Aig_ObjId(pObj)];
+        iClaEnd = iClaBeg + p->pCnf2->pObj2Count[Aig_ObjId(pObj)];
+        assert( iClaBeg < iClaEnd );
+/*
+        if ( (Pol & ~PolPres) != 3 )
+        for ( i = iFirstClause; i < iFirstClause + nClauses; i++ )
+        {
+            printf( "Clause %5d : ", i );
+            for ( iVar = 0; iVar < 4; iVar++ )
+                printf( "%d ", ((unsigned)p->pCnf2->pClaPols[i] >> (2*iVar)) & 3 );
+            printf( "  " );
+            for ( pLit = p->pCnf2->pClauses[i]; pLit < p->pCnf2->pClauses[i+1]; pLit++ )
+                printf( "%6d ", *pLit );
+            printf( "\n" );
+        }
+*/
+        pSat = Pdr_ManSolver(p, k);
+        vLits = Vec_WecEntry( p->vVLits, Level );
+        if ( (Pol & ~PolPres) == 3 )
+        {
+            assert( nVarCount + 1 == Vec_IntSize(vVar2Ids) );
+            for ( i = iClaBeg; i < iClaEnd; i++ )
+            {
+                Vec_IntClear( vLits );
+                Vec_IntPush( vLits, toLitCond( iVarThis, lit_sign(p->pCnf2->pClauses[i][0]) ) );
+                for ( pLit = p->pCnf2->pClauses[i]+1; pLit < p->pCnf2->pClauses[i+1]; pLit++ )
+                {
+                    iVar = Pdr_ObjSatVar2( p, k, Aig_ManObj(p->pAig, lit_var(*pLit)), Level+1, 3 );
+                    Vec_IntPush( vLits, toLitCond( iVar, lit_sign(*pLit) ) );
+                }
+                RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits) );
+                assert( RetValue );
+                (void) RetValue;
+            }
+        }
+        else // if ( (Pol & ~PolPres) == 2 || (Pol & ~PolPres) == 1 ) // write pos/neg polarity
+        {
+            assert( (Pol & ~PolPres) );
+            for ( i = iClaBeg; i < iClaEnd; i++ )
+            if ( 2 - !Abc_LitIsCompl(p->pCnf2->pClauses[i][0]) == (Pol & ~PolPres) ) // taking opposite literal
+            {
+                Vec_IntClear( vLits );
+                Vec_IntPush( vLits, toLitCond( iVarThis, Abc_LitIsCompl(p->pCnf2->pClauses[i][0]) ) );
+                for ( pLit = p->pCnf2->pClauses[i]+1; pLit < p->pCnf2->pClauses[i+1]; pLit++ )
+                {
+                    iVar = Pdr_ObjSatVar2( p, k, Aig_ManObj(p->pAig, lit_var(*pLit)), Level+1, ((unsigned)p->pCnf2->pClaPols[i] >> (2*(pLit-p->pCnf2->pClauses[i]-1))) & 3 );
+                    Vec_IntPush( vLits, toLitCond( iVar, lit_sign(*pLit) ) );
+                }
+                RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits) );
+                assert( RetValue );
+                (void) RetValue;
+            }
+        }
+    }
+    return iVarThis;
+}
+
+#else
+static inline int Pdr_ObjSatVar2FindOrAdd( Pdr_Man_t * p, int k, Aig_Obj_t * pObj, int * pfNewVar )
+{ 
+    Vec_Int_t * vId2Vars = p->pvId2Vars + Aig_ObjId(pObj);
+    assert( p->pCnf2->pObj2Count[Aig_ObjId(pObj)] >= 0 );
+    if ( Vec_IntSize(vId2Vars) == 0 )
+        Vec_IntGrow(vId2Vars, 2 * k + 1);
+    if ( Vec_IntGetEntry(vId2Vars, k) == 0 )
+    {
+        sat_solver * pSat = Pdr_ManSolver(p, k);
+        Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(&p->vVar2Ids, k);
+        int iVarNew = Vec_IntSize( vVar2Ids );
+        assert( iVarNew > 0 );
+        Vec_IntPush( vVar2Ids, Aig_ObjId(pObj) );
+        Vec_IntWriteEntry( vId2Vars, k, iVarNew );
+        sat_solver_setnvars( pSat, iVarNew + 1 );
+        if ( k == 0 && Saig_ObjIsLo(p->pAig, pObj) ) // initialize the register output
+        {
+            int Lit = toLitCond( iVarNew, 1 );
+            int RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
+            assert( RetValue == 1 );
+            (void) RetValue;
+            sat_solver_compress( pSat );
+        }
+        *pfNewVar = 1;
+    }
+    return Vec_IntEntry( vId2Vars, k );
+}
+int Pdr_ObjSatVar2( Pdr_Man_t * p, int k, Aig_Obj_t * pObj, int Level, int Pol )
+{
+    Vec_Int_t * vLits;
+    sat_solver * pSat;
+    int fNewVar = 0, iVarThis  = Pdr_ObjSatVar2FindOrAdd( p, k, pObj, &fNewVar );
+    int * pLit, i, iVar, iClaBeg, iClaEnd, RetValue;
+    if ( Aig_ObjIsCi(pObj) || !fNewVar )
+        return iVarThis;
+    iClaBeg = p->pCnf2->pObj2Clause[Aig_ObjId(pObj)];
+    iClaEnd = iClaBeg + p->pCnf2->pObj2Count[Aig_ObjId(pObj)];
+    assert( iClaBeg < iClaEnd );
+    pSat = Pdr_ManSolver(p, k);
+    vLits = Vec_WecEntry( p->vVLits, Level );
+    for ( i = iClaBeg; i < iClaEnd; i++ )
+    {
+        Vec_IntClear( vLits );
+        Vec_IntPush( vLits, toLitCond( iVarThis, lit_sign(p->pCnf2->pClauses[i][0]) ) );
+        for ( pLit = p->pCnf2->pClauses[i]+1; pLit < p->pCnf2->pClauses[i+1]; pLit++ )
+        {
+            iVar = Pdr_ObjSatVar2( p, k, Aig_ManObj(p->pAig, lit_var(*pLit)), Level+1, Pol );
+            Vec_IntPush( vLits, toLitCond( iVar, lit_sign(*pLit) ) );
+        }
+        RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits) );
+        assert( RetValue );
+        (void) RetValue;
+    }
+    return iVarThis;
+}
+#endif
+
+/**Function*************************************************************
+
+  Synopsis    [Returns SAT variable of the given object.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ObjSatVar( Pdr_Man_t * p, int k, int Pol, Aig_Obj_t * pObj )
+{
+    if ( p->pPars->fMonoCnf )
+        return Pdr_ObjSatVar1( p, k, pObj );
+    else
+        return Pdr_ObjSatVar2( p, k, pObj, 0, Pol );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns register number for the given SAT variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Pdr_ObjRegNum1( Pdr_Man_t * p, int k, int iSatVar )
+{
+    int RegId;
+    assert( iSatVar >= 0 );
+    // consider the case of auxiliary variable
+    if ( iSatVar >= p->pCnf1->nVars )
+        return -1;
+    // consider the case of register output
+    RegId = Vec_IntEntry( p->vVar2Reg, iSatVar );
+    assert( RegId >= 0 && RegId < Aig_ManRegNum(p->pAig) );
+    return RegId;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns register number for the given SAT variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Pdr_ObjRegNum2( Pdr_Man_t * p, int k, int iSatVar )
+{
+    Aig_Obj_t * pObj;
+    int ObjId;
+    Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(&p->vVar2Ids, k);
+    assert( iSatVar > 0 && iSatVar < Vec_IntSize(vVar2Ids) );
+    ObjId = Vec_IntEntry( vVar2Ids, iSatVar );
+    if ( ObjId == -1 ) // activation variable
+        return -1;
+    pObj = Aig_ManObj( p->pAig, ObjId );
+    if ( Saig_ObjIsLi( p->pAig, pObj ) )
+        return Aig_ObjCioId(pObj)-Saig_ManPoNum(p->pAig);
+    assert( 0 ); // should be called for register inputs only
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns register number for the given SAT variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ObjRegNum( Pdr_Man_t * p, int k, int iSatVar )
+{
+    if ( p->pPars->fMonoCnf )
+        return Pdr_ObjRegNum1( p, k, iSatVar );
+    else
+        return Pdr_ObjRegNum2( p, k, iSatVar );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the index of unused SAT variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ManFreeVar( Pdr_Man_t * p, int k )
+{
+    if ( p->pPars->fMonoCnf )
+        return sat_solver_nvars( Pdr_ManSolver(p, k) );
+    else
+    {
+        Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry( &p->vVar2Ids, k );
+        Vec_IntPush( vVar2Ids, -1 );
+        return Vec_IntSize( vVar2Ids ) - 1;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline sat_solver * Pdr_ManNewSolver1( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    assert( pSat );
+    if ( p->pCnf1 == NULL )
+    {
+        int nRegs = p->pAig->nRegs;
+        p->pAig->nRegs = Aig_ManCoNum(p->pAig);
+        p->pCnf1 = Cnf_DeriveWithMan( p->pCnfMan, p->pAig, Aig_ManCoNum(p->pAig) );
+        p->pAig->nRegs = nRegs;
+        assert( p->vVar2Reg == NULL );
+        p->vVar2Reg = Vec_IntStartFull( p->pCnf1->nVars );
+        Saig_ManForEachLi( p->pAig, pObj, i )
+            Vec_IntWriteEntry( p->vVar2Reg, Pdr_ObjSatVar(p, k, 3, pObj), i );
+    }
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolverInt( pSat, p->pCnf1, 1, fInit );
+    sat_solver_set_runtime_limit( pSat, p->timeToStop );
+    return pSat;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline sat_solver * Pdr_ManNewSolver2( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit )
+{
+    Vec_Int_t * vVar2Ids;
+    int i, Entry;
+    assert( pSat );
+    if ( p->pCnf2 == NULL )
+    {
+        p->pCnf2     = Cnf_DeriveOtherWithMan( p->pCnfMan, p->pAig, 0 );
+#ifdef USE_PG
+        p->pCnf2->pClaPols = Cnf_DataDeriveLitPolarities( p->pCnf2 );
+#endif
+        p->pvId2Vars = ABC_CALLOC( Vec_Int_t, Aig_ManObjNumMax(p->pAig) );
+        Vec_PtrGrow( &p->vVar2Ids, 256 );
+    }
+    // update the variable mapping
+    vVar2Ids = (Vec_Int_t *)Vec_PtrGetEntry( &p->vVar2Ids, k );
+    if ( vVar2Ids == NULL )
+    {
+        vVar2Ids = Vec_IntAlloc( 500 );
+        Vec_PtrWriteEntry( &p->vVar2Ids, k, vVar2Ids );
+    }
+    Vec_IntForEachEntry( vVar2Ids, Entry, i )
+    {
+        if ( Entry == -1 )
+            continue;
+        assert( Vec_IntEntry( p->pvId2Vars + Entry, k ) > 0 );
+        Vec_IntWriteEntry( p->pvId2Vars + Entry, k, 0 );
+    }
+    Vec_IntClear( vVar2Ids );
+    Vec_IntPush( vVar2Ids, -1 );
+    // start the SAT solver
+//    pSat = sat_solver_new();
+    sat_solver_setnvars( pSat, 500 );
+    sat_solver_set_runtime_limit( pSat, p->timeToStop );
+    return pSat;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+sat_solver * Pdr_ManNewSolver( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit )
+{
+    assert( pSat != NULL );
+    if ( p->pPars->fMonoCnf )
+        return Pdr_ManNewSolver1( pSat, p, k, fInit );
+    else
+        return Pdr_ManNewSolver2( pSat, p, k, fInit );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/pdr/pdrCore.c b/abc-build/src/proof/pdr/pdrCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/pdr/pdrCore.c
@@ -0,0 +1,938 @@
+/**CFile****************************************************************
+
+  FileName    [pdrCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Property driven reachability.]
+
+  Synopsis    [Core procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 20, 2010.]
+
+  Revision    [$Id: pdrCore.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "pdrInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Gia_ManToBridgeResult( FILE * pFile, int Result, Abc_Cex_t * pCex, int iPoProved );
+extern int Gia_ManToBridgeAbort( FILE * pFile, int Size, unsigned char * pBuffer );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the state could be blocked.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_ManSetDefaultParams( Pdr_Par_t * pPars )
+{
+    memset( pPars, 0, sizeof(Pdr_Par_t) );
+//    pPars->iOutput        =      -1;  // zero-based output number
+    pPars->nRecycle       =     300;  // limit on vars for recycling
+    pPars->nFrameMax      =   10000;  // limit on number of timeframes
+    pPars->nTimeOut       =       0;  // timeout in seconds
+    pPars->nTimeOutGap    =       0;  // timeout in seconds since the last solved
+    pPars->nConfLimit     =       0;  // limit on SAT solver conflicts
+    pPars->nRestLimit     =       0;  // limit on the number of proof-obligations
+    pPars->fTwoRounds     =       0;  // use two rounds for generalization
+    pPars->fMonoCnf       =       0;  // monolythic CNF
+    pPars->fDumpInv       =       0;  // dump inductive invariant
+    pPars->fShortest      =       0;  // forces bug traces to be shortest
+    pPars->fVerbose       =       0;  // verbose output
+    pPars->fVeryVerbose   =       0;  // very verbose output
+    pPars->fNotVerbose    =       0;  // not printing line-by-line progress
+    pPars->iFrame         =      -1;  // explored up to this frame
+    pPars->nFailOuts      =       0;  // the number of disproved outputs
+    pPars->nDropOuts      =       0;  // the number of timed out outputs
+    pPars->timeLastSolved =       0;  // last one solved
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces clause using analyzeFinal.]
+
+  Description [Assumes that the SAT solver just terminated an UNSAT call.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Pdr_Set_t * Pdr_ManReduceClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube )
+{
+    Pdr_Set_t * pCubeMin;
+    Vec_Int_t * vLits;
+    int i, Entry, nCoreLits, * pCoreLits;
+    // get relevant SAT literals
+    nCoreLits = sat_solver_final(Pdr_ManSolver(p, k), &pCoreLits);
+    // translate them into register literals and remove auxiliary
+    vLits = Pdr_ManLitsToCube( p, k, pCoreLits, nCoreLits );
+    // skip if there is no improvement
+    if ( Vec_IntSize(vLits) == pCube->nLits )
+        return NULL;
+    assert( Vec_IntSize(vLits) < pCube->nLits );
+    // if the cube overlaps with init, add any literal
+    Vec_IntForEachEntry( vLits, Entry, i )
+        if ( lit_sign(Entry) == 0 ) // positive literal
+            break;
+    if ( i == Vec_IntSize(vLits) ) // only negative literals
+    {
+        // add the first positive literal
+        for ( i = 0; i < pCube->nLits; i++ )
+            if ( lit_sign(pCube->Lits[i]) == 0 ) // positive literal
+            {
+                Vec_IntPush( vLits, pCube->Lits[i] );
+                break;
+            }
+        assert( i < pCube->nLits );
+    }
+    // generate a starting cube
+    pCubeMin  = Pdr_SetCreateSubset( pCube, Vec_IntArray(vLits), Vec_IntSize(vLits) );
+    assert( !Pdr_SetIsInit(pCubeMin, -1) );
+/*
+    // make sure the cube works
+    {
+    int RetValue;
+    RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, 0 );
+    assert( RetValue );
+    }
+*/
+    return pCubeMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the state could be blocked.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ManPushClauses( Pdr_Man_t * p )
+{
+    Pdr_Set_t * pTemp, * pCubeK, * pCubeK1;
+    Vec_Ptr_t * vArrayK, * vArrayK1;
+    int i, j, k, m, RetValue = 0, RetValue2, kMax = Vec_PtrSize(p->vSolvers)-1;
+    int iStartFrame = p->pPars->fShiftStart ? p->iUseFrame : 1;
+    int Counter = 0;
+    abctime clk = Abc_Clock();
+    assert( p->iUseFrame > 0 );
+    Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, k, iStartFrame, kMax )
+    {
+        Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare );
+        vArrayK1 = Vec_VecEntry( p->vClauses, k+1 );
+        Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j )
+        {
+            Counter++;
+
+            // remove cubes in the same frame that are contained by pCubeK
+            Vec_PtrForEachEntryStart( Pdr_Set_t *, vArrayK, pTemp, m, j+1 )
+            {
+                if ( !Pdr_SetContains( pTemp, pCubeK ) ) // pCubeK contains pTemp
+                    continue;
+                Pdr_SetDeref( pTemp );
+                Vec_PtrWriteEntry( vArrayK, m, Vec_PtrEntryLast(vArrayK) );
+                Vec_PtrPop(vArrayK);
+                m--;
+            }
+
+            // check if the clause can be moved to the next frame
+            RetValue2 = Pdr_ManCheckCube( p, k, pCubeK, NULL, 0 );
+            if ( RetValue2 == -1 )
+                return -1;
+            if ( !RetValue2 )
+                continue;
+
+            {
+                Pdr_Set_t * pCubeMin;
+                pCubeMin = Pdr_ManReduceClause( p, k, pCubeK );
+                if ( pCubeMin != NULL )
+                {
+//                Abc_Print( 1, "%d ", pCubeK->nLits - pCubeMin->nLits );
+                    Pdr_SetDeref( pCubeK );
+                    pCubeK = pCubeMin;
+                }
+            }
+
+            // if it can be moved, add it to the next frame
+            Pdr_ManSolverAddClause( p, k+1, pCubeK );
+            // check if the clause subsumes others
+            Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK1, pCubeK1, i )
+            {
+                if ( !Pdr_SetContains( pCubeK1, pCubeK ) ) // pCubeK contains pCubeK1
+                    continue;
+                Pdr_SetDeref( pCubeK1 );
+                Vec_PtrWriteEntry( vArrayK1, i, Vec_PtrEntryLast(vArrayK1) );
+                Vec_PtrPop(vArrayK1);
+                i--;
+            }
+            // add the last clause
+            Vec_PtrPush( vArrayK1, pCubeK );
+            Vec_PtrWriteEntry( vArrayK, j, Vec_PtrEntryLast(vArrayK) );
+            Vec_PtrPop(vArrayK);
+            j--;
+        }
+        if ( Vec_PtrSize(vArrayK) == 0 )
+            RetValue = 1;
+    }
+
+    // clean up the last one
+    vArrayK = Vec_VecEntry( p->vClauses, kMax );
+    Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare );
+    Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j )
+    {
+        // remove cubes in the same frame that are contained by pCubeK
+        Vec_PtrForEachEntryStart( Pdr_Set_t *, vArrayK, pTemp, m, j+1 )
+        {
+            if ( !Pdr_SetContains( pTemp, pCubeK ) ) // pCubeK contains pTemp
+                continue;
+/*
+            Abc_Print( 1, "===\n" );
+            Pdr_SetPrint( stdout, pCubeK, Aig_ManRegNum(p->pAig), NULL );
+            Abc_Print( 1, "\n" );
+            Pdr_SetPrint( stdout, pTemp, Aig_ManRegNum(p->pAig), NULL );
+            Abc_Print( 1, "\n" );
+*/
+            Pdr_SetDeref( pTemp );
+            Vec_PtrWriteEntry( vArrayK, m, Vec_PtrEntryLast(vArrayK) );
+            Vec_PtrPop(vArrayK);
+            m--;
+        }
+    }
+    p->tPush += Abc_Clock() - clk;
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the clause is contained in higher clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ManCheckContainment( Pdr_Man_t * p, int k, Pdr_Set_t * pSet )
+{
+    Pdr_Set_t * pThis;
+    Vec_Ptr_t * vArrayK;
+    int i, j, kMax = Vec_PtrSize(p->vSolvers)-1;
+    Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, i, k, kMax+1 )
+        Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pThis, j )
+            if ( Pdr_SetContains( pSet, pThis ) )
+                return 1;
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sorts literals by priority.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Pdr_ManSortByPriority( Pdr_Man_t * p, Pdr_Set_t * pCube )
+{
+    int * pPrios = Vec_IntArray(p->vPrio);
+    int * pArray = p->pOrder;
+    int temp, i, j, best_i, nSize = pCube->nLits;
+    // initialize variable order
+    for ( i = 0; i < nSize; i++ )
+        pArray[i] = i;
+    for ( i = 0; i < nSize-1; i++ )
+    {
+        best_i = i;
+        for ( j = i+1; j < nSize; j++ )
+//            if ( pArray[j] < pArray[best_i] )
+            if ( pPrios[pCube->Lits[pArray[j]]>>1] < pPrios[pCube->Lits[pArray[best_i]]>>1] )
+                best_i = j;
+        temp = pArray[i];
+        pArray[i] = pArray[best_i];
+        pArray[best_i] = temp;
+    }
+/*
+    for ( i = 0; i < pCube->nLits; i++ )
+        Abc_Print( 1, "%2d : %5d    %5d  %5d\n", i, pArray[i], pCube->Lits[pArray[i]]>>1, pPrios[pCube->Lits[pArray[i]]>>1] );
+    Abc_Print( 1, "\n" );
+*/
+    return pArray;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the state could be blocked.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ManGeneralize( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, Pdr_Set_t ** ppCubeMin )
+{
+    Pdr_Set_t * pCubeMin, * pCubeTmp = NULL;
+    int i, j, n, Lit, RetValue;
+    abctime clk = Abc_Clock();
+    int * pOrder;
+    // if there is no induction, return
+    *ppCubeMin = NULL;
+    RetValue = Pdr_ManCheckCube( p, k, pCube, ppPred, p->pPars->nConfLimit );
+    if ( RetValue == -1 )
+        return -1;
+    if ( RetValue == 0 )
+    {
+        p->tGeneral += Abc_Clock() - clk;
+        return 0;
+    }
+
+    // reduce clause using assumptions
+//    pCubeMin = Pdr_SetDup( pCube );
+    pCubeMin = Pdr_ManReduceClause( p, k, pCube );
+    if ( pCubeMin == NULL )
+        pCubeMin = Pdr_SetDup( pCube );
+
+    // perform generalization
+    if ( !p->pPars->fSkipGeneral )
+    {
+        // sort literals by their occurences
+        pOrder = Pdr_ManSortByPriority( p, pCubeMin );
+        // try removing literals
+        for ( j = 0; j < pCubeMin->nLits; j++ )
+        {
+            // use ordering
+    //        i = j;
+            i = pOrder[j];
+
+            // check init state
+            assert( pCubeMin->Lits[i] != -1 );
+            if ( Pdr_SetIsInit(pCubeMin, i) )
+                continue;
+            // try removing this literal
+            Lit = pCubeMin->Lits[i]; pCubeMin->Lits[i] = -1;
+            RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, p->pPars->nConfLimit );
+            if ( RetValue == -1 )
+            {
+                Pdr_SetDeref( pCubeMin );
+                return -1;
+            }
+            pCubeMin->Lits[i] = Lit;
+            if ( RetValue == 0 )
+                continue;
+
+            // remove j-th entry
+            for ( n = j; n < pCubeMin->nLits-1; n++ )
+                pOrder[n] = pOrder[n+1];
+            j--;
+
+            // success - update the cube
+            pCubeMin = Pdr_SetCreateFrom( pCubeTmp = pCubeMin, i );
+            Pdr_SetDeref( pCubeTmp );
+            assert( pCubeMin->nLits > 0 );
+            i--;
+
+            // get the ordering by decreasing priorit
+            pOrder = Pdr_ManSortByPriority( p, pCubeMin );
+        }
+
+        if ( p->pPars->fTwoRounds )
+        for ( j = 0; j < pCubeMin->nLits; j++ )
+        {
+            // use ordering
+    //        i = j;
+            i = pOrder[j];
+
+            // check init state
+            assert( pCubeMin->Lits[i] != -1 );
+            if ( Pdr_SetIsInit(pCubeMin, i) )
+                continue;
+            // try removing this literal
+            Lit = pCubeMin->Lits[i]; pCubeMin->Lits[i] = -1;
+            RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, p->pPars->nConfLimit );
+            if ( RetValue == -1 )
+            {
+                Pdr_SetDeref( pCubeMin );
+                return -1;
+            }
+            pCubeMin->Lits[i] = Lit;
+            if ( RetValue == 0 )
+                continue;
+
+            // remove j-th entry
+            for ( n = j; n < pCubeMin->nLits-1; n++ )
+                pOrder[n] = pOrder[n+1];
+            j--;
+
+            // success - update the cube
+            pCubeMin = Pdr_SetCreateFrom( pCubeTmp = pCubeMin, i );
+            Pdr_SetDeref( pCubeTmp );
+            assert( pCubeMin->nLits > 0 );
+            i--;
+
+            // get the ordering by decreasing priorit
+            pOrder = Pdr_ManSortByPriority( p, pCubeMin );
+        }
+    }
+
+    assert( ppCubeMin != NULL );
+    *ppCubeMin = pCubeMin;
+    p->tGeneral += Abc_Clock() - clk;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the state could be blocked.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ManBlockCube( Pdr_Man_t * p, Pdr_Set_t * pCube )
+{
+    Pdr_Obl_t * pThis;
+    Pdr_Set_t * pPred, * pCubeMin;
+    int i, k, RetValue, Prio = ABC_INFINITY, Counter = 0;
+    int kMax = Vec_PtrSize(p->vSolvers)-1;
+    abctime clk;
+    p->nBlocks++;
+    // create first proof obligation
+//    assert( p->pQueue == NULL );
+    pThis = Pdr_OblStart( kMax, Prio--, pCube, NULL ); // consume ref
+    Pdr_QueuePush( p, pThis );
+    // try to solve it recursively
+    while ( !Pdr_QueueIsEmpty(p) )
+    {
+        Counter++;
+        pThis = Pdr_QueueHead( p );
+        if ( pThis->iFrame == 0 )
+            return 0; // SAT
+        if ( pThis->iFrame > kMax ) // finished this level
+            return 1;
+        if ( p->nQueLim && p->nQueCur >= p->nQueLim )
+        {
+            p->nQueLim = p->nQueLim * 3 / 2;
+            Pdr_QueueStop( p );
+            return 1; // restart
+        }
+        pThis = Pdr_QueuePop( p );
+        assert( pThis->iFrame > 0 );
+        assert( !Pdr_SetIsInit(pThis->pState, -1) );
+        p->iUseFrame = Abc_MinInt( p->iUseFrame, pThis->iFrame );
+        clk = Abc_Clock();
+        if ( Pdr_ManCheckContainment( p, pThis->iFrame, pThis->pState ) )
+        {
+            p->tContain += Abc_Clock() - clk;
+            Pdr_OblDeref( pThis );
+            continue;
+        }
+        p->tContain += Abc_Clock() - clk;
+
+        // check if the cube is already contained
+        RetValue = Pdr_ManCheckCubeCs( p, pThis->iFrame, pThis->pState );
+        if ( RetValue == -1 ) // resource limit is reached
+        {
+            Pdr_OblDeref( pThis );
+            return -1;
+        }
+        if ( RetValue ) // cube is blocked by clauses in this frame
+        {
+            Pdr_OblDeref( pThis );
+            continue;
+        }
+
+        // check if the cube holds with relative induction
+        pCubeMin = NULL;
+        RetValue = Pdr_ManGeneralize( p, pThis->iFrame-1, pThis->pState, &pPred, &pCubeMin );
+        if ( RetValue == -1 ) // resource limit is reached
+        {
+            Pdr_OblDeref( pThis );
+            return -1;
+        }
+        if ( RetValue ) // cube is blocked inductively in this frame
+        {
+            assert( pCubeMin != NULL );
+            // k is the last frame where pCubeMin holds
+            k = pThis->iFrame;
+            // check other frames
+            assert( pPred == NULL );
+            for ( k = pThis->iFrame; k < kMax; k++ )
+            {
+                RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, 0 );
+                if ( RetValue == -1 )
+                {
+                    Pdr_OblDeref( pThis );
+                    return -1;
+                }
+                if ( !RetValue )
+                    break;
+            }
+            // add new clause
+            if ( p->pPars->fVeryVerbose )
+            {
+                Abc_Print( 1, "Adding cube " );
+                Pdr_SetPrint( stdout, pCubeMin, Aig_ManRegNum(p->pAig), NULL );
+                Abc_Print( 1, " to frame %d.\n", k );
+            }
+            // set priority flops
+            for ( i = 0; i < pCubeMin->nLits; i++ )
+            {
+                assert( pCubeMin->Lits[i] >= 0 );
+                assert( (pCubeMin->Lits[i] / 2) < Aig_ManRegNum(p->pAig) );
+                Vec_IntAddToEntry( p->vPrio, pCubeMin->Lits[i] / 2, 1 );
+            }
+            Vec_VecPush( p->vClauses, k, pCubeMin );   // consume ref
+            p->nCubes++;
+            // add clause
+            for ( i = 1; i <= k; i++ )
+                Pdr_ManSolverAddClause( p, i, pCubeMin );
+            // schedule proof obligation
+            if ( (k < kMax || p->pPars->fReuseProofOblig) && !p->pPars->fShortest )
+            {
+                pThis->iFrame = k+1;
+                pThis->prio   = Prio--;
+                Pdr_QueuePush( p, pThis );
+            }
+            else
+            {
+                Pdr_OblDeref( pThis );
+            }
+        }
+        else
+        {
+            assert( pCubeMin == NULL );
+            assert( pPred != NULL );
+            pThis->prio = Prio--;
+            Pdr_QueuePush( p, pThis );
+            pThis = Pdr_OblStart( pThis->iFrame-1, Prio--, pPred, Pdr_OblRef(pThis) );
+            Pdr_QueuePush( p, pThis );
+        }
+
+        // check termination
+        if ( p->pPars->pFuncStop && p->pPars->pFuncStop(p->pPars->RunId) )
+            return -1;
+        if ( p->timeToStop && Abc_Clock() > p->timeToStop )
+            return -1;
+        if ( p->timeToStopOne && Abc_Clock() > p->timeToStopOne )
+            return -1;
+        if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC )
+            return -1;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ManSolveInt( Pdr_Man_t * p )
+{
+    int fPrintClauses = 0;
+    Pdr_Set_t * pCube = NULL;
+    Aig_Obj_t * pObj;
+    Abc_Cex_t * pCexNew;
+    int k, RetValue = -1;
+    int nOutDigits = Abc_Base10Log( Saig_ManPoNum(p->pAig) );
+    abctime clkStart = Abc_Clock(), clkOne = 0;
+    p->timeToStop = p->pPars->nTimeOut ? p->pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0;
+    assert( Vec_PtrSize(p->vSolvers) == 0 );
+    // in the multi-output mode, mark trivial POs (those fed by const0) as solved 
+    if ( p->pPars->fSolveAll )
+        Saig_ManForEachPo( p->pAig, pObj, k )
+            if ( Aig_ObjChild0(pObj) == Aig_ManConst0(p->pAig) )
+            {
+                Vec_IntWriteEntry( p->pPars->vOutMap, k, 1 ); // unsat
+                p->pPars->nProveOuts++;
+                if ( p->pPars->fUseBridge )
+                    Gia_ManToBridgeResult( stdout, 1, NULL, k );
+            }
+    // create the first timeframe
+    p->pPars->timeLastSolved = Abc_Clock();
+    Pdr_ManCreateSolver( p, (k = 0) );
+    while ( 1 )
+    {
+        p->nFrames = k;
+        assert( k == Vec_PtrSize(p->vSolvers)-1 );
+        p->iUseFrame = Abc_MaxInt(k, 1);
+        Saig_ManForEachPo( p->pAig, pObj, p->iOutCur )
+        {
+            // skip disproved outputs
+            if ( p->vCexes && Vec_PtrEntry(p->vCexes, p->iOutCur) )
+                continue;
+            // skip output whose time has run out
+            if ( p->pTime4Outs && p->pTime4Outs[p->iOutCur] == 0 )
+                continue;
+            // check if the output is trivially solved
+            if ( Aig_ObjChild0(pObj) == Aig_ManConst0(p->pAig) )
+                continue;
+            // check if the output is trivially solved
+            if ( Aig_ObjChild0(pObj) == Aig_ManConst1(p->pAig) )
+            {
+                if ( !p->pPars->fSolveAll )
+                {
+                    pCexNew = Abc_CexMakeTriv( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Saig_ManPoNum(p->pAig), k*Saig_ManPoNum(p->pAig)+p->iOutCur );
+                    p->pAig->pSeqModel = pCexNew;
+                    return 0; // SAT
+                }
+                pCexNew = (p->pPars->fUseBridge || p->pPars->fStoreCex) ? Abc_CexMakeTriv( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Saig_ManPoNum(p->pAig), k*Saig_ManPoNum(p->pAig)+p->iOutCur ) : (Abc_Cex_t *)(ABC_PTRINT_T)1;
+                p->pPars->nFailOuts++;
+                if ( p->pPars->vOutMap ) Vec_IntWriteEntry( p->pPars->vOutMap, p->iOutCur, 0 );
+                Abc_Print( 1, "Output %*d was trivially asserted in frame %2d (solved %*d out of %*d outputs).\n",
+                    nOutDigits, p->iOutCur, k, nOutDigits, p->pPars->nFailOuts, nOutDigits, Saig_ManPoNum(p->pAig) );
+                assert( Vec_PtrEntry(p->vCexes, p->iOutCur) == NULL );
+                if ( p->pPars->fUseBridge )
+                    Gia_ManToBridgeResult( stdout, 0, pCexNew, pCexNew->iPo );
+                Vec_PtrWriteEntry( p->vCexes, p->iOutCur, pCexNew );
+                if ( p->pPars->pFuncOnFail && p->pPars->pFuncOnFail(p->iOutCur, p->pPars->fStoreCex ? (Abc_Cex_t *)Vec_PtrEntry(p->vCexes, p->iOutCur) : NULL) )
+                {
+                    if ( p->pPars->fVerbose )
+                        Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
+                    if ( !p->pPars->fSilent )
+                        Abc_Print( 1, "Quitting due to callback on fail.\n" );
+                    p->pPars->iFrame = k;
+                    return -1;
+                }
+                if ( p->pPars->nFailOuts + p->pPars->nDropOuts == Saig_ManPoNum(p->pAig) )
+                    return p->pPars->nFailOuts ? 0 : -1; // SAT or UNDEC
+                p->pPars->timeLastSolved = Abc_Clock();
+                continue;
+            }
+            // try to solve this output
+            if ( p->pTime4Outs )
+            {
+                assert( p->pTime4Outs[p->iOutCur] > 0 );
+                clkOne = Abc_Clock();
+                p->timeToStopOne = p->pTime4Outs[p->iOutCur] + Abc_Clock();
+            }
+            while ( 1 )
+            {
+                if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC )
+                {
+                    if ( p->pPars->fVerbose )
+                        Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
+                    if ( !p->pPars->fSilent )
+                        Abc_Print( 1, "Reached gap timeout (%d seconds).\n",  p->pPars->nTimeOutGap );
+                    p->pPars->iFrame = k;
+                    return -1;
+                }
+                RetValue = Pdr_ManCheckCube( p, k, NULL, &pCube, p->pPars->nConfLimit );
+                if ( RetValue == 1 )
+                    break;
+                if ( RetValue == -1 )
+                {
+                    if ( p->pPars->fVerbose )
+                        Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
+                    if ( p->timeToStop && Abc_Clock() > p->timeToStop )
+                        Abc_Print( 1, "Reached timeout (%d seconds).\n",  p->pPars->nTimeOut );
+                    else if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC )
+                        Abc_Print( 1, "Reached gap timeout (%d seconds).\n",  p->pPars->nTimeOutGap );
+                    else if ( p->timeToStopOne && Abc_Clock() > p->timeToStopOne )
+                    {
+                        Pdr_QueueClean( p );
+                        pCube = NULL;
+                        break; // keep solving
+                    }
+                    else if ( p->pPars->nConfLimit )
+                        Abc_Print( 1, "Reached conflict limit (%d).\n",  p->pPars->nConfLimit );
+                    else if ( p->pPars->fVerbose )
+                        Abc_Print( 1, "Computation cancelled by the callback.\n" );
+                    p->pPars->iFrame = k;
+                    return -1;
+                }
+                if ( RetValue == 0 )
+                {
+                    RetValue = Pdr_ManBlockCube( p, pCube );
+                    if ( RetValue == -1 )
+                    {
+                        if ( p->pPars->fVerbose )
+                            Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
+                        if ( p->timeToStop && Abc_Clock() > p->timeToStop )
+                            Abc_Print( 1, "Reached timeout (%d seconds).\n",  p->pPars->nTimeOut );
+                        else if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC )
+                            Abc_Print( 1, "Reached gap timeout (%d seconds).\n",  p->pPars->nTimeOutGap );
+                        else if ( p->timeToStopOne && Abc_Clock() > p->timeToStopOne )
+                        {
+                            Pdr_QueueClean( p );
+                            pCube = NULL;
+                            break; // keep solving
+                        }
+                        else if ( p->pPars->nConfLimit )
+                            Abc_Print( 1, "Reached conflict limit (%d).\n",  p->pPars->nConfLimit );
+                        else if ( p->pPars->fVerbose )
+                            Abc_Print( 1, "Computation cancelled by the callback.\n" );
+                        p->pPars->iFrame = k;
+                        return -1;
+                    }
+                    if ( RetValue == 0 )
+                    {
+                        if ( fPrintClauses )
+                        {
+                            Abc_Print( 1, "*** Clauses after frame %d:\n", k );
+                            Pdr_ManPrintClauses( p, 0 );
+                        }
+                        if ( p->pPars->fVerbose )
+                            Pdr_ManPrintProgress( p, !p->pPars->fSolveAll, Abc_Clock() - clkStart );
+                        p->pPars->iFrame = k;
+                        if ( !p->pPars->fSolveAll )
+                        {
+                            p->pAig->pSeqModel = Pdr_ManDeriveCex(p);
+                            return 0; // SAT
+                        }
+                        p->pPars->nFailOuts++;
+                        pCexNew = (p->pPars->fUseBridge || p->pPars->fStoreCex) ? Pdr_ManDeriveCex(p) : (Abc_Cex_t *)(ABC_PTRINT_T)1;
+                        if ( p->pPars->vOutMap ) Vec_IntWriteEntry( p->pPars->vOutMap, p->iOutCur, 0 );
+                        assert( Vec_PtrEntry(p->vCexes, p->iOutCur) == NULL );
+                        if ( p->pPars->fUseBridge )
+                            Gia_ManToBridgeResult( stdout, 0, pCexNew, pCexNew->iPo );
+                        Vec_PtrWriteEntry( p->vCexes, p->iOutCur, pCexNew );
+                        if ( p->pPars->pFuncOnFail && p->pPars->pFuncOnFail(p->iOutCur, p->pPars->fStoreCex ? (Abc_Cex_t *)Vec_PtrEntry(p->vCexes, p->iOutCur) : NULL) )
+                        {
+                            if ( p->pPars->fVerbose )
+                                Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
+                            if ( !p->pPars->fSilent )
+                                Abc_Print( 1, "Quitting due to callback on fail.\n" );
+                            p->pPars->iFrame = k;
+                            return -1;
+                        }
+                        if ( !p->pPars->fNotVerbose )
+                            Abc_Print( 1, "Output %*d was asserted in frame %2d (%2d) (solved %*d out of %*d outputs).\n",
+                                nOutDigits, p->iOutCur, k, k, nOutDigits, p->pPars->nFailOuts, nOutDigits, Saig_ManPoNum(p->pAig) );
+                        if ( p->pPars->nFailOuts == Saig_ManPoNum(p->pAig) )
+                            return 0; // all SAT
+                        Pdr_QueueClean( p );
+                        pCube = NULL;
+                        break; // keep solving
+                    }
+                    if ( p->pPars->fVerbose )
+                        Pdr_ManPrintProgress( p, 0, Abc_Clock() - clkStart );
+                }
+            }
+            if ( p->pTime4Outs )
+            {
+                abctime timeSince = Abc_Clock() - clkOne;
+                assert( p->pTime4Outs[p->iOutCur] > 0 );
+                p->pTime4Outs[p->iOutCur] = (p->pTime4Outs[p->iOutCur] > timeSince) ? p->pTime4Outs[p->iOutCur] - timeSince : 0;
+                if ( p->pTime4Outs[p->iOutCur] == 0 && Vec_PtrEntry(p->vCexes, p->iOutCur) == NULL ) // undecided
+                {
+                    p->pPars->nDropOuts++;
+                    if ( p->pPars->vOutMap ) 
+                        Vec_IntWriteEntry( p->pPars->vOutMap, p->iOutCur, -1 );
+                    if ( !p->pPars->fNotVerbose ) 
+                        Abc_Print( 1, "Timing out on output %*d.\n", nOutDigits, p->iOutCur );
+                }
+                p->timeToStopOne = 0;
+            }
+        }
+
+        if ( p->pPars->fVerbose )
+            Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
+        // open a new timeframe
+        p->nQueLim = p->pPars->nRestLimit;
+        assert( pCube == NULL );
+        Pdr_ManSetPropertyOutput( p, k );
+        Pdr_ManCreateSolver( p, ++k );
+        if ( fPrintClauses )
+        {
+            Abc_Print( 1, "*** Clauses after frame %d:\n", k );
+            Pdr_ManPrintClauses( p, 0 );
+        }
+        // push clauses into this timeframe
+        RetValue = Pdr_ManPushClauses( p );
+        if ( RetValue == -1 )
+        {
+            if ( p->pPars->fVerbose )
+                Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
+            if ( !p->pPars->fSilent )
+            {
+                if ( p->timeToStop && Abc_Clock() > p->timeToStop )
+                    Abc_Print( 1, "Reached timeout (%d seconds).\n",  p->pPars->nTimeOut );
+                else
+                    Abc_Print( 1, "Reached conflict limit (%d).\n",  p->pPars->nConfLimit );
+            }
+            p->pPars->iFrame = k;
+            return -1;
+        }
+        if ( RetValue )
+        {
+            if ( p->pPars->fVerbose )
+                Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
+            if ( !p->pPars->fSilent )
+                Pdr_ManReportInvariant( p );
+            if ( !p->pPars->fSilent )
+                Pdr_ManVerifyInvariant( p );
+            p->pPars->iFrame = k;
+            // count the number of UNSAT outputs
+            p->pPars->nProveOuts = Saig_ManPoNum(p->pAig) - p->pPars->nFailOuts - p->pPars->nDropOuts;
+            // convert previously 'unknown' into 'unsat'
+            if ( p->pPars->vOutMap )
+                for ( k = 0; k < Saig_ManPoNum(p->pAig); k++ )
+                    if ( Vec_IntEntry(p->pPars->vOutMap, k) == -2 ) // unknown
+                    {
+                        Vec_IntWriteEntry( p->pPars->vOutMap, k, 1 ); // unsat
+                        if ( p->pPars->fUseBridge )
+                            Gia_ManToBridgeResult( stdout, 1, NULL, k );
+                    }
+            if ( p->pPars->nProveOuts == Saig_ManPoNum(p->pAig) )
+                return 1; // UNSAT
+            if ( p->pPars->nFailOuts > 0 )
+                return 0; // SAT
+            return -1;
+        }
+        if ( p->pPars->fVerbose )
+            Pdr_ManPrintProgress( p, 0, Abc_Clock() - clkStart );
+
+        // check termination
+        if ( p->pPars->pFuncStop && p->pPars->pFuncStop(p->pPars->RunId) )
+        {
+            p->pPars->iFrame = k;
+            return -1;
+        }
+        if ( p->timeToStop && Abc_Clock() > p->timeToStop )
+        {
+            if ( fPrintClauses )
+            {
+                Abc_Print( 1, "*** Clauses after frame %d:\n", k );
+                Pdr_ManPrintClauses( p, 0 );
+            }
+            if ( p->pPars->fVerbose )
+                Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
+            if ( !p->pPars->fSilent )
+                Abc_Print( 1, "Reached timeout (%d seconds).\n",  p->pPars->nTimeOut );
+            p->pPars->iFrame = k;
+            return -1;
+        }
+        if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC )
+        {
+            if ( fPrintClauses )
+            {
+                Abc_Print( 1, "*** Clauses after frame %d:\n", k );
+                Pdr_ManPrintClauses( p, 0 );
+            }
+            if ( p->pPars->fVerbose )
+                Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
+            if ( !p->pPars->fSilent )
+                Abc_Print( 1, "Reached gap timeout (%d seconds).\n",  p->pPars->nTimeOutGap );
+            p->pPars->iFrame = k;
+            return -1;
+        }
+        if ( p->pPars->nFrameMax && k >= p->pPars->nFrameMax )
+        {
+            if ( p->pPars->fVerbose )
+                Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
+            if ( !p->pPars->fSilent )
+                Abc_Print( 1, "Reached limit on the number of timeframes (%d).\n", p->pPars->nFrameMax );
+            p->pPars->iFrame = k;
+            return -1;
+        }
+    }
+    assert( 0 );
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ManSolve( Aig_Man_t * pAig, Pdr_Par_t * pPars )
+{
+    Pdr_Man_t * p;
+    int k, RetValue;
+    abctime clk = Abc_Clock();
+    if ( pPars->nTimeOutOne && !pPars->fSolveAll )
+        pPars->nTimeOutOne = 0;
+    if ( pPars->nTimeOutOne && pPars->nTimeOut == 0 )
+        pPars->nTimeOut = pPars->nTimeOutOne * Saig_ManPoNum(pAig) / 1000 + (int)((pPars->nTimeOutOne * Saig_ManPoNum(pAig) % 1000) > 0);
+    if ( pPars->fVerbose )
+    {
+//    Abc_Print( 1, "Running PDR by Niklas Een (aka IC3 by Aaron Bradley) with these parameters:\n" );
+        Abc_Print( 1, "VarMax = %d. FrameMax = %d. QueMax = %d. TimeMax = %d. ",
+            pPars->nRecycle,
+            pPars->nFrameMax,
+            pPars->nRestLimit,
+            pPars->nTimeOut );
+        Abc_Print( 1, "MonoCNF = %s. SkipGen = %s. SolveAll = %s.\n",
+            pPars->fMonoCnf ?     "yes" : "no",
+            pPars->fSkipGeneral ? "yes" : "no",
+            pPars->fSolveAll ?    "yes" : "no" );
+    }
+    ABC_FREE( pAig->pSeqModel );
+    p = Pdr_ManStart( pAig, pPars, NULL );
+    RetValue = Pdr_ManSolveInt( p );
+    if ( RetValue == 0 )
+        assert( pAig->pSeqModel != NULL || p->vCexes != NULL );
+    if ( p->vCexes )
+    {
+        assert( p->pAig->vSeqModelVec == NULL );
+        p->pAig->vSeqModelVec = p->vCexes;
+        p->vCexes = NULL;
+    }
+    if ( p->pPars->fDumpInv )
+        Pdr_ManDumpClauses( p, (char *)"inv.pla", RetValue==1 );
+    p->tTotal += Abc_Clock() - clk;
+    Pdr_ManStop( p );
+    pPars->iFrame--;
+    // convert all -2 (unknown) entries into -1 (undec)
+    if ( pPars->vOutMap )
+        for ( k = 0; k < Saig_ManPoNum(pAig); k++ )
+            if ( Vec_IntEntry(pPars->vOutMap, k) == -2 ) // unknown
+                Vec_IntWriteEntry( pPars->vOutMap, k, -1 ); // undec
+    if ( pPars->fUseBridge )
+        Gia_ManToBridgeAbort( stdout, 7, (unsigned char *)"timeout" );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/pdr/pdrInt.h b/abc-build/src/proof/pdr/pdrInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/pdr/pdrInt.h
@@ -0,0 +1,220 @@
+/**CFile****************************************************************
+
+  FileName    [pdrInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Property driven reachability.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 20, 2010.]
+
+  Revision    [$Id: pdrInt.h,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__sat__pdr__pdrInt_h
+#define ABC__sat__pdr__pdrInt_h
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "aig/saig/saig.h"
+#include "misc/vec/vecWec.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver.h"
+#include "pdr.h" 
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+             
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Pdr_Set_t_ Pdr_Set_t;
+struct Pdr_Set_t_
+{
+    word        Sign;      // signature
+    int         nRefs;     // ref counter
+    int         nTotal;    // total literals
+    int         nLits;     // num flop literals
+    int         Lits[0];
+};
+
+typedef struct Pdr_Obl_t_ Pdr_Obl_t;
+struct Pdr_Obl_t_
+{
+    int         iFrame;    // time frame
+    int         prio;      // priority
+    int         nRefs;     // reference counter
+    Pdr_Set_t * pState;    // state cube
+    Pdr_Obl_t * pNext;     // next one
+    Pdr_Obl_t * pLink;     // queue link
+};
+
+typedef struct Pdr_Man_t_ Pdr_Man_t;
+struct Pdr_Man_t_
+{
+    // input problem
+    Pdr_Par_t * pPars;     // parameters
+    Aig_Man_t * pAig;      // user's AIG
+    // static CNF representation
+    Cnf_Man_t * pCnfMan;   // CNF manager
+    Cnf_Dat_t * pCnf1;     // CNF for this AIG
+    Vec_Int_t * vVar2Reg;  // mapping of SAT var into registers
+    // dynamic CNF representation
+    Cnf_Dat_t * pCnf2;     // CNF for this AIG
+    Vec_Int_t * pvId2Vars; // for each used ObjId, maps frame into SAT var
+    Vec_Ptr_t   vVar2Ids;  // for each used frame, maps SAT var into ObjId
+    Vec_Wec_t * vVLits;    // CNF literals
+    // data representation
+    int         iOutCur;   // current output
+    Vec_Ptr_t * vCexes;    // counter-examples for each output
+    Vec_Ptr_t * vSolvers;  // SAT solvers
+    Vec_Vec_t * vClauses;  // clauses by timeframe
+    Pdr_Obl_t * pQueue;    // proof obligations
+    int *       pOrder;    // ordering of the lits
+    Vec_Int_t * vActVars;  // the counter of activation variables
+    int         iUseFrame; // the first used frame
+    // internal use
+    Vec_Int_t * vPrio;     // priority flops
+    Vec_Int_t * vLits;     // array of literals
+    Vec_Int_t * vCiObjs;   // cone leaves
+    Vec_Int_t * vCoObjs;   // cone roots
+    Vec_Int_t * vCiVals;   // cone leaf values
+    Vec_Int_t * vCoVals;   // cone root values
+    Vec_Int_t * vNodes;    // cone nodes
+    Vec_Int_t * vUndo;     // cone undos
+    Vec_Int_t * vVisits;   // intermediate
+    Vec_Int_t * vCi2Rem;   // CIs to be removed
+    Vec_Int_t * vRes;      // final result
+    Vec_Int_t * vSuppLits; // support literals
+    Pdr_Set_t * pCubeJust; // justification
+    abctime *   pTime4Outs;// timeout per output
+    // statistics
+    int         nBlocks;   // the number of times blockState was called
+    int         nObligs;   // the number of proof obligations derived
+    int         nCubes;    // the number of cubes derived
+    int         nCalls;    // the number of SAT calls
+    int         nCallsS;   // the number of SAT calls (sat)
+    int         nCallsU;   // the number of SAT calls (unsat)
+    int         nStarts;   // the number of SAT solver restarts
+    int         nFrames;   // frames explored
+    int         nCasesSS;
+    int         nCasesSU;
+    int         nCasesUS;
+    int         nCasesUU;
+    int         nQueCur;
+    int         nQueMax;
+    int         nQueLim;
+    // runtime
+    abctime     timeToStop;
+    abctime     timeToStopOne;
+    // time stats
+    abctime     tSat;
+    abctime     tSatSat;
+    abctime     tSatUnsat;
+    abctime     tGeneral;
+    abctime     tPush;
+    abctime     tTsim;
+    abctime     tContain;
+    abctime     tCnf;
+    abctime     tTotal;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline sat_solver * Pdr_ManSolver( Pdr_Man_t * p, int k )  { return (sat_solver *)Vec_PtrEntry(p->vSolvers, k); }
+
+static inline abctime      Pdr_ManTimeLimit( Pdr_Man_t * p )
+{
+    if ( p->timeToStop == 0 )
+        return p->timeToStopOne;
+    if ( p->timeToStopOne == 0 )
+        return p->timeToStop;
+    if ( p->timeToStop < p->timeToStopOne )
+        return p->timeToStop;
+    return p->timeToStopOne;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== pdrCex.c ==========================================================*/
+extern Abc_Cex_t *     Pdr_ManDeriveCex( Pdr_Man_t * p );
+/*=== pdrCnf.c ==========================================================*/
+extern int             Pdr_ObjSatVar( Pdr_Man_t * p, int k, int Pol, Aig_Obj_t * pObj );
+extern int             Pdr_ObjRegNum( Pdr_Man_t * p, int k, int iSatVar );
+extern int             Pdr_ManFreeVar( Pdr_Man_t * p, int k );
+extern sat_solver *    Pdr_ManNewSolver( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit );
+/*=== pdrCore.c ==========================================================*/
+extern int             Pdr_ManCheckContainment( Pdr_Man_t * p, int k, Pdr_Set_t * pSet );
+/*=== pdrInv.c ==========================================================*/
+extern void            Pdr_ManPrintProgress( Pdr_Man_t * p, int fClose, abctime Time );
+extern void            Pdr_ManPrintClauses( Pdr_Man_t * p, int kStart );
+extern void            Pdr_ManDumpClauses( Pdr_Man_t * p, char * pFileName, int fProved );
+extern void            Pdr_ManReportInvariant( Pdr_Man_t * p );
+extern void            Pdr_ManVerifyInvariant( Pdr_Man_t * p );
+/*=== pdrMan.c ==========================================================*/
+extern Pdr_Man_t *     Pdr_ManStart( Aig_Man_t * pAig, Pdr_Par_t * pPars, Vec_Int_t * vPrioInit );
+extern void            Pdr_ManStop( Pdr_Man_t * p );
+extern Abc_Cex_t *     Pdr_ManDeriveCex( Pdr_Man_t * p );
+/*=== pdrSat.c ==========================================================*/
+extern sat_solver *    Pdr_ManCreateSolver( Pdr_Man_t * p, int k );
+extern sat_solver *    Pdr_ManFetchSolver( Pdr_Man_t * p, int k );
+extern void            Pdr_ManSetPropertyOutput( Pdr_Man_t * p, int k );
+extern Vec_Int_t *     Pdr_ManCubeToLits( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, int fCompl, int fNext );
+extern Vec_Int_t *     Pdr_ManLitsToCube( Pdr_Man_t * p, int k, int * pArray, int nArray );
+extern void            Pdr_ManSolverAddClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube );
+extern void            Pdr_ManCollectValues( Pdr_Man_t * p, int k, Vec_Int_t * vObjIds, Vec_Int_t * vValues );
+extern int             Pdr_ManCheckCubeCs( Pdr_Man_t * p, int k, Pdr_Set_t * pCube );
+extern int             Pdr_ManCheckCube( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, int nConfLimit );
+/*=== pdrTsim.c ==========================================================*/
+extern Pdr_Set_t *     Pdr_ManTernarySim( Pdr_Man_t * p, int k, Pdr_Set_t * pCube );
+/*=== pdrUtil.c ==========================================================*/
+extern Pdr_Set_t *     Pdr_SetAlloc( int nSize );
+extern Pdr_Set_t *     Pdr_SetCreate( Vec_Int_t * vLits, Vec_Int_t * vPiLits );
+extern Pdr_Set_t *     Pdr_SetCreateFrom( Pdr_Set_t * pSet, int iRemove );
+extern Pdr_Set_t *     Pdr_SetCreateSubset( Pdr_Set_t * pSet, int * pLits, int nLits );
+extern Pdr_Set_t *     Pdr_SetDup( Pdr_Set_t * pSet );
+extern Pdr_Set_t *     Pdr_SetRef( Pdr_Set_t * p );
+extern void            Pdr_SetDeref( Pdr_Set_t * p );
+extern int             Pdr_SetContains( Pdr_Set_t * pOld, Pdr_Set_t * pNew );
+extern int             Pdr_SetContainsSimple( Pdr_Set_t * pOld, Pdr_Set_t * pNew );
+extern int             Pdr_SetIsInit( Pdr_Set_t * p, int iRemove );
+extern void            Pdr_SetPrint( FILE * pFile, Pdr_Set_t * p, int nRegs, Vec_Int_t * vFlopCounts );
+extern int             Pdr_SetCompare( Pdr_Set_t ** pp1, Pdr_Set_t ** pp2 );
+extern Pdr_Obl_t *     Pdr_OblStart( int k, int prio, Pdr_Set_t * pState, Pdr_Obl_t * pNext );
+extern Pdr_Obl_t *     Pdr_OblRef( Pdr_Obl_t * p );
+extern void            Pdr_OblDeref( Pdr_Obl_t * p );
+extern int             Pdr_QueueIsEmpty( Pdr_Man_t * p );
+extern Pdr_Obl_t *     Pdr_QueueHead( Pdr_Man_t * p );
+extern Pdr_Obl_t *     Pdr_QueuePop( Pdr_Man_t * p );
+extern void            Pdr_QueueClean( Pdr_Man_t * p );
+extern void            Pdr_QueuePush( Pdr_Man_t * p, Pdr_Obl_t * pObl );
+extern void            Pdr_QueuePrint( Pdr_Man_t * p );
+extern void            Pdr_QueueStop( Pdr_Man_t * p );
+extern int             Pdr_ManCubeJust( Pdr_Man_t * p, int k, Pdr_Set_t * pCube );
+
+ABC_NAMESPACE_HEADER_END
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/pdr/pdrInv.c b/abc-build/src/proof/pdr/pdrInv.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/pdr/pdrInv.c
@@ -0,0 +1,458 @@
+/**CFile****************************************************************
+
+  FileName    [pdrInv.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Property driven reachability.]
+
+  Synopsis    [Invariant computation, printing, verification.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 20, 2010.]
+
+  Revision    [$Id: pdrInv.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "pdrInt.h"
+#include "base/abc/abc.h"      // for Abc_NtkCollectCioNames()
+#include "base/main/main.h"    // for Abc_FrameReadGlobalFrame()
+#include "aig/ioa/ioa.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_ManPrintProgress( Pdr_Man_t * p, int fClose, abctime Time )
+{
+    Vec_Ptr_t * vVec;
+    int i, ThisSize, Length, LengthStart;
+    if ( Vec_PtrSize(p->vSolvers) < 2 )
+        return;
+    if ( Abc_FrameIsBatchMode() && !fClose )
+        return;
+    // count the total length of the printout
+    Length = 0;
+    Vec_VecForEachLevel( p->vClauses, vVec, i )
+        Length += 1 + Abc_Base10Log(Vec_PtrSize(vVec)+1);
+    // determine the starting point
+    LengthStart = Abc_MaxInt( 0, Length - 60 );
+    Abc_Print( 1, "%3d :", Vec_PtrSize(p->vSolvers)-1 );
+    ThisSize = 5;
+    if ( LengthStart > 0 )
+    {
+        Abc_Print( 1, " ..." );
+        ThisSize += 4;
+    }
+    Length = 0;
+    Vec_VecForEachLevel( p->vClauses, vVec, i )
+    {
+        if ( Length < LengthStart )
+        {
+            Length += 1 + Abc_Base10Log(Vec_PtrSize(vVec)+1);
+            continue;
+        }
+        Abc_Print( 1, " %d", Vec_PtrSize(vVec) );
+        Length += 1 + Abc_Base10Log(Vec_PtrSize(vVec)+1);
+        ThisSize += 1 + Abc_Base10Log(Vec_PtrSize(vVec)+1);
+    }
+    for ( i = ThisSize; i < 70; i++ )
+        Abc_Print( 1, " " );
+    Abc_Print( 1, "%6d", p->nQueMax );
+    Abc_Print( 1, "%10.2f sec", 1.0*Time/CLOCKS_PER_SEC );
+    if ( p->pPars->fSolveAll )
+        Abc_Print( 1, "  CEX =%4d", p->pPars->nFailOuts );
+    if ( p->pPars->nTimeOutOne )
+        Abc_Print( 1, "  T/O =%3d", p->pPars->nDropOuts );
+    Abc_Print( 1, "%s", fClose ? "\n":"\r" );
+    if ( fClose )
+        p->nQueMax = 0;
+    fflush( stdout );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts how many times each flop appears in the set of cubes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Pdr_ManCountFlops( Pdr_Man_t * p, Vec_Ptr_t * vCubes )
+{
+    Vec_Int_t * vFlopCount;
+    Pdr_Set_t * pCube;
+    int i, n;
+    vFlopCount = Vec_IntStart( Aig_ManRegNum(p->pAig) );
+    Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i )
+        for ( n = 0; n < pCube->nLits; n++ )
+        {
+            assert( pCube->Lits[n] >= 0 && pCube->Lits[n] < 2*Aig_ManRegNum(p->pAig) );
+            Vec_IntAddToEntry( vFlopCount, pCube->Lits[n] >> 1, 1 );
+        }
+    return vFlopCount;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ManFindInvariantStart( Pdr_Man_t * p )
+{
+    Vec_Ptr_t * vArrayK;
+    int k, kMax = Vec_PtrSize(p->vSolvers)-1;
+    Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, k, 1, kMax+1 )
+        if ( Vec_PtrSize(vArrayK) == 0 )
+            return k;
+//    return -1;
+    // if there is no starting point (as in case of SAT or undecided), return the last frame
+//    Abc_Print( 1, "The last timeframe contains %d clauses.\n", Vec_PtrSize(Vec_VecEntry(p->vClauses, kMax)) );
+    return kMax;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of variables used in the clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Pdr_ManCollectCubes( Pdr_Man_t * p, int kStart )
+{
+    Vec_Ptr_t * vResult;
+    Vec_Ptr_t * vArrayK;
+    Pdr_Set_t * pSet;
+    int i, j;
+    vResult = Vec_PtrAlloc( 100 );
+    Vec_VecForEachLevelStart( p->vClauses, vArrayK, i, kStart )
+        Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pSet, j )
+            Vec_PtrPush( vResult, pSet );
+    return vResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of variables used in the clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ManCountVariables( Pdr_Man_t * p, int kStart )
+{
+    Vec_Int_t * vFlopCounts;
+    Vec_Ptr_t * vCubes;
+    int i, Entry, Counter = 0;
+    vCubes = Pdr_ManCollectCubes( p, kStart );
+    vFlopCounts = Pdr_ManCountFlops( p, vCubes );
+    Vec_IntForEachEntry( vFlopCounts, Entry, i )
+        Counter += (Entry > 0);
+    Vec_IntFreeP( &vFlopCounts );
+    Vec_PtrFree( vCubes );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_ManPrintClauses( Pdr_Man_t * p, int kStart )
+{
+    Vec_Ptr_t * vArrayK;
+    Pdr_Set_t * pCube;
+    int i, k, Counter = 0;
+    Vec_VecForEachLevelStart( p->vClauses, vArrayK, k, kStart )
+    {
+        Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare );
+        Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCube, i )
+        {
+            Abc_Print( 1, "C=%4d. F=%4d ", Counter++, k );
+            Pdr_SetPrint( stdout, pCube, Aig_ManRegNum(p->pAig), NULL );  
+            Abc_Print( 1, "\n" ); 
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+void Pdr_SetPrintOne( Pdr_Set_t * p )
+{
+    int i;
+    printf( "Clause: {" );
+    for ( i = 0; i < p->nLits; i++ )
+        printf( " %s%d", Abc_LitIsCompl(p->Lits[i])? "!":"", Abc_Lit2Var(p->Lits[i]) );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+Aig_Man_t * Pdr_ManDupAigWithClauses( Aig_Man_t * p, Vec_Ptr_t * vCubes )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjNew, * pLit;
+    Pdr_Set_t * pCube;
+    int i, n;
+    // create the new manager
+    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    // create the PIs
+    Aig_ManCleanData( p );
+    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pNew );
+    // create outputs for each cube
+    Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i )
+    {
+//        Pdr_SetPrintOne( pCube );
+        pObjNew = Aig_ManConst1(pNew);
+        for ( n = 0; n < pCube->nLits; n++ )
+        {
+            assert( Abc_Lit2Var(pCube->Lits[n]) < Saig_ManRegNum(p) );
+            pLit = Aig_NotCond( Aig_ManCi(pNew, Saig_ManPiNum(p) + Abc_Lit2Var(pCube->Lits[n])), Abc_LitIsCompl(pCube->Lits[n]) );
+            pObjNew = Aig_And( pNew, pObjNew, pLit );
+        }
+        Aig_ObjCreateCo( pNew, pObjNew );
+    }
+    // duplicate internal nodes
+    Aig_ManForEachNode( p, pObj, i )
+        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // add the POs
+    Saig_ManForEachLi( p, pObj, i )
+        Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
+    Aig_ManCleanup( pNew );
+    Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+    // check the resulting network
+    if ( !Aig_ManCheck(pNew) )
+        printf( "Aig_ManDupSimple(): The check has failed.\n" );
+    return pNew;
+}
+void Pdr_ManDumpAig( Aig_Man_t * p, Vec_Ptr_t * vCubes )
+{
+    Aig_Man_t * pNew = Pdr_ManDupAigWithClauses( p, vCubes );
+    Ioa_WriteAiger( pNew, "aig_with_clauses.aig", 0, 0 );
+    Aig_ManStop( pNew );
+    printf( "Dumped modified AIG into file \"aig_with_clauses.aig\".\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+void Pdr_ManDumpClauses( Pdr_Man_t * p, char * pFileName, int fProved )
+{
+    int fUseSupp = 1;
+    FILE * pFile;
+    Vec_Int_t * vFlopCounts;
+    Vec_Ptr_t * vCubes;
+    Pdr_Set_t * pCube;
+    char ** pNamesCi;
+    int i, kStart;
+    // create file
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        Abc_Print( 1, "Cannot open file \"%s\" for writing invariant.\n", pFileName );
+        return;
+    } 
+    // collect cubes
+    kStart = Pdr_ManFindInvariantStart( p );
+    vCubes = Pdr_ManCollectCubes( p, kStart );
+    Vec_PtrSort( vCubes, (int (*)(void))Pdr_SetCompare );
+//    Pdr_ManDumpAig( p->pAig, vCubes );
+    // collect variable appearances
+    vFlopCounts = fUseSupp ? Pdr_ManCountFlops( p, vCubes ) : NULL; 
+    // output the header
+    if ( fProved )
+        fprintf( pFile, "# Inductive invariant for \"%s\"\n", p->pAig->pName );
+    else
+        fprintf( pFile, "# Clauses of the last timeframe for \"%s\"\n", p->pAig->pName );
+    fprintf( pFile, "# generated by PDR in ABC on %s\n", Aig_TimeStamp() );
+    fprintf( pFile, ".i %d\n", fUseSupp ? Pdr_ManCountVariables(p, kStart) : Aig_ManRegNum(p->pAig) );
+    fprintf( pFile, ".o 1\n" );
+    fprintf( pFile, ".p %d\n", Vec_PtrSize(vCubes) );
+    // output flop names
+    pNamesCi = Abc_NtkCollectCioNames( Abc_FrameReadNtk( Abc_FrameReadGlobalFrame() ), 0 );
+    if ( pNamesCi )
+    {
+        fprintf( pFile, ".ilb" );
+        for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ )
+            if ( !fUseSupp || Vec_IntEntry( vFlopCounts, i ) )
+                fprintf( pFile, " %s", pNamesCi[Saig_ManPiNum(p->pAig) + i] );
+        fprintf( pFile, "\n" );
+        ABC_FREE( pNamesCi );
+        fprintf( pFile, ".ob inv\n" );
+    }
+    // output cubes
+    Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i )
+    {
+        Pdr_SetPrint( pFile, pCube, Aig_ManRegNum(p->pAig), vFlopCounts );  
+        fprintf( pFile, " 1\n" ); 
+    }
+    fprintf( pFile, ".e\n\n" );
+    fclose( pFile );
+    Vec_IntFreeP( &vFlopCounts );
+    Vec_PtrFree( vCubes );
+    if ( fProved )
+        Abc_Print( 1, "Inductive invariant was written into file \"%s\".\n", pFileName );
+    else
+        Abc_Print( 1, "Clauses of the last timeframe were written into file \"%s\".\n", pFileName );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_ManReportInvariant( Pdr_Man_t * p )
+{
+    Vec_Ptr_t * vCubes;
+    int kStart = Pdr_ManFindInvariantStart( p );
+    vCubes = Pdr_ManCollectCubes( p, kStart );
+    Abc_Print( 1, "Invariant F[%d] : %d clauses with %d flops (out of %d)\n", 
+        kStart, Vec_PtrSize(vCubes), Pdr_ManCountVariables(p, kStart), Aig_ManRegNum(p->pAig) );
+    Vec_PtrFree( vCubes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_ManVerifyInvariant( Pdr_Man_t * p )
+{
+    sat_solver * pSat;
+    Vec_Int_t * vLits;
+    Vec_Ptr_t * vCubes;
+    Pdr_Set_t * pCube;
+    int i, kStart, kThis, RetValue, Counter = 0;
+    abctime clk = Abc_Clock();
+    // collect cubes used in the inductive invariant
+    kStart = Pdr_ManFindInvariantStart( p );
+    vCubes = Pdr_ManCollectCubes( p, kStart );
+    // create solver with the cubes
+    kThis = Vec_PtrSize(p->vSolvers);
+    pSat  = Pdr_ManCreateSolver( p, kThis );
+    // add the property output
+//    Pdr_ManSetPropertyOutput( p, kThis );
+    // add the clauses
+    Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i )
+    {
+        vLits = Pdr_ManCubeToLits( p, kThis, pCube, 1, 0 );
+        RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
+        assert( RetValue );
+        sat_solver_compress( pSat );
+    }
+    // check each clause
+    Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i )
+    {
+        vLits = Pdr_ManCubeToLits( p, kThis, pCube, 0, 1 );
+        RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 );
+        if ( RetValue != l_False )
+        {
+            Abc_Print( 1, "Verification of clause %d failed.\n", i );
+            Counter++;
+        }
+    }
+    if ( Counter )
+        Abc_Print( 1, "Verification of %d clauses has failed.\n", Counter );
+    else
+    {
+        Abc_Print( 1, "Verification of invariant with %d clauses was successful.  ", Vec_PtrSize(vCubes) );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+//    sat_solver_delete( pSat );
+    Vec_PtrFree( vCubes );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/pdr/pdrMan.c b/abc-build/src/proof/pdr/pdrMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/pdr/pdrMan.c
@@ -0,0 +1,223 @@
+/**CFile****************************************************************
+
+  FileName    [pdrMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Property driven reachability.]
+
+  Synopsis    [Manager procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 20, 2010.]
+
+  Revision    [$Id: pdrMan.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "pdrInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Pdr_Man_t * Pdr_ManStart( Aig_Man_t * pAig, Pdr_Par_t * pPars, Vec_Int_t * vPrioInit )
+{
+    Pdr_Man_t * p;
+    p = ABC_CALLOC( Pdr_Man_t, 1 );
+    p->pPars    = pPars;
+    p->pAig     = pAig;
+    p->vSolvers = Vec_PtrAlloc( 0 );
+    p->vClauses = Vec_VecAlloc( 0 );
+    p->pQueue   = NULL;
+    p->pOrder   = ABC_ALLOC( int, Aig_ManRegNum(pAig) );
+    p->vActVars = Vec_IntAlloc( 256 );
+    if ( !p->pPars->fMonoCnf )
+        p->vVLits   = Vec_WecStart( 1+Abc_MaxInt(1, Aig_ManLevels(pAig)) );
+    // internal use
+    p->vPrio    = vPrioInit ? vPrioInit : Vec_IntStart( Aig_ManRegNum(pAig) );  // priority flops
+    p->vLits    = Vec_IntAlloc( 100 );  // array of literals
+    p->vCiObjs  = Vec_IntAlloc( 100 );  // cone leaves
+    p->vCoObjs  = Vec_IntAlloc( 100 );  // cone roots
+    p->vCiVals  = Vec_IntAlloc( 100 );  // cone leaf values
+    p->vCoVals  = Vec_IntAlloc( 100 );  // cone root values
+    p->vNodes   = Vec_IntAlloc( 100 );  // cone nodes
+    p->vUndo    = Vec_IntAlloc( 100 );  // cone undos
+    p->vVisits  = Vec_IntAlloc( 100 );  // intermediate
+    p->vCi2Rem  = Vec_IntAlloc( 100 );  // CIs to be removed
+    p->vRes     = Vec_IntAlloc( 100 );  // final result
+    p->vSuppLits= Vec_IntAlloc( 100 );  // support literals
+    p->pCubeJust= Pdr_SetAlloc( Saig_ManRegNum(pAig) );
+    p->pCnfMan  = Cnf_ManStart();
+    // additional AIG data-members
+    if ( pAig->pFanData == NULL )
+        Aig_ManFanoutStart( pAig );
+    if ( pAig->pTerSimData == NULL )
+        pAig->pTerSimData = ABC_CALLOC( unsigned, 1 + (Aig_ManObjNumMax(pAig) / 16) );
+    // time spent on each outputs
+    if ( pPars->nTimeOutOne )
+    {
+        int i;
+        p->pTime4Outs = ABC_ALLOC( abctime, Saig_ManPoNum(pAig) );
+        for ( i = 0; i < Saig_ManPoNum(pAig); i++ )
+            p->pTime4Outs[i] = pPars->nTimeOutOne * CLOCKS_PER_SEC / 1000 + 1;
+    }
+    if ( pPars->fSolveAll )
+    {
+        p->vCexes = Vec_PtrStart( Saig_ManPoNum(p->pAig) );
+        p->pPars->vOutMap = Vec_IntAlloc( Saig_ManPoNum(pAig) );
+        Vec_IntFill( p->pPars->vOutMap, Saig_ManPoNum(pAig), -2 );
+    }
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_ManStop( Pdr_Man_t * p )
+{
+    Pdr_Set_t * pCla;
+    sat_solver * pSat;
+    int i, k;
+    Aig_ManCleanMarkAB( p->pAig );
+    if ( p->pPars->fVerbose ) 
+    {
+        Abc_Print( 1, "Block =%5d  Oblig =%6d  Clause =%6d  Call =%6d (sat=%.1f%%)  Start =%4d\n", 
+            p->nBlocks, p->nObligs, p->nCubes, p->nCalls, 100.0 * p->nCallsS / p->nCalls, p->nStarts );
+        ABC_PRTP( "SAT solving", p->tSat,       p->tTotal );
+        ABC_PRTP( "  unsat    ", p->tSatUnsat,  p->tTotal );
+        ABC_PRTP( "  sat      ", p->tSatSat,    p->tTotal );
+        ABC_PRTP( "Generalize ", p->tGeneral,   p->tTotal );
+        ABC_PRTP( "Push clause", p->tPush,      p->tTotal );
+        ABC_PRTP( "Ternary sim", p->tTsim,      p->tTotal );
+        ABC_PRTP( "Containment", p->tContain,   p->tTotal );
+        ABC_PRTP( "CNF compute", p->tCnf,       p->tTotal );
+        ABC_PRTP( "TOTAL      ", p->tTotal,     p->tTotal );
+        fflush( stdout );
+    }
+//    Abc_Print( 1, "SS =%6d. SU =%6d. US =%6d. UU =%6d.\n", p->nCasesSS, p->nCasesSU, p->nCasesUS, p->nCasesUU );
+    Vec_PtrForEachEntry( sat_solver *, p->vSolvers, pSat, i )
+        sat_solver_delete( pSat );
+    Vec_PtrFree( p->vSolvers );
+    Vec_VecForEachEntry( Pdr_Set_t *, p->vClauses, pCla, i, k )
+        Pdr_SetDeref( pCla );
+    Vec_VecFree( p->vClauses );
+    Pdr_QueueStop( p );
+    ABC_FREE( p->pOrder );
+    Vec_IntFree( p->vActVars );
+    // static CNF
+    Cnf_DataFree( p->pCnf1 );
+    Vec_IntFreeP( &p->vVar2Reg );
+    // dynamic CNF
+    Cnf_DataFree( p->pCnf2 );
+    if ( p->pvId2Vars )
+    for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ )
+        ABC_FREE( p->pvId2Vars[i].pArray );
+    ABC_FREE( p->pvId2Vars );
+//    Vec_VecFreeP( (Vec_Vec_t **)&p->vVar2Ids );
+    for ( i = 0; i < Vec_PtrSize(&p->vVar2Ids); i++ )
+        Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(&p->vVar2Ids, i) );
+    ABC_FREE( p->vVar2Ids.pArray );
+    Vec_WecFreeP( &p->vVLits );
+    // CNF manager
+    Cnf_ManStop( p->pCnfMan );
+    // internal use
+    Vec_IntFreeP( &p->vPrio   );  // priority flops
+    Vec_IntFree( p->vLits     );  // array of literals
+    Vec_IntFree( p->vCiObjs   );  // cone leaves
+    Vec_IntFree( p->vCoObjs   );  // cone roots
+    Vec_IntFree( p->vCiVals   );  // cone leaf values
+    Vec_IntFree( p->vCoVals   );  // cone root values
+    Vec_IntFree( p->vNodes    );  // cone nodes
+    Vec_IntFree( p->vUndo     );  // cone undos
+    Vec_IntFree( p->vVisits   );  // intermediate
+    Vec_IntFree( p->vCi2Rem   );  // CIs to be removed
+    Vec_IntFree( p->vRes      );  // final result
+    Vec_IntFree( p->vSuppLits );  // support literals
+    ABC_FREE( p->pCubeJust );
+    ABC_FREE( p->pTime4Outs );
+    if ( p->vCexes )
+        Vec_PtrFreeFree( p->vCexes );
+    // additional AIG data-members
+    if ( p->pAig->pFanData != NULL )
+        Aig_ManFanoutStop( p->pAig );
+    if ( p->pAig->pTerSimData != NULL )
+        ABC_FREE( p->pAig->pTerSimData );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Pdr_ManDeriveCex( Pdr_Man_t * p )
+{
+    Abc_Cex_t * pCex;
+    Pdr_Obl_t * pObl;
+    int i, f, Lit, nFrames = 0;
+    // count the number of frames
+    for ( pObl = p->pQueue; pObl; pObl = pObl->pNext )
+        nFrames++;
+    // create the counter-example
+    pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), nFrames );
+//    pCex->iPo    = (p->pPars->iOutput==-1)? 0 : p->pPars->iOutput;
+    pCex->iPo    = p->iOutCur;
+    pCex->iFrame = nFrames-1;
+    for ( pObl = p->pQueue, f = 0; pObl; pObl = pObl->pNext, f++ )
+        for ( i = pObl->pState->nLits; i < pObl->pState->nTotal; i++ )
+        {
+            Lit = pObl->pState->Lits[i];
+            if ( lit_sign(Lit) )
+                continue;
+            assert( lit_var(Lit) < pCex->nPis );
+            Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + lit_var(Lit) );
+        }
+    assert( f == nFrames );
+    if ( !Saig_ManVerifyCex(p->pAig, pCex) )
+        printf( "CEX for output %d is not valid.\n", p->iOutCur );
+    return pCex;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/pdr/pdrSat.c b/abc-build/src/proof/pdr/pdrSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/pdr/pdrSat.c
@@ -0,0 +1,395 @@
+/**CFile****************************************************************
+
+  FileName    [pdrSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Property driven reachability.]
+
+  Synopsis    [SAT solver procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 20, 2010.]
+
+  Revision    [$Id: pdrSat.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "pdrInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates new SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+sat_solver * Pdr_ManCreateSolver( Pdr_Man_t * p, int k )
+{
+    sat_solver * pSat;
+    Aig_Obj_t * pObj;
+    int i;
+    assert( Vec_PtrSize(p->vSolvers) == k );
+    assert( Vec_VecSize(p->vClauses) == k );
+    assert( Vec_IntSize(p->vActVars) == k );
+    // create new solver
+    pSat = sat_solver_new();
+    pSat = Pdr_ManNewSolver( pSat, p, k, (int)(k == 0) );
+    Vec_PtrPush( p->vSolvers, pSat );
+    Vec_VecExpand( p->vClauses, k );
+    Vec_IntPush( p->vActVars, 0 );
+    // add property cone
+    Saig_ManForEachPo( p->pAig, pObj, i )
+        Pdr_ObjSatVar( p, k, 1, pObj );
+    return pSat;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns old or restarted solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+sat_solver * Pdr_ManFetchSolver( Pdr_Man_t * p, int k )
+{
+    sat_solver * pSat;
+    Vec_Ptr_t * vArrayK;
+    Pdr_Set_t * pCube;
+    int i, j;
+    pSat = Pdr_ManSolver(p, k);
+    if ( Vec_IntEntry(p->vActVars, k) < p->pPars->nRecycle )
+        return pSat;
+    assert( k < Vec_PtrSize(p->vSolvers) - 1 );
+    p->nStarts++;
+//    sat_solver_delete( pSat );
+//    pSat = sat_solver_new();
+    sat_solver_restart( pSat );
+    // create new SAT solver
+    pSat = Pdr_ManNewSolver( pSat, p, k, (int)(k == 0) );
+    // write new SAT solver
+    Vec_PtrWriteEntry( p->vSolvers, k, pSat );
+    Vec_IntWriteEntry( p->vActVars, k, 0 );
+    // set the property output
+    Pdr_ManSetPropertyOutput( p, k );
+    // add the clauses
+    Vec_VecForEachLevelStart( p->vClauses, vArrayK, i, k )
+        Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCube, j )
+            Pdr_ManSolverAddClause( p, k, pCube );
+    return pSat;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts SAT variables into register IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Pdr_ManLitsToCube( Pdr_Man_t * p, int k, int * pArray, int nArray )
+{
+    int i, RegId;
+    Vec_IntClear( p->vLits );
+    for ( i = 0; i < nArray; i++ )
+    {
+        RegId = Pdr_ObjRegNum( p, k, lit_var(pArray[i]) );
+        if ( RegId == -1 )
+            continue;
+        assert( RegId >= 0 && RegId < Aig_ManRegNum(p->pAig) );
+        Vec_IntPush( p->vLits, toLitCond(RegId, !lit_sign(pArray[i])) );
+    }
+    assert( Vec_IntSize(p->vLits) >= 0 && Vec_IntSize(p->vLits) <= nArray );
+    return p->vLits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts the cube in terms of RO numbers into array of CNF literals.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Pdr_ManCubeToLits( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, int fCompl, int fNext )
+{
+    Aig_Obj_t * pObj;
+    int i, iVar, iVarMax = 0;
+    abctime clk = Abc_Clock();
+    Vec_IntClear( p->vLits );
+    assert( !(fNext && fCompl) );
+    for ( i = 0; i < pCube->nLits; i++ )
+    {
+        if ( pCube->Lits[i] == -1 )
+            continue;
+        if ( fNext )
+            pObj = Saig_ManLi( p->pAig, lit_var(pCube->Lits[i]) );
+        else
+            pObj = Saig_ManLo( p->pAig, lit_var(pCube->Lits[i]) );
+        iVar = Pdr_ObjSatVar( p, k, fNext ? 2 - lit_sign(pCube->Lits[i]) : 3, pObj ); assert( iVar >= 0 );
+        iVarMax = Abc_MaxInt( iVarMax, iVar );
+        Vec_IntPush( p->vLits, toLitCond( iVar, fCompl ^ lit_sign(pCube->Lits[i]) ) );
+    }
+//    sat_solver_setnvars( Pdr_ManSolver(p, k), iVarMax + 1 );
+    p->tCnf += Abc_Clock() - clk;
+    return p->vLits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the property output to 0 (sat) forever.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_ManSetPropertyOutput( Pdr_Man_t * p, int k )
+{
+    sat_solver * pSat;
+    Aig_Obj_t * pObj;
+    int Lit, RetValue, i;
+    pSat = Pdr_ManSolver(p, k);
+    Saig_ManForEachPo( p->pAig, pObj, i )
+    {
+        // skip solved outputs
+        if ( p->vCexes && Vec_PtrEntry(p->vCexes, i) )
+            continue;
+        // skip timedout outputs
+        if ( p->pPars->vOutMap && Vec_IntEntry(p->pPars->vOutMap, i) == -1 )
+            continue;
+        Lit = toLitCond( Pdr_ObjSatVar(p, k, 1, pObj), 1 ); // neg literal
+        RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
+        assert( RetValue == 1 );
+    }
+    sat_solver_compress( pSat );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one clause in terms of ROs to the k-th SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_ManSolverAddClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube )
+{
+    sat_solver * pSat;
+    Vec_Int_t * vLits;
+    int RetValue;
+    pSat  = Pdr_ManSolver(p, k);
+    vLits = Pdr_ManCubeToLits( p, k, pCube, 1, 0 );
+    RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
+    assert( RetValue == 1 );
+    sat_solver_compress( pSat );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects values of the RO/RI variables in k-th SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_ManCollectValues( Pdr_Man_t * p, int k, Vec_Int_t * vObjIds, Vec_Int_t * vValues )
+{
+    sat_solver * pSat;
+    Aig_Obj_t * pObj;
+    int iVar, i;
+    Vec_IntClear( vValues );
+    pSat = Pdr_ManSolver(p, k);
+    Aig_ManForEachObjVec( vObjIds, p->pAig, pObj, i )
+    {
+        iVar = Pdr_ObjSatVar( p, k, 3, pObj ); assert( iVar >= 0 );
+        Vec_IntPush( vValues, sat_solver_var_value(pSat, iVar) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the cube holds (UNSAT) in the given timeframe.]
+ 
+  Description [Return 1/0 if cube or property are proved to hold/fail
+  in k-th timeframe.  Returns the predecessor bad state in ppPred.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ManCheckCubeCs( Pdr_Man_t * p, int k, Pdr_Set_t * pCube )
+{ 
+    sat_solver * pSat;
+    Vec_Int_t * vLits;
+    abctime Limit;
+    int RetValue;
+    pSat = Pdr_ManFetchSolver( p, k );
+    vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 0 );
+    Limit = sat_solver_set_runtime_limit( pSat, Pdr_ManTimeLimit(p) );
+    RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 );
+    sat_solver_set_runtime_limit( pSat, Limit );
+    if ( RetValue == l_Undef )
+        return -1;
+    return (RetValue == l_False);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if the cube holds (UNSAT) in the given timeframe.]
+ 
+  Description [Return 1/0 if cube or property are proved to hold/fail
+  in k-th timeframe.  Returns the predecessor bad state in ppPred.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ManCheckCube( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, int nConfLimit )
+{ 
+    int fUseLit = 1;
+    int fLitUsed = 0;
+    sat_solver * pSat;
+    Vec_Int_t * vLits;
+    int Lit, RetValue;
+    abctime clk, Limit;
+    p->nCalls++;
+    pSat = Pdr_ManFetchSolver( p, k );
+    if ( pCube == NULL ) // solve the property
+    {
+        clk = Abc_Clock();
+        Lit = toLit( Pdr_ObjSatVar(p, k, 2, Aig_ManCo(p->pAig, p->iOutCur)) ); // pos literal (property fails)
+        Limit = sat_solver_set_runtime_limit( pSat, Pdr_ManTimeLimit(p) );
+        RetValue = sat_solver_solve( pSat, &Lit, &Lit + 1, nConfLimit, 0, 0, 0 );
+        sat_solver_set_runtime_limit( pSat, Limit );
+        if ( RetValue == l_Undef )
+            return -1;
+    }
+    else // check relative containment in terms of next states
+    {
+        if ( fUseLit )
+        {
+            fLitUsed = 1;
+            Vec_IntAddToEntry( p->vActVars, k, 1 );
+            // add the cube in terms of current state variables
+            vLits = Pdr_ManCubeToLits( p, k, pCube, 1, 0 );
+            // add activation literal
+            Lit = toLit( Pdr_ManFreeVar(p, k) );
+            // add activation literal
+            Vec_IntPush( vLits, Lit );
+            RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
+            assert( RetValue == 1 );
+            sat_solver_compress( pSat );
+            // create assumptions
+            vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 1 );
+            // add activation literal
+            Vec_IntPush( vLits, lit_neg(Lit) );
+        }
+        else
+            vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 1 );
+
+        // solve 
+        clk = Abc_Clock();
+        Limit = sat_solver_set_runtime_limit( pSat, Pdr_ManTimeLimit(p) );
+        RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), nConfLimit, 0, 0, 0 );
+        sat_solver_set_runtime_limit( pSat, Limit );
+        if ( RetValue == l_Undef )
+            return -1;
+/*
+        if ( RetValue == l_True )
+        {
+            int RetValue2 = Pdr_ManCubeJust( p, k, pCube );
+            if ( RetValue2 )
+                p->nCasesSS++;
+            else
+                p->nCasesSU++;
+        }
+        else
+        {
+            int RetValue2 = Pdr_ManCubeJust( p, k, pCube );
+            if ( RetValue2 )
+                p->nCasesUS++;
+            else
+                p->nCasesUU++;
+        }
+*/
+    }
+    clk = Abc_Clock() - clk;
+    p->tSat += clk;
+    assert( RetValue != l_Undef );
+    if ( RetValue == l_False )
+    {
+        p->tSatUnsat += clk;
+        p->nCallsU++;
+        if ( ppPred )
+            *ppPred = NULL;
+        RetValue = 1;
+    }
+    else // if ( RetValue == l_True )
+    {
+        p->tSatSat += clk;
+        p->nCallsS++;
+        if ( ppPred )
+            *ppPred = Pdr_ManTernarySim( p, k, pCube );
+        RetValue = 0;
+    }
+
+/* // for some reason, it does not work...
+    if ( fLitUsed )
+    {
+        int RetValue;
+        Lit = lit_neg(Lit);
+        RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
+        assert( RetValue == 1 );
+        sat_solver_compress( pSat );
+    }
+*/
+    return RetValue;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/pdr/pdrTsim.c b/abc-build/src/proof/pdr/pdrTsim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/pdr/pdrTsim.c
@@ -0,0 +1,488 @@
+/**CFile****************************************************************
+
+  FileName    [pdrTsim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Property driven reachability.]
+
+  Synopsis    [Ternary simulation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 20, 2010.]
+
+  Revision    [$Id: pdrTsim.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "pdrInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define PDR_ZER 1
+#define PDR_ONE 2
+#define PDR_UND 3
+
+static inline int Pdr_ManSimInfoNot( int Value )
+{
+    if ( Value == PDR_ZER )
+        return PDR_ONE;
+    if ( Value == PDR_ONE )
+        return PDR_ZER;
+    return PDR_UND;
+}
+
+static inline int Pdr_ManSimInfoAnd( int Value0, int Value1 )
+{
+    if ( Value0 == PDR_ZER || Value1 == PDR_ZER )
+        return PDR_ZER;
+    if ( Value0 == PDR_ONE && Value1 == PDR_ONE )
+        return PDR_ONE;
+    return PDR_UND;
+}
+
+static inline int Pdr_ManSimInfoGet( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    return 3 & (p->pTerSimData[Aig_ObjId(pObj) >> 4] >> ((Aig_ObjId(pObj) & 15) << 1));
+}
+
+static inline void Pdr_ManSimInfoSet( Aig_Man_t * p, Aig_Obj_t * pObj, int Value )
+{
+    assert( Value >= PDR_ZER && Value <= PDR_UND );
+    Value ^= Pdr_ManSimInfoGet( p, pObj );
+    p->pTerSimData[Aig_ObjId(pObj) >> 4] ^= (Value << ((Aig_ObjId(pObj) & 15) << 1));
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the TFI cone and collects CIs and nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_ManCollectCone_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vCiObjs, Vec_Int_t * vNodes )
+{
+    assert( !Aig_IsComplement(pObj) );
+    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(pAig, pObj);
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        Vec_IntPush( vCiObjs, Aig_ObjId(pObj) );
+        return;
+    }
+    Pdr_ManCollectCone_rec( pAig, Aig_ObjFanin0(pObj), vCiObjs, vNodes );
+    if ( Aig_ObjIsCo(pObj) )
+        return;
+    Pdr_ManCollectCone_rec( pAig, Aig_ObjFanin1(pObj), vCiObjs, vNodes );
+    Vec_IntPush( vNodes, Aig_ObjId(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Marks the TFI cone and collects CIs and nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_ManCollectCone( Aig_Man_t * pAig, Vec_Int_t * vCoObjs, Vec_Int_t * vCiObjs, Vec_Int_t * vNodes )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Vec_IntClear( vCiObjs );
+    Vec_IntClear( vNodes );
+    Aig_ManIncrementTravId( pAig );
+    Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) );
+    Aig_ManForEachObjVec( vCoObjs, pAig, pObj, i )
+        Pdr_ManCollectCone_rec( pAig, pObj, vCiObjs, vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs ternary simulation for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ManExtendOneEval( Aig_Man_t * pAig, Aig_Obj_t * pObj )
+{
+    int Value0, Value1, Value;
+    Value0 = Pdr_ManSimInfoGet( pAig, Aig_ObjFanin0(pObj) );
+    if ( Aig_ObjFaninC0(pObj) )
+        Value0 = Pdr_ManSimInfoNot( Value0 );
+    if ( Aig_ObjIsCo(pObj) )
+    {
+        Pdr_ManSimInfoSet( pAig, pObj, Value0 );
+        return Value0;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    Value1 = Pdr_ManSimInfoGet( pAig, Aig_ObjFanin1(pObj) );
+    if ( Aig_ObjFaninC1(pObj) )
+        Value1 = Pdr_ManSimInfoNot( Value1 );
+    Value = Pdr_ManSimInfoAnd( Value0, Value1 );
+    Pdr_ManSimInfoSet( pAig, pObj, Value );
+    return Value;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs ternary simulation for one design.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ManSimDataInit( Aig_Man_t * pAig,
+    Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vNodes,
+    Vec_Int_t * vCoObjs, Vec_Int_t * vCoVals, Vec_Int_t * vCi2Rem )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    // set the CI values
+    Pdr_ManSimInfoSet( pAig, Aig_ManConst1(pAig), PDR_ONE );
+    Aig_ManForEachObjVec( vCiObjs, pAig, pObj, i )
+        Pdr_ManSimInfoSet( pAig, pObj, (Vec_IntEntry(vCiVals, i)?PDR_ONE:PDR_ZER) );
+    // set the FOs to remove
+    if ( vCi2Rem != NULL )
+    Aig_ManForEachObjVec( vCi2Rem, pAig, pObj, i )
+        Pdr_ManSimInfoSet( pAig, pObj, PDR_UND );
+    // perform ternary simulation
+    Aig_ManForEachObjVec( vNodes, pAig, pObj, i )
+        Pdr_ManExtendOneEval( pAig, pObj );
+    // transfer results to the output
+    Aig_ManForEachObjVec( vCoObjs, pAig, pObj, i )
+        Pdr_ManExtendOneEval( pAig, pObj );
+    // check the results
+    Aig_ManForEachObjVec( vCoObjs, pAig, pObj, i )
+        if ( Pdr_ManSimInfoGet( pAig, pObj ) != (Vec_IntEntry(vCoVals, i)?PDR_ONE:PDR_ZER) )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tries to assign ternary value to one of the CIs.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ManExtendOne( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vUndo, Vec_Int_t * vVis )
+{
+    Aig_Obj_t * pFanout;
+    int i, k, iFanout = -1, Value, Value2;
+    assert( Saig_ObjIsLo(pAig, pObj) );
+    assert( Aig_ObjIsTravIdCurrent(pAig, pObj) );
+    // save original value
+    Value = Pdr_ManSimInfoGet( pAig, pObj );
+    assert( Value == PDR_ZER || Value == PDR_ONE );
+    Vec_IntPush( vUndo, Aig_ObjId(pObj) );
+    Vec_IntPush( vUndo, Value );
+    // update original value
+    Pdr_ManSimInfoSet( pAig, pObj, PDR_UND );
+    // traverse
+    Vec_IntClear( vVis );
+    Vec_IntPush( vVis, Aig_ObjId(pObj) );
+    Aig_ManForEachObjVec( vVis, pAig, pObj, i )
+    {
+        Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, k )
+        {
+            if ( !Aig_ObjIsTravIdCurrent(pAig, pFanout) )
+                continue;
+            assert( Aig_ObjId(pObj) < Aig_ObjId(pFanout) );
+            Value = Pdr_ManSimInfoGet( pAig, pFanout );
+            if ( Value == PDR_UND )
+                continue;
+            Value2 = Pdr_ManExtendOneEval( pAig, pFanout );
+            if ( Value2 == Value )
+                continue;
+            assert( Value2 == PDR_UND );
+            Vec_IntPush( vUndo, Aig_ObjId(pFanout) );
+            Vec_IntPush( vUndo, Value );
+            if ( Aig_ObjIsCo(pFanout) )
+                return 0;
+            assert( Aig_ObjIsNode(pFanout) );
+            Vec_IntPushOrder( vVis, Aig_ObjId(pFanout) );
+        }
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Undoes the partial results of ternary simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_ManExtendUndo( Aig_Man_t * pAig, Vec_Int_t * vUndo )
+{
+    Aig_Obj_t * pObj;
+    int i, Value;
+    Aig_ManForEachObjVec( vUndo, pAig, pObj, i )
+    {
+        Value  = Vec_IntEntry(vUndo, ++i);
+        assert( Pdr_ManSimInfoGet(pAig, pObj) == PDR_UND );
+        Pdr_ManSimInfoSet( pAig, pObj, Value );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the resulting cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_ManDeriveResult( Aig_Man_t * pAig, Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vCi2Rem, Vec_Int_t * vRes, Vec_Int_t * vPiLits )
+{
+    Aig_Obj_t * pObj;
+    int i, Lit;
+    // mark removed flop outputs
+    Aig_ManIncrementTravId( pAig );
+    Aig_ManForEachObjVec( vCi2Rem, pAig, pObj, i )
+    {
+        assert( Saig_ObjIsLo( pAig, pObj ) );
+        Aig_ObjSetTravIdCurrent(pAig, pObj);
+    }
+    // collect flop outputs that are not marked
+    Vec_IntClear( vRes );
+    Vec_IntClear( vPiLits );
+    Aig_ManForEachObjVec( vCiObjs, pAig, pObj, i )
+    {
+        if ( Saig_ObjIsPi(pAig, pObj) )
+        {
+            Lit = toLitCond( Aig_ObjCioId(pObj), (Vec_IntEntry(vCiVals, i) == 0) );
+            Vec_IntPush( vPiLits, Lit );
+            continue;
+        }
+        assert( Saig_ObjIsLo(pAig, pObj) );
+        if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+            continue;
+        Lit = toLitCond( Aig_ObjCioId(pObj) - Saig_ManPiNum(pAig), (Vec_IntEntry(vCiVals, i) == 0) );
+        Vec_IntPush( vRes, Lit );
+    }
+    if ( Vec_IntSize(vRes) == 0 )
+        Vec_IntPush(vRes, 0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the resulting cube.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_ManPrintCex( Aig_Man_t * pAig, Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vCi2Rem )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    char * pBuff = ABC_ALLOC( char, Aig_ManCiNum(pAig)+1 );
+    for ( i = 0; i < Aig_ManCiNum(pAig); i++ )
+        pBuff[i] = '-';
+    pBuff[i] = 0;
+    Aig_ManForEachObjVec( vCiObjs, pAig, pObj, i )
+        pBuff[Aig_ObjCioId(pObj)] = (Vec_IntEntry(vCiVals, i)? '1':'0');
+    if ( vCi2Rem )
+    Aig_ManForEachObjVec( vCi2Rem, pAig, pObj, i )
+        pBuff[Aig_ObjCioId(pObj)] = 'x';
+    Abc_Print( 1, "%s\n", pBuff );
+    ABC_FREE( pBuff );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Shrinks values using ternary simulation.]
+
+  Description [The cube contains the set of flop index literals which,
+  when converted into a clause and applied to the combinational outputs, 
+  led to a satisfiable SAT run in frame k (values stored in the SAT solver).
+  If the cube is NULL, it is assumed that the first property output was
+  asserted and failed.
+  The resulting array is a set of flop index literals that asserts the COs.
+  Priority contains 0 for i-th entry if the i-th FF is desirable to remove.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Pdr_Set_t * Pdr_ManTernarySim( Pdr_Man_t * p, int k, Pdr_Set_t * pCube )
+{
+    Pdr_Set_t * pRes;
+    Vec_Int_t * vPrio   = p->vPrio;    // priority flops (flop indices)
+    Vec_Int_t * vPiLits = p->vLits;    // array of literals (0/1 PI values)
+    Vec_Int_t * vCiObjs = p->vCiObjs;  // cone leaves (CI obj IDs)
+    Vec_Int_t * vCoObjs = p->vCoObjs;  // cone roots (CO obj IDs)
+    Vec_Int_t * vCiVals = p->vCiVals;  // cone leaf values (0/1 CI values)
+    Vec_Int_t * vCoVals = p->vCoVals;  // cone root values (0/1 CO values)
+    Vec_Int_t * vNodes  = p->vNodes;   // cone nodes (node obj IDs)
+    Vec_Int_t * vUndo   = p->vUndo;    // cone undos (node obj IDs)
+    Vec_Int_t * vVisits = p->vVisits;  // intermediate (obj IDs)
+    Vec_Int_t * vCi2Rem = p->vCi2Rem;  // CIs to be removed (CI obj IDs)
+    Vec_Int_t * vRes    = p->vRes;     // final result (flop literals)
+    Aig_Obj_t * pObj;
+    int i, Entry, RetValue;
+    abctime clk = Abc_Clock();
+
+    // collect CO objects
+    Vec_IntClear( vCoObjs );
+    if ( pCube == NULL ) // the target is the property output
+    {
+//        Vec_IntPush( vCoObjs, Aig_ObjId(Aig_ManCo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput)) );
+        Vec_IntPush( vCoObjs, Aig_ObjId(Aig_ManCo(p->pAig, p->iOutCur)) );
+    }
+    else // the target is the cube
+    {
+        for ( i = 0; i < pCube->nLits; i++ )
+        {
+            if ( pCube->Lits[i] == -1 )
+                continue;
+            pObj = Saig_ManLi(p->pAig, (pCube->Lits[i] >> 1));
+            Vec_IntPush( vCoObjs, Aig_ObjId(pObj) );
+        }
+    }
+if ( p->pPars->fVeryVerbose )
+{
+Abc_Print( 1, "Trying to justify cube " );
+if ( pCube )
+    Pdr_SetPrint( stdout, pCube, Aig_ManRegNum(p->pAig), NULL );
+else
+    Abc_Print( 1, "<prop=fail>" );
+Abc_Print( 1, " in frame %d.\n", k );
+}
+
+    // collect CI objects
+    Pdr_ManCollectCone( p->pAig, vCoObjs, vCiObjs, vNodes );
+    // collect values
+    Pdr_ManCollectValues( p, k, vCiObjs, vCiVals );
+    Pdr_ManCollectValues( p, k, vCoObjs, vCoVals );
+    // simulate for the first time
+if ( p->pPars->fVeryVerbose )
+Pdr_ManPrintCex( p->pAig, vCiObjs, vCiVals, NULL );
+    RetValue = Pdr_ManSimDataInit( p->pAig, vCiObjs, vCiVals, vNodes, vCoObjs, vCoVals, NULL );
+    assert( RetValue );
+
+#if 1
+    // try removing high-priority flops
+    Vec_IntClear( vCi2Rem );
+    Aig_ManForEachObjVec( vCiObjs, p->pAig, pObj, i )
+    {
+        if ( !Saig_ObjIsLo( p->pAig, pObj ) )
+            continue;
+        Entry = Aig_ObjCioId(pObj) - Saig_ManPiNum(p->pAig);
+        if ( vPrio != NULL && Vec_IntEntry( vPrio, Entry ) != 0 )
+            continue;
+        Vec_IntClear( vUndo );
+        if ( Pdr_ManExtendOne( p->pAig, pObj, vUndo, vVisits ) )
+            Vec_IntPush( vCi2Rem, Aig_ObjId(pObj) );
+        else
+            Pdr_ManExtendUndo( p->pAig, vUndo );
+    }
+    // try removing low-priority flops
+    Aig_ManForEachObjVec( vCiObjs, p->pAig, pObj, i )
+    {
+        if ( !Saig_ObjIsLo( p->pAig, pObj ) )
+            continue;
+        Entry = Aig_ObjCioId(pObj) - Saig_ManPiNum(p->pAig);
+        if ( vPrio == NULL || Vec_IntEntry( vPrio, Entry ) == 0 )
+            continue;
+        Vec_IntClear( vUndo );
+        if ( Pdr_ManExtendOne( p->pAig, pObj, vUndo, vVisits ) )
+            Vec_IntPush( vCi2Rem, Aig_ObjId(pObj) );
+        else
+            Pdr_ManExtendUndo( p->pAig, vUndo );
+    }
+#else
+    // try removing low-priority flops
+    Aig_ManForEachObjVec( vCiObjs, p->pAig, pObj, i )
+    {
+        if ( !Saig_ObjIsLo( p->pAig, pObj ) )
+            continue;
+        Entry = Aig_ObjCioId(pObj) - Saig_ManPiNum(p->pAig);
+        if ( vPrio == NULL || Vec_IntEntry( vPrio, Entry ) == 0 )
+            continue;
+        Vec_IntClear( vUndo );
+        if ( Pdr_ManExtendOne( p->pAig, pObj, vUndo, vVisits ) )
+            Vec_IntPush( vCi2Rem, Aig_ObjId(pObj) );
+        else
+            Pdr_ManExtendUndo( p->pAig, vUndo );
+    }
+    // try removing high-priority flops
+    Vec_IntClear( vCi2Rem );
+    Aig_ManForEachObjVec( vCiObjs, p->pAig, pObj, i )
+    {
+        if ( !Saig_ObjIsLo( p->pAig, pObj ) )
+            continue;
+        Entry = Aig_ObjCioId(pObj) - Saig_ManPiNum(p->pAig);
+        if ( vPrio != NULL && Vec_IntEntry( vPrio, Entry ) != 0 )
+            continue;
+        Vec_IntClear( vUndo );
+        if ( Pdr_ManExtendOne( p->pAig, pObj, vUndo, vVisits ) )
+            Vec_IntPush( vCi2Rem, Aig_ObjId(pObj) );
+        else
+            Pdr_ManExtendUndo( p->pAig, vUndo );
+    }
+#endif
+
+if ( p->pPars->fVeryVerbose )
+Pdr_ManPrintCex( p->pAig, vCiObjs, vCiVals, vCi2Rem );
+    RetValue = Pdr_ManSimDataInit( p->pAig, vCiObjs, vCiVals, vNodes, vCoObjs, vCoVals, vCi2Rem );
+    assert( RetValue );
+
+    // derive the set of resulting registers
+    Pdr_ManDeriveResult( p->pAig, vCiObjs, vCiVals, vCi2Rem, vRes, vPiLits );
+    assert( Vec_IntSize(vRes) > 0 );
+    p->tTsim += Abc_Clock() - clk;
+    pRes = Pdr_SetCreate( vRes, vPiLits );
+    assert( k == 0 || !Pdr_SetIsInit(pRes, -1) );
+    return pRes;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/pdr/pdrUtil.c b/abc-build/src/proof/pdr/pdrUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/pdr/pdrUtil.c
@@ -0,0 +1,737 @@
+/**CFile****************************************************************
+
+  FileName    [pdrUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Property driven reachability.]
+
+  Synopsis    [Various utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - November 20, 2010.]
+
+  Revision    [$Id: pdrUtil.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "pdrInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Pdr_Set_t * Pdr_SetAlloc( int nSize )
+{
+    Pdr_Set_t * p;
+    assert( nSize >= 0 && nSize < (1<<30) );
+    p = (Pdr_Set_t *)ABC_CALLOC( char, sizeof(Pdr_Set_t) + nSize * sizeof(int) );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Pdr_Set_t * Pdr_SetCreate( Vec_Int_t * vLits, Vec_Int_t * vPiLits )
+{
+    Pdr_Set_t * p;
+    int i;
+    assert( Vec_IntSize(vLits) + Vec_IntSize(vPiLits) < (1<<30) );
+    p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (Vec_IntSize(vLits) + Vec_IntSize(vPiLits)) * sizeof(int) );
+    p->nLits  = Vec_IntSize(vLits);
+    p->nTotal = Vec_IntSize(vLits) + Vec_IntSize(vPiLits);
+    p->nRefs  = 1;
+    p->Sign   = 0;
+    for ( i = 0; i < p->nLits; i++ )
+    {
+        p->Lits[i] = Vec_IntEntry(vLits, i);
+        p->Sign   |= ((word)1 << (p->Lits[i] % 63));
+    }
+    Vec_IntSelectSort( p->Lits, p->nLits );
+    // remember PI literals 
+    for ( i = p->nLits; i < p->nTotal; i++ )
+        p->Lits[i] = Vec_IntEntry(vPiLits, i-p->nLits);
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Pdr_Set_t * Pdr_SetCreateFrom( Pdr_Set_t * pSet, int iRemove )
+{
+    Pdr_Set_t * p;
+    int i, k = 0;
+    assert( iRemove >= 0 && iRemove < pSet->nLits );
+    p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (pSet->nTotal - 1) * sizeof(int) );
+    p->nLits  = pSet->nLits - 1;
+    p->nTotal = pSet->nTotal - 1;
+    p->nRefs  = 1;
+    p->Sign   = 0;
+    for ( i = 0; i < pSet->nTotal; i++ )
+    {
+        if ( i == iRemove )
+            continue;
+        p->Lits[k++] = pSet->Lits[i];
+        if ( i >= pSet->nLits )
+            continue;
+        p->Sign   |= ((word)1 << (pSet->Lits[i] % 63));
+    }
+    assert( k == p->nTotal );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Pdr_Set_t * Pdr_SetCreateSubset( Pdr_Set_t * pSet, int * pLits, int nLits )
+{
+    Pdr_Set_t * p;
+    int i, k = 0;
+    assert( nLits >= 0 && nLits <= pSet->nLits );
+    p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (nLits + pSet->nTotal - pSet->nLits) * sizeof(int) );
+    p->nLits  = nLits;
+    p->nTotal = nLits + pSet->nTotal - pSet->nLits;
+    p->nRefs  = 1;
+    p->Sign   = 0;
+    for ( i = 0; i < nLits; i++ )
+    {
+        assert( pLits[i] >= 0 );
+        p->Lits[k++] = pLits[i];
+        p->Sign   |= ((word)1 << (pLits[i] % 63));
+    }
+    Vec_IntSelectSort( p->Lits, p->nLits );
+    for ( i = pSet->nLits; i < pSet->nTotal; i++ )
+        p->Lits[k++] = pSet->Lits[i];
+    assert( k == p->nTotal );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Pdr_Set_t * Pdr_SetDup( Pdr_Set_t * pSet )
+{
+    Pdr_Set_t * p;
+    int i;
+    p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + pSet->nTotal * sizeof(int) );
+    p->nLits  = pSet->nLits;
+    p->nTotal = pSet->nTotal;
+    p->nRefs  = 1;
+    p->Sign   = pSet->Sign;
+    for ( i = 0; i < pSet->nTotal; i++ )
+        p->Lits[i] = pSet->Lits[i];
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Pdr_Set_t * Pdr_SetRef( Pdr_Set_t * p )
+{
+    p->nRefs++;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_SetDeref( Pdr_Set_t * p )
+{
+    if ( --p->nRefs == 0 )
+        ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_SetPrint( FILE * pFile, Pdr_Set_t * p, int nRegs, Vec_Int_t * vFlopCounts )
+{
+    char * pBuff;
+    int i, k, Entry;
+    pBuff = ABC_ALLOC( char, nRegs + 1 );
+    for ( i = 0; i < nRegs; i++ )
+        pBuff[i] = '-';
+    pBuff[i] = 0;
+    for ( i = 0; i < p->nLits; i++ )
+    {
+        if ( p->Lits[i] == -1 )
+            continue;
+        pBuff[lit_var(p->Lits[i])] = (lit_sign(p->Lits[i])? '0':'1');
+    }
+    if ( vFlopCounts )
+    {
+        // skip some literals
+        k = 0;
+        Vec_IntForEachEntry( vFlopCounts, Entry, i )
+            if ( Entry ) 
+                pBuff[k++] = pBuff[i];
+        pBuff[k] = 0;
+    }
+    fprintf( pFile, "%s", pBuff );
+    ABC_FREE( pBuff );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Return 1 if pOld set-theoretically contains pNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_SetContains( Pdr_Set_t * pOld, Pdr_Set_t * pNew )
+{
+    int * pOldInt, * pNewInt;
+    assert( pOld->nLits > 0 );
+    assert( pNew->nLits > 0 );
+    if ( pOld->nLits < pNew->nLits )
+        return 0;
+    if ( (pOld->Sign & pNew->Sign) != pNew->Sign )
+        return 0;
+    pOldInt = pOld->Lits + pOld->nLits - 1;
+    pNewInt = pNew->Lits + pNew->nLits - 1;
+    while ( pNew->Lits <= pNewInt )
+    {
+        if ( pOld->Lits > pOldInt )
+            return 0;
+        assert( *pNewInt != -1 );
+        assert( *pOldInt != -1 );
+        if ( *pNewInt == *pOldInt )
+            pNewInt--, pOldInt--;
+        else if ( *pNewInt < *pOldInt )
+            pOldInt--;
+        else
+            return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Return 1 if pOld set-theoretically contains pNew.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_SetContainsSimple( Pdr_Set_t * pOld, Pdr_Set_t * pNew )
+{
+    int * pOldInt, * pNewInt;
+    assert( pOld->nLits > 0 );
+    assert( pNew->nLits > 0 );
+    pOldInt = pOld->Lits + pOld->nLits - 1;
+    pNewInt = pNew->Lits + pNew->nLits - 1;
+    while ( pNew->Lits <= pNewInt )
+    {
+        assert( *pOldInt != -1 );
+        if ( *pNewInt == -1 )
+        {
+            pNewInt--;
+            continue;
+        }
+        if ( pOld->Lits > pOldInt )
+            return 0;
+        assert( *pNewInt != -1 );
+        assert( *pOldInt != -1 );
+        if ( *pNewInt == *pOldInt )
+            pNewInt--, pOldInt--;
+        else if ( *pNewInt < *pOldInt )
+            pOldInt--;
+        else
+            return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Return 1 if the state cube contains init state (000...0).]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_SetIsInit( Pdr_Set_t * pCube, int iRemove )
+{
+    int i;
+    for ( i = 0; i < pCube->nLits; i++ )
+    {
+        assert( pCube->Lits[i] != -1 );
+        if ( i == iRemove )
+            continue;
+        if ( lit_sign( pCube->Lits[i] ) == 0 )
+            return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_SetCompare( Pdr_Set_t ** pp1, Pdr_Set_t ** pp2 )
+{
+    Pdr_Set_t * p1 = *pp1;
+    Pdr_Set_t * p2 = *pp2;
+    int i;
+    for ( i = 0; i < p1->nLits && i < p2->nLits; i++ )
+    {
+        if ( p1->Lits[i] > p2->Lits[i] )
+            return -1;
+        if ( p1->Lits[i] < p2->Lits[i] )
+            return 1;
+    }
+    if ( i == p1->nLits && i < p2->nLits )
+        return -1;
+    if ( i < p1->nLits && i == p2->nLits )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Pdr_Obl_t * Pdr_OblStart( int k, int prio, Pdr_Set_t * pState, Pdr_Obl_t * pNext )
+{
+    Pdr_Obl_t * p;
+    p = ABC_ALLOC( Pdr_Obl_t, 1 );
+    p->iFrame = k;
+    p->prio   = prio;
+    p->nRefs  = 1;
+    p->pState = pState;
+    p->pNext  = pNext;
+    p->pLink  = NULL;
+    return p;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Pdr_Obl_t * Pdr_OblRef( Pdr_Obl_t * p )
+{
+    p->nRefs++;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_OblDeref( Pdr_Obl_t * p )
+{
+    if ( --p->nRefs == 0 )
+    {
+        if ( p->pNext )
+            Pdr_OblDeref( p->pNext );
+        Pdr_SetDeref( p->pState );
+        ABC_FREE( p );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_QueueIsEmpty( Pdr_Man_t * p )
+{
+    return p->pQueue == NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Pdr_Obl_t * Pdr_QueueHead( Pdr_Man_t * p )
+{
+    return p->pQueue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Pdr_Obl_t * Pdr_QueuePop( Pdr_Man_t * p )
+{
+    Pdr_Obl_t * pRes = p->pQueue;
+    if ( p->pQueue == NULL )
+        return NULL;
+    p->pQueue = p->pQueue->pLink;
+    Pdr_OblDeref( pRes );
+    p->nQueCur--;
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_QueueClean( Pdr_Man_t * p )
+{
+    Pdr_Obl_t * pThis;
+    while ( (pThis = Pdr_QueuePop(p)) )
+        Pdr_OblDeref( pThis );
+    pThis = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_QueuePush( Pdr_Man_t * p, Pdr_Obl_t * pObl )
+{
+    Pdr_Obl_t * pTemp, ** ppPrev;
+    p->nObligs++;
+    p->nQueCur++;
+    p->nQueMax = Abc_MaxInt( p->nQueMax, p->nQueCur );
+    Pdr_OblRef( pObl );
+    if ( p->pQueue == NULL )
+    {
+        p->pQueue = pObl;
+        return;
+    }
+    for ( ppPrev = &p->pQueue, pTemp = p->pQueue; pTemp; ppPrev = &pTemp->pLink, pTemp = pTemp->pLink )
+        if ( pTemp->iFrame > pObl->iFrame || (pTemp->iFrame == pObl->iFrame && pTemp->prio > pObl->prio) )
+            break;
+    *ppPrev = pObl;
+    pObl->pLink = pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_QueuePrint( Pdr_Man_t * p )
+{
+    Pdr_Obl_t * pObl;
+    for ( pObl = p->pQueue; pObl; pObl = pObl->pLink )
+        Abc_Print( 1, "Frame = %2d.  Prio = %8d.\n", pObl->iFrame, pObl->prio );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pdr_QueueStop( Pdr_Man_t * p )
+{
+    Pdr_Obl_t * pObl;
+    while ( !Pdr_QueueIsEmpty(p) )
+    {
+        pObl = Pdr_QueuePop(p);
+        Pdr_OblDeref( pObl );
+    }
+    p->pQueue = NULL;
+    p->nQueCur = 0;
+}
+
+
+#define PDR_VAL0  1
+#define PDR_VAL1  2
+#define PDR_VALX  3
+
+/**Function*************************************************************
+
+  Synopsis    [Returns value (0 or 1) or X if unassigned.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Pdr_ObjSatValue( Aig_Man_t * pAig, Aig_Obj_t * pNode, int fCompl )
+{
+    if ( Aig_ObjIsTravIdCurrent(pAig, pNode) )
+        return (pNode->fMarkA ^ fCompl) ? PDR_VAL1 : PDR_VAL0;
+    return PDR_VALX;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively searched for a satisfying assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_NtkFindSatAssign_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode, int Value, Pdr_Set_t * pCube, int Heur )
+{
+    int Value0, Value1;
+    if ( Aig_ObjIsConst1(pNode) )
+        return 1;
+    if ( Aig_ObjIsTravIdCurrent(pAig, pNode) )
+        return ((int)pNode->fMarkA == Value);
+    Aig_ObjSetTravIdCurrent(pAig, pNode);
+    pNode->fMarkA = Value;
+    if ( Aig_ObjIsCi(pNode) )
+    {
+//        if ( vSuppLits )
+//            Vec_IntPush( vSuppLits, Abc_Var2Lit( Aig_ObjCioId(pNode), !Value ) );
+        if ( Saig_ObjIsLo(pAig, pNode) )
+        {
+//            pCube->Lits[pCube->nLits++] = Abc_Var2Lit( Aig_ObjCioId(pNode) - Saig_ManPiNum(pAig), !Value );
+            pCube->Lits[pCube->nLits++] = Abc_Var2Lit( Aig_ObjCioId(pNode) - Saig_ManPiNum(pAig), Value );
+            pCube->Sign |= ((word)1 << (pCube->Lits[pCube->nLits-1] % 63));
+        }
+        return 1;
+    }
+    assert( Aig_ObjIsNode(pNode) );
+    // propagation
+    if ( Value ) 
+    {
+        if ( !Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), !Aig_ObjFaninC0(pNode), pCube, Heur) )
+            return 0;
+        return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), !Aig_ObjFaninC1(pNode), pCube, Heur);
+    }
+    // justification
+    Value0 = Pdr_ObjSatValue( pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode) );
+    if ( Value0 == PDR_VAL0 )
+        return 1;
+    Value1 = Pdr_ObjSatValue( pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode) );
+    if ( Value1 == PDR_VAL0 )
+        return 1;
+    if ( Value0 == PDR_VAL1 && Value1 == PDR_VAL1 )
+        return 0;
+    if ( Value0 == PDR_VAL1 )
+        return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode), pCube, Heur);
+    if ( Value1 == PDR_VAL1 )
+        return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode), pCube, Heur);
+    assert( Value0 == PDR_VALX && Value1 == PDR_VALX );
+    // decision making
+//    if ( rand() % 10 == Heur )
+    if ( Aig_ObjId(pNode) % 4 == Heur )
+        return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode), pCube, Heur);
+    else
+        return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode), pCube, Heur);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if SAT assignment is found; 0 otherwise.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pdr_ManCubeJust( Pdr_Man_t * p, int k, Pdr_Set_t * pCube )
+{
+    Aig_Obj_t * pNode;
+    int i, v, fCompl;
+//    return 0;
+    for ( i = 0; i < 4; i++ )
+    {
+        // derive new assignment
+        p->pCubeJust->nLits = 0;
+        p->pCubeJust->Sign  = 0;
+        Aig_ManIncrementTravId( p->pAig );
+        for ( v = 0; v < pCube->nLits; v++ )
+        {
+            if ( pCube->Lits[v] == -1 )
+                continue;
+            pNode  = Saig_ManLi( p->pAig, lit_var(pCube->Lits[v]) );
+            fCompl = lit_sign(pCube->Lits[v]) ^ Aig_ObjFaninC0(pNode);
+            if ( !Pdr_NtkFindSatAssign_rec( p->pAig, Aig_ObjFanin0(pNode), !fCompl, p->pCubeJust, i ) )
+                break;
+        }
+        if ( v < pCube->nLits )
+            continue;
+        // figure this out!!!
+        if ( p->pCubeJust->nLits == 0 )
+            continue;
+        // successfully derived new assignment
+        Vec_IntSelectSort( p->pCubeJust->Lits, p->pCubeJust->nLits );
+        // check assignment against this cube
+        if ( Pdr_SetContainsSimple( p->pCubeJust, pCube ) )
+            continue;
+//printf( "\n" );
+//Pdr_SetPrint( stdout, pCube,        Saig_ManRegNum(p->pAig), NULL ); printf( "\n" );
+//Pdr_SetPrint( stdout, p->pCubeJust, Saig_ManRegNum(p->pAig), NULL ); printf( "\n" );
+        // check assignment against the clauses
+        if ( Pdr_ManCheckContainment( p, k, p->pCubeJust ) )
+            continue;
+        // find good assignment
+        return 1;
+    }
+    return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/ssc/module.make b/abc-build/src/proof/ssc/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssc/module.make
@@ -0,0 +1,5 @@
+SRC +=	src/proof/ssc/sscClass.c \
+	src/proof/ssc/sscCore.c \
+	src/proof/ssc/sscSat.c \
+	src/proof/ssc/sscSim.c \
+	src/proof/ssc/sscUtil.c
diff --git a/abc-build/src/proof/ssc/ssc.h b/abc-build/src/proof/ssc/ssc.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssc/ssc.h
@@ -0,0 +1,78 @@
+/**CFile****************************************************************
+
+  FileName    [ssc.h] 
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT sweeping under constraints.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: ssc.h,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__ssc__ssc_h
+#define ABC__aig__ssc__ssc_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// choicing parameters
+typedef struct Ssc_Pars_t_ Ssc_Pars_t;
+struct Ssc_Pars_t_
+{
+    int              nWords;        // the number of simulation words
+    int              nBTLimit;      // conflict limit at a node
+    int              nSatVarMax;    // the max number of SAT variables
+    int              nCallsRecycle; // calls to perform before recycling SAT solver
+    int              fAppend;       // append constraints to the resulting AIG
+    int              fVerbose;      // verbose stats
+    int              fVerify;       // enable internal verification
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== sscCore.c ==========================================================*/
+extern void          Ssc_ManSetDefaultParams( Ssc_Pars_t * p );
+extern Gia_Man_t *   Ssc_PerformSweeping( Gia_Man_t * pAig, Gia_Man_t * pCare, Ssc_Pars_t * pPars );
+extern Gia_Man_t *   Ssc_PerformSweepingConstr( Gia_Man_t * p, Ssc_Pars_t * pPars );
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/ssc/sscClass.c b/abc-build/src/proof/ssc/sscClass.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssc/sscClass.c
@@ -0,0 +1,326 @@
+/**CFile****************************************************************
+
+  FileName    [sscClass.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT sweeping under constraints.]
+
+  Synopsis    [Equivalence classes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: sscClass.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sscInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash key of the simuation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Ssc_GiaSimHashKey( Gia_Man_t * p, int iObj, int nTableSize )
+{
+    static int s_Primes[16] = { 
+        1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, 
+        4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 };
+    word * pSim = Gia_ObjSim( p, iObj );
+    unsigned uHash = 0;
+    int i, nWords = Gia_ObjSimWords(p);
+    if ( pSim[0] & 1 )
+        for ( i = 0; i < nWords; i++ )
+            uHash ^= ~pSim[i] * s_Primes[i & 0xf];
+    else
+        for ( i = 0; i < nWords; i++ )
+            uHash ^= pSim[i] * s_Primes[i & 0xf];
+    return (int)(uHash % nTableSize);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if sim patterns are equal up to the complement.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Ssc_GiaSimIsConst0( Gia_Man_t * p, int iObj0 )
+{
+    int w, nWords = Gia_ObjSimWords(p);
+    word * pSim = Gia_ObjSim( p, iObj0 );
+    if ( pSim[0] & 1 )
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( ~pSim[w] )
+                return 0;
+    }
+    else
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( pSim[w] )
+                return 0;
+    }
+    return 1;
+}
+static inline int Ssc_GiaSimAreEqual( Gia_Man_t * p, int iObj0, int iObj1 )
+{
+    int w, nWords = Gia_ObjSimWords(p);
+    word * pSim0 = Gia_ObjSim( p, iObj0 );
+    word * pSim1 = Gia_ObjSim( p, iObj1 );
+    if ( (pSim0[0] & 1) != (pSim1[0] & 1) )
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( pSim0[w] != ~pSim1[w] )
+                return 0;
+    }
+    else
+    {
+        for ( w = 0; w < nWords; w++ )
+            if ( pSim0[w] != pSim1[w] )
+                return 0;
+    }
+    return 1;
+}
+static inline int Ssc_GiaSimAreEqualBit( Gia_Man_t * p, int iObj0, int iObj1 )
+{
+    Gia_Obj_t * pObj0 = Gia_ManObj( p, iObj0 );
+    Gia_Obj_t * pObj1 = Gia_ManObj( p, iObj1 );
+    return (pObj0->fPhase ^ pObj0->fMark0) == (pObj1->fPhase ^ pObj1->fMark0);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines one equivalence class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssc_GiaSimClassCreate( Gia_Man_t * p, Vec_Int_t * vClass )
+{
+    int Repr = GIA_VOID, EntPrev = -1, Ent, i;
+    assert( Vec_IntSize(vClass) > 0 );
+    Vec_IntForEachEntry( vClass, Ent, i )
+    {
+        if ( i == 0 )
+        {
+            Repr = Ent;
+            Gia_ObjSetRepr( p, Ent, GIA_VOID );
+            EntPrev = Ent;
+        }
+        else
+        {
+            assert( Repr < Ent );
+            Gia_ObjSetRepr( p, Ent, Repr );
+            Gia_ObjSetNext( p, EntPrev, Ent );
+            EntPrev = Ent;
+        }
+    }
+    Gia_ObjSetNext( p, EntPrev, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines one equivalence class using individual bit-pattern.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssc_GiaSimClassRefineOneBit( Gia_Man_t * p, int i )
+{
+    Gia_Obj_t * pObj;
+    int Ent;
+    assert( Gia_ObjIsHead( p, i ) );
+    Vec_IntClear( p->vClassOld );
+    Vec_IntClear( p->vClassNew );
+    Vec_IntPush( p->vClassOld, i );
+    pObj = Gia_ManObj(p, i);
+    Gia_ClassForEachObj1( p, i, Ent )
+    {
+        if ( Ssc_GiaSimAreEqualBit( p, i, Ent ) )
+            Vec_IntPush( p->vClassOld, Ent );
+        else
+            Vec_IntPush( p->vClassNew, Ent );
+    }
+    if ( Vec_IntSize( p->vClassNew ) == 0 )
+        return 0;
+    Ssc_GiaSimClassCreate( p, p->vClassOld );
+    Ssc_GiaSimClassCreate( p, p->vClassNew );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Refines one class using simulation patterns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssc_GiaSimClassRefineOne( Gia_Man_t * p, int i )
+{
+    Gia_Obj_t * pObj;
+    int Ent;
+    assert( Gia_ObjIsHead( p, i ) );
+    Vec_IntClear( p->vClassOld );
+    Vec_IntClear( p->vClassNew );
+    Vec_IntPush( p->vClassOld, i );
+    pObj = Gia_ManObj(p, i);
+    Gia_ClassForEachObj1( p, i, Ent )
+    {
+        if ( Ssc_GiaSimAreEqual( p, i, Ent ) )
+            Vec_IntPush( p->vClassOld, Ent );
+        else
+            Vec_IntPush( p->vClassNew, Ent );
+    }
+    if ( Vec_IntSize( p->vClassNew ) == 0 )
+        return 0;
+    Ssc_GiaSimClassCreate( p, p->vClassOld );
+    Ssc_GiaSimClassCreate( p, p->vClassNew );
+    if ( Vec_IntSize(p->vClassNew) > 1 )
+        return 1 + Ssc_GiaSimClassRefineOne( p, Vec_IntEntry(p->vClassNew,0) );
+    return 1;
+}
+void Ssc_GiaSimProcessRefined( Gia_Man_t * p, Vec_Int_t * vRefined )
+{
+    int * pTable, nTableSize, i, k, Key;
+    if ( Vec_IntSize(vRefined) == 0 )
+        return;
+    nTableSize = Abc_PrimeCudd( 100 + Vec_IntSize(vRefined) / 3 );
+    pTable = ABC_CALLOC( int, nTableSize );
+    Vec_IntForEachEntry( vRefined, i, k )
+    {
+        assert( !Ssc_GiaSimIsConst0( p, i ) );
+        Key = Ssc_GiaSimHashKey( p, i, nTableSize );
+        if ( pTable[Key] == 0 )
+        {
+            assert( Gia_ObjRepr(p, i) == 0 );
+            assert( Gia_ObjNext(p, i) == 0 );
+            Gia_ObjSetRepr( p, i, GIA_VOID );
+        }
+        else
+        {
+            Gia_ObjSetNext( p, pTable[Key], i );
+            Gia_ObjSetRepr( p, i, Gia_ObjRepr(p, pTable[Key]) );
+            if ( Gia_ObjRepr(p, i) == GIA_VOID )
+                Gia_ObjSetRepr( p, i, pTable[Key] );
+            assert( Gia_ObjRepr(p, i) > 0 );
+        }
+        pTable[Key] = i;
+    }
+    Vec_IntForEachEntry( vRefined, i, k )
+        if ( Gia_ObjIsHead( p, i ) )
+            Ssc_GiaSimClassRefineOne( p, i );
+    ABC_FREE( pTable );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssc_GiaClassesInit( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    assert( p->pReprs == NULL );
+    p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) );
+    p->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p) );
+    Gia_ManForEachObj( p, pObj, i )
+        Gia_ObjSetRepr( p, i, Gia_ObjIsCand(pObj) ? 0 : GIA_VOID );
+    if ( p->vClassOld == NULL )
+        p->vClassOld = Vec_IntAlloc( 100 );
+    if ( p->vClassNew == NULL )
+        p->vClassNew = Vec_IntAlloc( 100 );
+}
+int Ssc_GiaClassesRefine( Gia_Man_t * p )
+{
+    Vec_Int_t * vRefinedC;
+    Gia_Obj_t * pObj;
+    int i, Counter = 0;
+    if ( p->pReprs != NULL );
+    vRefinedC = Vec_IntAlloc( 100 );
+    Gia_ManForEachCand( p, pObj, i )
+        if ( Gia_ObjIsTail(p, i) )
+            Counter += Ssc_GiaSimClassRefineOne( p, Gia_ObjRepr(p, i) );
+        else if ( Gia_ObjIsConst(p, i) && !Ssc_GiaSimIsConst0(p, i) )
+            Vec_IntPush( vRefinedC, i );
+    Ssc_GiaSimProcessRefined( p, vRefinedC );
+    Counter += Vec_IntSize( vRefinedC );
+    Vec_IntFree( vRefinedC );
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Check if the pairs have been disproved.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssc_GiaClassesCheckPairs( Gia_Man_t * p, Vec_Int_t * vDisPairs )
+{
+    int i, iRepr, iObj, Result = 1;
+    Vec_IntForEachEntryDouble( vDisPairs, iRepr, iObj, i )
+        if ( iRepr == Gia_ObjRepr(p, iObj) )
+            printf( "Pair (%d, %d) are still equivalent.\n", iRepr, iObj ), Result = 0;
+//    if ( Result )
+//        printf( "Classes are refined correctly.\n" );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/ssc/sscCore.c b/abc-build/src/proof/ssc/sscCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssc/sscCore.c
@@ -0,0 +1,469 @@
+/**CFile****************************************************************
+
+  FileName    [sscCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT sweeping under constraints.]
+
+  Synopsis    [The core procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: sscCore.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sscInt.h"
+#include "proof/cec/cec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssc_ManSetDefaultParams( Ssc_Pars_t * p )
+{
+    memset( p, 0, sizeof(Ssc_Pars_t) );
+    p->nWords         =     1;  // the number of simulation words
+    p->nBTLimit       =  1000;  // conflict limit at a node
+    p->nSatVarMax     =  5000;  // the max number of SAT variables
+    p->nCallsRecycle  =   100;  // calls to perform before recycling SAT solver
+    p->fVerbose       =     0;  // verbose stats
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssc_ManStop( Ssc_Man_t * p )
+{
+    Vec_IntFreeP( &p->vFront );
+    Vec_IntFreeP( &p->vFanins );
+    Vec_IntFreeP( &p->vPattern );
+    Vec_IntFreeP( &p->vDisPairs );
+    Vec_IntFreeP( &p->vPivot );
+    Vec_IntFreeP( &p->vId2Var );
+    Vec_IntFreeP( &p->vVar2Id );
+    if ( p->pSat ) sat_solver_delete( p->pSat );
+    Gia_ManStopP( &p->pFraig );
+    ABC_FREE( p );
+}
+Ssc_Man_t * Ssc_ManStart( Gia_Man_t * pAig, Gia_Man_t * pCare, Ssc_Pars_t * pPars )
+{
+    Ssc_Man_t * p;
+    p = ABC_CALLOC( Ssc_Man_t, 1 );
+    p->pPars  = pPars;
+    p->pAig   = pAig;
+    p->pCare  = pCare;
+    p->pFraig = Gia_ManDupDfs( p->pCare );
+    assert( p->pFraig->pHTable == NULL );
+    assert( !Gia_ManHasDangling(p->pFraig) );
+    Gia_ManInvertPos( p->pFraig );
+    Ssc_ManStartSolver( p );
+    if ( p->pSat == NULL )
+    {
+        printf( "Constraints are UNSAT after propagation.\n" );
+        Ssc_ManStop( p );
+        return (Ssc_Man_t *)(ABC_PTRINT_T)1;
+    }
+//    p->vPivot = Ssc_GiaFindPivotSim( p->pFraig );
+//    Vec_IntFreeP( &p->vPivot  );
+    p->vPivot = Ssc_ManFindPivotSat( p );
+    if ( p->vPivot == (Vec_Int_t *)(ABC_PTRINT_T)1 )
+    {
+        printf( "Constraints are UNSAT.\n" );
+        Ssc_ManStop( p );
+        return (Ssc_Man_t *)(ABC_PTRINT_T)1;
+    }
+    if ( p->vPivot == NULL )
+    {
+        printf( "Conflict limit is reached while trying to find one SAT assignment.\n" );
+        Ssc_ManStop( p );
+        return NULL;
+    }
+    sat_solver_bookmark( p->pSat );
+//    Vec_IntPrint( p->vPivot );
+    Gia_ManSetPhasePattern( p->pAig, p->vPivot );
+    Gia_ManSetPhasePattern( p->pCare, p->vPivot );
+    if ( Gia_ManCheckCoPhase(p->pCare) )
+    {
+        printf( "Computed reference pattern violates %d constraints (this is a bug!).\n", Gia_ManCheckCoPhase(p->pCare) );
+        Ssc_ManStop( p );
+        return NULL;
+    }
+    // other things
+    p->vDisPairs = Vec_IntAlloc( 100 );
+    p->vPattern = Vec_IntAlloc( 100 );
+    p->vFanins = Vec_IntAlloc( 100 );
+    p->vFront = Vec_IntAlloc( 100 );
+    Ssc_GiaClassesInit( pAig );
+    // now it is ready for refinement using simulation 
+    return p;
+}
+void Ssc_ManPrintStats( Ssc_Man_t * p )
+{
+    Abc_Print( 1, "Parameters: SimWords = %d. SatConfs = %d. SatVarMax = %d. CallsRec = %d. Verbose = %d.\n",
+        p->pPars->nWords, p->pPars->nBTLimit, p->pPars->nSatVarMax, p->pPars->nCallsRecycle, p->pPars->fVerbose );
+    Abc_Print( 1, "SAT calls : Total = %d. Proof = %d. Cex = %d. Undec = %d.\n",
+        p->nSatCalls, p->nSatCallsUnsat, p->nSatCallsSat, p->nSatCallsUndec );
+    Abc_Print( 1, "SAT solver: Vars = %d. Clauses = %d. Recycles = %d. Sim rounds = %d.\n",
+        sat_solver_nvars(p->pSat), sat_solver_nclauses(p->pSat), p->nRecycles, p->nSimRounds );
+
+    p->timeOther = p->timeTotal - p->timeSimInit - p->timeSimSat - p->timeCnfGen - p->timeSatSat - p->timeSatUnsat - p->timeSatUndec;
+    ABC_PRTP( "Initialization ", p->timeSimInit,            p->timeTotal );
+    ABC_PRTP( "SAT simulation ", p->timeSimSat,             p->timeTotal );
+    ABC_PRTP( "CNF generation ", p->timeSimSat,             p->timeTotal );
+    ABC_PRTP( "SAT solving    ", p->timeSat-p->timeCnfGen,  p->timeTotal );
+    ABC_PRTP( "  unsat        ", p->timeSatUnsat,           p->timeTotal );
+    ABC_PRTP( "  sat          ", p->timeSatSat,             p->timeTotal );
+    ABC_PRTP( "  undecided    ", p->timeSatUndec,           p->timeTotal );
+    ABC_PRTP( "Other          ", p->timeOther,              p->timeTotal );
+    ABC_PRTP( "TOTAL          ", p->timeTotal,              p->timeTotal );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refine one class by resimulating one pattern.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssc_GiaSimulatePatternFraig_rec( Ssc_Man_t * p, int iFraigObj )
+{
+    Gia_Obj_t * pObj;
+    int Res0, Res1;
+    if ( Ssc_ObjSatVar(p, iFraigObj) )
+        return sat_solver_var_value( p->pSat, Ssc_ObjSatVar(p, iFraigObj) );
+    pObj = Gia_ManObj( p->pFraig, iFraigObj );
+    assert( Gia_ObjIsAnd(pObj) );
+    Res0 = Ssc_GiaSimulatePatternFraig_rec( p, Gia_ObjFaninId0(pObj, iFraigObj) );
+    Res1 = Ssc_GiaSimulatePatternFraig_rec( p, Gia_ObjFaninId1(pObj, iFraigObj) );
+    pObj->fMark0 = (Res0 ^ Gia_ObjFaninC0(pObj)) & (Res1 ^ Gia_ObjFaninC1(pObj));
+    return pObj->fMark0;
+}
+int Ssc_GiaSimulatePattern_rec( Ssc_Man_t * p, Gia_Obj_t * pObj )
+{
+    int Res0, Res1;
+    if ( Gia_ObjIsTravIdCurrent(p->pAig, pObj) )
+        return pObj->fMark0;
+    Gia_ObjSetTravIdCurrent(p->pAig, pObj);
+    if ( ~pObj->Value )  // mapping into FRAIG exists - simulate FRAIG
+    { 
+        Res0 = Ssc_GiaSimulatePatternFraig_rec( p, Abc_Lit2Var(pObj->Value) );
+        pObj->fMark0 = Res0 ^ Abc_LitIsCompl(pObj->Value);
+    }
+    else // mapping into FRAIG does not exist - simulate AIG
+    {
+        Res0 = Ssc_GiaSimulatePattern_rec( p, Gia_ObjFanin0(pObj) );
+        Res1 = Ssc_GiaSimulatePattern_rec( p, Gia_ObjFanin1(pObj) );
+        pObj->fMark0 = (Res0 ^ Gia_ObjFaninC0(pObj)) & (Res1 ^ Gia_ObjFaninC1(pObj));
+    }
+    return pObj->fMark0;
+}
+int Ssc_GiaResimulateOneClass( Ssc_Man_t * p, int iRepr, int iObj )
+{
+    int Ent, RetValue;
+    assert( iRepr == Gia_ObjRepr(p->pAig, iObj) );
+    assert( Gia_ObjIsHead( p->pAig, iRepr ) );
+    // set bit-values at the nodes according to the counter-example
+    Gia_ManIncrementTravId( p->pAig );
+    Gia_ClassForEachObj( p->pAig, iRepr, Ent )
+        Ssc_GiaSimulatePattern_rec( p, Gia_ManObj(p->pAig, Ent) );
+    // refine one class using these bit-values
+    RetValue = Ssc_GiaSimClassRefineOneBit( p->pAig, iRepr );
+    // check that the candidate equivalence is indeed refined
+    assert( iRepr != Gia_ObjRepr(p->pAig, iObj) );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform verification of conditional sweeping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssc_PerformVerification( Gia_Man_t * p0, Gia_Man_t * p1, Gia_Man_t * pC )
+{
+    int Status;
+    Cec_ParCec_t ParsCec, * pPars = &ParsCec;
+    // derive the OR of constraint outputs
+    Gia_Man_t * pCond = Gia_ManDupAndOr( pC, Gia_ManPoNum(p0), 1, 0 );
+    // derive F = F & !OR(c0, c1, c2, ...)
+    Gia_Man_t * p0c = Gia_ManMiter( p0, pCond, 0, 0, 0, 1, 0 );
+    // derive F = F & !OR(c0, c1, c2, ...)
+    Gia_Man_t * p1c = Gia_ManMiter( p1, pCond, 0, 0, 0, 1, 0 );
+    // derive dual-output miter
+    Gia_Man_t * pMiter = Gia_ManMiter( p0c, p1c, 0, 1, 0, 0, 0 );
+    Gia_ManStop( p0c );
+    Gia_ManStop( p1c );
+    Gia_ManStop( pCond );
+    // run equivalence checking
+    Cec_ManCecSetDefaultParams( pPars );
+    Status = Cec_ManVerify( pMiter, pPars );
+    Gia_ManStop( pMiter );
+    // report the results
+    if ( Status == 1 )
+        printf( "Verification succeeded.\n" );
+    else if ( Status == 0 )
+        printf( "Verification failed.\n" );
+    else if ( Status == -1 )
+        printf( "Verification undecided.\n" );
+    else assert( 0 );
+    return Status;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Ssc_PerformSweepingInt( Gia_Man_t * pAig, Gia_Man_t * pCare, Ssc_Pars_t * pPars )
+{
+    Ssc_Man_t * p;
+    Gia_Man_t * pResult, * pTemp;
+    Gia_Obj_t * pObj, * pRepr;
+    abctime clk, clkTotal = Abc_Clock();
+    int i, fCompl, nRefined, status;
+clk = Abc_Clock();
+    assert( Gia_ManRegNum(pCare) == 0 );
+    assert( Gia_ManCiNum(pAig) == Gia_ManCiNum(pCare) );
+    assert( Gia_ManIsNormalized(pAig) );
+    assert( Gia_ManIsNormalized(pCare) );
+    // reset random numbers
+    Gia_ManRandom( 1 );
+    // sweeping manager
+    p = Ssc_ManStart( pAig, pCare, pPars );
+    if ( p == (Ssc_Man_t *)(ABC_PTRINT_T)1 ) // UNSAT
+        return Gia_ManDupZero( pAig );
+    if ( p == NULL ) // timeout
+        return Gia_ManDup( pAig );
+    if ( p->pPars->fVerbose )
+        printf( "Care set produced %d hits out of %d.\n", Ssc_GiaEstimateCare(p->pFraig, 5), 640 );
+    // perform simulation 
+    while ( 1 ) 
+    {
+        // simulate care set
+        Ssc_GiaRandomPiPattern( p->pFraig, 5, NULL );
+        Ssc_GiaSimRound( p->pFraig );
+        // transfer care patterns to user's AIG
+        if ( !Ssc_GiaTransferPiPattern( pAig, p->pFraig, p->vPivot ) )
+            break;
+        // simulate the main AIG
+        Ssc_GiaSimRound( pAig );
+        nRefined = Ssc_GiaClassesRefine( pAig );
+        if ( pPars->fVerbose ) 
+            Gia_ManEquivPrintClasses( pAig, 0, 0 );
+        if ( nRefined <= Gia_ManCandNum(pAig) / 100 )
+            break;
+    }
+p->timeSimInit += Abc_Clock() - clk;
+
+    // prepare user's AIG
+    Gia_ManFillValue(pAig);
+    Gia_ManConst0(pAig)->Value = 0;
+    Gia_ManForEachCi( pAig, pObj, i )
+        pObj->Value = Gia_Obj2Lit( p->pFraig, Gia_ManCi(p->pFraig, i) );
+//    Gia_ManLevelNum(pAig);
+    // prepare swept AIG (should be done after starting SAT solver in Ssc_ManStart)
+    Gia_ManHashStart( p->pFraig );
+    // perform sweeping
+    Ssc_GiaResetPiPattern( pAig, pPars->nWords );
+    Ssc_GiaSavePiPattern( pAig, p->vPivot );
+    Gia_ManForEachCand( pAig, pObj, i )
+    {
+        if ( pAig->iPatsPi == 64 * pPars->nWords )
+        {
+clk = Abc_Clock();
+            Ssc_GiaSimRound( pAig );
+            Ssc_GiaClassesRefine( pAig );
+            if ( pPars->fVerbose ) 
+                Gia_ManEquivPrintClasses( pAig, 0, 0 );
+            Ssc_GiaClassesCheckPairs( pAig, p->vDisPairs );
+            Vec_IntClear( p->vDisPairs );
+            // prepare next patterns
+            Ssc_GiaResetPiPattern( pAig, pPars->nWords );
+            Ssc_GiaSavePiPattern( pAig, p->vPivot );
+p->timeSimSat += Abc_Clock() - clk;
+//printf( "\n" );
+        }
+        if ( Gia_ObjIsAnd(pObj) )
+            pObj->Value = Gia_ManHashAnd( p->pFraig, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        if ( !Gia_ObjHasRepr(pAig, i) )
+            continue;
+        pRepr = Gia_ObjReprObj(pAig, i);
+        if ( (int)pObj->Value == Abc_LitNotCond( pRepr->Value, pRepr->fPhase ^ pObj->fPhase ) )
+        {
+            Gia_ObjSetProved( pAig, i );
+            continue;
+        }
+        assert( Abc_Lit2Var(pRepr->Value) != Abc_Lit2Var(pObj->Value) );
+        fCompl = pRepr->fPhase ^ pObj->fPhase ^ Abc_LitIsCompl(pRepr->Value) ^ Abc_LitIsCompl(pObj->Value);
+
+        // perform SAT call
+clk = Abc_Clock();
+        p->nSatCalls++;
+        status = Ssc_ManCheckEquivalence( p, Abc_Lit2Var(pRepr->Value), Abc_Lit2Var(pObj->Value), fCompl );
+        if ( status == l_False )
+        {
+            p->nSatCallsUnsat++;
+            pObj->Value = Abc_LitNotCond( pRepr->Value, pRepr->fPhase ^ pObj->fPhase );
+            Gia_ObjSetProved( pAig, i );
+        }
+        else if ( status == l_True )
+        {
+            p->nSatCallsSat++;
+            Ssc_GiaSavePiPattern( pAig, p->vPattern );
+            Vec_IntPush( p->vDisPairs, Gia_ObjRepr(p->pAig, i) );
+            Vec_IntPush( p->vDisPairs, i );
+//            printf( "Try %2d and %2d: ", Gia_ObjRepr(p->pAig, i), i );
+//            Vec_IntPrint( p->vPattern );
+            if ( Gia_ObjRepr(p->pAig, i) > 0 )
+                Ssc_GiaResimulateOneClass( p, Gia_ObjRepr(p->pAig, i), i );
+        }
+        else if ( status == l_Undef )
+            p->nSatCallsUndec++;
+        else assert( 0 );
+p->timeSat += Abc_Clock() - clk;
+    }
+    if ( pAig->iPatsPi > 1 )
+    {
+clk = Abc_Clock();
+        while ( pAig->iPatsPi < 64 * pPars->nWords )
+            Ssc_GiaSavePiPattern( pAig, p->vPivot );
+        Ssc_GiaSimRound( pAig );
+        Ssc_GiaClassesRefine( pAig );
+        if ( pPars->fVerbose ) 
+            Gia_ManEquivPrintClasses( pAig, 0, 0 );
+        Ssc_GiaClassesCheckPairs( pAig, p->vDisPairs );
+        Vec_IntClear( p->vDisPairs );
+p->timeSimSat += Abc_Clock() - clk;
+    }
+//    Gia_ManEquivPrintClasses( pAig, 1, 0 );
+//    Gia_ManPrint( pAig );
+
+    // generate the resulting AIG
+    pResult = Gia_ManEquivReduce( pAig, 0, 0, 1, 0 );
+    if ( pResult == NULL )
+    {
+        printf( "There is no equivalences.\n" );
+        ABC_FREE( pAig->pReprs );
+        ABC_FREE( pAig->pNexts );
+        pResult = Gia_ManDup( pAig );
+    }
+    pResult = Gia_ManCleanup( pTemp = pResult );
+    Gia_ManStop( pTemp );
+    p->timeTotal = Abc_Clock() - clkTotal;
+    if ( pPars->fVerbose )
+        Ssc_ManPrintStats( p );
+    Ssc_ManStop( p );
+    // count the number of representatives
+    if ( pPars->fVerbose ) 
+    {
+        Abc_Print( 1, "Reduction in AIG nodes:%8d  ->%8d (%6.2f %%).  ", 
+            Gia_ManAndNum(pAig), Gia_ManAndNum(pResult), 
+            100.0 - 100.0 * Gia_ManAndNum(pResult) / Gia_ManAndNum(pAig) );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+    }
+    return pResult;
+}
+Gia_Man_t * Ssc_PerformSweeping( Gia_Man_t * pAig, Gia_Man_t * pCare, Ssc_Pars_t * pPars )
+{
+    Gia_Man_t * pResult = Ssc_PerformSweepingInt( pAig, pCare, pPars );
+    if ( pPars->fVerify )
+        Ssc_PerformVerification( pAig, pResult, pCare );
+    return pResult;
+}
+Gia_Man_t * Ssc_PerformSweepingConstr( Gia_Man_t * p, Ssc_Pars_t * pPars )
+{
+    Gia_Man_t * pAig, * pCare, * pResult;
+    int i;
+    if ( pPars->fVerbose )
+        Abc_Print( 0, "SAT sweeping AIG with %d constraints.\n", p->nConstrs );
+    if ( p->nConstrs == 0 )
+    {
+        pAig = Gia_ManDup( p );
+        pCare = Gia_ManStart( Gia_ManCiNum(p) + 2 );
+        pCare->pName = Abc_UtilStrsav( "care" );
+        for ( i = 0; i < Gia_ManCiNum(p); i++ )
+            Gia_ManAppendCi( pCare );
+        Gia_ManAppendCo( pCare, 0 );
+    }
+    else
+    {
+        Vec_Int_t * vOuts = Vec_IntStartNatural( Gia_ManPoNum(p) );
+        pAig = Gia_ManDupCones( p, Vec_IntArray(vOuts), Gia_ManPoNum(p) - p->nConstrs, 0 );
+        pCare = Gia_ManDupCones( p, Vec_IntArray(vOuts) + Gia_ManPoNum(p) - p->nConstrs, p->nConstrs, 0 );
+        Vec_IntFree( vOuts );
+    }
+    if ( pPars->fVerbose )
+    {
+        printf( "User AIG: " );
+        Gia_ManPrintStats( pAig, NULL );
+        printf( "Care AIG: " );
+        Gia_ManPrintStats( pCare, NULL );
+    }
+
+    pAig = Gia_ManDupLevelized( pResult = pAig );
+    Gia_ManStop( pResult );
+    pResult = Ssc_PerformSweeping( pAig, pCare, pPars );
+    if ( pPars->fAppend )
+    {
+        Gia_ManDupAppendShare( pResult, pCare );
+        pResult->nConstrs = Gia_ManPoNum(pCare);
+    }
+    Gia_ManStop( pAig );
+    Gia_ManStop( pCare );
+    return pResult;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/ssc/sscInt.h b/abc-build/src/proof/ssc/sscInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssc/sscInt.h
@@ -0,0 +1,135 @@
+/**CFile****************************************************************
+
+  FileName    [sscInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Choice computation for tech-mapping.]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: sscInt.h,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__ssc__sscInt_h
+#define ABC__aig__ssc__sscInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "aig/gia/gia.h"
+#include "sat/bsat/satSolver.h"
+#include "ssc.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// choicing manager
+typedef struct Ssc_Man_t_ Ssc_Man_t;
+struct Ssc_Man_t_
+{
+    // user data
+    Ssc_Pars_t *     pPars;          // choicing parameters
+    Gia_Man_t *      pAig;           // subject AIG
+    Gia_Man_t *      pCare;          // care set AIG
+    // internal data
+    Gia_Man_t *      pFraig;         // resulting AIG
+    sat_solver *     pSat;           // recyclable SAT solver
+    Vec_Int_t *      vId2Var;        // mapping of each node into its SAT var
+    Vec_Int_t *      vVar2Id;        // mapping of each SAT var into its node
+    Vec_Int_t *      vPivot;         // one SAT pattern
+    int              nSatVarsPivot;  // the number of variables for constraints
+    int              nSatVars;       // the current number of variables  
+    // temporary storage
+    Vec_Int_t *      vFront;         // supergate fanins
+    Vec_Int_t *      vFanins;        // supergate fanins
+    Vec_Int_t *      vPattern;       // counter-example
+    Vec_Int_t *      vDisPairs;      // disproved pairs
+    // SAT calls statistics
+    int              nSimRounds;     // the number of simulation rounds
+    int              nRecycles;      // the number of times SAT solver was recycled
+    int              nCallsSince;    // the number of calls since the last recycle
+    int              nSatCalls;      // the number of SAT calls
+    int              nSatCallsUnsat; // the number of unsat SAT calls
+    int              nSatCallsSat;   // the number of sat SAT calls
+    int              nSatCallsUndec; // the number of undec SAT calls
+    // runtime stats
+    abctime          timeSimInit;    // simulation and class computation
+    abctime          timeSimSat;     // simulation of the counter-examples
+    abctime          timeCnfGen;     // generation of CNF
+    abctime          timeSat;        // total SAT time
+    abctime          timeSatSat;     // sat
+    abctime          timeSatUnsat;   // unsat
+    abctime          timeSatUndec;   // undecided
+    abctime          timeOther;      // other runtime
+    abctime          timeTotal;      // total runtime
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int    Ssc_ObjSatVar( Ssc_Man_t * p, int iObj )             { return Vec_IntEntry(p->vId2Var, iObj);     }
+static inline void   Ssc_ObjSetSatVar( Ssc_Man_t * p, int iObj, int Num ) { Vec_IntWriteEntry(p->vId2Var, iObj, Num);  Vec_IntWriteEntry(p->vVar2Id, Num, iObj);  }
+static inline void   Ssc_ObjCleanSatVar( Ssc_Man_t * p, int Num )         { Vec_IntWriteEntry(p->vId2Var, Vec_IntEntry(p->vVar2Id, Num), Num);  Vec_IntWriteEntry(p->vVar2Id, Num, 0);                        }
+
+static inline int    Ssc_ObjFraig( Ssc_Man_t * p, Gia_Obj_t * pObj )      { return pObj->Value;           }
+static inline void   Ssc_ObjSetFraig( Gia_Obj_t * pObj, int iNode )       { pObj->Value = iNode;          }
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== sscClass.c =================================================*/
+extern void          Ssc_GiaClassesInit( Gia_Man_t * p );
+extern int           Ssc_GiaClassesRefine( Gia_Man_t * p );
+extern void          Ssc_GiaClassesCheckPairs( Gia_Man_t * p, Vec_Int_t * vDisPairs );
+extern int           Ssc_GiaSimClassRefineOneBit( Gia_Man_t * p, int i );
+/*=== sscCnf.c ===================================================*/
+extern void          Ssc_CnfNodeAddToSolver( Ssc_Man_t * p, Gia_Obj_t * pObj );
+/*=== sscCore.c ==================================================*/
+/*=== sscSat.c ===================================================*/
+extern void          Ssc_ManSatSolverRecycle( Ssc_Man_t * p );
+extern void          Ssc_ManStartSolver( Ssc_Man_t * p );
+extern Vec_Int_t *   Ssc_ManFindPivotSat( Ssc_Man_t * p );
+extern int           Ssc_ManCheckEquivalence( Ssc_Man_t * p, int iRepr, int iObj, int fCompl );
+/*=== sscSim.c ===================================================*/
+extern void          Ssc_GiaResetPiPattern( Gia_Man_t * p, int nWords );
+extern void          Ssc_GiaRandomPiPattern( Gia_Man_t * p, int nWords, Vec_Int_t * vPivot );
+extern int           Ssc_GiaTransferPiPattern( Gia_Man_t * pAig, Gia_Man_t * pCare, Vec_Int_t * vPivot );
+extern void          Ssc_GiaSavePiPattern( Gia_Man_t * p, Vec_Int_t * vPat );
+extern void          Ssc_GiaSimRound( Gia_Man_t * p );
+extern Vec_Int_t *   Ssc_GiaFindPivotSim( Gia_Man_t * p );
+extern int           Ssc_GiaEstimateCare( Gia_Man_t * p, int nWords );
+/*=== sscUtil.c ===================================================*/
+extern Gia_Man_t *   Ssc_GenerateOneHot( int nVars );
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/ssc/sscSat.c b/abc-build/src/proof/ssc/sscSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssc/sscSat.c
@@ -0,0 +1,430 @@
+/**CFile****************************************************************
+
+  FileName    [sscSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT sweeping under constraints.]
+
+  Synopsis    [SAT procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: sscSat.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sscInt.h"
+#include "sat/cnf/cnf.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Ssc_ObjSatLit( Ssc_Man_t * p, int Lit ) { return Abc_Var2Lit( Ssc_ObjSatVar(p, Abc_Lit2Var(Lit)), Abc_LitIsCompl(Lit) ); }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Addes clauses to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Gia_ManAddClausesMux( Ssc_Man_t * p, Gia_Obj_t * pNode )
+{
+    Gia_Obj_t * pNodeI, * pNodeT, * pNodeE;
+    int pLits[4], LitF, LitI, LitT, LitE, RetValue;
+    assert( !Gia_IsComplement( pNode ) );
+    assert( Gia_ObjIsMuxType( pNode ) );
+    // get nodes (I = if, T = then, E = else)
+    pNodeI = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE );
+    // get the Litiable numbers
+    LitF = Ssc_ObjSatLit( p, Gia_Obj2Lit(p->pFraig,pNode) );
+    LitI = Ssc_ObjSatLit( p, Gia_Obj2Lit(p->pFraig,pNodeI) );
+    LitT = Ssc_ObjSatLit( p, Gia_Obj2Lit(p->pFraig,pNodeT) );
+    LitE = Ssc_ObjSatLit( p, Gia_Obj2Lit(p->pFraig,pNodeE) );
+
+    // f = ITE(i, t, e)
+
+    // i' + t' + f
+    // i' + t  + f'
+    // i  + e' + f
+    // i  + e  + f'
+
+    // create four clauses
+    pLits[0] = Abc_LitNotCond(LitI, 1);
+    pLits[1] = Abc_LitNotCond(LitT, 1);
+    pLits[2] = Abc_LitNotCond(LitF, 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = Abc_LitNotCond(LitI, 1);
+    pLits[1] = Abc_LitNotCond(LitT, 0);
+    pLits[2] = Abc_LitNotCond(LitF, 1);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = Abc_LitNotCond(LitI, 0);
+    pLits[1] = Abc_LitNotCond(LitE, 1);
+    pLits[2] = Abc_LitNotCond(LitF, 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = Abc_LitNotCond(LitI, 0);
+    pLits[1] = Abc_LitNotCond(LitE, 0);
+    pLits[2] = Abc_LitNotCond(LitF, 1);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+
+    // two additional clauses
+    // t' & e' -> f'
+    // t  & e  -> f
+
+    // t  + e   + f'
+    // t' + e'  + f
+
+    if ( LitT == LitE )
+    {
+//        assert( fCompT == !fCompE );
+        return;
+    }
+
+    pLits[0] = Abc_LitNotCond(LitT, 0);
+    pLits[1] = Abc_LitNotCond(LitE, 0);
+    pLits[2] = Abc_LitNotCond(LitF, 1);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = Abc_LitNotCond(LitT, 1);
+    pLits[1] = Abc_LitNotCond(LitE, 1);
+    pLits[2] = Abc_LitNotCond(LitF, 0);
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Addes clauses to the solver.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Gia_ManAddClausesSuper( Ssc_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSuper )
+{
+    int i, RetValue, Lit, LitNode, pLits[2];
+    assert( !Gia_IsComplement(pNode) );
+    assert( Gia_ObjIsAnd( pNode ) );
+    // suppose AND-gate is A & B = C
+    // add !A => !C   or   A + !C
+    // add !B => !C   or   B + !C
+    LitNode = Ssc_ObjSatLit( p, Gia_Obj2Lit(p->pFraig,pNode) );
+    Vec_IntForEachEntry( vSuper, Lit, i )
+    {
+        pLits[0] = Ssc_ObjSatLit( p, Lit );
+        pLits[1] = Abc_LitNot( LitNode );
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+        // update literals
+        Vec_IntWriteEntry( vSuper, i, Abc_LitNot(pLits[0]) );
+    }
+    // add A & B => C   or   !A + !B + C
+    Vec_IntPush( vSuper, LitNode );
+    RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(vSuper), Vec_IntArray(vSuper) + Vec_IntSize(vSuper) );
+    assert( RetValue );
+    (void) RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Ssc_ManCollectSuper_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper )
+{
+    // stop at complements, PIs, and MUXes
+    if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) || Gia_ObjIsMuxType(pObj) )
+    {
+        Vec_IntPushUnique( vSuper, Gia_Obj2Lit(p, pObj) );
+        return;
+    }
+    Ssc_ManCollectSuper_rec( p, Gia_ObjChild0(pObj), vSuper );
+    Ssc_ManCollectSuper_rec( p, Gia_ObjChild1(pObj), vSuper );
+}
+static void Ssc_ManCollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper )
+{
+    assert( !Gia_IsComplement(pObj) );
+    assert( Gia_ObjIsAnd(pObj) );
+    Vec_IntClear( vSuper );
+    Ssc_ManCollectSuper_rec( p, Gia_ObjChild0(pObj), vSuper );
+    Ssc_ManCollectSuper_rec( p, Gia_ObjChild1(pObj), vSuper );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the solver clause database.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Ssc_ManCnfAddToFrontier( Ssc_Man_t * p, int Id, Vec_Int_t * vFront )
+{
+    Gia_Obj_t * pObj;
+    assert( Id > 0 );
+    if ( Ssc_ObjSatVar(p, Id) )
+        return;
+    pObj = Gia_ManObj( p->pFraig, Id );
+    Ssc_ObjSetSatVar( p, Id, p->nSatVars++ );
+    sat_solver_setnvars( p->pSat, p->nSatVars + 100 );
+    if ( Gia_ObjIsAnd(pObj) )
+        Vec_IntPush( vFront, Id );
+}
+static void Ssc_ManCnfNodeAddToSolver( Ssc_Man_t * p, int NodeId )
+{
+    Gia_Obj_t * pNode;
+    int i, k, Id, Lit;
+    abctime clk;
+    assert( NodeId > 0 );
+    // quit if CNF is ready
+    if ( Ssc_ObjSatVar(p, NodeId) )
+        return;
+clk = Abc_Clock();
+    // start the frontier
+    Vec_IntClear( p->vFront );
+    Ssc_ManCnfAddToFrontier( p, NodeId, p->vFront );
+    // explore nodes in the frontier
+    Gia_ManForEachObjVec( p->vFront, p->pFraig, pNode, i )
+    {
+        // create the supergate
+        assert( Ssc_ObjSatVar(p, Gia_ObjId(p->pFraig, pNode)) );
+        if ( Gia_ObjIsMuxType(pNode) )
+        {
+            Vec_IntClear( p->vFanins );
+            Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId0p( p->pFraig, Gia_ObjFanin0(pNode) ) );
+            Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId0p( p->pFraig, Gia_ObjFanin1(pNode) ) );
+            Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId1p( p->pFraig, Gia_ObjFanin0(pNode) ) );
+            Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId1p( p->pFraig, Gia_ObjFanin1(pNode) ) );
+            Vec_IntForEachEntry( p->vFanins, Id, k )
+                Ssc_ManCnfAddToFrontier( p, Id, p->vFront );
+            Gia_ManAddClausesMux( p, pNode );
+        }
+        else
+        {
+            Ssc_ManCollectSuper( p->pFraig, pNode, p->vFanins );
+            Vec_IntForEachEntry( p->vFanins, Lit, k )
+                Ssc_ManCnfAddToFrontier( p, Abc_Lit2Var(Lit), p->vFront );
+            Gia_ManAddClausesSuper( p, pNode, p->vFanins );
+        }
+        assert( Vec_IntSize(p->vFanins) > 1 );
+    }
+p->timeCnfGen += Abc_Clock() - clk;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the SAT solver for constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssc_ManStartSolver( Ssc_Man_t * p )
+{
+    Aig_Man_t * pMan = Gia_ManToAigSimple( p->pFraig );
+    Cnf_Dat_t * pDat = Cnf_Derive( pMan, 0 );
+    Gia_Obj_t * pObj;
+    sat_solver * pSat;
+    int i, status;
+    assert( p->pSat == NULL && p->vId2Var == NULL );
+    assert( Aig_ManObjNumMax(pMan) == Gia_ManObjNum(p->pFraig) );
+    Aig_ManStop( pMan );
+    // save variable mapping
+    p->nSatVarsPivot = p->nSatVars = pDat->nVars;
+    p->vId2Var = Vec_IntStart( Gia_ManCandNum(p->pAig) + Gia_ManCandNum(p->pCare) + 10 ); // mapping of each node into its SAT var
+    p->vVar2Id = Vec_IntStart( Gia_ManCandNum(p->pAig) + Gia_ManCandNum(p->pCare) + 10 ); // mapping of each SAT var into its node
+    Ssc_ObjSetSatVar( p, 0, pDat->pVarNums[0] );
+    Gia_ManForEachCi( p->pFraig, pObj, i )
+    {
+        int iObj = Gia_ObjId( p->pFraig, pObj );
+        Ssc_ObjSetSatVar( p, iObj, pDat->pVarNums[iObj] );
+    }
+//Cnf_DataWriteIntoFile( pDat, "dump.cnf", 1, NULL, NULL );
+    // start the SAT solver
+    pSat = sat_solver_new();
+    sat_solver_setnvars( pSat, pDat->nVars + 1000 );
+    for ( i = 0; i < pDat->nClauses; i++ )
+    {
+        if ( !sat_solver_addclause( pSat, pDat->pClauses[i], pDat->pClauses[i+1] ) )
+        {
+            Cnf_DataFree( pDat );
+            sat_solver_delete( pSat );
+            return;
+        }
+    }
+    Cnf_DataFree( pDat );
+    status = sat_solver_simplify( pSat );
+    if ( status == 0 )
+    {
+        sat_solver_delete( pSat );
+        return;
+    }
+    p->pSat = pSat;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssc_ManCollectSatPattern( Ssc_Man_t * p, Vec_Int_t * vPattern )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Vec_IntClear( vPattern );
+    Gia_ManForEachCi( p->pFraig, pObj, i )
+        Vec_IntPush( vPattern, sat_solver_var_value(p->pSat, Ssc_ObjSatVar(p, Gia_ObjId(p->pFraig, pObj))) );
+}
+Vec_Int_t * Ssc_ManFindPivotSat( Ssc_Man_t * p )
+{
+    Vec_Int_t * vInit;
+    int status = sat_solver_solve( p->pSat, NULL, NULL, p->pPars->nBTLimit, 0, 0, 0 );
+    if ( status == l_False )
+        return (Vec_Int_t *)(ABC_PTRINT_T)1;
+    if ( status == l_Undef )
+        return NULL;
+    assert( status == l_True );
+    vInit = Vec_IntAlloc( Gia_ManCiNum(p->pFraig) );
+    Ssc_ManCollectSatPattern( p, vInit );
+    return vInit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssc_ManCheckEquivalence( Ssc_Man_t * p, int iRepr, int iNode, int fCompl )
+{
+    int pLitsSat[2], RetValue;
+    abctime clk;
+    assert( iRepr != iNode );
+    if ( iRepr > iNode )
+        return l_Undef;
+    assert( iRepr < iNode );
+//    if ( p->nTimeOut )
+//        sat_solver_set_runtime_limit( p->pSat, p->nTimeOut * CLOCKS_PER_SEC + Abc_Clock() );
+
+    // create CNF
+    if ( iRepr )
+    Ssc_ManCnfNodeAddToSolver( p, iRepr );
+    Ssc_ManCnfNodeAddToSolver( p, iNode );
+    sat_solver_compress( p->pSat );
+
+    // order the literals
+    pLitsSat[0] = Abc_Var2Lit( Ssc_ObjSatVar(p, iRepr), 0 );
+    pLitsSat[1] = Abc_Var2Lit( Ssc_ObjSatVar(p, iNode), fCompl ^ (int)(iRepr > 0) );
+
+    // solve under assumptions
+    // A = 1; B = 0
+    clk = Abc_Clock();
+    RetValue = sat_solver_solve( p->pSat, pLitsSat, pLitsSat + 2, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( RetValue == l_False )
+    {
+        pLitsSat[0] = Abc_LitNot( pLitsSat[0] ); // compl
+        pLitsSat[1] = Abc_LitNot( pLitsSat[1] ); // compl
+        RetValue = sat_solver_addclause( p->pSat, pLitsSat, pLitsSat + 2 );
+        assert( RetValue );
+        p->timeSatUnsat += Abc_Clock() - clk;
+    }
+    else if ( RetValue == l_True )
+    {
+        Ssc_ManCollectSatPattern( p, p->vPattern );
+        p->timeSatSat += Abc_Clock() - clk;
+        return l_True;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+        p->timeSatUndec += Abc_Clock() - clk;
+        return l_Undef;
+    }
+
+    // if the old node was constant 0, we already know the answer
+    if ( iRepr == 0 )
+        return l_False;
+
+    // solve under assumptions
+    // A = 0; B = 1
+    clk = Abc_Clock();
+    RetValue = sat_solver_solve( p->pSat, pLitsSat, pLitsSat + 2, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( RetValue == l_False )
+    {
+        pLitsSat[0] = Abc_LitNot( pLitsSat[0] );
+        pLitsSat[1] = Abc_LitNot( pLitsSat[1] );
+        RetValue = sat_solver_addclause( p->pSat, pLitsSat, pLitsSat + 2 );
+        assert( RetValue );
+        p->timeSatUnsat += Abc_Clock() - clk;
+    }
+    else if ( RetValue == l_True )
+    {
+        Ssc_ManCollectSatPattern( p, p->vPattern );
+        p->timeSatSat += Abc_Clock() - clk;
+        return l_True;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+        p->timeSatUndec += Abc_Clock() - clk;
+        return l_Undef;
+    }
+    return l_False;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/ssc/sscSim.c b/abc-build/src/proof/ssc/sscSim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssc/sscSim.c
@@ -0,0 +1,364 @@
+/**CFile****************************************************************
+
+  FileName    [sscSim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT sweeping under constraints.]
+
+  Synopsis    [Simulation procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: sscSim.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sscInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline word Ssc_Random()            { return ((word)Gia_ManRandom(0) << 32) | ((word)Gia_ManRandom(0) << 0);              }
+static inline word Ssc_Random1( int Bit )  { return ((word)Gia_ManRandom(0) << 32) | ((word)Gia_ManRandom(0) << 1) | (word)Bit;  }
+static inline word Ssc_Random2()           { return ((word)Gia_ManRandom(0) << 32) | ((word)Gia_ManRandom(0) << 2) | (word)2;    }
+
+static inline void Ssc_SimAnd( word * pSim, word * pSim0, word * pSim1, int nWords, int fComp0, int fComp1 )
+{
+    int w;
+    if ( fComp0 && fComp1 ) for ( w = 0; w < nWords; w++ )  pSim[w] = ~(pSim0[w] | pSim1[w]);
+    else if ( fComp0 )      for ( w = 0; w < nWords; w++ )  pSim[w] =  ~pSim0[w] & pSim1[w];
+    else if ( fComp1 )      for ( w = 0; w < nWords; w++ )  pSim[w] =   pSim0[w] &~pSim1[w];
+    else                    for ( w = 0; w < nWords; w++ )  pSim[w] =   pSim0[w] & pSim1[w];
+}
+
+static inline void Ssc_SimDup( word * pSim, word * pSim0, int nWords, int fComp0 )
+{
+    int w;
+    if ( fComp0 ) for ( w = 0; w < nWords; w++ )  pSim[w] = ~pSim0[w];
+    else          for ( w = 0; w < nWords; w++ )  pSim[w] =  pSim0[w];
+}
+
+static inline void Ssc_SimConst( word * pSim, int nWords, int fComp0 )
+{
+    int w;
+    if ( fComp0 ) for ( w = 0; w < nWords; w++ )  pSim[w] = ~(word)0;
+    else          for ( w = 0; w < nWords; w++ )  pSim[w] = 0;
+}
+
+static inline void Ssc_SimOr( word * pSim, word * pSim0, int nWords, int fComp0 )
+{
+    int w;
+    if ( fComp0 ) for ( w = 0; w < nWords; w++ )  pSim[w] |= ~pSim0[w];
+    else          for ( w = 0; w < nWords; w++ )  pSim[w] |=  pSim0[w];
+}
+
+static inline int Ssc_SimFindBitWord( word t )
+{
+    int n = 0;
+    if ( t == 0 ) return -1;
+    if ( (t & 0x00000000FFFFFFFF) == 0 ) { n += 32; t >>= 32; }
+    if ( (t & 0x000000000000FFFF) == 0 ) { n += 16; t >>= 16; }
+    if ( (t & 0x00000000000000FF) == 0 ) { n +=  8; t >>=  8; }
+    if ( (t & 0x000000000000000F) == 0 ) { n +=  4; t >>=  4; }
+    if ( (t & 0x0000000000000003) == 0 ) { n +=  2; t >>=  2; }
+    if ( (t & 0x0000000000000001) == 0 ) { n++; }
+    return n;
+}
+static inline int Ssc_SimFindBit( word * pSim, int nWords )
+{
+    int w;
+    for ( w = 0; w < nWords; w++ )
+        if ( pSim[w] )
+            return 64*w + Ssc_SimFindBitWord(pSim[w]);
+    return -1;
+}
+
+static inline int Ssc_SimCountBitsWord( word x )
+{
+    x = x - ((x >> 1) & ABC_CONST(0x5555555555555555));   
+    x = (x & ABC_CONST(0x3333333333333333)) + ((x >> 2) & ABC_CONST(0x3333333333333333));    
+    x = (x + (x >> 4)) & ABC_CONST(0x0F0F0F0F0F0F0F0F);    
+    x = x + (x >> 8);
+    x = x + (x >> 16);
+    x = x + (x >> 32); 
+    return (int)(x & 0xFF);
+}
+static inline int Ssc_SimCountBits( word * pSim, int nWords )
+{
+    int w, Counter = 0;
+    for ( w = 0; w < nWords; w++ )
+        Counter += Ssc_SimCountBitsWord(pSim[w]);
+    return Counter;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Vec_WrdDoubleSimInfo( Vec_Wrd_t * p, int nObjs )
+{
+    word * pArray = ABC_CALLOC( word, 2 * Vec_WrdSize(p) );
+    int i, nWords = Vec_WrdSize(p) / nObjs;
+    assert( Vec_WrdSize(p) % nObjs == 0 );
+    for ( i = 0; i < nObjs; i++ )
+        memcpy( pArray + 2*i*nWords, p->pArray + i*nWords, sizeof(word) * nWords );
+    ABC_FREE( p->pArray ); p->pArray = pArray;
+    p->nSize = p->nCap = 2*nWords*nObjs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssc_GiaResetPiPattern( Gia_Man_t * p, int nWords )
+{
+    p->iPatsPi = 0;
+    if ( p->vSimsPi == NULL )
+        p->vSimsPi = Vec_WrdStart(0);
+    Vec_WrdFill( p->vSimsPi, nWords * Gia_ManCiNum(p), 0 );
+    assert( nWords == Gia_ObjSimWords( p ) );
+}
+void Ssc_GiaSavePiPattern( Gia_Man_t * p, Vec_Int_t * vPat )
+{
+    word * pSimPi;
+    int i;
+    assert( Vec_IntSize(vPat) == Gia_ManCiNum(p) );
+    if ( p->iPatsPi == 64 * Gia_ObjSimWords(p) )
+        Vec_WrdDoubleSimInfo( p->vSimsPi, Gia_ManCiNum(p) );
+    assert( p->iPatsPi < 64 * Gia_ObjSimWords(p) );
+    pSimPi = Gia_ObjSimPi( p, 0 );
+    for ( i = 0; i < Gia_ManCiNum(p); i++, pSimPi += Gia_ObjSimWords(p) )
+        if ( Vec_IntEntry(vPat, i) )
+            Abc_InfoSetBit( (unsigned *)pSimPi, p->iPatsPi );
+    p->iPatsPi++;
+}
+void Ssc_GiaRandomPiPattern( Gia_Man_t * p, int nWords, Vec_Int_t * vPivot )
+{
+    word * pSimPi;
+    int i, w;
+    Ssc_GiaResetPiPattern( p, nWords );
+    pSimPi = Gia_ObjSimPi( p, 0 );
+    for ( i = 0; i < Gia_ManPiNum(p); i++, pSimPi += nWords )
+    {
+        pSimPi[0] = vPivot ? Ssc_Random1(Vec_IntEntry(vPivot, i)) : Ssc_Random2();
+        for ( w = 1; w < nWords; w++ )
+            pSimPi[w] = Ssc_Random();
+//        if ( i < 10 )
+//            Extra_PrintBinary( stdout, (unsigned *)pSimPi, 64 ), printf( "\n" );
+    }
+}
+void Ssc_GiaPrintPiPatterns( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    word * pSimAig;
+    int i;//, nWords = Gia_ObjSimWords( p );
+    Gia_ManForEachCi( p, pObj, i )
+    {
+        pSimAig = Gia_ObjSimObj( p, pObj );
+//        Extra_PrintBinary( stdout, pSimAig, 64 * nWords );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfer the simulation pattern from pCare to pAig.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssc_GiaTransferPiPattern( Gia_Man_t * pAig, Gia_Man_t * pCare, Vec_Int_t * vPivot )
+{
+    extern word * Ssc_GiaGetCareMask( Gia_Man_t * p );
+    Gia_Obj_t * pObj;
+    int i, w, nWords = Gia_ObjSimWords( pCare );
+    word * pCareMask = Ssc_GiaGetCareMask( pCare );
+    int Count = Ssc_SimCountBits( pCareMask, nWords );
+    word * pSimPiCare, * pSimPiAig;
+    if ( Count == 0 )
+    {
+        ABC_FREE( pCareMask );
+        return 0;
+    }
+    Ssc_GiaResetPiPattern( pAig, nWords );
+    Gia_ManForEachCi( pCare, pObj, i )
+    {
+        pSimPiAig  = Gia_ObjSimPi( pAig, i );
+        pSimPiCare = Gia_ObjSimObj( pCare, pObj );
+        for ( w = 0; w < nWords; w++ )
+            if ( Vec_IntEntry(vPivot, i) )
+                pSimPiAig[w] = pSimPiCare[w] | ~pCareMask[w];
+            else
+                pSimPiAig[w] = pSimPiCare[w] & pCareMask[w];
+    }
+    ABC_FREE( pCareMask );
+    return Count;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssc_GiaResetSimInfo( Gia_Man_t * p )
+{
+    assert( Vec_WrdSize(p->vSimsPi) % Gia_ManCiNum(p) == 0 );
+    if ( p->vSims == NULL )
+        p->vSims = Vec_WrdAlloc(0);
+    Vec_WrdFill( p->vSims, Gia_ObjSimWords(p) * Gia_ManObjNum(p), 0 );
+}
+void Ssc_GiaSimRound( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    word * pSim, * pSim0, * pSim1;
+    int i, nWords = Gia_ObjSimWords(p);
+    Ssc_GiaResetSimInfo( p );
+    assert( nWords == Vec_WrdSize(p->vSims) / Gia_ManObjNum(p) );
+    // constant node
+    Ssc_SimConst( Gia_ObjSim(p, 0), nWords, 0 );
+    // primary inputs
+    pSim = Gia_ObjSim( p, 1 );
+    pSim0 = Gia_ObjSimPi( p, 0 );
+    Gia_ManForEachCi( p, pObj, i )
+    {
+        assert( pSim == Gia_ObjSimObj( p, pObj ) );
+        Ssc_SimDup( pSim, pSim0, nWords, 0 );
+        pSim += nWords;
+        pSim0 += nWords;
+    }
+    // intermediate nodes
+    pSim = Gia_ObjSim( p, 1+Gia_ManCiNum(p) );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        assert( pSim == Gia_ObjSim( p, i ) );
+        pSim0 = pSim - pObj->iDiff0 * nWords;
+        pSim1 = pSim - pObj->iDiff1 * nWords;
+        Ssc_SimAnd( pSim, pSim0, pSim1, nWords, Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj) );
+        pSim += nWords;
+    }
+    // primary outputs
+    pSim = Gia_ObjSim( p, Gia_ManObjNum(p) - Gia_ManPoNum(p) );
+    Gia_ManForEachPo( p, pObj, i )
+    {
+        assert( pSim == Gia_ObjSimObj( p, pObj ) );
+        pSim0 = pSim - pObj->iDiff0 * nWords;
+        Ssc_SimDup( pSim, pSim0, nWords, Gia_ObjFaninC0(pObj) );
+//        Extra_PrintBinary( stdout, pSim, 64 ), printf( "\n" );
+        pSim += nWords;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns one SAT assignment of the PIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word * Ssc_GiaGetCareMask( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, nWords = Gia_ObjSimWords( p );
+    word * pRes = ABC_FALLOC( word, nWords );
+    Gia_ManForEachPo( p, pObj, i )
+        Ssc_SimAnd( pRes, pRes, Gia_ObjSimObj(p, pObj), nWords, 0, 0 );
+    return pRes;
+}
+Vec_Int_t * Ssc_GiaGetOneSim( Gia_Man_t * p )
+{
+    Vec_Int_t * vInit;
+    Gia_Obj_t * pObj;
+    int i, iBit, nWords = Gia_ObjSimWords( p );
+    word * pRes = Ssc_GiaGetCareMask( p );
+    iBit = Ssc_SimFindBit( pRes, nWords );
+    ABC_FREE( pRes );
+    if ( iBit == -1 )
+        return NULL;
+    vInit = Vec_IntAlloc( 100 );
+    Gia_ManForEachCi( p, pObj, i )
+        Vec_IntPush( vInit, Abc_InfoHasBit((unsigned *)Gia_ObjSimObj(p, pObj), iBit) );
+    return vInit;
+}
+Vec_Int_t * Ssc_GiaFindPivotSim( Gia_Man_t * p )
+{
+    Vec_Int_t * vInit;
+    Ssc_GiaRandomPiPattern( p, 1, NULL );
+    Ssc_GiaSimRound( p );
+    vInit = Ssc_GiaGetOneSim( p );
+    return vInit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssc_GiaCountCaresSim( Gia_Man_t * p )
+{
+    word * pRes = Ssc_GiaGetCareMask( p );
+    int nWords = Gia_ObjSimWords( p );
+    int Count = Ssc_SimCountBits( pRes, nWords );
+    ABC_FREE( pRes );
+    return Count;
+}
+int Ssc_GiaEstimateCare( Gia_Man_t * p, int nWords )
+{
+    Ssc_GiaRandomPiPattern( p, nWords, NULL );
+    Ssc_GiaSimRound( p );
+    return Ssc_GiaCountCaresSim( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/ssc/sscUtil.c b/abc-build/src/proof/ssc/sscUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssc/sscUtil.c
@@ -0,0 +1,173 @@
+/**CFile****************************************************************
+
+  FileName    [sscUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT sweeping under constraints.]
+
+  Synopsis    [Various utilities.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 29, 2008.]
+
+  Revision    [$Id: sscUtil.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sscInt.h"
+#include "sat/cnf/cnf.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDropContained( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew;
+    Aig_Man_t * pMan = Gia_ManToAigSimple( p );
+    Cnf_Dat_t * pDat = Cnf_Derive( pMan, Gia_ManPoNum(p) );
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vLits, * vKeep;
+    sat_solver * pSat;
+    int ConstLit = Abc_Var2Lit(pDat->pVarNums[0], 0);
+    int i, status;//, Count = 0;
+    Aig_ManStop( pMan );
+
+    vLits = Vec_IntAlloc( Gia_ManPoNum(p) );
+    Gia_ManForEachPo( p, pObj, i )
+    {
+        int iObj = Gia_ObjId( p, pObj );
+        Vec_IntPush( vLits, Abc_Var2Lit(pDat->pVarNums[iObj], 1) );
+    }
+
+    // start the SAT solver
+    pSat = sat_solver_new();
+    sat_solver_setnvars( pSat, pDat->nVars );
+    for ( i = 0; i < pDat->nClauses; i++ )
+    {
+        if ( !sat_solver_addclause( pSat, pDat->pClauses[i], pDat->pClauses[i+1] ) )
+        {
+            Cnf_DataFree( pDat );
+            sat_solver_delete( pSat );
+            Vec_IntFree( vLits );
+            return NULL;
+        }
+    }
+    Cnf_DataFree( pDat );
+    status = sat_solver_simplify( pSat );
+    if ( status == 0 )
+    {
+        sat_solver_delete( pSat );
+        Vec_IntFree( vLits );
+        return NULL;
+    }
+
+    // iterate over POs
+    vKeep = Vec_IntAlloc( Gia_ManPoNum(p) );
+    Gia_ManForEachPo( p, pObj, i )
+    {
+        Vec_IntWriteEntry( vLits, i, Abc_LitNot(Vec_IntEntry(vLits,i)) );
+        status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 );
+        Vec_IntWriteEntry( vLits, i, Abc_LitNot(Vec_IntEntry(vLits,i)) );
+        if ( status == l_False )
+            Vec_IntWriteEntry( vLits, i, ConstLit ); // const1 SAT var is always true
+        else 
+        {
+            assert( status = l_True );
+            Vec_IntPush( vKeep, i );
+        }
+    }
+    sat_solver_delete( pSat );
+    Vec_IntFree( vLits );
+    if ( Vec_IntSize(vKeep) == Gia_ManPoNum(p) )
+    {
+        Vec_IntFree( vKeep );
+        return Gia_ManDup(p);
+    }
+    pNew = Gia_ManDupCones( p, Vec_IntArray(vKeep), Vec_IntSize(vKeep), 0 );
+    Vec_IntFree( vKeep );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManOptimizeRing( Gia_Man_t * p )
+{
+    Ssc_Pars_t Pars, * pPars = &Pars;
+    Gia_Man_t * pTemp, * pAux;
+    int i;
+    assert( p->nConstrs == 0 );
+    printf( "User AIG: " );
+    Gia_ManPrintStats( p, NULL );
+    pTemp = Gia_ManDropContained( p );
+    printf( "Drop AIG: " );
+    Gia_ManPrintStats( pTemp, NULL );
+//    return pTemp;
+    if ( Gia_ManPoNum(pTemp) == 1 )
+        return pTemp;
+    Ssc_ManSetDefaultParams( pPars );
+    pPars->fAppend  = 1;
+    pPars->fVerbose = 0;
+    pTemp->nConstrs = Gia_ManPoNum(pTemp) - 1;    
+    for ( i = 0; i < Gia_ManPoNum(pTemp); i++ )
+    {
+        // move i-th PO forward
+        Gia_ManSwapPos( pTemp, i );
+        pTemp = Gia_ManDupDfs( pAux = pTemp );
+        Gia_ManStop( pAux );
+        // minimize this PO
+        pTemp = Ssc_PerformSweepingConstr( pAux = pTemp, pPars );
+        Gia_ManStop( pAux );
+        pTemp = Gia_ManDupDfs( pAux = pTemp );
+        Gia_ManStop( pAux );
+        // move i-th PO back
+        Gia_ManSwapPos( pTemp, i );
+        pTemp = Gia_ManDupDfs( pAux = pTemp );
+        Gia_ManStop( pAux );
+        // report results
+        printf( "AIG%3d  : ", i );
+        Gia_ManPrintStats( pTemp, NULL );
+    }
+    pTemp->nConstrs = 0;
+    return pTemp;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/ssw/module.make b/abc-build/src/proof/ssw/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/module.make
@@ -0,0 +1,20 @@
+SRC +=	src/proof/ssw/sswAig.c \
+	src/proof/ssw/sswBmc.c \
+	src/proof/ssw/sswClass.c \
+	src/proof/ssw/sswCnf.c \
+	src/proof/ssw/sswConstr.c \
+	src/proof/ssw/sswCore.c \
+	src/proof/ssw/sswDyn.c \
+	src/proof/ssw/sswFilter.c \
+	src/proof/ssw/sswIslands.c \
+	src/proof/ssw/sswLcorr.c \
+	src/proof/ssw/sswMan.c \
+	src/proof/ssw/sswPart.c \
+	src/proof/ssw/sswPairs.c \
+	src/proof/ssw/sswRarity.c \
+	src/proof/ssw/sswSat.c \
+	src/proof/ssw/sswSemi.c \
+	src/proof/ssw/sswSim.c \
+	src/proof/ssw/sswSimSat.c \
+	src/proof/ssw/sswSweep.c \
+	src/proof/ssw/sswUnique.c
diff --git a/abc-build/src/proof/ssw/ssw.h b/abc-build/src/proof/ssw/ssw.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/ssw.h
@@ -0,0 +1,170 @@
+/**CFile****************************************************************
+
+  FileName    [ssw.h] 
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: ssw.h,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__ssw__ssw_h
+#define ABC__aig__ssw__ssw_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// choicing parameters
+typedef struct Ssw_Pars_t_ Ssw_Pars_t;
+struct Ssw_Pars_t_
+{
+    int              nPartSize;     // size of the partition
+    int              nOverSize;     // size of the overlap between partitions
+    int              nFramesK;      // the induction depth
+    int              nFramesAddSim; // the number of additional frames to simulate
+    int              fConstrs;      // treat the last nConstrs POs as seq constraints
+    int              fMergeFull;    // enables full merge when constraints are used
+    int              nMaxLevs;      // the max number of levels of nodes to consider
+    int              nBTLimit;      // conflict limit at a node
+    int              nBTLimitGlobal;// conflict limit for multiple runs
+    int              nMinDomSize;   // min clock domain considered for optimization
+    int              nItersStop;    // stop after the given number of iterations
+    int              fDumpSRInit;   // dumps speculative reduction
+    int              nResimDelta;   // the number of nodes to resimulate
+    int              nStepsMax;     // (scorr only) the max number of induction steps
+    int              TimeLimit;     // time out in seconds
+    int              fPolarFlip;    // uses polarity adjustment
+    int              fLatchCorr;    // perform register correspondence
+    int              fConstCorr;    // perform constant correspondence
+    int              fOutputCorr;   // perform 'PO correspondence'
+    int              fSemiFormal;   // enable semiformal filtering
+//    int              fUniqueness;   // enable uniqueness constraints
+    int              fDynamic;      // enable dynamic addition of constraints
+    int              fLocalSim;     // enable local simulation simulation
+    int              fPartSigCorr;  // uses partial signal correspondence
+    int              nIsleDist;     // extends islands by the given distance
+    int              fScorrGia;     // new signal correspondence implementation
+    int              fUseCSat;      // new SAT solver using when fScorrGia is selected
+    int              fVerbose;      // verbose stats
+    int              fFlopVerbose;  // verbose printout of redundant flops
+    int              fEquivDump;    // enables dumping equivalences
+    int              fStopWhenGone; // stop when PO output is not a candidate constant
+    // optimized latch correspondence
+    int              fLatchCorrOpt; // perform register correspondence (optimized)
+    int              nSatVarMax;    // max number of SAT vars before recycling SAT solver (optimized latch corr only)
+    int              nRecycleCalls; // calls to perform before recycling SAT solver (optimized latch corr only)
+    // optimized signal correspondence
+    int              nSatVarMax2;   // max number of SAT vars before recycling SAT solver (optimized latch corr only)
+    int              nRecycleCalls2;// calls to perform before recycling SAT solver (optimized latch corr only)
+    // internal parameters
+    int              nIters;        // the number of iterations performed
+    int              nConflicts;    // the total number of conflicts performed
+    // callback
+    void *           pData;
+    void *           pFunc;
+};
+
+typedef struct Ssw_RarPars_t_ Ssw_RarPars_t;
+struct Ssw_RarPars_t_
+{
+    int              nFrames;
+    int              nWords;
+    int              nBinSize;
+    int              nRounds;
+    int              nRestart;
+    int              nRandSeed;
+    int              TimeOut;
+    int              TimeOutGap;
+    int              fSolveAll;
+    int              fSetLastState;
+    int              fVerbose;
+    int              fNotVerbose;
+    int              fSilent;
+    int              fDropSatOuts;
+    int              fMiter;
+    int              fUseCex;
+    int              fLatchOnly;
+    int              fUseFfGrouping;
+    int              nSolved;
+    Abc_Cex_t *      pCex;
+    int(*pFuncOnFail)(int,Abc_Cex_t*); // called for a failed output in MO mode
+};
+
+typedef struct Ssw_Sml_t_ Ssw_Sml_t; // sequential simulation manager
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== sswBmc.c ==========================================================*/
+extern int           Ssw_BmcDynamic( Aig_Man_t * pAig, int nFramesMax, int nConfLimit, int fVerbose, int * piFrame );
+/*=== sswConstr.c ==========================================================*/
+extern int           Ssw_ManSetConstrPhases( Aig_Man_t * p, int nFrames, Vec_Int_t ** pvInits );
+/*=== sswCore.c ==========================================================*/
+extern void          Ssw_ManSetDefaultParams( Ssw_Pars_t * p );
+extern void          Ssw_ManSetDefaultParamsLcorr( Ssw_Pars_t * p );
+extern Aig_Man_t *   Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars );
+extern Aig_Man_t *   Ssw_LatchCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars );
+/*=== sswIslands.c ==========================================================*/
+extern int           Ssw_SecWithSimilarityPairs( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars );
+extern int           Ssw_SecWithSimilarity( Aig_Man_t * p0, Aig_Man_t * p1, Ssw_Pars_t * pPars );
+/*=== sswMiter.c ===================================================*/
+/*=== sswPart.c ==========================================================*/
+extern Aig_Man_t *   Ssw_SignalCorrespondencePart( Aig_Man_t * pAig, Ssw_Pars_t * pPars );
+/*=== sswPairs.c ===================================================*/
+extern int           Ssw_MiterStatus( Aig_Man_t * p, int fVerbose );
+extern int           Ssw_SecWithPairs( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2, Ssw_Pars_t * pPars );
+extern int           Ssw_SecGeneral( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Ssw_Pars_t * pPars );
+extern int           Ssw_SecGeneralMiter( Aig_Man_t * pMiter, Ssw_Pars_t * pPars );
+/*=== sswRarity.c ===================================================*/
+extern void          Ssw_RarSetDefaultParams( Ssw_RarPars_t * p );
+extern int           Ssw_RarSignalFilter( Aig_Man_t * pAig, Ssw_RarPars_t * pPars );
+extern int           Ssw_RarSimulate( Aig_Man_t * pAig, Ssw_RarPars_t * pPars );
+/*=== sswSim.c ===================================================*/
+extern Ssw_Sml_t *   Ssw_SmlSimulateComb( Aig_Man_t * pAig, int nWords );
+extern Ssw_Sml_t *   Ssw_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords );
+extern void          Ssw_SmlUnnormalize( Ssw_Sml_t * p );
+extern void          Ssw_SmlStop( Ssw_Sml_t * p );
+extern int           Ssw_SmlNumFrames( Ssw_Sml_t * p );
+extern int           Ssw_SmlNumWordsTotal( Ssw_Sml_t * p );
+extern unsigned *    Ssw_SmlSimInfo( Ssw_Sml_t * p, Aig_Obj_t * pObj );
+extern int           Ssw_SmlObjsAreEqualWord( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 );
+extern void          Ssw_SmlInitializeSpecial( Ssw_Sml_t * p, Vec_Int_t * vInit );
+extern int           Ssw_SmlCheckNonConstOutputs( Ssw_Sml_t * p );
+extern Vec_Ptr_t *   Ssw_SmlSimDataPointers( Ssw_Sml_t * p );
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/ssw/sswAig.c b/abc-build/src/proof/ssw/sswAig.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswAig.c
@@ -0,0 +1,258 @@
+/**CFile****************************************************************
+
+  FileName    [sswAig.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [AIG manipulation.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswAig.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the SAT manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ssw_Frm_t * Ssw_FrmStart( Aig_Man_t * pAig )
+{
+    Ssw_Frm_t * p;
+    p = ABC_ALLOC( Ssw_Frm_t, 1 );
+    memset( p, 0, sizeof(Ssw_Frm_t) );
+    p->pAig          = pAig;
+    p->nObjs         = Aig_ManObjNumMax( pAig );
+    p->nFrames       = 0;
+    p->pFrames       = NULL;
+    p->vAig2Frm      = Vec_PtrAlloc( 0 );
+    Vec_PtrFill( p->vAig2Frm, 2 * p->nObjs, NULL );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the SAT manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_FrmStop( Ssw_Frm_t * p )
+{
+    if ( p->pFrames )
+        Aig_ManStop( p->pFrames );
+    Vec_PtrFree( p->vAig2Frm );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs speculative reduction for one node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Ssw_FramesConstrainNode( Ssw_Man_t * p, Aig_Man_t * pFrames, Aig_Man_t * pAig, Aig_Obj_t * pObj, int iFrame, int fTwoPos )
+{
+    Aig_Obj_t * pObjNew, * pObjNew2, * pObjRepr, * pObjReprNew, * pMiter;
+    // skip nodes without representative
+    pObjRepr = Aig_ObjRepr(pAig, pObj);
+    if ( pObjRepr == NULL )
+        return;
+    p->nConstrTotal++;
+    assert( pObjRepr->Id < pObj->Id );
+    // get the new node
+    pObjNew = Ssw_ObjFrame( p, pObj, iFrame );
+    // get the new node of the representative
+    pObjReprNew = Ssw_ObjFrame( p, pObjRepr, iFrame );
+    // if this is the same node, no need to add constraints
+    if ( pObj->fPhase == pObjRepr->fPhase )
+    {
+        assert( pObjNew != Aig_Not(pObjReprNew) );
+        if ( pObjNew == pObjReprNew )
+            return;
+    }
+    else
+    {
+        assert( pObjNew != pObjReprNew );
+        if ( pObjNew == Aig_Not(pObjReprNew) )
+            return;
+    }
+    p->nConstrReduced++;
+    // these are different nodes - perform speculative reduction
+    pObjNew2 = Aig_NotCond( pObjReprNew, pObj->fPhase ^ pObjRepr->fPhase );
+    // set the new node
+    Ssw_ObjSetFrame( p, pObj, iFrame, pObjNew2 );
+    // add the constraint
+    if ( fTwoPos )
+    {
+        Aig_ObjCreateCo( pFrames, pObjNew2 );
+        Aig_ObjCreateCo( pFrames, pObjNew );
+    }
+    else
+    {
+        pMiter = Aig_Exor( pFrames, pObjNew, pObjNew2 );
+        Aig_ObjCreateCo( pFrames, Aig_NotCond(pMiter, Aig_ObjPhaseReal(pMiter)) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the inductive case with speculative reduction.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Ssw_FramesWithClasses( Ssw_Man_t * p )
+{
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew;
+    int i, f, iLits;
+    assert( p->pFrames == NULL );
+    assert( Aig_ManRegNum(p->pAig) > 0 );
+    assert( Aig_ManRegNum(p->pAig) < Aig_ManCiNum(p->pAig) );
+    p->nConstrTotal = p->nConstrReduced = 0;
+
+    // start the fraig package
+    pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->nFrames );
+    // create latches for the first frame
+    Saig_ManForEachLo( p->pAig, pObj, i )
+        Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreateCi(pFrames) );
+    // add timeframes
+    iLits = 0;
+    for ( f = 0; f < p->pPars->nFramesK; f++ )
+    {
+        // map constants and PIs
+        Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(pFrames) );
+        Saig_ManForEachPi( p->pAig, pObj, i )
+        {
+            pObjNew = Aig_ObjCreateCi(pFrames);
+            pObjNew->fPhase = (p->vInits != NULL) && Vec_IntEntry(p->vInits, iLits++);
+            Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+        }
+        // set the constraints on the latch outputs
+        Saig_ManForEachLo( p->pAig, pObj, i )
+            Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, f, 1 );
+        // add internal nodes of this frame
+        Aig_ManForEachNode( p->pAig, pObj, i )
+        {
+            pObjNew = Aig_And( pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+            Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+            Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, f, 1 );
+        }
+        // transfer to the primary outputs
+        Aig_ManForEachCo( p->pAig, pObj, i )
+            Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj,f) );
+        // transfer latch input to the latch outputs
+        Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+            Ssw_ObjSetFrame( p, pObjLo, f+1, Ssw_ObjFrame(p, pObjLi,f) );
+    }
+    assert( p->vInits == NULL || Vec_IntSize(p->vInits) == iLits + Saig_ManPiNum(p->pAig) );
+    // add the POs for the latch outputs of the last frame
+    Saig_ManForEachLo( p->pAig, pObj, i )
+        Aig_ObjCreateCo( pFrames, Ssw_ObjFrame( p, pObj, p->pPars->nFramesK ) );
+
+    // remove dangling nodes
+    Aig_ManCleanup( pFrames );
+    // make sure the satisfying assignment is node assigned
+    assert( pFrames->pData == NULL );
+//Aig_ManShow( pFrames, 0, NULL );
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the inductive case with speculative reduction.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Ssw_SpeculativeReduction( Ssw_Man_t * p )
+{
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i;
+    assert( p->pFrames == NULL );
+    assert( Aig_ManRegNum(p->pAig) > 0 );
+    assert( Aig_ManRegNum(p->pAig) < Aig_ManCiNum(p->pAig) );
+    p->nConstrTotal = p->nConstrReduced = 0;
+
+    // start the fraig package
+    pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->nFrames );
+    pFrames->pName = Abc_UtilStrsav( p->pAig->pName );
+    // map constants and PIs
+    Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), 0, Aig_ManConst1(pFrames) );
+    Saig_ManForEachPi( p->pAig, pObj, i )
+        Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreateCi(pFrames) );
+    // create latches for the first frame
+    Saig_ManForEachLo( p->pAig, pObj, i )
+        Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreateCi(pFrames) );
+    // set the constraints on the latch outputs
+    Saig_ManForEachLo( p->pAig, pObj, i )
+        Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, 0, 0 );
+    // add internal nodes of this frame
+    Aig_ManForEachNode( p->pAig, pObj, i )
+    {
+        pObjNew = Aig_And( pFrames, Ssw_ObjChild0Fra(p, pObj, 0), Ssw_ObjChild1Fra(p, pObj, 0) );
+        Ssw_ObjSetFrame( p, pObj, 0, pObjNew );
+        Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, 0, 0 );
+    }
+    // add the POs for the latch outputs of the last frame
+    Saig_ManForEachLi( p->pAig, pObj, i )
+        Aig_ObjCreateCo( pFrames, Ssw_ObjChild0Fra(p, pObj,0) );
+    // remove dangling nodes
+    Aig_ManCleanup( pFrames );
+    Aig_ManSetRegNum( pFrames, Aig_ManRegNum(p->pAig) );
+//    Abc_Print( 1, "SpecRed: Total constraints = %d. Reduced constraints = %d.\n", 
+//        p->nConstrTotal, p->nConstrReduced );
+    return pFrames;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswBmc.c b/abc-build/src/proof/ssw/sswBmc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswBmc.c
@@ -0,0 +1,224 @@
+/**CFile****************************************************************
+
+  FileName    [sswBmc.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [Bounded model checker using dynamic unrolling.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswBmc.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Incrementally unroll the timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Ssw_BmcUnroll_rec( Ssw_Frm_t * pFrm, Aig_Obj_t * pObj, int f )
+{
+    Aig_Obj_t * pRes, * pRes0, * pRes1;
+    if ( (pRes = Ssw_ObjFrame_(pFrm, pObj, f)) )
+        return pRes;
+    if ( Aig_ObjIsConst1(pObj) )
+        pRes = Aig_ManConst1( pFrm->pFrames );
+    else if ( Saig_ObjIsPi(pFrm->pAig, pObj) )
+        pRes = Aig_ObjCreateCi( pFrm->pFrames );
+    else if ( Aig_ObjIsCo(pObj) )
+    {
+        Ssw_BmcUnroll_rec( pFrm, Aig_ObjFanin0(pObj), f );
+        pRes = Ssw_ObjChild0Fra_( pFrm, pObj, f );
+    }
+    else if ( Saig_ObjIsLo(pFrm->pAig, pObj) )
+    {
+        if ( f == 0 )
+            pRes = Aig_ManConst0( pFrm->pFrames );
+        else
+            pRes = Ssw_BmcUnroll_rec( pFrm, Saig_ObjLoToLi(pFrm->pAig, pObj), f-1 );
+    }
+    else
+    {
+        assert( Aig_ObjIsNode(pObj) );
+        Ssw_BmcUnroll_rec( pFrm, Aig_ObjFanin0(pObj), f );
+        Ssw_BmcUnroll_rec( pFrm, Aig_ObjFanin1(pObj), f );
+        pRes0 = Ssw_ObjChild0Fra_( pFrm, pObj, f );
+        pRes1 = Ssw_ObjChild1Fra_( pFrm, pObj, f );
+        pRes = Aig_And( pFrm->pFrames, pRes0, pRes1 );
+    }
+    Ssw_ObjSetFrame_( pFrm, pObj, f, pRes );
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives counter-example.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Ssw_BmcGetCounterExample( Ssw_Frm_t * pFrm, Ssw_Sat_t * pSat, int iPo, int iFrame )
+{
+    Abc_Cex_t * pCex;
+    Aig_Obj_t * pObj, * pObjFrames;
+    int f, i, nShift;
+    assert( Saig_ManRegNum(pFrm->pAig) > 0 );
+    // allocate the counter example
+    pCex = Abc_CexAlloc( Saig_ManRegNum(pFrm->pAig), Saig_ManPiNum(pFrm->pAig), iFrame + 1 );
+    pCex->iPo    = iPo;
+    pCex->iFrame = iFrame;
+    // create data-bits
+    nShift = Saig_ManRegNum(pFrm->pAig);
+    for ( f = 0; f <= iFrame; f++, nShift += Saig_ManPiNum(pFrm->pAig) )
+        Saig_ManForEachPi( pFrm->pAig, pObj, i )
+        {
+            pObjFrames = Ssw_ObjFrame_(pFrm, pObj, f);
+            if ( pObjFrames == NULL )
+                continue;
+            if ( Ssw_CnfGetNodeValue( pSat, pObjFrames ) )
+                Abc_InfoSetBit( pCex->pData, nShift + i );
+        }
+    return pCex;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BMC for the given AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_BmcDynamic( Aig_Man_t * pAig, int nFramesMax, int nConfLimit, int fVerbose, int * piFrame )
+{
+    Ssw_Frm_t * pFrm;
+    Ssw_Sat_t * pSat;
+    Aig_Obj_t * pObj, * pObjFrame;
+    int status, Lit, i, f, RetValue;
+    abctime clkPart;
+
+    // start managers
+    assert( Saig_ManRegNum(pAig) > 0 );
+    Aig_ManSetCioIds( pAig );
+    pSat = Ssw_SatStart( 0 );
+    pFrm = Ssw_FrmStart( pAig );
+    pFrm->pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * 3 );
+    // report statistics
+    if ( fVerbose )
+    {
+        Abc_Print( 1, "AIG:  PI/PO/Reg = %d/%d/%d.  Node = %6d. Lev = %5d.\n",
+            Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig),
+            Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) );
+        fflush( stdout );
+    }
+    // perform dynamic unrolling
+    RetValue = -1;
+    for ( f = 0; f < nFramesMax; f++ )
+    {
+        clkPart = Abc_Clock();
+        Saig_ManForEachPo( pAig, pObj, i )
+        {
+            // unroll the circuit for this output
+            Ssw_BmcUnroll_rec( pFrm, pObj, f );
+            pObjFrame = Ssw_ObjFrame_( pFrm, pObj, f );
+            Ssw_CnfNodeAddToSolver( pSat, Aig_Regular(pObjFrame) );
+            status = sat_solver_simplify(pSat->pSat);
+            assert( status );
+            // solve
+            Lit = toLitCond( Ssw_ObjSatNum(pSat,pObjFrame), Aig_IsComplement(pObjFrame) );
+            if ( fVerbose )
+            {
+                Abc_Print( 1, "Solving output %2d of frame %3d ... \r",
+                    i % Saig_ManPoNum(pAig), i / Saig_ManPoNum(pAig) );
+            }
+            status = sat_solver_solve( pSat->pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+            if ( status == l_False )
+            {
+/*
+                Lit = lit_neg( Lit );
+                RetValue = sat_solver_addclause( pSat->pSat, &Lit, &Lit + 1 );
+                assert( RetValue );
+                if ( pSat->pSat->qtail != pSat->pSat->qhead )
+                {
+                    RetValue = sat_solver_simplify(pSat->pSat);
+                    assert( RetValue );
+                }
+*/
+                RetValue = 1;
+                continue;
+            }
+            else if ( status == l_True )
+            {
+                pAig->pSeqModel = Ssw_BmcGetCounterExample( pFrm, pSat, i, f );
+                if ( piFrame )
+                    *piFrame = f;
+                RetValue = 0;
+                break;
+            }
+            else
+            {
+                if ( piFrame )
+                    *piFrame = f;
+                RetValue = -1;
+                break;
+            }
+        }
+        if ( fVerbose )
+        {
+            Abc_Print( 1, "Solved %2d outputs of frame %3d.  ", Saig_ManPoNum(pAig), f );
+            Abc_Print( 1, "Conf =%8.0f. Var =%8d. AIG=%9d. ",
+                (double)pSat->pSat->stats.conflicts,
+                pSat->nSatVars, Aig_ManNodeNum(pFrm->pFrames) );
+            ABC_PRT( "T", Abc_Clock() - clkPart );
+            clkPart = Abc_Clock();
+            fflush( stdout );
+        }
+        if ( RetValue != 1 )
+            break;
+    }
+
+    Ssw_SatStop( pSat );
+    Ssw_FrmStop( pFrm );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswClass.c b/abc-build/src/proof/ssw/sswClass.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswClass.c
@@ -0,0 +1,1170 @@
+/**CFile****************************************************************
+
+  FileName    [sswClass.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [Representation of candidate equivalence classes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswClass.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+    The candidate equivalence classes are stored as a vector of pointers 
+    to the array of pointers to the nodes in each class.
+    The first node of the class is its representative node.
+    The representative has the smallest topological order among the class nodes.
+    The nodes inside each class are ordered according to their topological order.
+    The classes are ordered according to the topo order of their representatives.
+*/
+
+// internal representation of candidate equivalence classes
+struct Ssw_Cla_t_
+{
+    // class information
+    Aig_Man_t *      pAig;             // original AIG manager
+    Aig_Obj_t ***    pId2Class;        // non-const classes by ID of repr node
+    int *            pClassSizes;      // sizes of each equivalence class
+    int              fConstCorr;
+    // statistics
+    int              nClasses;         // the total number of non-const classes
+    int              nCands1;          // the total number of const candidates
+    int              nLits;            // the number of literals in all classes
+    // memory
+    Aig_Obj_t **     pMemClasses;      // memory allocated for equivalence classes
+    Aig_Obj_t **     pMemClassesFree;  // memory allocated for equivalence classes to be used
+    // temporary data
+    Vec_Ptr_t *      vClassOld;        // old equivalence class after splitting
+    Vec_Ptr_t *      vClassNew;        // new equivalence class(es) after splitting
+    Vec_Ptr_t *      vRefined;         // the nodes refined since the last iteration
+    // procedures used for class refinement
+    void *           pManData;
+    unsigned (*pFuncNodeHash) (void *,Aig_Obj_t *);              // returns hash key of the node
+    int (*pFuncNodeIsConst)   (void *,Aig_Obj_t *);              // returns 1 if the node is a constant
+    int (*pFuncNodesAreEqual) (void *,Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement
+};
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline Aig_Obj_t *  Ssw_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj )                       { return ppNexts[pObj->Id];  }
+static inline void         Ssw_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; }
+
+// iterator through the equivalence classes
+#define Ssw_ManForEachClass( p, ppClass, i )                 \
+    for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ )        \
+        if ( ((ppClass) = p->pId2Class[i]) == NULL ) {} else
+// iterator through the nodes in one class
+#define Ssw_ClassForEachNode( p, pRepr, pNode, i )           \
+    for ( i = 0; i < p->pClassSizes[pRepr->Id]; i++ )        \
+        if ( ((pNode) = p->pId2Class[pRepr->Id][i]) == NULL ) {} else
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates one equivalence class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Ssw_ObjAddClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, Aig_Obj_t ** pClass, int nSize )
+{
+    assert( p->pId2Class[pRepr->Id] == NULL );
+    assert( pClass[0] == pRepr );
+    p->pId2Class[pRepr->Id] = pClass;
+    assert( p->pClassSizes[pRepr->Id] == 0 );
+    assert( nSize > 1 );
+    p->pClassSizes[pRepr->Id] = nSize;
+    p->nClasses++;
+    p->nLits += nSize - 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes one equivalence class.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Aig_Obj_t ** Ssw_ObjRemoveClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr )
+{
+    Aig_Obj_t ** pClass = p->pId2Class[pRepr->Id];
+    int nSize;
+    assert( pClass != NULL );
+    p->pId2Class[pRepr->Id] = NULL;
+    nSize = p->pClassSizes[pRepr->Id];
+    assert( nSize > 1 );
+    p->nClasses--;
+    p->nLits -= nSize - 1;
+    p->pClassSizes[pRepr->Id] = 0;
+    return pClass;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts representation of equivalence classes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ssw_Cla_t * Ssw_ClassesStart( Aig_Man_t * pAig )
+{
+    Ssw_Cla_t * p;
+    p = ABC_ALLOC( Ssw_Cla_t, 1 );
+    memset( p, 0, sizeof(Ssw_Cla_t) );
+    p->pAig         = pAig;
+    p->pId2Class    = ABC_CALLOC( Aig_Obj_t **, Aig_ManObjNumMax(pAig) );
+    p->pClassSizes  = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+    p->vClassOld    = Vec_PtrAlloc( 100 );
+    p->vClassNew    = Vec_PtrAlloc( 100 );
+    p->vRefined     = Vec_PtrAlloc( 1000 );
+    if ( pAig->pReprs == NULL )
+        Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts representation of equivalence classes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ClassesSetData( Ssw_Cla_t * p, void * pManData,
+    unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *),               // returns hash key of the node
+    int (*pFuncNodeIsConst)(void *,Aig_Obj_t *),                 // returns 1 if the node is a constant
+    int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ) // returns 1 if nodes are equal up to a complement
+{
+    p->pManData           = pManData;
+    p->pFuncNodeHash      = pFuncNodeHash;
+    p->pFuncNodeIsConst   = pFuncNodeIsConst;
+    p->pFuncNodesAreEqual = pFuncNodesAreEqual;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop representation of equivalence classes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ClassesStop( Ssw_Cla_t * p )
+{
+    if ( p->vClassNew )    Vec_PtrFree( p->vClassNew );
+    if ( p->vClassOld )    Vec_PtrFree( p->vClassOld );
+    Vec_PtrFree( p->vRefined );
+    ABC_FREE( p->pId2Class );
+    ABC_FREE( p->pClassSizes );
+    ABC_FREE( p->pMemClasses );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop representation of equivalence classes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Ssw_ClassesReadAig( Ssw_Cla_t * p )
+{
+    return p->pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Ssw_ClassesGetRefined( Ssw_Cla_t * p )
+{
+    return p->vRefined;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ClassesClearRefined( Ssw_Cla_t * p )
+{
+    Vec_PtrClear( p->vRefined );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop representation of equivalence classes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ClassesCand1Num( Ssw_Cla_t * p )
+{
+    return p->nCands1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop representation of equivalence classes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ClassesClassNum( Ssw_Cla_t * p )
+{
+    return p->nClasses;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop representation of equivalence classes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ClassesLitNum( Ssw_Cla_t * p )
+{
+    return p->nLits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop representation of equivalence classes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t ** Ssw_ClassesReadClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize )
+{
+    if ( p->pId2Class[pRepr->Id] == NULL )
+        return NULL;
+    assert( p->pId2Class[pRepr->Id] != NULL );
+    assert( p->pClassSizes[pRepr->Id] > 1 );
+    *pnSize = p->pClassSizes[pRepr->Id];
+    return p->pId2Class[pRepr->Id];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop representation of equivalence classes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ClassesCollectClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vClass )
+{
+    int i;
+    Vec_PtrClear( vClass );
+    if ( p->pId2Class[pRepr->Id] == NULL )
+        return;
+    assert( p->pClassSizes[pRepr->Id] > 1 );
+    for ( i = 1; i < p->pClassSizes[pRepr->Id]; i++ )
+        Vec_PtrPush( vClass, p->pId2Class[pRepr->Id][i] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks candidate equivalence classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ClassesCheck( Ssw_Cla_t * p )
+{
+    Aig_Obj_t * pObj, * pPrev, ** ppClass;
+    int i, k, nLits, nClasses, nCands1;
+    nClasses = nLits = 0;
+    Ssw_ManForEachClass( p, ppClass, k )
+    {
+        pPrev = NULL;
+        assert( p->pClassSizes[ppClass[0]->Id] >= 2 );
+        Ssw_ClassForEachNode( p, ppClass[0], pObj, i )
+        {
+            if ( i == 0 )
+                assert( Aig_ObjRepr(p->pAig, pObj) == NULL );
+            else
+            {
+                assert( Aig_ObjRepr(p->pAig, pObj) == ppClass[0] );
+                assert( pPrev->Id < pObj->Id );
+                nLits++;
+            }
+            pPrev = pObj;
+        }
+        nClasses++;
+    }
+    nCands1 = 0;
+    Aig_ManForEachObj( p->pAig, pObj, i )
+        nCands1 += Ssw_ObjIsConst1Cand( p->pAig, pObj );
+    assert( p->nLits == nLits );
+    assert( p->nCands1 == nCands1 );
+    assert( p->nClasses == nClasses );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints simulation classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ClassesPrintOne( Ssw_Cla_t * p, Aig_Obj_t * pRepr )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Abc_Print( 1, "{ " );
+    Ssw_ClassForEachNode( p, pRepr, pObj, i )
+        Abc_Print( 1, "%d(%d,%d,%d) ", pObj->Id, pObj->Level,
+        Aig_SupportSize(p->pAig,pObj), Aig_NodeMffcSupp(p->pAig,pObj,0,NULL) );
+    Abc_Print( 1, "}\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints simulation classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ClassesPrint( Ssw_Cla_t * p, int fVeryVerbose )
+{
+    Aig_Obj_t ** ppClass;
+    Aig_Obj_t * pObj;
+    int i;
+    Abc_Print( 1, "Equiv classes: Const1 = %5d. Class = %5d. Lit = %5d.\n",
+        p->nCands1, p->nClasses, p->nCands1+p->nLits );
+    if ( !fVeryVerbose )
+        return;
+    Abc_Print( 1, "Constants { " );
+    Aig_ManForEachObj( p->pAig, pObj, i )
+        if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) )
+            Abc_Print( 1, "%d(%d,%d,%d) ", pObj->Id, pObj->Level,
+            Aig_SupportSize(p->pAig,pObj), Aig_NodeMffcSupp(p->pAig,pObj,0,NULL) );
+    Abc_Print( 1, "}\n" );
+    Ssw_ManForEachClass( p, ppClass, i )
+    {
+        Abc_Print( 1, "%3d (%3d) : ", i, p->pClassSizes[i] );
+        Ssw_ClassesPrintOne( p, ppClass[0] );
+    }
+    Abc_Print( 1, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints simulation classes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ClassesRemoveNode( Ssw_Cla_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pRepr, * pTemp;
+    assert( p->pClassSizes[pObj->Id] == 0 );
+    assert( p->pId2Class[pObj->Id] == NULL );
+    pRepr = Aig_ObjRepr( p->pAig, pObj );
+    assert( pRepr != NULL );
+//    Vec_PtrPush( p->vRefined, pObj );
+    if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) )
+    {
+        assert( p->pClassSizes[pRepr->Id] == 0 );
+        assert( p->pId2Class[pRepr->Id] == NULL );
+        Aig_ObjSetRepr( p->pAig, pObj, NULL );
+        p->nCands1--;
+        return;
+    }
+//    Vec_PtrPush( p->vRefined, pRepr );
+    Aig_ObjSetRepr( p->pAig, pObj, NULL );
+    assert( p->pId2Class[pRepr->Id][0] == pRepr );
+    assert( p->pClassSizes[pRepr->Id] >= 2 );
+    if ( p->pClassSizes[pRepr->Id] == 2 )
+    {
+        p->pId2Class[pRepr->Id] = NULL;
+        p->nClasses--;
+        p->pClassSizes[pRepr->Id] = 0;
+        p->nLits--;
+    }
+    else
+    {
+        int i, k = 0;
+        // remove the entry from the class
+        Ssw_ClassForEachNode( p, pRepr, pTemp, i )
+            if ( pTemp != pObj )
+                p->pId2Class[pRepr->Id][k++] = pTemp;
+        assert( k + 1 == p->pClassSizes[pRepr->Id] );
+        // reduce the class
+        p->pClassSizes[pRepr->Id]--;
+        p->nLits--;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Takes the set of const1 cands and rehashes them using sim info.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ClassesPrepareRehash( Ssw_Cla_t * p, Vec_Ptr_t * vCands, int fConstCorr )
+{
+//    Aig_Man_t * pAig = p->pAig;
+    Aig_Obj_t ** ppTable, ** ppNexts, ** ppClassNew;
+    Aig_Obj_t * pObj, * pTemp, * pRepr;
+    int i, k, nTableSize, nNodes, iEntry, nEntries, nEntries2;
+
+    // allocate the hash table hashing simulation info into nodes
+    nTableSize = Abc_PrimeCudd( Vec_PtrSize(vCands)/2 );
+    ppTable = ABC_CALLOC( Aig_Obj_t *, nTableSize );
+    ppNexts = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) );
+
+    // sort through the candidates
+    nEntries = 0;
+    p->nCands1 = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vCands, pObj, i )
+    {
+        assert( p->pClassSizes[pObj->Id] == 0 );
+        Aig_ObjSetRepr( p->pAig, pObj, NULL );
+        // check if the node belongs to the class of constant 1
+        if ( p->pFuncNodeIsConst( p->pManData, pObj ) )
+        {
+            Ssw_ObjSetConst1Cand( p->pAig, pObj );
+            p->nCands1++;
+            continue;
+        }
+        if ( fConstCorr )
+            continue;
+        // hash the node by its simulation info
+        iEntry = p->pFuncNodeHash( p->pManData, pObj ) % nTableSize;
+        // add the node to the class
+        if ( ppTable[iEntry] == NULL )
+        {
+            ppTable[iEntry] = pObj;
+        }
+        else
+        {
+            // set the representative of this node
+            pRepr = ppTable[iEntry];
+            Aig_ObjSetRepr( p->pAig, pObj, pRepr );
+            // add node to the table
+            if ( Ssw_ObjNext( ppNexts, pRepr ) == NULL )
+            { // this will be the second entry
+                p->pClassSizes[pRepr->Id]++;
+                nEntries++;
+            }
+            // add the entry to the list
+            Ssw_ObjSetNext( ppNexts, pObj, Ssw_ObjNext( ppNexts, pRepr ) );
+            Ssw_ObjSetNext( ppNexts, pRepr, pObj );
+            p->pClassSizes[pRepr->Id]++;
+            nEntries++;
+        }
+    }
+
+    // copy the entries into storage in the topological order
+    nEntries2 = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vCands, pObj, i )
+    {
+        nNodes = p->pClassSizes[pObj->Id];
+        // skip the nodes that are not representatives of non-trivial classes
+        if ( nNodes == 0 )
+            continue;
+        assert( nNodes > 1 );
+        // add the nodes to the class in the topological order
+        ppClassNew = p->pMemClassesFree + nEntries2;
+        ppClassNew[0] = pObj;
+        for ( pTemp = Ssw_ObjNext(ppNexts, pObj), k = 1; pTemp;
+              pTemp = Ssw_ObjNext(ppNexts, pTemp), k++ )
+        {
+            ppClassNew[nNodes-k] = pTemp;
+        }
+        // add the class of nodes
+        p->pClassSizes[pObj->Id] = 0;
+        Ssw_ObjAddClass( p, pObj, ppClassNew, nNodes );
+        // increment the number of entries
+        nEntries2 += nNodes;
+    }
+    p->pMemClassesFree += nEntries2;
+    assert( nEntries == nEntries2 );
+    ABC_FREE( ppTable );
+    ABC_FREE( ppNexts );
+    // now it is time to refine the classes
+    return Ssw_ClassesRefine( p, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates initial simulation classes.]
+
+  Description [Assumes that simulation info is assigned.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int nFramesK, int fLatchCorr, int fConstCorr, int fOutputCorr, int nMaxLevs, int fVerbose )
+{
+//    int nFrames =  4;
+//    int nWords  =  1;
+//    int nIters  = 16;
+
+//    int nFrames = 32;
+//    int nWords  =  4;
+//    int nIters  =  0;
+
+    int nFrames =  Abc_MaxInt( nFramesK, 4 );
+    int nWords  =  2;
+    int nIters  = 16;
+    Ssw_Cla_t * p;
+    Ssw_Sml_t * pSml;
+    Vec_Ptr_t * vCands;
+    Aig_Obj_t * pObj;
+    int i, k, RetValue;
+    abctime clk;
+
+    // start the classes
+    p = Ssw_ClassesStart( pAig );
+    p->fConstCorr = fConstCorr;
+
+    // perform sequential simulation
+clk = Abc_Clock();
+    pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords );
+if ( fVerbose )
+{
+    Abc_Print( 1, "Allocated %.2f MB to store simulation information.\n",
+        1.0*(sizeof(unsigned) * Aig_ManObjNumMax(pAig) * nFrames * nWords)/(1<<20) );
+    Abc_Print( 1, "Initial simulation of %d frames with %d words.     ", nFrames, nWords );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+}
+
+    // set comparison procedures
+clk = Abc_Clock();
+    Ssw_ClassesSetData( p, pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord );
+
+    // collect nodes to be considered as candidates
+    vCands = Vec_PtrAlloc( 1000 );
+    Aig_ManForEachObj( p->pAig, pObj, i )
+    {
+        if ( fLatchCorr )
+        {
+            if ( !Saig_ObjIsLo(p->pAig, pObj) )
+                continue;
+        }
+        else
+        {
+            if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
+                continue;
+            // skip the node with more that the given number of levels
+            if ( nMaxLevs && (int)pObj->Level > nMaxLevs )
+                continue;
+        }
+        Vec_PtrPush( vCands, pObj );
+    }
+
+    // this change will consider all PO drivers
+    if ( fOutputCorr )
+    {
+        Vec_PtrClear( vCands );
+        Aig_ManForEachObj( p->pAig, pObj, i )
+            pObj->fMarkB = 0;
+        Saig_ManForEachPo( p->pAig, pObj, i )
+            if ( Aig_ObjIsCand(Aig_ObjFanin0(pObj)) )
+                Aig_ObjFanin0(pObj)->fMarkB = 1;
+        Aig_ManForEachObj( p->pAig, pObj, i )
+            if ( pObj->fMarkB )
+                Vec_PtrPush( vCands, pObj );
+        Aig_ManForEachObj( p->pAig, pObj, i )
+            pObj->fMarkB = 0;
+    }
+
+    // allocate room for classes
+    p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, Vec_PtrSize(vCands) );
+    p->pMemClassesFree = p->pMemClasses;
+
+    // now it is time to refine the classes
+    Ssw_ClassesPrepareRehash( p, vCands, fConstCorr );
+if ( fVerbose )
+{
+    Abc_Print( 1, "Collecting candidate equivalence classes.        " );
+ABC_PRT( "Time", Abc_Clock() - clk );
+}
+
+clk = Abc_Clock();
+    // perform iterative refinement using simulation
+    for ( i = 1; i < nIters; i++ )
+    {
+        // collect const1 candidates
+        Vec_PtrClear( vCands );
+        Aig_ManForEachObj( p->pAig, pObj, k )
+            if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) )
+                Vec_PtrPush( vCands, pObj );
+        assert( Vec_PtrSize(vCands) == p->nCands1 );
+        // perform new round of simulation
+        Ssw_SmlResimulateSeq( pSml );
+        // check equivalence classes
+        RetValue = Ssw_ClassesPrepareRehash( p, vCands, fConstCorr );
+        if ( RetValue == 0 )
+            break;
+    }
+    Ssw_SmlStop( pSml );
+    Vec_PtrFree( vCands );
+if ( fVerbose )
+{
+    Abc_Print( 1, "Simulation of %d frames with %d words (%2d rounds). ",
+        nFrames, nWords, i-1 );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+}
+    Ssw_ClassesCheck( p );
+//    Ssw_ClassesPrint( p, 0 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates initial simulation classes.]
+
+  Description [Assumes that simulation info is assigned.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ssw_Cla_t * Ssw_ClassesPrepareSimple( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs )
+{
+    Ssw_Cla_t * p;
+    Aig_Obj_t * pObj;
+    int i;
+    // start the classes
+    p = Ssw_ClassesStart( pAig );
+    // go through the nodes
+    p->nCands1 = 0;
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+        if ( fLatchCorr )
+        {
+            if ( !Saig_ObjIsLo(pAig, pObj) )
+                continue;
+        }
+        else
+        {
+            if ( !Aig_ObjIsNode(pObj) && !Saig_ObjIsLo(pAig, pObj) )
+                continue;
+            // skip the node with more that the given number of levels
+            if ( nMaxLevs && (int)pObj->Level > nMaxLevs )
+                continue;
+        }
+        Ssw_ObjSetConst1Cand( pAig, pObj );
+        p->nCands1++;
+    }
+    // allocate room for classes
+    p->pMemClassesFree = p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, p->nCands1 );
+//    Ssw_ClassesPrint( p, 0 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates initial simulation classes.]
+
+  Description [Assumes that simulation info is assigned.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ssw_Cla_t * Ssw_ClassesPrepareFromReprs( Aig_Man_t * pAig )
+{
+    Ssw_Cla_t * p;
+    Aig_Obj_t * pObj, * pRepr;
+    int * pClassSizes, nEntries, i;
+    // start the classes
+    p = Ssw_ClassesStart( pAig );
+    // allocate memory for classes
+    p->pMemClasses = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
+    // count classes
+    p->nCands1 = 0;
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+        if ( Ssw_ObjIsConst1Cand(pAig, pObj) )
+        {
+            p->nCands1++;
+            continue;
+        }
+        if ( (pRepr = Aig_ObjRepr(pAig, pObj)) )
+        {
+            if ( p->pClassSizes[pRepr->Id]++ == 0 )
+                p->pClassSizes[pRepr->Id]++;
+        }
+    }
+    // add nodes
+    nEntries = 0;
+    p->nClasses = 0;
+    pClassSizes = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+        if ( p->pClassSizes[i] )
+        {
+            p->pId2Class[i] = p->pMemClasses + nEntries;
+            nEntries += p->pClassSizes[i];
+            p->pId2Class[i][pClassSizes[i]++] = pObj;
+            p->nClasses++;
+            continue;
+        }
+        if ( Ssw_ObjIsConst1Cand(pAig, pObj) )
+            continue;
+        if ( (pRepr = Aig_ObjRepr(pAig, pObj)) )
+            p->pId2Class[pRepr->Id][pClassSizes[pRepr->Id]++] = pObj;
+    }
+    p->pMemClassesFree = p->pMemClasses + nEntries;
+    p->nLits = nEntries - p->nClasses;
+    assert( memcmp(pClassSizes, p->pClassSizes, sizeof(int)*Aig_ManObjNumMax(pAig)) == 0 );
+    ABC_FREE( pClassSizes );
+//    Abc_Print( 1, "After converting:\n" );
+//    Ssw_ClassesPrint( p, 0 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates initial simulation classes.]
+
+  Description [Assumes that simulation info is assigned.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ssw_Cla_t * Ssw_ClassesPrepareTargets( Aig_Man_t * pAig )
+{
+    Ssw_Cla_t * p;
+    Aig_Obj_t * pObj;
+    int i;
+    // start the classes
+    p = Ssw_ClassesStart( pAig );
+    // go through the nodes
+    p->nCands1 = 0;
+    Saig_ManForEachPo( pAig, pObj, i )
+    {
+        Ssw_ObjSetConst1Cand( pAig, Aig_ObjFanin0(pObj) );
+        p->nCands1++;
+    }
+    // allocate room for classes
+    p->pMemClassesFree = p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, p->nCands1 );
+//    Ssw_ClassesPrint( p, 0 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates classes from the temporary representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ssw_Cla_t * Ssw_ClassesPreparePairs( Aig_Man_t * pAig, Vec_Int_t ** pvClasses )
+{
+    Ssw_Cla_t * p;
+    Aig_Obj_t ** ppClassNew;
+    Aig_Obj_t * pObj, * pRepr, * pPrev;
+    int i, k, nTotalObjs, nEntries, Entry;
+    // start the classes
+    p = Ssw_ClassesStart( pAig );
+    // count the number of entries in the classes
+    nTotalObjs = 0;
+    for ( i = 0; i < Aig_ManObjNumMax(pAig); i++ )
+        nTotalObjs += pvClasses[i] ? Vec_IntSize(pvClasses[i]) : 0;
+    // allocate memory for classes
+    p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, nTotalObjs );
+    // create constant-1 class
+    if ( pvClasses[0] )
+    Vec_IntForEachEntry( pvClasses[0], Entry, i )
+    {
+        assert( (i == 0) == (Entry == 0) );
+        if ( i == 0 )
+            continue;
+        pObj = Aig_ManObj( pAig, Entry );
+        Ssw_ObjSetConst1Cand( pAig, pObj );
+        p->nCands1++;
+    }
+    // create classes
+    nEntries = 0;
+    for ( i = 1; i < Aig_ManObjNumMax(pAig); i++ )
+    {
+        if ( pvClasses[i] == NULL )
+            continue;
+        // get room for storing the class
+        ppClassNew = p->pMemClasses + nEntries;
+        nEntries  += Vec_IntSize( pvClasses[i] );
+        // store the nodes of the class
+        pPrev = pRepr = Aig_ManObj( pAig, Vec_IntEntry(pvClasses[i],0) );
+        ppClassNew[0] = pRepr;
+        Vec_IntForEachEntryStart( pvClasses[i], Entry, k, 1 )
+        {
+            pObj = Aig_ManObj( pAig, Entry );
+            assert( pPrev->Id < pObj->Id );
+            pPrev = pObj;
+            ppClassNew[k] = pObj;
+            Aig_ObjSetRepr( pAig, pObj, pRepr );
+        }
+        // create new class
+        Ssw_ObjAddClass( p, pRepr, ppClassNew, Vec_IntSize(pvClasses[i]) );
+    }
+    // prepare room for new classes
+    p->pMemClassesFree = p->pMemClasses + nEntries;
+    Ssw_ClassesCheck( p );
+//    Ssw_ClassesPrint( p, 0 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates classes from the temporary representation.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ssw_Cla_t * Ssw_ClassesPreparePairsSimple( Aig_Man_t * pMiter, Vec_Int_t * vPairs )
+{
+    Ssw_Cla_t * p;
+    Aig_Obj_t ** ppClassNew;
+    Aig_Obj_t * pObj, * pRepr;
+    int i;
+    // start the classes
+    p = Ssw_ClassesStart( pMiter );
+    // allocate memory for classes
+    p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, Vec_IntSize(vPairs) );
+    // create classes
+    for ( i = 0; i < Vec_IntSize(vPairs); i += 2 )
+    {
+        pRepr = Aig_ManObj( pMiter, Vec_IntEntry(vPairs, i) );
+        pObj  = Aig_ManObj( pMiter, Vec_IntEntry(vPairs, i+1) );
+        assert( Aig_ObjId(pRepr) < Aig_ObjId(pObj) );
+        Aig_ObjSetRepr( pMiter, pObj, pRepr );
+        // get room for storing the class
+        ppClassNew = p->pMemClasses + i;
+        ppClassNew[0] = pRepr;
+        ppClassNew[1] = pObj;
+        // create new class
+        Ssw_ObjAddClass( p, pRepr, ppClassNew, 2 );
+    }
+    // prepare room for new classes
+    p->pMemClassesFree = NULL;
+    Ssw_ClassesCheck( p );
+//    Ssw_ClassesPrint( p, 0 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Iteratively refines the classes after simulation.]
+
+  Description [Returns the number of refinements performed.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ClassesRefineOneClass( Ssw_Cla_t * p, Aig_Obj_t * pReprOld, int fRecursive )
+{
+    Aig_Obj_t ** pClassOld, ** pClassNew;
+    Aig_Obj_t * pObj, * pReprNew;
+    int i;
+
+    // split the class
+    Vec_PtrClear( p->vClassOld );
+    Vec_PtrClear( p->vClassNew );
+    Ssw_ClassForEachNode( p, pReprOld, pObj, i )
+        if ( p->pFuncNodesAreEqual(p->pManData, pReprOld, pObj) )
+            Vec_PtrPush( p->vClassOld, pObj );
+        else
+            Vec_PtrPush( p->vClassNew, pObj );
+    // check if splitting happened
+    if ( Vec_PtrSize(p->vClassNew) == 0 )
+        return 0;
+    // remember that this class is refined
+//    Ssw_ClassForEachNode( p, pReprOld, pObj, i )
+//        Vec_PtrPush( p->vRefined, pObj );
+
+    // get the new representative
+    pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 );
+    assert( Vec_PtrSize(p->vClassOld) > 0 );
+    assert( Vec_PtrSize(p->vClassNew) > 0 );
+
+    // create old class
+    pClassOld = Ssw_ObjRemoveClass( p, pReprOld );
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i )
+    {
+        pClassOld[i] = pObj;
+        Aig_ObjSetRepr( p->pAig, pObj, i? pReprOld : NULL );
+    }
+    // create new class
+    pClassNew = pClassOld + i;
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+    {
+        pClassNew[i] = pObj;
+        Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL );
+    }
+
+    // put classes back
+    if ( Vec_PtrSize(p->vClassOld) > 1 )
+        Ssw_ObjAddClass( p, pReprOld, pClassOld, Vec_PtrSize(p->vClassOld) );
+    if ( Vec_PtrSize(p->vClassNew) > 1 )
+        Ssw_ObjAddClass( p, pReprNew, pClassNew, Vec_PtrSize(p->vClassNew) );
+
+    // check if the class should be recursively refined
+    if ( fRecursive && Vec_PtrSize(p->vClassNew) > 1 )
+        return 1 + Ssw_ClassesRefineOneClass( p, pReprNew, 1 );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines the classes after simulation.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ClassesRefine( Ssw_Cla_t * p, int fRecursive )
+{
+    Aig_Obj_t ** ppClass;
+    int i, nRefis = 0;
+    Ssw_ManForEachClass( p, ppClass, i )
+        nRefis += Ssw_ClassesRefineOneClass( p, ppClass[0], fRecursive );
+    return nRefis;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refines the classes after simulation.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ClassesRefineGroup( Ssw_Cla_t * p, Vec_Ptr_t * vReprs, int fRecursive )
+{
+    Aig_Obj_t * pObj;
+    int i, nRefis = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vReprs, pObj, i )
+        nRefis += Ssw_ClassesRefineOneClass( p, pObj, fRecursive );
+    return nRefis;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refine the group of constant 1 nodes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ClassesRefineConst1Group( Ssw_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive )
+{
+    Aig_Obj_t * pObj, * pReprNew, ** ppClassNew;
+    int i;
+    if ( Vec_PtrSize(vRoots) == 0 )
+        return 0;
+    // collect the nodes to be refined
+    Vec_PtrClear( p->vClassNew );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i )
+        if ( !p->pFuncNodeIsConst( p->pManData, pObj ) )
+            Vec_PtrPush( p->vClassNew, pObj );
+    // check if there is a new class
+    if ( Vec_PtrSize(p->vClassNew) == 0 )
+        return 0;
+    p->nCands1 -= Vec_PtrSize(p->vClassNew);
+    pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 );
+    Aig_ObjSetRepr( p->pAig, pReprNew, NULL );
+    if ( Vec_PtrSize(p->vClassNew) == 1 )
+        return 1;
+    // create a new class composed of these nodes
+    ppClassNew = p->pMemClassesFree;
+    p->pMemClassesFree += Vec_PtrSize(p->vClassNew);
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+    {
+        ppClassNew[i] = pObj;
+        Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL );
+    }
+    Ssw_ObjAddClass( p, pReprNew, ppClassNew, Vec_PtrSize(p->vClassNew) );
+    // refine them recursively
+    if ( fRecursive )
+        return 1 + Ssw_ClassesRefineOneClass( p, pReprNew, 1 );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Refine the group of constant 1 nodes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ClassesRefineConst1( Ssw_Cla_t * p, int fRecursive )
+{
+    Aig_Obj_t * pObj, * pReprNew, ** ppClassNew;
+    int i;
+    // collect the nodes to be refined
+    Vec_PtrClear( p->vClassNew );
+    for ( i = 0; i < Vec_PtrSize(p->pAig->vObjs); i++ )
+        if ( p->pAig->pReprs[i] == Aig_ManConst1(p->pAig) )
+        {
+            pObj = Aig_ManObj( p->pAig, i );
+            if ( !p->pFuncNodeIsConst( p->pManData, pObj ) )
+            {
+                Vec_PtrPush( p->vClassNew, pObj );
+//                Vec_PtrPush( p->vRefined, pObj );
+            }
+        }
+    // check if there is a new class
+    if ( Vec_PtrSize(p->vClassNew) == 0 )
+        return 0;
+    if ( p->fConstCorr )
+    {
+        Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+            Aig_ObjSetRepr( p->pAig, pObj, NULL );
+        return 1;
+    }
+    p->nCands1 -= Vec_PtrSize(p->vClassNew);
+    pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 );
+    Aig_ObjSetRepr( p->pAig, pReprNew, NULL );
+    if ( Vec_PtrSize(p->vClassNew) == 1 )
+        return 1;
+    // create a new class composed of these nodes
+    ppClassNew = p->pMemClassesFree;
+    p->pMemClassesFree += Vec_PtrSize(p->vClassNew);
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+    {
+        ppClassNew[i] = pObj;
+        Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL );
+    }
+    Ssw_ObjAddClass( p, pReprNew, ppClassNew, Vec_PtrSize(p->vClassNew) );
+    // refine them recursively
+    if ( fRecursive )
+        return 1 + Ssw_ClassesRefineOneClass( p, pReprNew, 1 );
+    return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswCnf.c b/abc-build/src/proof/ssw/sswCnf.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswCnf.c
@@ -0,0 +1,427 @@
+/**CFile****************************************************************
+
+  FileName    [sswCnf.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [Computation of CNF.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswCnf.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the SAT manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ssw_Sat_t * Ssw_SatStart( int fPolarFlip )
+{
+    Ssw_Sat_t * p;
+    int Lit;
+    p = ABC_ALLOC( Ssw_Sat_t, 1 );
+    memset( p, 0, sizeof(Ssw_Sat_t) );
+    p->pAig          = NULL;
+    p->fPolarFlip    = fPolarFlip;
+    p->vSatVars      = Vec_IntStart( 10000 );
+    p->vFanins       = Vec_PtrAlloc( 100 );
+    p->vUsedPis      = Vec_PtrAlloc( 100 );
+    p->pSat          = sat_solver_new();
+    sat_solver_setnvars( p->pSat, 1000 );
+    // var 0 is not used
+    // var 1 is reserved for const1 node - add the clause
+    p->nSatVars = 1;
+    Lit = toLit( p->nSatVars );
+    if ( fPolarFlip )
+        Lit = lit_neg( Lit );
+    sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+//    Ssw_ObjSetSatNum( p, Aig_ManConst1(p->pAig), p->nSatVars++ );
+    Vec_IntWriteEntry( p->vSatVars, 0, p->nSatVars++ );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop the SAT manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SatStop( Ssw_Sat_t * p )
+{
+//    Abc_Print( 1, "Recycling SAT solver with %d vars and %d restarts.\n", 
+//        p->pSat->size, p->pSat->stats.starts );
+    if ( p->pSat )
+        sat_solver_delete( p->pSat );
+    Vec_IntFree( p->vSatVars );
+    Vec_PtrFree( p->vFanins );
+    Vec_PtrFree( p->vUsedPis );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Addes clauses to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_AddClausesMux( Ssw_Sat_t * p, Aig_Obj_t * pNode )
+{
+    Aig_Obj_t * pNodeI, * pNodeT, * pNodeE;
+    int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE;
+
+    assert( !Aig_IsComplement( pNode ) );
+    assert( Aig_ObjIsMuxType( pNode ) );
+    // get nodes (I = if, T = then, E = else)
+    pNodeI = Aig_ObjRecognizeMux( pNode, &pNodeT, &pNodeE );
+    // get the variable numbers
+    VarF = Ssw_ObjSatNum(p,pNode);
+    VarI = Ssw_ObjSatNum(p,pNodeI);
+    VarT = Ssw_ObjSatNum(p,Aig_Regular(pNodeT));
+    VarE = Ssw_ObjSatNum(p,Aig_Regular(pNodeE));
+    // get the complementation flags
+    fCompT = Aig_IsComplement(pNodeT);
+    fCompE = Aig_IsComplement(pNodeE);
+
+    // f = ITE(i, t, e)
+
+    // i' + t' + f
+    // i' + t  + f'
+    // i  + e' + f
+    // i  + e  + f'
+
+    // create four clauses
+    pLits[0] = toLitCond(VarI, 1);
+    pLits[1] = toLitCond(VarT, 1^fCompT);
+    pLits[2] = toLitCond(VarF, 0);
+    if ( p->fPolarFlip )
+    {
+        if ( pNodeI->fPhase )               pLits[0] = lit_neg( pLits[0] );
+        if ( Aig_Regular(pNodeT)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarI, 1);
+    pLits[1] = toLitCond(VarT, 0^fCompT);
+    pLits[2] = toLitCond(VarF, 1);
+    if ( p->fPolarFlip )
+    {
+        if ( pNodeI->fPhase )               pLits[0] = lit_neg( pLits[0] );
+        if ( Aig_Regular(pNodeT)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarI, 0);
+    pLits[1] = toLitCond(VarE, 1^fCompE);
+    pLits[2] = toLitCond(VarF, 0);
+    if ( p->fPolarFlip )
+    {
+        if ( pNodeI->fPhase )               pLits[0] = lit_neg( pLits[0] );
+        if ( Aig_Regular(pNodeE)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarI, 0);
+    pLits[1] = toLitCond(VarE, 0^fCompE);
+    pLits[2] = toLitCond(VarF, 1);
+    if ( p->fPolarFlip )
+    {
+        if ( pNodeI->fPhase )               pLits[0] = lit_neg( pLits[0] );
+        if ( Aig_Regular(pNodeE)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+
+    // two additional clauses
+    // t' & e' -> f'
+    // t  & e  -> f
+
+    // t  + e   + f'
+    // t' + e'  + f
+
+    if ( VarT == VarE )
+    {
+//        assert( fCompT == !fCompE );
+        return;
+    }
+
+    pLits[0] = toLitCond(VarT, 0^fCompT);
+    pLits[1] = toLitCond(VarE, 0^fCompE);
+    pLits[2] = toLitCond(VarF, 1);
+    if ( p->fPolarFlip )
+    {
+        if ( Aig_Regular(pNodeT)->fPhase )  pLits[0] = lit_neg( pLits[0] );
+        if ( Aig_Regular(pNodeE)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+    pLits[0] = toLitCond(VarT, 1^fCompT);
+    pLits[1] = toLitCond(VarE, 1^fCompE);
+    pLits[2] = toLitCond(VarF, 0);
+    if ( p->fPolarFlip )
+    {
+        if ( Aig_Regular(pNodeT)->fPhase )  pLits[0] = lit_neg( pLits[0] );
+        if ( Aig_Regular(pNodeE)->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        if ( pNode->fPhase )                pLits[2] = lit_neg( pLits[2] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+    assert( RetValue );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Addes clauses to the solver.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_AddClausesSuper( Ssw_Sat_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vSuper )
+{
+    Aig_Obj_t * pFanin;
+    int * pLits, nLits, RetValue, i;
+    assert( !Aig_IsComplement(pNode) );
+    assert( Aig_ObjIsNode( pNode ) );
+    // create storage for literals
+    nLits = Vec_PtrSize(vSuper) + 1;
+    pLits = ABC_ALLOC( int, nLits );
+    // suppose AND-gate is A & B = C
+    // add !A => !C   or   A + !C
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i )
+    {
+        pLits[0] = toLitCond(Ssw_ObjSatNum(p,Aig_Regular(pFanin)), Aig_IsComplement(pFanin));
+        pLits[1] = toLitCond(Ssw_ObjSatNum(p,pNode), 1);
+        if ( p->fPolarFlip )
+        {
+            if ( Aig_Regular(pFanin)->fPhase )  pLits[0] = lit_neg( pLits[0] );
+            if ( pNode->fPhase )                pLits[1] = lit_neg( pLits[1] );
+        }
+        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+    }
+    // add A & B => C   or   !A + !B + C
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i )
+    {
+        pLits[i] = toLitCond(Ssw_ObjSatNum(p,Aig_Regular(pFanin)), !Aig_IsComplement(pFanin));
+        if ( p->fPolarFlip )
+        {
+            if ( Aig_Regular(pFanin)->fPhase )  pLits[i] = lit_neg( pLits[i] );
+        }
+    }
+    pLits[nLits-1] = toLitCond(Ssw_ObjSatNum(p,pNode), 0);
+    if ( p->fPolarFlip )
+    {
+        if ( pNode->fPhase )  pLits[nLits-1] = lit_neg( pLits[nLits-1] );
+    }
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits );
+    assert( RetValue );
+    ABC_FREE( pLits );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_CollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes )
+{
+    // if the new node is complemented or a PI, another gate begins
+    if ( Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) ||
+         (!fFirst && Aig_ObjRefs(pObj) > 1) ||
+         (fUseMuxes && Aig_ObjIsMuxType(pObj)) )
+    {
+        Vec_PtrPushUnique( vSuper, pObj );
+        return;
+    }
+//    pObj->fMarkA = 1;
+    // go through the branches
+    Ssw_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes );
+    Ssw_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper )
+{
+    assert( !Aig_IsComplement(pObj) );
+    assert( !Aig_ObjIsCi(pObj) );
+    Vec_PtrClear( vSuper );
+    Ssw_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the solver clause database.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ObjAddToFrontier( Ssw_Sat_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier )
+{
+    assert( !Aig_IsComplement(pObj) );
+    if ( Ssw_ObjSatNum(p,pObj) )
+        return;
+    assert( Ssw_ObjSatNum(p,pObj) == 0 );
+    if ( Aig_ObjIsConst1(pObj) )
+        return;
+//    pObj->fMarkA = 1;
+    // save PIs (used by register correspondence)
+    if ( Aig_ObjIsCi(pObj) )
+        Vec_PtrPush( p->vUsedPis, pObj );
+    Ssw_ObjSetSatNum( p, pObj, p->nSatVars++ );
+    sat_solver_setnvars( p->pSat, 100 * (1 + p->nSatVars / 100) );
+    if ( Aig_ObjIsNode(pObj) )
+        Vec_PtrPush( vFrontier, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the solver clause database.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_CnfNodeAddToSolver( Ssw_Sat_t * p, Aig_Obj_t * pObj )
+{
+    Vec_Ptr_t * vFrontier;
+    Aig_Obj_t * pNode, * pFanin;
+    int i, k, fUseMuxes = 1;
+    // quit if CNF is ready
+    if ( Ssw_ObjSatNum(p,pObj) )
+        return;
+    // start the frontier
+    vFrontier = Vec_PtrAlloc( 100 );
+    Ssw_ObjAddToFrontier( p, pObj, vFrontier );
+    // explore nodes in the frontier
+    Vec_PtrForEachEntry( Aig_Obj_t *, vFrontier, pNode, i )
+    {
+        // create the supergate
+        assert( Ssw_ObjSatNum(p,pNode) );
+        if ( fUseMuxes && Aig_ObjIsMuxType(pNode) )
+        {
+            Vec_PtrClear( p->vFanins );
+            Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) );
+            Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) );
+            Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) );
+            Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) );
+            Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k )
+                Ssw_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier );
+            Ssw_AddClausesMux( p, pNode );
+        }
+        else
+        {
+            Ssw_CollectSuper( pNode, fUseMuxes, p->vFanins );
+            Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k )
+                Ssw_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier );
+            Ssw_AddClausesSuper( p, pNode, p->vFanins );
+        }
+        assert( Vec_PtrSize(p->vFanins) > 1 );
+    }
+    Vec_PtrFree( vFrontier );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Copy pattern from the solver into the internal storage.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_CnfGetNodeValue( Ssw_Sat_t * p, Aig_Obj_t * pObj )
+{
+    int Value0, Value1, nVarNum;
+    assert( !Aig_IsComplement(pObj) );
+    nVarNum = Ssw_ObjSatNum( p, pObj );
+    if ( nVarNum > 0 )
+        return sat_solver_var_value( p->pSat, nVarNum );
+//    if ( pObj->fMarkA == 1 )
+//        return 0;
+    if ( Aig_ObjIsCi(pObj) )
+        return 0;
+    assert( Aig_ObjIsNode(pObj) );
+    Value0 = Ssw_CnfGetNodeValue( p, Aig_ObjFanin0(pObj) );
+    Value0 ^= Aig_ObjFaninC0(pObj);
+    Value1 = Ssw_CnfGetNodeValue( p, Aig_ObjFanin1(pObj) );
+    Value1 ^= Aig_ObjFaninC1(pObj);
+    return Value0 & Value1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswConstr.c b/abc-build/src/proof/ssw/sswConstr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswConstr.c
@@ -0,0 +1,716 @@
+/**CFile****************************************************************
+
+  FileName    [sswConstr.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [One round of SAT sweeping.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswConstr.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+#include "sat/cnf/cnf.h"
+#include "misc/bar/bar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Constructs initialized timeframes with constraints as POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Ssw_FramesWithConstraints( Aig_Man_t * p, int nFrames )
+{
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i, f;
+//    assert( Saig_ManConstrNum(p) > 0 );
+    assert( Aig_ManRegNum(p) > 0 );
+    assert( Aig_ManRegNum(p) < Aig_ManCiNum(p) );
+    // start the fraig package
+    pFrames = Aig_ManStart( Aig_ManObjNumMax(p) * nFrames );
+    // create latches for the first frame
+    Saig_ManForEachLo( p, pObj, i )
+        Aig_ObjSetCopy( pObj, Aig_ManConst0(pFrames) );
+    // add timeframes
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // map constants and PIs
+        Aig_ObjSetCopy( Aig_ManConst1(p), Aig_ManConst1(pFrames) );
+        Saig_ManForEachPi( p, pObj, i )
+            Aig_ObjSetCopy( pObj, Aig_ObjCreateCi(pFrames) );
+        // add internal nodes of this frame
+        Aig_ManForEachNode( p, pObj, i )
+            Aig_ObjSetCopy( pObj, Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ) );
+        // transfer to the primary output
+        Aig_ManForEachCo( p, pObj, i )
+            Aig_ObjSetCopy( pObj, Aig_ObjChild0Copy(pObj) );
+        // create constraint outputs
+        Saig_ManForEachPo( p, pObj, i )
+        {
+            if ( i < Saig_ManPoNum(p) - Saig_ManConstrNum(p) )
+                continue;
+            Aig_ObjCreateCo( pFrames, Aig_Not( Aig_ObjCopy(pObj) ) );
+        }
+        // transfer latch inputs to the latch outputs
+        Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
+            Aig_ObjSetCopy( pObjLo, Aig_ObjCopy(pObjLi) );
+    }
+    // remove dangling nodes
+    Aig_ManCleanup( pFrames );
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Finds one satisfiable assignment of the timeframes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManSetConstrPhases( Aig_Man_t * p, int nFrames, Vec_Int_t ** pvInits )
+{
+    Aig_Man_t * pFrames;
+    sat_solver * pSat;
+    Cnf_Dat_t * pCnf;
+    Aig_Obj_t * pObj;
+    int i, RetValue;
+    if ( pvInits )
+        *pvInits = NULL;
+//    assert( p->nConstrs > 0 );
+    // derive the timeframes
+    pFrames = Ssw_FramesWithConstraints( p, nFrames );
+    // create CNF
+    pCnf = Cnf_Derive( pFrames, 0 );
+    // create SAT solver
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+    if ( pSat == NULL )
+    {
+        Cnf_DataFree( pCnf );
+        Aig_ManStop( pFrames );
+        return 1;
+    }
+    // solve
+    RetValue = sat_solver_solve( pSat, NULL, NULL,
+        (ABC_INT64_T)1000000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( RetValue == l_True && pvInits )
+    {
+        *pvInits = Vec_IntAlloc( 1000 );
+        Aig_ManForEachCi( pFrames, pObj, i )
+            Vec_IntPush( *pvInits, sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) );
+
+//        Aig_ManForEachCi( pFrames, pObj, i )
+//            Abc_Print( 1, "%d", Vec_IntEntry(*pvInits, i) );
+//        Abc_Print( 1, "\n" );
+    }
+    sat_solver_delete( pSat );
+    Cnf_DataFree( pCnf );
+    Aig_ManStop( pFrames );
+    if ( RetValue == l_False )
+        return 1;
+    if ( RetValue == l_True )
+        return 0;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for one node.]
+
+  Description [Returns the fraiged node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManSetConstrPhases_( Aig_Man_t * p, int nFrames, Vec_Int_t ** pvInits )
+{
+    Vec_Int_t * vLits;
+    sat_solver * pSat;
+    Cnf_Dat_t * pCnf;
+    Aig_Obj_t * pObj;
+    int i, f, iVar, RetValue, nRegs;
+    if ( pvInits )
+        *pvInits = NULL;
+    assert( p->nConstrs > 0 );
+    // create CNF
+    nRegs = p->nRegs; p->nRegs = 0;
+    pCnf = Cnf_Derive( p, Aig_ManCoNum(p) );
+    p->nRegs = nRegs;
+    // create SAT solver
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, nFrames, 0 );
+    assert( pSat->size == nFrames * pCnf->nVars );
+    // collect constraint literals
+    vLits = Vec_IntAlloc( 100 );
+    Saig_ManForEachLo( p, pObj, i )
+    {
+        assert( pCnf->pVarNums[Aig_ObjId(pObj)] >= 0 );
+        Vec_IntPush( vLits, toLitCond(pCnf->pVarNums[Aig_ObjId(pObj)], 1) );
+    }
+    for ( f = 0; f < nFrames; f++ )
+    {
+        Saig_ManForEachPo( p, pObj, i )
+        {
+            if ( i < Saig_ManPoNum(p) - Saig_ManConstrNum(p) )
+                continue;
+            assert( pCnf->pVarNums[Aig_ObjId(pObj)] >= 0 );
+            iVar = pCnf->pVarNums[Aig_ObjId(pObj)] + pCnf->nVars*f;
+            Vec_IntPush( vLits, toLitCond(iVar, 1) );
+        }
+    }
+    RetValue = sat_solver_solve( pSat, (int *)Vec_IntArray(vLits),
+        (int *)Vec_IntArray(vLits) + Vec_IntSize(vLits),
+        (ABC_INT64_T)1000000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( RetValue == l_True && pvInits )
+    {
+        *pvInits = Vec_IntAlloc( 1000 );
+        for ( f = 0; f < nFrames; f++ )
+        {
+            Saig_ManForEachPi( p, pObj, i )
+            {
+                iVar = pCnf->pVarNums[Aig_ObjId(pObj)] + pCnf->nVars*f;
+                Vec_IntPush( *pvInits, sat_solver_var_value(pSat, iVar) );
+            }
+        }
+    }
+    sat_solver_delete( pSat );
+    Vec_IntFree( vLits );
+    Cnf_DataFree( pCnf );
+    if ( RetValue == l_False )
+        return 1;
+    if ( RetValue == l_True )
+        return 0;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for one node.]
+
+  Description [Returns the fraiged node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManPrintPolarity( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachObj( p, pObj, i )
+        Abc_Print( 1, "%d", pObj->fPhase );
+    Abc_Print( 1, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for one node.]
+
+  Description [Returns the fraiged node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManRefineByConstrSim( Ssw_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pObjLi;
+    int f, i, iLits, RetValue1, RetValue2;
+    int nFrames = Vec_IntSize(p->vInits) / Saig_ManPiNum(p->pAig);
+    assert( Vec_IntSize(p->vInits) % Saig_ManPiNum(p->pAig) == 0 );
+    // assign register outputs
+    Saig_ManForEachLi( p->pAig, pObj, i )
+        pObj->fMarkB = 0;
+    // simulate the timeframes
+    iLits = 0;
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // set the PI simulation information
+        Aig_ManConst1(p->pAig)->fMarkB = 1;
+        Saig_ManForEachPi( p->pAig, pObj, i )
+            pObj->fMarkB = Vec_IntEntry( p->vInits, iLits++ );
+        Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i )
+            pObj->fMarkB = pObjLi->fMarkB;
+        // simulate internal nodes
+        Aig_ManForEachNode( p->pAig, pObj, i )
+            pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+                         & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+        // assign the COs
+        Aig_ManForEachCo( p->pAig, pObj, i )
+            pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) );
+        // check the outputs
+        Saig_ManForEachPo( p->pAig, pObj, i )
+        {
+            if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) )
+            {
+                if ( pObj->fMarkB && Saig_ManConstrNum(p->pAig) )
+                    Abc_Print( 1, "output %d failed in frame %d.\n", i, f );
+            }
+            else
+            {
+                if ( pObj->fMarkB && Saig_ManConstrNum(p->pAig) )
+                    Abc_Print( 1, "constraint %d failed in frame %d.\n", i, f );
+            }
+        }
+        // transfer
+        if ( f == 0 )
+        { // copy markB into phase
+            Aig_ManForEachObj( p->pAig, pObj, i )
+                pObj->fPhase = pObj->fMarkB;
+        }
+        else
+        { // refine classes
+            RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 0 );
+            RetValue2 = Ssw_ClassesRefine( p->ppClasses, 0 );
+        }
+    }
+    assert( iLits == Vec_IntSize(p->vInits) );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for one node.]
+
+  Description [Returns the fraiged node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManSweepNodeConstr( Ssw_Man_t * p, Aig_Obj_t * pObj, int f, int fBmc )
+{
+    Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig;
+    int RetValue;
+    // get representative of this class
+    pObjRepr = Aig_ObjRepr( p->pAig, pObj );
+    if ( pObjRepr == NULL )
+        return 0;
+    // get the fraiged node
+    pObjFraig = Ssw_ObjFrame( p, pObj, f );
+    // get the fraiged representative
+    pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, f );
+    // check if constant 0 pattern distinquishes these nodes
+    assert( pObjFraig != NULL && pObjReprFraig != NULL );
+    assert( (pObj->fPhase == pObjRepr->fPhase) == (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) );
+    // if the fraiged nodes are the same, return
+    if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) )
+        return 0;
+    // call equivalence checking
+    if ( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pFrames) )
+        RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) );
+    else
+        RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) );
+    if ( RetValue == 1 )  // proved equivalent
+    {
+        pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase );
+        Ssw_ObjSetFrame( p, pObj, f, pObjFraig2 );
+        return 0;
+    }
+    if ( RetValue == -1 ) // timed out
+    {
+        Ssw_ClassesRemoveNode( p->ppClasses, pObj );
+        return 1;
+    }
+    // disproved equivalence
+    Ssw_SmlSavePatternAig( p, f );
+    Ssw_ManResimulateBit( p, pObj, pObjRepr );
+    assert( Aig_ObjRepr( p->pAig, pObj ) != pObjRepr );
+    if ( Aig_ObjRepr( p->pAig, pObj ) == pObjRepr )
+    {
+        Abc_Print( 1, "Ssw_ManSweepNodeConstr(): Failed to refine representative.\n" );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Ssw_ManSweepBmcConstr_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, int f )
+{
+    Aig_Obj_t * pObjNew, * pObjLi;
+    pObjNew = Ssw_ObjFrame( p, pObj, f );
+    if ( pObjNew )
+        return pObjNew;
+    assert( !Saig_ObjIsPi(p->pAig, pObj) );
+    if ( Saig_ObjIsLo(p->pAig, pObj) )
+    {
+        assert( f > 0 );
+        pObjLi  = Saig_ObjLoToLi( p->pAig, pObj );
+        pObjNew = Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObjLi), f-1 );
+        pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObjLi) );
+    }
+    else
+    {
+        assert( Aig_ObjIsNode(pObj) );
+        Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObj), f );
+        Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin1(pObj), f );
+        pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+    }
+    Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+    assert( pObjNew != NULL );
+    return pObjNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for the internal nodes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManSweepBmcConstr_old( Ssw_Man_t * p )
+{
+    Bar_Progress_t * pProgress = NULL;
+    Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo;
+    int i, f, iLits;
+    abctime clk;
+clk = Abc_Clock();
+
+    // start initialized timeframes
+    p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK );
+    Saig_ManForEachLo( p->pAig, pObj, i )
+        Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) );
+
+    // build the constraint outputs
+    iLits = 0;
+    for ( f = 0; f < p->pPars->nFramesK; f++ )
+    {
+        // map constants and PIs
+        Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
+        Saig_ManForEachPi( p->pAig, pObj, i )
+        {
+            pObjNew = Aig_ObjCreateCi(p->pFrames);
+            pObjNew->fPhase = Vec_IntEntry( p->vInits, iLits++ );
+            Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+        }
+        // build the constraint cones
+        Saig_ManForEachPo( p->pAig, pObj, i )
+        {
+            if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) )
+                continue;
+            pObjNew = Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObj), f );
+            pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) );
+            if ( Aig_Regular(pObjNew) == Aig_ManConst1(p->pFrames) )
+            {
+                assert( Aig_IsComplement(pObjNew) );
+                continue;
+            }
+            Ssw_NodesAreConstrained( p, pObjNew, Aig_ManConst0(p->pFrames) );
+        }
+    }
+    assert( Vec_IntSize(p->vInits) == iLits + Saig_ManPiNum(p->pAig) );
+
+    // sweep internal nodes
+    p->fRefined = 0;
+    if ( p->pPars->fVerbose )
+        pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK );
+    for ( f = 0; f < p->pPars->nFramesK; f++ )
+    {
+        // sweep internal nodes
+        Aig_ManForEachNode( p->pAig, pObj, i )
+        {
+            if ( p->pPars->fVerbose )
+                Bar_ProgressUpdate( pProgress, Aig_ManObjNumMax(p->pAig) * f + i, NULL );
+            pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+            Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+            p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 1 );
+        }
+        // quit if this is the last timeframe
+        if ( f == p->pPars->nFramesK - 1 )
+            break;
+        // transfer latch input to the latch outputs
+        Aig_ManForEachCo( p->pAig, pObj, i )
+            Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) );
+        // build logic cones for register outputs
+        Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+        {
+            pObjNew = Ssw_ObjFrame( p, pObjLi, f );
+            Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew );
+            Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );//
+        }
+    }
+    if ( p->pPars->fVerbose )
+        Bar_ProgressStop( pProgress );
+
+    // cleanup
+//    Ssw_ClassesCheck( p->ppClasses );
+p->timeBmc += Abc_Clock() - clk;
+    return p->fRefined;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for the internal nodes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManSweepBmcConstr( Ssw_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo;
+    int i, f, iLits;
+    abctime clk;
+clk = Abc_Clock();
+
+    // start initialized timeframes
+    p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK );
+    Saig_ManForEachLo( p->pAig, pObj, i )
+        Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) );
+
+    // build the constraint outputs
+    iLits = 0;
+    p->fRefined = 0;
+    for ( f = 0; f < p->pPars->nFramesK; f++ )
+    {
+        // map constants and PIs
+        Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
+        Saig_ManForEachPi( p->pAig, pObj, i )
+        {
+            pObjNew = Aig_ObjCreateCi(p->pFrames);
+            pObjNew->fPhase = Vec_IntEntry( p->vInits, iLits++ );
+            Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+        }
+        // build the constraint cones
+        Saig_ManForEachPo( p->pAig, pObj, i )
+        {
+            if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) )
+                continue;
+            pObjNew = Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObj), f );
+            pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) );
+            if ( Aig_Regular(pObjNew) == Aig_ManConst1(p->pFrames) )
+            {
+                assert( Aig_IsComplement(pObjNew) );
+                continue;
+            }
+            Ssw_NodesAreConstrained( p, pObjNew, Aig_ManConst0(p->pFrames) );
+        }
+
+        // sweep internal nodes
+        Aig_ManForEachNode( p->pAig, pObj, i )
+        {
+            pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+            Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+            p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 1 );
+        }
+        // quit if this is the last timeframe
+        if ( f == p->pPars->nFramesK - 1 )
+            break;
+        // transfer latch input to the latch outputs
+        Aig_ManForEachCo( p->pAig, pObj, i )
+            Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) );
+        // build logic cones for register outputs
+        Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+        {
+            pObjNew = Ssw_ObjFrame( p, pObjLi, f );
+            Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew );
+            Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );//
+        }
+    }
+    assert( Vec_IntSize(p->vInits) == iLits + Saig_ManPiNum(p->pAig) );
+
+    // cleanup
+//    Ssw_ClassesCheck( p->ppClasses );
+p->timeBmc += Abc_Clock() - clk;
+    return p->fRefined;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for the internal nodes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Ssw_FramesWithClasses_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, int f )
+{
+    Aig_Obj_t * pObjNew, * pObjLi;
+    pObjNew = Ssw_ObjFrame( p, pObj, f );
+    if ( pObjNew )
+        return pObjNew;
+    assert( !Saig_ObjIsPi(p->pAig, pObj) );
+    if ( Saig_ObjIsLo(p->pAig, pObj) )
+    {
+        assert( f > 0 );
+        pObjLi  = Saig_ObjLoToLi( p->pAig, pObj );
+        pObjNew = Ssw_FramesWithClasses_rec( p, Aig_ObjFanin0(pObjLi), f-1 );
+        pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObjLi) );
+    }
+    else
+    {
+        assert( Aig_ObjIsNode(pObj) );
+        Ssw_FramesWithClasses_rec( p, Aig_ObjFanin0(pObj), f );
+        Ssw_FramesWithClasses_rec( p, Aig_ObjFanin1(pObj), f );
+        pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+    }
+    Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+    assert( pObjNew != NULL );
+    return pObjNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for the internal nodes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManSweepConstr( Ssw_Man_t * p )
+{
+    Bar_Progress_t * pProgress = NULL;
+    Aig_Obj_t * pObj, * pObj2, * pObjNew;
+    int nConstrPairs, i, f, iLits;
+    abctime clk;
+//Ssw_ManPrintPolarity( p->pAig );
+
+    // perform speculative reduction
+clk = Abc_Clock();
+    // create timeframes
+    p->pFrames = Ssw_FramesWithClasses( p );
+    // add constants
+    nConstrPairs = Aig_ManCoNum(p->pFrames)-Aig_ManRegNum(p->pAig);
+    assert( (nConstrPairs & 1) == 0 );
+    for ( i = 0; i < nConstrPairs; i += 2 )
+    {
+        pObj  = Aig_ManCo( p->pFrames, i   );
+        pObj2 = Aig_ManCo( p->pFrames, i+1 );
+        Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj), Aig_ObjChild0(pObj2) );
+    }
+    // build logic cones for register inputs
+    for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ )
+    {
+        pObj  = Aig_ManCo( p->pFrames, nConstrPairs + i );
+        Ssw_CnfNodeAddToSolver( p->pMSat, Aig_ObjFanin0(pObj) );//
+    }
+
+    // map constants and PIs of the last frame
+    f = p->pPars->nFramesK;
+//    iLits = 0;
+    iLits = f * Saig_ManPiNum(p->pAig);
+    Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
+    Saig_ManForEachPi( p->pAig, pObj, i )
+    {
+        pObjNew = Aig_ObjCreateCi(p->pFrames);
+        pObjNew->fPhase = (p->vInits != NULL) && Vec_IntEntry(p->vInits, iLits++);
+        Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+    }
+    assert( Vec_IntSize(p->vInits) == iLits );
+p->timeReduce += Abc_Clock() - clk;
+
+    // add constraints to all timeframes
+    for ( f = 0; f <= p->pPars->nFramesK; f++ )
+    {
+        Saig_ManForEachPo( p->pAig, pObj, i )
+        {
+            if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) )
+                continue;
+            Ssw_FramesWithClasses_rec( p, Aig_ObjFanin0(pObj), f );
+//            if ( Aig_Regular(Ssw_ObjChild0Fra(p,pObj,f)) == Aig_ManConst1(p->pFrames) )
+            if ( Ssw_ObjChild0Fra(p,pObj,f) == Aig_ManConst0(p->pFrames) )
+                continue;
+            assert( Ssw_ObjChild0Fra(p,pObj,f) != Aig_ManConst1(p->pFrames) );
+            if ( Ssw_ObjChild0Fra(p,pObj,f) == Aig_ManConst1(p->pFrames) )
+            {
+                Abc_Print( 1, "Polarity violation.\n" );
+                continue;
+            }
+            Ssw_NodesAreConstrained( p, Ssw_ObjChild0Fra(p,pObj,f), Aig_ManConst0(p->pFrames) );
+        }
+    }
+    f = p->pPars->nFramesK;
+    // clean the solver
+    sat_solver_simplify( p->pMSat->pSat );
+
+
+    // sweep internal nodes
+    p->fRefined = 0;
+    Ssw_ClassesClearRefined( p->ppClasses );
+    if ( p->pPars->fVerbose )
+        pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) );
+    Aig_ManForEachObj( p->pAig, pObj, i )
+    {
+        if ( p->pPars->fVerbose )
+            Bar_ProgressUpdate( pProgress, i, NULL );
+        if ( Saig_ObjIsLo(p->pAig, pObj) )
+            p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 0 );
+        else if ( Aig_ObjIsNode(pObj) )
+        {
+            pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+            Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+            p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 0 );
+        }
+    }
+    if ( p->pPars->fVerbose )
+        Bar_ProgressStop( pProgress );
+    // cleanup
+//    Ssw_ClassesCheck( p->ppClasses );
+    return p->fRefined;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswCore.c b/abc-build/src/proof/ssw/sswCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswCore.c
@@ -0,0 +1,539 @@
+/**CFile****************************************************************
+
+  FileName    [sswCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [The core procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswCore.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManSetDefaultParams( Ssw_Pars_t * p )
+{
+    memset( p, 0, sizeof(Ssw_Pars_t) );
+    p->nPartSize      =       0;  // size of the partition
+    p->nOverSize      =       0;  // size of the overlap between partitions
+    p->nFramesK       =       1;  // the induction depth
+    p->nFramesAddSim  =       2;  // additional frames to simulate
+    p->fConstrs       =       0;  // treat the last nConstrs POs as seq constraints
+    p->fMergeFull     =       0;  // enables full merge when constraints are used
+    p->nBTLimit       =    1000;  // conflict limit at a node
+    p->nBTLimitGlobal = 5000000;  // conflict limit for all runs
+    p->nMinDomSize    =     100;  // min clock domain considered for optimization
+    p->nItersStop     =      -1;  // stop after the given number of iterations
+    p->nResimDelta    =    1000;  // the internal of nodes to resimulate
+    p->nStepsMax      =      -1;  // (scorr only) the max number of induction steps
+    p->fPolarFlip     =       0;  // uses polarity adjustment
+    p->fLatchCorr     =       0;  // performs register correspondence
+    p->fConstCorr     =       0;  // performs constant correspondence
+    p->fOutputCorr    =       0;  // perform 'PO correspondence'
+    p->fSemiFormal    =       0;  // enable semiformal filtering
+    p->fDynamic       =       0;  // dynamic partitioning
+    p->fLocalSim      =       0;  // local simulation
+    p->fVerbose       =       0;  // verbose stats
+    p->fEquivDump     =       0;  // enables dumping equivalences
+
+    // latch correspondence
+    p->fLatchCorrOpt  =       0;  // performs optimized register correspondence
+    p->nSatVarMax     =    1000;  // the max number of SAT variables
+    p->nRecycleCalls  =      50;  // calls to perform before recycling SAT solver
+    // signal correspondence
+    p->nSatVarMax2    =    5000;  // the max number of SAT variables
+    p->nRecycleCalls2 =     250;  // calls to perform before recycling SAT solver
+    // return values
+    p->nIters         =       0;  // the number of iterations performed
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManSetDefaultParamsLcorr( Ssw_Pars_t * p )
+{
+    Ssw_ManSetDefaultParams( p );
+    p->fLatchCorrOpt = 1;
+    p->nBTLimit      = 10000;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports improvements for property cones.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ReportConeReductions( Ssw_Man_t * p, Aig_Man_t * pAigInit, Aig_Man_t * pAigStop )
+{
+    Aig_Man_t * pAig1, * pAig2, * pAux;
+    pAig1 = Aig_ManDupOneOutput( pAigInit, 0, 1 );
+    pAig1 = Aig_ManScl( pAux = pAig1, 1, 1, 0, -1, -1, 0, 0 );
+    Aig_ManStop( pAux );
+    pAig2 = Aig_ManDupOneOutput( pAigStop, 0, 1 );
+    pAig2 = Aig_ManScl( pAux = pAig2, 1, 1, 0, -1, -1, 0, 0 );
+    Aig_ManStop( pAux );
+
+    p->nNodesBegC = Aig_ManNodeNum(pAig1);
+    p->nNodesEndC = Aig_ManNodeNum(pAig2);
+    p->nRegsBegC  = Aig_ManRegNum(pAig1);
+    p->nRegsEndC  = Aig_ManRegNum(pAig2);
+
+    Aig_ManStop( pAig1 );
+    Aig_ManStop( pAig2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ReportOneOutput( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    if ( pObj == Aig_ManConst1(p) )
+        Abc_Print( 1, "1" );
+    else if ( pObj == Aig_ManConst0(p) )
+        Abc_Print( 1, "0" );
+    else
+        Abc_Print( 1, "X" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports improvements for property cones.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ReportOutputs( Aig_Man_t * pAig )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Saig_ManForEachPo( pAig, pObj, i )
+    {
+        if ( i < Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) )
+            Abc_Print( 1, "o" );
+        else
+            Abc_Print( 1, "c" );
+        Ssw_ReportOneOutput( pAig, Aig_ObjChild0(pObj) );
+    }
+    Abc_Print( 1, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Remove from-equivs that are in the cone of constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManUpdateEquivs( Ssw_Man_t * p, Aig_Man_t * pAig, int fVerbose )
+{
+    Vec_Ptr_t * vCones;
+    Aig_Obj_t ** pArray;
+    Aig_Obj_t * pObj;
+    int i, nTotal = 0, nRemoved = 0;
+    // collect the nodes in the cone of constraints
+    pArray  = (Aig_Obj_t **)Vec_PtrArray(pAig->vCos);
+    pArray += Saig_ManPoNum(pAig) - Saig_ManConstrNum(pAig);
+    vCones  = Aig_ManDfsNodes( pAig, pArray, Saig_ManConstrNum(pAig) );
+    // remove all the node that are equiv to something and are in the cones
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+        if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) )
+            continue;
+        if ( pAig->pReprs[i] != NULL )
+            nTotal++;
+        if ( !Aig_ObjIsTravIdCurrent(pAig, pObj) )
+            continue;
+        if ( pAig->pReprs[i] )
+        {
+            if ( p->pPars->fConstrs && !p->pPars->fMergeFull )
+            {
+                pAig->pReprs[i] = NULL;
+                nRemoved++;
+            }
+        }
+    }
+    // collect statistics    
+    p->nConesTotal   = Aig_ManCiNum(pAig) + Aig_ManNodeNum(pAig);
+    p->nConesConstr  = Vec_PtrSize(vCones);
+    p->nEquivsTotal  = nTotal;
+    p->nEquivsConstr = nRemoved;
+    Vec_PtrFree( vCones );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs computation of signal correspondence with constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Ssw_SignalCorrespondenceRefine( Ssw_Man_t * p )
+{
+    int nSatProof, nSatCallsSat, nRecycles, nSatFailsReal, nUniques;
+    Aig_Man_t * pAigNew;
+    int RetValue, nIter = -1;
+    abctime clk, clkTotal = Abc_Clock();
+    // get the starting stats
+    p->nLitsBeg  = Ssw_ClassesLitNum( p->ppClasses );
+    p->nNodesBeg = Aig_ManNodeNum(p->pAig);
+    p->nRegsBeg  = Aig_ManRegNum(p->pAig);
+    // refine classes using BMC
+    if ( p->pPars->fVerbose )
+    {
+        Abc_Print( 1, "Before BMC: " );
+        Ssw_ClassesPrint( p->ppClasses, 0 );
+    }
+    if ( !p->pPars->fLatchCorr )
+    {
+        p->pMSat = Ssw_SatStart( 0 );
+        if ( p->pPars->fConstrs )
+            Ssw_ManSweepBmcConstr( p );
+        else
+            Ssw_ManSweepBmc( p );
+        Ssw_SatStop( p->pMSat );
+        p->pMSat = NULL;
+        Ssw_ManCleanup( p );
+    }
+    if ( p->pPars->fVerbose )
+    {
+        Abc_Print( 1, "After  BMC: " );
+        Ssw_ClassesPrint( p->ppClasses, 0 );
+    }
+    // apply semi-formal filtering
+/*
+    if ( p->pPars->fSemiFormal )
+    {
+        Aig_Man_t * pSRed;
+        Ssw_FilterUsingSemi( p, 0, 2000, p->pPars->fVerbose );
+//        Ssw_FilterUsingSemi( p, 1, 100000, p->pPars->fVerbose );
+        pSRed = Ssw_SpeculativeReduction( p );
+        Aig_ManDumpBlif( pSRed, "srm.blif", NULL, NULL );
+        Aig_ManStop( pSRed );
+    }
+*/
+    if ( p->pPars->pFunc )
+    {
+        ((int (*)(void *))p->pPars->pFunc)( p->pPars->pData );
+        ((int (*)(void *))p->pPars->pFunc)( p->pPars->pData );
+    }
+    if ( p->pPars->nStepsMax == 0 )
+    {
+        Abc_Print( 1, "Stopped signal correspondence after BMC.\n" );
+        goto finalize;
+    }
+    // refine classes using induction
+    nSatProof = nSatCallsSat = nRecycles = nSatFailsReal = nUniques = 0;
+    for ( nIter = 0; ; nIter++ )
+    {
+        if ( p->pPars->nStepsMax == nIter )
+        {
+            Abc_Print( 1, "Stopped signal correspondence after %d refiment iterations.\n", nIter );
+            goto finalize;
+        }
+        if ( p->pPars->nItersStop >= 0 && p->pPars->nItersStop == nIter )
+        {
+            Aig_Man_t * pSRed = Ssw_SpeculativeReduction( p );
+            Aig_ManDumpBlif( pSRed, "srm.blif", NULL, NULL );
+            Aig_ManStop( pSRed );
+            Abc_Print( 1, "Iterative refinement is stopped before iteration %d.\n", nIter );
+            Abc_Print( 1, "The network is reduced using candidate equivalences.\n" );
+            Abc_Print( 1, "Speculatively reduced miter is saved in file \"%s\".\n", "srm.blif" );
+            Abc_Print( 1, "If the miter is SAT, the reduced result is incorrect.\n" );
+            break;
+        }
+
+clk = Abc_Clock();
+        p->pMSat = Ssw_SatStart( 0 );
+        if ( p->pPars->fLatchCorrOpt )
+        {
+            RetValue = Ssw_ManSweepLatch( p );
+            if ( p->pPars->fVerbose )
+            {
+                Abc_Print( 1, "%3d : C =%7d. Cl =%7d. Pr =%6d. Cex =%5d. R =%4d. F =%4d. ",
+                    nIter, Ssw_ClassesCand1Num(p->ppClasses), Ssw_ClassesClassNum(p->ppClasses),
+                    p->nSatProof-nSatProof, p->nSatCallsSat-nSatCallsSat,
+                    p->nRecycles-nRecycles, p->nSatFailsReal-nSatFailsReal );
+                ABC_PRT( "T", Abc_Clock() - clk );
+            }
+        }
+        else
+        {
+            if ( p->pPars->fConstrs )
+                RetValue = Ssw_ManSweepConstr( p );
+            else if ( p->pPars->fDynamic )
+                RetValue = Ssw_ManSweepDyn( p );
+            else
+                RetValue = Ssw_ManSweep( p );
+
+            p->pPars->nConflicts += p->pMSat->pSat->stats.conflicts;
+            if ( p->pPars->fVerbose )
+            {
+                Abc_Print( 1, "%3d : C =%7d. Cl =%7d. LR =%6d. NR =%6d. ",
+                    nIter, Ssw_ClassesCand1Num(p->ppClasses), Ssw_ClassesClassNum(p->ppClasses),
+                    p->nConstrReduced, Aig_ManNodeNum(p->pFrames) );
+                if ( p->pPars->fDynamic )
+                {
+                    Abc_Print( 1, "Cex =%5d. ", p->nSatCallsSat-nSatCallsSat );
+                    Abc_Print( 1, "R =%4d. ",   p->nRecycles-nRecycles );
+                }
+                Abc_Print( 1, "F =%5d. %s ", p->nSatFailsReal-nSatFailsReal,
+                    (Saig_ManPoNum(p->pAig)==1 && Ssw_ObjIsConst1Cand(p->pAig,Aig_ObjFanin0(Aig_ManCo(p->pAig,0))))? "+" : "-" );
+                ABC_PRT( "T", Abc_Clock() - clk );
+            }
+//            if ( p->pPars->fDynamic && p->nSatCallsSat-nSatCallsSat < 100 )
+//                p->pPars->nBTLimit = 10000;
+
+            if ( p->pPars->fStopWhenGone && Saig_ManPoNum(p->pAig) == 1 && !Ssw_ObjIsConst1Cand(p->pAig,Aig_ObjFanin0(Aig_ManCo(p->pAig,0))) )
+            {
+                printf( "Iterative refinement is stopped after iteration %d\n", nIter );
+                printf( "because the property output is no longer a candidate constant.\n" );
+                // prepare to quite
+                p->nLitsEnd  = p->nLitsBeg;
+                p->nNodesEnd = p->nNodesBeg;
+                p->nRegsEnd  = p->nRegsBeg;
+                // cleanup
+                Ssw_SatStop( p->pMSat );
+                p->pMSat = NULL;
+                Ssw_ManCleanup( p );
+                // cleanup
+                Aig_ManSetPhase( p->pAig );
+                Aig_ManCleanMarkB( p->pAig );
+                return Aig_ManDupSimple( p->pAig );
+            }
+        }
+        nSatProof     = p->nSatProof;
+        nSatCallsSat  = p->nSatCallsSat;
+        nRecycles     = p->nRecycles;
+        nSatFailsReal = p->nSatFailsReal;
+        nUniques      = p->nUniques;
+
+        p->nVarsMax  = Abc_MaxInt( p->nVarsMax,  p->pMSat->nSatVars );
+        p->nCallsMax = Abc_MaxInt( p->nCallsMax, p->pMSat->nSolverCalls );
+        Ssw_SatStop( p->pMSat );
+        p->pMSat = NULL;
+        Ssw_ManCleanup( p );
+        if ( !RetValue )
+            break;
+        if ( p->pPars->pFunc )
+            ((int (*)(void *))p->pPars->pFunc)( p->pPars->pData );
+    }
+
+finalize:
+    p->pPars->nIters = nIter + 1;
+p->timeTotal = Abc_Clock() - clkTotal;
+
+    Ssw_ManUpdateEquivs( p, p->pAig, p->pPars->fVerbose );
+    pAigNew = Aig_ManDupRepr( p->pAig, 0 );
+    Aig_ManSeqCleanup( pAigNew );
+//Ssw_ClassesPrint( p->ppClasses, 1 );
+    // get the final stats
+    p->nLitsEnd  = Ssw_ClassesLitNum( p->ppClasses );
+    p->nNodesEnd = Aig_ManNodeNum(pAigNew);
+    p->nRegsEnd  = Aig_ManRegNum(pAigNew);
+    // cleanup
+    Aig_ManSetPhase( p->pAig );
+    Aig_ManCleanMarkB( p->pAig );
+    return pAigNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs computation of signal correspondence with constraints.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars )
+{
+    Ssw_Pars_t Pars;
+    Aig_Man_t * pAigNew;
+    Ssw_Man_t * p;
+    assert( Aig_ManRegNum(pAig) > 0 );
+    // reset random numbers
+    Aig_ManRandom( 1 );
+    // if parameters are not given, create them
+    if ( pPars == NULL )
+        Ssw_ManSetDefaultParams( pPars = &Pars );
+    // consider the case of empty AIG
+    if ( Aig_ManNodeNum(pAig) == 0 )
+    {
+        pPars->nIters = 0;
+        // Ntl_ManFinalize() needs the following to satisfy an assertion
+        Aig_ManReprStart( pAig,Aig_ManObjNumMax(pAig) );
+        return Aig_ManDupOrdered(pAig);
+    }
+    // check and update parameters
+    if ( pPars->fLatchCorrOpt )
+    {
+        pPars->fLatchCorr = 1;
+        pPars->nFramesAddSim = 0;
+        if ( (pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0) )
+           return Ssw_SignalCorrespondencePart( pAig, pPars );
+    }
+    else
+    {
+        assert( pPars->nFramesK > 0 );
+        // perform partitioning
+        if ( (pPars->nPartSize > 0 && pPars->nPartSize < Aig_ManRegNum(pAig))
+             || (pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0)  )
+            return Ssw_SignalCorrespondencePart( pAig, pPars );
+    }
+
+    if ( pPars->fScorrGia )
+    {
+        if ( pPars->fLatchCorrOpt )
+        {
+            extern Aig_Man_t * Cec_LatchCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat );
+            return Cec_LatchCorrespondence( pAig, pPars->nBTLimit, pPars->fUseCSat );
+        }
+        else
+        {
+            extern Aig_Man_t * Cec_SignalCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat );
+            return Cec_SignalCorrespondence( pAig, pPars->nBTLimit, pPars->fUseCSat );
+        }
+    }
+
+    // start the induction manager
+    p = Ssw_ManCreate( pAig, pPars );
+    // compute candidate equivalence classes
+//    p->pPars->nConstrs = 1;
+    if ( p->pPars->fConstrs )
+    {
+        // create trivial equivalence classes with all nodes being candidates for constant 1
+        p->ppClasses = Ssw_ClassesPrepareSimple( pAig, pPars->fLatchCorr, pPars->nMaxLevs );
+        Ssw_ClassesSetData( p->ppClasses, NULL, NULL, Ssw_SmlObjIsConstBit, Ssw_SmlObjsAreEqualBit );
+        // derive phase bits to satisfy the constraints
+        if ( Ssw_ManSetConstrPhases( pAig, p->pPars->nFramesK + 1, &p->vInits ) != 0 )
+        {
+            Abc_Print( 1, "Ssw_SignalCorrespondence(): The init state does not satisfy the constraints!\n" );
+            p->pPars->fVerbose = 0;
+            Ssw_ManStop( p );
+            return NULL;
+        }
+        // perform simulation of the first timeframes
+        Ssw_ManRefineByConstrSim( p );
+    }
+    else
+    {
+        // perform one round of seq simulation and generate candidate equivalence classes
+        p->ppClasses = Ssw_ClassesPrepare( pAig, pPars->nFramesK, pPars->fLatchCorr, pPars->fConstCorr, pPars->fOutputCorr, pPars->nMaxLevs, pPars->fVerbose );
+//        p->ppClasses = Ssw_ClassesPrepareTargets( pAig );
+        if ( pPars->fLatchCorrOpt )
+            p->pSml = Ssw_SmlStart( pAig, 0, 2, 1 );
+        else if ( pPars->fDynamic )
+            p->pSml = Ssw_SmlStart( pAig, 0, p->nFrames + p->pPars->nFramesAddSim, 1 );
+        else
+            p->pSml = Ssw_SmlStart( pAig, 0, 1 + p->pPars->nFramesAddSim, 1 );
+        Ssw_ClassesSetData( p->ppClasses, p->pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord );
+    }
+    // allocate storage
+    if ( p->pPars->fLocalSim )
+        p->pVisited = ABC_CALLOC( int, Ssw_SmlNumFrames( p->pSml ) * Aig_ManObjNumMax(p->pAig) );
+    // perform refinement of classes
+    pAigNew = Ssw_SignalCorrespondenceRefine( p );
+//    Ssw_ReportOutputs( pAigNew );
+    if ( pPars->fConstrs && pPars->fVerbose )
+        Ssw_ReportConeReductions( p, pAig, pAigNew );
+    // cleanup
+    Ssw_ManStop( p );
+    return pAigNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs computation of latch correspondence.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Ssw_LatchCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars )
+{
+    Aig_Man_t * pRes;
+    Ssw_Pars_t Pars;
+    if ( pPars == NULL )
+        Ssw_ManSetDefaultParamsLcorr( pPars = &Pars );
+    pRes = Ssw_SignalCorrespondence( pAig, pPars );
+//    if ( pPars->fConstrs && pPars->fVerbose )
+//        Ssw_ReportConeReductions( pAig, pRes );
+    return pRes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswDyn.c b/abc-build/src/proof/ssw/sswDyn.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswDyn.c
@@ -0,0 +1,491 @@
+/**CFile****************************************************************
+
+  FileName    [sswDyn.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [Dynamic loading of constraints.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswDyn.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+#include "misc/bar/bar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Label PIs nodes of the frames corresponding to PIs of AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManLabelPiNodes( Ssw_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pObjFrames;
+    int f, i;
+    Aig_ManConst1( p->pFrames )->fMarkA = 1;
+    Aig_ManConst1( p->pFrames )->fMarkB = 1;
+    for ( f = 0; f < p->nFrames; f++ )
+    {
+        Saig_ManForEachPi( p->pAig, pObj, i )
+        {
+            pObjFrames = Ssw_ObjFrame( p, pObj, f );
+            assert( Aig_ObjIsCi(pObjFrames) );
+            assert( pObjFrames->fMarkB == 0 );
+            pObjFrames->fMarkA = 1;
+            pObjFrames->fMarkB = 1;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects new POs in p->vNewPos.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManCollectPis_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vNewPis )
+{
+    assert( !Aig_IsComplement(pObj) );
+    if ( pObj->fMarkA )
+        return;
+    pObj->fMarkA = 1;
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        Vec_PtrPush( vNewPis, pObj );
+        return;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    Ssw_ManCollectPis_rec( Aig_ObjFanin0(pObj), vNewPis );
+    Ssw_ManCollectPis_rec( Aig_ObjFanin1(pObj), vNewPis );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects new POs in p->vNewPos.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManCollectPos_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vNewPos )
+{
+    Aig_Obj_t * pFanout;
+    int iFanout = -1, i;
+    assert( !Aig_IsComplement(pObj) );
+    if ( pObj->fMarkB )
+        return;
+    pObj->fMarkB = 1;
+    if ( pObj->Id > p->nSRMiterMaxId )
+        return;
+    if ( Aig_ObjIsCo(pObj) )
+    {
+        // skip if it is a register input PO
+        if ( Aig_ObjCioId(pObj) >= Aig_ManCoNum(p->pFrames)-Aig_ManRegNum(p->pAig) )
+            return;
+        // add the number of this constraint
+        Vec_IntPush( vNewPos, Aig_ObjCioId(pObj)/2 );
+        return;
+    }
+    // visit the fanouts
+    assert( p->pFrames->pFanData != NULL );
+    Aig_ObjForEachFanout( p->pFrames, pObj, pFanout, iFanout, i )
+        Ssw_ManCollectPos_rec( p, pFanout, vNewPos );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Loads logic cones and relevant constraints.]
+
+  Description [Both pRepr and pObj are objects of the AIG.
+  The result is the current SAT solver loaded with the logic cones
+  for pRepr and pObj corresponding to them in the frames,
+  as well as all the relevant constraints.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManLoadSolver( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pObjFrames, * pReprFrames;
+    Aig_Obj_t * pTemp, * pObj0, * pObj1;
+    int i, iConstr, RetValue;
+
+    assert( pRepr != pObj );
+    // get the corresponding frames nodes
+    pReprFrames = Aig_Regular( Ssw_ObjFrame( p, pRepr, p->pPars->nFramesK ) );
+    pObjFrames  = Aig_Regular( Ssw_ObjFrame( p, pObj,  p->pPars->nFramesK ) );
+    assert( pReprFrames != pObjFrames );
+ /*
+    // compute the AIG support
+    Vec_PtrClear( p->vNewLos );
+    Ssw_ManCollectPis_rec( pRepr, p->vNewLos );
+    Ssw_ManCollectPis_rec( pObj,  p->vNewLos );
+    // add logic cones for register outputs
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vNewLos, pTemp, i )
+    {
+        pObj0 = Aig_Regular( Ssw_ObjFrame( p, pTemp, p->pPars->nFramesK ) );
+        Ssw_CnfNodeAddToSolver( p->pMSat, pObj0 );
+    }
+*/
+    // add cones for the nodes
+    Ssw_CnfNodeAddToSolver( p->pMSat, pReprFrames );
+    Ssw_CnfNodeAddToSolver( p->pMSat, pObjFrames );
+
+    // compute the frames support
+    Vec_PtrClear( p->vNewLos );
+    Ssw_ManCollectPis_rec( pReprFrames, p->vNewLos );
+    Ssw_ManCollectPis_rec( pObjFrames,  p->vNewLos );
+    // these nodes include both nodes corresponding to PIs and LOs
+    // (the nodes corresponding to PIs should be labeled with fMarkB!)
+
+    // collect the related constraint POs
+    Vec_IntClear( p->vNewPos );
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vNewLos, pTemp, i )
+        Ssw_ManCollectPos_rec( p, pTemp, p->vNewPos );
+    // check if the corresponding pairs are added
+    Vec_IntForEachEntry( p->vNewPos, iConstr, i )
+    {
+        pObj0 = Aig_ManCo( p->pFrames, 2*iConstr   );
+        pObj1 = Aig_ManCo( p->pFrames, 2*iConstr+1 );
+//        if ( pObj0->fMarkB && pObj1->fMarkB )
+        if ( pObj0->fMarkB || pObj1->fMarkB )
+        {
+            pObj0->fMarkB = 1;
+            pObj1->fMarkB = 1;
+            Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj0), Aig_ObjChild0(pObj1) );
+        }
+    }
+    if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead )
+    {
+        RetValue = sat_solver_simplify(p->pMSat->pSat);
+        assert( RetValue != 0 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tranfers simulation information from FRAIG to AIG.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManSweepTransferDyn( Ssw_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pObjFraig;
+    unsigned * pInfo;
+    int i, f, nFrames;
+
+    // transfer simulation information
+    Aig_ManForEachCi( p->pAig, pObj, i )
+    {
+        pObjFraig = Ssw_ObjFrame( p, pObj, 0 );
+        if ( pObjFraig == Aig_ManConst0(p->pFrames) )
+        {
+            Ssw_SmlObjAssignConst( p->pSml, pObj, 0, 0 );
+            continue;
+        }
+        assert( !Aig_IsComplement(pObjFraig) );
+        assert( Aig_ObjIsCi(pObjFraig) );
+        pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjCioId(pObjFraig) );
+        Ssw_SmlObjSetWord( p->pSml, pObj, pInfo[0], 0, 0 );
+    }
+    // set random simulation info for the second frame
+    for ( f = 1; f < p->nFrames; f++ )
+    {
+        Saig_ManForEachPi( p->pAig, pObj, i )
+        {
+            pObjFraig = Ssw_ObjFrame( p, pObj, f );
+            assert( !Aig_IsComplement(pObjFraig) );
+            assert( Aig_ObjIsCi(pObjFraig) );
+            pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjCioId(pObjFraig) );
+            Ssw_SmlObjSetWord( p->pSml, pObj, pInfo[0], 0, f );
+        }
+    }
+    // create random info
+    nFrames = Ssw_SmlNumFrames( p->pSml );
+    for ( ; f < nFrames; f++ )
+    {
+        Saig_ManForEachPi( p->pAig, pObj, i )
+            Ssw_SmlAssignRandomFrame( p->pSml, pObj, f );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one round of simulation with counter-examples.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManSweepResimulateDyn( Ssw_Man_t * p, int f )
+{
+    int RetValue1, RetValue2;
+    abctime clk = Abc_Clock();
+    // transfer PI simulation information from storage
+//    Ssw_SmlAssignDist1Plus( p->pSml, p->pPatWords );
+    Ssw_ManSweepTransferDyn( p );
+    // simulate internal nodes
+//    Ssw_SmlSimulateOneFrame( p->pSml );
+    Ssw_SmlSimulateOne( p->pSml );
+    // check equivalence classes
+    RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 );
+    RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 );
+    // prepare simulation info for the next round
+    Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 );
+    p->nPatterns = 0;
+    p->nSimRounds++;
+p->timeSimSat += Abc_Clock() - clk;
+    return RetValue1 > 0 || RetValue2 > 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one round of simulation with counter-examples.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManSweepResimulateDynLocal( Ssw_Man_t * p, int f )
+{
+    Aig_Obj_t * pObj, * pRepr, ** ppClass;
+    int i, k, nSize, RetValue1, RetValue2;
+    abctime clk = Abc_Clock();
+    p->nSimRounds++;
+    // transfer PI simulation information from storage
+//    Ssw_SmlAssignDist1Plus( p->pSml, p->pPatWords );
+    Ssw_ManSweepTransferDyn( p );
+    // determine const1 cands and classes to be simulated
+    Vec_PtrClear( p->vResimConsts );
+    Vec_PtrClear( p->vResimClasses );
+    Aig_ManIncrementTravId( p->pAig );
+    for ( i = p->iNodeStart; i < p->iNodeLast + p->pPars->nResimDelta; i++ )
+    {
+        if ( i >= Aig_ManObjNumMax( p->pAig ) )
+            break;
+        pObj = Aig_ManObj( p->pAig, i );
+        if ( pObj == NULL )
+            continue;
+        if ( Ssw_ObjIsConst1Cand(p->pAig, pObj) )
+        {
+            Vec_PtrPush( p->vResimConsts, pObj );
+            continue;
+        }
+        pRepr = Aig_ObjRepr(p->pAig, pObj);
+        if ( pRepr == NULL )
+            continue;
+        if ( Aig_ObjIsTravIdCurrent(p->pAig, pRepr) )
+            continue;
+        Aig_ObjSetTravIdCurrent(p->pAig, pRepr);
+        Vec_PtrPush( p->vResimClasses, pRepr );
+    }
+    // simulate internal nodes
+//    Ssw_SmlSimulateOneFrame( p->pSml );
+//    Ssw_SmlSimulateOne( p->pSml );
+    // resimulate dynamically
+//    Aig_ManIncrementTravId( p->pAig );
+//    Aig_ObjIsTravIdCurrent( p->pAig, Aig_ManConst1(p->pAig) );
+    p->nVisCounter++;
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vResimConsts, pObj, i )
+        Ssw_SmlSimulateOneDyn_rec( p->pSml, pObj, p->nFrames-1, p->pVisited, p->nVisCounter );
+    // resimulate the cone of influence of the cand classes
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vResimClasses, pRepr, i )
+    {
+        ppClass = Ssw_ClassesReadClass( p->ppClasses, pRepr, &nSize );
+        for ( k = 0; k < nSize; k++ )
+            Ssw_SmlSimulateOneDyn_rec( p->pSml, ppClass[k], p->nFrames-1, p->pVisited, p->nVisCounter );
+    }
+
+    // check equivalence classes
+//    RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 );
+//    RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 );
+    // refine these nodes
+    RetValue1 = Ssw_ClassesRefineConst1Group( p->ppClasses, p->vResimConsts, 1 );
+    RetValue2 = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vResimClasses, pRepr, i )
+        RetValue2 += Ssw_ClassesRefineOneClass( p->ppClasses, pRepr, 1 );
+
+    // prepare simulation info for the next round
+    Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 );
+    p->nPatterns = 0;
+    p->nSimRounds++;
+p->timeSimSat += Abc_Clock() - clk;
+    return RetValue1 > 0 || RetValue2 > 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for the internal nodes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManSweepDyn( Ssw_Man_t * p )
+{
+    Bar_Progress_t * pProgress = NULL;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i, f;
+    abctime clk;
+
+    // perform speculative reduction
+clk = Abc_Clock();
+    // create timeframes
+    p->pFrames = Ssw_FramesWithClasses( p );
+    Aig_ManFanoutStart( p->pFrames );
+    p->nSRMiterMaxId = Aig_ManObjNumMax( p->pFrames );
+
+    // map constants and PIs of the last frame
+    f = p->pPars->nFramesK;
+    Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
+    Saig_ManForEachPi( p->pAig, pObj, i )
+        Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreateCi(p->pFrames) );
+    Aig_ManSetCioIds( p->pFrames );
+    // label nodes corresponding to primary inputs
+    Ssw_ManLabelPiNodes( p );
+p->timeReduce += Abc_Clock() - clk;
+
+    // prepare simulation info
+    assert( p->vSimInfo == NULL );
+    p->vSimInfo = Vec_PtrAllocSimInfo( Aig_ManCiNum(p->pFrames), 1 );
+    Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 );
+
+    // sweep internal nodes
+    p->fRefined = 0;
+    Ssw_ClassesClearRefined( p->ppClasses );
+    if ( p->pPars->fVerbose )
+        pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) );
+    p->iNodeStart = 0;
+    Aig_ManForEachObj( p->pAig, pObj, i )
+    {
+        if ( p->iNodeStart == 0 )
+            p->iNodeStart = i;
+        if ( p->pPars->fVerbose )
+            Bar_ProgressUpdate( pProgress, i, NULL );
+        if ( Saig_ObjIsLo(p->pAig, pObj) )
+            p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, NULL );
+        else if ( Aig_ObjIsNode(pObj) )
+        {
+            pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+            Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+            p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, NULL );
+        }
+        // check if it is time to recycle the solver
+        if ( p->pMSat->pSat == NULL ||
+            (p->pPars->nSatVarMax2 &&
+             p->pMSat->nSatVars > p->pPars->nSatVarMax2 &&
+             p->nRecycleCalls > p->pPars->nRecycleCalls2) )
+        {
+            // resimulate
+            if ( p->nPatterns > 0 )
+            {
+                p->iNodeLast = i;
+                if ( p->pPars->fLocalSim )
+                    Ssw_ManSweepResimulateDynLocal( p, f );
+                else
+                    Ssw_ManSweepResimulateDyn( p, f );
+                p->iNodeStart = i+1;
+            }
+//                Abc_Print( 1, "Recycling SAT solver with %d vars and %d calls.\n", 
+//                    p->pMSat->nSatVars, p->nRecycleCalls );
+//            Aig_ManCleanMarkAB( p->pAig );
+            Aig_ManCleanMarkAB( p->pFrames );
+            // label nodes corresponding to primary inputs
+            Ssw_ManLabelPiNodes( p );
+            // replace the solver
+            if ( p->pMSat )
+            {
+                p->nVarsMax  = Abc_MaxInt( p->nVarsMax,  p->pMSat->nSatVars );
+                p->nCallsMax = Abc_MaxInt( p->nCallsMax, p->pMSat->nSolverCalls );
+                Ssw_SatStop( p->pMSat );
+                p->nRecycles++;
+                p->nRecyclesTotal++;
+                p->nRecycleCalls = 0;
+            }
+            p->pMSat = Ssw_SatStart( 0 );
+            assert( p->nPatterns == 0 );
+        }
+        // resimulate
+        if ( p->nPatterns == 32 )
+        {
+            p->iNodeLast = i;
+            if ( p->pPars->fLocalSim )
+                Ssw_ManSweepResimulateDynLocal( p, f );
+            else
+                Ssw_ManSweepResimulateDyn( p, f );
+            p->iNodeStart = i+1;
+        }
+    }
+    // resimulate
+    if ( p->nPatterns > 0 )
+    {
+        p->iNodeLast = i;
+        if ( p->pPars->fLocalSim )
+            Ssw_ManSweepResimulateDynLocal( p, f );
+        else
+            Ssw_ManSweepResimulateDyn( p, f );
+    }
+    // collect stats
+    if ( p->pPars->fVerbose )
+        Bar_ProgressStop( pProgress );
+
+    // cleanup
+//    Ssw_ClassesCheck( p->ppClasses );
+    return p->fRefined;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswFilter.c b/abc-build/src/proof/ssw/sswFilter.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswFilter.c
@@ -0,0 +1,493 @@
+/**CFile****************************************************************
+
+  FileName    [sswConstr.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [One round of SAT sweeping.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswConstr.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for one node.]
+
+  Description [Returns the fraiged node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManRefineByFilterSim( Ssw_Man_t * p, int nFrames )
+{
+    Aig_Obj_t * pObj, * pObjLi;
+    int f, i, RetValue1, RetValue2;
+    assert( nFrames > 0 );
+    // assign register outputs
+    Saig_ManForEachLi( p->pAig, pObj, i )
+        pObj->fMarkB = Abc_InfoHasBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i );
+    // simulate the timeframes
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // set the PI simulation information
+        Aig_ManConst1(p->pAig)->fMarkB = 1;
+        Saig_ManForEachPi( p->pAig, pObj, i )
+            pObj->fMarkB = 0;
+        Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i )
+            pObj->fMarkB = pObjLi->fMarkB;
+        // simulate internal nodes
+        Aig_ManForEachNode( p->pAig, pObj, i )
+            pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+                         & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+        // assign the COs
+        Aig_ManForEachCo( p->pAig, pObj, i )
+            pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) );
+        // transfer
+        if ( f == 0 )
+        { // copy markB into phase
+            Aig_ManForEachObj( p->pAig, pObj, i )
+                pObj->fPhase = pObj->fMarkB;
+        }
+        else
+        { // refine classes
+            RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 0 );
+            RetValue2 = Ssw_ClassesRefine( p->ppClasses, 0 );
+        }
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for one node.]
+
+  Description [Returns the fraiged node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManRollForward( Ssw_Man_t * p, int nFrames )
+{
+    Aig_Obj_t * pObj, * pObjLi;
+    int f, i;
+    assert( nFrames > 0 );
+    // assign register outputs
+    Saig_ManForEachLi( p->pAig, pObj, i )
+        pObj->fMarkB = Abc_InfoHasBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i );
+    // simulate the timeframes
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // set the PI simulation information
+        Aig_ManConst1(p->pAig)->fMarkB = 1;
+        Saig_ManForEachPi( p->pAig, pObj, i )
+            pObj->fMarkB = Aig_ManRandom(0) & 1;
+        Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i )
+            pObj->fMarkB = pObjLi->fMarkB;
+        // simulate internal nodes
+        Aig_ManForEachNode( p->pAig, pObj, i )
+            pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+                         & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+        // assign the COs
+        Aig_ManForEachCo( p->pAig, pObj, i )
+            pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) );
+    }
+    // record the new pattern
+    Saig_ManForEachLi( p->pAig, pObj, i )
+        if ( pObj->fMarkB ^ Abc_InfoHasBit(p->pPatWords, Saig_ManPiNum(p->pAig) + i) )
+            Abc_InfoXorBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for one node.]
+
+  Description [Returns the fraiged node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManFindStartingState( Ssw_Man_t * p, Abc_Cex_t * pCex )
+{
+    Aig_Obj_t * pObj, * pObjLi;
+    int f, i, iBit;
+    // assign register outputs
+    Saig_ManForEachLi( p->pAig, pObj, i )
+        pObj->fMarkB = 0;
+    // simulate the timeframes
+    iBit = pCex->nRegs;
+    for ( f = 0; f <= pCex->iFrame; f++ )
+    {
+        // set the PI simulation information
+        Aig_ManConst1(p->pAig)->fMarkB = 1;
+        Saig_ManForEachPi( p->pAig, pObj, i )
+            pObj->fMarkB = Abc_InfoHasBit( pCex->pData, iBit++ );
+        Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i )
+            pObj->fMarkB = pObjLi->fMarkB;
+        // simulate internal nodes
+        Aig_ManForEachNode( p->pAig, pObj, i )
+            pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+                         & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+        // assign the COs
+        Aig_ManForEachCo( p->pAig, pObj, i )
+            pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) );
+    }
+    assert( iBit == pCex->nBits );
+    // check that the output failed as expected -- cannot check because it is not an SRM!
+//    pObj = Aig_ManCo( p->pAig, pCex->iPo );
+//    if ( pObj->fMarkB != 1 )
+//        Abc_Print( 1, "The counter-example does not refine the output.\n" );
+    // record the new pattern
+    Saig_ManForEachLo( p->pAig, pObj, i )
+        if ( pObj->fMarkB ^ Abc_InfoHasBit(p->pPatWords, Saig_ManPiNum(p->pAig) + i) )
+            Abc_InfoXorBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for one node.]
+
+  Description [Returns the fraiged node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManSweepNodeFilter( Ssw_Man_t * p, Aig_Obj_t * pObj, int f )
+{
+    Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig;
+    int RetValue;
+    // get representative of this class
+    pObjRepr = Aig_ObjRepr( p->pAig, pObj );
+    if ( pObjRepr == NULL )
+        return 0;
+    // get the fraiged node
+    pObjFraig = Ssw_ObjFrame( p, pObj, f );
+    // get the fraiged representative
+    pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, f );
+    // check if constant 0 pattern distinquishes these nodes
+    assert( pObjFraig != NULL && pObjReprFraig != NULL );
+    assert( (pObj->fPhase == pObjRepr->fPhase) == (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) );
+    // if the fraiged nodes are the same, return
+    if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) )
+        return 0;
+    // call equivalence checking
+    if ( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pFrames) )
+        RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) );
+    else
+        RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) );
+    if ( RetValue == 1 )  // proved equivalent
+    {
+        pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase );
+        Ssw_ObjSetFrame( p, pObj, f, pObjFraig2 );
+        return 0;
+    }
+    if ( RetValue == -1 ) // timed out
+    {
+//        Ssw_ClassesRemoveNode( p->ppClasses, pObj );
+        return 1;
+    }
+    // disproved equivalence
+    Ssw_SmlSavePatternAig( p, f );
+    Ssw_ManResimulateBit( p, pObj, pObjRepr );
+    assert( Aig_ObjRepr( p->pAig, pObj ) != pObjRepr );
+    if ( Aig_ObjRepr( p->pAig, pObj ) == pObjRepr )
+    {
+        Abc_Print( 1, "Ssw_ManSweepNodeFilter(): Failed to refine representative.\n" );
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Ssw_ManSweepBmcFilter_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, int f )
+{
+    Aig_Obj_t * pObjNew, * pObjLi;
+    pObjNew = Ssw_ObjFrame( p, pObj, f );
+    if ( pObjNew )
+        return pObjNew;
+    assert( !Saig_ObjIsPi(p->pAig, pObj) );
+    if ( Saig_ObjIsLo(p->pAig, pObj) )
+    {
+        assert( f > 0 );
+        pObjLi  = Saig_ObjLoToLi( p->pAig, pObj );
+        pObjNew = Ssw_ManSweepBmcFilter_rec( p, Aig_ObjFanin0(pObjLi), f-1 );
+        pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObjLi) );
+    }
+    else
+    {
+        assert( Aig_ObjIsNode(pObj) );
+        Ssw_ManSweepBmcFilter_rec( p, Aig_ObjFanin0(pObj), f );
+        Ssw_ManSweepBmcFilter_rec( p, Aig_ObjFanin1(pObj), f );
+        pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+    }
+    Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+    assert( pObjNew != NULL );
+    return pObjNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Filter equivalence classes of nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManSweepBmcFilter( Ssw_Man_t * p, int TimeLimit )
+{
+    Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo;
+    int f, f1, i;
+    abctime clkTotal = Abc_Clock();
+    // start initialized timeframes
+    p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK );
+    Saig_ManForEachLo( p->pAig, pObj, i )
+    {
+        if ( Abc_InfoHasBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i ) )
+        {
+            Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst1(p->pFrames) );
+//Abc_Print( 1, "1" );
+        }
+        else
+        {
+            Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) );
+//Abc_Print( 1, "0" );
+        }
+    }
+//Abc_Print( 1, "\n" );
+
+    // sweep internal nodes
+    for ( f = 0; f < p->pPars->nFramesK; f++ )
+    {
+        // realloc mapping of timeframes
+        if ( f == p->nFrames-1 )
+        {
+            Aig_Obj_t ** pNodeToFrames;
+            pNodeToFrames = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) * 2 * p->nFrames );
+            for ( f1 = 0; f1 < p->nFrames; f1++ )
+            {
+                Aig_ManForEachObj( p->pAig, pObj, i )
+                    pNodeToFrames[2*p->nFrames*pObj->Id + f1] = Ssw_ObjFrame( p, pObj, f1 );
+            }
+            ABC_FREE( p->pNodeToFrames );
+            p->pNodeToFrames = pNodeToFrames;
+            p->nFrames *= 2;
+        }
+        // map constants and PIs
+        Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
+        Saig_ManForEachPi( p->pAig, pObj, i )
+        {
+            pObjNew = Aig_ObjCreateCi(p->pFrames);
+            Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+        }
+        // sweep internal nodes
+        Aig_ManForEachNode( p->pAig, pObj, i )
+        {
+            pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+            Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+            if ( Ssw_ManSweepNodeFilter( p, pObj, f ) )
+                break;
+        }
+        // printout
+        if ( p->pPars->fVerbose )
+        {
+            Abc_Print( 1, "Frame %4d : ", f );
+            Ssw_ClassesPrint( p->ppClasses, 0 );
+        }
+        if ( i < Vec_PtrSize(p->pAig->vObjs) )
+        {
+            if ( p->pPars->fVerbose )
+                Abc_Print( 1, "Exceeded the resource limits (%d conflicts). Quitting...\n", p->pPars->nBTLimit );
+            break;
+        }
+        // quit if this is the last timeframe
+        if ( f == p->pPars->nFramesK - 1 )
+        {
+            if ( p->pPars->fVerbose )
+                Abc_Print( 1, "Exceeded the time frame limit (%d time frames). Quitting...\n", p->pPars->nFramesK );
+            break;
+        }
+        // check timeout
+        if ( TimeLimit && ((float)TimeLimit <= (float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC)) )
+            break;
+        // transfer latch input to the latch outputs 
+        Aig_ManForEachCo( p->pAig, pObj, i )
+            Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) );
+        // build logic cones for register outputs
+        Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+        {
+            pObjNew = Ssw_ObjFrame( p, pObjLi, f );
+            Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew );
+            Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );//
+        }
+    }
+    // verify
+//    Ssw_ClassesCheck( p->ppClasses );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Filter equivalence classes of nodes.]
+
+  Description [Unrolls at most nFramesMax frames. Works with nConfMax
+  conflicts until the first undefined SAT call. Verbose prints the message.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SignalFilter( Aig_Man_t * pAig, int nFramesMax, int nConfMax, int nRounds, int TimeLimit, int TimeLimit2, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose )
+{
+    Ssw_Pars_t Pars, * pPars = &Pars;
+    Ssw_Man_t * p;
+    int r, TimeLimitPart;//, clkTotal = Abc_Clock();
+    abctime nTimeToStop = TimeLimit ? TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0;
+    assert( Aig_ManRegNum(pAig) > 0 );
+    assert( Aig_ManConstrNum(pAig) == 0 );
+    // consider the case of empty AIG
+    if ( Aig_ManNodeNum(pAig) == 0 )
+        return;
+    // reset random numbers
+    Aig_ManRandom( 1 );
+    // if parameters are not given, create them
+    Ssw_ManSetDefaultParams( pPars = &Pars );
+    pPars->nFramesK  = 3; //nFramesMax;
+    pPars->nBTLimit  = nConfMax;
+    pPars->TimeLimit = TimeLimit;
+    pPars->fVerbose  = fVerbose;
+    // start the induction manager
+    p = Ssw_ManCreate( pAig, pPars );
+    pPars->nFramesK  = nFramesMax;
+    // create trivial equivalence classes with all nodes being candidates for constant 1
+    if ( pAig->pReprs == NULL )
+        p->ppClasses = Ssw_ClassesPrepareSimple( pAig, fLatchOnly, 0 );
+    else
+        p->ppClasses = Ssw_ClassesPrepareFromReprs( pAig );
+    Ssw_ClassesSetData( p->ppClasses, NULL, NULL, Ssw_SmlObjIsConstBit, Ssw_SmlObjsAreEqualBit );
+    assert( p->vInits == NULL );
+    // compute starting state if needed
+    if ( pCex )
+        Ssw_ManFindStartingState( p, pCex );
+    // refine classes using BMC
+    for ( r = 0; r < nRounds; r++ )
+    {
+        if ( p->pPars->fVerbose )
+            Abc_Print( 1, "Round %3d:\n", r );
+        // start filtering equivalence classes
+        Ssw_ManRefineByFilterSim( p, p->pPars->nFramesK );
+        if ( Ssw_ClassesCand1Num(p->ppClasses) == 0 && Ssw_ClassesClassNum(p->ppClasses) == 0 )
+        {
+            Abc_Print( 1, "All equivalences are refined away.\n" );
+            break;
+        }
+        // printout
+        if ( p->pPars->fVerbose )
+        {
+            Abc_Print( 1, "Initial    : " );
+            Ssw_ClassesPrint( p->ppClasses, 0 );
+        }
+        p->pMSat = Ssw_SatStart( 0 );
+        TimeLimitPart = TimeLimit ? (nTimeToStop - Abc_Clock()) / CLOCKS_PER_SEC : 0;
+        if ( TimeLimit2 )
+        {
+            if ( TimeLimitPart )
+                TimeLimitPart = Abc_MinInt( TimeLimitPart, TimeLimit2 );
+            else
+                TimeLimitPart = TimeLimit2;
+        }
+        Ssw_ManSweepBmcFilter( p, TimeLimitPart );
+        Ssw_SatStop( p->pMSat );
+        p->pMSat = NULL;
+        Ssw_ManCleanup( p );
+        // simulate pattern forward
+        Ssw_ManRollForward( p, p->pPars->nFramesK );
+        // check timeout
+        if ( TimeLimit && Abc_Clock() > nTimeToStop )
+        {
+            Abc_Print( 1, "Reached timeout (%d seconds).\n",  TimeLimit );
+            break;
+        }
+    }
+    // cleanup
+    Aig_ManSetPhase( p->pAig );
+    Aig_ManCleanMarkB( p->pAig );
+    // cleanup
+    pPars->fVerbose = 0;
+    Ssw_ManStop( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Filter equivalence classes of nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SignalFilterGia( Gia_Man_t * p, int nFramesMax, int nConfMax, int nRounds, int TimeLimit, int TimeLimit2, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose )
+{
+    Aig_Man_t * pAig;
+    pAig = Gia_ManToAigSimple( p );
+    if ( p->pReprs != NULL )
+    {
+        Gia_ManReprToAigRepr2( pAig, p );
+        ABC_FREE( p->pReprs );
+        ABC_FREE( p->pNexts );
+    }
+    Ssw_SignalFilter( pAig, nFramesMax, nConfMax, nRounds, TimeLimit, TimeLimit2, pCex, fLatchOnly, fVerbose );
+    Gia_ManReprFromAigRepr( pAig, p );
+    Aig_ManStop( pAig );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswInt.h b/abc-build/src/proof/ssw/sswInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswInt.h
@@ -0,0 +1,302 @@
+/**CFile****************************************************************
+
+  FileName    [sswInt.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswInt.h,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__ssw__sswInt_h
+#define ABC__aig__ssw__sswInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "aig/saig/saig.h"
+#include "sat/bsat/satSolver.h"
+#include "ssw.h"
+#include "aig/ioa/ioa.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ssw_Man_t_ Ssw_Man_t; // signal correspondence manager
+typedef struct Ssw_Frm_t_ Ssw_Frm_t; // unrolled frames manager
+typedef struct Ssw_Sat_t_ Ssw_Sat_t; // SAT solver manager
+typedef struct Ssw_Cla_t_ Ssw_Cla_t; // equivalence classe manager
+
+struct Ssw_Man_t_
+{
+    // parameters
+    Ssw_Pars_t *     pPars;          // parameters
+    int              nFrames;        // for quick lookup
+    // AIGs used in the package
+    Aig_Man_t *      pAig;           // user-given AIG
+    Aig_Man_t *      pFrames;        // final AIG
+    Aig_Obj_t **     pNodeToFrames;  // mapping of AIG nodes into FRAIG nodes
+    // equivalence classes
+    Ssw_Cla_t *      ppClasses;      // equivalence classes of nodes
+    int              fRefined;       // is set to 1 when refinement happens
+    // SAT solving 
+    Ssw_Sat_t *      pMSatBmc;       // SAT manager for base case
+    Ssw_Sat_t *      pMSat;          // SAT manager for inductive case
+    // SAT solving (latch corr only)
+    Vec_Ptr_t *      vSimInfo;       // simulation information for the framed PIs
+    int              nPatterns;      // the number of patterns saved
+    int              nSimRounds;     // the number of simulation rounds performed
+    int              nCallsCount;    // the number of calls in this round
+    int              nCallsDelta;    // the number of calls to skip
+    int              nCallsSat;      // the number of SAT calls in this round
+    int              nCallsUnsat;    // the number of UNSAT calls in this round
+    int              nRecycleCalls;  // the number of calls since last recycling
+    int              nRecycles;      // the number of time SAT solver was recycled
+    int              nRecyclesTotal; // the number of time SAT solver was recycled
+    int              nVarsMax;       // the maximum variables in the solver
+    int              nCallsMax;      // the maximum number of SAT calls
+    // uniqueness
+    Vec_Ptr_t *      vCommon;        // the set of common variables in the logic cones
+    int              iOutputLit;     // the output literal of the uniqueness constraint
+    Vec_Int_t *      vDiffPairs;     // is set to 1 if reg pair can be diff
+    int              nUniques;       // the number of uniqueness constraints used 
+    int              nUniquesAdded;  // useful uniqueness constraints
+    int              nUniquesUseful; // useful uniqueness constraints
+    // dynamic constraint addition
+    int              nSRMiterMaxId;  // max ID after which the last frame begins
+    Vec_Ptr_t *      vNewLos;        // new time frame LOs of to constrain
+    Vec_Int_t *      vNewPos;        // new time frame POs of to add constraints
+    int *            pVisited;       // flags to label visited nodes in each frame
+    int              nVisCounter;    // the traversal ID
+    // sequential simulation
+    Ssw_Sml_t *      pSml;           // the simulator
+    int              iNodeStart;     // the first node considered
+    int              iNodeLast;      // the last node considered
+    Vec_Ptr_t *      vResimConsts;   // resimulation constants
+    Vec_Ptr_t *      vResimClasses;  // resimulation classes
+    Vec_Int_t *      vInits;         // the init values of primary inputs under constraints
+    // counter example storage
+    int              nPatWords;      // the number of words in the counter example
+    unsigned *       pPatWords;      // the counter example
+    // constraints
+    int              nConstrTotal;   // the number of total constraints
+    int              nConstrReduced; // the number of reduced constraints
+    int              nStrangers;     // the number of strange situations
+    // SAT calls statistics
+    int              nSatCalls;      // the number of SAT calls
+    int              nSatProof;      // the number of proofs
+    int              nSatFailsReal;  // the number of timeouts
+    int              nSatCallsUnsat; // the number of unsat SAT calls
+    int              nSatCallsSat;   // the number of sat SAT calls
+    // node/register/lit statistics
+    int              nLitsBeg;
+    int              nLitsEnd;
+    int              nNodesBeg;
+    int              nNodesEnd;
+    int              nRegsBeg;
+    int              nRegsEnd;
+    // equiv statistis
+    int              nConesTotal;
+    int              nConesConstr;
+    int              nEquivsTotal;
+    int              nEquivsConstr;
+    int              nNodesBegC;
+    int              nNodesEndC;
+    int              nRegsBegC;
+    int              nRegsEndC;
+    // runtime stats
+    abctime          timeBmc;        // bounded model checking
+    abctime          timeReduce;     // speculative reduction
+    abctime          timeMarkCones;  // marking the cones not to be refined
+    abctime          timeSimSat;     // simulation of the counter-examples
+    abctime          timeSat;        // solving SAT
+    abctime          timeSatSat;     // sat
+    abctime          timeSatUnsat;   // unsat
+    abctime          timeSatUndec;   // undecided
+    abctime          timeOther;      // other runtime
+    abctime          timeTotal;      // total runtime
+};
+
+// internal SAT manager
+struct Ssw_Sat_t_
+{
+    Aig_Man_t *      pAig;           // the AIG manager
+    int              fPolarFlip;     // flips polarity 
+    sat_solver *     pSat;           // recyclable SAT solver
+    int              nSatVars;       // the counter of SAT variables
+    Vec_Int_t *      vSatVars;       // mapping of each node into its SAT var
+    Vec_Ptr_t *      vFanins;        // fanins of the CNF node
+    Vec_Ptr_t *      vUsedPis;       // the PIs with SAT variables 
+    int              nSolverCalls;   // the total number of SAT calls
+};
+
+// internal frames manager
+struct Ssw_Frm_t_
+{
+    Aig_Man_t *      pAig;           // user-given AIG
+    int              nObjs;          // offset in terms of AIG nodes
+    int              nFrames;        // the number of frames in current unrolling
+    Aig_Man_t *      pFrames;        // unrolled AIG
+    Vec_Ptr_t *      vAig2Frm;       // mapping of AIG nodes into frame nodes
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int  Ssw_ObjSatNum( Ssw_Sat_t * p, Aig_Obj_t * pObj )             { return Vec_IntGetEntry( p->vSatVars, pObj->Id );  }
+static inline void Ssw_ObjSetSatNum( Ssw_Sat_t * p, Aig_Obj_t * pObj, int Num ) { Vec_IntSetEntry(p->vSatVars, pObj->Id, Num);      }
+
+static inline int  Ssw_ObjIsConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) 
+{
+    return Aig_ObjRepr(pAig, pObj) == Aig_ManConst1(pAig);
+}
+static inline void Ssw_ObjSetConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) 
+{
+    assert( !Ssw_ObjIsConst1Cand( pAig, pObj ) );
+    Aig_ObjSetRepr( pAig, pObj, Aig_ManConst1(pAig) );
+}
+
+static inline Aig_Obj_t * Ssw_ObjFrame( Ssw_Man_t * p, Aig_Obj_t * pObj, int i )                       { return p->pNodeToFrames[p->nFrames*pObj->Id + i];  }
+static inline void        Ssw_ObjSetFrame( Ssw_Man_t * p, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { p->pNodeToFrames[p->nFrames*pObj->Id + i] = pNode; }
+
+static inline Aig_Obj_t * Ssw_ObjChild0Fra( Ssw_Man_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Ssw_ObjFrame(p, Aig_ObjFanin0(pObj), i), Aig_ObjFaninC0(pObj)) : NULL;  }
+static inline Aig_Obj_t * Ssw_ObjChild1Fra( Ssw_Man_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Ssw_ObjFrame(p, Aig_ObjFanin1(pObj), i), Aig_ObjFaninC1(pObj)) : NULL;  }
+
+static inline Aig_Obj_t * Ssw_ObjFrame_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i )                       { return (Aig_Obj_t *)Vec_PtrGetEntry( p->vAig2Frm, p->nObjs*i+pObj->Id );     }
+static inline void        Ssw_ObjSetFrame_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { Vec_PtrSetEntry( p->vAig2Frm, p->nObjs*i+pObj->Id, pNode );     }
+
+static inline Aig_Obj_t * Ssw_ObjChild0Fra_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Ssw_ObjFrame_(p, Aig_ObjFanin0(pObj), i), Aig_ObjFaninC0(pObj)) : NULL;  }
+static inline Aig_Obj_t * Ssw_ObjChild1Fra_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Ssw_ObjFrame_(p, Aig_ObjFanin1(pObj), i), Aig_ObjFaninC1(pObj)) : NULL;  }
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== sswAig.c ===================================================*/
+extern Ssw_Frm_t *   Ssw_FrmStart( Aig_Man_t * pAig );
+extern void          Ssw_FrmStop( Ssw_Frm_t * p );
+extern Aig_Man_t *   Ssw_FramesWithClasses( Ssw_Man_t * p );
+extern Aig_Man_t *   Ssw_SpeculativeReduction( Ssw_Man_t * p );
+/*=== sswBmc.c ===================================================*/
+/*=== sswClass.c =================================================*/
+extern Ssw_Cla_t *   Ssw_ClassesStart( Aig_Man_t * pAig );
+extern void          Ssw_ClassesSetData( Ssw_Cla_t * p, void * pManData,
+                         unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *),
+                         int (*pFuncNodeIsConst)(void *,Aig_Obj_t *),
+                         int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) );
+extern void          Ssw_ClassesStop( Ssw_Cla_t * p );
+extern Aig_Man_t *   Ssw_ClassesReadAig( Ssw_Cla_t * p );
+extern Vec_Ptr_t *   Ssw_ClassesGetRefined( Ssw_Cla_t * p );
+extern void          Ssw_ClassesClearRefined( Ssw_Cla_t * p );
+extern int           Ssw_ClassesCand1Num( Ssw_Cla_t * p );
+extern int           Ssw_ClassesClassNum( Ssw_Cla_t * p );
+extern int           Ssw_ClassesLitNum( Ssw_Cla_t * p );
+extern Aig_Obj_t **  Ssw_ClassesReadClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize );
+extern void          Ssw_ClassesCollectClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vClass );
+extern void          Ssw_ClassesCheck( Ssw_Cla_t * p );
+extern void          Ssw_ClassesPrint( Ssw_Cla_t * p, int fVeryVerbose );
+extern void          Ssw_ClassesRemoveNode( Ssw_Cla_t * p, Aig_Obj_t * pObj );
+extern Ssw_Cla_t *   Ssw_ClassesPrepare( Aig_Man_t * pAig, int nFramesK, int fLatchCorr, int fConstCorr, int fOutputCorr, int nMaxLevs, int fVerbose );
+extern Ssw_Cla_t *   Ssw_ClassesPrepareSimple( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs );
+extern Ssw_Cla_t *   Ssw_ClassesPrepareFromReprs( Aig_Man_t * pAig );
+extern Ssw_Cla_t *   Ssw_ClassesPrepareTargets( Aig_Man_t * pAig );
+extern Ssw_Cla_t *   Ssw_ClassesPreparePairs( Aig_Man_t * pAig, Vec_Int_t ** pvClasses );
+extern Ssw_Cla_t *   Ssw_ClassesPreparePairsSimple( Aig_Man_t * pMiter, Vec_Int_t * vPairs );
+extern int           Ssw_ClassesRefine( Ssw_Cla_t * p, int fRecursive );
+extern int           Ssw_ClassesRefineGroup( Ssw_Cla_t * p, Vec_Ptr_t * vReprs, int fRecursive );
+extern int           Ssw_ClassesRefineOneClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, int fRecursive );
+extern int           Ssw_ClassesRefineConst1Group( Ssw_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive );
+extern int           Ssw_ClassesRefineConst1( Ssw_Cla_t * p, int fRecursive );
+extern int           Ssw_ClassesPrepareRehash( Ssw_Cla_t * p, Vec_Ptr_t * vCands, int fConstCorr );
+/*=== sswCnf.c ===================================================*/
+extern Ssw_Sat_t *   Ssw_SatStart( int fPolarFlip );
+extern void          Ssw_SatStop( Ssw_Sat_t * p );
+extern void          Ssw_CnfNodeAddToSolver( Ssw_Sat_t * p, Aig_Obj_t * pObj );
+extern int           Ssw_CnfGetNodeValue( Ssw_Sat_t * p, Aig_Obj_t * pObjFraig );
+/*=== sswConstr.c ===================================================*/
+extern int           Ssw_ManSweepBmcConstr( Ssw_Man_t * p );
+extern int           Ssw_ManSweepConstr( Ssw_Man_t * p );
+extern void          Ssw_ManRefineByConstrSim( Ssw_Man_t * p );
+/*=== sswCore.c ===================================================*/
+extern Aig_Man_t *   Ssw_SignalCorrespondenceRefine( Ssw_Man_t * p );
+/*=== sswDyn.c ===================================================*/
+extern void          Ssw_ManLoadSolver( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj );
+extern int           Ssw_ManSweepDyn( Ssw_Man_t * p );
+/*=== sswLcorr.c ==========================================================*/
+extern int           Ssw_ManSweepLatch( Ssw_Man_t * p );
+/*=== sswMan.c ===================================================*/
+extern Ssw_Man_t *   Ssw_ManCreate( Aig_Man_t * pAig, Ssw_Pars_t * pPars );
+extern void          Ssw_ManCleanup( Ssw_Man_t * p );
+extern void          Ssw_ManStop( Ssw_Man_t * p );
+/*=== sswSat.c ===================================================*/
+extern int           Ssw_NodesAreEquiv( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew );
+extern int           Ssw_NodesAreConstrained( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew );
+extern int           Ssw_NodeIsConstrained( Ssw_Man_t * p, Aig_Obj_t * pPoObj );
+/*=== sswSemi.c ===================================================*/
+extern int           Ssw_FilterUsingSemi( Ssw_Man_t * pMan, int fCheckTargets, int nConfMax, int fVerbose );
+/*=== sswSim.c ===================================================*/
+extern unsigned      Ssw_SmlObjHashWord( Ssw_Sml_t * p, Aig_Obj_t * pObj );
+extern int           Ssw_SmlObjIsConstWord( Ssw_Sml_t * p, Aig_Obj_t * pObj );
+extern int           Ssw_SmlObjsAreEqualWord( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 );
+extern int           Ssw_SmlObjIsConstBit( void * p, Aig_Obj_t * pObj );
+extern int           Ssw_SmlObjsAreEqualBit( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 );
+extern void          Ssw_SmlAssignRandomFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame );
+extern Ssw_Sml_t *   Ssw_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame );
+extern void          Ssw_SmlClean( Ssw_Sml_t * p );
+extern void          Ssw_SmlStop( Ssw_Sml_t * p );
+extern void          Ssw_SmlObjAssignConst( Ssw_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame );
+extern void          Ssw_SmlObjSetWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, unsigned Word, int iWord, int iFrame );
+extern void          Ssw_SmlAssignDist1Plus( Ssw_Sml_t * p, unsigned * pPat );
+extern void          Ssw_SmlSimulateOne( Ssw_Sml_t * p );
+extern void          Ssw_SmlSimulateOneFrame( Ssw_Sml_t * p );
+extern void          Ssw_SmlSimulateOneDyn_rec( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f, int * pVisited, int nVisCounter );
+extern void          Ssw_SmlResimulateSeq( Ssw_Sml_t * p );
+/*=== sswSimSat.c ===================================================*/
+extern void          Ssw_ManResimulateBit( Ssw_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr );
+extern void          Ssw_ManResimulateWord( Ssw_Man_t * p, Aig_Obj_t * pCand, Aig_Obj_t * pRepr, int f );
+/*=== sswSweep.c ===================================================*/
+extern int           Ssw_ManGetSatVarValue( Ssw_Man_t * p, Aig_Obj_t * pObj, int f );
+extern void          Ssw_SmlSavePatternAig( Ssw_Man_t * p, int f );
+extern int           Ssw_ManSweepNode( Ssw_Man_t * p, Aig_Obj_t * pObj, int f, int fBmc, Vec_Int_t * vPairs );
+extern int           Ssw_ManSweepBmc( Ssw_Man_t * p );
+extern int           Ssw_ManSweep( Ssw_Man_t * p );
+/*=== sswUnique.c ===================================================*/
+extern void          Ssw_UniqueRegisterPairInfo( Ssw_Man_t * p );
+extern int           Ssw_ManUniqueOne( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj, int fVerbose );
+extern int           Ssw_ManUniqueAddConstraint( Ssw_Man_t * p, Vec_Ptr_t * vCommon, int f1, int f2 );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/proof/ssw/sswIslands.c b/abc-build/src/proof/ssw/sswIslands.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswIslands.c
@@ -0,0 +1,598 @@
+/**CFile****************************************************************
+
+  FileName    [sswIslands.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [Detection of islands of difference.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswIslands.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates pair of structurally equivalent nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_CreatePair( Vec_Int_t * vPairs, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+    pObj0->pData = pObj1;
+    pObj1->pData = pObj0;
+    Vec_IntPush( vPairs, pObj0->Id );
+    Vec_IntPush( vPairs, pObj1->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Establishes relationship between nodes using pairing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_MatchingStart( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs )
+{
+    Aig_Obj_t * pObj0, * pObj1;
+    int i;
+    // create matching
+    Aig_ManCleanData( p0 );
+    Aig_ManCleanData( p1 );
+    for ( i = 0; i < Vec_IntSize(vPairs); i += 2 )
+    {
+        pObj0 = Aig_ManObj( p0, Vec_IntEntry(vPairs, i) );
+        pObj1 = Aig_ManObj( p1, Vec_IntEntry(vPairs, i+1) );
+        assert( pObj0->pData == NULL );
+        assert( pObj1->pData == NULL );
+        pObj0->pData = pObj1;
+        pObj1->pData = pObj0;
+    }
+    // make sure constants are matched
+    pObj0 = Aig_ManConst1( p0 );
+    pObj1 = Aig_ManConst1( p1 );
+    assert( pObj0->pData == pObj1 );
+    assert( pObj1->pData == pObj0 );
+    // make sure PIs are matched
+    Saig_ManForEachPi( p0, pObj0, i )
+    {
+        pObj1 = Aig_ManCi( p1, i );
+        assert( pObj0->pData == pObj1 );
+        assert( pObj1->pData == pObj0 );
+    }
+    // make sure the POs are not matched
+    Aig_ManForEachCo( p0, pObj0, i )
+    {
+        pObj1 = Aig_ManCo( p1, i );
+        assert( pObj0->pData == NULL );
+        assert( pObj1->pData == NULL );
+    }
+
+    // check that LIs/LOs are matched in sync
+    Saig_ManForEachLo( p0, pObj0, i )
+    {
+        if ( pObj0->pData == NULL )
+            continue;
+        pObj1 = (Aig_Obj_t *)pObj0->pData;
+        if ( !Saig_ObjIsLo(p1, pObj1) )
+            Abc_Print( 1, "Mismatch between LO pairs.\n" );
+    }
+    Saig_ManForEachLo( p1, pObj1, i )
+    {
+        if ( pObj1->pData == NULL )
+            continue;
+        pObj0 = (Aig_Obj_t *)pObj1->pData;
+        if ( !Saig_ObjIsLo(p0, pObj0) )
+            Abc_Print( 1, "Mismatch between LO pairs.\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Establishes relationship between nodes using pairing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_MatchingExtendOne( Aig_Man_t * p, Vec_Ptr_t * vNodes )
+{
+    Aig_Obj_t * pNext, * pObj;
+    int i, k, iFan = -1;
+    Vec_PtrClear( vNodes );
+    Aig_ManIncrementTravId( p );
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
+            continue;
+        if ( pObj->pData != NULL )
+            continue;
+        if ( Saig_ObjIsLo(p, pObj) )
+        {
+            pNext = Saig_ObjLoToLi(p, pObj);
+            pNext = Aig_ObjFanin0(pNext);
+            if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) && !Aig_ObjIsConst1(pNext) )
+            {
+                Aig_ObjSetTravIdCurrent(p, pNext);
+                Vec_PtrPush( vNodes, pNext );
+            }
+        }
+        if ( Aig_ObjIsNode(pObj) )
+        {
+            pNext = Aig_ObjFanin0(pObj);
+            if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) )
+            {
+                Aig_ObjSetTravIdCurrent(p, pNext);
+                Vec_PtrPush( vNodes, pNext );
+            }
+            pNext = Aig_ObjFanin1(pObj);
+            if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) )
+            {
+                Aig_ObjSetTravIdCurrent(p, pNext);
+                Vec_PtrPush( vNodes, pNext );
+            }
+        }
+        Aig_ObjForEachFanout( p, pObj, pNext, iFan, k )
+        {
+            if ( Saig_ObjIsPo(p, pNext) )
+                continue;
+            if ( Saig_ObjIsLi(p, pNext) )
+                pNext = Saig_ObjLiToLo(p, pNext);
+            if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) )
+            {
+                Aig_ObjSetTravIdCurrent(p, pNext);
+                Vec_PtrPush( vNodes, pNext );
+            }
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Establishes relationship between nodes using pairing.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_MatchingCountUnmached( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    Aig_ManForEachObj( p, pObj, i )
+    {
+        if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
+            continue;
+        if ( pObj->pData != NULL )
+            continue;
+        Counter++;
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Establishes relationship between nodes using pairing.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_MatchingExtend( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose )
+{
+    Vec_Ptr_t * vNodes0, * vNodes1;
+    Aig_Obj_t * pNext0, * pNext1;
+    int d, k;
+    Aig_ManFanoutStart(p0);
+    Aig_ManFanoutStart(p1);
+    vNodes0 = Vec_PtrAlloc( 1000 );
+    vNodes1 = Vec_PtrAlloc( 1000 );
+    if ( fVerbose )
+    {
+        int nUnmached = Ssw_MatchingCountUnmached(p0);
+        Abc_Print( 1, "Extending islands by %d steps:\n", nDist );
+        Abc_Print( 1, "%2d : Total = %6d. Unmatched = %6d.  Ratio = %6.2f %%\n",
+            0, Aig_ManCiNum(p0) + Aig_ManNodeNum(p0),
+            nUnmached, 100.0 * nUnmached/(Aig_ManCiNum(p0) + Aig_ManNodeNum(p0)) );
+    }
+    for ( d = 0; d < nDist; d++ )
+    {
+        Ssw_MatchingExtendOne( p0, vNodes0 );
+        Ssw_MatchingExtendOne( p1, vNodes1 );
+        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pNext0, k )
+        {
+            pNext1 = (Aig_Obj_t *)pNext0->pData;
+            if ( pNext1 == NULL )
+                continue;
+            assert( pNext1->pData == pNext0 );
+            if ( Saig_ObjIsPi(p0, pNext1) )
+                continue;
+            pNext0->pData = NULL;
+            pNext1->pData = NULL;
+        }
+        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pNext0, k )
+        {
+            pNext1 = (Aig_Obj_t *)pNext0->pData;
+            if ( pNext1 == NULL )
+                continue;
+            assert( pNext1->pData == pNext0 );
+            if ( Saig_ObjIsPi(p1, pNext1) )
+                continue;
+            pNext0->pData = NULL;
+            pNext1->pData = NULL;
+        }
+        if ( fVerbose )
+        {
+            int nUnmached = Ssw_MatchingCountUnmached(p0);
+            Abc_Print( 1, "%2d : Total = %6d. Unmatched = %6d.  Ratio = %6.2f %%\n",
+                d+1, Aig_ManCiNum(p0) + Aig_ManNodeNum(p0),
+                nUnmached, 100.0 * nUnmached/(Aig_ManCiNum(p0) + Aig_ManNodeNum(p0)) );
+        }
+    }
+    Vec_PtrFree( vNodes0 );
+    Vec_PtrFree( vNodes1 );
+    Aig_ManFanoutStop(p0);
+    Aig_ManFanoutStop(p1);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Used differences in p0 to complete p1.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_MatchingComplete( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+    Vec_Ptr_t * vNewLis;
+    Aig_Obj_t * pObj0, * pObj0Li, * pObj1;
+    int i;
+    // create register outputs in p0 that are absent in p1
+    vNewLis = Vec_PtrAlloc( 100 );
+    Saig_ManForEachLiLo( p0, pObj0Li, pObj0, i )
+    {
+        if ( pObj0->pData != NULL )
+            continue;
+        pObj1 = Aig_ObjCreateCi( p1 );
+        pObj0->pData = pObj1;
+        pObj1->pData = pObj0;
+        Vec_PtrPush( vNewLis, pObj0Li );
+    }
+    // add missing nodes in the topological order
+    Aig_ManForEachNode( p0, pObj0, i )
+    {
+        if ( pObj0->pData != NULL )
+            continue;
+        pObj1 = Aig_And( p1, Aig_ObjChild0Copy(pObj0), Aig_ObjChild1Copy(pObj0) );
+        pObj0->pData = pObj1;
+        pObj1->pData = pObj0;
+    }
+    // create register outputs in p0 that are absent in p1
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNewLis, pObj0Li, i )
+        Aig_ObjCreateCo( p1, Aig_ObjChild0Copy(pObj0Li) );
+    // increment the number of registers
+    Aig_ManSetRegNum( p1, Aig_ManRegNum(p1) + Vec_PtrSize(vNewLis) );
+    Vec_PtrFree( vNewLis );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives matching for all pairs.]
+
+  Description [Modifies both AIGs.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Ssw_MatchingPairs( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+    Vec_Int_t * vPairsNew;
+    Aig_Obj_t * pObj0, * pObj1;
+    int i;
+    // check correctness
+    assert( Aig_ManCiNum(p0) == Aig_ManCiNum(p1) );
+    assert( Aig_ManCoNum(p0) == Aig_ManCoNum(p1) );
+    assert( Aig_ManRegNum(p0) == Aig_ManRegNum(p1) );
+    assert( Aig_ManObjNum(p0) == Aig_ManObjNum(p1) );
+    // create complete pairs
+    vPairsNew = Vec_IntAlloc( 2*Aig_ManObjNum(p0) );
+    Aig_ManForEachObj( p0, pObj0, i )
+    {
+        if ( Aig_ObjIsCo(pObj0) )
+            continue;
+        pObj1 = (Aig_Obj_t *)pObj0->pData;
+        Vec_IntPush( vPairsNew, pObj0->Id );
+        Vec_IntPush( vPairsNew, pObj1->Id );
+    }
+    return vPairsNew;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the result of matching to miter.]
+
+  Description [The array of pairs should be complete.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Ssw_MatchingMiter( Aig_Man_t * pMiter, Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairsAll )
+{
+    Vec_Int_t * vPairsMiter;
+    Aig_Obj_t * pObj0, * pObj1;
+    int i;
+    // create matching of nodes in the miter
+    vPairsMiter = Vec_IntAlloc( 2*Aig_ManObjNum(p0) );
+    for ( i = 0; i < Vec_IntSize(vPairsAll); i += 2 )
+    {
+        pObj0 = Aig_ManObj( p0, Vec_IntEntry(vPairsAll, i) );
+        pObj1 = Aig_ManObj( p1, Vec_IntEntry(vPairsAll, i+1) );
+        assert( pObj0->pData != NULL );
+        assert( pObj1->pData != NULL );
+        if ( pObj0->pData == pObj1->pData )
+            continue;
+        if ( Aig_ObjIsNone((Aig_Obj_t *)pObj0->pData) || Aig_ObjIsNone((Aig_Obj_t *)pObj1->pData) )
+            continue;
+        // get the miter nodes
+        pObj0 = (Aig_Obj_t *)pObj0->pData;
+        pObj1 = (Aig_Obj_t *)pObj1->pData;
+        assert( !Aig_IsComplement(pObj0) );
+        assert( !Aig_IsComplement(pObj1) );
+        assert( Aig_ObjType(pObj0) == Aig_ObjType(pObj1) );
+        if ( Aig_ObjIsCo(pObj0) )
+            continue;
+        assert( Aig_ObjIsNode(pObj0) || Saig_ObjIsLo(pMiter, pObj0) );
+        assert( Aig_ObjIsNode(pObj1) || Saig_ObjIsLo(pMiter, pObj1) );
+        assert( pObj0->Id < pObj1->Id );
+        Vec_IntPush( vPairsMiter, pObj0->Id );
+        Vec_IntPush( vPairsMiter, pObj1->Id );
+    }
+    return vPairsMiter;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Solves SEC using structural similarity.]
+
+  Description [Modifies both p0 and p1 by adding extra logic.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Ssw_SecWithSimilaritySweep( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars )
+{
+    Ssw_Man_t * p;
+    Vec_Int_t * vPairsAll, * vPairsMiter;
+    Aig_Man_t * pMiter, * pAigNew;
+    // derive full matching
+    Ssw_MatchingStart( p0, p1, vPairs );
+    if ( pPars->nIsleDist )
+        Ssw_MatchingExtend( p0, p1, pPars->nIsleDist, pPars->fVerbose );
+    Ssw_MatchingComplete( p0, p1 );
+    Ssw_MatchingComplete( p1, p0 );
+    vPairsAll = Ssw_MatchingPairs( p0, p1 );
+    // create miter and transfer matching
+    pMiter = Saig_ManCreateMiter( p0, p1, 0 );
+    vPairsMiter = Ssw_MatchingMiter( pMiter, p0, p1, vPairsAll );
+    Vec_IntFree( vPairsAll );
+    // start the induction manager
+    p = Ssw_ManCreate( pMiter, pPars );
+    // create equivalence classes using these IDs
+    if ( p->pPars->fPartSigCorr )
+        p->ppClasses = Ssw_ClassesPreparePairsSimple( pMiter, vPairsMiter );
+    else
+        p->ppClasses = Ssw_ClassesPrepare( pMiter, pPars->nFramesK, pPars->fLatchCorr, pPars->fConstCorr, pPars->fOutputCorr, pPars->nMaxLevs, pPars->fVerbose );
+    if ( p->pPars->fDumpSRInit )
+    {
+        if ( p->pPars->fPartSigCorr )
+        {
+            Aig_Man_t * pSRed = Ssw_SpeculativeReduction( p );
+            Aig_ManDumpBlif( pSRed, "srm_part.blif", NULL, NULL );
+            Aig_ManStop( pSRed );
+            Abc_Print( 1, "Speculatively reduced miter is saved in file \"%s\".\n", "srm_part.blif" );
+        }
+        else
+            Abc_Print( 1, "Dumping speculative miter is possible only for partial signal correspondence (switch \"-c\").\n" );
+    }
+    p->pSml = Ssw_SmlStart( pMiter, 0, 1 + p->pPars->nFramesAddSim, 1 );
+    Ssw_ClassesSetData( p->ppClasses, p->pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord );
+    // perform refinement of classes
+    pAigNew = Ssw_SignalCorrespondenceRefine( p );
+    // cleanup
+    Ssw_ManStop( p );
+    Aig_ManStop( pMiter );
+    Vec_IntFree( vPairsMiter );
+    return pAigNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Solves SEC with structural similarity.]
+
+  Description [The first two arguments are pointers to the AIG managers.
+  The third argument is the array of pairs of IDs of structurally equivalent
+  nodes from the first and second managers, respectively.]
+               
+  SideEffects [The managers will be updated by adding "islands of difference".]
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SecWithSimilarityPairs( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars )
+{
+    Ssw_Pars_t Pars;
+    Aig_Man_t * pAigRes;
+    int RetValue;
+    abctime clk = Abc_Clock();
+    // derive parameters if not given
+    if ( pPars == NULL )
+        Ssw_ManSetDefaultParams( pPars = &Pars );
+    // reduce the AIG with pairs
+    pAigRes = Ssw_SecWithSimilaritySweep( p0, p1, vPairs, pPars );
+    // report the result of verification
+    RetValue = Ssw_MiterStatus( pAigRes, 1 );
+    if ( RetValue == 1 )
+        Abc_Print( 1, "Verification successful.  " );
+    else if ( RetValue == 0 )
+        Abc_Print( 1, "Verification failed with a counter-example.  " );
+    else
+        Abc_Print( 1, "Verification UNDECIDED. The number of remaining regs = %d (total = %d).  ",
+            Aig_ManRegNum(pAigRes), Aig_ManRegNum(p0)+Aig_ManRegNum(p1) );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    Aig_ManStop( pAigRes );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dummy procedure to detect structural similarity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_StrSimPerformMatching_hack( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+    Vec_Int_t * vPairs;
+    Aig_Obj_t * pObj;
+    int i;
+    // create array of pairs
+    vPairs = Vec_IntAlloc( 100 );
+    Aig_ManForEachObj( p0, pObj, i )
+    {
+        if ( !Aig_ObjIsConst1(pObj) && !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) )
+            continue;
+        Vec_IntPush( vPairs, i );
+        Vec_IntPush( vPairs, i );
+    }
+    return vPairs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Solves SEC with structural similarity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SecWithSimilarity( Aig_Man_t * p0, Aig_Man_t * p1, Ssw_Pars_t * pPars )
+{
+    Vec_Int_t * vPairs;
+    Aig_Man_t * pPart0, * pPart1;
+    int RetValue;
+    if ( pPars->fVerbose )
+        Abc_Print( 1, "Performing sequential verification using structural similarity.\n" );
+    // consider the case when a miter is given
+    if ( p1 == NULL )
+    {
+        if ( pPars->fVerbose )
+        {
+            Aig_ManPrintStats( p0 );
+        }
+        // demiter the miter
+        if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) )
+        {
+            Abc_Print( 1, "Demitering has failed.\n" );
+            return -1;
+        }
+    }
+    else
+    {
+        pPart0 = Aig_ManDupSimple( p0 );
+        pPart1 = Aig_ManDupSimple( p1 );
+    }
+    if ( pPars->fVerbose )
+    {
+//        Aig_ManPrintStats( pPart0 );
+//        Aig_ManPrintStats( pPart1 );
+        if ( p1 == NULL )
+        {
+//        Aig_ManDumpBlif( pPart0, "part0.blif", NULL, NULL );
+//        Aig_ManDumpBlif( pPart1, "part1.blif", NULL, NULL );
+//        Abc_Print( 1, "The result of demitering is written into files \"%s\" and \"%s\".\n", "part0.blif", "part1.blif" );
+        }
+    }
+    assert( Aig_ManRegNum(pPart0) > 0 );
+    assert( Aig_ManRegNum(pPart1) > 0 );
+    assert( Saig_ManPiNum(pPart0) == Saig_ManPiNum(pPart1) );
+    assert( Saig_ManPoNum(pPart0) == Saig_ManPoNum(pPart1) );
+    // derive pairs
+//    vPairs = Saig_StrSimPerformMatching_hack( pPart0, pPart1 );
+    vPairs = Saig_StrSimPerformMatching( pPart0, pPart1, 0, pPars->fVerbose, NULL );
+    RetValue = Ssw_SecWithSimilarityPairs( pPart0, pPart1, vPairs, pPars );
+    Aig_ManStop( pPart0 );
+    Aig_ManStop( pPart1 );
+    Vec_IntFree( vPairs );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswLcorr.c b/abc-build/src/proof/ssw/sswLcorr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswLcorr.c
@@ -0,0 +1,337 @@
+/**CFile****************************************************************
+
+  FileName    [sswLcorr.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [Latch correspondence.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswLcorr.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+//#include "bar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Tranfers simulation information from FRAIG to AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManSweepTransfer( Ssw_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pObjFraig;
+    unsigned * pInfo;
+    int i;
+    // transfer simulation information
+    Aig_ManForEachCi( p->pAig, pObj, i )
+    {
+        pObjFraig = Ssw_ObjFrame( p, pObj, 0 );
+        if ( pObjFraig == Aig_ManConst0(p->pFrames) )
+        {
+            Ssw_SmlObjAssignConst( p->pSml, pObj, 0, 0 );
+            continue;
+        }
+        assert( !Aig_IsComplement(pObjFraig) );
+        assert( Aig_ObjIsCi(pObjFraig) );
+        pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjCioId(pObjFraig) );
+        Ssw_SmlObjSetWord( p->pSml, pObj, pInfo[0], 0, 0 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one round of simulation with counter-examples.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManSweepResimulate( Ssw_Man_t * p )
+{
+    int RetValue1, RetValue2;
+    abctime clk = Abc_Clock();
+    // transfer PI simulation information from storage
+    Ssw_ManSweepTransfer( p );
+    // simulate internal nodes
+    Ssw_SmlSimulateOneFrame( p->pSml );
+    // check equivalence classes
+    RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 );
+    RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 );
+    // prepare simulation info for the next round
+    Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 );
+    p->nPatterns = 0;
+    p->nSimRounds++;
+p->timeSimSat += Abc_Clock() - clk;
+    return RetValue1 > 0 || RetValue2 > 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Saves one counter-example into internal storage.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlAddPattern( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pCand )
+{
+    Aig_Obj_t * pObj;
+    unsigned * pInfo;
+    int i, nVarNum, Value;
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->pMSat->vUsedPis, pObj, i )
+    {
+        nVarNum = Ssw_ObjSatNum( p->pMSat, pObj );
+        assert( nVarNum > 0 );
+        Value = sat_solver_var_value( p->pMSat->pSat, nVarNum );
+        if ( Value == 0 )
+            continue;
+        pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjCioId(pObj) );
+        Abc_InfoSetBit( pInfo, p->nPatterns );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Builds fraiged logic cone of the node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManBuildCone_rec( Ssw_Man_t * p, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pObjNew;
+    assert( !Aig_IsComplement(pObj) );
+    if ( Ssw_ObjFrame( p, pObj, 0 ) )
+        return;
+    assert( Aig_ObjIsNode(pObj) );
+    Ssw_ManBuildCone_rec( p, Aig_ObjFanin0(pObj) );
+    Ssw_ManBuildCone_rec( p, Aig_ObjFanin1(pObj) );
+    pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, 0), Ssw_ObjChild1Fra(p, pObj, 0) );
+    Ssw_ObjSetFrame( p, pObj, 0, pObjNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the SAT solver.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManSweepLatchOne( Ssw_Man_t * p, Aig_Obj_t * pObjRepr, Aig_Obj_t * pObj )
+{
+    Aig_Obj_t * pObjFraig, * pObjReprFraig, * pObjLi;
+    int RetValue;
+    abctime clk;
+    assert( Aig_ObjIsCi(pObj) );
+    assert( Aig_ObjIsCi(pObjRepr) || Aig_ObjIsConst1(pObjRepr) );
+    // check if it makes sense to skip some calls
+    if ( p->nCallsCount > 100 && p->nCallsUnsat < p->nCallsSat )
+    {
+        if ( ++p->nCallsDelta < 0 )
+            return;
+    }
+    p->nCallsDelta = 0;
+clk = Abc_Clock();
+    // get the fraiged node
+    pObjLi = Saig_ObjLoToLi( p->pAig, pObj );
+    Ssw_ManBuildCone_rec( p, Aig_ObjFanin0(pObjLi) );
+    pObjFraig = Ssw_ObjChild0Fra( p, pObjLi, 0 );
+    // get the fraiged representative
+    if ( Aig_ObjIsCi(pObjRepr) )
+    {
+        pObjLi = Saig_ObjLoToLi( p->pAig, pObjRepr );
+        Ssw_ManBuildCone_rec( p, Aig_ObjFanin0(pObjLi) );
+        pObjReprFraig = Ssw_ObjChild0Fra( p, pObjLi, 0 );
+    }
+    else
+        pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, 0 );
+p->timeReduce += Abc_Clock() - clk;
+    // if the fraiged nodes are the same, return
+    if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) )
+        return;
+    p->nRecycleCalls++;
+    p->nCallsCount++;
+
+    // check equivalence of the two nodes
+    if ( (pObj->fPhase == pObjRepr->fPhase) != (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) )
+    {
+        p->nPatterns++;
+        p->nStrangers++;
+        p->fRefined = 1;
+    }
+    else
+    {
+        RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) );
+        if ( RetValue == 1 )  // proved equivalence
+        {
+            p->nCallsUnsat++;
+            return;
+        }
+        if ( RetValue == -1 ) // timed out
+        {
+            Ssw_ClassesRemoveNode( p->ppClasses, pObj );
+            p->nCallsUnsat++;
+            p->fRefined = 1;
+            return;
+        }
+        else // disproved equivalence
+        {
+            Ssw_SmlAddPattern( p, pObjRepr, pObj );
+            p->nPatterns++;
+            p->nCallsSat++;
+            p->fRefined = 1;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one iteration of sweeping latches.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManSweepLatch( Ssw_Man_t * p )
+{
+//    Bar_Progress_t * pProgress = NULL;
+    Vec_Ptr_t * vClass;
+    Aig_Obj_t * pObj, * pRepr, * pTemp;
+    int i, k;
+
+    // start the timeframe
+    p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) );
+    // map constants and PIs
+    Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), 0, Aig_ManConst1(p->pFrames) );
+    Saig_ManForEachPi( p->pAig, pObj, i )
+        Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreateCi(p->pFrames) );
+
+    // implement equivalence classes
+    Saig_ManForEachLo( p->pAig, pObj, i )
+    {
+        pRepr = Aig_ObjRepr( p->pAig, pObj );
+        if ( pRepr == NULL )
+        {
+            pTemp = Aig_ObjCreateCi(p->pFrames);
+            pTemp->pData = pObj;
+        }
+        else
+            pTemp = Aig_NotCond( Ssw_ObjFrame(p, pRepr, 0), pRepr->fPhase ^ pObj->fPhase );
+        Ssw_ObjSetFrame( p, pObj, 0, pTemp );
+    }
+    Aig_ManSetCioIds( p->pFrames );
+
+    // prepare simulation info
+    assert( p->vSimInfo == NULL );
+    p->vSimInfo = Vec_PtrAllocSimInfo( Aig_ManCiNum(p->pFrames), 1 );
+    Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 );
+
+    // go through the registers
+//    if ( p->pPars->fVerbose )
+//        pProgress = Bar_ProgressStart( stdout, Aig_ManRegNum(p->pAig) );
+    vClass = Vec_PtrAlloc( 100 );
+    p->fRefined = 0;
+    p->nCallsCount = p->nCallsSat = p->nCallsUnsat = 0;
+    Saig_ManForEachLo( p->pAig, pObj, i )
+    {
+//        if ( p->pPars->fVerbose )
+//            Bar_ProgressUpdate( pProgress, i, NULL );
+        // consider the case of constant candidate
+        if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) )
+            Ssw_ManSweepLatchOne( p, Aig_ManConst1(p->pAig), pObj );
+        else
+        {
+            // consider the case of equivalence class
+            Ssw_ClassesCollectClass( p->ppClasses, pObj, vClass );
+            if ( Vec_PtrSize(vClass) == 0 )
+                continue;
+            // try to prove equivalences in this class
+            Vec_PtrForEachEntry( Aig_Obj_t *, vClass, pTemp, k )
+                if ( Aig_ObjRepr(p->pAig, pTemp) == pObj )
+                {
+                    Ssw_ManSweepLatchOne( p, pObj, pTemp );
+                    if ( p->nPatterns == 32 )
+                        break;
+                }
+        }
+        // resimulate
+        if ( p->nPatterns == 32 )
+            Ssw_ManSweepResimulate( p );
+        // attempt recycling the SAT solver
+        if ( p->pPars->nSatVarMax &&
+             p->pMSat->nSatVars > p->pPars->nSatVarMax &&
+             p->nRecycleCalls > p->pPars->nRecycleCalls )
+        {
+            p->nVarsMax  = Abc_MaxInt( p->nVarsMax,  p->pMSat->nSatVars );
+            p->nCallsMax = Abc_MaxInt( p->nCallsMax, p->pMSat->nSolverCalls );
+            Ssw_SatStop( p->pMSat );
+            p->pMSat = Ssw_SatStart( 0 );
+            p->nRecycles++;
+            p->nRecycleCalls = 0;
+        }
+    }
+//    ABC_PRT( "reduce", p->timeReduce );
+//    Aig_TableProfile( p->pFrames );
+//    Abc_Print( 1, "And gates = %d\n", Aig_ManNodeNum(p->pFrames) );
+    // resimulate
+    if ( p->nPatterns > 0 )
+        Ssw_ManSweepResimulate( p );
+    // cleanup
+    Vec_PtrFree( vClass );
+//    if ( p->pPars->fVerbose )
+//        Bar_ProgressStop( pProgress );
+
+    // cleanup
+//    Ssw_ClassesCheck( p->ppClasses );
+    return p->fRefined;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswMan.c b/abc-build/src/proof/ssw/sswMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswMan.c
@@ -0,0 +1,217 @@
+/**CFile****************************************************************
+
+  FileName    [sswMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [Calls to the SAT solver.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswMan.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ssw_Man_t * Ssw_ManCreate( Aig_Man_t * pAig, Ssw_Pars_t * pPars )
+{
+    Ssw_Man_t * p;
+    // prepare the sequential AIG
+    assert( Saig_ManRegNum(pAig) > 0 );
+    Aig_ManFanoutStart( pAig );
+    Aig_ManSetCioIds( pAig );
+    // create interpolation manager
+    p = ABC_ALLOC( Ssw_Man_t, 1 );
+    memset( p, 0, sizeof(Ssw_Man_t) );
+    p->pPars         = pPars;
+    p->pAig          = pAig;
+    p->nFrames       = pPars->nFramesK + 1;
+    p->pNodeToFrames = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) * p->nFrames );
+    p->vCommon       = Vec_PtrAlloc( 100 );
+    p->iOutputLit    = -1;
+    // allocate storage for sim pattern
+    p->nPatWords     = Abc_BitWordNum( Saig_ManPiNum(pAig) * p->nFrames + Saig_ManRegNum(pAig) );
+    p->pPatWords     = ABC_CALLOC( unsigned, p->nPatWords );
+    // other
+    p->vNewLos       = Vec_PtrAlloc( 100 );
+    p->vNewPos       = Vec_IntAlloc( 100 );
+    p->vResimConsts  = Vec_PtrAlloc( 100 );
+    p->vResimClasses = Vec_PtrAlloc( 100 );
+//    p->pPars->fVerbose = 1;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats of the manager.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManCountEquivs( Ssw_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, nEquivs = 0;
+    Aig_ManForEachObj( p->pAig, pObj, i )
+        nEquivs += ( Aig_ObjRepr(p->pAig, pObj) != NULL );
+    return nEquivs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints stats of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManPrintStats( Ssw_Man_t * p )
+{
+    double nMemory = 1.0*Aig_ManObjNumMax(p->pAig)*p->nFrames*(2*sizeof(int)+2*sizeof(void*))/(1<<20);
+
+    Abc_Print( 1, "Parameters: F = %d. AddF = %d. C-lim = %d. Constr = %d. MaxLev = %d. Mem = %0.2f MB.\n",
+        p->pPars->nFramesK, p->pPars->nFramesAddSim, p->pPars->nBTLimit, Saig_ManConstrNum(p->pAig), p->pPars->nMaxLevs, nMemory );
+    Abc_Print( 1, "AIG       : PI = %d. PO = %d. Latch = %d. Node = %d.  Ave SAT vars = %d.\n",
+        Saig_ManPiNum(p->pAig), Saig_ManPoNum(p->pAig), Saig_ManRegNum(p->pAig), Aig_ManNodeNum(p->pAig),
+        0/(p->pPars->nIters+1) );
+    Abc_Print( 1, "SAT calls : Proof = %d. Cex = %d. Fail = %d. Lits proved = %d.\n",
+        p->nSatProof, p->nSatCallsSat, p->nSatFailsReal, Ssw_ManCountEquivs(p) );
+    Abc_Print( 1, "SAT solver: Vars max = %d. Calls max = %d. Recycles = %d. Sim rounds = %d.\n",
+        p->nVarsMax, p->nCallsMax, p->nRecyclesTotal, p->nSimRounds );
+    Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%).  RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n",
+        p->nNodesBeg, p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/(p->nNodesBeg?p->nNodesBeg:1),
+        p->nRegsBeg, p->nRegsEnd, 100.0*(p->nRegsBeg-p->nRegsEnd)/(p->nRegsBeg?p->nRegsBeg:1) );
+
+    p->timeOther = p->timeTotal-p->timeBmc-p->timeReduce-p->timeMarkCones-p->timeSimSat-p->timeSat;
+    ABC_PRTP( "BMC        ", p->timeBmc,       p->timeTotal );
+    ABC_PRTP( "Spec reduce", p->timeReduce,    p->timeTotal );
+    ABC_PRTP( "Mark cones ", p->timeMarkCones, p->timeTotal );
+    ABC_PRTP( "Sim SAT    ", p->timeSimSat,    p->timeTotal );
+    ABC_PRTP( "SAT solving", p->timeSat,       p->timeTotal );
+    ABC_PRTP( "  unsat    ", p->timeSatUnsat,  p->timeTotal );
+    ABC_PRTP( "  sat      ", p->timeSatSat,    p->timeTotal );
+    ABC_PRTP( "  undecided", p->timeSatUndec,  p->timeTotal );
+    ABC_PRTP( "Other      ", p->timeOther,     p->timeTotal );
+    ABC_PRTP( "TOTAL      ", p->timeTotal,     p->timeTotal );
+
+    // report the reductions
+    if ( p->pAig->nConstrs )
+    {
+        Abc_Print( 1, "Statistics reflecting the use of constraints:\n" );
+        Abc_Print( 1, "Total cones  = %6d.  Constraint cones = %6d. (%6.2f %%)\n",
+            p->nConesTotal, p->nConesConstr, 100.0*p->nConesConstr/p->nConesTotal );
+        Abc_Print( 1, "Total equivs = %6d.  Removed equivs   = %6d. (%6.2f %%)\n",
+            p->nEquivsTotal, p->nEquivsConstr, 100.0*p->nEquivsConstr/p->nEquivsTotal );
+        Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%).  RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n",
+            p->nNodesBegC, p->nNodesEndC, 100.0*(p->nNodesBegC-p->nNodesEndC)/(p->nNodesBegC?p->nNodesBegC:1),
+            p->nRegsBegC, p->nRegsEndC,   100.0*(p->nRegsBegC-p->nRegsEndC)/(p->nRegsBegC?p->nRegsBegC:1) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManCleanup( Ssw_Man_t * p )
+{
+//    Aig_ManCleanMarkAB( p->pAig );
+    assert( p->pMSat == NULL );
+    if ( p->pFrames )
+    {
+        Aig_ManCleanMarkAB( p->pFrames );
+        Aig_ManStop( p->pFrames );
+        p->pFrames = NULL;
+        memset( p->pNodeToFrames, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p->pAig) * p->nFrames );
+    }
+    if ( p->vSimInfo )
+    {
+        Vec_PtrFree( p->vSimInfo );
+        p->vSimInfo = NULL;
+    }
+    p->nConstrTotal = 0;
+    p->nConstrReduced = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the manager.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManStop( Ssw_Man_t * p )
+{
+    ABC_FREE( p->pVisited );
+    if ( p->pPars->fVerbose )//&& p->pPars->nStepsMax == -1 )
+        Ssw_ManPrintStats( p );
+    if ( p->ppClasses )
+        Ssw_ClassesStop( p->ppClasses );
+    if ( p->pSml )
+        Ssw_SmlStop( p->pSml );
+    if ( p->vDiffPairs )
+        Vec_IntFree( p->vDiffPairs );
+    if ( p->vInits )
+        Vec_IntFree( p->vInits );
+    Vec_PtrFree( p->vResimConsts );
+    Vec_PtrFree( p->vResimClasses );
+    Vec_PtrFree( p->vNewLos );
+    Vec_IntFree( p->vNewPos );
+    Vec_PtrFree( p->vCommon );
+    ABC_FREE( p->pNodeToFrames );
+    ABC_FREE( p->pPatWords );
+    ABC_FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswPairs.c b/abc-build/src/proof/ssw/sswPairs.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswPairs.c
@@ -0,0 +1,480 @@
+/**CFile****************************************************************
+
+  FileName    [sswPairs.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [Calls to the SAT solver.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswPairs.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Reports the status of the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_MiterStatus( Aig_Man_t * p, int fVerbose )
+{
+    Aig_Obj_t * pObj, * pChild;
+    int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0;
+//    if ( p->pData )
+//        return 0;
+    Saig_ManForEachPo( p, pObj, i )
+    {
+        pChild = Aig_ObjChild0(pObj);
+        // check if the output is constant 0
+        if ( pChild == Aig_ManConst0(p) )
+        {
+            CountConst0++;
+            continue;
+        }
+        // check if the output is constant 1
+        if ( pChild == Aig_ManConst1(p) )
+        {
+            CountNonConst0++;
+            continue;
+        }
+        // check if the output is a primary input
+        if ( p->nRegs == 0 && Aig_ObjIsCi(Aig_Regular(pChild)) )
+        {
+            CountNonConst0++;
+            continue;
+        }
+        // check if the output can be not constant 0
+        if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) )
+        {
+            CountNonConst0++;
+            continue;
+        }
+        CountUndecided++;
+    }
+
+    if ( fVerbose )
+    {
+        Abc_Print( 1, "Miter has %d outputs. ", Saig_ManPoNum(p) );
+        Abc_Print( 1, "Const0 = %d.  ", CountConst0 );
+        Abc_Print( 1, "NonConst0 = %d.  ", CountNonConst0 );
+        Abc_Print( 1, "Undecided = %d.  ", CountUndecided );
+        Abc_Print( 1, "\n" );
+    }
+
+    if ( CountNonConst0 )
+        return 0;
+    if ( CountUndecided )
+        return -1;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfer equivalent pairs to the miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Ssw_TransferSignalPairs( Aig_Man_t * pMiter, Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2 )
+{
+    Vec_Int_t * vIds;
+    Aig_Obj_t * pObj1, * pObj2;
+    Aig_Obj_t * pObj1m, * pObj2m;
+    int i;
+    vIds = Vec_IntAlloc( 2 * Vec_IntSize(vIds1) );
+    for ( i = 0; i < Vec_IntSize(vIds1); i++ )
+    {
+        pObj1 = Aig_ManObj( pAig1, Vec_IntEntry(vIds1, i) );
+        pObj2 = Aig_ManObj( pAig2, Vec_IntEntry(vIds2, i) );
+        pObj1m = Aig_Regular((Aig_Obj_t *)pObj1->pData);
+        pObj2m = Aig_Regular((Aig_Obj_t *)pObj2->pData);
+        assert( pObj1m && pObj2m );
+        if ( pObj1m == pObj2m )
+            continue;
+        if ( pObj1m->Id < pObj2m->Id )
+        {
+            Vec_IntPush( vIds, pObj1m->Id );
+            Vec_IntPush( vIds, pObj2m->Id );
+        }
+        else
+        {
+            Vec_IntPush( vIds, pObj2m->Id );
+            Vec_IntPush( vIds, pObj1m->Id );
+        }
+    }
+    return vIds;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transform pairs into class representation.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t ** Ssw_TransformPairsIntoTempClasses( Vec_Int_t * vPairs, int nObjNumMax )
+{
+    Vec_Int_t ** pvClasses;   // vector of classes
+    int * pReprs;             // mapping nodes into their representatives
+    int Entry, idObj, idRepr, idReprObj, idReprRepr, i;
+    // allocate data-structures
+    pvClasses = ABC_CALLOC( Vec_Int_t *, nObjNumMax );
+    pReprs    = ABC_ALLOC( int, nObjNumMax );
+    for ( i = 0; i < nObjNumMax; i++ )
+        pReprs[i] = -1;
+    // consider pairs
+    for ( i = 0; i < Vec_IntSize(vPairs); i += 2 )
+    {
+        // get both objects
+        idRepr = Vec_IntEntry( vPairs, i   );
+        idObj  = Vec_IntEntry( vPairs, i+1 );
+        assert( idObj > 0 );
+        assert( (pReprs[idRepr] == -1) || (pvClasses[pReprs[idRepr]] != NULL) );
+        assert( (pReprs[idObj]  == -1) || (pvClasses[pReprs[idObj] ] != NULL) );
+        // get representatives of both objects
+        idReprRepr = pReprs[idRepr];
+        idReprObj  = pReprs[idObj];
+        // check different situations
+        if ( idReprRepr == -1 && idReprObj == -1 )
+        {   // they do not have classes
+            // create a class
+            pvClasses[idRepr] = Vec_IntAlloc( 4 );
+            Vec_IntPush( pvClasses[idRepr], idRepr );
+            Vec_IntPush( pvClasses[idRepr], idObj );
+            pReprs[ idRepr ] = idRepr;
+            pReprs[ idObj  ] = idRepr;
+        }
+        else if ( idReprRepr >= 0 && idReprObj == -1 )
+        {   // representative has a class
+            // add iObj to the same class
+            Vec_IntPushUniqueOrder( pvClasses[idReprRepr], idObj );
+            pReprs[ idObj ] = idReprRepr;
+        }
+        else if ( idReprRepr == -1 && idReprObj >= 0 )
+        {   // object has a class
+            assert( idReprObj != idRepr );
+            if ( idReprObj < idRepr )
+            { // add idRepr to the same class
+                Vec_IntPushUniqueOrder( pvClasses[idReprObj], idRepr );
+                pReprs[ idRepr ] = idReprObj;
+            }
+            else // if ( idReprObj > idRepr )
+            { // make idRepr new representative
+                Vec_IntPushFirst( pvClasses[idReprObj], idRepr );
+                pvClasses[idRepr] = pvClasses[idReprObj];
+                pvClasses[idReprObj] = NULL;
+                // set correct representatives of each node
+                Vec_IntForEachEntry( pvClasses[idRepr], Entry, i )
+                    pReprs[ Entry ] = idRepr;
+            }
+        }
+        else // if ( idReprRepr >= 0 && idReprObj >= 0 )
+        {   // both have classes
+            if ( idReprRepr == idReprObj )
+            {  // the classes are the same
+                // nothing to do
+            }
+            else
+            {  // the classes are different
+                // find the repr of the new class
+                if ( idReprRepr < idReprObj )
+                {
+                    Vec_IntForEachEntry( pvClasses[idReprObj], Entry, i )
+                    {
+                        Vec_IntPushUniqueOrder( pvClasses[idReprRepr], Entry );
+                        pReprs[ Entry ] = idReprRepr;
+                    }
+                    Vec_IntFree( pvClasses[idReprObj] );
+                    pvClasses[idReprObj] = NULL;
+                }
+                else // if ( idReprRepr > idReprObj )
+                {
+                    Vec_IntForEachEntry( pvClasses[idReprRepr], Entry, i )
+                    {
+                        Vec_IntPushUniqueOrder( pvClasses[idReprObj], Entry );
+                        pReprs[ Entry ] = idReprObj;
+                    }
+                    Vec_IntFree( pvClasses[idReprRepr] );
+                    pvClasses[idReprRepr] = NULL;
+                }
+            }
+        }
+    }
+    ABC_FREE( pReprs );
+    return pvClasses;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_FreeTempClasses( Vec_Int_t ** pvClasses, int nObjNumMax )
+{
+    int i;
+    for ( i = 0; i < nObjNumMax; i++ )
+        if ( pvClasses[i] )
+            Vec_IntFree( pvClasses[i] );
+    ABC_FREE( pvClasses );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs signal correspondence for the miter of two AIGs with node pairs defined.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Ssw_SignalCorrespondenceWithPairs( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2, Ssw_Pars_t * pPars )
+{
+    Ssw_Man_t * p;
+    Aig_Man_t * pAigNew, * pMiter;
+    Ssw_Pars_t Pars;
+    Vec_Int_t * vPairs;
+    Vec_Int_t ** pvClasses;
+    assert( Vec_IntSize(vIds1) == Vec_IntSize(vIds2) );
+    // create sequential miter
+    pMiter = Saig_ManCreateMiter( pAig1, pAig2, 0 );
+    Aig_ManCleanup( pMiter );
+    // transfer information to the miter
+    vPairs = Ssw_TransferSignalPairs( pMiter, pAig1, pAig2, vIds1, vIds2 );
+    // create representation of the classes
+    pvClasses = Ssw_TransformPairsIntoTempClasses( vPairs, Aig_ManObjNumMax(pMiter) );
+    Vec_IntFree( vPairs );
+    // if parameters are not given, create them
+    if ( pPars == NULL )
+        Ssw_ManSetDefaultParams( pPars = &Pars );
+    // start the induction manager
+    p = Ssw_ManCreate( pMiter, pPars );
+    // create equivalence classes using these IDs
+    p->ppClasses = Ssw_ClassesPreparePairs( pMiter, pvClasses );
+    p->pSml = Ssw_SmlStart( pMiter, 0, p->nFrames + p->pPars->nFramesAddSim, 1 );
+    Ssw_ClassesSetData( p->ppClasses, p->pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord );
+    // perform refinement of classes
+    pAigNew = Ssw_SignalCorrespondenceRefine( p );
+    // cleanup
+    Ssw_FreeTempClasses( pvClasses, Aig_ManObjNumMax(pMiter) );
+    Ssw_ManStop( p );
+    Aig_ManStop( pMiter );
+    return pAigNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Runs inductive SEC for the miter of two AIGs with node pairs defined.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Ssw_SignalCorrespondeceTestPairs( Aig_Man_t * pAig )
+{
+    Aig_Man_t * pAigNew, * pAigRes;
+    Ssw_Pars_t Pars, * pPars = &Pars;
+    Vec_Int_t * vIds1, * vIds2;
+    Aig_Obj_t * pObj, * pRepr;
+    int RetValue, i;
+    abctime clk = Abc_Clock();
+    Ssw_ManSetDefaultParams( pPars );
+    pPars->fVerbose = 1;
+    pAigNew = Ssw_SignalCorrespondence( pAig, pPars );
+    // record pairs of equivalent nodes
+    vIds1 = Vec_IntAlloc( Aig_ManObjNumMax(pAig) );
+    vIds2 = Vec_IntAlloc( Aig_ManObjNumMax(pAig) );
+    Aig_ManForEachObj( pAig, pObj, i )
+    {
+        pRepr = Aig_Regular((Aig_Obj_t *)pObj->pData);
+        if ( pRepr == NULL )
+            continue;
+        if ( Aig_ManObj(pAigNew, pRepr->Id) == NULL )
+            continue;
+/*
+        if ( Aig_ObjIsNode(pObj) )
+            Abc_Print( 1, "n " );
+        else if ( Saig_ObjIsPi(pAig, pObj) )
+            Abc_Print( 1, "pi " );
+        else if ( Saig_ObjIsLo(pAig, pObj) )
+            Abc_Print( 1, "lo " );
+*/
+        Vec_IntPush( vIds1, Aig_ObjId(pObj) );
+        Vec_IntPush( vIds2, Aig_ObjId(pRepr) );
+    }
+    Abc_Print( 1, "Recorded %d pairs (before: %d  after: %d).\n", Vec_IntSize(vIds1), Aig_ManObjNumMax(pAig), Aig_ManObjNumMax(pAigNew) );
+    // try the new AIGs
+    pAigRes = Ssw_SignalCorrespondenceWithPairs( pAig, pAigNew, vIds1, vIds2, pPars );
+    Vec_IntFree( vIds1 );
+    Vec_IntFree( vIds2 );
+    // report the results
+    RetValue = Ssw_MiterStatus( pAigRes, 1 );
+    if ( RetValue == 1 )
+        Abc_Print( 1, "Verification successful.  " );
+    else if ( RetValue == 0 )
+        Abc_Print( 1, "Verification failed with the counter-example.  " );
+    else
+        Abc_Print( 1, "Verification UNDECIDED. Remaining registers %d (total %d).  ",
+            Aig_ManRegNum(pAigRes), Aig_ManRegNum(pAig) + Aig_ManRegNum(pAigNew) );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    // cleanup
+    Aig_ManStop( pAigNew );
+    return pAigRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Runs inductive SEC for the miter of two AIGs with node pairs defined.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SecWithPairs( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2, Ssw_Pars_t * pPars )
+{
+    Aig_Man_t * pAigRes;
+    int RetValue;
+    abctime clk = Abc_Clock();
+    assert( vIds1 != NULL && vIds2 != NULL );
+    // try the new AIGs
+    Abc_Print( 1, "Performing specialized verification with node pairs.\n" );
+    pAigRes = Ssw_SignalCorrespondenceWithPairs( pAig1, pAig2, vIds1, vIds2, pPars );
+    // report the results
+    RetValue = Ssw_MiterStatus( pAigRes, 1 );
+    if ( RetValue == 1 )
+        Abc_Print( 1, "Verification successful.  " );
+    else if ( RetValue == 0 )
+        Abc_Print( 1, "Verification failed with a counter-example.  " );
+    else
+        Abc_Print( 1, "Verification UNDECIDED. The number of remaining regs = %d (total = %d).  ",
+            Aig_ManRegNum(pAigRes), Aig_ManRegNum(pAig1) + Aig_ManRegNum(pAig2) );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    // cleanup
+    Aig_ManStop( pAigRes );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Runs inductive SEC for the miter of two AIGs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SecGeneral( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Ssw_Pars_t * pPars )
+{
+    Aig_Man_t * pAigRes, * pMiter;
+    int RetValue;
+    abctime clk = Abc_Clock();
+    // try the new AIGs
+    Abc_Print( 1, "Performing general verification without node pairs.\n" );
+    pMiter = Saig_ManCreateMiter( pAig1, pAig2, 0 );
+    Aig_ManCleanup( pMiter );
+    pAigRes = Ssw_SignalCorrespondence( pMiter, pPars );
+    Aig_ManStop( pMiter );
+    // report the results
+    RetValue = Ssw_MiterStatus( pAigRes, 1 );
+    if ( RetValue == 1 )
+        Abc_Print( 1, "Verification successful.  " );
+    else if ( RetValue == 0 )
+        Abc_Print( 1, "Verification failed with a counter-example.  " );
+    else
+        Abc_Print( 1, "Verification UNDECIDED. The number of remaining regs = %d (total = %d).  ",
+            Aig_ManRegNum(pAigRes), Aig_ManRegNum(pAig1) + Aig_ManRegNum(pAig2) );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    // cleanup
+    Aig_ManStop( pAigRes );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Runs inductive SEC for the miter of two AIGs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SecGeneralMiter( Aig_Man_t * pMiter, Ssw_Pars_t * pPars )
+{
+    Aig_Man_t * pAigRes;
+    int RetValue;
+    abctime clk = Abc_Clock();
+    // try the new AIGs
+//    Abc_Print( 1, "Performing general verification without node pairs.\n" );
+    pAigRes = Ssw_SignalCorrespondence( pMiter, pPars );
+    // report the results
+    RetValue = Ssw_MiterStatus( pAigRes, 1 );
+    if ( RetValue == 1 )
+        Abc_Print( 1, "Verification successful.  " );
+    else if ( RetValue == 0 )
+        Abc_Print( 1, "Verification failed with a counter-example.  " );
+    else
+        Abc_Print( 1, "Verification UNDECIDED. The number of remaining regs = %d (total = %d).  ",
+            Aig_ManRegNum(pAigRes), Aig_ManRegNum(pMiter) );
+    ABC_PRT( "Time", Abc_Clock() - clk );
+    // cleanup
+    Aig_ManStop( pAigRes );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswPart.c b/abc-build/src/proof/ssw/sswPart.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswPart.c
@@ -0,0 +1,140 @@
+/**CFile****************************************************************
+
+  FileName    [sswPart.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [Partitioned signal correspondence.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswPart.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+#include "aig/ioa/ioa.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs partitioned sequential SAT sweeping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Ssw_SignalCorrespondencePart( Aig_Man_t * pAig, Ssw_Pars_t * pPars )
+{
+    int fPrintParts = 0;
+    char Buffer[100];
+    Aig_Man_t * pTemp, * pNew;
+    Vec_Ptr_t * vResult;
+    Vec_Int_t * vPart;
+    int * pMapBack;
+    int i, nCountPis, nCountRegs;
+    int nClasses, nPartSize, fVerbose;
+    abctime clk = Abc_Clock();
+    if ( pPars->fConstrs )
+    {
+        Abc_Print( 1, "Cannot use partitioned computation with constraints.\n" );
+        return NULL;
+    }
+    // save parameters
+    nPartSize = pPars->nPartSize; pPars->nPartSize = 0;
+    fVerbose  = pPars->fVerbose;  pPars->fVerbose  = 0;
+    // generate partitions
+    if ( pAig->vClockDoms )
+    {
+        // divide large clock domains into separate partitions
+        vResult = Vec_PtrAlloc( 100 );
+        Vec_PtrForEachEntry( Vec_Int_t *, (Vec_Ptr_t *)pAig->vClockDoms, vPart, i )
+        {
+            if ( nPartSize && Vec_IntSize(vPart) > nPartSize )
+                Aig_ManPartDivide( vResult, vPart, nPartSize, pPars->nOverSize );
+            else
+                Vec_PtrPush( vResult, Vec_IntDup(vPart) );
+        }
+    }
+    else
+        vResult = Aig_ManRegPartitionSimple( pAig, nPartSize, pPars->nOverSize );
+//    vResult = Aig_ManPartitionSmartRegisters( pAig, nPartSize, 0 ); 
+//    vResult = Aig_ManRegPartitionSmart( pAig, nPartSize );
+    if ( fPrintParts )
+    {
+        // print partitions
+        Abc_Print( 1, "Simple partitioning. %d partitions are saved:\n", Vec_PtrSize(vResult) );
+        Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i )
+        {
+//            extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact );
+            sprintf( Buffer, "part%03d.aig", i );
+            pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, NULL );
+            Ioa_WriteAiger( pTemp, Buffer, 0, 0 );
+            Abc_Print( 1, "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n",
+                i, Vec_IntSize(vPart), Aig_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp) );
+            Aig_ManStop( pTemp );
+        }
+    }
+
+    // perform SSW with partitions
+    Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) );
+    Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i )
+    {
+        pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, &pMapBack );
+        Aig_ManSetRegNum( pTemp, pTemp->nRegs );
+        // create the projection of 1-hot registers
+        if ( pAig->vOnehots )
+            pTemp->vOnehots = Aig_ManRegProjectOnehots( pAig, pTemp, pAig->vOnehots, fVerbose );
+        // run SSW
+        if (nCountPis>0) {
+            pNew = Ssw_SignalCorrespondence( pTemp, pPars );
+            nClasses = Aig_TransferMappedClasses( pAig, pTemp, pMapBack );
+            if ( fVerbose )
+                Abc_Print( 1, "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. It = %3d. Cl = %5d.\n",
+                    i, Vec_IntSize(vPart), Aig_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp), pPars->nIters, nClasses );
+            Aig_ManStop( pNew );
+        }
+        Aig_ManStop( pTemp );
+        ABC_FREE( pMapBack );
+    }
+    // remap the AIG
+    pNew = Aig_ManDupRepr( pAig, 0 );
+    Aig_ManSeqCleanup( pNew );
+//    Aig_ManPrintStats( pAig );
+//    Aig_ManPrintStats( pNew );
+    Vec_VecFree( (Vec_Vec_t *)vResult );
+    pPars->nPartSize = nPartSize;
+    pPars->fVerbose = fVerbose;
+    if ( fVerbose )
+    {
+        ABC_PRT( "Total time", Abc_Clock() - clk );
+    }
+    return pNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswRarity.c b/abc-build/src/proof/ssw/sswRarity.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswRarity.c
@@ -0,0 +1,1385 @@
+/**CFile****************************************************************
+
+  FileName    [sswRarity.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [Rarity-driven refinement of equivalence classes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswRarity.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+#include "aig/gia/giaAig.h"
+#include "base/main/main.h"
+#include "sat/bmc/bmc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ssw_RarMan_t_ Ssw_RarMan_t;
+struct Ssw_RarMan_t_
+{
+    // parameters
+    Ssw_RarPars_t* pPars;
+    int            nGroups;      // the number of flop groups
+    int            nWordsReg;    // the number of words in the registers
+    // internal data
+    Aig_Man_t *    pAig;         // AIG with equivalence classes
+    Ssw_Cla_t *    ppClasses;    // equivalence classes
+    Vec_Int_t *    vInits;       // initial state
+    // simulation data
+    word *         pObjData;     // simulation info for each obj
+    word *         pPatData;     // pattern data for each reg
+    // candidates to update
+    Vec_Ptr_t *    vUpdConst;    // constant 1 candidates
+    Vec_Ptr_t *    vUpdClass;    // class representatives
+    // rarity data
+    int *          pRarity;      // occur counts for patterns in groups
+    double *       pPatCosts;    // pattern costs
+    // best patterns
+    Vec_Int_t *    vPatBests;    // best patterns
+    int            iFailPo;      // failed primary output
+    int            iFailPat;     // failed pattern
+    // counter-examples
+    Vec_Ptr_t *    vCexes;
+};
+
+
+static inline int  Ssw_RarGetBinPat( Ssw_RarMan_t * p, int iBin, int iPat )
+{
+    assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->pPars->nBinSize );
+    assert( iPat >= 0 && iPat < (1 << p->pPars->nBinSize) );
+    return p->pRarity[iBin * (1 << p->pPars->nBinSize) + iPat];
+}
+static inline void Ssw_RarSetBinPat( Ssw_RarMan_t * p, int iBin, int iPat, int Value )
+{
+    assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->pPars->nBinSize );
+    assert( iPat >= 0 && iPat < (1 << p->pPars->nBinSize) );
+    p->pRarity[iBin * (1 << p->pPars->nBinSize) + iPat] = Value;
+}
+static inline void Ssw_RarAddToBinPat( Ssw_RarMan_t * p, int iBin, int iPat )
+{
+    assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->pPars->nBinSize );
+    assert( iPat >= 0 && iPat < (1 << p->pPars->nBinSize) );
+    p->pRarity[iBin * (1 << p->pPars->nBinSize) + iPat]++;
+}
+
+static inline int    Ssw_RarBitWordNum( int nBits )             { return (nBits>>6) + ((nBits&63) > 0);  }
+
+static inline word * Ssw_RarObjSim( Ssw_RarMan_t * p, int Id )  { assert( Id < Aig_ManObjNumMax(p->pAig) ); return p->pObjData + p->pPars->nWords * Id;    }
+static inline word * Ssw_RarPatSim( Ssw_RarMan_t * p, int Id )  { assert( Id < 64 * p->pPars->nWords );     return p->pPatData + p->nWordsReg * Id;        }
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_RarSetDefaultParams( Ssw_RarPars_t * p )
+{
+    memset( p, 0, sizeof(Ssw_RarPars_t) );
+    p->nFrames       =  20;
+    p->nWords        =  50;
+    p->nBinSize      =   8;
+    p->nRounds       =   0;
+    p->nRestart      =   0;
+    p->nRandSeed     =   0;
+    p->TimeOut       =   0;
+    p->TimeOutGap    =   0;
+    p->fSolveAll     =   0;
+    p->fDropSatOuts  =   0;
+    p->fSetLastState =   0;
+    p->fVerbose      =   0;
+    p->fNotVerbose   =   0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares random number generator.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_RarManPrepareRandom( int nRandSeed )
+{
+    int i;
+    Aig_ManRandom( 1 );
+    for ( i = 0; i < nRandSeed; i++ )
+        Aig_ManRandom( 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Initializes random primary inputs.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_RarManAssingRandomPis( Ssw_RarMan_t * p )
+{
+    word * pSim;
+    Aig_Obj_t * pObj;
+    int w, i;
+    Saig_ManForEachPi( p->pAig, pObj, i )
+    {
+        pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+        for ( w = 0; w < p->pPars->nWords; w++ )
+            pSim[w] = Aig_ManRandom64(0);
+//        pSim[0] <<= 1;
+//        pSim[0] = (pSim[0] << 2) | 2;
+        pSim[0] = (pSim[0] << 4) | ((i & 1) ? 0xA : 0xC);
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives the counter-example.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Ssw_RarDeriveCex( Ssw_RarMan_t * p, int iFrame, int iPo, int iPatFinal, int fVerbose )
+{
+    Abc_Cex_t * pCex;
+    Aig_Obj_t * pObj;
+    Vec_Int_t * vTrace;
+    word * pSim;
+    int i, r, f, iBit, iPatThis;
+    // compute the pattern sequence
+    iPatThis = iPatFinal;
+    vTrace = Vec_IntStartFull( iFrame / p->pPars->nFrames + 1 );
+    Vec_IntWriteEntry( vTrace, iFrame / p->pPars->nFrames, iPatThis );
+    for ( r = iFrame / p->pPars->nFrames - 1; r >= 0; r-- )
+    {
+        iPatThis = Vec_IntEntry( p->vPatBests, r * p->pPars->nWords + iPatThis / 64 );
+        Vec_IntWriteEntry( vTrace, r, iPatThis );
+    }
+    // create counter-example
+    pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), iFrame+1 );
+    pCex->iFrame = iFrame;
+    pCex->iPo = iPo;
+    // insert the bits
+    iBit = Aig_ManRegNum(p->pAig);
+    for ( f = 0; f <= iFrame; f++ )
+    {
+        Ssw_RarManAssingRandomPis( p );
+        iPatThis = Vec_IntEntry( vTrace, f / p->pPars->nFrames );
+        Saig_ManForEachPi( p->pAig, pObj, i )
+        {
+            pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+            if ( Abc_InfoHasBit( (unsigned *)pSim, iPatThis ) )
+                Abc_InfoSetBit( pCex->pData, iBit );
+            iBit++;
+        }
+    }
+    Vec_IntFree( vTrace );
+    assert( iBit == pCex->nBits );
+    // verify the counter example
+    if ( !Saig_ManVerifyCex( p->pAig, pCex ) )
+    {
+        Abc_Print( 1, "Ssw_RarDeriveCex(): Counter-example is invalid.\n" );
+//        Abc_CexFree( pCex );
+//        pCex = NULL;
+    }
+    else
+    {
+//      Abc_Print( 1, "Counter-example verification is successful.\n" );
+    }
+    return pCex;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Transposing 32-bit matrix.]
+
+  Description [Borrowed from "Hacker's Delight", by Henry Warren.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void transpose32( unsigned A[32] )
+{
+    int j, k;
+    unsigned t, m = 0x0000FFFF;
+    for ( j = 16; j != 0; j = j >> 1, m = m ^ (m << j) )
+    {
+        for ( k = 0; k < 32; k = (k + j + 1) & ~j )
+        {
+            t = (A[k] ^ (A[k+j] >> j)) & m;
+            A[k] = A[k] ^ t;
+            A[k+j] = A[k+j] ^ (t << j);
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transposing 64-bit matrix.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void transpose64( word A[64] )
+{
+    int j, k;
+    word t, m = 0x00000000FFFFFFFF;
+    for ( j = 32; j != 0; j = j >> 1, m = m ^ (m << j) )
+    {
+        for ( k = 0; k < 64; k = (k + j + 1) & ~j )
+        {
+            t = (A[k] ^ (A[k+j] >> j)) & m;
+            A[k] = A[k] ^ t;
+            A[k+j] = A[k+j] ^ (t << j);
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transposing 64-bit matrix.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void transpose64Simple( word A[64], word B[64] )
+{
+    int i, k;
+    for ( i = 0; i < 64; i++ )
+        B[i] = 0;
+    for ( i = 0; i < 64; i++ )
+    for ( k = 0; k < 64; k++ )
+        if ( (A[i] >> k) & 1 )
+            B[k] |= ((word)1 << (63-i));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Testing the transposing code.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void TransposeTest()
+{
+    word M[64], N[64];
+    int i;
+    abctime clk;
+    Aig_ManRandom64( 1 );
+//    for ( i = 0; i < 64; i++ )
+//        M[i] = Aig_ManRandom64( 0 );
+    for ( i = 0; i < 64; i++ )
+        M[i] = i? (word)0 : ~(word)0;
+//    for ( i = 0; i < 64; i++ )
+//        Extra_PrintBinary( stdout, (unsigned *)&M[i], 64 ), Abc_Print( 1, "\n" );
+
+    clk = Abc_Clock();
+    for ( i = 0; i < 100001; i++ )
+        transpose64Simple( M, N );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+
+    clk = Abc_Clock();
+    for ( i = 0; i < 100001; i++ )
+        transpose64( M );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+
+    for ( i = 0; i < 64; i++ )
+        if ( M[i] != N[i] )
+            Abc_Print( 1, "Mismatch\n" );
+/*
+    Abc_Print( 1, "\n" );
+    for ( i = 0; i < 64; i++ )
+        Extra_PrintBinary( stdout, (unsigned *)&M[i], 64 ), Abc_Print( 1, "\n" );
+    Abc_Print( 1, "\n" );
+    for ( i = 0; i < 64; i++ )
+        Extra_PrintBinary( stdout, (unsigned *)&N[i], 64 ), Abc_Print( 1, "\n" );
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transposing pObjData[ nRegs x nWords ] -> pPatData[ nWords x nRegs ].]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_RarTranspose( Ssw_RarMan_t * p )
+{
+    Aig_Obj_t * pObj;
+    word M[64];
+    int w, r, i;
+    for ( w = 0; w < p->pPars->nWords; w++ )
+    for ( r = 0; r < p->nWordsReg; r++ )
+    {
+        // save input
+        for ( i = 0; i < 64; i++ )
+        {
+            if ( r*64 + 63-i < Aig_ManRegNum(p->pAig) )
+            {
+                pObj = Saig_ManLi( p->pAig, r*64 + 63-i );
+                M[i] = Ssw_RarObjSim( p, Aig_ObjId(pObj) )[w];
+            }
+            else
+                M[i] = 0;
+        }
+        // transpose
+        transpose64( M );
+        // save output
+        for ( i = 0; i < 64; i++ )
+            Ssw_RarPatSim( p, w*64 + 63-i )[r] = M[i];
+    }
+/*
+    Saig_ManForEachLi( p->pAig, pObj, i )
+    {
+        word * pBitData = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+        Extra_PrintBinary( stdout, (unsigned *)pBitData, 64*p->pPars->nWords ); Abc_Print( 1, "\n" );
+    }
+    Abc_Print( 1, "\n" );
+    for ( i = 0; i < p->pPars->nWords*64; i++ )
+    {
+        word * pBitData = Ssw_RarPatSim( p, i );
+        Extra_PrintBinary( stdout, (unsigned *)pBitData, Aig_ManRegNum(p->pAig) ); Abc_Print( 1, "\n" );
+    }
+    Abc_Print( 1, "\n" );
+*/
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Sets random inputs and specialied flop outputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_RarManInitialize( Ssw_RarMan_t * p, Vec_Int_t * vInit )
+{
+    Aig_Obj_t * pObj, * pObjLi;
+    word * pSim, * pSimLi;
+    int w, i;
+    // constant
+    pObj = Aig_ManConst1( p->pAig );
+    pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+    for ( w = 0; w < p->pPars->nWords; w++ )
+        pSim[w] = ~(word)0;
+    // primary inputs
+    Ssw_RarManAssingRandomPis( p );
+    // flop outputs
+    if ( vInit )
+    {
+        assert( Vec_IntSize(vInit) == Saig_ManRegNum(p->pAig) * p->pPars->nWords );
+        Saig_ManForEachLo( p->pAig, pObj, i )
+        {
+            pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+            for ( w = 0; w < p->pPars->nWords; w++ )
+                pSim[w] = Vec_IntEntry(vInit, w * Saig_ManRegNum(p->pAig) + i) ? ~(word)0 : (word)0;
+        }
+    }
+    else
+    {
+        Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i )
+        {
+            pSimLi = Ssw_RarObjSim( p, Aig_ObjId(pObjLi) );
+            pSim   = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+            for ( w = 0; w < p->pPars->nWords; w++ )
+                pSim[w] = pSimLi[w];
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation info is composed of all zeros.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_RarManPoIsConst0( void * pMan, Aig_Obj_t * pObj )
+{
+    Ssw_RarMan_t * p = (Ssw_RarMan_t *)pMan;
+    word * pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+    int w;
+    for ( w = 0; w < p->pPars->nWords; w++ )
+        if ( pSim[w] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation info is composed of all zeros.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_RarManObjIsConst( void * pMan, Aig_Obj_t * pObj )
+{
+    Ssw_RarMan_t * p = (Ssw_RarMan_t *)pMan;
+    word * pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+    word Flip = pObj->fPhase ? ~(word)0 : 0;
+    int w;
+    for ( w = 0; w < p->pPars->nWords; w++ )
+        if ( pSim[w] ^ Flip )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation infos are equal.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_RarManObjsAreEqual( void * pMan, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+    Ssw_RarMan_t * p = (Ssw_RarMan_t *)pMan;
+    word * pSim0 = Ssw_RarObjSim( p, pObj0->Id );
+    word * pSim1 = Ssw_RarObjSim( p, pObj1->Id );
+    word Flip = (pObj0->fPhase != pObj1->fPhase) ? ~(word)0 : 0;
+    int w;
+    for ( w = 0; w < p->pPars->nWords; w++ )
+        if ( pSim0[w] ^ pSim1[w] ^ Flip )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash value of the node using its simulation info.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Ssw_RarManObjHashWord( void * pMan, Aig_Obj_t * pObj )
+{
+    Ssw_RarMan_t * p = (Ssw_RarMan_t *)pMan;
+    static int s_SPrimes[128] = {
+        1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459,
+        1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997,
+        2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543,
+        2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089,
+        3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671,
+        3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243,
+        4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871,
+        4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471,
+        5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073,
+        6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689,
+        6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309,
+        7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933,
+        8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+    };
+    unsigned * pSims;
+    unsigned uHash;
+    int i;
+    uHash = 0;
+    pSims = (unsigned *)Ssw_RarObjSim( p, pObj->Id );
+    for ( i = 0; i < 2 * p->pPars->nWords; i++ )
+        uHash ^= pSims[i] * s_SPrimes[i & 0x7F];
+    return uHash;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation info is composed of all zeros.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_RarManObjWhichOne( Ssw_RarMan_t * p, Aig_Obj_t * pObj )
+{
+    word * pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+    word Flip = 0;//pObj->fPhase ? ~(word)0 : 0; // bug fix!
+    int w, i;
+    for ( w = 0; w < p->pPars->nWords; w++ )
+        if ( pSim[w] ^ Flip )
+        {
+            for ( i = 0; i < 64; i++ )
+                if ( ((pSim[w] ^ Flip) >> i) & 1 )
+                    break;
+            assert( i < 64 );
+            return w * 64 + i;
+        }
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check if any of the POs becomes non-constant.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_RarManCheckNonConstOutputs( Ssw_RarMan_t * p, int iFrame, abctime Time )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    p->iFailPo  = -1;
+    p->iFailPat = -1;
+    Saig_ManForEachPo( p->pAig, pObj, i )
+    {
+        if ( p->pAig->nConstrs && i >= Saig_ManPoNum(p->pAig) - p->pAig->nConstrs )
+            break;
+        if ( p->vCexes && Vec_PtrEntry(p->vCexes, i) )
+            continue;
+        if ( Ssw_RarManPoIsConst0(p, pObj) )
+            continue;
+        p->iFailPo  = i;
+        p->iFailPat = Ssw_RarManObjWhichOne( p, pObj );
+        if ( !p->pPars->fSolveAll )
+            break;
+        // remember the one solved
+        p->pPars->nSolved++;
+        if ( p->vCexes == NULL )
+            p->vCexes = Vec_PtrStart( Saig_ManPoNum(p->pAig) );
+        assert( Vec_PtrEntry(p->vCexes, i) == NULL );
+        Vec_PtrWriteEntry( p->vCexes, i, (void *)(ABC_PTRINT_T)1 );
+        if ( p->pPars->pFuncOnFail && p->pPars->pFuncOnFail(i, NULL) )
+            return 2; // quitting due to callback
+        // print final report
+        if ( !p->pPars->fNotVerbose )
+        {
+            int nOutDigits = Abc_Base10Log( Saig_ManPoNum(p->pAig) );
+            Abc_Print( 1, "Output %*d was asserted in frame %4d (solved %*d out of %*d outputs).  ", 
+                nOutDigits, p->iFailPo, iFrame, 
+                nOutDigits, p->pPars->nSolved, 
+                nOutDigits, Saig_ManPoNum(p->pAig) );
+            Abc_PrintTime( 1, "Time", Time );
+        }
+    }
+    if ( p->iFailPo >= 0 ) // found CEX
+        return 1;
+    else
+        return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one round of simulation.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_RarManSimulate( Ssw_RarMan_t * p, Vec_Int_t * vInit, int fUpdate, int fFirst )
+{
+    Aig_Obj_t * pObj, * pRepr;
+    word * pSim, * pSim0, * pSim1;
+    word Flip, Flip0, Flip1;
+    int w, i;
+    // initialize
+    Ssw_RarManInitialize( p, vInit );
+    Vec_PtrClear( p->vUpdConst );
+    Vec_PtrClear( p->vUpdClass );
+    Aig_ManIncrementTravId( p->pAig );
+    // check comb inputs
+    if ( fUpdate )
+    Aig_ManForEachCi( p->pAig, pObj, i )
+    {
+        pRepr = Aig_ObjRepr(p->pAig, pObj);
+        if ( pRepr == NULL || Aig_ObjIsTravIdCurrent( p->pAig, pRepr ) )
+            continue;
+        if ( Ssw_RarManObjsAreEqual( p, pObj, pRepr ) )
+            continue;
+        // save for update
+        if ( pRepr == Aig_ManConst1(p->pAig) )
+            Vec_PtrPush( p->vUpdConst, pObj );
+        else
+        {
+            Vec_PtrPush( p->vUpdClass, pRepr );
+            Aig_ObjSetTravIdCurrent( p->pAig, pRepr );
+        }
+    }
+    // simulate
+    Aig_ManForEachNode( p->pAig, pObj, i )
+    {
+        pSim  = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+        pSim0 = Ssw_RarObjSim( p, Aig_ObjFaninId0(pObj) );
+        pSim1 = Ssw_RarObjSim( p, Aig_ObjFaninId1(pObj) );
+        Flip0 = Aig_ObjFaninC0(pObj) ? ~(word)0 : 0;
+        Flip1 = Aig_ObjFaninC1(pObj) ? ~(word)0 : 0;
+        for ( w = 0; w < p->pPars->nWords; w++ )
+            pSim[w] = (Flip0 ^ pSim0[w]) & (Flip1 ^ pSim1[w]);
+
+
+        if ( !fUpdate )
+            continue;
+        // check classes
+        pRepr = Aig_ObjRepr(p->pAig, pObj);
+        if ( pRepr == NULL || Aig_ObjIsTravIdCurrent( p->pAig, pRepr ) )
+            continue;
+        if ( Ssw_RarManObjsAreEqual( p, pObj, pRepr ) )
+            continue;
+        // save for update
+        if ( pRepr == Aig_ManConst1(p->pAig) )
+            Vec_PtrPush( p->vUpdConst, pObj );
+        else
+        {
+            Vec_PtrPush( p->vUpdClass, pRepr );
+            Aig_ObjSetTravIdCurrent( p->pAig, pRepr );
+        }
+    }
+    // transfer to POs
+    Aig_ManForEachCo( p->pAig, pObj, i )
+    {
+        pSim  = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+        pSim0 = Ssw_RarObjSim( p, Aig_ObjFaninId0(pObj) );
+        Flip  = Aig_ObjFaninC0(pObj) ? ~(word)0 : 0;
+        for ( w = 0; w < p->pPars->nWords; w++ )
+            pSim[w] = Flip ^ pSim0[w];
+    }
+    // refine classes
+    if ( fUpdate )
+    {
+        if ( fFirst )
+        {
+            Vec_Ptr_t * vCands = Vec_PtrAlloc( 1000 );
+            Aig_ManForEachObj( p->pAig, pObj, i )
+                if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) )
+                    Vec_PtrPush( vCands, pObj );
+            assert( Vec_PtrSize(vCands) == Ssw_ClassesCand1Num(p->ppClasses) );
+            Ssw_ClassesPrepareRehash( p->ppClasses, vCands, 0 );
+            Vec_PtrFree( vCands );
+        }
+        else
+        {
+            Ssw_ClassesRefineConst1Group( p->ppClasses, p->vUpdConst, 1 );
+            Ssw_ClassesRefineGroup( p->ppClasses, p->vUpdClass, 1 );
+        }
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Ssw_RarMan_t * Ssw_RarManStart( Aig_Man_t * pAig, Ssw_RarPars_t * pPars )
+{
+    Ssw_RarMan_t * p;
+//    if ( Aig_ManRegNum(pAig) < nBinSize || nBinSize <= 0 )
+//        return NULL;
+    p = ABC_CALLOC( Ssw_RarMan_t, 1 );
+    p->pAig      = pAig;
+    p->pPars     = pPars;
+    p->nGroups   = Aig_ManRegNum(pAig) / pPars->nBinSize;
+    p->pRarity   = ABC_CALLOC( int, (1 << pPars->nBinSize) * p->nGroups );
+    p->pPatCosts = ABC_CALLOC( double, p->pPars->nWords * 64 );
+    p->nWordsReg = Ssw_RarBitWordNum( Aig_ManRegNum(pAig) );
+    p->pObjData  = ABC_ALLOC( word, Aig_ManObjNumMax(pAig) * p->pPars->nWords );
+    p->pPatData  = ABC_ALLOC( word, 64 * p->pPars->nWords * p->nWordsReg );
+    p->vUpdConst = Vec_PtrAlloc( 100 );
+    p->vUpdClass = Vec_PtrAlloc( 100 );
+    p->vPatBests = Vec_IntAlloc( 100 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Ssw_RarManStop( Ssw_RarMan_t * p )
+{
+//    Vec_PtrFreeP( &p->vCexes );
+    if ( p->vCexes )
+    {
+        assert( p->pAig->vSeqModelVec == NULL );
+        p->pAig->vSeqModelVec = p->vCexes;
+        p->vCexes = NULL;
+    }
+    if ( p->ppClasses ) Ssw_ClassesStop( p->ppClasses );
+    Vec_IntFreeP( &p->vInits );
+    Vec_IntFreeP( &p->vPatBests );
+    Vec_PtrFreeP( &p->vUpdConst );
+    Vec_PtrFreeP( &p->vUpdClass );
+    ABC_FREE( p->pObjData );
+    ABC_FREE( p->pPatData );
+    ABC_FREE( p->pPatCosts );
+    ABC_FREE( p->pRarity );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Select best patterns.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Ssw_RarTransferPatterns( Ssw_RarMan_t * p, Vec_Int_t * vInits )
+{
+//    Aig_Obj_t * pObj;
+    unsigned char * pData;
+    unsigned * pPattern;
+    int i, k, Value;
+
+    // more data from regs to pats
+    Ssw_RarTranspose( p );
+
+    // update counters
+    for ( k = 0; k < p->pPars->nWords * 64; k++ )
+    {
+        pData = (unsigned char *)Ssw_RarPatSim( p, k );
+        for ( i = 0; i < p->nGroups; i++ )
+            Ssw_RarAddToBinPat( p, i, pData[i] );
+    }
+
+    // for each pattern
+    for ( k = 0; k < p->pPars->nWords * 64; k++ )
+    {
+        pData = (unsigned char *)Ssw_RarPatSim( p, k );
+        // find the cost of its values
+        p->pPatCosts[k] = 0.0;
+        for ( i = 0; i < p->nGroups; i++ )
+        {
+            Value = Ssw_RarGetBinPat( p, i, pData[i] );
+            assert( Value > 0 );
+            p->pPatCosts[k] += 1.0/(Value*Value);
+        }
+        // print the result
+//Abc_Print( 1, "%3d : %9.6f\n", k, p->pPatCosts[k] );
+    }
+
+    // choose as many as there are words
+    Vec_IntClear( vInits );
+    for ( i = 0; i < p->pPars->nWords; i++ )
+    {
+        // select the best
+        int iPatBest = -1;
+        double iCostBest = -ABC_INFINITY;
+        for ( k = 0; k < p->pPars->nWords * 64; k++ )
+            if ( iCostBest < p->pPatCosts[k] )
+            {
+                iCostBest = p->pPatCosts[k];
+                iPatBest  = k;
+            }
+        // remove from costs
+        assert( iPatBest >= 0 );
+        p->pPatCosts[iPatBest] = -ABC_INFINITY;
+        // set the flops
+        pPattern = (unsigned *)Ssw_RarPatSim( p, iPatBest );
+        for ( k = 0; k < Aig_ManRegNum(p->pAig); k++ )
+            Vec_IntPush( vInits, Abc_InfoHasBit(pPattern, k) );
+//Abc_Print( 1, "Best pattern %5d\n", iPatBest );
+        Vec_IntPush( p->vPatBests, iPatBest );
+    }
+    assert( Vec_IntSize(vInits) == Aig_ManRegNum(p->pAig) * p->pPars->nWords );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for one node.]
+
+  Description [Returns the fraiged node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Vec_Int_t * Ssw_RarFindStartingState( Aig_Man_t * pAig, Abc_Cex_t * pCex )
+{
+    Vec_Int_t * vInit;
+    Aig_Obj_t * pObj, * pObjLi;
+    int f, i, iBit;
+    // assign register outputs
+    Saig_ManForEachLi( pAig, pObj, i )
+        pObj->fMarkB = Abc_InfoHasBit( pCex->pData, i );
+    // simulate the timeframes
+    iBit = pCex->nRegs;
+    for ( f = 0; f <= pCex->iFrame; f++ )
+    {
+        // set the PI simulation information
+        Aig_ManConst1(pAig)->fMarkB = 1;
+        Saig_ManForEachPi( pAig, pObj, i )
+            pObj->fMarkB = Abc_InfoHasBit( pCex->pData, iBit++ );
+        Saig_ManForEachLiLo( pAig, pObjLi, pObj, i )
+            pObj->fMarkB = pObjLi->fMarkB;
+        // simulate internal nodes
+        Aig_ManForEachNode( pAig, pObj, i )
+            pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+                         & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+        // assign the COs
+        Aig_ManForEachCo( pAig, pObj, i )
+            pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) );
+    }
+    assert( iBit == pCex->nBits );
+    // check that the output failed as expected -- cannot check because it is not an SRM!
+//    pObj = Aig_ManCo( pAig, pCex->iPo );
+//    if ( pObj->fMarkB != 1 )
+//        Abc_Print( 1, "The counter-example does not refine the output.\n" );
+    // record the new pattern
+    vInit = Vec_IntAlloc( Saig_ManRegNum(pAig) );
+    Saig_ManForEachLo( pAig, pObj, i )
+    {
+//Abc_Print( 1, "%d", pObj->fMarkB );
+        Vec_IntPush( vInit, pObj->fMarkB );
+    }
+//Abc_Print( 1, "\n" );
+    Aig_ManCleanMarkB( pAig );
+    return vInit;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_RarCheckTrivial( Aig_Man_t * pAig, int fVerbose )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Saig_ManForEachPo( pAig, pObj, i )
+    {
+        if ( pAig->nConstrs && i >= Saig_ManPoNum(pAig) - pAig->nConstrs )
+            return 0;
+        if ( pObj->fPhase )
+        {
+            ABC_FREE( pAig->pSeqModel );
+            pAig->pSeqModel = Abc_CexAlloc( Aig_ManRegNum(pAig), Saig_ManPiNum(pAig), 1 );
+            pAig->pSeqModel->iPo = i;
+            if ( fVerbose )
+                Abc_Print( 1, "Output %d is trivally SAT in frame 0. \n", i );
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform sequential simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_RarSimulate( Aig_Man_t * pAig, Ssw_RarPars_t * pPars )
+{
+    int fTryBmc = 0;
+    int fMiter = 1;
+    Ssw_RarMan_t * p;
+    int r, f = -1;
+    abctime clk, clkTotal = Abc_Clock();
+    abctime nTimeToStop = pPars->TimeOut ? pPars->TimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0;
+    abctime timeLastSolved = 0;
+    int nNumRestart = 0;
+    int nSavedSeed = pPars->nRandSeed;
+    int RetValue = -1;
+    int iFrameFail = -1;
+    assert( Aig_ManRegNum(pAig) > 0 );
+    assert( Aig_ManConstrNum(pAig) == 0 );
+    ABC_FREE( pAig->pSeqModel );
+    // consider the case of empty AIG
+//    if ( Aig_ManNodeNum(pAig) == 0 )
+//        return -1;
+    // check trivially SAT miters
+//    if ( fMiter && Ssw_RarCheckTrivial( pAig, fVerbose ) )
+//        return 0;
+    if ( pPars->fVerbose )
+        Abc_Print( 1, "Rarity simulation with %d words, %d frames, %d rounds, %d restart, %d seed, and %d sec timeout.\n",
+            pPars->nWords, pPars->nFrames, pPars->nRounds, pPars->nRestart, pPars->nRandSeed, pPars->TimeOut );
+    // reset random numbers
+    Ssw_RarManPrepareRandom( nSavedSeed );
+
+    // create manager
+    p = Ssw_RarManStart( pAig, pPars );
+    p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) * pPars->nWords );
+
+    // perform simulation rounds
+    pPars->nSolved = 0;
+    timeLastSolved = Abc_Clock();
+    for ( r = 0; !pPars->nRounds || (nNumRestart * pPars->nRestart + r < pPars->nRounds); r++ )
+    {
+        clk = Abc_Clock();
+        if ( fTryBmc )
+        {
+            Aig_Man_t * pNewAig = Saig_ManDupWithPhase( pAig, p->vInits );
+            Saig_BmcPerform( pNewAig, 0, 100, 2000, 3, 0, 0, 1 /*fVerbose*/, 0, &iFrameFail, 0 );
+//            if ( pNewAig->pSeqModel != NULL )
+//                Abc_Print( 1, "BMC has found a counter-example in frame %d.\n", iFrameFail );
+            Aig_ManStop( pNewAig );
+        }
+        // simulate
+        for ( f = 0; f < pPars->nFrames; f++ )
+        {
+            Ssw_RarManSimulate( p, f ? NULL : p->vInits, 0, 0 );
+            if ( fMiter )
+            {
+                int Status = Ssw_RarManCheckNonConstOutputs(p, r * p->pPars->nFrames + f, Abc_Clock() - clkTotal);
+                if ( Status == 2 )
+                {
+                    Abc_Print( 1, "Quitting due to callback on fail.\n" );
+                    goto finish;
+                }
+                if ( Status == 1 ) // found CEX
+                {
+                    RetValue = 0;
+                    if ( !pPars->fSolveAll )
+                    {
+                        if ( pPars->fVerbose ) Abc_Print( 1, "\n" );
+        //                Abc_Print( 1, "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames );
+                        Ssw_RarManPrepareRandom( nSavedSeed );
+                        if ( pPars->fVerbose )
+                            Abc_Print( 1, "Simulated %d frames for %d rounds with %d restarts.\n", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart );
+                        pAig->pSeqModel = Ssw_RarDeriveCex( p, r * p->pPars->nFrames + f, p->iFailPo, p->iFailPat, pPars->fVerbose );
+                        // print final report
+                        Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.  ", pAig->pSeqModel->iPo, pAig->pName, pAig->pSeqModel->iFrame );
+                        Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+                        goto finish;
+                    }
+                    timeLastSolved = Abc_Clock();
+                }
+                // else - did not find a counter example
+            }
+            // check timeout
+            if ( pPars->TimeOut && Abc_Clock() > nTimeToStop )
+            {
+                if ( !pPars->fSilent )
+                {
+                if ( pPars->fVerbose && !pPars->fSolveAll ) Abc_Print( 1, "\n" );
+                Abc_Print( 1, "Simulated %d frames for %d rounds with %d restarts and solved %d outputs.  ", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart, pPars->nSolved );
+                Abc_Print( 1, "Reached timeout (%d sec).\n",  pPars->TimeOut );
+                }
+                goto finish;
+            }
+            if ( pPars->TimeOutGap && timeLastSolved && Abc_Clock() > timeLastSolved + pPars->TimeOutGap * CLOCKS_PER_SEC )
+            {
+                if ( !pPars->fSilent )
+                {
+                if ( pPars->fVerbose && !pPars->fSolveAll ) Abc_Print( 1, "\n" );
+                Abc_Print( 1, "Simulated %d frames for %d rounds with %d restarts and solved %d outputs.  ", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart, pPars->nSolved );
+                Abc_Print( 1, "Reached gap timeout (%d sec).\n",  pPars->TimeOutGap );
+                }
+                goto finish;
+            }
+            // check if all outputs are solved by now
+            if ( pPars->fSolveAll && p->vCexes && Vec_PtrCountZero(p->vCexes) == 0 )
+                goto finish;
+        }
+        // get initialization patterns
+        if ( pPars->nRestart && r == pPars->nRestart )
+        {
+            r = -1;
+            nSavedSeed = (nSavedSeed + 1) % 1000;
+            Ssw_RarManPrepareRandom( nSavedSeed );
+            Vec_IntFill( p->vInits, Aig_ManRegNum(pAig) * pPars->nWords, 0 );
+            nNumRestart++;
+            Vec_IntClear( p->vPatBests );
+            // clean rarity info
+//            memset( p->pRarity, 0, sizeof(int) * (1 << nBinSize) * p->nGroups );
+        }
+        else
+            Ssw_RarTransferPatterns( p, p->vInits );
+        // printout
+        if ( pPars->fVerbose )
+        {
+            if ( pPars->fSolveAll )
+            {
+                Abc_Print( 1, "Starts =%6d   ",  nNumRestart );
+                Abc_Print( 1, "Rounds =%6d   ",  nNumRestart * pPars->nRestart + ((r==-1)?0:r) );
+                Abc_Print( 1, "Frames =%6d   ", (nNumRestart * pPars->nRestart + r) * pPars->nFrames );
+                Abc_Print( 1, "CEX =%6d (%6.2f %%)   ", pPars->nSolved, 100.0*pPars->nSolved/Saig_ManPoNum(p->pAig) );
+                Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+            }
+            else
+                Abc_Print( 1, "." );
+        }
+
+    }
+finish:
+    if ( pPars->fSetLastState && p->vInits )
+    {
+        assert( Vec_IntSize(p->vInits) % Aig_ManRegNum(pAig) == 0 );
+        Vec_IntShrink( p->vInits, Aig_ManRegNum(pAig) );
+        pAig->pData = p->vInits;  p->vInits = NULL;
+    }
+    if ( pPars->nSolved )
+    {
+/*
+        if ( !pPars->fSilent )
+        {
+        if ( pPars->fVerbose && !pPars->fSolveAll ) Abc_Print( 1, "\n" );
+        Abc_Print( 1, "Simulation of %d frames for %d rounds with %d restarts asserted %d (out of %d) POs.    ", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart, pPars->nSolved, Saig_ManPoNum(p->pAig) );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+        }
+*/
+    }
+    else if ( r == pPars->nRounds && f == pPars->nFrames )
+    {
+        if ( !pPars->fSilent )
+        {
+        if ( pPars->fVerbose ) Abc_Print( 1, "\n" );
+        Abc_Print( 1, "Simulation of %d frames for %d rounds with %d restarts did not assert POs.    ", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+        }
+    }
+    // cleanup
+    Ssw_RarManStop( p );
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derive random flop permutation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Ssw_RarRandomPermFlop( int nFlops, int nUnused )
+{
+    Vec_Int_t * vPerm;
+    int i, k, * pArray;
+    srand( 1 );
+    printf( "Generating random permutation of %d flops.\n", nFlops );
+    vPerm = Vec_IntStartNatural( nFlops );
+    pArray = Vec_IntArray( vPerm );
+    for ( i = 0; i < nFlops; i++ )
+    {
+        k = rand() % nFlops;
+        ABC_SWAP( int, pArray[i], pArray[k] );
+    }
+    printf( "Randomly adding %d unused flops.\n", nUnused );
+    for ( i = 0; i < nUnused; i++ )
+    {
+        k = rand() % Vec_IntSize(vPerm);
+        Vec_IntPush( vPerm, -1 );
+        pArray = Vec_IntArray( vPerm );
+        ABC_SWAP( int, pArray[Vec_IntSize(vPerm)-1], pArray[k] );
+    }
+//    Vec_IntPrint(vPerm);
+    return vPerm;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform sequential simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_RarSimulateGia( Gia_Man_t * p, Ssw_RarPars_t * pPars )
+{
+    Aig_Man_t * pAig;
+    int RetValue;
+    if ( pPars->fUseFfGrouping )
+    {
+        Vec_Int_t * vPerm = Ssw_RarRandomPermFlop( Gia_ManRegNum(p), 10 );
+        Gia_Man_t * pTemp = Gia_ManDupPermFlopGap( p, vPerm );
+        Vec_IntFree( vPerm );
+        pAig = Gia_ManToAigSimple( pTemp );
+        Gia_ManStop( pTemp );
+    }
+    else
+        pAig = Gia_ManToAigSimple( p );
+    RetValue = Ssw_RarSimulate( pAig, pPars );
+    // save counter-example
+    Abc_CexFree( p->pCexSeq );
+    p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL;
+    Aig_ManStop( pAig );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Filter equivalence classes of nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_RarSignalFilter( Aig_Man_t * pAig, Ssw_RarPars_t * pPars )
+{
+    Ssw_RarMan_t * p;
+    int r, f = -1, i, k;
+    abctime clkTotal = Abc_Clock();
+    abctime nTimeToStop = pPars->TimeOut ? pPars->TimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0;
+    int nNumRestart = 0;
+    int nSavedSeed = pPars->nRandSeed;
+    int RetValue = -1;
+    assert( Aig_ManRegNum(pAig) > 0 );
+    assert( Aig_ManConstrNum(pAig) == 0 );
+    // consider the case of empty AIG
+    if ( Aig_ManNodeNum(pAig) == 0 )
+        return -1;
+    // check trivially SAT miters
+    if ( pPars->fMiter && Ssw_RarCheckTrivial( pAig, 1 ) )
+        return 0;
+    if ( pPars->fVerbose )
+        Abc_Print( 1, "Rarity equiv filtering with %d words, %d frames, %d rounds, %d seed, and %d sec timeout.\n",
+            pPars->nWords, pPars->nFrames, pPars->nRounds, pPars->nRandSeed, pPars->TimeOut );
+    // reset random numbers
+    Ssw_RarManPrepareRandom( nSavedSeed );
+
+    // create manager
+    p = Ssw_RarManStart( pAig, pPars );
+    // compute starting state if needed
+    assert( p->vInits == NULL );
+    if ( pPars->pCex )
+    {
+        p->vInits = Ssw_RarFindStartingState( pAig, pPars->pCex );
+        Abc_Print( 1, "Beginning simulation from the state derived using the counter-example.\n" );
+    }
+    else
+        p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) );
+    // duplicate the array
+    for ( i = 1; i < pPars->nWords; i++ )
+        for ( k = 0; k < Aig_ManRegNum(pAig); k++ )
+            Vec_IntPush( p->vInits, Vec_IntEntry(p->vInits, k) );
+    assert( Vec_IntSize(p->vInits) == Aig_ManRegNum(pAig) * pPars->nWords );
+
+    // create trivial equivalence classes with all nodes being candidates for constant 1
+    if ( pAig->pReprs == NULL )
+        p->ppClasses = Ssw_ClassesPrepareSimple( pAig, pPars->fLatchOnly, 0 );
+    else
+        p->ppClasses = Ssw_ClassesPrepareFromReprs( pAig );
+    Ssw_ClassesSetData( p->ppClasses, p, Ssw_RarManObjHashWord, Ssw_RarManObjIsConst, Ssw_RarManObjsAreEqual );
+    // print the stats
+    if ( pPars->fVerbose )
+    {
+        Abc_Print( 1, "Initial  :  " );
+        Ssw_ClassesPrint( p->ppClasses, 0 );
+    }
+    // refine classes using BMC
+    for ( r = 0; !pPars->nRounds || (nNumRestart * pPars->nRestart + r < pPars->nRounds); r++ )
+    {
+        // start filtering equivalence classes
+        if ( Ssw_ClassesCand1Num(p->ppClasses) == 0 && Ssw_ClassesClassNum(p->ppClasses) == 0 )
+        {
+            Abc_Print( 1, "All equivalences are refined away.\n" );
+            break;
+        }
+        // simulate
+        for ( f = 0; f < pPars->nFrames; f++ )
+        {
+            Ssw_RarManSimulate( p, f ? NULL : p->vInits, 1, !r && !f );
+            if ( pPars->fMiter && Ssw_RarManCheckNonConstOutputs(p, -1, 0) )
+            {
+                if ( !pPars->fVerbose )
+                    Abc_Print( 1, "%s", Abc_FrameIsBatchMode() ? "\n" : "\r" );
+//                Abc_Print( 1, "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * pPars->nFrames, (r+1) * pPars->nFrames );
+                if ( pPars->fVerbose )
+                    Abc_Print( 1, "Simulated %d frames for %d rounds with %d restarts.\n", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart );
+                Ssw_RarManPrepareRandom( nSavedSeed );
+                Abc_CexFree( pAig->pSeqModel );
+                pAig->pSeqModel = Ssw_RarDeriveCex( p, r * p->pPars->nFrames + f, p->iFailPo, p->iFailPat, 1 );
+                // print final report
+                Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.  ", pAig->pSeqModel->iPo, pAig->pName, pAig->pSeqModel->iFrame );
+                Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+                RetValue = 0;
+                goto finish;
+            }
+            // check timeout
+            if ( pPars->TimeOut && Abc_Clock() > nTimeToStop )
+            {
+                if ( pPars->fVerbose ) Abc_Print( 1, "\n" );
+                Abc_Print( 1, "Simulated %d frames for %d rounds with %d restarts.  ", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart );
+                Abc_Print( 1, "Reached timeout (%d sec).\n",  pPars->TimeOut );
+                goto finish;
+            }
+        }
+        // get initialization patterns
+        if ( pPars->pCex == NULL && pPars->nRestart && r == pPars->nRestart )
+        {
+            r = -1;
+            nSavedSeed = (nSavedSeed + 1) % 1000;
+            Ssw_RarManPrepareRandom( nSavedSeed );
+            Vec_IntFill( p->vInits, Aig_ManRegNum(pAig) * pPars->nWords, 0 );
+            nNumRestart++;
+            Vec_IntClear( p->vPatBests );
+            // clean rarity info
+//            memset( p->pRarity, 0, sizeof(int) * (1 << nBinSize) * p->nGroups );
+        }
+        else
+            Ssw_RarTransferPatterns( p, p->vInits );
+        // printout
+        if ( pPars->fVerbose )
+        {
+            Abc_Print( 1, "Round %3d:  ", r );
+            Ssw_ClassesPrint( p->ppClasses, 0 );
+        }
+        else
+        {
+            Abc_Print( 1, "." );
+        }
+    }
+finish:
+    // report
+    if ( r == pPars->nRounds && f == pPars->nFrames )
+    {
+        if ( !pPars->fVerbose )
+            Abc_Print( 1, "%s", Abc_FrameIsBatchMode() ? "\n" : "\r" );
+        Abc_Print( 1, "Simulation of %d frames for %d rounds with %d restarts did not assert POs.    ", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+    }
+    // cleanup
+    Ssw_RarManStop( p );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Filter equivalence classes of nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_RarSignalFilterGia( Gia_Man_t * p, Ssw_RarPars_t * pPars )
+{
+    Aig_Man_t * pAig;
+    int RetValue;
+    pAig = Gia_ManToAigSimple( p );
+    if ( p->pReprs != NULL )
+    {
+        Gia_ManReprToAigRepr2( pAig, p );
+        ABC_FREE( p->pReprs );
+        ABC_FREE( p->pNexts );
+    }
+    RetValue = Ssw_RarSignalFilter( pAig, pPars );
+    Gia_ManReprFromAigRepr( pAig, p );
+    // save counter-example
+    Abc_CexFree( p->pCexSeq );
+    p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL;
+    Aig_ManStop( pAig );
+    return RetValue;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswRarity2.c b/abc-build/src/proof/ssw/sswRarity2.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswRarity2.c
@@ -0,0 +1,518 @@
+/**CFile****************************************************************
+
+  FileName    [sswRarity.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [Rarity-driven refinement of equivalence classes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswRarity.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ssw_RarMan_t_ Ssw_RarMan_t;
+struct Ssw_RarMan_t_
+{
+    // parameters
+    int            nWords;       // the number of words to simulate
+    int            nFrames;      // the number of frames to simulate
+    int            nBinSize;     // the number of flops in one group
+    int            fVerbose;     // the verbosiness flag
+    int            nGroups;      // the number of flop groups
+    // internal data
+    Aig_Man_t *    pAig;         // AIG with equivalence classes
+    Ssw_Cla_t *    ppClasses;    // equivalence classes
+    Ssw_Sml_t *    pSml;         // simulation manager
+    Vec_Ptr_t *    vSimInfo;     // simulation info from pSml manager
+    Vec_Int_t *    vInits;       // initial state
+    // rarity data
+    int *          pRarity;      // occur counts for patterns in groups
+    int *          pGroupValues; // occur counts in each group
+    double *       pPatCosts;    // pattern costs
+
+};
+
+static inline int  Ssw_RarGetBinPat( Ssw_RarMan_t * p, int iBin, int iPat )
+{
+    assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize );
+    assert( iPat >= 0 && iPat < (1 << p->nBinSize) );
+    return p->pRarity[iBin * (1 << p->nBinSize) + iPat];
+}
+static inline void Ssw_RarSetBinPat( Ssw_RarMan_t * p, int iBin, int iPat, int Value )
+{
+    assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize );
+    assert( iPat >= 0 && iPat < (1 << p->nBinSize) );
+    p->pRarity[iBin * (1 << p->nBinSize) + iPat] = Value;
+}
+static inline void Ssw_RarAddToBinPat( Ssw_RarMan_t * p, int iBin, int iPat )
+{
+    assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize );
+    assert( iPat >= 0 && iPat < (1 << p->nBinSize) );
+    p->pRarity[iBin * (1 << p->nBinSize) + iPat]++;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Ssw_RarMan_t * Ssw_RarManStart( Aig_Man_t * pAig, int nWords, int nFrames, int nBinSize, int fVerbose )
+{
+    Ssw_RarMan_t * p;
+    if ( Aig_ManRegNum(pAig) < nBinSize || nBinSize <= 0 )
+        return NULL;
+    p = ABC_CALLOC( Ssw_RarMan_t, 1 );
+    p->pAig = pAig;
+    p->nWords = nWords;
+    p->nFrames = nFrames;
+    p->nBinSize = nBinSize;
+    p->fVerbose = fVerbose;
+    p->nGroups  = Aig_ManRegNum(pAig) / nBinSize;
+    p->pRarity  = ABC_CALLOC( int, (1 << nBinSize) * p->nGroups );
+    p->pGroupValues = ABC_CALLOC( int, p->nGroups );
+    p->pPatCosts = ABC_CALLOC( double, p->nWords * 32 );
+    p->pSml = Ssw_SmlStart( pAig, 0, nFrames, nWords );
+    p->vSimInfo = Ssw_SmlSimDataPointers( p->pSml );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Ssw_RarManStop( Ssw_RarMan_t * p )
+{
+    if ( p->pSml ) Ssw_SmlStop( p->pSml );
+    if ( p->ppClasses ) Ssw_ClassesStop( p->ppClasses );
+    Vec_PtrFreeP( &p->vSimInfo );
+    Vec_IntFreeP( &p->vInits );
+    ABC_FREE( p->pGroupValues );
+    ABC_FREE( p->pPatCosts );
+    ABC_FREE( p->pRarity );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Updates rarity counters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Ssw_RarUpdateCounters( Ssw_RarMan_t * p )
+{
+    Aig_Obj_t * pObj;
+    unsigned * pData;
+    int i, k;
+/*
+    Saig_ManForEachLi( p->pAig, pObj, i )
+    {
+        pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1);
+        Extra_PrintBinary( stdout, pData, 32 );  Abc_Print( 1, "\n" );
+    }
+*/
+    for ( k = 0; k < p->nWords * 32; k++ )
+    {
+        for ( i = 0; i < p->nGroups; i++ )
+            p->pGroupValues[i] = 0;
+        Saig_ManForEachLi( p->pAig, pObj, i )
+        {
+            pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1);
+            if ( Abc_InfoHasBit(pData, k) && i / p->nBinSize < p->nGroups )
+                p->pGroupValues[i / p->nBinSize] |= (1 << (i % p->nBinSize));
+        }
+        for ( i = 0; i < p->nGroups; i++ )
+            Ssw_RarAddToBinPat( p, i, p->pGroupValues[i] );
+    }
+/*
+    for ( i = 0; i < p->nGroups; i++ )
+    {
+        for ( k = 0; k < (1 << p->nBinSize); k++ )
+            Abc_Print( 1, "%d ", Ssw_RarGetBinPat(p, i, k) );
+        Abc_Print( 1, "\n" );
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Select best patterns.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Ssw_RarTransferPatterns( Ssw_RarMan_t * p, Vec_Int_t * vInits )
+{
+    Aig_Obj_t * pObj;
+    unsigned * pData;
+    int i, k, Value;
+
+    // for each pattern
+    for ( k = 0; k < p->nWords * 32; k++ )
+    {
+        for ( i = 0; i < p->nGroups; i++ )
+            p->pGroupValues[i] = 0;
+        // compute its group values
+        Saig_ManForEachLi( p->pAig, pObj, i )
+        {
+            pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1);
+            if ( Abc_InfoHasBit(pData, k) && i / p->nBinSize < p->nGroups )
+                p->pGroupValues[i / p->nBinSize] |= (1 << (i % p->nBinSize));
+        }
+        // find the cost of its values
+        p->pPatCosts[k] = 0.0;
+        for ( i = 0; i < p->nGroups; i++ )
+        {
+            Value = Ssw_RarGetBinPat( p, i, p->pGroupValues[i] );
+            assert( Value > 0 );
+            p->pPatCosts[k] += 1.0/(Value*Value);
+        }
+        // print the result
+//        Abc_Print( 1, "%3d : %9.6f\n", k, p->pPatCosts[k] );
+    }
+
+    // choose as many as there are words
+    Vec_IntClear( vInits );
+    for ( i = 0; i < p->nWords; i++ )
+    {
+        // select the best
+        int iPatBest = -1;
+        double iCostBest = -ABC_INFINITY;
+        for ( k = 0; k < p->nWords * 32; k++ )
+            if ( iCostBest < p->pPatCosts[k] )
+            {
+                iCostBest = p->pPatCosts[k];
+                iPatBest  = k;
+            }
+        // remove from costs
+        assert( iPatBest >= 0 );
+        p->pPatCosts[iPatBest] = -ABC_INFINITY;
+        // set the flops
+        Saig_ManForEachLi( p->pAig, pObj, k )
+        {
+            pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1);
+            Vec_IntPush( vInits, Abc_InfoHasBit(pData, iPatBest) );
+        }
+//Abc_Print( 1, "Best pattern %5d\n", iPatBest );
+    }
+    assert( Vec_IntSize(vInits) == Aig_ManRegNum(p->pAig) * p->nWords );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for one node.]
+
+  Description [Returns the fraiged node.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Vec_Int_t * Ssw_RarFindStartingState( Aig_Man_t * pAig, Abc_Cex_t * pCex )
+{
+    Vec_Int_t * vInit;
+    Aig_Obj_t * pObj, * pObjLi;
+    int f, i, iBit;
+    // assign register outputs
+    Saig_ManForEachLi( pAig, pObj, i )
+        pObj->fMarkB = Abc_InfoHasBit( pCex->pData, i );
+    // simulate the timeframes
+    iBit = pCex->nRegs;
+    for ( f = 0; f <= pCex->iFrame; f++ )
+    {
+        // set the PI simulation information
+        Aig_ManConst1(pAig)->fMarkB = 1;
+        Saig_ManForEachPi( pAig, pObj, i )
+            pObj->fMarkB = Abc_InfoHasBit( pCex->pData, iBit++ );
+        Saig_ManForEachLiLo( pAig, pObjLi, pObj, i )
+            pObj->fMarkB = pObjLi->fMarkB;
+        // simulate internal nodes
+        Aig_ManForEachNode( pAig, pObj, i )
+            pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+                         & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+        // assign the COs
+        Aig_ManForEachCo( pAig, pObj, i )
+            pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) );
+    }
+    assert( iBit == pCex->nBits );
+    // check that the output failed as expected -- cannot check because it is not an SRM!
+//    pObj = Aig_ManCo( pAig, pCex->iPo );
+//    if ( pObj->fMarkB != 1 )
+//        Abc_Print( 1, "The counter-example does not refine the output.\n" );
+    // record the new pattern
+    vInit = Vec_IntAlloc( Saig_ManRegNum(pAig) );
+    Saig_ManForEachLo( pAig, pObj, i )
+        Vec_IntPush( vInit, pObj->fMarkB );
+    return vInit;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Perform sequential simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_RarSimulate2( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int TimeOut, int fVerbose )
+{
+    int fMiter = 1;
+    Ssw_RarMan_t * p;
+    int r;
+    abctime clk, clkTotal = Abc_Clock();
+    abctime nTimeToStop = TimeOut ? TimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0;
+    int RetValue = -1;
+    assert( Aig_ManRegNum(pAig) > 0 );
+    assert( Aig_ManConstrNum(pAig) == 0 );
+    // consider the case of empty AIG
+    if ( Aig_ManNodeNum(pAig) == 0 )
+        return -1;
+    if ( fVerbose )
+        Abc_Print( 1, "Simulating %d words through %d frames with %d binsize, %d rounds, and %d sec timeout.\n",
+            nWords, nFrames, nBinSize, nRounds, TimeOut );
+    // reset random numbers
+    Aig_ManRandom( 1 );
+
+    // create manager
+    p = Ssw_RarManStart( pAig, nWords, nFrames, nBinSize, fVerbose );
+    p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) * nWords );
+    Ssw_SmlInitializeSpecial( p->pSml, p->vInits );
+
+    // perform simulation rounds
+    for ( r = 0; r < nRounds; r++ )
+    {
+        clk = Abc_Clock();
+        // simulate
+        Ssw_SmlSimulateOne( p->pSml );
+        if ( fMiter && Ssw_SmlCheckNonConstOutputs(p->pSml) )
+        {
+            if ( fVerbose ) Abc_Print( 1, "\n" );
+            Abc_Print( 1, "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames );
+            RetValue = 0;
+            break;
+        }
+        // get initialization patterns
+        Ssw_RarUpdateCounters( p );
+        Ssw_RarTransferPatterns( p, p->vInits );
+        Ssw_SmlInitializeSpecial( p->pSml, p->vInits );
+        // printout
+        if ( fVerbose )
+        {
+//            Abc_Print( 1, "Round %3d:  ", r );
+//            Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+            Abc_Print( 1, "." );
+        }
+        // check timeout
+        if ( TimeOut && Abc_Clock() > nTimeToStop )
+        {
+            if ( fVerbose ) Abc_Print( 1, "\n" );
+            Abc_Print( 1, "Reached timeout (%d seconds).\n",  TimeOut );
+            break;
+        }
+    }
+    if ( r == nRounds )
+    {
+        if ( fVerbose ) Abc_Print( 1, "\n" );
+        Abc_Print( 1, "Simulation did not assert POs in the first %d frames.  ", nRounds * nFrames );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+    }
+    // cleanup
+    Ssw_RarManStop( p );
+    return RetValue;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Filter equivalence classes of nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_RarSignalFilter2( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int TimeOut, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose )
+{
+    int fMiter = 0;
+    Ssw_RarMan_t * p;
+    int r, i, k;
+    abctime clkTotal = Abc_Clock();
+    abctime nTimeToStop = TimeOut ? TimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0;
+    int RetValue = -1;
+    assert( Aig_ManRegNum(pAig) > 0 );
+    assert( Aig_ManConstrNum(pAig) == 0 );
+    // consider the case of empty AIG
+    if ( Aig_ManNodeNum(pAig) == 0 )
+        return -1;
+    if ( fVerbose )
+        Abc_Print( 1, "Filtering equivs with %d words through %d frames with %d binsize, %d rounds, and %d sec timeout.\n",
+            nWords, nFrames, nBinSize, nRounds, TimeOut );
+    // reset random numbers
+    Aig_ManRandom( 1 );
+
+    // create manager
+    p = Ssw_RarManStart( pAig, nWords, nFrames, nBinSize, fVerbose );
+    // compute starting state if needed
+    assert( p->vInits == NULL );
+    if ( pCex )
+        p->vInits = Ssw_RarFindStartingState( pAig, pCex );
+    else
+        p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) );
+    // duplicate the array
+    for ( i = 1; i < nWords; i++ )
+        for ( k = 0; k < Aig_ManRegNum(pAig); k++ )
+            Vec_IntPush( p->vInits, Vec_IntEntry(p->vInits, k) );
+    assert( Vec_IntSize(p->vInits) == Aig_ManRegNum(pAig) * nWords );
+    // initialize simulation manager
+    Ssw_SmlInitializeSpecial( p->pSml, p->vInits );
+
+    // create trivial equivalence classes with all nodes being candidates for constant 1
+    if ( pAig->pReprs == NULL )
+        p->ppClasses = Ssw_ClassesPrepareSimple( pAig, fLatchOnly, 0 );
+    else
+        p->ppClasses = Ssw_ClassesPrepareFromReprs( pAig );
+    Ssw_ClassesSetData( p->ppClasses, p->pSml, NULL, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord );
+    // print the stats
+    if ( fVerbose )
+    {
+        Abc_Print( 1, "Initial  :  " );
+        Ssw_ClassesPrint( p->ppClasses, 0 );
+    }
+    // refine classes using BMC
+    for ( r = 0; r < nRounds; r++ )
+    {
+        // start filtering equivalence classes
+        if ( Ssw_ClassesCand1Num(p->ppClasses) == 0 && Ssw_ClassesClassNum(p->ppClasses) == 0 )
+        {
+            Abc_Print( 1, "All equivalences are refined away.\n" );
+            break;
+        }
+        // simulate
+        Ssw_SmlSimulateOne( p->pSml );
+        if ( fMiter && Ssw_SmlCheckNonConstOutputs(p->pSml) )
+        {
+            if ( fVerbose ) Abc_Print( 1, "\n" );
+            Abc_Print( 1, "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames );
+            RetValue = 0;
+            break;
+        }
+        // check equivalence classes
+        Ssw_ClassesRefineConst1( p->ppClasses, 1 );
+        Ssw_ClassesRefine( p->ppClasses, 1 );
+        // printout
+        if ( fVerbose )
+        {
+            Abc_Print( 1, "Round %3d:  ", r );
+            Ssw_ClassesPrint( p->ppClasses, 0 );
+        }
+        // get initialization patterns
+        Ssw_RarUpdateCounters( p );
+        Ssw_RarTransferPatterns( p, p->vInits );
+        Ssw_SmlInitializeSpecial( p->pSml, p->vInits );
+        // check timeout
+        if ( TimeOut && Abc_Clock() > nTimeToStop )
+        {
+            if ( fVerbose ) Abc_Print( 1, "\n" );
+            Abc_Print( 1, "Reached timeout (%d seconds).\n",  TimeOut );
+            break;
+        }
+    }
+    if ( r == nRounds )
+    {
+        Abc_Print( 1, "Simulation did not assert POs in the first %d frames.  ", nRounds * nFrames );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
+    }
+    // cleanup
+    Ssw_RarManStop( p );
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Filter equivalence classes of nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_RarSignalFilterGia2( Gia_Man_t * p, int nFrames, int nWords, int nBinSize, int nRounds, int TimeOut, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose )
+{
+    Aig_Man_t * pAig;
+    int RetValue;
+    pAig = Gia_ManToAigSimple( p );
+    if ( p->pReprs != NULL )
+    {
+        Gia_ManReprToAigRepr2( pAig, p );
+        ABC_FREE( p->pReprs );
+        ABC_FREE( p->pNexts );
+    }
+    RetValue = Ssw_RarSignalFilter2( pAig, nFrames, nWords, nBinSize, nRounds, TimeOut, pCex, fLatchOnly, fVerbose );
+    Gia_ManReprFromAigRepr( pAig, p );
+    Aig_ManStop( pAig );
+    return RetValue;
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswSat.c b/abc-build/src/proof/ssw/sswSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswSat.c
@@ -0,0 +1,307 @@
+/**CFile****************************************************************
+
+  FileName    [sswSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [Calls to the SAT solver.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswSat.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Runs equivalence test for the two nodes.]
+
+  Description [Both nodes should be regular and different from each other.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_NodesAreEquiv( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew )
+{
+    int nBTLimit = p->pPars->nBTLimit;
+    int pLits[3], nLits, RetValue, RetValue1;
+    abctime clk;//, status;
+    p->nSatCalls++;
+    p->pMSat->nSolverCalls++;
+
+    // sanity checks
+    assert( !Aig_IsComplement(pOld) );
+    assert( !Aig_IsComplement(pNew) );
+    assert( pOld != pNew );
+    assert( p->pMSat != NULL );
+
+    // if the nodes do not have SAT variables, allocate them
+    Ssw_CnfNodeAddToSolver( p->pMSat, pOld );
+    Ssw_CnfNodeAddToSolver( p->pMSat, pNew );
+
+    // solve under assumptions
+    // A = 1; B = 0     OR     A = 1; B = 1 
+    nLits = 2;
+    pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 0 );
+    pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), pOld->fPhase == pNew->fPhase );
+    if ( p->iOutputLit > -1 )
+        pLits[nLits++] = p->iOutputLit;
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( pOld->fPhase )  pLits[0] = lit_neg( pLits[0] );
+        if ( pNew->fPhase )  pLits[1] = lit_neg( pLits[1] );
+    }
+//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
+
+    if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead )
+    {
+        RetValue = sat_solver_simplify(p->pMSat->pSat);
+        assert( RetValue != 0 );
+    }
+
+clk = Abc_Clock();
+    RetValue1 = sat_solver_solve( p->pMSat->pSat, pLits, pLits + nLits, 
+        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+p->timeSat += Abc_Clock() - clk;
+    if ( RetValue1 == l_False )
+    {
+p->timeSatUnsat += Abc_Clock() - clk;
+        if ( nLits == 2 )
+        {
+            pLits[0] = lit_neg( pLits[0] );
+            pLits[1] = lit_neg( pLits[1] );
+            RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 );
+            assert( RetValue );
+/*
+            if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead )
+            {
+                RetValue = sat_solver_simplify(p->pMSat->pSat);
+                assert( RetValue != 0 );
+            }
+*/
+        }
+        p->nSatCallsUnsat++;
+    }
+    else if ( RetValue1 == l_True )
+    {
+p->timeSatSat += Abc_Clock() - clk;
+        p->nSatCallsSat++;
+        return 0;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+p->timeSatUndec += Abc_Clock() - clk;
+        p->nSatFailsReal++;
+        return -1;
+    }
+
+    // if the old node was constant 0, we already know the answer
+    if ( pOld == Aig_ManConst1(p->pFrames) )
+    {
+        p->nSatProof++;
+        return 1;
+    }
+
+    // solve under assumptions
+    // A = 0; B = 1     OR     A = 0; B = 0 
+    nLits = 2;
+    pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 1 );
+    pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), pOld->fPhase ^ pNew->fPhase );
+    if ( p->iOutputLit > -1 )
+        pLits[nLits++] = p->iOutputLit;
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( pOld->fPhase )  pLits[0] = lit_neg( pLits[0] );
+        if ( pNew->fPhase )  pLits[1] = lit_neg( pLits[1] );
+    }
+
+    if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead )
+    {
+        RetValue = sat_solver_simplify(p->pMSat->pSat);
+        assert( RetValue != 0 );
+    }
+
+clk = Abc_Clock();
+    RetValue1 = sat_solver_solve( p->pMSat->pSat, pLits, pLits + nLits, 
+        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+p->timeSat += Abc_Clock() - clk;
+    if ( RetValue1 == l_False )
+    {
+p->timeSatUnsat += Abc_Clock() - clk;
+        if ( nLits == 2 )
+        {
+            pLits[0] = lit_neg( pLits[0] );
+            pLits[1] = lit_neg( pLits[1] );
+            RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 );
+            assert( RetValue );
+/*
+            if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead )
+            {
+                RetValue = sat_solver_simplify(p->pMSat->pSat);
+                assert( RetValue != 0 );
+            }
+*/
+        }
+        p->nSatCallsUnsat++;
+    }
+    else if ( RetValue1 == l_True )
+    {
+p->timeSatSat += Abc_Clock() - clk;
+        p->nSatCallsSat++;
+        return 0;
+    }
+    else // if ( RetValue1 == l_Undef )
+    {
+p->timeSatUndec += Abc_Clock() - clk;
+        p->nSatFailsReal++;
+        return -1;
+    }
+    // return SAT proof
+    p->nSatProof++;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constrains two nodes to be equivalent in the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_NodesAreConstrained( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew )
+{
+    int pLits[2], RetValue, fComplNew;
+    Aig_Obj_t * pTemp;
+
+    // sanity checks
+    assert( Aig_Regular(pOld) != Aig_Regular(pNew) );
+    assert( p->pPars->fConstrs || Aig_ObjPhaseReal(pOld) == Aig_ObjPhaseReal(pNew) );
+
+    // move constant to the old node
+    if ( Aig_Regular(pNew) == Aig_ManConst1(p->pFrames) )
+    {
+        assert( Aig_Regular(pOld) != Aig_ManConst1(p->pFrames) );
+        pTemp = pOld;
+        pOld  = pNew;
+        pNew  = pTemp;
+    }
+
+    // move complement to the new node
+    if ( Aig_IsComplement(pOld) )
+    {
+        pOld = Aig_Regular(pOld);
+        pNew = Aig_Not(pNew);
+    }
+    assert( p->pMSat != NULL );
+
+    // if the nodes do not have SAT variables, allocate them
+    Ssw_CnfNodeAddToSolver( p->pMSat, pOld );
+    Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pNew) );
+
+    // transform the new node
+    fComplNew = Aig_IsComplement( pNew );
+    pNew = Aig_Regular( pNew );
+
+    // consider the constant 1 case
+    if ( pOld == Aig_ManConst1(p->pFrames) )
+    {
+        // add constraint A = 1  ---->  A
+        pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), fComplNew );
+        if ( p->pPars->fPolarFlip )
+        {
+            if ( pNew->fPhase )  pLits[0] = lit_neg( pLits[0] );
+        }
+        RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 1 );
+        assert( RetValue );
+    }
+    else
+    {
+        // add constraint A = B  ---->  (A v !B)(!A v B)
+
+        // (A v !B)
+        pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 0 );
+        pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), !fComplNew );
+        if ( p->pPars->fPolarFlip )
+        {
+            if ( pOld->fPhase )  pLits[0] = lit_neg( pLits[0] );
+            if ( pNew->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        }
+        pLits[0] = lit_neg( pLits[0] );
+        pLits[1] = lit_neg( pLits[1] );
+        RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+
+        // (!A v B)
+        pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 1 );
+        pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), fComplNew);
+        if ( p->pPars->fPolarFlip )
+        {
+            if ( pOld->fPhase )  pLits[0] = lit_neg( pLits[0] );
+            if ( pNew->fPhase )  pLits[1] = lit_neg( pLits[1] );
+        }
+        pLits[0] = lit_neg( pLits[0] );
+        pLits[1] = lit_neg( pLits[1] );
+        RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 );
+        assert( RetValue );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Constrains one node in the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_NodeIsConstrained( Ssw_Man_t * p, Aig_Obj_t * pPoObj )
+{
+    int RetValue, Lit;
+    Ssw_CnfNodeAddToSolver( p->pMSat, Aig_ObjFanin0(pPoObj) );
+    // add constraint A = 1  ---->  A
+    Lit = toLitCond( Ssw_ObjSatNum(p->pMSat,Aig_ObjFanin0(pPoObj)), !Aig_ObjFaninC0(pPoObj) );
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( Aig_ObjFanin0(pPoObj)->fPhase )  Lit = lit_neg( Lit );
+    }
+    RetValue = sat_solver_addclause( p->pMSat->pSat, &Lit, &Lit + 1 );
+    assert( RetValue );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/proof/ssw/sswSemi.c b/abc-build/src/proof/ssw/sswSemi.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswSemi.c
@@ -0,0 +1,323 @@
+/**CFile****************************************************************
+
+  FileName    [sswSemi.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [Semiformal for equivalence classes.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswSemi.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ssw_Sem_t_ Ssw_Sem_t; // BMC manager
+
+struct Ssw_Sem_t_
+{
+    // parameters
+    int              nConfMaxStart;  // the starting conflict limit
+    int              nConfMax;       // the intermediate conflict limit
+    int              nFramesSweep;   // the number of frames to sweep
+    int              fVerbose;       // prints output statistics
+    // equivalences considered
+    Ssw_Man_t *      pMan;           // SAT sweeping manager
+    Vec_Ptr_t *      vTargets;       // the nodes that are watched
+    // storage for patterns
+    int              nPatternsAlloc; // the max number of interesting states
+    int              nPatterns;      // the number of patterns
+    Vec_Ptr_t *      vPatterns;      // storage for the interesting states
+    Vec_Int_t *      vHistory;       // what state and how many steps
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ssw_Sem_t * Ssw_SemManStart( Ssw_Man_t * pMan, int nConfMax, int fVerbose )
+{
+    Ssw_Sem_t * p;
+    Aig_Obj_t * pObj;
+    int i;
+    // create interpolation manager
+    p = ABC_ALLOC( Ssw_Sem_t, 1 );
+    memset( p, 0, sizeof(Ssw_Sem_t) );
+    p->nConfMaxStart  = nConfMax;
+    p->nConfMax       = nConfMax;
+    p->nFramesSweep   = Abc_MaxInt( (1<<21)/Aig_ManNodeNum(pMan->pAig), pMan->nFrames );
+    p->fVerbose       = fVerbose;
+    // equivalences considered
+    p->pMan           = pMan;
+    p->vTargets       = Vec_PtrAlloc( Saig_ManPoNum(p->pMan->pAig) );
+    Saig_ManForEachPo( p->pMan->pAig, pObj, i )
+        Vec_PtrPush( p->vTargets, Aig_ObjFanin0(pObj) );
+    // storage for patterns
+    p->nPatternsAlloc = 512;
+    p->nPatterns      = 1;
+    p->vPatterns      = Vec_PtrAllocSimInfo( Aig_ManRegNum(p->pMan->pAig), Abc_BitWordNum(p->nPatternsAlloc) );
+    Vec_PtrCleanSimInfo( p->vPatterns, 0, Abc_BitWordNum(p->nPatternsAlloc) );
+    p->vHistory       = Vec_IntAlloc( 100 );
+    Vec_IntPush( p->vHistory, 0 );
+    // update arrays of the manager
+    assert( 0 );
+/*
+    ABC_FREE( p->pMan->pNodeToFrames );
+    Vec_IntFree( p->pMan->vSatVars );
+    p->pMan->pNodeToFrames = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pMan->pAig) * p->nFramesSweep );
+    p->pMan->vSatVars      = Vec_IntStart( Aig_ManObjNumMax(p->pMan->pAig) * (p->nFramesSweep+1) );
+*/
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SemManStop( Ssw_Sem_t * p )
+{
+    Vec_PtrFree( p->vTargets );
+    Vec_PtrFree( p->vPatterns );
+    Vec_IntFree( p->vHistory );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SemCheckTargets( Ssw_Sem_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vTargets, pObj, i )
+        if ( !Ssw_ObjIsConst1Cand(p->pMan->pAig, pObj) )
+            return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManFilterBmcSavePattern( Ssw_Sem_t * p )
+{
+    unsigned * pInfo;
+    Aig_Obj_t * pObj;
+    int i;
+    if ( p->nPatterns >= p->nPatternsAlloc )
+        return;
+    Saig_ManForEachLo( p->pMan->pAig, pObj, i )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry( p->vPatterns, i );
+        if ( Abc_InfoHasBit( p->pMan->pPatWords, Saig_ManPiNum(p->pMan->pAig) + i ) )
+            Abc_InfoSetBit( pInfo, p->nPatterns );
+    }
+    p->nPatterns++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for the internal nodes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManFilterBmc( Ssw_Sem_t * pBmc, int iPat, int fCheckTargets )
+{
+    Ssw_Man_t * p = pBmc->pMan;
+    Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo;
+    unsigned * pInfo;
+    int i, f, RetValue, fFirst = 0;
+    abctime clk;
+clk = Abc_Clock();
+
+    // start initialized timeframes
+    p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * 3 );
+    Saig_ManForEachLo( p->pAig, pObj, i )
+    {
+        pInfo = (unsigned *)Vec_PtrEntry( pBmc->vPatterns, i );
+        pObjNew = Aig_NotCond( Aig_ManConst1(p->pFrames), !Abc_InfoHasBit(pInfo, iPat) );
+        Ssw_ObjSetFrame( p, pObj, 0, pObjNew );
+    }
+
+    // sweep internal nodes
+    RetValue = pBmc->nFramesSweep;
+    for ( f = 0; f < pBmc->nFramesSweep; f++ )
+    {
+        // map constants and PIs
+        Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
+        Saig_ManForEachPi( p->pAig, pObj, i )
+            Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreateCi(p->pFrames) );
+        // sweep internal nodes
+        Aig_ManForEachNode( p->pAig, pObj, i )
+        {
+            pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+            Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+            if ( Ssw_ManSweepNode( p, pObj, f, 1, NULL ) )
+            {
+                Ssw_ManFilterBmcSavePattern( pBmc );
+                if ( fFirst == 0 )
+                {
+                    fFirst = 1;
+                    pBmc->nConfMax *= 10;
+                }
+            }
+            if ( f > 0 && p->pMSat->pSat->stats.conflicts >= pBmc->nConfMax )
+            {
+                RetValue = -1;
+                break;
+            }
+        }
+        // quit if this is the last timeframe
+        if ( p->pMSat->pSat->stats.conflicts >= pBmc->nConfMax )
+        {
+            RetValue += f + 1;
+            break;
+        }
+        if ( fCheckTargets && Ssw_SemCheckTargets( pBmc ) )
+            break;
+        // transfer latch input to the latch outputs 
+        // build logic cones for register outputs
+        Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+        {
+            pObjNew = Ssw_ObjChild0Fra(p, pObjLi,f);
+            Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew );
+            Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );
+        }
+//Abc_Print( 1, "Frame %2d : Conflicts = %6d. \n", f, p->pSat->stats.conflicts );
+    }
+    if ( fFirst )
+        pBmc->nConfMax /= 10;
+
+    // cleanup
+    Ssw_ClassesCheck( p->ppClasses );
+p->timeBmc += Abc_Clock() - clk;
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if one of the targets has failed.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_FilterUsingSemi( Ssw_Man_t * pMan, int fCheckTargets, int nConfMax, int fVerbose )
+{
+    Ssw_Sem_t * p;
+    int RetValue, Frames, Iter;
+    abctime clk = Abc_Clock();
+    p = Ssw_SemManStart( pMan, nConfMax, fVerbose );
+    if ( fCheckTargets && Ssw_SemCheckTargets( p ) )
+    {
+        assert( 0 );
+        Ssw_SemManStop( p );
+        return 1;
+    }
+    if ( fVerbose )
+    {
+        Abc_Print( 1, "AIG : C = %6d. Cl = %6d. Nodes = %6d.  ConfMax = %6d. FramesMax = %6d.\n",
+            Ssw_ClassesCand1Num(p->pMan->ppClasses), Ssw_ClassesClassNum(p->pMan->ppClasses),
+            Aig_ManNodeNum(p->pMan->pAig), p->nConfMax, p->nFramesSweep );
+    }
+    RetValue = 0;
+    for ( Iter = 0; Iter < p->nPatterns; Iter++ )
+    {
+clk = Abc_Clock();
+        pMan->pMSat = Ssw_SatStart( 0 );
+        Frames = Ssw_ManFilterBmc( p, Iter, fCheckTargets );
+        if ( fVerbose )
+        {
+            Abc_Print( 1, "%3d : C = %6d. Cl = %6d. NR = %6d. F = %3d. C = %5d. P = %3d. %s ",
+                Iter, Ssw_ClassesCand1Num(p->pMan->ppClasses), Ssw_ClassesClassNum(p->pMan->ppClasses),
+                Aig_ManNodeNum(p->pMan->pFrames), Frames, (int)p->pMan->pMSat->pSat->stats.conflicts, p->nPatterns,
+                p->pMan->nSatFailsReal? "f" : " " );
+            ABC_PRT( "T", Abc_Clock() - clk );
+        }
+        Ssw_ManCleanup( p->pMan );
+        if ( fCheckTargets && Ssw_SemCheckTargets( p ) )
+        {
+            Abc_Print( 1, "Target is hit!!!\n" );
+            RetValue = 1;
+        }
+        if ( p->nPatterns >= p->nPatternsAlloc )
+            break;
+    }
+    Ssw_SemManStop( p );
+
+    pMan->nStrangers = 0;
+    pMan->nSatCalls = 0;
+    pMan->nSatProof = 0;
+    pMan->nSatFailsReal = 0;
+    pMan->nSatCallsUnsat = 0;
+    pMan->nSatCallsSat = 0;
+    pMan->timeSimSat = 0;
+    pMan->timeSat = 0;
+    pMan->timeSatSat = 0;
+    pMan->timeSatUnsat = 0;
+    pMan->timeSatUndec = 0;
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswSim.c b/abc-build/src/proof/ssw/sswSim.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswSim.c
@@ -0,0 +1,1406 @@
+/**CFile****************************************************************
+
+  FileName    [sswSim.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [Sequential simulator used by the inductive prover.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswSim.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// simulation manager
+struct Ssw_Sml_t_
+{
+    Aig_Man_t *      pAig;              // the original AIG manager
+    int              nPref;             // the number of timeframes in the prefix
+    int              nFrames;           // the number of timeframes 
+    int              nWordsFrame;       // the number of words in each timeframe
+    int              nWordsTotal;       // the total number of words at a node
+    int              nWordsPref;        // the number of word in the prefix
+    int              fNonConstOut;      // have seen a non-const-0 output during simulation
+    int              nSimRounds;        // statistics
+    abctime          timeSim;           // statistics
+    unsigned         pData[0];          // simulation data for the nodes
+};
+
+static inline unsigned * Ssw_ObjSim( Ssw_Sml_t * p, int Id )  { return p->pData + p->nWordsTotal * Id; }
+static inline unsigned   Ssw_ObjRandomSim()                   { return Aig_ManRandom(0);               }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes hash value of the node using its simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned Ssw_SmlObjHashWord( Ssw_Sml_t * p, Aig_Obj_t * pObj )
+{
+    static int s_SPrimes[128] = {
+        1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459,
+        1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997,
+        2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543,
+        2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089,
+        3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671,
+        3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243,
+        4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871,
+        4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471,
+        5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073,
+        6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689,
+        6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309,
+        7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933,
+        8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+    };
+    unsigned * pSims;
+    unsigned uHash;
+    int i;
+//    assert( p->nWordsTotal <= 128 );
+    uHash = 0;
+    pSims = Ssw_ObjSim(p, pObj->Id);
+    for ( i = p->nWordsPref; i < p->nWordsTotal; i++ )
+        uHash ^= pSims[i] * s_SPrimes[i & 0x7F];
+    return uHash;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation info is composed of all zeros.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SmlObjIsConstWord( Ssw_Sml_t * p, Aig_Obj_t * pObj )
+{
+    unsigned * pSims;
+    int i;
+    pSims = Ssw_ObjSim(p, pObj->Id);
+    for ( i = p->nWordsPref; i < p->nWordsTotal; i++ )
+        if ( pSims[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation infos are equal.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SmlObjsAreEqualWord( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+    unsigned * pSims0, * pSims1;
+    int i;
+    pSims0 = Ssw_ObjSim(p, pObj0->Id);
+    pSims1 = Ssw_ObjSim(p, pObj1->Id);
+    for ( i = p->nWordsPref; i < p->nWordsTotal; i++ )
+        if ( pSims0[i] != pSims1[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the node appears to be constant 1 candidate.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SmlObjIsConstBit( void * p, Aig_Obj_t * pObj )
+{
+    return pObj->fPhase == pObj->fMarkB;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the nodes appear equal.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SmlObjsAreEqualBit( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+    return (pObj0->fPhase == pObj1->fPhase) == (pObj0->fMarkB == pObj1->fMarkB);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of 1s in the XOR of simulation data.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SmlNodeNotEquWeight( Ssw_Sml_t * p, int Left, int Right )
+{
+    unsigned * pSimL, * pSimR;
+    int k, Counter = 0;
+    pSimL = Ssw_ObjSim( p, Left );
+    pSimR = Ssw_ObjSim( p, Right );
+    for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+        Counter += Aig_WordCountOnes( pSimL[k] ^ pSimR[k] );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks implication.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand )
+{
+    unsigned * pSimLi, * pSimLo, * pSimCand;
+    int k;
+    assert( pObjLo->fPhase == 0 );
+    // pObjLi->fPhase may be 1, but the LI simulation data is not complemented!
+    pSimCand = Ssw_ObjSim( p, Aig_Regular(pCand)->Id );
+    pSimLi   = Ssw_ObjSim( p, pObjLi->Id );
+    pSimLo   = Ssw_ObjSim( p, pObjLo->Id );
+    if ( Aig_Regular(pCand)->fPhase ^ Aig_IsComplement(pCand) )
+    {
+        for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+            if ( ~pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) )
+                return 0;
+    }
+    else
+    {
+        for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+            if ( pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) )
+                return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of 1s in the implication.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SmlCountXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand )
+{
+    unsigned * pSimLi, * pSimLo, * pSimCand;
+    int k, Counter = 0;
+    assert( pObjLo->fPhase == 0 );
+    // pObjLi->fPhase may be 1, but the LI simulation data is not complemented!
+    pSimCand = Ssw_ObjSim( p, Aig_Regular(pCand)->Id );
+    pSimLi   = Ssw_ObjSim( p, pObjLi->Id );
+    pSimLo   = Ssw_ObjSim( p, pObjLo->Id );
+    if ( Aig_Regular(pCand)->fPhase ^ Aig_IsComplement(pCand) )
+    {
+        for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+            Counter += Aig_WordCountOnes(~pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k]));
+    }
+    else
+    {
+        for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+            Counter += Aig_WordCountOnes(pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k]));
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of 1s in the implication.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SmlCountEqual( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo )
+{
+    unsigned * pSimLi, * pSimLo;
+    int k, Counter = 0;
+    assert( pObjLo->fPhase == 0 );
+    // pObjLi->fPhase may be 1, but the LI simulation data is not complemented!
+    pSimLi   = Ssw_ObjSim( p, pObjLi->Id );
+    pSimLo   = Ssw_ObjSim( p, pObjLo->Id );
+    for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+        Counter += Aig_WordCountOnes( ~(pSimLi[k] ^ pSimLo[k]) );
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation info is composed of all zeros.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SmlNodeIsZero( Ssw_Sml_t * p, Aig_Obj_t * pObj )
+{
+    unsigned * pSims;
+    int i;
+    pSims = Ssw_ObjSim(p, pObj->Id);
+    for ( i = p->nWordsPref; i < p->nWordsTotal; i++ )
+        if ( pSims[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if simulation info is composed of all zeros.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SmlNodeIsZeroFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f )
+{
+    unsigned * pSims = Ssw_ObjSim(p, pObj->Id);
+    return pSims[f] == 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of one's in the pattern of the object.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SmlNodeCountOnesReal( Ssw_Sml_t * p, Aig_Obj_t * pObj )
+{
+    unsigned * pSims;
+    int i, Counter = 0;
+    pSims = Ssw_ObjSim(p, Aig_Regular(pObj)->Id);
+    if ( Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) )
+    {
+        for ( i = 0; i < p->nWordsTotal; i++ )
+            Counter += Aig_WordCountOnes( ~pSims[i] );
+    }
+    else
+    {
+        for ( i = 0; i < p->nWordsTotal; i++ )
+            Counter += Aig_WordCountOnes( pSims[i] );
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of one's in the pattern of the objects.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SmlNodeCountOnesRealVec( Ssw_Sml_t * p, Vec_Ptr_t * vObjs )
+{
+    Aig_Obj_t * pObj;
+    unsigned * pSims, uWord;
+    int i, k, Counter = 0;
+    if ( Vec_PtrSize(vObjs) == 0 )
+        return 0;
+    for ( i = 0; i < p->nWordsTotal; i++ )
+    {
+        uWord = 0;
+        Vec_PtrForEachEntry( Aig_Obj_t *, vObjs, pObj, k )
+        {
+            pSims = Ssw_ObjSim(p, Aig_Regular(pObj)->Id);
+            if ( Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) )
+                uWord |= ~pSims[i];
+            else
+                uWord |= pSims[i];
+        }
+        Counter += Aig_WordCountOnes( uWord );
+    }
+    return Counter;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Generated const 0 pattern.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlSavePattern0( Ssw_Man_t * p, int fInit )
+{
+    memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [[Generated const 1 pattern.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlSavePattern1( Ssw_Man_t * p, int fInit )
+{
+    Aig_Obj_t * pObj;
+    int i, k, nTruePis;
+    memset( p->pPatWords, 0xff, sizeof(unsigned) * p->nPatWords );
+    if ( !fInit )
+        return;
+    // clear the state bits to correspond to all-0 initial state
+    nTruePis = Saig_ManPiNum(p->pAig);
+    k = 0;
+    Saig_ManForEachLo( p->pAig, pObj, i )
+        Abc_InfoXorBit( p->pPatWords, nTruePis * p->nFrames + k++ );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the counter-example from the successful pattern.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Ssw_SmlCheckOutputSavePattern( Ssw_Sml_t * p, Aig_Obj_t * pObjPo )
+{
+    Aig_Obj_t * pFanin, * pObjPi;
+    unsigned * pSims;
+    int i, k, BestPat, * pModel;
+    // find the word of the pattern
+    pFanin = Aig_ObjFanin0(pObjPo);
+    pSims = Ssw_ObjSim(p, pFanin->Id);
+    for ( i = 0; i < p->nWordsTotal; i++ )
+        if ( pSims[i] )
+            break;
+    assert( i < p->nWordsTotal );
+    // find the bit of the pattern
+    for ( k = 0; k < 32; k++ )
+        if ( pSims[i] & (1 << k) )
+            break;
+    assert( k < 32 );
+    // determine the best pattern
+    BestPat = i * 32 + k;
+    // fill in the counter-example data
+    pModel = ABC_ALLOC( int, Aig_ManCiNum(p->pAig)+1 );
+    Aig_ManForEachCi( p->pAig, pObjPi, i )
+    {
+        pModel[i] = Abc_InfoHasBit(Ssw_ObjSim(p, pObjPi->Id), BestPat);
+//        Abc_Print( 1, "%d", pModel[i] );
+    }
+    pModel[Aig_ManCiNum(p->pAig)] = pObjPo->Id;
+//    Abc_Print( 1, "\n" );
+    return pModel;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the one of the output is already non-constant 0.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Ssw_SmlCheckOutput( Ssw_Sml_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    // make sure the reference simulation pattern does not detect the bug
+    pObj = Aig_ManCo( p->pAig, 0 );
+    assert( Aig_ObjFanin0(pObj)->fPhase == (unsigned)Aig_ObjFaninC0(pObj) );
+    Aig_ManForEachCo( p->pAig, pObj, i )
+    {
+        if ( !Ssw_SmlObjIsConstWord( p, Aig_ObjFanin0(pObj) ) )
+        {
+            // create the counter-example from this pattern
+            return Ssw_SmlCheckOutputSavePattern( p, pObj );
+        }
+    }
+    return NULL;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns random patterns to the PI node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlAssignRandom( Ssw_Sml_t * p, Aig_Obj_t * pObj )
+{
+    unsigned * pSims;
+    int i, f;
+    assert( Aig_ObjIsCi(pObj) );
+    pSims = Ssw_ObjSim( p, pObj->Id );
+    for ( i = 0; i < p->nWordsTotal; i++ )
+        pSims[i] = Ssw_ObjRandomSim();
+    // set the first bit 0 in each frame
+    assert( p->nWordsFrame * p->nFrames == p->nWordsTotal );
+    for ( f = 0; f < p->nFrames; f++ )
+        pSims[p->nWordsFrame*f] <<= 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns random patterns to the PI node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlAssignRandomFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame )
+{
+    unsigned * pSims;
+    int i;
+    assert( iFrame < p->nFrames );
+    assert( Aig_ObjIsCi(pObj) );
+    pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame;
+    for ( i = 0; i < p->nWordsFrame; i++ )
+        pSims[i] = Ssw_ObjRandomSim();
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns constant patterns to the PI node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlObjAssignConst( Ssw_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame )
+{
+    unsigned * pSims;
+    int i;
+    assert( iFrame < p->nFrames );
+    assert( Aig_ObjIsCi(pObj) );
+    pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame;
+    for ( i = 0; i < p->nWordsFrame; i++ )
+        pSims[i] = fConst1? ~(unsigned)0 : 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns constant patterns to the PI node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlObjAssignConstWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame, int iWord )
+{
+    unsigned * pSims;
+    assert( iFrame < p->nFrames );
+    assert( iWord < p->nWordsFrame );
+    assert( Aig_ObjIsCi(pObj) );
+    pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame;
+    pSims[iWord] = fConst1? ~(unsigned)0 : 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns constant patterns to the PI node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlObjSetWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, unsigned Word, int iWord, int iFrame )
+{
+    unsigned * pSims;
+    assert( iFrame < p->nFrames );
+    assert( Aig_ObjIsCi(pObj) );
+    pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame;
+    pSims[iWord] = Word;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assings distance-1 simulation info for the PIs.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlAssignDist1( Ssw_Sml_t * p, unsigned * pPat )
+{
+    Aig_Obj_t * pObj;
+    int f, i, k, Limit, nTruePis;
+    assert( p->nFrames > 0 );
+    if ( p->nFrames == 1 )
+    {
+        // copy the PI info
+        Aig_ManForEachCi( p->pAig, pObj, i )
+            Ssw_SmlObjAssignConst( p, pObj, Abc_InfoHasBit(pPat, i), 0 );
+        // flip one bit
+        Limit = Abc_MinInt( Aig_ManCiNum(p->pAig), p->nWordsTotal * 32 - 1 );
+        for ( i = 0; i < Limit; i++ )
+            Abc_InfoXorBit( Ssw_ObjSim( p, Aig_ManCi(p->pAig,i)->Id ), i+1 );
+    }
+    else
+    {
+        int fUseDist1 = 0;
+
+        // copy the PI info for each frame
+        nTruePis = Aig_ManCiNum(p->pAig) - Aig_ManRegNum(p->pAig);
+        for ( f = 0; f < p->nFrames; f++ )
+            Saig_ManForEachPi( p->pAig, pObj, i )
+                Ssw_SmlObjAssignConst( p, pObj, Abc_InfoHasBit(pPat, nTruePis * f + i), f );
+        // copy the latch info
+        k = 0;
+        Saig_ManForEachLo( p->pAig, pObj, i )
+            Ssw_SmlObjAssignConst( p, pObj, Abc_InfoHasBit(pPat, nTruePis * p->nFrames + k++), 0 );
+//        assert( p->pFrames == NULL || nTruePis * p->nFrames + k == Aig_ManCiNum(p->pFrames) );
+
+        // flip one bit of the last frame
+        if ( fUseDist1 ) //&& p->nFrames == 2 )
+        {
+            Limit = Abc_MinInt( nTruePis, p->nWordsFrame * 32 - 1 );
+            for ( i = 0; i < Limit; i++ )
+                Abc_InfoXorBit( Ssw_ObjSim( p, Aig_ManCi(p->pAig, i)->Id ) + p->nWordsFrame*(p->nFrames-1), i+1 );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assings distance-1 simulation info for the PIs.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlAssignDist1Plus( Ssw_Sml_t * p, unsigned * pPat )
+{
+    Aig_Obj_t * pObj;
+    int f, i, Limit;
+    assert( p->nFrames > 0 );
+
+    // copy the pattern into the primary inputs
+    Aig_ManForEachCi( p->pAig, pObj, i )
+        Ssw_SmlObjAssignConst( p, pObj, Abc_InfoHasBit(pPat, i), 0 );
+
+    // set distance one PIs for the first frame
+    Limit = Abc_MinInt( Saig_ManPiNum(p->pAig), p->nWordsFrame * 32 - 1 );
+    for ( i = 0; i < Limit; i++ )
+        Abc_InfoXorBit( Ssw_ObjSim( p, Aig_ManCi(p->pAig, i)->Id ), i+1 );
+
+    // create random info for the remaining timeframes
+    for ( f = 1; f < p->nFrames; f++ )
+        Saig_ManForEachPi( p->pAig, pObj, i )
+            Ssw_SmlAssignRandomFrame( p, pObj, f );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlNodeSimulate( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame )
+{
+    unsigned * pSims, * pSims0, * pSims1;
+    int fCompl, fCompl0, fCompl1, i;
+    assert( iFrame < p->nFrames );
+    assert( !Aig_IsComplement(pObj) );
+    assert( Aig_ObjIsNode(pObj) );
+    assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal );
+    // get hold of the simulation information
+    pSims  = Ssw_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame;
+    pSims0 = Ssw_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame;
+    pSims1 = Ssw_ObjSim(p, Aig_ObjFanin1(pObj)->Id) + p->nWordsFrame * iFrame;
+    // get complemented attributes of the children using their random info
+    fCompl  = pObj->fPhase;
+    fCompl0 = Aig_ObjPhaseReal(Aig_ObjChild0(pObj));
+    fCompl1 = Aig_ObjPhaseReal(Aig_ObjChild1(pObj));
+    // simulate
+    if ( fCompl0 && fCompl1 )
+    {
+        if ( fCompl )
+            for ( i = 0; i < p->nWordsFrame; i++ )
+                pSims[i] = (pSims0[i] | pSims1[i]);
+        else
+            for ( i = 0; i < p->nWordsFrame; i++ )
+                pSims[i] = ~(pSims0[i] | pSims1[i]);
+    }
+    else if ( fCompl0 && !fCompl1 )
+    {
+        if ( fCompl )
+            for ( i = 0; i < p->nWordsFrame; i++ )
+                pSims[i] = (pSims0[i] | ~pSims1[i]);
+        else
+            for ( i = 0; i < p->nWordsFrame; i++ )
+                pSims[i] = (~pSims0[i] & pSims1[i]);
+    }
+    else if ( !fCompl0 && fCompl1 )
+    {
+        if ( fCompl )
+            for ( i = 0; i < p->nWordsFrame; i++ )
+                pSims[i] = (~pSims0[i] | pSims1[i]);
+        else
+            for ( i = 0; i < p->nWordsFrame; i++ )
+                pSims[i] = (pSims0[i] & ~pSims1[i]);
+    }
+    else // if ( !fCompl0 && !fCompl1 )
+    {
+        if ( fCompl )
+            for ( i = 0; i < p->nWordsFrame; i++ )
+                pSims[i] = ~(pSims0[i] & pSims1[i]);
+        else
+            for ( i = 0; i < p->nWordsFrame; i++ )
+                pSims[i] = (pSims0[i] & pSims1[i]);
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SmlNodesCompareInFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int iFrame0, int iFrame1 )
+{
+    unsigned * pSims0, * pSims1;
+    int i;
+    assert( iFrame0 < p->nFrames );
+    assert( iFrame1 < p->nFrames );
+    assert( !Aig_IsComplement(pObj0) );
+    assert( !Aig_IsComplement(pObj1) );
+    assert( iFrame0 == 0 || p->nWordsFrame < p->nWordsTotal );
+    assert( iFrame1 == 0 || p->nWordsFrame < p->nWordsTotal );
+    // get hold of the simulation information
+    pSims0  = Ssw_ObjSim(p, pObj0->Id) + p->nWordsFrame * iFrame0;
+    pSims1  = Ssw_ObjSim(p, pObj1->Id) + p->nWordsFrame * iFrame1;
+    // compare
+    for ( i = 0; i < p->nWordsFrame; i++ )
+        if ( pSims0[i] != pSims1[i] )
+            return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlNodeCopyFanin( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame )
+{
+    unsigned * pSims, * pSims0;
+    int fCompl, fCompl0, i;
+    assert( iFrame < p->nFrames );
+    assert( !Aig_IsComplement(pObj) );
+    assert( Aig_ObjIsCo(pObj) );
+    assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal );
+    // get hold of the simulation information
+    pSims  = Ssw_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame;
+    pSims0 = Ssw_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame;
+    // get complemented attributes of the children using their random info
+    fCompl  = pObj->fPhase;
+    fCompl0 = Aig_ObjPhaseReal(Aig_ObjChild0(pObj));
+    // copy information as it is
+    if ( fCompl0 )
+        for ( i = 0; i < p->nWordsFrame; i++ )
+            pSims[i] = ~pSims0[i];
+    else
+        for ( i = 0; i < p->nWordsFrame; i++ )
+            pSims[i] = pSims0[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlNodeTransferNext( Ssw_Sml_t * p, Aig_Obj_t * pOut, Aig_Obj_t * pIn, int iFrame )
+{
+    unsigned * pSims0, * pSims1;
+    int i;
+    assert( iFrame < p->nFrames );
+    assert( !Aig_IsComplement(pOut) );
+    assert( !Aig_IsComplement(pIn) );
+    assert( Aig_ObjIsCo(pOut) );
+    assert( Aig_ObjIsCi(pIn) );
+    assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal );
+    // get hold of the simulation information
+    pSims0 = Ssw_ObjSim(p, pOut->Id) + p->nWordsFrame * iFrame;
+    pSims1 = Ssw_ObjSim(p, pIn->Id) + p->nWordsFrame * (iFrame+1);
+    // copy information as it is
+    for ( i = 0; i < p->nWordsFrame; i++ )
+        pSims1[i] = pSims0[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlNodeTransferFirst( Ssw_Sml_t * p, Aig_Obj_t * pOut, Aig_Obj_t * pIn )
+{
+    unsigned * pSims0, * pSims1;
+    int i;
+    assert( !Aig_IsComplement(pOut) );
+    assert( !Aig_IsComplement(pIn) );
+    assert( Aig_ObjIsCo(pOut) );
+    assert( Aig_ObjIsCi(pIn) );
+    assert( p->nWordsFrame < p->nWordsTotal );
+    // get hold of the simulation information
+    pSims0 = Ssw_ObjSim(p, pOut->Id) + p->nWordsFrame * (p->nFrames-1);
+    pSims1 = Ssw_ObjSim(p, pIn->Id);
+    // copy information as it is
+    for ( i = 0; i < p->nWordsFrame; i++ )
+        pSims1[i] = pSims0[i];
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Assings random simulation info for the PIs.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlInitialize( Ssw_Sml_t * p, int fInit )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    if ( fInit )
+    {
+        assert( Aig_ManRegNum(p->pAig) > 0 );
+        assert( Aig_ManRegNum(p->pAig) <= Aig_ManCiNum(p->pAig) );
+        // assign random info for primary inputs
+        Saig_ManForEachPi( p->pAig, pObj, i )
+            Ssw_SmlAssignRandom( p, pObj );
+        // assign the initial state for the latches
+        Saig_ManForEachLo( p->pAig, pObj, i )
+            Ssw_SmlObjAssignConst( p, pObj, 0, 0 );
+    }
+    else
+    {
+        Aig_ManForEachCi( p->pAig, pObj, i )
+            Ssw_SmlAssignRandom( p, pObj );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assings random simulation info for the PIs.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlInitializeSpecial( Ssw_Sml_t * p, Vec_Int_t * vInit )
+{
+    Aig_Obj_t * pObj;
+    int Entry, i, nRegs;
+    nRegs = Aig_ManRegNum(p->pAig);
+    assert( nRegs > 0 );
+    assert( nRegs <= Aig_ManCiNum(p->pAig) );
+    assert( Vec_IntSize(vInit) == nRegs * p->nWordsFrame );
+    // assign random info for primary inputs
+    Saig_ManForEachPi( p->pAig, pObj, i )
+        Ssw_SmlAssignRandom( p, pObj );
+    // assign the initial state for the latches
+    Vec_IntForEachEntry( vInit, Entry, i )
+        Ssw_SmlObjAssignConstWord( p, Saig_ManLo(p->pAig, i % nRegs), Entry, 0, i / nRegs );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assings random simulation info for the PIs.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlReinitialize( Ssw_Sml_t * p )
+{
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i;
+    assert( Aig_ManRegNum(p->pAig) > 0 );
+    assert( Aig_ManRegNum(p->pAig) < Aig_ManCiNum(p->pAig) );
+    // assign random info for primary inputs
+    Saig_ManForEachPi( p->pAig, pObj, i )
+        Ssw_SmlAssignRandom( p, pObj );
+    // copy simulation info into the inputs
+    Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+        Ssw_SmlNodeTransferFirst( p, pObjLi, pObjLo );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Check if any of the POs becomes non-constant.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SmlCheckNonConstOutputs( Ssw_Sml_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Saig_ManForEachPo( p->pAig, pObj, i )
+    {
+        if ( p->pAig->nConstrs && i >= Saig_ManPoNum(p->pAig) - p->pAig->nConstrs )
+            return 0;
+        if ( !Ssw_SmlNodeIsZero(p, pObj) )
+            return 1;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates AIG manager.]
+
+  Description [Assumes that the PI simulation info is attached.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlSimulateOne( Ssw_Sml_t * p )
+{
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int f, i;
+    abctime clk;
+clk = Abc_Clock();
+    for ( f = 0; f < p->nFrames; f++ )
+    {
+        // simulate the nodes
+        Aig_ManForEachNode( p->pAig, pObj, i )
+            Ssw_SmlNodeSimulate( p, pObj, f );
+        // copy simulation info into outputs
+        Saig_ManForEachPo( p->pAig, pObj, i )
+            Ssw_SmlNodeCopyFanin( p, pObj, f );
+        // copy simulation info into outputs
+        Saig_ManForEachLi( p->pAig, pObj, i )
+            Ssw_SmlNodeCopyFanin( p, pObj, f );
+        // quit if this is the last timeframe
+        if ( f == p->nFrames - 1 )
+            break;
+        // copy simulation info into the inputs
+        Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+            Ssw_SmlNodeTransferNext( p, pObjLi, pObjLo, f );
+    }
+p->timeSim += Abc_Clock() - clk;
+p->nSimRounds++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts simulation information to be not normallized.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlUnnormalize( Ssw_Sml_t * p )
+{
+    Aig_Obj_t * pObj;
+    unsigned * pSims;
+    int i, k;
+    // convert constant 1
+    pSims  = Ssw_ObjSim( p, 0 );
+    for ( i = 0; i < p->nWordsFrame; i++ )
+        pSims[i] = ~pSims[i];
+    // convert internal nodes
+    Aig_ManForEachNode( p->pAig, pObj, k )
+    {
+        if ( pObj->fPhase == 0 )
+            continue;
+        pSims  = Ssw_ObjSim( p, pObj->Id );
+        for ( i = 0; i < p->nWordsFrame; i++ )
+            pSims[i] = ~pSims[i];
+    }
+    // PIs/POs are always stored in their natural state
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates AIG manager.]
+
+  Description [Assumes that the PI simulation info is attached.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlSimulateOneDyn_rec( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f, int * pVisited, int nVisCounter )
+{
+//    if ( Aig_ObjIsTravIdCurrent(p->pAig, pObj) )
+//        return;
+//    Aig_ObjSetTravIdCurrent(p->pAig, pObj);
+    if ( pVisited[p->nFrames*pObj->Id+f] == nVisCounter )
+        return;
+    pVisited[p->nFrames*pObj->Id+f] = nVisCounter;
+    if ( Saig_ObjIsPi( p->pAig, pObj ) || Aig_ObjIsConst1(pObj) )
+        return;
+    if ( Saig_ObjIsLo( p->pAig, pObj ) )
+    {
+        if ( f == 0 )
+            return;
+        Ssw_SmlSimulateOneDyn_rec( p, Saig_ObjLoToLi(p->pAig, pObj), f-1, pVisited, nVisCounter );
+        Ssw_SmlNodeTransferNext( p, Saig_ObjLoToLi(p->pAig, pObj), pObj, f-1 );
+        return;
+    }
+    if ( Saig_ObjIsLi( p->pAig, pObj ) )
+    {
+        Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin0(pObj), f, pVisited, nVisCounter );
+        Ssw_SmlNodeCopyFanin( p, pObj, f );
+        return;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin0(pObj), f, pVisited, nVisCounter );
+    Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin1(pObj), f, pVisited, nVisCounter );
+    Ssw_SmlNodeSimulate( p, pObj, f );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates AIG manager.]
+
+  Description [Assumes that the PI simulation info is attached.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlSimulateOneFrame( Ssw_Sml_t * p )
+{
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i;
+    abctime clk;
+clk = Abc_Clock();
+    // simulate the nodes
+    Aig_ManForEachNode( p->pAig, pObj, i )
+        Ssw_SmlNodeSimulate( p, pObj, 0 );
+    // copy simulation info into outputs
+    Saig_ManForEachLi( p->pAig, pObj, i )
+        Ssw_SmlNodeCopyFanin( p, pObj, 0 );
+    // copy simulation info into the inputs
+    Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+        Ssw_SmlNodeTransferNext( p, pObjLi, pObjLo, 0 );
+p->timeSim += Abc_Clock() - clk;
+p->nSimRounds++;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates simulation manager.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ssw_Sml_t * Ssw_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame )
+{
+    Ssw_Sml_t * p;
+    p = (Ssw_Sml_t *)ABC_ALLOC( char, sizeof(Ssw_Sml_t) + sizeof(unsigned) * Aig_ManObjNumMax(pAig) * (nPref + nFrames) * nWordsFrame );
+    memset( p, 0, sizeof(Ssw_Sml_t) + sizeof(unsigned) * (nPref + nFrames) * nWordsFrame );
+    p->pAig        = pAig;
+    p->nPref       = nPref;
+    p->nFrames     = nPref + nFrames;
+    p->nWordsFrame = nWordsFrame;
+    p->nWordsTotal = (nPref + nFrames) * nWordsFrame;
+    p->nWordsPref  = nPref * nWordsFrame;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates simulation manager.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlClean( Ssw_Sml_t * p )
+{
+    memset( p->pData, 0, sizeof(unsigned) * Aig_ManObjNumMax(p->pAig) * p->nWordsTotal );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Get simulation data.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Ssw_SmlSimDataPointers( Ssw_Sml_t * p )
+{
+    Vec_Ptr_t * vSimInfo;
+    Aig_Obj_t * pObj;
+    int i;
+    vSimInfo = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) );
+    Aig_ManForEachObj( p->pAig, pObj, i )
+        Vec_PtrWriteEntry( vSimInfo, i, Ssw_ObjSim(p, i) );
+    return vSimInfo;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates simulation manager.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlStop( Ssw_Sml_t * p )
+{
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs simulation of the uninitialized circuit.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ssw_Sml_t * Ssw_SmlSimulateComb( Aig_Man_t * pAig, int nWords )
+{
+    Ssw_Sml_t * p;
+    p = Ssw_SmlStart( pAig, 0, 1, nWords );
+    Ssw_SmlInitialize( p, 0 );
+    Ssw_SmlSimulateOne( p );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs simulation of the initialized circuit.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ssw_Sml_t * Ssw_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords )
+{
+    Ssw_Sml_t * p;
+    p = Ssw_SmlStart( pAig, nPref, nFrames, nWords );
+    Ssw_SmlInitialize( p, 1 );
+    Ssw_SmlSimulateOne( p );
+    p->fNonConstOut = Ssw_SmlCheckNonConstOutputs( p );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs next round of sequential simulation.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlResimulateSeq( Ssw_Sml_t * p )
+{
+    Ssw_SmlReinitialize( p );
+    Ssw_SmlSimulateOne( p );
+    p->fNonConstOut = Ssw_SmlCheckNonConstOutputs( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of frames simulated in the manager.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SmlNumFrames( Ssw_Sml_t * p )
+{
+    return p->nFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the total number of simulation words.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_SmlNumWordsTotal( Ssw_Sml_t * p )
+{
+    return p->nWordsTotal;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the pointer to the simulation info of the node.]
+
+  Description [The simulation info is normalized unless procedure
+  Ssw_SmlUnnormalize() is called in advance.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Ssw_SmlSimInfo( Ssw_Sml_t * p, Aig_Obj_t * pObj )
+{
+    assert( !Aig_IsComplement(pObj) );
+    return Ssw_ObjSim( p, pObj->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates sequential counter-example from the simulation info.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Ssw_SmlGetCounterExample( Ssw_Sml_t * p )
+{
+    Abc_Cex_t * pCex;
+    Aig_Obj_t * pObj;
+    unsigned * pSims;
+    int iPo, iFrame, iBit, i, k;
+
+    // make sure the simulation manager has it
+    assert( p->fNonConstOut );
+
+    // find the first output that failed
+    iPo = -1;
+    iBit = -1;
+    iFrame = -1;
+    Saig_ManForEachPo( p->pAig, pObj, iPo )
+    {
+        if ( Ssw_SmlNodeIsZero(p, pObj) )
+            continue;
+        pSims = Ssw_ObjSim( p, pObj->Id );
+        for ( i = p->nWordsPref; i < p->nWordsTotal; i++ )
+            if ( pSims[i] )
+            {
+                iFrame = i / p->nWordsFrame;
+                iBit = 32 * (i % p->nWordsFrame) + Aig_WordFindFirstBit( pSims[i] );
+                break;
+            }
+        break;
+    }
+    assert( iPo < Aig_ManCoNum(p->pAig)-Aig_ManRegNum(p->pAig) );
+    assert( iFrame < p->nFrames );
+    assert( iBit < 32 * p->nWordsFrame );
+
+    // allocate the counter example
+    pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Aig_ManCiNum(p->pAig) - Aig_ManRegNum(p->pAig), iFrame + 1 );
+    pCex->iPo    = iPo;
+    pCex->iFrame = iFrame;
+
+    // copy the bit data
+    Saig_ManForEachLo( p->pAig, pObj, k )
+    {
+        pSims = Ssw_ObjSim( p, pObj->Id );
+        if ( Abc_InfoHasBit( pSims, iBit ) )
+            Abc_InfoSetBit( pCex->pData, k );
+    }
+    for ( i = 0; i <= iFrame; i++ )
+    {
+        Saig_ManForEachPi( p->pAig, pObj, k )
+        {
+            pSims = Ssw_ObjSim( p, pObj->Id );
+            if ( Abc_InfoHasBit( pSims, 32 * p->nWordsFrame * i + iBit ) )
+                Abc_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * i + k );
+        }
+    }
+    // verify the counter example
+    if ( !Saig_ManVerifyCex( p->pAig, pCex ) )
+    {
+        Abc_Print( 1, "Ssw_SmlGetCounterExample(): Counter-example is invalid.\n" );
+        Abc_CexFree( pCex );
+        pCex = NULL;
+    }
+    return pCex;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswSimSat.c b/abc-build/src/proof/ssw/sswSimSat.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswSimSat.c
@@ -0,0 +1,124 @@
+/**CFile****************************************************************
+
+  FileName    [sswSimSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [Performs resimulation using counter-examples.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswSimSat.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Handle the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManResimulateBit( Ssw_Man_t * p, Aig_Obj_t * pCand, Aig_Obj_t * pRepr )
+{
+    Aig_Obj_t * pObj;
+    int i, RetValue1, RetValue2;
+    abctime clk = Abc_Clock();
+    // set the PI simulation information
+    Aig_ManConst1(p->pAig)->fMarkB = 1;
+    Aig_ManForEachCi( p->pAig, pObj, i )
+        pObj->fMarkB = Abc_InfoHasBit( p->pPatWords, i );
+    // simulate internal nodes
+    Aig_ManForEachNode( p->pAig, pObj, i )
+        pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+                     & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+    // if repr is given, perform refinement
+    if ( pRepr )
+    {
+        // check equivalence classes
+        RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 0 );
+        RetValue2 = Ssw_ClassesRefine( p->ppClasses, 0 );
+        // make sure refinement happened
+        if ( Aig_ObjIsConst1(pRepr) )
+        {
+            assert( RetValue1 );
+            if ( RetValue1 == 0 )
+                Abc_Print( 1, "\nSsw_ManResimulateBit() Error: RetValue1 does not hold.\n" );
+        }
+        else
+        {
+            assert( RetValue2 );
+            if ( RetValue2 == 0 )
+                Abc_Print( 1, "\nSsw_ManResimulateBit() Error: RetValue2 does not hold.\n" );
+        }
+    }
+p->timeSimSat += Abc_Clock() - clk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Handle the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManResimulateWord( Ssw_Man_t * p, Aig_Obj_t * pCand, Aig_Obj_t * pRepr, int f )
+{
+    int RetValue1, RetValue2;
+    abctime clk = Abc_Clock();
+    // set the PI simulation information
+    Ssw_SmlAssignDist1Plus( p->pSml, p->pPatWords );
+    // simulate internal nodes
+    Ssw_SmlSimulateOne( p->pSml );
+    // check equivalence classes
+    RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 );
+    RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 );
+    // make sure refinement happened
+    if ( Aig_ObjIsConst1(pRepr) )
+    {
+        assert( RetValue1 );
+        if ( RetValue1 == 0 )
+            Abc_Print( 1, "\nSsw_ManResimulateWord() Error: RetValue1 does not hold.\n" );
+    }
+    else
+    {
+        assert( RetValue2 );
+        if ( RetValue2 == 0 )
+            Abc_Print( 1, "\nSsw_ManResimulateWord() Error: RetValue2 does not hold.\n" );
+    }
+p->timeSimSat += Abc_Clock() - clk;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswSweep.c b/abc-build/src/proof/ssw/sswSweep.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswSweep.c
@@ -0,0 +1,437 @@
+/**CFile****************************************************************
+
+  FileName    [sswSweep.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [One round of SAT sweeping.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswSweep.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+#include "misc/bar/bar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Retrives value of the PI in the original AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManGetSatVarValue( Ssw_Man_t * p, Aig_Obj_t * pObj, int f )
+{
+    int fUseNoBoundary = 0;
+    Aig_Obj_t * pObjFraig;
+    int Value;
+//    assert( Aig_ObjIsCi(pObj) );
+    pObjFraig = Ssw_ObjFrame( p, pObj, f );
+    if ( fUseNoBoundary )
+    {
+        Value = Ssw_CnfGetNodeValue( p->pMSat, Aig_Regular(pObjFraig) );
+        Value ^= Aig_IsComplement(pObjFraig);
+    }
+    else
+    {
+        int nVarNum = Ssw_ObjSatNum( p->pMSat, Aig_Regular(pObjFraig) );
+        Value = (!nVarNum)? 0 : (Aig_IsComplement(pObjFraig) ^ sat_solver_var_value( p->pMSat->pSat, nVarNum ));
+    }
+
+//    Value = (Aig_IsComplement(pObjFraig) ^ ((!nVarNum)? 0 : sat_solver_var_value( p->pSat, nVarNum )));
+//    Value = (!nVarNum)? Aig_ManRandom(0) & 1 : (Aig_IsComplement(pObjFraig) ^ sat_solver_var_value( p->pSat, nVarNum ));
+    if ( p->pPars->fPolarFlip )
+    {
+        if ( Aig_Regular(pObjFraig)->fPhase )  Value ^= 1;
+    }
+    return Value;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_CheckConstraints( Ssw_Man_t * p )
+{
+    Aig_Obj_t * pObj, * pObj2;
+    int nConstrPairs, i;
+    int Counter = 0;
+    nConstrPairs = Aig_ManCoNum(p->pFrames)-Aig_ManRegNum(p->pAig);
+    assert( (nConstrPairs & 1) == 0 );
+    for ( i = 0; i < nConstrPairs; i += 2 )
+    {
+        pObj  = Aig_ManCo( p->pFrames, i   );
+        pObj2 = Aig_ManCo( p->pFrames, i+1 );
+        if ( Ssw_NodesAreEquiv( p, Aig_ObjFanin0(pObj), Aig_ObjFanin0(pObj2) ) != 1 )
+        {
+            Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj), Aig_ObjChild0(pObj2) );
+            Counter++;
+        }
+    }
+    Abc_Print( 1, "Total constraints = %d. Added constraints = %d.\n", nConstrPairs/2, Counter );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Copy pattern from the solver into the internal storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlSavePatternAigPhase( Ssw_Man_t * p, int f )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+    Aig_ManForEachCi( p->pAig, pObj, i )
+        if ( Aig_ObjPhaseReal( Ssw_ObjFrame(p, pObj, f) ) )
+            Abc_InfoSetBit( p->pPatWords, i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Copy pattern from the solver into the internal storage.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlSavePatternAig( Ssw_Man_t * p, int f )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+    Aig_ManForEachCi( p->pAig, pObj, i )
+        if ( Ssw_ManGetSatVarValue( p, pObj, f ) )
+            Abc_InfoSetBit( p->pPatWords, i );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Saves one counter-example into internal storage.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_SmlAddPatternDyn( Ssw_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    unsigned * pInfo;
+    int i, nVarNum;
+    // iterate through the PIs of the frames
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->pMSat->vUsedPis, pObj, i )
+    {
+        assert( Aig_ObjIsCi(pObj) );
+        nVarNum = Ssw_ObjSatNum( p->pMSat, pObj );
+        assert( nVarNum > 0 );
+        if ( sat_solver_var_value( p->pMSat->pSat, nVarNum ) )
+        {
+            pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjCioId(pObj) );
+            Abc_InfoSetBit( pInfo, p->nPatterns );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for one node.]
+
+  Description [Returns the fraiged node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManSweepNode( Ssw_Man_t * p, Aig_Obj_t * pObj, int f, int fBmc, Vec_Int_t * vPairs )
+{
+    Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig;
+    int RetValue;
+    abctime clk;
+    // get representative of this class
+    pObjRepr = Aig_ObjRepr( p->pAig, pObj );
+    if ( pObjRepr == NULL )
+        return 0;
+    // get the fraiged node
+    pObjFraig = Ssw_ObjFrame( p, pObj, f );
+    // get the fraiged representative
+    pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, f );
+    // check if constant 0 pattern distinquishes these nodes
+    assert( pObjFraig != NULL && pObjReprFraig != NULL );
+    assert( (pObj->fPhase == pObjRepr->fPhase) == (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) );
+    // if the fraiged nodes are the same, return
+    if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) )
+        return 0;
+    // add constraints on demand
+    if ( !fBmc && p->pPars->fDynamic )
+    {
+clk = Abc_Clock();
+        Ssw_ManLoadSolver( p, pObjRepr, pObj );
+        p->nRecycleCalls++;
+p->timeMarkCones += Abc_Clock() - clk;
+    }
+    // call equivalence checking
+    if ( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pFrames) )
+        RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) );
+    else
+        RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) );
+    if ( RetValue == 1 )  // proved equivalent
+    {
+        pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase );
+        Ssw_ObjSetFrame( p, pObj, f, pObjFraig2 );
+        return 0;
+    }
+    if ( vPairs )
+    {
+        Vec_IntPush( vPairs, pObjRepr->Id );
+        Vec_IntPush( vPairs, pObj->Id );
+    }
+    if ( RetValue == -1 ) // timed out
+    {
+        Ssw_ClassesRemoveNode( p->ppClasses, pObj );
+        return 1;
+    }
+    // disproved the equivalence
+    if ( !fBmc && p->pPars->fDynamic )
+    {
+        Ssw_SmlAddPatternDyn( p );
+        p->nPatterns++;
+        return 1;
+    }
+    else
+        Ssw_SmlSavePatternAig( p, f );
+    if ( !p->pPars->fConstrs )
+        Ssw_ManResimulateWord( p, pObj, pObjRepr, f );
+    else
+        Ssw_ManResimulateBit( p, pObj, pObjRepr );
+    assert( Aig_ObjRepr( p->pAig, pObj ) != pObjRepr );
+    if ( Aig_ObjRepr( p->pAig, pObj ) == pObjRepr )
+    {
+        Abc_Print( 1, "Ssw_ManSweepNode(): Failed to refine representative.\n" );
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManSweepBmc( Ssw_Man_t * p )
+{
+    Bar_Progress_t * pProgress = NULL;
+    Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo;
+    int i, f;
+    abctime clk;
+clk = Abc_Clock();
+
+    // start initialized timeframes
+    p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK );
+    Saig_ManForEachLo( p->pAig, pObj, i )
+        Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) );
+
+    // sweep internal nodes
+    p->fRefined = 0;
+    if ( p->pPars->fVerbose )
+        pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK );
+    for ( f = 0; f < p->pPars->nFramesK; f++ )
+    {
+        // map constants and PIs
+        Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
+        Saig_ManForEachPi( p->pAig, pObj, i )
+            Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreateCi(p->pFrames) );
+        // sweep internal nodes
+        Aig_ManForEachNode( p->pAig, pObj, i )
+        {
+            if ( p->pPars->fVerbose )
+                Bar_ProgressUpdate( pProgress, Aig_ManObjNumMax(p->pAig) * f + i, NULL );
+            pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+            Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+            p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 1, NULL );
+        }
+        // quit if this is the last timeframe
+        if ( f == p->pPars->nFramesK - 1 )
+            break;
+        // transfer latch input to the latch outputs
+        Aig_ManForEachCo( p->pAig, pObj, i )
+            Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) );
+        // build logic cones for register outputs
+        Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+        {
+            pObjNew = Ssw_ObjFrame( p, pObjLi, f );
+            Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew );
+            Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );//
+        }
+    }
+    if ( p->pPars->fVerbose )
+        Bar_ProgressStop( pProgress );
+
+    // cleanup
+//    Ssw_ClassesCheck( p->ppClasses );
+p->timeBmc += Abc_Clock() - clk;
+    return p->fRefined;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Generates AIG with the following nodes put into seq miters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_ManDumpEquivMiter( Aig_Man_t * p, Vec_Int_t * vPairs, int Num )
+{
+    FILE * pFile;
+    char pBuffer[16];
+    Aig_Man_t * pNew;
+    sprintf( pBuffer, "equiv%03d.aig", Num );
+    pFile = fopen( pBuffer, "w" );
+    if ( pFile == NULL )
+    {
+        Abc_Print( 1, "Cannot open file %s for writing.\n", pBuffer );
+        return;
+    }
+    fclose( pFile );
+    pNew = Saig_ManCreateEquivMiter( p, vPairs );
+    Ioa_WriteAiger( pNew, pBuffer, 0, 0 );
+    Aig_ManStop( pNew );
+    Abc_Print( 1, "AIG with %4d disproved equivs is dumped into file \"%s\".\n", Vec_IntSize(vPairs)/2, pBuffer );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Performs fraiging for the internal nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManSweep( Ssw_Man_t * p )
+{
+    static int Counter;
+    Bar_Progress_t * pProgress = NULL;
+    Aig_Obj_t * pObj, * pObj2, * pObjNew;
+    int nConstrPairs, i, f;
+    abctime clk;
+    Vec_Int_t * vDisproved;
+
+    // perform speculative reduction
+clk = Abc_Clock();
+    // create timeframes
+    p->pFrames = Ssw_FramesWithClasses( p );
+    // add constants
+    nConstrPairs = Aig_ManCoNum(p->pFrames)-Aig_ManRegNum(p->pAig);
+    assert( (nConstrPairs & 1) == 0 );
+    for ( i = 0; i < nConstrPairs; i += 2 )
+    {
+        pObj  = Aig_ManCo( p->pFrames, i   );
+        pObj2 = Aig_ManCo( p->pFrames, i+1 );
+        Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj), Aig_ObjChild0(pObj2) );
+    }
+    // build logic cones for register inputs
+    for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ )
+    {
+        pObj  = Aig_ManCo( p->pFrames, nConstrPairs + i );
+        Ssw_CnfNodeAddToSolver( p->pMSat, Aig_ObjFanin0(pObj) );//
+    }
+    sat_solver_simplify( p->pMSat->pSat );
+
+    // map constants and PIs of the last frame
+    f = p->pPars->nFramesK;
+    Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
+    Saig_ManForEachPi( p->pAig, pObj, i )
+        Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreateCi(p->pFrames) );
+p->timeReduce += Abc_Clock() - clk;
+
+    // sweep internal nodes
+    p->fRefined = 0;
+    Ssw_ClassesClearRefined( p->ppClasses );
+    if ( p->pPars->fVerbose )
+        pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) );
+    vDisproved = p->pPars->fEquivDump? Vec_IntAlloc(1000) : NULL;
+    Aig_ManForEachObj( p->pAig, pObj, i )
+    {
+        if ( p->pPars->fVerbose )
+            Bar_ProgressUpdate( pProgress, i, NULL );
+        if ( Saig_ObjIsLo(p->pAig, pObj) )
+            p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, vDisproved );
+        else if ( Aig_ObjIsNode(pObj) )
+        {
+            pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+            Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+            p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, vDisproved );
+        }
+    }
+    if ( p->pPars->fVerbose )
+        Bar_ProgressStop( pProgress );
+
+    // cleanup
+//    Ssw_ClassesCheck( p->ppClasses );
+    if ( p->pPars->fEquivDump )
+        Ssw_ManDumpEquivMiter( p->pAig, vDisproved, Counter++ );
+    Vec_IntFreeP( &vDisproved );
+    return p->fRefined;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/proof/ssw/sswUnique.c b/abc-build/src/proof/ssw/sswUnique.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/proof/ssw/sswUnique.c
@@ -0,0 +1,196 @@
+/**CFile****************************************************************
+
+  FileName    [sswSat.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Inductive prover with constraints.]
+
+  Synopsis    [On-demand uniqueness constraints.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 1, 2008.]
+
+  Revision    [$Id: sswSat.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs computation of signal correspondence with constraints.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ssw_UniqueRegisterPairInfo( Ssw_Man_t * p )
+{
+    Aig_Obj_t * pObjLo, * pObj0, * pObj1;
+    int i, RetValue, Counter;
+    if ( p->vDiffPairs == NULL )
+        p->vDiffPairs = Vec_IntAlloc( Saig_ManRegNum(p->pAig) );
+    Vec_IntClear( p->vDiffPairs );
+    Saig_ManForEachLo( p->pAig, pObjLo, i )
+    {
+        pObj0 = Ssw_ObjFrame( p, pObjLo, 0 );
+        pObj1 = Ssw_ObjFrame( p, pObjLo, 1 );
+        if ( pObj0 == pObj1 )
+            Vec_IntPush( p->vDiffPairs, 0 );
+        else if ( pObj0 == Aig_Not(pObj1) )
+            Vec_IntPush( p->vDiffPairs, 1 );
+//        else
+//            Vec_IntPush( p->vDiffPairs, 1 );
+        else if ( Aig_ObjPhaseReal(pObj0) != Aig_ObjPhaseReal(pObj1) )
+            Vec_IntPush( p->vDiffPairs, 1 );
+        else
+        {
+            RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObj0), Aig_Regular(pObj1) );
+            Vec_IntPush( p->vDiffPairs, RetValue!=1 );
+        }
+    }
+    assert( Vec_IntSize(p->vDiffPairs) == Saig_ManRegNum(p->pAig) );
+    // count the number of ones
+    Counter = 0;
+    Vec_IntForEachEntry( p->vDiffPairs, RetValue, i )
+        Counter += RetValue;
+//    Abc_Print( 1, "The number of different register pairs = %d.\n", Counter );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if uniqueness constraints can be added.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManUniqueOne( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj, int fVerbose )
+{
+    Aig_Obj_t * ppObjs[2], * pTemp;
+    int i, k, Value0, Value1, RetValue, fFeasible;
+
+    assert( p->pPars->nFramesK > 1 );
+    assert( p->vDiffPairs && Vec_IntSize(p->vDiffPairs) == Saig_ManRegNum(p->pAig) );
+
+    // compute the first support in terms of LOs
+    ppObjs[0] = pRepr;
+    ppObjs[1] = pObj;
+    Aig_SupportNodes( p->pAig, ppObjs, 2, p->vCommon );
+    // keep only LOs
+    RetValue = Vec_PtrSize( p->vCommon );
+    fFeasible = 0;
+    k = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vCommon, pTemp, i )
+    {
+        assert( Aig_ObjIsCi(pTemp) );
+        if ( !Saig_ObjIsLo(p->pAig, pTemp) )
+            continue;
+        assert( Aig_ObjCioId(pTemp) > 0 );
+        Vec_PtrWriteEntry( p->vCommon, k++, pTemp );
+        if ( Vec_IntEntry(p->vDiffPairs, Aig_ObjCioId(pTemp) - Saig_ManPiNum(p->pAig)) )
+            fFeasible = 1;
+    }
+    Vec_PtrShrink( p->vCommon, k );
+
+    if ( fVerbose )
+        Abc_Print( 1, "Node = %5d : Supp = %3d. Regs = %3d. Feasible = %s. ",
+            Aig_ObjId(pObj), RetValue, Vec_PtrSize(p->vCommon),
+            fFeasible? "yes": "no " );
+
+    // check the current values
+    RetValue = 1;
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vCommon, pTemp, i )
+    {
+        Value0 = Ssw_ManGetSatVarValue( p, pTemp, 0 );
+        Value1 = Ssw_ManGetSatVarValue( p, pTemp, 1 );
+        if ( Value0 != Value1 )
+            RetValue = 0;
+        if ( fVerbose )
+            Abc_Print( 1, "%d", Value0 ^ Value1 );
+    }
+    if ( fVerbose )
+        Abc_Print( 1, "\n" );
+
+    return RetValue && fFeasible;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the output of the uniqueness constraint.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ssw_ManUniqueAddConstraint( Ssw_Man_t * p, Vec_Ptr_t * vCommon, int f1, int f2 )
+{
+    Aig_Obj_t * pObj, * pObj1New, * pObj2New, * pMiter, * pTotal;
+    int i, pLits[2];
+//    int RetValue;
+    assert( Vec_PtrSize(vCommon) > 0 );
+    // generate the constraint
+    pTotal = Aig_ManConst0(p->pFrames);
+    Vec_PtrForEachEntry( Aig_Obj_t *, vCommon, pObj, i )
+    {
+        assert( Saig_ObjIsLo(p->pAig, pObj) );
+        pObj1New = Ssw_ObjFrame( p, pObj, f1 );
+        pObj2New = Ssw_ObjFrame( p, pObj, f2 );
+        pMiter = Aig_Exor( p->pFrames, pObj1New, pObj2New );
+        pTotal = Aig_Or( p->pFrames, pTotal, pMiter );
+    }
+    if ( Aig_ObjIsConst1(Aig_Regular(pTotal)) )
+    {
+//        Abc_Print( 1, "Skipped\n" );
+        return 0;
+    }
+    // create CNF
+    Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pTotal) );
+    // add output constraint
+    pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,Aig_Regular(pTotal)), Aig_IsComplement(pTotal) );
+/*
+    RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+    assert( RetValue );
+    // simplify the solver
+    if ( p->pSat->qtail != p->pSat->qhead )
+    {
+        RetValue = sat_solver_simplify(p->pSat);
+        assert( RetValue != 0 );
+    }
+*/
+    assert( p->iOutputLit == -1 );
+    p->iOutputLit = pLits[0];
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/python/abc.sh b/abc-build/src/python/abc.sh
new file mode 100644
--- /dev/null
+++ b/abc-build/src/python/abc.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+#
+# Setup the ABC/Py environment and run the ABC/Py executable
+# (ABC/Py stands for ABC with embedded Python)
+#
+# ABC/Py expects the following directory structure
+#
+# abc_root/
+#   bin/
+#     abc - this script
+#     abc_exe - the ABC executable
+#	  ... - Other scripts
+#   lib/
+#     pyabc.py - support file for pyabc extension
+#     python_library.zip - The Python standard library. Only if not using the system Python interpreter.
+#     *.so - Python extensions, Only if not using the system Python interpreter.
+#   scripts/
+#     *.py - default directory for python scripts
+#             
+
+# usage: abspath <dir>
+# get the absolute path of <dir>
+abspath()
+{
+    cwd="$(pwd)"
+    cd "$1"
+    echo "$(pwd)"
+    cd "${cwd}"
+}
+
+self=$0
+
+self_dir=$(dirname "${self}")
+self_dir=$(abspath "${self_dir}")
+
+abc_root=$(dirname "${self_dir}")
+
+abc_exe="${abc_root}/bin/abc_exe"
+
+PYTHONPATH="${abc_root}/lib":"${PYTHONPATH}"
+export PYTHONPATH
+
+if [ -d "${abc_root}/scripts" ] ; then
+    ABC_PYTHON_SCRIPTS="${abc_root}/scripts"
+    export ABC_PYTHON_SCRIPTS
+    
+    PYTHONPATH="${ABC_PYTHON_SCRIPTS}":"${PYTHONPATH}"
+    export PYTHONPATH
+fi
+
+if [ -f "${abc_root}/scripts/abc.rc" ] ; then
+    ABC_PYTHON_ABC_RC="${abc_root}/scripts/abc.rc"
+    export ABC_PYTHON_ABC_RC
+fi
+
+if [ -f "${abc_root}/lib/python_library.zip" ] ; then
+    PYTHONHOME="${abc_root}"
+    export PYTHONHOME
+    
+    PYTHONPATH="${abc_root}/lib/python_library.zip":"${PYTHONPATH}"
+    export PYTHONPATH
+fi
+
+PATH="${abc_root}/bin:$PATH"
+export PATH
+
+if [ "$1" = "--debug" ]; then
+    shift
+    abc_debugger="$1"
+    shift
+    
+    echo export PYTHONHOME=$PYTHONHOME
+    echo export PYTHONPATH=$PYTHONPATH
+    echo export ABC_PYTHON_SCRIPTS=$ABC_PYTHON_SCRIPTS
+    echo export ABC_PYTHON_ABC_RC=$ABC_PYTHON_ABC_RC
+fi
+
+exec ${abc_debugger} "${abc_exe}" "$@"
diff --git a/abc-build/src/python/abcpy_test.py b/abc-build/src/python/abcpy_test.py
new file mode 100644
--- /dev/null
+++ b/abc-build/src/python/abcpy_test.py
@@ -0,0 +1,54 @@
+# You can use 'from pyabc import *' and then not need the pyabc. prefix everywhere
+import pyabc
+
+# A new command is just a function that accepts a list of string arguments
+#   The first argument is always the name of the command
+#   It MUST return an integer. -1: user quits, -2: error. Return 0 for success.
+
+# a simple command that just prints its arguments and returns success
+def pytest1_cmd(args):
+    print args
+    return 0
+
+# registers the command:
+#   The first argument is the function
+#   The second argument is the category (mainly for the ABC help command)
+#   The third argument is the new command name
+#   Keet the fourth argument 0, or consult with Alan
+pyabc.add_abc_command(pytest1_cmd, "Python-Test", "pytest1", 0)
+
+# a simple command that just prints its arguments and runs the command 'scorr -h'
+def pytest2_cmd(args):
+    print args
+    pyabc.run_command('scorr -h')
+    return 0
+
+pyabc.add_abc_command(pytest2_cmd, "Python-Test", "pytest2", 0)
+
+# Now a more complicated command with argument parsing
+# This command gets two command line arguments -c and -v. -c cmd runs the command 'cmd -h' and -v prints the python version
+# for more details see the optparse module: http://docs.python.org/library/optparse.html
+
+import optparse
+
+def pytest3_cmd(args):
+    usage = "usage: %prog [options]"
+    
+    parser = optparse.OptionParser(usage, prog="pytest3")
+    
+    parser.add_option("-c", "--cmd", dest="cmd", help="command to ask help for")
+    parser.add_option("-v", "--version", action="store_true", dest="version", help="display Python Version")
+
+    options, args = parser.parse_args(args)
+    
+    if options.version:
+        print sys.version
+        return 0
+    
+    if options.cmd:
+        pyabc.run_command("%s -h"%options.cmd)
+        return 0
+    
+    return 0
+
+pyabc.add_abc_command(pytest3_cmd, "Python-Test", "pytest3", 0)
diff --git a/abc-build/src/python/build.txt b/abc-build/src/python/build.txt
new file mode 100644
--- /dev/null
+++ b/abc-build/src/python/build.txt
@@ -0,0 +1,32 @@
+On Windows:
+
+python setup.py build
+python setup.py bdist_wininst
+
+On Linux (from the main abc directory)
+
+To build the extensions (make sure -fPIC is added to OPTFLAG in the main ABC Makefile first)
+
+make ABC_PYTHON=/usr/bin/python pyabc_extension_install
+
+To build the ABC with embedded python
+
+make pyabc.tgz
+
+
+
+
+Updating the latest version on mima:
+
+alanmi@mima:~/abc_60$ cp ./src/python/build/lib.linux-x86_64-2.6/_pyabc.so /hd/common/pyabc/builds/101030/_pyabc.so
+alanmi@mima:~/abc_60$ cp ./src/python/build/lib.linux-x86_64-2.6/pyabc.py /hd/common/pyabc/builds/101030/pyabc.py
+
+alanmi@mima:/hd/common/pyabc$ rm current
+alanmi@mima:/hd/common/pyabc$ ln -s builds/101030 current
+alanmi@mima:/hd/common/pyabc$ ls -l
+total 4
+lrwxrwxrwx 1 alanmi common   13 2010-10-30 14:55 current -> builds/101030
+
+
+Latest documentation:
+http://goo.gl/jNV2
diff --git a/abc-build/src/python/getch.py b/abc-build/src/python/getch.py
new file mode 100644
--- /dev/null
+++ b/abc-build/src/python/getch.py
@@ -0,0 +1,37 @@
+
+class _Getch:
+    """Gets a single character from standard input.  Does not echo to the screen."""
+    def __init__(self):
+        try:
+            self.impl = _GetchWindows()
+        except ImportError:
+            self.impl = _GetchUnix()
+
+    def __call__(self): return self.impl()
+
+
+class _GetchUnix:
+    def __init__(self):
+        import tty, sys
+
+    def __call__(self):
+        import sys, tty, termios
+        fd = sys.stdin.fileno()
+        old_settings = termios.tcgetattr(fd)
+        try:
+            tty.setraw(sys.stdin.fileno())
+            ch = sys.stdin.read(1)
+        finally:
+            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
+        return ch
+
+
+class _GetchWindows:
+    def __init__(self):
+        import msvcrt
+
+    def __call__(self):
+        import msvcrt
+        return msvcrt.getch()
+
+getch = _Getch()
diff --git a/abc-build/src/python/module.make b/abc-build/src/python/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/python/module.make
@@ -0,0 +1,92 @@
+# To compile with the embedded python interpreter set 
+# the variable ABC_PYTHON to point to the python executable
+# 
+# Examples:
+# make ABC_PYTHON=/usr/bin/python
+# make ABC_PYTHON=/usr/bin/python2.5
+# 
+# To build the Python extension build the target pyabc
+# To create a package of ABC with embedded Python use the target pyabc.tgz
+
+ifdef ABC_PYTHON
+
+	# get the directory containing this file
+	ABC_PYTHON_FILES_PREFIX := $(CURDIR)/src/python
+	
+	ABC_SWIG := swig
+	ABC_PYTHON_CONFIG := $(ABC_PYTHON)-config
+	ABC_PYTHON_CFLAGS := $(shell $(ABC_PYTHON_CONFIG) --includes) -DABC_PYTHON_EMBED=1
+	ABC_PYTHON_LDFLAGS := $(shell $(ABC_PYTHON_CONFIG) --ldflags)
+
+	CFLAGS += $(ABC_PYTHON_CFLAGS)
+	CXXFLAGS += $(ABC_PYTHON_CFLAGS)
+	LIBS += $(ABC_PYTHON_LDFLAGS)
+
+	ABC_PYTHON_SRC := $(ABC_PYTHON_FILES_PREFIX)/pyabc_wrap.c
+	
+	SRC += $(ABC_PYTHON_SRC)
+	
+	GARBAGE += \
+		$(ABC_PYTHON_SRC) \
+		$(ABC_PYTHON_SRC:_wrap.c=.py) \
+		$(ABC_PYTHON_SRC:_wrap.c=.pyc) \
+		$(ABC_PYTHON_FILES_PREFIX)/build \
+		$(ABC_PYTHON_FILES_PREFIX)/dist \
+		pyabc.tgz
+
+	ABC_PYABC_DIR ?= pyabc
+	ABC_PYABC_TGZ ?= pyabc.tgz
+	ABC_PYABC_EXTRA_BIN ?=
+	ABC_PYABC_EXTRA_LIB ?=
+
+
+%_wrap.c %.py : %.i
+	$(ABC_SWIG) -python -outdir $(<D) $<
+
+.PHONY: pyabc_extension_build
+
+pyabc_extension_build : lib$(PROG).a $(ABC_PYTHON_SRC) $(ABC_PYTHON_SRC:_wrap.c=.py)
+	( cd $(ABC_PYTHON_FILES_PREFIX) && rm -rf build/ )	
+	( cd $(ABC_PYTHON_FILES_PREFIX) && $(ABC_PYTHON) setup.py build )
+	
+.PHONY: pyabc_extension_install
+
+pyabc_extension_install : pyabc_extension_build	
+	( cd $(ABC_PYTHON_FILES_PREFIX) && $(ABC_PYTHON) setup.py install --user )
+	
+.PHONY: pyabc_extension_bdist
+
+pyabc_extension_bdist : pyabc_extension_build	
+	( cd $(ABC_PYTHON_FILES_PREFIX) && python setup.py bdist )
+	
+.PHONY: pyabc_tgz
+
+pyabc_tgz : $(ABC_PYABC_TGZ)
+	
+$(ABC_PYABC_TGZ) : $(PROG) $(ABC_PYTHON_SRC:_wrap.c=.py) $(ABC_PYTHON_FILES_PREFIX)/abc.sh $(ABC_PYTHON_FILES_PREFIX)/package.py
+	$(ABC_PYTHON) $(ABC_PYTHON_FILES_PREFIX)/package.py \
+	        --pyabc_dir=$(ABC_PYABC_DIR) \
+		--abc=$(PROG) \
+		--abc_sh=$(ABC_PYTHON_FILES_PREFIX)/abc.sh \
+		--pyabc=$(ABC_PYTHON_FILES_PREFIX) \
+		--extra_bin="$(ABC_PYABC_EXTRA_BIN)" \
+		--extra_lib="$(ABC_PYABC_EXTRA_LIB)" \
+		--out=$@ \
+		$(ABC_PYTHON_OPTIONS)
+
+PYABC_INSTALL_TARGET ?= $(shell date +%Y-%m-%d_%H-%M.%N_${USER})
+PYABC_INSTALL_TARGET := $(PYABC_INSTALL_TARGET)
+
+PYABC_INSTALL_DIR ?= /hd/common/pyabc/builds/pyabc_builds/
+
+pyabc_install_target: pyabc_extension_bdist
+	mkdir -p "$(PYABC_INSTALL_DIR)/$(PYABC_INSTALL_TARGET)"
+	tar \
+	   --directory="$(PYABC_INSTALL_DIR)/$(PYABC_INSTALL_TARGET)" \
+	   --show-transformed-names \
+	   --transform='s#^.*/##g' \
+	   -xvzf "$(ABC_PYTHON_FILES_PREFIX)/dist/pyabc-1.0.linux-x86_64.tar.gz"
+	find "$(PYABC_INSTALL_DIR)/$(PYABC_INSTALL_TARGET)/"* -type d | xargs rmdir
+	echo "Installed at $(PYABC_INSTALL_DIR)/$(PYABC_INSTALL_TARGET)" 	  
+
+endif
diff --git a/abc-build/src/python/package.py b/abc-build/src/python/package.py
new file mode 100644
--- /dev/null
+++ b/abc-build/src/python/package.py
@@ -0,0 +1,176 @@
+import os
+import sys
+import optparse
+import zipfile
+import tarfile
+import tempfile
+import time
+import py_compile
+
+def zip_library(f, extra_files = []):
+    lib = "%s/lib/python%s/"%(sys.prefix,sys.version[:3])
+    
+    zf = zipfile.ZipFile(f, "w", zipfile.ZIP_DEFLATED)
+    
+    for root, _, files in os.walk(lib):
+        arcroot = os.path.relpath(root, lib)
+        for f in files:
+            _, ext = os.path.splitext(f)
+            if ext in ['.py']:
+                zf.write(os.path.join(root,f), os.path.join(arcroot, f))
+
+    for s, r in extra_files:
+        zf.write( s, r )
+
+    zf.close()
+    
+def add_python_lib(tf, lib_dir, lib, mtime):
+
+    _, prefix = os.path.split(lib)
+    
+    for root, _, files in os.walk(lib):
+
+        relpath = os.path.relpath(root, lib)
+
+        if '.hg' in relpath.split('/'):
+            continue
+
+        if relpath=='.':
+            arcroot = lib_dir
+        else:
+            arcroot = os.path.join( lib_dir, os.path.relpath(root, lib) )
+
+        arcroot = os.path.join(arcroot, prefix)
+
+        add_dir(tf, arcroot, mtime)
+        
+        for f in files:
+            _, ext = os.path.splitext(f)
+            if ext in ['.py', '.so']:
+                add_file( tf, os.path.join(root,f), os.path.join(arcroot, f), 0666, mtime)
+
+def add_dir(tf, dir, mtime):
+    ti = tarfile.TarInfo(dir)
+    ti.mode = 0777
+    ti.mtime = mtime
+    ti.type = tarfile.DIRTYPE
+    
+    tf.addfile(ti)
+
+def add_fileobj(tf, f, arcname, mode, mtime):
+    ti = tarfile.TarInfo(arcname)
+    ti.mode = mode
+    ti.mtime = mtime
+    
+    f.seek(0, os.SEEK_END)
+    ti.size = f.tell()
+    
+    f.seek(0, os.SEEK_SET)
+    tf.addfile(ti, f)
+    
+def add_file(tf, fname, arcname, mode, mtime):
+    print "\t adding %s as %s"%(fname, arcname)
+    
+    with open(fname, "rb") as f:
+        add_fileobj(tf, f, arcname, mode, mtime)
+
+def package(pyabc_dir, extra_bin, extra_lib, extra_files, abc_exe, abc_sh, pyabc, ofname, scripts_dir, use_sys):
+    
+    mtime = time.time()
+    
+    tf = tarfile.open(ofname, "w:gz")
+    
+    add_dir(tf, "%s"%pyabc_dir, mtime)
+    
+    add_dir(tf, "%s/bin"%pyabc_dir, mtime)
+    
+    add_file(tf, abc_exe, "%s/bin/abc_exe"%pyabc_dir, 0777, mtime)
+    add_file(tf, abc_sh, "%s/bin/abc"%pyabc_dir, 0777, mtime)
+
+    if scripts_dir:
+        for fn in os.listdir(scripts_dir):
+            if fn.startswith('.'):
+                continue
+            fullname = os.path.join(scripts_dir, fn)
+            if os.path.isfile(fullname):
+                fnroot, fnext = os.path.splitext(fn)
+                if fnext==".sh":
+                    add_file( tf, fullname, os.path.join("%s/bin"%pyabc_dir, fnroot), 0777, mtime)
+                elif fnext not in ( '.pyc', '.pyo'):
+                    add_file( tf, fullname, os.path.join("%s/scripts"%pyabc_dir, fn), 0666, mtime)
+    
+    for bin in extra_bin:
+        add_file( tf, bin, os.path.join("%s/bin"%pyabc_dir, os.path.basename(bin)), 0777, mtime)
+        
+    lib_dir = "%s/lib"%pyabc_dir
+
+    add_dir(tf, lib_dir, mtime)
+
+    for lib in extra_lib:
+        add_python_lib( tf, lib_dir, lib, mtime)
+    
+    for file, dest in extra_files:
+        add_file(tf, file, '%s/%s'%(pyabc_dir, dest), 0666, mtime)
+    
+    for entry in os.listdir(pyabc):
+        if entry.endswith('.py'):
+            add_file( tf, os.path.join(pyabc, entry), os.path.join("%s/lib"%pyabc_dir, entry), 0666, mtime)
+    
+    if not use_sys:
+        # ZIP standard library    
+        zf = tempfile.NamedTemporaryFile("w+b")
+        #zip_library(zf, [(pyabc, "pyabc.py")])
+        zip_library(zf, [])
+        zf.flush()
+        
+        add_fileobj(tf, zf, "%s/lib/python_library.zip"%pyabc_dir, 0666, mtime)
+        
+        zf.close()
+    
+        # add all extensions
+        
+        lib_dynload = os.path.join(sys.exec_prefix,"lib", "python%s"%sys.version[:3], "lib-dynload")
+        
+        for fn in os.listdir(lib_dynload):
+            fullname = os.path.join(lib_dynload, fn)
+            if os.path.isfile(fullname):
+                add_file( tf, fullname, os.path.join("%s/lib"%pyabc_dir, fn), 0666, mtime)
+    
+    tf.close()
+
+
+def main(args):
+    
+    usage = "usage: %prog [options]"
+
+    parser = optparse.OptionParser(usage)
+
+    parser.add_option("-d", "--pyabc_dir", dest="pyabc_dir", help="name of generated directory" )
+    parser.add_option("-b", "--extra_bin", dest="extra_bin", help="extra binaries to pack" )
+    parser.add_option("-l", "--extra_lib", dest="extra_lib", help="extra directories in lib to pack" )
+    parser.add_option("-f", "--extra_files", dest="extra_files", help="additional files (comma separated pairs of file:dest" )
+    parser.add_option("-a", "--abc", dest="abc", help="location of the ABC exeutable")
+    parser.add_option("-s", "--abc_sh", dest="abc_sh", help="location of the ABC setup script")
+    parser.add_option("-p", "--pyabc", dest="pyabc", help="location of pyabc.py")
+    parser.add_option("-o", "--out", dest="out", help="location of output tar gzipped file")
+    parser.add_option("-x", "--scripts", dest="scripts", default="scripts", help="location of scripts")
+    parser.add_option("-S", "--system", action="store_false", dest="sys", default=True, help="use default python installation")
+
+    options, args = parser.parse_args(args)
+
+    if len(args) > 1:
+        parser.print_help()
+        return 1
+        
+    if not options.pyabc_dir or not options.abc or not options.abc_sh or not options.pyabc or not options.out:
+        parser.print_help()
+        return 1
+
+    extra_bin = options.extra_bin.split(',') if options.extra_bin else []
+    extra_lib = options.extra_lib.split(',') if options.extra_lib else []
+    extra_files = [ s.split(':') for s in options.extra_files.split(',')] if options.extra_files else []    
+
+    return package(options.pyabc_dir, extra_bin, extra_lib, extra_files, options.abc, options.abc_sh, options.pyabc, options.out, options.scripts, options.sys)
+
+if __name__=="__main__":
+    main(sys.argv)
diff --git a/abc-build/src/python/pyabc.i b/abc-build/src/python/pyabc.i
new file mode 100644
--- /dev/null
+++ b/abc-build/src/python/pyabc.i
@@ -0,0 +1,1259 @@
+%module pyabc
+
+// -------------------------------------------------------------------
+// SWIG typemap allowing us to grab a Python callable object
+// -------------------------------------------------------------------
+
+#ifdef SWIG<Python>
+
+%typemap(in) PyObject *PyFunc 
+{
+  
+  if ( !PyCallable_Check($source) ) 
+  {
+      PyErr_SetString(PyExc_TypeError, "Need a callable object!");
+      return NULL;
+  }
+  
+  $target = $source;
+}
+
+#endif /* #ifdef SWIG<Python> */
+
+%{
+    
+#include <base/main/main.h>
+#include <misc/util/utilCex.h>
+
+#include <stdlib.h>
+#include <signal.h>
+
+#include <sys/prctl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+    
+int n_ands()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+
+    if ( pNtk && Abc_NtkIsStrash(pNtk) )
+    {        
+        return Abc_NtkNodeNum(pNtk);
+    }
+
+    return -1;
+}
+    
+int n_nodes()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+
+    if ( pNtk )
+    {        
+        return Abc_NtkNodeNum(pNtk);
+    }
+
+    return -1;
+}
+
+int n_pis()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+
+    if ( pNtk )
+    {        
+        return Abc_NtkPiNum(pNtk);
+    }
+
+    return -1;
+}
+
+
+int n_pos()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+
+    if ( pNtk )
+    {        
+        return Abc_NtkPoNum(pNtk);
+    }
+
+    return -1;
+}
+
+int n_latches()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+
+    if ( pNtk )
+    {        
+        return Abc_NtkLatchNum(pNtk);
+    }
+
+    return -1;
+}
+
+int n_levels()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+
+    if ( pNtk )
+    {        
+        return Abc_NtkLevel(pNtk);
+    }
+
+    return -1;
+}
+
+double n_area()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+
+    if ( pNtk && Abc_NtkHasMapping(pNtk) )
+    {        
+        return Abc_NtkGetMappedArea(pNtk);
+    }
+
+    return -1;
+}
+
+int has_comb_model()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+
+    return pNtk && pNtk->pModel;
+}
+
+int has_seq_model()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+
+    return pNtk && pNtk->pSeqModel;
+}
+
+int n_bmc_frames()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    return Abc_FrameReadBmcFrames(pAbc);
+}
+
+int prob_status()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    return Abc_FrameReadProbStatus(pAbc);
+}
+
+int is_valid_cex()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+
+    return pNtk && Abc_FrameReadCex(pAbc) && Abc_NtkIsValidCex( pNtk, Abc_FrameReadCex(pAbc) );
+}
+
+int is_true_cex()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+
+    return pNtk && Abc_FrameReadCex(pAbc) && Abc_NtkIsTrueCex( pNtk, Abc_FrameReadCex(pAbc) );
+}
+
+int n_cex_pis()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+
+    return Abc_FrameReadCex(pAbc) ? Abc_FrameReadCexPiNum( pAbc ) : -1;
+}
+
+int n_cex_regs()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+
+    return Abc_FrameReadCex(pAbc) ? Abc_FrameReadCexRegNum( pAbc ) : -1;
+}
+
+int cex_po()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+
+    return Abc_FrameReadCex(pAbc) ? Abc_FrameReadCexPo( pAbc ) : -1;
+}
+
+int cex_frame()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+
+    return Abc_FrameReadCex(pAbc) ? Abc_FrameReadCexFrame( pAbc ) : -1;
+}
+
+int n_phases()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+
+    return pNtk ? Abc_NtkPhaseFrameNum(pNtk) : 1;
+}
+
+int is_const_po( int iPoNum )
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    return Abc_FrameCheckPoConst( pAbc, iPoNum );
+}
+
+Abc_Cex_t* _cex_get()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Abc_Cex_t* pCex = Abc_FrameReadCex(pAbc);
+    
+    if ( ! pCex )
+    {
+        return NULL;
+    }
+
+    return Abc_CexDup( pCex, -1 ); 
+}
+
+int _cex_get_vec_len()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Vec_Ptr_t* vCexVec = Abc_FrameReadCexVec(pAbc);
+    
+    if( ! vCexVec )
+    {
+        return 0;
+    }
+    
+    return Vec_PtrSize(vCexVec);
+}
+
+Abc_Cex_t* _cex_get_vec(int i)
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Vec_Ptr_t* vCexVec = Abc_FrameReadCexVec(pAbc);
+
+    if( ! vCexVec )
+    {
+        return NULL;
+    }
+
+    Abc_Cex_t* pCex = (Abc_Cex_t*)Vec_PtrEntry( vCexVec, i );
+
+    if ( ! pCex )
+    {
+        return NULL;
+    }
+
+    return Abc_CexDup( pCex, -1 ); 
+}
+
+int _status_get_vec_len()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Vec_Int_t* vStatusVec = Abc_FrameReadStatusVec(pAbc);
+    
+    if( ! vStatusVec )
+    {
+        return 0;
+    }
+    
+    return Vec_IntSize(vStatusVec);
+}
+
+int _status_get_vec(int i)
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Vec_Int_t* vStatusVec = Abc_FrameReadStatusVec(pAbc);
+
+    if( ! vStatusVec )
+    {
+        return -1;
+    }
+
+    return Vec_IntEntry( vStatusVec, i );
+}
+
+void _cex_put(Abc_Cex_t* pCex)
+{
+    if ( pCex )
+    {
+        pCex = Abc_CexDup(pCex, -1);
+    }
+    
+    Abc_FrameSetCex( pCex );
+}
+
+void _cex_free(Abc_Cex_t* pCex)
+{
+    Abc_CexFree(pCex);
+}
+
+int _cex_n_regs(Abc_Cex_t* pCex)
+{
+    return pCex->nRegs;
+}
+
+int _cex_n_pis(Abc_Cex_t* pCex)
+{
+    return pCex->nPis;
+}
+
+int _cex_get_po(Abc_Cex_t* pCex)
+{
+    return pCex->iPo;
+}
+
+int _cex_get_frame(Abc_Cex_t* pCex)
+{
+    return pCex->iFrame;
+}
+
+static PyObject* VecInt_To_PyList(Vec_Int_t* v)
+{
+    PyObject* pylist = PyList_New( Vec_IntSize(v) );
+    
+    int elem, i;
+    
+    Vec_IntForEachEntry( v, elem, i)
+    {
+        PyList_SetItem( pylist, i, PyInt_FromLong(elem) );
+    }
+    
+    return pylist;
+}
+
+PyObject* eq_classes()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Vec_Ptr_t *vPoEquivs = Abc_FrameReadPoEquivs(pAbc);
+    
+    PyObject* eq_classes;
+    Vec_Int_t* pEntry;
+    int i;
+    
+    if( ! vPoEquivs )
+    {
+        Py_RETURN_NONE;
+    }
+    
+    eq_classes = PyList_New( Vec_PtrSize(vPoEquivs) );
+    
+    Vec_PtrForEachEntry( Vec_Int_t*, vPoEquivs, pEntry, i )
+    {
+        PyList_SetItem( eq_classes, i, VecInt_To_PyList(pEntry) );
+    }
+
+    return eq_classes;    
+}
+
+void _pyabc_array_clear()
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Vec_Int_t *vObjIds = Abc_FrameReadObjIds(pAbc);
+    Vec_IntClear( vObjIds );
+}
+
+void _pyabc_array_push(int i)
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Vec_Int_t *vObjIds = Abc_FrameReadObjIds(pAbc);
+    Vec_IntPush( vObjIds, i );
+}
+
+int pyabc_array_read_entry(int i)
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    Vec_Int_t *vObjIds = Abc_FrameReadObjIds(pAbc);
+    if( !vObjIds )
+        return -1;
+    return Vec_IntEntry( vObjIds, i );
+}
+
+static PyObject* pyabc_internal_python_command_callback = 0;
+
+void pyabc_internal_set_command_callback( PyObject* callback )
+{
+    Py_XINCREF(callback);
+    Py_XDECREF(pyabc_internal_python_command_callback);
+
+    pyabc_internal_python_command_callback = callback;
+}
+
+static int pyabc_internal_abc_command_callback(Abc_Frame_t * pAbc, int argc, char ** argv)
+{
+    int i;
+    
+    PyObject* args;
+    PyObject* arglist;
+    PyObject* res;
+    
+    PyGILState_STATE gstate;
+    
+    long lres;
+    
+    if ( !pyabc_internal_python_command_callback )
+            return 0;
+            
+    gstate = PyGILState_Ensure();
+            
+    args = PyList_New(argc);
+    
+    for( i=0 ; i<argc ; i++ )
+            PyList_SetItem(args, i, PyString_FromString(argv[i]) );
+
+    arglist = Py_BuildValue("(O)", args);
+    Py_INCREF(arglist);
+
+    res = PyEval_CallObject( pyabc_internal_python_command_callback, arglist );
+    Py_DECREF(arglist);
+
+    if ( !res )
+    {
+        PyGILState_Release(gstate);
+        return -1;
+    }
+    
+    lres = PyInt_AsLong(res);
+    Py_DECREF(res);
+
+    PyGILState_Release(gstate);
+    
+    return lres;
+}
+
+int run_command(char* cmd)
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+    int rc;
+    
+    Py_BEGIN_ALLOW_THREADS
+    
+    rc = Cmd_CommandExecute(pAbc, cmd);
+    
+    Py_END_ALLOW_THREADS
+    
+    return rc;
+}
+
+void pyabc_internal_register_command( char * sGroup, char * sName, int fChanges )
+{
+    Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
+
+    Cmd_CommandAdd( pAbc, sGroup, sName, (Cmd_CommandFuncType)pyabc_internal_abc_command_callback, fChanges);
+}
+
+static int sigchld_pipe_fd = -1;
+    
+static void sigchld_handler(int signum)
+{
+    while( write(sigchld_pipe_fd, "", 1) == -1 && errno==EINTR )
+        ;
+}
+
+static void install_sigchld_handler(int sigchld_fd)
+{
+    sigchld_pipe_fd = sigchld_fd;
+    signal(SIGCHLD, sigchld_handler);
+}
+
+static int sigint_pipe_fd = -1;
+
+static void sigint_handler(int signum)
+{
+    unsigned char tmp = (unsigned char)signum;
+    while( write(sigint_pipe_fd, &tmp, 1) == -1 && errno==EINTR )
+        ;
+}
+
+static void install_sigint_handler(int sigint_fd)
+{
+    sigint_pipe_fd = sigint_fd;
+    
+    signal(SIGINT, sigint_handler);
+
+    // try to catch other signals that ask the process to terminate    
+    signal(SIGABRT, sigint_handler);
+    signal(SIGQUIT, sigint_handler);
+    signal(SIGTERM, sigint_handler);
+
+    // try to ensure cleanup on exceptional conditions
+    signal(SIGBUS, sigint_handler);
+    signal(SIGILL, sigint_handler);
+    signal(SIGSEGV, sigint_handler);
+    
+    // try to ensure cleanup before being killed due to resource limit
+    signal(SIGXCPU, sigint_handler);
+    signal(SIGXFSZ, sigint_handler);
+}
+
+sigset_t old_procmask;
+static int nblocks = 0;
+
+void block_sigint()
+{
+    sigset_t procmask;
+
+    assert(nblocks==0);
+    nblocks ++ ;
+    
+    sigemptyset(&procmask);
+    sigaddset(&procmask, SIGINT);
+    
+    sigprocmask(SIG_BLOCK, &procmask, &old_procmask);
+}
+
+void unblock_sigint()
+{
+    assert( nblocks==1);
+    nblocks--;
+    
+    sigprocmask(SIG_SETMASK, &old_procmask, NULL);
+}
+
+static PyObject* pyabc_internal_system_callback = 0;
+static PyObject* pyabc_internal_tmpfile_callback = 0;
+static PyObject* pyabc_internal_tmpfile_remove_callback = 0;
+
+int Util_SignalSystem(const char* cmd)
+{
+    PyObject* arglist;
+    PyObject* res;
+    
+    PyGILState_STATE gstate;
+
+    long lres;
+    
+    if ( !pyabc_internal_system_callback )
+            return -1;
+            
+    gstate = PyGILState_Ensure();
+            
+    arglist = Py_BuildValue("(O)", PyString_FromString(cmd));
+    Py_INCREF(arglist);
+
+    res = PyEval_CallObject( pyabc_internal_system_callback, arglist );
+    Py_DECREF(arglist);
+
+    if ( !res )
+    {
+        PyGILState_Release(gstate);
+        return -1;
+    }
+    
+    lres = PyInt_AsLong(res);
+    Py_DECREF(res);
+
+    PyGILState_Release(gstate);
+    
+    return lres;
+}
+
+int Util_SignalTmpFile(const char* prefix, const char* suffix, char** out_name)
+{
+    char* str;
+    Py_ssize_t size;
+    
+    PyObject* arglist;
+    PyObject* res;
+    
+    PyGILState_STATE gstate;
+    
+    *out_name = NULL;
+
+    if ( !pyabc_internal_tmpfile_callback )
+            return 0;
+            
+    gstate = PyGILState_Ensure();
+            
+    arglist = Py_BuildValue("(ss)", prefix, suffix);
+    Py_INCREF(arglist);
+
+    res = PyEval_CallObject( pyabc_internal_tmpfile_callback, arglist );
+    Py_DECREF(arglist);
+
+    if ( !res )
+    {
+        PyGILState_Release(gstate);
+        return -1;
+    }
+    
+    PyString_AsStringAndSize(res, &str, &size);
+    
+    *out_name = ABC_ALLOC(char, size+1);
+    strcpy(*out_name, str);
+    
+    Py_DECREF(res);
+
+    PyGILState_Release(gstate);
+    
+    return open(*out_name, O_WRONLY);
+}
+
+void Util_SignalTmpFileRemove(const char* fname, int fLeave)
+{
+    PyObject* arglist;
+    PyObject* res;
+    
+    PyGILState_STATE gstate;
+
+    if ( !pyabc_internal_tmpfile_remove_callback )
+            return;
+            
+    gstate = PyGILState_Ensure();
+            
+    arglist = Py_BuildValue("(si)", fname, fLeave);
+    Py_INCREF(arglist);
+
+    res = PyEval_CallObject( pyabc_internal_tmpfile_remove_callback, arglist );
+    Py_DECREF(arglist);
+    Py_XDECREF(res);
+
+    PyGILState_Release(gstate);
+}
+
+void pyabc_internal_set_util_callbacks( PyObject* system_callback, PyObject* tmpfile_callback, PyObject* tmpfile_remove_callback )
+{
+    Py_XINCREF(system_callback);
+    Py_XDECREF(pyabc_internal_system_callback);
+
+    pyabc_internal_system_callback = system_callback;
+
+    Py_XINCREF(tmpfile_callback);
+    Py_XDECREF(pyabc_internal_tmpfile_callback);
+
+    pyabc_internal_tmpfile_callback = tmpfile_callback;
+
+    Py_XINCREF(tmpfile_remove_callback);
+    Py_XDECREF(pyabc_internal_tmpfile_remove_callback);
+
+    pyabc_internal_tmpfile_remove_callback = tmpfile_remove_callback;
+}
+
+PyObject* _wait_no_hang()
+{
+    int status;
+    int pid;
+    
+    pid = wait3(&status, WNOHANG, NULL);
+    
+    return Py_BuildValue("(iii)", pid, status, errno);
+}
+
+int _posix_kill(int pid, int signum)
+{
+    return kill(pid, signum);
+}
+
+void _set_death_signal()
+{
+    // send SIGINT if parent process is dead
+    prctl(PR_SET_PDEATHSIG, SIGINT);
+    
+    // if parent process is already dead (and adopted by init)
+    if ( getppid() == 1)
+    {
+        raise(SIGINT);
+    }
+}
+
+%}
+
+%init 
+%{
+    Abc_Start();
+%}
+
+int n_ands();
+int n_nodes();
+int n_pis();
+int n_pos();
+int n_latches();
+int n_levels();
+double n_area();
+
+int run_command(char* cmd);
+
+int has_comb_model();
+int has_seq_model();
+
+int  n_bmc_frames();
+int  prob_status();
+
+int is_valid_cex();
+int is_true_cex();
+int  n_cex_pis();
+int  n_cex_regs();
+int  cex_po();
+int  cex_frame();
+
+int  n_phases();
+int  is_const_po( int iPoNum );
+
+Abc_Cex_t* _cex_get();
+int _cex_get_vec_len();
+Abc_Cex_t* _cex_get_vec(int i);
+int _status_get_vec_len();
+int _status_get_vec(int i);
+void _cex_put(Abc_Cex_t* pCex);
+void _cex_free(Abc_Cex_t* pCex);
+int _cex_n_regs(Abc_Cex_t* pCex);
+int _cex_n_pis(Abc_Cex_t* pCex);
+int _cex_get_po(Abc_Cex_t* pCex);
+int _cex_get_frame(Abc_Cex_t* pCex);
+
+PyObject* eq_classes();
+
+void _pyabc_array_clear();
+void _pyabc_array_push(int i);
+int pyabc_array_read_entry(int i);
+
+void pyabc_internal_set_command_callback( PyObject* callback );
+void pyabc_internal_register_command( char * sGroup, char * sName, int fChanges );
+
+void install_sigchld_handler(int sigint_fd);
+void install_sigint_handler(int sigint_fd);
+
+void block_sigint();
+void unblock_sigint();
+
+void pyabc_internal_set_util_callbacks( PyObject* system_callback, PyObject* tmpfile_callback, PyObject* tmpfile_remove_callback );
+
+PyObject* _wait_no_hang();
+
+void _set_death_signal();
+
+int _posix_kill(int pid, int signum);
+void _set_death_signal();
+
+%pythoncode 
+%{
+
+class _Cex(object):
+
+    def __new__(cls, pCex):
+        if not pCex:
+            return None        
+        return object.__new__(cls)
+
+    def __init__(self, pCex):
+        self.pCex = pCex
+        
+    def __del__(self):
+        _cex_free(self.pCex)
+
+    def n_regs(self):
+        return _cex_n_regs(self.pCex)
+        
+    def n_pis(self):
+        return _cex_n_pis(self.pCex)
+    
+    def get_po(self):
+        return _cex_get_po(self.pCex)
+
+    def get_frame(self):
+        return _cex_get_frame(self.pCex)
+       
+def cex_get_vector():
+    
+    return [ _Cex(_cex_get_vec(i)) for i in xrange(_cex_get_vec_len()) ]
+       
+def status_get_vector():
+    
+    return [ _status_get_vec(i) for i in xrange(_status_get_vec_len()) ]
+       
+def cex_get():
+
+    return _Cex( _cex_get() )
+    
+def cex_put(cex):
+
+    assert cex is not None
+    assert cex.pCex is not None
+    
+    return _cex_put(cex.pCex)
+    
+    
+def create_abc_array(List):
+    _pyabc_array_clear()
+    for ObjId in List:
+        _pyabc_array_push(ObjId)       
+        
+        
+import threading
+import select
+import signal
+import tempfile
+import os
+import errno
+import sys, traceback
+import subprocess
+
+_active_lock = threading.Lock()
+_die_flag = False
+
+_active_pids = set()
+_active_temp_files = set()
+
+_terminated_pids_cond = threading.Condition(_active_lock)
+_terminated_pids = {}
+
+def add_temp_file(fname):
+    with _active_lock:
+        _active_temp_files.add(fname)
+            
+def remove_temp_file(fname):
+    with _active_lock:
+        _active_temp_files.remove(fname)
+            
+_old_os_wait3 = os.wait3
+_select_select = select.select
+
+def _retry_select(fd):
+    while True:
+        try:
+            rrdy,_,_ = _select_select([fd],[],[])
+            if fd in rrdy:
+                return
+        except select.error as e:
+            if e[0] == errno.EINTR:
+                continue
+            raise
+
+def _retry_read(fd):
+
+    while True:
+        try:
+            return fd.read(1)
+        except OSError as e:
+            if e.errno == errno.EINTR:
+                continue
+            raise
+
+def _retry_os_read(fd):
+
+    while True:
+        try:
+            return os.read(fd, 1)
+        except OSError as e:
+            if e.errno == errno.EINTR:
+                continue
+            raise
+
+def _retry_wait():
+
+    while True:
+        
+        pid, status, e = _wait_no_hang()
+        
+        if pid>0:
+            return pid, status
+            
+        elif pid==0:
+            return 0,0
+            
+        elif pid == -1 and e == errno.ECHILD:
+            return 0,0
+            
+        elif pid==-1 and e != errno.EINTR:
+            raise OSError(e, 'unknown error in wait3()')
+
+def _sigint_wait_thread_func(fd):
+
+    global _die_flag
+    
+    while True:
+        
+        _retry_select(fd)
+        _retry_read(fd) 
+
+        with _active_lock:
+        
+            if _die_flag:
+                os._exit(-1)
+            
+            _die_flag = True
+        
+            for pid in _active_pids:
+                rc = _posix_kill(pid, signal.SIGINT)
+    
+            for fname in _active_temp_files:
+                os.remove(fname)
+
+            os._exit(-1)
+
+def _child_wait_thread_func(fd):
+
+    while True:
+    
+        _retry_select(fd)
+        rc = _retry_read(fd)
+                
+        with _active_lock:
+        
+            while True:
+            
+                pid, status = _retry_wait()
+
+                if pid==0:
+                    break
+                    
+                if pid in _active_pids:
+                    _active_pids.remove(pid)
+                    
+                _terminated_pids[pid] = status
+                os.write(_wait_fd_write, "1")
+                _terminated_pids_cond.notifyAll()
+
+_sigint_pipe_read_fd = -1
+_sigint_pipe_write_fd = -1
+
+_sigchld_pipe_read_fd = -1
+_sigchld_pipe_write_fd = -1
+
+wait_fd = -1
+_wait_fd_write = -1
+
+def _start_threads():
+
+    global wait_fd, _wait_fd_write
+    wait_fd, _wait_fd_write = os.pipe()
+
+    global _sigint_pipe_read_fd, _sigint_pipe_write_fd
+    
+    _sigint_pipe_read_fd, _sigint_pipe_write_fd = os.pipe()
+    sigint_read = os.fdopen(_sigint_pipe_read_fd, "r", 0 )
+    
+    sigint_wait_thread = threading.Thread(target=_sigint_wait_thread_func, name="SIGINT wait thread", args=(sigint_read,))
+    sigint_wait_thread.setDaemon(True)
+    sigint_wait_thread.start()
+    
+    install_sigint_handler(_sigint_pipe_write_fd)
+    
+    global _sigchld_pipe_read_fd, _sigchld_pipe_write_fd
+  
+    _sigchld_pipe_read_fd, _sigchld_pipe_write_fd = os.pipe()
+    sigchld_read = os.fdopen(_sigchld_pipe_read_fd, "r", 0 )
+    
+    child_wait_thread = threading.Thread(target=_child_wait_thread_func, name="child process wait thread", args=(sigchld_read,))
+    child_wait_thread.setDaemon(True)
+    child_wait_thread.start()
+    
+    install_sigchld_handler(_sigchld_pipe_write_fd)
+
+_close_on_fork = []
+
+def close_on_fork(fd):
+    _close_on_fork.append(fd)
+
+def after_fork():
+
+    _set_death_signal()
+
+    global _close_on_fork
+
+    for fd in _close_on_fork:
+        os.close(fd)
+        
+    _close_on_fork = []
+
+    os.close(wait_fd)
+    os.close(_wait_fd_write)
+
+    os.close(_sigint_pipe_read_fd)
+    os.close(_sigint_pipe_write_fd)
+    
+    os.close(_sigchld_pipe_read_fd)
+    os.close(_sigchld_pipe_write_fd)
+   
+    global _active_lock
+    _active_lock = threading.Lock()
+
+    global _terminated_pids_cond
+    _terminated_pids_cond = threading.Condition(_active_lock)
+    
+    global _terminated_pids
+    _terminated_pids = {}
+    
+    global _active_pids
+    _active_pids = set()
+    
+    global _active_temp_files
+    _active_temp_files = set()
+    
+    _start_threads()
+
+class _sigint_block_section(object):
+    def __init__(self):
+        self.blocked = False
+        
+    def __enter__(self):
+        block_sigint()
+        self.blocked = True
+        
+    def __exit__(self, type, value, traceback):
+        self.release()
+        
+    def release(self):
+        if self.blocked:
+            self.blocked = False
+            unblock_sigint()
+
+_old_os_fork = os.fork
+
+def _fork():
+
+    ppid = os.getpid()
+
+    with _sigint_block_section() as cs:
+    
+        with _active_lock:
+        
+            if _die_flag:
+                os._exit(-1)
+    
+            pid = _old_os_fork()
+    
+            if pid == 0:
+                after_fork()
+            
+            if pid > 0:
+                _active_pids.add(pid)  
+    
+            return pid
+    
+def _waitpid(pid, options=0):
+    
+    while True:
+    
+        with _active_lock:
+        
+            if pid in _terminated_pids:
+                _retry_os_read(wait_fd)
+                status = _terminated_pids[pid]
+                del _terminated_pids[pid]
+                return pid, status
+            
+            if options==os.WNOHANG:
+                return 0, 0
+                
+            _terminated_pids_cond.wait()
+
+def _wait(options=0):
+
+    while True:
+        
+        with _active_lock:
+        
+            for pid, status in _terminated_pids.iteritems():
+                _retry_os_read(wait_fd)
+                del _terminated_pids[pid]
+                return pid, status
+            
+            if options==os.WNOHANG:
+                return 0, 0
+                
+            _terminated_pids_cond.wait()
+
+_old_os_kill = os.kill
+
+def _kill(pid, sig):
+
+    with _active_lock:
+    
+        if pid in _terminated_pids:
+            return None
+            
+        return _old_os_kill(pid,sig)
+    
+os.kill = _kill
+os.fork = _fork
+os.wait = _wait
+os.waitpid = _waitpid
+
+def _split_command_line(cmd):
+    
+    args = []
+    
+    i=0
+    
+    while i<len(cmd):
+        
+        while i<len(cmd) and cmd[i] in [' ','\t','\f']:
+            i += 1
+            
+        if i >= len(cmd):
+            break
+            
+        arg = []
+        
+        in_quotes = None
+
+        while i<len(cmd):
+            
+            if not in_quotes and cmd[i] in ['\'','\"','\'']:
+                in_quotes = cmd[i]
+                
+            elif in_quotes and cmd[i]==in_quotes:
+                in_quotes = None
+                
+            elif cmd[i] == '\\' and i<(len(cmd)+1):
+                
+                i += 1
+                
+                if cmd[i]=='\\':
+                    arg.append('\\')
+                elif cmd[i]=='\'':
+                    arg.append('\'')
+                elif cmd[i]=='\"':
+                    arg.append('\'')
+                elif cmd[i]=='\"':
+                    arg.append('\"')
+                elif cmd[i]=='a':
+                    arg.append('\a')
+                elif cmd[i]=='b':
+                    arg.append('\b')
+                elif cmd[i]=='n':
+                    arg.append('\n')
+                elif cmd[i]=='f':
+                    arg.append('\f')
+                elif cmd[i]=='r':
+                    arg.append('\r')
+                elif cmd[i]=='t':
+                    arg.append('\t')
+                elif cmd[i]=='v':
+                    arg.append('\v')
+                else:
+                    arg.append(cmd[i])
+                    
+            elif not in_quotes and cmd[i] in [' ','\t','\f']:
+                break
+                
+            else:
+                arg.append(cmd[i])
+                
+            i += 1
+        
+        args.append( "".join(arg) )
+    
+    return args
+
+
+def system(cmd):
+
+    args = _split_command_line(cmd)
+    
+    if args[-2] == '>':
+    
+        with open(args[-1],'w') as fout:
+            p = subprocess.Popen(args[:-2], stdout=fout)
+            rc = p.wait()
+            return rc
+         
+    else:
+        p = subprocess.Popen(args)
+        return p.wait()
+
+def tmpfile(prefix, suffix):
+
+    with _active_lock:
+        with tempfile.NamedTemporaryFile(delete=False, prefix=prefix, suffix=suffix) as file:
+            _active_temp_files.add(file.name)
+            return file.name
+       
+def tmpfile_remove(fname, leave):
+
+    with _active_lock:
+        os.remove(fname)
+        _active_temp_files.remove(fname) 
+
+pyabc_internal_set_util_callbacks( system, tmpfile,tmpfile_remove )
+
+
+_start_threads()
+
+
+_registered_commands = {}
+
+def _cmd_callback(args):
+    try:
+        assert len(args) > 0
+        
+        cmd = args[0]
+        assert cmd in _registered_commands
+    
+        res = _registered_commands[cmd](args)
+        
+        assert type(res) == int, "User-defined Python command must return an integer."
+        
+        return res
+    
+    except Exception, e:
+        import traceback
+        traceback.print_exc()
+
+    except SystemExit, se:
+        pass
+            
+    return 0
+    
+pyabc_internal_set_command_callback( _cmd_callback )
+    
+def add_abc_command(fcmd, group, cmd, change):
+    _registered_commands[ cmd ] = fcmd
+    pyabc_internal_register_command( group, cmd, change)
+
+import optparse
+
+xxx = {} 
+
+def cmd_python(cmd_args):
+    
+    usage = "usage: %prog [options] <Python files>"
+    
+    parser = optparse.OptionParser(usage, prog="python")
+    
+    parser.add_option("-c", "--cmd", dest="cmd", help="Execute Python command directly")
+    parser.add_option("-v", "--version", action="store_true", dest="version", help="Display Python Version")
+
+    options, args = parser.parse_args(cmd_args)
+    
+    if options.version:
+        print sys.version
+        return 0
+    
+    if options.cmd:
+        exec options.cmd in xxx
+        return 0
+    
+    scripts_dir = os.getenv('ABC_PYTHON_SCRIPTS', ".")
+    scripts_dirs = scripts_dir.split(':')
+    
+    for fname in args[1:]:
+        if os.path.isabs(fname):
+            execfile(fname, xxx)
+        else:
+            for d in scripts_dirs:
+                fname = os.path.join(scripts_dir, fname)
+                if os.path.exists(fname):
+                    execfile(fname, xxx)
+                    break
+    
+    return 0
+    
+add_abc_command(cmd_python, "Python", "python", 0) 
+
+
+%}
diff --git a/abc-build/src/python/pyabc_split.py b/abc-build/src/python/pyabc_split.py
new file mode 100644
--- /dev/null
+++ b/abc-build/src/python/pyabc_split.py
@@ -0,0 +1,412 @@
+"""
+module pyabc_split
+
+Executes python functions and their arguements as separate processes and returns their return values through pickling. This modules offers a single function:
+
+Function: split_all(funcs)
+
+The function returns a generator objects that allowes iteration over the results,
+
+Arguments:
+
+funcs: a list of tuples (f, args) where f is a python function and args is a collection of arguments for f.
+
+Caveats:
+
+1. Global variables in the parent process are not affected by the child processes.
+2. The functions can only return simple types, see the pickle module for details
+
+Usage:
+
+Assume you would like to run the function f_1(1), f_2(1,2), f_3(1,2,3) in different processes. 
+
+def f_1(i):
+    return i+1
+    
+def f_2(i,j):
+    return i*10+j+1
+    
+def f_3(i,j,k):
+    return i*100+j*10+k+1
+
+Construct a tuple of the function and arguments for each function
+
+t_1 = (f_1, [1])
+t_2 = (f_2, [1,2])
+t_3 = (f_3, [1,2,3])
+
+Create a list containing these tuples:
+
+funcs = [t_1, t_2, t_3]
+
+Use the function split_all() to run these functions in separate processes:
+
+for res in split_all(funcs):
+    print res
+    
+The output will be:
+
+2
+13
+124
+
+(The order may be different, except that in this case the processes are so fast that they terminate before the next one is created)
+
+Alternatively, you may quite in the middle, say after the first process returns:
+
+for res in split_all(funcs):
+    print res
+    break
+    
+This will kill all processes not yet finished.
+
+To run ABC operations, that required saving the child process state and restoring it at the parent, use abc_split_all().
+
+    import pyabc
+    
+    def abc_f(truth):
+        import os
+        print "pid=%d, abc_f(%s)"%(os.getpid(), truth)
+        pyabc.run_command('read_truth %s'%truth)
+        pyabc.run_command('strash')
+        
+    funcs = [
+        defer(abc_f)("1000"),
+        defer(abc_f)("0001")
+    ]
+    
+    for _ in abc_split_all(funcs):
+        pyabc.run_command('write_verilog /dev/stdout')
+
+Author: Baruch Sterin <sterin@berkeley.edu>
+"""
+
+import os
+import select
+import fcntl
+import errno
+import sys
+import cPickle as pickle
+import signal
+import cStringIO
+
+import traceback
+
+from contextlib import contextmanager
+
+import pyabc
+
+def _retry_select(rlist):
+    while True:
+        try:
+            rrdy,_,_ = select.select(rlist,[],[])
+            if rrdy:
+                return rrdy
+        except select.error as e:
+            if e[0] == errno.EINTR:
+                continue
+            raise
+
+class _splitter(object):
+    
+    def __init__(self):
+        self.pids = []
+        self.fds = {}
+        self.buffers = {}
+        self.results = {}
+    
+    def is_done(self):
+        return len(self.fds) == 0
+    
+    def _kill(self, pids):
+
+        # close pipes and kill child processes
+        for pid in pids:
+
+            if pid == -1:
+                continue
+
+            i, fd = self.fds[pid]
+            
+            del self.buffers[fd]
+            del self.fds[pid]
+
+            self.pids[i] = -1
+            self.results[pid] = None
+            
+            os.close(fd)
+            
+            try:
+                os.kill( pid, signal.SIGINT)
+            except Exception as e:
+                print >>sys.stderr, 'exception while trying to kill pid=%d: '%pid, e
+                raise
+
+        # wait for termination and update result
+        for pid in pids:
+            os.waitpid( pid, 0 )
+
+    def kill(self, ids):
+        
+        self._kill( [ self.pids[i] for i in ids ] )
+            
+    def cleanup(self):
+        self._kill( self.fds.keys() )
+
+    def child( self, fdw, f):
+
+        # call function
+        try:
+            res = f()
+        except:
+            traceback.print_exc()
+            raise
+        
+        # write return value into pipe
+        with os.fdopen( fdw, "w" ) as fout:
+            pickle.dump(res, fout)
+            
+        return 0
+
+    def _fork_one(self, f):
+        
+        # create a pipe to communicate with the child process
+        pr,pw = os.pipe()
+        
+        # set pr to be non-blocking
+        fcntl.fcntl(pr, fcntl.F_SETFL, os.O_NONBLOCK)
+        
+        parentpid = os.getpid()
+        rc = 1
+        
+        try:
+
+            # create child process
+            pid = os.fork()
+    
+            if pid == 0:
+                # child process:
+                os.close(pr)
+                pyabc.close_on_fork(pw)
+                
+                rc = self.child( pw, f)
+                os._exit(rc)
+            else:
+                # parent process:
+                os.close(pw)
+                return (pid, pr)
+                
+        finally:
+            if os.getpid() != parentpid:
+                os._exit(rc)
+
+    def fork_one(self, func):
+        pid, fd = self._fork_one(func)
+        i = len(self.pids)
+        self.pids.append(pid)
+        self.fds[pid] = (i, fd)
+        self.buffers[fd] = cStringIO.StringIO()
+        return i
+    
+    def fork_all(self, funcs):
+        return [ self.fork_one(f) for f in funcs ]
+
+    def communicate(self):
+        
+        rlist = [ fd for _, (_,fd) in self.fds.iteritems() ]
+        rlist.append(pyabc.wait_fd)
+
+        stop = False
+        
+        while not stop:
+
+            rrdy = _retry_select( rlist )
+            
+            for fd in rrdy:
+                
+                if fd == pyabc.wait_fd:
+                    stop = True
+                    continue
+                    
+                self.buffers[fd].write( os.read(fd, 16384) )
+    
+    def get_next_result(self):
+
+        # read from the pipes as needed, while waiting for the next child process to terminate
+        self.communicate()
+    
+        # wait for the next child process to terminate
+        pid, rc = os.wait()
+        assert pid in self.fds
+        
+        # retrieve the pipe file descriptor
+        i, fd = self.fds[pid]
+        del self.fds[pid]
+
+        # remove the pid
+        self.pids[i] = -1
+
+        # retrieve the buffer
+        buffer = self.buffers[fd]
+        del self.buffers[fd]
+
+        # fill the buffer
+        while True:
+            s = os.read(fd, 16384)
+            if not s:
+                break
+            buffer.write(s)
+            
+        os.close(fd)
+
+        try:
+            return (i, pickle.loads(buffer.getvalue()))
+        except EOFError, pickle.UnpicklingError:
+            return (i, None)
+            
+    def __iter__(self):
+        def iterator():
+            while not self.is_done():
+                yield self.get_next_result()
+        return iterator()
+
+@contextmanager
+def make_splitter():
+    # ensure cleanup of child processes
+    s = _splitter()
+    try:
+        yield s
+    finally:
+        s.cleanup()
+        
+def split_all_full(funcs):
+    # provide an iterator for child process result
+    with make_splitter() as s:
+        
+        s.fork_all(funcs)
+        
+        for res in s:
+            yield res
+
+def defer(f):
+    return lambda *args, **kwargs: lambda : f(*args,**kwargs)
+
+def split_all(funcs):
+    for _, res in split_all_full( ( defer(f)(*args) for f,args in funcs ) ):
+        yield res
+
+import tempfile
+
+@contextmanager
+def temp_file_names(suffixes):
+    names = []
+    try:
+        for suffix in suffixes:
+            with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as file:
+                names.append( file.name )
+        yield names
+    finally:
+        for name in names:
+            os.unlink(name)
+
+class abc_state(object):
+    def __init__(self):
+        with tempfile.NamedTemporaryFile(delete=False, suffix='.aig') as file:
+            self.aig = file.name
+        with tempfile.NamedTemporaryFile(delete=False, suffix='.log') as file:
+            self.log = file.name
+        pyabc.run_command(r'write_status %s'%self.log)
+        pyabc.run_command(r'write_aiger %s'%self.aig)
+    
+    def __del__(self):
+        os.unlink( self.aig )
+        os.unlink( self.log )
+
+    def restore(self):
+        pyabc.run_command(r'read_aiger %s'%self.aig)
+        pyabc.run_command(r'read_status %s'%self.log)
+
+def abc_split_all(funcs):
+    import pyabc
+    
+    def child(f, aig, log):
+        res = f()
+        pyabc.run_command(r'write_status %s'%log)
+        pyabc.run_command(r'write_aiger %s'%aig)
+        return res
+        
+    def parent(res, aig, log):
+        pyabc.run_command(r'read_aiger %s'%aig)
+        pyabc.run_command(r'read_status %s'%log)
+        return res
+        
+    with temp_file_names( ['.aig','.log']*len(funcs) ) as tmp:
+
+        funcs = [ defer(child)(f, tmp[2*i],tmp[2*i+1]) for i,f in enumerate(funcs) ]
+        
+        for i, res in split_all_full(funcs):
+            yield i, parent(res, tmp[2*i],tmp[2*i+1])
+
+if __name__ == "__main__":
+    
+    # define some functions to run
+    
+    def f_1(i):
+        return i+1
+        
+    def f_2(i,j):
+        return i*10+j+1
+        
+    def f_3(i,j,k):
+        return i*100+j*10+k+1
+    
+    # Construct a tuple of the function and arguments for each function
+    
+    t_1 = (f_1, [1])
+    t_2 = (f_2, [1,2])
+    t_3 = (f_3, [1,2,3])
+
+    # Create a list containing these tuples:
+
+    funcs = [t_1, t_2, t_3]
+
+    # Use the function split_all() to run these functions in separate processes:
+
+    for res in split_all(funcs):
+        print res
+
+    # Alternatively, quit after the first process returns:
+    
+    for res in split_all(funcs):
+        print res
+        break
+        
+    # For operations with ABC that save and restore status
+    
+    import pyabc
+    
+    def abc_f(truth):
+        import os
+        print "pid=%d, abc_f(%s)"%(os.getpid(), truth)
+        pyabc.run_command('read_truth %s'%truth)
+        pyabc.run_command('strash')
+        return 100
+        
+    funcs = [
+        defer(abc_f)("1000"),
+        defer(abc_f)("0001")
+    ]
+    
+    best = None
+    
+    for i, res in abc_split_all(funcs):
+        print i, res
+        if best is None:\
+            # save state
+            best = abc_state()
+        pyabc.run_command('write_verilog /dev/stdout')
+    
+    # if there is a saved state, restore it
+    if best is not None:
+        best.restore()
+        pyabc.run_command('write_verilog /dev/stdout')
diff --git a/abc-build/src/python/reachx_cmd.py b/abc-build/src/python/reachx_cmd.py
new file mode 100644
--- /dev/null
+++ b/abc-build/src/python/reachx_cmd.py
@@ -0,0 +1,108 @@
+# You can use 'from pyabc import *' and then not need the pyabc. prefix everywhere
+
+import sys
+import optparse
+import subprocess
+import tempfile
+import threading
+import os
+import os.path
+from contextlib import contextmanager, nested
+
+import pyabc
+
+
+def popen_and_wait_with_timeout(timeout,cmd, *args, **kwargs):
+    """ Wait for a subprocess.Popen object to terminate, or until timeout (in seconds) expires. """
+
+    p = None
+    t = None
+
+    try:
+        p = subprocess.Popen(cmd, *args, **kwargs)
+
+        if timeout <= 0:
+            timeout = None
+        
+        t = threading.Thread(target=lambda: p.communicate())
+        t.start()
+        
+        t.join(timeout)
+        
+    finally:
+        
+        if p is not None and p.poll() is None:
+            p.kill()
+
+        if t is not None and t.is_alive():
+            t.join()
+        
+        if p is not None:
+            return p.returncode
+            
+        return -1
+
+@contextmanager
+def temp_file_name(suffix=""):
+    file = tempfile.NamedTemporaryFile(delete=False, suffix=suffix)
+    name = file.name
+    file.close()
+
+    try:
+        yield name
+    finally:
+        os.unlink(name)
+
+def cygpath(path):
+    if sys.platform == "win32":
+        if os.path.isabs(path):
+            drive, tail = os.path.splitdrive(path)
+            drive = drive.lower()
+            tail = tail.split(os.path.sep)
+            return '/cygdrive/%s'%drive[0] + '/'.join(tail) 
+        else:
+            path = path.split(os.path.sep)
+            return "/".join(path)
+    return path
+
+def run_reachx_cmd(effort, timeout):
+    with nested(temp_file_name(suffix=".aig"), temp_file_name()) as (tmpaig_name, tmplog_name):
+        pyabc.run_command("write %s"%tmpaig_name)
+        
+        cmdline = [ 
+            'read %s'%cygpath(tmpaig_name),
+            'qua_ffix -effort %d -L %s'%(effort, cygpath(tmplog_name)),
+            'quit'
+            ]
+
+        cmd = ["jabc", "-c", " ; ".join(cmdline)]
+        
+        rc = popen_and_wait_with_timeout(timeout, cmd, shell=False, stdout=sys.stdout, stderr=sys.stderr)
+
+        if rc != 0:
+            # jabc failed or stopped. Write a status file to update the status to unknown
+            with open(tmplog_name, "w") as f:
+                f.write('snl_UNK -1 unknown\n')
+                f.write('NULL\n')
+                f.write('NULL\n')
+            
+        pyabc.run_command("read_status %s"%tmplog_name)
+        
+        return rc
+
+def reachx_cmd(argv):
+    usage = "usage: %prog [options]"
+    
+    parser = optparse.OptionParser(usage, prog="reachx")
+    
+    parser.add_option("-e", "--effort", dest="effort", type=int, default=0, help="effort level. [default=0, means unlimited]")
+    parser.add_option("-t", "--timeout", dest="timeout", type=int, default=0, help="timeout in seconds [default=0, unlimited]")
+
+    options, args = parser.parse_args(argv)
+
+    rc = run_reachx_cmd(options.effort, options.timeout)
+    print "%s command: jabc returned: %d"%(argv[0], rc)
+    
+    return 0
+
+pyabc.add_abc_command(reachx_cmd, "Verification", "reachx", 0)
diff --git a/abc-build/src/python/redirect.py b/abc-build/src/python/redirect.py
new file mode 100644
--- /dev/null
+++ b/abc-build/src/python/redirect.py
@@ -0,0 +1,111 @@
+"""
+
+A simple context manager for redirecting streams in Python. 
+The streams are redirected at the the C runtime level so that the output of C extensions
+that use stdio will also be redirected.
+
+null_file : a stream representing the null device (e.g. /dev/null on Unix)
+redirect: a context manager for redirecting streams
+
+Author: Baruch Sterin (sterin@berkeley.edu)
+
+"""
+
+import os
+import sys
+
+from contextlib import contextmanager
+
+null_file = open( os.devnull, "w" )
+
+@contextmanager
+def _dup( f ):
+    fd = os.dup( f.fileno() )
+    yield fd
+    os.close(fd)
+    
+@contextmanager
+def save_stdout( src = sys.stdout ):
+    """
+    Redirect 
+    """
+    fd = os.dup( src.fileno() )
+    own = True
+    
+    try:
+        with os.fdopen( fd, "w", 0) as f:
+            own = False
+            yield f
+    except:
+        if own:
+            os.close(fd)
+        raise
+    
+@contextmanager
+def redirect(dst = null_file, src = sys.stdout):
+    
+    """
+    Redirect the src stream into dst.
+    
+    Example:
+        with redirect( open("somefile.txt", sys.stdout ) ):
+            do some stuff ...        
+    """
+
+    if src.fileno() == dst.fileno():
+        yield 
+        return
+        
+    with _dup( src ) as fd_dup_src:
+
+        dst.flush()
+        
+        src.flush()
+        os.close( src.fileno() )
+        os.dup2( dst.fileno(), src.fileno() )
+
+        yield
+
+        src.flush()
+        os.close( src.fileno() )
+        os.dup2( fd_dup_src, src.fileno() ) 
+
+def start_redirect(dst = null_file, src = sys.stdout):
+    
+    """
+    Start redirection of src stream into dst. Return the duplicated file handle of the source.
+    
+    Example:
+        fd = start_redirect( open("somefile.txt"), sys.stdout )
+            ... do some stuff ...        
+        end_redirect(sys.stdout, fd)
+    """
+
+    if src.fileno() == dst.fileno():
+        return None
+        
+    fd_dup_src = os.dup( src.fileno() )
+    
+    dst.flush()
+    src.flush()
+
+    os.close( src.fileno() )
+    os.dup2( dst.fileno(), src.fileno() )
+    
+    return fd_dup_src
+
+def end_redirect(src, fd_dup_src):
+    
+    """
+    End redirection of stream src.Redirect the src stream into dst. src is the source stream and fd_dup_src is the value returned by
+    start_redirect()
+    """
+
+    if fd_dup_src is None:
+        return
+
+    src.flush()
+    os.close( src.fileno() )
+    os.dup2( fd_dup_src, src.fileno() ) 
+    
+    os.close(fd_dup_src)
diff --git a/abc-build/src/python/setup.py b/abc-build/src/python/setup.py
new file mode 100644
--- /dev/null
+++ b/abc-build/src/python/setup.py
@@ -0,0 +1,67 @@
+import sys
+
+from distutils.core import setup, Extension
+from distutils.sysconfig import get_config_vars
+from distutils import util
+from distutils.command.build_ext import build_ext
+from distutils import sysconfig
+
+define_macros = []
+libraries = []
+library_dirs = []
+
+if sys.platform == "win32":
+    
+    src_file = [ 'pyabc.i' ]
+    
+    define_macros.append( ('WIN32', 1) )
+    define_macros.append( ('ABC_DLL', 'ABC_DLLEXPORT') )
+    
+    libraries.append('abcr')
+    library_dirs.append('./../../lib')
+
+else:
+
+    src_file = [ 'pyabc_wrap.c' ]
+    
+    if get_config_vars()['SIZEOF_VOID_P'] > 4:
+        define_macros.append( ('LIN64', 1) )
+    else:
+        define_macros.append( ('LIN', 1) )
+
+    libraries.append( 'abc' )
+    libraries.append( 'rt' )
+    libraries.append( 'readline' )
+    library_dirs.append('./../../')
+
+
+# ugly hack to silence strict-prototype warnings
+
+class build_ext_subclass( build_ext ):
+    
+    def build_extensions(self):
+        
+        CC = sysconfig.get_config_var("CC")
+        
+        if self.compiler.compiler_type == 'unix' and ( 'gcc' in CC or 'g++' in CC):
+            for e in self.extensions:
+                e.extra_compile_args.append( '-Wno-strict-prototypes' )
+                
+        build_ext.build_extensions(self)
+
+ext = Extension(
+    '_pyabc',
+    src_file,
+    define_macros=define_macros,
+    include_dirs = ["../../src"],
+    library_dirs=library_dirs,
+    libraries=libraries
+    )
+
+setup(
+    name='pyabc',
+    version='1.0',
+    ext_modules=[ext],
+    py_modules=['pyabc','getch','pyabc_split','redirect', 'reachx_cmd'],
+    cmdclass = {'build_ext': build_ext_subclass }
+)
diff --git a/abc-build/src/sat/bmc/bmc.c b/abc-build/src/sat/bmc/bmc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmc.c
@@ -0,0 +1,52 @@
+/**CFile****************************************************************
+
+  FileName    [bmc.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bmc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmc.h b/abc-build/src/sat/bmc/bmc.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmc.h
@@ -0,0 +1,186 @@
+/**CFile****************************************************************
+
+  FileName    [bmc.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmc.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC___sat_bmc_BMC_h
+#define ABC___sat_bmc_BMC_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "aig/saig/saig.h"
+#include "aig/gia/gia.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+// unrolling manager 
+typedef struct Unr_Man_t_ Unr_Man_t;
+
+typedef struct Saig_ParBmc_t_ Saig_ParBmc_t;
+struct Saig_ParBmc_t_
+{
+    int         nStart;         // starting timeframe
+    int         nFramesMax;     // maximum number of timeframes 
+    int         nConfLimit;     // maximum number of conflicts at a node
+    int         nConfLimitJump; // maximum number of conflicts after jumping
+    int         nFramesJump;    // the number of tiemframes to jump
+    int         nTimeOut;       // approximate timeout in seconds
+    int         nTimeOutGap;    // approximate timeout in seconds since the last change
+    int         nTimeOutOne;    // timeout per output in multi-output solving
+    int         nPisAbstract;   // the number of PIs to abstract
+    int         fSolveAll;      // does not stop at the first SAT output
+    int         fStoreCex;      // enable storing CEXes in the MO mode
+    int         fUseBridge;     // use bridge interface
+    int         fDropSatOuts;   // replace sat outputs by constant 0
+    int         nFfToAddMax;    // max number of flops to add during CBA
+    int         fSkipRand;      // skip random decisions
+    int         nLearnedStart;  // starting learned clause limit
+    int         nLearnedDelta;  // delta of learned clause limit
+    int         nLearnedPerce;  // ratio of learned clause limit
+    int         fVerbose;       // verbose 
+    int         fNotVerbose;    // skip line-by-line print-out 
+    char *      pLogFileName;   // log file name
+    int         fSilent;        // completely silent
+    int         iFrame;         // explored up to this frame
+    int         nFailOuts;      // the number of failed outputs
+    int         nDropOuts;      // the number of dropped outputs
+    abctime     timeLastSolved; // the time when the last output was solved
+    int(*pFuncOnFail)(int,Abc_Cex_t*); // called for a failed output in MO mode
+};
+
+ 
+typedef struct Bmc_AndPar_t_ Bmc_AndPar_t;
+struct Bmc_AndPar_t_
+{
+    int         nStart;         // starting timeframe
+    int         nFramesMax;     // maximum number of timeframes 
+    int         nFramesAdd;     // the number of additional frames
+    int         nConfLimit;     // maximum number of conflicts at a node
+    int         nTimeOut;       // timeout in seconds
+    int         fLoadCnf;       // dynamic CNF loading
+    int         fDumpFrames;    // dump unrolled timeframes
+    int         fUseSynth;      // use synthesis
+    int         fUseOldCnf;     // use old CNF construction
+    int         fVerbose;       // verbose 
+    int         fVeryVerbose;   // very verbose 
+    int         fNotVerbose;    // skip line-by-line print-out 
+    int         iFrame;         // explored up to this frame
+    int         nFailOuts;      // the number of failed outputs
+    int         nDropOuts;      // the number of dropped outputs
+};
+  
+typedef struct Bmc_BCorePar_t_ Bmc_BCorePar_t;
+struct Bmc_BCorePar_t_
+{
+    int         iFrame;         // timeframe
+    int         iOutput;        // property output
+    int         nTimeOut;       // timeout in seconds
+    char *      pFilePivots;    // file name with AIG IDs of pivot objects
+    char *      pFileProof;     // file name to write the resulting proof
+    int         fVerbose;       // verbose output
+};
+
+typedef struct Bmc_MulPar_t_ Bmc_MulPar_t;
+struct Bmc_MulPar_t_
+{
+    int         TimeOutGlo;
+    int         TimeOutLoc;
+    int         TimeOutInc;
+    int         TimeOutGap;
+    int         TimePerOut;
+    int         fUseSyn;
+    int         fDumpFinal;
+    int         fVerbose;
+    int         fVeryVerbose;
+};
+
+typedef struct Bmc_ParFf_t_ Bmc_ParFf_t;
+struct Bmc_ParFf_t_
+{
+    char *     pFileName;
+    char *     pFormStr;
+    int        Algo;
+    int        fComplVars;
+    int        fStartPats;
+    int        nTimeOut;
+    int        fBasic;
+    int        fDump;
+    int        fDumpUntest;
+    int        fVerbose;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== bmcBCore.c ==========================================================*/
+extern void              Bmc_ManBCorePerform( Gia_Man_t * pGia, Bmc_BCorePar_t * pPars );
+/*=== bmcBmc.c ==========================================================*/
+extern int               Saig_ManBmcSimple( Aig_Man_t * pAig, int nFrames, int nSizeMax, int nBTLimit, int fRewrite, int fVerbose, int * piFrame, int nCofFanLit );
+/*=== bmcBmc2.c ==========================================================*/
+extern int               Saig_BmcPerform( Aig_Man_t * pAig, int nStart, int nFramesMax, int nNodesMax, int nTimeOut, int nConfMaxOne, int nConfMaxAll, int fVerbose, int fVerbOverwrite, int * piFrames, int fSilent );
+/*=== bmcBmc3.c ==========================================================*/
+extern void              Saig_ParBmcSetDefaultParams( Saig_ParBmc_t * p );
+extern int               Saig_ManBmcScalable( Aig_Man_t * pAig, Saig_ParBmc_t * pPars );
+/*=== bmcBmcAnd.c ==========================================================*/
+extern int               Gia_ManBmcPerform( Gia_Man_t * p, Bmc_AndPar_t * pPars );
+/*=== bmcCexCare.c ==========================================================*/
+extern Abc_Cex_t *       Bmc_CexCareMinimize( Aig_Man_t * p, Abc_Cex_t * pCex, int fCheck, int fVerbose );
+extern void              Bmc_CexCareVerify( Aig_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexMin, int fVerbose );
+/*=== bmcCexCut.c ==========================================================*/
+extern Gia_Man_t *       Bmc_GiaTargetStates( Gia_Man_t * p, Abc_Cex_t * pCex, int iFrBeg, int iFrEnd, int fCombOnly, int fGenAll, int fAllFrames, int fVerbose );
+extern Aig_Man_t *       Bmc_AigTargetStates( Aig_Man_t * p, Abc_Cex_t * pCex, int iFrBeg, int iFrEnd, int fCombOnly, int fGenAll, int fAllFrames, int fVerbose );
+/*=== bmcCexMin.c ==========================================================*/
+extern Abc_Cex_t *       Saig_ManCexMinPerform( Aig_Man_t * pAig, Abc_Cex_t * pCex );
+/*=== bmcCexTool.c ==========================================================*/
+extern void              Bmc_CexPrint( Abc_Cex_t * pCex, int nInputs, int fVerbose );
+extern int               Bmc_CexVerify( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare );
+/*=== bmcICheck.c ==========================================================*/
+extern void              Bmc_PerformICheck( Gia_Man_t * p, int nFramesMax, int nTimeOut, int fEmpty, int fVerbose );
+extern Vec_Int_t *       Bmc_PerformISearch( Gia_Man_t * p, int nFramesMax, int nTimeOut, int fReverse, int fDump, int fVerbose );
+/*=== bmcUnroll.c ==========================================================*/
+extern Unr_Man_t *       Unr_ManUnrollStart( Gia_Man_t * pGia, int fVerbose );
+extern Gia_Man_t *       Unr_ManUnrollFrame( Unr_Man_t * p, int f );
+extern void              Unr_ManFree( Unr_Man_t * p );
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/sat/bmc/bmcBCore.c b/abc-build/src/sat/bmc/bmcBCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcBCore.c
@@ -0,0 +1,273 @@
+/**CFile****************************************************************
+
+  FileName    [bmcBCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    [Performs recording of BMC core.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcBCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bmc.h"
+#include "sat/bsat/satSolver.h"
+#include "sat/bsat/satStore.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Collect pivot variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Bmc_ManBCoreReadPivots( char * pName )
+{
+    int Num;
+    Vec_Int_t * vPivots = Vec_IntAlloc( 100 );
+    FILE * pFile = fopen( pName, "r" );
+    while ( fscanf( pFile, "%d", &Num ) == 1 )
+        Vec_IntPush( vPivots, Num );
+    fclose( pFile );
+    return vPivots;
+}
+Vec_Int_t * Bmc_ManBCoreCollectPivots( Gia_Man_t * p, char * pName, Vec_Int_t * vVarMap )
+{
+    Gia_Obj_t * pObj;
+    int i, iVar, iFrame;
+    Vec_Int_t * vPivots = Vec_IntAlloc( 100 );
+    Vec_Int_t * vVars = Bmc_ManBCoreReadPivots( pName );
+    Gia_ManForEachObj( p, pObj, i )
+        pObj->fMark0 = 0;
+    Vec_IntForEachEntry( vVars, iVar, i )
+        if ( iVar > 0 && iVar < Gia_ManObjNum(p) )
+            Gia_ManObj( p, iVar )->fMark0 = 1;
+        else
+            printf( "Cannot find object with Id %d in the given AIG.\n", iVar );
+    Vec_IntForEachEntryDouble( vVarMap, iVar, iFrame, i )
+        if ( Gia_ManObj( p, iVar )->fMark0 )
+            Vec_IntPush( vPivots, Abc_Lit2Var(i) );
+    Gia_ManForEachObj( p, pObj, i )
+        pObj->fMark0 = 0;
+    Vec_IntFree( vVars );
+    return vPivots;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect (Id; Frame) pairs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Bmc_ManBCoreAssignVar( Gia_Man_t * p, Gia_Obj_t * pObj, int f, Vec_Int_t * vNodes )
+{
+    pObj->Value = Abc_Lit2Var(Vec_IntSize(vNodes));
+    Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+    Vec_IntPush( vNodes, f );
+//    printf( "Obj %3d  Frame %3d  --->  Var %3d    ", Gia_ObjId(p, pObj), f, pObj->Value );
+//    Gia_ObjPrint( p, pObj );
+}
+void Bmc_ManBCoreCollect_rec( Gia_Man_t * p, int Id, int f, Vec_Int_t * vNodes, Vec_Int_t * vRootsNew )
+{
+    Gia_Obj_t * pObj;
+    if ( Gia_ObjIsTravIdCurrentId(p, Id) )
+        return;
+    Gia_ObjSetTravIdCurrentId(p, Id);
+    pObj = Gia_ManObj( p, Id );
+    Bmc_ManBCoreAssignVar( p, pObj, f, vNodes );
+    if ( Gia_ObjIsPi(p, pObj) )
+        return;
+    if ( Gia_ObjIsRo(p, pObj) )
+    {
+        Vec_IntPush( vRootsNew, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) );
+        return;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    Bmc_ManBCoreCollect_rec( p, Gia_ObjFaninId0p(p, pObj), f, vNodes, vRootsNew );
+    Bmc_ManBCoreCollect_rec( p, Gia_ObjFaninId1p(p, pObj), f, vNodes, vRootsNew );
+}
+Vec_Int_t * Bmc_ManBCoreCollect( Gia_Man_t * p, int iFrame, int iOut, sat_solver * pSat )
+{
+    Gia_Obj_t * pObj; 
+    int f, i, iObj, nNodesOld;
+    Vec_Int_t * vNodes  = Vec_IntAlloc( 100 );
+    Vec_Int_t * vRoots  = Vec_IntAlloc( 100 );
+    Vec_Int_t * vRoots2 = Vec_IntAlloc( 100 );
+    assert( iFrame >= 0 && iOut >= 0 );
+    // add first variables
+    Vec_IntPush( vNodes, -1 );
+    Vec_IntPush( vNodes, -1 );
+    Bmc_ManBCoreAssignVar( p, Gia_ManPo(p, iOut), iFrame, vNodes );
+    // start with root node
+    Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ManPo(p, iOut)) );
+    // iterate through time frames
+    for ( f = iFrame; f >= 0; f-- )
+    {
+        Gia_ManIncrementTravId( p );
+        // add constant node
+        Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
+        Bmc_ManBCoreAssignVar( p, Gia_ManConst0(p), f, vNodes );
+        sat_solver_add_const( pSat, Gia_ManConst0(p)->Value, 1 );
+        // collect nodes in this timeframe
+        Vec_IntClear( vRoots2 );
+        nNodesOld = Vec_IntSize(vNodes);
+        Gia_ManForEachObjVec( vRoots, p, pObj, i )
+            Bmc_ManBCoreCollect_rec( p, Gia_ObjFaninId0p(p, pObj), f, vNodes, vRoots2 );
+        if ( f == iFrame )
+        {
+            // add the final clause
+            pObj = Gia_ManPo(p, iOut);
+            assert( pObj->Value == 1 );
+            assert( Gia_ObjFanin0(pObj)->Value == 3 );
+//            sat_solver_add_const( pSat, Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) );
+            sat_solver_add_constraint( pSat, Gia_ObjFanin0(pObj)->Value, pObj->Value, Gia_ObjFaninC0(pObj) );
+        }
+        else
+        {
+            // connect current RIs to previous ROs
+            Gia_ManForEachObjVec( vRoots, p, pObj, i )
+                sat_solver_add_buffer( pSat, pObj->Value, Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) );
+        }
+        Gia_ManForEachObjVec( vRoots2, p, pObj, i )
+            pObj->Value = Gia_ObjRiToRo(p, pObj)->Value;
+        // add nodes of this timeframe
+        Vec_IntForEachEntryStart( vNodes, iObj, i, nNodesOld )
+        {
+            pObj = Gia_ManObj(p, iObj); i++;
+            if ( Gia_ObjIsCi(pObj) )
+                continue;
+            assert( Gia_ObjIsAnd(pObj) );
+            sat_solver_add_and( pSat, pObj->Value, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 );
+        }
+        // collect constant node
+        ABC_SWAP( Vec_Int_t *, vRoots, vRoots2 );
+    }
+    // add constraint variables for the init state
+    Gia_ManForEachObjVec( vRoots, p, pObj, i )
+    {
+        sat_solver_add_constraint( pSat, pObj->Value, Abc_Lit2Var(Vec_IntSize(vNodes)), 1 );
+        pObj = Gia_ObjRiToRo(p, pObj);
+        Bmc_ManBCoreAssignVar( p, pObj, -1, vNodes );
+    }
+    Vec_IntFree( vRoots );
+    Vec_IntFree( vRoots2 );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bmc_ManBCorePerform( Gia_Man_t * p, Bmc_BCorePar_t * pPars )
+{
+    clock_t clk = clock();
+    Intp_Man_t * pManProof;
+    Vec_Int_t * vVarMap, * vCore;
+    sat_solver * pSat;
+    FILE * pFile;
+    void * pSatCnf; 
+    int RetValue;
+    // create SAT solver
+    pSat = sat_solver_new();
+    sat_solver_store_alloc( pSat ); 
+    sat_solver_setnvars( pSat, 1000 );
+    sat_solver_set_runtime_limit( pSat, pPars->nTimeOut ? pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 );
+    vVarMap = Bmc_ManBCoreCollect( p, pPars->iFrame, pPars->iOutput, pSat );
+    sat_solver_store_mark_roots( pSat ); 
+    // create pivot variables
+    if ( pPars->pFilePivots )
+    {
+        Vec_Int_t * vPivots = Bmc_ManBCoreCollectPivots(p, pPars->pFilePivots, vVarMap);
+        sat_solver_set_pivot_variables( pSat, Vec_IntArray(vPivots), Vec_IntSize(vPivots) );
+        Vec_IntReleaseArray( vPivots );
+        Vec_IntFree( vPivots );
+    }
+    // solve the problem
+    RetValue = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( RetValue == l_Undef )
+    {
+        Vec_IntFree( vVarMap );
+        sat_solver_delete( pSat );
+        printf( "Timeout of conflict limit is reached.\n" );
+        return;
+    }
+    if ( RetValue == l_True )
+    {
+        Vec_IntFree( vVarMap );
+        sat_solver_delete( pSat );
+        printf( "The BMC problem is SAT.\n" );
+        return;
+    }
+    if ( pPars->fVerbose )
+    {
+        printf( "SAT solver returned UNSAT after %7d conflicts.      ", (int)pSat->stats.conflicts );
+        Abc_PrintTime( 1, "Time", clock() - clk );
+    }
+    assert( RetValue == l_False );
+    pSatCnf = sat_solver_store_release( pSat ); 
+//    Sto_ManDumpClauses( (Sto_Man_t *)pSatCnf, "cnf_store.txt" );
+    // derive the UNSAT core
+    clk = clock();
+    pManProof = Intp_ManAlloc();
+    vCore = (Vec_Int_t *)Intp_ManUnsatCore( pManProof, (Sto_Man_t *)pSatCnf, 1, pPars->fVerbose );
+    Intp_ManFree( pManProof );
+    if ( pPars->fVerbose )
+    {
+        printf( "UNSAT core contains %d (out of %d) learned clauses.   ", Vec_IntSize(vCore), sat_solver_nconflicts(pSat) );
+        Abc_PrintTime( 1, "Time", clock() - clk );
+    }
+    // write the problem
+    Vec_IntSort( vCore, 0 );
+    pFile = pPars->pFileProof ? fopen( pPars->pFileProof, "wb" ) : stdout;
+    Intp_ManUnsatCorePrintForBmc( pFile, (Sto_Man_t *)pSatCnf, vCore, vVarMap );
+    if ( pFile != stdout )
+        fclose( pFile );
+    // cleanup
+    Sto_ManFree( (Sto_Man_t *)pSatCnf );
+    Vec_IntFree( vVarMap );
+    Vec_IntFree( vCore );
+    sat_solver_delete( pSat );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcBmc.c b/abc-build/src/sat/bmc/bmcBmc.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcBmc.c
@@ -0,0 +1,338 @@
+/**CFile****************************************************************
+
+  FileName    [bmcBmc.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    [Simple BMC package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcBmc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "proof/fra/fra.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satStore.h"
+#include "bmc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Create timeframes of the manager for BMC.]
+
+  Description [The resulting manager is combinational. POs correspond to \
+  the property outputs in each time-frame.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManFramesBmc( Aig_Man_t * pAig, int nFrames )
+{
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+    int i, f;
+    assert( Saig_ManRegNum(pAig) > 0 );
+    pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames );
+    // map the constant node
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames );
+    // create variables for register outputs
+    Saig_ManForEachLo( pAig, pObj, i )
+        pObj->pData = Aig_ManConst0( pFrames );
+    // add timeframes
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // create PI nodes for this frame
+        Saig_ManForEachPi( pAig, pObj, i )
+            pObj->pData = Aig_ObjCreateCi( pFrames );
+        // add internal nodes of this frame
+        Aig_ManForEachNode( pAig, pObj, i )
+            pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+        // create POs for this frame
+        Saig_ManForEachPo( pAig, pObj, i )
+            Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) );
+        if ( f == nFrames - 1 )
+            break;
+        // save register inputs
+        Saig_ManForEachLi( pAig, pObj, i )
+            pObj->pData = Aig_ObjChild0Copy(pObj);
+        // transfer to register outputs
+        Saig_ManForEachLiLo(  pAig, pObjLi, pObjLo, i )
+            pObjLo->pData = pObjLi->pData;
+    }
+    Aig_ManCleanup( pFrames );
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of internal nodes that are not counted yet.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManFramesCount_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+    if ( !Aig_ObjIsNode(pObj) )
+        return 0;
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return 0;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    return 1 + Saig_ManFramesCount_rec( p, Aig_ObjFanin0(pObj) ) + 
+        Saig_ManFramesCount_rec( p, Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create timeframes of the manager for BMC.]
+
+  Description [The resulting manager is combinational. POs correspond to 
+  the property outputs in each time-frame.
+  The unrolling is stopped as soon as the number of nodes in the frames
+  exceeds the given maximum size.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManFramesBmcLimit( Aig_Man_t * pAig, int nFrames, int nSizeMax )
+{
+    Aig_Man_t * pFrames;
+    Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjPo;
+    int i, f, Counter = 0;
+    assert( Saig_ManRegNum(pAig) > 0 );
+    pFrames = Aig_ManStart( nSizeMax );
+    Aig_ManIncrementTravId( pFrames );
+    // map the constant node
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames );
+    // create variables for register outputs
+    Saig_ManForEachLo( pAig, pObj, i )
+        pObj->pData = Aig_ManConst0( pFrames );
+    // add timeframes
+    Counter = 0;
+    for ( f = 0; f < nFrames; f++ )
+    {
+        // create PI nodes for this frame
+        Saig_ManForEachPi( pAig, pObj, i )
+            pObj->pData = Aig_ObjCreateCi( pFrames );
+        // add internal nodes of this frame
+        Aig_ManForEachNode( pAig, pObj, i )
+            pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+        // create POs for this frame
+        Saig_ManForEachPo( pAig, pObj, i )
+        {
+            pObjPo = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) );
+            Counter += Saig_ManFramesCount_rec( pFrames, Aig_ObjFanin0(pObjPo) );
+        }
+        if ( Counter >= nSizeMax )
+        {
+            Aig_ManCleanup( pFrames );
+            return pFrames;
+        }
+        if ( f == nFrames - 1 )
+            break;
+        // save register inputs
+        Saig_ManForEachLi( pAig, pObj, i )
+            pObj->pData = Aig_ObjChild0Copy(pObj);
+        // transfer to register outputs
+        Saig_ManForEachLiLo(  pAig, pObjLi, pObjLo, i )
+            pObjLo->pData = pObjLi->pData;
+    }
+    Aig_ManCleanup( pFrames );
+    return pFrames;
+}
+
+ABC_NAMESPACE_IMPL_END
+
+#include "misc/util/utilMem.h"
+
+ABC_NAMESPACE_IMPL_START
+
+ 
+/**Function*************************************************************
+
+  Synopsis    [Performs BMC for the given AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManBmcSimple( Aig_Man_t * pAig, int nFrames, int nSizeMax, int nConfLimit, int fRewrite, int fVerbose, int * piFrame, int nCofFanLit )
+{
+    extern Aig_Man_t * Gia_ManCofactorAig( Aig_Man_t * p, int nFrames, int nCofFanLit );
+    sat_solver * pSat;
+    Cnf_Dat_t * pCnf;
+    Aig_Man_t * pFrames, * pAigTemp;
+    Aig_Obj_t * pObj;
+    int status, Lit, i, RetValue = -1;
+    abctime clk;
+
+    // derive the timeframes
+    clk = Abc_Clock();
+    if ( nCofFanLit )
+    {
+        pFrames = Gia_ManCofactorAig( pAig, nFrames, nCofFanLit );
+        if ( pFrames == NULL )
+            return -1;
+    }
+    else if ( nSizeMax > 0 )
+    {
+        pFrames = Saig_ManFramesBmcLimit( pAig, nFrames, nSizeMax );
+        nFrames = Aig_ManCoNum(pFrames) / Saig_ManPoNum(pAig) + ((Aig_ManCoNum(pFrames) % Saig_ManPoNum(pAig)) > 0);
+    }
+    else
+        pFrames = Saig_ManFramesBmc( pAig, nFrames );
+    if ( piFrame )
+        *piFrame = nFrames;
+    if ( fVerbose )
+    {
+        printf( "Running \"bmc\". AIG:  PI/PO/Reg = %d/%d/%d.  Node = %6d. Lev = %5d.\n", 
+            Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig),
+            Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) );
+        printf( "Time-frames (%d):  PI/PO = %d/%d.  Node = %6d. Lev = %5d.  ", 
+            nFrames, Aig_ManCiNum(pFrames), Aig_ManCoNum(pFrames), 
+            Aig_ManNodeNum(pFrames), Aig_ManLevelNum(pFrames) );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+        fflush( stdout );
+    }
+    // rewrite the timeframes
+    if ( fRewrite )
+    {
+        clk = Abc_Clock();
+//        pFrames = Dar_ManBalance( pAigTemp = pFrames, 0 );
+        pFrames = Dar_ManRwsat( pAigTemp = pFrames, 1, 0 );
+        Aig_ManStop( pAigTemp );
+        if ( fVerbose )
+        {
+            printf( "Time-frames after rewriting:  Node = %6d. Lev = %5d.  ", 
+                Aig_ManNodeNum(pFrames), Aig_ManLevelNum(pFrames) );
+            ABC_PRT( "Time", Abc_Clock() - clk );
+            fflush( stdout );
+        }
+    }
+    // create the SAT solver
+    clk = Abc_Clock();
+    pCnf = Cnf_Derive( pFrames, Aig_ManCoNum(pFrames) );  
+//if ( s_fInterrupt )
+//return -1;
+    pSat = sat_solver_new();
+    sat_solver_setnvars( pSat, pCnf->nVars );
+    for ( i = 0; i < pCnf->nClauses; i++ )
+    {
+        if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
+            assert( 0 );
+    }
+    if ( fVerbose )
+    {
+        printf( "CNF: Variables = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+        fflush( stdout );
+    }
+    status = sat_solver_simplify(pSat);
+    if ( status == 0 )
+    {
+        if ( fVerbose )
+        {
+            printf( "The BMC problem is trivially UNSAT\n" );
+            fflush( stdout );
+        }
+    }
+    else
+    {
+        abctime clkPart = Abc_Clock();
+        Aig_ManForEachCo( pFrames, pObj, i )
+        {
+//if ( s_fInterrupt )
+//return -1;
+            Lit = toLitCond( pCnf->pVarNums[pObj->Id], 0 );
+            if ( fVerbose )
+            {
+                printf( "Solving output %2d of frame %3d ... \r", 
+                    i % Saig_ManPoNum(pAig), i / Saig_ManPoNum(pAig) );
+            }
+            clk = Abc_Clock();
+            status = sat_solver_solve( pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+            if ( fVerbose && (i % Saig_ManPoNum(pAig) == Saig_ManPoNum(pAig) - 1) )
+            {
+                printf( "Solved %2d outputs of frame %3d.  ", 
+                    Saig_ManPoNum(pAig), i / Saig_ManPoNum(pAig) );
+                printf( "Conf =%8.0f. Imp =%11.0f. ", (double)pSat->stats.conflicts, (double)pSat->stats.propagations );
+                ABC_PRT( "T", Abc_Clock() - clkPart );
+                clkPart = Abc_Clock();
+                fflush( stdout );
+            }
+            if ( status == l_False )
+            {
+/*
+                Lit = lit_neg( Lit );
+                RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
+                assert( RetValue );
+                if ( pSat->qtail != pSat->qhead )
+                {
+                    RetValue = sat_solver_simplify(pSat);
+                    assert( RetValue );
+                }
+*/
+            }
+            else if ( status == l_True )
+            {
+                Vec_Int_t * vCiIds = Cnf_DataCollectPiSatNums( pCnf, pFrames );
+                int * pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize );
+                pModel[Aig_ManCiNum(pFrames)] = pObj->Id;
+                pAig->pSeqModel = Fra_SmlCopyCounterExample( pAig, pFrames, pModel );
+                ABC_FREE( pModel );
+                Vec_IntFree( vCiIds );
+
+                if ( piFrame )
+                    *piFrame = i / Saig_ManPoNum(pAig);
+                RetValue = 0;
+                break;
+            }
+            else
+            {
+                if ( piFrame )
+                    *piFrame = i / Saig_ManPoNum(pAig);
+                RetValue = -1;
+                break;
+            }
+        }
+    }
+    sat_solver_delete( pSat );
+    Cnf_DataFree( pCnf );
+    Aig_ManStop( pFrames );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcBmc2.c b/abc-build/src/sat/bmc/bmcBmc2.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcBmc2.c
@@ -0,0 +1,888 @@
+/**CFile****************************************************************
+
+  FileName    [bmcBmc2.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    [Simple BMC package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcBmc2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satStore.h"
+#include "proof/ssw/ssw.h"
+#include "bmc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+//#define AIG_VISITED       ((Aig_Obj_t *)(ABC_PTRUINT_T)1)
+
+typedef struct Saig_Bmc_t_ Saig_Bmc_t;
+struct Saig_Bmc_t_
+{
+    // parameters
+    int                   nFramesMax;     // the max number of timeframes to consider
+    int                   nNodesMax;      // the max number of nodes to add
+    int                   nConfMaxOne;    // the max number of conflicts at a target
+    int                   nConfMaxAll;    // the max number of conflicts for all targets
+    int                   fVerbose;       // enables verbose output
+    // AIG managers
+    Aig_Man_t *           pAig;           // the user's AIG manager
+    Aig_Man_t *           pFrm;           // Frames manager
+    Vec_Int_t *           vVisited;       // nodes visited in Frames
+    // node mapping
+    int                   nObjs;          // the largest number of an AIG object
+    Vec_Ptr_t *           vAig2Frm;       // mapping of AIG nodees into Frames nodes
+    // SAT solver
+    sat_solver *          pSat;           // SAT solver
+    int                   nSatVars;       // the number of used SAT variables
+    Vec_Int_t *           vObj2Var;       // mapping of frames objects in CNF variables
+    int                   nStitchVars;
+    // subproblems
+    Vec_Ptr_t *           vTargets;       // targets to be solved in this interval
+    int                   iFramePrev;     // previous frame  
+    int                   iFrameLast;     // last frame  
+    int                   iOutputLast;    // last output
+    int                   iFrameFail;     // failed frame 
+    int                   iOutputFail;    // failed output
+};
+
+static inline Aig_Obj_t * Saig_BmcObjFrame( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i )                       
+{ 
+//    return (Aig_Obj_t *)Vec_PtrGetEntry( p->vAig2Frm, p->nObjs*i+pObj->Id );     
+    Aig_Obj_t * pRes;
+    Vec_Int_t * vFrame = (Vec_Int_t *)Vec_PtrEntry( p->vAig2Frm, i );
+    int iObjLit = Vec_IntEntry( vFrame, Aig_ObjId(pObj) );
+    if ( iObjLit == -1 )
+        return NULL;
+    pRes = Aig_ManObj( p->pFrm, Abc_Lit2Var(iObjLit) );
+    if ( pRes == NULL )
+        Vec_IntWriteEntry( vFrame, Aig_ObjId(pObj), -1 );
+    else
+        pRes = Aig_NotCond( pRes, Abc_LitIsCompl(iObjLit) );
+    return pRes;
+}
+static inline void        Saig_BmcObjSetFrame( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) 
+{
+//    Vec_PtrSetEntry( p->vAig2Frm, p->nObjs*i+pObj->Id, pNode );     
+    Vec_Int_t * vFrame;
+    int iObjLit;
+    if ( i == Vec_PtrSize(p->vAig2Frm) )
+        Vec_PtrPush( p->vAig2Frm, Vec_IntStartFull(p->nObjs) );
+    assert( i < Vec_PtrSize(p->vAig2Frm) );
+    vFrame = (Vec_Int_t *)Vec_PtrEntry( p->vAig2Frm, i );
+    if ( pNode == NULL )
+        iObjLit = -1;
+    else
+        iObjLit = Abc_Var2Lit( Aig_ObjId(Aig_Regular(pNode)), Aig_IsComplement(pNode) );
+    Vec_IntWriteEntry( vFrame, Aig_ObjId(pObj), iObjLit );
+}
+
+static inline Aig_Obj_t * Saig_BmcObjChild0( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i )                   { assert( !Aig_IsComplement(pObj) ); return Aig_NotCond(Saig_BmcObjFrame(p, Aig_ObjFanin0(pObj), i), Aig_ObjFaninC0(pObj));  }
+static inline Aig_Obj_t * Saig_BmcObjChild1( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i )                   { assert( !Aig_IsComplement(pObj) ); return Aig_NotCond(Saig_BmcObjFrame(p, Aig_ObjFanin1(pObj), i), Aig_ObjFaninC1(pObj));  }
+
+static inline int         Saig_BmcSatNum( Saig_Bmc_t * p, Aig_Obj_t * pObj )                             { return Vec_IntGetEntry( p->vObj2Var, pObj->Id );  }
+static inline void        Saig_BmcSetSatNum( Saig_Bmc_t * p, Aig_Obj_t * pObj, int Num )                 { Vec_IntSetEntry(p->vObj2Var, pObj->Id, Num);      }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+#define ABS_ZER 1
+#define ABS_ONE 2
+#define ABS_UND 3
+
+static inline int Abs_ManSimInfoNot( int Value )
+{
+    if ( Value == ABS_ZER )
+        return ABS_ONE;
+    if ( Value == ABS_ONE )
+        return ABS_ZER;
+    return ABS_UND;
+}
+
+static inline int Abs_ManSimInfoAnd( int Value0, int Value1 )
+{
+    if ( Value0 == ABS_ZER || Value1 == ABS_ZER )
+        return ABS_ZER;
+    if ( Value0 == ABS_ONE && Value1 == ABS_ONE )
+        return ABS_ONE;
+    return ABS_UND;
+}
+
+static inline int Abs_ManSimInfoGet( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame )
+{
+    unsigned * pInfo = (unsigned *)Vec_PtrEntry( vSimInfo, iFrame );
+    return 3 & (pInfo[Aig_ObjId(pObj) >> 4] >> ((Aig_ObjId(pObj) & 15) << 1));
+}
+
+static inline void Abs_ManSimInfoSet( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame, int Value )
+{
+    unsigned * pInfo = (unsigned *)Vec_PtrEntry( vSimInfo, iFrame );
+    assert( Value >= ABS_ZER && Value <= ABS_UND );
+    Value ^= Abs_ManSimInfoGet( vSimInfo, pObj, iFrame );
+    pInfo[Aig_ObjId(pObj) >> 4] ^= (Value << ((Aig_ObjId(pObj) & 15) << 1));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs ternary simulation for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abs_ManExtendOneEval_rec( Vec_Ptr_t * vSimInfo, Aig_Man_t * p, Aig_Obj_t * pObj, int iFrame )
+{
+    int Value0, Value1, Value;
+    Value = Abs_ManSimInfoGet( vSimInfo, pObj, iFrame );
+    if ( Value )
+        return Value;
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        assert( Saig_ObjIsLo(p, pObj) );
+        Value = Abs_ManExtendOneEval_rec( vSimInfo, p, Saig_ObjLoToLi(p, pObj), iFrame-1 );
+        Abs_ManSimInfoSet( vSimInfo, pObj, iFrame, Value );
+        return Value;
+    }
+    Value0 = Abs_ManExtendOneEval_rec( vSimInfo, p, Aig_ObjFanin0(pObj), iFrame );
+    if ( Aig_ObjFaninC0(pObj) )
+        Value0 = Abs_ManSimInfoNot( Value0 );
+    if ( Aig_ObjIsCo(pObj) )
+    {
+        Abs_ManSimInfoSet( vSimInfo, pObj, iFrame, Value0 );
+        return Value0;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    if ( Value0 == ABS_ZER )
+        Value = ABS_ZER;
+    else
+    {
+        Value1 = Abs_ManExtendOneEval_rec( vSimInfo, p, Aig_ObjFanin1(pObj), iFrame );
+        if ( Aig_ObjFaninC1(pObj) )
+            Value1 = Abs_ManSimInfoNot( Value1 );
+        Value = Abs_ManSimInfoAnd( Value0, Value1 );
+    }
+    Abs_ManSimInfoSet( vSimInfo, pObj, iFrame, Value );
+    assert( Value );
+    return Value;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs ternary simulation for one design.]
+
+  Description [The returned array contains the result of ternary 
+  simulation for all the frames where the output could be proved 0.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Abs_ManTernarySimulate( Aig_Man_t * p, int nFramesMax, int fVerbose )
+{
+    Vec_Ptr_t * vSimInfo;
+    Aig_Obj_t * pObj;
+    int i, f, nFramesLimit, nFrameWords;
+    abctime clk = Abc_Clock();
+    assert( Aig_ManRegNum(p) > 0 );
+    // the maximum number of frames will be determined to use at most 200Mb of RAM
+    nFramesLimit = 1 + (200000000 * 4)/Aig_ManObjNum(p);
+    nFramesLimit = Abc_MinInt( nFramesLimit, nFramesMax );
+    nFrameWords  = Abc_BitWordNum( 2 * Aig_ManObjNum(p) );
+    // allocate simulation info
+    vSimInfo = Vec_PtrAlloc( nFramesLimit );
+    for ( f = 0; f < nFramesLimit; f++ )
+    {
+        Vec_PtrPush( vSimInfo, ABC_CALLOC(unsigned, nFrameWords) );
+        if ( f == 0 ) 
+        {
+            Saig_ManForEachLo( p, pObj, i )
+                Abs_ManSimInfoSet( vSimInfo, pObj, 0, ABS_ZER );
+        }
+        Abs_ManSimInfoSet( vSimInfo, Aig_ManConst1(p), f, ABS_ONE );
+        Saig_ManForEachPi( p, pObj, i )
+            Abs_ManSimInfoSet( vSimInfo, pObj, f, ABS_UND );
+        Saig_ManForEachPo( p, pObj, i )
+            Abs_ManExtendOneEval_rec( vSimInfo, p, pObj, f );
+        // check if simulation has derived at least one fail or unknown
+        Saig_ManForEachPo( p, pObj, i )
+            if ( Abs_ManSimInfoGet(vSimInfo, pObj, f) != ABS_ZER )
+            {
+                if ( fVerbose )
+                {
+                    printf( "Ternary sim found non-zero output in frame %d.  Used %5.2f MB.  ", 
+                        f, 0.25 * (f+1) * Aig_ManObjNum(p) / (1<<20) );
+                    ABC_PRT( "Time", Abc_Clock() - clk );
+                }
+                return vSimInfo;
+            }
+    }
+    if ( fVerbose )
+    {
+        printf( "Ternary sim proved all outputs in the first %d frames.  Used %5.2f MB.  ", 
+            nFramesLimit, 0.25 * nFramesLimit * Aig_ManObjNum(p) / (1<<20) );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    return vSimInfo;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Free the array of simulation info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abs_ManFreeAray( Vec_Ptr_t * p )
+{
+    void * pTemp;
+    int i;
+    Vec_PtrForEachEntry( void *, p, pTemp, i )
+        ABC_FREE( pTemp );
+    Vec_PtrFree( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Create manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Saig_Bmc_t * Saig_BmcManStart( Aig_Man_t * pAig, int nFramesMax, int nNodesMax, int nConfMaxOne, int nConfMaxAll, int fVerbose )
+{
+    Saig_Bmc_t * p;
+    Aig_Obj_t * pObj;
+    int i, Lit;
+//    assert( Aig_ManRegNum(pAig) > 0 );
+    p = (Saig_Bmc_t *)ABC_ALLOC( char, sizeof(Saig_Bmc_t) );
+    memset( p, 0, sizeof(Saig_Bmc_t) );
+    // set parameters
+    p->nFramesMax   = nFramesMax;
+    p->nNodesMax    = nNodesMax;
+    p->nConfMaxOne  = nConfMaxOne;
+    p->nConfMaxAll  = nConfMaxAll;
+    p->fVerbose     = fVerbose;
+    p->pAig         = pAig;
+    p->nObjs        = Aig_ManObjNumMax(pAig);
+    // create node and variable mappings
+    p->vAig2Frm     = Vec_PtrAlloc( 100 );
+    p->vObj2Var     = Vec_IntAlloc( 0 );
+    Vec_IntFill( p->vObj2Var, p->nObjs, 0 );
+    // start the AIG manager and map primary inputs
+    p->pFrm         = Aig_ManStart( p->nObjs );
+    Saig_ManForEachLo( pAig, pObj, i )
+        Saig_BmcObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrm) ); 
+    // create SAT solver
+    p->nSatVars     = 1;
+    p->pSat         = sat_solver_new();
+    p->pSat->nLearntStart = 10000;//p->pPars->nLearnedStart;
+    p->pSat->nLearntDelta =  5000;//p->pPars->nLearnedDelta;
+    p->pSat->nLearntRatio =    75;//p->pPars->nLearnedPerce;
+    p->pSat->nLearntMax   = p->pSat->nLearntStart;
+    sat_solver_setnvars( p->pSat, 2000 );
+    Lit = toLit( p->nSatVars );
+    sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+    Saig_BmcSetSatNum( p, Aig_ManConst1(p->pFrm), p->nSatVars++ );
+    // other data structures
+    p->vTargets     = Vec_PtrAlloc( 1000 );
+    p->vVisited     = Vec_IntAlloc( 1000 );
+    p->iOutputFail  = -1;
+    p->iFrameFail   = -1;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Delete manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_BmcManStop( Saig_Bmc_t * p )
+{
+    Aig_ManStop( p->pFrm  );
+    Vec_VecFree( (Vec_Vec_t *)p->vAig2Frm );
+    Vec_IntFree( p->vObj2Var );
+    sat_solver_delete( p->pSat );
+    Vec_PtrFree( p->vTargets );
+    Vec_IntFree( p->vVisited );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Explores the possibility of constructing the output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+Aig_Obj_t * Saig_BmcIntervalExplore_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i )
+{
+    Aig_Obj_t * pRes, * p0, * p1, * pConst1 = Aig_ManConst1(p->pAig);
+    pRes = Saig_BmcObjFrame( p, pObj, i );
+    if ( pRes != NULL )
+        return pRes;
+    if ( Saig_ObjIsPi( p->pAig, pObj ) )
+        pRes = AIG_VISITED;
+    else if ( Saig_ObjIsLo( p->pAig, pObj ) )
+        pRes = Saig_BmcIntervalExplore_rec( p, Saig_ObjLoToLi(p->pAig, pObj), i-1 );
+    else if ( Aig_ObjIsCo( pObj ) )
+    {
+        pRes = Saig_BmcIntervalExplore_rec( p, Aig_ObjFanin0(pObj), i );
+        if ( pRes != AIG_VISITED )
+            pRes = Saig_BmcObjChild0( p, pObj, i );
+    }
+    else 
+    {
+        p0 = Saig_BmcIntervalExplore_rec( p, Aig_ObjFanin0(pObj), i );
+        if ( p0 != AIG_VISITED )
+            p0 = Saig_BmcObjChild0( p, pObj, i );
+        p1 = Saig_BmcIntervalExplore_rec( p, Aig_ObjFanin1(pObj), i );
+        if ( p1 != AIG_VISITED )
+            p1 = Saig_BmcObjChild1( p, pObj, i );
+
+        if ( p0 == Aig_Not(p1) )
+            pRes = Aig_ManConst0(p->pFrm);
+        else if ( Aig_Regular(p0) == pConst1 )
+            pRes = (p0 == pConst1) ? p1 : Aig_ManConst0(p->pFrm);
+        else if ( Aig_Regular(p1) == pConst1 )
+            pRes = (p1 == pConst1) ? p0 : Aig_ManConst0(p->pFrm);
+        else 
+            pRes = AIG_VISITED;
+
+        if ( pRes != AIG_VISITED && !Aig_ObjIsConst1(Aig_Regular(pRes)) )
+            pRes = AIG_VISITED;
+    }
+    Saig_BmcObjSetFrame( p, pObj, i, pRes );
+    return pRes;
+}
+*/
+
+/**Function*************************************************************
+
+  Synopsis    [Performs the actual construction of the output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Saig_BmcIntervalConstruct_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i, Vec_Int_t * vVisited )
+{
+    Aig_Obj_t * pRes;
+    pRes = Saig_BmcObjFrame( p, pObj, i );
+    if ( pRes != NULL )
+        return pRes;
+    if ( Saig_ObjIsPi( p->pAig, pObj ) )
+        pRes = Aig_ObjCreateCi(p->pFrm);
+    else if ( Saig_ObjIsLo( p->pAig, pObj ) )
+        pRes = Saig_BmcIntervalConstruct_rec( p, Saig_ObjLoToLi(p->pAig, pObj), i-1, vVisited );
+    else if ( Aig_ObjIsCo( pObj ) )
+    {
+        Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin0(pObj), i, vVisited );
+        pRes = Saig_BmcObjChild0( p, pObj, i );
+    }
+    else 
+    {
+        Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin0(pObj), i, vVisited );
+        if ( Saig_BmcObjChild0(p, pObj, i) == Aig_ManConst0(p->pFrm) )
+            pRes = Aig_ManConst0(p->pFrm);
+        else
+        {
+            Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin1(pObj), i, vVisited );
+            pRes = Aig_And( p->pFrm, Saig_BmcObjChild0(p, pObj, i), Saig_BmcObjChild1(p, pObj, i) );
+        }
+    }
+    assert( pRes != NULL );
+    Saig_BmcObjSetFrame( p, pObj, i, pRes );
+    Vec_IntPush( vVisited, Aig_ObjId(pObj) );
+    Vec_IntPush( vVisited, i );
+    return pRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds new AIG nodes to the frames.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_BmcInterval( Saig_Bmc_t * p )
+{
+    Aig_Obj_t * pTarget;
+    int i, iObj, iFrame;
+    int nNodes = Aig_ManObjNum( p->pFrm );
+    Vec_PtrClear( p->vTargets );
+    p->iFramePrev = p->iFrameLast;
+    for ( ; p->iFrameLast < p->nFramesMax; p->iFrameLast++, p->iOutputLast = 0 )
+    { 
+        if ( p->iOutputLast == 0 )
+        {
+            Saig_BmcObjSetFrame( p, Aig_ManConst1(p->pAig), p->iFrameLast, Aig_ManConst1(p->pFrm) );
+        }
+        for ( ; p->iOutputLast < Saig_ManPoNum(p->pAig); p->iOutputLast++ )
+        {
+            if ( Aig_ManObjNum(p->pFrm) >= nNodes + p->nNodesMax )
+                return;
+//            Saig_BmcIntervalExplore_rec( p, Aig_ManCo(p->pAig, p->iOutputLast), p->iFrameLast );
+            Vec_IntClear( p->vVisited );
+            pTarget = Saig_BmcIntervalConstruct_rec( p, Aig_ManCo(p->pAig, p->iOutputLast), p->iFrameLast, p->vVisited );
+            Vec_PtrPush( p->vTargets, pTarget );
+            Aig_ObjCreateCo( p->pFrm, pTarget );
+            Aig_ManCleanup( p->pFrm ); // it is not efficient to cleanup the whole manager!!!
+            // check if the node is gone
+            Vec_IntForEachEntryDouble( p->vVisited, iObj, iFrame, i )
+                Saig_BmcObjFrame( p, Aig_ManObj(p->pAig, iObj), iFrame );
+            // it is not efficient to remove nodes, which may be used later!!!
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs the actual construction of the output.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Obj_t * Saig_BmcIntervalToAig_rec( Saig_Bmc_t * p, Aig_Man_t * pNew, Aig_Obj_t * pObj )
+{
+    if ( pObj->pData )
+        return (Aig_Obj_t *)pObj->pData;
+    Vec_IntPush( p->vVisited, Aig_ObjId(pObj) );
+    if ( Saig_BmcSatNum(p, pObj) || Aig_ObjIsCi(pObj) )
+    {
+        p->nStitchVars += !Aig_ObjIsCi(pObj);
+        return (Aig_Obj_t *)(pObj->pData = Aig_ObjCreateCi(pNew));
+    }
+    Saig_BmcIntervalToAig_rec( p, pNew, Aig_ObjFanin0(pObj) );
+    Saig_BmcIntervalToAig_rec( p, pNew, Aig_ObjFanin1(pObj) );
+    assert( pObj->pData == NULL );
+    return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates AIG of the newly added nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_BmcIntervalToAig( Saig_Bmc_t * p )
+{
+    Aig_Man_t * pNew;
+    Aig_Obj_t * pObj, * pObjNew;
+    int i;
+    Aig_ManForEachObj( p->pFrm, pObj, i )
+        assert( pObj->pData == NULL );
+
+    pNew = Aig_ManStart( p->nNodesMax );
+    Aig_ManConst1(p->pFrm)->pData = Aig_ManConst1(pNew);
+    Vec_IntClear( p->vVisited );
+    Vec_IntPush( p->vVisited, Aig_ObjId(Aig_ManConst1(p->pFrm)) );
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vTargets, pObj, i )
+    {
+//        assert( !Aig_ObjIsConst1(Aig_Regular(pObj)) );
+        pObjNew = Saig_BmcIntervalToAig_rec( p, pNew, Aig_Regular(pObj) );
+        assert( !Aig_IsComplement(pObjNew) );
+        Aig_ObjCreateCo( pNew, pObjNew );
+    } 
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CNF for the newly added nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_BmcLoadCnf( Saig_Bmc_t * p, Cnf_Dat_t * pCnf )
+{
+    Aig_Obj_t * pObj, * pObjNew;
+    int i, Lits[2], VarNumOld, VarNumNew;
+    Aig_ManForEachObjVec( p->vVisited, p->pFrm, pObj, i )
+    {
+        // get the new variable of this node
+        pObjNew     = (Aig_Obj_t *)pObj->pData;
+        pObj->pData = NULL;
+        VarNumNew   = pCnf->pVarNums[ pObjNew->Id ];
+        if ( VarNumNew == -1 )
+            continue;
+        // get the old variable of this node
+        VarNumOld   = Saig_BmcSatNum( p, pObj );
+        if ( VarNumOld == 0 )
+        {
+            Saig_BmcSetSatNum( p, pObj, VarNumNew );
+            continue;
+        }
+        // add clauses connecting existing variables
+        Lits[0] = toLitCond( VarNumOld, 0 );
+        Lits[1] = toLitCond( VarNumNew, 1 );
+        if ( !sat_solver_addclause( p->pSat, Lits, Lits+2 ) )
+            assert( 0 );
+        Lits[0] = toLitCond( VarNumOld, 1 );
+        Lits[1] = toLitCond( VarNumNew, 0 );
+        if ( !sat_solver_addclause( p->pSat, Lits, Lits+2 ) )
+            assert( 0 );
+    }
+    // add CNF to the SAT solver
+    for ( i = 0; i < pCnf->nClauses; i++ )
+        if ( !sat_solver_addclause( p->pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
+            break;
+    if ( i < pCnf->nClauses )
+        printf( "SAT solver became UNSAT after adding clauses.\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Solves targets with the given resource limit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_BmcDeriveFailed( Saig_Bmc_t * p, int iTargetFail )
+{
+    int k;
+    p->iOutputFail = p->iOutputLast;
+    p->iFrameFail  = p->iFrameLast;
+    for ( k = Vec_PtrSize(p->vTargets); k > iTargetFail; k-- )
+    {
+        if ( p->iOutputFail == 0 )
+        {
+            p->iOutputFail = Saig_ManPoNum(p->pAig);
+            p->iFrameFail--;
+        }
+        p->iOutputFail--;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Solves targets with the given resource limit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Saig_BmcGenerateCounterExample( Saig_Bmc_t * p )
+{
+    Abc_Cex_t * pCex;
+    Aig_Obj_t * pObj, * pObjFrm;
+    int i, f, iVarNum;
+    // start the counter-example
+    pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), p->iFrameFail+1 );
+    pCex->iFrame = p->iFrameFail;
+    pCex->iPo    = p->iOutputFail;
+    // copy the bit data
+    for ( f = 0; f <= p->iFrameFail; f++ )
+    {
+        Saig_ManForEachPi( p->pAig, pObj, i )
+        {
+            pObjFrm = Saig_BmcObjFrame( p, pObj, f );
+            if ( pObjFrm == NULL )
+                continue;
+            iVarNum = Saig_BmcSatNum( p, pObjFrm );
+            if ( iVarNum == 0 )
+                continue;
+            if ( sat_solver_var_value( p->pSat, iVarNum ) )
+                Abc_InfoSetBit( pCex->pData, pCex->nRegs + Saig_ManPiNum(p->pAig) * f + i );
+        }
+    }
+    // verify the counter example
+    if ( !Saig_ManVerifyCex( p->pAig, pCex ) )
+    {
+        printf( "Saig_BmcGenerateCounterExample(): Counter-example is invalid.\n" );
+        Abc_CexFree( pCex );
+        pCex = NULL;
+    }
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Solves targets with the given resource limit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_BmcSolveTargets( Saig_Bmc_t * p, int nStart, int * pnOutsSolved )
+{
+    Aig_Obj_t * pObj;
+    int i, k, VarNum, Lit, status, RetValue;
+    assert( Vec_PtrSize(p->vTargets) > 0 );
+    if ( p->pSat->qtail != p->pSat->qhead )
+    {
+        RetValue = sat_solver_simplify(p->pSat);
+        assert( RetValue != 0 );
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vTargets, pObj, i )
+    {
+        if ( ((*pnOutsSolved)++ / Saig_ManPoNum(p->pAig)) < nStart )
+            continue;
+        if ( p->nConfMaxAll && p->pSat->stats.conflicts > p->nConfMaxAll )
+            return l_Undef;
+        VarNum = Saig_BmcSatNum( p, Aig_Regular(pObj) );
+        Lit = toLitCond( VarNum, Aig_IsComplement(pObj) );
+        RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, (ABC_INT64_T)p->nConfMaxOne, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        if ( RetValue == l_False ) // unsat
+        {
+            // add final unit clause
+            Lit = lit_neg( Lit );
+            status = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+            assert( status );
+            // add learned units
+            for ( k = 0; k < veci_size(&p->pSat->unit_lits); k++ )
+            {
+                Lit = veci_begin(&p->pSat->unit_lits)[k];
+                status = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+                assert( status );
+            }
+            veci_resize(&p->pSat->unit_lits, 0);
+            // propagate units
+            sat_solver_compress( p->pSat );
+            continue;
+        }
+        if ( RetValue == l_Undef ) // undecided
+            return l_Undef;
+        // generate counter-example
+        Saig_BmcDeriveFailed( p, i );
+        p->pAig->pSeqModel = Saig_BmcGenerateCounterExample( p );
+
+        {
+//            extern Vec_Int_t * Saig_ManExtendCounterExampleTest( Aig_Man_t * p, int iFirstPi, void * pCex );
+//            Saig_ManExtendCounterExampleTest( p->pAig, 0, p->pAig->pSeqModel );
+        }
+        return l_True;
+    }
+    return l_False;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_BmcAddTargetsAsPos( Saig_Bmc_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Vec_PtrForEachEntry( Aig_Obj_t *, p->vTargets, pObj, i )
+        Aig_ObjCreateCo( p->pFrm, pObj );
+    Aig_ManPrintStats( p->pFrm );
+    Aig_ManCleanup( p->pFrm );
+    Aig_ManPrintStats( p->pFrm );
+} 
+
+/**Function*************************************************************
+
+  Synopsis    [Performs BMC with the given parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_BmcPerform( Aig_Man_t * pAig, int nStart, int nFramesMax, int nNodesMax, int nTimeOut, int nConfMaxOne, int nConfMaxAll, int fVerbose, int fVerbOverwrite, int * piFrames, int fSilent )
+{
+    Saig_Bmc_t * p;
+    Aig_Man_t * pNew;
+    Cnf_Dat_t * pCnf;
+    int nOutsSolved = 0;
+    int Iter, RetValue = -1;
+    abctime nTimeToStop = nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0;
+    abctime clk = Abc_Clock(), clk2, clkTotal = Abc_Clock();
+    int Status = -1;
+/*
+    Vec_Ptr_t * vSimInfo;
+    vSimInfo = Abs_ManTernarySimulate( pAig, nFramesMax, fVerbose );
+    Abs_ManFreeAray( vSimInfo );
+*/
+    if ( fVerbose )
+    {
+        printf( "Running \"bmc2\". AIG:  PI/PO/Reg = %d/%d/%d.  Node = %6d. Lev = %5d.\n", 
+            Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig),
+            Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) );
+        printf( "Params: FramesMax = %d. NodesDelta = %d. ConfMaxOne = %d. ConfMaxAll = %d.\n", 
+            nFramesMax, nNodesMax, nConfMaxOne, nConfMaxAll );
+    } 
+    nFramesMax = nFramesMax ? nFramesMax : ABC_INFINITY;
+    p = Saig_BmcManStart( pAig, nFramesMax, nNodesMax, nConfMaxOne, nConfMaxAll, fVerbose );
+    // set runtime limit
+    if ( nTimeOut )
+        sat_solver_set_runtime_limit( p->pSat, nTimeToStop );
+    for ( Iter = 0; ; Iter++ )
+    {
+        clk2 = Abc_Clock();
+        // add new logic interval to frames
+        Saig_BmcInterval( p );
+//        Saig_BmcAddTargetsAsPos( p );
+        if ( Vec_PtrSize(p->vTargets) == 0 )
+            break;
+        // convert logic slice into new AIG
+        pNew = Saig_BmcIntervalToAig( p );
+//printf( "StitchVars = %d.\n", p->nStitchVars );
+        // derive CNF for the new AIG
+        pCnf = Cnf_Derive( pNew, Aig_ManCoNum(pNew) );
+        Cnf_DataLift( pCnf, p->nSatVars );
+        p->nSatVars += pCnf->nVars;
+        // add this CNF to the solver
+        Saig_BmcLoadCnf( p, pCnf );
+        Cnf_DataFree( pCnf );
+        Aig_ManStop( pNew );
+        // solve the targets
+        RetValue = Saig_BmcSolveTargets( p, nStart, &nOutsSolved );
+        if ( fVerbose )
+        {
+            printf( "%4d : F =%5d. O =%4d.  And =%8d. Var =%8d. Conf =%7d. ", 
+                Iter, p->iFrameLast, p->iOutputLast, Aig_ManNodeNum(p->pFrm), p->nSatVars, (int)p->pSat->stats.conflicts );   
+            printf( "%4.0f MB",     4.0*(p->iFrameLast+1)*p->nObjs/(1<<20) );
+            printf( "%9.2f sec", (float)(Abc_Clock() - clkTotal)/(float)(CLOCKS_PER_SEC) );
+            printf( "\n" );
+            fflush( stdout );
+        }
+        if ( RetValue != l_False )
+            break;
+        // check the timeout
+        if ( nTimeOut && Abc_Clock() > nTimeToStop )
+        {
+            if ( !fSilent )
+                printf( "Reached timeout (%d seconds).\n",  nTimeOut );
+            if ( piFrames )
+                *piFrames = p->iFrameLast-1;
+            Saig_BmcManStop( p );
+            return Status;
+        }
+    }
+    if ( RetValue == l_True )
+    {
+        assert( p->iFrameFail * Saig_ManPoNum(p->pAig) + p->iOutputFail + 1 == nOutsSolved );
+        if ( !fSilent )
+            Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", 
+                p->iOutputFail, p->pAig->pName, p->iFrameFail );
+        Status = 0;
+        if ( piFrames )
+            *piFrames = p->iFrameFail - 1;
+    }
+    else // if ( RetValue == l_False || RetValue == l_Undef )
+    {
+        if ( !fSilent )
+            Abc_Print( 1, "No output failed in %d frames.  ", Abc_MaxInt(p->iFramePrev-1, 0) );
+        if ( piFrames )
+        {
+            if ( p->iOutputLast > 0 )
+                *piFrames = p->iFramePrev - 2;
+            else
+                *piFrames = p->iFramePrev - 1;
+        }
+    }
+    if ( !fSilent )
+    {
+        if ( fVerbOverwrite )
+        {
+            ABC_PRTr( "Time", Abc_Clock() - clk );
+        }
+        else
+        {
+            ABC_PRT( "Time", Abc_Clock() - clk );
+        }
+        if ( RetValue != l_True )
+        {
+            if ( p->iFrameLast >= p->nFramesMax )
+                printf( "Reached limit on the number of timeframes (%d).\n", p->nFramesMax );
+            else if ( p->nConfMaxAll && p->pSat->stats.conflicts > p->nConfMaxAll )
+                printf( "Reached global conflict limit (%d).\n", p->nConfMaxAll );
+            else if ( nTimeOut && Abc_Clock() > nTimeToStop )
+                printf( "Reached timeout (%d seconds).\n", nTimeOut );
+            else
+                printf( "Reached local conflict limit (%d).\n", p->nConfMaxOne );
+        }
+    }
+    Saig_BmcManStop( p );
+    fflush( stdout );
+    return Status;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcBmc3.c b/abc-build/src/sat/bmc/bmcBmc3.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcBmc3.c
@@ -0,0 +1,1758 @@
+/**CFile****************************************************************
+
+  FileName    [bmcBmc3.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    [Simple BMC package.]
+
+  Author      [Alan Mishchenko in collaboration with Niklas Een.]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcBmc3.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "proof/fra/fra.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satStore.h"
+#include "misc/vec/vecHsh.h"
+#include "misc/vec/vecWec.h"
+#include "bmc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Gia_ManBmc_t_ Gia_ManBmc_t;
+struct Gia_ManBmc_t_
+{
+    // input/output data
+    Saig_ParBmc_t *   pPars;       // parameters
+    Aig_Man_t *       pAig;        // user AIG
+    Vec_Ptr_t *       vCexes;      // counter-examples
+    // intermediate data
+    Vec_Int_t *       vMapping;    // mapping
+    Vec_Int_t *       vMapRefs;    // mapping references
+//    Vec_Vec_t *       vSects;      // sections
+    Vec_Int_t *       vId2Num;     // number of each node 
+    Vec_Ptr_t *       vTerInfo;    // ternary information
+    Vec_Ptr_t *       vId2Var;     // SAT vars for each object
+    Vec_Wec_t *       vVisited;    // visited nodes
+    abctime *         pTime4Outs;  // timeout per output
+    // hash table
+    Vec_Int_t *       vData;       // storage for cuts
+    Hsh_IntMan_t *    vHash;       // hash table
+    Vec_Int_t *       vId2Lit;     // mapping cuts into literals
+    int               nHashHit;    // hash table hits
+    int               nHashMiss;   // hash table misses
+    int               nBufNum;     // the number of simple nodes
+    int               nDupNum;     // the number of simple nodes
+    int               nUniProps;   // propagating learned clause values
+    int               nLitUsed;    // used literals
+    int               nLitUseless; // useless literals
+    // SAT solver
+    sat_solver *      pSat;        // SAT solver
+    int               nSatVars;    // SAT variables
+    int               nObjNums;    // SAT objects
+    int               nWordNum;    // unsigned words for ternary simulation
+    char * pSopSizes, ** pSops;    // CNF representation
+};
+
+extern int Gia_ManToBridgeResult( FILE * pFile, int Result, Abc_Cex_t * pCex, int iPoProved );
+
+void Gia_ManReportProgress( FILE * pFile, int prop_no, int depth )
+{
+    extern int Gia_ManToBridgeProgress( FILE * pFile, int Size, unsigned char * pBuffer );
+    char buf[100];
+    sprintf(buf, "property: safe<%d>\nbug-free-depth: %d\n", prop_no, depth);
+    Gia_ManToBridgeProgress(pFile, strlen(buf), (unsigned char *)buf);
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+#define SAIG_TER_NON 0
+#define SAIG_TER_ZER 1
+#define SAIG_TER_ONE 2
+#define SAIG_TER_UND 3
+
+static inline int Saig_ManBmcSimInfoNot( int Value )
+{
+    if ( Value == SAIG_TER_ZER )
+        return SAIG_TER_ONE;
+    if ( Value == SAIG_TER_ONE )
+        return SAIG_TER_ZER;
+    return SAIG_TER_UND;
+}
+
+static inline int Saig_ManBmcSimInfoAnd( int Value0, int Value1 )
+{
+    if ( Value0 == SAIG_TER_ZER || Value1 == SAIG_TER_ZER )
+        return SAIG_TER_ZER;
+    if ( Value0 == SAIG_TER_ONE && Value1 == SAIG_TER_ONE )
+        return SAIG_TER_ONE;
+    return SAIG_TER_UND;
+}
+
+static inline int Saig_ManBmcSimInfoGet( unsigned * pInfo, Aig_Obj_t * pObj )
+{
+    return 3 & (pInfo[Aig_ObjId(pObj) >> 4] >> ((Aig_ObjId(pObj) & 15) << 1));
+}
+
+static inline void Saig_ManBmcSimInfoSet( unsigned * pInfo, Aig_Obj_t * pObj, int Value )
+{
+    assert( Value >= SAIG_TER_ZER && Value <= SAIG_TER_UND );
+    Value ^= Saig_ManBmcSimInfoGet( pInfo, pObj );
+    pInfo[Aig_ObjId(pObj) >> 4] ^= (Value << ((Aig_ObjId(pObj) & 15) << 1));
+}
+
+static inline int Saig_ManBmcSimInfoClear( unsigned * pInfo, Aig_Obj_t * pObj )
+{
+    int Value = Saig_ManBmcSimInfoGet( pInfo, pObj );
+    pInfo[Aig_ObjId(pObj) >> 4] ^= (Value << ((Aig_ObjId(pObj) & 15) << 1));
+    return Value;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of LIs with binary ternary info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManBmcTerSimCount01( Aig_Man_t * p, unsigned * pInfo )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    if ( pInfo == NULL )
+        return Saig_ManRegNum(p);
+    Saig_ManForEachLi( p, pObj, i )
+        if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) )
+            Counter += (Saig_ManBmcSimInfoGet(pInfo, pObj) != SAIG_TER_UND);
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs ternary simulation of one frame.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned * Saig_ManBmcTerSimOne( Aig_Man_t * p, unsigned * pPrev )
+{
+    Aig_Obj_t * pObj, * pObjLi;
+    unsigned * pInfo;
+    int i, Val0, Val1;
+    pInfo = ABC_CALLOC( unsigned, Abc_BitWordNum(2 * Aig_ManObjNumMax(p)) );
+    Saig_ManBmcSimInfoSet( pInfo, Aig_ManConst1(p), SAIG_TER_ONE );
+    Saig_ManForEachPi( p, pObj, i )
+        Saig_ManBmcSimInfoSet( pInfo, pObj, SAIG_TER_UND );
+    if ( pPrev == NULL )
+    {
+        Saig_ManForEachLo( p, pObj, i )
+            Saig_ManBmcSimInfoSet( pInfo, pObj, SAIG_TER_ZER );
+    }
+    else
+    {
+        Saig_ManForEachLiLo( p, pObjLi, pObj, i )
+            Saig_ManBmcSimInfoSet( pInfo, pObj, Saig_ManBmcSimInfoGet(pPrev, pObjLi) );
+    }
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        Val0 = Saig_ManBmcSimInfoGet( pInfo, Aig_ObjFanin0(pObj) );
+        Val1 = Saig_ManBmcSimInfoGet( pInfo, Aig_ObjFanin1(pObj) );
+        if ( Aig_ObjFaninC0(pObj) )
+            Val0 = Saig_ManBmcSimInfoNot( Val0 );
+        if ( Aig_ObjFaninC1(pObj) )
+            Val1 = Saig_ManBmcSimInfoNot( Val1 );
+        Saig_ManBmcSimInfoSet( pInfo, pObj, Saig_ManBmcSimInfoAnd(Val0, Val1) );
+    }
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        Val0 = Saig_ManBmcSimInfoGet( pInfo, Aig_ObjFanin0(pObj) );
+        if ( Aig_ObjFaninC0(pObj) )
+            Val0 = Saig_ManBmcSimInfoNot( Val0 );
+        Saig_ManBmcSimInfoSet( pInfo, pObj, Val0 );
+    }
+    return pInfo;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes and PIs in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_ManBmcTerSim( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vInfos;
+    unsigned * pInfo = NULL;
+    int i, TerPrev = ABC_INFINITY, TerCur, CountIncrease = 0;
+    vInfos = Vec_PtrAlloc( 100 );
+    for ( i = 0; i < 1000 && CountIncrease < 5 && TerPrev > 0; i++ )
+    {
+        TerCur = Saig_ManBmcTerSimCount01( p, pInfo );
+        if ( TerCur >= TerPrev )
+            CountIncrease++;
+        TerPrev = TerCur;
+        pInfo = Saig_ManBmcTerSimOne( p, pInfo );
+        Vec_PtrPush( vInfos, pInfo );
+    }
+    return vInfos;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManBmcTerSimTest( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vInfos;
+    unsigned * pInfo;
+    int i;
+    vInfos = Saig_ManBmcTerSim( p );
+    Vec_PtrForEachEntry( unsigned *, vInfos, pInfo, i )
+        Abc_Print( 1, "%d=%d ", i, Saig_ManBmcTerSimCount01(p, pInfo) );
+    Abc_Print( 1, "\n" );
+    Vec_PtrFreeFree( vInfos );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Count the number of non-ternary per frame.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManBmcCountNonternary_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vInfos, unsigned * pInfo, int f, int * pCounter )
+{ 
+    int Value = Saig_ManBmcSimInfoClear( pInfo, pObj );
+    if ( Value == SAIG_TER_NON )
+        return 0;
+    assert( f >= 0 );
+    pCounter[f] += (Value == SAIG_TER_UND);
+    if ( Saig_ObjIsPi(p, pObj) || (f == 0 && Saig_ObjIsLo(p, pObj)) || Aig_ObjIsConst1(pObj) )
+        return 0;
+    if ( Saig_ObjIsLi(p, pObj) )
+        return Saig_ManBmcCountNonternary_rec( p, Aig_ObjFanin0(pObj), vInfos, pInfo, f, pCounter );
+    if ( Saig_ObjIsLo(p, pObj) )
+        return Saig_ManBmcCountNonternary_rec( p, Saig_ObjLoToLi(p, pObj), vInfos, (unsigned *)Vec_PtrEntry(vInfos, f-1), f-1, pCounter );
+    assert( Aig_ObjIsNode(pObj) );
+    Saig_ManBmcCountNonternary_rec( p, Aig_ObjFanin0(pObj), vInfos, pInfo, f, pCounter );
+    Saig_ManBmcCountNonternary_rec( p, Aig_ObjFanin1(pObj), vInfos, pInfo, f, pCounter );
+    return 0;
+}
+void Saig_ManBmcCountNonternary( Aig_Man_t * p, Vec_Ptr_t * vInfos, int iFrame )
+{
+    int i, * pCounters = ABC_CALLOC( int, iFrame + 1 );
+    unsigned * pInfo = (unsigned *)Vec_PtrEntry(vInfos, iFrame);
+    assert( Saig_ManBmcSimInfoGet( pInfo, Aig_ManCo(p, 0) ) == SAIG_TER_UND );
+    Saig_ManBmcCountNonternary_rec( p, Aig_ObjFanin0(Aig_ManCo(p, 0)), vInfos, pInfo, iFrame, pCounters );
+    for ( i = 0; i <= iFrame; i++ )
+        Abc_Print( 1, "%d=%d ", i, pCounters[i] );
+    Abc_Print( 1, "\n" );
+    ABC_FREE( pCounters );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of POs with binary ternary info.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManBmcTerSimCount01Po( Aig_Man_t * p, unsigned * pInfo )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    Saig_ManForEachPo( p, pObj, i )
+        Counter += (Saig_ManBmcSimInfoGet(pInfo, pObj) != SAIG_TER_UND);
+    return Counter;
+}
+Vec_Ptr_t * Saig_ManBmcTerSimPo( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vInfos;
+    unsigned * pInfo = NULL;
+    int i, nPoBin;
+    vInfos = Vec_PtrAlloc( 100 );
+    for ( i = 0; ; i++ )
+    {
+        if ( i % 100 == 0 )
+            Abc_Print( 1, "Frame %5d\n", i );
+        pInfo = Saig_ManBmcTerSimOne( p, pInfo );
+        Vec_PtrPush( vInfos, pInfo );
+        nPoBin = Saig_ManBmcTerSimCount01Po( p, pInfo );
+        if ( nPoBin < Saig_ManPoNum(p) )
+            break;
+    }
+    Abc_Print( 1, "Detected terminary PO in frame %d.\n", i );
+    Saig_ManBmcCountNonternary( p, vInfos, i );
+    return vInfos;
+}
+void Saig_ManBmcTerSimTestPo( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vInfos;
+    vInfos = Saig_ManBmcTerSimPo( p );
+    Vec_PtrFreeFree( vInfos );
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManBmcDfs_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    assert( !Aig_IsComplement(pObj) );
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Aig_ObjIsNode(pObj) )
+    {
+        Saig_ManBmcDfs_rec( p, Aig_ObjFanin0(pObj), vNodes );
+        Saig_ManBmcDfs_rec( p, Aig_ObjFanin1(pObj), vNodes );
+    }
+    Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects internal nodes and PIs in the DFS order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_ManBmcDfsNodes( Aig_Man_t * p, Vec_Ptr_t * vRoots )
+{
+    Vec_Ptr_t * vNodes;
+    Aig_Obj_t * pObj;
+    int i;
+    vNodes = Vec_PtrAlloc( 100 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i )
+        Saig_ManBmcDfs_rec( p, Aig_ObjFanin0(pObj), vNodes );
+    return vNodes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Saig_ManBmcSections( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vSects, * vRoots, * vCone;
+    Aig_Obj_t * pObj, * pObjPo;
+    int i;
+    Aig_ManIncrementTravId( p );
+    Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
+    // start the roots
+    vRoots = Vec_PtrAlloc( 1000 );
+    Saig_ManForEachPo( p, pObjPo, i )
+    {
+        Aig_ObjSetTravIdCurrent( p, pObjPo );
+        Vec_PtrPush( vRoots, pObjPo );
+    }
+    // compute the cones
+    vSects = Vec_PtrAlloc( 20 );
+    while ( Vec_PtrSize(vRoots) > 0 )
+    {
+        vCone = Saig_ManBmcDfsNodes( p, vRoots );
+        Vec_PtrPush( vSects, vCone );
+        // get the next set of roots
+        Vec_PtrClear( vRoots );
+        Vec_PtrForEachEntry( Aig_Obj_t *, vCone, pObj, i )
+        {
+            if ( !Saig_ObjIsLo(p, pObj) )
+                continue;
+            pObjPo = Saig_ObjLoToLi( p, pObj );
+            if ( Aig_ObjIsTravIdCurrent(p, pObjPo) )
+                continue;
+            Aig_ObjSetTravIdCurrent( p, pObjPo );
+            Vec_PtrPush( vRoots, pObjPo );
+        }
+    }
+    Vec_PtrFree( vRoots );
+    return (Vec_Vec_t *)vSects;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManBmcSectionsTest( Aig_Man_t * p )
+{
+    Vec_Vec_t * vSects;
+    Vec_Ptr_t * vOne;
+    int i;
+    vSects = Saig_ManBmcSections( p );
+    Vec_VecForEachLevel( vSects, vOne, i )
+        Abc_Print( 1, "%d=%d ", i, Vec_PtrSize(vOne) );
+    Abc_Print( 1, "\n" );
+    Vec_VecFree( vSects );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManBmcSupergate_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper )
+{
+    // if the new node is complemented or a PI, another gate begins
+    if ( Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) ) // || (Aig_ObjRefs(pObj) > 1) )
+    {
+        Vec_PtrPushUnique( vSuper, Aig_Regular(pObj) );
+        return;
+    }
+    // go through the branches
+    Saig_ManBmcSupergate_rec( Aig_ObjChild0(pObj), vSuper );
+    Saig_ManBmcSupergate_rec( Aig_ObjChild1(pObj), vSuper );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collect the topmost supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_ManBmcSupergate( Aig_Man_t * p, int iPo )
+{
+    Vec_Ptr_t * vSuper;
+    Aig_Obj_t * pObj;
+    vSuper = Vec_PtrAlloc( 10 );
+    pObj = Aig_ManCo( p, iPo );
+    pObj = Aig_ObjChild0( pObj );
+    if ( !Aig_IsComplement(pObj) )
+    {
+        Vec_PtrPush( vSuper, pObj );
+        return vSuper;
+    }
+    pObj = Aig_Regular( pObj );
+    if ( !Aig_ObjIsNode(pObj) )
+    {
+        Vec_PtrPush( vSuper, pObj );
+        return vSuper;
+    }
+    Saig_ManBmcSupergate_rec( Aig_ObjChild0(pObj), vSuper );
+    Saig_ManBmcSupergate_rec( Aig_ObjChild1(pObj), vSuper );
+    return vSuper;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of nodes with ref counter more than 1.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManBmcCountRefed( Aig_Man_t * p, Vec_Ptr_t * vSuper )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pObj, i )
+    {
+        assert( !Aig_IsComplement(pObj) );
+        Counter += (Aig_ObjRefs(pObj) > 1);
+    }
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManBmcSupergateTest( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vSuper;
+    Aig_Obj_t * pObj;
+    int i;
+    Abc_Print( 1, "Supergates: " );
+    Saig_ManForEachPo( p, pObj, i )
+    {
+        vSuper = Saig_ManBmcSupergate( p, i );
+        Abc_Print( 1, "%d=%d(%d) ", i, Vec_PtrSize(vSuper), Saig_ManBmcCountRefed(p, vSuper) );
+        Vec_PtrFree( vSuper );
+    }
+    Abc_Print( 1, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManBmcWriteBlif( Aig_Man_t * p, Vec_Int_t * vMapping, char * pFileName )
+{
+    FILE * pFile;
+    char * pSopSizes, ** pSops;
+    Aig_Obj_t * pObj;
+    char Vals[4];
+    int i, k, b, iFan, iTruth, * pData;
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        Abc_Print( 1, "Cannot open file %s\n", pFileName );
+        return;
+    }
+    fprintf( pFile, ".model test\n" );
+    fprintf( pFile, ".inputs" );
+    Aig_ManForEachCi( p, pObj, i )
+        fprintf( pFile, " n%d", Aig_ObjId(pObj) );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, ".outputs" );
+    Aig_ManForEachCo( p, pObj, i )
+        fprintf( pFile, " n%d", Aig_ObjId(pObj) );
+    fprintf( pFile, "\n" );
+    fprintf( pFile, ".names" );
+    fprintf( pFile, " n%d\n", Aig_ObjId(Aig_ManConst1(p)) );
+    fprintf( pFile, " 1\n" );
+
+    Cnf_ReadMsops( &pSopSizes, &pSops );
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        if ( Vec_IntEntry(vMapping, i) == 0 )
+            continue;
+        pData = Vec_IntEntryP( vMapping, Vec_IntEntry(vMapping, i) );
+        fprintf( pFile, ".names" );
+        for ( iFan = 0; iFan < 4; iFan++ )
+            if ( pData[iFan+1] >= 0 )
+                fprintf( pFile, " n%d", pData[iFan+1] );
+            else
+                break;
+        fprintf( pFile, " n%d\n", i );
+        // write SOP
+        iTruth = pData[0] & 0xffff;
+        for ( k = 0; k < pSopSizes[iTruth]; k++ )
+        {
+            int Lit = pSops[iTruth][k];
+            for ( b = 3; b >= 0; b-- )
+            {
+                if ( Lit % 3 == 0 )
+                    Vals[b] = '0';
+                else if ( Lit % 3 == 1 )
+                    Vals[b] = '1';
+                else
+                    Vals[b] = '-';
+                Lit = Lit / 3;
+            }
+            for ( b = 0; b < iFan; b++ )
+                fprintf( pFile, "%c", Vals[b] );
+            fprintf( pFile, " 1\n" );
+        }
+    }
+    free( pSopSizes );
+    free( pSops[1] );
+    free( pSops );
+
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        fprintf( pFile, ".names" );
+        fprintf( pFile, " n%d", Aig_ObjId(Aig_ObjFanin0(pObj)) );
+        fprintf( pFile, " n%d\n", Aig_ObjId(pObj) );
+        fprintf( pFile, "%d 1\n", !Aig_ObjFaninC0(pObj) );
+    }
+    fprintf( pFile, ".end\n" );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManBmcMappingTest( Aig_Man_t * p )
+{
+    Vec_Int_t * vMapping;
+    vMapping = Cnf_DeriveMappingArray( p );
+    Saig_ManBmcWriteBlif( p, vMapping, "test.blif" );
+    Vec_IntFree( vMapping );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManBmcComputeMappingRefs( Aig_Man_t * p, Vec_Int_t * vMap )
+{
+    Vec_Int_t * vRefs;
+    Aig_Obj_t * pObj;
+    int i, iFan, * pData;
+    vRefs = Vec_IntStart( Aig_ManObjNumMax(p) );
+    Aig_ManForEachCo( p, pObj, i )
+        Vec_IntAddToEntry( vRefs, Aig_ObjFaninId0(pObj), 1 );
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        if ( Vec_IntEntry(vMap, i) == 0 )
+            continue;
+        pData = Vec_IntEntryP( vMap, Vec_IntEntry(vMap, i) );
+        for ( iFan = 0; iFan < 4; iFan++ )
+            if ( pData[iFan+1] >= 0 )
+                Vec_IntAddToEntry( vRefs, pData[iFan+1], 1 );
+    }
+    return vRefs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_ManBmc_t * Saig_Bmc3ManStart( Aig_Man_t * pAig, int nTimeOutOne )
+{
+    Gia_ManBmc_t * p;
+    Aig_Obj_t * pObj;
+    int i;
+//    assert( Aig_ManRegNum(pAig) > 0 );
+    p = ABC_CALLOC( Gia_ManBmc_t, 1 );
+    p->pAig = pAig;
+    // create mapping
+    p->vMapping = Cnf_DeriveMappingArray( pAig );
+    p->vMapRefs = Saig_ManBmcComputeMappingRefs( pAig, p->vMapping );
+    // create sections
+//    p->vSects = Saig_ManBmcSections( pAig );
+    // map object IDs into their numbers and section numbers
+    p->nObjNums = 0;
+    p->vId2Num  = Vec_IntStartFull( Aig_ManObjNumMax(pAig) );
+    Vec_IntWriteEntry( p->vId2Num,  Aig_ObjId(Aig_ManConst1(pAig)), p->nObjNums++ );
+    Aig_ManForEachCi( pAig, pObj, i )
+        Vec_IntWriteEntry( p->vId2Num,  Aig_ObjId(pObj), p->nObjNums++ );
+    Aig_ManForEachNode( pAig, pObj, i )
+        if ( Vec_IntEntry(p->vMapping, Aig_ObjId(pObj)) > 0 )
+            Vec_IntWriteEntry( p->vId2Num,  Aig_ObjId(pObj), p->nObjNums++ );
+    Aig_ManForEachCo( pAig, pObj, i )
+        Vec_IntWriteEntry( p->vId2Num,  Aig_ObjId(pObj), p->nObjNums++ );
+    p->vId2Var  = Vec_PtrAlloc( 100 );
+    p->vTerInfo = Vec_PtrAlloc( 100 );
+    p->vVisited = Vec_WecAlloc( 100 );
+    // create solver
+    p->nSatVars = 1;
+    p->pSat     = sat_solver_new();
+    sat_solver_setnvars( p->pSat, 1000 );
+    Cnf_ReadMsops( &p->pSopSizes, &p->pSops );
+    // terminary simulation 
+    p->nWordNum = Abc_BitWordNum( 2 * Aig_ManObjNumMax(pAig) );
+    // hash table
+    p->vData = Vec_IntAlloc( 5 * 10000 );
+    p->vHash = Hsh_IntManStart( p->vData, 5, 10000 );
+    p->vId2Lit = Vec_IntAlloc( 10000 );
+    // time spent on each outputs
+    if ( nTimeOutOne )
+    {
+        p->pTime4Outs = ABC_ALLOC( abctime, Saig_ManPoNum(pAig) );
+        for ( i = 0; i < Saig_ManPoNum(pAig); i++ )
+            p->pTime4Outs[i] = nTimeOutOne * CLOCKS_PER_SEC / 1000 + 1;
+    }
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Delete manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_Bmc3ManStop( Gia_ManBmc_t * p )
+{
+    if ( p->pPars->fVerbose )
+    {
+        int nUsedVars = sat_solver_count_usedvars(p->pSat);
+        Abc_Print( 1, "LStart(P) = %d  LDelta(Q) = %d  LRatio(R) = %d  ReduceDB = %d  Vars = %d  Used = %d (%.2f %%)\n", 
+            p->pSat->nLearntStart, p->pSat->nLearntDelta, p->pSat->nLearntRatio, 
+            p->pSat->nDBreduces, p->pSat->size, nUsedVars, 100.0*nUsedVars/p->pSat->size );
+        Abc_Print( 1, "Buffs = %d. Dups = %d.   Hash hits = %d.  Hash misses = %d.  UniProps = %d.\n", 
+            p->nBufNum, p->nDupNum, p->nHashHit, p->nHashMiss, p->nUniProps );
+    }
+//    Aig_ManCleanMarkA( p->pAig );
+    if ( p->vCexes )
+    {
+        assert( p->pAig->vSeqModelVec == NULL );
+        p->pAig->vSeqModelVec = p->vCexes;
+        p->vCexes = NULL;
+    }
+//    Vec_PtrFreeFree( p->vCexes );
+    Vec_WecFree( p->vVisited );
+    Vec_IntFree( p->vMapping );
+    Vec_IntFree( p->vMapRefs );
+//    Vec_VecFree( p->vSects );
+    Vec_IntFree( p->vId2Num );
+    Vec_VecFree( (Vec_Vec_t *)p->vId2Var );
+    Vec_PtrFreeFree( p->vTerInfo );
+    sat_solver_delete( p->pSat );
+    ABC_FREE( p->pTime4Outs );
+    Vec_IntFree( p->vData );
+    Hsh_IntManStop( p->vHash );
+    Vec_IntFree( p->vId2Lit );
+    ABC_FREE( p->pSopSizes );
+    ABC_FREE( p->pSops[1] );
+    ABC_FREE( p->pSops );
+    ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int * Saig_ManBmcMapping( Gia_ManBmc_t * p, Aig_Obj_t * pObj )
+{
+    if ( Vec_IntEntry(p->vMapping, Aig_ObjId(pObj)) == 0 )
+        return NULL;
+    return Vec_IntEntryP( p->vMapping, Vec_IntEntry(p->vMapping, Aig_ObjId(pObj)) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Saig_ManBmcLiteral( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame )
+{
+    Vec_Int_t * vFrame;
+    int ObjNum;
+    assert( !Aig_ObjIsNode(pObj) || Saig_ManBmcMapping(p, pObj) );
+    ObjNum  = Vec_IntEntry( p->vId2Num, Aig_ObjId(pObj) );
+    assert( ObjNum >= 0 );
+    vFrame  = (Vec_Int_t *)Vec_PtrEntry( p->vId2Var, iFrame );
+    assert( vFrame != NULL );
+    return Vec_IntEntry( vFrame, ObjNum );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Saig_ManBmcSetLiteral( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame, int iLit )
+{
+    Vec_Int_t * vFrame;
+    int ObjNum;
+    assert( !Aig_ObjIsNode(pObj) || Saig_ManBmcMapping(p, pObj) );
+    ObjNum  = Vec_IntEntry( p->vId2Num, Aig_ObjId(pObj) );
+    vFrame  = (Vec_Int_t *)Vec_PtrEntry( p->vId2Var, iFrame );
+    Vec_IntWriteEntry( vFrame, ObjNum, iLit );
+/*
+    if ( Vec_IntEntry( p->vMapRefs, Aig_ObjId(pObj) ) > 1 )
+        p->nLitUsed++;
+    else
+        p->nLitUseless++;
+*/
+    return iLit;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Saig_ManBmcCof0( int t, int v )
+{
+    static int s_Truth[4] = { 0xAAAA, 0xCCCC, 0xF0F0, 0xFF00 };
+    return 0xffff & ((t & ~s_Truth[v]) | ((t & ~s_Truth[v]) << (1<<v)));
+}
+static inline int Saig_ManBmcCof1( int t, int v )
+{
+    static int s_Truth[4] = { 0xAAAA, 0xCCCC, 0xF0F0, 0xFF00 };
+    return 0xffff & ((t & s_Truth[v]) | ((t & s_Truth[v]) >> (1<<v)));
+}
+static inline int Saig_ManBmcCofEqual( int t, int v )
+{
+    assert( v >= 0 && v <= 3 );
+    if ( v == 0 )
+        return ((t & 0xAAAA) >> 1) == (t & 0x5555);
+    if ( v == 1 )
+        return ((t & 0xCCCC) >> 2) == (t & 0x3333);
+    if ( v == 2 )
+        return ((t & 0xF0F0) >> 4) == (t & 0x0F0F);
+    if ( v == 3 )
+        return ((t & 0xFF00) >> 8) == (t & 0x00FF);
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CNF for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Saig_ManBmcReduceTruth( int uTruth, int Lits[] )
+{
+    int v;
+    for ( v = 0; v < 4; v++ )
+        if ( Lits[v] == 0 )
+        {
+            uTruth = Saig_ManBmcCof0(uTruth, v);
+            Lits[v] = -1;
+        }
+        else if ( Lits[v] == 1 )
+        {
+            uTruth = Saig_ManBmcCof1(uTruth, v);
+            Lits[v] = -1;
+        }
+    for ( v = 0; v < 4; v++ )
+        if ( Lits[v] == -1 )
+            assert( Saig_ManBmcCofEqual(uTruth, v) );
+        else if ( Saig_ManBmcCofEqual(uTruth, v) )
+            Lits[v] = -1;
+    return uTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CNF for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Saig_ManBmcAddClauses( Gia_ManBmc_t * p, int uTruth, int Lits[], int iLitOut )
+{
+    int i, k, b, CutLit, nClaLits, ClaLits[5];
+    assert( uTruth > 0 && uTruth < 0xffff );
+    // write positive/negative polarity
+    for ( i = 0; i < 2; i++ )
+    {
+        if ( i )
+            uTruth = 0xffff & ~uTruth;
+//        Extra_PrintBinary( stdout, &uTruth, 16 ); Abc_Print( 1, "\n" );
+        for ( k = 0; k < p->pSopSizes[uTruth]; k++ )
+        {
+            nClaLits = 0;
+            ClaLits[nClaLits++] = i ? lit_neg(iLitOut) : iLitOut;
+            CutLit = p->pSops[uTruth][k];
+            for ( b = 3; b >= 0; b-- )
+            {
+                if ( CutLit % 3 == 0 ) // value 0 --> write positive literal
+                {
+                    assert( Lits[b] > 1 );
+                    ClaLits[nClaLits++] = Lits[b];
+                }
+                else if ( CutLit % 3 == 1 ) // value 1 --> write negative literal
+                {
+                    assert( Lits[b] > 1 );
+                    ClaLits[nClaLits++] = lit_neg(Lits[b]);
+                }
+                CutLit = CutLit / 3;
+            }
+            if ( !sat_solver_addclause( p->pSat, ClaLits, ClaLits+nClaLits ) )
+                assert( 0 );
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CNF for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManBmcCreateCnf_rec( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame )
+{
+    extern unsigned Dar_CutSortVars( unsigned uTruth, int * pVars );
+    int * pMapping, i, iLit, Lits[5], uTruth;
+    iLit = Saig_ManBmcLiteral( p, pObj, iFrame );
+    if ( iLit != ~0 )
+        return iLit; 
+    assert( iFrame >= 0 );
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        if ( Saig_ObjIsPi(p->pAig, pObj) )
+            iLit = toLit( p->nSatVars++ );
+        else
+            iLit = Saig_ManBmcCreateCnf_rec( p, Saig_ObjLoToLi(p->pAig, pObj), iFrame-1 );
+        return Saig_ManBmcSetLiteral( p, pObj, iFrame, iLit );
+    }
+    if ( Aig_ObjIsCo(pObj) )
+    {
+        iLit = Saig_ManBmcCreateCnf_rec( p, Aig_ObjFanin0(pObj), iFrame );
+        if ( Aig_ObjFaninC0(pObj) )
+            iLit = lit_neg(iLit);
+        return Saig_ManBmcSetLiteral( p, pObj, iFrame, iLit );
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    pMapping = Saig_ManBmcMapping( p, pObj );
+    for ( i = 0; i < 4; i++ )
+        if ( pMapping[i+1] == -1 )
+            Lits[i] = -1;
+        else
+            Lits[i] = Saig_ManBmcCreateCnf_rec( p, Aig_ManObj(p->pAig, pMapping[i+1]), iFrame );
+    uTruth = 0xffff & (unsigned)pMapping[0];
+    // propagate constants
+    uTruth = Saig_ManBmcReduceTruth( uTruth, Lits );
+    if ( uTruth == 0 || uTruth == 0xffff )
+    {
+        iLit = (uTruth == 0xffff);
+        return Saig_ManBmcSetLiteral( p, pObj, iFrame, iLit );
+    }
+    // canonicize inputs
+    uTruth = Dar_CutSortVars( uTruth, Lits );
+    assert( uTruth != 0 && uTruth != 0xffff );
+    if ( uTruth == 0xAAAA || uTruth == 0x5555 )
+    {
+        iLit = Abc_LitNotCond( Lits[0], uTruth == 0x5555 );
+        p->nBufNum++;
+    }
+    else 
+    {
+        int iEntry, iRes;
+        int fCompl = (uTruth & 1);
+        Lits[4] = (uTruth & 1) ? 0xffff & ~uTruth : uTruth;
+        iEntry = Vec_IntSize(p->vData) / 5;
+        assert( iEntry * 5 == Vec_IntSize(p->vData) );
+        for ( i = 0; i < 5; i++ )
+            Vec_IntPush( p->vData, Lits[i] );
+        iRes = Hsh_IntManAdd( p->vHash, iEntry );
+        if ( iRes == iEntry )
+        {
+            iLit = toLit( p->nSatVars++ );
+            Saig_ManBmcAddClauses( p, Lits[4], Lits, iLit );
+            assert( iEntry == Vec_IntSize(p->vId2Lit) );
+            Vec_IntPush( p->vId2Lit, iLit );
+            p->nHashMiss++;
+        }
+        else
+        {
+            iLit = Vec_IntEntry( p->vId2Lit, iRes );
+            Vec_IntShrink( p->vData, Vec_IntSize(p->vData) - 5 );
+            p->nHashHit++;
+        }
+        iLit = Abc_LitNotCond( iLit, fCompl );
+    }
+    return Saig_ManBmcSetLiteral( p, pObj, iFrame, iLit );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CNF for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManBmcCreateCnf_iter( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame, Vec_Int_t * vVisit )
+{
+    if ( Saig_ManBmcLiteral( p, pObj, iFrame ) != ~0 )
+        return; 
+    if ( Aig_ObjIsTravIdCurrent(p->pAig, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p->pAig, pObj);
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        if ( Saig_ObjIsLo(p->pAig, pObj) )
+            Vec_IntPush( vVisit, Saig_ObjLoToLi(p->pAig, pObj)->Id );
+        return;
+    }
+    if ( Aig_ObjIsCo(pObj) )
+    {
+        Saig_ManBmcCreateCnf_iter( p, Aig_ObjFanin0(pObj), iFrame, vVisit );
+        return;
+    }
+    else
+    {
+        int * pMapping, i;
+        assert( Aig_ObjIsNode(pObj) );
+        pMapping = Saig_ManBmcMapping( p, pObj );
+        for ( i = 0; i < 4; i++ )
+            if ( pMapping[i+1] != -1 )
+                Saig_ManBmcCreateCnf_iter( p, Aig_ManObj(p->pAig, pMapping[i+1]), iFrame, vVisit );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively performs terminary simulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManBmcRunTerSim_rec( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame )
+{
+    unsigned * pInfo = (unsigned *)Vec_PtrEntry( p->vTerInfo, iFrame );
+    int Val0, Val1, Value = Saig_ManBmcSimInfoGet( pInfo, pObj );
+    if ( Value != SAIG_TER_NON )
+    {
+/*
+        // check the value of this literal in the SAT solver
+        if ( Value == SAIG_TER_UND && Saig_ManBmcMapping(p, pObj) )
+        {
+            int Lit = Saig_ManBmcLiteral( p, pObj, iFrame );
+            if ( Lit >= 0  )
+            {
+                assert( Lit >= 2 );
+                if ( p->pSat->assigns[Abc_Lit2Var(Lit)] < 2 )
+                {
+                    p->nUniProps++;
+                    if ( Abc_LitIsCompl(Lit) ^ (p->pSat->assigns[Abc_Lit2Var(Lit)] == 0) )
+                        Value = SAIG_TER_ONE;
+                    else
+                        Value = SAIG_TER_ZER;
+
+//                    Value = SAIG_TER_UND;  // disable!
+
+                    // use the new value
+                    Saig_ManBmcSimInfoSet( pInfo, pObj, Value );
+                    // transfer to the unrolling
+                    if ( Value != SAIG_TER_UND )
+                        Saig_ManBmcSetLiteral( p, pObj, iFrame, (int)(Value == SAIG_TER_ONE) );
+                }
+            }
+        }
+*/
+        return Value;
+    }
+    if ( Aig_ObjIsCo(pObj) )
+    {
+        Value = Saig_ManBmcRunTerSim_rec( p, Aig_ObjFanin0(pObj), iFrame );
+        if ( Aig_ObjFaninC0(pObj) )
+            Value = Saig_ManBmcSimInfoNot( Value );
+    }
+    else if ( Saig_ObjIsLo(p->pAig, pObj) )
+    {
+        assert( iFrame > 0 );
+        Value = Saig_ManBmcRunTerSim_rec( p, Saig_ObjLoToLi(p->pAig, pObj), iFrame - 1 );
+    }
+    else if ( Aig_ObjIsNode(pObj) )
+    {
+        Val0 = Saig_ManBmcRunTerSim_rec( p, Aig_ObjFanin0(pObj), iFrame  );
+        Val1 = Saig_ManBmcRunTerSim_rec( p, Aig_ObjFanin1(pObj), iFrame  );
+        if ( Aig_ObjFaninC0(pObj) )
+            Val0 = Saig_ManBmcSimInfoNot( Val0 );
+        if ( Aig_ObjFaninC1(pObj) )
+            Val1 = Saig_ManBmcSimInfoNot( Val1 );
+        Value = Saig_ManBmcSimInfoAnd( Val0, Val1 );
+    }
+    else assert( 0 );
+    Saig_ManBmcSimInfoSet( pInfo, pObj, Value );
+    // transfer to the unrolling
+    if ( Saig_ManBmcMapping(p, pObj) && Value != SAIG_TER_UND )
+        Saig_ManBmcSetLiteral( p, pObj, iFrame, (int)(Value == SAIG_TER_ONE) );
+    return Value;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CNF for one node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManBmcCreateCnf( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame )
+{
+    Vec_Int_t * vVisit, * vVisit2;
+    Aig_Obj_t * pTemp;
+    int Lit, f, i;
+    // perform ternary simulation
+    int Value = Saig_ManBmcRunTerSim_rec( p, pObj, iFrame );
+    if ( Value != SAIG_TER_UND )
+        return (int)(Value == SAIG_TER_ONE);
+    // construct CNF if value is ternary
+//    Lit = Saig_ManBmcCreateCnf_rec( p, pObj, iFrame );
+    Vec_WecClear( p->vVisited );
+    vVisit = Vec_WecPushLevel( p->vVisited );
+    Vec_IntPush( vVisit, Aig_ObjId(pObj) );
+    for ( f = iFrame; f >= 0; f-- )
+    {
+        Aig_ManIncrementTravId( p->pAig );
+        vVisit2 = Vec_WecPushLevel( p->vVisited );
+        vVisit = Vec_WecEntry( p->vVisited, Vec_WecSize(p->vVisited)-2 );
+        Aig_ManForEachObjVec( vVisit, p->pAig, pTemp, i )
+            Saig_ManBmcCreateCnf_iter( p, pTemp, f, vVisit2 );
+        if ( Vec_IntSize(vVisit2) == 0 )
+            break;
+    }
+    Vec_WecForEachLevelReverse( p->vVisited, vVisit, f )
+        Aig_ManForEachObjVec( vVisit, p->pAig, pTemp, i )
+            Saig_ManBmcCreateCnf_rec( p, pTemp, iFrame-f );
+    Lit = Saig_ManBmcLiteral( p, pObj, iFrame );
+    // extend the SAT solver
+    if ( p->nSatVars > sat_solver_nvars(p->pSat) )
+        sat_solver_setnvars( p->pSat, p->nSatVars );
+    return Lit;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Procedure used for sorting the nodes in decreasing order of levels.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_NodeCompareRefsIncrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 )
+{
+    int Diff = Aig_ObjRefs(*pp1) - Aig_ObjRefs(*pp2);
+    if ( Diff < 0 )
+        return -1;
+    if ( Diff > 0 ) 
+        return 1;
+    Diff = Aig_ObjId(*pp1) - Aig_ObjId(*pp2);
+    if ( Diff < 0 )
+        return -1;
+    if ( Diff > 0 ) 
+        return 1;
+    return 0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ParBmcSetDefaultParams( Saig_ParBmc_t * p )
+{
+    memset( p, 0, sizeof(Saig_ParBmc_t) );
+    p->nStart         =     0;    // maximum number of timeframes 
+    p->nFramesMax     =     0;    // maximum number of timeframes 
+    p->nConfLimit     =     0;    // maximum number of conflicts at a node
+    p->nConfLimitJump =     0;    // maximum number of conflicts after jumping
+    p->nFramesJump    =     0;    // the number of tiemframes to jump
+    p->nTimeOut       =     0;    // approximate timeout in seconds
+    p->nTimeOutGap    =     0;    // time since the last CEX found
+    p->nPisAbstract   =     0;    // the number of PIs to abstract
+    p->fSolveAll      =     0;    // stops on the first SAT instance
+    p->fDropSatOuts   =     0;    // replace sat outputs by constant 0
+    p->nLearnedStart  = 10000;    // starting learned clause limit
+    p->nLearnedDelta  =  2000;    // delta of learned clause limit
+    p->nLearnedPerce  =    80;    // ratio of learned clause limit
+    p->fVerbose       =     0;    // verbose 
+    p->fNotVerbose    =     0;    // skip line-by-line print-out 
+    p->iFrame         =    -1;    // explored up to this frame
+    p->nFailOuts      =     0;    // the number of failed outputs
+    p->nDropOuts      =     0;    // the number of timed out outputs
+    p->timeLastSolved =     0;    // time when the last one was solved
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns time to stop.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+abctime Saig_ManBmcTimeToStop( Saig_ParBmc_t * pPars, abctime nTimeToStopNG )
+{
+    abctime nTimeToStopGap = pPars->nTimeOutGap ? pPars->nTimeOutGap * CLOCKS_PER_SEC + Abc_Clock(): 0;
+    abctime nTimeToStop = 0;
+    if ( nTimeToStopNG && nTimeToStopGap )
+        nTimeToStop = nTimeToStopNG < nTimeToStopGap ? nTimeToStopNG : nTimeToStopGap;
+    else if ( nTimeToStopNG )
+        nTimeToStop = nTimeToStopNG;
+    else if ( nTimeToStopGap )
+        nTimeToStop = nTimeToStopGap;
+    return nTimeToStop;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Saig_ManGenerateCex( Gia_ManBmc_t * p, int f, int i )
+{
+    Aig_Obj_t * pObjPi;
+    Abc_Cex_t * pCex = Abc_CexMakeTriv( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Saig_ManPoNum(p->pAig), f*Saig_ManPoNum(p->pAig)+i );
+    int j, k, iBit = Saig_ManRegNum(p->pAig);
+    for ( j = 0; j <= f; j++, iBit += Saig_ManPiNum(p->pAig) )
+        Saig_ManForEachPi( p->pAig, pObjPi, k )
+        {
+            int iLit = Saig_ManBmcLiteral( p, pObjPi, j );
+            if ( iLit != ~0 && sat_solver_var_value(p->pSat, lit_var(iLit)) )
+                Abc_InfoSetBit( pCex->pData, iBit + k );
+        }
+    return pCex;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManCallSolver( Gia_ManBmc_t * p, int Lit )
+{
+    if ( Lit == 0 )
+        return l_False;
+    if ( Lit == 1 )
+        return l_True;
+    return sat_solver_solve( p->pSat, &Lit, &Lit + 1, (ABC_INT64_T)p->pPars->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Bounded model checking engine.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Saig_ManBmcScalable( Aig_Man_t * pAig, Saig_ParBmc_t * pPars )
+{
+    Gia_ManBmc_t * p;
+    Aig_Obj_t * pObj;
+    Abc_Cex_t * pCexNew, * pCexNew0;
+    FILE * pLogFile = NULL;
+    unsigned * pInfo;
+    int RetValue = -1, fFirst = 1, nJumpFrame = 0, fUnfinished = 0;
+    int nOutDigits = Abc_Base10Log( Saig_ManPoNum(pAig) );
+    int i, f, k, Lit, status;
+    abctime clk, clk2, clkSatRun, clkOther = 0, clkTotal = Abc_Clock();
+    abctime nTimeUnsat = 0, nTimeSat = 0, nTimeUndec = 0, clkOne = 0;
+    abctime nTimeToStopNG, nTimeToStop;
+    if ( pPars->pLogFileName )
+        pLogFile = fopen( pPars->pLogFileName, "wb" );
+    if ( pPars->nTimeOutOne && pPars->nTimeOut == 0 )
+        pPars->nTimeOut = pPars->nTimeOutOne * Saig_ManPoNum(pAig) / 1000 + 1;
+    if ( pPars->nTimeOutOne && !pPars->fSolveAll )
+        pPars->nTimeOutOne = 0;
+    nTimeToStopNG = pPars->nTimeOut ? pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0;
+    nTimeToStop   = Saig_ManBmcTimeToStop( pPars, nTimeToStopNG );
+    // create BMC manager
+    p = Saig_Bmc3ManStart( pAig, pPars->nTimeOutOne );
+    p->pPars = pPars;
+    p->pSat->nLearntStart = p->pPars->nLearnedStart;
+    p->pSat->nLearntDelta = p->pPars->nLearnedDelta;
+    p->pSat->nLearntRatio = p->pPars->nLearnedPerce;
+    p->pSat->nLearntMax   = p->pSat->nLearntStart;
+    if ( pPars->fSolveAll && p->vCexes == NULL )
+        p->vCexes = Vec_PtrStart( Saig_ManPoNum(pAig) );
+    if ( pPars->fVerbose )
+    {
+        Abc_Print( 1, "Running \"bmc3\". PI/PO/Reg = %d/%d/%d. And =%7d. Lev =%6d. ObjNums =%6d.\n",// Sect =%3d.\n", 
+            Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig),
+            Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig), p->nObjNums );//, Vec_VecSize(p->vSects) );
+        Abc_Print( 1, "Params: FramesMax = %d. Start = %d. ConfLimit = %d. TimeOut = %d. SolveAll = %d.\n", 
+            pPars->nFramesMax, pPars->nStart, pPars->nConfLimit, pPars->nTimeOut, pPars->fSolveAll );
+    } 
+    pPars->nFramesMax = pPars->nFramesMax ? pPars->nFramesMax : ABC_INFINITY;
+    // set runtime limit
+    if ( nTimeToStop )
+        sat_solver_set_runtime_limit( p->pSat, nTimeToStop );
+    // perform frames
+    Aig_ManRandom( 1 );
+    pPars->timeLastSolved = Abc_Clock();
+    for ( f = 0; f < pPars->nFramesMax; f++ )
+    {
+        // stop BMC after exploring all reachable states
+        if ( !pPars->nFramesJump && Aig_ManRegNum(pAig) < 30 && f == (1 << Aig_ManRegNum(pAig)) )
+        {
+            Abc_Print( 1, "Stopping BMC because all 2^%d reachable states are visited.\n", Aig_ManRegNum(pAig) );
+            if ( p->pPars->fUseBridge )
+                Saig_ManForEachPo( pAig, pObj, i )
+                    if ( !(p->vCexes && Vec_PtrEntry(p->vCexes, i)) && !(p->pTime4Outs && p->pTime4Outs[i] == 0) ) // not SAT and not timed out
+                        Gia_ManToBridgeResult( stdout, 1, NULL, i );
+            RetValue = pPars->nFailOuts ? 0 : 1;
+            goto finish;
+        }
+        // stop BMC if all targets are solved
+        if ( pPars->fSolveAll && pPars->nFailOuts + pPars->nDropOuts >= Saig_ManPoNum(pAig) )
+        {
+            Abc_Print( 1, "Stopping BMC because all targets are disproved or timed out.\n" );
+            RetValue = pPars->nFailOuts ? 0 : 1;
+            goto finish;
+        }
+        // consider the next timeframe
+        if ( (RetValue == -1 || pPars->fSolveAll) && pPars->nStart == 0 && !nJumpFrame )
+            pPars->iFrame = f-1;
+        // map nodes of this section
+        Vec_PtrPush( p->vId2Var, Vec_IntStartFull(p->nObjNums) );
+        Vec_PtrPush( p->vTerInfo, (pInfo = ABC_CALLOC(unsigned, p->nWordNum)) );
+/*
+        // cannot remove mapping of frame values for any timeframes
+        // because with constant propagation they may be needed arbitrarily far
+        if ( f > 2*Vec_VecSize(p->vSects) )
+        {
+            int iFrameOld = f - 2*Vec_VecSize( p->vSects );
+            void * pMemory = Vec_IntReleaseArray( Vec_PtrEntry(p->vId2Var, iFrameOld) );
+            ABC_FREE( pMemory );
+        } 
+*/
+        // prepare some nodes
+        Saig_ManBmcSetLiteral( p, Aig_ManConst1(pAig), f, 1 );
+        Saig_ManBmcSimInfoSet( pInfo, Aig_ManConst1(pAig), SAIG_TER_ONE );
+        Saig_ManForEachPi( pAig, pObj, i )
+            Saig_ManBmcSimInfoSet( pInfo, pObj, SAIG_TER_UND );
+        if ( f == 0 )
+        {
+            Saig_ManForEachLo( p->pAig, pObj, i )
+            {
+                Saig_ManBmcSetLiteral( p, pObj, 0, 0 );
+                Saig_ManBmcSimInfoSet( pInfo, pObj, SAIG_TER_ZER );
+            }
+        }
+        if ( (pPars->nStart && f < pPars->nStart) || (nJumpFrame && f < nJumpFrame) )
+            continue;
+        // create CNF upfront
+        if ( pPars->fSolveAll )
+        {
+            Saig_ManForEachPo( pAig, pObj, i )
+            {
+                if ( i >= Saig_ManPoNum(pAig) )
+                    break;
+                // check for timeout
+                if ( pPars->nTimeOutGap && pPars->timeLastSolved && Abc_Clock() > pPars->timeLastSolved + pPars->nTimeOutGap * CLOCKS_PER_SEC )
+                {
+                    Abc_Print( 1, "Reached gap timeout (%d seconds).\n",  pPars->nTimeOutGap );
+                    goto finish;
+                }
+                if ( nTimeToStop && Abc_Clock() > nTimeToStop )
+                {
+                    if ( !pPars->fSilent )
+                        Abc_Print( 1, "Reached timeout (%d seconds).\n",  pPars->nTimeOut );
+                    goto finish;
+                }
+                // skip solved outputs
+                if ( p->vCexes && Vec_PtrEntry(p->vCexes, i) )
+                    continue;
+                // skip output whose time has run out
+                if ( p->pTime4Outs && p->pTime4Outs[i] == 0 )
+                    continue;
+                // add constraints for this output
+clk2 = Abc_Clock();
+                Saig_ManBmcCreateCnf( p, pObj, f );
+clkOther += Abc_Clock() - clk2;
+            }
+        }
+        // solve SAT
+        clk = Abc_Clock(); 
+        Saig_ManForEachPo( pAig, pObj, i )
+        {
+            if ( i >= Saig_ManPoNum(pAig) )
+                break;
+            // check for timeout
+            if ( pPars->nTimeOutGap && pPars->timeLastSolved && Abc_Clock() > pPars->timeLastSolved + pPars->nTimeOutGap * CLOCKS_PER_SEC )
+            {
+                Abc_Print( 1, "Reached gap timeout (%d seconds).\n",  pPars->nTimeOutGap );
+                goto finish;
+            }
+            if ( nTimeToStop && Abc_Clock() > nTimeToStop )
+            {
+                if ( !pPars->fSilent )
+                    Abc_Print( 1, "Reached timeout (%d seconds).\n",  pPars->nTimeOut );
+                goto finish;
+            }
+            // skip solved outputs
+            if ( p->vCexes && Vec_PtrEntry(p->vCexes, i) )
+                continue;
+            // skip output whose time has run out
+            if ( p->pTime4Outs && p->pTime4Outs[i] == 0 )
+                continue;
+            // add constraints for this output
+clk2 = Abc_Clock();
+            Lit = Saig_ManBmcCreateCnf( p, pObj, f );
+clkOther += Abc_Clock() - clk2;
+            // solve this output
+            fUnfinished = 0;
+            sat_solver_compress( p->pSat );
+            if ( p->pTime4Outs )
+            {
+                assert( p->pTime4Outs[i] > 0 );
+                clkOne = Abc_Clock();
+                sat_solver_set_runtime_limit( p->pSat, p->pTime4Outs[i] + Abc_Clock() );
+            }
+clk2 = Abc_Clock();
+            status = Saig_ManCallSolver( p, Lit );
+clkSatRun = Abc_Clock() - clk2;
+            if ( pLogFile )
+                fprintf( pLogFile, "Frame %5d  Output %5d  Time(ms) %8d %8d\n", f, i, 
+                    Lit < 2 ? 0 : (int)(clkSatRun * 1000 / CLOCKS_PER_SEC),
+                    Lit < 2 ? 0 : Abc_MaxInt(0, Abc_MinInt(pPars->nTimeOutOne, pPars->nTimeOutOne - (int)((p->pTime4Outs[i] - clkSatRun) * 1000 / CLOCKS_PER_SEC))) );
+            if ( p->pTime4Outs )
+            {
+                abctime timeSince = Abc_Clock() - clkOne;
+                assert( p->pTime4Outs[i] > 0 );
+                p->pTime4Outs[i] = (p->pTime4Outs[i] > timeSince) ? p->pTime4Outs[i] - timeSince : 0;
+                if ( p->pTime4Outs[i] == 0 && status != l_True )
+                    pPars->nDropOuts++;
+            }
+            if ( status == l_False )
+            {
+nTimeUnsat += clkSatRun;
+                if ( Lit != 0 )
+                {
+                    // add final unit clause
+                    Lit = lit_neg( Lit );
+                    status = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+                    assert( status );
+                    // add learned units
+                    for ( k = 0; k < veci_size(&p->pSat->unit_lits); k++ )
+                    {
+                        Lit = veci_begin(&p->pSat->unit_lits)[k];
+                        status = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+                        assert( status );
+                    }
+                    veci_resize(&p->pSat->unit_lits, 0);
+                    // propagate units
+                    sat_solver_compress( p->pSat );
+                }
+                if ( p->pPars->fUseBridge )
+                    Gia_ManReportProgress( stdout, i, f );
+            }
+            else if ( status == l_True )
+            {
+nTimeSat += clkSatRun;
+                RetValue = 0;
+                fFirst = 0;
+                if ( !pPars->fSolveAll )
+                {
+                    if ( pPars->fVerbose )
+                    {
+                        Abc_Print( 1, "%4d %s : ", f,  fUnfinished ? "-" : "+" );
+                        Abc_Print( 1, "Var =%8.0f. ",  (double)p->nSatVars );
+                        Abc_Print( 1, "Cla =%9.0f. ",  (double)p->pSat->stats.clauses );
+                        Abc_Print( 1, "Conf =%7.0f. ", (double)p->pSat->stats.conflicts );
+//                        Abc_Print( 1, "Imp =%10.0f. ", (double)p->pSat->stats.propagations );
+                        Abc_Print( 1, "Uni =%7.0f. ",(double)sat_solver_count_assigned(p->pSat) );
+//                        ABC_PRT( "Time", Abc_Clock() - clk );
+                        Abc_Print( 1, "%4.0f MB",      4.25*(f+1)*p->nObjNums /(1<<20) );
+                        Abc_Print( 1, "%4.0f MB",      1.0*sat_solver_memory(p->pSat)/(1<<20) );
+                        Abc_Print( 1, "%9.2f sec  ",   (float)(Abc_Clock() - clkTotal)/(float)(CLOCKS_PER_SEC) );
+//                        Abc_Print( 1, "\n" );
+//                        ABC_PRMn( "Id2Var", (f+1)*p->nObjNums*4 );
+//                        ABC_PRMn( "SAT", 42 * p->pSat->size + 16 * (int)p->pSat->stats.clauses + 4 * (int)p->pSat->stats.clauses_literals );
+//                        Abc_Print( 1, "S =%6d. ", p->nBufNum );
+//                        Abc_Print( 1, "D =%6d. ", p->nDupNum );
+                        Abc_Print( 1, "\n" );
+                        fflush( stdout );
+                    }
+                    ABC_FREE( pAig->pSeqModel );
+                    pAig->pSeqModel = Saig_ManGenerateCex( p, f, i );
+                    goto finish;
+                }
+                pPars->nFailOuts++;
+                if ( !pPars->fNotVerbose )
+                    Abc_Print( 1, "Output %*d was asserted in frame %2d (solved %*d out of %*d outputs).\n",  
+                        nOutDigits, i, f, nOutDigits, pPars->nFailOuts, nOutDigits, Saig_ManPoNum(pAig) );
+                if ( p->vCexes == NULL )
+                    p->vCexes = Vec_PtrStart( Saig_ManPoNum(pAig) );
+                pCexNew = (p->pPars->fUseBridge || pPars->fStoreCex) ? Saig_ManGenerateCex( p, f, i ) : (Abc_Cex_t *)(ABC_PTRINT_T)1;
+                pCexNew0 = NULL;
+                if ( p->pPars->fUseBridge )
+                {
+                    Gia_ManToBridgeResult( stdout, 0, pCexNew, pCexNew->iPo );
+                    //Abc_CexFree( pCexNew );
+                    pCexNew0 = pCexNew; 
+                    pCexNew = (Abc_Cex_t *)(ABC_PTRINT_T)1;
+                }
+                Vec_PtrWriteEntry( p->vCexes, i, pCexNew );
+                if ( pPars->pFuncOnFail && pPars->pFuncOnFail(i, pPars->fStoreCex ? (Abc_Cex_t *)Vec_PtrEntry(p->vCexes, i) : NULL) )
+                {
+                    Abc_CexFreeP( &pCexNew0 );
+                    Abc_Print( 1, "Quitting due to callback on fail.\n" );
+                    goto finish;
+                }
+                // reset the timeout
+                pPars->timeLastSolved = Abc_Clock();
+                nTimeToStop = Saig_ManBmcTimeToStop( pPars, nTimeToStopNG );
+                if ( nTimeToStop )
+                    sat_solver_set_runtime_limit( p->pSat, nTimeToStop );
+
+                // check if other outputs failed under the same counter-example
+                Saig_ManForEachPo( pAig, pObj, k )
+                {
+                    if ( k >= Saig_ManPoNum(pAig) )
+                        break;
+                    // skip solved outputs
+                    if ( p->vCexes && Vec_PtrEntry(p->vCexes, k) )
+                        continue;
+                    // check if this output is solved
+                    Lit = Saig_ManBmcCreateCnf( p, pObj, f );
+                    if ( sat_solver_var_value(p->pSat, lit_var(Lit)) == Abc_LitIsCompl(Lit) )
+                        continue;
+                    // write entry
+                    pPars->nFailOuts++;
+                    if ( !pPars->fNotVerbose )
+                        Abc_Print( 1, "Output %*d was asserted in frame %2d (solved %*d out of %*d outputs).\n",  
+                            nOutDigits, k, f, nOutDigits, pPars->nFailOuts, nOutDigits, Saig_ManPoNum(pAig) );
+                    // report to the bridge
+                    if ( p->pPars->fUseBridge )
+                    {
+                        // set the output number
+                        pCexNew0->iPo = k;
+                        Gia_ManToBridgeResult( stdout, 0, pCexNew0, pCexNew0->iPo );
+                    }
+                    // remember solved output
+                    Vec_PtrWriteEntry( p->vCexes, k, Abc_CexDup(pCexNew, Saig_ManRegNum(pAig)) );
+                }
+                Abc_CexFreeP( &pCexNew0 );
+                Abc_CexFree( pCexNew );
+            }
+            else 
+            {
+nTimeUndec += clkSatRun;
+                assert( status == l_Undef );
+                if ( pPars->nFramesJump )
+                {
+                    pPars->nConfLimit = pPars->nConfLimitJump;
+                    nJumpFrame = f + pPars->nFramesJump;
+                    fUnfinished = 1;
+                    break;
+                }
+                if ( p->pTime4Outs == NULL )
+                    goto finish;
+            }
+        }
+        if ( pPars->fVerbose ) 
+        {
+            if ( fFirst == 1 && f > 0 && p->pSat->stats.conflicts > 1 )
+            {
+                fFirst = 0;
+//                Abc_Print( 1, "Outputs of frames up to %d are trivially UNSAT.\n", f );
+            }
+            Abc_Print( 1, "%4d %s : ", f, fUnfinished ? "-" : "+" );
+            Abc_Print( 1, "Var =%8.0f. ", (double)p->nSatVars );
+//            Abc_Print( 1, "Used =%8.0f. ", (double)sat_solver_count_usedvars(p->pSat) );
+            Abc_Print( 1, "Cla =%9.0f. ", (double)p->pSat->stats.clauses );
+            Abc_Print( 1, "Conf =%7.0f. ",(double)p->pSat->stats.conflicts );
+//            Abc_Print( 1, "Imp =%10.0f. ", (double)p->pSat->stats.propagations );
+            Abc_Print( 1, "Uni =%7.0f. ",(double)sat_solver_count_assigned(p->pSat) );
+            if ( pPars->fSolveAll )
+                Abc_Print( 1, "CEX =%5d. ", pPars->nFailOuts );
+            if ( pPars->nTimeOutOne )
+                Abc_Print( 1, "T/O =%4d. ", pPars->nDropOuts );
+//            ABC_PRT( "Time", Abc_Clock() - clk );
+//            Abc_Print( 1, "%4.0f MB",     4.0*Vec_IntSize(p->vVisited) /(1<<20) );
+            Abc_Print( 1, "%4.0f MB",     4.0*(f+1)*p->nObjNums /(1<<20) );
+            Abc_Print( 1, "%4.0f MB",     1.0*sat_solver_memory(p->pSat)/(1<<20) );
+//            Abc_Print( 1, " %6d %6d ",   p->nLitUsed, p->nLitUseless );
+            Abc_Print( 1, "%9.2f sec ",  1.0*(Abc_Clock() - clkTotal)/CLOCKS_PER_SEC );
+//            Abc_Print( 1, "\n" );
+//            ABC_PRMn( "Id2Var", (f+1)*p->nObjNums*4 );
+//            ABC_PRMn( "SAT", 42 * p->pSat->size + 16 * (int)p->pSat->stats.clauses + 4 * (int)p->pSat->stats.clauses_literals );
+//            Abc_Print( 1, "Simples = %6d. ", p->nBufNum );
+//            Abc_Print( 1, "Dups = %6d. ", p->nDupNum );
+            Abc_Print( 1, "\n" );
+            fflush( stdout );
+        }
+    }
+    // consider the next timeframe
+    if ( nJumpFrame && pPars->nStart == 0 )
+        pPars->iFrame = nJumpFrame - pPars->nFramesJump;
+    else if ( RetValue == -1 && pPars->nStart == 0 )
+        pPars->iFrame = f-1;
+//ABC_PRT( "CNF generation runtime", clkOther );
+finish:
+    if ( pPars->fVerbose )
+    {
+        Abc_Print( 1, "Runtime:  " );
+        Abc_Print( 1, "CNF = %.1f sec (%.1f %%)  ",   1.0*clkOther/CLOCKS_PER_SEC,   100.0*clkOther/(Abc_Clock() - clkTotal)   );
+        Abc_Print( 1, "UNSAT = %.1f sec (%.1f %%)  ", 1.0*nTimeUnsat/CLOCKS_PER_SEC, 100.0*nTimeUnsat/(Abc_Clock() - clkTotal) );
+        Abc_Print( 1, "SAT = %.1f sec (%.1f %%)  ",   1.0*nTimeSat/CLOCKS_PER_SEC,   100.0*nTimeSat/(Abc_Clock() - clkTotal)   );
+        Abc_Print( 1, "UNDEC = %.1f sec (%.1f %%)",   1.0*nTimeUndec/CLOCKS_PER_SEC, 100.0*nTimeUndec/(Abc_Clock() - clkTotal) );
+        Abc_Print( 1, "\n" );
+    }
+    Saig_Bmc3ManStop( p );
+    fflush( stdout );
+    if ( pLogFile )
+        fclose( pLogFile );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcBmcAnd.c b/abc-build/src/sat/bmc/bmcBmcAnd.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcBmcAnd.c
@@ -0,0 +1,1098 @@
+/**CFile****************************************************************
+
+  FileName    [bmcBmcAnd.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    [Memory-efficient BMC engine]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcBmcAnd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bmc.h"
+#include "aig/gia/giaAig.h"
+#include "sat/bsat/satStore.h"
+#include "sat/cnf/cnf.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Bmc_Mna_t_ Bmc_Mna_t; 
+struct Bmc_Mna_t_
+{
+    Gia_Man_t *         pFrames;  // time frames
+    Cnf_Dat_t *         pCnf;     // CNF derived for the timeframes
+    Vec_Int_t *         vPiMap;   // maps unrolled GIA PIs into user GIA PIs
+    Vec_Int_t *         vId2Var;  // maps GIA IDs into SAT vars
+    Vec_Int_t *         vInputs;  // inputs of the cone
+    Vec_Int_t *         vOutputs; // outputs of the cone
+    Vec_Int_t *         vNodes;   // internal nodes of the cone
+    sat_solver *        pSat;     // SAT solver
+    int                 nSatVars; // the counter of SAT variables
+    abctime             clkStart; // starting time
+};
+
+static inline int Gia_ManTerSimInfoGet( unsigned * pInfo, int i )
+{
+    return 3 & (pInfo[i >> 4] >> ((i & 15) << 1));
+}
+static inline void Gia_ManTerSimInfoSet( unsigned * pInfo, int i, int Value )
+{
+    assert( Value >= GIA_ZER && Value <= GIA_UND );
+    Value ^= Gia_ManTerSimInfoGet( pInfo, i );
+    pInfo[i >> 4] ^= (Value << ((i & 15) << 1));
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs ternary simulation of the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Bmc_MnaTernary( Gia_Man_t * p, int nFrames, int nFramesAdd, int fVerbose, int * iFirst )
+{
+    Vec_Ptr_t * vStates;
+    unsigned * pState;
+    int nStateWords = Abc_BitWordNum( 2*Gia_ManCoNum(p) );
+    Gia_Obj_t * pObj, * pObjRo;
+    int f, i, Count[4];
+    abctime clk = Abc_Clock();
+    Gia_ManConst0(p)->Value = GIA_ZER;
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->Value = GIA_UND;
+    Gia_ManForEachRi( p, pObj, i )
+        pObj->Value = GIA_ZER;
+    *iFirst = -1;
+    vStates = Vec_PtrAlloc( 100 );
+    for ( f = 0; ; f++ )
+    {
+        // if frames are given, break at frames
+        if ( nFrames && f == nFrames )
+            break;
+        // if frames are not given, break after nFramesAdd from the first x-valued
+        if ( !nFrames && *iFirst >= 0 && f == *iFirst + nFramesAdd )
+            break;
+        // aassign CI values
+        Gia_ManForEachRiRo( p, pObj, pObjRo, i )
+            pObjRo->Value = pObj->Value;
+        Gia_ManForEachAnd( p, pObj, i )
+            pObj->Value = Gia_XsimAndCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj), Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC1(pObj) );
+        // compute and save CO values
+        pState = ABC_ALLOC( unsigned, nStateWords );
+        Gia_ManForEachCo( p, pObj, i )
+        {
+            pObj->Value = Gia_XsimNotCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) );
+            Gia_ManTerSimInfoSet( pState, i, pObj->Value );
+            if ( *iFirst == -1 && i < Gia_ManPoNum(p) && pObj->Value == GIA_UND )
+                *iFirst = f;
+        }
+        Vec_PtrPush( vStates, pState );
+        // print statistics
+        if ( !fVerbose )
+            continue;
+        Count[0] = Count[1] = Count[2] = Count[3] = 0;
+        Gia_ManForEachRi( p, pObj, i )
+            Count[pObj->Value]++;
+        printf( "%5d : 0 =%7d    1 =%7d    x =%7d    all =%7d   out = %s\n", 
+            f, Count[GIA_ZER], Count[GIA_ONE], Count[GIA_UND], Gia_ManRegNum(p), 
+            Gia_ManPo(p, 0)->Value == GIA_UND ? "x" : "0" );  
+    }
+//    assert( Vec_PtrSize(vStates) == nFrames );
+    if ( fVerbose )
+        printf( "Finished %d frames. First x-valued PO is in frame %d.  ", nFrames, *iFirst );
+    if ( fVerbose )
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return vStates;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collect AIG nodes for the group of POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bmc_MnaCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes, unsigned * pState )
+{
+    if ( pObj->fPhase )
+        return;
+    pObj->fPhase = 1;
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        Bmc_MnaCollect_rec( p, Gia_ObjFanin0(pObj), vNodes, pState );
+        Bmc_MnaCollect_rec( p, Gia_ObjFanin1(pObj), vNodes, pState );
+        pObj->Value = Gia_XsimAndCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj), Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC1(pObj) );
+    }
+    else if ( Gia_ObjIsRo(p, pObj) )
+        pObj->Value = pState ? Gia_ManTerSimInfoGet( pState, Gia_ObjCioId(Gia_ObjRoToRi(p, pObj)) ) : GIA_ZER;
+    else if ( Gia_ObjIsPi(p, pObj) )
+        pObj->Value = GIA_UND;
+    else assert( 0 );
+    Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
+}
+void Bmc_MnaCollect( Gia_Man_t * p, Vec_Int_t * vCos, Vec_Int_t * vNodes, unsigned * pState )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Vec_IntClear( vNodes );
+    Gia_ManConst0(p)->fPhase = 1;
+    Gia_ManConst0(p)->Value = GIA_ZER;
+    Gia_ManForEachObjVec( vCos, p, pObj, i )
+    {
+        assert( Gia_ObjIsCo(pObj) );
+        Bmc_MnaCollect_rec( p, Gia_ObjFanin0(pObj), vNodes, pState );
+        pObj->Value = Gia_XsimNotCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) );
+        assert( pObj->Value == GIA_UND );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Select related logic cones for the COs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bmc_MnaSelect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves )
+{
+    if ( !pObj->fPhase )
+        return;
+    pObj->fPhase = 0;
+    assert( pObj->Value == GIA_UND );
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        if ( Gia_ObjFanin0(pObj)->Value == GIA_UND )
+            Bmc_MnaSelect_rec( p, Gia_ObjFanin0(pObj), vLeaves );
+        else assert( Gia_ObjFanin0(pObj)->Value + Gia_ObjFaninC0(pObj) == GIA_ONE );
+        if ( Gia_ObjFanin1(pObj)->Value == GIA_UND )
+            Bmc_MnaSelect_rec( p, Gia_ObjFanin1(pObj), vLeaves );
+        else assert( Gia_ObjFanin1(pObj)->Value + Gia_ObjFaninC1(pObj) == GIA_ONE );
+    }
+    else if ( Gia_ObjIsRo(p, pObj) )
+        Vec_IntPush( vLeaves, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) );
+}
+void Bmc_MnaSelect( Gia_Man_t * p, Vec_Int_t * vCos, Vec_Int_t * vNodes, Vec_Int_t * vLeaves )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Vec_IntClear( vLeaves );
+    Gia_ManForEachObjVec( vCos, p, pObj, i )
+        Bmc_MnaSelect_rec( p, Gia_ObjFanin0(pObj), vLeaves );
+    Gia_ManConst0(p)->fPhase = 0;
+    Gia_ManForEachObjVec( vNodes, p, pObj, i )
+        pObj->fPhase = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Build AIG for the selected cones.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bmc_MnaBuild_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Man_t * pNew, Vec_Int_t * vMap, Vec_Int_t * vPiMap )
+{
+    if ( !pObj->fPhase )
+        return;
+    pObj->fPhase = 0;
+    assert( pObj->Value == GIA_UND );
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        int iLit0 = 1, iLit1 = 1;
+        if ( Gia_ObjFanin0(pObj)->Value == GIA_UND )
+            Bmc_MnaBuild_rec( p, Gia_ObjFanin0(pObj), pNew, vMap, vPiMap );
+        if ( Gia_ObjFanin1(pObj)->Value == GIA_UND )
+            Bmc_MnaBuild_rec( p, Gia_ObjFanin1(pObj), pNew, vMap, vPiMap );
+        if ( Gia_ObjFanin0(pObj)->Value == GIA_UND )
+            iLit0 = Abc_LitNotCond( Vec_IntEntry(vMap, Gia_ObjFaninId0p(p, pObj)), Gia_ObjFaninC0(pObj) );
+        if ( Gia_ObjFanin1(pObj)->Value == GIA_UND )
+            iLit1 = Abc_LitNotCond( Vec_IntEntry(vMap, Gia_ObjFaninId1p(p, pObj)), Gia_ObjFaninC1(pObj) );
+        Vec_IntWriteEntry( vMap, Gia_ObjId(p, pObj), Gia_ManHashAnd(pNew, iLit0, iLit1) );
+    }
+    else if ( Gia_ObjIsRo(p, pObj) )
+        assert( Vec_IntEntry(vMap, Gia_ObjId(p, pObj)) != -1 );
+    else if ( Gia_ObjIsPi(p, pObj) )
+    {
+        Vec_IntPush( vPiMap, Gia_ObjCioId(pObj) );
+        Vec_IntWriteEntry( vMap, Gia_ObjId(p, pObj), Gia_ManAppendCi(pNew) );
+    }
+    else assert( 0 );
+}
+void Bmc_MnaBuild( Gia_Man_t * p, Vec_Int_t * vCos, Vec_Int_t * vNodes, Gia_Man_t * pNew, Vec_Int_t * vMap, Vec_Int_t * vPiMap )
+{
+    Gia_Obj_t * pObj;
+    int i, iLit;
+    Gia_ManForEachObjVec( vCos, p, pObj, i )
+    {
+        assert( Gia_ObjIsCo(pObj) );
+        Bmc_MnaBuild_rec( p, Gia_ObjFanin0(pObj), pNew, vMap, vPiMap );
+        iLit = Abc_LitNotCond( Vec_IntEntry(vMap, Gia_ObjFaninId0p(p, pObj)), Gia_ObjFaninC0(pObj) );
+        Vec_IntWriteEntry( vMap, Gia_ObjId(p, pObj), iLit );
+    }
+    Gia_ManConst0(p)->fPhase = 0;
+    Gia_ManForEachObjVec( vNodes, p, pObj, i )
+        pObj->fPhase = 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the first non-trivial timeframe.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManBmcUnroll( Gia_Man_t * pGia, int nFramesMax, int nFramesAdd, int fVerbose, Vec_Int_t ** pvPiMap )
+{
+    Gia_Obj_t * pObj;
+    Gia_Man_t * pNew, * pTemp;
+    Vec_Ptr_t * vStates, * vBegins;
+    Vec_Int_t * vRoots, * vCone, * vLeaves, * vMap;
+    unsigned * pStateF, * pStateP;
+    int f, i, iFirst;
+    Gia_ManCleanPhase( pGia );
+    vCone = Vec_IntAlloc( 1000 );
+    vLeaves = Vec_IntAlloc( 1000 );
+    // perform ternary simulation
+    vStates = Bmc_MnaTernary( pGia, nFramesMax, nFramesAdd, fVerbose, &iFirst );
+    // go backward
+    *pvPiMap = Vec_IntAlloc( 1000 );
+    vBegins = Vec_PtrStart( Vec_PtrSize(vStates) );
+    for ( f = Vec_PtrSize(vStates) - 1; f >= 0; f-- )
+    {
+        // get ternary states
+        pStateF = (unsigned *)Vec_PtrEntry(vStates, f);
+        pStateP = f ? (unsigned *)Vec_PtrEntry(vStates, f-1) : 0;
+        // collect roots of this frame
+        vRoots = Vec_IntAlloc( 100 );
+        Gia_ManForEachPo( pGia, pObj, i )
+            if ( Gia_ManTerSimInfoGet( pStateF, Gia_ObjCioId(pObj) ) == GIA_UND )
+                Vec_IntPush( vRoots, Gia_ObjId(pGia, pObj) );
+        // add leaves from the previous frame
+        Vec_IntAppend( vRoots, vLeaves );
+        Vec_PtrWriteEntry( vBegins, f, vRoots );
+        // find the cone
+        Bmc_MnaCollect( pGia, vRoots, vCone, pStateP ); // computes vCone
+        Bmc_MnaSelect( pGia, vRoots, vCone, vLeaves );  // computes vLeaves 
+        if ( fVerbose )
+        printf( "Frame %4d :  Roots = %6d  Leaves = %6d  Cone = %6d\n", 
+            f, Vec_IntSize(vRoots), Vec_IntSize(vLeaves), Vec_IntSize(vCone) );
+        if ( Vec_IntSize(vLeaves) == 0 )
+            break;
+        // it is possible that some of the POs are still ternary... 
+    }
+    assert( f >= 0 );
+    // go forward
+    vMap = Vec_IntStartFull( Gia_ManObjNum(pGia) );
+    pNew = Gia_ManStart( 10000 );
+    pNew->pName = Abc_UtilStrsav( pGia->pName );
+    Gia_ManHashStart( pNew );
+    for ( f = 0; f < Vec_PtrSize(vStates); f++ )
+    {
+        vRoots = (Vec_Int_t *)Vec_PtrEntry( vBegins, f );
+        if ( vRoots == NULL )
+        {
+            Gia_ManForEachPo( pGia, pObj, i )
+                Gia_ManAppendCo( pNew, 0 );
+            continue;
+        }
+        // get ternary states
+        pStateF = (unsigned *)Vec_PtrEntry(vStates, f);
+        pStateP = f ? (unsigned *)Vec_PtrEntry(vStates, f-1) : 0;
+        // clean POs
+        Gia_ManForEachPo( pGia, pObj, i )
+            Vec_IntWriteEntry( vMap, Gia_ObjId(pGia, pObj), 0 );
+        // find the cone
+        Vec_IntPush( *pvPiMap, -f-1 );
+        Bmc_MnaCollect( pGia, vRoots, vCone, pStateP );   // computes vCone
+        Bmc_MnaBuild( pGia, vRoots, vCone, pNew, vMap, *pvPiMap );  // computes pNew       
+        if ( fVerbose )
+        printf( "Frame %4d :  Roots = %6d  Leaves = %6d  Cone = %6d\n", 
+            f, Vec_IntSize(vRoots), Vec_IntSize(vLeaves), Vec_IntSize(vCone) );
+        // create POs
+        Gia_ManForEachPo( pGia, pObj, i )
+            Gia_ManAppendCo( pNew, Vec_IntEntry(vMap, Gia_ObjId(pGia, pObj)) );
+        // set a new map
+        Gia_ManForEachObjVec( vRoots, pGia, pObj, i )
+            if ( Gia_ObjIsRi(pGia, pObj) )
+                Vec_IntWriteEntry( vMap, Gia_ObjId(pGia, Gia_ObjRiToRo(pGia, pObj)), Vec_IntEntry(vMap, Gia_ObjId(pGia, pObj)) );
+//            else if ( Gia_ObjIsPo(pGia, pObj) )
+//                Gia_ManAppendCo( pNew, Vec_IntEntry(vMap, Gia_ObjId(pGia, pObj)) );
+//            else assert( 0 );
+    }
+    Gia_ManHashStop( pNew );
+    Vec_VecFree( (Vec_Vec_t *)vBegins );
+    Vec_PtrFreeFree( vStates );
+    Vec_IntFree( vLeaves );
+    Vec_IntFree( vCone );
+    Vec_IntFree( vMap );
+    // cleanup
+//    Gia_ManPrintStats( pNew, NULL );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+//    Gia_ManPrintStats( pNew, NULL );
+    return pNew;
+}
+ 
+
+
+/**Function*************************************************************
+
+  Synopsis    [BMC manager manipulation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bmc_Mna_t * Bmc_MnaAlloc()
+{
+    Bmc_Mna_t * p;
+    p = ABC_CALLOC( Bmc_Mna_t, 1 );
+    p->vId2Var   = Vec_IntAlloc( 0 );
+    p->vInputs   = Vec_IntAlloc( 1000 );
+    p->vOutputs  = Vec_IntAlloc( 1000 );
+    p->vNodes    = Vec_IntAlloc( 10000 );
+    p->pSat      = sat_solver_new();
+    p->nSatVars  = 1;
+    p->clkStart  = Abc_Clock();
+    sat_solver_setnvars( p->pSat, 1000 );
+    return p;
+}
+void Bmc_MnaFree( Bmc_Mna_t * p )
+{
+    Cnf_DataFree( p->pCnf );
+    Vec_IntFreeP( &p->vPiMap );
+    Vec_IntFreeP( &p->vId2Var );
+    Vec_IntFreeP( &p->vInputs );
+    Vec_IntFreeP( &p->vOutputs );
+    Vec_IntFreeP( &p->vNodes );
+    sat_solver_delete( p->pSat );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives GIA for the given cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManBmcDupCone( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vNodes, Vec_Int_t * vOuts )
+{
+    Gia_Man_t * pNew;
+    Vec_Int_t * vTempIn, * vTempNode;
+    Gia_Obj_t * pObj;
+    int i;
+    // save values
+    vTempIn = Vec_IntAlloc( Vec_IntSize(vIns) );
+    Gia_ManForEachObjVec( vIns, p, pObj, i )
+        Vec_IntPush( vTempIn, pObj->Value );
+    // save values
+    vTempNode = Vec_IntAlloc( Vec_IntSize(vNodes) );
+    Gia_ManForEachObjVec( vNodes, p, pObj, i )
+        Vec_IntPush( vTempNode, pObj->Value );
+    // derive new GIA
+    pNew = Gia_ManDupFromVecs( p, vIns, vNodes, vOuts, 0 );
+    // reset values
+    Gia_ManForEachObjVec( vIns, p, pObj, i )
+        pObj->Value = Vec_IntEntry( vTempIn, i );
+    // reset values
+    Gia_ManForEachObjVec( vNodes, p, pObj, i )
+        pObj->Value = Vec_IntEntry( vTempNode, i );
+    // reset values
+    Gia_ManForEachObjVec( vOuts, p, pObj, i )
+        pObj->Value = 0;
+    Vec_IntFree( vTempIn );
+    Vec_IntFree( vTempNode );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives GIA for the given cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManBmcAssignVarIds( Bmc_Mna_t * p, Vec_Int_t * vIns, Vec_Int_t * vUsed, Vec_Int_t * vOuts )
+{
+    int i, iObj, VarC0 = p->nSatVars++;
+    Vec_IntForEachEntry( vIns, iObj, i )
+        if ( Vec_IntEntry( p->vId2Var, iObj ) == 0 )
+            Vec_IntWriteEntry( p->vId2Var, iObj, p->nSatVars++ );
+    Vec_IntForEachEntryReverse( vUsed, iObj, i )
+    {
+        assert( Vec_IntEntry( p->vId2Var, iObj ) == 0 );
+        Vec_IntWriteEntry( p->vId2Var, iObj, p->nSatVars++ );
+    }
+    Vec_IntForEachEntry( vOuts, iObj, i )
+    {
+        assert( Vec_IntEntry( p->vId2Var, iObj ) == 0 );
+        Vec_IntWriteEntry( p->vId2Var, iObj, p->nSatVars++ );
+    }
+    // extend the SAT solver
+    if ( p->nSatVars > sat_solver_nvars(p->pSat) )
+        sat_solver_setnvars( p->pSat, p->nSatVars );
+    return VarC0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CNF for the given cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManBmcAddCnf( Bmc_Mna_t * p, Gia_Man_t * pGia, Vec_Int_t * vIns, Vec_Int_t * vNodes, Vec_Int_t * vOuts )
+{
+    Gia_Man_t * pNew = Gia_ManBmcDupCone( pGia, vIns, vNodes, vOuts );
+    Aig_Man_t * pAig = Gia_ManToAigSimple( pNew );
+    Cnf_Dat_t * pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) );
+    Vec_Int_t * vUsed, * vMap;
+    Gia_Obj_t * pObj;
+    int i, iObj, VarC0;
+    // collect used variables
+    vUsed = Vec_IntAlloc( pCnf->nVars - Vec_IntSize(vIns) - Vec_IntSize(vOuts) );
+    Gia_ManForEachAnd( pNew, pObj, i )
+        if ( pCnf->pVarNums[i] >= 0 )
+            Vec_IntPush( vUsed, Vec_IntEntry(vNodes, i - Vec_IntSize(vIns) - 1) );
+    // assign variable IDs
+    VarC0 = Gia_ManBmcAssignVarIds( p, vIns, vUsed, vOuts );
+    Vec_IntFree( vUsed );
+    // create variable map from CNF vars into SAT vars
+    vMap = Vec_IntStartFull( pCnf->nVars );
+    assert( pCnf->pVarNums[0] > 0 );
+    Vec_IntWriteEntry( vMap, pCnf->pVarNums[0], VarC0 );
+    Gia_ManForEachObj1( pNew, pObj, i )
+    {
+        if ( pCnf->pVarNums[i] < 0 )
+            continue;
+        assert( pCnf->pVarNums[i] >= 0 && pCnf->pVarNums[i] < pCnf->nVars );
+        if ( Gia_ObjIsCi(pObj) )
+            iObj = Vec_IntEntry( vIns, i - 1 );
+        else if ( Gia_ObjIsAnd(pObj) )
+            iObj = Vec_IntEntry( vNodes, i - Vec_IntSize(vIns) - 1 );
+        else if ( Gia_ObjIsCo(pObj) )
+            iObj = Vec_IntEntry( vOuts, i - Vec_IntSize(vIns) - Vec_IntSize(vNodes) - 1 );
+        else assert( 0 );
+        assert( Vec_IntEntry(p->vId2Var, iObj) > 0 );
+        Vec_IntWriteEntry( vMap, pCnf->pVarNums[i], Vec_IntEntry(p->vId2Var, iObj) );
+    }
+//Vec_IntPrint( vMap );
+    // remap CNF
+    for ( i = 0; i < pCnf->nLiterals; i++ )
+    {
+        assert( pCnf->pClauses[0][i] > 1 && pCnf->pClauses[0][i] < 2 * pCnf->nVars );
+        pCnf->pClauses[0][i] = Abc_Lit2LitV( Vec_IntArray(vMap), pCnf->pClauses[0][i] );
+    }
+    Vec_IntFree( vMap );
+    // add clauses
+    for ( i = 0; i < pCnf->nClauses; i++ )
+    {
+/*
+        int v;
+        for ( v = 0; v < pCnf->pClauses[i+1] - pCnf->pClauses[i]; v++ )
+            printf( "%d ", pCnf->pClauses[i][v] );
+        printf( "\n" );
+*/
+        if ( !sat_solver_addclause( p->pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
+            break;
+    }
+    if ( i < pCnf->nClauses )
+        printf( "SAT solver became UNSAT after adding clauses.\n" );
+    Aig_ManStop( pAig );
+    Cnf_DataFree( pCnf );
+    Gia_ManStop( pNew );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects new nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManBmcAddCone_rec( Bmc_Mna_t * p, Gia_Obj_t * pObj )
+{
+    int iObj;
+    if ( pObj->fMark0 )
+        return;
+    pObj->fMark0 = 1;
+    iObj = Gia_ObjId( p->pFrames, pObj );
+    if ( Gia_ObjIsAnd(pObj) && Vec_IntEntry(p->vId2Var, iObj) == 0 )
+    {
+        Gia_ManBmcAddCone_rec( p, Gia_ObjFanin0(pObj) );
+        Gia_ManBmcAddCone_rec( p, Gia_ObjFanin1(pObj) );
+        Vec_IntPush( p->vNodes, iObj );
+    }
+    else
+        Vec_IntPush( p->vInputs, iObj );
+}
+void Gia_ManBmcAddCone( Bmc_Mna_t * p, int iStart, int iStop )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Vec_IntClear( p->vNodes );
+    Vec_IntClear( p->vInputs );
+    Vec_IntClear( p->vOutputs );
+    Vec_IntFillExtra( p->vId2Var, Gia_ManObjNum(p->pFrames), 0 );
+    for ( i = iStart; i < iStop; i++ )
+    {
+        pObj = Gia_ManPo(p->pFrames, i);
+        if ( Gia_ObjChild0(pObj) == Gia_ManConst0(p->pFrames) )
+            continue;
+        Gia_ManBmcAddCone_rec( p, Gia_ObjFanin0(pObj) );
+        Vec_IntPush( p->vOutputs, Gia_ObjId(p->pFrames, pObj) );
+    }
+    // clean attributes and create new variables
+    Gia_ManForEachObjVec( p->vNodes, p->pFrames, pObj, i )
+        pObj->fMark0 = 0;
+    Gia_ManForEachObjVec( p->vInputs, p->pFrames, pObj, i )
+        pObj->fMark0 = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManBmcCheckOutputs( Gia_Man_t * pFrames, int iStart, int iStop )
+{
+    int i;
+    for ( i = iStart; i < iStop; i++ )
+        if ( Gia_ObjChild0(Gia_ManPo(pFrames, i)) != Gia_ManConst0(pFrames) )
+            return 0;
+    return 1;
+}
+int Gia_ManBmcFindFirst( Gia_Man_t * pFrames )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    Gia_ManForEachPo( pFrames, pObj, i )
+        if ( Gia_ObjChild0(pObj) != Gia_ManConst0(pFrames) )
+            return i;
+    return -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManBmcPerform_Unr( Gia_Man_t * pGia, Bmc_AndPar_t * pPars )
+{
+    Unr_Man_t * pUnroll;
+    Bmc_Mna_t * p;
+    int nFramesMax = pPars->nFramesMax ? pPars->nFramesMax : ABC_INFINITY;
+    int f, i=0, Lit, status, RetValue = -2;
+    p = Bmc_MnaAlloc();
+    pUnroll = Unr_ManUnrollStart( pGia, pPars->fVeryVerbose );
+    for ( f = 0; f < nFramesMax; f++ )
+    {
+        p->pFrames = Unr_ManUnrollFrame( pUnroll, f );
+        if ( !Gia_ManBmcCheckOutputs( p->pFrames, f * Gia_ManPoNum(pGia), (f+1) * Gia_ManPoNum(pGia) ) )
+        {
+            // create another slice
+            Gia_ManBmcAddCone( p, f * Gia_ManPoNum(pGia), (f+1) * Gia_ManPoNum(pGia) );
+            // create CNF in the SAT solver
+            Gia_ManBmcAddCnf( p, p->pFrames, p->vInputs, p->vNodes, p->vOutputs );
+            // try solving the outputs
+            for ( i = f * Gia_ManPoNum(pGia); i < (f+1) * Gia_ManPoNum(pGia); i++ )
+            {
+                Gia_Obj_t * pObj = Gia_ManPo(p->pFrames, i);
+                if ( Gia_ObjChild0(pObj) == Gia_ManConst0(p->pFrames) )
+                    continue;
+                Lit = Abc_Var2Lit( Vec_IntEntry(p->vId2Var, Gia_ObjId(p->pFrames, pObj)), 0 );
+                status = sat_solver_solve( p->pSat, &Lit, &Lit + 1, (ABC_INT64_T)pPars->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+                if ( status == l_False ) // unsat
+                    continue;
+                if ( status == l_True ) // sat
+                    RetValue = 0;
+                if ( status == l_Undef ) // undecided
+                    RetValue = -1;
+                break;
+            }
+        }
+        // report statistics
+        if ( pPars->fVerbose )
+        {
+            printf( "%4d :  PI =%9d.  AIG =%9d.  Var =%8d.  In =%6d.  And =%9d.  Cla =%9d.  Conf =%9d.  Mem =%7.1f MB   ", 
+                f, Gia_ManPiNum(p->pFrames), Gia_ManAndNum(p->pFrames), 
+                p->nSatVars-1, Vec_IntSize(p->vInputs), Vec_IntSize(p->vNodes), 
+                sat_solver_nclauses(p->pSat), sat_solver_nconflicts(p->pSat), Gia_ManMemory(p->pFrames)/(1<<20) );
+            Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
+        }
+        if ( RetValue != -2 )
+        {
+            if ( RetValue == -1 )
+                printf( "SAT solver reached conflict/runtime limit in frame %d.\n", f );
+            else
+            {
+                printf( "Output %d of miter \"%s\" was asserted in frame %d.  ", 
+                    i - f * Gia_ManPoNum(pGia), Gia_ManName(pGia), f );
+                Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
+            }
+            break;
+        }
+    }
+    if ( RetValue == -2 )
+        RetValue = -1;
+    // dump unfolded frames
+    if ( pPars->fDumpFrames )
+    {
+        p->pFrames = Gia_ManCleanup( p->pFrames );
+        Gia_AigerWrite( p->pFrames, "frames.aig", 0, 0 );
+        printf( "Dumped unfolded frames into file \"frames.aig\".\n" );
+        Gia_ManStop( p->pFrames );
+    }
+    // cleanup
+    Unr_ManFree( pUnroll );
+    Bmc_MnaFree( p );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generate counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Gia_ManBmcCexGen( Bmc_Mna_t * pMan, Gia_Man_t * p, int iOut )
+{
+    Abc_Cex_t * pCex;
+    int i, iObjId, iSatVar, iOrigPi;
+    int iFramePi = 0, iFrame = -1;
+    pCex = Abc_CexAlloc( Gia_ManRegNum(p), Gia_ManPiNum(p), iOut / Gia_ManPoNum(p) + 1 );
+    pCex->iFrame = iOut / Gia_ManPoNum(p);
+    pCex->iPo = iOut % Gia_ManPoNum(p);
+    // fill in the input values
+    Vec_IntForEachEntry( pMan->vPiMap, iOrigPi, i )
+    {
+        if ( iOrigPi < 0 )
+        {
+            iFrame = -iOrigPi-1;
+            continue;
+        }
+        // iOrigPi in iFrame of pGia has PI index iFramePi in pMan->pFrames,
+        iObjId = Gia_ObjId( pMan->pFrames, Gia_ManPi(pMan->pFrames, iFramePi) );
+        iSatVar = Vec_IntEntry( pMan->vId2Var, iObjId );
+        if ( sat_solver_var_value(pMan->pSat, iSatVar) )
+            Abc_InfoSetBit( pCex->pData, Gia_ManRegNum(p) + Gia_ManPiNum(p) * iFrame + iOrigPi );
+        iFramePi++;
+    }
+    assert( iFramePi == Gia_ManPiNum(pMan->pFrames) );
+    return pCex;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManBmcPerform_old_cnf( Gia_Man_t * pGia, Bmc_AndPar_t * pPars )
+{
+    Bmc_Mna_t * p;
+    int nFramesMax, f, i=0, Lit, status, RetValue = -2;
+    abctime clk = Abc_Clock();
+    p = Bmc_MnaAlloc();
+    p->pFrames = Gia_ManBmcUnroll( pGia, pPars->nFramesMax, pPars->nFramesAdd, pPars->fVeryVerbose, &p->vPiMap );
+    nFramesMax = Gia_ManPoNum(p->pFrames) / Gia_ManPoNum(pGia);
+    if ( pPars->fVerbose )
+    {
+        printf( "Unfolding for %d frames with first non-trivial PO %d.  ", nFramesMax, Gia_ManBmcFindFirst(p->pFrames) );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    if ( pPars->fUseSynth )
+    {
+        Gia_Man_t * pTemp = p->pFrames;
+        p->pFrames = Gia_ManAigSyn2( pTemp, 1, 0, 0, 0, pPars->fVerbose, 0 );
+        Gia_ManStop( pTemp );
+    }
+    else if ( pPars->fVerbose )
+        Gia_ManPrintStats( p->pFrames, NULL );
+    if ( pPars->fDumpFrames )
+    {
+        Gia_AigerWrite( p->pFrames, "frames.aig", 0, 0 );
+        printf( "Dumped unfolded frames into file \"frames.aig\".\n" );
+    }
+    for ( f = 0; f < nFramesMax; f++ )
+    {
+        if ( !Gia_ManBmcCheckOutputs( p->pFrames, f * Gia_ManPoNum(pGia), (f+1) * Gia_ManPoNum(pGia) ) )
+        {
+            // create another slice
+            Gia_ManBmcAddCone( p, f * Gia_ManPoNum(pGia), (f+1) * Gia_ManPoNum(pGia) );
+            // create CNF in the SAT solver
+            Gia_ManBmcAddCnf( p, p->pFrames, p->vInputs, p->vNodes, p->vOutputs );
+            // try solving the outputs
+            for ( i = f * Gia_ManPoNum(pGia); i < (f+1) * Gia_ManPoNum(pGia); i++ )
+            {
+                Gia_Obj_t * pObj = Gia_ManPo(p->pFrames, i);
+                if ( Gia_ObjChild0(pObj) == Gia_ManConst0(p->pFrames) )
+                    continue;
+                Lit = Abc_Var2Lit( Vec_IntEntry(p->vId2Var, Gia_ObjId(p->pFrames, pObj)), 0 );
+                status = sat_solver_solve( p->pSat, &Lit, &Lit + 1, (ABC_INT64_T)pPars->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+                if ( status == l_False ) // unsat
+                    continue;
+                if ( status == l_True ) // sat
+                    RetValue = 0;
+                if ( status == l_Undef ) // undecided
+                    RetValue = -1;
+                break;
+            }
+            // report statistics
+            if ( pPars->fVerbose )
+            {
+                printf( "%4d :  PI =%9d.  AIG =%9d.  Var =%8d.  In =%6d.  And =%9d.  Cla =%9d.  Conf =%9d.  Mem =%7.1f MB   ", 
+                    f, Gia_ManPiNum(p->pFrames), Gia_ManAndNum(p->pFrames), 
+                    p->nSatVars-1, Vec_IntSize(p->vInputs), Vec_IntSize(p->vNodes), 
+                    sat_solver_nclauses(p->pSat), sat_solver_nconflicts(p->pSat), Gia_ManMemory(p->pFrames)/(1<<20) );
+                Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
+            }
+        }
+        if ( RetValue != -2 )
+        {
+            if ( RetValue == -1 )
+                printf( "SAT solver reached conflict/runtime limit in frame %d.\n", f );
+            else
+            {
+                ABC_FREE( pGia->pCexSeq );
+                pGia->pCexSeq = Gia_ManBmcCexGen( p, pGia, i );
+                printf( "Output %d of miter \"%s\" was asserted in frame %d.  ", 
+                    i - f * Gia_ManPoNum(pGia), Gia_ManName(pGia), f );
+                Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
+            }
+            break;
+        }
+        pPars->iFrame = f;
+    }
+    if ( RetValue == -2 )
+        RetValue = -1;
+    // cleanup
+    Gia_ManStop( p->pFrames );
+    Bmc_MnaFree( p );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManBmcAddCnfNew_rec( Bmc_Mna_t * p, Gia_Obj_t * pObj )
+{
+    int iObj = Gia_ObjId( p->pFrames, pObj );
+    if ( Gia_ObjIsAnd(pObj) && p->pCnf->pObj2Count[iObj] == -1 )
+    {
+        Gia_ManBmcAddCnfNew_rec( p, Gia_ObjFanin0(pObj) );
+        Gia_ManBmcAddCnfNew_rec( p, Gia_ObjFanin1(pObj) );
+        return;
+    }
+    if ( Vec_IntEntry(p->vId2Var, iObj) > 0 )
+        return;
+    Vec_IntWriteEntry(p->vId2Var, iObj, p->nSatVars++);
+    if ( Gia_ObjIsAnd(pObj) || Gia_ObjIsPo(p->pFrames, pObj) )
+    {
+        int i, nClas, iCla;
+        Gia_ManBmcAddCnfNew_rec( p, Gia_ObjFanin0(pObj) );
+        if ( Gia_ObjIsAnd(pObj) )
+        Gia_ManBmcAddCnfNew_rec( p, Gia_ObjFanin1(pObj) );
+        // extend the SAT solver
+        if ( p->nSatVars > sat_solver_nvars(p->pSat) )
+            sat_solver_setnvars( p->pSat, p->nSatVars );
+        // add clauses
+        nClas = p->pCnf->pObj2Count[iObj];
+        iCla  = p->pCnf->pObj2Clause[iObj];
+        for ( i = 0; i < nClas; i++ )
+        {
+            int nLits, pLits[8];
+            int * pClauseThis = p->pCnf->pClauses[iCla+i];
+            int * pClauseNext = p->pCnf->pClauses[iCla+i+1];
+            for ( nLits = 0; pClauseThis + nLits < pClauseNext; nLits++ )
+            {
+                if ( pClauseThis[nLits] < 2 )
+                    printf( "\n\n\nError in CNF generation:  Constant literal!\n\n\n" );
+                assert( pClauseThis[nLits] > 1 && pClauseThis[nLits] < 2*Gia_ManObjNum(p->pFrames) );
+                pLits[nLits] = Abc_Lit2LitV( Vec_IntArray(p->vId2Var), pClauseThis[nLits] );
+            }
+            assert( nLits < 8 );
+            if ( !sat_solver_addclause( p->pSat, pLits, pLits + nLits ) )
+                break;
+        }
+        if ( i < nClas )
+            printf( "SAT solver became UNSAT after adding clauses.\n" );
+    }
+    else assert( Gia_ObjIsCi(pObj) );
+}
+void Gia_ManBmcAddCnfNew( Bmc_Mna_t * p, int iStart, int iStop )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    for ( i = iStart; i < iStop; i++ )
+    {
+        pObj = Gia_ManPo(p->pFrames, i);
+        if ( Gia_ObjFanin0(pObj) == Gia_ManConst0(p->pFrames) )
+            continue;
+        Gia_ManBmcAddCnfNew_rec( p, pObj );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Cnf_Dat_t * Cnf_DeriveGia( Gia_Man_t * p )
+{
+    Aig_Man_t * pAig = Gia_ManToAigSimple( p );
+    Cnf_Dat_t * pCnf = Cnf_DeriveOther( pAig, 1 );
+    Aig_ManStop( pAig );
+    return pCnf;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManBmcPerformInt( Gia_Man_t * pGia, Bmc_AndPar_t * pPars )
+{
+    Bmc_Mna_t * p;
+    Gia_Man_t * pTemp;
+    int nFramesMax, f, i=0, Lit = 1, status, RetValue = -2;
+    abctime clk = Abc_Clock();
+    p = Bmc_MnaAlloc();
+    sat_solver_set_runtime_limit( p->pSat, pPars->nTimeOut ? pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 );
+    p->pFrames = Gia_ManBmcUnroll( pGia, pPars->nFramesMax, pPars->nFramesAdd, pPars->fVeryVerbose, &p->vPiMap );
+    nFramesMax = Gia_ManPoNum(p->pFrames) / Gia_ManPoNum(pGia);
+    if ( pPars->fVerbose )
+    {
+        printf( "Unfolding for %d frames with first non-trivial PO %d.  ", nFramesMax, Gia_ManBmcFindFirst(p->pFrames) );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    if ( pPars->fUseSynth )
+    {
+        p->pFrames = Gia_ManAigSyn2( pTemp = p->pFrames, 1, 0, 0, 0, pPars->fVerbose, 0 );  Gia_ManStop( pTemp );
+    }
+    else if ( pPars->fVerbose )
+        Gia_ManPrintStats( p->pFrames, NULL );
+    if ( pPars->fDumpFrames )
+    {
+        Gia_AigerWrite( p->pFrames, "frames.aig", 0, 0 );
+        printf( "Dumped unfolded frames into file \"frames.aig\".\n" );
+    }
+    if ( pPars->fUseOldCnf )
+        p->pCnf = Cnf_DeriveGia( p->pFrames );
+    else
+    {
+        p->pFrames = Jf_ManDeriveCnf( pTemp = p->pFrames, 1 );  Gia_ManStop( pTemp );
+        p->pCnf = (Cnf_Dat_t *)p->pFrames->pData; p->pFrames->pData = NULL;
+    }
+    Vec_IntFillExtra( p->vId2Var, Gia_ManObjNum(p->pFrames), 0 );
+    // create clauses for constant node
+//    sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+    for ( f = 0; f < nFramesMax; f++ )
+    {
+        if ( !Gia_ManBmcCheckOutputs( p->pFrames, f * Gia_ManPoNum(pGia), (f+1) * Gia_ManPoNum(pGia) ) )
+        {
+            // create another slice
+            Gia_ManBmcAddCnfNew( p, f * Gia_ManPoNum(pGia), (f+1) * Gia_ManPoNum(pGia) );
+            // try solving the outputs
+            for ( i = f * Gia_ManPoNum(pGia); i < (f+1) * Gia_ManPoNum(pGia); i++ )
+            {
+                Gia_Obj_t * pObj = Gia_ManPo(p->pFrames, i);
+                if ( Gia_ObjChild0(pObj) == Gia_ManConst0(p->pFrames) )
+                    continue;
+                if ( Gia_ObjChild0(pObj) == Gia_ManConst1(p->pFrames) )
+                {
+                    printf( "Output %d is trivially SAT.\n", i );
+                    continue;
+                }
+                Lit = Abc_Var2Lit( Vec_IntEntry(p->vId2Var, Gia_ObjId(p->pFrames, pObj)), 0 );
+                status = sat_solver_solve( p->pSat, &Lit, &Lit + 1, (ABC_INT64_T)pPars->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+                if ( status == l_False ) // unsat
+                    continue;
+                if ( status == l_True )  // sat
+                    RetValue = 0;
+                if ( status == l_Undef ) // undecided
+                    RetValue = -1;
+                break;
+            }
+            // report statistics
+            if ( pPars->fVerbose )
+            {
+                printf( "%4d :  PI =%9d.  AIG =%9d.  Var =%8d.  In =%6d.  And =%9d.  Cla =%9d.  Conf =%9d.  Mem =%7.1f MB   ", 
+                    f, Gia_ManPiNum(p->pFrames), Gia_ManAndNum(p->pFrames), 
+                    p->nSatVars-1, Vec_IntSize(p->vInputs), Vec_IntSize(p->vNodes), 
+                    sat_solver_nclauses(p->pSat), sat_solver_nconflicts(p->pSat), Gia_ManMemory(p->pFrames)/(1<<20) );
+                Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
+            }
+        }
+        if ( RetValue != -2 )
+        {
+            if ( RetValue == -1 )
+                printf( "SAT solver reached conflict/runtime limit in frame %d.\n", f );
+            else
+            {
+                ABC_FREE( pGia->pCexSeq );
+                pGia->pCexSeq = Gia_ManBmcCexGen( p, pGia, i );
+                printf( "Output %d of miter \"%s\" was asserted in frame %d.  ", 
+                    i - f * Gia_ManPoNum(pGia), Gia_ManName(pGia), f );
+                Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
+            }
+            break;
+        }
+        pPars->iFrame = f;
+    }
+    if ( RetValue == -2 )
+        RetValue = -1;
+    // cleanup
+    Gia_ManStop( p->pFrames );
+    Bmc_MnaFree( p );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManBmcPerform( Gia_Man_t * pGia, Bmc_AndPar_t * pPars )
+{
+    abctime TimeToStop = pPars->nTimeOut ? pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock() : 0;
+    if ( pPars->nFramesAdd == 0 )
+        return Gia_ManBmcPerformInt( pGia, pPars );
+    // iterate over the engine until we read the global timeout
+    assert( pPars->nTimeOut >= 0 );
+    while ( 1 )
+    {
+        if ( TimeToStop && TimeToStop < Abc_Clock() )
+            return -1;
+        if ( Gia_ManBmcPerformInt( pGia, pPars ) == 0 )
+            return 0;
+        // set the new runtime limit
+        if ( pPars->nTimeOut )
+        {
+            pPars->nTimeOut = Abc_MinInt( pPars->nTimeOut-1, (int)((TimeToStop - Abc_Clock()) / CLOCKS_PER_SEC) );
+            if ( pPars->nTimeOut <= 0 )
+                return -1;
+        }
+        else
+            return -1;
+        // set the new frames limit
+        pPars->nFramesAdd *= 2;
+    }
+    return -1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcBmci.c b/abc-build/src/sat/bmc/bmcBmci.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcBmci.c
@@ -0,0 +1,344 @@
+/**CFile****************************************************************
+
+  FileName    [bmcBmci.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcBmci.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bmc.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satStore.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Cnf_Dat_t * Cnf_DeriveGiaRemapped( Gia_Man_t * p )
+{
+    Cnf_Dat_t * pCnf;
+    Aig_Man_t * pAig = Gia_ManToAigSimple( p );
+    pAig->nRegs = 0;
+    pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) );
+    Aig_ManStop( pAig );
+    return pCnf;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cnf_DataLiftGia( Cnf_Dat_t * p, Gia_Man_t * pGia, int nVarsPlus )
+{
+    Gia_Obj_t * pObj;
+    int v;
+    Gia_ManForEachObj( pGia, pObj, v )
+        if ( p->pVarNums[Gia_ObjId(pGia, pObj)] >= 0 )
+            p->pVarNums[Gia_ObjId(pGia, pObj)] += nVarsPlus;
+    for ( v = 0; v < p->nLiterals; v++ )
+        p->pClauses[0][v] += 2*nVarsPlus;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bmc_BmciUnfold( Gia_Man_t * pNew, Gia_Man_t * p, Vec_Int_t * vFFLits, int fPiReuse )
+{
+    Gia_Obj_t * pObj;
+    int i;
+    assert( Gia_ManRegNum(p) == Vec_IntSize(vFFLits) );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachRo( p, pObj, i )
+        pObj->Value = Vec_IntEntry(vFFLits, i);
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->Value = fPiReuse ? Gia_ObjToLit(pNew, Gia_ManPi(pNew, Gia_ManPiNum(pNew)-Gia_ManPiNum(p)+i)) : Gia_ManAppendCi(pNew);
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachRi( p, pObj, i )
+        Vec_IntWriteEntry( vFFLits, i, Gia_ObjFanin0Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bmc_BmciPart_rec( Gia_Man_t * pNew, Vec_Int_t * vSatMap, int iIdNew, Gia_Man_t * pPart, Vec_Int_t * vPartMap, Vec_Int_t * vCopies )
+{
+    Gia_Obj_t * pObj = Gia_ManObj( pNew, iIdNew ); 
+    int iLitPart0, iLitPart1, iRes;
+    if ( Vec_IntEntry(vCopies, iIdNew) )
+        return Vec_IntEntry(vCopies, iIdNew);
+    if ( Vec_IntEntry(vSatMap, iIdNew) >= 0 || Gia_ObjIsCi(pObj) )
+    {
+        Vec_IntPush( vPartMap, iIdNew );
+        iRes = Gia_ManAppendCi(pPart);
+        Vec_IntWriteEntry( vCopies, iIdNew, iRes );
+        return iRes;
+    }
+    assert( Gia_ObjIsAnd(pObj) );
+    iLitPart0 = Bmc_BmciPart_rec( pNew, vSatMap, Gia_ObjFaninId0(pObj, iIdNew), pPart, vPartMap, vCopies );
+    iLitPart1 = Bmc_BmciPart_rec( pNew, vSatMap, Gia_ObjFaninId1(pObj, iIdNew), pPart, vPartMap, vCopies );
+    iLitPart0 = Abc_LitNotCond( iLitPart0, Gia_ObjFaninC0(pObj) );
+    iLitPart1 = Abc_LitNotCond( iLitPart1, Gia_ObjFaninC1(pObj) );
+    Vec_IntPush( vPartMap, iIdNew );
+    iRes = Gia_ManAppendAnd( pPart, iLitPart0, iLitPart1 );
+    Vec_IntWriteEntry( vCopies, iIdNew, iRes );
+    return iRes;
+}
+Gia_Man_t * Bmc_BmciPart( Gia_Man_t * pNew, Vec_Int_t * vSatMap, Vec_Int_t * vMiters, Vec_Int_t * vPartMap, Vec_Int_t * vCopies )
+{
+    Gia_Man_t * pPart;
+    int i, iLit, iLitPart;
+    Vec_IntFill( vCopies, Gia_ManObjNum(pNew), 0 );
+    Vec_IntFillExtra( vSatMap, Gia_ManObjNum(pNew), -1 );
+    pPart = Gia_ManStart( 1000 );
+    pPart->pName = Abc_UtilStrsav( pNew->pName );
+    Vec_IntClear( vPartMap );
+    Vec_IntPush( vPartMap, 0 );
+    Vec_IntForEachEntry( vMiters, iLit, i )
+    {
+        if ( iLit == -1 )
+            continue;
+        assert( iLit >= 2 );
+        iLitPart = Bmc_BmciPart_rec( pNew, vSatMap, Abc_Lit2Var(iLit), pPart, vPartMap, vCopies );
+        Gia_ManAppendCo( pPart, Abc_LitNotCond(iLitPart, Abc_LitIsCompl(iLit)) );
+        Vec_IntPush( vPartMap, -1 );
+    }
+    assert( Gia_ManPoNum(pPart) > 0 );
+    assert( Vec_IntSize(vPartMap) == Gia_ManObjNum(pPart) );
+    return pPart;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bmc_BmciPerform( Gia_Man_t * p, Vec_Int_t * vInit0, Vec_Int_t * vInit1, int nFrames, int nWords, int nTimeOut, int fVerbose )
+{
+    int nSatVars = 1;
+    Vec_Int_t * vLits0, * vLits1, * vMiters, * vSatMap, * vPartMap, * vCopies;
+    Gia_Man_t * pNew, * pPart;
+    Gia_Obj_t * pObj;
+    Cnf_Dat_t * pCnf;
+    sat_solver * pSat;
+    int iVar0, iVar1, iLit, iLit0, iLit1;
+    int i, f, status, nChanges, nMiters, RetValue = 1;
+    assert( Vec_IntSize(vInit0) == Gia_ManRegNum(p) );
+    assert( Vec_IntSize(vInit1) == Gia_ManRegNum(p) );
+
+    // start the SAT solver
+    pSat = sat_solver_new();
+    sat_solver_set_runtime_limit( pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 );
+
+    pNew = Gia_ManStart( 10000 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManConst0(p)->Value = 0;
+
+    vLits0 = Vec_IntAlloc( Gia_ManRegNum(p) );
+    Vec_IntForEachEntry( vInit0, iLit, i )
+        Vec_IntPush( vLits0, iLit < 2 ? iLit : Gia_ManAppendCi(pNew) );
+
+    vLits1 = Vec_IntAlloc( Gia_ManRegNum(p) );
+    Vec_IntForEachEntry( vInit1, iLit, i )
+        Vec_IntPush( vLits1, iLit < 2 ? iLit : Gia_ManAppendCi(pNew) );
+
+    vMiters  = Vec_IntAlloc( 1000 );
+    vSatMap  = Vec_IntAlloc( 1000 );
+    vPartMap = Vec_IntAlloc( 1000 );
+    vCopies  = Vec_IntAlloc( 1000 );
+    for ( f = 0; f < nFrames; f++ )
+    {
+        abctime clk = Abc_Clock();
+        Bmc_BmciUnfold( pNew, p, vLits0, 0 );
+        Bmc_BmciUnfold( pNew, p, vLits1, 1 );
+        assert( Vec_IntSize(vLits0) == Vec_IntSize(vLits1) );
+        nMiters  = 0;
+        Vec_IntClear( vMiters );
+        Vec_IntForEachEntryTwo( vLits0, vLits1, iLit0, iLit1, i )
+            if ( (iLit0 >= 2 || iLit1 >= 2) && iLit0 != iLit1 )
+                Vec_IntPush( vMiters, Gia_ManHashXor(pNew, iLit0, iLit1) ), nMiters++;
+            else
+                Vec_IntPush( vMiters, -1 );
+        assert( Vec_IntSize(vMiters) == Gia_ManRegNum(p) );
+        if ( Vec_IntSum(vMiters) + Vec_IntSize(vLits1) == 0 )
+        {
+            if ( fVerbose )
+                printf( "Reached a fixed point after %d frames.  \n", f+1 );
+            break;
+        }
+        // create new part
+        pPart = Bmc_BmciPart( pNew, vSatMap, vMiters, vPartMap, vCopies );
+        pCnf = Cnf_DeriveGiaRemapped( pPart );
+        Cnf_DataLiftGia( pCnf, pPart, nSatVars );
+        nSatVars += pCnf->nVars;
+        sat_solver_setnvars( pSat, nSatVars );
+        for ( i = 0; i < pCnf->nClauses; i++ )
+            if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
+                assert( 0 );
+        // stitch the clauses
+        Gia_ManForEachPi( pPart, pObj, i )
+        {
+            iVar0 = pCnf->pVarNums[Gia_ObjId(pPart, pObj)];
+            iVar1 = Vec_IntEntry( vSatMap, Vec_IntEntry(vPartMap, Gia_ObjId(pPart, pObj)) );
+            if ( iVar1 == -1 )
+                continue;
+            sat_solver_add_buffer( pSat, iVar0, iVar1, 0 );
+        }
+        // transfer variables
+        Gia_ManForEachCand( pPart, pObj, i )
+            if ( pCnf->pVarNums[i] >= 0 )
+            {
+                assert( Gia_ObjIsCi(pObj) || Vec_IntEntry( vSatMap, Vec_IntEntry(vPartMap, i) ) == -1 );
+                Vec_IntWriteEntry( vSatMap, Vec_IntEntry(vPartMap, i), pCnf->pVarNums[i] );
+            }
+        Cnf_DataFree( pCnf );
+        Gia_ManStop( pPart );
+        // perform runs
+        nChanges = 0;
+        Vec_IntForEachEntry( vMiters, iLit, i )
+        {
+            if ( iLit == -1 )
+                continue;
+            assert( Vec_IntEntry(vSatMap, Abc_Lit2Var(iLit)) > 0 );
+            iLit = Abc_Lit2LitV( Vec_IntArray(vSatMap), iLit );
+            status = sat_solver_solve( pSat, &iLit, &iLit + 1, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+            if ( status == l_True )
+            {
+                nChanges++;
+                continue;
+            }
+            if ( status == l_Undef )
+            {
+                printf( "Timeout reached after %d seconds.  \n", nTimeOut );
+                RetValue = 0;
+                goto cleanup;
+            }
+            assert( status == l_False );
+            iLit0 = Vec_IntEntry( vLits0, i );
+            iLit1 = Vec_IntEntry( vLits1, i );
+            assert( (iLit0 >= 2 || iLit1 >= 2) && iLit0 != iLit1 );
+            if ( iLit1 >= 2 )
+                Vec_IntWriteEntry( vLits1, i, iLit0 );
+            else
+                Vec_IntWriteEntry( vLits0, i, iLit1 );
+            iLit0 = Vec_IntEntry( vLits0, i );
+            iLit1 = Vec_IntEntry( vLits1, i );
+            assert( iLit0 == iLit1 );
+        }
+        if ( fVerbose )
+        {
+            printf( "Frame %4d : ",     f+1 );
+            printf( "Vars =%7d  ",      nSatVars );
+            printf( "Clause =%10d  ",   sat_solver_nclauses(pSat) );
+            printf( "Conflict =%10d  ", sat_solver_nconflicts(pSat) );
+            printf( "AIG =%7d  ",       Gia_ManAndNum(pNew) );
+            printf( "Miters =%5d  ",    nMiters );
+            printf( "SAT =%5d  ",       nChanges );
+            Abc_PrintTime( 1, "Time",   Abc_Clock() - clk );
+        }
+        if ( nChanges == 0 )
+        {
+            printf( "Reached a fixed point after %d frames.  \n", f+1 );
+            break;
+        }
+    }
+cleanup:
+
+    sat_solver_delete( pSat );
+    Gia_ManStopP( &pNew );
+    Vec_IntFree( vLits0 );
+    Vec_IntFree( vLits1 );
+    Vec_IntFree( vMiters );
+    Vec_IntFree( vSatMap );
+    Vec_IntFree( vPartMap );
+    Vec_IntFree( vCopies );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManBmciTest( Gia_Man_t * p, Vec_Int_t * vInit, int nFrames, int nWords, int nTimeOut, int fSim, int fVerbose )
+{
+    Vec_Int_t * vInit0 = Vec_IntStart( Gia_ManRegNum(p) );
+    Bmc_BmciPerform( p, vInit, vInit0, nFrames, nWords, nTimeOut, fVerbose );
+    Vec_IntFree( vInit0 );
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcCexCare.c b/abc-build/src/sat/bmc/bmcCexCare.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcCexCare.c
@@ -0,0 +1,298 @@
+/**CFile****************************************************************
+
+  FileName    [bmcCexCare.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    [Computing care set of the counter-example.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcCexCare.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bmc.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Backward propagation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bmc_CexCarePropagateFwdOne( Gia_Man_t * p, Abc_Cex_t * pCex, int f, int fGrow )
+{
+    Gia_Obj_t * pObj;
+    int Prio, Prio0, Prio1;
+    int i, Phase0, Phase1;
+    if ( (fGrow & 2) )
+    {
+        Gia_ManForEachPi( p, pObj, i )
+            pObj->Value = Abc_Var2Lit( f * pCex->nPis + (pCex->nPis-1-i) + 1, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i) );
+    }
+    else
+    {
+        Gia_ManForEachPi( p, pObj, i )
+            pObj->Value = Abc_Var2Lit( f * pCex->nPis + i + 1, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i) );
+    }
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        Prio0  = Abc_Lit2Var(Gia_ObjFanin0(pObj)->Value);
+        Prio1  = Abc_Lit2Var(Gia_ObjFanin1(pObj)->Value);
+        Phase0 = Abc_LitIsCompl(Gia_ObjFanin0(pObj)->Value) ^ Gia_ObjFaninC0(pObj);
+        Phase1 = Abc_LitIsCompl(Gia_ObjFanin1(pObj)->Value) ^ Gia_ObjFaninC1(pObj);
+        if ( Phase0 && Phase1 )
+            Prio = (fGrow & 1) ? Abc_MinInt(Prio0, Prio1) : Abc_MaxInt(Prio0, Prio1);
+        else if ( Phase0 && !Phase1 )
+            Prio = Prio1;
+        else if ( !Phase0 && Phase1 )
+            Prio = Prio0;
+        else // if ( !Phase0 && !Phase1 )
+            Prio = (fGrow & 1) ? Abc_MaxInt(Prio0, Prio1) : Abc_MinInt(Prio0, Prio1);
+        pObj->Value = Abc_Var2Lit( Prio, Phase0 & Phase1 );
+    }
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->Value = Abc_LitNotCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) );
+}
+void Bmc_CexCarePropagateFwd( Gia_Man_t * p, Abc_Cex_t * pCex, int fGrow, Vec_Int_t * vPrios )
+{
+    Gia_Obj_t * pObj, * pObjRo, * pObjRi;
+    int f, i;
+    Gia_ManConst0( p )->Value = 0;
+    Gia_ManForEachRi( p, pObj, i )
+        pObj->Value = 0;
+    Vec_IntClear( vPrios );
+    for ( f = 0; f <= pCex->iFrame; f++ )
+    {
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, i )
+            Vec_IntPush( vPrios, (pObjRo->Value = pObjRi->Value) );
+        Bmc_CexCarePropagateFwdOne( p, pCex, f, fGrow );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Forward propagation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bmc_CexCarePropagateBwdOne( Gia_Man_t * p, Abc_Cex_t * pCex, int f, Abc_Cex_t * pCexMin )
+{
+    Gia_Obj_t * pObj;
+    int i, Phase0, Phase1;
+    Gia_ManForEachCand( p, pObj, i )
+        pObj->fPhase = 0;
+    Gia_ManForEachCo( p, pObj, i )
+        if ( pObj->fPhase )
+            Gia_ObjFanin0(pObj)->fPhase = 1;
+    Gia_ManForEachAndReverse( p, pObj, i )
+    {
+        if ( !pObj->fPhase )
+            continue;
+        Phase0 = Abc_LitIsCompl(Gia_ObjFanin0(pObj)->Value) ^ Gia_ObjFaninC0(pObj);
+        Phase1 = Abc_LitIsCompl(Gia_ObjFanin1(pObj)->Value) ^ Gia_ObjFaninC1(pObj);
+        if ( Phase0 && Phase1 )
+        {
+            Gia_ObjFanin0(pObj)->fPhase = 1;
+            Gia_ObjFanin1(pObj)->fPhase = 1;
+        }
+        else if ( Phase0 && !Phase1 )
+            Gia_ObjFanin1(pObj)->fPhase = 1;
+        else if ( !Phase0 && Phase1 )
+            Gia_ObjFanin0(pObj)->fPhase = 1;
+        else // if ( !Phase0 && !Phase1 )
+        {
+            if ( Abc_Lit2Var(Gia_ObjFanin0(pObj)->Value) <= Abc_Lit2Var(Gia_ObjFanin1(pObj)->Value) )
+                Gia_ObjFanin0(pObj)->fPhase = 1;
+            else
+                Gia_ObjFanin1(pObj)->fPhase = 1;
+        }
+    }
+    Gia_ManForEachPi( p, pObj, i )
+        if ( pObj->fPhase )
+            Abc_InfoSetBit( pCexMin->pData, pCexMin->nRegs + pCexMin->nPis * f + i );
+}
+Abc_Cex_t * Bmc_CexCarePropagateBwd( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vPrios, int fGrow )
+{
+    Abc_Cex_t * pCexMin;
+    Gia_Obj_t * pObj, * pObjRo, * pObjRi;
+    int f, i;
+    pCexMin = Abc_CexAlloc( pCex->nRegs, pCex->nPis, pCex->iFrame + 1 );
+    pCexMin->iPo    = pCex->iPo;
+    pCexMin->iFrame = pCex->iFrame;
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->fPhase = 0;
+    for ( f = pCex->iFrame; f >= 0; f-- )
+    {
+        Gia_ManPo(p, pCex->iPo)->fPhase = (int)(f == pCex->iFrame);
+        Gia_ManForEachRo( p, pObj, i )
+            pObj->Value = Vec_IntEntry( vPrios, f * pCex->nRegs + i );
+        Bmc_CexCarePropagateFwdOne( p, pCex, f, fGrow );
+        Bmc_CexCarePropagateBwdOne( p, pCex, f, pCexMin );
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, i )
+            pObjRi->fPhase = pObjRo->fPhase;
+    }
+    return pCexMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the care set of the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Bmc_CexCareMinimizeAig( Gia_Man_t * p, Abc_Cex_t * pCex, int fCheck, int fVerbose )
+{
+    int nTryCexes = 4; // belongs to range [1;4]
+    Abc_Cex_t * pCexBest, * pCexMin[4] = {NULL};
+    int k, nOnesBest, nOnesCur;
+    Vec_Int_t * vPrios;
+    if ( pCex->nPis != Gia_ManPiNum(p) )
+    {
+        printf( "Given CEX does to have same number of inputs as the AIG.\n" );
+        return NULL;
+    }
+    if ( pCex->nRegs != Gia_ManRegNum(p) )
+    {
+        printf( "Given CEX does to have same number of flops as the AIG.\n" );
+        return NULL;
+    }
+    if ( !(pCex->iPo >= 0 && pCex->iPo < Gia_ManPoNum(p)) )
+    {
+        printf( "Given CEX has PO whose index is out of range for the AIG.\n" );
+        return NULL;
+    }
+    assert( pCex->nPis == Gia_ManPiNum(p) );
+    assert( pCex->nRegs == Gia_ManRegNum(p) );
+    assert( pCex->iPo >= 0 && pCex->iPo < Gia_ManPoNum(p) );
+    if ( fVerbose )
+    {
+        printf( "Original :    " );
+        Bmc_CexPrint( pCex, Gia_ManPiNum(p), 0 );
+    }
+    vPrios = Vec_IntAlloc( pCex->nRegs * (pCex->iFrame + 1) );
+    for ( k = 0; k < nTryCexes; k++ )
+    {
+        Bmc_CexCarePropagateFwd(p, pCex, k, vPrios );
+        assert( Vec_IntSize(vPrios) == pCex->nRegs * (pCex->iFrame + 1) );
+        if ( !Abc_LitIsCompl(Gia_ManPo(p, pCex->iPo)->Value) )
+        {
+            printf( "Counter-example is invalid.\n" );
+            Vec_IntFree( vPrios );
+            return NULL;
+        }
+        pCexMin[k] = Bmc_CexCarePropagateBwd( p, pCex, vPrios, k );
+        if ( fVerbose )
+        {
+            if ( (k & 1) )
+                printf( "Decrease :    " );
+            else
+                printf( "Increase :    " );
+            Bmc_CexPrint( pCexMin[k], Gia_ManPiNum(p), 0 );
+        }
+    }
+    Vec_IntFree( vPrios );
+    // select the best one
+    pCexBest  = pCexMin[0];
+    nOnesBest = Abc_CexCountOnes(pCexMin[0]);
+    for ( k = 1; k < nTryCexes; k++ )
+    {
+        nOnesCur = Abc_CexCountOnes(pCexMin[k]);
+        if ( nOnesBest > nOnesCur )
+        {
+            nOnesBest = nOnesCur;
+            pCexBest  = pCexMin[k];
+        }
+    }
+    for ( k = 0; k < nTryCexes; k++ )
+        if ( pCexBest != pCexMin[k] )
+            Abc_CexFreeP( &pCexMin[k] );
+    // verify and return
+    if ( fVerbose )
+    {
+        printf( "Final    :    " );
+        Bmc_CexPrint( pCexBest, Gia_ManPiNum(p), 0 );
+    }
+    if ( !Bmc_CexVerify( p, pCex, pCexBest ) )
+        printf( "Counter-example verification has failed.\n" );
+    else if ( fCheck ) 
+        printf( "Counter-example verification succeeded.\n" );
+    return pCexBest;
+}
+Abc_Cex_t * Bmc_CexCareMinimize( Aig_Man_t * p, Abc_Cex_t * pCex, int fCheck, int fVerbose )
+{
+    Gia_Man_t * pGia = Gia_ManFromAigSimple( p );
+    Abc_Cex_t * pCexMin = Bmc_CexCareMinimizeAig( pGia, pCex, fCheck, fVerbose );
+    Gia_ManStop( pGia );
+    return pCexMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the care set of the counter-example.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bmc_CexCareVerify( Aig_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexMin, int fVerbose )
+{
+    Gia_Man_t * pGia = Gia_ManFromAigSimple( p );
+    if ( fVerbose )
+    {
+        printf( "Original :    " );
+        Bmc_CexPrint( pCex, Gia_ManPiNum(pGia), 0 );
+        printf( "Minimized:    " );
+        Bmc_CexPrint( pCexMin, Gia_ManPiNum(pGia), 0 );
+    }
+    if ( !Bmc_CexVerify( pGia, pCex, pCexMin ) )
+        printf( "Counter-example verification has failed.\n" );
+    else 
+        printf( "Counter-example verification succeeded.\n" );
+    Gia_ManStop( pGia );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcCexCut.c b/abc-build/src/sat/bmc/bmcCexCut.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcCexCut.c
@@ -0,0 +1,537 @@
+/**CFile****************************************************************
+
+  FileName    [bmcCexCut.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    [Derives characterization of bad states.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcCexCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bmc.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Generate justifying assignments.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bmc_GiaGenerateJust_rec( Gia_Man_t * p, int iFrame, int iObj, Vec_Bit_t * vValues, Vec_Bit_t * vJustis )
+{
+    Gia_Obj_t * pObj;
+    int Shift = Gia_ManObjNum(p) * iFrame;
+    if ( iFrame < 0 )
+        return 0;
+    assert( iFrame >= 0 );
+    if ( Vec_BitEntry( vJustis, Shift + iObj ) )
+        return 0;
+    Vec_BitWriteEntry( vJustis, Shift + iObj, 1 );
+    pObj = Gia_ManObj( p, iObj );
+    if ( Gia_ObjIsCo(pObj) )
+        return Bmc_GiaGenerateJust_rec( p, iFrame, Gia_ObjFaninId0(pObj, iObj), vValues, vJustis );
+    if ( Gia_ObjIsCi(pObj) )
+        return Bmc_GiaGenerateJust_rec( p, iFrame-1, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)), vValues, vJustis );
+    assert( Gia_ObjIsAnd(pObj) );
+    if ( Vec_BitEntry( vValues, Shift + iObj ) )
+    {
+        Bmc_GiaGenerateJust_rec( p, iFrame, Gia_ObjFaninId0(pObj, iObj), vValues, vJustis );
+        Bmc_GiaGenerateJust_rec( p, iFrame, Gia_ObjFaninId1(pObj, iObj), vValues, vJustis );
+    }
+    else if ( Vec_BitEntry( vValues, Shift + Gia_ObjFaninId0(pObj, iObj) ) == Gia_ObjFaninC0(pObj) )
+        Bmc_GiaGenerateJust_rec( p, iFrame, Gia_ObjFaninId0(pObj, iObj), vValues, vJustis );
+    else if ( Vec_BitEntry( vValues, Shift + Gia_ObjFaninId1(pObj, iObj) ) == Gia_ObjFaninC1(pObj) )
+        Bmc_GiaGenerateJust_rec( p, iFrame, Gia_ObjFaninId1(pObj, iObj), vValues, vJustis );
+    else assert( 0 );
+    return 0;
+}
+void Bmc_GiaGenerateJustNonRec( Gia_Man_t * p, int iFrame, Vec_Bit_t * vValues, Vec_Bit_t * vJustis )
+{
+    Gia_Obj_t * pObj;
+    int i, k, Shift = Gia_ManObjNum(p) * iFrame;
+    for ( i = iFrame; i >= 0; i--, Shift -= Gia_ManObjNum(p) )
+    {
+        Gia_ManForEachObjReverse( p, pObj, k )
+        {
+            if ( k == 0 || Gia_ObjIsPi(p, pObj) )
+                continue;
+            if ( !Vec_BitEntry( vJustis, Shift + k ) )
+                continue;
+            if ( Gia_ObjIsAnd(pObj) )
+            {
+                if ( Vec_BitEntry( vValues, Shift + k ) )
+                {
+                    Vec_BitWriteEntry( vJustis, Shift + Gia_ObjFaninId0(pObj, k), 1 );
+                    Vec_BitWriteEntry( vJustis, Shift + Gia_ObjFaninId1(pObj, k), 1 );
+                }
+                else if ( Vec_BitEntry( vValues, Shift + Gia_ObjFaninId0(pObj, k) ) == Gia_ObjFaninC0(pObj) )
+                    Vec_BitWriteEntry( vJustis, Shift + Gia_ObjFaninId0(pObj, k), 1 );
+                else if ( Vec_BitEntry( vValues, Shift + Gia_ObjFaninId1(pObj, k) ) == Gia_ObjFaninC1(pObj) )
+                    Vec_BitWriteEntry( vJustis, Shift + Gia_ObjFaninId1(pObj, k), 1 );
+                else assert( 0 );
+            }
+            else if ( Gia_ObjIsCo(pObj) )
+                Vec_BitWriteEntry( vJustis, Shift + Gia_ObjFaninId0(pObj, k), 1 );
+            else if ( Gia_ObjIsCi(pObj) && i )
+                Vec_BitWriteEntry( vJustis, Shift - Gia_ManObjNum(p) + Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)), 1 );
+        }
+    }
+}
+void Bmc_GiaGenerateJust( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Bit_t ** pvValues, Vec_Bit_t ** pvJustis )
+{
+    Vec_Bit_t * vValues = Vec_BitStart( Gia_ManObjNum(p) * (pCex->iFrame + 1) );
+    Vec_Bit_t * vJustis = Vec_BitStart( Gia_ManObjNum(p) * (pCex->iFrame + 1) );
+    Gia_Obj_t * pObj;
+    int i, k, iBit = 0, fCompl0, fCompl1, fJusti0, fJusti1, Shift;
+
+    Gia_ManCleanMark0(p);
+    Gia_ManCleanMark1(p);
+    Gia_ManForEachRi( p, pObj, k )
+        pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++);
+    for ( Shift = i = 0; i <= pCex->iFrame; i++, Shift += Gia_ManObjNum(p) )
+    {
+        Gia_ManForEachObj( p, pObj, k )
+        {
+            if ( Gia_ObjIsAnd(pObj) )
+            {
+                fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+                fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj);
+                fJusti0 = Gia_ObjFanin0(pObj)->fMark1;
+                fJusti1 = Gia_ObjFanin1(pObj)->fMark1;
+                pObj->fMark0 = fCompl0 & fCompl1;
+                if ( pObj->fMark0 )
+                    pObj->fMark1 = fJusti0 & fJusti1;
+                else if ( !fCompl0 && !fCompl1 )
+                    pObj->fMark1 = fJusti0 | fJusti1;
+                else if ( !fCompl0 )
+                    pObj->fMark1 = fJusti0;
+                else if ( !fCompl1 )
+                    pObj->fMark1 = fJusti1;
+                else assert( 0 );
+            }
+            else if ( Gia_ObjIsCi(pObj) )
+            {
+                if ( Gia_ObjIsPi(p, pObj) )
+                {
+                    pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++);
+                    pObj->fMark1 = 1;
+                }
+                else
+                {
+                    pObj->fMark0 = Gia_ObjRoToRi(p, pObj)->fMark0;
+                    pObj->fMark1 = Gia_ObjRoToRi(p, pObj)->fMark1;
+                }
+            }
+            else if ( Gia_ObjIsCo(pObj) )
+            {
+                pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+                pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1;
+            }
+            else if ( Gia_ObjIsConst0(pObj) )
+                pObj->fMark1 = 1;
+            else assert( 0 );
+            if ( pObj->fMark0 )
+                Vec_BitWriteEntry( vValues, Shift + k, 1 );
+            if ( pObj->fMark1 )
+                Vec_BitWriteEntry( vJustis, Shift + k, 1 );
+        }
+    }
+    assert( iBit == pCex->nBits );
+    Gia_ManCleanMark0(p);
+    Gia_ManCleanMark1(p);
+    // perform backward traversal to mark just nodes
+    pObj = Gia_ManPo( p, pCex->iPo );
+    assert( Vec_BitEntry(vJustis, Gia_ManObjNum(p) * pCex->iFrame + Gia_ObjId(p, pObj)) == 0 );
+//    Bmc_GiaGenerateJust_rec( p, pCex->iFrame, Gia_ObjId(p, pObj), vValues, vJustis );
+    Vec_BitWriteEntry(vJustis, Gia_ManObjNum(p) * pCex->iFrame + Gia_ObjId(p, pObj), 1);
+    Bmc_GiaGenerateJustNonRec( p, pCex->iFrame, vValues, vJustis );
+    assert( Vec_BitEntry(vJustis, Gia_ManObjNum(p) * pCex->iFrame + Gia_ObjId(p, pObj)) == 1 );
+
+    // return the result
+    *pvValues = vValues;
+    *pvJustis = vJustis;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Bmc_GiaGenerateGiaOne( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Bit_t ** pvInits, int iFrBeg, int iFrEnd )
+{
+    Vec_Bit_t * vValues;
+    Vec_Bit_t * vJustis;
+    Gia_Man_t * pNew;
+    Gia_Obj_t * pObj;
+    int k, Cube = 1, Counter = 0;
+    Bmc_GiaGenerateJust( p, pCex, &vValues, &vJustis );
+    // collect flop values in frame iFrBeg
+    *pvInits = Vec_BitStart( Gia_ManRegNum(p) );
+    Gia_ManForEachRo( p, pObj, k )
+        if ( Vec_BitEntry(vValues, Gia_ManObjNum(p) * iFrBeg + Gia_ObjId(p, pObj)) )
+            Vec_BitWriteEntry( *pvInits, k, 1 );
+    // create GIA with justified values in iFrEnd
+    pNew = Gia_ManStart( 2 * Gia_ManRegNum(p) + 2 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Gia_ManForEachRo( p, pObj, k )
+    {
+        int Literal = Gia_ManAppendCi(pNew);
+        if ( !Vec_BitEntry(vJustis, Gia_ManObjNum(p) * iFrEnd + Gia_ObjId(p, pObj)) )
+            continue;
+        if ( Vec_BitEntry(vValues, Gia_ManObjNum(p) * iFrEnd + Gia_ObjId(p, pObj)) )
+            Cube = Gia_ManAppendAnd( pNew, Cube, Literal );
+        else
+            Cube = Gia_ManAppendAnd( pNew, Cube, Abc_LitNot(Literal) );
+        Counter++;
+    }
+//    printf( "Only %d flops (out of %d) belong to the care set.\n", Counter, Gia_ManRegNum(p) );
+    Gia_ManAppendCo( pNew, Cube );
+    Vec_BitFree( vValues );
+    Vec_BitFree( vJustis );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generates all frames from G to the last one.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Bmc_GiaGenerateGiaAllFrames( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Bit_t ** pvInits, int iFrBeg, int iFrEnd )
+{
+    Vec_Bit_t * vInitEnd;
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pObjRo, * pObjRi;
+    int f, i, k, iBitOld, iBit = 0, fCompl0, fCompl1;
+
+    // skip trough the first iFrEnd frames
+    Gia_ManCleanMark0(p);
+    Gia_ManForEachRo( p, pObj, k )
+        pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++);
+    *pvInits = Vec_BitStart( Gia_ManRegNum(p) );
+    for ( i = 0; i < iFrEnd; i++ )
+    {
+        // remember values in frame iFrBeg
+        if ( i == iFrBeg )
+            Gia_ManForEachRo( p, pObjRo, k )
+                if ( pObjRo->fMark0 )
+                    Vec_BitWriteEntry( *pvInits, k, 1 );
+        // simulate other values
+        Gia_ManForEachPi( p, pObj, k )
+            pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++);
+        Gia_ManForEachAnd( p, pObj, k )
+            pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & 
+                           (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+        Gia_ManForEachCo( p, pObj, k )
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
+            pObjRo->fMark0 = pObjRi->fMark0;
+    }
+    assert( i == iFrEnd );
+    vInitEnd = Vec_BitStart( Gia_ManRegNum(p) );
+    Gia_ManForEachRo( p, pObjRo, k )
+        if ( pObjRo->fMark0 )
+            Vec_BitWriteEntry( vInitEnd, k, 1 );
+
+    // create new AIG manager
+    pNew = Gia_ManStart( 10000 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Gia_ManForEachRo( p, pObjRo, k )
+        Gia_ManAppendCi(pNew);
+    Gia_ManHashStart( pNew );
+
+    Gia_ManConst0(p)->Value = 1;
+    Gia_ManForEachPi( p, pObj, k )
+        pObj->Value = 1;
+
+    iBitOld = iBit;
+    for ( f = iFrEnd; f <= pCex->iFrame; f++ )
+    {
+        // set up correct init state
+        Gia_ManForEachRo( p, pObjRo, k )
+            pObjRo->fMark0 = Vec_BitEntry( vInitEnd, k );
+        // simulate it for a few frames
+        iBit = iBitOld;
+        for ( i = iFrEnd; i < f; i++ )
+        {
+            Gia_ManForEachPi( p, pObj, k )
+                pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++);
+            Gia_ManForEachAnd( p, pObj, k )
+                pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & 
+                               (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+            Gia_ManForEachCo( p, pObj, k )
+                pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+            Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
+                pObjRo->fMark0 = pObjRi->fMark0;
+        }
+        // start creating values
+        Gia_ManForEachRo( p, pObjRo, k )
+            pObjRo->Value = Abc_LitNotCond( Gia_Obj2Lit(pNew, Gia_ManPi(pNew, k)), !pObjRo->fMark0 );
+        for ( i = f; i <= pCex->iFrame; i++ )
+        {
+            Gia_ManForEachPi( p, pObj, k )
+                pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++);
+            Gia_ManForEachAnd( p, pObj, k )
+            {
+                fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+                fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj);
+                pObj->fMark0 = fCompl0 & fCompl1;
+                if ( pObj->fMark0 )
+                    pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value );
+                else if ( !fCompl0 && !fCompl1 )
+                    pObj->Value = Gia_ManHashOr( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value );
+                else if ( !fCompl0 )
+                    pObj->Value = Gia_ObjFanin0(pObj)->Value;
+                else if ( !fCompl1 )
+                    pObj->Value = Gia_ObjFanin1(pObj)->Value;
+                else assert( 0 );
+                assert( pObj->Value > 0 );
+            }
+            Gia_ManForEachCo( p, pObj, k )
+            {
+                pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+                pObj->Value = Gia_ObjFanin0(pObj)->Value;
+                assert( pObj->Value > 0 );
+            } 
+            if ( i == pCex->iFrame )
+                break;
+            Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
+            {
+                pObjRo->fMark0 = pObjRi->fMark0;
+                pObjRo->Value = pObjRi->Value;
+            }
+        }
+        assert( iBit == pCex->nBits );
+        // create PO
+        Gia_ManAppendCo( pNew, Gia_ManPo(p, pCex->iPo)->Value );
+    }
+    Gia_ManHashStop( pNew );
+    Vec_BitFree( vInitEnd );
+
+    // cleanup
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generates one frame.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Bmc_GiaGenerateGiaAllOne( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Bit_t ** pvInits, int iFrBeg, int iFrEnd )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pObjRo, * pObjRi;
+    int i, k, iBit = 0, fCompl0, fCompl1;
+
+    // skip trough the first iFrEnd frames
+    Gia_ManCleanMark0(p);
+    Gia_ManForEachRo( p, pObj, k )
+        pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++);
+    *pvInits = Vec_BitStart( Gia_ManRegNum(p) );
+    for ( i = 0; i < iFrEnd; i++ )
+    {
+        // remember values in frame iFrBeg
+        if ( i == iFrBeg )
+            Gia_ManForEachRo( p, pObjRo, k )
+                if ( pObjRo->fMark0 )
+                    Vec_BitWriteEntry( *pvInits, k, 1 );
+        // simulate other values
+        Gia_ManForEachPi( p, pObj, k )
+            pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++);
+        Gia_ManForEachAnd( p, pObj, k )
+            pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & 
+                           (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+        Gia_ManForEachCo( p, pObj, k )
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
+            pObjRo->fMark0 = pObjRi->fMark0;
+    }
+    assert( i == iFrEnd );
+
+    // create new AIG manager
+    pNew = Gia_ManStart( 10000 );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Gia_ManConst0(p)->Value = 1;
+    Gia_ManForEachPi( p, pObj, k )
+        pObj->Value = 1;
+    Gia_ManForEachRo( p, pObjRo, k )
+        pObjRo->Value = Abc_LitNotCond( Gia_ManAppendCi(pNew), !pObjRo->fMark0 );
+    Gia_ManHashStart( pNew );
+    for ( i = iFrEnd; i <= pCex->iFrame; i++ )
+    {
+        Gia_ManForEachPi( p, pObj, k )
+            pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++);
+        Gia_ManForEachAnd( p, pObj, k )
+        {
+            fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+            fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj);
+            pObj->fMark0 = fCompl0 & fCompl1;
+            if ( pObj->fMark0 )
+                pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value );
+            else if ( !fCompl0 && !fCompl1 )
+                pObj->Value = Gia_ManHashOr( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value );
+            else if ( !fCompl0 )
+                pObj->Value = Gia_ObjFanin0(pObj)->Value;
+            else if ( !fCompl1 )
+                pObj->Value = Gia_ObjFanin1(pObj)->Value;
+            else assert( 0 );
+            assert( pObj->Value > 0 );
+        }
+        Gia_ManForEachCo( p, pObj, k )
+        {
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+            pObj->Value = Gia_ObjFanin0(pObj)->Value;
+            assert( pObj->Value > 0 );
+        } 
+        if ( i == pCex->iFrame )
+            break;
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
+        {
+            pObjRo->fMark0 = pObjRi->fMark0;
+            pObjRo->Value = pObjRi->Value;
+        }
+    }
+    Gia_ManHashStop( pNew );
+    assert( iBit == pCex->nBits );
+
+    // create PO
+    Gia_ManAppendCo( pNew, Gia_ManPo(p, pCex->iPo)->Value );
+    // cleanup
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generate GIA for target bad states.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Bmc_GiaTargetStates( Gia_Man_t * p, Abc_Cex_t * pCex, int iFrBeg, int iFrEnd, int fCombOnly, int fUseOne, int fAllFrames, int fVerbose )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Vec_Bit_t * vInitNew;
+
+    if ( iFrBeg < 0 )
+        { printf( "Starting frame is less than 0.\n" ); return NULL; }
+    if ( iFrEnd < 0 )
+        { printf( "Stopping frame is less than 0.\n" ); return NULL; }
+    if ( iFrBeg > pCex->iFrame )
+        { printf( "Starting frame is more than the last frame of CEX (%d).\n", pCex->iFrame ); return NULL; }
+    if ( iFrEnd > pCex->iFrame )
+        { printf( "Stopping frame is more than the last frame of CEX (%d).\n", pCex->iFrame ); return NULL; }
+    if ( iFrBeg > iFrEnd )
+        { printf( "Starting frame (%d) should be less than stopping frame (%d).\n", iFrBeg, iFrEnd ); return NULL; }
+    assert( iFrBeg >= 0 && iFrBeg <= pCex->iFrame );
+    assert( iFrEnd >= 0 && iFrEnd <= pCex->iFrame );
+    assert( iFrBeg < iFrEnd );
+
+    if ( fUseOne )
+        pNew = Bmc_GiaGenerateGiaOne( p, pCex, &vInitNew, iFrBeg, iFrEnd );
+    else if ( fAllFrames )
+        pNew = Bmc_GiaGenerateGiaAllFrames( p, pCex, &vInitNew, iFrBeg, iFrEnd );
+    else 
+        pNew = Bmc_GiaGenerateGiaAllOne( p, pCex, &vInitNew, iFrBeg, iFrEnd );
+
+    if ( !fCombOnly )
+    {
+        // create new GIA
+        pNew = Gia_ManDupWithNewPo( p, pTemp = pNew ); 
+        Gia_ManStop( pTemp );
+
+        // create new initial state
+        pNew = Gia_ManDupFlip( pTemp = pNew, Vec_BitArray(vInitNew) );
+        Gia_ManStop( pTemp );
+    }
+
+    Vec_BitFree( vInitNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Generate AIG for target bad states.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Bmc_AigTargetStates( Aig_Man_t * p, Abc_Cex_t * pCex, int iFrBeg, int iFrEnd, int fCombOnly, int fUseOne, int fAllFrames, int fVerbose )
+{
+    Aig_Man_t * pAig;
+    Gia_Man_t * pGia, * pRes;
+    pGia = Gia_ManFromAigSimple( p );
+    if ( !Gia_ManVerifyCex( pGia, pCex, 0 ) )
+    {
+        Abc_Print( 1, "Current CEX does not fail AIG \"%s\".\n", p->pName ); 
+        Gia_ManStop( pGia );
+        return NULL;
+    }
+    pRes = Bmc_GiaTargetStates( pGia, pCex, iFrBeg, iFrEnd, fCombOnly, fUseOne, fAllFrames, fVerbose );
+    Gia_ManStop( pGia );
+    pAig = Gia_ManToAigSimple( pRes );
+    Gia_ManStop( pRes );
+    return pAig;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcCexDepth.c b/abc-build/src/sat/bmc/bmcCexDepth.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcCexDepth.c
@@ -0,0 +1,373 @@
+/**CFile****************************************************************
+
+  FileName    [bmcCexDepth.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    [CEX depth minimization.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcCexDepth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bmc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+extern Abc_Cex_t * Bmc_CexInnerStates( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t ** ppCexImpl, int fVerbose );
+extern Abc_Cex_t * Bmc_CexCareBits( Gia_Man_t * p, Abc_Cex_t * pCexState, Abc_Cex_t * pCexImpl, Abc_Cex_t * pCexEss, int fFindAll, int fVerbose );
+extern int Bmc_CexVerify( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Performs targe enlargement of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Bmc_CexTargetEnlarge( Gia_Man_t * p, int nFrames )
+{
+    Gia_Man_t * pNew, * pOne;
+    Gia_Obj_t * pObj, * pObjRo;
+    int i, k;
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManConst0(p)->Value = 0;
+    for ( k = 0; k < nFrames; k++ )
+        Gia_ManForEachPi( p, pObj, i )
+            Gia_ManAppendCi( pNew );
+    Gia_ManForEachRo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    for ( k = 0; k < nFrames; k++ )
+    {
+        Gia_ManForEachPi( p, pObj, i )
+            pObj->Value = Gia_ManCiLit( pNew, (nFrames - 1 - k) * Gia_ManPiNum(p) + i );
+        Gia_ManForEachAnd( p, pObj, i )
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        Gia_ManForEachRi( p, pObj, i )
+            pObj->Value = Gia_ObjFanin0Copy(pObj);
+        Gia_ManForEachRiRo( p, pObj, pObjRo, i )
+            pObjRo->Value  = pObj->Value;
+    }
+    pObj = Gia_ManPo( p, 0 );
+    pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    Gia_ManHashStop( pNew );
+    pNew = Gia_ManCleanup( pOne = pNew );
+    Gia_ManStop( pOne );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Create target with quantified inputs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Bmc_CexTarget( Gia_Man_t * p, int nFrames )
+{
+    Gia_Man_t * pNew, * pTemp;
+    int i, Limit = nFrames * Gia_ManPiNum(p);
+    pNew = Bmc_CexTargetEnlarge( p, nFrames );
+    for ( i = 0; i < Limit; i++ )
+    {
+        printf( "%3d : ", i );
+        if ( i % Gia_ManPiNum(p) == 0 )
+            Gia_ManPrintStats( pNew, NULL );
+        pNew = Gia_ManDupExist( pTemp = pNew, i );
+        Gia_ManStop( pTemp );
+    }
+    Gia_ManPrintStats( pNew, NULL );
+    pNew = Gia_ManDupLastPis( pTemp = pNew, Gia_ManRegNum(p) );
+    Gia_ManStop( pTemp );  
+    Gia_ManPrintStats( pNew, NULL );
+    pTemp = Gia_ManDupAppendCones( p, &pNew, 1, 1 );
+    Gia_ManStop( pNew );
+    Gia_AigerWrite( pTemp, "miter3.aig", 0, 0 );
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes CE-induced network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Bmc_CexBuildNetwork2( Gia_Man_t * p, Abc_Cex_t * pCex, int fStart )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pObjRo, * pObjRi;
+    int fCompl0, fCompl1;
+    int i, k, iBit;
+    assert( pCex->nRegs == 0 );
+    assert( pCex->nPis == Gia_ManCiNum(p) );
+    assert( fStart <= pCex->iFrame );
+    // start the manager
+    pNew = Gia_ManStart( 1000 );
+    pNew->pName = Abc_UtilStrsav( "unate" );
+    // set const0
+    Gia_ManConst0(p)->fMark0 = 0; // value
+    Gia_ManConst0(p)->fMark1 = 1; // care
+    Gia_ManConst0(p)->Value  = ~0;
+    // set init state
+    Gia_ManForEachRi( p, pObj, k )
+    {
+        pObj->fMark0 = Abc_InfoHasBit( pCex->pData, pCex->nRegs + fStart * Gia_ManCiNum(p) + Gia_ManPiNum(p) + k );
+        pObj->fMark1 = 0;
+        pObj->Value  = Abc_LitNotCond( Gia_ManAppendCi(pNew), !pObj->fMark0 );
+    }
+    Gia_ManHashAlloc( pNew );
+    iBit = pCex->nRegs + fStart * Gia_ManCiNum(p);
+    for ( i = fStart; i <= pCex->iFrame; i++ )
+    {
+        //  primary inputs
+        Gia_ManForEachPi( p, pObj, k )
+        {
+            pObj->fMark0 = Abc_InfoHasBit( pCex->pData, iBit++ );
+            pObj->fMark1 = 1;
+            pObj->Value  = ~0;
+        }
+        iBit += Gia_ManRegNum(p);
+        // transfer 
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
+        {
+            pObjRo->fMark0 = pObjRi->fMark0;
+            pObjRo->fMark1 = pObjRi->fMark1;
+            pObjRo->Value  = pObjRi->Value;
+        }
+        // internal nodes
+        Gia_ManForEachAnd( p, pObj, k )
+        {
+            fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+            fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj);
+            pObj->fMark0 = fCompl0 & fCompl1;
+            if ( pObj->fMark0 )
+                pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 & Gia_ObjFanin1(pObj)->fMark1;
+            else if ( !fCompl0 && !fCompl1 )
+                pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 | Gia_ObjFanin1(pObj)->fMark1;
+            else if ( !fCompl0 )
+                pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1;
+            else if ( !fCompl1 )
+                pObj->fMark1 = Gia_ObjFanin1(pObj)->fMark1;
+            else assert( 0 );
+            pObj->Value = ~0;
+            if ( pObj->fMark1 )
+                continue;
+            if ( pObj->fMark0 )
+                pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value );
+            else if ( !fCompl0 && !fCompl1 )
+                pObj->Value = Gia_ManHashOr( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value );
+            else if ( !fCompl0 )
+                pObj->Value = Gia_ObjFanin0(pObj)->Value;
+            else if ( !fCompl1 )
+                pObj->Value = Gia_ObjFanin1(pObj)->Value;
+            else assert( 0 );
+            assert( pObj->Value > 0 );
+        }
+        // combinational outputs
+        Gia_ManForEachCo( p, pObj, k )
+        {
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+            pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1;
+            pObj->Value  = Gia_ObjFanin0(pObj)->Value;
+        }
+    }
+    Gia_ManHashStop( pNew );
+    assert( iBit == pCex->nBits );
+    // create primary output
+    pObj = Gia_ManPo(p, pCex->iPo);
+    assert( pObj->fMark0 == 1 );
+    assert( pObj->fMark1 == 0 );
+    assert( pObj->Value > 0 );
+    Gia_ManAppendCo( pNew, pObj->Value );
+    // cleanup
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+Gia_Man_t * Bmc_CexBuildNetwork2_( Gia_Man_t * p, Abc_Cex_t * pCex, int fStart )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pObjRo, * pObjRi;
+    int fCompl0, fCompl1;
+    int i, k, iBit;
+    assert( pCex->nRegs == 0 );
+    assert( pCex->nPis == Gia_ManCiNum(p) );
+    assert( fStart <= pCex->iFrame );
+    // start the manager
+    pNew = Gia_ManStart( 1000 );
+    pNew->pName = Abc_UtilStrsav( "unate" );
+    // set const0
+    Gia_ManConst0(p)->fMark0 = 0; // value
+    Gia_ManConst0(p)->Value  = 1;
+    // set init state
+    Gia_ManForEachRi( p, pObj, k )
+    {
+        pObj->fMark0 = Abc_InfoHasBit( pCex->pData, pCex->nRegs + fStart * Gia_ManCiNum(p) + Gia_ManPiNum(p) + k );
+        pObj->Value  = Abc_LitNotCond( Gia_ManAppendCi(pNew), !pObj->fMark0 );
+    }
+    Gia_ManHashAlloc( pNew );
+    iBit = pCex->nRegs + fStart * Gia_ManCiNum(p);
+    for ( i = fStart; i <= pCex->iFrame; i++ )
+    {
+        //  primary inputs
+        Gia_ManForEachPi( p, pObj, k )
+        {
+            pObj->fMark0 = Abc_InfoHasBit( pCex->pData, iBit++ );
+            pObj->Value  = 1;
+        }
+        iBit += Gia_ManRegNum(p);
+        // transfer 
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
+        {
+            pObjRo->fMark0 = pObjRi->fMark0;
+            pObjRo->Value  = pObjRi->Value;
+        }
+        // internal nodes
+        Gia_ManForEachAnd( p, pObj, k )
+        {
+            fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+            fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj);
+            pObj->fMark0 = fCompl0 & fCompl1;
+            if ( pObj->fMark0 )
+                pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value );
+            else if ( !fCompl0 && !fCompl1 )
+                pObj->Value = Gia_ManHashOr( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value );
+            else if ( !fCompl0 )
+                pObj->Value = Gia_ObjFanin0(pObj)->Value;
+            else if ( !fCompl1 )
+                pObj->Value = Gia_ObjFanin1(pObj)->Value;
+            else assert( 0 );
+        }
+        // combinational outputs
+        Gia_ManForEachCo( p, pObj, k )
+        {
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+            pObj->Value  = Gia_ObjFanin0(pObj)->Value;
+        }
+    }
+    Gia_ManHashStop( pNew );
+    assert( iBit == pCex->nBits );
+    // create primary output
+    pObj = Gia_ManPo(p, pCex->iPo);
+    assert( pObj->fMark0 == 1 );
+    assert( pObj->Value > 0 );
+    Gia_ManAppendCo( pNew, pObj->Value );
+    // cleanup
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+Gia_Man_t * Bmc_CexBuildNetwork2Test( Gia_Man_t * p, Abc_Cex_t * pCex, int nFramesMax )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Vec_Ptr_t * vCones;
+    abctime clk = Abc_Clock();
+    int i;
+    nFramesMax = Abc_MinInt( nFramesMax, pCex->iFrame );
+    printf( "Processing CEX in frame %d (max frames %d).\n", pCex->iFrame, nFramesMax );
+    vCones = Vec_PtrAlloc( nFramesMax );
+    for ( i = pCex->iFrame; i > pCex->iFrame - nFramesMax; i-- )
+    {
+        printf( "Frame %5d : ", i );
+        pNew = Bmc_CexBuildNetwork2_( p, pCex, i );
+        Gia_ManPrintStats( pNew, NULL );
+        Vec_PtrPush( vCones, pNew );
+    }
+    pNew = Gia_ManDupAppendCones( p, (Gia_Man_t **)Vec_PtrArray(vCones), Vec_PtrSize(vCones), 1 );
+    Gia_AigerWrite( pNew, "miter2.aig", 0, 0 );
+//Bmc_CexDumpAogStats( pNew, Abc_Clock() - clk );
+    Vec_PtrForEachEntry( Gia_Man_t *, vCones, pTemp, i )
+        Gia_ManStop( pTemp );
+    Vec_PtrFree( vCones );
+    printf( "GIA with additional properties is written into \"miter2.aig\".\n" );
+//    printf( "CE-induced network is written into file \"unate.aig\".\n" );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+//    Gia_ManStop( pNew );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Bmc_CexDepthTest( Gia_Man_t * p, Abc_Cex_t * pCex, int nFrames, int fVerbose )
+{
+    Gia_Man_t * pNew;
+    abctime clk = Abc_Clock();
+    Abc_Cex_t * pCexImpl   = NULL;
+    Abc_Cex_t * pCexStates = Bmc_CexInnerStates( p, pCex, &pCexImpl, fVerbose );
+    Abc_Cex_t * pCexCare   = Bmc_CexCareBits( p, pCexStates, pCexImpl, NULL, 1, fVerbose );
+//    Abc_Cex_t * pCexEss, * pCexMin;
+
+    if ( !Bmc_CexVerify( p, pCex, pCexCare ) )
+        printf( "Counter-example care-set verification has failed.\n" );
+
+//    pCexEss = Bmc_CexEssentialBits( p, pCexStates, pCexCare, fVerbose );
+//    pCexMin = Bmc_CexCareBits( p, pCexStates, pCexImpl, pCexEss, 0, fVerbose );
+
+//    if ( !Bmc_CexVerify( p, pCex, pCexMin ) )
+//        printf( "Counter-example min-set verification has failed.\n" );
+
+//    Bmc_CexDumpStats( p, pCex, pCexCare, pCexEss, pCexMin, Abc_Clock() - clk );
+
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    pNew = Bmc_CexBuildNetwork2Test( p, pCexStates, nFrames );
+//    Bmc_CexPerformUnrollingTest( p, pCex );
+
+    Abc_CexFreeP( &pCexStates );
+    Abc_CexFreeP( &pCexImpl );
+    Abc_CexFreeP( &pCexCare );
+//    Abc_CexFreeP( &pCexEss );
+//    Abc_CexFreeP( &pCexMin );
+    return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcCexMin1.c b/abc-build/src/sat/bmc/bmcCexMin1.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcCexMin1.c
@@ -0,0 +1,578 @@
+/**CFile****************************************************************
+
+  FileName    [bmcCexMin1.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    [CEX minimization.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcCexMin1.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig/ioa/ioa.h"
+#include "bmc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Find the roots to begin traversal.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManCexMinGetCos( Aig_Man_t * pAig, Abc_Cex_t * pCex, Vec_Int_t * vLeaves, Vec_Int_t * vRoots )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Vec_IntClear( vRoots );
+    if ( vLeaves == NULL )
+    {
+        pObj = Aig_ManCo( pAig, pCex->iPo );
+        Vec_IntPush( vRoots, Aig_ObjId(pObj) );
+        return;
+    }
+    Aig_ManForEachObjVec( vLeaves, pAig, pObj, i )
+        if ( Saig_ObjIsLo(pAig, pObj) )
+            Vec_IntPush( vRoots, Aig_ObjId( Saig_ObjLoToLi(pAig, pObj) ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects CI of the given timeframe.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManCexMinCollectFrameTerms_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vFrameCisOne )
+{
+    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(pAig, pObj);
+    if ( Aig_ObjIsCo(pObj) )
+        Saig_ManCexMinCollectFrameTerms_rec( pAig, Aig_ObjFanin0(pObj), vFrameCisOne );
+    else if ( Aig_ObjIsNode(pObj) )
+    {
+        Saig_ManCexMinCollectFrameTerms_rec( pAig, Aig_ObjFanin0(pObj), vFrameCisOne );
+        Saig_ManCexMinCollectFrameTerms_rec( pAig, Aig_ObjFanin1(pObj), vFrameCisOne );
+    }
+    else if ( Aig_ObjIsCi(pObj) )
+        Vec_IntPush( vFrameCisOne, Aig_ObjId(pObj) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects CIs of all timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Saig_ManCexMinCollectFrameTerms( Aig_Man_t * pAig, Abc_Cex_t * pCex )
+{
+    Vec_Vec_t * vFrameCis;
+    Vec_Int_t * vRoots, * vLeaves;
+    Aig_Obj_t * pObj;
+    int i, f;
+    // create terminals
+    vRoots = Vec_IntAlloc( 1000 );
+    vFrameCis = Vec_VecStart( pCex->iFrame+1 );
+    for ( f = pCex->iFrame; f >= 0; f-- )
+    {
+        // create roots
+        vLeaves = (f == pCex->iFrame) ? NULL : Vec_VecEntryInt(vFrameCis, f+1);
+        Saig_ManCexMinGetCos( pAig, pCex, vLeaves, vRoots );
+        // collect nodes starting from the roots
+        Aig_ManIncrementTravId( pAig );
+        Aig_ManForEachObjVec( vRoots, pAig, pObj, i )
+            Saig_ManCexMinCollectFrameTerms_rec( pAig, pObj, Vec_VecEntryInt(vFrameCis, f) );
+    }
+    Vec_IntFree( vRoots );
+    return vFrameCis;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively sets phase and priority.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManCexMinDerivePhasePriority_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj )
+{
+    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(pAig, pObj);
+    if ( Aig_ObjIsCo(pObj) )
+    {
+        Saig_ManCexMinDerivePhasePriority_rec( pAig, Aig_ObjFanin0(pObj) );
+        assert( Aig_ObjFanin0(pObj)->iData >= 0 );
+        pObj->iData = Aig_ObjFanin0(pObj)->iData ^ Aig_ObjFaninC0(pObj);
+    }
+    else if ( Aig_ObjIsNode(pObj) )
+    {
+        int fPhase0, fPhase1, iPrio0, iPrio1;
+        Saig_ManCexMinDerivePhasePriority_rec( pAig, Aig_ObjFanin0(pObj) );
+        Saig_ManCexMinDerivePhasePriority_rec( pAig, Aig_ObjFanin1(pObj) );
+        assert( Aig_ObjFanin0(pObj)->iData >= 0 );
+        assert( Aig_ObjFanin1(pObj)->iData >= 0 );
+        fPhase0 = Abc_LitIsCompl( Aig_ObjFanin0(pObj)->iData ) ^ Aig_ObjFaninC0(pObj);
+        fPhase1 = Abc_LitIsCompl( Aig_ObjFanin1(pObj)->iData ) ^ Aig_ObjFaninC1(pObj);
+        iPrio0  = Abc_Lit2Var( Aig_ObjFanin0(pObj)->iData );
+        iPrio1  = Abc_Lit2Var( Aig_ObjFanin1(pObj)->iData );
+        if ( fPhase0 && fPhase1 ) // both are one
+            pObj->iData = Abc_Var2Lit( Abc_MinInt(iPrio0, iPrio1), 1 );
+        else if ( !fPhase0 && fPhase1 ) 
+            pObj->iData = Abc_Var2Lit( iPrio0, 0 );
+        else if ( fPhase0 && !fPhase1 )
+            pObj->iData = Abc_Var2Lit( iPrio1, 0 );
+        else // both are zero
+            pObj->iData = Abc_Var2Lit( Abc_MaxInt(iPrio0, iPrio1), 0 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verify phase.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManCexMinVerifyPhase( Aig_Man_t * pAig, Abc_Cex_t * pCex, int f )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManConst1(pAig)->fPhase = 1;
+    Saig_ManForEachPi( pAig, pObj, i )
+        pObj->fPhase = Abc_InfoHasBit(pCex->pData, pCex->nRegs + f * pCex->nPis + i);
+    if ( f == 0 )
+    {
+        Saig_ManForEachLo( pAig, pObj, i )
+            pObj->fPhase = 0;
+    }
+    else
+    {
+        Saig_ManForEachLo( pAig, pObj, i )
+            pObj->fPhase = Saig_ObjLoToLi(pAig, pObj)->fPhase;
+    }
+    Aig_ManForEachNode( pAig, pObj, i )
+        pObj->fPhase = (Aig_ObjFaninC0(pObj) ^ Aig_ObjFanin0(pObj)->fPhase) & 
+                       (Aig_ObjFaninC1(pObj) ^ Aig_ObjFanin1(pObj)->fPhase);
+    Aig_ManForEachCo( pAig, pObj, i )
+        pObj->fPhase = (Aig_ObjFaninC0(pObj) ^ Aig_ObjFanin0(pObj)->fPhase);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects phase and priority of all timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManCexMinDerivePhasePriority( Aig_Man_t * pAig, Abc_Cex_t * pCex, Vec_Vec_t * vFrameCis, Vec_Vec_t * vFramePPs, int f, Vec_Int_t * vRoots )
+{
+    Vec_Int_t * vFramePPsOne, * vFrameCisOne, * vLeaves;
+    Aig_Obj_t * pObj;
+    int i;
+    // set PP for the CIs
+    vFrameCisOne = Vec_VecEntryInt( vFrameCis, f );
+    vFramePPsOne = Vec_VecEntryInt( vFramePPs, f );
+    Aig_ManForEachObjVec( vFrameCisOne, pAig, pObj, i )
+    {
+        pObj->iData = Vec_IntEntry( vFramePPsOne, i );
+        assert( pObj->iData >= 0 );
+    }
+//    if ( f == 0 )
+//        Saig_ManCexMinVerifyPhase( pAig, pCex, f );
+
+    // create roots
+    vLeaves = (f == pCex->iFrame) ? NULL : Vec_VecEntryInt(vFrameCis, f+1);
+    Saig_ManCexMinGetCos( pAig, pCex, vLeaves, vRoots );
+    // derive for the nodes starting from the roots
+    Aig_ManIncrementTravId( pAig );
+    Aig_ManForEachObjVec( vRoots, pAig, pObj, i )
+    {
+        Saig_ManCexMinDerivePhasePriority_rec( pAig, pObj );
+//        if ( f == 0 )
+//            assert( (pObj->iData & 1) == pObj->fPhase );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects phase and priority of all timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+Vec_Vec_t * Saig_ManCexMinCollectPhasePriority_( Aig_Man_t * pAig, Abc_Cex_t * pCex, Vec_Vec_t * vFrameCis )
+{
+    Vec_Vec_t * vFramePPs;
+    Vec_Int_t * vRoots, * vFramePPsOne, * vFrameCisOne;
+    Aig_Obj_t * pObj;
+    int i, f, nPrioOffset;
+
+    // initialize phase and priority
+    Aig_ManForEachObj( pAig, pObj, i )
+        pObj->iData = -1;
+
+    // set the constant node to higher priority than the flops
+    vFramePPs = Vec_VecStart( pCex->iFrame+1 );
+    nPrioOffset = (pCex->iFrame + 1) * pCex->nPis;
+    Aig_ManConst1(pAig)->iData = Abc_Var2Lit( nPrioOffset + pCex->nRegs, 1 );
+    vRoots = Vec_IntAlloc( 1000 );
+    for ( f = 0; f <= pCex->iFrame; f++ )
+    {
+        int nPiCount = 0;
+        // fill in PP for the CIs
+        vFrameCisOne = Vec_VecEntryInt( vFrameCis, f );
+        vFramePPsOne = Vec_VecEntryInt( vFramePPs, f );
+        assert( Vec_IntSize(vFramePPsOne) == 0 );
+        Aig_ManForEachObjVec( vFrameCisOne, pAig, pObj, i )
+        {
+            assert( Aig_ObjIsCi(pObj) );
+            if ( Saig_ObjIsPi(pAig, pObj) )
+                Vec_IntPush( vFramePPsOne, Abc_Var2Lit( (f+1) * pCex->nPis - nPiCount++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + f * pCex->nPis + Aig_ObjCioId(pObj)) ) );
+            else if ( f == 0 )
+                Vec_IntPush( vFramePPsOne, Abc_Var2Lit( nPrioOffset + Saig_ObjRegId(pAig, pObj), 0 ) );
+            else
+                Vec_IntPush( vFramePPsOne, Saig_ObjLoToLi(pAig, pObj)->iData );
+        }
+        // compute the PP info
+        Saig_ManCexMinDerivePhasePriority( pAig, pCex, vFrameCis, vFramePPs, f, vRoots );
+    }
+    Vec_IntFree( vRoots );
+    // check the output
+    pObj = Aig_ManCo( pAig, pCex->iPo );
+    assert( Abc_LitIsCompl(pObj->iData) );
+    return vFramePPs;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects phase and priority of all timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+Vec_Vec_t * Saig_ManCexMinCollectPhasePriority( Aig_Man_t * pAig, Abc_Cex_t * pCex, Vec_Vec_t * vFrameCis )
+{
+    Vec_Vec_t * vFramePPs;
+    Vec_Int_t * vRoots, * vFramePPsOne, * vFrameCisOne;
+    Aig_Obj_t * pObj;
+    int i, f, nPrioOffset;
+
+    // initialize phase and priority
+    Aig_ManForEachObj( pAig, pObj, i )
+        pObj->iData = -1;
+
+    // set the constant node to higher priority than the flops
+    vFramePPs = Vec_VecStart( pCex->iFrame+1 );
+    nPrioOffset = pCex->nRegs;
+    Aig_ManConst1(pAig)->iData = Abc_Var2Lit( nPrioOffset + (pCex->iFrame + 1) * pCex->nPis, 1 );
+    vRoots = Vec_IntAlloc( 1000 );
+    for ( f = 0; f <= pCex->iFrame; f++ )
+    {
+        int nPiCount = 0;
+        // fill in PP for the CIs
+        vFrameCisOne = Vec_VecEntryInt( vFrameCis, f );
+        vFramePPsOne = Vec_VecEntryInt( vFramePPs, f );
+        assert( Vec_IntSize(vFramePPsOne) == 0 );
+        Aig_ManForEachObjVec( vFrameCisOne, pAig, pObj, i )
+        {
+            assert( Aig_ObjIsCi(pObj) );
+            if ( Saig_ObjIsPi(pAig, pObj) )
+                Vec_IntPush( vFramePPsOne, Abc_Var2Lit( nPrioOffset + (f+1) * pCex->nPis - 1 - nPiCount++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + f * pCex->nPis + Aig_ObjCioId(pObj)) ) );
+            else if ( f == 0 )
+                Vec_IntPush( vFramePPsOne, Abc_Var2Lit( Saig_ObjRegId(pAig, pObj), 0 ) );
+            else
+                Vec_IntPush( vFramePPsOne, Saig_ObjLoToLi(pAig, pObj)->iData );
+        }
+        // compute the PP info
+        Saig_ManCexMinDerivePhasePriority( pAig, pCex, vFrameCis, vFramePPs, f, vRoots );
+    }
+    Vec_IntFree( vRoots );
+    // check the output
+    pObj = Aig_ManCo( pAig, pCex->iPo );
+    assert( Abc_LitIsCompl(pObj->iData) );
+    return vFramePPs;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns reasons for the property to fail.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Saig_ManCexMinCollectReason_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vReason, int fPiReason )
+{
+    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+        return;
+    Aig_ObjSetTravIdCurrent(p, pObj);
+    if ( Aig_ObjIsCi(pObj) )
+    {
+        if ( fPiReason && Saig_ObjIsPi(p, pObj) )
+            Vec_IntPush( vReason, Abc_Var2Lit( Aig_ObjCioId(pObj), !Abc_LitIsCompl(pObj->iData) ) );
+        else if ( !fPiReason && Saig_ObjIsLo(p, pObj) )
+            Vec_IntPush( vReason, Abc_Var2Lit( Saig_ObjRegId(p, pObj), !Abc_LitIsCompl(pObj->iData) ) );
+        return;
+    }
+    if ( Aig_ObjIsCo(pObj) )
+    {
+        Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin0(pObj), vReason, fPiReason );
+        return;
+    }
+    if ( Aig_ObjIsConst1(pObj) )
+        return;
+    assert( Aig_ObjIsNode(pObj) );
+    if ( Abc_LitIsCompl(pObj->iData) ) // value 1
+    {
+        int fPhase0 = Abc_LitIsCompl( Aig_ObjFanin0(pObj)->iData ) ^ Aig_ObjFaninC0(pObj);
+        int fPhase1 = Abc_LitIsCompl( Aig_ObjFanin1(pObj)->iData ) ^ Aig_ObjFaninC1(pObj);
+        assert( fPhase0 && fPhase1 );
+        Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin0(pObj), vReason, fPiReason );
+        Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin1(pObj), vReason, fPiReason );
+    }
+    else
+    {
+        int fPhase0 = Abc_LitIsCompl( Aig_ObjFanin0(pObj)->iData ) ^ Aig_ObjFaninC0(pObj);
+        int fPhase1 = Abc_LitIsCompl( Aig_ObjFanin1(pObj)->iData ) ^ Aig_ObjFaninC1(pObj);
+        assert( !fPhase0 || !fPhase1 );
+        if ( !fPhase0 && fPhase1 )
+            Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin0(pObj), vReason, fPiReason );
+        else if ( fPhase0 && !fPhase1 )
+            Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin1(pObj), vReason, fPiReason );
+        else 
+        {
+            int iPrio0 = Abc_Lit2Var( Aig_ObjFanin0(pObj)->iData );
+            int iPrio1 = Abc_Lit2Var( Aig_ObjFanin1(pObj)->iData );
+            if ( iPrio0 >= iPrio1 )
+                Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin0(pObj), vReason, fPiReason );
+            else
+                Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin1(pObj), vReason, fPiReason );
+        }
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects phase and priority of all timeframes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Saig_ManCexMinCollectReason( Aig_Man_t * pAig, Abc_Cex_t * pCex, Vec_Vec_t * vFrameCis, Vec_Vec_t * vFramePPs, int fPiReason )
+{
+    Vec_Vec_t * vFrameReas;
+    Vec_Int_t * vRoots, * vLeaves;
+    Aig_Obj_t * pObj;
+    int i, f;
+    // select reason for the property to fail
+    vFrameReas = Vec_VecStart( pCex->iFrame+1 );
+    vRoots = Vec_IntAlloc( 1000 );
+    for ( f = pCex->iFrame; f >= 0; f-- )
+    {
+        // set phase and polarity
+        Saig_ManCexMinDerivePhasePriority( pAig, pCex, vFrameCis, vFramePPs, f, vRoots );
+        // create roots
+        vLeaves = (f == pCex->iFrame) ? NULL : Vec_VecEntryInt(vFrameCis, f+1);
+        Saig_ManCexMinGetCos( pAig, pCex, vLeaves, vRoots );
+        // collect nodes starting from the roots
+        Aig_ManIncrementTravId( pAig );
+        Aig_ManForEachObjVec( vRoots, pAig, pObj, i )
+            Saig_ManCexMinCollectReason_rec( pAig, pObj, Vec_VecEntryInt(vFrameReas, f), fPiReason );
+//printf( "%d(%d) ", Vec_VecLevelSize(vFrameCis, f), Vec_VecLevelSize(vFrameReas, f) ); 
+    }
+//printf( "\n" );
+    Vec_IntFree( vRoots );
+    return vFrameReas;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Vec_t * Saig_ManCexMinComputeReason( Aig_Man_t * pAig, Abc_Cex_t * pCex, int fPiReason )
+{
+    Vec_Vec_t * vFrameCis, * vFramePPs, * vFrameReas;
+    // sanity checks
+    assert( pCex->nPis == Saig_ManPiNum(pAig) );
+    assert( pCex->nRegs == Saig_ManRegNum(pAig) );
+    assert( pCex->iPo >= 0 && pCex->iPo < Saig_ManPoNum(pAig) );
+    // derive frame terms
+    vFrameCis = Saig_ManCexMinCollectFrameTerms( pAig, pCex );
+    // derive phase and priority
+    vFramePPs = Saig_ManCexMinCollectPhasePriority( pAig, pCex, vFrameCis );
+    // derive reasons for property failure
+    vFrameReas = Saig_ManCexMinCollectReason( pAig, pCex, vFrameCis, vFramePPs, fPiReason );
+    Vec_VecFree( vFramePPs );
+    Vec_VecFree( vFrameCis );
+    return vFrameReas;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicate with literals.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManCexMinDupWithCubes( Aig_Man_t * pAig, Vec_Vec_t * vReg2Value )
+{
+    Vec_Int_t * vLevel;
+    Aig_Man_t * pAigNew;
+    Aig_Obj_t * pObj, * pMiter;
+    int i, k, Lit;
+    assert( pAig->nConstrs == 0 );
+    // start the new manager
+    pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) + Vec_VecSizeSize(vReg2Value) + Vec_VecSize(vReg2Value) );
+    pAigNew->pName = Abc_UtilStrsav( pAig->pName );
+    // map the constant node
+    Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew );
+    // create variables for PIs
+    Aig_ManForEachCi( pAig, pObj, i )
+        pObj->pData = Aig_ObjCreateCi( pAigNew );
+    // add internal nodes of this frame
+    Aig_ManForEachNode( pAig, pObj, i )
+        pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+    // create POs for cubes
+    Vec_VecForEachLevelInt( vReg2Value, vLevel, i )
+    {
+        if ( i == 0 )
+            continue;
+        pMiter = Aig_ManConst1( pAigNew );
+        Vec_IntForEachEntry( vLevel, Lit, k )
+        {
+            assert( Lit >= 0 && Lit < 2 * Aig_ManRegNum(pAig) );
+            pObj = Saig_ManLi( pAig, Abc_Lit2Var(Lit) );
+            pMiter = Aig_And( pAigNew, pMiter, Aig_NotCond(Aig_ObjChild0Copy(pObj), Abc_LitIsCompl(Lit)) );
+        }
+        Aig_ObjCreateCo( pAigNew, pMiter );
+    }
+    // transfer to register outputs
+    Saig_ManForEachLi( pAig, pObj, i )
+        Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) );
+    // finalize
+    Aig_ManCleanup( pAigNew );
+    Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) );
+    return pAigNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Saig_ManCexMinPerform( Aig_Man_t * pAig, Abc_Cex_t * pCex )
+{
+    int fReasonPi = 0;
+
+    Abc_Cex_t * pCexMin = NULL;
+    Aig_Man_t * pManNew = NULL;
+    Vec_Vec_t * vFrameReas;
+    vFrameReas = Saig_ManCexMinComputeReason( pAig, pCex, fReasonPi );
+    printf( "Reason size = %d.  Ave = %d.\n", Vec_VecSizeSize(vFrameReas), Vec_VecSizeSize(vFrameReas)/(pCex->iFrame + 1) );
+
+    // try reducing the frames
+    if ( !fReasonPi )
+    {
+        char * pFileName = "aigcube.aig";
+        pManNew = Saig_ManCexMinDupWithCubes( pAig, vFrameReas );
+        Ioa_WriteAiger( pManNew, pFileName, 0, 0 );
+        Aig_ManStop( pManNew );
+        printf( "Intermediate AIG is written into file \"%s\".\n", pFileName );
+    }
+
+    // find reduced counter-example
+    Vec_VecFree( vFrameReas );
+    return pCexMin;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcCexMin2.c b/abc-build/src/sat/bmc/bmcCexMin2.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcCexMin2.c
@@ -0,0 +1,363 @@
+/**CFile****************************************************************
+
+  FileName    [bmcCexMin2.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    [CEX minimization.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcCexMin2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig/gia/gia.h"
+#include "bmc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int  Abc_InfoGet2Bits( Vec_Int_t * vData, int nWords, int iFrame, int iObj )
+{
+    unsigned * pInfo = (unsigned *)Vec_IntEntryP( vData, nWords * iFrame );
+    return 3 & (pInfo[iObj >> 4] >> ((iObj & 15) << 1));
+}
+static inline void Abc_InfoSet2Bits( Vec_Int_t * vData, int nWords, int iFrame, int iObj, int Value )
+{
+    unsigned * pInfo = (unsigned *)Vec_IntEntryP( vData, nWords * iFrame );
+    Value ^= (3 & (pInfo[iObj >> 4] >> ((iObj & 15) << 1)));
+    pInfo[iObj >> 4] ^= (Value << ((iObj & 15) << 1));
+}
+static inline void Abc_InfoAdd2Bits( Vec_Int_t * vData, int nWords, int iFrame, int iObj, int Value )
+{
+    unsigned * pInfo = (unsigned *)Vec_IntEntryP( vData, nWords * iFrame );
+    pInfo[iObj >> 4] |= (Value << ((iObj & 15) << 1));
+}
+
+static inline int  Gia_ManGetTwo( Gia_Man_t * p, int iFrame, Gia_Obj_t * pObj )              { return Abc_InfoGet2Bits( p->vTruths, p->nTtWords, iFrame, Gia_ObjId(p, pObj) ); }
+static inline void Gia_ManSetTwo( Gia_Man_t * p, int iFrame, Gia_Obj_t * pObj, int Value )   { Abc_InfoSet2Bits( p->vTruths, p->nTtWords, iFrame, Gia_ObjId(p, pObj), Value ); }
+static inline void Gia_ManAddTwo( Gia_Man_t * p, int iFrame, Gia_Obj_t * pObj, int Value )   { Abc_InfoAdd2Bits( p->vTruths, p->nTtWords, iFrame, Gia_ObjId(p, pObj), Value ); }
+
+/*
+    For CEX minimization, all terminals (const0, PI, RO in frame0) have equal priority.
+    For abstraction refinement, all terminals, except PPis, have higher priority.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Annotates the unrolling with CEX value/priority.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManAnnotateUnrolling( Gia_Man_t * p, Abc_Cex_t * pCex, int fJustMax )
+{
+    Gia_Obj_t * pObj, * pObjRi, * pObjRo;
+    int RetValue, f, k, Value, Value0, Value1, iBit;
+    // start storage for internal info
+    assert( p->vTruths == NULL );
+    p->nTtWords = Abc_BitWordNum( 2 * Gia_ManObjNum(p) );
+    p->vTruths  = Vec_IntStart( (pCex->iFrame + 1) * p->nTtWords );
+    // assign values to all objects (const0 and RO in frame0 are assigned 0)
+    Gia_ManCleanMark0(p);
+    for ( f = 0, iBit = pCex->nRegs; f <= pCex->iFrame; f++ )
+    {
+        Gia_ManForEachPi( p, pObj, k )
+            if ( (pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++)) )
+                Gia_ManAddTwo( p, f, pObj, 1 );
+        Gia_ManForEachAnd( p, pObj, k )
+            if ( (pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj))) )
+                Gia_ManAddTwo( p, f, pObj, 1 );
+        Gia_ManForEachCo( p, pObj, k )
+            if ( (pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) )
+                Gia_ManAddTwo( p, f, pObj, 1 );
+        if ( f == pCex->iFrame )
+            break;
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
+            if ( (pObjRo->fMark0 = pObjRi->fMark0) )
+                Gia_ManAddTwo( p, f+1, pObjRo, 1 );
+    }
+    assert( iBit == pCex->nBits );
+    // check the output value
+    RetValue = Gia_ManPo(p, pCex->iPo)->fMark0;
+    if ( RetValue != 1 )
+        printf( "Counter-example is invalid.\n" );
+    // assign justification to nodes
+    Gia_ManCleanMark0(p);
+    pObj = Gia_ManPo(p, pCex->iPo);
+    pObj->fMark0 = 1;
+    Gia_ManAddTwo( p, pCex->iFrame, pObj, 2 );
+    for ( f = pCex->iFrame; f >= 0; f-- )
+    {
+        // transfer to CO drivers
+        Gia_ManForEachCo( p, pObj, k )
+            if ( (Gia_ObjFanin0(pObj)->fMark0 = pObj->fMark0) )
+            {
+                pObj->fMark0 = 0;
+                Gia_ManAddTwo( p, f, Gia_ObjFanin0(pObj), 2 );
+            }
+        // compute justification
+        Gia_ManForEachAndReverse( p, pObj, k )
+        {
+            if ( !pObj->fMark0 ) 
+                continue;
+            pObj->fMark0 = 0;
+            Value = (1 & Gia_ManGetTwo(p, f, pObj));
+            Value0 = (1 & Gia_ManGetTwo(p, f, Gia_ObjFanin0(pObj))) ^ Gia_ObjFaninC0(pObj);
+            Value1 = (1 & Gia_ManGetTwo(p, f, Gia_ObjFanin1(pObj))) ^ Gia_ObjFaninC1(pObj);
+            if ( Value0 == Value1 )
+            {
+                assert( Value == (Value0 & Value1) );
+                if ( fJustMax || Value == 1 )
+                {
+                    Gia_ObjFanin0(pObj)->fMark0 = Gia_ObjFanin1(pObj)->fMark0 = 1;
+                    Gia_ManAddTwo( p, f, Gia_ObjFanin0(pObj), 2 );
+                    Gia_ManAddTwo( p, f, Gia_ObjFanin1(pObj), 2 );
+                }
+                else
+                {
+                    Gia_ObjFanin0(pObj)->fMark0 = 1;
+                    Gia_ManAddTwo( p, f, Gia_ObjFanin0(pObj), 2 );
+                }
+            }
+            else if ( Value0 == 0 )
+            {
+                assert( Value == 0 );
+                Gia_ObjFanin0(pObj)->fMark0 = 1;
+                Gia_ManAddTwo( p, f, Gia_ObjFanin0(pObj), 2 );
+            }
+            else if ( Value1 == 0 )
+            {
+                assert( Value == 0 );
+                Gia_ObjFanin1(pObj)->fMark0 = 1;
+                Gia_ManAddTwo( p, f, Gia_ObjFanin1(pObj), 2 );
+            }
+            else assert( 0 );
+        }
+        if ( f == 0 )
+            break;
+        // transfer to RIs
+        Gia_ManForEachPi( p, pObj, k )
+            pObj->fMark0 = 0;
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
+            if ( (pObjRi->fMark0 = pObjRo->fMark0) )
+            {
+                pObjRo->fMark0 = 0;
+                Gia_ManAddTwo( p, f-1, pObjRi, 2 );
+            }
+    }
+    Gia_ManCleanMark0(p);
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computing AIG characterizing all justifying assignments.]
+
+  Description [Used in CEX minimization.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManCreateUnate( Gia_Man_t * p, Abc_Cex_t * pCex, int iFrame, int nRealPis, int fUseAllObjects )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pObjRo, * pObjRi;
+    int f, k, Value;
+    assert( iFrame >= 0 && iFrame <= pCex->iFrame );
+    pNew = Gia_ManStart( 1000 );
+    pNew->pName = Abc_UtilStrsav( "unate" );
+    Gia_ManCleanValue( p );
+    // set flop outputs
+    if ( nRealPis < 0 ) // CEX min
+    {
+        Gia_ManForEachRo( p, pObj, k )
+        {
+            if ( fUseAllObjects )
+            {
+                int Value = Gia_ManAppendCi(pNew);
+                if ( (Gia_ManGetTwo(p, iFrame, pObj) >> 1) ) // in the path
+                    pObj->Value = Value;
+            }
+            else if ( (Gia_ManGetTwo(p, iFrame, pObj) >> 1) ) // in the path
+                pObj->Value = Gia_ManAppendCi(pNew);
+        }
+    }
+    else
+    {
+        Gia_ManForEachRo( p, pObj, k )
+            pObj->Value = (Gia_ManGetTwo(p, iFrame, pObj) >> 1);
+    }
+    Gia_ManHashAlloc( pNew );
+    for ( f = iFrame; f <= pCex->iFrame; f++ )
+    {
+/*
+        printf( "  F%03d ", f );
+        Gia_ManForEachRo( p, pObj, k )
+            printf( "%d", pObj->Value > 0 );
+        printf( "\n" );
+*/
+        // set const0 to const1 if present
+        pObj = Gia_ManConst0(p);
+        pObj->Value = (Gia_ManGetTwo(p, f, pObj) >> 1);
+        // set primary inputs 
+        if ( nRealPis < 0 ) // CEX min
+        {
+            Gia_ManForEachPi( p, pObj, k )
+                pObj->Value = (Gia_ManGetTwo(p, f, pObj) >> 1);
+        }
+        else
+        {
+            Gia_ManForEachPi( p, pObj, k )
+            {
+                pObj->Value = (Gia_ManGetTwo(p, f, pObj) >> 1);
+                if ( k >= nRealPis )
+                {
+                    if ( fUseAllObjects )
+                    {
+                        int Value = Gia_ManAppendCi(pNew);
+                        if ( (Gia_ManGetTwo(p, f, pObj) >> 1) ) // in the path
+                            pObj->Value = Value;
+                    }
+                    else if ( (Gia_ManGetTwo(p, f, pObj) >> 1) ) // in the path
+                        pObj->Value = Gia_ManAppendCi(pNew);
+                }
+            }
+        }
+        // traverse internal nodes
+        Gia_ManForEachAnd( p, pObj, k )
+        { 
+            pObj->Value = 0;
+            Value = Gia_ManGetTwo(p, f, pObj);
+            if ( !(Value >> 1) ) // not in the path
+                continue;
+            if ( Gia_ObjFanin0(pObj)->Value && Gia_ObjFanin1(pObj)->Value )
+            {
+                if ( 1 & Gia_ManGetTwo(p, f, pObj) ) // value 1
+                {
+                    if ( Gia_ObjFanin0(pObj)->Value > 1 && Gia_ObjFanin1(pObj)->Value > 1 )
+                        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value );
+                    else if ( Gia_ObjFanin0(pObj)->Value > 1 )
+                        pObj->Value = Gia_ObjFanin0(pObj)->Value;
+                    else if ( Gia_ObjFanin1(pObj)->Value > 1 )
+                        pObj->Value = Gia_ObjFanin1(pObj)->Value;
+                    else 
+                        pObj->Value = 1;
+                }
+                else // value 0
+                {
+                    if ( Gia_ObjFanin0(pObj)->Value > 1 && Gia_ObjFanin1(pObj)->Value > 1 )
+                        pObj->Value = Gia_ManHashOr( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value );
+                    else if ( Gia_ObjFanin0(pObj)->Value > 1 )
+                        pObj->Value = Gia_ObjFanin0(pObj)->Value;
+                    else if ( Gia_ObjFanin1(pObj)->Value > 1 )
+                        pObj->Value = Gia_ObjFanin1(pObj)->Value;
+                    else 
+                        pObj->Value = 1;
+                }
+            }
+            else if ( Gia_ObjFanin0(pObj)->Value )
+                pObj->Value = Gia_ObjFanin0(pObj)->Value;
+            else if ( Gia_ObjFanin1(pObj)->Value )
+                pObj->Value = Gia_ObjFanin1(pObj)->Value;
+            else assert( 0 );
+        }
+        Gia_ManForEachCo( p, pObj, k )
+            pObj->Value = Gia_ObjFanin0(pObj)->Value;
+        if ( f == pCex->iFrame )
+            break;
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
+            pObjRo->Value = pObjRi->Value;
+    }
+    Gia_ManHashStop( pNew );
+    // create primary output
+    pObj = Gia_ManPo(p, pCex->iPo);
+    assert( (Gia_ManGetTwo(p, pCex->iFrame, pObj) >> 1) );
+    assert( pObj->Value );
+    Gia_ManAppendCo( pNew, pObj->Value );
+    // cleanup
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Gia_ManCexMin( Gia_Man_t * p, Abc_Cex_t * pCex, int iFrameStart, int nRealPis, int fJustMax, int fUseAll, int fVerbose )
+{
+    Gia_Man_t * pNew;
+    int f, RetValue;
+    // check CEX
+    assert( pCex->nPis == Gia_ManPiNum(p) );
+//    assert( pCex->nRegs == Gia_ManRegNum(p) );
+    assert( pCex->iPo < Gia_ManPoNum(p) );
+    // check frames
+    assert( iFrameStart >= 0 && iFrameStart <= pCex->iFrame );
+    // check primary inputs
+    assert( nRealPis < Gia_ManPiNum(p) );
+    // prepare
+    RetValue = Gia_ManAnnotateUnrolling( p, pCex, fJustMax );
+    if ( nRealPis >= 0 ) // refinement
+    {
+        pNew = Gia_ManCreateUnate( p, pCex, iFrameStart, nRealPis, fUseAll );
+        printf( "%3d : ", iFrameStart );
+        Gia_ManPrintStats( pNew, NULL );
+        if ( fVerbose )
+            Gia_AigerWrite( pNew, "temp.aig", 0, 0 );
+        Gia_ManStop( pNew );
+    }
+    else // CEX min
+    {
+        for ( f = pCex->iFrame; f >= iFrameStart; f-- )
+        {
+            pNew = Gia_ManCreateUnate( p, pCex, f, -1, fUseAll );
+            printf( "%3d : ", f );
+            Gia_ManPrintStats( pNew, NULL );
+            if ( fVerbose )
+                Gia_AigerWrite( pNew, "temp.aig", 0, 0 );
+            Gia_ManStop( pNew );
+        }
+    }
+    Vec_IntFreeP( &p->vTruths );
+    p->nTtWords = 0;
+    return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcCexTools.c b/abc-build/src/sat/bmc/bmcCexTools.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcCexTools.c
@@ -0,0 +1,852 @@
+/**CFile****************************************************************
+
+  FileName    [bmcCexTools.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    [CEX analysis and optimization toolbox.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcCexTools.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bmc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline word Bmc_CexBitMask( int iBit )                                    { assert( iBit < 64 ); return ~(((word)1) << iBit); }
+static inline void Bmc_CexCopySim( Vec_Wrd_t * vSims, int iObjTo, int iObjFrom ) { Vec_WrdWriteEntry( vSims, iObjTo, iObjFrom );     }
+static inline void Bmc_CexAndSim( Vec_Wrd_t * vSims, int iObjTo, int i, int j )  { Vec_WrdWriteEntry( vSims, iObjTo, Vec_WrdEntry(vSims, i) & Vec_WrdEntry(vSims, j) ); }
+static inline void Bmc_CexOrSim( Vec_Wrd_t * vSims, int iObjTo, int i, int j )   { Vec_WrdWriteEntry( vSims, iObjTo, Vec_WrdEntry(vSims, i) | Vec_WrdEntry(vSims, j) ); }
+static inline int  Bmc_CexSim( Vec_Wrd_t * vSims, int iObj, int i )              { return (Vec_WrdEntry(vSims, iObj) >> i) & 1;      }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bmc_CexBitCount( Abc_Cex_t * p, int nInputs )
+{
+    int k, Counter = 0, Counter2 = 0;
+    if ( p == NULL )
+    {
+        printf( "The counter example is NULL.\n" );
+        return -1;
+    }
+    for ( k = 0; k < p->nBits; k++ )
+    {
+        Counter += Abc_InfoHasBit(p->pData, k);
+        if ( (k - p->nRegs) % p->nPis < nInputs )
+            Counter2 += Abc_InfoHasBit(p->pData, k);
+    }
+    return Counter2;
+}
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bmc_CexDumpStats( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare, Abc_Cex_t * pCexEss, Abc_Cex_t * pCexMin, abctime clk )
+{
+    int nInputs    = Gia_ManPiNum(p);
+    int nBitsTotal = (pCex->iFrame + 1) * nInputs;
+    int nBitsCare  = Bmc_CexBitCount(pCexCare, nInputs);
+    int nBitsDC    = nBitsTotal - nBitsCare;
+    int nBitsEss   = Bmc_CexBitCount(pCexEss, nInputs);
+    int nBitsOpt   = nBitsCare - nBitsEss;
+    int nBitsMin   = Bmc_CexBitCount(pCexMin, nInputs);
+
+    FILE * pTable  = fopen( "cex/stats.txt", "a+" );
+    fprintf( pTable, "%s ", p->pName );
+    fprintf( pTable, "%d ", nInputs );
+    fprintf( pTable, "%d ", Gia_ManRegNum(p) );
+    fprintf( pTable, "%d ", pCex->iFrame + 1 );
+    fprintf( pTable, "%d ", nBitsTotal );
+    fprintf( pTable, "%.2f ", 100.0 * nBitsDC  / nBitsTotal );
+    fprintf( pTable, "%.2f ", 100.0 * nBitsOpt / nBitsTotal );
+    fprintf( pTable, "%.2f ", 100.0 * nBitsEss / nBitsTotal );
+    fprintf( pTable, "%.2f ", 100.0 * nBitsMin / nBitsTotal );
+    fprintf( pTable, "%.2f ", 1.0*clk/(CLOCKS_PER_SEC) );
+    fprintf( pTable, "\n" );
+    fclose( pTable );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bmc_CexDumpAogStats( Gia_Man_t * p, abctime clk )
+{
+    FILE * pTable  = fopen( "cex/aig_stats.txt", "a+" );
+    fprintf( pTable, "%s ", p->pName );
+    fprintf( pTable, "%d ", Gia_ManPiNum(p) );
+    fprintf( pTable, "%d ", Gia_ManAndNum(p) );
+    fprintf( pTable, "%d ", Gia_ManLevelNum(p) );
+    fprintf( pTable, "%.2f ", 1.0*clk/(CLOCKS_PER_SEC) );
+    fprintf( pTable, "\n" );
+    fclose( pTable );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs initialized unrolling till the last frame.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Bmc_CexPerformUnrolling( Gia_Man_t * p, Abc_Cex_t * pCex )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pObjRo, * pObjRi;
+    int i, k;
+    assert( Gia_ManRegNum(p) > 0 );
+    pNew = Gia_ManStart( (pCex->iFrame + 1) * Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachRi( p, pObj, k )
+        pObj->Value = 0;
+    Gia_ManHashAlloc( pNew );
+    for ( i = 0; i <= pCex->iFrame; i++ )
+    {
+        Gia_ManForEachPi( p, pObj, k )
+            pObj->Value = Gia_ManAppendCi( pNew );
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
+            pObjRo->Value = pObjRi->Value;
+        Gia_ManForEachAnd( p, pObj, k )
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        Gia_ManForEachCo( p, pObj, k )
+            pObj->Value = Gia_ObjFanin0Copy(pObj);
+    }
+    Gia_ManHashStop( pNew );
+    pObj = Gia_ManPo(p, pCex->iPo);
+    Gia_ManAppendCo( pNew, pObj->Value );
+    // cleanup
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+void Bmc_CexPerformUnrollingTest( Gia_Man_t * p, Abc_Cex_t * pCex )
+{
+    Gia_Man_t * pNew;
+    abctime clk = Abc_Clock();
+    pNew = Bmc_CexPerformUnrolling( p, pCex );
+    Gia_ManPrintStats( pNew, NULL );
+    Gia_AigerWrite( pNew, "unroll.aig", 0, 0 );
+//Bmc_CexDumpAogStats( pNew, Abc_Clock() - clk );
+    Gia_ManStop( pNew );
+    printf( "CE-induced network is written into file \"unroll.aig\".\n" );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes CE-induced network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Bmc_CexBuildNetwork( Gia_Man_t * p, Abc_Cex_t * pCex )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj, * pObjRo, * pObjRi;
+    int fCompl0, fCompl1;
+    int i, k, iBit = pCex->nRegs;
+    // start the manager
+    pNew = Gia_ManStart( 1000 );
+    pNew->pName = Abc_UtilStrsav( "unate" );
+    // set const0
+    Gia_ManConst0(p)->fMark0 = 0;
+    Gia_ManConst0(p)->fMark1 = 1;
+    Gia_ManConst0(p)->Value  = ~0;
+    // set init state
+    Gia_ManForEachRi( p, pObj, k )
+    {
+        pObj->fMark0 = 0;
+        pObj->fMark1 = 1;
+        pObj->Value  = ~0;
+    }
+    Gia_ManHashAlloc( pNew );
+    for ( i = 0; i <= pCex->iFrame; i++ )
+    {
+        //  primary inputs
+        Gia_ManForEachPi( p, pObj, k )
+        {
+            pObj->fMark0 = Abc_InfoHasBit( pCex->pData, iBit++ );
+            pObj->fMark1 = 0;
+            pObj->Value  = Gia_ManAppendCi(pNew);
+        }
+        // transfer 
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
+        {
+            pObjRo->fMark0 = pObjRi->fMark0;
+            pObjRo->fMark1 = pObjRi->fMark1;
+            pObjRo->Value  = pObjRi->Value;
+        }
+        // internal nodes
+        Gia_ManForEachAnd( p, pObj, k )
+        {
+            fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+            fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj);
+            pObj->fMark0 = fCompl0 & fCompl1;
+            if ( pObj->fMark0 )
+                pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 & Gia_ObjFanin1(pObj)->fMark1;
+            else if ( !fCompl0 && !fCompl1 )
+                pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 | Gia_ObjFanin1(pObj)->fMark1;
+            else if ( !fCompl0 )
+                pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1;
+            else if ( !fCompl1 )
+                pObj->fMark1 = Gia_ObjFanin1(pObj)->fMark1;
+            else assert( 0 );
+            pObj->Value = ~0;
+            if ( pObj->fMark1 )
+                continue;
+            if ( pObj->fMark0 )
+                pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value );
+            else if ( !fCompl0 && !fCompl1 )
+                pObj->Value = Gia_ManHashOr( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value );
+            else if ( !fCompl0 )
+                pObj->Value = Gia_ObjFanin0(pObj)->Value;
+            else if ( !fCompl1 )
+                pObj->Value = Gia_ObjFanin1(pObj)->Value;
+            else assert( 0 );
+            assert( pObj->Value > 0 );
+        }
+        // combinational outputs
+        Gia_ManForEachCo( p, pObj, k )
+        {
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+            pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1;
+            pObj->Value  = Gia_ObjFanin0(pObj)->Value;
+        }
+    }
+    Gia_ManHashStop( pNew );
+    assert( iBit == pCex->nBits );
+    // create primary output
+    pObj = Gia_ManPo(p, pCex->iPo);
+    assert( pObj->fMark0 == 1 );
+    assert( pObj->fMark1 == 0 );
+    assert( pObj->Value > 0 );
+    Gia_ManAppendCo( pNew, pObj->Value );
+    // cleanup
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    return pNew;
+}
+void Bmc_CexBuildNetworkTest( Gia_Man_t * p, Abc_Cex_t * pCex )
+{
+    Gia_Man_t * pNew;
+    abctime clk = Abc_Clock();
+    pNew = Bmc_CexBuildNetwork( p, pCex );
+    Gia_ManPrintStats( pNew, NULL );
+    Gia_AigerWrite( pNew, "unate.aig", 0, 0 );
+//Bmc_CexDumpAogStats( pNew, Abc_Clock() - clk );
+    Gia_ManStop( pNew );
+    printf( "CE-induced network is written into file \"unate.aig\".\n" );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints one counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bmc_CexPrint( Abc_Cex_t * pCex, int nInputs, int fVerbose )
+{
+    int i, k, Count, iBit = 0;
+    Abc_CexPrintStatsInputs( pCex, nInputs );
+    if ( !fVerbose )
+        return;
+
+    for ( i = 0; i <= pCex->iFrame; i++ )
+    {
+        Count = 0;
+        printf( "%3d : ", i );
+        for ( k = 0; k < nInputs; k++ )
+        {
+            Count += Abc_InfoHasBit(pCex->pData, iBit);
+            printf( "%d", Abc_InfoHasBit(pCex->pData, iBit++) );
+        }
+        printf( " %3d ", Count );
+        Count = 0;
+        for (      ; k < pCex->nPis; k++ )
+        {
+            Count += Abc_InfoHasBit(pCex->pData, iBit);
+            printf( "%d", Abc_InfoHasBit(pCex->pData, iBit++) );
+        }
+        printf( " %3d\n", Count );
+    }
+    assert( iBit == pCex->nBits );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the care set of the counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bmc_CexVerify( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare )
+{
+    Gia_Obj_t * pObj;
+    int i, k;
+    assert( pCex->nRegs > 0 );
+//    assert( pCexCare->nRegs == 0 );
+    Gia_ObjTerSimSet0( Gia_ManConst0(p) );
+    Gia_ManForEachRi( p, pObj, k )
+        Gia_ObjTerSimSet0( pObj );
+    for ( i = 0; i <= pCex->iFrame; i++ )
+    {
+        Gia_ManForEachPi( p, pObj, k )
+        {
+            if ( !Abc_InfoHasBit( pCexCare->pData, pCexCare->nRegs + i * pCexCare->nPis + k ) )
+                Gia_ObjTerSimSetX( pObj );
+            else if ( Abc_InfoHasBit( pCex->pData, pCex->nRegs + i * pCex->nPis + k ) )
+                Gia_ObjTerSimSet1( pObj );
+            else
+                Gia_ObjTerSimSet0( pObj );
+        }
+        Gia_ManForEachRo( p, pObj, k )
+            Gia_ObjTerSimRo( p, pObj );
+        Gia_ManForEachAnd( p, pObj, k )
+            Gia_ObjTerSimAnd( pObj );
+        Gia_ManForEachCo( p, pObj, k )
+            Gia_ObjTerSimCo( pObj );
+    }
+    pObj = Gia_ManPo( p, pCex->iPo );
+    return Gia_ObjTerSimGet1(pObj);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes internal states of the CEX.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Bmc_CexInnerStates( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t ** ppCexImpl, int fVerbose )
+{
+    Abc_Cex_t * pNew, * pNew2;
+    Gia_Obj_t * pObj, * pObjRo, * pObjRi;
+    int fCompl0, fCompl1;
+    int i, k, iBit = 0;
+    assert( pCex->nRegs > 0 );
+    // start the counter-example
+    pNew = Abc_CexAlloc( 0, Gia_ManCiNum(p), pCex->iFrame + 1 );
+    pNew->iFrame = pCex->iFrame;
+    pNew->iPo    = pCex->iPo;
+    // start the counter-example
+    pNew2 = Abc_CexAlloc( 0, Gia_ManCiNum(p), pCex->iFrame + 1 );
+    pNew2->iFrame = pCex->iFrame;
+    pNew2->iPo    = pCex->iPo;
+    // set initial state
+    Gia_ManCleanMark01(p);
+    // set const0
+    Gia_ManConst0(p)->fMark0 = 0;
+    Gia_ManConst0(p)->fMark1 = 1;
+    // set init state
+    Gia_ManForEachRi( p, pObjRi, k )
+    {
+        pObjRi->fMark0 = 0;
+        pObjRi->fMark1 = 1;
+    }
+    iBit = pCex->nRegs;
+    for ( i = 0; i <= pCex->iFrame; i++ )
+    {
+        Gia_ManForEachPi( p, pObj, k )
+            pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++);
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
+        {
+            pObjRo->fMark0 = pObjRi->fMark0;
+            pObjRo->fMark1 = pObjRi->fMark1;
+        }
+        Gia_ManForEachCi( p, pObj, k )
+        {
+            if ( pObj->fMark0 )
+                Abc_InfoSetBit( pNew->pData, pNew->nPis * i + k );
+            if ( pObj->fMark1 )
+                Abc_InfoSetBit( pNew2->pData, pNew2->nPis * i + k );
+        }
+        Gia_ManForEachAnd( p, pObj, k )
+        {
+            fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+            fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj);
+            pObj->fMark0 = fCompl0 & fCompl1;
+            if ( pObj->fMark0 )
+                pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 & Gia_ObjFanin1(pObj)->fMark1;
+            else if ( !fCompl0 && !fCompl1 )
+                pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 | Gia_ObjFanin1(pObj)->fMark1;
+            else if ( !fCompl0 )
+                pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1;
+            else if ( !fCompl1 )
+                pObj->fMark1 = Gia_ObjFanin1(pObj)->fMark1;
+            else assert( 0 );
+        }
+        Gia_ManForEachCo( p, pObj, k )
+        {
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+            pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1;
+        }
+
+/*
+        // print input/state/output
+        printf( "%3d : ", i );
+        Gia_ManForEachPi( p, pObj, k )
+            printf( "%d", pObj->fMark0 );
+        printf( " " );
+        Gia_ManForEachRo( p, pObj, k )
+            printf( "%d", pObj->fMark0 );
+        printf( " " );
+        Gia_ManForEachPo( p, pObj, k )
+            printf( "%d", pObj->fMark0 );
+        printf( "\n" );
+*/
+    }
+    assert( iBit == pCex->nBits );
+    assert( Gia_ManPo(p, pCex->iPo)->fMark0 == 1 );
+
+    printf( "Inner states: " );
+    Bmc_CexPrint( pNew, Gia_ManPiNum(p), fVerbose );
+    printf( "Implications: " );
+    Bmc_CexPrint( pNew2, Gia_ManPiNum(p), fVerbose );
+    if ( ppCexImpl )
+        *ppCexImpl = pNew2;
+    else
+        Abc_CexFree( pNew2 );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes care bits of the CEX.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bmc_CexCareBits_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    int fCompl0, fCompl1;
+    if ( Gia_ObjIsConst0(pObj) )
+        return;
+    if ( pObj->fMark1 )
+        return;
+    pObj->fMark1 = 1;
+    if ( Gia_ObjIsCi(pObj) )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+    fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj);
+    if ( pObj->fMark0 )
+    {
+        assert( fCompl0 == 1 && fCompl1 == 1 );
+        Bmc_CexCareBits_rec( p, Gia_ObjFanin0(pObj) );
+        Bmc_CexCareBits_rec( p, Gia_ObjFanin1(pObj) );
+    }
+    else
+    {
+        assert( fCompl0 == 0 || fCompl1 == 0 );
+        if ( fCompl0 == 0 )
+            Bmc_CexCareBits_rec( p, Gia_ObjFanin0(pObj) );
+        if ( fCompl1 == 0 )
+            Bmc_CexCareBits_rec( p, Gia_ObjFanin1(pObj) );
+    }
+}
+void Bmc_CexCareBits2_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+    int fCompl0, fCompl1;
+    if ( Gia_ObjIsConst0(pObj) )
+        return;
+    if ( pObj->fMark1 )
+        return;
+    pObj->fMark1 = 1;
+    if ( Gia_ObjIsCi(pObj) )
+        return;
+    assert( Gia_ObjIsAnd(pObj) );
+    fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+    fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj);
+    if ( pObj->fMark0 )
+    {
+        assert( fCompl0 == 1 && fCompl1 == 1 );
+        Bmc_CexCareBits2_rec( p, Gia_ObjFanin0(pObj) );
+        Bmc_CexCareBits2_rec( p, Gia_ObjFanin1(pObj) );
+    }
+    else
+    {
+        assert( fCompl0 == 0 || fCompl1 == 0 );
+        if ( fCompl0 == 0 )
+            Bmc_CexCareBits2_rec( p, Gia_ObjFanin0(pObj) );
+        /**/ 
+        else 
+        /**/ 
+        if ( fCompl1 == 0 )
+            Bmc_CexCareBits2_rec( p, Gia_ObjFanin1(pObj) );
+    }
+}
+Abc_Cex_t * Bmc_CexCareBits( Gia_Man_t * p, Abc_Cex_t * pCexState, Abc_Cex_t * pCexImpl, Abc_Cex_t * pCexEss, int fFindAll, int fVerbose )
+{
+    Abc_Cex_t * pNew;
+    Gia_Obj_t * pObj;
+    int fCompl0, fCompl1;
+    int i, k, iBit;
+    assert( pCexState->nRegs == 0 );
+    // start the counter-example
+    pNew = Abc_CexAlloc( 0, Gia_ManCiNum(p), pCexState->iFrame + 1 );
+    pNew->iFrame = pCexState->iFrame;
+    pNew->iPo    = pCexState->iPo;
+    // set initial state
+    Gia_ManCleanMark01(p);
+    // set const0
+    Gia_ManConst0(p)->fMark0 = 0;
+    Gia_ManConst0(p)->fMark1 = 1;
+    for ( i = pCexState->iFrame; i >= 0; i-- )
+    {
+        // set correct values
+        iBit = pCexState->nPis * i;
+        Gia_ManForEachCi( p, pObj, k )
+        {
+            pObj->fMark0 = Abc_InfoHasBit(pCexState->pData, iBit+k);
+            pObj->fMark1 = 0;
+            if ( pCexImpl )
+                pObj->fMark1 |= Abc_InfoHasBit(pCexImpl->pData, iBit+k);
+            if ( pCexEss )
+                pObj->fMark1 |= Abc_InfoHasBit(pCexEss->pData, iBit+k);
+        }
+        Gia_ManForEachAnd( p, pObj, k )
+        {
+            fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+            fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj);
+            pObj->fMark0 = fCompl0 & fCompl1;
+            if ( pObj->fMark0 )
+                pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 & Gia_ObjFanin1(pObj)->fMark1;
+            else if ( !fCompl0 && !fCompl1 )
+                pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 | Gia_ObjFanin1(pObj)->fMark1;
+            else if ( !fCompl0 )
+                pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1;
+            else if ( !fCompl1 )
+                pObj->fMark1 = Gia_ObjFanin1(pObj)->fMark1;
+            else assert( 0 );
+        }
+        Gia_ManForEachCo( p, pObj, k )
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+        // move values from COs to CIs
+        if ( i == pCexState->iFrame )
+        {
+            assert( Gia_ManPo(p, pCexState->iPo)->fMark0 == 1 );
+            if ( fFindAll )
+                Bmc_CexCareBits_rec( p, Gia_ObjFanin0(Gia_ManPo(p, pCexState->iPo)) );
+            else
+                Bmc_CexCareBits2_rec( p, Gia_ObjFanin0(Gia_ManPo(p, pCexState->iPo)) );
+        }
+        else
+        {
+            Gia_ManForEachRi( p, pObj, k )
+                if ( Abc_InfoHasBit(pNew->pData, pNew->nPis * (i+1) + Gia_ManPiNum(p) + k) )
+                {
+                     if ( fFindAll )
+                         Bmc_CexCareBits_rec( p, Gia_ObjFanin0(pObj) );
+                     else
+                         Bmc_CexCareBits2_rec( p, Gia_ObjFanin0(pObj) );
+                }
+        }
+        // save the results
+        Gia_ManForEachCi( p, pObj, k )
+            if ( pObj->fMark1 )
+            {
+                pObj->fMark1 = 0;
+                if ( pCexImpl == NULL || !Abc_InfoHasBit(pCexImpl->pData, pNew->nPis * i + k) )
+                    Abc_InfoSetBit(pNew->pData, pNew->nPis * i + k);
+            }
+    }
+    if ( pCexEss )
+        printf( "Minimized:    " );
+    else
+        printf( "Care bits:    " );
+    Bmc_CexPrint( pNew, Gia_ManPiNum(p), fVerbose );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simulates one bit to check whether it is essential.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Bmc_CexEssentialBitOne( Gia_Man_t * p, Abc_Cex_t * pCexState, int iBit, Abc_Cex_t * pCexPrev, int * pfEqual )
+{
+    Abc_Cex_t * pNew;
+    Gia_Obj_t * pObj;
+    int i, k, fCompl0, fCompl1;
+    assert( pCexState->nRegs == 0 );
+    assert( iBit < pCexState->nBits );
+    if ( pfEqual )
+        *pfEqual = 0;
+    // start the counter-example
+    pNew = Abc_CexAllocFull( 0, Gia_ManCiNum(p), pCexState->iFrame + 1 );
+    pNew->iFrame = pCexState->iFrame;
+    pNew->iPo    = pCexState->iPo;
+    // clean bit
+    Abc_InfoXorBit( pNew->pData, iBit );
+    // simulate the remaining frames
+    Gia_ManConst0(p)->fMark0 = 0;
+    Gia_ManConst0(p)->fMark1 = 1;
+    for ( i = iBit / pCexState->nPis; i <= pCexState->iFrame; i++ )
+    {
+        Gia_ManForEachCi( p, pObj, k )
+        {
+            pObj->fMark0 = Abc_InfoHasBit( pCexState->pData, i * pCexState->nPis + k );
+            pObj->fMark1 = Abc_InfoHasBit( pNew->pData,      i * pCexState->nPis + k );
+        }
+        Gia_ManForEachAnd( p, pObj, k )
+        {
+            fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+            fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj);
+            pObj->fMark0 = fCompl0 & fCompl1;
+            if ( pObj->fMark0 )
+                pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 & Gia_ObjFanin1(pObj)->fMark1;
+            else if ( !fCompl0 && !fCompl1 )
+                pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 | Gia_ObjFanin1(pObj)->fMark1;
+            else if ( !fCompl0 )
+                pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1;
+            else if ( !fCompl1 )
+                pObj->fMark1 = Gia_ObjFanin1(pObj)->fMark1;
+            else assert( 0 );
+        }
+        Gia_ManForEachCo( p, pObj, k )
+        {
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+            pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1;
+        }
+        if ( i < pCexState->iFrame )
+        {
+            int fChanges  = 0;
+            int fEqual    = (pCexPrev != NULL);
+            int iBitShift = (i + 1) * pCexState->nPis + Gia_ManPiNum(p);
+            Gia_ManForEachRi( p, pObj, k )
+            {
+                if ( fEqual && pCexPrev && (int)pObj->fMark1 != Abc_InfoHasBit(pCexPrev->pData, iBitShift + k) )
+                    fEqual = 0;
+                if ( !pObj->fMark1 )
+                {
+                    fChanges = 1;
+                    Abc_InfoXorBit( pNew->pData, iBitShift + k );
+                }
+            }
+            if ( !fChanges || fEqual )
+            {
+                if ( pfEqual )
+                    *pfEqual = fEqual;
+                Abc_CexFree( pNew );
+                return NULL;
+            }
+        }
+/*
+        if ( i == 20 )
+        {
+            printf( "Frame %d : ", i );
+            Gia_ManForEachRi( p, pObj, k )
+                printf( "%d", pObj->fMark1 );
+            printf( "\n" );
+        }
+*/
+    }
+    return pNew;
+}
+void Bmc_CexEssentialBitTest( Gia_Man_t * p, Abc_Cex_t * pCexState )
+{
+    Abc_Cex_t * pNew;
+    int b;
+    for ( b = 0; b < pCexState->nBits; b++ )
+    {
+        if ( b % 100 )
+            continue;
+        pNew = Bmc_CexEssentialBitOne( p, pCexState, b, NULL, NULL );
+        Bmc_CexPrint( pNew, Gia_ManPiNum(p), 0 );
+
+        if ( Gia_ManPo(p, pCexState->iPo)->fMark1 )
+            printf( "Not essential\n" );
+        else
+            printf( "Essential\n" );
+
+        Abc_CexFree( pNew );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes essential bits of the CEX.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Cex_t * Bmc_CexEssentialBits( Gia_Man_t * p, Abc_Cex_t * pCexState, Abc_Cex_t * pCexCare, int fVerbose )
+{
+    Abc_Cex_t * pNew, * pTemp, * pPrev = NULL;
+    int b, fEqual = 0, fPrevStatus = 0;
+//    abctime clk = Abc_Clock();
+    assert( pCexState->nBits == pCexCare->nBits );
+    // start the counter-example
+    pNew = Abc_CexAlloc( 0, Gia_ManCiNum(p), pCexState->iFrame + 1 );
+    pNew->iFrame = pCexState->iFrame;
+    pNew->iPo    = pCexState->iPo;
+    // iterate through care-bits
+    for ( b = 0; b < pCexState->nBits; b++ )
+    {
+        // skip don't-care bits
+        if ( !Abc_InfoHasBit(pCexCare->pData, b) )
+            continue;
+
+        // skip state bits
+        if ( b % pCexCare->nPis >= Gia_ManPiNum(p) )
+        {
+            Abc_InfoSetBit( pNew->pData, b );
+            continue;
+        }
+
+        // check if this is an essential bit
+        pTemp = Bmc_CexEssentialBitOne( p, pCexState, b, pPrev, &fEqual );
+//        pTemp = Bmc_CexEssentialBitOne( p, pCexState, b, NULL, &fEqual );
+        if ( pTemp == NULL )
+        {
+            if ( fEqual && fPrevStatus )
+                Abc_InfoSetBit( pNew->pData, b );
+            continue;
+        }
+//        Bmc_CexPrint( pTemp, Gia_ManPiNum(p), fVerbose );
+        Abc_CexFree( pPrev );
+        pPrev = pTemp;
+
+        // record essential bit
+        fPrevStatus = !Gia_ManPo(p, pCexState->iPo)->fMark1;
+        if ( !Gia_ManPo(p, pCexState->iPo)->fMark1 )
+            Abc_InfoSetBit( pNew->pData, b );
+    }
+    Abc_CexFreeP( &pPrev );
+//    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    printf( "Essentials:   " );
+    Bmc_CexPrint( pNew, Gia_ManPiNum(p), fVerbose );
+    return pNew;
+}
+ 
+
+/**Function*************************************************************
+
+  Synopsis    [Computes essential bits of the CEX.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bmc_CexTest( Gia_Man_t * p, Abc_Cex_t * pCex, int fVerbose )
+{
+    abctime clk = Abc_Clock();
+    Abc_Cex_t * pCexImpl   = NULL;
+    Abc_Cex_t * pCexStates = Bmc_CexInnerStates( p, pCex, &pCexImpl, fVerbose );
+    Abc_Cex_t * pCexCare   = Bmc_CexCareBits( p, pCexStates, pCexImpl, NULL, 1, fVerbose );
+    Abc_Cex_t * pCexEss, * pCexMin;
+
+    if ( !Bmc_CexVerify( p, pCex, pCexCare ) )
+        printf( "Counter-example care-set verification has failed.\n" );
+
+    pCexEss = Bmc_CexEssentialBits( p, pCexStates, pCexCare, fVerbose );
+    pCexMin = Bmc_CexCareBits( p, pCexStates, pCexImpl, pCexEss, 0, fVerbose );
+
+    if ( !Bmc_CexVerify( p, pCex, pCexMin ) )
+        printf( "Counter-example min-set verification has failed.\n" );
+
+//    Bmc_CexDumpStats( p, pCex, pCexCare, pCexEss, pCexMin, Abc_Clock() - clk );
+
+    Abc_CexFreeP( &pCexStates );
+    Abc_CexFreeP( &pCexImpl );
+    Abc_CexFreeP( &pCexCare );
+    Abc_CexFreeP( &pCexEss );
+    Abc_CexFreeP( &pCexMin );
+
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+//    Bmc_CexBuildNetworkTest( p, pCex );
+//    Bmc_CexPerformUnrollingTest( p, pCex );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcEco.c b/abc-build/src/sat/bmc/bmcEco.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcEco.c
@@ -0,0 +1,318 @@
+/**CFile****************************************************************
+
+  FileName    [bmcEco.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcEco.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bmc.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes miter for ECO with given root node and fanins.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Bmc_EcoMiter( Gia_Man_t * pGold, Gia_Man_t * pOld, Vec_Int_t * vFans )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pRoot = Gia_ObjFanin0( Gia_ManPo(pOld, Gia_ManPoNum(pOld)-1) ); // fanin of the last PO
+    Gia_Obj_t * pObj;
+    int i, NewPi, Miter;
+    assert( Gia_ManCiNum(pGold) == Gia_ManCiNum(pOld) );
+    assert( Gia_ManCoNum(pGold) == Gia_ManCoNum(pOld) - 1 );
+    assert( Gia_ObjIsAnd(pRoot) );
+    // create the miter
+    pNew = Gia_ManStart( 3 * Gia_ManObjNum(pGold) );
+    pNew->pName = Abc_UtilStrsav( pGold->pName );
+    Gia_ManHashAlloc( pNew );
+    // copy gold
+    Gia_ManConst0(pGold)->Value = 0;
+    Gia_ManForEachCi( pGold, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    NewPi = Gia_ManAppendCi( pNew );
+    Gia_ManForEachAnd( pGold, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachCo( pGold, pObj, i )
+        pObj->Value = Gia_ObjFanin0Copy( pObj );
+    // create onset
+    Gia_ManConst0(pOld)->Value = 0;
+    Gia_ManForEachCi( pOld, pObj, i )
+        pObj->Value = Gia_ManCi(pGold, i)->Value;
+    Gia_ManForEachAnd( pOld, pObj, i )
+        if ( pObj == pRoot )
+            pObj->Value = NewPi;
+        else
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachCo( pOld, pObj, i )
+        pObj->Value = Gia_ObjFanin0Copy( pObj );
+    Gia_ManForEachCo( pGold, pObj, i )
+        Gia_ManAppendCo( pNew, Gia_ManHashXor(pNew, pObj->Value, Gia_ManCo(pOld, i)->Value) );
+    // create offset
+    Gia_ManForEachAnd( pOld, pObj, i )
+        if ( pObj == pRoot )
+            pObj->Value = Abc_LitNot(NewPi);
+        else
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachCo( pOld, pObj, i )
+        pObj->Value = Gia_ObjFanin0Copy( pObj );
+    Miter = 0;
+    Gia_ManForEachCo( pGold, pObj, i )
+        Miter = Gia_ManHashOr( pNew, Miter, Gia_ManHashXor(pNew, pObj->Value, Gia_ManCo(pOld, i)->Value) );
+    Gia_ManAppendCo( pNew, Miter );
+    // add outputs for the nodes
+    Gia_ManForEachObjVec( vFans, pOld, pObj, i )
+        Gia_ManAppendCo( pNew, pObj->Value );
+    // cleanup
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    assert( Gia_ManPiNum(pNew) == Gia_ManCiNum(pGold) + 1 );
+    assert( Gia_ManPoNum(pNew) == Gia_ManCoNum(pGold) + 1 + Vec_IntSize(vFans) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Cnf_Dat_t * Cnf_DeriveGiaRemapped( Gia_Man_t * p )
+{
+    Cnf_Dat_t * pCnf;
+    Aig_Man_t * pAig = Gia_ManToAigSimple( p );
+    pAig->nRegs = 0;
+    pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) );
+    Aig_ManStop( pAig );
+    return pCnf;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Solve the enumeration problem.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bmc_EcoSolve( sat_solver * pSat, int Root, Vec_Int_t * vVars )
+{
+    int nBTLimit = 1000000;
+    Vec_Int_t * vValues = Vec_IntAlloc( Vec_IntSize(vVars) );
+    Vec_Int_t * vLits   = Vec_IntAlloc( Vec_IntSize(vVars) );
+    int status, i, Div, iVar, nFinal, * pFinal, nIter = 0, RetValue = 0;
+    int pLits[2], nVars = sat_solver_nvars( pSat );
+    sat_solver_setnvars( pSat, nVars + 1 );
+    pLits[0] = Abc_Var2Lit( Root, 0 );  // F = 1
+    pLits[1] = Abc_Var2Lit( nVars, 0 ); // iNewLit
+    while ( 1 ) 
+    {
+        // find onset minterm
+        status = sat_solver_solve( pSat, pLits, pLits + 2, nBTLimit, 0, 0, 0 );
+        if ( status == l_Undef )
+            { RetValue = -1; break; }
+        if ( status == l_False )
+            { RetValue = 1; break; }
+        assert( status == l_True );
+        // remember variable values
+        Vec_IntClear( vValues );
+        Vec_IntForEachEntry( vVars, iVar, i )
+            Vec_IntPush( vValues, sat_solver_var_value(pSat, iVar) );
+        // collect divisor literals
+        Vec_IntClear( vLits );
+        Vec_IntPush( vLits, Abc_LitNot(pLits[0]) ); // F = 0
+        Vec_IntForEachEntry( vVars, Div, i )
+            Vec_IntPush( vLits, sat_solver_var_literal(pSat, Div) );
+        // check against offset
+        status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), nBTLimit, 0, 0, 0 );
+        if ( status == l_Undef )
+            { RetValue = -1; break; }
+        if ( status == l_True )
+            break;
+        assert( status == l_False );
+        // compute cube and add clause
+        nFinal = sat_solver_final( pSat, &pFinal );
+        Vec_IntClear( vLits );
+        Vec_IntPush( vLits, Abc_LitNot(pLits[1]) ); // NOT(iNewLit)
+        printf( "Cube %d : ", nIter );
+        for ( i = 0; i < nFinal; i++ )
+        {
+            if ( pFinal[i] == pLits[0] )
+                continue;
+            Vec_IntPush( vLits, pFinal[i] );
+            iVar = Vec_IntFind( vVars, Abc_Lit2Var(pFinal[i]) );   assert( iVar >= 0 );
+            printf( "%s%d ", Abc_LitIsCompl(pFinal[i]) ? "+":"-", iVar );
+        }
+        printf( "\n" );
+        status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
+        assert( status );
+        nIter++;
+    }
+//    assert( status == l_True );
+    Vec_IntFree( vValues );
+    Vec_IntFree( vLits );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Compute the patch function.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bmc_EcoPatch( Gia_Man_t * p, int nIns, int nOuts )
+{
+    int i, Lit, RetValue, Root;
+    Gia_Obj_t * pObj;
+    Vec_Int_t * vVars;
+    // generate CNF and solver
+    Cnf_Dat_t * pCnf = Cnf_DeriveGiaRemapped( p );
+    sat_solver * pSat = sat_solver_new();
+    sat_solver_setnvars( pSat, pCnf->nVars );
+    // add timeframe clauses
+    for ( i = 0; i < pCnf->nClauses; i++ )
+        if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
+            assert( 0 );
+    // add equality constraints
+    assert( Gia_ManPoNum(p) == nOuts + 1 + nIns );
+    Gia_ManForEachPo( p, pObj, i )
+    {
+        if ( i == nOuts )
+            break;
+        Lit = Abc_Var2Lit( pCnf->pVarNums[Gia_ObjId(p, pObj)], 1 ); // neg lit
+        RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
+        assert( RetValue );
+    }
+    // add inequality constraint
+    pObj = Gia_ManPo( p, nOuts );
+    Lit = Abc_Var2Lit( pCnf->pVarNums[Gia_ObjId(p, pObj)], 0 ); // pos lit
+    RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
+    assert( RetValue );
+    // simplify the SAT solver
+    RetValue = sat_solver_simplify( pSat );
+    assert( RetValue );
+    // collect input variables
+    vVars = Vec_IntAlloc( nIns );
+    Gia_ManForEachPo( p, pObj, i )
+        if ( i >= nOuts + 1 )
+            Vec_IntPush( vVars, pCnf->pVarNums[Gia_ObjId(p, pObj)] );
+    assert( Vec_IntSize(vVars) == nIns );
+    // derive the root variable
+    pObj = Gia_ManPi( p, Gia_ManPiNum(p) - 1 );
+    Root = pCnf->pVarNums[Gia_ObjId(p, pObj)];
+    // solve the problem
+    RetValue = Bmc_EcoSolve( pSat, Root, vVars );
+    Vec_IntFree( vVars );
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Tests the ECO miter.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bmc_EcoMiterTest()
+{
+    char * pFileGold = "eco_gold.aig";
+    char * pFileOld =  "eco_old.aig";
+    Vec_Int_t * vFans;
+    FILE * pFile;
+    Gia_Man_t * pMiter;
+    Gia_Obj_t * pObj;
+    Gia_Man_t * pGold;
+    Gia_Man_t * pOld;
+    int i, RetValue;
+    // check that the files exist
+    pFile = fopen( pFileGold, "r" );
+    if ( pFile == NULL )
+    {
+        printf( "File \"%s\" does not exist.\n", pFileGold );
+        return;
+    }
+    fclose( pFile );
+    pFile = fopen( pFileOld, "r" );
+    if ( pFile == NULL )
+    {
+        printf( "File \"%s\" does not exist.\n", pFileOld );
+        return;
+    }
+    fclose( pFile );
+    // read files
+    pGold = Gia_AigerRead( pFileGold, 0, 0 );
+    pOld  = Gia_AigerRead( pFileOld, 0, 0 );
+    // create ECO miter
+    vFans = Vec_IntAlloc( Gia_ManCiNum(pOld) );
+    Gia_ManForEachCi( pOld, pObj, i )
+        Vec_IntPush( vFans, Gia_ObjId(pOld, pObj) );
+    pMiter = Bmc_EcoMiter( pGold, pOld, vFans );
+    Vec_IntFree( vFans );
+    Gia_AigerWrite( pMiter, "eco_miter.aig", 0, 0 );
+    // find the patch
+    RetValue = Bmc_EcoPatch( pMiter, Gia_ManCiNum(pGold), Gia_ManCoNum(pGold) );
+    if ( RetValue == 1 )
+        printf( "Patch is computed.\n" );
+    if ( RetValue == 0 )
+        printf( "Cannot be patched.\n" );
+    if ( RetValue == -1 )
+        printf( "Resource limit exceeded.\n" );
+    Gia_ManStop( pMiter );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcFault.c b/abc-build/src/sat/bmc/bmcFault.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcFault.c
@@ -0,0 +1,1155 @@
+/**CFile****************************************************************
+
+  FileName    [bmcFault.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    [Checking for functional faults.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcFault.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bmc.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satStore.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define FFTEST_MAX_VARS 2
+#define FFTEST_MAX_PARS 8
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ParFfSetDefault( Bmc_ParFf_t * p )
+{
+    memset( p, 0, sizeof(Bmc_ParFf_t) );
+    p->pFileName     =  NULL; 
+    p->Algo          =     0; 
+    p->fStartPats    =     0; 
+    p->nTimeOut      =     0; 
+    p->fBasic        =     0; 
+    p->fDump         =     0; 
+    p->fDumpUntest   =     0; 
+    p->fVerbose      =     0; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add constraint that no more than 1 variable is 1.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cnf_AddCardinConstr( sat_solver * p, Vec_Int_t * vVars )
+{
+    int i, k, pLits[2], iVar, nVars = sat_solver_nvars(p);
+    Vec_IntForEachEntry( vVars, iVar, i )
+        assert( iVar >= 0 && iVar < nVars );
+    iVar = nVars;
+    sat_solver_setnvars( p, nVars + Vec_IntSize(vVars) - 1 );
+    while ( Vec_IntSize(vVars) > 1 )
+    {
+        for ( k = i = 0; i < Vec_IntSize(vVars)/2; i++ )
+        {
+            pLits[0] = Abc_Var2Lit( Vec_IntEntry(vVars, 2*i), 1 );
+            pLits[1] = Abc_Var2Lit( Vec_IntEntry(vVars, 2*i+1), 1 );
+            sat_solver_addclause( p, pLits, pLits + 2 );
+            sat_solver_add_and( p, iVar, Vec_IntEntry(vVars, 2*i), Vec_IntEntry(vVars, 2*i+1), 1, 1, 1 );
+            Vec_IntWriteEntry( vVars, k++, iVar++ );
+        }
+        if ( Vec_IntSize(vVars) & 1 )
+            Vec_IntWriteEntry( vVars, k++, Vec_IntEntryLast(vVars) );
+        Vec_IntShrink( vVars, k );
+    }
+    return iVar;
+}
+void Cnf_AddCardinConstrTest()
+{
+    int i, status, nVars = 7;
+    Vec_Int_t * vVars = Vec_IntStartNatural( nVars );
+    sat_solver * pSat = sat_solver_new();
+    sat_solver_setnvars( pSat, nVars );
+    Cnf_AddCardinConstr( pSat, vVars );
+    while ( 1 )
+    {
+        status = sat_solver_solve( pSat, NULL, NULL, 0, 0, 0, 0 );
+        if ( status != l_True )
+            break;
+        Vec_IntClear( vVars );
+        for ( i = 0; i < nVars; i++ )
+        {
+            Vec_IntPush( vVars, Abc_Var2Lit(i, sat_solver_var_value(pSat, i)) );
+            printf( "%d", sat_solver_var_value(pSat, i) );
+        }
+        printf( "\n" );
+        status = sat_solver_addclause( pSat, Vec_IntArray(vVars), Vec_IntArray(vVars) + Vec_IntSize(vVars) );
+        if ( status == 0 )
+            break;
+    }
+    sat_solver_delete( pSat );
+    Vec_IntFree( vVars );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Cnf_Dat_t * Cnf_DeriveGiaRemapped( Gia_Man_t * p )
+{
+    Cnf_Dat_t * pCnf;
+    Aig_Man_t * pAig = Gia_ManToAigSimple( p );
+    pAig->nRegs = 0;
+    pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) );
+    Aig_ManStop( pAig );
+    return pCnf;
+//    return Mf_ManGenerateCnf( p, 8, 0, 0, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cnf_DataLiftGia( Cnf_Dat_t * p, Gia_Man_t * pGia, int nVarsPlus )
+{
+    Gia_Obj_t * pObj;
+    int v;
+    Gia_ManForEachObj( pGia, pObj, v )
+        if ( p->pVarNums[Gia_ObjId(pGia, pObj)] >= 0 )
+            p->pVarNums[Gia_ObjId(pGia, pObj)] += nVarsPlus;
+    for ( v = 0; v < p->nLiterals; v++ )
+        p->pClauses[0][v] += 2*nVarsPlus;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFaultUnfold( Gia_Man_t * p, int fUseMuxes )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, iCtrl, iThis;
+    pNew = Gia_ManStart( (2 + 3 * fUseMuxes) * Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManConst0(p)->Value = 0;
+    // add first timeframe
+    Gia_ManForEachRo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->Value = Gia_ObjFanin0Copy(pObj);
+    // add second timeframe
+    Gia_ManForEachRo( p, pObj, i )
+        pObj->Value = Gia_ObjRoToRi(p, pObj)->Value;
+    Gia_ManForEachPi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        iCtrl = Gia_ManAppendCi(pNew);
+        iThis = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        if ( fUseMuxes )
+            pObj->Value = Gia_ManHashMux( pNew, iCtrl, pObj->Value, iThis );
+        else
+            pObj->Value = iThis;
+    }
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    assert( Gia_ManPiNum(pNew) == Gia_ManRegNum(p) + 2 * Gia_ManPiNum(p) + Gia_ManAndNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManStuckAtUnfold( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i;
+    pNew = Gia_ManStart( 3 * Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        pObj->Value = Gia_ManHashAnd( pNew, Abc_LitNot(Gia_ManAppendCi(pNew)), pObj->Value );
+        pObj->Value = Gia_ManHashOr( pNew, Gia_ManAppendCi(pNew), pObj->Value );
+    }
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    assert( Gia_ManPiNum(pNew) == Gia_ManCiNum(p) + 2 * Gia_ManAndNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFlipUnfold( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i;
+    pNew = Gia_ManStart( 4 * Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        pObj->Value = Gia_ManHashXor( pNew, Gia_ManAppendCi(pNew), pObj->Value );
+    }
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    assert( Gia_ManPiNum(pNew) == Gia_ManCiNum(p) + Gia_ManAndNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFOFUnfold( Gia_Man_t * p )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, iCtrl0, iCtrl1, iCtrl2, iCtrl3, iMuxA, iMuxB;
+    pNew = Gia_ManStart( 9 * Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        iCtrl0 = Gia_ManAppendCi(pNew);
+        iCtrl1 = Gia_ManAppendCi(pNew);
+        iCtrl2 = Gia_ManAppendCi(pNew);
+        iCtrl3 = Gia_ManAppendCi(pNew);
+        if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) )
+            iCtrl0 = Abc_LitNot(iCtrl0);
+        else if ( !Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) )
+            iCtrl1 = Abc_LitNot(iCtrl1);
+        else if ( Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) )
+            iCtrl2 = Abc_LitNot(iCtrl2);
+        else //if ( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) )
+            iCtrl3 = Abc_LitNot(iCtrl3);
+        iMuxA       = Gia_ManHashMux( pNew, Gia_ObjFanin0(pObj)->Value, iCtrl1, iCtrl0 );
+        iMuxB       = Gia_ManHashMux( pNew, Gia_ObjFanin0(pObj)->Value, iCtrl3, iCtrl2 );
+        pObj->Value = Gia_ManHashMux( pNew, Gia_ObjFanin1(pObj)->Value, iMuxB,  iMuxA );
+    }
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    assert( Gia_ManPiNum(pNew) == Gia_ManCiNum(p) + 4 * Gia_ManAndNum(p) );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure sets default parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_FormStrCount( char * pStr, int * pnVars, int * pnPars )
+{
+    int i, Counter = 0;
+    if ( pStr[0] != '(' )
+    {
+        printf( "The first symbol should be the opening paranthesis \"(\".\n" );
+        return 1;
+    }
+    if ( pStr[strlen(pStr)-1] != ')' )
+    {
+        printf( "The last symbol should be the closing paranthesis \")\".\n" );
+        return 1;
+    }
+    for ( i = 0; pStr[i]; i++ )
+        if (  pStr[i] == '(' )
+            Counter++;
+        else if (  pStr[i] == ')' )
+            Counter--;
+    if ( Counter != 0 )
+    {
+        printf( "The number of opening and closing parantheses is not equal.\n" );
+        return 1;
+    }
+    *pnVars = 0;
+    *pnPars = 0;
+    for ( i = 0; pStr[i]; i++ )
+    {
+        if ( pStr[i] >= 'a' && pStr[i] <= 'b' )
+            *pnVars = Abc_MaxInt( *pnVars, pStr[i] - 'a' + 1 );
+        else if ( pStr[i] >= 'p' && pStr[i] <= 's' )
+            *pnPars = Abc_MaxInt( *pnPars, pStr[i] - 'p' + 1 );
+        else if ( pStr[i] == '(' || pStr[i] == ')' )
+        {}
+        else if ( pStr[i] == '&' || pStr[i] == '|' || pStr[i] == '^' )
+        {}
+        else if ( pStr[i] == '?' || pStr[i] == ':' )
+        {}
+        else if ( pStr[i] == '~' )
+        {
+            if ( pStr[i+1] < 'a' || pStr[i+1] > 'z' )
+            {
+                printf( "Expecting alphabetic symbol (instead of \"%c\") after negation (~)\n",  pStr[i+1] );
+                return 1;
+            }
+        }
+        else 
+        {
+            printf( "Unknown symbol (%c) in the formula (%s)\n", pStr[i], pStr );
+            return 1;
+        }
+    }
+    if ( *pnVars != FFTEST_MAX_VARS )
+        { printf( "The number of input variables (%d) should be 2\n", *pnVars ); return 1; }
+    if ( *pnPars < 1 && *pnPars > FFTEST_MAX_PARS )
+        { printf( "The number of parameters should be between 1 and %d\n", *pnPars ); return 1; }
+    return 0;
+}
+void Gia_FormStrTransform( char * pStr, char * pForm )
+{
+    int i, k;
+    for ( k = i = 0; pForm[i]; i++ )
+    {
+        if ( pForm[i] == '~' )
+        {
+            i++;
+            assert( pForm[i] >= 'a' && pForm[i] <= 'z' );
+            pStr[k++] = 'A' + pForm[i] - 'a';
+        }
+        else
+            pStr[k++] = pForm[i];
+    }
+    pStr[k] = 0; 
+}   
+
+
+/**Function*************************************************************
+
+  Synopsis    [Implements fault model formula using functional/parameter vars.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Gia_ManFormulaEndToken( char * pForm )
+{
+    int Counter = 0;
+    char * pThis;
+    for ( pThis = pForm; *pThis; pThis++ )
+    {
+        assert( *pThis != '~' );
+        if ( *pThis == '(' )
+            Counter++;
+        else if ( *pThis == ')' )
+            Counter--;
+        if ( Counter == 0 )
+            return pThis + 1;
+    }
+    assert( 0 );
+    return NULL;
+}
+int Gia_ManRealizeFormula_rec( Gia_Man_t * p, int * pVars, int * pPars, char * pBeg, char * pEnd, int nPars )
+{
+    int iFans[3], Oper = -1;
+    char * pEndNew;
+    if ( pBeg + 1 == pEnd )
+    {
+        if ( pBeg[0] >= 'a' && pBeg[0] <= 'b' )
+            return pVars[pBeg[0] - 'a'];
+        if ( pBeg[0] >= 'A' && pBeg[0] <= 'B' )
+            return Abc_LitNot( pVars[pBeg[0] - 'A'] );
+        if ( pBeg[0] >= 'p' && pBeg[0] <= 'w' ) // pqrstuvw
+            return pPars[pBeg[0] - 'p'];
+        if ( pBeg[0] >= 'P' && pBeg[0] <= 'W' )
+            return Abc_LitNot( pPars[pBeg[0] - 'P'] );
+        assert( 0 );
+        return -1;
+    }
+    if ( pBeg[0] == '(' )
+    {
+        pEndNew = Gia_ManFormulaEndToken( pBeg );
+        if ( pEndNew == pEnd )
+        {
+            assert( pBeg[0] == '(' );
+            assert( pBeg[pEnd-pBeg-1] == ')' );
+            return Gia_ManRealizeFormula_rec( p, pVars, pPars, pBeg + 1, pEnd - 1, nPars );
+        }
+    }
+    // get first part
+    pEndNew  = Gia_ManFormulaEndToken( pBeg );
+    iFans[0] = Gia_ManRealizeFormula_rec( p, pVars, pPars, pBeg, pEndNew, nPars );
+    Oper     = pEndNew[0];
+    // get second part
+    pBeg     = pEndNew + 1;
+    pEndNew  = Gia_ManFormulaEndToken( pBeg );
+    iFans[1] = Gia_ManRealizeFormula_rec( p, pVars, pPars, pBeg, pEndNew, nPars );
+    // derive the formula
+    if ( Oper == '&' )
+        return Gia_ManHashAnd( p, iFans[0], iFans[1] );
+    if ( Oper == '|' )
+        return Gia_ManHashOr( p, iFans[0], iFans[1] );
+    if ( Oper == '^' )
+        return Gia_ManHashXor( p, iFans[0], iFans[1] );
+    // get third part
+    assert( Oper == '?' );
+    assert( pEndNew[0] == ':' );
+    pBeg     = pEndNew + 1;
+    pEndNew  = Gia_ManFormulaEndToken( pBeg );
+    iFans[2] = Gia_ManRealizeFormula_rec( p, pVars, pPars, pBeg, pEndNew, nPars );
+    return Gia_ManHashMux( p, iFans[0], iFans[1], iFans[2] );
+}
+int Gia_ManRealizeFormula( Gia_Man_t * p, int * pVars, int * pPars, char * pStr, int nPars )
+{
+    return Gia_ManRealizeFormula_rec( p, pVars, pPars, pStr, pStr + strlen(pStr), nPars );
+}
+Gia_Man_t * Gia_ManFormulaUnfold( Gia_Man_t * p, char * pForm )
+{
+    char pStr[100];
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, k, iCtrl[FFTEST_MAX_PARS], iFans[FFTEST_MAX_VARS];
+    int nVars, nPars;
+    assert( strlen(pForm) < 100 );
+    Gia_FormStrCount( pForm, &nVars, &nPars );
+    assert( nVars == 2 );
+    Gia_FormStrTransform( pStr, pForm );
+    pNew = Gia_ManStart( 5 * Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachCi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCi( pNew );
+    Gia_ManForEachAnd( p, pObj, i )
+    {
+        for ( k = 0; k < nPars; k++ )
+            iCtrl[k] = Gia_ManAppendCi(pNew);
+        iFans[0] = Gia_ObjFanin0Copy(pObj);
+        iFans[1] = Gia_ObjFanin1Copy(pObj);
+        pObj->Value = Gia_ManRealizeFormula( pNew, iFans, iCtrl, pStr, nPars );
+    }
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    assert( Gia_ManPiNum(pNew) == Gia_ManCiNum(p) + nPars * Gia_ManAndNum(p) );
+//    if ( fUseFaults )
+//        Gia_AigerWrite( pNew, "newfault.aig", 0, 0 );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManFaultCofactor( Gia_Man_t * p, Vec_Int_t * vValues )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i;
+    pNew = Gia_ManStart( Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManConst0(p)->Value = 0;
+    Gia_ManForEachPi( p, pObj, i )
+    {
+        pObj->Value = Gia_ManAppendCi( pNew );
+        if ( i < Vec_IntSize(vValues) )
+            pObj->Value = Vec_IntEntry( vValues, i );
+    }
+    Gia_ManForEachAnd( p, pObj, i )
+        pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+    Gia_ManForEachCo( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    assert( Gia_ManPiNum(pNew) == Gia_ManPiNum(p) );
+    return pNew;
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManDumpTests( Vec_Int_t * vTests, int nIter, char * pFileName )
+{
+    FILE * pFile = fopen( pFileName, "wb" );
+    int i, k, v, nVars = Vec_IntSize(vTests) / nIter;
+    assert( Vec_IntSize(vTests) % nIter == 0 );
+    for ( v = i = 0; i < nIter; i++, fprintf(pFile, "\n") )
+        for ( k = 0; k < nVars; k++ )
+            fprintf( pFile, "%d", Vec_IntEntry(vTests, v++) );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManPrintResults( Gia_Man_t * p, sat_solver * pSat, int nIter, abctime clk )
+{
+    FILE * pTable = fopen( "fault_stats.txt", "a+" );
+
+    fprintf( pTable, "%s ", Gia_ManName(p) );
+    fprintf( pTable, "%d ", Gia_ManPiNum(p) );
+    fprintf( pTable, "%d ", Gia_ManPoNum(p) );
+    fprintf( pTable, "%d ", Gia_ManRegNum(p) );
+    fprintf( pTable, "%d ", Gia_ManAndNum(p) );
+
+    fprintf( pTable, "%d ", sat_solver_nvars(pSat) );
+    fprintf( pTable, "%d ", sat_solver_nclauses(pSat) );
+    fprintf( pTable, "%d ", sat_solver_nconflicts(pSat) );
+
+    fprintf( pTable, "%d ", nIter );
+    fprintf( pTable, "%.2f", 1.0*clk/CLOCKS_PER_SEC );
+    fprintf( pTable, "\n" );
+    fclose( pTable );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFaultAddOne( Gia_Man_t * pM, Cnf_Dat_t * pCnf, sat_solver * pSat, Vec_Int_t * vLits, int nFuncVars )
+{
+    Gia_Man_t * pC;
+    Cnf_Dat_t * pCnf2;
+    Gia_Obj_t * pObj;
+    int i, Lit;
+    // derive the cofactor
+    pC = Gia_ManFaultCofactor( pM, vLits );
+//Gia_AigerWrite( pC, "fftest_cof.aig", 0, 0 );
+//printf( "Dumped cofactor circuit into file \"%s\".\n", "fftest_cof.aig" );
+    // derive new CNF
+    pCnf2 = Cnf_DeriveGiaRemapped( pC );
+    Cnf_DataLiftGia( pCnf2, pC, sat_solver_nvars(pSat) );
+    // add timeframe clauses
+    for ( i = 0; i < pCnf2->nClauses; i++ )
+        if ( !sat_solver_addclause( pSat, pCnf2->pClauses[i], pCnf2->pClauses[i+1] ) )
+            assert( 0 );
+    // add constraint clauses
+    Gia_ManForEachPo( pC, pObj, i )
+    {
+        Lit = Abc_Var2Lit( pCnf2->pVarNums[Gia_ObjId(pC, pObj)], 1 );
+        if ( !sat_solver_addclause( pSat, &Lit, &Lit+1 ) )
+            assert( 0 );
+    }
+    // add connection clauses
+    Gia_ManForEachPi( pM, pObj, i )
+        if ( i >= nFuncVars )
+            sat_solver_add_buffer( pSat, pCnf->pVarNums[Gia_ObjId(pM, pObj)], pCnf2->pVarNums[Gia_ObjId(pC, Gia_ManPi(pC, i))], 0 );
+    Cnf_DataFree( pCnf2 );
+    Gia_ManStop( pC );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManDumpUntests( Gia_Man_t * pM, Cnf_Dat_t * pCnf, sat_solver * pSat, int nFuncVars, char * pFileName, int fVerbose )
+{
+    FILE * pFile = fopen( pFileName, "wb" );
+    Vec_Int_t * vLits;
+    Gia_Obj_t * pObj;
+    int nItersMax = 10000;
+    int i, nIters, status, Value, Count = 0;
+    vLits = Vec_IntAlloc( Gia_ManPiNum(pM) - nFuncVars );
+    for ( nIters = 0; nIters < nItersMax; nIters++ )
+    {
+        status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        if ( status == l_Undef )
+            printf( "Timeout reached after dumping %d untestable faults.\n", nIters );
+        if ( status == l_Undef )
+            break;
+        if ( status == l_False )
+            break;
+        // collect literals
+        Vec_IntClear( vLits );
+        Gia_ManForEachPi( pM, pObj, i )
+            if ( i >= nFuncVars )
+                Vec_IntPush( vLits, Abc_Var2Lit(pCnf->pVarNums[Gia_ObjId(pM, pObj)], sat_solver_var_value(pSat, pCnf->pVarNums[Gia_ObjId(pM, pObj)])) );
+        // dump the fault
+        Vec_IntForEachEntry( vLits, Value, i )
+            if ( Abc_LitIsCompl(Value) )
+                break;
+        if ( i < Vec_IntSize(vLits) )
+        {
+            if ( fVerbose )
+            {
+                printf( "Untestable fault %4d : ", ++Count );
+                Vec_IntForEachEntry( vLits, Value, i )
+                    if ( Abc_LitIsCompl(Value) )
+                        printf( "%d ", i );
+                printf( "\n" );
+            }
+            Vec_IntForEachEntry( vLits, Value, i )
+                if ( Abc_LitIsCompl(Value) )
+                    fprintf( pFile, "%d ", i );
+            fprintf( pFile, "\n" );
+        }
+        // add this clause
+        if ( !sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ) )
+            break;
+    }
+    Vec_IntFree( vLits );
+    fclose( pFile );
+    return nIters;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManGetTestPatterns( char * pFileName )
+{
+    FILE * pFile = fopen( pFileName, "rb" );
+    Vec_Int_t * vTests; int c;
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open input file \"%s\".\n", pFileName );
+        return NULL;
+    }
+    vTests = Vec_IntAlloc( 10000 );
+    while ( (c = fgetc(pFile)) != EOF )
+    {
+        if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' )
+            continue;
+        if ( c != '0' && c != '1' )
+        {
+            printf( "Wring symbol (%c) in the input file.\n", c );
+            Vec_IntFreeP( &vTests );
+            break;
+        }
+        Vec_IntPush( vTests, c - '0' );
+    }
+    fclose( pFile );
+    return vTests;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive the second AIG.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManDeriveDup( Gia_Man_t * p, int nPisNew )
+{
+    int i;
+    Gia_Man_t * pNew = Gia_ManDup(p);
+    for ( i = 0; i < nPisNew; i++ )
+        Gia_ManAppendCi( pNew );
+    return pNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManFaultTest( Gia_Man_t * p, Gia_Man_t * pG, Bmc_ParFf_t * pPars )
+{
+    int nIterMax = 1000000, nVars, nPars;
+    int i, Iter, Iter2, status, nFuncVars = -1;
+    abctime clkSat = 0, clkTotal = Abc_Clock();
+    Vec_Int_t * vLits, * vTests;
+    Gia_Man_t * p0 = NULL, * p1 = NULL, * pM;
+    Gia_Obj_t * pObj;
+    Cnf_Dat_t * pCnf;
+    sat_solver * pSat;
+
+    if ( pPars->Algo == 0 && Gia_FormStrCount( pPars->pFormStr, &nVars, &nPars ) )
+        return;
+
+    // select algorithm
+    if ( pPars->Algo == 0 )
+        printf( "FFTEST is computing test patterns for fault model \"%s\"...\n", pPars->pFormStr );
+    else if ( pPars->Algo == 1 )
+        printf( "FFTEST is computing test patterns for %sdelay faults...\n", pPars->fBasic ? "single " : "" );
+    else if ( pPars->Algo == 2 )
+        printf( "FFTEST is computing test patterns for %sstuck-at faults...\n", pPars->fBasic ? "single " : "" );
+    else if ( pPars->Algo == 3 )
+        printf( "FFTEST is computing test patterns for %scomplement faults...\n", pPars->fBasic ? "single " : "" );
+    else if ( pPars->Algo == 4 )
+        printf( "FFTEST is computing test patterns for %sfunctionally observable faults...\n", pPars->fBasic ? "single " : "" );
+    else
+    {
+        printf( "Unrecognized algorithm (%d).\n", pPars->Algo );
+        return;
+    }
+
+    // select algorithm
+    if ( pPars->Algo == 0 )
+        nFuncVars = Gia_ManCiNum(p);
+    else if ( pPars->Algo == 1 )
+        nFuncVars = Gia_ManRegNum(p) + 2 * Gia_ManPiNum(p);
+    else if ( pPars->Algo == 2 )
+        nFuncVars = Gia_ManCiNum(p);
+    else if ( pPars->Algo == 3 )
+        nFuncVars = Gia_ManCiNum(p);
+    else if ( pPars->Algo == 4 )
+        nFuncVars = Gia_ManCiNum(p);
+
+    // collect test patterns from file
+    if ( pPars->pFileName )
+        vTests = Gia_ManGetTestPatterns( pPars->pFileName );
+    else
+        vTests = Vec_IntAlloc( 10000 );
+    if ( vTests == NULL )
+        return;
+    if ( Vec_IntSize(vTests) % nFuncVars != 0 )
+    {
+        printf( "The number of symbols in the input patterns (%d) does not divide evenly on the number of test variables (%d).\n", Vec_IntSize(vTests), nFuncVars );
+        Vec_IntFree( vTests );
+        return;
+    }
+
+    // select algorithm
+    if ( pPars->Algo == 0 )
+        p1 = Gia_ManFormulaUnfold( p, pPars->pFormStr );
+    else if ( pPars->Algo == 1 )
+    {
+        assert( Gia_ManRegNum(p) > 0 );
+        p0 = Gia_ManFaultUnfold( pG, 0 );
+        p1 = Gia_ManFaultUnfold( p, 1 );
+    }
+    else if ( pPars->Algo == 2 )
+        p1 = Gia_ManStuckAtUnfold( p );
+    else if ( pPars->Algo == 3 )
+        p1 = Gia_ManFlipUnfold( p );
+    else if ( pPars->Algo == 4 )
+        p1 = Gia_ManFOFUnfold( p );
+    if ( pPars->Algo != 1 )
+        p0 = Gia_ManDeriveDup( pG, Gia_ManCiNum(p1) - Gia_ManCiNum(pG) );
+//    Gia_AigerWrite( p1, "newfault.aig", 0, 0 );
+//    printf( "Dumped circuit with fault parameters into file \"newfault.aig\".\n" );
+
+    // create miter
+    pM = Gia_ManMiter( p0, p1, 0, 0, 0, 0, 0 );
+    pCnf = Cnf_DeriveGiaRemapped( pM );
+    Gia_ManStop( p0 );
+    Gia_ManStop( p1 );
+
+    // start the SAT solver
+    pSat = sat_solver_new();
+    sat_solver_setnvars( pSat, pCnf->nVars );
+    sat_solver_set_runtime_limit( pSat, pPars->nTimeOut ? pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 );
+    // add timeframe clauses
+    for ( i = 0; i < pCnf->nClauses; i++ )
+        if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
+            assert( 0 );
+
+    // add one large OR clause
+    vLits = Vec_IntAlloc( Gia_ManCoNum(p) );
+    Gia_ManForEachCo( pM, pObj, i )
+        Vec_IntPush( vLits, Abc_Var2Lit(pCnf->pVarNums[Gia_ObjId(pM, pObj)], 0) );
+    sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
+
+    // add cardinality constraint
+    if ( pPars->fBasic )
+    {
+        Vec_IntClear( vLits );
+        Gia_ManForEachPi( pM, pObj, i )
+            if ( i >= nFuncVars )
+                Vec_IntPush( vLits, pCnf->pVarNums[Gia_ObjId(pM, pObj)] );
+        Cnf_AddCardinConstr( pSat, vLits );
+    }
+
+    // add available test-patterns
+    if ( Vec_IntSize(vTests) > 0 )
+    {
+        int nTests = Vec_IntSize(vTests) / nFuncVars;
+        assert( Vec_IntSize(vTests) % nFuncVars == 0 );
+        printf( "Reading %d pre-computed test patterns from file \"%s\".\n", Vec_IntSize(vTests) / nFuncVars, pPars->pFileName );
+        for ( Iter = 0; Iter < nTests; Iter++ )
+        {
+            abctime clk = Abc_Clock();
+            status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+            clkSat += Abc_Clock() - clk;
+            if ( status == l_Undef )
+            {
+                if ( pPars->fVerbose )
+                    printf( "\n" );
+                printf( "Timeout reached after %d seconds and adding %d tests.\n", pPars->nTimeOut, Iter );
+                goto finish;
+            }
+            if ( status == l_False )
+            {
+                if ( pPars->fVerbose )
+                    printf( "\n" );
+                printf( "The problem is UNSAT after adding %d tests.\n", Iter );
+                goto finish;
+            }
+            // get pattern
+            Vec_IntClear( vLits );
+            for ( i = 0; i < nFuncVars; i++ )
+                Vec_IntPush( vLits, Vec_IntEntry(vTests, Iter*nFuncVars + i) );
+            Gia_ManFaultAddOne( pM, pCnf, pSat, vLits, nFuncVars );
+            if ( pPars->fVerbose )
+            {
+                printf( "Iter%6d : ",       Iter );
+                printf( "Var =%10d  ",      sat_solver_nvars(pSat) );
+                printf( "Clause =%10d  ",   sat_solver_nclauses(pSat) );
+                printf( "Conflict =%10d  ", sat_solver_nconflicts(pSat) );
+                //Abc_PrintTime( 1, "Time", clkSat );
+                ABC_PRTr( "Solver time", clkSat );
+            }
+        }
+    }
+    else if ( pPars->fStartPats )
+    {
+        for ( Iter = 0; Iter < 2; Iter++ )
+        {
+            status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+            if ( status == l_Undef )
+            {
+                if ( pPars->fVerbose )
+                    printf( "\n" );
+                printf( "Timeout reached after %d seconds and %d iterations.\n", pPars->nTimeOut, Iter );
+                goto finish;
+            }
+            if ( status == l_False )
+            {
+                if ( pPars->fVerbose )
+                    printf( "\n" );
+                printf( "The problem is UNSAT after %d iterations.\n", Iter );
+                goto finish;
+            }
+            // initialize simple pattern
+            Vec_IntFill( vLits, nFuncVars, Iter );
+            Vec_IntAppend( vTests, vLits );
+            Gia_ManFaultAddOne( pM, pCnf, pSat, vLits, nFuncVars );
+        }
+    }
+
+    // iterate through the test vectors
+    for ( Iter = pPars->fStartPats ? 2 : Vec_IntSize(vTests) / nFuncVars; Iter < nIterMax; Iter++ )
+    {
+        abctime clk = Abc_Clock();
+        status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        clkSat += Abc_Clock() - clk;
+        if ( pPars->fVerbose )
+        {
+            printf( "Iter%6d : ",       Iter );
+            printf( "Var =%10d  ",      sat_solver_nvars(pSat) );
+            printf( "Clause =%10d  ",   sat_solver_nclauses(pSat) );
+            printf( "Conflict =%10d  ", sat_solver_nconflicts(pSat) );
+            //Abc_PrintTime( 1, "Time", clkSat );
+            ABC_PRTr( "Solver time", clkSat );
+        }
+        if ( status == l_Undef )
+        {
+            if ( pPars->fVerbose )
+                printf( "\n" );
+            printf( "Timeout reached after %d seconds and %d iterations.\n", pPars->nTimeOut, Iter );
+            goto finish;
+        }
+        if ( status == l_False )
+        {
+            if ( pPars->fVerbose )
+                printf( "\n" );
+            printf( "The problem is UNSAT after %d iterations.  ", Iter );
+            break;
+        }
+        assert( status == l_True );
+        // collect SAT assignment
+        Vec_IntClear( vLits );
+        Gia_ManForEachPi( pM, pObj, i )
+            if ( i < nFuncVars )
+                Vec_IntPush( vLits, sat_solver_var_value(pSat, pCnf->pVarNums[Gia_ObjId(pM, pObj)]) );
+        Vec_IntAppend( vTests, vLits );
+        // add constraint
+        Gia_ManFaultAddOne( pM, pCnf, pSat, vLits, nFuncVars );
+    }
+finish:
+    // print results
+//    if ( status == l_False )
+//        Gia_ManPrintResults( p, pSat, Iter, Abc_Clock() - clkTotal );
+    // cleanup
+    Abc_PrintTime( 1, "Testing runtime", Abc_Clock() - clkTotal );
+    // dump the test suite
+    if ( pPars->fDump )
+    {
+        char * pFileName = "tests.txt";
+        Gia_ManDumpTests( vTests, Iter, pFileName );
+        printf( "Dumping %d computed test patterns into file \"%s\".\n", Vec_IntSize(vTests) / nFuncVars, pFileName );
+    }
+
+    // compute untestable faults
+    if ( p != pG || pPars->fDumpUntest )
+    {
+        abctime clkTotal = Abc_Clock();
+        // restart the SAT solver
+        sat_solver_delete( pSat );
+        pSat = sat_solver_new();
+        sat_solver_setnvars( pSat, pCnf->nVars );
+        sat_solver_set_runtime_limit( pSat, pPars->nTimeOut ? pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 );
+        // add timeframe clauses
+        for ( i = 0; i < pCnf->nClauses; i++ )
+            if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
+                assert( 0 );
+        // add constraint to rule out no fault
+//        if ( p == pG )
+        {
+            Vec_IntClear( vLits );
+            Gia_ManForEachPi( pM, pObj, i )
+                if ( i >= nFuncVars )
+                    Vec_IntPush( vLits, Abc_Var2Lit(pCnf->pVarNums[Gia_ObjId(pM, pObj)], 0) );
+            sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
+        }
+        // add cardinality constraint
+        if ( pPars->fBasic )
+        {
+            Vec_IntClear( vLits );
+            Gia_ManForEachPi( pM, pObj, i )
+                if ( i >= nFuncVars )
+                    Vec_IntPush( vLits, pCnf->pVarNums[Gia_ObjId(pM, pObj)] );
+            Cnf_AddCardinConstr( pSat, vLits );
+        }
+        // add output clauses
+        Gia_ManForEachCo( pM, pObj, i )
+        {
+            int Lit = Abc_Var2Lit( pCnf->pVarNums[Gia_ObjId(pM, pObj)], 1 );
+            sat_solver_addclause( pSat, &Lit, &Lit + 1 );
+        }
+        // simplify the SAT solver
+        status = sat_solver_simplify( pSat );
+        assert( status );
+
+        // add test patterns
+        assert( Vec_IntSize(vTests) == Iter * nFuncVars );
+        for ( Iter2 = 0; ; Iter2++ )
+        {
+            abctime clk = Abc_Clock();
+            status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+            clkSat += Abc_Clock() - clk;
+            if ( pPars->fVerbose )
+            {
+                printf( "Iter%6d : ",       Iter2 );
+                printf( "Var =%10d  ",      sat_solver_nvars(pSat) );
+                printf( "Clause =%10d  ",   sat_solver_nclauses(pSat) );
+                printf( "Conflict =%10d  ", sat_solver_nconflicts(pSat) );
+                //Abc_PrintTime( 1, "Time", clkSat );
+                ABC_PRTr( "Solver time", clkSat );
+            }
+            if ( status == l_Undef )
+            {
+                if ( pPars->fVerbose )
+                    printf( "\n" );
+                printf( "Timeout reached after %d seconds and %d iterations.\n", pPars->nTimeOut, Iter2 );
+                goto finish;
+            }
+            if ( Iter2 == Iter )
+                break;
+            assert( status == l_True );
+            // get pattern
+            Vec_IntClear( vLits );
+            for ( i = 0; i < nFuncVars; i++ )
+                Vec_IntPush( vLits, Vec_IntEntry(vTests, Iter2*nFuncVars + i) );
+            Gia_ManFaultAddOne( pM, pCnf, pSat, vLits, nFuncVars );
+        }
+        assert( Iter2 == Iter );
+        if ( pPars->fVerbose )
+            printf( "\n" );
+        if ( p == pG )
+        {
+            if ( status == l_True )
+                printf( "There are untestable faults.  " );
+            else if ( status == l_False )
+                printf( "There is no untestable faults.  " );
+            else assert( 0 );
+            Abc_PrintTime( 1, "Fault computation runtime", Abc_Clock() - clkTotal );
+        }
+        else
+        {
+            if ( status == l_True )
+                printf( "The circuit is rectifiable.  " );
+            else if ( status == l_False )
+                printf( "The circuit is not rectifiable (or equivalent to the golden one).  " );
+            else assert( 0 );
+            Abc_PrintTime( 1, "Rectification runtime", Abc_Clock() - clkTotal );
+        }
+        // dump untestable faults
+        if ( pPars->fDumpUntest && status == l_True )
+        {
+            abctime clk = Abc_Clock();
+            char * pFileName = "untest.txt";
+            int nUntests = Gia_ManDumpUntests( pM, pCnf, pSat, nFuncVars, pFileName, pPars->fVerbose );
+            if ( p == pG )
+                printf( "Dumped %d untestable multiple faults into file \"%s\".  ", nUntests, pFileName );
+            else
+                printf( "Dumped %d ways of rectifying the circuit into file \"%s\".  ", nUntests, pFileName );
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+        }
+    }
+    sat_solver_delete( pSat );
+    Cnf_DataFree( pCnf );
+    Gia_ManStop( pM );
+    Vec_IntFree( vTests );
+    Vec_IntFree( vLits );
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcICheck.c b/abc-build/src/sat/bmc/bmcICheck.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcICheck.c
@@ -0,0 +1,468 @@
+/**CFile****************************************************************
+
+  FileName    [bmcICheck.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    [Performs specialized check.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcICheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bmc.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satStore.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Cnf_Dat_t * Cnf_DeriveGiaRemapped( Gia_Man_t * p )
+{
+    Cnf_Dat_t * pCnf;
+    Aig_Man_t * pAig = Gia_ManToAigSimple( p );
+    pAig->nRegs = 0;
+    pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) );
+    Aig_ManStop( pAig );
+    return pCnf;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Cnf_DataLiftGia( Cnf_Dat_t * p, Gia_Man_t * pGia, int nVarsPlus )
+{
+    Gia_Obj_t * pObj;
+    int v;
+    Gia_ManForEachObj( pGia, pObj, v )
+        if ( p->pVarNums[Gia_ObjId(pGia, pObj)] >= 0 )
+            p->pVarNums[Gia_ObjId(pGia, pObj)] += nVarsPlus;
+    for ( v = 0; v < p->nLiterals; v++ )
+        p->pClauses[0][v] += 2*nVarsPlus;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+sat_solver * Bmc_DeriveSolver( Gia_Man_t * p, Gia_Man_t * pMiter, Cnf_Dat_t * pCnf, int nFramesMax, int nTimeOut, int fVerbose )
+{
+    sat_solver * pSat;
+    Vec_Int_t * vLits;
+    Gia_Obj_t * pObj, * pObj0, * pObj1;
+    int i, k, iVar0, iVar1, iVarOut;
+    int VarShift = 0;
+
+    // start the SAT solver
+    pSat = sat_solver_new();
+    sat_solver_setnvars( pSat, Gia_ManRegNum(p) + Gia_ManCoNum(p) + pCnf->nVars * (nFramesMax + 1) );
+    sat_solver_set_runtime_limit( pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 );
+
+    // add one large OR clause
+    vLits = Vec_IntAlloc( Gia_ManCoNum(p) );
+    Gia_ManForEachCo( p, pObj, i )
+        Vec_IntPush( vLits, Abc_Var2Lit(Gia_ManRegNum(p) + i, 0) );
+    sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
+
+    // load the last timeframe
+    Cnf_DataLiftGia( pCnf, pMiter, Gia_ManRegNum(p) + Gia_ManCoNum(p) );
+    VarShift += Gia_ManRegNum(p) + Gia_ManCoNum(p);
+
+    // add XOR clauses
+    Gia_ManForEachPo( p, pObj, i )
+    {
+        pObj0 = Gia_ManPo( pMiter, 2*i+0 );
+        pObj1 = Gia_ManPo( pMiter, 2*i+1 );
+        iVar0 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj0)];
+        iVar1 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj1)];
+        iVarOut = Gia_ManRegNum(p) + i;
+        sat_solver_add_xor( pSat, iVar0, iVar1, iVarOut, 0 );
+    }
+    Gia_ManForEachRi( p, pObj, i )
+    {
+        pObj0 = Gia_ManRi( pMiter, i );
+        pObj1 = Gia_ManRi( pMiter, i + Gia_ManRegNum(p) );
+        iVar0 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj0)];
+        iVar1 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj1)];
+        iVarOut = Gia_ManRegNum(p) + Gia_ManPoNum(p) + i;
+        sat_solver_add_xor_and( pSat, iVarOut, iVar0, iVar1, i );
+    }
+    // add timeframe clauses
+    for ( i = 0; i < pCnf->nClauses; i++ )
+        if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
+            assert( 0 );
+
+    // add other timeframes
+    for ( k = 0; k < nFramesMax; k++ )
+    {
+        // collect variables of the RO nodes
+        Vec_IntClear( vLits );
+        Gia_ManForEachRo( pMiter, pObj, i )
+            Vec_IntPush( vLits, pCnf->pVarNums[Gia_ObjId(pMiter, pObj)] );
+        // lift CNF again
+        Cnf_DataLiftGia( pCnf, pMiter, pCnf->nVars );
+        VarShift += pCnf->nVars;
+        // stitch the clauses
+        Gia_ManForEachRi( pMiter, pObj, i )
+        {
+            iVar0 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj)];
+            iVar1 = Vec_IntEntry( vLits, i );
+            if ( iVar1 == -1 )
+                continue;
+            sat_solver_add_buffer( pSat, iVar0, iVar1, 0 );
+        }
+        // add equality clauses for the COs
+        Gia_ManForEachPo( p, pObj, i )
+        {
+            pObj0 = Gia_ManPo( pMiter, 2*i+0 );
+            pObj1 = Gia_ManPo( pMiter, 2*i+1 );
+            iVar0 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj0)];
+            iVar1 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj1)];
+            sat_solver_add_buffer( pSat, iVar0, iVar1, 0 );
+        }
+        Gia_ManForEachRi( p, pObj, i )
+        {
+            pObj0 = Gia_ManRi( pMiter, i );
+            pObj1 = Gia_ManRi( pMiter, i + Gia_ManRegNum(p) );
+            iVar0 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj0)];
+            iVar1 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj1)];
+            sat_solver_add_buffer_enable( pSat, iVar0, iVar1, i, 0 );
+        }
+        // add timeframe clauses
+        for ( i = 0; i < pCnf->nClauses; i++ )
+            if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
+                assert( 0 );
+    }
+//    sat_solver_compress( pSat );
+    Cnf_DataLiftGia( pCnf, pMiter, -VarShift );
+    Vec_IntFree( vLits );
+    return pSat;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bmc_PerformICheck( Gia_Man_t * p, int nFramesMax, int nTimeOut, int fEmpty, int fVerbose )
+{
+    int fUseOldCnf = 0;
+    Gia_Man_t * pMiter, * pTemp;
+    Cnf_Dat_t * pCnf;
+    sat_solver * pSat;
+    Vec_Int_t * vLits, * vUsed;
+    int i, status, Lit;
+    int nLitsUsed, nLits, * pLits;
+    abctime clkStart = Abc_Clock();
+    assert( nFramesMax > 0 );
+    assert( Gia_ManRegNum(p) > 0 );
+
+    if ( fVerbose )
+    printf( "Solving M-inductiveness for design %s with %d AND nodes and %d flip-flops:\n",
+        Gia_ManName(p), Gia_ManAndNum(p), Gia_ManRegNum(p) );
+
+    // create miter
+    pTemp = Gia_ManDup( p );
+    pMiter = Gia_ManMiter( p, pTemp, 0, 1, 1, 0, 0 );
+    Gia_ManStop( pTemp );
+    assert( Gia_ManPoNum(pMiter)  == 2 * Gia_ManPoNum(p) );
+    assert( Gia_ManRegNum(pMiter) == 2 * Gia_ManRegNum(p) );
+    // derive CNF
+    if ( fUseOldCnf )
+        pCnf = Cnf_DeriveGiaRemapped( pMiter );
+    else
+    {
+        pMiter = Jf_ManDeriveCnf( pTemp = pMiter, 0 );
+        Gia_ManStop( pTemp );
+        pCnf = (Cnf_Dat_t *)pMiter->pData; pMiter->pData = NULL;
+    }
+
+    // collect positive literals
+    vLits = Vec_IntAlloc( Gia_ManCoNum(p) );
+    for ( i = 0; i < Gia_ManRegNum(p); i++ )
+        Vec_IntPush( vLits, Abc_Var2Lit(i, fEmpty) );
+
+    // iteratively compute a minimal M-inductive set of next-state functions
+    nLitsUsed = fEmpty ? 0 : Vec_IntSize(vLits);
+    vUsed = Vec_IntAlloc( Vec_IntSize(vLits) );
+    while ( 1 )
+    {
+        int fChanges = 0;
+        // derive SAT solver        
+        pSat = Bmc_DeriveSolver( p, pMiter, pCnf, nFramesMax, nTimeOut, fVerbose );
+//        sat_solver_bookmark( pSat );
+        status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        if ( status == l_Undef )
+        {
+            printf( "Timeout reached after %d seconds.\n", nTimeOut );
+            break;
+        }
+        if ( status == l_True )
+        {
+            printf( "The problem is satisfiable (the current set is not M-inductive).\n" );
+            break;
+        }
+        assert( status == l_False );
+        // call analize_final
+        nLits = sat_solver_final( pSat, &pLits );
+        // mark used literals
+        Vec_IntFill( vUsed, Vec_IntSize(vLits), 0 );
+        for ( i = 0; i < nLits; i++ )
+            Vec_IntWriteEntry( vUsed, Abc_Lit2Var(pLits[i]), 1 );
+
+        // check if there are any positive unused
+        Vec_IntForEachEntry( vLits, Lit, i )
+        {
+            assert( i == Abc_Lit2Var(Lit) );
+            if ( Abc_LitIsCompl(Lit) )
+                continue;
+            if ( Vec_IntEntry(vUsed, i) )
+                continue;
+            // positive literal became unused
+            Vec_IntWriteEntry( vLits, i, Abc_LitNot(Lit) );
+            nLitsUsed--;
+            fChanges = 1;
+        }
+        // report the results
+        if ( fVerbose )
+        printf( "M =%4d :  AIG =%8d.  SAT vars =%8d.  SAT conf =%8d.  S =%6d. (%6.2f %%)  ",
+            nFramesMax, (nFramesMax+1) * Gia_ManAndNum(pMiter), 
+            Gia_ManRegNum(p) + Gia_ManCoNum(p) + sat_solver_nvars(pSat), 
+            sat_solver_nconflicts(pSat), nLitsUsed, 100.0 * nLitsUsed / Gia_ManRegNum(p) );
+        if ( fVerbose )
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart );
+        // count the number of negative literals
+        sat_solver_delete( pSat );
+        if ( !fChanges || fEmpty )
+            break;
+//        break;
+//        sat_solver_rollback( pSat );
+    }
+    Cnf_DataFree( pCnf );
+    Gia_ManStop( pMiter );
+    Vec_IntFree( vLits );
+    Vec_IntFree( vUsed );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bmc_PerformISearchOne( Gia_Man_t * p, int nFramesMax, int nTimeOut, int fReverse, int fVerbose, Vec_Int_t * vLits )
+{
+    int fUseOldCnf = 0;
+    Gia_Man_t * pMiter, * pTemp;
+    Cnf_Dat_t * pCnf;
+    sat_solver * pSat;
+//    Vec_Int_t * vLits;
+    int i, Iter, status;
+    int nLitsUsed, RetValue = 0;
+    abctime clkStart = Abc_Clock();
+    assert( nFramesMax > 0 );
+    assert( Gia_ManRegNum(p) > 0 );
+
+    // create miter
+    pTemp = Gia_ManDup( p );
+    pMiter = Gia_ManMiter( p, pTemp, 0, 1, 1, 0, 0 );
+    Gia_ManStop( pTemp );
+    assert( Gia_ManPoNum(pMiter)  == 2 * Gia_ManPoNum(p) );
+    assert( Gia_ManRegNum(pMiter) == 2 * Gia_ManRegNum(p) );
+    // derive CNF
+    if ( fUseOldCnf )
+        pCnf = Cnf_DeriveGiaRemapped( pMiter );
+    else
+    {
+        pMiter = Jf_ManDeriveCnf( pTemp = pMiter, 0 );
+        Gia_ManStop( pTemp );
+        pCnf = (Cnf_Dat_t *)pMiter->pData; pMiter->pData = NULL;
+    }
+/*
+    // collect positive literals
+    vLits = Vec_IntAlloc( Gia_ManCoNum(p) );
+    for ( i = 0; i < Gia_ManRegNum(p); i++ )
+        Vec_IntPush( vLits, Abc_Var2Lit(i, 0) );
+*/
+    // derive SAT solver        
+    pSat = Bmc_DeriveSolver( p, pMiter, pCnf, nFramesMax, nTimeOut, fVerbose );
+    status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( status == l_True )
+    {
+        printf( "I = %4d :  ", nFramesMax );
+        printf( "Problem is satisfiable.\n" );
+        sat_solver_delete( pSat );
+        Cnf_DataFree( pCnf );
+        Gia_ManStop( pMiter );
+        return 1;
+    }
+    if ( status == l_Undef )
+    {
+        printf( "ICheck: Timeout reached after %d seconds.                                                                          \n", nTimeOut );
+        RetValue = 1;
+        goto cleanup;
+    }
+    assert( status == l_False );
+
+    // count the number of positive literals
+    nLitsUsed = 0;
+    for ( i = 0; i < Gia_ManRegNum(p); i++ )
+        if ( !Abc_LitIsCompl(Vec_IntEntry(vLits, i)) )
+            nLitsUsed++;
+
+    // try removing variables
+    for ( Iter = 0; Iter < Gia_ManRegNum(p); Iter++ )
+    {
+        i = fReverse ? Gia_ManRegNum(p) - 1 - Iter : Iter;
+        if ( Abc_LitIsCompl(Vec_IntEntry(vLits, i)) )
+            continue;
+        Vec_IntWriteEntry( vLits, i, Abc_LitNot(Vec_IntEntry(vLits, i)) );
+        status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        if ( status == l_Undef )
+        {
+            printf( "ICheck: Timeout reached after %d seconds.                                                                          \n", nTimeOut );
+            RetValue = 1;
+            goto cleanup;
+        }
+        if ( status == l_True )
+            Vec_IntWriteEntry( vLits, i, Abc_LitNot(Vec_IntEntry(vLits, i)) );
+        else if ( status == l_False )
+            nLitsUsed--;
+        else assert( 0 );
+        // report the results
+        //printf( "Round %d:  ", o );
+        if ( fVerbose )
+        {
+            printf( "I = %4d :  AIG =%8d.  SAT vars =%8d.  SAT conf =%8d.  S =%6d. (%6.2f %%)  ",
+                i, (nFramesMax+1) * Gia_ManAndNum(pMiter), 
+                Gia_ManRegNum(p) + Gia_ManCoNum(p) + sat_solver_nvars(pSat), 
+                sat_solver_nconflicts(pSat), nLitsUsed, 100.0 * nLitsUsed / Gia_ManRegNum(p) );
+            ABC_PRTr( "Time", Abc_Clock() - clkStart );
+            fflush( stdout );
+        }
+    }
+    // report the results
+    //printf( "Round %d:  ", o );
+    if ( fVerbose )
+    {
+        printf( "M = %4d :  AIG =%8d.  SAT vars =%8d.  SAT conf =%8d.  S =%6d. (%6.2f %%)  ",
+            nFramesMax, (nFramesMax+1) * Gia_ManAndNum(pMiter), 
+            Gia_ManRegNum(p) + Gia_ManCoNum(p) + sat_solver_nvars(pSat), 
+            sat_solver_nconflicts(pSat), nLitsUsed, 100.0 * nLitsUsed / Gia_ManRegNum(p) );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart );
+        fflush( stdout );
+    }
+cleanup:
+    // cleanup
+    sat_solver_delete( pSat );
+    Cnf_DataFree( pCnf );
+    Gia_ManStop( pMiter );
+//    Vec_IntFree( vLits );
+    return RetValue;
+}
+Vec_Int_t * Bmc_PerformISearch( Gia_Man_t * p, int nFramesMax, int nTimeOut, int fReverse, int fDump, int fVerbose )
+{
+    Vec_Int_t * vLits, * vFlops;
+    int i, f;
+    if ( fVerbose )
+    printf( "Solving M-inductiveness for design %s with %d AND nodes and %d flip-flops:\n",
+        Gia_ManName(p), Gia_ManAndNum(p), Gia_ManRegNum(p) );
+    fflush( stdout );
+
+    // collect positive literals
+    vLits = Vec_IntAlloc( Gia_ManCoNum(p) );
+    for ( i = 0; i < Gia_ManRegNum(p); i++ )
+        Vec_IntPush( vLits, Abc_Var2Lit(i, 0) );
+
+    for ( f = 1; f <= nFramesMax; f++ )
+        if ( Bmc_PerformISearchOne( p, f, nTimeOut, fReverse, fVerbose, vLits ) )
+        {
+            Vec_IntFree( vLits );
+            return NULL;
+        }
+
+    // dump the numbers of the flops
+    if ( fDump )
+    {
+        int nLitsUsed = 0;
+        for ( i = 0; i < Gia_ManRegNum(p); i++ )
+            if ( !Abc_LitIsCompl(Vec_IntEntry(vLits, i)) )
+                nLitsUsed++;
+        printf( "The set contains %d (out of %d) next-state functions with 0-based numbers:\n", nLitsUsed, Gia_ManRegNum(p) );
+        for ( i = 0; i < Gia_ManRegNum(p); i++ )
+            if ( !Abc_LitIsCompl(Vec_IntEntry(vLits, i)) )
+                printf( "%d ", i );
+        printf( "\n" );
+    }       
+    // save flop indexes
+    vFlops = Vec_IntAlloc( Gia_ManRegNum(p) );
+    for ( i = 0; i < Gia_ManRegNum(p); i++ )
+        if ( !Abc_LitIsCompl(Vec_IntEntry(vLits, i)) )
+            Vec_IntPush( vFlops, 1 );
+        else
+            Vec_IntPush( vFlops, 0 );
+    Vec_IntFree( vLits );
+    return vFlops;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcInse.c b/abc-build/src/sat/bmc/bmcInse.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcInse.c
@@ -0,0 +1,345 @@
+/**CFile****************************************************************
+
+  FileName    [bmcInse.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcInse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bmc.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satStore.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline void   Gia_ParTestAlloc( Gia_Man_t * p, int nWords ) { assert( !p->pData ); p->pData = (unsigned *)ABC_ALLOC(word, 2*nWords*Gia_ManObjNum(p)); p->iData = nWords; }
+static inline void   Gia_ParTestFree( Gia_Man_t * p )              { ABC_FREE( p->pData ); p->iData = 0;             }
+static inline word * Gia_ParTestObj( Gia_Man_t * p, int Id )       { return (word *)p->pData + Id*(p->iData << 1);   }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManInseInit( Gia_Man_t * p, Vec_Int_t * vInit )
+{
+    Gia_Obj_t * pObj;
+    word * pData1, * pData0;
+    int i, k;
+    Gia_ManForEachRi( p, pObj, k )
+    {
+        pData0 = Gia_ParTestObj( p, Gia_ObjId(p, pObj) );
+        pData1 = pData0 + p->iData;
+        if ( Vec_IntEntry(vInit, k) == 0 ) // 0
+            for ( i = 0; i < p->iData; i++ )
+                pData0[i] = ~(word)0, pData1[i] = 0;
+        else if ( Vec_IntEntry(vInit, k) == 1 ) // 1
+            for ( i = 0; i < p->iData; i++ )
+                pData0[i] = 0, pData1[i] = ~(word)0;
+        else // if ( Vec_IntEntry(vInit, k) > 1 ) // X
+            for ( i = 0; i < p->iData; i++ )
+                pData0[i] = pData1[i] = 0;
+    }
+}
+void Gia_ManInseSimulateObj( Gia_Man_t * p, int Id )
+{
+    Gia_Obj_t * pObj = Gia_ManObj( p, Id );
+    word * pData0, * pDataA0, * pDataB0;
+    word * pData1, * pDataA1, * pDataB1;
+    int i;
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        pData0  = Gia_ParTestObj( p, Id );
+        pData1  = pData0 + p->iData;
+        if ( Gia_ObjFaninC0(pObj) )
+        {
+            pDataA1 = Gia_ParTestObj( p, Gia_ObjFaninId0(pObj, Id) );
+            pDataA0 = pDataA1 + p->iData;
+            if ( Gia_ObjFaninC1(pObj) )
+            {
+                pDataB1 = Gia_ParTestObj( p, Gia_ObjFaninId1(pObj, Id) );
+                pDataB0 = pDataB1 + p->iData;
+            }
+            else 
+            {
+                pDataB0 = Gia_ParTestObj( p, Gia_ObjFaninId1(pObj, Id) );
+                pDataB1 = pDataB0 + p->iData;
+            }
+        }
+        else 
+        {
+            pDataA0 = Gia_ParTestObj( p, Gia_ObjFaninId0(pObj, Id) );
+            pDataA1 = pDataA0 + p->iData;
+            if ( Gia_ObjFaninC1(pObj) )
+            {
+                pDataB1 = Gia_ParTestObj( p, Gia_ObjFaninId1(pObj, Id) );
+                pDataB0 = pDataB1 + p->iData;
+            }
+            else 
+            {
+                pDataB0 = Gia_ParTestObj( p, Gia_ObjFaninId1(pObj, Id) );
+                pDataB1 = pDataB0 + p->iData;
+            }
+        }
+        for ( i = 0; i < p->iData; i++ )
+            pData0[i] = pDataA0[i] | pDataB0[i], pData1[i] = pDataA1[i] & pDataB1[i];
+    }
+    else if ( Gia_ObjIsCo(pObj) )
+    {
+        pData0  = Gia_ParTestObj( p, Id );
+        pData1  = pData0 + p->iData;
+        if ( Gia_ObjFaninC0(pObj) )
+        {
+            pDataA1 = Gia_ParTestObj( p, Gia_ObjFaninId0(pObj, Id) );
+            pDataA0 = pDataA1 + p->iData;
+        }
+        else 
+        {
+            pDataA0 = Gia_ParTestObj( p, Gia_ObjFaninId0(pObj, Id) );
+            pDataA1 = pDataA0 + p->iData;
+        }
+        for ( i = 0; i < p->iData; i++ )
+            pData0[i] = pDataA0[i], pData1[i] = pDataA1[i];
+    }
+    else if ( Gia_ObjIsCi(pObj) )
+    {
+        if ( Gia_ObjIsPi(p, pObj) )
+        {
+            pData0  = Gia_ParTestObj( p, Id );
+            pData1  = pData0 + p->iData;
+            for ( i = 0; i < p->iData; i++ )
+                pData0[i] = Gia_ManRandomW(0), pData1[i] = ~pData0[i];
+        }
+        else
+        {
+            int Id2 = Gia_ObjId(p, Gia_ObjRoToRi(p, pObj));
+            pData0  = Gia_ParTestObj( p, Id );
+            pData1  = pData0 + p->iData;
+            pDataA0 = Gia_ParTestObj( p, Id2 );
+            pDataA1 = pDataA0 + p->iData;
+            for ( i = 0; i < p->iData; i++ )
+                pData0[i] = pDataA0[i], pData1[i] = pDataA1[i];
+        }
+    }
+    else if ( Gia_ObjIsConst0(pObj) )
+    {
+        pData0  = Gia_ParTestObj( p, Id );
+        pData1  = pData0 + p->iData;
+        for ( i = 0; i < p->iData; i++ )
+            pData0[i] = ~(word)0, pData1[i] = 0;
+    }
+    else assert( 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManInseHighestScore( Gia_Man_t * p, int * pCost )
+{
+    Gia_Obj_t * pObj;
+    word * pData0, * pData1;
+    int * pCounts, CountBest;
+    int i, k, b, nPats, iPat;
+    nPats = 64 * p->iData;
+    pCounts = ABC_CALLOC( int, nPats );
+    Gia_ManForEachRi( p, pObj, k )
+    {
+        pData0 = Gia_ParTestObj( p, Gia_ObjId(p, pObj) );
+        pData1 = pData0 + p->iData;
+        for ( i = 0; i < p->iData; i++ )
+            for ( b = 0; b < 64; b++ )
+                pCounts[64*i+b] += (((pData0[i] >> b) & 1) || ((pData1[i] >> b) & 1)); // binary
+    }
+    iPat = 0;
+    CountBest = pCounts[0]; 
+    for ( k = 1; k < nPats; k++ )
+        if ( CountBest < pCounts[k] )
+            CountBest = pCounts[k], iPat = k;
+    *pCost = Gia_ManRegNum(p) - CountBest; // ternary
+    ABC_FREE( pCounts );
+    return iPat;
+}
+void Gia_ManInseFindStarting( Gia_Man_t * p, int iPat, Vec_Int_t * vInit, Vec_Int_t * vInputs )
+{
+    Gia_Obj_t * pObj;
+    word * pData0, * pData1;
+    int i, k;
+    Vec_IntClear( vInit );
+    Gia_ManForEachRi( p, pObj, k )
+    {
+        pData0 = Gia_ParTestObj( p, Gia_ObjId(p, pObj) );
+        pData1 = pData0 + p->iData;
+        for ( i = 0; i < p->iData; i++ )
+            assert( (pData0[i] & pData1[i]) == 0 );
+        if ( Abc_InfoHasBit( (unsigned *)pData0, iPat ) )
+            Vec_IntPush( vInit, 0 );
+        else if ( Abc_InfoHasBit( (unsigned *)pData1, iPat ) )
+            Vec_IntPush( vInit, 1 );
+        else 
+            Vec_IntPush( vInit, 2 );
+    }
+    Gia_ManForEachPi( p, pObj, k )
+    {
+        pData0 = Gia_ParTestObj( p, Gia_ObjId(p, pObj) );
+        pData1 = pData0 + p->iData;
+        for ( i = 0; i < p->iData; i++ )
+            assert( (pData0[i] & pData1[i]) == 0 );
+        if ( Abc_InfoHasBit( (unsigned *)pData0, iPat ) )
+            Vec_IntPush( vInputs, 0 );
+        else if ( Abc_InfoHasBit( (unsigned *)pData1, iPat ) )
+            Vec_IntPush( vInputs, 1 );
+        else 
+            Vec_IntPush( vInputs, 2 );
+    }
+}
+Vec_Int_t * Gia_ManInseSimulate( Gia_Man_t * p, Vec_Int_t * vInit0, Vec_Int_t * vInputs, Vec_Int_t * vInit )
+{
+    Vec_Int_t * vRes;
+    Gia_Obj_t * pObj, * pObjRo, * pObjRi;
+    int nFrames = Vec_IntSize(vInputs) / Gia_ManPiNum(p);
+    int i, f, iBit = 0;
+    assert( Vec_IntSize(vInputs) % Gia_ManPiNum(p) == 0 );
+    assert( Vec_IntSize(vInit0) == Gia_ManRegNum(p) );
+    assert( Vec_IntSize(vInit) == Gia_ManRegNum(p) );
+    Gia_ManConst0(p)->fMark0 = 0;
+    Gia_ManForEachRi( p, pObj, i )
+        pObj->fMark0 = Vec_IntEntry(vInit0, i);
+    for ( f = 0; f < nFrames; f++ )
+    {
+        Gia_ManForEachPi( p, pObj, i )
+            pObj->fMark0 = Vec_IntEntry(vInputs, iBit++);
+        Gia_ManForEachAnd( p, pObj, i )
+            pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & 
+                           (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+        Gia_ManForEachRi( p, pObj, i )
+            pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
+        Gia_ManForEachRiRo( p, pObjRi, pObjRo, i )
+            pObjRo->fMark0 = pObjRi->fMark0;
+    }
+    assert( iBit == Vec_IntSize(vInputs) );
+    vRes = Vec_IntAlloc( Gia_ManRegNum(p) );
+    Gia_ManForEachRo( p, pObj, i )
+        assert( Vec_IntEntry(vInit, i) == 2 || Vec_IntEntry(vInit, i) == (int)pObj->fMark0 );
+    Gia_ManForEachRo( p, pObj, i )
+        Vec_IntPush( vRes, pObj->fMark0 | (Vec_IntEntry(vInit, i) != 2 ? 4 : 0) );
+    Gia_ManForEachObj( p, pObj, i )
+        pObj->fMark0 = 0;
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManInsePerform( Gia_Man_t * p, Vec_Int_t * vInit0, int nFrames, int nWords, int fVerbose )
+{
+    Vec_Int_t * vRes, * vInit, * vInputs;
+    Gia_Obj_t * pObj;
+    int i, f, iPat, Cost, Cost0;
+    abctime clk, clkTotal = Abc_Clock();
+    Gia_ManRandomW( 1 );
+    if ( fVerbose )
+        printf( "Running with %d frames, %d words, and %sgiven init state.\n", nFrames, nWords, vInit0 ? "":"no " );
+    vInit = Vec_IntAlloc(0); Vec_IntFill( vInit, Gia_ManRegNum(p), 2 );
+    vInputs = Vec_IntStart( Gia_ManPiNum(p) * nFrames );
+    Gia_ParTestAlloc( p, nWords );
+    Gia_ManInseInit( p, vInit );
+    Cost0 = 0;
+    Vec_IntForEachEntry( vInit, iPat, i )
+        Cost0 += ((iPat >> 1) & 1);
+    if ( fVerbose )
+        printf( "Frame =%6d : Values =%6d (out of %6d)\n", 0, Cost0, Cost0 );
+    for ( f = 0; f < nFrames; f++ )
+    {
+        clk = Abc_Clock();
+        Gia_ManForEachObj( p, pObj, i )
+            Gia_ManInseSimulateObj( p, i );
+        iPat = Gia_ManInseHighestScore( p, &Cost );
+        Gia_ManInseFindStarting( p, iPat, vInit, vInputs );
+        Gia_ManInseInit( p, vInit );
+        if ( fVerbose )
+            printf( "Frame =%6d : Values =%6d (out of %6d)   ", f+1, Cost, Cost0 );
+        if ( fVerbose )
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    Gia_ParTestFree( p );
+    vRes = Gia_ManInseSimulate( p, vInit0, vInputs, vInit );
+    Vec_IntFreeP( &vInit );
+    Vec_IntFreeP( &vInputs );
+    printf( "After %d frames, found a sequence to produce %d x-values (out of %d).  ", f, Cost, Gia_ManRegNum(p) );
+    Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal );
+    return vRes;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManInseTest( Gia_Man_t * p, Vec_Int_t * vInit0, int nFrames, int nWords, int nTimeOut, int fSim, int fVerbose )
+{
+    Vec_Int_t * vRes, * vInit;
+    vInit = Vec_IntAlloc(0); Vec_IntFill( vInit, Gia_ManRegNum(p), 0 );
+    vRes = Gia_ManInsePerform( p, vInit, nFrames, nWords, fVerbose );
+    if ( vInit != vInit0 )
+        Vec_IntFree( vInit );
+    return vRes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcLoad.c b/abc-build/src/sat/bmc/bmcLoad.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcLoad.c
@@ -0,0 +1,212 @@
+/**CFile****************************************************************
+
+  FileName    [bmcLoad.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    [Experiments with CNF loading.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcLoad.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bmc.h"
+#include "sat/bsat/satStore.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Bmc_Load_t_ Bmc_Load_t;  
+struct Bmc_Load_t_
+{
+    Bmc_AndPar_t *   pPars;     // parameters
+    Gia_Man_t *      pGia;      // unrolled AIG
+    sat_solver *     pSat;      // SAT solvers
+    Vec_Int_t *      vSat2Id;   // maps SAT var into its node
+//    Vec_Int_t *      vCut;      // cut in terms of GIA IDs
+//    Vec_Int_t *      vCnf;      // CNF for the cut
+    int              nCallBacks1; 
+    int              nCallBacks2; 
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    [Load CNF for the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Bmc_LoadGetSatVar( Bmc_Load_t * p, int Id )
+{
+    Gia_Obj_t * pObj = Gia_ManObj( p->pGia, Id );
+    if ( pObj->Value == 0 )
+    {
+        pObj->Value = Vec_IntSize( p->vSat2Id );
+        Vec_IntPush( p->vSat2Id, Id );
+        sat_solver_setnvars( p->pSat, Vec_IntSize(p->vSat2Id) );
+    }
+    return pObj->Value;
+}
+int Bmc_LoadAddCnf( void * pMan, int iLit )
+{
+    Bmc_Load_t * p = (Bmc_Load_t *)pMan;
+    int Lits[3], iVar = Abc_Lit2Var(iLit);
+    Gia_Obj_t * pObj = Gia_ManObj( p->pGia, Vec_IntEntry(p->vSat2Id, iVar) );
+    p->nCallBacks1++;
+    if ( Gia_ObjIsCi(pObj) || Gia_ObjIsConst0(pObj) )
+        return 0;
+    assert( Gia_ObjIsAnd(pObj) );
+    if ( (Abc_LitIsCompl(iLit) ? pObj->fMark1 : pObj->fMark0) )
+        return 0;
+    Lits[0] = Abc_LitNot(iLit);
+    if ( Abc_LitIsCompl(iLit) )
+    {
+        Lits[1] = Abc_Var2Lit( Bmc_LoadGetSatVar(p, Gia_ObjFaninId0p(p->pGia, pObj)), !Gia_ObjFaninC0(pObj) );
+        Lits[2] = Abc_Var2Lit( Bmc_LoadGetSatVar(p, Gia_ObjFaninId1p(p->pGia, pObj)), !Gia_ObjFaninC1(pObj) );
+        sat_solver_clause_new( p->pSat, Lits, Lits + 3, 0 );
+        pObj->fMark1 = 1;
+    }
+    else
+    {
+        Lits[1] = Abc_Var2Lit( Bmc_LoadGetSatVar(p, Gia_ObjFaninId0p(p->pGia, pObj)), Gia_ObjFaninC0(pObj) );
+        sat_solver_clause_new( p->pSat, Lits, Lits + 2, 0 );
+        Lits[1] = Abc_Var2Lit( Bmc_LoadGetSatVar(p, Gia_ObjFaninId1p(p->pGia, pObj)), Gia_ObjFaninC1(pObj) );
+        sat_solver_clause_new( p->pSat, Lits, Lits + 2, 0 );
+        pObj->fMark0 = 1;
+    }
+    p->nCallBacks2++;
+    return 1;
+}
+int Bmc_LoadAddCnf_rec( Bmc_Load_t * p, int Id )
+{
+    int iVar = Bmc_LoadGetSatVar( p, Id );
+    Gia_Obj_t * pObj = Gia_ManObj( p->pGia, Id );
+    if ( Gia_ObjIsAnd(pObj) && !(pObj->fMark0 && pObj->fMark1) )
+    {
+        Bmc_LoadAddCnf( p, Abc_Var2Lit(iVar, 0) );
+        Bmc_LoadAddCnf( p, Abc_Var2Lit(iVar, 1) );
+        Bmc_LoadAddCnf_rec( p, Gia_ObjFaninId0(pObj, Id) );
+        Bmc_LoadAddCnf_rec( p, Gia_ObjFaninId1(pObj, Id) );
+    }
+    return iVar;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Bmc_Load_t * Bmc_LoadStart( Gia_Man_t * pGia )
+{
+    Bmc_Load_t * p;
+    int Lit;
+    Gia_ManSetPhase( pGia );
+    Gia_ManCleanValue( pGia );
+    Gia_ManCreateRefs( pGia );
+    p = ABC_CALLOC( Bmc_Load_t, 1 );
+    p->pGia      = pGia;
+    p->pSat      = sat_solver_new();
+    p->vSat2Id   = Vec_IntAlloc( 1000 );
+    Vec_IntPush( p->vSat2Id, 0 );
+    // create constant node
+    Lit = Abc_Var2Lit( Bmc_LoadGetSatVar(p, 0), 1 );
+    sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+    return p;
+}
+void Bmc_LoadStop( Bmc_Load_t * p )
+{
+    Vec_IntFree( p->vSat2Id );
+    sat_solver_delete( p->pSat );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Bmc_LoadTest( Gia_Man_t * pGia, int fLoadCnf, int fVerbose )
+{
+    int nConfLimit = 0;
+    Bmc_Load_t * p;
+    Gia_Obj_t * pObj;
+    int i, status, Lit;
+    abctime clk = Abc_Clock();
+    // create the loading manager
+    p = Bmc_LoadStart( pGia );
+    // add callback for CNF loading
+    if ( fLoadCnf )
+    {
+        p->pSat->pCnfMan  = p;
+        p->pSat->pCnfFunc = Bmc_LoadAddCnf;
+    }
+    // solve SAT problem for each PO
+    Gia_ManForEachPo( pGia, pObj, i )
+    {
+        if ( fLoadCnf )
+            Lit = Abc_Var2Lit( Bmc_LoadGetSatVar(p, Gia_ObjFaninId0p(pGia, pObj)), Gia_ObjFaninC0(pObj) );
+        else
+            Lit = Abc_Var2Lit( Bmc_LoadAddCnf_rec(p, Gia_ObjFaninId0p(pGia, pObj)), Gia_ObjFaninC0(pObj) );
+        if ( fVerbose )
+        {
+            printf( "Frame%4d :  ", i );
+            printf( "Vars = %6d  ", Vec_IntSize(p->vSat2Id) );
+            printf( "Clas = %6d  ", sat_solver_nclauses(p->pSat) );
+        }
+        status = sat_solver_solve( p->pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        if ( fVerbose )
+        {
+            printf( "Conf = %6d  ", sat_solver_nconflicts(p->pSat) );
+            if ( status == l_False )
+                printf( "UNSAT  " );
+            else if ( status == l_True )
+                printf( "SAT    " );
+            else // if ( status == l_Undec )
+                printf( "UNDEC  " );
+            Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+        }
+    }
+    printf( "Callbacks = %d.  Loadings = %d.\n", p->nCallBacks1, p->nCallBacks2 );
+    Bmc_LoadStop( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcMaxi.c b/abc-build/src/sat/bmc/bmcMaxi.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcMaxi.c
@@ -0,0 +1,282 @@
+/**CFile****************************************************************
+
+  FileName    [bmcMaxi.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcMaxi.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bmc.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satStore.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Cnf_Dat_t * Cnf_DeriveGiaRemapped( Gia_Man_t * p )
+{
+    Cnf_Dat_t * pCnf;
+    Aig_Man_t * pAig = Gia_ManToAigSimple( p );
+    pAig->nRegs = 0;
+    pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) );
+    Aig_ManStop( pAig );
+    return pCnf;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManMaxiUnfold( Gia_Man_t * p, int nFrames, int fUseVars, Vec_Int_t * vInit )
+{
+    Gia_Man_t * pNew, * pTemp;
+    Gia_Obj_t * pObj;
+    int i, f;
+    pNew = Gia_ManStart( fUseVars * 2 * Gia_ManRegNum(p) + nFrames * Gia_ManObjNum(p) );
+    pNew->pName = Abc_UtilStrsav( p->pName );
+    Gia_ManHashAlloc( pNew );
+    Gia_ManConst0(p)->Value = 0;
+    // control/data variables
+    Gia_ManForEachRo( p, pObj, i )
+        Gia_ManAppendCi( pNew );
+    Gia_ManForEachRo( p, pObj, i )
+        Gia_ManAppendCi( pNew );
+    // build timeframes
+    assert( !vInit || Vec_IntSize(vInit) == Gia_ManRegNum(p) );
+    Gia_ManForEachRo( p, pObj, i )
+    {
+        int Value = Vec_IntEntry( vInit, i );
+        int iCtrl = Gia_ManCiLit( pNew, i );
+        int iData = Gia_ManCiLit( pNew, Gia_ManRegNum(p)+i );
+        // decide based on Value
+        if ( Value == 0 )
+            pObj->Value = fUseVars ? Gia_ManHashAnd(pNew, iCtrl, iData) : 0;
+        else if ( Value == 1 )
+            pObj->Value = fUseVars ? Gia_ManHashOr(pNew, Abc_LitNot(iCtrl), iData) : 1;
+        else if ( Value == 2 )
+            pObj->Value = Gia_ManHashAnd(pNew, iCtrl, iData);
+        else if ( Value == 3 )
+            pObj->Value = Gia_ManHashOr(pNew, Abc_LitNot(iCtrl), iData);
+        else if ( Value == 4 )
+            pObj->Value = 0;
+        else if ( Value == 5 )
+            pObj->Value = 1;
+        else assert( 0 );
+    }
+    for ( f = 0; f < nFrames; f++ )
+    {
+        Gia_ManForEachPi( p, pObj, i )
+            pObj->Value = Gia_ManAppendCi( pNew );
+        Gia_ManForEachAnd( p, pObj, i )
+            pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        Gia_ManForEachRi( p, pObj, i )
+            pObj->Value = Gia_ObjFanin0Copy(pObj);
+        Gia_ManForEachRo( p, pObj, i )
+            pObj->Value = Gia_ObjRoToRi(p, pObj)->Value;
+    }
+    Gia_ManForEachRi( p, pObj, i )
+        pObj->Value = Gia_ManAppendCo( pNew, pObj->Value );
+    pNew = Gia_ManCleanup( pTemp = pNew );
+    Gia_ManStop( pTemp );
+    assert( Gia_ManPiNum(pNew) == 2 * Gia_ManRegNum(p) + nFrames * Gia_ManPiNum(p) );
+    return pNew;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManMaxiPerform( Gia_Man_t * p, Vec_Int_t * vInit, int nFrames, int nTimeOut, int fVerbose )
+{
+    int nIterMax = 1000000;
+    int i, iLit, Iter, status;
+    int nLits, * pLits;
+    abctime clkTotal = Abc_Clock();
+    abctime clkSat = 0;
+    Vec_Int_t * vLits, * vMap;
+    sat_solver * pSat;
+    Gia_Obj_t * pObj;
+    Gia_Man_t * p0 = Gia_ManMaxiUnfold( p, nFrames, 0, vInit );
+    Gia_Man_t * p1 = Gia_ManMaxiUnfold( p, nFrames, 1, vInit );
+    Gia_Man_t * pM = Gia_ManMiter( p0, p1, 0, 0, 0, 0, 0 );
+    Cnf_Dat_t * pCnf = Cnf_DeriveGiaRemapped( pM );
+    Gia_ManStop( p0 );
+    Gia_ManStop( p1 );
+    assert( Gia_ManRegNum(p) > 0 );
+    if ( fVerbose )
+        printf( "Running with %d frames and %sgiven init state.\n", nFrames, vInit ? "":"no " );
+
+    pSat = sat_solver_new();
+    sat_solver_setnvars( pSat, pCnf->nVars );
+    sat_solver_set_runtime_limit( pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 );
+    for ( i = 0; i < pCnf->nClauses; i++ )
+        if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
+            assert( 0 );
+
+    // add one large OR clause
+    vLits = Vec_IntAlloc( Gia_ManCoNum(p) );
+    Gia_ManForEachCo( pM, pObj, i )
+        Vec_IntPush( vLits, Abc_Var2Lit(pCnf->pVarNums[Gia_ObjId(pM, pObj)], 0) );
+    sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
+
+    // create assumptions
+    Vec_IntClear( vLits );
+    Gia_ManForEachPi( pM, pObj, i )
+        if ( i == Gia_ManRegNum(p) )
+            break;
+        else if ( Vec_IntEntry(vInit, i) == 0 || Vec_IntEntry(vInit, i) == 1 )
+            Vec_IntPush( vLits, Abc_Var2Lit(pCnf->pVarNums[Gia_ObjId(pM, pObj)], 1) );
+
+    if ( fVerbose )
+    {
+        printf( "Iter%6d : ",       0 );
+        printf( "Var =%10d  ",      sat_solver_nvars(pSat) );
+        printf( "Clause =%10d  ",   sat_solver_nclauses(pSat) );
+        printf( "Conflict =%10d  ", sat_solver_nconflicts(pSat) );
+        printf( "Subset =%6d  ",    Vec_IntSize(vLits) );
+        Abc_PrintTime( 1, "Time", clkSat );
+//      ABC_PRTr( "Solver time", clkSat );
+    }
+    for ( Iter = 0; Iter < nIterMax; Iter++ )
+    {
+        abctime clk = Abc_Clock();
+        status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+        clkSat += Abc_Clock() - clk;
+        if ( status == l_Undef )
+        {
+//            if ( fVerbose )
+//                printf( "\n" );
+            printf( "Timeout reached after %d seconds and %d iterations.  ", nTimeOut, Iter );
+            break;
+        }
+        if ( status == l_True )
+        {
+//            if ( fVerbose )
+//                printf( "\n" );
+            printf( "The problem is SAT after %d iterations.  ", Iter );
+            break;
+        }
+        assert( status == l_False );
+        nLits = sat_solver_final( pSat, &pLits );
+        if ( fVerbose )
+        {
+            printf( "Iter%6d : ",       Iter+1 );
+            printf( "Var =%10d  ",      sat_solver_nvars(pSat) );
+            printf( "Clause =%10d  ",   sat_solver_nclauses(pSat) );
+            printf( "Conflict =%10d  ", sat_solver_nconflicts(pSat) );
+            printf( "Subset =%6d  ",    nLits );
+            Abc_PrintTime( 1, "Time", clkSat );
+//            ABC_PRTr( "Solver time", clkSat );
+        }
+        if ( Vec_IntSize(vLits) == nLits )
+        {
+//            if ( fVerbose )
+//                printf( "\n" );
+            printf( "Reached fixed point with %d entries after %d iterations.  ", Vec_IntSize(vLits), Iter+1 );
+            break;
+        }
+        // collect used literals
+        Vec_IntClear( vLits );
+        for ( i = 0; i < nLits; i++ )
+            Vec_IntPush( vLits, Abc_LitNot(pLits[i]) );
+    }
+    // create map
+    vMap = Vec_IntStart( pCnf->nVars );
+    Vec_IntForEachEntry( vLits, iLit, i )
+        Vec_IntWriteEntry( vMap, Abc_Lit2Var(iLit), 1 );
+
+    // create output
+    Vec_IntFree( vLits );
+    vLits = Vec_IntDup(vInit);
+    Gia_ManForEachPi( pM, pObj, i )
+        if ( i == Gia_ManRegNum(p) )
+            break;
+        else if ( Vec_IntEntry(vLits, i) == 4 || Vec_IntEntry(vLits, i) == 5 )
+            Vec_IntWriteEntry( vLits, i, Vec_IntEntry(vLits, i) );
+        else if ( (Vec_IntEntry(vLits, i) == 0 || Vec_IntEntry(vLits, i) == 1) && !Vec_IntEntry(vMap, pCnf->pVarNums[Gia_ObjId(pM, pObj)]) )
+            Vec_IntWriteEntry( vLits, i, Vec_IntEntry(vLits, i) | 2 );
+    Vec_IntFree( vMap );
+
+    // cleanup
+    sat_solver_delete( pSat );
+    Cnf_DataFree( pCnf );
+    Gia_ManStop( pM );
+    Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal );
+    return vLits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManMaxiTest( Gia_Man_t * p, Vec_Int_t * vInit0, int nFrames, int nWords, int nTimeOut, int fSim, int fVerbose )
+{
+    Vec_Int_t * vRes, * vInit;
+    vInit = vInit0 ? vInit0 : Vec_IntStart( Gia_ManRegNum(p) );
+    vRes = Gia_ManMaxiPerform( p, vInit, nFrames, nTimeOut, fVerbose );
+    if ( vInit != vInit0 )
+        Vec_IntFree( vInit );
+    return vRes;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcMulti.c b/abc-build/src/sat/bmc/bmcMulti.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcMulti.c
@@ -0,0 +1,296 @@
+/**CFile****************************************************************
+
+  FileName    [bmcMulti.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    [Proving multi-output properties.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmcMulti.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bmc.h"
+#include "proof/ssw/ssw.h"
+#include "misc/extra/extra.h"
+#include "aig/gia/giaAig.h"
+#include "aig/ioa/ioa.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Divides outputs into solved and unsolved.]
+
+  Description [Return array of unsolved outputs to extract into a new AIG.
+  Updates the resulting CEXes (vCexesOut) and current output map (vOutMap).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManProcessOutputs( Vec_Ptr_t * vCexesIn, Vec_Ptr_t * vCexesOut, Vec_Int_t * vOutMap )
+{
+    Abc_Cex_t * pCex; 
+    Vec_Int_t * vLeftOver;
+    int i, iOut;
+    assert( Vec_PtrSize(vCexesIn) == Vec_IntSize(vOutMap) );
+    vLeftOver = Vec_IntAlloc( Vec_PtrSize(vCexesIn) );
+    Vec_IntForEachEntry( vOutMap, iOut, i )
+    {
+        assert( Vec_PtrEntry(vCexesOut, iOut) == NULL );
+        pCex = (Abc_Cex_t *)Vec_PtrEntry( vCexesIn, i );
+        if ( pCex ) // found a CEX for output iOut
+        {
+            Vec_PtrWriteEntry( vCexesIn, i, NULL );
+            Vec_PtrWriteEntry( vCexesOut, iOut, pCex );
+        }
+        else // still unsolved
+        {
+            Vec_IntWriteEntry( vOutMap, Vec_IntSize(vLeftOver), iOut );
+            Vec_IntPush( vLeftOver, i );
+        }
+    }
+    Vec_IntShrink( vOutMap, Vec_IntSize(vLeftOver) );
+    return vLeftOver;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of constant 0 POs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Gia_ManCountConst0PosGia( Gia_Man_t * p )
+{
+    Gia_Obj_t * pObj;
+    int i, Counter = 0;
+    Gia_ManForEachPo( p, pObj, i )
+        Counter += (Gia_ObjFaninLit0p(p, pObj) == 0);
+    return Counter;
+}
+int Gia_ManCountConst0Pos( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i, Counter = 0;
+    Saig_ManForEachPo( p, pObj, i )
+        Counter += (Aig_ObjChild0(pObj) == Aig_ManConst0(p));
+    return Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Gia_ManMultiReport( Aig_Man_t * p, char * pStr, int nTotalPo, int nTotalSize, abctime clkStart )
+{
+    printf( "%3s : ", pStr );
+    printf( "PI =%6d  ", Saig_ManPiNum(p) );
+    printf( "PO =%6d  ", Saig_ManPoNum(p) );
+    printf( "FF =%7d  ", Saig_ManRegNum(p) );
+    printf( "ND =%7d  ", Aig_ManNodeNum(p) );
+    printf( "Solved =%7d (%5.1f %%)  ", nTotalPo-Saig_ManPoNum(p), 100.0*(nTotalPo-Saig_ManPoNum(p))/Abc_MaxInt(1, nTotalPo) );
+    printf( "Size   =%7d (%5.1f %%)  ", Aig_ManObjNum(p),          100.0*Aig_ManObjNum(p)/Abc_MaxInt(1, nTotalSize) );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Gia_ManMultiProveSyn( Aig_Man_t * p, int fVerbose, int fVeryVerbose )
+{
+    Aig_Man_t * pAig;
+    Gia_Man_t * pGia, * pTemp;
+    pGia = Gia_ManFromAig( p );
+    pGia = Gia_ManAigSyn2( pTemp = pGia, 1, 0, 0, 0, 0, 0 );
+    Gia_ManStop( pTemp );
+    pAig = Gia_ManToAig( pGia, 0 );
+    Gia_ManStop( pGia );
+    return pAig;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Gia_ManMultiProveAig( Aig_Man_t * p, Bmc_MulPar_t * pPars )
+{
+    Ssw_RarPars_t ParsSim, * pParsSim = &ParsSim;
+    Saig_ParBmc_t ParsBmc, * pParsBmc = &ParsBmc;
+    Vec_Int_t * vOutMap, * vLeftOver;
+    Vec_Ptr_t * vCexes;
+    Aig_Man_t * pTemp;
+    abctime clkStart = Abc_Clock();
+    abctime nTimeToStop = pPars->TimeOutGlo ? Abc_Clock() + pPars->TimeOutGlo * CLOCKS_PER_SEC : 0;
+    int nTotalPo     = Saig_ManPoNum(p);
+    int nTotalSize   = Aig_ManObjNum(p);
+    int TimeOutLoc   = pPars->TimeOutLoc;
+    int i, RetValue  = -1;
+    if ( pPars->fVerbose )
+        printf( "MultiProve parameters: Global timeout = %d sec.  Local timeout = %d sec.  Time increase = %d %%.\n", 
+            pPars->TimeOutGlo, pPars->TimeOutLoc, pPars->TimeOutInc );
+    if ( pPars->fVerbose )
+        printf( "Gap timout = %d sec. Per-output timeout = %d msec. Use synthesis = %d. Dump final = %d. Verbose = %d.\n", 
+            pPars->TimeOutGap, pPars->TimePerOut, pPars->fUseSyn, pPars->fDumpFinal, pPars->fVerbose );
+    // create output map
+    vOutMap = Vec_IntStartNatural( Saig_ManPoNum(p) ); // maps current outputs into their original IDs
+    vCexes  = Vec_PtrStart( Saig_ManPoNum(p) );        // maps solved outputs into their CEXes (or markers)
+    for ( i = 0; i < 1000; i++ )
+    {
+        int nSolved = Vec_PtrCountZero(vCexes);
+        // perform SIM3
+        Ssw_RarSetDefaultParams( pParsSim );
+        pParsSim->fSolveAll = 1;
+        pParsSim->fNotVerbose = 1;
+        pParsSim->fSilent = !pPars->fVeryVerbose;
+        pParsSim->TimeOut = TimeOutLoc;
+        pParsSim->nRandSeed = (i * 17) % 500;
+        pParsSim->nWords = 5;
+        RetValue *= Ssw_RarSimulate( p, pParsSim );
+        // sort outputs
+        if ( p->vSeqModelVec )
+        {
+            vLeftOver = Gia_ManProcessOutputs( p->vSeqModelVec, vCexes, vOutMap );
+            if ( Vec_IntSize(vLeftOver) == 0 )
+                break;
+            // remove solved        
+            p = Saig_ManDupCones( pTemp = p, Vec_IntArray(vLeftOver), Vec_IntSize(vLeftOver) );
+            Vec_IntFree( vLeftOver );
+            Aig_ManStop( pTemp );
+        }
+        if ( pPars->fVerbose )
+            Gia_ManMultiReport( p, "SIM", nTotalPo, nTotalSize, clkStart );
+
+        // check timeout
+        if ( nTimeToStop && Abc_Clock() + TimeOutLoc * CLOCKS_PER_SEC > nTimeToStop )
+        {
+            printf( "Global timeout (%d sec) is reached.\n", pPars->TimeOutGlo );
+            break;
+        }
+
+        // perform BMC
+        Saig_ParBmcSetDefaultParams( pParsBmc );
+        pParsBmc->fSolveAll = 1;
+        pParsBmc->fNotVerbose = 1;
+        pParsBmc->fSilent = !pPars->fVeryVerbose;
+        pParsBmc->nTimeOut = TimeOutLoc;
+        pParsBmc->nTimeOutOne = pPars->TimePerOut;
+        RetValue *= Saig_ManBmcScalable( p, pParsBmc );
+        if ( pPars->fVeryVerbose )
+            Abc_Print( 1, "Some outputs are SAT (%d out of %d) after %d frames.\n", 
+                Saig_ManPoNum(p) - Vec_PtrCountZero(p->vSeqModelVec), Saig_ManPoNum(p), pParsBmc->iFrame );
+        // sort outputs
+        if ( p->vSeqModelVec )
+        {
+            vLeftOver = Gia_ManProcessOutputs( p->vSeqModelVec, vCexes, vOutMap );
+            if ( Vec_IntSize(vLeftOver) == 0 )
+                break;
+            // remove solved        
+            p = Saig_ManDupCones( pTemp = p, Vec_IntArray(vLeftOver), Vec_IntSize(vLeftOver) );
+            Vec_IntFree( vLeftOver );
+            Aig_ManStop( pTemp );
+        }
+        if ( pPars->fVerbose )
+            Gia_ManMultiReport( p, "BMC", nTotalPo, nTotalSize, clkStart );
+
+        // check timeout
+        if ( nTimeToStop && Abc_Clock() + TimeOutLoc * CLOCKS_PER_SEC > nTimeToStop )
+        {
+            printf( "Global timeout (%d sec) is reached.\n", pPars->TimeOutGlo );
+            break;
+        }
+
+        // check gap timeout
+        if ( pPars->TimeOutGap && pPars->TimeOutGap <= TimeOutLoc && nSolved == Vec_PtrCountZero(vCexes) )
+        {
+            printf( "Gap timeout (%d sec) is reached.\n", pPars->TimeOutGap );
+            break;
+        }
+
+        // synthesize
+        if ( pPars->fUseSyn )
+        {
+            p = Gia_ManMultiProveSyn( pTemp = p, pPars->fVerbose, pPars->fVeryVerbose );
+            Aig_ManStop( pTemp );
+            if ( pPars->fVerbose )
+                Gia_ManMultiReport( p, "SYN", nTotalPo, nTotalSize, clkStart );
+        }
+
+        // increase timeout
+        TimeOutLoc += TimeOutLoc * pPars->TimeOutInc / 100;
+    }
+    Vec_IntFree( vOutMap );
+    if ( pPars->fVerbose )
+        printf( "The number of POs proved UNSAT by synthesis = %d.\n", Gia_ManCountConst0Pos(p) );
+    if ( pPars->fDumpFinal )
+    {
+        char * pFileName = Extra_FileNameGenericAppend( p->pName, "_out.aig" );
+        Ioa_WriteAiger( p, pFileName, 0, 0 );
+        printf( "Final AIG was dumped into file \"%s\".\n", pFileName );
+    }
+    Aig_ManStop( p );
+    return vCexes;
+}
+int Gia_ManMultiProve( Gia_Man_t * p, Bmc_MulPar_t * pPars )
+{
+    Aig_Man_t * pAig;
+    if ( p->vSeqModelVec )
+        Vec_PtrFreeFree( p->vSeqModelVec ), p->vSeqModelVec = NULL;
+    pAig = Gia_ManToAig( p, 0 );
+    p->vSeqModelVec = Gia_ManMultiProveAig( pAig, pPars ); // deletes pAig
+    assert( Vec_PtrSize(p->vSeqModelVec) == Gia_ManPoNum(p) );
+    return Vec_PtrCountZero(p->vSeqModelVec) == Vec_PtrSize(p->vSeqModelVec) ? -1 : 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/bmcUnroll.c b/abc-build/src/sat/bmc/bmcUnroll.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/bmcUnroll.c
@@ -0,0 +1,505 @@
+/**CFile****************************************************************
+
+  FileName    [bmcUnroll.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT-based bounded model checking.]
+
+  Synopsis    [Unrolling manager.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: bmc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bmc.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define UNR_DIFF_NULL 0x7FFF
+
+typedef struct Unr_Obj_t_ Unr_Obj_t; // 24 bytes + (RankMax-1) * 4 bytes
+struct Unr_Obj_t_
+{
+    unsigned              hFan0;        // address of the fanin
+    unsigned              hFan1;        // address of the fanin
+    unsigned              fCompl0 :  1; // complemented bit
+    unsigned              fCompl1 :  1; // complemented bit
+    unsigned              uRDiff0 : 15; // rank diff of the fanin
+    unsigned              uRDiff1 : 15; // rank diff of the fanin
+    unsigned              fItIsPi :  1; // remember attributes
+    unsigned              fItIsPo :  1; // remember attributes
+    unsigned              RankMax : 15; // max rank diff between node and its fanout
+    unsigned              RankCur : 15; // cur rank of the node
+    unsigned              OrigId;       // original object ID
+    unsigned              Res[1];       // RankMax entries
+};
+
+struct Unr_Man_t_
+{
+    // input data
+    Gia_Man_t *           pGia;           // the user's AIG manager
+    Gia_Man_t *           pFrames;        // unrolled manager
+    int                   nObjs;          // the number of objects
+    // intermediate data
+    Vec_Int_t *           vOrder;         // ordering of GIA objects
+    Vec_Int_t *           vOrderLim;      // beginning of each time frame
+    Vec_Int_t *           vTents;         // tents of GIA objects
+    Vec_Int_t *           vRanks;         // ranks of GIA objects
+    // unrolling data
+    int *                 pObjs;          // storage for unroling objects
+    int *                 pEnd;           // end of storage
+    Vec_Int_t *           vObjLim;        // handle of the first object in each frame
+    Vec_Int_t *           vCiMap;         // mapping of GIA CIs into unrolling objects
+    Vec_Int_t *           vCoMap;         // mapping of GIA POs into unrolling objects
+    Vec_Int_t *           vPiLits;        // storage for PI literals
+};
+
+static inline Unr_Obj_t * Unr_ManObj( Unr_Man_t * p, int h )  { assert( h >= 0 && h < p->pEnd - p->pObjs ); return (Unr_Obj_t *)(p->pObjs + h);  }
+static inline int         Unr_ObjSizeInt( int Rank )          { return 0xFFFFFFFE & (sizeof(Unr_Obj_t) / sizeof(int) + Rank);                    }
+static inline int         Unr_ObjSize( Unr_Obj_t * pObj )     { return Unr_ObjSizeInt(pObj->RankMax);                                            }
+
+static inline int Unr_ManFanin0Value( Unr_Man_t * p, Unr_Obj_t * pObj )
+{
+    Unr_Obj_t * pFanin = Unr_ManObj( p, pObj->hFan0 );
+    int Index = (pFanin->RankCur + pFanin->RankMax - pObj->uRDiff0) % pFanin->RankMax;
+    assert( pFanin->RankCur < pFanin->RankMax );
+    assert( pObj->uRDiff0 < pFanin->RankMax );
+    return Abc_LitNotCond( pFanin->Res[Index], pObj->fCompl0 );
+}
+static inline int Unr_ManFanin1Value( Unr_Man_t * p, Unr_Obj_t * pObj )
+{
+    Unr_Obj_t * pFanin = Unr_ManObj( p, pObj->hFan1 );
+    int Index = (pFanin->RankCur + pFanin->RankMax - pObj->uRDiff1) % pFanin->RankMax;
+    assert( pFanin->RankCur < pFanin->RankMax );
+    assert( pObj->uRDiff1 < pFanin->RankMax );
+    return Abc_LitNotCond( pFanin->Res[Index], pObj->fCompl1 );
+}
+static inline int Unr_ManObjReadValue( Unr_Obj_t * pObj )
+{
+    assert( pObj->RankCur >= 0 && pObj->RankCur < pObj->RankMax );
+    return pObj->Res[ pObj->RankCur ];
+}
+static inline void Unr_ManObjSetValue( Unr_Obj_t * pObj, int Value )
+{
+    assert( Value >= 0 );
+    pObj->RankCur = (UNR_DIFF_NULL & (pObj->RankCur + 1)) % pObj->RankMax;
+    pObj->Res[ pObj->RankCur ] = Value;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_IntWriteMaxEntry( Vec_Int_t * p, int i, int Entry )
+{
+    assert( i >= 0 && i < p->nSize );
+    p->pArray[i] = Abc_MaxInt( p->pArray[i], Entry );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Unr_ManProfileRanks( Vec_Int_t * vRanks )
+{
+    int RankMax = Vec_IntFindMax( vRanks );
+    Vec_Int_t * vCounts = Vec_IntStart( RankMax+1 );
+    int i, Rank, Count, nExtras = 0;
+    Vec_IntForEachEntry( vRanks, Rank, i )
+        Vec_IntAddToEntry( vCounts, Rank, 1 );
+    Vec_IntForEachEntry( vCounts, Count, i )
+    {
+        if ( Count == 0 )
+            continue;
+        printf( "%2d : %8d  (%6.2f %%)\n", i, Count, 100.0 * Count / Vec_IntSize(vRanks) );
+        nExtras += Count * i;
+    }
+    printf( "Extra space = %d (%6.2f %%)  ", nExtras, 100.0 * nExtras / Vec_IntSize(vRanks) );
+    Vec_IntFree( vCounts );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Unr_ManSetup_rec( Unr_Man_t * p, int iObj, int iTent, Vec_Int_t * vRoots )
+{
+    Gia_Obj_t * pObj;
+    int iFanin;
+    if ( Vec_IntEntry(p->vTents, iObj) >= 0 )
+        return;
+    Vec_IntWriteEntry(p->vTents, iObj, iTent);
+    pObj = Gia_ManObj( p->pGia, iObj );
+    if ( Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) )
+    {
+        Unr_ManSetup_rec( p, (iFanin = Gia_ObjFaninId0(pObj, iObj)), iTent, vRoots );
+        Vec_IntWriteMaxEntry( p->vRanks, iFanin, Abc_MaxInt(0, iTent - Vec_IntEntry(p->vTents, iFanin) - 1) );
+    }
+    if ( Gia_ObjIsAnd(pObj) )
+    {
+        Unr_ManSetup_rec( p, (iFanin = Gia_ObjFaninId1(pObj, iObj)), iTent, vRoots );
+        Vec_IntWriteMaxEntry( p->vRanks, iFanin, Abc_MaxInt(0, iTent - Vec_IntEntry(p->vTents, iFanin) - 1) );
+    }
+    else if ( Gia_ObjIsRo(p->pGia, pObj) )
+    {
+        Vec_IntPush( vRoots, (iFanin = Gia_ObjId(p->pGia, Gia_ObjRoToRi(p->pGia, pObj))) );
+        Vec_IntWriteMaxEntry( p->vRanks, iFanin, 0 );
+    }
+    Vec_IntPush( p->vOrder, iObj );
+}
+void Unr_ManSetup( Unr_Man_t * p, int fVerbose )
+{
+    Vec_Int_t * vRoots, * vRoots2, * vMap;
+    Unr_Obj_t * pUnrObj;
+    Gia_Obj_t * pObj;
+    int i, k, t, iObj, nInts, * pInts;
+    abctime clk = Abc_Clock();
+    // create zero rank
+    assert( Vec_IntSize(p->vOrder) == 0 );
+    Vec_IntPush( p->vOrder, 0 );
+    Vec_IntPush( p->vOrderLim, Vec_IntSize(p->vOrder) );
+    Vec_IntWriteEntry( p->vTents, 0, 0 );
+    Vec_IntWriteEntry( p->vRanks, 0, 0 );
+    // start from the POs
+    vRoots  = Vec_IntAlloc( 100 );
+    vRoots2 = Vec_IntAlloc( 100 );
+    Gia_ManForEachPo( p->pGia, pObj, i )
+        Unr_ManSetup_rec( p, Gia_ObjId(p->pGia, pObj), 0, vRoots );
+    // collect tents
+    while ( Vec_IntSize(vRoots) > 0 )
+    {
+        Vec_IntPush( p->vOrderLim, Vec_IntSize(p->vOrder) );
+        Vec_IntClear( vRoots2 );
+        Vec_IntForEachEntry( vRoots, iObj, i )
+            Unr_ManSetup_rec( p, iObj, Vec_IntSize(p->vOrderLim)-1, vRoots2 );
+        ABC_SWAP( Vec_Int_t *, vRoots, vRoots2 );
+    }
+    Vec_IntPush( p->vOrderLim, Vec_IntSize(p->vOrder) );
+    Vec_IntFree( vRoots );
+    Vec_IntFree( vRoots2 );
+    // allocate memory
+    nInts = 0;
+    Vec_IntForEachEntry( p->vOrder, iObj, i )
+        nInts += Unr_ObjSizeInt( Vec_IntEntry(p->vRanks, iObj) + 1 );
+    p->pObjs = pInts = ABC_CALLOC( int, nInts );
+    p->pEnd = p->pObjs + nInts;
+    // create const0 node
+    pUnrObj = Unr_ManObj( p, pInts - p->pObjs );
+    pUnrObj->RankMax = Vec_IntEntry(p->vRanks, 0) + 1;
+    pUnrObj->uRDiff0 = pUnrObj->uRDiff1 = UNR_DIFF_NULL;
+    pUnrObj->Res[0]  = 0; // const0
+    // map the objects
+    vMap = Vec_IntStartFull( p->nObjs );
+    Vec_IntWriteEntry( vMap, 0, pInts - p->pObjs );
+    pInts += Unr_ObjSize(pUnrObj);
+    // mark up the entries
+    assert( Vec_IntSize(p->vObjLim) == 0 );
+    for ( t = Vec_IntSize(p->vOrderLim) - 2; t >= 0; t-- )
+    {
+        int Beg = Vec_IntEntry(p->vOrderLim, t);
+        int End = Vec_IntEntry(p->vOrderLim, t+1);
+        Vec_IntPush( p->vObjLim, pInts - p->pObjs );
+        Vec_IntForEachEntryStartStop( p->vOrder, iObj, i, Beg, End )
+        {
+            pObj = Gia_ManObj( p->pGia, iObj );
+            pUnrObj = Unr_ManObj( p, pInts - p->pObjs );
+            pUnrObj->uRDiff0 = pUnrObj->uRDiff1 = UNR_DIFF_NULL;
+            if ( Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) )
+                pUnrObj->uRDiff0 = Abc_MaxInt(0, Vec_IntEntry(p->vTents, iObj) - Vec_IntEntry(p->vTents, Gia_ObjFaninId0(pObj, iObj)) - 1);
+            if ( Gia_ObjIsAnd(pObj) )
+                pUnrObj->uRDiff1 = Abc_MaxInt(0, Vec_IntEntry(p->vTents, iObj) - Vec_IntEntry(p->vTents, Gia_ObjFaninId1(pObj, iObj)) - 1);
+            else if ( Gia_ObjIsRo(p->pGia, pObj) )
+                pUnrObj->uRDiff0 = 0;
+            pUnrObj->RankMax = Vec_IntEntry(p->vRanks, iObj) + 1;
+            pUnrObj->RankCur = UNR_DIFF_NULL;
+            pUnrObj->OrigId  = iObj;
+            for ( k = 0; k < (int)pUnrObj->RankMax; k++ )
+                pUnrObj->Res[k] = -1;
+            assert( ((pInts - p->pObjs) & 1) == 0 ); // align for 64-bits
+            Vec_IntWriteEntry( vMap, iObj, pInts - p->pObjs );
+            pInts += Unr_ObjSize( pUnrObj );
+        }
+    }
+    assert( pInts - p->pObjs == nInts );
+    // label the objects
+    Gia_ManForEachObj( p->pGia, pObj, i )
+    {
+        if ( Vec_IntEntry(vMap, i) == -1 )
+            continue;
+        pUnrObj = Unr_ManObj( p, Vec_IntEntry(vMap, i) );
+        if ( Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) )
+        {
+            pUnrObj->hFan0   = Vec_IntEntry( vMap, Gia_ObjFaninId0(pObj, i) );
+            pUnrObj->fCompl0 = Gia_ObjFaninC0(pObj);
+            pUnrObj->fItIsPo = Gia_ObjIsPo(p->pGia, pObj);
+        }
+        if ( Gia_ObjIsAnd(pObj) )
+        {
+            pUnrObj->hFan1   = Vec_IntEntry( vMap, Gia_ObjFaninId1(pObj, i) );
+            pUnrObj->fCompl1 = Gia_ObjFaninC1(pObj);
+        }
+        else if ( Gia_ObjIsRo(p->pGia, pObj) )
+        {
+            pUnrObj->hFan0   = Vec_IntEntry( vMap, Gia_ObjId(p->pGia, Gia_ObjRoToRi(p->pGia, pObj)) );
+            pUnrObj->fCompl0 = 0;
+        }
+        else if ( Gia_ObjIsPi(p->pGia, pObj) )
+        {
+            pUnrObj->hFan0   = Gia_ObjCioId(pObj);           // remember CIO id
+            pUnrObj->hFan1   = Vec_IntEntry(p->vTents, i);   // remember tent
+            pUnrObj->fItIsPi = 1;
+        }
+    }
+    // store CI/PO objects;
+    Gia_ManForEachCi( p->pGia, pObj, i )
+        Vec_IntPush( p->vCiMap, Vec_IntEntry(vMap, Gia_ObjId(p->pGia, pObj)) );
+    Gia_ManForEachCo( p->pGia, pObj, i )
+        Vec_IntPush( p->vCoMap, Vec_IntEntry(vMap, Gia_ObjId(p->pGia, pObj)) );
+    Vec_IntFreeP( &vMap );
+    // print stats
+    if ( fVerbose )
+    {
+        Unr_ManProfileRanks( p->vRanks );
+        printf( "Memory usage = %6.2f MB  ", 4.0 * nInts / (1<<20) );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    Vec_IntFreeP( &p->vOrder );
+    Vec_IntFreeP( &p->vOrderLim );
+    Vec_IntFreeP( &p->vRanks );
+    Vec_IntFreeP( &p->vTents );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Unr_Man_t * Unr_ManAlloc( Gia_Man_t * pGia )
+{
+    Unr_Man_t * p;
+    p = ABC_CALLOC( Unr_Man_t, 1 );
+    p->pGia      = pGia;
+    p->nObjs     = Gia_ManObjNum(pGia);
+    p->vOrder    = Vec_IntAlloc( p->nObjs );
+    p->vOrderLim = Vec_IntAlloc( 100 );
+    p->vTents    = Vec_IntStartFull( p->nObjs );
+    p->vRanks    = Vec_IntStart( p->nObjs );
+    p->vObjLim   = Vec_IntAlloc( 100 );
+    p->vCiMap    = Vec_IntAlloc( Gia_ManCiNum(pGia) );
+    p->vCoMap    = Vec_IntAlloc( Gia_ManCoNum(pGia) );
+    p->vPiLits   = Vec_IntAlloc( 10000 );
+    p->pFrames   = Gia_ManStart( 10000 );
+    p->pFrames->pName = Abc_UtilStrsav( pGia->pName );
+    Gia_ManHashStart( p->pFrames );
+    return p;
+}
+void Unr_ManFree( Unr_Man_t * p )
+{
+    Gia_ManStop( p->pFrames );
+    // intermediate data
+    Vec_IntFreeP( &p->vOrder );
+    Vec_IntFreeP( &p->vOrderLim );
+    Vec_IntFreeP( &p->vTents );
+    Vec_IntFreeP( &p->vRanks );
+    // unrolling data
+    Vec_IntFreeP( &p->vObjLim );
+    Vec_IntFreeP( &p->vCiMap );
+    Vec_IntFreeP( &p->vCoMap );
+    Vec_IntFreeP( &p->vPiLits );
+    ABC_FREE( p->pObjs );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform smart unrolling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Unr_Man_t * Unr_ManUnrollStart( Gia_Man_t * pGia, int fVerbose )
+{
+    int i, iHandle;
+    Unr_Man_t * p;
+    p = Unr_ManAlloc( pGia );
+    Unr_ManSetup( p, fVerbose );
+    for ( i = 0; i < Gia_ManRegNum(p->pGia); i++ )
+        if ( (iHandle = Vec_IntEntry(p->vCoMap, Gia_ManPoNum(p->pGia) + i)) != -1 )
+            Unr_ManObjSetValue( Unr_ManObj(p, iHandle), 0 );
+    return p;
+}
+Gia_Man_t * Unr_ManUnrollFrame( Unr_Man_t * p, int f )
+{
+    int i, iLit, iLit0, iLit1, hStart;
+    for ( i = 0; i < Gia_ManPiNum(p->pGia); i++ )
+        Vec_IntPush( p->vPiLits, Gia_ManAppendCi(p->pFrames) );
+    hStart = Vec_IntEntry( p->vObjLim, Abc_MaxInt(0, Vec_IntSize(p->vObjLim)-1-f) );
+    while ( p->pObjs + hStart < p->pEnd )
+    {
+        Unr_Obj_t * pUnrObj = Unr_ManObj( p, hStart );
+        if ( pUnrObj->uRDiff0 != UNR_DIFF_NULL && pUnrObj->uRDiff1 != UNR_DIFF_NULL ) // AND node
+        {
+            iLit0 = Unr_ManFanin0Value( p, pUnrObj );
+            iLit1 = Unr_ManFanin1Value( p, pUnrObj );
+            iLit  = Gia_ManHashAnd( p->pFrames, iLit0, iLit1 );
+            Unr_ManObjSetValue( pUnrObj, iLit );
+        }
+        else if ( pUnrObj->uRDiff0 != UNR_DIFF_NULL && pUnrObj->uRDiff1 == UNR_DIFF_NULL ) // PO/RI/RO
+        {
+            iLit  = Unr_ManFanin0Value( p, pUnrObj );
+            Unr_ManObjSetValue( pUnrObj, iLit );
+            if ( pUnrObj->fItIsPo )
+                Gia_ManAppendCo( p->pFrames, iLit );
+        }
+        else // PI  (pUnrObj->hFan0 is CioId; pUnrObj->hFan1 is tent)
+        {
+            assert( pUnrObj->fItIsPi && f >= (int)pUnrObj->hFan1 );
+            iLit = Vec_IntEntry( p->vPiLits, Gia_ManPiNum(p->pGia) * (f - pUnrObj->hFan1) + pUnrObj->hFan0 );
+            Unr_ManObjSetValue( pUnrObj, iLit );
+        }
+        hStart += Unr_ObjSize( pUnrObj );
+    }
+    assert( p->pObjs + hStart == p->pEnd );
+    assert( Gia_ManPoNum(p->pFrames) == (f + 1) * Gia_ManPoNum(p->pGia) );
+    return p->pFrames;
+}
+Gia_Man_t * Unr_ManUnroll( Gia_Man_t * pGia, int nFrames )
+{
+    Unr_Man_t * p;
+    Gia_Man_t * pFrames;
+    int f;
+    p = Unr_ManUnrollStart( pGia, 1 );
+    for ( f = 0; f < nFrames; f++ )
+        Unr_ManUnrollFrame( p, f );
+    pFrames = Gia_ManCleanup( p->pFrames );
+    Unr_ManFree( p );
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform naive unrolling.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Unr_ManUnrollSimple( Gia_Man_t * pGia, int nFrames )
+{
+    Gia_Man_t * pFrames;
+    Gia_Obj_t * pObj, * pObjRi;
+    int f, i; 
+    pFrames = Gia_ManStart( 10000 );
+    pFrames->pName = Abc_UtilStrsav( pGia->pName );
+    Gia_ManHashAlloc( pFrames );
+    Gia_ManConst0(pGia)->Value = 0;
+    Gia_ManForEachRi( pGia, pObj, i )
+        pObj->Value = 0;
+    for ( f = 0; f < nFrames; f++ )
+    {
+        Gia_ManForEachPi( pGia, pObj, i )
+            pObj->Value = Gia_ManAppendCi(pFrames);
+        Gia_ManForEachRiRo( pGia, pObjRi, pObj, i )
+            pObj->Value = pObjRi->Value;
+        Gia_ManForEachAnd( pGia, pObj, i )
+            pObj->Value = Gia_ManHashAnd( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+        Gia_ManForEachCo( pGia, pObj, i )
+            pObj->Value = Gia_ObjFanin0Copy(pObj);
+        Gia_ManForEachPo( pGia, pObj, i )
+            Gia_ManAppendCo( pFrames, pObj->Value );
+    }
+    Gia_ManHashStop( pFrames );
+    Gia_ManSetRegNum( pFrames, 0 );
+    pFrames = Gia_ManCleanup( pGia = pFrames );
+    Gia_ManStop( pGia );
+    return pFrames;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Perform evaluation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Unr_ManTest( Gia_Man_t * pGia, int nFrames )
+{
+    Gia_Man_t * pFrames0, * pFrames1;
+    abctime clk = Abc_Clock();
+    pFrames0 = Unr_ManUnroll( pGia, nFrames );
+    Abc_PrintTime( 1, "Unroll ", Abc_Clock() - clk );
+    clk = Abc_Clock();
+    pFrames1 = Unr_ManUnrollSimple( pGia, nFrames );
+    Abc_PrintTime( 1, "UnrollS", Abc_Clock() - clk );
+
+Gia_ManPrintStats( pFrames0, NULL );
+Gia_ManPrintStats( pFrames1, NULL );
+Gia_AigerWrite( pFrames0, "frames0.aig", 0, 0 );
+Gia_AigerWrite( pFrames1, "frames1.aig", 0, 0 );
+
+    Gia_ManStop( pFrames0 );
+    Gia_ManStop( pFrames1 );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bmc/module.make b/abc-build/src/sat/bmc/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bmc/module.make
@@ -0,0 +1,20 @@
+SRC +=	src/sat/bmc/bmcBCore.c \
+	src/sat/bmc/bmcBmc.c \
+	src/sat/bmc/bmcBmc2.c \
+	src/sat/bmc/bmcBmc3.c \
+	src/sat/bmc/bmcBmcAnd.c \
+	src/sat/bmc/bmcBmci.c \
+	src/sat/bmc/bmcCexCare.c \
+	src/sat/bmc/bmcCexCut.c \
+	src/sat/bmc/bmcCexDepth.c \
+	src/sat/bmc/bmcCexMin1.c \
+	src/sat/bmc/bmcCexMin2.c \
+	src/sat/bmc/bmcCexTools.c \
+	src/sat/bmc/bmcEco.c \
+	src/sat/bmc/bmcFault.c \
+	src/sat/bmc/bmcICheck.c \
+	src/sat/bmc/bmcInse.c \
+	src/sat/bmc/bmcLoad.c \
+	src/sat/bmc/bmcMaxi.c \
+	src/sat/bmc/bmcMulti.c \
+	src/sat/bmc/bmcUnroll.c
diff --git a/abc-build/src/sat/bsat/license b/abc-build/src/sat/bsat/license
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/license
@@ -0,0 +1,21 @@
+MiniSat -- Copyright (c) 2005, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/abc-build/src/sat/bsat/module.make b/abc-build/src/sat/bsat/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/module.make
@@ -0,0 +1,13 @@
+SRC +=  src/sat/bsat/satMem.c \
+	src/sat/bsat/satInter.c \
+	src/sat/bsat/satInterA.c \
+	src/sat/bsat/satInterB.c \
+	src/sat/bsat/satInterP.c \
+	src/sat/bsat/satProof.c \
+	src/sat/bsat/satSolver.c \
+	src/sat/bsat/satSolver2.c \
+	src/sat/bsat/satSolver2i.c \
+	src/sat/bsat/satStore.c \
+	src/sat/bsat/satTrace.c \
+	src/sat/bsat/satTruth.c \
+	src/sat/bsat/satUtil.c
diff --git a/abc-build/src/sat/bsat/satChecker.c b/abc-build/src/sat/bsat/satChecker.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satChecker.c
@@ -0,0 +1,193 @@
+/**CFile****************************************************************
+
+  FileName    [satChecker.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT sat_solver.]
+
+  Synopsis    [Resolution proof checker.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: satChecker.c,v 1.4 2005/09/16 22:55:03 casem Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_PrintClause( Vec_Vec_t * vClauses, int Clause )
+{
+    Vec_Int_t * vClause;
+    int i, Entry;
+    printf( "Clause %d:  {", Clause );
+    vClause = Vec_VecEntry( vClauses, Clause );
+    Vec_IntForEachEntry( vClause, Entry, i )
+        printf( " %d", Entry );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sat_ProofResolve( Vec_Vec_t * vClauses, int Result, int Clause1, int Clause2 )
+{
+    Vec_Int_t * vResult  = Vec_VecEntry( vClauses, Result );
+    Vec_Int_t * vClause1 = Vec_VecEntry( vClauses, Clause1 );
+    Vec_Int_t * vClause2 = Vec_VecEntry( vClauses, Clause2 );
+    int Entry1, Entry2, ResVar;
+    int i, j, Counter = 0;
+
+    Vec_IntForEachEntry( vClause1, Entry1, i )
+    Vec_IntForEachEntry( vClause2, Entry2, j )
+    if ( Entry1 == -Entry2 )
+    {
+        ResVar = Entry1;
+        Counter++;
+    }
+    if ( Counter != 1 )
+    {
+        printf( "Error: Clause %d = Resolve(%d, %d): The number of pivot vars is %d.\n", 
+            Result, Clause1, Clause2, Counter );
+        Sat_PrintClause( vClauses, Clause1 );
+        Sat_PrintClause( vClauses, Clause2 );
+        return 0;
+    }
+    // create new clause
+    assert( Vec_IntSize(vResult) == 0 );
+    Vec_IntForEachEntry( vClause1, Entry1, i )
+        if ( Entry1 != ResVar && Entry1 != -ResVar )
+            Vec_IntPushUnique( vResult, Entry1 );
+    assert( Vec_IntSize(vResult) + 1 == Vec_IntSize(vClause1) );
+    Vec_IntForEachEntry( vClause2, Entry2, i )
+        if ( Entry2 != ResVar && Entry2 != -ResVar )
+            Vec_IntPushUnique( vResult, Entry2 );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_ProofChecker( char * pFileName )
+{
+    FILE * pFile;
+    Vec_Vec_t * vClauses;
+    int c, i, Num, RetValue, Counter, Counter2, Clause1, Clause2;
+    int RetValue;
+    // open the file
+    pFile = fopen( pFileName, "r" );
+    if ( pFile == NULL )
+        return;
+    // count the number of clauses
+    Counter = Counter2 = 0;
+    while ( (c = fgetc(pFile)) != EOF )
+    {
+        Counter += (c == '\n');
+        Counter2 += (c == '*');
+    }
+    vClauses = Vec_VecStart( Counter+1 );
+    printf( "The proof contains %d roots and %d resolution steps.\n", Counter-Counter2, Counter2 );
+    // read the clauses
+    rewind( pFile );
+    for ( i = 1 ; ; i++ )
+    {
+        RetValue = RetValue = fscanf( pFile, "%d", &Num );
+        if ( RetValue != 1 )
+            break;
+        assert( Num == i );
+        while ( (c = fgetc( pFile )) == ' ' );
+        if ( c == '*' )
+        {
+            RetValue = fscanf( pFile, "%d %d", &Clause1, &Clause2 );
+            assert( RetValue == 2 );
+            RetValue = fscanf( pFile, "%d", &Num );
+            assert( RetValue == 1 );
+            assert( Num == 0 );
+            if ( !Sat_ProofResolve( vClauses, i, Clause1, Clause2 ) )
+            {
+                printf( "Error detected in the resolution proof.\n" );
+                Vec_VecFree( vClauses );
+                fclose( pFile );
+                return;
+            }
+        }
+        else
+        {
+            ungetc( c, pFile );
+            while ( 1 )
+            {
+                RetValue = fscanf( pFile, "%d", &Num );
+                assert( RetValue == 1 );
+                if ( Num == 0 )
+                    break;
+                Vec_VecPush( vClauses, i, (void *)Num );
+            }
+            RetValue = fscanf( pFile, "%d", &Num );
+            assert( RetValue == 1 );
+            assert( Num == 0 );
+        }
+    }
+    assert( i-1 == Counter );
+    if ( Vec_IntSize( Vec_VecEntry(vClauses, Counter) ) != 0 )
+        printf( "The last clause is not empty.\n" );
+    else
+        printf( "The empty clause is derived.\n" );
+    Vec_VecFree( vClauses );
+    fclose( pFile );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bsat/satClause.h b/abc-build/src/sat/bsat/satClause.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satClause.h
@@ -0,0 +1,476 @@
+/**CFile****************************************************************
+
+  FileName    [satMem.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT solver.]
+
+  Synopsis    [Memory management.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: satMem.h,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__sat__bsat__satMem_h
+#define ABC__sat__bsat__satMem_h
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "misc/util/abc_global.h"
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+//#define LEARNT_MAX_START_DEFAULT  0
+#define LEARNT_MAX_START_DEFAULT  10000
+#define LEARNT_MAX_INCRE_DEFAULT   1000
+#define LEARNT_MAX_RATIO_DEFAULT     50
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+//=================================================================================================
+// Clause datatype + minor functions:
+
+typedef struct clause_t clause;
+struct clause_t
+{
+    unsigned   lrn   :   1;
+    unsigned   mark  :   1;
+    unsigned   partA :   1;
+    unsigned   lbd   :   8;
+    unsigned   size  :  21;
+    lit        lits[0];
+};
+
+// learned clauses have "hidden" literal (c->lits[c->size]) to store clause ID
+
+// data-structure for logging entries
+// memory is allocated in 2^nPageSize word-sized pages
+// the first 'word' of each page are stores the word limit
+
+// although clause memory pieces are aligned to 64-bit words
+// the integer clause handles are in terms of 32-bit unsigneds
+// allowing for the first bit to be used for labeling 2-lit clauses
+
+
+typedef struct Sat_Mem_t_ Sat_Mem_t;
+struct Sat_Mem_t_
+{
+    int                 nEntries[2];  // entry count
+    int                 BookMarkH[2]; // bookmarks for handles
+    int                 BookMarkE[2]; // bookmarks for entries
+    int                 iPage[2];     // current memory page
+    int                 nPageSize;    // page log size in terms of ints
+    unsigned            uPageMask;    // page mask
+    unsigned            uLearnedMask; // learned mask
+    int                 nPagesAlloc;  // page count allocated
+    int **              pPages;       // page pointers
+}; 
+
+static inline int       Sat_MemLimit( int * p )                      { return p[0];                                 }
+static inline int       Sat_MemIncLimit( int * p, int nInts )        { return p[0] += nInts;                        }
+static inline void      Sat_MemWriteLimit( int * p, int nInts )      { p[0] = nInts;                                }
+
+static inline int       Sat_MemHandPage( Sat_Mem_t * p, cla h )      { return h >> p->nPageSize;                    }
+static inline int       Sat_MemHandShift( Sat_Mem_t * p, cla h )     { return h & p->uPageMask;                     }
+
+static inline int       Sat_MemIntSize( int size, int lrn )          { return (size + 2 + lrn) & ~01;               }
+static inline int       Sat_MemClauseSize( clause * p )              { return Sat_MemIntSize(p->size, p->lrn);      }
+static inline int       Sat_MemClauseSize2( clause * p )             { return Sat_MemIntSize(p->size, 1);           }
+
+//static inline clause *  Sat_MemClause( Sat_Mem_t * p, int i, int k ) { assert(i <= p->iPage[i&1] && k <= Sat_MemLimit(p->pPages[i]));  return (clause *)(p->pPages[i] + k ); }
+static inline clause *  Sat_MemClause( Sat_Mem_t * p, int i, int k ) { assert( k ); return (clause *)(p->pPages[i] + k);         }
+//static inline clause *  Sat_MemClauseHand( Sat_Mem_t * p, cla h )    { assert(Sat_MemHandPage(p, h) <= p->iPage[(h & p->uLearnedMask) > 0]); assert(Sat_MemHandShift(p, h) >= 2 && Sat_MemHandShift(p, h) < (int)p->uLearnedMask); return Sat_MemClause( p, Sat_MemHandPage(p, h), Sat_MemHandShift(p, h) );     }
+static inline clause *  Sat_MemClauseHand( Sat_Mem_t * p, cla h )    { return h ? Sat_MemClause( p, Sat_MemHandPage(p, h), Sat_MemHandShift(p, h) ) : NULL;                  }
+static inline int       Sat_MemEntryNum( Sat_Mem_t * p, int lrn )    { return p->nEntries[lrn];                                                                              }
+
+static inline cla       Sat_MemHand( Sat_Mem_t * p, int i, int k )   { return (i << p->nPageSize) | k;                                                                       }
+static inline cla       Sat_MemHandCurrent( Sat_Mem_t * p, int lrn ) { return (p->iPage[lrn] << p->nPageSize) | Sat_MemLimit( p->pPages[p->iPage[lrn]] );                    }
+
+static inline int       Sat_MemClauseUsed( Sat_Mem_t * p, cla h )    { return h < p->BookMarkH[(h & p->uLearnedMask) > 0];                                                   }
+
+static inline double    Sat_MemMemoryHand( Sat_Mem_t * p, cla h )    { return 1.0 * ((Sat_MemHandPage(p, h) + 2)/2 * (1 << (p->nPageSize+2)) + Sat_MemHandShift(p, h) * 4);  }
+static inline double    Sat_MemMemoryUsed( Sat_Mem_t * p, int lrn )  { return Sat_MemMemoryHand( p, Sat_MemHandCurrent(p, lrn) );                                            }
+static inline double    Sat_MemMemoryAllUsed( Sat_Mem_t * p )        { return Sat_MemMemoryUsed( p, 0 ) + Sat_MemMemoryUsed( p, 1 );                                         }
+static inline double    Sat_MemMemoryAll( Sat_Mem_t * p )            { return 1.0 * (p->iPage[0] + p->iPage[1] + 2) * (1 << (p->nPageSize+2));                               }
+
+// p is memory storage
+// c is clause pointer
+// i is page number
+// k is page offset
+
+// print problem clauses NOT in proof mode
+#define Sat_MemForEachClause( p, c, i, k )      \
+    for ( i = 0; i <= p->iPage[0]; i += 2 )     \
+        for ( k = 2; k < Sat_MemLimit(p->pPages[i]) && ((c) = Sat_MemClause( p, i, k )); k += Sat_MemClauseSize(c) ) if ( i == 0 && k == 2 ) {} else
+
+// print problem clauses in proof mode
+#define Sat_MemForEachClause2( p, c, i, k )      \
+    for ( i = 0; i <= p->iPage[0]; i += 2 )     \
+        for ( k = 2; k < Sat_MemLimit(p->pPages[i]) && ((c) = Sat_MemClause( p, i, k )); k += Sat_MemClauseSize2(c) ) if ( i == 0 && k == 2 ) {} else
+
+#define Sat_MemForEachLearned( p, c, i, k )     \
+    for ( i = 1; i <= p->iPage[1]; i += 2 )     \
+        for ( k = 2; k < Sat_MemLimit(p->pPages[i]) && ((c) = Sat_MemClause( p, i, k )); k += Sat_MemClauseSize(c) )
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int      clause_from_lit( lit l )                     { return l + l + 1;                            }
+static inline int      clause_is_lit( cla h )                       { return (h & 1);                              }
+static inline lit      clause_read_lit( cla h )                     { return (lit)(h >> 1);                        }
+
+static inline int      clause_learnt_h( Sat_Mem_t * p, cla h )      { return (h & p->uLearnedMask) > 0;            }
+static inline int      clause_learnt( clause * c )                  { return c->lrn;                               }
+static inline int      clause_id( clause * c )                      { return c->lits[c->size];                     }
+static inline void     clause_set_id( clause * c, int id )          { c->lits[c->size] = id;                       }
+static inline int      clause_size( clause * c )                    { return c->size;                              }
+static inline lit *    clause_begin( clause * c )                   { return c->lits;                              }
+static inline lit *    clause_end( clause * c )                     { return c->lits + c->size;                    }
+static inline void     clause_print( clause * c )               
+{ 
+    int i;
+    printf( "{ " );
+    for ( i = 0; i < clause_size(c); i++ )
+        printf( "%d ", (clause_begin(c)[i] & 1)? -(clause_begin(c)[i] >> 1) : clause_begin(c)[i] >> 1 );
+    printf( "}\n" );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DECLARATIONS                        ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocating vector.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Sat_MemCountL( Sat_Mem_t * p )
+{
+    clause * c;
+    int i, k, Count = 0;
+    Sat_MemForEachLearned( p, c, i, k )
+        Count++;
+    return Count;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocating vector.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Sat_MemAlloc_( Sat_Mem_t * p, int nPageSize )
+{
+    assert( nPageSize > 8 && nPageSize < 32 );
+    memset( p, 0, sizeof(Sat_Mem_t) );
+    p->nPageSize    = nPageSize;
+    p->uLearnedMask = (unsigned)(1 << nPageSize);
+    p->uPageMask    = (unsigned)((1 << nPageSize) - 1);
+    p->nPagesAlloc  = 256;
+    p->pPages       = ABC_CALLOC( int *, p->nPagesAlloc );
+    p->pPages[0]    = ABC_ALLOC( int, (1 << p->nPageSize) );
+    p->pPages[1]    = ABC_ALLOC( int, (1 << p->nPageSize) );
+    p->iPage[0]     = 0;
+    p->iPage[1]     = 1;
+    Sat_MemWriteLimit( p->pPages[0], 2 );
+    Sat_MemWriteLimit( p->pPages[1], 2 );
+}
+static inline Sat_Mem_t * Sat_MemAlloc( int nPageSize )
+{
+    Sat_Mem_t * p;
+    p = ABC_CALLOC( Sat_Mem_t, 1 );
+    Sat_MemAlloc_( p, nPageSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resetting vector.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Sat_MemRestart( Sat_Mem_t * p )
+{
+    p->nEntries[0]  = 0;
+    p->nEntries[1]  = 0;
+    p->iPage[0]     = 0;
+    p->iPage[1]     = 1;
+    Sat_MemWriteLimit( p->pPages[0], 2 );
+    Sat_MemWriteLimit( p->pPages[1], 2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the bookmark.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Sat_MemBookMark( Sat_Mem_t * p )
+{
+    p->BookMarkE[0] = p->nEntries[0];
+    p->BookMarkE[1] = p->nEntries[1];
+    p->BookMarkH[0] = Sat_MemHandCurrent( p, 0 );
+    p->BookMarkH[1] = Sat_MemHandCurrent( p, 1 );
+}
+static inline void Sat_MemRollBack( Sat_Mem_t * p )
+{
+    p->nEntries[0]  = p->BookMarkE[0];
+    p->nEntries[1]  = p->BookMarkE[1];
+    p->iPage[0]     = Sat_MemHandPage( p, p->BookMarkH[0] );
+    p->iPage[1]     = Sat_MemHandPage( p, p->BookMarkH[1] );
+    Sat_MemWriteLimit( p->pPages[p->iPage[0]], Sat_MemHandShift( p, p->BookMarkH[0] ) );
+    Sat_MemWriteLimit( p->pPages[p->iPage[1]], Sat_MemHandShift( p, p->BookMarkH[1] ) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Freeing vector.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Sat_MemFree_( Sat_Mem_t * p )
+{
+    int i;
+    for ( i = 0; i < p->nPagesAlloc; i++ )
+        ABC_FREE( p->pPages[i] );
+    ABC_FREE( p->pPages );
+}
+static inline void Sat_MemFree( Sat_Mem_t * p )
+{
+    Sat_MemFree_( p );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates new clause.]
+
+  Description [The resulting clause is fully initialized.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Sat_MemAppend( Sat_Mem_t * p, int * pArray, int nSize, int lrn, int fPlus1 )
+{
+    clause * c;
+    int * pPage = p->pPages[p->iPage[lrn]];
+    int nInts = Sat_MemIntSize( nSize, lrn | fPlus1 );
+    assert( nInts + 3 < (1 << p->nPageSize) );
+    // need two extra at the begining of the page and one extra in the end
+    if ( Sat_MemLimit(pPage) + nInts + 2 >= (1 << p->nPageSize) )
+    { 
+        p->iPage[lrn] += 2;
+        if ( p->iPage[lrn] >= p->nPagesAlloc )
+        {
+            p->pPages = ABC_REALLOC( int *, p->pPages, p->nPagesAlloc * 2 );
+            memset( p->pPages + p->nPagesAlloc, 0, sizeof(int *) * p->nPagesAlloc );
+            p->nPagesAlloc *= 2;
+        }
+        if ( p->pPages[p->iPage[lrn]] == NULL )
+            p->pPages[p->iPage[lrn]] = ABC_ALLOC( int, (1 << p->nPageSize) );
+        pPage = p->pPages[p->iPage[lrn]];
+        Sat_MemWriteLimit( pPage, 2 );
+    }
+    pPage[Sat_MemLimit(pPage)] = 0;
+    c = (clause *)(pPage + Sat_MemLimit(pPage));
+    c->size = nSize;
+    c->lrn = lrn;
+    if ( pArray )
+        memcpy( c->lits, pArray, sizeof(int) * nSize );
+    if ( lrn | fPlus1 )
+        c->lits[c->size] = p->nEntries[lrn];
+    p->nEntries[lrn]++;
+    Sat_MemIncLimit( pPage, nInts );
+    return Sat_MemHandCurrent(p, lrn) - nInts;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Shrinking vector size.]
+
+  Description []
+
+  SideEffects [This procedure does not update the number of entries.]
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Sat_MemShrink( Sat_Mem_t * p, int h, int lrn )
+{
+    assert( clause_learnt_h(p, h) == lrn );
+    assert( h && h <= Sat_MemHandCurrent(p, lrn) );
+    p->iPage[lrn] = Sat_MemHandPage(p, h);
+    Sat_MemWriteLimit( p->pPages[p->iPage[lrn]], Sat_MemHandShift(p, h) );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Compacts learned clauses by removing marked entries.]
+
+  Description [Returns the number of remaining entries.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Sat_MemCompactLearned( Sat_Mem_t * p, int fDoMove )
+{
+    clause * c, * cPivot = NULL;
+    int i, k, iNew = 1, kNew = 2, nInts, fStartLooking, Counter = 0;
+    int hLimit = Sat_MemHandCurrent(p, 1);
+    if ( hLimit == Sat_MemHand(p, 1, 2) )
+        return 0;
+    if ( fDoMove && p->BookMarkH[1] )
+    {
+        // move the pivot
+        assert( p->BookMarkH[1] >= Sat_MemHand(p, 1, 2) && p->BookMarkH[1] <= hLimit );
+        // get the pivot and remember it may be pointed offlimit
+        cPivot = Sat_MemClauseHand( p, p->BookMarkH[1] );
+        if ( p->BookMarkH[1] < hLimit && !cPivot->mark )
+        {
+            p->BookMarkH[1] = cPivot->lits[cPivot->size];
+            cPivot = NULL;
+        }
+        // else find the next used clause after cPivot
+    }
+    // iterate through the learned clauses
+    fStartLooking = 0;
+    Sat_MemForEachLearned( p, c, i, k )
+    {
+        assert( c->lrn );
+        // skip marked entry
+        if ( c->mark )
+        {
+            // if pivot is a marked clause, start looking for the next non-marked one
+            if ( cPivot && cPivot == c )
+            {
+                fStartLooking = 1;
+                cPivot = NULL;
+            }
+            continue;
+        }
+        // if we started looking before, we found it!
+        if ( fStartLooking )
+        {
+            fStartLooking = 0;
+            p->BookMarkH[1] = c->lits[c->size];
+        }
+        // compute entry size
+        nInts = Sat_MemClauseSize(c);
+        assert( !(nInts & 1) );
+        // check if we need to scroll to the next page
+        if ( kNew + nInts >= (1 << p->nPageSize) )
+        {
+            // set the limit of the current page
+            if ( fDoMove )
+                Sat_MemWriteLimit( p->pPages[iNew], kNew );
+            // move writing position to the new page
+            iNew += 2;
+            kNew = 2;
+        }
+        if ( fDoMove )
+        {
+            // make sure the result is the same as previous dry run
+            assert( c->lits[c->size] == Sat_MemHand(p, iNew, kNew) );
+            // only copy the clause if it has changed
+            if ( i != iNew || k != kNew )
+            {
+                memmove( p->pPages[iNew] + kNew, c, sizeof(int) * nInts );
+//                c = Sat_MemClause( p, iNew, kNew ); // assersions do not hold during dry run
+                c = (clause *)(p->pPages[iNew] + kNew);
+                assert( nInts == Sat_MemClauseSize(c) );
+            }
+            // set the new ID value
+            c->lits[c->size] = Counter;
+        }
+        else // remember the address of the clause in the new location
+            c->lits[c->size] = Sat_MemHand(p, iNew, kNew);
+        // update writing position
+        kNew += nInts;
+        assert( iNew <= i && kNew < (1 << p->nPageSize) );
+        // update counter
+        Counter++;
+    }
+    if ( fDoMove )
+    {
+        // update the counter
+        p->nEntries[1] = Counter;
+        // update the page count
+        p->iPage[1] = iNew;
+        // set the limit of the last page
+        Sat_MemWriteLimit( p->pPages[iNew], kNew );
+        // check if the pivot need to be updated
+        if ( p->BookMarkH[1] )
+        {
+            if ( cPivot )
+            {
+                p->BookMarkH[1] = Sat_MemHandCurrent(p, 1);
+                p->BookMarkE[1] = p->nEntries[1];
+            }
+            else
+                p->BookMarkE[1] = clause_id(Sat_MemClauseHand( p, p->BookMarkH[1] ));
+        }
+
+    }
+    return Counter;
+}
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/sat/bsat/satInter.c b/abc-build/src/sat/bsat/satInter.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satInter.c
@@ -0,0 +1,1077 @@
+/**CFile****************************************************************
+
+  FileName    [satInter.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT sat_solver.]
+
+  Synopsis    [Interpolation package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: satInter.c,v 1.4 2005/09/16 22:55:03 casem Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "satStore.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// variable assignments 
+static const lit    LIT_UNDEF = 0xffffffff;
+
+// interpolation manager
+struct Int_Man_t_
+{
+    // clauses of the problems
+    Sto_Man_t *     pCnf;         // the set of CNF clauses for A and B
+    int             pGloVars[16]; // global variables
+    int             nGloVars;     // the number of global variables
+    // various parameters
+    int             fVerbose;     // verbosiness flag
+    int             fProofVerif;  // verifies the proof
+    int             fProofWrite;  // writes the proof file
+    int             nVarsAlloc;   // the allocated size of var arrays
+    int             nClosAlloc;   // the allocated size of clause arrays
+    // internal BCP
+    int             nRootSize;    // the number of root level assignments
+    int             nTrailSize;   // the number of assignments made 
+    lit *           pTrail;       // chronological order of assignments (size nVars)
+    lit *           pAssigns;     // assignments by variable (size nVars) 
+    char *          pSeens;       // temporary mark (size nVars)
+    Sto_Cls_t **    pReasons;     // reasons for each assignment (size nVars)          
+    Sto_Cls_t **    pWatches;     // watched clauses for each literal (size 2*nVars)          
+    // interpolation data
+    int             nVarsAB;      // the number of global variables
+    int *           pVarTypes;    // variable type (size nVars) [1=A, 0=B, <0=AB]
+    unsigned *      pInters;      // storage for interpolants as truth tables (size nClauses)
+    int             nIntersAlloc; // the allocated size of truth table array
+    int             nWords;       // the number of words in the truth table
+    // proof recording
+    int             Counter;      // counter of resolved clauses
+    int *           pProofNums;   // the proof numbers for each clause (size nClauses)
+    FILE *          pFile;        // the file for proof recording
+    // internal verification
+    lit *           pResLits;     // the literals of the resolvent   
+    int             nResLits;     // the number of literals of the resolvent
+    int             nResLitsAlloc;// the number of literals of the resolvent
+    // runtime stats
+    abctime         timeBcp;      // the runtime for BCP
+    abctime         timeTrace;    // the runtime of trace construction
+    abctime         timeTotal;    // the total runtime of interpolation
+};
+
+// procedure to get hold of the clauses' truth table 
+static inline unsigned * Int_ManTruthRead( Int_Man_t * p, Sto_Cls_t * pCls )          { return p->pInters + pCls->Id * p->nWords;                 }
+static inline void       Int_ManTruthClear( unsigned * p, int nWords )                { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i]  =  0;    }
+static inline void       Int_ManTruthFill( unsigned * p, int nWords )                 { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i]  = ~0;    }
+static inline void       Int_ManTruthCopy( unsigned * p, unsigned * q, int nWords )   { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i]  =  q[i]; }
+static inline void       Int_ManTruthAnd( unsigned * p, unsigned * q, int nWords )    { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] &=  q[i]; }
+static inline void       Int_ManTruthOr( unsigned * p, unsigned * q, int nWords )     { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] |=  q[i]; }
+static inline void       Int_ManTruthOrNot( unsigned * p, unsigned * q, int nWords )  { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] |= ~q[i]; }
+
+// reading/writing the proof for a clause
+static inline int        Int_ManProofGet( Int_Man_t * p, Sto_Cls_t * pCls )           { return p->pProofNums[pCls->Id];  }
+static inline void       Int_ManProofSet( Int_Man_t * p, Sto_Cls_t * pCls, int n )    { p->pProofNums[pCls->Id] = n;     }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocate proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Int_Man_t * Int_ManAlloc()
+{
+    Int_Man_t * p;
+    // allocate the manager
+    p = (Int_Man_t *)ABC_ALLOC( char, sizeof(Int_Man_t) );
+    memset( p, 0, sizeof(Int_Man_t) );
+    // verification
+    p->nResLitsAlloc = (1<<16);
+    p->pResLits = ABC_ALLOC( lit, p->nResLitsAlloc );
+    // parameters
+    p->fProofWrite = 0;
+    p->fProofVerif = 1;
+    return p;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocate proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Int_ManSetGlobalVars( Int_Man_t * p, int nGloVars )
+{
+    p->nGloVars = nGloVars;
+    return p->pGloVars;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count common variables in the clauses of A and B.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Int_ManGlobalVars( Int_Man_t * p )
+{
+    Sto_Cls_t * pClause;
+    int Var, nVarsAB, v;
+
+    // mark the variable encountered in the clauses of A
+    Sto_ManForEachClauseRoot( p->pCnf, pClause )
+    {
+        if ( !pClause->fA )
+            break;
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+            p->pVarTypes[lit_var(pClause->pLits[v])] = 1;
+    }
+
+    if ( p->nGloVars )
+    {
+        for ( v = 0; v < p->nGloVars; v++ )
+            p->pVarTypes[ p->pGloVars[v] ] = - v - 1;
+        return p->nGloVars;
+    }
+
+    // check variables that appear in clauses of B
+    nVarsAB = 0;
+    Sto_ManForEachClauseRoot( p->pCnf, pClause )
+    {
+        if ( pClause->fA )
+            continue;
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+        {
+            Var = lit_var(pClause->pLits[v]);
+            if ( p->pVarTypes[Var] == 1 ) // var of A
+            {
+                // change it into a global variable
+                nVarsAB++;
+                p->pVarTypes[Var] = -1;
+            }
+        }
+    }
+
+    // order global variables
+    nVarsAB = 0;
+    for ( v = 0; v < p->pCnf->nVars; v++ )
+        if ( p->pVarTypes[v] == -1 )
+            p->pVarTypes[v] -= nVarsAB++;
+//printf( "There are %d global variables.\n", nVarsAB );
+    return nVarsAB;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resize proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Int_ManResize( Int_Man_t * p )
+{
+    // check if resizing is needed
+    if ( p->nVarsAlloc < p->pCnf->nVars )
+    {
+        // find the new size
+        if ( p->nVarsAlloc == 0 )
+            p->nVarsAlloc = 1;
+        while ( p->nVarsAlloc < p->pCnf->nVars ) 
+            p->nVarsAlloc *= 2;
+        // resize the arrays
+        p->pTrail    = ABC_REALLOC(lit,         p->pTrail,    p->nVarsAlloc );
+        p->pAssigns  = ABC_REALLOC(lit,         p->pAssigns,  p->nVarsAlloc );
+        p->pSeens    = ABC_REALLOC(char,        p->pSeens,    p->nVarsAlloc );
+        p->pVarTypes = ABC_REALLOC(int,         p->pVarTypes, p->nVarsAlloc );
+        p->pReasons  = ABC_REALLOC(Sto_Cls_t *, p->pReasons,  p->nVarsAlloc );
+        p->pWatches  = ABC_REALLOC(Sto_Cls_t *, p->pWatches,  p->nVarsAlloc*2 );
+    }
+
+    // clean the free space
+    memset( p->pAssigns , 0xff, sizeof(lit) * p->pCnf->nVars );
+    memset( p->pSeens   , 0,    sizeof(char) * p->pCnf->nVars );
+    memset( p->pVarTypes, 0,    sizeof(int) * p->pCnf->nVars );
+    memset( p->pReasons , 0,    sizeof(Sto_Cls_t *) * p->pCnf->nVars );
+    memset( p->pWatches , 0,    sizeof(Sto_Cls_t *) * p->pCnf->nVars*2 );
+
+    // compute the number of common variables
+    p->nVarsAB = Int_ManGlobalVars( p );
+    // compute the number of words in the truth table
+    p->nWords = (p->nVarsAB <= 5 ? 1 : (1 << (p->nVarsAB - 5)));
+
+    // check if resizing of clauses is needed
+    if ( p->nClosAlloc < p->pCnf->nClauses )
+    {
+        // find the new size
+        if ( p->nClosAlloc == 0 )
+            p->nClosAlloc = 1;
+        while ( p->nClosAlloc < p->pCnf->nClauses ) 
+            p->nClosAlloc *= 2;
+        // resize the arrays
+        p->pProofNums = ABC_REALLOC(int, p->pProofNums,  p->nClosAlloc );
+    }
+    memset( p->pProofNums, 0, sizeof(int) * p->pCnf->nClauses );
+
+    // check if resizing of truth tables is needed
+    if ( p->nIntersAlloc < p->nWords * p->pCnf->nClauses )
+    {
+        p->nIntersAlloc = p->nWords * p->pCnf->nClauses;
+        p->pInters = ABC_REALLOC(unsigned, p->pInters, p->nIntersAlloc );
+    }
+//    memset( p->pInters, 0, sizeof(unsigned) * p->nWords * p->pCnf->nClauses );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocate proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Int_ManFree( Int_Man_t * p )
+{
+/*
+    printf( "Runtime stats:\n" );
+ABC_PRT( "BCP     ", p->timeBcp   );
+ABC_PRT( "Trace   ", p->timeTrace );
+ABC_PRT( "TOTAL   ", p->timeTotal );
+*/
+    ABC_FREE( p->pInters );
+    ABC_FREE( p->pProofNums );
+    ABC_FREE( p->pTrail );
+    ABC_FREE( p->pAssigns );
+    ABC_FREE( p->pSeens );
+    ABC_FREE( p->pVarTypes );
+    ABC_FREE( p->pReasons );
+    ABC_FREE( p->pWatches );
+    ABC_FREE( p->pResLits );
+    ABC_FREE( p );
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Int_ManPrintClause( Int_Man_t * p, Sto_Cls_t * pClause )
+{
+    int i;
+    printf( "Clause ID = %d. Proof = %d. {", pClause->Id, Int_ManProofGet(p, pClause) );
+    for ( i = 0; i < (int)pClause->nLits; i++ )
+        printf( " %d", pClause->pLits[i] );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the resolvent.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Int_ManPrintResolvent( lit * pResLits, int nResLits )
+{
+    int i;
+    printf( "Resolvent: {" );
+    for ( i = 0; i < nResLits; i++ )
+        printf( " %d", pResLits[i] );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records the proof.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_PrintBinary__( FILE * pFile, unsigned Sign[], int nBits )
+{
+    int Remainder, nWords;
+    int w, i;
+
+    Remainder = (nBits%(sizeof(unsigned)*8));
+    nWords    = (nBits/(sizeof(unsigned)*8)) + (Remainder>0);
+
+    for ( w = nWords-1; w >= 0; w-- )
+        for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- )
+            fprintf( pFile, "%c", '0' + (int)((Sign[w] & (1<<i)) > 0) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the interpolant for one clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Int_ManPrintInterOne( Int_Man_t * p, Sto_Cls_t * pClause )
+{
+    printf( "Clause %2d :  ", pClause->Id );
+    Extra_PrintBinary__( stdout, Int_ManTruthRead(p, pClause), (1 << p->nVarsAB) );
+    printf( "\n" );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one clause to the watcher list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Int_ManWatchClause( Int_Man_t * p, Sto_Cls_t * pClause, lit Lit )
+{
+    assert( lit_check(Lit, p->pCnf->nVars) );
+    if ( pClause->pLits[0] == Lit )
+        pClause->pNext0 = p->pWatches[lit_neg(Lit)];  
+    else
+    {
+        assert( pClause->pLits[1] == Lit );
+        pClause->pNext1 = p->pWatches[lit_neg(Lit)];  
+    }
+    p->pWatches[lit_neg(Lit)] = pClause;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Records implication.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Int_ManEnqueue( Int_Man_t * p, lit Lit, Sto_Cls_t * pReason )
+{
+    int Var = lit_var(Lit);
+    if ( p->pAssigns[Var] != LIT_UNDEF )
+        return p->pAssigns[Var] == Lit;
+    p->pAssigns[Var] = Lit;
+    p->pReasons[Var] = pReason;
+    p->pTrail[p->nTrailSize++] = Lit;
+//printf( "assigning var %d value %d\n", Var, !lit_sign(Lit) );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records implication.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Int_ManCancelUntil( Int_Man_t * p, int Level )
+{
+    lit Lit;
+    int i, Var;
+    for ( i = p->nTrailSize - 1; i >= Level; i-- )
+    {
+        Lit = p->pTrail[i];
+        Var = lit_var( Lit );
+        p->pReasons[Var] = NULL;
+        p->pAssigns[Var] = LIT_UNDEF;
+//printf( "cancelling var %d\n", Var );
+    }
+    p->nTrailSize = Level;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagate one assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Sto_Cls_t * Int_ManPropagateOne( Int_Man_t * p, lit Lit )
+{
+    Sto_Cls_t ** ppPrev, * pCur, * pTemp;
+    lit LitF = lit_neg(Lit);
+    int i;
+    // iterate through the literals
+    ppPrev = p->pWatches + Lit;
+    for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev )
+    {
+        // make sure the false literal is in the second literal of the clause
+        if ( pCur->pLits[0] == LitF )
+        {
+            pCur->pLits[0] = pCur->pLits[1];
+            pCur->pLits[1] = LitF;
+            pTemp = pCur->pNext0;
+            pCur->pNext0 = pCur->pNext1;
+            pCur->pNext1 = pTemp;
+        }
+        assert( pCur->pLits[1] == LitF );
+
+        // if the first literal is true, the clause is satisfied
+        if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] )
+        {
+            ppPrev = &pCur->pNext1;
+            continue;
+        }
+
+        // look for a new literal to watch
+        for ( i = 2; i < (int)pCur->nLits; i++ )
+        {
+            // skip the case when the literal is false
+            if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] )
+                continue;
+            // the literal is either true or unassigned - watch it
+            pCur->pLits[1] = pCur->pLits[i];
+            pCur->pLits[i] = LitF;
+            // remove this clause from the watch list of Lit
+            *ppPrev = pCur->pNext1;
+            // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1])
+            Int_ManWatchClause( p, pCur, pCur->pLits[1] );
+            break;
+        }
+        if ( i < (int)pCur->nLits ) // found new watch
+            continue;
+
+        // clause is unit - enqueue new implication
+        if ( Int_ManEnqueue(p, pCur->pLits[0], pCur) )
+        {
+            ppPrev = &pCur->pNext1;
+            continue;
+        }
+
+        // conflict detected - return the conflict clause
+        return pCur;
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagate the current assignments.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Sto_Cls_t * Int_ManPropagate( Int_Man_t * p, int Start )
+{
+    Sto_Cls_t * pClause;
+    int i;
+    abctime clk = Abc_Clock();
+    for ( i = Start; i < p->nTrailSize; i++ )
+    {
+        pClause = Int_ManPropagateOne( p, p->pTrail[i] );
+        if ( pClause )
+        {
+p->timeBcp += Abc_Clock() - clk;
+            return pClause;
+        }
+    }
+p->timeBcp += Abc_Clock() - clk;
+    return NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes one root clause into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Int_ManProofWriteOne( Int_Man_t * p, Sto_Cls_t * pClause )
+{
+    Int_ManProofSet( p, pClause, ++p->Counter );
+
+    if ( p->fProofWrite )
+    {
+        int v;
+        fprintf( p->pFile, "%d", Int_ManProofGet(p, pClause) );
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+            fprintf( p->pFile, " %d", lit_print(pClause->pLits[v]) );
+        fprintf( p->pFile, " 0 0\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Traces the proof for one clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Int_ManProofTraceOne( Int_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pFinal )
+{
+    Sto_Cls_t * pReason;
+    int i, v, Var, PrevId;
+    int fPrint = 0;
+    abctime clk = Abc_Clock();
+
+    // collect resolvent literals
+    if ( p->fProofVerif )
+    {
+        assert( (int)pConflict->nLits <= p->nResLitsAlloc );
+        memcpy( p->pResLits, pConflict->pLits, sizeof(lit) * pConflict->nLits );
+        p->nResLits = pConflict->nLits;
+    }
+
+    // mark all the variables in the conflict as seen
+    for ( v = 0; v < (int)pConflict->nLits; v++ )
+        p->pSeens[lit_var(pConflict->pLits[v])] = 1;
+
+    // start the anticedents
+//    pFinal->pAntis = Vec_PtrAlloc( 32 );
+//    Vec_PtrPush( pFinal->pAntis, pConflict );
+
+    if ( p->pCnf->nClausesA )
+        Int_ManTruthCopy( Int_ManTruthRead(p, pFinal), Int_ManTruthRead(p, pConflict), p->nWords );
+
+    // follow the trail backwards
+    PrevId = Int_ManProofGet(p, pConflict);
+    for ( i = p->nTrailSize - 1; i >= 0; i-- )
+    {
+        // skip literals that are not involved
+        Var = lit_var(p->pTrail[i]);
+        if ( !p->pSeens[Var] )
+            continue;
+        p->pSeens[Var] = 0;
+
+        // skip literals of the resulting clause
+        pReason = p->pReasons[Var];
+        if ( pReason == NULL )
+            continue;
+        assert( p->pTrail[i] == pReason->pLits[0] );
+
+        // add the variables to seen
+        for ( v = 1; v < (int)pReason->nLits; v++ )
+            p->pSeens[lit_var(pReason->pLits[v])] = 1;
+
+
+        // record the reason clause
+        assert( Int_ManProofGet(p, pReason) > 0 );
+        p->Counter++;
+        if ( p->fProofWrite )
+            fprintf( p->pFile, "%d * %d %d 0\n", p->Counter, PrevId, Int_ManProofGet(p, pReason) );
+        PrevId = p->Counter;
+
+        if ( p->pCnf->nClausesA )
+        {
+            if ( p->pVarTypes[Var] == 1 ) // var of A
+                Int_ManTruthOr( Int_ManTruthRead(p, pFinal), Int_ManTruthRead(p, pReason), p->nWords );
+            else
+                Int_ManTruthAnd( Int_ManTruthRead(p, pFinal), Int_ManTruthRead(p, pReason), p->nWords );
+        }
+ 
+        // resolve the temporary resolvent with the reason clause
+        if ( p->fProofVerif )
+        {
+            int v1, v2; 
+            if ( fPrint )
+                Int_ManPrintResolvent( p->pResLits, p->nResLits );
+            // check that the var is present in the resolvent
+            for ( v1 = 0; v1 < p->nResLits; v1++ )
+                if ( lit_var(p->pResLits[v1]) == Var )
+                    break;
+            if ( v1 == p->nResLits )
+                printf( "Recording clause %d: Cannot find variable %d in the temporary resolvent.\n", pFinal->Id, Var );
+            if ( p->pResLits[v1] != lit_neg(pReason->pLits[0]) )
+                printf( "Recording clause %d: The resolved variable %d is in the wrong polarity.\n", pFinal->Id, Var );
+            // remove this variable from the resolvent
+            assert( lit_var(p->pResLits[v1]) == Var );
+            p->nResLits--;
+            for ( ; v1 < p->nResLits; v1++ )
+                p->pResLits[v1] = p->pResLits[v1+1];
+            // add variables of the reason clause
+            for ( v2 = 1; v2 < (int)pReason->nLits; v2++ )
+            {
+                for ( v1 = 0; v1 < p->nResLits; v1++ )
+                    if ( lit_var(p->pResLits[v1]) == lit_var(pReason->pLits[v2]) )
+                        break;
+                // if it is a new variable, add it to the resolvent
+                if ( v1 == p->nResLits ) 
+                {
+                    if ( p->nResLits == p->nResLitsAlloc )
+                        printf( "Recording clause %d: Ran out of space for intermediate resolvent.\n", pFinal->Id );
+                    p->pResLits[ p->nResLits++ ] = pReason->pLits[v2];
+                    continue;
+                }
+                // if the variable is the same, the literal should be the same too
+                if ( p->pResLits[v1] == pReason->pLits[v2] )
+                    continue;
+                // the literal is different
+                printf( "Recording clause %d: Trying to resolve the clause with more than one opposite literal.\n", pFinal->Id );
+            }
+        }
+
+//        Vec_PtrPush( pFinal->pAntis, pReason );
+    }
+
+    // unmark all seen variables
+//    for ( i = p->nTrailSize - 1; i >= 0; i-- )
+//        p->pSeens[lit_var(p->pTrail[i])] = 0;
+    // check that the literals are unmarked
+//    for ( i = p->nTrailSize - 1; i >= 0; i-- )
+//        assert( p->pSeens[lit_var(p->pTrail[i])] == 0 );
+
+    // use the resulting clause to check the correctness of resolution
+    if ( p->fProofVerif )
+    {
+        int v1, v2; 
+        if ( fPrint )
+            Int_ManPrintResolvent( p->pResLits, p->nResLits );
+        for ( v1 = 0; v1 < p->nResLits; v1++ )
+        {
+            for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ )
+                if ( pFinal->pLits[v2] == p->pResLits[v1] )
+                    break;
+            if ( v2 < (int)pFinal->nLits )
+                continue;
+            break;
+        }
+        if ( v1 < p->nResLits )
+        {
+            printf( "Recording clause %d: The final resolvent is wrong.\n", pFinal->Id );
+            Int_ManPrintClause( p, pConflict );
+            Int_ManPrintResolvent( p->pResLits, p->nResLits );
+            Int_ManPrintClause( p, pFinal );
+        }
+
+        // if there are literals in the clause that are not in the resolvent
+        // it means that the derived resolvent is stronger than the clause
+        // we can replace the clause with the resolvent by removing these literals
+        if ( p->nResLits != (int)pFinal->nLits )
+        {
+            for ( v1 = 0; v1 < (int)pFinal->nLits; v1++ )
+            {
+                for ( v2 = 0; v2 < p->nResLits; v2++ )
+                    if ( pFinal->pLits[v1] == p->pResLits[v2] )
+                        break;
+                if ( v2 < p->nResLits )
+                    continue;
+                // remove literal v1 from the final clause
+                pFinal->nLits--;
+                for ( v2 = v1; v2 < (int)pFinal->nLits; v2++ )
+                    pFinal->pLits[v2] = pFinal->pLits[v2+1];
+                v1--;
+            }
+            assert( p->nResLits == (int)pFinal->nLits );
+        }
+    }
+p->timeTrace += Abc_Clock() - clk;
+
+    // return the proof pointer 
+    if ( p->pCnf->nClausesA )
+    {
+//        Int_ManPrintInterOne( p, pFinal );
+    }
+    Int_ManProofSet( p, pFinal, p->Counter );
+    // make sure the same proof ID is not asssigned to two consecutive clauses
+    assert( p->pProofNums[pFinal->Id-1] != p->Counter );
+    return p->Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records the proof for one clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Int_ManProofRecordOne( Int_Man_t * p, Sto_Cls_t * pClause )
+{
+    Sto_Cls_t * pConflict;
+    int i;
+
+    // empty clause never ends up there
+    assert( pClause->nLits > 0 );
+    if ( pClause->nLits == 0 )
+        printf( "Error: Empty clause is attempted.\n" );
+
+    // add assumptions to the trail
+    assert( !pClause->fRoot );
+    assert( p->nTrailSize == p->nRootSize );
+
+    // if any of the clause literals are already assumed
+    // it means that the clause is redundant and can be skipped
+    for ( i = 0; i < (int)pClause->nLits; i++ )
+        if ( p->pAssigns[lit_var(pClause->pLits[i])] == pClause->pLits[i] )
+            return 1;
+
+    for ( i = 0; i < (int)pClause->nLits; i++ )
+        if ( !Int_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) )
+        {
+            assert( 0 ); // impossible
+            return 0;
+        }
+
+    // propagate the assumptions
+    pConflict = Int_ManPropagate( p, p->nRootSize );
+    if ( pConflict == NULL )
+    {
+        assert( 0 ); // cannot prove
+        return 0;
+    }
+
+    // skip the clause if it is weaker or the same as the conflict clause
+    if ( pClause->nLits >= pConflict->nLits )
+    {
+        // check if every literal of conflict clause can be found in the given clause
+        int j;
+        for ( i = 0; i < (int)pConflict->nLits; i++ )
+        {
+            for ( j = 0; j < (int)pClause->nLits; j++ )
+                if ( pConflict->pLits[i] == pClause->pLits[j] )
+                    break;
+            if ( j == (int)pClause->nLits ) // literal pConflict->pLits[i] is not found
+                break;
+        }
+        if ( i == (int)pConflict->nLits ) // all lits are found
+        {
+            // undo to the root level
+            Int_ManCancelUntil( p, p->nRootSize );
+            return 1;
+        }
+    }
+
+    // construct the proof
+    Int_ManProofTraceOne( p, pConflict, pClause );
+
+    // undo to the root level
+    Int_ManCancelUntil( p, p->nRootSize );
+
+    // add large clauses to the watched lists
+    if ( pClause->nLits > 1 )
+    {
+        Int_ManWatchClause( p, pClause, pClause->pLits[0] );
+        Int_ManWatchClause( p, pClause, pClause->pLits[1] );
+        return 1;
+    }
+    assert( pClause->nLits == 1 );
+
+    // if the clause proved is unit, add it and propagate
+    if ( !Int_ManEnqueue( p, pClause->pLits[0], pClause ) )
+    {
+        assert( 0 ); // impossible
+        return 0;
+    }
+
+    // propagate the assumption
+    pConflict = Int_ManPropagate( p, p->nRootSize );
+    if ( pConflict )
+    {
+        // construct the proof
+        Int_ManProofTraceOne( p, pConflict, p->pCnf->pEmpty );
+        if ( p->fVerbose )
+            printf( "Found last conflict after adding unit clause number %d!\n", pClause->Id );
+        return 0;
+    }
+
+    // update the root level
+    p->nRootSize = p->nTrailSize;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagate the root clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Int_ManProcessRoots( Int_Man_t * p )
+{
+    Sto_Cls_t * pClause;
+    int Counter;
+
+    // make sure the root clauses are preceeding the learnt clauses
+    Counter = 0;
+    Sto_ManForEachClause( p->pCnf, pClause )
+    {
+        assert( (int)pClause->fA    == (Counter < (int)p->pCnf->nClausesA) );
+        assert( (int)pClause->fRoot == (Counter < (int)p->pCnf->nRoots)    );
+        Counter++;
+    }
+    assert( p->pCnf->nClauses == Counter );
+
+    // make sure the last clause if empty
+    assert( p->pCnf->pTail->nLits == 0 );
+
+    // go through the root unit clauses
+    p->nTrailSize = 0;
+    Sto_ManForEachClauseRoot( p->pCnf, pClause )
+    {
+        // create watcher lists for the root clauses
+        if ( pClause->nLits > 1 )
+        {
+            Int_ManWatchClause( p, pClause, pClause->pLits[0] );
+            Int_ManWatchClause( p, pClause, pClause->pLits[1] );
+        }
+        // empty clause and large clauses
+        if ( pClause->nLits != 1 )
+            continue;
+        // unit clause
+        assert( lit_check(pClause->pLits[0], p->pCnf->nVars) );
+        if ( !Int_ManEnqueue( p, pClause->pLits[0], pClause ) )
+        {
+            // detected root level conflict
+//            printf( "Error in Int_ManProcessRoots(): Detected a root-level conflict too early!\n" );
+//            assert( 0 );
+            // detected root level conflict
+            Int_ManProofTraceOne( p, pClause, p->pCnf->pEmpty );
+            if ( p->fVerbose )
+                printf( "Found root level conflict!\n" );
+            return 0;
+        }
+    }
+
+    // propagate the root unit clauses
+    pClause = Int_ManPropagate( p, 0 );
+    if ( pClause )
+    {
+        // detected root level conflict
+        Int_ManProofTraceOne( p, pClause, p->pCnf->pEmpty );
+        if ( p->fVerbose )
+            printf( "Found root level conflict!\n" );
+        return 0;
+    }
+
+    // set the root level
+    p->nRootSize = p->nTrailSize;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records the proof.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Int_ManPrepareInter( Int_Man_t * p )
+{
+    // elementary truth tables
+    unsigned uTruths[8][8] = {
+        { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA },
+        { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC },
+        { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 },
+        { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 },
+        { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, 
+        { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, 
+        { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, 
+        { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } 
+    };
+    Sto_Cls_t * pClause;
+    int Var, VarAB, v;
+    assert( p->nVarsAB <= 8 );
+
+    // set interpolants for root clauses
+    Sto_ManForEachClauseRoot( p->pCnf, pClause )
+    {
+        if ( !pClause->fA ) // clause of B
+        {
+            Int_ManTruthFill( Int_ManTruthRead(p, pClause), p->nWords );
+//            Int_ManPrintInterOne( p, pClause );
+            continue;
+        }
+        // clause of A
+        Int_ManTruthClear( Int_ManTruthRead(p, pClause), p->nWords );
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+        {
+            Var = lit_var(pClause->pLits[v]);
+            if ( p->pVarTypes[Var] < 0 ) // global var
+            {
+                VarAB = -p->pVarTypes[Var]-1;
+                assert( VarAB >= 0 && VarAB < p->nVarsAB );
+                if ( lit_sign(pClause->pLits[v]) ) // negative var
+                    Int_ManTruthOrNot( Int_ManTruthRead(p, pClause), uTruths[VarAB], p->nWords );
+                else
+                    Int_ManTruthOr( Int_ManTruthRead(p, pClause), uTruths[VarAB], p->nWords );
+            }
+        }
+//        Int_ManPrintInterOne( p, pClause );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes interpolant for the given CNF.]
+
+  Description [Returns the number of common variable found and interpolant.
+  Returns 0, if something did not work.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Int_ManInterpolate( Int_Man_t * p, Sto_Man_t * pCnf, int fVerbose, unsigned ** ppResult )
+{
+    Sto_Cls_t * pClause;
+    int RetValue = 1;
+    abctime clkTotal = Abc_Clock();
+
+    // check that the CNF makes sense
+    assert( pCnf->nVars > 0 && pCnf->nClauses > 0 );
+    p->pCnf = pCnf;
+    p->fVerbose = fVerbose;
+    *ppResult = NULL;
+
+    // adjust the manager
+    Int_ManResize( p );
+
+    // prepare the interpolant computation
+    Int_ManPrepareInter( p );
+
+    // construct proof for each clause
+    // start the proof
+    if ( p->fProofWrite )
+    {
+        p->pFile = fopen( "proof.cnf_", "w" );
+        p->Counter = 0;
+    }
+
+    // write the root clauses
+    Sto_ManForEachClauseRoot( p->pCnf, pClause )
+        Int_ManProofWriteOne( p, pClause );
+
+    // propagate root level assignments
+    if ( Int_ManProcessRoots( p ) )
+    {
+        // if there is no conflict, consider learned clauses
+        Sto_ManForEachClause( p->pCnf, pClause )
+        {
+            if ( pClause->fRoot )
+                continue;
+            if ( !Int_ManProofRecordOne( p, pClause ) )
+            {
+                RetValue = 0;
+                break;
+            }
+        }
+    }
+
+    // stop the proof
+    if ( p->fProofWrite )
+    {
+        fclose( p->pFile );
+        p->pFile = NULL;    
+    }
+
+    if ( fVerbose )
+    {
+    printf( "Vars = %d. Roots = %d. Learned = %d. Resol steps = %d.  Ave = %.2f.  Mem = %.2f MB\n", 
+        p->pCnf->nVars, p->pCnf->nRoots, p->pCnf->nClauses-p->pCnf->nRoots, p->Counter,  
+        1.0*(p->Counter-p->pCnf->nRoots)/(p->pCnf->nClauses-p->pCnf->nRoots), 
+        1.0*Sto_ManMemoryReport(p->pCnf)/(1<<20) );
+p->timeTotal += Abc_Clock() - clkTotal;
+    }
+
+    *ppResult = Int_ManTruthRead( p, p->pCnf->pTail );
+    return p->nVarsAB;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bsat/satInterA.c b/abc-build/src/sat/bsat/satInterA.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satInterA.c
@@ -0,0 +1,1089 @@
+/**CFile****************************************************************
+
+  FileName    [satInter.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT sat_solver.]
+
+  Synopsis    [Interpolation package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: satInter.c,v 1.4 2005/09/16 22:55:03 casem Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "satStore.h"
+#include "aig/aig/aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// variable assignments 
+static const lit    LIT_UNDEF = 0xffffffff;
+
+// interpolation manager
+struct Inta_Man_t_
+{
+    // clauses of the problems
+    Sto_Man_t *     pCnf;         // the set of CNF clauses for A and B
+    Vec_Int_t *     vVarsAB;      // the array of global variables
+    // various parameters
+    int             fVerbose;     // verbosiness flag
+    int             fProofVerif;  // verifies the proof
+    int             fProofWrite;  // writes the proof file
+    int             nVarsAlloc;   // the allocated size of var arrays
+    int             nClosAlloc;   // the allocated size of clause arrays
+    // internal BCP
+    int             nRootSize;    // the number of root level assignments
+    int             nTrailSize;   // the number of assignments made 
+    lit *           pTrail;       // chronological order of assignments (size nVars)
+    lit *           pAssigns;     // assignments by variable (size nVars) 
+    char *          pSeens;       // temporary mark (size nVars)
+    Sto_Cls_t **    pReasons;     // reasons for each assignment (size nVars)          
+    Sto_Cls_t **    pWatches;     // watched clauses for each literal (size 2*nVars)          
+    // interpolation data
+    Aig_Man_t *     pAig;         // the AIG manager for recording the interpolant
+    int *           pVarTypes;    // variable type (size nVars) [1=A, 0=B, <0=AB]
+    Aig_Obj_t **    pInters;      // storage for interpolants as truth tables (size nClauses)
+    int             nIntersAlloc; // the allocated size of truth table array
+    // proof recording
+    int             Counter;      // counter of resolved clauses
+    int *           pProofNums;   // the proof numbers for each clause (size nClauses)
+    FILE *          pFile;        // the file for proof recording
+    // internal verification
+    Vec_Int_t *     vResLits;
+    // runtime stats
+    abctime         timeBcp;      // the runtime for BCP
+    abctime         timeTrace;    // the runtime of trace construction
+    abctime         timeTotal;    // the total runtime of interpolation
+};
+
+// procedure to get hold of the clauses' truth table 
+static inline Aig_Obj_t ** Inta_ManAigRead( Inta_Man_t * pMan, Sto_Cls_t * pCls )                   { return pMan->pInters + pCls->Id;          }
+static inline void         Inta_ManAigClear( Inta_Man_t * pMan, Aig_Obj_t ** p )                    { *p = Aig_ManConst0(pMan->pAig);           }
+static inline void         Inta_ManAigFill( Inta_Man_t * pMan, Aig_Obj_t ** p )                     { *p = Aig_ManConst1(pMan->pAig);           }
+static inline void         Inta_ManAigCopy( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q )     { *p = *q;                                  }
+static inline void         Inta_ManAigAnd( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q )      { *p = Aig_And(pMan->pAig, *p, *q);         }
+static inline void         Inta_ManAigOr( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q )       { *p = Aig_Or(pMan->pAig, *p, *q);          }
+static inline void         Inta_ManAigOrNot( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q )    { *p = Aig_Or(pMan->pAig, *p, Aig_Not(*q)); }
+static inline void         Inta_ManAigOrVar( Inta_Man_t * pMan, Aig_Obj_t ** p, int v )             { *p = Aig_Or(pMan->pAig, *p, Aig_IthVar(pMan->pAig, v));          }
+static inline void         Inta_ManAigOrNotVar( Inta_Man_t * pMan, Aig_Obj_t ** p, int v )          { *p = Aig_Or(pMan->pAig, *p, Aig_Not(Aig_IthVar(pMan->pAig, v))); }
+
+// reading/writing the proof for a clause
+static inline int          Inta_ManProofGet( Inta_Man_t * p, Sto_Cls_t * pCls )                  { return p->pProofNums[pCls->Id];           }
+static inline void         Inta_ManProofSet( Inta_Man_t * p, Sto_Cls_t * pCls, int n )           { p->pProofNums[pCls->Id] = n;              }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocate proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Inta_Man_t * Inta_ManAlloc()
+{
+    Inta_Man_t * p;
+    // allocate the manager
+    p = (Inta_Man_t *)ABC_ALLOC( char, sizeof(Inta_Man_t) );
+    memset( p, 0, sizeof(Inta_Man_t) );
+    // verification
+    p->vResLits = Vec_IntAlloc( 1000 );
+    // parameters
+    p->fProofWrite = 0;
+    p->fProofVerif = 1;
+    return p;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count common variables in the clauses of A and B.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Inta_ManGlobalVars( Inta_Man_t * p )
+{
+    Sto_Cls_t * pClause;
+    int LargeNum = -100000000;
+    int Var, nVarsAB, v;
+
+    // mark the variable encountered in the clauses of A
+    Sto_ManForEachClauseRoot( p->pCnf, pClause )
+    {
+        if ( !pClause->fA )
+            break;
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+            p->pVarTypes[lit_var(pClause->pLits[v])] = 1;
+    }
+
+    // check variables that appear in clauses of B
+    nVarsAB = 0;
+    Sto_ManForEachClauseRoot( p->pCnf, pClause )
+    {
+        if ( pClause->fA )
+            continue;
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+        {
+            Var = lit_var(pClause->pLits[v]);
+            if ( p->pVarTypes[Var] == 1 ) // var of A
+            {
+                // change it into a global variable
+                nVarsAB++;
+                p->pVarTypes[Var] = LargeNum;
+            }
+        }
+    }
+    assert( nVarsAB <= Vec_IntSize(p->vVarsAB) );
+
+    // order global variables
+    nVarsAB = 0;
+    Vec_IntForEachEntry( p->vVarsAB, Var, v )
+        p->pVarTypes[Var] = -(1+nVarsAB++);
+
+    // check that there is no extra global variables
+    for ( v = 0; v < p->pCnf->nVars; v++ )
+        assert( p->pVarTypes[v] != LargeNum );
+    return nVarsAB;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resize proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Inta_ManResize( Inta_Man_t * p )
+{
+    p->Counter = 0;
+    // check if resizing is needed
+    if ( p->nVarsAlloc < p->pCnf->nVars )
+    {
+        // find the new size
+        if ( p->nVarsAlloc == 0 )
+            p->nVarsAlloc = 1;
+        while ( p->nVarsAlloc < p->pCnf->nVars ) 
+            p->nVarsAlloc *= 2;
+        // resize the arrays
+        p->pTrail    = ABC_REALLOC(lit,         p->pTrail,    p->nVarsAlloc );
+        p->pAssigns  = ABC_REALLOC(lit,         p->pAssigns,  p->nVarsAlloc );
+        p->pSeens    = ABC_REALLOC(char,        p->pSeens,    p->nVarsAlloc );
+        p->pVarTypes = ABC_REALLOC(int,         p->pVarTypes, p->nVarsAlloc );
+        p->pReasons  = ABC_REALLOC(Sto_Cls_t *, p->pReasons,  p->nVarsAlloc );
+        p->pWatches  = ABC_REALLOC(Sto_Cls_t *, p->pWatches,  p->nVarsAlloc*2 );
+    }
+
+    // clean the free space
+    memset( p->pAssigns , 0xff, sizeof(lit) * p->pCnf->nVars );
+    memset( p->pSeens   , 0,    sizeof(char) * p->pCnf->nVars );
+    memset( p->pVarTypes, 0,    sizeof(int) * p->pCnf->nVars );
+    memset( p->pReasons , 0,    sizeof(Sto_Cls_t *) * p->pCnf->nVars );
+    memset( p->pWatches , 0,    sizeof(Sto_Cls_t *) * p->pCnf->nVars*2 );
+
+    // compute the number of common variables
+    Inta_ManGlobalVars( p );
+
+    // check if resizing of clauses is needed
+    if ( p->nClosAlloc < p->pCnf->nClauses )
+    {
+        // find the new size
+        if ( p->nClosAlloc == 0 )
+            p->nClosAlloc = 1;
+        while ( p->nClosAlloc < p->pCnf->nClauses ) 
+            p->nClosAlloc *= 2;
+        // resize the arrays
+        p->pProofNums = ABC_REALLOC( int, p->pProofNums,  p->nClosAlloc );
+    }
+    memset( p->pProofNums, 0, sizeof(int) * p->pCnf->nClauses );
+
+    // check if resizing of truth tables is needed
+    if ( p->nIntersAlloc < p->pCnf->nClauses )
+    {
+        p->nIntersAlloc = p->pCnf->nClauses;
+        p->pInters = ABC_REALLOC( Aig_Obj_t *, p->pInters, p->nIntersAlloc );
+    }
+    memset( p->pInters, 0, sizeof(Aig_Obj_t *) * p->pCnf->nClauses );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocate proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Inta_ManFree( Inta_Man_t * p )
+{
+/*
+    printf( "Runtime stats:\n" );
+ABC_PRT( "BCP     ", p->timeBcp   );
+ABC_PRT( "Trace   ", p->timeTrace );
+ABC_PRT( "TOTAL   ", p->timeTotal );
+*/
+    ABC_FREE( p->pInters );
+    ABC_FREE( p->pProofNums );
+    ABC_FREE( p->pTrail );
+    ABC_FREE( p->pAssigns );
+    ABC_FREE( p->pSeens );
+    ABC_FREE( p->pVarTypes );
+    ABC_FREE( p->pReasons );
+    ABC_FREE( p->pWatches );
+    Vec_IntFree( p->vResLits );
+    ABC_FREE( p );
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Inta_ManPrintClause( Inta_Man_t * p, Sto_Cls_t * pClause )
+{
+    int i;
+    printf( "Clause ID = %d. Proof = %d. {", pClause->Id, Inta_ManProofGet(p, pClause) );
+    for ( i = 0; i < (int)pClause->nLits; i++ )
+        printf( " %d", pClause->pLits[i] );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the resolvent.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Inta_ManPrintResolvent( Vec_Int_t * vResLits )
+{
+    int i, Entry;
+    printf( "Resolvent: {" );
+    Vec_IntForEachEntry( vResLits, Entry, i )
+        printf( " %d", Entry );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the interpolant for one clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Inta_ManPrintInterOne( Inta_Man_t * p, Sto_Cls_t * pClause )
+{
+    printf( "Clause %2d :  ", pClause->Id );
+//    Extra_PrintBinary___( stdout, Inta_ManAigRead(p, pClause), (1 << p->nVarsAB) );
+    printf( "\n" );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one clause to the watcher list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Inta_ManWatchClause( Inta_Man_t * p, Sto_Cls_t * pClause, lit Lit )
+{
+    assert( lit_check(Lit, p->pCnf->nVars) );
+    if ( pClause->pLits[0] == Lit )
+        pClause->pNext0 = p->pWatches[lit_neg(Lit)];  
+    else
+    {
+        assert( pClause->pLits[1] == Lit );
+        pClause->pNext1 = p->pWatches[lit_neg(Lit)];  
+    }
+    p->pWatches[lit_neg(Lit)] = pClause;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Records implication.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Inta_ManEnqueue( Inta_Man_t * p, lit Lit, Sto_Cls_t * pReason )
+{
+    int Var = lit_var(Lit);
+    if ( p->pAssigns[Var] != LIT_UNDEF )
+        return p->pAssigns[Var] == Lit;
+    p->pAssigns[Var] = Lit;
+    p->pReasons[Var] = pReason;
+    p->pTrail[p->nTrailSize++] = Lit;
+//printf( "assigning var %d value %d\n", Var, !lit_sign(Lit) );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records implication.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Inta_ManCancelUntil( Inta_Man_t * p, int Level )
+{
+    lit Lit;
+    int i, Var;
+    for ( i = p->nTrailSize - 1; i >= Level; i-- )
+    {
+        Lit = p->pTrail[i];
+        Var = lit_var( Lit );
+        p->pReasons[Var] = NULL;
+        p->pAssigns[Var] = LIT_UNDEF;
+//printf( "cancelling var %d\n", Var );
+    }
+    p->nTrailSize = Level;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagate one assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Sto_Cls_t * Inta_ManPropagateOne( Inta_Man_t * p, lit Lit )
+{
+    Sto_Cls_t ** ppPrev, * pCur, * pTemp;
+    lit LitF = lit_neg(Lit);
+    int i;
+    // iterate through the literals
+    ppPrev = p->pWatches + Lit;
+    for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev )
+    {
+        // make sure the false literal is in the second literal of the clause
+        if ( pCur->pLits[0] == LitF )
+        {
+            pCur->pLits[0] = pCur->pLits[1];
+            pCur->pLits[1] = LitF;
+            pTemp = pCur->pNext0;
+            pCur->pNext0 = pCur->pNext1;
+            pCur->pNext1 = pTemp;
+        }
+        assert( pCur->pLits[1] == LitF );
+
+        // if the first literal is true, the clause is satisfied
+        if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] )
+        {
+            ppPrev = &pCur->pNext1;
+            continue;
+        }
+
+        // look for a new literal to watch
+        for ( i = 2; i < (int)pCur->nLits; i++ )
+        {
+            // skip the case when the literal is false
+            if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] )
+                continue;
+            // the literal is either true or unassigned - watch it
+            pCur->pLits[1] = pCur->pLits[i];
+            pCur->pLits[i] = LitF;
+            // remove this clause from the watch list of Lit
+            *ppPrev = pCur->pNext1;
+            // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1])
+            Inta_ManWatchClause( p, pCur, pCur->pLits[1] );
+            break;
+        }
+        if ( i < (int)pCur->nLits ) // found new watch
+            continue;
+
+        // clause is unit - enqueue new implication
+        if ( Inta_ManEnqueue(p, pCur->pLits[0], pCur) )
+        {
+            ppPrev = &pCur->pNext1;
+            continue;
+        }
+
+        // conflict detected - return the conflict clause
+        return pCur;
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagate the current assignments.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Sto_Cls_t * Inta_ManPropagate( Inta_Man_t * p, int Start )
+{
+    Sto_Cls_t * pClause;
+    int i;
+    abctime clk = Abc_Clock();
+    for ( i = Start; i < p->nTrailSize; i++ )
+    {
+        pClause = Inta_ManPropagateOne( p, p->pTrail[i] );
+        if ( pClause )
+        {
+p->timeBcp += Abc_Clock() - clk;
+            return pClause;
+        }
+    }
+p->timeBcp += Abc_Clock() - clk;
+    return NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes one root clause into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Inta_ManProofWriteOne( Inta_Man_t * p, Sto_Cls_t * pClause )
+{
+    Inta_ManProofSet( p, pClause, ++p->Counter );
+
+    if ( p->fProofWrite )
+    {
+        int v;
+        fprintf( p->pFile, "%d", Inta_ManProofGet(p, pClause) );
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+            fprintf( p->pFile, " %d", lit_print(pClause->pLits[v]) );
+        fprintf( p->pFile, " 0 0\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Traces the proof for one clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Inta_ManProofTraceOne( Inta_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pFinal )
+{
+    Sto_Cls_t * pReason;
+    int i, v, Var, PrevId;
+    int fPrint = 0;
+    abctime clk = Abc_Clock();
+
+    // collect resolvent literals
+    if ( p->fProofVerif )
+    {
+        Vec_IntClear( p->vResLits );
+        for ( i = 0; i < (int)pConflict->nLits; i++ )
+            Vec_IntPush( p->vResLits, pConflict->pLits[i] );
+    }
+
+    // mark all the variables in the conflict as seen
+    for ( v = 0; v < (int)pConflict->nLits; v++ )
+        p->pSeens[lit_var(pConflict->pLits[v])] = 1;
+
+    // start the anticedents
+//    pFinal->pAntis = Vec_PtrAlloc( 32 );
+//    Vec_PtrPush( pFinal->pAntis, pConflict );
+
+    if ( p->pCnf->nClausesA )
+        Inta_ManAigCopy( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pConflict) );
+
+    // follow the trail backwards
+    PrevId = Inta_ManProofGet(p, pConflict);
+    for ( i = p->nTrailSize - 1; i >= 0; i-- )
+    {
+        // skip literals that are not involved
+        Var = lit_var(p->pTrail[i]);
+        if ( !p->pSeens[Var] )
+            continue;
+        p->pSeens[Var] = 0;
+
+        // skip literals of the resulting clause
+        pReason = p->pReasons[Var];
+        if ( pReason == NULL )
+            continue;
+        assert( p->pTrail[i] == pReason->pLits[0] );
+
+        // add the variables to seen
+        for ( v = 1; v < (int)pReason->nLits; v++ )
+            p->pSeens[lit_var(pReason->pLits[v])] = 1;
+
+        // record the reason clause
+        assert( Inta_ManProofGet(p, pReason) > 0 );
+        p->Counter++;
+        if ( p->fProofWrite )
+            fprintf( p->pFile, "%d * %d %d 0\n", p->Counter, PrevId, Inta_ManProofGet(p, pReason) );
+        PrevId = p->Counter;
+
+        if ( p->pCnf->nClausesA )
+        {
+            if ( p->pVarTypes[Var] == 1 ) // var of A
+                Inta_ManAigOr( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pReason) );
+            else
+                Inta_ManAigAnd( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pReason) );
+        }
+ 
+        // resolve the temporary resolvent with the reason clause
+        if ( p->fProofVerif )
+        {
+            int v1, v2, Entry = -1; 
+            if ( fPrint )
+                Inta_ManPrintResolvent( p->vResLits );
+            // check that the var is present in the resolvent
+            Vec_IntForEachEntry( p->vResLits, Entry, v1 )
+                if ( lit_var(Entry) == Var )
+                    break;
+            if ( v1 == Vec_IntSize(p->vResLits) )
+                printf( "Recording clause %d: Cannot find variable %d in the temporary resolvent.\n", pFinal->Id, Var );
+            if ( Entry != lit_neg(pReason->pLits[0]) )
+                printf( "Recording clause %d: The resolved variable %d is in the wrong polarity.\n", pFinal->Id, Var );
+            // remove variable v1 from the resolvent
+            assert( lit_var(Entry) == Var );
+            Vec_IntRemove( p->vResLits, Entry );
+            // add variables of the reason clause
+            for ( v2 = 1; v2 < (int)pReason->nLits; v2++ )
+            {
+                Vec_IntForEachEntry( p->vResLits, Entry, v1 )
+                    if ( lit_var(Entry) == lit_var(pReason->pLits[v2]) )
+                        break;
+                // if it is a new variable, add it to the resolvent
+                if ( v1 == Vec_IntSize(p->vResLits) ) 
+                {
+                    Vec_IntPush( p->vResLits, pReason->pLits[v2] );
+                    continue;
+                }
+                // if the variable is the same, the literal should be the same too
+                if ( Entry == pReason->pLits[v2] )
+                    continue;
+                // the literal is different
+                printf( "Recording clause %d: Trying to resolve the clause with more than one opposite literal.\n", pFinal->Id );
+            }
+        }
+//        Vec_PtrPush( pFinal->pAntis, pReason );
+    }
+
+    // unmark all seen variables
+//    for ( i = p->nTrailSize - 1; i >= 0; i-- )
+//        p->pSeens[lit_var(p->pTrail[i])] = 0;
+    // check that the literals are unmarked
+//    for ( i = p->nTrailSize - 1; i >= 0; i-- )
+//        assert( p->pSeens[lit_var(p->pTrail[i])] == 0 );
+
+    // use the resulting clause to check the correctness of resolution
+    if ( p->fProofVerif )
+    {
+        int v1, v2, Entry = -1; 
+        if ( fPrint )
+            Inta_ManPrintResolvent( p->vResLits );
+        Vec_IntForEachEntry( p->vResLits, Entry, v1 )
+        {
+            for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ )
+                if ( pFinal->pLits[v2] == Entry )
+                    break;
+            if ( v2 < (int)pFinal->nLits )
+                continue;
+            break;
+        }
+        if ( v1 < Vec_IntSize(p->vResLits) )
+        {
+            printf( "Recording clause %d: The final resolvent is wrong.\n", pFinal->Id );
+            Inta_ManPrintClause( p, pConflict );
+            Inta_ManPrintResolvent( p->vResLits );
+            Inta_ManPrintClause( p, pFinal );
+        }
+
+        // if there are literals in the clause that are not in the resolvent
+        // it means that the derived resolvent is stronger than the clause
+        // we can replace the clause with the resolvent by removing these literals
+        if ( Vec_IntSize(p->vResLits) != (int)pFinal->nLits )
+        {
+            for ( v1 = 0; v1 < (int)pFinal->nLits; v1++ )
+            {
+                Vec_IntForEachEntry( p->vResLits, Entry, v2 )
+                    if ( pFinal->pLits[v1] == Entry )
+                        break;
+                if ( v2 < Vec_IntSize(p->vResLits) )
+                    continue;
+                // remove literal v1 from the final clause
+                pFinal->nLits--;
+                for ( v2 = v1; v2 < (int)pFinal->nLits; v2++ )
+                    pFinal->pLits[v2] = pFinal->pLits[v2+1];
+                v1--;
+            }
+            assert( Vec_IntSize(p->vResLits) == (int)pFinal->nLits );
+        }
+    }
+p->timeTrace += Abc_Clock() - clk;
+
+    // return the proof pointer 
+    if ( p->pCnf->nClausesA )
+    {
+//        Inta_ManPrintInterOne( p, pFinal );
+    }
+    Inta_ManProofSet( p, pFinal, p->Counter );
+    // make sure the same proof ID is not asssigned to two consecutive clauses
+    assert( p->pProofNums[pFinal->Id-1] != p->Counter );
+//    if ( p->pProofNums[pFinal->Id] == p->pProofNums[pFinal->Id-1] )
+//        p->pProofNums[pFinal->Id] = p->pProofNums[pConflict->Id];
+    return p->Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records the proof for one clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Inta_ManProofRecordOne( Inta_Man_t * p, Sto_Cls_t * pClause )
+{
+    Sto_Cls_t * pConflict;
+    int i;
+
+    // empty clause never ends up there
+    assert( pClause->nLits > 0 );
+    if ( pClause->nLits == 0 )
+        printf( "Error: Empty clause is attempted.\n" );
+
+    assert( !pClause->fRoot );
+    assert( p->nTrailSize == p->nRootSize );
+
+    // if any of the clause literals are already assumed
+    // it means that the clause is redundant and can be skipped
+    for ( i = 0; i < (int)pClause->nLits; i++ )
+        if ( p->pAssigns[lit_var(pClause->pLits[i])] == pClause->pLits[i] )
+            return 1;
+
+    // add assumptions to the trail
+    for ( i = 0; i < (int)pClause->nLits; i++ )
+        if ( !Inta_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) )
+        {
+            assert( 0 ); // impossible
+            return 0;
+        }
+
+    // propagate the assumptions
+    pConflict = Inta_ManPropagate( p, p->nRootSize );
+    if ( pConflict == NULL )
+    {
+        assert( 0 ); // cannot prove
+        return 0;
+    } 
+
+    // skip the clause if it is weaker or the same as the conflict clause
+    if ( pClause->nLits >= pConflict->nLits )
+    {
+        // check if every literal of conflict clause can be found in the given clause
+        int j;
+        for ( i = 0; i < (int)pConflict->nLits; i++ )
+        {
+            for ( j = 0; j < (int)pClause->nLits; j++ )
+                if ( pConflict->pLits[i] == pClause->pLits[j] )
+                    break;
+            if ( j == (int)pClause->nLits ) // literal pConflict->pLits[i] is not found
+                break;
+        }
+        if ( i == (int)pConflict->nLits ) // all lits are found
+        {
+            // undo to the root level
+            Inta_ManCancelUntil( p, p->nRootSize );
+            return 1;
+        }
+    }
+
+    // construct the proof
+    Inta_ManProofTraceOne( p, pConflict, pClause );
+
+    // undo to the root level
+    Inta_ManCancelUntil( p, p->nRootSize );
+
+    // add large clauses to the watched lists
+    if ( pClause->nLits > 1 )
+    {
+        Inta_ManWatchClause( p, pClause, pClause->pLits[0] );
+        Inta_ManWatchClause( p, pClause, pClause->pLits[1] );
+        return 1;
+    }
+    assert( pClause->nLits == 1 );
+
+    // if the clause proved is unit, add it and propagate
+    if ( !Inta_ManEnqueue( p, pClause->pLits[0], pClause ) )
+    {
+        assert( 0 ); // impossible
+        return 0;
+    }
+
+    // propagate the assumption
+    pConflict = Inta_ManPropagate( p, p->nRootSize );
+    if ( pConflict )
+    {
+        // construct the proof
+        Inta_ManProofTraceOne( p, pConflict, p->pCnf->pEmpty );
+//        if ( p->fVerbose )
+//            printf( "Found last conflict after adding unit clause number %d!\n", pClause->Id );
+        return 0;
+    }
+
+    // update the root level
+    p->nRootSize = p->nTrailSize;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagate the root clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Inta_ManProcessRoots( Inta_Man_t * p )
+{
+    Sto_Cls_t * pClause;
+    int Counter;
+
+    // make sure the root clauses are preceeding the learnt clauses
+    Counter = 0;
+    Sto_ManForEachClause( p->pCnf, pClause )
+    {
+        assert( (int)pClause->fA    == (Counter < (int)p->pCnf->nClausesA) );
+        assert( (int)pClause->fRoot == (Counter < (int)p->pCnf->nRoots)    );
+        Counter++;
+    }
+    assert( p->pCnf->nClauses == Counter );
+
+    // make sure the last clause if empty
+    assert( p->pCnf->pTail->nLits == 0 );
+
+    // go through the root unit clauses
+    p->nTrailSize = 0;
+    Sto_ManForEachClauseRoot( p->pCnf, pClause )
+    {
+        // create watcher lists for the root clauses
+        if ( pClause->nLits > 1 )
+        {
+            Inta_ManWatchClause( p, pClause, pClause->pLits[0] );
+            Inta_ManWatchClause( p, pClause, pClause->pLits[1] );
+        }
+        // empty clause and large clauses
+        if ( pClause->nLits != 1 )
+            continue;
+        // unit clause
+        assert( lit_check(pClause->pLits[0], p->pCnf->nVars) );
+        if ( !Inta_ManEnqueue( p, pClause->pLits[0], pClause ) )
+        {
+            // detected root level conflict
+//            printf( "Error in Inta_ManProcessRoots(): Detected a root-level conflict too early!\n" );
+//            assert( 0 );
+            // detected root level conflict
+            Inta_ManProofTraceOne( p, pClause, p->pCnf->pEmpty );
+            if ( p->fVerbose )
+                printf( "Found root level conflict!\n" );
+            return 0;
+        }
+    }
+
+    // propagate the root unit clauses
+    pClause = Inta_ManPropagate( p, 0 );
+    if ( pClause )
+    {
+        // detected root level conflict
+        Inta_ManProofTraceOne( p, pClause, p->pCnf->pEmpty );
+        if ( p->fVerbose )
+            printf( "Found root level conflict!\n" );
+        return 0;
+    }
+
+    // set the root level
+    p->nRootSize = p->nTrailSize;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records the proof.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Inta_ManPrepareInter( Inta_Man_t * p )
+{
+    Sto_Cls_t * pClause;
+    int Var, VarAB, v;
+
+    // set interpolants for root clauses
+    Sto_ManForEachClauseRoot( p->pCnf, pClause )
+    {
+        if ( !pClause->fA ) // clause of B
+        {
+            Inta_ManAigFill( p, Inta_ManAigRead(p, pClause) );
+//            Inta_ManPrintInterOne( p, pClause );
+            continue;
+        }
+        // clause of A
+        Inta_ManAigClear( p, Inta_ManAigRead(p, pClause) );
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+        {
+            Var = lit_var(pClause->pLits[v]);
+            if ( p->pVarTypes[Var] < 0 ) // global var
+            {
+                VarAB = -p->pVarTypes[Var]-1;
+                assert( VarAB >= 0 && VarAB < Vec_IntSize(p->vVarsAB) );
+                if ( lit_sign(pClause->pLits[v]) ) // negative var
+                    Inta_ManAigOrNotVar( p, Inta_ManAigRead(p, pClause), VarAB );
+                else
+                    Inta_ManAigOrVar( p, Inta_ManAigRead(p, pClause), VarAB );
+            }
+        }
+//        Inta_ManPrintInterOne( p, pClause );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes interpolant for the given CNF.]
+
+  Description [Takes the interpolation manager, the CNF deriving by the SAT
+  solver, which includes ClausesA, ClausesB, and learned clauses. Additional
+  arguments are the vector of variables common to AB and the verbosiness flag.
+  Returns the AIG manager with a single output, containing the interpolant.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Inta_ManInterpolate( Inta_Man_t * p, Sto_Man_t * pCnf, abctime TimeToStop, void * vVarsAB, int fVerbose )
+{
+    Aig_Man_t * pRes;
+    Aig_Obj_t * pObj;
+    Sto_Cls_t * pClause;
+    int RetValue = 1;
+    abctime clkTotal = Abc_Clock();
+
+    if ( TimeToStop && Abc_Clock() > TimeToStop )
+        return NULL;
+
+    // check that the CNF makes sense
+    assert( pCnf->nVars > 0 && pCnf->nClauses > 0 );
+    p->pCnf = pCnf;
+    p->fVerbose = fVerbose;
+    p->vVarsAB = (Vec_Int_t *)vVarsAB;
+    p->pAig = pRes = Aig_ManStart( 10000 );
+    Aig_IthVar( p->pAig, Vec_IntSize(p->vVarsAB) - 1 );
+
+    // adjust the manager
+    Inta_ManResize( p );
+
+    // prepare the interpolant computation
+    Inta_ManPrepareInter( p );
+
+    // construct proof for each clause
+    // start the proof
+    if ( p->fProofWrite )
+    {
+        p->pFile = fopen( "proof.cnf_", "w" );
+        p->Counter = 0;
+    }
+
+    // write the root clauses
+    Sto_ManForEachClauseRoot( p->pCnf, pClause )
+    {
+        Inta_ManProofWriteOne( p, pClause );
+        if ( TimeToStop && Abc_Clock() > TimeToStop )
+        {
+            Aig_ManStop( pRes );
+            p->pAig = NULL;
+            return NULL;
+        }
+    }
+
+    // propagate root level assignments
+    if ( Inta_ManProcessRoots( p ) )
+    {
+        // if there is no conflict, consider learned clauses
+        Sto_ManForEachClause( p->pCnf, pClause )
+        {
+            if ( pClause->fRoot )
+                continue;
+            if ( !Inta_ManProofRecordOne( p, pClause ) )
+            {
+                RetValue = 0;
+                break;
+            }
+            if ( TimeToStop && Abc_Clock() > TimeToStop )
+            {
+                Aig_ManStop( pRes );
+                p->pAig = NULL;
+                return NULL;
+            }
+        }
+    }
+
+    // stop the proof
+    if ( p->fProofWrite )
+    { 
+        fclose( p->pFile );
+//        Sat_ProofChecker( "proof.cnf_" );
+        p->pFile = NULL;    
+    }
+
+    if ( fVerbose )
+    {
+//        ABC_PRT( "Interpo", Abc_Clock() - clkTotal );
+    printf( "Vars = %d. Roots = %d. Learned = %d. Resol steps = %d.  Ave = %.2f.  Mem = %.2f MB\n", 
+        p->pCnf->nVars, p->pCnf->nRoots, p->pCnf->nClauses-p->pCnf->nRoots, p->Counter,  
+        1.0*(p->Counter-p->pCnf->nRoots)/(p->pCnf->nClauses-p->pCnf->nRoots), 
+        1.0*Sto_ManMemoryReport(p->pCnf)/(1<<20) );
+p->timeTotal += Abc_Clock() - clkTotal;
+    }
+
+    pObj = *Inta_ManAigRead( p, p->pCnf->pTail );
+    Aig_ObjCreateCo( pRes, pObj );
+    Aig_ManCleanup( pRes );
+
+    p->pAig = NULL;
+    return pRes;
+    
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Inta_ManDeriveClauses( Inta_Man_t * pMan, Sto_Man_t * pCnf, int fClausesA )
+{
+    Aig_Man_t * p;
+    Aig_Obj_t * pMiter, * pSum, * pLit;
+    Sto_Cls_t * pClause;
+    int Var, VarAB, v;
+    p = Aig_ManStart( 10000 );
+    pMiter = Aig_ManConst1(p);
+    Sto_ManForEachClauseRoot( pCnf, pClause )
+    {
+        if ( fClausesA ^ pClause->fA ) // clause of B
+            continue;
+        // clause of A
+        pSum = Aig_ManConst0(p);
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+        {
+            Var = lit_var(pClause->pLits[v]);
+            if ( pMan->pVarTypes[Var] < 0 ) // global var
+            {
+                VarAB = -pMan->pVarTypes[Var]-1;
+                assert( VarAB >= 0 && VarAB < Vec_IntSize(pMan->vVarsAB) );
+                pLit = Aig_NotCond( Aig_IthVar(p, VarAB), lit_sign(pClause->pLits[v]) );
+            }
+            else
+                pLit = Aig_NotCond( Aig_IthVar(p, Vec_IntSize(pMan->vVarsAB)+1+Var), lit_sign(pClause->pLits[v]) );
+            pSum = Aig_Or( p, pSum, pLit );
+        }
+        pMiter = Aig_And( p, pMiter, pSum );
+    }
+    Aig_ObjCreateCo( p, pMiter );
+    return p;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bsat/satInterB.c b/abc-build/src/sat/bsat/satInterB.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satInterB.c
@@ -0,0 +1,1115 @@
+/**CFile****************************************************************
+
+  FileName    [satInter.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT sat_solver.]
+
+  Synopsis    [Interpolation package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: satInter.c,v 1.4 2005/09/16 22:55:03 casem Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "satStore.h"
+#include "aig/aig/aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// variable assignments 
+static const lit    LIT_UNDEF = 0xffffffff;
+
+// interpolation manager
+struct Intb_Man_t_
+{
+    // clauses of the problems
+    Sto_Man_t *     pCnf;         // the set of CNF clauses for A and B
+    Vec_Int_t *     vVarsAB;      // the array of global variables
+    // various parameters
+    int             fVerbose;     // verbosiness flag
+    int             fProofVerif;  // verifies the proof
+    int             fProofWrite;  // writes the proof file
+    int             nVarsAlloc;   // the allocated size of var arrays
+    int             nClosAlloc;   // the allocated size of clause arrays
+    // internal BCP
+    int             nRootSize;    // the number of root level assignments
+    int             nTrailSize;   // the number of assignments made 
+    lit *           pTrail;       // chronological order of assignments (size nVars)
+    lit *           pAssigns;     // assignments by variable (size nVars) 
+    char *          pSeens;       // temporary mark (size nVars)
+    Sto_Cls_t **    pReasons;     // reasons for each assignment (size nVars)          
+    Sto_Cls_t **    pWatches;     // watched clauses for each literal (size 2*nVars)          
+    // interpolation data
+    Aig_Man_t *     pAig;         // the AIG manager for recording the interpolant
+    int *           pVarTypes;    // variable type (size nVars) [1=A, 0=B, <0=AB]
+    Aig_Obj_t **    pInters;      // storage for interpolants as truth tables (size nClauses)
+    int             nIntersAlloc; // the allocated size of truth table array
+    // proof recording
+    int             Counter;      // counter of resolved clauses
+    int *           pProofNums;   // the proof numbers for each clause (size nClauses)
+    FILE *          pFile;        // the file for proof recording
+    // internal verification
+    lit *           pResLits;     // the literals of the resolvent   
+    int             nResLits;     // the number of literals of the resolvent
+    int             nResLitsAlloc;// the number of literals of the resolvent
+    // runtime stats
+    abctime         timeBcp;      // the runtime for BCP
+    abctime         timeTrace;    // the runtime of trace construction
+    abctime         timeTotal;    // the total runtime of interpolation
+};
+
+// procedure to get hold of the clauses' truth table 
+static inline Aig_Obj_t ** Intb_ManAigRead( Intb_Man_t * pMan, Sto_Cls_t * pCls )                   { return pMan->pInters + pCls->Id;          }
+static inline void         Intb_ManAigClear( Intb_Man_t * pMan, Aig_Obj_t ** p )                    { *p = Aig_ManConst0(pMan->pAig);           }
+static inline void         Intb_ManAigFill( Intb_Man_t * pMan, Aig_Obj_t ** p )                     { *p = Aig_ManConst1(pMan->pAig);           }
+static inline void         Intb_ManAigCopy( Intb_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q )     { *p = *q;                                  }
+static inline void         Intb_ManAigAnd( Intb_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q )      { *p = Aig_And(pMan->pAig, *p, *q);         }
+static inline void         Intb_ManAigOr( Intb_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q )       { *p = Aig_Or(pMan->pAig, *p, *q);          }
+static inline void         Intb_ManAigOrNot( Intb_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q )    { *p = Aig_Or(pMan->pAig, *p, Aig_Not(*q)); }
+static inline void         Intb_ManAigOrVar( Intb_Man_t * pMan, Aig_Obj_t ** p, int v )             { *p = Aig_Or(pMan->pAig, *p, Aig_IthVar(pMan->pAig, v));          }
+static inline void         Intb_ManAigOrNotVar( Intb_Man_t * pMan, Aig_Obj_t ** p, int v )          { *p = Aig_Or(pMan->pAig, *p, Aig_Not(Aig_IthVar(pMan->pAig, v))); }
+static inline void         Intb_ManAigMux0( Intb_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q, int v){ *p = Aig_Mux(pMan->pAig, Aig_IthVar(pMan->pAig, v), *q, *p);     }
+static inline void         Intb_ManAigMux1( Intb_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q, int v){ *p = Aig_Mux(pMan->pAig, Aig_IthVar(pMan->pAig, v), *p, *q);     }
+
+// reading/writing the proof for a clause
+static inline int          Intb_ManProofGet( Intb_Man_t * p, Sto_Cls_t * pCls )                  { return p->pProofNums[pCls->Id];           }
+static inline void         Intb_ManProofSet( Intb_Man_t * p, Sto_Cls_t * pCls, int n )           { p->pProofNums[pCls->Id] = n;              }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocate proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Intb_Man_t * Intb_ManAlloc()
+{
+    Intb_Man_t * p;
+    // allocate the manager
+    p = (Intb_Man_t *)ABC_ALLOC( char, sizeof(Intb_Man_t) );
+    memset( p, 0, sizeof(Intb_Man_t) );
+    // verification
+    p->nResLitsAlloc = (1<<16);
+    p->pResLits = ABC_ALLOC( lit, p->nResLitsAlloc );
+    // parameters
+    p->fProofWrite = 0;
+    p->fProofVerif = 1;
+    return p;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Count common variables in the clauses of A and B.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Intb_ManGlobalVars( Intb_Man_t * p )
+{
+    Sto_Cls_t * pClause;
+    int LargeNum = -100000000;
+    int Var, nVarsAB, v;
+
+    // mark the variable encountered in the clauses of A
+    Sto_ManForEachClauseRoot( p->pCnf, pClause )
+    {
+        if ( !pClause->fA )
+            break;
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+            p->pVarTypes[lit_var(pClause->pLits[v])] = 1;
+    }
+
+    // check variables that appear in clauses of B
+    nVarsAB = 0;
+    Sto_ManForEachClauseRoot( p->pCnf, pClause )
+    {
+        if ( pClause->fA )
+            continue;
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+        {
+            Var = lit_var(pClause->pLits[v]);
+            if ( p->pVarTypes[Var] == 1 ) // var of A
+            {
+                // change it into a global variable
+                nVarsAB++;
+                p->pVarTypes[Var] = LargeNum;
+            }
+        }
+    }
+    assert( nVarsAB <= Vec_IntSize(p->vVarsAB) );
+
+    // order global variables
+    nVarsAB = 0;
+    Vec_IntForEachEntry( p->vVarsAB, Var, v )
+        p->pVarTypes[Var] = -(1+nVarsAB++);
+
+    // check that there is no extra global variables
+    for ( v = 0; v < p->pCnf->nVars; v++ )
+        assert( p->pVarTypes[v] != LargeNum );
+    return nVarsAB;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resize proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Intb_ManResize( Intb_Man_t * p )
+{
+    p->Counter = 0;
+    // check if resizing is needed
+    if ( p->nVarsAlloc < p->pCnf->nVars )
+    {
+        // find the new size
+        if ( p->nVarsAlloc == 0 )
+            p->nVarsAlloc = 1;
+        while ( p->nVarsAlloc < p->pCnf->nVars ) 
+            p->nVarsAlloc *= 2;
+        // resize the arrays
+        p->pTrail    = ABC_REALLOC(lit,         p->pTrail,    p->nVarsAlloc );
+        p->pAssigns  = ABC_REALLOC(lit,         p->pAssigns,  p->nVarsAlloc );
+        p->pSeens    = ABC_REALLOC(char,        p->pSeens,    p->nVarsAlloc );
+        p->pVarTypes = ABC_REALLOC(int,         p->pVarTypes, p->nVarsAlloc );
+        p->pReasons  = ABC_REALLOC(Sto_Cls_t *, p->pReasons,  p->nVarsAlloc );
+        p->pWatches  = ABC_REALLOC(Sto_Cls_t *, p->pWatches,  p->nVarsAlloc*2 );
+    }
+
+    // clean the free space
+    memset( p->pAssigns , 0xff, sizeof(lit) * p->pCnf->nVars );
+    memset( p->pSeens   , 0,    sizeof(char) * p->pCnf->nVars );
+    memset( p->pVarTypes, 0,    sizeof(int) * p->pCnf->nVars );
+    memset( p->pReasons , 0,    sizeof(Sto_Cls_t *) * p->pCnf->nVars );
+    memset( p->pWatches , 0,    sizeof(Sto_Cls_t *) * p->pCnf->nVars*2 );
+
+    // compute the number of common variables
+    Intb_ManGlobalVars( p );
+
+    // check if resizing of clauses is needed
+    if ( p->nClosAlloc < p->pCnf->nClauses )
+    {
+        // find the new size
+        if ( p->nClosAlloc == 0 )
+            p->nClosAlloc = 1;
+        while ( p->nClosAlloc < p->pCnf->nClauses ) 
+            p->nClosAlloc *= 2;
+        // resize the arrays
+        p->pProofNums = ABC_REALLOC( int, p->pProofNums,  p->nClosAlloc );
+    }
+    memset( p->pProofNums, 0, sizeof(int) * p->pCnf->nClauses );
+
+    // check if resizing of truth tables is needed
+    if ( p->nIntersAlloc < p->pCnf->nClauses )
+    {
+        p->nIntersAlloc = p->pCnf->nClauses;
+        p->pInters = ABC_REALLOC( Aig_Obj_t *, p->pInters, p->nIntersAlloc );
+    }
+    memset( p->pInters, 0, sizeof(Aig_Obj_t *) * p->pCnf->nClauses );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocate proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Intb_ManFree( Intb_Man_t * p )
+{
+/*
+    printf( "Runtime stats:\n" );
+ABC_PRT( "BCP     ", p->timeBcp   );
+ABC_PRT( "Trace   ", p->timeTrace );
+ABC_PRT( "TOTAL   ", p->timeTotal );
+*/
+    ABC_FREE( p->pInters );
+    ABC_FREE( p->pProofNums );
+    ABC_FREE( p->pTrail );
+    ABC_FREE( p->pAssigns );
+    ABC_FREE( p->pSeens );
+    ABC_FREE( p->pVarTypes );
+    ABC_FREE( p->pReasons );
+    ABC_FREE( p->pWatches );
+    ABC_FREE( p->pResLits );
+    ABC_FREE( p );
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Intb_ManPrintClause( Intb_Man_t * p, Sto_Cls_t * pClause )
+{
+    int i;
+    printf( "Clause ID = %d. Proof = %d. {", pClause->Id, Intb_ManProofGet(p, pClause) );
+    for ( i = 0; i < (int)pClause->nLits; i++ )
+        printf( " %d", pClause->pLits[i] );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the resolvent.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Intb_ManPrintResolvent( lit * pResLits, int nResLits )
+{
+    int i;
+    printf( "Resolvent: {" );
+    for ( i = 0; i < nResLits; i++ )
+        printf( " %d", pResLits[i] );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the interpolant for one clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Intb_ManPrintInterOne( Intb_Man_t * p, Sto_Cls_t * pClause )
+{
+    printf( "Clause %2d :  ", pClause->Id );
+//    Extra_PrintBinary___( stdout, Intb_ManAigRead(p, pClause), (1 << p->nVarsAB) );
+    printf( "\n" );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one clause to the watcher list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Intb_ManWatchClause( Intb_Man_t * p, Sto_Cls_t * pClause, lit Lit )
+{
+    assert( lit_check(Lit, p->pCnf->nVars) );
+    if ( pClause->pLits[0] == Lit )
+        pClause->pNext0 = p->pWatches[lit_neg(Lit)];  
+    else
+    {
+        assert( pClause->pLits[1] == Lit );
+        pClause->pNext1 = p->pWatches[lit_neg(Lit)];  
+    }
+    p->pWatches[lit_neg(Lit)] = pClause;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Records implication.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Intb_ManEnqueue( Intb_Man_t * p, lit Lit, Sto_Cls_t * pReason )
+{
+    int Var = lit_var(Lit);
+    if ( p->pAssigns[Var] != LIT_UNDEF )
+        return p->pAssigns[Var] == Lit;
+    p->pAssigns[Var] = Lit;
+    p->pReasons[Var] = pReason;
+    p->pTrail[p->nTrailSize++] = Lit;
+//printf( "assigning var %d value %d\n", Var, !lit_sign(Lit) );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records implication.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Intb_ManCancelUntil( Intb_Man_t * p, int Level )
+{
+    lit Lit;
+    int i, Var;
+    for ( i = p->nTrailSize - 1; i >= Level; i-- )
+    {
+        Lit = p->pTrail[i];
+        Var = lit_var( Lit );
+        p->pReasons[Var] = NULL;
+        p->pAssigns[Var] = LIT_UNDEF;
+//printf( "cancelling var %d\n", Var );
+    }
+    p->nTrailSize = Level;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagate one assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Sto_Cls_t * Intb_ManPropagateOne( Intb_Man_t * p, lit Lit )
+{
+    Sto_Cls_t ** ppPrev, * pCur, * pTemp;
+    lit LitF = lit_neg(Lit);
+    int i;
+    // iterate through the literals
+    ppPrev = p->pWatches + Lit;
+    for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev )
+    {
+        // make sure the false literal is in the second literal of the clause
+        if ( pCur->pLits[0] == LitF )
+        {
+            pCur->pLits[0] = pCur->pLits[1];
+            pCur->pLits[1] = LitF;
+            pTemp = pCur->pNext0;
+            pCur->pNext0 = pCur->pNext1;
+            pCur->pNext1 = pTemp;
+        }
+        assert( pCur->pLits[1] == LitF );
+
+        // if the first literal is true, the clause is satisfied
+        if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] )
+        {
+            ppPrev = &pCur->pNext1;
+            continue;
+        }
+
+        // look for a new literal to watch
+        for ( i = 2; i < (int)pCur->nLits; i++ )
+        {
+            // skip the case when the literal is false
+            if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] )
+                continue;
+            // the literal is either true or unassigned - watch it
+            pCur->pLits[1] = pCur->pLits[i];
+            pCur->pLits[i] = LitF;
+            // remove this clause from the watch list of Lit
+            *ppPrev = pCur->pNext1;
+            // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1])
+            Intb_ManWatchClause( p, pCur, pCur->pLits[1] );
+            break;
+        }
+        if ( i < (int)pCur->nLits ) // found new watch
+            continue;
+
+        // clause is unit - enqueue new implication
+        if ( Intb_ManEnqueue(p, pCur->pLits[0], pCur) )
+        {
+            ppPrev = &pCur->pNext1;
+            continue;
+        }
+
+        // conflict detected - return the conflict clause
+        return pCur;
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagate the current assignments.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Sto_Cls_t * Intb_ManPropagate( Intb_Man_t * p, int Start )
+{
+    Sto_Cls_t * pClause;
+    int i;
+    abctime clk = Abc_Clock();
+    for ( i = Start; i < p->nTrailSize; i++ )
+    {
+        pClause = Intb_ManPropagateOne( p, p->pTrail[i] );
+        if ( pClause )
+        {
+p->timeBcp += Abc_Clock() - clk;
+            return pClause;
+        }
+    }
+p->timeBcp += Abc_Clock() - clk;
+    return NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes one root clause into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Intb_ManProofWriteOne( Intb_Man_t * p, Sto_Cls_t * pClause )
+{
+    Intb_ManProofSet( p, pClause, ++p->Counter );
+
+    if ( p->fProofWrite )
+    {
+        int v;
+        fprintf( p->pFile, "%d", Intb_ManProofGet(p, pClause) );
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+            fprintf( p->pFile, " %d", lit_print(pClause->pLits[v]) );
+        fprintf( p->pFile, " 0 0\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Traces the proof for one clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Intb_ManGetGlobalVar( Intb_Man_t * p, int Var )
+{
+    int VarAB;
+    if ( p->pVarTypes[Var] >= 0 ) // global var
+        return -1;
+    VarAB = -p->pVarTypes[Var]-1;
+    assert( VarAB >= 0 && VarAB < Vec_IntSize(p->vVarsAB) );
+    return VarAB;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Traces the proof for one clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Intb_ManProofTraceOne( Intb_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pFinal )
+{
+    Sto_Cls_t * pReason;
+    int i, v, Var, PrevId;
+    int fPrint = 0;
+    abctime clk = Abc_Clock();
+
+    // collect resolvent literals
+    if ( p->fProofVerif )
+    {
+        assert( (int)pConflict->nLits <= p->nResLitsAlloc );
+        memcpy( p->pResLits, pConflict->pLits, sizeof(lit) * pConflict->nLits );
+        p->nResLits = pConflict->nLits;
+    }
+
+    // mark all the variables in the conflict as seen
+    for ( v = 0; v < (int)pConflict->nLits; v++ )
+        p->pSeens[lit_var(pConflict->pLits[v])] = 1;
+
+    // start the anticedents
+//    pFinal->pAntis = Vec_PtrAlloc( 32 );
+//    Vec_PtrPush( pFinal->pAntis, pConflict );
+
+    if ( p->pCnf->nClausesA )
+        Intb_ManAigCopy( p, Intb_ManAigRead(p, pFinal), Intb_ManAigRead(p, pConflict) );
+
+    // follow the trail backwards
+    PrevId = Intb_ManProofGet(p, pConflict);
+    for ( i = p->nTrailSize - 1; i >= 0; i-- )
+    {
+        // skip literals that are not involved
+        Var = lit_var(p->pTrail[i]);
+        if ( !p->pSeens[Var] )
+            continue;
+        p->pSeens[Var] = 0;
+
+        // skip literals of the resulting clause
+        pReason = p->pReasons[Var];
+        if ( pReason == NULL )
+            continue;
+        assert( p->pTrail[i] == pReason->pLits[0] );
+
+        // add the variables to seen
+        for ( v = 1; v < (int)pReason->nLits; v++ )
+            p->pSeens[lit_var(pReason->pLits[v])] = 1;
+
+        // record the reason clause
+        assert( Intb_ManProofGet(p, pReason) > 0 );
+        p->Counter++;
+        if ( p->fProofWrite )
+            fprintf( p->pFile, "%d * %d %d 0\n", p->Counter, PrevId, Intb_ManProofGet(p, pReason) );
+        PrevId = p->Counter;
+
+        if ( p->pCnf->nClausesA )
+        {
+            if ( p->pVarTypes[Var] == 1 )// || rand() % 10 == 0 ) // var of A
+                Intb_ManAigOr( p, Intb_ManAigRead(p, pFinal), Intb_ManAigRead(p, pReason) );
+            else if ( p->pVarTypes[Var] == 0 ) // var of B
+                Intb_ManAigAnd( p, Intb_ManAigRead(p, pFinal), Intb_ManAigRead(p, pReason) );
+            else
+            {
+                int VarAB = Intb_ManGetGlobalVar(p, Var);
+                // check that the var is present in the reason
+                for ( v = 0; v < (int)pReason->nLits; v++ )
+                    if ( lit_var(pReason->pLits[v]) == Var )
+                        break;
+                assert( v < (int)pReason->nLits );
+                if ( lit_sign(pReason->pLits[v]) ) // negative polarity
+                    Intb_ManAigMux0( p, Intb_ManAigRead(p, pFinal), Intb_ManAigRead(p, pReason), VarAB );
+                else
+                    Intb_ManAigMux1( p, Intb_ManAigRead(p, pFinal), Intb_ManAigRead(p, pReason), VarAB );
+            }
+        }
+ 
+        // resolve the temporary resolvent with the reason clause
+        if ( p->fProofVerif )
+        {
+            int v1, v2; 
+            if ( fPrint )
+                Intb_ManPrintResolvent( p->pResLits, p->nResLits );
+            // check that the var is present in the resolvent
+            for ( v1 = 0; v1 < p->nResLits; v1++ )
+                if ( lit_var(p->pResLits[v1]) == Var )
+                    break;
+            if ( v1 == p->nResLits )
+                printf( "Recording clause %d: Cannot find variable %d in the temporary resolvent.\n", pFinal->Id, Var );
+            if ( p->pResLits[v1] != lit_neg(pReason->pLits[0]) )
+                printf( "Recording clause %d: The resolved variable %d is in the wrong polarity.\n", pFinal->Id, Var );
+            // remove this variable from the resolvent
+            assert( lit_var(p->pResLits[v1]) == Var );
+            p->nResLits--;
+            for ( ; v1 < p->nResLits; v1++ )
+                p->pResLits[v1] = p->pResLits[v1+1];
+            // add variables of the reason clause
+            for ( v2 = 1; v2 < (int)pReason->nLits; v2++ )
+            {
+                for ( v1 = 0; v1 < p->nResLits; v1++ )
+                    if ( lit_var(p->pResLits[v1]) == lit_var(pReason->pLits[v2]) )
+                        break;
+                // if it is a new variable, add it to the resolvent
+                if ( v1 == p->nResLits ) 
+                {
+                    if ( p->nResLits == p->nResLitsAlloc )
+                        printf( "Recording clause %d: Ran out of space for intermediate resolvent.\n", pFinal->Id );
+                    p->pResLits[ p->nResLits++ ] = pReason->pLits[v2];
+                    continue;
+                }
+                // if the variable is the same, the literal should be the same too
+                if ( p->pResLits[v1] == pReason->pLits[v2] )
+                    continue;
+                // the literal is different
+                printf( "Recording clause %d: Trying to resolve the clause with more than one opposite literal.\n", pFinal->Id );
+            }
+        }
+//        Vec_PtrPush( pFinal->pAntis, pReason );
+    }
+
+    // unmark all seen variables
+//    for ( i = p->nTrailSize - 1; i >= 0; i-- )
+//        p->pSeens[lit_var(p->pTrail[i])] = 0;
+    // check that the literals are unmarked
+//    for ( i = p->nTrailSize - 1; i >= 0; i-- )
+//        assert( p->pSeens[lit_var(p->pTrail[i])] == 0 );
+
+    // use the resulting clause to check the correctness of resolution
+    if ( p->fProofVerif )
+    {
+        int v1, v2; 
+        if ( fPrint )
+            Intb_ManPrintResolvent( p->pResLits, p->nResLits );
+        for ( v1 = 0; v1 < p->nResLits; v1++ )
+        {
+            for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ )
+                if ( pFinal->pLits[v2] == p->pResLits[v1] )
+                    break;
+            if ( v2 < (int)pFinal->nLits )
+                continue;
+            break;
+        }
+        if ( v1 < p->nResLits )
+        {
+            printf( "Recording clause %d: The final resolvent is wrong.\n", pFinal->Id );
+            Intb_ManPrintClause( p, pConflict );
+            Intb_ManPrintResolvent( p->pResLits, p->nResLits );
+            Intb_ManPrintClause( p, pFinal );
+        }
+
+        // if there are literals in the clause that are not in the resolvent
+        // it means that the derived resolvent is stronger than the clause
+        // we can replace the clause with the resolvent by removing these literals
+        if ( p->nResLits != (int)pFinal->nLits )
+        {
+            for ( v1 = 0; v1 < (int)pFinal->nLits; v1++ )
+            {
+                for ( v2 = 0; v2 < p->nResLits; v2++ )
+                    if ( pFinal->pLits[v1] == p->pResLits[v2] )
+                        break;
+                if ( v2 < p->nResLits )
+                    continue;
+                // remove literal v1 from the final clause
+                pFinal->nLits--;
+                for ( v2 = v1; v2 < (int)pFinal->nLits; v2++ )
+                    pFinal->pLits[v2] = pFinal->pLits[v2+1];
+                v1--;
+            }
+            assert( p->nResLits == (int)pFinal->nLits );
+        }
+    }
+p->timeTrace += Abc_Clock() - clk;
+
+    // return the proof pointer 
+    if ( p->pCnf->nClausesA )
+    {
+//        Intb_ManPrintInterOne( p, pFinal );
+    }
+    Intb_ManProofSet( p, pFinal, p->Counter );
+    // make sure the same proof ID is not asssigned to two consecutive clauses
+    assert( p->pProofNums[pFinal->Id-1] != p->Counter );
+//    if ( p->pProofNums[pFinal->Id] == p->pProofNums[pFinal->Id-1] )
+//        p->pProofNums[pFinal->Id] = p->pProofNums[pConflict->Id];
+    return p->Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records the proof for one clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Intb_ManProofRecordOne( Intb_Man_t * p, Sto_Cls_t * pClause )
+{
+    Sto_Cls_t * pConflict;
+    int i;
+
+    // empty clause never ends up there
+    assert( pClause->nLits > 0 );
+    if ( pClause->nLits == 0 )
+        printf( "Error: Empty clause is attempted.\n" );
+
+    assert( !pClause->fRoot );
+    assert( p->nTrailSize == p->nRootSize );
+
+    // if any of the clause literals are already assumed
+    // it means that the clause is redundant and can be skipped
+    for ( i = 0; i < (int)pClause->nLits; i++ )
+        if ( p->pAssigns[lit_var(pClause->pLits[i])] == pClause->pLits[i] )
+            return 1;
+
+    // add assumptions to the trail
+    for ( i = 0; i < (int)pClause->nLits; i++ )
+        if ( !Intb_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) )
+        {
+            assert( 0 ); // impossible
+            return 0;
+        }
+
+    // propagate the assumptions
+    pConflict = Intb_ManPropagate( p, p->nRootSize );
+    if ( pConflict == NULL )
+    {
+        assert( 0 ); // cannot prove
+        return 0;
+    } 
+
+    // skip the clause if it is weaker or the same as the conflict clause
+    if ( pClause->nLits >= pConflict->nLits )
+    {
+        // check if every literal of conflict clause can be found in the given clause
+        int j;
+        for ( i = 0; i < (int)pConflict->nLits; i++ )
+        {
+            for ( j = 0; j < (int)pClause->nLits; j++ )
+                if ( pConflict->pLits[i] == pClause->pLits[j] )
+                    break;
+            if ( j == (int)pClause->nLits ) // literal pConflict->pLits[i] is not found
+                break;
+        }
+        if ( i == (int)pConflict->nLits ) // all lits are found
+        {
+            // undo to the root level
+            Intb_ManCancelUntil( p, p->nRootSize );
+            return 1;
+        }
+    }
+
+    // construct the proof
+    Intb_ManProofTraceOne( p, pConflict, pClause );
+
+    // undo to the root level
+    Intb_ManCancelUntil( p, p->nRootSize );
+
+    // add large clauses to the watched lists
+    if ( pClause->nLits > 1 )
+    {
+        Intb_ManWatchClause( p, pClause, pClause->pLits[0] );
+        Intb_ManWatchClause( p, pClause, pClause->pLits[1] );
+        return 1;
+    }
+    assert( pClause->nLits == 1 );
+
+    // if the clause proved is unit, add it and propagate
+    if ( !Intb_ManEnqueue( p, pClause->pLits[0], pClause ) )
+    {
+        assert( 0 ); // impossible
+        return 0;
+    }
+
+    // propagate the assumption
+    pConflict = Intb_ManPropagate( p, p->nRootSize );
+    if ( pConflict )
+    {
+        // construct the proof
+        Intb_ManProofTraceOne( p, pConflict, p->pCnf->pEmpty );
+//        if ( p->fVerbose )
+//            printf( "Found last conflict after adding unit clause number %d!\n", pClause->Id );
+        return 0;
+    }
+
+    // update the root level
+    p->nRootSize = p->nTrailSize;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagate the root clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Intb_ManProcessRoots( Intb_Man_t * p )
+{
+    Sto_Cls_t * pClause;
+    int Counter;
+
+    // make sure the root clauses are preceeding the learnt clauses
+    Counter = 0;
+    Sto_ManForEachClause( p->pCnf, pClause )
+    {
+        assert( (int)pClause->fA    == (Counter < (int)p->pCnf->nClausesA) );
+        assert( (int)pClause->fRoot == (Counter < (int)p->pCnf->nRoots)    );
+        Counter++;
+    }
+    assert( p->pCnf->nClauses == Counter );
+
+    // make sure the last clause if empty
+    assert( p->pCnf->pTail->nLits == 0 );
+
+    // go through the root unit clauses
+    p->nTrailSize = 0;
+    Sto_ManForEachClauseRoot( p->pCnf, pClause )
+    {
+        // create watcher lists for the root clauses
+        if ( pClause->nLits > 1 )
+        {
+            Intb_ManWatchClause( p, pClause, pClause->pLits[0] );
+            Intb_ManWatchClause( p, pClause, pClause->pLits[1] );
+        }
+        // empty clause and large clauses
+        if ( pClause->nLits != 1 )
+            continue;
+        // unit clause
+        assert( lit_check(pClause->pLits[0], p->pCnf->nVars) );
+        if ( !Intb_ManEnqueue( p, pClause->pLits[0], pClause ) )
+        {
+            // detected root level conflict
+//            printf( "Error in Intb_ManProcessRoots(): Detected a root-level conflict too early!\n" );
+//            assert( 0 );
+            // detected root level conflict
+            Intb_ManProofTraceOne( p, pClause, p->pCnf->pEmpty );
+            if ( p->fVerbose )
+                printf( "Found root level conflict!\n" );
+            return 0;
+        }
+    }
+
+    // propagate the root unit clauses
+    pClause = Intb_ManPropagate( p, 0 );
+    if ( pClause )
+    {
+        // detected root level conflict
+        Intb_ManProofTraceOne( p, pClause, p->pCnf->pEmpty );
+        if ( p->fVerbose )
+            printf( "Found root level conflict!\n" );
+        return 0;
+    }
+
+    // set the root level
+    p->nRootSize = p->nTrailSize;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records the proof.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Intb_ManPrepareInter( Intb_Man_t * p )
+{
+    Sto_Cls_t * pClause;
+    int Var, VarAB, v;
+
+    // set interpolants for root clauses
+    Sto_ManForEachClauseRoot( p->pCnf, pClause )
+    {
+        if ( !pClause->fA ) // clause of B
+        {
+            Intb_ManAigFill( p, Intb_ManAigRead(p, pClause) );
+//            Intb_ManPrintInterOne( p, pClause );
+            continue;
+        }
+        // clause of A
+        Intb_ManAigClear( p, Intb_ManAigRead(p, pClause) );
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+        {
+            Var = lit_var(pClause->pLits[v]);
+            if ( p->pVarTypes[Var] < 0 ) // global var
+            {
+                VarAB = -p->pVarTypes[Var]-1;
+                assert( VarAB >= 0 && VarAB < Vec_IntSize(p->vVarsAB) );
+                if ( lit_sign(pClause->pLits[v]) ) // negative var
+                    Intb_ManAigOrNotVar( p, Intb_ManAigRead(p, pClause), VarAB );
+                else
+                    Intb_ManAigOrVar( p, Intb_ManAigRead(p, pClause), VarAB );
+            }
+        }
+//        Intb_ManPrintInterOne( p, pClause );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes interpolant for the given CNF.]
+
+  Description [Takes the interpolation manager, the CNF deriving by the SAT
+  solver, which includes ClausesA, ClausesB, and learned clauses. Additional
+  arguments are the vector of variables common to AB and the verbosiness flag.
+  Returns the AIG manager with a single output, containing the interpolant.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Intb_ManInterpolate( Intb_Man_t * p, Sto_Man_t * pCnf, void * vVarsAB, int fVerbose )
+{
+    Aig_Man_t * pRes;
+    Aig_Obj_t * pObj;
+    Sto_Cls_t * pClause;
+    int RetValue = 1;
+    abctime clkTotal = Abc_Clock();
+
+    // check that the CNF makes sense
+    assert( pCnf->nVars > 0 && pCnf->nClauses > 0 );
+    p->pCnf = pCnf;
+    p->fVerbose = fVerbose;
+    p->vVarsAB = (Vec_Int_t *)vVarsAB;
+    p->pAig = pRes = Aig_ManStart( 10000 );
+    Aig_IthVar( p->pAig, Vec_IntSize(p->vVarsAB) - 1 );
+
+    // adjust the manager
+    Intb_ManResize( p );
+
+    // prepare the interpolant computation
+    Intb_ManPrepareInter( p );
+
+    // construct proof for each clause
+    // start the proof
+    if ( p->fProofWrite )
+    {
+        p->pFile = fopen( "proof.cnf_", "w" );
+        p->Counter = 0;
+    }
+
+    // write the root clauses
+    Sto_ManForEachClauseRoot( p->pCnf, pClause )
+        Intb_ManProofWriteOne( p, pClause );
+
+    // propagate root level assignments
+    if ( Intb_ManProcessRoots( p ) )
+    {
+        // if there is no conflict, consider learned clauses
+        Sto_ManForEachClause( p->pCnf, pClause )
+        {
+            if ( pClause->fRoot )
+                continue;
+            if ( !Intb_ManProofRecordOne( p, pClause ) )
+            {
+                RetValue = 0;
+                break;
+            }
+        }
+    }
+
+    // stop the proof
+    if ( p->fProofWrite )
+    { 
+        fclose( p->pFile );
+//        Sat_ProofChecker( "proof.cnf_" );
+        p->pFile = NULL;    
+    }
+
+    if ( fVerbose )
+    {
+//        ABC_PRT( "Interpo", Abc_Clock() - clkTotal );
+    printf( "Vars = %d. Roots = %d. Learned = %d. Resol steps = %d.  Ave = %.2f.  Mem = %.2f MB\n", 
+        p->pCnf->nVars, p->pCnf->nRoots, p->pCnf->nClauses-p->pCnf->nRoots, p->Counter,  
+        1.0*(p->Counter-p->pCnf->nRoots)/(p->pCnf->nClauses-p->pCnf->nRoots), 
+        1.0*Sto_ManMemoryReport(p->pCnf)/(1<<20) );
+p->timeTotal += Abc_Clock() - clkTotal;
+    }
+
+    pObj = *Intb_ManAigRead( p, p->pCnf->pTail );
+    Aig_ObjCreateCo( pRes, pObj );
+    Aig_ManCleanup( pRes );
+
+    p->pAig = NULL;
+    return pRes;
+    
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Aig_Man_t * Intb_ManDeriveClauses( Intb_Man_t * pMan, Sto_Man_t * pCnf, int fClausesA )
+{
+    Aig_Man_t * p;
+    Aig_Obj_t * pMiter, * pSum, * pLit;
+    Sto_Cls_t * pClause;
+    int Var, VarAB, v;
+    p = Aig_ManStart( 10000 );
+    pMiter = Aig_ManConst1(p);
+    Sto_ManForEachClauseRoot( pCnf, pClause )
+    {
+        if ( fClausesA ^ pClause->fA ) // clause of B
+            continue;
+        // clause of A
+        pSum = Aig_ManConst0(p);
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+        {
+            Var = lit_var(pClause->pLits[v]);
+            if ( pMan->pVarTypes[Var] < 0 ) // global var
+            {
+                VarAB = -pMan->pVarTypes[Var]-1;
+                assert( VarAB >= 0 && VarAB < Vec_IntSize(pMan->vVarsAB) );
+                pLit = Aig_NotCond( Aig_IthVar(p, VarAB), lit_sign(pClause->pLits[v]) );
+            }
+            else
+                pLit = Aig_NotCond( Aig_IthVar(p, Vec_IntSize(pMan->vVarsAB)+1+Var), lit_sign(pClause->pLits[v]) );
+            pSum = Aig_Or( p, pSum, pLit );
+        }
+        pMiter = Aig_And( p, pMiter, pSum );
+    }
+    Aig_ObjCreateCo( p, pMiter );
+    return p;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bsat/satInterP.c b/abc-build/src/sat/bsat/satInterP.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satInterP.c
@@ -0,0 +1,1096 @@
+/**CFile****************************************************************
+
+  FileName    [satInter.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT sat_solver.]
+
+  Synopsis    [Interpolation package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: satInter.c,v 1.4 2005/09/16 22:55:03 casem Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "satStore.h"
+#include "misc/vec/vec.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// variable assignments 
+static const lit    LIT_UNDEF = 0xffffffff;
+
+// interpolation manager
+struct Intp_Man_t_
+{
+    // clauses of the problems
+    Sto_Man_t *     pCnf;         // the set of CNF clauses for A and B
+    // various parameters
+    int             fVerbose;     // verbosiness flag
+    int             fProofVerif;  // verifies the proof
+    int             fProofWrite;  // writes the proof file
+    int             nVarsAlloc;   // the allocated size of var arrays
+    int             nClosAlloc;   // the allocated size of clause arrays
+    // internal BCP
+    int             nRootSize;    // the number of root level assignments
+    int             nTrailSize;   // the number of assignments made 
+    lit *           pTrail;       // chronological order of assignments (size nVars)
+    lit *           pAssigns;     // assignments by variable (size nVars) 
+    char *          pSeens;       // temporary mark (size nVars)
+    Sto_Cls_t **    pReasons;     // reasons for each assignment (size nVars)          
+    Sto_Cls_t **    pWatches;     // watched clauses for each literal (size 2*nVars)          
+    // proof data
+//    Vec_Int_t *     vAnties;      // anticedents for all clauses
+//    Vec_Int_t *     vBreaks;      // beginnings of anticedents for each clause
+    Vec_Ptr_t *     vAntClas;     // anticedant clauses
+    int             nAntStart;    // starting antecedant clause
+    // proof recording
+    int             Counter;      // counter of resolved clauses
+    int *           pProofNums;   // the proof numbers for each clause (size nClauses)
+    FILE *          pFile;        // the file for proof recording
+    // internal verification
+    lit *           pResLits;     // the literals of the resolvent   
+    int             nResLits;     // the number of literals of the resolvent
+    int             nResLitsAlloc;// the number of literals of the resolvent
+    // runtime stats
+    abctime         timeBcp;      // the runtime for BCP
+    abctime         timeTrace;    // the runtime of trace construction
+    abctime         timeTotal;    // the total runtime of interpolation
+};
+
+// reading/writing the proof for a clause
+static inline int          Intp_ManProofGet( Intp_Man_t * p, Sto_Cls_t * pCls )                  { return p->pProofNums[pCls->Id];           }
+static inline void         Intp_ManProofSet( Intp_Man_t * p, Sto_Cls_t * pCls, int n )           { p->pProofNums[pCls->Id] = n;              }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocate proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Intp_Man_t * Intp_ManAlloc()
+{
+    Intp_Man_t * p;
+    // allocate the manager
+    p = (Intp_Man_t *)ABC_ALLOC( char, sizeof(Intp_Man_t) );
+    memset( p, 0, sizeof(Intp_Man_t) );
+    // verification
+    p->nResLitsAlloc = (1<<16);
+    p->pResLits = ABC_ALLOC( lit, p->nResLitsAlloc );
+    // proof recording
+//    p->vAnties = Vec_IntAlloc( 1000 );
+//    p->vBreaks = Vec_IntAlloc( 1000 );
+    p->vAntClas = Vec_PtrAlloc( 1000 );
+    p->nAntStart = 0;
+    // parameters
+    p->fProofWrite = 0;
+    p->fProofVerif = 1;
+    return p;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resize proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Intp_ManResize( Intp_Man_t * p )
+{
+    // check if resizing is needed
+    if ( p->nVarsAlloc < p->pCnf->nVars )
+    {
+        // find the new size
+        if ( p->nVarsAlloc == 0 )
+            p->nVarsAlloc = 1;
+        while ( p->nVarsAlloc < p->pCnf->nVars ) 
+            p->nVarsAlloc *= 2;
+        // resize the arrays
+        p->pTrail    = ABC_REALLOC(lit,         p->pTrail,    p->nVarsAlloc );
+        p->pAssigns  = ABC_REALLOC(lit,         p->pAssigns,  p->nVarsAlloc );
+        p->pSeens    = ABC_REALLOC(char,        p->pSeens,    p->nVarsAlloc );
+//        p->pVarTypes = ABC_REALLOC(int,         p->pVarTypes, p->nVarsAlloc );
+        p->pReasons  = ABC_REALLOC(Sto_Cls_t *, p->pReasons,  p->nVarsAlloc );
+        p->pWatches  = ABC_REALLOC(Sto_Cls_t *, p->pWatches,  p->nVarsAlloc*2 );
+    }
+
+    // clean the free space
+    memset( p->pAssigns , 0xff, sizeof(lit) * p->pCnf->nVars );
+    memset( p->pSeens   , 0,    sizeof(char) * p->pCnf->nVars );
+//    memset( p->pVarTypes, 0,    sizeof(int) * p->pCnf->nVars );
+    memset( p->pReasons , 0,    sizeof(Sto_Cls_t *) * p->pCnf->nVars );
+    memset( p->pWatches , 0,    sizeof(Sto_Cls_t *) * p->pCnf->nVars*2 );
+
+    // check if resizing of clauses is needed
+    if ( p->nClosAlloc < p->pCnf->nClauses )
+    {
+        // find the new size
+        if ( p->nClosAlloc == 0 )
+            p->nClosAlloc = 1;
+        while ( p->nClosAlloc < p->pCnf->nClauses ) 
+            p->nClosAlloc *= 2;
+        // resize the arrays
+        p->pProofNums = ABC_REALLOC( int, p->pProofNums,  p->nClosAlloc );
+    }
+    memset( p->pProofNums, 0, sizeof(int) * p->pCnf->nClauses );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocate proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Intp_ManFree( Intp_Man_t * p )
+{
+/*
+    printf( "Runtime stats:\n" );
+ABC_PRT( "BCP     ", p->timeBcp   );
+ABC_PRT( "Trace   ", p->timeTrace );
+ABC_PRT( "TOTAL   ", p->timeTotal );
+*/
+//    Vec_IntFree( p->vAnties );
+//    Vec_IntFree( p->vBreaks );
+    Vec_VecFree( (Vec_Vec_t *)p->vAntClas );
+//    ABC_FREE( p->pInters );
+    ABC_FREE( p->pProofNums );
+    ABC_FREE( p->pTrail );
+    ABC_FREE( p->pAssigns );
+    ABC_FREE( p->pSeens );
+//    ABC_FREE( p->pVarTypes );
+    ABC_FREE( p->pReasons );
+    ABC_FREE( p->pWatches );
+    ABC_FREE( p->pResLits );
+    ABC_FREE( p );
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Intp_ManPrintClause( Intp_Man_t * p, Sto_Cls_t * pClause )
+{
+    int i;
+    printf( "Clause ID = %d. Proof = %d. {", pClause->Id, Intp_ManProofGet(p, pClause) );
+    for ( i = 0; i < (int)pClause->nLits; i++ )
+        printf( " %d", pClause->pLits[i] );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the resolvent.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Intp_ManPrintResolvent( lit * pResLits, int nResLits )
+{
+    int i;
+    printf( "Resolvent: {" );
+    for ( i = 0; i < nResLits; i++ )
+        printf( " %d", pResLits[i] );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the interpolant for one clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Intp_ManPrintInterOne( Intp_Man_t * p, Sto_Cls_t * pClause )
+{
+    printf( "Clause %2d :  ", pClause->Id );
+//    Extra_PrintBinary___( stdout, Intp_ManAigRead(p, pClause), (1 << p->nVarsAB) );
+    printf( "\n" );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one clause to the watcher list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Intp_ManWatchClause( Intp_Man_t * p, Sto_Cls_t * pClause, lit Lit )
+{
+    assert( lit_check(Lit, p->pCnf->nVars) );
+    if ( pClause->pLits[0] == Lit )
+        pClause->pNext0 = p->pWatches[lit_neg(Lit)];  
+    else
+    {
+        assert( pClause->pLits[1] == Lit );
+        pClause->pNext1 = p->pWatches[lit_neg(Lit)];  
+    }
+    p->pWatches[lit_neg(Lit)] = pClause;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Records implication.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Intp_ManEnqueue( Intp_Man_t * p, lit Lit, Sto_Cls_t * pReason )
+{
+    int Var = lit_var(Lit);
+    if ( p->pAssigns[Var] != LIT_UNDEF )
+        return p->pAssigns[Var] == Lit;
+    p->pAssigns[Var] = Lit;
+    p->pReasons[Var] = pReason;
+    p->pTrail[p->nTrailSize++] = Lit;
+//printf( "assigning var %d value %d\n", Var, !lit_sign(Lit) );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records implication.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Intp_ManCancelUntil( Intp_Man_t * p, int Level )
+{
+    lit Lit;
+    int i, Var;
+    for ( i = p->nTrailSize - 1; i >= Level; i-- )
+    {
+        Lit = p->pTrail[i];
+        Var = lit_var( Lit );
+        p->pReasons[Var] = NULL;
+        p->pAssigns[Var] = LIT_UNDEF;
+//printf( "cancelling var %d\n", Var );
+    }
+    p->nTrailSize = Level;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagate one assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Sto_Cls_t * Intp_ManPropagateOne( Intp_Man_t * p, lit Lit )
+{
+    Sto_Cls_t ** ppPrev, * pCur, * pTemp;
+    lit LitF = lit_neg(Lit);
+    int i;
+    // iterate through the literals
+    ppPrev = p->pWatches + Lit;
+    for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev )
+    {
+        // make sure the false literal is in the second literal of the clause
+        if ( pCur->pLits[0] == LitF )
+        {
+            pCur->pLits[0] = pCur->pLits[1];
+            pCur->pLits[1] = LitF;
+            pTemp = pCur->pNext0;
+            pCur->pNext0 = pCur->pNext1;
+            pCur->pNext1 = pTemp;
+        }
+        assert( pCur->pLits[1] == LitF );
+
+        // if the first literal is true, the clause is satisfied
+        if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] )
+        {
+            ppPrev = &pCur->pNext1;
+            continue;
+        }
+
+        // look for a new literal to watch
+        for ( i = 2; i < (int)pCur->nLits; i++ )
+        {
+            // skip the case when the literal is false
+            if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] )
+                continue;
+            // the literal is either true or unassigned - watch it
+            pCur->pLits[1] = pCur->pLits[i];
+            pCur->pLits[i] = LitF;
+            // remove this clause from the watch list of Lit
+            *ppPrev = pCur->pNext1;
+            // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1])
+            Intp_ManWatchClause( p, pCur, pCur->pLits[1] );
+            break;
+        }
+        if ( i < (int)pCur->nLits ) // found new watch
+            continue;
+
+        // clause is unit - enqueue new implication
+        if ( Intp_ManEnqueue(p, pCur->pLits[0], pCur) )
+        {
+            ppPrev = &pCur->pNext1;
+            continue;
+        }
+
+        // conflict detected - return the conflict clause
+        return pCur;
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagate the current assignments.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Sto_Cls_t * Intp_ManPropagate( Intp_Man_t * p, int Start )
+{
+    Sto_Cls_t * pClause;
+    int i;
+    abctime clk = Abc_Clock();
+    for ( i = Start; i < p->nTrailSize; i++ )
+    {
+        pClause = Intp_ManPropagateOne( p, p->pTrail[i] );
+        if ( pClause )
+        {
+p->timeBcp += Abc_Clock() - clk;
+            return pClause;
+        }
+    }
+p->timeBcp += Abc_Clock() - clk;
+    return NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes one root clause into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Intp_ManProofWriteOne( Intp_Man_t * p, Sto_Cls_t * pClause )
+{
+    Intp_ManProofSet( p, pClause, ++p->Counter );
+
+    if ( p->fProofWrite )
+    {
+        int v;
+        fprintf( p->pFile, "%d", Intp_ManProofGet(p, pClause) );
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+            fprintf( p->pFile, " %d", lit_print(pClause->pLits[v]) );
+        fprintf( p->pFile, " 0 0\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Traces the proof for one clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Intp_ManProofTraceOne( Intp_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pFinal )
+{
+    Sto_Cls_t * pReason;
+    int i, v, Var, PrevId;
+    int fPrint = 0;
+    abctime clk = Abc_Clock();
+
+    // collect resolvent literals
+    if ( p->fProofVerif )
+    {
+        assert( (int)pConflict->nLits <= p->nResLitsAlloc );
+        memcpy( p->pResLits, pConflict->pLits, sizeof(lit) * pConflict->nLits );
+        p->nResLits = pConflict->nLits;
+    }
+
+    // mark all the variables in the conflict as seen
+    for ( v = 0; v < (int)pConflict->nLits; v++ )
+        p->pSeens[lit_var(pConflict->pLits[v])] = 1;
+
+    // start the anticedents
+//    pFinal->pAntis = Vec_PtrAlloc( 32 );
+//    Vec_PtrPush( pFinal->pAntis, pConflict );
+
+//    assert( pFinal->Id == Vec_IntSize(p->vBreaks) );
+//    Vec_IntPush( p->vBreaks, Vec_IntSize(p->vAnties) );
+//    Vec_IntPush( p->vAnties, pConflict->Id );
+    {
+        Vec_Int_t * vAnts = Vec_IntAlloc( 16 );
+        assert( Vec_PtrSize(p->vAntClas) == pFinal->Id - p->nAntStart );
+        Vec_IntPush( vAnts, pConflict->Id );
+        Vec_PtrPush( p->vAntClas, vAnts );
+    }
+
+//    if ( p->pCnf->nClausesA )
+//        Intp_ManAigCopy( p, Intp_ManAigRead(p, pFinal), Intp_ManAigRead(p, pConflict) );
+
+    // follow the trail backwards
+    PrevId = Intp_ManProofGet(p, pConflict);
+    for ( i = p->nTrailSize - 1; i >= 0; i-- )
+    {
+        // skip literals that are not involved
+        Var = lit_var(p->pTrail[i]);
+        if ( !p->pSeens[Var] )
+            continue;
+        p->pSeens[Var] = 0;
+
+        // skip literals of the resulting clause
+        pReason = p->pReasons[Var];
+        if ( pReason == NULL )
+            continue;
+        assert( p->pTrail[i] == pReason->pLits[0] );
+
+        // add the variables to seen
+        for ( v = 1; v < (int)pReason->nLits; v++ )
+            p->pSeens[lit_var(pReason->pLits[v])] = 1;
+
+
+        // record the reason clause
+        assert( Intp_ManProofGet(p, pReason) > 0 );
+        p->Counter++;
+        if ( p->fProofWrite )
+            fprintf( p->pFile, "%d * %d %d 0\n", p->Counter, PrevId, Intp_ManProofGet(p, pReason) );
+        PrevId = p->Counter;
+
+//        if ( p->pCnf->nClausesA )
+//       {
+//            if ( p->pVarTypes[Var] == 1 ) // var of A
+//                Intp_ManAigOr( p, Intp_ManAigRead(p, pFinal), Intp_ManAigRead(p, pReason) );
+//            else
+//                Intp_ManAigAnd( p, Intp_ManAigRead(p, pFinal), Intp_ManAigRead(p, pReason) );
+//        }
+ 
+        // resolve the temporary resolvent with the reason clause
+        if ( p->fProofVerif )
+        {
+            int v1, v2; 
+            if ( fPrint )
+                Intp_ManPrintResolvent( p->pResLits, p->nResLits );
+            // check that the var is present in the resolvent
+            for ( v1 = 0; v1 < p->nResLits; v1++ )
+                if ( lit_var(p->pResLits[v1]) == Var )
+                    break;
+            if ( v1 == p->nResLits )
+                printf( "Recording clause %d: Cannot find variable %d in the temporary resolvent.\n", pFinal->Id, Var );
+            if ( p->pResLits[v1] != lit_neg(pReason->pLits[0]) )
+                printf( "Recording clause %d: The resolved variable %d is in the wrong polarity.\n", pFinal->Id, Var );
+            // remove this variable from the resolvent
+            assert( lit_var(p->pResLits[v1]) == Var );
+            p->nResLits--;
+            for ( ; v1 < p->nResLits; v1++ )
+                p->pResLits[v1] = p->pResLits[v1+1];
+            // add variables of the reason clause
+            for ( v2 = 1; v2 < (int)pReason->nLits; v2++ )
+            {
+                for ( v1 = 0; v1 < p->nResLits; v1++ )
+                    if ( lit_var(p->pResLits[v1]) == lit_var(pReason->pLits[v2]) )
+                        break;
+                // if it is a new variable, add it to the resolvent
+                if ( v1 == p->nResLits ) 
+                {
+                    if ( p->nResLits == p->nResLitsAlloc )
+                        printf( "Recording clause %d: Ran out of space for intermediate resolvent.\n", pFinal->Id );
+                    p->pResLits[ p->nResLits++ ] = pReason->pLits[v2];
+                    continue;
+                }
+                // if the variable is the same, the literal should be the same too
+                if ( p->pResLits[v1] == pReason->pLits[v2] )
+                    continue;
+                // the literal is different
+                printf( "Recording clause %d: Trying to resolve the clause with more than one opposite literal.\n", pFinal->Id );
+            }
+        }
+
+//        Vec_PtrPush( pFinal->pAntis, pReason );
+//        Vec_IntPush( p->vAnties, pReason->Id );
+        Vec_IntPush( (Vec_Int_t *)Vec_PtrEntryLast(p->vAntClas), pReason->Id );
+    }
+
+    // unmark all seen variables
+//    for ( i = p->nTrailSize - 1; i >= 0; i-- )
+//        p->pSeens[lit_var(p->pTrail[i])] = 0;
+    // check that the literals are unmarked
+//    for ( i = p->nTrailSize - 1; i >= 0; i-- )
+//        assert( p->pSeens[lit_var(p->pTrail[i])] == 0 );
+
+    // use the resulting clause to check the correctness of resolution
+    if ( p->fProofVerif )
+    {
+        int v1, v2; 
+        if ( fPrint )
+            Intp_ManPrintResolvent( p->pResLits, p->nResLits );
+        for ( v1 = 0; v1 < p->nResLits; v1++ )
+        {
+            for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ )
+                if ( pFinal->pLits[v2] == p->pResLits[v1] )
+                    break;
+            if ( v2 < (int)pFinal->nLits )
+                continue;
+            break;
+        }
+        if ( v1 < p->nResLits )
+        {
+            printf( "Recording clause %d: The final resolvent is wrong.\n", pFinal->Id );
+            Intp_ManPrintClause( p, pConflict );
+            Intp_ManPrintResolvent( p->pResLits, p->nResLits );
+            Intp_ManPrintClause( p, pFinal );
+        }
+
+        // if there are literals in the clause that are not in the resolvent
+        // it means that the derived resolvent is stronger than the clause
+        // we can replace the clause with the resolvent by removing these literals
+        if ( p->nResLits != (int)pFinal->nLits )
+        {
+            for ( v1 = 0; v1 < (int)pFinal->nLits; v1++ )
+            {
+                for ( v2 = 0; v2 < p->nResLits; v2++ )
+                    if ( pFinal->pLits[v1] == p->pResLits[v2] )
+                        break;
+                if ( v2 < p->nResLits )
+                    continue;
+                // remove literal v1 from the final clause
+                pFinal->nLits--;
+                for ( v2 = v1; v2 < (int)pFinal->nLits; v2++ )
+                    pFinal->pLits[v2] = pFinal->pLits[v2+1];
+                v1--;
+            }
+            assert( p->nResLits == (int)pFinal->nLits );
+        }
+    }
+p->timeTrace += Abc_Clock() - clk;
+
+    // return the proof pointer 
+//    if ( p->pCnf->nClausesA )
+//    {
+//        Intp_ManPrintInterOne( p, pFinal );
+//    }
+    Intp_ManProofSet( p, pFinal, p->Counter );
+    // make sure the same proof ID is not asssigned to two consecutive clauses
+    assert( p->pProofNums[pFinal->Id-1] != p->Counter );
+//    if ( p->pProofNums[pFinal->Id] == p->pProofNums[pFinal->Id-1] )
+//        p->pProofNums[pFinal->Id] = p->pProofNums[pConflict->Id];
+    return p->Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records the proof for one clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Intp_ManProofRecordOne( Intp_Man_t * p, Sto_Cls_t * pClause )
+{
+    Sto_Cls_t * pConflict;
+    int i;
+
+    // empty clause never ends up there
+    assert( pClause->nLits > 0 );
+    if ( pClause->nLits == 0 )
+        printf( "Error: Empty clause is attempted.\n" );
+
+    assert( !pClause->fRoot );
+    assert( p->nTrailSize == p->nRootSize );
+
+    // if any of the clause literals are already assumed
+    // it means that the clause is redundant and can be skipped
+    for ( i = 0; i < (int)pClause->nLits; i++ )
+        if ( p->pAssigns[lit_var(pClause->pLits[i])] == pClause->pLits[i] )
+        {
+//            Vec_IntPush( p->vBreaks, Vec_IntSize(p->vAnties) );
+            Vec_PtrPush( p->vAntClas, Vec_IntAlloc(0) );
+            return 1;
+        }
+
+    // add assumptions to the trail
+    for ( i = 0; i < (int)pClause->nLits; i++ )
+        if ( !Intp_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) )
+        {
+            assert( 0 ); // impossible
+            return 0;
+        }
+
+    // propagate the assumptions
+    pConflict = Intp_ManPropagate( p, p->nRootSize );
+    if ( pConflict == NULL )
+    {
+        assert( 0 ); // cannot prove
+        return 0;
+    }
+
+    // skip the clause if it is weaker or the same as the conflict clause
+    if ( pClause->nLits >= pConflict->nLits )
+    {
+        // check if every literal of conflict clause can be found in the given clause
+        int j;
+        for ( i = 0; i < (int)pConflict->nLits; i++ )
+        {
+            for ( j = 0; j < (int)pClause->nLits; j++ )
+                if ( pConflict->pLits[i] == pClause->pLits[j] )
+                    break;
+            if ( j == (int)pClause->nLits ) // literal pConflict->pLits[i] is not found
+                break;
+        }
+        if ( i == (int)pConflict->nLits ) // all lits are found
+        {
+            // undo to the root level
+            Intp_ManCancelUntil( p, p->nRootSize );
+//            Vec_IntPush( p->vBreaks, Vec_IntSize(p->vAnties) );
+            Vec_PtrPush( p->vAntClas, Vec_IntAlloc(0) );
+            return 1;
+        }
+    }
+
+    // construct the proof
+    Intp_ManProofTraceOne( p, pConflict, pClause );
+
+    // undo to the root level
+    Intp_ManCancelUntil( p, p->nRootSize );
+
+    // add large clauses to the watched lists
+    if ( pClause->nLits > 1 )
+    {
+        Intp_ManWatchClause( p, pClause, pClause->pLits[0] );
+        Intp_ManWatchClause( p, pClause, pClause->pLits[1] );
+        return 1;
+    }
+    assert( pClause->nLits == 1 );
+
+    // if the clause proved is unit, add it and propagate
+    if ( !Intp_ManEnqueue( p, pClause->pLits[0], pClause ) )
+    {
+        assert( 0 ); // impossible
+        return 0;
+    }
+
+    // propagate the assumption
+    pConflict = Intp_ManPropagate( p, p->nRootSize );
+    if ( pConflict )
+    {
+        // insert place-holders till the empty clause
+        while ( Vec_PtrSize(p->vAntClas) < p->pCnf->pEmpty->Id - p->nAntStart )
+            Vec_PtrPush( p->vAntClas, Vec_IntAlloc(0) );
+        // construct the proof for the empty clause
+        Intp_ManProofTraceOne( p, pConflict, p->pCnf->pEmpty );
+//        if ( p->fVerbose )
+//            printf( "Found last conflict after adding unit clause number %d!\n", pClause->Id );
+        return 0;
+    }
+
+    // update the root level
+    p->nRootSize = p->nTrailSize;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagate the root clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Intp_ManProcessRoots( Intp_Man_t * p )
+{
+    Sto_Cls_t * pClause;
+    int Counter;
+
+    // make sure the root clauses are preceeding the learnt clauses
+    Counter = 0;
+    Sto_ManForEachClause( p->pCnf, pClause )
+    {
+        assert( (int)pClause->fA    == (Counter < (int)p->pCnf->nClausesA) );
+        assert( (int)pClause->fRoot == (Counter < (int)p->pCnf->nRoots)    );
+        Counter++;
+    }
+    assert( p->pCnf->nClauses == Counter );
+
+    // make sure the last clause if empty
+    assert( p->pCnf->pTail->nLits == 0 );
+
+    // go through the root unit clauses
+    p->nTrailSize = 0;
+    Sto_ManForEachClauseRoot( p->pCnf, pClause )
+    {
+        // create watcher lists for the root clauses
+        if ( pClause->nLits > 1 )
+        {
+            Intp_ManWatchClause( p, pClause, pClause->pLits[0] );
+            Intp_ManWatchClause( p, pClause, pClause->pLits[1] );
+        }
+        // empty clause and large clauses
+        if ( pClause->nLits != 1 )
+            continue;
+        // unit clause
+        assert( lit_check(pClause->pLits[0], p->pCnf->nVars) );
+        if ( !Intp_ManEnqueue( p, pClause->pLits[0], pClause ) )
+        {
+            // detected root level conflict
+//            printf( "Error in Intp_ManProcessRoots(): Detected a root-level conflict too early!\n" );
+//            assert( 0 );
+            // detected root level conflict
+            Intp_ManProofTraceOne( p, pClause, p->pCnf->pEmpty );
+            if ( p->fVerbose )
+                printf( "Found root level conflict!\n" );
+            return 0;
+        }
+    }
+
+    // propagate the root unit clauses
+    pClause = Intp_ManPropagate( p, 0 );
+    if ( pClause )
+    {
+        // detected root level conflict
+        Intp_ManProofTraceOne( p, pClause, p->pCnf->pEmpty );
+        if ( p->fVerbose )
+            printf( "Found root level conflict!\n" );
+        return 0;
+    }
+
+    // set the root level
+    p->nRootSize = p->nTrailSize;
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies the UNSAT core.]
+
+  Description [Takes the interpolation manager, the CNF derived by the SAT
+  solver, which includes the root clauses and the learned clauses. Returns
+  the array of integers representing the number of root clauses that are in
+  the UNSAT core.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Intp_ManUnsatCoreVerify( Sto_Man_t * pCnf, Vec_Int_t * vCore )
+{
+    int fVerbose = 0;
+    int nConfMax = 1000000;
+    sat_solver * pSat;
+    Sto_Cls_t * pClause;
+    Vec_Ptr_t * vClauses;
+    int i, iClause, RetValue;
+    abctime clk = Abc_Clock();
+    // collect the clauses
+    vClauses = Vec_PtrAlloc( 1000 );
+    Sto_ManForEachClauseRoot( pCnf, pClause )
+    {
+        assert( Vec_PtrSize(vClauses) == pClause->Id );
+        Vec_PtrPush( vClauses, pClause );
+    }
+    // create new SAT solver
+    pSat = sat_solver_new();
+//    sat_solver_setnvars( pSat, nSatVars );
+    Vec_IntForEachEntry( vCore, iClause, i )
+    {
+        pClause = (Sto_Cls_t *)Vec_PtrEntry( vClauses, iClause );
+        if ( !sat_solver_addclause( pSat, pClause->pLits, pClause->pLits+pClause->nLits ) )
+        {
+            printf( "The core verification problem is trivially UNSAT.\n" );
+            break;
+        }
+    }
+    Vec_PtrFree( vClauses );
+    // solve the problem
+    RetValue = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    sat_solver_delete( pSat );
+    if ( fVerbose )
+    {
+        if ( RetValue == l_Undef )
+            printf( "Conflict limit is reached.  " );
+        else if ( RetValue == l_True )
+            printf( "UNSAT core verification FAILED.  " );
+        else
+            printf( "UNSAT core verification succeeded.  " );
+        ABC_PRT( "Time", Abc_Clock() - clk );
+    }
+    else
+    {
+        if ( RetValue == l_True )
+            printf( "UNSAT core verification FAILED.  \n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively computes the UNSAT core.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Intp_ManUnsatCore_rec( Vec_Ptr_t * vAntClas, int iThis, Vec_Int_t * vCore, int nRoots, Vec_Str_t * vVisited, int fLearned )
+{
+//    int i, iStop, iStart;
+    Vec_Int_t * vAnt;
+    int i, Entry;
+    // skip visited clauses
+    if ( Vec_StrEntry( vVisited, iThis ) )
+        return;
+    Vec_StrWriteEntry( vVisited, iThis, 1 );
+    // add a root clause to the core
+    if ( iThis < nRoots )
+    {
+        if ( !fLearned )
+            Vec_IntPush( vCore, iThis );
+        return; 
+    }
+    // iterate through the clauses
+//    iStart = Vec_IntEntry( vBreaks, iThis );
+//    iStop = Vec_IntEntry( vBreaks, iThis+1 );
+//    assert( iStop != -1 );
+//    for ( i = iStart; i < iStop; i++ )
+    vAnt = (Vec_Int_t *)Vec_PtrEntry( vAntClas, iThis - nRoots );
+    Vec_IntForEachEntry( vAnt, Entry, i )
+//        Intp_ManUnsatCore_rec( vAntClas, Vec_IntEntry(vAnties, i), vCore, nRoots, vVisited );
+        Intp_ManUnsatCore_rec( vAntClas, Entry, vCore, nRoots, vVisited, fLearned );
+    // collect learned clause
+    if ( fLearned )
+        Vec_IntPush( vCore, iThis );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes UNSAT core of the satisfiablity problem.]
+
+  Description [Takes the interpolation manager, the CNF derived by the SAT
+  solver, which includes the root clauses and the learned clauses. Returns
+  the array of integers representing the number of root clauses that are in
+  the UNSAT core.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Intp_ManUnsatCore( Intp_Man_t * p, Sto_Man_t * pCnf, int fLearned, int fVerbose )
+{
+    Vec_Int_t * vCore;
+    Vec_Str_t * vVisited;
+    Sto_Cls_t * pClause;
+    int RetValue = 1;
+    abctime clkTotal = Abc_Clock();
+
+    // check that the CNF makes sense
+    assert( pCnf->nVars > 0 && pCnf->nClauses > 0 );
+    p->pCnf = pCnf;
+    p->fVerbose = fVerbose;
+
+    // adjust the manager
+    Intp_ManResize( p ); 
+
+    // construct proof for each clause
+    // start the proof
+    if ( p->fProofWrite )
+    {
+        p->pFile = fopen( "proof.cnf_", "w" );
+        p->Counter = 0;
+    }
+
+    // write the root clauses
+//    Vec_IntClear( p->vAnties );
+//    Vec_IntFill( p->vBreaks, p->pCnf->nRoots, 0 );
+    Vec_PtrClear( p->vAntClas );
+    p->nAntStart = p->pCnf->nRoots;
+
+    Sto_ManForEachClauseRoot( p->pCnf, pClause )
+        Intp_ManProofWriteOne( p, pClause );
+
+    // propagate root level assignments
+    if ( Intp_ManProcessRoots( p ) )
+    {
+        // if there is no conflict, consider learned clauses
+        Sto_ManForEachClause( p->pCnf, pClause )
+        {
+            if ( pClause->fRoot )
+                continue;
+            if ( !Intp_ManProofRecordOne( p, pClause ) )
+            {
+                RetValue = 0;
+                break;
+            }
+        }
+    }
+
+    // add the last breaker
+//    assert( p->pCnf->pEmpty->Id == Vec_IntSize(p->vBreaks) - 1 );
+//    Vec_IntPush( p->vBreaks, Vec_IntSize(p->vAnties) );
+    assert( p->pCnf->pEmpty->Id - p->nAntStart == Vec_PtrSize(p->vAntClas) - 1 );
+    Vec_PtrPush( p->vAntClas, Vec_IntAlloc(0) );
+
+    // stop the proof
+    if ( p->fProofWrite )
+    {
+        fclose( p->pFile );
+//        Sat_ProofChecker( "proof.cnf_" );
+        p->pFile = NULL;    
+    }
+
+    if ( fVerbose )
+    {
+//        ABC_PRT( "Core", Abc_Clock() - clkTotal );
+    printf( "Vars = %d. Roots = %d. Learned = %d. Resol steps = %d.  Ave = %.2f.  Mem = %.2f MB\n", 
+        p->pCnf->nVars, p->pCnf->nRoots, p->pCnf->nClauses-p->pCnf->nRoots, p->Counter,  
+        1.0*(p->Counter-p->pCnf->nRoots)/(p->pCnf->nClauses-p->pCnf->nRoots), 
+        1.0*Sto_ManMemoryReport(p->pCnf)/(1<<20) );
+p->timeTotal += Abc_Clock() - clkTotal;
+    }
+
+    // derive the UNSAT core
+    vCore = Vec_IntAlloc( 1000 );
+    vVisited = Vec_StrStart( p->pCnf->pEmpty->Id+1 );
+    Intp_ManUnsatCore_rec( p->vAntClas, p->pCnf->pEmpty->Id, vCore, p->pCnf->nRoots, vVisited, fLearned );
+    Vec_StrFree( vVisited );
+    if ( fVerbose )
+        printf( "Root clauses = %d. Learned clauses = %d. UNSAT core size = %d.\n", 
+            p->pCnf->nRoots, p->pCnf->nClauses-p->pCnf->nRoots, Vec_IntSize(vCore) );
+//    Intp_ManUnsatCoreVerify( p->pCnf, vCore );
+    return vCore;   
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints learned clauses in terms of original problem varibles.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Intp_ManUnsatCorePrintForBmc( FILE * pFile, Sto_Man_t * pCnf, void * vCore0, void * vVarMap0 )
+{
+    Vec_Int_t * vCore   = (Vec_Int_t *)vCore0;
+    Vec_Int_t * vVarMap = (Vec_Int_t *)vVarMap0;
+    Vec_Ptr_t * vClaMap;
+    Sto_Cls_t * pClause;
+    int v, i, iClause, fCompl, iObj, iFrame;
+    // create map of clause
+    vClaMap = Vec_PtrAlloc( pCnf->nClauses );
+    Sto_ManForEachClause( pCnf, pClause )
+        Vec_PtrPush( vClaMap, pClause );
+    // print clauses
+    fprintf( pFile, "UNSAT contains %d learned clauses:\n", Vec_IntSize(vCore) );
+    Vec_IntForEachEntry( vCore, iClause, i )
+    {
+        pClause = (Sto_Cls_t *)Vec_PtrEntry(vClaMap, iClause);
+        fprintf( pFile, "%6d : %6d : ", i, iClause - pCnf->nRoots );
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+        {
+            fCompl = Abc_LitIsCompl(pClause->pLits[v]);
+            iObj   = Vec_IntEntry(vVarMap, 2*Abc_Lit2Var(pClause->pLits[v]));
+            iFrame = Vec_IntEntry(vVarMap, 2*Abc_Lit2Var(pClause->pLits[v])+1);
+            fprintf( pFile, "%s%d(%d) ", fCompl ? "!":"", iObj, iFrame );
+        }
+        if ( pClause->nLits == 0 )
+            fprintf( pFile, "Empty" );
+        fprintf( pFile, "\n" );
+    }
+    Vec_PtrFree( vClaMap );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bsat/satMem.c b/abc-build/src/sat/bsat/satMem.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satMem.c
@@ -0,0 +1,583 @@
+/**CFile****************************************************************
+
+  FileName    [satMem.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT solver.]
+
+  Synopsis    [Memory management.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: satMem.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "satMem.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+struct Sat_MmFixed_t_
+{
+    // information about individual entries
+    int           nEntrySize;    // the size of one entry
+    int           nEntriesAlloc; // the total number of entries allocated
+    int           nEntriesUsed;  // the number of entries in use
+    int           nEntriesMax;   // the max number of entries in use
+    char *        pEntriesFree;  // the linked list of free entries
+
+    // this is where the memory is stored
+    int           nChunkSize;    // the size of one chunk
+    int           nChunksAlloc;  // the maximum number of memory chunks 
+    int           nChunks;       // the current number of memory chunks 
+    char **       pChunks;       // the allocated memory
+
+    // statistics
+    int           nMemoryUsed;   // memory used in the allocated entries
+    int           nMemoryAlloc;  // memory allocated
+};
+
+struct Sat_MmFlex_t_
+{
+    // information about individual entries
+    int           nEntriesUsed;  // the number of entries allocated
+    char *        pCurrent;      // the current pointer to free memory
+    char *        pEnd;          // the first entry outside the free memory
+
+    // this is where the memory is stored
+    int           nChunkSize;    // the size of one chunk
+    int           nChunksAlloc;  // the maximum number of memory chunks 
+    int           nChunks;       // the current number of memory chunks 
+    char **       pChunks;       // the allocated memory
+
+    // statistics
+    int           nMemoryUsed;   // memory used in the allocated entries
+    int           nMemoryAlloc;  // memory allocated
+};
+
+struct Sat_MmStep_t_
+{
+    int               nMems;     // the number of fixed memory managers employed
+    Sat_MmFixed_t **  pMems;     // memory managers: 2^1 words, 2^2 words, etc
+    int               nMapSize;  // the size of the memory array
+    Sat_MmFixed_t **  pMap;      // maps the number of bytes into its memory manager
+    // additional memory chunks
+    int           nChunksAlloc;  // the maximum number of memory chunks 
+    int           nChunks;       // the current number of memory chunks 
+    char **       pChunks;       // the allocated memory
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates memory pieces of fixed size.]
+
+  Description [The size of the chunk is computed as the minimum of
+  1024 entries and 64K. Can only work with entry size at least 4 byte long.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Sat_MmFixed_t * Sat_MmFixedStart( int nEntrySize )
+{
+    Sat_MmFixed_t * p;
+
+    p = ABC_ALLOC( Sat_MmFixed_t, 1 );
+    memset( p, 0, sizeof(Sat_MmFixed_t) );
+
+    p->nEntrySize    = nEntrySize;
+    p->nEntriesAlloc = 0;
+    p->nEntriesUsed  = 0;
+    p->pEntriesFree  = NULL;
+
+    if ( nEntrySize * (1 << 10) < (1<<16) )
+        p->nChunkSize = (1 << 10);
+    else
+        p->nChunkSize = (1<<16) / nEntrySize;
+    if ( p->nChunkSize < 8 )
+        p->nChunkSize = 8;
+
+    p->nChunksAlloc  = 64;
+    p->nChunks       = 0;
+    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
+
+    p->nMemoryUsed   = 0;
+    p->nMemoryAlloc  = 0;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_MmFixedStop( Sat_MmFixed_t * p, int fVerbose )
+{
+    int i;
+    if ( p == NULL )
+        return;
+    if ( fVerbose )
+    {
+        printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n",
+            p->nEntrySize, p->nChunkSize, p->nChunks );
+        printf( "   Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n",
+            p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc );
+    }
+    for ( i = 0; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    ABC_FREE( p->pChunks );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Sat_MmFixedEntryFetch( Sat_MmFixed_t * p )
+{
+    char * pTemp;
+    int i;
+
+    // check if there are still free entries
+    if ( p->nEntriesUsed == p->nEntriesAlloc )
+    { // need to allocate more entries
+        assert( p->pEntriesFree == NULL );
+        if ( p->nChunks == p->nChunksAlloc )
+        {
+            p->nChunksAlloc *= 2;
+            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
+        }
+        p->pEntriesFree = ABC_ALLOC( char, p->nEntrySize * p->nChunkSize );
+        p->nMemoryAlloc += p->nEntrySize * p->nChunkSize;
+        // transform these entries into a linked list
+        pTemp = p->pEntriesFree;
+        for ( i = 1; i < p->nChunkSize; i++ )
+        {
+            *((char **)pTemp) = pTemp + p->nEntrySize;
+            pTemp += p->nEntrySize;
+        }
+        // set the last link
+        *((char **)pTemp) = NULL;
+        // add the chunk to the chunk storage
+        p->pChunks[ p->nChunks++ ] = p->pEntriesFree;
+        // add to the number of entries allocated
+        p->nEntriesAlloc += p->nChunkSize;
+    }
+    // incrememt the counter of used entries
+    p->nEntriesUsed++;
+    if ( p->nEntriesMax < p->nEntriesUsed )
+        p->nEntriesMax = p->nEntriesUsed;
+    // return the first entry in the free entry list
+    pTemp = p->pEntriesFree;
+    p->pEntriesFree = *((char **)pTemp);
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_MmFixedEntryRecycle( Sat_MmFixed_t * p, char * pEntry )
+{
+    // decrement the counter of used entries
+    p->nEntriesUsed--;
+    // add the entry to the linked list of free entries
+    *((char **)pEntry) = p->pEntriesFree;
+    p->pEntriesFree = pEntry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description [Relocates all the memory except the first chunk.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_MmFixedRestart( Sat_MmFixed_t * p )
+{
+    int i;
+    char * pTemp;
+    if ( p->nChunks == 0 )
+        return;
+    assert( p->nChunks > 0 );
+
+    // deallocate all chunks except the first one
+    for ( i = 1; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    p->nChunks = 1;
+    // transform these entries into a linked list
+    pTemp = p->pChunks[0];
+    for ( i = 1; i < p->nChunkSize; i++ )
+    {
+        *((char **)pTemp) = pTemp + p->nEntrySize;
+        pTemp += p->nEntrySize;
+    }
+    // set the last link
+    *((char **)pTemp) = NULL;
+    // set the free entry list
+    p->pEntriesFree  = p->pChunks[0];
+    // set the correct statistics
+    p->nMemoryAlloc  = p->nEntrySize * p->nChunkSize;
+    p->nMemoryUsed   = 0;
+    p->nEntriesAlloc = p->nChunkSize;
+    p->nEntriesUsed  = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sat_MmFixedReadMemUsage( Sat_MmFixed_t * p )
+{
+    return p->nMemoryAlloc;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates entries of flexible size.]
+
+  Description [Can only work with entry size at least 4 byte long.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Sat_MmFlex_t * Sat_MmFlexStart()
+{
+    Sat_MmFlex_t * p;
+
+    p = ABC_ALLOC( Sat_MmFlex_t, 1 );
+    memset( p, 0, sizeof(Sat_MmFlex_t) );
+
+    p->nEntriesUsed  = 0;
+    p->pCurrent      = NULL;
+    p->pEnd          = NULL;
+
+    p->nChunkSize    = (1 << 16);
+    p->nChunksAlloc  = 64;
+    p->nChunks       = 0;
+    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
+
+    p->nMemoryUsed   = 0;
+    p->nMemoryAlloc  = 0;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_MmFlexStop( Sat_MmFlex_t * p, int fVerbose )
+{
+    int i;
+    if ( p == NULL )
+        return;
+    if ( fVerbose )
+    {
+        printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n",
+            p->nChunkSize, p->nChunks );
+        printf( "   Entries used = %d. Memory used = %d. Memory alloc = %d.\n",
+            p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc );
+    }
+    for ( i = 0; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    ABC_FREE( p->pChunks );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Sat_MmFlexEntryFetch( Sat_MmFlex_t * p, int nBytes )
+{
+    char * pTemp;
+    // check if there are still free entries
+    if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd )
+    { // need to allocate more entries
+        if ( p->nChunks == p->nChunksAlloc )
+        {
+            p->nChunksAlloc *= 2;
+            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
+        }
+        if ( nBytes > p->nChunkSize )
+        {
+            // resize the chunk size if more memory is requested than it can give
+            // (ideally, this should never happen)
+            p->nChunkSize = 2 * nBytes;
+        }
+        p->pCurrent = ABC_ALLOC( char, p->nChunkSize );
+        p->pEnd     = p->pCurrent + p->nChunkSize;
+        p->nMemoryAlloc += p->nChunkSize;
+        // add the chunk to the chunk storage
+        p->pChunks[ p->nChunks++ ] = p->pCurrent;
+    }
+    assert( p->pCurrent + nBytes <= p->pEnd );
+    // increment the counter of used entries
+    p->nEntriesUsed++;
+    // keep track of the memory used
+    p->nMemoryUsed += nBytes;
+    // return the next entry
+    pTemp = p->pCurrent;
+    p->pCurrent += nBytes;
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sat_MmFlexReadMemUsage( Sat_MmFlex_t * p )
+{
+    return p->nMemoryAlloc;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the hierarchical memory manager.]
+
+  Description [This manager can allocate entries of any size.
+  Iternally they are mapped into the entries with the number of bytes
+  equal to the power of 2. The smallest entry size is 8 bytes. The
+  next one is 16 bytes etc. So, if the user requests 6 bytes, he gets 
+  8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc.
+  The input parameters "nSteps" says how many fixed memory managers
+  are employed internally. Calling this procedure with nSteps equal
+  to 10 results in 10 hierarchically arranged internal memory managers, 
+  which can allocate up to 4096 (1Kb) entries. Requests for larger 
+  entries are handed over to malloc() and then ABC_FREE()ed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Sat_MmStep_t * Sat_MmStepStart( int nSteps )
+{
+    Sat_MmStep_t * p;
+    int i, k;
+    p = ABC_ALLOC( Sat_MmStep_t, 1 );
+    p->nMems = nSteps;
+    // start the fixed memory managers
+    p->pMems = ABC_ALLOC( Sat_MmFixed_t *, p->nMems );
+    for ( i = 0; i < p->nMems; i++ )
+        p->pMems[i] = Sat_MmFixedStart( (8<<i) );
+    // set up the mapping of the required memory size into the corresponding manager
+    p->nMapSize = (4<<p->nMems);
+    p->pMap = ABC_ALLOC( Sat_MmFixed_t *, p->nMapSize+1 );
+    p->pMap[0] = NULL;
+    for ( k = 1; k <= 4; k++ )
+        p->pMap[k] = p->pMems[0];
+    for ( i = 0; i < p->nMems; i++ )
+        for ( k = (4<<i)+1; k <= (8<<i); k++ )
+            p->pMap[k] = p->pMems[i];
+//for ( i = 1; i < 100; i ++ )
+//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize );
+    p->nChunksAlloc  = 64;
+    p->nChunks       = 0;
+    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_MmStepStop( Sat_MmStep_t * p, int fVerbose )
+{
+    int i;
+    if ( p->nChunksAlloc )
+    {
+        for ( i = 0; i < p->nChunks; i++ )
+            ABC_FREE( p->pChunks[i] );
+        ABC_FREE( p->pChunks );
+    }
+    for ( i = 0; i < p->nMems; i++ )
+        Sat_MmFixedStop( p->pMems[i], fVerbose );
+    ABC_FREE( p->pMems );
+    ABC_FREE( p->pMap );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_MmStepRestart( Sat_MmStep_t * p )
+{
+    int i;
+    if ( p->nChunksAlloc )
+    {
+        for ( i = 0; i < p->nChunks; i++ )
+            ABC_FREE( p->pChunks[i] );
+        p->nChunks = 0;
+    }
+    for ( i = 0; i < p->nMems; i++ )
+        Sat_MmFixedRestart( p->pMems[i] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Sat_MmStepEntryFetch( Sat_MmStep_t * p, int nBytes )
+{
+    if ( nBytes == 0 )
+        return NULL;
+    if ( nBytes > p->nMapSize )
+    {
+        if ( p->nChunks == p->nChunksAlloc )
+        {
+            p->nChunksAlloc *= 2;
+            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
+        }
+        p->pChunks[ p->nChunks++ ] = ABC_ALLOC( char, nBytes );
+        return p->pChunks[p->nChunks-1];
+    }
+    return Sat_MmFixedEntryFetch( p->pMap[nBytes] );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_MmStepEntryRecycle( Sat_MmStep_t * p, char * pEntry, int nBytes )
+{
+    if ( nBytes == 0 )
+        return;
+    if ( nBytes > p->nMapSize )
+    {
+//        ABC_FREE( pEntry );
+        return;
+    }
+    Sat_MmFixedEntryRecycle( p->pMap[nBytes], pEntry );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sat_MmStepReadMemUsage( Sat_MmStep_t * p )
+{
+    int i, nMemTotal = 0;
+    for ( i = 0; i < p->nMems; i++ )
+        nMemTotal += p->pMems[i]->nMemoryAlloc;
+    return nMemTotal;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bsat/satMem.h b/abc-build/src/sat/bsat/satMem.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satMem.h
@@ -0,0 +1,85 @@
+/**CFile****************************************************************
+
+  FileName    [satMem.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT solver.]
+
+  Synopsis    [Memory management.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: satMem.h,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__sat__bsat__satMem_h
+#define ABC__sat__bsat__satMem_h
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "misc/util/abc_global.h"
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Sat_MmFixed_t_ Sat_MmFixed_t;
+typedef struct Sat_MmFlex_t_  Sat_MmFlex_t;
+typedef struct Sat_MmStep_t_  Sat_MmStep_t;
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DECLARATIONS                        ///
+////////////////////////////////////////////////////////////////////////
+
+// fixed-size-block memory manager
+extern Sat_MmFixed_t *     Sat_MmFixedStart( int nEntrySize );
+extern void                Sat_MmFixedStop( Sat_MmFixed_t * p, int fVerbose );
+extern char *              Sat_MmFixedEntryFetch( Sat_MmFixed_t * p );
+extern void                Sat_MmFixedEntryRecycle( Sat_MmFixed_t * p, char * pEntry );
+extern void                Sat_MmFixedRestart( Sat_MmFixed_t * p );
+extern int                 Sat_MmFixedReadMemUsage( Sat_MmFixed_t * p );
+// flexible-size-block memory manager
+extern Sat_MmFlex_t *      Sat_MmFlexStart();
+extern void                Sat_MmFlexStop( Sat_MmFlex_t * p, int fVerbose );
+extern char *              Sat_MmFlexEntryFetch( Sat_MmFlex_t * p, int nBytes );
+extern int                 Sat_MmFlexReadMemUsage( Sat_MmFlex_t * p );
+// hierarchical memory manager
+extern Sat_MmStep_t *      Sat_MmStepStart( int nSteps );
+extern void                Sat_MmStepStop( Sat_MmStep_t * p, int fVerbose );
+extern void                Sat_MmStepRestart( Sat_MmStep_t * p );
+extern char *              Sat_MmStepEntryFetch( Sat_MmStep_t * p, int nBytes );
+extern void                Sat_MmStepEntryRecycle( Sat_MmStep_t * p, char * pEntry, int nBytes );
+extern int                 Sat_MmStepReadMemUsage( Sat_MmStep_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/sat/bsat/satProof.c b/abc-build/src/sat/bsat/satProof.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satProof.c
@@ -0,0 +1,934 @@
+/**CFile****************************************************************
+
+  FileName    [satProof.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT solver.]
+
+  Synopsis    [Proof manipulation procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: satProof.c,v 1.4 2005/09/16 22:55:03 casem Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+#include "misc/vec/vecSet.h"
+#include "aig/aig/aig.h"
+#include "satTruth.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/*
+    Proof is represented as a vector of records.
+    A resolution record is represented by a handle (an offset in this vector).
+    A resolution record entry is <size><label><ant1><ant2>...<antN>
+    Label is initialized to 0. Root clauses are given by their handles.
+    They are marked by bitshifting by 2 bits up and setting the LSB to 1
+*/
+
+typedef struct satset_t satset;
+struct satset_t 
+{
+    unsigned learnt :  1;
+    unsigned mark   :  1;
+    unsigned partA  :  1;
+    unsigned nEnts  : 29;
+    int      Id;
+    int      pEnts[0];
+};
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+//static inline satset* Proof_ClauseRead  ( Vec_Int_t* p, int h )     { assert( h > 0 );     return satset_read( (veci *)p, h );    }
+//static inline satset* Proof_ClauseRead  ( Vec_Int_t* p, int h )     { assert( h > 0 );     return (satset *)Vec_IntEntryP( p, h );}
+static inline satset* Proof_NodeRead    ( Vec_Set_t* p, int h )     { assert( h > 0 );     return (satset*)Vec_SetEntry( p, h );  }
+static inline int     Proof_NodeWordNum ( int nEnts )               { assert( nEnts > 0 ); return 1 + ((nEnts + 1) >> 1);         }
+
+void Proof_ClauseSetEnts( Vec_Set_t* p, int h, int nEnts )          { Proof_NodeRead(p, h)->nEnts = nEnts;             }
+
+// iterating through nodes in the proof
+#define Proof_ForeachClauseVec( pVec, p, pNode, i )          \
+    for ( i = 0; (i < Vec_IntSize(pVec)) && ((pNode) = Proof_ClauseRead(p, Vec_IntEntry(pVec,i))); i++ )
+#define Proof_ForeachNodeVec( pVec, p, pNode, i )            \
+    for ( i = 0; (i < Vec_IntSize(pVec)) && ((pNode) = Proof_NodeRead(p, Vec_IntEntry(pVec,i))); i++ )
+#define Proof_ForeachNodeVec1( pVec, p, pNode, i )            \
+    for ( i = 1; (i < Vec_IntSize(pVec)) && ((pNode) = Proof_NodeRead(p, Vec_IntEntry(pVec,i))); i++ )
+
+// iterating through fanins of a proof node
+#define Proof_NodeForeachFanin( pProof, pNode, pFanin, i )        \
+    for ( i = 0; (i < (int)pNode->nEnts) && (((pFanin) = (pNode->pEnts[i] & 1) ? NULL : Proof_NodeRead(pProof, pNode->pEnts[i] >> 2)), 1); i++ )
+/*
+#define Proof_NodeForeachLeaf( pClauses, pNode, pLeaf, i )   \
+    for ( i = 0; (i < (int)pNode->nEnts) && (((pLeaf) = (pNode->pEnts[i] & 1) ? Proof_ClauseRead(pClauses, pNode->pEnts[i] >> 2) : NULL), 1); i++ )
+#define Proof_NodeForeachFaninLeaf( pProof, pClauses, pNode, pFanin, i )    \
+    for ( i = 0; (i < (int)pNode->nEnts) && ((pFanin) = (pNode->pEnts[i] & 1) ? Proof_ClauseRead(pClauses, pNode->pEnts[i] >> 2) : Proof_NodeRead(pProof, pNode->pEnts[i] >> 2)); i++ )
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans collected resultion nodes belonging to the proof.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Proof_CleanCollected( Vec_Set_t * vProof, Vec_Int_t * vUsed )
+{
+    satset * pNode;
+    int hNode;
+    Proof_ForeachNodeVec( vUsed, vProof, pNode, hNode )
+        pNode->Id = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Proof_CollectUsed_iter( Vec_Set_t * vProof, int hNode, Vec_Int_t * vUsed, Vec_Int_t * vStack )
+{
+    satset * pNext, * pNode = Proof_NodeRead( vProof, hNode );
+    int i;
+    if ( pNode->Id )
+        return;
+    // start with node
+    pNode->Id = 1;
+    Vec_IntPush( vStack, hNode << 1 );
+    // perform DFS search
+    while ( Vec_IntSize(vStack) )
+    {
+        hNode = Vec_IntPop( vStack );
+        if ( hNode & 1 ) // extracted second time
+        {
+            Vec_IntPush( vUsed, hNode >> 1 );
+            continue;
+        }
+        // extracted first time        
+        Vec_IntPush( vStack, hNode ^ 1 ); // add second time
+        // add its anticedents        ;
+        pNode = Proof_NodeRead( vProof, hNode >> 1 );
+        Proof_NodeForeachFanin( vProof, pNode, pNext, i )
+            if ( pNext && !pNext->Id )
+            {
+                pNext->Id = 1;
+                Vec_IntPush( vStack, (pNode->pEnts[i] >> 2) << 1 ); // add first time
+            }
+    }
+}
+Vec_Int_t * Proof_CollectUsedIter( Vec_Set_t * vProof, Vec_Int_t * vRoots, int fSort )
+{
+    int fVerify = 0;
+    Vec_Int_t * vUsed, * vStack;
+    abctime clk = Abc_Clock();
+    int i, Entry, iPrev = 0;
+    vUsed = Vec_IntAlloc( 1000 );
+    vStack = Vec_IntAlloc( 1000 );
+    Vec_IntForEachEntry( vRoots, Entry, i )
+        if ( Entry >= 0 )
+            Proof_CollectUsed_iter( vProof, Entry, vUsed, vStack );
+    Vec_IntFree( vStack );
+//    Abc_PrintTime( 1, "Iterative clause collection time", Abc_Clock() - clk );
+    clk = Abc_Clock();
+    Abc_MergeSort( Vec_IntArray(vUsed), Vec_IntSize(vUsed) );
+//    Abc_PrintTime( 1, "Postprocessing with sorting time", Abc_Clock() - clk );
+    // verify topological order
+    if ( fVerify )
+    {
+        iPrev = 0;
+        Vec_IntForEachEntry( vUsed, Entry, i )
+        {
+            if ( iPrev >= Entry )
+                printf( "Out of topological order!!!\n" );
+            assert( iPrev < Entry );
+            iPrev = Entry;
+        }
+    }
+    return vUsed;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively collects useful proof nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Proof_CollectUsed_rec( Vec_Set_t * vProof, int hNode, Vec_Int_t * vUsed )
+{
+    satset * pNext, * pNode = Proof_NodeRead( vProof, hNode );
+    int i;
+    if ( pNode->Id )
+        return;
+    pNode->Id = 1;
+    Proof_NodeForeachFanin( vProof, pNode, pNext, i )
+        if ( pNext && !pNext->Id )
+            Proof_CollectUsed_rec( vProof, pNode->pEnts[i] >> 2, vUsed );
+    Vec_IntPush( vUsed, hNode );
+}
+Vec_Int_t * Proof_CollectUsedRec( Vec_Set_t * vProof, Vec_Int_t * vRoots )
+{
+    Vec_Int_t * vUsed;
+    int i, Entry;
+    vUsed = Vec_IntAlloc( 1000 );
+    Vec_IntForEachEntry( vRoots, Entry, i )
+        if ( Entry >= 0 )
+            Proof_CollectUsed_rec( vProof, Entry, vUsed );
+    return vUsed;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Recursively visits useful proof nodes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Proof_MarkUsed_rec( Vec_Set_t * vProof, int hNode )
+{
+    satset * pNext, * pNode = Proof_NodeRead( vProof, hNode );
+    int i, Counter = 1;
+    if ( pNode->Id )
+        return 0;
+    pNode->Id = 1;
+    Proof_NodeForeachFanin( vProof, pNode, pNext, i )
+        if ( pNext && !pNext->Id )
+            Counter += Proof_MarkUsed_rec( vProof, pNode->pEnts[i] >> 2 );
+    return Counter;
+}
+int Proof_MarkUsedRec( Vec_Set_t * vProof, Vec_Int_t * vRoots )
+{
+    int i, Entry, Counter = 0;
+    Vec_IntForEachEntry( vRoots, Entry, i )
+        if ( Entry >= 0 )
+            Counter += Proof_MarkUsed_rec( vProof, Entry );
+    return Counter;
+}
+
+
+
+  
+/**Function*************************************************************
+
+  Synopsis    [Checks the validity of the check point.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+void Sat_ProofReduceCheck_rec( Vec_Set_t * vProof, Vec_Int_t * vClauses, satset * pNode, int hClausePivot, Vec_Ptr_t * vVisited )
+{
+    satset * pFanin;
+    int k;
+    if ( pNode->Id )
+        return;
+    pNode->Id = -1;
+    Proof_NodeForeachFaninLeaf( vProof, vClauses, pNode, pFanin, k )
+        if ( (pNode->pEnts[k] & 1) == 0 ) // proof node
+            Sat_ProofReduceCheck_rec( vProof, vClauses, pFanin, hClausePivot, vVisited );
+        else // problem clause
+            assert( (pNode->pEnts[k] >> 2) < hClausePivot );
+    Vec_PtrPush( vVisited, pNode );
+}
+void Sat_ProofReduceCheckOne( sat_solver2 * s, int iLearnt, Vec_Ptr_t * vVisited )
+{
+    Vec_Set_t * vProof   = (Vec_Set_t *)&s->Proofs;
+    Vec_Int_t * vClauses = (Vec_Int_t *)&s->clauses;
+    Vec_Int_t * vRoots   = (Vec_Int_t *)&s->claProofs;
+    int hProofNode = Vec_IntEntry( vRoots, iLearnt );
+    satset * pNode = Proof_NodeRead( vProof, hProofNode );
+    Sat_ProofReduceCheck_rec( vProof, vClauses, pNode, s->hClausePivot, vVisited );
+}
+void Sat_ProofReduceCheck( sat_solver2 * s )
+{
+    Vec_Ptr_t * vVisited;
+    satset * c;
+    int h, i = 1;
+    vVisited = Vec_PtrAlloc( 1000 );
+    sat_solver_foreach_learnt( s, c, h )
+        if ( h < s->hLearntPivot )
+            Sat_ProofReduceCheckOne( s, i++, vVisited );
+    Vec_PtrForEachEntry( satset *, vVisited, c, i )
+        c->Id = 0;
+    Vec_PtrFree( vVisited );
+}
+*/
+
+/**Function*************************************************************
+
+  Synopsis    [Reduces the proof to contain only roots and their children.]
+
+  Description [The result is updated proof and updated roots.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+void Sat_ProofReduce2( sat_solver2 * s )
+{
+    Vec_Set_t * vProof   = (Vec_Set_t *)&s->Proofs;
+    Vec_Int_t * vRoots   = (Vec_Int_t *)&s->claProofs;
+    Vec_Int_t * vClauses = (Vec_Int_t *)&s->clauses;
+
+    int fVerbose = 0;
+    Vec_Int_t * vUsed;
+    satset * pNode, * pFanin, * pPivot;
+    int i, k, hTemp;
+    abctime clk = Abc_Clock();
+    static abctime TimeTotal = 0;
+
+    // collect visited nodes
+    vUsed = Proof_CollectUsedIter( vProof, vRoots, 1 );
+
+    // relabel nodes to use smaller space
+    Vec_SetShrinkS( vProof, 2 );
+    Proof_ForeachNodeVec( vUsed, vProof, pNode, i )
+    {
+        pNode->Id = Vec_SetAppendS( vProof, 2+pNode->nEnts );
+        Proof_NodeForeachFaninLeaf( vProof, vClauses, pNode, pFanin, k )
+            if ( (pNode->pEnts[k] & 1) == 0 ) // proof node
+                pNode->pEnts[k] = (pFanin->Id << 2) | (pNode->pEnts[k] & 2);
+            else // problem clause
+                assert( (int*)pFanin >= Vec_IntArray(vClauses) && (int*)pFanin < Vec_IntArray(vClauses)+Vec_IntSize(vClauses) );
+    }
+    // update roots
+    Proof_ForeachNodeVec1( vRoots, vProof, pNode, i )
+        Vec_IntWriteEntry( vRoots, i, pNode->Id );
+    // determine new pivot
+    assert( s->hProofPivot >= 1 && s->hProofPivot <= Vec_SetHandCurrent(vProof) );
+    pPivot = Proof_NodeRead( vProof, s->hProofPivot );
+    s->hProofPivot = Vec_SetHandCurrentS(vProof);
+    // compact the nodes
+    Proof_ForeachNodeVec( vUsed, vProof, pNode, i )
+    {
+        hTemp = pNode->Id; pNode->Id = 0;
+        memmove( Vec_SetEntry(vProof, hTemp), pNode, sizeof(word)*Proof_NodeWordNum(pNode->nEnts) );
+        if ( pPivot && pPivot <= pNode )
+        { 
+            s->hProofPivot = hTemp;
+            pPivot = NULL;
+        }
+    }
+    Vec_SetWriteEntryNum( vProof, Vec_IntSize(vUsed) );
+    Vec_IntFree( vUsed );
+
+    // report the result
+    if ( fVerbose )
+    {
+        printf( "\n" );
+        printf( "The proof was reduced from %6.2f MB to %6.2f MB (by %6.2f %%)  ", 
+            1.0 * Vec_SetMemory(vProof) / (1<<20), 1.0 * Vec_SetMemoryS(vProof) / (1<<20), 
+            100.0 * (Vec_SetMemory(vProof) - Vec_SetMemoryS(vProof)) / Vec_SetMemory(vProof) );
+        TimeTotal += Abc_Clock() - clk;
+        Abc_PrintTime( 1, "Time", TimeTotal );
+    }
+    Vec_SetShrink( vProof, Vec_SetHandCurrentS(vProof) );
+//    Sat_ProofReduceCheck( s );
+} 
+*/
+
+
+void Sat_ProofCheck0( Vec_Set_t * vProof )
+{
+    satset * pNode, * pFanin;
+    int i, j, k, nSize;
+    Vec_SetForEachEntry( satset *, vProof, nSize, pNode, i, j )
+    {
+        nSize = Vec_SetWordNum( 2 + pNode->nEnts );
+        Proof_NodeForeachFanin( vProof, pNode, pFanin, k )
+            assert( (pNode->pEnts[k] >> 2) );
+    }
+}
+
+int Sat_ProofReduce( Vec_Set_t * vProof, void * pRoots, int hProofPivot )
+{
+//    Vec_Set_t * vProof   = (Vec_Set_t *)&s->Proofs;
+//    Vec_Int_t * vRoots   = (Vec_Int_t *)&s->claProofs;
+    Vec_Int_t * vRoots   = (Vec_Int_t *)pRoots;
+//    Vec_Int_t * vClauses = (Vec_Int_t *)&s->clauses;
+    int fVerbose = 0;
+    Vec_Ptr_t * vUsed;
+    satset * pNode, * pFanin, * pPivot;
+    int i, j, k, hTemp, nSize;
+    abctime clk = Abc_Clock();
+    static abctime TimeTotal = 0;
+    int RetValue;
+//Sat_ProofCheck0( vProof );
+
+    // collect visited nodes
+    nSize = Proof_MarkUsedRec( vProof, vRoots );
+    vUsed = Vec_PtrAlloc( nSize );
+//Sat_ProofCheck0( vProof );
+
+    // relabel nodes to use smaller space
+    Vec_SetShrinkS( vProof, 2 );
+    Vec_SetForEachEntry( satset *, vProof, nSize, pNode, i, j )
+    {
+        nSize = Vec_SetWordNum( 2 + pNode->nEnts );
+        if ( pNode->Id == 0 ) 
+            continue;
+        pNode->Id = Vec_SetAppendS( vProof, 2 + pNode->nEnts );
+        assert( pNode->Id > 0 );
+        Vec_PtrPush( vUsed, pNode );
+        // update fanins
+        Proof_NodeForeachFanin( vProof, pNode, pFanin, k )
+            if ( (pNode->pEnts[k] & 1) == 0 ) // proof node
+            {
+                assert( pFanin->Id > 0 );
+                pNode->pEnts[k] = (pFanin->Id << 2) | (pNode->pEnts[k] & 2);
+            }
+//            else // problem clause
+//                assert( (int*)pFanin >= Vec_IntArray(vClauses) && (int*)pFanin < Vec_IntArray(vClauses)+Vec_IntSize(vClauses) );
+    }
+    // update roots
+    Proof_ForeachNodeVec1( vRoots, vProof, pNode, i )
+        Vec_IntWriteEntry( vRoots, i, pNode->Id );
+    // determine new pivot
+    assert( hProofPivot >= 1 && hProofPivot <= Vec_SetHandCurrent(vProof) );
+    pPivot = Proof_NodeRead( vProof, hProofPivot );
+    RetValue = Vec_SetHandCurrentS(vProof);
+    // compact the nodes
+    Vec_PtrForEachEntry( satset *, vUsed, pNode, i )
+    {
+        hTemp = pNode->Id; pNode->Id = 0;
+        memmove( Vec_SetEntry(vProof, hTemp), pNode, sizeof(word)*Proof_NodeWordNum(pNode->nEnts) );
+        if ( pPivot && pPivot <= pNode )
+        {
+            RetValue = hTemp;
+            pPivot = NULL;
+        }
+    }
+    Vec_SetWriteEntryNum( vProof, Vec_PtrSize(vUsed) );
+    Vec_PtrFree( vUsed );
+
+    // report the result
+    if ( fVerbose )
+    {
+        printf( "\n" );
+        printf( "The proof was reduced from %6.2f MB to %6.2f MB (by %6.2f %%)  ", 
+            1.0 * Vec_SetMemory(vProof) / (1<<20), 1.0 * Vec_SetMemoryS(vProof) / (1<<20), 
+            100.0 * (Vec_SetMemory(vProof) - Vec_SetMemoryS(vProof)) / Vec_SetMemory(vProof) );
+        TimeTotal += Abc_Clock() - clk;
+        Abc_PrintTime( 1, "Time", TimeTotal );
+    }
+    Vec_SetShrink( vProof, Vec_SetHandCurrentS(vProof) );
+    Vec_SetShrinkLimits( vProof );
+//    Sat_ProofReduceCheck( s );
+//Sat_ProofCheck0( vProof );
+
+    return RetValue;
+}
+
+#if 0
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one resultion step.]
+
+  Description [Returns ID of the resolvent if success, and -1 if failure.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sat_ProofCheckResolveOne( Vec_Set_t * p, satset * c1, satset * c2, Vec_Int_t * vTemp )
+{
+    satset * c;
+    int h, i, k, Var = -1, Count = 0;
+    // find resolution variable
+    for ( i = 0; i < (int)c1->nEnts; i++ )
+    for ( k = 0; k < (int)c2->nEnts; k++ )
+        if ( (c1->pEnts[i] ^ c2->pEnts[k]) == 1 )
+        {
+            Var = (c1->pEnts[i] >> 1);
+            Count++;
+        }
+    if ( Count == 0 )
+    {
+        printf( "Cannot find resolution variable\n" );
+        return 0;
+    }
+    if ( Count > 1 )
+    {
+        printf( "Found more than 1 resolution variables\n" );
+        return 0;
+    }
+    // perform resolution
+    Vec_IntClear( vTemp );
+    Vec_IntPush( vTemp, 0 ); // placeholder
+    Vec_IntPush( vTemp, 0 );
+    for ( i = 0; i < (int)c1->nEnts; i++ )
+        if ( (c1->pEnts[i] >> 1) != Var )
+            Vec_IntPush( vTemp, c1->pEnts[i] );
+    for ( i = 0; i < (int)c2->nEnts; i++ )
+        if ( (c2->pEnts[i] >> 1) != Var )
+            Vec_IntPushUnique( vTemp, c2->pEnts[i] );
+    // create new resolution entry
+    h = Vec_SetAppend( p, Vec_IntArray(vTemp), Vec_IntSize(vTemp) );
+    // return the new entry
+    c = Proof_NodeRead( p, h );
+    c->nEnts = Vec_IntSize(vTemp)-2;
+    return h;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the proof for consitency.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+satset * Sat_ProofCheckReadOne( Vec_Int_t * vClauses, Vec_Set_t * vProof, Vec_Set_t * vResolves, int iAnt )
+{
+    satset * pAnt;
+    if ( iAnt & 1 )
+        return Proof_ClauseRead( vClauses, iAnt >> 2 );
+    assert( iAnt > 0 );
+    pAnt = Proof_NodeRead( vProof, iAnt >> 2 );
+    assert( pAnt->Id > 0 );
+    return Proof_NodeRead( vResolves, pAnt->Id );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the proof for consitency.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_ProofCheck( sat_solver2 * s )
+{
+    Vec_Int_t * vClauses = (Vec_Int_t *)&s->clauses;
+    Vec_Set_t * vProof   = (Vec_Set_t *)&s->Proofs;
+    Vec_Int_t Roots = { 1, 1, &s->hProofLast }, * vRoots = &Roots;
+    Vec_Set_t * vResolves;
+    Vec_Int_t * vUsed, * vTemp;
+    satset * pSet, * pSet0 = NULL, * pSet1;
+    int i, k, hRoot, Handle, Counter = 0;
+    abctime clk = Abc_Clock(); 
+    hRoot = s->hProofLast;
+    if ( hRoot == -1 )
+        return;
+    // collect visited clauses
+    vUsed = Proof_CollectUsedIter( vProof, vRoots, 1 );
+    Proof_CleanCollected( vProof, vUsed );
+    // perform resolution steps
+    vTemp = Vec_IntAlloc( 1000 );
+    vResolves = Vec_SetAlloc( 20 );
+    Proof_ForeachNodeVec( vUsed, vProof, pSet, i )
+    {
+        Handle = -1;
+        pSet0 = Sat_ProofCheckReadOne( vClauses, vProof, vResolves, pSet->pEnts[0] );
+        for ( k = 1; k < (int)pSet->nEnts; k++ )
+        {
+            pSet1  = Sat_ProofCheckReadOne( vClauses, vProof, vResolves, pSet->pEnts[k] );
+            Handle = Sat_ProofCheckResolveOne( vResolves, pSet0, pSet1, vTemp );
+            pSet0  = Proof_NodeRead( vResolves, Handle );
+        }
+        pSet->Id = Handle;
+        Counter++;
+    }
+    Vec_IntFree( vTemp );
+    // clean the proof
+    Proof_CleanCollected( vProof, vUsed );
+    // compare the final clause
+    printf( "Used %6.2f MB for resolvents.\n", 1.0 * Vec_SetMemory(vResolves) / (1<<20) );
+    if ( pSet0->nEnts > 0 )
+        printf( "Derived clause with %d lits instead of the empty clause.  ", pSet0->nEnts );
+    else
+        printf( "Proof verification successful.  " );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    // cleanup
+    Vec_SetFree( vResolves );
+    Vec_IntFree( vUsed );
+}
+#endif
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes belonging to the UNSAT core.]
+
+  Description [The resulting array contains 1-based IDs of root clauses.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Sat_ProofCollectCore( Vec_Set_t * vProof, Vec_Int_t * vUsed )
+{
+    Vec_Int_t * vCore;
+    satset * pNode, * pFanin;
+    unsigned * pBitMap;
+    int i, k, MaxCla = 0;
+    // find the largest number
+    Proof_ForeachNodeVec( vUsed, vProof, pNode, i )
+        Proof_NodeForeachFanin( vProof, pNode, pFanin, k )
+            if ( pFanin == NULL )
+                MaxCla = Abc_MaxInt( MaxCla, pNode->pEnts[k] >> 2 );
+    // allocate bitmap
+    pBitMap = ABC_CALLOC( unsigned, Abc_BitWordNum(MaxCla) + 1 );
+    // collect leaves
+    vCore = Vec_IntAlloc( 1000 );
+    Proof_ForeachNodeVec( vUsed, vProof, pNode, i )
+        Proof_NodeForeachFanin( vProof, pNode, pFanin, k )
+            if ( pFanin == NULL )
+            {
+                int Entry = (pNode->pEnts[k] >> 2);
+                if ( Abc_InfoHasBit(pBitMap, Entry) )
+                    continue;
+                Abc_InfoSetBit(pBitMap, Entry);
+                Vec_IntPush( vCore, Entry );
+            }
+    ABC_FREE( pBitMap );
+//    Vec_IntUniqify( vCore );
+    return vCore;
+}
+
+#if 0
+
+/**Function*************************************************************
+
+  Synopsis    [Verifies that variables are labeled correctly.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_ProofInterpolantCheckVars( sat_solver2 * s, Vec_Int_t * vGloVars )
+{
+    satset* c; 
+    Vec_Int_t * vVarMap;
+    int i, k, Entry, * pMask;
+    int Counts[5] = {0};
+    // map variables into their type (A, B, or AB)
+    vVarMap = Vec_IntStart( s->size );
+    sat_solver_foreach_clause( s, c, i )
+        for ( k = 0; k < (int)c->nEnts; k++ )
+            *Vec_IntEntryP(vVarMap, lit_var(c->pEnts[k])) |= 2 - c->partA;
+    // analyze variables
+    Vec_IntForEachEntry( vGloVars, Entry, i )
+    {
+        pMask = Vec_IntEntryP(vVarMap, Entry);
+        assert( *pMask >= 0 && *pMask <= 3 );
+        Counts[(*pMask & 3)]++;
+        *pMask = 0;
+    }
+    // count the number of global variables not listed
+    Vec_IntForEachEntry( vVarMap, Entry, i )
+        if ( Entry == 3 )
+            Counts[4]++;
+    Vec_IntFree( vVarMap );
+    // report
+    if ( Counts[0] )
+        printf( "Warning: %6d variables listed as global do not appear in clauses (this is normal)\n", Counts[0] );
+    if ( Counts[1] )
+        printf( "Warning: %6d variables listed as global appear only in A-clauses (this is a BUG)\n", Counts[1] );
+    if ( Counts[2] )
+        printf( "Warning: %6d variables listed as global appear only in B-clauses (this is a BUG)\n", Counts[2] );
+    if ( Counts[3] )
+        printf( "Warning: %6d (out of %d) variables listed as global appear in both A- and B-clauses (this is normal)\n", Counts[3], Vec_IntSize(vGloVars) );
+    if ( Counts[4] )
+        printf( "Warning: %6d variables not listed as global appear in both A- and B-clauses (this is a BUG)\n", Counts[4] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes interpolant of the proof.]
+
+  Description [Aassuming that vars/clause of partA are marked.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Sat_ProofInterpolant( sat_solver2 * s, void * pGloVars )
+{
+    Vec_Int_t * vClauses  = (Vec_Int_t *)&s->clauses;
+    Vec_Set_t * vProof    = (Vec_Set_t *)&s->Proofs;
+    Vec_Int_t * vGlobVars = (Vec_Int_t *)pGloVars;
+    Vec_Int_t Roots = { 1, 1, &s->hProofLast }, * vRoots = &Roots;
+    Vec_Int_t * vUsed, * vCore, * vCoreNums, * vVarMap;
+    satset * pNode, * pFanin;
+    Aig_Man_t * pAig;
+    Aig_Obj_t * pObj = NULL;
+    int i, k, iVar, Lit, Entry, hRoot;
+//    if ( s->hLearntLast < 0 )
+//        return NULL;
+//    hRoot = veci_begin(&s->claProofs)[satset_read(&s->learnts, s->hLearntLast>>1)->Id];
+    hRoot = s->hProofLast;
+    if ( hRoot == -1 )
+        return NULL;
+
+    Sat_ProofInterpolantCheckVars( s, vGlobVars );
+
+    // collect visited nodes
+    vUsed = Proof_CollectUsedIter( vProof, vRoots, 1 );
+    // collect core clauses (cleans vUsed and vCore)
+    vCore = Sat_ProofCollectCore( vProof, vUsed ); 
+    // vCore arrived in terms of clause handles
+
+    // map variables into their global numbers
+    vVarMap = Vec_IntStartFull( s->size );
+    Vec_IntForEachEntry( vGlobVars, Entry, i )
+        Vec_IntWriteEntry( vVarMap, Entry, i );
+
+    // start the AIG
+    pAig = Aig_ManStart( 10000 );
+    pAig->pName = Abc_UtilStrsav( "interpol" );
+    for ( i = 0; i < Vec_IntSize(vGlobVars); i++ )
+        Aig_ObjCreateCi( pAig );
+
+    // copy the numbers out and derive interpol for clause
+    vCoreNums = Vec_IntAlloc( Vec_IntSize(vCore) );
+    Proof_ForeachClauseVec( vCore, vClauses, pNode, i )
+    {
+        if ( pNode->partA )
+        {
+            pObj = Aig_ManConst0( pAig );
+            satset_foreach_lit( pNode, Lit, k, 0 )
+                if ( (iVar = Vec_IntEntry(vVarMap, lit_var(Lit))) >= 0 )
+                    pObj = Aig_Or( pAig, pObj, Aig_NotCond(Aig_IthVar(pAig, iVar), lit_sign(Lit)) );
+        }
+        else
+            pObj = Aig_ManConst1( pAig );
+        // remember the interpolant
+        Vec_IntPush( vCoreNums, pNode->Id );
+        pNode->Id = Aig_ObjToLit(pObj);
+    }
+    Vec_IntFree( vVarMap );
+
+    // copy the numbers out and derive interpol for resolvents
+    Proof_ForeachNodeVec( vUsed, vProof, pNode, i )
+    {
+//        satset_print( pNode );
+        assert( pNode->nEnts > 1 );
+        Proof_NodeForeachFaninLeaf( vProof, vClauses, pNode, pFanin, k )
+        {
+            assert( pFanin->Id < 2*Aig_ManObjNumMax(pAig) );
+            if ( k == 0 )
+                pObj = Aig_ObjFromLit( pAig, pFanin->Id );
+            else if ( pNode->pEnts[k] & 2 ) // variable of A
+                pObj = Aig_Or( pAig, pObj, Aig_ObjFromLit(pAig, pFanin->Id) );
+            else
+                pObj = Aig_And( pAig, pObj, Aig_ObjFromLit(pAig, pFanin->Id) );
+        }
+        // remember the interpolant
+        pNode->Id = Aig_ObjToLit(pObj);
+    }
+    // save the result
+//    assert( Proof_NodeHandle(vProof, pNode) == hRoot );
+    Aig_ObjCreateCo( pAig, pObj );
+    Aig_ManCleanup( pAig );
+
+    // move the results back
+    Proof_ForeachClauseVec( vCore, vClauses, pNode, i )
+        pNode->Id = Vec_IntEntry( vCoreNums, i );
+    Proof_ForeachNodeVec( vUsed, vProof, pNode, i )
+        pNode->Id = 0;
+    // cleanup
+    Vec_IntFree( vCore );
+    Vec_IntFree( vUsed );
+    Vec_IntFree( vCoreNums );
+    return pAig;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Computes interpolant of the proof.]
+
+  Description [Aassuming that vars/clause of partA are marked.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word * Sat_ProofInterpolantTruth( sat_solver2 * s, void * pGloVars )
+{
+    Vec_Int_t * vClauses  = (Vec_Int_t *)&s->clauses;
+    Vec_Set_t * vProof    = (Vec_Set_t *)&s->Proofs;
+    Vec_Int_t * vGlobVars = (Vec_Int_t *)pGloVars;
+    Vec_Int_t Roots = { 1, 1, &s->hProofLast }, * vRoots = &Roots;
+    Vec_Int_t * vUsed, * vCore, * vCoreNums, * vVarMap;
+    satset * pNode, * pFanin;
+    Tru_Man_t * pTru;
+    int nVars = Vec_IntSize(vGlobVars);
+    int nWords = (nVars < 6) ? 1 : (1 << (nVars-6));
+    word * pRes = ABC_ALLOC( word, nWords );
+    int i, k, iVar, Lit, Entry, hRoot;
+    assert( nVars > 0 && nVars <= 16 );
+    hRoot = s->hProofLast;
+    if ( hRoot == -1 )
+        return NULL;
+
+    Sat_ProofInterpolantCheckVars( s, vGlobVars );
+
+    // collect visited nodes
+    vUsed = Proof_CollectUsedIter( vProof, vRoots, 1 );
+    // collect core clauses (cleans vUsed and vCore)
+    vCore = Sat_ProofCollectCore( vProof, vUsed, 0 );
+    // vCore arrived in terms of clause handles
+
+    // map variables into their global numbers
+    vVarMap = Vec_IntStartFull( s->size );
+    Vec_IntForEachEntry( vGlobVars, Entry, i )
+        Vec_IntWriteEntry( vVarMap, Entry, i );
+
+    // start the AIG
+    pTru = Tru_ManAlloc( nVars );
+
+    // copy the numbers out and derive interpol for clause
+    vCoreNums = Vec_IntAlloc( Vec_IntSize(vCore) );
+    Proof_ForeachClauseVec( vCore, vClauses, pNode, i )
+    {
+        if ( pNode->partA )
+        {
+//            pObj = Aig_ManConst0( pAig );
+            Tru_ManClear( pRes, nWords );
+            satset_foreach_lit( pNode, Lit, k, 0 )
+                if ( (iVar = Vec_IntEntry(vVarMap, lit_var(Lit))) >= 0 )
+//                    pObj = Aig_Or( pAig, pObj, Aig_NotCond(Aig_IthVar(pAig, iVar), lit_sign(Lit)) );
+                    pRes = Tru_ManOrNotCond( pRes, Tru_ManVar(pTru, iVar), nWords, lit_sign(Lit) );
+        }
+        else
+//            pObj = Aig_ManConst1( pAig );
+            Tru_ManFill( pRes, nWords );
+        // remember the interpolant
+        Vec_IntPush( vCoreNums, pNode->Id );
+//        pNode->Id = Aig_ObjToLit(pObj);
+        pNode->Id = Tru_ManInsert( pTru, pRes );
+    }
+    Vec_IntFree( vVarMap );
+
+    // copy the numbers out and derive interpol for resolvents
+    Proof_ForeachNodeVec( vUsed, vProof, pNode, i )
+    {
+//        satset_print( pNode );
+        assert( pNode->nEnts > 1 );
+        Proof_NodeForeachFaninLeaf( vProof, vClauses, pNode, pFanin, k )
+        {
+//            assert( pFanin->Id < 2*Aig_ManObjNumMax(pAig) );
+//            assert( pFanin->Id <= Tru_ManHandleMax(pTru) );
+            if ( k == 0 )
+//                pObj = Aig_ObjFromLit( pAig, pFanin->Id );
+                pRes = Tru_ManCopyNotCond( pRes, Tru_ManFunc(pTru, pFanin->Id & ~1), nWords, pFanin->Id & 1 );
+            else if ( pNode->pEnts[k] & 2 ) // variable of A
+//                pObj = Aig_Or( pAig, pObj, Aig_ObjFromLit(pAig, pFanin->Id) );
+                pRes = Tru_ManOrNotCond( pRes, Tru_ManFunc(pTru, pFanin->Id & ~1), nWords, pFanin->Id & 1 );
+            else
+//                pObj = Aig_And( pAig, pObj, Aig_ObjFromLit(pAig, pFanin->Id) );
+                pRes = Tru_ManAndNotCond( pRes, Tru_ManFunc(pTru, pFanin->Id & ~1), nWords, pFanin->Id & 1 );
+        }
+        // remember the interpolant
+//        pNode->Id = Aig_ObjToLit(pObj);
+        pNode->Id = Tru_ManInsert( pTru, pRes );
+    }
+    // save the result
+//    assert( Proof_NodeHandle(vProof, pNode) == hRoot );
+//    Aig_ObjCreateCo( pAig, pObj );
+//    Aig_ManCleanup( pAig );
+
+    // move the results back
+    Proof_ForeachClauseVec( vCore, vClauses, pNode, i )
+        pNode->Id = Vec_IntEntry( vCoreNums, i );
+    Proof_ForeachNodeVec( vUsed, vProof, pNode, i )
+        pNode->Id = 0;
+    // cleanup
+    Vec_IntFree( vCore );
+    Vec_IntFree( vUsed );
+    Vec_IntFree( vCoreNums );
+    Tru_ManFree( pTru );
+//    ABC_FREE( pRes );
+    return pRes;
+}
+
+#endif
+
+/**Function*************************************************************
+
+  Synopsis    [Computes UNSAT core.]
+
+  Description [The result is the array of root clause indexes.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Proof_DeriveCore( Vec_Set_t * vProof, int hRoot )
+{
+    Vec_Int_t Roots = { 1, 1, &hRoot }, * vRoots = &Roots;
+    Vec_Int_t * vCore, * vUsed;
+    if ( hRoot == -1 )
+        return NULL;
+    // collect visited clauses
+    vUsed = Proof_CollectUsedIter( vProof, vRoots, 0 );
+    // collect core clauses 
+    vCore = Sat_ProofCollectCore( vProof, vUsed );
+    Vec_IntFree( vUsed );
+    Vec_IntSort( vCore, 1 );
+    return vCore;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bsat/satProof2.h b/abc-build/src/sat/bsat/satProof2.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satProof2.h
@@ -0,0 +1,327 @@
+/**CFile****************************************************************
+
+  FileName    [satProof2.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT solver.]
+
+  Synopsis    [Proof logging.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: satProof2.h,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__sat__bsat__satProof2_h
+#define ABC__sat__bsat__satProof2_h
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "misc/vec/vec.h"
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Prf_Man_t_ Prf_Man_t;
+struct Prf_Man_t_ 
+{
+    int             iFirst;    // first learned clause with proof
+    int             iFirst2;   // first learned clause with proof
+    int             nWords;    // the number of proof words
+    word *          pInfo;     // pointer to the current proof
+    Vec_Wrd_t *     vInfo;     // proof information
+    Vec_Int_t *     vSaved;    // IDs of saved clauses
+    Vec_Int_t *     vId2Pr;    // mapping proof IDs of problem clauses into bitshifts (user's array)
+};
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int    Prf_BitWordNum( int nWidth )                { return (nWidth >> 6) + ((nWidth & 63) > 0);                           }
+static inline int    Prf_ManSize( Prf_Man_t * p )                { return Vec_WrdSize( p->vInfo ) / p->nWords;                           }
+static inline void   Prf_ManClearNewInfo( Prf_Man_t * p )        { int w; for ( w = 0; w < p->nWords; w++ ) Vec_WrdPush( p->vInfo, 0 );  }
+static inline word * Prf_ManClauseInfo( Prf_Man_t * p, int Id )  { return Vec_WrdEntryP( p->vInfo, Id * p->nWords );                     }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DECLARATIONS                        ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Prf_Man_t * Prf_ManAlloc()
+{
+    Prf_Man_t * p;
+    p = ABC_CALLOC( Prf_Man_t, 1 );
+    p->iFirst  = -1;
+    p->iFirst2 = -1;
+    p->vInfo   = Vec_WrdAlloc( 1000 );
+    p->vSaved  = Vec_IntAlloc( 1000 );
+    return p;
+}
+static inline void Prf_ManStop( Prf_Man_t * p )
+{
+    if ( p == NULL )
+        return;
+    Vec_IntFree( p->vSaved );
+    Vec_WrdFree( p->vInfo );
+    ABC_FREE( p );
+}
+static inline void Prf_ManStopP( Prf_Man_t ** p )
+{
+    Prf_ManStop( *p );
+    *p = NULL;
+}
+static inline double Prf_ManMemory( Prf_Man_t * p )
+{
+    return Vec_WrdMemory(p->vInfo) + Vec_IntMemory(p->vSaved) + sizeof(Prf_Man_t);
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Prf_ManRestart( Prf_Man_t * p, Vec_Int_t * vId2Pr, int iFirst, int nWidth )
+{
+    assert( p->iFirst == -1 );
+    p->iFirst = iFirst;
+    p->nWords = Prf_BitWordNum( nWidth );
+    p->vId2Pr = vId2Pr;
+    p->pInfo  = NULL;
+    Vec_WrdClear( p->vInfo );
+}
+static inline void Prf_ManGrow( Prf_Man_t * p, int nWidth )
+{
+    Vec_Wrd_t * vInfoNew;
+    int i, w, nSize, nWordsNew;
+    assert( p->iFirst >= 0 );
+    assert( p->pInfo == NULL );
+    if ( nWidth < 64 * p->nWords )
+        return;
+    // get word count after resizing
+    nWordsNew = Abc_MaxInt( Prf_BitWordNum(nWidth), 2 * p->nWords );
+    // remap the entries
+    nSize = Prf_ManSize( p );
+    vInfoNew = Vec_WrdAlloc( (nSize + 1000) * nWordsNew );
+    for ( i = 0; i < nSize; i++ )
+    {
+        p->pInfo = Prf_ManClauseInfo( p, i );
+        for ( w = 0; w < p->nWords; w++ )
+            Vec_WrdPush( vInfoNew, p->pInfo[w] );
+        for ( ; w < nWordsNew; w++ )
+            Vec_WrdPush( vInfoNew, 0 );
+    }
+    Vec_WrdFree( p->vInfo );
+    p->vInfo = vInfoNew;
+    p->nWords = nWordsNew;
+    p->pInfo = NULL;
+
+}
+static inline void Prf_ManShrink( Prf_Man_t * p, int iClause )
+{
+    assert( p->iFirst >= 0 );
+    assert( iClause - p->iFirst >= 0 );
+    assert( iClause - p->iFirst < Prf_ManSize(p) ); 
+    Vec_WrdShrink( p->vInfo, (iClause - p->iFirst) * p->nWords );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Prf_ManAddSaved( Prf_Man_t * p, int i, int iNew )
+{
+    assert( p->iFirst >= 0 );
+    if ( i < p->iFirst )
+        return;
+    if ( Vec_IntSize(p->vSaved) == 0 )
+    {
+        assert( p->iFirst2 == -1 );
+        p->iFirst2 = iNew;
+    }
+    Vec_IntPush( p->vSaved, i );
+}
+static inline void Prf_ManCompact( Prf_Man_t * p, int iNew )
+{
+    int i, w, k = 0, Entry, nSize;
+    assert( p->iFirst >= 0 );
+    assert( p->pInfo == NULL );
+    nSize = Prf_ManSize( p );
+    Vec_IntForEachEntry( p->vSaved, Entry, i )
+    {
+        assert( Entry - p->iFirst >= 0 && Entry - p->iFirst < nSize );
+        p->pInfo = Prf_ManClauseInfo( p, Entry - p->iFirst );
+        for ( w = 0; w < p->nWords; w++ )
+            Vec_WrdWriteEntry( p->vInfo, k++, p->pInfo[w] );
+    }
+    Vec_WrdShrink( p->vInfo, k );
+    Vec_IntClear( p->vSaved );
+    p->pInfo = NULL;
+    // update first
+    if ( p->iFirst2 == -1 )
+        p->iFirst = iNew;
+    else
+        p->iFirst = p->iFirst2;
+    p->iFirst2 = -1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Prf_ManChainResolve( Prf_Man_t * p, clause * c )
+{
+    assert( p->iFirst >= 0 );
+    assert( p->pInfo != NULL );
+    // add to proof info
+    if ( c->lrn ) // learned clause
+    {
+        if ( clause_id(c) >= p->iFirst )
+        {
+            word * pProofStart;
+            int w;
+            assert( clause_id(c) - p->iFirst >= 0 );
+            assert( clause_id(c) - p->iFirst < Prf_ManSize(p) ); 
+            pProofStart = Prf_ManClauseInfo( p, clause_id(c) - p->iFirst );
+            for ( w = 0; w < p->nWords; w++ )
+                p->pInfo[w] |= pProofStart[w];
+        }
+    }
+    else // problem clause
+    {  
+        if ( clause_id(c) >= 0 ) // has proof ID
+        {
+            int Entry;
+            if ( p->vId2Pr == NULL )
+                Entry = clause_id(c);
+            else
+                Entry = Vec_IntEntry( p->vId2Pr, clause_id(c) );
+            if ( Entry >= 0 )
+            {
+                assert( Entry < 64 * p->nWords );
+                Abc_InfoSetBit( (unsigned *)p->pInfo, Entry );
+            }
+        }
+    }
+}
+static inline void Prf_ManChainStart( Prf_Man_t * p, clause * c )
+{
+    assert( p->iFirst >= 0 );
+    // prepare info for new clause
+    Prf_ManClearNewInfo( p );
+    // get pointer to the proof
+    assert( p->pInfo == NULL );
+    p->pInfo = Prf_ManClauseInfo( p, Prf_ManSize(p)-1 );
+    // add to proof info
+    Prf_ManChainResolve( p, c );
+}
+static inline int Prf_ManChainStop( Prf_Man_t * p )
+{
+    assert( p->pInfo != NULL );
+    p->pInfo = NULL;
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Vec_Int_t * Prf_ManUnsatCore( Prf_Man_t * p )
+{
+    Vec_Int_t * vCore;
+    int i, Entry;
+    assert( p->iFirst >= 0 );
+    assert( p->pInfo == NULL );
+    assert( Prf_ManSize(p) > 0 );
+    vCore = Vec_IntAlloc( 64 * p->nWords );
+    p->pInfo = Prf_ManClauseInfo( p, Prf_ManSize(p)-1 );
+    if ( p->vId2Pr == NULL )
+    {
+        for ( i = 0; i < 64 * p->nWords; i++ )
+            if ( Abc_InfoHasBit( (unsigned *)p->pInfo, i ) )
+                Vec_IntPush( vCore, i );
+    }
+    else
+    {
+        Vec_IntForEachEntry( p->vId2Pr, Entry, i )
+        {
+            if ( Entry < 0 )
+                continue;
+            assert( Entry < 64 * p->nWords );
+            if ( Abc_InfoHasBit( (unsigned *)p->pInfo, Entry ) )
+                Vec_IntPush( vCore, i );
+        }
+    }
+    p->pInfo = NULL;
+    Vec_IntSort( vCore, 1 );
+    return vCore;
+}
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/sat/bsat/satSolver.c b/abc-build/src/sat/bsat/satSolver.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satSolver.c
@@ -0,0 +1,1961 @@
+/**************************************************************************************************
+MiniSat -- Copyright (c) 2005, Niklas Sorensson
+http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+// Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+
+#include "satSolver.h"
+#include "satStore.h"
+
+ABC_NAMESPACE_IMPL_START
+
+#define SAT_USE_ANALYZE_FINAL
+
+//=================================================================================================
+// Debug:
+
+//#define VERBOSEDEBUG
+
+// For derivation output (verbosity level 2)
+#define L_IND    "%-*d"
+#define L_ind    sat_solver_dl(s)*2+2,sat_solver_dl(s)
+#define L_LIT    "%sx%d"
+#define L_lit(p) lit_sign(p)?"~":"", (lit_var(p))
+
+// Just like 'assert()' but expression will be evaluated in the release version as well.
+static inline void check(int expr) { assert(expr); }
+
+static void printlits(lit* begin, lit* end)
+{
+    int i;
+    for (i = 0; i < end - begin; i++)
+        printf(L_LIT" ",L_lit(begin[i]));
+}
+
+//=================================================================================================
+// Random numbers:
+
+
+// Returns a random float 0 <= x < 1. Seed must never be 0.
+static inline double drand(double* seed) {
+    int q;
+    *seed *= 1389796;
+    q = (int)(*seed / 2147483647);
+    *seed -= (double)q * 2147483647;
+    return *seed / 2147483647; }
+
+
+// Returns a random integer 0 <= x < size. Seed must never be 0.
+static inline int irand(double* seed, int size) {
+    return (int)(drand(seed) * size); }
+
+
+//=================================================================================================
+// Variable datatype + minor functions:
+
+static const int var0  = 1;
+static const int var1  = 0;
+static const int varX  = 3;
+
+struct varinfo_t
+{
+    unsigned val    :  2;  // variable value 
+    unsigned pol    :  1;  // last polarity
+    unsigned tag    :  1;  // conflict analysis tag
+    unsigned lev    : 28;  // variable level
+};
+
+static inline int     var_level     (sat_solver* s, int v)            { return s->levels[v];   }
+static inline int     var_value     (sat_solver* s, int v)            { return s->assigns[v];  }
+static inline int     var_polar     (sat_solver* s, int v)            { return s->polarity[v]; }
+
+static inline void    var_set_level (sat_solver* s, int v, int lev)   { s->levels[v] = lev;    }
+static inline void    var_set_value (sat_solver* s, int v, int val)   { s->assigns[v] = val;   }
+static inline void    var_set_polar (sat_solver* s, int v, int pol)   { s->polarity[v] = pol;  }
+
+// variable tags
+static inline int     var_tag       (sat_solver* s, int v)            { return s->tags[v]; }
+static inline void    var_set_tag   (sat_solver* s, int v, int tag)   { 
+    assert( tag > 0 && tag < 16 );
+    if ( s->tags[v] == 0 )
+        veci_push( &s->tagged, v );
+    s->tags[v] = tag;                           
+}
+static inline void    var_add_tag   (sat_solver* s, int v, int tag)   { 
+    assert( tag > 0 && tag < 16 );
+    if ( s->tags[v] == 0 )
+        veci_push( &s->tagged, v );
+    s->tags[v] |= tag;                           
+}
+static inline void    solver2_clear_tags(sat_solver* s, int start)    { 
+    int i, * tagged = veci_begin(&s->tagged);
+    for (i = start; i < veci_size(&s->tagged); i++)
+        s->tags[tagged[i]] = 0;
+    veci_resize(&s->tagged,start);
+}
+
+int sat_solver_get_var_value(sat_solver* s, int v)
+{
+    if ( var_value(s, v) == var0 )
+        return l_False;
+    if ( var_value(s, v) == var1 )
+        return l_True;
+    if ( var_value(s, v) == varX )
+        return l_Undef;
+    assert( 0 );
+    return 0;
+}
+
+//=================================================================================================
+// Simple helpers:
+
+static inline int      sat_solver_dl(sat_solver* s)                { return veci_size(&s->trail_lim); }
+static inline veci*    sat_solver_read_wlist(sat_solver* s, lit l) { return &s->wlists[l];            }
+
+//=================================================================================================
+// Variable order functions:
+
+static inline void order_update(sat_solver* s, int v) // updateorder
+{
+    int*    orderpos = s->orderpos;
+    int*    heap     = veci_begin(&s->order);
+    int     i        = orderpos[v];
+    int     x        = heap[i];
+    int     parent   = (i - 1) / 2;
+
+    assert(s->orderpos[v] != -1);
+
+    while (i != 0 && s->activity[x] > s->activity[heap[parent]]){
+        heap[i]           = heap[parent];
+        orderpos[heap[i]] = i;
+        i                 = parent;
+        parent            = (i - 1) / 2;
+    }
+    heap[i]     = x;
+    orderpos[x] = i;
+}
+
+static inline void order_assigned(sat_solver* s, int v) 
+{
+}
+
+static inline void order_unassigned(sat_solver* s, int v) // undoorder
+{
+    int* orderpos = s->orderpos;
+    if (orderpos[v] == -1){
+        orderpos[v] = veci_size(&s->order);
+        veci_push(&s->order,v);
+        order_update(s,v);
+//printf( "+%d ", v );
+    }
+}
+
+static inline int  order_select(sat_solver* s, float random_var_freq) // selectvar
+{
+    int*      heap     = veci_begin(&s->order);
+    int*      orderpos = s->orderpos;
+    // Random decision:
+    if (drand(&s->random_seed) < random_var_freq){
+        int next = irand(&s->random_seed,s->size);
+        assert(next >= 0 && next < s->size);
+        if (var_value(s, next) == varX)
+            return next;
+    }
+    // Activity based decision:
+    while (veci_size(&s->order) > 0){
+        int    next  = heap[0];
+        int    size  = veci_size(&s->order)-1;
+        int    x     = heap[size];
+        veci_resize(&s->order,size);
+        orderpos[next] = -1;
+        if (size > 0){
+            int    i     = 0;
+            int    child = 1;
+            while (child < size){
+                if (child+1 < size && s->activity[heap[child]] < s->activity[heap[child+1]])
+                    child++;
+                assert(child < size);
+                if (s->activity[x] >= s->activity[heap[child]])
+                    break;
+                heap[i]           = heap[child];
+                orderpos[heap[i]] = i;
+                i                 = child;
+                child             = 2 * child + 1;
+            }
+            heap[i]           = x;
+            orderpos[heap[i]] = i;
+        }
+        if (var_value(s, next) == varX)
+            return next;
+    }
+    return var_Undef;
+}
+
+//=================================================================================================
+// Activity functions:
+
+#ifdef USE_FLOAT_ACTIVITY
+
+static inline void act_var_rescale(sat_solver* s)  {
+    double* activity = s->activity;
+    int i;
+    for (i = 0; i < s->size; i++)
+        activity[i] *= 1e-100;
+    s->var_inc *= 1e-100;
+}
+static inline void act_clause_rescale(sat_solver* s) {
+//    static abctime Total = 0;
+    clause** cs = (clause**)veci_begin(&s->learnts);
+    int i;//, clk = Abc_Clock();
+    for (i = 0; i < veci_size(&s->learnts); i++){
+        float a = clause_activity(cs[i]);
+        clause_setactivity(cs[i], a * (float)1e-20);
+    }
+    s->cla_inc *= (float)1e-20;
+
+    Total += Abc_Clock() - clk;
+//    printf( "Rescaling...   Cla inc = %10.3f  Conf = %10d   ", s->cla_inc,  s->stats.conflicts );
+//    Abc_PrintTime( 1, "Time", Total );
+}
+static inline void act_var_bump(sat_solver* s, int v) {
+    s->activity[v] += s->var_inc;
+    if (s->activity[v] > 1e100)
+        act_var_rescale(s);
+    if (s->orderpos[v] != -1)
+        order_update(s,v);
+}
+static inline void act_var_bump_global(sat_solver* s, int v) {
+    if ( !s->pGlobalVars )
+        return;
+    s->activity[v] += (s->var_inc * 3.0 * s->pGlobalVars[v]);
+    if (s->activity[v] > 1e100)
+        act_var_rescale(s);
+    if (s->orderpos[v] != -1)
+        order_update(s,v);
+}
+static inline void act_var_bump_factor(sat_solver* s, int v) {
+    if ( !s->factors )
+        return;
+    s->activity[v] += (s->var_inc * s->factors[v]);
+    if (s->activity[v] > 1e100)
+        act_var_rescale(s);
+    if (s->orderpos[v] != -1)
+        order_update(s,v);
+}
+static inline void act_clause_bump(sat_solver* s, clause *c) {
+    float a = clause_activity(c) + s->cla_inc;
+    clause_setactivity(c,a);
+    if (a > 1e20) act_clause_rescale(s);
+}
+static inline void act_var_decay(sat_solver* s)    { s->var_inc *= s->var_decay; }
+static inline void act_clause_decay(sat_solver* s) { s->cla_inc *= s->cla_decay; }
+
+#else
+
+static inline void act_var_rescale(sat_solver* s) {
+    unsigned* activity = s->activity;
+    int i;
+    for (i = 0; i < s->size; i++)
+        activity[i] >>= 19;
+    s->var_inc >>= 19;
+    s->var_inc = Abc_MaxInt( s->var_inc, (1<<4) );
+}
+
+static inline void act_clause_rescale(sat_solver* s) {
+    static abctime Total = 0;
+    abctime clk = Abc_Clock();
+    unsigned* activity = (unsigned *)veci_begin(&s->act_clas);
+    int i;
+    for (i = 0; i < veci_size(&s->act_clas); i++)
+        activity[i] >>= 14;
+    s->cla_inc >>= 14;
+    s->cla_inc = Abc_MaxInt( s->cla_inc, (1<<10) );
+    Total += Abc_Clock() - clk;
+//    printf( "Rescaling...   Cla inc = %5d  Conf = %10d   ", s->cla_inc,  s->stats.conflicts );
+//    Abc_PrintTime( 1, "Time", Total );
+}
+
+static inline void act_var_bump(sat_solver* s, int v) {
+    s->activity[v] += s->var_inc;
+    if (s->activity[v] & 0x80000000)
+        act_var_rescale(s);
+    if (s->orderpos[v] != -1)
+        order_update(s,v);
+}
+static inline void act_var_bump_global(sat_solver* s, int v) {
+    if ( !s->pGlobalVars )
+        return;
+    s->activity[v] += (int)(s->var_inc * 3 * s->pGlobalVars[v]);
+    if (s->activity[v] & 0x80000000)
+        act_var_rescale(s);
+    if (s->orderpos[v] != -1)
+        order_update(s,v);
+}
+static inline void act_var_bump_factor(sat_solver* s, int v) {
+    if ( !s->factors )
+        return;
+    s->activity[v] += (int)(s->var_inc * s->factors[v]);
+    if (s->activity[v] & 0x80000000)
+        act_var_rescale(s);
+    if (s->orderpos[v] != -1)
+        order_update(s,v);
+}
+
+static inline void act_clause_bump(sat_solver* s, clause*c) {
+    unsigned* act = (unsigned *)veci_begin(&s->act_clas) + c->lits[c->size];
+    *act += s->cla_inc;
+    if ( *act & 0x80000000 )
+        act_clause_rescale(s);
+}
+
+static inline void act_var_decay(sat_solver* s)    { s->var_inc += (s->var_inc >>  4); }
+static inline void act_clause_decay(sat_solver* s) { s->cla_inc += (s->cla_inc >> 10); }
+
+#endif
+
+
+//=================================================================================================
+// Sorting functions (sigh):
+
+static inline void selectionsort(void** array, int size, int(*comp)(const void *, const void *))
+{
+    int     i, j, best_i;
+    void*   tmp;
+
+    for (i = 0; i < size-1; i++){
+        best_i = i;
+        for (j = i+1; j < size; j++){
+            if (comp(array[j], array[best_i]) < 0)
+                best_i = j;
+        }
+        tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp;
+    }
+}
+
+static void sortrnd(void** array, int size, int(*comp)(const void *, const void *), double* seed)
+{
+    if (size <= 15)
+        selectionsort(array, size, comp);
+
+    else{
+        void*       pivot = array[irand(seed, size)];
+        void*       tmp;
+        int         i = -1;
+        int         j = size;
+
+        for(;;){
+            do i++; while(comp(array[i], pivot)<0);
+            do j--; while(comp(pivot, array[j])<0);
+
+            if (i >= j) break;
+
+            tmp = array[i]; array[i] = array[j]; array[j] = tmp;
+        }
+
+        sortrnd(array    , i     , comp, seed);
+        sortrnd(&array[i], size-i, comp, seed);
+    }
+}
+
+//=================================================================================================
+// Clause functions:
+
+static inline int sat_clause_compute_lbd( sat_solver* s, clause* c )
+{
+    int i, lev, minl = 0, lbd = 0;
+    for (i = 0; i < (int)c->size; i++)
+    {
+        lev = var_level(s, lit_var(c->lits[i]));
+        if ( !(minl & (1 << (lev & 31))) )
+        {
+            minl |= 1 << (lev & 31);
+            lbd++;
+//            printf( "%d ", lev );
+        }
+    }
+//    printf( " -> %d\n", lbd );
+    return lbd;
+}
+
+/* pre: size > 1 && no variable occurs twice
+ */
+int sat_solver_clause_new(sat_solver* s, lit* begin, lit* end, int learnt)
+{
+    int fUseBinaryClauses = 1;
+    int size;
+    clause* c;
+    int h;
+
+    assert(end - begin > 1);
+    assert(learnt >= 0 && learnt < 2);
+    size           = end - begin;
+
+    // do not allocate memory for the two-literal problem clause
+    if ( fUseBinaryClauses && size == 2 && !learnt )
+    {
+        veci_push(sat_solver_read_wlist(s,lit_neg(begin[0])),(clause_from_lit(begin[1])));
+        veci_push(sat_solver_read_wlist(s,lit_neg(begin[1])),(clause_from_lit(begin[0])));
+        s->stats.clauses++;
+        s->stats.clauses_literals += size;
+        return 0;
+    }
+
+    // create new clause
+//    h = Vec_SetAppend( &s->Mem, NULL, size + learnt + 1 + 1 ) << 1;
+    h = Sat_MemAppend( &s->Mem, begin, size, learnt, 0 );
+    assert( !(h & 1) );
+    if ( s->hLearnts == -1 && learnt )
+        s->hLearnts = h;
+    if (learnt)
+    {
+        c = clause_read( s, h );
+        c->lbd = sat_clause_compute_lbd( s, c );
+        assert( clause_id(c) == veci_size(&s->act_clas) );
+//        veci_push(&s->learned, h);
+//        act_clause_bump(s,clause_read(s, h));
+        veci_push(&s->act_clas, (1<<10));
+        s->stats.learnts++;
+        s->stats.learnts_literals += size;
+    }
+    else
+    {
+        s->stats.clauses++;
+        s->stats.clauses_literals += size;
+    }
+
+    assert(begin[0] >= 0);
+    assert(begin[0] < s->size*2);
+    assert(begin[1] >= 0);
+    assert(begin[1] < s->size*2);
+
+    assert(lit_neg(begin[0]) < s->size*2);
+    assert(lit_neg(begin[1]) < s->size*2);
+
+    //veci_push(sat_solver_read_wlist(s,lit_neg(begin[0])),c);
+    //veci_push(sat_solver_read_wlist(s,lit_neg(begin[1])),c);
+    veci_push(sat_solver_read_wlist(s,lit_neg(begin[0])),(size > 2 ? h : clause_from_lit(begin[1])));
+    veci_push(sat_solver_read_wlist(s,lit_neg(begin[1])),(size > 2 ? h : clause_from_lit(begin[0])));
+
+    return h;
+}
+
+
+//=================================================================================================
+// Minor (solver) functions:
+
+static inline int sat_solver_enqueue(sat_solver* s, lit l, int from)
+{
+    int v  = lit_var(l);
+    if ( s->pFreqs[v] == 0 )
+//    {
+        s->pFreqs[v] = 1;
+//        s->nVarUsed++;
+//    }
+
+#ifdef VERBOSEDEBUG
+    printf(L_IND"enqueue("L_LIT")\n", L_ind, L_lit(l));
+#endif
+    if (var_value(s, v) != varX)
+        return var_value(s, v) == lit_sign(l);
+    else{
+/*
+        if ( s->pCnfFunc )
+        {
+            if ( lit_sign(l) )
+            {
+                if ( (s->loads[v] & 1) == 0 )
+                {
+                    s->loads[v] ^= 1;
+                    s->pCnfFunc( s->pCnfMan, l );
+                }
+            }
+            else
+            {
+                if ( (s->loads[v] & 2) == 0 )
+                {
+                    s->loads[v] ^= 2;
+                    s->pCnfFunc( s->pCnfMan, l );
+                }
+            }
+        }
+*/
+        // New fact -- store it.
+#ifdef VERBOSEDEBUG
+        printf(L_IND"bind("L_LIT")\n", L_ind, L_lit(l));
+#endif
+        var_set_value(s, v, lit_sign(l));
+        var_set_level(s, v, sat_solver_dl(s));
+        s->reasons[v] = from;
+        s->trail[s->qtail++] = l;
+        order_assigned(s, v);
+        return true;
+    }
+}
+
+
+static inline int sat_solver_assume(sat_solver* s, lit l){
+    assert(s->qtail == s->qhead);
+    assert(var_value(s, lit_var(l)) == varX);
+#ifdef VERBOSEDEBUG
+    printf(L_IND"assume("L_LIT")  ", L_ind, L_lit(l));
+    printf( "act = %.20f\n", s->activity[lit_var(l)] );
+#endif
+    veci_push(&s->trail_lim,s->qtail);
+    return sat_solver_enqueue(s,l,0);
+}
+
+
+static void sat_solver_canceluntil(sat_solver* s, int level) {
+    int      bound;
+    int      lastLev;
+    int      c;
+    
+    if (sat_solver_dl(s) <= level)
+        return;
+
+    assert( veci_size(&s->trail_lim) > 0 );
+    bound   = (veci_begin(&s->trail_lim))[level];
+    lastLev = (veci_begin(&s->trail_lim))[veci_size(&s->trail_lim)-1];
+
+    ////////////////////////////////////////
+    // added to cancel all assignments
+//    if ( level == -1 )
+//        bound = 0;
+    ////////////////////////////////////////
+
+    for (c = s->qtail-1; c >= bound; c--) {
+        int     x  = lit_var(s->trail[c]);
+        var_set_value(s, x, varX);
+        s->reasons[x] = 0;
+        if ( c < lastLev )
+            var_set_polar( s, x, !lit_sign(s->trail[c]) );
+    }
+
+    for (c = s->qhead-1; c >= bound; c--)
+        order_unassigned(s,lit_var(s->trail[c]));
+
+    s->qhead = s->qtail = bound;
+    veci_resize(&s->trail_lim,level);
+}
+
+static void sat_solver_canceluntil_rollback(sat_solver* s, int NewBound) {
+    int      c, x;
+   
+    assert( sat_solver_dl(s) == 0 );
+    assert( s->qtail == s->qhead );
+    assert( s->qtail >= NewBound );
+
+    for (c = s->qtail-1; c >= NewBound; c--) 
+    {
+        x = lit_var(s->trail[c]);
+        var_set_value(s, x, varX);
+        s->reasons[x] = 0;
+    }
+
+    for (c = s->qhead-1; c >= NewBound; c--)
+        order_unassigned(s,lit_var(s->trail[c]));
+
+    s->qhead = s->qtail = NewBound;
+}
+
+static void sat_solver_record(sat_solver* s, veci* cls)
+{
+    lit*    begin = veci_begin(cls);
+    lit*    end   = begin + veci_size(cls);
+    int     h     = (veci_size(cls) > 1) ? sat_solver_clause_new(s,begin,end,1) : 0;
+    sat_solver_enqueue(s,*begin,h);
+    assert(veci_size(cls) > 0);
+    if ( h == 0 )
+        veci_push( &s->unit_lits, *begin );
+
+    ///////////////////////////////////
+    // add clause to internal storage
+    if ( s->pStore )
+    {
+        int RetValue = Sto_ManAddClause( (Sto_Man_t *)s->pStore, begin, end );
+        assert( RetValue );
+        (void) RetValue;
+    }
+    ///////////////////////////////////
+/*
+    if (h != 0) {
+        act_clause_bump(s,clause_read(s, h));
+        s->stats.learnts++;
+        s->stats.learnts_literals += veci_size(cls);
+    }
+*/
+}
+
+int sat_solver_count_assigned(sat_solver* s)
+{
+    // count top-level assignments
+    int i, Count = 0;
+    assert(sat_solver_dl(s) == 0);
+    for ( i = 0; i < s->size; i++ )
+        if (var_value(s, i) != varX)
+            Count++;
+    return Count;
+}
+
+static double sat_solver_progress(sat_solver* s)
+{
+    int     i;
+    double  progress = 0;
+    double  F        = 1.0 / s->size;
+    for (i = 0; i < s->size; i++)
+        if (var_value(s, i) != varX)
+            progress += pow(F, var_level(s, i));
+    return progress / s->size;
+}
+
+//=================================================================================================
+// Major methods:
+
+static int sat_solver_lit_removable(sat_solver* s, int x, int minl)
+{
+    int      top     = veci_size(&s->tagged);
+
+    assert(s->reasons[x] != 0);
+    veci_resize(&s->stack,0);
+    veci_push(&s->stack,x);
+
+    while (veci_size(&s->stack)){
+        int v = veci_pop(&s->stack);
+        assert(s->reasons[v] != 0);
+        if (clause_is_lit(s->reasons[v])){
+            v = lit_var(clause_read_lit(s->reasons[v]));
+            if (!var_tag(s,v) && var_level(s, v)){
+                if (s->reasons[v] != 0 && ((1 << (var_level(s, v) & 31)) & minl)){
+                    veci_push(&s->stack,v);
+                    var_set_tag(s, v, 1);
+                }else{
+                    solver2_clear_tags(s, top);
+                    return 0;
+                }
+            }
+        }else{
+            clause* c = clause_read(s, s->reasons[v]);
+            lit* lits = clause_begin(c);
+            int  i;
+            for (i = 1; i < clause_size(c); i++){
+                int v = lit_var(lits[i]);
+                if (!var_tag(s,v) && var_level(s, v)){
+                    if (s->reasons[v] != 0 && ((1 << (var_level(s, v) & 31)) & minl)){
+                        veci_push(&s->stack,lit_var(lits[i]));
+                        var_set_tag(s, v, 1);
+                    }else{
+                        solver2_clear_tags(s, top);
+                        return 0;
+                    }
+                }
+            }
+        }
+    }
+    return 1;
+}
+
+
+/*_________________________________________________________________________________________________
+|
+|  analyzeFinal : (p : Lit)  ->  [void]
+|  
+|  Description:
+|    Specialized analysis procedure to express the final conflict in terms of assumptions.
+|    Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and
+|    stores the result in 'out_conflict'.
+|________________________________________________________________________________________________@*/
+/*
+void Solver::analyzeFinal(Clause* confl, bool skip_first)
+{
+    // -- NOTE! This code is relatively untested. Please report bugs!
+    conflict.clear();
+    if (root_level == 0) return;
+
+    vec<char>& seen  = analyze_seen;
+    for (int i = skip_first ? 1 : 0; i < confl->size(); i++){
+        Var x = var((*confl)[i]);
+        if (level[x] > 0)
+            seen[x] = 1;
+    }
+
+    int start = (root_level >= trail_lim.size()) ? trail.size()-1 : trail_lim[root_level];
+    for (int i = start; i >= trail_lim[0]; i--){
+        Var     x = var(trail[i]);
+        if (seen[x]){
+            GClause r = reason[x];
+            if (r == GClause_NULL){
+                assert(level[x] > 0);
+                conflict.push(~trail[i]);
+            }else{
+                if (r.isLit()){
+                    Lit p = r.lit();
+                    if (level[var(p)] > 0)
+                        seen[var(p)] = 1;
+                }else{
+                    Clause& c = *r.clause();
+                    for (int j = 1; j < c.size(); j++)
+                        if (level[var(c[j])] > 0)
+                            seen[var(c[j])] = 1;
+                }
+            }
+            seen[x] = 0;
+        }
+    }
+}
+*/
+
+#ifdef SAT_USE_ANALYZE_FINAL
+
+static void sat_solver_analyze_final(sat_solver* s, int hConf, int skip_first)
+{
+    clause* conf = clause_read(s, hConf);
+    int i, j, start;
+    veci_resize(&s->conf_final,0);
+    if ( s->root_level == 0 )
+        return;
+    assert( veci_size(&s->tagged) == 0 );
+//    assert( s->tags[lit_var(p)] == l_Undef );
+//    s->tags[lit_var(p)] = l_True;
+    for (i = skip_first ? 1 : 0; i < clause_size(conf); i++)
+    {
+        int x = lit_var(clause_begin(conf)[i]);
+        if (var_level(s, x) > 0)
+            var_set_tag(s, x, 1);
+    }
+
+    start = (s->root_level >= veci_size(&s->trail_lim))? s->qtail-1 : (veci_begin(&s->trail_lim))[s->root_level];
+    for (i = start; i >= (veci_begin(&s->trail_lim))[0]; i--){
+        int x = lit_var(s->trail[i]);
+        if (var_tag(s,x)){
+            if (s->reasons[x] == 0){
+                assert(var_level(s, x) > 0);
+                veci_push(&s->conf_final,lit_neg(s->trail[i]));
+            }else{
+                if (clause_is_lit(s->reasons[x])){
+                    lit q = clause_read_lit(s->reasons[x]);
+                    assert(lit_var(q) >= 0 && lit_var(q) < s->size);
+                    if (var_level(s, lit_var(q)) > 0)
+                        var_set_tag(s, lit_var(q), 1);
+                }
+                else{
+                    clause* c = clause_read(s, s->reasons[x]);
+                    int* lits = clause_begin(c);
+                    for (j = 1; j < clause_size(c); j++)
+                        if (var_level(s, lit_var(lits[j])) > 0)
+                            var_set_tag(s, lit_var(lits[j]), 1);
+                }
+            }
+        }
+    }
+    solver2_clear_tags(s,0);
+}
+
+#endif
+
+static void sat_solver_analyze(sat_solver* s, int h, veci* learnt)
+{
+    lit*     trail   = s->trail;
+    int      cnt     = 0;
+    lit      p       = lit_Undef;
+    int      ind     = s->qtail-1;
+    lit*     lits;
+    int      i, j, minl;
+    veci_push(learnt,lit_Undef);
+    do{
+        assert(h != 0);
+        if (clause_is_lit(h)){
+            int x = lit_var(clause_read_lit(h));
+            if (var_tag(s, x) == 0 && var_level(s, x) > 0){
+                var_set_tag(s, x, 1);
+                act_var_bump(s,x);
+                if (var_level(s, x) == sat_solver_dl(s))
+                    cnt++;
+                else
+                    veci_push(learnt,clause_read_lit(h));
+            }
+        }else{
+            clause* c = clause_read(s, h);
+            if (clause_learnt(c))
+                act_clause_bump(s,c);
+            lits = clause_begin(c);
+            //printlits(lits,lits+clause_size(c)); printf("\n");
+            for (j = (p == lit_Undef ? 0 : 1); j < clause_size(c); j++){
+                int x = lit_var(lits[j]);
+                if (var_tag(s, x) == 0 && var_level(s, x) > 0){
+                    var_set_tag(s, x, 1);
+                    act_var_bump(s,x);
+                    // bump variables propaged by the LBD=2 clause
+//                    if ( s->reasons[x] && clause_read(s, s->reasons[x])->lbd <= 2 )
+//                        act_var_bump(s,x);
+                    if (var_level(s,x) == sat_solver_dl(s))
+                        cnt++;
+                    else
+                        veci_push(learnt,lits[j]);
+                }
+            }
+        }
+
+        while ( !var_tag(s, lit_var(trail[ind--])) );
+
+        p = trail[ind+1];
+        h = s->reasons[lit_var(p)];
+        cnt--;
+
+    }while (cnt > 0);
+
+    *veci_begin(learnt) = lit_neg(p);
+
+    lits = veci_begin(learnt);
+    minl = 0;
+    for (i = 1; i < veci_size(learnt); i++){
+        int lev = var_level(s, lit_var(lits[i]));
+        minl    |= 1 << (lev & 31);
+    }
+
+    // simplify (full)
+    for (i = j = 1; i < veci_size(learnt); i++){
+        if (s->reasons[lit_var(lits[i])] == 0 || !sat_solver_lit_removable(s,lit_var(lits[i]),minl))
+            lits[j++] = lits[i];
+    }
+
+    // update size of learnt + statistics
+    veci_resize(learnt,j);
+    s->stats.tot_literals += j;
+
+
+    // clear tags
+    solver2_clear_tags(s,0);
+
+#ifdef DEBUG
+    for (i = 0; i < s->size; i++)
+        assert(!var_tag(s, i));
+#endif
+
+#ifdef VERBOSEDEBUG
+    printf(L_IND"Learnt {", L_ind);
+    for (i = 0; i < veci_size(learnt); i++) printf(" "L_LIT, L_lit(lits[i]));
+#endif
+    if (veci_size(learnt) > 1){
+        int max_i = 1;
+        int max   = var_level(s, lit_var(lits[1]));
+        lit tmp;
+
+        for (i = 2; i < veci_size(learnt); i++)
+            if (var_level(s, lit_var(lits[i])) > max){
+                max   = var_level(s, lit_var(lits[i]));
+                max_i = i;
+            }
+
+        tmp         = lits[1];
+        lits[1]     = lits[max_i];
+        lits[max_i] = tmp;
+    }
+#ifdef VERBOSEDEBUG
+    {
+        int lev = veci_size(learnt) > 1 ? var_level(s, lit_var(lits[1])) : 0;
+        printf(" } at level %d\n", lev);
+    }
+#endif
+}
+
+//#define TEST_CNF_LOAD
+
+int sat_solver_propagate(sat_solver* s)
+{
+    int     hConfl = 0;
+    lit*    lits;
+    lit false_lit;
+
+    //printf("sat_solver_propagate\n");
+    while (hConfl == 0 && s->qtail - s->qhead > 0){
+        lit p = s->trail[s->qhead++];
+
+#ifdef TEST_CNF_LOAD
+        int v = lit_var(p);
+        if ( s->pCnfFunc )
+        {
+            if ( lit_sign(p) )
+            {
+                if ( (s->loads[v] & 1) == 0 )
+                {
+                    s->loads[v] ^= 1;
+                    s->pCnfFunc( s->pCnfMan, p );
+                }
+            }
+            else
+            {
+                if ( (s->loads[v] & 2) == 0 )
+                {
+                    s->loads[v] ^= 2;
+                    s->pCnfFunc( s->pCnfMan, p );
+                }
+            }
+        }
+        {
+#endif
+
+        veci* ws    = sat_solver_read_wlist(s,p);
+        int*  begin = veci_begin(ws);
+        int*  end   = begin + veci_size(ws);
+        int*i, *j;
+
+        s->stats.propagations++;
+//        s->simpdb_props--;
+
+        //printf("checking lit %d: "L_LIT"\n", veci_size(ws), L_lit(p));
+        for (i = j = begin; i < end; ){
+            if (clause_is_lit(*i)){
+
+                int Lit = clause_read_lit(*i);
+                if (var_value(s, lit_var(Lit)) == lit_sign(Lit)){
+                    *j++ = *i++;
+                    continue;
+                }
+
+                *j++ = *i;
+                if (!sat_solver_enqueue(s,clause_read_lit(*i),clause_from_lit(p))){
+                    hConfl = s->hBinary;
+                    (clause_begin(s->binary))[1] = lit_neg(p);
+                    (clause_begin(s->binary))[0] = clause_read_lit(*i++);
+                    // Copy the remaining watches:
+                    while (i < end)
+                        *j++ = *i++;
+                }
+            }else{
+
+                clause* c = clause_read(s,*i);
+                lits = clause_begin(c);
+
+                // Make sure the false literal is data[1]:
+                false_lit = lit_neg(p);
+                if (lits[0] == false_lit){
+                    lits[0] = lits[1];
+                    lits[1] = false_lit;
+                }
+                assert(lits[1] == false_lit);
+
+                // If 0th watch is true, then clause is already satisfied.
+                if (var_value(s, lit_var(lits[0])) == lit_sign(lits[0]))
+                    *j++ = *i;
+                else{
+                    // Look for new watch:
+                    lit* stop = lits + clause_size(c);
+                    lit* k;
+                    for (k = lits + 2; k < stop; k++){
+                        if (var_value(s, lit_var(*k)) != !lit_sign(*k)){
+                            lits[1] = *k;
+                            *k = false_lit;
+                            veci_push(sat_solver_read_wlist(s,lit_neg(lits[1])),*i);
+                            goto next; }
+                    }
+
+                    *j++ = *i;
+                    // Clause is unit under assignment:
+                    if ( c->lrn )
+                        c->lbd = sat_clause_compute_lbd(s, c);
+                    if (!sat_solver_enqueue(s,lits[0], *i)){
+                        hConfl = *i++;
+                        // Copy the remaining watches:
+                        while (i < end)
+                            *j++ = *i++;
+                    }
+                }
+            }
+        next:
+            i++;
+        }
+
+        s->stats.inspects += j - veci_begin(ws);
+        veci_resize(ws,j - veci_begin(ws));
+#ifdef TEST_CNF_LOAD
+        }
+#endif
+    }
+
+    return hConfl;
+}
+
+//=================================================================================================
+// External solver functions:
+
+sat_solver* sat_solver_new(void)
+{
+    sat_solver* s = (sat_solver*)ABC_CALLOC( char, sizeof(sat_solver));
+
+//    Vec_SetAlloc_(&s->Mem, 15);
+    Sat_MemAlloc_(&s->Mem, 15);
+    s->hLearnts = -1;
+    s->hBinary = Sat_MemAppend( &s->Mem, NULL, 2, 0, 0 );
+    s->binary = clause_read( s, s->hBinary );
+
+    s->nLearntStart = LEARNT_MAX_START_DEFAULT;  // starting learned clause limit
+    s->nLearntDelta = LEARNT_MAX_INCRE_DEFAULT;  // delta of learned clause limit
+    s->nLearntRatio = LEARNT_MAX_RATIO_DEFAULT;  // ratio of learned clause limit
+    s->nLearntMax   = s->nLearntStart;
+
+    // initialize vectors
+    veci_new(&s->order);
+    veci_new(&s->trail_lim);
+    veci_new(&s->tagged);
+//    veci_new(&s->learned);
+    veci_new(&s->act_clas);
+    veci_new(&s->stack);
+//    veci_new(&s->model);
+    veci_new(&s->act_vars);
+    veci_new(&s->unit_lits);
+    veci_new(&s->temp_clause);
+    veci_new(&s->conf_final);
+
+    // initialize arrays
+    s->wlists    = 0;
+    s->activity  = 0;
+    s->orderpos  = 0;
+    s->reasons   = 0;
+    s->trail     = 0;
+
+    // initialize other vars
+    s->size                   = 0;
+    s->cap                    = 0;
+    s->qhead                  = 0;
+    s->qtail                  = 0;
+#ifdef USE_FLOAT_ACTIVITY
+    s->var_inc                = 1;
+    s->cla_inc                = 1;
+    s->var_decay              = (float)(1 / 0.95 );
+    s->cla_decay              = (float)(1 / 0.999);
+#else
+    s->var_inc                = (1 <<  5);
+    s->cla_inc                = (1 << 11);
+#endif
+    s->root_level             = 0;
+//    s->simpdb_assigns         = 0;
+//    s->simpdb_props           = 0;
+    s->random_seed            = 91648253;
+    s->progress_estimate      = 0;
+//    s->binary                 = (clause*)ABC_ALLOC( char, sizeof(clause) + sizeof(lit)*2);
+//    s->binary->size_learnt    = (2 << 1);
+    s->verbosity              = 0;
+
+    s->stats.starts           = 0;
+    s->stats.decisions        = 0;
+    s->stats.propagations     = 0;
+    s->stats.inspects         = 0;
+    s->stats.conflicts        = 0;
+    s->stats.clauses          = 0;
+    s->stats.clauses_literals = 0;
+    s->stats.learnts          = 0;
+    s->stats.learnts_literals = 0;
+    s->stats.tot_literals     = 0;
+    return s;
+}
+
+void sat_solver_setnvars(sat_solver* s,int n)
+{
+    int var;
+
+    if (s->cap < n){
+        int old_cap = s->cap;
+        while (s->cap < n) s->cap = s->cap*2+1;
+        if ( s->cap < 50000 )
+            s->cap = 50000;
+
+        s->wlists    = ABC_REALLOC(veci,   s->wlists,   s->cap*2);
+//        s->vi        = ABC_REALLOC(varinfo,s->vi,       s->cap);
+        s->levels    = ABC_REALLOC(int,    s->levels,   s->cap);
+        s->assigns   = ABC_REALLOC(char,   s->assigns,  s->cap);
+        s->polarity  = ABC_REALLOC(char,   s->polarity, s->cap);
+        s->tags      = ABC_REALLOC(char,   s->tags,     s->cap);
+        s->loads     = ABC_REALLOC(char,   s->loads,    s->cap);
+#ifdef USE_FLOAT_ACTIVITY
+        s->activity  = ABC_REALLOC(double,   s->activity, s->cap);
+#else
+        s->activity  = ABC_REALLOC(unsigned, s->activity, s->cap);
+        s->activity2 = ABC_REALLOC(unsigned, s->activity2,s->cap);
+#endif
+        s->pFreqs    = ABC_REALLOC(char,   s->pFreqs,   s->cap);
+
+        if ( s->factors )
+        s->factors   = ABC_REALLOC(double, s->factors,  s->cap);
+        s->orderpos  = ABC_REALLOC(int,    s->orderpos, s->cap);
+        s->reasons   = ABC_REALLOC(int,    s->reasons,  s->cap);
+        s->trail     = ABC_REALLOC(lit,    s->trail,    s->cap);
+        s->model     = ABC_REALLOC(int,    s->model,    s->cap);
+        memset( s->wlists + 2*old_cap, 0, 2*(s->cap-old_cap)*sizeof(veci) );
+    } 
+
+    for (var = s->size; var < n; var++){
+        assert(!s->wlists[2*var].size);
+        assert(!s->wlists[2*var+1].size);
+        if ( s->wlists[2*var].ptr == NULL )
+            veci_new(&s->wlists[2*var]);
+        if ( s->wlists[2*var+1].ptr == NULL )
+            veci_new(&s->wlists[2*var+1]);
+#ifdef USE_FLOAT_ACTIVITY
+        s->activity[var] = 0;
+#else
+        s->activity[var] = (1<<10);
+#endif
+        s->pFreqs[var]   = 0;
+        if ( s->factors )
+        s->factors [var] = 0;
+//        *((int*)s->vi + var) = 0; s->vi[var].val = varX;
+        s->levels  [var] = 0;
+        s->assigns [var] = varX;
+        s->polarity[var] = 0;
+        s->tags    [var] = 0;
+        s->loads   [var] = 0;
+        s->orderpos[var] = veci_size(&s->order);
+        s->reasons [var] = 0;
+        s->model   [var] = 0; 
+        
+        /* does not hold because variables enqueued at top level will not be reinserted in the heap
+           assert(veci_size(&s->order) == var); 
+         */
+        veci_push(&s->order,var);
+        order_update(s, var);
+    }
+
+    s->size = n > s->size ? n : s->size;
+}
+
+void sat_solver_delete(sat_solver* s)
+{
+//    Vec_SetFree_( &s->Mem );
+    Sat_MemFree_( &s->Mem );
+
+    // delete vectors
+    veci_delete(&s->order);
+    veci_delete(&s->trail_lim);
+    veci_delete(&s->tagged);
+//    veci_delete(&s->learned);
+    veci_delete(&s->act_clas);
+    veci_delete(&s->stack);
+//    veci_delete(&s->model);
+    veci_delete(&s->act_vars);
+    veci_delete(&s->unit_lits);
+    veci_delete(&s->pivot_vars);
+    veci_delete(&s->temp_clause);
+    veci_delete(&s->conf_final);
+
+    // delete arrays
+    if (s->reasons != 0){
+        int i;
+        for (i = 0; i < s->cap*2; i++)
+            veci_delete(&s->wlists[i]);
+        ABC_FREE(s->wlists   );
+//        ABC_FREE(s->vi       );
+        ABC_FREE(s->levels   );
+        ABC_FREE(s->assigns  );
+        ABC_FREE(s->polarity );
+        ABC_FREE(s->tags     );
+        ABC_FREE(s->loads    );
+        ABC_FREE(s->activity );
+        ABC_FREE(s->activity2);
+        ABC_FREE(s->pFreqs   );
+        ABC_FREE(s->factors  );
+        ABC_FREE(s->orderpos );
+        ABC_FREE(s->reasons  );
+        ABC_FREE(s->trail    );
+        ABC_FREE(s->model    );
+    }
+
+    sat_solver_store_free(s);
+    ABC_FREE(s);
+}
+
+void sat_solver_restart( sat_solver* s )
+{
+    int i;
+    Sat_MemRestart( &s->Mem );
+    s->hLearnts = -1;
+    s->hBinary = Sat_MemAppend( &s->Mem, NULL, 2, 0, 0 );
+    s->binary = clause_read( s, s->hBinary );
+
+    veci_resize(&s->act_clas, 0);
+    veci_resize(&s->trail_lim, 0);
+    veci_resize(&s->order, 0);
+    for ( i = 0; i < s->size*2; i++ )
+        s->wlists[i].size = 0;
+
+    s->nDBreduces = 0;
+
+    // initialize other vars
+    s->size                   = 0;
+//    s->cap                    = 0;
+    s->qhead                  = 0;
+    s->qtail                  = 0;
+#ifdef USE_FLOAT_ACTIVITY
+    s->var_inc                = 1;
+    s->cla_inc                = 1;
+    s->var_decay              = (float)(1 / 0.95  );
+    s->cla_decay              = (float)(1 / 0.999 );
+#else
+    s->var_inc                = (1 <<  5);
+    s->cla_inc                = (1 << 11);
+#endif
+    s->root_level             = 0;
+//    s->simpdb_assigns         = 0;
+//    s->simpdb_props           = 0;
+    s->random_seed            = 91648253;
+    s->progress_estimate      = 0;
+    s->verbosity              = 0;
+
+    s->stats.starts           = 0;
+    s->stats.decisions        = 0;
+    s->stats.propagations     = 0;
+    s->stats.inspects         = 0;
+    s->stats.conflicts        = 0;
+    s->stats.clauses          = 0;
+    s->stats.clauses_literals = 0;
+    s->stats.learnts          = 0;
+    s->stats.learnts_literals = 0;
+    s->stats.tot_literals     = 0;
+}
+
+// returns memory in bytes used by the SAT solver
+double sat_solver_memory( sat_solver* s )
+{
+    int i;
+    double Mem = sizeof(sat_solver);
+    for (i = 0; i < s->cap*2; i++)
+        Mem += s->wlists[i].cap * sizeof(int);
+    Mem += s->cap * sizeof(veci);     // ABC_FREE(s->wlists   );
+    Mem += s->cap * sizeof(int);      // ABC_FREE(s->levels   );
+    Mem += s->cap * sizeof(char);     // ABC_FREE(s->assigns  );
+    Mem += s->cap * sizeof(char);     // ABC_FREE(s->polarity );
+    Mem += s->cap * sizeof(char);     // ABC_FREE(s->tags     );
+    Mem += s->cap * sizeof(char);     // ABC_FREE(s->loads    );
+#ifdef USE_FLOAT_ACTIVITY
+    Mem += s->cap * sizeof(double);   // ABC_FREE(s->activity );
+#else
+    Mem += s->cap * sizeof(unsigned); // ABC_FREE(s->activity );
+    if ( s->activity2 )
+    Mem += s->cap * sizeof(unsigned); // ABC_FREE(s->activity2);
+#endif
+    if ( s->factors )
+    Mem += s->cap * sizeof(double);   // ABC_FREE(s->factors  );
+    Mem += s->cap * sizeof(int);      // ABC_FREE(s->orderpos );
+    Mem += s->cap * sizeof(int);      // ABC_FREE(s->reasons  );
+    Mem += s->cap * sizeof(lit);      // ABC_FREE(s->trail    );
+    Mem += s->cap * sizeof(int);      // ABC_FREE(s->model    );
+
+    Mem += s->order.cap * sizeof(int);
+    Mem += s->trail_lim.cap * sizeof(int);
+    Mem += s->tagged.cap * sizeof(int);
+//    Mem += s->learned.cap * sizeof(int);
+    Mem += s->stack.cap * sizeof(int);
+    Mem += s->act_vars.cap * sizeof(int);
+    Mem += s->unit_lits.cap * sizeof(int);
+    Mem += s->act_clas.cap * sizeof(int);
+    Mem += s->temp_clause.cap * sizeof(int);
+    Mem += s->conf_final.cap * sizeof(int);
+    Mem += Sat_MemMemoryAll( &s->Mem );
+    return Mem;
+}
+
+int sat_solver_simplify(sat_solver* s)
+{
+    assert(sat_solver_dl(s) == 0);
+    if (sat_solver_propagate(s) != 0)
+        return false;
+    return true;
+}
+
+void sat_solver_reducedb(sat_solver* s)
+{
+    static abctime TimeTotal = 0;
+    abctime clk = Abc_Clock();
+    Sat_Mem_t * pMem = &s->Mem;
+    int nLearnedOld = veci_size(&s->act_clas);
+    int * act_clas = veci_begin(&s->act_clas);
+    int * pPerm, * pArray, * pSortValues, nCutoffValue;
+    int i, k, j, Id, Counter, CounterStart, nSelected;
+    clause * c;
+
+    assert( s->nLearntMax > 0 );
+    assert( nLearnedOld == Sat_MemEntryNum(pMem, 1) );
+    assert( nLearnedOld == (int)s->stats.learnts );
+
+    s->nDBreduces++;
+
+//    printf( "Calling reduceDB with %d learned clause limit.\n", s->nLearntMax );
+    s->nLearntMax = s->nLearntStart + s->nLearntDelta * s->nDBreduces;
+//    return;
+
+    // create sorting values
+    pSortValues = ABC_ALLOC( int, nLearnedOld );
+    Sat_MemForEachLearned( pMem, c, i, k )
+    {
+        Id = clause_id(c);
+        pSortValues[Id] = (((7 - Abc_MinInt(c->lbd, 7)) << 28) | (act_clas[Id] >> 4));
+//        pSortValues[Id] = act[Id];
+        assert( pSortValues[Id] >= 0 );
+    }
+
+    // preserve 1/20 of last clauses
+    CounterStart  = nLearnedOld - (s->nLearntMax / 20);
+
+    // preserve 3/4 of most active clauses
+    nSelected = nLearnedOld*s->nLearntRatio/100;
+
+    // find non-decreasing permutation
+    pPerm = Abc_MergeSortCost( pSortValues, nLearnedOld );
+    assert( pSortValues[pPerm[0]] <= pSortValues[pPerm[nLearnedOld-1]] );
+    nCutoffValue = pSortValues[pPerm[nLearnedOld-nSelected]];
+    ABC_FREE( pPerm );
+//    ActCutOff = ABC_INFINITY;
+
+    // mark learned clauses to remove
+    Counter = j = 0;
+    Sat_MemForEachLearned( pMem, c, i, k )
+    {
+        assert( c->mark == 0 );
+        if ( Counter++ > CounterStart || clause_size(c) < 3 || pSortValues[clause_id(c)] > nCutoffValue || s->reasons[lit_var(c->lits[0])] == Sat_MemHand(pMem, i, k) )
+            act_clas[j++] = act_clas[clause_id(c)];
+        else // delete
+        {
+            c->mark = 1;
+            s->stats.learnts_literals -= clause_size(c);
+            s->stats.learnts--;
+        }
+    }
+    assert( s->stats.learnts == (unsigned)j );
+    assert( Counter == nLearnedOld );
+    veci_resize(&s->act_clas,j);
+    ABC_FREE( pSortValues );
+
+    // update ID of each clause to be its new handle
+    Counter = Sat_MemCompactLearned( pMem, 0 );
+    assert( Counter == (int)s->stats.learnts );
+
+    // update reasons
+    for ( i = 0; i < s->size; i++ )
+    {
+        if ( !s->reasons[i] ) // no reason
+            continue;
+        if ( clause_is_lit(s->reasons[i]) ) // 2-lit clause
+            continue;
+        if ( !clause_learnt_h(pMem, s->reasons[i]) ) // problem clause
+            continue;
+        c = clause_read( s, s->reasons[i] );
+        assert( c->mark == 0 );
+        s->reasons[i] = clause_id(c); // updating handle here!!!
+    }
+
+    // update watches
+    for ( i = 0; i < s->size*2; i++ )
+    {
+        pArray = veci_begin(&s->wlists[i]);
+        for ( j = k = 0; k < veci_size(&s->wlists[i]); k++ )
+        {
+            if ( clause_is_lit(pArray[k]) ) // 2-lit clause
+                pArray[j++] = pArray[k];
+            else if ( !clause_learnt_h(pMem, pArray[k]) ) // problem clause
+                pArray[j++] = pArray[k];
+            else 
+            {
+                c = clause_read(s, pArray[k]);
+                if ( !c->mark ) // useful learned clause
+                   pArray[j++] = clause_id(c); // updating handle here!!!
+            }
+        }
+        veci_resize(&s->wlists[i],j);
+    }
+
+    // perform final move of the clauses
+    Counter = Sat_MemCompactLearned( pMem, 1 );
+    assert( Counter == (int)s->stats.learnts );
+
+    // report the results
+    TimeTotal += Abc_Clock() - clk;
+    if ( s->fVerbose )
+    {
+    Abc_Print(1, "reduceDB: Keeping %7d out of %7d clauses (%5.2f %%)  ",
+        s->stats.learnts, nLearnedOld, 100.0 * s->stats.learnts / nLearnedOld );
+    Abc_PrintTime( 1, "Time", TimeTotal );
+    }
+}
+
+
+// reverses to the previously bookmarked point
+void sat_solver_rollback( sat_solver* s )
+{
+    Sat_Mem_t * pMem = &s->Mem;
+    int i, k, j;
+    static int Count = 0;
+    Count++;
+    assert( s->iVarPivot >= 0 && s->iVarPivot <= s->size );
+    assert( s->iTrailPivot >= 0 && s->iTrailPivot <= s->qtail );
+    // reset implication queue
+    sat_solver_canceluntil_rollback( s, s->iTrailPivot );
+    // update order 
+    if ( s->iVarPivot < s->size )
+    { 
+        if ( s->activity2 )
+        {
+            s->var_inc = s->var_inc2;
+            memcpy( s->activity, s->activity2, sizeof(unsigned) * s->iVarPivot );
+        }
+        veci_resize(&s->order, 0);
+        for ( i = 0; i < s->iVarPivot; i++ )
+        {
+            if ( var_value(s, i) != varX )
+                continue;
+            s->orderpos[i] = veci_size(&s->order);
+            veci_push(&s->order,i);
+            order_update(s, i);
+        }
+    }
+    // compact watches
+    for ( i = 0; i < s->iVarPivot*2; i++ )
+    {
+        cla* pArray = veci_begin(&s->wlists[i]);
+        for ( j = k = 0; k < veci_size(&s->wlists[i]); k++ )
+            if ( Sat_MemClauseUsed(pMem, pArray[k]) )
+                pArray[j++] = pArray[k];
+        veci_resize(&s->wlists[i],j);
+    }
+    // reset watcher lists
+    for ( i = 2*s->iVarPivot; i < 2*s->size; i++ )
+        s->wlists[i].size = 0;
+
+    // reset clause counts
+    s->stats.clauses = pMem->BookMarkE[0];
+    s->stats.learnts = pMem->BookMarkE[1];
+    // rollback clauses
+    Sat_MemRollBack( pMem );
+
+    // resize learned arrays
+    veci_resize(&s->act_clas,  s->stats.learnts);
+
+    // initialize other vars
+    s->size = s->iVarPivot;
+    if ( s->size == 0 )
+    {
+    //    s->size                   = 0;
+    //    s->cap                    = 0;
+        s->qhead                  = 0;
+        s->qtail                  = 0;
+#ifdef USE_FLOAT_ACTIVITY
+        s->var_inc                = 1;
+        s->cla_inc                = 1;
+        s->var_decay              = (float)(1 / 0.95  );
+        s->cla_decay              = (float)(1 / 0.999 );
+#else
+        s->var_inc                = (1 <<  5);
+        s->cla_inc                = (1 << 11);
+#endif
+        s->root_level             = 0;
+        s->random_seed            = 91648253;
+        s->progress_estimate      = 0;
+        s->verbosity              = 0;
+
+        s->stats.starts           = 0;
+        s->stats.decisions        = 0;
+        s->stats.propagations     = 0;
+        s->stats.inspects         = 0;
+        s->stats.conflicts        = 0;
+        s->stats.clauses          = 0;
+        s->stats.clauses_literals = 0;
+        s->stats.learnts          = 0;
+        s->stats.learnts_literals = 0;
+        s->stats.tot_literals     = 0;
+
+        // initialize rollback
+        s->iVarPivot              =  0; // the pivot for variables
+        s->iTrailPivot            =  0; // the pivot for trail
+        s->hProofPivot            =  1; // the pivot for proof records
+    }
+}
+
+
+int sat_solver_addclause(sat_solver* s, lit* begin, lit* end)
+{
+    int fVerbose = 0;
+    lit *i,*j;
+    int maxvar;
+    lit last;
+    assert( begin < end );
+    if ( fVerbose )
+    {
+        for ( i = begin; i < end; i++ )
+            printf( "%s%d ", (*i)&1 ? "!":"", (*i)>>1 );
+        printf( "\n" );
+    }
+
+    veci_resize( &s->temp_clause, 0 );
+    for ( i = begin; i < end; i++ )
+        veci_push( &s->temp_clause, *i );
+    begin = veci_begin( &s->temp_clause );
+    end = begin + veci_size( &s->temp_clause );
+
+    // insertion sort
+    maxvar = lit_var(*begin);
+    for (i = begin + 1; i < end; i++){
+        lit l = *i;
+        maxvar = lit_var(l) > maxvar ? lit_var(l) : maxvar;
+        for (j = i; j > begin && *(j-1) > l; j--)
+            *j = *(j-1);
+        *j = l;
+    }
+    sat_solver_setnvars(s,maxvar+1);
+
+    ///////////////////////////////////
+    // add clause to internal storage
+    if ( s->pStore )
+    {
+        int RetValue = Sto_ManAddClause( (Sto_Man_t *)s->pStore, begin, end );
+        assert( RetValue );
+        (void) RetValue;
+    }
+    ///////////////////////////////////
+
+    // delete duplicates
+    last = lit_Undef;
+    for (i = j = begin; i < end; i++){
+        //printf("lit: "L_LIT", value = %d\n", L_lit(*i), (lit_sign(*i) ? -s->assignss[lit_var(*i)] : s->assignss[lit_var(*i)]));
+        if (*i == lit_neg(last) || var_value(s, lit_var(*i)) == lit_sign(*i))
+            return true;   // tautology
+        else if (*i != last && var_value(s, lit_var(*i)) == varX)
+            last = *j++ = *i;
+    }
+//    j = i;
+
+    if (j == begin)          // empty clause
+        return false;
+
+    if (j - begin == 1) // unit clause
+        return sat_solver_enqueue(s,*begin,0);
+
+    // create new clause
+    sat_solver_clause_new(s,begin,j,0);
+    return true;
+}
+
+double luby(double y, int x)
+{
+    int size, seq;
+    for (size = 1, seq = 0; size < x+1; seq++, size = 2*size + 1);
+    while (size-1 != x){
+        size = (size-1) >> 1;
+        seq--;
+        x = x % size;
+    }
+    return pow(y, (double)seq);
+} 
+
+void luby_test()
+{
+    int i;
+    for ( i = 0; i < 20; i++ )
+        printf( "%d ", (int)luby(2,i) );
+    printf( "\n" );
+}
+
+static lbool sat_solver_search(sat_solver* s, ABC_INT64_T nof_conflicts)
+{
+//    double  var_decay       = 0.95;
+//    double  clause_decay    = 0.999;
+    double  random_var_freq = s->fNotUseRandom ? 0.0 : 0.02;
+
+    ABC_INT64_T  conflictC       = 0;
+    veci    learnt_clause;
+    int     i;
+
+    assert(s->root_level == sat_solver_dl(s));
+
+    s->nRestarts++;
+    s->stats.starts++;
+//    s->var_decay = (float)(1 / var_decay   );  // move this to sat_solver_new()
+//    s->cla_decay = (float)(1 / clause_decay);  // move this to sat_solver_new()
+//    veci_resize(&s->model,0);
+    veci_new(&learnt_clause);
+
+    // use activity factors in every even restart
+    if ( (s->nRestarts & 1) && veci_size(&s->act_vars) > 0 )
+//    if ( veci_size(&s->act_vars) > 0 )
+        for ( i = 0; i < s->act_vars.size; i++ )
+            act_var_bump_factor(s, s->act_vars.ptr[i]);
+
+    // use activity factors in every restart
+    if ( s->pGlobalVars && veci_size(&s->act_vars) > 0 )
+        for ( i = 0; i < s->act_vars.size; i++ )
+            act_var_bump_global(s, s->act_vars.ptr[i]);
+
+    for (;;){
+        int hConfl = sat_solver_propagate(s);
+        if (hConfl != 0){
+            // CONFLICT
+            int blevel;
+
+#ifdef VERBOSEDEBUG
+            printf(L_IND"**CONFLICT**\n", L_ind);
+#endif
+            s->stats.conflicts++; conflictC++;
+            if (sat_solver_dl(s) == s->root_level){
+#ifdef SAT_USE_ANALYZE_FINAL
+                sat_solver_analyze_final(s, hConfl, 0);
+#endif
+                veci_delete(&learnt_clause);
+                return l_False;
+            }
+
+            veci_resize(&learnt_clause,0);
+            sat_solver_analyze(s, hConfl, &learnt_clause);
+            blevel = veci_size(&learnt_clause) > 1 ? var_level(s, lit_var(veci_begin(&learnt_clause)[1])) : s->root_level;
+            blevel = s->root_level > blevel ? s->root_level : blevel;
+            sat_solver_canceluntil(s,blevel);
+            sat_solver_record(s,&learnt_clause);
+#ifdef SAT_USE_ANALYZE_FINAL
+//            if (learnt_clause.size() == 1) level[var(learnt_clause[0])] = 0;    // (this is ugly (but needed for 'analyzeFinal()') -- in future versions, we will backtrack past the 'root_level' and redo the assumptions)
+            if ( learnt_clause.size == 1 ) 
+                var_set_level(s, lit_var(learnt_clause.ptr[0]), 0);
+#endif
+            act_var_decay(s);
+            act_clause_decay(s);
+
+        }else{
+            // NO CONFLICT
+            int next;
+ 
+            // Reached bound on number of conflicts:
+            if ((nof_conflicts >= 0 && conflictC >= nof_conflicts) || (s->nRuntimeLimit && (s->stats.conflicts & 63) == 0 && Abc_Clock() > s->nRuntimeLimit)){
+                s->progress_estimate = sat_solver_progress(s);
+                sat_solver_canceluntil(s,s->root_level);
+                veci_delete(&learnt_clause);
+                return l_Undef; }
+
+            // Reached bound on number of conflicts:
+            if ( (s->nConfLimit && s->stats.conflicts > s->nConfLimit) ||
+                 (s->nInsLimit  && s->stats.propagations > s->nInsLimit) )
+            {
+                s->progress_estimate = sat_solver_progress(s);
+                sat_solver_canceluntil(s,s->root_level);
+                veci_delete(&learnt_clause);
+                return l_Undef; 
+            }
+
+            // Simplify the set of problem clauses:
+            if (sat_solver_dl(s) == 0 && !s->fSkipSimplify)
+                sat_solver_simplify(s);
+
+            // Reduce the set of learnt clauses:
+//            if (s->nLearntMax && veci_size(&s->learned) - s->qtail >= s->nLearntMax)
+            if (s->nLearntMax && veci_size(&s->act_clas) >= s->nLearntMax)
+                sat_solver_reducedb(s);
+
+            // New variable decision:
+            s->stats.decisions++;
+            next = order_select(s,(float)random_var_freq);
+
+            if (next == var_Undef){
+                // Model found:
+                int i;
+                for (i = 0; i < s->size; i++)
+                    s->model[i] = (var_value(s,i)==var1 ? l_True : l_False);
+                sat_solver_canceluntil(s,s->root_level);
+                veci_delete(&learnt_clause);
+
+                /*
+                veci apa; veci_new(&apa);
+                for (i = 0; i < s->size; i++) 
+                    veci_push(&apa,(int)(s->model.ptr[i] == l_True ? toLit(i) : lit_neg(toLit(i))));
+                printf("model: "); printlits((lit*)apa.ptr, (lit*)apa.ptr + veci_size(&apa)); printf("\n");
+                veci_delete(&apa);
+                */
+
+                return l_True;
+            }
+
+            if ( var_polar(s, next) ) // positive polarity
+                sat_solver_assume(s,toLit(next));
+            else
+                sat_solver_assume(s,lit_neg(toLit(next)));
+        }
+    }
+
+    return l_Undef; // cannot happen
+}
+
+int sat_solver_solve(sat_solver* s, lit* begin, lit* end, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, ABC_INT64_T nConfLimitGlobal, ABC_INT64_T nInsLimitGlobal)
+{
+    int restart_iter = 0;
+    ABC_INT64_T  nof_conflicts;
+//    ABC_INT64_T  nof_learnts   = sat_solver_nclauses(s) / 3;
+    lbool   status        = l_Undef;
+    lit*    i;
+
+    if ( s->fVerbose )
+        printf( "Running SAT solver with parameters %d and %d and %d.\n", s->nLearntStart, s->nLearntDelta, s->nLearntRatio );
+
+    ////////////////////////////////////////////////
+    if ( s->fSolved )
+    {
+        if ( s->pStore )
+        {
+            int RetValue = Sto_ManAddClause( (Sto_Man_t *)s->pStore, NULL, NULL );
+            assert( RetValue );
+            (void) RetValue;
+        }
+        return l_False;
+    }
+    ////////////////////////////////////////////////
+    veci_resize(&s->unit_lits, 0);
+
+    // set the external limits
+    s->nCalls++;
+    s->nRestarts  = 0;
+    s->nConfLimit = 0;
+    s->nInsLimit  = 0;
+    if ( nConfLimit )
+        s->nConfLimit = s->stats.conflicts + nConfLimit;
+    if ( nInsLimit )
+//        s->nInsLimit = s->stats.inspects + nInsLimit;
+        s->nInsLimit = s->stats.propagations + nInsLimit;
+    if ( nConfLimitGlobal && (s->nConfLimit == 0 || s->nConfLimit > nConfLimitGlobal) )
+        s->nConfLimit = nConfLimitGlobal;
+    if ( nInsLimitGlobal && (s->nInsLimit == 0 || s->nInsLimit > nInsLimitGlobal) )
+        s->nInsLimit = nInsLimitGlobal;
+
+#ifndef SAT_USE_ANALYZE_FINAL
+
+    //printf("solve: "); printlits(begin, end); printf("\n");
+    for (i = begin; i < end; i++){
+//        switch (lit_sign(*i) ? -s->assignss[lit_var(*i)] : s->assignss[lit_var(*i)]){
+        switch (var_value(s, *i)) {
+        case var1: // l_True: 
+            break;
+        case varX: // l_Undef
+            sat_solver_assume(s, *i);
+            if (sat_solver_propagate(s) == 0)
+                break;
+            // fallthrough
+        case var0: // l_False 
+            sat_solver_canceluntil(s, 0);
+            return l_False;
+        }
+    }
+    s->root_level = sat_solver_dl(s);
+
+#endif
+
+/*
+    // Perform assumptions:
+    root_level = assumps.size();
+    for (int i = 0; i < assumps.size(); i++){
+        Lit p = assumps[i];
+        assert(var(p) < nVars());
+        if (!sat_solver_assume(p)){
+            GClause r = reason[var(p)];
+            if (r != GClause_NULL){
+                Clause* confl;
+                if (r.isLit()){
+                    confl = propagate_tmpbin;
+                    (*confl)[1] = ~p;
+                    (*confl)[0] = r.lit();
+                }else
+                    confl = r.clause();
+                analyzeFinal(confl, true);
+                conflict.push(~p);
+            }else
+                conflict.clear(),
+                conflict.push(~p);
+            cancelUntil(0);
+            return false; }
+        Clause* confl = propagate();
+        if (confl != NULL){
+            analyzeFinal(confl), assert(conflict.size() > 0);
+            cancelUntil(0);
+            return false; }
+    }
+    assert(root_level == decisionLevel());
+*/
+
+#ifdef SAT_USE_ANALYZE_FINAL
+    // Perform assumptions:
+    s->root_level = end - begin;
+    for ( i = begin; i < end; i++ )
+    {
+        lit p = *i;
+        assert(lit_var(p) < s->size);
+        veci_push(&s->trail_lim,s->qtail);
+        if (!sat_solver_enqueue(s,p,0))
+        {
+            int h = s->reasons[lit_var(p)];
+            if (h)
+            {
+                if (clause_is_lit(h))
+                {
+                    (clause_begin(s->binary))[1] = lit_neg(p);
+                    (clause_begin(s->binary))[0] = clause_read_lit(h);
+                    h = s->hBinary;
+                }
+                sat_solver_analyze_final(s, h, 1);
+                veci_push(&s->conf_final, lit_neg(p));
+            }
+            else
+            {
+                veci_resize(&s->conf_final,0);
+                veci_push(&s->conf_final, lit_neg(p));
+                // the two lines below are a bug fix by Siert Wieringa 
+                if (var_level(s, lit_var(p)) > 0)
+                    veci_push(&s->conf_final, p);
+            }
+            sat_solver_canceluntil(s, 0);
+            return l_False; 
+        }
+        else
+        {
+            int fConfl = sat_solver_propagate(s);
+            if (fConfl){
+                sat_solver_analyze_final(s, fConfl, 0);
+                assert(s->conf_final.size > 0);
+                sat_solver_canceluntil(s, 0);
+                return l_False; }
+        }
+    }
+    assert(s->root_level == sat_solver_dl(s));
+#endif
+
+    s->nCalls2++;
+
+    if (s->verbosity >= 1){
+        printf("==================================[MINISAT]===================================\n");
+        printf("| Conflicts |     ORIGINAL     |              LEARNT              | Progress |\n");
+        printf("|           | Clauses Literals |   Limit Clauses Literals  Lit/Cl |          |\n");
+        printf("==============================================================================\n");
+    }
+
+    while (status == l_Undef){
+        double Ratio = (s->stats.learnts == 0)? 0.0 :
+            s->stats.learnts_literals / (double)s->stats.learnts;
+        if ( s->nRuntimeLimit && Abc_Clock() > s->nRuntimeLimit )
+            break;
+        if (s->verbosity >= 1)
+        {
+            printf("| %9.0f | %7.0f %8.0f | %7.0f %7.0f %8.0f %7.1f | %6.3f %% |\n", 
+                (double)s->stats.conflicts,
+                (double)s->stats.clauses, 
+                (double)s->stats.clauses_literals,
+//                (double)nof_learnts, 
+                (double)0, 
+                (double)s->stats.learnts, 
+                (double)s->stats.learnts_literals,
+                Ratio,
+                s->progress_estimate*100);
+            fflush(stdout);
+        }
+        nof_conflicts = (ABC_INT64_T)( 100 * luby(2, restart_iter++) );
+        status = sat_solver_search(s, nof_conflicts);
+//        nof_learnts    = nof_learnts * 11 / 10; //*= 1.1;
+        // quit the loop if reached an external limit
+        if ( s->nConfLimit && s->stats.conflicts > s->nConfLimit )
+            break;
+        if ( s->nInsLimit  && s->stats.propagations > s->nInsLimit )
+            break;
+        if ( s->nRuntimeLimit && Abc_Clock() > s->nRuntimeLimit )
+            break;
+    }
+    if (s->verbosity >= 1)
+        printf("==============================================================================\n");
+
+    sat_solver_canceluntil(s,0);
+
+    ////////////////////////////////////////////////
+    if ( status == l_False && s->pStore )
+    {
+        int RetValue = Sto_ManAddClause( (Sto_Man_t *)s->pStore, NULL, NULL );
+        assert( RetValue );
+        (void) RetValue;
+    }
+    ////////////////////////////////////////////////
+    return status;
+}
+
+
+int sat_solver_nvars(sat_solver* s)
+{
+    return s->size;
+}
+
+
+int sat_solver_nclauses(sat_solver* s)
+{
+    return s->stats.clauses;
+}
+
+
+int sat_solver_nconflicts(sat_solver* s)
+{
+    return (int)s->stats.conflicts;
+}
+
+//=================================================================================================
+// Clause storage functions:
+
+void sat_solver_store_alloc( sat_solver * s )
+{
+    assert( s->pStore == NULL );
+    s->pStore = Sto_ManAlloc();
+}
+
+void sat_solver_store_write( sat_solver * s, char * pFileName )
+{
+    if ( s->pStore ) Sto_ManDumpClauses( (Sto_Man_t *)s->pStore, pFileName );
+}
+
+void sat_solver_store_free( sat_solver * s )
+{
+    if ( s->pStore ) Sto_ManFree( (Sto_Man_t *)s->pStore );
+    s->pStore = NULL;
+}
+
+int sat_solver_store_change_last( sat_solver * s )
+{
+    if ( s->pStore ) return Sto_ManChangeLastClause( (Sto_Man_t *)s->pStore );
+    return -1;
+}
+ 
+void sat_solver_store_mark_roots( sat_solver * s )
+{
+    if ( s->pStore ) Sto_ManMarkRoots( (Sto_Man_t *)s->pStore );
+}
+
+void sat_solver_store_mark_clauses_a( sat_solver * s )
+{
+    if ( s->pStore ) Sto_ManMarkClausesA( (Sto_Man_t *)s->pStore );
+}
+
+void * sat_solver_store_release( sat_solver * s )
+{
+    void * pTemp;
+    if ( s->pStore == NULL )
+        return NULL;
+    pTemp = s->pStore;
+    s->pStore = NULL;
+    return pTemp;
+}
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bsat/satSolver.h b/abc-build/src/sat/bsat/satSolver.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satSolver.h
@@ -0,0 +1,547 @@
+/**************************************************************************************************
+MiniSat -- Copyright (c) 2005, Niklas Sorensson
+http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+// Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko
+
+#ifndef ABC__sat__bsat__satSolver_h
+#define ABC__sat__bsat__satSolver_h
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "satVec.h"
+#include "satClause.h"
+
+ABC_NAMESPACE_HEADER_START
+
+//#define USE_FLOAT_ACTIVITY
+
+//=================================================================================================
+// Public interface:
+
+struct sat_solver_t;
+typedef struct sat_solver_t sat_solver;
+
+extern sat_solver* sat_solver_new(void);
+extern void        sat_solver_delete(sat_solver* s);
+
+extern int         sat_solver_addclause(sat_solver* s, lit* begin, lit* end);
+extern int         sat_solver_clause_new(sat_solver* s, lit* begin, lit* end, int learnt);
+extern int         sat_solver_simplify(sat_solver* s);
+extern int         sat_solver_solve(sat_solver* s, lit* begin, lit* end, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, ABC_INT64_T nConfLimitGlobal, ABC_INT64_T nInsLimitGlobal);
+extern void        sat_solver_restart( sat_solver* s );
+extern void        sat_solver_rollback( sat_solver* s );
+
+extern int         sat_solver_nvars(sat_solver* s);
+extern int         sat_solver_nclauses(sat_solver* s);
+extern int         sat_solver_nconflicts(sat_solver* s);
+extern double      sat_solver_memory(sat_solver* s);
+extern int         sat_solver_count_assigned(sat_solver* s);
+
+extern void        sat_solver_setnvars(sat_solver* s,int n);
+extern int         sat_solver_get_var_value(sat_solver* s, int v);
+
+
+extern void        Sat_SolverWriteDimacs( sat_solver * p, char * pFileName, lit* assumptionsBegin, lit* assumptionsEnd, int incrementVars );
+extern void        Sat_SolverPrintStats( FILE * pFile, sat_solver * p );
+extern int *       Sat_SolverGetModel( sat_solver * p, int * pVars, int nVars );
+extern void        Sat_SolverDoubleClauses( sat_solver * p, int iVar );
+
+// trace recording
+extern void        Sat_SolverTraceStart( sat_solver * pSat, char * pName );
+extern void        Sat_SolverTraceStop( sat_solver * pSat );
+extern void        Sat_SolverTraceWrite( sat_solver * pSat, int * pBeg, int * pEnd, int fRoot );
+
+// clause storage
+extern void        sat_solver_store_alloc( sat_solver * s );
+extern void        sat_solver_store_write( sat_solver * s, char * pFileName );
+extern void        sat_solver_store_free( sat_solver * s );
+extern void        sat_solver_store_mark_roots( sat_solver * s );
+extern void        sat_solver_store_mark_clauses_a( sat_solver * s );
+extern void *      sat_solver_store_release( sat_solver * s ); 
+
+//=================================================================================================
+// Solver representation:
+
+//struct clause_t;
+//typedef struct clause_t clause;
+
+struct varinfo_t;
+typedef struct varinfo_t varinfo;
+
+struct sat_solver_t
+{
+    int         size;          // nof variables
+    int         cap;           // size of varmaps
+    int         qhead;         // Head index of queue.
+    int         qtail;         // Tail index of queue.
+
+    // clauses
+    Sat_Mem_t   Mem;
+    int         hLearnts;      // the first learnt clause
+    int         hBinary;       // the special binary clause
+    clause *    binary;
+    veci*       wlists;        // watcher lists
+    veci        act_clas;      // contain clause activities
+
+    // rollback
+    int         iVarPivot;     // the pivot for variables
+    int         iTrailPivot;   // the pivot for trail
+    int         hProofPivot;   // the pivot for proof records
+
+    // activities
+#ifdef USE_FLOAT_ACTIVITY
+    double      var_inc;       // Amount to bump next variable with.
+    double      var_decay;     // INVERSE decay factor for variable activity: stores 1/decay. 
+    float       cla_inc;       // Amount to bump next clause with.
+    float       cla_decay;     // INVERSE decay factor for clause activity: stores 1/decay.
+    double*     activity;      // A heuristic measurement of the activity of a variable.
+#else
+    int         var_inc;       // Amount to bump next variable with.
+    int         var_inc2;      // Amount to bump next variable with.
+    int         cla_inc;       // Amount to bump next clause with.
+    unsigned*   activity;      // A heuristic measurement of the activity of a variable.
+    unsigned*   activity2;     // backup variable activity
+#endif
+    char *      pFreqs;        // how many times this variable was assigned a value
+    int         nVarUsed;
+
+//    varinfo *   vi;            // variable information
+    int*        levels;        //
+    char*       assigns;       // Current values of variables.
+    char*       polarity;      //
+    char*       tags;          //
+    char*       loads;         //
+
+    int*        orderpos;      // Index in variable order.
+    int*        reasons;       //
+    lit*        trail;
+    veci        tagged;        // (contains: var)
+    veci        stack;         // (contains: var)
+
+    veci        order;         // Variable order. (heap) (contains: var)
+    veci        trail_lim;     // Separator indices for different decision levels in 'trail'. (contains: int)
+//    veci        model;         // If problem is solved, this vector contains the model (contains: lbool).
+    int *       model;         // If problem is solved, this vector contains the model (contains: lbool).
+    veci        conf_final;    // If problem is unsatisfiable (possibly under assumptions),
+                               // this vector represent the final conflict clause expressed in the assumptions.
+
+    int         root_level;    // Level of first proper decision.
+    int         simpdb_assigns;// Number of top-level assignments at last 'simplifyDB()'.
+    int         simpdb_props;  // Number of propagations before next 'simplifyDB()'.
+    double      random_seed;
+    double      progress_estimate;
+    int         verbosity;     // Verbosity level. 0=silent, 1=some progress report, 2=everything
+    int         fVerbose;
+
+    stats_t     stats;
+    int         nLearntMax;    // max number of learned clauses
+    int         nLearntStart;  // starting learned clause limit
+    int         nLearntDelta;  // delta of learned clause limit
+    int         nLearntRatio;  // ratio percentage of learned clauses
+    int         nDBreduces;    // number of DB reductions
+
+    ABC_INT64_T nConfLimit;    // external limit on the number of conflicts
+    ABC_INT64_T nInsLimit;     // external limit on the number of implications
+    abctime     nRuntimeLimit; // external limit on runtime
+
+    veci        act_vars;      // variables whose activity has changed
+    double*     factors;       // the activity factors
+    int         nRestarts;     // the number of local restarts
+    int         nCalls;        // the number of local restarts
+    int         nCalls2;       // the number of local restarts
+    veci        unit_lits;     // variables whose activity has changed
+    veci        pivot_vars;    // pivot variables
+
+    int         fSkipSimplify; // set to one to skip simplification of the clause database
+    int         fNotUseRandom; // do not allow random decisions with a fixed probability
+
+    int *       pGlobalVars;   // for experiments with global vars during interpolation
+    // clause store
+    void *      pStore;
+    int         fSolved;
+
+    // trace recording
+    FILE *      pFile;
+    int         nClauses;
+    int         nRoots;
+
+    veci        temp_clause;    // temporary storage for a CNF clause
+
+    // CNF loading
+    void *      pCnfMan;           // external CNF manager
+    int(*pCnfFunc)(void * p, int); // external callback
+};
+
+static inline clause * clause_read( sat_solver * s, cla h )          
+{ 
+    return Sat_MemClauseHand( &s->Mem, h );      
+}
+
+static int sat_solver_var_value( sat_solver* s, int v )
+{
+    assert( v >= 0 && v < s->size );
+    return (int)(s->model[v] == l_True);
+}
+static int sat_solver_var_literal( sat_solver* s, int v )
+{
+    assert( v >= 0 && v < s->size );
+    return toLitCond( v, s->model[v] != l_True );
+}
+static void sat_solver_act_var_clear(sat_solver* s) 
+{
+    int i;
+    for (i = 0; i < s->size; i++)
+        s->activity[i] = 0.0;
+    s->var_inc = 1.0;
+}
+static void sat_solver_compress(sat_solver* s) 
+{
+    if ( s->qtail != s->qhead )
+    {
+        int RetValue = sat_solver_simplify(s);
+        assert( RetValue != 0 );
+        (void) RetValue;
+    }
+}
+
+static int sat_solver_final(sat_solver* s, int ** ppArray)
+{
+    *ppArray = s->conf_final.ptr;
+    return s->conf_final.size;
+}
+
+static abctime sat_solver_set_runtime_limit(sat_solver* s, abctime Limit)
+{
+    abctime nRuntimeLimit = s->nRuntimeLimit;
+    s->nRuntimeLimit = Limit;
+    return nRuntimeLimit;
+}
+
+static int sat_solver_set_random(sat_solver* s, int fNotUseRandom)
+{
+    int fNotUseRandomOld = s->fNotUseRandom;
+    s->fNotUseRandom = fNotUseRandom;
+    return fNotUseRandomOld;
+}
+
+static inline void sat_solver_bookmark(sat_solver* s)
+{
+    assert( s->qhead == s->qtail );
+    s->iVarPivot    = s->size;
+    s->iTrailPivot  = s->qhead;
+    Sat_MemBookMark( &s->Mem );
+    if ( s->activity2 )
+    {
+        s->var_inc2 = s->var_inc;
+        memcpy( s->activity2, s->activity, sizeof(unsigned) * s->iVarPivot );
+    }
+}
+static inline void sat_solver_set_pivot_variables( sat_solver* s, int * pPivots, int nPivots )
+{
+    s->pivot_vars.cap = nPivots;
+    s->pivot_vars.size = nPivots;
+    s->pivot_vars.ptr = pPivots;
+}
+static inline int sat_solver_count_usedvars(sat_solver* s)
+{
+    int i, nVars = 0;
+    for ( i = 0; i < s->size; i++ )
+        if ( s->pFreqs[i] )
+        {
+            s->pFreqs[i] = 0;
+            nVars++;
+        }
+    return nVars;
+}
+
+static inline int sat_solver_add_const( sat_solver * pSat, int iVar, int fCompl )
+{
+    lit Lits[1];
+    int Cid;
+    assert( iVar >= 0 );
+
+    Lits[0] = toLitCond( iVar, fCompl );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 1 );
+    assert( Cid );
+    return 1;
+}
+static inline int sat_solver_add_buffer( sat_solver * pSat, int iVarA, int iVarB, int fCompl )
+{
+    lit Lits[2];
+    int Cid;
+    assert( iVarA >= 0 && iVarB >= 0 );
+
+    Lits[0] = toLitCond( iVarA, 0 );
+    Lits[1] = toLitCond( iVarB, !fCompl );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 2 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarA, 1 );
+    Lits[1] = toLitCond( iVarB, fCompl );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 2 );
+    assert( Cid );
+    return 2;
+}
+static inline int sat_solver_add_buffer_enable( sat_solver * pSat, int iVarA, int iVarB, int iVarEn, int fCompl )
+{
+    lit Lits[3];
+    int Cid;
+    assert( iVarA >= 0 && iVarB >= 0 && iVarEn >= 0 );
+
+    Lits[0] = toLitCond( iVarA, 0 );
+    Lits[1] = toLitCond( iVarB, !fCompl );
+    Lits[2] = toLitCond( iVarEn, 1 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 3 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarA, 1 );
+    Lits[1] = toLitCond( iVarB, fCompl );
+    Lits[2] = toLitCond( iVarEn, 1 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 3 );
+    assert( Cid );
+    return 2;
+}
+static inline int sat_solver_add_and( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1, int fCompl )
+{
+    lit Lits[3];
+    int Cid;
+
+    Lits[0] = toLitCond( iVar, !fCompl );
+    Lits[1] = toLitCond( iVar0, fCompl0 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 2 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVar, !fCompl );
+    Lits[1] = toLitCond( iVar1, fCompl1 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 2 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVar, fCompl );
+    Lits[1] = toLitCond( iVar0, !fCompl0 );
+    Lits[2] = toLitCond( iVar1, !fCompl1 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 3 );
+    assert( Cid );
+    return 3;
+}
+static inline int sat_solver_add_xor( sat_solver * pSat, int iVarA, int iVarB, int iVarC, int fCompl )
+{
+    lit Lits[3];
+    int Cid;
+    assert( iVarA >= 0 && iVarB >= 0 && iVarC >= 0 );
+
+    Lits[0] = toLitCond( iVarA, !fCompl );
+    Lits[1] = toLitCond( iVarB, 1 );
+    Lits[2] = toLitCond( iVarC, 1 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 3 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarA, !fCompl );
+    Lits[1] = toLitCond( iVarB, 0 );
+    Lits[2] = toLitCond( iVarC, 0 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 3 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarA, fCompl );
+    Lits[1] = toLitCond( iVarB, 1 );
+    Lits[2] = toLitCond( iVarC, 0 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 3 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarA, fCompl );
+    Lits[1] = toLitCond( iVarB, 0 );
+    Lits[2] = toLitCond( iVarC, 1 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 3 );
+    assert( Cid );
+    return 4;
+}
+static inline int sat_solver_add_mux( sat_solver * pSat, int iVarC, int iVarT, int iVarE, int iVarZ )
+{
+    lit Lits[3];
+    int Cid;
+    assert( iVarC >= 0 && iVarT >= 0 && iVarE >= 0 && iVarZ >= 0 );
+
+    Lits[0] = toLitCond( iVarC, 1 );
+    Lits[1] = toLitCond( iVarT, 1 );
+    Lits[2] = toLitCond( iVarZ, 0 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 3 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarC, 1 );
+    Lits[1] = toLitCond( iVarT, 0 );
+    Lits[2] = toLitCond( iVarZ, 1 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 3 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarC, 0 );
+    Lits[1] = toLitCond( iVarE, 1 );
+    Lits[2] = toLitCond( iVarZ, 0 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 3 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarC, 0 );
+    Lits[1] = toLitCond( iVarE, 0 );
+    Lits[2] = toLitCond( iVarZ, 1 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 3 );
+    assert( Cid );
+
+    if ( iVarT == iVarE )
+        return 4;
+
+    Lits[0] = toLitCond( iVarT, 0 );
+    Lits[1] = toLitCond( iVarE, 0 );
+    Lits[2] = toLitCond( iVarZ, 1 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 3 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarT, 1 );
+    Lits[1] = toLitCond( iVarE, 1 );
+    Lits[2] = toLitCond( iVarZ, 0 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 3 );
+    assert( Cid );
+    return 6;
+}
+static inline int sat_solver_add_mux41( sat_solver * pSat, int iVarC0, int iVarC1, int iVarD0, int iVarD1, int iVarD2, int iVarD3, int iVarZ )
+{
+    lit Lits[4];
+    int Cid;
+    assert( iVarC0 >= 0 && iVarC1 >= 0 && iVarD0 >= 0 && iVarD1 >= 0 && iVarD2 >= 0 && iVarD3 >= 0 && iVarZ >= 0 );
+
+    Lits[0] = toLitCond( iVarD0, 1 );
+    Lits[1] = toLitCond( iVarC0, 0 );
+    Lits[2] = toLitCond( iVarC1, 0 );
+    Lits[3] = toLitCond( iVarZ,  0 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 4 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarD1, 1 );
+    Lits[1] = toLitCond( iVarC0, 1 );
+    Lits[2] = toLitCond( iVarC1, 0 );
+    Lits[3] = toLitCond( iVarZ,  0 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 4 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarD2, 1 );
+    Lits[1] = toLitCond( iVarC0, 0 );
+    Lits[2] = toLitCond( iVarC1, 1 );
+    Lits[3] = toLitCond( iVarZ,  0 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 4 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarD3, 1 );
+    Lits[1] = toLitCond( iVarC0, 1 );
+    Lits[2] = toLitCond( iVarC1, 1 );
+    Lits[3] = toLitCond( iVarZ,  0 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 4 );
+    assert( Cid );
+
+
+    Lits[0] = toLitCond( iVarD0, 0 );
+    Lits[1] = toLitCond( iVarC0, 0 );
+    Lits[2] = toLitCond( iVarC1, 0 );
+    Lits[3] = toLitCond( iVarZ,  1 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 4 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarD1, 0 );
+    Lits[1] = toLitCond( iVarC0, 1 );
+    Lits[2] = toLitCond( iVarC1, 0 );
+    Lits[3] = toLitCond( iVarZ,  1 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 4 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarD2, 0 );
+    Lits[1] = toLitCond( iVarC0, 0 );
+    Lits[2] = toLitCond( iVarC1, 1 );
+    Lits[3] = toLitCond( iVarZ,  1 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 4 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarD3, 0 );
+    Lits[1] = toLitCond( iVarC0, 1 );
+    Lits[2] = toLitCond( iVarC1, 1 );
+    Lits[3] = toLitCond( iVarZ,  1 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 4 );
+    assert( Cid );
+    return 8;
+}
+static inline int sat_solver_add_xor_and( sat_solver * pSat, int iVarF, int iVarA, int iVarB, int iVarC )
+{
+    // F = (a (+) b) * c
+    lit Lits[4];
+    int Cid;
+    assert( iVarF >= 0 && iVarA >= 0 && iVarB >= 0 && iVarC >= 0 );
+
+    Lits[0] = toLitCond( iVarF, 1 );
+    Lits[1] = toLitCond( iVarA, 1 );
+    Lits[2] = toLitCond( iVarB, 1 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 3 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarF, 1 );
+    Lits[1] = toLitCond( iVarA, 0 );
+    Lits[2] = toLitCond( iVarB, 0 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 3 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarF, 1 );
+    Lits[1] = toLitCond( iVarC, 0 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 2 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarF, 0 );
+    Lits[1] = toLitCond( iVarA, 1 );
+    Lits[2] = toLitCond( iVarB, 0 );
+    Lits[3] = toLitCond( iVarC, 1 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 4 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVarF, 0 );
+    Lits[1] = toLitCond( iVarA, 0 );
+    Lits[2] = toLitCond( iVarB, 1 );
+    Lits[3] = toLitCond( iVarC, 1 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 4 );
+    assert( Cid );
+    return 5;
+}
+static inline int sat_solver_add_constraint( sat_solver * pSat, int iVar, int iVar2, int fCompl )
+{
+    lit Lits[2];
+    int Cid;
+    assert( iVar >= 0 );
+
+    Lits[0] = toLitCond( iVar, fCompl );
+    Lits[1] = toLitCond( iVar2, 0 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 2 );
+    assert( Cid );
+
+    Lits[0] = toLitCond( iVar, fCompl );
+    Lits[1] = toLitCond( iVar2, 1 );
+    Cid = sat_solver_addclause( pSat, Lits, Lits + 2 );
+    assert( Cid );
+    return 2;
+}
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/sat/bsat/satSolver2.c b/abc-build/src/sat/bsat/satSolver2.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satSolver2.c
@@ -0,0 +1,1998 @@
+/**************************************************************************************************
+MiniSat -- Copyright (c) 2005, Niklas Sorensson
+http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+// Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+
+#include "satSolver2.h"
+
+ABC_NAMESPACE_IMPL_START
+
+#define SAT_USE_PROOF_LOGGING
+
+//=================================================================================================
+// Debug:
+ 
+//#define VERBOSEDEBUG
+
+// For derivation output (verbosity level 2)
+#define L_IND    "%-*d"
+#define L_ind    solver2_dlevel(s)*2+2,solver2_dlevel(s)
+#define L_LIT    "%sx%d"
+#define L_lit(p) lit_sign(p)?"~":"", (lit_var(p))
+static void printlits(lit* begin, lit* end)
+{
+    int i;
+    for (i = 0; i < end - begin; i++)
+        Abc_Print(1,L_LIT" ",L_lit(begin[i]));
+}
+
+//=================================================================================================
+// Random numbers:
+
+
+// Returns a random float 0 <= x < 1. Seed must never be 0.
+static inline double drand(double* seed) {
+    int q;
+    *seed *= 1389796;
+    q = (int)(*seed / 2147483647);
+    *seed -= (double)q * 2147483647;
+    return *seed / 2147483647; }
+
+
+// Returns a random integer 0 <= x < size. Seed must never be 0.
+static inline int irand(double* seed, int size) {
+    return (int)(drand(seed) * size); }
+
+//=================================================================================================
+// Variable datatype + minor functions:
+
+static const int var0  = 1;
+static const int var1  = 0;
+static const int varX  = 3;
+
+struct varinfo2_t
+{
+//    unsigned val    :  2;  // variable value 
+    unsigned pol    :  1;  // last polarity
+    unsigned partA  :  1;  // partA variable
+    unsigned tag    :  4;  // conflict analysis tags
+//    unsigned lev    : 24;  // variable level
+};
+
+int    var_is_assigned(sat_solver2* s, int v)            { return s->assigns[v] != varX; }
+int    var_is_partA (sat_solver2* s, int v)              { return s->vi[v].partA;        }
+void   var_set_partA(sat_solver2* s, int v, int partA)   { s->vi[v].partA = partA;       }
+
+//static inline int     var_level     (sat_solver2* s, int v)            { return s->vi[v].lev; }
+static inline int     var_level     (sat_solver2* s, int v)            { return s->levels[v];  }
+//static inline int     var_value     (sat_solver2* s, int v)            { return s->vi[v].val; }
+static inline int     var_value     (sat_solver2* s, int v)            { return s->assigns[v]; }
+static inline int     var_polar     (sat_solver2* s, int v)            { return s->vi[v].pol; }
+
+//static inline void    var_set_level (sat_solver2* s, int v, int lev)   { s->vi[v].lev = lev;  }
+static inline void    var_set_level (sat_solver2* s, int v, int lev)   { s->levels[v] = lev;  }
+//static inline void    var_set_value (sat_solver2* s, int v, int val)   { s->vi[v].val = val;  }
+static inline void    var_set_value (sat_solver2* s, int v, int val)   { s->assigns[v] = val; }
+static inline void    var_set_polar (sat_solver2* s, int v, int pol)   { s->vi[v].pol = pol;  }
+
+// check if the literal is false under current assumptions
+static inline int     solver2_lit_is_false( sat_solver2* s, int Lit )  { return var_value(s, lit_var(Lit)) == !lit_sign(Lit); }
+
+
+
+// variable tags
+static inline int     var_tag       (sat_solver2* s, int v)            { return s->vi[v].tag; }
+static inline void    var_set_tag   (sat_solver2* s, int v, int tag)   {
+    assert( tag > 0 && tag < 16 );
+    if ( s->vi[v].tag == 0 )
+        veci_push( &s->tagged, v );
+    s->vi[v].tag = tag;
+}
+static inline void    var_add_tag   (sat_solver2* s, int v, int tag)   {
+    assert( tag > 0 && tag < 16 );
+    if ( s->vi[v].tag == 0 )
+        veci_push( &s->tagged, v );
+    s->vi[v].tag |= tag;
+}
+static inline void    solver2_clear_tags(sat_solver2* s, int start)    {
+    int i, * tagged = veci_begin(&s->tagged);
+    for (i = start; i < veci_size(&s->tagged); i++)
+        s->vi[tagged[i]].tag = 0;
+    veci_resize(&s->tagged,start);
+}
+
+// level marks
+static inline int     var_lev_mark (sat_solver2* s, int v)             {
+    return (veci_begin(&s->trail_lim)[var_level(s,v)] & 0x80000000) > 0;
+}
+static inline void    var_lev_set_mark (sat_solver2* s, int v)         {
+    int level = var_level(s,v);
+    assert( level < veci_size(&s->trail_lim) );
+    veci_begin(&s->trail_lim)[level] |= 0x80000000;
+    veci_push(&s->mark_levels, level);
+}
+static inline void    solver2_clear_marks(sat_solver2* s)              {
+    int i, * mark_levels = veci_begin(&s->mark_levels);
+    for (i = 0; i < veci_size(&s->mark_levels); i++)
+        veci_begin(&s->trail_lim)[mark_levels[i]] &= 0x7FFFFFFF;
+    veci_resize(&s->mark_levels,0);
+}
+
+//=================================================================================================
+// Clause datatype + minor functions:
+
+//static inline int     var_reason    (sat_solver2* s, int v)      { return (s->reasons[v]&1) ? 0 : s->reasons[v] >> 1;                   }
+//static inline int     lit_reason    (sat_solver2* s, int l)      { return (s->reasons[lit_var(l)&1]) ? 0 : s->reasons[lit_var(l)] >> 1; }
+//static inline clause* var_unit_clause(sat_solver2* s, int v)           { return (s->reasons[v]&1) ? clause2_read(s, s->reasons[v] >> 1) : NULL;  }
+//static inline void    var_set_unit_clause(sat_solver2* s, int v, cla i){ assert(i && !s->reasons[v]); s->reasons[v] = (i << 1) | 1;             }
+static inline int     var_reason    (sat_solver2* s, int v)            { return s->reasons[v];           }
+static inline int     lit_reason    (sat_solver2* s, int l)            { return s->reasons[lit_var(l)];  }
+static inline clause* var_unit_clause(sat_solver2* s, int v)           { return clause2_read(s, s->units[v]);                                          }
+static inline void    var_set_unit_clause(sat_solver2* s, int v, cla i){ 
+    assert(v >= 0 && v < s->size && !s->units[v]); s->units[v] = i; s->nUnits++; 
+}
+
+#define clause_foreach_var( p, var, i, start )        \
+    for ( i = start; (i < (int)(p)->size) && ((var) = lit_var((p)->lits[i])); i++ )
+
+//=================================================================================================
+// Simple helpers:
+
+static inline int     solver2_dlevel(sat_solver2* s)       { return veci_size(&s->trail_lim); }
+static inline veci*   solver2_wlist(sat_solver2* s, lit l) { return &s->wlists[l];            }
+
+//=================================================================================================
+// Proof logging:
+
+static inline void proof_chain_start( sat_solver2* s, clause* c )
+{
+    if ( !s->fProofLogging )
+        return;
+    if ( s->pInt2 )
+        s->tempInter = Int2_ManChainStart( s->pInt2, c );
+    if ( s->pPrf2 )
+        Prf_ManChainStart( s->pPrf2, c );
+    if ( s->pPrf1 )
+    {
+        int ProofId = clause2_proofid(s, c, 0);
+        assert( (ProofId >> 2) > 0 );
+        veci_resize( &s->temp_proof, 0 );
+        veci_push( &s->temp_proof, 0 );
+        veci_push( &s->temp_proof, 0 );
+        veci_push( &s->temp_proof, ProofId );
+    }
+}
+
+static inline void proof_chain_resolve( sat_solver2* s, clause* cls, int Var )
+{
+    if ( !s->fProofLogging )
+        return;
+    if ( s->pInt2 )
+    {
+        clause* c = cls ? cls : var_unit_clause( s, Var );
+        s->tempInter = Int2_ManChainResolve( s->pInt2, c, s->tempInter, var_is_partA(s,Var) );
+    }
+    if ( s->pPrf2 )
+    {
+        clause* c = cls ? cls : var_unit_clause( s, Var );
+        Prf_ManChainResolve( s->pPrf2, c );
+    }
+    if ( s->pPrf1 )
+    {
+        clause* c = cls ? cls : var_unit_clause( s, Var );
+        int ProofId = clause2_proofid(s, c, var_is_partA(s,Var));
+        assert( (ProofId >> 2) > 0 );
+        veci_push( &s->temp_proof, ProofId );
+    }
+}
+
+static inline int proof_chain_stop( sat_solver2* s )
+{
+    if ( !s->fProofLogging )
+        return 0;
+    if ( s->pInt2 )
+    {
+        int h = s->tempInter; 
+        s->tempInter = -1; 
+        return h;
+    }
+    if ( s->pPrf2 )
+        Prf_ManChainStop( s->pPrf2 );
+    if ( s->pPrf1 )
+    {
+        extern void Proof_ClauseSetEnts( Vec_Set_t* p, int h, int nEnts );
+        int h = Vec_SetAppend( s->pPrf1, veci_begin(&s->temp_proof), veci_size(&s->temp_proof) );
+        Proof_ClauseSetEnts( s->pPrf1, h, veci_size(&s->temp_proof) - 2 );
+        return h;
+    }
+    return 0;
+}
+
+//=================================================================================================
+// Variable order functions:
+
+static inline void order_update(sat_solver2* s, int v) // updateorder
+{
+    int*      orderpos = s->orderpos;
+    int*      heap     = veci_begin(&s->order);
+    int       i        = orderpos[v];
+    int       x        = heap[i];
+    int       parent   = (i - 1) / 2;
+    assert(s->orderpos[v] != -1);
+    while (i != 0 && s->activity[x] > s->activity[heap[parent]]){
+        heap[i]           = heap[parent];
+        orderpos[heap[i]] = i;
+        i                 = parent;
+        parent            = (i - 1) / 2;
+    }
+    heap[i]     = x;
+    orderpos[x] = i;
+}
+static inline void order_assigned(sat_solver2* s, int v)
+{
+}
+static inline void order_unassigned(sat_solver2* s, int v) // undoorder
+{
+    int* orderpos = s->orderpos;
+    if (orderpos[v] == -1){
+        orderpos[v] = veci_size(&s->order);
+        veci_push(&s->order,v);
+        order_update(s,v);
+    }
+}
+static inline int  order_select(sat_solver2* s, float random_var_freq) // selectvar
+{
+    int*      heap     = veci_begin(&s->order);
+    int*      orderpos = s->orderpos;
+    // Random decision:
+    if (drand(&s->random_seed) < random_var_freq){
+        int next = irand(&s->random_seed,s->size);
+        assert(next >= 0 && next < s->size);
+        if (var_value(s, next) == varX)
+            return next;
+    }
+    // Activity based decision:
+    while (veci_size(&s->order) > 0){
+        int    next  = heap[0];
+        int    size  = veci_size(&s->order)-1;
+        int    x     = heap[size];
+        veci_resize(&s->order,size);
+        orderpos[next] = -1;
+        if (size > 0){
+            unsigned act   = s->activity[x];
+            int      i     = 0;
+            int      child = 1;
+            while (child < size){
+                if (child+1 < size && s->activity[heap[child]] < s->activity[heap[child+1]])
+                    child++;
+                assert(child < size);
+                if (act >= s->activity[heap[child]])
+                    break;
+                heap[i]           = heap[child];
+                orderpos[heap[i]] = i;
+                i                 = child;
+                child             = 2 * child + 1;
+            }
+            heap[i]           = x;
+            orderpos[heap[i]] = i;
+        }
+        if (var_value(s, next) == varX)
+            return next;
+    }
+    return var_Undef;
+}
+
+
+//=================================================================================================
+// Activity functions:
+
+#ifdef USE_FLOAT_ACTIVITY2
+
+static inline void act_var_rescale(sat_solver2* s)  {
+    double* activity = s->activity;
+    int i;
+    for (i = 0; i < s->size; i++)
+        activity[i] *= 1e-100;
+    s->var_inc *= 1e-100;
+}
+static inline void act_clause2_rescale(sat_solver2* s) {
+    static abctime Total = 0;
+    float * act_clas = (float *)veci_begin(&s->act_clas);
+    int i;
+    abctime clk = Abc_Clock();
+    for (i = 0; i < veci_size(&s->act_clas); i++)
+        act_clas[i] *= (float)1e-20;
+    s->cla_inc *= (float)1e-20;
+
+    Total += Abc_Clock() - clk;
+    Abc_Print(1, "Rescaling...   Cla inc = %10.3f  Conf = %10d   ", s->cla_inc,  s->stats.conflicts );
+    Abc_PrintTime( 1, "Time", Total );
+}
+static inline void act_var_bump(sat_solver2* s, int v) {
+    s->activity[v] += s->var_inc;
+    if (s->activity[v] > 1e100)
+        act_var_rescale(s);
+    if (s->orderpos[v] != -1)
+        order_update(s,v);
+}
+static inline void act_clause2_bump(sat_solver2* s, clause*c) {
+    float * act_clas = (float *)veci_begin(&s->act_clas);
+    assert( c->Id < veci_size(&s->act_clas) );
+    act_clas[c->Id] += s->cla_inc;
+    if (act_clas[c->Id] > (float)1e20)
+        act_clause2_rescale(s);
+}
+static inline void act_var_decay(sat_solver2* s)    { s->var_inc *= s->var_decay; }
+static inline void act_clause2_decay(sat_solver2* s) { s->cla_inc *= s->cla_decay; }
+
+#else
+
+static inline void act_var_rescale(sat_solver2* s) {
+    unsigned* activity = s->activity;
+    int i;
+    for (i = 0; i < s->size; i++)
+        activity[i] >>= 19;
+    s->var_inc >>= 19;
+    s->var_inc = Abc_MaxInt( s->var_inc, (1<<4) );
+}
+static inline void act_clause2_rescale(sat_solver2* s) {
+//    static abctime Total = 0;
+//    abctime clk = Abc_Clock();
+    int i;
+    unsigned * act_clas = (unsigned *)veci_begin(&s->act_clas);
+    for (i = 0; i < veci_size(&s->act_clas); i++)
+        act_clas[i] >>= 14;
+    s->cla_inc >>= 14;
+    s->cla_inc = Abc_MaxInt( s->cla_inc, (1<<10) );
+//    Total += Abc_Clock() - clk;
+//    Abc_Print(1, "Rescaling...   Cla inc = %5d  Conf = %10d   ", s->cla_inc,  s->stats.conflicts );
+//    Abc_PrintTime( 1, "Time", Total );
+}
+static inline void act_var_bump(sat_solver2* s, int v) {
+    s->activity[v] += s->var_inc;
+    if (s->activity[v] & 0x80000000)
+        act_var_rescale(s);
+    if (s->orderpos[v] != -1)
+        order_update(s,v);
+}
+static inline void act_clause2_bump(sat_solver2* s, clause*c) {
+    unsigned * act_clas = (unsigned *)veci_begin(&s->act_clas);
+    int Id = clause_id(c);
+    assert( Id >= 0 && Id < veci_size(&s->act_clas) );
+    act_clas[Id] += s->cla_inc;
+    if (act_clas[Id] & 0x80000000)
+        act_clause2_rescale(s);
+}
+static inline void act_var_decay(sat_solver2* s)    { s->var_inc += (s->var_inc >>  4); }
+static inline void act_clause2_decay(sat_solver2* s) { s->cla_inc += (s->cla_inc >> 10); }
+
+#endif
+
+//=================================================================================================
+// Clause functions:
+
+static inline int sat_clause_compute_lbd( sat_solver2* s, clause* c )
+{
+    int i, lev, minl = 0, lbd = 0;
+    for (i = 0; i < (int)c->size; i++) {
+        lev = var_level(s, lit_var(c->lits[i]));
+        if ( !(minl & (1 << (lev & 31))) ) {
+            minl |= 1 << (lev & 31);
+            lbd++;
+        }
+    }
+    return lbd;
+}
+
+static int clause2_create_new(sat_solver2* s, lit* begin, lit* end, int learnt, int proof_id )
+{
+    clause* c;
+    int h, size = end - begin;
+    assert(size < 1 || begin[0] >= 0);
+    assert(size < 2 || begin[1] >= 0);
+    assert(size < 1 || lit_var(begin[0]) < s->size);
+    assert(size < 2 || lit_var(begin[1]) < s->size);
+    // create new clause
+    h = Sat_MemAppend( &s->Mem, begin, size, learnt, 1 );
+    assert( !(h & 1) );
+    c = clause2_read( s, h );
+    if (learnt)
+    {
+        if ( s->pPrf1 )
+            assert( proof_id );
+        c->lbd = sat_clause_compute_lbd( s, c );
+        assert( clause_id(c) == veci_size(&s->act_clas) );
+        if ( s->pPrf1 || s->pInt2 )
+            veci_push(&s->claProofs, proof_id);
+//        veci_push(&s->act_clas, (1<<10));
+        veci_push(&s->act_clas, 0);
+        if ( size > 2 )
+            act_clause2_bump( s,c );
+        s->stats.learnts++;
+        s->stats.learnts_literals += size;
+        // remember the last one
+        s->hLearntLast = h;
+    }
+    else
+    {
+        assert( clause_id(c) == (int)s->stats.clauses );
+        s->stats.clauses++;
+        s->stats.clauses_literals += size;
+    }
+    // watch the clause
+    if ( size > 1 )
+    {
+        veci_push(solver2_wlist(s,lit_neg(begin[0])),h);
+        veci_push(solver2_wlist(s,lit_neg(begin[1])),h);
+    }
+    return h;
+}
+
+//=================================================================================================
+// Minor (solver) functions:
+
+static inline int solver2_enqueue(sat_solver2* s, lit l, cla from)
+{
+    int v = lit_var(l);
+#ifdef VERBOSEDEBUG
+    Abc_Print(1,L_IND"enqueue("L_LIT")\n", L_ind, L_lit(l));
+#endif
+    if (var_value(s, v) != varX)
+        return var_value(s, v) == lit_sign(l);
+    else
+    {  // New fact -- store it.
+#ifdef VERBOSEDEBUG
+        Abc_Print(1,L_IND"bind("L_LIT")\n", L_ind, L_lit(l));
+#endif
+        var_set_value( s, v, lit_sign(l) );
+        var_set_level( s, v, solver2_dlevel(s) );
+        s->reasons[v] = from;  //  = from << 1;
+        s->trail[s->qtail++] = l;
+        order_assigned(s, v);
+        return true;
+    }
+}
+
+static inline int solver2_assume(sat_solver2* s, lit l)
+{
+    assert(s->qtail == s->qhead);
+    assert(var_value(s, lit_var(l)) == varX);
+#ifdef VERBOSEDEBUG
+    Abc_Print(1,L_IND"assume("L_LIT")  ", L_ind, L_lit(l));
+    Abc_Print(1, "act = %.20f\n", s->activity[lit_var(l)] );
+#endif
+    veci_push(&s->trail_lim,s->qtail);
+    return solver2_enqueue(s,l,0);
+}
+
+static void solver2_canceluntil(sat_solver2* s, int level) {
+    int      bound;
+    int      lastLev;
+    int      c, x;
+
+    if (solver2_dlevel(s) <= level)
+        return;
+    assert( solver2_dlevel(s) > 0 );
+
+    bound   = (veci_begin(&s->trail_lim))[level];
+    lastLev = (veci_begin(&s->trail_lim))[veci_size(&s->trail_lim)-1];
+
+    for (c = s->qtail-1; c >= bound; c--)
+    {
+        x = lit_var(s->trail[c]);
+        var_set_value(s, x, varX);
+        s->reasons[x] = 0;
+        s->units[x] = 0; // temporary?
+        if ( c < lastLev )
+            var_set_polar(s, x, !lit_sign(s->trail[c]));
+    }
+
+    for (c = s->qhead-1; c >= bound; c--)
+        order_unassigned(s,lit_var(s->trail[c]));
+
+    s->qhead = s->qtail = bound;
+    veci_resize(&s->trail_lim,level);
+}
+
+static void solver2_canceluntil_rollback(sat_solver2* s, int NewBound) {
+    int      c, x;
+   
+    assert( solver2_dlevel(s) == 0 );
+    assert( s->qtail == s->qhead );
+    assert( s->qtail >= NewBound );
+
+    for (c = s->qtail-1; c >= NewBound; c--) 
+    {
+        x = lit_var(s->trail[c]);
+        var_set_value(s, x, varX);
+        s->reasons[x] = 0;
+        s->units[x] = 0; // temporary?
+    }
+
+    for (c = s->qhead-1; c >= NewBound; c--)
+        order_unassigned(s,lit_var(s->trail[c]));
+
+    s->qhead = s->qtail = NewBound;
+}
+
+
+static void solver2_record(sat_solver2* s, veci* cls, int proof_id)
+{
+    lit* begin = veci_begin(cls);
+    lit* end   = begin + veci_size(cls);
+    cla  Cid   = clause2_create_new(s,begin,end,1, proof_id);
+    assert(veci_size(cls) > 0);
+    if ( veci_size(cls) == 1 )
+    {
+        if ( s->fProofLogging )
+            var_set_unit_clause(s, lit_var(begin[0]), Cid);
+        Cid = 0;
+    }
+    solver2_enqueue(s, begin[0], Cid);
+}
+
+
+static double solver2_progress(sat_solver2* s)
+{
+    int i;
+    double progress = 0.0, F = 1.0 / s->size;
+    for (i = 0; i < s->size; i++)
+        if (var_value(s, i) != varX)
+            progress += pow(F, var_level(s, i));
+    return progress / s->size;
+}
+
+//=================================================================================================
+// Major methods:
+
+/*_________________________________________________________________________________________________
+|
+|  analyzeFinal : (p : Lit)  ->  [void]
+|  
+|  Description:
+|    Specialized analysis procedure to express the final conflict in terms of assumptions.
+|    Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and
+|    stores the result in 'out_conflict'.
+|________________________________________________________________________________________________@*/
+/*
+void Solver::analyzeFinal(clause* confl, bool skip_first)
+{
+    // -- NOTE! This code is relatively untested. Please report bugs!
+    conflict.clear();
+    if (root_level == 0) return;
+
+    vec<char>& seen  = analyze_seen;
+    for (int i = skip_first ? 1 : 0; i < confl->size(); i++){
+        Var x = var((*confl)[i]);
+        if (level[x] > 0)
+            seen[x] = 1;
+    }
+
+    int start = (root_level >= trail_lim.size()) ? trail.size()-1 : trail_lim[root_level];
+    for (int i = start; i >= trail_lim[0]; i--){
+        Var     x = var(trail[i]);
+        if (seen[x]){
+            GClause r = reason[x];
+            if (r == Gclause2_NULL){
+                assert(level[x] > 0);
+                conflict.push(~trail[i]);
+            }else{
+                if (r.isLit()){
+                    Lit p = r.lit();
+                    if (level[var(p)] > 0)
+                        seen[var(p)] = 1;
+                }else{
+                    Clause& c = *r.clause();
+                    for (int j = 1; j < c.size(); j++)
+                        if (level[var(c[j])] > 0)
+                            seen[var(c[j])] = 1;
+                }
+            }
+            seen[x] = 0;
+        }
+    }
+}
+*/
+
+static int solver2_analyze_final(sat_solver2* s, clause* conf, int skip_first)
+{
+    int i, j, x;//, start;
+    veci_resize(&s->conf_final,0);
+    if ( s->root_level == 0 )
+        return s->hProofLast;
+    proof_chain_start( s, conf );
+    assert( veci_size(&s->tagged) == 0 );
+    clause_foreach_var( conf, x, i, skip_first ){
+        if ( var_level(s,x) )
+            var_set_tag(s, x, 1);
+        else
+            proof_chain_resolve( s, NULL, x );
+    }
+    assert( s->root_level >= veci_size(&s->trail_lim) );
+//    start = (s->root_level >= veci_size(&s->trail_lim))? s->qtail-1 : (veci_begin(&s->trail_lim))[s->root_level];
+    for (i = s->qtail-1; i >= (veci_begin(&s->trail_lim))[0]; i--){
+        x = lit_var(s->trail[i]);
+        if (var_tag(s,x)){
+            clause* c = clause2_read(s, var_reason(s,x));
+            if (c){
+                proof_chain_resolve( s, c, x );
+                clause_foreach_var( c, x, j, 1 ){
+                    if ( var_level(s,x) )
+                        var_set_tag(s, x, 1);
+                    else
+                        proof_chain_resolve( s, NULL, x );
+                }
+            }else {
+                assert( var_level(s,x) );
+                veci_push(&s->conf_final,lit_neg(s->trail[i]));
+            }
+        }
+    }
+    solver2_clear_tags(s,0);
+    return proof_chain_stop( s );
+}
+
+static int solver2_lit_removable_rec(sat_solver2* s, int v)
+{
+    // tag[0]: True if original conflict clause literal.
+    // tag[1]: Processed by this procedure
+    // tag[2]: 0=non-removable, 1=removable
+
+    clause* c;
+    int i, x;
+
+    // skip visited
+    if (var_tag(s,v) & 2)
+        return (var_tag(s,v) & 4) > 0;
+
+    // skip decisions on a wrong level
+    c = clause2_read(s, var_reason(s,v));
+    if ( c == NULL ){
+        var_add_tag(s,v,2);
+        return 0;
+    }
+
+    clause_foreach_var( c, x, i, 1 ){
+        if (var_tag(s,x) & 1)
+            solver2_lit_removable_rec(s, x);
+        else{
+            if (var_level(s,x) == 0 || var_tag(s,x) == 6) continue;     // -- 'x' checked before, found to be removable (or belongs to the toplevel)
+            if (var_tag(s,x) == 2 || !var_lev_mark(s,x) || !solver2_lit_removable_rec(s, x))
+            {  // -- 'x' checked before, found NOT to be removable, or it belongs to a wrong level, or cannot be removed
+                var_add_tag(s,v,2);
+                return 0;
+            }
+        }
+    }
+    if ( s->fProofLogging && (var_tag(s,v) & 1) )
+        veci_push(&s->min_lit_order, v );
+    var_add_tag(s,v,6);
+    return 1;
+}
+
+static int solver2_lit_removable(sat_solver2* s, int x)
+{
+    clause* c;
+    int i, top;
+    if ( !var_reason(s,x) )
+        return 0;
+    if ( var_tag(s,x) & 2 )
+    {
+        assert( var_tag(s,x) & 1 );
+        return 1;
+    }
+    top = veci_size(&s->tagged);
+    veci_resize(&s->stack,0);
+    veci_push(&s->stack, x << 1);
+    while (veci_size(&s->stack))
+    {
+        x = veci_pop(&s->stack);
+        if ( s->fProofLogging )
+        {
+            if ( x & 1 ){
+                if ( var_tag(s,x >> 1) & 1 )
+                    veci_push(&s->min_lit_order, x >> 1 );
+                continue;
+            }
+            veci_push(&s->stack, x ^ 1 );
+        }
+        x >>= 1;
+        c = clause2_read(s, var_reason(s,x));
+        clause_foreach_var( c, x, i, 1 ){
+            if (var_tag(s,x) || !var_level(s,x))
+                continue;
+            if (!var_reason(s,x) || !var_lev_mark(s,x)){
+                solver2_clear_tags(s, top);
+                return 0;
+            }
+            veci_push(&s->stack, x << 1);
+            var_set_tag(s, x, 2);
+        }
+    }
+    return 1;
+}
+
+static void solver2_logging_order(sat_solver2* s, int x)
+{
+    clause* c;
+    int i;
+    if ( (var_tag(s,x) & 4) )
+        return;
+    var_add_tag(s, x, 4);
+    veci_resize(&s->stack,0);
+    veci_push(&s->stack,x << 1);
+    while (veci_size(&s->stack))
+    {
+        x = veci_pop(&s->stack);
+        if ( x & 1 ){
+            veci_push(&s->min_step_order, x >> 1 );
+            continue;
+        }
+        veci_push(&s->stack, x ^ 1 );
+        x >>= 1;
+        c = clause2_read(s, var_reason(s,x));
+//        if ( !c )
+//            Abc_Print(1, "solver2_logging_order(): Error in conflict analysis!!!\n" );
+        clause_foreach_var( c, x, i, 1 ){
+            if ( !var_level(s,x) || (var_tag(s,x) & 1) )
+                continue;
+            veci_push(&s->stack, x << 1);
+            var_add_tag(s, x, 4);
+        }
+    }
+}
+
+static void solver2_logging_order_rec(sat_solver2* s, int x)
+{
+    clause* c;
+    int i, y;
+    if ( (var_tag(s,x) & 8) )
+        return;
+    c = clause2_read(s, var_reason(s,x));
+    clause_foreach_var( c, y, i, 1 )
+        if ( var_level(s,y) && (var_tag(s,y) & 1) == 0 )
+            solver2_logging_order_rec(s, y);
+    var_add_tag(s, x, 8);
+    veci_push(&s->min_step_order, x);
+}
+
+static int solver2_analyze(sat_solver2* s, clause* c, veci* learnt)
+{
+    int cnt      = 0;
+    lit p        = 0;
+    int x, ind   = s->qtail-1;
+    int proof_id = 0;
+    lit* lits,* vars, i, j, k;
+    assert( veci_size(&s->tagged) == 0 );
+    // tag[0] - visited by conflict analysis (afterwards: literals of the learned clause)
+    // tag[1] - visited by solver2_lit_removable() with success
+    // tag[2] - visited by solver2_logging_order()
+
+    proof_chain_start( s, c );
+    veci_push(learnt,lit_Undef);
+    while ( 1 ){
+        assert(c != 0);
+        if (c->lrn)
+            act_clause2_bump(s,c);
+        clause_foreach_var( c, x, j, (int)(p > 0) ){
+            assert(x >= 0 && x < s->size);
+            if ( var_tag(s, x) )
+                continue;
+            if ( var_level(s,x) == 0 )
+            {
+                proof_chain_resolve( s, NULL, x );
+                continue;
+            }
+            var_set_tag(s, x, 1);
+            act_var_bump(s,x);
+            if (var_level(s,x) == solver2_dlevel(s))
+                cnt++;
+            else
+                veci_push(learnt,c->lits[j]);
+        }
+
+        while (!var_tag(s, lit_var(s->trail[ind--])));
+
+        p = s->trail[ind+1];
+        c = clause2_read(s, lit_reason(s,p));
+        cnt--;
+        if ( cnt == 0 )
+            break;
+        proof_chain_resolve( s, c, lit_var(p) );
+    }
+    *veci_begin(learnt) = lit_neg(p);
+
+    // mark levels
+    assert( veci_size(&s->mark_levels) == 0 );
+    lits = veci_begin(learnt);
+    for (i = 1; i < veci_size(learnt); i++)
+        var_lev_set_mark(s, lit_var(lits[i]));
+
+    // simplify (full)
+    veci_resize(&s->min_lit_order, 0);
+    for (i = j = 1; i < veci_size(learnt); i++){
+//        if (!solver2_lit_removable( s,lit_var(lits[i])))
+        if (!solver2_lit_removable_rec(s,lit_var(lits[i]))) // changed to vars!!!
+            lits[j++] = lits[i];
+    }
+
+    // record the proof
+    if ( s->fProofLogging )
+    {
+        // collect additional clauses to resolve
+        veci_resize(&s->min_step_order, 0);
+        vars = veci_begin(&s->min_lit_order);
+        for (i = 0; i < veci_size(&s->min_lit_order); i++)
+//            solver2_logging_order(s, vars[i]);
+            solver2_logging_order_rec(s, vars[i]);
+
+        // add them in the reverse order
+        vars = veci_begin(&s->min_step_order);
+        for (i = veci_size(&s->min_step_order); i > 0; ) { i--;
+            c = clause2_read(s, var_reason(s,vars[i]));
+            proof_chain_resolve( s, c, vars[i] );
+            clause_foreach_var(c, x, k, 1)
+                if ( var_level(s,x) == 0 )
+                    proof_chain_resolve( s, NULL, x );
+        }
+        proof_id = proof_chain_stop( s );
+    }
+
+    // unmark levels
+    solver2_clear_marks( s );
+
+    // update size of learnt + statistics
+    veci_resize(learnt,j);
+    s->stats.tot_literals += j;
+
+    // clear tags
+    solver2_clear_tags(s,0);
+
+#ifdef DEBUG
+    for (i = 0; i < s->size; i++)
+        assert(!var_tag(s, i));
+#endif
+
+#ifdef VERBOSEDEBUG
+    Abc_Print(1,L_IND"Learnt {", L_ind);
+    for (i = 0; i < veci_size(learnt); i++) Abc_Print(1," "L_LIT, L_lit(lits[i]));
+#endif
+    if (veci_size(learnt) > 1){
+        lit tmp;
+        int max_i = 1;
+        int max   = var_level(s, lit_var(lits[1]));
+        for (i = 2; i < veci_size(learnt); i++)
+            if (max < var_level(s, lit_var(lits[i]))) {
+                max = var_level(s, lit_var(lits[i]));
+                max_i = i;
+            }
+
+        tmp         = lits[1];
+        lits[1]     = lits[max_i];
+        lits[max_i] = tmp;
+    }
+#ifdef VERBOSEDEBUG
+    {
+        int lev = veci_size(learnt) > 1 ? var_level(s, lit_var(lits[1])) : 0;
+        Abc_Print(1," } at level %d\n", lev);
+    }
+#endif
+    return proof_id;
+}
+
+clause* solver2_propagate(sat_solver2* s)
+{
+    clause* c, * confl  = NULL;
+    veci* ws;
+    lit* lits, false_lit, p, * stop, * k;
+    cla* begin,* end, *i, *j;
+    int Lit;
+
+    while (confl == 0 && s->qtail - s->qhead > 0){
+
+        p  = s->trail[s->qhead++];
+        ws = solver2_wlist(s,p);
+        begin = (cla*)veci_begin(ws);
+        end   = begin + veci_size(ws);
+
+        s->stats.propagations++;
+        for (i = j = begin; i < end; ){
+            c = clause2_read(s,*i);
+            lits = c->lits;
+
+            // Make sure the false literal is data[1]:
+            false_lit = lit_neg(p);
+            if (lits[0] == false_lit){
+                lits[0] = lits[1];
+                lits[1] = false_lit;
+            }
+            assert(lits[1] == false_lit);
+
+            // If 0th watch is true, then clause is already satisfied.
+            if (var_value(s, lit_var(lits[0])) == lit_sign(lits[0]))
+                *j++ = *i;
+            else{
+                // Look for new watch:
+                stop = lits + c->size;
+                for (k = lits + 2; k < stop; k++){
+                    if (var_value(s, lit_var(*k)) != !lit_sign(*k)){
+                        lits[1] = *k;
+                        *k = false_lit;
+                        veci_push(solver2_wlist(s,lit_neg(lits[1])),*i);
+                        goto WatchFound; }
+                }
+
+                // Did not find watch -- clause is unit under assignment:
+                Lit = lits[0];
+                if ( s->fProofLogging && solver2_dlevel(s) == 0 )
+                {
+                    int k, x, proof_id, Cid, Var = lit_var(Lit);
+                    int fLitIsFalse = (var_value(s, Var) == !lit_sign(Lit));
+                    // Log production of top-level unit clause:
+                    proof_chain_start( s, c );
+                    clause_foreach_var( c, x, k, 1 ){
+                        assert( var_level(s, x) == 0 );
+                        proof_chain_resolve( s, NULL, x );
+                    }
+                    proof_id = proof_chain_stop( s );
+                    // get a new clause
+                    Cid = clause2_create_new( s, &Lit, &Lit + 1, 1, proof_id );
+                    assert( (var_unit_clause(s, Var) == NULL) != fLitIsFalse );
+                    // if variable already has unit clause, it must be with the other polarity 
+                    // in this case, we should derive the empty clause here
+                    if ( var_unit_clause(s, Var) == NULL )
+                        var_set_unit_clause(s, Var, Cid);
+                    else{
+                        // Empty clause derived:
+                        proof_chain_start( s, clause2_read(s,Cid) );
+                        proof_chain_resolve( s, NULL, Var );
+                        proof_id = proof_chain_stop( s );
+                        s->hProofLast = proof_id;
+//                        clause2_create_new( s, &Lit, &Lit, 1, proof_id );
+                    }
+                }
+
+                *j++ = *i;
+                // Clause is unit under assignment:
+                if ( c->lrn )
+                    c->lbd = sat_clause_compute_lbd(s, c);
+                if (!solver2_enqueue(s,Lit, *i)){
+                    confl = clause2_read(s,*i++);
+                    // Copy the remaining watches:
+                    while (i < end)
+                        *j++ = *i++;
+                }
+            }
+WatchFound: i++;
+        }
+        s->stats.inspects += j - (int*)veci_begin(ws);
+        veci_resize(ws,j - (int*)veci_begin(ws));
+    }
+
+    return confl;
+}
+
+int sat_solver2_simplify(sat_solver2* s)
+{
+    assert(solver2_dlevel(s) == 0);
+    return (solver2_propagate(s) == NULL);
+}
+
+static lbool solver2_search(sat_solver2* s, ABC_INT64_T nof_conflicts)
+{
+    double  random_var_freq = s->fNotUseRandom ? 0.0 : 0.02;
+
+    ABC_INT64_T  conflictC       = 0;
+    veci    learnt_clause;
+    int     proof_id;
+
+    assert(s->root_level == solver2_dlevel(s));
+
+    s->stats.starts++;
+//    s->var_decay = (float)(1 / 0.95   );
+//    s->cla_decay = (float)(1 / 0.999);
+    veci_new(&learnt_clause);
+
+    for (;;){
+        clause* confl = solver2_propagate(s);
+        if (confl != 0){
+            // CONFLICT
+            int blevel;
+
+#ifdef VERBOSEDEBUG
+            Abc_Print(1,L_IND"**CONFLICT**\n", L_ind);
+#endif
+            s->stats.conflicts++; conflictC++;
+            if (solver2_dlevel(s) <= s->root_level){
+                proof_id = solver2_analyze_final(s, confl, 0);
+                if ( s->pPrf1 )
+                    assert( proof_id > 0 );
+                s->hProofLast = proof_id;
+                veci_delete(&learnt_clause);
+                return l_False;
+            }
+
+            veci_resize(&learnt_clause,0);
+            proof_id = solver2_analyze(s, confl, &learnt_clause);
+            blevel = veci_size(&learnt_clause) > 1 ? var_level(s, lit_var(veci_begin(&learnt_clause)[1])) : s->root_level;
+            blevel = s->root_level > blevel ? s->root_level : blevel;
+            solver2_canceluntil(s,blevel);
+            solver2_record(s,&learnt_clause, proof_id);
+            // if (learnt_clause.size() == 1) level[var(learnt_clause[0])] = 0;    
+            // (this is ugly (but needed for 'analyzeFinal()') -- in future versions, we will backtrack past the 'root_level' and redo the assumptions)
+            if ( learnt_clause.size == 1 )
+                var_set_level( s, lit_var(learnt_clause.ptr[0]), 0 );
+            act_var_decay(s);
+            act_clause2_decay(s);
+
+        }else{
+            // NO CONFLICT
+            int next;
+
+            if ((nof_conflicts >= 0 && conflictC >= nof_conflicts) || (s->nRuntimeLimit && (s->stats.conflicts & 63) == 0 && Abc_Clock() > s->nRuntimeLimit)){
+                // Reached bound on number of conflicts:
+                s->progress_estimate = solver2_progress(s);
+                solver2_canceluntil(s,s->root_level);
+                veci_delete(&learnt_clause);
+                return l_Undef; }
+
+            if ( (s->nConfLimit && s->stats.conflicts > s->nConfLimit) ||
+//                 (s->nInsLimit  && s->stats.inspects  > s->nInsLimit) )
+                 (s->nInsLimit  && s->stats.propagations > s->nInsLimit) )
+            {
+                // Reached bound on number of conflicts:
+                s->progress_estimate = solver2_progress(s);
+                solver2_canceluntil(s,s->root_level);
+                veci_delete(&learnt_clause);
+                return l_Undef;
+            }
+
+//            if (solver2_dlevel(s) == 0 && !s->fSkipSimplify)
+                // Simplify the set of problem clauses:
+//                sat_solver2_simplify(s);
+
+            // Reduce the set of learnt clauses:
+//            if (s->nLearntMax > 0 && s->stats.learnts >= (unsigned)s->nLearntMax)
+//                sat_solver2_reducedb(s);
+
+            // New variable decision:
+            s->stats.decisions++;
+            next = order_select(s,(float)random_var_freq);
+
+            if (next == var_Undef){
+                // Model found:
+                int i;
+                for (i = 0; i < s->size; i++)
+                {
+                    assert( var_value(s,i) != varX );
+                    s->model[i] = (var_value(s,i)==var1 ? l_True : l_False);
+                }
+                solver2_canceluntil(s,s->root_level);
+                veci_delete(&learnt_clause);
+                return l_True;
+            }
+
+            if ( var_polar(s, next) ) // positive polarity
+                solver2_assume(s,toLit(next));
+            else
+                solver2_assume(s,lit_neg(toLit(next)));
+        }
+    }
+
+    return l_Undef; // cannot happen
+}
+
+//=================================================================================================
+// External solver functions:
+
+sat_solver2* sat_solver2_new(void)
+{
+    sat_solver2* s = (sat_solver2 *)ABC_CALLOC( char, sizeof(sat_solver2) );
+
+#ifdef USE_FLOAT_ACTIVITY2
+    s->var_inc        = 1;
+    s->cla_inc        = 1;
+    s->var_decay      = (float)(1 / 0.95  );
+    s->cla_decay      = (float)(1 / 0.999 );
+//    s->cla_decay      = 1;
+//    s->var_decay      = 1;
+#else
+    s->var_inc        = (1 <<  5);
+    s->cla_inc        = (1 << 11);
+#endif
+    s->random_seed    = 91648253;
+
+#ifdef SAT_USE_PROOF_LOGGING
+    s->fProofLogging  =  1;
+#else
+    s->fProofLogging  =  0;
+#endif
+    s->fSkipSimplify  =  1;
+    s->fNotUseRandom  =  0;
+    s->fVerbose       =  0;
+
+    s->nLearntStart   = LEARNT_MAX_START_DEFAULT;  // starting learned clause limit
+    s->nLearntDelta   = LEARNT_MAX_INCRE_DEFAULT;  // delta of learned clause limit
+    s->nLearntRatio   = LEARNT_MAX_RATIO_DEFAULT;  // ratio of learned clause limit
+    s->nLearntMax     = s->nLearntStart;
+
+    // initialize vectors
+    veci_new(&s->order);
+    veci_new(&s->trail_lim);
+    veci_new(&s->tagged);
+    veci_new(&s->stack);
+    veci_new(&s->temp_clause);
+    veci_new(&s->temp_proof);
+    veci_new(&s->conf_final);
+    veci_new(&s->mark_levels);
+    veci_new(&s->min_lit_order);
+    veci_new(&s->min_step_order);
+//    veci_new(&s->learnt_live);
+    Sat_MemAlloc_( &s->Mem, 14 );
+    veci_new(&s->act_clas);  
+    // proof-logging
+    veci_new(&s->claProofs);
+//    s->pPrf1 = Vec_SetAlloc( 20 );
+    s->tempInter = -1;
+
+    // initialize clause pointers
+    s->hLearntLast            = -1; // the last learnt clause 
+    s->hProofLast             = -1; // the last proof ID
+    // initialize rollback
+    s->iVarPivot              =  0; // the pivot for variables
+    s->iTrailPivot            =  0; // the pivot for trail
+    s->hProofPivot            =  1; // the pivot for proof records
+    return s;
+}
+
+
+void sat_solver2_setnvars(sat_solver2* s,int n)
+{
+    int var;
+
+    if (s->cap < n){
+        int old_cap = s->cap;
+        while (s->cap < n) s->cap = s->cap*2+1;
+
+        s->wlists    = ABC_REALLOC(veci,     s->wlists,   s->cap*2);
+        s->vi        = ABC_REALLOC(varinfo2, s->vi,       s->cap);
+        s->levels    = ABC_REALLOC(int,      s->levels,   s->cap);
+        s->assigns   = ABC_REALLOC(char,     s->assigns,  s->cap);
+        s->trail     = ABC_REALLOC(lit,      s->trail,    s->cap);
+        s->orderpos  = ABC_REALLOC(int,      s->orderpos, s->cap);
+        s->reasons   = ABC_REALLOC(cla,      s->reasons,  s->cap);
+        if ( s->fProofLogging )
+        s->units     = ABC_REALLOC(cla,      s->units,    s->cap);
+#ifdef USE_FLOAT_ACTIVITY2
+        s->activity  = ABC_REALLOC(double,   s->activity, s->cap);
+#else
+        s->activity  = ABC_REALLOC(unsigned, s->activity, s->cap);
+        s->activity2 = ABC_REALLOC(unsigned, s->activity2,s->cap);
+#endif
+        s->model     = ABC_REALLOC(int,      s->model,    s->cap);
+        memset( s->wlists + 2*old_cap, 0, 2*(s->cap-old_cap)*sizeof(vecp) );
+    }
+
+    for (var = s->size; var < n; var++){
+        assert(!s->wlists[2*var].size);
+        assert(!s->wlists[2*var+1].size);
+        if ( s->wlists[2*var].ptr == NULL )
+            veci_new(&s->wlists[2*var]);
+        if ( s->wlists[2*var+1].ptr == NULL )
+            veci_new(&s->wlists[2*var+1]);
+        *((int*)s->vi + var) = 0; //s->vi[var].val = varX;
+        s->levels  [var] = 0;
+        s->assigns [var] = varX;
+        s->reasons [var] = 0;
+        if ( s->fProofLogging )
+        s->units   [var] = 0;
+#ifdef USE_FLOAT_ACTIVITY2
+        s->activity[var] = 0;
+#else
+        s->activity[var] = (1<<10);
+#endif
+        s->model   [var] = 0;
+        // does not hold because variables enqueued at top level will not be reinserted in the heap
+        // assert(veci_size(&s->order) == var); 
+        s->orderpos[var] = veci_size(&s->order);
+        veci_push(&s->order,var);
+        order_update(s, var);
+    }
+    s->size = n > s->size ? n : s->size;
+}
+
+void sat_solver2_delete(sat_solver2* s)
+{
+    int fVerify = 0;
+    if ( fVerify )
+    {
+        veci * pCore = (veci *)Sat_ProofCore( s );
+//        Abc_Print(1, "UNSAT core contains %d clauses (%6.2f %%).\n", veci_size(pCore), 100.0*veci_size(pCore)/veci_size(&s->clauses) );
+        veci_delete( pCore );
+        ABC_FREE( pCore );
+//        if ( s->fProofLogging )
+//            Sat_ProofCheck( s );
+    }
+
+    // report statistics
+//    Abc_Print(1, "Used %6.2f MB for proof-logging.   Unit clauses = %d.\n", 1.0 * Vec_ReportMemory(&s->Proofs) / (1<<20), s->nUnits );
+
+    // delete vectors
+    veci_delete(&s->order);
+    veci_delete(&s->trail_lim);
+    veci_delete(&s->tagged);
+    veci_delete(&s->stack);
+    veci_delete(&s->temp_clause);
+    veci_delete(&s->temp_proof);
+    veci_delete(&s->conf_final);
+    veci_delete(&s->mark_levels);
+    veci_delete(&s->min_lit_order);
+    veci_delete(&s->min_step_order);
+//    veci_delete(&s->learnt_live);
+    veci_delete(&s->act_clas);
+    veci_delete(&s->claProofs);
+//    veci_delete(&s->clauses);
+//    veci_delete(&s->lrns);
+    Sat_MemFree_( &s->Mem );
+//    veci_delete(&s->proofs);
+    Vec_SetFree( s->pPrf1 );
+    Prf_ManStop( s->pPrf2 );
+    Int2_ManStop( s->pInt2 );
+
+    // delete arrays
+    if (s->vi != 0){
+        int i;
+        if ( s->wlists )
+            for (i = 0; i < s->cap*2; i++)
+                veci_delete(&s->wlists[i]);
+        ABC_FREE(s->wlists   );
+        ABC_FREE(s->vi       );
+        ABC_FREE(s->levels   );
+        ABC_FREE(s->assigns  );
+        ABC_FREE(s->trail    );
+        ABC_FREE(s->orderpos );
+        ABC_FREE(s->reasons  );
+        ABC_FREE(s->units    );
+        ABC_FREE(s->activity );
+        ABC_FREE(s->activity2);
+        ABC_FREE(s->model    );
+    }
+    ABC_FREE(s);
+
+//    Abc_PrintTime( 1, "Time", Time );
+}
+
+
+int sat_solver2_addclause(sat_solver2* s, lit* begin, lit* end, int Id)
+{
+    cla Cid;
+    lit *i,*j,*iFree = NULL;
+    int maxvar, count, temp;
+    assert( solver2_dlevel(s) == 0 );
+    assert( begin < end );
+    assert( Id != 0 );
+
+    // copy clause into storage
+    veci_resize( &s->temp_clause, 0 );
+    for ( i = begin; i < end; i++ )
+        veci_push( &s->temp_clause, *i );
+    begin = veci_begin( &s->temp_clause );
+    end = begin + veci_size( &s->temp_clause );
+
+    // insertion sort
+    maxvar = lit_var(*begin);
+    for (i = begin + 1; i < end; i++){
+        lit l = *i;
+        maxvar = lit_var(l) > maxvar ? lit_var(l) : maxvar;
+        for (j = i; j > begin && *(j-1) > l; j--)
+            *j = *(j-1);
+        *j = l;
+    }
+    sat_solver2_setnvars(s,maxvar+1);
+
+
+    // delete duplicates
+    for (i = j = begin + 1; i < end; i++)
+    {
+        if ( *(i-1) == lit_neg(*i) ) // tautology
+            return clause2_create_new( s, begin, end, 0, 0 ); // add it anyway, to preserve proper clause count       
+        if ( *(i-1) != *i )
+            *j++ = *i;
+    }
+    end = j;
+    assert( begin < end );
+
+    // coount the number of 0-literals
+    count = 0;
+    for ( i = begin; i < end; i++ )
+    {
+        // make sure all literals are unique
+        assert( i == begin || lit_var(*(i-1)) != lit_var(*i) );
+        // consider the value of this literal
+        if ( var_value(s, lit_var(*i)) == lit_sign(*i) ) // this clause is always true
+            return clause2_create_new( s, begin, end, 0, 0 ); // add it anyway, to preserve proper clause count       
+        if ( var_value(s, lit_var(*i)) == varX ) // unassigned literal
+            iFree = i;
+        else
+            count++; // literal is 0
+    }
+    assert( count < end-begin ); // the clause cannot be UNSAT
+
+    // swap variables to make sure the clause is watched using unassigned variable
+    temp   = *iFree;
+    *iFree = *begin;
+    *begin = temp;
+
+    // create a new clause
+    Cid = clause2_create_new( s, begin, end, 0, 0 );
+    if ( Id )
+        clause2_set_id( s, Cid, Id );
+
+    // handle unit clause
+    if ( count+1 == end-begin )
+    {
+        if ( s->fProofLogging )
+        {
+            if ( count == 0 ) // original learned clause
+            {
+                var_set_unit_clause( s, lit_var(begin[0]), Cid );
+                if ( !solver2_enqueue(s,begin[0],0) )
+                    assert( 0 );
+            }
+            else
+            {
+                // Log production of top-level unit clause:
+                int x, k, proof_id, CidNew;
+                clause* c = clause2_read(s, Cid);
+                proof_chain_start( s, c );
+                clause_foreach_var( c, x, k, 1 )
+                    proof_chain_resolve( s, NULL, x );
+                proof_id = proof_chain_stop( s );
+                // generate a new clause
+                CidNew = clause2_create_new( s, begin, begin+1, 1, proof_id );
+                var_set_unit_clause( s, lit_var(begin[0]), CidNew );
+                if ( !solver2_enqueue(s,begin[0],Cid) )
+                    assert( 0 );
+            }
+        }
+    }
+    return Cid;
+}
+
+
+double luby2(double y, int x)
+{
+    int size, seq;
+    for (size = 1, seq = 0; size < x+1; seq++, size = 2*size + 1);
+    while (size-1 != x){
+        size = (size-1) >> 1;
+        seq--;
+        x = x % size;
+    }
+    return pow(y, (double)seq);
+}
+
+void luby2_test()
+{
+    int i;
+    for ( i = 0; i < 20; i++ )
+        Abc_Print(1, "%d ", (int)luby2(2,i) );
+    Abc_Print(1, "\n" );
+}
+
+
+// updates clauses, watches, units, and proof
+void sat_solver2_reducedb(sat_solver2* s)
+{
+    static abctime TimeTotal = 0;
+    Sat_Mem_t * pMem = &s->Mem;
+    clause * c = NULL;
+    int nLearnedOld = veci_size(&s->act_clas);
+    int * act_clas = veci_begin(&s->act_clas);
+    int * pPerm, * pSortValues, nCutoffValue, * pClaProofs;
+    int i, j, k, Id, nSelected;//, LastSize = 0;
+    int Counter, CounterStart;
+    abctime clk = Abc_Clock();
+    static int Count = 0;
+    Count++;
+    assert( s->nLearntMax );
+    s->nDBreduces++;
+//    printf( "Calling reduceDB with %d clause limit and parameters (%d %d %d).\n", s->nLearntMax, s->nLearntStart, s->nLearntDelta, s->nLearntRatio );
+
+/*
+    // find the new limit
+    s->nLearntMax = s->nLearntMax * 11 / 10;
+    // preserve 1/10 of last clauses
+    CounterStart  = s->stats.learnts - (s->nLearntMax / 10);
+    // preserve 1/10 of most active clauses
+    pSortValues = veci_begin(&s->act_clas);
+    pPerm = Abc_MergeSortCost( pSortValues, nLearnedOld );
+    assert( pSortValues[pPerm[0]] <= pSortValues[pPerm[nLearnedOld-1]] );
+    nCutoffValue = pSortValues[pPerm[nLearnedOld*9/10]];
+    ABC_FREE( pPerm );
+//    nCutoffValue = ABC_INFINITY;
+*/
+
+
+    // find the new limit
+    s->nLearntMax = s->nLearntStart + s->nLearntDelta * s->nDBreduces;
+    // preserve 1/20 of last clauses
+    CounterStart  = nLearnedOld - (s->nLearntMax / 20);
+    // preserve 3/4 of most active clauses
+    nSelected = nLearnedOld*s->nLearntRatio/100;
+    // create sorting values
+    pSortValues = ABC_ALLOC( int, nLearnedOld );
+    Sat_MemForEachLearned( pMem, c, i, k )
+    {
+        Id = clause_id(c);
+        pSortValues[Id] = (((7 - Abc_MinInt(c->lbd, 7)) << 28) | (act_clas[Id] >> 4));
+//        pSortValues[Id] = act_clas[Id];
+        assert( pSortValues[Id] >= 0 );
+    }
+    // find non-decreasing permutation
+    pPerm = Abc_MergeSortCost( pSortValues, nLearnedOld );
+    assert( pSortValues[pPerm[0]] <= pSortValues[pPerm[nLearnedOld-1]] );
+    nCutoffValue = pSortValues[pPerm[nLearnedOld-nSelected]];
+    ABC_FREE( pPerm );
+//    nCutoffValue = ABC_INFINITY;
+
+    // count how many clauses satisfy the condition
+    Counter = j = 0;
+    Sat_MemForEachLearned( pMem, c, i, k )
+    {
+        assert( c->mark == 0 );
+        if ( Counter++ > CounterStart || clause_size(c) < 2 || pSortValues[clause_id(c)] >= nCutoffValue || s->reasons[lit_var(c->lits[0])] == Sat_MemHand(pMem, i, k) )
+        {
+        }
+        else
+            j++;
+        if ( j >= nLearnedOld / 6 )
+            break;
+    }
+    if ( j < nLearnedOld / 6 )
+    {
+        ABC_FREE( pSortValues );
+        return;
+    }
+
+    // mark learned clauses to remove
+    Counter = j = 0;
+    pClaProofs = veci_size(&s->claProofs) ? veci_begin(&s->claProofs) : NULL;
+    Sat_MemForEachLearned( pMem, c, i, k )
+    {
+        assert( c->mark == 0 );
+        if ( Counter++ > CounterStart || clause_size(c) < 2 || pSortValues[clause_id(c)] >= nCutoffValue || s->reasons[lit_var(c->lits[0])] == Sat_MemHand(pMem, i, k) )
+        {
+            pSortValues[j] = pSortValues[clause_id(c)];
+            if ( pClaProofs ) 
+                pClaProofs[j] = pClaProofs[clause_id(c)];
+            if ( s->pPrf2 )
+                Prf_ManAddSaved( s->pPrf2, clause_id(c), j );
+            j++;
+        }
+        else // delete
+        {
+            c->mark = 1;
+            s->stats.learnts_literals -= clause_size(c);
+            s->stats.learnts--;
+        }
+    }
+    ABC_FREE( pSortValues );
+    if ( s->pPrf2 )
+        Prf_ManCompact( s->pPrf2, j );
+//    if ( j == nLearnedOld )
+//        return;
+
+    assert( s->stats.learnts == (unsigned)j );
+    assert( Counter == nLearnedOld );
+    veci_resize(&s->act_clas,j);
+    if ( veci_size(&s->claProofs) )
+        veci_resize(&s->claProofs,j);
+
+    // update ID of each clause to be its new handle
+    Counter = Sat_MemCompactLearned( pMem, 0 );
+    assert( Counter == (int)s->stats.learnts );
+
+    // update reasons
+    for ( i = 0; i < s->size; i++ )
+    {
+        if ( !s->reasons[i] ) // no reason
+            continue;
+        if ( clause_is_lit(s->reasons[i]) ) // 2-lit clause
+            continue;
+        if ( !clause_learnt_h(pMem, s->reasons[i]) ) // problem clause
+            continue;
+        assert( c->lrn );
+        c = clause2_read( s, s->reasons[i] );
+        assert( c->mark == 0 );
+        s->reasons[i] = clause_id(c); // updating handle here!!!
+    }
+
+    // update watches
+    for ( i = 0; i < s->size*2; i++ )
+    {
+        int * pArray = veci_begin(&s->wlists[i]);
+        for ( j = k = 0; k < veci_size(&s->wlists[i]); k++ )
+        {
+            if ( clause_is_lit(pArray[k]) ) // 2-lit clause
+                pArray[j++] = pArray[k];
+            else if ( !clause_learnt_h(pMem, pArray[k]) ) // problem clause
+                pArray[j++] = pArray[k];
+            else 
+            {
+                assert( c->lrn );
+                c = clause2_read(s, pArray[k]);
+                if ( !c->mark ) // useful learned clause
+                   pArray[j++] = clause_id(c); // updating handle here!!!
+            }
+        }
+        veci_resize(&s->wlists[i],j);
+    }
+
+    // compact units
+    if ( s->fProofLogging )
+        for ( i = 0; i < s->size; i++ )
+            if ( s->units[i] && clause_learnt_h(pMem, s->units[i]) )
+            {
+                assert( c->lrn );
+                c = clause2_read( s, s->units[i] );
+                assert( c->mark == 0 );
+                s->units[i] = clause_id(c);
+            }
+
+    // perform final move of the clauses
+    Counter = Sat_MemCompactLearned( pMem, 1 );
+    assert( Counter == (int)s->stats.learnts );
+
+    // compact proof (compacts 'proofs' and update 'claProofs')
+    if ( s->pPrf1 )
+    {
+        extern int Sat_ProofReduce( Vec_Set_t * vProof, void * pRoots, int hProofPivot );
+        s->hProofPivot = Sat_ProofReduce( s->pPrf1, &s->claProofs, s->hProofPivot );
+    }
+
+    // report the results
+    TimeTotal += Abc_Clock() - clk;
+    if ( s->fVerbose )
+    {
+        Abc_Print(1, "reduceDB: Keeping %7d out of %7d clauses (%5.2f %%)  ",
+            s->stats.learnts, nLearnedOld, 100.0 * s->stats.learnts / nLearnedOld );
+        Abc_PrintTime( 1, "Time", TimeTotal );
+    }
+}
+
+// reverses to the previously bookmarked point
+void sat_solver2_rollback( sat_solver2* s )
+{
+    Sat_Mem_t * pMem = &s->Mem;
+    int i, k, j;
+    static int Count = 0;
+    Count++;
+    assert( s->iVarPivot >= 0 && s->iVarPivot <= s->size );
+    assert( s->iTrailPivot >= 0 && s->iTrailPivot <= s->qtail );
+    assert( s->pPrf1 == NULL || (s->hProofPivot >= 1 && s->hProofPivot <= Vec_SetHandCurrent(s->pPrf1)) );
+    // reset implication queue
+    solver2_canceluntil_rollback( s, s->iTrailPivot );
+    // update order 
+    if ( s->iVarPivot < s->size )
+    { 
+        if ( s->activity2 )
+        {
+            s->var_inc = s->var_inc2;
+            memcpy( s->activity, s->activity2, sizeof(unsigned) * s->iVarPivot );
+        }
+        veci_resize(&s->order, 0);
+        for ( i = 0; i < s->iVarPivot; i++ )
+        {
+            if ( var_value(s, i) != varX )
+                continue;
+            s->orderpos[i] = veci_size(&s->order);
+            veci_push(&s->order,i);
+            order_update(s, i);
+        }
+    }
+    // compact watches
+    for ( i = 0; i < s->iVarPivot*2; i++ )
+    {
+        cla* pArray = veci_begin(&s->wlists[i]);
+        for ( j = k = 0; k < veci_size(&s->wlists[i]); k++ )
+            if ( Sat_MemClauseUsed(pMem, pArray[k]) )
+                pArray[j++] = pArray[k];
+        veci_resize(&s->wlists[i],j);
+    }
+    // reset watcher lists
+    for ( i = 2*s->iVarPivot; i < 2*s->size; i++ )
+        s->wlists[i].size = 0;
+
+    // reset clause counts
+    s->stats.clauses = pMem->BookMarkE[0];
+    s->stats.learnts = pMem->BookMarkE[1];
+    // rollback clauses
+    Sat_MemRollBack( pMem );
+
+    // resize learned arrays
+    veci_resize(&s->act_clas,  s->stats.learnts);
+    if ( s->pPrf1 ) 
+    {
+        veci_resize(&s->claProofs, s->stats.learnts);
+        Vec_SetShrink(s->pPrf1, s->hProofPivot); 
+        // some weird bug here, which shows only on 64-bits!
+        // temporarily, perform more general proof reduction
+//        Sat_ProofReduce( s->pPrf1, &s->claProofs, s->hProofPivot );
+    }
+    assert( s->pPrf2 == NULL );
+//    if ( s->pPrf2 )
+//        Prf_ManShrink( s->pPrf2, s->stats.learnts );
+
+    // initialize other vars
+    s->size = s->iVarPivot;
+    if ( s->size == 0 )
+    {
+    //    s->size                   = 0;
+    //    s->cap                    = 0;
+        s->qhead                  = 0;
+        s->qtail                  = 0;
+#ifdef USE_FLOAT_ACTIVITY2
+        s->var_inc                = 1;
+        s->cla_inc                = 1;
+        s->var_decay              = (float)(1 / 0.95  );
+        s->cla_decay              = (float)(1 / 0.999 );
+#else
+        s->var_inc                = (1 <<  5);
+        s->cla_inc                = (1 << 11);
+#endif
+        s->root_level             = 0;
+        s->random_seed            = 91648253;
+        s->progress_estimate      = 0;
+        s->verbosity              = 0;
+
+        s->stats.starts           = 0;
+        s->stats.decisions        = 0;
+        s->stats.propagations     = 0;
+        s->stats.inspects         = 0;
+        s->stats.conflicts        = 0;
+        s->stats.clauses          = 0;
+        s->stats.clauses_literals = 0;
+        s->stats.learnts          = 0;
+        s->stats.learnts_literals = 0;
+        s->stats.tot_literals     = 0;
+        // initialize clause pointers
+        s->hLearntLast            = -1; // the last learnt clause 
+        s->hProofLast             = -1; // the last proof ID
+
+        // initialize rollback
+        s->iVarPivot              =  0; // the pivot for variables
+        s->iTrailPivot            =  0; // the pivot for trail
+        s->hProofPivot            =  1; // the pivot for proof records
+    }
+}
+
+// returns memory in bytes used by the SAT solver
+double sat_solver2_memory( sat_solver2* s, int fAll )
+{
+    int i;
+    double Mem = sizeof(sat_solver2);
+    if ( fAll )
+        for (i = 0; i < s->cap*2; i++)
+            Mem += s->wlists[i].cap * sizeof(int);
+    Mem += s->cap * sizeof(veci);     // ABC_FREE(s->wlists   );
+    Mem += s->act_clas.cap * sizeof(int);
+    Mem += s->claProofs.cap * sizeof(int);
+//    Mem += s->cap * sizeof(char);     // ABC_FREE(s->polarity );
+//    Mem += s->cap * sizeof(char);     // ABC_FREE(s->tags     );
+    Mem += s->cap * sizeof(varinfo2); // ABC_FREE(s->vi       );
+    Mem += s->cap * sizeof(int);      // ABC_FREE(s->levels   );
+    Mem += s->cap * sizeof(char);     // ABC_FREE(s->assigns  );
+#ifdef USE_FLOAT_ACTIVITY2
+    Mem += s->cap * sizeof(double);   // ABC_FREE(s->activity );
+#else
+    Mem += s->cap * sizeof(unsigned); // ABC_FREE(s->activity );
+    if ( s->activity2 )
+    Mem += s->cap * sizeof(unsigned); // ABC_FREE(s->activity2);
+#endif
+    Mem += s->cap * sizeof(lit);      // ABC_FREE(s->trail    );
+    Mem += s->cap * sizeof(int);      // ABC_FREE(s->orderpos );
+    Mem += s->cap * sizeof(int);      // ABC_FREE(s->reasons  );
+    Mem += s->cap * sizeof(int);      // ABC_FREE(s->units    );
+    Mem += s->cap * sizeof(int);      // ABC_FREE(s->model    );
+    Mem += s->tagged.cap * sizeof(int);
+    Mem += s->stack.cap * sizeof(int);
+    Mem += s->order.cap * sizeof(int);
+    Mem += s->trail_lim.cap * sizeof(int);
+    Mem += s->temp_clause.cap * sizeof(int);
+    Mem += s->conf_final.cap * sizeof(int);
+    Mem += s->mark_levels.cap * sizeof(int);
+    Mem += s->min_lit_order.cap * sizeof(int);
+    Mem += s->min_step_order.cap * sizeof(int);
+    Mem += s->temp_proof.cap * sizeof(int);
+    Mem += Sat_MemMemoryAll( &s->Mem );
+//    Mem += Vec_ReportMemory( s->pPrf1 );
+    return Mem;
+}
+double sat_solver2_memory_proof( sat_solver2* s )
+{
+    double Mem = s->dPrfMemory;
+    if ( s->pPrf1 )
+        Mem += Vec_ReportMemory( s->pPrf1 );
+    return Mem;
+}
+
+
+// find the clause in the watcher lists
+/*
+int sat_solver2_find_clause( sat_solver2* s, int Hand, int fVerbose )
+{
+    int i, k, Found = 0;
+    if ( Hand >= s->clauses.size )
+        return 1;
+    for ( i = 0; i < s->size*2; i++ )
+    {
+        cla* pArray = veci_begin(&s->wlists[i]);
+        for ( k = 0; k < veci_size(&s->wlists[i]); k++ )
+            if ( (pArray[k] >> 1) == Hand )
+            {
+                if ( fVerbose )
+                Abc_Print(1, "Clause found in list %d at position %d.\n", i, k );
+                Found = 1;
+                break;
+            }
+    }
+    if ( Found == 0 )
+    {
+        if ( fVerbose )
+        Abc_Print(1, "Clause with handle %d is not found.\n", Hand );
+    }
+    return Found;
+}
+*/
+/*
+// verify that all problem clauses are satisfied
+void sat_solver2_verify( sat_solver2* s )
+{
+    clause * c;
+    int i, k, v, Counter = 0;
+    clause_foreach_entry( &s->clauses, c, i, 1 )
+    {
+        for ( k = 0; k < (int)c->size; k++ )
+        {
+            v = lit_var(c->lits[k]);
+            if ( sat_solver2_var_value(s, v) ^ lit_sign(c->lits[k]) )
+                break;
+        }
+        if ( k == (int)c->size )
+        {
+            Abc_Print(1, "Clause %d is not satisfied.   ", c->Id );
+            clause_print( c );
+            sat_solver2_find_clause( s, clause_handle(&s->clauses, c), 1 );
+            Counter++;
+        }
+    }
+    if ( Counter != 0 )
+        Abc_Print(1, "Verification failed!\n" );
+//    else
+//        Abc_Print(1, "Verification passed.\n" );
+}
+*/
+
+// checks how many watched clauses are satisfied by 0-level assignments
+// (this procedure may be called before setting up a new bookmark for rollback)
+int sat_solver2_check_watched( sat_solver2* s )
+{
+    clause * c;
+    int i, k, j, m;
+    int claSat[2] = {0};
+    // update watches
+    for ( i = 0; i < s->size*2; i++ )
+    {
+        int * pArray = veci_begin(&s->wlists[i]);
+        for ( m = k = 0; k < veci_size(&s->wlists[i]); k++ )
+        {
+            c = clause2_read(s, pArray[k]);
+            for ( j = 0; j < (int)c->size; j++ )
+                if ( var_value(s, lit_var(c->lits[j])) == lit_sign(c->lits[j]) ) // true lit
+                    break;
+            if ( j == (int)c->size )
+            {
+                pArray[m++] = pArray[k];
+                continue;
+            }
+            claSat[c->lrn]++;
+        }
+        veci_resize(&s->wlists[i],m);
+        if ( m == 0 )
+        {
+//            s->wlists[i].cap = 0;
+//            s->wlists[i].size = 0;
+//            ABC_FREE( s->wlists[i].ptr );
+        }
+    }
+//    printf( "\nClauses = %d  (Sat = %d).  Learned = %d  (Sat = %d).\n",
+//        s->stats.clauses, claSat[0], s->stats.learnts, claSat[1] );
+    return 0;
+}
+
+int sat_solver2_solve(sat_solver2* s, lit* begin, lit* end, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, ABC_INT64_T nConfLimitGlobal, ABC_INT64_T nInsLimitGlobal)
+{
+    int restart_iter = 0;
+    ABC_INT64_T  nof_conflicts;
+    lbool status = l_Undef;
+    int proof_id;
+    lit * i;
+
+    s->hLearntLast = -1;
+    s->hProofLast = -1;
+
+    // set the external limits
+//    s->nCalls++;
+//    s->nRestarts  = 0;
+    s->nConfLimit = 0;
+    s->nInsLimit  = 0;
+    if ( nConfLimit )
+        s->nConfLimit = s->stats.conflicts + nConfLimit;
+    if ( nInsLimit )
+//        s->nInsLimit = s->stats.inspects + nInsLimit;
+        s->nInsLimit = s->stats.propagations + nInsLimit;
+    if ( nConfLimitGlobal && (s->nConfLimit == 0 || s->nConfLimit > nConfLimitGlobal) )
+        s->nConfLimit = nConfLimitGlobal;
+    if ( nInsLimitGlobal && (s->nInsLimit == 0 || s->nInsLimit > nInsLimitGlobal) )
+        s->nInsLimit = nInsLimitGlobal;
+
+/*
+    // Perform assumptions:
+    root_level = assumps.size();
+    for (int i = 0; i < assumps.size(); i++){
+        Lit p = assumps[i];
+        assert(var(p) < nVars());
+        if (!solver2_assume(p)){
+            GClause r = reason[var(p)];
+            if (r != Gclause2_NULL){
+                clause* confl;
+                if (r.isLit()){
+                    confl = propagate_tmpbin;
+                    (*confl)[1] = ~p;
+                    (*confl)[0] = r.lit();
+                }else
+                    confl = r.clause();
+                analyzeFinal(confl, true);
+                conflict.push(~p);
+            }else
+                conflict.clear(),
+                conflict.push(~p);
+            cancelUntil(0);
+            return false; }
+        clause* confl = propagate();
+        if (confl != NULL){
+            analyzeFinal(confl), assert(conflict.size() > 0);
+            cancelUntil(0);
+            return false; }
+    }
+    assert(root_level == decisionLevel());
+*/
+
+    // Perform assumptions:
+    s->root_level = end - begin;
+    for ( i = begin; i < end; i++ )
+    {
+        lit p = *i;
+        assert(lit_var(p) < s->size);
+        veci_push(&s->trail_lim,s->qtail);
+        if (!solver2_enqueue(s,p,0))
+        {
+            clause* r = clause2_read(s, lit_reason(s,p));
+            if (r != NULL)
+            {
+                clause* confl = r;
+                proof_id = solver2_analyze_final(s, confl, 1);
+                veci_push(&s->conf_final, lit_neg(p));
+            }
+            else
+            {
+//                assert( 0 );
+//                r = var_unit_clause( s, lit_var(p) );
+//                assert( r != NULL );
+//                proof_id = clause2_proofid(s, r, 0);
+                proof_id = -1; // the only case when ProofId is not assigned (conflicting assumptions)
+                veci_resize(&s->conf_final,0);
+                veci_push(&s->conf_final, lit_neg(p));
+                // the two lines below are a bug fix by Siert Wieringa 
+                if (var_level(s, lit_var(p)) > 0)
+                    veci_push(&s->conf_final, p);
+            }
+            s->hProofLast = proof_id;
+            solver2_canceluntil(s, 0);
+            return l_False;
+        }
+        else
+        {
+            clause* confl = solver2_propagate(s);
+            if (confl != NULL){
+                proof_id = solver2_analyze_final(s, confl, 0);
+                assert(s->conf_final.size > 0);
+                s->hProofLast = proof_id;
+                solver2_canceluntil(s, 0);
+                return l_False;
+            }
+        }
+    }
+    assert(s->root_level == solver2_dlevel(s));
+
+    if (s->verbosity >= 1){
+        Abc_Print(1,"==================================[MINISAT]===================================\n");
+        Abc_Print(1,"| Conflicts |     ORIGINAL     |              LEARNT              | Progress |\n");
+        Abc_Print(1,"|           | Clauses Literals |   Limit Clauses Literals  Lit/Cl |          |\n");
+        Abc_Print(1,"==============================================================================\n");
+    }
+
+    while (status == l_Undef){
+        if (s->verbosity >= 1)
+        {
+            Abc_Print(1,"| %9.0f | %7.0f %8.0f | %7.0f %7.0f %8.0f %7.1f | %6.3f %% |\n",
+                (double)s->stats.conflicts,
+                (double)s->stats.clauses,
+                (double)s->stats.clauses_literals,
+                (double)s->nLearntMax,
+                (double)s->stats.learnts,
+                (double)s->stats.learnts_literals,
+                (s->stats.learnts == 0)? 0.0 : (double)s->stats.learnts_literals / s->stats.learnts,
+                s->progress_estimate*100);
+            fflush(stdout);
+        }
+        if ( s->nRuntimeLimit && Abc_Clock() > s->nRuntimeLimit )
+            break;
+        // reduce the set of learnt clauses
+        if ( s->nLearntMax && veci_size(&s->act_clas) >= s->nLearntMax && s->pPrf2 == NULL )
+            sat_solver2_reducedb(s);
+        // perform next run
+        nof_conflicts = (ABC_INT64_T)( 100 * luby2(2, restart_iter++) );
+        status = solver2_search(s, nof_conflicts);
+        // quit the loop if reached an external limit
+        if ( s->nConfLimit && s->stats.conflicts > s->nConfLimit )
+            break;
+        if ( s->nInsLimit  && s->stats.propagations > s->nInsLimit )
+            break;
+    }
+    if (s->verbosity >= 1)
+        Abc_Print(1,"==============================================================================\n");
+
+    solver2_canceluntil(s,0);
+//    assert( s->qhead == s->qtail );
+//    if ( status == l_True )
+//        sat_solver2_verify( s );
+    return status;
+}
+
+void * Sat_ProofCore( sat_solver2 * s )
+{
+    extern void * Proof_DeriveCore( Vec_Set_t * vProof, int hRoot );
+    if ( s->pPrf1 )
+        return Proof_DeriveCore( s->pPrf1, s->hProofLast );
+    if ( s->pPrf2 )
+    {
+        s->dPrfMemory = Abc_MaxDouble( s->dPrfMemory, Prf_ManMemory(s->pPrf2) );
+        return Prf_ManUnsatCore( s->pPrf2 );
+    }
+    return NULL;
+}
+
+ABC_NAMESPACE_IMPL_END
diff --git a/abc-build/src/sat/bsat/satSolver2.h b/abc-build/src/sat/bsat/satSolver2.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satSolver2.h
@@ -0,0 +1,377 @@
+/**************************************************************************************************
+MiniSat -- Copyright (c) 2005, Niklas Sorensson
+http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+// Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko
+
+#ifndef ABC__sat__bsat__satSolver2_h
+#define ABC__sat__bsat__satSolver2_h
+ 
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "satVec.h"
+#include "satClause.h"
+#include "misc/vec/vecSet.h"
+#include "satProof2.h"
+
+ABC_NAMESPACE_HEADER_START
+
+//#define USE_FLOAT_ACTIVITY2
+
+//=================================================================================================
+// Public interface:
+
+struct sat_solver2_t;
+typedef struct sat_solver2_t sat_solver2;
+typedef struct Int2_Man_t_ Int2_Man_t;
+
+extern sat_solver2* sat_solver2_new(void);
+extern void         sat_solver2_delete(sat_solver2* s);
+
+extern int          sat_solver2_addclause(sat_solver2* s, lit* begin, lit* end, int Id);
+extern int          sat_solver2_simplify(sat_solver2* s);
+extern int          sat_solver2_solve(sat_solver2* s, lit* begin, lit* end, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, ABC_INT64_T nConfLimitGlobal, ABC_INT64_T nInsLimitGlobal);
+extern void         sat_solver2_rollback(sat_solver2* s);
+extern void         sat_solver2_reducedb(sat_solver2* s);
+extern double       sat_solver2_memory( sat_solver2* s, int fAll );
+extern double       sat_solver2_memory_proof( sat_solver2* s );
+
+extern void         sat_solver2_setnvars(sat_solver2* s,int n);
+
+extern void         Sat_Solver2WriteDimacs( sat_solver2 * p, char * pFileName, lit* assumptionsBegin, lit* assumptionsEnd, int incrementVars );
+extern void         Sat_Solver2PrintStats( FILE * pFile, sat_solver2 * p );
+extern int *        Sat_Solver2GetModel( sat_solver2 * p, int * pVars, int nVars );
+extern void         Sat_Solver2DoubleClauses( sat_solver2 * p, int iVar );
+
+// global variables
+extern int          var_is_assigned(sat_solver2* s, int v);
+extern int          var_is_partA   (sat_solver2* s, int v);
+extern void         var_set_partA  (sat_solver2* s, int v, int partA);
+
+// proof-based APIs
+extern void *       Sat_ProofCore( sat_solver2 * s );
+extern void *       Sat_ProofInterpolant( sat_solver2 * s, void * pGloVars );
+extern word *       Sat_ProofInterpolantTruth( sat_solver2 * s, void * pGloVars );
+extern void         Sat_ProofCheck( sat_solver2 * s );
+
+// interpolation APIs
+extern Int2_Man_t * Int2_ManStart( sat_solver2 * pSat, int * pGloVars, int nGloVars );
+extern void         Int2_ManStop( Int2_Man_t * p );
+extern int          Int2_ManChainStart( Int2_Man_t * p, clause * c );
+extern int          Int2_ManChainResolve( Int2_Man_t * p, clause * c, int iLit, int varA );
+extern void *       Int2_ManReadInterpolant( sat_solver2 * s );
+
+
+//=================================================================================================
+// Solver representation:
+
+struct varinfo_t;
+typedef struct varinfo2_t varinfo2;
+
+struct sat_solver2_t
+{
+    int             size;           // nof variables
+    int             cap;            // size of varmaps
+    int             qhead;          // Head index of queue.
+    int             qtail;          // Tail index of queue.
+
+    int             root_level;     // Level of first proper decision.
+    double          random_seed;
+    double          progress_estimate;
+    int             verbosity;      // Verbosity level. 0=silent, 1=some progress report, 2=everything    // activities
+
+#ifdef USE_FLOAT_ACTIVITY2
+    double          var_inc;        // Amount to bump next variable with.
+    double          var_decay;      // INVERSE decay factor for variable activity: stores 1/decay. 
+    float           cla_inc;        // Amount to bump next clause with.
+    float           cla_decay;      // INVERSE decay factor for clause activity: stores 1/decay.
+    double*         activity;       // A heuristic measurement of the activity of a variable.
+#else
+    int             var_inc;        // Amount to bump next variable with.
+    int             var_inc2;       // Amount to bump next variable with.
+    int             cla_inc;        // Amount to bump next clause with.
+    unsigned*       activity;       // A heuristic measurement of the activity of a variable
+    unsigned*       activity2;      // backup variable activity
+#endif
+
+    int             nUnits;         // the total number of unit clauses
+    int             nof_learnts;    // the number of clauses to trigger reduceDB
+    int             nLearntMax;     // enables using reduce DB method
+    int             nLearntStart;   // starting learned clause limit
+    int             nLearntDelta;   // delta of learned clause limit
+    int             nLearntRatio;   // ratio percentage of learned clauses
+    int             nDBreduces;     // number of DB reductions
+    int             fNotUseRandom;  // do not allow random decisions with a fixed probability
+    int             fSkipSimplify;  // set to one to skip simplification of the clause database
+    int             fProofLogging;  // enable proof-logging
+    int             fVerbose;
+
+    // clauses
+    Sat_Mem_t       Mem;
+    veci*           wlists;         // watcher lists (for each literal)
+    veci            act_clas;       // clause activities
+    veci            claProofs;      // clause proofs
+
+    // rollback
+    int             iVarPivot;      // the pivot for variables
+    int             iTrailPivot;    // the pivot for trail
+    int             hProofPivot;    // the pivot for proof records
+
+    // internal state
+    varinfo2 *      vi;             // variable information
+    int*            levels;         // 
+    char*           assigns;        // 
+    lit*            trail;          // sequence of assignment and implications
+    int*            orderpos;       // Index in variable order.
+    cla*            reasons;        // reason clauses
+    cla*            units;          // unit clauses
+    int*            model;          // If problem is solved, this vector contains the model (contains: lbool).
+
+    veci            tagged;         // (contains: var)
+    veci            stack;          // (contains: var)
+    veci            order;          // Variable order. (heap) (contains: var)
+    veci            trail_lim;      // Separator indices for different decision levels in 'trail'. (contains: int)
+    veci            temp_clause;    // temporary storage for a CNF clause
+    veci            conf_final;     // If problem is unsatisfiable (possibly under assumptions),
+                                    // this vector represent the final conflict clause expressed in the assumptions.
+    veci            mark_levels;    // temporary storage for labeled levels
+    veci            min_lit_order;  // ordering of removable literals
+    veci            min_step_order; // ordering of resolution steps
+    veci            learnt_live;    // remaining clauses after reduce DB
+
+    // proof logging
+    Vec_Set_t *     pPrf1;          // sequence of proof records
+    veci            temp_proof;     // temporary place to store proofs
+    int             hLearntLast;    // in proof-logging mode, the ID of the final conflict clause (conf_final)
+    int             hProofLast;     // in proof-logging mode, the ID of the final conflict clause (conf_final)
+    Prf_Man_t *     pPrf2;          // another proof manager
+    double          dPrfMemory;     // memory used by the proof-logger
+    Int2_Man_t *    pInt2;          // interpolation manager
+    int             tempInter;      // temporary storage for the interpolant
+
+    // statistics
+    stats_t         stats;
+    ABC_INT64_T     nConfLimit;     // external limit on the number of conflicts
+    ABC_INT64_T     nInsLimit;      // external limit on the number of implications
+    abctime         nRuntimeLimit;  // external limit on runtime
+};
+
+static inline clause * clause2_read( sat_solver2 * s, cla h )                  { return Sat_MemClauseHand( &s->Mem, h ); }
+static inline int      clause2_proofid(sat_solver2* s, clause* c, int varA)    { return c->lrn ? (veci_begin(&s->claProofs)[clause_id(c)]<<2) | (varA<<1) : (clause_id(c)<<2) | (varA<<1) | 1; }
+
+// these two only work after creating a clause before the solver is called
+static inline int   clause2_is_partA (sat_solver2* s, int h)                   { return clause2_read(s, h)->partA;       }
+static inline void  clause2_set_partA(sat_solver2* s, int h, int partA)        { clause2_read(s, h)->partA = partA;      }
+static inline int   clause2_id(sat_solver2* s, int h)                          { return clause_id(clause2_read(s, h));   }
+static inline void  clause2_set_id(sat_solver2* s, int h, int id)              { clause_set_id(clause2_read(s, h), id);  }
+
+//=================================================================================================
+// Public APIs:
+
+static inline int sat_solver2_nvars(sat_solver2* s)
+{
+    return s->size;
+}
+
+static inline int sat_solver2_nclauses(sat_solver2* s)
+{
+    return (int)s->stats.clauses;
+}
+
+static inline int sat_solver2_nlearnts(sat_solver2* s)
+{
+    return (int)s->stats.learnts;
+}
+
+static inline int sat_solver2_nconflicts(sat_solver2* s)
+{
+    return (int)s->stats.conflicts;
+}
+
+static inline int sat_solver2_var_value( sat_solver2* s, int v ) 
+{
+    assert( v >= 0 && v < s->size );
+    return (int)(s->model[v] == l_True);
+}
+static inline int sat_solver2_var_literal( sat_solver2* s, int v ) 
+{
+    assert( v >= 0 && v < s->size );
+    return toLitCond( v, s->model[v] != l_True );
+}
+static inline void sat_solver2_act_var_clear(sat_solver2* s) 
+{
+    int i;
+    for (i = 0; i < s->size; i++)
+        s->activity[i] = 0;//.0;
+    s->var_inc = 1.0;
+}
+
+static inline int sat_solver2_final(sat_solver2* s, int ** ppArray)
+{
+    *ppArray = s->conf_final.ptr;
+    return s->conf_final.size;
+}
+
+static inline abctime sat_solver2_set_runtime_limit(sat_solver2* s, abctime Limit)
+{
+    abctime temp = s->nRuntimeLimit;
+    s->nRuntimeLimit = Limit;
+    return temp;
+}
+
+static inline int sat_solver2_set_learntmax(sat_solver2* s, int nLearntMax)
+{
+    int temp = s->nLearntMax;
+    s->nLearntMax = nLearntMax;
+    return temp;
+}
+
+static inline void sat_solver2_bookmark(sat_solver2* s)
+{
+    assert( s->qhead == s->qtail );
+    s->iVarPivot    = s->size;
+    s->iTrailPivot  = s->qhead;
+    if ( s->pPrf1 )
+        s->hProofPivot  = Vec_SetHandCurrent(s->pPrf1);
+    Sat_MemBookMark( &s->Mem );
+    if ( s->activity2 )
+    {
+        s->var_inc2 = s->var_inc;
+        memcpy( s->activity2, s->activity, sizeof(unsigned) * s->iVarPivot );
+    }
+}
+
+static inline int sat_solver2_add_const( sat_solver2 * pSat, int iVar, int fCompl, int fMark, int Id )
+{
+    lit Lits[1];
+    int Cid;
+    assert( iVar >= 0 );
+
+    Lits[0] = toLitCond( iVar, fCompl );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 1, Id );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+    return 1;
+}
+static inline int sat_solver2_add_buffer( sat_solver2 * pSat, int iVarA, int iVarB, int fCompl, int fMark, int Id )
+{
+    lit Lits[2];
+    int Cid;
+    assert( iVarA >= 0 && iVarB >= 0 );
+
+    Lits[0] = toLitCond( iVarA, 0 );
+    Lits[1] = toLitCond( iVarB, !fCompl );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 2, Id );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+
+    Lits[0] = toLitCond( iVarA, 1 );
+    Lits[1] = toLitCond( iVarB, fCompl );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 2, Id );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+    return 2;
+}
+static inline int sat_solver2_add_and( sat_solver2 * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1, int fMark, int Id )
+{
+    lit Lits[3];
+    int Cid;
+
+    Lits[0] = toLitCond( iVar, 1 );
+    Lits[1] = toLitCond( iVar0, fCompl0 );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 2, Id );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+
+    Lits[0] = toLitCond( iVar, 1 );
+    Lits[1] = toLitCond( iVar1, fCompl1 );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 2, Id );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+
+    Lits[0] = toLitCond( iVar, 0 );
+    Lits[1] = toLitCond( iVar0, !fCompl0 );
+    Lits[2] = toLitCond( iVar1, !fCompl1 );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, Id );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+    return 3;
+}
+static inline int sat_solver2_add_xor( sat_solver2 * pSat, int iVarA, int iVarB, int iVarC, int fCompl, int fMark, int Id )
+{
+    lit Lits[3];
+    int Cid;
+    assert( iVarA >= 0 && iVarB >= 0 && iVarC >= 0 );
+
+    Lits[0] = toLitCond( iVarA, !fCompl );
+    Lits[1] = toLitCond( iVarB, 1 );
+    Lits[2] = toLitCond( iVarC, 1 );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, Id );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+
+    Lits[0] = toLitCond( iVarA, !fCompl );
+    Lits[1] = toLitCond( iVarB, 0 );
+    Lits[2] = toLitCond( iVarC, 0 );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, Id );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+
+    Lits[0] = toLitCond( iVarA, fCompl );
+    Lits[1] = toLitCond( iVarB, 1 );
+    Lits[2] = toLitCond( iVarC, 0 );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, Id );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+
+    Lits[0] = toLitCond( iVarA, fCompl );
+    Lits[1] = toLitCond( iVarB, 0 );
+    Lits[2] = toLitCond( iVarC, 1 );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, Id );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+    return 4;
+}
+static inline int sat_solver2_add_constraint( sat_solver2 * pSat, int iVar, int iVar2, int fCompl, int fMark, int Id )
+{
+    lit Lits[2];
+    int Cid;
+    assert( iVar >= 0 );
+
+    Lits[0] = toLitCond( iVar, fCompl );
+    Lits[1] = toLitCond( iVar2, 0 );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 2, Id );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+
+    Lits[0] = toLitCond( iVar, fCompl );
+    Lits[1] = toLitCond( iVar2, 1 );
+    Cid = sat_solver2_addclause( pSat, Lits, Lits + 2, Id );
+    if ( fMark )
+        clause2_set_partA( pSat, Cid, 1 );
+    return 2;
+}
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/sat/bsat/satSolver2i.c b/abc-build/src/sat/bsat/satSolver2i.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satSolver2i.c
@@ -0,0 +1,242 @@
+/**CFile****************************************************************
+
+  FileName    [satSolver2i.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT solver.]
+
+  Synopsis    [Records the trace of SAT solving in the CNF form.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - September 2, 2013.]
+
+  Revision    [$Id: satSolver2i.c,v 1.4 2013/09/02 00:00:00 casem Exp $]
+
+***********************************************************************/
+
+#include "satSolver2.h"
+#include "aig/gia/gia.h"
+#include "aig/gia/giaAig.h"
+#include "sat/cnf/cnf.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+struct Int2_Man_t_ 
+{
+    sat_solver2 *   pSat;      // user's SAT solver
+    Vec_Int_t *     vGloVars;  // IDs of global variables
+    Vec_Int_t *     vVar2Glo;  // mapping of SAT variables into their global IDs
+    Gia_Man_t *     pGia;      // AIG manager to store the interpolant
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Managing interpolation manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Int2_Man_t * Int2_ManStart( sat_solver2 * pSat, int * pGloVars, int nGloVars )
+{
+    Int2_Man_t * p;
+    int i;
+    p = ABC_CALLOC( Int2_Man_t, 1 );
+    p->pSat     = pSat;
+    p->vGloVars = Vec_IntAllocArrayCopy( pGloVars, nGloVars );
+    p->vVar2Glo = Vec_IntInvert( p->vGloVars, -1 );
+    p->pGia     = Gia_ManStart( 10 * Vec_IntSize(p->vGloVars) );
+    p->pGia->pName = Abc_UtilStrsav( "interpolant" );
+    for ( i = 0; i < nGloVars; i++ )
+        Gia_ManAppendCi( p->pGia );
+    Gia_ManHashStart( p->pGia );
+    return p;
+}
+void Int2_ManStop( Int2_Man_t * p )
+{
+    if ( p == NULL )
+        return;
+    Gia_ManStopP( &p->pGia );
+    Vec_IntFree( p->vGloVars );
+    Vec_IntFree( p->vVar2Glo );
+    ABC_FREE( p );
+}
+void * Int2_ManReadInterpolant( sat_solver2 * pSat )
+{
+    Int2_Man_t * p = pSat->pInt2;
+    Gia_Man_t * pTemp, * pGia = p->pGia; p->pGia = NULL;
+    // return NULL, if the interpolant is not ready (for example, when the solver returned 'sat')
+    if ( pSat->hProofLast == -1 )
+        return NULL;
+    // create AIG with one primary output
+    assert( Gia_ManPoNum(pGia) == 0 );
+    Gia_ManAppendCo( pGia, pSat->hProofLast );  
+    pSat->hProofLast = -1;
+    // cleanup the resulting AIG
+    pGia = Gia_ManCleanup( pTemp = pGia );
+    Gia_ManStop( pTemp );
+    return (void *)pGia;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computing interpolant for a clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Int2_ManChainStart( Int2_Man_t * p, clause * c )
+{
+    if ( c->lrn )
+        return veci_begin(&p->pSat->claProofs)[clause_id(c)];
+    if ( !c->partA )
+        return 1;
+    if ( c->lits[c->size] < 0 )
+    {
+        int i, Var, CiId, Res = 0;
+        for ( i = 0; i < (int)c->size; i++ )
+        {
+            // get ID of the global variable
+            if ( Abc_Lit2Var(c->lits[i]) >= Vec_IntSize(p->vVar2Glo) )
+                continue;
+            Var = Vec_IntEntry( p->vVar2Glo, Abc_Lit2Var(c->lits[i]) );
+            if ( Var < 0 )
+                continue;
+            // get literal of the AIG node
+            CiId = Gia_ObjId( p->pGia, Gia_ManCi(p->pGia, Var) );
+            // compute interpolant of the clause
+            Res = Gia_ManHashOr( p->pGia, Res, Abc_Var2Lit(CiId, Abc_LitIsCompl(c->lits[i])) );
+        }
+        c->lits[c->size] = Res;
+    }
+    return c->lits[c->size];
+}
+int Int2_ManChainResolve( Int2_Man_t * p, clause * c, int iLit, int varA )
+{
+    int iLit2 = Int2_ManChainStart( p, c );
+    assert( iLit >= 0 );
+    if ( varA )
+        iLit = Gia_ManHashOr( p->pGia, iLit, iLit2 );
+    else
+        iLit = Gia_ManHashAnd( p->pGia, iLit, iLit2 );
+    return iLit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Test for the interpolation procedure.]
+
+  Description [The input AIG can be any n-input comb circuit with one PO 
+  (not necessarily a comb miter).  The interpolant depends on n+1 variables
+  and equal to the relation f = F(x0,x1,...,xn).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManInterTest( Gia_Man_t * p )
+{
+    sat_solver2 * pSat;
+    Gia_Man_t * pInter;
+    Aig_Man_t * pMan;
+    Vec_Int_t * vGVars;
+    Cnf_Dat_t * pCnf;
+    Aig_Obj_t * pObj;
+    int Lit, Cid, Var, status, i;
+    abctime clk = Abc_Clock();
+    assert( Gia_ManRegNum(p) == 0 );
+    assert( Gia_ManCoNum(p) == 1 );
+
+    // derive CNFs
+    pMan = Gia_ManToAigSimple( p );
+    pCnf = Cnf_Derive( pMan, 1 );
+
+    // start the solver
+    pSat = sat_solver2_new();
+    pSat->fVerbose = 1;
+    sat_solver2_setnvars( pSat, 2*pCnf->nVars+1 );
+
+    // set A-variables (all used except PI/PO, which will be global variables)
+    Aig_ManForEachObj( pMan, pObj, i )
+        if ( pCnf->pVarNums[pObj->Id] >= 0 && !Aig_ObjIsCi(pObj) && !Aig_ObjIsCo(pObj) )
+            var_set_partA( pSat, pCnf->pVarNums[pObj->Id], 1 );
+
+    // add clauses of A
+    for ( i = 0; i < pCnf->nClauses; i++ )
+    {
+        Cid = sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], -1 );
+        clause2_set_partA( pSat, Cid, 1 ); // this API should be called for each clause of A
+    }
+
+    // add clauses of B (after shifting all CNF variables by pCnf->nVars)
+    Cnf_DataLift( pCnf, pCnf->nVars );
+    for ( i = 0; i < pCnf->nClauses; i++ )
+        sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], -1 );
+    Cnf_DataLift( pCnf, -pCnf->nVars );
+
+    // add PI equality clauses
+    vGVars = Vec_IntAlloc( Aig_ManCoNum(pMan)+1 );
+    Aig_ManForEachCi( pMan, pObj, i )
+    {
+        Var = pCnf->pVarNums[pObj->Id];
+        sat_solver2_add_buffer( pSat, Var, pCnf->nVars + Var, 0, 0, -1 );
+        Vec_IntPush( vGVars, Var );
+    }
+
+    // add an XOR clause in the end
+    Var = pCnf->pVarNums[Aig_ManCo(pMan,0)->Id];
+    sat_solver2_add_xor( pSat, Var, pCnf->nVars + Var, 2*pCnf->nVars, 0, 0, -1 );
+    Vec_IntPush( vGVars, Var );
+
+    // start the interpolation manager
+    pSat->pInt2 = Int2_ManStart( pSat, Vec_IntArray(vGVars), Vec_IntSize(vGVars) );
+
+    // solve the problem
+    Lit = toLitCond( 2*pCnf->nVars, 0 );
+    status = sat_solver2_solve( pSat, &Lit, &Lit + 1, 0, 0, 0, 0 );
+    assert( status == l_False );
+    Sat_Solver2PrintStats( stdout, pSat );
+
+    // derive interpolant
+    pInter = (Gia_Man_t *)Int2_ManReadInterpolant( pSat );
+    Gia_ManPrintStats( pInter, NULL );
+    Abc_PrintTime( 1, "Total interpolation time", Abc_Clock() - clk );
+
+    // clean up
+    Vec_IntFree( vGVars );
+    Cnf_DataFree( pCnf );
+    Aig_ManStop( pMan );
+    sat_solver2_delete( pSat );
+
+    // return interpolant
+    return pInter;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bsat/satStore.c b/abc-build/src/sat/bsat/satStore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satStore.c
@@ -0,0 +1,469 @@
+/**CFile****************************************************************
+
+  FileName    [satStore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT solver.]
+
+  Synopsis    [Records the trace of SAT solving in the CNF form.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: satStore.c,v 1.4 2005/09/16 22:55:03 casem Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "satStore.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Fetches memory.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Sto_ManMemoryFetch( Sto_Man_t * p, int nBytes )
+{
+    char * pMem;
+    if ( p->pChunkLast == NULL || nBytes > p->nChunkSize - p->nChunkUsed )
+    {
+        pMem = (char *)ABC_ALLOC( char, p->nChunkSize );
+        *(char **)pMem = p->pChunkLast;
+        p->pChunkLast = pMem;
+        p->nChunkUsed = sizeof(char *);
+    }
+    pMem = p->pChunkLast + p->nChunkUsed;
+    p->nChunkUsed += nBytes;
+    return pMem;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sto_ManMemoryStop( Sto_Man_t * p )
+{
+    char * pMem, * pNext;
+    if ( p->pChunkLast == NULL )
+        return;
+    for ( pMem = p->pChunkLast; (pNext = *(char **)pMem); pMem = pNext )
+        ABC_FREE( pMem );
+    ABC_FREE( pMem );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports memory usage in bytes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sto_ManMemoryReport( Sto_Man_t * p )
+{
+    int Total;
+    char * pMem, * pNext;
+    if ( p->pChunkLast == NULL )
+        return 0;
+    Total = p->nChunkUsed; 
+    for ( pMem = p->pChunkLast; (pNext = *(char **)pMem); pMem = pNext )
+        Total += p->nChunkSize;
+    return Total;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocate proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Sto_Man_t * Sto_ManAlloc()
+{
+    Sto_Man_t * p;
+    // allocate the manager
+    p = (Sto_Man_t *)ABC_ALLOC( char, sizeof(Sto_Man_t) );
+    memset( p, 0, sizeof(Sto_Man_t) );
+    // memory management
+    p->nChunkSize = (1<<16); // use 64K chunks
+    return p;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocate proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sto_ManFree( Sto_Man_t * p )
+{
+    Sto_ManMemoryStop( p );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one clause to the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sto_ManAddClause( Sto_Man_t * p, lit * pBeg, lit * pEnd )
+{
+    Sto_Cls_t * pClause;
+    lit Lit, * i, * j;
+    int nSize;
+
+    // process the literals
+    if ( pBeg < pEnd )
+    {
+        // insertion sort
+        for ( i = pBeg + 1; i < pEnd; i++ )
+        {
+            Lit = *i;
+            for ( j = i; j > pBeg && *(j-1) > Lit; j-- )
+                *j = *(j-1);
+            *j = Lit;
+        }
+        // make sure there is no duplicated variables
+        for ( i = pBeg + 1; i < pEnd; i++ )
+            if ( lit_var(*(i-1)) == lit_var(*i) )
+            {
+                printf( "The clause contains two literals of the same variable: %d and %d.\n", *(i-1), *i );
+                return 0;
+            }
+        // check the largest var size
+        p->nVars = STO_MAX( p->nVars, lit_var(*(pEnd-1)) + 1 );
+    }
+
+    // get memory for the clause
+    nSize = sizeof(Sto_Cls_t) + sizeof(lit) * (pEnd - pBeg);
+    nSize = (nSize / sizeof(char*) + ((nSize % sizeof(char*)) > 0)) * sizeof(char*); // added by Saurabh on Sep 3, 2009
+    pClause = (Sto_Cls_t *)Sto_ManMemoryFetch( p, nSize );
+    memset( pClause, 0, sizeof(Sto_Cls_t) );
+
+    // assign the clause
+    pClause->Id = p->nClauses++;
+    pClause->nLits = pEnd - pBeg;
+    memcpy( pClause->pLits, pBeg, sizeof(lit) * (pEnd - pBeg) );
+//    assert( pClause->pLits[0] >= 0 );
+
+    // add the clause to the list
+    if ( p->pHead == NULL )
+        p->pHead = pClause;
+    if ( p->pTail == NULL )
+        p->pTail = pClause;
+    else
+    {
+        p->pTail->pNext = pClause;
+        p->pTail = pClause;
+    }
+
+    // add the empty clause
+    if ( pClause->nLits == 0 )
+    {
+        if ( p->pEmpty )
+        {
+            printf( "More than one empty clause!\n" );
+            return 0;
+        }
+        p->pEmpty = pClause;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Mark all clauses added so far as root clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sto_ManMarkRoots( Sto_Man_t * p )
+{
+    Sto_Cls_t * pClause;
+    p->nRoots = 0;
+    Sto_ManForEachClause( p, pClause )
+    {
+        pClause->fRoot = 1;
+        p->nRoots++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Mark all clauses added so far as clause of A.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sto_ManMarkClausesA( Sto_Man_t * p )
+{
+    Sto_Cls_t * pClause;
+    p->nClausesA = 0;
+    Sto_ManForEachClause( p, pClause )
+    {
+        pClause->fA = 1;
+        p->nClausesA++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the literal of the last clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sto_ManChangeLastClause( Sto_Man_t * p )
+{
+    Sto_Cls_t * pClause, * pPrev;
+    pPrev = NULL;
+    Sto_ManForEachClause( p, pClause )
+        pPrev = pClause;
+    assert( pPrev != NULL );
+    assert( pPrev->fA == 1 );
+    assert( pPrev->nLits == 1 );
+    p->nClausesA--;
+    pPrev->fA = 0;
+    return pPrev->pLits[0] >> 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the stored clauses into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sto_ManDumpClauses( Sto_Man_t * p, char * pFileName )
+{
+    FILE * pFile;
+    Sto_Cls_t * pClause;
+    int i;
+    // start the file
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        printf( "Error: Cannot open output file (%s).\n", pFileName );
+        return;
+    }
+    // write the data
+    fprintf( pFile, "p %d %d %d %d\n", p->nVars, p->nClauses, p->nRoots, p->nClausesA );
+    Sto_ManForEachClause( p, pClause )
+    {
+        for ( i = 0; i < (int)pClause->nLits; i++ )
+            fprintf( pFile, " %d", lit_print(pClause->pLits[i]) );
+        fprintf( pFile, " 0\n" );
+    }
+//    fprintf( pFile, " 0\n" );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads one literal from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sto_ManLoadNumber( FILE * pFile, int * pNumber )
+{
+    int Char, Number = 0, Sign = 0;
+    // skip space-like chars
+    do {
+        Char = fgetc( pFile );
+        if ( Char == EOF )
+            return 0;
+    } while ( Char == ' ' || Char == '\t' || Char == '\r' || Char == '\n' );
+    // read the literal
+    while ( 1 )
+    {
+        // get the next character
+        Char = fgetc( pFile );
+        if ( Char == ' ' || Char == '\t' || Char == '\r' || Char == '\n' )
+            break;
+        // check that the char is a digit
+        if ( (Char < '0' || Char > '9') && Char != '-' )
+        {
+            printf( "Error: Wrong char (%c) in the input file.\n", Char );
+            return 0;
+        }
+        // check if this is a minus
+        if ( Char == '-' )
+            Sign = 1;
+        else
+            Number = 10 * Number + Char;
+    }
+    // return the number
+    *pNumber = Sign? -Number : Number;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads CNF from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Sto_Man_t * Sto_ManLoadClauses( char * pFileName )
+{
+    FILE * pFile;
+    Sto_Man_t * p;
+    Sto_Cls_t * pClause;
+    char pBuffer[1024];
+    int nLits, nLitsAlloc, Counter, Number;
+    lit * pLits;
+
+    // start the file
+    pFile = fopen( pFileName, "r" );
+    if ( pFile == NULL )
+    {
+        printf( "Error: Cannot open input file (%s).\n", pFileName );
+        return NULL;
+    }
+
+    // create the manager
+    p = Sto_ManAlloc();
+
+    // alloc the array of literals
+    nLitsAlloc = 1024;
+    pLits = (lit *)ABC_ALLOC( char, sizeof(lit) * nLitsAlloc );
+
+    // read file header
+    p->nVars = p->nClauses = p->nRoots = p->nClausesA = 0;
+    while ( fgets( pBuffer, 1024, pFile ) )
+    {
+        if ( pBuffer[0] == 'c' )
+            continue;
+        if ( pBuffer[0] == 'p' )
+        {
+            sscanf( pBuffer + 1, "%d %d %d %d", &p->nVars, &p->nClauses, &p->nRoots, &p->nClausesA );
+            break;
+        }
+        printf( "Warning: Skipping line: \"%s\"\n", pBuffer );
+    }
+
+    // read the clauses
+    nLits = 0;
+    while ( Sto_ManLoadNumber(pFile, &Number) )
+    {
+        if ( Number == 0 )
+        {
+            int RetValue;
+            RetValue = Sto_ManAddClause( p, pLits, pLits + nLits );
+            assert( RetValue );
+            nLits = 0;
+            continue;
+        }
+        if ( nLits == nLitsAlloc )
+        {
+            nLitsAlloc *= 2;
+            pLits = ABC_REALLOC( lit, pLits, nLitsAlloc );
+        }
+        pLits[ nLits++ ] = lit_read(Number);
+    }
+    if ( nLits > 0 )
+        printf( "Error: The last clause was not saved.\n" );
+
+    // count clauses
+    Counter = 0;
+    Sto_ManForEachClause( p, pClause )
+        Counter++;
+
+    // check the number of clauses
+    if ( p->nClauses != Counter )
+    {
+        printf( "Error: The actual number of clauses (%d) is different than declared (%d).\n", Counter, p->nClauses );
+        Sto_ManFree( p );
+        return NULL;
+    }
+
+    ABC_FREE( pLits );
+    fclose( pFile );
+    return p;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bsat/satStore.h b/abc-build/src/sat/bsat/satStore.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satStore.h
@@ -0,0 +1,158 @@
+/**CFile****************************************************************
+
+  FileName    [satStore.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Proof recording.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: pr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__sat__bsat__satStore_h
+#define ABC__sat__bsat__satStore_h
+
+
+/*
+    The trace of SAT solving contains the original clauses of the problem
+    along with the learned clauses derived during SAT solving.
+    The first line of the resulting file contains 3 numbers instead of 2:
+    c <num_vars> <num_all_clauses> <num_root_clauses>
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include "satSolver.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+#ifdef _WIN32
+#define inline __inline // compatible with MS VS 6.0
+#endif
+
+#define STO_MAX(a,b)  ((a) > (b) ? (a) : (b))
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+/*
+typedef unsigned lit;
+// variable/literal conversions (taken from MiniSat)
+static inline lit   toLit    (int v)        { return v + v;  }
+static inline lit   toLitCond(int v, int c) { return v + v + (c != 0); }
+static inline lit   lit_neg  (lit l)        { return l ^ 1;  }
+static inline int   lit_var  (lit l)        { return l >> 1; }
+static inline int   lit_sign (lit l)        { return l & 1;  }
+static inline int   lit_print(lit l)        { return lit_sign(l)? -lit_var(l)-1 : lit_var(l)+1; }
+static inline lit   lit_read (int s)        { return s > 0 ? toLit(s-1) : lit_neg(toLit(-s-1)); }
+static inline int   lit_check(lit l, int n) { return l >= 0 && lit_var(l) < n;                  }
+*/
+
+typedef struct Sto_Cls_t_ Sto_Cls_t;
+struct Sto_Cls_t_
+{
+    Sto_Cls_t *     pNext;        // the next clause
+    Sto_Cls_t *     pNext0;       // the next 0-watch
+    Sto_Cls_t *     pNext1;       // the next 1-watch
+    int             Id;           // the clause ID
+    unsigned        fA     :  1;  // belongs to A
+    unsigned        fRoot  :  1;  // original clause
+    unsigned        fVisit :  1;  // visited clause
+    unsigned        nLits  : 24;  // the number of literals
+    lit             pLits[0];     // literals of this clause
+};
+
+typedef struct Sto_Man_t_ Sto_Man_t;
+struct Sto_Man_t_
+{
+    // general data
+    int             nVars;        // the number of variables
+    int             nRoots;       // the number of root clauses
+    int             nClauses;     // the number of all clauses
+    int             nClausesA;    // the number of clauses of A 
+    Sto_Cls_t *     pHead;        // the head clause
+    Sto_Cls_t *     pTail;        // the tail clause
+    Sto_Cls_t *     pEmpty;       // the empty clause
+    // memory management
+    int             nChunkSize;   // the number of bytes in a chunk
+    int             nChunkUsed;   // the number of bytes used in the last chunk
+    char *          pChunkLast;   // the last memory chunk
+};
+
+// iterators through the clauses
+#define Sto_ManForEachClause( p, pCls )      for( pCls = p->pHead; pCls; pCls = pCls->pNext )
+#define Sto_ManForEachClauseRoot( p, pCls )  for( pCls = p->pHead; pCls && pCls->fRoot; pCls = pCls->pNext )
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== satStore.c ==========================================================*/
+extern Sto_Man_t *  Sto_ManAlloc();
+extern void         Sto_ManFree( Sto_Man_t * p );
+extern int          Sto_ManAddClause( Sto_Man_t * p, lit * pBeg, lit * pEnd );
+extern int          Sto_ManMemoryReport( Sto_Man_t * p );
+extern void         Sto_ManMarkRoots( Sto_Man_t * p );
+extern void         Sto_ManMarkClausesA( Sto_Man_t * p );
+extern void         Sto_ManDumpClauses( Sto_Man_t * p, char * pFileName );
+extern int          Sto_ManChangeLastClause( Sto_Man_t * p );
+extern Sto_Man_t *  Sto_ManLoadClauses( char * pFileName );
+
+
+/*=== satInter.c ==========================================================*/
+typedef struct Int_Man_t_ Int_Man_t;
+extern Int_Man_t *  Int_ManAlloc();
+extern int *        Int_ManSetGlobalVars( Int_Man_t * p, int nGloVars );
+extern void         Int_ManFree( Int_Man_t * p );
+extern int          Int_ManInterpolate( Int_Man_t * p, Sto_Man_t * pCnf, int fVerbose, unsigned ** ppResult );
+
+/*=== satInterA.c ==========================================================*/
+typedef struct Inta_Man_t_ Inta_Man_t;
+extern Inta_Man_t * Inta_ManAlloc();
+extern void         Inta_ManFree( Inta_Man_t * p );
+extern void *       Inta_ManInterpolate( Inta_Man_t * p, Sto_Man_t * pCnf, abctime TimeToStop, void * vVarsAB, int fVerbose );
+
+/*=== satInterB.c ==========================================================*/
+typedef struct Intb_Man_t_ Intb_Man_t;
+extern Intb_Man_t * Intb_ManAlloc();
+extern void         Intb_ManFree( Intb_Man_t * p );
+extern void *       Intb_ManInterpolate( Intb_Man_t * p, Sto_Man_t * pCnf, void * vVarsAB, int fVerbose );
+
+/*=== satInterP.c ==========================================================*/
+typedef struct Intp_Man_t_ Intp_Man_t;
+extern Intp_Man_t * Intp_ManAlloc();
+extern void         Intp_ManFree( Intp_Man_t * p );
+extern void *       Intp_ManUnsatCore( Intp_Man_t * p, Sto_Man_t * pCnf, int fLearned, int fVerbose );
+extern void         Intp_ManUnsatCorePrintForBmc( FILE * pFile, Sto_Man_t * pCnf, void * vCore, void * vVarMap );
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/sat/bsat/satTrace.c b/abc-build/src/sat/bsat/satTrace.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satTrace.c
@@ -0,0 +1,112 @@
+/**CFile****************************************************************
+
+  FileName    [satTrace.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT sat_solver.]
+
+  Synopsis    [Records the trace of SAT solving in the CNF form.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: satTrace.c,v 1.4 2005/09/16 22:55:03 casem Exp $]
+
+***********************************************************************/
+
+#include "satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+    The trace of SAT solving contains the original clause of the problem
+    along with the learned clauses derived during SAT solving.
+    The first line of the resulting file contains 3 numbers instead of 2:
+    c <num_vars> <num_all_clauses> <num_root_clauses>
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Start the trace recording.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_SolverTraceStart( sat_solver * pSat, char * pName )
+{
+    assert( pSat->pFile == NULL );
+    pSat->pFile = fopen( pName, "w" );
+    fprintf( pSat->pFile, "                                        \n" );
+    pSat->nClauses = 0;
+    pSat->nRoots = 0;
+}   
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the trace recording.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_SolverTraceStop( sat_solver * pSat )
+{
+    if ( pSat->pFile == NULL )
+        return;
+    rewind( pSat->pFile );
+    fprintf( pSat->pFile, "p %d %d %d", sat_solver_nvars(pSat), pSat->nClauses, pSat->nRoots );
+    fclose( pSat->pFile );
+    pSat->pFile = NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes one clause into the trace file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_SolverTraceWrite( sat_solver * pSat, int * pBeg, int * pEnd, int fRoot )
+{
+    if ( pSat->pFile == NULL )
+        return;
+    pSat->nClauses++;
+    pSat->nRoots += fRoot;
+    for ( ; pBeg < pEnd ; pBeg++ )
+        fprintf( pSat->pFile, " %d", lit_print(*pBeg) );
+    fprintf( pSat->pFile, " 0\n" );
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bsat/satTruth.c b/abc-build/src/sat/bsat/satTruth.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satTruth.c
@@ -0,0 +1,299 @@
+/**CFile****************************************************************
+
+  FileName    [satTruth.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT solver.]
+
+  Synopsis    [Truth table computation package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: satTruth.c,v 1.4 2005/09/16 22:55:03 casem Exp $]
+
+***********************************************************************/
+
+#include "satTruth.h"
+#include "misc/vec/vecSet.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+struct Tru_Man_t_
+{
+    int              nVars;        // the number of variables
+    int              nWords;       // the number of words in the truth table
+    int              nEntrySize;   // the size of one entry in 'int'
+    int              nTableSize;   // hash table size
+    int *            pTable;       // hash table
+    Vec_Set_t *      pMem;         // memory for truth tables
+    word *           pZero;        // temporary truth table 
+    int              hIthVars[16]; // variable handles
+    int              nTableLookups;
+};
+
+typedef struct Tru_One_t_ Tru_One_t; // 16 bytes minimum
+struct Tru_One_t_
+{
+    int              Handle;       // support
+    int              Next;         // next one in the table
+    word             pTruth[0];    // truth table
+};
+
+static inline Tru_One_t * Tru_ManReadOne( Tru_Man_t * p, int h ) { return h ? (Tru_One_t *)Vec_SetEntry(p->pMem, h) : NULL; }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the hash key.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Tru_ManHash( word * pTruth, int nWords, int nBins, int * pPrimes )
+{
+    int i;
+    unsigned uHash = 0;
+    for ( i = 0; i < nWords; i++ )
+        uHash ^= pTruth[i] * pPrimes[i & 0x7];
+    return uHash % nBins;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the given record.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Tru_ManLookup( Tru_Man_t * p, word * pTruth )
+{
+    static int s_Primes[10] = { 1291, 1699, 2357, 4177, 5147, 5647, 6343, 7103, 7873, 8147 };
+    Tru_One_t * pEntry;
+    int * pSpot;
+    assert( (pTruth[0] & 1) == 0 );
+    pSpot = p->pTable + Tru_ManHash( pTruth, p->nWords, p->nTableSize, s_Primes );
+    for ( pEntry = Tru_ManReadOne(p, *pSpot); pEntry; pSpot = &pEntry->Next, pEntry = Tru_ManReadOne(p, *pSpot) )
+        if ( Tru_ManEqual(pEntry->pTruth, pTruth, p->nWords) )
+            return pSpot;
+    return pSpot;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the given record.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tru_ManResize( Tru_Man_t * p )
+{
+    Tru_One_t * pThis;
+    int * pTableOld, * pSpot;
+    int nTableSizeOld, iNext, Counter, i;
+    assert( p->pTable != NULL );
+    // replace the table
+    pTableOld = p->pTable;
+    nTableSizeOld = p->nTableSize;
+    p->nTableSize = 2 * p->nTableSize + 1; 
+    p->pTable = ABC_CALLOC( int, p->nTableSize );
+    // rehash the entries from the old table
+    Counter = 0;
+    for ( i = 0; i < nTableSizeOld; i++ )
+    for ( pThis = Tru_ManReadOne(p, pTableOld[i]),
+          iNext = (pThis? pThis->Next : 0);  
+          pThis;  pThis = Tru_ManReadOne(p, iNext),   
+          iNext = (pThis? pThis->Next : 0)  )
+    {
+        assert( pThis->Handle );
+        pThis->Next = 0;
+        pSpot = Tru_ManLookup( p, pThis->pTruth );
+        assert( *pSpot == 0 ); // should not be there
+        *pSpot = pThis->Handle;
+        Counter++;
+    }
+    assert( Counter == Vec_SetEntryNum(p->pMem) );
+    ABC_FREE( pTableOld );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds entry to the hash table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Tru_ManInsert( Tru_Man_t * p, word * pTruth )
+{
+    int fCompl, * pSpot;
+    if ( Tru_ManEqual0(pTruth, p->nWords) )
+        return 0;
+    if ( Tru_ManEqual1(pTruth, p->nWords) )
+        return 1;
+    p->nTableLookups++;
+    if ( Vec_SetEntryNum(p->pMem) > 2 * p->nTableSize )
+        Tru_ManResize( p );
+    fCompl = pTruth[0] & 1;
+    if ( fCompl )  
+        Tru_ManNot( pTruth, p->nWords );
+    pSpot = Tru_ManLookup( p, pTruth );
+    if ( *pSpot == 0 )
+    {
+        Tru_One_t * pEntry;
+        *pSpot = Vec_SetAppend( p->pMem, NULL, p->nEntrySize );
+        assert( (*pSpot & 1) == 0 );
+        pEntry = Tru_ManReadOne( p, *pSpot );
+        Tru_ManCopy( pEntry->pTruth, pTruth, p->nWords );
+        pEntry->Handle = *pSpot;
+        pEntry->Next = 0;
+    }
+    if ( fCompl )  
+        Tru_ManNot( pTruth, p->nWords );
+    return *pSpot ^ fCompl;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Start the truth table logging.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Tru_Man_t * Tru_ManAlloc( int nVars )
+{
+    word Masks[6] = 
+    { 
+        ABC_CONST(0xAAAAAAAAAAAAAAAA), 
+        ABC_CONST(0xCCCCCCCCCCCCCCCC), 
+        ABC_CONST(0xF0F0F0F0F0F0F0F0), 
+        ABC_CONST(0xFF00FF00FF00FF00), 
+        ABC_CONST(0xFFFF0000FFFF0000), 
+        ABC_CONST(0xFFFFFFFF00000000) 
+    };
+    Tru_Man_t * p;
+    int i, w;
+    assert( nVars > 0 && nVars <= 16 );
+    p = ABC_CALLOC( Tru_Man_t, 1 );
+    p->nVars      = nVars;
+    p->nWords     = (nVars < 6) ? 1 : (1 << (nVars-6));
+    p->nEntrySize = (sizeof(Tru_One_t) + p->nWords * sizeof(word))/sizeof(int);
+    p->nTableSize = 8147;
+    p->pTable     = ABC_CALLOC( int, p->nTableSize );
+    p->pMem       = Vec_SetAlloc( 16 );
+    // initialize truth tables
+    p->pZero = ABC_ALLOC( word, p->nWords );
+    for ( i = 0; i < nVars; i++ )
+    {
+        for ( w = 0; w < p->nWords; w++ )
+            if ( i < 6 )
+                p->pZero[w] = Masks[i];
+            else if ( w & (1 << (i-6)) )
+                p->pZero[w] = ~(word)0;
+            else
+                p->pZero[w] = 0;
+        p->hIthVars[i] = Tru_ManInsert( p, p->pZero );
+        assert( !i || p->hIthVars[i] > p->hIthVars[i-1] );
+    }
+    Tru_ManClear( p->pZero, p->nWords );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stop the truth table logging.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Tru_ManFree( Tru_Man_t * p )
+{
+    printf( "Lookups = %d. Entries = %d.\n", p->nTableLookups, Vec_SetEntryNum(p->pMem) );
+    Vec_SetFree( p->pMem );
+    ABC_FREE( p->pZero );
+    ABC_FREE( p->pTable );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns elementary variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word * Tru_ManVar( Tru_Man_t * p, int v )
+{
+    assert( v >= 0 && v < p->nVars );
+    return Tru_ManReadOne( p, p->hIthVars[v] )->pTruth;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns stored truth table]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word * Tru_ManFunc( Tru_Man_t * p, int h )
+{
+    assert( (h & 1) == 0 );
+    if ( h == 0 )
+        return p->pZero;
+    return Tru_ManReadOne( p, h )->pTruth;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bsat/satTruth.h b/abc-build/src/sat/bsat/satTruth.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satTruth.h
@@ -0,0 +1,89 @@
+/**CFile****************************************************************
+
+  FileName    [satTruth.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [SAT solver.]
+
+  Synopsis    [Truth table computation package.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: satTruth.h,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__sat__bsat__satTruth_h
+#define ABC__sat__bsat__satTruth_h
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "misc/util/abc_global.h"
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Tru_Man_t_ Tru_Man_t;
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int    Tru_ManEqual( word * pOut, word * pIn, int nWords )  { int w; for ( w = 0; w < nWords; w++ ) if(pOut[w]!=pIn[w])  return 0; return 1; }
+static inline int    Tru_ManEqual0( word * pOut, int nWords )             { int w; for ( w = 0; w < nWords; w++ ) if(pOut[w]!=0)       return 0; return 1; }
+static inline int    Tru_ManEqual1( word * pOut, int nWords )             { int w; for ( w = 0; w < nWords; w++ ) if(pOut[w]!=~(word)0)return 0; return 1; }
+static inline word * Tru_ManCopy( word * pOut, word * pIn, int nWords )   { int w; for ( w = 0; w < nWords; w++ ) pOut[w] =   pIn[w];  return pOut;        }
+static inline word * Tru_ManClear( word * pOut, int nWords )              { int w; for ( w = 0; w < nWords; w++ ) pOut[w] = 0;         return pOut;        }
+static inline word * Tru_ManFill( word * pOut, int nWords )               { int w; for ( w = 0; w < nWords; w++ ) pOut[w] = ~(word)0;  return pOut;        }
+static inline word * Tru_ManNot( word * pOut, int nWords )                { int w; for ( w = 0; w < nWords; w++ ) pOut[w] = ~pOut[w];  return pOut;        }
+static inline word * Tru_ManAnd( word * pOut, word * pIn, int nWords )    { int w; for ( w = 0; w < nWords; w++ ) pOut[w] &=  pIn[w];  return pOut;        }
+static inline word * Tru_ManOr( word * pOut, word * pIn, int nWords )     { int w; for ( w = 0; w < nWords; w++ ) pOut[w] |=  pIn[w];  return pOut;        }
+static inline word * Tru_ManCopyNot( word * pOut, word * pIn, int nWords ){ int w; for ( w = 0; w < nWords; w++ ) pOut[w] =  ~pIn[w];  return pOut;        }
+static inline word * Tru_ManAndNot( word * pOut, word * pIn, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) pOut[w] &= ~pIn[w];  return pOut;        }
+static inline word * Tru_ManOrNot( word * pOut, word * pIn, int nWords )  { int w; for ( w = 0; w < nWords; w++ ) pOut[w] |= ~pIn[w];  return pOut;        }
+static inline word * Tru_ManCopyNotCond( word * pOut, word * pIn, int nWords, int fCompl ){ return fCompl ? Tru_ManCopyNot(pOut, pIn, nWords) : Tru_ManCopy(pOut, pIn, nWords); }
+static inline word * Tru_ManAndNotCond( word * pOut, word * pIn, int nWords, int fCompl ) { return fCompl ? Tru_ManAndNot(pOut, pIn, nWords)  : Tru_ManAnd(pOut, pIn, nWords);  }
+static inline word * Tru_ManOrNotCond( word * pOut, word * pIn, int nWords, int fCompl )  { return fCompl ? Tru_ManOrNot(pOut, pIn, nWords)   : Tru_ManOr(pOut, pIn, nWords);   }
+
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DECLARATIONS                        ///
+////////////////////////////////////////////////////////////////////////
+
+extern Tru_Man_t *   Tru_ManAlloc( int nVars );
+extern void          Tru_ManFree( Tru_Man_t * p );
+extern word *        Tru_ManVar( Tru_Man_t * p, int v );
+extern word *        Tru_ManFunc( Tru_Man_t * p, int h );
+extern int           Tru_ManInsert( Tru_Man_t * p, word * pTruth );
+//extern int           Tru_ManHandleMax( Tru_Man_t * p );
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/sat/bsat/satUtil.c b/abc-build/src/sat/bsat/satUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satUtil.c
@@ -0,0 +1,354 @@
+/**CFile****************************************************************
+
+  FileName    [satUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [C-language MiniSat solver.]
+
+  Synopsis    [Additional SAT solver procedures.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: satUtil.c,v 1.4 2005/09/16 22:55:03 casem Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <assert.h>
+#include "satSolver.h"
+#include "satSolver2.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Sat_SolverClauseWriteDimacs( FILE * pFile, clause * pC, int fIncrement );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the given clause in a file in DIMACS format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_SolverClauseWriteDimacs( FILE * pFile, clause * pC, int fIncrement )
+{
+    int i;
+    for ( i = 0; i < (int)pC->size; i++ )
+        fprintf( pFile, "%s%d ", (lit_sign(pC->lits[i])? "-": ""),  lit_var(pC->lits[i]) + (fIncrement>0) );
+    if ( fIncrement )
+        fprintf( pFile, "0" );
+    fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Write the clauses in the solver into a file in DIMACS format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_SolverWriteDimacs( sat_solver * p, char * pFileName, lit* assumpBegin, lit* assumpEnd, int incrementVars )
+{
+    Sat_Mem_t * pMem = &p->Mem;
+    FILE * pFile;
+    clause * c;
+    int i, k, nUnits;
+
+    // count the number of unit clauses
+    nUnits = 0;
+    for ( i = 0; i < p->size; i++ )
+        if ( p->levels[i] == 0 && p->assigns[i] != 3 )
+            nUnits++;
+
+    // start the file
+    pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Sat_SolverWriteDimacs(): Cannot open the ouput file.\n" );
+        return;
+    }
+//    fprintf( pFile, "c CNF generated by ABC on %s\n", Extra_TimeStamp() );
+    fprintf( pFile, "p cnf %d %d\n", p->size, Sat_MemEntryNum(&p->Mem, 0)-1+Sat_MemEntryNum(&p->Mem, 1)+nUnits+(int)(assumpEnd-assumpBegin) );
+
+    // write the original clauses
+    Sat_MemForEachClause( pMem, c, i, k )
+        Sat_SolverClauseWriteDimacs( pFile, c, incrementVars );
+
+    // write the learned clauses
+//    Sat_MemForEachLearned( pMem, c, i, k )
+//        Sat_SolverClauseWriteDimacs( pFile, c, incrementVars );
+
+    // write zero-level assertions
+    for ( i = 0; i < p->size; i++ )
+        if ( p->levels[i] == 0 && p->assigns[i] != 3 ) // varX
+            fprintf( pFile, "%s%d%s\n",
+                     (p->assigns[i] == 1)? "-": "",    // var0
+                     i + (int)(incrementVars>0),
+                     (incrementVars) ? " 0" : "");
+
+    // write the assump
+    if (assumpBegin) {
+        for (; assumpBegin != assumpEnd; assumpBegin++) {
+            fprintf( pFile, "%s%d%s\n",
+                     lit_sign(*assumpBegin)? "-": "",
+                     lit_var(*assumpBegin) + (int)(incrementVars>0),
+                     (incrementVars) ? " 0" : "");
+        }
+    }
+
+    fprintf( pFile, "\n" );
+    fclose( pFile );
+} 
+void Sat_Solver2WriteDimacs( sat_solver2 * p, char * pFileName, lit* assumpBegin, lit* assumpEnd, int incrementVars )
+{
+    Sat_Mem_t * pMem = &p->Mem;
+    FILE * pFile;
+    clause * c;
+    int i, k, nUnits;
+
+    // count the number of unit clauses
+    nUnits = 0;
+    for ( i = 0; i < p->size; i++ )
+        if ( p->levels[i] == 0 && p->assigns[i] != 3 )
+            nUnits++;
+
+    // start the file
+    pFile = fopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Sat_SolverWriteDimacs(): Cannot open the ouput file.\n" );
+        return;
+    }
+//    fprintf( pFile, "c CNF generated by ABC on %s\n", Extra_TimeStamp() );
+    fprintf( pFile, "p cnf %d %d\n", p->size, Sat_MemEntryNum(&p->Mem, 0)-1+Sat_MemEntryNum(&p->Mem, 1)+nUnits+(int)(assumpEnd-assumpBegin) );
+
+    // write the original clauses
+    Sat_MemForEachClause2( pMem, c, i, k )
+        Sat_SolverClauseWriteDimacs( pFile, c, incrementVars );
+
+    // write the learned clauses
+//    Sat_MemForEachLearned( pMem, c, i, k )
+//        Sat_SolverClauseWriteDimacs( pFile, c, incrementVars );
+
+    // write zero-level assertions
+    for ( i = 0; i < p->size; i++ )
+        if ( p->levels[i] == 0 && p->assigns[i] != 3 ) // varX
+            fprintf( pFile, "%s%d%s\n",
+                     (p->assigns[i] == 1)? "-": "",    // var0
+                     i + (int)(incrementVars>0),
+                     (incrementVars) ? " 0" : "");
+
+    // write the assump
+    if (assumpBegin) {
+        for (; assumpBegin != assumpEnd; assumpBegin++) {
+            fprintf( pFile, "%s%d%s\n",
+                     lit_sign(*assumpBegin)? "-": "",
+                     lit_var(*assumpBegin) + (int)(incrementVars>0),
+                     (incrementVars) ? " 0" : "");
+        }
+    }
+
+    fprintf( pFile, "\n" );
+    fclose( pFile );
+}   
+  
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the given clause in a file in DIMACS format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_SolverPrintStats( FILE * pFile, sat_solver * p )
+{
+//    printf( "calls         : %10d (%d)\n", (int)p->nCalls, (int)p->nCalls2 );
+    printf( "starts        : %10d\n", (int)p->stats.starts );
+    printf( "conflicts     : %10d\n", (int)p->stats.conflicts );
+    printf( "decisions     : %10d\n", (int)p->stats.decisions );
+    printf( "propagations  : %10d\n", (int)p->stats.propagations );
+//    printf( "inspects      : %10d\n", (int)p->stats.inspects );
+//    printf( "inspects2     : %10d\n", (int)p->stats.inspects2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the given clause in a file in DIMACS format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_Solver2PrintStats( FILE * pFile, sat_solver2 * s )
+{
+    printf( "starts        : %10d\n", (int)s->stats.starts );
+    printf( "conflicts     : %10d\n", (int)s->stats.conflicts );
+    printf( "decisions     : %10d\n", (int)s->stats.decisions );
+    printf( "propagations  : %10d\n", (int)s->stats.propagations );
+//    printf( "inspects      : %10d\n", (int)s->stats.inspects );
+//    printf( "inspects2     : %10d\n", (int)s->stats.inspects2 );
+/*
+    printf( "memory for variables %.1f MB (free %6.2f %%) and clauses %.1f MB (free %6.2f %%)\n", 
+        1.0 * Sat_Solver2GetVarMem(s) * s->size / (1<<20),
+        100.0 * (s->cap - s->size) / s->cap,
+        4.0 * (s->clauses.cap + s->learnts.cap) / (1<<20),
+        100.0 * (s->clauses.cap - s->clauses.size + 
+                 s->learnts.cap - s->learnts.size) / 
+                (s->clauses.cap + s->learnts.cap) );
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of bytes used for each variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Sat_Solver2GetVarMem( sat_solver2 * s )
+{
+    int Mem = 0;
+    Mem += (sizeof(s->activity[0]) == 4) ? sizeof(unsigned) : sizeof(double);  // activity
+    Mem += 2 * sizeof(veci); // wlists
+    Mem += sizeof(int);      // vi (variable info)
+    Mem += sizeof(int);      // trail
+    Mem += sizeof(int);      // orderpos
+    Mem += sizeof(int);      // reasons
+    Mem += sizeof(int);      // units
+    Mem += sizeof(int);      // order
+    Mem += sizeof(int);      // model
+    return Mem;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns a counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Sat_SolverGetModel( sat_solver * p, int * pVars, int nVars )
+{
+    int * pModel;
+    int i;
+    pModel = ABC_CALLOC( int, nVars+1 );
+    for ( i = 0; i < nVars; i++ )
+        pModel[i] = sat_solver_var_value(p, pVars[i]);
+    return pModel;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns a counter-example.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Sat_Solver2GetModel( sat_solver2 * p, int * pVars, int nVars )
+{
+    int * pModel;
+    int i;
+    pModel = ABC_CALLOC( int, nVars+1 );
+    for ( i = 0; i < nVars; i++ )
+        pModel[i] = sat_solver2_var_value(p, pVars[i]);
+    return pModel;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates all clauses, complements unit clause of the given var.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Sat_SolverDoubleClauses( sat_solver * p, int iVar )
+{
+    assert( 0 );
+/*
+    clause * pClause;
+    lit Lit, * pLits;
+    int RetValue, nClauses, nVarsOld, nLitsOld, nLits, c, v;
+    // get the number of variables
+    nVarsOld = p->size;
+    nLitsOld = 2 * p->size;
+    // extend the solver to depend on two sets of variables
+    sat_solver_setnvars( p, 2 * p->size );
+    // duplicate implications
+    for ( v = 0; v < nVarsOld; v++ )
+        if ( p->assigns[v] != l_Undef )
+        {
+            Lit = nLitsOld + toLitCond( v, p->assigns[v]==l_False );
+            if ( v == iVar )
+                Lit = lit_neg(Lit);
+            RetValue = sat_solver_addclause( p, &Lit, &Lit + 1 );
+            assert( RetValue );
+        }
+    // duplicate clauses
+    nClauses = vecp_size(&p->clauses);
+    for ( c = 0; c < nClauses; c++ )
+    {
+        pClause = (clause *)p->clauses.ptr[c];
+        nLits = clause_size(pClause);
+        pLits = clause_begin(pClause);
+        for ( v = 0; v < nLits; v++ )
+            pLits[v] += nLitsOld;
+        RetValue = sat_solver_addclause( p, pLits, pLits + nLits );
+        assert( RetValue );
+        for ( v = 0; v < nLits; v++ )
+            pLits[v] -= nLitsOld;
+    }
+*/
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/bsat/satVec.h b/abc-build/src/sat/bsat/satVec.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/bsat/satVec.h
@@ -0,0 +1,161 @@
+/**************************************************************************************************
+MiniSat -- Copyright (c) 2005, Niklas Sorensson
+http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+// Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko
+
+#ifndef ABC__sat__bsat__satVec_h
+#define ABC__sat__bsat__satVec_h
+
+#include "misc/util/abc_global.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+// vector of 32-bit intergers (added for 64-bit portability)
+struct veci_t {
+    int    cap;
+    int    size;
+    int*   ptr;
+};
+typedef struct veci_t veci;
+
+static inline void veci_new (veci* v) {
+    v->cap  = 4;
+    v->size = 0;
+    v->ptr  = (int*)ABC_ALLOC( char, sizeof(int)*v->cap);
+}
+
+static inline void   veci_delete (veci* v)          { ABC_FREE(v->ptr);   }
+static inline int*   veci_begin  (veci* v)          { return v->ptr;  }
+static inline int    veci_size   (veci* v)          { return v->size; }
+static inline void   veci_resize (veci* v, int k)   { 
+    assert(k <= v->size); 
+//    memset( veci_begin(v) + k, -1, sizeof(int) * (veci_size(v) - k) );
+    v->size = k;         
+} // only safe to shrink !!
+static inline int    veci_pop    (veci* v)          { assert(v->size); return v->ptr[--v->size]; }
+static inline void   veci_push   (veci* v, int e)
+{
+    if (v->size == v->cap) {
+//        int newsize = v->cap * 2;//+1;
+        int newsize = (v->cap < 4) ? v->cap * 2 : (v->cap / 2) * 3;
+        v->ptr = ABC_REALLOC( int, v->ptr, newsize );
+        if ( v->ptr == NULL )
+        {
+            printf( "Failed to realloc memory from %.1f MB to %.1f MB.\n", 
+                1.0 * v->cap / (1<<20), 1.0 * newsize / (1<<20) );
+            fflush( stdout );
+        }
+        v->cap = newsize; }
+    v->ptr[v->size++] = e;
+}
+static inline void   veci_remove(veci* v, int e)
+{
+    int * ws = (int*)veci_begin(v);
+    int    j  = 0;
+    for (; ws[j] != e  ; j++);
+    assert(j < veci_size(v));
+    for (; j < veci_size(v)-1; j++) ws[j] = ws[j+1];
+    veci_resize(v,veci_size(v)-1);
+}
+
+
+// vector of 32- or 64-bit pointers
+struct vecp_t {
+    int    cap;
+    int    size;
+    void** ptr;
+};
+typedef struct vecp_t vecp;
+
+static inline void vecp_new (vecp* v) {
+    v->size = 0;
+    v->cap  = 4;
+    v->ptr  = (void**)ABC_ALLOC( char, sizeof(void*)*v->cap);
+}
+
+static inline void   vecp_delete (vecp* v)          { ABC_FREE(v->ptr);   }
+static inline void** vecp_begin  (vecp* v)          { return v->ptr;  }
+static inline int    vecp_size   (vecp* v)          { return v->size; }
+static inline void   vecp_resize (vecp* v, int   k) { assert(k <= v->size); v->size = k;    } // only safe to shrink !!
+static inline void   vecp_push   (vecp* v, void* e)
+{
+    if (v->size == v->cap) {
+//        int newsize = v->cap * 2;//+1;
+        int newsize = (v->cap < 4) ? v->cap * 2 : (v->cap / 2) * 3;
+        v->ptr = ABC_REALLOC( void*, v->ptr, newsize );
+        v->cap = newsize; }
+    v->ptr[v->size++] = e;
+}
+static inline void   vecp_remove(vecp* v, void* e)
+{
+    void** ws = vecp_begin(v);
+    int    j  = 0;
+    for (; ws[j] != e  ; j++);
+    assert(j < vecp_size(v));
+    for (; j < vecp_size(v)-1; j++) ws[j] = ws[j+1];
+    vecp_resize(v,vecp_size(v)-1);
+}
+
+
+
+//=================================================================================================
+// Simple types:
+
+#ifndef __cplusplus
+#ifndef false
+#  define false 0
+#endif
+#ifndef true
+#  define true 1
+#endif
+#endif
+
+typedef int    lit;
+typedef int    cla;
+
+typedef char               lbool;
+
+static const int   var_Undef = -1;
+static const lit   lit_Undef = -2;
+
+static const lbool l_Undef   =  0;
+static const lbool l_True    =  1;
+static const lbool l_False   = -1;
+
+static inline lit  toLit    (int v)        { return v + v; }
+static inline lit  toLitCond(int v, int c) { return v + v + (c != 0); }
+static inline lit  lit_neg  (lit l)        { return l ^ 1; }
+static inline int  lit_var  (lit l)        { return l >> 1; }
+static inline int  lit_sign (lit l)        { return l & 1; }
+static inline int  lit_print(lit l)        { return lit_sign(l)? -lit_var(l)-1 : lit_var(l)+1; }
+static inline lit  lit_read (int s)        { return s > 0 ? toLit(s-1) : lit_neg(toLit(-s-1)); }
+static inline int  lit_check(lit l, int n) { return l >= 0 && lit_var(l) < n;                  }
+
+struct stats_t
+{
+    unsigned starts, clauses, learnts;
+    ABC_INT64_T decisions, propagations, inspects, conflicts;
+    ABC_INT64_T clauses_literals, learnts_literals, tot_literals;
+};
+typedef struct stats_t stats_t;
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/sat/cnf/cnf.h b/abc-build/src/sat/cnf/cnf.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/cnf/cnf.h
@@ -0,0 +1,201 @@
+/**CFile****************************************************************
+
+  FileName    [cnf.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [DAG-aware AIG rewriting.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: cnf.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__aig__cnf__cnf_h
+#define ABC__aig__cnf__cnf_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/vec/vec.h"
+#include "aig/aig/aig.h"
+#include "opt/dar/darInt.h"
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+ 
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Cnf_Man_t_            Cnf_Man_t;
+typedef struct Cnf_Dat_t_            Cnf_Dat_t;
+typedef struct Cnf_Cut_t_            Cnf_Cut_t;
+
+// the CNF asserting outputs of AIG to be 1
+struct Cnf_Dat_t_
+{
+    Aig_Man_t *     pMan;            // the AIG manager, for which CNF is computed
+    int             nVars;           // the number of variables
+    int             nLiterals;       // the number of CNF literals
+    int             nClauses;        // the number of CNF clauses
+    int **          pClauses;        // the CNF clauses
+    int *           pVarNums;        // the number of CNF variable for each node ID (-1 if unused)
+    int *           pObj2Clause;     // the mapping of objects into clauses
+    int *           pObj2Count;      // the mapping of objects into clause number
+    unsigned char * pClaPols;        // polarity of input literals in each clause
+    Vec_Int_t *     vMapping;        // mapping of internal nodes
+};
+
+// the cut used to represent node in the AIG
+struct Cnf_Cut_t_
+{
+    char            nFanins;         // the number of leaves
+    char            Cost;            // the cost of this cut
+    short           nWords;          // the number of words in truth table
+    Vec_Int_t *     vIsop[2];        // neg/pos ISOPs
+    int             pFanins[0];      // the fanins (followed by the truth table)
+};
+
+// the CNF computation manager
+struct Cnf_Man_t_
+{
+    Aig_Man_t *     pManAig;         // the underlying AIG manager
+    char *          pSopSizes;       // sizes of SOPs for 4-variable functions
+    char **         pSops;           // the SOPs for 4-variable functions
+    int             aArea;           // the area of the mapping
+    Aig_MmFlex_t *  pMemCuts;        // memory manager for cuts
+    int             nMergeLimit;     // the limit on the size of merged cut
+    unsigned *      pTruths[4];      // temporary truth tables
+    Vec_Int_t *     vMemory;         // memory for intermediate ISOP representation
+    abctime         timeCuts; 
+    abctime         timeMap;
+    abctime         timeSave;
+};
+
+
+static inline Dar_Cut_t *  Dar_ObjBestCut( Aig_Obj_t * pObj ) { Dar_Cut_t * pCut; int i; Dar_ObjForEachCut( pObj, pCut, i ) if ( pCut->fBest ) return pCut; return NULL; }
+
+static inline int          Cnf_CutSopCost( Cnf_Man_t * p, Dar_Cut_t * pCut ) { return p->pSopSizes[pCut->uTruth] + p->pSopSizes[0xFFFF & ~pCut->uTruth]; }
+
+static inline int          Cnf_CutLeaveNum( Cnf_Cut_t * pCut )    { return pCut->nFanins;                               }
+static inline int *        Cnf_CutLeaves( Cnf_Cut_t * pCut )      { return pCut->pFanins;                               }
+static inline unsigned *   Cnf_CutTruth( Cnf_Cut_t * pCut )       { return (unsigned *)(pCut->pFanins + pCut->nFanins); }
+
+static inline Cnf_Cut_t *  Cnf_ObjBestCut( Aig_Obj_t * pObj )                       { return (Cnf_Cut_t *)pObj->pData;  }
+static inline void         Cnf_ObjSetBestCut( Aig_Obj_t * pObj, Cnf_Cut_t * pCut )  { pObj->pData = pCut;  }
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                           ITERATORS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// iterator over the clauses
+#define Cnf_CnfForClause( p, pBeg, pEnd, i )                         \
+    for ( i = 0; i < p->nClauses && (pBeg = p->pClauses[i]) && (pEnd = p->pClauses[i+1]); i++ )
+
+// iterator over leaves of the cut
+#define Cnf_CutForEachLeaf( p, pCut, pLeaf, i )                         \
+    for ( i = 0; (i < (int)(pCut)->nFanins) && ((pLeaf) = Aig_ManObj(p, (pCut)->pFanins[i])); i++ )
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== cnfCore.c ========================================================*/
+extern Vec_Int_t *     Cnf_DeriveMappingArray( Aig_Man_t * pAig );
+extern Cnf_Dat_t *     Cnf_Derive( Aig_Man_t * pAig, int nOutputs );
+extern Cnf_Dat_t *     Cnf_DeriveWithMan( Cnf_Man_t * p, Aig_Man_t * pAig, int nOutputs );
+extern Cnf_Dat_t *     Cnf_DeriveOther( Aig_Man_t * pAig, int fSkipTtMin );
+extern Cnf_Dat_t *     Cnf_DeriveOtherWithMan( Cnf_Man_t * p, Aig_Man_t * pAig, int fSkipTtMin );
+extern void            Cnf_ManPrepare();
+extern Cnf_Man_t *     Cnf_ManRead();
+extern void            Cnf_ManFree();
+/*=== cnfCut.c ========================================================*/
+extern Cnf_Cut_t *     Cnf_CutCreate( Cnf_Man_t * p, Aig_Obj_t * pObj );
+extern void            Cnf_CutPrint( Cnf_Cut_t * pCut );
+extern void            Cnf_CutFree( Cnf_Cut_t * pCut );
+extern void            Cnf_CutUpdateRefs( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, Cnf_Cut_t * pCutRes );
+extern Cnf_Cut_t *     Cnf_CutCompose( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int iFan );
+/*=== cnfData.c ========================================================*/
+extern void            Cnf_ReadMsops( char ** ppSopSizes, char *** ppSops );
+/*=== cnfFast.c ========================================================*/
+extern void            Cnf_CollectLeaves( Aig_Obj_t * pRoot, Vec_Ptr_t * vSuper, int fStopCompl );
+extern void            Cnf_ComputeClauses( Aig_Man_t * p, Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, 
+                           Vec_Ptr_t * vNodes, Vec_Int_t * vMap, Vec_Int_t * vCover, Vec_Int_t * vClauses );
+extern void            Cnf_DeriveFastMark( Aig_Man_t * p );
+extern Cnf_Dat_t *     Cnf_DeriveFast( Aig_Man_t * p, int nOutputs );
+/*=== cnfMan.c ========================================================*/
+extern Cnf_Man_t *     Cnf_ManStart();
+extern void            Cnf_ManStop( Cnf_Man_t * p );
+extern Vec_Int_t *     Cnf_DataCollectPiSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p );
+extern Cnf_Dat_t *     Cnf_DataAlloc( Aig_Man_t * pAig, int nVars, int nClauses, int nLiterals );
+extern Cnf_Dat_t *     Cnf_DataDup( Cnf_Dat_t * p );
+extern void            Cnf_DataFree( Cnf_Dat_t * p );
+extern void            Cnf_DataLift( Cnf_Dat_t * p, int nVarsPlus );
+extern void            Cnf_DataFlipLastLiteral( Cnf_Dat_t * p );
+extern void            Cnf_DataPrint( Cnf_Dat_t * p, int fReadable );
+extern void            Cnf_DataWriteIntoFile( Cnf_Dat_t * p, char * pFileName, int fReadable, Vec_Int_t * vForAlls, Vec_Int_t * vExists );
+extern void *          Cnf_DataWriteIntoSolver( Cnf_Dat_t * p, int nFrames, int fInit );
+extern void *          Cnf_DataWriteIntoSolverInt( void * pSat, Cnf_Dat_t * p, int nFrames, int fInit );
+extern int             Cnf_DataWriteOrClause( void * pSat, Cnf_Dat_t * pCnf );
+extern int             Cnf_DataWriteAndClauses( void * p, Cnf_Dat_t * pCnf );
+extern void            Cnf_DataTranformPolarity( Cnf_Dat_t * pCnf, int fTransformPos );
+extern int             Cnf_DataAddXorClause( void * pSat, int iVarA, int iVarB, int iVarC );
+/*=== cnfMap.c ========================================================*/
+extern void            Cnf_DeriveMapping( Cnf_Man_t * p );
+extern int             Cnf_ManMapForCnf( Cnf_Man_t * p );
+/*=== cnfPost.c ========================================================*/
+extern void            Cnf_ManTransferCuts( Cnf_Man_t * p );
+extern void            Cnf_ManFreeCuts( Cnf_Man_t * p );
+extern void            Cnf_ManPostprocess( Cnf_Man_t * p );
+/*=== cnfUtil.c ========================================================*/
+extern Vec_Ptr_t *     Aig_ManScanMapping( Cnf_Man_t * p, int fCollect );
+extern Vec_Ptr_t *     Cnf_ManScanMapping( Cnf_Man_t * p, int fCollect, int fPreorder );
+extern Vec_Int_t *     Cnf_DataCollectCiSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p );
+extern Vec_Int_t *     Cnf_DataCollectCoSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p );
+extern unsigned char * Cnf_DataDeriveLitPolarities( Cnf_Dat_t * p );
+extern Cnf_Dat_t *     Cnf_DataReadFromFile( char * pFileName );
+/*=== cnfWrite.c ========================================================*/
+extern Vec_Int_t *     Cnf_ManWriteCnfMapping( Cnf_Man_t * p, Vec_Ptr_t * vMapped );
+extern void            Cnf_SopConvertToVector( char * pSop, int nCubes, Vec_Int_t * vCover );
+extern Cnf_Dat_t *     Cnf_ManWriteCnf( Cnf_Man_t * p, Vec_Ptr_t * vMapped, int nOutputs );
+extern Cnf_Dat_t *     Cnf_ManWriteCnfOther( Cnf_Man_t * p, Vec_Ptr_t * vMapped );
+extern Cnf_Dat_t *     Cnf_DeriveSimple( Aig_Man_t * p, int nOutputs );
+extern Cnf_Dat_t *     Cnf_DeriveSimpleForRetiming( Aig_Man_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/sat/cnf/cnfCore.c b/abc-build/src/sat/cnf/cnfCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/cnf/cnfCore.c
@@ -0,0 +1,290 @@
+/**CFile****************************************************************
+
+  FileName    [cnfCore.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG-to-CNF conversion.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: cnfCore.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cnf.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static Cnf_Man_t * s_pManCnf = NULL;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_ManPrepare()
+{
+    if ( s_pManCnf == NULL )
+    {
+//        printf( "\n\nCreating CNF manager!!!!!\n\n" );
+        s_pManCnf = Cnf_ManStart();
+    }
+}
+Cnf_Man_t * Cnf_ManRead()
+{
+    return s_pManCnf;
+}
+void Cnf_ManFree()
+{
+    if ( s_pManCnf == NULL )
+        return;
+    Cnf_ManStop( s_pManCnf );
+    s_pManCnf = NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Converts AIG into the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Cnf_DeriveMappingArray( Aig_Man_t * pAig )
+{
+    Vec_Int_t * vResult;
+    Cnf_Man_t * p;
+    Vec_Ptr_t * vMapped;
+    Aig_MmFixed_t * pMemCuts;
+    abctime clk;
+    // allocate the CNF manager
+    p = Cnf_ManStart();
+    p->pManAig = pAig;
+
+    // generate cuts for all nodes, assign cost, and find best cuts
+clk = Abc_Clock();
+    pMemCuts = Dar_ManComputeCuts( pAig, 10, 0, 0 );
+p->timeCuts = Abc_Clock() - clk;
+
+    // find the mapping
+clk = Abc_Clock();
+    Cnf_DeriveMapping( p );
+p->timeMap = Abc_Clock() - clk;
+//    Aig_ManScanMapping( p, 1 );
+
+    // convert it into CNF
+clk = Abc_Clock();
+    Cnf_ManTransferCuts( p );
+    vMapped = Cnf_ManScanMapping( p, 1, 0 );
+    vResult = Cnf_ManWriteCnfMapping( p, vMapped );
+    Vec_PtrFree( vMapped );
+    Aig_MmFixedStop( pMemCuts, 0 );
+p->timeSave = Abc_Clock() - clk;
+
+   // reset reference counters
+    Aig_ManResetRefs( pAig );
+//ABC_PRT( "Cuts   ", p->timeCuts );
+//ABC_PRT( "Map    ", p->timeMap  );
+//ABC_PRT( "Saving ", p->timeSave );
+    Cnf_ManStop( p );
+    return vResult;
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Converts AIG into the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Dat_t * Cnf_DeriveWithMan( Cnf_Man_t * p, Aig_Man_t * pAig, int nOutputs )
+{
+    Cnf_Dat_t * pCnf;
+    Vec_Ptr_t * vMapped;
+    Aig_MmFixed_t * pMemCuts;
+    abctime clk;
+    // connect the managers
+    p->pManAig = pAig;
+
+    // generate cuts for all nodes, assign cost, and find best cuts
+clk = Abc_Clock();
+    pMemCuts = Dar_ManComputeCuts( pAig, 10, 0, 0 );
+p->timeCuts = Abc_Clock() - clk;
+
+    // find the mapping
+clk = Abc_Clock();
+    Cnf_DeriveMapping( p );
+p->timeMap = Abc_Clock() - clk;
+//    Aig_ManScanMapping( p, 1 );
+
+    // convert it into CNF
+clk = Abc_Clock();
+    Cnf_ManTransferCuts( p );
+    vMapped = Cnf_ManScanMapping( p, 1, 1 );
+    pCnf = Cnf_ManWriteCnf( p, vMapped, nOutputs );
+    Vec_PtrFree( vMapped );
+    Aig_MmFixedStop( pMemCuts, 0 );
+p->timeSave = Abc_Clock() - clk;
+
+   // reset reference counters
+    Aig_ManResetRefs( pAig );
+//ABC_PRT( "Cuts   ", p->timeCuts );
+//ABC_PRT( "Map    ", p->timeMap  );
+//ABC_PRT( "Saving ", p->timeSave );
+    return pCnf;
+}
+Cnf_Dat_t * Cnf_Derive( Aig_Man_t * pAig, int nOutputs )
+{
+    Cnf_ManPrepare();
+    return Cnf_DeriveWithMan( s_pManCnf, pAig, nOutputs );
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    [Converts AIG into the SAT solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Dat_t * Cnf_DeriveOtherWithMan( Cnf_Man_t * p, Aig_Man_t * pAig, int fSkipTtMin )
+{
+    Cnf_Dat_t * pCnf;
+    Vec_Ptr_t * vMapped;
+    Aig_MmFixed_t * pMemCuts;
+    abctime clk;
+    // connect the managers
+    p->pManAig = pAig;
+
+    // generate cuts for all nodes, assign cost, and find best cuts
+clk = Abc_Clock();
+    pMemCuts = Dar_ManComputeCuts( pAig, 10, fSkipTtMin, 0 );
+p->timeCuts = Abc_Clock() - clk;
+
+    // find the mapping
+clk = Abc_Clock();
+    Cnf_DeriveMapping( p );
+p->timeMap = Abc_Clock() - clk;
+//    Aig_ManScanMapping( p, 1 );
+
+    // convert it into CNF
+clk = Abc_Clock();
+    Cnf_ManTransferCuts( p );
+    vMapped = Cnf_ManScanMapping( p, 1, 1 );
+    pCnf = Cnf_ManWriteCnfOther( p, vMapped );
+    pCnf->vMapping = Cnf_ManWriteCnfMapping( p, vMapped );
+    Vec_PtrFree( vMapped );
+    Aig_MmFixedStop( pMemCuts, 0 );
+p->timeSave = Abc_Clock() - clk;
+
+   // reset reference counters
+    Aig_ManResetRefs( pAig );
+//ABC_PRT( "Cuts   ", p->timeCuts );
+//ABC_PRT( "Map    ", p->timeMap  );
+//ABC_PRT( "Saving ", p->timeSave );
+    return pCnf;
+}
+Cnf_Dat_t * Cnf_DeriveOther( Aig_Man_t * pAig, int fSkipTtMin )
+{
+    Cnf_ManPrepare();
+    return Cnf_DeriveOtherWithMan( s_pManCnf, pAig, fSkipTtMin );
+}
+
+#if 0
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Dat_t * Cnf_Derive_old( Aig_Man_t * pAig )
+{
+/*
+    // iteratively improve area flow
+    for ( i = 0; i < nIters; i++ )
+    {
+clk = Abc_Clock();
+        Cnf_ManScanMapping( p, 0 );
+        Cnf_ManMapForCnf( p );
+ABC_PRT( "iter ", Abc_Clock() - clk );
+    }
+*/
+    // write the file
+    vMapped = Aig_ManScanMapping( p, 1 );
+    Vec_PtrFree( vMapped );
+
+clk = Abc_Clock();
+    Cnf_ManTransferCuts( p );
+
+    Cnf_ManPostprocess( p );
+    Cnf_ManScanMapping( p, 0 );
+/*
+    Cnf_ManPostprocess( p );
+    Cnf_ManScanMapping( p, 0 );
+    Cnf_ManPostprocess( p );
+    Cnf_ManScanMapping( p, 0 );
+*/
+ABC_PRT( "Ext ", Abc_Clock() - clk );
+
+/*
+    vMapped = Cnf_ManScanMapping( p, 1 );
+    pCnf = Cnf_ManWriteCnf( p, vMapped );
+    Vec_PtrFree( vMapped );
+
+    // clean up
+    Cnf_ManFreeCuts( p );
+    Dar_ManCutsFree( pAig );
+    return pCnf;
+*/
+    Aig_MmFixedStop( pMemCuts, 0 );
+    return NULL;
+}
+
+#endif
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/cnf/cnfCut.c b/abc-build/src/sat/cnf/cnfCut.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/cnf/cnfCut.c
@@ -0,0 +1,376 @@
+/**CFile****************************************************************
+
+  FileName    [cnfCut.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG-to-CNF conversion.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: cnfCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cnf.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates cut of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Cut_t * Cnf_CutAlloc( Cnf_Man_t * p, int nLeaves )
+{
+    Cnf_Cut_t * pCut;
+    int nSize = sizeof(Cnf_Cut_t) + sizeof(int) * nLeaves + sizeof(unsigned) * Abc_TruthWordNum(nLeaves);
+    pCut = (Cnf_Cut_t *)Aig_MmFlexEntryFetch( p->pMemCuts, nSize );
+    pCut->nFanins = nLeaves;
+    pCut->nWords = Abc_TruthWordNum(nLeaves);
+    pCut->vIsop[0] = pCut->vIsop[1] = NULL;
+    return pCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_CutFree( Cnf_Cut_t * pCut )
+{
+    if ( pCut->vIsop[0] )
+        Vec_IntFree( pCut->vIsop[0] );
+    if ( pCut->vIsop[1] )
+        Vec_IntFree( pCut->vIsop[1] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates cut for the given node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Cut_t * Cnf_CutCreate( Cnf_Man_t * p, Aig_Obj_t * pObj )
+{
+    Dar_Cut_t * pCutBest;
+    Cnf_Cut_t * pCut;
+    unsigned * pTruth;
+    assert( Aig_ObjIsNode(pObj) );
+    pCutBest = Dar_ObjBestCut( pObj );
+    assert( pCutBest != NULL );
+    assert( pCutBest->nLeaves <= 4 );
+    pCut = Cnf_CutAlloc( p, pCutBest->nLeaves );
+    memcpy( pCut->pFanins, pCutBest->pLeaves, sizeof(int) * pCutBest->nLeaves );
+    pTruth = Cnf_CutTruth(pCut);
+    *pTruth = (pCutBest->uTruth << 16) | pCutBest->uTruth;
+    pCut->Cost = Cnf_CutSopCost( p, pCutBest );
+    return pCut;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_CutPrint( Cnf_Cut_t * pCut )
+{
+    int i;
+    printf( "{" );
+    for ( i = 0; i < pCut->nFanins; i++ )
+        printf( "%d ", pCut->pFanins[i] );
+    printf( " } " );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates cut of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_CutDeref( Cnf_Man_t * p, Cnf_Cut_t * pCut )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Cnf_CutForEachLeaf( p->pManAig, pCut, pObj, i )
+    {
+        assert( pObj->nRefs > 0 );
+        pObj->nRefs--;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates cut of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_CutRef( Cnf_Man_t * p, Cnf_Cut_t * pCut )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Cnf_CutForEachLeaf( p->pManAig, pCut, pObj, i )
+    {
+        pObj->nRefs++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates cut of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_CutUpdateRefs( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, Cnf_Cut_t * pCutRes )
+{
+    Cnf_CutDeref( p, pCut );
+    Cnf_CutDeref( p, pCutFan );
+    Cnf_CutRef( p, pCutRes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two arrays of integers.]
+
+  Description [Returns the number of items.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cnf_CutMergeLeaves( Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int * pFanins )
+{
+    int i, k, nFanins = 0;
+    for ( i = k = 0; i < pCut->nFanins && k < pCutFan->nFanins; )
+    {
+        if ( pCut->pFanins[i] == pCutFan->pFanins[k] )
+            pFanins[nFanins++] = pCut->pFanins[i], i++, k++;
+        else if ( pCut->pFanins[i] < pCutFan->pFanins[k] )
+            pFanins[nFanins++] = pCut->pFanins[i], i++;
+        else
+            pFanins[nFanins++] = pCutFan->pFanins[k], k++;
+    }
+    for ( ; i < pCut->nFanins; i++ )
+        pFanins[nFanins++] = pCut->pFanins[i];
+    for ( ; k < pCutFan->nFanins; k++ )
+        pFanins[nFanins++] = pCutFan->pFanins[k];
+    return nFanins;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes the stretching phase of the cut w.r.t. the merged cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline unsigned Cnf_TruthPhase( Cnf_Cut_t * pCut, Cnf_Cut_t * pCut1 )
+{
+    unsigned uPhase = 0;
+    int i, k;
+    for ( i = k = 0; i < pCut->nFanins; i++ )
+    {
+        if ( k == pCut1->nFanins )
+            break;
+        if ( pCut->pFanins[i] < pCut1->pFanins[k] )
+            continue;
+        assert( pCut->pFanins[i] == pCut1->pFanins[k] );
+        uPhase |= (1 << i);
+        k++;
+    }
+    return uPhase;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes the fanin variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_CutRemoveIthVar( Cnf_Cut_t * pCut, int iVar, int iFan )
+{
+    int i;
+    assert( pCut->pFanins[iVar] == iFan );
+    pCut->nFanins--;
+    for ( i = iVar; i < pCut->nFanins; i++ )
+        pCut->pFanins[i] = pCut->pFanins[i+1];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the fanin variable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_CutInsertIthVar( Cnf_Cut_t * pCut, int iVar, int iFan )
+{
+    int i;
+    for ( i = pCut->nFanins; i > iVar; i-- )
+        pCut->pFanins[i] = pCut->pFanins[i-1];
+    pCut->pFanins[iVar] = iFan;
+    pCut->nFanins++;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Merges two cuts.]
+
+  Description [Returns NULL of the cuts cannot be merged.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Cut_t * Cnf_CutCompose( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int iFan )
+{
+    Cnf_Cut_t * pCutRes;
+    static int pFanins[32];
+    unsigned * pTruth, * pTruthFan, * pTruthRes;
+    unsigned * pTop = p->pTruths[0], * pFan = p->pTruths[2], * pTemp = p->pTruths[3];
+    unsigned uPhase, uPhaseFan;
+    int i, iVar, nFanins, RetValue;
+
+    // make sure the second cut is the fanin of the first
+    for ( iVar = 0; iVar < pCut->nFanins; iVar++ )
+        if ( pCut->pFanins[iVar] == iFan )
+            break;
+    assert( iVar < pCut->nFanins );
+    // remove this variable
+    Cnf_CutRemoveIthVar( pCut, iVar, iFan );
+    // merge leaves of the cuts
+    nFanins = Cnf_CutMergeLeaves( pCut, pCutFan, pFanins );
+    if ( nFanins+1 > p->nMergeLimit )
+    {
+        Cnf_CutInsertIthVar( pCut, iVar, iFan );
+        return NULL;
+    }
+    // create new cut
+    pCutRes = Cnf_CutAlloc( p, nFanins );
+    memcpy( pCutRes->pFanins, pFanins, sizeof(int) * nFanins );
+    assert( pCutRes->nFanins <= pCut->nFanins + pCutFan->nFanins );
+
+    // derive its truth table
+    // get the truth tables in the composition space
+    pTruth    = Cnf_CutTruth(pCut);
+    pTruthFan = Cnf_CutTruth(pCutFan);
+    pTruthRes = Cnf_CutTruth(pCutRes);
+    for ( i = 0; i < 2*pCutRes->nWords; i++ )
+        pTop[i] = pTruth[i % pCut->nWords];
+    for ( i = 0; i < pCutRes->nWords; i++ )
+        pFan[i] = pTruthFan[i % pCutFan->nWords];
+    // move the variable to the end
+    uPhase = Kit_BitMask( pCutRes->nFanins+1 ) & ~(1 << iVar);
+    Kit_TruthShrink( pTemp, pTop, pCutRes->nFanins, pCutRes->nFanins+1, uPhase, 1 );
+    // compute the phases
+    uPhase    = Cnf_TruthPhase( pCutRes, pCut    ) | (1 << pCutRes->nFanins);
+    uPhaseFan = Cnf_TruthPhase( pCutRes, pCutFan );
+    // permute truth-tables to the common support
+    Kit_TruthStretch( pTemp, pTop, pCut->nFanins+1,  pCutRes->nFanins+1, uPhase,    1 );
+    Kit_TruthStretch( pTemp, pFan, pCutFan->nFanins, pCutRes->nFanins,   uPhaseFan, 1 );
+    // perform Boolean operation
+    Kit_TruthMux( pTruthRes, pTop, pTop+pCutRes->nWords, pFan, pCutRes->nFanins );
+    // return the cut to its original condition
+    Cnf_CutInsertIthVar( pCut, iVar, iFan );
+    // consider the simple case
+    if ( pCutRes->nFanins < 5 )
+    {
+        pCutRes->Cost = p->pSopSizes[0xFFFF & *pTruthRes] + p->pSopSizes[0xFFFF & ~*pTruthRes];
+        return pCutRes;
+    }
+
+    // derive ISOP for positive phase
+    RetValue = Kit_TruthIsop( pTruthRes, pCutRes->nFanins, p->vMemory, 0 );
+    pCutRes->vIsop[1] = (RetValue == -1)? NULL : Vec_IntDup( p->vMemory );
+    // derive ISOP for negative phase
+    Kit_TruthNot( pTruthRes, pTruthRes, pCutRes->nFanins );
+    RetValue = Kit_TruthIsop( pTruthRes, pCutRes->nFanins, p->vMemory, 0 );
+    pCutRes->vIsop[0] = (RetValue == -1)? NULL : Vec_IntDup( p->vMemory );
+    Kit_TruthNot( pTruthRes, pTruthRes, pCutRes->nFanins );
+
+    // compute the cut cost
+    if ( pCutRes->vIsop[0] == NULL || pCutRes->vIsop[1] == NULL )
+        pCutRes->Cost = 127;
+    else if ( Vec_IntSize(pCutRes->vIsop[0]) + Vec_IntSize(pCutRes->vIsop[1]) > 127 )
+        pCutRes->Cost = 127;
+    else
+        pCutRes->Cost = Vec_IntSize(pCutRes->vIsop[0]) + Vec_IntSize(pCutRes->vIsop[1]);
+    return pCutRes;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/cnf/cnfData.c b/abc-build/src/sat/cnf/cnfData.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/cnf/cnfData.c
@@ -0,0 +1,4789 @@
+/**CFile****************************************************************
+
+  FileName    [cnfData.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG-to-CNF conversion.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: cnfData.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cnf.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static const char s_Data3[82] = "!#&()*+,-.0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]abcdefghijklmnopqrstuvwxyz|";
+
+static const char * s_Data4[] = {
+"! B a . 8 .B 8a K !K T Ta j 8j Tj s ( + (B +a (. +8 .B( +8a (K +K T( +T j( ",
+"+j Tj( s+ E !E H Ha E. 8E H. H8 EK EK! HT HTa jE 8jE Hj sH d +d Hd g d. 8d ",
+"Hd. g8 dK +dK Td gT dj +jd Hjd gs 2 !2 2B a2 5 58 5B 5a 2K 2K! T2 Ta2 5j 58",
+"j 5T s5 ; +; ;B a; 5; > 5;B >a ;K +;K T; +T; ;j >j 5T; s> E2 !E2 H2 Ha2 5E ",
+"58E H5 H58 EK2 !E2K HT2 TaH2 5jE 8j5E H5T sH5 d; +d; H; g; 5d >d H5d g> dK;",
+" dK+; H;T gT; 5dj >jd H;j gs> N !N NB aN N. 8N .BN 8aN Q Q! QT Qa Qj Q8 QTj",
+" sQ (N +N (BN +aN N.( +8N (BN. 8a+N Q( +Q QT( +QT Qj( +Q8 TjQ( s+Q W W! HW ",
+"Wa W. W8 HW. H8W WQ Q!W Z Za Wj W8Q Zj sZ Wd +W HWd gW Wd. +W8 WdH. gW8 Qd ",
+"+WQ Zd gZ Wjd +Wj Zdj gZs m m! mB am 5m 8m 5mB 5am Qm Q!m Tm Qam p p8 pT sp",
+" m; +m m;B +ma 5m; >m m;5B >ma Q; +Qm Q;T +Tm p; p> pT; sp> Wm W!m Hm Hma 5",
+"W 5W8 H5W H8m WQm WmQ! Zm Zam pW pW8 Zp sZp v v+ vH gv v5 v> vH5 gv> vQ v+Q",
+" Zv gZv pv pv> Zpv y # & #B a& #. 8& .B# 8a& #K &K T# T& j# &j Tj# s& #( +&",
+" #B( +a& #(. +8& #(.B 8a+& #(K +&K T#( +T& j#( +j& j#T( s+& #E &E H# H& #E.",
+" 8&E H#. H8& EK# &EK HT# H&T j#E &jE Hj# sH& d# d& Hd# g& d#. 8d& d#H. g8& ",
+"dK# d&K Td# gT& dj# d&j H#dj gs& #2 &2 2B# a&2 5# 5& 5B# 5a& 2K# &2K T#2 T&",
+"2 5j# 5&j 5T# s5& ;# ;& ;#B a;& 5;# >& ;#5B >&a ;#K ;&K T;# T;& ;j# >&j 5#T",
+"; s>& #E2 &E2 H#2 H&2 5#E 5&E H5# H5& #E2K EK&2 T#H2 H2T& j#5E 5E&j H#5T H5",
+"s& d;# d&; H;# g;& 5d# >&d H#5d g>& ;#dK dK;& H#T; T;g& 5#dj d&>j H#;j >&gs",
+" #N &N #BN a&N N.# 8&N #BN. aN8& Q# Q& QT# Qa& Qj# Q8& TjQ# sQ& #(N +&N #(N",
+"B a&+N #(N. 8&+N .BN#( +8a&N Q#( +Q& T#Q( Q&+T j#Q( Q&+j QTj#( +Qs& W# W& H",
+"W# H&W W#. W8& W#H. W8H& WQ# W&Q Z# Z& Wj# W&j Zj# sZ& Wd# +W& WdH# gW& d#W",
+". 8dW& HWd#. W8g& Qd# Qd& Zd# gZ& W#dj W&+j djZ# Z&gs m# m& m#B am& 5m# 5&m",
+" m#5B am5& Qm# Q&m Tm# Tm& p# p& pT# sp& m;# +m& ;#mB m&a; m;5# >m& 5m;#B a",
+"m>& Q;# Q;& Q#T; T;Q& p;# p>& T;p# p&s> Wm# W&m Hm# Hm& 5W# 5W& H#5W 5WH& Q",
+"mW# WQm& Zm# Z&m pW# p&W Zp# Zp& v# v& vH# gv& v5# v>& H5v# v&g> vQ# v&Q Zv",
+"# Zv& pv# pv& Z#pv y& C !C D Da C. 8C D. D8 CK CK! DT DTa jC 8jC Dj sD C( +",
+"C D( +D C(. +8C D(. +D8 CK( +CK DT( +DT jC( +jC Dj( s+D CE !CE HD HDa CE. 8",
+"CE HD. H8D EKC !CEK HDT DTHa jCE jC8E HjD sHD dC +dC Dd gD dC. 8dC Dd. gD8 ",
+"dKC dK+C DdT gDT djC +Cdj Ddj gsD C2 !C2 D2 Da2 5C 58C 5D 5D8 2KC !C2K DT2 ",
+"T2Da 5jC 8j5C 5DT s5D ;C +;C D; +D; 5;C >C 5D; >D ;CK ;C+K D;T D;+T ;jC >jC",
+" D;j s>D CE2 CE!2 HD2 H2Da 5CE 8C5E H5D 5DH8 CE2K !E2CK H2DT HDTa2 jC5E 58j",
+"CE 5DHj H5sD d;C d;+C H;D gD; 5dC >Cd 5Dd g>D ;CdK +d;CK TdD; D;gT 5Cdj dj>",
+"C Dd5T >Dgs CN !CN DN DaN N.C 8CN DN. D8N QC Q!C QD QDa QjC Q8C QDj sQD C(N",
+" +CN D(N +DN C(N. 8C+N N.D( +ND8 QC( +QC QD( +QD jCQ( +CQ8 Q(Dj +QsD WC W!C",
+" WD WDa WC. W8C WD. WD8 WQC WCQ! ZD ZDa WjC WCQ8 ZDj sZD WdC +WC WDd gWD dC",
+"W. +CW8 W.Dd WDg8 QdC +CQd ZDd gZD WCdj +CWj DdZj gDsZ mC mC! Dm Dma 5mC 8m",
+"C 5Dm D8m QmC mCQ! QDm DmQa pC p8C pD spD m;C +mC Dm; +Dm m;5C >mC 5mD; >Dm",
+" Q;C +CQ; QD; QD+m p;C p>C pD; p>D WmC mCW! HmD DmWa 5WC 5CW8 5WD WD5a QmWC",
+" Q!WmC ZDm DmZa pWC W8pC ZpD pDsZ vC v+C vD gvD v5C v>C vD5 v>D vQC +QvC Zv",
+"D vDgZ pvC >Cpv pvD yD b b& bD c b. b8 bD. c8 bK bK& bT cT bj b8j bTj sc b(",
+" b+ bD( c+ b(. b+8 D(b. c+8 bK( b+K bT( c+T bj( b+j b(Dj sc+ bE b&E bH cH b",
+"E. b8E bH. cH8 bKE &EbK bHT cHT bjE bE&j bHj scH bd b+d bHd gc bd. b8d b.Dd",
+" gc8 bdK bKd& bTd gcT bdj +jbd Hjbd gsc b2 b&2 bD2 c2 b5 b58 b5D c5 bK2 &2b",
+"K bT2 c2T b5j 5&bj b5T sc5 b; b+; b;D c; b5; >b 5Db; c> b;K bK;& bT; c;T b;",
+"j >bj 5Tb; c>s bE2 &Eb2 bH2 c2H b5E bE5& bH5 c5H EKb2 bK&E2 HTb2 HTc2 5jbE ",
+"&jEb5 H5bT sHc5 bd; d&b; bH; gc; b5d >bd H5bd c>g dKb; d&;bK H;bT gTc; 5dbj",
+" bd>j H;bj gsc> bN b&N bDN cN bN. b8N DNb. c8N bQ bQ& bQD cQ bQj bQ8 QDbj s",
+"cQ b(N b+N D(bN c+N N.b( +8bN bD(N. +8cN bQ( b+Q b(QD cQ+ Qjb( +Qb8 bQDj( s",
+"+cQ bW bW& bHW cW bW. bW8 b.WD cW8 bWQ W&bQ Zb Zc bWj W8bQ Zbj Zcs bWd b+W ",
+"WDbd gcW Wdb. +Wb8 bHWd. g8cW bQd +WbQ Zbd Zcg Wjbd +Wbj bdZj gsZc bm bm& b",
+"mD cm b5m b8m 5Dbm c5m bQm Q&bm bTm cQm pb pb8 pbD cp bm; b+m Dmb; cm+ 5mb;",
+" >bm b5Dm; c>m bQ; +Qbm QDb; cQ; pb; p>b bTp; cp> bWm W&bm bHm cWm b5W 5Wb8",
+" H5bW c5W WQbm bWQm& Zbm Zcm pbW bWp& Zpb cpZ vb vb+ vbH cv vb5 v>b bHv5 cv",
+"> vbQ b+vQ Zvb cvZ pvb v>pb pvZb yc 0 !0 0B a0 1 18 1B 1a 0K !K0 T0 Ta0 1j ",
+"18j 1T s1 0( +0 0B( +a0 1( 1+ 1(B 1+a 0(K +0K T0( +T0 1j( 1+j 1T( s1+ E0 !E",
+"0 H0 Ha0 1E 18E 1H 1H8 EK0 !0EK HT0 TaH0 1jE 8j1E 1HT s1H d0 +d0 Hd0 g0 1d ",
+"1+d 1Hd g1 dK0 dK+0 Td0 gT0 1dj +j1d 1Td gs1 02 !02 2B0 a02 15 158 15B 1a5 ",
+"2K0 !02K T02 T2a0 15j 581j 1T5 s15 ;0 +;0 ;0B a;0 1; >1 1;B >1a ;0K ;0+K T;",
+"0 +0T; 1;j >j1 1T; s>1 E02 E0!2 H02 a0H2 15E 581E 1H5 H51a E02K !E20K T0H2 ",
+"HTa02 5j1E 158jE H51T 1Hs5 d;0 d;+0 H;0 g;0 1d5 >1d 1H; g>1 ;0dK +d;0K H0T;",
+" T;g0 dj1; 1d>j H;1T s>g1 0N !0N 0BN a0N 1N 18N 1NB 1aN Q0 Q!0 QT0 Qa0 1Q 1",
+"Q8 1QT s1Q 0(N +0N 0(NB a0+N 1(N 1+N (B1N +a1N Q0( +Q0 T0Q( +0Qa 1Q( 1+Q QT",
+"1( 1+sQ W0 W!0 HW0 Wa0 1W 1W8 1HW 1Wa WQ0 W0Q! Z0 Za0 1WQ W81Q Z1 sZ1 Wd0 +",
+"W0 WdH0 gW0 1Wd 1+W HW1d g1W Qd0 +0Qd Zd0 gZ0 1Qd +W1Q Z1d gZ1 m0 m0! m0B a",
+"m0 1m 1m8 1mB 1am Qm0 m0Q! Tm0 Q0am p1 p18 p1T sp1 m;0 +m0 ;0mB +0am 1m; >m",
+"1 m;1B 1a>m Q;0 +0Q; Q0T; +0Tm p1; p>1 1Tp; s1p> Wm0 m0W! Hm0 H0am 1W5 W81m",
+" 1Hm H81m QmW0 Q!Wm0 Zm0 amZ0 p1W 1Wp8 Zp1 Z1sp v0 v+0 vH0 gv0 v1 v>1 v1H g",
+"v1 vQ0 +Qv0 Zv0 g0Zv pv1 v1p> Zv1 y1 9 9& 9B 9a 91 : 91B :a 9K 9&K 9T 9Ta 9",
+"j :j 9T1 s: 9( 9+ 9(B 9+a 91( :+ 1B9( :+a 9(K 9+K 9T( 9+T 9j( :+j 9(1T s:+ ",
+"9E 9&E 9H 9Ha 91E :E 9H1 :H 9EK &E9K 9HT H&9T 9jE :jE 9Hj s:H 9d 9+d 9Hd g9",
+" 9d1 :d 1H9d g: 9dK 9Kd& 9Td g9T 9dj :dj 1T9d g:s 92 9&2 92B 9a2 95 :5 95B ",
+":5a 92K &29K 9T2 92T& 95j :5j 95T s:5 9; 9+; 9;B 9a; 95; :> 1B9; :>a 9;K 9K",
+";& 9T; +T9; 9;j :>j 1T9; s:> 9E2 &E92 9H2 92H& 95E :5E 9H5 :H5 EK92 9&E2K H",
+"T92 9HT&2 5j9E 5j:E H59T s5:H 9d; d&9; 9H; g9; 95d :>d 1H9; g:> dK9; d&;9K ",
+"H;9T 9Tg; 5d9j >j:d H;9j s:g> 9N 9&N 9NB 9aN 91N :N 1B9N :aN 9Q 9Q& 9QT 9Qa",
+" 9Q1 :Q 1Q9T s:Q 9(N 9+N (B9N +a9N 1(9N :+N 91(NB +a:N 9Q( 9+Q QT9( +Q9T 9(",
+"1Q :Q+ 9Q1T( s+:Q 9W 9W& 9HW 9Wa 9W1 :W 1H9W :HW 9WQ W&9Q Z9 Z9a 9Wj :WQ Z9",
+"1 Z: 9Wd 9+W HW9d g9W 1W9d :W+ 9H1Wd g:W 9Qd +W9Q Z9d gZ9 1Q9d :Qd 9dZ1 Z:g",
+" 9m 9m& 9mB 9am 95m :m 1B9m :ma 9Qm Q&9m 9Tm Qa9m p9 :p p9T :ps 9m; 9+m m;9",
+"B +m9a 1m9; :>m 95;mB :a>m 9Q; +Q9m Q;9T +T9m p9; :p> 9Tp; s>:p 9Wm W&9m 9H",
+"m Hm9a 95W :W5 1H9m :Hm WQ9m 9WQm& Z9m 9aZm p9W :pW Zp9 Z:p v9 v9+ v9H gv9 ",
+"v91 :v 9Hv1 :vg v9Q 9+vQ Zv9 Zvg9 pv9 :vp pvZ9 y: C0 !C0 D0 Da0 1C 18C 1D 1",
+"D8 CK0 !0CK DT0 TaD0 1jC 8j1C 1DT s1D C0( +C0 D0( +D0 1C( 1+C 1D( 1+D 0(CK ",
+"CK+0 T0D( DT+0 jC1( 1C+j 1(Dj 1+sD CE0 CE!0 HD0 DaH0 1CE 8C1E 1HD H81D C0EK",
+" !E0CK DTH0 HDTa0 jC1E 18jCE Hj1D 1HsD dC0 dC+0 Dd0 gD0 1dC 1C8d 1Dd g1D CK",
+"d0 +dC0K D0Td DTg0 1Cdj djC1+ Dd1T s1gD C02 C0!2 D02 D2a0 15C 581C 1D5 5D1a",
+" C02K C02!K T2D0 DTa02 5j1C 158jC 5D1T 1Ds5 ;C0 ;C+0 D;0 +0D; 1;C >C1 1D; >",
+"D1 CK;0 +;C0K D0T; a;0DT 1C;j 1j>C D;1T s1>D E0C2 C02!E D0H2 HDa02 5C1E 158",
+"CE H51D 1H5D8 C02EK EK0!C2 HDT02 DTaH02 15jCE 58j1CE 1H5Dj s1H5D ;Cd0 +d;C0",
+" H0D; D;g0 1C5d 1d>C H;1D >Dg1 dK;C0 dK;+C0 H;DT0 gDT;0 djC1; >j1dC 1H;Dj g",
+"s>1D C0N C0!N D0N a0DN 1CN 8C1N 1DN 1ND8 QC0 !CQ0 QD0 DaQ0 1QC 1CQ8 1QD 1Qs",
+"D 0(CN C0+N 0(DN D0+N C(1N +C1N D(1N 1N+D C0Q( QC+0 D0Q( +0QD QC1( 1C+Q 1(Q",
+"D +Q1D WC0 !CW0 WD0 DaW0 1WC 1CW8 1WD WD1a QCW0 Q!WC0 ZD0 DaZ0 1CWj 1WQ8C Z",
+"1D sDZ1 dCW0 WC+0 W0Dd WDg0 Wd1C 1C+W WD1d 1WgD dCQ0 +WQC0 DdZ0 ZDg0 1CQd 1",
+"+WQC 1DZd gDZ1 mC0 !Cm0 Dm0 D0am 1mC 1C8m 1Dm D81m mCQ0 Q!mC0 Q0Dm am0QD p1",
+"C 18pC pD1 s1pD ;Cm0 mC+0 m;D0 +0Dm m;1C 1m>C Dm1; 1D>m ;CQ0 +QmC0 Q0D; +QD",
+"m0 1;pC p1>C 1Dp; p1>D mCW0 W!mC0 H0Dm am0WD 1C5W 1W58C Hm1D 1HmD8 WQmC0 Wm",
+"CQ!0 DmZ0 ZDam0 1WpC p1W8C pDZ1 Zp1sD vC0 +Cv0 vD0 g0vD v1C >Cv1 v1D vDg1 Q",
+"Cv0 v+QC0 Z0vD ZvDg0 pCv1 pv>1C v1pD y1D b9 b9& 9D c9 b1 :b b1D :c b9K 9&bK",
+" bT9 c9T b1j :bj b1T s:c b9( b+9 9D( c9+ b1( :b+ b(1D :c+ 9(bK bK9+ b(9T 9+",
+"cT b(9j b+:j b(1T s+:c b9E 9&bE bH9 c9H b1E :bE b1H :cH 9EbK b9&EK 9HbT 9Hc",
+"T bE9j bj:E 9Hbj :Hsc bd9 9+bd 9Dd gc9 b1d :db 1Hbd g:c bK9d d&Kb9 9Tbd c9g",
+"T 9dbj bd:j 1Tbd s:gc b92 9&b2 9D2 c29 b15 :b5 95D :c5 92bK b9&2K b29T 9Tc2",
+" 95bj b5:j 95bT c5s: b;9 9+b; 9D; c;9 b1; :>b 1Db; c>: bK9; ;&Kb9 9Tb; 9Tc;",
+" 9;bj :b>j 1Tb; s:c> 9Eb2 b9&E2 b29H 9Hc2 bE95 b5:E 9Hb5 c5:H b9E2K 9&EbK2 ",
+"bH9T2 c29HT b15jE :b5jE b1H5T :cHs5 9db; d&;b9 9Hb; c;g9 95bd >b:d 1Hb; c>g",
+": bd9;K bd9;&K bH;9T c;9gT b1d;j :>bdj b1HT; g:sc> b9N 9&bN 9DN c9N b1N :bN",
+" bN1D :cN bQ9 b9Q& 9QD cQ9 b1Q :Qb 1QbT :cQ 9(bN bN9+ D(9N 9+cN 1(bN b+:N b",
+"1D(N cN:+ b(9Q 9+bQ 9(QD 9+cQ b(1Q b+:Q b1QD( :+cQ bW9 b9W& 9WD cW9 b1W :Wb",
+" 1HbW :cW 9WbQ bW9Q& Zb9 Zc9 9Wbj bW:Q Zb1 Z:c 9Wbd 9+bW WD9d cWg9 1Wbd b+:",
+"W b1HWd :Wgc 9Qbd b+W9Q bdZ9 g9Zc 1Qbd bQ:d b1Zd Zcg: bm9 b9m& 9Dm cm9 b1m ",
+":mb 1Dbm :cm 9Qbm bQ9m& 9Tbm 9Qcm pb9 :pb p9D cp: 9mb; 9+bm Dm9; 9+cm 1mb; ",
+">b:m b1mD; :mc> 9Qb; b+Q9m QD9; 9Qc; b1p; pb:> 9Dp; c>:p 9Wbm bW9m& 9Hbm 9H",
+"cm 95bW b5:W 1Hbm c5:W bW9Qm 9WQbm& bmZ9 cmZ9 b1pW pb:W pbZ9 cpZ: vb9 b+v9 ",
+"v9D cv9 vb1 :vb b1vD :vc bQv9 vb9+Q vbZ9 Z9cv vbp9 pb:v vbZ1 y:c L !L LB aL",
+" L. 8L .BL 8aL M M! TM aM Mj 8M TMj sM (L +L (BL +aL (L. +8L (L.B 8a+L M( +",
+"M TM( +TM Mj( +M8 MjT( s+M EL !EL HL HaL EL. 8EL HL. H8L ME ME! HM HMa MjE ",
+"8ME HMj sHM dL +dL HdL gL dL. 8dL dLH. g8L dM +Md HMd gM dMj 8dM dMHj gsM L",
+"2 !L2 2BL aL2 5L 58L 5BL 5aL M2 M2! TM2 aM2 5M 5M8 5TM s5M ;L +;L ;LB a;L 5",
+";L >L ;L5B >La M; +M; T;M aM; 5M; >M T;5M >Ms EL2 EL!2 HL2 aLH2 5EL 8E5L H5",
+"L HL5a ME2 !EM2 HM2 H2aM 5ME 5E8M H5M H5sM d;L d;+L H;L g;L 5dL >Ld HL5d g>",
+"L dM; +dM; HM; gM; 5dM >Md 5dHM >Mg LN !LN NBL aLN N.L 8LN LBN. aN8L QM Q!M",
+" QTM QaM QMj Q8M TMQj sQM (LN +LN (LNB aL+N (LN. 8L+N (BLN. +8aLN QM( +QM T",
+"MQ( Qa+M MjQ( Q8+M QTMj( +QsM WL W!L HWL WaL WL. W8L WLH. HLW8 WM WM! ZM Za",
+"M WMj W8M ZMj sZM WdL +WL WdHL gWL dLW. +LW8 HWdL. W8gL WMd +WM ZdM gZM dMW",
+"j W8+M dMZj sZgM mL mL! mLB amL 5mL 8mL mL5B 5Lam Mm Mm! TmM aMm pM p8M pTM",
+" spM m;L +mL ;LmB +Lam m;5L >mL 5m;LB am>L Q;M +Mm MmT; Tm+M pM; >Mp T;pM s",
+"p>M WmL mLW! HmL HLam 5WL 5LW8 HL5W HL8m WMm W!Mm ZMm aMZm pWM W8pM ZpM sMZ",
+"p vL v+L vHL gvL v5L v>L H5vL >Lgv vM vM+ ZvM gvM pvM >Mv vMZp yM #L &L #BL",
+" a&L #L. 8&L #L.B a&8L M# M& TM# T&M Mj# 8M& MjT# sM& #(L +&L #(LB a&+L (L#",
+". 8&+L #L.(B +8a&L M#( +M& M#T( T&+M j#M( M&+j TMj#( +Ms& #EL &EL H#L H&L E",
+"L#. &E8L #LH. 8&HL M#E M&E HM# HM& j#ME 8EM& MjH# HMs& d#L d&L d#HL g&L #Ld",
+". 8Ld& Hd#L. 8&gL dM# dM& H#dM gM& Mjd# d&8M dMjH# sMg& #L2 &L2 #L2B &2aL 5",
+"#L 5&L #B5L a&5L M#2 M&2 M#T2 T2M& 5M# 5M& TM5# 5Ms& ;#L ;&L #B;L aL;& ;#5L",
+" >&L 5;#LB a&>L M;# M;& T#M; M;T& 5#M; >M& M;#5T sM>& EL#2 EL&2 #LH2 &LH2 #",
+"E5L &E5L 5#HL HL5& #EM2 &EM2 M#H2 H2M& M#5E 5EM& H#5M 5MH& ;#dL dL;& ;#HL ;",
+"&gL d#5L d&>L H5d#L g&>L d#M; M;d& H#M; M;g& 5#dM dM>& H5Md# >&gM #LN &LN #",
+"LNB &LaN #LN. &L8N #LN.B 8a&LN QM# Q&M TMQ# aMQ& MjQ# 8MQ& QTMj# Q&sM (L#N ",
+"&L+N #LN(B +a&LN #LN(. +8&LN N.#(BL 8a&+LN M#Q( Q&+M QTM#( +QTM& QMj#( +Q8M",
+"& TMjQ#( s+QM& W#L W&L W#HL HLW& #LW. 8&WL HW#L. H8W&L WM# WM& ZM# Z&M MjW#",
+" 8MW& MjZ# sMZ& d#WL +LW& HWd#L W&gL Wd#L. d&LW8 Wd#HL. gW8&L W#dM W&+M dMZ",
+"# Z&gM dMjW# dM&W8 ZdMj# Z&Mgs m#L m&L #BmL aLm& m#5L 5Lm& 5m#LB am&5L Mm# ",
+"Mm& T#Mm MmT& pM# p&M TMp# sMp& ;#mL +Lm& m;#LB am&+L 5m;#L m&>L m;#5BL >ma",
+"&L Q#M; M;Q& Mm#T; aMm;& M;p# p&>M pTM;# >Mps& m#WL WLm& m#HL HLm& W#5L 5LW",
+"& H5W#L H5&WL W#Mm MmW& MmZ# MmZ& WMp# WMp& pMZ# ZMp& v#L v&L H#vL gLv& 5#v",
+"L >Lv& vH5#L gv>&L vM# vM& Z#vM vMZ& p#vM vMp& ZpvM# y&M U U! UD Ua U. U8 U",
+"D. U8D UM U!M V Va Uj U8M Vj Vs U( U+ UD( U+D U(. U+8 D(U. +DU8 UM( U+M V( ",
+"V+ Uj( U+j Vj( Vs+ UE U!E UH UHa UE. U8E UH. UH8 UME MEU! VH VHa UjE UE8M V",
+"Hj VsH Ud U+d UHd gU Ud. U8d U.Dd gU8 UdM +MUd Vd gV Udj +jUd Vdj gVs U2 U!",
+"2 UD2 Ua2 U5 U58 U5D U5a UM2 M2U! V2 V2a U5M 5MU8 V5 Vs5 U; U+; U;D Ua; U5;",
+" >U 5DU; >UD U;M +MU; V; V+; U;j >MU V5; V> UE2 !EU2 UH2 HaU2 U5E 58UE UH5 ",
+"H5U8 MEU2 U!ME2 V2H HaV2 UE5M U58ME V5H sHV5 Ud; +dU; UH; gU; U5d >Ud H5Ud ",
+"g>U dMU; dM;U+ Vd; gV; 5dUj Ud>M V5d V>g UN U!N UDN UaN UN. U8N DNU. UND8 U",
+"Q UQ! VQ VQa UQj UQ8 VQj VsQ U(N U+N D(UN UN+D N.U( +8UN UD(N. U+D8N UQ( U+",
+"Q VQ( V+Q QjU( +QU8 QjV( sQV+ UW UW! UHW UWa UW. UW8 U.WD H8UW UWQ Q!UW VZ ",
+"VZa UWj W8UQ VZj sZV UWd U+W WDUd gUW WdU. +WU8 UHWd. UWg8 UQd +WUQ VZd gVZ",
+" WjUd +WUj ZjVd sZgV Um Um! UmD Uam U5m U8m 5DUm 5aUm UQm Q!Um Vm Vma pU pU",
+"8 Vp Vps Um; U+m DmU; +DUm 5mU; >Um U5Dm; Ua>m UQ; +QUm Vm; V+m pU; p>U Vp;",
+" V>p UWm W!Um UHm HmUa U5W 5WU8 H5UW H8Um WMUm Mm!UW VZm ZaVm pUW UWp8 VpZ ",
+"sZVp vU vU+ vUH gvU vU5 v>U UHv5 v>gU vUQ U+vM Vv Vvg pvU v>pU Vvp yV bU U&",
+" bUD cU bU. b8U UDb. cU8 bM bM& Vb Vc bMj b8M Vbj scV bU( b+U UDb( cU+ U(b.",
+" U+b8 bUD(. U+c8 bM( b+M Vb( Vc+ b(Uj U+bj bjV( V+sc bUE U&E bHU cUH UEb. b",
+"EU8 b.UH UHc8 bME bEM& VbH VcH bEUj bE8M bHVj sHVc bdU Ud& UHbd gcU b.Ud U8",
+"bd bHUd. cUg8 bdM +Mbd Vdb gVc Udbj 8dbM bdVj scgV bU2 U&2 UDb2 c2U b5U U5&",
+" bU5D c5U bM2 b2M& V2b Vc2 b5M 5Mb8 V5b c5V b;U U;& bUD; c;U U5b; >bU b5UD;",
+" c>U bM; +Mb; V;b c;V U;bj >Mb b5V; V>c UEb2 &EU2 b2UH UHc2 bEU5 UE5& UHb5 ",
+"UHc5 MEb2 M&Eb2 bHV2 cHV2 bE5M b5M8E bHV5 cHV5 Udb; d&U; UHb; c;gU U5bd bd>",
+"U bH5Ud gUc> dMb; dM&b; bHV; c;gV 5dbM bd>M b5Vd c>gV bUN U&N UDbN cUN UNb.",
+" bNU8 bUDN. U8cN bQU UQ& VbQ cQV UQbj UQb8 bQVj VscQ U(bN bNU+ bUD(N U+cN b",
+"U(N. b+U8N UD(bN. cU+8N b(UQ U+bQ bQV( V+cQ bQUj( b+QU8 VbQj( cQVs+ bWU UW&",
+" UHbW cWU b.UW UWb8 bHUW. UWc8 bWM WMU& ZbV ZcV UWbj W8bM VbZj VZsc UWbd U+",
+"bW bHUWd cWgU bWUd. b+WU8 UHWbd. cWUg8 UQbd +WbM VdZb ZcgV bWMdj d&jUW ZbVd",
+"j gVZsc bmU Um& bUDm cmU U5bm U8bm b5UDm U5cm bMm Q&Um Vmb cmV pbU pU& Vpb ",
+"cpV Umb; U+bm bmUD; U+cm b5Um; bm>U U5Dbm; >Ucm UQb; +Mbm bQV; V+cm bMp; pb",
+">M V;pb V>cp UWbm W&Um UHbm UHcm U5bW 5WU& bH5UW U5cW WMbm Mm&bW VmZb VZcm ",
+"bWpU UWp& ZbVp VpZc vbU vU& bHvU cvU b5vU >bvU vbUH5 vUc> vbM b+vM Vvb cvV ",
+"vbpU vb>M pbVv yVc k k! kB ak 1k 8k 1kB 1ak kM kM! Tk Tka l l8 lT ls k( +k ",
+"k(B +ka 1k( 1+k k(1B +k1a kM( +kM Tk( +Tk l( l+ lT( ls+ kE kE! Hk Hka 1kE 8",
+"kE 1Hk H8k kME M!kE HkT akHM lE l8E lH lsH dk +kd Hkd gk 1dk 8dk Hk1d g1k d",
+"kM dk+M Tdk gkT ld l+d lHd gl k2 k2! k2B ak2 5k 5k8 5kB 5ak kM2 M!k2 Tk2 T2",
+"ak l5 l58 l5T ls5 k; +k; k;B ak; 1;k >k 1Bk; >ka k;M k;+M Tk; T;+k l; l> l;",
+"T l>s kE2 !Ek2 Hk2 H2ak 5kE 5E8k H5k 5aHk MEk2 kME!2 H2Tk ak2HM l5E 58lE lH",
+"5 sHl5 dk; +dk; Hk; gk; 5dk >kd Hk1; >kg k;dM dkM+; TkH; Tkg; ld5 l>d lH; g",
+"l> kN kN! kNB akN 1kN 8kN kN1B 1Nak Qk Qk! QkT Qak lQ lQ8 lQT lsQ k(N +kN (",
+"BkN +Nak k(1N 1N+k 1k(NB akN1+ Qk( +Qk Q(Tk Qa+k lQ( l+Q QTl( s+lQ Wk Wk! H",
+"kW Wak 1Wk W8k Hk1W W8Hk WkQ Q!Wk Zk Zka lW lW8 lZ lZs Wkd +Wk HWdk gkW Wk1",
+"d +k1W 1HWdk 1Wgk Qdk Wk+Q Zkd gZk lWd l+W lZd glZ km km! kmB akm 1mk 8km 1",
+"Bkm ak1m Qkm Q!km Tkm akTm lp lp8 lpT lsp km; +km m;kB ak+m km1; >km km;1B ",
+"ak>m Qk; Qk+m TkQ; Tk+m l;p l>p pTl; spl> Wkm W!km Hkm akHm 5Wk W85k Hk1m W",
+"a5k kmWM km!WM Zkm akZm lWp pWl8 lZp splZ vk vk+ vkH gvk v1k >kv 1Hvk gv>k ",
+"vkQ +Qvk Zvk Zvgk lv lv> lvZ yl 9k k& 9kB 9ak 91k :k 1B9k :ak 9M 9M& 9Tk 9a",
+"M l9 l: l9T ls: 9k( 9+k k(9B +k9a 1k9( :+k 91k(B +k:a 9M( 9+M 9(Tk +T9M l9(",
+" l:+ 9Tl( s:l+ 9kE k&E 9Hk Hk& 1k9E :kE 91Hk :Hk 9ME 9EM& 9HM HM9a l9E l:E ",
+"lH9 l:H 9dk dk& Hk9d g9k 91dk :dk 9H1dk g:k 9dM +M9d HM9d g9M ld9 l:d 9Hld ",
+"gl: 9k2 k&2 k29B 92ak 95k :5k 9B5k 5a:k 9M2 92M& 92Tk 92aM l95 l:5 95lT l5s",
+": 9;k k;& 9Bk; ak9; 5k9; >k: k;B95 :a>k 9M; +M9; Tk9; aM9; l;9 l>: 9Tl; s:l",
+"> kE92 &Ek2 92Hk H2k& 9E5k 5k:E Hk95 H5:k ME92 k&EM2 92HM 9HM&2 95lE :5lE 9",
+"Hl5 l5:H dk9; k;d& Hk9; 9;gk 5k9d :d>k 9H5dk >kg: dM9; dk&M; HM9; 9Mg; 95ld",
+" :>ld 9Hl; g:l> 9kN k&N kN9B 9Nak 1k9N :kN 91kNB ak:N 9Qk Qk& Qk9T Qa9M l9Q",
+" l:Q 9QlT :Qls k(9N 9N+k 9k(NB akN9+ 91k(N +k:N 1k(9NB :+akN 9(Qk +Q9M 9QTk",
+"( 9+QTk 9Ql( :Ql+ l9QT( :Q+ls 9Wk Wk& Hk9W Wk9a 91Wk :Wk 9H1Wk Hk:W 9WM W&9",
+"M Z9k Zk& lW9 l:W lZ9 Z:l Wk9d +k9W 9HWdk 9Wgk 9W1dk +W:k 1HW9dk :Wgk WM9d ",
+"+W9M 9dZk Z9gk 9Wld :Wl+ Z9ld Z:gl 9mk km& 9Bkm ak9m 5k9m :mk kmB95 ak:m 9M",
+"m kmQ& Tk9m aM9m p9l :pl lTp9 ls:p km9; +k9m km;9B akm9+ km;95 :m>k 95;kmB ",
+":>akm Qk9; +M9m 9Q;Tk ak;9Q p9l; :pl> l;p9T l>ps: Wk9m kmW& Hk9m kmH& 5k9W ",
+"5W:k 9H5Wk Hk:m WM9m km&WM 9MZm kmZ& p9lW lW:p p9lZ lZ:p v9k vk& 9Hvk v9gk ",
+"95vk :vk v91Hk gk:v v9M 9+vM v9Zk v9gM lv9 lv: Z9lv yl: Uk U!k Dk Uak 1U 1U",
+"8 1UD 1Ua UkM kMU! Vk Vak lU lU8 Vl lsV Uk( U+k Dk( +Dk 1U( 1U+ 1(Dk U+1D k",
+"MU( Uk+M Vk( V+k lU( l+U Vl( l+V UkE kEU! UHk HkUa 1UE 1EU8 1UH UH1a kMUE U",
+"!kME VHk HkVa lUE U8lE lHV VslH Udk +kUd Ddk gUk 1Ud U+1d UH1d g1U UkdM dkM",
+"U+ Vdk gVk ldU U+ld ldV glV Uk2 k2U! Dk2 U2ak 1U5 5kU8 5Dk U51a kMU2 U!kM2 ",
+"V2k akV2 lU5 U5l8 Vl5 V5ls U;k +kU; Dk; D;+k 1U; >kU U;1D >kD UkM; k;MU+ V;",
+"k +kV; l;U l>U l;V V>l kEU2 U!kE2 U2Hk ak2UH 1EU5 1U58E U51H 1UH5a UkME2 kM",
+"EU!2 HkV2 V2Hak U5lE lU58E V5lH lsVH5 dkU; dk;U+ HkU; U;gk U51d 1U>d UH1; g",
+"U>k dkMU; U+dk;M HkV; V;gk U5ld >Uld V5ld V>gl UkN kNU! DkN UNak 1UN 1NU8 1",
+"NDk 1NUa UQk U!Qk VQk QaVk lUQ UQl8 VlQ lQVs k(UN UN+k k(DN +NDk U(1N 1NU+ ",
+"1UD(N 1U+DN U(Qk +kUQ QkV( +QVk UQl( U+lQ VQl( lQV+ UWk U!Wk WDk WkUa 1UW U",
+"81W UH1W UW1a WkUQ UWQk! ZkV VaZk lWU UWl8 lZV VlsZ WkUd +kUW DdWk UWgk UW1",
+"d U+1W 1UHWd 1UgW QkUd U+WQk VdZk ZkgV UWld U+lW VZld lZgV Umk U!km Dkm akU",
+"m 1Um U81m Um1D Ua1m QkUm km!UQ Vmk akVm pUl l8pU Vpl lsVp kmU; +kUm kmD; D",
+"k+m Um1; 1U>m 1UmD; Dk>m QkU; U+Qkm QkV; +kVm pUl; pUl> l;Vp Vpl> WkUm km!U",
+"W HkUm akmUH U51W 1UW8m UH1m 1UH8m UWQkm UWQkm! VmZk ZkVam pUlW lWpU8 lZVp ",
+"VplsZ vUk U+vk vDk vUgk v1U vU>k 1UvD v1gU UQvk vU+Qk Vvk gkVv lvU vUl> lvV",
+" ylV t t& tD tc t1 t: t1D t:c tM tM& Vt tcV lt lt: ltV u t( t+ tD( tc+ t1( ",
+"t:+ 1Dt( :ct+ tM( t+M Vt( t+V lt( lt+ l(Vt u+ tE t&E tH tcH t1E t:E tH1 t:H",
+" tME M&tE tHV VctH ltE lEt: ltH uH td t+d tHd gt td1 t:d 1Htd gt: tdM +Mtd ",
+"tdV gtV ltd t:ld tHld ug t2 t&2 tD2 tc2 t5 t:5 t5D tc5 tM2 M&t2 Vt2 V2tc lt",
+"5 t5l: t5V u5 t; t+; t;D tc; t5; t> 1Dt; t>c t;M +Mt; t;V Vtc; lt; t>l Vlt;",
+" u> tE2 &Et2 tH2 c2tH t5E :5tE tH5 :Ht5 MEt2 tM&E2 V2tH tcVH2 lEt5 t:5lE t5",
+"lH uH5 td; d&t; tH; gt; t5d t>d 1Ht; gt> dMt; t+dM; Vdt; t;gV t5ld ldt> tHl",
+"; ug> tN t&N tDN tcN t1N t:N 1DtN tN:c tQ tQ& tQV tcQ ltQ t:Q VltQ uQ t(N t",
+"+N D(tN c+tN 1(tN :+tN t1D(N t:c+N tQ( t+Q VQt( cQt+ l(tQ tQl+ tQVl( u+Q tW",
+" tW& tHW tcW tW1 t:W 1HtW :ctW tWQ WMt& tZ tZc ltW t:lW tZl uZ tWd t+W WDtd",
+" gtW 1Wtd :Wt+ tH1Wd tWg: tQd +WtQ tZd gtZ tWld t+lW ldtZ uZg tm tm& tmD tc",
+"m t5m t:m 1Dtm :ctm tQm Q&tm tmV cQtm tp tp: tpV up tm; t+m Dmt; cmt+ 1mt; ",
+"t>m t5Dm; tmc> tQ; +Qtm Vmt; cQt; tp; tp> t;Vp up> tWm W&tm tHm cWtm t5W :W",
+"t5 1Htm :Htm WMtm tWQm& tZm tmZc tpW tW:p tZp uZp tv tv+ tvH gtv tv1 tv: v1",
+"tH :vgt tvQ vMt+ tZv cvtZ lvt t>lv tZlv yu ) !) )B a) ). 8) .B) 8a) )K !K) ",
+"T) Ta) j) 8j) Tj) s) * +* *B a* *. 8* *B. 8*a *K +*K T* +T* *j +j* T*j s* E",
+") !E) H) Ha) E). 8E) H). H8) EK) !)EK HT) TaH) jE) jE8) Hj) sH) d* +d* H* g",
+"* d*. 8d* H*. g8* dK* dK+* H*T gT* dj* dj8* H*j gs* )2 !)2 2B) a)2 5) 58) 5",
+"B) 5a) 2K) !)2K T)2 T2a) 5j) 8j5) 5T) s5) ;* +;* *B; a;* 5* >* 5*B >*a ;*K ",
+";*+K T;* a;T* 5*j >*j 5T* s>* E)2 E)!2 H)2 a)H2 5E) 8E5) H5) H)5a E)2K !)2E",
+"K T)H2 HTa)2 jE5) 58jE) H)5T H5s) d;* d;+* H;* g;* 5d* >*d H5* g>* ;*dK +d;",
+"*K T;H* T;g* dj5* dj>* 5TH* s*g> )N !)N )BN a)N N.) 8)N )BN. aN8) Q) Q!) QT",
+") Qa) Qj) Q8) TjQ) sQ) *N +*N *BN a*N *N. 8*N .B*N aN8* Q* +Q* Q*T Qa* Q*j ",
+"Q8* QT*j s*Q W) W!) HW) Wa) W). W8) W)H. H)W8 WQ) W)Q! Z) Za) Wj) W)Q8 Zj) ",
+"sZ) W* +W* H*W gW* W*. W8* H.W* W8g* W*Q W*+Q Z* gZ* W*j W*+j Z*j sZ* m) m)",
+"! m)B am) 5m) 8m) m)5B 5)am Qm) m)Q! Tm) Q)am p) p8) pT) sp) m* +m* m*B am*",
+" 5*m >m* 5m*B am>* Q;* Q*+m Tm* T*+m p* p>* p*T sp* Wm) m)W! Hm) H)am 5W) 5",
+")W8 H)5W H)8m QmW) Q!Wm) Zm) amZ) pW) W8p) Zp) s)Zp v* v+* vH* gv* v5* v>* ",
+"H5v* >*gv vQ* +Qv* Zv* Z*gv pv* v>p* Zp* y* , ,& ,B ,a ,. ,8 ,.B ,8a ,K ,&K",
+" ,T ,Ta ,j ,8j ,Tj s, ,* - *B, -a ,*. -8 ,.*B -8a ,*K -K ,T* -T ,j* -j T*,j",
+" s- ,E ,&E ,H ,Ha ,E. ,8E ,H. ,H8 ,EK &E,K ,HT H&,T ,jE ,E&j ,Hj s,H ,d -d ",
+",Hd g- ,d. -8d ,.H* g-8 ,dK -dK ,Td g-T ,dj -jd H*,j s-g ,2 ,&2 ,2B ,a2 ,5 ",
+",58 ,5B ,5a ,2K &2,K ,T2 ,2T& ,5j 5&,j ,5T s,5 ,; -; ,;B -a; ,5; -> *B,5 ->",
+"a ,;K -;K ,T; -T; ,;j ->j 5T,; s-> ,E2 &E,2 ,H2 ,2H& ,5E ,E5& ,H5 H5,8 EK,2",
+" ,&E2K HT,2 ,HT&2 5j,E &jE,5 H5,T ,Hs5 ,d; -d; ,H; g-; ,5d ->d H5,d g-> dK,",
+"; dK-; H;,T g;-T 5d,j -d>j H;,j g>s- ,N ,&N ,NB ,aN ,N. ,8N .B,N 8a,N ,Q ,Q",
+"& ,QT ,Qa ,Qj ,Q8 QT,j s,Q ,*N -N ,N*B -aN *N,. -8N *B,N. 8a-N ,Q* -Q Q*,T ",
+"-QT Q*,j -Q8 ,QT*j s-Q ,W ,W& ,HW ,Wa ,W. ,W8 HW,. H8,W ,WQ W&,Q Z, Z&, ,Wj",
+" W8,Q Z,j sZ, ,Wd -W H*,W g-W ,.W* -W8 ,HWd. g8-W ,Qd -WQ Z*, Z- W*,j -Wj ,",
+"dZj Z-s ,m ,m& ,mB ,am ,5m ,8m 5m,B 5a,m ,Qm Q&,m ,Tm Qa,m p, p&, p,T sp, ,",
+"m; -m *B,m -ma 5*,m ->m m*B,5 -a>m ,Q; -Qm Q;,T -Tm p*, -p ,Tp* -ps ,Wm W&,",
+"m ,Hm Hm,a ,5W 5W,8 H5,W H8,m WQ,m ,WQm& Z,m ,aZm p,W ,Wp& Zp, Zps, v, -v v",
+",H -vg v,5 -v> ,Hv5 g>-v v,Q -vQ Zv, Z-v pv, -pv pvZ, y- C) !C) D) Da) C). ",
+"8C) D). D8) CK) !)CK DT) TaD) jC) jC8) Dj) sD) *C +*C D* +D* *C. 8*C D*. D8",
+"* *CK *C+K D*T D*+T *jC +C*j D*j s*D CE) CE!) HD) DaH) E)C. CE8) D)H. H)D8 ",
+"C)EK CE)!K DTH) HDTa) CEj) 8jCE) H)Dj HDs) d*C d*+C H*D gD* *Cd. d*8C H.D* ",
+"D8g* *CdK +d*CK TdD* D*gT dC*j dj*+C D*Hj gDs* C)2 C)!2 D)2 D2a) 5C) 8C5) 5",
+"D) 5)D8 C)2K !)2CK T2D) DTa)2 jC5) 58jC) 5)Dj 5Ds) ;*C ;*+C D;* a;D* 5*C >*",
+"C 5D* >D* *C;K +;*CK T;D* a;*DT 5C*j *j>C D*5T >Ds* E)C2 CE)!2 D)H2 HDa)2 C",
+"E5) 58CE) H)5D H5D8) CE)2K EKC!)2 HDT)2 DTaH)2 5jCE) 8jC5E) H5DT) sH5D) ;*d",
+"C +d;*C D;H* D;g* d*5C d*>C 5DH* gD>* dK;*C dK;+*C H;DT* gDT;* dj*5C >*djC ",
+"H5*Dj >D*gs C)N C)!N D)N a)DN C)N. C)8N N.D) 8)DN QC) !CQ) QD) DaQ) jCQ) 8C",
+"Q) Q)Dj QDs) *CN *C+N D*N +ND* N.*C *C8N *ND. DN8* Q*C +CQ* QD* Q*+D QC*j Q",
+"C8* DjQ* QDs* WC) !CW) WD) DaW) C)W. 8CW) D)W. W)D8 QCW) Q!WC) ZD) DaZ) jCW",
+") W8QC) DjZ) ZDs) W*C +CW* WD* WDg* *CW. WC8* W.D* D8W* WCQ* +WQ*C Z*D gDZ*",
+" WC*j +Wj*C D*Zj sDZ* mC) !Cm) Dm) D)am mC5) mC8) 5)Dm D)8m mCQ) Q!mC) Q)Dm",
+" am)QD pC) 8Cp) pD) s)pD m*C +Cm* Dm* D*+m 5Cm* m*>C Dm5* Dm>* QCm* m*C+Q D",
+"mQ* am*QD p*C >Cp* pD* pDs* mCW) W!mC) H)Dm am)WD WC5) 5W8C) 5)WD H8mD) WQm",
+"C) WmCQ!) DmZ) ZDam) WCp) pW8C) Z)pD ZpDs) v*C +*vC vD* g*vD 5*vC v*>C 5Dv*",
+" >*vD Q*vC v+Q*C vDZ* ZvDg* v*pC pv>*C pDZ* y*D ,b ,b& ,D c, ,b. ,8b ,D. c8",
+", ,bK bK,& ,DT cT, ,jb b8,j ,Dj sc, b* -b ,D* c- b*. -b8 ,.D* c-8 b*K -bK b",
+"T* c-T b*j -jb D*,j s-c ,bE b&,E ,Hb cH, bE,. ,Eb8 ,.bH ,Hc8 bK,E ,b&EK bH,",
+"T ,HcT ,Ebj &jE,b bH,j cHs, ,db -bd ,Dd gc- ,.bd b8-d ,.Dd g8c- ,Kbd bd-K b",
+"T,d -Tgc bd,j bd-j H*bj gcs- ,b2 b&,2 ,D2 c2, ,5b b5,8 ,5D c5, bK,2 ,b&2K ,",
+"2bT ,Tc2 b5,j ,5b&j b5,T c5s, ,;b -b; ,D; c-; b5* ->b 5D,; c>- ,Kb; b;-K bT",
+",; -Tc; b;,j >b-j 5Tb* c>s- bE,2 ,b&E2 ,2bH ,Hc2 ,Eb5 ,5b8E bH,5 ,Hc5 ,bE2K",
+" bK&,E2 ,HbT2 c2H,T ,5bjE ,5b&jE ,H5bT s,Hc5 bd,; bd-; bH,; c;g- b5,d -d>b ",
+"H5b* g-c> ,db;K -bd;K ,H;bT c-Tg; ,5dbj ->bdj ,H;bj s-gc> ,bN b&,N ,DN c,N ",
+"bN,. ,Nb8 DN,. ,8cN ,Qb ,bQ& ,QD cQ, bQ,j bQ,8 QD,j cQs, b*N -bN ,ND* c-N *",
+"Nb. b8-N ,D*N. -8cN bQ* -Qb QDb* c-Q Q*bj bQ-j ,QD*j cQs- ,Wb ,bW& ,WD cW, ",
+",.bW bW,8 ,.WD ,Wc8 bW,Q ,WbQ& Zb, Zc, bW,j ,W8bQ ,DZj s,Zc bW* -Wb H*bW c-",
+"W b.W* bW-8 ,WDd. c8-W bQ,d bW-Q Zb* Z-c W*bj bW-j b*Zj Zcs- ,mb ,bm& ,Dm c",
+"m, b5,m b8,m 5D,m ,5cm bQ,m ,Qbm& bT,m ,Qcm pb, ,8pb pD, cp, bm* -mb Dm,; c",
+"-m 5*bm >b-m ,5Dm* ->cm bQ,; bQ-m QD,; -Qcm pb* -pb ,Dp* cp- bW,m ,Wbm& bH,",
+"m ,Hcm b5,W ,5Wb8 5W,D ,5cW ,WbQm bWQ,m& ,DZm cmZ, ,Wpb pbW,8 pbZ, Z,cp vb*",
+" -vb vD, cv- ,5vb vb-> ,5vD -vc> ,Qvb vb-Q vbZ* cvZ- vbp* pb-v pbZ* yc- 0) ",
+"!0) )B0 a0) 1) 18) 1)B 1a) 0)K 0)!K T0) a0T) 1j) 8j1) 1T) s1) *0 +*0 *B0 a*",
+"0 1* 1+* 1*B 1a* *0K *0+K T*0 +0T* 1*j +j1* 1T* s*1 E0) E0!) H0) a0H) 1E) 8",
+"E1) 1H) 1)H8 0)EK !E)0K T0H) HTa0) jE1) 18jE) 1)Hj 1Hs) d*0 d*+0 H*0 g*0 1d",
+"* 8d1* 1H* g1* *0dK +d*0K H0T* T*g0 dj1* dj*1+ H*1T s*g1 0)2 0)!2 0)2B 0)a2",
+" 15) 581) 5B1) 1)5a 0)2K 0)2!K 0)T2 Ta0)2 5j1) 158j) 1)5T 15s) ;*0 ;*+0 ;0*",
+"B ;*a0 1;* >*1 *B1; 1a>* *0;K +;*0K ;*T0 a;*T0 ;j1* 1*>j 5T1* s1>* 0)E2 0)2",
+"!E 0)H2 Ha0)2 5E1) 158E) 1)H5 1H58) 0)2EK EK0!)2 HT0)2 Ta0H)2 15jE) 58j1E) ",
+"1H5T) s1H5) ;*d0 +d;*0 ;*H0 ;*g0 5d1* 1d>* H51* >*g1 dK;*0 dK;+*0 H;T*0 gT;",
+"*0 dj*1; >*1dj 1H;T* s*1g> 0)N 0)!N 0)NB 0)aN 1)N 8)1N )B1N a)1N Q0) !0Q) T",
+"0Q) a0Q) 1Q) 1)Q8 QT1) 1Qs) *0N *0+N 0B*N *0aN 1*N 1N8* 1N*B 1Na* Q*0 +0Q* ",
+"Q0T* Q0a* 1Q* +Q1* Q*1T 1Qs* W0) !0W) W0H) a0W) 1W) 1)W8 HW1) 1)Wa Q0W) Q!W",
+"0) Z0) a0Z) 1)Wj 1WQ8) Z1) s)Z1 W*0 +0W* H0W* W*g0 1W* +W1* H*1W 1Wg* W0Q* ",
+"+WQ*0 Z*0 g0Z* W*1Q 1+WQ* Z1* Z1s* m0) !0m) )Bm0 m0a) 1m) 1)8m m)1B 1)am m0",
+"Q) Q!m0) m0T) am0Q) p1) 18p) 1Tp) p1s) m*0 +0m* m0*B a0m* 1m* 1m>* *B1m am1",
+"* Q0m* m*0+Q T0m* am*Q0 p*1 p1>* 1Tp* s1p* m0W) W!m0) m0H) am0H) 1)5W 1W58)",
+" 1)Hm 1Hm8) WQm0) Wm0Q!) m0Z) Zam0) 1Wp) p1W8) p1Z) Zp1s) v*0 +*v0 H*v0 v*g",
+"0 v1* >*v1 1Hv* g*v1 Q*v0 v+Q*0 v*Z0 Zv*g0 v1p* pv>1* p*Z1 y*1 ,9 ,9& ,9B ,",
+"a9 ,1 :, ,1B :a, ,9K 9&,K ,T9 9T,a ,1j :j, ,1T s:, 9* -9 9*B -9a ,1* :- *B,",
+"1 :-a 9*K -9K 9T* -T9 9*j :-j 1T9* s-: ,9E 9&,E ,H9 9H,a ,1E :,E ,1H :H, 9E",
+",K ,9&EK 9H,T ,H9T& ,E9j ,j:E 9H,j :Hs, ,d9 -9d 9H* g-9 ,1d :-d 1H,d g:- ,K",
+"9d 9d-K 9T,d -Tg9 9d,j -j:d 1T,d s-g: ,92 9&,2 92,B ,29a ,15 :5, ,B95 ,5:a ",
+"92,K ,9&2K ,29T ,T9&2 95,j ,5:j 95,T :5s, ,;9 -9; *B9; 9a-; ,1; :-> *B95 :a",
+"-> ,K9; 9;-K 9T,; 9T-; 9;,j -j:> 1T,; :-s> 9E,2 ,9&E2 ,29H ,H9&2 ,E95 ,5:E ",
+"9H,5 ,H:5 ,9E2K 9&E,2K ,H9T2 9HT,a2 ,15jE :5j,E ,1H5T s,H:5 9d,; 9d-; 9H,; ",
+"-9g; 95,d ->:d 1H,; :-g> ,d9;K -9d;K ,H;9T -T9g; ,1d;j :->dj ,1HT; g:s-> ,9",
+"N 9&,N 9N,B ,N9a ,1N :,N 1N,B ,a:N ,Q9 ,9Q& 9Q,T 9Q,a ,1Q :Q, 1Q,T :Qs, 9*N",
+" -9N 9N*B 9a-N ,N1* :-N ,1*NB -a:N 9Q* -Q9 Q*9T 9Q-T 1Q9* :-Q ,1QT* :Qs- ,W",
+"9 ,9W& 9H,W 9W,a ,1W :W, 1H,W ,H:W 9W,Q ,W9Q& Z9, ,aZ9 9W,j ,W:Q Z1, Z:, 9W",
+"* -W9 H*9W -Wg9 1W,d :-W ,1HW* :Wg- 9Q,d 9W-Q Z9* Z-9 1Q,d -W:Q ,1Z* Z:- ,m",
+"9 ,9m& ,B9m 9a,m ,1m :m, ,B1m ,a:m 9Q,m ,Q9m& 9T,m ,Qa9m p9, :p, ,1pT s,:p ",
+"9m* -m9 *B9m 9a-m 1m,; :-m ,1m*B :a-m 9Q,; 9Q-m Tm9* 9T-m p9* -p: 9Tp* :ps-",
+" 9W,m ,W9m& 9H,m ,Hm9a 95,W ,5:W 1H,m ,H:m ,W9Qm 9WQ,m& ,mZ9 Z9a,m ,1pW p,:",
+"W p9Z, Z,:p v9* -v9 ,Hv9 g9-v v1, :v- ,1vH -vg: ,Qv9 v9-Q v9Z* Z9-v v9p* -p",
+":v p9Z* y:- C0) C0!) D0) a0D) 1C) 8C1) 1D) 1)D8 0)CK C0)!K T0D) DTa0) jC1) ",
+"18jC) 1)Dj 1Ds) *C0 *C+0 D*0 +0D* 1*C 1C8* 1D* +D1* CK*0 +*C0K D0T* a*0DT 1",
+"C*j *jC1+ D*1T 1Ds* E0C) C0)!E D0H) HDa0) CE1) 18CE) HD1) 1HD8) C0)EK EK)!C",
+"0 HDT0) DTaH0) 1jCE) 8jC1E) 1HDT) s1HD) *Cd0 +d*C0 H0D* D*g0 d*1C 1+d*C H*1",
+"D 1Dg* dK*C0 dK*+C0 H*DT0 gDT*0 dj*1C 1+d*jC 1H*Dj s*1gD 0)C2 C02!) 0)D2 Da",
+"0)2 5C1) 158C) 1)5D 1D58) C02)K 2K!C0) DT0)2 Ta0D)2 15jC) 58j1C) 1D5T) s15D",
+") *C;0 +;*C0 ;*D0 a;*D0 1C5* 1*>C 5D1* 1D>* ;*C0K ;*C+0K D;T*0 D;Ta*0 ;jC1*",
+" >*1jC 1D;T* >D*s1 C02E) !E)C02 HD0)2 Da0H)2 15CE) 58C1E) 1H5D) H5D1a) EKC0",
+")2 0)C2EK! DT0H)2 0)T2HDa 5jC1E) 5C1)8jE H5D1T) 1H5sD) d;*C0 d;*+C0 H;D*0 g",
+"D;*0 1d5*C >*1dC 1H;D* >D*g1 ;*CdK0 dK+*;C0 D;TH*0 D;Tg*0 1d5*jC dj*>C1 H;j",
+"1D* gs1>D* 0)CN C0N!) 0)DN Da0)N C)1N 18C)N D)1N 1D8)N C0Q) Q!C0) D0Q) QDa0",
+") QC1) 1Q8C) 1)QD s1QD) C0*N +*C0N *0DN a*0DN *C1N 1+*CN 1ND* 1+D*N *CQ0 +Q",
+"*C0 Q0D* +QD*0 1CQ* 1+Q*C QD1* s*1QD C0W) W!C0) D0W) WDa0) WC1) 1W8C) 1)WD ",
+"1WD8) WQC0) WC0Q!) D0Z) ZDa0) 1WQC) W8C1Q) 1DZ) Z1Ds) *CW0 +W*C0 W0D* gWD*0",
+" 1CW* 1+W*C WD1* g1DW* W*QC0 W*C+Q0 D*Z0 Z*Dg0 1W*QC *jC1+W 1DZ* Z1*gD C0m)",
+" mC0!) m0D) am0D) mC1) 1m8C) 1)Dm 1Dm8) QmC0) mC0Q!) QDm0) QD0am) 1Cp) p18C",
+") 1Dp) pD1s) *Cm0 m*C+0 D0m* am*D0 1Cm* >m1*C Dm1* >Dm1* m*CQ0 +QCm*0 QD;*0",
+" am0QD* 1*pC p>1*C 1Dp* p>D1* WmC0) mC0W!) HmD0) WD0am) 1W5C) W8C1m) 1HmD) ",
+"am)1WD QmCW0) QCW0m)! ZDm0) am0ZD) p1WC) 1W8pC) Zp1D) sZ1pD) *Cv0 v+*C0 D*v",
+"0 gvD*0 1*vC v>1*C 1Dv* gv1D* vQ*C0 +Q*vC0 ZvD*0 gvDZ*0 pv1*C v>1p*C Zp*1D ",
+"1Dy* ,b9 b9,& ,D9 c9, ,1b :b, ,1D :c, b9,K ,b9&K 9D,T ,Tc9 b1,j ,j:b b1,T :",
+"cs, b*9 -b9 9D* c-9 b1* :-b 1Db* :c- bK9* b9-K 9Tb* c9-T 9*bj :b-j 1Tb* :cs",
+"- b9,E ,b9&E 9H,D ,Hc9 ,Eb1 ,b:E b1,H cH:, ,b9EK b9&,EK ,H9bT c9H,T ,1bjE :",
+"bj,E ,1HbT s,H:c 9db* bd-9 9Hb* c-g9 b1,d -b:d 1Hb* :cg- ,db9K -b9dK ,Dd9T ",
+"c-9gT ,1dbj :-bdj ,1DTd g:sc- b9,2 ,b9&2 ,29D ,9c2 b1,5 ,5:b 95,D :,c5 ,b92",
+"K b9&,2K ,D9T2 c29,T ,1b5j :b5,j ,1D5T s,5:c 9;b* b;-9 9D,; -9c; b1,; >b:- ",
+"1D,; :-c> ,;b9K -b9;K ,D;9T c-9T; ,1;bj :->bj ,1DT; s-:c> ,b9E2 b9&,E2 ,H9b",
+"2 c29,H ,1b5E :b5,E ,1Hb5 :cH,5 b9E,2K b9,&EK2 bH9,T2 ,H9c2T b15,jE ,5b:jE ",
+"b1H,5T :cHs,5 ,db9; -b9d; ,H;9D c-9g; ,1db5 :->bd ,1Hb; g:c-> bd9,;K bd9-;K",
+" 9H;bT* -T9gc; b1d,;j ->b:dj b1H,T; s-cg:> b9,N ,b9&N ,N9D ,9cN ,Nb1 ,b:N ,",
+"N1D cN:, ,b9Q ,Qb9& 9Q,D ,Qc9 b1,Q ,Q:b 1Q,D :,cQ bN9* b9-N 9ND* -9cN bN1* ",
+"-b:N ,1D*N cN:- 9Qb* bQ-9 QD9* c9-Q 1Qb* :b-Q ,1QD* c-:Q ,b9W ,Wb9& 9W,D ,W",
+"c9 b1,W ,W:b 1W,D :,cW ,Wb9Q bW9,Q& ,DZ9 c9Z, ,1WbQ :Wb,Q ,1Zb :cZ, 9Wb* bW",
+"-9 WD9* c9-W 1Wb* :b-W ,1WDd c-:W ,Qdb9 -Wb9Q b*Z9 c-Z9 ,1Qbd :-WbQ b1Z* :c",
+"Z- ,b9m ,mb9& 9D,m ,mc9 b1,m ,m:b 1D,m :,cm ,Qb9m bQ9,m& ,QD9m cQ9,m ,1pb :",
+"bp, ,1pD p,:c 9mb* bm-9 Dm9* c9-m 1mb* :b-m ,1Dm* c-:m ,Q;b9 -Qb9m ,QD9; c-",
+"Q9m b1p* pb:- 9Dp* :c-p ,Wb9m bW9,m& ,Hm9D cW9,m ,1Wb5 :Wb,5 ,1Hbm :cW,5 bW",
+"9,Qm WQ9m,b& Zb9,m Zc9,m pb9,W :pb,W Zpb,1 cpZ:, b*v9 -bv9 ,Dv9 v9c- ,1vb v",
+"b:- ,1vD :c-v vb9,Q -vb9Q Zvb9* cvZ-9 pvb,1 :v-pb Zpb9* :cy- )L !)L )BL a)L",
+" )L. 8)L )L.B a)8L M) M)! TM) aM) Mj) 8M) MjT) sM) *L +*L *BL a*L *L. 8*L .",
+"B*L 8La* M* +M* T*M aM* M*j 8M* TM*j s*M E)L E)!L H)L a)HL )LE. E)8L )LH. 8",
+")HL ME) !EM) HM) H)aM jEM) ME8) MjH) HMs) d*L d*+L H*L g*L *Ld. d*8L *LH. 8",
+"*gL dM* +dM* HM* gM* M*dj dM8* M*Hj s*gM )L2 )L!2 )L2B )La2 5)L 8)5L )B5L a",
+")5L M)2 !)M2 M)T2 M2a) 5M) 5)8M TM5) 5Ms) ;*L ;*+L ;L*B ;*aL 5*L >*L 5L*B a",
+"*>L M;* +;M* M;T* M;a* 5M* >M* T*5M s*>M )LE2 !)2EL )LH2 Ha)L2 E)5L 58E)L 5",
+")HL H58)L E)M2 ME)!2 M)H2 aM)H2 ME5) 5M8E) H)5M sH5M) ;*dL +d;*L ;*HL ;*gL ",
+"d*5L d*>L HL5* g*>L d;M* dM;+* M;H* M;g* dM5* dM>* 5MH* >*gM )LN )L!N )LNB ",
+")LaN )LN. )L8N .BL)N 8a)LN QM) M)Q! TMQ) Q)aM MjQ) Q)8M QTMj) QMs) *LN *L+N",
+" NB*L *LaN N.*L *L8N *BLN. a*L8N Q*M Q*+M QTM* aMQ* QM*j 8MQ* M*jQT Q*sM W)",
+"L !)WL W)HL a)WL )LW. 8)WL HW)L. H8W)L WM) M)W! ZM) aMZ) MjW) W)8M MjZ) ZMs",
+") W*L +LW* HLW* W*gL *LW. WL8* H*WL. gW8*L WM* W*+M Z*M Z*gM M*Wj 8MW* M*Zj",
+" sMZ* m)L !)mL )BmL m)aL m)5L m)8L 5m)LB am)5L Mm) M!m) T)Mm a)Mm pM) 8Mp) ",
+"TMp) pMs) m*L +Lm* mL*B aLm* 5Lm* m*>L m*L5B >ma*L Mm* M*+m MmT* Mma* p*M p",
+"*>M T*pM sMp* m)WL W!m)L m)HL am)HL W)5L 5W8)L H5W)L H8m)L W)Mm Mm)W! MmZ) ",
+"aMmZ) WMp) pW8M) pMZ) ZpMs) v*L +*vL H*vL v*gL 5*vL v*>L vH5*L gv>*L vM* +M",
+"v* vMZ* g*vM vMp* >*vM ZMp* y*M ,L ,&L ,LB ,aL ,L. ,8L .B,L 8a,L ,M ,M& ,TM",
+" ,aM ,Mj ,8M TM,j s,M ,*L -L ,L*B -aL *L,. -8L *B,L. 8a-L ,M* -M T*,M -TM M",
+"*,j -M8 M*j,T s-M ,EL &E,L ,HL ,LH& EL,. 8E,L HL,. ,LH8 ,ME ,EM& ,HM HM,a M",
+"j,E ,E8M HM,j ,HsM ,dL -dL ,LH* g-L dL,. 8d-L ,HdL. -8gL ,dM -Md HM,d g-M d",
+"M,j 8d-M ,HMdj gMs- ,L2 &L,2 2B,L aL,2 ,5L ,L5& 5B,L ,L5a ,M2 ,2M& TM,2 ,2a",
+"M ,5M 5M,8 5T,M ,5sM ,;L -;L ;L,B a;-L ,L5* ->L ,5;LB -a>L ,M; -M; T;,M T;-",
+"M 5M,; >M- ,5TM; >Ms- EL,2 ,&EL2 HL,2 ,HaL2 5E,L ,58EL ,LH5 ,H58L ME,2 M&E,",
+"2 ,2HM ,HM&2 ,E5M ,5M8E H5,M s,H5M d;,L d;-L ,LH; -;gL ,L5d -d>L ,H5dL >Lg-",
+" dM,; dM-; HM,; g;-M 5d,M -d>M ,H5dM g->M ,LN &L,N NB,L aL,N N.,L 8L,N ,LN.",
+"B ,8aLN ,QM Q&,M QT,M Qa,M QM,j Q8,M ,QTMj ,QsM *L,N -LN *B,LN aL-N ,*LN. 8",
+"L-N ,LN*B. -8aLN Q*,M -QM ,QTM* Qa-M M*j,Q Q8-M ,QTM*j sQ-M ,WL ,LW& HW,L ,",
+"LWa WL,. ,LW8 ,HWL. ,H8WL ,WM W&,M Z,M ,aZM WM,j W8,M ,MZj sMZ, ,LW* -WL ,H",
+"WdL gL-W ,WdL. W8-L H*L,W. -W8gL WM,d -WM ,dZM Z-M ,WMdj W8-M Z*M,j -MsZ ,m",
+"L ,Lm& mL,B ,Lam 5m,L ,L8m ,5mLB ,5amL ,Mm M&,m Tm,M aM,m p,M ,8pM ,TpM sMp",
+", ,Lm* -mL m*L,B am-L m*L,5 >L-m ,5Lm*B ->amL Q;,M -Mm Mm*,T Tm-M ,Mp* -pM ",
+"p*T,M -Msp Wm,L m&L,W ,LHm ,HmaL ,L5W ,5W8L ,H5WL ,H8mL WM,m Mm&,W ,MZm Z&M",
+",m ,WpM p&W,M ZMp, Zp&,M v,L -vL ,HvL gL-v ,5vL >L-v v,H5L -vg>L vM, -vM vM",
+"Z, gM-v vMp, >M-v Zp*,M y-M U) U!) UD) Ua) U). U8) D)U. U)D8 UM) M)U! V) Va",
+") Uj) U)8M Vj) Vs) U* U+* U*D Ua* U*. U8* U.D* D8U* U*M +MU* V* V+* U*j +jU",
+"* V*j s*V UE) !EU) UH) HaU) E)U. 8EU) H)U. U)H8 MEU) U!ME) VH) HaV) jEU) U8",
+"ME) HjV) VHs) Ud* +dU* UH* gU* d*U. 8dU* U.H* U8g* dMU* dM*U+ Vd* gV* djU* ",
+"U+jd* H*Vj s*gV U)2 !)U2 D)U2 a)U2 U5) 58U) U)5D U)5a M)U2 U!M)2 V2) a)V2 U",
+")5M U58M) V5) s)V5 U;* +;U* D;U* a;U* U5* >U* 5DU* Ua>* M;U* M;*U+ V;* a;V*",
+" 5MU* U*>M V5* V>* E)U2 U!E)2 H)U2 UHa)2 5EU) U58E) U)H5 UH58) UME)2 ME)U!2",
+" H)V2 V2Ha) U5ME) 5MEU8) H5V) VsH5) d;U* U+d;* H;U* U;g* 5dU* Ud>* H5U* >*g",
+"U dM;U* U+dM;* H;V* g;V* U5dM* >MUd* H5V* V*g> U)N !)UN D)UN a)UN N.U) 8)UN",
+" UD)N. U8D)N UQ) U)Q! VQ) QaV) QjU) U)Q8 QjV) VQs) U*N +*UN UND* UNa* *NU. ",
+"UN8* U*DN. U8*DN UQ* +QU* V*Q +QV* Q*Uj Q8U* Q*Vj sQV* UW) W!U) U)WD U)Wa W",
+")U. U)W8 UHW). UH8W) U)WM UWQ!) VZ) VaZ) U)Wj UW8Q) VjZ) s)VZ UW* +WU* H*UW",
+" UWg* U.W* W8U* UH*W. gUW8* WMU* U+WQ* Z*V Z*gV W*Uj U+W*j ZjV* VZs* Um) m)",
+"U! U)Dm U)am 5mU) U)8m U5Dm) U5am) U)Mm Mm)U! Vm) amV) pU) U8p) Vp) s)Vp Um",
+"* +mU* DmU* amU* 5*Um Um>* U5*Dm >DmU* Q;U* Mm*U+ Vm* +mV* pU* >Up* Vp* s*V",
+"p WmU) UWm!) U)Hm UHma) U)5W U5W8) UH5W) UH8m) Mm)UW UW)Mm! Z)Vm VZam) UWp)",
+" pUW8) Z)Vp VpZs) vU* U+v* UHv* g*vU U5v* >*vU vUH5* gvU>* UQv* vU+Q* Vv* V",
+"*gv vUp* >MvU* Z*Vp yV* ,U ,U& ,UD cU, ,U. ,U8 UD,. ,Uc8 ,UM U&,M V, Vc, ,U",
+"j b8,M V,j s,V ,U* -U U*,D c-U ,.U* -U8 ,UD*. c8-U bM* -UM V*b V- U*,j -Uj ",
+",jV* V-s ,UE ,EU& ,UH ,UcH UE,. ,EU8 ,.UH UH,8 ,EbM M&E,U V,H cHV, ,EUj ,U8",
+"ME ,HVj sHV, ,Ud -Ud UH,d g-U ,.Ud U8-d ,UHd. g8-U bd,M bd-M Vd, V-g Ud,j U",
+"d-j ,dVj s-gV ,U2 ,2U& UD,2 ,Uc2 ,U5 U5,8 U5,D ,Uc5 ,2bM M&2,U V,2 c2V, b5,",
+"M ,U58M V5, V5s, ,U; -U; U;,D -Uc; U5,; ->U ,U5D; -Uc> bM,; bM-; V;, V-; U;",
+",j -U>M ,5V; V-> UE,2 ,U&E2 ,2UH c2U,H ,EU5 ,U58E UH,5 c5U,H ,UME2 ,UEM&2 ,",
+"HV2 VcH,2 ,U5ME M&E,U5 ,HV5 s,VH5 Ud,; Ud-; UH,; g;-U U5,d -d>U ,UH5d ->gU ",
+",UdM; -UdM; ,HV; V;g- ,U5dM >M-bd ,5Vd g-V> ,UN ,NU& UD,N ,UcN UN,. ,NU8 ,U",
+"DN. cU8,N ,UQ U&,Q V,Q V,cQ UQ,j UQ,8 ,QVj sQV, ,NU* -UN ,UD*N cN-U ,U*N. U",
+"8-N U*N,D. c-U8N UQb* -UQ ,QV* V-Q ,UQ*j UQ-j V*bQj -QVs ,UW U&,W UH,W ,UcW",
+" ,.UW UW,8 ,UHW. cWU,8 bW,M ,UWQ& Z,V VcZ, UW,j ,UWQ8 ZjV, VZs, UW,d -UW ,U",
+"HW* -UcW ,UWd. UW-8 ,U.WD* c-WU8 UQ,d bW-M VdZ, Z-V ,UWdj UW-j Zb*Vj sZV- ,",
+"Um U&,m Um,D ,Ucm U5,m U8,m ,U5Dm c5U,m bM,m Mm&,U Vm, V,cm pU, ,Up& Vp, s,",
+"Vp Um,; -Um ,UmD; -Ucm ,U5m* >U-m U5*,Dm c>-Um UQ,; bM-m ,QV; V-m ,Up* -pU ",
+"V*pb V-p UW,m ,UWm& UH,m cWU,m U5,W ,U5W8 ,UH5W c5W,U ,UWMm ,UWMm& VmZ, ZcV",
+",m ,UpW pU&,W Z,Vp cpZV, vU, -vU ,UvD gU-v ,Uv5 v>-U vU,H5 cv->U ,UvM vb-M ",
+"Vv, V-v vUp, pv-U V,pv yV- k) k)! k)B ak) 1k) 8k) k)1B 1)ak kM) M!k) Tk) T)",
+"ak l) l8) lT) ls) k* +k* k*B ak* 1*k 8k* 1k*B ak1* k*M k*+M Tk* T*+k l* l+*",
+" l*T ls* kE) !Ek) Hk) H)ak kE1) kE8) 1)Hk H)8k MEk) kME!) H)Tk ak)HM lE) 8E",
+"l) lH) sHl) dk* +dk* Hk* gk* dk1* dk8* Hk1* 1*gk k*dM dkM+* TkH* Tkg* ld* 8",
+"dl* lH* gl* k)2 !)k2 2Bk) k2a) 5k) 5)8k k)5B 5)ak M)k2 kM)!2 k)T2 ak)T2 l5)",
+" 58l) 5Tl) s5l) k;* +;k* *Bk; k;a* 5k* >k* *B5k ak>* M;k* k;M+* k;T* ak;T* ",
+"l;* l>* 5Tl* s>l* E)k2 kE)!2 k)H2 ak)H2 kE5) 5k8E) H)5k H5k8) kME)2 ME)k2! ",
+"HkT)2 Hk)aM2 5El) l58E) H5l) lsH5) d;k* dk;+* k;H* k;g* dk5* dk>* 5kH* >*gk",
+" dkM;* +kdM;* Hk;T* gkT;* 5dl* >*ld H5l* g>l* k)N !)kN )BkN k)aN k)1N kN8) ",
+"1k)NB ak)1N Qk) k)Q! Q)Tk Q)ak lQ) Q8l) QTl) sQl) k*N +Nk* kN*B aNk* 1Nk* k",
+"N8* k*N1B ak*1N Qk* Q*+k TkQ* akQ* l*Q +Ql* Q*lT lQs* Wk) k)W! H)Wk W)ak 1)",
+"Wk W)8k 1HWk) 1Wak) W)Qk WkQ!) Zk) akZ) lW) W8l) lZ) l)sZ Wk* W*+k WkH* Wkg",
+"* Wk1* 8kW* 1H*Wk g1Wk* QkW* +WkQ* Zk* Z*gk lW* +Wl* lZ* l*gZ km) k!m) m)kB",
+" a)km 1)km 8)km km)1B akm1) Q)km km)Q! T)km akmQ) lp) p8l) pTl) l)sp km* k*",
+"+m *Bkm kma* km1* km>* km*1B >kam* kmQ* km*+Q kmT* akmQ* l*p p>l* lTp* spl*",
+" W)km km)W! H)km akmH) 5)Wk 5Wk8) 1Hmk) H8km) km)WM Wk)Mm! kmZ) Zkam) pWl) ",
+"lWp8) l)Zp lZps) vk* +kv* Hkv* g*vk 1*vk >*vk v1Hk* >kgv* Qkv* vk+Q* vkZ* Z",
+"vkg* lv* v>l* Zpl* yl* ,k ,k& ,kB ,ak ,1k :k, 1k,B ,a:k ,kM k&,M ,Tk 9a,M l",
+", l:, l,T ls, ,k* -k *B,k -ka 1*,k :-k k*B,1 :a-k 9M* -kM Tk9* -Tk l*9 l- ,",
+"Tl* l-s ,kE ,Ek& ,Hk Hk,a 1k,E ,k:E 1H,k ,H:k ,E9M k&E,M 9H,M ,HkT& l,E :,l",
+"E lH, s,lH ,dk -kd Hk,d g-k 1d,k -k:d ,1Hdk :-gk 9d,M 9d-M HM9* -Tgk ld, l-",
+"d ,Hld gl- ,k2 ,2k& k2,B ,2ak ,5k ,5:k ,B5k 5a,k ,29M k&2,M ,2Tk ,Tk&2 l,5 ",
+":5l, ,5lT l5s, ,k; -k; ,Bk; ak-; 1;,k >k- ,1;kB -a>k 9M,; 9M-; Tk,; Tk-; l;",
+", l-> ,Tl; s-l> kE,2 k&E,2 ,2Hk ,Hk&2 ,E5k :5k,E H5,k :H5,k ,kME2 ,kEM&2 ,H",
+"kT2 ak2,HM ,5lE l:5,E ,Hl5 ls,H5 dk,; dk-; Hk,; g;-k 5d,k -d>k ,1Hk; g->k ,",
+"dkM; -kdM; ,HkT; -Tkg; ,5ld ->ld ,Hl; g-l> ,kN ,Nk& kN,B ,Nak 1k,N ,k:N ,1k",
+"NB :ak,N ,Qk Q&,k Qk,T Qa,k l,Q :Ql, ,QlT lQs, ,Nk* -kN k*N,B ak-N k*N,1 :N",
+"-k ,1Nk*B :-akN Qk9* -Qk ,QkT* Qa-k ,Ql* l-Q l*9QT -Qls ,Wk W&,k Hk,W Wa,k ",
+"1W,k ,W:k ,1HWk :HW,k 9W,M ,WkQ& Zk, ,aZk lW, :Wl, lZ, l,Z: Wk,d -Wk ,HkW* ",
+"-Wgk ,1Wdk -k:W 1H*,Wk g:-Wk WM9* 9W-M ,dZk Z-k ,Wld l-W Z9l* l-Z ,km k&,m ",
+",Bkm ak,m 1m,k ,k:m ,1mkB :ma,k 9M,m km&,Q Tk,m akm,Q l,p l,:p lTp, spl, km",
+",; -km km*,B ak-m km*,1 -k:m kmB,1; :-mak Qk,; 9M-m km*,T Tk-m p9l* l-p l;,",
+"pT ls-p Wk,m km&,W Hk,m akm,H 5W,k :W5,k ,1Hkm :Hm,k ,WkMm ,WkMm& ,kZm Zk&,",
+"m p,lW :pl,W Zpl, lZ,:p vk, -vk ,Hvk gk-v ,1vk >k-v v1,Hk :v-gk ,Qvk v9-M v",
+"kZ, Zk-v lv, l-v Zvl, yl- Uk) k)U! Dk) U)ak 1U) 1)U8 1)Dk 1)Ua kMU) U!kM) V",
+"k) akV) lU) U8l) Vl) l)Vs U*k +kU* Dk* D*+k 1U* U+1* U*1D Ua1* UkM* k*MU+ V",
+"*k +kV* l*U U+l* l*V Vls* kEU) U!kE) U)Hk ak)UH UE1) 1U8E) 1)UH 1UH8) UkME)",
+" kMEU!) HkV) VHak) UEl) lU8E) VHl) lsVH) dkU* dk*U+ HkU* U*gk Ud1* 1U+d* UH",
+"1* 1Ug* dkMU* U+dk*M HkV* V*gk Udl* l+Ud* Vdl* l*gV k)U2 U!k)2 k)D2 ak)U2 1",
+")U5 1U58) 5)Dk 1Ua5) UkM)2 kM)U!2 k)V2 V2ak) U5l) lU58) l)V5 lsV5) k;U* k;*",
+"U+ k;D* ak;U* U51* 1U>* Dk5* Dk>* k;MU* U+kM;* k;V* V+k;* U5l* >Ul* V5l* l*",
+"V> UkE)2 kE)U!2 UHk)2 UH)ak2 1U5E) 5kEU8) 1UH5) ak)UH5 kMEU)2 !)k2UME V2Hk)",
+" ak)V2H lU5E) U58lE) Vl5H) Vs5lH) dk;U* U+dk;* UH;k* gUk;* 1Ud5* >kUd* 1UH5",
+"* >kgU* UdkM;* dkU;+M* Vdk;* gVk;* ldU5* l>Ud* lH;V* V>lg* k)UN U!k)N k)DN ",
+"ak)UN U)1N 1U8)N 1UD)N 1Ua)N U)Qk UQk!) QkV) VQak) UQl) lUQ8) VQl) lsVQ) UN",
+"k* k*NU+ DNk* ak*UN 1NU* 1U+*N 1U*DN 1Ua*N QkU* U+Qk* QkV* V+Qk* UQl* l+UQ*",
+" lQV* s*VlQ U)Wk UWk!) W)Dk UWak) 1)UW 1UW8) 1UHW) 1UWa) UWQk) Wk)UQ! VkZ) ",
+"ZkVa) UWl) lWU8) l)VZ lZVs) WkU* U+Wk* DkW* gUWk* UW1* 1U+W* 1UHW* g1UW* UW",
+"*Qk +WkUQ* V*Zk gVZk* UWl* l+WU* VlZ* glZV* U)km km)U! D)km akmU) 1)Um 1Um8",
+") 1UmD) 1Uam) km)UQ UQ)km! kmV) Vmak) l)pU pUl8) l)Vp Vpls) kmU* km*U+ kmD*",
+" akmU* Um1* >kUm* km*1D >kDm* km*UQ U+Qkm* kmV* V+mk* pUl* l>pU* l*Vp V>lp*",
+" km)UW UW)km! UHmk) ak)UHm 1UW5) km)UW8 1UHm) ak)U5W UWQkm) W)QkUm! ZkVm) V",
+"maZk) lWpU) pU8lW) VplZ) lZsVp) U*vk vU+k* Dkv* gvUk* 1Uv* >kvU* v1UH* >kvD",
+"* vUQk* U+Qvk* vkV* Vvgk* vUl* lv>U* l*Vv l*yV t, t&, tD, tc, t1, t:, ,1tD ",
+"t,:c tM, ,Mt& Vt, V,tc lt, t:l, l,V u, t* t- t*D t-c t*1 t-: 1Dt* :ct- t*M ",
+"t-M t*V V-t lt* l-t Vlt* u- t,E ,&tE tH, cHt, ,1tE :,tE ,1tH t,:H ,MtE tM&,",
+"E V,tH tcV,H t,lE t:,lE tHl, uH, td* t-d tH* gt- ,1td :-td 1Ht* t-g: ,dtM -",
+"Mtd Vdt* V-gt tdl* ldt- tHl* ug- t,2 ,&t2 ,Dt2 c2t, t5, :5t, ,5tD t,c5 ,Mt2",
+" tM&,2 t,V2 tcV,2 t5l, t:5l, V5l, u5, t;* t-; ,Dt; c-t; t5* t>- 5Dt* c>t- ,",
+"Mt; -Mt; V;t* t;V- t5l* t>l- V5t* u-> ,Et2 t&,E2 ,Ht2 tcH,2 ,5tE t:5,E ,Ht5",
+" t:H,5 tM,E2 M&Et,2 tHV,2 Vc,tH2 t5,lE l:,t5E tH5l, ,Hu5 ,dt; -dt; ,Ht; t;g",
+"- ,5td ->td H5t* g-t> tdM,; t-dM; tH;V* V-gt; t5dl* l-t>d tH5l* g-u> t,N ,&",
+"tN ,DtN c,tN ,1tN :,tN t1D,N t:c,N tQ, ,Qt& V,tQ t,cQ tQl, t,:Q lQV, uQ, t*",
+"N t-N D*tN tNc- 1*tN tN:- t*1DN t-:cN tQ* t-Q V*tQ tQV- tQl* tQl- tQ*Vl u-Q",
+" tW, ,Wt& ,HtW t,cW ,1tW t,:W tH1,W t:H,W ,WtQ tWQ,& tZ, Z,tc tWl, t:Wl, l,",
+"tZ uZ, tW* t-W H*tW tWg- 1Wt* :-tW tH*1W t-Wg: ,Qtd -WtQ tZ* tZ- tWl* lWt- ",
+"l*tZ uZ- tm, ,mt& ,Dtm t,cm ,1tm t,:m t5D,m t:mc, ,Qtm tQm,& V,tm tcQ,m tp,",
+" p,t: l,Vp up, tm* t-m Dmt* c-tm 1mt* :-tm t5*Dm t-mc> ,Qt; -Qtm Vmt* tmV- ",
+"tp* tp- t*Vp up- ,Wtm tWm,& ,Htm tcW,m ,5tW t:W,5 tH5,W t:H,m tWQ,m Mm&tW, ",
+"Z,tm tZc,m p,tW tp:,W Z,tp Zpu, tv* tv- vDt* t-cv v1t* t-:v tv1,H gtv:- vMt",
+"* tQ-v t*Vv Z-tv l*tv tvl- l,Vv yu- F !F FB aF F. 8F .BF 8aF FK !KF TF TaF ",
+"jF 8jF TjF sF (F +F (BF +aF (F. +8F (F.B 8a+F (FK +FK T(F +TF j(F +jF j(TF ",
+"s+F G G! GH Ga G. G8 GH. G8H GK GK! GT GTa Gj G8j GTj sG Gd +G GHd gG Gd. +",
+"G8 HdG. gG8 GdK +GK GTd gGT Gjd +Gj TdGj gsG F2 !F2 2BF aF2 5F 58F 5BF 5aF ",
+"2KF !F2K TF2 T2aF 5jF 8j5F 5TF s5F ;F +;F ;FB a;F 5;F >F ;F5B >Fa ;FK ;F+K ",
+"T;F +FT; ;jF >jF 5FT; s>F G2 G2! GH2 Ga2 G5 G58 G5H G5a G2K 2KG! GT2 TaG2 G",
+"5j 58Gj G5T sG5 G; +G; G;H gG; G5d >G H5G; g>G G;K GK+; GT; GTg; G;j >Gj H;",
+"Gj s>G FN !FN NBF aFN N.F 8FN FBN. aN8F QF Q!F QTF QaF QjF Q8F TjQF sQF (FN",
+" +FN (FNB aF+N (FN. 8F+N .BN(F +8aFN Q(F +QF T(QF +FQa j(QF +FQ8 QTj(F +QsF",
+" GW W!G GHW GaW GW. G8W HWG. W8Ga GQ GQ! ZG ZGa GQj GQ8 ZGj sZG GWd +GW HWG",
+"d gGW WdG. G8+W GHWd. G8gW GQd +GQ ZGd gZG QdGj GQ+j GjZd sGgZ mF mF! mFB a",
+"mF 5mF 8mF mF5B 5Fam QmF mFQ! TmF QFam pF p8F pTF spF m;F +mF ;FmB +Fam m;5",
+"F >mF 5m;FB am>F Q;F +FQ; QFT; +FTm p;F p>F T;pF >Fsp Gm Gm! GmH Gam G5W G8",
+"m H5Gm H8Gm GQm Q!Gm ZGm GaZm pG pG8 ZpG spG vG v+G vGH gvG vG5 v>G G5vH >G",
+"gv vGQ +GvQ ZvG gGZv pvG p>G pGZv yG #F &F #BF a&F #F. 8&F #F.B a&8F #FK &F",
+"K T#F T&F j#F &jF j#TF s&F #(F +&F #(FB a&+F (F#. 8&+F #BF(. +8a&F (F#K &F+",
+"K #(TF +FT& #(jF +F&j Tj#(F +&sF G# G& GH# Ga& G#. G8& H#G. H8G& G#K G&K GT",
+"# GT& Gj# G&j G#Hj sG& Gd# +G& HdG# gG& d#G. 8dG& GHd#. G8g& dKG# GKd& G#Td",
+" GTg& G#dj G&+j dj#GT g&sG #F2 &F2 #F2B &2aF 5#F 5&F #B5F a&5F #F2K 2K&F #F",
+"T2 &FT2 j#5F 5F&j T#5F 5&sF ;#F ;&F #B;F aF;& ;#5F >&F 5;#FB a&>F #F;K &F;K",
+" ;#TF TF;& j#;F &j>F ;j#TF s&>F G#2 G&2 H#G2 G2H& G5# G5& G#H5 H5G& 2KG# &2",
+"GK T#G2 G2T& 5jG# 5&Gj G#5T G5s& G;# G;& G#H; G;g& G#5d >G& G5Hd# gG>& ;#GK",
+" GK;& G#T; T;G& G#;j G&>j G5Td# >&sG #FN &FN #FNB &FaN #FN. &F8N #FN.B 8a&F",
+"N Q#F Q&F T#QF QFT& j#QF QF&j QTj#F Q&sF (F#N &F+N #FN(B +a&FN #FN(. +8&FN ",
+"#BFN.( 8a&+FN #(QF +FQ& QT#(F +QT&F Qj#(F &jF+Q Tj#Q(F s+Q&F GW# G&W HWG# W",
+"aG& W#G. W8G& GHW#. G8HW& GQ# GQ& ZG# Z&G G#Wj W&Gj GjZ# Z&sG WdG# G&+W GHW",
+"d# G&gW GWd#. +GW8& HWdG#. gGW8& G#Qd G&+Q GdZ# gGZ& dj#GQ d&jGQ ZGdj# Z&Gg",
+"s m#F m&F #BmF aFm& m#5F 5Fm& 5m#FB am&5F m#QF QFm& m#TF TFm& p#F p&F T#pF ",
+"sFp& ;#mF +Fm& m;#FB am&+F 5m;#F m&>F m;#5BF >ma&F ;#QF QF;& Q;T#F +Tm&F ;#",
+"pF >Fp& pT;#F p>&sF Gm# Gm& G#Hm HmG& G#5W 5WG& G5HW# G5aW& QmG# Q&Gm GmZ# ",
+"GmZ& pG# pG& Z#pG pGZ& vG# v&G GHv# gGv& G5v# >Gv& vGH5# gv>G& GQv# GQv& vG",
+"Z# ZGv& vGp# v&pG ZpvG# y&G I I! DI aI I. 8I DI. D8I IK IK! TI TIa Ij 8Ij D",
+"jI sI I( +I DI( +DI I(. +I8 I(D. D8+I I(K +IK TI( +TI Ij( +Ij D(Ij sI+ GI G",
+"I! J Ja GI. G8I J. J8 GIK IKG! JT JTa GjI 8IGj Jj sJ Id +GI Jd gJ Id. 8Id J",
+"d. gJ8 IdK GK+I JTd gJT Idj Gj+I Jjd sJg I2 I2! DI2 aI2 5I 5I8 5DI 5aI I2K ",
+"2KI! TI2 I2Ta 5Ij 58Ij 5TI sI5 I; +I; D;I aI; 5I; >I D;5I >DI I;K +KI; TI; ",
+"T;+I I;j >Ij T;5I s>I GI2 I2G! J2 Ja2 G5I 5IG8 J5 J58 I2GK GI2!K JT2 TaJ2 5",
+"IGj G58Ij J5T sJ5 G;I G;+I J; gJ; 5Id >GI J5d J> GKI; IdK+; J;T gTJ; I;Gj G",
+"j>I J;j J>s IN IN! DIN aIN IN. 8IN IND. DN8I QI QI! QDI QaI QIj Q8I DjQI sI",
+"Q I(N +IN I(DN +NaI N.I( +N8I DI(N. +D8IN QI( +QI Q(TI QD+I Q(Ij Q8+I Ij(QD",
+" +QsI WI WI! JW JWa WI. W8I JW. J8W GQI Q!WI ZJ ZJa WIj Q8WI ZJj sJZ WId +W",
+"I JWd gJW W.Id W8+I WdJ. gWJ8 QId GQ+I ZJd gZJ IdWj WI+j ZdJj gZsJ Im Im! D",
+"mI aIm 5Im 8Im Dm5I 8IDm QIm Q!Im TIm aITm pI pI8 pDI spI Im; +Im ImD; Dm+I",
+" 5mI; >Im Im;5D Dm>I QI; QI+m D;QI TI+m pI; p>I D;pI p>sI GmI W!Im Jm Jma 5",
+"WI W85I J5W J8m QIGm Im!GQ ZJm ZaJm pGI G8pI Jp Jps vI vI+ Jv Jvg vI5 v>I J",
+"v5 J>v vIQ +QvI JvZ gZJv pvI v>pI Jpv yJ bI I& bDI cI bI. b8I DIb. c8I bKI ",
+"I&K bTI cTI bjI I&j TIbj scI bI( b+I DIb( c+I I(b. +Ib8 bDI(. +Ic8 I(bK bK+",
+"I b(TI +TcI b(Ij +Ibj Ij(bT c+sI bG bG& Jb cJ bG. bG8 Jb. cJ8 bGK bKG& JbT ",
+"cJT bGj G8bj Jjb sJc bGd b+G Jbd gJc b.Id +Gb8 bdJ. J8gc bKId bK+G bTJd gTc",
+"J Gjbd +Gbj bdJj gcsJ bI2 I&2 DIb2 c2I b5I 5I& bD5I c5I I2bK &2IK b2TI TIc2",
+" 5Ibj Ij5& 5IbT c5sI b;I I;& bDI; c;I 5Ib; >bI b5DI; c>I bKI; IK;& TIb; TIc",
+"; I;bj bj>I I;jbT sIc> bG2 b2G& Jb2 cJ2 bG5 G5b8 J5b cJ5 G2bK I&2GK bTJ2 JT",
+"c2 G5bj I&jG5 b5Jj c5sJ bG; +Gb; J;b cJ; G5bd >bG b5J; J>c bKG; I;&GK bTJ; ",
+"cTJ; G;bj bG>j b;Jj c>sJ bIN I&N DIbN cIN INb. bN8I bDIN. 8IcN bQI QI& QIbT",
+" cQI QIbj QIb8 bQDIj cQsI I(bN bN+I bDI(N +IcN bI(N. I&N+8 DI(bN. c+8IN b(Q",
+"I +IbQ bQDI( +QcI Ij(bQ I&j+Q bQDIj( sI+cQ bGW WI& JbW cJW b.WI G8bW bWJ. J",
+"8cW bGQ G&bQ ZJb ZcJ GQbj GQb8 JjZb ZcsJ WIbd +GbW bWJd cWgJ Id.bW b+GW8 Jb",
+"Wd. cJWg8 GQbd +GbQ JbZd gJZc IdjbW IdjW& ZJbdj sJZgc bmI Im& bDIm cmI 5Ibm",
+" 8Ibm b5DIm 5Icm QIbm ImQ& TIbm QIcm pbI pI& bTpI cpI Imb; +Ibm Im;bD +Icm ",
+"Im;b5 bm>I b5DIm; >Icm QIb; I;Q& bQ;TI QIc; b;pI >bpI pbDI; pIc> bGm G&bm J",
+"mb cJm G5bW G8bm b5Jm J5cW GQbm Im&GQ JmZb cmZJ pbG bGp& Jpb cpJ vbG vI& Jv",
+"b cvJ bGv5 >bvI vbJ5 J>cv bGvQ QIv& ZbJv JvZc vbpG vIp& pbJv yJc 0F !0F 0BF",
+" a0F 1F 18F 1FB 1aF 0FK 0F!K T0F a0TF 1jF 8j1F 1TF s1F 0(F +0F 0(FB a0+F 1(",
+"F 1+F (B1F +a1F (F0K 0F+K 0(TF T0+F j(1F 1F+j T(1F 1+sF G0 G0! GH0 Ga0 1G 1",
+"G8 1GH 1Ga G0K !KG0 GT0 TaG0 1Gj 18Gj 1GT sG1 Gd0 +G0 HdG0 gG0 1Gd 1+G GH1d",
+" g1G dKG0 GK+0 G0Td GTg0 Gj1d +j1G GT1d sGg1 0F2 0F!2 0F2B 0Fa2 15F 581F 5B",
+"1F 1F5a 0F2K 2K0!F 0FT2 Ta0F2 5j1F 158jF 1F5T 15sF ;0F ;0+F 0B;F ;0aF 1;F >",
+"F1 ;F1B 1a>F 0F;K +;0FK ;0TF a;0TF 1F;j 1j>F 1FT; s1>F G02 !0G2 H0G2 a0G2 1",
+"G5 15G8 G51H G51a 2KG0 G02!K T0G2 GTa02 15Gj 1G58j G51T 1Gs5 G;0 +0G; G0H; ",
+"G;g0 1G; >G1 G;1H >Gg1 ;0GK +G;0K G0T; gGT;0 Gj1; 1G>j GT1; s1>G 0FN 0F!N 0",
+"FNB 0FaN 1FN 8F1N NB1F aF1N Q0F !0QF T0QF a0QF 1QF 1FQ8 QT1F 1QsF (F0N 0F+N",
+" 0B(FN +a0FN (F1N +F1N 1(FNB 1+aFN 0(QF Q0+F QT0(F +QT0F Q(1F 1F+Q 1QT(F s1",
+"+QF GW0 G0W! HWG0 G0Wa 1GW G81W GH1W Ga1W GQ0 G0Q! ZG0 GaZ0 1GQ G81Q Z1G Z1",
+"sG WdG0 GW+0 GHWd0 GWg0 GW1d +G1W 1GHWd 1GgW G0Qd +0GQ GdZ0 ZGg0 GQ1d +G1Q ",
+"1GZd gGZ1 m0F !0mF 0BmF m0aF 1mF 1F8m mF1B 1Fam m0QF Q!m0F m0TF am0QF p1F 1",
+"8pF 1TpF p1sF ;0mF m0+F m;0FB am0+F m;1F 1m>F 1m;FB >m1aF ;0QF +Qm0F Q;T0F ",
+"+Tm0F 1;pF p1>F p1T;F p>1sF Gm0 m0G! G0Hm G0am 1Gm G81m Gm1H Ga1m QmG0 GQm!",
+"0 GmZ0 ZGam0 pG1 1Gp8 pGZ1 s1pG vG0 +Gv0 GHv0 vGg0 v1G >Gv1 1GvH gGv1 GQv0 ",
+"v+GQ0 vGZ0 ZvGg0 v1pG p1>G ZGv1 y1G 9F 9&F 9FB 9aF 91F :F 1B9F :aF 9FK &F9K",
+" 9TF 9FT& 9jF :jF 9F1T s:F 9(F 9+F (B9F +a9F 1(9F :+F 91(FB +a:F (F9K +F9K ",
+"T(9F 9F+T j(9F +j:F 9T1(F :+sF 9G 9G& 9GH 9Ga 9G1 :G 1G9H :GH 9GK 9KG& 9GT ",
+"GT9a 9Gj :Gj 1G9T s:G 9Gd 9+G GH9d g9G 1G9d :G+ 9G1Hd g:G Gd9K 9K+G GT9d 9G",
+"gT Gj9d +G:j 9GT1d sGg: 9F2 &F92 2B9F aF92 95F :5F 5B9F 5a:F 2K9F 9&F2K TF9",
+"2 9TaF2 5j9F 5j:F 9F5T :5sF 9;F 9F;& ;F9B 9Fa; 9F1; :>F 95;FB :a>F ;F9K ;&F",
+"9K 9FT; 9+T;F 9F;j :j>F 95T;F >Fs: 9G2 92G& GH92 92Ga 9G5 :G5 G59H G5:H G29",
+"K 9G&2K 92GT 9GT&2 G59j G5:j G59T s5:G 9G; +G9; G;9H 9Gg; 1G9; :>G 9G5H; :G",
+"g> 9KG; 9+G;K GT9; g9GT; G;9j >j:G 9G5Td :>sG 9FN &F9N NB9F aF9N 1F9N :FN 9",
+"1FNB aF:N 9QF 9FQ& QT9F 9FQa 9F1Q :QF 9Q1TF sF:Q (F9N +F9N 9(FNB 9+aFN 91(F",
+"N +F:N 1(F9NB :+aFN Q(9F 9F+Q 9QT(F 9+QTF 9Q1(F +Q:F 1Q(9TF :Q+sF 9GW G&9W ",
+"GH9W Ga9W 1G9W :GW 9G1HW Ga:W 9GQ G&9Q Z9G 9GZ& 1G9Q :GQ 9GZ1 Z:G GW9d +G9W",
+" 9GHWd 9GgW 9G1Wd +G:W 1GH9Wd gG:W GQ9d +G9Q 9GZd gGZ9 9GQ1d +G:Q Z91Gd :Gg",
+"Z 9mF 9Fm& mF9B 9Fam 9F1m :mF 95mFB am:F Qm9F m&F9Q 9FTm 9QamF p9F :pF 9TpF",
+" sF:p m;9F 9F+m 9m;FB 9+maF 95;mF >F:m 1mF9;B :>amF 9FQ; 9+QmF 9Q;TF 9+TmF ",
+"9;pF >F:p p9T;F :ps>F 9Gm G&9m Gm9H Ga9m 1G9m :Gm 9G5Hm Ga:m GQ9m 9GQm& 9GZ",
+"m Z9Gam p9G :pG pGZ9 sG:p v9G 9+vG 9GvH gGv9 9Gv1 :vG v91GH :Ggv 9GvQ v9+GQ",
+" ZGv9 Zv9gG v9pG pv:G Zp9vG y:G I0 I0! DI0 aI0 1I 1I8 1DI 1aI I0K !KI0 TI0 ",
+"T0aI 1Ij 18Ij 1TI sI1 I0( +I0 I0D( +0aI 1I( 1+I DI1( +D1I 0(IK I0+K I0T( +0",
+"TI 1(Ij +j1I 1(TI 1+sI GI0 I0G! J0 Ja0 1GI G81I J1 J18 I0GK GI0!K JT0 TaJ0 ",
+"Gj1I 1G8Ij J1T sJ1 Id0 +0Id Jd0 gJ0 1Id +G1I J1d gJ1 I0dK Id0+K TdJ0 JTg0 I",
+"j1d Idj1+ 1TJd g1sJ I02 !0I2 I2D0 I2a0 1I5 158I 5D1I 5a1I 2KI0 I02!K I2T0 T",
+"Ia02 15Ij 1I58j 5T1I 1Is5 I;0 +0I; D0I; a0I; 1I; >I1 D;1I 1D>I ;0IK I;0+K T",
+"0I; +TI;0 Ij1; 1I>j TI1; s1>I I0G2 GI0!2 J02 a0J2 G51I 1G58I J15 1aJ5 GI02K",
+" I02GK! T0J2 JTa02 1G5Ij G581Ij 1TJ5 s1J5 G0I; Id0+; J;0 g0J; G;1I 1G>I J1;",
+" J>1 Id0;K +G0I;K T;J0 gJT;0 Idj1; >I1Gj 1TJ; J1s> I0N !0IN I0DN I0aN 1IN 1",
+"N8I DI1N 1NaI QI0 I0Q! Q0TI Q0aI 1QI Q81I QD1I 1QsI 0(IN I0+N DI0(N +DI0N I",
+"(1N 1N+I 1DI(N 1+DIN I0Q( +0QI QDI0( +QDI0 1(QI +Q1I 1QDI( sI1+Q WI0 I0W! J",
+"W0 WaJ0 1WI W81I J1W 1WJ8 G0QI GQI!0 ZJ0 JaZ0 GQ1I 1GQ8I ZJ1 Z1sJ W0Id +0WI",
+" WdJ0 JWg0 WI1d +W1I 1WJd gWJ1 Q0Id +GQI0 JdZ0 g0ZJ QI1d 1+GQI ZdJ1 ZJg1 Im",
+"0 I!m0 D0Im a0Im 1Im 8I1m Dm1I aI1m Q0Im Im0Q! T0Im QaIm0 pI1 1Ip8 1DpI s1p",
+"I m;I0 +0Im Im;D0 +DmI0 Im1; 1I>m 1DmI; >Dm1I Q0I; +QIm0 QD;I0 +TIm0 1Ip; p",
+"1>I pD1I; p>D1I G0Im Im0W! Jm0 amJ0 Gm1I 1Gm8I J1m 1aJm Im0GQ GQ0Im! Z0Jm Z",
+"Jam0 1GpI pG81I Jp1 J1sp vI0 +Iv0 Jv0 g0Jv v1I >Iv1 Jv1 g1Jv QIv0 vI+Q0 Z0J",
+"v JvZg0 v1pI pvI>1 Z1Jv yJ1 9I 9I& 9DI c9I b1I :I 1D9I :cI 9IK 9KI& 9TI 9Tc",
+"I 9Ij :Ij 1T9I s:I 9I( 9+I DI9( 9+cI b(1I :I+ b1DI( c+:I I(9K 9K+I 9(TI +T9",
+"I 9(Ij +I:j b1TI( s+:I bG9 G&9I J9 cJ9 b1G :Gb J91 :J bK9G I&K9G J9T cTJ9 9",
+"Gbj bG:j J9j :Js 9Id 9+bG J9d gJ9 1Gbd :Id b1Jd :Jg 9KId b+G9K 9TJd gTJ9 Id",
+"9j Id:j 9dJj sJg: 9I2 92I& DI92 9Ic2 95I :I5 5D9I c5:I I29K I&29K 92TI c29T",
+"I 5I9j 5I:j 5T9I s5:I 9I; +I9; D;9I 9Ic; 1Ib; :>I b1;DI :Ic> 9KI; I;&9K TI9",
+"; c;9TI I;9j >j:I I;j9D :>sI b29G I&29G J92 c2J9 9Gb5 bG:5 J95 :J5 bG92K 9G",
+"2I&K 9TJ2 cJ9T2 b1G5j :Gb5j 95Jj J5s: 9Gb; I;&9G J9; J9c; 1Gb; >b:G b1J; :J",
+"> bG;9K I;K9+G 9TJ; cJ;9T Idj95 :>Gbj 9;Jj s:J> 9IN 9NI& DI9N 9IcN bN1I :IN",
+" b1DIN cN:I 9QI Q&9I QD9I 9QcI 1Q9I :QI b1QTI :QsI I(9N 9N+I 9DI(N c9+IN b1",
+"I(N +I:N 1D(9IN :c+IN 9(QI +Q9I 9QDI( cQ9+I b1QI( +Q:I Ij(9QD :cQ+I 9WI W&9",
+"I J9W J9cW 1GbW :WI b1JW :JW 9GbQ bGQ9& ZJ9 cJZ9 1GbQ bG:Q J9Z1 Z:J WI9d +W",
+"9I 9WJd gWJ9 b1GWd +W:I J91Wd :WgJ QI9d b+G9Q ZdJ9 ZJg9 Idj9W QI:d ZJ91d gZ",
+":J 9Im I&9m Dm9I 9Icm 1Ibm :Im b1mDI cm:I QI9m Im&9Q TI9m cQ9Im p9I :pI 9Dp",
+"I sI:p Im9; +I9m 9DmI; cm9+I b1mI; >I:m 1Dm9I; c>:Im QI9; I;&9Q 9QDI; cQ;9I",
+" 9Ip; p>:I p9DI; cp:>I 9Gbm Im&9G J9m J9cm 1Gbm bG:m b1Jm :Jm bGQ9m 9GQIm& ",
+"JmZ9 ZJ9cm b1pG pb:G Jp9 :Jp v9I 9+vI Jv9 g9Jv b1vI :vI vbJ1 :Jv 9QvI v9I+Q",
+" Z9Jv cvZJ9 v9pI pv:I pvJ9 yJ: FL !FL LBF aFL FL. 8FL FL.B aF8L MF MF! TMF ",
+"aMF MjF 8MF MjTF sMF (FL +FL (FLB aF+L FL(. 8F+L (BLF. +8aFL M(F +MF M(TF +",
+"FaM j(MF +F8M TMj(F +MsF GL GL! GHL GaL GL. G8L HLG. GLH8 GM GM! GTM GaM GM",
+"j G8M HMGj sGM GdL +GL HdGL gGL dLG. +LG8 GHdL. G8gL GMd +GM TdGM gMG dMGj ",
+"G8+M dMjGT sGgM FL2 FL!2 FL2B FLa2 5FL 8F5L LB5F aF5L MF2 !FM2 MFT2 M2aF 5M",
+"F 5F8M TM5F 5MsF ;FL ;F+L LB;F ;FaL ;F5L >FL 5;FLB aF>L M;F +FM; TFM; aFM; ",
+"5FM; >MF M;F5T sM>F GL2 !LG2 HLG2 aLG2 G5L 58GL GLH5 GL5a GM2 M2G! G2HM G2a",
+"M G5M 5MG8 H5GM G5sM G;L +LG; GLH; G;gL GL5d >GL G5HdL gG>L GM; G;+M HMG; G",
+"Mg; 5dGM >MG G5TdM sG>M FLN FL!N FLNB FLaN FLN. FL8N .BLFN 8aFLN QMF MFQ! T",
+"MQF QFaM MjQF QF8M QTMjF QMsF FL(N FL+N (BLFN +aFLN N.(FL +8FLN (BFN.L 8aF+",
+"LN M(QF QM+F QTM(F aMF+Q QMj(F +Q8MF TMjQ(F s+QMF GWL GLW! HWGL GLWa WLG. G",
+"LW8 GHWL. G8HWL GQM Q!GM ZGM GaZM WMGj W8GM GMZj ZGsM WdGL GW+L GHWdL GWgL ",
+"GWdL. +GW8L HWdGL. gGW8L QdGM GQ+M GMZd ZGgM dMjGQ +GQ8M ZGdMj gZsGM mFL !F",
+"mL LBmF mFaL mF5L mF8L 5mFLB amF5L MmF M!mF TFMm aFMm pMF 8MpF TMpF pMsF ;F",
+"mL mF+L m;FLB amF+L 5m;FL mF>L m;F5BL >maFL QFM; +FMm MmFT; aMm+F M;pF pM>F",
+" pTM;F >MpsF GmL mLG! GLHm GLam GL5W GL8m G5HWL G5aWL GMm G!Mm GMZm aMGm pG",
+"M G8pM ZMpG sMpG vGL +GvL GHvL vGgL G5vL vG>L vGH5L gv>GL vMG +GvM ZGvM gGv",
+"M vMpG pG>M ZpvGM yGM #FL &FL #FLB &FaL FL#. &F8L #L.FB 8a&FL M#F M&F M#TF ",
+"TFM& j#MF 8FM& TMj#F M&sF (F#L &F+L (BL#F +a&FL #L.(F +8&FL (BF#L. 8a&+FL #",
+"(MF +FM& TM#(F aMF+& Mj#(F M&F+j Mj#T(F s+M&F G#L G&L H#GL GLH& #LG. 8&GL G",
+"H#L. G8H&L GM# GM& G#HM HMG& MjG# 8MG& GTMj# GMs& d#GL +LG& GHd#L G&gL Gd#L",
+". d&LG8 Hd#GL. gG8&L G#dM G&+M dM#GT GMg& dMjG# dM&G8 GTMdj# gsGM& FL#2 FL&",
+"2 #L2FB a&FL2 #F5L &F5L 5B#FL 5a&FL #FM2 &FM2 TM#F2 aMF&2 M#5F 5FM& 5TM#F s",
+"5M&F #F;L &F;L ;#FLB a;&FL 5;#FL &F>L ;#F5BL >&aFL ;#MF MF;& M;#TF aM;&F M;",
+"#5F M&>F 5T#M;F >Ms&F #LG2 &LG2 GH#L2 Ga&L2 5#GL GL5& G5H#L G5a&L M#G2 G2M&",
+" GTM#2 GT&M2 G#5M 5MG& G5TM# sG5M& ;#GL GL;& G;H#L gG;&L G5d#L G&>L H5#G;L ",
+"g>G&L G#M; M;G& GT;M# gMG;& G5Md# GM>& dM#G5T >MgG& FL#N FL&N #LNFB a&FLN #",
+"LNF. 8&FLN .BL#FN a&F8LN M#QF QFM& QTM#F aMFQ& QMj#F M&FQ8 TMjQ#F sQM&F #LN",
+"(F +&FLN #FN(BL a&F+LN #(FN.L 8&F+LN (FLBN.# 8a+&FLN QM#(F M&F+Q TM#Q(F +QT",
+"M&F Mj#Q(F +Q8M&F #(TFQMj M&Fs+Q W#GL GLW& GHW#L GaW&L GW#L. G8W&L HW#GL. H",
+"8WG&L G#WM WMG& GMZ# GMZ& GQMj# GQ8M& ZGMj# Z&GsM GWd#L d&LGW HWdG#L gGW&L ",
+"Wd#GL. G8Wd&L WdG#HL. G8Wg&L dM#GQ dM&GQ ZGdM# Z&GgM GQMdj# GQ8dM& dMjZG# g",
+"sGZ&M #FmL &FmL m#FLB am&FL 5m#FL m&F5L m#F5BL 5aFm&L m#MF MFm& Mm#TF aMm&F",
+" M#pF M&pF pTM#F p&MsF m;#FL m&F+L ;#FmLB m&Fa;L m;#5FL >m&FL LBmF5;# am&>F",
+"L Mm#;F Mm&+F Tm#M;F aMFQ;& pM;#F >Mp&F M;#pTF p&F>Ms m#GL GLm& GmH#L Gam&L",
+" G5W#L G5&WL H5#GmL amLG5& G#Mm MmG& ZGMm# Z&GMm GMp# GMp& ZpGM# Zp&GM G#vL",
+" G&vL vGH#L gvG&L vG5#L v>G&L G5Hv#L v&Gg>L GMv# GMv& ZvGM# Zv&GM pvGM# >Mv",
+"G& pGMZv# GMy& UI U!I UDI UaI UI. U8I DIU. 8IUa IM IM! VI VaI UjI 8IM VIj s",
+"IV UI( U+I DIU( +IUa I(U. +IU8 UDI(. U+D8I IM( +IM VI( V+I U(Ij +IUj IjV( V",
+"+sI UG UG! JU JUa UG. UG8 JU. J8U UGM U!GM VJ VJa UGj G8Uj JjV sJV UGd U+G ",
+"JUd gJU U.Id +GU8 UdJ. J8gU IdM +MUG VJd gVJ GjUd +GUj VdJj sJgV UI2 I2U! D",
+"IU2 U2aI U5I 5IU8 UD5I 5IUa IM2 I!M2 V2I aIV2 5IM 8I5M V5I V5sI U;I +IU; UD",
+"I; aIU; 5IU; >UI U5DI; Ua>I IM; I;+M V;I +IV; I;Uj >MI 5IV; V>I UG2 G2U! JU",
+"2 UaJ2 UG5 G5U8 J5U U5J8 U2GM IM2G! VJ2 JaV2 G5Uj UG58M J5V VsJ5 UG; +GU; J",
+";U J;gU G5Ud >UG U5J; J>U GMU; IdM+; J;V J;gV G;Uj UG>M V5J; J>V UIN INU! D",
+"IUN UNaI INU. UN8I UDIN. U8IDN UQI Q!IM VQI QaVI QIUj QIU8 QIVj VQsI I(UN U",
+"N+I UDI(N U+DIN UI(N. U+8IN DI(UN. +DIU8N U(QI +IUQ QIV( +QVI IM(Qj U+Q8I V",
+"QIj( sIV+Q UGW U!WI JUW UWJa U.WI G8UW UWJ. UWJ8 UGQ Q!UG ZJV ZaVJ GQUj GQU",
+"8 VZJj VZsJ WIUd +GUW UWJd JUgW Id.UW U+GW8 JUWd. gJUW8 GQUd +GUQ VdZJ ZJgV",
+" IdMWj IdMW8 ZJVdj gVZsJ UmI U!Im UDIm aIUm 5IUm 8IUm U5DIm U5aIm IMm I!Mm ",
+"VmI aIVm pUI U8pI VpI sIVp ImU; +IUm Im;UD U+maI Im;U5 Um>I U5DIm; >DmUI QI",
+"U; IM+m QIV; +IVm U;pI pI>M pIV; pIV> UGm U!Gm JmU UaJm G5UW G8Um U5Jm U8Jm",
+" GQUm IMmW! JmV JaVm pUG UGp8 JpV VpsJ vUG U+vI JvU gUJv UGv5 >UvI vUJ5 vUJ",
+"> vIM +IvM VvJ JvgV vUpG vI>M VvJp yJV bUI U&I UDbI cUI UIb. 8IU& bUDI. U8c",
+"I bMI IM& VbI VcI IMbj 8IbM bjVI VcsI UIb( +IU& bUDI( U+cI bUI(. b+U8I UDIb",
+"(. cU+8I b(IM +IbM bIV( cIV+ IM(bj IM&+j VbIj( sIVc+ bGU UG& JbU cJU b.UG U",
+"Gb8 bUJ. cUJ8 bGM GMU& VJb cJV UGbj G8bM VbJj VJsc UGbd U+bG bdJU cJgU Id.b",
+"U b+GU8 JbUd. cJUg8 GMbd +GbM JbVd cJgV IdMbj IdMb8 JjVbd gVJsc UIb2 U2I& b",
+"UDI2 UIc2 bU5I 5IU& b5UDI U5cI b2IM I2M& bIV2 cIV2 5IbM IM5& b5VI cIV5 bUI;",
+" I;U& b;UDI U;cI b5UI; U&>I U5Db;I cU>I IMb; M;I& b;VI cIV; IM;b5 bM>I V5bI",
+"; >IVc b2UG U2G& bUJ2 JUc2 UGb5 G5U& b5JU cUJ5 b2GM IM&G2 JbV2 V2cJ G5bM IM",
+"&G5 JbV5 VJc5 UGb; G;U& b;JU cUJ; bG5Ud bG>U J5bUd >UcJ GMb; IdM;& JbV; VJc",
+"; IdMb5 bG>M J5Vbd cJV> UIbN UNI& bUDIN UIcN bUIN. I&NU8 UDIbN. cU8IN QIbM ",
+"QIU& bQVI VQcI bQUIj IM&Q8 VbQIj sIVcQ bUI(N I&NU+ UDIb(N cU+IN UI(bN. U+8I",
+"&N UDbIN.( U+8cIN IM(bQ IM&+Q VbQI( cQV+I bQUIj( U+QI&j Ij(VbQ cQVsI+ UGbW ",
+"G&UW bWJU JUcW bGUW. bG8UW JbUW. cJUW8 UGbQ GQU& VJZb VZcJ bGQUj IM&W8 ZJVb",
+"j sJZVc bGUWd b+GUW JbUWd cJUgW bWUId. U+GbW8 bWUJd. gJUcW8 IdMbW IdMW& ZJV",
+"bd gVZcJ bWMIdj bW8IdM JjVZbd sJZgVc bUIm ImU& bmUDI UmcI b5UIm Im&U5 U5Dbm",
+"I c5UIm IMbm MmI& bmVI cIVm bMpI U&pI VbpI pIVc Im;bU Im&U+ UmDb;I cmU+I b5",
+"UIm; >ImU& Imb;U5D c>UIm IMmb; IMmb+ VmbI; cQ;VI pbUI; >MbpI VpbI; cpV>I UG",
+"bm GmU& bmJU cUJm bG5UW bG8Um J5bUW cJ5UW GMbm IMmG& JbVm VJcm bGpU UGp& pb",
+"VJ cJVp bGvU UGv& JbvU vUcJ vbUG5 v>bUG JvbU5 cvJ>U bGvM IMv& vbVJ cJVv pvb",
+"UG >MvbG JpVvb cJyV kF kF! kFB akF 1kF 8kF kF1B 1Fak kMF M!kF TkF TFak lF l",
+"8F lTF lsF k(F +kF (BkF +Fak k(1F 1F+k 1k(FB akF1+ M(kF kM+F k(TF +FTk l(F ",
+"l+F T(lF sFl+ Gk Gk! GkH Gak 1Gk G8k Gk1H Gk1a GkM kMG! GTk TkGa lG lG8 lGH",
+" lsG Gkd +Gk GHdk gkG Gk1d +k1G 1GHdk 1Ggk dkGM Gk+M TdGk GTgk lGd l+G GTld",
+" glG kF2 !Fk2 2BkF k2aF 5kF 5F8k kF5B 5Fak MFk2 kMF!2 kFT2 akFT2 l5F 58lF 5",
+"TlF sFl5 k;F +Fk; ;FkB aFk; 1Fk; >kF k;F1B ak>F kFM; k;M+F TFk; ak;TF l;F l",
+">F T;lF >Fls Gk2 k2G! G2Hk G2ak G5k 5kG8 H5Gk 5aGk kMG2 GkM!2 G2Tk GTka2 lG",
+"5 G5l8 G5lH l5sG Gk; G;+k HkG; Gkg; Gk1; >kG 1G;Hk >Ggk k;GM +GkM; TkG; gkG",
+"T; lG; l>G GTl; g>lG kFN !FkN NBkF kFaN kF1N kN8F 1kFNB akF1N QkF kFQ! QFTk",
+" QFak lQF Q8lF QTlF sFlQ (FkN kF+N k(FNB akF+N 1k(FN 1+kFN k(F1NB 1+FakN k(",
+"QF +FQk QkT(F +QkTF Q(lF +QlF lQT(F ls+QF GkW W!Gk GHWk WaGk Gk1W W8Gk 1GHW",
+"k 1GaWk GQk Q!Gk ZkG GaZk lGW GQl8 lZG sZlG GWdk Gk+W GkHWd GkgW 1GWdk 1+GW",
+"k GkH1Wd g1GWk QdGk GQ+k GkZd gGZk GQld +GlW ZGld lGgZ kmF k!mF mFkB aFkm 1",
+"Fkm 8Fkm kmF1B akm1F QFkm kmFQ! TFkm akmQF lpF p8lF pTlF sFlp m;kF +Fkm km;",
+"FB akm+F km;1F km>F 1mFk;B >kamF QFk; +QkmF Qk;TF ak;QF p;lF >Flp l;pTF l>p",
+"sF Gkm G!km HkGm akGm Gk1m 8kGm 1GmHk akm1G QkGm GQkm! GkZm ZkGam lGp l8pG ",
+"ZplG splG vkG +Gvk GkvH gGvk 1Gvk >Gvk v1GHk >kgvG GQvk vk+GQ ZGvk ZvkgG lv",
+"G p>lG ZvlG ylG 9kF k&F kF9B 9Fak 1k9F :kF 91kFB ak:F 9MF 9FM& 9FTk 9FaM l9",
+"F l:F 9TlF sFl: k(9F 9F+k 9k(FB akF9+ 91k(F +k:F 1k(9FB :+akF M(9F 9F+M 9Tk",
+"(F 9+TkF 9(lF :+lF l9T(F ls:+F 9Gk Gk& Gk9H Gk9a 91Gk :Gk 9G1Hk Ga:k 9GM G&",
+"9M GT9M Ga9M lG9 l:G 9GlH s:lG Gk9d +k9G 9GHdk 9Ggk 9G1dk +G:k 1GH9dk :Ggk ",
+"GM9d +G9M 9GTdk 9GgM 9Gld :Gl+ lG9Td lGg: kF92 &Fk2 9kF2B akF92 9F5k 5k:F 9",
+"5kFB :5akF MF92 k&FM2 9TkF2 9aMF2 95lF :5lF l95TF ls:5F 9Fk; kF;& k;F9B ak;",
+"9F k;F95 :k>F 95Fk;B :>akF 9FM; k;&MF 9T;kF aM;9F 9;lF >Fl: l;9TF l>s:F 92G",
+"k G2k& 9GHk2 9Gak2 Gk95 G5:k 9G5Hk :GH5k 92GM 9GM&2 9GTk2 9GaM2 9Gl5 l5:G l",
+"G9H5 lsG:5 Gk9; k;G& 9G;Hk g9Gk; 9G5dk :G>k G5k9H; g:>Gk GM9; k;&GM 9GTk; g",
+"9MG; 9Gl; :>lG lG;9H l>Gg: kF9N &FkN 9kFNB akF9N 91kFN kF:N 1kF9NB :akFN 9F",
+"Qk QFk& 9QTkF 9QakF 9QlF lF:Q l9QTF :QFls 9k(FN k&F+N k(F9NB 9+FakN 1k(9FN ",
+":+kFN 1k9(NBF akF:+N 9Qk(F 9+QkF Qk(9TF akF9+Q l9Q(F :Q+lF 9QTl(F ls+:QF Gk",
+"9W WkG& 9GHWk 9GaWk 9G1Wk Gk:W 1GH9Wk :GHWk GQ9M QkG& 9GZk GkZ& 9GlW :GlW Z",
+"9lG lGZ: 9GWdk dk&GW GkH9Wd g9GWk 1GW9dk :G+Wk 91GkHWd g:GWk 9GQdk dk&GQ Z9",
+"Gdk Zk&gG lG9Qd :GQl+ lZ9Gd glZ:G 9Fkm kFm& kmF9B akm9F kmF95 km:F 95FkmB :",
+"makF 9FMm km&QF 9TmkF aMm9F lFp9 lF:p p9lTF :plsF km;9F km&+F 9mFk;B akF9+m",
+" 95;kmF :>mkF km1;9FB >ka:mF 9Q;kF k;&QF kmF9T; akF9Q; l;p9F l>p:F p9Tl;F :",
+"psl>F Gk9m kmG& 9GmHk akm9G 9G5Wk Gk:m G5k9Hm :GmHk GM9m km&GQ Z9Gkm Zk&Gm ",
+"p9lG lG:p Zp9lG :pGlZ 9Gvk Gkv& v9GHk gv9Gk v91Gk vk:G 9G5vkH :vGgk 9GvM v9",
+"M+G Zv9Gk ZvkG& v9lG lG:v lvZ9G l:yG Ik Ik! DkI aIk 1UI 8Ik Dk1I Ua1I IkM I",
+"!kM VIk aIVk lI lI8 lIV lsI Ik( +Ik D(Ik Dk+I 1(Ik U+1I Ik(1D 1U+aI kMI( Ik",
+"+M IkV( +IVk lI( l+I VIl( sIl+ UGk U!Gk Jk Jka 1UG U81G J1U J8k IkGM IkMG! ",
+"JkV VaJk lGU UGl8 lJ lJs Idk +kUG Jkd gJk UG1d U+1G 1UJd J1gU dkIM Idk+M Vd",
+"Jk JkgV lId U+lG lJd glJ Ik2 I!k2 I2Dk I2ak 5Ik 8I5k Dk5I aI5k kMI2 IkM!2 I",
+"kV2 V2aIk lI5 5Il8 V5lI l5sI Ik; I;+k IkD; Ika; U;1I >kI Ik;1D Dk>I k;IM Ik",
+";+M IkV; V+Ik; lI; l>I V;lI lIV> U2Gk Ik2G! Jk2 akJ2 U51G 1UG58 J5k 5aJk Ik",
+"MG2 Gk2IM! V2Jk JkVa2 UGl5 lGU58 lJ5 J5ls GkU; Idk+; Jk; J;gk UG1; 1U>G 1UJ",
+"; J>k IdkM; +GkIM; V;Jk gVJk; UGl; >UlG lJ; J>l IkN I!kN DNIk aNIk 1NIk IN8",
+"k IkN1D 1UaIN QIk Q!Ik QIVk aIQk lIQ Q8lI VQlI lQsI k(IN +NIk Ik(DN +DkIN I",
+"k(1N 1U+IN 1D(IkN akN1+I Q(Ik QI+k VQIk( V+QIk QIl( +QlI VlQI( lsI+Q WIk W!",
+"Ik JkW WaJk UG1W 8IWk 1UJW W8Jk GkUQ UGQk! ZJk ZaJk lWI W8lI lJZ lZsJ IdWk ",
+"WI+k WkJd gWJk Idk1W IdkW8 J1UWd gJ1UW IdQk Idk+Q ZdJk ZJgk WIld +WlI ZJld ",
+"gZlJ Ikm I!km IkDm Ikam Um1I Ik8m Ikm1D akm1I ImQk IkmQ! IkVm VmaIk lIp l8p",
+"I lIVp splI kmI; Ik+m IkmD; akm+I Ikm1; Ik>m 1DmIk; >kDIm IkQ; Ikm+Q VmIk; ",
+"V+mIk pIl; p>lI VplI; V>lpI GkUm IkmW! Jkm akJm UG1m IkmG8 1UJm 8kJm IkmGQ ",
+"Ik!GMm JmZk ZJkam pUlG lGpU8 Jpl lsJp vIk +Ivk Jvk gkJv 1UvI vI>k v1Jk >kJv",
+" QIvk vIk+Q ZkJv VvJgk lvI v>lI lvJ ylJ tI tI& tDI tcI t1I t:I 1DtI :Itc tI",
+"M IMt& VtI tIVc ltI l:I VtlI uI tI( t+I DIt( c+tI 1It( :It+ t1DI( t:c+I IMt",
+"( +ItM VIt( tIV+ tIl( t+lI ltVI( u+I tG tG& tJ tJc tG1 t:G tJ1 :Jt tGM GMt&",
+" tJV VJtc ltG t:lG lJt uJ tGd t+G tJd gtJ 1Gtd :Gt+ J1td :Jgt GMtd +GtM VJt",
+"d tJgV tGld t+lG ldtJ uJg tI2 I&t2 DIt2 c2tI t5I :It5 5DtI tIc5 IMt2 IM&t2 ",
+"tIV2 tcVI2 t5lI l5:I tIV5 u5I t;I +It; D;tI tIc; 1It; t>I t5DI; >Itc IMt; t",
+"+IM; tIV; tc;VI t;lI lIt> t5VI; u>I tG2 G&t2 tJ2 c2tJ tG5 :Gt5 tJ5 t5:J GMt",
+"2 tGM&2 V2tJ tJVc2 t5lG t:Gl5 t5lJ uJ5 tG; +Gt; tJ; t;gJ 1Gt; t>G J1t; t>J ",
+"GMt; t+GM; VJt; tJ;gV tGl; lGt> l;tJ uJ> tIN I&tN DItN cItN 1ItN tN:I t1DIN",
+" t:cIN tQI QIt& VQtI tIcQ tQlI :QlI tQVlI uQI I(tN +ItN tDI(N tc+IN t1I(N t",
+":+IN 1DIt(N :cIt+N QIt( +QtI tQVI( tcQ+I tQIl( t:Q+I Vl(tQI +QuI tGW G&tW t",
+"JW cJtW 1GtW :GtW J1tW tW:J tGQ GQt& tZJ ZctJ tGlW :GtQ lJtZ uZJ WItd +GtW ",
+"JWtd tWgJ tG1Wd t:G+W tJ1Wd gtJ:W GQtd +GtQ ZJtd gZtJ tGQld t:G+Q lJZtd gZu",
+"J tmI Imt& DmtI tIcm 1Itm :Itm t5DIm t:mcI QItm tQIm& tIVm tcQIm tpI lI:p p",
+"IVt upI Imt; +Itm tmDI; tcm+I t5Im; >Itm 1Dmt;I t>cIm QIt; t+QIm tQ;VI tcQI",
+"; pIt; pIt> tpVI; p>uI tGm Gmt& tJm cJtm 1Gtm :Gtm J1tm tm:J GQtm tGQm& ZJt",
+"m tJmZc tpG tG:p tpJ uJp tvG vIt+ tvJ tJcv v1tG tG:v t5Jv :Jtv vItQ tv+GQ t",
+"JVv cvVtJ lGtv lI:v Jptv yuJ e e! eB ae e. 8e e.B 8ea eK eK! Te Tea ej 8ej ",
+"Tej se e* +e *Be +ea e*. +e8 e.*B ae8* e*K +eK Te* +Te ej* +ej ejT* se+ Ge ",
+"Ge! He Gae Ge. G8e He. H8e GeK eKG! GTe TeGa Gje 8eGj Hej sGe f f+ fH gf f.",
+" f8 fH. gf8 fK f+K fT gfT fj f8j fTj sf e2 e2! e2B ae2 5e 5e8 5eB 5ae e2K 2",
+"Ke! Te2 T2ae 5ej 58ej 5Te se5 e; +e; e;B ae; 5e; >e *B5e >ea e;K +Ke; Te; T",
+";+e e;j >ej Te5* >es Ge2 e2G! He2 G2ae G5e 5eG8 H5e 5aHe e2GK Ge2!K G2Te ae",
+"2GT 5eGj G58ej 5THe G5se f; f+; fH; gf; f5 f> f5H f>g f;K +;fK fT; g;fT f5j",
+" f>j f5T sf> eN eN! eNB aeN eN. 8eN .BeN aN8e Qe Qe! QeT Qae Qej Q8e QTej s",
+"eQ e*N +eN eN*B +Nae *Ne. +N8e *BeN. aeN8* Qe* +Qe TeQ* Qa+e ejQ* Q8+e ej*Q",
+"T +Qse We We! HeW Wae We. W8e H.We W8He GQe Q!We Ze Zea Wej Q8We Zej sZe fW",
+" f+W fHW gfW fW. f8W HWf. gWf8 fQ fQ+ Zf Zfg fQj fQ8 Zfj sfZ em em! emB aem",
+" 5em 8em 5Bem ae8m Qem Q!em Tem aeTm pe pe8 peT spe em; +em *Bem ae+m em5* ",
+">em em;5B ae>m Qe; Qe+m TeQ; Te+m pe; >ep Tep* sp>e Gme W!em Hem aeGm 5We W",
+"85e 5WHe Wa5e QeGm em!GQ Zem aeZm pGe G8pe Zpe Zpse fv fv+ fvH gfv fv5 f>v ",
+"vHf5 gvf> fvQ v+fQ Zfv gvZf fp fp> fpZ yf ,e e& ,eB ,ae ,e. ,8e e.,B 8e,a ,",
+"eK e&K ,Te Te& ,je e&j Te,j se& ,e* -e ,e*B -ae e*,. -8e *Be,. 8e-a e*,K -e",
+"K ,eT* -Te ,e*j -je ej*,T s-e ,G ,G& ,GH ,Ga ,G. ,G8 ,.He G8,H ,GK ,KG& ,GT",
+" GT,a ,Gj G8,j GT,j sG, f, f- fH, gf- f,. f-8 ,Hf. f8g- f,K f-K fT, f-T fj,",
+" f-j ,Hfj sf- ,e2 e&2 e2,B ,2ae ,5e 5e& ,B5e 5e,a e2,K &2eK ,2Te T2e& 5e,j ",
+"ej5& 5e,T ,5se ,;e -e; ,Be; ae-; 5e,; >e- e;B,5 -a>e ,Ke; e;-K Te,; Te-; e;",
+",j -j>e e;j,T >es- ,G2 ,2G& ,2He ,2Ga ,G5 G5,8 G5,H G5,a G2,K e&2GK ,2GT ,G",
+"T&2 G5,j e&jG5 G5,T ,Gs5 f;, f-; ,Hf; g;f- f5, f>- ,Hf5 g-f> ,;fK fK-; ,Tf;",
+" f;-T ,5fj ->fj ,5fT f>s- ,eN e&N eN,B ,Nae eN,. ,N8e ,eN.B aeN,8 ,Qe Qe& Q",
+"e,T Qe,a Qe,j Qe,8 ,QTej ,Qse e*,N -eN *Be,N ae-N ,e*N. 8e-N ,eN*B. -8aeN ,",
+"eQ* -Qe ,QTe* Qa-e ej*,Q Q8-e ,QTej* -Qse ,GW We& He,W Ga,W ,.We G8,W ,GHW.",
+" ,G8Wa ,GQ G&,Q Ze, Ze& GQ,j GQ,8 ,GZj Zes, fW, f-W ,HfW -Wgf ,Wf. -Wf8 fHW",
+",. f-Wg8 fQ, f-Q Zf, Z-f ,Wfj -Wfj fjZ, Z-sf ,me em& ,Bem ae,m 5e,m 8e,m em",
+"B,5 aem,5 Qe,m emQ& Te,m emT& pe, pe& ,Tpe pes, em,; -me em;,B ae-m em;,5 -",
+"m>e ,5em*B >e-am Qe,; Qe-m ,Q;Te Te-m ,;pe -pe peT,; se-p ,Gm G&,m Gm,H Ga,",
+"m G5,W G8,m ,G5Hm em&H5 GQ,m em&GQ ,GZm emZ& pG, ,Gp& pGZ, pGs, fv, -vf fHv",
+", gf-v v,f5 -vf> fvH,5 f>g-v v,fQ fQ-v fvZ, -vZf fp, fp- Z,fp yf- Ie Ie! De",
+" Dea Ie. 8Ie De. D8e IeK I!eK DeT aITe Ije Ij8e Dej sIe I* +Ie De* +De I*. ",
+"8I* D.I* D8+e I*K +KI* TI* De+T I*j I*+j I*Dj sI* GIe IeG! Je Jae IeG. GI8e",
+" Je. J8e IeGK GIe!K JTe TeJa GIej IjeG8 Jje sJe fI f+I Jf gJf fI. f8I Jf. J",
+"f8 fIK +IfK JfT fTgJ fjI +Ifj Jfj sfJ Ie2 I!e2 De2 I2ae 5Ie 8I5e 5De D85e e",
+"2IK Ie2!K I2Te ae2TI Ij5e Ije58 De5T 5Dse I;e I;+e De; D;+e 5I* >eI De5* >e",
+"D IKe; I;e+K TeD; ae;TI Ij5* I*>j TI5* sI>e IeG2 GIe!2 Je2 aeJ2 GI5e G58Ie ",
+"J5e 5aJe GIe2K Ie2GK! TeJ2 JTae2 IjeG5 G58Ije 5TJe J5se fI; +If; Jf; J;gf f",
+"5I f>I Jf5 J>f I;fK f+I;K fTJ; JfTg; 5Ifj >Ifj f5Jj J>sf IeN I!eN DeN DNae ",
+"eNI. IN8e eND. DN8e QIe IeQ! QDe DeQa IjQe 8IQe DjQe QDse I*N +NI* DNI* +ND",
+"e *NI. IN8* I*ND. +De8N QI* QI+e DeQ* QD+e IjQ* 8IQ* I*jQD QIs* WIe IeW! JW",
+"e WaJe IeW. 8IWe WeJ. W8Je QIWe GQIe! ZJe JaZe IjWe GQ8Ie JjZe ZJse fWI +Wf",
+"I JfW gWJf WIf. W8fI fWJ. JWf8 fQI +QfI ZfJ gJZf WIfj Q8fI JjZf ZfsJ Ime I!",
+"em Dem aeDm Im5e Im8e Dm5e 8eDm ImQe ImeQ! DmQe aemQD pIe 8Ipe pDe pDse Im*",
+" Im+e ImD* De+m Im5* Im>e Im*5D De>m ImQ* Im*+Q DeQ; ae;QD pI* pI>e Dep* pD",
+">e ImWe ImeW! Jme aeJm WI5e G8mIe 5WJe 8eJm ImeGQ GQIem! JmZe ZJaem WIpe pG",
+"8Ie Jpe seJp fvI f+vI Jvf gfJv vIf5 vIf> fvJ5 f>Jv vIfQ fv+QI JvZf ZfJgv fp",
+"I pIf> Jpf yJf h h& hD hc h. h8 hD. hc8 hK h&K hT hcT hj h8j hTj hs h* h- h",
+"D* hc- h*. h-8 D*h. c-h8 h*K h-K hT* h-T hj* h-j D*hj hs- hG hG& hJ hJc hG.",
+" h8G hJ. hJ8 hGK G&hK hJT cJhT hjG G8hj hJj hsJ hf hf- hJf i hf. hf8 h.Jf i",
+"8 hfK hKf- hfT iT hfj f-hj Jfhj is h2 h&2 hD2 hc2 h5 h58 h5D hc5 h2K &2hK h",
+"T2 c2hT h5j 5&hj h5T hs5 h; h-; h;D hc; h5; h> 5Dh; h>c h;K -;hK hT; c;hT h",
+";j h>j 5Th; hs> hG2 G&h2 hJ2 h2cJ h5G G5h8 hJ5 cJh5 G2hK hG&2K JTh2 cJTh2 G",
+"5hj h5G&j J5hT h5sJ hf; f-h; hJ; i; hf5 h>f Jfh5 i> f;hK f-;hK J;hT iT; f5h",
+"j hjf> J;hj is> hN h&N hDN hcN hN. h8N DNh. c8hN hQ hQ& hQD hcQ hQj hQ8 QDh",
+"j hsQ h*N h-N D*hN hNc- *Nh. -8hN hD*N. c-8hN hQ* h-Q QDh* c-hQ Q*hj -Qh8 h",
+"QD*j hQs- hW hW& hJW hcW hW. hW8 JWh. cWh8 hWQ GQh& hZ hZc hWj GQh8 hZj hZs",
+" hfW h-W JfhW iW fWh. f8hW JfWh. iW8 hfQ f-hQ hZf iZ fQhj fQh8 hjZf iZs hm ",
+"hm& hmD hcm h5m h8m 5Dhm c5hm hQm Q&hm hTm cQhm hp hp8 hpD hps hm; h-m Dmh;",
+" c-hm 5*hm h>m h5Dm* hmc> hQ; -Qhm QDh; cQh; hp; hp- pDh; cph> hWm Gmh& hJm",
+" cJhm h5W G8hm J5hW c5hW GQhm hWQm& hZm hmZc hpG pGh8 hZp cphZ hv hv- hvJ i",
+"v hv5 hv> h5Jv iv> hvQ hQ-v hZv iZv hpf fph> Jphv yi e0 e0! e0B ae0 1e 1e8 ",
+"1eB 1ae e0K !Ke0 Te0 T0ae 1ej 18ej 1Te se1 e*0 +e0 e0*B +0ae 1e* 1+e *B1e +",
+"e1a *0eK e0+K e*T0 +0Te ej1* +j1e Te1* 1+se Ge0 e0G! He0 G0ae 1Ge G81e 1He ",
+"Ga1e e0GK Ge0!K G0Te ae0GT Gj1e 1G8ej GT1e 1Gse f0 f+0 fH0 gf0 f1 f1+ f1H g",
+"f1 f0K +0fK fT0 g0fT f1j 1+fj f1T sf1 e02 !0e2 2Be0 e2a0 1e5 158e 1B5e 5a1e",
+" 2Ke0 e02!K e0T2 ae0T2 15ej 1e58j 5T1e 1es5 e;0 +0e; ;0eB a0e; 1e; >e1 1Be;",
+" 1a>e ;0eK e;0+K T0e; ae;T0 ej1; 1e>j Te1; s1>e e0G2 Ge0!2 e0H2 ae0G2 G51e ",
+"1G58e H51e 1Ga5e Ge02K e02GK! GTe02 GT0ae2 1G5ej G581ej 1GT5e se1G5 f;0 +;f",
+"0 H;f0 f;g0 f15 f>1 1Hf5 g1f> ;0fK f+;0K T;f0 fT;g0 1;fj >jf1 1Tf5 f1s> e0N",
+" !0eN 0BeN e0aN 1eN 1N8e eN1B 1Nae Qe0 e0Q! Q0Te Q0ae 1Qe Q81e Qe1T 1Qse *0",
+"eN e0+N *Be0N ae0+N e*1N 1N+e 1e*NB 1+eaN e*Q0 +0Qe QeT*0 +QeT0 Qe1* +Q1e 1",
+"QeT* se1+Q We0 e0W! H0We W0ae 1We W81e He1W Wa1e G0Qe GQe!0 Ze0 aeZ0 GQ1e 1",
+"GQ8e Z1e Z1se fW0 +Wf0 HWf0 fWg0 f1W 1+fW 1HfW gWf1 fQ0 +Qf0 Zf0 g0Zf f1Q 1",
+"+fQ Zf1 g1Zf em0 e!m0 m0eB a0em 1em 8e1m 1Bem ae1m Q0em em0Q! T0em aemQ0 pe",
+"1 1ep8 1Tpe s1pe e0m* +0em em;0B aem+0 em1; 1e>m 1em*B >e1am Q0e; +Qem0 Qe;",
+"T0 ae;Q0 1ep* p1>e pe1T; >eps1 G0em em0W! H0em aemG0 Gm1e 1Gm8e He1m aem1G ",
+"em0GQ GQ0em! emZ0 Zeam0 1Gpe pG81e peZ1 Zpes1 fv0 v+f0 vHf0 g0fv fv1 v>f1 f",
+"Hv1 fvg1 vQf0 fv+Q0 Z0fv Zfgv0 fp1 p>f1 Z1fp yf1 9e 9e& 9eB 9ae ,1e :e ,B1e",
+" :ea 9eK 9Ke& 9Te Te9a 9ej :ej 1T9e s:e 9e* -9e *B9e 9a-e 1e9* :-e ,1e*B -a",
+":e e*9K 9e-K Te9* 9T-e ej9* -j:e ,1Te* :-se ,G9 G&9e 9He 9G,a ,1G :Ge 1G,H ",
+":He ,K9G e&K9G 9G,T ,GT9a 9G,j ,G:j 1G,T :Gse f9 f-9 f9H gf9 f91 :f ,1fH :f",
+"g f9K fK-9 f9T fTg9 f9j :fj ,1fT sf: 9e2 92e& e29B 92ae 95e :e5 9B5e 5a:e e",
+"29K e&29K 92Te 9Te&2 5e9j 5e:j 5T9e s5:e 9e; 9e-; 9Be; ae9; 1e,; >e: ,1;eB ",
+":a>e 9Ke; -9e;K Te9; -T9e; e;9j >j:e e;j9T s:>e ,29G e&29G 92He ,Ga92 9G,5 ",
+",G:5 H59e H5:e ,G92K 9G2e&K ,GT92 ae29GT ,1G5j :G5,j ,1G5T :Hes5 f9; -9f; 9",
+"Hf; g;f9 f95 :f> 9Hf5 f>g: 9;fK f-9;K 9Tf; f-T9; 95fj fj:> 95fT s:f> 9eN 9N",
+"e& eN9B 9Nae ,N1e :eN ,1eNB ae:N 9Qe Q&9e Qe9T Qa9e 1Q9e :Qe ,1QTe :Qse e*9",
+"N 9e-N 9e*NB -9aeN ,1e*N -e:N 1eN9*B :-aeN Qe9* 9Q-e 9QeT* -Q9Te ,1Qe* -Q:e",
+" 1Qe9T* s-:Qe 9We W&9e He9W Wa9e 1G,W :We ,1GHW He:W 9G,Q ,GQ9& Z9e 9aZe 1G",
+",Q ,G:Q ,1Ze Z:e f9W -Wf9 9HfW gWf9 ,1fW :fW f91HW :Wgf f9Q -Qf9 Zf9 g9Zf ,",
+"1fQ :fQ f9Z1 Z:f 9em e&9m 9Bem ae9m 1e,m :em ,1meB ae:m Qe9m em&9Q Te9m aem",
+"9Q p9e :pe 9Tpe se:p em9; 9e-m 9em*B -m9ae ,1me; :m>e emB,1; :-mae Qe9; -Q9",
+"em 9QeT; -Tm9e 9ep* >e:p p9eT; -ps:e 9G,m em&9G He9m aem9G 1G,m ,G:m ,1GHm ",
+"He:m ,GQ9m 9GQem& 9eZm Z9eam ,1pG pG:e p9Ze Ze:p fv9 f9-v fHv9 fvg9 v9f1 :f",
+"v fv91H gf:v v9fQ -vf9Q fvZ9 Zf9-v fp9 :fp Z9fp y:f Ie0 I!e0 De0 D0ae 1Ie 8",
+"I1e 1De D81e e0IK Ie0!K D0Te ae0TI Ij1e Ije18 De1T 1Dse I*0 +0I* D0I* +0De ",
+"1I* +I1e De1* +D1e *0IK I*0+K T0I* +DeT0 Ij1* I*j1+ TI1* 1Is* IeG0 GIe!0 Je",
+"0 aeJ0 GI1e 1G8Ie J1e 1aJe GIe0K Ie0GK! TeJ0 JTae0 Ije1G 1G8Ije 1TJe J1se f",
+"I0 +If0 Jf0 g0Jf f1I 1+fI Jf1 Jfg1 I0fK f+I0K J0fT JfTg0 1Ifj f1+Ij f1Jj J1",
+"sf e0I2 Ie0!2 e0D2 ae0I2 5I1e 1I58e 5D1e 1De5a Ie02K e02IK! DeT02 TI0ae2 Ij",
+"e15 5I81ej 1De5T sI15e I0e; I;e+0 D0e; ae;D0 5I1* 1I>e De1; 1D>e I;e0K +I0e",
+";K De;T0 ae0TI; I;j1e >I1ej e;j1D sI*>1 GIe02 Ie0G2! e0J2 Jae02 1G5Ie G581I",
+"e 1eJ5 J158e Ie0G2K !0I2GeK JTe02 ae0JT2 1G5Ije 8eGj1I5 J15Te sJ15e I;f0 f+",
+"I;0 f;J0 Jf;g0 1If5 >If1 f1J5 J1f> fI;0K I;0f+K JfT;0 fT;gJ0 f15Ij f>1Ij Jf",
+"15T J>sf1 e0IN Ie0!N e0DN ae0DN Ie1N 1I8eN 1NDe 1DeaN IeQ0 QIe!0 Q0De QDea0",
+" QI1e 1QI8e QD1e sI1Qe *0IN I*0+N I*0DN +De0N 1NI* 1+IeN 1De*N 1+DeN Q0I* +",
+"QIe0 QDe*0 +QDe0 QI1* 1+QI* 1QDI* sI*1Q IeW0 WIe!0 WeJ0 JWae0 WI1e 1WI8e 1W",
+"Je J1W8e GQIe0 QI0We! JeZ0 ZJae0 1GQIe W8I1Qe J1Ze sJZ1e WIf0 f+WI0 fWJ0 Jf",
+"Wg0 1WfI f1+WI JWf1 Jf1gW QIf0 fQ+I0 Z0Jf ZfJg0 1QfI f1Q+I JfZ1 Zf1sJ I0em ",
+"Ime!0 D0em aemD0 Im1e 1Im8e De1m aem1D ImeQ0 QI0em! QDem0 ae0TIm 1Ipe pI81e",
+" 1Dpe pDes1 I0m* Im*+0 Im*D0 am*I0 Im1* >I1em Im*1D >eD1m Im*Q0 Im0+Qe Im*T",
+"0 ae0QD; 1Ip* >ep1I pDe1; sI*p1 ImeG0 WI0em! emJ0 Jmae0 1GmIe W8I1em 1eJm J",
+"1m8e GQIem0 ImQeW!0 ZJem0 JmaZe0 pG1Ie 1WIpe8 peJ1 Jps1e f0vI fv+I0 J0fv Jv",
+"gf0 vIf1 f>v1I fvJ1 J>fv1 fvQI0 vI+fQ0 ZfJv0 JvgZf0 pIf1 fp>1I J1fp Jfy1 h9",
+" h9& h9D hc9 h1 h: h1D h:c h9K 9&hK hT9 c9hT h1j h:j h1T hs: h9* h-9 9Dh* h",
+"9c- h1* h:- 1Dh* :ch- 9*hK -9hK 9Th* h9-T 9*hj :-hj 1Th* s-h: h9G 9Gh& hJ9 ",
+"J9hc h1G h:G hJ1 :Jh 9GhK h9G&K J9hT cJ9hT 9Ghj :Ghj J9hj :Jhs hf9 f9h- Jf9",
+" i9 hf1 :fh Jfh1 i: hKf9 f-9hK f9hT i9T f9hj hj:f f9Jj is: h92 9&h2 9Dh2 c2",
+"h9 h15 h:5 95hD :ch5 92hK h9&2K 9Th2 hc9T2 95hj :5hj 95hT s:h5 h;9 -9h; 9Dh",
+"; h9c; h1; h>: 1Dh; c>h: 9;hK h-9;K 9Th; hc;9T 9;hj :>hj 1Th; s:h> 9Gh2 h9G",
+"&2 h2J9 cJ9h2 9Gh5 :Gh5 J9h5 h5:J h9G2K 9G&h2K J9Th2 hcTJ92 h1G5j h:G5j J95",
+"hT hsJ:5 f9h; f-9h; J9h; i9; f9h5 :fh> J1h; i:> f9;hK h-;f9K Jf9T; 9Ti; f95",
+"hj h>:fj Jf95T s:i> h9N 9&hN 9DhN c9hN h1N h:N 1DhN hN:c hQ9 9Qh& 9QhT h9cQ",
+" h1Q h:Q 1QhT s:hQ 9*hN -9hN h9D*N c-9hN 1*hN hN:- h1D*N h:c-N 9Qh* h9-Q hQ",
+"9D* c-Qh9 1Qh* :-hQ h1QD* h:Qs- hW9 9Wh& J9hW h9cW h1W h:W J1hW hW:J 9GhQ h",
+"W9Q& hZ9 Z9hc 9Whj :GhQ hZ1 hZ: f9hW h9-W JWf9 i9W f1hW hW:f Jf91W i:W f9hQ",
+" f-Qh9 Z9hf iZ9 f1hQ hQ:f h1Zf iZ: hm9 9mh& 9Dhm h9cm h1m h:m 1Dhm :chm 9Qh",
+"m hQ9m& 9Thm hcQ9m hp9 hp: p9hT h:cp 9mh; h9-m hm9D; c-mh9 1mh; :-hm h1mD; ",
+"h:mc> 9Qh; h-Q9m hQ;9D cQ;h9 p9h; h:-p hp9D; cp-h: 9Ghm hW9m& J9hm cJmh9 95",
+"hW :Ghm J1hm hm:J hW9Qm 9GQhm& Z9hm hZc9m p9hW hW:p h1Jp Z:hp hv9 v9h- J9hv",
+" iv9 hv1 hv: h1Jv i:v v9hQ hv-9Q Z9hv Zvi9 h1fp :fhp Zvh1 yi: eL eL! eLB ae",
+"L eL. 8eL .BeL 8Lae Me Me! TeM aMe Mej 8Me TMej seM e*L +eL eL*B +Lae *Le. ",
+"+L8e *BeL. aeL8* Me* +Me MeT* Te+M ejM* 8M+e Me*Tj +Mse GeL eLG! HeL GLae e",
+"LG. GL8e eLH. HL8e GMe G!Me HMe aMHe MeGj 8eGM MeHj GMse fL f+L fHL gfL fL.",
+" f8L HLf. gLf8 fM fM+ fTM gfM fMj f8M HMfj sfM eL2 !Le2 2BeL e2aL 5eL 5L8e ",
+"eL5B 5Lae Me2 M!e2 T2Me M2ae 5Me 8M5e Te5M 5Mse e;L +Le; ;LeB aLe; 5Le; >eL",
+" e;L5B ae>L Me; M;+e MeT; Mea; Me5* >Me Me;5T se>M eLG2 GeL!2 eLH2 aeLG2 GL",
+"5e G58eL HL5e G5aeL G2Me Me2G! H2Me aMeG2 5eGM G5M8e 5MHe se5GM f;L +;fL H;",
+"fL f;gL f5L f>L H5fL >Lgf fM; +Mf; HMf; g;fM f5M f>M H5fM >Msf eLN !LeN NBe",
+"L eLaN N.eL eN8L eLN.B aeL8N QeM Q!Me QTMe aMQe QMej 8MQe MejQT QesM *LeN e",
+"L+N *BeLN aeL+N e*LN. +e8LN eLN*B. 8eLa*N MeQ* Qe+M Me*QT aMe+Q Me*Qj +Qe8M",
+" QeTM*j se+QM WeL eLW! HLWe WLae eLW. WL8e HeWL. H8eWL WMe W!Me ZeM aMZe Me",
+"Wj 8MWe MeZj sMZe fWL +WfL HWfL fWgL WLf. W8fL fHWL. f8WgL fQM +WfM ZfM gMZ",
+"f WMfj W8fM ZMfj fMsZ emL e!mL mLeB aLem 5Lem 8Lem emL5B aem5L Mem M!em MeT",
+"m Meam peM 8Mpe TepM sMpe eLm* +Lem em;LB aem+L em;5L em>L 5eLm*B >eamL MeQ",
+"; Me+m MemT; aMe+m Mep* pe>M peTM; >Mesp GLem emLW! HLem aemGL 5LWe G8meL H",
+"5eWL H8emL MeGm MemW! MeZm ZeaMm GMpe pG8Me ZMpe ZpesM fvL v+fL vHfL gLfv v",
+"5fL >Lfv fvH5L f>gvL fvM f+vM fMZv fvgM fpM >Mfp fMZp yfM ,eL e&L eL,B ,Lae",
+" eL,. ,L8e ,eL.B aeL,8 ,Me Me& Te,M ae,M Me,j 8e,M Mej,T ,Mse e*,L -eL *Be,",
+"L ae-L ,e*L. 8e-L ,eL*B. -8aeL ,eM* -Me Me*,T Te-M Me*,j 8M-e ,TMej* -Mse ,",
+"GL ,LG& ,LHe ,LGa GL,. ,LG8 ,GHL. ,G8HL ,GM G&,M GT,M Ga,M GM,j G8,M ,GTMj ",
+",GsM f,L f-L ,HfL gLf- ,Lf. -8fL fH,L. f-8gL fM, f-M ,HfM f-gM ,Mfj -Mf8 fT",
+"M,j fMs- eL,2 &Le2 ,eL2B aeL,2 ,L5e 5Le& ,5eLB ,5aeL ,2Me M2e& Me2,T aMe,2 ",
+"5e,M Me5& ,5TMe se5,M ,Le; e;-L e;L,B ae;-L e;L,5 -e>L ,5Le;B >e-aL Me,; Me",
+"-; Me;,T -TMe; Me;,5 -M>e ,5TMe; s->Me GL,2 e&LG2 ,GHL2 ,GaL2 ,LG5 ,G58L ,G",
+"5HL ,G5aL ,2GM Me&G2 ,GTM2 Me&H2 G5,M Me&G5 ,G5HM sG,5M ,;fL -;fL fH;,L f-;",
+"gL ,5fL >Lf- f5H,L f>g-L ,Mf; f;-M fTM,; f-TM; ,5fM f->M f5T,M f>Ms- eL,N &",
+"LeN ,eLNB aeL,N ,eLN. e&L8N eLN,.B ,8LaeN Qe,M MeQ& ,QTMe aMe,Q Mej,Q Me&Q8",
+" ,QTMej seM,Q ,e*LN eL-N ,eL*BN -aeLN e*L,N. -8eLN NB*L,e. aeL-8N Me*,Q Qe-",
+"M ,QTMe* -QTMe ,QMej* -Q8Me QMej,T* s-QMe ,LWe WLe& ,GHWL ,GaWL ,GWL. ,G8WL",
+" HeL,W. aeL,W8 GQ,M MeW& ,GZM MeZ& ,GQMj Me&W8 ZeM,j Ze&sM ,WfL fL-W fHW,L ",
+"f-WgL fW,L. f-W8L ,HWfL. gf8-WL ,WfM -WfM fMZ, fMZ- fQM,j f-Q8M ZfM,j sfZ-M",
+" ,Lem eLm& emL,B aem,L emL,5 em&5L ,5LemB aeL,8m Me,m emM& Mem,T aMe,m ,Mpe",
+" Mep& peT,M pe&sM em;,L em-L ,mLe;B -maeL ,5em*L >e-mL 5m*B,eL -ma>eL Mem,;",
+" Me-m ,TmMe; -TmMe peM,; pe-M Me;p,T -psMe ,LGm em&GL ,GmHL em&HL ,G5WL ,G8",
+"mL emL,H5 aeL,5W GM,m MemG& ZeM,m Ze&Mm ,GpM pG&,M Zpe,M ZpeM& fLv, fL-v fv",
+"H,L -vgfL fv5,L f>-vL v,Hf5L -vgf>L v,fM fM-v Zfv,M -vMZf p,fM fM-p fpZ,M f",
+"-yM Ue Ue! UeD Uae Ue. U8e U.De D8Ue UeM U!Me Ve Vea Uej 8MUe Vej seV Ue* U",
+"+e DeU* +DUe U.I* +eU8 I*.UD U+eD8 IM* +MUe Ve* V+e I*Uj +eUj I*Vj V+se UGe",
+" GeU! JUe UaJe GeU. G8Ue UeJ. U8Je GMUe IM!Ge VJe JaVe GjUe UG8Me VeJj VJse",
+" fU fU+ JfU gfU fU. fU8 J.fU fUJ8 fUM U+fM Vf Vfg fUj U+fj Vfj sfV Ue2 e2U!",
+" U2De U2ae U5e 5eU8 5DUe 5aUe U2Me IM2e! Ve2 aeV2 5MUe U5e8M V5e V5se Ue; +",
+"eU; DeU; aeU; 5IU* >eU U5eD; Ua>e MeU; IM;+e Ve; +eV; IM5* Ue>M 5IV* V>e Ge",
+"U2 UGe!2 UeJ2 JUae2 G5Ue UG58e U5Je J5U8e IM2Ge UG2Me! JeV2 VJae2 UG5Me G5M",
+"U8e VeJ5 seVJ5 fU; U+f; fUJ; g;fU fU5 f>U fUJ5 gUf> U;fM fU+M; Vf; V;gf U5f",
+"M fU>M Vf5 Vf> UeN eNU! UNDe UNae eNU. UN8e UeDN. U8eDN UQe Q!Ue VeQ QaVe Q",
+"eUj Q8Ue QeVj sQVe UNI* UN+e I*NUD U+eDN I*NU. U+e8N DeNU*. aeNU8* QIU* +QU",
+"e QIV* +QVe IM*Qj IM*Q8 VeQ*j sI*VQ UWe U!We UWJe WaUe U.We W8Ue JUWe. J8UW",
+"e GQUe UGQe! ZeV ZaVe WeUj UGQ8e ZjVe VZse fUW U+fW JWfU gWfU UWf. UWf8 JfU",
+"W. Jf8UW fUQ U+fQ VfZ ZfgV UWfj UQf8 fjVZ sZVf Uem U!em DeUm aeUm 5eUm 8eUm",
+" U5eDm aemU5 QeUm IMme! Vem aeVm pUe U8pe Vpe seVp ImU* +eUm Im*UD aemU+ Im",
+"*U5 Ue>m 5DeUm* >eUDm QeU; IMm+e QeV; +eVm Uep* pU>e pIV* >eVp GmUe UGme! U",
+"eJm JmUae 5WUe UG8em J5UWe J8mUe IMmWe Im!WMe VeJm ZeVam UGpe pUG8e ZeVp Jp",
+"Vse fvU f+vU fUJv fvgU vUf5 v>fU JvfU5 J>fvU vUfQ fvU+Q Vfv gfVv fpU p>fU f",
+"pV yVf hU hU& hUD hcU hU. h8U UDh. cUh8 hM hM& Vh Vhc hMj h8M Vhj hsV hU* h",
+"-U U*hD -Uhc U*h. -Uh8 hUD*. c-Uh8 hM* h-M Vh* V-h U*hj -Uhj V*hj V-hs hUG ",
+"UGh& hJU hUcJ UGh. UGh8 JUh. hUJ8 hMG GMh& VhJ cJVh UGhj G8hM JjVh VhsJ hfU",
+" f-U fUhJ iU h.fU fUh8 JfUh. iU8 hfM f-hM Vfh iV fUhj f8hM hjVf iVs hU2 U&h",
+"2 UDh2 c2hU h5U U5h8 U5hD hUc5 hM2 M&h2 Vh2 h2Vc h5M 5Mh8 Vh5 c5Vh h;U -Uh;",
+" U;hD hUc; U5h; h>U h5UD; >Uhc hM; -Mh; Vh; h;V- U;hj h>M V5h; h>V UGh2 hUG",
+"&2 JUh2 cJUh2 UGh5 h5UG8 hUJ5 cJ5hU GMh2 hMG&2 h2VJ VhJc2 G5hM h5MG8 J5Vh V",
+"h5sJ fUh; f;-U hUJ; iU; fUh5 fUh> Jf5hU i>U fMh; f-UM; h;Vf iV; f5hM hf>M h",
+"5Vf iV> hUN U&hN UDhN cUhN UNh. U8hN hUDN. hcU8N hQU UQh& VhQ cQVh UQhj UQh",
+"8 VQhj VshQ U*hN hN-U hUD*N c-UhN hU*N. -U8hN U*DhN. hc8-UN UQh* -UhQ V*hQ ",
+"hQV- hQU*j -UQh8 VhQ*j V-hsQ hWU UWh& JUhW hUcW UWh. UWh8 hJUW. hJ8UW hWM W",
+"Mh& hZV VhZc UWhj W8hM VZhj sZVh fUhW -UhW JfUhW iUW fUWh. f-UW8 hJWfU. UWi",
+"8 fUhQ -UfQ VfhZ iZV fUQhj f-UWj VfZhj sZiV hmU Umh& UmhD hUcm U5hm U8hm h5",
+"UDm hc5Um hMm Mmh& Vhm cmVh hpU pUh8 hpV Vphs Umh; -Uhm hmUD; c-mhU h5Um* >",
+"Uhm U5*hmD h>cUm UQh; -Mhm Vmh; hmV- pUh; >Mhp h;Vp V-hp UGhm hWUm& hUJm cJ",
+"mhU U5hW h5WU8 hJ5UW c5WhU GMhm hWMm& JmVh VhmZc pUhW hpUG8 VphZ cpJVh hvU ",
+"fU-v vUhJ ivU vUh5 vUh> hvJU5 v>iU hvM hM-v hvV iVv hMfp >Mhv Vfhp yiV ke k",
+"e! keB ake 1ek 8ke 1Bke ak1e keM M!ke Tke akTe le le8 leT lse ke* +ke *Bke ",
+"ak+e ke1* +k1e ke*1B ake1+ Mek* ke+M keT* Tk+e le* l+e Tel* sel+ Gke G!ke H",
+"ke akHe Gk1e 8eGk Hk1e 8kHe keGM keMG! TkHe akeGT lGe G8le lHe sGle fk fk+ ",
+"fkH gfk f1k f8k 1Hfk f1gk fkM +kfM fTk fTgk lf lf+ lfH glf ke2 k!e2 e2kB k2",
+"ae 5ke 8k5e 5Bke ak5e k2Me keM!2 T2ke akeT2 le5 5el8 5Tle l5se ke; k;+e kBe",
+"; kea; ke1; >ke ke;1B ak>e Mek; ke;+M keT; akeT; le; l>e Tel; >els G2ke ke2",
+"G! H2ke akeG2 5eGk G5k8e 5kHe akeG5 keMG2 Gk2Me! GTke2 ak2HMe G5le lG58e H5",
+"le lsG5e fk; +kf; Hkf; g;fk f5k f>k H5fk gf>k k;fM fk+M; Tkf; fTkg; lf5 lf>",
+" f5lH l>sf keN k!eN eNkB aNke 1Nke kN8e keN1B ake1N Qke Q!ke TkQe akQe leQ ",
+"Q8le QelT lQse e*kN +Nke ke*NB ake+N ke*1N 1+ekN 1eNk*B akN1+e keQ* Qk+e Qk",
+"eT* ake+Q Qel* +Qle leQT* lse+Q Wke W!ke WkHe akWe Wk1e 8kWe 1HeWk ake1W Qk",
+"We GQke! Zke akZe lWe W8le lZe sZle fkW +Wfk HkfW gWfk 1Wfk W8fk f1HWk f8kg",
+"W fQk +Qfk Zfk gkZf lfW fQl+ lfZ Zfgl kem k!em kBem keam ke1m ke8m kem1B ak",
+"e1m kmQe kemQ! keTm akeTm lep l8pe lTpe sple emk; ke+m kem*B ake+m kem1; ke",
+">m keB1m* >keam keQ; kem+Q kemT; akeQ; pel; p>le lepT; l>esp keGm kemW! keH",
+"m akeGm Wk5e kemG8 kem1H ake5W kemGQ ke!GMm keZm Zkeam pGle lGp8e Zple lZes",
+"p fvk f+vk fHvk fvgk v1fk fv>k fv1Hk f>kgv vkfQ fvk+Q fvZk Zfkgv lfp l>fp Z",
+"flv ylf ,ke ke& ,Bke ak9e 1e,k :ek keB,1 ak:e 9Me Mek& Tk9e aM9e le9 l:e ,T",
+"le s:le ke9* -ke ke*,B ak-e ke*,1 -k:e ,1ek*B :-ake Me9* 9M-e ,Tke* Tk-e 9e",
+"l* l-e le9T* les- ,Gk G&,k Gk,H Ga,k 1G,k ,G:k ,1GHk Hk:e 9G,M ke&GM GT,k a",
+"Me9G lG, :Gle ,GlH sGl, f9k f-k ,Hfk f-gk ,1fk :fk f91Hk gk:f f9M -kfM ,Tfk",
+" f9gM lf9 lf: f9lH sfl- ,2ke k2e& ke2,B ake,2 5k9e 5k:e ,5keB :e5ak 92Me ke",
+"&M2 ,Tke2 aMe92 ,5le l5:e le95T lse:5 ke,; ke-; ke;,B -kae; ke;,1 :e>k keB,",
+"1; >k-ae Me9; -kMe; ke;,T -Tke; ,;le >el- le;,T l>es- ,2Gk ke&G2 ,GkH2 ke&H",
+"2 G5,k :G5,k ,G5Hk :He5k ,GkM2 ke2GM& ,GTk2 ak2,GT ,Gl5 l:G,5 lG,H5 :Hel5 ,",
+"kf; f;-k f9Hk; f-kg; ,5fk >k:f f95Hk f>kg: 9Mf; f-kM; f9Tk; f-Tk; f9l; l>:f",
+" lf9H5 glf:> ,Nke kNe& keN,B ake,N keN,1 ke:N ,1NkeB :eakN Qk9e keQ& ,QkTe ",
+"ake,Q ,Qle :Qle le9QT :Qels ke*,N ke-N 9eNk*B -kaeN ,1ek*N :-keN ke1*,NB -k",
+"a:eN ,Qke* Qk-e Qke9T* -QkTe le9Q* -Qle 9Qel*T l-sQe Gk,W keW& ,GkHW ake,W ",
+",1GWk Wk:e 1He,Wk :HeWk GQ,k ke&GQ ,GZk keZ& ,GlW :Wle Z9le leZ: ,Wfk -Wfk ",
+"f9HWk f-kgW f91Wk fk:W ,1HfkW :fgWk ,Qfk -Qfk f9Zk f-Zk f9lW lW:f l,Zf Z:lf",
+" ke,m emk& kem,B ake,m kem,1 ke:m keB,1m :emak Me9m kemQ& kem,T aMe9m p9le ",
+"le:p lep,T :pels kem,; ke-m keB9m* -kmae ,1mke; :-mke ke,m1;B :ea-km ke;,Q ",
+"-Qkem ,Tmke; -Tkem lep,; le-p leTp9* l-pse Gk,m kemG& kem,H akm,G ,1Gkm :Gm",
+",k ,1Hkem :Hekm Mem9G ,GQkm& Z9ekm Zkem& pGl, :pGle lZep9 Z:elp v9fk fk-v f",
+"v9Hk -vkgf fv95k fk:v f1Hvk, :fvgk v9fM -vkfQ Zf9vk Z-kfv l,fp :flv fp9lZ l",
+"fy: Uek U!ke Dke akUe 1Ue U81e Ue1D Ua1e keIM IkMe! Vek akVe lIe U8le leV s",
+"Ile Ik* +kUe IkD* Dk+e Ue1* U+1e Ik*1D ak*1I k*IM Ik*+M IkV* +kVe lI* U+le ",
+"Vel* sIl* GkUe Ik!Ge Jke akJe UG1e 1UG8e 1UJe 8kJe IkMGe UGkMe! VeJk JkVae ",
+"UGle lGU8e lJe lesJ fUk U+fk Jfk Jfgk f1U 1Uf8 f1Jk f1gU IkfM fU+kM Vfk gkV",
+"f lfU fUl+ lfJ Vfgl U2ke Ik2e! D2ke akeU2 U51e 1Ue58 Dk5e akeU5 IkMe2 ke2IM",
+"! keV2 Veka2 U5le lI58e V5le seVl5 keU; Ik;+e keD; akeU; Ue1; 1U>e Ik*5D Dk",
+">e Ik;Me +IkMe; keV; V+ek; Uel; lI>e Vel; leV> Ik2Ge UG2ke! keJ2 Jkae2 1UG5",
+"e G5kU8e 5kJe J5k8e UGkMe2 IkGMe2! JkVe2 VeaJk2 lGU5e UG5le8 J5le lJs5e U;f",
+"k fU+k; fkJ; Jfkg; 1Uf5 fU>k f5Jk Jf>k fUkM; Ik;fM+ V;fk Vfgk; fUl; lIf> l;",
+"Vf J>lf UNke IkNe! DNke akeUN 1NUe 1Ue8N 1UeDN 1UaeN QkUe UQek! QkVe VeQak ",
+"UQle lIQ8e lQVe seVlQ INk* Ik*+N Ik*DN ak*IN Ik*1N Ik*8N IkN1D* akN1I* IkQ*",
+" Ik*+Q VeQk* V+eQk QIl* l+IQe lI*VQ sI*lQ WkUe UWek! WkJe JkWae UW1e 1UW8e ",
+"J1UWe J8kWe UGQke Ik!WMe JkZe ZJkae UWle lWI8e ZJle lJZse UWfk fU+Wk JWfk J",
+"fkgW 1UfW f1U+W Jf1UW Jf8Wk UQfk fUQ+k ZkVf VfZgk fUlW lfU+W ZflJ glJZf keU",
+"m Ikme! keDm akeUm Ue1m Ikm8e kem1D aem1U IkmQe Ik!Mem keVm Vemak pUle lIp8",
+"e leVp Vpels kmI* Ikm+e IkmD* akmI* Ikm1* >kIem 1Dekm* >kDem IkmQ* U+Qkem V",
+"emk; V+ekm pIl* l>Ipe Vpel; V>elp IkmWe Im!Wke keJm Jkmae 1UGem UG8kem J1mU",
+"e J8kem UGQkem ImQkWe! ZJkem ZkaVem lGpUe lG8pUe leJp Jplse vUfk fvU+k fvJk",
+" Jvkgf v1fU f>Uv1 Jv1fU J>kfv fvUQk fQ+vIk fkVv Vfvgk lIfp fpUl> Jplf lfyJ ",
+"ht ht& htD htc ht1 h:t t1hD t:hc htM tMh& Vht tcVh lh lh: lhV uh ht* t-h hD",
+"t* hct- t*h1 t-h: t*1hD h:tc- t*hM hMt- t*Vh Vht- lh* l-h l*Vh uh- htG h&tG",
+" tJh hctJ tGh1 tGh: h1tJ tJh: tGhM tGMh& VhtJ tJVhc lhG lGh: lJh uJh tf tf-",
+" tfJ it tf1 tf: J1tf it: tfM fMt- tfV iVt lfh tfl- lJtf ui ht2 t&h2 tDh2 h2",
+"tc ht5 t:h5 hDt5 tch5 tMh2 htM&2 h2Vt Vhtc2 lh5 h5l: t5Vh uh5 ht; h;t- hDt;",
+" tch; t5h; h>t t5*hD htc> t;hM t-hM; t;Vh V-ht; lh; h>l l;Vh uh> h2tG tG&h2",
+" h2tJ tJhc2 tGh5 t:Gh5 h5tJ tJ5h: tGMh2 hM&tG2 tJVh2 VhctJ2 h5lG lh:G5 h5lJ",
+" hJu5 tf; f-t; h;tJ it; tf5 tf> Jft5 it> fMt; tf-M; t;Vf t;iV l;tf h>lf hJl",
+"; ui> htN t&hN tDhN hNtc t1hN hNt: ht1DN h:tcN htQ h&tQ tQVh tchQ lhQ hQl: ",
+"VlhQ uhQ hNt* hNt- t*DhN t-hcN t*1hN h:t-N h1Dt*N t-ch:N t*hQ hQt- tQ*Vh V-",
+"htQ hQl* hQl- lhVQ* h-uQ htW h&tW hWtJ tchW tWh1 t:hW tJh1W h:WtJ tGhQ tGQh",
+"& hZt htZc lhW lWh: hZl uZh tfW hWt- JftW itW f1tW tW:f tfJ1W t:iW tfQ f-tQ",
+" tZf iZt lWtf h-lW hZlf uiZ htm h&tm hDtm tchm t5hm t:hm ht5Dm h:mtc tQhm h",
+"tQm& tmVh Vhmtc hpl h:tp Vplh uph tmh; hmt- tm*hD t-mhc t5*hm hmt> tmDh1; h",
+">tcm tQh; t-Qhm Vhmt; V-mht l;hp hpl- lh;Vp hpu- tGhm tGmh& hmtJ tJmhc t5hW",
+" h:Wt5 tJ5hW :Jmht tGQhm tG&hMm hmtZ hZtcm lGhp lhW:p tZhp hZup hvt t-hv tJ",
+"hv itv h1tv tvh> hvtJ1 tvi: hQtv hvt-Q tZhv tZiv lvh hvl- hZlv uiy 3 !3 3B ",
+"a3 3. 83 .B3 8a3 3K !K3 T3 Ta3 j3 8j3 Tj3 s3 3( +3 3B( +a3 3(. +83 3(.B 8a+",
+"3 3(K +3K T3( +T3 j3( +j3 j3T( s+3 E3 !E3 H3 Ha3 E3. 8E3 H3. H83 EK3 !3EK H",
+"T3 TaH3 jE3 jE83 Hj3 sH3 d3 +d3 Hd3 g3 d3. 8d3 d3H. g83 dK3 dK+3 Td3 gT3 dj",
+"3 +3dj H3dj gs3 4 4! 4B 4a 45 48 45B 48a 4K 4K! 4T 4Ta 4j 48j 4T5 s4 4; 4+ ",
+"4;B 4+a 45; >4 5;4B >4a 4;K 4+K 4T; 4+T 4j; >j4 T;4j s>4 4E 4E! 4H 4Ha 45E ",
+"48E 4H5 4H8 4EK EK4! 4HT HT4a 4jE 8j4E 4Hj s4H 4d 4+d 4Hd g4 4d5 >4d H54d g",
+">4 4dK +d4K 4Td g4T 4dj 4d>j H;4j gs4 3N !3N 3BN a3N N.3 83N 3BN. aN83 Q3 Q",
+"!3 QT3 Qa3 Qj3 Q83 TjQ3 sQ3 3(N +3N 3(NB a3+N 3(N. 83+N 3(N.B +8a3N Q3( +Q3",
+" T3Q( +3Qa j3Q( +3Q8 QTj3( +Qs3 W3 W!3 HW3 Wa3 W3. W83 W3H. H3W8 WQ3 W3Q! Z",
+"3 Za3 Wj3 W3Q8 Zj3 sZ3 Wd3 +W3 WdH3 gW3 d3W. +3W8 HWd3. W8g3 Qd3 +3Qd Zd3 g",
+"Z3 W3dj +3Wj djZ3 g3sZ 4m 4m! 4mB 4am 45m 48m 5m4B 8m4a 4Q 4Q! 4QT 4Qa p4 p",
+"48 p4T sp4 4m; 4+m m;4B +m4a 5m4; >m4 45m;B 4a>m 4Q; 4+Q Q;4T +Q4T p4; p>4 ",
+"4Tp; p>s4 4W 4W! 4HW 4Wa 4W5 4W8 H54W H84W 4WQ Q!4W Z4 Z4a p4W 4Wp8 Zp4 sZ4",
+" v4 v4+ v4H gv4 v45 v>4 4Hv5 v>g4 v4Q 4+vQ Zv4 gZ4 pv4 p4v> pvZ4 y4 #3 &3 #",
+"B3 a&3 #3. 8&3 #3.B a&83 #3K &3K T#3 T&3 j#3 &j3 j#T3 s&3 #3( +&3 #3(B a&+3",
+" 3(#. 8&+3 .B3#( +8a&3 3(#K &3+K #3T( +3T& #3j( +3&j Tj#3( +&s3 #E3 &E3 H#3",
+" H&3 E3#. &E83 #3H. 8&H3 #3EK EK&3 T#H3 H3T& #Ej3 jE&3 j#H3 H&s3 d#3 d&3 d#",
+"H3 g&3 #3d. 83d& Hd#3. 8&g3 #3dK &3dK d#T3 T&g3 j#d3 d3&j dj#H3 s&g3 4# 4& ",
+"4#B 4a& 45# 48& 5B4# 5a4& 4#K 4&K 4T# 4T& 4j# 4&j 4#5T s4& 4;# 4+& ;#4B a;4",
+"& 5;4# >&4 45;#B 4a>& ;#4K 4K;& 4#T; +T4& 4#;j 4&>j ;j#4T >&s4 4#E 4&E 4H# ",
+"4H& 5#4E 4E5& 4#H5 H54& EK4# &E4K HT4# H&4T j#4E 4E&j 4#Hj 4Hs& 4d# 4d& 4#H",
+"; g4& 4#5d 4d>& 4H5d# >&g4 dK4# 4Kd& 4#Td 4Tg& 4#dj d&4j 4Hjd# g&s4 #3N &3N",
+" #3NB &3aN #3N. &38N 3BN#. 8a&3N Q#3 Q&3 T#Q3 Q3T& j#Q3 Q3&j QTj#3 Q&s3 3(#",
+"N &3+N 3(N#B +a&3N 3(N#. +8&3N 3B(N.# 8a&+3N #3Q( +3Q& QT#3( +QT&3 Qj#3( &j",
+"3+Q Tj#Q3( s+Q&3 W#3 W&3 W#H3 H3W& #3W. 8&W3 HW#3. H8W&3 Q#W3 W3Q& Z#3 Z&3 ",
+"j#W3 W3&j j#Z3 s3Z& d#W3 +3W& HWd#3 W&g3 Wd#3. d&3W8 Wd#H3. gW8&3 d#Q3 Q3d&",
+" d#Z3 g3Z& dj#W3 d&jW3 Zdj#3 Z&3gs 4m# 4&m m#4B am4& 5m4# 8m4& 45m#B am&48 ",
+"4Q# 4Q& 4#Tm Qa4& p4# p&4 4Tp# p&s4 m;4# +m4& 4m;#B am&4+ 45m;# 4&>m 5m;4#B",
+" >m4a& 4#Q; +Q4& 4QT;# 4+QT& 4;p# p4>& p4T;# p>4s& 4W# 4W& 4#Hm Hm4& 4#5W 5",
+"W4& 4H5W# 4H8W& WQ4# W&4Q Z4# Z4& 4Wp# 4Wp& p4Z# Z&s4 v4# v&4 4Hv# v&g4 45v",
+"# v4>& v4H5# gv>4& 4Qv# 4Qv& v4Z# Z&g4 v4p# p4v& Zpv4# y&4 C3 !C3 D3 Da3 C3",
+". 8C3 D3. D83 CK3 !3CK DT3 TaD3 jC3 jC83 Dj3 sD3 C3( +C3 D3( +D3 3(C. 8C+3 ",
+"3(D. +3D8 3(CK CK+3 T3D( DT+3 C3j( jC+3 j3D( +Ds3 CE3 CE!3 HD3 DaH3 E3C. CE",
+"83 D3H. H3D8 C3EK EKC!3 DTH3 HDTa3 CEj3 8jCE3 H3Dj HDs3 dC3 dC+3 Dd3 gD3 C3",
+"d. dC83 d3D. D8g3 CKd3 +dC3K D3Td DTg3 jCd3 djC+3 D3dj sDg3 4C 4C! 4D 4Da 4",
+"5C 48C 4D5 4D8 4CK CK4! 4DT DT4a 4jC 8j4C 4Dj s4D 4;C 4+C 4D; 4+D 5;4C >C4 ",
+"45D; >D4 ;C4K +C4K D;4T +D4T 4C;j 4j>C D;4j >Ds4 4CE !C4E 4HD HD4a 5C4E 8C4",
+"E H54D H84D EK4C 4CE!K HD4T 4HDTa jC4E 48jCE Hj4D 4HsD 4dC +d4C 4Dd g4D 4C5",
+"d 4d>C 5D4d >Dg4 dK4C 4+dCK Dd4T 4DgT 4Cdj >j4dC Dd4j gDs4 C3N C3!N D3N a3D",
+"N C3N. C38N N.D3 83DN QC3 !CQ3 QD3 DaQ3 jCQ3 8CQ3 Q3Dj QDs3 3(CN C3+N 3(DN ",
+"D3+N C3N(. +8C3N D3(N. +D83N C3Q( QC+3 D3Q( +3QD QjC3( +Q8C3 QDj3( s+QD3 WC",
+"3 !CW3 WD3 DaW3 C3W. 8CW3 D3W. W3D8 QCW3 Q!WC3 ZD3 DaZ3 jCW3 W8QC3 DjZ3 ZDs",
+"3 dCW3 WC+3 W3Dd WDg3 WdC3. +W8C3 WDd3. gWD83 dCQ3 +WQC3 DdZ3 ZDg3 djCW3 +W",
+"jC3 ZDdj3 gZsD3 4mC mC4! 4Dm Dm4a 5m4C 4C8m 45Dm Dm48 4QC 4CQ! 4QD QD4a p4C",
+" 48pC pD4 pDs4 m;4C 4C+m 4mD; +m4D 45m;C 4m>C 4D5m; 4D>m 4CQ; 4C+Q Q;4D +Q4",
+"D 4;pC p4>C 4Dp; p4>D 4WC W!4C 4WD WD4a 4C5W 4CW8 5W4D WD48 WQ4C 4WQ!C Z4D ",
+"4DZa 4WpC p4W8C pDZ4 sDZ4 v4C 4+vC vD4 vDg4 45vC v4>C 4Dv5 v4>D 4QvC v4+QC ",
+"vDZ4 gDZ4 v4pC pv>4C p4vD y4D b3 b&3 bD3 c3 b3. b83 D3b. c83 bK3 &3bK bT3 c",
+"T3 bj3 b3&j b3Dj sc3 b3( b+3 D3b( c+3 3(b. +8b3 bD3(. +8c3 3(bK +3bK T3b( +",
+"Tc3 j3b( b3+j bTj3( c+s3 bE3 &Eb3 bH3 cH3 E3b. 8Eb3 H3b. H8c3 EKb3 bK&E3 HT",
+"b3 HTc3 jEb3 &jEb3 b3Hj cHs3 bd3 b3d& b3Dd gc3 d3b. b38d bHd3. c8g3 dKb3 d&",
+"3bK b3Td cTg3 b3dj d&jb3 bHjd3 g3sc 4b 4b& 4bD c4 4b5 4b8 b54D c45 4bK bK4&",
+" 4bT c4T 4bj b84j b54T sc4 4b; 4b+ b;4D c4+ 45b; >b4 4b5D; c>4 4Kb; 4Kb+ b;",
+"4T 4+cT b;4j 4b>j 4bT;j s4c> 4bE b&4E 4bH c4H 4Eb5 4Eb8 b54H 4Hc5 bK4E 4b&E",
+"K bH4T 4HcT 4Ebj 4b8jE bH4j sHc4 4bd b+4d bH4d gc4 b54d 4b>d 4bH5d g4c> 4Kb",
+"d 4b+dK bT4d gTc4 bd4j >b4dj 4bHdj scg4 b3N &3bN D3bN c3N N.b3 83bN bD3N. 8",
+"3cN bQ3 b3Q& b3QD cQ3 Qjb3 b3Q8 bQDj3 s3cQ 3(bN +3bN bD3(N +3cN b3(N. b+83N",
+" D3(bN. c+83N Q3b( b3+Q bQD3( +Qc3 bQj3( b+Q83 QD3bj( cQ+s3 bW3 b3W& b3WD c",
+"W3 W3b. b3W8 bHW3. W8c3 WQb3 bWQ&3 Zb3 Zc3 b3Wj bW8Q3 bjZ3 s3Zc Wdb3 b3+W b",
+"HWd3 g3cW bWd3. b+W83 WD3bd. cW8g3 b3Qd b+WQ3 bdZ3 g3Zc bWjd3 b+Wj3 Zbdj3 Z",
+"cgs3 4bm bm4& bm4D c4m 45bm bm48 4b5Dm 48cm 4bQ bQ4& bQ4D c4Q pb4 4bp& 4bpD",
+" cp4 4mb; bm4+ 4bDm; 4+cm 4b5m; 4b>m b5m4D; >mc4 b;4Q b+4Q 4bQD; 4+cQ 4bp; ",
+"p4>b pb4D; p>c4 4bW bW4& bH4W c4W b54W bW48 4bH5W 4Wc5 bW4Q 4bWQ& Z4b Zc4 4",
+"bpW pb4W8 pbZ4 s4Zc vb4 4bv& 4bvD cv4 4bv5 v4>b vb4H5 v>c4 4bvQ vb4+Q vbZ4 ",
+"g4Zc p4vb pvb>4 Zpbv4 yc4 6 6! 6B 6a 61 68 61B 68a 6K 6!K 6T 6Ta 6j 68j 6T1",
+" s6 6( 6+ 6(B 6+a 61( 6+1 1(6B 1+6a 6(K 6+K 6T( 6+T 6j( 6+j 6(1T s6+ 6E 6!E",
+" 6H 6Ha 61E 68E 6H1 6H8 6EK EK6! 6HT HT6a 6jE 8j6E 6Hj s6H 6d 6+d 6Hd g6 6d",
+"1 68d 1H6d g61 6dK +d6K 6Td g6T 6dj +j6d 1T6d gs6 46 6!4 46B 4a6 7 78 7B 7a",
+" 46K 4K6! 4T6 6T4a 7j 78j 7T 7s 6; 4+6 6;B 6a; 7; 7> 7B; 7>a 6;K 4K6+ 6T; 6",
+"+4T 7;j 7>j 7T; 7s> 46E 4E6! 4H6 6H4a 7E 78E 7H 7H8 6E4K 6!4EK 6H4T 4H6Ta 7",
+"jE 8j7E 7HT 7sH 4d6 6+4d 6H; g46 7d 7>d 7Hd g7 4K6d 4+6dK 6T4d 4Tg6 7dj >j7",
+"d 7Td g7s 6N 6!N 6NB 6aN 61N 68N 1N6B 6N1a 6Q 6Q! 6QT 6Qa 6Q1 6Q8 1Q6T s6Q ",
+"6(N 6+N (B6N +a6N 1(6N 6N1+ 61(NB 6+1aN 6Q( 6+Q QT6( +Q6T 6(1Q 1+6Q 6Q1T( 6",
+"+sQ 6W 6W! 6HW 6Wa 6W1 6W8 1H6W 1W6a 6WQ Q!6W Z6 Z6a 6Wj W86Q Z61 sZ6 6Wd 6",
+"+W HW6d g6W 1W6d 1+6W 6H1Wd 6Wg1 6Qd +W6Q Z6d gZ6 1Q6d +W6j 6dZ1 sZg6 6m 6m",
+"! 6mB 6am 7m 78m 7Bm 7am 4Q6 Q!6m 6Tm 6Q4a 7p 7p8 7pT 7sp 6m; 6+m m;6B +m6a",
+" 7m; 7>m m;7B >m7a 6Q; 6+4Q Q;6T +T6m 7p; 7p> pT7; 7ps> 4W6 6!4W 6Hm 6W4a 7",
+"W 7W8 7HW 7Wa 6W4Q 4WQ6! Z46 4aZ6 7pW pW78 7Z 7Zs v6 v6+ v6H gv6 7v 7v> 7vH",
+" g7v v6Q 6+vQ Zv6 Zvg6 7vp pv7> 7Zv y7 69 6& 69B 6a9 691 :6 916B :6a 69K 6&",
+"K 6T9 6T& 6j9 :6j 9T6j s:6 69( 6+9 9(6B 9+6a 916( :6+ 691(B 6+:a 9(6K 6K9+ ",
+"6(9T 9+6T 6(9j 6+:j 6T91( :6s+ 69E 6&E 6H9 6H& 916E :6E 691H :H6 9E6K &E6K ",
+"9H6T H&6T 6E9j 6j:E 9H6j :Hs6 6d9 6d& 9H6d g69 691d :d6 6H91d g:6 6K9d 6Kd&",
+" 9T6d 6Tg9 9d6j 6d:j 6Hj9d s:g6 49 49& 49B 49a 79 7: 7B9 7:a 49K 4K6& 49T 6",
+"T4& 79j 7:j 7T9 7s: 49; 49+ 4B9; 9+4a 79; 7:> 9;7B :>7a 4K9; 4K9+ 9T6; 9+4T",
+" 9;7j >j7: 9T7; 7:s> 49E 4E6& 49H 6H4& 79E 7:E 7H9 7:H 9E4K 49&EK 9H4T 49HT",
+"& 9j7E :j7E 9H7T 7Hs: 49d 6d4& 9H4d g49 7d9 7:d 9H7d g7: 4K9d 49+dK 9T4d 49",
+"gT 9d7j 7j:d 9T7d 7sg: 69N 6&N 9N6B 6N9a 916N :6N 691NB 6a:N 6Q9 6Q& 9Q6T 9",
+"Q6a 9Q6j :Q6 6Q91T :Qs6 9(6N 6N9+ 69(NB 6+9aN 691(N 6+:N 91(6NB :6+aN 6(9Q ",
+"9+6Q 6Q9T( 6+Q9T 6Q91( 6+:Q 9Q16T( :Q6s+ 6W9 6W& 9H6W 9W6a 691W :W6 6H91W 6",
+"H:W 9W6Q W&6Q Z69 Z6& 9W6j 6W:Q 6jZ9 Z:6 9W6d 9+6W 6H9Wd 6Wg9 6W91d 6+:W 9H",
+"16Wd :Wg6 9Q6d Qd6& 6dZ9 Z6g9 6Wj9d 6Q:d Z691d g6Z: 49m 6m& 4B9m 9a6m 79m 7",
+":m 9m7B :m7a 49Q 6Q4& 9Q4T 9Q4a 7p9 :p7 p97T :p7s 9m6; 9+6m 49m;B 49+am 9m7",
+"; :m7> 7B9m; 7:>am 9Q6; 9+4Q 49QT; 49+Qa 7;p9 7>:p 7p9T; 7p>s: 49W 6W4& 9H4",
+"W 9W4a 7W9 7:W 9H7W :H7W 9W4Q 49WQ& Z49 49Z& p97W 7W:p 7Z9 7Z: v69 v6& 49vH",
+" v6g9 7v9 :v7 v97H :vg7 49vQ 6Qv& v6Z9 Z4g9 p97v :p7v Z97v y7: 6C 6!C 6D 6D",
+"a 61C 68C 6D1 6D8 6CK CK6! 6DT DT6a 6jC 8j6C 6Dj s6D 6C( 6+C 6D( 6+D 1C6( 6",
+"C1+ 6(1D 1+6D CK6( +C6K DT6( +D6T jC6( 6C+j 6(Dj 6+sD 6CE !C6E 6HD HD6a 1C6",
+"E 8C6E 1H6D H86D EK6C 6!CEK HD6T 6HDTa jC6E 68jCE Hj6D 6HsD 6dC +d6C 6Dd g6",
+"D 6C1d 6C8d 1D6d 6Dg1 dK6C 6+dCK Dd6T 6DgT 6Cdj 6+jdC Dd6j gDs6 46C 4C6! 4D",
+"6 6D4a 7C 78C 7D 7D8 6C4K 6!4CK 6D4T 4DT6a 7jC 8j7C 7DT 7sD 6;C 4C6+ 6D; 6+",
+"4D 7;C 7>C 7D; 7>D ;C6K 4+6CK D;6T 4+D6T ;j7C 7j>C D;7T 7Ds> 6C4E 6!4CE 6H4",
+"D 4H6Da 7CE 8C7E 7HD H87D 46CEK 4CE6!K 4H6DT 6HD4Ta jC7E 78jCE Hj7D sH7D 4C",
+"6d 4+6dC 6D4d 4Dg6 7dC >C7d 7Dd g7D 4d6CK 6+C4dK 4Dd6T g46DT dj7C 7>djC Dd7",
+"T 7Dgs 6CN !C6N 6DN Da6N 1C6N 8C6N 6N1D 6ND8 6QC 6CQ! 6QD QD6a 6C1Q 6CQ8 1Q",
+"6D 6QsD C(6N +C6N D(6N 6N+D 61C(N 6+1CN 6D1(N 6+D1N QC6( 6C+Q 6(QD +Q6D 6Q1",
+"C( 6+Q1C 6QD1( s6+QD 6WC W!6C 6WD WD6a 6C1W 6CW8 1W6D WD68 WQ6C 6WQ!C Z6D 6",
+"DZa 6CWj 6W8QC 6DZ1 sDZ6 Wd6C 6C+W WD6d 6WgD 6W1dC 6+W1C 6WD1d g61WD 6CQd 6",
+"+WQC 6DZd gDZ6 6WjdC 6+WjC Z61Dd gZ6sD 6mC mC6! 6Dm Dm6a 7mC 8m7C 7Dm D87m ",
+"4C6Q 4Q6!C 6Q4D 4QD6a 7pC p87C 7pD 7Dsp m;6C 6C+m Dm6; +D6m m;7C 7m>C Dm7; ",
+">m7D 6CQ; 4+Q6C QD6; 4+Q6D p;7C >C7p 7;pD p>7D 4C6W 4W6!C 6W4D 4WD6a 7WC W8",
+"7C 7WD WD7a 4WQ6C 6WC4Q! 4DZ6 Z46Da pW7C 7pW8C 7ZD 7DsZ v6C 6+vC v6D vDg6 7",
+"vC >C7v 7vD 7Dgv 6QvC v6+QC vDZ6 Zv6gD 7Cpv 7p>vC 7DZv y7D b6 b6& b6D c6 b6",
+"1 :b6 6Db1 :c6 b6K bK6& b6T c6T b6j b6:j 6Dbj sc6 b6( b6+ b(6D c6+ 61b( b6:",
+"+ b61D( :+c6 6(bK bK6+ b(6T 6+cT b(6j 6+bj b6T1( s+c6 b6E bE6& b6H c6H 61bE",
+" b6:E 6Hb1 c6:H 6EbK b6&EK 6HbT 6HcT bE6j :b6jE 6Hbj sHc6 b6d 6+bd 6Hbd gc6",
+" 6db1 b6:d b6H1d :cg6 bK6d b6+dK 6Tbd gTc6 6dbj :db6j b6Hdj scg6 4b6 b64& 4",
+"9D c46 7b 7:b 7bD 7c 4Kb6 4b6&K b64T 49cT 7bj :b7j 7bT 7cs b6; b64+ 6Db; c6",
+"; 7b; 7>b b;7D 7c> bK6; 4b+6K 6Tb; 6Tc; b;7j >j7b bT7; c>7s 4Eb6 4b6&E b64H",
+" 49cH 7bE 7E:b 7bH 7cH 4b6EK b6E4&K 4bH6T c46HT bj7E 7:bjE bH7T 7Hsc b64d 4",
+"b+6d 6Hb; c4g6 7bd :d7b bH7d g7c 4bd6K d&Kb6; 4bT6d c6;gT bd7j 7:dbj bT7d g",
+"s7c b6N bN6& bN6D c6N 61bN b6:N b61DN cN:6 b6Q 6&bQ 6QbT c6Q 6Qb1 b6:Q b6Q1",
+"D c6:Q 6(bN bN6+ b6D(N 6+cN b61(N :b6+N 6D(b1N :c6+N b(6Q 6+bQ b6QD( 6+cQ b",
+"6Q1( :Qb6+ b6(1QD :cQ6+ b6W 6&bW 6HbW c6W 6Wb1 b6:W b6H1W c6:W 6WbQ b6WQ& Z",
+"b6 Zc6 6Wbj :Wb6Q b6Z1 s6Zc 6Wbd 6+bW b6HWd cWg6 b6W1d :Wb6+ 6WDb1d g:c6W 6",
+"Qbd b6+Qd b6Zd g6Zc b6Wdj :Qdb6 Zb61d Zc6g: b6m 6&bm 6Dbm c6m 7bm :m7b bm7D",
+" 7cm b64Q 4bQ6& 6Tbm 49cQ 7pb 7b:p pb7D 7cp 6mb; 6+bm 49Dm; 6+cm bm7; >m7b ",
+"7bDm; cm7> 6Qb; 4b+6Q 49QD; 6Qc; 7;pb p>7b 7pbD; 7pc> b64W 4bW6& 6Hbm 49cW ",
+"7bW :W7b bH7W 7cW 4bW6Q b6W4Q& 4bZ6 c4Z6 pb7W 7pb:W 7Zb 7Zc vb6 b6v& 49vD c",
+"v6 7vb 7b:v vb7H 7cv b6vQ vb6+Q vbZ6 Z6cv pv7b :vb7p Zv7b y7c 3L !3L 3BL a3",
+"L 3L. 83L 3L.B a38L M3 M3! TM3 aM3 Mj3 8M3 MjT3 sM3 3(L +3L 3(LB a3+L (L3. ",
+"83+L 3L.(B +8a3L M3( +M3 M3T( +3aM j3M( +38M TMj3( +Ms3 E3L E3!L H3L a3HL 3",
+"LE. E38L 3LH. 83HL ME3 !EM3 HM3 H3aM jEM3 ME83 MjH3 HMs3 d3L d3+L d3HL g3L ",
+"3Ld. d38L Hd3L. 83gL dM3 +3dM H3dM gM3 Mjd3 83dM dMjH3 sMg3 4L 4L! 4LB 4aL ",
+"45L 48L 5B4L 4L5a 4M 4M! 4TM 4aM 4M5 48M 5T4M s4M 4;L 4+L ;L4B 4La; 5;4L >L",
+"4 45;LB 4a>L 4M; 4+M T;4M +T4M M;4j >M4 4T5M; s4>M 4EL !E4L 4HL Ha4L 5E4L 8",
+"E4L 4LH5 4LH8 4ME ME4! 4HM HM4a 4E5M 4E8M H54M 4HsM 4dL +d4L 4LH; g4L 4L5d ",
+"4d>L 4H5dL >Lg4 4dM +M4d HM4d g4M 5d4M 4d>M 4HM5d g4>M 3LN 3L!N 3LNB 3LaN 3",
+"LN. 3L8N 3L.NB 8a3LN QM3 M3Q! TMQ3 Q3aM MjQ3 Q38M QTMj3 QMs3 (L3N 3L+N 3(NL",
+"B +a3LN 3L.(N +83LN .BL3(N 8a3+LN M3Q( QM+3 QTM3( aM3+Q QMj3( +Q8M3 TMjQ3( ",
+"s+QM3 W3L !3WL W3HL a3WL 3LW. 83WL HW3L. H8W3L WM3 M3W! ZM3 aMZ3 MjW3 W38M ",
+"MjZ3 ZMs3 d3WL W3+L HWd3L W3gL Wd3L. +W83L Wd3HL. gW83L W3dM +3WM dMZ3 ZMg3",
+" dMjW3 +WM83 ZdMj3 gZsM3 4mL mL4! mL4B 4Lam 5m4L 4L8m 45mLB amL48 4QM Q!4M ",
+"Tm4M Qa4M p4M 48pM 4TpM p4sM m;4L 4L+m 4m;LB amL4+ 45m;L 4m>L 5m;4LB >m4aL ",
+"Q;4M +Q4M 4QTM; aMm4+ 4Mp; p4>M p4TM; >Mps4 4WL W!4L 4LHm 4LWa 4L5W 4LW8 4H",
+"5WL 4H8WL 4WM 4!WM Z4M 4aZM 4WpM W84M p4ZM sMZ4 v4L 4+vL 4HvL v4gL 45vL v4>",
+"L v4H5L gv>4L vM4 4+vM vMZ4 Z4gM p4vM v4>M Zpv4M y4M #3L &3L #3LB &3aL 3L#.",
+" &38L 3L.#B 8a&3L M#3 M&3 M#T3 T3M& j#M3 83M& TMj#3 M&s3 3(#L &3+L (BL#3 +a",
+"&3L 3L.#( +8&3L 3B(#L. 8a&+3L #3M( +3M& TM#3( aM3+& Mj#3( M&3+j Mj#T3( s+M&",
+"3 E3#L E3&L #3HL &3HL 3L.#E 8&E3L H#3L. H8&3L #EM3 &EM3 M#H3 H3M& Mj#E3 M&E",
+"83 HMj#3 sHM&3 #3dL &3dL Hd#3L &3gL d#3L. d&38L d#3HL. g8&3L M#d3 d3M& dM#H",
+"3 M&g3 dMj#3 dM&83 HM#dj3 gsM&3 4#L 4&L #B4L a&4L 5#4L 4L5& 45#LB 48a&L 4M#",
+" 4M& TM4# T&4M 4#5M 5M4& 4T5M# 4Ms& ;#4L 4L;& 4;#LB a;&4L 45;#L 4&>L 5;#4LB",
+" >&4aL 4#M; +M4& M;#4T aM;4& M;#4j 4M>& 4T5M;# >Ms4& #E4L &E4L H#4L 4LH& 45",
+"#EL 48&EL 4H5#L 4H8&L M#4E 4EM& 4#HM HM4& 4M5#E 48M&E 4HM5# s4HM& d#4L 4Ld&",
+" 4Hd#L 4&gL 4d5#L >&4dL H5#4dL g>4&L 4#dM dM4& 4HMd# 4Mg& 4dM5# >M4d& dM#4H",
+"j >Mg4& 3L#N 3L&N #LN3B a&3LN 3L.#N 8&3LN #L.3BN a&38LN M#Q3 Q3M& QTM#3 aM3",
+"Q& QMj#3 M&3Q8 TMjQ#3 sQM&3 3(N#L +&3LN 3B(#LN a&3+LN #L.3(N 8&3+LN 3LNB#(.",
+" 3L+N8a& QM#3( M&3+Q TM#Q3( +QTM&3 Mj#Q3( +Q8M&3 TMQj#3( M&3s+Q #3WL &3WL H",
+"W#3L H&W3L W#3L. W8&3L W#3HL. W83H&L M#W3 W3M& M#Z3 M&Z3 WMj#3 W8M&3 ZMj#3 ",
+"Z&Ms3 Wd#3L d&3WL Wd#H3L gW&3L d#3WL. W83d&L W3HLd#. W8&g3L dM#W3 dM&W3 ZdM",
+"#3 Z&Mg3 WM#dj3 dM3W&j dMjZ#3 gsMZ&3 m#4L 4Lm& 4m#LB am&4L 45m#L m&L48 5m#4",
+"LB 48am&L 4#Mm Q&4M Mm#4T aMm4& 4Mp# 4Mp& p4TM# p&4sM 4m;#L m&L4+ m;#4LB 4+",
+"am&L 5m;4#L >m4&L mL4B5;# am&>L4 Mm#4; Mm&4+ 4QTM;# 4+TMm& p4M;# >Mp4& M;#p",
+"4T p&4>Ms W#4L 4LW& 4HW#L 4H&WL 4W5#L 4W8&L H5#4WL m&L4H8 4#WM WM4& 4MZ# 4M",
+"Z& p4WM# p&4WM Zp4M# Zp&4M 4#vL 4&vL v4H#L gv4&L v45#L v>4&L 4H5v#L v>&g4L ",
+"4Mv# 4Mv& Zv4M# Zv&4M pv4M# >Mv4& pvMZ4# 4My& U3 U!3 UD3 Ua3 U3. U83 D3U. U",
+"3D8 UM3 M3U! V3 Va3 Uj3 U38M Vj3 Vs3 U3( U+3 D3U( U3+D 3(U. +8U3 UD3(. U+D8",
+"3 M3U( U3+M V3( V+3 j3U( U3+j j3V( s3V+ UE3 !EU3 UH3 HaU3 E3U. 8EU3 H3U. U3",
+"H8 MEU3 U!ME3 VH3 HaV3 jEU3 U8ME3 HjV3 VHs3 Ud3 +dU3 U3Dd gU3 d3U. U38d UHd",
+"3. U8g3 U3dM dM3U+ Vd3 gV3 U3dj U+jd3 djV3 g3Vs 4U 4U! 4UD 4Ua 4U5 4U8 U54D",
+" U54a 4UM U!4M V4 V4a 4Uj U84M V45 s4V 4U; 4U+ U;4D U+4D 45U; >U4 4U5D; 4U>",
+"D U;4M U+4M V4; V4+ U;4j 4U>M 4jV; V>4 4UE U!4E 4UH UH4a 4EU5 4EU8 U54H UH4",
+"8 UM4E 4UM!E V4H 4HVa 4EUj 4U8ME 4HV5 sHV4 4Ud U+4d UH4d g4U U54d 4U>d 4UH5",
+"d >Ug4 Ud4M 4U+dM V4d gV4 Ud4j >M4Ud 4dV5 g4V> U3N !3UN D3UN a3UN N.U3 83UN",
+" UD3N. U8D3N UQ3 U3Q! VQ3 QaV3 QjU3 U3Q8 QjV3 VQs3 3(UN +3UN UD3(N U+D3N U3",
+"(N. U+83N D3(UN. +D3U8N Q3U( U3+Q Q3V( +QV3 UQj3( U+Q83 VQj3( Vs+Q3 UW3 W!U",
+"3 U3WD U3Wa W3U. U3W8 UHW3. UH8W3 U3WM UWQ!3 VZ3 VaZ3 U3Wj UW8Q3 VjZ3 s3VZ ",
+"WdU3 U3+W UHWd3 UWg3 UWd3. U+W83 WD3Ud. gUW83 U3Qd U+WQ3 Z3Vd g3VZ UWjd3 U+",
+"Wj3 VZdj3 gVZs3 4Um 4!Um Um4D Um4a 45Um Um48 4U5Dm 4U8Dm 4UQ Q!4U V4Q 4QVa ",
+"pU4 4Up8 Vp4 s4Vp 4mU; Um4+ 4UDm; 4U+Dm 4U5m; 4U>m U5m4D; >Dm4U U;4Q U+4Q 4",
+"QV; 4+Vm 4Up; p4>U p4V; p>V4 4UW 4!UW UH4W UW4a U54W UW48 4UH5W 4UHW8 UW4Q ",
+"4UWQ! Z4V ZaV4 4UpW pU4W8 Z4Vp VZs4 vU4 4Uv+ 4UvD vUg4 4Uv5 v4>U vU4H5 gvU>",
+"4 4UvM vU4+Q Vv4 g4Vv p4vU >Mv4U pvV4 yV4 bU3 U&3 UDb3 cU3 U3b. b3U8 bUD3. ",
+"U8c3 bM3 b3M& Vb3 Vc3 b3Uj b38M bjV3 s3Vc U3b( b3U+ bUD3( U+c3 bU3(. b+U83 ",
+"UD3b(. cU+83 M3b( b3+M b3V( c3V+ bMj3( b+M83 Vbj3( Vs+c3 UEb3 &EU3 b3UH UHc",
+"3 bUE3. b8UE3 bHU3. cUH83 MEb3 M&Eb3 bHV3 VHc3 bMjE3 b8ME3 VbHj3 VsHc3 b3Ud",
+" U3d& bHUd3 cUg3 bdU3. b8dU3 UH3bd. gcU83 b3dM dM&b3 bdV3 g3Vc bdMj3 d&jU3 ",
+"Vdbj3 gVsc3 4bU 4U& bU4D c4U b54U b84U 4bU5D 4Uc5 4bM bM4& V4b c4V b54M b84",
+"M 4bV5 Vsc4 b;4U b+4U 4bUD; 4Uc; 4bU5; 4b>U b5U4D; >Uc4 b;4M b+4M 4bV; V4c;",
+" 4bM;j 4b>M V4b;j c4V> bU4E 4EU& bH4U 4UcH 4bU5E 4b8UE 4bHU5 c4UH5 4EbM 4bM",
+"&E 4bVH cHV4 4bM5E 4b8ME V4bH5 c4VsH bd4U Ud4& 4bHUd c4gU 4bdU5 >b4Ud bH54U",
+"d c>g4U bd4M dM&4b 4bVd c4gV 4bdUj >Mb4d V4db5 V>gc4 U3bN &3UN bUD3N U3cN b",
+"U3N. b8U3N UD3bN. cU83N b3UQ U3Q& bQV3 VQc3 bQUj3 bQ8U3 VbQj3 cQVs3 bU3(N b",
+"+U3N UD3b(N cU+3N U3(bN. U+3b8N D3UNb(. U+8c3N bQU3( b+QU3 VbQ3( cQV+3 UQ3b",
+"j( &j3U+Q bQjV3( Vs+cQ3 b3UW U3W& bHUW3 UWc3 bWU3. bW8U3 UH3bW. cWU83 b3WM ",
+"bWM&3 VbZ3 Z3Vc bWMj3 bW8M3 ZbVj3 ZcVs3 bWUd3 b+WU3 UHWbd3 cWUg3 UW3bd. d&3",
+"UW8 W.DdbU3 gU8cW3 bWMd3 b+WM3 ZbVd3 gVZc3 dM3bWj dM3bW8 VdjZb3 ZcsgV3 bm4U",
+" Um4& 4bUDm 4Ucm 4bU5m 4b8Um b5U4Dm c4U8m bQ4U UQ4& 4bVm V4cQ 4bpU 4Up& pbV",
+"4 c4Vp 4bUm; 4b+Um bmU4D; c4U+m b5m4U; >b4Um 5mD;4bU c>4Um 4bQU; 4b+UQ V4bQ",
+"; c4V+Q pb4U; >Mbp4 Vp4b; cpV>4 bW4U UW4& 4bHUW 4UcW 4bWU5 4bWU8 bH54UW c4W",
+"U5 bW4M 4bWM& V4Zb VZc4 pb4UW pU&4W ZpbV4 cpZV4 4bvU 4Uv& vb4UH vUc4 vb4U5 ",
+"v>b4U 4bHvU5 cv>4U 4bvM vbM4+ vbV4 c4Vv pvb4U >Mv4b Vvp4b c4yV 6k 6!k 6kB 6",
+"ak 61k 68k 1k6B 8k6a 6M 6M! 6Tk 6aM l6 l68 l6T ls6 6k( 6+k k(6B +k6a 1k6( +",
+"k68 61k(B 6+1ak 6M( 6+M 6(Tk +T6M l6( l+6 6Tl( s6l+ 6kE kE6! 6Hk Hk6a 1k6E ",
+"6E8k 61Hk Hk68 6ME ME6! 6HM HM6a l6E 68lE lH6 s6lH 6dk +k6d Hk6d g6k 61dk 8",
+"k6d 6H1dk 68gk 6dM +M6d HM6d g6M ld6 6+ld 6Hld gl6 4k 4k! 4kB 4ak 7k 78k 7B",
+"k 7ak 4kM 6!4M 4Tk 6a4M 7l 7l8 7lT 7sl 4k; 4+k 4Bk; +k4a 7k; >k7 k;7B 7a>k ",
+"6M; 6+4M Tk6; +T4k l;7 l>7 7Tl; 7sl> 4kE kE4! 4Hk Hk4a 7kE 8k7E 7Hk H87k 4E",
+"6M 4kM!E 6H4M 4HkaM 7lE 78lE lH7 lH7s 4dk +k4d Hk4d g4k 7dk 7d>k Hk7d g7k 6",
+"d4M 4+kdM HM6; 4Tgk ld7 7>ld 7Hld gl7 6kN kN6! kN6B 6Nak 1k6N 6N8k 61kNB ak",
+"N68 6Qk Q!6M Qk6T Qa6M l6Q 6Ql8 6QlT lQs6 k(6N 6N+k 6k(NB akN6+ 61k(N 6+1kN",
+" 1k(6NB 6+1akN 6(Qk +Q6M 6QTk( 6+QTk 6Ql( 6+lQ l6QT( ls6+Q 6Wk 6!Wk Hk6W Wk",
+"6a 61Wk Wk68 6H1Wk 6H8Wk 6WM 6!WM Z6k 6aZk lW6 6Wl8 lZ6 s6lZ Wk6d +k6W 6HWd",
+"k 6Wgk 6W1dk 6+W8k 1HW6dk g61Wk WM6d +W6M 6dZk Z6gk 6Wld 6+lW Z6ld g6lZ 4km",
+" 6!km 4Bkm ak6m 7km 8k7m km7B ak7m 4Qk Q!4k Qk4T Qa4k 7lp l87p lp7T 7lsp km",
+"6; +k6m km;4B akm4+ km7; 7k>m 7Bkm; 7>akm Qk6; +Q4k 4QkT; ak;4Q 7pl; 7pl> 7",
+"lpT; l>p7s 4Wk 4!Wk Hk4W Wa4k 7Wk W87k Hk7W Wa7k 6W4M 4WkQ! Z4k 4aZk lW7 l8",
+"7W 7Zl lZ7s v6k 4+vk 4Hvk v6gk 7vk >k7v vk7H gk7v v6M 6+vM v6Zk Z4gk lv7 7v",
+"l> 7Zlv yl7 69k 6&k 9k6B ak6& 916k :6k 691kB 6a:k 6M9 6M& 9T6M 9a6M l69 l:6",
+" 6Tl9 s6l: 9k6( +k6& 69k(B 6+9ak 691k( 6+:k 91k6(B :6+ak 6(9M 9+6M 6T9k( 6+",
+"T9M 69l( :6l+ l69T( ls:6+ 9k6E 6Ek& 69Hk Hk6& 691kE 6k:E 6H91k 6H:k 6E9M 6E",
+"M& 9H6M HM6& 69lE :6lE 6Hl9 l6:H 69dk dk6& 6H9dk 6&gk 6d91k 6d:k 9H16dk :6g",
+"k 9d6M dM6& 6HM9d 6Mg9 6dl9 l6:d lH69d g6l: 49k 4k& 9k4B 9a4k 79k 7:k 9k7B ",
+":a7k 49M 6M4& 9T4k 9a4M 7l9 l:7 l97T l:7s 9;4k 9+4k k;B49 ak;49 9;7k 7:>k 7",
+"B9k; 7:>ak 9M6; 9+4M 49Tk; aM;49 79l; 7:l> 7l9T; l>7s: 9k4E 4Ek& 9H4k Hk4& ",
+"9k7E :k7E 9H7k 7k:H 4E9M 49M&E 9H4M 49HaM 79lE lE7: l97H 7:lH 9d4k dk4& 49H",
+"dk 49gk 9d7k 7k:d 7H9dk 7:gk 9d4M dk&4M 49HdM 49gM l97d 7:ld 7Tdl9 l:g7 9k6",
+"N 6Nk& 69kNB akN6& 691kN 6k:N 91k6NB :6akN 9Q6M Qk6& 6Q9Tk 6Qa9M 6Ql9 l6:Q ",
+"l69QT :Q6ls 69k(N k&N6+ 9k(6NB 6+9akN 91k6(N :6+kN 916k(BN akN:6+ 6Q9k( 6+Q",
+"9M 9QT6M( 9+Q6aM l69Q( :Q6l+ 6Q9lT( ls6:Q+ 69Wk Wk6& 6H9Wk 6H&Wk 6W91k 6W:k",
+" 9H16Wk :H6Wk 9W6M WM6& 6MZ9 6MZ& 6Wl9 l6:W l6Z9 Z6l: 6W9dk dk&6W 9HW6dk g6",
+"9Wk 9W16dk :W6+k 691HWkd g:6Wk 6WM9d dk&6Q Z69dk Z6&gk lW69d :Qdl6 lZ69d gl",
+"Z:6 9m4k km4& kmB49 akm49 9m7k 7k:m 7B9km 7:akm 9Q4k Qk4& 49QTk aMm49 p97l ",
+"7l:p 7lp9T 7sl:p km;49 km&4+ 49mk;B 49+akm 79km; 7:>km km;7B9 :>m7ak 49Qk; ",
+"k;&4Q 9Q;4Tk 49+aMm 7lp9; l>p7: l;p7T9 7spl>: 9W4k Wk4& 49HWk km&4H 9W7k 7k",
+":W 7H9Wk 7:HWk 9W4M Mm&6W 49Zk 4kZ& l97W 7:lW Z97l l:7Z 49vk 4kv& v69Hk gv6",
+"k& 79vk vk7: 7v9Hk :vkg7 49vM 6Mv& Zv69M Zv6k& v97l l:7v lvZ79 l:y7 6U 6U! ",
+"6UD 6Ua 6U1 6U8 1U6D 1U6a 6UM U!6M V6 V6a l6U 6Ul8 Vl6 s6V 6U( 6U+ 6(Dk U+6",
+"D 6(1U 1U6+ 6U1D( 6U+1D UM6( U+6M V6( V6+ 6Ul( 6Ul+ l(V6 V6l+ 6UE U!6E 6UH ",
+"UH6a 6E1U 6EU8 1U6H UH68 UM6E 6UM!E V6H 6HVa 6UlE l6U8E V6lH sHV6 6Ud U+6d ",
+"UH6d g6U 1U6d U86d 6UH1d 6Ug1 Ud6M 6U+dM V6d gV6 6Uld l+6Ud V6ld s6gV 4U6 6",
+"!4U 4Dk 6U4a 7U 7U8 7UD 7Ua 6U4M 4U6M! V46 4aV6 7lU l87U 7V 7Vs 6U; 6U4+ U;",
+"6D Ua6; 7U; 7>U U;7D 7D>k U;6M 4U+6M V6; 4+V6 7Ul; 7Ul> 7V; 7V> 4E6U 4U6!E ",
+"6U4H 4UH6a 7UE U87E 7UH UH7a 4U6ME 6UE4M! 4HV6 V46Ha lE7U 7lU8E 7VH Vs7H 6U",
+"4d 4U+6d UH6; 4Ug6 7Ud >U7d UH7d g7U 4Ud6M 6U+4dM 4dV6 V4g6 7Uld l>7Ud 7Vd ",
+"g7V 6UN U!6N 6NDk 6NUa 6N1U 6NU8 6U1DN 6U8DN 6UQ Q!6U V6Q 6QVa 6UlQ UQ68 lQ",
+"V6 sQV6 U(6N 6NU+ 6UD(N 6U+DN 6U1(N 6U+1N 1U(6DN 6UN1+D 6(UQ U+6Q 6QV( 6+VQ",
+" l6UQ( l+6UQ Vl6Q( l+V6Q 6UW 6!UW UH6W UW6a 1U6W UW68 6UH1W 6UHW8 UW6Q 6UWQ",
+"! Z6V ZaV6 6UlW lW6U8 VlZ6 VZs6 UW6d U+6W 6UHWd 6UgW 6UW1d 6U+1W 1UW6Dd g6U",
+"1W UQ6d 6U+WM VdZ6 Z6gV lW6Ud l+W6U Z6Vld gV6lZ 6Um 6!Um Um6D Ua6m 7Um U87m",
+" Um7D Ua7m 6U4Q 4UQ6! V6m 6aVm 7pU 78pU 7Vp Vp7s Um6; U+6m 4Dkm; 4+Dkm Um7;",
+" >m7U 7UDm; 7>UDm UQ6; 4U+6Q 6QV; 6+Vm 7;pU p>7U V;7p 7pV> 6U4W 4UW6! UH6m ",
+"4UW6a 7UW UW78 UH7W UW7a 4UW6Q Mm!6UW V4Z6 Z4V6a 7UlW 7pUW8 7ZV sZ7V v6U 6U",
+"v+ 4Dvk v6gU 7vU v>7U vU7H gU7v 6UvM v6U+Q Vv6 g6Vv 7Ulv 7vUl> 7Vv y7V t6 t",
+"6& t6D tc6 t61 t:6 6Dt1 c6t: t6M 6Mt& Vt6 c6V lt6 l6t: V6lt u6 t6( t+6 6Dt(",
+" c6t+ 61t( :6t+ t61D( t:c6+ 6Mt( 6+tM t(V6 V6t+ t6l( l6t+ ltV6( u6+ t6E 6&t",
+"E tH6 c6tH 61tE :6tE 6Ht1 t6:H 6MtE t6M&E V6tH cHV6 t6lE t:6lE l6tH u6H td6",
+" 6+td 6Htd gt6 6dt1 t6:d tH61d t:g6 6dtM t+6dM V6td c6gV l6td t:dl6 tdVl6 u",
+"g6 t4 t4& t4D tc4 7t 7t: 7tD 7ct t4M 4Mt& t4V Vtc4 7tl l:7t 7Vt u7 t4; t4+ ",
+"4Dt; c4t+ 7t; t>7 7Dt; 7ct> 4Mt; 4+tM V4t; V4t+ l;7t 7tl> t;7V u7> t4E 4&tE",
+" t4H c4tH 7tE tE7: 7tH tH7c 4MtE t4M&E V4tH tc4VH lE7t 7tl:E lH7t u7H t4d 4",
+"+td 4Htd gt4 7td 7:td 7Htd g7t 4dtM t4+dM V4td t4gV ld7t 7tdl> td7V ug7 t6N",
+" 6&tN 6DtN tNc6 61tN :6tN t61DN t:c6N tQ6 6Qt& V6tQ c6tQ l6tQ t6:Q tQVl6 u6",
+"Q 6(tN 6+tN t6D(N tc6+N t61(N t:6+N 6D1t(N :c6t+N 6Qt( 6+tQ tQV6( tcQ6+ tQ6",
+"l( t:Q6+ Vl6tQ( 6+uQ tW6 6Wt& 6HtW c6tW 6Wt1 t6:W tH61W t:H6W 6WtQ tW6Q& tZ",
+"6 Z6tc l6tW t:Wl6 Z6lt uZ6 6Wtd 6+tW tH6Wd tWg6 tW61d t:W6+ 6WDtd1 gt:6W 6Q",
+"td t+W6Q Z6td g6tZ tQdl6 t:Q6d tZl6d gZu6 t4m 4&tm 4Dtm c4tm 7tm 7:tm 7Dtm ",
+"tm7c t4Q 4Qt& V4tQ c4tQ tp7 :p7t 7Vtp up7 6mt; 4+tm t4Dm; tc4+m 7mt; 7>tm 7",
+"tDm; t>7cm 4Qt; 4+tQ t4VQ; tc4+Q 7pt; 7pt> tp7V; 7pu> t4W 4Wt& 4HtW c4tW 7t",
+"W 7:tW 7HtW tW7c 4WtQ t4WQ& tZ4 t4Zc lW7t 7tW:p tZ7 uZ7 tv4 v6t+ v6tH g4tv ",
+"tv7 7t:v tH7v tvg7 v6tQ tv4+Q t4Vv g4tZ 7tlv lvt7: 7Ztv yu7 < <! <B a< <. 8",
+"< <.B 8<a <K <K! T< T<a <j 8<j T<j s< <* +< *B< +<a <*. +<8 <.*B a<8* <*K +",
+"<K T<* +T< <j* +<j <jT* s<+ <E <E! H< H<a <E. 8<E H<. H8< <EK EK<! H<T HTa<",
+" <jE 8E<j H<j s<H <d +<d H<d g< <d. 8<d H.<d g<8 <dK +K<d T<d g<T <dj <d+j ",
+"<dHj gs< 4< 4<! 4<B 4a< 5< 48< 5<B 5a< 4<K <K4! 4T< T<4a 4j< 8<4j 5T< s4< =",
+" =+ =B =a =5 >= =B5 =a> =K =+K =T =T+ =j =j> =T5 s= 4<E <E4! 4H< H<4a 5<E 4",
+"E8< H5< H<48 <E4K 4<E!K H<4T 4HTa< 4E<j <jE48 H<4j 4Hs< =d =+d =H g= =5d >=",
+"d =H5 g=> =dK +d=K =HT g=T =jd =d>j =Hj s=g <N <N! <NB a<N <N. 8<N .B<N aN8",
+"< Q< Q<! Q<T Qa< Q<j Q8< QT<j s<Q <*N +<N <N*B +Na< *N<. +N8< *B<N. a*N8< Q",
+"<* +Q< T<Q* Qa+< <jQ* Q8+< <j*QT +Qs< W< W<! H<W Wa< W<. W8< H.W< W8H< W<Q ",
+"Q!W< Z< Z<a W<j Q8W< Z<j sZ< W<d +W< W<H* g<W W.<d W8+< <d.HW W8g< Q<d W<+Q",
+" Z<d gZ< <dWj W<+j <dZj sZg< <m <m! <mB a<m 5<m 8<m 5B<m a<8m 4Q< Q!<m T<m ",
+"Q<4a p< p<8 p<T sp< =m =+m =Bm =am =5m >=m 5m=B >m=a =Q =Q+ =QT =Qa p= p=> ",
+"p=T s=p 4W< 4!W< H<m W<4a 5W< W85< 5WH< Wa5< W<4Q <m!WQ Z4< 4aZ< p<W W8p< Z",
+"p< Zps< v= v=+ =Hv g=v v=5 v>= vH=5 v>g= =Qv v+=Q Z= Z=g p=v v>p= Z=p y= ,<",
+" <& ,<B ,a< ,<. ,8< <.,B 8<,a ,<K <&K ,T< T<& ,j< <&j T<,j s<& ,<* -< ,<*B ",
+"-a< <*,. -8< *B<,. 8<-a <*,K -<K ,<T* -T< ,<*j -j< <j*,T s-< ,<E <&E ,H< H<",
+"& <E,. ,E8< ,.H< H<,8 <E,K &E<K H<,T T<H& ,E<j <E&j H<,j ,Hs< ,d< -<d H<,d ",
+"g-< ,.<d 8<-d <d.,H -8g< ,K<d <d-K T<,d -Tg< <d,j <d-j <dj,H g<s- ,4 ,4& ,4",
+"B ,4a ,45 ,48 4B,5 48,a ,4K ,K4& ,4T 4T,a ,4j 48,j 4T,5 s4, =, -= =B, =a- =",
+"5, ->= ,5=B ->=a =,K -=K =T, =T- =j, =j- ,5=T s=- ,4E ,E4& ,4H 4H,a ,E5< ,E",
+"48 4H,5 4H,8 4E,K <&E4K 4H,T ,4HT& ,E4j <&j4E 4H,j ,4sH =d, -=d =H, g=- ,5=",
+"d =d-> ,H=5 ->g= ,d=K -d=K ,H=T g-=T ,d=j =d-j ,H=j s-g= ,<N <&N <N,B ,Na< ",
+"<N,. ,N8< ,<N.B <&N8a ,Q< Q<& Q<,T Q<,a Q<,j Q<,8 ,QT<j ,Qs< <*,N -<N *B<,N",
+" a<-N ,<*N. 8<-N ,<N*B. -8a<N ,<Q* -Q< ,QT<* Qa-< <j*,Q Q8-< ,QT<j* -Qs< ,W",
+"< W<& H<,W W<,a ,.W< W<,8 ,HW<. ,H8W< W<,Q Q<W& Z<, Z<& W<,j <&Wj ,jZ< Z<s,",
+" W<,d -W< ,HW<d -Wg< <d.,W W8-< ,HW<d. -W8g< Q<,d W<-Q ,dZ< Z-< <dj,W W<-j ",
+"Z<d,j s<Z- ,4m <m& 4B,m 4a,m 5<,m 48,m <mB,5 <m&5a ,4Q 4&,Q 4Q,T 4Q,a p<, p",
+"<& ,4pT p<s, =m, -=m ,m=B -m=a ,5=m >=-m =B5,m =a->m =Q, =Q- ,Q=T -Q=T p=, ",
+"-p= p,=T -ps= ,4W 4&,W 4H,W 4W,a 4W,5 4W,8 ,4H5W <m&H5 4W,Q <m&WQ Z4, ,4Z& ",
+",4pW W<p& p<Z, Z4s, v=, -v= v,=H -vg= =5v, v>-= =Hv,5 g=-v> v,=Q =Q-v Z=, Z",
+"-= v=p, p=-v Z,p= y-= <C <C! D< D<a <C. 8<C D<. D8< <CK CK<! D<T DTa< <jC 8",
+"C<j D<j s<D <*C +<C D<* +D< *C<. +C8< <*D. D8+< *C<K <C+K T<D* D<+T <C*j +C",
+"<j <jD* +Ds< <CE !C<E H<D HDa< CE<. <C8E H.D< D8H< EK<C <CE!K HDT< H<DTa jC",
+"<E <jC8E D<Hj H<sD <dC +C<d D<d g<D dC<. 8C<d D.<d D8g< <CdK <dC+K T<Dd D<g",
+"T <Cdj <dj+C <dDj gDs< 4<C <C4! 4D< D<4a 5<C 4C8< 5D< D85< <C4K 4<C!K D<4T ",
+"4DTa< 4C<j <jC48 D<4j 4Ds< =C =+C =D =D+ =5C >=C =D5 =D> =CK +C=K =DT +D=T ",
+"=jC >C=j =Dj s=D <C4E 4<C!E H<4D 4HDa< <C5E 48<CE 5DH< 4H8D< 4<CEK <CE4K! 4",
+"HDT< H<D4Ta <jC4E 48C<jE 4HjD< s<H4D =dC +d=C =HD g=D 5d=C =d>C H5=D g>=D d",
+"K=C =+dCK Dd=T gD=T dj=C =j>dC Hj=D gs=D <CN !C<N D<N DNa< N.<C <N8C <ND. D",
+"N8< Q<C <CQ! QD< D<Qa QC<j QC8< DjQ< QDs< *C<N <C+N <*DN +ND< <*CN. +<8CN D",
+"<*N. +D<8N <*QC +CQ< D<Q* QD+< <j*QC +Q<8C QD<*j s<+QD W<C <CW! WD< D<Wa <C",
+"W. WC8< W.D< D8W< WCQ< W<Q!C Z<D D<Za WC<j W8<QC D<Zj sDZ< WC<d +CW< D<W* W",
+"Dg< <dCW. +W<8C WD<d. g<WD8 QC<d +W<QC D<Z* gDZ< <djWC +W<jC Z<Ddj gZ<sD <m",
+"C <!mC D<m a<Dm 5C<m 8C<m Dm5< 8<Dm 4CQ< <mCQ! Q<4D 4QDa< p<C 8<pC pD< pDs<",
+" =mC +m=C =Dm +D=m 5m=C =m>C 5D=m >m=D =QC +Q=C =QD +Q=D p=C >Cp= p=D sp=D ",
+"4CW< <mCW! W<4D 4WDa< 5CW< 4W8<C WD5< 4WD8< <mCWQ W<C4Q! 4DZ< Z4Da< W<pC p<",
+"W8C pDZ< Zp<sD v=C v+=C =Dv gv=D v5=C >Cv= =5vD v>=D vQ=C =Qv+C Z=D =DgZ =C",
+"pv p=v>C Zp=D y=D b< b<& ,D< c< b<. b8< ,.D< c<8 b<K bK<& bT< c<T b<j 8<bj ",
+"D<,j sc< b<* -b< D<b* c-< <*b. b8-< ,D<*. -8c< <*bK b<-K T<b* -Tc< <jb* b<-",
+"j ,Dj<* c-s< b<E bE<& bH< c<H <Eb. bE8< b.H< H8c< <EbK <&EbK H<bT H<cT bE<j",
+" <&jbE H<bj sHc< b<d b<-d H<bd gc< b.<d 8<bd ,Dd<. g8c< bK<d -b<dK T<bd gTc",
+"< <dbj -jb<d <dj,D scg< ,4b b<4& ,4D c4< b5< 4b,8 4D,5 c5< ,K4b <&K4b 4b,T ",
+",4cT 4b,j <&j4b 4D,j c4s< =b =b- =bD c= =b5 =b> ,5=D c=> =bK -b=K =bT c=T =",
+"bj -j=b ,D=j s=c ,E4b <&E4b 4b,H ,4cH bE5< ,48bE H5b< H5c< ,4bEK 4bE<&K ,4H",
+"bT c4H,T ,4jbE <&E4bj ,4Hbj c5<sH =bd -b=d =bH c=g b5=d =d>b bH=5 c>g= bd=K",
+" =b-dK bH=T gc=T bd=j =b>dj bH=j gsc= b<N bN<& ,ND< c<N <Nb. bN8< ,D<N. 8<c",
+"N bQ< Q&b< QDb< cQ< Q<bj Q8b< ,QD<j cQs< <*bN b<-N ,D<*N -<cN b<*N. -b8<N D",
+"<Nb*. c-8<N Q<b* bQ-< ,QD<* -Qc< bQ<*j -Qb8< QD<b*j s-cQ< bW< W&b< H<bW cW<",
+" b.W< W8b< ,WD<. W8c< W<bQ bW<Q& Zb< Zc< W<bj <&jbW b<Zj s<Zc W<bd bW-< ,WD",
+"<d cWg< bW<d. -Wb8< <d.,WD c-W8< Q<bd -WbQ< b<Z* g<Zc <djbW -Wjb< Zb<dj Zc<",
+"s- b<m <&bm 4D,m c<m 5<bm 8<bm ,4D5m 5<cm 4b,Q <m&bQ 4Q,D ,4cQ pb< b8p< ,4p",
+"D cp< =bm -m=b ,D=m c=m b5=m >m=b =b5Dm >=cm =bQ -Q=b ,Q=D c=Q p=b =b-p pb=",
+"D cp= 4b,W <m&bW 4W,D ,4cW 5Wb< ,4Wb8 ,4W5D 5Wc< ,4WbQ bW<4Q& ,4Zb c4Z< bWp",
+"< pb<W8 pbZ< Z<cp =bv =b-v vb=H cv= =5vb v>=b =bvH5 v>c= vb=Q -v=bQ Z=b Z=c",
+" pv=b -pv=b Zp=b yc= 6< 6!< 6<B 6a< 1< 68< 1<B 1a< 6<K <K6! 6T< T<6a 6j< 8<",
+"6j 1T< s6< 6* 6+< 6*B 6a* 6*1 68* *B1< 1a6* 6*K 6K+< 6T* +T6* 6*j +<6j 1T6*",
+" s6* 6<E <E6! 6H< H<6a 1<E 6E8< 1H< H81< <E6K 6!<EK H<6T 6HTa< 6E<j <jE68 H",
+"<6j 6Hs< 6d< +<6d 6H* g6< 1<d +<1d 1H6* g1< 6K<d <dK6+ H*6T 6Tg< <d6j <dj6+",
+" H*6j s6g< 46< 4<6! 6<4B 46a< 7< 78< 7B< 7a< 6<4K 6!4<K 46T< 4T6a< 7<j 8<7j",
+" 7T< 7s< =6 =6+ =B6 =a6 7= 7>= 7=B =a7 =6K 6+=K =T6 6+=T =j7 7>=j =T7 s=7 6",
+"<4E 6!4<E 46H< 4H6a< 7<E 8<7E 7H< H87< 46<EK 4<E6!K 4H6T< 6HT4a< <j7E 78<jE",
+" H<7T 7Hs< =6d 6+=d =H6 g=6 7=d >=7d =H7 g7= 6d=K =6+dK 6H=T g6=T 7d=j 7>=d",
+"j 7H=T s=g7 6<N <N6! <N6B 6Na< 1<N 6N8< <N1B 1Na< 6Q< 6!Q< Q<6T Q<6a 1Q< Q8",
+"1< Q<1T 6Qs< 6*N 6N+< 6N*B 6Na* 6N1* 6N8* 6*1NB 68*aN 6Q* +Q6* Q*6T Qa6* 1Q",
+"6* +Q1< 6Q*1T 6Qs* 6W< 6!W< H<6W W<6a 1W< W81< H<1W Wa1< W<6Q 6WQ<! Z6< 6aZ",
+"< W<6j 6W8Q< Z1< Z6s< 6W* +W6* H*6W 6Wg< 1W6* +W1< 6H*1W 1Wg< W*6Q 6+WQ< Z6",
+"* Z6g< W*6j 6+W<j 6*Z1 Z6s* 6m< 6!<m 6B<m a<6m 7<m 8<7m <m7B a<7m Q<6m <m!6",
+"Q T<6m 4Qa6< 7p< 78p< p<7T 7ps< =6m 6+=m 6m=B 6a=m 7=m >m7= =m7B =m7a =Q6 6",
+"+=Q 6Q=T 6Q=a p=7 7>p= 7p=T p=7s W<6m <m!6W H<6m 4Wa6< 7W< W87< H<7W Wa7< 4",
+"WQ6< 6WQ<m! 6mZ< Z46a< p<7W 7pW8< 7Z< s<7Z v=6 =+v6 v6=H v=g6 7v= v>7= =H7v",
+" 7vg= v6=Q =Qv6+ Z=6 g6Z= p=7v 7p>v= 7Z= y7= ? ?& ?B ?a ?1 ?: ?B1 ?:a ?K ?&",
+"K ?T ?Ta ?j ?:j ?T1 s? ?* ?- ?B* ?-a ?1* ?:- 1*?B :-?a ?*K ?-K ?T* ?-T ?j* ",
+"?-j 1T?* s?- ?E ?&E ?H ?Ha ?1E ?:E ?H1 ?:H ?EK &E?K ?HT H&?T ?jE :j?E ?Hj s",
+"?H ?d ?-d ?Hd g? ?d1 ?:d 1H?d g?: ?dK -d?K ?Td g?T ?dj :d?j 1T?d g?s ?4 ?4&",
+" ?B4 ?a4 7? ?:7 7?B ?a7 ?4K 4&?K ?T4 4T?a ?j7 7:?j ?T7 s?7 ?= ?-= ?=B =a? ?",
+"=7 A =B7? Aa ?=K =K?- =T? ?-=T =j? Aj ?T=j As ?4E 4&?E ?H4 4H?a 7?E ?E7: ?H",
+"7 7:?H 4E?K ?4&EK 4H?T ?H4T& 7j?E ?:7jE 7H?T ?H7s ?=d -=?d =H? g?= ?d7 Ad 7",
+"?=H Ag =K?d ?-=dK ?H=T =Tg? ?d=j Ajd ?H=j Ags ?N ?&N ?BN ?aN ?1N ?:N 1N?B :",
+"a?N ?Q ?Q& ?QT ?Qa ?Q1 ?:Q 1Q?T s?Q ?*N ?-N *B?N -a?N 1*?N ?N:- ?B1*N ?:-aN",
+" ?Q* ?-Q Q*?T -Q?T 1Q?* :-?Q ?Q1T* ?Qs- ?W ?W& ?HW ?Wa ?W1 ?:W 1H?W :H?W ?W",
+"Q W&?Q ?Z ?Za ?Wj :W?Q ?Z1 s?Z ?Wd ?-W H*?W g?W 1W?d :-?W ?H1W* ?Wg: ?Qd -W",
+"?Q ?Zd g?Z 1Q?d :Q?d Z1?d Z:g? ?m ?m& ?mB ?am ?m7 ?:m 7B?m 7a?m ?Q4 4Q?& ?T",
+"m 4Q?a ?p ?p: ?pT s?p ?=m ?-m =B?m ?m=a 7=?m Am ?=7mB Aam =Q? ?-=Q ?Q=T ?Q=",
+"a ?p= Ap =T?p Aps ?W4 4W?& ?Hm 4W?a ?W7 7:?W 7H?W 7W?a 4W?Q ?W4Q& ?Z4 Z4?a ",
+"?pW ?W:p ?Zp 7Zs? ?v ?v- ?vH g?v ?v7 Av ?H7v Agv ?vQ ?Q-v ?Zv Z-?v ?pv Apv ",
+"7Z?v yA 6<C <C6! 6D< D<6a 1<C 6C8< 1D< D81< <C6K 6!<CK D<6T 6DTa< 6C<j <jC6",
+"8 D<6j 6Ds< 6*C 6C+< 6D* +D6* 6C1* 6C8* 1D6* +D1< *C6K 6+<CK D*6T 6+DT< 6C*",
+"j 6+j<C D*6j 6Ds* <C6E 6!<CE H<6D 6HDa< <C1E 68<CE H<1D 6H8D< 6<CEK <CE6!K ",
+"6HDT< H<D6Ta <jC6E 68C<jE 6HjD< s<H6D 6C<d <dC6+ H*6D 6Dg< 1C<d 68d<C D<1d ",
+"1Dg< <dC6K 6+C<dK 6H*DT g6DT< <dj6C <dC6+j <dj6D gs6D< 6<4C 6!4<C 46D< 4D6a",
+"< 7<C 8<7C 7D< D87< 46<CK 4<C6!K 4DT6< 6DT4a< <j7C 78<jC D<7T 7Ds< =6C 6+=C",
+" =D6 6+=D 7=C >C7= =D7 7>=D 6C=K =6+CK 6D=T =D6+T 7j=C 7>=jC 7D=T =D7s 46<C",
+"E 4<C6!E 4H6D< 6HD4a< <C7E 78<CE H<7D 7HD8< 6<C4EK 4<6!EKC 6HD4T< HD6a4T< 7",
+"<jCE <jC78E 7HDT< 7sHD< 6d=C =6+dC 6H=D g6=D =C7d 7>=dC 7H=D =Dg7 =6dCK 6+d",
+"=CK =H6DT g=6DT 7=djC =j>7dC 7Dd=T g7s=D <C6N 6!<CN 6ND< 6Da<N <C1N 68<CN 1",
+"ND< 6D8<N 6CQ< 6Q<!C Q<6D 6QDa< 1CQ< 6Q8<C QD1< s<Q6D *C6N 6+<CN 6ND* 6+D<N",
+" 6*1CN 68*CN 6D*1N 6D8*N 6CQ* 6+Q<C QD6* 6+QD< 6Q*1C 6Q8*C 6QD1* s6*QD 6CW<",
+" 6W<!C W<6D 6WDa< 1CW< 6W8<C WD1< 6WD8< 6WQ<C W<C6Q! 6DZ< Z6Da< 6Wj<C <jC6W",
+"8 1DZ< Z1<sD 6CW* 6+W<C WD6* g6WD< 6W*1C 6W8*C 6WD1* g1<WD 6W*QC <dC6+Q 6DZ",
+"* Z6*gD 6W*jC <dC6Q8 Z6*1D Z6*sD 6C<m <mC6! D<6m 6Dma< <m7C 78<mC D<7m 7D8<",
+"m <mC6Q 6QC<m! 4QD6< QD<6am 7Cp< 7p8<C p<7D 7pDs< 6m=C =6+mC 6D=m =D6+m 7m=",
+"C 7>=mC =m7D 7>D=m 6Q=C =Q6+C 6Q=D =QD6+ =C7p 7p>=C 7p=D p=D7s <mC6W 6WC<m!",
+" 4WD6< WD<6am W<7C 7W8<C WD7< 7WD8< 6WQ<mC WQ4C6!< Z46D< 6DmZ<a 7pW<C p<87W",
+"C Z<7D 7ZsD< =Cv6 v=6+C v6=D g=v6D =C7v 7v>=C =D7v 7vDg= =Qv6C v6+=QC Z6=D ",
+"Z=g6D 7vp=C p=>7vC =D7Z =Dy7 ?b ?b& ?D ?c ?b1 ?:b ?D1 ?c: ?bK bK?& ?DT ?cT ",
+"?jb :b?j ?Dj s?c ?b* ?-b ?D* ?c- b1?* ?b:- 1D?* :c?- b*?K -b?K bT?* c-?T b*",
+"?j ?b-j D*?j ?cs- ?bE b&?E ?Hb ?cH b1?E :b?E b1?H :c?H bK?E ?b&EK bH?T cH?T",
+" bj?E ?:bjE bH?j ?Hsc ?db -b?d ?Dd g?c b1?d ?b:d 1D?d ?cg: bd?K ?-bdK bT?d ",
+"?Tgc bd?j ?:dbj Dd?j gs?c ?4b 4b?& ?D4 ?c4 7?b 7b?: ?D7 7c? 4b?K ?4b&K 4b?T",
+" c4?T 7b?j ?:7bj 7b?T 7cs? =b? ?-=b =D? c=? =b7 Ab 7?=D Ac ?b=K ?-=bK ?D=T ",
+"=T?c ?j=b Ajb ?D=j Asc 4b?E ?4b&E 4b?H c4?H ?E7b ?:7bE 7b?H ?H7c ?4bEK 4b&?",
+"EK ?H4bT ?c4HT ?j7bE 7:b?jE ?H7bT s?7cH ?d=b ?-=bd ?H=b c=g? 7b?d Abd 7b=H ",
+"Agc ?=dbK =b-?dK ?Dd=T c=?gT ?d7bj bdAj ?Hj=b gsAc ?bN b&?N ?DN ?cN b1?N :b",
+"?N 1D?N ?N:c ?Qb bQ?& ?QD ?cQ b1?Q ?b:Q 1Q?D ?Qsc b*?N -b?N D*?N ?Nc- ?b1*N",
+" ?:-bN ?D1*N ?c:-N bQ?* ?b-Q QD?* c-?Q ?Qb1* ?:Q-b ?QD1* ?cQs- ?Wb bW?& ?WD",
+" ?cW b1?W ?b:W 1W?D :c?W bW?Q ?WbQ& ?Zb ?Zc bW?j ?:WbQ Zb?j ?cZ: bW?d ?b-W ",
+"WD?d ?Wgc ?Wb1d ?:W-b ?WD1d ?cWg: bQ?d ?-WbQ Zb?d ?cZ- ?Wjbd ?:Qbd ?Zb1d g?",
+"Zsc ?mb bm?& ?Dm ?cm 7b?m ?b:m 7D?m ?m7c 4b?Q ?Q4b& 4Q?D c4?Q ?pb pb?: ?pD ",
+"?pc ?m=b ?b-m ?m=D ?mc= =m7b Abm ?D7=m Acm ?Q=b ?-Q=b ?Q=D =Q?c =b?p Apb =D",
+"?p Apc 4b?W ?W4b& 4W?D c4?W 7b?W ?:W7b 7W?D ?W7c ?W4bQ 4bW?Q& Z4?D ?mZc pb?",
+"W ?p:bW ?D7Z 7c?Z ?vb vb?- ?vD ?vc =b7v Avb ?D7v Acv vb?Q ?v-bQ =b?Z cv?Z p",
+"b?v pvAb =b7Z yAc <L <L! <LB a<L <L. 8<L .B<L 8La< <M <M! T<M a<M <Mj 8<M T",
+"M<j s<M <*L +<L <L*B +La< *L<. +L8< *B<L. a*L8< <M* +<M <MT* T<+M M*<j 8<+M",
+" <M*Tj +<sM <EL !E<L H<L HLa< EL<. <E8L <LH. HL8< <ME <!ME H<M a<HM Mj<E 8E",
+"<M <MHj H<sM <dL +L<d HL<d g<L dL<. 8L<d <dLH. 8<gL <dM <d+M <dHM g<M dM<j ",
+"<d8M <dMHj s<gM 4<L <L4! <L4B 4La< 5<L 4L8< <L5B 5La< 4M< 4!<M T<4M a<4M 5<",
+"M 8<4M T<5M 4Ms< =L =+L =BL =aL =5L >=L 5B=L >L=a =M =M+ =TM =aM =M5 >M= 5T",
+"=M s=M <E4L 4<E!L 4LH< 4Ha<L <E5L 48<EL HL5< 4H8<L 4E<M <ME4! H<4M 4HMa< 5E",
+"<M 48M<E 5<HM s<H4M =dL +d=L =HL g=L 5d=L =d>L H5=L >Lg= =Md +M=d =HM g=M 5",
+"d=M =d>M H5=M >Mg= <LN !L<N NB<L <LaN N.<L <N8L <LN.B 8<aLN Q<M Q!<M QT<M a",
+"MQ< QM<j 8MQ< <MjQT Q<sM *L<N <L+N *B<LN a*L<N <*LN. +<8LN <LN*B. 8<La*N <M",
+"Q* Q<+M <M*QT aM*Q< <M*Qj +Q<8M Q<TM*j s<+QM W<L <LW! HLW< WLa< <LW. WL8< H",
+"<WL. H8<WL W<M W!<M Z<M a<ZM <MWj 8<WM <MZj sMZ< WL<d +LW< <dLHW W<gL <dLW.",
+" +W<8L W<LH*. g<W8L <dWM W<+M <dZM Z<gM <dMWj <dMW8 Z<dMj gZ<sM <mL <!mL mL",
+"<B aL<m 5L<m 8L<m <mL5B 5a<mL <Mm <!Mm <MTm <Mam p<M 8<pM T<pM sMp< =mL +m=",
+"L mL=B am=L 5m=L =m>L =B5mL =a>mL =QM +Q=M Tm=M Qa=M p=M >Mp= pT=M sp=M 4LW",
+"< <mLW! HL<m 4Wa<L 5LW< 4W8<L H5<WL H8<mL W<4M <MmW! 4MZ< Z4a<M W<pM p<W8M ",
+"ZMp< Zp<sM v=L v+=L vH=L =Lgv v5=L >Lv= =Hv5L g=v>L =Mv =+vM Z=M =MgZ pv=M ",
+"v>=M Zp=M y=M ,<L <&L <L,B ,La< <L,. ,L8< ,<L.B <&L8a ,M< <M& T<,M a<,M <M,",
+"j 8<,M <Mj,T ,Ms< <*,L -<L *B<,L a<-L ,<*L. 8<-L ,<L*B. -8a<L ,<M* -M< <M*,",
+"T T<-M <M*,j 8<-M ,T<M*j -Ms< <E,L &E<L ,LH< HL<& ,<EL. <&E8L ,H<L. ,H8<L ,",
+"E<M <EM& H<,M <MH& <Mj,E <M&8E ,HM<j s<H,M ,L<d <d-L <dL,H -<gL <dL,. -8<dL",
+" ,HL<d. g-8<L <d,M <d-M <dM,H -Mg< <dM,j -M8<d ,HM<dj s-g<M ,4L ,L4& 4B,L ,",
+"L4a ,L5< ,L48 ,45LB ,48aL ,4M 4&,M 4T,M 4a,M 4M,5 48,M ,4T5M ,4sM =,L -=L ,",
+"L=B -a=L ,5=L >L-= =B5,L =a->L =M, =M- ,T=M -T=M ,5=M ->=M =T5,M =Ms- 4E,L ",
+"<&E4L ,L4H ,4HaL ,45EL ,48EL ,4H5L ,4H8L ,E4M <M&4E 4H,M <M&4H ,4M5E <M&5E ",
+",4H5M s4,HM ,d=L -d=L ,H=L =Lg- =5d,L ->=dL =H5,L g=->L ,d=M =d-M ,H=M g-=M",
+" =M5,d >M-=d =HM,5 g=Ms- <L,N &L<N ,<LNB <&LaN ,<LN. <&L8N <LN,.B 8<L,aN Q<",
+",M <MQ& ,QT<M <M&Qa <Mj,Q <M&Q8 ,QT<Mj s<Q,M ,<*LN <L-N ,<L*BN -a<LN <*L,N.",
+" -8<LN NB*L,<. 8<a-LN <M*,Q Q<-M ,QT<M* -QT<M ,Q<M*j -Q8<M QTM*,j< s-Q<M ,L",
+"W< WL<& ,HW<L ,Wa<L ,W<L. ,W8<L H<L,W. ,HLW8< W<,M <MW& ,MZ< <MZ& ,WM<j <M&",
+"W8 Z<M,j Z<&sM <dL,W W<-L ,HW<dL -W<gL ,WL<d. -W8<L W.<d,HL g<8-WL <dM,W W<",
+"-M Z<d,M -MZ< ,WM<dj -WM8< <dMZ,j Z-s<M ,L<m <Lm& <mL,B <m&aL <mL,5 <m&5L ,",
+"5L<mB amL,48 4Q,M Mm<& <Mm,T aMm,4 ,4pM <Mp& p<T,M p<&sM ,m=L =L-m =Bm,L =a",
+"-mL =5m,L ->=mL ,5m=BL ->m=aL ,Q=M -Q=M =QT,M =Q-aM p,=M =M-p p=T,M -ps=M ,",
+"L4W <m&WL ,4HWL <m&HL ,4W5L ,4W8L <mL,H5 <mL,H8 4W,M <MmW& ,4ZM Z4&,M p<W,M",
+" p<&WM Zp<,M Zp<M& =Lv, =L-v =Hv,L g=-vL v=5,L -v>=L v,5=HL -v>g=L v,=M =M-",
+"v Z,=M =MZ- p=v,M -pv=M Z=p,M =My- U< U<! U<D Ua< U<. U8< U.D< D8U< U<M U!<",
+"M V< V<a U<j 8<Uj V<j s<V U<* U+< D<U* +DU< <*U. +<U8 U<D*. U+<D8 <MU* +MU<",
+" V<* V+< <jU* +<Uj <jV* V+s< U<E <EU! UH< H<Ua <EU. UE8< U.H< H8U< UE<M <ME",
+"U! V<H H<Va UE<j U8<ME H<Vj sHV< U<d +<Ud H<Ud gU< U.<d 8<Ud UH<d. U8g< <MU",
+"d <dMU+ V<d gV< <dUj <dMU8 <dVj s<gV 4U< 4!U< U<4D U<4a U5< U<48 5DU< 5aU< ",
+"U<4M <M!4U V4< 4aV< U<4j 4U8<M V5< V4s< =U =U+ =UD =Ua =U5 =U> U5=D >U=D =U",
+"M U+=M V= V=+ =Uj =U>M V=5 s=V 4EU< 4U<!E U<4H 4UHa< UE5< 4U8<E H5U< 4UH8< ",
+"<ME4U 4UE<M! 4HV< V4Ha< 4Uj<E <ME4U8 H5V< s<V4H =Ud U+=d =UH g=U U5=d =d>U ",
+"UH=5 g>=U Ud=M =U+dM V=H V=g Ud=j >M=Ud V5=H gVs= U<N <NU! UND< UNa< <NU. U",
+"N8< U<DN. U8<DN UQ< Q!U< V<Q QaV< Q<Uj Q8U< Q<Vj sQV< <*UN UN+< U<D*N U+<DN",
+" U<*N. U+<8N D<NU*. a*NU8< Q<U* +QU< Q<V* +QV< UQ<*j U+Q8< V<Q*j s<V+Q UW< ",
+"U!W< H<UW WaU< U.W< W8U< UH<W. UH8W< W<UQ UW<Q! Z<V ZaV< W<Uj UW8Q< ZjV< VZ",
+"s< W<Ud +WU< UH<W* UWg< UW<d. U+W8< UHW<d. gU<W8 Q<Ud U+WQ< V<Z* Z<gV <djUW",
+" U+W<j Z<Vdj gV<sZ U<m U!<m D<Um a<Um 5<Um 8<Um U5<Dm U5a<m U<4Q <MmU! V<m ",
+"a<Vm pU< U8p< Vp< s<Vp =Um U+=m Um=D Ua=m U5=m >m=U =U5Dm =U>Dm =UQ U+=Q V=",
+"Q V+=Q p=U p>=U V=p Vps= U<4W 4UW<! H<Um 4UWa< 5WU< 4UW8< UH5W< UH8<m <MmUW",
+" <M!4UW V4Z< Z4Va< UWp< pU<W8 Z<Vp Vp<sZ =Uv =+vU vU=H gv=U =5vU v>=U =UvH5",
+" g=Uv> vU=Q =Uv+Q Z=V gVZ= pv=U p=Uv> VpZ= yV= ,U< U<& U<,D c<U ,.U< U8b< ,",
+"UD<. U8c< b<M <MU& V<b c<V U<,j 8<bM ,jV< Vsc< U<b* -U< ,UD<* -Uc< ,U<*. U8",
+"-< U<Db*. c-U8< <Mb* b<-M b<V* V-< ,Uj<* U<-j V<b*j s<V- ,EU< UE<& UHb< UHc",
+"< ,U<E. ,U8<E ,UH<. c<UH8 bE<M <M&bE ,HV< cHV< ,Uj<E <&jUE V<bHj s<VcH U<,d",
+" U<-d ,UH<d c<gU ,Ud<. -U8<d <d.,UH gc<U8 <dbM -U<dM ,dV< g<V- <dMbj -Uj<d ",
+"V<d,j V-gs< ,4U 4&,U 4U,D ,4cU 4U,5 4U,8 ,4U5D U5c< 4b,M <M&4b V4, V4c< 4U,",
+"j <M&b5 ,4V5 V4s, =bU =U- ,U=D c=U ,U=5 ->=U =bU5D =Uc> =bM -U=M V=b c=V ,U",
+"=j =b>M V5=b V-s= ,E4U ,4U&E 4U,H c4U,H ,4U5E ,4U8E ,4UH5 c5<UH ,4UME <ME4U",
+"& ,4VH c4V,H ,4UjE <ME4b8 V4,H5 s,V4H ,U=d =d-U ,U=H gc=U =bU5d =b>Ud =bHU5",
+" c=g>U bd=M =bM-d Vd=b gVc= =bM5d >M=bd V=bH5 c=Vgs ,NU< UN<& ,UD<N U<cN ,U",
+"<N. ,U8<N U<N,D. c<U8N UQb< Q<U& ,QV< V<cQ ,UQ<j <&jUQ V<bQj s<VcQ ,U<*N U<",
+"-N U<Db*N c-U<N U<Nb*. -U8<N ,NU<D*. -U8c<N ,UQ<* UQ-< V<bQ* V<-Q UQ<b*j -U",
+"Q8< bQ<V*j V-sQ< UWb< W<U& ,UHW< UWc< ,UW<. ,UW8< ,U.WD< cW<U8 W<bM <M&bW V",
+"<Zb VZc< ,UW<j <&jUW Zb<Vj Zc<Vs ,UW<d UW-< UH<bW* c-WU< <d.,UW -UW8< ,.UHW",
+"<d cW8gU< <dMbW -UWQ< Zb<Vd Z<V- ,UW<dj -UW<j ZbjV<d Z-Vs< 4U,m <mU& ,4UDm ",
+"U<cm ,4U5m <m&U5 U5<,Dm c5<Um 4U,Q <MmU& ,4Vm V<cm ,4pU U<p& pbV< c<Vp ,U=m",
+" -m=U =bUDm cm=U =bU5m =b>Um ,U5=Dm c=>Um ,U=Q -U=Q Vm=b =QV- pb=U =U-p =bV",
+"p V=cp 4U,W <m&UW ,4UHm c4W,U ,4U5W ,4UW8 4UH,5W c5WU< <MmbW 4bW<M& V4Z, Zc",
+"4V< pb<UW pU<W& Vp<Zb cp<VZ vb=U =U-v =bvUH =Ucv =bvU5 -vU>= =U5vD, cv=>U v",
+"b=M -vU=Q =bVv V-Z= p=bvU -pUv= Vv,p= c=yV <k <k! <kB a<k 1<k 8<k 1B<k a<8k",
+" 6M< 6!<M T<k a<6M l< l<8 l<T ls< 6*k +<k *B<k a<+k <k1* +k1< <kB1* ak*68 6",
+"M* +<6M Tk6* T<+k l<* l+< 6Tl* s6l* <kE <!kE H<k a<Hk 1E<k 8E<k Hk1< 8<Hk 6",
+"E<M <kEM! H<6M 6HMa< l<E 8<lE lH< s<lH <dk <d+k Hk6* g<k <k1d <d8k <dk1H 1<",
+"gk <d6M <dk+M HM6* 6Mg< l<d +<ld 6Hl* gl< 4k< 4!<k 4B<k a<4k 7<k 8<7k <k7B ",
+"a<7k <k4M <k!4M T<4k 4Tka< l<7 78l< 7Tl< l<7s =k =k+ =kB =ak =k7 >k= 7B=k =",
+"a>k =kM 6+=M =Tk 6a=M l= l=> l=T l=s 4E<k <kE4! H<4k 4Hka< <k7E 78<kE H<7k ",
+"7H8<k <kE4M 4kE<M! 4HkT< H<k4aM 7<lE 7l8<E 7Hl< 7slH< =kd +k=d =Hk g=k 7d=k",
+" =d>k 7H=k >kg= 6d=M =k+dM 6H=M g6=M l=d >=ld l=H gl= <kN <!kN kN<B aN<k 1N",
+"<k <N8k <kN1B 1a<kN Q<k Q!<k T<Qk a<Qk l<Q Q8l< Q<lT lQs< 6Nk* +N<k <kN*B a",
+"k*6N <kN1* 68*kN 1<Nk*B akN68* Qk6* Q<+k 6Q*Tk ak*6Q 6Ql* +Ql< l<QT* ls<+Q ",
+"W<k W!<k W<Hk a<Wk Wk1< 8<Wk 1H<Wk 1Wa<k W<6M 6WM<! Z<k a<Zk lW< W8l< lZ< s",
+"Zl< Wk6* W<+k <dkHW W<gk <dk1W <dkW8 H<k1W* g1<Wk WM6* <dk+Q 6MZ* Z<gk 6Wl*",
+" +Wl< Z6l* l<gZ <km <!km <Bkm <kam <k7m <k8m 7B<km 7a<km Q<4k <kmQ! <kTm ak",
+"mQ< l<p l8p< lTp< spl< =km +k=m km=B ak=m 7k=m >m=k 7=mkB >k=am =Qk +Q=k Qk",
+"=T Qa=k l=p p=l> lp=T lsp= W<4k <kmW! <kHm akmH< W<7k 7W8<k 7HW<k 7Wa<k <km",
+"WM <k!4WM 4kZ< Z4ka< 7Wl< lW78< l<7Z lZ<7s =kv =+vk vk=H gv=k =k7v v>=k 7v=",
+"Hk g=k7v v6=M =Qkv+ Z=k =kgZ lv= v>l= l=Z yl= ?k ?k& ?Bk ?ak ?1k ?:k 1k?B :",
+"a?k ?M ?M& ?Tk ?aM l? l?: l?T s?l ?k* ?-k k*?B -k?a 1*?k -k?: ?B1k* ?:-ak ?",
+"M* ?-M Tk?* -T?M l?* l-? ?Tl* s?l- ?kE k&?E ?Hk Hk?a 1k?E :k?E 1H?k ?k:H ?M",
+"E M&?E ?HM HM?a l?E lE?: l?H lHs? ?dk -k?d Hk?d g?k 1d?k ?k:d ?H1dk ?:gk ?d",
+"M -M?d HM?d g?M l?d ?:ld ?Hld gl? ?4k 4k?& 4k?B 4a?k 7?k ?k7: ?k7B ?k7a ?M4",
+" 4M?& 4T?M 4a?M l?7 7l?: 7l?T l?7s =k? =k- ?B=k ?a=k 7?=k Ak ?=7kB Aak =M? ",
+"?-=M ?T=k ?a=M l=? Al =Tl? Als 4k?E ?4k&E 4H?k ?H4ak 7k?E ?:7kE ?k7H ?:H7k ",
+"4M?E ?M4&E 4H?M ?HM4a lE7? l?7:E 7l?H l?H7s ?d=k =d-k ?H=k =kg? ?k7d Adk ?H",
+"7=k Agk ?d=M ?-M=d ?H=M =Mg? ?=ld Ald =Hl? Alg ?kN k&?N kN?B ak?N 1k?N :k?N",
+" ?B1kN ?:akN ?Qk Qk?& Qk?T Qa?M l?Q ?Ql: lQ?T ?Qls k*?N ?N-k ?Bk*N ?-akN ?1",
+"k*N ?:-kN k*N?B1 :-k?aN Qk?* -Q?M ?QTk* ?-QTk ?Ql* ?Ql- l?QT* l-?sQ ?Wk Wk?",
+"& Hk?W Wa?k 1W?k ?k:W ?H1Wk ?:HWk ?WM WM?& ?Zk Zk?a l?W ?:lW ?Zl l?Z: Wk?d ",
+"-k?W ?HWdk ?Wgk ?W1dk ?:W-k 1H*?Wk g?:Wk WM?d -W?M Zk?d gk?Z ?Wld ?-lW ld?Z",
+" ?Zgl ?mk km?& km?B ak?m 7k?m ?k:m ?m7kB ?:mak ?Mm Mm?& Tk?m aM?m ?pl l?:p ",
+"lp?T ls?p ?m=k -k?m ?=mkB ?-mak ?=7km Akm 7=B?mk akAm ?Q=k -Q=k ?Tm=k ?-Tkm",
+" ?pl= Alp l=?pT lsAp 4W?k ?W4k& Hk?m ?Hmak ?k7W ?:W7k ?H7Wk ?:Hkm 4W?M ?WM4",
+"& Z4?M ?Z4ak lW?p l?W:p l?7Z s?Z7l ?vk =k-v vk?H gk?v vk7? Avk ?v7Hk gvAk ?",
+"vM ?M-v =k?Z =kZ- lv? Alv ?Zlv yAl 6U< 6!U< D<k U<6a 1U< U81< U<1D Ua1< U<6",
+"M <k!UM V6< 6aV< l<U U8l< l<V Vls< 6U* U+6* U*6D Ua6* 1U6* U+1< 6U*1D 6U8D*",
+" U*6M 6U+<M V6* 6+V< 6Ul* U+l< V6l* V6s* 6EU< <kEU! U<6H 6UHa< 1EU< 6U8<E U",
+"H1< 6UH8< <kEUM 6UE<M! 6HV< V6Ha< U<lE l<U8E V<lH s<VlH U<6d <dkU+ UH6* 6Ug",
+"< U<1d <dkU8 <dk1D 1Ug< <dkUM 6U+<dM 6HV* V6g< U<ld l+<Ud V<ld l<gV U<4k <k",
+"!4U D<4k 4Ua<k 7U< U87< U<7D Ua7< 4U6<M 4U6<M! 4kV< V46a< 7Ul< 7lU8< 7V< s<",
+"7V =U6 6U=+ =Dk 6U=a =U7 =U>k 7U=D =D>k 6U=M =U6+M V=6 V6=a l=U =Ul> l=V 7V",
+"s= <kE4U 4UE<k! 4UH<k UH<4ak U<7E 7U8<E UH7< 7UH8< 4U6<ME <k4MU!E V46H< 4Hk",
+"V<a 7lU<E l<87UE V<7H 7VsH< 6U=d =U6+d 6U=H g6=U 7d=U 7>U=d 7U=H =Ug7 =U6dM",
+" 6U+=Md V6=H =kgV ld=U l=>Ud =H7V V=gl 6NU< <kNU! DN<k 6Ua<N 1NU< 6U8<N 1U<",
+"DN 1Ua<N U<6Q 6UQ<! 6QV< V6Qa< UQl< l<UQ8 lQV< s<VlQ 6NU* 6U+<N 6U*DN 6Ua*N",
+" 6U*1N 6U8*N <kN1D* a*N6U8 UQ6* 6U+Q< 6QV* V6+Q< l<UQ* l+<UQ l<VQ* s*V6Q U<",
+"6W 6UW<! D<Wk 6UWa< UW1< 6UW8< 1UHW< 1UWa< 6UWQ< <M!6UW V6Z< Z6Va< UWl< lW<",
+"U8 VlZ< lZ<Vs UW6* 6U+W< <dkWD g6UW< 6UW1* 6UW8* 1UH6W* g1UW< <dkUQ U+W6Q* ",
+"V6Z* gV6Z< lW<Ud l+WU< lZ<Vd gl<VZ U<6m <kmU! <kDm akmU< U<7m 7U8<m 7UD<m 7",
+"Ua<m <kmUQ <k!4UQ 6mV< V6ma< pUl< 7pU8< l<Vp Vp<7s 6U=m =U6+m Dk=m =Ua6m =m",
+"7U 7>U=m =U7Dm 7Ua=m 6U=Q =UQ6+ V6=Q V=6+Q 7p=U l=p>U Vpl= V=pl> <kmUW <k!4",
+"UW <kmUH UH<akm UW7< 7UW8< 7UHW< 7UWa< 6UW<Mm Q!4UW<k Z4V<k Z6aV<m 7pUW< 7U",
+"8lW< Z<7V 7ZVs< v6=U =Uv6+ vD=k g=Uv6 =U7v 7vU>= 7vU=H g7Uv= =Uv6Q =U+v6M =",
+"kVv Vv6g= =Ulv lv=>U Z=7V l=yV ?t ?t& ?tD ?ct ?t1 ?t: t1?D t:?c ?tM tM?& V?",
+" V?c l?t ?tl: V?l u? ?t* t-? t*?D t-?c ?1t* ?:t- ?t1D* ?t:c- t*?M ?Mt- V?* ",
+"V?- ?tl* l?t- l*V? u?- ?tE t&?E ?tH tc?H t1?E ?Et: ?1tH t:?H tM?E ?tM&E V?H",
+" Vc?H lE?t ?t:lE lHV? u?H ?td ?dt- tH?d g?t ?1td t:?d ?tH1d ?tg: td?M ?td-M",
+" V?d g?V ?tld l-?td ldV? u?g ?t4 ?&t4 t4?D t4?c 7t? ?:7t ?D7t 7t?c t4?M ?t4",
+"M& V?4 c4V? l?7t ?t:7l 7V? u?7 t= t=- t=D t=c t=7 At =D7t Atc t=M =Mt- t=V ",
+"V?c= l=t Alt 7Vt= Au ?Et4 ?t4&E t4?H ?tHc4 ?E7t ?t:7E ?H7t 7tH?c ?t4ME t4&?",
+"ME V4?H V?c4H 7tl?E l?:7tE ?H7V ?Hu7 t=d -=td t=H gt= ?d7t Atd =H7t Agt td=",
+"M t=-dM =HV? V=g? ldt= ltAd =Hlt Aug ?tN t&?N tD?N ?Ntc t1?N ?Nt: ?t1DN ?t:",
+"cN ?tQ ?&tQ V?Q tc?Q ?Qlt t:?Q Vl?Q u?Q ?Nt* ?Nt- ?tD*N ?ct-N ?t1*N ?t:-N t",
+"*1?DN t-:?cN t*?Q ?Qt- V*?Q ?QV- ?tQl* t-Ql? V?lQ* ?-uQ ?tW ?&tW tH?W tc?W ",
+"?1tW t:?W ?tH1W ?cWt: tW?Q ?tWQ& ?ZV ?ctZ ?tlW l?Wt: l?tZ u?Z tW?d ?Wt- ?tH",
+"W* ?Wgt ?tW1d t-W?: ?H1tW* g?t:W tQ?d t-W?Q ?dtZ ?Zgt l?Wtd l-W?t V?dlZ g?u",
+"Z ?tm ?&tm tm?D tc?m ?m7t t:?m ?tm7D ?cm7t t4?Q ?tQ4& V?m cmV? ?pt ?t:p ?pV",
+" u?p t=m ?mt- tm=D tmc= 7=tm Atm t=7Dm tcAm t=Q =Qt- =QV? ?mV- tp= Apt V=?p",
+" Aup t4?W ?tW4& tH?m ?cWt4 ?W7t 7tW?: 7tH?W 7cW?t ?tW4Q ?W&t4Q ?mtZ V?mZc ?",
+"Wtp ?pt:W tZ?p ?Zup ?vt t-?v =Htv ?vgt 7t?v Atv ?vt7H gtAv =Qtv ?vt-Q ?vV Z",
+"-t= tp?v lvAt tZl= Auy 3F !3F 3BF a3F 3F. 83F 3F.B a38F 3FK 3F!K T3F a3TF j",
+"3F j38F j3TF s3F 3(F +3F 3(FB a3+F (F3. 83+F 3F.(B +8a3F (F3K 3F+K 3(TF T3+",
+"F 3(jF j3+F Tj3(F +3sF G3 G3! GH3 Ga3 G3. G83 H3G. G3H8 G3K !KG3 GT3 TaG3 G",
+"j3 8jG3 G3Hj sG3 Gd3 +G3 HdG3 gG3 d3G. +3G8 GHd3. G8g3 dKG3 GK+3 G3Td GTg3 ",
+"G3dj +3Gj dj3GT g3sG 4F 4F! 4FB 4aF 45F 48F 5B4F 4F5a 4FK !K4F 4TF Ta4F 4jF",
+" 8j4F 4F5T s4F 4;F 4+F ;F4B 4Fa; 5;4F >F4 45;FB 4a>F ;F4K +F4K 4FT; 4F+T 4F",
+";j 4j>F ;jF4T >Fs4 4G 4G! 4GH 4Ga 4G5 4G8 G54H G54a 4GK GK4! 4GT GT4a 4Gj G",
+"84j G54T s4G 4Gd 4+G G;4H g4G G54d >G4 4GH5d >Gg4 4KG; 4K+G GT4d 4GgT G;4j ",
+"4G>j 4GT5d sGg4 3FN 3F!N 3FNB 3FaN 3FN. 3F8N 3F.NB 8a3FN Q3F !3QF T3QF a3QF",
+" j3QF 83QF QTj3F Q3sF (F3N 3F+N 3FN(B +a3FN 3F.(N +83FN N.(3BF 8a3+FN 3(QF ",
+"Q3+F QT3(F +QT3F Qj3(F +Q83F Tj3Q(F s+Q3F GW3 G3W! HWG3 G3Wa W3G. G3W8 GHW3",
+". G8HW3 GQ3 G3Q! ZG3 GaZ3 G3Wj G3Q8 GjZ3 ZGs3 WdG3 GW+3 GHWd3 GWg3 GWd3. +G",
+"W83 HWdG3. gGW83 G3Qd +3GQ GdZ3 ZGg3 dj3GQ +GQ83 ZGdj3 gZsG3 4mF mF4! mF4B ",
+"4Fam 5m4F 4F8m 45mFB amF48 4QF 4FQ! 4FTm 4FQa p4F 48pF 4TpF p4sF m;4F 4F+m ",
+"4m;FB amF4+ 45m;F 4m>F 5m;4FB >m4aF 4FQ; 4F+Q 4QT;F 4+QTF 4;pF p4>F p4T;F p",
+">4sF 4GW 4!Gm Gm4H Ga4W G54W G84W 4GH5W 4G8Hm 4GQ Q!4G Z4G 4GZa pG4 4Gp8 pG",
+"Z4 Z4sG v4G 4+vG 4GvH v4gG 4Gv5 v4>G v4GH5 gv>4G 4GvQ +G4Q v4ZG gGZ4 v4pG p",
+"4>G Zpv4G y4G #3F &3F #3FB &3aF 3F#. &38F 3F.#B 8a&3F 3F#K 3F&K #3TF &3TF #",
+"3jF j3&F Tj#3F &3sF 3(#F &3+F 3BF#( +a&3F 3F.#( +8&3F #(F.B3 8a&+3F 3FK#( +",
+"&3FK T#3(F +T&3F j#3(F &j3+F j#3T(F s+&3F G#3 G&3 H#G3 G3H& #3G. 8&G3 GH#3.",
+" G8H&3 #3GK &3GK T#G3 G3T& j#G3 G3&j GTj#3 G&s3 d#G3 +3G& GHd#3 G&g3 Gd#3. ",
+"d&3G8 Hd#G3. gG8&3 Gd#3K d&3GK GTd#3 gGT&3 dj#G3 d&jG3 GT#dj3 gsG&3 4#F 4&F",
+" #B4F a&4F 5#4F 4F5& 45#FB 48a&F #F4K &F4K T#4F 4FT& j#4F 4F&j 4T5#F 4&sF ;",
+"#4F 4F;& 4;#FB a;&4F 45;#F 4&>F 5;#4FB >&4aF 4;#FK ;&F4K 4T;#F 4+T&F ;j#4F ",
+">&4jF 4T#;jF s>4&F 4G# 4G& GH4# Ga4& 4#G5 G54& 4GH5# 4G8H& G#4K 4KG& 4#GT G",
+"T4& 4#Gj G&4j 4GT5# 4Gs& 4#G; +G4& 4GHd# 4Gg& 4G5d# 4G>& G5H4d# g>4G& 4Gd#K",
+" 4+G&K 4GTd# g4GT& 4Gjd# >G4&j dj#4GT gs4G& 3F#N 3F&N 3FN#B a&3FN 3F.#N 8&3",
+"FN .B3#FN a&38FN #3QF &3QF QT#3F Qa&3F Qj#3F &j3QF Tj#Q3F sQ&3F 3FN#( +&3FN",
+" #BF3(N a&3+FN #3FN.( 8&3+FN 3F#N.B( 3F&N+8a Q#3(F +Q&3F T#3Q(F Q&3+TF j#3Q",
+"(F +Q3&jF 3(jFQT# +Q&s3F W#G3 G3W& GHW#3 GaW&3 GW#3. G8W&3 HW#G3. H8WG&3 Q#",
+"G3 G3Q& G#Z3 G&Z3 GQj#3 GQ8&3 ZGj#3 Z&Gs3 GWd#3 d&3GW HWdG#3 gGW&3 Wd#G3. G",
+"8Wd&3 W#H3Gd. G8Wg&3 GQd#3 +GQ&3 ZGd#3 Z&Gg3 GQ#dj3 d&3GQ8 dj#ZG3 gsGZ&3 m#",
+"4F 4Fm& 4m#FB am&4F 45m#F m&F48 5m#4FB 48am&F Q#4F 4FQ& 4QT#F 4Qa&F 4#pF 4&",
+"pF p4T#F p&4sF 4m;#F m&F4+ m;#4FB 4+am&F 5m;4#F >m4&F 5B4Fm;# am&>F4 4Q;#F ",
+"4+Q&F Q;#4TF a;F4Q& p4;#F p>4&F 4T;p#F s>4p&F 4#Gm Gm4& 4GHW# 4GaW& 4G5W# 4",
+"G8W& G5H4W# G5a4W& 4#GQ GQ4& 4GZ# 4GZ& 4Gp# 4Gp& Zp4G# Zp&4G 4Gv# 4Gv& v4GH",
+"# gv4G& v4G5# v>4G& 4GHv5# v>Gg4& v4GQ# v&4GQ Zv4G# Zv&4G pv4G# pv&4G pvGZ4",
+"# 4Gy& I3 I3! DI3 aI3 I3. 8I3 I3D. D38I I3K !KI3 TI3 T3aI Ij3 83Ij D3Ij sI3",
+" I3( +I3 I3D( +3aI 3(I. +38I DI3(. +D8I3 3(IK I3+K I3T( +3TI j3I( +3Ij Ij3D",
+"( +Is3 GI3 I3G! J3 Ja3 I3G. G38I J3. J83 I3GK GI3!K JT3 TaJ3 G3Ij Ij3G8 Jj3",
+" sJ3 Id3 +3Id Jd3 gJ3 d3I. 83Id d3J. g3J8 I3dK Id3+K TdJ3 JTg3 I3dj Idj+3 d",
+"jJ3 g3sJ 4I 4I! 4DI 4aI 4I5 48I 5D4I 5a4I 4IK IK4! 4TI TI4a 4Ij 8I4j 5T4I s",
+"4I 4I; 4+I D;4I +D4I 45I; >I4 4D5I; 4D>I 4KI; 4K+I T;4I +T4I I;4j 4I>j I;j4",
+"D >Is4 4GI GI4! J4 J4a G54I G84I J45 J48 GI4K 4GI!K J4T 4TJa Gj4I 4G8Ij J4j",
+" sJ4 4Id +G4I J4d gJ4 5I4d 4G>I 4dJ5 J>4 4KId 4+GIK 4TJ; gTJ4 Id4j >I4Gj 4d",
+"Jj g4sJ I3N !3IN I3DN I3aN N.I3 IN83 DI3N. D8I3N QI3 I3Q! Q3TI Q3aI Q3Ij Q3",
+"8I Ij3QD QIs3 3(IN I3+N DI3(N +DI3N I3(N. +I83N I3(DN. D83+IN I3Q( +3QI QDI",
+"3( +QDI3 Ij3Q( +QI83 QD3Ij( sI+Q3 WI3 I3W! JW3 WaJ3 I3W. W38I W3J. W8J3 G3Q",
+"I GQI!3 ZJ3 JaZ3 W3Ij GQ8I3 Z3Jj s3ZJ W3Id +3WI WdJ3 JWg3 Id3W. +WI83 JWd3.",
+" gJW83 Q3Id +GQI3 JdZ3 g3ZJ IdjW3 +WIj3 ZJdj3 sJZg3 4Im 4!Im Dm4I am4I 45Im",
+" 8m4I 4D5Im 4D8Im 4QI Q!4I QD4I Qa4I pI4 48pI 4DpI pIs4 4mI; +m4I Im;4D 4+D",
+"Im Im;45 4I>m 4D5Im; >Dm4I Q;4I +Q4I 4QDI; 4+QTI 4Ip; p4>I pD4I; p>D4I 4WI ",
+"4!WI J4W 4WJa 5W4I W84I 4WJ5 4WJ8 GQ4I 4GQI! ZJ4 ZaJ4 4GpI pG48I Jp4 s4Jp v",
+"I4 4+vI Jv4 g4Jv 4Iv5 v4>I v4J5 v>J4 4QvI vI4+Q Z4Jv ZJg4 p4vI pvI>4 pvJ4 y",
+"J4 bI3 I&3 DIb3 cI3 I3b. b38I bDI3. 8Ic3 I3bK &3IK b3TI TIc3 b3Ij I3&j Ij3b",
+"T cIs3 I3b( b3+I bDI3( +Ic3 bI3(. I&3+8 DI3b(. c+8I3 bKI3( I&3+K bTI3( c+TI",
+"3 Ij3b( I&j+3 bT3Ij( sI+c3 bG3 b3G& Jb3 cJ3 G3b. b3G8 b3J. c3J8 G3bK I&3GK ",
+"bTJ3 JTc3 b3Gj I&jG3 bjJ3 s3cJ b3Id b3+G bdJ3 g3cJ Id3b. b+G83 Jbd3. cJ8g3 ",
+"Id3bK b+G3K JbTd3 cJTg3 Idjb3 Idj&3 Jjbd3 sJgc3 4bI 4I& bD4I c4I b54I b84I ",
+"4b5DI 48cI bK4I 4KI& bT4I 4TcI bj4I I&4j 4bT5I c4sI b;4I b+4I 4bDI; 4+cI 4b",
+"5I; 4b>I b5D4I; >Ic4 I;K4b I;&4K 4bTI; c4+TI I;j4b >I4bj 4bTI;j c>s4I 4bG b",
+"G4& J4b cJ4 b54G bG48 4bJ5 J4c5 4KbG 4bG&K 4bJT cTJ4 bG4j I&j4G 4bJj cJs4 b",
+"G4d b+4G 4bJ; cJg4 4bG5d 4b>G J4b5d c4J> 4bGdK 4b+GK J4bTd cJ4gT Idj4b >bG4",
+"j J4jbd J>sc4 I3bN &3IN bDI3N I3cN bI3N. I&38N DI3bN. c8I3N b3QI Q3I& bQDI3",
+" QIc3 Ij3bQ I&jQ3 bQDIj3 sIQc3 bI3(N I&3+N DI3b(N c+I3N I3(bN. +I3b8N 3(INb",
+"D. +I8c3N bQI3( b+QI3 QI3bT( cQ+I3 bQ3Ij( Ij3b+Q Qjb3TI( cQ+sI3 b3WI W3I& b",
+"WJ3 JWc3 bGW3. bG8W3 JbW3. cJW83 b3GQ bGQ&3 JbZ3 Z3cJ bGQj3 I&jW3 ZJbj3 sJZ",
+"c3 Id3bW b+GW3 JbWd3 cJWg3 bW3Id. Id3bW8 bWdJ3. gJ8cW3 bGQd3 b+GQ3 ZJbd3 Zc",
+"Jg3 Id3bWj Id3bQ8 JjdZb3 ZcgsJ3 bm4I Im4& 4bDIm 4Icm 4b5Im Im&48 b5D4Im c45",
+"Im bQ4I QI4& 4bQTI 4QcI 4bpI 4Ip& pb4TI pIc4 Im;4b Im&4+ 4bDIm; c4+Im 4b5Im",
+"; >I4bm Imb;4D5 c>4Im 4bQI; I;&4Q bQ;4TI c4Q+I pb4I; p>b4I 4bTpI; cp>4I bG4",
+"W WI4& 4bJm J4cW 4bG5W 4bGW8 J4b5W cJ45W bG4Q 4bGQ& J4Zb cJZ4 4bpG pbG48 pb",
+"J4 c4Jp 4bvI 4Iv& vbJ4 c4Jv vb4G5 v>b4G Jv4b5 cvJ>4 vb4GQ vI&4Q ZJ4vb cvZJ4",
+" pvb4G pvI4& Jpv4b cJy4 6F 6!F 6FB 6aF 61F 68F 1F6B 6F1a 6FK !K6F 6TF Ta6F ",
+"6jF 8j6F 6F1T s6F 6(F 6+F (B6F +a6F 1(6F 6F1+ 61(FB 6+1aF (F6K +F6K T(6F 6F",
+"+T j(6F 6F+j 6T1(F 6+sF 6G 6G! 6GH 6Ga 6G1 6G8 1G6H 1G6a 6GK GK6! 6GT GT6a ",
+"6Gj G86j 1G6T s6G 6Gd 6+G GH6d g6G 1G6d 1+6G 6G1Hd 6Gg1 Gd6K 6K+G GT6d 6GgT",
+" Gj6d +G6j 6GT1d sGg6 46F 4F6! 6F4B 4F6a 7F 78F 7BF 7aF 6F4K 6!4FK 4F6T 4T6",
+"aF 7jF 8j7F 7TF 7sF 6;F 4F6+ ;F6B 6Fa; 7;F 7>F ;F7B >F7a ;F6K 4+6FK 6FT; 4+",
+"T6F ;j7F 7j>F T;7F >F7s 4G6 6!4G 6G4H 6G4a 7G 7G8 7GH 7Ga 4K6G 4G6!K 6G4T 4",
+"GT6a 7Gj G87j 7GT 7sG 6G; 6+4G G;6H 4Gg6 7Gd 7>G G;7H g7G 6KG; 4+G6K GT6; g",
+"46GT G;7j >j7G GT7d sGg7 6FN !F6N NB6F aF6N 1F6N 8F6N 61FNB 68aFN 6QF 6FQ! ",
+"QT6F 6FQa 6F1Q 6FQ8 6Q1TF 6QsF (F6N +F6N 6(FNB 6+aFN 61(FN 6+1FN 1(F6NB 1+F",
+"6aN Q(6F 6F+Q 6QT(F 6+QTF 6Q1(F 6+Q1F 1Q(6TF s6+QF 6GW W!6G GH6W Ga6W 1G6W ",
+"G86W 6G1HW 6G8Wa 6GQ Q!6G Z6G 6GZa 1G6Q GQ68 6GZ1 Z6sG GW6d +G6W 6GHWd 6GgW",
+" 6G1Wd 6+G1W 1GH6Wd g61GW GQ6d +G6Q 6GZd gGZ6 6GQ1d 6+G1Q Z61Gd gZ6sG 6mF m",
+"F6! mF6B 6Fam 7mF 8m7F mF7B am7F 4F6Q 4Q6!F 6FTm 4Qa6F 7pF p87F pT7F sF7p m",
+";6F 6F+m 6m;FB 6+maF m;7F 7m>F 7Bm;F 7>amF 6FQ; 4+Q6F 6Q;TF 6+TmF p;7F >F7p",
+" 7pT;F 7p>sF 6Gm 6!Gm Gm6H Ga6m 7GW G87W Gm7H Ga7W 6G4Q 4GQ6! 4GZ6 Z46Ga 7p",
+"G 78pG 7ZG sG7Z v6G 6+vG 6GvH gGv6 7vG v>7G vG7H 7Ggv 6GvQ v6+GQ ZGv6 Zv6gG",
+" pv7G p>7G 7GZv y7G 69F 6&F 9F6B 6F9a 916F :6F 691FB 6a:F 9F6K &F6K 6F9T 6F",
+"T& 6F9j 6j:F 6T91F :6sF 9(6F 6F9+ 69(FB 6+9aF 691(F 6+:F 91(6FB :6+aF 69(FK",
+" 6+9FK 6T9(F 6+T9F 6j9(F :6+jF 9T(6jF s:6+F 6G9 6G& 9G6H 9G6a 691G :G6 6G91",
+"H 6G:H 6K9G 6KG& 9G6T GT6& 9G6j 6G:j 6GT9j :Gs6 9G6d 9+6G 6G9Hd 6Gg9 6G91d ",
+"6+:G 9G16Hd :Gg6 6G9dK 6+G9K 6GT9d g69GT 6Gj9d :G6+j 9GT6dj g:s6G 49F 4F6& ",
+"9F4B 4F9a 79F 7:F 9F7B :a7F 9F4K 49&FK 4F9T 49TaF 9j7F :j7F 9T7F sF7: 4F9; ",
+"4F9+ 49;FB 49+aF 9;7F >F7: 7B9;F 7:>aF 49;FK 49+FK 49T;F 49+TF 79;jF 7:>jF ",
+"7T9;F 7s:>F 49G 6G4& 9G4H 9G4a 7G9 7:G 9G7H :G7H 4K9G 49G&K 9G4T 49GT& 9G7j",
+" 7j:G 9G7T 7:sG 9G4d 9+4G 49GH; 49gG 9G7d :>7G 7G9H; 7Gg: 49GdK 49+GK 49GTd",
+" g49GT 7G9dj 7:G>j 7GT9d 7sGg: 9F6N &F6N 69FNB 6a9FN 691FN 6F:N 91F6NB :6aF",
+"N 6F9Q 6FQ& 6Q9TF 6Qa9F 6Q91F 6Q:F 9Q16TF :Q6sF 69(FN 6+9FN 9(F6NB 9+F6aN 9",
+"1(6FN :6+FN 916N(BF 6+a:FN 6Q9(F 6+Q9F 9Q(6TF 6+F9Qa 9Q(6jF :Q6+F QT1(69F s",
+"6+:QF 9G6W G&6W 6G9HW 6Ga9W 6G91W 6G:W 9G16HW :G6Wa 9G6Q GQ6& 6GZ9 6GZ& 6GQ",
+"9j 6G:Q Z691G :GZ6 6G9Wd 6+G9W 9GH6Wd g69GW 9G16Wd :G6+W 691HGWd g:6GW 6GQ9",
+"d 6+G9Q Z69Gd Z6&gG 9GQ6dj :GQ6+ 6GjZ9d Z:g6G 4F9m 6Fm& 49mFB 49amF 9m7F 7F",
+":m 7B9mF 7:amF 4F9Q 49Q&F 49QTF 49QaF 7Fp9 7F:p 7p9TF 7sp:F 49m;F 49+mF 9mF",
+"6;B amF49+ 79m;F 7:>mF 9m;7BF :>m7aF 49Q;F 49+QF 4QF9T; a;F49Q 7p9;F 7p>:F ",
+"p9;7TF :p>7sF 9G4W Gm6& 49GHm 49GWa 9G7W :G7W 7G9Hm 7:GHm 9G4Q 49GQ& 49ZG Z",
+"49Ga p97G 7G:p Z97G 7GZ: 49vG 6Gv& v69GH gv69G v97G 7G:v 7v9GH :vGg7 v69GQ ",
+"v6&GQ Zv69G Zv6G& 7pGv9 :vG7p 7Zv9G 7:yG 6I 6I! 6DI 6aI 6I1 68I 1D6I 1a6I 6",
+"IK IK6! 6TI TI6a 6Ij 8I6j 1T6I s6I 6I( 6+I DI6( +D6I 6(1I 1+6I 6D1I( 6+D1I ",
+"I(6K 6K+I 6(TI +T6I 6(Ij +I6j 6DjI( 6+sI 6GI GI6! J6 J6a 1G6I G86I J61 J68 ",
+"GI6K 6GI!K J6T 6TJa Gj6I 6G8Ij J6j sJ6 6Id +G6I J6d gJ6 1I6d 8I6d 6dJ1 J6g1",
+" 6KId 6+GIK 6TJd gTJ6 Id6j Idj6+ 6dJj g6sJ 4I6 6!4I 6D4I 6a4I 7I 7I8 7DI 7a",
+"I 4K6I 4I6!K 6T4I 4TI6a 7Ij 8I7j 7TI 7sI 6I; 6+4I D;6I aI6; 7I; 7>I D;7I >D",
+"7I 6KI; 4+I6K TI6; 4+T6I I;7j >j7I TI7; 7>sI 6G4I 4G6I! J46 4aJ6 7GI G87I 7",
+"J 7J8 4G6IK 6GK4I! 4TJ6 J46Ta Gj7I 7G8Ij 7JT 7Js 6I4d 4+G6I J6; J4g6 7Id >G",
+"7I 7Jd g7J 4Id6K I;K6+G 6TJ; gJ46T Id7j 7>GIj J;7T sJg7 6IN IN6! DI6N 6NaI ",
+"6N1I 6N8I 6D1IN 6D8IN 6QI Q!6I QD6I Qa6I 1Q6I Q86I 6QD1I 6QsI I(6N 6N+I 6DI",
+"(N 6+DIN 6I1(N 6+I1N 1D(6IN 6+N1aI 6(QI +Q6I 6QDI( 6+QTI 6QI1( 6+Q1I Ij(6QD",
+" s6I+Q 6WI 6!WI J6W 6WJa 1W6I W86I 6WJ1 6WJ8 GQ6I 6GQI! ZJ6 ZaJ6 WI6j 6GQ8I",
+" J6Z1 ZJs6 WI6d +W6I 6WJd gWJ6 6WI1d 6+W1I J61Wd gJ61W QI6d 6+GQI ZdJ6 ZJg6",
+" Idj6W 6+WIj ZJ61d sJ6gZ 6Im 6!Im Dm6I aI6m 7Im 8I7m Dm7I aI7m 6Q4I 4QI6! T",
+"I6m 4Qa6I 7pI 78pI pD7I 7psI Im6; +I6m 6DmI; 6+DIm Im7; >m7I 7DIm; 7>DIm QI",
+"6; 4+Q6I 6QDI; 6+TIm 7;pI p>7I 7pDI; 7sIp> 6W4I 4WI6! J6m 6aJm 7WI W87I 7JW",
+" J87W 4GQ6I Im!6GQ J4Z6 ZJ46a pG7I 7pG8I 7ZJ sJ7Z v6I 6+vI Jv6 g6Jv 7vI v>7",
+"I 7Jv 7vJ> 6QvI v6I+Q Z6Jv Jv6gZ pv7I 7vIp> 7vJp yJ7 b6I 6I& 9D6I c6I 6Ib1 ",
+":I6 b61DI c6:I bK6I 6KI& 6IbT 6TcI 6Ibj 6I:j b6T1I :Is6 b(6I 6Ib+ b6DI( 6+c",
+"I b61I( 6+:I 6DIb1( :c6+I b6I(K b6+IK b6TI( c6+TI b6jI( :I6+j Ij(b6T s:I6+ ",
+"b6G 6&bG J6b cJ6 6Gb1 b6:G b6J1 :J6 bK6G b6G&K b6JT cTJ6 6Gbj :Gb6j b6Jj s6",
+":J 6Gbd 6+bG b6Jd cJg6 b6G1d 6I:d J6b1d g6:J b6GdK b6+GK J6bTd cJ6gT Idjb6 ",
+":Id6j J6jbd sJ6g: 49I 6I4& 9D4I 49cI 7bI 7:I 9D7I 7cI 4K9I 49I&K 9T4I c46TI",
+" bj7I 7j:I bT7I sI7c 6Ib; 9+4I 49DI; 6Ic; b;7I :>7I 7bDI; 7Ic> 49I;K I;&6K ",
+"49TI; c6;TI 7bI;j 7:I>j 7bTI; 7sIc> b64G 4bG6& J49 J4c6 7bG :G7b 7Jb 7J: 4b",
+"G6K I&K49G 49JT cJ46T bG7j 7:Gbj J97T sJ7c 6Gb; I;&6G 49J; J4g9 bG7d :I7d J",
+"97d :Jg7 49IdK IdK49+ J49Td cJ6T; 7bGdj 7:Idj 7JbTd g7Js: bN6I 6NI& b6DIN 6",
+"IcN b61IN 6I:N 6DIb1N :c6IN 6IbQ QI6& b6QTI 6QcI b6Q1I 6Q:I 6QIb1T :cQ6I b6",
+"I(N b6+IN 9D(6IN c6+IN 6I(b1N :I6+N b(6D1IN c6+:IN b6QI( b6+QI bQ(6TI c6Q+I",
+" Ij(b6Q :QI6+ b(6Q1TI sI+c6Q 6GbW WI6& b6JW J6cW b6G1W 6W:I J6b1W J6:W 6GbQ",
+" b6GQ& J6Zb cJZ6 b6G1Q :GQb6 ZJ6b1 Z6:J b6GWd b6+WI J6bWd cJ6gW 6WIb1d :WI6",
+"+ b6WJ1d :Jg6W b6GQd b6+GQ ZJ6bd Zc6gJ b6WIdj :QI6d ZbdJ6j Z:Jg6 6Ibm Im6& ",
+"49DIm 6Icm bm7I :m7I 7bDIm cm7I 9Q4I Im&6Q 49QTI c4Q6I pb7I 7I:p 7pbTI 7Icp",
+" 49Im; Im&6+ 9Dm6I; c6m+I 7bIm; 7:I>m 9Dm7I; 7c>Im 49QI; I;&6Q 6QIbT; c6QI;",
+" 7pbI; :pI7> 7D;p9I 7cp>I 6Gbm Im&6G 49Jm J6cm bG7W :W7I J97W 7W:J 4bG6Q b6",
+"G4Q& J4Z9 Zc4J6 pb7G :pG7b 7bJp Z:7J 49vI 6Iv& vbJ6 c6Jv vb7G 7I:v 7bJv :v7",
+"J vb6GQ v6IQ& Jv6Zb cv6ZJ 7vbpG :vI7p Jp97v 7Jy: 3FL 3F!L 3FLB 3FaL FL3. 3F",
+"8L 3L.FB 8a3FL M3F !3MF M3TF M3aF j3MF M38F TMj3F M3sF (F3L 3F+L 3FL(B +a3F",
+"L 3L.(F +83FL (BL3F. 8a3+FL 3(MF M3+F TM3(F aM3+F Mj3(F +M83F Mj3T(F s+M3F ",
+"G3L !3GL H3GL a3GL 3LG. 83GL GH3L. G8H3L GM3 M3G! G3HM G3aM MjG3 G38M GTMj3",
+" GMs3 d3GL G3+L GHd3L G3gL Gd3L. +G83L Hd3GL. gG83L G3dM +3GM dM3GT GMg3 dM",
+"jG3 +GM83 GTMdj3 gsGM3 4FL !F4L LB4F aF4L 5F4L 8F4L 45FLB 48aFL 4MF MF4! TM",
+"4F 4FaM 4F5M 4F8M 4T5MF 4MsF ;F4L +F4L 4;FLB a;F4L 45;FL 4F>L 5;F4LB >F4aL ",
+"4FM; 4F+M M;F4T aM;4F M;F4j 4M>F 4T5M;F >Ms4F 4GL GL4! GH4L 4LGa 4LG5 4LG8 ",
+"4GH5L 4G8HL 4GM 4!GM GT4M Ga4M G54M G84M 4GT5M 4GsM 4LG; 4L+G 4GHdL 4GgL 4G",
+"5dL 4G>L G5H4dL g>4GL GM4d +G4M 4GTdM 4GgM 4GM5d 4G>M G5T4dM >Mg4G FL3N 3FN",
+"!L 3FNLB a3FLN 3L.FN 83FLN .BL3FN a3F8LN M3QF Q!M3F QTM3F aM3QF QMj3F Q8M3F",
+" TMjQ3F sQM3F 3FN(L +3FLN (BL3FN a3F+LN N.(3FL 83F+LN (FLBN.3 3L+N8aF QM3(F",
+" +QM3F TM3Q(F +Q3aMF Mj3Q(F Q83+MF 3(MFQTj +QMs3F W3GL W!G3L GHW3L GaW3L GW",
+"3L. G8W3L HW3GL. W83GaL G3WM GQM!3 GMZ3 ZGaM3 GQMj3 GQ8M3 ZGMj3 sZGM3 GWd3L",
+" +GW3L HWdG3L gGW3L Wd3GL. G83+WL W3HLGd. G8Wg3L dM3GQ +GQM3 ZGdM3 gZGM3 GQ",
+"Mdj3 dM3GQ8 dMjZG3 sZGgM3 mF4L 4mF!L 4mFLB amF4L 45mFL 48mFL 5mF4LB 48FamL ",
+"4FMm MmF4! MmF4T aMm4F 4MpF p48MF p4TMF sp4MF 4m;FL 4+mFL m;F4LB 4+FamL 5m;",
+"4FL >m4FL mL4B5;F amF>L4 MmF4; 4+QMF 4QTM;F aMF4+Q p4M;F >Mp4F M;Fp4T sp4>M",
+"F 4LGm 4GW!L 4GHWL 4GaWL 4G5WL 4G8WL G5H4WL amL4G8 GQ4M 4GQM! 4GZM Z4GaM 4G",
+"pM pG48M Zp4GM sZ4GM 4GvL v4+GL v4GHL gv4GL v4G5L v>4GL 4GHv5L g4Lv>G 4GvM ",
+"vM4+G Zv4GM gZ4GM pv4GM >Mv4G pvGZ4M 4GyM 3F#L 3F&L 3FL#B a&3FL 3L.#F 8&3FL",
+" #L.3BF a&38FL #3MF &3MF TM#3F aM3&F Mj#3F M&38F Mj#T3F sM&3F 3FL#( +&3FL #",
+"3(LBF a&3+FL #(F3L. 8&3+FL (FLB#3. 3F+L8a& M#3(F M&3+F M#3T(F +T3M&F j#3M(F",
+" +M3&jF 3(MFTj# M&3s+F #3GL &3GL GH#3L Ga&3L G#3L. G8&3L H#3GL. H83G&L M#G3",
+" G3M& GTM#3 GT&M3 GMj#3 G8M&3 HM#Gj3 sGM&3 Gd#3L d&3GL Hd#G3L gG&3L d#3GL. ",
+"G83d&L H#G3dL. G8&g3L dM#G3 dM&G3 GT#dM3 gMG&3 GM#dj3 dM3G&j dMGjH#3 sG&gM3",
+" #F4L &F4L 4#FLB 4a&FL 45#FL 48&FL 5B#4FL 5aF4&L M#4F 4FM& 4TM#F 4T&MF 4M5#",
+"F 48M&F 5T#4MF s4M&F 4;#FL ;&F4L ;#F4LB 4aF;&L 5;#4FL >&4FL 5#4L;FB 4a&>FL ",
+"M;#4F M;&4F 4T#M;F a;F4M& 4M#;jF >M4&F 5FM;4T# s4&>MF G#4L 4LG& 4GH#L 4Ga&L",
+" 4G5#L 4G8&L G5#4HL 4GLH5& 4#GM GM4& 4GTM# 4GTM& 4GM5# 4G8M& 4G#H5M s4GM& 4",
+"Gd#L 4+G&L G;#4HL g4G&L G5#4dL >G4&L HL5d4G# >G&g4L 4GMd# dM&4G dM#4GT g4MG",
+"& dM#4Gj >MG4& 5#dM4GT >M&s4G 3FN#L &3FLN #LN3BF &3FaLN #LN3F. &3F8LN 3LNB#",
+"F. 3F&N8aL QM#3F M&3QF TM#Q3F Qa3M&F Mj#Q3F Q83M&F TMQj#3F M&3sQF #(L3FN &3",
+"F+LN (FLB#3N 3L+Na&F 3F#LN.( 3L+N8&F (BN.3F#L 8a+F3L&N M#3Q(F +Q3M&F 3(MFQT",
+"# Q3aM+&F 3(MFQj# j3+FQ&M TjQ#3(MF M&s3+QF GW#3L G&W3L HW#G3L Wa3G&L W#3GL.",
+" W83G&L W3HLG#. HLW&G83 GQM#3 GQ&M3 ZGM#3 Z&GM3 WM#Gj3 M&3GQ8 GMjZ#3 sGMZ&3",
+" Wd#G3L G&3+WL W3HLGd# G&Wg3L W3GLd#. GW+38&L 3LH.WdG# GWg38&L GQ#dM3 dM3GQ",
+"& dM#ZG3 gMGZ&3 Q#G3dMj W38M+G& dMZjG#3 sGgZM&3 4m#FL m&F4L m#F4LB 4aFm&L 5",
+"m#4FL 48Fm&L mL4B5#F am5&4FL Mm#4F Mm&4F 4T#MmF aMF4Q& p4M#F p&4MF 4TMp#F s",
+"4Mp&F m;#4FL 4+Fm&L mL4B;#F a;4&mFL 5#4Lm;F m&F>L4 LB;F5m4# am>&4FL 4Q#M;F ",
+"M;F4Q& Q#M;4TF MmT&4+F M;#p4F p&4>MF M;p#4TF >&s4pMF 4GW#L 4G&WL Gm#4HL amL",
+"4G& G5#4WL m&L4G8 W#4LG5H HL5&4GW 4GQM# Mm&4G Z4GM# Z4&GM pG4M# pG&4M pGMZ4",
+"# Z4MpG& v4G#L v&4GL 4GHv#L v&Gg4L 4G5v#L >G4v&L 45v#GHL >&g4vGL vM4G# vM&4",
+"G vMGZ4# Z4GvM& vM4pG# >M4pG& ZGvMp4# y&4GM UI3 I3U! DIU3 U3aI I3U. U38I UD",
+"I3. U8ID3 IM3 I!M3 VI3 aIV3 U3Ij 83IM IjV3 VIs3 I3U( U3+I UDI3( U+DI3 UI3(.",
+" U+8I3 DI3U(. +DIU83 M3I( +3IM I3V( +IV3 IM3j( U+jI3 VIj3( sIV+3 UG3 G3U! J",
+"U3 UaJ3 G3U. U3G8 U3J. U8J3 U3GM IM3G! VJ3 VaJ3 U3Gj UG8M3 VjJ3 s3VJ U3Id U",
+"3+G UdJ3 JUg3 Id3U. U+G83 JUd3. gJU83 I3dM IdM+3 J3Vd g3VJ IdMj3 IdM83 JjVd",
+"3 gVJs3 4UI U!4I UD4I Ua4I U54I U84I 4U5DI 4U8aI 4IM 4!IM V4I 4aVI Uj4I 8I4",
+"M 4IV5 V4sI U;4I U+4I 4UDI; 4U+aI 4U5I; 4U>I U5D4I; >I4Ua I;4M +I4M 4IV; 4+",
+"VI IM;4j 4I>M V45I; >IV4 4UG 4!UG J4U 4UJa U54G UG48 4UJ5 4UJ8 UG4M 4UGM! J",
+"4V JaV4 UG4j 4UG8M V4J5 VJs4 UG4d U+4G 4UJ; J4gU 4UG5d 4U>G J4U5d >UJ4 Id4M",
+" IdM4+ V4J; J4gV IdM4j >MG4U J4V5d J4V> I3UN U!I3N UDI3N UaI3N UI3N. U8I3N ",
+"DI3UN. 8I3UaN U3QI IM3Q! QIV3 VQaI3 IM3Qj UQ8I3 VQIj3 sIVQ3 UI3(N U+I3N DI3",
+"U(N +I3UaN I3(UN. +I3U8N D3UNI(. +3UND8I IM3Q( U+QI3 VQI3( V+QI3 UQ3Ij( Ij3",
+"U+Q Ij3VQ( V+QsI3 U3WI UGW!3 UWJ3 JUWa3 UGW3. UG8W3 JUW3. J8UW3 U3GQ UGQ!3 ",
+"Z3VJ ZJVa3 UGQj3 UGQ83 ZJVj3 sJZV3 Id3UW U+GW3 JUWd3 gJUW3 UW3Id. Id3UW8 UW",
+"dJ3. gUWJ83 IdMW3 U+GQ3 ZJVd3 gVZJ3 Id3UWj Id3UQ8 VZdJj3 sJZgV3 Um4I Im!4U ",
+"4UDIm 4UaIm 4U5Im 4U8Im U5D4Im U8m4aI UQ4I IMm4! 4QVI V4QaI 4UpI pU48I pIV4",
+" Vps4I Im;4U 4U+Im 4UDIm; U+m4aI 4U5Im; >I4Um ImU;4D5 4Ua>Im IMm4; IMm4+ V4",
+"QI; V4+QI pU4I; >MIp4 Vp4I; V>p4I UG4W 4UGW! 4UJm J4UWa 4UG5W 4UGW8 J4U5W J",
+"48UW UG4Q 4UGQ! VZJ4 ZJ4Va 4UpG pUG48 J4Vp JpVs4 4UvI vU4+G vUJ4 Jvg4U vU4G",
+"5 v>U4G Jv4U5 J>v4U 4IvM vIM4+ J4Vv VvJg4 pvU4G >Mv4I JpVv4 J4yV UIb3 U3I& ",
+"bUDI3 UIc3 bUI3. I&3U8 UDIb3. cU8I3 b3IM I3M& bIV3 VIc3 IM3bj IM&83 VbIj3 s",
+"IVc3 bUI3( I&3U+ UDIb3( cU+I3 UI3b(. U+8I&3 3(U.bDI U+8cI3 IM3b( IM&+3 VbI3",
+"( Vc+I3 bM3Ij( IM3b+j Ij3Vb( Vc+sI3 b3UG U3G& bUJ3 JUc3 bGU3. bG8U3 JbU3. c",
+"JU83 b3GM IM&G3 VbJ3 c3VJ bGMj3 bG8M3 JjVb3 sJVc3 Id3bU b+GU3 JbUd3 cJUg3 U",
+"G3bd. I&3U8d bdUJ3. gcUJ83 IdMb3 IdM&3 VJbd3 gVJc3 IM3bdj Id3b8M VdbJj3 sJc",
+"gV3 bU4I U&4I 4bUDI 4UcI 4bU5I 4b8UI b5U4DI c4U5I bM4I IM4& 4bVI cIV4 4bM5I",
+" IM&48 V4b5I c4VsI 4bUI; I;&4U b;U4DI c4U+I b5U4I; >I4U& 45b;UDI c>4UI IM;4",
+"b IM;4& V4bI; c4V+I 4bMI;j >Mb4I I;jV4b V>c4I bG4U UG4& 4bJU cUJ4 4bGU5 4bG",
+"U8 J4bU5 cJ4U5 bG4M IM&4G JbV4 VJc4 4bGUj 4bG8M J4Vb5 sJ4Vc 4bGUd 4b+UG J4b",
+"Ud cJ4gU bG54Ud >bG4U 4bdJ5U J>c4U IdM4b IdM4& J4Vbd gV4cJ 4bMIdj >Mb4G J4b",
+"V5d J>Vc4 bUI3N I&3UN UDIb3N cUI3N UI3bN. U83I&N D3UNbI. U8Ic3N IM3bQ IM&Q3",
+" VbQI3 cQVI3 bQUIj3 IM3bQ8 Ij3VbQ cQVsI3 UI3b(N U+3I&N D3UNbI( U+Ic3N 3(U.b",
+"IN b3U+8IN UDb.3(IN UIc3+8N bQ3IM( IM3b+Q bQIV3( V+IcQ3 Qjb3IM( b3+Q8IM IjV",
+"3bQ( s+cQVI3 bGUW3 UG&W3 JbUW3 cJUW3 UG3bW. I&3UW8 bWUJ3. J8UcW3 bGQU3 IM&W",
+"3 ZJVb3 ZcJV3 IM3bWj IM3bW8 JjVZb3 ZcVsJ3 bWUId3 Id3UW& bWUJd3 gJUcW3 Wdb3U",
+"G. b3+GUW8 W3J.bdU gWJ8cU3 Id3bWM Id3UQ& VJdZb3 ZcJgV3 IdWjbM3 +WUjI&3 djJ3",
+"ZbV g3sJZcV 4bUIm Im&4U bmU4DI c4UIm b5U4Im 4U8Im& 45bmUDI 4U8cmI IMm4b IMm",
+"4& V4bQI c4VQI pb4IM pU&4I Vp4bI cpV4I 4bUIm; 4U+Im& Imb;4UD 4U+cmI Imb;4U5",
+" Im&>U4 bU4I5mD; c4U>Im 4bQIM; 4b+IMm 4bQV;I c4IV+m IM;pb4 >I4pU& pbIV4; V>",
+"4cpI 4bGUW 4UGW& J4bUW cJ4UW bG54UW bG84UW 4bWJ5U c4UJ8m 4bGUQ IM&4W ZJ4Vb ",
+"Zc4VJ pbG4U pUG4& JpV4b cpJV4 vb4UG vU&4G Jv4bU cvJ4U 4bGvU5 >I4vU& vb4J5U ",
+"J>4cvU vbM4G vIM4& VvJ4b cvVJ4 pb4vIM >I4vbM Vv4Jpb yJVc4 6kF kF6! kF6B 6Fa",
+"k 1k6F 6F8k 61kFB akF68 6MF MF6! 6FTk 6FaM l6F 68lF 6TlF sFl6 k(6F 6F+k 6k(",
+"FB akF6+ 61k(F 6+1kF 1k(6FB 6+1akF M(6F 6F+M 6Tk(F 6+TkF 6(lF 6+lF l6T(F ls",
+"6+F 6Gk 6!Gk Gk6H Gk6a 61Gk Gk68 6G1Hk 6G8Hk 6GM 6!GM GT6M Ga6M lG6 6Gl8 6G",
+"lH s6lG Gk6d +k6G 6GHdk 6Ggk 6G1dk 6+G8k 1GH6dk g61Gk GM6d +G6M 6GTdk 6GgM ",
+"6Gld 6+lG lG6Td g6lG 4kF kF4! kF4B 4Fak 7kF 8k7F kF7B ak7F 4F6M 4kM!F 4FTk ",
+"4TkaF 7lF 78lF lF7T sF7l 4Fk; 4F+k k;F4B ak;4F k;7F 7k>F 7Bk;F 7>akF 6FM; 4",
+"+kMF 4Tk;F aM;6F 7;lF >F7l 7lT;F l>7sF 4Gk 4!Gk Gk4H Ga4k 7Gk G87k Gk7H Ga7",
+"k 6G4M 4GkM! GT4k 4GTak lG7 l87G 7GlH lG7s Gk4d +G4k 4GkH; 4Ggk Gk7d 7G>k 7",
+"GHdk 7Ggk GM6; 4+G6M 4GTdk g4kGT 7Gld 7>lG 7GTld lGg7 kF6N 6!kFN 6kFNB akF6",
+"N 61kFN 68kFN 1kF6NB 68FakN 6FQk 6Qk!F 6QTkF 6QakF 6QlF l6Q8F l6QTF ls6QF 6",
+"k(FN 6+kFN k(F6NB 6+FakN 1k(6FN +kF68N 1k6(NBF 6F1+akN 6Qk(F 6+QkF Qk(6TF a",
+"kF6+Q l6Q(F l+6QF 6QTl(F s6Ql+F Gk6W 6GWk! 6GHWk 6GaWk 6G1Wk 6G8Wk 1GH6Wk G",
+"8k6Wa GQ6M 6GQM! 6GZk Z6Gak 6GlW lG6W8 Z6lG lZs6G 6GWdk 6+GWk GkH6Wd g6GWk ",
+"1GW6dk +Gk6W8 61GkHWd 6G8gkW 6GQdk 6+GWM Z6Gdk gZ6Gk lG6Qd l+G6W lZ6Gd glZ6",
+"G 4Fkm kmF6! kmF4B akm4F km7F 78kmF 7BkmF 7akmF 4FQk 4Qk!F 4QkTF aMm6F lF7p",
+" 7lp8F 7lpTF 7slpF km;4F 4+kmF 6mFk;B akF6+m 7km;F 7>mkF km;7BF >km7aF 4Qk;",
+"F 4+QkF kmF6T; akF4+Q 7lp;F l>p7F l;p7TF 7spl>F Gk4W 4GkW! 4GkHm akm4G Gk7W",
+" 7GW8k 7GHWk 7GaWk GQ4k 4GQk! 4GZk Z4kGa 7plG 7pGl8 lG7Z 7sGlZ 4Gvk v6+Gk v",
+"6GHk gv6Gk vk7G 7>Gvk 7vGHk g7vGk 6GvM v6M+G Zv6Gk Z4kgG lG7v l>G7v lvZ7G l",
+"Gy7 9k6F 6Fk& 69kFB akF6& 691kF 6k:F 91k6FB :6akF 6F9M 6FM& 6T9kF 6T&kF 69l",
+"F :6lF l69TF ls:6F 69k(F k&F6+ 9k(6FB 6+9akF 91k6(F :6+kF 916k(BF akF:6+ 6M",
+"9(F 6+M9F 9T(6MF k&F6+T l69(F l:6+F 6T9l(F s:6l+F 69Gk Gk6& 6G9Hk 6Gak& 6G9",
+"1k 6G:k 9G16Hk :G6Hk 9G6M GM6& 6GT9M 6GTk& 6Gl9 l6:G lG69H lsG:6 6G9dk dk&6",
+"G 9GH6dk g69Gk 9G16dk :G6+k 691HGkd g:6Gk 6GM9d dM&6G 9GT6dM g6M9G lG69d l:",
+"G6+ 6GTld9 gl:6G 9k4F 4Fk& 49kFB 49akF 9k7F :k7F 7B9kF 7:akF 4F9M 49M&F 49T",
+"kF 49aMF lF79 lF7: 7l9TF 7sl:F k;F49 k;&4F 49Fk;B akF49+ 79k;F 7:>kF k;F7B9",
+" :>F7ak 49M;F M;&6F k;F49T aMF49+ 7l9;F l>7:F l;97TF 7s:l>F 9G4k Gk4& 49GHk",
+" 49Gak 9G7k 7k:G 7G9Hk 7:GHk 9G4M 49GM& 49GHM 49GaM l97G 7:lG 7GTl9 7sGl: 4",
+"9Gdk dk&4G 9G;4Hk g49Gk 7G9dk 7:G>k 9G;7Hk g7:Gk 49GdM M;&6G 9GT4dk g49GM l",
+"G79d l>G7: 7G9lH; gl7:G 69kFN k&F6N 9kF6NB 6aFk&N 91k6FN :6kFN 916kNBF akF:",
+"6N 6Q9kF 6Q&kF 9QT6MF akF6Q& l69QF :Q6lF 6Q9lTF ls6:QF 9k(6FN 6+Fk&N 9k6(NB",
+"F ak6&+FN 916k(FN 6+k:FN NB1F9k6( ak:F6+N 9Q(6MF k&F6+Q QT6F9M( 6F+Q9aM 6Q9",
+"l(F l+6:QF 69l(QTF l6:Qs+F 6G9Wk 6G&Wk 9GH6Wk Gak6W& 9G16Wk :G6Wk 691HGkW 6",
+"Ga:Wk 6GQ9M 6GQk& Z69Gk Z6&Gk lG69W :GQl6 lZ69G Z:l6G 9GW6dk +Gk6W& 69HkGWd",
+" 6G&gkW 691WGkd 6+G:Wk GH1d69Wk g6G:Wk 9GQ6dM 6GQdk& 6GMZ9d Z6Gg9M 6GQld9 :",
+"G6l+W lG6Z9d Z:6glG kmF49 km&4F 49FkmB akF6m& 79kmF 7:kmF kmF7B9 :mk7aF 49Q",
+"kF Mm&6F kmF49T akF49Q 7lp9F :pl7F p9l7TF :pl7sF 49mk;F kmF49+ km6;9FB ak6m",
+";&F km;79F :mk7>F km7B9;F ak:m7>F k;F49Q k;F4Q& Tk9;4QF aM9m4+F l;97pF :p7l",
+">F l97Tp;F >F7s:pl 49GWk km&4G 9Gm4Hk 49Gakm 7G9Wk 7:GWk 9Gm7Hk 7Gk:Hm 49GW",
+"M Mm&6G Z49Gk Z4kG& 7pGl9 :pG7l 7Zl9G 7Z:lG v69Gk v6&Gk 49GvkH g4Gvk& 7v9Gk",
+" :vG7k v9G7Hk g7G:vk v6M9G v6MG& Z4Gv9M Z4Gg9M lv79G lv:7G 7Z9lvG yl7:G 6UI",
+" 6!Ik Dk6I Ua6I 1U6I U86I 6U1DI 6U8aI 6IM 6!IM V6I 6aVI lI6 68lI V6lI s6lI ",
+"6(Ik U+6I Ik(6D 6U+aI Ik(61 6U+1I 6D1Ik( 1U+6aI 6(IM +I6M 6IV( 6+VI 6Il( 6+",
+"lI Vl6I( lsI6+ 6UG 6!UG J6U 6UJa 1U6G UG68 6UJ1 6UJ8 UG6M 6UGM! J6V JaV6 6U",
+"lG lG6U8 lJ6 s6lJ UG6d U+6G 6UJd J6gU Idk61 Idk68 J61Ud gJ61U Id6M IdM6+ Vd",
+"J6 J6gV 6Ild l+G6U J6ld g6lJ 4Ik 4!Ik Dk4I aI4k 7UI U87I Dk7I Ua7I 6I4M 4Ik",
+"M! 4IV6 V46aI lI7 l87I 7VI lI7s U;6I +I4k Ik;4D ak;4I U;7I 7I>k 7UDI; 7>UaI",
+" IM6; IM;6+ 6IV; V4+6I 7Il; 7>lI V;7I 7IV> 6U4G 4UG6! J4k 4aJk 7UG UG78 7JU",
+" J87U 4UG6M Ik!4GM V4J6 J4V6a 7UlG 7UGl8 7Jl sJ7V UG6; Idk4+ 4dJk J4gk UG7d",
+" >U7G Jk7d >k7J Idk4M 4+kIdM V6J; gV4J6 7Ild l>G7U ld7J 7Jgl 6NIk IkN6! IkN",
+"6D 6UaIN IkN61 6U8IN 6D1IkN akN68I UQ6I 6UQI! 6QVI V6QaI 6QlI lI6Q8 Vl6QI l",
+"sI6Q Ik(6N 6U+IN 6D(IkN akN6+I 1U(6IN 6UN1+I 6(1UDIN 6NU+1aI 6UQI( 6U+QI V6",
+"QI( V6+QI lI6Q( l+I6Q V6QlI( sIQV6+ UG6W 6UGW! 6UJW J6WUa 6UG1W 6UGW8 J61UW",
+" J68UW UG6Q 6UGQ! J6Zk ZJ6Va 6WlI lWI68 Z6lJ lJZs6 Idk6W 6U+WI J6WUd gJ6UW ",
+"1UW6Id 6W8Idk 6UWJ1d J6Wg1U Idk6Q 6U+GQ ZJ6Vd gV6ZJ lWI6d l+W6I lJZ6d glJZ6",
+" Um6I Ikm6! Ikm4D akm4I Um7I 7U8Im 7UDIm 7UaIm QI4k IMm6! 6IVm V6maI 7plI 7",
+"pU8I 7IVp 7sIVp Ikm6; Ikm4+ 6DmIk; 4+DIkm 7UIm; 7>UIm Ikm7D; >Im7Ua Ik;4Q I",
+"Mm6+ V6mI; V6+Im 7pUI; l>I7p 7VpI; 7V>pI UG6m 4WIk! 4WJk J4kWa UG7W 7UGW8 J",
+"k7W 7JUW8 IMm6G Ik!4GQ J4Zk ZJ4ak 7WlI 7pUG8 Jp7V Jpl7s 4Ivk v6U+G v6Jk Jv6",
+"gU vU7G 7vU>G 7UJv J>k7v 6IvM v6I+M J6Vv Vv6gJ lI7v lvI7> 7Jlv 7Jyl t6I 6It",
+"& 6DtI tIc6 6It1 t6:I t61DI t:c6I 6ItM IM6& tIV6 cIV6 t6lI l6:I ltV6I u6I 6",
+"It( 6+tI t6DI( tc6+I t61I( t:6+I 6D1tI( :c6t+I t6IM( t+6IM Vt6I( t+V6I lt6I",
+"( lt+6I Vt6lI( 6+uI tG6 6Gt& tJ6 c6tJ 6Gt1 t6:G t6J1 J6t: 6GtM tG6M& VtJ6 V",
+"Jc6 l6tG t:Gl6 J6lt uJ6 6Gtd 6+tG J6td g6tJ tG61d t:G6+ tJ61d gtJ:6 tG6dM t",
+"+G6M tdVJ6 gV6tJ ltG6d t+Gl6 lJt6d gJu6 t4I 4It& 4DtI tIc4 7tI 7It: tD7I 7I",
+"tc 4ItM t4IM& tIV4 tc4VI lI7t 7:lI Vt7I u7I 4It; 4+tI t4DI; tc4+I 7It; 7It>",
+" 7tDI; t>7cI t4IM; t4+IM t4VI; t4V+I 7tlI; l>I7t 7VtI; 7>uI t4G 4Gt& tJ4 cJ",
+"t4 7tG 7:tG 7Jt tJ7c 4GtM t4GM& VJt4 tJ4Vc lG7t 7tGl: tJ7V uJ7 4Gtd 4+tG J4",
+"td g4tJ 7Gtd 7>tG td7J 7Jgt t4GdM t4+GM tJ4Vd gt4VJ 7tGld t>G7l lJ;7t g7uJ ",
+"6ItN t6I&N t6DIN tc6IN t61IN t:6IN 6D1tIN :I6tcN 6QtI tQ6I& tQV6I tcQ6I tQ6",
+"lI t:Q6I Vl6tQI 6QuI t6I(N t+6IN 6DIt(N c6It+N 6I1t(N :I6t+N 61t(DIN t6:Ic+",
+"N tQ6I( t+Q6I V6ItQ( t+Ic6Q lI6tQ( t+6:QI l6tQVI( u6+QI 6GtW tG6W& J6tW tcW",
+"J6 tG61W t:G6W tJ61W :Jt6W 6GtQ tGQ6& Z6tJ Zc6tJ tGQl6 t:G6Q lJZt6 ZJu6 tG6",
+"Wd t+G6W tJ6Wd gtJ6W 6WItd1 t+6:WI J61tWd :J6gtW tGQ6d t+G6Q tZJ6d gtZJ6 tW",
+"6lId t+6:GQ tZ6lJd ug6ZJ 4Itm t4Im& t4DIm tc4Im 7Itm t:m7I 7tDIm 7ctIm 4QtI",
+" t4QI& t4VQI tc4QI 7Itp :pI7t tp7VI 7puI t4Im; t4+Im 6Dmt;I t+Ic6m 7tIm; t>",
+"7Im 7DItm; 7cIt>m t4QI; t4+QI tQIV6; t4IcQ; tp7I; tp>7I 7VItp; u7Ip> 4GtW t",
+"4GW& J4tW tJ4cW 7GtW 7tG:W tW7J 7Jt:W 4GtQ t4GQ& ZJt4 tZ4cJ 7ptG tpG7: 7JtZ",
+" 7ZuJ v6tG tv4+G t4Jv cv6tJ tG7v :vI7t 7Jtv g7tJv tv4GQ t4+GQ Vv6tJ cvVJ6 l",
+"vt7G :vI7l lvJ7t yJu7 <e <e! <eB a<e <e. 8<e e.<B a<8e <eK <!eK T<e a<Te <j",
+"e <j8e <jTe s<e <e* +<e <e*B a<+e e*<. 8<+e *B<e. +<a8e e*<K <e+K <eT* T<+e",
+" <e*j <j+e <jeT* +<se G< G<! G<H Ga< G<. G8< G.H< H8G< G<K <KG! GT< T<Ga G<",
+"j 8<Gj H<Gj sG< f< f+< fH< gf< f<. f8< H<f. f8g< f<K +<fK fT< fTg< fj< +<fj",
+" H<fj sf< 4e 4e! 4eB 4ae 4e5 48e 4B5e 5a4e 4eK eK4! 4Te Te4a 4ej 8e4j 5T4e ",
+"s4e =e =+e =Be =ae =5e >e= 5e=B =a>e =eK +e=K =Te +T=e =je =j>e 5T=e s=e 4G",
+"< 4!G< 4He Ga4e G5< G84e H54e H84e 4KG< 4G<!K GT4e 4GTa< G<4j 4G8<j He4j 4G",
+"s< f= f=+ =Hf g=f f=5 f>= f5=H f>g= f=K f+=K =Tf gf=T =jf =jf> f5=T sf= <eN",
+" <!eN eN<B <eaN eN<. <N8e <eN.B aeN8< Q<e <eQ! T<Qe a<Qe <jQe 8<Qe <jeQT Q<",
+"se e*<N <e+N *B<eN aeN+< <e*N. +<8eN <eN*B. +<8aeN <eQ* Q<+e Q<Te* +Q<Te <j",
+"eQ* +Q<8e Q<Tej* s<+Qe G<W W!G< W<He WaG< G.W< W8G< G<HW. G8<Wa GQ< Q!G< Z<",
+"G GaZ< W<Gj Q8G< G<Zj Z<sG fW< +Wf< H<fW fWg< W<f. W8f< fHW<. f8Wg< fQ< +Qf",
+"< Zf< g<Zf W<fj Q8f< fjZ< s<Zf 4em 4!em 4Bem am4e <m5e 8m4e <mB5e aem48 4Qe",
+" Q!4e Qe4T Qa4e p<e 48pe 4Tpe p<se =em +e=m em=B ae=m 5e=m =e>m =B5em >e=am",
+" =Qe +Q=e Qe=T Qa=e p=e >ep= pe=T sep= 4We 4!We H<Gm Wa4e 5W4e W84e 4He5W 4",
+"H8We GQ4e 4GQ<! Z4e 4aZe pG< G8p< pGZ< Z4se fv= =+fv fv=H fvg= v=f5 v>f= =H",
+"fv5 g=fv> =Qf =+fQ Z=f Zfg= fp= p=f> fpZ= yf= ,<e <&e <e,B <&ae <e,. <&8e ,",
+"<e.B <&e8a <e,K <Ke& ,<Te <&Te ,<ej e&<j <je,T <&se <e,* -<e *B<,e a<-e ,<e",
+"*. 8<-e ,<e*B. -8a<e ,<e*K <e-K ,T<e* T<-e <je,* <j-e ,T<ej* -<se ,G< G<& G",
+"<,H G<,a ,.G< G<,8 ,GH<. ,G8H< ,KG< GK<& G<,T T<G& G<,j <&Gj ,GT<j ,Gs< f<,",
+" f-< ,Hf< f-g< ,<f. -8f< fH<,. f-8g< ,<fK fK-< ,Tf< f<-T ,jf< f<-j fT<,j f-",
+"s< ,4e 4e& 4B,e 4e,a 4e,5 4e,8 ,45eB ,48ae ,K4e 4Ke& 4e,T Te4& 4e,j e&4j ,4",
+"T5e ,4se =e, -=e ,e=B -a=e ,5=e -=>e =B5,e >e-=a ,e=K -e=K ,T=e =e-T ,j=e =",
+"e-j =T5,e -=se ,4G 4&,G 4G,H 4G,a 4G,5 4G,8 ,4GH5 ,4GH8 ,K4G ,4G&K 4G,T ,4G",
+"T& 4G,j <&j4G ,4GHj ,4sG f=, f-= fH=, f-g= =,f5 ->f= =Hf,5 g=f-> f,=K =Kf- ",
+"=,fT f-=T =,fj f-=j =Hjf, f-s= <e,N <Ne& ,<eNB aeN<& ,<eN. <&e8N <eN,.B ,8<",
+"aeN ,<Qe <&Qe ,QT<e ,Qa<e <je,Q <&jQe ,QT<je s<Qe& ,<e*N <e-N ,<e*BN -a<eN ",
+"<e*,N. -8<eN ,<*BeN. aeN-8< ,Q<e* Q<-e Q<e,T* -QT<e ,Q<ej* -Q8<e QT,j<e* s-",
+"Q<e G<,W W<G& ,GHW< ,GaW< ,GW<. ,G8W< G<H,W. G8<,Wa G<,Q Q<G& ,GZ< G<Z& ,GQ",
+"<j <&jGQ Z<G,j Z<&sG ,Wf< f<-W fHW,< f-Wg< fW<,. f-W8< ,HWf<. gf8-W< ,Qf< f",
+"<-Q f<Z, f-Z< fQ<,j f-Q8< Zf<,j sfZ-< 4e,m em4& <mB,e aem,4 ,45em <m&5e ,45",
+"emB ,48aem 4e,Q Qe4& ,4QTe <m&Te ,4pe 4ep& p<T,e p<&se ,m=e =e-m =Be,m =a-e",
+"m =5e,m >e-=m emB=5, =a->em ,Q=e =e-Q =QT,e =Q-Te =ep, pe-= p=T,e -ps=e 4G,",
+"W We4& ,4GHm <m&Ga ,4G5W <m&G5 4He,5W 4G8,Hm 4G,Q <m&GQ ,4Ze 4eZ& ,4pG G<p&",
+" Zp<,G Zp<G& v,f= f=-v =Hfv, g=f-v fv=,5 f>-v= fv5=H, f>-g=v =,fQ f-=Q f=Z,",
+" f-Z= p,f= f-p= fpZ=, f-y= I< I<! D<I aI< I<. 8I< D.I< 8ID< I<K <!IK TI< aI",
+"T< I<j Ij8< I<Dj sI< I<* +I< I<D* D<+I <*I. 8I+< I<*D. +D<8I <*IK +KI< I<T*",
+" TI+< <jI* I<+j I<jD* +Is< G<I G!I< J< J<a G.I< 8IG< J<. J8< GKI< I<KG! J<T",
+" T<Ja I<Gj I<jG8 J<j sJ< fI< +If< Jf< gJ< I<f. 8If< f<J. J8g< I<fK f+I<K fT",
+"J< gTJ< I<fj f8I<j fjJ< g<sJ 4I< 4!I< 4De De4a 5I< 8I4e 5D4e D84e 4KI< I<K4",
+"! De4T 4DeTa I<4j I<j48 De4j 4Dse =I =I+ =DI =aI =I5 =I> 5D=I =D>e =IK +I=K",
+" =TI +T=I =Ij >I=j 5T=I s=I G<4I I<!4G J4< 4aJ< 5IG< 4G8I< J5< 48J< I<K4G 4",
+"GKI<! 4TJ< J4Ta< I<j4G 4G8I<j 4eJj J4s< =If f+=I J= J=g f5=I =If> J=5 J>= f",
+"I=K =If+K J=T =TgJ fj=I f>=Ij J=j s=J I<N <!IN DNI< aNI< <NI. IN8< I<ND. D8",
+"<IN QI< Q!I< D<QI aIQ< IjQ< 8IQ< I<jQD QIs< <*IN +NI< I<*DN +D<IN I<*N. +I<",
+"8N D<NI*. a*N8I< I<Q* QI+< QD<I* +QDI< I<jQ* I<j+Q QD<I*j sI<+Q WI< W!I< J<",
+"W WaJ< W.I< 8IW< W<J. W8J< QIG< GQ<I! ZJ< ZaJ< I<Wj I<jW8 JjZ< ZJs< WIf< WI",
+"+< fWJ< gWJ< fWI<. f8WI< JfW<. Jf8W< QIf< fQ+I< JfZ< ZJg< fQI<j fQ8I< ZJ<fj",
+" sJ<Zf I<m <!Im Dm4e I<am Im5< I<8m I<m5D I<m5a QI4e I<mQ! QD4e I<mQa pI< 8",
+"Ip< 4Dpe pIs< =Im +I=m De=m aI=m 5I=m >m=I =D5Im >eD=m =QI +Q=I QD=I Qa=I p",
+"=I p>=I pD=I sp=I WI4e I<mW! J<m a<Jm WI5< I<mG8 5WJ< 8<Jm I<mGQ I<!4GQ J4Z",
+"< ZJ4a< G<pI pG<8I Jp< s<Jp =Iv =+vI J=v Jvg= =5vI v>=I v=J5 v>J= fQ=I =Qf+",
+"I Z=J gZJ= =Ifp fp>=I Jp= yJ= h< h<& hD< hc< h<. h8< D<h. c<h8 h<K <&hK hT<",
+" c<hT hj< 8<hj D<hj hs< h<* h-< D<h* c<h- <*h. -8h< hD<*. c-8h< <*hK -<hK T",
+"<h* h<-T <jh* h<-j hT<*j s<h- hG< G<h& hJ< cJ< G<h. G8h< h.J< J8c< G<hK hG<",
+"&K J<hT cTJ< G<hj h8G<j J<hj s<hJ hf< h<f- J<hf i< f<h. h<f8 Jf<h. i8< f<hK",
+" f-<hK h<fT iT< h<fj f-jh< Jfjh< is< h4 h4& h4D hc4 h45 h48 4Dh5 c4h5 h4K 4",
+"&hK h4T c4hT h4j 48hj 4Dhj hs4 h= h=- h=D c=h h=5 h>= h5=D c=h> h=K =Kh- h=",
+"T hc=T h=j =jh> h5=T hs= h4G 4Gh& hJ4 cJh4 4Gh5 4Gh8 J4h5 J4h8 4GhK h4G&K J",
+"4hT cJ4hT 4Ghj h48Gj J4hj h4sJ h=f f-h= J=h i= f=h5 f>h= h5J= i>= =Khf h=f-",
+"K hJ=T i=T hf=j h=jf> hJ=j is= h<N <&hN D<hN hNc< <Nh. 8<hN hD<N. c<8hN hQ<",
+" Q<h& QDh< c<hQ Q<hj Q8h< hQD<j s<hQ <*hN -<hN hD<*N c-<hN h<*N. h-8<N D<*h",
+"N. h-8c<N Q<h* h<-Q hQD<* c-Qh< hQ<*j h-Q8< QD<hj* hs-Q< hW< W<h& J<hW c<hW",
+" W<h. W8h< J<Wh. cJ<W8 GQh< hWQ<& hZ< Z<hc W<hj hW8Q< Z<hj s<hZ fWh< h<-W J",
+"fWh< iW< hfW<. hf8W< hfWJ<. W8i< h<fQ f-Qh< Z<hf iZ< hfQ<j fQ8h< hZf<j sZi<",
+" h4m 4&hm 4Dhm c4hm 5<hm 48hm h45Dm c5<hm h4Q 4Qh& 4QhT c4hQ hp4 p<h8 pDh4 ",
+"h4cp h=m -=hm hm=D hmc= =5hm >=hm h=5Dm c=h>m h=Q h-=Q hQ=D hc=Q hp= h=-p =",
+"Dhp s=hp h4W 4Wh& J4hW c4hW 4Wh5 4Wh8 J5<hW cJ5W< 4GhQ h4WQ& hZ4 h4Zc pGh4 ",
+"hp4G8 h4Jp sZh4 hv= -vh= J=hv iv= v=h5 v>h= J=hv5 v>i= =Qhv h=Q-v hZ= iZ= h",
+"=fp fp-h= Z=hp yi= 6e 6e! 6eB 6ae 6e1 68e 6B1e 1a6e 6eK eK6! 6Te Te6a 6ej 8",
+"e6j 1T6e s6e 6e* 6+e *B6e +e6a 1e6* 1+6e 6e1*B 6+e1a e*6K 6K+e Te6* +T6e ej",
+"6* +e6j 6Te1* 6+se 6G< 6!G< 6He Ga6e 1G< G86e 1H6e Ga1< 6KG< 6G<!K GT6e 6GT",
+"a< G<6j 6G8<j GT1< 6Gs< f6 f6+ f6H gf6 f61 f68 6Hf1 f6g1 f6K 6+fK f6T fTg6 ",
+"f6j 6+fj 6Hfj sf6 4e6 6!4e 4B6e 6a4e 7e 7e8 7eB 7ae 4K6e 4e6!K 6T4e 4Te6a 7",
+"ej 8e7j 7Te 7se =6e 6+=e 6e=B 6a=e 7=e >e7 =B7e 7a>e 6e=K =6+eK 6T=e =T6+e ",
+"7e=j >j7e 7e=T >e7s 6G4e 4G6<! 6H4e 4Ga6e 7G< G87e 7He Ga7e 4G6<K 6GK4e! 4G",
+"T6e 6GT4ae G<7j 7G8<j GT7e 7Gs< f=6 =+f6 f6=H f=g6 7f 7f> 7fH g7f =Kf6 f=6+",
+"K f6=T g=f6T 7fj fj7> 7fT sf7 6eN eN6! eN6B 6Nae 6N1e 6N8e 6e1NB 68eaN 6Qe ",
+"Q!6e Qe6T Qa6e 1Q6e Q86e 6Qe1T 6Qse e*6N 6N+e 6e*NB 6+eaN 6e1*N 6+e1N 1eN6*",
+"B aeN68* Qe6* +Q6e 6QeT* 6+QTe 6Qe1* 6+Q1e 1Qe6T* s6e+Q 6We 6!We He6W Wa6e ",
+"1W6e W86e 6He1W 6H8We GQ6e 6GQ<! Z6e 6aZe GQ1< 6GQ8< 6eZ1 Z6se f6W 6+fW 6Hf",
+"W gWf6 6Wf1 6Wf8 f61HW f68gW f6Q 6+fQ Zf6 g6Zf 6Wfj 6Qf8 f6Z1 s6Zf 6em 6!em",
+" 6Bem ae6m 7em 8e7m em7B ae7m 6Q4e 4Qe6! Te6m aem6Q 7pe 78pe pe7T 7pse 6e=m",
+" +e6m =B6em =a6em =m7e >m7e 7=emB 7ae>m 6Q=e =Q6+e =Q6Te =Qa6e 7ep= 7p>e 7p",
+"e=T 7sep= 6W4e 4We6! He6m aem6G 7We W87e He7W Wa7e 4GQ6e <m!6GQ 4eZ6 Z4e6a ",
+"pG7e 7pG8< 7Ze se7Z fv6 f+v6 fHv6 fvg6 7fv f>7v fv7H gf7v f6=Q =Qf6+ fvZ6 Z",
+"f6g= 7fp 7pf> 7Zf y7f ?e ?e& ?Be ?ae ?1e ?:e 1e?B :e?a ?eK e&?K ?Te Te?a ?j",
+"e :e?j 1T?e s?e ?e* ?-e *B?e -a?e 1e?* :e?- ?B1e* ?:-ae e*?K -e?K Te?* ?e-T",
+" ej?* ?e-j ?T1e* ?-se ?G ?G& ?GH ?Ga ?G1 ?:G 1G?H :G?H ?GK G&?K ?GT GT?a ?G",
+"j :G?j 1G?T s?G ?f ?f- ?fH g?f ?f1 :f? f1?H :fg? ?fK ?Kf- ?fT ?Tgf ?fj ?j:f",
+" f1?T s?f ?4e 4e?& 4e?B 4a?e 7?e 7:e ?B7e 7e?a 4e?K ?4e&K 4T?e ?T4ae 7e?j 7",
+"j:e 7e?T 7?se ?=e =e?- ?B=e =e?a 7e?= Ae ?=7eB Aae ?e=K ?-=eK =e?T ?-T=e =e",
+"?j Aje ?T7=e Ase ?G4 4G?& 4G?H 4G?a ?G7 7:?G 7G?H 7G?a 4G?K ?G4&K 4G?T ?GT4",
+"a 7G?j ?:G7j 7G?T ?G7s ?f= f-?= =H?f ?fg= 7f? Af ?H7f Agf =K?f ?f-=K =T?f ?",
+"fTg= =j?f Afj ?T7f Asf ?eN e&?N eN?B ae?N 1e?N ?N:e ?B1eN ?:aeN ?Qe Qe?& Qe",
+"?T Qa?e 1Q?e :e?Q ?Q1Te ?Qse e*?N -e?N ?Be*N ?-aeN ?1e*N ?:-eN 1e*?BN :-e?a",
+"N Qe?* ?e-Q ?QTe* ?-QTe ?Q1e* ?:Q-e 1Qe?T* s?-Qe ?GW G&?W He?W Ga?W 1G?W :G",
+"?W ?G1HW ?:GWa ?GQ GQ?& ?ZG Ze?a 1G?Q :G?Q Z1?G sG?Z ?fW f-?W fH?W ?Wgf f1?",
+"W ?W:f ?f1HW g?:fW ?fQ f-?Q ?Zf ?fZ- f1?Q ?Q:f ?jZf ?Zsf ?me em?& em?B ae?m",
+" 7e?m :e?m ?m7eB ?:mae 4Q?e ?Q4e& Te?m ?Qa4e ?pe 7e:p pe?T se?p =e?m ?e-m ?",
+"=emB ?-mae ?=7em Aem 7=e?mB aeAm =e?Q ?-Q=e ?Tm=e ?-Tem pe?= Ape ?p=Te spAe",
+" ?Gm Gm?& Gm?H Ga?m 7G?W :G?m ?G7Hm ?:GHm 4G?Q ?GQ4& Z4?G ?Z4Ga ?pG ?G:p ?G",
+"7Z sG?p ?vf -v?f fv?H gf?v 7f?v Afv ?v7fH gfAv =Q?f ?fQ-v ?fZ= g?Zfv ?pf Ap",
+"f 7f?Z yAf 6I< 6!I< 6De De6a 1I< 8I6e 1D6e D86e 6KI< I<K6! De6T 6DeTa I<6j ",
+"I<j68 De6j 6Dse 6I* +I6e De6* +D6e 1I6* +I1< 6De1* 6+D1e 6KI* 6+I<K TI6* 6+",
+"DTe I*6j I<j6+ I*j6D 6Is* G<6I I<!6G J6< 6aJ< G<1I 6G8I< J1< 68J< I<K6G 6GK",
+"I<! 6TJ< J6Ta< I<j6G 6G8I<j 6eJj J6s< f6I 6+fI Jf6 Jfg6 6If1 68fI f6J1 J1g<",
+" 6IfK f6+IK fTJ6 Jf6gT 6Ifj f68Ij f6Jj Jfs6 6I4e I<!46 6D4e 4De6a 7I< 8I7e ",
+"7De D87e I<K46 6IK4e! 4De6T 6TI4ae I<7j 7I8<j De7T 7Dse =I6 6+=I 6D=I 6a=I ",
+"=I7 7>=I 7D=I 7D>e 6I=K =I6+K 6T=I =TI6+ 7I=j 7>I=j 7T=I =I7s 4G6I< 4G6I<! ",
+"4eJ6 J46a< G<7I 7G8I< 7J< J87e 4G6I<K 6!4GI<K J46T< 4TeJ6a 7GI<j I<j7G8 J<7",
+"T s<7J f6=I =If6+ J=6 g6J= 7fI 7If> 7Jf J>7f =If6K f6+=IK J6=T J=g6T fj7I 7",
+"f>Ij =T7J 7Jsf 6NI< I<N6! 6NDe 6DeaN 1NI< 68I<N 6De1N 6D8eN QI6e 6QI<! QD6e",
+" 6QDae QI1< 6Q8I< 6QD1e sI<6Q 6NI* 6+I<N 6De*N 6+DeN 6I*1N 68I*N I<N1D* a*N",
+"68I QI6* 6+QI< 6QDI* 6+QDe I*j6Q 6Q8I* 6QDI*j sI*6Q WI6e 6WI<! 6WJ< J6Wa< W",
+"I1< 6W8I< 1WJ< J68W< 6GQI< I<!6GQ J6Z< ZJ6a< I<j6W 6W8I<j J1Z< sJ6Z< 6WfI f",
+"6+WI JWf6 Jf6gW f61WI f68WI Jf61W Jf6W8 6QfI f6Q+I JfZ6 Zf6gJ f6Q1I f6Q8I Z",
+"f6J1 sf6ZJ I<6m I<m6! De6m aem6D I<7m 7I8<m De7m 7De8m I<m6Q Im!6Qe I<m6T 6",
+"QDaem pI7e 7pI8< pD7e 7sIp< 6I=m =I6+m =D6Im =aI6m =m7I 7>I=m 7De=m 7>Dem 6",
+"Q=I =QI6+ =QD6I =Qa6I 7p=I p=I7> p=D7I s=I7p I<m6G I<!6Gm 6eJm J6ma< WI7e 7",
+"WI8< J<7W 7JW8< 6GQI<m I<6mGQ! ZJ46e Z6aJ<m 7pGI< 7G8pI< Z<7J Jp<7s v6=I =I",
+"v6+ fvJ6 J=gv6 =I7v 7vIf> 7vJ= J>=7v =Qf6I =Q+v6I Z6J= Z=Jg6 7Ifp 7fp>I Z=7",
+"J 7Jyf h? h?& h?D ?ch h?1 h:? ?Dh1 ?ch: h?K ?Kh& h?T hT?c h?j ?:hj ?Dhj hs?",
+" h?* h?- h*?D h-?c ?1h* ?:h- ?D1h* h:?c- ?Kh* ?Kh- h*?T ?-hT h*?j ?-hj ?Djh",
+"* h?s- h?G h&?G ?J ?Jc ?Gh1 ?Gh: ?J1 ?J: ?KhG ?G&hK ?JT cJ?T ?Ghj ?:Ghj ?Jj",
+" s?J ?fh h-?f ?Jf i? h1?f ?fh: J1?f i?: ?Khf ?fh-K hT?f i?T hj?f ?fjh: Jf?j",
+" i?s h?4 ?4h& ?Dh4 h4?c 7h 7h: 7hD 7hc ?Kh4 h?4&K ?Th4 ?ch4T 7hj 7:hj 7hT h",
+"s7 h=? ?-h= h?=D ?ch= 7h= Ah =D7h Ahc =Kh? h=?-K h?=T c=?hT =j7h Ahj =T7h A",
+"hs ?Gh4 ?G4h& ?J4 c4?J 7hG 7Gh: ?J7 7c?J ?G4hK h4&?GK J4?T ?Jc4T 7Ghj 7h:Gj",
+" hT7J 7Jhs ?fh= h=?f- ?J= i?= 7hf Ahf 7f?J Ai h=?fK ?f-h=K =T?J =Ti? hj7f h",
+"fAj =j?J Ais h?N ?&hN hN?D hN?c ?1hN hN?: ?D1hN h:?cN h?Q h&?Q ?QhT hQ?c ?Q",
+"h1 ?:hQ ?QDh1 hQs? ?*hN hN?- ?D*hN ?ch-N h?1*N h:?-N h1*?DN ?c-h:N h*?Q ?-h",
+"Q ?QDh* ?cQh- h?Q1* h:Q?- ?Q*h1T hs?-Q h?W h&?W ?JW hW?c ?Wh1 ?:hW J1?W ?W:",
+"J ?GhQ ?GQh& hZ? ?chZ ?Whj h:W?Q h1?Z s?hZ hW?f ?-hW Jf?W i?W ?fh1W h:W?f ?",
+"Jf1W ?:iW hQ?f ?fQh- ?fhZ i?Z ?fQh1 :fQh? hZ?f1 s?iZ h?m h&?m ?Dhm hm?c 7hm",
+" ?:hm 7Dhm hm7c ?Qh4 h?Q4& ?Thm ?cQh4 hp? h:?p hT?p s?hp ?=hm ?-hm ?Dmh= c=",
+"?hm 7=hm Ahm 7h=Dm hcAm h?=Q h=Q?- h=Q?D c=Qh? h=?p Aph hp?=D hpAs ?Ghm ?Gm",
+"h& ?Jm cJ?m 7hW 7:hW hW7J hW7c ?GQh4 ?G&h4Q h4?Z hZ?c4 hW?p hp?:G hZ7 7Zhs ",
+"hv? h?-v ?Jv i?v hv7 Ahv 7Jhv Aiv hQ?v hv?-Q ?Zhv ?Ziv ?phv hpAf 7Zhv Aiy <",
+"eL <!eL eL<B <eaL eL<. <e8L <eL.B aeL8< <Me <!Me <MTe <Mae Me<j <M8e <MeTj ",
+"<Mse e*<L <e+L *B<eL aeL+< <e*L. +<8eL <eL*B. +<8aeL <eM* <M+e <MeT* aMe+< ",
+"<Me*j +<M8e T<Mej* s<+Me G<L <LG! GLH< GLa< <LG. GL8< G<HL. G8<HL G<M G!<M ",
+"H<GM a<GM <MGj 8<GM GT<Mj G<sM f<L +<fL H<fL f<gL <Lf. 8<fL fH<L. f8<gL fM<",
+" +<fM H<fM fMg< <Mfj 8<fM fT<Mj fMs< 4eL eL4! eL4B 4Lae 4L5e 4L8e 4e5LB 48e",
+"aL 4Me 4!Me Te4M aM4e 5M4e 8M4e 4Te5M 4Mse =eL +e=L eL=B ae=L 5e=L =e>L =B5",
+"eL >e=aL =Me +M=e Te=M aM=e 5M=e =M>e =T5Me se=M 4LG< 4G<!L 4LHe 4Ga<L GL5<",
+" 4G8<L 4He5L 4H8eL G<4M 4GM<! HM4e aMe4G 5<GM 4G8<M 4HM5e s4G<M f=L f+=L fH",
+"=L =Lgf =Lf5 >Lf= =Hf5L g=f>L =Mf =+fM fT=M gf=M f5=M =Mf> =HMf5 =Msf eL<N ",
+"<eL!N <eLNB aeL<N <eLN. 8<eLN eLN<.B 8<LaeN <MQe <MeQ! <MeQT aMeQ< <MeQj Q8",
+"<Me Q<TMej s<QMe <e*LN +<eLN <eL*BN +<LaeN e*L<N. 8<L+eN NB*L<e. a<+e8LN <M",
+"eQ* +Q<Me Q<TMe* +Q<aMe Q<Mej* Q8<+Me QMejT<* +Q<seM GLW< G<W!L G<HWL Ga<WL",
+" G<WL. G8<WL W<LHe. aeLW8< W<GM GQ<M! G<ZM Z<GaM GQ<Mj GQ8<M Z<GMj sZ<GM W<",
+"fL f+W<L fHW<L gfW<L fW<L. f8W<L H<WfL. g<Wf8L W<fM fQ+<M fMZ< Zfg<M fQ<Mj ",
+"fQ8<M Zf<Mj sfZ<M 4Lem <mLe! <mLeB aem4L <mL5e 48emL 5<LemB aeL8<m Qe4M <Mm",
+"e! <MmTe aMe4Q 4Mpe p<8Me p<TMe sp<Me em=L =+emL =BemL =aemL =5emL >e=mL em",
+"L=B5 =am>eL Qe=M =Q+Me =QTMe =QaMe pe=M p=>Me p=TMe s=pMe 4LWe 4We!L 4HeWL ",
+"4WaeL 4We5L 4W8eL <mLH5e aeL4W8 WM4e <MmG! 4MZe Z4eaM G<pM pG<8M Zp<GM Z4es",
+"M =Lfv fv=+L =HfvL g=fvL fv=5L f>v=L fv5=HL f>vg=L fv=M =Qf+M =MZf g=MZf =M",
+"fp fp>=M fpZ=M =Myf <e,L <Le& ,<eLB aeL<& ,<eL. <&e8L <eL,.B ,8<aeL ,<Me Me",
+"<& <Me,T aMe<& <Me,j <M&8e ,T<Mej s<Me& ,<e*L <e-L ,<e*BL -a<eL <e*,L. -8<e",
+"L ,<*BeL. aeL-8< <Me,* <M-e ,T<Me* -T<Me ,M<ej* -M8<e <M,jTe* s-<Me ,LG< GL",
+"<& ,GH<L ,Ga<L ,G<L. ,G8<L G<L,H. <&LH8e G<,M <MG& ,GT<M <M&GT ,GM<j <M&G8 ",
+"G<M,Hj sG<,M ,<fL -<fL fH<,L f-<gL f<,L. f-8<L ,H<fL. g-<f8L ,Mf< f<-M fT<,",
+"M f-T<M fM<,j f-M8< ,HMfj< sf-<M ,L4e 4Le& ,4eLB ,4aeL ,45eL ,48eL 4eL,5B a",
+"eL,48 4e,M Me4& ,4TMe aMe,4 ,4M5e <M&5e 4Te,5M s4e,M ,e=L -e=L =Be,L =a-eL ",
+"=5e,L >e-=L ,5e=BL =a->eL ,M=e =e-M =TM,e =T-Me =M5,e >M-=e ,5T=Me s=-Me ,L",
+"4G ,4G&L ,4GHL ,4GaL ,4G5L ,4G8L ,4LH5e <&LG5a 4G,M <M&4G ,4GHM Me&4H ,4G5M",
+" <M&G5 4GT,5M s4G,M f,=L =Lf- =Hf,L g=f-L f=5,L f>-=L f5,=HL f>-g=L =,fM f-",
+"=M =HMf, g=Mf- =Mf,5 f>M-= =H,f5M sf=-M ,<eLN <&eLN <eL,NB <&LaeN <eL,N. 8<",
+"Le&N .B,L<eN a<8e,LN <Me,Q <M&Qe ,QT<Me Qa<Me& ,Q<Mej Q8<Me& QMej,T< <M&seQ",
+" <e*,LN -<eLN NB*L,<e aeL-<N N.*L,<e 8<e-LN <e,.NB*L ae-L8<N ,Q<Me* -Q<Me Q",
+"TM*,<e aMe-Q< QMej,<* Q8<-Me T*,M<jQe -Q<seM ,GW<L G<&WL G<H,WL aeLW<& G<L,",
+"W. <&LW8e WL,.G<H WLa<,G8 ,GQ<M <M&GQ Z<G,M Z<&GM G<M,Wj GQ8<M& ,GMZ<j s<MZ",
+"e& fW<,L f-W<L ,HWf<L gf<-WL ,W<fL. -W<f8L ,<fLHW. gWf8-<L fQ<,M f-Q<M Zf<,",
+"M Z-f<M ,WMfj< f8<-WM fM<Z,j Z-<sfM <mL,e <m&eL ,4LemB aeL<m& ,45emL <mL5e&",
+" 5L<m,eB a<8me&L <Mm,e <Mme& ,4TMem <M&aem p<M,e p<&Me ,4TpeM s<Mpe& =em,L ",
+"-=emL emL=B, -me=aL emL=5, -=m>eL 5m=L,eB >m=a-eL =QM,e =Q-Me Mem=T, =Te-Mm",
+" p=M,e -p=Me peT=M, s=M-pe ,4GWL <m&GL emL,4H aeL,4W <mL,G5 <mL,G8 ,L4GH5W ",
+"4G,8amL <Mm,G <MmG& Z4e,M Z4eM& pG<,M pG<M& Z4MpG, s<MpG& fv=,L -vf=L fv,=H",
+"L -vfg=L v=,f5L -v=f>L =,f5vHL >Lg=-vf =Qf,M -vMf= Z=f,M Z-=fM fp=,M fp-=M ",
+"Z=Mfp, yf-=M U<I U!I< D<Ue aIU< U.I< 8IU< I<.UD U8<De I<M <!IM V<I aIV< I<U",
+"j I<8M I<Vj V<sI I<U* +IU< I<*UD U+<De I<*U. U+<8I U<DI*. +D<U8e <MI* I<+M ",
+"I<V* +IV< I<M*j I<M+j V<I*j sI<V+ UG< U!G< J<U UaJ< U.G< G8U< U<J. U8J< GMU",
+"< I<MG! J<V JaV< G<Uj I<MG8 V<Jj VJs< fU< U+f< fUJ< J<gU U<f. U8f< JfU<. Jf",
+"8U< U<fM fU+<M Vf< g<Vf U<fj fU8<M V<fj s<Vf 4Ue 4!Ue Ue4D Ua4e U54e U84e 4",
+"Ue5D 4U8De Ue4M I<M4! V4e 4aVe Ue4j I<M48 4eV5 V4se =UI U+=I Ue=D Ua=I U5=I",
+" =U>e =U5De >eU=D =IM +I=M V=I V+=I Ue=j =I>M V5=I >eV= UG4e 4UG<! 4UJ< J4U",
+"a< G5U< 4UG8< U5J< J48U< I<M4G I<!4GM V4J< J4Va< I<MG5 4G8I<M V5J< sJ4V< =U",
+"f =+fU J=U =UgJ f5=U =Uf> J5=U =UJ> fU=M =Uf+M J=V gVJ= fU=j f>U=M =jVf Vfs",
+"= UNI< I<NU! I<NUD Ua<IN I<NU. U8<IN D<NUe. aeNU8< QIU< I<MQ! QIV< V<QaI I<",
+"MQj I<MQ8 V<QIj sI<VQ I<*UN U+<IN U<DI*N aeNU+< U<NI*. I<NU8* I<U*DN. UN+<D",
+"8e I<MQ* I<M+Q V<QI* V+<QI UQ<I*j U+QI<j I<jV*Q sIQV+< G<UW UG<W! UWJ< J<UW",
+"a UG<W. UG8W< J<UW. J8<UW GQU< I<MW! VZJ< ZJ<Va I<MWj I<MW8 ZJ<Vj sJ<VZ UWf",
+"< fU+W< JfUW< gJ<UW fUW<. fU8W< fUWJ<. J8WgU< UQf< fUQ+< Z<Vf VfZg< fUQ<j f",
+"UQ8< VfZ<j sfVZ< Um4e I<mU! I<mUD aem4U I<mU5 I<mU8 5D<Uem 4U8aem UQ4e I<Mm",
+"! 4QVe V4eQa 4Upe pU<8I pIV< Vp<sI Ue=m =U+Im =UDIm =UaIm =U5Im >eU=m U5e=D",
+"m >Im=Ua UQ=I =UQ+I Ve=Q V=+QI pU=I p=U>e =IVp V>ep= UW4e 4UWe! U<Jm J<mUa ",
+"4UW5e 4UW8e J5<UW J8<Um I<M4W I<!4WM V4Ze Z4Vae UGp< pUG8< J<Vp Jp<Vs fv=U ",
+"=Ufv+ =UJv J=gvU =Ufv5 f>Uv= J=vU5 J>=vU fU=Q =Uf+Q VfZ= J=VgZ =Ufp fpU>= V",
+"=Jp J=yV hU< U<h& U<hD hUc< U<h. U8h< hUD<. c<Uh8 hM< <Mh& Vh< c<Vh U<hj 8<",
+"hM V<hj s<Vh U<h* h<-U hUD<* c-Uh< hU<*. -U8h< U<Dh*. hc8-U< <Mh* h<-M h<V*",
+" V<h- hM<*j -Ujh< Vh<*j V-hs< UGh< G<U& hUJ< cUJ< hUG<. h8UG< J<Uh. cJ<U8 G",
+"<hM hMG<& J<Vh VJc< hMG<j h8MG< VhJ<j sJ<Vh h<fU f<-U JfUh< iU< fU<h. f-U8<",
+" hJ<fU. U8i< h<fM f-U<M V<hf iV< fUjh< f-U<j Vfh<j s<iV h4U 4Uh& 4UhD hUc4 ",
+"4Uh5 4Uh8 h4U5D c5<hU h4M 4Mh& Vh4 c4Vh 4Uhj 48hM V4h5 s4Vh h=U h-=U hU=D h",
+"c=U h5=U =Uh> h=U5D c=h>U h=M h-=M V=h h=V- h5=M >Mh= =jVh V=hs 4UhG h4UG& ",
+"hUJ4 cJ4hU h4UG5 h48UG J5<hU cJ5U< 4GhM h4MG& J4Vh Vh4cJ h4MG5 h48GM Vh4J5 ",
+"hs4VJ hf=U f-=U hJ=U i=U h=fU5 f>Uh= J=hU5 =Ui> hf=M h=Mf- h=Vf iV= h=Mf5 h",
+">Mf= J=Vh5 s=iV U<hN hU<&N hUD<N c<UhN hU<N. h8U<N U<DhN. h8Uc<N UQh< hQU<&",
+" V<hQ VhcQ< hQU<j hQ8U< VhQ<j hsVQ< hU<*N -U<hN U<Dh*N hc<-UN U<*hN. h8<-UN",
+" UDhN<*. hUc<-8N hQU<* -UQh< VhQ<* V-hQ< UQ<hj* -U<hQ8 hQ<V*j hsQV-< UWh< h",
+"WU<& J<UhW cJ<UW hWU<. hW8U< hWUJ<. cWUJ8< W<hM hWM<& Z<Vh Zc<Vh hWM<j hW8<",
+"M hZV<j hZsV< fUWh< f-UW< hJWfU< UWi< hW<fU. fU<hW8 hUJ<fW. iUW8< fUQh< f-U",
+"Q< VfZh< Z<iV fU<hWj fU<-Wj hZ<Vfj iZVs< 4Uhm h4Um& h4UDm c<mhU h4U5m h48Um",
+" U5<hmD c4Uh8m 4UhQ h4QU& V4hQ Vh4cQ pUh4 hp4U8 h4Vp cp<Vh hm=U h=-Um h=UDm",
+" c=hUm h=U5m h>=Um h5U=Dm h>Uc=m hQ=U h=Q-U =QVh c=VhQ =Uhp -pUh= V=hp cp=V",
+"h 4UhW h4WU& J<mhU cJ<Um h4WU5 h4WU8 J4Uh5W c4Uh5W 4WhM h4WM& Z4Vh hZ4Vc hp",
+"4UG pUG<& Jp<Vh cpJV< =Uhv -vUh= J=hvU =Uiv hv=U5 hv>=U hvUJ=5 iv>=U =Mhv h",
+"vM-= V=hZ Z=iV fpUh= fp-=U Jp=Vh yVi= 6ek 6!ke 6Bke ak6e <k1e 8k6e <kB1e ak",
+"e68 6Me 6!Me Tk6e aM6e l<e 68le 6Tle s6le ke6* +k6e <kBe* ake6+ ke*1< 6+e8k",
+" 6e1k*B 68eak* Me6* +M6e 6Tek* aMe6+ 6el* 6+le l<Te* ls<+e G<k G!<k H<Gk a<",
+"Gk Gk1< 8<Gk 6He1k 6H8ke G<6M 6GM<! HM6e aMe6G lG< G8l< 6Hle sGl< f6k 6+fk ",
+"6Hfk f6gk 1<fk 68fk f61Hk f68gk f6M 6+fM 6HfM f6gM lf6 f6l+ f6lH l<sf 4ke 4",
+"!ke 4Bke ak4e 7ek 8k7e ke7B ak7e 6M4e 4keM! Tk4e ake4T le7 l87e 7Tle le7s =",
+"ke +k=e ke=B ak=e 7e=k =k>e 7=ekB 7ae>k 6M=e =k+Me Tk=e =Tk+e l=e >el= le=T",
+" les= G<4k 4Gk<! Hk4e ake4G G<7k 7G8<k Hk7e 7Ga<k 4Gk<M <k!4GM 4GT<k 4GTake",
+" 7Gl< lG78< 7Hle 7sGl< =kf =+fk fk=H gf=k 7fk >k7f fk7H gk7f f6=M =kf+M fT=",
+"k g=kfT lf7 l>7f =Hlf g7lf 6Nke <kNe! <kNeB ake6N <kN1e 68ekN 1<NkeB akN68e",
+" Qk6e 6QeM! 6QeTk ake6Q 6Qle l<Q8e l<QTe ls<Qe <kNe* 6+ekN 6eNk*B akN6+e 6e",
+"1k*N <kN1+e <k1e*BN a<+k1eN 6Qek* 6+Qke Qke6T* 6+Qake l<Qe* l+<Qe 6Qel*T s<",
+"Ql+e W<Gk 6Wek! 6HeWk ake6W 6We1k 6W8ke H<k1We 6W8ake WM6e 6WMe! 6MZe Z6eak",
+" 6Wle lG<W8 Z6le lZ<sG 6Wfk f6+Wk f6HWk gf6Wk f61Wk f68Wk 1H<fkW f1Wg<k 6Wf",
+"M f6Q+k f6Zk Zf6gk f6lW lf6+W l<Zf glfZ6 ke6m <kme! <kmeB ake6m ke7m 7e8km ",
+"7ekmB 7aekm Qk4e Mem6! <kmTe ake4Q 7ple 7pel8 7pelT 7selp ke=m =k+em =kemB ",
+"=akem 7=ekm >k=em =km7eB 7am>ke Qk=e =Qk+e =QkTe =Qake lep= l>ep= l=pTe l=s",
+"pe Wk4e <kmG! <kmHe ake4W Wk7e 7We8k 7HeWk 7Wake <kmGQ <k!4GQ 4kZe Z4kae 7W",
+"le 7Wel8 le7Z 7Zels fv=k =kfv+ =Hkfv g=kfv fk7v f>k7v 7fvHk g7fvk fQ=k =Qf+",
+"k =kZf Z=kgf 7flv lfp7> 7Zlf lfy7 ?ke ke?& ke?B ak?e 1e?k ?k:e ?B1ke ?:ake ",
+"?Me Me?& Tk?e aM?e l?e ?:le ?Tle les? ke?* ?e-k ?Bke* ?-ake ?1ke* ?:-ke ke*",
+"?B1 :-k?ae Me?* ?e-M ?Tke* ?-Tke ?el* ?-le l?Te* l-?se ?Gk Gk?& Gk?H Ga?k 1",
+"G?k ?k:G ?G1Hk ?:GHk ?GM GM?& GT?M Ga?M l?G ?:lG ?GlH lGs? ?fk fk?- fk?H gk",
+"?f ?1fk fk?: ?f1Hk g?:fk ?fM f-?M fT?M gM?f lf? ?fl- lH?f lfg? 4k?e ke4& ?B",
+"4ke ?a4ke ?k7e 7k:e 7?keB ?a7ke 4M?e ?M4e& ?T4ke ?aM4e 7?le 7:le ?T7le 7sel",
+"? ?k=e =e-k ?=ekB =a?ke ?=7ke Ake 7ek?=B akAe =e?M ?-M=e =T?ke ?aM=e ?=le A",
+"le l=?Te lsAe 4G?k ?G4k& ?G4Hk ?Ga4k ?k7G ?:G7k ?G7Hk ?G7ak 4G?M ?GM4& ?GT4",
+"k ?Ga4M 7l?G l?G7: l?G7H s?G7l =k?f f-=k ?f=Hk g=k?f fk7? Afk 7f?Hk gfAk =M",
+"?f ?fM-= ?fT=k g?Mf= ?fl= Alf lf?=H glAf ke?N ke&?N ?BkeN ?akeN ?1keN ?:ekN",
+" keN?B1 :ek?aN Qk?e ?Qke& ?QTke ?Qake ?Qle ?:Qle l?QTe s?lQe ?ke*N ?-keN ke",
+"*?BN -ke?aN ke*?1N :ek?-N ke?B1*N ak:e?-N ?Qke* ?-Qke Qke?T* ?Qe-Tk l?Qe* l",
+"-?Qe leQ?T* s?Ql-e Gk?W ?GWk& ?GHWk ?GaWk ?G1Wk ?:GWk 1He?Wk ?Hk:We GQ?M ?G",
+"Qk& Zk?G ?ZGak ?GlW l?G:W lG?Z s?ZlG fk?W ?-Wfk ?fHWk g?fWk ?f1Wk :f?Wk f1H",
+"?Wk :fWg?k fQ?M ?fQ-k ?MZf g?Zfk lW?f lf?:W ?Zlf gl?Zf ke?m ?mke& ?mkeB ?am",
+"ke ?m7ke ?:mke 7ek?mB ?ak:em Me?m ?Mme& ?Tmke ?aMem le?p :pel? ?plTe s?ple ",
+"?=ekm ?-mke =ke?mB ?ae-km 7=e?mk keAm =B?m7ek Akmae ?Mm=e ?-Mem ?Qe=Tk ?Qe=",
+"ak l=?pe leAp ?pTl=e Apels Gk?m ?Gmk& ?GmHk ?Gakm ?G7Wk ?:Gkm ?Hk7We ?Gk7Wa",
+" GM?m ?GMm& ?Z4Gk ?GaMm lG?p ?pGl: ?Zl7G s?plG fk?v -vk?f ?vfHk g?vfk ?v7fk",
+" fvAk 7fH?vk Avkgf fv?M ?vMf- ?Zf=k g?vfM ?plf lfAp lv?Zf ylAf 6Ue 6!Ue Ue6",
+"D Ua6e 1U6e U86e 6Ue1D 6U8De Ue6M I<M6! V6e 6aVe lI< 8Il< V6le sIl< Ue6* U+",
+"6e Ik*6D ak*6I Ik*1< Ik*68 1Ue6D* 6D8Ik* IM6* I<M6+ 6IV* 6+Ve 6Il* +Il< lI<",
+"V* sI<l+ UG6e 6UG<! J<k a<Jk UG1< 6UG8< 1UJ< 8<Jk I<M6G I<!6GM V6J< J6Va< U",
+"Gl< lG<U8 lJ< l<sJ f6U 6Uf+ f6Jk J<gk 6Uf1 6Uf8 Jf61U Jf6U8 6UfM f6U+M Vf6 ",
+"g6Vf f6lI lf6U+ l<Vf l<gJ 6U4e 4Ue6! Dk4e ake4U 7Ue U87e Ue7D Ua7e I<M4k Ik",
+"!4Me 4kVe V4e6a 7Ule 7Uel8 7Ve se7V =Ik +I=k Dk=I aI=k 7U=I =I>k 7Ue=D 7>UD",
+"e 6I=M =Ik+M V6=I V=6+I l=I =Il> =I7V >e7V 4UG6e I<!4Gk 4kJ< J4ka< UG7e 7UG",
+"8< J<7U 7JU8< 4GkI<M 6!UG4Me J4V6e J4aV6e 7UGl< 7U8lG< l<7J lJ<7s f6=U =Uf6",
+"+ J=k =kgJ 7fU 7Uf> =U7J >kJ= =Uf6M =U+f6M =kVf J=Vg6 =Ulf lf7>U l=J 7Vsf 6",
+"NUe 6Ue!N 6UeDN 6UaeN 6Ue1N 6U8eN IkN1D< akN1I< UQ6e 6UQe! 6QVe V6eQa QIl< ",
+"lI<Q8 lI<VQ sI<lQ Ik*6N 6U+eN I<NDk* akN6I* I<N1U* I<N1U+ IkD*1<N Ua1*I<N I",
+"k*6Q 6U+Qe V6eQ* V6+Qe lI<Q* l+IQ< lIQV6* sIQl+< UW6e 6UWe! W<Jk J<kWa 6UW1",
+"e 6UW8e J1<UW J8<Wk I<M6W I<!6WM J<Zk ZJ<ak WIl< lWI8< ZJl< lJ<sZ 6UfW f6U+",
+"W Jf6UW gJ<Wk f6U1W f6UW8 J6Wf1U J6WfU8 6UfQ f6U+Q Z6Vf Vf6gZ lf6UW l+WI< V",
+"f6lZ Vf6sZ Ue6m I<mk! I<mDk akmI< Ue7m 7Ue8m 7UeDm 7Uaem I<M6m I<!4Qk 6eVm ",
+"V6eam pU7e 7pU8e 7eVp 7Vesp Ik=m =Ik+m =DkIm =aIkm 7Ue=m 7>Uem 7Dm=Ik >Dm7U",
+"e QI=k =QI+k V=6QI =QaIk lIp= l=Ip> V=plI V>e7p I<mGk I<!4Wk <kJm J<kam UW7",
+"e 7UW8e 7JUW< 7UWae 4WkI<M UG4Q<k! ZJ4<k Z4aJ<k 7pUG< 7U8lWe l<Jp Jpls< v6f",
+"U =Iv+k =kJv J=kgv fv7U 7fUv> J=k7v J>=vk =Uf6Q =U+f6Q ZJ=k J=kgZ =Ilv fpU7",
+"> Jpl= l=yJ h?t h&?t ?Dht ht?c ?th1 ?th: ?t1hD ?t:hc h?M h&?M V?h Vh?c lh? ",
+"l?h: lhV? u?h t*h? h?t- ?tDh* ?cht- ?t1h* ?t:h- h?1t*D ?cth:- h*?M ?-hM V*h",
+"? h?V- h?l* h?l- V?lh* h?u- ?tG ?&tG ?Jt tJ?c ?1tG t:?G J1?t ?t:J ?GhM ?tGM",
+"& ?JV cJV? h?lG lh?:G ?Jl u?J tf? t-?f tf?J i?t f1?t ?t:f ?Jtf1 ?ti: hM?f ?",
+"fMt- V?f i?V ?flh lf?h: ?Jlf ui? ht4 h&t4 hDt4 tch4 7ht 7th: 7Dht ht7c ?Mh4",
+" h?M4& h4V? V?hc4 7hl l:7h 7Vh u7h t=h t-h= ht=D htc= 7ht= Aht t=7hD htAc h",
+"?=M h=Mt- h=V? c=Vh? l=h Alh V=7h Auh t4?G ?tG4& h4tJ tJ4?c ?G7t 7tGh: tJ7h",
+" ?J7t: ?tG4M ?G&h4M J4V? ?JVc4 lG7h 7hl:G 7V?J ?Ju7 tf= f-t= t=J it= tf7 At",
+"f 7Jtf Ait =Mtf tf=-M V?J= t=iV tfl= lfAh ?Jl= Aiu hN?t ?t&hN ?tDhN ?chtN ?",
+"t1hN ?t:hN ht1?DN ?cth:N ?thQ ?tQh& hQV? V?hcQ hQl? lh?:Q V?lhQ h?uQ ?t*hN ",
+"t-?hN h?Dt*N t-h?cN h?1t*N t-?h:N hDt*?1N hN?ct-: ?tQh* t-Qh? V?hQ* V?-hQ l",
+"h?Q* l-h?Q lhQV?* uh-?Q ?thW ?tGW& ?WtJ ?cWtJ ?tG1W h:W?t ?Jt1W ?J:tW ?WhM ",
+"?tGQ& tZ?J hZ?tc h?lW lhW?: lJ?Z hZu? ?Wtf t-W?f ?JtfW ?tiW tf?1W tf:?W tf1",
+"?JW i?t:W ?Qtf tfQ?- tf?Z ?ZiV lhW?f lhW?- V?flZ i?uZ ?thm ?tmh& ?tmhD ?cmh",
+"t hm7t h:m7t 7htDm 7hctm ?Mhm ?Mmh& hmV? V?mhc 7htp hpl?: 7Vhp hpu? hmt= t-",
+"mh= t=hDm t=chm t=7hm htAm 7hDt=m Atmhc ht=Q t=Qh- V?mh= c=Qht hpl= hpAl l=",
+"hVp upAh t4hW ?tGm& ?mtJ ?Jmtc hW7t 7hWt: ?J7tW ?J:tm ?tG4Q ?G&t4Q h4tZ V?m",
+"cJ lW7h lhW7: tp?J hZu7 tf?v hv?t- tv?J ?vit 7htv hvAt hv7tJ itAv =Qtf hv?-",
+"M t=hZ ?viV hvl= lvAh hZl= yAui O !O OB aO O. 8O .BO 8aO OK !KO TO TaO jO j",
+"O8 jOT sO (O +O (BO +aO (O. +8O (O.B 8a+O (OK +OK T(O +TO jO( +jO T(jO s+O ",
+"EO !EO HO HaO EO. 8EO HO. H8O EKO !OEK HTO TaHO jOE 8EjO HjO sHO dO +dO HdO",
+" gO dO. 8dO dOH. g8O dKO dK+O TdO gTO djO jO8d jOTd gsO O2 !O2 2BO aO2 5O 5",
+"8O 5BO 5aO 2KO !O2K TO2 T2aO jO5 58jO 5TO s5O ;O +;O ;OB a;O 5;O >O ;O5B >O",
+"a ;OK ;O+K T;O +OT; ;jO >jO jOT; s>O EO2 EO!2 HO2 aOH2 5EO 8E5O H5O HO5a EO",
+"2K !EO2K TOH2 HTaO2 5EjO jO58E jOH5 H5sO d;O d;+O H;O g;O 5dO >Od HO5d g>O ",
+";OdK +d;OK HOT; T;gO jO5d dj>O jOH; >Ogs P P! PB aP P. 8P P.B 8Pa QP Q!P TP",
+" QaP Pj Q8P TPj sP P( +P P(B +Pa P(. +P8 .BP( +8aP QP( +QP TP( +TP Pj( +Pj ",
+"T(Pj sP+ WP W!P HP HPa WP. W8P HP. H8P WQP WPQ! ZP ZaP WjP 8PWj ZPj sZP dP ",
+"+WP HPd gP dP. 8dP H.dP gP8 QdP Qd+P ZdP gZP dPj Wj+P dPZj gsP mP mP! mPB a",
+"mP 5P 5P8 5PB 5aP QmP mPQ! TmP amTP pP p8P pTP spP ;P +mP ;PB a;P 5P; >P 5B",
+";P >Pa Q;P Q;+P T;P Tm+P p;P >Pp T;pP >Ps WmP mPW! HmP amHP 5WP W85P H5P 5a",
+"HP QmWP Q!WmP ZmP amZP pWP W8pP ZpP ZpsP vP v+P vHP gvP v5P >Pv H5vP >Pg vQ",
+"P +QvP ZvP ZvgP pvP pv>P ZPpv yP #O &O #BO a&O #O. 8&O #O.B a&8O #OK &OK T#",
+"O T&O jO# &jO T#jO s&O #(O +&O #(OB a&+O (O#. 8&+O (BO#. +8a&O (O#K &O+K #(",
+"TO +OT& #(jO +&jO jOT#( +&sO #EO &EO H#O H&O EO#. &E8O #OH. 8&HO #OEK EK&O ",
+"T#HO HOT& #EjO &EjO H#jO H&sO d#O d&O d#HO g&O #Od. 8Od& Hd#O. 8&gO #OdK &O",
+"dK d#TO T&gO d#jO jOd& dj#HO gOs& #O2 &O2 #O2B &2aO 5#O 5&O #B5O a&5O #O2K ",
+"2K&O #OT2 &OT2 5#jO jO5& T#5O 5&sO ;#O ;&O #B;O aO;& ;#5O >&O 5;#OB a&>O #O",
+";K &O;K ;#TO TO;& ;#jO &j>O ;j#TO s&>O EO#2 EO&2 #OH2 &OH2 #E5O &E5O 5#HO H",
+"O5& #O2EK &EO2K HT#O2 H&TO2 jO5#E &jE5O H5T#O sH5&O ;#dO dO;& ;#HO ;&gO d#5",
+"O d&>O H5d#O g&>O dK;#O d&;OK H;T#O gT;&O dj#5O >&djO H;j#O gs>&O P# P& P#B",
+" aP& P#. 8P& .BP# 8aP& QP# Q&P TP# TP& Pj# P&j T#Pj sP& P#( +P& #BP( +aP& #",
+"(P. +8P& P#(.B aP&+8 P#Q( Q&+P P#T( T&+P j#P( P&+j Pj#T( +Ps& WP# W&P HP# H",
+"P& P#W. 8PW& P#H. 8PH& QPW# WQP& ZP# Z&P W#Pj P&Wj PjZ# Z&sP dP# dP& H#dP g",
+"P& P#d. d&8P dP#H. 8Pg& Q#dP dPQ& dPZ# Z&gP d#Pj P&dj dPjZ# g&sP mP# m&P P#",
+"mB m&aP 5P# 5P& P#5B aP5& mPQ# QmP& mPT# m&TP pP# p&P TPp# p&sP ;P# ;P& PB;",
+"# ;&aP 5#;P >P& ;P#5B aP>& Q#;P ;PQ& T#;P ;PT& ;Pp# p&>P pT;P# >&sP mPW# Wm",
+"P& mPH# m&HP WP5# W&5P H#5P 5PH& WQmP# m&PWQ mPZ# m&ZP WPp# W&pP pPZ# ZPp& ",
+"vP# v&P HPv# v&gP 5Pv# v&>P vH5P# >&gP QPv# Q&vP vPZ# ZPv& vPp# pPv& ZpvP# ",
+"y&P CO !CO DO DaO CO. 8CO DO. D8O CKO !OCK DTO TaDO jOC 8CjO DjO sDO C(O +C",
+"O D(O +DO (OC. 8C+O (OD. +OD8 (OCK CK+O T(DO DT+O C(jO +CjO D(jO +DsO CEO C",
+"E!O HDO DaHO EOC. CE8O DOH. HOD8 COEK !EOCK DTHO HDTaO CEjO jO8CE HDjO HDsO",
+" dCO dC+O DdO gDO COd. dC8O dOD. D8gO CKdO +dCOK DOTd DTgO dCjO djC+O jODd ",
+"gOsD CO2 CO!2 DO2 D2aO 5CO 8C5O 5DO 5OD8 CO2K !C2OK T2DO DTaO2 5CjO jO58C j",
+"O5D 5DsO ;CO ;C+O D;O +OD; ;C5O >CO 5OD; >DO CK;O +;COK DOT; a;ODT ;CjO jO>",
+"C jOD; sD>O EOC2 !EOC2 DOH2 HDaO2 CE5O 58CEO HO5D H5D8O EKCO2 EK2!CO HDTO2 ",
+"DTaHO2 jO5CE 58CjOE H5DjO sH5DO ;CdO +d;CO HOD; D;gO dC5O dC>O 5ODd gD>O dK",
+";CO dK;+CO H;DTO gDT;O djC5O >jdCO H;jDO >DOgs PC PC! DP DPa PC. 8PC DP. D8",
+"P QPC PCQ! QDP DPQa PjC QC8P DPj sPD PC( +PC DP( +DP C(P. +C8P P(D. D8+P PC",
+"Q( QP+C Q(DP QD+P jCP( +CPj D(Pj +DsP WPC PCW! HPD DPWa PCW. WC8P H.DP D8HP",
+" QPWC Q!WPC ZDP DPZa WCPj PjCW8 DPZj ZDsP dPC +CdP DdP gPD PCd. 8CdP D.dP D",
+"8gP QCdP dPC+Q DdZP ZDgP dCPj dPj+C dPDj gDsP mPC P!mC DmP amDP 5PC 5C8P 5D",
+"P D85P mPQC Q!mPC TmDP amPQD pPC 8PpC pDP pDsP ;PC +C;P D;P Dm+P 5C;P >PC D",
+";5P >PD QC;P ;PC+Q DPQ; a;PQD ;PpC pP>C D;pP pD>P mPWC W!mPC DmHP amPWD WP5",
+"C 5W8PC 5DHP H5PD8 WQmPC WmPQ!C DmZP ZDamP WPpC pW8PC ZPpD sPDZp vPC +PvC v",
+"DP vDgP 5PvC vP>C 5DvP vD>P QPvC v+QPC ZPvD ZvDgP vPpC >PpvC pPvD yDP bO b&",
+"O bDO cO bO. b8O DOb. c8O bKO &ObK bTO cTO bjO jOb8 jObT scO b(O b+O D(bO c",
+"+O (Ob. +8bO bD(O. +8cO (ObK +ObK T(bO +TcO b(jO jOb+ bTj(O c+sO bEO &EbO b",
+"HO cHO EOb. 8EbO HOb. H8cO EKbO bK&EO HTbO HTcO bEjO &jEbO jObH cHsO bdO bO",
+"d& bODd gcO dOb. bO8d bHdO. c8gO dKbO d&ObK bOTd cTgO jObd d&jbO bHjdO gOsc",
+" bO2 &Ob2 DOb2 c2O b5O bO5& bO5D c5O 2KbO bK&O2 TOb2 TOc2 jOb5 &jOb5 bO5T s",
+"Oc5 b;O bO;& bOD; c;O 5;bO >bO b5D;O c>O ;ObK ;&ObK bOT; T;cO jOb; bj>O b5T",
+";O >Osc EOb2 b&EO2 HOb2 HOc2 5EbO b58EO bOH5 H5cO bKEO2 &EObK2 bHTO2 c2HTO ",
+"b5jEO b5E&jO bH5jO c5HsO d;bO d&;bO bOH; gOc; bO5d bd>O bH5dO >Ogc bd;OK bd",
+"O;&K bH;TO c;TgO b5djO >bdjO bH;jO c>gsO bP bP& bPD cP bP. b8P b.DP cP8 bQP",
+" Q&bP bTP cQP bPj Q8bP DPbj scP bP( b+P b(DP cP+ P(b. +Pb8 bPD(. +Pc8 QPb( ",
+"+QbP b(TP +QcP b(Pj +Pbj bTPj( s+cP bWP W&bP bHP cWP WPb. W8bP b.HP H8cP WQ",
+"bP bWQP& ZbP ZcP WjbP P&jbW bPZj sPZc bdP +WbP HPbd gcP b.dP 8dbP bHPd. g8c",
+"P QdbP dP&bQ bdZP gPZc dPbj dP&bj ZbdPj scgP bmP m&bP DmbP cmP b5P 5Pb8 5Db",
+"P c5P QmbP m&PbQ TmbP TmcP pbP b8pP bTpP cpP b;P +mbP D;bP c;P 5Pb; >Pb b5P",
+"D; c>P Q;bP ;P&bQ T;bP Q;cP b;pP pb>P pbD;P >Pcp WmbP m&PbW HmbP HmcP 5WbP ",
+"b5W8P H5bP H5cP bWQmP bWQm&P bmZP ZmcP bWpP pbW8P ZPpb cPZp vbP b+vP bHvP c",
+"vP b5vP vb>P vbH5P >Pcv bQvP vb+QP ZPvb cPZv pPvb >Pbpv ZpbvP ycP 0O !0O 0B",
+"O a0O 1O 18O 1OB 1aO 0OK 0O!K T0O a0TO jO1 18jO 1TO s1O 0(O +0O 0(OB a0+O 1",
+"(O 1+O (B1O +a1O (O0K 0O+K 0(TO T0+O 1(jO jO1+ T(1O 1+sO E0O E0!O H0O a0HO ",
+"1EO 8E1O 1HO 1OH8 0OEK !EO0K T0HO HTa0O 1EjO jO18E jO1H 1HsO d0O d0+O d0HO ",
+"g0O 1dO 1O8d Hd1O g1O 0OdK +d0OK d0TO T0gO jO1d djO1+ 1OTd gOs1 0O2 0O!2 0O",
+"2B 0Oa2 15O 581O 5B1O 1O5a 0O2K 2K0!O 0OT2 Ta0O2 15jO jO158 1O5T 15sO ;0O ;",
+"0+O 0B;O ;0aO 1;O >O1 ;O1B 1a>O 0O;K +;0OK ;0TO a;0TO jO1; jO>1 1OT; s1>O 0",
+"OE2 !EO02 0OH2 Ha0O2 5E1O 158EO 1OH5 1H58O EK0O2 2K0!EO HT0O2 Ta0HO2 jO15E ",
+"158jOE 1H5jO s1H5O ;0dO +d;0O ;0HO ;0gO 1O5d 1d>O 1OH; >Og1 dK;0O dK;+0O H;",
+"T0O gT;0O djO1; >j1dO 1H;jO gs>1O P0 P0! P0B aP0 1P 1P8 1PB 1aP QP0 P0Q! TP",
+"0 Q0aP 1QP Q81P 1TP sP1 P0( +P0 0BP( +0aP 1P( 1+P P(1B +P1a P0Q( QP+0 P0T( ",
+"+0TP 1(Pj +Q1P 1(TP 1+sP WP0 P0W! HP0 H0aP 1WP W81P 1HP H81P QPW0 Q!WP0 ZP0",
+" aPZ0 Wj1P 1WQ8P Z1P Z1sP dP0 +0dP H0dP gP0 1dP +W1P HP1d g1P Q0dP dP0+Q dP",
+"Z0 ZPg0 Qd1P dPj1+ 1dZP sPg1 mP0 P!m0 P0mB mPa0 1mP 8m1P 1B5P 5a1P mPQ0 Q!m",
+"P0 mPT0 amPQ0 p1P 1Pp8 1TpP p1sP ;P0 +0;P PB;0 a0;P 1;P >P1 1B;P 1a>P Q0;P ",
+";P0+Q T0;P a;PQ0 1;pP p1>P T;1P s1>P mPW0 W!mP0 mPH0 amPH0 5W1P 1W58P H51P ",
+"1Hm8P WQmP0 WmPQ!0 mPZ0 ZamP0 1WpP p1W8P p1ZP sP1Zp vP0 +Pv0 HPv0 vPg0 v1P ",
+"v1>P 1HvP g1>P QPv0 v+QP0 vPZ0 ZvPg0 pPv1 >Ppv1 ZPv1 y1P 9O 9&O 9OB 9aO 91O",
+" :O 1B9O :aO 9OK &O9K 9TO 9OT& 9jO :jO jO9T s:O 9(O 9+O (B9O +a9O 1(9O :+O ",
+"91(OB +a:O (O9K +O9K T(9O 9O+T 9(jO +j:O 9T1(O :+sO 9EO &E9O 9HO 9OH& 1E9O ",
+":EO 9O1H :HO EK9O 9&EOK HT9O 9HTaO 9EjO jO:E jO9H sO:H 9dO 9Od& Hd9O g9O 9O",
+"1d :dO 9H1dO g:O dK9O d&O9K 9OTd 9TgO jO9d dj:O 9HjdO gOs: 9O2 &O92 2B9O aO",
+"92 95O :5O 5B9O 5a:O 2K9O 9&O2K TO92 9TaO2 jO95 jO:5 9O5T :5sO 9;O 9O;& ;O9",
+"B 9Oa; 9O1; :>O 95;OB :a>O ;O9K ;&O9K 9OT; 9+T;O jO9; :j>O 95T;O >Os: EO92 ",
+"9&EO2 HO92 9HaO2 5E9O 5E:O 9OH5 H5:O 9EO2K &EO92K 9HTO2 H&O9T2 95jEO :5jEO ",
+"9H5jO :H5sO d;9O d&;9O 9OH; 9;gO 9O5d >O:d 9H5dO >Og: 9d;OK 9dO;&K 9H;TO g9",
+"T;O 95djO :>djO 9H;jO g:s>O 9P 9P& 9PB 9aP 9P1 :P 1B9P :Pa 9QP Q&9P 9TP Qa9",
+"P 9Pj :QP 1T9P s:P 9P( 9+P P(9B +P9a 9(1P :P+ 9P1(B +P:a QP9( +Q9P 9(TP +T9",
+"P 9(Pj +Q:P 9TP1( s+:P 9WP W&9P 9HP HP9a 1W9P :WP 1H9P :HP WQ9P 9WQP& Z9P 9",
+"aZP Wj9P Wj:P 9PZ1 Z:P 9dP +W9P HP9d g9P 1d9P :dP 9HP1d g:P Qd9P dP&9Q 9dZP",
+" Z9gP dP9j Qd:P Z91dP gPZ: 9mP m&9P mP9B am9P 95P :mP 9B5P 5a:P Qm9P m&P9Q ",
+"Tm9P 9QamP p9P :pP 9TpP sP:p 9;P +m9P 9B;P a;9P 1;9P >P: 95P;B :a>P Q;9P ;P",
+"&9Q T;9P a;P9Q 9;pP >P:p p9T;P s:>P Wm9P m&P9W Hm9P 9HmaP 5W9P 5W:P H59P H5",
+":P 9WQmP 9WQm&P 9mZP Z9amP 9WpP pW:P ZPp9 :PZp v9P 9+vP 9HvP v9gP 95vP :vP ",
+"v91HP >Pg: 9QvP v9+QP ZPv9 Zv9gP pPv9 pv:P Zp9vP y:P C0O C0!O D0O a0DO 1CO ",
+"8C1O 1DO 1OD8 0OCK C0O!K T0DO DTa0O 1CjO jO18C jO1D 1DsO 0(CO C0+O 0(DO D0+",
+"O C(1O +C1O D(1O 1O+D C0O(K +C0OK DT0(O +DT0O jO1C( 1+jCO 1DT(O s1+DO E0CO ",
+"C0O!E D0HO HDa0O CE1O 18CEO HD1O 1HD8O C0OEK EK0!CO HDT0O DTaH0O jO1CE 18Cj",
+"OE 1HDjO s1HDO C0dO +dC0O d0DO D0gO dC1O 1+dCO 1ODd 1DgO dKC0O dKC+0O DdT0O",
+" gDT0O djC1O 1+CdjO 1DdjO gs1DO 0OC2 C02!O 0OD2 Da0O2 5C1O 158CO 1O5D 1D58O",
+" C02OK 2K0!CO DT0O2 Ta0DO2 jO15C 158jOC 1D5jO s15DO C0;O +;C0O ;0DO a;0DO ;",
+"C1O 1C>O 1OD; 1D>O ;C0OK ;C0+OK D;T0O D;0+TO ;jC1O >j1CO 1D;jO >DOs1 C02EO ",
+"!EOC02 HD0O2 Da0HO2 15CEO 58C1EO 1H5DO H5D1aO EK2C0O E02K!CO DT0HO2 DTH0aO2",
+" 15CjOE 5E1O8jC H5D1TO 1H5sDO d;C0O d;C+0O H;D0O gD;0O 1d5CO >C1dO 1H;DO >D",
+"Og1 ;C0dKO C0;O+dK Td0D;O D;Tg0O 1dC;jO djC>O1 djO1D; gs1>DO PC0 !CP0 DP0 D",
+"0aP 1PC 1C8P 1DP D81P PCQ0 Q!PC0 Q0DP aP0QD 1CPj PjC18 QD1P 1DsP C0P( PC+0 ",
+"P0D( +0DP PC1( 1C+P 1(DP +D1P QPC0( +QPC0 QDP0( +QDP0 PjC1( 1+QPC 1QDP( sP1",
+"+D PCW0 W!PC0 H0DP aP0WD WP1C 1W8PC HP1D 1HPD8 WQPC0 WPCQ!0 DPZ0 ZDaP0 PjC1",
+"W 1W8PjC 1DZP sP1ZD PCd0 dPC+0 D0dP DPg0 1CdP 1+WPC Dd1P 1DgP dPCQ0 +QCdP0 ",
+"ZDdP0 gZDP0 dPj1C dPC1+Q Z1DdP gZ1DP PCm0 mPC!0 mPD0 amPD0 1C5P 1m8PC 5D1P ",
+"1Dm8P QmPC0 mPCQ!0 QDmP0 QDmaP0 1PpC p18PC 1DpP sP1pD PC;0 ;PC+0 D0;P a;PD0",
+" 1C;P 1P>C D;1P 1D>P ;PCQ0 +QC;P0 QD;P0 aP0QD; p1;PC >Pp1C pD1;P >Ps1D WmPC",
+"0 mPCW!0 HmDP0 HmDaP0 1W5PC 5W81PC 1HmDP H8m1DP QmPWC0 QCW0mP! ZDmP0 amPZD0",
+" p1WPC 1W8pPC Zp1DP Zp1sPD PCv0 v+PC0 DPv0 gvDP0 1PvC >Pv1C 1DvP >Pg1D vQPC",
+"0 +QPvC0 ZvDP0 vDPgZ0 pv1PC pv1>PC Zv1DP 1DyP b9O 9&bO 9DO c9O b1O :bO bO1D",
+" :cO 9ObK b9&OK bO9T 9TcO jOb1 bj:O jO9D sO:c 9(bO bO9+ D(9O 9+cO 1(bO b+:O",
+" b1D(O c+:O b9(OK b+9OK bT9(O c9+TO b1j(O :b+jO b1T(O :c+sO 9EbO b9&EO bO9H",
+" 9HcO 1EbO bE:O bO1H cH:O b9EOK 9&EbKO bH9TO c9HTO b1jEO :bjEO b1HjO :cHsO ",
+"bO9d d&Ob9 9ODd c9gO bO1d bd:O b1HdO gO:c bd9OK 9+ObdK bTd9O gc9TO b1djO :d",
+"bjO b1TdO g:scO 9Ob2 b9&O2 DO92 9Oc2 bO95 b5:O 9O5D :Oc5 b9O2K 9&ObK2 bT9O2",
+" c29TO b15jO :b5jO b1T5O :c5sO bO9; ;&Ob9 9OD; 9;cO bO1; :b>O b1;DO >O:c b;",
+"9OK 9+Ob;K bT;9O c;9TO b1;jO :>bjO b1T;O c>s:O b9EO2 9&EbO2 bH9O2 c29HO b15",
+"EO :b5EO b1H5O :cH5O 9EObK2 EOb29&K 9HObT2 9HTc2O 95EbjO b5j:EO bHO95T s:Hc",
+"5O bd9;O bd9;&O bH;9O c;9gO b1d5O :>bdO b1H;O g:c>O 9dOb;K d&b;9OK bHO9T; g",
+"9Tc;O djOb1; >bj:dO djO95D c>sg:O bP9 b9P& 9DP cP9 b1P :Pb 1DbP :cP 9QbP bQ",
+"9P& 9TbP 9QcP 9Pbj bQ:P 1TbP :csP b(9P 9+bP 9(DP 9+cP b(1P b+:P b1PD( :+cP ",
+"bQ9P( b+Q9P bTP9( cQ9+P b1QP( :Qb+P b1TP( :cQ+P 9WbP bW9P& 9HbP 9HcP 1WbP b",
+"W:P 1HbP cW:P bW9QP 9WQbP& bPZ9 cPZ9 b1WPj :WbPj b1ZP :PZc 9dbP dP&b9 Dd9P ",
+"cPg9 1dbP bd:P b1HdP :cgP bQd9P 9+QbdP Zb9dP Zcg9P dPjb1 :QdbP Zb1dP g:PZc ",
+"9mbP m&Pb9 Dm9P 9mcP 95bP b5:P 5D9P c5:P bQ9mP bQ9m&P bTm9P cQ9mP b1pP pb:P",
+" 9DpP :Pcp 9;bP ;P&b9 D;9P 9;cP 1;bP >b:P b1;DP :c>P bQ;9P 9+Qb;P bT;9P cQ;",
+"9P pb9;P :p>bP p9D;P cp:>P bW9mP bW9m&P bHm9P cW9mP b1W5P :Wb5P b1H5P :cW5P",
+" 9WQbmP QmP&bW9 Zb9mP Zc9mP pb9WP :pbWP Zpb9P cpZ:P bPv9 vb9+P 9DvP v9cP b1",
+"vP vb:P vb1HP :Pcv vb9QP b+Qv9P Zvb9P cvZ9P pvb9P :vbpP Zvb1P :cyP R R! RB ",
+"Ra R. R8 R.B R8a RM RM! RT RTa Rj R8M RTj sR R( R+ R(B R+a R(. R+8 .BR( +8R",
+"a RM( R+M RT( R+T Rj( R+j TjR( sR+ RE RE! RH RHa RE. R8E RH. RH8 RME MER! R",
+"HT HMRa RjE RE8M RHj sRH Rd R+d RHd gR Rd. R8d HdR. gR8 RdM +MRd RTd gRT Rd",
+"j +jRd HjRd gsR R2 R2! R2B Ra2 R5 R58 R5B R5a RM2 M2R! RT2 R2aM R5M 5MR8 R5",
+"T sR5 R; R+; R;B Ra; R5; >R 5;RB >Ra R;M +MR; RT; +TR; R;j >MR 5TR; s>R RE2",
+" !ER2 RH2 HaR2 R5E 58RE RH5 H5R8 MER2 RME!2 R2HM aM2RH RE5M R58ME H5RT RHs5",
+" Rd; +dR; RH; gR; R5d >Rd H5Rd g>R dMR; dM;R+ HMR; RTg; 5dRj Rd>M H;Rj gR>M",
+" RP RP! RPB RaP RP. R8P P.RB 8PRa S S! ST Sa Sj S8 STj Ss RP( R+P P(RB +PRa",
+" P(R. +PR8 RP(.B R+8aP S( S+ ST( S+T Sj( S+8 TjS( Ss+ RW RW! RHW RWa RW. RW",
+"8 R.HP H8RW SW S!W SZ SZa SWj S8W SZj SsZ RWd R+W HPRd gRW R.dP +WR8 dP.RH ",
+"RWg8 Sd S+W SZd gS Sdj S8d ZdSj gSs Rm Rm! RmB Ram R5m R8m RB5P 5aRm Sm S!m",
+" STm Sam Sp Sp8 SpT Ssp Rm; R+m RB;P +mRa 5PR; >PR ;PBR5 Ra>P S; S+m S;T Sa",
+"; Sp; S> pTS; S>s RWm W!Rm RHm HmRa R5W 5WR8 H5RW H8Rm SWm W!Sm SZm ZaSm Sp",
+"W pWS8 SZp SZsp vR vR+ vRH gvR vR5 v>R RHv5 gR>P Sv Sv+ SvZ gSv Svp S>v ZpS",
+"v yS R# R& R#B Ra& R#. R8& .BR# 8aR& RM# R&M RT# RT& Rj# R&j TjR# sR& R#( R",
+"+& #BR( +aR& #(R. +8R& R#(.B R+8a& M#R( +MR& T#R( +TR& j#R( +jR& RTj#( R+s&",
+" R#E R&E RH# RH& #ER. 8&RE H#R. H8R& M#RE REM& R#HM HMR& j#RE RE&j R#Hj RHs",
+"& Rd# Rd& HdR# gR& d#R. 8dR& RHd#. R8g& R#dM dMR& R#Td RTg& R#dj d&Rj RHjd#",
+" g&sR R#2 R&2 2BR# a&R2 R5# R5& 5BR# 5aR& M#R2 R2M& T#R2 R2T& R#5M 5MR& R#5",
+"T R5s& R;# R;& ;#RB a;R& 5;R# >R& R5;#B Ra>& R#M; M;R& R#T; T;R& R#;j R&>M ",
+"R5T;# >&sR #ER2 &ER2 H#R2 R2H& 5#RE RE5& R#H5 H5R& RM#E2 M&ER2 RHT#2 RH&T2 ",
+"R5M#E R5&ME RH5T# sRH5& d;R# d&R; R#H; R;g& R#5d Rd>& RH5d# >&gR dM;R# dM&R",
+"; RH;T# gRT;& R5dM# >MRd& RH;j# >MgR& RP# R&P P#RB aPR& P#R. 8PR& RP#.B aP&",
+"R8 S# S& ST# Sa& Sj# S8& TjS# Ss& P#R( +PR& RP#(B aP&R+ RP#(. R+8P& P#(R.B ",
+"R+8aP& S#( S+& T#S( +TS& j#S( +jS& STj#( s+S& RW# RW& R#HP HPR& W#R. W8R& R",
+"HW#. RH8W& SW# S&W SZ# SZ& WjS# W8S& ZjS# S&sZ R#dP +WR& dP#RH RWg& dP#R. d",
+"P&R8 RH#dP. gRW8& Sd# Sd& ZdS# gS& djS# 8dS& SZdj# S&gs Rm# Rm& m#RB amR& R",
+"#5P 5PR& R5m#B R5am& Sm# S&m TmS# TmS& Sp# Sp& pTS# S&sp R#;P +mR& ;P#RB a;",
+"PR& ;P#R5 Rm>& R5#;PB >PRa& S;# S;& T;S# T;S& p;S# S>& SpT;# S&s> WmR# W&Rm",
+" R#Hm HmR& R#5W 5WR& RH5W# RH5W& WmS# W&Sm ZmS# SmZ& pWS# SWp& S#Zp ZpS& vR",
+"# vR& RHv# v&gR R5v# >Rv& vRH5# >PgR& Sv# Sv& S#Zv S&gv S#pv pvS& SZpv# yS&",
+" RU RU! RD RDa RU. R8U RD. RD8 RUM U!RM VR VRa RjU U8Rj VRj sRV RU( R+U RD(",
+" R+D U(R. U+R8 D(R. +DR8 UMR( RU+M VR( V+R R(Uj U+Rj RjV( V+sR RUE U!RE RHU",
+" UHRa UER. REU8 R.UH UHR8 UMRE RUM!E VRH RHVa REUj R8UME RHVj VRsH RdU U+Rd",
+" RDd gRU R.Ud U8Rd R.Dd RDg8 RUdM R+UdM VdR gVR UdRj R+jUd RdVj sRgV RU2 U!",
+"R2 RD2 R2Ua R5U U5R8 R5D U5Ra UMR2 RUM!2 V2R RaV2 U5Rj R5U8M V5R V5sR R;U U",
+"+R; RD; UaR; U5R; >RU 5DR; >RD RUM; R+UM; V;R R+V; U;Rj Rj>U R5V; V>R UER2 ",
+"RUE!2 R2UH RHUa2 REU5 R5U8E UHR5 RH5U8 RUME2 U!MRE2 RHV2 V2RHa R5UME U58RjE",
+" RHV5 VsHR5 UdR; R+Ud; UHR; RDg; U5Rd Rd>U 5DRd >RgU dM;RU R+UdM; RHV; V;gR",
+" R5dUj >MRUd R5Vd gRV> UP UP! RDP UaP UP. U8P R.DP D8UP SU S!U SV SVa SUj S",
+"8U SVj SsV UP( U+P R(DP +DUP P(U. +PU8 RDP(. R+D8P SU( S+U SV( SV+ UjS( U+S",
+"8 VjS( VsS+ RWU R!UW RWD UWRa R.UW UWR8 R.WD H8UP SUW UWS! SZV VZSa UWSj UW",
+"S8 SjVZ SVsZ UdP U+RW HPUd gUP U.dP 8dUP RWDd. U8gP SdU U+Sd SVd gSV UdSj U",
+"8Sd SjVd SsgV RmU R!Um RDm UaRm U5P U8Rm 5DRm 5aUP SUm UmS! SVm VmSa SpU pU",
+"S8 VpS VpSs U;P U+Rm DmR; +DRm 5PU; >PU R5D;P RD>P S;U U+S; SV; V+S; pUS; S",
+">U S;Vp S>V UWRm RWUm! UHRm RHmUa U5RW R5WU8 H5UP RH8Um UWSm S!UWm VmSZ SZV",
+"am SWpU SpUW8 SZVp SZpVs vRU R+vU vRD vRgU R5vU vU>P R5vD gU>P SvU vUS+ VvS",
+" VvgS pUSv vUS> VpSv yVS Rb Rb& RbD cR Rb. Rb8 bDR. cR8 RbM bMR& VRb cRV Rb",
+"j b8Rj RbVj scR Rb( Rb+ bDR( cR+ b(R. b+R8 RbD(. R+c8 R(bM bMR+ RbV( V+cR R",
+"(bj b+Rj VRbj( s+cR RbE REU& RbH cRH bER. REb8 R.bH RHc8 REbM M&ERb RbVH VR",
+"cH REbj Rb8ME bHRj sHcR Rbd b+Rd bHRd gcR R.bd b8Rd RbHd. g8cR bMRd dM&Rb R",
+"bVd cRgV bdRj d&jRb VdRbj scgR Rb2 R2U& bDR2 cR2 Rb5 b5R8 b5RD cR5 R2bM M&2",
+"Rb RbV2 V2cR b5Rj Rb58M RbV5 c5sR Rb; b+R; b;RD cR; b5R; >Rb Rb5D; c>R bMR;",
+" M;&Rb RbV; V;cR b;Rj Rb>M V5Rb; sRc> bER2 Rb&E2 R2bH RHc2 REb5 Rb58E bHR5 ",
+"RHc5 RbME2 RbEM&2 V2RbH cRVH2 Rb5ME M&ERb5 V5RbH cR5sH bdR; Rb+d; bHR; c;gR",
+" b5Rd Rb>d RbH5d gRc> RbdM; RbdM;& VdRb; gVcR; Rb5dM >MbRd V5dRb V>gcR RbP ",
+"UP& bPRD cRP R.bP bPR8 RbDP. R8cP Sb Sb& SVb Sc Sbj Sb8 VbSj Scs R(bP bPR+ ",
+"RbDP( R+cP RbP(. Rb+8P bP(RD. cR+8P Sb( Sb+ VbS( Sc+ bjS( b+S8 SVbj( S+sc R",
+"bW bWR& bHRW cRW R.bW bWR8 RbHW. RWc8 SbW bWS& SZb ScZ bWSj bWS8 SjZb ZcSs ",
+"bWRd b+RW RbHdP cRgP RbWd. dP&U8 dP.RbH cRWg8 Sbd b+Sd ZbSd gSc bdSj b8Sd S",
+"Zbdj gsSc Rbm bmR& bmRD cRm b5Rm b8Rm Rb5Dm R5cm Sbm bmS& VmSb Scm Spb pbS8",
+" SbVp Scp bmR; b+Rm RbmD; R+cm Rb5;P Rb>P b5PRD; cR>P Sb; b+S; V;Sb Sc; pbS",
+"; S>b SpbV; Sc> bWRm RbWm& bHRm RHcm b5RW Rb5W8 RbH5W R5cW bWSm SbWm& SmZb ",
+"cmSZ SWpb SpbW8 ZpSb SZcp vRb Rbv& RbvD cvR Rbv5 >Rvb vRbH5 v>cR Svb vbS+ S",
+"bVv Scv pvSb v>Sb VvpSb ycS Rk Rk! RkB Rak R1 R18 R1B R1a RkM kMR! RTk TkRa",
+" lR lR8 lRT lsR Rk( R+k k(RB +kRa R1( R1+ 1(RB 1+Ra kMR( Rk+M R(Tk +kRT lR(",
+" l+R RTl( sRl+ RkE kER! RHk HkRa R1E RE8k R1H 1HR8 kMRE RkM!E HkRT RHTak lR",
+"E R8lE lHR sRlH Rdk +kRd HkRd gRk R1d 1+Rd 1HRd gR1 RkdM dkMR+ TkRd RTgk ld",
+"R R+ld RHld glR Rk2 k2R! k2RB R2ak R15 5kR8 RB5k 1aR5 kMR2 RkM!2 R2Tk ak2RT",
+" lR5 R5l8 R5lT l5sR R;k +kR; RBk; akR; R1; >kR RB1; R1>a RkM; k;MR+ TkR; ak",
+";RT l;R l>R RTl; sRl> kER2 RkE!2 R2Hk ak2RH RE5k R158E 1HR5 R1H5a RkME2 kME",
+"R2! RHTk2 RHTak2 R5lE lR58E RHl5 lsRH5 dkR; dk;R+ HkR; R;gk 1dR5 R1>d 1HR; ",
+"gR>k dkMR; R+dk;M RH;Tk gRTk; R5ld >Rld RHl; gRl> kP kP! kPB akP R1P 8kP RB",
+"1P 1PRa Sk S!k STk Sak Sl Sl8 SlT Ssl kP( +kP P(kB ak+P R(1P 1PR+ kP(1B akP",
+"1+ Sk( S+k TkS( +TSk Sl( l+S STl( l+Ss RWk R!Wk HkP WkRa R1W 1WR8 1HRW 1WRa",
+" SWk WkS! SZk ZkSa lWS S8lW lZS lZSs dkP +kRW dkHP gkP 1WRd 1+RW dkP1H R1gP",
+" Sdk +WSk ZkSd gSk ldS S+lW SZld glS Rmk R!km RBkm akRm R1m 1mR8 RB1m 1aRm ",
+"Skm kmS! TkSm akSm Slp lpS8 lTSp Slsp k;P +kRm kB;P k;aP 1mR; >kP k;P1B ak>",
+"P S;k +kS; TkS; akS; l;S S>l lTS; Ssl> WkRm km!RW HkRm akmRH 1WR5 R1W8m 1HR",
+"m akPH5 WkSm S!Wkm SmZk SZakm SplW SlpW8 SplZ SZpls vRk R+vk RHvk vRgk vR1 ",
+"vR>k R1vH gk>P Svk vkS+ ZkSv gkSv lvS S>lv lZSv ylS R9 R9& R9B R9a R91 :R 9",
+"1RB :Ra R9M 9MR& R9T 9TRa lR9 l:R R9lT s:R R9( R9+ 9(RB 9+Ra 91R( :R+ R91(B",
+" R+:a R(9M 9MR+ R(9T 9+RT R9l( :Rl+ lR9T( s+:R R9E REk& R9H 9HRa 91RE :RE 9",
+"HR1 :RH RE9M k&ERM 9HRT R9HT& R9lE lE:R R9lH :RlH R9d 9+Rd 9HRd gR9 9dR1 :R",
+"d R9H1d g:R 9MRd dk&RM 9TRd R9gM R9ld :Rld lHR9d gRl: R92 R2k& 92RB R29a R9",
+"5 :R5 RB95 R5:a R29M k&2RM R29T R9T&2 R9l5 l5:R 95RT s5:R R9; 9+R; RB9; 9aR",
+"; 95R; :>R R95;B :a>R 9MR; k;&RM 9TR; aM;R9 R9l; :Rl> l;R9T :>sR 9ER2 k&ER2",
+" R29H R9H&2 RE95 R5:E 9HR5 RH:5 R9ME2 R9EM&2 R9HT2 aM2R9H lR95E :R5lE lHR95",
+" :RHl5 9dR; dk&R; 9HR; R9g; 95Rd >R:d R9H1; :>gR R9dM; R9dM;& R9HT; gR9T; l",
+"dR95 l>:Rd lH;R9 g:Rl> R9P kP& RB9P 9PRa 9PR1 :RP kPB91 Ra:P S9 S9& S9T S9a",
+" Sl9 S: lTS9 S:s R(9P 9PR+ kP(9B akP9+ kP(91 R+:P 9P(R1B :R+aP S9( S9+ 9TS(",
+" 9+Sa l(S9 S:+ Sl9T( S+s: R9W 9WR& 9HRW 9WRa 9WR1 :RW R9H1W RH:W S9W 9WS& S",
+"Z9 Z9Sa S9lW S:W S9lZ S:Z 9WRd 9+RW dkP9H R9gP dkP91 R+:W 9HPR1d :RgP S9d 9",
+"+Sd Z9Sd gS9 S9ld S:d SZ9ld gS: R9m 9mR& RB9m 9aRm 95Rm :Rm R95mB Ra:m S9m ",
+"9mS& 9TSm 9aSm Sp9 S:p STp9 :pSs 9mR; 9+Rm k;P9B ak;9P k;P95 :R>P k;B95P :>",
+"Ram S9; 9+S; 9TS; 9aS; S9l; S:> Sp9T; s:S> 9WRm km&RW 9HRm km&RH 95RW R5:W ",
+"R9H1m RH:m 9WSm S9Wm& SmZ9 SZ9am SWp9 :WSp ZpS9 SZ:p vR9 R9v& R9vH vRg9 R9v",
+"1 :vR vR91H gR:v Sv9 v9S+ ZvS9 g9Sv S9lv S:v Sv9lZ y:S RUk U!Rk RDk DkRa R1",
+"U 1UR8 R1D 1URa UkRM RUkM! VRk RaVk lRU R8lU VlR VlsR UkR( RU+k R(Dk +kRD R",
+"(1U 1UR+ R(1D 1+RD RUkM( R+UkM RkV( R+Vk RUl( R+lU VRl( lRV+ UkRE RUk!E HkR",
+"D RHUak RE1U R1U8E 1URH R1HU8 RUkME U!kRME RHVk VRHak RUlE lRU8E VRlH lsVRH",
+" RUdk R+Udk DkRd RDgk 1URd R1+Ud 1DRd R1gU dkMRU R+UdkM RdVk VRgk RdlU l+RU",
+"d lRVd VlgR UkR2 RUk!2 R2Dk ak2RD 1UR5 R1U58 1DR5 R1D5a RUkM2 U!kRM2 RkV2 V",
+"2Rak R5lU lRU58 lRV5 lsVR5 RUk; R+Uk; DkR; ak;RD 1UR; R1>U 1DR; R1>D k;MRU ",
+"R+Uk;M R;Vk V+Rk; R;lU lR>U lRV; >RVl RUkE2 U!kRE2 RHUk2 RHUak2 R1U5E 1U5R8",
+"E R1HU5 1UHR5a UkMRE2 !ER2UkM V2RHk ak2VRH lRU5E R5Ul8E VlRH5 Vs5lHR dk;RU ",
+"R+Udk; RH;Dk gRUk; R1dU5 >kRUd R1HU; >kgRD RdUk;M dkR;U+M VdRk; gVRk; ldRU5",
+" l>RUd lH;VR V>lgR UPk U!kP DkP akUP 1UP U81P 1PRD Ua1P SUk U!Sk SVk VaSk S",
+"lU lUS8 SlV SVls U(kP +kUP D(kP Dk+P 1(UP U+1P R1DP( R1+DP UkS( U+Sk VkS( S",
+"kV+ SUl( lUS+ l(SV SVl+ WkUP kP!UW HkUP akPUH 1URW R1WU8 1WRD R1WUa UWSk S!",
+"UWk ZkSV SZVak SUlW SlUW8 SVlZ SlVsZ dkUP dkPU+ dkDP UPgk Ud1P dkPU8 dkP1D ",
+"1UgP UdSk S+UWk SkVd SVgk lUSd S8dlU SVld SlgV kmUP km!UP DkRm akmRD 1URm R",
+"1mU8 1DRm akPU5 UmSk S!Ukm SkVm SVakm pUSl SlpU8 SlVp SlVsp k;UP k;PU+ k;DP",
+" ak;UP U;1P 1U>P k;P1D Dk>P U;Sk S+Ukm SkV; SV+km lUS; >USl SVl; SlV> RWUkm",
+" RWUkm! RHmDk RWDakm R1WU5 1UWR8m R1HUm 1UHR8m SUWkm km!SUW SZVkm ZkVSam Sl",
+"pUW lWpS8U SlVZp VplSsZ UPvk vRU+k RDvk gvRDk R1vU >kvUP R1vD >kgUP SUvk Sv",
+"U+k vkSV VvgSk vUSl lv>SU SlVv SlyV tR tR& tRD tcR tR1 t:R R1tD :cR tRM R&t",
+"M VtR VtcR ltR :Rlt lRVt uR tR( t+R RDt( cRt+ R1t( :Rt+ tR1D( :+cR RMt( R+t",
+"M VRt( tRV+ tRl( lRt+ ltVR( uR+ tRE R&tE tHR cRtH R1tE tE:R R1tH :RtH RMtE ",
+"tRM&E VRtH tcVRH tRlE t:RlE lRtH uRH tdR R+td RHtd gtR R1td :Rtd tHR1d t:gR",
+" RdtM t+RdM tRVd VtgR lRtd t:dlR tdVlR ugR tR2 R&t2 RDt2 c2tR t5R :Rt5 R5tD",
+" cRt5 RMt2 tRM&2 tRV2 tcVR2 lRt5 t:Rl5 tRV5 uR5 t;R R+t; RDt; cRt; R1t; t>R",
+" t5RD; :Rc> R;tM t+RM; tRV; tc;VR lRt; >Rlt t5VR; u>R REt2 tR&E2 RHt2 tcRH2",
+" R5tE t:R5E RHt5 t:HR5 tRME2 M&EtR2 tHVR2 cRVtH2 t5RlE lt5:RE tH5lR RHu5 Rd",
+"t; t+Rd; RHt; t;gR R5td >Rtd tH5Rd gRt> tdRM; dM&t;R tH;VR gtVR; t5dlR t>lR",
+"d tH;lR g>uR tP tP& tPD tcP tP1 t:P 1DtP :ctP St St& StV Sct Stl S:t SVlt u",
+"S tP( t+P DPt( cPt+ 1Pt( :Pt+ tP1D( t:Pc+ St( St+ S(Vt tcS+ l(St l+St SlVt(",
+" uS+ tWR RWt& tHP cRtW R1tW :RtW 1HtP :HtP StW tWS& tZS tZSc lWSt tWS: lZSt",
+" uZS tdP R+tW HPtd gtP 1dtP :dtP tHP1d t:gP Std t+Sd SdtZ gtS ldSt t:Sd Std",
+"lZ ugS tmR Rmt& RDtm cRtm t5P :Rtm 5DtP cR:m Stm tmS& tmSV tmSc tpS tpS: Vp",
+"St upS t;P R+tm D;tP c;tP 1;tP t>P t5PD; tc>P St; t+S; t;SV S;tc l;St S>t S",
+"t;Vp u>S RWtm tWRm& RHtm tcWRm R5tW t:WR5 H5tP t:HRm SWtm StWm& tmSZ ScZtm ",
+"tWSp S:ptW SZtp SZup tvR vRt+ vRtH gRtv vRt5 >Ptv tvR1H >Pgt tvS S+tv StVv ",
+"tvgS Stlv tvS: lvVSt yuS )O !)O )BO a)O )O. 8)O )O.B a)8O )OK )O!K T)O a)TO",
+" jO) 8)jO T)jO s)O *O +*O *BO a*O *O. 8*O .B*O 8Oa* *OK *O+K T*O +OT* *jO j",
+"O8* jOT* s*O E)O E)!O H)O a)HO )OE. E)8O )OH. 8)HO )OEK !E)OK T)HO HTa)O E)",
+"jO jO8E) H)jO H)sO d*O d*+O H*O g*O *Od. d*8O *OH. 8*gO *OdK +d*OK HOT* T*g",
+"O d*jO dj*+O jOH* gOs* )O2 )O!2 )O2B )Oa2 5)O 8)5O )B5O a)5O )O2K !)2OK )OT",
+"2 Ta)O2 5)jO jO58) T)5O 5)sO ;*O ;*+O ;O*B ;*aO 5*O >*O 5O*B a*>O *O;K +;*O",
+"K ;*TO a;*TO jO5* *j>O 5OT* >Os* )OE2 !)2EO )OH2 Ha)O2 E)5O 58E)O 5)HO H58)",
+"O EK)O2 !)OEK2 HT)O2 Ta)HO2 jO5E) 58EjO) H5T)O sH5)O ;*dO +d;*O ;*HO ;*gO d",
+"*5O d*>O HO5* g*>O dK;*O dK;+*O H;T*O gT;*O dj*5O >*djO H5*jO s*Og> P) P)! ",
+"P)B aP) P). 8P) .BP) 8)aP QP) P)Q! TP) Q)aP Pj) Q)8P T)Pj sP) P* +P* P*B aP",
+"* P*. 8P* P.*B aP8* Q*P Q*+P TP* T*+P P*j 8PQ* PjT* sP* WP) P)W! HP) H)aP P",
+")W. W)8P P)H. H)8P QPW) Q!WP) ZP) aPZ) W)Pj Pj)W8 PjZ) ZPs) W*P W*+P HP* gP",
+"* W.P* 8PW* H.P* 8Pg* dPQ* +WQP* Z*P Z*gP P*Wj dPj8* P*Zj s*gP mP) P!m) P)m",
+"B mPa) 5P) 5)8P P)5B 5)aP mPQ) Q!mP) mPT) amPQ) pP) 8Pp) TPp) pPs) m*P m*+P",
+" *B;P m*aP 5P* >P* *B5P aP>* ;PQ* m*P+Q m*TP am*TP p*P p*>P TPp* s*>P mPW) ",
+"W!mP) mPH) amPH) WP5) 5W8P) H)5P H5P8) WQmP) WmPQ!) mPZ) ZamP) WPp) pW8P) p",
+"PZ) sP)Zp vP* +Pv* HPv* vPg* 5Pv* vP>* 5PH* >*gP Q*vP v+QP* vPZ* ZvPg* vPp*",
+" >Ppv* ZPp* y*P ,O ,&O ,OB ,aO ,O. ,8O .B,O 8a,O ,OK &O,K ,TO ,OT& ,jO ,O&j",
+" jO,T s,O ,*O -O ,O*B -aO *O,. -8O *B,O. 8a-O *O,K -OK ,OT* -TO ,O*j -jO *j",
+"O,T s-O ,EO &E,O ,HO ,OH& EO,. 8E,O HO,. ,OH8 EK,O ,&EOK HT,O ,HTaO jO,E &j",
+"E,O ,OHj ,HsO ,dO -dO ,OH* g-O dO,. 8d-O ,HdO. -8gO dK,O dK-O ,OTd gO-T ,Od",
+"j dj-O ,HjdO gOs- ,O2 &O,2 2B,O aO,2 ,5O ,O5& 5B,O ,O5a 2K,O ,&O2K TO,2 ,Ta",
+"O2 jO,5 &jO,5 ,O5T ,5sO ,;O -;O ;O,B a;-O ,O5* ->O ,5;OB -a>O ;O,K ;O-K ,OT",
+"; T;-O ,O;j >O-j ,5T;O >Os- EO,2 ,&EO2 HO,2 ,HaO2 5E,O ,58EO ,OH5 ,H58O ,EO",
+"2K &EO,2K ,HTO2 H&O,T2 ,5jEO ,5E&jO ,H5jO s,H5O d;,O d;-O ,OH; -;gO ,O5d -d",
+">O ,H5dO >Og- ,d;OK -d;OK ,H;TO -T;gO ,5djO ->djO ,H;jO s-g>O ,P ,P& ,PB ,a",
+"P ,P. ,8P P.,B 8P,a ,QP Q&,P ,TP Qa,P ,Pj Q8,P TP,j sP, ,P* -P *B,P -Pa ,.P",
+"* -P8 P*.,B 8P-a Q*,P -QP T*,P -TP P*,j -Pj P*j,T s-P ,WP W&,P ,HP HP,a WP,",
+". W8,P ,.HP H8,P WQ,P ,WQP& Z,P ,aZP Wj,P P&j,W ,PZj Z,sP ,dP -WP HP,d g-P ",
+",.dP W8-P ,HPd. g8-P Qd,P Qd-P ,dZP Z-P dP,j Wj-P Z*P,j gPs- ,mP m&,P mP,B ",
+"am,P ,5P 5P,8 ,B5P 5a,P Qm,P m&P,Q Tm,P ,QamP p,P ,8pP ,TpP p,sP ,;P -mP ,B",
+";P am-P 5P,; >P- ,5P*B -a>P Q;,P Q;-P T;,P Tm-P ,;pP -pP p*T,P >Ps- Wm,P m&",
+"P,W Hm,P ,HmaP 5W,P ,5W8P H5,P ,H58P ,WQmP ,WQm&P ,mZP Z&m,P ,WpP p&W,P ZPp",
+", sP,Zp v,P -vP ,HvP gP-v ,5vP >P-v v,H5P g->P ,QvP vQ-P ZPv, -PZv pPv, pv-",
+"P Zp*,P y-P C)O C)!O D)O a)DO )OC. C)8O )OD. 8)DO )OCK !CO)K T)DO DTa)O C)j",
+"O jO8C) D)jO D)sO *CO *C+O D*O +OD* CO*. *C8O *OD. DO8* CK*O +*COK DOT* a*O",
+"DT *CjO *jC+O jOD* D*sO E)CO CE)!O D)HO HDa)O C).EO 8CE)O HD)O. H8D)O CE)OK",
+" EK)!CO HDT)O DTaH)O jOCE) 8CEjO) HjD)O sHD)O *CdO +d*CO HOD* D*gO d*CO. 8d",
+"*CO H*DO. gD8*O dK*CO dK*+CO H*DTO gDT*O dj*CO 8dC*jO H*jDO s*DgO )OC2 !)2C",
+"O )OD2 Da)O2 C)5O 58C)O D)5O 5D8)O 2KC)O CKO!)2 DT)O2 Ta)DO2 jO5C) 58CjO) 5",
+"DT)O s5D)O *C;O +;*CO ;*DO a;*DO *C5O *C>O 5OD* D*>O ;*COK ;*C+OK D;T*O D;T",
+"a*O ;jC*O >*jCO 5D*jO >D*sO CE)O2 !O2CE) HD)O2 Da)HO2 5CE)O 8CE5)O H5D)O 5D",
+")H8O C)OEK2 C)!OEK2 DT)HO2 DTH)aO2 5CEjO) 5)jO8CE 5D)HjO H5Ds)O d;*CO d;*+C",
+"O H;D*O gD;*O 5d*CO >*dCO H5*DO >D*gO ;*CdKO dK+*;CO D;TH*O D;Tg*O 5dC*jO d",
+"j*>CO djO5D* gs*>DO PC) !CP) DP) D)aP C)P. PC8) P)D. D)8P PCQ) Q!PC) Q)DP a",
+"P)QD jCP) PjC8) D)Pj DPs) P*C +CP* DP* D*+P *CP. 8CP* D.P* 8PD* QCP* P*C+Q ",
+"DPQ* aP*QD PC*j P*j+C P*Dj DPs* PCW) W!PC) H)DP aP)WD WPC). W8PC) HPD). H8P",
+"D) WQPC) WPCQ!) DPZ) ZDaP) PjCW) W8CPj) ZDPj) sPDZ) WCP* dPC+* DPH* DPg* dP",
+"C*. W8*PC HP*D. gPD8* dPCQ* +WQP*C DPZ* Z*DgP dPj*C dPCQ8* Z*DPj sP*gD PCm)",
+" mPC!) mPD) amPD) PC5) 5P8C) 5)DP 5DP8) QmPC) mPCQ!) QDmP) QDmaP) PCp) p8PC",
+") DPp) sPDp) mCP* m*P+C m*DP am*DP 5CP* P*>C DP5* DP>* m*PQC +QmP*C QD;P* Q",
+"D;aP* P*pC >Pp*C DPp* sP*pD WmPC) mPCW!) HmDP) HmDaP) 5WPC) W8C5P) H5PD) aP",
+")5WD QmPWC) W)Q!mPC ZDmP) amPZD) pWPC) W8PpC) ZpDP) ZpDsP) P*vC v+P*C DPv* ",
+"gvDP* v5P*C >Pv*C vD5P* >PgD* vQP*C P*Cv+Q ZvDP* gvDZ*P pvP*C pv*>PC Zp*DP ",
+"DPy* ,bO b&,O ,DO c,O bO,. ,Ob8 DO,. ,8cO bK,O ,b&OK ,ObT ,TcO ,Obj &jO,b ,",
+"ODj c,sO b*O -bO ,OD* c-O *Ob. b8-O ,D*O. -8cO *ObK bK-O bOT* cO-T jOb* bj-",
+"O ,Dj*O sOc- bE,O ,b&EO ,ObH ,HcO ,bEO. ,8bEO ,HbO. cH8,O ,bEOK bK&,EO ,HbT",
+"O cHT,O ,jbEO b8E,jO ,HjbO s,HcO ,Obd bd-O ,ODd gOc- ,dbO. -b8dO ,DdO. c-8g",
+"O ,dbOK -bdOK ,DdTO c-TgO ,djbO -jbdO ,DdjO s-gcO bO,2 ,b&O2 DO,2 ,Oc2 ,Ob5",
+" ,5b8O ,O5D ,5cO ,bO2K bK&,O2 ,DTO2 c2T,O ,5bjO ,5b&jO ,5DjO s,5cO ,Ob; b;-",
+"O ,OD; -;cO bO5* -b>O ,5D;O >Oc- ,;bOK -b;OK ,D;TO c-T;O ,;jbO ->bjO ,D;jO ",
+"s-c>O ,bEO2 b&E,O2 ,HbO2 c2H,O ,5bEO b5E,8O ,H5bO c5H,O bKE,O2 EO,2bK& bHO,",
+"T2 ,HTc2O b5E,jO 5jbE,8O ,HOb5T c5Hs,O ,db;O -bd;O ,H;bO c-;gO ,5dbO ->bdO ",
+",5DdO c>g-O bdO,;K bd;-OK ,HObT; -T;gcO djOb5* >bd-jO djO,5D c>gs-O ,Pb ,bP",
+"& ,DP cP, ,.bP b8,P ,.DP ,8cP bQ,P ,QbP& bT,P ,QcP bP,j P&j,b DP,j cPs, bP*",
+" -Pb DPb* c-P b.P* b8-P ,DP*. c8-P Q*bP bQ-P TPb* -QcP P*bj bP-j P*j,D c-sP",
+" bW,P ,WbP& bH,P ,HcP ,WbP. ,W8bP ,HPb. cW8,P ,WbQP bWQ,P& ,DZP cPZ, ,WjbP ",
+"bW8,Pj ZbP,j sP,Zc bd,P bW-P HPb* c-gP ,dPb. -Wb8P ,DdP. c-W8P ,QdbP -WbQP ",
+"bPZ* cPZ- dPjb* -WjbP Zb*Pj s-PZc bm,P m&P,b Dm,P ,mcP b5,P ,5Pb8 5D,P ,5cP",
+" ,QbmP ,Qbm&P ,QDmP cQm,P ,Ppb pb8,P ,DpP p,cP b;,P bm-P D;,P -mcP 5Pb* >b-",
+"P ,5D;P c->P ,Q;bP -Qb;P ,QD;P c-Q;P bPp* pb-P pb*DP cP-p ,WbmP ,Wbm&P ,Hmb",
+"P cWm,P ,5WbP b5W,8P ,H5bP c5W,P bWQ,mP QmP&,Wb Zbm,P ZcP,m pbW,P ,W8pbP Zp",
+"b,P cpZ,P ,Pvb vb-P ,DvP cP-v vb5,P -v>bP vD,5P cv->P vbQ,P -vbQP Zvb,P cvZ",
+"-P pvb,P -pvbP ZpbP* c-yP 0)O 0)!O 0)OB 0)aO 1)O 8)1O )B1O a)1O )O0K !K0)O ",
+"0)TO Ta0)O 1)jO jO18) T)1O 1)sO *0O *0+O 0B*O *0aO 1*O 1O8* 1O*B 1Oa* 0O*K ",
+"+*0OK *0TO a*0TO jO1* *jO1+ 1OT* 1*sO 0)EO !E)0O 0)HO Ha0)O E)1O 18E)O H)1O",
+" 1H8)O EK0)O !0OEK) HT0)O Ta0H)O jO1E) 18EjO) 1HT)O s1H)O *0dO +d*0O *0HO *",
+"0gO d*1O 1+d*O 1OH* 1*gO dK*0O dK*+0O H*T0O gT*0O dj*1O 1+d*jO 1H*jO s*1gO ",
+")O02 0)2!O 0)2OB a0)O2 5)1O 158)O 15)OB 1a5)O 0)2OK !)O2K0 T0)O2 a0)TO2 jO1",
+"5) 158jO) 1T5)O s15)O *0;O +;*0O *B;0O a;*0O 1O5* 1*>O 1;*OB >*1aO ;*0OK ;*",
+"0+OK T;*0O T;0a*O ;jO1* >*1jO 1T;*O s*1>O 0)2EO !EO0)2 H0)O2 a0)HO2 15E)O 5",
+"8E1)O 1H5)O H5)1aO E)O2K0 0)EO2K! T0)HO2 0)HOTa2 15EjO) 5)jO18E H5)1TO 1H5s",
+")O d;*0O d;*+0O H;*0O g;*0O 1d5*O >*1dO 1H;*O g>1*O ;*0dKO dK+*;0O T;0H*O T",
+";*g0O 1d5*jO dj*>O1 ;jO1H* g>1s*O P0) !0P) )BP0 P0a) 1P) 1)8P P)1B 1)aP P0Q",
+") Q!P0) P0T) aP0Q) 1)Pj Pj)18 1)TP 1Ps) P*0 +0P* P0*B a0P* 1P* +P1* *B1P aP",
+"1* Q0P* P*0+Q T0P* aP*Q0 Q*1P P*j1+ TP1* 1Ps* P0W) W!P0) P0H) aP0H) WP1) 1W",
+"8P) 1)HP 1HP8) WQP0) WP0Q!) P0Z) ZaP0) Pj)1W 1W8Pj) 1PZ) sP1Z) W0P* dP0+* H",
+"0P* P*g0 W*1P 1+WP* HP1* 1Pg* dP0Q* +WQP*0 P*Z0 Z*Pg0 dPj1* 1+WP*j 1PZ* sP*",
+"g1 P0m) mP0!) mP0)B amP0) 1)5P 1m8P) 1mP)B 1amP) QmP0) mP0Q!) TmP0) Tm0aP) ",
+"1Pp) p18P) p1TP) sP1p) m0P* m*P+0 m*P0B am*P0 5P1* 1P>* 1m*PB >P1a* m*PQ0 +",
+"QmP*0 Tm*P0 am0TP* 1Pp* >Pp1* p*1TP sP*p1 WmP0) mP0W!) HmP0) Hm0aP) 1W5P) 5",
+"W81P) 1HmP) am)1HP QmPW0) P!m0WQ) ZmP0) amPZ0) p1WP) 1W8pP) Zp1P) Zp1sP) P*",
+"v0 v+P*0 vHP*0 gvP*0 1Pv* >Pv1* v1HP* >Pg1* vQP*0 P*0v+Q ZvP*0 gvPZ*0 pv1P*",
+" pv1>P* Zp*1P 1Py* ,9O 9&,O 9O,B ,O9a ,1O :,O 1O,B ,a:O 9O,K ,9&OK ,O9T ,T9",
+"aO ,O9j ,j:O ,O1T :,sO 9*O -9O 9O*B 9a-O ,O1* :-O ,1*OB -a:O *O9K 9O-K 9OT*",
+" 9T-O jO9* :O-j ,1T*O sO:- 9E,O ,9&EO ,O9H ,H9aO 1E,O ,E:O ,O1H ,H:O ,9EOK ",
+"9&E,OK ,H9TO 9HT,aO ,1jEO :j,EO ,1HjO s,H:O ,O9d 9d-O 9OH* -9gO ,O1d -d:O ,",
+"1HdO gO:- ,d9OK -9dOK ,Td9O -T9gO ,1djO :-djO ,1TdO g:s-O 9O,2 ,9&O2 ,9O2B ",
+",a9O2 ,O95 ,5:O ,15OB :5a,O ,9O2K 9&O,2K ,T9O2 9TO,a2 ,15jO :5j,O ,1T5O s,5",
+":O ,O9; 9;-O ,;9OB -9a;O ,O1; >O:- ,1;OB :->aO ,;9OK -9;OK ,T;9O -T9;O ,1;j",
+"O :->jO ,1T;O s-:>O ,9EO2 9&E,O2 ,H9O2 9HO,a2 ,15EO :5,EO ,1H5O :H5,O 9EO,2",
+"K EO,29&K 9HO,T2 HO,29Ta 95E,jO ,5j:EO ,HO95T :H5s,O ,d9;O -9d;O ,H;9O g-9;",
+"O ,1d5O :->dO ,1H;O g:->O 9dO,;K 9d;-OK ,HO9T; g9;-TO djO,1; ->j:dO ;jO,1H ",
+"s->g:O ,P9 ,9P& ,B9P 9a,P ,1P :P, ,B1P ,a:P 9Q,P ,Q9P& 9T,P ,Qa9P 9P,j ,Q:P",
+" 1T,P :Ps, 9P* -P9 *B9P 9a-P 1P9* :-P ,1P*B :a-P Q*9P 9Q-P TP9* 9T-P P*9j -",
+"Q:P P*j9T :-sP 9W,P ,W9P& 9H,P ,HP9a 1W,P ,W:P 1H,P ,H:P ,W9QP 9WQ,P& ,PZ9 ",
+"Z9a,P ,1WPj :WQ,P ,1ZP :PZ, 9d,P 9W-P HP9* -Pg9 1d,P -W:P ,1HdP :-gP ,Qd9P ",
+"-W9QP 9PZ* -PZ9 dPj,1 :-WPj Z9*1P :PZ- 9m,P m&P,9 ,m9PB ,am9P 95,P ,5:P ,1m",
+"PB :ma,P ,Q9mP ,Q9m&P ,Tm9P 9Tm,aP ,1pP p,:P p9T,P sP,:p 9;,P 9m-P ,;P9B -m",
+"9aP 1;,P :->P ,1;PB :-maP ,Q;9P -Q9;P ,T;9P -Tm9P 9Pp* :P-p p9*TP -ps:P ,W9",
+"mP ,W9m&P ,Hm9P 9Hm,aP ,1W5P :W5,P ,1H5P :Hm,P 9WQ,mP QmP&,W9 Z9m,P ,amZ9P ",
+"p9W,P :pW,P Zp9,P Z:p,P ,Pv9 v9-P v9H,P -vg9P ,1vP :P-v v1,HP :v-gP v9Q,P -",
+"v9QP Zv9,P Z-v9P pv9,P :v-pP Zp9P* :-yP 0)CO C0)!O 0)DO Da0)O C)1O 18C)O D)",
+"1O 1D8)O C0)OK !K)C0O DT0)O Ta0D)O jO1C) 18CjO) 1DT)O s1D)O C0*O +*C0O *0DO",
+" a*0DO *C1O 1+*CO 1OD* 1+D*O *C0OK *C0+OK D*T0O D*0+TO *jC1O 1+C*jO 1D*jO s",
+"*1DO C0)EO !E)C0O HD0)O Da0H)O 1CE)O 8CE1)O 1HD)O H8)1DO EK)C0O 0)EOCK! DT0",
+"H)O 0)HODTa 1CEjO) C)8O1jE Hj)1DO 1HDs)O d*C0O d*C+0O H*D0O gD*0O 1d*CO 8dC",
+"1*O 1H*DO g1D*O *C0dKO C0dO+*K Td0D*O D*Tg0O 1dC*jO dj1*+CO djO1D* g1Ds*O C",
+"02)O !)2C0O D0)O2 a0)DO2 15C)O 58C1)O 1D5)O 5D)1aO CKO0)2 0)C2!KO T0)DO2 0)",
+"TODa2 15CjO) 5)jO18C 5D)1TO 1D5s)O ;*C0O ;*C+0O D;*0O D;0a*O 1;*CO >*1CO 1D",
+";*O >D*1O *C0;OK C0;O+*K T;0D*O a;D*T0O 1;C*jO *jC>O1 ;jO1D* s*1>DO CEO0)2 ",
+"0)C2!EO D0)HO2 0)HODa2 5CE1)O 5E1O8C) H5)1DO 5OD81H) 0)C2EKO C)!OE02K 0)HOD",
+"T2 DaHO0)T2 5)jO1CE 5j1EC)8O H)Dj15O 15s)HDO ;*Cd0O C0;O+d* D;0H*O D;*g0O 5",
+"dC1*O 1d*>CO 1HO5D* g1*>DO C0;OdK* dK+*C0;O T;H*D0O D*g0T;O dj1;*CO dj>*1CO",
+" jOH;1D* >Dgs1*O C0P) PC0!) P0D) aP0D) PC1) 1P8C) 1)DP 1DP8) QPC0) PC0Q!) Q",
+"DP0) QD0aP) PjC1) Q8C1P) 1QDP) sP1D) *CP0 P*C+0 D0P* aP*D0 1CP* 1+P*C DP1* ",
+"aP*1D P*CQ0 +QCP*0 QD*P0 aP0QD* P*j1C P*C1+Q P*j1D sP*1D WPC0) PC0W!) HPD0)",
+" WD0aP) 1WPC) W8C1P) 1HPD) aP)1WD QPCW0) QCW0P)! ZDP0) aP0ZD) 1WCPj) QC8P1W",
+") Z1DP) Z1DsP) dPC*0 +WCP*0 HP*D0 gPD*0 1W*PC P*C1+W 1HPD* g1PD* QdCP*0 QCd",
+"P+*0 Z*DP0 gPDZ*0 dPC1Q* WC*j1+P Z1*DP sPDZ1* mPC0) PC0m)! DmP0) Dm0aP) 1mP",
+"C) 8mC1P) 1DmP) am)1DP mPCQ0) P!m0QC) Tm0DP) amDPQ0) p1PC) 1P8pC) pD1P) pD1",
+"sP) m*PC0 +mCP*0 Dm*P0 am0DP* 1m*PC >P1*C 1DmP* >PD1* Q;CP*0 QCm*+P0 ;P0QD*",
+" m*DP+Q0 p*1PC p*1>PC pD*1P sP1pD* mPCW0) P!m0WC) Dm0HP) amHPD0) 5WC1P) W)8",
+"P1mC 1H)5DP H)8m1DP QCW0mP) !Cm)QPW0 DmPZ0) amZPD0) 1WPpC) 18pCWP) pDPZ1) s",
+"1pDZP) vP*C0 P*Cv+0 vDP*0 gP*vD0 v1P*C v1*>PC v1DP* >D*g1P P*CvQ0 P*vC+Q0 v",
+"DPZ*0 gDZ*vP0 v1Pp*C >*v1pPC Z1PpD* y*1DP b9,O ,b9&O ,O9D ,9cO ,Ob1 ,b:O ,O",
+"1D c,:O ,b9OK b9&,OK ,D9TO c9T,O ,1bjO :bj,O ,1DjO s,O:c bO9* b9-O 9OD* -9c",
+"O bO1* -b:O ,1D*O :Oc- b*9OK -b9OK bT*9O c-9TO b1*jO :-bjO b1T*O s-:cO ,b9E",
+"O b9&,EO ,H9bO c9H,O ,1bEO :b,EO ,1HbO :cH,O b9E,OK b9,&EKO bH9,TO ,H9cTO b",
+"1E,jO ,jb:EO ,1ObHj :cHs,O ,db9O -b9dO ,Dd9O c-9gO ,1dbO :-bdO ,1DdO g:c-O ",
+"9dOb*K bd9-OK ,DO9Td -T9gcO djOb1* -jb:dO djO,1D s-cg:O ,b9O2 b9&,O2 ,D9O2 ",
+"c29,O ,1b5O :b5,O ,1D5O :c5,O b9O,2K bO,29&K 9DO,T2 ,T9c2O b15,jO ,5b:jO ,1",
+"Ob5T :c5s,O ,;b9O -b9;O ,D;9O c-9;O ,1;bO :->bO ,1D;O c>:-O 9;Ob*K b;9-OK ,",
+"DO9T; -T9c;O ;jOb1* -jb:>O ;jO,1D c>:s-O b9E,O2 EO,2b9& 9HO,D2 ,H9c2O b1E,5",
+"O ,5b:EO ,1ObH5 c5,:HO EO,2b9K 9&,KEOb2 HO,2bT9 ,9c2HTO 5E9O,jb ,b:EjO5 ,O1",
+"Hb5T sHc5:,O bd9,;O bd9-;O ,HO9D; g-9c;O ,1Ob5d ->b:dO ,1ObH; c>-g:O ,Obd9;",
+"K b9-OdK; ,OH;bT9 gTc;-9O ,O1db;j >j:d-bO 1H,;bTO >Og:s-c ,b9P ,P9b& 9D,P ,",
+"Pc9 b1,P ,P:b 1D,P :,cP ,Qb9P bQ9,P& ,QD9P cQ9,P ,1QbP :Qb,P ,1QDP sP,:c 9P",
+"b* bP-9 DP9* c9-P 1Pb* :b-P ,1DP* c-:P bQ*9P -Qb9P bTP9* c-Q9P P*jb1 :-QbP ",
+"P*j9D s-P:c ,Wb9P bW9,P& ,HP9D cW9,P ,1WbP :Wb,P ,1HbP :cW,P bW9,QP WQP&,b9",
+" Zb9,P Zc9,P b1W,Pj ,Wj:Pb Zb1,P Z:c,P ,dPb9 -Wb9P ,Dd9P c-W9P ,1dbP :-WbP ",
+",1DdP g:Pc- 9QdbP* bQd-P9 Zb*9P Z-c9P b1WP*j :Wb-Pj Zb1P* Z:-cP ,mb9P bm9,P",
+"& ,Dm9P cm9,P ,1mbP :mb,P ,1D5P :cm,P bQ9,mP QmP&,b9 9Dm,TP ,TmcP9 pb9,P :p",
+"b,P p9D,P cp:,P ,;Pb9 -mb9P ,D;9P c-m9P ,1;bP :-mbP ,1D;P c>P:- 9Q;bP* bQ;-",
+"P9 9QD,;P cm9-TP pb*9P -p:bP p9DP* cp-:P bW9,mP WmbP,9& 9Hm,DP ,HmcP9 b1W,5",
+"P ,5W:Pb b1H,5P :H,c5P QmbP,W9 ,bP&WQ9m ,DmZ9P cm9Z,P ,1WpbP pbW:P, Z9PpD, ",
+"Z:Pcp, vb9,P -vb9P v9D,P cv-9P vb1,P :v-bP v1D,P :vc-P bQ*v9P vb9-QP Z9PvD,",
+" Z-9cvP pbPv1, -pb:vP ZbPp9* y:c-P R) R)! R)B Ra) R). R8) .BR) 8aR) RM) M)R",
+"! RT) R)aM Rj) R)8M TjR) sR) R* R+* R*B Ra* R*. R8* R.*B 8*Ra R*M +MR* RT* ",
+"+TR* R*j +jR* T*Rj sR* RE) !ER) RH) HaR) E)R. 8ER) H)R. R)H8 MER) RME!) R)H",
+"M aM)RH jER) R8ME) R)Hj RHs) Rd* +dR* RH* gR* d*R. 8dR* R.H* R8g* dMR* dM*R",
+"+ HMR* RTg* djR* R+jd* H*Rj s*gR R)2 !)R2 2BR) a)R2 R5) 58R) 5BR) R)5a M)R2",
+" RM)!2 T)R2 aM)R2 R)5M R58M) R)5T R5s) R;* +;R* *BR; a;R* R5* >R* *BR5 Ra>*",
+" M;R* M;*R+ T;R* aM;R* 5MR* R*>M 5TR* >Rs* E)R2 RE)!2 H)R2 RHa)2 5ER) R58E)",
+" R)H5 RH58) RME)2 ME)R2! RHT)2 RH)aM2 R5ME) 5MER8) RH5T) sRH5) d;R* R+d;* H",
+";R* R;g* 5dR* Rd>* H5R* >*gR dM;R* R+dM;* RH;T* gRT;* R5dM* >MRd* RH5T* >Mg",
+"R* RP) P)R! P)RB R)aP P)R. R)8P RP).B aP)R8 S) S!) ST) Sa) Sj) S8) TjS) Ss)",
+" R*P +PR* RP*B aPR* R.P* 8PR* P*.RB aP*R8 S* S+* S*T Sa* S*j S8* T*Sj Ss* R",
+"W) W!R) R)HP R)Wa W)R. R)W8 RHW). RH8W) SW) W!S) SZ) ZaS) WjS) W8S) ZjS) s)",
+"SZ RW* +WR* HPR* RWg* R.W* W8R* RH*W. gRW8* Sd* +WS* SZ* gS* W*Sj W8S* SjZ*",
+" s*gS Rm) m)R! m)RB R)am R)5P R)8m R5m)B R5am) Sm) m)S! TmS) amS) Sp) p8S) ",
+"pTS) s)Sp Rm* +mR* *BRm amR* 5PR* Rm>* R5*mB >PRa* S;* +mS* TmS* amS* Sp* S",
+">* STp* s*S> WmR) RWm!) R)Hm RHma) R)5W R5W8) RH5W) RH8m) WmS) S!Wm) ZmS) S",
+"Zam) pWS) SpW8) S)Zp SZps) vR* R+v* RHv* g*vR R5v* >*vR vRH5* >PgR* Sv* v+S",
+"* ZvS* S*gv pvS* v>S* ZpS* yS* ,R ,R& ,RB ,Ra ,R. ,R8 RB,. R8,a ,RM R&,M ,R",
+"T RT,a ,Rj R8,M RT,j sR, ,R* -R *B,R -Ra ,.R* -R8 ,R*.B R8-a R*,M -RM R*,T ",
+"-RT R*,j -Rj ,RT*j s-R ,RE ,ER& ,RH RH,a RE,. ,ER8 ,.RH RH,8 RM,E M&E,R RH,",
+"T ,RHT& ,ERj ,R8ME RH,j ,RsH ,Rd -Rd RH,d g-R ,.Rd R8-d ,RHd. g8-R Rd,M Rd-",
+"M RT,d -RgM Rd,j Rd-j ,RHdj gRs- ,R2 ,2R& RB,2 ,2Ra ,R5 R5,8 RB,5 R5,a RM,2",
+" M&2,R ,2RT ,RT&2 R5,M ,R58M R5,T ,Rs5 ,R; -R; RB,; Ra-; R5,; ->R ,R5*B -a>",
+"R R;,M R;-M RT,; RT-; R;,j -R>M ,R5T; ->sR RE,2 ,R&E2 ,2RH ,RH&2 ,ER5 ,R58E",
+" RH,5 ,RH5a ,RME2 ,REM&2 ,RHT2 aM2,RH ,R5ME M&E,R5 ,RH5T sR,H5 Rd,; Rd-; RH",
+",; g;-R R5,d -d>R ,RH5d ->gR ,RdM; -RdM; ,RHT; -RTg; ,R5dM >M-Rd ,RH;j s-Rg",
+"> ,RP R&,P RB,P Ra,P RP,. R8,P ,RP.B ,R8aP S, S&, S,T Sa, S,j S8, ,TSj Ss, ",
+"R*,P -RP P*B,R Ra-P P*.,R R8-P ,R.P*B -R8aP S*, S- ,TS* S-T ,jS* S-8 S*T,j ",
+"S-s ,RW R&,W RH,W RW,a ,.RW RW,8 ,RHW. ,RHW8 S,W ,WS& SZ, Z&S, ,WSj ,WS8 Sj",
+"Z, s,SZ RW,d -RW ,RHW* -RgP ,RWd. RW-8 dP.,RH -RWg8 Sd, S-W Z*S, gS- ,dSj -",
+"WS8 SZ*,j s-gS ,Rm R&,m RB,m Ra,m R5,m R8,m ,R5mB ,R5am S,m ,mS& ,TSm ,aSm ",
+"Sp, p&S, STp, s,Sp Rm,; -Rm ,Rm*B Ra-m ,R5m* -R>P m*B,R5 >P-Ra S;, S-m ,TS;",
+" -TS; p*S, S-p Sp*,T s-S> RW,m ,RWm& RH,m ,RHam R5,W ,R5W8 ,RH5W ,RH8m ,WSm",
+" S&W,m SmZ, SZ&,m SWp, Sp&,W ZpS, Ss,Zp vR, -vR ,RvH gR-v ,Rv5 v>-R vR,H5 -",
+"vRg> Sv, S-v ZvS, SvZ- pvS, Sv-p Sv,Zp y-S RU) U!R) RD) R)Ua U)R. R)U8 D)R.",
+" R)D8 UMR) RUM!) VR) RaV) R)Uj R8UM) RjV) VRs) R*U U+R* RD* UaR* R.U* U8R* ",
+"R.D* D8R* RUM* R+UM* V*R R+V* U*Rj R+jU* R*Vj V*sR UER) RUE!) R)UH RHUa) RU",
+"E). R8UE) RHU). RH8U) RUME) U!MRE) RHV) VRHa) RjUE) U8ERj) VRHj) VsHR) UdR*",
+" R+Ud* UHR* RDg* RdU*. R8dU* RH*U. gRU8* dM*RU R+UdM* RHV* V*gR RdjU* U8dR*",
+"j VdR*j s*VgR U)R2 RU)!2 D)R2 RDa)2 R)U5 R5U8) R)5D R5D8) RUM)2 U!MR)2 R)V2",
+" V2Ra) R5UM) U58Rj) R5V) Vs5R) U;R* R+U;* D;R* R+D;* U5R* R*>U 5DR* RD>* M;",
+"*RU R+UM;* R;V* V+R;* R5*Uj >MRU* R5V* >RV* RUE)2 U!ER)2 RHU)2 UH)Ra2 R5UE)",
+" U5ER8) RH5U) RH)U5a UMER)2 !ER)UM2 V2RH) RHaV2) U5ERj) REU85M) V5RH) sRHV5",
+") RdU;* U+dR;* RH;U* gRU;* R5dU* >RUd* RH5U* g>RU* RdUM;* dMR;U+* VdR;* gVR",
+";* U5dR*j Rdj>U* V5dR* V>gR* UP) P)U! R)DP U)aP P)U. U)8P RDP). RD8P) SU) U",
+"!S) SV) VaS) UjS) U8S) VjS) s)SV UP* +PU* DPR* aPU* U.P* 8PU* RD*P. aP*U8 S",
+"*U U+S* SV* V+S* U*Sj U8S* SjV* s*SV R)UW RWU!) R)WD RWDa) RWU). RW8U) RWD)",
+". RWD8) UWS) S!UW) S)VZ SZVa) SUWj) S8UW) SZVj) SsZV) UWR* R+WU* HPU* UPg* ",
+"RW*U. RW8U* RWD*. gUP8* UWS* S+UW* Z*SV S*gV SdU*j S8dU* SZ*Vj Ss*gV R)Um R",
+"mU!) R)Dm RDma) U)5P R8mU) R5Dm) RD8m) UmS) S!Um) S)Vm SVam) S)pU SpU8) S)V",
+"p SspV) UmR* R+mU* DmR* am*RD 5PU* UP>* R5Dm* >PUD* UmS* S+Um* VmS* SV+m* p",
+"US* >US* S*Vp S*V> RWUm) UW)Rm! RHmU) am)RWD R5WU) R5)UW8 R5WD) aP)UH5 SUWm",
+") UWmS!) SZVm) VZmSa) SpUW) pUWS8) SZpV) VpZSs) R*vU vRU+* RDv* gvRU* vRU5*",
+" >PUv* vRD5* >PgU* vUS* SvU+* S*Vv VvgS* Sp*vU S>vU* VvpS* SVy* ,Rb R&,U ,R",
+"D cR, ,.Rb Rb,8 ,.RD ,Rc8 Rb,M ,RbM& V,R V,cR Rb,j ,R8bM ,RVj cRs, Rb* -Rb ",
+"R*,D c-R R.b* Rb-8 ,RD*. c8-R bMR* Rb-M ,RV* V-R b*Rj Rb-j V*R,j sRV- ,ERb ",
+",Rb&E Rb,H ,RcH ,RbE. ,R8bE ,RHb. cRH,8 ,RbME ,RbM&E ,RVH cRV,H ,RjbE ,Rb&j",
+"E V,RHj s,VRH Rb,d Rb-d RD,d c-gR ,Rdb. -Rb8d ,RDd. c-Rg8 ,RdbM -RbdM ,RVd ",
+"gRV- ,Rdbj -Rjbd Vd,Rj V-gsR ,2Rb ,Rb&2 ,2RD ,Rc2 Rb,5 ,R5b8 R5,D ,Rc5 ,RbM",
+"2 ,RbM&2 ,RV2 cRV,2 ,R5bM Rb5,8M ,RV5 s,VR5 Rb,; Rb-; RD,; -Rc; b5R* >R-U ,",
+"R5D; ->cR ,R;bM -RbM; ,RV; V;-R ,R;bj >M-Rb V5*,R -RV> ,RbE2 R&E,U2 ,RHb2 c",
+"RH,2 ,R5bE ,REU5& ,RHb5 cR5,H RbE,M2 bER2,M& V,RH2 V,HcR2 ,REb5M ,ER5b8M V5",
+",RH s,HcR5 ,Rdb; -Rbd; ,RHb; c-Rg; ,R5bd ->Rbd ,R5Dd c>Rg- Rbd,M; Rbd-M; Vd",
+",R; V-gR; Rb5,dM -Rb>Md V5d,R V->gR ,UP U&,P RD,P ,RcP ,.UP U8,P ,RDP. cR8,",
+"P Sb, ,US& SV, Sc, ,USj ,US8 SjV, s,Sc bPR* -UP ,RDP* -RcP ,UP*. U8-P P*.,R",
+"D c-R8P Sb* S-b V*Sb Sc- b*Sj -US8 SV*,j s-Sc Rb,W ,RWU& RW,D ,RcW ,RWb. ,R",
+"Wb8 ,RWD. cRW,8 ,USW SbW,& ZbS, S,Zc SbW,j Sb8,W SZb,j Ss,Zc bWR* Rb-W ,RWD",
+"d -RcW ,UdP. -RWb8 dP.,RD c-RW8 ,USd -USd ZbS* Z-Sc Sbd,j S-bW8 SZb*j gScs-",
+" Rb,m ,RmU& RD,m ,Rcm U5,P ,R8bm ,R5Dm cR5,m ,USm Sbm,& VmS, cmS, pbS, Spb,",
+"8 S,Vp S,cp bmR* Rb-m ,RDm* -Rcm ,U5;P -U>P R5D,;P c>R-m ,US; -US; V;S, S;V",
+"- pbS* Sb-p Vp*Sb cpS- ,RWbm RW&,Um ,RHbm cRW,m ,R5bW Rb5,W8 ,R5WD cR5,W Sb",
+"W,m ,UWS&m SZb,m ScZ,m Spb,W S8WpU, Vp,SZ ScpZ, ,Rvb vR-U ,RvD cR-v vRb,5 -",
+"vR>b vRD,5 cvR-> vbS* Sb-v S,Vv cvS- Svbp* -pUSv Vv,Sp Scy- Rk) k)R! k)RB R",
+")ak R1) R)8k 1)RB R)1a kMR) RkM!) R)Tk ak)RT lR) R8l) RTl) l)sR R*k +kR* Rk",
+"*B akR* R1* 1+R* *BR1 1aR* RkM* k*MR+ TkR* ak*RT l*R R+l* RTl* sRl* kER) Rk",
+"E!) R)Hk ak)RH 1ER) R18E) R)1H R1H8) RkME) kMER)! RHTk) RHTak) REl) lR8E) R",
+"Hl) lsRH) dkR* dk*R+ HkR* R*gk 1dR* R1+d* 1HR* R1g* dkMR* R+dk*M RH*Tk gRTk",
+"* Rdl* l+Rd* RHl* gRl* k)R2 Rk)!2 Rk)2B ak)R2 R)5k R158) R15)B R1a5) RkM)2 ",
+"kM)R2! RTk)2 RT)ak2 R5l) lR58) lR5T) lsR5) k;R* k;*R+ k;*RB ak;R* 1;R* R1>*",
+" R1;*B >kRa* k;MR* R+kM;* RT;k* RT;ak* R5l* >Rl* l;RT* l>sR* RkE)2 kE)R2! R",
+"Hk)2 RH)ak2 R15E) 5kER8) R1H5) ak)RH5 kMER)2 !ER)kM2 Hk)RT2 akHMR)2 lR5E) R",
+"58lE) lHR5) sR5lH) dk;R* R+dk;* RH;k* gRk;* R1d5* >kRd* R1H5* >kgR* RdkM;* ",
+"dkR;+M* Hk;RT* RT;gk* ldR5* l>Rd* lH;R* gl>R* kP) k!P) P)kB a)kP R)1P 8)kP ",
+"kP)1B akP1) Sk) k)S! TkS) akS) Sl) l)S8 STl) l)Ss kP* k*+P *BkP kPa* 1PR* k",
+"P8* kP*1B akP1* S*k +kS* TkS* akS* l*S S+l* lTS* l*Ss R)Wk kP)W! H)kP akPH)",
+" R)1W R1W8) R1HW) R1Wa) WkS) S!Wk) S)Zk SZak) SWl) Sl8W) l)SZ SslZ) WkR* dk",
+"P+* kPH* kPg* 1WR* dkP8* kP*1H gR1W* WkS* S+Wk* ZkS* S*gk Sdl* S8dl* SZl* l",
+"*gS R)km km)R! km)RB akmR) R)1m R1m8) R1m)B akP5) kmS) S!km) STkm) Sakm) l)",
+"Sp Slp8) SlpT) Sslp) kmR* km*R+ km*RB akmR* 1mR* kP>* kP*5B >kPa* kmS* S+km",
+"* S;Tk* Sa;k* Spl* l*S> Sp*lT Ss*l> km)RW RW)km! RHmk) ak)RHm R1W5) km)RW8 ",
+"R1Hm) ak)R5W SWkm) km)S!W SZkm) ZkmSa) SlpW) lWpS8) SZpl) lZpSs) R*vk vR+k*",
+" vRHk* gvRk* R1v* >kvR* vR1H* >kgP* vkS* Sv+k* SZ*vk gSvk* l*Sv lv>S* lvZS*",
+" l*yS ,R9 R&,k RB,k R9,a ,R1 :R, RB,1 ,R:a R9,M ,R9M& R9,T ,RT9a l,R :Rl, ,",
+"RlT sRl, R9* -R9 *BR9 R9-a R*,1 :-R ,R1*B :a-R 9MR* R9-M 9TR* R9-T ,Rl* l-R",
+" l*R,T sRl- ,ER9 k&E,R R9,H ,RH9a ,ER1 ,R:E R1,H ,R:H ,R9ME ,R9M&E ,RH9T R9",
+"H,aM ,RlE :R,lE ,RlH :RHl, R9,d R9-d 9HR* -Rg9 R1,d -R:d ,R1H* :-gR ,Rd9M -",
+"R9dM ,RT9d -RTg9 ,Rld -Rld lH*,R gRl- ,2R9 k&2,R ,R92B ,Ra92 R9,5 ,R:5 ,R15",
+"B :R5,a ,R9M2 ,R9M&2 ,RT92 ak2,RT ,Rl5 :R5l, l,R5T ls,R5 R9,; R9-; ,R;9B -R",
+"9a; R1,; ->:R ,R1;B :-R>a ,R;9M -R9M; ,RT9; -RT9; ,Rl; -Rl> l;,RT s-Rl> ,R9",
+"E2 ,REk&2 ,RH92 ak2,RH ,R15E :R5,E ,R1H5 :RH,5 R9E,M2 k&,MRE2 ,R29HM ,2RH9a",
+"M l,R5E l,5:RE lH,R5 s,5:RH ,Rd9; -R9d; ,RH9; g-R9; ,R15d :-R>d ,R1H; g:R->",
+" R9d,M; R9d-M; R9H,T; -R;g9M ld,R5 l->Rd lH;,R gl->R ,kP k&,P ,BkP ak,P R1,",
+"P ,R:P ,R1PB :Ra,P S9, ,kS& ,TS9 ,aS9 l,S S:, lTS, l,Ss 9PR* -kP kP*,B ak-P",
+" kP*,1 -R:P k*B,1P :-RaP S9* S-9 9TS* -TS9 S9l* l-S S9*lT s-S: R9,W kP&,W H",
+"k,P akP,H R1,W ,R:W ,R1HP :RH,W ,WS9 S9W,& Z9S, SZ9,a S,lW :WS, SZl, S,Z: 9",
+"WR* R9-W dkP,H -kgP dkP,1 -R:W ,1HdkP g:R-W ,dS9 -WS9 Z9S* g9S- Sdl, lWS- l",
+"Z*S9 gSl- R9,m km&,R ,Rm9B akm,R R1,m ,R:m ,R1mB :Rm,a ,kSm S9m,& S9T,m S9a",
+",m Spl, S,:p Sp9,T Ss,:p 9mR* R9-m k;P,B -Rm9a k;P,1 -R:m k;B,1P :-Ram ,kS;",
+" -kS; S9;,T S-9Tm S;l, S>l- Sp9T* l-pSs ,RW9m ,RWkm& ,RH9m ,RHakm ,R15W :RW",
+",5 ,R1Hm :RH,m S9W,m km&S,W SZ9,m SamZk, Sp9,W S:p,W lZ,Sp S:Zp, ,Rv9 vR-k ",
+"vR9,H -vRg9 ,Rv1 :R-v vR1,H :vRg- v9S* S9-v Sv9Z* gS-v9 l,Sv S-lv lv,SZ l-y",
+"S UkR) RUk!) R)Dk ak)RD R)1U R1U8) R)1D R1D8) RUkM) U!kRM) RkV) VRak) RUl) ",
+"lRU8) VRl) lsVR) RUk* R+Uk* DkR* ak*RD 1UR* R1+U* 1DR* R1+D* k*MRU R+Uk*M R",
+"*Vk V+Rk* R*lU l+RU* lRV* s*VlR RUkE) U!kRE) RHUk) RHUak) R1UE) 1UER8) R1HU",
+") R1)UH8 UkMRE) !ER)UkM VRHk) ak)VRH lRUE) R8UlE) VlRH) Vs)lHR dk*RU R+Udk*",
+" RH*Dk gRUk* R1dU* 1UdR8* R1HU* gR1U* RdUk*M dkR*U+M VdRk* gVRk* ldRU* R8dl",
+"*U lH*VR glVR* RUk)2 U!kR)2 RDk)2 RD)ak2 R1U5) 1U5R8) R1D5) ak)R5D UkMR)2 !",
+")k2RUM V2Rk) ak)V2R lRU5) R5Ul8) VlR5) V5Rls) k;*RU R+Uk;* RD;k* RD;ak* R1;",
+"U* >kRU* R1D5* >kDR* R;Uk*M k;R*U+M V;Rk* ak;V*R l;RU* l>RU* l;VR* V>lR* Uk",
+"ER)2 !ER)Uk2 Hk)RD2 R)UHak2 1UER5) RE1U58) R1)UH5 R)1HU5a E)R2UkM U!RME)k2 ",
+"RHkV2) akV2RH) R5UlE) RUlE58) V5RlH) lRV5sH) RdUk;* dkR;U+* Hk;RD* RD;gk* 1",
+"UdR5* R1d>U* 1UHR5* >D*gR1 dkR;U*M U+R*k;dM RH;V*k gRkV;* R5dl*U >RUld* lHR",
+"V5* glRV>* U)kP kP)U! D)kP akPU) 1)UP 1UP8) R1DP) 1UaP) UkS) S!Uk) VkS) SVa",
+"k) SUl) SlU8) l)SV SlVs) kPU* kP*U+ kPD* akPU* UP1* kP*U8 kP*1D aP*1U U*Sk ",
+"S+Uk* SkV* SV+k* lUS* S8*lU SVl* Ss*Vl kP)UW UW)kP! RWDk) ak)RWD R1WU) kP)U",
+"W8 R1WD) aP)1UH SUWk) UWkS!) SZVk) ZkVSa) SlUW) lWUS8) SlVZ) lZVSs) dkPU* U",
+"+WkP* dkPD* gUPk* R1WU* 1U+RW* R1WD* g1UP* SdkU* U+WS*k SZ*Vk gSVk* lW*SU S",
+"+UlW* lZ*SV glSV* km)UP Um)kP! RDmk) ak)RDm R1mU) km)U8P R1Dm) ak)U5P SUkm)",
+" km)S!U SVkm) VmkSa) SlpU) pUlS8) SlVp) VplSs) km*UP U+mkP* km*RD R+Dkm* kP",
+"*U5 >kPU* kP*5D >kDP* S;Uk* km*S+U SV;k* S+kVm* Sp*lU S>lU* Vp*Sl S>Vl* RWU",
+"km) k!m)RWU km)RWD akRmUH) kP)U5W R)1WU8m kP)UH5 1HRmU8) km)SUW WmS)U!k Zkm",
+"SV) akVmSZ) lWUSp) SplWU8) lZSVp) SlVpsZ) vRUk* kP*vU+ vRDk* gR*vDk vR1U* >",
+"P*v1U vR1D* >D*vR1 SvUk* vU+S*k VvSk* gSkVv* lvSU* S>Ulv* lvVS* ylVS* tR, ,",
+"Rt& ,RtD t,cR ,Rt1 t,:R R1,D :,cR ,RtM tRM,& tRV, tcV,R tRl, t:Rl, lRV, uR,",
+" t*R t-R RDt* cRt- R1t* :Rt- t*R1D c-:R R*tM tR-M tRV* -RVt lRt* -Rlt t*VlR",
+" u-R ,RtE tR&,E ,RtH tcR,H tR1,E t:R,E tHR,1 t:H,R tRM,E M&EtR, tHV,R cRVtH",
+", ltR,E lt,:RE ltH,R ,RuH ,Rtd -Rtd RHt* gRt- tdR,1 t:d-R tH*R1 g:Rt- tdR,M",
+" t-RdM tH*VR V-gtR ltd,R l-tRd tH*lR g-uR ,Rt2 tR&,2 tRD,2 tcR,2 ,Rt5 t:R,5",
+" t5R,D tc5,R tRM,2 M&2tR, VtR,2 Vt,cR2 t5Rl, lt5:R, t5V,R ,Ru5 ,Rt; -Rt; t;",
+"R,D tc;-R R5t* -Rt> t5*RD c>Rt- t;R,M t-RM; t;V,R V-tR; t5*lR l-t>R t5VR* -",
+">uR tR,E2 ,R&tE2 tHR,2 cR,tH2 t5R,E :R,t5E tH5,R tH,cR5 ,RMtE2 M&tE,R2 V,Rt",
+"H2 V2tc,RH l,Rt5E lRt5:,E tHRV5, uRH,5 tdR,; t-Rd; tH;,R gt-R; t5d,R t>-Rd ",
+"tH5R* gt>-R ,Rdt;M -Rdt;M tHRV;, gtRV-; t5Rld, t>Rl-d tHRl;, u->gR tP, ,Pt&",
+" ,DtP t,cP ,1tP t,:P tP1,D t:Pc, St, t&S, VtS, S,tc l,St S,t: SVl, uS, tP* ",
+"t-P DPt* c-tP 1Pt* :-tP tP*1D t-P:c St* S-t t*SV StV- l*St Stl- St*Vl u-S ,",
+"RtW tWR,& ,HtP tcW,R tWR,1 t:W,R tHP,1 t:H,P S,tW StW,& S,tZ ScZt, Stl,W S:",
+"t,W lZ,St SZu, ,dtP -RtW HPt* gPt- tW*R1 t-W:R tHP1* gtP:- tWS* Sdt- S*tZ S",
+"-gt Stdl* l-StW tZ*Sl gSu- ,Rtm tmR,& tmR,D tcm,R ,5tP t:m,R t5P,D tc5,P tm",
+"S, Stm,& SV,tm Sct,m S,tp S:pt, Vp,St Spu, ,;tP -Rtm tm*RD t-mcR 5Pt* >Pt- ",
+"t5PD* t>Pc- tmS* S;t- St;V* V-mSt S*tp tpS- tp*SV S-up tWR,m ,RWtm& tHm,R t",
+"H,cRm t5W,R t5,:RW tH5,P tH,:Rm StW,m tWmS&, tZS,m tZmSc, tpS,W tpWS:, tZpS",
+", uZ,Sp vRt* tP-v tvR,H cvRt- tvR,1 :vRt- tH5P* :vRc- S*tv tvS- Vv,St V-vSt",
+" lvtS* l-vSt Vv,Sl y-uS X X! XB aX X. 8X X.B 8Xa XK XK! TX TXa Xj 8Xj TXj s",
+"X X( +X X(B +Xa X(. +X8 .BX( +8aX X(K +XK TX( +TX Xj( +Xj T(Xj sX+ GX GX! H",
+"X GaX GX. G8X HX. H8X GXK XKG! GTX TXGa GjX 8XGj HXj sGX dX +GX HXd gX dX. ",
+"8dX H.dX gX8 dXK GK+X TdX gXT dXj Gj+X dXHj gsX X2 X2! X2B aX2 5X 5X8 5XB 5",
+"aX X2K 2KX! TX2 T2aX 5Xj 58Xj 5TX sX5 X; +X; X;B aX; 5X; >X 5BX; >Xa X;K +K",
+"X; TX; T;+X X;j >Xj T;5X >Xs GX2 X2G! HX2 G2aX G5X 5XG8 H5X 5aHX X2GK GX2!K",
+" G2TX aX2GT 5XGj G58Xj 5THX G5sX G;X G;+X HX; gX; 5dX >XG 5dHX >Xg GKX; dXK",
+"+; TXG; TXg; dj5X Gj>X Td5X gs>X XP XP! XPB aXP XP. 8XP P.XB aX8P QX QX! QX",
+"T QaX QXj Q8X XjTP sXQ XP( +XP P(XB aX+P P(X. 8X+P XP(.B aXP+8 QX( +QX Q(TX",
+" Qa+X Q(Xj Q8+X Xj(TP +QsX Y Y! YH Ya Y. Y8 YH. Y8H YQ YQ! YZ YZa Yj Y8Q YZ",
+"j sY Yd Y+ YHd gY Yd. Y+8 HdY. gY8 YQd Y+Q YZd gYZ Yjd Y+j ZdYj sYg Xm Xm! ",
+"XmB aXm 5Xm 8Xm 5BXm aX5P QXm Q!Xm TXm aXTm pX pX8 pXT spX Xm; +Xm XB;P aX+",
+"m X;5P >Xm Xm;5B aX>P QX; QX+m TXQ; TX+m pX; >Xp TXp; sp>X Ym Ym! YHm Yam Y",
+"5 Y58 Y5H Y5a YQm Q!Ym YZm ZaYm Yp Yp8 YpZ sYp Yv Yv+ YvH gYv Yv5 Y> vHY5 Y",
+">g YvQ v+YQ YZv YZgv Ypv Y>p ZpYv yY X# X& X#B aX& X#. 8X& .BX# 8aX& X#K X&",
+"K TX# TX& Xj# X&j T#Xj sX& X#( +X& #BX( +aX& #(X. +8X& X#(.B aX&+8 #(XK +KX",
+"& X#T( T&+X j#X( X&+j Xj#T( +Xs& GX# G&X HX# HX& X#G. 8XG& X#H. 8XH& X#GK G",
+"KX& G#TX TXG& G#Xj X&Gj H#Xj G&sX dX# dX& H#dX gX& X#d. d&8X dX#H. 8Xg& X#d",
+"K dKX& T#dX TXg& d#Xj X&dj dXjH# g&sX X#2 X&2 2BX# X2a& 5X# 5X& X#5B aX5& 2",
+"KX# &2XK X#T2 T2X& 5#Xj Xj5& 5#TX 5Xs& X;# X;& ;#XB X&a; 5#X; >X& X;#5B aX>",
+"& ;#XK XK;& T#X; X;T& X#;j X&>j X;jT# >&sX X#G2 G2X& X#H2 H2X& G#5X 5XG& H#",
+"5X 5XH& GX#2K X&2GK GTX#2 GT&X2 Xj#G5 X&jG5 G5TX# sX5G& G#X; X;G& H#X; X;g&",
+" 5#dX G&>X H5Xd# >&gX dX#;K dX&;K GT;X# gXT;& dXj5# >XG&j X;jH# >Xgs& XP# X",
+"&P P#XB X&aP P#X. X&8P XP#.B aXP8& QX# QX& Q#TX TXQ& Q#Xj 8XQ& Xj#TP QXs& P",
+"#X( X&+P XP#(B aXP+& XP#(. X&P+8 P#(X.B +X8aP& X#Q( Q&+X QXT#( +QXT& Xj#Q( ",
+"X&j+Q TX#Pj( sX+Q& Y# Y& YH# Ya& Y#. Y8& H#Y. H8Y& YQ# Y&Q YZ# YZ& Yj# Y&j ",
+"ZjY# sY& Yd# Y+& HdY# gY& d#Y. 8dY& YHd#. g8Y& QdY# +QY& ZdY# Y&gZ djY# +jY",
+"& YZdj# Y&gs Xm# Xm& m#XB X&am 5#Xm Xm5& Xm#5B aXm5& Q#Xm XmQ& T#Xm XmT& pX",
+"# pX& TXp# p&sX X#;P X&+m Xm;#B aXm;& Xm;5# Xm>& 5X#;PB >Xam& Q#X; X;Q& QX;",
+"T# aX;Q& X;p# p&>X pXT;# >Xps& Ym# Y&m HmY# HmY& Y5# Y5& H5Y# H5Y& QmY# Q&Y",
+"m ZmY# YmZ& Yp# Yp& Y#Zp Y&sp Yv# Yv& vHY# Y&gv v5Y# Y>& YvH5# Y&g> vQY# YQ",
+"v& Y#Zv ZvY& Y#pv pvY& YZvp# yY& IX IX! DX DXa IX. 8IX DX. D8X IXK I!XK DXT",
+" aITX IjX Ij8X DXj sIX IX( +IX DX( +DX X(I. 8I+X X(D. D8+X X(IK IX+K D(TX D",
+"X+T I(Xj Ij+X D(Xj +DsX GIX IXG! JX JaX IXG. GI8X JX. J8X IXGK GIX!K JTX TX",
+"Ja GIXj IjXG8 JjX sJX IdX Id+X JdX gJX I.dX Id8X dXJ. J8gX IXdK IdX+K TdJX ",
+"JTgX dXIj Idj+X dXJj gXsJ IX2 I!X2 DX2 I2aX 5IX 8I5X 5DX D85X X2IK IX2!K I2",
+"TX aX2TI Ij5X IjX58 DX5T 5DsX I;X I;+X DX; D;+X I;5X >XI D;5X >XD IKX; I;X+",
+"K TXD; aX;TI X;Ij Ij>X X;Dj sI>X IXG2 GIX!2 JX2 aXJ2 GI5X G58IX J5X 5aJX GI",
+"X2K IX2GK! TXJ2 JTaX2 IjXG5 G58IjX 5TJX J5sX dXI; IdX+; J;X J;gX Id5X Id>X ",
+"5dJX J>X IdX;K +GIX;K TXJ; gJTX; Idj5X >IjdX X;Jj >XsJ IP IP! DXP aIP IP. 8",
+"IP D.IP 8IDP QIX Q!IP QDX DXQa IPj 8IQX DjQX sIP IP( +IP D(IP DX+P P(I. 8I+",
+"P IP(D. +DX8P Q(IP QI+X Q(DX QD+X I(Pj IP+j IPjD( +IsP YI YI! YJ YJa YI. Y8",
+"I YJ. YJ8 YQI QIY! YZJ ZJYa YjI Q8YI YJj sYJ YId Y+I YJd gYJ IdY. +IY8 JdY.",
+" Y8gJ QIYd +QYI YdZJ YZgJ IdYj +IYj YdJj sJgY ImX I!Xm DXm aXDm 5IP 8I5P DX",
+"5P 8XDm ImQX ImXQ! DmQX aXmQD pIX 8IpX pDX pDsX I;P Im+X I;DP DX+m I;5P >PI",
+" I;P5D DX>P I;QX I;P+Q DXQ; aX;QD I;pX pI>X DXp; sI>P YIm ImY! YJm JmYa Y5I",
+" 5IY8 YJ5 J5Y8 QIYm YQIm! JmYZ YZJam YpI pIY8 JpY JpsY YvI vIY+ JvY JvgY vI",
+"Y5 Y>I Y5Jv Y>J YQvI Yv+QI YZJv gYZJv pIYv pIY> JvYp yJY bX bX& bXD cX bX. ",
+"b8X b.DX cX8 bXK bKX& bTX cXT bXj 8Xbj DXbj scX bX( b+X b(DX cX+ X(b. +Xb8 ",
+"bXD(. +Xc8 X(bK bK+X b(TX +TcX b(Xj +Xbj bTXj( s+cX bGX G&bX JbX cJX GXb. G",
+"8bX bXJ. J8cX GXbK I&KGX bTJX JTcX GjbX I&jGX bXJj cJsX bdX +GbX bdJX gcX b",
+".dX 8dbX JbdX. g8cX bKdX dX&bK TdbX gTcX dXbj IdjX& JjbdX scgX bX2 b2X& b2D",
+"X cX2 b5X 5Xb8 5DbX c5X X2bK I&2XK b2TX TXc2 5Xbj I&j5X 5TbX c5sX bX; +Xb; ",
+"DXb; cX; 5Xb; >Xb b5XD; c>X bKX; I;&XK TXb; TXc; X;bj bX>j X;jbT sc>X GXb2 ",
+"I&2GX bXJ2 JXc2 G5bX bG58X b5JX J5cX bGX2K bG2X&K JbTX2 cJTX2 bG5Xj bG5X&j ",
+"J5bTX sJc5X G;bX I;&dX bXJ; c;gX 5dbX bG>X J5bdX gc>X bG;XK IdKX;& J;bTX cJ",
+";TX dXjb5 >XbGj J;jbX J>scX bXP IP& DXbP cXP b.IP 8IbP IP.bD 8IcP bQX Q&bX ",
+"QDbX cQX QXbj Q8bX IPjbT cQsX b(IP +IbP IP(bD +IcP IP(b. IP&+8 DX(bP. cX+8P",
+" b(QX +QbX bQXD( +QcX IPjb( IP&+j Ij(bTP sIPc+ Yb Yb& YJb Yc Yb. Yb8 JbY. Y",
+"c8 YbQ bQY& YZb YcZ Ybj bQY8 ZbYj sYc Ybd Yb+ JbYd Ycg bdY. b+Y8 YJbd. Y8gc",
+" bQYd b+YQ YdZb ZcgY bdYj b+Yj YZbdj gsYc bXm XmI& DXbm cXm 5IbP 8Xbm b5XDm",
+" 5IcP QXbm Im&QX TXbm QXcm pbX b8pX bTpX cpX I;bP +Xbm I;PbD +Xcm I;Pb5 bX>",
+"P 5DXb;P cX>P QXb; I;PQ& I;PbT QXc; bXp; pb>X pbXD; >Xcp Ybm bmY& JmYb Ycm ",
+"Yb5 b5Y8 J5Yb Yc5 bQYm YbQm& YmZb cmYZ Ypb pbY8 YbJp Ycp Yvb vbY+ YbJv Ycv ",
+"vbY5 Y>b YJ5vb Yc> YQvb Yvb+Q ZvYb YZcv pvYb p>Yb JpYvb yYc X0 X0! X0B aX0 ",
+"1X 1X8 1XB 1aX X0K !KX0 TX0 T0aX 1Xj 18Xj 1TX sX1 X0( +X0 0BX( +0aX 1X( 1+X",
+" X(1B +X1a 0(XK X0+K X0T( +0TX 1(Xj +j1X 1(TX 1+sX GX0 X0G! HX0 G0aX 1GX G8",
+"1X 1HX Ga1X X0GK GX0!K G0TX aX0GT Gj1X 1G8Xj GT1X 1GsX dX0 +0dX H0dX gX0 1d",
+"X +G1X HX1d g1X X0dK dX0+K T0dX TXg0 dj1X dXj1+ Td1X sXg1 X02 !0X2 2BX0 X2a",
+"0 1X5 158X 1B5X 5a1X 2KX0 X02!K X0T2 aX0T2 15Xj 1X58j 5T1X 1Xs5 X;0 +0X; ;0",
+"XB a0X; 1X; >X1 1BX; 1a>X ;0XK X;0+K T0X; aX;T0 Xj1; 1X>j TX1; s1>X X0G2 GX",
+"0!2 X0H2 aX0G2 G51X 1G58X H51X 1Ga5X GX02K X02GK! GTX02 GT0aX2 1G5Xj G581Xj",
+" 1GT5X sX1G5 G0X; dX0+; H0X; X;g0 G;1X 1G>X HX1; g1>X dX0;K +G0X;K GT;X0 gX",
+"T;0 dXj1; >X1Gj X;j1H >Xgs1 XP0 X!P0 P0XB XPa0 1XP 8X1P XP1B aX1P QX0 X0Q! ",
+"Q0TX Q0aX 1QX Q81X QX1T 1QsX P0X( XP+0 XP0(B aXP+0 XP1( +X1P 1XP(B 1+XaP X0",
+"Q( +0QX QXT0( +QXT0 1(QX +Q1X 1QXT( sX1+Q Y0 Y0! YH0 Ya0 Y1 Y18 Y1H Y1a YQ0",
+" Q!Y0 YZ0 ZaY0 Y1Q 1QY8 YZ1 sY1 Yd0 Y+0 HdY0 gY0 Y1d Y1+ 1HYd gY1 QdY0 +QY0",
+" ZdY0 g0YZ 1QYd 1+Yj YdZ1 g1sY Xm0 X!m0 m0XB a0Xm 1Xm 8X1m 1BXm aX1m Q0Xm X",
+"m0Q! T0Xm aXmQ0 pX1 1Xp8 1TpX s1pX X0;P +0Xm Xm;0B aXm+0 Xm1; 1X>P 1Xm;B >X",
+"1am Q0X; +QXm0 QX;T0 aX;Q0 1Xp; p1>X pX1T; >Xps1 Ym0 m0Y! HmY0 amY0 Y15 1mY",
+"8 1HY5 1aY5 QmY0 YQm!0 ZmY0 YZam0 Yp1 p1Y8 ZpY1 Y1sp Yv0 v+Y0 vHY0 g0Yv Yv1",
+" Y>1 YHv1 g1Y> vQY0 Yv+Q0 Y0Zv gYZv0 pvY1 p>Y1 ZvY1 yY1 9X 9X& 9XB 9aX 9X1 ",
+":X 1B9X :Xa 9XK 9KX& 9TX TX9a 9Xj :Xj 1T9X s:X 9X( 9+X X(9B +X9a 9(1X :X+ 9",
+"X1(B +X:a X(9K 9K+X 9(TX +T9X 9(Xj +X:j 9TX1( s+:X 9GX G&9X 9HX Ga9X 1G9X :",
+"GX 1H9X :HX GX9K X&K9G GT9X 9GTaX Gj9X Gj:X HX9j :GsX 9dX +G9X HX9d g9X 1d9",
+"X :dX 9HX1d g:X 9KdX dX&9K Td9X 9TgX dX9j dX:j dXj9H s:gX 9X2 92X& X29B 92a",
+"X 95X :X5 9B5X 5a:X X29K X&29K 92TX 9TX&2 5X9j 5X:j 5T9X s5:X 9X; +X9; 9BX;",
+" aX9; 1X9; >X: 95X;B :a>X 9KX; X;&9K TX9; aX;9T X;9j >j:X X;j9T s:>X GX92 X",
+"&29G 92HX 9GaX2 G59X G5:X H59X H5:X 9GX2K 9G2X&K 9GTX2 aX29GT 9G5Xj :G5Xj 9",
+"G5TX :HXs5 G;9X dX&9; HX9; 9Xg; 5d9X :G>X 9H5dX >Xg: 9G;XK d&K9X; 9GTX; g9X",
+"T; dXj95 :>GXj X;j9H g:Xs> 9XP X&9P XP9B aX9P 1X9P :XP 9X1PB aX:P 9QX Q&9X ",
+"QX9T Qa9X 1Q9X :QX 9QX1T :QsX XP9( +X9P 9XP(B 9+XaP 9X1P( +X:P 1X(9PB :X+aP",
+" 9(QX +Q9X 9QXT( 9+QTX 9QX1( +Q:X Xj(9TP :QXs+ Y9 Y9& Y9H Y9a Y91 Y: 9HY1 Y",
+":H Y9Q 9QY& YZ9 Z9Ya Y9j Y:Q Z9Y1 sY: Y9d Y9+ 9HYd gY9 9dY1 Y:+ Y91Hd Y:g 9",
+"QYd 9+YQ YdZ9 YZg9 9dYj :QY+ YZ91d gYZ: 9Xm X&9m 9BXm aX9m 1X9m :Xm 95XmB a",
+"X:m QX9m Xm&9Q TX9m aXm9Q p9X :pX 9TpX sX:p Xm9; +X9m 9Xm;B aXm9+ 95X;P :X>",
+"P X;B95P :Xm>a QX9; X;&9Q 9QXT; aX;9Q 9Xp; >X:p p9XT; :pXs> Y9m 9mY& 9HYm 9",
+"aYm Y95 Y:5 9HY5 :HY5 9QYm Y9Qm& YmZ9 YZ9am Yp9 Y:p ZpY9 YpZ: Yv9 v9Y+ YHv9",
+" Yvg9 v9Y1 Y:v Yv91H gY:v YQv9 Yv9+Q ZvY9 gY9Zv pvY9 Yp:v Yp9Zv yY: IX0 I!X",
+"0 DX0 D0aX 1IX 8I1X 1DX D81X X0IK IX0!K D0TX aX0TI Ij1X IjX18 DX1T 1DsX X0I",
+"( IX+0 X0D( +0DX IX1( +I1X 1(DX +D1X IX0(K +IX0K DXT0( +DXT0 IjX1( 1+IXj 1D",
+"XT( sI1+X IXG0 GIX!0 JX0 aXJ0 GI1X 1G8IX J1X 1aJX GIX0K IX0GK! TXJ0 JTaX0 I",
+"jX1G 1G8IjX 1TJX J1sX I0dX IdX+0 dXJ0 JXg0 Id1X 1+GIX 1dJX J1gX IdX0K +I0dX",
+"K JTdX0 gJTX0 Idj1X 1+IdXj J1TdX sJg1X X0I2 IX0!2 X0D2 aX0I2 5I1X 1I58X 5D1",
+"X 1DX5a IX02K X02IK! DXT02 TI0aX2 IjX15 5I81Xj 1DX5T sI15X I0X; I;X+0 D0X; ",
+"aX;D0 I;1X 1I>X DX1; 1D>X I;X0K +I0X;K DX;T0 aX0TI; I;j1X >I1Xj X;j1D >Xs1D",
+" GIX02 IX0G2! X0J2 JaX02 1G5IX G581IX 1XJ5 J158X IX0G2K I!X2G0K JTX02 aX0JT",
+"2 1G5IjX Ij1XG58 J15TX sJ15X IdX;0 +GIX;0 X;J0 gJX;0 1G;IX >I1dX 1XJ; J1>X ",
+"dX0I;K Id+X;0K J;TX0 gXTJ;0 1IdX;j Idj>X1 J1;TX J>s1X IP0 I!P0 D0IP a0IP 1I",
+"P 8I1P DX1P aI1P Q0IP IP0Q! Q0DX QDXa0 QI1X IPj18 QD1X 1IsP P0I( +0IP IP0D(",
+" +DXP0 1(IP +I1P 1DXP( 1+DIP IP0Q( +QIX0 QDX0( +QDX0 IPj1( IPj1+ 1QDX( sIP1",
+"+ YI0 I0Y! YJ0 JaY0 Y1I 1IY8 YJ1 J1Y8 QIY0 YQI!0 Y0ZJ YZJa0 1QYI Y1Q8I ZJY1",
+" Y1sJ IdY0 +IY0 JdY0 g0YJ 1IYd 1+YI YdJ1 YJg1 YQId0 Y+QI0 YZJd0 gYZJ0 Y1QId",
+" Y1+QI YZ1Jd gY1sJ I0Xm ImX!0 D0Xm aXmD0 5I1P 1Im8X DX1m aXm1D ImXQ0 QI0Xm!",
+" QDXm0 aX0TIm 1IpX pI81X 1DpX sIPp1 I0;P I;P+0 I;PD0 a;PI0 I;1P 1I>P I;P1D ",
+">XD1m I;PQ0 Im0+QX I;PT0 aX0QD; pI1X; >Xp1I pDX1; sIP>1 ImY0 YIm!0 Y0Jm YJa",
+"m0 1IY5 Y158I J1Y5 YJ15a YQIm0 Im0YQ! YZJm0 ZJmYa0 pIY1 Yp18I Y1Jp JpsY1 Y0",
+"vI Yv+I0 Y0Jv gYJv0 vIY1 >IY1 Y1Jv Y1J> YvQI0 vIQY+0 YZvJ0 JvZgY0 Yv1pI Y>p",
+"1I JpYv1 YJy1 bX9 I&9X 9DX cX9 b1X :IX 1DbX :cX bK9X I&K9X 9TbX 9TcX 9Xbj b",
+"X:j 1TbX :csX b(9X 9+bX 9(DX 9+cX b(1X b+:X b1XD( :+cX bX9(K b+X9K bTX9( cX",
+"9+T b1Xj( :I+Xj b1TX( :cXs+ 9GbX bG9X& J9X J9cX 1GbX bG:X b1JX :JX bG9XK bG",
+"9X&K 9TJX cJ9TX b1GXj :GbXj 9XJj sX:J 9dbX dX&9I 9dJX cXg9 1dbX bd:X J91dX ",
+"gX:J bdX9K IdK9+X J9TdX gJ9TX Idj9X :IdXj J9jdX g:XsJ b29X I&29X 92DX 9Xc2 ",
+"95bX b5:X 5D9X c5:X bX92K 9I2X&K bTX92 cX9T2 b1X5j :I5Xj b1T5X :cXs5 9Xb; I",
+";&9X DX9; 9Xc; 1Xb; :I>X b1XD; :c>X bX;9K I;K9+X bTX9; cX;9T I;j9X :>IXj X;",
+"j9D c>Xs: bG9X2 bG9X&2 9XJ2 cJ9X2 b1G5X :Gb5X 95JX J5:X 9G2bXK bK9GX&2 J9TX",
+"2 J9TcX2 9G5bXj bG5:Xj J95TX :Js5X bG;9X 9+GbX; 9XJ; cJ;9X b1GX; :>GbX J95d",
+"X >X:J IdK9X; X;G&9IK J9;TX cXTJ9; b1GX;j >Ij:dX J9;Xj :J>sX 9IP I&9P DX9P ",
+"9IcP 1IbP :IP b1XDP cX:P 9QbX IP&9Q QD9X 9QcX 1QbX bQ:X IPj9D :IsP 9(IP +I9",
+"P 9DXP( cX9+P b1XP( +I:P b1DIP( :cX+P bQX9( b+Q9X 9QDX( cQX9+ IPj9( :QI+X I",
+"P(b1T sIP:+ Yb9 9IY& YJ9 Yc9 Yb1 Y:b J9Y1 Y:J bQY9 Yb9Q& ZJY9 Y9Zc b1Yj :QY",
+"b ZbY1 Z:Yc bdY9 b+Y9 YdJ9 g9Yc b1Yd :IY+ YJ91d gY:J Yb9Qd Yb+9Q YZb9d gY9Z",
+"c Yb1Qd Y:b+Q YZb1d sY:gJ 9Xbm Im&9X DX9m 9Xcm 1Xbm bX:m b1XDm cX:m bQX9m 9",
+"QIXm& bTX9m cQX9m b1pX pb:X 9DpX :Xcp I;9P I;P9+ I;P9D cXm9+ I;Pb1 :I>P 95D",
+"I;P c>X:m I;P9Q 9+QI;P I;P9T cQX9; pbX9; :pI>X p9DX; cpX:> bmY9 Yb9m& JmY9 ",
+"cmY9 b1Y5 :IY5 J9Y5 Y5:J Yb9Qm Im&Y9Q YZb9m YcZ9m pbY9 Yb:p Y9Jp cpY: vbY9 ",
+"Yvb9+ Y9Jv Y9cv vbY1 Yb:v Jv9Y1 :JY> Yvb9Q Y9QvI& Jv9YZ YcvZ9 Ypbv9 :vIYp J",
+"p9Yv Y:yJ RX RX! RXB RaX RX. R8X X.RB 8XRa XM XM! RTX aXM RjX 8XM TXRj sRX ",
+"RX( R+X X(RB +XRa X(R. +XR8 RX(.B R+8aX XM( +XM R(TX +XRT R(Xj +XRj XM(Tj R",
+"+sX RG RG! RGH RGa RG. RG8 R.HX G8RH RGM R!GM RGT GTRa RGj G8Rj GTRj sRG RG",
+"d R+G HXRd gRG R.dX +GR8 dX.RH RGg8 dXM +MRG GTRd gXM GjRd +GRj dXMHj sRgX ",
+"RX2 X2R! X2RB R2aX R5X 5XR8 RB5X 5XRa XM2 M!X2 R2TX X2aM 5XM 8X5M 5XRT R5sX",
+" R;X +XR; RBX; aXR; 5XR; >XR X;BR5 Ra>X XM; X;+M TXR; XMa; X;Rj >XM XM;5T s",
+"R>X RG2 G2R! R2HX R2Ga RG5 G5R8 G5RH G5Ra R2GM XM2G! R2GT aXMG2 G5Rj RG58M ",
+"G5RT RGs5 RG; +GR; G;RH RGg; G5Rd >RG RG5H; gR>X GMR; dXM+; GTR; XMg; G;Rj ",
+"RG>M dXMH5 gX>M RXP XPR! XPRB RXaP XPR. RX8P RXP.B aXPR8 SX S!X STX SaX SXj",
+" S8X TXSj SsX XPR( RX+P RXP(B aXPR+ RXP(. R+8XP XP(R.B R+8aXP SX( S+X TXS( ",
+"+TSX XjS( +XS8 STXj( S+sX YR YR! YRH YaR YR. Y8R RHY. RHY8 SY SY! SZY SYa S",
+"Yj SY8 YjSZ sYS YRd Y+R RHYd gYR RdY. R+Y8 YRHd. Y8gR SYd SY+ YZSd gSY YjSd",
+" Y+S8 SZYdj sYgS RmX R!Xm RBXm aXRm 5XRm 8XRm XmBR5 aXmR5 SXm XmS! TXSm aXS",
+"m SpX pXS8 STpX sXSp XmR; +XRm Xm;RB aXmR+ Xm;R5 Rm>X R5X;PB >XRam S;X +XS;",
+" TXS; aXS; pXS; S>X SpTX; >XSs YRm RmY! RHYm RaYm Y5R R5Y8 RHY5 R5Ya SYm Ym",
+"S! SmYZ SmYa YpS S8Yp SZYp YpSs YvR vRY+ YHvR YvgR vRY5 Y>R YvRH5 gRY> SvY ",
+"YvS+ YZSv SvgY YpSv S>Y SZpYv yYS RX# R&X X#RB aXR& X#R. 8XR& RX#.B aX&R8 X",
+"M# XM& R#TX TXR& R#Xj X&Rj XM#Tj R&sX X#R( +XR& RX#(B aX&R+ RX#(. R+8X& X#(",
+"R.B R+8aX& M#X( X&+M XM#T( aXM+& XM#j( XM&+j RT#Xj( sX+R& RG# RG& R#HX GaR&",
+" G#R. G8R& RGH#. RG8H& R#GM GMR& R#GT GTR& R#Gj G&Rj RGTj# RGs& R#dX +GR& d",
+"X#RH RGg& dX#R. dX&R8 RH#dX. gRG8& d#XM XMd& dXMH# XMg& dXMj# dXM&j dX#RHj ",
+"gsRG& X#R2 R2X& RX#2B aX&R2 R#5X 5XR& R5X#B R5aX& M#X2 X2M& XM#T2 aXM&2 5#X",
+"M XM5& R5TX# sX5R& R#X; X;R& X;#RB aX;R& X;#R5 R&>X R5#X;B >XRa& X#M; M;X& ",
+"XM;T# aXM;& XM;5# XM>& X;#R5T >XsR& G#R2 R2G& RGH#2 RGa&2 R#G5 G5R& RG5H# R",
+"G5H& XM#G2 XM&G2 RGT#2 XM&H2 RG5M# XM&G5 RG5T# sRG5& R#G; G;R& RG;H# gRG;& ",
+"RG5d# RG>& dX#RH5 >XgR& dXM;# dXM;& XM;H# gXM;& dXM5# >XMG& dX#R5T >XgM& XP",
+"R# RXP& RXP#B aXPR& RXP#. X&PR8 XP#R.B R8aX&P SX# S&X TXS# TXS& XjS# 8XS& S",
+"TXj# S&sX RXP#( X&PR+ XP#R(B R+aX&P XP#R(. R+8X&P .BR(XP# aXR&+P8 X#S( +XS&",
+" STX#( S+TX& SXj#( S+8X& Xj#ST( Ss+X& YR# Y&R RHY# RHY& R#Y. R8Y& YRH#. Y8R",
+"H& SY# SY& S#YZ YZS& S#Yj Y8S& SZYj# S&sY RdY# R+Y& YRHd# Y&gR YRd#. Y+R8& ",
+"RHdY#. gYR8& YdS# Y+S& SZYd# S&gY SYdj# SY+&j YZjSd# gSsY& R#Xm XmR& Xm#RB ",
+"aXmR& Xm#R5 Xm&R5 R5#XmB R5aXm& XmS# XmS& STXm# SaXm& S#pX pXS& SpTX# Sp&sX",
+" Xm;R# Xm&R+ Rm#X;B RamX;& R5X;P# >XRm& 5#XmR;B aXm>R& X;S# X;S& S;TX# Sa;X",
+"& SpX;# S&>X pXTS;# S>sX& RmY# RmY& YRHm# YaRm& R5Y# R5Y& Y5RH# Y5aR& YmS# ",
+"SmY& SZYm# SZ&Ym S#Yp S&Yp SZpY# Yp&Ss Y#vR vRY& YvRH# gYvR& YvR5# >RY& vRH",
+"Y5# Y>gR& S#Yv YvS& YZvS# Sv&gY SvpY# S&Y> YpZSv# SYy& [ [! [D [a [. [8 [D.",
+" [8D [M [!M V[ V[a [j [8M V[j [s [( [+ [D( [+D [(. [+8 D([. +D[8 [M( [+M V[",
+"( V[+ [j( [+j V([j [s+ [G [!G [J [Ja [G. [8G [J. J8[ [GM GM[! VJ[ [aVJ [jG ",
+"G8[j Jj[ [sJ [d [+G [Jd g[ [d. [8d J.[d g[8 [dM +G[M V[d g[V [dj +G[j [dJj ",
+"g[s [2 [!2 [D2 [a2 [5 [58 [5D [5a [M2 M2[! V[2 V2[a [5M 5M[8 V[5 [s5 [; [+;",
+" [;D [a; [5; [> 5D[; [>D [;M +M[; V[; [+V; [;j [>M [5V; V>[ [G2 G2[! [J2 J2",
+"[a [5G G5[8 J5[ [5J8 GM[2 [!GM2 V2[J VJ[a2 G5[j [5G8M V[J5 J5[s [d; +G[; J;",
+"[ g[; [5d [>G [5J; g[> GM[; [+GM; V[J; V;g[ G;[j [d>M [5Vd V>g[ [P [!P [DP ",
+"[aP [P. [8P DP[. D8[P S[ S[! SV[ S[a S[j S[8 [jSV [sS [P( [+P DP[( +D[P P([",
+". +P[8 [DP(. [+D8P S[( S[+ S(V[ V[S+ S([j [+S8 SV[j( S+[s [Y [Y! YJ[ Ya[ [Y",
+". Y8[ Y.[J [JY8 S[Y S![Y ] ]a Yj[ Y8S[ ]j ]s [Yd Y+[ [dYJ g[Y Y.[d [+Y8 YJ[",
+"d. Y8g[ S[d Y+S[ ]d ]g [dYj [+Yj ]jd ]gs [m [m! [mD [am [5m [8m 5D[m 5a[m S",
+"[m S![m V[m [aVm [p [p8 [pV [ps [m; [+m Dm[; +D[m 5P[; [>m [5D;P [a>P S[; [",
+"+S; V[S; [+Vm [p; S>[ V;[p [pV> [Ym Ym[! Jm[ [aJm Y5[ [5Y8 [JY5 [5Ya [mSY S",
+"[Ym! ]m ]am [pY Y8[p ]p ]ps [v [v+ [vJ g[v [v5 Y>[ J5[v Y>g[ [vS S+[v ]v ]g",
+"v [pv [pY> ]pv ]y [b [& [bD [c [b. [8b bD[. [c8 [bM [&M V[b [cV [jb [&j Vb[",
+"j [sc [b( [+b bD[( [c+ b([. b+[8 [bD(. c+[8 bM[( b+[M [bV( V+[c bj[( b+[j V",
+"[bj( [+sc [bG [&G [Jb [cJ bG[. bG[8 [bJ. J8[c bG[M GM[& JbV[ VJ[c bG[j G&[j",
+" Jb[j [csJ [db [d& Jb[d g[c bd[. b8[d [Jbd. [8gc bd[M dM[& Vb[d [cgV bd[j d",
+"&[j Jj[bd gs[c [b2 [&2 bD[2 [c2 [5b [5& b5[D [c5 bM[2 M&[2 [bV2 V2[c b5[j 5",
+"M[& Vb[5 c5[s [;b [;& b;[D [c; b5[; [>b [5bD; [>c bM[; M;[& Vb[; V[c; b;[j ",
+"[&>M V[5b; c>[s bG[2 G&[2 [bJ2 c2[J bG[5 G5[& Jb[5 J5[c [bGM2 [&GM2 VJ[b2 [",
+"cJV2 [5bGM [5&GM J5V[b [sJc5 bG[; G;[& Jb[; c;g[ b5[d >b[d J5[bd c>g[ [dbM;",
+" [d&M; J;V[b g[Vc; [5dbM [>bGM J;[bj J>V[c [bP [&P bP[D [cP bP[. b8[P [bDP.",
+" [8cP S[b S[& V[Sb Sc[ [jSb [8Sb SV[bj [sSc bP[( b+[P [bDP( [+cP [bP(. [+b8",
+"P bPD[(. [c+8P [bS( [+Sb SV[b( S+[c S[bj( S[+b8 V[jSb( [scS+ Yb[ Y&[ [JYb Y",
+"c[ [bY. [8Yb YJ[b. Y8[c SYb YbS& ]b ]c YjSb YbS8 ]jb ]sc [dYb [+Yb YJ[bd Yc",
+"g[ Yb[d. Yb+[8 [JdYb. g[Yc8 YbSd YbS+ ]bd ]gc S[dbj S[8bd bd]j gs]c [mb [m&",
+" bm[D [cm b5[m b8[m [5bDm [5cm [mSb [mS& Vb[m cmS[ [pb [p& pbV[ cp[ bm[; b+",
+"[m [mbD; [+cm [5b;P [&>P b5P[;D >P[c [;Sb [;S& SV;[b S;[c [;pb Sb[> [pVb; [",
+">Sc [mYb [mY& Jb[m Jm[c [5Yb [5Y& YJ5[b Y5[c SmYb S[&Ym ]bm ]cm SbYp Y&[p ]",
+"pb ]pc [vb [v& vb[J cv[ [5vb Yb[> [vJb5 [>Yc Sb[v S&[v ]vb ]cv pb[v SbY> pv",
+"]b ]yc kX kX! kXB akX R1X 8kX RB1X 1XRa kXM M!kX TkX akTX lX lX8 lXT lsX kX",
+"( +kX X(kB ak+X R(1X 1XR+ kX(1B akX1+ k(XM kX+M T(kX Tk+X lX( l+X TXl( sXl+",
+" RGk R!Gk HkX GkRa R1G 1GR8 1GRH 1GRa kXGM kXMG! GkRT akXGT lGR RGl8 lHX sR",
+"lG dkX +kRG dkHX gkX 1GRd 1+RG dkX1H R1gX kXdM dkX+M dkTX TkgX ldX R+lG HXl",
+"d glX kX2 X!k2 X2kB k2aX 5kX 8k5X 5BkX ak5X k2XM kXM!2 T2kX akXT2 lX5 5Xl8 ",
+"5TlX l5sX kX; k;+X kBX; kXa; 1XR; >kX kX;1B ak>X XMk; kX;+M kXT; akXT; lX; ",
+"l>X TXl; >Xls R2Gk kX2G! H2kX akXG2 1GR5 R1G58 5kHX akXG5 kXMG2 Gk2XM! RGTk",
+"2 ak2RGT RGl5 lGR58 H5lX lsGR5 GkR; dkX+; kXH; kXg; 1GR; R1>G dkXH5 gk>X dk",
+"XM; +GkXM; dkXT; gkXT; RGl; lG>X HXl; >Xgl kXP X!kP XPkB kXaP kX1P kX8P kXP",
+"1B akX1P SkX kXS! TkSX akSX lXS S8lX STlX lXSs XPk( kX+P kXP(B akX+P kXP1( ",
+"R1+XP 1X(kPB 1+XakP kXS( +kSX STkX( S+TkX SXl( S+lX SlTX( Ssl+X Yk Yk! YkH ",
+"Yak Y1R Y8k R1YH R1Ya SYk S!Yk YZk YkSa lY lY8 lYZ lYs Ykd Y+k HkYd gYk R1Y",
+"d R1Y+ Y1RHd Y1gR YkSd YkS+ YdZk SYgk lYd lY+ YZld glY kXm X!km kBXm kXam 1",
+"XRm kX8m kXm1B akX1m kXSm kXmS! kXTm SakXm lXp l8pX lTpX splX Xmk; kX+m kXm",
+";B akX+m kXm1; kX>P kXB1;P >kXam kXS; S+kXm S;TkX Sa;kX S;lX lXS> lXpT; l>X",
+"Ss Ykm kmY! HkYm akYm Y5k 5kY8 H5Yk 5aYk SmYk SYkm! YmZk SYakm lYp lpY8 lZY",
+"p lsYp Yvk vkY+ YHvk Yvgk vRY1 Y>k Yv1RH >kgY YkSv SY+vk ZvYk gYkSv lYv lY>",
+" YZlv ylY R9X kX& RB9X 9XRa 9XR1 :RX kXB91 Ra:X 9XM XMk& 9XRT aX9M lX9 l:X ",
+"9TlX s:lX R(9X 9XR+ kX(9B akX9+ kX(91 R+:X 9X(R1B :R+aX 9(XM +X9M R9TX( aXM",
+"9+ 9Xl( :Xl+ lX9T( lsX:+ R9G 9GR& 9GRH 9GRa 9GR1 :RG R9G1H RG:H 9MRG kX&GM ",
+"9GRT aXM9G R9lG :RlG 9HlX :RsG 9GRd 9+RG dkX9H R9gX dkX91 R+:G 9HXR1d :RgX ",
+"dX9M dkXM& dkX9T 9XgM 9dlX :dlX lHX9d lXg: R29X k2X& kX29B akX92 9XR5 R5:X ",
+"R95XB :R5aX 92XM kX&M2 R9TX2 aXM92 95lX l5:X lX95T lsX:5 9XR; X;k& kX;9B ak",
+"X9; kX;95 :R>X k;B95X :>RaX XM9; kX;M& kX;9T aXM9; 9Xl; l:>X lX;9T l>Xs: R2",
+"9G kX&G2 R9GH2 kX&H2 9GR5 RG:5 R9GH5 :RGH5 R9GM2 kX2GM& R9GT2 aX29GM lGR95 ",
+":RGl5 lHX95 :RGs5 9GR; dkX;& kX;9H gR9G; dkX95 >R:G 9G5RH; g:R>X dXM9; kX;d",
+"M& XM;9H g9XM; lG;R9 l>G:R lHX9; glX:> kX9P X&kP kXP9B akX9P kXP91 kX:P 9X1",
+"kPB :RaXP S9X 9XS& 9TSX 9aSX S9lX S:X Sl9TX sXS: kXP9( kX&+P 9X(kPB 9+XakP ",
+"9X1kP( :R+XP kX9P1(B akX:P+ 9XS( 9+SX S9TX( S9+TX Sl9X( :XS+ lXTS9( S:s+X Y",
+"9R Yk& R9YH R9Ya R9Y1 Y:R Y9R1H :RYa SY9 Y9S& YZS9 Y9Sa lY9 lY: Y9lZ S:sY R",
+"9Yd R9Y+ Y9RHd Y9gR Y9R1d :RY+ R9HY1d gRY: Y9Sd Y9S+ SZ9Yd SYg9 Y9ld l+Y: l",
+"YZ9d Y:gl 9XRm Xmk& kXm9B akX9m kXm95 Rm:X kXB95P :RmaX 9XSm S9Xm& S9TXm S9",
+"aXm p9lX lX:p Sp9TX :pXSs kXm9; kXm9+ kXB9;P kX&a;P 95Xk;P :>RXm 1;9PkXB :X",
+"a>kP 9XS; S9+Xm S9;TX S9aX; Sp9X; >XS: S9TlX; S:>sX R9Ym kmY& Y9RHm Y9aRm R",
+"9Y5 :RY5 Y95RH Y:RH5 SmY9 SY9m& SZ9Ym SY9am S9Yp YpS: Yp9lZ lYs:p vRY9 vkY&",
+" Yv9RH gY9vR Yv9R1 >kY: Y9HvR1 :vRgY YvS9 Sv9Y+ Sv9YZ gS9Yv Y9lv Y:lv lYvZ9",
+" lYy: [k [!k [Dk [ak [1 [18 [1D [1a [kM kM[! V[k Vk[a [l [l8 [lV [sl [k( [+",
+"k Dk[( +D[k [1( [1+ 1D[( 1+[a kM[( +k[M [kV( Vk[+ [l( [l+ l(V[ l+[s [Gk Gk[",
+"! Jk[ [aJk [1G 1G[8 J1[ [1J8 Gk[M [!GkM V[Jk JkV[a [lG [8lG lJ[ lJ[s [dk +G",
+"[k [dJk g[k [1d 1+[d [dJ1 g[1 dk[M [+GkM Vk[d V[gk [ld [+lG V[ld gl[ [k2 k2",
+"[! Dk[2 ak[2 [15 5k[8 1D[5 1a[5 kM[2 [!kM2 [kV2 V[ak2 [l5 l5[8 V5[l [5ls [;",
+"k +k[; Dk[; ak[; [1; [>1 1D[; [a>k k;[M [+kM; Vk[; V[+k; [l; [>l V[l; l>[s ",
+"Gk[2 [!Gk2 [kJ2 Jk[a2 1G[5 [1G58 [1J5 J1[5a [GkM2 GkM[!2 JkV[2 V[aJk2 [5lG ",
+"[lG58 J5[l [slJ5 Gk[; [+Gk; [;Jk [;gk 1G[; [d>k [1J; >kg[ [dkM; +Gk[;M Jk;V",
+"[ g[Vk; [5ld lG[> J;[l [>gl [kP kP[! Dk[P ak[P [1P 1P[8 1D[P 1a[P S[k [!Sk ",
+"SkV[ Sk[a [lS S8[l SV[l [lSs kP[( +k[P [DkP( [+DkP 1P[( 1+[P [1DP( [1+DP [k",
+"S( Sk[+ SV[k( SV+[k l(S[ S[l+ SlV[( [slS+ Yk[ [!Yk YJk JkYa Y1[ [1Y8 J1Yk J",
+"8Yk YkS[ S[Yk! ]k ]ak lY[ Y8[l ]l ]ls [dYk [+Yk YdJk YJgk [dY1 [1Y+ YJ1[d Y",
+"1g[ Sk[d S[+Yk ]dk ]gk S[ld Y+[l ]ld ]lg [mk km[! Dk[m ak[m [1m 1m[8 1D[m 1",
+"a[m Sk[m S[km! Vk[m S[akm [pl lp[8 [lVp ls[p km[; +k[m [mDk; [+mDk 1m[; [1>",
+"P [1mD; [>1Dm Sk[; S[+km SV;[k S[ak; l;[p l>[p [plV; V>[Sl [mYk Yk[m! JmYk ",
+"YJkam [1Y5 Y1[8m J5Yk YJ58k S[Ykm YkmS[! ]km ak]m [plY [plY8 ]lp ls]p [vk [",
+"+vk YkJv gk[v [v1 >k[v J1[v g1[v vkS[ [vS+k ]vk gv]k lv[ [>lY ]lv ]yl [t [t",
+"& [tD [ct [t1 [: tD[1 [:c [tM tM[& V[t V[tc [lt [:l V[lt u[ [t( t+[ [Dt( t+",
+"[c t([1 [:+ [t1D( [+:c [Mt( tM[+ t(V[ V[t+ l([t l+[: [lVt( u[+ tG[ [&tG tJ[",
+" [ctJ [1tG [:G [tJ1 :J[ [GtM tG[M& V[tJ tJV[c tG[l lG[: [ltJ uJ[ td[ [+tG [",
+"Jtd g[t [1td [:d td[J1 g[: tM[d t+[GM V[td V[gt td[l ld[: lJ[td ug[ [t2 t2[",
+"& [Dt2 c2[t t5[ [:5 tD[5 t5[c [Mt2 [tM&2 V2[t [cVt2 t5[l [5l: V[t5 u[5 t;[ ",
+"[+t; tD[; t;[c [1t; t>[ t5[D; c>[: tM[; t+[M; V[t; [c;Vt t;[l l>[: [l;Vt u[",
+"> [Gt2 tG[&2 t2[J tJ[c2 [5tG [5:G [Jt5 J5[: tG[M2 [&MtG2 tJV[2 [cVtJ2 tG5[l",
+" [:lG5 lJ[t5 J5u[ [dt; t+[G; [Jt; t;g[ [5td tG[> tJ5[d t>g[ tG;[M tGM[;& tJ",
+";V[ g[tV; [ldt5 [:dl> lJ;[t g[u> tP[ [&tP [DtP tP[c [1tP [:P tP[1D :P[c St[",
+" [tS& V[St [cSt [lSt S:[ SlV[t u[S [Pt( [+tP tP[D( tcP[+ tP[1( [+:P [1DtP( ",
+"[:c+P S([t t+S[ StV[( St+[c Stl[( S+[: [lVSt( S[u+ tY tY& tYJ tYc tY1 tY: Y",
+"1tJ :JtY tYS S&tY ]t ]tc lYt tYS: ]lt ]u tYd tY+ YJtd gtY Y1td t+Y: tYJ1d Y",
+":g[ SdtY S+tY ]td ]gt ldtY l+tY lt]d ]ug tm[ [&tm tD[m tm[c [1tm [:m t5[Dm ",
+":m[c tmS[ S[&tm V[tm [cmSt tp[ [p: V[tp up[ [mt; [+tm tm[D; [cmt+ t5[;P >P[",
+": tmD[1; [:mc> t;S[ St+[m St;V[ Sc;[t t;[p [pt> tp[V; S>u[ tYm Y&tm YJtm tm",
+"Yc tY5 t5Y: YJt5 t5Yc tmSY tYSm& ]tm tc]m tpY Y:tp ]pt ]up tYv t+[v tJ[v tv",
+"g[ t5[v tY> [v1tJ Yct> St[v [v&St ]tv gt]v tYlv tYS> lv]t ]yu Xe Xe! XeB aX",
+"e Xe. 8Xe e.XB aX8e XeK X!eK TXe aXTe Xje Xj8e XjTe sXe X* +Xe X*B aX* X*. ",
+"8X* X.*B aX8* X*K +KX* TX* TX+e X*j X*+j XjT* sX* GXe XeG! HXe aXHe XeG. GX",
+"8e XeH. 8XHe XeGK GXe!K TXHe aXeGT GXej XjeG8 XjHe HXse fX f+X fHX gfX fX. ",
+"f8X HXf. f8gX fXK +XfK fTX fTgX fjX +Xfj HXfj sfX Xe2 X!e2 e2XB X2ae 5Xe 8X",
+"5e Xe5B aX5e e2XK Xe2!K XeT2 aXeT2 Xj5e Xje58 TX5e 5Xse X;e X;+e *BX; X;ae ",
+"5X* >Xe *B5X aX>e XKe; X;e+K X;Te aX;Te Xj5* X*>j TX5* sX>e XeG2 GXe!2 XeH2",
+" aXeG2 GX5e G58Xe 5XHe G5aXe GXe2K Xe2GK! GTXe2 GTXae2 XjeG5 G58Xje G5TXe s",
+"X5He fX; +Xf; HXf; fXg; f5X f>X H5fX gf>X X;fK f+X;K TXf; fTXg; 5Xfj fj>X 5",
+"TfX >Xsf eP eP! ePB aeP eP. 8eP P.eB ae8P QXe Q!eP TeP aXQe ePj 8XQe ejTP s",
+"eP X*P +eP *BeP ae+P X.P* 8e+P X*P.B aX*8P QX* QX+e TXQ* Te+P XjQ* 8XQ* X*j",
+"TP +esP Ye Ye! YHe Yae Ye. Y8e HeY. H8Ye YQe QeY! YZe ZeYa Yje Q8Ye ZeYj sY",
+"e Yf Yf+ YfH gYf Yf. Yf8 fHY. Y8gf YfQ fQY+ ZfY ZfgY Yfj fQY8 YjZf sYf Xme ",
+"X!em XBem Xmae 5eP 8e5P 5BeP ae5P XmQe XmeQ! XmTe aXmQe pXe 8Xpe TXpe pXse ",
+"Xm* Xm+e *BXm Xma* Xm5* >eP Xm*5B ae>P XmQ* Xm*+Q XmT* aXmQ* pX* pX>e TXp* ",
+"se>P Yem emY! HeYm aeYm Y5e 5eY8 H5Ye 5aYe QeYm YQem! YmZe YZaem Ype peY8 Z",
+"eYp seYp Yfv fvY+ YHfv Yfgv Yf5 Y>f YHf5 f>gY fQYv Yfv+Q YvZf gYZfv fpY fpY",
+"> ZfYp yYf ,X ,X& ,XB ,aX ,X. ,8X X.,B 8X,a ,XK ,KX& ,TX TX,a ,Xj 8X,j TX,j",
+" sX, ,X* -X *B,X -Xa ,.X* -X8 X*.,B 8X-a ,KX* -XK T*,X -TX X*,j -Xj X*j,T s",
+"-X ,GX G&,X ,HX Ga,X GX,. G8,X ,.HX H8,X GX,K X&K,G GT,X ,GTaX Gj,X X&j,G H",
+"X,j ,GsX fX, f-X ,HfX g-X ,Xf. -Xf8 fHX,. g8-X ,XfK fK-X ,TfX -TgX ,Xfj -Xf",
+"j fTX,j gXs- ,X2 ,2X& X2,B ,2aX ,5X 5X,8 ,B5X 5a,X X2,K X&2,K ,2TX ,TX&2 5X",
+",j X&j,5 5T,X ,5sX ,X; -X; ,BX; aX-; 5X,; >X- ,5X*B -a>X ,KX; X;-K TX,; TX-",
+"; X;,j -j>X X;j,T >Xs- GX,2 X&2,G ,2HX ,GaX2 G5,X ,G58X H5,X ,G5aX ,GX2K ,G",
+"2X&K ,GTX2 aX2,GT ,G5Xj ,G5X&j ,G5TX sX,G5 ,Xf; f;-X HX,; g;-X ,5fX f->X f5",
+"H,X g->X fX;,K f-X;K fTX,; f-TX; f5X,j f>-Xj f5T,X s-Xf> ,XP eP& ,BeP aX,P ",
+",.eP 8X,P eP.,B aeP,8 ,QX Q&,X QX,T Qa,X QX,j Q8,X ePj,T ,QsX X*,P -XP X*P,",
+"B aX-P X*P,. 8X-P ,X.P*B -X8aP Q*,X -QX ,QXT* Qa-X X*j,Q Q8-X ,TXP*j -QsX Y",
+", Y&e Y,H Ya, Y,. Y8, ,HY. ,HY8 Y,Q ,QY& YZ, ZeY& Yj, ,QY8 Z,Yj sY, Yf, Y- ",
+"fHY, Y-g f,Y. Y-8 YfH,. Y8g- fQY, Y-Q Y,Zf Y-Z fjY, Y-j YZ,fj sY- ,Xm X&,m ",
+",BXm aX,m 5X,m 8X,m ,5XmB aXm,5 QX,m Xm&,Q TX,m aXm,Q pX, ,8pX ,TpX pXs, Xm",
+",; -Xm Xm*,B aX-m Xm*,5 -X>P X;B,5P >X-am QX,; QX-m Xm*,T TX-m ,Xp* -pX pX*",
+",T sX-p Y,m ,mY& ,HYm ,aYm Y5, ,5Y8 ,HY5 ,5Ya ,QYm Y&Q,m YmZ, YZ&,m Yp, peY",
+"& ZpY, s,Yp Yv, Y-v YHv, -vgY f5Y, Y-> Yf5,H g-Y> YQv, -QYv ZvY, YZ-v Y,fp ",
+"Y-p fpZY, yY- IXe I!Xe DXe aXDe XeI. IX8e XeD. 8XDe XeIK IXe!K TXDe aXeTI I",
+"Xej IjX8e XjDe DXse I*X I*+X DX* DX+e I.X* I*8X D.X* 8XD* IKX* I*X+K TXD* a",
+"X*TI X*Ij I*j+X X*Dj DXs* IXGe GIXe! JXe aXJe GIXe. G8IXe XeJ. 8XJe GIXeK I",
+"XeGK! TXJe JTaXe IjXGe G8IXje XjJe JXse fIX +IfX JfX JfgX IXf. 8IfX fXJ. JX",
+"f8 IXfK f+IXK JXfT JfTgX IjfX f8IXj JXfj JfsX XeI2 IXe!2 XeD2 aXeI2 IX5e 5I",
+"8Xe DX5e 5DX8e IXe2K Xe2IK! DXTe2 DXTae2 IjX5e 5I8Xje 5DXTe sI5Xe X;I* I;X+",
+"e X;De aX;De I*5X I*>X DX5* DX>e I;XeK +IXe;K DX;Te DX;+Te I;jX* >IjX* X;jD",
+"e sI*>X GIXe2 IXeG2! XeJ2 JaXe2 G5IXe 5IXG8e 5XJe J58Xe IXeG2K I!X2GeK JTXe",
+"2 aXeJT2 G5IXje 8eGj5IX J5TXe sJ5Xe I;fX f+IX; fXJ; JfXg; 5IfX fI>X JXf5 Jf",
+">X fIX;K I;Xf+K JfTX; fTXgJ; f5IXj f>IXj Jf5TX J>sfX IPe I!eP DeP aeDP I.eP",
+" IP8e D.eP 8eDP IPQe IPeQ! DXQe aePQD ePIj IPj8e ePDj DesP IP* IP+e IPD* De",
+"+P I.P* IP8* IP*D. aP*8I IPQ* IP*+Q DXQ* aX*QD P*Ij IP*+j IP*Dj IPs* YIe Ie",
+"Y! YJe JaYe IeY. 8IYe JeY. YeJ8 QIYe YQIe! ZeYJ YZJae IjYe Y8QIe YeJj YJse ",
+"YfI f+YI YJf YJgf fIY. YIf8 Y.Jf JfY8 YIfQ Yf+QI YJZf gYZJf YIfj Yf8QI JfYj",
+" YJsf emIP ImXe! XmDe aXmDe IP5e 5IP8e De5P aeP5D ImXQe QIXem! QDXem QDXaem",
+" IPpe pI8eP DXpe sIPpe XmI* Im*+X XmD* aXmD* IP5* IP>e IP*5D De>P Im*QX +QI",
+"Xm* Im*TX +QDXm* IPp* >XpI* DXp* sIP>e ImYe YIem! YeJm YJaem 5IYe Y58Ie YeJ",
+"5 YJ58e YQIem ImeYQ! YZJem ZJeYam YIpe Yp8Ie peYJ JpsYe vIYf Yfv+I YfJv gYJ",
+"fv YIf5 >IYf JfY5 YJf> YfvQI fvQY+I YZvJf ZfJgYv pIYf fpY>I YJfp YJyf hX hX",
+"& hDX hcX hX. h8X DXh. cXh8 hXK X&hK hTX cXhT hjX 8Xhj DXhj hsX hX* h-X DXh",
+"* c-X X*h. -Xh8 hDX*. c8-X X*hK hK-X TXh* -TcX X*hj -Xhj hTX*j sXh- hGX G&h",
+"X hJX cXhJ GXh. G8hX JXh. hXJ8 GXhK hGX&K JThX cJThX GjhX h8GXj hXJj sXhJ h",
+"fX -Xhf hXJf iX fXh. hXf8 JfXh. i8X fXhK f-XhK hXfT iTX hXfj f-jhX JfjhX is",
+"X hX2 X&h2 DXh2 h2cX h5X 5Xh8 5DhX cXh5 X2hK hX&2K TXh2 cXTh2 5Xhj h58Xj 5T",
+"hX sXh5 h;X -Xh; DXh; cXh; 5Xh; h>X h5DX; hc>X X;hK -X;hK TXh; c-XT; X;hj h",
+"j>X h5TX; >Xhs GXh2 hGX&2 JXh2 cJXh2 G5hX h5G8X hXJ5 cJ5hX hGX2K X&2hGK hJT",
+"X2 hJTcX2 h5GXj X&jh5G hJ5TX hsJ5X fXh; f-Xh; hXJ; iX; hXf5 hf>X Jf5hX i>X ",
+"hfX;K hf;-XK hJ;TX TXi; hf5Xj h>fXj J;jhX >Xis hP hP& hPD hcP hP. h8P DPh. ",
+"cPh8 hQX QXh& hTP cQhP hPj Q8hP DPhj hsP hP* h-P DPh* c-hP P*h. -Ph8 hPD*. ",
+"c-X8P QXh* -QhP TPh* -QcX P*hj -Phj hTP*j hPs- hY hY& hYJ Ych hY. hY8 h.YJ ",
+"h8Yc hYQ Y&hQ hZY YchZ hYj Y8hQ YZhj hsY hYf Y-h YJhf iY h.Yf h8Y- hYJf. iY",
+"8 YfhQ hQY- ZfhY iZY Yfhj hjY- hYjZf isY hmX Xmh& DXhm cXhm h5P 5Ph8 5DhP c",
+"5hP QXhm hQXm& TXhm cQXhm hpX pXh8 pDhP hPcp h;P -Xhm D;hP c;hP 5Ph; h>P h5",
+"PD; hc>P QXh; -QXhm T;hP c-QXm pXh; >Xhp hpDX; >Phs hYm Y&hm YJhm hmYc hY5 ",
+"Y5h8 YJh5 h5Yc YQhm hYQm& YZhm hZYcm hpY h8Yp hYJp sYhp hvY Y-hv JvhY iYv Y",
+"fh5 h>Y hY5Jv iY> YvhQ hvY-Q YZhv YZiv hYfp Y-hp JpfhY yiY Xe0 X!e0 e0XB Xe",
+"a0 1Xe 8X1e Xe1B aX1e e0XK Xe0!K XeT0 aXeT0 Xj1e Xje18 TX1e 1Xse X*0 +0X* X",
+"0*B a0X* 1X* +X1e *B1X aX1* *0XK X*0+K T0X* aX*T0 Xj1* X*j1+ TX1* 1Xs* XeG0",
+" GXe!0 XeH0 aXeG0 GX1e 1G8Xe HX1e 1GaXe GXe0K Xe0GK! GTXe0 GTXae0 Xje1G 1G8",
+"Xje 1GTXe sX1He fX0 +Xf0 HXf0 fXg0 f1X 1+fX 1HfX f1gX X0fK f+X0K TXf0 fTXg0",
+" 1Xfj f1+Xj 1TfX f1sX e0X2 Xe0!2 Xe02B aXe02 5X1e 1X58e 1X5eB 1aX5e Xe02K e",
+"02XK! TXe02 TX0ae2 Xje15 5X81ej 1TX5e sX15e X0e; X;e+0 X;e0B aX;e0 5X1* 1X>",
+"e 1X;*B >X1ae X;e0K +X0e;K TX;e0 aX0Te; X;j1e >X1ej 1TX5* sX*>1 GXe02 Xe0G2",
+"! HXe02 HX0ae2 1G5Xe G581Xe 1HX5e H5X1ae Xe0G2K 2Ke!GX0 TX0He2 aXHeT02 1G5X",
+"je 8eGj1X5 H5X1Te 1HXse5 X;f0 f+X;0 fHX;0 gfX;0 1Xf5 f1>X f1H5X f>g1X fX;0K",
+" X;0f+K fTX;0 gX;fT0 f15Xj f>1Xj f1T5X sf>1X eP0 P!e0 P0eB a0eP 1eP 8e1P 1B",
+"eP ae1P Q0eP eP0Q! T0eP aePQ0 QX1e ePj18 Te1P 1esP X0P* +0eP X*P0B aX*P0 X*",
+"1P +e1P 1X*PB aX*1P Q0X* +QXe0 QX*T0 aX*Q0 QX1* ePj1+ 1QXT* sX*1Q Ye0 e0Y! ",
+"HeY0 aeY0 Y1e 1eY8 1HYe 1aYe QeY0 YQe!0 Y0Ze YZae0 1QYe Y1Q8e ZeY1 Y1se Yf0",
+" f+Y0 fHY0 g0Yf Yf1 f1Y+ YHf1 Yfg1 Y0fQ Yf+Q0 Y0Zf gYZf0 f1Yj Yf1+Q Y1Zf Y1",
+"sf X0em Xme!0 Xme0B aXme0 5e1P 1Xm8e 1XmeB aXm1e XmeQ0 QX0em! TXme0 aX0Tem ",
+"1Xpe pX18e pX1Te sePp1 X0m* Xm*+0 Xm*0B aXm*0 Xm1* 1e>P Xm*1B >eP1a Xm*Q0 X",
+"m0+Qe Xm*T0 aX0Qe; 1Xp* >Xp1e pX*1T sX*p1 emY0 Yem!0 YHem0 Yaem0 1eY5 Y158e",
+" Y1H5e Y1a5e YQem0 em0YQ! YZem0 ZemYa0 peY1 Yp18e YZ1pe sYp1e Y0fv Yfv+0 Yf",
+"vH0 gYfv0 fvY1 Y1f> Yf1vH gY1f> YfvQ0 fvQY+0 YZvf0 ZfvgY0 Y1fp fpY>1 fpZY1 ",
+"Yfy1 ,X9 X&9e ,B9X 9a,X ,1X :Xe ,B1X ,a:X ,K9X X&K9e 9T,X ,TX9a 9X,j ,X:j 1",
+"T,X :Xse 9X* -X9 *B9X 9a-X 1X9* :-X ,1X*B :a-X 9KX* 9X-K TX9* 9T-X X*9j -j:",
+"X X*j9T :-sX 9G,X ,G9X& 9H,X ,Ga9X 1G,X ,G:X 1H,X ,H:X ,G9XK ,G9X&K ,GT9X 9",
+"GT,aX ,1GXj :GX,j ,1GTX sX,:G f9X -Xf9 9HfX f9gX ,1fX :fX f91HX gX:f 9XfK f",
+"-9XK 9TfX f-T9X 9Xfj fj:X f9T1X sX:f ,29X X&29e ,X92B ,aX92 95,X ,5:X ,1X5B",
+" :X5,a ,X92K 9X2e&K ,TX92 aX29Te ,1X5j :X5,j ,1T5X sX,:5 9X,; 9X-; ,X;9B -X",
+"9a; 1X,; :->X ,1X;B :-X>a ,X;9K -X9;K ,TX9; -TX9; X;j,1 :-X>j ,1TX; s-X:> ,",
+"G9X2 ,G9X&2 ,HX92 aX29He ,1G5X :G5,X ,1H5X :HX,5 9G2,XK X&9eG2K ,G29TX ,2GT",
+"9aX 9G5,Xj ,G5:Xj 9G5,TX sX5:He 9Xf; f-9X; f9HX; gf9X; 95fX >X:f f95HX g:Xf",
+"> f9X;K -X;f9K f9TX; f9;-TX f95Xj :f>Xj f95TX sf:>X 9eP e&9P 9BeP ae9P 1X,P",
+" :eP ,1XPB ae:P 9Q,X eP&9Q Te9P aeP9Q 1Q,X ,Q:X ePj9T :esP X*9P 9X-P 9X*PB ",
+"-X9aP ,1XP* -X:P X*B,1P :-XaP QX9* 9Q-X 9QXT* -QX9T X*j9Q -Q:X 9TXP*j s-X:Q",
+" Y9e 9eY& ,HY9 ,aY9 Y1, Y:e ,1YH :HY, ,QY9 Y9Qe& Z9Y, YZ9,a ,1Yj :QY, Z1Y, ",
+"seY: Yf9 Y-9 YHf9 g9Y- f9Y1 Y:f Yf91H gY:f fQY9 -QY9 Y9Zf Y9Z- f9Yj Yj:f Zf",
+"9Y1 Y:sf 9X,m Xm&9e ,Xm9B aXm9e 1X,m ,X:m ,1XmB :Xm,a ,QX9m 9QXem& ,TX9m 9Q",
+"a,Xm ,1pX pX:e p9X,T :pXse Xm9* 9X-m Xm*9B -Xm9a Xm*,1 :e>P XmB,1; :-Xam Xm",
+"*9Q -QX9m Xm*9T -TX9m 9Xp* :X-p p9XT* -pXs: ,mY9 Y9em& Y9H,m Y9a,m ,1Y5 :eY",
+"5 Y95,H Y:H,5 Y9Q,m em&Y9Q YZ9,m Y9mZe& p9Y, Y,:p Yp9Ze sY:pe fvY9 Y9-v Yf9",
+"vH gY9-v f9Y5 :fY> Yf9H5 Y:gf> Yf9vQ Y-v9Q Zf9Yv Y-Zv9 Y9fp fpY: fp9YZ Y:yf",
+" XeI0 IXe!0 XeD0 aXeD0 IX1e 1I8Xe DX1e 1DX8e IXe0K Xe0IK! DXTe0 DXTae0 IjX1",
+"e 1I8Xje 1DXTe sI1Xe I0X* I*X+0 D0X* aX*D0 I*1X 1+IX* DX1* aX*1D I*X0K +I0X",
+"*K DX*T0 aX0TI* I*j1X 1+IX*j X*j1D sI*1X GIXe0 IXeG0! XeJ0 JaXe0 1GIXe G8I1",
+"Xe 1XJe J18Xe IXeG0K I!XKGe0 JTXe0 aXeJT0 1GIXje 8eGj1IX J1TXe sJ1Xe IXf0 f",
+"+IX0 fXJ0 JfXg0 1IfX f1+IX JXf1 Jf1gX fIX0K +IXf0K JfTX0 fTXgJ0 f1IXj 1+Ifj",
+"X Jf1TX sfJ1X IXe02 Xe0I2! DXe02 DX0ae2 1I5Xe 5I81Xe 1DX5e 5DX1ae Xe0I2K I!",
+"X2e0K TX0De2 aXDeT02 1I5Xje 8X5e1Ij 5DX1Te 1DXse5 I;Xe0 +IXe;0 DX;e0 aX0De;",
+" 1I;X* >I1X* 1DX5* >XD1e X;0I*K +KI;X*0 I;0TX* X;De+T0 1I;X*j I*j>X1 1DXe;j",
+" >I1sX* IXeG02 I!X2Ge0 JXe02 aXeJ02 G5I1Xe 8X5e1GI J15Xe 1aXJ5e IXG0e2K IXG",
+"02Ke! TXeJ02 aXJeT02 Ij1XG5e GX8e15Ij 1TXJ5e J15sXe fIX;0 I;Xf+0 JfX;0 gfXJ",
+";0 f15IX f>1IX Jf15X J>f1X I;Xf0K I;fX+0K fTXJ;0 X;g0JfT I;jf1X f1I>Xj J1Xf",
+"5T sf1J>X I0eP IPe!0 D0eP aePD0 IP1e 1IP8e De1P aeP1D IPeQ0 QI0eP! QDXe0 aX",
+"0QDe IPj1e Q8I1eP ePj1D sIP1e I0P* IP*+0 IP*D0 aP*I0 IP1* IP*1+ IP*1D aP*1I",
+" IP*Q0 IP0+Qe IP*T0 aX0QD* IP*1Q 1+QIP* IP*1T sIP1* IeY0 YIe!0 JeY0 YJae0 1",
+"IYe Y18Ie YeJ1 YJ18e YQIe0 QIeY0! YZJe0 ZJeYa0 Y1QIe 1QIY8e YZ1Je sYJ1e fIY",
+"0 Yf+I0 Y0Jf gYJf0 YIf1 Yf1+I JfY1 gY1Jf YfQI0 fQIY+0 YJfZ0 ZfJgY0 Yf1QI Y1",
+"IfQ8 Zf1YJ sYfJ1 ImXe0 em0IP! DXme0 aX0Dem 1ImeP 8Im1eP 1DXem 1DXaem QIXem0",
+" ImQXe0! Im0TeP aXQeIm0 pI1eP 1IPpe8 pDX1e sX1pDe Im*X0 Im0+eP Xm*D0 aX0Im*",
+" Im*1X >eP1I Xm*1D >eD1P Im0QX* Im+XQe0 Im0TX* XmD*+Q0 pI*1X >I1pX* pDX1* >",
+"I1seP YIem0 ImeY0! YJem0 JmeYa0 Y15Ie 1ImY8e YJ15e Y1eJ8m ImeYQ0 QmY0Ie! Ze",
+"mYJ0 aeJmYZ0 Yp1Ie pI8Y1e JpY1e sY1Jpe YfvI0 fvIY+0 YJfv0 JvfgY0 Yf1vI Y>f1",
+"I Jv1Yf Y>Jf1 fQIYv0 YQvIf+0 JvYZf0 gJZfYv0 fpY1I Y>1fpI JpfY1 yJYf1 h9X 9X",
+"h& 9DhX h9cX h1X h:X 1DhX :Xhc 9XhK h9X&K 9ThX cX9hT 9Xhj :Xhj 1ThX sXh: 9X",
+"h* h9-X DX9* c9-X 1Xh* :Xh- h1DX* c-:X h9X*K -X9hK hT9X* c-X9T h1X*j h:-Xj ",
+"h1TX* s-Xh: 9GhX h9GX& hXJ9 cJ9hX 1GhX hG:X hXJ1 :XhJ h9GXK X&Kh9G J9ThX hJ",
+"9cXT h1GXj h:GXj J9jhX hsJ:X hXf9 f-9hX JXf9 i9X hXf1 :Xhf Jf91X i:X f9XhK ",
+"hf9-XK Jf9TX 9TiX f9jhX :fhXj Jf9Xj s:iX 9Xh2 h9X&2 h9DX2 cX9h2 95hX :Xh5 h",
+"15DX h:c5X h9X2K X&2h9K hT9X2 hT9cX2 h15Xj h:5Xj h1T5X hs:5X 9Xh; -X9h; h;9",
+"DX c-X9; 1Xh; >Xh: h1;DX c>Xh: h;9XK h;9-XK hT;9X cX9hT; h1;Xj h>:Xj h1TX; ",
+"hs>:X h9GX2 X&2h9G J9Xh2 hJ9cX2 h1G5X h:G5X J95hX :Jh5X 9GXh2K X&h29GK hTXJ",
+"92 h9cXJT2 9G5hjX h5G:Xj J9Xh5T :J5hsX f9Xh; hf9-X; Jf9X; 9Xi; f95hX h>:fX ",
+"Jf95X >Xi: h;Xf9K h9-Xf;K J9XhT; i9;TX f9Xh;j :fXh>j J9Xf5T is:>X hP9 9Ph& ",
+"9DhP h9cP h1P h:P 1DhP :chP 9QhP hQ9X& 9ThP cQXh9 9Phj :QhP 1ThP s:hP 9Ph* ",
+"h9-P hP9D* c-X9P 1Ph* :-hP h1PD* h:Pc- hQ9X* -QXh9 hTP9* c-Q9X h1QX* h:Q-X ",
+"h1TP* hsP:- hY9 h9Y& Y9hJ Y9hc hY1 Y:h YJh1 hY:J Y9hQ hY9Q& Y9hZ hZYc9 Y9hj",
+" hQY: YZh1 Y:hZ Y9hf Y9h- JfY9 iY9 Yfh1 hY:f hY1Jf iY: hYf9Q Y-h9Q Zf9hY YZ",
+"i9 hY1fQ Y:hfQ hZ1Yf sYi: 9Xhm hm9X& hm9DX cXmh9 95hP :Xhm h1mDX h:mcX hQ9X",
+"m Xm&hQ9 hTm9X cX9hTm p9hP hP:p hp9DX cpXh: 9;hP -Xmh9 h;P9D c-X9m 1;hP >Ph",
+": h1;DP h>P:c hQ;9X -Q9h;P hT;9P cQ9-Xm hp9X; -pXh: p9DX* cp-:X Y9hm hY9m& ",
+"hYJ9m Ych9m Y9h5 h5Y: hY1J5 Y:Jh5 hY9Qm hQ9Y&m hZY9m Yc9hZm h1Yp Y:hp Jp9hY",
+" hZ:Yp Y9hv hvY-9 Jv9hY Yvi9 Yvh1 Y:hv hv1YJ Y:iv hvY9Q Y-9hvQ hZvY9 iZYv9 ",
+"fp9hY hv:Yp JpfY9 yYi: Re Re! ReB Rae Re. R8e e.RB 8eRa ReM R!Me RTe TeRa R",
+"ej 8MRe TeRj sRe Re* R+e *BRe +eRa R.X* +eR8 X*.RB aX*R8 XM* +MRe TXR* +TRe",
+" X*Rj +eRj XM*Tj R+se RGe GeR! RHe GaRe GeR. G8Re R.He H8Re GMRe XM!Ge GTRe",
+" aXMHe GjRe RG8Me HeRj RGse fR fR+ fRH gfR fR. fR8 RHf. f8gR fRM R+fM fRT f",
+"RgM fRj R+fj RHfj sfR Re2 e2R! e2RB R2ae R5e 5eR8 RB5e 5aRe R2Me XM2e! R2Te",
+" aXMe2 5MRe R5e8M 5TRe R5se Re; +eR; RBe; aeR; 5XR* >eR R5e*B Ra>e MeR; XM;",
+"+e TeR; aXMe; XM5* Re>M XM*5T sR>e GeR2 RGe!2 R2He RGae2 G5Re RG58e H5Re RG",
+"5ae XM2Ge RG2Me! RGTe2 aX2HMe RG5Me G5MR8e RG5Te sRG5e fR; R+f; RHf; g;fR f",
+"R5 f>R RHf5 gRf> R;fM fR+M; RTf; fRTg; R5fM fR>M R5fT sRf> ReP R!eP RBeP aP",
+"Re R.eP 8PRe eP.RB aePR8 Se Se! SeT Sae Sej S8e TeSj Sse ePR* +PRe X*PRB aX",
+"*RP X*PR. R+e8P Re.P*B R8eaP* Se* S+e TXS* +TSe X*Sj +eS8 SeT*j S+se YRe Re",
+"Y! RHYe RaYe ReY. R8Ye YRHe. Y8RHe SYe YeS! SZe YaSe YjSe Y8Se SjZe seSZ Yf",
+"R fRY+ YHfR YfgR Y.fR fRY8 YfRH. gYfR8 Sf Sf+ SfZ gSf Sfj Sf8 fjSZ sfS Rem ",
+"R!em RBem aeRm 5eRm 8eRm R5emB aemR5 Sem emS! TeSm aeSm Spe peS8 STpe seSp ",
+"XmR* +eRm Xm*RB aXmR* Xm*R5 Re>P XmBR5* >eRam Se; +eS; TeS; aeS; pXS* S>e S",
+"peT; >eSs ReYm YRem! HeRm YaRem R5Ye Y5R8e Y5RHe Y5aRe YeSm SYem! SmZe SZea",
+"m SeYp SpeY8 ZpSe SseYp fvR f+vR fHvR fvgR fRY5 fRY> Yf5RH f>RgY Sfv fvS+ Z",
+"fSv gfSv Sfp Sf> SZfp yfS ,RX Re& RB,X Ra,X ,.Re R8,X ,RX.B ,R8aX ,XM X&,M ",
+"RT,X TeR& Re,j 8X,M ,RTXj ,RsX R*,X -RX X*B,R Ra-X X*.,R R8-X ,R.X*B -R8aX ",
+"X*,M -XM XM*,T RT-X XM*,j Re-j ,RTX*j -RsX ,RG R&,G RG,H RG,a ,.RG RG,8 ,RG",
+"H. ,RGH8 RG,M XM&,G RG,T aXM,G RG,j e&jRG ,RGHj ,RsG fR, f-R ,RfH f-gR ,Rf.",
+" -Rf8 fRH,. f-Rg8 ,RfM -RfM ,RfT -RfT ,Rfj -Rfj fRT,j f-sR ,2Re R2e& ,RX2B ",
+",RaX2 R5,X 5eR& ,R5XB ,R5aX ,2XM XM&,2 ,RTX2 aXM,2 5X,M XM&,5 ,R5TX sX,R5 R",
+"e,; Re-; ,R;XB -RaX; ,R5X; -R>X X;B,R5 >X-Ra XM,; XM-; XM;,T -RTX; XM;,5 -X",
+">M ,RTX;j s-R>X ,2RG ,RG&2 ,RGH2 ,RGa2 RG,5 ,RG5& ,RGH5 ,RG5a ,RGM2 X&2,GM ",
+",RGT2 aX2,GM ,RG5M ,G5XM& ,RG5T sRG,5 ,Rf; f;-R fRH,; f-Rg; ,Rf5 ->fR fR5,H",
+" f>Rg- fRM,; f-RM; fRT,; f-RT; fR5,M f>R-M fR5,T sfR-> Re,P ePR& ePB,R aeP,",
+"R eP.,R eP&R8 ,R.ePB ,R8aeP Se, Se& ,TSe ,aSe ,XSj ,8Se SeT,j Ses, X*P,R Re",
+"-P ,RXP*B -RaeP ,RXP*. -R8eP ePR*,.B aeP-R8 ,XS* S-X SeT,* -TSe Se*,j -XS8 ",
+"X*jS,T sXS- Y,R ,RY& ,RYH ,RYa ,RY. ,RY8 Y,RH. Y8,RH SY, Y&Se YZS, YaS, YjS",
+", Y8S, SZe,j SYs, fRY, Y-R YfR,H gRY- YfR,. -RY8 fRHY,. Y-gR8 Sf, Sf- S,Zf ",
+"Y-gS fjS, S8Y- SfZ,j S-sY Re,m emR& ,RmXB aXm,R ,R5Xm em&R5 XmB,R5 ,R5aXm ,",
+"XSm emS& SeT,m Sae,m pXS, peS& Spe,T Ssep& Xm*,R Re-m XmB,R; -RmaX ,R5Xm* >",
+"X-Rm Xm,;R5B >Xa-Rm ,XS; -XS; Se;,T S-TXm Spe,; >XS- S;TpX, -pXSs ,RYm Y&R,",
+"m Y,RHm Ya,Rm ,RY5 Y5&,R Y5,RH Y5a,R SmY, SY&,m SZe,m SZem& S,Yp Yp&Se Yp,S",
+"Z sY,Sp vRY, fR-v Yv,RH -vRgY Yf5,R -RY> Y5HvR, Y->gR YvS, SvY- Sv,Zf gSf-v",
+" S,fp Y-S> SfpZ, Sfy- [e [!e [De [ae [e. [8e De[. D8[e [Me Me[! V[e [aVe [j",
+"e 8M[e [jVe [se [* [+e [*D [a* [*. [8* D*[. D8[* [*M +M[* V[* [+Ve [*j +e[j",
+" [jV* [s* [Ge Ge[! [Je Je[a Ge[. G8[e [eJ. Je[8 GM[e [!GMe [JVe VJ[ae Gj[e ",
+"[8GMe Je[j [Jse [f [f+ [fJ g[f [f. [f8 J.[f J8[f [fM [+fM Vf[ Vfg[ [fj [+fj",
+" Jj[f sf[ [e2 e2[! De[2 ae[2 [5e 5e[8 5D[e 5a[e Me[2 [!Me2 [eV2 V[ae2 5M[e ",
+"[58Me [5Ve [5se [;e +e[; De[; ae[; [5* [>e 5D[* [a>e Me[; [+Me; [;Ve V[+e; ",
+"5M[* [*>M [5V* >e[s Ge[2 [!Ge2 [eJ2 [Jae2 G5[e [5G8e Je[5 J5[8e [GMe2 Me2[!",
+"G VJ[e2 [JaVe2 [5GMe G5M[8e J5V[e [sJ5e [f; f+[; J;[f [;gf [f5 [>f J5[f f>g",
+"[ [;fM [f+M; V;[f Vfg[; [5fM >M[f V[f5 [>sf [eP eP[! De[P ae[P eP[. 8e[P [D",
+"eP. [8DeP S[e [!Se SVe VeSa [jSe [8Se SjVe SVse [*P +e[P DP[* aP[* P*[. 8P[",
+"* [*DP. [8*DP S[* [+Se V[S* V+Se [jS* [8S* SVe*j s*S[ [Ye Ye[! Ye[J Ye[a [e",
+"Y. Ye[8 YJ[e. YJ8[e [YSe S[Ye! ]e ]ae Ye[j S[8Ye ]je ]se [fY Y+[f YJ[f [fgY",
+" Y.[f Y8[f YJf[. g[Yf8 Sf[ S+[f ]f ]gf Yj[f S8[f ]fj ]sf [me em[! De[m ae[m",
+" 5e[m 8e[m [5Dem [5aem [mSe S[em! VmSe SVeam [pe [8pe SeVp se[p [m* +e[m Dm",
+"[* am[* 5P[* [m>e [5*Dm [>Dem [mS* S[+em VeS; SV+em [p* >e[p V*[p SV>e Ye[m",
+" [Yem! Je[m Ya[em Ye[5 Y5[8e YJ5[e Y5[ae S[Yem [YmSe! ]em ae]m [Ype [pY8e ]",
+"pe sp]e [vf [+fv [fJv gf[v Y5[f f>[v [vJf5 [>fgY [vSf [vfS+ ]fv gf]v fp[ [>",
+"Sf ]pf ]yf [h [h& [hD [ch [h. h8[ [Dh. h8[c hM[ [&hM Vh[ [cVh hj[ [8hM V[hj",
+" hs[ [h* [- hD[* [-c h.[* [-8 [hD*. [8c- [*hM [-M [hV* V-[ [*hj [-j Vh[*j [",
+"s- [hG hG[& hJ[ hJ[c [Gh. hG[8 h.[J [Jh8 [GhM [hGM& V[hJ VhJ[c hG[j h8[GM [",
+"Jhj hJ[s [fh [-f hJ[f i[ h.[f h8[f [fJh. i[8 hM[f fM[- [fVh iV[ hj[f fj[- V",
+"f[hj i[s [h2 h2[& [Dh2 h2[c h5[ [5h8 hD[5 h5[c [Mh2 [h&M2 h2V[ Vh[c2 [5hM h",
+"5[8M V[h5 h5[s h;[ [-; hD[; h;[c [5h; h>[ h5[D; c>[- [;hM [;-M V[h; V;[- [;",
+"hj >M[- Vh5[; [sh> [Gh2 [hG&2 h2[J [cJh2 hG[5 h5[G8 [Jh5 [c5hJ [hGM2 [&GhM2",
+" VhJ[2 [cJVh2 h5[GM h5G[&j Vh5[J hs[J5 h;[f [;f- [Jh; i[; h5[f f>[- [f5hJ i",
+"[> [fhM; [-fM; Vf[h; V[i; [f5hM [-jf> Vf5[h V>i[ hP[ [&hP [DhP hP[c [Ph. [8",
+"hP [hDP. [ch8P Sh Sh& ShV Shc Shj Sh8 SVhj hsS [*hP [-P [hDP* cP[- [h*P. [8",
+"-P [*DhP. [-c8P Sh* Sh- S*Vh V-Sh S*hj h8S- ShV*j S-hs hY[ [hY& [JhY [chY h",
+".[Y [hY8 hYJ[. hY8[c ShY S&hY ]h ]hc SYhj SYh8 ]hj ]hs [fhY Y-[ hYJ[f i[Y h",
+"Y[f. Y8[- [fJhY. Y8i[ Shf Y-Sh ]hf ]i hjSf h8Sf hf]j ]is hm[ [&hm hD[m hm[c",
+" [5hm [8hm h5[Dm [c5hm Shm S&hm SVhm hmSc hp[ h8[p VpSh Schp [mh; [-m hm[D;",
+" cm[- h5[m* >P[- h5D[m* [-mc> Sh; hmS- SVh; h;Sc h;[p h>S [p*Vh Sch> [Yhm h",
+"Y[m& [Jhm [cmhY [hY5 hY5[8 hY5[J Yc5[h SYhm ShYm& ]hm hc]m hY[p [p&hY ]ph h",
+"p]s hv[ [-v hJ[v i[v h5[v [-Y> hv[J5 Y>i[ hvS S-hv ]hv ]iv Sfhp Sfh> hp]f ]",
+"yi Rek R!ke RBke akRe R1e 1eR8 RB1e 1aRe XMke kXMe! TkRe akXTe lXe R8le RTl",
+"e sRle kX* +kRe *BkX kXa* 1XR* 1+Re kX*1B akX1* XMk* kX*+M kXT* akXT* lX* R",
+"+le TXl* sXl* GkRe kX!Ge HkRe akXHe 1GRe R1G8e 1HRe R1Gae kXMGe RGkMe! RGTk",
+"e RGTake RGle lGR8e RHle lsGRe fRk R+fk RHfk fRgk fR1 R1f8 R1fH fRg1 kXfM f",
+"R+kM RTfk fRTgk lfR fRl+ fRlH lXsf R2ke kX2e! kX2eB akXe2 1eR5 R1e58 R1e5B ",
+"akX5e kXMe2 XM2ke! RTek2 ak2RTe R5le lX58e lX5Te lsX5e keR; kX;+e kX;*B akX",
+"e; 1eR; R1>e kX*5B >kXae kX;Me +kXMe; kX;Te kX;aMe Rel; lX>e lX;Te l>Xse kX",
+"2Ge RG2ke! RHek2 ak2RHe R1G5e G5kR8e R1H5e RG5ake RGkMe2 M!kXGe2 kX2HMe akR",
+"eGT2 lGR5e RG5le8 lHX5e sX5lHe R;fk fR+k; fRHk; gfRk; R1f5 fR>k fR1H5 f>Rg1",
+" fRkM; kX;fM+ fRTk; fT;gkX fRl; >Xlf lfRH5 glf>X keP k!eP kBeP keaP 1PRe ke",
+"8P keP1B ake1P Sek keS! TkSe akSe leS S8le lTSe leSs X*kP ke+P kX*PB akXP* ",
+"kX*1P kX*8P kXB1P* R1+aeP kXS* +kSe SeTk* S+eTk Sel* S+le lX*ST Ssel+ Yke k",
+"eY! HkYe akYe R1Ye 8kYe Y1RHe Y1aRe YkSe SYke! ZkSe SZeak lYe Y8le SZle les",
+"Y Yfk fkY+ YHfk Yfgk fRY1 f8Yk Yf1RH gY1fR Sfk fkS+ YkZf gkSf lYf l+Sf ZflY",
+" gSlf keRm kXme! kXmeB akXem 1eRm kXm8e keP5B ake5P keSm Sekm! SeTkm Saekm ",
+"Sple Spel8 SpelT Sselp Xmk* kXm+e kXm*B akXm* kXm1* ke>P kXB1m* >keaP keS; ",
+"S+ekm Se;Tk Saek; Sel; leS> Se;lT S>els keYm Ykem! YkHem Yakem 5kYe Y5k8e Y",
+"5kHe Y5ake SYkem YkmSe! SZekm SamZke leYp lYp8e lYZpe lYspe fvYk Yfkv+ Yfkv",
+"H gYkfv f5Yk Yf>k Yf5Hk Y>kgf fkSv Sfv+k ZfkSv gSfvk Sflv S>lf lYfZp lYyf ,",
+"kX 9eR& RB9e 9aRe R1,X :Re ,R1XB Ra:e 9X,M kX&,M 9TRe akX,T lX, :Rle ,TlX s",
+"Xl, 9XR* -kX kX*,B ak-X kX*,1 -R:X k*B,1X :-RaX XM9* 9X-M kX*,T Tk-X ,Xl* l",
+"-X lX*,T lXs- R9,G kX&,G 9HRe akX,G R1,G ,R:G ,R1HX RH:e ,RG9M ,GkXM& ,RG9T",
+" ,GTakX ,RlG :RGle ,HlX sX,lG fR9 -Rf9 R9fH fRg9 ,Rf1 :fR fR91H gR:f R9fM f",
+"-R9M R9fT f-R9T fRl, lX:f lfR,H g-lX ,2kX kX&,2 ,kX2B akX,2 95Re R5:e ,5kXB",
+" :Re5a ,kXM2 kX2Me& ,TkX2 ak2,TX ,5lX :Rel5 lX,5T sX,l5 9eR; kX-; kX;,B -kX",
+"a; kX;,1 :R>e kXB,1; :>Rae kX;,M -kXM; kX;,T -TkX; ,Xl; >Xl- lX;,T l-Xs> ,R",
+"G92 ke2RG& ,HkX2 ak2,RG ,R1G5 :RG,5 ,H5kX :RH5e kX2,GM XMk&,G2 kX2,GT aX9M,",
+"G2 lG,R5 :R5lG, lHX,5 sX5lG, R9f; f-R9; fR9H; fR9g; R9f5 :Rf> fR9H5 :fRg> f",
+"R9M; f9;-XM fR9T; fR;-Tk lfR,5 lf:>X fR95T gl->X 9PRe ePk& keP,B akX,P keP,",
+"1 Re:P kXB,1P :ReaP S9e 9eS& 9TSe 9aSe S9le S:e S9elT seS: kX*,P kX-P kXB9P",
+"* -kXaP ,1XkP* :-ReP X*9PR1B :Xa-kP 9XS* -kSe S9eT* S-9TX S9el* lXS- S9TlX*",
+" l-SsX Yk, ,kY& ,HYk ,aYk ,RY1 :RY, Y1,RH Y:R,H Y9Se SY9e& Z9Se SZ9ae lY, l",
+"eY: YZl, l,sY fRY9 Y-k Yf9RH gkY- Yf9R1 Yk:f Y9HfR1 Y:gfR Sf9 S9Y- S9Zf g9S",
+"f l,Sf lY- lYfZ9 sYl- 9eRm kXme& kXm,B akX,m kXm,1 Re:m kXB,1m :Ream 9eSm S",
+"9em& S9eTm S9aem p9Se Se:p Sp9Te S:esp kXm,; kX-m kXB,;P -kXam ,R1Xm* :-RXm",
+" Xm9*R1B :Ra>eP 9eS; S-9Xm S9eT; S9ae; Sp9X* >eS: S9Tle; -pXls ,kYm Yk&,m Y",
+"k,Hm Yak,m ,5Yk Y:R,5 Y5k,H Y5a,k SY9,m SemYk& SZ9em S9mYa, l,Yp lY:pe lY,Z",
+"p lYsp, vRf9 Yk-v Yvk,H Y-kgv Yf9R5 >kY- Y9HfR5 :vRgf fvS9 Sf-v9 Sf9Zv gSfv",
+"9 S9fp Y-lv fp9SZ lYy- [ke ke[! Dk[e ak[e [1e 1e[8 1D[e 1a[e ke[M [!kMe [kV",
+"e V[ake [le [8le V[le le[s [*k +k[* Dk[* ak[* [1* 1+[* 1D[* 1a[* k*[M [+kMe",
+" Vk[* V[+ke [l* [+le V[l* l*[s Gk[e [!Gke [kJe Jk[ae 1G[e [1G8e Je[1 J1[8e ",
+"[GkMe keM[!G JkV[e V[aJke [Gle [lG8e [Jle [slJe [fk [+fk Jk[f gk[f [f1 [1f8",
+" J1[f g1[f [kfM [f+kM fkV[ Vfg[k lf[ l+[f [lVf g[lf ke[2 [!ke2 [Dke2 [ake2 ",
+"1e[5 [158e [15De [1a5e [kMe2 keM[!2 V[ke2 [akVe2 [5le [l58e [lV5e [sl5e ke[",
+"; [+ke; [;Dke [a;ke 1e[; [1>e [1;De [>1De [;kMe ke;[+M V[;ke Vek[a; [5l* >e",
+"[l [l;Ve V>[le [Gke2 ke2[!G Jk[e2 [aeJk2 [1G5e G5k[8e J1[5e J1e[5a keM[G2 k",
+"e[!GM2 V[eJk2 akVe[J2 [lG5e [5Gle8 lJ[5e lJ5[se [;fk [f+k; [fJk; g[fk; [1f5",
+" >k[f [f1J5 J>k[f [fkM; [+kfM; Vf[k; g[kVf; l;[f [>lf Vf5[l J>l[f ke[P keP[",
+"! keDP [akeP 1e[P [18eP [1DeP [1aeP [kSe S[ke! SkVe SVeak S[le S[8le SVle [",
+"slSe kP[* [+keP [*DkP [a*kP 1P[* [1+eP [1*DP [1aP* Sk[* S[+ke SVek* SV+ke S",
+"[l* [l+Se [l*SV [s*Sl [kYe Yk[e! YeJk YJkae Ye[1 Y1[8e YJ1[e YJ8ke S[Yke Yk",
+"[Se! ]ke ak]e [Yle lY[8e ]le ls]e Yk[f Yfk[+ JfYk gYk[f Y1[f [f1Y+ [f1YJ g[",
+"1Yf fkS[ Sf[+k ]fk gf]k [lSf lYf[+ ]lf gl]f ke[m [mke! [mDke [amke 1e[m [1m",
+"8e [1mDe [1aem S[kem [mkSe! SVekm SakVem le[p [pl8e [plVe [psle km[* [+mke ",
+"[m*Dk [amk* 1m[* [>1em [1mD* >kDeP S[;ke S+k[m* SVek; S+kVem l*[p [p*l> [p*",
+"Vl V>eSl Yk[em [meYk! YJkem YaeJkm Y1[5e Y1e[8m YJ5ke Y1e[5a Yk[Sem ke[mSY!",
+" ke]m ]akem [plYe lY8[pe le]p ]lpse fk[v [vf+k [vJfk g[vfk f1[v [v1f> [v1Jf",
+" J>kYf [vfSk Sf+[vk fv]k ]gfvk [plf fp[l> lf]p yl]f ht[ [&ht hD[t ht[c h1[ ",
+"[:h hD[1 [ch: [thM ht[M& V[ht Vh[tc lh[ lh[: [lVh u[h t*[ [-t tD[* [ct- [1t",
+"* [:- t*[1D :c[- tM[* [t-M V[t* V[t- t*[l l-[ lhV[* u[- [htG tG[h& [Jht tJ[",
+"hc hG[1 [h:G [Jh1 hJ[: tG[hM [h&tGM tJV[h Vh[tJc [hlG [:lhG hJ[l hJu[ tf[ [",
+"-tf [ftJ i[t h1[f :f[ [f1tJ i[: [tfM [-tfM V[tf V[it [ltf [:lf lJh[f ui[ h2",
+"[t ht[&2 ht[D2 [cht2 [ht5 h5[: t5[hD [:hc5 ht[M2 hM&[t2 Vh[t2 [ctVh2 h5[l [",
+":lh5 lhV[5 h5u[ [ht; t;[- t;[hD [-tc; [1h; [:h> t5[D* [:-c> t;[hM [-tM; Vh;",
+"[t V-[t; h;[l [>l- lh;V[ h>u[ tG[h2 [h&tG2 tJ[h2 [chtJ2 tG5[h [:hG5 tJ5[h :",
+"J[h5 [h2tGM hG[&tM2 Vh[tJ2 h2tJ[cV lh[G5 lhG[:5 lJh[5 uh5[J t;[f [-tf; tJ;[",
+"f t;i[ t5[f [>tf tf5[J t>i[ tf[M; tfM[-; tfV[; iV[t; lh;[f l-[f> Vf5[t i[u>",
+" htP h&tP hDtP tchP tPh1 hP[: htP1D [:hcP Sht S&ht VhSt htSc Shl Sh: SlVh u",
+"hS t*hP hPt- tP*hD [-tcP tP*h1 :P[- tPD[1* [:-cP S*ht St[- St*Vh V-[St l*Sh",
+" Shl- ShlV* Shu- tYh Y&ht tJhY htYc h1tY hY[: hY1tJ tY:hJ tYSh ShtY& ]ht ht",
+"]c lYh Y:Sh ]lh ]uh tYf tY- YJtf itY Y1tf Y:tf tYfJ1 tYi: Sft tYS- ]tf ]it ",
+"Shlf tYl- lf]h ui] tmhP tm[h& tm[hD [cmht t5hP hm[: t5PhD [:mhc hmSt Shtm& ",
+"VhmSt Shctm tpSh S:hp hplSV hpu[ t;hP tm[- tm[D* [-mtc t5[m* ht>P t5Dh;P [:",
+"-cm h;St [-mSt Sh;Vt V-[tm l;Sh S:h> [p*Vt h>uS hmtY tYhm& tJmhY tYchm h5tY",
+" [:mhY tY5hJ [:mhJ ShtYm tYmSh& ht]m ]htcm hplY [p:hY hp]l ]puh tYhv Y-tv h",
+"v[tJ tYiv h1[v tYh> [v1hJ tYi> tvSh [-vSt hv]t ]tiv hvlY h>lY lv]h ]yui n n",
+"! nB an n. 8n n.B 8na nK n!K Tn Tna nj 8nj Tnj sn n( +n n(B +na n(. +n8 .Bn",
+"( +8an n(K +nK Tn( +Tn nj( +nj T(nj sn+ nE n!E Hn Hna nE. 8nE Hn. H8n nEK E",
+"Kn! HnT HTan njE 8Enj Hnj snH dn +nd Hnd gn dn. 8dn H.dn gn8 dnK +Kdn Tdn g",
+"nT dnj dn+j dnHj gsn 4n 4n! 4nB 4an 5n 48n 5nB 5an 4nK n!4K 4Tn Tn4a 4jn 8n",
+"4j 5Tn s4n ;n 4+n ;nB a;n 5n; >n 5B;n >na ;nK 4K+n T;n +n4T ;nj >nj T;5n >n",
+"s 4nE n!4E 4Hn Hn4a 5nE 4E8n H5n Hn48 nE4K 4nE!K Hn4T 4HTan 4Enj njE48 Hn4j",
+" 4Hsn 4dn +n4d H;n g4n 5dn >nd 5dHn >ng 4Kdn dnK4+ T;Hn 4Tgn dn4j dn>j Td5n",
+" gs>n Pn n!P PnB aPn Pn. 8Pn n.PB aP8n Qn Qn! QnT Qan Qnj Q8n PjTn sPn Pn( ",
+"+Pn n(PB aP+n n(P. 8P+n Pn(.B aPn+8 Qn( +Qn Q(Tn Qa+n Q(nj Q8+n Pj(Tn +Qsn ",
+"Wn Wn! HPn Wan Wn. W8n H.Wn W8Hn WnQ Q!Wn Zn Zna Wnj Q8Wn Znj sZn Wnd +Wn d",
+"PHn gPn W.dn W8+n dP.Hn W8gn Qdn Wn+Q Znd gZn dnWj Wn+j dnZj gnsZ o o! oB o",
+"a o5 o8 o5B o8a oQ o!Q oT oTa op op8 opT os o; o+ o;B o+a o5; o> 5;oB o>a o",
+"Q; o+Q oT; o+T op; o>p pTo; os> oW o!W oH oHa o5W o8W oH5 oH8 oWQ Q!oW oZ o",
+"Za opW pWo8 oZp osZ ov ov+ ovH go ov5 o>v vHo5 go> ovQ v+oQ oZv goZ opv pvo",
+"> opZv yo n# &n n#B an& n#. 8n& .Bn# 8a&n n#K &nK Tn# T&n nj# &nj T#nj sn& ",
+"n#( +n& #Bn( +a&n #(n. +8&n n#(.B an&+8 #(nK +K&n n#T( T&+n j#n( &n+j nj#T(",
+" +ns& n#E &nE Hn# H&n #En. 8E&n n#H. 8nH& EKn# nK&E H#Tn T&Hn j#nE &Enj H#n",
+"j H&sn dn# d&n H#dn gn& n#d. d&8n dn#H. 8ng& n#dK dK&n T#dn T&gn d#nj &ndj ",
+"dnjH# g&sn 4n# 4&n n#4B an4& 5n# 5&n n#5B an5& n#4K 4K&n 4#Tn Tn4& 4#nj &n4",
+"j 5#Tn 4&sn ;n# ;&n nB;# ;&an 5#;n >n& ;n#5B an>& n#;K ;K&n T#;n ;&Tn ;#nj ",
+"&n>j ;njT# >&sn n#4E 4E&n 4#Hn Hn4& n#5E 5E&n H#5n 5&Hn 4n#EK &nE4K 4HTn# 4",
+"H&Tn nj#4E &nj4E 4Hjn# snH4& 4#dn dn4& H#;n 4&gn 5#dn d&>n H5nd# >&gn dn#4K",
+" d&n4K 4Tdn# g4T&n dnj4# >nd&j ;njH# >ngs& Pn# P&n n#PB P&an n#P. P&8n Pn#.",
+"B aP&8n Qn# Q&n Q#Tn T&Qn Q#nj 8nQ& Pj#Tn Q&sn n#P( P&+n Pn#(B aP&+n Pn#(. ",
+"P&n+8 n#(P.B +P8an& n#Q( Q&+n QnT#( +QnT& Pj#n( P&j+n TP#nj( sP+&n Wn# W&n ",
+"H#Wn W&Hn n#W. 8nW& HPn#. H8P&n W#Qn Q&Wn Zn# Z&n W#nj &nWj njZ# Z&sn W#dn ",
+"W&+n dP#Hn W&gn dP#n. dP&8n HP#dn. gP8&n Q#dn d&Qn dnZ# Z&gn dPjn# dP&nj Zn",
+"dj# Z&ngs o# o& o#B oa& o5# o8& 5Bo# 5ao& oQ# o&Q oT# oT& op# op& pTo# os& ",
+"o;# o+& ;#oB a;o& 5;o# o>& o5;#B >&oa Q;o# +Qo& T;o# +To& p;o# p>o& opT;# o",
+"&s> oW# o&W oH# oH& 5Wo# 5Wo& H5o# H5o& WQo# W&oQ oZ# oZ& pWo# oWp& Z#op Z&",
+"os ov# ov& vHo# go& v5o# v>o& ovH5# o&g> vQo# oQv& Z#ov Z&go o#pv pvo& oZpv",
+"# yo& nC n!C Dn Dna nC. 8nC Dn. D8n nCK CKn! DnT DTan njC 8Cnj Dnj snD nC( ",
+"+nC Dn( +Dn C(n. +C8n n(D. D8+n CKn( nC+K D(Tn Dn+T jCn( +Cnj D(nj +Dsn nCE",
+" !CnE HnD HDan CEn. nC8E H.Dn D8Hn EKnC n!CEK HDTn HnDTa jCnE njC8E DnHj Hn",
+"sD dnC +Cdn Ddn gnD nCd. 8Cdn D.dn D8gn nCdK dnC+K TdDn DngT dCnj dnj+C dnD",
+"j gDsn 4nC n!4C 4Dn Dn4a 5nC 4C8n 5Dn D85n nC4K 4nC!K Dn4T 4DTan 4Cnj njC48",
+" Dn4j 4Dsn ;nC 4C+n D;n +n4D 5C;n >nC D;5n >nD nC;K ;nC+K T;Dn a;nDT ;Cnj n",
+"j>C ;nDj >Dsn nC4E 4nC!E Hn4D 4HDan nC5E 48nCE 5DHn 4H8Dn 4nCEK n!C4EK 4HDT",
+"n HnD4Ta njC4E 48CnjE 4HjDn snH4D 4Cdn dnC4+ D;Hn 4Dgn 5Cdn dn>C Dd5n >Dgn ",
+"dnC4K 4+CdnK 4DdTn g4DTn dnj4C >ndjC dnj4D >ngsD PnC PCn! DPn aPDn nCP. Pn8",
+"C PnD. 8PDn QnC n!QC QDn DnQa QCnj QC8n DjQn QDsn nCP( Pn+C PnD( DP+n PnC(.",
+" +P8nC DPn(. +DP8n nCQ( +CQn Q(Dn QD+n PjCn( +Qn8C QDnj( sP+Dn WnC n!WC WDn",
+" DnWa nCW. WC8n W.Dn D8Wn WCQn WnQ!C ZnD DnZa WCnj W8nQC DnZj sDZn WCdn +CW",
+"n DdWn WDgn dPCn. +Wn8C WDnd. gPD8n QCdn +WnQC DdZn gDZn dPjnC +WnjC ZnDdj ",
+"gZnsD oC o!C oD oDa o5C o8C oD5 oD8 oQC Q!oC oDQ QDoa opC p8oC opD osD o;C ",
+"o+C oD; o+D 5;oC o>C 5Do; o>D Q;oC +QoC QDo; +QoD p;oC >Cop o;pD oDs> oWC W",
+"!oC oHD WDoa 5WoC W8oC H5oD H8oD WQoC o!WQC oZD ZDoa pWoC opW8C oDZp oDsZ o",
+"vC v+oC ovD goD v5oC >Cov o5vD oDg> vQoC ov+QC oDZv oDgZ oCpv o>pvC pvoD yo",
+"D bn bn& bnD cn bn. b8n b.Dn cn8 bnK bK&n bTn cnT bnj 8nbj Dnbj scn bn( b+n",
+" b(Dn cn+ n(b. +nb8 bnD(. +nc8 n(bK bK+n b(Tn +Tcn b(nj +nbj bTnj( s+cn bnE",
+" bE&n bHn cnH nEb. bE8n b.Hn H8cn nEbK &nEbK HnbT HncT bEnj &njbE Hnbj sHcn",
+" bdn +nbd Hnbd gcn b.dn 8dbn bHnd. g8cn bKdn d&nbK Tdbn gTcn dnbj d&nbj dnj",
+"bH gnsc 4bn bn4& bn4D c4n b5n bn48 5Dbn c5n 4Kbn &nK4b bn4T 4Tcn bn4j &nj4b",
+" 5Tbn c4sn b;n bn4+ D;bn c;n 5nb; >nb b5nD; c>n bK;n ;&nbK T;bn T;cn ;nbj b",
+"n>j ;njbT sc>n 4Ebn &nE4b bn4H 4Hcn bE5n 4b8nE H5bn H5cn 4bnEK 4bE&nK 4bHTn",
+" c4HTn 4bjnE &nE4bj 4bHnj c5nsH bn4d d&n4b H;bn c4gn 5dbn bd>n bH5dn gc>n 4",
+"bdnK d&Kb;n 4bTdn c;ngT dnj4b >nbdj ;njbH c>ngs bPn P&bn DPbn cPn Pnb. 8Pbn",
+" bPDn. 8Pcn bQn Q&bn QDbn cQn Qnbj Q8bn bQnDj cQsn Pnb( +Pbn bPDn( +Pcn bPn",
+"(. b+P8n DP(bn. cP+8n b(Qn +Qbn bQnD( +Qcn bQnj( b+Q8n Pj(bTn cQns+ bWn W&b",
+"n HPbn cWn b.Wn W8bn bHPn. W8cn WnbQ bWnQ& Zbn Zcn Wnbj &njbW bnZj snZc Wnb",
+"d +Wbn bHPdn cWgn bWnd. b+W8n dP.bHn cWng8 Qdbn d&nbQ bdZn gnZc dPjbn b+Wnj",
+" Zbndj Zcngs ob ob& obD oc ob5 ob8 b5oD oc5 obQ bQo& obT ocQ opb pbo8 pboD ",
+"osc ob; ob+ b;oD oc+ b5o; o>b ob5D; oc> bQo; b+oQ bTo; o+cQ o;pb p>ob opbD;",
+" c>os obW bWo& obH ocH b5oW bWo8 bHo5 oHc5 bWoQ obWQ& oZb ocZ oWpb opbW8 op",
+"Zb Zcos ovb vbo+ vboH goc o5vb v>ob ovbH5 c>go oQvb ovb+Q ovZb Zcgo pvob o>",
+"bpv oZbpv yoc 6n 6!n 6nB 6an 1n 68n 1nB 1an 6nK n!6K 6Tn Tn6a 6jn 8n6j 1Tn ",
+"s6n 6n( 6+n n(6B +n6a 1n( 1+n n(1B +n1a n(6K 6K+n 6(Tn +n6T 6(nj +n6j 1(Tn ",
+"6+sn 6nE n!6E 6Hn Hn6a 1nE 6E8n 1Hn H81n nE6K 6!nEK Hn6T 6HTan 6Enj njE68 H",
+"n6j 6Hsn 6dn +n6d Hn6d g6n 1dn +n1d Hn1d g1n 6Kdn dnK6+ Tn6d 6Tgn dn6j dnj6",
+"+ Td1n s6gn 46n 4n6! 6n4B 46an 7n 78n 7Bn 7an 6n4K 6!4nK 46Tn 4T6an 7nj 8n7",
+"j 7Tn 7sn 6;n +n6; 6B;n an6; 7;n >n7 ;n7B 7a>n 6K;n ;nK6+ Tn6; a;n6T ;n7j 7",
+"n>j T;7n >n7s 6n4E 6!4nE 46Hn 4H6an 7nE 8n7E 7Hn H87n 46nEK 4nE6!K 4H6Tn 6H",
+"T4an nj7E 78njE Hn7T 7Hsn dn6; 4+6dn Hn6; 6;gn 7dn 7d>n H;7n g7n dnK6; 4+6d",
+"nK 4Td6n g46Tn dn7j 7>dnj Td7n gn7s 6P 6P! 6PB 6aP 6P1 68P 6B1P 1a6P 6QP Q!",
+"6P 6TP Qa6P 6Pj Q86P 1T6P s6P 6P( 6+P P(6B +P6a 6(1P 1+6P 6P1(B 6+P1a 6(Qn ",
+"+Q6P 6(TP +T6P 6(Pj +Q1n 6TP1( 6+sP 6WP 6!Wn 6HP HP6a 1Wn W86P 1H6P H86P Wn",
+"6Q 6WQn! Z6P 6aZn Wn6j 6W8Qn Z1n Z6sP 6dP +W6P HP6d g6P 1d6P +W1n 6HP1d 68g",
+"P Qd6P 6+WQn 6dZn Z6gP Qd1n dPj6+ 1dZn s6gP o6 o!6 o6B oa6 7o 7o8 7oB 7oa o",
+"6Q 6Qo! oT6 6Qoa 7op o87p 7oT os7 o6; o+6 6;oB 6+oa 7o; o>7 o;7B 7ao> 6Qo; ",
+"6+oQ 6To; 6+oT 7;op 7po> 7;oT o>7s o6W 6Wo! oH6 6Hoa 7oW o87W 7oH oH7a 6WoQ",
+" o!6WQ oZ6 oaZ6 op7W 7opW8 7Zo os7Z ov6 v6o+ v6oH go6 7vo o>7v ov7H go7 oQv",
+"6 ov6+Q ovZ6 g6oZ op7v 7p>ov oZ7v yo7 9n 6&n 9nB 9an 9n1 :n 1B9n :na 9nK 6K",
+"&n 9Tn T&9n 9nj :nj 1T9n s:n 9n( 9+n n(9B +n9a 9(1n :n+ 9n1(B +n:a n(9K 9K+",
+"n 9(Tn +T9n 9(nj +n:j 9Tn1( s+:n 9nE 6E&n 9Hn H&9n 9E1n :nE 1H9n :Hn nE9K &",
+"nE6K Hn9T 6H&Tn 9Enj nj:E Hn9j :Hsn 9dn +n9d Hn9d g9n 1d9n :dn 9Hn1d g:n 9K",
+"dn d&n6K Td9n 9Tgn dn9j dn:j dnj9H gns: 49n 9n4& 4B9n 9n4a 79n 7:n 9n7B :n7",
+"a 4K9n &nK49 9n4T 49Tan 9n7j 7j:n 9T7n 7:sn 9;n 9n4+ 9B;n a;9n 9;7n >n: 7B9",
+";n :a>n 9K;n ;&n6K T;9n a;n9T ;n9j >j:n 7T9;n s:>n 4E9n &nE49 9n4H 49Han 9n",
+"7E 7E:n 9H7n :n7H 49nEK 49E&nK 49HTn 9Hn4T& 79njE 7:njE 7H9Tn 7:Hsn 9n4d d&",
+"n49 H;9n 49gn 9d7n :d>n 7H9dn >ng: 49dnK d&K9;n 49Tdn g49Tn 7d9nj 7:dnj 7Td",
+"9n g:n7s 6P9 6P& 6B9P 9a6P 1P9n :P6 6P19B 6a:P 9Qn Q&6P 9T6P Qa9n 9P6j :Qn ",
+"6TP9j :Qsn 6(9P 9+6P 6P9(B 6+P9a 6P19( 6+:P 1P(9nB :P6+a 9(Qn +Q9n 6TP9( 6+",
+"T9P 6Pj9( +Q:n Pj(9Tn :Qns+ 9Wn W&6P 9H6P HP6& 1W9n :Wn 6HP91 6H:P Wn9Q 6W&",
+"Qn Z9n 6PZ& Wn9j Wn:Q 9nZ1 Z:n 9d6P +W9n 6HP9d 6Pg9 6dP91 6d:P 1HP9dn :Wgn ",
+"Qd9n dP&6Q 9dZn Z9gn dPj9n Qd:n Z9n1d gnZ: o9 o9& o9B o9a 7o9 o: 7Bo9 o:a o",
+"9Q 6Qo& o9T 6To& op9 o:p o97T os: o9; o9+ 9;oB 9+oa 7;o9 o:> 7o9;B oa:> 9Qo",
+"; 9+oQ 9To; 9+oT o;p9 o>:p 7oT9; s:o> o9W 6Wo& o9H 6Ho& o97W o:W o97H o:H 9",
+"WoQ o9WQ& oZ9 o9Z& oWp9 op:W Z97o Z:o ov9 v6o& v9oH go9 o97v :vo 7oHv9 go: ",
+"oQv9 ov9+Q ovZ9 g9oZ pvo9 op:v oZ97v yo: 6nC n!6C 6Dn Dn6a 1nC 6C8n 1Dn D81",
+"n nC6K 6!nCK Dn6T 6DTan 6Cnj njC68 Dn6j 6Dsn nC6( 6C+n 6(Dn +n6D nC1( 1C+n ",
+"1(Dn +D1n 6nC(K 6+nCK 6DTn( 6+DTn njC6( 6+jnC 6Djn( sn+6D nC6E 6!nCE Hn6D 6",
+"HDan nC1E 68nCE Hn1D 6H8Dn 6nCEK n!C6EK 6HDTn HnD6Ta njC6E 68CnjE 6HjDn snH",
+"6D 6Cdn dnC6+ Dn6d 6Dgn 1Cdn 68dnC Dd1n 1Dgn dnC6K 6+CdnK 6DdTn g6DTn dnj6C",
+" dnC6+j dnj6D gs6Dn 6n4C 6!4nC 46Dn 4D6an 7nC 8n7C 7Dn D87n 46nCK 4nC6!K 4D",
+"T6n 6DT4an nj7C 78njC Dn7T 7Dsn 6C;n ;nC6+ Dn6; a;n6D ;n7C 7n>C D;7n 7D>n ;",
+"nC6K 6+C;nK 6D;Tn +Dn6T; ;nj7C 7>jnC 7DT;n 7s>Dn 46nCE 4nC6!E 4H6Dn 6HD4an ",
+"nC7E 78nCE Hn7D 7HD8n 6nC4EK 4n6!EKC 6HD4Tn 46anHDT 7njCE njC78E 7HDTn 7sHD",
+"n dnC6; 4+6dnC 4Dd6n g46Dn dn7C 7>dnC Dd7n 7Dgn 6dC;nK dn6;+CK Ddn6T; 6D;gn",
+"T 7dnjC >nj7dC 7DdTn g7sDn 6PC PC6! 6DP DP6a 6C1P 6C8P 1D6P D86P 6CQn 6QP!C",
+" QD6P 6QDaP 6CPj 6Q8PC QD1n 6DsP PC6( 6C+P 6(DP +D6P 6P1C( 6+P1C 6DP1( 6+D1",
+"P 6QPC( 6+QPC 6QDP( 6+QDP 6PjC( 6+PjC 6DPj( s6P+D 6CWn 6WP!C HP6D 6HPDa 1CW",
+"n 6W8PC WD1n 6H8DP 6WQPC WnC6Q! 6DZn Z6DaP 6WjPC PjC6W8 1DZn Z1nsD 6CdP 6+W",
+"PC Dd6P 6DgP 6dP1C 68dPC 6Dd1P g6P1D 6QdPC dPC6+Q Z6DdP gZ6DP dPj6C dPC6+j ",
+"Z1nDd Z1ngD o6C 6!oC oD6 6Doa 7oC 7Co8 7oD oD7a 6QoC o!6QC 6QoD oD6Qa 7Cop ",
+"7op8C op7D 7Dos 6;oC 6+oC 6Do; 6+oD o;7C >C7o 7;oD 7Do> o6Q;C o+6QC oD6Q; o",
+"+D6Q 7op;C 7p>oC 7oDp; os7>D 6WoC o!6WC 6HoD oH6Da oW7C 7oW8C oH7D 7oHD8 o6",
+"WQC 6WQo!C oDZ6 oZ6Da 7opWC op87WC 7DoZ osZ7D oCv6 ov6+C v6oD oDg6 7Cov 7vo",
+">C ov7D 7Dgo ov6QC v6Qo+C Zv6oD goZ6D 7vopC o>p7vC 7vDoZ 7oyD b6n 6&bn 9Dn ",
+"c6n b1n :nb 1Dbn :cn bK9n &nKb6 6Tbn 6Tcn 6jbn bn:j 1Tbn :csn b(9n 6+bn 9(D",
+"n 6+cn b(1n b+:n b1nD( :+cn b6n(K b6+nK b6Tn( c6+Tn b6jn( :nb+j b1Tn( :cns+",
+" bE9n &nEb6 6Hbn 6Hcn bE1n bn:E 1Hbn cn:H b6nEK b6E&nK b6HTn c6HTn b6jnE :n",
+"bjE b6Hnj :cnsH 6dbn d&nb6 Dd9n c6gn 1dbn bd:n b1Hdn :cgn b6dnK dnKb6+ b6Td",
+"n gc6Tn dnjb6 :dnbj dnj9D g:nsc bn49 4b6&n 9n4D 49cn 7bn :n7b bn7D 7cn 4b6n",
+"K 4b6&nK 4bT9n c46Tn bn7j 7:bnj bT7n sn7c 6;bn ;&nb6 D;9n 6;cn b;7n 7b>n 7b",
+"D;n >n7c b6;nK ;nKb6+ b6T;n c6;Tn 7b;nj 7>bnj 7bT;n c>n7s 4b6nE 4b6&nE 4bH9",
+"n c46Hn bn7E 7:bnE bH7n cn7H bnE49K 4Eb6&nK bHn49T 49HcnT 7bnjE :nj7bE 7bHT",
+"n 7csHn 4bd9n b6d;&n 49Ddn c6;gn bd7n 7:dbn 7bHdn gn7c dnKb6; dn4&b6K bTn49",
+"d c4Tg9n 7bdnj 7bj:dn 7bTdn g7csn b6P 6&bP 6DbP c6P 6Pb1 b6:P b6P1D c6:P 6Q",
+"bP b6QP& 6TbP 6QcP 6Pbj bQ:n b6T1P c6sP b(6P 6+bP b6PD( 6+cP b6P1( :Pb6+ b6",
+"(1DP :cP6+ b6QP( b6+Qn b6TP( c6Q+P b6Pj( :Qnb+ Pj(b6T :cQ+n 6WbP b6WP& 6HbP",
+" 6HcP 1Wbn bW:n b6H1P cW:n b6WQn 6W&bQn b6Zn c6Zn b6WPj :WnbQ b1Zn :cZn 6db",
+"P dP&b6 b6HdP c6gP b6d1P :Wnb+ 6HPb1d g:Pc6 b6QdP b6QdP& Zb6dP Zc6gP dPjb6 ",
+":Qdbn Zb1dn Z:ngc ob6 b6o& o9D oc6 7ob o:b ob7D 7co b6oQ ob6Q& b6oT o9cQ op",
+"7b ob:p ob7T os7c b6o; b6o+ 9Do; o9c; 7;ob 7bo> 7obD; c>o: ob6Q; ob+6Q obT6",
+"; oc6+Q 7obp; o:p>b 7obT; os:c> b6oW ob6W& b6oH o9cW ob7W ob:W ob7H 7Hoc ob",
+"6WQ b6Wo&Q obZ6 Z6oc 7obpW o:pbW 7boZ oc7Z vbo9 ovb6+ v9oD g6oc ov7b ob:v 7",
+"vboH 7cgo ovb6Q obQv6& oZbv6 cv6oZ 7vbop :vopb 7Zbov 7cyo Rn Rn! RnB Ran Rn",
+". R8n n.RB 8nRa Mn Mn! RTn aMn Rjn 8Mn TnRj sRn Rn( R+n n(RB +nRa n(R. +nR8",
+" Rn(.B R+8an Mn( +Mn R(Tn +nRT R(nj +nRj Mn(Tj R+sn RnE n!RE RHn HnRa nER. ",
+"RE8n R.Hn HnR8 MnE MEn! HMn aMHn REnj 8EMn HnRj RHsn Rdn +nRd HnRd gRn R.dn",
+" 8nRd dn.RH R8gn dMn dM+n TnRd gMn dnRj dM8n dMnHj sRgn R4 R4! R4B R4a R45 ",
+"R48 RB5n 48Ra R4M 4!Mn R4T 4TRa R4j 48Rj 4TR5 sR4 R4; R4+ RB;n 4+Ra 5nR; >n",
+"R ;nBR5 R4>a M;n 4MR+ 4TR; 4+RT 4jR; >Mn M;n5T sR>n R4E 4!RE R4H 4HRa RE5n ",
+"RE48 4HR5 4HR8 RE4M MnE4! 4HRT aMn4H RE4j R48ME 4HRj R4sH R4d 4+Rd 4HRd gR4",
+" 4dR5 R4>d R4H5d gR>n 4MRd dMn4+ 4TRd R4gM 4dRj dM>n dMnH5 gM>n RPn n!RP Pn",
+"RB RPan PnR. RP8n RPn.B aPnR8 Sn S!n STn San Snj S8n TnSj Ssn PnR( RP+n RPn",
+"(B aPnR+ RPn(. R+8Pn Pn(R.B R+8aPn Sn( S+n TnS( +TSn njS( +nS8 STnj( S+sn R",
+"Wn R!Wn HnRW WnRa R.Wn WnR8 RHWn. RH8Wn SWn WnS! SZn ZnSa WnSj W8Sn SjZn sn",
+"SZ WnRd +nRW RHWdn RWgn dP.Rn R+W8n RHWdn. gRW8n Sdn +WSn ZnSd gSn dnSj 8dS",
+"n SZdnj gnSs oR o!R oRB oaR oR5 o8R R5oB R5oa So So! SoT Soa Sop So8 oTSp o",
+"sS oR; o+R R;oB R+oa R5o; o>R oR5;B >Roa So; So+ oTS; o+Sa opS; S>o SpTo; o",
+"sS> oRW RWo! oHR RHoa R5oW RWo8 RHo5 RHo8 SoW o!SW oZS SaoZ SWop SWo8 SpoZ ",
+"oZSs ovR vRo+ vRoH goR o5vR vRo> ovRH5 gRo> Svo ovS+ oZSv goS opSv o>Sv SZp",
+"ov yoS Rn# R&n n#RB anR& n#R. 8nR& Rn#.B an&R8 Mn# M&n R#Tn TnR& R#nj M&8n ",
+"Mn#Tj R&sn n#R( +nR& Rn#(B an&R+ Rn#(. R+8&n n#(R.B R+8an& n#M( M&+n Mn#T( ",
+"aMn+& Mn#j( M&n+j RT#nj( sn+R& n#RE RE&n R#Hn HnR& Rn#E. &nER8 RHn#. RH8&n ",
+"n#ME ME&n H#Mn M&Hn Mn#jE M&n8E RHjn# snHR& R#dn dnR& dn#RH R&gn dn#R. d&nR",
+"8 RH#dn. gR8&n d#Mn M&dn dMnH# M&gn dMnj# dM&8n dM#Hnj gsR&n R4# R4& 4#RB 4",
+"aR& R#5n 48R& R45#B R48a& R#4M 4MR& R#4T 4TR& R#4j 4&Rj R4T5# R4s& R#;n 4+R",
+"& ;n#RB a;nR& ;n#R5 R4>& R5#;nB >nRa& M#;n ;&Mn M;nT# aM;&n M;n5# M&>n M;#5",
+"Tn >Mns& 4#RE RE4& R#4H 4HR& R45#E R48&E R4H5# R4H5& Mn#4E M&n4E R4HT# M&n4",
+"H R4j#E M&n5E R4Hj# sR4H& R#4d 4dR& R4Hd# R4g& R4d5# >nRd& dn#RH5 >ngR& dMn",
+"4# dM&R4 M;nH# gR4T& dMn5# >Mnd& dM#H5n >Mg&n PnR# RP&n RPn#B aP&Rn RPn#. P",
+"&nR8 Pn#R.B R8aP&n Sn# S&n TnS# T&Sn njS# 8nS& STnj# S&sn RPn#( P&nR+ Pn#R(",
+"B R+aP&n Pn#R(. R+8P&n .BR(Pn# aP8nR+& n#S( +nS& STn#( S+T&n Snj#( S+8&n nj",
+"#ST( Ss+&n R#Wn WnR& RHWn# RH&Wn RWn#. RW8&n Hn#RW. H8nRW& WnS# W&Sn S#Zn Z",
+"nS& SWnj# S8W&n SZnj# SZ&sn dP#Rn dP&Rn RHWdn# gRW&n RW#dn. RW8d&n dPHnR#. ",
+"RW8gn& dnS# d&Sn SZdn# S&gn Sdnj# S8d&n ZnjSd# gSs&n oR# o&R R#oB Rao& R5o#",
+" R5o& oR5#B o8Ra& So# So& S#oT oTS& S#op opS& SpTo# S&os R;o# R+o& oR;#B o+",
+"Ra& oR5;# >Ro& R5;o#B o>Ra& o;S# o+S& S;To# Sa;o& Sp;o# S&o> opTS;# os>S& R",
+"Wo# RWo& RHo# RHo& oR5W# o8RW& oHR5# oH8R& oWS# SWo& S#oZ S&oZ SpWo# Sp&oW ",
+"SZpo# osZS& o#vR vRo& ovRH# o&gR ovR5# o>vR& vR5oH# go>R& S#ov ovS& SvoZ# S",
+"&go Svop# Sv&o> oZpSv# Soy& Un Un! RDn Uan Un. U8n R.Dn D8Un UnM U!Mn Vn Vn",
+"a Unj 8MUn Vnj snV Un( U+n R(Dn +DUn n(U. +nU8 RDn(. R+D8n U(Mn +MUn Vn( V+",
+"n U(nj +nUj njV( V+sn UnE n!UE UHn HnUa nEU. UE8n U.Hn H8Un UEMn MnEU! VnH ",
+"HnVa UEnj U8nME HnVj sHVn Udn +nUd HnUd gUn U.dn 8dUn RDdn. U8gn dMUn dMnU+",
+" Vdn gVn dnUj dMnU8 dnVj sngV R4U 4!Un R4D 4URa U5n 4UR8 4DR5 4DR8 Un4M Mn!",
+"4U V4R R4Va 4URj R48Uj V5n V4sR U;n 4UR+ 4DR; 4+RD 5nU; >nU R4D5; R4>D M;Un",
+" M;nU+ V;n R4V+ ;nUj Un>M 5nV; V>n RE4U R4U!E 4URH R4HUa UE5n R48UE H5Un R4",
+"HU8 MnE4U 4UEMn! R4VH V4RHa R4jUE MnE4U8 H5Vn snV4H 4URd R4+Ud 4DRd R4gU 5d",
+"Un Ud>n R4D5d gU>n dMn4U 4U+dMn R4Vd V4gR dMnU5 >MnUd 5dVn >ngV UPn n!UP DP",
+"Un aPUn PnU. 8PUn RDPn. RD8Pn SUn UnS! SVn VnSa UnSj U8Sn SjVn snSV PnU( +P",
+"Un RDPn( R+DPn UPn(. U+P8n DP(Un. +DPU8n UnS( U+Sn S(Vn VnS+ SUnj( S+U8n SV",
+"nj( SV+sn UWn U!Wn HPUn WaUn U.Wn W8Un RWDn. RWD8n UWSn S!UWn ZnV ZaVn WnUj",
+" S8UWn ZjVn VZsn WnUd +WUn RWDdn UWgn UWnd. U+W8n dP.UHn gUP8n UdSn S+UWn V",
+"dZn SVgn SdUnj S8dUn SVdnj gVnSs oU oU! oUD oUa oU5 oU8 R5oD RDo8 SoU S!oU ",
+"oV oVa opU oUS8 oVp oVs oU; oU+ RDo; R+oD U5o; o>U oU5D; >RoD oUS; oUS+ oV;",
+" oV+ o;pU oUS> V;op oV> oUW UWo! oUH UHoa U5oW UWo8 UHo5 UHo8 SWoU oUWS! oV",
+"Z VZoa oWpU opUW8 VpoZ sZoV ovU vUo+ vRoD goU o5vU v>oU ovUH5 gUo> oUSv Svo",
+"U+ oVv goV pvoU o>USv opVv yoV Rbn U&n bnRD cRn R.bn bnR8 RbDn. R8cn bMn M&",
+"bn Vnb cnV bnRj 8Mbn bnVj cRsn R(bn bnR+ RbDn( R+cn Rbn(. Rb+8n bn(RD. cR+8",
+"n b(Mn +Mbn bnV( V+cn Rbjn( &njU+ Vnbj( snVc+ REbn UE&n bnRH RHcn RbnE. Rb8",
+"nE RbHn. cRH8n bEMn M&nbE bHVn cHVn RbjnE &njUE VnbHj snVcH bnRd d&Un RbHdn",
+" cRgn Rbdn. d&nU8 dn.RbH gcR8n dMbn dM&bn bdVn cngV dMnbj dMnb8 Vdnbj gVnsc",
+" R4b 4bR& 4bRD cR4 4bR5 4bR8 R4b5D R4c5 4MRb M&n4b R4Vb V4cR 4bRj M&nb5 b5V",
+"n cRs4 4bR; 4bR+ R4bD; R4c; R4b5; R4>b b5nRD; cR>n M;bn M;&bn b;Vn V;cn M;n",
+"b5 bM>n V5nb; cnV> RE4b R4b&E 4bRH R4cH R4b5E R4b8E R4bH5 cR4H5 R4bME M&ER4",
+"b V4RbH cR4VH R4bjE M&Eb5n V5nbH cR4sH 4bRd d&n4U R4bH; cRg4 R4b5d >nbRd 4b",
+"HR5d c>Rg4 dMn4b R4bdM& V4dRb gV4cR dMnb5 >Mbdn V5dbn V>ngc UPbn P&Un RbDPn",
+" UPcn RbPn. Rb8Pn bPnRD. cR8Pn Sbn bnS& VnSb Scn bnSj b8Sn SVbnj snSc RbPn(",
+" Rb+Pn bPnRD( cR+Pn UP(bn. U+Pb8n R(bPDn. U+Pcn8 bnS( b+Sn SVbn( cnS+ Sbnj(",
+" Sb+8n VnjSb( Scs+n bnRW W&Un RbHWn RWcn RbWn. RbW8n Rb.WDn cRW8n bWSn SbW&",
+"n ZnSb ZnSc SbWnj Sb8Wn SZbnj ZcnSs RbWdn dP&Un bWnRDd cRWgn dn.RbW b+nRW8 ",
+"R.bHWnd cW8gUn bdSn Sb+Wn SZbdn gnSc Sbdnj Sb8dn SbjVdn gScsn obR oU& RboD ",
+"ocR Rbo5 Rbo8 obR5D oUc5 Sob obS& oVb Sco opSb obS8 obVp osSc Rbo; Rbo+ obR",
+"D; oUc; obR5; >Rob Rb5oD; cRo> obS; obS+ V;ob S+oc Spbo; Sbo> oVpb; ocS> Rb",
+"oW UWo& RboH oUcW obR5W ob8RW obHR5 ocRH5 SWob oU&SW SboZ ZcoV SpboW Sb8oW ",
+"oVZpb oVsZc vRob vUo& ovbRH gRoc ovbR5 o>bvR ob5vRD cvRo> ovSb Svbo+ obVv S",
+"cgo Svbop S>bov oVvpb Scyo q q! qB qa q1 q8 q1B q8a qM q!M qT qTa lq q8l qT",
+"l sq q( q+ q(B q+a q1( q+1 1(qB 1+qa qM( q+M qT( q+T lq( l+q l(qT sq+ qE q!",
+"E qH qHa q1E q8E qH1 qH8 qME MEq! qHT HMqa lqE lEq8 lHq sqH qd q+d qHd gq q",
+"d1 q8d 1Hqd gq1 qdM +Mqd qTd gqT ldq q+ld qHld glq q4 q!4 q4B qa4 7q 7q8 7q",
+"B 7qa q4M 4Mq! qT4 4Tqa 7lq q87l 7qT sq7 q; q+4 q;B qa; 7q; q> 7Bq; q>a q;M",
+" 4+qM qT; 4+qT l;q q>l qTl; sq> q4E 4Eq! qH4 4Hqa 7qE 7Eq8 7qH qH7a 4MqE q!",
+"4ME 4HqT qH4aM lE7q 7lq8E 7qlH 7Hsq qd4 4+qd qH; gq4 7qd q>d qH7d gq7 4dqM ",
+"q+4dM 4Tqd qTg4 7qld ldq> qHl; sqg7 qP q!P qPB qaP q1P q8P 1PqB 1aqP Sq Sq!",
+" SqT Sqa Slq Sq8 qTSl sqS qP( q+P P(qB +Pqa 1Pq( 1+qP q1P(B q+1aP Sq( Sq+ S",
+"(qT q+Sa l(Sq Sql+ SlqT( S+sq qW qW! qHW qWa qW1 qW8 1HqW 1Wqa SqW S!qW Zq ",
+"Zqa lWq qWS8 Zql sqZ qWd q+W HPqd gqW 1Wqd 1+qW qH1dP qWg1 Sqd q+Sd Zqd gqZ",
+" Sqld q+lW ldZq sqgS oq oq! oqB oqa 7oq oq8 7Boq oq7a Soq S!oq oqT oqSa r r",
+"8 rT rs oq; oq+ oBq; q+oa q;7o q>o 7oq;B oaq> Sq; oqS+ qTS; q+oT r; r> r;T ",
+"rs> oqW o!qW oqH qHoa 7qW qWo8 oq7H qHo8 qWSo SqWo! Zqo oaZq rW rW8 rZ rZs ",
+"vq vq+ vqH goq vq7 vq> 7Hvq vqg7 vqS S+vq Zqv Zqgo rv rv> rZv yr q9 q& q9B ",
+"qa9 q91 :q 91qB :qa q9M q&M qT9 qT& lq9 :ql l9qT sq: q9( q+9 9(qB 9+qa 91q(",
+" :q+ q91(B :+qa 9Mq( 9+qM 9Tq( 9+qT q9l( l+:q qTl9( q+s: q9E q&E qH9 qH& 91",
+"qE :qE 9Hq1 :qH 9MqE M&qE 9HqT HMq& q9lE lE:q l9qH lH:q qd9 qd& 9Hqd gq9 9d",
+"q1 :qd qH91d gq: 9dqM dMq& 9Tqd qTg9 l9qd ld:q lHq9d g:sq q49 q&4 49qB 49qa",
+" 7q9 :q7 q97B 7a:q 49qM 4Mq& 49qT 4Tq& l97q 7l:q 79qT :q7s q;9 q;& 9;qB 9aq",
+"; 79q; q>: 7q9;B qa:> 9Mq; M;q& 9Tq; T;q& l9q; :ql> 7qT9; s:q> 49qE 4&qE 49",
+"qH 4Hq& q97E 7E:q 79qH 7H:q q49ME q&4ME qH49T qH&4T 7lq9E :ql7E 7qHl9 :qH7s",
+" 49qd 4dq& 9Hq; q;g9 79qd 7d:q 7qH9d g:q> qd49M qd&4M qH;9T gq49T 7qdl9 q>l",
+":d 7qT9d glq7: q9P q&P 9PqB 9aqP 9Pq1 :qP q91PB qa:P Sq9 Sq& qTS9 qTS& lqS9",
+" S:q Slq9T S:sq 9Pq( 9+qP q9P(B q+9aP q91P( q+:P 9P1q(B :q+aP q9S( q+S9 Sq9",
+"T( Sq+9T Slq9( S+:q qTlS9( sq:S+ qW9 qW& 9HqW 9Wqa 9Wq1 :qW qH91W qH:W qWS9",
+" qWS& Zq9 Zq& l9qW lW:q lqZ9 Zq: 9Wqd 9+qW qH9dP qWg9 qW19d q+:W 9HPqd1 gP:",
+"q qdS9 qdS& qdZ9 g9Zq Sqdl9 Sd:q Zql9d S:gq oq9 oq& q9oB qao9 o97q o:q 7oq9",
+"B oa:q So9 oqS& oTS9 o9Sa r9 r: r9T rs: q;o9 q+o9 oq9;B oq+9a 7oq9; q>o: o9",
+";7qB o:q>a o9S; o9S+ Sq;9T Sqa9; r;9 r:> 9Tr; s:r> qWo9 qWo& qHo9 qHo& 79qW",
+" 7W:q 7oHq9 oq:H SWo9 Sq&oW S9oZ oqZ& r9W r:W rZ9 rZ: vq9 vq& qHv9 g9vq v97",
+"q :vq vq79H :vgq S9vq S&vq Z9vq Sog9 rv9 r:v Zvr9 yr: qU q!U qD qDa q1U q8U",
+" qD1 qD8 qUM U!qM Vq Vqa lqU lUq8 Vql sqV qU( q+U qD( q+D 1Uq( 1Uq+ 1Dq( 1+",
+"qD UMq( U+qM Vq( Vq+ qUl( lUq+ l(Vq l+Vq qUE U!qE qHU UHqa 1UqE U8qE 1UqH U",
+"Hq8 UMqE q!UME VqH VHqa qUlE q8lUE lHVq qHVs qdU U+qd qDd gqU 1Uqd U8qd 1Dq",
+"d qDg1 UdqM q+UdM Vqd gqV lUqd l+qUd ldVq gVsq q4U 4Uq! qD4 4Uqa 7qU q87U 7",
+"qD qD7a 4UqM q!4UM Vq4 qaV4 lq7U 7lqU8 7Vq 7Vsq q;U 4Uq+ qD; 4+qD q;7U q>U ",
+"q;7D q>D U;qM q+4UM Vq; q+V4 lUq; lq>U l;Vq V>q 4UqE q!4UE 4UqH qH4Ua qU7E ",
+"7qU8E qH7U 7qHU8 q4UME 4UMq!E qHV4 Vq4Ha 7lqUE q8l7UE 7HVq sq7VH 4Uqd q+4Ud",
+" 4Dqd qDg4 qd7U >Uqd qD7d gUq> qd4UM 4U+qdM qHV; g4Vq 7qdlU q>lUd 7dVq 7Vgq",
+" qUP UPq! qDP UaqP 1UqP U8qP 1DqP D8qP SqU q!SU VqS SaVq lUSq SUq8 SlVq VqS",
+"s UPq( U+qP DPq( +DqP q1UP( q+1UP qD1P( q+D1P qUS( SUq+ S(Vq S+Vq SlqU( Sq+",
+"lU SlVq( Vq+Ss qWU UWq! qWD UWqa 1UqW UWq8 1WqD WDq8 SUqW SqUW! ZqV qaVZ lU",
+"qW Sq8UW lZVq sZVq UWqd U+qW WDqd qWgU qW1Ud q+W1U qWD1d gq1UW SUqd Sq+UW S",
+"dVq gVZq SqdlU Sq8Ud VqdlZ glqSV oqU q!oU oqD qDoa 7oU o87U oq7D oU7a oUSq ",
+"SqUo! oVq oaVq rU rU8 rV rVs q;oU q+oU q;oD q+oD 7;oU 7Uo> 7oUD; oDq> SUq; ",
+"Sq+oU S;Vq o+Vq r;U r>U rV; rV> qWoU oqUW! qHoU oqHUa oU7W 7oUW8 oU7H 7oUH8",
+" SqUoW oUWSq! oVZq oVZqa rUW UWr8 rZV sZrV vqU q+vU vqD gUvq 7Uvq vUq> 7Dvq",
+" 7ogU vUSq vqSU+ Vvq oVgq rvU v>rU rVv yrV tq tq& tqD cq tq1 :qt t1qD cq: t",
+"qM tMq& Vqt cqV ltq lt:q ltVq uq tq( tq+ t(qD cq+ q1t( t+:q tq1D( q+:c qMt(",
+" tMq+ t(Vq t+Vq l(tq tql+ Vqlt( uq+ tqE tEq& tqH cqH q1tE tE:q t1qH tH:q qM",
+"tE tqM&E tHVq qHVc lEtq :qltE tqlH uqH tqd q+td qHtd gqt t1qd td:q tqH1d g:",
+"cq tMqd tq+dM tdVq gVcq tqld :qdlt Vqdlt uqg tq4 q&t4 qDt4 cq4 7tq :q7t 7Dt",
+"q 7cq q4tM tq4M& t4Vq c4Vq 7ltq 7tl:q Vq7t uq7 tq; q+t4 qDt; cq; 7qt; t>q t",
+"q;7D cq> tMq; tq+4M t;Vq c;Vq tql; ltq> Vq;7t uq> q4tE tq4&E qHt4 qHc4 tE7q",
+" 7tq:E 7qtH 7Hcq tq4ME q&Mt4E tqHV4 cqV4H 7tlqE :ql7tE 7tHVq 7quH qdt4 tq+4",
+"d qHt; g4cq 7qtd tdq> 7tHqd t>gq tqd4M t4Mqd& Vqdt4 cq;gV 7tdlq t>qld 7Vdtq",
+" gqu7 tqP q&tP qDtP cqP q1tP tP:q tq1DP :Pcq Stq S&tq VqSt Scq Sqlt :qSt Sl",
+"Vtq uqS qPt( q+tP tqDP( q+cP tq1P( tq+:P qD1tP( cq:+P S(tq tqS+ StqV( S+cq ",
+"Stlq( St+:q VqlSt( Squ+ tqW q&tW qHtW cqW t1qW tW:q tqH1W :Wcq tWSq Sq&tW t",
+"Zq Zqc tqlW :qWSt ltZq uZq qWtd q+tW tqHdP gPcq tqW1d :qWt+ tW1qDd cqWg: Sd",
+"tq St+qW tdZq Scgq Stdlq S:dtq tZqld gquZ ot ot& otD otc ot7 ot: 7Dot ot7c ",
+"otS S&ot oVt otSc rt rt: rVt ur ot; ot+ oDt; t+oc 7ot; t>o ot7D; oct> S;ot ",
+"S+ot t;oV S;cq rt; rt> t;rV ur> otW o&tW otH tHoc 7otW tWo: 7otH tHo: tWSo ",
+"otSW& tZo octZ rtW t:rW rZt urZ tvo t+vq tHvq got 7tvq ot:v otH7v t>go Stvq",
+" ot+Sv Zqtv tZgo rtv tvr: tZrv ury <n n!< <nB a<n <n. 8<n n.<B a<8n <nK <Kn",
+"! T<n a<Tn <jn <j8n <jTn s<n n* +<n n*B an* n*. 8n* n.*B an8* n*K +Kn* Tn* ",
+"T<+n n*j <j+n njT* sn* <nE <En! H<n a<Hn nE<. <n8E <nH. 8<Hn nE<K n!<EK T<H",
+"n H<Tan <Enj <jn8E <jHn H<sn <dn <d+n Hn* g<n <.dn <d8n H.n* 8<gn dKn* <dn+",
+"K TnH* T<gn dn<j <dj+n n*Hj s<gn 4<n n!4< <n4B 4<an 5<n 8<5n <n5B a<5n <n4K",
+" 4<n!K 4<Tn 4Ta<n <j5n <jn48 T<5n 5<sn =n =+n =Bn =an =5n >n= 5n=B =a>n =nK",
+" +n=K =Tn +T=n =jn =j>n 5T=n s=n <n4E 4<n!E 4<Hn 4Ha<n <n5E 48<nE 5<Hn 4H8<",
+"n 4<nEK n!<4EK 4HT<n H<T4an <jn4E 48<njE 4Hj<n s<H5n =dn +n=d =Hn g=n 5d=n ",
+"=d>n H5=n >ng= dn=K =+dnK Hn=T gn=T dn=j >n=dj Hn=j gns= <P <P! <PB a<P <P.",
+" 8<P P.<B a<8P Q<P Q!<P T<P a<Qn <Pj 8<Qn <jTP s<P <P* +<P *B<P a<+P <.P* 8",
+"<+P <P*.B aP*8< Qn* Q<+P TnQ* T<+P P*<j 8nQ* <PjT* +<sP W<P W!<P H<P a<HP W",
+".<P 8<Wn H.<P 8<HP Q<Wn <P!WQ Z<P a<Zn <PWj <PjW8 <PZj Z<sP Wn* W<+P WnH* g",
+"<P W.n* 8nW* H<Pd. 8<gP QnW* +W<Qn Zn* Z<gP dP<j <dj+P n*Zj s<gP o< o!< o<B",
+" oa< o5< o8< 5<oB 5ao< oQ< Q<o! oT< Qao< op< p<o8 p<oT os< o= o=+ o=B =ao o",
+"=5 o>= o5=B =ao> =Qo o+=Q =To o+=T p=o p=o> op=T s=o oW< W<o! oH< H<oa 5Wo<",
+" W8o< H5o< H8o< W<oQ o!WQ< oZ< oaZ< oWp< opW8< opZ< s<oZ ov= v=o+ =Ho go= =",
+"5ov v>o= =5oH o>g= ov=Q ov=+Q Z=o Z=go ovp= o>pv= p=oZ yo= ,n ,n& ,nB ,an ,",
+"n. ,8n n.,B 8n,a ,nK ,K&n ,Tn T&,n ,nj 8n,j Tn,j sn, ,n* -n *B,n -na ,.n* -",
+"n8 n*.,B 8n-a ,Kn* -nK T*,n -Tn n*,j -nj n*j,T s-n ,nE ,E&n ,Hn H&,n nE,. ,",
+"E8n ,.Hn H8,n nE,K <&EnK Hn,T ,HnT& ,Enj <&jnE Hn,j ,Hsn ,dn -nd Hn,d g-n ,",
+".dn 8d-n ,Hnd. g8-n ,Kdn dn-K Td,n -Tgn dn,j dn-j dnj,H gns- ,4n 4&,n 4B,n ",
+"4a,n ,5n 48,n ,B5n 5a,n 4n,K <&K4n 4T,n ,4Tan 4j,n <&j5n 5T,n ,4sn =n, -=n ",
+",n=B -n=a ,5=n >n- =B5,n -a>n ,n=K =K-n ,T=n -n=T ,n=j -n=j =T5,n >ns- 4n,E",
+" <&E4n 4H,n ,4Han ,E5n ,48nE H5,n ,4H8n ,4nEK ,4E&nK ,4HTn 4H&,Tn ,4jnE <jE",
+"5&n ,4Hnj sn,4H ,d=n =d-n ,H=n -=gn 5d,n -d>n =H5,n g->n =dn,K -=dnK =HT,n ",
+"g=-Tn =jd,n >n-dj =Hj,n s-ng= ,P< <P& ,B<P a<,P ,.<P 8<,P <P.,B <P&8a ,Qn Q",
+"&,n Qn,T Qa,n Qn,j Q8,n <Pj,T ,Qsn P*,n -P< <P*,B a<-P <P*,. 8<-P ,P.n*B -P",
+"8a< Q*,n -Qn ,QnT* Qa-n <Pj,* Q8-n ,TPn*j -Qsn ,Wn W&,n H<,P Wa,n ,.Wn W8,n",
+" ,HP<. <P&H8 Wn,Q <P&WQ Zn, ,aZn Wn,j <P&Wj ,nZj Zns, Wn,d -Wn ,HP<d -Wgn ,",
+"Wnd. W8-n <d.,HP -Wng8 Qd,n Wn-Q ,dZn Z-n <dj,P Wn-j Zn*,j snZ- o, o&< o,B ",
+"oa, o,5 o8, ,5oB ,5oa o,Q ,Qo& oT, ,Qoa op, p<o& p,oT os, o=, o- =Bo, o-a =",
+"5o, o-> o=5,B ->oa o,=Q o-Q o,=T o-T o,p= o-p p=o,T os- o,W ,Wo& oH, ,Hoa ,",
+"5oW ,Wo8 ,Ho5 ,Ho8 ,WoQ o&W,Q oZ, oaZ, oWp, op&,W opZ, s,oZ ov, o-v o,=H go",
+"- o5v, -vo> ov,H5 g-o> oQv, -Qov ovZ, Z-o pvo, op-v oZ,p= yo- <nC <Cn! D<n ",
+"a<Dn nC<. <n8C <nD. 8<Dn nC<K n!<CK T<Dn D<aTn <Cnj <jn8C <jDn D<sn n*C +Cn",
+"* Dn* D<+n *Cn. 8Cn* D.n* 8nD* *CnK n*C+K TnD* an*DT nC*j n*j+C n*Dj Dns* n",
+"C<E n!<CE D<Hn H<Dan <nCE. 8<nCE H<Dn. H8<Dn <nCEK <CEn!K H<DTn D<aHnT <jnC",
+"E 8<CnjE H<jDn s<HDn <Cdn <dn+C DnH* D<gn <dnC. 8<dnC Hn*D. g<D8n <dnCK +<C",
+"dnK Hn*DT g<TDn <djnC <dC+nj <djDn sn*gD <n4C 4<n!C 4<Dn 4Da<n <n5C 48<nC D",
+"<5n 4D8<n 4<nCK n!<4CK 4DT<n D<a4Tn <jn4C 48<njC 4Dj<n s<D5n =nC +n=C =Dn +",
+"D=n 5n=C =n>C 5D=n =D>n nC=K =+nCK Dn=T =D+Tn nj=C >n=jC Dn=j sn=D 4<nCE n!",
+"<4CE 4HD<n H<D4an 5<nCE 8<C5nE H5<Dn 5D<H8n <nC4EK EK<!4nC H<D4Tn a<Hn4DT 5",
+"<CnjE <j5n8CE 5D<Hnj H5<snD dn=C =+dnC Hn=D gn=D =5dnC >n=dC =H5Dn g=>Dn =d",
+"nCK dnC=+K =HDTn g=DTn =jdnC =jd>nC =HjDn s=gDn <PC <!PC D<P a<DP PC<. 8C<P",
+" D.<P 8<DP QC<P <PCQ! D<Qn QD<aP <CPj <Pj8C <PDj D<sP <CP* +C<P <PD* D<+P <",
+"P*C. +<P8C D<P*. +D<8P QCn* +Q<PC DnQ* an*QD <Pj*C <Pj+C <PjD* s<P+D WC<P <",
+"PCW! D<HP H<PDa <PCW. W8<PC H<PD. H8<DP <PCWQ Q<CWn! D<Zn Z<DaP <PjWC <jCW8",
+"n Z<DPj s<PZD WCn* +W<PC DnW* D<gP Wn*C. W8n*C WDn*. g<PD8 Wn*QC <dC+Qn DnZ",
+"* Zn*gD <djPC <dC+Pj Zn*Dj s<PgD o<C <Co! oD< D<oa 5<oC 8<oC 5Do< D8o< Q<oC",
+" o!Q<C QDo< oDQa< oCp< op8<C p<oD oDs< o=C =Co+ =Do o+=D o5=C >Co= =5oD =Do",
+"> oQ=C o=+QC oD=Q o+D=Q =Cop o>p=C op=D =Dos W<oC o!W<C H<oD oHDa< o5W<C o8",
+"W<C oH5D< oH8D< oWQ<C W<Qo!C oDZ< oZDa< opW<C p<Wo8C Zp<oD osZD< =Cov ov=+C",
+" ov=D =Dgo ov=5C o>v=C ovD=5 go>=D ov=QC =Qvo+C =DoZ goZ=D p=ovC p=vo>C p=D",
+"oZ =Dyo ,nb <&bn ,Dn c<n ,.bn b8,n ,.Dn ,8cn ,Kbn <&Kbn bT,n ,Tcn bn,j <&jb",
+"n Dn,j c<sn bn* -nb Dnb* c-n b.n* b8-n ,Dn*. c8-n bKn* bn-K Tnb* -Tcn n*bj ",
+"bn-j n*j,D c-sn ,Ebn <&Ebn bH,n ,Hcn ,nbE. ,8nbE ,Hnb. c<H8n ,nbEK b<E&nK ,",
+"HnbT c<HTn ,njbE <&Ebnj ,Hnbj sn,cH bd,n bd-n Hnb* c-gn ,dnb. -nb8d ,Ddn. c",
+"-ng8 ,dnbK -nbdK ,DdTn c-ngT <djbn -njbd dnj,D s-ngc 4b,n ,4b&n 4D,n ,4cn b",
+"5,n ,48bn 5D,n ,5cn ,4bnK ,4b&nK ,4DTn c4T,n ,4jbn 4b8,nj ,4Dnj sn,c4 =bn -",
+"n=b ,D=n c=n b5=n =b>n =b5Dn >nc= bn=K =b-nK bT=n cn=T bn=j >n-bj =bT5n snc",
+"= ,4bnE ,4b&nE ,4Hbn c4H,n ,5nbE <&Eb5n ,H5bn c5<Hn 4bE,nK <&bn4EK 4bH,Tn ,",
+"4HcnT <jEb5n &n4jb<E 4bH,nj s<Hc5n bd=n =b-dn bH=n gnc= =b5dn >n-bd =bH5n c",
+"=g>n =bdnK -nd=bK =bHTn c=gTn =bjdn >nd=bj =bHnj s=cgn b<P <&bP D<,P c<P b.",
+"<P 8<bP ,DP<. 8<cP bQ,n <P&bQ QD,n ,Qcn <Pbj <P&bj <Pj,D c<sP <Pb* b<-P ,DP",
+"n* -Pc< b<P*. -Pb8< P*.,Dn c-P8< Qnb* bQ-n ,QDn* -Qcn <Pjb* -Qnb8 ,QDn*j s-",
+"Pc< bW,n <P&bW H<bP ,Wcn ,Wnb. ,W8bn ,WDn. cW<8P ,WnbQ W<&bQn ,DZn c<Zn <Pj",
+"bW bW8<Pj Zb<Pj Zc<sP Wnb* bW-n ,WDdn c<gP bWn*. -Wnb8 <d.,DP c-W8n ,Qdbn -",
+"WnbQ bnZ* c-Zn <djbP -Wnbj Zbn*j Z-nsc ob< b<o& oD, oc< ,5ob ,8ob ,5oD o8c<",
+" ,Qob obQ<& ,QoD oTc< pbo, opb,8 pDo, s<oc =bo o-b ob=D oc- =5ob =bo> =bo5D",
+" c>o- ob=Q -Qob ob=T =Qoc op=b ob-p p=boD ocs= ,Wob obW<& ,Hob oHc< ob5,W o",
+"b8,W obH,5 ocH,5 obW,Q bW<o&Q obZ< Z<oc opb,W obWp<& oZbp< oscZ< ov=b ob-v ",
+"ob=H c=go ovb=5 o-v>b ovD,5 cv=o> ovb=Q o-vbQ =boZ ocZ- p=bov o-pvb Z=bop o",
+"cy- 6<n n!6< <n6B 6<an 1<n 8<1n <n1B a<1n <n6K 6!<nK 6<Tn 6Ta<n <j1n <jn68 ",
+"T<1n 1<sn 6*n +n6* 6n*B an6* 1n* +<1n *B1n an1* 6Kn* n*K6+ Tn6* an*6T n*6j ",
+"n*j6+ Tn1* 6*sn <n6E 6!<nE 6<Hn 6Ha<n <n1E 68<nE H<1n 6H8<n 6<nEK n!<6EK 6H",
+"T<n H<T6an <jn6E 68<njE 6Hj<n s<H1n dn6* <dn6+ Hn6* 6*gn <d1n 68dn* Hn1* 1<",
+"gn <dn6K 6+<dnK 6H*Tn g6Tn* <dj1n 68dn*j n*j6H sn*g6 6<4n 6!4<n 46<nB 4a6<n",
+" 7<n 8<7n <n7B a<7n 46<nK 4<n6!K 4T6<n 6T<4an <j7n 78<nj T<7n 7<sn =6n 6+=n",
+" 6n=B 6a=n 7=n 7=>n =n7B =n7a 6n=K =6+nK 6T=n =T6+n 7n=j 7>=nj =n7T 7=sn 46",
+"<nE 4<n6!E 4H6<n 6H<4an <n7E 78<nE H<7n 7H8<n 6<n4EK 4<6!nEK 6H<4Tn a<Hn4T6",
+" 7<njE <jn78E 7HT<n 7sH<n 6d=n =6+dn 6H=n =6gn =n7d 7>=dn =n7H 7=gn =6dnK d",
+"nK=6+ =H6Tn g=6Tn 7=dnj >n=7dj 7Td=n g7s=n 6P< 6!<P 6B<P a<6P 1<P 8<6P 1B<P",
+" a<1P Q<6P <P!6Q T<6P 6Qa<P Q<1P <Pj68 T<1P 6Ps< 6P* +<6P *B6P aP6* 1P6* +<",
+"1P 6P*1B aP*68 Qn6* 6+Q<P TP6* aP*6Q Qn1* <Pj6+ P*j6T 6Ps* W<6P <P!6W H<6P ",
+"6HPa< W<1P 6W8<P H<1P 6H8<P 6WQ<P 6WQ<P! 6PZ< Z6a<P <Pj6W 6W8<Pj 1<Zn s<PZ6",
+" Wn6* 6+W<P HP6* 6Pg< Wn1* 6W8P* 6HP1* 1<gP 6W*Qn +Wn6Q* 6PZ* Z6*gP <dj6P 6",
+"+W<Pj 1nZ* s<Pg6 o6< 6!o< 6<oB 6ao< 7o< 7<o8 o<7B 7<oa 6Qo< o!6Q< 6To< oT6a",
+"< p<7o 7op8< 7<oT 7os< o=6 =6o+ o6=B =6oa 7o= 7=o> =B7o 7o=a o6=Q o=6+Q =6o",
+"T o+T=6 7op= 7o=p> 7o=T 7os= 6Wo< o!6W< 6Ho< oH6a< oW7< 7oW8< 7<oH 7oH8< o6",
+"WQ< 6WQo!< o6Z< oZ6a< 7opW< op87W< Z<7o osZ7< v6o= ov=6+ =6oH o=g6 ov7= 7o=",
+"v> 7o=H 7og= ov=6Q =Qvo+6 o=Z6 goZ=6 7o=pv o>p7v= 7oZ= 7oy= ?n ?&n ?Bn ?an ",
+"?1n ?:n 1n?B :n?a ?nK &n?K ?Tn T&?n ?jn :n?j 1T?n s?n ?n* ?-n n*?B -n?a 1n?",
+"* :-n ?B1n* :a-n n*?K ?K-n Tn?* -n?T n*?j -n?j ?T1n* ?-sn ?nE &n?E ?Hn H&?n",
+" 1n?E ?E:n 1H?n :n?H nE?K ?&nEK Hn?T ?HTan nj?E ?:njE Hn?j ?Hsn ?dn -n?d Hn",
+"?d g?n 1d?n :n?d ?H1dn ?:gn dn?K ?-dnK Td?n ?Tgn dn?j ?:dnj ?Hjdn gns? ?4n ",
+"4&?n 4n?B 4a?n 7?n :n7? ?n7B ?n7a 4n?K ?4&nK 4T?n ?T4an 7n?j ?:7nj ?n7T 7?s",
+"n ?=n -n?= ?B=n =n?a =n7? An ?=7nB Aan ?n=K ?-=nK =n?T ?-T=n =n?j Ajn ?T7=n",
+" Asn 4n?E ?4&nE 4H?n ?H4an 7n?E ?:7nE ?n7H ?:H7n ?4nEK &nE?4K ?H4Tn 4H&?Tn ",
+"?j7nE 7:n?jE ?H7Tn s?7Hn =n?d ?-=dn =n?H ?=gn ?n7d Adn ?H7=n Agn ?=dnK -=n?",
+"dK ?Td=n g?=Tn ?d7nj dnAj ?Hj=n gsAn ?P ?P& ?PB ?aP ?P1 ?:P 1P?B :P?a ?QP Q",
+"&?P ?TP Qa?P ?Pj :Q?P 1T?P s?P ?P* ?-P P*?B -P?a 1P?* :-?P ?P1*B ?:P-a Qn?*",
+" -Q?P TP?* -T?P P*?j -Q:n ?TP1* ?-sP ?WP W&?P ?HP HP?a 1W?P :W?P 1H?P :H?P ",
+"Wn?Q ?WQP& ?ZP Z&?P Wn?j ?:WQn Z1?P sP?Z ?dP -W?P HP?d g?P 1d?P :d?P ?HP1d ",
+"?:gP Qd?P ?-WQn Zn?d gP?Z dP?j ?:QdP ?Z1dP gPs? o? o?& o?B o?a o?7 o:? 7Bo?",
+" ?ao: o?Q o&?Q o?T oT?a ?po o:?p 7o?T s?o o?= o-? =Bo? =ao? 7o?= Ao 7o=?B A",
+"oa =Qo? ?Qo- =To? ?To- p=o? Aop o?Tp= Aos o?W o&?W o?H oH?a 7o?W ?Wo: 7o?H ",
+"?Ho: oW?Q o?WQ& ?Zo ?aoZ op?W o:?pW o?7Z os?Z ?vo o-?v =Ho? go? o?7v Aov o?",
+"H7v Aog ov?Q o-?vQ o?Z= ?Zgo op?v opAv ?Zo7v yAo <n6C 6!<nC 6<Dn 6Da<n <n1C",
+" 68<nC D<1n 6D8<n 6<nCK n!<6CK 6DT<n D<a6Tn <jn6C 68<njC 6Dj<n s<D1n 6Cn* n",
+"*C6+ Dn6* an*6D 1Cn* 68*nC Dn1* an*1D n*C6K 6+Cn*K 6D*Tn +Dn6T* n*j6C <jC1+",
+"n n*j6D sn*6D 6<nCE n!<6CE 6HD<n H<D6an 1<nCE 8<C1nE 1H<Dn H8<1Dn <nC6EK EK",
+"<!6nC H<D6Tn a<Hn6DT 1<CnjE <j1n8CE H<j1Dn 1H<snD <dn6C 6+<dnC 6H*Dn g6Dn* ",
+"1<dnC <dC1+n 1HnD* g1<Dn 6dCn*K <d+n6CK Ddn6T* 6D*gnT <jC1dn <d6j+nC 6Ddn*j",
+" s<Dg1n 46<nC 4<n6!C 4D6<n 6D<4an <n7C 78<nC D<7n 7D8<n 6<n4CK 4<6!nCK 6D<4",
+"Tn a<Dn4T6 7<njC <jn78C 7DT<n 7sD<n 6n=C =6+nC 6D=n =D6+n 7n=C 7>=nC =n7D 7",
+">D=n =6nCK 6+n=CK =D6Tn 6+D=Tn 7=njC >nj7=C =D7Tn s=7Dn 6<n4CE 4<6!nCE 6H<4",
+"Dn a<Hn4D6 7<nCE 8<n7CE 7HD<n H8<7Dn 6<4nEKC 6n4CEK<! T<Hn4D6 46T<HDan <jn7",
+"CE <j7n8CE H<j7Dn 7HDs<n =6dnC dnC=6+ =H6Dn g=6Dn 7=dnC >n=7dC 7Dd=n g7=Dn ",
+"dnC=6K dn=C6+K 6Dd=Tn g6D=Tn =jn7dC >j7d=nC 7Hn=Dj s=Dg7n 6C<P <PC6! D<6P 6",
+"DPa< 1C<P 68P<C D<1P 6D8<P <PC6Q 6QC<P! 6QD<P QD<6aP <Pj6C <PC6Q8 <Pj6D s<P",
+"6D 6CP* 6+P<C DP6* aP*6D 6P*1C 68P*C 6DP1* 6D8P* 6Q*PC <PC6+Q 6QDP* 6QDaP* ",
+"P*j6C <PC6+j P*j6D sP*6D <PC6W 6WC<P! 6HPD< WD<6aP 1W<PC <PC6W8 1H<DP H8<6D",
+"P 6WQ<PC QC<P6W! Z6D<P 6DPZ<a <PC6Wj <PWj68C Z1<DP s<DZ1n 6W*PC <dC6+P 6HPD",
+"* g6PD< 1Wn*C <dC68P 1WDn* g1<DP <PC6Qd 6C+WQn* Z6*DP Z6Dg<P <dC6Pj dP<j6+C",
+" Z1nD* s<Dg6P 6<oC o!6<C 6Do< oD6a< o<7C 7o8<C 7<oD 7oD8< o6Q<C 6Q<o!C oD6Q",
+"< 6QDoa< 7op<C o8<7pC 7oDp< os7D< o6=C o=6+C =6oD o+D=6 =C7o 7o=>C 7o=D o>D",
+"7= o=6QC =Q6o+C =QDo6 o+6=QD 7o=pC p=7o>C p=D7o s=o7D o6W<C 6W<o!C oH6D< 6W",
+"Doa< 7oW<C o8<7WC 7oHD< 7H<oD8 6WQo<C Q!oW6<C oZ6D< oD6Z<a op<7WC 78p<oWC 7",
+"ZoD< 7ZDos< ov=6C v=6o+C ovD=6 go=6D 7o=vC o>=7vC 7vDo= go7=D =Q6ovC =6o+vQ",
+"C Z=o6D Z=6goD p=o7vC >C7vp=o 7Z=oD yo7=D ?bn bn?& ?Dn ?cn b1?n ?b:n 1D?n :",
+"n?c bn?K ?b&nK bT?n cn?T bn?j ?:bnj Dn?j sn?c bn?* ?b-n Dn?* cn?- 1nb* :b-n",
+" ?D1n* c-:n ?bn*K ?-bnK ?DTn* ?-Tcn ?jbn* ?-jbn ?Djn* s-n?c bn?E ?b&nE bH?n",
+" cn?H ?b1nE ?:bnE ?Hb1n ?:Hcn ?bnEK &nE?bK ?HbTn ?cHTn ?jbnE :nb?jE ?Hjbn s",
+"?cHn bd?n ?-bdn Dd?n gn?c ?d1bn ?:dbn ?Dd1n g:n?c ?dbnK -nb?dK ?DdTn g?cTn ",
+"?djbn ?db-nj ?Ddnj g?scn 4b?n ?4b&n 4D?n ?4cn ?n7b ?:7bn ?n7D cn7? ?4bnK &n",
+"K?4b ?D4Tn ?c4Tn ?j7bn 7:b?jn ?D7Tn s?7cn ?b=n ?-=bn =n?D cn?= =n7b Abn ?D7",
+"=n Acn ?=nbK =bn?-K =bT?n c=?Tn =b7nj bnAj ?Dj=n scAn ?4bnE &nE?4b ?H4bn ?c",
+"4Hn 7?bnE 7bn?:E ?H7bn 7c?Hn 4bn?EK &n?E4bK 4bH?Tn c4H?Tn 7bn?jE 7j?E:nb ?H",
+"n7bT 7cHs?n ?=dbn =b-?dn ?Dd=n c=?gn ?d7bn bdAn ?D7dn gcAn =bn?dK =d-n?bK ?",
+"Hn=bT g?Tc=n ?dn=bj Adnbj ?Hn=bj Agnsc ?Pb bP?& ?DP ?cP b1?P ?b:P 1D?P :c?P",
+" bQ?P ?QbP& bT?P cQ?P bP?j ?:QbP DP?j sP?c bP?* ?b-P DP?* c-?P ?Pb1* ?:P-b ",
+"?DP1* ?cP:- ?QbP* ?-QbP ?QDP* ?cQ-P ?Pjb* ?-Pbj ?DP*j s?Pc- bW?P ?WbP& bH?P",
+" cW?P ?Wb1P ?:WbP ?HPb1 ?cW:P ?WbQn bWn?Q& Zb?P ?PZc ?WjbP ?Wb:Qn ?Zb1P s?Z",
+"cP bd?P ?-WbP Dd?P gP?c ?dPb1 ?:dbP ?Dd1P g?P:c ?QdbP ?Wb-Qn ?ZbdP g?ZcP ?d",
+"Pbj ?Wb-Pj ?DdPj g?scP o?b ?bo& o?D oc? 7bo? ob?: 7o?D ?co: ob?Q o?bQ& ob?T",
+" ?Qoc ob?p o:?pb op?D ocs? =bo? ob?- =Do? ?co- 7o=b Aob o?D7= Aoc o?=bQ o-?",
+"bQ o?D=Q oc?=Q p=bo? opAb ?pDo= osAc ob?W o?bW& ob?H ?Hoc ?W7ob o:?bW o?H7b",
+" o:H?c o?bWQ obW?Q& ?DoZ oc?Z ?pobW ?pbo:W ?Zo7b s?oZc ob?v o-?vb ov?D ocg?",
+" 7vbo? ovAb ?vD7o goAc ?vobQ ?vbo-Q ?Zo=b go?Zc ?pvob Aopvb ?pvoD yoAc R< R",
+"<! R<B Ra< R<. R8< <.RB 8<Ra R<M R!<M RT< T<Ra R<j 8<Rj T<Rj sR< R<* R+< *B",
+"R< +<Ra R.n* +<R8 n*.RB an*R8 Mn* +MR< T<R* +TR< <jR* +<Rj Mn*Tj R+s< R<E <",
+"ER! RH< H<Ra <ER. RE8< R.H< H8R< RE<M <MER! H<RT aMnH< RE<j R8<ME H<Rj RHs<",
+" R<d +<Rd H<Rd gR< R.<d 8<Rd RH<d. R8g< <MRd <dMR+ T<Rd RTg< <dRj <dMR8 <dj",
+"RH sRg< R4< 4!R< 4<RB 4aR< R5< 48R< RB5< 5aR< 4MR< <M!R4 4TR< aMn4< 4jR< R4",
+"8<M 5TR< R4s< =R =R+ =RB =Ra =R5 =R> R5=B >R=a =RM R+=M =RT R+=T =Rj =R>M R",
+"5=T s=R 4<RE R4<!E 4HR< R4Ha< RE5< R48<E H5R< R4H8< <MER4 R4E<M! R4HT< 4HMR",
+"a< R4j<E <MER48 R4H<j sR4H< =Rd R+=d =RH g=R R5=d =d>R RH=5 g>=R Rd=M =R+dM",
+" RH=T gR=T Rd=j >M=Rd RH=j gs=R R<P R!<P RB<P aPR< R.<P 8PR< <P.RB R8<aP S<",
+" S<! S<T Sa< S<j S8< T<Sj Ss< <PR* +PR< <P*RB aP*R< <P*R. R+<8P R<.P*B R8<a",
+"P* S<* S+< T<S* +TS< <jS* +<S8 S<T*j S+s< RW< R!W< H<RW WaR< R.W< W8R< RH<W",
+". RH8W< S<W W<S! SZ< Z<Sa W<Sj W8S< SjZ< s<SZ W<Rd +WR< RH<W* RWg< RW<d. R+",
+"W8< <P.RH* gR<W8 S<d +WS< Z<Sd gS< <dSj 8<Sd SZ<dj g<Ss oR< R<o! R<oB Rao< ",
+"R5o< R8o< oR5<B o8Ra< So< o!S< oTS< oaS< Sp< o8S< STp< s<So =Ro o+=R oR=B o",
+"a=R oR=5 =Ro> o=5RB o>=Ra S= S=+ S=T S=a S=p S>= Sp=T s=S RWo< o!RW< RHo< o",
+"HRa< 5WR< o8RW< oHR5< oH8R< oWS< S<Wo! S<oZ SZ<oa SWp< Sp<W8 ZpS< osZS< =Rv",
+" =+vR oH=R =Rgo =5vR v>=R =RvH5 g=Ro> S=v v=S+ S=Z gS= p=Sv v>S= SZp= y=S ,",
+"R< R<& RB,n Ra,n ,.R< R8,n ,R<.B ,R8a< ,Mn <MR& RT,n T<R& R<,j 8M,n ,RT<j ,",
+"Rs< R*,n -R< n*B,R Ra-n n*.,R R8-n ,R.n*B -R8a< M*,n -Mn Mn*,T RT-n Mn*,j R",
+"<-j ,RTn*j -Rs< ,ER< RE<& RH,n H<R& ,R<E. ,R8<E ,RH<. ,RH8< ,EMn <M&RE HM,n",
+" aMn,H ,Rj<E <&jRE ,RH<j sn,RH R<,d R<-d ,RH<d -Rg< ,Rd<. -R8<d <d.,RH g-R8",
+"< dM,n dM-n dMn,H -Mgn <dj,R -Rj<d ,RH<dj s-Rg< ,R4 R&,4 RB,4 R4,a R4,5 R4,",
+"8 ,R45B ,R45a R4,M <M&R4 R4,T aMn,4 R4,j <M&R5 ,R45T ,Rs4 =R, =R- ,R=B -R=a",
+" ,R=5 ->=R =R5,B >n-Ra ,R=M -R=M ,R=T -R=T ,R=j -R=j =RT,5 =Rs- ,ER4 ,R4&E ",
+"R4,H ,R4H& ,R45E ,R48E ,R4H5 ,R4H8 ,R4ME <MER4& ,R4HM ,4HaMn ,R4jE <MER5& ,",
+"R4Hj sR4,H ,R=d =d-R ,R=H g-=R =R5,d >n-Rd =RH,5 g=R-> =Rd,M =R-dM =RH,T g=",
+"R-T =Rj,d >M-dn =RH,j s=Rg- R<,P <PR& <PB,R <P&Ra <P.,R <P&R8 ,R.<PB R8<,aP",
+" S<, S<& ,TS< ,aS< ,nSj ,8S< S<T,j S<s, <P*,R R<-P ,R<P*B -Ra<P ,R<P*. -R8<",
+"P <PR*,.B R8<-Pa ,nS* S-< S<T,* -TS< S<*,j -nS8 n*jS,T s<S- RW,n W<R& ,RHW<",
+" <P&RH ,RW<. ,RW8< <P.,RH RH8<P& ,WS< W<S& Z<S, Z<S& S<W,j S8<,W SZ<,j Ss<Z",
+"& ,RW<d RW-n RH<,dP -RWg< <d.,RW -RW8< ,.RHWn* -R8g<P ,dS< -WS< SZ<,d g<S- ",
+"S<d,j S-W8< SdjZn, gS-s< o,R ,Ro& ,RoB ,Roa ,Ro5 ,Ro8 o,R5B o8,Ra So, o&S< ",
+"oTS, oaS, opS, o8S, Sp<,T s,So o,=R o-R o=,RB -Roa o=5,R -Ro> o,5=RB o->Ra ",
+"S=, S-o S,=T =TS- S,p= o-S> S=p,T S-s= ,RoW o&R,W ,RoH oH&,R o,R5W o8,RW oH",
+",R5 oH8,R SWo, S<&oW S,oZ oZ&S< Sp<,W Sp<W& oZ,Sp os,SZ vRo, =R-v ov,RH gRo",
+"- ov,R5 o-v>R =R5oH, go->R ovS, Svo- S,Z= S-go Sv,p= o-pSv S=Zp, S-yo R<U R",
+"!U< RD< UaR< R.U< U8R< R.D< D8R< <MUn <M!Un V<R RaV< U<Rj R8<Uj R<Vj V<sR U",
+"n* U+R< D<R* +DR< U.n* 8nU* RD<*. an*U8 MnU* Mn*U+ Vn* R+V< n*Uj Mn*U8 n*Vj",
+" Vns* REU< R<U!E UHR< RH<Ua R<UE. R8<UE RH<U. RH8U< <MEUn U<EMn! RHV< V<RHa",
+" R<jUE <MEU8n V<RHj s<VRH U<Rd R+<Ud HnU* RDg< R<dU. R8<Ud RD<d. gR<U8 <dMU",
+"n U+<dMn R<Vd V<gR <djUn U+<dnj V<dRj gV<sR 4UR< R4U<! 4DR< R4Da< U5R< R48U",
+"< 5DR< R4D8< R4U<M R4U<M! R4V< V4Ra< R4jU< 4U8R<j R5V< s<VR4 =RU R+=U =RD R",
+"+=D R5=U =U>n R5=D >R=D Un=M =RU+M V=R V+=R Rj=U >M=Un V5=R >nV= R4U<E 4UER",
+"<! R4HU< 4UHRa< R5<UE R4EU8< RH5U< 4UHR8< R4U<ME <MUn4E! V4RH< R4HV<a <MEU5",
+"n RE48U<j V5<RH s<HV5n Rd=U =RU+d RH=U gR=U =RU5d >nU=d =RHU5 g=R>U =RUdM d",
+"Mn=U+ Vd=R =RgV =RjUd >nd=Uj V=RH5 V>ng= U<P U!<P D<UP a<UP U.<P 8<UP RD<P.",
+" RD8<P S<U U<S! SV< V<Sa U<Sj U8S< SjV< SVs< <PU* +<UP RD<P* aP*U< U<P*. U+",
+"<8P <P.RD* U8<aP* U<S* U+S< V<S* V+S< S<U*j S+<U8 SV<*j Ss<V+ UWR< RW<U! H<",
+"UP RWDa< RW<U. RW8U< RWD<. RWD8< UWS< S<UW! Z<SV SZ<Va S<UWj S8<UW SZ<Vj Ss",
+"<VZ WnU* R+WU< RWD<d U<gP UWn*. UW8n* <d.RWD gU<8P U<Sd S+<UW V<Sd SVg< S<d",
+"Uj S8<Ud SV<dj gS<Vs oU< U<o! RDo< Uao< U5o< U8o< oU5D< oU8D< oUS< S<Uo! oV",
+"< V<oa pUS< Sp<U8 S<Vp s<oV =Uo o+=U oU=D oU=a =5oU =Uo> =RDo5 o>U=D S=U S+",
+"=U S=V =aoV Sp=U =US> VpS= oVs= UWo< oUW<! UHo< oUHa< oU5W< oU8W< oUH5< oUH",
+"8< S<UoW oUWS<! Z<oV oVZa< Sp<UW S8WpU< oVZp< oVsZ< ov=U ovU=+ oU=H =Ugo ov",
+"U=5 o>Uv= =Rv5D goU>= =USv S=vU+ oVZ= V=go p=USv S>=vU oVvp= S=yV ,Un b<R& ",
+"RD,n cR< ,.Un b8R< ,RD<. R8c< bM,n <M&Rb Vn, V<cR b<Rj <&jRb ,nVj cRs< b<R*",
+" -Un ,RDn* -Rc< ,Un*. U8-n n*.,RD c-R8< Mnb* bM-n ,nV* V-n Mn*bj Un-j Vn*,j",
+" snV- ,EUn ,Un&E bHR< RHc< ,UnE. ,U8nE ,UHn. cR<H8 ,UnME <MEU&n ,HVn cR<VH ",
+",UnjE <MERb8 Vn,Hj snV,H b<Rd Ud-n ,RD<d cRg< ,Udn. -Un8d <d.,RD cR<g8 <dMR",
+"b -UndM ,dVn gnV- <djRb -Undj Vdn,j V-ngs R4,U ,R4U& R4,D ,Rc4 b5R< ,R4b8 ,",
+"R45D R5c< ,R4bM ,4UM&n ,RV4 cR4V< ,R4bj ,4U&nj ,5Vn snV,4 =Rb -R=b ,R=D c=R",
+" Rb=5 -U>n =Rb5D =Rc> Rb=M =R-bM Vn=b =RV- Rb=j >M-bn V=R,5 >nV- ,R4bE <&ER",
+"4b ,R4bH cR4,H ,U5nE <&ERb5 ,UH5n cR5H< <MER4b <MR&4bE V4,RH cRHV4, <MERb5 ",
+"R4,jb8E V5n,H s<HcR4 Rb=d =R-bd Rb=H gc=R =Rb5d >n-Ud =RbH5 c=Rg> =RbdM =bd",
+"-Mn V=R,H c=VgR =Rbdj >Md=Rb =RbHj c=Rgs bPR< <PU& ,RD<P R<cP ,UP<. <P&U8 <",
+"P.,RD cR<8P Sb< b<S& V<Sb Sc< b<Sj b8S< SV<,j s<Sc ,UPn* U<-P b<PRD* c-R<P ",
+"<P.Rb* -UP8< <Pb*RD. c<8-UP b<S* -US< SV<b* S<V- Sb<*j S-b8< SbjVn* V-nSs b",
+"WR< <P&UW ,RWD< RWc< ,UWn. ,UW8n <P.,UH cRW8< bWS< Sb<W& ZbS< S<Zc Sb<Wj Sb",
+"8W< SZb<j Sc<sZ ,UWdn UW-n RWD,dn c-RW< <d.,UP -UW8n RW,D<d. cR8-Wn b<Sd S-",
+"bW< SZb<d g<Sc Sb<dj Sb8<d SbjZn* V-nsZ oU, ,Uo& ,RoD oUc< ,Uo5 ,Uo8 oU,5D ",
+"ocR,5 obS< Sb<o& oV, S<oc pbS< Spb8< o,Vp s,oV ob=R o-U =RboD =Roc =Rbo5 ->",
+"oU ob5=RD oc->R S=b =bS- =boV Sc= Sp=b =bS> oV,p= Scs= ,UoW oU&,W ,UoH ocR,",
+"H oU,5W oU8,W oUH,5 cR5W< Sb<oW S<WoU& Z,oV oV,Zc SpbW< SbWo8, oV,Zp oVsZ, ",
+"vR=b oU-v ovU,H =Rcv ovU,5 o-Uv> ob5=RH cv=>R =bSv o-USv SZ=b Z=Sc S=bpv o-",
+"pvU oVvp, Scy= q< q!< q<B qa< q1< q8< 1<qB 1aq< q<M <Mq! qT< T<qa l<q q8l< ",
+"qTl< sq< q* q+< q*B qa* q*1 q8* 1*qB 1aq* q*M +<qM qT* +Tq* l*q q+l< qTl* s",
+"q* q<E <Eq! qH< H<qa 1<qE 8<qE 1Hq< H8q< <MqE q!<ME H<qT qHTa< q<lE l<q8E q",
+"Hl< qHs< qd< +<qd qH* gq< 1<qd 8<qd 1Hq* q8g< <dqM q+<dM HMq* qTg< qdl< l+q",
+"<d qHl* l<gq q4< 4<q! 4<qB 4aq< 7q< 7<q8 q<7B 7<qa 4Mq< q!4<M 4Tq< qT4a< 7q",
+"l< 7lq8< 7<qT 7qs< q= q=+ q=B q=a q=7 q>= =B7q =aq> q=M q+=M q=T q+=T l=q q",
+">l= 7q=T sq= 4<qE q!4<E 4Hq< qH4a< q<7E 7q8<E 7<qH 7qH8< q4<ME <MEq!4 qH4T<",
+" 4HMqa< 7lq<E l<87qE 7qHl< sq7H< q=d =+qd q=H gq= 7dq= >=qd 7q=H g=q> qd=M ",
+"q=+dM qH=T =Tgq ldq= q>l=d lHq= l=gq q<P <Pq! <PqB a<qP 1<qP 8<qP q1<PB q8a",
+"<P Sq< q!S< qTS< qaS< l<S S8l< lTS< l<Ss q*P +<qP P*qB aPq* 1Pq* 8Pq* q*1PB",
+" q8*aP Sq* q+S< qTS* qaS* Sql* S+l< Sq*lT s*Sq qW< W<q! H<qW Waq< 1Wq< W8q<",
+" qH1W< qH8W< qWS< SqW<! Zq< qaZ< S<lW Sq8W< l<Zq s<Zq qW* +Wq* HPq* qWg< 1W",
+"q* W8q* qH*1W gq1W< qWS* Sq+W< Zq* g<Zq S<ld Sq8W* l*Zq l<gS oq< o<q! q<oB ",
+"o<qa 7<oq o<q8 7oq<B 7oaq< oqS< Sq<o! o<qT Sqao< r< r8< rT< rs< q=o o+q= =B",
+"oq oq=a 7oq= q=o> 7o=qB q>o=a S=q S+q= Sq=T Sq=a r= r>= r=T rs= o<qW oqW<! ",
+"o<qH oqHa< 7<qW 7qW8< 7oHq< 7qWa< SqWo< oqWS<! oqZ< Zqoa< rW< W8r< rZ< sZr<",
+" vq= q+v= =Hvq g=vq q=7v v>q= vq7=H vq>g= vqS= vq=S+ Zq= S=gq rv= v>r= rZ= ",
+"yr= ?q ?q& ?qB ?qa ?q1 :q? q1?B ?a:q ?qM q&?M ?qT qT?a l?q l?:q qTl? s?q ?q",
+"* -q ?Bq* -qa ?1q* -q: ?q1*B qa:- q*?M -qM q*?T -qT ?ql* l-q ?qTl* sq- ?qE ",
+"?Eq& ?qH qH?a q1?E ?E:q ?1qH ?H:q qM?E ?qM&E qH?T ?qHT& lE?q :ql?E ?qlH ?Hs",
+"q ?qd -qd qH?d g?q ?1qd ?d:q ?qH1d g:-q qd?M qd-M qT?d gM-q ?qld ld-q l?Hqd",
+" gql- ?q4 ?4q& q4?B ?4qa ?q7 7?:q 7B?q 7q?a q4?M ?q4M& ?4qT ?qT4a 7l?q ?q7l",
+": 7q?T ?q7s q=? -q= =B?q =a-q 7?q= Aq ?q7=B Aqa ?q=M =M-q ?q=T =T-q l?q= Al",
+"q l=?qT Aqs q4?E ?q4&E ?4qH ?qH4a ?E7q ?q7:E 7q?H :qH7? ?q4ME q&4?ME ?qH4T ",
+"?H4qT& ?q7lE l?7:qE l?H7q s?q7H ?dq= qd-= ?q=H g=-q 7q?d Aqd q=H7? Aqg ?qd=",
+"M -q=dM q=H?T -qTg= l=?qd ldAq l=H?q glAq ?qP q&?P qP?B qa?P q1?P ?P:q ?q1P",
+"B ?qa:P S? S?& S?T S?a S?l S?: ?TSl s?S q*?P -qP ?qP*B qa-P ?q1P* :P-q q*1?",
+"PB -q:aP S?* S?- S*?T ?TS- l*S? S?l- S?lT* S-s? ?qW q&?W qH?W qW?a ?1qW ?W:",
+"q ?qH1W :qH?W S?W S&?W S?Z ?aZq lWS? ?WS: l?Zq ?Zsq qW?d -qW ?qHW* gP-q ?qW",
+"1d :W-q ?H1qW* -qWg: S?d ?WS- ?dZq g?S ldS? lW-q S?Zld s?gS o?q o&?q ?Boq o",
+"q?a 7o?q o?:q ?q7oB o:?qa S?o S&o? ?TSo ?aSo r? r?: r?T r?s q=o? o-q o?q=B ",
+"oa-q ?q7o= Aoq q=7o?B oqAa S?= o-S? =TS? =aS? r?= Ar =Tr? Ars oq?W ?qWo& oq",
+"?H o?Hqa 7q?W o:?qW o?H7q o:H?q ?WSo S?oW& o?Zq S?Zoa r?W ?:rW r?Z s?rZ ?vq",
+" -qv ?Hvq ?vgq ?q7v Aqv ?vq7H goAq S?v S-?v S=?Z S?go r?v Arv ?Zrv Ary qU< ",
+"U<q! qD< Uaq< 1Uq< U8q< 1Dq< D8q< U<qM q!U<M Vq< qaV< qUl< l<qU8 l<Vq s<Vq ",
+"q*U U+q* qD* Uaq* 1Uq* U8q* 1Dq* D8q* U*qM q+U<M Vq* q+V< lUq* l+qU< l*Vq s",
+"*Vq U<qE q!U<E UHq< qHUa< q1U<E q8U<E qH1U< qH8U< qU<ME <MEq!U qHV< VqHa< l",
+"<qUE q8Ul<E VqlH< sqVH< U<qd q+U<d UHq* qDg< qd1U< q8dU< qH*1U gq1U< qdU<M ",
+"<dMq+U qHV* g<Vq l<dqU l<Uq8d Vqdl< glqV< 4Uq< q!4U< 4Dq< qD4a< qU7< 7qU8< ",
+"7<qD 7qD8< q4U<M <M!q4U q4V< Vq4a< 7lqU< l<q7U8 V<7q sq7V< q=U q+=U q=D q+=",
+"D 7q=U =Uq> 7q=D =Dq> qU=M q=U+M V=q =aVq lq=U q>l=U Vql= V=sq q4U<E 4U<q!E",
+" qH4U< 4UHqa< 7qU<E q8<7UE 7qHU< 7U<qH8 <MEq4U <Mq!4UE Vq4H< qH4V<a l<q7UE ",
+"lUq87<E 7VqH< 7VHsq< qd=U q=U+d qH=U =Ugq 7qd=U q>=Ud q=H7U q>Dg= q=UdM q+U",
+"=Md =HVq V=gq l=qUd l=Uq>d V=qlH V>qg= U<qP q!U<P D<qP qDa<P U<1P q8U<P qD1",
+"<P qD8<P qUS< SqU<! S<Vq SqaV< lUS< Sq8U< SVl< Ss<Vq UPq* q+U<P DPq* q+D<P ",
+"q*1UP q8*UP qD*1P qD8P* SUq* Sq+U< S*Vq Vq+S< Sq*lU Sq8U* Vq*Sl sq*SV UWq< ",
+"qWU<! WDq< qWDa< qW1U< qW8U< qWD1< qWD8< SqUW< qWUS<! Z<Vq ZqVa< lWqU< S8Ul",
+"W< lZ<Vq sqZV< UWq* q+WU< WDq* gqUW< qW*1U qW8U* qWD1* g1U<P SqdU< S+UqW* Z",
+"*Vq gqZV< S<dlU S+UlW< Zq*Vl glSV< qUo< oqU<! o<qD oqDa< 7<oU 7oU8< 7oUD< 7",
+"oUa< SqUo< oqUS<! V<oq oVqa< rU< U8r< rV< s<rV oq=U q=oU+ oq=D q=Do+ 7o=U q",
+">o=U q=D7o q>Do= Sq=U S=qU+ VqS= oV+q= r=U =Ur> rV= s=rV oqUW< qW<oU! oqHU<",
+" oU<qWa 7oUW< 7U<qW8 7oUH< 7U<oH8 oqUS<W S!oqUW< oVZq< ZqaoV< UWr< rU8W< Z<",
+"rV rZVs< =Uvq vq=U+ =Dvq vqDg= vq7=U vq>=U vqD7= vq>=D vq=SU S=Uvq+ V=Zq Vv",
+"qg= =Urv rv>=U Z=rV y=rV ?qt q&?t ?qD cq? ?1tq ?t:q ?1qD :q?c tq?M ?qtM& V?",
+"q V?cq ?qlt ?t:lq l?Vq u?q tq* -qt qDt* cq- t1q* :qt- ?qD1* :c-q tMq* -Mtq ",
+"t*Vq V-q tql* lt-q V?lq* uq- ?Etq ?qt&E tq?H ?Hcq ?qt1E ?t:qE ?qHt1 cq?:H ?",
+"qtME tq&?ME ?HVq cq?VH l?qtE l?t:qE V?lqH ?quH tq?d td-q qHt* cqg? ?qdt1 -q",
+"t:d ?qD1d cq-g: ?qdtM -qtdM ?dVq V?gq l?dtq l-qtd V?dlq g?uq t4?q ?qt4& ?4q",
+"D c4?q ?q7t ?q7t: 7q?D ?q7c ?qt4M tq4?M& V4?q cq?V4 ?q7lt :ql7t? ?q7V ?qu7 ",
+"t=q -qt= ?q=D cq= q=7t Aqt q=D7t Aqc tq=M -qt=M Vqt= V=cq ltq= ltAq V=q7t A",
+"uq ?qt4E t4&?qE ?qHt4 cq?4H ?q7tE :q?7tE 7tH?q 7cq?H tq4?ME M&?Etq4 V?q4H V",
+"?4cqH l?q7tE lE7t:q? 7V?qH u?q7H tdq= -qt=d tq=H t=gq 7tdq= tqAd t=H7q gqAt",
+" t=qdM t=d-qM V?dq= cq=gV l=tqd Aqdlt V?d7q uqAg ?tP ?&tP tP?D ?Pcq ?1tP t:",
+"?P ?qD1P cq?:P S?t S&?t S?V S?c l?St ?tS: SlV? u?S t*?P ?Pt- ?qDP* cP-q ?tP",
+"1* -qt:P ?D1tP* cq-:P S*?t St-q S*V? cqS- St*l? l-qSt S?Vl* S?u- tq?W ?qWt&",
+" tH?P ?Wcq ?qWt1 :qW?t ?qW1D cqW?: ?WSt S?tW& tZS? Sc?Z l?WSt S?:tW S?Zlt S",
+"?uZ td?P tW-q ?qWDd ?tgP ?td1P -qWt: ?H1tdP cq-:W ?dSt -qWSt ?dSV S?gt S?dl",
+"t -qWlt V?dSl g?uS ot? o&?t ?Dot ?cot o?7t ?to: ot?7D ot:?c otS? ot?S& oV? ",
+"ocS? r?t ?tr: r?V ur? t=o ot- =Dot oct= 7ot= Aot t=o7D otAc S=t t=S- oVt= t",
+"=Sc rt= Art t=rV Aru ?Wot ot?W& ?Hot otc?H ot?7W ot:?W otH7? ot:?H ot?SW S?",
+"Wot& oV?Z oV?Zc ?trW r?t:W ?ZrV r?uZ ot?v o-tv =Hot t=go ?vq7t tvAo otH7= g",
+"oAt tvS? ot-Sv tZS= ?vSc ?vrt rtAv ?vrV yAur Xn n!X XnB aXn Xn. 8Xn n.XB aX",
+"8n XnK XKn! TXn aXTn Xjn Xj8n XjTn sXn Xn( +Xn n(XB aX+n n(X. 8X+n Xn(.B aX",
+"n+8 n(XK Xn+K XnT( TX+n X(nj Xj+n XjnT( +Xsn Gn Gn! GnH Gan Gn. G8n G.Hn H8",
+"Gn GnK n!GK GTn TnGa Gnj 8nGj HnGj sGn Gnd +Gn dXHn gXn G.dn G8+n dX.Hn G8g",
+"n GKdn GK+n TdGn GTgn dnGj Gn+j dXjHn sGgn 4X 4X! 4XB 4aX 4X5 48X 4B5X 5a4X",
+" 4XK XK4! 4TX TX4a 4Xj 8X4j 5T4X s4X 4X; 4+X 4BX; +X4a X;5n >X4 X;B5n 4a>X ",
+"4KX; 4K+X T;4X +T4X X;4j 4X>j X;j4T s4>X 4GX 4!Gn 4HX Ga4X G5n G84X H54X H8",
+"4X 4KGn 4GX!K GT4X 4GTaX Gn4j 4G8Xj HX4j 4GsX 4dX +G4X HX4d g4X 5d4X >nG 4H",
+"X5d g4>X 4KdX 4+GXK Td4X 4TgX dX4j Gn>j dXj4H s4gX XPn XPn! PnXB XPan PnX. ",
+"XP8n XPn.B aXP8n QXn n!QX TXQn aXQn XjQn 8XQn XjnTP QXsn PnX( XP+n XPn(B aX",
+"P+n XPn(. +X8Pn Pn(X.B +X8aPn XnQ( QX+n QXnT( +QXTn XjnQ( +QX8n QXTnj( sX+Q",
+"n Yn Yn! YHn Yan Yn. Y8n HnY. H8Yn YQn QnY! YZn ZnYa Yjn Q8Yn ZnYj sYn Ydn ",
+"Y+n HnYd gYn dnY. +nY8 YHdn. Y8gn QdYn +QYn YdZn YZgn dnYj +nYj YZdnj gnsY ",
+"oX o!X oXB oaX o5X o8X 5XoB 5aoX oQX QXo! oTX QaoX opX pXo8 pXoT osX oX; o+",
+"X X;oB +Xoa 5Xo; o>X o5X;B oa>X QXo; +QoX TXo; +ToX o;pX op>X opTX; >Xos oY",
+" oY! oYH Yao Y5o Y8o oHY5 oHY8 oYQ YQo! oZY YaoZ Ypo opY8 oZYp sYo Yvo Y+o ",
+"oHYv goY ovY5 Y>o YvoH5 Y>go YQov YQo+ YvoZ oZgY opYv o>Yp YZvop yoY Xn# X&",
+"n n#XB X&an n#X. X&8n Xn#.B aXn8& n#XK XK&n XnT# X&Tn X#nj &nXj XjnT# X&sn ",
+"n#X( X&+n Xn#(B aXn+& Xn#(. X&n+8 n#(X.B +X8an& Xn#(K X&n+K TXn#( +TX&n Xjn",
+"#( X&j+n TX#nj( sX+&n Gn# G&n G#Hn H&Gn n#G. 8nG& GnH#. G8nH& n#GK GK&n G#T",
+"n T&Gn G#nj &nGj GTnj# G&sn G#dn G&+n dX#Hn G&gn dX#n. dX&8n HX#dn. gX8&n d",
+"X#nK dX&nK GTnd# gXT&n dXjn# dX&nj dX#Hnj gsX&n 4X# 4X& X#4B aX4& 4#5X 5X4&",
+" 4X5#B 48Xa& X#4K 4KX& 4#TX TX4& 4#Xj X&4j 4TX5# 4Xs& 4#X; +X4& X;#4B aX;4&",
+" X;#5n 4X>& 5X#;nB >X4a& X;#4K X;&4K 4TX;# X;&4T X;j4# >X4&j X;#5Tn >Xs4& 4",
+"#Gn G&4X 4#HX HX4& G#5n 5&Gn 4HX5# 4H8X& 4GX#K 4G&XK 4GTX# 4GTX& 4GjX# X&j4",
+"G 4HXj# s4GX& 4#dX dX4& 4HXd# 4Xg& 4dX5# G&>n dX#H5n >Xg4& 4dX#K dX&4K 4TdX",
+"# g4XT& dXj4# >nG&j dX#4Hj >nsG& PnX# XP&n XPn#B aXP&n XPn#. X&P8n Pn#X.B 8",
+"XaP&n XnQ# X&Qn QXnT# QaX&n XjnQ# X&jQn QXTnj# sXQ&n XPn#( X&P+n Pn#X(B +Xa",
+"P&n Pn#X(. +X8P&n .BX(Pn# aX+P8n& QXn#( +QX&n TX#Qn( QX&+Tn QX#nj( +QX&nj Q",
+"#TnXj( +QXsn& Yn# Y&n HnY# H&Yn n#Y. 8nY& YHn#. Y8H&n QnY# Q&Yn Y#Zn ZnY& n",
+"jY# &nYj YZnj# Y&sn dnY# +nY& YHdn# Y&gn Ydn#. Y+8&n dn#YH. gY8&n YQdn# Y+Q",
+"&n YZdn# gYZ&n Yjdn# Y+j&n ZndYj# sYg&n oX# o&X X#oB aXo& 5Xo# 5Xo& o5X#B o",
+"8aX& QXo# QXo& TXo# TXo& o#pX pXo& opTX# o&sX X;o# +Xo& oX;#B o+aX& o5X;# o",
+"&>X X;#o5B o>aX& oQX;# o+QX& oTX;# o+TX& opX;# o>pX& pX;oT# os>X& oY# Y&o Y",
+"#oH oHY& o5Y# o8Y& Y5oH# Y5ao& oQY# YQo& Y#oZ Y&oZ Y#op opY& YpoZ# Y&os Y#o",
+"v ovY& YvoH# Y&go Yvo5# Y&o> ovHY5# goY>& YvoQ# Yv&oQ YZvo# goZY& Ypov# Yp&",
+"o> oZvYp# Y&yo In In! DXn aIn In. 8In D.In 8IDn InK IKn! TIn aITn Inj Ij8n ",
+"InDj sIn In( +In D(In DX+n n(I. 8I+n In(D. +DX8n n(IK +KIn T(In TI+n I(nj I",
+"n+j InjD( +Isn GnI G!In Jn Jna G.In 8IGn Jn. J8n GKIn InKG! JnT TnJa InGj I",
+"njG8 Jnj sJn Idn Gn+I Jnd gJn I.dn Id8n dnJ. J8gn dKIn Idn+K TdJn gTJn dnIj",
+" Idn+j dnJj gnsJ 4IX 4!In 4DX DX4a 5In 8I4X 5D4X D84X 4KIn InK4! DX4T 4DXTa",
+" In4j Inj48 DX4j 4DsX I;n +I4X D;4X +D4X I;5n >nI I;n5D 4D>X IK;n I;n+K I;T",
+"n a;nTI ;nIj In>j I;n5T sI>n Gn4I In!4G J4X 4aJn 5IGn 4G8In J5n 48Jn InK4G ",
+"4GKIn! 4TJn J4TaX Inj4G 4G8Inj 4XJj J4sX Id4X Idn4+ J;n J4gX Id5n Gn>I 5dJn",
+" J>n Idn4K IdK4+X T;Jn gJ4TX Idn4j >nGIj ;nJj >nsJ IPn n!IP IPDn IPan PnI. ",
+"IP8n IPnD. D8XPn QIn Q!In DXQn aIQn IjQn 8IQn IPjDn QIsn PnI( IP+n IPnD( +D",
+"XPn IPn(. +IP8n DP(In. D8P+In Q(In QI+n QDXn( +QDIn IPjn( IPj+n IP(Dnj sIP+",
+"n YIn InY! YJn JnYa InY. 8IYn Y.Jn JnY8 QIYn YQIn! ZJn ZaJn InYj Y8QIn JnYj",
+" YJsn IdYn +IYn YdJn YJgn IdnY. Y+8In YJdn. gYJ8n IdQn Y+QIn ZdJn ZJgn YjId",
+"n Y+jIn YJjdn sJngY oI oI! oDI oaI oI5 o8I 5DoI 5aoI oIQ QIo! oTI QaoI opI ",
+"pIo8 pDoI osI oI; o+I DXo; +DoI 5Io; o>I oD5I; oD>X QIo; +QoI TIo; +ToI o;p",
+"I p>oI opDI; sIo> oYI YIo! oJ oJa oIY5 oIY8 oJ5 oJ8 YQoI oYQI! oJZ oaZJ oIY",
+"p Y8opI oJp oJs ovI oIY+ oJv goJ o5vI oIY> J5ov oJ> oQvI Y+oQI JvoZ gZoJ pv",
+"oI o>IYp opJv yoJ bXn I&n DXbn cXn b.In 8Ibn In.bD 8Icn bKIn IK&n TIbn TIcn",
+" Inbj &nIj InjbT cXsn b(In +Ibn In(bD +Icn In(b. I&n+8 DX(bn. cX+8n In(bK I",
+"&n+K bTXn( cX+Tn Injb( I&n+j Ij(bTn sInc+ bGn G&bn Jnb cJn b.Gn G8bn bnJ. J",
+"8cn bKGn I&nGK bTJn cTJn Gnbj I&nGj bnJj cJsn Gnbd +Gbn bdJn cJgn Idnb. Idn",
+"b8 Jnbd. cJng8 IdnbK Idn&K JnbTd cJngT Idnbj Idn&j Jnjbd sJngc 4bX bX4& bX4",
+"D c4X b54X b84X 4bX5D 48cX 4KbX I&n4K bT4X 4TcX bX4j I&n4j 4bT5X c4sX b;4X ",
+"b+4X I;nbD 4+cX I;nb5 4b>X 5DXb;n c4>X I;nbK I;&nK I;nbT c4X+T I;nbj >Xb4j ",
+"4bTX;j c>Xs4 bG4X I&n4G 4bJn J4cX G5bn I&nG5 b5Jn J5cn 4bGXK InK4G& J4bTX c",
+"J4TX 4bGXj 4bGX&j J4jbX sJ4cX bd4X Idn4& b;Jn c4gX Idnb5 bG>n J5nbd cJ>n 4b",
+"dXK IdK;&n J;nbT cJ;Tn dXj4b >nbGj J;nbj J>nsc IPbn P&In IPnbD IPcn IPnb. I",
+"P&8n bPDIn. cX8Pn QIbn I&Qn bQXDn QIcn IPjbn IP&nj bTPInj sIPcn IPnb( IP&+n",
+" bPDIn( cX+Pn bP(In. +IPb8n IPbnD(. +IPcn8 bQXn( I&n+Q IP(bTn cQX+n IP(bnj ",
+"b+QInj InbjQD( sI+cQn Ybn bnY& JnYb Ycn bnY. b8Yn YJbn. cnY8 bQYn YbQ&n ZnY",
+"b ZnYc bnYj Yb8Qn YZbnj snYc bdYn b+Yn YJbdn gnYc Ybdn. Yb+8n JndYb. Ycg8n ",
+"YbQdn Yb+Qn YZbdn ZcngY Ybjdn Yb+nj YbdJnj sYcgn obI oI& bXoD ocI b5oI b8oI",
+" ob5DX o8cX bQoI QIo& bToI oTcX pboI pIo& opbDX sIoc bXo; b+oI obDI; o+cX o",
+"b5I; ob>X b5XoD; >Xoc obQI; ob+QI obTI; oc+QI opbI; o>bpI ob;pDX osc>X Ybo ",
+"obY& oJb Yco obY5 obY8 J5ob Y5oc YQob YboQ& YboZ ZcoJ opYb Ypbo8 obJp osYc ",
+"ovYb obY+ obJv Ycgo Yvbo5 Ybo> oJvb5 ocY> YvboQ Ybo+Q oJZvb ocZgY Ypbov Y>b",
+"op oJpvb Ycyo 6X 6X! 6XB 6aX 6X1 68X 6B1X 1a6X 6XK XK6! 6TX TX6a 6Xj 8X6j 1",
+"T6X s6X 6X( 6+X X(6B +X6a 6(1X 1+6X 6X1(B 6+X1a X(6K 6K+X 6(TX +T6X 6(Xj +X",
+"6j 6TX1( 6+sX 6GX 6!Gn 6HX Ga6X 1Gn G86X 1H6X Ga1n 6KGn 6GX!K GT6X 6GTaX Gn",
+"6j 6G8Xj GT1n 6GsX 6dX +G6X HX6d g6X 1d6X +G1n 6HX1d 68gX 6KdX 6+GXK Td6X 6",
+"TgX dX6j dXj6+ dXj6H s6gX 4X6 6!4X 4B6X 6a4X 7X 7X8 7XB 7aX 4K6X 4X6!K 6T4X",
+" 4TX6a 7Xj 8X7j 7TX 7sX 6X; 6+4X 6BX; aX6; 7X; >X7 X;7B 7a>X 6KX; 4+X6K TX6",
+"; aX;6T X;7j >j7X TX7; >X7s 6G4X 4G6n! 6H4X 4Ga6X 7GX G87X 7HX Ga7X 4G6XK 6",
+"GK4X! 4GT6X 6GT4aX Gn7j 7G8Xj GT7X 7GsX 6d4X 4+G6X HX6; 4Xg6 7dX 7G>X HX7d ",
+"g7X 4dX6K X;K6+G 4Td6X g4X6T dX7j 7>GXj Td7X gX7s 6XP XP6! XP6B aX6P 1X6P 8",
+"X6P 6X1PB 68XaP 6QX Q!6X QX6T Qa6X 1Q6X Q86X 6QX1T 6QsX XP6( +X6P 6XP(B 6+X",
+"aP 6X1P( 6+X1P 1X(6PB 1+X6aP 6(QX +Q6X 6QXT( 6+QTX 6QX1( 6+Q1X Xj(6TP s6X+Q",
+" Y6 Y6! Y6H Y6a Y61 Y68 6HY1 6HY8 Y6Q 6QY! YZ6 Z6Ya Y6j 6QY8 Z6Y1 sY6 Y6d Y",
+"6+ 6HYd gY6 6dY1 6+Y1 Y61Hd Y6g1 6QYd 6+YQ YdZ6 YZg6 6dYj 6+Yj YZ61d g6sY o",
+"6X 6Xo! 6XoB 6aoX 7oX o87X oX7B oa7X 6QoX o!6QX 6ToX oT6aX 7pX 78pX oT7X 7o",
+"sX 6Xo; 6+oX o6X;B o+6aX oX7; 7o>X 7oX;B 7oa>X QX6; o+6QX oT6X; o+T6X 7;pX ",
+"7p>X 7oTX; os7>X Y6o o!Y6 oHY6 oaY6 7Y 7Y8 7YH 7Ya o6YQ Y6oQ! Y6oZ YZ6oa 7Y",
+"p Y87p 7ZY sY7 Yv6 o+Y6 YHv6 Yvg6 7Yv Y>7 7HYv g7Y YQv6 Yv6+Q ZvY6 gY6oZ 7v",
+"Yp 7pY> YZ7v y7Y 6X9 6X& 6B9X 9a6X 1X9n :X6 6X19B 6a:X 6K9X 6KX& 9T6X TX6& ",
+"9X6j 6X:j 6TX9j :Xs6 6(9X 9+6X 6X9(B 6+X9a 6X19( 6+:X 1X(9nB :X6+a 6X9(K 6+",
+"X9K 6TX9( 6+T9X 6Xj9( :X6+j Xj(9Tn s:X6+ 9Gn G&6X 9H6X Ga9n 1G9n :Gn 6HX91 ",
+"6H:X 9KGn 6G&XK GT9n 6GTX& Gn9j Gn:j 6HX9j :Gsn 9d6X +G9n 6HX9d 6Xg9 6dX91 ",
+"6d:X 1HX9dn :Ggn 6dX9K dX&6K 6Td9X g6X9T dXj9n :Gn+j 9GTdnj g:Xs6 49X 6X4& ",
+"4B9X 9a4X 7X9 7:X 9X7B :X7a 4K9X 49X&K 9T4X 49TaX 9X7j 7j:X 9T7X 7:sX 9X6; ",
+"9+4X 49X;B aX;49 9X7; 7:>X 7X9;B 7:X>a 49X;K X;&6K 49TX; X;&6T 7X9;j 7:X>j ",
+"7TX9; 7sX:> 9G4X 49GX& 9H4X 49GaX 9G7X :G7X 9H7X :H7X 49GXK X&K49G 49GTX 6G",
+"T4X& 7G9Xj 7:GXj 7GT9X 7sG:X 9d4X dX&49 49HdX 49gX 9d7X :G>n 7HX9d 7:gX 49d",
+"XK dXK49+ 49TdX g49TX 7dX9j 7:dXj 7Td9X g7Xs: 9X6P X&6P 6XP9B 6aX9P 6X19P 6",
+"X:P 9X16PB :X6aP 9Q6X QX6& 6QX9T 6Qa9X 6QX9j 6Q:X 9TX6Pj :QXs6 6XP9( 6+X9P ",
+"9X(6PB 9+X6aP 9X16P( :X6+P 6(9X1PB 6+X:Pa 6QX9( 6+Q9X 6Q(9TX 9+Q6TX Xj(9Qn ",
+":QX6+ 6(QX9T1 sX+:Qn Y69 Y6& 6HY9 6HY& 9nY1 Y:6 Y691H :HY6 6QY9 6QY& Z6Y9 Z",
+"6Y& 6jY9 :QY6 YZ69j s6Y: 6dY9 6+Y9 Y69Hd Y6g9 Y691d :dY6 9HnY1d g6Y: Y69Qd ",
+"Y6+9Q YZ69d gY6Z9 Y6j9d Y:6+Q Y9dZ1n sY:g6 o9X 6Xo& 9XoB 9aoX o97X o:X 7o9X",
+"B oa:X 9QoX o9QX& 9ToX o9TaX p97X 7X:p 7oT9X sXo: 9Xo; 9+oX o9X;B o9+aX 7o9",
+"X; >Xo: o9;7XB o:>aX o9QX; o9+QX o9TX; o9+TX 7pX9; o:p>X 7T;p9X os:>X Y9o o",
+"9Y& oHY9 o9Ya 7Y9 Y:o 7HY9 Yao: YQo9 Y6&oQ Y9oZ oZ9Ya Y97p Ypo: Y97Z Y:7Z o",
+"vY9 o9Y+ Yv69H Y9go Y97v :v7Y 7Yv9H Y:go Yv69Q Yv6Q& oZ9Yv go9YZ Yp97v Y:op",
+"v 7ZYv9 Y:yo 6IX 6!In 6DX DX6a 1In 8I6X 1D6X D86X 6KIn InK6! DX6T 6DXTa In6",
+"j Inj68 DX6j 6DsX 6(In +I6X 6(DX +D6X 1(In +I1n 6DX1( 6+D1X In(6K 6+IXK 6DX",
+"T( 6+DTX Inj6( Inj6+ 6DXj( sIn6+ Gn6I In!6G J6X 6aJn Gn1I 6G8In J1n 68Jn In",
+"K6G 6GKIn! 6TJn J6TaX Inj6G 6G8Inj 6XJj J6sX Id6X Idn6+ 6dJn J6gX Id1n Idn6",
+"8 1dJn J1gn Idn6K IdK6+X J6TdX gJ6TX Idn6j 6+GInj J6jdX sJ6gX 6I4X In!46 6D",
+"4X 4DX6a 7IX 8I7X 7DX D87X InK46 6IK4X! 4DX6T 6TI4aX In7j 7I8Xj DX7T 7DsX I",
+";6X I;n6+ DX6; aX;6D I;7X 7I>X DX7; 7D>X I;n6K I;K6+X I;n6T 6+D4TX 7IX;j 7>",
+"IXj 7DXT; 7sI>X 4G6In 4G6In! 4XJ6 J46aX Gn7I 7G8In 7JX J87X 4G6InK 6!4GInK ",
+"J46TX 4TXJ6a 7GIXj Inj7G8 Jn7T sX7J Idn6; 6+GI;n 6XJ; gJ46X Id7X 7>GIn J;7X",
+" >X7J IdK6X; Id4X6+K J6;TX J4Tg6X 7IdXj >Ij7dX 7JTdX J>n7s 6IP 6!IP DX6P aI",
+"6P 1I6P 8I6P 6DX1P 6D8IP QI6X 6QIn! QD6X 6QDaX QI1n IPj68 IPj6D 6IsP 6(IP +",
+"I6P 6DXP( 6+DIP 6IP1( 6+I1P IP(1Dn 1+D6IP 6QIX( 6+QIP 6QDX( 6+QDX IPj6( IPj",
+"6+ IP(6Dj sIP6+ Y6I 6IY! YJ6 J6Ya 6IY1 68YI J6Y1 J6Y8 6QYI Y6QI! ZJY6 YZ6Ja",
+" 6IYj Y68QI J6Yj YJs6 6IYd 6+YI YdJ6 YJg6 Y61Id Y6+1I YJ61d gY6J1 Y6QId Y6+",
+"QI YZ6Jd gY6ZJ Y6jId Y6+Ij YJ6dj sY6gJ oI6 6Io! 6DoI 6aoI 7oI o87I oD7I oa7",
+"I 6QoI oIQ6! 6ToI oTI6a op7I 7oIp8 oT7I 7osI 6Io; 6+oI oD6I; o+D6I 7;oI 7Io",
+"> 7oDI; o>D7I oIQ6; o+I6Q oTI6; o+T6I 7oIp; o>I7p 7oTI; osI7> oIY6 Y6oI! oJ",
+"6 oaJ6 7YI 7IY8 7Jo Y87J Y6oQI oIQY6! Z6oJ oJZ6a 7IYp 7Yp8I oJ7Z 7JsY v6oI ",
+"Yv6+I Y6Jv g6oJ 7IYv 7IY> 7voJ 7Jgo Yv6QI Y6Qo+I oJZv6 goJZ6 7vIYp Y>7pI oJ",
+"p7v 7Jyo b6X 6&bX 6DbX c6X 6Xb1 :In b6X1D c6:X bK6X I&n6K 6TbX 6TcX 6Xbj In",
+":j Inj9D :Isn b(6X 6+bX b6XD( 6+cX b6X1( +I:n b6(1DX :cX6+ b6X(K b6+XK b6TX",
+"( c6X+T Inj9( :In+j In(b1T sIn:+ 6GbX I&n6G J9n J6cX 1Gbn bG:n b1Jn :Jn b6G",
+"XK I&K9Gn 9TJn cJ6TX Inj9G :Gnbj 9nJj sn:J 6dbX Idn6& 9dJn c6gX Idnb1 Id:n ",
+"J9n1d gn:J Idn9K IdK6X& J9nTd c6XgT Idn9j :Idnj J9ndj :Jngs b64X I&n49 9D4X",
+" 49cX 7bX :I7X bX7D 7cX 4bX6K I&K49X 4bT6X c4X6T bX7j 7:IXj bT7X sX7c 6Xb; ",
+"I;&6X I;n9D 6Xc; bX7; 7b>X 7bXD; >X7c I;n9K I;K6X& I;n9T c6XT; 7bX;j 7>bXj ",
+"7bTX; 7cXs> 4bG6X 49GI&n 49Jn cJ46X bG7X 7:GbX J97X 7X:J InK49G 4KbG6X& J49",
+"TX c4TJ9n 7bGXj 7bj:Gn 7JbTX 7Js:X Idn49 49+Idn 9;Jn cJ6X; bd7X 7:IdX 7JbdX",
+" >n:J IdK49X dX4&b6K J9;Tn c4Tg6X 7bdXj >Ij:Gn 7bTdX J>ns: 6IbP IP6& b6XDP ",
+"6IcP b6X1P 6I:P 6DXb1P :cX6P 6QbX IP&6Q b6QDX 6QcX IPjb6 QI:n b6TIPj sIP:n ",
+"b6XP( IP&6+ IP(9Dn c6X+P IP(b1n :IP6+ b(6X1DP :I+c6P b6QX( b6+QX IP(b6T c6Q",
+"+X IP(b6j :QI+n 6XbjQD( sI+:Qn Yb6 b6Y& J6Yb Yc6 b6Y1 :IY6 YJ6b1 Y6:J b6YQ ",
+"Yb6Q& ZbY6 Y6Zc b6Yj Y:b6Q YZb6j s6Yc b6Yd b6Y+ YJ6bd g6Yc Yb61d Y:b6+ YbdJ",
+"1n Y:Jg6 Yb6Qd Yb6+Q YZb6d Yc6gZ Yb6dj Yb6+j YbdZ1n sYcg6 o9I 6Io& 9DoI o9c",
+"X ob7I o:I 7obDX 7Ioc 9QoI o9IQ& 9ToI oc6QI pb7X op:I 7obTI sIo: 9Io; 9+oI ",
+"o9DI; oc6+I 7obI; :Io> 7D;o9I o:Ic> o9IQ; o9+QI o9TI; c6QX; 7pbX; o:Ip> 7b;",
+"oTI os:>I obY6 Ybo6& oJ9 Y6oc 7Yb Ybo: Yb7J Yc7 Ybo6Q Y6QoI& Z9oJ oJ9Zc Yb7",
+"p o:IYp Yb7Z Yc7Z vbY6 Yvb6+ o9Jv g9oJ Yb7v 7>Yb oJ97v Ycg7 Yvb6Q YbQo9+ oJ",
+"9Zv oJ9gZ 7Ybpv :vIop oJpv9 Ycy7 RXn n!RX XnRB RXan XnR. RX8n RXn.B aXnR8 X",
+"Mn n!XM XMTn XMan MnXj XM8n XMnTj XMsn XnR( RX+n RXn(B aXnR+ RXn(. R+8Xn Xn",
+"(R.B R+8aXn X(Mn XM+n XMnT( aXM+n XMnj( R+jXn RTXnj( sX+Mn RGn R!Gn GnRH Gn",
+"Ra R.Gn GnR8 RGHn. RG8Hn GMn G!Mn GnRT aMGn GnRj 8MGn RGTnj RGsn GnRd +nRG ",
+"RGHdn RGgn dX.Rn R+G8n RGHdn. gRG8n dMGn GM+n dXMHn GMgn dXMnj dXM8n RGTdnj",
+" gsRGn R4X 4!RX RB4X 4XRa 4XR5 4XR8 R45XB R48aX 4XM 4!XM 4XRT aX4M 4XRj 8X4",
+"M R4T5X R4sX 4XR; 4XR+ X;BR4 aX;R4 R45X; R4>X R45X;B >XR4a X;4M +X4M XM;4T ",
+"aXM4+ XM;4j 4X>M R4TX;j >XsR4 R4G 4!RG 4GRH 4GRa 4GR5 4GR8 R4GH5 R4GH8 4MRG",
+" R4GM! 4GRT aXM4G 4GRj R4G8M R4GHj R4sG 4GRd 4+RG R4GH; R4gX R4G5d R4>G 4HX",
+"R5d >XgR4 dX4M dXM4+ dXM4H 4XgM dXM4j GM>n R4HdXj >Xg4M XPRn RXPn! RXPnB aX",
+"PRn RXPn. R8XPn XPnR.B R8XaPn SXn n!SX TXSn aXSn XjSn 8XSn STXnj SXsn RXPn(",
+" R+XPn XPnR(B R+XaPn XPnR(. +XPR8n .BR(XPn aX+PR8n XnS( +XSn STXn( S+TXn SX",
+"nj( S+8Xn XjnST( Ss+Xn YRn RnY! RHYn RaYn RnY. R8Yn YRHn. Y8RHn SYn YnS! Zn",
+"SY SnYa SnYj SnY8 SZYnj SYsn RdYn R+Yn YRHdn YRgn YRdn. Y+R8n dn.YRH gYR8n ",
+"YdSn SnY+ SZYdn SYgn SYdnj SY+8n YZnSdj gSsYn oRX RXo! RXoB RaoX R5oX R8oX ",
+"oR5XB o8RaX SoX o!SX SXoT SXoa pXSo SXo8 SpToX sXSo R;oX R+oX oRX;B o+RaX o",
+"R5X; oR>X X;BoR5 o>RaX oXS; SXo+ S;ToX Sa;oX SpXo; So>X opTS;X os>SX oYR YR",
+"o! YRoH YRoa oRY5 YRo8 Y5oRH Y5aoR SoY S!oY SYoZ YaSo SoYp Y8So SZpoY SosY ",
+"vRoY YRo+ YvoRH oYgR YvoR5 >RoY ovRY5H goY>R YvSo Y+So YZvSo SogY SvoYp SoY",
+"> YpoSvZ SoyY XnR# RX&n RXn#B aXnR& RXn#. X&nR8 Xn#R.B R8aX&n X#Mn MnX& XMn",
+"T# aXM&n XMnj# XM&8n RTXnj# sX&Mn RXn#( X&nR+ Xn#R(B R+aX&n Xn#R(. R+8X&n .",
+"BR(Xn# aXR&+n8 XMn#( XM&+n TX#Mn( +TXM&n Mn#Xj( +XM&nj XMTnj#( XM&sn+ R#Gn ",
+"GnR& RGHn# RGa&n RGn#. RG8&n Gn#RH. G8nRH& G#Mn M&Gn RGTn# aMnG& RGjn# M&nG",
+"8 XM#Hnj sRG&n dX#Rn dX&Rn RGHdn# gRG&n RG#dn. RG8d&n dXHnR#. RG8gn& dXMn# ",
+"dXM&n dX#HMn gXM&n dM#Gnj XM&dnj dXHjMn# sX&gMn R#4X 4XR& R4X#B R4aX& R45X#",
+" R48X& 4X#R5B 4aXR5& 4#XM XM4& R4TX# aXM4& R4jX# XM&48 XM#5Tn sR4X& X;#R4 X",
+";&R4 R4#X;B R4aX;& R45X;# >XR4& 5#X;R4B R4a>X& XM;4# XM;4& XM#T;n XM&a;n XM",
+"#;nj >XM4& X;Rj4T# sX&>Mn R#4G 4GR& R4GH# R4GH& R4G5# R4G5& R4#H5X 4G8RH& R",
+"4GM# XM&4G R4GT# XM&4H R4Gj# M&nG5 XM#4Hj sR4G& R4Gd# dX&R4 dX#R4H gR4G& dn",
+"#RG5 >nGR& H#5nRG; >X&gR4 dXM4# dXM4& dX#R4T g4XM& dX#R4j >MG&n dX4MH5# sX&",
+"gR4 RXPn# X&PRn XPnR#B RaXP&n XPnR#. R8XP&n .BP#RXn aXR&8Pn XnS# X&Sn STXn#",
+" SaX&n SXnj# S8X&n XjnST# SsX&n XPnR#( R+XP&n XPRn#B( aXR&+Pn #(P.RXn 8X+PR",
+"&n XnR(.BP# anR&8X+P SXn#( S+X&n TXnS#( +TXS&n XjnS#( X&jS+n XjSnT#( S+Xsn&",
+" RnY# R&Yn YRHn# YaR&n YRn#. Y8R&n RHnY#. RH8Y&n YnS# SnY& SZYn# SZ&Yn SYnj",
+"# SY8&n YjnSZ# sYS&n YRdn# Y+R&n dn#YRH gYR&n dn#YR. d&nY8R dnY#RH. gR8Y&n ",
+"SYdn# SY+&n YZnSd# gSY&n YjnSd# S+nY&j dnYjSZ# sY&gSn RXo# R&oX oRX#B oaRX&",
+" oR5X# o8RX& R5Xo#B R5ao&X oXS# SXo& oTXS# oT&SX SpXo# Sp&oX oTXSp# osSX& o",
+"RX;# o+RX& X;#oRB aX;o&R X;#oR5 o>RX& X;o#R5B oaR>X& S;Xo# S;&oX oTXS;# S+X",
+"oT& opXS;# S>oX& X;S#opT S>Xos& oRY# YRo& oYRH# YaoR& Y5oR# Y5&oR oHRY5# Y5",
+"RoH& S#oY Y&So oZYS# oZ&SY YpoS# Yp&So oZSYp# sYoS& YvoR# Yv&oR oHRYv# goYR",
+"& ovRY5# Y>oR& YRoHv5# Y>Rgo& SvoY# Sv&oY oZYSv# goSY& YpoSv# S>Yo& SZYpov#",
+" yoYS& [n [!n [Dn [an [n. [8n Dn[. D8[n [Mn Mn[! V[n [aVn [jn 8M[n [jVn [sn",
+" [n( [+n Dn[( +D[n n([. +n[8 [Dn(. [+D8n Mn[( +M[n [nV( [+Vn nj[( +n[j V[nj",
+"( [+sn [Gn Gn[! Jn[ [aJn Gn[. G8[n [nJ. [8Jn GM[n [!GMn JnV JaVn Gn[j [8GMn",
+" VnJj Jn[s [dn +G[n [dJn g[n dn[. 8d[n Jn[d. [8gn dM[n [+GMn VdJn JngV dn[j",
+" [+jGn JnVdj gn[s [4 [4! [4D [4a [45 [48 4D[5 4D[8 [4M 4M[! V[4 [aV4 [4j 48",
+"[j [4V5 [s4 [4; [4+ 4D[; 4+[a 5n[; [>4 [45D; [a>n 4M[; 4+[M [4V; [4V+ 4j[; ",
+"[4>M V[4;j >n[s [4G 4G[! J4[ [aJ4 4G[5 4G[8 [4J5 [4J8 4G[M [4GM! V[J4 J4V[a",
+" 4G[j [48GM V5Jn J4[s [4d 4+[d [4J; g[4 4d[5 [d>n J4[5d >ng[ 4d[M [4+GM V;J",
+"n V[g4 4d[j [>4GM J4[dj g4[s [Pn n![P DP[n aP[n Pn[. 8P[n [DPn. [8DPn S[n [",
+"!Sn VnS[ Sn[a Sn[j Sn[8 SV[nj S[sn Pn[( +P[n [DPn( [+DPn [Pn(. [+8Pn DPn[(.",
+" +DP[8n [nS( Sn[+ SV[n( SV+[n S[nj( S[+8n VnjS[( [sS+n [Yn Yn[! [YJn Yn[a [",
+"nY. Yn[8 YJ[n. YJ8[n Sn[Y S[Yn! ]n ]an Yn[j S[8Yn ]jn ]sn Yn[d Yn[+ YJ[dn [",
+"Ygn [Ydn. Y+[8n [YdJn. g[Y8n Sn[d S[+Yn ]dn ]gn S[dnj S[8dn dn]j gs]n o[ o[",
+"! o[D o[a o[5 o[8 [5oD [5oa o[S S!o[ oV[ Sao[ [po S8o[ [poV os[ o[; o[+ [;o",
+"D [+oD o5[; [>o o[5D; oD[> S;o[ S+o[ V;o[ V[o+ [;op o[S> oVp[; [>oV o[Y o![",
+"Y oJ[ Yao[ Y5o[ Y8o[ J5o[ J8o[ SYo[ o[YS! ]o ]oa o[Yp [poY8 ]op ]os [vo Y+o",
+"[ [voJ go[ [5ov o[Y> oJ[v5 [>go o[Sv [voS+ ]ov ]og op[v [pvo> op]v ]yo [bn ",
+"[&n bn[D [cn bn[. b8[n [bDn. [8cn bM[n M&[n [bVn V[cn bn[j &n[j V[bnj sn[c ",
+"bn[( b+[n [bDn( [+cn [bn(. [+b8n bnD[(. [c+8n [bMn( [+bMn V[bn( [cV+n [jbn(",
+" [+jbn [jbVn( [sc+n bG[n G&[n [bJn Jn[c [bGn. [8bGn Jn[b. [cJ8n GMbn [&GMn ",
+"JbVn VJcn [jbGn [&jGn JnVbj [sJcn bd[n d&[n Jn[bd gn[c [dbn. [8dbn [dbJn. g",
+"[c8n [dbMn [d&Mn JnVbd gVn[c [djbn [d&nj Jnb[dj g[scn [4b [4& 4b[D [c4 4b[5",
+" 4b[8 [4b5D [4c5 4b[M 4M[& Vb[4 V[c4 4b[j 4&[j V[4b5 s4[c 4b[; 4b[+ [4bD; [",
+"4c; [4b5; [&>n b5n[;D >n[c [4bM; [4+bM V[4b; [c4V+ [4jb; [>4bM V4b[;j V>[c4",
+" 4b[G 4G[& Jb[4 J4[c [4bG5 [48bG J4[b5 [c4J5 [4bGM [4&GM J4V[b [c4VJ [4jbG ",
+"[4&Gj J4[bj [s4cJ 4b[d 4d[& J4[bd g4[c [4db5 [>4bG J4b[5d J>n[c [4dbM [4dM&",
+" J;Vbn g[4Vc [4dbj >MbGn J4b[dj J>Vcn bP[n P&[n [bDPn [Pcn [bPn. [8bPn bPD[",
+"n. [c8Pn [bSn Sn[& SV[bn cnS[ S[bnj S[8bn V[nSbj [scSn [bPn( [+bPn bPD[n( [",
+"c+Pn bPn[(. b+P[8n bD[(Pn. [+8cPn S[bn( S[+bn V[nSb( Sc[+n [jnSb( Sbn[+j nj",
+"V(S[b Sc+[sn [bYn Yn[& YJ[bn [Ycn Yb[n. Yb8[n Jn[Yb. Yc[8n SnYb S[&Yn ]bn ]",
+"cn SYbnj SYb8n bn]j sc]n Yb[dn Yb+[n Jn[Ybd g[Ycn [dnYb. Ybn[8d dnJ.Yb[ Yc8",
+"g[n S[dbn S[d&n bd]n gc]n Sbn[dj SbnY+j ]jnbd ]cngs o[b o[& [boD oc[ [5ob [",
+"5o& o[b5D c5o[ Sbo[ S&o[ V[ob o[Sc ob[p o&[p oVp[b [poc [;ob [+ob o[bD; c;o",
+"[ o[b5; ob[> [5boD; [>oc S[;ob o[+Sb oV[b; oV+[c [pob; [p&o> [pboV; oV>[c Y",
+"bo[ Y&o[ [Job o[Yc Ybo[5 o[8Yb oJ[b5 oJ8[c YbSo o[&SY ]ob ]oc [poYb [p&oY o",
+"p]b os]c ob[v o&[v oJ[vb ocg[ [vob5 [v&o> [vboJ5 oJ>[c [voSb [v&So ov]b go]",
+"c [pvob [pvo& ]opvb yo]c qX q!X qXB qaX q1X q8X 1XqB 1aqX qXM XMq! qTX TXqa",
+" lXq q8lX qTlX sqX qX( q+X X(qB +Xqa 1Xq( 1+qX q1X(B q+1aX XMq( +XqM TXq( +",
+"TqX qXl( q+lX lXqT( q+sX qG qG! qGH qGa qG1 qG8 1GqH 1Gqa qGM GMq! qGT GTqa",
+" lGq q8lG qGlH sqG qGd q+G HXqd gqG 1Gqd 1+qG qG1Hd qGg1 GMqd +GqM GTqd qGg",
+"M qGld q+lG lGqTd lGgq q4X 4Xq! 4XqB 4aqX 7qX q87X qX7B qa7X 4XqM q!4XM 4Tq",
+"X qT4aX lX7 l87X 7TlX lX7s q;X 4+qX X;qB aXq; q;7X q>X 7qX;B qa>X XMq; q+4X",
+"M TXq; q+T4X 7Xl; lXq> 7qTX; >Xsq qG4 4Gq! 4GqH 4Gqa 7qG q87G qG7H qG7a 4Gq",
+"M qG4M! 4GqT qGT4a 7qlG 7qGl8 7HlX 7qsG qG; 4+qG G;qH qGg4 qG7d q>G 7qGH; >",
+"Xgq GMq; q+G4M GTq; gq4GT 7dlX lGq> 7qGTd lXg7 qXP XPq! XPqB aXqP 1XqP 8XqP",
+" q1XPB q8aXP SqX q!SX SXqT SXqa SqlX SXq8 SlqTX SqsX XPq( +XqP qXP(B q+aXP ",
+"q1XP( q+1XP 1XPq(B 1+XqaP qXS( SXq+ SqTX( Sq+TX SlqX( Sq+lX lXTSq( sqS+X Yq",
+" Yq! YqH Yqa Yq1 Yq8 qHY1 qHY8 YqS S!Yq ZqY SaYq lYq S8Yq ZqlY sqY Yqd Yq+ ",
+"YHqd gqY qdY1 q+Y1 Yq1Hd g1Yq SdYq S+Yq qdYZ gYZq ldYq l+Yq lYZqd gqlY oqX ",
+"oXq! qXoB oXqa oq7X oXq8 7oqXB 7oaqX SXoq SqXo! oXqT SqaoX rX r8X rTX rsX o",
+"Xq; oXq+ oqX;B oq+aX 7oqX; oq>X oq;7XB q>oaX SXq; Sq+oX Sq;TX SqaX; r;X r>X",
+" TXr; >Xrs Yqo o!Yq oHYq oqYa 7Yq Y87q 7HYq Ya7q SoYq YqoS! oZYq YqaoZ rY r",
+"Y8 rZY rsY vqY Y+vq qHYv gYvq vq7Y Y>q vq7YH Y>gq YqSv vqYS+ YZvq goqSY rYv",
+" rY> YZrv yrY q9X q&X 9XqB 9aqX 9Xq1 :qX q91XB qa:X 9XqM XMq& 9TqX TXq& q9l",
+"X lX:q lXq9T sX:q 9Xq( 9+qX q9X(B q+9aX q91X( q+:X 9X1q(B :q+aX q9XM( q+9XM",
+" qT9X( q+T9X lXq9( :ql+X qT9lX( sq:+X qG9 qG& 9GqH 9Gqa 9Gq1 :qG qG91H qG:H",
+" 9GqM GMq& 9GqT GTq& l9qG lG:q lGq9H sG:q 9Gqd 9+qG qG9Hd qGg9 qG91d q+:G 9",
+"HXqd1 gX:q qG9dM q+G9M qGT9d gq9GT lGq9d :qGl+ lG9qTd glq:G 49qX 4Xq& q49XB",
+" qa49X q97X 7X:q 7q9XB 7qa:X 9X4M q&4XM qT49X qT&4X l97X 7:lX 7qT9X 7sX:q 9",
+"Xq; X;q& q;9XB qa;9X 7q9X; >X:q q;97XB q>:aX q;9XM q;&XM qT;9X qT;X& lX79; ",
+"q>l:X 7T9lX; sq>:X 49qG 4Gq& qG49H qGa49 79qG 7G:q 7qG9H :qG7H qG49M qG&4M ",
+"qGT49 qGT4& 7qGl9 :qG7l 7qG9T sqG7: 9Gq; G;q& qG;9H gq49G 7qG9d :Gq> 7G9qH;",
+" q>Gg: qG;9M qG;M& qGT9; g49XM 7dXl9 q>Gl: 7G9qTd q>Gs: 9XqP X&qP q9XPB qa9",
+"XP q91XP qX:P 9X1qPB :qaXP q9SX SXq& Sq9TX Sqa9X Slq9X :XSq lXqS9T sq:SX q9",
+"XP( q+9XP 9XPq(B 9+XqaP 9X1qP( :q+XP 91q(XPB q+a:XP Sq9X( Sq+9X qTXS9( S9Xq",
+"+T lXqS9( S:q+X l9qTSX( S:+sqX Yq9 Yq& qHY9 qHY& q9Y1 Y:q Yq91H Ya:q S9Yq S",
+"&Yq Y9Zq Y&Zq lqY9 YqS: lYZq9 Y:sq qdY9 q+Y9 Yq9Hd g9Yq Yq91d Y+:q qH9Y1d Y",
+":gq SqdY9 Yq+S9 ZqY9d gqZY9 lYq9d lY:q+ Zq9lYd glY:q q9oX oXq& oq9XB oqa9X ",
+"7oq9X oq:X oq97XB o:qaX SXo9 Sq&oX oqT9X S9aoX r9X r:X 9TrX s:rX oq9X; oq+9",
+"X q;Xo9B o9Xqa; oq97X; o:q>X 7Boq9X; q>ao:X Sq;9X Sq;X& S9XqT; S9Xo+T 9Xr; ",
+">Xr: r;X9T r>Xs: oqY9 oqY& Y9oqH Yqao9 Y97q Yqo: 7Yq9H o:HYq Y9So Yq&So oZ9",
+"Yq Zq&oY rY9 rY: YZr9 sYr: Y9vq Y&vq vqY9H vq&gY vq7Y9 vqY: 7Y9vqH go:Yq vq",
+"YS9 vq&SY ZqvY9 vq&YZ Yvr9 Y:rv rZYv9 rYy: [q [q! [qD [qa [q1 [q8 qD[1 qD[8",
+" [qM [Mq! Vq[ [aVq [lq q8[l [lVq sq[ [q( [q+ [(qD q+[a [(q1 q+[1 [q1D( [q+1",
+"D [(qM [Mq+ V([q [qV+ l([q [ql+ Vql[( [+sq [qG [!qG Jq Jqa qG[1 qG[8 Jq1 Jq",
+"8 [MqG [qGM! JqV qaVJ [qlG [lqG8 Jql sqJ [qd q+[d Jqd gqJ qd[1 q8[d qdJ1 g1",
+"Jq [Mqd [q+GM VdJq gVJq [qld [l+qG ldJq sqg[ [q4 q![4 qD[4 qa[4 7[ 7[8 7[D ",
+"7[a q4[M [q4M! [qV4 Vq[4a 7[l [87l 7V[ 7[s [q; q+[4 qD[; qa[; 7[; 7[> [;7D ",
+"7D[> [Mq; [q+4M [qV; Vq+[4 l;7[ l>7[ V;7[ V>7[ qG[4 [q4G! Jq4 qaJ4 7[G [87G",
+" 7Jq 7aJq [q4GM qGM[4! J4Vq JqV4a lG7[ 7[lG8 Jq7V 7Jsq qG[; [q+4G Jq; g4Jq ",
+"7[d 7G[> 7dJq g7[ [qd4M [4Mq+G J;Vq Jq;gV ld7[ [>l7G l;Jq 7Vg[ [qP [Pq! [Pq",
+"D [Pqa [Pq1 [Pq8 [q1DP [q8DP Sq[ S![q S[Vq [qSa Sq[l [qS8 SlV[q Sq[s qP[( [",
+"Pq+ [qDP( [q+DP [q1P( [q+1P qDP[1( [1Pq+D S([q [qS+ Sq[V( Vq+S[ Sq[l( [l+Sq",
+" [lSVq( sq[S+ Yq[ [!Yq JqY YaJq [qY1 [qY8 Y1Jq Y8Jq S[Yq Sq[Y! ]q ]qa [lYq ",
+"Yq8[l ]lq ]qs [dYq [qY+ qdYJ gYJq Y1[qd Yq+[1 JqY1d Jq8gY [qSd Yq+S[ ]qd ]q",
+"g lYq[d lY+[q ld]q gl]q o[q o![q [qoD [qoa 7[o o87[ 7Do[ 7ao[ Sqo[ Sq[o! Vq",
+"o[ oVq[a r[ r[8 rV[ r[s [;oq [qo+ o[qD; o[+qD [;7o o[q> 7[oD; [>o7D [qS; o[",
+"+Sq oVq[; oV+[q r[; r[> V[r; V>r[ o[Yq Yqo[! oJq oaJq 7[Y Y87[ oJ7[ Ya7[ Sq",
+"[oY o[SYq! ]oq oq]a r[Y Y8r[ ]r ]rs vq[ [+vq Jqv oJgq 7[v 7[Y> vq7J 7[go Sq",
+"[v vq[S+ ]qv go]q r[v Y>r[ ]rv ]yr tq[ [q& qD[t cq[ [1tq [:q tq[1D [:cq tM[",
+"q [Mq& V[tq [cVq tq[l [l:q Vql[t uq[ t([q [qt+ tq[D( [+cq tq[1( [+:q [1Dtq(",
+" cq[:+ tq[M( tq+[M Vq[t( cqV[+ [lqt( [:lq+ [ltVq( [qu+ tqG [&qG Jqt cqJ t1q",
+"G tG:q J1tq :Jq tMqG tqGM& VqtJ cJVq tqlG [:lqG ltJq uJq [qtd q+tG tdJq cqg",
+"[ tqG1d [q:d Jqt1d :Jgq tqGdM tq+GM JqVtd cqJgV [ldtq [:dlq Jqltd gquJ t4[ ",
+"[&t4 tD[4 t4[c 7[t 7[: [t7D 7[c tM[4 t4[M& V[t4 cqV[4 [l7t l:7[ V[7t u7[ [q",
+"t; [4t+ tq;[D [qc; t;7[ 7[t> 7[tD; [>7c tq;[M t4[+M Vq;[t cq;V[ [l;7t [>l7t",
+" 7V[t; 7[u> [4tG tqG4& t4Jq c4Jq tG7[ 7G[: tJ7[ :J7[ tqG4M t4MqG& JqVt4 cqJ",
+"V4 7tG[l 7[:lG Jql7t 7Juq [4td tq+4G t;Jq t4g[ td7[ tGq> Jq;7t 7[gt tqGM; t",
+"4M[d& Jq;Vt cqJV; 7[dlt [:d7l Jqlt; g7u[ [qtP [Pq& tq[DP [qcP tq[1P [q:P [q",
+"1tPD cq[:P tqS[ [qS& Sq[Vt Sq[c Sq[lt Sq[: VqlSt[ Squ[ tq[P( tq+[P [qDtP( c",
+"q[+P [q1tP( [:q+P t1qD[P( [:+cqP Sq[t( St+[q Vq[St( Scq[+ [lqSt( S:[q+ SlVq",
+"[t( uS+[q tYq Y&tq JqtY Ycq Y1tq Yq[: JqtY1 cqY: YqSt Yq&St ]qt ]qc ltYq lY",
+"t:q lt]q ]uq tdYq t+Yq JqtYd tYgq tYq1d [:dYq tY1Jqd g[:Yq StdYq tY+Sq tq]d",
+" gq]t lYtqd [:dSq ]lqtd ]qug ot[ [qo& [toD o[cq ot7[ o:[ ot7[D oc7[ o[St ot",
+"[S& V[ot oVt[c r[t r[: V[rt ur[ t;o[ t+o[ ot[D; otc[+ ot7[; [>ot 7[Dot; cq>",
+"o[ ot[S; ot+S[ oVt[; oVt[+ t;r[ t>r[ rV[t; r[u> tYo Y&ot oJt otYc tY7 7[Y: ",
+"7JtY 7[Yc SotY tYoS& ]ot ot]c rtY tYr: ]rt ur] vqtY Y+ot oJtv tYgo 7[tv 7Yt",
+"> oJt7v tYg7 vq[St ot+SY tv]o go]t tYrv tYr> rt]v ]yur w w! wB wa w. w8 w.B",
+" w8a wK w!K wT wTa wj w8j wTj sw w* w+ w*B w+a w*. w+8 *Bw. 8*wa w*K w+K wT",
+"* w+T wj* w+j T*wj sw+ wG w!G wH wHa wG. w8G wH. wH8 wGK GKw! wHT GTwa wjG ",
+"G8wj wHj swG fw fw+ fwH gw fw. fw8 f.wH gw8 fwK fKw+ fwT gwT fwj w+fj wHfj ",
+"gws w4 w!4 w4B wa4 w5 w58 w5B w5a w4K 4Kw! wT4 4Twa w5j 48wj w5T sw4 w= w=+",
+" w=B =aw w=5 w> =Bw5 w>a w=K =Kw+ =Tw w+=T =jw w>j w5=T sw> w4G 4Gw! wH4 4G",
+"wa w5G 4Gw8 wH5 4Hw8 4GwK w!4GK 4GwT wH4Ta 4Gwj w5G8j 4Hwj wHs4 fw= w+f= =H",
+"w gw= fw5 w>f wHf5 gw> =Kfw fw=+K fw=T =Tgw fw=j fjw> wH=j s=gw wP w!P wPB ",
+"waP wP. w8P P.wB 8Pwa wQ wQ! wQT wQa wQj wQ8 TPwj swQ wP* w+P P*wB +Pwa P*w",
+". +Pw8 wP*.B w+a8P wQ* w+Q Q*wT +QwT Q*wj +Qw8 wQT*j w+sP Yw Yw! YwH Ywa Yw",
+". Yw8 Y.wH wHY8 YwQ Y!wQ Zw Zwa Ywj wQY8 Zwj sYw Yfw Yw+ wHYf gwY Y.fw fwY8",
+" YfwH. Y8gw fwQ w+fQ Zwf gwZ fwYj w+Yj fjZw sYgw ow ow! owB owa ow5 ow8 oBw",
+"5 w5oa owQ o!wQ owT wQoa pw pw8 pwT swo ow= ow+ =Bow ow=a w5o= w>o ow=5B oa",
+"w> =Qw w+=Q ow=T w+oT pw= pw> =Tpw pws= Ywo o!Yw owH owYa Yw5 owY8 wHY5 wHo",
+"8 wQoY YwoQ! Zwo oaZw pwY Y8pw Zwp osZw x x+ xH xg x5 x> xH5 xg> xQ x+Q xZ ",
+"xZg xp xp> xZp yx w, w& w,B wa& w,. w8& ,.wB ,8wa w,K w&K wT, wT& wj, w&j ,",
+"Twj sw& w*, -w *Bw, -wa ,*w. -w8 w*,.B -8wa ,*wK -wK ,Tw* -wT ,jw* -wj wT*,",
+"j sw- wG, w&G wH, wH& ,Gw. ,Gw8 ,Hw. ,Hw8 ,GwK G&wK ,GwT GTw& ,Gwj G&wj ,Hw",
+"j wHs, fw, -wf f,wH gw- w,f. f8-w fwH,. w8g- w,fK fK-w f,wT fT-w f,wj fj-w ",
+"fwT,j s-gw w4, w&4 ,4wB ,4wa w5, w5& ,5wB ,5wa ,4wK 4&wK ,4wT 4Tw& ,4wj 4&w",
+"j ,5wT w5s, w=, -w= w,=B =a-w =,w5 w>- w=5,B wa-> w,=K =K-w =,wT =T-w =,wj ",
+"=j-w =Tw,5 s-w> ,4wG 4Gw& ,4wH 4Hw& ,Gw5 G5w& ,Hw5 H5w& w4G,K w&4GK wH4,T w",
+"H&4T w5G,j w5&Gj wH5,T sw4,G =,fw f=-w =,wH -wg= f,w5 -wf> =Hw,5 g-w> fw=,K",
+" -wf=K =Hw,T -wTg= fw5,j w>f-j =Hw,j gws-> wP, w&P ,PwB ,awP ,Pw. ,8wP wP,.",
+"B w8a,P wQ, wQ& ,QwT ,Qwa ,Qwj ,Qw8 wQT,j wQs, ,Pw* -wP wP*,B wa-P wP*,. w8",
+"-P P*.w,B -w8aP ,Qw* -wQ wQT,* wQ-T wQ*,j wQ-j P*jwT, sP-w Yw, Yw& wHY, wHY",
+"& w,Y. w8Y& YwH,. Yw8,H wQY, wQY& Zw, Zw& wjY, w&Yj wjZ, s,Zw fwY, Y-w Yfw,",
+"H Y-gw Yfw,. Y8-w fwHY,. gwY-8 f,wQ fQ-w fwZ, Z-w Yfjw, Yj-w Zwf,j Y-sw ow,",
+" ow& w,oB wao& w5o, w5o& ow5,B ow8,a wQo, wQo& wTo, wTo& pw, pw& wTp, s,pw ",
+"w=o, o-w ow=,B oa-w ow=,5 w>o- w=5o,B o-w>a =,wQ =Q-w owT=, oT-w w=p, -pw p",
+"w=,T o-sw Y,o owY& oHY, oaY, o,Y5 o8Y, Yw5,H Yw5,a YQo, Yw&oQ Y,oZ owZ& Y,p",
+"w Y&pw Z,pw Y,os x, x- x,H xg- x,5 x-> ,Hx5 g-x> x,Q x-Q xZ, xZ- xp, xp- Zp",
+"x, yx- wI w!I wD wDa wI. w8I wD. wD8 wIK IKw! wDT TIwa wjI 8Iwj wDj swD wI*",
+" w+I wD* w+D I*w. +Iw8 D*w. +Dw8 I*wK +IwK D*wT +DwT I*wj +Iwj D*wj w+sI wG",
+"I GIw! Jw Jwa GIw. G8wI Jw. Jw8 GIwK w!GIK JwT JTwa GjwI w8GIj Jwj swJ fwI ",
+"fIw+ Jwf gwJ wIf. fIw8 J.fw J8gw wIfK fw+IK fTJw wTgJ fIwj fw8Ij fwJj sJgw ",
+"w4I 4Iw! wD4 4Dwa w5I 48wI w5D 4Dw8 4IwK w!4IK 4DwT wD4Ta 4Iwj w58Ij 4Dwj w",
+"5sI =Iw w+=I =Dw w+=D w5=I w>I w5=D w>D wI=K =Iw+K wD=T =Dw+T wj=I >Iwj wD=",
+"j =Dsw 4GwI w!4GI Jw4 waJ4 G5wI w5G8I Jw5 w5J8 w4GIK 4GIw!K wTJ4 Jw4Ta w5GI",
+"j 4G8wjI w5Jj s4Jw fw=I =Ifw+ J=w J=gw fIw5 >Ifw fwJ5 J>w =IfwK fw+=IK =TJw",
+" J=gwT =Ijfw w>fIj =jJw J>sw wIP IPw! wDP DPwa IPw. 8IwP DPw. D8wP wQI QIw!",
+" wQD QDwa QIwj Q8wI QDwj wQsI IPw* +IwP DPw* +DwP IP*w. w+8IP wDP*. w+D8P Q",
+"Iw* +QwI QDw* +QwD wQI*j w+Q8I wQD*j sw+QD YwI w!YI JwY YaJw wIY. YIw8 Y.Jw",
+" Y8Jw YIwQ YwQI! ZwJ waZJ YIwj Yw8QI YjJw sJZw YIfw YIw+ YfJw JwgY YfwI. Yf",
+"8wI YJfw. Jw8gY fIwQ Yw+QI JwZf gZJw YfjwI Yw+Ij JwjZf gwZsJ owI w!oI owD w",
+"Doa w5oI w8oI w5oD wDo8 wQoI owQI! wQoD owDQa pwI w8pI pwD sIpw =Io o+=I ow",
+"=D oa=I =5oI =Io> owD=5 oDw> oI=Q ow+QI oT=I ow+QD =Ipw pIw> =Dpw =Ios oIYw",
+" YwoI! oJw oaJw YIw5 Yw58I Y5Jw o8Jw YwoQI oIQYw! oJZw oJZwa pIYw pwY8I Jpw",
+" oJsw xI x+I xJ xJg x5I x>I xJ5 xJ> xQI +QxI xZJ gZxJ xpI p>xI xJp yxJ hw h",
+"w& hwD cw hw. hw8 h.wD cw8 hwK hKw& hwT cwT hwj w8hj wDhj hsw hw* -wh h*wD ",
+"cw- w*h. h8-w hwD*. w8c- w*hK hK-w h*wT hT-w h*wj hj-w hwT*j s-cw hwG hGw& ",
+"Jwh cwJ wGh. hGw8 h.Jw h8Jw wGhK hwG&K hTJw wTcJ hGwj hw8Gj hjJw sJcw hfw h",
+"f-w hfJw iw h.fw fwh8 Jwhf. iw8 hKfw -whfK fwhT iwT fwhj -wjhf Jwjhf isw hw",
+"4 w&h4 wDh4 cw4 hw5 w5h8 wDh5 cw5 w4hK hw4&K wTh4 wTc4 w5hj hw5&j w5hT h4sw",
+" h=w -wh= hw=D cw= w=h5 h>w h=w5D cw> =Khw h=-wK hw=T =Tcw hw=j hjw> h=Tw5 ",
+"swh> w4hG hw4G& h4Jw c4Jw hGw5 hw5G8 h5Jw c5Jw hw4GK w&Gh4K Jwh4T cwJ4T hw5",
+"Gj h4Gw&j Jw5hT cw5sJ fwh= h=f-w Jwh= iw= fwh5 hfw> J=hw5 iw> h=fwK -wfh=K ",
+"J=hwT =Tiw h=jfw h>wfj J=jhw swi> hwP w&hP wDhP cwP wPh. w8hP hwDP. w8cP hw",
+"Q w&hQ wQhT cwQ wQhj wQh8 hwQDj hQsw wPh* hP-w hwDP* cP-w hwP*. -wh8P wD*hP",
+". cw-8P h*wQ hQ-w hwQD* cQ-w hwQ*j -wQh8 hQ*wDj cwQs- hYw Y&hw JwhY Ycw h.Y",
+"w Ywh8 hYJw. Y8cw YwhQ hYwQ& hZw Zwc Ywhj hY8wQ hjZw swhZ Yfhw -whY hYJfw i",
+"Yw hYfw. hY8-w JwfhY. Ywi8 fwhQ -wQhY hfZw iZw hYjfw Y-jhw hZwfj sYiw oh oh",
+"& ohD ohc oh5 oh8 oDh5 h5oc ohQ o&hQ ohT hQoc hpo h8pw hTpw hso oh= oh- =Do",
+"h c=oh o=h5 h>o oh=5D och> =Qoh hQo- =Toh =Qcw h=pw o-hp ohTp= ohs= ohY Y&o",
+"h oJh ohYc Ywh5 Y8oh h5oJ h8oJ oYhQ ohYQ& hZo ochZ hYpw oh8Yp Zwhp oJhs xh ",
+"xh- xJh ix xh5 xh> hJx5 ix> xhQ h-xQ xZh ixZ xph hpx- hZxp ixy w6 w!6 w6B w",
+"a6 w1 w18 w1B w1a w6K 6!wK wT6 6Twa w1j 68wj w1T sw6 w6* w+6 6*wB 6+wa w1* ",
+"w1+ 1*wB 1+wa 6*wK 6+wK 6Tw* 6+wT 6*wj 6+wj 1Tw* w1s* w6G 6Gw! wH6 6Gwa w1G",
+" 6Gw8 w1H 6Hw8 6GwK w!6GK 6GwT wH6Ta 6Gwj w1G8j 6Hwj w1sG fw6 w+f6 wHf6 gw6",
+" fw1 w1f8 wHf1 gw1 w6fK fw6+K wTf6 wTg6 w1fj fw1+j w1fT g6sw w46 6!w4 46wB ",
+"4aw6 7w 7w8 7wB 7wa 46wK w!46K 4Tw6 wT46a 7wj 78wj 7wT sw7 w=6 =6w+ w6=B =6",
+"wa 7w= w>7 =B7w =a7w w6=K w=6+K =6wT =Tw6+ =j7w wj7> =T7w 7sw> 4Gw6 w!46G 4",
+"Hw6 wH46a 7wG w87G 7wH wH7a w46GK 4G6w!K wH46T 4GTwa6 wj7G 7wG8j wH7T sG7w ",
+"w=f6 fw=6+ =6wH w=g6 7fw w>7f =H7w g7w fw=6K w=+f6K =Hw6T gw=6T fj7w w>7fj ",
+"fw7T swg7 w6P 6Pw! 6PwB 6awP w1P 68wP 1PwB 1awP wQ6 6Qw! 6QwT 6Qwa w1Q 6Qw8",
+" 1QwT w1sP 6Pw* 6+wP w6P*B w+6aP 1Pw* 1+wP w1P*B w1+aP 6Qw* 6+wQ wQ6T* w+Q6",
+"T 1Qw* 1+wQ w1QT* sw6+Q Yw6 w!Y6 wHY6 waY6 Yw1 w1Y8 wHY1 w1Ya wQY6 Yw6Q! Zw",
+"6 waZ6 w1Yj Yw1Q8 Zw1 s6Zw Yf6 f6Y+ YHf6 Yfg6 fwY1 f6Y8 Yf61H Ywg1 fQY6 Yf6",
+"+Q Y6Zf g6Zw f6Yj Yf6+j fwZ1 g1Zw ow6 w!o6 w6oB o6wa 7wo o87w 7Bow ow7a o6w",
+"Q ow6Q! o6wT owT6a pw7 w87p 7Tpw 7spw =6ow o6w+ ow=6B ow+6a ow7= o>7w 7o=wB",
+" w>o7a =6wQ ow+6Q owT=6 ow+6T p=7w 7pw> pw7=T pw>7s owY6 Ywo6! o6wH Ywao6 7",
+"Yw Y87w 7HYw Ya7w Ywo6Q owQY6! owZ6 Zwo6a pw7Y pw7Y8 7Zw 7Zsw x6 x6+ x6H xg",
+"6 x7 x7> x7H xg7 x6Q 6+xQ xZ6 gZx6 xp7 7px> xZ7 yx7 ?w ?w& ?wB ?wa ?w1 :w ?",
+"Bw1 :wa ?wK ?Kw& ?wT wT?a ?wj :wj w1?T s?w ?w* -w? w*?B ?a-w ?*w1 :w- ?w1*B",
+" wa:- w*?K ?K-w ?*wT ?T-w ?*wj ?j-w ?wT1* s-:w ?wG w&?G ?wH wH?a w1?G :wG w",
+"1?H :wH wG?K ?wG&K wH?T ?wHT& wj?G wj:G wH?j sG:w ?fw -w?f fw?H g?w f1?w :f",
+"w ?wHf1 gw: ?Kfw ?f-wK fw?T ?Tgw fw?j fj:w ?fTw1 s?gw ?w4 ?4w& w4?B ?4wa 7w",
+"? :w7 7B?w ?a7w w4?K ?w4&K ?4wT ?wT4a ?j7w wj7: ?T7w 7s:w ?w= ?=-w =B?w ?w=",
+"a ?=7w Aw ?w=7B Awa =K?w ?w=-K ?w=T -wT?= ?w=j Awj 7wT?= Asw w4?G ?w4G& ?4w",
+"H ?wH4a ?G7w 7G:w ?H7w 7H:w ?w4GK w&4?GK ?wH4T ?G4wT& ?wj7G :w7Gj 7wH?T :wH",
+"7s fw?= ?w=f- ?w=H ?wg= 7w?f Afw 7wH?f Agw ?w=fK -w=?fK ?fTw= g?w=T ?fj7w f",
+"wAj 7fT?w gwAs ?wP w&?P wP?B wa?P w1?P :wP ?w1PB wa:P ?wQ w&?Q wQ?T wQ?a w1",
+"?Q :wQ ?wQ1T sP:w wP?* ?P-w ?wP*B ?-Pwa ?w1P* :P-w w1*?PB :w-aP ?*wQ ?Q-w ?",
+"wQT* -wQ?T ?wQ1* :Q-w ?Q*w1T :wQs- ?Y ?Y& ?YH ?Ya ?Y1 ?Y: Y1?H ?HY: ?YQ Y&?",
+"Q ?ZY ?aZw ?Yj ?QY: ?jZw s?Y ?Yf ?Y- Yf?H g?Y Y1?f :f?Y ?Yf1H Y:g? Yf?Q ?QY",
+"- ?fZw ?Zgw Yf?j ?jY- ?ZYf1 sYg? o?w o&?w ?Bow ow?a o?7w :wo 7wo?B oa:w ow?",
+"Q ?wQo& ow?T o?Twa ?pw :wp ?Tpw ?psw ow?= -wo? ?w=oB o-?wa ?w=7o Aow o?=7wB",
+" owAa ?w=Q o-?wQ o?Tw= o-T?w ?wp= Apw ?pw=T swAo ?Yo Y&o? oY?H Yao? ?Y7 :w7",
+"Y ?H7Y ?a7Y oY?Q ?YoQ& o?Zw ?ZoYa ?pY Y:?p 7Z?Y ?psY x? x?- x?H x?g x?7 Ax ",
+"?Hx7 Axg x?Q ?-xQ x?Z g?xZ x?p Axp ?Zxp Axy w6I 6Iw! wD6 6Dwa w1I 68wI w1D ",
+"6Dw8 6IwK w!6IK 6DwT wD6Ta 6Iwj w18Ij 6Dwj w1sI 6Iw* 6+wI 6Dw* 6+wD 1Iw* 1+",
+"wI 1Dw* 1+wD w6I*K w+6IK wD6T* w+D6T w1I*j w1+Ij w1DT* sw6+D 6GwI w!6GI Jw6",
+" waJ6 1GwI w1G8I Jw1 w1J8 w6GIK 6GIw!K wTJ6 Jw6Ta w1GIj 6G8wjI w1Jj s6Jw w6",
+"fI fw6+I fwJ6 g6Jw fIw1 fw1+I fwJ1 g1Jw fw6IK w+If6K Jwf6T gwJ6T fw1Ij f6Iw",
+"+j Jw1fT gwsJ6 4Iw6 w!46I 4Dw6 wD46a 7wI w87I 7wD wD7a w46IK 4I6w!K wD46T 4",
+"TIwa6 wj7I 7w8Ij wD7T sI7w w6=I =Iw6+ =6wD =Dw6+ =I7w 7Iw> =D7w 7Dw> =Iw6K ",
+"w+6=IK =Dw6T =D6w+T 7w=Ij w>7Ij 7wD=T w>D7s w46GI 4G6w!I w4J6 Jw64a wG7I 7w",
+"G8I 7Jw 7aJw 4G6wIK 6!w4GIK Jw64T wT4J6a 7wGIj w8G7Ij 7TJw 7Jsw =Ifw6 fw6=I",
+"+ w=J6 J=gw6 fw7I w>7fI 7wJ= 7Jgw fw6=IK =6w+fIK J=w6T gw6J=T 7fwIj 7fIw>j ",
+"J=j7w J>w7s 6IwP w!6IP 6DwP wD6aP 1IwP w18IP 1DwP w1D8P 6QwI wQ6I! 6QwD wQD",
+"6a 1QwI w1Q8I 1QwD sw6QD IP6* w+6IP wD6P* w+D6P w1IP* w1+IP w1DP* w1+DP wQ6",
+"I* w+Q6I wQD6* w+Q6D w1QI* w1+QI w1QD* sIP6* w6YI Yw6I! Y6Jw YJ6wa YIw1 Yw1",
+"8I Y1Jw Jw1Y8 Yw6QI wQIY6! Z6Jw ZwJ6a Yw1QI Y6IwQ8 Z1Jw sYwJ6 YIf6 Yf6+I Jf",
+"Y6 gY6Jw Yf61I Yf68I Jw1Yf gw1YJ Yf6QI Y6Iw+Q Zf6Jw gwZJ6 Yf6Ij Y6IfQ8 Zw1J",
+"f gwZJ1 w6oI ow6I! o6wD owD6a ow7I 7oIw8 ow7D 7wDo8 ow6QI wQ6oI! owD6Q oD6w",
+"Qa 7Ipw pw78I 7Dpw osI7w =6oI ow+6I owD=6 ow+6D 7o=I w>o7I 7wDo= w>D7o =Qw6",
+"I o+6=QI oTI=6 o+6=TI pw7=I pw>7I pwD7= osI7= Ywo6I owIY6! J6ow oJw6a 7IYw ",
+"7Yw8I 7woJ oJ87w owQY6I o!Yw6QI oJZw6 Zw6oJa pw7YI 7Y8pwI Zw7J oJs7w x6I 6+",
+"xI xJ6 gJx6 x7I 7>xI xJ7 g7xJ 6QxI x6+QI ZJx6 xZJg6 7pxI xp7>I 7ZxJ x7yJ h?",
+"w w&h? ?wD cw? hw1 :wh w1?D :wc ?Khw ?w&hK ?whT ?Tcw ?whj hj:w w1hT :whs h*",
+"?w h?-w ?*wD -w?c h*w1 -wh: ?wD1* :c-w ?w*hK -w?hK ?wDT* cw?-T ?wjh* :wh-j ",
+"?wD*j :wcs- ?Ghw ?wGh& ?Jw cw?J hGw1 :Ghw h1Jw :Jw ?wGhK hw&?GK ?TJw cw?JT ",
+"?wjhG :whGj ?jJw ?Jsw hw?f ?fh-w Jw?f i?w fwh1 hf:w Jw1?f i:w ?fhwK -wh?fK ",
+"?fTJw ?wiT ?fjhw :fwhj ?Jjfw s?iw ?wh4 ?w4h& ?4wD c4?w 7hw :w7h ?D7w 7cw ?w",
+"4hK h4&?wK ?wD4T cw?4T hj7w :w7hj hT7w 7hsw ?wh= ?w=h- ?w=D ?wc= 7wh= Ahw 7",
+"wDh= Acw ?w=hK -w?h=K h=T?w cw=?T h=j7w hwAj 7hTw= hsAw ?w4hG hw4?G& J4?w c",
+"w?J4 7Ghw :w7hG 7w?J :w7J hw4?GK hGw&?4K ?Jw4T ?J4cwT 7hwGj 7hG:wj ?J7wT hs",
+"7Jw ?w=hf ?f-h=w ?wJ= ?wi= hf7w hfAw ?J7fw Aiw ?fwh=K =K?f-wh ?J=wT i?w=T 7",
+"hfwj Ahjfw J=j?w isAw h?P h&?P ?DhP hP?c ?Ph1 hP:w ?wD1P :Pcw ?whQ ?wQh& ?T",
+"hP ?Qcw ?Phj hQ:w ?wQ1D hPs? h*?P ?-hP ?wDP* cw?-P h?P1* :wh-P ?D*h1P :wc-P",
+" ?wQh* -wQh? ?wQD* cwQ?- ?Pjh* :wQh- ?Q*w1D :wc-Q ?Yh Y&h? ?JY ?Yc h1?Y hY:",
+"w Y1?J Y:?J hQ?Y ?YhQ& ?YhZ Yc?Z hj?Y :wQhY h1Zw ?JsY ?fhY h?Y- YJ?f i?Y hY",
+"1?f ?Y:hf ?JYf1 ?Yi: ?fQhY ?Y-hQ hZ?Yf ?ZiY ?Yjhf :wQhf hZwf1 s?iY oh? o&h?",
+" ?Doh ?coh 7ho oh: 7Doh oh7c hQo? oh?Q& hTo? ohc?Q oh?p :whp ?Dpw ohs? o?h=",
+" h?o- oh?=D ohc?- 7oh= Aoh 7ho=D ohAc oh?=Q oh-?Q ohT?= oh-?T hpo?= hpAo oh",
+"T7= hsAo oh?Y oh?Y& ?Jo oc?J 7hY 7hY: 7J?Y 7hYc oh?YQ ?YQoh& oJ?Z hZo?c ?Yh",
+"p :wphY 7YhZ Yc?p x?h h?x- x?J ix? x7h Axh ?Jx7 Aix h?xQ x?h-Q hZx? x?iZ hp",
+"x? xpAh hZx7 yAix wR w!R wRB waR wR. w8R R.wB R8wa wM wM! wTR waM wMj w8M R",
+"Twj swR wR* w+R R*wB R+wa R*w. R+w8 wR*.B w+R8a wM* w+M RTw* R+wT R*wj R+wj",
+" wTR*j w+sR wRG RGw! wHR RGwa RGw. RGw8 RHw. RHw8 wMG GMw! wHM GawM RGwj G8",
+"wM RHwj wHsR fwR w+fR wHfR gwR wRf. w8fR fwRH. w8gR fwM w+fM wHfM gwM wMfj ",
+"w8fM fwTRj gRsw wR4 R4w! R4wB R4wa w5R R4w8 R5wB R5wa wM4 4Mw! R4wT 4awM w5",
+"M 48wM R5wT w5sR =Rw w+=R wR=B wa=R w5=R w>R =Rw5B >Rwa =Mw w+=M wT=R wa=M ",
+"w5=M w>M =RTw5 >Msw R4wG w!R4G R4wH wHR4a RGw5 w5RG8 RHw5 wH5R8 4GwM wM4G! ",
+"4HwM wHM4a G5wM w5MG8 H5wM swR4G =Rf =+fR fR=H =Rgw f5=R =Rf> =RfH5 gRw> fw",
+"=M =Rf+M fR=T =Mgw fR=j fw>M =RfHj >Mgw wRP RPw! RPwB RawP RPw. R8wP wRP.B ",
+"w8RaP Sw Sw! SwT Swa Swj Sw8 STwj swS R*wP R+wP wRP*B w+RaP wRP*. w+R8P P*.",
+"wRB aP*w8R Sw* Sw+ wTS* w+Sa wjS* w+S8 SwT*j s*Sw YwR w!YR YRwH YRwa wRY. Y",
+"Rw8 YwRH. Yw8RH SwY S!Yw ZwS SaZw YjSw YwS8 wjSZ SsZw fRYw YRw+ YfwRH YwgR ",
+"YfwR. Yf8wR fRHYw. gwYR8 Sfw YwS+ ZwSf gwS fjSw fwS8 SfZwj swgS owR w!oR wR",
+"oB oRwa oRw5 oRw8 owR5B ow8Ra Swo S!ow oTSw owSa pwS S8pw wTSp Sspw ow=R oR",
+"w+ ow=RB ow+Ra ow=R5 >Row =R5owB w>oRa S=w owS+ =TSw =aSw pwS= S>w pw=ST S>",
+"sw YRow YwoR! oRwH YwaoR YRw5 Yw5R8 Yw5RH Yw5Ra YwSo SwoY! oZSw SwaoZ YpSw ",
+"pwYS8 SZpw sYoSw xR xR+ xRH xgR xR5 x>R RHx5 g>xR xS xS+ xZS xgS xpS x>S SZ",
+"xp yxS wR, w&R ,RwB ,Rwa ,Rw. ,Rw8 wR,.B w8R,a wM, wM& ,RwT ,awM ,Rwj ,8wM ",
+"wTR,j wMs, ,Rw* -wR wR*,B wa-R wR*,. w8-R ,R*w.B -wR8a ,Mw* -wM wTR,* wT-R ",
+"wM*,j w8-M ,RTwj* sR-w ,RwG RGw& ,RwH RHw& wRG,. w8R,G wHR,. wH8,R ,GwM GMw",
+"& ,HwM HMw& wMG,j w8M,G wHM,j swR,G wRf, fR-w fwR,H gR-w fwR,. -wfR8 wH,fR.",
+" gw-R8 f,wM fM-w fwT,R gM-w fwM,j -wMf8 fR,wHj gws-R ,Rw4 R4w& wR4,B waR,4 ",
+",Rw5 R5w& w5R,B w5a,R ,4wM 4Mw& wTR,4 wT&R4 ,5wM 5Mw& w5T,R swR,4 wR=, =R-w",
+" =Rw,B -w=Ra =Rw,5 -Rw> w5,=RB w>-Ra =,wM =M-w =RTw, -wT=R =Rjw, >M-w =R,w5",
+"T w>Ms- R4,G w&R4G wHR,4 wH&R4 w5R,G w5&RG wH5,R wH5R& wM4,G wM&4G wHM,4 wH",
+"M4& w5M,G w5MG& wH5,M wH5M& =,fR f-=R =Rf,H g=R-w =Rf,5 w>f-R =R,wH5 gw>-R ",
+"=Rf,M -wMf= =Rf,T gwM-= =Rf,j w>Mf- =R,f5T w>Mg- ,RwP R&wP wRP,B waR,P wRP,",
+". w8R,P ,RPw.B ,R8waP Sw, Sw& wTS, wTS& wjS, w8S& SwT,j s,Sw wRP,* wR-P P*B",
+"wR, -wRaP P*.wR, -wR8P ,RwBP*. w8R-Pa w*S, S-w SwT,* Sa-w Sw*,j S8-w wT*S,j",
+" S-sw wRY, YRw& YwR,H Ywa,R YwR,. Yw8,R wHRY,. Y8RwH& YwS, YwS& S,Zw S&Zw S",
+"Y,wj Sw8Y& ZwS,j sYwS& Yfw,R -RYw fwRY,H gwY-R fwRY,. Y-wR8 ,Hw.YfR Y-Rgw8 ",
+"fwS, SwY- SfZw, S-gw Sfw,j Sf-w8 ZwjSf, gwSs- wRo, oRw& owR,B owa,R owR,5 o",
+"w8,R w5Ro,B oaRw5& owS, owS& Swo,T Swao& S,pw S&pw pwS,T os,Sw ow=,R -Row =",
+"R,owB o-wRa =R5ow, o-w>R =Bow,R5 w>Ro-a w=S, Swo- S=w,T o-TSw pw=S, pwS- S=",
+"Tpw, os-Sw YRo, Yw&oR Y,oRH Yao,R Yw5,R Yw5R& Y5RoH, Y5Roa, Y,So Sw&oY oZ,S",
+"w Zw&So pwYS, pw&SY ZwpS, os,SY x,R x-R ,RxH g-xR ,Rx5 ->xR x,RH5 xg->R xS,",
+" x-S SZx, gSx- Spx, S-xp xZpS, y-xS [w [w! [wD [wa [w. [w8 w.[D [8wD [wM [!",
+"wM Vw Vwa [wj [8wM Vwj swV [w* [w+ [*wD wD[+ w.[* w8[+ [wD*. [w+D8 [*wM wM[",
+"+ Vw* Vw+ [*wj wj[+ wjV* s*Vw [wG wG[! Jw[ wa[J w.[G wG[8 J.[w [wJ8 [GwM [w",
+"GM! VwJ waVJ wG[j [w8GM JjVw sJVw [fw w+[f [fJw g[w f.[w [wf8 Jw[f. w8g[ [w",
+"fM [fw+M Vfw gwV [wfj [f8wM fjVw swg[ [w4 w![4 wD[4 wa[4 [w5 w8[4 [5wD wa[5",
+" wM[4 [w4M! Vw4 waV4 wM[5 [w58M Vw5 s4Vw [= [=+ [=D [=a [=5 [>w [5=D =D[> [",
+"=M [+=M Vw= =aVw [=j >M[= =jVw s=[ wG[4 [w4G! [wJ4 Jw[4a wG[5 [w5G8 [wJ5 Jw",
+"5[8 [w4GM wMG[4! J4Vw VwJ4a [w5GM [4Gw8M J5Vw Vw5sJ [=f [+f= J=[ g[= f5[= f",
+">[= J5[= [>gw =M[f [=f+M VwJ= V=g[ =j[f [>f=M Jj[= s=g[ [wP wP[! wP[D wP[a ",
+"[Pw. wP[8 [wDP. [w8DP Sw[ S![w VwS SaVw wjS[ [wS8 wjSV SsVw wP[* wP[+ [wDP*",
+" [w+DP [wP*. [w+8P [*PwD. [+PwD8 [wS* [wS+ S*Vw S+Vw S[*wj Sw+[8 VwS*j Vw+S",
+"s Yw[ [!Yw [JYw [wYa Y.[w [wY8 Yw[J. Jw8[Y YwS[ Yw[S! ]w ]wa [wYj Sw8[Y ]wj",
+" ]sw Yw[f [wY+ YJf[w Ywg[ Yw[f. [f8Yw [fYJw. g[wY8 [fSw Sw+[f ]fw ]gw [fjSw",
+" Sf8[w fw]j gw]s o[w o![w [woD [woa w5o[ [wo8 o[w5D o[8wD o[Sw Swo[! oVw oa",
+"Vw pw[ w8[p Vwp oVsw [=o o+[= =Do[ =ao[ [5o= o[w> [=o5D [>o=D S=[ S+[= VwS=",
+" S[=a [p= [>S= pwV= VwS> Ywo[ Yw[o! Jwo[ oJ[wa [wY5 o[8Yw oJ[w5 oJ8[w Yw[So",
+" o[YSw! ]ow ow]a Yw[p pw[Y8 ]pw sw]o x[ x[+ xJ[ xg[ x[5 x[> J5x[ g[x> x[S S",
+"[x+ ]x ]xg xp[ S>x[ ]xp ]yx hw[ [w& wD[h cw[ h.[w [wh8 hw[D. w8[c hwM w&hM ",
+"Vwh cwV [whj w8hM hjVw Vwhs [*hw [-w hw[D* [-cw hw[*. w8[- wD*[h. cw[-8 h*w",
+"M hM-w V*hw V-w hwM*j [w-j Vwh*j V-sw hG[w wG[& [Jhw [cJw hw[G. hw8[G Jw[h.",
+" cwJ[8 hGwM hwMG& VhJw cJVw hwMGj hw8GM VwJhj cwVsJ hw[f [f-w Jw[hf i[w [fh",
+"w. [-fw8 [fhJw. [wi8 fwhM [-fwM hfVw iVw [fjhw [-jfw Vfwhj swiV h4[ w&[4 hD",
+"[4 h4[c [wh5 [4h8 hw5[D [wc5 [4hM hwM4& h4Vw c4Vw [4hj hw58M h5Vw h4[s [=h ",
+"[-= [h=D c=[ h5[= w>[- [=h5D [>cw hw=M =M[- h=Vw Vwc= hj[= =j[- Vw=h5 Vwh> ",
+"hG[4 h4[G& [Jh4 cwJ[4 hw5[G h4[G8 Jw5[h cw5[J hwM4G h4GwM& VwJh4 cwVJ4 hw5G",
+"M h4Gw8M Vw5hJ cwVJ5 [fh= f-[= hJ[= i[= [=hf5 [-=f> J=[h5 [>iw [=hfM [-=fM ",
+"J=Vhw Vwi= [=jhf [-=fj J=[hj s=i[ [whP wP[& hw[DP [wcP hw[P. hw8[P hPD[w. c",
+"w[8P Shw S&hw VwSh Scw hjSw h8Sw VwhSj Shsw hw[P* [w-P hPD[w* cw[-P hP*[w. ",
+"[-w8P h*wD[P. [-8cwP S*hw Sw[- VwhS* cwS- Shw*j [-jSw Sh*Vwj V-wSs [hYw [wY",
+"& hYJ[w Yw[c hY[w. hY8[w Jw[hY. Ycw[8 SwhY Sw&hY ]hw ]cw hYjSw Sh8Yw hw]j h",
+"s]w hY[fw Yw[- Jw[hYf Ywi[ [fwhY. Y-[w8 h.Jw[fY i[Yw8 hfSw Shf-w hf]w ]iw S",
+"hfwj [-jYw ]hfwj iw]s oh[ [ho& [hoD o[cw h5o[ h8o[ oh[5D ohc[5 Sho S&oh oVh",
+" ohSc pwSh Soh8 oVhp oVhs [=oh o-[ oh[=D [-oc oh[=5 [>oh [=5ohD cw>o[ Sh= o",
+"hS- V=Sh cwS= S=hp S=h> oVhp= Shs= o[hY oh[Y& hJo[ oJh[c oh[Y5 oh8[Y oJh[5 ",
+"oJh[8 SohY ShoY& ]oh oh]c pw[hY oh8SY hp]o hs]o x[h x[- hJx[ ix[ h5x[ h>x[ ",
+"xJ[h5 x[i> xhS Shx- ]xh ]ix hpx[ h>xS xp]h ix]y wq wq! wqB wqa wq1 wq8 q1wB",
+" q8wa wqM q!wM wqT qTwa lw lw8 lwT lws wq* wq+ wBq* q+wa q*w1 q+w1 wq1*B wq",
+"+1a q*wM q+wM q*wT q+wT lw* lw+ wTl* l+sw wqG w!qG wqH qGwa qGw1 qGw8 qHw1 ",
+"qHw8 qGwM wqGM! qGwT wqHaM lwG w8lG lwH lGsw fq fq+ fqH gqf fq1 fq8 qHf1 g1",
+"fq fqM q+fM fqT gMfq lfq l+fq lHfq glw wq4 w4q! q4wB w4qa 7wq w87q 7Bwq wq7",
+"a q4wM wq4M! w4qT wqT4a lw7 w87l 7Tlw 7slw q=w w+q= =Bwq wq=a q=7w w>q 7wq=",
+"B waq> wq=M q=w+M wq=T q=Tw+ lw= lw> =Tlw swl= w4qG wq4G! w4qH wqH4a wq7G 7",
+"qGw8 wq7H 7wHq8 wq4GM qG4wM! wqH4T wT4qGa lG7w lw7G8 lH7w lws7G fq= q+f= =H",
+"fq g=fq 7fq fq> 7Hfq 7fgq =Mfq fq=+M =Tfq fqTg= 7flw w>lf =Hlw g7lw wqP wPq",
+"! qPwB wPqa q1wP wPq8 wq1PB wq8aP Swq S!wq wTSq wqSa lwS S8lw wTSl Sslw wPq",
+"* wPq+ wqP*B wq+aP wq1P* wq+1P q*Pw1B w1Pqa* wqS* wqS+ Sq*wT Sw+qT l*Sw l+S",
+"w lwST* lwsS+ Yqw q!Yw wHYq wqYa wqY1 wqY8 Yw1qH Yq8wH YqSw SwqY! Zqw waZq ",
+"lYw Y8lw lwZ sYlw fqY Y+fq qHYf gYfq Y1fq Y8fq fqY1H fq8gY Sfq S+fq Zqf Sfg",
+"q Sflw S8fq Zqlf gwlY oqw o!wq oBwq wqoa oq7w wqo8 7woqB 7waoq oqSw Swoq! w",
+"qoT Swaoq rw rw8 rwT rsw owq= wqo+ q=owB q=aow 7o=wq oqw> q=o7wB w>qoa q=Sw",
+" Sw+q= q=TSw S=awq rw= rw> =Trw swr> oqYw Yqow! wqoH Yqaow 7wYq Yq87w 7wHYq",
+" 7Yawq SwoYq YqoSw! oqZw Zqwoa rYw Ywr8 rZw sYrw xq xq+ xqH xqg xq7 xq> 7qx",
+"H gqx7 xqS Sqx+ xZq gqxZ xr xr> xrZ yxr ?qw wq& ?Bwq wq?a w1?q :wq ?qw1B wa",
+":q ?wM w&?M wq?T wa?M lw? lw: ?Tlw s?lw q*?w -qw ?qw*B wa-q ?qw1* -q:w w1*?",
+"qB :wq-a ?*wM ?M-w ?qTw* wq-T ?wl* l-w lw?T* swl- ?qG qGw& wq?H qG?a ?1qG ?",
+"G:q ?qG1H wq:H wM?G ?qGM& wH?M ?qGT& ?qlG lG:w ?wlH lH:w fq? fq- ?Hfq fqg? ",
+"f1?q :fq fq?1H :fgq ?Mfq fM-q ?Tfq ?wgM ?flw :flw fqTl? lwg? ?4wq w4q& ?qw4",
+"B ?qaw4 ?q7w :q7w ?q7wB :wq7a ?4wM ?wM4& ?qTw4 ?wa4M l?7w l:7w 7wTl? lws7? ",
+"?wq= q=-w ?w=qB -qw=a ?q7w= Aqw q=?7wB wqAa ?w=M -qw=M q=T?w -qTw= ?wl= Alw",
+" lw=?T lwAs ?4qG ?qG4& ?qG4H ?qG4a 7q?G :wq7G 7wH?q :wH7q ?qG4M ?G4wM& ?qG4",
+"T ?G4waM lw?7G lw:7G lwH7? :wH7l q=?f f-q= fq?=H fq-g= ?q7f Aqf 7fq?H gqAf ",
+"fq?=M fq-=M fqT?= fq-=T lf?7w lfAq fqT7? glAw wq?P wPq& ?qwPB ?qawP ?qw1P w",
+"q:P wq1?PB :wqaP S?w S&?w ?TSw ?aSw S?lw S:w lw?ST S?sw ?qwP* wq-P wq*?PB -",
+"qwaP wq1?P* :wq-P ?Bwq1P* -qa:wP S*?w Sw-q S?wT* -qTSw lw?S* S-lw S?Tlw* l-",
+"wSs ?Yq Y&?q ?HYq ?aYq Y1?q Yq:w ?Yq1H :wHYq S?Y S&?Y Zq?Y ?aSY lY? ?YS: ?Z",
+"lY s?lY fq?Y Y-q fq?YH ?Ygq fq?Y1 fqY: ?Y1fqH g?Y:q S?f S-?Y Sf?Z S?gw S?lf",
+" ?Yl- lY?Zf g?lY oq?w wqo& o?qwB o?awq ?q7ow oq:w o?q7wB :woqa o?Sw Sw&o? o",
+"?TSw S?aow r?w r:w ?wrT s?rw ?w=oq oq-w q=wo?B o-qwa o?q7w= oqAw =B7wo?q Ao",
+"awq ?wS= o-qSw S?=wT o-qwT ?wr= Arw r=T?w rsAw o?Yq Yq&o? o?HYq ?Yaoq ?q7Y ",
+":woYq ?Y7qH :woqH So?Y S?Yo& S?ZoY S?Yoa r?Y ?Yr: ?ZrY s?rY x?q xq- ?qxH g?",
+"xq ?qx7 Axq x?q7H xqAg x?S S?x- S?xZ g?xS xr? Axr r?xZ yxAr [qw [!wq wqD wa",
+"[q [w1 w8[q wD[1 wa[1 wM[q [qwM! Vwq waVq lw[ w8[l lwV Vwsq [q* w+[q [*qD q",
+"+wD [*w1 [1w+ [q*1D [q8D* [Mq* [q+wM [qV* wqV+ [ql* [wl+ l*Vw l+Vw qG[w [qw",
+"G! Jqw waJq wG[1 [q8wG [wJ1 wqJ8 [qwGM wMG[q! VwJq JqVwa [wlG lw[G8 lwJ Jqs",
+"w fq[ [+fq Jqf Jqgw [qf1 [qf8 J1fq J8fq [qfM fq[+M fqV Vfgq [lfq fq8[l Jqlf",
+" g[lw [4wq [qw4! w4qD [qaw4 7[w w87[ [w7D [w7a [qw4M [4Mwq! wqV4 Vwq4a 7[lw",
+" lw7[8 7Vw 7Vsw [=q [+q= [q=D [q=a 7[= w>7[ =D7[ =a7[ [q=M [=q+M Vq[= Vw=q+",
+" l=[ [>lw Vwl= 7[s= [qw4G [4Gwq! wqJ4 Jqw4a [w7G 7[wG8 7wJq Jq87w [4GwqM [!",
+"wq4GM JqVw4 Vw4Jqa lw7[G 7[Glw8 7Jlw lwJ7s [=fq fq[=+ Jq= J=gq 7[f [>7f Jq7",
+"f 7[gw fq[=M [=+fqM V=Jq Jq=gV 7[lf fq>[l Jql= g[l= wP[q [qwP! wPqD [qawP w",
+"P[1 [q8wP [w1DP [w1aP [qSw Sq[w! VqSw VwqSa [lSw Sw8[l SlVw lwVSs [Pq* [q+w",
+"P [q*DP [qaP* [q*1P [q8P* w1PqD* w1P[a* [qS* Sw+[q VwqS* Vw+Sq lw[S* lw+S[ ",
+"lwVS* Vw+Sl [qYw Yw[q! JwYq JqYwa [wY1 Yq8[w JqYw1 Jq8Yw Sq[Yw Yq[Sw! ]qw w",
+"q]a Yw[l lYw[8 ]lw lw]s [fYq fq[Y+ YJfq JqfgY fq[Y1 fq8[Y JqfY1 JqfY8 Sq[f ",
+"Sfq[+ ]qf gq]f lYf[q fq8S[ lf]q gl]w [qow o[qw! wqoD o[awq o[7w o[87w 7wDo[",
+" 7[aow Sq[ow o[qSw! oqVw oVwqa r[w [wr8 rVw swrV q=o[ [=oq+ [=oqD [=aoq 7o[",
+"= [>o7w 7[=oD w>qoD Sq[= S=[q+ oVwq= oVwq+ r[= [>rw Vwr= s=r[ Yw[oq o[wYq! ",
+"oqJw oJqwa Yw7[ 7[Yw8 oJq7w oJqw8 YqoSw[ Sqo[Yw! oq]w ]oqwa Ywr[ r[Yw8 ]rw ",
+"rs]w xq[ [qx+ xJq gqxJ x7[ 7[x> 7Jxq g7x[ Sqx[ xq[S+ ]xq xq]g xr[ r[x> ]xr ",
+"yx]r z z& zD zc z1 z: z1D z:c zM zM& zV zVc zl zl: zlV uz z* z- z*D zc- z*1",
+" z:- 1Dz* :cz- z*M z-M zV* zV- zl* zl- l*zV uz- zG zG& zJ zJc z1G z:G zJ1 z",
+"J: zGM GMz& zJV cJzV zlG l:zG zlJ uzJ zf zf- zJf iz zf1 z:f Jfz1 iz: zfM f-",
+"zM zVf izV zlf lfz: lfzJ uzi z4 z4& z4D zc4 z7 z7: z7D z7c z4M 4Mz& zV4 c4z",
+"V zl7 l:z7 z7V uz7 z= z-= z=D zc= z7= Az =Dz7 Azc z=M =Mz- zV= c=zV zl= Azl",
+" l=zV Azu z4G 4Gz& zJ4 cJz4 z7G 7:zG zJ7 7Jz: 4GzM z4GM& J4zV zJVc4 lGz7 zl",
+"7:G 7Jzl zJu7 zf= f-z= zJ= iz= z7f Azf 7Jzf Azi =Mzf zf-=M J=zV zVi= lfz7 z",
+"lAf l=zJ uzAi zP zP& zDP zcP z1P z:P 1DzP :czP zS zS& zVS zcS zlS z:S SlzV ",
+"uzS z*P z-P DPz* c-zP 1Pz* :-zP z*1DP z:c-P zS* z-S SVz* Scz- l*zS l-zS zlV",
+"S* z-uS zY zY& zJY zYc zY1 zY: YJz1 Y:zJ zYS SYz& ]z ]zc zlY lYz: ]zl uz] z",
+"Yf zY- YJzf izY Yfz1 Y:zf zJYf1 zYi: zfS Sfz- ]zf ]zi lYzf lYz- zl]f ]zui z",
+"o zo& zoD zoc zo7 zo: 7ozD 7czo zoS Soz& zoV Sczo zr zr: zrV uzr zo= zo- =D",
+"zo ocz- 7oz= Azo zo7=D zoAc z=S S-zo S=zV Scz= zr= Azr rVz= uzAr zoY Y&zo z",
+"oJ Yczo z7Y Y:zo 7Jzo Ycz7 SozY zoYS& ]zo zo]c zrY rYz: ]zr ]zur zx zx- zxJ",
+" izx zx7 Azx xJz7 izAx zxS x-zS ]zx iz]x zxr zxAr zx]r |                   ",
+NULL
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the data for MSOPs of 4-variable functions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_ReadMsops( char ** ppSopSizes, char *** ppSops )
+{
+    unsigned uMasks[4][2] = {
+        { 0x5555, 0xAAAA },
+        { 0x3333, 0xCCCC },
+        { 0x0F0F, 0xF0F0 },
+        { 0x00FF, 0xFF00 }
+    };
+    char Map[256], * pPrev, * pMemory;
+    char * pSopSizes, ** pSops;
+    int i, k, b, Size;
+
+    // map chars into their numbers
+    for ( i = 0; i < 256; i++ )
+        Map[i] = (char)(-1);
+    for ( i = 0; i < 81; i++ )
+        Map[(int)s_Data3[i]] = (char)i;
+
+    // count the number of strings
+    for ( Size = 0; s_Data4[Size] && Size < 100000; Size++ );
+    assert( Size < 100000 );
+
+    // allocate memory
+    pMemory = ABC_ALLOC( char, Size * 75 );
+    // copy the array into memory
+    for ( i = 0; i < Size; i++ )
+        for ( k = 0; k < 75; k++ )
+            if ( s_Data4[i][k] == ' ' )
+                pMemory[i*75+k] = (char)(-1);
+            else
+                pMemory[i*75+k] = Map[(int)s_Data4[i][k]];
+
+    // set pointers and compute SOP sizes
+    pSopSizes = ABC_ALLOC( char, 65536 );
+    pSops = ABC_ALLOC( char *, 65536 );
+    pSopSizes[0] = 0;
+    pSops[0] = NULL;
+    pPrev = pMemory;
+    for ( k = 0, i = 1; i < 65536; k++ )
+        if ( pMemory[k] == (char)(-1) )
+        {
+            pSopSizes[i] = pMemory + k - pPrev; 
+            pSops[i++] = pPrev;
+            pPrev = pMemory + k + 1;
+        }
+    *ppSopSizes = pSopSizes;
+    *ppSops = pSops;
+
+    // verify the results - derive truth table from SOP
+    for ( i = 1; i < 65536; i++ )
+    {
+        int uTruth = 0, uCube, Lit;
+        for ( k = 0; k < pSopSizes[i]; k++ )
+        {
+            uCube = 0xFFFF;
+            Lit = pSops[i][k];
+            for ( b = 3; b >= 0; b-- )
+            {
+                if ( Lit % 3 == 0 )
+                    uCube &= uMasks[b][0];
+                else if ( Lit % 3 == 1 )
+                    uCube &= uMasks[b][1];
+                Lit = Lit / 3;
+            }
+            uTruth |= uCube;
+        }
+        assert( uTruth == i );
+    }
+}
+
+#if 0
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManDeriveCnfTest()
+{
+    int i, k, Lit;
+    printf( "\n" );
+    for ( i = 80; i >= 0; i-- )
+    {
+        Lit = i;
+        for ( k = 0; k < 4; k++ )
+        {
+            if ( Lit % 3 == 0 )
+                printf( "%c", 'A' + k );
+            else if ( Lit % 3 == 1 )
+                printf( "%c", 'a' + k );
+            Lit = Lit / 3;
+        }
+        printf( "\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManDeriveCnfTest2()
+{
+    char s_Data3[81] = "!#&()*+,-.0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]abcdefghijklmnopqrstuvwxyz|";
+
+    unsigned uMasks[4][2] = {
+        { 0x5555, 0xAAAA },
+        { 0x3333, 0xCCCC },
+        { 0x0F0F, 0xF0F0 },
+        { 0x00FF, 0xFF00 }
+    };
+    char Buffer[100], * pCur;
+    FILE * pFile;
+    int CountCur, Counter = 0, nLines = 0;
+    int pLines[1<<16] = {0};
+    int pNums[1<<16] = {0};
+    unsigned uTruth, uTruth2, uCube, cCube;
+    char * pSops[1<<16] = {0};
+    char Sop[10];
+    char Cube[4];
+    int i, k;
+
+    pFile = fopen( "cands2.txt", "r" );
+    while ( fgets( Buffer, 100, pFile ) )
+    {
+        if ( Buffer[0] == '0' )
+            Extra_ReadHexadecimal( &uTruth2, Buffer+2, 4 );
+        else
+            uTruth2 = 0xFFFFFF;
+
+        // skip all chars till a-d or A-D
+        if ( Buffer[0] == '0' )
+        for ( pCur = Buffer; *pCur != '\n'; pCur++ )
+        {
+//            if ( *pCur >= 'a' && *pCur <= 'd' || *pCur >= 'A' && *pCur <= 'D' )
+            if ( *pCur == ':' )
+            {
+                pCur++;
+                break;
+            }
+        }
+        else
+            pCur = Buffer;
+
+
+        uTruth = 0;
+        CountCur = 0;
+        uCube = 0xFFFF;
+        for ( i = 0; i < 4; i++ )
+            Cube[i] = 2;
+
+        for ( ; *pCur; pCur++ )
+        {
+            if ( *pCur == '+' || *pCur == '\n' )
+            {
+                uTruth |= uCube;
+                uCube = 0xFFFF;
+
+                // get the cube
+                cCube = 0;
+                for ( i = 0; i < 4; i++ )
+                    cCube = 3 * cCube + Cube[i];
+                for ( i = 0; i < 4; i++ )
+                    Cube[i] = 2;
+
+                assert( cCube >= 0 && cCube < 81 );
+                Sop[CountCur] = cCube;
+                CountCur++;
+                if ( *pCur == '\n' )
+                {
+                    Sop[CountCur] = 0;
+                    break;
+                }
+            }
+            else if ( *pCur >= 'a' && *pCur <= 'd' )
+            {
+                uCube &= uMasks[*pCur-'a'][1];
+                Cube[*pCur-'a'] = 1;
+            }
+            else if ( *pCur >= 'A' && *pCur <= 'D' )
+            {
+                uCube &= uMasks[*pCur-'A'][0];
+                Cube[*pCur-'A'] = 0;
+            }
+        }
+        assert( *pCur == '\n' );
+        assert( uTruth2 == 0xFFFFFF || uTruth2 == uTruth );
+
+        Counter += CountCur;
+        pNums[uTruth] = CountCur;
+        pSops[uTruth] = ALLOC( char, CountCur );
+        memcpy( pSops[uTruth], Sop, CountCur );
+        pLines[nLines++] = Counter;
+    }
+    fclose( pFile );
+
+    printf( "Lines = %d. Counter = %d.\n", nLines, Counter );
+
+/*
+    // write the number of cubes
+    for ( i = 0; i < 65536; i++ )
+        printf( "%d,%d ", pNums[i], pNums[i] + pNums[0xffff & ~i] );
+    printf( "\n" );
+*/
+
+    // write the number of cubes
+    Counter = 0;
+    for ( i = 1; i < 65536; i++ )
+    {
+        CountCur = pNums[i];
+        assert( CountCur > 0 );
+        for ( k = 0; k <= CountCur; k++ )
+        {
+            if ( k < CountCur )
+            {
+                assert( pSops[i][k] >= 0 && pSops[i][k] < 81 );
+                printf( "%c", s_Data3[pSops[i][k]] );
+            }
+            else 
+                printf( " " );
+            if ( ++Counter == 75 )
+            {
+                printf( "\",\n\"" );
+                Counter = 0;
+            }
+        }
+    }
+    printf( "\n" );
+
+    return 1;
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/cnf/cnfFast.c b/abc-build/src/sat/cnf/cnfFast.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/cnf/cnfFast.c
@@ -0,0 +1,697 @@
+/**CFile****************************************************************
+
+  FileName    [cnfFast.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG-to-CNF conversion.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: cnfFast.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cnf.h"
+#include "bool/kit/kit.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Detects multi-input gate rooted at this node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_CollectLeaves_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper, int fStopCompl )
+{
+    if ( pRoot != pObj && (pObj->fMarkA || (fStopCompl && Aig_IsComplement(pObj))) )
+    {
+        Vec_PtrPushUnique( vSuper, fStopCompl ? pObj : Aig_Regular(pObj) );
+        return;
+    }
+    assert( Aig_ObjIsNode(pObj) );
+    if ( fStopCompl )
+    {
+        Cnf_CollectLeaves_rec( pRoot, Aig_ObjChild0(pObj), vSuper, 1 );
+        Cnf_CollectLeaves_rec( pRoot, Aig_ObjChild1(pObj), vSuper, 1 );
+    }
+    else
+    {
+        Cnf_CollectLeaves_rec( pRoot, Aig_ObjFanin0(pObj), vSuper, 0 );
+        Cnf_CollectLeaves_rec( pRoot, Aig_ObjFanin1(pObj), vSuper, 0 );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Detects multi-input gate rooted at this node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_CollectLeaves( Aig_Obj_t * pRoot, Vec_Ptr_t * vSuper, int fStopCompl )
+{
+    assert( !Aig_IsComplement(pRoot) );
+    Vec_PtrClear( vSuper );
+    Cnf_CollectLeaves_rec( pRoot, pRoot, vSuper, fStopCompl );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes inside the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_CollectVolume_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+    if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
+        return;
+    Aig_ObjSetTravIdCurrent( p, pObj );
+    assert( Aig_ObjIsNode(pObj) );
+    Cnf_CollectVolume_rec( p, Aig_ObjFanin0(pObj), vNodes );
+    Cnf_CollectVolume_rec( p, Aig_ObjFanin1(pObj), vNodes );
+    Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes inside the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_CollectVolume( Aig_Man_t * p, Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManIncrementTravId( p );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i )
+        Aig_ObjSetTravIdCurrent( p, pObj );
+    Vec_PtrClear( vNodes );
+    Cnf_CollectVolume_rec( p, pRoot, vNodes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derive truth table.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+word Cnf_CutDeriveTruth( Aig_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes )
+{
+    static word Truth6[6] = {
+        ABC_CONST(0xAAAAAAAAAAAAAAAA),
+        ABC_CONST(0xCCCCCCCCCCCCCCCC),
+        ABC_CONST(0xF0F0F0F0F0F0F0F0),
+        ABC_CONST(0xFF00FF00FF00FF00),
+        ABC_CONST(0xFFFF0000FFFF0000),
+        ABC_CONST(0xFFFFFFFF00000000)
+    };
+    static word C[2] = { 0, ~(word)0 };
+    static word S[256];
+    Aig_Obj_t * pObj = NULL;
+    int i;
+    assert( Vec_PtrSize(vLeaves) <= 6 && Vec_PtrSize(vNodes) > 0 );
+    assert( Vec_PtrSize(vLeaves) + Vec_PtrSize(vNodes) <= 256 );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i )
+    {
+        pObj->iData    = i;
+        S[pObj->iData] = Truth6[i];
+    }
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+    {
+        pObj->iData    = Vec_PtrSize(vLeaves) + i;
+        S[pObj->iData] = (S[Aig_ObjFanin0(pObj)->iData] ^ C[Aig_ObjFaninC0(pObj)]) & 
+                         (S[Aig_ObjFanin1(pObj)->iData] ^ C[Aig_ObjFaninC1(pObj)]);
+    }
+    return S[pObj->iData];
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes inside the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cnf_ObjGetLit( Vec_Int_t * vMap, Aig_Obj_t * pObj, int fCompl )
+{
+    int iSatVar = vMap ? Vec_IntEntry(vMap, Aig_ObjId(pObj)) : Aig_ObjId(pObj);
+    assert( iSatVar > 0 );
+    return iSatVar + iSatVar + fCompl;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects nodes inside the cone.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_ComputeClauses( Aig_Man_t * p, Aig_Obj_t * pRoot, 
+    Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Int_t * vMap, Vec_Int_t * vCover, Vec_Int_t * vClauses )
+{
+    Aig_Obj_t * pLeaf;
+    int c, k, Cube, OutLit, RetValue;
+    word Truth;
+    assert( pRoot->fMarkA );
+
+    Vec_IntClear( vClauses );
+
+    OutLit = Cnf_ObjGetLit( vMap, pRoot, 0 );
+    // detect cone
+    Cnf_CollectLeaves( pRoot, vLeaves, 0 );
+    Cnf_CollectVolume( p, pRoot, vLeaves, vNodes );
+    assert( pRoot == Vec_PtrEntryLast(vNodes) );
+    // check if this is an AND-gate
+    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pLeaf, k )
+    {
+        if ( Aig_ObjFaninC0(pLeaf) && !Aig_ObjFanin0(pLeaf)->fMarkA )
+            break;
+        if ( Aig_ObjFaninC1(pLeaf) && !Aig_ObjFanin1(pLeaf)->fMarkA )
+            break;
+    }
+    if ( k == Vec_PtrSize(vNodes) )
+    {
+        Cnf_CollectLeaves( pRoot, vLeaves, 1 );
+        // write big clause
+        Vec_IntPush( vClauses, 0 );
+        Vec_IntPush( vClauses, OutLit );
+        Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, k )
+            Vec_IntPush( vClauses, Cnf_ObjGetLit(vMap, Aig_Regular(pLeaf), !Aig_IsComplement(pLeaf)) );
+        // write small clauses
+        Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, k )
+        {
+            Vec_IntPush( vClauses, 0 );
+            Vec_IntPush( vClauses, OutLit ^ 1 );
+            Vec_IntPush( vClauses, Cnf_ObjGetLit(vMap, Aig_Regular(pLeaf), Aig_IsComplement(pLeaf)) );
+        }
+        return;
+    }
+    if ( Vec_PtrSize(vLeaves) > 6 )
+        printf( "FastCnfGeneration:  Internal error!!!\n" );
+    assert( Vec_PtrSize(vLeaves) <= 6 );
+
+    Truth = Cnf_CutDeriveTruth( p, vLeaves, vNodes );
+    if ( Truth == 0 || Truth == ~(word)0 )
+    {
+        Vec_IntPush( vClauses, 0 );
+        Vec_IntPush( vClauses, (Truth == 0) ? (OutLit ^ 1) : OutLit );
+        return;
+    }
+
+    RetValue = Kit_TruthIsop( (unsigned *)&Truth, Vec_PtrSize(vLeaves), vCover, 0 );
+    assert( RetValue >= 0 );
+
+    Vec_IntForEachEntry( vCover, Cube, c )
+    {
+        Vec_IntPush( vClauses, 0 );
+        Vec_IntPush( vClauses, OutLit );
+        for ( k = 0; k < Vec_PtrSize(vLeaves); k++, Cube >>= 2 )
+        {
+            if ( (Cube & 3) == 0 )
+                continue;
+            assert( (Cube & 3) != 3 );
+            Vec_IntPush( vClauses, Cnf_ObjGetLit(vMap, (Aig_Obj_t *)Vec_PtrEntry(vLeaves,k), (Cube&3)!=1) );
+        }
+    }
+
+    Truth = ~Truth;
+
+    RetValue = Kit_TruthIsop( (unsigned *)&Truth, Vec_PtrSize(vLeaves), vCover, 0 );
+    assert( RetValue >= 0 );
+    Vec_IntForEachEntry( vCover, Cube, c )
+    {
+        Vec_IntPush( vClauses, 0 );
+        Vec_IntPush( vClauses, OutLit ^ 1 );
+        for ( k = 0; k < Vec_PtrSize(vLeaves); k++, Cube >>= 2 )
+        {
+            if ( (Cube & 3) == 0 )
+                continue;
+            assert( (Cube & 3) != 3 );
+            Vec_IntPush( vClauses, Cnf_ObjGetLit(vMap, (Aig_Obj_t *)Vec_PtrEntry(vLeaves,k), (Cube&3)!=1) );
+        }
+    }
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Marks AIG for CNF computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_DeriveFastMark( Aig_Man_t * p )
+{
+    Vec_Int_t * vSupps;
+    Vec_Ptr_t * vLeaves, * vNodes;
+    Aig_Obj_t * pObj, * pTemp, * pObjC, * pObj0, * pObj1;
+    int i, k, nFans, Counter;
+
+    vLeaves = Vec_PtrAlloc( 100 );
+    vNodes  = Vec_PtrAlloc( 100 );
+    vSupps  = Vec_IntStart( Aig_ManObjNumMax(p) );
+
+    // mark CIs
+    Aig_ManForEachCi( p, pObj, i )
+        pObj->fMarkA = 1;
+
+    // mark CO drivers
+    Aig_ManForEachCo( p, pObj, i )
+        Aig_ObjFanin0(pObj)->fMarkA = 1;
+
+    // mark MUX/XOR nodes
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        assert( !pObj->fMarkB );
+        if ( !Aig_ObjIsMuxType(pObj) )
+            continue;
+        pObj0 = Aig_ObjFanin0(pObj);
+        if ( pObj0->fMarkB || Aig_ObjRefs(pObj0) > 1 )
+            continue;
+        pObj1 = Aig_ObjFanin1(pObj);
+        if ( pObj1->fMarkB || Aig_ObjRefs(pObj1) > 1 )
+            continue;
+        // mark nodes
+        pObj->fMarkB = 1;
+        pObj0->fMarkB = 1;
+        pObj1->fMarkB = 1;
+        // mark inputs and outputs
+        pObj->fMarkA = 1;
+        Aig_ObjFanin0(pObj0)->fMarkA = 1;
+        Aig_ObjFanin1(pObj0)->fMarkA = 1;
+        Aig_ObjFanin0(pObj1)->fMarkA = 1;
+        Aig_ObjFanin1(pObj1)->fMarkA = 1;
+    }
+
+    // mark nodes with multiple fanouts and pointed to by complemented edges
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        // mark nodes with many fanouts
+        if ( Aig_ObjRefs(pObj) > 1 )
+            pObj->fMarkA = 1;
+        // mark nodes pointed to by a complemented edge
+        if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFanin0(pObj)->fMarkB )
+            Aig_ObjFanin0(pObj)->fMarkA = 1;
+        if ( Aig_ObjFaninC1(pObj) && !Aig_ObjFanin1(pObj)->fMarkB )
+            Aig_ObjFanin1(pObj)->fMarkA = 1;
+    }
+
+    // compute supergate size for internal marked nodes
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        if ( !pObj->fMarkA )
+            continue;
+        if ( pObj->fMarkB )
+        {
+            if ( !Aig_ObjIsMuxType(pObj) )
+                continue;
+            pObjC = Aig_ObjRecognizeMux( pObj, &pObj1, &pObj0 );
+            pObj0 = Aig_Regular(pObj0);
+            pObj1 = Aig_Regular(pObj1);
+            assert( pObj0->fMarkA );
+            assert( pObj1->fMarkA );
+//            if ( pObj0 == pObj1 )
+//                continue;
+            nFans = 1 + (pObj0 == pObj1);
+            if ( !pObj0->fMarkB && !Aig_ObjIsCi(pObj0) && Aig_ObjRefs(pObj0) == nFans && Vec_IntEntry(vSupps, Aig_ObjId(pObj0)) < 3 )
+            {
+                pObj0->fMarkA = 0;
+                continue;
+            }
+            if ( !pObj1->fMarkB && !Aig_ObjIsCi(pObj1) && Aig_ObjRefs(pObj1) == nFans && Vec_IntEntry(vSupps, Aig_ObjId(pObj1)) < 3 )
+            {
+                pObj1->fMarkA = 0;
+                continue;
+            }
+            continue;
+        }
+
+        Cnf_CollectLeaves( pObj, vLeaves, 1 );
+        Vec_IntWriteEntry( vSupps, Aig_ObjId(pObj), Vec_PtrSize(vLeaves) );
+        if ( Vec_PtrSize(vLeaves) >= 6 )
+            continue;
+        Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pTemp, k )
+        {
+            pTemp = Aig_Regular(pTemp);
+            assert( pTemp->fMarkA );
+            if ( pTemp->fMarkB || Aig_ObjIsCi(pTemp) || Aig_ObjRefs(pTemp) > 1 )
+                continue;
+            assert( Vec_IntEntry(vSupps, Aig_ObjId(pTemp)) > 0 );
+            if ( Vec_PtrSize(vLeaves) - 1 + Vec_IntEntry(vSupps, Aig_ObjId(pTemp)) > 6 )
+                continue;
+            pTemp->fMarkA = 0;
+            Vec_IntWriteEntry( vSupps, Aig_ObjId(pObj), 6 );
+//printf( "%d %d   ", Vec_PtrSize(vLeaves), Vec_IntEntry(vSupps, Aig_ObjId(pTemp)) );
+            break;
+        }
+    }
+    Aig_ManCleanMarkB( p );
+
+    // check CO drivers
+    Counter = 0;
+    Aig_ManForEachCo( p, pObj, i )
+        Counter += !Aig_ObjFanin0(pObj)->fMarkA;
+    if ( Counter )
+    printf( "PO-driver rule is violated %d times.\n", Counter );
+
+    // check that the AND-gates are fine
+    Counter = 0;
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        assert( pObj->fMarkB == 0 );
+        if ( !pObj->fMarkA )
+            continue;
+        Cnf_CollectLeaves( pObj, vLeaves, 0 );
+        if ( Vec_PtrSize(vLeaves) <= 6 )
+            continue;
+        Cnf_CollectVolume( p, pObj, vLeaves, vNodes );
+        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pTemp, k )
+        {
+            if ( Aig_ObjFaninC0(pTemp) && !Aig_ObjFanin0(pTemp)->fMarkA )
+                Counter++;
+            if ( Aig_ObjFaninC1(pTemp) && !Aig_ObjFanin1(pTemp)->fMarkA )
+                Counter++;
+        }
+    }
+    if ( Counter )
+    printf( "AND-gate rule is violated %d times.\n", Counter );
+
+    Vec_PtrFree( vLeaves );
+    Vec_PtrFree( vNodes );
+    Vec_IntFree( vSupps );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the number of clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cnf_CutCountClauses( Aig_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Int_t * vCover )
+{
+    word Truth;
+    Aig_Obj_t * pObj;
+    int i, RetValue, nSize = 0;
+    if ( Vec_PtrSize(vLeaves) > 6 )
+    {
+        // make sure this is an AND gate
+        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+        {
+            if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFanin0(pObj)->fMarkA )
+                printf( "Unusual 1!\n" );
+            if ( Aig_ObjFaninC1(pObj) && !Aig_ObjFanin1(pObj)->fMarkA )
+                printf( "Unusual 2!\n" );
+            continue;
+
+            assert( !Aig_ObjFaninC0(pObj) || Aig_ObjFanin0(pObj)->fMarkA );
+            assert( !Aig_ObjFaninC1(pObj) || Aig_ObjFanin1(pObj)->fMarkA );
+        }
+        return Vec_PtrSize(vLeaves) + 1;
+    }
+    Truth = Cnf_CutDeriveTruth( p, vLeaves, vNodes );
+
+    RetValue = Kit_TruthIsop( (unsigned *)&Truth, Vec_PtrSize(vLeaves), vCover, 0 );
+    assert( RetValue >= 0 );
+    nSize += Vec_IntSize(vCover);
+
+    Truth = ~Truth;
+
+    RetValue = Kit_TruthIsop( (unsigned *)&Truth, Vec_PtrSize(vLeaves), vCover, 0 );
+    assert( RetValue >= 0 );
+    nSize += Vec_IntSize(vCover);
+    return nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Counts the size of the CNF, assuming marks are set.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cnf_CountCnfSize( Aig_Man_t * p )
+{
+    Vec_Ptr_t * vLeaves, * vNodes;
+    Vec_Int_t * vCover;
+    Aig_Obj_t * pObj;
+    int nVars = 0, nClauses = 0;
+    int i, nSize;
+
+    vLeaves = Vec_PtrAlloc( 100 );
+    vNodes  = Vec_PtrAlloc( 100 );
+    vCover  = Vec_IntAlloc( 1 << 16 );
+
+    Aig_ManForEachObj( p, pObj, i )
+        nVars += pObj->fMarkA;
+
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        if ( !pObj->fMarkA )
+            continue;
+        Cnf_CollectLeaves( pObj, vLeaves, 0 );
+        Cnf_CollectVolume( p, pObj, vLeaves, vNodes );
+        assert( pObj == Vec_PtrEntryLast(vNodes) );
+
+        nSize = Cnf_CutCountClauses( p, vLeaves, vNodes, vCover );
+//        printf( "%d(%d) ", Vec_PtrSize(vLeaves), nSize );
+
+        nClauses += nSize;
+    }
+//    printf( "\n" );
+    printf( "Vars = %d  Clauses = %d\n", nVars, nClauses );
+
+    Vec_PtrFree( vLeaves );
+    Vec_PtrFree( vNodes );
+    Vec_IntFree( vCover );
+    return nClauses;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CNF from the marked AIG.]
+
+  Description [Assumes that marking is such that when we traverse from each
+  marked node, the logic cone has 6 inputs or less, or it is a multi-input AND.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Dat_t * Cnf_DeriveFastClauses( Aig_Man_t * p, int nOutputs )
+{
+    Cnf_Dat_t * pCnf;
+    Vec_Int_t * vLits, * vClas, * vMap, * vTemp;
+    Vec_Ptr_t * vLeaves, * vNodes;
+    Vec_Int_t * vCover;
+    Aig_Obj_t * pObj;
+    int i, k, nVars, Entry, OutLit, DriLit;
+
+    vLits = Vec_IntAlloc( 1 << 16 );
+    vClas = Vec_IntAlloc( 1 << 12 );
+    vMap  = Vec_IntStartFull( Aig_ManObjNumMax(p) );
+
+    // assign variables for the outputs
+    nVars = 1;
+    if ( nOutputs )
+    {
+        if ( Aig_ManRegNum(p) == 0 )
+        {
+            assert( nOutputs == Aig_ManCoNum(p) );
+            Aig_ManForEachCo( p, pObj, i )
+                Vec_IntWriteEntry( vMap, Aig_ObjId(pObj), nVars++ );
+        }
+        else
+        {
+            assert( nOutputs == Aig_ManRegNum(p) );
+            Aig_ManForEachLiSeq( p, pObj, i )
+                Vec_IntWriteEntry( vMap, Aig_ObjId(pObj), nVars++ );
+        }
+    }
+    // assign variables to the internal nodes
+    Aig_ManForEachNodeReverse( p, pObj, i )
+        if ( pObj->fMarkA )
+            Vec_IntWriteEntry( vMap, Aig_ObjId(pObj), nVars++ );
+    // assign variables to the PIs and constant node
+    Aig_ManForEachCi( p, pObj, i )
+        Vec_IntWriteEntry( vMap, Aig_ObjId(pObj), nVars++ );
+    Vec_IntWriteEntry( vMap, Aig_ObjId(Aig_ManConst1(p)), nVars++ );
+
+    // create clauses
+    vLeaves = Vec_PtrAlloc( 100 );
+    vNodes  = Vec_PtrAlloc( 100 );
+    vCover  = Vec_IntAlloc( 1 << 16 );
+    vTemp   = Vec_IntAlloc( 100 );
+    Aig_ManForEachNodeReverse( p, pObj, i )
+    {
+        if ( !pObj->fMarkA )
+            continue;
+        Cnf_ComputeClauses( p, pObj, vLeaves, vNodes, vMap, vCover, vTemp );
+        Vec_IntForEachEntry( vTemp, Entry, k )
+        {
+            if ( Entry == 0 )
+                Vec_IntPush( vClas, Vec_IntSize(vLits) );
+            else
+                Vec_IntPush( vLits, Entry );
+        }       
+    }
+    Vec_PtrFree( vLeaves );
+    Vec_PtrFree( vNodes );
+    Vec_IntFree( vCover );
+    Vec_IntFree( vTemp );
+
+    // create clauses for the outputs
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        DriLit = Cnf_ObjGetLit( vMap, Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj) );
+        if ( i < Aig_ManCoNum(p) - nOutputs )
+        {
+            Vec_IntPush( vClas, Vec_IntSize(vLits) );
+            Vec_IntPush( vLits, DriLit );
+        }
+        else
+        {
+            OutLit = Cnf_ObjGetLit( vMap, pObj, 0 );
+            // first clause
+            Vec_IntPush( vClas, Vec_IntSize(vLits) );
+            Vec_IntPush( vLits, OutLit );
+            Vec_IntPush( vLits, DriLit ^ 1 );
+            // second clause
+            Vec_IntPush( vClas, Vec_IntSize(vLits) );
+            Vec_IntPush( vLits, OutLit ^ 1 );
+            Vec_IntPush( vLits, DriLit );
+        }
+    }
+ 
+    // write the constant literal
+    OutLit = Cnf_ObjGetLit( vMap, Aig_ManConst1(p), 0 );
+    Vec_IntPush( vClas, Vec_IntSize(vLits) );
+    Vec_IntPush( vLits, OutLit );
+
+    // create structure
+    pCnf = ABC_CALLOC( Cnf_Dat_t, 1 );
+    pCnf->pMan = p;
+    pCnf->nVars = nVars;
+    pCnf->nLiterals = Vec_IntSize( vLits );
+    pCnf->nClauses  = Vec_IntSize( vClas );
+    pCnf->pClauses  = ABC_ALLOC( int *, pCnf->nClauses + 1 );
+    pCnf->pClauses[0] = Vec_IntReleaseArray( vLits );
+    Vec_IntForEachEntry( vClas, Entry, i )
+        pCnf->pClauses[i] = pCnf->pClauses[0] + Entry;
+    pCnf->pClauses[pCnf->nClauses] = pCnf->pClauses[0] + pCnf->nLiterals;
+    pCnf->pVarNums  = Vec_IntReleaseArray( vMap );
+
+    // cleanup
+    Vec_IntFree( vLits );
+    Vec_IntFree( vClas );
+    Vec_IntFree( vMap );
+    return pCnf;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fast CNF computation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Dat_t * Cnf_DeriveFast( Aig_Man_t * p, int nOutputs )
+{
+    Cnf_Dat_t * pCnf = NULL;
+    abctime clk;//, clkTotal = Abc_Clock();
+//    printf( "\n" );
+    Aig_ManCleanMarkAB( p );
+    // create initial marking
+    clk = Abc_Clock();
+    Cnf_DeriveFastMark( p );
+//    Abc_PrintTime( 1, "Marking", Abc_Clock() - clk );
+    // compute CNF size
+    clk = Abc_Clock();
+    pCnf = Cnf_DeriveFastClauses( p, nOutputs );
+//    Abc_PrintTime( 1, "Clauses", Abc_Clock() - clk );
+    // derive the resulting CNF
+    Aig_ManCleanMarkA( p );
+//    Abc_PrintTime( 1, "TOTAL  ", Abc_Clock() - clkTotal );
+
+//    printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d.   \n", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals );
+
+//    Cnf_DataFree( pCnf );
+//    pCnf = NULL;
+    return pCnf;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/cnf/cnfMan.c b/abc-build/src/sat/cnf/cnfMan.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/cnf/cnfMan.c
@@ -0,0 +1,726 @@
+/**CFile****************************************************************
+
+  FileName    [cnfMan.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG-to-CNF conversion.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: cnfMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cnf.h"
+#include "sat/bsat/satSolver.h"
+#include "sat/bsat/satSolver2.h"
+#include "misc/zlib/zlib.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Cnf_Lit2Var( int Lit )        { return (Lit & 1)? -(Lit >> 1)-1 : (Lit >> 1)+1;  }
+static inline int Cnf_Lit2Var2( int Lit )       { return (Lit & 1)? -(Lit >> 1)   : (Lit >> 1);    }
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the fraiging manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Man_t * Cnf_ManStart()
+{
+    Cnf_Man_t * p;
+    int i;
+    // allocate the manager
+    p = ABC_ALLOC( Cnf_Man_t, 1 );
+    memset( p, 0, sizeof(Cnf_Man_t) );
+    // derive internal data structures
+    Cnf_ReadMsops( &p->pSopSizes, &p->pSops );
+    // allocate memory manager for cuts
+    p->pMemCuts = Aig_MmFlexStart();
+    p->nMergeLimit = 10;
+    // allocate temporary truth tables
+    p->pTruths[0] = ABC_ALLOC( unsigned, 4 * Abc_TruthWordNum(p->nMergeLimit) );
+    for ( i = 1; i < 4; i++ )
+        p->pTruths[i] = p->pTruths[i-1] + Abc_TruthWordNum(p->nMergeLimit);
+    p->vMemory = Vec_IntAlloc( 1 << 18 );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the fraiging manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_ManStop( Cnf_Man_t * p )
+{
+    Vec_IntFree( p->vMemory );
+    ABC_FREE( p->pTruths[0] );
+    Aig_MmFlexStop( p->pMemCuts, 0 );
+    ABC_FREE( p->pSopSizes );
+    ABC_FREE( p->pSops[1] );
+    ABC_FREE( p->pSops );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of CI IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Cnf_DataCollectPiSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p )
+{
+    Vec_Int_t * vCiIds;
+    Aig_Obj_t * pObj;
+    int i;
+    vCiIds = Vec_IntAlloc( Aig_ManCiNum(p) );
+    Aig_ManForEachCi( p, pObj, i )
+        Vec_IntPush( vCiIds, pCnf->pVarNums[pObj->Id] );
+    return vCiIds;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the new CNF.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Dat_t * Cnf_DataAlloc( Aig_Man_t * pAig, int nVars, int nClauses, int nLiterals )
+{
+    Cnf_Dat_t * pCnf;
+    int i;
+    pCnf = ABC_ALLOC( Cnf_Dat_t, 1 );
+    memset( pCnf, 0, sizeof(Cnf_Dat_t) );
+    pCnf->pMan = pAig;
+    pCnf->nVars = nVars;
+    pCnf->nClauses = nClauses;
+    pCnf->nLiterals = nLiterals;
+    pCnf->pClauses = ABC_ALLOC( int *, nClauses + 1 );
+    pCnf->pClauses[0] = ABC_ALLOC( int, nLiterals );
+    pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals;
+    pCnf->pVarNums = ABC_ALLOC( int, Aig_ManObjNumMax(pAig) );
+//    memset( pCnf->pVarNums, 0xff, sizeof(int) * Aig_ManObjNumMax(pAig) );
+    for ( i = 0; i < Aig_ManObjNumMax(pAig); i++ )
+        pCnf->pVarNums[i] = -1;
+    return pCnf;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the new CNF.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Dat_t * Cnf_DataDup( Cnf_Dat_t * p )
+{
+    Cnf_Dat_t * pCnf;
+    int i;
+    pCnf = Cnf_DataAlloc( p->pMan, p->nVars, p->nClauses, p->nLiterals );
+    memcpy( pCnf->pClauses[0], p->pClauses[0], sizeof(int) * p->nLiterals );
+    memcpy( pCnf->pVarNums, p->pVarNums, sizeof(int) * Aig_ManObjNumMax(p->pMan) );
+    for ( i = 1; i < p->nClauses; i++ )
+        pCnf->pClauses[i] = pCnf->pClauses[0] + (p->pClauses[i] - p->pClauses[0]);
+    return pCnf;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_DataFree( Cnf_Dat_t * p )
+{
+    if ( p == NULL )
+        return;
+    Vec_IntFreeP( &p->vMapping );
+    ABC_FREE( p->pClaPols );
+    ABC_FREE( p->pObj2Clause );
+    ABC_FREE( p->pObj2Count );
+    ABC_FREE( p->pClauses[0] );
+    ABC_FREE( p->pClauses );
+    ABC_FREE( p->pVarNums );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes CNF into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_DataLift( Cnf_Dat_t * p, int nVarsPlus )
+{
+    Aig_Obj_t * pObj;
+    int v;
+    if ( p->pMan )
+    {
+        Aig_ManForEachObj( p->pMan, pObj, v )
+            if ( p->pVarNums[pObj->Id] >= 0 )
+                p->pVarNums[pObj->Id] += nVarsPlus;
+    }
+    for ( v = 0; v < p->nLiterals; v++ )
+        p->pClauses[0][v] += 2*nVarsPlus;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes CNF into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_DataFlipLastLiteral( Cnf_Dat_t * p )
+{
+    p->pClauses[0][p->nLiterals-1] = lit_neg( p->pClauses[0][p->nLiterals-1] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes CNF into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_DataPrint( Cnf_Dat_t * p, int fReadable )
+{
+    FILE * pFile = stdout;
+    int * pLit, * pStop, i;
+    fprintf( pFile, "p cnf %d %d\n", p->nVars, p->nClauses );
+    for ( i = 0; i < p->nClauses; i++ )
+    {
+        for ( pLit = p->pClauses[i], pStop = p->pClauses[i+1]; pLit < pStop; pLit++ )
+            fprintf( pFile, "%d ", fReadable? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit) );
+        fprintf( pFile, "\n" );
+    }
+    fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes CNF into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_DataWriteIntoFileGz( Cnf_Dat_t * p, char * pFileName, int fReadable, Vec_Int_t * vForAlls, Vec_Int_t * vExists )
+{
+    gzFile pFile;
+    int * pLit, * pStop, i, VarId;
+    pFile = gzopen( pFileName, "wb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cnf_WriteIntoFile(): Output file cannot be opened.\n" );
+        return;
+    }
+    gzprintf( pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n" );
+    gzprintf( pFile, "p cnf %d %d\n", p->nVars, p->nClauses );
+    if ( vForAlls )
+    {
+        gzprintf( pFile, "a " );
+        Vec_IntForEachEntry( vForAlls, VarId, i )
+            gzprintf( pFile, "%d ", fReadable? VarId : VarId+1 );
+        gzprintf( pFile, "0\n" );
+    }
+    if ( vExists )
+    {
+        gzprintf( pFile, "e " );
+        Vec_IntForEachEntry( vExists, VarId, i )
+            gzprintf( pFile, "%d ", fReadable? VarId : VarId+1 );
+        gzprintf( pFile, "0\n" );
+    }
+    for ( i = 0; i < p->nClauses; i++ )
+    {
+        for ( pLit = p->pClauses[i], pStop = p->pClauses[i+1]; pLit < pStop; pLit++ )
+            gzprintf( pFile, "%d ", fReadable? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit) );
+        gzprintf( pFile, "0\n" );
+    }
+    gzprintf( pFile, "\n" );
+    gzclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes CNF into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_DataWriteIntoFile( Cnf_Dat_t * p, char * pFileName, int fReadable, Vec_Int_t * vForAlls, Vec_Int_t * vExists )
+{
+    FILE * pFile;
+    int * pLit, * pStop, i, VarId;
+    if ( !strncmp(pFileName+strlen(pFileName)-3,".gz",3) ) 
+    {
+        Cnf_DataWriteIntoFileGz( p, pFileName, fReadable, vForAlls, vExists );
+        return;
+    }
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        printf( "Cnf_WriteIntoFile(): Output file cannot be opened.\n" );
+        return;
+    }
+    fprintf( pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n" );
+    fprintf( pFile, "p cnf %d %d\n", p->nVars, p->nClauses );
+    if ( vForAlls )
+    {
+        fprintf( pFile, "a " );
+        Vec_IntForEachEntry( vForAlls, VarId, i )
+            fprintf( pFile, "%d ", fReadable? VarId : VarId+1 );
+        fprintf( pFile, "0\n" );
+    }
+    if ( vExists )
+    {
+        fprintf( pFile, "e " );
+        Vec_IntForEachEntry( vExists, VarId, i )
+            fprintf( pFile, "%d ", fReadable? VarId : VarId+1 );
+        fprintf( pFile, "0\n" );
+    }
+    for ( i = 0; i < p->nClauses; i++ )
+    {
+        for ( pLit = p->pClauses[i], pStop = p->pClauses[i+1]; pLit < pStop; pLit++ )
+            fprintf( pFile, "%d ", fReadable? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit) );
+        fprintf( pFile, "0\n" );
+    }
+    fprintf( pFile, "\n" );
+    fclose( pFile );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes CNF into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Cnf_DataWriteIntoSolverInt( void * pSolver, Cnf_Dat_t * p, int nFrames, int fInit )
+{
+	sat_solver * pSat = (sat_solver *)pSolver;
+    int i, f, status;
+    assert( nFrames > 0 );
+    assert( pSat );
+//    pSat = sat_solver_new();
+    sat_solver_setnvars( pSat, p->nVars * nFrames );
+    for ( i = 0; i < p->nClauses; i++ )
+    {
+        if ( !sat_solver_addclause( pSat, p->pClauses[i], p->pClauses[i+1] ) )
+        {
+            sat_solver_delete( pSat );
+            return NULL;
+        }
+    }
+    if ( nFrames > 1 )
+    {
+        Aig_Obj_t * pObjLo, * pObjLi;
+        int nLitsAll, * pLits, Lits[2];
+        nLitsAll = 2 * p->nVars;
+        pLits = p->pClauses[0];
+        for ( f = 1; f < nFrames; f++ )
+        {
+            // add equality of register inputs/outputs for different timeframes
+            Aig_ManForEachLiLoSeq( p->pMan, pObjLi, pObjLo, i )
+            {
+                Lits[0] = (f-1)*nLitsAll + toLitCond( p->pVarNums[pObjLi->Id], 0 );
+                Lits[1] =  f   *nLitsAll + toLitCond( p->pVarNums[pObjLo->Id], 1 );
+                if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+                {
+                    sat_solver_delete( pSat );
+                    return NULL;
+                }
+                Lits[0]++;
+                Lits[1]--;
+                if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+                {
+                    sat_solver_delete( pSat );
+                    return NULL;
+                }
+            }
+            // add clauses for the next timeframe
+            for ( i = 0; i < p->nLiterals; i++ )
+                pLits[i] += nLitsAll;
+            for ( i = 0; i < p->nClauses; i++ )
+            {
+                if ( !sat_solver_addclause( pSat, p->pClauses[i], p->pClauses[i+1] ) )
+                {
+                    sat_solver_delete( pSat );
+                    return NULL;
+                }
+            }
+        }
+        // return literals to their original state
+        nLitsAll = (f-1) * nLitsAll;
+        for ( i = 0; i < p->nLiterals; i++ )
+            pLits[i] -= nLitsAll;
+    }
+    if ( fInit )
+    {
+        Aig_Obj_t * pObjLo;
+        int Lits[1];
+        Aig_ManForEachLoSeq( p->pMan, pObjLo, i )
+        {
+            Lits[0] = toLitCond( p->pVarNums[pObjLo->Id], 1 );
+            if ( !sat_solver_addclause( pSat, Lits, Lits + 1 ) )
+            {
+                sat_solver_delete( pSat );
+                return NULL;
+            }
+        }
+    }
+    status = sat_solver_simplify(pSat);
+    if ( status == 0 )
+    {
+        sat_solver_delete( pSat );
+        return NULL;
+    }
+    return pSat;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes CNF into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p, int nFrames, int fInit )
+{
+    return Cnf_DataWriteIntoSolverInt( sat_solver_new(), p, nFrames, fInit );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes CNF into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Cnf_DataWriteIntoSolver2( Cnf_Dat_t * p, int nFrames, int fInit )
+{
+    sat_solver2 * pSat;
+    int i, f, status;
+    assert( nFrames > 0 );
+    pSat = sat_solver2_new();
+    sat_solver2_setnvars( pSat, p->nVars * nFrames );
+    for ( i = 0; i < p->nClauses; i++ )
+    {
+        if ( !sat_solver2_addclause( pSat, p->pClauses[i], p->pClauses[i+1], 0 ) )
+        {
+            sat_solver2_delete( pSat );
+            return NULL;
+        }
+    }
+    if ( nFrames > 1 )
+    {
+        Aig_Obj_t * pObjLo, * pObjLi;
+        int nLitsAll, * pLits, Lits[2];
+        nLitsAll = 2 * p->nVars;
+        pLits = p->pClauses[0];
+        for ( f = 1; f < nFrames; f++ )
+        {
+            // add equality of register inputs/outputs for different timeframes
+            Aig_ManForEachLiLoSeq( p->pMan, pObjLi, pObjLo, i )
+            {
+                Lits[0] = (f-1)*nLitsAll + toLitCond( p->pVarNums[pObjLi->Id], 0 );
+                Lits[1] =  f   *nLitsAll + toLitCond( p->pVarNums[pObjLo->Id], 1 );
+                if ( !sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ) )
+                {
+                    sat_solver2_delete( pSat );
+                    return NULL;
+                }
+                Lits[0]++;
+                Lits[1]--;
+                if ( !sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ) )
+                {
+                    sat_solver2_delete( pSat );
+                    return NULL;
+                }
+            }
+            // add clauses for the next timeframe
+            for ( i = 0; i < p->nLiterals; i++ )
+                pLits[i] += nLitsAll;
+            for ( i = 0; i < p->nClauses; i++ )
+            {
+                if ( !sat_solver2_addclause( pSat, p->pClauses[i], p->pClauses[i+1], 0 ) )
+                {
+                    sat_solver2_delete( pSat );
+                    return NULL;
+                }
+            }
+        }
+        // return literals to their original state
+        nLitsAll = (f-1) * nLitsAll;
+        for ( i = 0; i < p->nLiterals; i++ )
+            pLits[i] -= nLitsAll;
+    }
+    if ( fInit )
+    {
+        Aig_Obj_t * pObjLo;
+        int Lits[1];
+        Aig_ManForEachLoSeq( p->pMan, pObjLo, i )
+        {
+            Lits[0] = toLitCond( p->pVarNums[pObjLo->Id], 1 );
+            if ( !sat_solver2_addclause( pSat, Lits, Lits + 1, 0 ) )
+            {
+                sat_solver2_delete( pSat );
+                return NULL;
+            }
+        }
+    }
+    status = sat_solver2_simplify(pSat);
+    if ( status == 0 )
+    {
+        sat_solver2_delete( pSat );
+        return NULL;
+    }
+    return pSat;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the OR-clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cnf_DataWriteOrClause( void * p, Cnf_Dat_t * pCnf )
+{
+    sat_solver * pSat = (sat_solver *)p;
+    Aig_Obj_t * pObj;
+    int i, * pLits;
+    pLits = ABC_ALLOC( int, Aig_ManCoNum(pCnf->pMan) );
+    Aig_ManForEachCo( pCnf->pMan, pObj, i )
+        pLits[i] = toLitCond( pCnf->pVarNums[pObj->Id], 0 );
+    if ( !sat_solver_addclause( pSat, pLits, pLits + Aig_ManCoNum(pCnf->pMan) ) )
+    {
+        ABC_FREE( pLits );
+        return 0;
+    }
+    ABC_FREE( pLits );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the OR-clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cnf_DataWriteOrClause2( void * p, Cnf_Dat_t * pCnf )
+{
+    sat_solver2 * pSat = (sat_solver2 *)p;
+    Aig_Obj_t * pObj;
+    int i, * pLits;
+    pLits = ABC_ALLOC( int, Aig_ManCoNum(pCnf->pMan) );
+    Aig_ManForEachCo( pCnf->pMan, pObj, i )
+        pLits[i] = toLitCond( pCnf->pVarNums[pObj->Id], 0 );
+    if ( !sat_solver2_addclause( pSat, pLits, pLits + Aig_ManCoNum(pCnf->pMan), 0 ) )
+    {
+        ABC_FREE( pLits );
+        return 0;
+    }
+    ABC_FREE( pLits );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds the OR-clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cnf_DataWriteAndClauses( void * p, Cnf_Dat_t * pCnf )
+{
+    sat_solver * pSat = (sat_solver *)p;
+    Aig_Obj_t * pObj;
+    int i, Lit;
+    Aig_ManForEachCo( pCnf->pMan, pObj, i )
+    {
+        Lit = toLitCond( pCnf->pVarNums[pObj->Id], 0 );
+        if ( !sat_solver_addclause( pSat, &Lit, &Lit+1 ) )
+            return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transforms polarity of the internal veriables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_DataTranformPolarity( Cnf_Dat_t * pCnf, int fTransformPos )
+{
+    Aig_Obj_t * pObj;
+    int * pVarToPol;
+    int i, iVar;
+    // create map from the variable number to its polarity
+    pVarToPol = ABC_CALLOC( int, pCnf->nVars );
+    Aig_ManForEachObj( pCnf->pMan, pObj, i )
+    {
+        if ( !fTransformPos && Aig_ObjIsCo(pObj) )
+            continue;
+        if ( pCnf->pVarNums[pObj->Id] >= 0 )
+            pVarToPol[ pCnf->pVarNums[pObj->Id] ] = pObj->fPhase;
+    }
+    // transform literals
+    for ( i = 0; i < pCnf->nLiterals; i++ )
+    {
+        iVar = lit_var(pCnf->pClauses[0][i]);
+        assert( iVar < pCnf->nVars );
+        if ( pVarToPol[iVar] )
+            pCnf->pClauses[0][i] = lit_neg( pCnf->pClauses[0][i] );
+    }
+    ABC_FREE( pVarToPol );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds constraints for the two-input AND-gate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cnf_DataAddXorClause( void * pSat, int iVarA, int iVarB, int iVarC )
+{
+    lit Lits[3];
+    assert( iVarA > 0 && iVarB > 0 && iVarC > 0 );
+
+    Lits[0] = toLitCond( iVarA, 1 );
+    Lits[1] = toLitCond( iVarB, 1 );
+    Lits[2] = toLitCond( iVarC, 1 );
+    if ( !sat_solver_addclause( (sat_solver *)pSat, Lits, Lits + 3 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVarA, 1 );
+    Lits[1] = toLitCond( iVarB, 0 );
+    Lits[2] = toLitCond( iVarC, 0 );
+    if ( !sat_solver_addclause( (sat_solver *)pSat, Lits, Lits + 3 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVarA, 0 );
+    Lits[1] = toLitCond( iVarB, 1 );
+    Lits[2] = toLitCond( iVarC, 0 );
+    if ( !sat_solver_addclause( (sat_solver *)pSat, Lits, Lits + 3 ) )
+        return 0;
+
+    Lits[0] = toLitCond( iVarA, 0 );
+    Lits[1] = toLitCond( iVarB, 0 );
+    Lits[2] = toLitCond( iVarC, 1 );
+    if ( !sat_solver_addclause( (sat_solver *)pSat, Lits, Lits + 3 ) )
+        return 0;
+
+    return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/cnf/cnfMap.c b/abc-build/src/sat/cnf/cnfMap.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/cnf/cnfMap.c
@@ -0,0 +1,362 @@
+/**CFile****************************************************************
+
+  FileName    [cnfMap.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG-to-CNF conversion.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: cnfMap.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cnf.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area flow of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_CutAssignAreaFlow( Cnf_Man_t * p, Dar_Cut_t * pCut, int * pAreaFlows )
+{
+    Aig_Obj_t * pLeaf;
+    int i;
+    pCut->Value = 0;
+//    pCut->uSign = 100 * Cnf_CutSopCost( p, pCut );
+    pCut->uSign = 10 * Cnf_CutSopCost( p, pCut );
+    Dar_CutForEachLeaf( p->pManAig, pCut, pLeaf, i )
+    {
+        pCut->Value += pLeaf->nRefs;
+        if ( !Aig_ObjIsNode(pLeaf) )
+            continue;
+        assert( pLeaf->nRefs > 0 );
+        pCut->uSign += pAreaFlows[pLeaf->Id] / (pLeaf->nRefs? pLeaf->nRefs : 1);
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area flow of the supergate.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cnf_CutSuperAreaFlow( Vec_Ptr_t * vSuper, int * pAreaFlows )
+{
+    Aig_Obj_t * pLeaf;
+    int i, nAreaFlow;
+    nAreaFlow = 100 * (Vec_PtrSize(vSuper) + 1);
+    Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pLeaf, i )
+    {
+        pLeaf = Aig_Regular(pLeaf);
+        if ( !Aig_ObjIsNode(pLeaf) )
+            continue;
+        assert( pLeaf->nRefs > 0 );
+        nAreaFlow += pAreaFlows[pLeaf->Id] / (pLeaf->nRefs? pLeaf->nRefs : 1);
+    }
+    return nAreaFlow;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_DeriveMapping( Cnf_Man_t * p )
+{
+    Vec_Ptr_t * vSuper;
+    Aig_Obj_t * pObj;
+    Dar_Cut_t * pCut, * pCutBest;
+    int i, k, AreaFlow, * pAreaFlows;
+    // allocate area flows
+    pAreaFlows = ABC_ALLOC( int, Aig_ManObjNumMax(p->pManAig) );
+    memset( pAreaFlows, 0, sizeof(int) * Aig_ManObjNumMax(p->pManAig) );
+    // visit the nodes in the topological order and update their best cuts
+    vSuper = Vec_PtrAlloc( 100 );
+    Aig_ManForEachNode( p->pManAig, pObj, i )
+    {
+        // go through the cuts
+        pCutBest = NULL;
+        Dar_ObjForEachCut( pObj, pCut, k )
+        {
+            pCut->fBest = 0;
+            if ( k == 0 )
+                continue;
+            Cnf_CutAssignAreaFlow( p, pCut, pAreaFlows );
+            if ( pCutBest == NULL || pCutBest->uSign > pCut->uSign || 
+                (pCutBest->uSign == pCut->uSign && pCutBest->Value < pCut->Value) )
+                 pCutBest = pCut;
+        }
+        // check the big cut
+//        Aig_ObjCollectSuper( pObj, vSuper );
+        // get the area flow of this cut
+//        AreaFlow = Cnf_CutSuperAreaFlow( vSuper, pAreaFlows );
+        AreaFlow = ABC_INFINITY;
+        if ( AreaFlow >= (int)pCutBest->uSign )
+        {
+            pAreaFlows[pObj->Id] = pCutBest->uSign;
+            pCutBest->fBest = 1;
+        }
+        else
+        {
+            pAreaFlows[pObj->Id] = AreaFlow;
+            pObj->fMarkB = 1; // mark the special node
+        }
+    }
+    Vec_PtrFree( vSuper );
+    ABC_FREE( pAreaFlows );
+
+/*
+    // compute the area of mapping
+    AreaFlow = 0;
+    Aig_ManForEachCo( p->pManAig, pObj, i )
+        AreaFlow += Dar_ObjBestCut(Aig_ObjFanin0(pObj))->uSign / 100 / Aig_ObjFanin0(pObj)->nRefs;
+    printf( "Area of the network = %d.\n", AreaFlow );
+*/
+}
+
+
+
+#if 0
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area of the first level.]
+
+  Description [The cut need to be derefed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+ 
+***********************************************************************/
+void Aig_CutDeref( Aig_Man_t * p, Dar_Cut_t * pCut )
+{ 
+    Aig_Obj_t * pLeaf;
+    int i;
+    Dar_CutForEachLeaf( p, pCut, pLeaf, i )
+    {
+        assert( pLeaf->nRefs > 0 );
+        if ( --pLeaf->nRefs > 0 || !Aig_ObjIsAnd(pLeaf) )
+            continue;
+        Aig_CutDeref( p, Aig_ObjBestCut(pLeaf) );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area of the first level.]
+
+  Description [The cut need to be derefed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_CutRef( Aig_Man_t * p, Dar_Cut_t * pCut )
+{
+    Aig_Obj_t * pLeaf;
+    int i, Area = pCut->Value;
+    Dar_CutForEachLeaf( p, pCut, pLeaf, i )
+    {
+        assert( pLeaf->nRefs >= 0 );
+        if ( pLeaf->nRefs++ > 0 || !Aig_ObjIsAnd(pLeaf) )
+            continue;
+        Area += Aig_CutRef( p, Aig_ObjBestCut(pLeaf) );
+    }
+    return Area;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes exact area of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cnf_CutArea( Aig_Man_t * p, Dar_Cut_t * pCut )
+{
+    int Area;
+    Area = Aig_CutRef( p, pCut );
+    Aig_CutDeref( p, pCut );
+    return Area;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 1 if the second cut is better.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Cnf_CutCompare( Dar_Cut_t * pC0, Dar_Cut_t * pC1 )
+{
+    if ( pC0->Area < pC1->Area - 0.0001 )
+        return -1;
+    if ( pC0->Area > pC1->Area + 0.0001 ) // smaller area flow is better
+        return 1;
+//    if ( pC0->NoRefs < pC1->NoRefs )
+//        return -1;
+//    if ( pC0->NoRefs > pC1->NoRefs ) // fewer non-referenced fanins is better
+//        return 1;
+//    if ( pC0->FanRefs / pC0->nLeaves > pC1->FanRefs / pC1->nLeaves )
+//        return -1;
+//    if ( pC0->FanRefs / pC0->nLeaves < pC1->FanRefs / pC1->nLeaves )
+//        return 1; // larger average fanin ref-counter is better
+//    return 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the cut with the smallest area flow.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Dar_Cut_t * Cnf_ObjFindBestCut( Aig_Obj_t * pObj )
+{
+    Dar_Cut_t * pCut, * pCutBest;
+    int i;
+    pCutBest = NULL;
+    Dar_ObjForEachCut( pObj, pCut, i )
+        if ( pCutBest == NULL || Cnf_CutCompare(pCutBest, pCut) == 1 )
+            pCutBest = pCut;
+    return pCutBest;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area flow of the cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_CutAssignArea( Cnf_Man_t * p, Dar_Cut_t * pCut )
+{
+    Aig_Obj_t * pLeaf;
+    int i;
+    pCut->Area    = (float)pCut->Cost;
+    pCut->NoRefs  = 0;
+    pCut->FanRefs = 0;
+    Dar_CutForEachLeaf( p->pManAig, pCut, pLeaf, i )
+    {
+        if ( !Aig_ObjIsNode(pLeaf) )
+            continue;
+        if ( pLeaf->nRefs == 0 )
+        {
+            pCut->Area += Aig_ObjBestCut(pLeaf)->Cost;
+            pCut->NoRefs++;
+        }
+        else
+        {
+            if ( pCut->FanRefs + pLeaf->nRefs > 15 )
+                pCut->FanRefs = 15;
+            else
+                pCut->FanRefs += pLeaf->nRefs;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs one round of "area recovery" using exact local area.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cnf_ManMapForCnf( Cnf_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    Dar_Cut_t * pCut, * pCutBest;
+    int i, k;
+    // visit the nodes in the topological order and update their best cuts
+    Aig_ManForEachNode( p->pManAig, pObj, i )
+    {
+        // find the old best cut
+        pCutBest = Aig_ObjBestCut(pObj);
+        Dar_ObjClearBestCut(pCutBest);
+        // if the node is used, dereference its cut
+        if ( pObj->nRefs )
+            Aig_CutDeref( p->pManAig, pCutBest );
+
+        // evaluate the cuts of this node
+        Dar_ObjForEachCut( pObj, pCut, k )
+//            Cnf_CutAssignAreaFlow( p, pCut );
+            pCut->Area = (float)Cnf_CutArea( p->pManAig, pCut );
+
+        // find the new best cut
+        pCutBest = Cnf_ObjFindBestCut(pObj);
+        Dar_ObjSetBestCut( pCutBest );
+        // if the node is used, reference its cut
+        if ( pObj->nRefs )
+            Aig_CutRef( p->pManAig, pCutBest );
+    }
+    return 1;
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/cnf/cnfPost.c b/abc-build/src/sat/cnf/cnfPost.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/cnf/cnfPost.c
@@ -0,0 +1,238 @@
+/**CFile****************************************************************
+
+  FileName    [cnfPost.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG-to-CNF conversion.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: cnfPost.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cnf.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_ManPostprocess_old( Cnf_Man_t * p )
+{
+//    extern int Aig_ManLargeCutEval( Aig_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCutR, Dar_Cut_t * pCutL, int Leaf );
+    int nNew, Gain, nGain = 0, nVars = 0;
+
+    Aig_Obj_t * pObj, * pFan;
+    Dar_Cut_t * pCutBest, * pCut;
+    int i, k;//, a, b, Counter;
+    Aig_ManForEachObj( p->pManAig, pObj, i )
+    {
+        if ( !Aig_ObjIsNode(pObj) )
+            continue;
+        if ( pObj->nRefs == 0 )
+            continue;
+//        pCutBest = Aig_ObjBestCut(pObj);
+        pCutBest = NULL;
+
+        Dar_CutForEachLeaf( p->pManAig, pCutBest, pFan, k )
+        {
+            if ( !Aig_ObjIsNode(pFan) )
+                continue;
+            assert( pFan->nRefs != 0 );
+            if ( pFan->nRefs != 1 )
+                continue;
+//            pCut = Aig_ObjBestCut(pFan);
+            pCut = NULL;
+/*
+            // find how many common variable they have
+            Counter = 0;
+            for ( a = 0; a < (int)pCut->nLeaves; a++ )
+            {
+                for ( b = 0; b < (int)pCutBest->nLeaves; b++ )
+                    if ( pCut->pLeaves[a] == pCutBest->pLeaves[b] )
+                        break;
+                if ( b == (int)pCutBest->nLeaves )
+                    continue;
+                Counter++;
+            }
+            printf( "%d ", Counter );
+*/
+            // find the new truth table after collapsing these two cuts
+
+
+//            nNew = Aig_ManLargeCutEval( p->pManAig, pObj, pCutBest, pCut, pFan->Id );
+            nNew = 0;
+
+
+//            printf( "%d+%d=%d:%d(%d) ", pCutBest->Cost, pCut->Cost, 
+//                pCutBest->Cost+pCut->Cost, nNew, pCutBest->Cost+pCut->Cost-nNew );
+
+            Gain = pCutBest->Value + pCut->Value - nNew;
+            if ( Gain > 0 )
+            {
+                nGain += Gain;
+                nVars++;
+            }
+        }
+    }
+    printf( "Total gain = %d.  Vars = %d.\n", nGain, nVars );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers cuts of the mapped nodes into internal representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_ManTransferCuts( Cnf_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_MmFlexRestart( p->pMemCuts );
+    Aig_ManForEachObj( p->pManAig, pObj, i )
+    {
+        if ( Aig_ObjIsNode(pObj) && pObj->nRefs > 0 )
+            pObj->pData = Cnf_CutCreate( p, pObj );
+        else
+            pObj->pData = NULL;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers cuts of the mapped nodes into internal representation.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_ManFreeCuts( Cnf_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    int i;
+    Aig_ManForEachObj( p->pManAig, pObj, i )
+        if ( pObj->pData )
+        {
+            Cnf_CutFree( (Cnf_Cut_t *)pObj->pData );
+            pObj->pData = NULL;
+        }
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_ManPostprocess( Cnf_Man_t * p )
+{
+    Cnf_Cut_t * pCut, * pCutFan, * pCutRes;
+    Aig_Obj_t * pObj, * pFan;
+    int Order[16], Costs[16];
+    int i, k, fChanges;
+    Aig_ManForEachNode( p->pManAig, pObj, i )
+    {
+        if ( pObj->nRefs == 0 )
+            continue;
+        pCut = Cnf_ObjBestCut(pObj);
+
+        // sort fanins according to their size
+        Cnf_CutForEachLeaf( p->pManAig, pCut, pFan, k )
+        {
+            Order[k] = k;
+            Costs[k] = Aig_ObjIsNode(pFan)? Cnf_ObjBestCut(pFan)->Cost : 0;
+        }
+        // sort the cuts by Weight
+        do {
+            int Temp;
+            fChanges = 0;
+            for ( k = 0; k < pCut->nFanins - 1; k++ )
+            {
+                if ( Costs[Order[k]] <= Costs[Order[k+1]] )
+                    continue;
+                Temp = Order[k];
+                Order[k] = Order[k+1];
+                Order[k+1] = Temp;
+                fChanges = 1;
+            }
+        } while ( fChanges );
+
+
+//        Cnf_CutForEachLeaf( p->pManAig, pCut, pFan, k )
+        for ( k = 0; (k < (int)(pCut)->nFanins) && ((pFan) = Aig_ManObj(p->pManAig, (pCut)->pFanins[Order[k]])); k++ )
+        {
+            if ( !Aig_ObjIsNode(pFan) )
+                continue;
+            assert( pFan->nRefs != 0 );
+            if ( pFan->nRefs != 1 )
+                continue;
+            pCutFan = Cnf_ObjBestCut(pFan);
+            // try composing these two cuts
+//            Cnf_CutPrint( pCut );
+            pCutRes = Cnf_CutCompose( p, pCut, pCutFan, pFan->Id );
+//            Cnf_CutPrint( pCut );
+//            printf( "\n" );
+            // check if the cost if reduced
+            if ( pCutRes == NULL || pCutRes->Cost == 127 || pCutRes->Cost > pCut->Cost + pCutFan->Cost )
+            {
+                if ( pCutRes )
+                    Cnf_CutFree( pCutRes );
+                continue;
+            }
+            // update the cut
+            Cnf_ObjSetBestCut( pObj, pCutRes );
+            Cnf_ObjSetBestCut( pFan, NULL );
+            Cnf_CutUpdateRefs( p, pCut, pCutFan, pCutRes );
+            assert( pFan->nRefs == 0 );
+            Cnf_CutFree( pCut );
+            Cnf_CutFree( pCutFan );
+            break;
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/cnf/cnfUtil.c b/abc-build/src/sat/cnf/cnfUtil.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/cnf/cnfUtil.c
@@ -0,0 +1,456 @@
+/**CFile****************************************************************
+
+  FileName    [cnfUtil.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG-to-CNF conversion.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: cnfUtil.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cnf.h"
+#include "sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area, references, and nodes used in the mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Aig_ManScanMapping_rec( Cnf_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vMapped )
+{
+    Aig_Obj_t * pLeaf;
+    Dar_Cut_t * pCutBest;
+    int aArea, i;
+    if ( pObj->nRefs++ || Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) )
+        return 0;
+    assert( Aig_ObjIsAnd(pObj) );
+    // collect the node first to derive pre-order
+    if ( vMapped )
+        Vec_PtrPush( vMapped, pObj );
+    // visit the transitive fanin of the selected cut
+    if ( pObj->fMarkB )
+    {
+        Vec_Ptr_t * vSuper = Vec_PtrAlloc( 100 );
+        Aig_ObjCollectSuper( pObj, vSuper );
+        aArea = Vec_PtrSize(vSuper) + 1;
+        Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pLeaf, i )
+            aArea += Aig_ManScanMapping_rec( p, Aig_Regular(pLeaf), vMapped );
+        Vec_PtrFree( vSuper );
+        ////////////////////////////
+        pObj->fMarkB = 1;
+    }
+    else
+    {
+        pCutBest = Dar_ObjBestCut( pObj );
+        aArea = Cnf_CutSopCost( p, pCutBest );
+        Dar_CutForEachLeaf( p->pManAig, pCutBest, pLeaf, i )
+            aArea += Aig_ManScanMapping_rec( p, pLeaf, vMapped );
+    }
+    return aArea;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area, references, and nodes used in the mapping.]
+
+  Description [Collects the nodes in reverse topological order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManScanMapping( Cnf_Man_t * p, int fCollect )
+{
+    Vec_Ptr_t * vMapped = NULL;
+    Aig_Obj_t * pObj;
+    int i;
+    // clean all references
+    Aig_ManForEachObj( p->pManAig, pObj, i )
+        pObj->nRefs = 0;
+    // allocate the array
+    if ( fCollect )
+        vMapped = Vec_PtrAlloc( 1000 );
+    // collect nodes reachable from POs in the DFS order through the best cuts
+    p->aArea = 0;
+    Aig_ManForEachCo( p->pManAig, pObj, i )
+        p->aArea += Aig_ManScanMapping_rec( p, Aig_ObjFanin0(pObj), vMapped );
+//    printf( "Variables = %6d. Clauses = %8d.\n", vMapped? Vec_PtrSize(vMapped) + Aig_ManCiNum(p->pManAig) + 1 : 0, p->aArea + 2 );
+    return vMapped;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area, references, and nodes used in the mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cnf_ManScanMapping_rec( Cnf_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vMapped, int fPreorder )
+{
+    Aig_Obj_t * pLeaf;
+    Cnf_Cut_t * pCutBest;
+    int aArea, i;
+    if ( pObj->nRefs++ || Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) )
+        return 0;
+    assert( Aig_ObjIsAnd(pObj) );
+    assert( pObj->pData != NULL );
+    // add the node to the mapping
+    if ( vMapped && fPreorder )
+         Vec_PtrPush( vMapped, pObj );
+    // visit the transitive fanin of the selected cut
+    if ( pObj->fMarkB )
+    {
+        Vec_Ptr_t * vSuper = Vec_PtrAlloc( 100 );
+        Aig_ObjCollectSuper( pObj, vSuper );
+        aArea = Vec_PtrSize(vSuper) + 1;
+        Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pLeaf, i )
+            aArea += Cnf_ManScanMapping_rec( p, Aig_Regular(pLeaf), vMapped, fPreorder );
+        Vec_PtrFree( vSuper );
+        ////////////////////////////
+        pObj->fMarkB = 1;
+    }
+    else
+    {
+        pCutBest = (Cnf_Cut_t *)pObj->pData;
+//        assert( pCutBest->nFanins > 0 );
+        assert( pCutBest->Cost < 127 );
+        aArea = pCutBest->Cost;
+        Cnf_CutForEachLeaf( p->pManAig, pCutBest, pLeaf, i )
+            aArea += Cnf_ManScanMapping_rec( p, pLeaf, vMapped, fPreorder );
+    }
+    // add the node to the mapping
+    if ( vMapped && !fPreorder )
+         Vec_PtrPush( vMapped, pObj );
+    return aArea;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes area, references, and nodes used in the mapping.]
+
+  Description [Collects the nodes in reverse topological order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Cnf_ManScanMapping( Cnf_Man_t * p, int fCollect, int fPreorder )
+{
+    Vec_Ptr_t * vMapped = NULL;
+    Aig_Obj_t * pObj;
+    int i;
+    // clean all references
+    Aig_ManForEachObj( p->pManAig, pObj, i )
+        pObj->nRefs = 0;
+    // allocate the array
+    if ( fCollect )
+        vMapped = Vec_PtrAlloc( 1000 );
+    // collect nodes reachable from POs in the DFS order through the best cuts
+    p->aArea = 0;
+    Aig_ManForEachCo( p->pManAig, pObj, i )
+        p->aArea += Cnf_ManScanMapping_rec( p, Aig_ObjFanin0(pObj), vMapped, fPreorder );
+//    printf( "Variables = %6d. Clauses = %8d.\n", vMapped? Vec_PtrSize(vMapped) + Aig_ManCiNum(p->pManAig) + 1 : 0, p->aArea + 2 );
+    return vMapped;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of CI IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Cnf_DataCollectCiSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p )
+{
+    Vec_Int_t * vCiIds;
+    Aig_Obj_t * pObj;
+    int i;
+    vCiIds = Vec_IntAlloc( Aig_ManCiNum(p) );
+    Aig_ManForEachCi( p, pObj, i )
+        Vec_IntPush( vCiIds, pCnf->pVarNums[pObj->Id] );
+    return vCiIds;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the array of CI IDs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Cnf_DataCollectCoSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p )
+{
+    Vec_Int_t * vCoIds;
+    Aig_Obj_t * pObj;
+    int i;
+    vCoIds = Vec_IntAlloc( Aig_ManCoNum(p) );
+    Aig_ManForEachCo( p, pObj, i )
+        Vec_IntPush( vCoIds, pCnf->pVarNums[pObj->Id] );
+    return vCoIds;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+unsigned char * Cnf_DataDeriveLitPolarities( Cnf_Dat_t * p )
+{
+    int i, c, iClaBeg, iClaEnd, * pLit;
+    unsigned * pPols0 = ABC_CALLOC( unsigned, Aig_ManObjNumMax(p->pMan) );
+    unsigned * pPols1 = ABC_CALLOC( unsigned, Aig_ManObjNumMax(p->pMan) );
+    unsigned char * pPres = ABC_CALLOC( unsigned char, p->nClauses );
+    for ( i = 0; i < Aig_ManObjNumMax(p->pMan); i++ )
+    {
+        if ( p->pObj2Count[i] == 0 )
+            continue;
+        iClaBeg = p->pObj2Clause[i];
+        iClaEnd = p->pObj2Clause[i] + p->pObj2Count[i];
+        // go through the negative polarity clauses
+        for ( c = iClaBeg; c < iClaEnd; c++ )
+            for ( pLit = p->pClauses[c]+1; pLit < p->pClauses[c+1]; pLit++ )
+                if ( Abc_LitIsCompl(p->pClauses[c][0]) )
+                    pPols0[Abc_Lit2Var(*pLit)] |= (unsigned)(2 - Abc_LitIsCompl(*pLit));  // taking the opposite (!) -- not the case
+                else
+                    pPols1[Abc_Lit2Var(*pLit)] |= (unsigned)(2 - Abc_LitIsCompl(*pLit));  // taking the opposite (!) -- not the case
+        // record these clauses
+        for ( c = iClaBeg; c < iClaEnd; c++ )
+            for ( pLit = p->pClauses[c]+1; pLit < p->pClauses[c+1]; pLit++ )
+                if ( Abc_LitIsCompl(p->pClauses[c][0]) )
+                    pPres[c] = (unsigned char)( (unsigned)pPres[c] | (pPols0[Abc_Lit2Var(*pLit)] << (2*(pLit-p->pClauses[c]-1))) );
+                else
+                    pPres[c] = (unsigned char)( (unsigned)pPres[c] | (pPols1[Abc_Lit2Var(*pLit)] << (2*(pLit-p->pClauses[c]-1))) );
+        // clean negative polarity
+        for ( c = iClaBeg; c < iClaEnd; c++ )
+            for ( pLit = p->pClauses[c]+1; pLit < p->pClauses[c+1]; pLit++ )
+                pPols0[Abc_Lit2Var(*pLit)] = pPols1[Abc_Lit2Var(*pLit)] = 0;
+    }
+    ABC_FREE( pPols0 );
+    ABC_FREE( pPols1 );
+/*
+//    for ( c = 0; c < p->nClauses; c++ )
+    for ( c = 0; c < 100; c++ )
+    {
+        printf( "Clause %6d : ", c );
+        for ( i = 0; i < 4; i++ )
+            printf( "%d ", ((unsigned)pPres[c] >> (2*i)) & 3 );
+        printf( "  " );
+        for ( pLit = p->pClauses[c]; pLit < p->pClauses[c+1]; pLit++ )
+            printf( "%6d ", *pLit );
+        printf( "\n" );
+    }
+*/
+    return pPres;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Dat_t * Cnf_DataReadFromFile( char * pFileName )
+{
+    int MaxLine = 1000000;
+    int Var, Lit, nVars = -1, nClas = -1, i, Entry, iLine = 0;
+    Cnf_Dat_t * pCnf = NULL;
+    Vec_Int_t * vClas = NULL;
+    Vec_Int_t * vLits = NULL;
+    char * pBuffer, * pToken;
+    FILE * pFile = fopen( pFileName, "rb" );
+    if ( pFile == NULL )
+    {
+        printf( "Cannot open file \"%s\" for writing.\n", pFileName );
+        return NULL;
+    }
+    pBuffer = ABC_ALLOC( char, MaxLine );
+    while ( fgets(pBuffer, MaxLine, pFile) != NULL )
+    {
+        iLine++;
+        if ( pBuffer[0] == 'c' )
+            continue;
+        if ( pBuffer[0] == 'p' )
+        {
+            pToken = strtok( pBuffer+1, " \t" );
+            if ( strcmp(pToken, "cnf") )
+            {
+                printf( "Incorrect input file.\n" );
+                goto finish;
+            }
+            pToken = strtok( NULL, " \t" );
+            nVars = atoi( pToken );
+            pToken = strtok( NULL, " \t" );
+            nClas = atoi( pToken );
+            if ( nVars <= 0 || nClas <= 0 )
+            {
+                printf( "Incorrect parameters.\n" );
+                goto finish;
+            }
+            // temp storage
+            vClas = Vec_IntAlloc( nClas+1 );
+            vLits = Vec_IntAlloc( nClas*8 );
+            continue;
+        }
+        pToken = strtok( pBuffer, " \t\r\n" );
+        if ( pToken == NULL )
+            continue;
+        Vec_IntPush( vClas, Vec_IntSize(vLits) );
+        while ( pToken )
+        {
+            Var = atoi( pToken );
+            if ( Var == 0 )
+                break;
+            Lit = (Var > 0) ? Abc_Var2Lit(Var-1, 0) : Abc_Var2Lit(-Var-1, 1);
+            if ( Lit >= 2*nVars )
+            {
+                printf( "Literal %d is out-of-bound for %d variables.\n", Lit, nVars );
+                goto finish;
+            }
+            Vec_IntPush( vLits, Lit );
+            pToken = strtok( NULL, " \t\r\n" );
+        }
+        if ( Var != 0 )
+        {
+            printf( "There is no zero-terminator in line %d.\n", iLine );
+            goto finish;
+        }
+    }
+    // finalize
+    if ( Vec_IntSize(vClas) != nClas )
+        printf( "Warning! The number of clauses (%d) is different from declaration (%d).\n", Vec_IntSize(vClas), nClas );
+    Vec_IntPush( vClas, Vec_IntSize(vLits) );
+    // create
+    pCnf = ABC_CALLOC( Cnf_Dat_t, 1 );
+    pCnf->nVars     = nVars;
+    pCnf->nClauses  = nClas;
+    pCnf->nLiterals = Vec_IntSize(vLits);
+    pCnf->pClauses  = ABC_ALLOC( int *, Vec_IntSize(vClas) );
+    pCnf->pClauses[0] = Vec_IntReleaseArray(vLits);
+    Vec_IntForEachEntry( vClas, Entry, i )
+        pCnf->pClauses[i] = pCnf->pClauses[0] + Entry;
+finish:
+    fclose( pFile );
+    Vec_IntFreeP( &vClas );
+    Vec_IntFreeP( &vLits );
+    ABC_FREE( pBuffer );
+    return pCnf;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cnf_DataSolveFromFile( char * pFileName, int nConfLimit, int fVerbose )
+{
+    abctime clk = Abc_Clock();
+    Cnf_Dat_t * pCnf = Cnf_DataReadFromFile( pFileName );
+    sat_solver * pSat;
+    int status, RetValue = -1;
+    if ( pCnf == NULL )
+        return -1;
+    if ( fVerbose )
+    {
+        printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals );
+        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    }
+    // convert into SAT solver
+    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+    Cnf_DataFree( pCnf );
+    if ( pSat == NULL )
+    {
+        printf( "The problem is trivially UNSAT.\n" );
+        return 1;
+    }
+    // solve the miter
+//    if ( fVerbose )
+//        pSat->verbosity = 1;
+    status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, 0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+    if ( status == l_Undef )
+        RetValue = -1;
+    else if ( status == l_True )
+        RetValue = 0;
+    else if ( status == l_False )
+        RetValue = 1;
+    else
+        assert( 0 );
+    if ( fVerbose )
+        Sat_SolverPrintStats( stdout, pSat );
+    sat_solver_delete( pSat );
+    if ( RetValue == -1 )
+        Abc_Print( 1, "UNDECIDED      " );
+    else if ( RetValue == 0 )
+        Abc_Print( 1, "SATISFIABLE    " );
+    else
+        Abc_Print( 1, "UNSATISFIABLE  " );
+    //Abc_Print( -1, "\n" );
+    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+    return RetValue;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/cnf/cnfWrite.c b/abc-build/src/sat/cnf/cnfWrite.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/cnf/cnfWrite.c
@@ -0,0 +1,806 @@
+/**CFile****************************************************************
+
+  FileName    [cnfWrite.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG-to-CNF conversion.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: cnfWrite.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cnf.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CNF mapping.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Int_t * Cnf_ManWriteCnfMapping( Cnf_Man_t * p, Vec_Ptr_t * vMapped )
+{
+    Vec_Int_t * vResult;
+    Aig_Obj_t * pObj;
+    Cnf_Cut_t * pCut;
+    int i, k, nOffset;
+    nOffset = Aig_ManObjNumMax(p->pManAig);
+    vResult = Vec_IntStart( nOffset );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vMapped, pObj, i )
+    {
+        assert( Aig_ObjIsNode(pObj) );
+        pCut = Cnf_ObjBestCut( pObj );
+        assert( pCut->nFanins < 5 );
+        Vec_IntWriteEntry( vResult, Aig_ObjId(pObj), nOffset );
+        Vec_IntPush( vResult, *Cnf_CutTruth(pCut) );
+        for ( k = 0; k < pCut->nFanins; k++ )
+            Vec_IntPush( vResult, pCut->pFanins[k] );
+        for (      ; k < 4; k++ )
+            Vec_IntPush( vResult, -1 );
+        nOffset += 5;
+    }
+    return vResult;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the cover into the array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Cnf_SopConvertToVector( char * pSop, int nCubes, Vec_Int_t * vCover )
+{
+    int Lits[4], Cube, iCube, i, b;
+    Vec_IntClear( vCover );
+    for ( i = 0; i < nCubes; i++ )
+    {
+        Cube = pSop[i];
+        for ( b = 0; b < 4; b++ )
+        {
+            if ( Cube % 3 == 0 )
+                Lits[b] = 1;
+            else if ( Cube % 3 == 1 )
+                Lits[b] = 2;
+            else
+                Lits[b] = 0;
+            Cube = Cube / 3;
+        }
+        iCube = 0;
+        for ( b = 0; b < 4; b++ )
+            iCube = (iCube << 2) | Lits[b];
+        Vec_IntPush( vCover, iCube );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of literals in the SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cnf_SopCountLiterals( char * pSop, int nCubes )
+{
+    int nLits = 0, Cube, i, b;
+    for ( i = 0; i < nCubes; i++ )
+    {
+        Cube = pSop[i];
+        for ( b = 0; b < 4; b++ )
+        {
+            if ( Cube % 3 != 2 )
+                nLits++;
+            Cube = Cube / 3;
+        }
+    }
+    return nLits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the number of literals in the SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cnf_IsopCountLiterals( Vec_Int_t * vIsop, int nVars )
+{
+    int nLits = 0, Cube, i, b;
+    Vec_IntForEachEntry( vIsop, Cube, i )
+    {
+        for ( b = 0; b < nVars; b++ )
+        {
+            if ( (Cube & 3) == 1 || (Cube & 3) == 2 )
+                nLits++;
+            Cube >>= 2;
+        }
+    }
+    return nLits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the cube and returns the number of literals in it.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Cnf_IsopWriteCube( int Cube, int nVars, int * pVars, int * pLiterals )
+{
+    int nLits = nVars, b;
+    for ( b = 0; b < nVars; b++ )
+    {
+        if ( (Cube & 3) == 1 ) // value 0 --> write positive literal
+            *pLiterals++ = 2 * pVars[b];
+        else if ( (Cube & 3) == 2 ) // value 1 --> write negative literal
+            *pLiterals++ = 2 * pVars[b] + 1;
+        else
+            nLits--;
+        Cube >>= 2;
+    }
+    return nLits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CNF for the mapping.]
+
+  Description [The last argument shows the number of last outputs
+  of the manager, which will not be converted into clauses but the
+  new variables for which will be introduced.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Dat_t * Cnf_ManWriteCnf( Cnf_Man_t * p, Vec_Ptr_t * vMapped, int nOutputs )
+{
+    int fChangeVariableOrder = 0; // should be set to 0 to improve performance
+    Aig_Obj_t * pObj;
+    Cnf_Dat_t * pCnf;
+    Cnf_Cut_t * pCut;
+    Vec_Int_t * vCover, * vSopTemp;
+    int OutVar, PoVar, pVars[32], * pLits, ** pClas;
+    unsigned uTruth;
+    int i, k, nLiterals, nClauses, Cube, Number;
+
+    // count the number of literals and clauses
+    nLiterals = 1 + Aig_ManCoNum( p->pManAig ) + 3 * nOutputs;
+    nClauses = 1 + Aig_ManCoNum( p->pManAig ) + nOutputs;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vMapped, pObj, i )
+    {
+        assert( Aig_ObjIsNode(pObj) );
+        pCut = Cnf_ObjBestCut( pObj );
+
+        // positive polarity of the cut
+        if ( pCut->nFanins < 5 )
+        {
+            uTruth = 0xFFFF & *Cnf_CutTruth(pCut);
+            nLiterals += Cnf_SopCountLiterals( p->pSops[uTruth], p->pSopSizes[uTruth] ) + p->pSopSizes[uTruth];
+            assert( p->pSopSizes[uTruth] >= 0 );
+            nClauses += p->pSopSizes[uTruth];
+        }
+        else
+        {
+            nLiterals += Cnf_IsopCountLiterals( pCut->vIsop[1], pCut->nFanins ) + Vec_IntSize(pCut->vIsop[1]);
+            nClauses += Vec_IntSize(pCut->vIsop[1]);
+        }
+        // negative polarity of the cut
+        if ( pCut->nFanins < 5 )
+        {
+            uTruth = 0xFFFF & ~*Cnf_CutTruth(pCut);
+            nLiterals += Cnf_SopCountLiterals( p->pSops[uTruth], p->pSopSizes[uTruth] ) + p->pSopSizes[uTruth];
+            assert( p->pSopSizes[uTruth] >= 0 );
+            nClauses += p->pSopSizes[uTruth];
+        }
+        else
+        {
+            nLiterals += Cnf_IsopCountLiterals( pCut->vIsop[0], pCut->nFanins ) + Vec_IntSize(pCut->vIsop[0]);
+            nClauses += Vec_IntSize(pCut->vIsop[0]);
+        }
+//printf( "%d ", nClauses-(1 + Aig_ManCoNum( p->pManAig )) );
+    }
+//printf( "\n" );
+
+    // allocate CNF
+    pCnf = ABC_CALLOC( Cnf_Dat_t, 1 );
+    pCnf->pMan = p->pManAig;
+    pCnf->nLiterals = nLiterals;
+    pCnf->nClauses = nClauses;
+    pCnf->pClauses = ABC_ALLOC( int *, nClauses + 1 );
+    pCnf->pClauses[0] = ABC_ALLOC( int, nLiterals );
+    pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals;
+    // create room for variable numbers
+    pCnf->pVarNums = ABC_ALLOC( int, Aig_ManObjNumMax(p->pManAig) );
+//    memset( pCnf->pVarNums, 0xff, sizeof(int) * Aig_ManObjNumMax(p->pManAig) );
+    for ( i = 0; i < Aig_ManObjNumMax(p->pManAig); i++ )
+        pCnf->pVarNums[i] = -1;
+
+    if ( !fChangeVariableOrder )
+    {
+        // assign variables to the last (nOutputs) POs
+        Number = 1;
+        if ( nOutputs )
+        {
+            if ( Aig_ManRegNum(p->pManAig) == 0 )
+            {
+                assert( nOutputs == Aig_ManCoNum(p->pManAig) );
+                Aig_ManForEachCo( p->pManAig, pObj, i )
+                    pCnf->pVarNums[pObj->Id] = Number++;
+            }
+            else
+            {
+                assert( nOutputs == Aig_ManRegNum(p->pManAig) );
+                Aig_ManForEachLiSeq( p->pManAig, pObj, i )
+                    pCnf->pVarNums[pObj->Id] = Number++;
+            }
+        }
+        // assign variables to the internal nodes
+        Vec_PtrForEachEntry( Aig_Obj_t *, vMapped, pObj, i )
+            pCnf->pVarNums[pObj->Id] = Number++;
+        // assign variables to the PIs and constant node
+        Aig_ManForEachCi( p->pManAig, pObj, i )
+            pCnf->pVarNums[pObj->Id] = Number++;
+        pCnf->pVarNums[Aig_ManConst1(p->pManAig)->Id] = Number++;
+        pCnf->nVars = Number;
+    }
+    else
+    {
+        // assign variables to the last (nOutputs) POs
+        Number = Aig_ManObjNumMax(p->pManAig) + 1;
+        pCnf->nVars = Number + 1;
+        if ( nOutputs )
+        {
+            if ( Aig_ManRegNum(p->pManAig) == 0 )
+            {
+                assert( nOutputs == Aig_ManCoNum(p->pManAig) );
+                Aig_ManForEachCo( p->pManAig, pObj, i )
+                    pCnf->pVarNums[pObj->Id] = Number--;
+            }
+            else
+            {
+                assert( nOutputs == Aig_ManRegNum(p->pManAig) );
+                Aig_ManForEachLiSeq( p->pManAig, pObj, i )
+                    pCnf->pVarNums[pObj->Id] = Number--;
+            }
+        }
+        // assign variables to the internal nodes
+        Vec_PtrForEachEntry( Aig_Obj_t *, vMapped, pObj, i )
+            pCnf->pVarNums[pObj->Id] = Number--;
+        // assign variables to the PIs and constant node
+        Aig_ManForEachCi( p->pManAig, pObj, i )
+            pCnf->pVarNums[pObj->Id] = Number--;
+        pCnf->pVarNums[Aig_ManConst1(p->pManAig)->Id] = Number--;
+        assert( Number >= 0 );
+    }
+
+    // assign the clauses
+    vSopTemp = Vec_IntAlloc( 1 << 16 );
+    pLits = pCnf->pClauses[0];
+    pClas = pCnf->pClauses;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vMapped, pObj, i )
+    {
+        pCut = Cnf_ObjBestCut( pObj );
+
+        // save variables of this cut
+        OutVar = pCnf->pVarNums[ pObj->Id ];
+        for ( k = 0; k < (int)pCut->nFanins; k++ )
+        {
+            pVars[k] = pCnf->pVarNums[ pCut->pFanins[k] ];
+            assert( pVars[k] <= Aig_ManObjNumMax(p->pManAig) );
+        }
+
+        // positive polarity of the cut
+        if ( pCut->nFanins < 5 )
+        {
+            uTruth = 0xFFFF & *Cnf_CutTruth(pCut);
+            Cnf_SopConvertToVector( p->pSops[uTruth], p->pSopSizes[uTruth], vSopTemp );
+            vCover = vSopTemp;
+        }
+        else
+            vCover = pCut->vIsop[1];
+        Vec_IntForEachEntry( vCover, Cube, k )
+        {
+            *pClas++ = pLits;
+            *pLits++ = 2 * OutVar; 
+            pLits += Cnf_IsopWriteCube( Cube, pCut->nFanins, pVars, pLits );
+        }
+
+        // negative polarity of the cut
+        if ( pCut->nFanins < 5 )
+        {
+            uTruth = 0xFFFF & ~*Cnf_CutTruth(pCut);
+            Cnf_SopConvertToVector( p->pSops[uTruth], p->pSopSizes[uTruth], vSopTemp );
+            vCover = vSopTemp;
+        }
+        else
+            vCover = pCut->vIsop[0];
+        Vec_IntForEachEntry( vCover, Cube, k )
+        {
+            *pClas++ = pLits;
+            *pLits++ = 2 * OutVar + 1; 
+            pLits += Cnf_IsopWriteCube( Cube, pCut->nFanins, pVars, pLits );
+        }
+    }
+    Vec_IntFree( vSopTemp );
+ 
+    // write the constant literal
+    OutVar = pCnf->pVarNums[ Aig_ManConst1(p->pManAig)->Id ];
+    assert( OutVar <= Aig_ManObjNumMax(p->pManAig) );
+    *pClas++ = pLits;
+    *pLits++ = 2 * OutVar; 
+
+    // write the output literals
+    Aig_ManForEachCo( p->pManAig, pObj, i )
+    {
+        OutVar = pCnf->pVarNums[ Aig_ObjFanin0(pObj)->Id ];
+        if ( i < Aig_ManCoNum(p->pManAig) - nOutputs )
+        {
+            *pClas++ = pLits;
+            *pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj); 
+        }
+        else
+        {
+            PoVar = pCnf->pVarNums[ pObj->Id ];
+            // first clause
+            *pClas++ = pLits;
+            *pLits++ = 2 * PoVar; 
+            *pLits++ = 2 * OutVar + !Aig_ObjFaninC0(pObj); 
+            // second clause
+            *pClas++ = pLits;
+            *pLits++ = 2 * PoVar + 1; 
+            *pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj); 
+        }
+    }
+
+    // verify that the correct number of literals and clauses was written
+    assert( pLits - pCnf->pClauses[0] == nLiterals );
+    assert( pClas - pCnf->pClauses == nClauses );
+//Cnf_DataPrint( pCnf, 1 );
+    return pCnf;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives CNF for the mapping.]
+
+  Description [Derives CNF with obj IDs as SAT vars and mapping of
+  objects into clauses (pObj2Clause and pObj2Count).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Dat_t * Cnf_ManWriteCnfOther( Cnf_Man_t * p, Vec_Ptr_t * vMapped )
+{
+    Aig_Obj_t * pObj;
+    Cnf_Dat_t * pCnf;
+    Cnf_Cut_t * pCut;
+    Vec_Int_t * vCover, * vSopTemp;
+    int OutVar, PoVar, pVars[32], * pLits, ** pClas;
+    unsigned uTruth;
+    int i, k, nLiterals, nClauses, Cube;
+
+    // count the number of literals and clauses
+    nLiterals = 1 + 4 * Aig_ManCoNum( p->pManAig );
+    nClauses  = 1 + 2 * Aig_ManCoNum( p->pManAig );
+    Vec_PtrForEachEntry( Aig_Obj_t *, vMapped, pObj, i )
+    {
+        assert( Aig_ObjIsNode(pObj) );
+        pCut = Cnf_ObjBestCut( pObj );
+        // positive polarity of the cut
+        if ( pCut->nFanins < 5 )
+        {
+            uTruth = 0xFFFF & *Cnf_CutTruth(pCut);
+            nLiterals += Cnf_SopCountLiterals( p->pSops[uTruth], p->pSopSizes[uTruth] ) + p->pSopSizes[uTruth];
+            assert( p->pSopSizes[uTruth] >= 0 );
+            nClauses += p->pSopSizes[uTruth];
+        }
+        else
+        {
+            nLiterals += Cnf_IsopCountLiterals( pCut->vIsop[1], pCut->nFanins ) + Vec_IntSize(pCut->vIsop[1]);
+            nClauses += Vec_IntSize(pCut->vIsop[1]);
+        }
+        // negative polarity of the cut
+        if ( pCut->nFanins < 5 )
+        {
+            uTruth = 0xFFFF & ~*Cnf_CutTruth(pCut);
+            nLiterals += Cnf_SopCountLiterals( p->pSops[uTruth], p->pSopSizes[uTruth] ) + p->pSopSizes[uTruth];
+            assert( p->pSopSizes[uTruth] >= 0 );
+            nClauses += p->pSopSizes[uTruth];
+        }
+        else
+        {
+            nLiterals += Cnf_IsopCountLiterals( pCut->vIsop[0], pCut->nFanins ) + Vec_IntSize(pCut->vIsop[0]);
+            nClauses += Vec_IntSize(pCut->vIsop[0]);
+        }
+    }
+
+    // allocate CNF
+    pCnf = ABC_CALLOC( Cnf_Dat_t, 1 );
+    pCnf->pMan = p->pManAig;
+    pCnf->nLiterals = nLiterals;
+    pCnf->nClauses  = nClauses;
+    pCnf->pClauses  = ABC_ALLOC( int *, nClauses + 1 );
+    pCnf->pClauses[0] = ABC_ALLOC( int, nLiterals );
+    pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals;
+    // create room for variable numbers
+    pCnf->pObj2Clause = ABC_ALLOC( int, Aig_ManObjNumMax(p->pManAig) );
+    pCnf->pObj2Count  = ABC_ALLOC( int, Aig_ManObjNumMax(p->pManAig) );
+    for ( i = 0; i < Aig_ManObjNumMax(p->pManAig); i++ )
+        pCnf->pObj2Clause[i] = pCnf->pObj2Count[i] = -1;
+    pCnf->nVars = Aig_ManObjNumMax(p->pManAig);
+
+    // clear the PI counters
+    Aig_ManForEachCi( p->pManAig, pObj, i )
+        pCnf->pObj2Count[pObj->Id] = 0;
+
+    // assign the clauses
+    vSopTemp = Vec_IntAlloc( 1 << 16 );
+    pLits = pCnf->pClauses[0];
+    pClas = pCnf->pClauses;
+    Vec_PtrForEachEntry( Aig_Obj_t *, vMapped, pObj, i )
+    {
+        // remember the starting clause
+        pCnf->pObj2Clause[pObj->Id] = pClas - pCnf->pClauses;
+        pCnf->pObj2Count[pObj->Id] = 0;
+
+        // get the best cut
+        pCut = Cnf_ObjBestCut( pObj );
+        // save variables of this cut
+        OutVar = pObj->Id;
+        for ( k = 0; k < (int)pCut->nFanins; k++ )
+        {
+            pVars[k] = pCut->pFanins[k];
+            assert( pVars[k] <= Aig_ManObjNumMax(p->pManAig) );
+        }
+
+        // positive polarity of the cut
+        if ( pCut->nFanins < 5 )
+        {
+            uTruth = 0xFFFF & *Cnf_CutTruth(pCut);
+            Cnf_SopConvertToVector( p->pSops[uTruth], p->pSopSizes[uTruth], vSopTemp );
+            vCover = vSopTemp;
+        }
+        else
+            vCover = pCut->vIsop[1];
+        Vec_IntForEachEntry( vCover, Cube, k )
+        {
+            *pClas++ = pLits;
+            *pLits++ = 2 * OutVar; 
+            pLits += Cnf_IsopWriteCube( Cube, pCut->nFanins, pVars, pLits );
+        }
+        pCnf->pObj2Count[pObj->Id] += Vec_IntSize(vCover);
+
+        // negative polarity of the cut
+        if ( pCut->nFanins < 5 )
+        {
+            uTruth = 0xFFFF & ~*Cnf_CutTruth(pCut);
+            Cnf_SopConvertToVector( p->pSops[uTruth], p->pSopSizes[uTruth], vSopTemp );
+            vCover = vSopTemp;
+        }
+        else
+            vCover = pCut->vIsop[0];
+        Vec_IntForEachEntry( vCover, Cube, k )
+        {
+            *pClas++ = pLits;
+            *pLits++ = 2 * OutVar + 1; 
+            pLits += Cnf_IsopWriteCube( Cube, pCut->nFanins, pVars, pLits );
+        }
+        pCnf->pObj2Count[pObj->Id] += Vec_IntSize(vCover);
+    }
+    Vec_IntFree( vSopTemp );
+
+    // write the output literals
+    Aig_ManForEachCo( p->pManAig, pObj, i )
+    {
+        // remember the starting clause
+        pCnf->pObj2Clause[pObj->Id] = pClas - pCnf->pClauses;
+        pCnf->pObj2Count[pObj->Id] = 2;
+        // get variables
+        OutVar = Aig_ObjFanin0(pObj)->Id;
+        PoVar = pObj->Id;
+        // first clause
+        *pClas++ = pLits;
+        *pLits++ = 2 * PoVar; 
+        *pLits++ = 2 * OutVar + !Aig_ObjFaninC0(pObj); 
+        // second clause
+        *pClas++ = pLits;
+        *pLits++ = 2 * PoVar + 1; 
+        *pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj); 
+    }
+ 
+    // remember the starting clause
+    pCnf->pObj2Clause[Aig_ManConst1(p->pManAig)->Id] = pClas - pCnf->pClauses;
+    pCnf->pObj2Count[Aig_ManConst1(p->pManAig)->Id] = 1;
+    // write the constant literal
+    OutVar = Aig_ManConst1(p->pManAig)->Id;
+    *pClas++ = pLits;
+    *pLits++ = 2 * OutVar; 
+
+    // verify that the correct number of literals and clauses was written
+    assert( pLits - pCnf->pClauses[0] == nLiterals );
+    assert( pClas - pCnf->pClauses == nClauses );
+//Cnf_DataPrint( pCnf, 1 );
+    return pCnf;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Derives a simple CNF for the AIG.]
+
+  Description [The last argument lists the number of last outputs
+  of the manager, which will not be converted into clauses. 
+  New variables will be introduced for these outputs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Dat_t * Cnf_DeriveSimple( Aig_Man_t * p, int nOutputs )
+{
+    Aig_Obj_t * pObj;
+    Cnf_Dat_t * pCnf;
+    int OutVar, PoVar, pVars[32], * pLits, ** pClas;
+    int i, nLiterals, nClauses, Number;
+
+    // count the number of literals and clauses
+    nLiterals = 1 + 7 * Aig_ManNodeNum(p) + Aig_ManCoNum( p ) + 3 * nOutputs;
+    nClauses = 1 + 3 * Aig_ManNodeNum(p) + Aig_ManCoNum( p ) + nOutputs;
+
+    // allocate CNF
+    pCnf = ABC_ALLOC( Cnf_Dat_t, 1 );
+    memset( pCnf, 0, sizeof(Cnf_Dat_t) );
+    pCnf->pMan = p;
+    pCnf->nLiterals = nLiterals;
+    pCnf->nClauses = nClauses;
+    pCnf->pClauses = ABC_ALLOC( int *, nClauses + 1 );
+    pCnf->pClauses[0] = ABC_ALLOC( int, nLiterals );
+    pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals;
+
+    // create room for variable numbers
+    pCnf->pVarNums = ABC_ALLOC( int, Aig_ManObjNumMax(p) );
+//    memset( pCnf->pVarNums, 0xff, sizeof(int) * Aig_ManObjNumMax(p) );
+    for ( i = 0; i < Aig_ManObjNumMax(p); i++ )
+        pCnf->pVarNums[i] = -1;
+    // assign variables to the last (nOutputs) POs
+    Number = 1;
+    if ( nOutputs )
+    {
+//        assert( nOutputs == Aig_ManRegNum(p) );
+//        Aig_ManForEachLiSeq( p, pObj, i )
+//            pCnf->pVarNums[pObj->Id] = Number++;
+        Aig_ManForEachCo( p, pObj, i )
+            pCnf->pVarNums[pObj->Id] = Number++;
+    }
+    // assign variables to the internal nodes
+    Aig_ManForEachNode( p, pObj, i )
+        pCnf->pVarNums[pObj->Id] = Number++;
+    // assign variables to the PIs and constant node
+    Aig_ManForEachCi( p, pObj, i )
+        pCnf->pVarNums[pObj->Id] = Number++;
+    pCnf->pVarNums[Aig_ManConst1(p)->Id] = Number++;
+    pCnf->nVars = Number;
+/*
+    // print CNF numbers
+    printf( "SAT numbers of each node:\n" );
+    Aig_ManForEachObj( p, pObj, i )
+        printf( "%d=%d ", pObj->Id, pCnf->pVarNums[pObj->Id] );
+    printf( "\n" );
+*/
+    // assign the clauses
+    pLits = pCnf->pClauses[0];
+    pClas = pCnf->pClauses;
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        OutVar   = pCnf->pVarNums[ pObj->Id ];
+        pVars[0] = pCnf->pVarNums[ Aig_ObjFanin0(pObj)->Id ];
+        pVars[1] = pCnf->pVarNums[ Aig_ObjFanin1(pObj)->Id ];
+
+        // positive phase
+        *pClas++ = pLits;
+        *pLits++ = 2 * OutVar; 
+        *pLits++ = 2 * pVars[0] + !Aig_ObjFaninC0(pObj); 
+        *pLits++ = 2 * pVars[1] + !Aig_ObjFaninC1(pObj); 
+        // negative phase
+        *pClas++ = pLits;
+        *pLits++ = 2 * OutVar + 1; 
+        *pLits++ = 2 * pVars[0] + Aig_ObjFaninC0(pObj); 
+        *pClas++ = pLits;
+        *pLits++ = 2 * OutVar + 1; 
+        *pLits++ = 2 * pVars[1] + Aig_ObjFaninC1(pObj); 
+    }
+ 
+    // write the constant literal
+    OutVar = pCnf->pVarNums[ Aig_ManConst1(p)->Id ];
+    assert( OutVar <= Aig_ManObjNumMax(p) );
+    *pClas++ = pLits;
+    *pLits++ = 2 * OutVar;  
+
+    // write the output literals
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        OutVar = pCnf->pVarNums[ Aig_ObjFanin0(pObj)->Id ];
+        if ( i < Aig_ManCoNum(p) - nOutputs )
+        {
+            *pClas++ = pLits;
+            *pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj); 
+        }
+        else
+        {
+            PoVar  = pCnf->pVarNums[ pObj->Id ];
+            // first clause
+            *pClas++ = pLits;
+            *pLits++ = 2 * PoVar; 
+            *pLits++ = 2 * OutVar + !Aig_ObjFaninC0(pObj); 
+            // second clause
+            *pClas++ = pLits;
+            *pLits++ = 2 * PoVar + 1; 
+            *pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj); 
+        }
+    }
+
+    // verify that the correct number of literals and clauses was written
+    assert( pLits - pCnf->pClauses[0] == nLiterals );
+    assert( pClas - pCnf->pClauses == nClauses );
+    return pCnf;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Derives a simple CNF for backward retiming computation.]
+
+  Description [The last argument shows the number of last outputs
+  of the manager, which will not be converted into clauses. 
+  New variables will be introduced for these outputs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Cnf_Dat_t * Cnf_DeriveSimpleForRetiming( Aig_Man_t * p )
+{
+    Aig_Obj_t * pObj;
+    Cnf_Dat_t * pCnf;
+    int OutVar, PoVar, pVars[32], * pLits, ** pClas;
+    int i, nLiterals, nClauses, Number;
+
+    // count the number of literals and clauses
+    nLiterals = 1 + 7 * Aig_ManNodeNum(p) + 5 * Aig_ManCoNum(p);
+    nClauses = 1 + 3 * Aig_ManNodeNum(p) + 3 * Aig_ManCoNum(p);
+
+    // allocate CNF
+    pCnf = ABC_ALLOC( Cnf_Dat_t, 1 );
+    memset( pCnf, 0, sizeof(Cnf_Dat_t) );
+    pCnf->pMan = p;
+    pCnf->nLiterals = nLiterals;
+    pCnf->nClauses = nClauses;
+    pCnf->pClauses = ABC_ALLOC( int *, nClauses + 1 );
+    pCnf->pClauses[0] = ABC_ALLOC( int, nLiterals );
+    pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals;
+
+    // create room for variable numbers
+    pCnf->pVarNums = ABC_ALLOC( int, Aig_ManObjNumMax(p) );
+//    memset( pCnf->pVarNums, 0xff, sizeof(int) * Aig_ManObjNumMax(p) );
+    for ( i = 0; i < Aig_ManObjNumMax(p); i++ )
+        pCnf->pVarNums[i] = -1;
+    // assign variables to the last (nOutputs) POs
+    Number = 1;
+    Aig_ManForEachCo( p, pObj, i )
+        pCnf->pVarNums[pObj->Id] = Number++;
+    // assign variables to the internal nodes
+    Aig_ManForEachNode( p, pObj, i )
+        pCnf->pVarNums[pObj->Id] = Number++;
+    // assign variables to the PIs and constant node
+    Aig_ManForEachCi( p, pObj, i )
+        pCnf->pVarNums[pObj->Id] = Number++;
+    pCnf->pVarNums[Aig_ManConst1(p)->Id] = Number++;
+    pCnf->nVars = Number;
+    // assign the clauses
+    pLits = pCnf->pClauses[0];
+    pClas = pCnf->pClauses;
+    Aig_ManForEachNode( p, pObj, i )
+    {
+        OutVar   = pCnf->pVarNums[ pObj->Id ];
+        pVars[0] = pCnf->pVarNums[ Aig_ObjFanin0(pObj)->Id ];
+        pVars[1] = pCnf->pVarNums[ Aig_ObjFanin1(pObj)->Id ];
+
+        // positive phase
+        *pClas++ = pLits;
+        *pLits++ = 2 * OutVar; 
+        *pLits++ = 2 * pVars[0] + !Aig_ObjFaninC0(pObj); 
+        *pLits++ = 2 * pVars[1] + !Aig_ObjFaninC1(pObj); 
+        // negative phase
+        *pClas++ = pLits;
+        *pLits++ = 2 * OutVar + 1; 
+        *pLits++ = 2 * pVars[0] + Aig_ObjFaninC0(pObj); 
+        *pClas++ = pLits;
+        *pLits++ = 2 * OutVar + 1; 
+        *pLits++ = 2 * pVars[1] + Aig_ObjFaninC1(pObj); 
+    }
+ 
+    // write the constant literal
+    OutVar = pCnf->pVarNums[ Aig_ManConst1(p)->Id ];
+    assert( OutVar <= Aig_ManObjNumMax(p) );
+    *pClas++ = pLits;
+    *pLits++ = 2 * OutVar; 
+
+    // write the output literals
+    Aig_ManForEachCo( p, pObj, i )
+    {
+        OutVar = pCnf->pVarNums[ Aig_ObjFanin0(pObj)->Id ];
+        PoVar  = pCnf->pVarNums[ pObj->Id ];
+        // first clause
+        *pClas++ = pLits;
+        *pLits++ = 2 * PoVar; 
+        *pLits++ = 2 * OutVar + !Aig_ObjFaninC0(pObj); 
+        // second clause
+        *pClas++ = pLits;
+        *pLits++ = 2 * PoVar + 1; 
+        *pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj); 
+        // final clause (init-state is always 0 -> set the output to 0)
+        *pClas++ = pLits;
+        *pLits++ = 2 * PoVar + 1; 
+    }
+
+    // verify that the correct number of literals and clauses was written
+    assert( pLits - pCnf->pClauses[0] == nLiterals );
+    assert( pClas - pCnf->pClauses == nClauses );
+    return pCnf;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/cnf/cnf_.c b/abc-build/src/sat/cnf/cnf_.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/cnf/cnf_.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+  FileName    [cnf_.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [AIG-to-CNF conversion.]
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - April 28, 2007.]
+
+  Revision    [$Id: cnf_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cnf.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/cnf/module.make b/abc-build/src/sat/cnf/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/cnf/module.make
@@ -0,0 +1,9 @@
+SRC +=	src/sat/cnf/cnfCore.c \
+	src/sat/cnf/cnfCut.c \
+	src/sat/cnf/cnfData.c \
+	src/sat/cnf/cnfFast.c \
+	src/sat/cnf/cnfMan.c \
+	src/sat/cnf/cnfMap.c \
+	src/sat/cnf/cnfPost.c \
+	src/sat/cnf/cnfUtil.c \
+	src/sat/cnf/cnfWrite.c 
diff --git a/abc-build/src/sat/csat/csat_apis.c b/abc-build/src/sat/csat/csat_apis.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/csat/csat_apis.c
@@ -0,0 +1,778 @@
+/**CFile****************************************************************
+
+  FileName    [csat_apis.h]
+
+  PackageName [Interface to CSAT.]
+
+  Synopsis    [APIs, enums, and data structures expected from the use of CSAT.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 28, 2005]
+
+  Revision    [$Id: csat_apis.h,v 1.00 2005/08/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "base/abc/abc.h"
+#include "proof/fraig/fraig.h"
+#include "csat_apis.h"
+#include "misc/st/stmm.h"
+#include "base/main/main.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+#define ABC_DEFAULT_CONF_LIMIT     0   // limit on conflicts
+#define ABC_DEFAULT_IMP_LIMIT      0   // limit on implications
+
+
+struct ABC_ManagerStruct_t
+{
+    // information about the problem
+    stmm_table *          tName2Node;    // the hash table mapping names to nodes
+    stmm_table *          tNode2Name;    // the hash table mapping nodes to names
+    Abc_Ntk_t *           pNtk;          // the starting ABC network
+    Abc_Ntk_t *           pTarget;       // the AIG representing the target
+    char *                pDumpFileName; // the name of the file to dump the target network
+    Mem_Flex_t *      pMmNames;      // memory manager for signal names
+    // solving parameters
+    int                   mode;          // 0 = resource-aware integration; 1 = brute-force SAT
+    Prove_Params_t        Params;        // integrated CEC parameters
+    // information about the target 
+    int                   nog;           // the numbers of gates in the target
+    Vec_Ptr_t *           vNodes;        // the gates in the target
+    Vec_Int_t *           vValues;       // the values of gate's outputs in the target
+    // solution
+    CSAT_Target_ResultT * pResult;       // the result of solving the target
+};
+
+static CSAT_Target_ResultT * ABC_TargetResAlloc( int nVars );
+static char * ABC_GetNodeName( ABC_Manager mng, Abc_Obj_t * pNode );
+
+// procedures to start and stop the ABC framework
+extern void  Abc_Start();
+extern void  Abc_Stop();
+
+// some external procedures
+extern int Io_WriteBench( Abc_Ntk_t * pNtk, const char * FileName );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+ABC_Manager ABC_InitManager()
+{
+    ABC_Manager_t * mng;
+    Abc_Start();
+    mng = ABC_ALLOC( ABC_Manager_t, 1 );
+    memset( mng, 0, sizeof(ABC_Manager_t) );
+    mng->pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+    mng->pNtk->pName = Extra_UtilStrsav("csat_network");
+    mng->tName2Node = stmm_init_table(strcmp, stmm_strhash);
+    mng->tNode2Name = stmm_init_table(stmm_ptrcmp, stmm_ptrhash);
+    mng->pMmNames   = Mem_FlexStart();
+    mng->vNodes     = Vec_PtrAlloc( 100 );
+    mng->vValues    = Vec_IntAlloc( 100 );
+    mng->mode       = 0; // set "resource-aware integration" as the default mode
+    // set default parameters for CEC
+    Prove_ParamsSetDefault( &mng->Params );
+    // set infinite resource limit for the final mitering
+//    mng->Params.nMiteringLimitLast = ABC_INFINITY;
+    return mng;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deletes the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void ABC_ReleaseManager( ABC_Manager mng )
+{
+    CSAT_Target_ResultT * p_res = ABC_Get_Target_Result( mng,0 );
+    ABC_TargetResFree(p_res);
+    if ( mng->tNode2Name ) stmm_free_table( mng->tNode2Name );
+    if ( mng->tName2Node ) stmm_free_table( mng->tName2Node );
+    if ( mng->pMmNames )   Mem_FlexStop( mng->pMmNames, 0 );
+    if ( mng->pNtk )       Abc_NtkDelete( mng->pNtk );
+    if ( mng->pTarget )    Abc_NtkDelete( mng->pTarget );
+    if ( mng->vNodes )     Vec_PtrFree( mng->vNodes );
+    if ( mng->vValues )    Vec_IntFree( mng->vValues );
+    ABC_FREE( mng->pDumpFileName );
+    ABC_FREE( mng );
+    Abc_Stop();
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets solver options for learning.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void ABC_SetSolveOption( ABC_Manager mng, enum CSAT_OptionT option )
+{
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets solving mode by brute-force SAT.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void ABC_UseOnlyCoreSatSolver( ABC_Manager mng )
+{
+    mng->mode = 1;  // switch to "brute-force SAT" as the solving option
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds a gate to the circuit.]
+
+  Description [The meaning of the parameters are:
+    type: the type of the gate to be added
+    name: the name of the gate to be added, name should be unique in a circuit.
+    nofi: number of fanins of the gate to be added;
+    fanins: the name array of fanins of the gate to be added.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int ABC_AddGate( ABC_Manager mng, enum GateType type, char * name, int nofi, char ** fanins, int dc_attr )
+{
+    Abc_Obj_t * pObj = NULL; // Suppress "might be used uninitialized"
+    Abc_Obj_t * pFanin;
+    char * pSop = NULL; // Suppress "might be used uninitialized"
+    char * pNewName;
+    int i;
+
+    // save the name in the local memory manager
+    pNewName = Mem_FlexEntryFetch( mng->pMmNames, strlen(name) + 1 );
+    strcpy( pNewName, name );
+    name = pNewName;
+
+    // consider different cases, create the node, and map the node into the name
+    switch( type )
+    {
+    case CSAT_BPI:
+    case CSAT_BPPI:
+        if ( nofi != 0 )
+            { printf( "ABC_AddGate: The PI/PPI gate \"%s\" has fanins.\n", name ); return 0; }
+        // create the PI
+        pObj = Abc_NtkCreatePi( mng->pNtk );
+        stmm_insert( mng->tNode2Name, (char *)pObj, name );
+        break;
+    case CSAT_CONST:
+    case CSAT_BAND:
+    case CSAT_BNAND:
+    case CSAT_BOR:
+    case CSAT_BNOR:
+    case CSAT_BXOR:
+    case CSAT_BXNOR:
+    case CSAT_BINV:
+    case CSAT_BBUF:
+        // create the node
+        pObj = Abc_NtkCreateNode( mng->pNtk );
+        // create the fanins
+        for ( i = 0; i < nofi; i++ )
+        {
+            if ( !stmm_lookup( mng->tName2Node, fanins[i], (char **)&pFanin ) )
+                { printf( "ABC_AddGate: The fanin gate \"%s\" is not in the network.\n", fanins[i] ); return 0; }
+            Abc_ObjAddFanin( pObj, pFanin );
+        }
+        // create the node function
+        switch( type )
+        {
+            case CSAT_CONST:
+                if ( nofi != 0 )
+                    { printf( "ABC_AddGate: The constant gate \"%s\" has fanins.\n", name ); return 0; }
+                pSop = Abc_SopCreateConst1( (Mem_Flex_t *)mng->pNtk->pManFunc );
+                break;
+            case CSAT_BAND:
+                if ( nofi < 1 )
+                    { printf( "ABC_AddGate: The AND gate \"%s\" no fanins.\n", name ); return 0; }
+                pSop = Abc_SopCreateAnd( (Mem_Flex_t *)mng->pNtk->pManFunc, nofi, NULL );
+                break;
+            case CSAT_BNAND:
+                if ( nofi < 1 )
+                    { printf( "ABC_AddGate: The NAND gate \"%s\" no fanins.\n", name ); return 0; }
+                pSop = Abc_SopCreateNand( (Mem_Flex_t *)mng->pNtk->pManFunc, nofi );
+                break;
+            case CSAT_BOR:
+                if ( nofi < 1 )
+                    { printf( "ABC_AddGate: The OR gate \"%s\" no fanins.\n", name ); return 0; }
+                pSop = Abc_SopCreateOr( (Mem_Flex_t *)mng->pNtk->pManFunc, nofi, NULL );
+                break;
+            case CSAT_BNOR:
+                if ( nofi < 1 )
+                    { printf( "ABC_AddGate: The NOR gate \"%s\" no fanins.\n", name ); return 0; }
+                pSop = Abc_SopCreateNor( (Mem_Flex_t *)mng->pNtk->pManFunc, nofi );
+                break;
+            case CSAT_BXOR:
+                if ( nofi < 1 )
+                    { printf( "ABC_AddGate: The XOR gate \"%s\" no fanins.\n", name ); return 0; }
+                if ( nofi > 2 )
+                    { printf( "ABC_AddGate: The XOR gate \"%s\" has more than two fanins.\n", name ); return 0; }
+                pSop = Abc_SopCreateXor( (Mem_Flex_t *)mng->pNtk->pManFunc, nofi );
+                break;
+            case CSAT_BXNOR:
+                if ( nofi < 1 )
+                    { printf( "ABC_AddGate: The XNOR gate \"%s\" no fanins.\n", name ); return 0; }
+                if ( nofi > 2 )
+                    { printf( "ABC_AddGate: The XNOR gate \"%s\" has more than two fanins.\n", name ); return 0; }
+                pSop = Abc_SopCreateNxor( (Mem_Flex_t *)mng->pNtk->pManFunc, nofi );
+                break;
+            case CSAT_BINV:
+                if ( nofi != 1 )
+                    { printf( "ABC_AddGate: The inverter gate \"%s\" does not have exactly one fanin.\n", name ); return 0; }
+                pSop = Abc_SopCreateInv( (Mem_Flex_t *)mng->pNtk->pManFunc );
+                break;
+            case CSAT_BBUF:
+                if ( nofi != 1 )
+                    { printf( "ABC_AddGate: The buffer gate \"%s\" does not have exactly one fanin.\n", name ); return 0; }
+                pSop = Abc_SopCreateBuf( (Mem_Flex_t *)mng->pNtk->pManFunc );
+                break;
+            default :
+                break;
+        }
+        Abc_ObjSetData( pObj, pSop );
+        break;
+    case CSAT_BPPO:
+    case CSAT_BPO:
+        if ( nofi != 1 )
+            { printf( "ABC_AddGate: The PO/PPO gate \"%s\" does not have exactly one fanin.\n", name ); return 0; }
+        // create the PO
+        pObj = Abc_NtkCreatePo( mng->pNtk );
+        stmm_insert( mng->tNode2Name, (char *)pObj, name );
+        // connect to the PO fanin
+        if ( !stmm_lookup( mng->tName2Node, fanins[0], (char **)&pFanin ) )
+            { printf( "ABC_AddGate: The fanin gate \"%s\" is not in the network.\n", fanins[0] ); return 0; }
+        Abc_ObjAddFanin( pObj, pFanin );
+        break;
+    default:
+        printf( "ABC_AddGate: Unknown gate type.\n" );
+        break;
+    }
+
+    // map the name into the node
+    if ( stmm_insert( mng->tName2Node, name, (char *)pObj ) )
+        { printf( "ABC_AddGate: The same gate \"%s\" is added twice.\n", name ); return 0; }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [This procedure also finalizes construction of the ABC network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void ABC_Network_Finalize( ABC_Manager mng )
+{
+    Abc_Ntk_t * pNtk = mng->pNtk;
+    Abc_Obj_t * pObj;
+    int i;
+    Abc_NtkForEachPi( pNtk, pObj, i )
+        Abc_ObjAssignName( pObj, ABC_GetNodeName(mng, pObj), NULL );
+    Abc_NtkForEachPo( pNtk, pObj, i )
+        Abc_ObjAssignName( pObj, ABC_GetNodeName(mng, pObj), NULL );
+    assert( Abc_NtkLatchNum(pNtk) == 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks integraty of the manager.]
+
+  Description [Checks if there are gates that are not used by any primary output.
+  If no such gates exist, return 1 else return 0.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int ABC_Check_Integrity( ABC_Manager mng )
+{
+    Abc_Ntk_t * pNtk = mng->pNtk;
+    Abc_Obj_t * pObj;
+    int i;
+
+    // check that there are no dangling nodes
+    Abc_NtkForEachNode( pNtk, pObj, i )
+    {
+        if ( i == 0 ) 
+            continue;
+        if ( Abc_ObjFanoutNum(pObj) == 0 )
+        {
+//            printf( "ABC_Check_Integrity: The network has dangling nodes.\n" );
+            return 0;
+        }
+    }
+
+    // make sure everything is okay with the network structure
+    if ( !Abc_NtkDoCheck( pNtk ) )
+    {
+        printf( "ABC_Check_Integrity: The internal network check has failed.\n" );
+        return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets time limit for solving a target.]
+
+  Description [Runtime: time limit (in second).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void ABC_SetTimeLimit( ABC_Manager mng, int runtime )
+{
+//    printf( "ABC_SetTimeLimit: The resource limit is not implemented (warning).\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void ABC_SetLearnLimit( ABC_Manager mng, int num )
+{
+//    printf( "ABC_SetLearnLimit: The resource limit is not implemented (warning).\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void ABC_SetLearnBacktrackLimit( ABC_Manager mng, int num )
+{
+//    printf( "ABC_SetLearnBacktrackLimit: The resource limit is not implemented (warning).\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void ABC_SetSolveBacktrackLimit( ABC_Manager mng, int num )
+{
+    mng->Params.nMiteringLimitLast = num;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void ABC_SetSolveImplicationLimit( ABC_Manager mng, int num )
+{
+//    printf( "ABC_SetSolveImplicationLimit: The resource limit is not implemented (warning).\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void ABC_SetTotalBacktrackLimit( ABC_Manager mng, ABC_UINT64_T num )
+{
+    mng->Params.nTotalBacktrackLimit = num;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void ABC_SetTotalInspectLimit( ABC_Manager mng, ABC_UINT64_T num )
+{
+    mng->Params.nTotalInspectLimit = num;
+}
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+ABC_UINT64_T ABC_GetTotalBacktracksMade( ABC_Manager mng )
+{
+    return mng->Params.nTotalBacktracksMade;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+ABC_UINT64_T ABC_GetTotalInspectsMade( ABC_Manager mng )
+{
+    return mng->Params.nTotalInspectsMade;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the file name to dump the structurally hashed network used for solving.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void ABC_EnableDump( ABC_Manager mng, char * dump_file )
+{
+    ABC_FREE( mng->pDumpFileName );
+    mng->pDumpFileName = Extra_UtilStrsav( dump_file );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds a new target to the manager.]
+
+  Description [The meaning of the parameters are:
+    nog: number of gates that are in the targets,
+    names: name array of gates,
+    values: value array of the corresponding gates given in "names" to be solved. 
+    The relation of them is AND.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int ABC_AddTarget( ABC_Manager mng, int nog, char ** names, int * values )
+{
+    Abc_Obj_t * pObj;
+    int i;
+    if ( nog < 1 )
+        { printf( "ABC_AddTarget: The target has no gates.\n" ); return 0; }
+    // clear storage for the target
+    mng->nog = 0;
+    Vec_PtrClear( mng->vNodes );
+    Vec_IntClear( mng->vValues );
+    // save the target
+    for ( i = 0; i < nog; i++ )
+    {
+        if ( !stmm_lookup( mng->tName2Node, names[i], (char **)&pObj ) )
+            { printf( "ABC_AddTarget: The target gate \"%s\" is not in the network.\n", names[i] ); return 0; }
+        Vec_PtrPush( mng->vNodes, pObj );
+        if ( values[i] < 0 || values[i] > 1 )
+            { printf( "ABC_AddTarget: The value of gate \"%s\" is not 0 or 1.\n", names[i] ); return 0; }
+        Vec_IntPush( mng->vValues, values[i] );
+    }
+    mng->nog = nog;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Initialize the solver internal data structure.]
+
+  Description [Prepares the solver to work on one specific target
+  set by calling ABC_AddTarget before.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void ABC_SolveInit( ABC_Manager mng )
+{
+    // check if the target is available
+    assert( mng->nog == Vec_PtrSize(mng->vNodes) );
+    if ( mng->nog == 0 )
+        { printf( "ABC_SolveInit: Target is not specified by ABC_AddTarget().\n" ); return; }
+
+    // free the previous target network if present
+    if ( mng->pTarget ) Abc_NtkDelete( mng->pTarget );
+
+    // set the new target network
+//    mng->pTarget = Abc_NtkCreateTarget( mng->pNtk, mng->vNodes, mng->vValues );
+    mng->pTarget = Abc_NtkStrash( mng->pNtk, 0, 1, 0 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Currently not implemented.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void ABC_AnalyzeTargets( ABC_Manager mng )
+{
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Solves the targets added by ABC_AddTarget().]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+enum CSAT_StatusT ABC_Solve( ABC_Manager mng )
+{
+    Prove_Params_t * pParams = &mng->Params;
+    int RetValue, i;
+
+    // check if the target network is available
+    if ( mng->pTarget == NULL )
+        { printf( "ABC_Solve: Target network is not derived by ABC_SolveInit().\n" ); return UNDETERMINED; }
+
+    // try to prove the miter using a number of techniques
+    if ( mng->mode )
+        RetValue = Abc_NtkMiterSat( mng->pTarget, (ABC_INT64_T)pParams->nMiteringLimitLast, (ABC_INT64_T)0, 0, NULL, NULL );
+    else
+//        RetValue = Abc_NtkMiterProve( &mng->pTarget, pParams ); // old CEC engine
+        RetValue = Abc_NtkIvyProve( &mng->pTarget, pParams ); // new CEC engine
+
+    // analyze the result
+    mng->pResult = ABC_TargetResAlloc( Abc_NtkCiNum(mng->pTarget) );
+    if ( RetValue == -1 )
+        mng->pResult->status = UNDETERMINED;
+    else if ( RetValue == 1 )
+        mng->pResult->status = UNSATISFIABLE;
+    else if ( RetValue == 0 )
+    {
+        mng->pResult->status = SATISFIABLE;
+        // create the array of PI names and values
+        for ( i = 0; i < mng->pResult->no_sig; i++ )
+        {
+            mng->pResult->names[i]  = Extra_UtilStrsav( ABC_GetNodeName(mng, Abc_NtkCi(mng->pNtk, i)) ); 
+            mng->pResult->values[i] = mng->pTarget->pModel[i];
+        }
+        ABC_FREE( mng->pTarget->pModel );
+    }
+    else assert( 0 );
+
+    // delete the target
+    Abc_NtkDelete( mng->pTarget );
+    mng->pTarget = NULL;
+    // return the status
+    return mng->pResult->status;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Gets the solve status of a target.]
+
+  Description [TargetID: the target id returned by ABC_AddTarget().]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+CSAT_Target_ResultT * ABC_Get_Target_Result( ABC_Manager mng, int TargetID )
+{
+    return mng->pResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dumps the original network into the BENCH file.]
+
+  Description [This procedure should be modified to dump the target.]
+               
+  SideEffects []
+
+  SeeAlso     [] 
+
+***********************************************************************/
+void ABC_Dump_Bench_File( ABC_Manager mng )
+{
+    Abc_Ntk_t * pNtkTemp, * pNtkAig;
+    const char * pFileName;
+ 
+    // derive the netlist
+    pNtkAig = Abc_NtkStrash( mng->pNtk, 0, 0, 0 );
+    pNtkTemp = Abc_NtkToNetlistBench( pNtkAig );
+    Abc_NtkDelete( pNtkAig );
+    if ( pNtkTemp == NULL ) 
+        { printf( "ABC_Dump_Bench_File: Dumping BENCH has failed.\n" ); return; }
+    pFileName = mng->pDumpFileName? mng->pDumpFileName: "abc_test.bench";
+    Io_WriteBench( pNtkTemp, pFileName );
+    Abc_NtkDelete( pNtkTemp );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the target result.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+CSAT_Target_ResultT * ABC_TargetResAlloc( int nVars )
+{
+    CSAT_Target_ResultT * p;
+    p = ABC_ALLOC( CSAT_Target_ResultT, 1 );
+    memset( p, 0, sizeof(CSAT_Target_ResultT) );
+    p->no_sig = nVars;
+    p->names = ABC_ALLOC( char *, nVars );
+    p->values = ABC_ALLOC( int, nVars );
+    memset( p->names, 0, sizeof(char *) * nVars );
+    memset( p->values, 0, sizeof(int) * nVars );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the target result.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void ABC_TargetResFree( CSAT_Target_ResultT * p )
+{
+    if ( p == NULL )
+        return;
+    if( p->names )
+    {
+        int i = 0;
+        for ( i = 0; i < p->no_sig; i++ )
+        {
+            ABC_FREE(p->names[i]);
+        }
+    }
+    ABC_FREE( p->names );
+    ABC_FREE( p->values );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dumps the target AIG into the BENCH file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * ABC_GetNodeName( ABC_Manager mng, Abc_Obj_t * pNode )
+{
+    char * pName = NULL;
+    if ( !stmm_lookup( mng->tNode2Name, (char *)pNode, (char **)&pName ) )
+    {
+        assert( 0 );
+    }
+    return pName;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/csat/csat_apis.h b/abc-build/src/sat/csat/csat_apis.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/csat/csat_apis.h
@@ -0,0 +1,226 @@
+/**CFile****************************************************************
+
+  FileName    [csat_apis.h]
+
+  PackageName [Interface to CSAT.]
+
+  Synopsis    [APIs, enums, and data structures expected from the use of CSAT.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - August 28, 2005]
+
+  Revision    [$Id: csat_apis.h,v 1.5 2005/12/30 10:54:40 rmukherj Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__sat__csat__csat_apis_h
+#define ABC__sat__csat__csat_apis_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+
+typedef struct ABC_ManagerStruct_t     ABC_Manager_t;
+typedef struct ABC_ManagerStruct_t *   ABC_Manager;
+
+
+// GateType defines the gate type that can be added to circuit by
+// ABC_AddGate();
+#ifndef _ABC_GATE_TYPE_
+#define _ABC_GATE_TYPE_
+enum GateType
+{
+    CSAT_CONST = 0,  // constant gate
+    CSAT_BPI,    // boolean PI
+    CSAT_BPPI,   // bit level PSEUDO PRIMARY INPUT
+    CSAT_BAND,   // bit level AND
+    CSAT_BNAND,  // bit level NAND
+    CSAT_BOR,    // bit level OR
+    CSAT_BNOR,   // bit level NOR
+    CSAT_BXOR,   // bit level XOR
+    CSAT_BXNOR,  // bit level XNOR
+    CSAT_BINV,   // bit level INVERTER
+    CSAT_BBUF,   // bit level BUFFER
+    CSAT_BMUX,   // bit level MUX --not supported 
+    CSAT_BDFF,   // bit level D-type FF
+    CSAT_BSDFF,  // bit level scan FF --not supported 
+    CSAT_BTRIH,  // bit level TRISTATE gate with active high control --not supported 
+    CSAT_BTRIL,  // bit level TRISTATE gate with active low control --not supported 
+    CSAT_BBUS,   // bit level BUS --not supported 
+    CSAT_BPPO,   // bit level PSEUDO PRIMARY OUTPUT
+    CSAT_BPO,    // boolean PO
+    CSAT_BCNF,   // boolean constraint
+    CSAT_BDC,    // boolean don't care gate (2 input)
+};
+#endif
+
+
+//CSAT_StatusT defines the return value by ABC_Solve();
+#ifndef _ABC_STATUS_
+#define _ABC_STATUS_
+enum CSAT_StatusT 
+{
+    UNDETERMINED = 0,
+    UNSATISFIABLE,
+    SATISFIABLE,
+    TIME_OUT,
+    FRAME_OUT,
+    NO_TARGET,
+    ABORTED,
+    SEQ_SATISFIABLE     
+};
+#endif
+
+
+// to identify who called the CSAT solver
+#ifndef _ABC_CALLER_
+#define _ABC_CALLER_
+enum CSAT_CallerT
+{
+    BLS = 0,
+    SATORI,
+    NONE
+};
+#endif
+
+
+// CSAT_OptionT defines the solver option about learning
+// which is used by ABC_SetSolveOption();
+#ifndef _ABC_OPTION_
+#define _ABC_OPTION_
+enum CSAT_OptionT
+{
+    BASE_LINE = 0,
+    IMPLICT_LEARNING, //default
+    EXPLICT_LEARNING
+};
+#endif
+
+
+#ifndef _ABC_Target_Result
+#define _ABC_Target_Result
+typedef struct _CSAT_Target_ResultT CSAT_Target_ResultT;
+struct _CSAT_Target_ResultT
+{
+    enum CSAT_StatusT status; // solve status of the target
+    int num_dec;              // num of decisions to solve the target
+    int num_imp;              // num of implications to solve the target
+    int num_cftg;             // num of conflict gates learned 
+    int num_cfts;             // num of conflict signals in conflict gates
+    double time;              // time(in second) used to solve the target
+    int no_sig;               // if "status" is SATISFIABLE, "no_sig" is the number of 
+                              // primary inputs, if the "status" is TIME_OUT, "no_sig" is the
+                              // number of constant signals found.
+    char** names;             // if the "status" is SATISFIABLE, "names" is the name array of
+                              // primary inputs, "values" is the value array of primary 
+                              // inputs that satisfy the target. 
+                              // if the "status" is TIME_OUT, "names" is the name array of
+                              // constant signals found (signals at the root of decision 
+                              // tree), "values" is the value array of constant signals found.
+    int* values;
+};
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+// create a new manager
+extern ABC_Manager          ABC_InitManager(void);
+
+// release a manager
+extern void ABC_ReleaseManager(ABC_Manager mng);
+
+// set solver options for learning
+extern void                  ABC_SetSolveOption(ABC_Manager mng, enum CSAT_OptionT option);
+
+// enable checking by brute-force SAT solver (MiniSat-1.14)
+extern void                  ABC_UseOnlyCoreSatSolver(ABC_Manager mng);
+
+
+// add a gate to the circuit
+// the meaning of the parameters are:
+// type: the type of the gate to be added
+// name: the name of the gate to be added, name should be unique in a circuit.
+// nofi: number of fanins of the gate to be added;
+// fanins: the name array of fanins of the gate to be added
+extern int                   ABC_AddGate(ABC_Manager mng,
+					 enum GateType type,
+					 char* name,
+					 int nofi,
+					 char** fanins,
+					 int dc_attr);
+
+// check if there are gates that are not used by any primary ouput.
+// if no such gates exist, return 1 else return 0;
+extern int                   ABC_Check_Integrity(ABC_Manager mng);
+
+// THIS PROCEDURE SHOULD BE CALLED AFTER THE NETWORK IS CONSTRUCTED!!!
+extern void                  ABC_Network_Finalize( ABC_Manager mng );
+
+// set time limit for solving a target.
+// runtime: time limit (in second).
+extern void                  ABC_SetTimeLimit(ABC_Manager mng, int runtime);
+extern void                  ABC_SetLearnLimit(ABC_Manager mng, int num);
+extern void                  ABC_SetSolveBacktrackLimit(ABC_Manager mng, int num);
+extern void                  ABC_SetLearnBacktrackLimit(ABC_Manager mng, int num);
+extern void                  ABC_EnableDump(ABC_Manager mng, char* dump_file);
+
+extern void                  ABC_SetTotalBacktrackLimit( ABC_Manager mng, ABC_UINT64_T num );
+extern void                  ABC_SetTotalInspectLimit( ABC_Manager mng, ABC_UINT64_T num );
+extern ABC_UINT64_T         ABC_GetTotalBacktracksMade( ABC_Manager mng );
+extern ABC_UINT64_T         ABC_GetTotalInspectsMade( ABC_Manager mng );
+
+// the meaning of the parameters are:
+// nog: number of gates that are in the targets
+// names: name array of gates
+// values: value array of the corresponding gates given in "names" to be
+// solved. the relation of them is AND.
+extern int                   ABC_AddTarget(ABC_Manager mng, int nog, char**names, int* values);
+
+// initialize the solver internal data structure.
+extern void                  ABC_SolveInit(ABC_Manager mng);
+extern void                  ABC_AnalyzeTargets(ABC_Manager mng);
+
+// solve the targets added by ABC_AddTarget()
+extern enum CSAT_StatusT     ABC_Solve(ABC_Manager mng);
+
+// get the solve status of a target
+// TargetID: the target id returned by  ABC_AddTarget().
+extern CSAT_Target_ResultT * ABC_Get_Target_Result(ABC_Manager mng, int TargetID);
+extern void                  ABC_Dump_Bench_File(ABC_Manager mng);
+
+// ADDED PROCEDURES:
+extern void                  ABC_TargetResFree( CSAT_Target_ResultT * p );
+
+extern void CSAT_SetCaller(ABC_Manager mng, enum CSAT_CallerT caller);
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/sat/csat/module.make b/abc-build/src/sat/csat/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/csat/module.make
@@ -0,0 +1,1 @@
+SRC +=  src/sat/csat/csat_apis.c
diff --git a/abc-build/src/sat/lsat/solver.h b/abc-build/src/sat/lsat/solver.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/lsat/solver.h
@@ -0,0 +1,132 @@
+/****************************************************************************************[solver.h]
+Copyright (c) 2008, Niklas Sorensson
+              2008, Koen Claessen
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef ABC__sat__lsat__solver_h
+#define ABC__sat__lsat__solver_h
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+// SolverTypes:
+//
+typedef struct solver_t solver;
+typedef int solver_Var;
+typedef int solver_Lit;
+typedef int solver_lbool;
+
+// Constants: (can these be made inline-able?)
+//
+
+extern const solver_lbool solver_l_True;
+extern const solver_lbool solver_l_False;
+extern const solver_lbool solver_l_Undef;
+
+
+solver*      solver_new             (void);
+void         solver_delete          (solver* s);
+             
+solver_Var   solver_newVar          (solver *s);
+solver_Lit   solver_newLit          (solver *s);
+             
+solver_Lit   solver_mkLit           (solver_Var x);
+solver_Lit   solver_mkLit_args      (solver_Var x, int sign);
+solver_Lit   solver_negate          (solver_Lit p);
+                                    
+solver_Var   solver_var             (solver_Lit p);
+int          solver_sign            (solver_Lit p);
+             
+int          solver_addClause       (solver *s, int len, solver_Lit *ps);
+void         solver_addClause_begin (solver *s);
+void         solver_addClause_addLit(solver *s, solver_Lit p);
+int          solver_addClause_commit(solver *s);
+             
+int          solver_simplify        (solver *s);
+             
+int          solver_solve           (solver *s, int len, solver_Lit *ps);
+void         solver_solve_begin     (solver *s);
+void         solver_solve_addLit    (solver *s, solver_Lit p);
+int          solver_solve_commit    (solver *s);
+             
+int          solver_okay            (solver *s);
+             
+void         solver_setPolarity     (solver *s, solver_Var v, int b);
+void         solver_setDecisionVar  (solver *s, solver_Var v, int b);
+
+solver_lbool solver_get_l_True      (void);
+solver_lbool solver_get_l_False     (void);
+solver_lbool solver_get_l_Undef     (void);
+
+solver_lbool solver_value_Var       (solver *s, solver_Var x);
+solver_lbool solver_value_Lit       (solver *s, solver_Lit p);
+
+solver_lbool solver_modelValue_Var  (solver *s, solver_Var x);
+solver_lbool solver_modelValue_Lit  (solver *s, solver_Lit p);
+
+int          solver_num_assigns     (solver *s);
+int          solver_num_clauses     (solver *s);     
+int          solver_num_learnts     (solver *s);     
+int          solver_num_vars        (solver *s);  
+int          solver_num_freeVars    (solver *s);
+
+int          solver_conflict_len    (solver *s);
+solver_Lit   solver_conflict_nthLit (solver *s, int i);
+
+// Setters:
+
+void         solver_set_verbosity   (solver *s, int v);
+
+// Getters:
+
+int          solver_num_conflicts   (solver *s);
+
+/* TODO
+
+    // Mode of operation:
+    //
+    int       verbosity;
+    double    var_decay;
+    double    clause_decay;
+    double    random_var_freq;
+    double    random_seed;
+    double    restart_luby_start; // The factor with which the values of the luby sequence is multiplied to get the restart    (default 100)
+    double    restart_luby_inc;   // The constant that the luby sequence uses powers of                                        (default 2)
+    int       expensive_ccmin;    // FIXME: describe.
+    int       rnd_pol;            // FIXME: describe.
+
+    int       restart_first;      // The initial restart limit.                                                                (default 100)
+    double    restart_inc;        // The factor with which the restart limit is multiplied in each restart.                    (default 1.5)
+    double    learntsize_factor;  // The intitial limit for learnt clauses is a factor of the original clauses.                (default 1 / 3)
+    double    learntsize_inc;     // The limit for learnt clauses is multiplied with this factor each restart.                 (default 1.1)
+
+    int       learntsize_adjust_start_confl;
+    double    learntsize_adjust_inc;
+
+    // Statistics: (read-only member variable)
+    //
+    uint64_t starts, decisions, rnd_decisions, propagations, conflicts;
+    uint64_t dec_vars, clauses_literals, learnts_literals, max_literals, tot_literals;
+*/
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/sat/msat/module.make b/abc-build/src/sat/msat/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/msat/module.make
@@ -0,0 +1,13 @@
+SRC +=  src/sat/msat/msatActivity.c \
+	src/sat/msat/msatClause.c \
+	src/sat/msat/msatClauseVec.c \
+	src/sat/msat/msatMem.c \
+	src/sat/msat/msatOrderH.c \
+	src/sat/msat/msatQueue.c \
+	src/sat/msat/msatRead.c \
+	src/sat/msat/msatSolverApi.c \
+	src/sat/msat/msatSolverCore.c \
+	src/sat/msat/msatSolverIo.c \
+	src/sat/msat/msatSolverSearch.c \
+	src/sat/msat/msatSort.c \
+	src/sat/msat/msatVec.c
diff --git a/abc-build/src/sat/msat/msat.h b/abc-build/src/sat/msat/msat.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/msat/msat.h
@@ -0,0 +1,168 @@
+/**CFile****************************************************************
+
+  FileName    [msat.h]
+
+  PackageName [A C version of SAT solver MINISAT, originally developed 
+  in C++ by Niklas Een and Niklas Sorensson, Chalmers University of 
+  Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.]
+
+  Synopsis    [External definitions of the solver.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: msat.h,v 1.6 2004/05/12 06:30:20 satrajit Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__sat__msat__msat_h
+#define ABC__sat__msat__msat_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Msat_Solver_t_      Msat_Solver_t;
+
+// the vector of intergers and of clauses
+typedef struct Msat_IntVec_t_      Msat_IntVec_t;
+typedef struct Msat_ClauseVec_t_   Msat_ClauseVec_t;
+typedef struct Msat_VarHeap_t_     Msat_VarHeap_t;
+
+// the return value of the solver
+typedef enum { MSAT_FALSE = -1, MSAT_UNKNOWN = 0, MSAT_TRUE = 1 } Msat_Type_t;
+
+// representation of variables and literals
+// the literal (l) is the variable (v) and the sign (s)
+// s = 0 the variable is positive
+// s = 1 the variable is negative
+#define MSAT_VAR2LIT(v,s) (2*(v)+(s)) 
+#define MSAT_LITNOT(l)    ((l)^1)
+#define MSAT_LITSIGN(l)   ((l)&1)     
+#define MSAT_LIT2VAR(l)   ((l)>>1)
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DECLARATIONS                        ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== satRead.c ============================================================*/
+extern int              Msat_SolverParseDimacs( FILE * pFile, Msat_Solver_t ** p, int fVerbose );
+/*=== satSolver.c ===========================================================*/
+// adding vars, clauses, simplifying the database, and solving
+extern int              Msat_SolverAddVar( Msat_Solver_t * p, int Level );
+extern int              Msat_SolverAddClause( Msat_Solver_t * p, Msat_IntVec_t * pLits );
+extern int              Msat_SolverSimplifyDB( Msat_Solver_t * p );
+extern int              Msat_SolverSolve( Msat_Solver_t * p, Msat_IntVec_t * pVecAssumps, int nBackTrackLimit, int nTimeLimit );
+// printing stats, assignments, and clauses
+extern void             Msat_SolverPrintStats( Msat_Solver_t * p );
+extern void             Msat_SolverPrintAssignment( Msat_Solver_t * p );
+extern void             Msat_SolverPrintClauses( Msat_Solver_t * p );
+extern void             Msat_SolverWriteDimacs( Msat_Solver_t * p, char * pFileName );
+// access to the solver internal data
+extern int              Msat_SolverReadVarNum( Msat_Solver_t * p );
+extern int              Msat_SolverReadClauseNum( Msat_Solver_t * p );
+extern int              Msat_SolverReadVarAllocNum( Msat_Solver_t * p );
+extern int *            Msat_SolverReadAssignsArray( Msat_Solver_t * p );
+extern int *            Msat_SolverReadModelArray( Msat_Solver_t * p );
+extern unsigned         Msat_SolverReadTruth( Msat_Solver_t * p );
+extern int              Msat_SolverReadBackTracks( Msat_Solver_t * p );
+extern int              Msat_SolverReadInspects( Msat_Solver_t * p );
+extern void             Msat_SolverSetVerbosity( Msat_Solver_t * p, int fVerbose );
+extern void             Msat_SolverSetProofWriting( Msat_Solver_t * p, int fProof );
+extern void             Msat_SolverSetVarTypeA( Msat_Solver_t * p, int Var );
+extern void             Msat_SolverSetVarMap( Msat_Solver_t * p, Msat_IntVec_t * vVarMap );
+extern void             Msat_SolverMarkLastClauseTypeA( Msat_Solver_t * p );
+extern void             Msat_SolverMarkClausesStart( Msat_Solver_t * p );
+extern float *          Msat_SolverReadFactors( Msat_Solver_t * p );
+// returns the solution after incremental solving
+extern int              Msat_SolverReadSolutions( Msat_Solver_t * p );
+extern int *            Msat_SolverReadSolutionsArray( Msat_Solver_t * p );
+extern Msat_ClauseVec_t *  Msat_SolverReadAdjacents( Msat_Solver_t * p );
+extern Msat_IntVec_t *  Msat_SolverReadConeVars( Msat_Solver_t * p );
+extern Msat_IntVec_t *  Msat_SolverReadVarsUsed( Msat_Solver_t * p );
+/*=== satSolverSearch.c ===========================================================*/
+extern void             Msat_SolverRemoveLearned( Msat_Solver_t * p );
+extern void             Msat_SolverRemoveMarked( Msat_Solver_t * p );
+/*=== satSolverApi.c ===========================================================*/
+// allocation, cleaning, and freeing the solver
+extern Msat_Solver_t *  Msat_SolverAlloc( int nVars, double dClaInc, double dClaDecay, double dVarInc, double dVarDecay, int fVerbose );
+extern void             Msat_SolverResize( Msat_Solver_t * pMan, int nVarsAlloc );
+extern void             Msat_SolverClean( Msat_Solver_t * p, int nVars );
+extern void             Msat_SolverPrepare( Msat_Solver_t * pSat, Msat_IntVec_t * vVars );
+extern void             Msat_SolverFree( Msat_Solver_t * p );
+/*=== satVec.c ===========================================================*/
+extern Msat_IntVec_t *  Msat_IntVecAlloc( int nCap );
+extern Msat_IntVec_t *  Msat_IntVecAllocArray( int * pArray, int nSize );
+extern Msat_IntVec_t *  Msat_IntVecAllocArrayCopy( int * pArray, int nSize );
+extern Msat_IntVec_t *  Msat_IntVecDup( Msat_IntVec_t * pVec );
+extern Msat_IntVec_t *  Msat_IntVecDupArray( Msat_IntVec_t * pVec );
+extern void             Msat_IntVecFree( Msat_IntVec_t * p );
+extern void             Msat_IntVecFill( Msat_IntVec_t * p, int nSize, int Entry );
+extern int *            Msat_IntVecReleaseArray( Msat_IntVec_t * p );
+extern int *            Msat_IntVecReadArray( Msat_IntVec_t * p );
+extern int              Msat_IntVecReadSize( Msat_IntVec_t * p );
+extern int              Msat_IntVecReadEntry( Msat_IntVec_t * p, int i );
+extern int              Msat_IntVecReadEntryLast( Msat_IntVec_t * p );
+extern void             Msat_IntVecWriteEntry( Msat_IntVec_t * p, int i, int Entry );
+extern void             Msat_IntVecGrow( Msat_IntVec_t * p, int nCapMin );
+extern void             Msat_IntVecShrink( Msat_IntVec_t * p, int nSizeNew );
+extern void             Msat_IntVecClear( Msat_IntVec_t * p );
+extern void             Msat_IntVecPush( Msat_IntVec_t * p, int Entry );
+extern int              Msat_IntVecPushUnique( Msat_IntVec_t * p, int Entry );
+extern void             Msat_IntVecPushUniqueOrder( Msat_IntVec_t * p, int Entry, int fIncrease );
+extern int              Msat_IntVecPop( Msat_IntVec_t * p );
+extern void             Msat_IntVecSort( Msat_IntVec_t * p, int fReverse );
+/*=== satHeap.c ===========================================================*/
+extern Msat_VarHeap_t * Msat_VarHeapAlloc();
+extern void             Msat_VarHeapSetActivity( Msat_VarHeap_t * p, double * pActivity );
+extern void             Msat_VarHeapStart( Msat_VarHeap_t * p, int * pVars, int nVars, int nVarsAlloc );
+extern void             Msat_VarHeapGrow( Msat_VarHeap_t * p, int nSize );
+extern void             Msat_VarHeapStop( Msat_VarHeap_t * p );
+extern void             Msat_VarHeapPrint( FILE * pFile, Msat_VarHeap_t * p );
+extern void             Msat_VarHeapCheck( Msat_VarHeap_t * p );
+extern void             Msat_VarHeapCheckOne( Msat_VarHeap_t * p, int iVar );
+extern int              Msat_VarHeapContainsVar( Msat_VarHeap_t * p, int iVar );
+extern void             Msat_VarHeapInsert( Msat_VarHeap_t * p, int iVar );  
+extern void             Msat_VarHeapUpdate( Msat_VarHeap_t * p, int iVar );  
+extern void             Msat_VarHeapDelete( Msat_VarHeap_t * p, int iVar );  
+extern double           Msat_VarHeapReadMaxWeight( Msat_VarHeap_t * p );
+extern int              Msat_VarHeapCountNodes( Msat_VarHeap_t * p, double WeightLimit );  
+extern int              Msat_VarHeapReadMax( Msat_VarHeap_t * p );  
+extern int              Msat_VarHeapGetMax( Msat_VarHeap_t * p );  
+ 
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
diff --git a/abc-build/src/sat/msat/msatActivity.c b/abc-build/src/sat/msat/msatActivity.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/msat/msatActivity.c
@@ -0,0 +1,165 @@
+/**CFile****************************************************************
+
+  FileName    [msatActivity.c]
+
+  PackageName [A C version of SAT solver MINISAT, originally developed 
+  in C++ by Niklas Een and Niklas Sorensson, Chalmers University of 
+  Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.]
+
+  Synopsis    [Procedures controlling activity of variables and clauses.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: msatActivity.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "msatInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverVarBumpActivity( Msat_Solver_t * p, Msat_Lit_t Lit )
+{
+    Msat_Var_t Var;
+    if ( p->dVarDecay < 0 ) // (negative decay means static variable order -- don't bump)
+        return;
+    Var = MSAT_LIT2VAR(Lit);
+    p->pdActivity[Var] += p->dVarInc;
+//    p->pdActivity[Var] += p->dVarInc * p->pFactors[Var];
+    if ( p->pdActivity[Var] > 1e100 )
+        Msat_SolverVarRescaleActivity( p );
+    Msat_OrderUpdate( p->pOrder, Var );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverVarDecayActivity( Msat_Solver_t * p )
+{
+    if ( p->dVarDecay >= 0 )
+        p->dVarInc *= p->dVarDecay;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Divide all variable activities by 1e100.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverVarRescaleActivity( Msat_Solver_t * p )
+{
+    int i;
+    for ( i = 0; i < p->nVars; i++ )
+        p->pdActivity[i] *= 1e-100;
+    p->dVarInc *= 1e-100;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverClaBumpActivity( Msat_Solver_t * p, Msat_Clause_t * pC )
+{
+    float Activ;
+    Activ = Msat_ClauseReadActivity(pC);
+    if ( Activ + p->dClaInc > 1e20 )
+    {
+        Msat_SolverClaRescaleActivity( p );
+        Activ = Msat_ClauseReadActivity( pC );
+    }
+    Msat_ClauseWriteActivity( pC, Activ + (float)p->dClaInc );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverClaDecayActivity( Msat_Solver_t * p )
+{
+    p->dClaInc *= p->dClaDecay;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Divide all constraint activities by 1e20.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverClaRescaleActivity( Msat_Solver_t * p )
+{
+    Msat_Clause_t ** pLearned;
+    int nLearned, i;
+    float Activ;
+    nLearned = Msat_ClauseVecReadSize( p->vLearned );
+    pLearned = Msat_ClauseVecReadArray( p->vLearned );
+    for ( i = 0; i < nLearned; i++ )
+    {
+        Activ = Msat_ClauseReadActivity( pLearned[i] );
+        Msat_ClauseWriteActivity( pLearned[i], Activ * (float)1e-20 );
+    }
+    p->dClaInc *= 1e-20;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/msat/msatClause.c b/abc-build/src/sat/msat/msatClause.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/msat/msatClause.c
@@ -0,0 +1,534 @@
+/**CFile****************************************************************
+
+  FileName    [msatClause.c]
+
+  PackageName [A C version of SAT solver MINISAT, originally developed 
+  in C++ by Niklas Een and Niklas Sorensson, Chalmers University of 
+  Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.]
+
+  Synopsis    [Procedures working with SAT clauses.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: msatClause.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "msatInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+struct Msat_Clause_t_
+{
+    int           Num;              // unique number of the clause
+    unsigned      fLearned   :  1;  // 1 if the clause is learned
+    unsigned      fMark      :  1;  // used to mark visited clauses during proof recording
+    unsigned      fTypeA     :  1;  // used to mark clauses belonging to A for interpolant computation
+    unsigned      nSize      : 14;  // the number of literals in the clause
+    unsigned      nSizeAlloc : 15;  // the number of bytes allocated for the clause
+    Msat_Lit_t     pData[0];
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Creates a new clause.]
+
+  Description [Returns FALSE if top-level conflict detected (must be handled); 
+  TRUE otherwise. 'pClause_out' may be set to NULL if clause is already 
+  satisfied by the top-level assignment.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int  Msat_ClauseCreate( Msat_Solver_t * p, Msat_IntVec_t * vLits, int  fLearned, Msat_Clause_t ** pClause_out )
+{
+    int * pAssigns = Msat_SolverReadAssignsArray(p);
+    Msat_ClauseVec_t ** pvWatched;
+    Msat_Clause_t * pC;
+    int * pLits;
+    int nLits, i, j;
+    int nBytes;
+    Msat_Var_t Var;
+    int  Sign;
+
+    *pClause_out = NULL;
+
+    nLits = Msat_IntVecReadSize(vLits);
+    pLits = Msat_IntVecReadArray(vLits);
+
+    if ( !fLearned ) 
+    {
+        int * pSeen = Msat_SolverReadSeenArray( p );
+        int nSeenId;
+        assert( Msat_SolverReadDecisionLevel(p) == 0 );
+        // sorting literals makes the code trace-equivalent 
+        // with to the original C++ solver
+        Msat_IntVecSort( vLits, 0 );
+        // increment the counter of seen twice
+        nSeenId = Msat_SolverIncrementSeenId( p );
+        nSeenId = Msat_SolverIncrementSeenId( p );
+        // nSeenId - 1 stands for negative
+        // nSeenId     stands for positive
+        // Remove false literals
+
+        // there is a bug here!!!!
+        // when the same var in opposite polarities is given, it drops one polarity!!!
+
+        for ( i = j = 0; i < nLits; i++ ) {
+            // get the corresponding variable
+            Var  = MSAT_LIT2VAR(pLits[i]);
+            Sign = MSAT_LITSIGN(pLits[i]); // Sign=0 for positive
+            // check if we already saw this variable in the this clause
+            if ( pSeen[Var] >= nSeenId - 1 )
+            {
+                if ( (pSeen[Var] != nSeenId) == Sign ) // the same lit
+                    continue;
+                return 1; // two opposite polarity lits -- don't add the clause
+            }
+            // mark the variable as seen
+            pSeen[Var] = nSeenId - !Sign;
+
+            // analize the value of this literal
+            if ( pAssigns[Var] != MSAT_VAR_UNASSIGNED )
+            {
+                if ( pAssigns[Var] == pLits[i] )
+                    return 1;  // the clause is always true -- don't add anything
+                // the literal has no impact - skip it
+                continue;
+            }
+            // otherwise, add this literal to the clause
+            pLits[j++] = pLits[i];
+        }
+        Msat_IntVecShrink( vLits, j );
+        nLits = j;
+/*
+        // the problem with this code is that performance is very
+        // sensitive to the ordering of adjacency lits
+        // the best ordering requires fanins first, next fanouts
+        // this ordering is more convenient to make from FRAIG
+
+        // create the adjacency information
+        if ( nLits > 2 )
+        {
+            Msat_Var_t VarI, VarJ;
+            Msat_IntVec_t * pAdjI, * pAdjJ;
+
+            for ( i = 0; i < nLits; i++ )
+            {
+                VarI = MSAT_LIT2VAR(pLits[i]);
+                pAdjI = (Msat_IntVec_t *)p->vAdjacents->pArray[VarI];
+
+                for ( j = i+1; j < nLits; j++ )
+                {
+                    VarJ = MSAT_LIT2VAR(pLits[j]);
+                    pAdjJ = (Msat_IntVec_t *)p->vAdjacents->pArray[VarJ];
+
+                    Msat_IntVecPushUniqueOrder( pAdjI, VarJ, 1 );
+                    Msat_IntVecPushUniqueOrder( pAdjJ, VarI, 1 );
+                }
+            }
+        }
+*/
+    }
+    // 'vLits' is now the (possibly) reduced vector of literals.
+    if ( nLits == 0 )
+        return 0;
+    if ( nLits == 1 )
+        return Msat_SolverEnqueue( p, pLits[0], NULL );
+
+    // Allocate clause:
+//    nBytes = sizeof(unsigned)*(nLits + 1 + (int)fLearned);
+    nBytes = sizeof(unsigned)*(nLits + 2 + (int)fLearned);
+#ifdef USE_SYSTEM_MEMORY_MANAGEMENT
+    pC = (Msat_Clause_t *)ABC_ALLOC( char, nBytes );
+#else
+    pC = (Msat_Clause_t *)Msat_MmStepEntryFetch( Msat_SolverReadMem(p), nBytes );
+#endif
+    pC->Num        = p->nClauses++;
+    pC->fTypeA     = 0;
+    pC->fMark      = 0;
+    pC->fLearned   = fLearned;
+    pC->nSize      = nLits;
+    pC->nSizeAlloc = nBytes;
+    memcpy( pC->pData, pLits, sizeof(int)*nLits );
+
+    // For learnt clauses only:
+    if ( fLearned )
+    {
+        int * pLevel = Msat_SolverReadDecisionLevelArray( p );
+        int iLevelMax, iLevelCur, iLitMax;
+
+        // Put the second watch on the literal with highest decision level:
+        iLitMax = 1;
+        iLevelMax = pLevel[ MSAT_LIT2VAR(pLits[1]) ];
+        for ( i = 2; i < nLits; i++ )
+        {
+            iLevelCur = pLevel[ MSAT_LIT2VAR(pLits[i]) ];
+            assert( iLevelCur != -1 );
+            if ( iLevelMax < iLevelCur )
+            // this is very strange - shouldn't it be???
+            // if ( iLevelMax > iLevelCur )
+                iLevelMax = iLevelCur, iLitMax = i;
+        }
+        pC->pData[1]       = pLits[iLitMax];
+        pC->pData[iLitMax] = pLits[1];
+
+        // Bumping:
+        // (newly learnt clauses should be considered active)
+        Msat_ClauseWriteActivity( pC, 0.0 );
+        Msat_SolverClaBumpActivity( p, pC ); 
+//        if ( nLits < 20 )
+        for ( i = 0; i < nLits; i++ )
+        {
+            Msat_SolverVarBumpActivity( p, pLits[i] );
+//            Msat_SolverVarBumpActivity( p, pLits[i] );
+//            p->pFreq[ MSAT_LIT2VAR(pLits[i]) ]++;
+        }
+    }
+
+    // Store clause:
+    pvWatched = Msat_SolverReadWatchedArray( p );
+    Msat_ClauseVecPush( pvWatched[ MSAT_LITNOT(pC->pData[0]) ], pC );
+    Msat_ClauseVecPush( pvWatched[ MSAT_LITNOT(pC->pData[1]) ], pC );
+    *pClause_out = pC;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocates the clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_ClauseFree( Msat_Solver_t * p, Msat_Clause_t * pC, int  fRemoveWatched )
+{
+    if ( fRemoveWatched )
+    {
+        Msat_Lit_t Lit;
+        Msat_ClauseVec_t ** pvWatched;
+        pvWatched = Msat_SolverReadWatchedArray( p );
+        Lit = MSAT_LITNOT( pC->pData[0] );
+        Msat_ClauseRemoveWatch( pvWatched[Lit], pC );
+        Lit = MSAT_LITNOT( pC->pData[1] );
+        Msat_ClauseRemoveWatch( pvWatched[Lit], pC ); 
+    }
+
+#ifdef USE_SYSTEM_MEMORY_MANAGEMENT
+    ABC_FREE( pC );
+#else
+    Msat_MmStepEntryRecycle( Msat_SolverReadMem(p), (char *)pC, pC->nSizeAlloc );
+#endif
+
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Access the data field of the clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int   Msat_ClauseReadLearned( Msat_Clause_t * pC )  {  return pC->fLearned; }
+int   Msat_ClauseReadSize( Msat_Clause_t * pC )     {  return pC->nSize;    }
+int * Msat_ClauseReadLits( Msat_Clause_t * pC )     {  return pC->pData;    }
+int   Msat_ClauseReadMark( Msat_Clause_t * pC )     {  return pC->fMark;    }
+int   Msat_ClauseReadNum( Msat_Clause_t * pC )      {  return pC->Num;      }
+int   Msat_ClauseReadTypeA( Msat_Clause_t * pC )    {  return pC->fTypeA;    }
+
+void  Msat_ClauseSetMark( Msat_Clause_t * pC, int  fMark )   {  pC->fMark = fMark;   }
+void  Msat_ClauseSetNum( Msat_Clause_t * pC, int Num )       {  pC->Num = Num;       }
+void  Msat_ClauseSetTypeA( Msat_Clause_t * pC, int  fTypeA ) {  pC->fTypeA = fTypeA; }
+
+/**Function*************************************************************
+
+  Synopsis    [Checks whether the learned clause is locked.]
+
+  Description [The clause may be locked if it is the reason of a
+  recent conflict. Such clause cannot be removed from the database.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int  Msat_ClauseIsLocked( Msat_Solver_t * p, Msat_Clause_t * pC )
+{
+    Msat_Clause_t ** pReasons = Msat_SolverReadReasonArray( p );
+    return (int )(pReasons[MSAT_LIT2VAR(pC->pData[0])] == pC);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the activity of the given clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+float Msat_ClauseReadActivity( Msat_Clause_t * pC )
+{
+    return *((float *)(pC->pData + pC->nSize));
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the activity of the clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_ClauseWriteActivity( Msat_Clause_t * pC, float Num )
+{
+    *((float *)(pC->pData + pC->nSize)) = Num;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propages the assignment.]
+
+  Description [The literal that has become true (Lit) is given to this 
+  procedure. The array of current variable assignments is given for
+  efficiency. The output literal (pLit_out) can be the second watched
+  literal (if TRUE is returned) or the conflict literal (if FALSE is 
+  returned). This messy interface is used to improve performance.
+  This procedure accounts for ~50% of the runtime of the solver.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int  Msat_ClausePropagate( Msat_Clause_t * pC, Msat_Lit_t Lit, int * pAssigns, Msat_Lit_t * pLit_out )
+{
+    // make sure the false literal is pC->pData[1]
+    Msat_Lit_t LitF = MSAT_LITNOT(Lit);
+    if ( pC->pData[0] == LitF )
+         pC->pData[0] = pC->pData[1], pC->pData[1] = LitF;
+    assert( pC->pData[1] == LitF );
+    // if the 0-th watch is true, clause is already satisfied
+    if ( pAssigns[MSAT_LIT2VAR(pC->pData[0])] == pC->pData[0] )
+        return 1; 
+    // look for a new watch
+    if ( pC->nSize > 2 )
+    {
+        int i;
+        for ( i = 2; i < (int)pC->nSize; i++ )
+            if ( pAssigns[MSAT_LIT2VAR(pC->pData[i])] != MSAT_LITNOT(pC->pData[i]) )
+            {
+                pC->pData[1] = pC->pData[i], pC->pData[i] = LitF;
+                *pLit_out = MSAT_LITNOT(pC->pData[1]);
+                return 1; 
+            }
+    }
+    // clause is unit under assignment
+    *pLit_out = pC->pData[0];
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simplifies the clause.]
+
+  Description [Assumes everything has been propagated! (esp. watches 
+  in clauses are NOT unsatisfied)]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int  Msat_ClauseSimplify( Msat_Clause_t * pC, int * pAssigns )
+{
+    Msat_Var_t Var;
+    int i, j;
+    for ( i = j = 0; i < (int)pC->nSize; i++ )
+    {
+        Var = MSAT_LIT2VAR(pC->pData[i]);
+        if ( pAssigns[Var] == MSAT_VAR_UNASSIGNED )
+        {
+            pC->pData[j++] = pC->pData[i];
+            continue;
+        }
+        if ( pAssigns[Var] == pC->pData[i] )
+            return 1;
+        // otherwise, the value of the literal is false
+        // make sure, this literal is not watched
+        assert( i >= 2 );
+    }
+    // if the size has changed, update it and move activity
+    if ( j < (int)pC->nSize )
+    {
+        float Activ = Msat_ClauseReadActivity(pC);
+        pC->nSize = j;
+        Msat_ClauseWriteActivity(pC, Activ);
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes reason of conflict in the given clause.]
+
+  Description [If the literal is unassigned, finds the reason by 
+  complementing literals in the given cluase (pC). If the literal is
+  assigned, makes sure that this literal is the first one in the clause
+  and computes the complement of all other literals in the clause.
+  Returns the reason in the given array (vLits_out). If the clause is
+  learned, bumps its activity.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_ClauseCalcReason( Msat_Solver_t * p, Msat_Clause_t * pC, Msat_Lit_t Lit, Msat_IntVec_t * vLits_out )
+{
+    int i;
+    // clear the reason
+    Msat_IntVecClear( vLits_out );
+    assert( Lit == MSAT_LIT_UNASSIGNED || Lit == pC->pData[0] );
+    for ( i = (Lit != MSAT_LIT_UNASSIGNED); i < (int)pC->nSize; i++ )
+    {
+        assert( Msat_SolverReadAssignsArray(p)[MSAT_LIT2VAR(pC->pData[i])] == MSAT_LITNOT(pC->pData[i]) );
+        Msat_IntVecPush( vLits_out, MSAT_LITNOT(pC->pData[i]) );
+    }
+    if ( pC->fLearned ) 
+        Msat_SolverClaBumpActivity( p, pC );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes the given clause from the watched list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_ClauseRemoveWatch( Msat_ClauseVec_t * vClauses, Msat_Clause_t * pC )
+{
+    Msat_Clause_t ** pClauses;
+    int nClauses, i;
+    nClauses = Msat_ClauseVecReadSize( vClauses );
+    pClauses = Msat_ClauseVecReadArray( vClauses );
+    for ( i = 0; pClauses[i] != pC; i++ )
+        assert( i < nClauses );
+    for (      ; i < nClauses - 1; i++ )
+        pClauses[i] = pClauses[i+1];
+    Msat_ClauseVecPop( vClauses );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the given clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_ClausePrint( Msat_Clause_t * pC )
+{
+    int i;
+    if ( pC == NULL )
+        printf( "NULL pointer" );
+    else 
+    {
+        if ( pC->fLearned )
+            printf( "Act = %.4f  ", Msat_ClauseReadActivity(pC) );
+        for ( i = 0; i < (int)pC->nSize; i++ )
+            printf( " %s%d", ((pC->pData[i]&1)? "-": ""),  pC->pData[i]/2 + 1 );
+    }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes the given clause in a file in DIMACS format.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_ClauseWriteDimacs( FILE * pFile, Msat_Clause_t * pC, int  fIncrement )
+{
+    int i;
+    for ( i = 0; i < (int)pC->nSize; i++ )
+        fprintf( pFile, "%s%d ", ((pC->pData[i]&1)? "-": ""),  pC->pData[i]/2 + (int)(fIncrement>0) );
+    if ( fIncrement )
+        fprintf( pFile, "0" );
+    fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the given clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_ClausePrintSymbols( Msat_Clause_t * pC )
+{
+    int i;
+    if ( pC == NULL )
+        printf( "NULL pointer" );
+    else 
+    {
+//        if ( pC->fLearned )
+//            printf( "Act = %.4f  ", Msat_ClauseReadActivity(pC) );
+        for ( i = 0; i < (int)pC->nSize; i++ )
+            printf(" "L_LIT, L_lit(pC->pData[i]));
+    }
+    printf( "\n" );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/msat/msatClauseVec.c b/abc-build/src/sat/msat/msatClauseVec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/msat/msatClauseVec.c
@@ -0,0 +1,237 @@
+/**CFile****************************************************************
+
+  FileName    [msatClauseVec.c]
+
+  PackageName [A C version of SAT solver MINISAT, originally developed 
+  in C++ by Niklas Een and Niklas Sorensson, Chalmers University of 
+  Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.]
+
+  Synopsis    [Procedures working with arrays of SAT clauses.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: msatClauseVec.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "msatInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_ClauseVec_t * Msat_ClauseVecAlloc( int nCap )
+{
+    Msat_ClauseVec_t * p;
+    p = ABC_ALLOC( Msat_ClauseVec_t, 1 );
+    if ( nCap > 0 && nCap < 16 )
+        nCap = 16;
+    p->nSize  = 0;
+    p->nCap   = nCap;
+    p->pArray = p->nCap? ABC_ALLOC( Msat_Clause_t *, p->nCap ) : NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_ClauseVecFree( Msat_ClauseVec_t * p )
+{
+    ABC_FREE( p->pArray );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_Clause_t ** Msat_ClauseVecReadArray( Msat_ClauseVec_t * p )
+{
+    return p->pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_ClauseVecReadSize( Msat_ClauseVec_t * p )
+{
+    return p->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the vector to the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_ClauseVecGrow( Msat_ClauseVec_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pArray = ABC_REALLOC( Msat_Clause_t *, p->pArray, nCapMin ); 
+    p->nCap   = nCapMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_ClauseVecShrink( Msat_ClauseVec_t * p, int nSizeNew )
+{
+    assert( p->nSize >= nSizeNew );
+    p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_ClauseVecClear( Msat_ClauseVec_t * p )
+{
+    p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_ClauseVecPush( Msat_ClauseVec_t * p, Msat_Clause_t * Entry )
+{
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Msat_ClauseVecGrow( p, 16 );
+        else
+            Msat_ClauseVecGrow( p, 2 * p->nCap );
+    }
+    p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_Clause_t * Msat_ClauseVecPop( Msat_ClauseVec_t * p )
+{
+    return p->pArray[--p->nSize];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_ClauseVecWriteEntry( Msat_ClauseVec_t * p, int i, Msat_Clause_t * Entry )
+{
+    assert( i >= 0 && i < p->nSize );
+    p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_Clause_t * Msat_ClauseVecReadEntry( Msat_ClauseVec_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray[i];
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/msat/msatInt.h b/abc-build/src/sat/msat/msatInt.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/msat/msatInt.h
@@ -0,0 +1,295 @@
+/**CFile****************************************************************
+
+  FileName    [msatInt.c]
+
+  PackageName [A C version of SAT solver MINISAT, originally developed 
+  in C++ by Niklas Een and Niklas Sorensson, Chalmers University of 
+  Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.]
+
+  Synopsis    [Internal definitions of the solver.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: msatInt.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__sat__msat__msatInt_h
+#define ABC__sat__msat__msatInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <math.h>
+
+#include "misc/util/abc_global.h"
+#include "msat.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    STRUCTURE DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+// By default, custom memory management is used
+// which guarantees constant time allocation/deallocation 
+// for SAT clauses and other frequently modified objects.
+// For debugging, it is possible use system memory management
+// directly. In which case, uncomment the macro below.
+//#define USE_SYSTEM_MEMORY_MANAGEMENT 
+
+// internal data structures
+typedef struct Msat_Clause_t_      Msat_Clause_t;
+typedef struct Msat_Queue_t_       Msat_Queue_t;
+typedef struct Msat_Order_t_       Msat_Order_t;
+// memory managers (duplicated from Extra for stand-aloneness)
+typedef struct Msat_MmFixed_t_     Msat_MmFixed_t;    
+typedef struct Msat_MmFlex_t_      Msat_MmFlex_t;     
+typedef struct Msat_MmStep_t_      Msat_MmStep_t;     
+// variables and literals
+typedef int                       Msat_Lit_t;  
+typedef int                       Msat_Var_t;  
+// the type of return value
+#define MSAT_VAR_UNASSIGNED (-1)
+#define MSAT_LIT_UNASSIGNED (-2)
+#define MSAT_ORDER_UNKNOWN  (-3)
+
+// printing the search tree
+#define L_IND      "%-*d"
+#define L_ind      Msat_SolverReadDecisionLevel(p)*3+3,Msat_SolverReadDecisionLevel(p)
+#define L_LIT      "%s%d"
+#define L_lit(Lit) MSAT_LITSIGN(Lit)?"-":"", MSAT_LIT2VAR(Lit)+1
+
+typedef struct Msat_SolverStats_t_ Msat_SolverStats_t;
+struct Msat_SolverStats_t_
+{
+    ABC_INT64_T   nStarts;        // the number of restarts
+    ABC_INT64_T   nDecisions;     // the number of decisions
+    ABC_INT64_T   nPropagations;  // the number of implications
+    ABC_INT64_T   nInspects;      // the number of times clauses are vising while watching them
+    ABC_INT64_T   nConflicts;     // the number of conflicts
+    ABC_INT64_T   nSuccesses;     // the number of sat assignments found
+};
+
+typedef struct Msat_SearchParams_t_ Msat_SearchParams_t;
+struct Msat_SearchParams_t_
+{
+    double  dVarDecay;
+    double  dClaDecay;
+};
+
+// sat solver data structure visible through all the internal files
+struct Msat_Solver_t_
+{
+    int                 nClauses;    // the total number of clauses
+    int                 nClausesStart; // the number of clauses before adding
+    Msat_ClauseVec_t *  vClauses;    // problem clauses
+    Msat_ClauseVec_t *  vLearned;    // learned clauses
+    double              dClaInc;     // Amount to bump next clause with.
+    double              dClaDecay;   // INVERSE decay factor for clause activity: stores 1/decay.
+
+    double *            pdActivity;  // A heuristic measurement of the activity of a variable.
+    float *             pFactors;    // the multiplicative factors of variable activity
+    double              dVarInc;     // Amount to bump next variable with.
+    double              dVarDecay;   // INVERSE decay factor for variable activity: stores 1/decay. Use negative value for static variable order.
+    Msat_Order_t *      pOrder;      // Keeps track of the decision variable order.
+
+    Msat_ClauseVec_t ** pvWatched;   // 'pvWatched[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true).
+    Msat_Queue_t *      pQueue;      // Propagation queue.
+
+    int                 nVars;       // the current number of variables
+    int                 nVarsAlloc;  // the maximum allowed number of variables
+    int *               pAssigns;    // The current assignments (literals or MSAT_VAR_UNKOWN)
+    int *               pModel;      // The satisfying assignment
+    Msat_IntVec_t *     vTrail;      // List of assignments made. 
+    Msat_IntVec_t *     vTrailLim;   // Separator indices for different decision levels in 'trail'.
+    Msat_Clause_t **    pReasons;    // 'reason[var]' is the clause that implied the variables current value, or 'NULL' if none.
+    int *               pLevel;      // 'level[var]' is the decision level at which assignment was made. 
+    int                 nLevelRoot;  // Level of first proper decision.
+
+    double              dRandSeed;   // For the internal random number generator (makes solver deterministic over different platforms). 
+
+    int                 fVerbose;    // the verbosity flag
+    double              dProgress;   // Set by 'search()'.
+
+    // the variable cone and variable connectivity
+    Msat_IntVec_t *     vConeVars;
+    Msat_IntVec_t *     vVarsUsed;
+    Msat_ClauseVec_t *  vAdjacents;
+
+    // internal data used during conflict analysis
+    int *               pSeen;       // time when a lit was seen for the last time
+    int                 nSeenId;     // the id of current seeing
+    Msat_IntVec_t *     vReason;     // the temporary array of literals
+    Msat_IntVec_t *     vTemp;       // the temporary array of literals
+    int *               pFreq;       // the number of times each var participated in conflicts
+
+    // the memory manager
+    Msat_MmStep_t *     pMem;
+
+    // statistics
+    Msat_SolverStats_t  Stats;
+    int                 nTwoLits;
+    int                 nTwoLitsL;
+    int                 nClausesInit;
+    int                 nClausesAlloc;
+    int                 nClausesAllocL;
+    int                 nBackTracks;
+};
+
+struct Msat_ClauseVec_t_
+{
+    Msat_Clause_t **    pArray;
+    int                 nSize;
+    int                 nCap;
+};
+
+struct Msat_IntVec_t_
+{
+    int *               pArray;
+    int                 nSize;
+    int                 nCap;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                       GLOBAL VARIABLES                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                       MACRO DEFINITIONS                          ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DECLARATIONS                        ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== satActivity.c ===========================================================*/
+extern void                Msat_SolverVarDecayActivity( Msat_Solver_t * p );
+extern void                Msat_SolverVarRescaleActivity( Msat_Solver_t * p );
+extern void                Msat_SolverClaDecayActivity( Msat_Solver_t * p );
+extern void                Msat_SolverClaRescaleActivity( Msat_Solver_t * p );
+/*=== satSolverApi.c ===========================================================*/
+extern Msat_Clause_t *     Msat_SolverReadClause( Msat_Solver_t * p, int Num );
+/*=== satSolver.c ===========================================================*/
+extern int                 Msat_SolverReadDecisionLevel( Msat_Solver_t * p );
+extern int *               Msat_SolverReadDecisionLevelArray( Msat_Solver_t * p );
+extern Msat_Clause_t **    Msat_SolverReadReasonArray( Msat_Solver_t * p );
+extern Msat_Type_t         Msat_SolverReadVarValue( Msat_Solver_t * p, Msat_Var_t Var );
+extern Msat_ClauseVec_t *  Msat_SolverReadLearned( Msat_Solver_t * p );
+extern Msat_ClauseVec_t ** Msat_SolverReadWatchedArray( Msat_Solver_t * p );
+extern int *               Msat_SolverReadSeenArray( Msat_Solver_t * p );
+extern int                 Msat_SolverIncrementSeenId( Msat_Solver_t * p );
+extern Msat_MmStep_t *     Msat_SolverReadMem( Msat_Solver_t * p );
+extern void                Msat_SolverClausesIncrement( Msat_Solver_t * p );
+extern void                Msat_SolverClausesDecrement( Msat_Solver_t * p );
+extern void                Msat_SolverClausesIncrementL( Msat_Solver_t * p );
+extern void                Msat_SolverClausesDecrementL( Msat_Solver_t * p );
+extern void                Msat_SolverVarBumpActivity( Msat_Solver_t * p, Msat_Lit_t Lit );
+extern void                Msat_SolverClaBumpActivity( Msat_Solver_t * p, Msat_Clause_t * pC );
+extern int                 Msat_SolverEnqueue( Msat_Solver_t * p, Msat_Lit_t Lit, Msat_Clause_t * pC );
+extern double              Msat_SolverProgressEstimate( Msat_Solver_t * p );
+/*=== satSolverSearch.c ===========================================================*/
+extern int                 Msat_SolverAssume( Msat_Solver_t * p, Msat_Lit_t Lit );
+extern Msat_Clause_t *     Msat_SolverPropagate( Msat_Solver_t * p );
+extern void                Msat_SolverCancelUntil( Msat_Solver_t * p, int Level );
+extern Msat_Type_t         Msat_SolverSearch( Msat_Solver_t * p, int nConfLimit, int nLearnedLimit, int nBackTrackLimit, Msat_SearchParams_t * pPars );
+/*=== satQueue.c ===========================================================*/
+extern Msat_Queue_t *      Msat_QueueAlloc( int nVars );
+extern void                Msat_QueueFree( Msat_Queue_t * p );
+extern int                 Msat_QueueReadSize( Msat_Queue_t * p );
+extern void                Msat_QueueInsert( Msat_Queue_t * p, int Lit );
+extern int                 Msat_QueueExtract( Msat_Queue_t * p );
+extern void                Msat_QueueClear( Msat_Queue_t * p );
+/*=== satOrder.c ===========================================================*/
+extern Msat_Order_t *      Msat_OrderAlloc( Msat_Solver_t * pSat );
+extern void                Msat_OrderSetBounds( Msat_Order_t * p, int nVarsMax );
+extern void                Msat_OrderClean( Msat_Order_t * p, Msat_IntVec_t * vCone );
+extern int                 Msat_OrderCheck( Msat_Order_t * p );
+extern void                Msat_OrderFree( Msat_Order_t * p );
+extern int                 Msat_OrderVarSelect( Msat_Order_t * p );
+extern void                Msat_OrderVarAssigned( Msat_Order_t * p, int Var );
+extern void                Msat_OrderVarUnassigned( Msat_Order_t * p, int Var );
+extern void                Msat_OrderUpdate( Msat_Order_t * p, int Var );
+/*=== satClause.c ===========================================================*/
+extern int                 Msat_ClauseCreate( Msat_Solver_t * p, Msat_IntVec_t * vLits, int  fLearnt, Msat_Clause_t ** pClause_out );
+extern Msat_Clause_t *     Msat_ClauseCreateFake( Msat_Solver_t * p, Msat_IntVec_t * vLits );
+extern Msat_Clause_t *     Msat_ClauseCreateFakeLit( Msat_Solver_t * p, Msat_Lit_t Lit );
+extern int                 Msat_ClauseReadLearned( Msat_Clause_t * pC );
+extern int                 Msat_ClauseReadSize( Msat_Clause_t * pC );
+extern int *               Msat_ClauseReadLits( Msat_Clause_t * pC );
+extern int                 Msat_ClauseReadMark( Msat_Clause_t * pC );
+extern void                Msat_ClauseSetMark( Msat_Clause_t * pC, int  fMark );
+extern int                 Msat_ClauseReadNum( Msat_Clause_t * pC );
+extern void                Msat_ClauseSetNum( Msat_Clause_t * pC, int Num );
+extern int                 Msat_ClauseReadTypeA( Msat_Clause_t * pC );
+extern void                Msat_ClauseSetTypeA( Msat_Clause_t * pC, int  fTypeA );
+extern int                 Msat_ClauseIsLocked( Msat_Solver_t * p, Msat_Clause_t * pC );
+extern float               Msat_ClauseReadActivity( Msat_Clause_t * pC );
+extern void                Msat_ClauseWriteActivity( Msat_Clause_t * pC, float Num );
+extern void                Msat_ClauseFree( Msat_Solver_t * p, Msat_Clause_t * pC, int  fRemoveWatched );
+extern int                 Msat_ClausePropagate( Msat_Clause_t * pC, Msat_Lit_t Lit, int * pAssigns, Msat_Lit_t * pLit_out );
+extern int                 Msat_ClauseSimplify( Msat_Clause_t * pC, int * pAssigns );
+extern void                Msat_ClauseCalcReason( Msat_Solver_t * p, Msat_Clause_t * pC, Msat_Lit_t Lit, Msat_IntVec_t * vLits_out );
+extern void                Msat_ClauseRemoveWatch( Msat_ClauseVec_t * vClauses, Msat_Clause_t * pC );
+extern void                Msat_ClausePrint( Msat_Clause_t * pC );
+extern void                Msat_ClausePrintSymbols( Msat_Clause_t * pC );
+extern void                Msat_ClauseWriteDimacs( FILE * pFile, Msat_Clause_t * pC, int  fIncrement );
+extern unsigned            Msat_ClauseComputeTruth( Msat_Solver_t * p, Msat_Clause_t * pC );
+/*=== satSort.c ===========================================================*/
+extern void                Msat_SolverSortDB( Msat_Solver_t * p );
+/*=== satClauseVec.c ===========================================================*/
+extern Msat_ClauseVec_t *  Msat_ClauseVecAlloc( int nCap );
+extern void                Msat_ClauseVecFree( Msat_ClauseVec_t * p );
+extern Msat_Clause_t **    Msat_ClauseVecReadArray( Msat_ClauseVec_t * p );
+extern int                 Msat_ClauseVecReadSize( Msat_ClauseVec_t * p );
+extern void                Msat_ClauseVecGrow( Msat_ClauseVec_t * p, int nCapMin );
+extern void                Msat_ClauseVecShrink( Msat_ClauseVec_t * p, int nSizeNew );
+extern void                Msat_ClauseVecClear( Msat_ClauseVec_t * p );
+extern void                Msat_ClauseVecPush( Msat_ClauseVec_t * p, Msat_Clause_t * Entry );
+extern Msat_Clause_t *     Msat_ClauseVecPop( Msat_ClauseVec_t * p );
+extern void                Msat_ClauseVecWriteEntry( Msat_ClauseVec_t * p, int i, Msat_Clause_t * Entry );
+extern Msat_Clause_t *     Msat_ClauseVecReadEntry( Msat_ClauseVec_t * p, int i );
+
+/*=== satMem.c ===========================================================*/
+// fixed-size-block memory manager
+extern Msat_MmFixed_t *    Msat_MmFixedStart( int nEntrySize );
+extern void                Msat_MmFixedStop( Msat_MmFixed_t * p, int fVerbose );
+extern char *              Msat_MmFixedEntryFetch( Msat_MmFixed_t * p );
+extern void                Msat_MmFixedEntryRecycle( Msat_MmFixed_t * p, char * pEntry );
+extern void                Msat_MmFixedRestart( Msat_MmFixed_t * p );
+extern int                 Msat_MmFixedReadMemUsage( Msat_MmFixed_t * p );
+// flexible-size-block memory manager
+extern Msat_MmFlex_t *     Msat_MmFlexStart();
+extern void                Msat_MmFlexStop( Msat_MmFlex_t * p, int fVerbose );
+extern char *              Msat_MmFlexEntryFetch( Msat_MmFlex_t * p, int nBytes );
+extern int                 Msat_MmFlexReadMemUsage( Msat_MmFlex_t * p );
+// hierarchical memory manager
+extern Msat_MmStep_t *     Msat_MmStepStart( int nSteps );
+extern void                Msat_MmStepStop( Msat_MmStep_t * p, int fVerbose );
+extern char *              Msat_MmStepEntryFetch( Msat_MmStep_t * p, int nBytes );
+extern void                Msat_MmStepEntryRecycle( Msat_MmStep_t * p, char * pEntry, int nBytes );
+extern int                 Msat_MmStepReadMemUsage( Msat_MmStep_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/sat/msat/msatMem.c b/abc-build/src/sat/msat/msatMem.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/msat/msatMem.c
@@ -0,0 +1,534 @@
+/**CFile****************************************************************
+
+  FileName    [msatMem.c]
+
+  PackageName [A C version of SAT solver MINISAT, originally developed 
+  in C++ by Niklas Een and Niklas Sorensson, Chalmers University of 
+  Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.]
+
+  Synopsis    [Memory managers borrowed from Extra.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: msatMem.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "msatInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+struct Msat_MmFixed_t_
+{
+    // information about individual entries
+    int           nEntrySize;    // the size of one entry
+    int           nEntriesAlloc; // the total number of entries allocated
+    int           nEntriesUsed;  // the number of entries in use
+    int           nEntriesMax;   // the max number of entries in use
+    char *        pEntriesFree;  // the linked list of free entries
+
+    // this is where the memory is stored
+    int           nChunkSize;    // the size of one chunk
+    int           nChunksAlloc;  // the maximum number of memory chunks 
+    int           nChunks;       // the current number of memory chunks 
+    char **       pChunks;       // the allocated memory
+
+    // statistics
+    int           nMemoryUsed;   // memory used in the allocated entries
+    int           nMemoryAlloc;  // memory allocated
+};
+
+struct Msat_MmFlex_t_
+{
+    // information about individual entries
+    int           nEntriesUsed;  // the number of entries allocated
+    char *        pCurrent;      // the current pointer to free memory
+    char *        pEnd;          // the first entry outside the free memory
+
+    // this is where the memory is stored
+    int           nChunkSize;    // the size of one chunk
+    int           nChunksAlloc;  // the maximum number of memory chunks 
+    int           nChunks;       // the current number of memory chunks 
+    char **       pChunks;       // the allocated memory
+
+    // statistics
+    int           nMemoryUsed;   // memory used in the allocated entries
+    int           nMemoryAlloc;  // memory allocated
+};
+
+
+struct Msat_MmStep_t_
+{
+    int                nMems;    // the number of fixed memory managers employed
+    Msat_MmFixed_t **   pMems;    // memory managers: 2^1 words, 2^2 words, etc
+    int                nMapSize; // the size of the memory array
+    Msat_MmFixed_t **   pMap;     // maps the number of bytes into its memory manager
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates memory pieces of fixed size.]
+
+  Description [The size of the chunk is computed as the minimum of
+  1024 entries and 64K. Can only work with entry size at least 4 byte long.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_MmFixed_t * Msat_MmFixedStart( int nEntrySize )
+{
+    Msat_MmFixed_t * p;
+
+    p = ABC_ALLOC( Msat_MmFixed_t, 1 );
+    memset( p, 0, sizeof(Msat_MmFixed_t) );
+
+    p->nEntrySize    = nEntrySize;
+    p->nEntriesAlloc = 0;
+    p->nEntriesUsed  = 0;
+    p->pEntriesFree  = NULL;
+
+    if ( nEntrySize * (1 << 10) < (1<<16) )
+        p->nChunkSize = (1 << 10);
+    else
+        p->nChunkSize = (1<<16) / nEntrySize;
+    if ( p->nChunkSize < 8 )
+        p->nChunkSize = 8;
+
+    p->nChunksAlloc  = 64;
+    p->nChunks       = 0;
+    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
+
+    p->nMemoryUsed   = 0;
+    p->nMemoryAlloc  = 0;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_MmFixedStop( Msat_MmFixed_t * p, int fVerbose )
+{
+    int i;
+    if ( p == NULL )
+        return;
+    if ( fVerbose )
+    {
+        printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n",
+            p->nEntrySize, p->nChunkSize, p->nChunks );
+        printf( "   Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n",
+            p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc );
+    }
+    for ( i = 0; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    ABC_FREE( p->pChunks );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Msat_MmFixedEntryFetch( Msat_MmFixed_t * p )
+{
+    char * pTemp;
+    int i;
+
+    // check if there are still free entries
+    if ( p->nEntriesUsed == p->nEntriesAlloc )
+    { // need to allocate more entries
+        assert( p->pEntriesFree == NULL );
+        if ( p->nChunks == p->nChunksAlloc )
+        {
+            p->nChunksAlloc *= 2;
+            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
+        }
+        p->pEntriesFree = ABC_ALLOC( char, p->nEntrySize * p->nChunkSize );
+        p->nMemoryAlloc += p->nEntrySize * p->nChunkSize;
+        // transform these entries into a linked list
+        pTemp = p->pEntriesFree;
+        for ( i = 1; i < p->nChunkSize; i++ )
+        {
+            *((char **)pTemp) = pTemp + p->nEntrySize;
+            pTemp += p->nEntrySize;
+        }
+        // set the last link
+        *((char **)pTemp) = NULL;
+        // add the chunk to the chunk storage
+        p->pChunks[ p->nChunks++ ] = p->pEntriesFree;
+        // add to the number of entries allocated
+        p->nEntriesAlloc += p->nChunkSize;
+    }
+    // incrememt the counter of used entries
+    p->nEntriesUsed++;
+    if ( p->nEntriesMax < p->nEntriesUsed )
+        p->nEntriesMax = p->nEntriesUsed;
+    // return the first entry in the free entry list
+    pTemp = p->pEntriesFree;
+    p->pEntriesFree = *((char **)pTemp);
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_MmFixedEntryRecycle( Msat_MmFixed_t * p, char * pEntry )
+{
+    // decrement the counter of used entries
+    p->nEntriesUsed--;
+    // add the entry to the linked list of free entries
+    *((char **)pEntry) = p->pEntriesFree;
+    p->pEntriesFree = pEntry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description [Relocates all the memory except the first chunk.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_MmFixedRestart( Msat_MmFixed_t * p )
+{
+    int i;
+    char * pTemp;
+
+    // deallocate all chunks except the first one
+    for ( i = 1; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    p->nChunks = 1;
+    // transform these entries into a linked list
+    pTemp = p->pChunks[0];
+    for ( i = 1; i < p->nChunkSize; i++ )
+    {
+        *((char **)pTemp) = pTemp + p->nEntrySize;
+        pTemp += p->nEntrySize;
+    }
+    // set the last link
+    *((char **)pTemp) = NULL;
+    // set the free entry list
+    p->pEntriesFree  = p->pChunks[0];
+    // set the correct statistics
+    p->nMemoryAlloc  = p->nEntrySize * p->nChunkSize;
+    p->nMemoryUsed   = 0;
+    p->nEntriesAlloc = p->nChunkSize;
+    p->nEntriesUsed  = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_MmFixedReadMemUsage( Msat_MmFixed_t * p )
+{
+    return p->nMemoryAlloc;
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates entries of flexible size.]
+
+  Description [Can only work with entry size at least 4 byte long.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_MmFlex_t * Msat_MmFlexStart()
+{
+    Msat_MmFlex_t * p;
+
+    p = ABC_ALLOC( Msat_MmFlex_t, 1 );
+    memset( p, 0, sizeof(Msat_MmFlex_t) );
+
+    p->nEntriesUsed  = 0;
+    p->pCurrent      = NULL;
+    p->pEnd          = NULL;
+
+    p->nChunkSize    = (1 << 12);
+    p->nChunksAlloc  = 64;
+    p->nChunks       = 0;
+    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
+
+    p->nMemoryUsed   = 0;
+    p->nMemoryAlloc  = 0;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_MmFlexStop( Msat_MmFlex_t * p, int fVerbose )
+{
+    int i;
+    if ( p == NULL )
+        return;
+    if ( fVerbose )
+    {
+        printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n",
+            p->nChunkSize, p->nChunks );
+        printf( "   Entries used = %d. Memory used = %d. Memory alloc = %d.\n",
+            p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc );
+    }
+    for ( i = 0; i < p->nChunks; i++ )
+        ABC_FREE( p->pChunks[i] );
+    ABC_FREE( p->pChunks );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Msat_MmFlexEntryFetch( Msat_MmFlex_t * p, int nBytes )
+{
+    char * pTemp;
+    // check if there are still free entries
+    if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd )
+    { // need to allocate more entries
+        if ( p->nChunks == p->nChunksAlloc )
+        {
+            p->nChunksAlloc *= 2;
+            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
+        }
+        if ( nBytes > p->nChunkSize )
+        {
+            // resize the chunk size if more memory is requested than it can give
+            // (ideally, this should never happen)
+            p->nChunkSize = 2 * nBytes;
+        }
+        p->pCurrent = ABC_ALLOC( char, p->nChunkSize );
+        p->pEnd     = p->pCurrent + p->nChunkSize;
+        p->nMemoryAlloc += p->nChunkSize;
+        // add the chunk to the chunk storage
+        p->pChunks[ p->nChunks++ ] = p->pCurrent;
+    }
+    assert( p->pCurrent + nBytes <= p->pEnd );
+    // increment the counter of used entries
+    p->nEntriesUsed++;
+    // keep track of the memory used
+    p->nMemoryUsed += nBytes;
+    // return the next entry
+    pTemp = p->pCurrent;
+    p->pCurrent += nBytes;
+    return pTemp;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_MmFlexReadMemUsage( Msat_MmFlex_t * p )
+{
+    return p->nMemoryAlloc;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the hierarchical memory manager.]
+
+  Description [This manager can allocate entries of any size.
+  Iternally they are mapped into the entries with the number of bytes
+  equal to the power of 2. The smallest entry size is 8 bytes. The
+  next one is 16 bytes etc. So, if the user requests 6 bytes, he gets 
+  8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc.
+  The input parameters "nSteps" says how many fixed memory managers
+  are employed internally. Calling this procedure with nSteps equal
+  to 10 results in 10 hierarchically arranged internal memory managers, 
+  which can allocate up to 4096 (1Kb) entries. Requests for larger 
+  entries are handed over to malloc() and then ABC_FREE()ed.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_MmStep_t * Msat_MmStepStart( int nSteps )
+{
+    Msat_MmStep_t * p;
+    int i, k;
+    p = ABC_ALLOC( Msat_MmStep_t, 1 );
+    p->nMems = nSteps;
+    // start the fixed memory managers
+    p->pMems = ABC_ALLOC( Msat_MmFixed_t *, p->nMems );
+    for ( i = 0; i < p->nMems; i++ )
+        p->pMems[i] = Msat_MmFixedStart( (8<<i) );
+    // set up the mapping of the required memory size into the corresponding manager
+    p->nMapSize = (4<<p->nMems);
+    p->pMap = ABC_ALLOC( Msat_MmFixed_t *, p->nMapSize+1 );
+    p->pMap[0] = NULL;
+    for ( k = 1; k <= 4; k++ )
+        p->pMap[k] = p->pMems[0];
+    for ( i = 0; i < p->nMems; i++ )
+        for ( k = (4<<i)+1; k <= (8<<i); k++ )
+            p->pMap[k] = p->pMems[i];
+//for ( i = 1; i < 100; i ++ )
+//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_MmStepStop( Msat_MmStep_t * p, int fVerbose )
+{
+    int i;
+    for ( i = 0; i < p->nMems; i++ )
+        Msat_MmFixedStop( p->pMems[i], fVerbose );
+    ABC_FREE( p->pMems );
+    ABC_FREE( p->pMap );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Msat_MmStepEntryFetch( Msat_MmStep_t * p, int nBytes )
+{
+    if ( nBytes == 0 )
+        return NULL;
+    if ( nBytes > p->nMapSize )
+    {
+//        printf( "Allocating %d bytes.\n", nBytes );
+        return ABC_ALLOC( char, nBytes );
+    }
+    return Msat_MmFixedEntryFetch( p->pMap[nBytes] );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Recycles the entry.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_MmStepEntryRecycle( Msat_MmStep_t * p, char * pEntry, int nBytes )
+{
+    if ( nBytes == 0 )
+        return;
+    if ( nBytes > p->nMapSize )
+    {
+        ABC_FREE( pEntry );
+        return;
+    }
+    Msat_MmFixedEntryRecycle( p->pMap[nBytes], pEntry );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_MmStepReadMemUsage( Msat_MmStep_t * p )
+{
+    int i, nMemTotal = 0;
+    for ( i = 0; i < p->nMems; i++ )
+        nMemTotal += p->pMems[i]->nMemoryAlloc;
+    return nMemTotal;
+}
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/msat/msatOrderH.c b/abc-build/src/sat/msat/msatOrderH.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/msat/msatOrderH.c
@@ -0,0 +1,415 @@
+/**CFile****************************************************************
+
+  FileName    [msatOrder.c]
+
+  PackageName [A C version of SAT solver MINISAT, originally developed 
+  in C++ by Niklas Een and Niklas Sorensson, Chalmers University of 
+  Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.]
+
+  Synopsis    [The manager of variable assignment.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: msatOrder.c,v 1.0 2005/05/30 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "msatInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// the variable package data structure
+struct Msat_Order_t_
+{
+    Msat_Solver_t *      pSat;         // the SAT solver 
+    Msat_IntVec_t *      vIndex;       // the heap
+    Msat_IntVec_t *      vHeap;        // the mapping of var num into its heap num
+};
+
+//The solver can communicate to the variable order the following parts:
+//- the array of current assignments (pSat->pAssigns)
+//- the array of variable activities (pSat->pdActivity)
+//- the array of variables currently in the cone (pSat->vConeVars)
+//- the array of arrays of variables adjucent to each(pSat->vAdjacents)
+
+#define HLEFT(i)               ((i)<<1)
+#define HRIGHT(i)             (((i)<<1)+1)
+#define HPARENT(i)             ((i)>>1)
+#define HCOMPARE(p, i, j)      ((p)->pSat->pdActivity[i] > (p)->pSat->pdActivity[j])
+#define HHEAP(p, i)            ((p)->vHeap->pArray[i])
+#define HSIZE(p)               ((p)->vHeap->nSize)
+#define HOKAY(p, i)            ((i) >= 0 && (i) < (p)->vIndex->nSize)
+#define HINHEAP(p, i)          (HOKAY(p, i) && (p)->vIndex->pArray[i] != 0)
+#define HEMPTY(p)              (HSIZE(p) == 1)
+
+static int Msat_HeapCheck_rec( Msat_Order_t * p, int i );
+static int Msat_HeapGetTop( Msat_Order_t * p );
+static void Msat_HeapInsert( Msat_Order_t * p, int n );
+static void Msat_HeapIncrease( Msat_Order_t * p, int n );
+static void Msat_HeapPercolateUp( Msat_Order_t * p, int i );
+static void Msat_HeapPercolateDown( Msat_Order_t * p, int i );
+
+extern abctime timeSelect;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the ordering structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_Order_t * Msat_OrderAlloc( Msat_Solver_t * pSat )
+{
+    Msat_Order_t * p;
+    p = ABC_ALLOC( Msat_Order_t, 1 );
+    memset( p, 0, sizeof(Msat_Order_t) );
+    p->pSat   = pSat;
+    p->vIndex = Msat_IntVecAlloc( 0 );
+    p->vHeap  = Msat_IntVecAlloc( 0 );
+    Msat_OrderSetBounds( p, pSat->nVarsAlloc );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the bound of the ordering structure.]
+
+  Description [Should be called whenever the SAT solver is resized.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_OrderSetBounds( Msat_Order_t * p, int nVarsMax )
+{
+    Msat_IntVecGrow( p->vIndex, nVarsMax );
+    Msat_IntVecGrow( p->vHeap, nVarsMax + 1 );
+    p->vIndex->nSize = nVarsMax;
+    p->vHeap->nSize = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the ordering structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_OrderClean( Msat_Order_t * p, Msat_IntVec_t * vCone )
+{
+    int i;
+    for ( i = 0; i < p->vIndex->nSize; i++ )
+        p->vIndex->pArray[i] = 0;
+    for ( i = 0; i < vCone->nSize; i++ )
+    {
+        assert( i+1 < p->vHeap->nCap );
+        p->vHeap->pArray[i+1] = vCone->pArray[i];
+
+        assert( vCone->pArray[i] < p->vIndex->nSize );
+        p->vIndex->pArray[vCone->pArray[i]] = i+1;
+    }
+    p->vHeap->nSize = vCone->nSize + 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks that the J-boundary is okay.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_OrderCheck( Msat_Order_t * p )
+{
+    return Msat_HeapCheck_rec( p, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the ordering structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_OrderFree( Msat_Order_t * p )
+{
+    Msat_IntVecFree( p->vHeap );
+    Msat_IntVecFree( p->vIndex );
+    ABC_FREE( p );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Selects the next variable to assign.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_OrderVarSelect( Msat_Order_t * p )
+{
+    // Activity based decision:
+//    while (!heap.empty()){
+//        Var next = heap.getmin();
+//        if (toLbool(assigns[next]) == l_Undef)
+//            return next;
+//    }
+//    return var_Undef;
+
+    int Var;
+    abctime clk = Abc_Clock();
+
+    while ( !HEMPTY(p) )
+    {
+        Var = Msat_HeapGetTop(p);
+        if ( (p)->pSat->pAssigns[Var] == MSAT_VAR_UNASSIGNED )
+        {
+//assert( Msat_OrderCheck(p) );
+timeSelect += Abc_Clock() - clk;
+            return Var;
+        }
+    }
+    return MSAT_ORDER_UNKNOWN;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates J-boundary when the variable is assigned.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_OrderVarAssigned( Msat_Order_t * p, int Var )
+{
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the order after a variable is unassigned.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_OrderVarUnassigned( Msat_Order_t * p, int Var )
+{
+//    if (!heap.inHeap(x))
+//        heap.insert(x);
+
+    abctime clk = Abc_Clock();
+    if ( !HINHEAP(p,Var) )
+        Msat_HeapInsert( p, Var );
+timeSelect += Abc_Clock() - clk;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the order after a variable changed weight.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_OrderUpdate( Msat_Order_t * p, int Var )
+{
+//    if (heap.inHeap(x))
+//        heap.increase(x);
+
+    abctime clk = Abc_Clock();
+    if ( HINHEAP(p,Var) )
+        Msat_HeapIncrease( p, Var );
+timeSelect += Abc_Clock() - clk;
+}
+
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Checks the heap property recursively.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_HeapCheck_rec( Msat_Order_t * p, int i )
+{
+    return i >= HSIZE(p) ||
+        (
+            ( HPARENT(i) == 0 || !HCOMPARE(p, HHEAP(p, i), HHEAP(p, HPARENT(i))) ) &&
+
+            Msat_HeapCheck_rec( p, HLEFT(i) ) && 
+            
+            Msat_HeapCheck_rec( p, HRIGHT(i) )
+        );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Retrieves the minimum element.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_HeapGetTop( Msat_Order_t * p )
+{
+    int Result, NewTop;
+    Result                    = HHEAP(p, 1);
+    NewTop                    = Msat_IntVecPop( p->vHeap );
+    p->vHeap->pArray[1]       = NewTop;
+    p->vIndex->pArray[NewTop] = 1;
+    p->vIndex->pArray[Result] = 0;
+    if ( p->vHeap->nSize > 1 )
+        Msat_HeapPercolateDown( p, 1 );
+    return Result;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the new element.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_HeapInsert( Msat_Order_t * p, int n )
+{
+    assert( HOKAY(p, n) );
+    p->vIndex->pArray[n] = HSIZE(p);
+    Msat_IntVecPush( p->vHeap, n );
+    Msat_HeapPercolateUp( p, p->vIndex->pArray[n] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the new element.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_HeapIncrease( Msat_Order_t * p, int n )
+{
+    Msat_HeapPercolateUp( p, p->vIndex->pArray[n] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Moves the entry up.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_HeapPercolateUp( Msat_Order_t * p, int i )
+{
+    int x = HHEAP(p, i);
+    while ( HPARENT(i) != 0 && HCOMPARE(p, x, HHEAP(p, HPARENT(i))) )
+    {
+        p->vHeap->pArray[i]            = HHEAP(p, HPARENT(i));
+        p->vIndex->pArray[HHEAP(p, i)] = i;
+        i                              = HPARENT(i);
+    }
+    p->vHeap->pArray[i]  = x;
+    p->vIndex->pArray[x] = i;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Moves the entry down.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_HeapPercolateDown( Msat_Order_t * p, int i )
+{
+    int x = HHEAP(p, i);
+    int Child;
+    while ( HLEFT(i) < HSIZE(p) )
+    {
+        if ( HRIGHT(i) < HSIZE(p) && HCOMPARE(p, HHEAP(p, HRIGHT(i)), HHEAP(p, HLEFT(i))) )
+            Child = HRIGHT(i);
+        else
+            Child = HLEFT(i);
+        if ( !HCOMPARE(p, HHEAP(p, Child), x) )
+            break;
+        p->vHeap->pArray[i]            = HHEAP(p, Child);
+        p->vIndex->pArray[HHEAP(p, i)] = i;
+        i                              = Child;
+    }
+    p->vHeap->pArray[i]  = x;
+    p->vIndex->pArray[x] = i;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/msat/msatOrderJ.c b/abc-build/src/sat/msat/msatOrderJ.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/msat/msatOrderJ.c
@@ -0,0 +1,477 @@
+/**CFile****************************************************************
+
+  FileName    [msatOrder.c]
+
+  PackageName [A C version of SAT solver MINISAT, originally developed 
+  in C++ by Niklas Een and Niklas Sorensson, Chalmers University of 
+  Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.]
+
+  Synopsis    [The manager of variable assignment.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: msatOrder.c,v 1.0 2005/05/30 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "msatInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/* 
+The J-boundary (justification boundary) is defined as a set of unassigned 
+variables belonging to the cone of interest, such that for each of them,
+there exist an adjacent assigned variable in the cone of interest.
+*/
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Msat_OrderVar_t_  Msat_OrderVar_t;
+typedef struct Msat_OrderRing_t_ Msat_OrderRing_t;
+
+// the variable data structure
+struct Msat_OrderVar_t_
+{
+    Msat_OrderVar_t    * pNext;
+    Msat_OrderVar_t    * pPrev;
+    int                  Num;
+};
+
+// the ring of variables data structure (J-boundary)
+struct Msat_OrderRing_t_
+{
+    Msat_OrderVar_t    * pRoot; 
+    int                 nItems;
+};
+
+// the variable package data structure
+struct Msat_Order_t_
+{
+    Msat_Solver_t *      pSat;         // the SAT solver 
+    Msat_OrderVar_t *    pVars;        // the storage for variables
+    int                 nVarsAlloc;   // the number of variables allocated
+    Msat_OrderRing_t     rVars;        // the J-boundary as a ring of variables
+};
+
+//The solver can communicate to the variable order the following parts:
+//- the array of current assignments (pSat->pAssigns)
+//- the array of variable activities (pSat->pdActivity)
+//- the array of variables currently in the cone (pSat->vConeVars)
+//- the array of arrays of variables adjucent to each(pSat->vAdjacents)
+
+#define Msat_OrderVarIsInBoundary( p, i )   ((p)->pVars[i].pNext)
+#define Msat_OrderVarIsAssigned( p, i )     ((p)->pSat->pAssigns[i] != MSAT_VAR_UNASSIGNED)
+#define Msat_OrderVarIsUsedInCone( p, i )   ((p)->pSat->vVarsUsed->pArray[i])
+
+// iterator through the entries in J-boundary
+#define Msat_OrderRingForEachEntry( pRing, pVar, pNext )         \
+    for ( pVar = pRing,                                         \
+          pNext = pVar? pVar->pNext : NULL;                     \
+          pVar;                                                 \
+          pVar = (pNext != pRing)? pNext : NULL,                \
+          pNext = pVar? pVar->pNext : NULL )
+
+static void Msat_OrderRingAddLast( Msat_OrderRing_t * pRing, Msat_OrderVar_t * pVar );
+static void Msat_OrderRingRemove( Msat_OrderRing_t * pRing, Msat_OrderVar_t * pVar );
+
+extern clock_t timeSelect;
+extern clock_t timeAssign;
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the ordering structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_Order_t * Msat_OrderAlloc( Msat_Solver_t * pSat )
+{
+    Msat_Order_t * p;
+    p = ALLOC( Msat_Order_t, 1 );
+    memset( p, 0, sizeof(Msat_Order_t) );
+    p->pSat = pSat;
+    Msat_OrderSetBounds( p, pSat->nVarsAlloc );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets the bound of the ordering structure.]
+
+  Description [Should be called whenever the SAT solver is resized.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_OrderSetBounds( Msat_Order_t * p, int nVarsMax )
+{
+    int i;
+    // add variables if they are missing
+    if ( p->nVarsAlloc < nVarsMax )
+    {
+        p->pVars = REALLOC( Msat_OrderVar_t, p->pVars, nVarsMax );
+        for ( i = p->nVarsAlloc; i < nVarsMax; i++ )
+        {
+            p->pVars[i].pNext = p->pVars[i].pPrev = NULL;
+            p->pVars[i].Num = i;
+        }
+        p->nVarsAlloc = nVarsMax;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the ordering structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_OrderClean( Msat_Order_t * p, Msat_IntVec_t * vCone )
+{
+    Msat_OrderVar_t * pVar, * pNext;
+    // quickly undo the ring
+    Msat_OrderRingForEachEntry( p->rVars.pRoot, pVar, pNext )
+        pVar->pNext = pVar->pPrev = NULL;
+    p->rVars.pRoot  = NULL;
+    p->rVars.nItems = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks that the J-boundary is okay.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_OrderCheck( Msat_Order_t * p )
+{
+    Msat_OrderVar_t * pVar, * pNext;
+    Msat_IntVec_t * vRound;
+    int * pRound, nRound;
+    int * pVars, nVars, i, k;
+    int Counter = 0;
+
+    // go through all the variables in the boundary
+    Msat_OrderRingForEachEntry( p->rVars.pRoot, pVar, pNext )
+    {
+        assert( !Msat_OrderVarIsAssigned(p, pVar->Num) );
+        // go though all the variables in the neighborhood
+        // and check that it is true that there is least one assigned
+        vRound = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( p->pSat->vAdjacents, pVar->Num );
+        nRound = Msat_IntVecReadSize( vRound );
+        pRound = Msat_IntVecReadArray( vRound );
+        for ( i = 0; i < nRound; i++ )
+        {
+            if ( !Msat_OrderVarIsUsedInCone(p, pRound[i]) )
+                continue;
+            if ( Msat_OrderVarIsAssigned(p, pRound[i]) )
+                break;
+        }
+//        assert( i != nRound );
+//        if ( i == nRound )
+//            return 0;
+        if ( i == nRound )
+            Counter++;
+    }
+    if ( Counter > 0 )
+        printf( "%d(%d) ", Counter, p->rVars.nItems );
+
+    // we may also check other unassigned variables in the cone
+    // to make sure that if they are not in J-boundary, 
+    // then they do not have an assigned neighbor
+    nVars = Msat_IntVecReadSize( p->pSat->vConeVars );
+    pVars = Msat_IntVecReadArray( p->pSat->vConeVars );
+    for ( i = 0; i < nVars; i++ )
+    {
+        assert( Msat_OrderVarIsUsedInCone(p, pVars[i]) );
+        // skip assigned vars, vars in the boundary, and vars not used in the cone
+        if ( Msat_OrderVarIsAssigned(p, pVars[i]) || 
+             Msat_OrderVarIsInBoundary(p, pVars[i]) )
+            continue;
+        // make sure, it does not have assigned neighbors
+        vRound = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( p->pSat->vAdjacents, pVars[i] );
+        nRound = Msat_IntVecReadSize( vRound );
+        pRound = Msat_IntVecReadArray( vRound );
+        for ( k = 0; k < nRound; k++ )
+        {
+            if ( !Msat_OrderVarIsUsedInCone(p, pRound[k]) )
+                continue;
+            if ( Msat_OrderVarIsAssigned(p, pRound[k]) )
+                break;
+        }
+//        assert( k == nRound );
+//        if ( k != nRound )
+//            return 0;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the ordering structure.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_OrderFree( Msat_Order_t * p )
+{
+    free( p->pVars );
+    free( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Selects the next variable to assign.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_OrderVarSelect( Msat_Order_t * p )
+{
+    Msat_OrderVar_t * pVar, * pNext, * pVarBest;
+    double * pdActs = p->pSat->pdActivity;
+    double dfActBest;
+//    clock_t clk = clock();
+
+    pVarBest = NULL;
+    dfActBest = -1.0;
+    Msat_OrderRingForEachEntry( p->rVars.pRoot, pVar, pNext )
+    {
+        if ( dfActBest < pdActs[pVar->Num] )
+        {
+            dfActBest = pdActs[pVar->Num];
+            pVarBest  = pVar;
+        }
+    }
+//timeSelect += clock() - clk;
+//timeAssign += clock() - clk;
+
+//if ( pVarBest && pVarBest->Num % 1000 == 0 )
+//printf( "%d ", p->rVars.nItems );
+
+//    Msat_OrderCheck( p );
+    if ( pVarBest )
+    {
+        assert( Msat_OrderVarIsUsedInCone(p, pVarBest->Num) );
+        return pVarBest->Num;
+    }
+    return MSAT_ORDER_UNKNOWN;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates J-boundary when the variable is assigned.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_OrderVarAssigned( Msat_Order_t * p, int Var )
+{
+    Msat_IntVec_t * vRound;
+    int i;//, clk = clock();
+
+    // make sure the variable is in the boundary
+    assert( Var < p->nVarsAlloc );
+    // if it is not in the boundary (initial decision, random decision), do not remove
+    if ( Msat_OrderVarIsInBoundary( p, Var ) )
+        Msat_OrderRingRemove( &p->rVars, &p->pVars[Var] );
+    // add to the boundary those neighbors that are (1) unassigned, (2) not in boundary
+    // because for them we know that there is a variable (Var) which is assigned
+    vRound = (Msat_IntVec_t *)p->pSat->vAdjacents->pArray[Var];
+    for ( i = 0; i < vRound->nSize; i++ )
+    {
+        if ( !Msat_OrderVarIsUsedInCone(p, vRound->pArray[i]) )
+            continue;
+        if ( Msat_OrderVarIsAssigned(p, vRound->pArray[i]) )
+            continue;
+        if ( Msat_OrderVarIsInBoundary(p, vRound->pArray[i]) )
+            continue;
+        Msat_OrderRingAddLast( &p->rVars, &p->pVars[vRound->pArray[i]] );
+    }
+//timeSelect += clock() - clk;
+//    Msat_OrderCheck( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the order after a variable is unassigned.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_OrderVarUnassigned( Msat_Order_t * p, int Var )
+{
+    Msat_IntVec_t * vRound, * vRound2;
+    int i, k;//, clk = clock();
+
+    // make sure the variable is not in the boundary
+    assert( Var < p->nVarsAlloc );
+    assert( !Msat_OrderVarIsInBoundary( p, Var ) );
+    // go through its neigbors - if one of them is assigned add this var
+    // add to the boundary those neighbors that are not there already
+    // this will also get rid of variable outside of the current cone
+    // because they are unassigned in Msat_SolverPrepare()
+    vRound = (Msat_IntVec_t *)p->pSat->vAdjacents->pArray[Var];
+    for ( i = 0; i < vRound->nSize; i++ )
+        if ( Msat_OrderVarIsAssigned(p, vRound->pArray[i]) ) 
+            break;
+    if ( i != vRound->nSize )
+        Msat_OrderRingAddLast( &p->rVars, &p->pVars[Var] );
+
+    // unassigning a variable may lead to its adjacents dropping from the boundary
+    for ( i = 0; i < vRound->nSize; i++ )
+        if ( Msat_OrderVarIsInBoundary(p, vRound->pArray[i]) )
+        { // the neighbor is in the J-boundary (and unassigned)
+            assert( !Msat_OrderVarIsAssigned(p, vRound->pArray[i]) );
+            vRound2 = (Msat_IntVec_t *)p->pSat->vAdjacents->pArray[vRound->pArray[i]];
+            // go through its neighbors and determine if there is at least one assigned
+            for ( k = 0; k < vRound2->nSize; k++ )
+                if ( Msat_OrderVarIsAssigned(p, vRound2->pArray[k]) ) 
+                    break;
+            if ( k == vRound2->nSize ) // there is no assigned vars, delete this one
+                Msat_OrderRingRemove( &p->rVars, &p->pVars[vRound->pArray[i]] );
+        }
+//timeSelect += clock() - clk;
+//    Msat_OrderCheck( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Updates the order after a variable changed weight.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_OrderUpdate( Msat_Order_t * p, int Var )
+{
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Adds node to the end of the ring.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_OrderRingAddLast( Msat_OrderRing_t * pRing, Msat_OrderVar_t * pVar )
+{
+//printf( "adding %d\n", pVar->Num );
+    // check that the node is not in a ring
+    assert( pVar->pPrev == NULL );
+    assert( pVar->pNext == NULL );
+    // if the ring is empty, make the node point to itself
+    pRing->nItems++;
+    if ( pRing->pRoot == NULL )
+    {
+        pRing->pRoot  = pVar;
+        pVar->pPrev  = pVar;
+        pVar->pNext  = pVar;
+        return;
+    }
+    // if the ring is not empty, add it as the last entry
+    pVar->pPrev = pRing->pRoot->pPrev;
+    pVar->pNext = pRing->pRoot;
+    pVar->pPrev->pNext = pVar;
+    pVar->pNext->pPrev = pVar;
+
+    // move the root so that it points to the new entry
+//    pRing->pRoot = pRing->pRoot->pPrev;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes the node from the ring.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_OrderRingRemove( Msat_OrderRing_t * pRing, Msat_OrderVar_t * pVar )
+{
+//printf( "removing %d\n", pVar->Num );
+    // check that the var is in a ring
+    assert( pVar->pPrev );
+    assert( pVar->pNext );
+    pRing->nItems--;
+    if ( pRing->nItems == 0 )
+    {
+        assert( pRing->pRoot == pVar );
+        pVar->pPrev = NULL;
+        pVar->pNext = NULL;
+        pRing->pRoot = NULL;
+        return;
+    }
+    // move the root if needed
+    if ( pRing->pRoot == pVar )
+        pRing->pRoot = pVar->pNext;
+    // move the root to the next entry after pVar
+    // this way all the additions to the list will be traversed first
+//    pRing->pRoot = pVar->pPrev;
+    // delete the node
+    pVar->pPrev->pNext = pVar->pNext;
+    pVar->pNext->pPrev = pVar->pPrev;
+    pVar->pPrev = NULL;
+    pVar->pNext = NULL;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/msat/msatQueue.c b/abc-build/src/sat/msat/msatQueue.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/msat/msatQueue.c
@@ -0,0 +1,162 @@
+/**CFile****************************************************************
+
+  FileName    [msatQueue.c]
+
+  PackageName [A C version of SAT solver MINISAT, originally developed 
+  in C++ by Niklas Een and Niklas Sorensson, Chalmers University of 
+  Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.]
+
+  Synopsis    [The manager of the assignment propagation queue.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: msatQueue.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "msatInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+struct Msat_Queue_t_ 
+{
+    int         nVars;
+    int *       pVars;
+    int         iFirst;
+    int         iLast;
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the variable propagation queue.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_Queue_t * Msat_QueueAlloc( int nVars )
+{
+    Msat_Queue_t * p;
+    p = ABC_ALLOC( Msat_Queue_t, 1 );
+    memset( p, 0, sizeof(Msat_Queue_t) );
+    p->nVars  = nVars;
+    p->pVars  = ABC_ALLOC( int, nVars );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocate the variable propagation queue.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_QueueFree( Msat_Queue_t * p )
+{
+    ABC_FREE( p->pVars );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the queue size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_QueueReadSize( Msat_Queue_t * p )
+{
+    return p->iLast - p->iFirst;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Insert an entry into the queue.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_QueueInsert( Msat_Queue_t * p, int Lit )
+{
+    if ( p->iLast == p->nVars )
+    {
+        int i;
+        assert( 0 );
+        for ( i = 0; i < p->iLast; i++ )
+            printf( "entry = %2d  lit = %2d  var = %2d \n", i, p->pVars[i], p->pVars[i]/2 );
+    }
+    assert( p->iLast < p->nVars );
+    p->pVars[p->iLast++] = Lit;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Extracts an entry from the queue.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_QueueExtract( Msat_Queue_t * p )
+{
+    if ( p->iFirst == p->iLast )
+        return -1;
+    return p->pVars[p->iFirst++];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resets the queue.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_QueueClear( Msat_Queue_t * p )
+{
+    p->iFirst = 0;
+    p->iLast  = 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/msat/msatRead.c b/abc-build/src/sat/msat/msatRead.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/msat/msatRead.c
@@ -0,0 +1,274 @@
+/**CFile****************************************************************
+
+  FileName    [msatRead.c]
+
+  PackageName [A C version of SAT solver MINISAT, originally developed 
+  in C++ by Niklas Een and Niklas Sorensson, Chalmers University of 
+  Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.]
+
+  Synopsis    [The reader of the CNF formula in DIMACS format.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: msatRead.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "msatInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static char * Msat_FileRead( FILE * pFile );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Read the file into the internal buffer.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Msat_FileRead( FILE * pFile )
+{
+    int nFileSize;
+    char * pBuffer;
+    int RetValue;
+    // get the file size, in bytes
+    fseek( pFile, 0, SEEK_END );  
+    nFileSize = ftell( pFile );  
+    // move the file current reading position to the beginning
+    rewind( pFile ); 
+    // load the contents of the file into memory
+    pBuffer = ABC_ALLOC( char, nFileSize + 3 );
+    RetValue = fread( pBuffer, nFileSize, 1, pFile );
+    // terminate the string with '\0'
+    pBuffer[ nFileSize + 0] = '\n';
+    pBuffer[ nFileSize + 1] = '\0';
+    return pBuffer;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Msat_ReadWhitespace( char ** pIn ) 
+{
+    while ((**pIn >= 9 && **pIn <= 13) || **pIn == 32)
+        (*pIn)++; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Msat_ReadNotWhitespace( char ** pIn ) 
+{
+    while ( !((**pIn >= 9 && **pIn <= 13) || **pIn == 32) )
+        (*pIn)++; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void skipLine( char ** pIn ) 
+{
+    while ( 1 )
+    {
+        if (**pIn == 0) 
+            return;
+        if (**pIn == '\n') 
+        { 
+            (*pIn)++; 
+            return; 
+        }
+        (*pIn)++; 
+    } 
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int Msat_ReadInt( char ** pIn ) 
+{
+    int     val = 0;
+    int     neg = 0;
+
+    Msat_ReadWhitespace( pIn );
+    if ( **pIn == '-' ) 
+        neg = 1, 
+        (*pIn)++;
+    else if ( **pIn == '+' ) 
+        (*pIn)++;
+    if ( **pIn < '0' || **pIn > '9' ) 
+        fprintf(stderr, "PARSE ERROR! Unexpected char: %c\n", **pIn), 
+        exit(1);
+    while ( **pIn >= '0' && **pIn <= '9' )
+        val = val*10 + (**pIn - '0'),
+        (*pIn)++;
+    return neg ? -val : val; 
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static void Msat_ReadClause( char ** pIn, Msat_Solver_t * p, Msat_IntVec_t * pLits ) 
+{
+    int nVars = Msat_SolverReadVarNum( p );
+    int parsed_lit, var, sign;
+
+    Msat_IntVecClear( pLits );
+    while ( 1 )
+    {
+        parsed_lit = Msat_ReadInt(pIn);
+        if ( parsed_lit == 0 ) 
+            break;
+        var = abs(parsed_lit) - 1;
+        sign = (parsed_lit > 0);
+        if ( var >= nVars )
+        {
+            printf( "Variable %d is larger than the number of allocated variables (%d).\n", var+1, nVars );
+            exit(1);
+        }
+        Msat_IntVecPush( pLits, MSAT_VAR2LIT(var, !sign) );
+    }
+}
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static int  Msat_ReadDimacs( char * pText, Msat_Solver_t ** pS, int  fVerbose ) 
+{
+    Msat_Solver_t * p = NULL; // Suppress "might be used uninitialized"
+    Msat_IntVec_t * pLits = NULL; // Suppress "might be used uninitialized"
+    char * pIn = pText;
+    int nVars, nClas;
+    while ( 1 )
+    {
+        Msat_ReadWhitespace( &pIn );
+        if ( *pIn == 0 )
+            break;
+        else if ( *pIn == 'c' )
+            skipLine( &pIn );
+        else if ( *pIn == 'p' )
+        {
+            pIn++;
+            Msat_ReadWhitespace( &pIn );
+            Msat_ReadNotWhitespace( &pIn );
+
+            nVars = Msat_ReadInt( &pIn );
+            nClas = Msat_ReadInt( &pIn );
+            skipLine( &pIn );
+            // start the solver
+            p = Msat_SolverAlloc( nVars, 1, 1, 1, 1, 0 ); 
+            Msat_SolverClean( p, nVars );
+            Msat_SolverSetVerbosity( p, fVerbose );
+            // allocate the vector
+            pLits = Msat_IntVecAlloc( nVars );
+        }
+        else
+        {
+            if ( p == NULL )
+            {
+                printf( "There is no parameter line.\n" );
+                exit(1);
+            }
+            Msat_ReadClause( &pIn, p, pLits );
+            if ( !Msat_SolverAddClause( p, pLits ) )
+                return 0;
+        }
+    }
+    Msat_IntVecFree( pLits );
+    *pS = p;
+    return Msat_SolverSimplifyDB( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the solver and reads the DIMAC file.]
+
+  Description [Returns FALSE upon immediate conflict.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int  Msat_SolverParseDimacs( FILE * pFile, Msat_Solver_t ** p, int fVerbose )
+{
+    char * pText;
+    int  Value;
+    pText = Msat_FileRead( pFile );
+    Value = Msat_ReadDimacs( pText, p, fVerbose );
+    ABC_FREE( pText );
+    return Value;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/msat/msatSolverApi.c b/abc-build/src/sat/msat/msatSolverApi.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/msat/msatSolverApi.c
@@ -0,0 +1,505 @@
+/**CFile****************************************************************
+
+  FileName    [msatSolverApi.c]
+
+  PackageName [A C version of SAT solver MINISAT, originally developed 
+  in C++ by Niklas Een and Niklas Sorensson, Chalmers University of 
+  Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.]
+
+  Synopsis    [APIs of the SAT solver.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: msatSolverApi.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "msatInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void Msat_SolverSetupTruthTables( unsigned uTruths[][2] );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Simple SAT solver APIs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int                Msat_SolverReadVarNum( Msat_Solver_t * p )                  { return p->nVars;      }
+int                Msat_SolverReadClauseNum( Msat_Solver_t * p )               { return p->nClauses;   }
+int                Msat_SolverReadVarAllocNum( Msat_Solver_t * p )             { return p->nVarsAlloc; }
+int                Msat_SolverReadDecisionLevel( Msat_Solver_t * p )           { return Msat_IntVecReadSize(p->vTrailLim); }
+int *              Msat_SolverReadDecisionLevelArray( Msat_Solver_t * p )      { return p->pLevel;     }
+Msat_Clause_t **    Msat_SolverReadReasonArray( Msat_Solver_t * p )            { return p->pReasons;   }
+Msat_Type_t         Msat_SolverReadVarValue( Msat_Solver_t * p, Msat_Var_t Var ) { return (Msat_Type_t)p->pAssigns[Var]; }
+Msat_ClauseVec_t *  Msat_SolverReadLearned( Msat_Solver_t * p )                { return p->vLearned;   }
+Msat_ClauseVec_t ** Msat_SolverReadWatchedArray( Msat_Solver_t * p )           { return p->pvWatched;  }
+int *              Msat_SolverReadAssignsArray( Msat_Solver_t * p )            { return p->pAssigns;   }
+int *              Msat_SolverReadModelArray( Msat_Solver_t * p )              { return p->pModel;     }
+int                Msat_SolverReadBackTracks( Msat_Solver_t * p )              { return (int)p->Stats.nConflicts; }
+int                Msat_SolverReadInspects( Msat_Solver_t * p )                { return (int)p->Stats.nInspects;  }
+Msat_MmStep_t *     Msat_SolverReadMem( Msat_Solver_t * p )                    { return p->pMem;       }
+int *              Msat_SolverReadSeenArray( Msat_Solver_t * p )               { return p->pSeen;      }
+int                Msat_SolverIncrementSeenId( Msat_Solver_t * p )             { return ++p->nSeenId;  }
+void               Msat_SolverSetVerbosity( Msat_Solver_t * p, int fVerbose )  { p->fVerbose = fVerbose; }
+void               Msat_SolverClausesIncrement( Msat_Solver_t * p )            { p->nClausesAlloc++;   }
+void               Msat_SolverClausesDecrement( Msat_Solver_t * p )            { p->nClausesAlloc--;   }
+void               Msat_SolverClausesIncrementL( Msat_Solver_t * p )           { p->nClausesAllocL++;  }
+void               Msat_SolverClausesDecrementL( Msat_Solver_t * p )           { p->nClausesAllocL--;  }
+void               Msat_SolverMarkLastClauseTypeA( Msat_Solver_t * p )         { Msat_ClauseSetTypeA( Msat_ClauseVecReadEntry( p->vClauses, Msat_ClauseVecReadSize(p->vClauses)-1 ), 1 ); }
+void               Msat_SolverMarkClausesStart( Msat_Solver_t * p )            { p->nClausesStart = Msat_ClauseVecReadSize(p->vClauses); }
+float *            Msat_SolverReadFactors( Msat_Solver_t * p )                 { return p->pFactors;   }
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the clause with the given number.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_Clause_t * Msat_SolverReadClause( Msat_Solver_t * p, int Num )
+{
+    int nClausesP;
+    assert( Num < p->nClauses );
+    nClausesP = Msat_ClauseVecReadSize( p->vClauses );
+    if ( Num < nClausesP )
+        return Msat_ClauseVecReadEntry( p->vClauses, Num );
+    return Msat_ClauseVecReadEntry( p->vLearned, Num - nClausesP );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the clause with the given number.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_ClauseVec_t *  Msat_SolverReadAdjacents( Msat_Solver_t * p )
+{
+    return p->vAdjacents;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the clause with the given number.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_IntVec_t *  Msat_SolverReadConeVars( Msat_Solver_t * p )
+{
+    return p->vConeVars;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads the clause with the given number.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_IntVec_t *  Msat_SolverReadVarsUsed( Msat_Solver_t * p )
+{
+    return p->vVarsUsed;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates the solver.]
+
+  Description [After the solver is allocated, the procedure
+  Msat_SolverClean() should be called to set the number of variables.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_Solver_t * Msat_SolverAlloc( int nVarsAlloc,
+    double dClaInc, double dClaDecay, 
+    double dVarInc, double dVarDecay, 
+    int  fVerbose )
+{
+    Msat_Solver_t * p;
+    int i;
+
+    assert(sizeof(Msat_Lit_t) == sizeof(unsigned));
+    assert(sizeof(float)     == sizeof(unsigned));
+
+    p = ABC_ALLOC( Msat_Solver_t, 1 );
+    memset( p, 0, sizeof(Msat_Solver_t) );
+
+    p->nVarsAlloc = nVarsAlloc;
+    p->nVars     = 0;
+
+    p->nClauses  = 0;
+    p->vClauses  = Msat_ClauseVecAlloc( 512 );
+    p->vLearned  = Msat_ClauseVecAlloc( 512 );
+
+    p->dClaInc   = dClaInc;
+    p->dClaDecay = dClaDecay;
+    p->dVarInc   = dVarInc;
+    p->dVarDecay = dVarDecay;
+
+    p->pdActivity = ABC_ALLOC( double, p->nVarsAlloc );
+    p->pFactors   = ABC_ALLOC( float, p->nVarsAlloc );
+    for ( i = 0; i < p->nVarsAlloc; i++ )
+    {
+        p->pdActivity[i] = 0.0;
+        p->pFactors[i]   = 1.0;
+    }
+
+    p->pAssigns  = ABC_ALLOC( int, p->nVarsAlloc ); 
+    p->pModel    = ABC_ALLOC( int, p->nVarsAlloc ); 
+    for ( i = 0; i < p->nVarsAlloc; i++ )
+        p->pAssigns[i] = MSAT_VAR_UNASSIGNED;
+//    p->pOrder    = Msat_OrderAlloc( p->pAssigns, p->pdActivity, p->nVarsAlloc );
+    p->pOrder    = Msat_OrderAlloc( p );
+
+    p->pvWatched = ABC_ALLOC( Msat_ClauseVec_t *, 2 * p->nVarsAlloc );
+    for ( i = 0; i < 2 * p->nVarsAlloc; i++ )
+        p->pvWatched[i] = Msat_ClauseVecAlloc( 16 );
+    p->pQueue    = Msat_QueueAlloc( p->nVarsAlloc );
+
+    p->vTrail    = Msat_IntVecAlloc( p->nVarsAlloc );
+    p->vTrailLim = Msat_IntVecAlloc( p->nVarsAlloc );
+    p->pReasons  = ABC_ALLOC( Msat_Clause_t *, p->nVarsAlloc );
+    memset( p->pReasons, 0, sizeof(Msat_Clause_t *) * p->nVarsAlloc );
+    p->pLevel = ABC_ALLOC( int, p->nVarsAlloc );
+    for ( i = 0; i < p->nVarsAlloc; i++ )
+        p->pLevel[i] = -1;
+    p->dRandSeed = 91648253;
+    p->fVerbose  = fVerbose;
+    p->dProgress = 0.0;
+//    p->pModel = Msat_IntVecAlloc( p->nVarsAlloc );
+    p->pMem = Msat_MmStepStart( 10 );
+
+    p->vConeVars   = Msat_IntVecAlloc( p->nVarsAlloc ); 
+    p->vAdjacents  = Msat_ClauseVecAlloc( p->nVarsAlloc );
+    for ( i = 0; i < p->nVarsAlloc; i++ )
+        Msat_ClauseVecPush( p->vAdjacents, (Msat_Clause_t *)Msat_IntVecAlloc(5) );
+    p->vVarsUsed   = Msat_IntVecAlloc( p->nVarsAlloc ); 
+    Msat_IntVecFill( p->vVarsUsed, p->nVarsAlloc, 1 );
+
+
+    p->pSeen     = ABC_ALLOC( int, p->nVarsAlloc );
+    memset( p->pSeen, 0, sizeof(int) * p->nVarsAlloc );
+    p->nSeenId   = 1;
+    p->vReason   = Msat_IntVecAlloc( p->nVarsAlloc );
+    p->vTemp     = Msat_IntVecAlloc( p->nVarsAlloc );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the solver.]
+
+  Description [Assumes that the solver contains some clauses, and that 
+  it is currently between the calls. Resizes the solver to accomodate 
+  more variables.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverResize( Msat_Solver_t * p, int nVarsAlloc )
+{
+    int nVarsAllocOld, i;
+
+    nVarsAllocOld = p->nVarsAlloc;
+    p->nVarsAlloc = nVarsAlloc;
+
+    p->pdActivity = ABC_REALLOC( double, p->pdActivity, p->nVarsAlloc );
+    p->pFactors   = ABC_REALLOC( float, p->pFactors, p->nVarsAlloc );
+    for ( i = nVarsAllocOld; i < p->nVarsAlloc; i++ )
+    {
+        p->pdActivity[i] = 0.0;
+        p->pFactors[i]   = 1.0;
+    }
+
+    p->pAssigns  = ABC_REALLOC( int, p->pAssigns, p->nVarsAlloc );
+    p->pModel    = ABC_REALLOC( int, p->pModel, p->nVarsAlloc );
+    for ( i = nVarsAllocOld; i < p->nVarsAlloc; i++ )
+        p->pAssigns[i] = MSAT_VAR_UNASSIGNED;
+
+//    Msat_OrderRealloc( p->pOrder, p->pAssigns, p->pdActivity, p->nVarsAlloc );
+    Msat_OrderSetBounds( p->pOrder, p->nVarsAlloc );
+
+    p->pvWatched = ABC_REALLOC( Msat_ClauseVec_t *, p->pvWatched, 2 * p->nVarsAlloc );
+    for ( i = 2 * nVarsAllocOld; i < 2 * p->nVarsAlloc; i++ )
+        p->pvWatched[i] = Msat_ClauseVecAlloc( 16 );
+
+    Msat_QueueFree( p->pQueue );
+    p->pQueue    = Msat_QueueAlloc( p->nVarsAlloc );
+
+    p->pReasons  = ABC_REALLOC( Msat_Clause_t *, p->pReasons, p->nVarsAlloc );
+    p->pLevel    = ABC_REALLOC( int, p->pLevel, p->nVarsAlloc );
+    for ( i = nVarsAllocOld; i < p->nVarsAlloc; i++ )
+    {
+        p->pReasons[i] = NULL;
+        p->pLevel[i] = -1;
+    }
+
+    p->pSeen     = ABC_REALLOC( int, p->pSeen, p->nVarsAlloc );
+    for ( i = nVarsAllocOld; i < p->nVarsAlloc; i++ )
+        p->pSeen[i] = 0;
+
+    Msat_IntVecGrow( p->vTrail, p->nVarsAlloc );
+    Msat_IntVecGrow( p->vTrailLim, p->nVarsAlloc );
+
+    // make sure the array of adjucents has room to store the variable numbers
+    for ( i = Msat_ClauseVecReadSize(p->vAdjacents); i < p->nVarsAlloc; i++ )
+        Msat_ClauseVecPush( p->vAdjacents, (Msat_Clause_t *)Msat_IntVecAlloc(5) );
+    Msat_IntVecFill( p->vVarsUsed, p->nVarsAlloc, 1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the solver.]
+
+  Description [Cleans the solver assuming that the problem will involve 
+  the given number of variables (nVars). This procedure is useful 
+  for many small (incremental) SAT problems, to prevent the solver
+  from being reallocated each time.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverClean( Msat_Solver_t * p, int nVars )
+{
+    int i;
+    // free the clauses
+    int nClauses;
+    Msat_Clause_t ** pClauses;
+
+    assert( p->nVarsAlloc >= nVars );
+    p->nVars    = nVars;
+    p->nClauses = 0;
+
+    nClauses = Msat_ClauseVecReadSize( p->vClauses );
+    pClauses = Msat_ClauseVecReadArray( p->vClauses );
+    for ( i = 0; i < nClauses; i++ )
+        Msat_ClauseFree( p, pClauses[i], 0 );
+//    Msat_ClauseVecFree( p->vClauses );
+    Msat_ClauseVecClear( p->vClauses );
+
+    nClauses = Msat_ClauseVecReadSize( p->vLearned );
+    pClauses = Msat_ClauseVecReadArray( p->vLearned );
+    for ( i = 0; i < nClauses; i++ )
+        Msat_ClauseFree( p, pClauses[i], 0 );
+//    Msat_ClauseVecFree( p->vLearned );
+    Msat_ClauseVecClear( p->vLearned );
+
+//    ABC_FREE( p->pdActivity );
+    for ( i = 0; i < p->nVars; i++ )
+        p->pdActivity[i] = 0;
+
+//    Msat_OrderFree( p->pOrder );
+//    Msat_OrderClean( p->pOrder, p->nVars, NULL );
+    Msat_OrderSetBounds( p->pOrder, p->nVars );
+
+    for ( i = 0; i < 2 * p->nVars; i++ )
+//        Msat_ClauseVecFree( p->pvWatched[i] );
+        Msat_ClauseVecClear( p->pvWatched[i] );
+//    ABC_FREE( p->pvWatched );
+//    Msat_QueueFree( p->pQueue );
+    Msat_QueueClear( p->pQueue );
+
+//    ABC_FREE( p->pAssigns );
+    for ( i = 0; i < p->nVars; i++ )
+        p->pAssigns[i] = MSAT_VAR_UNASSIGNED;
+//    Msat_IntVecFree( p->vTrail );
+    Msat_IntVecClear( p->vTrail );
+//    Msat_IntVecFree( p->vTrailLim );
+    Msat_IntVecClear( p->vTrailLim );
+//    ABC_FREE( p->pReasons );
+    memset( p->pReasons, 0, sizeof(Msat_Clause_t *) * p->nVars );
+//    ABC_FREE( p->pLevel );
+    for ( i = 0; i < p->nVars; i++ )
+        p->pLevel[i] = -1;
+//    Msat_IntVecFree( p->pModel );
+//    Msat_MmStepStop( p->pMem, 0 );
+    p->dRandSeed = 91648253;
+    p->dProgress = 0.0;
+
+//    ABC_FREE( p->pSeen );
+    memset( p->pSeen, 0, sizeof(int) * p->nVars );
+    p->nSeenId = 1;
+//    Msat_IntVecFree( p->vReason );
+    Msat_IntVecClear( p->vReason );
+//    Msat_IntVecFree( p->vTemp );
+    Msat_IntVecClear( p->vTemp );
+//    printf(" The number of clauses remaining = %d (%d).\n", p->nClausesAlloc, p->nClausesAllocL );
+//    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverFree( Msat_Solver_t * p )
+{
+    int i;
+
+    // free the clauses
+    int nClauses;
+    Msat_Clause_t ** pClauses;
+//printf( "clauses = %d. learned = %d.\n", Msat_ClauseVecReadSize( p->vClauses ), 
+//                                         Msat_ClauseVecReadSize( p->vLearned ) );
+
+    nClauses = Msat_ClauseVecReadSize( p->vClauses );
+    pClauses = Msat_ClauseVecReadArray( p->vClauses );
+    for ( i = 0; i < nClauses; i++ )
+        Msat_ClauseFree( p, pClauses[i], 0 );
+    Msat_ClauseVecFree( p->vClauses );
+
+    nClauses = Msat_ClauseVecReadSize( p->vLearned );
+    pClauses = Msat_ClauseVecReadArray( p->vLearned );
+    for ( i = 0; i < nClauses; i++ )
+        Msat_ClauseFree( p, pClauses[i], 0 );
+    Msat_ClauseVecFree( p->vLearned );
+
+    ABC_FREE( p->pdActivity );
+    ABC_FREE( p->pFactors );
+    Msat_OrderFree( p->pOrder );
+
+    for ( i = 0; i < 2 * p->nVarsAlloc; i++ )
+        Msat_ClauseVecFree( p->pvWatched[i] );
+    ABC_FREE( p->pvWatched );
+    Msat_QueueFree( p->pQueue );
+
+    ABC_FREE( p->pAssigns );
+    ABC_FREE( p->pModel );
+    Msat_IntVecFree( p->vTrail );
+    Msat_IntVecFree( p->vTrailLim );
+    ABC_FREE( p->pReasons );
+    ABC_FREE( p->pLevel );
+
+    Msat_MmStepStop( p->pMem, 0 );
+
+    nClauses = Msat_ClauseVecReadSize( p->vAdjacents );
+    pClauses = Msat_ClauseVecReadArray( p->vAdjacents );
+    for ( i = 0; i < nClauses; i++ )
+        Msat_IntVecFree( (Msat_IntVec_t *)pClauses[i] );
+    Msat_ClauseVecFree( p->vAdjacents );
+    Msat_IntVecFree( p->vConeVars );
+    Msat_IntVecFree( p->vVarsUsed );
+
+    ABC_FREE( p->pSeen );
+    Msat_IntVecFree( p->vReason );
+    Msat_IntVecFree( p->vTemp );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares the solver to run on a subset of variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverPrepare( Msat_Solver_t * p, Msat_IntVec_t * vVars )
+{
+
+    int i;
+    // undo the previous data
+    for ( i = 0; i < p->nVarsAlloc; i++ )
+    {
+        p->pAssigns[i]   = MSAT_VAR_UNASSIGNED;
+        p->pReasons[i]   = NULL;
+        p->pLevel[i]     = -1;
+        p->pdActivity[i] = 0.0;
+    }
+
+    // set the new variable order
+    Msat_OrderClean( p->pOrder, vVars );
+
+    Msat_QueueClear( p->pQueue );
+    Msat_IntVecClear( p->vTrail );
+    Msat_IntVecClear( p->vTrailLim );
+    p->dProgress = 0.0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sets up the truth tables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverSetupTruthTables( unsigned uTruths[][2] )
+{
+    int m, v;
+    // set up the truth tables
+    for ( m = 0; m < 32; m++ )
+        for ( v = 0; v < 5; v++ )
+            if ( m & (1 << v) )
+                uTruths[v][0] |= (1 << m);
+    // make adjustments for the case of 6 variables
+    for ( v = 0; v < 5; v++ )
+        uTruths[v][1] = uTruths[v][0];
+    uTruths[5][0] = 0;
+    uTruths[5][1] = ~((unsigned)0);
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/msat/msatSolverCore.c b/abc-build/src/sat/msat/msatSolverCore.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/msat/msatSolverCore.c
@@ -0,0 +1,215 @@
+/**CFile****************************************************************
+
+  FileName    [msatSolverCore.c]
+
+  PackageName [A C version of SAT solver MINISAT, originally developed 
+  in C++ by Niklas Een and Niklas Sorensson, Chalmers University of 
+  Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.]
+
+  Synopsis    [The SAT solver core procedures.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: msatSolverCore.c,v 1.2 2004/05/12 03:37:40 satrajit Exp $]
+
+***********************************************************************/
+
+#include "msatInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one variable to the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int  Msat_SolverAddVar( Msat_Solver_t * p, int Level )
+{
+    if ( p->nVars == p->nVarsAlloc )
+        Msat_SolverResize( p, 2 * p->nVarsAlloc );
+    p->pLevel[p->nVars] = Level;
+    p->nVars++;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one clause to the solver's clause database.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int  Msat_SolverAddClause( Msat_Solver_t * p, Msat_IntVec_t * vLits )
+{
+    Msat_Clause_t * pC; 
+    int  Value;
+    Value = Msat_ClauseCreate( p, vLits, 0, &pC );
+    if ( pC != NULL )
+        Msat_ClauseVecPush( p->vClauses, pC );
+//    else if ( p->fProof )
+//        Msat_ClauseCreateFake( p, vLits );
+    return Value;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns search-space coverage. Not extremely reliable.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+double Msat_SolverProgressEstimate( Msat_Solver_t * p )
+{
+    double dProgress = 0.0;
+    double dF = 1.0 / p->nVars;
+    int i;
+    for ( i = 0; i < p->nVars; i++ )
+        if ( p->pAssigns[i] != MSAT_VAR_UNASSIGNED )
+            dProgress += pow( dF, p->pLevel[i] );
+    return dProgress / p->nVars;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints statistics about the solver.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverPrintStats( Msat_Solver_t * p )
+{
+    printf("C solver (%d vars; %d clauses; %d learned):\n", 
+        p->nVars, Msat_ClauseVecReadSize(p->vClauses), Msat_ClauseVecReadSize(p->vLearned) );
+    printf("starts        : %d\n", (int)p->Stats.nStarts);
+    printf("conflicts     : %d\n", (int)p->Stats.nConflicts);
+    printf("decisions     : %d\n", (int)p->Stats.nDecisions);
+    printf("propagations  : %d\n", (int)p->Stats.nPropagations);
+    printf("inspects      : %d\n", (int)p->Stats.nInspects);
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Top-level solve.]
+
+  Description [If using assumptions (non-empty 'assumps' vector), you must 
+  call 'simplifyDB()' first to see that no top-level conflict is present 
+  (which would put the solver in an undefined state. If the last argument
+  is given (vProj), the solver enumerates through the satisfying solutions,
+  which are projected on the variables listed in this array. Note that the
+  variables in the array may be complemented, in which case the derived
+  assignment for the variable is complemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int  Msat_SolverSolve( Msat_Solver_t * p, Msat_IntVec_t * vAssumps, int nBackTrackLimit, int nTimeLimit )
+{
+    Msat_SearchParams_t Params = { 0.95, 0.999 };
+    double nConflictsLimit, nLearnedLimit;
+    Msat_Type_t Status;
+    abctime timeStart = Abc_Clock();
+
+//    p->pFreq = ABC_ALLOC( int, p->nVarsAlloc );
+//    memset( p->pFreq, 0, sizeof(int) * p->nVarsAlloc );
+ 
+    if ( vAssumps )
+    {
+        int * pAssumps, nAssumps, i;
+
+        assert( Msat_IntVecReadSize(p->vTrailLim) == 0 );
+
+        nAssumps = Msat_IntVecReadSize( vAssumps );
+        pAssumps = Msat_IntVecReadArray( vAssumps );
+        for ( i = 0; i < nAssumps; i++ )
+        {
+            if ( !Msat_SolverAssume(p, pAssumps[i]) || Msat_SolverPropagate(p) )
+            {
+                Msat_QueueClear( p->pQueue );
+                Msat_SolverCancelUntil( p, 0 );
+                return MSAT_FALSE;
+            }
+        }
+    }
+    p->nLevelRoot   = Msat_SolverReadDecisionLevel(p);
+    p->nClausesInit = Msat_ClauseVecReadSize( p->vClauses );    
+    nConflictsLimit = 100;
+    nLearnedLimit   = Msat_ClauseVecReadSize(p->vClauses) / 3;
+    Status = MSAT_UNKNOWN;
+    p->nBackTracks = (int)p->Stats.nConflicts;
+    while ( Status == MSAT_UNKNOWN )
+    {
+        if ( p->fVerbose )
+            printf("Solving -- conflicts=%d   learnts=%d   progress=%.4f %%\n", 
+                (int)nConflictsLimit, (int)nLearnedLimit, p->dProgress*100);
+        Status = Msat_SolverSearch( p, (int)nConflictsLimit, (int)nLearnedLimit, nBackTrackLimit, &Params );
+        nConflictsLimit *= 1.5;
+        nLearnedLimit   *= 1.1;
+        // if the limit on the number of backtracks is given, quit the restart loop
+        if ( nBackTrackLimit > 0 && (int)p->Stats.nConflicts - p->nBackTracks > nBackTrackLimit )
+            break;
+        // if the runtime limit is exceeded, quit the restart loop
+        if ( nTimeLimit > 0 && Abc_Clock() - timeStart >= nTimeLimit * CLOCKS_PER_SEC )
+            break;
+    }
+    Msat_SolverCancelUntil( p, 0 );
+    p->nBackTracks = (int)p->Stats.nConflicts - p->nBackTracks;
+/*
+    ABC_PRT( "True solver runtime", Abc_Clock() - timeStart );
+    // print the statistics
+    {
+        int i, Counter = 0;
+        for ( i = 0; i < p->nVars; i++ )
+            if ( p->pFreq[i] > 0 )
+            {
+                printf( "%d ", p->pFreq[i] );
+                Counter++;
+            }
+        if ( Counter )
+            printf( "\n" );
+        printf( "Total = %d. Used = %d.  Decisions = %d. Imps = %d. Conflicts = %d. ", p->nVars, Counter, (int)p->Stats.nDecisions, (int)p->Stats.nPropagations, (int)p->Stats.nConflicts );
+        ABC_PRT( "Time", Abc_Clock() - timeStart );
+    }
+*/
+    return Status;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/msat/msatSolverIo.c b/abc-build/src/sat/msat/msatSolverIo.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/msat/msatSolverIo.c
@@ -0,0 +1,182 @@
+/**CFile****************************************************************
+
+  FileName    [msatSolverIo.c]
+
+  PackageName [A C version of SAT solver MINISAT, originally developed 
+  in C++ by Niklas Een and Niklas Sorensson, Chalmers University of 
+  Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.]
+
+  Synopsis    [Input/output of CNFs.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: msatSolverIo.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "msatInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static char * Msat_TimeStamp();
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverPrintAssignment( Msat_Solver_t * p )
+{
+    int i;
+    printf( "Current assignments are: \n" );
+    for ( i = 0; i < p->nVars; i++ )
+        printf( "%d", i % 10 );
+    printf( "\n" );
+    for ( i = 0; i < p->nVars; i++ )
+        if ( p->pAssigns[i] == MSAT_VAR_UNASSIGNED )
+            printf( "." );
+        else
+        {
+            assert( i == MSAT_LIT2VAR(p->pAssigns[i]) );
+            if ( MSAT_LITSIGN(p->pAssigns[i]) )
+                printf( "0" );
+            else 
+                printf( "1" );
+        }
+    printf( "\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverPrintClauses( Msat_Solver_t * p )
+{
+    Msat_Clause_t ** pClauses;
+    int nClauses, i;
+
+    printf( "Original clauses: \n" );
+    nClauses = Msat_ClauseVecReadSize( p->vClauses );
+    pClauses = Msat_ClauseVecReadArray( p->vClauses );
+    for ( i = 0; i < nClauses; i++ )
+    {
+        printf( "%3d: ", i );
+        Msat_ClausePrint( pClauses[i] );
+    }
+
+    printf( "Learned clauses: \n" );
+    nClauses = Msat_ClauseVecReadSize( p->vLearned );
+    pClauses = Msat_ClauseVecReadArray( p->vLearned );
+    for ( i = 0; i < nClauses; i++ )
+    {
+        printf( "%3d: ", i );
+        Msat_ClausePrint( pClauses[i] );
+    }
+
+    printf( "Variable activity: \n" );
+    for ( i = 0; i < p->nVars; i++ )
+        printf( "%3d : %.4f\n", i, p->pdActivity[i] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverWriteDimacs( Msat_Solver_t * p, char * pFileName )
+{
+    FILE * pFile;
+    Msat_Clause_t ** pClauses;
+    int nClauses, i;
+
+    nClauses = Msat_ClauseVecReadSize(p->vClauses) + Msat_ClauseVecReadSize(p->vLearned);
+    for ( i = 0; i < p->nVars; i++ )
+        nClauses += ( p->pLevel[i] == 0 );
+
+    pFile = fopen( pFileName, "wb" );
+    fprintf( pFile, "c Produced by Msat_SolverWriteDimacs() on %s\n", Msat_TimeStamp() );
+    fprintf( pFile, "p cnf %d %d\n", p->nVars, nClauses );
+
+    nClauses = Msat_ClauseVecReadSize( p->vClauses );
+    pClauses = Msat_ClauseVecReadArray( p->vClauses );
+    for ( i = 0; i < nClauses; i++ )
+        Msat_ClauseWriteDimacs( pFile, pClauses[i], 1 );
+
+    nClauses = Msat_ClauseVecReadSize( p->vLearned );
+    pClauses = Msat_ClauseVecReadArray( p->vLearned );
+    for ( i = 0; i < nClauses; i++ )
+        Msat_ClauseWriteDimacs( pFile, pClauses[i], 1 );
+
+    // write zero-level assertions
+    for ( i = 0; i < p->nVars; i++ )
+        if ( p->pLevel[i] == 0 )
+            fprintf( pFile, "%s%d 0\n", ((p->pAssigns[i]&1)? "-": ""), i + 1 );
+
+    fprintf( pFile, "\n" );
+    fclose( pFile );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the time stamp.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Msat_TimeStamp()
+{
+    static char Buffer[100];
+	time_t ltime;
+	char * TimeStamp;
+    // get the current time
+	time( &ltime );
+	TimeStamp = asctime( localtime( &ltime ) );
+	TimeStamp[ strlen(TimeStamp) - 1 ] = 0;
+    strcpy( Buffer, TimeStamp );
+    return Buffer;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/msat/msatSolverSearch.c b/abc-build/src/sat/msat/msatSolverSearch.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/msat/msatSolverSearch.c
@@ -0,0 +1,634 @@
+/**CFile****************************************************************
+
+  FileName    [msatSolverSearch.c]
+
+  PackageName [A C version of SAT solver MINISAT, originally developed 
+  in C++ by Niklas Een and Niklas Sorensson, Chalmers University of 
+  Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.]
+
+  Synopsis    [The search part of the solver.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: msatSolverSearch.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "msatInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static void            Msat_SolverUndoOne( Msat_Solver_t * p );
+static void            Msat_SolverCancel( Msat_Solver_t * p );
+static Msat_Clause_t * Msat_SolverRecord( Msat_Solver_t * p, Msat_IntVec_t * vLits );
+static void            Msat_SolverAnalyze( Msat_Solver_t * p, Msat_Clause_t * pC, Msat_IntVec_t * vLits_out, int * pLevel_out );
+static void            Msat_SolverReduceDB( Msat_Solver_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Makes the next assumption (Lit).]
+
+  Description [Returns FALSE if immediate conflict.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int  Msat_SolverAssume( Msat_Solver_t * p, Msat_Lit_t Lit )
+{
+    assert( Msat_QueueReadSize(p->pQueue) == 0 );
+    if ( p->fVerbose )
+        printf(L_IND"assume("L_LIT")\n", L_ind, L_lit(Lit));
+    Msat_IntVecPush( p->vTrailLim, Msat_IntVecReadSize(p->vTrail) );
+//    assert( Msat_IntVecReadSize(p->vTrailLim) <= Msat_IntVecReadSize(p->vTrail) + 1 );
+//    assert( Msat_IntVecReadSize( p->vTrailLim ) < p->nVars );
+    return Msat_SolverEnqueue( p, Lit, NULL );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reverts one variable binding on the trail.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverUndoOne( Msat_Solver_t * p )
+{
+    Msat_Lit_t Lit;
+    Msat_Var_t Var;
+    Lit = Msat_IntVecPop( p->vTrail ); 
+    Var = MSAT_LIT2VAR(Lit);
+    p->pAssigns[Var] = MSAT_VAR_UNASSIGNED;
+    p->pReasons[Var] = NULL;
+    p->pLevel[Var]   = -1;
+//    Msat_OrderUndo( p->pOrder, Var );
+    Msat_OrderVarUnassigned( p->pOrder, Var );
+
+    if ( p->fVerbose )
+        printf(L_IND"unbind("L_LIT")\n", L_ind, L_lit(Lit)); 
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reverts to the state before last Msat_SolverAssume().]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverCancel( Msat_Solver_t * p )
+{
+    int c;
+    assert( Msat_QueueReadSize(p->pQueue) == 0 );
+    if ( p->fVerbose )
+    {
+        if ( Msat_IntVecReadSize(p->vTrail) != Msat_IntVecReadEntryLast(p->vTrailLim) )
+        {
+            Msat_Lit_t Lit;
+            Lit = Msat_IntVecReadEntry( p->vTrail, Msat_IntVecReadEntryLast(p->vTrailLim) ); 
+            printf(L_IND"cancel("L_LIT")\n", L_ind, L_lit(Lit));
+        }
+    }
+    for ( c = Msat_IntVecReadSize(p->vTrail) - Msat_IntVecPop( p->vTrailLim ); c != 0; c-- )
+        Msat_SolverUndoOne( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reverts to the state at given level.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverCancelUntil( Msat_Solver_t * p, int Level )
+{
+    while ( Msat_IntVecReadSize(p->vTrailLim) > Level )
+        Msat_SolverCancel(p);
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Record a clause and drive backtracking.]
+
+  Description [vLits[0] must contain the asserting literal.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_Clause_t * Msat_SolverRecord( Msat_Solver_t * p, Msat_IntVec_t * vLits )
+{
+    Msat_Clause_t * pC;
+    int Value;
+    assert( Msat_IntVecReadSize(vLits) != 0 );
+    Value = Msat_ClauseCreate( p, vLits, 1, &pC );
+    assert( Value );
+    Value = Msat_SolverEnqueue( p, Msat_IntVecReadEntry(vLits,0), pC );
+    assert( Value );
+    if ( pC )
+        Msat_ClauseVecPush( p->vLearned, pC );
+    return pC;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Enqueues one variable assignment.]
+
+  Description [Puts a new fact on the propagation queue and immediately 
+  updates the variable value. Should a conflict arise, FALSE is returned.
+  Otherwise returns TRUE.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int  Msat_SolverEnqueue( Msat_Solver_t * p, Msat_Lit_t Lit, Msat_Clause_t * pC )
+{
+    Msat_Var_t Var = MSAT_LIT2VAR(Lit);
+
+    // skip literals that are not in the current cone
+    if ( !Msat_IntVecReadEntry( p->vVarsUsed, Var ) )
+        return 1;
+
+//    assert( Msat_QueueReadSize(p->pQueue) == Msat_IntVecReadSize(p->vTrail) );
+    // if the literal is assigned
+    // return 1 if the assignment is consistent
+    // return 0 if the assignment is inconsistent (conflict)
+    if ( p->pAssigns[Var] != MSAT_VAR_UNASSIGNED )
+        return p->pAssigns[Var] == Lit;
+    // new fact - store it
+    if ( p->fVerbose )
+    {
+//        printf(L_IND"bind("L_LIT")\n", L_ind, L_lit(Lit));
+        printf(L_IND"bind("L_LIT")  ", L_ind, L_lit(Lit));
+        Msat_ClausePrintSymbols( pC );
+    }
+    p->pAssigns[Var] = Lit;
+    p->pLevel[Var]   = Msat_IntVecReadSize(p->vTrailLim);
+//    p->pReasons[Var] = p->pLevel[Var]? pC: NULL;
+    p->pReasons[Var] = pC;
+    Msat_IntVecPush( p->vTrail, Lit );
+    Msat_QueueInsert( p->pQueue, Lit );
+
+    Msat_OrderVarAssigned( p->pOrder, Var );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagates the assignments in the queue.]
+
+  Description [Propagates all enqueued facts. If a conflict arises, 
+  the conflicting clause is returned, otherwise NULL.]
+               
+  SideEffects [The propagation queue is empty, even if there was a conflict.]
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_Clause_t * Msat_SolverPropagate( Msat_Solver_t * p )
+{
+    Msat_ClauseVec_t ** pvWatched = p->pvWatched;
+    Msat_Clause_t ** pClauses;
+    Msat_Clause_t * pConflict;
+    Msat_Lit_t Lit, Lit_out;
+    int i, j, nClauses;
+
+    // propagate all the literals in the queue
+    while ( (Lit = Msat_QueueExtract( p->pQueue )) >= 0 )
+    {
+        p->Stats.nPropagations++;
+        // get the clauses watched by this literal
+        nClauses = Msat_ClauseVecReadSize( pvWatched[Lit] );
+        pClauses = Msat_ClauseVecReadArray( pvWatched[Lit] );
+        // go through the watched clauses and decide what to do with them
+        for ( i = j = 0; i < nClauses; i++ )
+        {
+            p->Stats.nInspects++;
+            // clear the returned literal
+            Lit_out = -1;
+            // propagate the clause
+            if ( !Msat_ClausePropagate( pClauses[i], Lit, p->pAssigns, &Lit_out ) )
+            {   // the clause is unit
+                // "Lit_out" contains the new assignment to be enqueued
+                if ( Msat_SolverEnqueue( p, Lit_out, pClauses[i] ) ) 
+                { // consistent assignment 
+                    // no changes to the implication queue; the watch is the same too
+                    pClauses[j++] = pClauses[i];
+                    continue;
+                }
+                // remember the reason of conflict (will be returned)
+                pConflict = pClauses[i];
+                // leave the remaning clauses in the same watched list
+                for ( ; i < nClauses; i++ )
+                    pClauses[j++] = pClauses[i];
+                Msat_ClauseVecShrink( pvWatched[Lit], j );
+                // clear the propagation queue
+                Msat_QueueClear( p->pQueue );
+                return pConflict;
+            }
+            // the clause is not unit
+            // in this case "Lit_out" contains the new watch if it has changed
+            if ( Lit_out >= 0 )
+                Msat_ClauseVecPush( pvWatched[Lit_out], pClauses[i] );
+            else // the watch did not change
+                pClauses[j++] = pClauses[i];
+        }
+        Msat_ClauseVecShrink( pvWatched[Lit], j );
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Simplifies the data base.]
+
+  Description [Simplify all constraints according to the current top-level 
+  assigment (redundant constraints may be removed altogether).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int  Msat_SolverSimplifyDB( Msat_Solver_t * p )
+{
+    Msat_ClauseVec_t * vClauses;
+    Msat_Clause_t ** pClauses;
+    int nClauses, Type, i, j;
+    int * pAssigns;
+    int Counter;
+
+    assert( Msat_SolverReadDecisionLevel(p) == 0 );
+    if ( Msat_SolverPropagate(p) != NULL )
+        return 0;
+//Msat_SolverPrintClauses( p );
+//Msat_SolverPrintAssignment( p );
+//printf( "Simplification\n" );
+
+    // simplify and reassign clause numbers
+    Counter = 0;
+    pAssigns = Msat_SolverReadAssignsArray( p );
+    for ( Type = 0; Type < 2; Type++ )
+    {
+        vClauses = Type? p->vLearned : p->vClauses;
+        nClauses = Msat_ClauseVecReadSize( vClauses );
+        pClauses = Msat_ClauseVecReadArray( vClauses );
+        for ( i = j = 0; i < nClauses; i++ )
+            if ( Msat_ClauseSimplify( pClauses[i], pAssigns ) )
+                Msat_ClauseFree( p, pClauses[i], 1 );
+            else
+            {
+                pClauses[j++] = pClauses[i];
+                Msat_ClauseSetNum( pClauses[i], Counter++ );
+            }
+        Msat_ClauseVecShrink( vClauses, j );
+    }
+    p->nClauses = Counter;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Cleans the clause databased from the useless learnt clauses.]
+
+  Description [Removes half of the learnt clauses, minus the clauses locked 
+  by the current assignment. Locked clauses are clauses that are reason 
+  to a some assignment.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverReduceDB( Msat_Solver_t * p )
+{
+    Msat_Clause_t ** pLearned;
+    int nLearned, i, j;
+    double dExtraLim = p->dClaInc / Msat_ClauseVecReadSize(p->vLearned); 
+    // Remove any clause below this activity
+
+    // sort the learned clauses in the increasing order of activity
+    Msat_SolverSortDB( p );
+
+    // discard the first half the clauses (the less active ones)
+    nLearned = Msat_ClauseVecReadSize( p->vLearned );
+    pLearned = Msat_ClauseVecReadArray( p->vLearned );
+    for ( i = j = 0; i < nLearned / 2; i++ )
+        if ( !Msat_ClauseIsLocked( p, pLearned[i]) )
+            Msat_ClauseFree( p, pLearned[i], 1 );
+        else
+            pLearned[j++] = pLearned[i];
+    // filter the more active clauses and leave those above the limit
+    for (  ; i < nLearned; i++ )
+        if ( !Msat_ClauseIsLocked( p, pLearned[i] ) && 
+            Msat_ClauseReadActivity(pLearned[i]) < dExtraLim )
+            Msat_ClauseFree( p, pLearned[i], 1 );
+        else
+            pLearned[j++] = pLearned[i];
+    Msat_ClauseVecShrink( p->vLearned, j );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes the learned clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverRemoveLearned( Msat_Solver_t * p )
+{
+    Msat_Clause_t ** pLearned;
+    int nLearned, i;
+
+    // discard the learned clauses
+    nLearned = Msat_ClauseVecReadSize( p->vLearned );
+    pLearned = Msat_ClauseVecReadArray( p->vLearned );
+    for ( i = 0; i < nLearned; i++ )
+    {
+        assert( !Msat_ClauseIsLocked( p, pLearned[i]) );
+        
+        Msat_ClauseFree( p, pLearned[i], 1 );
+    }
+    Msat_ClauseVecShrink( p->vLearned, 0 );
+    p->nClauses = Msat_ClauseVecReadSize(p->vClauses);
+
+    for ( i = 0; i < p->nVarsAlloc; i++ )
+        p->pReasons[i] = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Removes the recently added clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverRemoveMarked( Msat_Solver_t * p )
+{
+    Msat_Clause_t ** pLearned, ** pClauses;
+    int nLearned, nClauses, i;
+
+    // discard the learned clauses
+    nClauses = Msat_ClauseVecReadSize( p->vClauses );
+    pClauses = Msat_ClauseVecReadArray( p->vClauses );
+    for ( i = p->nClausesStart; i < nClauses; i++ )
+    {
+//        assert( !Msat_ClauseIsLocked( p, pClauses[i]) );
+        Msat_ClauseFree( p, pClauses[i], 1 );
+    }
+    Msat_ClauseVecShrink( p->vClauses, p->nClausesStart );
+
+    // discard the learned clauses
+    nLearned = Msat_ClauseVecReadSize( p->vLearned );
+    pLearned = Msat_ClauseVecReadArray( p->vLearned );
+    for ( i = 0; i < nLearned; i++ )
+    {
+//        assert( !Msat_ClauseIsLocked( p, pLearned[i]) );
+        Msat_ClauseFree( p, pLearned[i], 1 );
+    }
+    Msat_ClauseVecShrink( p->vLearned, 0 );
+    p->nClauses = Msat_ClauseVecReadSize(p->vClauses);
+/*
+    // undo the previous data
+    for ( i = 0; i < p->nVarsAlloc; i++ )
+    {
+        p->pAssigns[i]   = MSAT_VAR_UNASSIGNED;
+        p->pReasons[i]   = NULL;
+        p->pLevel[i]     = -1;
+        p->pdActivity[i] = 0.0;
+    }
+    Msat_OrderClean( p->pOrder, p->nVars, NULL );
+    Msat_QueueClear( p->pQueue );
+*/
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Analyze conflict and produce a reason clause.]
+
+  Description [Current decision level must be greater than root level.]
+               
+  SideEffects [vLits_out[0] is the asserting literal at level pLevel_out.]
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverAnalyze( Msat_Solver_t * p, Msat_Clause_t * pC, Msat_IntVec_t * vLits_out, int * pLevel_out )
+{
+    Msat_Lit_t LitQ, Lit = MSAT_LIT_UNASSIGNED;
+    Msat_Var_t VarQ, Var;
+    int * pReasonArray, nReasonSize;
+    int j, pathC = 0, nLevelCur = Msat_IntVecReadSize(p->vTrailLim);
+    int iStep = Msat_IntVecReadSize(p->vTrail) - 1;
+
+    // increment the seen counter
+    p->nSeenId++;
+    // empty the vector array
+    Msat_IntVecClear( vLits_out );
+    Msat_IntVecPush( vLits_out, -1 ); // (leave room for the asserting literal)
+    *pLevel_out = 0;
+    do {
+        assert( pC != NULL );  // (otherwise should be UIP)
+        // get the reason of conflict
+        Msat_ClauseCalcReason( p, pC, Lit, p->vReason );
+        nReasonSize  = Msat_IntVecReadSize( p->vReason );
+        pReasonArray = Msat_IntVecReadArray( p->vReason );
+        for ( j = 0; j < nReasonSize; j++ ) {
+            LitQ = pReasonArray[j];
+            VarQ = MSAT_LIT2VAR(LitQ);
+            if ( p->pSeen[VarQ] != p->nSeenId ) {
+                p->pSeen[VarQ] = p->nSeenId;
+
+                // added to better fine-tune the search
+                Msat_SolverVarBumpActivity( p, LitQ );
+
+                // skip all the literals on this decision level
+                if ( p->pLevel[VarQ] == nLevelCur )
+                    pathC++;
+                else if ( p->pLevel[VarQ] > 0 ) { 
+                    // add the literals on other decision levels but
+                    // exclude variables from decision level 0
+                    Msat_IntVecPush( vLits_out, MSAT_LITNOT(LitQ) );
+                    if ( *pLevel_out < p->pLevel[VarQ] )
+                        *pLevel_out = p->pLevel[VarQ];
+                }
+            }
+        }
+        // Select next clause to look at:
+        do {
+//            Lit = Msat_IntVecReadEntryLast(p->vTrail);
+            Lit = Msat_IntVecReadEntry( p->vTrail, iStep-- );
+            Var = MSAT_LIT2VAR(Lit);
+            pC = p->pReasons[Var];
+//            Msat_SolverUndoOne( p );
+        } while ( p->pSeen[Var] != p->nSeenId );
+        pathC--;
+    } while ( pathC > 0 );
+    // we do not unbind the variables above
+    // this will be done after conflict analysis
+
+    Msat_IntVecWriteEntry( vLits_out, 0, MSAT_LITNOT(Lit) );
+    if ( p->fVerbose )
+    {
+        printf( L_IND"Learnt {", L_ind );
+        nReasonSize  = Msat_IntVecReadSize( vLits_out );
+        pReasonArray = Msat_IntVecReadArray( vLits_out );
+        for ( j = 0; j < nReasonSize; j++ ) 
+            printf(" "L_LIT, L_lit(pReasonArray[j]));
+        printf(" } at level %d\n", *pLevel_out); 
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [The search procedure called between the restarts.]
+
+  Description [Search for a satisfying solution as long as the number of 
+  conflicts does not exceed the limit (nConfLimit) while keeping the number 
+  of learnt clauses below the provided limit (nLearnedLimit). NOTE! Use 
+  negative value for nConfLimit or nLearnedLimit to indicate infinity.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_Type_t Msat_SolverSearch( Msat_Solver_t * p, int nConfLimit, int nLearnedLimit, int nBackTrackLimit, Msat_SearchParams_t * pPars )
+{
+    Msat_Clause_t * pConf;
+    Msat_Var_t Var;
+    int nLevelBack, nConfs, nAssigns, Value;
+    int i;
+
+    assert( Msat_SolverReadDecisionLevel(p) == p->nLevelRoot );
+    p->Stats.nStarts++;
+    p->dVarDecay = 1 / pPars->dVarDecay;
+    p->dClaDecay = 1 / pPars->dClaDecay;
+
+    // reset the activities
+    for ( i = 0; i < p->nVars; i++ )
+       p->pdActivity[i] = (double)p->pFactors[i];
+//       p->pdActivity[i] = 0.0;
+
+    nConfs = 0;
+    while ( 1 )
+    {
+        pConf = Msat_SolverPropagate( p );
+        if ( pConf != NULL ){
+            // CONFLICT
+            if ( p->fVerbose )
+            {
+//                printf(L_IND"**CONFLICT**\n", L_ind);
+                printf(L_IND"**CONFLICT**  ", L_ind);
+                Msat_ClausePrintSymbols( pConf );
+            }
+            // count conflicts
+            p->Stats.nConflicts++;
+            nConfs++;
+
+            // if top level, return UNSAT
+            if ( Msat_SolverReadDecisionLevel(p) == p->nLevelRoot )
+                return MSAT_FALSE;
+
+            // perform conflict analysis
+            Msat_SolverAnalyze( p, pConf, p->vTemp, &nLevelBack );
+            Msat_SolverCancelUntil( p, (p->nLevelRoot > nLevelBack)? p->nLevelRoot : nLevelBack );
+            Msat_SolverRecord( p, p->vTemp );
+
+            // it is important that recording is done after cancelling
+            // because canceling cleans the queue while recording adds to it
+            Msat_SolverVarDecayActivity( p );
+            Msat_SolverClaDecayActivity( p );
+
+        }
+        else{
+            // NO CONFLICT
+            if ( Msat_IntVecReadSize(p->vTrailLim) == 0 ) {
+                // Simplify the set of problem clauses:
+//                Value = Msat_SolverSimplifyDB(p);
+//                assert( Value );
+            }
+            nAssigns = Msat_IntVecReadSize( p->vTrail );
+            if ( nLearnedLimit >= 0 && Msat_ClauseVecReadSize(p->vLearned) >= nLearnedLimit + nAssigns ) {
+                // Reduce the set of learnt clauses:
+                Msat_SolverReduceDB(p);
+            }
+
+            Var = Msat_OrderVarSelect( p->pOrder );
+            if ( Var == MSAT_ORDER_UNKNOWN ) {
+                // Model found and stored in p->pAssigns
+                memcpy( p->pModel, p->pAssigns, sizeof(int) * p->nVars );
+                Msat_QueueClear( p->pQueue );
+                Msat_SolverCancelUntil( p, p->nLevelRoot );
+                return MSAT_TRUE;
+            }
+            if ( nConfLimit > 0 && nConfs > nConfLimit ) {
+                // Reached bound on number of conflicts:
+                p->dProgress = Msat_SolverProgressEstimate( p );
+                Msat_QueueClear( p->pQueue );
+                Msat_SolverCancelUntil( p, p->nLevelRoot );
+                return MSAT_UNKNOWN; 
+            }
+            else if ( nBackTrackLimit > 0 && (int)p->Stats.nConflicts - p->nBackTracks > nBackTrackLimit ) {
+                // Reached bound on number of conflicts:
+                Msat_QueueClear( p->pQueue );
+                Msat_SolverCancelUntil( p, p->nLevelRoot );
+                return MSAT_UNKNOWN; 
+            }
+            else{
+                // New variable decision:
+                p->Stats.nDecisions++;
+                assert( Var != MSAT_ORDER_UNKNOWN && Var >= 0 && Var < p->nVars );
+                Value = Msat_SolverAssume(p, MSAT_VAR2LIT(Var,0) );
+                assert( Value );
+            }
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/msat/msatSort.c b/abc-build/src/sat/msat/msatSort.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/msat/msatSort.c
@@ -0,0 +1,178 @@
+/**CFile****************************************************************
+
+  FileName    [msatSort.c]
+
+  PackageName [A C version of SAT solver MINISAT, originally developed 
+  in C++ by Niklas Een and Niklas Sorensson, Chalmers University of 
+  Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.]
+
+  Synopsis    [Sorting clauses.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: msatSort.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "msatInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Msat_SolverSortCompare( Msat_Clause_t ** ppC1, Msat_Clause_t ** ppC2 );
+
+// Returns a random float 0 <= x < 1. Seed must never be 0.
+static double drand(double seed) {
+    int q;
+    seed *= 1389796;
+    q = (int)(seed / 2147483647);
+    seed -= (double)q * 2147483647;
+    return seed / 2147483647; }
+
+// Returns a random integer 0 <= x < size. Seed must never be 0.
+static int irand(double seed, int size) {
+    return (int)(drand(seed) * size); }
+
+static void Msat_SolverSort( Msat_Clause_t ** array, int size, double seed );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Msat_SolverSort the learned clauses in the increasing order of activity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverSortDB( Msat_Solver_t * p )
+{
+    Msat_ClauseVec_t * pVecClauses;
+    Msat_Clause_t ** pLearned;
+    int nLearned;
+    // read the parameters
+    pVecClauses = Msat_SolverReadLearned( p );
+    nLearned    = Msat_ClauseVecReadSize( pVecClauses );
+    pLearned    = Msat_ClauseVecReadArray( pVecClauses );
+    // Msat_SolverSort the array
+//    qMsat_SolverSort( (void *)pLearned, nLearned, sizeof(Msat_Clause_t *), 
+//            (int (*)(const void *, const void *)) Msat_SolverSortCompare );
+//    printf( "Msat_SolverSorting.\n" );
+    Msat_SolverSort( pLearned, nLearned, 91648253 );
+/*
+    if ( nLearned > 2 )
+    {
+    printf( "Clause 1: %0.20f\n", Msat_ClauseReadActivity(pLearned[0]) );
+    printf( "Clause 2: %0.20f\n", Msat_ClauseReadActivity(pLearned[1]) );
+    printf( "Clause 3: %0.20f\n", Msat_ClauseReadActivity(pLearned[2]) );
+    }
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_SolverSortCompare( Msat_Clause_t ** ppC1, Msat_Clause_t ** ppC2 )
+{
+    float Value1 = Msat_ClauseReadActivity( *ppC1 );
+    float Value2 = Msat_ClauseReadActivity( *ppC2 );
+    if ( Value1 < Value2 )
+        return -1;
+    if ( Value1 > Value2 )
+        return 1;
+    return 0;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Selection sort for small array size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverSortSelection( Msat_Clause_t ** array, int size )
+{
+    Msat_Clause_t * tmp;
+    int i, j, best_i;
+    for ( i = 0; i < size-1; i++ )
+    {
+        best_i = i;
+        for (j = i+1; j < size; j++)
+        {
+            if ( Msat_ClauseReadActivity(array[j]) < Msat_ClauseReadActivity(array[best_i]) )
+                best_i = j;
+        }
+        tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [The original MiniSat sorting procedure.]
+
+  Description [This procedure is used to preserve trace-equivalence
+  with the orignal C++ implemenation of the solver.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_SolverSort( Msat_Clause_t ** array, int size, double seed )
+{
+    if (size <= 15)
+        Msat_SolverSortSelection( array, size );
+    else
+    {
+        Msat_Clause_t *   pivot = array[irand(seed, size)];
+        Msat_Clause_t *   tmp;
+        int              i = -1;
+        int              j = size;
+
+        for(;;)
+        {
+            do i++; while( Msat_ClauseReadActivity(array[i]) < Msat_ClauseReadActivity(pivot) );
+            do j--; while( Msat_ClauseReadActivity(pivot) < Msat_ClauseReadActivity(array[j]) );
+
+            if ( i >= j ) break;
+
+            tmp = array[i]; array[i] = array[j]; array[j] = tmp;
+        }
+        Msat_SolverSort(array    , i     , seed);
+        Msat_SolverSort(&array[i], size-i, seed);
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/msat/msatVec.c b/abc-build/src/sat/msat/msatVec.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/msat/msatVec.c
@@ -0,0 +1,500 @@
+/**CFile****************************************************************
+
+  FileName    [msatVec.c]
+
+  PackageName [A C version of SAT solver MINISAT, originally developed 
+  in C++ by Niklas Een and Niklas Sorensson, Chalmers University of 
+  Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.]
+
+  Synopsis    [Integer vector borrowed from Extra.]
+
+  Author      [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - January 1, 2004.]
+
+  Revision    [$Id: msatVec.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "msatInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+static int Msat_IntVecSortCompare1( int * pp1, int * pp2 );
+static int Msat_IntVecSortCompare2( int * pp1, int * pp2 );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocates a vector with the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_IntVec_t * Msat_IntVecAlloc( int nCap )
+{
+    Msat_IntVec_t * p;
+    p = ABC_ALLOC( Msat_IntVec_t, 1 );
+    if ( nCap > 0 && nCap < 16 )
+        nCap = 16;
+    p->nSize  = 0;
+    p->nCap   = nCap;
+    p->pArray = p->nCap? ABC_ALLOC( int, p->nCap ) : NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the vector from an integer array of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_IntVec_t * Msat_IntVecAllocArray( int * pArray, int nSize )
+{
+    Msat_IntVec_t * p;
+    p = ABC_ALLOC( Msat_IntVec_t, 1 );
+    p->nSize  = nSize;
+    p->nCap   = nSize;
+    p->pArray = pArray;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the vector from an integer array of the given size.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_IntVec_t * Msat_IntVecAllocArrayCopy( int * pArray, int nSize )
+{
+    Msat_IntVec_t * p;
+    p = ABC_ALLOC( Msat_IntVec_t, 1 );
+    p->nSize  = nSize;
+    p->nCap   = nSize;
+    p->pArray = ABC_ALLOC( int, nSize );
+    memcpy( p->pArray, pArray, sizeof(int) * nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicates the integer array.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_IntVec_t * Msat_IntVecDup( Msat_IntVec_t * pVec )
+{
+    Msat_IntVec_t * p;
+    p = ABC_ALLOC( Msat_IntVec_t, 1 );
+    p->nSize  = pVec->nSize;
+    p->nCap   = pVec->nCap;
+    p->pArray = p->nCap? ABC_ALLOC( int, p->nCap ) : NULL;
+    memcpy( p->pArray, pVec->pArray, sizeof(int) * pVec->nSize );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Transfers the array into another vector.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Msat_IntVec_t * Msat_IntVecDupArray( Msat_IntVec_t * pVec )
+{
+    Msat_IntVec_t * p;
+    p = ABC_ALLOC( Msat_IntVec_t, 1 );
+    p->nSize  = pVec->nSize;
+    p->nCap   = pVec->nCap;
+    p->pArray = pVec->pArray;
+    pVec->nSize  = 0;
+    pVec->nCap   = 0;
+    pVec->pArray = NULL;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_IntVecFree( Msat_IntVec_t * p )
+{
+    ABC_FREE( p->pArray );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fills the vector with given number of entries.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_IntVecFill( Msat_IntVec_t * p, int nSize, int Entry )
+{
+    int i;
+    Msat_IntVecGrow( p, nSize );
+    p->nSize = nSize;
+    for ( i = 0; i < p->nSize; i++ )
+        p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Msat_IntVecReleaseArray( Msat_IntVec_t * p )
+{
+    int * pArray = p->pArray;
+    p->nCap = 0;
+    p->nSize = 0;
+    p->pArray = NULL;
+    return pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int * Msat_IntVecReadArray( Msat_IntVec_t * p )
+{
+    return p->pArray;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_IntVecReadSize( Msat_IntVec_t * p )
+{
+    return p->nSize;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_IntVecReadEntry( Msat_IntVec_t * p, int i )
+{
+    assert( i >= 0 && i < p->nSize );
+    return p->pArray[i];
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_IntVecWriteEntry( Msat_IntVec_t * p, int i, int Entry )
+{
+    assert( i >= 0 && i < p->nSize );
+    p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_IntVecReadEntryLast( Msat_IntVec_t * p )
+{
+    return p->pArray[p->nSize-1];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resizes the vector to the given capacity.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_IntVecGrow( Msat_IntVec_t * p, int nCapMin )
+{
+    if ( p->nCap >= nCapMin )
+        return;
+    p->pArray = ABC_REALLOC( int, p->pArray, nCapMin ); 
+    p->nCap   = nCapMin;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_IntVecShrink( Msat_IntVec_t * p, int nSizeNew )
+{
+    assert( p->nSize >= nSizeNew );
+    p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_IntVecClear( Msat_IntVec_t * p )
+{
+    p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_IntVecPush( Msat_IntVec_t * p, int Entry )
+{
+    if ( p->nSize == p->nCap )
+    {
+        if ( p->nCap < 16 )
+            Msat_IntVecGrow( p, 16 );
+        else
+            Msat_IntVecGrow( p, 2 * p->nCap );
+    }
+    p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Add the element while ensuring uniqueness.]
+
+  Description [Returns 1 if the element was found, and 0 if it was new. ]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_IntVecPushUnique( Msat_IntVec_t * p, int Entry )
+{
+    int i;
+    for ( i = 0; i < p->nSize; i++ )
+        if ( p->pArray[i] == Entry )
+            return 1;
+    Msat_IntVecPush( p, Entry );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts the element while sorting in the increasing order.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_IntVecPushUniqueOrder( Msat_IntVec_t * p, int Entry, int fIncrease )
+{
+    int Entry1, Entry2;
+    int i;
+    Msat_IntVecPushUnique( p, Entry );
+    // find the p of the node
+    for ( i = p->nSize-1; i > 0; i-- )
+    {
+        Entry1 = p->pArray[i  ];
+        Entry2 = p->pArray[i-1];
+        if (( fIncrease && Entry1 >= Entry2) ||
+            (!fIncrease && Entry1 <= Entry2) )
+            break;
+        p->pArray[i  ] = Entry2;
+        p->pArray[i-1] = Entry1;
+    }
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the last entry and removes it from the list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_IntVecPop( Msat_IntVec_t * p )
+{
+    assert( p->nSize > 0 );
+    return p->pArray[--p->nSize];
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Sorting the entries by their integer value.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Msat_IntVecSort( Msat_IntVec_t * p, int fReverse )
+{
+    if ( fReverse ) 
+        qsort( (void *)p->pArray, p->nSize, sizeof(int), 
+                (int (*)(const void *, const void *)) Msat_IntVecSortCompare2 );
+    else
+        qsort( (void *)p->pArray, p->nSize, sizeof(int), 
+                (int (*)(const void *, const void *)) Msat_IntVecSortCompare1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_IntVecSortCompare1( int * pp1, int * pp2 )
+{
+    // for some reason commenting out lines (as shown) led to crashing of the release version
+    if ( *pp1 < *pp2 )
+        return -1;
+    if ( *pp1 > *pp2 ) //
+        return 1;
+    return 0; //
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison procedure for two clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Msat_IntVecSortCompare2( int * pp1, int * pp2 )
+{
+    // for some reason commenting out lines (as shown) led to crashing of the release version
+    if ( *pp1 > *pp2 )
+        return -1;
+    if ( *pp1 < *pp2 ) //
+        return 1;
+    return 0; //
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/proof/pr.c b/abc-build/src/sat/proof/pr.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/proof/pr.c
@@ -0,0 +1,1264 @@
+/**CFile****************************************************************
+
+  FileName    [pr.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Proof recording.]
+
+  Synopsis    [Core procedures of the package.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: pr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "misc/util/abc_global.h"
+#include "pr.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef unsigned lit;
+
+typedef struct Pr_Cls_t_ Pr_Cls_t;
+struct Pr_Cls_t_
+{
+    unsigned        uTruth;       // interpolant
+    void *          pProof;       // the proof node 
+//    void *          pAntis;       // the anticedents
+    Pr_Cls_t *      pNext;        // the next clause
+    Pr_Cls_t *      pNext0;       // the next 0-watch
+    Pr_Cls_t *      pNext1;       // the next 0-watch
+    int             Id;           // the clause ID
+    unsigned        fA     :  1;  // belongs to A
+    unsigned        fRoot  :  1;  // original clause
+    unsigned        fVisit :  1;  // visited clause
+    unsigned        nLits  : 24;  // the number of literals
+    lit             pLits[0];     // literals of this clause
+};
+
+struct Pr_Man_t_
+{
+    // general data
+    int             fProofWrite;  // writes the proof file
+    int             fProofVerif;  // verifies the proof
+    int             nVars;        // the number of variables
+    int             nVarsAB;      // the number of global variables
+    int             nRoots;       // the number of root clauses
+    int             nClauses;     // the number of all clauses
+    int             nClausesA;    // the number of clauses of A 
+    Pr_Cls_t *      pHead;        // the head clause
+    Pr_Cls_t *      pTail;        // the tail clause
+    Pr_Cls_t *      pLearnt;      // the tail clause
+    Pr_Cls_t *      pEmpty;       // the empty clause
+    // internal BCP
+    int             nRootSize;    // the number of root level assignments
+    int             nTrailSize;   // the number of assignments made 
+    lit *           pTrail;       // chronological order of assignments (size nVars)
+    lit *           pAssigns;     // assignments by variable (size nVars) 
+    char *          pSeens;       // temporary mark (size nVars)
+    char *          pVarTypes;    // variable type (size nVars) [1=A, 0=B, <0=AB]
+    Pr_Cls_t **     pReasons;     // reasons for each assignment (size nVars)          
+    Pr_Cls_t **     pWatches;     // watched clauses for each literal (size 2*nVars)          
+    int             nVarsAlloc;   // the allocated size of arrays
+    // proof recording
+    void *          pManProof;    // proof manager
+    int             Counter;      // counter of resolved clauses
+    // memory management
+    int             nChunkSize;   // the number of bytes in a chunk
+    int             nChunkUsed;   // the number of bytes used in the last chunk
+    char *          pChunkLast;   // the last memory chunk
+    // internal verification
+    lit *           pResLits;     // the literals of the resolvent   
+    int             nResLits;     // the number of literals of the resolvent
+    int             nResLitsAlloc;// the number of literals of the resolvent
+    // runtime stats
+    abctime         timeBcp;
+    abctime         timeTrace;
+    abctime         timeRead;
+    abctime         timeTotal;
+};
+
+// variable assignments 
+static const lit  LIT_UNDEF = 0xffffffff;
+
+// variable/literal conversions (taken from MiniSat)
+static inline lit   toLit    (int v)        { return v + v;  }
+static inline lit   toLitCond(int v, int c) { return v + v + (c != 0); }
+static inline lit   lit_neg  (lit l)        { return l ^ 1;  }
+static inline int   lit_var  (lit l)        { return l >> 1; }
+static inline int   lit_sign (lit l)        { return l & 1;  }
+static inline int   lit_print(lit l)        { return lit_sign(l)? -lit_var(l)-1 : lit_var(l)+1; }
+static inline lit   lit_read (int s)        { return s > 0 ? toLit(s-1) : lit_neg(toLit(-s-1)); }
+static inline int   lit_check(lit l, int n) { return l >= 0 && lit_var(l) < n;                  }
+
+// iterators through the clauses
+#define Pr_ManForEachClause( p, pCls )        for( pCls = p->pHead; pCls; pCls = pCls->pNext )
+#define Pr_ManForEachClauseRoot( p, pCls )    for( pCls = p->pHead; pCls != p->pLearnt; pCls = pCls->pNext )
+#define Pr_ManForEachClauseLearnt( p, pCls )  for( pCls = p->pLearnt; pCls; pCls = pCls->pNext )
+
+// static procedures
+static char *     Pr_ManMemoryFetch( Pr_Man_t * p, int nBytes );
+static void       Pr_ManMemoryStop( Pr_Man_t * p );
+static void       Pr_ManResize( Pr_Man_t * p, int nVarsNew );
+
+// exported procedures
+extern Pr_Man_t * Pr_ManAlloc( int nVarsAlloc );
+extern void       Pr_ManFree( Pr_Man_t * p );
+extern int        Pr_ManAddClause( Pr_Man_t * p, lit * pBeg, lit * pEnd, int fRoot, int fClauseA );
+extern int        Pr_ManProofWrite( Pr_Man_t * p );
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Allocate proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Pr_Man_t * Pr_ManAlloc( int nVarsAlloc )
+{
+    Pr_Man_t * p;
+    // allocate the manager
+    p = (Pr_Man_t *)ABC_ALLOC( char, sizeof(Pr_Man_t) );
+    memset( p, 0, sizeof(Pr_Man_t) );
+    // allocate internal arrays
+    Pr_ManResize( p, nVarsAlloc? nVarsAlloc : 256 );
+    // set the starting number of variables
+    p->nVars = 0;
+    // memory management
+    p->nChunkSize = (1<<16); // use 64K chunks
+    // verification
+    p->nResLitsAlloc = (1<<16);
+    p->pResLits = ABC_ALLOC( lit, p->nResLitsAlloc );
+    // parameters
+    p->fProofWrite = 0;
+    p->fProofVerif = 0;
+    return p;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Resize proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pr_ManResize( Pr_Man_t * p, int nVarsNew )
+{
+    // check if resizing is needed
+    if ( p->nVarsAlloc < nVarsNew )
+    {
+        int nVarsAllocOld = p->nVarsAlloc;
+        // find the new size
+        if ( p->nVarsAlloc == 0 )
+            p->nVarsAlloc = 1;
+        while ( p->nVarsAlloc < nVarsNew ) 
+            p->nVarsAlloc *= 2;
+        // resize the arrays
+        p->pTrail    = ABC_REALLOC(lit,        p->pTrail,    p->nVarsAlloc );
+        p->pAssigns  = ABC_REALLOC(lit,        p->pAssigns,  p->nVarsAlloc );
+        p->pSeens    = ABC_REALLOC(char,       p->pSeens,    p->nVarsAlloc );
+        p->pVarTypes = ABC_REALLOC(char,       p->pVarTypes, p->nVarsAlloc );
+        p->pReasons  = ABC_REALLOC(Pr_Cls_t *, p->pReasons,  p->nVarsAlloc );
+        p->pWatches  = ABC_REALLOC(Pr_Cls_t *, p->pWatches,  p->nVarsAlloc*2 );
+        // clean the free space
+        memset( p->pAssigns  + nVarsAllocOld, 0xff, sizeof(lit) * (p->nVarsAlloc - nVarsAllocOld) );
+        memset( p->pSeens    + nVarsAllocOld, 0, sizeof(char) * (p->nVarsAlloc - nVarsAllocOld) );
+        memset( p->pVarTypes + nVarsAllocOld, 0, sizeof(char) * (p->nVarsAlloc - nVarsAllocOld) );
+        memset( p->pReasons  + nVarsAllocOld, 0, sizeof(Pr_Cls_t *) * (p->nVarsAlloc - nVarsAllocOld) );
+        memset( p->pWatches  + nVarsAllocOld, 0, sizeof(Pr_Cls_t *) * (p->nVarsAlloc - nVarsAllocOld)*2 );
+    }
+    // adjust the number of variables
+    if ( p->nVars < nVarsNew )
+        p->nVars = nVarsNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Deallocate proof manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pr_ManFree( Pr_Man_t * p )
+{
+    printf( "Runtime stats:\n" );
+ABC_PRT( "Reading ", p->timeRead  );
+ABC_PRT( "BCP     ", p->timeBcp   );
+ABC_PRT( "Trace   ", p->timeTrace );
+ABC_PRT( "TOTAL   ", p->timeTotal );
+
+    Pr_ManMemoryStop( p );
+    ABC_FREE( p->pTrail );
+    ABC_FREE( p->pAssigns );
+    ABC_FREE( p->pSeens );
+    ABC_FREE( p->pVarTypes );
+    ABC_FREE( p->pReasons );
+    ABC_FREE( p->pWatches );
+    ABC_FREE( p->pResLits );
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one clause to the watcher list.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Pr_ManWatchClause( Pr_Man_t * p, Pr_Cls_t * pClause, lit Lit )
+{
+    assert( lit_check(Lit, p->nVars) );
+    if ( pClause->pLits[0] == Lit )
+        pClause->pNext0 = p->pWatches[lit_neg(Lit)];  
+    else
+    {
+        assert( pClause->pLits[1] == Lit );
+        pClause->pNext1 = p->pWatches[lit_neg(Lit)];  
+    }
+    p->pWatches[lit_neg(Lit)] = pClause;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Adds one clause to the manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pr_ManAddClause( Pr_Man_t * p, lit * pBeg, lit * pEnd, int fRoot, int fClauseA )
+{
+    Pr_Cls_t * pClause;
+    lit Lit, * i, * j;
+    int nSize, VarMax;
+
+    // process the literals
+    if ( pBeg < pEnd )
+    {
+        // insertion sort
+        VarMax = lit_var( *pBeg );
+        for ( i = pBeg + 1; i < pEnd; i++ )
+        {
+            Lit = *i;
+            VarMax = lit_var(Lit) > VarMax ? lit_var(Lit) : VarMax;
+            for ( j = i; j > pBeg && *(j-1) > Lit; j-- )
+                *j = *(j-1);
+            *j = Lit;
+        }
+        // make sure there is no duplicated variables
+        for ( i = pBeg + 1; i < pEnd; i++ )
+            assert( lit_var(*(i-1)) != lit_var(*i) );
+        // resize the manager
+        Pr_ManResize( p, VarMax+1 );
+    }
+
+    // get memory for the clause
+    nSize = sizeof(Pr_Cls_t) + sizeof(lit) * (pEnd - pBeg);
+    pClause = (Pr_Cls_t *)Pr_ManMemoryFetch( p, nSize );
+    memset( pClause, 0, sizeof(Pr_Cls_t) );
+
+    // assign the clause
+    assert( !fClauseA || fRoot ); // clause of A is always a root clause
+    p->nRoots += fRoot;
+    p->nClausesA += fClauseA;
+    pClause->Id = p->nClauses++;
+    pClause->fA = fClauseA;
+    pClause->fRoot = fRoot;
+    pClause->nLits = pEnd - pBeg;
+    memcpy( pClause->pLits, pBeg, sizeof(lit) * (pEnd - pBeg) );
+
+    // add the clause to the list
+    if ( p->pHead == NULL )
+        p->pHead = pClause;
+    if ( p->pTail == NULL )
+        p->pTail = pClause;
+    else
+    {
+        p->pTail->pNext = pClause;
+        p->pTail = pClause;
+    }
+
+    // mark the first learnt clause
+    if ( p->pLearnt == NULL && !pClause->fRoot )
+        p->pLearnt = pClause;
+
+    // add the empty clause
+    if ( pClause->nLits == 0 )
+    {
+        if ( p->pEmpty )
+            printf( "More than one empty clause!\n" );
+        p->pEmpty = pClause;
+    }
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Fetches memory.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Pr_ManMemoryFetch( Pr_Man_t * p, int nBytes )
+{
+    char * pMem;
+    if ( p->pChunkLast == NULL || nBytes > p->nChunkSize - p->nChunkUsed )
+    {
+        pMem = (char *)ABC_ALLOC( char, p->nChunkSize );
+        *(char **)pMem = p->pChunkLast;
+        p->pChunkLast = pMem;
+        p->nChunkUsed = sizeof(char *);
+    }
+    pMem = p->pChunkLast + p->nChunkUsed;
+    p->nChunkUsed += nBytes;
+    return pMem;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Frees memory manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pr_ManMemoryStop( Pr_Man_t * p )
+{
+    char * pMem, * pNext;
+    if ( p->pChunkLast == NULL )
+        return;
+    for ( pMem = p->pChunkLast; pNext = *(char **)pMem; pMem = pNext )
+        ABC_FREE( pMem );
+    ABC_FREE( pMem );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reports memory usage in bytes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pr_ManMemoryReport( Pr_Man_t * p )
+{
+    int Total;
+    char * pMem, * pNext;
+    if ( p->pChunkLast == NULL )
+        return 0;
+    Total = p->nChunkUsed; 
+    for ( pMem = p->pChunkLast; pNext = *(char **)pMem; pMem = pNext )
+        Total += p->nChunkSize;
+    return Total;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records the proof.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Extra_PrintBinary_( FILE * pFile, unsigned Sign[], int nBits )
+{
+    int Remainder, nWords;
+    int w, i;
+
+    Remainder = (nBits%(sizeof(unsigned)*8));
+    nWords    = (nBits/(sizeof(unsigned)*8)) + (Remainder>0);
+
+    for ( w = nWords-1; w >= 0; w-- )
+        for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- )
+            fprintf( pFile, "%c", '0' + (int)((Sign[w] & (1<<i)) > 0) );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the interpolant for one clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pr_ManPrintInterOne( Pr_Man_t * p, Pr_Cls_t * pClause )
+{
+    printf( "Clause %2d :  ", pClause->Id );
+    Extra_PrintBinary_( stdout, &pClause->uTruth, (1 << p->nVarsAB) );
+    printf( "\n" );
+}
+
+
+
+/**Function*************************************************************
+
+  Synopsis    [Records implication.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Pr_ManEnqueue( Pr_Man_t * p, lit Lit, Pr_Cls_t * pReason )
+{
+    int Var = lit_var(Lit);
+    if ( p->pAssigns[Var] != LIT_UNDEF )
+        return p->pAssigns[Var] == Lit;
+    p->pAssigns[Var] = Lit;
+    p->pReasons[Var] = pReason;
+    p->pTrail[p->nTrailSize++] = Lit;
+//printf( "assigning var %d value %d\n", Var, !lit_sign(Lit) );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records implication.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Pr_ManCancelUntil( Pr_Man_t * p, int Level )
+{
+    lit Lit;
+    int i, Var;
+    for ( i = p->nTrailSize - 1; i >= Level; i-- )
+    {
+        Lit = p->pTrail[i];
+        Var = lit_var( Lit );
+        p->pReasons[Var] = NULL;
+        p->pAssigns[Var] = LIT_UNDEF;
+//printf( "cancelling var %d\n", Var );
+    }
+    p->nTrailSize = Level;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagate one assignment.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline Pr_Cls_t * Pr_ManPropagateOne( Pr_Man_t * p, lit Lit )
+{
+    Pr_Cls_t ** ppPrev, * pCur, * pTemp;
+    lit LitF = lit_neg(Lit);
+    int i;
+    // iterate through the literals
+    ppPrev = p->pWatches + Lit;
+    for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev )
+    {
+        // make sure the false literal is in the second literal of the clause
+        if ( pCur->pLits[0] == LitF )
+        {
+            pCur->pLits[0] = pCur->pLits[1];
+            pCur->pLits[1] = LitF;
+            pTemp = pCur->pNext0;
+            pCur->pNext0 = pCur->pNext1;
+            pCur->pNext1 = pTemp;
+        }
+        assert( pCur->pLits[1] == LitF );
+
+        // if the first literal is true, the clause is satisfied
+        if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] )
+        {
+            ppPrev = &pCur->pNext1;
+            continue;
+        }
+
+        // look for a new literal to watch
+        for ( i = 2; i < (int)pCur->nLits; i++ )
+        {
+            // skip the case when the literal is false
+            if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] )
+                continue;
+            // the literal is either true or unassigned - watch it
+            pCur->pLits[1] = pCur->pLits[i];
+            pCur->pLits[i] = LitF;
+            // remove this clause from the watch list of Lit
+            *ppPrev = pCur->pNext1;
+            // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1])
+            Pr_ManWatchClause( p, pCur, pCur->pLits[1] );
+            break;
+        }
+        if ( i < (int)pCur->nLits ) // found new watch
+            continue;
+
+        // clause is unit - enqueue new implication
+        if ( Pr_ManEnqueue(p, pCur->pLits[0], pCur) )
+        {
+            ppPrev = &pCur->pNext1;
+            continue;
+        }
+
+        // conflict detected - return the conflict clause
+        return pCur;
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagate the current assignments.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Pr_Cls_t * Pr_ManPropagate( Pr_Man_t * p, int Start )
+{
+    Pr_Cls_t * pClause;
+    int i;
+    abctime clk = Abc_Clock();
+    for ( i = Start; i < p->nTrailSize; i++ )
+    {
+        pClause = Pr_ManPropagateOne( p, p->pTrail[i] );
+        if ( pClause )
+        {
+p->timeBcp += Abc_Clock() - clk;
+            return pClause;
+        }
+    }
+p->timeBcp += Abc_Clock() - clk;
+    return NULL;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pr_ManPrintClause( Pr_Cls_t * pClause )
+{
+    int i;
+    printf( "Clause ID = %d. Proof = %d. {", pClause->Id, (int)pClause->pProof );
+    for ( i = 0; i < (int)pClause->nLits; i++ )
+        printf( " %d", pClause->pLits[i] );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prints the resolvent.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pr_ManPrintResolvent( lit * pResLits, int nResLits )
+{
+    int i;
+    printf( "Resolvent: {" );
+    for ( i = 0; i < nResLits; i++ )
+        printf( " %d", pResLits[i] );
+    printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Writes one root clause into a file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pr_ManProofWriteOne( Pr_Man_t * p, Pr_Cls_t * pClause )
+{
+    pClause->pProof = (void *)++p->Counter;
+
+    if ( p->fProofWrite )
+    {
+        int v;
+        fprintf( (FILE *)p->pManProof, "%d", (int)pClause->pProof );
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+            fprintf( (FILE *)p->pManProof, " %d", lit_print(pClause->pLits[v]) );
+        fprintf( (FILE *)p->pManProof, " 0 0\n" );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Traces the proof for one clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pr_ManProofTraceOne( Pr_Man_t * p, Pr_Cls_t * pConflict, Pr_Cls_t * pFinal )
+{
+    Pr_Cls_t * pReason;
+    int i, v, Var, PrevId;
+    int fPrint = 0;
+    abctime clk = Abc_Clock();
+
+    // collect resolvent literals
+    if ( p->fProofVerif )
+    {
+        assert( (int)pConflict->nLits <= p->nResLitsAlloc );
+        memcpy( p->pResLits, pConflict->pLits, sizeof(lit) * pConflict->nLits );
+        p->nResLits = pConflict->nLits;
+    }
+
+    // mark all the variables in the conflict as seen
+    for ( v = 0; v < (int)pConflict->nLits; v++ )
+        p->pSeens[lit_var(pConflict->pLits[v])] = 1;
+
+    // start the anticedents
+//    pFinal->pAntis = Vec_PtrAlloc( 32 );
+//    Vec_PtrPush( pFinal->pAntis, pConflict );
+
+    if ( p->nClausesA )
+        pFinal->uTruth = pConflict->uTruth;
+   
+    // follow the trail backwards
+    PrevId = (int)pConflict->pProof;
+    for ( i = p->nTrailSize - 1; i >= 0; i-- )
+    {
+        // skip literals that are not involved
+        Var = lit_var(p->pTrail[i]);
+        if ( !p->pSeens[Var] )
+            continue;
+        p->pSeens[Var] = 0;
+
+        // skip literals of the resulting clause
+        pReason = p->pReasons[Var];
+        if ( pReason == NULL )
+            continue;
+        assert( p->pTrail[i] == pReason->pLits[0] );
+
+        // add the variables to seen
+        for ( v = 1; v < (int)pReason->nLits; v++ )
+            p->pSeens[lit_var(pReason->pLits[v])] = 1;
+
+
+        // record the reason clause
+        assert( pReason->pProof > 0 );
+        p->Counter++;
+        if ( p->fProofWrite )
+            fprintf( (FILE *)p->pManProof, "%d * %d %d 0\n", p->Counter, PrevId, (int)pReason->pProof );
+        PrevId = p->Counter;
+
+        if ( p->nClausesA )
+        {
+            if ( p->pVarTypes[Var] == 1 ) // var of A
+                pFinal->uTruth |= pReason->uTruth;
+            else
+                pFinal->uTruth &= pReason->uTruth;
+        }
+ 
+        // resolve the temporary resolvent with the reason clause
+        if ( p->fProofVerif )
+        {
+            int v1, v2; 
+            if ( fPrint )
+                Pr_ManPrintResolvent( p->pResLits, p->nResLits );
+            // check that the var is present in the resolvent
+            for ( v1 = 0; v1 < p->nResLits; v1++ )
+                if ( lit_var(p->pResLits[v1]) == Var )
+                    break;
+            if ( v1 == p->nResLits )
+                printf( "Recording clause %d: Cannot find variable %d in the temporary resolvent.\n", pFinal->Id, Var );
+            if ( p->pResLits[v1] != lit_neg(pReason->pLits[0]) )
+                printf( "Recording clause %d: The resolved variable %d is in the wrong polarity.\n", pFinal->Id, Var );
+            // remove this variable from the resolvent
+            assert( lit_var(p->pResLits[v1]) == Var );
+            p->nResLits--;
+            for ( ; v1 < p->nResLits; v1++ )
+                p->pResLits[v1] = p->pResLits[v1+1];
+            // add variables of the reason clause
+            for ( v2 = 1; v2 < (int)pReason->nLits; v2++ )
+            {
+                for ( v1 = 0; v1 < p->nResLits; v1++ )
+                    if ( lit_var(p->pResLits[v1]) == lit_var(pReason->pLits[v2]) )
+                        break;
+                // if it is a new variable, add it to the resolvent
+                if ( v1 == p->nResLits ) 
+                {
+                    if ( p->nResLits == p->nResLitsAlloc )
+                        printf( "Recording clause %d: Ran out of space for intermediate resolvent.\n, pFinal->Id" );
+                    p->pResLits[ p->nResLits++ ] = pReason->pLits[v2];
+                    continue;
+                }
+                // if the variable is the same, the literal should be the same too
+                if ( p->pResLits[v1] == pReason->pLits[v2] )
+                    continue;
+                // the literal is different
+                printf( "Recording clause %d: Trying to resolve the clause with more than one opposite literal.\n", pFinal->Id );
+            }
+        }
+
+//        Vec_PtrPush( pFinal->pAntis, pReason );
+    }
+
+    // unmark all seen variables
+//    for ( i = p->nTrailSize - 1; i >= 0; i-- )
+//        p->pSeens[lit_var(p->pTrail[i])] = 0;
+    // check that the literals are unmarked
+//    for ( i = p->nTrailSize - 1; i >= 0; i-- )
+//        assert( p->pSeens[lit_var(p->pTrail[i])] == 0 );
+
+    // use the resulting clause to check the correctness of resolution
+    if ( p->fProofVerif )
+    {
+        int v1, v2; 
+        if ( fPrint )
+            Pr_ManPrintResolvent( p->pResLits, p->nResLits );
+        for ( v1 = 0; v1 < p->nResLits; v1++ )
+        {
+            for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ )
+                if ( pFinal->pLits[v2] == p->pResLits[v1] )
+                    break;
+            if ( v2 < (int)pFinal->nLits )
+                continue;
+            break;
+        }
+        if ( v1 < p->nResLits )
+        {
+            printf( "Recording clause %d: The final resolvent is wrong.\n", pFinal->Id );
+            Pr_ManPrintClause( pConflict );
+            Pr_ManPrintResolvent( p->pResLits, p->nResLits );
+            Pr_ManPrintClause( pFinal );
+        }
+    }
+p->timeTrace += Abc_Clock() - clk;
+
+    // return the proof pointer 
+    if ( p->nClausesA )
+    {
+        Pr_ManPrintInterOne( p, pFinal );
+    }
+    return p->Counter;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records the proof for one clause.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pr_ManProofRecordOne( Pr_Man_t * p, Pr_Cls_t * pClause )
+{
+    Pr_Cls_t * pConflict;
+    int i;
+
+    // empty clause never ends up there
+    assert( pClause->nLits > 0 );
+    if ( pClause->nLits == 0 )
+        printf( "Error: Empty clause is attempted.\n" );
+
+    // add assumptions to the trail
+    assert( !pClause->fRoot );
+    assert( p->nTrailSize == p->nRootSize );
+    for ( i = 0; i < (int)pClause->nLits; i++ )
+        if ( !Pr_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) )
+        {
+            assert( 0 ); // impossible
+            return 0;
+        }
+
+    // propagate the assumptions
+    pConflict = Pr_ManPropagate( p, p->nRootSize );
+    if ( pConflict == NULL )
+    {
+        assert( 0 ); // cannot prove
+        return 0;
+    }
+
+    // construct the proof
+    pClause->pProof = (void *)Pr_ManProofTraceOne( p, pConflict, pClause );
+
+    // undo to the root level
+    Pr_ManCancelUntil( p, p->nRootSize );
+
+    // add large clauses to the watched lists
+    if ( pClause->nLits > 1 )
+    {
+        Pr_ManWatchClause( p, pClause, pClause->pLits[0] );
+        Pr_ManWatchClause( p, pClause, pClause->pLits[1] );
+        return 1;
+    }
+    assert( pClause->nLits == 1 );
+
+    // if the clause proved is unit, add it and propagate
+    if ( !Pr_ManEnqueue( p, pClause->pLits[0], pClause ) )
+    {
+        assert( 0 ); // impossible
+        return 0;
+    }
+
+    // propagate the assumption
+    pConflict = Pr_ManPropagate( p, p->nRootSize );
+    if ( pConflict )
+    {
+        // construct the proof
+        p->pEmpty->pProof = (void *)Pr_ManProofTraceOne( p, pConflict, p->pEmpty );
+        printf( "Found last conflict after adding unit clause number %d!\n", pClause->Id );
+        return 0;
+    }
+
+    // update the root level
+    p->nRootSize = p->nTrailSize;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Propagate the root clauses.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pr_ManProcessRoots( Pr_Man_t * p )
+{
+    Pr_Cls_t * pClause;
+    int Counter;
+
+    // make sure the root clauses are preceeding the learnt clauses
+    Counter = 0;
+    Pr_ManForEachClause( p, pClause )
+    {
+        assert( (int)pClause->fA    == (Counter < (int)p->nClausesA) );
+        assert( (int)pClause->fRoot == (Counter < (int)p->nRoots)    );
+        Counter++;
+    }
+    assert( p->nClauses == Counter );
+
+    // make sure the last clause if empty
+    assert( p->pTail->nLits == 0 );
+
+    // go through the root unit clauses
+    p->nTrailSize = 0;
+    Pr_ManForEachClauseRoot( p, pClause )
+    {
+        // create watcher lists for the root clauses
+        if ( pClause->nLits > 1 )
+        {
+            Pr_ManWatchClause( p, pClause, pClause->pLits[0] );
+            Pr_ManWatchClause( p, pClause, pClause->pLits[1] );
+        }
+        // empty clause and large clauses
+        if ( pClause->nLits != 1 )
+            continue;
+        // unit clause
+        assert( lit_check(pClause->pLits[0], p->nVars) );
+        if ( !Pr_ManEnqueue( p, pClause->pLits[0], pClause ) )
+        {
+            // detected root level conflict
+            printf( "Pr_ManProcessRoots(): Detected a root-level conflict\n" );
+            assert( 0 );
+            return 0;
+        }
+    }
+
+    // propagate the root unit clauses
+    pClause = Pr_ManPropagate( p, 0 );
+    if ( pClause )
+    {
+        // detected root level conflict
+        printf( "Pr_ManProcessRoots(): Detected a root-level conflict\n" );
+        assert( 0 );
+        return 0;
+    }
+
+    // set the root level
+    p->nRootSize = p->nTrailSize;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records the proof.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Pr_ManPrepareInter( Pr_Man_t * p )
+{
+    unsigned uTruths[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+    Pr_Cls_t * pClause;
+    int Var, v;
+
+    // mark the variable encountered in the clauses of A
+    Pr_ManForEachClauseRoot( p, pClause )
+    {
+        if ( !pClause->fA )
+            break;
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+            p->pVarTypes[lit_var(pClause->pLits[v])] = 1;
+    }
+
+    // check variables that appear in clauses of B
+    p->nVarsAB = 0;
+    Pr_ManForEachClauseRoot( p, pClause )
+    {
+        if ( pClause->fA )
+            continue;
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+        {
+            Var = lit_var(pClause->pLits[v]);
+            if ( p->pVarTypes[Var] == 1 ) // var of A
+            {
+                // change it into a global variable
+                p->nVarsAB++;
+                p->pVarTypes[Var] = -1;
+            }
+        }
+    }
+
+    // order global variables
+    p->nVarsAB = 0;
+    for ( v = 0; v < p->nVars; v++ )
+        if ( p->pVarTypes[v] == -1 )
+            p->pVarTypes[v] -= p->nVarsAB++;
+printf( "There are %d global variables.\n", p->nVarsAB );
+
+    // set interpolants for root clauses
+    Pr_ManForEachClauseRoot( p, pClause )
+    {
+        if ( !pClause->fA ) // clause of B
+        {
+            pClause->uTruth = ~0;
+            Pr_ManPrintInterOne( p, pClause );
+            continue;
+        }
+        // clause of A
+        pClause->uTruth = 0;
+        for ( v = 0; v < (int)pClause->nLits; v++ )
+        {
+            Var = lit_var(pClause->pLits[v]);
+            if ( p->pVarTypes[Var] < 0 ) // global var
+            {
+                if ( lit_sign(pClause->pLits[v]) ) // negative var
+                    pClause->uTruth |= ~uTruths[ -p->pVarTypes[Var]-1 ];
+                else
+                    pClause->uTruth |= uTruths[ -p->pVarTypes[Var]-1 ];
+            }
+        }
+        Pr_ManPrintInterOne( p, pClause );
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records the proof.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pr_ManProofWrite( Pr_Man_t * p )
+{
+    Pr_Cls_t * pClause;
+    int RetValue = 1;
+
+    // propagate root level assignments
+    Pr_ManProcessRoots( p );
+
+    // prepare the interpolant computation
+    if ( p->nClausesA )
+        Pr_ManPrepareInter( p );
+
+    // construct proof for each clause
+    // start the proof
+    if ( p->fProofWrite )
+        p->pManProof = fopen( "proof.cnf_", "w" );
+    p->Counter = 0;
+
+    // write the root clauses
+    Pr_ManForEachClauseRoot( p, pClause )
+        Pr_ManProofWriteOne( p, pClause );
+
+    // consider each learned clause
+    Pr_ManForEachClauseLearnt( p, pClause )
+    {
+        if ( !Pr_ManProofRecordOne( p, pClause ) )
+        {
+            RetValue = 0;
+            break;
+        }
+    }
+
+    if ( p->nClausesA )
+    {
+        printf( "Interpolant:  " );
+    }
+
+
+    // stop the proof
+    if ( p->fProofWrite )
+    {
+        fclose( (FILE *)p->pManProof );
+        p->pManProof = NULL;    
+    }
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Reads clauses from file.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Pr_Man_t * Pr_ManProofRead( char * pFileName )
+{
+    Pr_Man_t * p = NULL;
+    char * pCur, * pBuffer = NULL;
+    int * pArray = NULL;
+    FILE * pFile;
+    int RetValue, Counter, nNumbers, Temp;
+    int nClauses, nClausesA, nRoots, nVars;
+
+    // open the file
+    pFile = fopen( pFileName, "r" );
+    if ( pFile == NULL )
+    {
+        printf( "Count not open input file \"%s\".\n", pFileName );
+        return NULL;
+    }
+
+    // read the file
+    pBuffer = (char *)ABC_ALLOC( char, (1<<16) );
+    for ( Counter = 0; fgets( pBuffer, (1<<16), pFile ); )
+    {
+        if ( pBuffer[0] == 'c' )
+            continue;
+        if ( pBuffer[0] == 'p' )
+        {
+            assert( p == NULL );
+            nClausesA = 0;
+            RetValue = sscanf( pBuffer + 1, "%d %d %d %d", &nVars, &nClauses, &nRoots, &nClausesA );
+            if ( RetValue != 3 && RetValue != 4 )
+            {
+                printf( "Wrong input file format.\n" );
+            }
+            p = Pr_ManAlloc( nVars );
+            pArray = (int *)ABC_ALLOC( char, sizeof(int) * (nVars + 10) );
+            continue;
+        }
+        // skip empty lines
+        for ( pCur = pBuffer; *pCur; pCur++ )
+            if ( !(*pCur == ' ' || *pCur == '\t' || *pCur == '\r' || *pCur == '\n') )
+                break;
+        if ( *pCur == 0 )
+            continue;
+        // scan the numbers from file
+        nNumbers = 0;
+        pCur = pBuffer;
+        while ( *pCur )
+        {
+            // skip spaces
+            for ( ; *pCur && *pCur == ' '; pCur++ );
+            // read next number
+            Temp = 0;
+            sscanf( pCur, "%d", &Temp );
+            if ( Temp == 0 )
+                break;
+            pArray[ nNumbers++ ] = lit_read( Temp );
+            // skip non-spaces
+            for ( ; *pCur && *pCur != ' '; pCur++ );
+        }
+        // add the clause
+        if ( !Pr_ManAddClause( p, (unsigned *)pArray, (unsigned *)pArray + nNumbers, Counter < nRoots, Counter < nClausesA ) )
+        {
+            printf( "Bad clause number %d.\n", Counter );
+            return NULL;
+        }
+        // count the clauses
+        Counter++;
+    }
+    // check the number of clauses
+    if ( Counter != nClauses )
+        printf( "Expected %d clauses but read %d.\n", nClauses, Counter );
+
+    // finish
+    if ( pArray ) ABC_FREE( pArray );
+    if ( pBuffer ) ABC_FREE( pBuffer );
+    fclose( pFile );
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Records the proof.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+/*
+int Pr_ManProofCount_rec( Pr_Cls_t * pClause )
+{
+    Pr_Cls_t * pNext;
+    int i, Counter;    
+    if ( pClause->fRoot )
+        return 0;
+    if ( pClause->fVisit )
+        return 0;
+    pClause->fVisit = 1;
+    // count the number of visited clauses
+    Counter = 1;
+    Vec_PtrForEachEntry( Pr_Cls_t *, pClause->pAntis, pNext, i )
+        Counter += Pr_ManProofCount_rec( pNext );
+    return Counter;
+}
+*/
+
+/**Function*************************************************************
+
+  Synopsis    [Records the proof.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Pr_ManProofTest( char * pFileName )
+{
+    Pr_Man_t * p;
+    abctime clk, clkTotal = Abc_Clock();
+
+clk = Abc_Clock();
+    p = Pr_ManProofRead( pFileName );
+p->timeRead = Abc_Clock() - clk;
+    if ( p == NULL )
+        return 0;
+
+    Pr_ManProofWrite( p );
+
+    // print stats
+/*
+    nUsed = Pr_ManProofCount_rec( p->pEmpty );
+    printf( "Roots = %d. Learned = %d. Total = %d. Steps = %d.  Ave = %.2f.  Used = %d. Ratio = %.2f. \n", 
+        p->nRoots, p->nClauses-p->nRoots, p->nClauses, p->Counter,  
+        1.0*(p->Counter-p->nRoots)/(p->nClauses-p->nRoots),
+        nUsed, 1.0*nUsed/(p->nClauses-p->nRoots)  );
+*/
+    printf( "Vars = %d. Roots = %d. Learned = %d. Resol steps = %d.  Ave = %.2f.  Mem = %.2f MB\n", 
+        p->nVars, p->nRoots, p->nClauses-p->nRoots, p->Counter,  
+        1.0*(p->Counter-p->nRoots)/(p->nClauses-p->nRoots), 
+        1.0*Pr_ManMemoryReport(p)/(1<<20) );
+
+p->timeTotal = Abc_Clock() - clkTotal;
+    Pr_ManFree( p );
+    return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abc-build/src/sat/proof/pr.h b/abc-build/src/sat/proof/pr.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/proof/pr.h
@@ -0,0 +1,69 @@
+/**CFile****************************************************************
+
+  FileName    [pr.h]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Proof recording.]
+
+  Synopsis    [External declarations.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: pr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+ 
+#ifndef ABC__sat__proof__pr_h
+#define ABC__sat__proof__pr_h
+
+
+#ifdef _WIN32
+#define inline __inline // compatible with MS VS 6.0
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                          INCLUDES                                ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                         PARAMETERS                               ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+///                         BASIC TYPES                              ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Pr_Man_t_ Pr_Man_t;
+
+////////////////////////////////////////////////////////////////////////
+///                      MACRO DEFINITIONS                           ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+///                    FUNCTION DECLARATIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== pr.c ==========================================================*/
+ 
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/abc-build/src/sat/proof/stats.txt b/abc-build/src/sat/proof/stats.txt
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/proof/stats.txt
@@ -0,0 +1,66 @@
+UC Berkeley, ABC 1.01 (compiled Jan 20 2007 16:47:34)
+abc.rc: No such file or directory
+Loaded "abc.rc" from the parent directory.
+abc 01> test
+Found last conflict after adding unit clause number 10229!
+Roots = 7184. Learned = 3047. Total = 10231. Steps = 196361.  Ave = 62.09.  Used = 2224. Ratio = 0.73.
+Runtime stats:
+Reading  =   0.03 sec
+BCP      =   0.32 sec
+Trace    =   0.06 sec
+TOTAL    =   0.43 sec
+abc 01> test
+Found last conflict after adding unit clause number 7676!
+Roots = 6605. Learned = 1073. Total = 7678. Steps = 52402.  Ave = 42.68.  Used = 1011. Ratio = 0.94.
+Runtime stats:
+Reading  =   0.01 sec
+BCP      =   0.02 sec
+Trace    =   0.02 sec
+TOTAL    =   0.06 sec
+abc 01> test
+Found last conflict after adding unit clause number 37868!
+Roots = 15443. Learned = 22427. Total = 37870. Steps = 2365472.  Ave = 104.79.  Used = 19763. Ratio = 0.88.
+Runtime stats:
+Reading  =   0.20 sec
+BCP      =  14.67 sec
+Trace    =   0.56 sec
+TOTAL    =  15.74 sec
+abc 01>
+
+
+abc 05> wb ibm_bmc/len25u_renc.blif
+abc 05> ps
+(no name)    : i/o =  348/   1  lat =    0  nd =  3648  bdd  = 15522  lev = 246
+abc 05> sat -v
+==================================[MINISAT]===================================
+| Conflicts |     ORIGINAL     |              LEARNT              | Progress |
+|           | Clauses Literals |   Limit Clauses Literals  Lit/Cl |          |
+==============================================================================
+|         0 |   17413    54996 |    5804       0        0     0.0 |  0.000 % |
+|       100 |   17413    54996 |    6384     100      606     6.1 |  0.417 % |
+|       250 |   17413    54996 |    7023     250     1586     6.3 |  0.417 % |
+|       476 |   17413    54996 |    7725     476     3288     6.9 |  0.417 % |
+|       813 |   17413    54996 |    8498     813     7586     9.3 |  0.417 % |
+|      1319 |   17403    54970 |    9347    1318    14848    11.3 |  0.442 % |
+|      2078 |   17403    54970 |   10282    2076    40186    19.4 |  0.466 % |
+|      3217 |   17397    54948 |   11310    3208    99402    31.0 |  0.466 % |
+|      4926 |   17392    54930 |   12441    4911   131848    26.8 |  0.491 % |
+|      7489 |   17392    54930 |   13686    7474   204217    27.3 |  0.491 % |
+|     11336 |   17357    54829 |   15054   11310   332863    29.4 |  0.638 % |
+|     17103 |   17346    54794 |   16559    9130   203029    22.2 |  0.687 % |
+|     25752 |   17288    54606 |   18215    9083   176982    19.5 |  0.834 % |
+|     38727 |   17266    54536 |   20037   12674   278949    22.0 |  0.883 % |
+|     58188 |   17240    54453 |   22041   11905   255255    21.4 |  0.957 % |
+==============================================================================
+Start =   15. Conf =  79435. Dec = 130967. Prop = 24083434. Insp = 136774586.
+Total runtime =   18.66 sec.  Var select =    0.00 sec.  Var update =    0.00 sec.
+UNSATISFIABLE  Time =  18.69 sec
+abc 05>
+abc 05> test
+Found last conflict after adding unit clause number 96902!
+Roots = 17469. Learned = 79435. Total = 96904. Steps = 9700042.  Ave = 121.89.  Used = 57072. Ratio = 0.72.
+Runtime stats:
+Reading  =   1.26 sec
+BCP      = 204.99 sec
+Trace    =   2.85 sec
+TOTAL    = 209.85 sec
diff --git a/abc-build/src/sat/psat/m114p.h b/abc-build/src/sat/psat/m114p.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/psat/m114p.h
@@ -0,0 +1,47 @@
+// C-language header for MiniSat 1.14p
+
+#ifndef ABC__sat__psat__m114p_h
+#define ABC__sat__psat__m114p_h
+
+
+#include "m114p_types.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+// SAT solver APIs
+extern M114p_Solver_t M114p_SolverNew( int fRecordProof );
+extern void           M114p_SolverDelete( M114p_Solver_t s );
+extern void           M114p_SolverPrintStats( M114p_Solver_t s, double Time );
+extern void           M114p_SolverSetVarNum( M114p_Solver_t s, int nVars );
+extern int            M114p_SolverAddClause( M114p_Solver_t s, lit* begin, lit* end );
+extern int            M114p_SolverSimplify( M114p_Solver_t s );
+extern int            M114p_SolverSolve( M114p_Solver_t s, lit* begin, lit* end, int nConfLimit );
+extern int            M114p_SolverGetConflictNum( M114p_Solver_t s );
+
+// proof status APIs
+extern int            M114p_SolverProofIsReady( M114p_Solver_t s );
+extern void           M114p_SolverProofSave( M114p_Solver_t s, char * pFileName );
+extern int            M114p_SolverProofClauseNum( M114p_Solver_t s );
+
+// proof traversal APIs
+extern int            M114p_SolverGetFirstRoot( M114p_Solver_t s, int ** ppLits );
+extern int            M114p_SolverGetNextRoot( M114p_Solver_t s, int ** ppLits );
+extern int            M114p_SolverGetFirstChain( M114p_Solver_t s, int ** ppClauses, int ** ppVars );
+extern int            M114p_SolverGetNextChain( M114p_Solver_t s, int ** ppClauses, int ** ppVars );
+
+// iterator over the root clauses (should be called first)
+#define M114p_SolverForEachRoot( s, ppLits, nLits, i )                           \
+    for ( i = 0, nLits = M114p_SolverGetFirstRoot(s, ppLits); nLits;             \
+          i++, nLits = M114p_SolverGetNextRoot(s, ppLits) )
+
+// iterator over the learned clauses (should be called after iterating over roots)
+#define M114p_SolverForEachChain( s, ppClauses, ppVars, nVars, i )               \
+    for ( i = 0, nVars = M114p_SolverGetFirstChain(s, ppClauses, ppVars); nVars; \
+          i++, nVars = M114p_SolverGetNextChain(s, ppClauses, ppVars) )
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/sat/psat/m114p_types.h b/abc-build/src/sat/psat/m114p_types.h
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/psat/m114p_types.h
@@ -0,0 +1,13 @@
+// C-language header for MiniSat 1.14p
+
+#ifndef ABC__sat__psat__m114p_types_h
+#define ABC__sat__psat__m114p_types_h
+
+
+ABC_NAMESPACE_HEADER_START
+
+typedef int   M114p_Solver_t;
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
diff --git a/abc-build/src/sat/psat/module.make b/abc-build/src/sat/psat/module.make
new file mode 100644
--- /dev/null
+++ b/abc-build/src/sat/psat/module.make
@@ -0,0 +1,1 @@
+SRC += 
diff --git a/abc-build/src/starter.c b/abc-build/src/starter.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/starter.c
@@ -0,0 +1,190 @@
+/**CFile****************************************************************
+
+  FileName    [starter.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Wrapper for calling ABC.]
+
+  Synopsis    [A demo program illustrating parallel execution of ABC.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - October 22, 2009.]
+
+  Revision    [$Id: starter.c,v 1.00 2009/10/22 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+// To compile on Linux run:  gcc -pthread -o starter starter.c
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#ifdef WIN32
+#include "pthread.h"
+#else
+#include <pthread.h>
+#include <unistd.h>
+#endif
+
+// the max number of commands to execute from the input file
+#define MAX_COMM_NUM 1000
+
+// time printing
+#define ABC_PRT(a,t)    (printf("%s = ", (a)), printf("%7.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)))
+
+// the number of currently running threads
+static int nThreadsRunning = 0;
+
+// mutext to control access to the number of threads
+pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+// procedure for duplicating strings
+char * Abc_UtilStrsav( char * s )   { return s ? strcpy(malloc(strlen(s)+1), s) : NULL;  }
+
+/**Function*************************************************************
+
+  Synopsis    [This procedures executes one call to system().]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void * Abc_RunThread( void * Command )
+{
+    // perform the call
+    if ( system( (char *)Command ) )
+    {
+        assert(pthread_mutex_lock(&mutex) == 0);
+        fprintf( stderr, "The following command has returned non-zero exit status:\n" );
+        fprintf( stderr, "\"%s\"\n", (char *)Command );
+        fprintf( stderr, "Sorry for the inconvenience.\n" );
+        fflush( stdout );
+        assert(pthread_mutex_unlock(&mutex) == 0);
+    }
+
+    // decrement the number of threads runining 
+    assert(pthread_mutex_lock(&mutex) == 0);
+    nThreadsRunning--;
+    assert(pthread_mutex_unlock(&mutex) == 0);
+
+    // quit this thread
+	//printf("...Finishing %s\n", (char *)Command);
+    free( Command );
+	pthread_exit( NULL );
+	assert(0);
+	return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Takes file with commands to be executed and the number of CPUs.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int main( int argc, char * argv[] )
+{
+    FILE * pFile, * pOutput = stdout;
+	pthread_t ThreadIds[MAX_COMM_NUM];
+    char * pBufferCopy, Buffer[MAX_COMM_NUM];
+	int i, nCPUs = 0, nLines = 0, Counter;
+    clock_t clk = clock();
+    
+    // check command line arguments
+    if ( argc != 3 )
+        { fprintf( stderr, "Wrong number of command line arguments.\n" ); goto usage; }
+
+    // get the number of CPUs
+    nCPUs = atoi( argv[1] );
+    if ( nCPUs <= 0 )
+        { fprintf( pOutput, "Cannot read an integer represting the number of CPUs.\n" ); goto usage; }
+
+    // open the file and make sure it is available
+    pFile = fopen( argv[2], "r" );
+    if ( pFile == NULL )
+        { fprintf( pOutput, "Input file \"%s\" cannot be opened.\n", argv[2] ); goto usage; }
+
+    // read commands and execute at most <num> of them at a time
+//    assert(mutex == PTHREAD_MUTEX_INITIALIZER);
+    while ( fgets( Buffer, MAX_COMM_NUM, pFile ) != NULL )
+    {
+        // get the command from the file
+        if ( Buffer[0] == '\n' || Buffer[0] == '\r' || Buffer[0] == '\t' || 
+			 Buffer[0] == ' ' || Buffer[0] == '#')
+		{
+            continue;
+		}
+
+        if ( Buffer[strlen(Buffer)-1] == '\n' )
+            Buffer[strlen(Buffer)-1] = 0;
+        if ( Buffer[strlen(Buffer)-1] == '\r' )
+            Buffer[strlen(Buffer)-1] = 0;
+
+        // wait till there is an empty thread
+        while ( 1 )
+        {
+            assert(pthread_mutex_lock(&mutex) == 0);
+            Counter = nThreadsRunning;
+            assert(pthread_mutex_unlock(&mutex) == 0);
+            if ( Counter < nCPUs - 1 )
+                break;
+//            Sleep( 100 );
+        }
+
+        // increament the number of threads running
+        assert(pthread_mutex_lock(&mutex) == 0);
+        nThreadsRunning++;
+        printf( "Calling:  %s\n", (char *)Buffer );  
+        fflush( stdout );
+        assert(pthread_mutex_unlock(&mutex) == 0);
+
+        // create thread to execute this command
+        pBufferCopy = Abc_UtilStrsav( Buffer );
+        assert(pthread_create( &ThreadIds[nLines], NULL, Abc_RunThread, (void *)pBufferCopy ) == 0);
+        if ( ++nLines == MAX_COMM_NUM )
+            { fprintf( pOutput, "Cannot execute more than %d commands from file \"%s\".\n", nLines, argv[2] ); break; }
+    }
+
+    // wait for all the threads to finish
+    while ( 1 )
+    {
+        assert(pthread_mutex_lock(&mutex) == 0);
+        Counter = nThreadsRunning;
+        assert(pthread_mutex_unlock(&mutex) == 0);
+        if ( Counter == 0 )
+            break;
+    }
+
+    // cleanup
+    assert(pthread_mutex_destroy(&mutex) == 0);
+//    assert(mutex == NULL);
+    fclose( pFile );
+    printf( "Finished processing commands in file \"%s\".  ", argv[2] );
+    ABC_PRT( "Total time", clock() - clk );
+	return 0;
+
+usage: 
+    // skip the path name till the binary name
+    for ( i = strlen(argv[0]) - 1; i > 0; i-- )
+        if ( argv[0][i-1] == '\\' || argv[0][i-1] == '/' )
+            break;
+    // print usage message
+    fprintf( pOutput, "usage: %s <num> <file>\n", argv[0]+i );
+    fprintf( pOutput, "       executes command listed in <file> in parallel on <num> CPUs\n" );
+    fprintf( pOutput, "\n" );
+    return 1;
+
+}
+
diff --git a/abc-build/src/template.c b/abc-build/src/template.c
new file mode 100644
--- /dev/null
+++ b/abc-build/src/template.c
@@ -0,0 +1,111 @@
+/**CFile****************************************************************
+
+  FileName    [.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName []
+
+  Synopsis    []
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: .c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig/aig/aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+
+// parameter structure 
+typedef struct Xyz_ParTry_t_ Xyz_ParTry_t;
+struct Xyz_ParTry_t_
+{
+    int                Par;
+};
+ 
+// operation manager
+typedef struct Xyz_ManTry_t_ Xyz_ManTry_t;
+struct Xyz_ManTry_t_
+{
+    Xyz_ParTry_t *     pPar;           // parameters
+    Aig_Man_t *        pAig;           // user's AIG 
+};
+
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+ 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Xyz_ManTry_t * Xyz_ManTryAlloc( Aig_Man_t * pAig, Xyz_ParTry_t * pPar )
+{
+    Xyz_ManTry_t * p;
+    p = ABC_CALLOC( Xyz_ManTry_t, 1 );
+    p->pAig    = pAig;
+    p->pPar    = pPar;
+    return p;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Xyz_ManTryFree( Xyz_ManTry_t * p )
+{
+    ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Xyz_ManPerform( Aig_Man_t * pAig, Xyz_ParTry_t * pPar )
+{
+    Xyz_ManTry_t * p;
+    int RetValue;
+    p = Xyz_ManTryAlloc( pAig, pPar );
+    RetValue = 1;
+    Xyz_ManTryFree( p );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/abcBridge.cabal b/abcBridge.cabal
new file mode 100644
--- /dev/null
+++ b/abcBridge.cabal
@@ -0,0 +1,158 @@
+Name:               abcBridge
+Version:            0.10.0.0
+Synopsis:           Bindings for ABC, A System for Sequential
+                    Synthesis and Verification
+Description:        Bindings for ABC focused on creating And-Inverter
+                    Graphs (AIG) and then performing synthesis and
+                    equivalence checking.
+License:            BSD3
+License-file:       LICENSE
+Author:             Galois Inc.
+Maintainer:         jhendrix@galois.com
+Copyright:          (c) 2010-2014 Galois Inc.
+Category:           Data
+build-type:         Custom
+cabal-Version:      >= 1.10
+
+extra-source-files:
+  include/*.h
+  cbits/*.c
+  scripts/*.sh
+  scripts/*.txt
+  tests/eijk.S298.S.aig
+
+flag enable-pthreads
+  Description: Turn on multithreading
+  Default: False
+
+-- Ugh. Temporary fix to make Hackage happy.
+--flag enable-hpc
+--  Description: Collect HPC coverage information.
+--  Default: False
+
+source-repository head
+  type: git
+  location: https://github.com/GaloisInc/abcBridge.git
+
+library
+  Hs-source-dirs:       src
+  Exposed-modules:
+    Data.ABC
+    Data.ABC.AIG
+    Data.ABC.GIA
+    Data.ABC.Internal.Field
+    Data.ABC.Internal.ABCGlobal
+    Data.ABC.Internal.VecInt
+    Data.ABC.Internal.VecPtr
+    Data.ABC.Internal.ABC
+    Data.ABC.Internal.Main
+    Data.ABC.Internal.FRAIG
+    Data.ABC.Internal.GIA
+    Data.ABC.Internal.CEC
+    Data.ABC.Internal.IO
+    Data.ABC.Internal.AIG
+    Data.ABC.Internal.GiaAig
+    Data.ABC.Internal.CNF
+    Data.ABC.Internal.Orphan
+  other-modules:
+    Data.ABC.Util
+  Default-Language:     Haskell98
+  Default-Extensions:   ForeignFunctionInterface,
+                        CPP,
+                        FlexibleContexts,
+                        MultiParamTypeClasses,
+                        EmptyDataDecls
+  Ghc-options:          -Wall
+  -- -U__BLOCKS__ to work around https://github.com/haskell/c2hs/issues/29
+  Cc-options:           -U__BLOCKS__ -U__has_attribute -w
+
+  if flag(enable-pthreads) {
+    Cc-options: -DABC_USE_PTHREADS
+    Extra-libraries: pthread
+  }
+
+  if os(windows) {
+     Cc-options: -D_WIN32
+  }
+
+  if !os(windows) {
+    --Cc-options:             -rdynamic
+    if arch(x86_64) {
+      Cc-options:           -DLIN64
+    } else {
+      Cc-options:           -DLIN
+    }
+  }
+  Include-dirs:         include
+
+  
+  Build-depends:
+    base >= 4,
+    aig,
+    directory,
+    vector
+  Extra-libraries:      abc
+  Build-tools:          c2hs
+  C-sources:            cbits/abcbridge.c
+                        cbits/abcbridge_qbf.c
+                        cbits/cnfWriteHeader.c
+                        cbits/abcBridgeGiaDup.c
+                        cbits/pthread_stubs.c
+
+  -- Ugh. Temporary fix to make Hackage happy.
+  --if flag(enable-hpc)
+  --  ghc-options: -fhpc -hpcdir .hpc
+
+
+test-suite abc-test
+  type: exitcode-stdio-1.0
+  hs-source-dirs: tests
+
+  ghc-options: -Wall
+  ghc-prof-options: -fprof-auto -O2
+
+  -- Ugh. Temporary fix to make Hackage happy.
+  --if flag(enable-hpc)
+  --  ghc-options: -fhpc
+
+  default-Language: Haskell98
+
+  -- Ugh. Temporary fix to make Hackage happy.
+  --if flag(enable-hpc)
+  --  ghc-options: -fhpc
+
+  other-modules:
+    Tests.Basic
+    Tests.Operations
+    Tests.QBF
+  main-is:
+    abc-test.hs
+  build-depends:
+    base == 4.*,
+    abcBridge,
+    aig,
+    directory,
+    HUnit,
+    QuickCheck >= 2.7,
+    test-framework,
+    test-framework-hunit,
+    test-framework-quickcheck2,
+    vector
+
+Executable long-test
+  hs-source-dirs: tests
+
+  ghc-options: -Wall
+  ghc-prof-options: -fprof-auto -O2
+
+  -- Ugh. Temporary fix to make Hackage happy.
+  --if flag(enable-hpc)
+  --  ghc-options: -fhpc
+
+  default-Language: Haskell98
+
+  main-is:
+    long-test.hs
+  build-depends:
+    base == 4.*,
+    abcBridge
diff --git a/cbits/abcBridgeGiaDup.c b/cbits/abcBridgeGiaDup.c
new file mode 100644
--- /dev/null
+++ b/cbits/abcBridgeGiaDup.c
@@ -0,0 +1,79 @@
+#include "aig.h"
+#include "gia.h"
+
+/**
+ * This copies the given object into a new GIA, using the value field of objects
+ * for mappings.  It is similar to Gia_ManDupDfs_rec, but supports objects that
+ * are uncopied inputs by allocating new inputs on demand.
+ *
+ * This function is written in C so that we get efficient access to inline functions
+ * that manipulate bitfields.
+ */
+static
+int Gia_CopyGiaObj(Gia_Man_t* pNew, Gia_Obj_t* pObj)
+{
+  if (pObj->Value != -1) return pObj->Value;
+  if (Gia_ObjIsAnd(pObj)) {
+    Gia_CopyGiaObj(pNew, Gia_ObjFanin0(pObj));
+    Gia_CopyGiaObj(pNew, Gia_ObjFanin1(pObj));
+    return pObj->Value = Gia_ManAppendAnd(pNew, Gia_ObjFanin0Copy(pObj),
+                                                Gia_ObjFanin1Copy(pObj));
+
+  } else {
+    assert(Gia_ObjIsCi(pObj));
+    return pObj->Value = Gia_ManAppendCi(pNew);
+  }
+}
+
+int AbcBridge_Gia_DupLit(Gia_Man_t* pNew, Gia_Man_t* p, int iLit)
+{
+  int var = Gia_CopyGiaObj(pNew, Gia_ManObj(p, Abc_Lit2Var(iLit)));
+  return Abc_LitNotCond(var, Abc_LitIsCompl(iLit));
+}
+
+/**
+ * Returns lit in most recently duplicated new manager or -1 if lit has not
+ * been copied.
+ */
+int Gia_LitCopy(Gia_Man_t* p, int iLit)
+{
+  Gia_Obj_t* obj = Gia_ManObj(p, Abc_Lit2Var(iLit));
+  return (obj->Value == -1)
+         ? -1
+         : Abc_LitNotCond(obj->Value, Abc_LitIsCompl(iLit));
+}
+
+/**
+ * Pointer to an array where for each GIA object o, the element
+ * at index Gia_ObjId(_,o) stores the AIG object equivalent to o.
+ */
+typedef Aig_Obj_t* GiaAigMap;
+
+static
+Aig_Obj_t* Aig_CopyGiaObj(Aig_Man_t* pNew, GiaAigMap* m, Gia_Man_t* p, Gia_Obj_t* pObj)
+{
+  int id = Gia_ObjId(p, pObj);
+  if (m[id]) return m[id]; // Return previous object if pObj has already been copied.
+
+  if (Gia_ObjIsAnd(pObj)) {
+    Aig_Obj_t* obj0 = Aig_NotCond(Aig_CopyGiaObj(pNew, m, p, Gia_ObjFanin0(pObj)),
+                                  Gia_ObjFaninC0(pObj));
+    Aig_Obj_t* obj1 = Aig_NotCond(Aig_CopyGiaObj(pNew, m, p, Gia_ObjFanin1(pObj)),
+                                  Gia_ObjFaninC1(pObj));
+    return m[id] = Aig_And(pNew, obj0, obj1);
+  } else {
+    assert(Gia_ObjIsCi(pObj));
+    return m[id] = Aig_ObjCreateCi(pNew);
+  }
+}
+
+/**
+ * Copies a GIA literal to an AIG, and adds it to the list of combinational outputs.
+ */
+Aig_Obj_t* AbcBridge_Aig_DupGiaLit(Aig_Man_t* pNew, GiaAigMap* m, Gia_Man_t* p, int iLit)
+{
+  // Copy underlying var to new AIG.
+  Aig_Obj_t* obj = Aig_CopyGiaObj(pNew, m, p, Gia_ManObj(p, Abc_Lit2Var(iLit)));
+  // Negate obj if necessary.
+  return Aig_NotCond(obj, Abc_LitIsCompl(iLit));
+}
diff --git a/cbits/abcbridge.c b/cbits/abcbridge.c
new file mode 100644
--- /dev/null
+++ b/cbits/abcbridge.c
@@ -0,0 +1,102 @@
+/**
+ * Wrapper functions for static inline functions (when reimplementing it
+ * ourselves in Haskell would be error-prone).
+ */
+
+#include "abcbridge.h"
+
+Abc_Obj_t * AbcBridge_Abc_ObjNot( Abc_Obj_t * p ) { return Abc_ObjNot(p); }
+Abc_Obj_t * AbcBridge_Abc_ObjRegular( Abc_Obj_t * p ) { return Abc_ObjRegular(p); }
+int AbcBridge_Abc_ObjIsComplement( Abc_Obj_t * p ) { return Abc_ObjIsComplement(p); }
+void AbcBridge_Abc_ObjSetFaninC( Abc_Obj_t * p, int i ) { return Abc_ObjSetFaninC(p, i); }
+void AbcBridge_Abc_ObjXorFaninC( Abc_Obj_t * p, int i ) { return Abc_ObjXorFaninC(p, i); }
+Abc_Obj_t * AbcBridge_Abc_ObjFanin( Abc_Obj_t * p, int i ) { return Abc_ObjFanin(p, i); }
+int AbcBridge_Abc_ObjFaninNum( Abc_Obj_t * p ) { return Abc_ObjFaninNum(p); }
+int AbcBridge_Abc_ObjFanoutNum( Abc_Obj_t * p ) { return Abc_ObjFanoutNum(p); }
+int AbcBridge_Abc_ObjFaninC( Abc_Obj_t * p, int i ) { return Abc_ObjFaninC(p, i); }
+Abc_Obj_t * AbcBridge_Abc_ObjCopy( Abc_Obj_t * p ) { return Abc_ObjCopy(p); }
+void AbcBridge_Abc_ObjSetCopy( Abc_Obj_t * p, Abc_Obj_t * pCopy ) { return Abc_ObjSetCopy(p, pCopy); }
+
+int AbcBridge_Gia_ManAppendCi( Gia_Man_t * p ) { return Gia_ManAppendCi(p); }
+int AbcBridge_Gia_ManAppendAnd( Gia_Man_t * p, int iLit0, int iLit1 ) { return Gia_ManAppendAnd(p, iLit0, iLit1); }
+int AbcBridge_Gia_ManAppendCo( Gia_Man_t * p, int iLit0 ) { return Gia_ManAppendCo(p, iLit0); }
+Gia_Obj_t * AbcBridge_Gia_ManCi( Gia_Man_t * p, int v ) { return Gia_ManCi(p, v); }
+Gia_Obj_t * AbcBridge_Gia_ManCo( Gia_Man_t * p, int v ) { return Gia_ManCo(p, v); }
+
+int AbcBridge_Gia_ObjToLit( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjToLit(p, pObj); }
+Gia_Obj_t * AbcBridge_Gia_ObjFromLit( Gia_Man_t * p, int l ) { return Gia_ObjFromLit(p, l); }
+
+size_t AbcBridge_Gia_ObjSize() { return sizeof(Gia_Obj_t); }
+int AbcBridge_Gia_ObjIsTerm( Gia_Obj_t * pObj ) { return pObj->fTerm; }
+unsigned AbcBridge_Gia_ObjDiff0( Gia_Obj_t * pObj ) { return pObj->iDiff0; }
+unsigned AbcBridge_Gia_ObjDiff1( Gia_Obj_t * pObj ) { return pObj->iDiff1; }
+int AbcBridge_Gia_ObjFaninC0( Gia_Obj_t * pObj ) { return pObj->fCompl0; }
+int AbcBridge_Gia_ObjFaninC1( Gia_Obj_t * pObj ) { return pObj->fCompl1; }
+
+int AbcBridge_Gia_Mark0(Gia_Obj_t* p) { return p->fMark0; }
+void AbcBridge_Gia_SetMark0(Gia_Obj_t* p, int v) { p->fMark0 = v; }
+
+int AbcBridge_Gia_Mark1(Gia_Obj_t* p) { return p->fMark1; }
+void AbcBridge_Gia_SetMark1(Gia_Obj_t* p, int v) { p->fMark1 = v; }
+
+int AbcBridge_Aig_ManNObj(Aig_Man_t* p, Aig_Type_t tp) { return p->nObjs[tp]; }
+
+Aig_Obj_t * AbcBridge_Aig_ManCi( Aig_Man_t * p, int v ) { return Aig_ManCi(p, v); }
+Aig_Obj_t * AbcBridge_Aig_ManCo( Aig_Man_t * p, int v ) { return Aig_ManCo(p, v); }
+int AbcBridge_Aig_ObjId( Aig_Obj_t * pObj ) { return Aig_ObjId(pObj);  }
+
+int AbcBridge_Abc_NtkObjCount( Abc_Ntk_t * p, Abc_ObjType_t t) {
+    return p->nObjCounts[t];
+}
+
+/**
+ * Helper functions for foreign pointers.
+ */
+
+void AbcBridge_NtkPtrDelete( Abc_Ntk_t **pp ) {
+    if (pp == NULL) {
+        // This shouldn't happen: it indicates that we created a foreign
+        // pointer to NULL.
+        assert(0);
+        return;
+    }
+    if (*pp == NULL) {
+        // Some ABC code must have punted it prematurely.  Note that
+        // this is not really a safe state of affairs, since most of the
+        // Haskell code assumes that the inner pointer is not NULL.
+        assert(0);
+        return;
+    }
+    Abc_NtkDelete(*pp);
+}
+
+void AbcBridge_Gia_MmFixedStop( Gia_MmFixed_t *p ) {
+    Gia_MmFixedStop(p, 0);
+}
+
+void AbcBridge_Gia_MmFlexStop( Gia_MmFlex_t *p ) {
+    Gia_MmFlexStop(p, 0);
+}
+
+void AbcBridge_Gia_MmStepStop( Gia_MmStep_t *p ) {
+    Gia_MmStepStop(p, 0);
+}
+
+/**
+ * Make the linker happy.
+ */
+
+int Abc_NtkIsSeq( Abc_Ntk_t *p ) {
+    assert(0);
+    return 0;
+}
+
+int Seq_ObjFaninL0( Abc_Obj_t *p ) {
+    assert(0);
+    return 0;
+}
+
+int Seq_ObjFaninL1( Abc_Obj_t *p ) {
+    assert(0);
+    return 0;
+}
diff --git a/cbits/abcbridge_qbf.c b/cbits/abcbridge_qbf.c
new file mode 100644
--- /dev/null
+++ b/cbits/abcbridge_qbf.c
@@ -0,0 +1,165 @@
+#include "abcbridge.h"
+
+/**Function*************************************************************
+
+  Synopsis    [Translates model into the vector of values.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static
+void AbcBridge_NtkModelToVector( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues )
+{
+    int * pModel, i;
+    pModel = pNtk->pModel;
+    for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ )
+        Vec_IntWriteEntry( vPiValues, i, pModel[i] );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Clears parameters.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static
+void AbcBridge_NtkVectorClearPars( Vec_Int_t * vPiValues, int nPars )
+{
+    int i;
+    for ( i = 0; i < nPars; i++ )
+        Vec_IntWriteEntry( vPiValues, i, -1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Clears variables.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static
+void AbcBridge_NtkVectorClearVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars )
+{
+    int i;
+    for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ )
+        Vec_IntWriteEntry( vPiValues, i, -1 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Solve the QBF problem EpAx[M(p,x)].]
+
+  Description [The network should be a Boolean network where, the variables
+               p go first, followed by variables x.
+               The number of parameters is nPars.
+               The number of iterations to try is nItersMax.
+               The inputs to try are in vPiValues, and it will store the
+               results if a model is found.
+               The return value is 1 if the problem is false, 0 if the problem is
+               true (and an assignment to p returned via vPiValeus), -1 if the
+               iteration limit reached, and -2 if the sat solver times out. ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int AbcBridge_NtkQbf( Abc_Ntk_t * pNtk,
+                       int nPars,
+                       int nItersMax,
+                       Vec_Int_t* vPiValues)
+{
+    Abc_Ntk_t * pNtkVer, * pNtkSyn, * pNtkSyn2, * pNtkTemp;
+    int nIters, nInputs, RetValue, fFound = 0;
+
+    assert( Abc_NtkIsStrash(pNtk) );
+    assert( Abc_NtkIsComb(pNtk) );
+    assert( Abc_NtkPoNum(pNtk) == 1 );
+    assert( nPars > 0 && nPars < Abc_NtkPiNum(pNtk) );
+//    assert( Abc_NtkPiNum(pNtk)-nPars < 32 );
+    nInputs = Abc_NtkPiNum(pNtk) - nPars;
+
+    assert(Vec_IntSize(vPiValues) == Abc_NtkPiNum(pNtk));
+
+    AbcBridge_NtkVectorClearPars( vPiValues, nPars );
+    pNtkSyn = Abc_NtkMiterCofactor( pNtk, vPiValues );
+
+    // iteratively solve
+    for ( nIters = 0; nIters < nItersMax; nIters++ )
+    {
+        // solve the synthesis instance
+//        RetValue = Abc_NtkMiterSat( pNtkSyn, 0, 0, 0, NULL, NULL );
+        RetValue = Abc_NtkDSat( pNtkSyn, (ABC_INT64_T)0, (ABC_INT64_T)0, 0, 0, 0, 1, 0, 0, 0 );
+        if ( RetValue == 0 )
+            AbcBridge_NtkModelToVector( pNtkSyn, vPiValues );
+
+        // Formula is unsat when forall variables replaced with concrete inputs, and
+        // thus unsat in general.
+        if ( RetValue == 1 )
+        {
+          Abc_NtkDelete(pNtkSyn);
+          return 1; // Return UNSAT
+        }
+
+        // Synthesis timed out.
+        if (RetValue == -1) {
+          Abc_NtkDelete(pNtkSyn);
+          return -2; 
+        }
+        // there is a counter-example
+
+        // construct the verification instance
+        AbcBridge_NtkVectorClearVars( pNtk, vPiValues, nPars );
+
+        pNtkVer = Abc_NtkMiterCofactor( pNtk, vPiValues );
+        // complement the output
+        Abc_ObjXorFaninC( Abc_NtkPo(pNtkVer,0), 0 );
+
+        // solve the verification instance
+        RetValue = Abc_NtkMiterSat( pNtkVer, 0, 0, 0, NULL, NULL );
+
+        if ( RetValue == 0 )
+            AbcBridge_NtkModelToVector( pNtkVer, vPiValues );
+        Abc_NtkDelete( pNtkVer );
+
+        if ( RetValue == 1 )
+        {
+          Abc_NtkDelete( pNtkSyn );
+          return 0; // Return sat
+        }
+
+        // If verification timed out.
+        if ( RetValue == -1 ) {
+          Abc_NtkDelete(pNtkSyn);
+          return -2;
+        }
+
+        // there is a counter-example
+
+        // create a new synthesis network
+        AbcBridge_NtkVectorClearPars( vPiValues, nPars );
+        pNtkSyn2 = Abc_NtkMiterCofactor( pNtk, vPiValues );
+        // add to the synthesis instance
+        pNtkSyn = Abc_NtkMiterAnd( pNtkTemp = pNtkSyn, pNtkSyn2, 0, 0 );
+        Abc_NtkDelete( pNtkSyn2 );
+        Abc_NtkDelete( pNtkTemp );
+    }
+
+    Abc_NtkDelete( pNtkSyn );
+
+    // Limit reached.
+    return -1;
+}
diff --git a/cbits/cnfWriteHeader.c b/cbits/cnfWriteHeader.c
new file mode 100644
--- /dev/null
+++ b/cbits/cnfWriteHeader.c
@@ -0,0 +1,32 @@
+#include "cnf.h"
+
+static inline int Cnf_Lit2Var( int Lit ) {
+    return (Lit & 1)? -(Lit >> 1)-1 : (Lit >> 1)+1;
+}
+
+static inline int Cnf_Lit2Var2( int Lit ) {
+    return (Lit & 1)? -(Lit >> 1)   : (Lit >> 1);
+}
+
+int Cnf_DataWriteIntoFileWithHeader( Cnf_Dat_t * p, char * pFileName, char * header, int fReadable )
+{
+    FILE * pFile;
+    int * pLit, * pStop, i;
+    pFile = fopen( pFileName, "w" );
+    if ( pFile == NULL )
+    {
+        return 1;
+    }
+    fprintf( pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n" );
+    fprintf( pFile, "p cnf %d %d\n", p->nVars, p->nClauses );
+    fprintf( pFile, "%s", header);
+    for ( i = 0; i < p->nClauses; i++ )
+    {
+        for ( pLit = p->pClauses[i], pStop = p->pClauses[i+1]; pLit < pStop; pLit++ )
+            fprintf( pFile, "%d ", fReadable? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit) );
+        fprintf( pFile, "0\n" );
+    }
+    fprintf( pFile, "\n" );
+    fclose( pFile );
+    return 0;
+}
diff --git a/cbits/pthread_stubs.c b/cbits/pthread_stubs.c
new file mode 100644
--- /dev/null
+++ b/cbits/pthread_stubs.c
@@ -0,0 +1,43 @@
+/* This file defines stub pthread functions to link against the ABC sources.  This way,
+ * we can compile and link against ABC even when it unconditionally depends on pthreads.
+ * We simply will abort with an error message if we ever call an ABC function that
+ * requires threading.
+ *
+ * Yes, this is a bit of a hack.
+ */
+
+#ifndef ABC_USE_PTHREADS
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef _WIN32
+#include "../abc-build/lib/pthread.h"
+#else
+#include <unistd.h>
+#include <pthread.h>
+#endif
+
+int pthread_create(pthread_t * thread, const pthread_attr_t* attr, void *(*start_routine)(void *), void* arg ) { 
+  fprintf(stderr,"ABC tried to use pthreads on a system not configured with a pthread library... sorry.");
+  exit(1);
+}
+
+pthread_t global_self;
+
+void pthread_exit( void* value ) { exit(0); }
+int pthread_equal(pthread_t t1, pthread_t t2) { return 1; }
+int pthread_detach(pthread_t t) { return 0; }
+int pthread_join(pthread_t t, void** v) { return 0; }
+int pthread_cancel(pthread_t t) { return 0; }
+pthread_t pthread_self(void) { return global_self; }
+
+int pthread_mutex_lock( pthread_mutex_t *m ) { return 0; }
+int pthread_mutex_unlock( pthread_mutex_t *m ) { return 0; }
+int pthread_mutex_trylock( pthread_mutex_t *m ) { return 0; }
+int pthread_mutex_destroy( pthread_mutex_t *m ) { return 0; }
+int pthread_mutex_init( pthread_mutex_t *m, const pthread_mutexattr_t *attr ) { return 0; }
+int pthread_mutextattr_init( pthread_mutexattr_t *attr ) { return 0; }
+int pthread_mutextattr_destroy( pthread_mutexattr_t *attr ) { return 0; }
+
+#endif
diff --git a/include/abcbridge.h b/include/abcbridge.h
new file mode 100644
--- /dev/null
+++ b/include/abcbridge.h
@@ -0,0 +1,29 @@
+#define ABC_LIB
+#define WIN32_NO_DLL
+
+#include <stdio.h>
+#include "abc.h"
+#include "gia.h"
+#include "aig.h"
+#include "abc_global.h"
+
+int AbcBridge_Gia_ManAppendCi( Gia_Man_t * p );
+int AbcBridge_Gia_ManAppendAnd( Gia_Man_t * p, int iLit0, int iLit1 );
+int AbcBridge_Gia_ManAppendCo( Gia_Man_t * p, int iLit0 );
+
+int AbcBridge_Gia_DupLit(Gia_Man_t* pNew, Gia_Man_t* p, int iLit);
+
+Gia_Obj_t * AbcBridge_Gia_ManCi( Gia_Man_t * p, int v );
+Gia_Obj_t * AbcBridge_Gia_ManCo( Gia_Man_t * p, int v );
+int AbcBridge_Gia_ObjToLit( Gia_Man_t * p, Gia_Obj_t * pObj );
+Gia_Obj_t * AbcBridge_Gia_ObjFromLit( Gia_Man_t * p, int l );
+
+int AbcBridge_NtkQbf( Abc_Ntk_t * pNtk,
+                       int nPars,
+                       int nItersMax,
+                       Vec_Int_t* vPiValues);
+
+int AbcBridge_Aig_ManNObj(Aig_Man_t* p, Aig_Type_t tp);
+Aig_Obj_t * AbcBridge_Aig_ManCi( Aig_Man_t * p, int v );
+Aig_Obj_t * AbcBridge_Aig_ManCo( Aig_Man_t * p, int v );
+int AbcBridge_Aig_ObjId( Aig_Obj_t * pObj );
diff --git a/include/cnfheader.h b/include/cnfheader.h
new file mode 100644
--- /dev/null
+++ b/include/cnfheader.h
@@ -0,0 +1,3 @@
+#include "cnf.h"
+
+int Cnf_DataWriteIntoFileWithHeader( Cnf_Dat_t * p, char * pFileName, char * header, int fReadable );
diff --git a/include/orphan.h b/include/orphan.h
new file mode 100644
--- /dev/null
+++ b/include/orphan.h
@@ -0,0 +1,5 @@
+
+
+int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Fra_Sec_t * pSecPar );
+Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan );
+Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters);
diff --git a/scripts/abc-incl-dirs.txt b/scripts/abc-incl-dirs.txt
new file mode 100644
--- /dev/null
+++ b/scripts/abc-incl-dirs.txt
@@ -0,0 +1,103 @@
+abc-build/src
+abc-build/src/aig
+abc-build/src/aig/aig
+abc-build/src/aig/gia
+abc-build/src/aig/hop
+abc-build/src/aig/ioa
+abc-build/src/aig/ivy
+abc-build/src/aig/miniaig
+abc-build/src/aig/saig
+abc-build/src/base
+abc-build/src/base/abc
+abc-build/src/base/abci
+abc-build/src/base/cmd
+abc-build/src/base/io
+abc-build/src/base/main
+abc-build/src/base/test
+abc-build/src/base/ver
+abc-build/src/bdd
+abc-build/src/bdd/cas
+abc-build/src/bdd/cudd
+abc-build/src/bdd/dsd
+abc-build/src/bdd/epd
+abc-build/src/bdd/mtr
+abc-build/src/bdd/parse
+abc-build/src/bdd/reo
+abc-build/src/bool
+abc-build/src/bool/bdc
+abc-build/src/bool/dec
+abc-build/src/bool/deco
+abc-build/src/bool/kit
+abc-build/src/bool/lucky
+abc-build/src/bool/rpo
+abc-build/src/bool/rsb
+abc-build/src/map
+abc-build/src/map/amap
+abc-build/src/map/cov
+abc-build/src/map/fpga
+abc-build/src/map/if
+abc-build/src/map/mapper
+abc-build/src/map/mio
+abc-build/src/map/mpm
+abc-build/src/map/scl
+abc-build/src/map/super
+abc-build/src/misc
+abc-build/src/misc/avl
+abc-build/src/misc/bar
+abc-build/src/misc/bbl
+abc-build/src/misc/bzlib
+abc-build/src/misc/espresso
+abc-build/src/misc/ext
+abc-build/src/misc/extra
+abc-build/src/misc/hash
+abc-build/src/misc/mem
+abc-build/src/misc/mvc
+abc-build/src/misc/nm
+abc-build/src/misc/st
+abc-build/src/misc/tim
+abc-build/src/misc/util
+abc-build/src/misc/vec
+abc-build/src/misc/zlib
+abc-build/src/opt
+abc-build/src/opt/cgt
+abc-build/src/opt/csw
+abc-build/src/opt/cut
+abc-build/src/opt/dar
+abc-build/src/opt/dau
+abc-build/src/opt/fsim
+abc-build/src/opt/fxu
+abc-build/src/opt/lpk
+abc-build/src/opt/mfs
+abc-build/src/opt/nwk
+abc-build/src/opt/res
+abc-build/src/opt/ret
+abc-build/src/opt/rwr
+abc-build/src/opt/rwt
+abc-build/src/opt/sfm
+abc-build/src/opt/sim
+abc-build/src/phys
+abc-build/src/phys/place
+abc-build/src/proof
+abc-build/src/proof/abs
+abc-build/src/proof/bbr
+abc-build/src/proof/cec
+abc-build/src/proof/dch
+abc-build/src/proof/fra
+abc-build/src/proof/fraig
+abc-build/src/proof/int
+abc-build/src/proof/int2
+abc-build/src/proof/live
+abc-build/src/proof/llb
+abc-build/src/proof/pdr
+abc-build/src/proof/ssc
+abc-build/src/proof/ssw
+abc-build/src/python
+abc-build/src/sat
+abc-build/src/sat/bmc
+abc-build/src/sat/bsat
+abc-build/src/sat/cnf
+abc-build/src/sat/csat
+abc-build/src/sat/lsat
+abc-build/src/sat/msat
+abc-build/src/sat/proof
+abc-build/src/sat/psat
diff --git a/scripts/abc-sources.txt b/scripts/abc-sources.txt
new file mode 100644
--- /dev/null
+++ b/scripts/abc-sources.txt
@@ -0,0 +1,1436 @@
+abc-build/.hg_archival.txt
+abc-build/.hgignore
+abc-build/abc.rc
+abc-build/abcexe.dsp
+abc-build/abclib.dsp
+abc-build/abcspace.dsw
+abc-build/arch_flags.c
+abc-build/copyright.txt
+abc-build/depends.sh
+abc-build/i10.aig
+abc-build/lib/pthread.h
+abc-build/lib/sched.h
+abc-build/lib/semaphore.h
+abc-build/lib/x64/pthreadVC2.dll
+abc-build/lib/x64/pthreadVC2.lib
+abc-build/lib/x86/pthreadVC2.dll
+abc-build/lib/x86/pthreadVC2.lib
+abc-build/Makefile
+abc-build/readme.md
+abc-build/readmeaig
+abc-build/scripts/abc.rc
+abc-build/scripts/abc_common.py
+abc-build/scripts/main.py
+abc-build/scripts/multi_prove.sh
+abc-build/scripts/new_abc_commands.py
+abc-build/scripts/niklas.py
+abc-build/scripts/par.py
+abc-build/scripts/simple.sh
+abc-build/scripts/simple_bip.sh
+abc-build/scripts/simple_liveness.sh
+abc-build/scripts/simple_sat.sh
+abc-build/scripts/super_prove.sh
+abc-build/src/aig/aig/aig.h
+abc-build/src/aig/aig/aig_.c
+abc-build/src/aig/aig/aigCanon.c
+abc-build/src/aig/aig/aigCheck.c
+abc-build/src/aig/aig/aigCuts.c
+abc-build/src/aig/aig/aigDfs.c
+abc-build/src/aig/aig/aigDoms.c
+abc-build/src/aig/aig/aigDup.c
+abc-build/src/aig/aig/aigFact.c
+abc-build/src/aig/aig/aigFanout.c
+abc-build/src/aig/aig/aigFrames.c
+abc-build/src/aig/aig/aigInter.c
+abc-build/src/aig/aig/aigJust.c
+abc-build/src/aig/aig/aigMan.c
+abc-build/src/aig/aig/aigMem.c
+abc-build/src/aig/aig/aigMffc.c
+abc-build/src/aig/aig/aigObj.c
+abc-build/src/aig/aig/aigOper.c
+abc-build/src/aig/aig/aigOrder.c
+abc-build/src/aig/aig/aigPack.c
+abc-build/src/aig/aig/aigPart.c
+abc-build/src/aig/aig/aigPartReg.c
+abc-build/src/aig/aig/aigPartSat.c
+abc-build/src/aig/aig/aigRepar.c
+abc-build/src/aig/aig/aigRepr.c
+abc-build/src/aig/aig/aigRet.c
+abc-build/src/aig/aig/aigRetF.c
+abc-build/src/aig/aig/aigScl.c
+abc-build/src/aig/aig/aigShow.c
+abc-build/src/aig/aig/aigSplit.c
+abc-build/src/aig/aig/aigTable.c
+abc-build/src/aig/aig/aigTest.c
+abc-build/src/aig/aig/aigTiming.c
+abc-build/src/aig/aig/aigTruth.c
+abc-build/src/aig/aig/aigTsim.c
+abc-build/src/aig/aig/aigUtil.c
+abc-build/src/aig/aig/aigWin.c
+abc-build/src/aig/aig/module.make
+abc-build/src/aig/gia/gia.c
+abc-build/src/aig/gia/gia.h
+abc-build/src/aig/gia/giaAgi.c
+abc-build/src/aig/gia/giaAig.c
+abc-build/src/aig/gia/giaAig.h
+abc-build/src/aig/gia/giaAiger.c
+abc-build/src/aig/gia/giaAigerExt.c
+abc-build/src/aig/gia/giaBalance.c
+abc-build/src/aig/gia/giaBalance2.c
+abc-build/src/aig/gia/giaBidec.c
+abc-build/src/aig/gia/giaCCof.c
+abc-build/src/aig/gia/giaCex.c
+abc-build/src/aig/gia/giaCof.c
+abc-build/src/aig/gia/giaCone.c
+abc-build/src/aig/gia/giaConstr.c
+abc-build/src/aig/gia/giaCSat.c
+abc-build/src/aig/gia/giaCSatOld.c
+abc-build/src/aig/gia/giaCTas.c
+abc-build/src/aig/gia/giaCTas2.c
+abc-build/src/aig/gia/giaDfs.c
+abc-build/src/aig/gia/giaDup.c
+abc-build/src/aig/gia/giaEmbed.c
+abc-build/src/aig/gia/giaEnable.c
+abc-build/src/aig/gia/giaEquiv.c
+abc-build/src/aig/gia/giaEra.c
+abc-build/src/aig/gia/giaEra2.c
+abc-build/src/aig/gia/giaFalse.c
+abc-build/src/aig/gia/giaFanout.c
+abc-build/src/aig/gia/giaForce.c
+abc-build/src/aig/gia/giaFrames.c
+abc-build/src/aig/gia/giaFront.c
+abc-build/src/aig/gia/giaFx.c
+abc-build/src/aig/gia/giaGiarf.c
+abc-build/src/aig/gia/giaGig.c
+abc-build/src/aig/gia/giaGlitch.c
+abc-build/src/aig/gia/giaHash.c
+abc-build/src/aig/gia/giaHcd.c
+abc-build/src/aig/gia/giaIf.c
+abc-build/src/aig/gia/giaIff.c
+abc-build/src/aig/gia/giaIso.c
+abc-build/src/aig/gia/giaIso2.c
+abc-build/src/aig/gia/giaIso3.c
+abc-build/src/aig/gia/giaJf.c
+abc-build/src/aig/gia/giaKf.c
+abc-build/src/aig/gia/giaLf.c
+abc-build/src/aig/gia/giaMan.c
+abc-build/src/aig/gia/giaMem.c
+abc-build/src/aig/gia/giaMf.c
+abc-build/src/aig/gia/giaMfs.c
+abc-build/src/aig/gia/giaMini.c
+abc-build/src/aig/gia/giaMuxes.c
+abc-build/src/aig/gia/giaNf.c
+abc-build/src/aig/gia/giaPat.c
+abc-build/src/aig/gia/giaProp.c
+abc-build/src/aig/gia/giaResub.c
+abc-build/src/aig/gia/giaRetime.c
+abc-build/src/aig/gia/giaSat.c
+abc-build/src/aig/gia/giaScl.c
+abc-build/src/aig/gia/giaShrink.c
+abc-build/src/aig/gia/giaShrink6.c
+abc-build/src/aig/gia/giaShrink7.c
+abc-build/src/aig/gia/giaSim.c
+abc-build/src/aig/gia/giaSim2.c
+abc-build/src/aig/gia/giaSopb.c
+abc-build/src/aig/gia/giaSort.c
+abc-build/src/aig/gia/giaSpeedup.c
+abc-build/src/aig/gia/giaStg.c
+abc-build/src/aig/gia/giaStr.c
+abc-build/src/aig/gia/giaSupMin.c
+abc-build/src/aig/gia/giaSweep.c
+abc-build/src/aig/gia/giaSweeper.c
+abc-build/src/aig/gia/giaSwitch.c
+abc-build/src/aig/gia/giaTim.c
+abc-build/src/aig/gia/giaTis.c
+abc-build/src/aig/gia/giaTruth.c
+abc-build/src/aig/gia/giaTsim.c
+abc-build/src/aig/gia/giaUtil.c
+abc-build/src/aig/gia/module.make
+abc-build/src/aig/hop/cudd2.c
+abc-build/src/aig/hop/cudd2.h
+abc-build/src/aig/hop/hop.h
+abc-build/src/aig/hop/hop_.c
+abc-build/src/aig/hop/hopBalance.c
+abc-build/src/aig/hop/hopCheck.c
+abc-build/src/aig/hop/hopDfs.c
+abc-build/src/aig/hop/hopMan.c
+abc-build/src/aig/hop/hopMem.c
+abc-build/src/aig/hop/hopObj.c
+abc-build/src/aig/hop/hopOper.c
+abc-build/src/aig/hop/hopTable.c
+abc-build/src/aig/hop/hopTruth.c
+abc-build/src/aig/hop/hopUtil.c
+abc-build/src/aig/hop/module.make
+abc-build/src/aig/ioa/ioa.h
+abc-build/src/aig/ioa/ioaReadAig.c
+abc-build/src/aig/ioa/ioaUtil.c
+abc-build/src/aig/ioa/ioaWriteAig.c
+abc-build/src/aig/ioa/module.make
+abc-build/src/aig/ivy/attr.h
+abc-build/src/aig/ivy/ivy.h
+abc-build/src/aig/ivy/ivy_.c
+abc-build/src/aig/ivy/ivyBalance.c
+abc-build/src/aig/ivy/ivyCanon.c
+abc-build/src/aig/ivy/ivyCheck.c
+abc-build/src/aig/ivy/ivyCut.c
+abc-build/src/aig/ivy/ivyCutTrav.c
+abc-build/src/aig/ivy/ivyDfs.c
+abc-build/src/aig/ivy/ivyDsd.c
+abc-build/src/aig/ivy/ivyFanout.c
+abc-build/src/aig/ivy/ivyFastMap.c
+abc-build/src/aig/ivy/ivyFraig.c
+abc-build/src/aig/ivy/ivyHaig.c
+abc-build/src/aig/ivy/ivyMan.c
+abc-build/src/aig/ivy/ivyMem.c
+abc-build/src/aig/ivy/ivyMulti.c
+abc-build/src/aig/ivy/ivyMulti8.c
+abc-build/src/aig/ivy/ivyObj.c
+abc-build/src/aig/ivy/ivyOper.c
+abc-build/src/aig/ivy/ivyResyn.c
+abc-build/src/aig/ivy/ivyRwr.c
+abc-build/src/aig/ivy/ivyRwrAlg.c
+abc-build/src/aig/ivy/ivySeq.c
+abc-build/src/aig/ivy/ivyShow.c
+abc-build/src/aig/ivy/ivyTable.c
+abc-build/src/aig/ivy/ivyUtil.c
+abc-build/src/aig/ivy/module.make
+abc-build/src/aig/miniaig/abcapis.h
+abc-build/src/aig/miniaig/miniaig.h
+abc-build/src/aig/miniaig/module.make
+abc-build/src/aig/saig/module.make
+abc-build/src/aig/saig/saig.h
+abc-build/src/aig/saig/saig_.c
+abc-build/src/aig/saig/saigCone.c
+abc-build/src/aig/saig/saigConstr.c
+abc-build/src/aig/saig/saigConstr2.c
+abc-build/src/aig/saig/saigDual.c
+abc-build/src/aig/saig/saigDup.c
+abc-build/src/aig/saig/saigGlaCba.c
+abc-build/src/aig/saig/saigGlaPba.c
+abc-build/src/aig/saig/saigGlaPba2.c
+abc-build/src/aig/saig/saigInd.c
+abc-build/src/aig/saig/saigIoa.c
+abc-build/src/aig/saig/saigIso.c
+abc-build/src/aig/saig/saigIsoFast.c
+abc-build/src/aig/saig/saigIsoSlow.c
+abc-build/src/aig/saig/saigMiter.c
+abc-build/src/aig/saig/saigOutDec.c
+abc-build/src/aig/saig/saigPhase.c
+abc-build/src/aig/saig/saigRefSat.c
+abc-build/src/aig/saig/saigRetFwd.c
+abc-build/src/aig/saig/saigRetMin.c
+abc-build/src/aig/saig/saigRetStep.c
+abc-build/src/aig/saig/saigScl.c
+abc-build/src/aig/saig/saigSimFast.c
+abc-build/src/aig/saig/saigSimMv.c
+abc-build/src/aig/saig/saigSimSeq.c
+abc-build/src/aig/saig/saigStrSim.c
+abc-build/src/aig/saig/saigSwitch.c
+abc-build/src/aig/saig/saigSynch.c
+abc-build/src/aig/saig/saigTempor.c
+abc-build/src/aig/saig/saigTrans.c
+abc-build/src/aig/saig/saigUnfold2.c
+abc-build/src/aig/saig/saigWnd.c
+abc-build/src/base/abc/abc.h
+abc-build/src/base/abc/abc_.c
+abc-build/src/base/abc/abcAig.c
+abc-build/src/base/abc/abcBarBuf.c
+abc-build/src/base/abc/abcBlifMv.c
+abc-build/src/base/abc/abcCheck.c
+abc-build/src/base/abc/abcDfs.c
+abc-build/src/base/abc/abcFanio.c
+abc-build/src/base/abc/abcFanOrder.c
+abc-build/src/base/abc/abcFunc.c
+abc-build/src/base/abc/abcHie.c
+abc-build/src/base/abc/abcHieCec.c
+abc-build/src/base/abc/abcHieNew.c
+abc-build/src/base/abc/abcInt.h
+abc-build/src/base/abc/abcLatch.c
+abc-build/src/base/abc/abcLib.c
+abc-build/src/base/abc/abcMinBase.c
+abc-build/src/base/abc/abcNames.c
+abc-build/src/base/abc/abcNetlist.c
+abc-build/src/base/abc/abcNtk.c
+abc-build/src/base/abc/abcObj.c
+abc-build/src/base/abc/abcRefs.c
+abc-build/src/base/abc/abcShow.c
+abc-build/src/base/abc/abcSop.c
+abc-build/src/base/abc/abcUtil.c
+abc-build/src/base/abc/module.make
+abc-build/src/base/abci/abc.c
+abc-build/src/base/abci/abcAttach.c
+abc-build/src/base/abci/abcAuto.c
+abc-build/src/base/abci/abcBalance.c
+abc-build/src/base/abci/abcBidec.c
+abc-build/src/base/abci/abcBm.c
+abc-build/src/base/abci/abcBmc.c
+abc-build/src/base/abci/abcCas.c
+abc-build/src/base/abci/abcCascade.c
+abc-build/src/base/abci/abcCollapse.c
+abc-build/src/base/abci/abcCut.c
+abc-build/src/base/abci/abcDar.c
+abc-build/src/base/abci/abcDarUnfold2.c
+abc-build/src/base/abci/abcDebug.c
+abc-build/src/base/abci/abcDec.c
+abc-build/src/base/abci/abcDress.c
+abc-build/src/base/abci/abcDress2.c
+abc-build/src/base/abci/abcDsd.c
+abc-build/src/base/abci/abcEspresso.c
+abc-build/src/base/abci/abcExtract.c
+abc-build/src/base/abci/abcFlop.c
+abc-build/src/base/abci/abcFpga.c
+abc-build/src/base/abci/abcFpgaFast.c
+abc-build/src/base/abci/abcFraig.c
+abc-build/src/base/abci/abcFx.c
+abc-build/src/base/abci/abcFxu.c
+abc-build/src/base/abci/abcGen.c
+abc-build/src/base/abci/abcHaig.c
+abc-build/src/base/abci/abcIf.c
+abc-build/src/base/abci/abcIfif.c
+abc-build/src/base/abci/abcIfMux.c
+abc-build/src/base/abci/abciUnfold2.c
+abc-build/src/base/abci/abcIvy.c
+abc-build/src/base/abci/abcLog.c
+abc-build/src/base/abci/abcLut.c
+abc-build/src/base/abci/abcLutmin.c
+abc-build/src/base/abci/abcMap.c
+abc-build/src/base/abci/abcMeasure.c
+abc-build/src/base/abci/abcMerge.c
+abc-build/src/base/abci/abcMffc.c
+abc-build/src/base/abci/abcMfs.c
+abc-build/src/base/abci/abcMini.c
+abc-build/src/base/abci/abcMiter.c
+abc-build/src/base/abci/abcMulti.c
+abc-build/src/base/abci/abcMv.c
+abc-build/src/base/abci/abcNpn.c
+abc-build/src/base/abci/abcNpnSave.c
+abc-build/src/base/abci/abcNtbdd.c
+abc-build/src/base/abci/abcOdc.c
+abc-build/src/base/abci/abcOrder.c
+abc-build/src/base/abci/abcPart.c
+abc-build/src/base/abci/abcPlace.c
+abc-build/src/base/abci/abcPrint.c
+abc-build/src/base/abci/abcProve.c
+abc-build/src/base/abci/abcQbf.c
+abc-build/src/base/abci/abcQuant.c
+abc-build/src/base/abci/abcReach.c
+abc-build/src/base/abci/abcRec3.c
+abc-build/src/base/abci/abcReconv.c
+abc-build/src/base/abci/abcRefactor.c
+abc-build/src/base/abci/abcRenode.c
+abc-build/src/base/abci/abcReorder.c
+abc-build/src/base/abci/abcRestruct.c
+abc-build/src/base/abci/abcResub.c
+abc-build/src/base/abci/abcRewrite.c
+abc-build/src/base/abci/abcRpo.c
+abc-build/src/base/abci/abcRr.c
+abc-build/src/base/abci/abcSat.c
+abc-build/src/base/abci/abcSaucy.c
+abc-build/src/base/abci/abcScorr.c
+abc-build/src/base/abci/abcSense.c
+abc-build/src/base/abci/abcSpeedup.c
+abc-build/src/base/abci/abcStrash.c
+abc-build/src/base/abci/abcSweep.c
+abc-build/src/base/abci/abcSymm.c
+abc-build/src/base/abci/abcTim.c
+abc-build/src/base/abci/abcTiming.c
+abc-build/src/base/abci/abcUnate.c
+abc-build/src/base/abci/abcUnreach.c
+abc-build/src/base/abci/abcVerify.c
+abc-build/src/base/abci/abcXsim.c
+abc-build/src/base/abci/fahout_cut.c
+abc-build/src/base/abci/module.make
+abc-build/src/base/cmd/cmd.c
+abc-build/src/base/cmd/cmd.h
+abc-build/src/base/cmd/cmdAlias.c
+abc-build/src/base/cmd/cmdApi.c
+abc-build/src/base/cmd/cmdFlag.c
+abc-build/src/base/cmd/cmdHist.c
+abc-build/src/base/cmd/cmdInt.h
+abc-build/src/base/cmd/cmdLoad.c
+abc-build/src/base/cmd/cmdPlugin.c
+abc-build/src/base/cmd/cmdStarter.c
+abc-build/src/base/cmd/cmdUtils.c
+abc-build/src/base/cmd/module.make
+abc-build/src/base/io/io.c
+abc-build/src/base/io/ioAbc.h
+abc-build/src/base/io/ioInt.h
+abc-build/src/base/io/ioReadAiger.c
+abc-build/src/base/io/ioReadBaf.c
+abc-build/src/base/io/ioReadBblif.c
+abc-build/src/base/io/ioReadBench.c
+abc-build/src/base/io/ioReadBlif.c
+abc-build/src/base/io/ioReadBlifAig.c
+abc-build/src/base/io/ioReadBlifMv.c
+abc-build/src/base/io/ioReadDsd.c
+abc-build/src/base/io/ioReadEdif.c
+abc-build/src/base/io/ioReadEqn.c
+abc-build/src/base/io/ioReadPla.c
+abc-build/src/base/io/ioReadVerilog.c
+abc-build/src/base/io/ioUtil.c
+abc-build/src/base/io/ioWriteAiger.c
+abc-build/src/base/io/ioWriteBaf.c
+abc-build/src/base/io/ioWriteBblif.c
+abc-build/src/base/io/ioWriteBench.c
+abc-build/src/base/io/ioWriteBlif.c
+abc-build/src/base/io/ioWriteBlifMv.c
+abc-build/src/base/io/ioWriteBook.c
+abc-build/src/base/io/ioWriteCnf.c
+abc-build/src/base/io/ioWriteDot.c
+abc-build/src/base/io/ioWriteEqn.c
+abc-build/src/base/io/ioWriteGml.c
+abc-build/src/base/io/ioWriteList.c
+abc-build/src/base/io/ioWritePla.c
+abc-build/src/base/io/ioWriteSmv.c
+abc-build/src/base/io/ioWriteVerilog.c
+abc-build/src/base/io/module.make
+abc-build/src/base/main/libSupport.c
+abc-build/src/base/main/main.c
+abc-build/src/base/main/main.h
+abc-build/src/base/main/mainFrame.c
+abc-build/src/base/main/mainInit.c
+abc-build/src/base/main/mainInt.h
+abc-build/src/base/main/mainLib.c
+abc-build/src/base/main/mainMC.c
+abc-build/src/base/main/mainUtils.c
+abc-build/src/base/main/module.make
+abc-build/src/base/test/module.make
+abc-build/src/base/test/test.c
+abc-build/src/base/ver/module.make
+abc-build/src/base/ver/ver.h
+abc-build/src/base/ver/ver_.c
+abc-build/src/base/ver/verCore.c
+abc-build/src/base/ver/verFormula.c
+abc-build/src/base/ver/verParse.c
+abc-build/src/base/ver/verStream.c
+abc-build/src/base/ver/verWords.c
+abc-build/src/bdd/cas/cas.h
+abc-build/src/bdd/cas/casCore.c
+abc-build/src/bdd/cas/casDec.c
+abc-build/src/bdd/cas/module.make
+abc-build/src/bdd/cudd/cuBdd.make
+abc-build/src/bdd/cudd/cudd.h
+abc-build/src/bdd/cudd/cudd.make
+abc-build/src/bdd/cudd/cuddAddAbs.c
+abc-build/src/bdd/cudd/cuddAddApply.c
+abc-build/src/bdd/cudd/cuddAddFind.c
+abc-build/src/bdd/cudd/cuddAddInv.c
+abc-build/src/bdd/cudd/cuddAddIte.c
+abc-build/src/bdd/cudd/cuddAddNeg.c
+abc-build/src/bdd/cudd/cuddAddWalsh.c
+abc-build/src/bdd/cudd/cuddAndAbs.c
+abc-build/src/bdd/cudd/cuddAnneal.c
+abc-build/src/bdd/cudd/cuddApa.c
+abc-build/src/bdd/cudd/cuddAPI.c
+abc-build/src/bdd/cudd/cuddApprox.c
+abc-build/src/bdd/cudd/cuddBddAbs.c
+abc-build/src/bdd/cudd/cuddBddCorr.c
+abc-build/src/bdd/cudd/cuddBddIte.c
+abc-build/src/bdd/cudd/cuddBridge.c
+abc-build/src/bdd/cudd/cuddCache.c
+abc-build/src/bdd/cudd/cuddCheck.c
+abc-build/src/bdd/cudd/cuddClip.c
+abc-build/src/bdd/cudd/cuddCof.c
+abc-build/src/bdd/cudd/cuddCompose.c
+abc-build/src/bdd/cudd/cuddDecomp.c
+abc-build/src/bdd/cudd/cuddEssent.c
+abc-build/src/bdd/cudd/cuddExact.c
+abc-build/src/bdd/cudd/cuddExport.c
+abc-build/src/bdd/cudd/cuddGenCof.c
+abc-build/src/bdd/cudd/cuddGenetic.c
+abc-build/src/bdd/cudd/cuddGroup.c
+abc-build/src/bdd/cudd/cuddHarwell.c
+abc-build/src/bdd/cudd/cuddInit.c
+abc-build/src/bdd/cudd/cuddInt.h
+abc-build/src/bdd/cudd/cuddInteract.c
+abc-build/src/bdd/cudd/cuddLCache.c
+abc-build/src/bdd/cudd/cuddLevelQ.c
+abc-build/src/bdd/cudd/cuddLinear.c
+abc-build/src/bdd/cudd/cuddLiteral.c
+abc-build/src/bdd/cudd/cuddMatMult.c
+abc-build/src/bdd/cudd/cuddPriority.c
+abc-build/src/bdd/cudd/cuddRead.c
+abc-build/src/bdd/cudd/cuddRef.c
+abc-build/src/bdd/cudd/cuddReorder.c
+abc-build/src/bdd/cudd/cuddSat.c
+abc-build/src/bdd/cudd/cuddSign.c
+abc-build/src/bdd/cudd/cuddSolve.c
+abc-build/src/bdd/cudd/cuddSplit.c
+abc-build/src/bdd/cudd/cuddSubsetHB.c
+abc-build/src/bdd/cudd/cuddSubsetSP.c
+abc-build/src/bdd/cudd/cuddSymmetry.c
+abc-build/src/bdd/cudd/cuddTable.c
+abc-build/src/bdd/cudd/cuddUtil.c
+abc-build/src/bdd/cudd/cuddWindow.c
+abc-build/src/bdd/cudd/cuddZddCount.c
+abc-build/src/bdd/cudd/cuddZddFuncs.c
+abc-build/src/bdd/cudd/cuddZddGroup.c
+abc-build/src/bdd/cudd/cuddZddIsop.c
+abc-build/src/bdd/cudd/cuddZddLin.c
+abc-build/src/bdd/cudd/cuddZddMisc.c
+abc-build/src/bdd/cudd/cuddZddPort.c
+abc-build/src/bdd/cudd/cuddZddReord.c
+abc-build/src/bdd/cudd/cuddZddSetop.c
+abc-build/src/bdd/cudd/cuddZddSymm.c
+abc-build/src/bdd/cudd/cuddZddUtil.c
+abc-build/src/bdd/cudd/license
+abc-build/src/bdd/cudd/Makefile
+abc-build/src/bdd/cudd/module.make
+abc-build/src/bdd/cudd/r7x8.1.mat
+abc-build/src/bdd/cudd/r7x8.1.out
+abc-build/src/bdd/cudd/testcudd.c
+abc-build/src/bdd/dsd/dsd.h
+abc-build/src/bdd/dsd/dsdApi.c
+abc-build/src/bdd/dsd/dsdCheck.c
+abc-build/src/bdd/dsd/dsdInt.h
+abc-build/src/bdd/dsd/dsdLocal.c
+abc-build/src/bdd/dsd/dsdMan.c
+abc-build/src/bdd/dsd/dsdProc.c
+abc-build/src/bdd/dsd/dsdTree.c
+abc-build/src/bdd/dsd/module.make
+abc-build/src/bdd/epd/epd.c
+abc-build/src/bdd/epd/epd.h
+abc-build/src/bdd/epd/module.make
+abc-build/src/bdd/mtr/module.make
+abc-build/src/bdd/mtr/mtr.h
+abc-build/src/bdd/mtr/mtrBasic.c
+abc-build/src/bdd/mtr/mtrGroup.c
+abc-build/src/bdd/mtr/mtrInt.h
+abc-build/src/bdd/parse/module.make
+abc-build/src/bdd/parse/parse.h
+abc-build/src/bdd/parse/parseCore.c
+abc-build/src/bdd/parse/parseEqn.c
+abc-build/src/bdd/parse/parseInt.h
+abc-build/src/bdd/parse/parseStack.c
+abc-build/src/bdd/reo/module.make
+abc-build/src/bdd/reo/reo.h
+abc-build/src/bdd/reo/reoApi.c
+abc-build/src/bdd/reo/reoCore.c
+abc-build/src/bdd/reo/reoProfile.c
+abc-build/src/bdd/reo/reoShuffle.c
+abc-build/src/bdd/reo/reoSift.c
+abc-build/src/bdd/reo/reoSwap.c
+abc-build/src/bdd/reo/reoTest.c
+abc-build/src/bdd/reo/reoTransfer.c
+abc-build/src/bdd/reo/reoUnits.c
+abc-build/src/bool/bdc/bdc.h
+abc-build/src/bool/bdc/bdc_.c
+abc-build/src/bool/bdc/bdcCore.c
+abc-build/src/bool/bdc/bdcDec.c
+abc-build/src/bool/bdc/bdcInt.h
+abc-build/src/bool/bdc/bdcSpfd.c
+abc-build/src/bool/bdc/bdcTable.c
+abc-build/src/bool/bdc/module.make
+abc-build/src/bool/dec/dec.h
+abc-build/src/bool/dec/decAbc.c
+abc-build/src/bool/dec/decFactor.c
+abc-build/src/bool/dec/decMan.c
+abc-build/src/bool/dec/decPrint.c
+abc-build/src/bool/dec/decUtil.c
+abc-build/src/bool/dec/module.make
+abc-build/src/bool/deco/deco.h
+abc-build/src/bool/deco/module.make
+abc-build/src/bool/kit/cloud.c
+abc-build/src/bool/kit/cloud.h
+abc-build/src/bool/kit/kit.h
+abc-build/src/bool/kit/kit_.c
+abc-build/src/bool/kit/kitAig.c
+abc-build/src/bool/kit/kitBdd.c
+abc-build/src/bool/kit/kitCloud.c
+abc-build/src/bool/kit/kitDec.c
+abc-build/src/bool/kit/kitDsd.c
+abc-build/src/bool/kit/kitFactor.c
+abc-build/src/bool/kit/kitGraph.c
+abc-build/src/bool/kit/kitHop.c
+abc-build/src/bool/kit/kitIsop.c
+abc-build/src/bool/kit/kitPerm.c
+abc-build/src/bool/kit/kitPla.c
+abc-build/src/bool/kit/kitSop.c
+abc-build/src/bool/kit/kitTruth.c
+abc-build/src/bool/kit/module.make
+abc-build/src/bool/lucky/lucky.c
+abc-build/src/bool/lucky/lucky.h
+abc-build/src/bool/lucky/luckyFast16.c
+abc-build/src/bool/lucky/luckyFast6.c
+abc-build/src/bool/lucky/luckyInt.h
+abc-build/src/bool/lucky/luckyRead.c
+abc-build/src/bool/lucky/luckySimple.c
+abc-build/src/bool/lucky/luckySwap.c
+abc-build/src/bool/lucky/luckySwapIJ.c
+abc-build/src/bool/lucky/module.make
+abc-build/src/bool/rpo/literal.h
+abc-build/src/bool/rpo/module.make
+abc-build/src/bool/rpo/rpo.c
+abc-build/src/bool/rpo/rpo.h
+abc-build/src/bool/rsb/module.make
+abc-build/src/bool/rsb/rsb.h
+abc-build/src/bool/rsb/rsbDec6.c
+abc-build/src/bool/rsb/rsbInt.h
+abc-build/src/bool/rsb/rsbMan.c
+abc-build/src/demo.c
+abc-build/src/generic.c
+abc-build/src/generic.h
+abc-build/src/map/amap/amap.h
+abc-build/src/map/amap/amapCore.c
+abc-build/src/map/amap/amapGraph.c
+abc-build/src/map/amap/amapInt.h
+abc-build/src/map/amap/amapLib.c
+abc-build/src/map/amap/amapLiberty.c
+abc-build/src/map/amap/amapMan.c
+abc-build/src/map/amap/amapMatch.c
+abc-build/src/map/amap/amapMerge.c
+abc-build/src/map/amap/amapOutput.c
+abc-build/src/map/amap/amapParse.c
+abc-build/src/map/amap/amapPerm.c
+abc-build/src/map/amap/amapRead.c
+abc-build/src/map/amap/amapRule.c
+abc-build/src/map/amap/amapUniq.c
+abc-build/src/map/amap/module.make
+abc-build/src/map/cov/cov.h
+abc-build/src/map/cov/covBuild.c
+abc-build/src/map/cov/covCore.c
+abc-build/src/map/cov/covInt.h
+abc-build/src/map/cov/covMan.c
+abc-build/src/map/cov/covMinEsop.c
+abc-build/src/map/cov/covMinMan.c
+abc-build/src/map/cov/covMinSop.c
+abc-build/src/map/cov/covMinUtil.c
+abc-build/src/map/cov/covTest.c
+abc-build/src/map/cov/module.make
+abc-build/src/map/fpga/fpga.c
+abc-build/src/map/fpga/fpga.h
+abc-build/src/map/fpga/fpgaCore.c
+abc-build/src/map/fpga/fpgaCreate.c
+abc-build/src/map/fpga/fpgaCut.c
+abc-build/src/map/fpga/fpgaCutUtils.c
+abc-build/src/map/fpga/fpgaFanout.c
+abc-build/src/map/fpga/fpgaGENERIC.c
+abc-build/src/map/fpga/fpgaInt.h
+abc-build/src/map/fpga/fpgaLib.c
+abc-build/src/map/fpga/fpgaMatch.c
+abc-build/src/map/fpga/fpgaSwitch.c
+abc-build/src/map/fpga/fpgaTime.c
+abc-build/src/map/fpga/fpgaTruth.c
+abc-build/src/map/fpga/fpgaUtils.c
+abc-build/src/map/fpga/fpgaVec.c
+abc-build/src/map/fpga/module.make
+abc-build/src/map/if/if.h
+abc-build/src/map/if/if_.c
+abc-build/src/map/if/ifCache.c
+abc-build/src/map/if/ifCheck.c
+abc-build/src/map/if/ifCom.c
+abc-build/src/map/if/ifCore.c
+abc-build/src/map/if/ifCount.h
+abc-build/src/map/if/ifCut.c
+abc-build/src/map/if/ifDec07.c
+abc-build/src/map/if/ifDec08.c
+abc-build/src/map/if/ifDec10.c
+abc-build/src/map/if/ifDec16.c
+abc-build/src/map/if/ifDec75.c
+abc-build/src/map/if/ifDelay.c
+abc-build/src/map/if/ifDsd.c
+abc-build/src/map/if/ifLibBox.c
+abc-build/src/map/if/ifLibLut.c
+abc-build/src/map/if/ifMan.c
+abc-build/src/map/if/ifMap.c
+abc-build/src/map/if/ifReduce.c
+abc-build/src/map/if/ifSat.c
+abc-build/src/map/if/ifSelect.c
+abc-build/src/map/if/ifSeq.c
+abc-build/src/map/if/ifTest.c
+abc-build/src/map/if/ifTime.c
+abc-build/src/map/if/ifTruth.c
+abc-build/src/map/if/ifTune.c
+abc-build/src/map/if/ifUtil.c
+abc-build/src/map/if/module.make
+abc-build/src/map/mapper/mapper.c
+abc-build/src/map/mapper/mapper.h
+abc-build/src/map/mapper/mapperCanon.c
+abc-build/src/map/mapper/mapperCore.c
+abc-build/src/map/mapper/mapperCreate.c
+abc-build/src/map/mapper/mapperCut.c
+abc-build/src/map/mapper/mapperCutUtils.c
+abc-build/src/map/mapper/mapperFanout.c
+abc-build/src/map/mapper/mapperInt.h
+abc-build/src/map/mapper/mapperLib.c
+abc-build/src/map/mapper/mapperMatch.c
+abc-build/src/map/mapper/mapperRefs.c
+abc-build/src/map/mapper/mapperSuper.c
+abc-build/src/map/mapper/mapperSwitch.c
+abc-build/src/map/mapper/mapperTable.c
+abc-build/src/map/mapper/mapperTime.c
+abc-build/src/map/mapper/mapperTree.c
+abc-build/src/map/mapper/mapperTruth.c
+abc-build/src/map/mapper/mapperUtils.c
+abc-build/src/map/mapper/mapperVec.c
+abc-build/src/map/mapper/module.make
+abc-build/src/map/mio/exp.h
+abc-build/src/map/mio/mio.c
+abc-build/src/map/mio/mio.h
+abc-build/src/map/mio/mioApi.c
+abc-build/src/map/mio/mioForm.c
+abc-build/src/map/mio/mioFunc.c
+abc-build/src/map/mio/mioInt.h
+abc-build/src/map/mio/mioParse.c
+abc-build/src/map/mio/mioRead.c
+abc-build/src/map/mio/mioSop.c
+abc-build/src/map/mio/mioUtils.c
+abc-build/src/map/mio/module.make
+abc-build/src/map/mpm/module.make
+abc-build/src/map/mpm/mpm.c
+abc-build/src/map/mpm/mpm.h
+abc-build/src/map/mpm/mpmAbc.c
+abc-build/src/map/mpm/mpmCore.c
+abc-build/src/map/mpm/mpmDsd.c
+abc-build/src/map/mpm/mpmGates.c
+abc-build/src/map/mpm/mpmInt.h
+abc-build/src/map/mpm/mpmLib.c
+abc-build/src/map/mpm/mpmMan.c
+abc-build/src/map/mpm/mpmMap.c
+abc-build/src/map/mpm/mpmMig.c
+abc-build/src/map/mpm/mpmMig.h
+abc-build/src/map/mpm/mpmPre.c
+abc-build/src/map/mpm/mpmTruth.c
+abc-build/src/map/mpm/mpmUtil.c
+abc-build/src/map/scl/module.make
+abc-build/src/map/scl/scl.c
+abc-build/src/map/scl/scl.h
+abc-build/src/map/scl/sclBuffer.c
+abc-build/src/map/scl/sclBufSize.c
+abc-build/src/map/scl/sclDnsize.c
+abc-build/src/map/scl/sclLib.h
+abc-build/src/map/scl/sclLiberty.c
+abc-build/src/map/scl/sclLibScl.c
+abc-build/src/map/scl/sclLibUtil.c
+abc-build/src/map/scl/sclLoad.c
+abc-build/src/map/scl/sclSize.c
+abc-build/src/map/scl/sclSize.h
+abc-build/src/map/scl/sclTime.h
+abc-build/src/map/scl/sclUpsize.c
+abc-build/src/map/scl/sclUtil.c
+abc-build/src/map/super/module.make
+abc-build/src/map/super/super.c
+abc-build/src/map/super/super.h
+abc-build/src/map/super/superAnd.c
+abc-build/src/map/super/superGate.c
+abc-build/src/map/super/superGENERIC.c
+abc-build/src/map/super/superInt.h
+abc-build/src/map/super/superWrite.c
+abc-build/src/misc/avl/avl.c
+abc-build/src/misc/avl/avl.doc
+abc-build/src/misc/avl/avl.h
+abc-build/src/misc/bar/bar.c
+abc-build/src/misc/bar/bar.h
+abc-build/src/misc/bar/module.make
+abc-build/src/misc/bbl/bblif.c
+abc-build/src/misc/bbl/bblif.h
+abc-build/src/misc/bbl/module.make
+abc-build/src/misc/bzlib/blocksort.c
+abc-build/src/misc/bzlib/bzip2.txt
+abc-build/src/misc/bzlib/bzlib.c
+abc-build/src/misc/bzlib/bzlib.h
+abc-build/src/misc/bzlib/bzlib_private.h
+abc-build/src/misc/bzlib/CHANGES
+abc-build/src/misc/bzlib/compress.c
+abc-build/src/misc/bzlib/crctable.c
+abc-build/src/misc/bzlib/decompress.c
+abc-build/src/misc/bzlib/huffman.c
+abc-build/src/misc/bzlib/LICENSE
+abc-build/src/misc/bzlib/link.txt
+abc-build/src/misc/bzlib/manual.html
+abc-build/src/misc/bzlib/module.make
+abc-build/src/misc/bzlib/randtable.c
+abc-build/src/misc/espresso/cofactor.c
+abc-build/src/misc/espresso/cols.c
+abc-build/src/misc/espresso/compl.c
+abc-build/src/misc/espresso/contain.c
+abc-build/src/misc/espresso/cubehack.c
+abc-build/src/misc/espresso/cubestr.c
+abc-build/src/misc/espresso/cvrin.c
+abc-build/src/misc/espresso/cvrm.c
+abc-build/src/misc/espresso/cvrmisc.c
+abc-build/src/misc/espresso/cvrout.c
+abc-build/src/misc/espresso/dominate.c
+abc-build/src/misc/espresso/equiv.c
+abc-build/src/misc/espresso/espresso.c
+abc-build/src/misc/espresso/espresso.h
+abc-build/src/misc/espresso/essen.c
+abc-build/src/misc/espresso/exact.c
+abc-build/src/misc/espresso/expand.c
+abc-build/src/misc/espresso/gasp.c
+abc-build/src/misc/espresso/gimpel.c
+abc-build/src/misc/espresso/globals.c
+abc-build/src/misc/espresso/hack.c
+abc-build/src/misc/espresso/indep.c
+abc-build/src/misc/espresso/irred.c
+abc-build/src/misc/espresso/main.c
+abc-build/src/misc/espresso/main.h.bak
+abc-build/src/misc/espresso/map.c
+abc-build/src/misc/espresso/matrix.c
+abc-build/src/misc/espresso/mincov.c
+abc-build/src/misc/espresso/mincov.h
+abc-build/src/misc/espresso/mincov_int.h
+abc-build/src/misc/espresso/module.make
+abc-build/src/misc/espresso/opo.c
+abc-build/src/misc/espresso/pair.c
+abc-build/src/misc/espresso/part.c
+abc-build/src/misc/espresso/primes.c
+abc-build/src/misc/espresso/reduce.c
+abc-build/src/misc/espresso/rows.c
+abc-build/src/misc/espresso/set.c
+abc-build/src/misc/espresso/setc.c
+abc-build/src/misc/espresso/sharp.c
+abc-build/src/misc/espresso/sminterf.c
+abc-build/src/misc/espresso/solution.c
+abc-build/src/misc/espresso/sparse.c
+abc-build/src/misc/espresso/sparse.h
+abc-build/src/misc/espresso/sparse_int.h
+abc-build/src/misc/espresso/unate.c
+abc-build/src/misc/espresso/util_old.h
+abc-build/src/misc/espresso/verify.c
+abc-build/src/misc/ext/ext.h
+abc-build/src/misc/ext/module.make
+abc-build/src/misc/extra/extra.h
+abc-build/src/misc/extra/extraBdd.h
+abc-build/src/misc/extra/extraBddAuto.c
+abc-build/src/misc/extra/extraBddCas.c
+abc-build/src/misc/extra/extraBddImage.c
+abc-build/src/misc/extra/extraBddKmap.c
+abc-build/src/misc/extra/extraBddMisc.c
+abc-build/src/misc/extra/extraBddSymm.c
+abc-build/src/misc/extra/extraBddTime.c
+abc-build/src/misc/extra/extraBddUnate.c
+abc-build/src/misc/extra/extraUtilBitMatrix.c
+abc-build/src/misc/extra/extraUtilCanon.c
+abc-build/src/misc/extra/extraUtilCube.c
+abc-build/src/misc/extra/extraUtilDsd.c
+abc-build/src/misc/extra/extraUtilEnum.c
+abc-build/src/misc/extra/extraUtilFile.c
+abc-build/src/misc/extra/extraUtilMemory.c
+abc-build/src/misc/extra/extraUtilMisc.c
+abc-build/src/misc/extra/extraUtilPerm.c
+abc-build/src/misc/extra/extraUtilProgress.c
+abc-build/src/misc/extra/extraUtilReader.c
+abc-build/src/misc/extra/extraUtilSupp.c
+abc-build/src/misc/extra/extraUtilTruth.c
+abc-build/src/misc/extra/extraUtilUtil.c
+abc-build/src/misc/extra/extraZddTrunc.c
+abc-build/src/misc/extra/module.make
+abc-build/src/misc/hash/hash.h
+abc-build/src/misc/hash/hashFlt.h
+abc-build/src/misc/hash/hashGen.h
+abc-build/src/misc/hash/hashInt.h
+abc-build/src/misc/hash/hashPtr.h
+abc-build/src/misc/hash/module.make
+abc-build/src/misc/mem/mem.c
+abc-build/src/misc/mem/mem.h
+abc-build/src/misc/mem/mem2.h
+abc-build/src/misc/mem/module.make
+abc-build/src/misc/mvc/module.make
+abc-build/src/misc/mvc/mvc.c
+abc-build/src/misc/mvc/mvc.h
+abc-build/src/misc/mvc/mvcApi.c
+abc-build/src/misc/mvc/mvcCompare.c
+abc-build/src/misc/mvc/mvcContain.c
+abc-build/src/misc/mvc/mvcCover.c
+abc-build/src/misc/mvc/mvcCube.c
+abc-build/src/misc/mvc/mvcDivide.c
+abc-build/src/misc/mvc/mvcDivisor.c
+abc-build/src/misc/mvc/mvcList.c
+abc-build/src/misc/mvc/mvcLits.c
+abc-build/src/misc/mvc/mvcMan.c
+abc-build/src/misc/mvc/mvcOpAlg.c
+abc-build/src/misc/mvc/mvcOpBool.c
+abc-build/src/misc/mvc/mvcPrint.c
+abc-build/src/misc/mvc/mvcSort.c
+abc-build/src/misc/mvc/mvcUtils.c
+abc-build/src/misc/nm/module.make
+abc-build/src/misc/nm/nm.h
+abc-build/src/misc/nm/nmApi.c
+abc-build/src/misc/nm/nmInt.h
+abc-build/src/misc/nm/nmTable.c
+abc-build/src/misc/st/module.make
+abc-build/src/misc/st/st.c
+abc-build/src/misc/st/st.h
+abc-build/src/misc/st/stmm.c
+abc-build/src/misc/st/stmm.h
+abc-build/src/misc/tim/module.make
+abc-build/src/misc/tim/tim.c
+abc-build/src/misc/tim/tim.h
+abc-build/src/misc/tim/timBox.c
+abc-build/src/misc/tim/timDump.c
+abc-build/src/misc/tim/timInt.h
+abc-build/src/misc/tim/timMan.c
+abc-build/src/misc/tim/timTime.c
+abc-build/src/misc/tim/timTrav.c
+abc-build/src/misc/util/abc_global.h
+abc-build/src/misc/util/module.make
+abc-build/src/misc/util/util_hack.h
+abc-build/src/misc/util/utilBridge.c
+abc-build/src/misc/util/utilCex.c
+abc-build/src/misc/util/utilCex.h
+abc-build/src/misc/util/utilColor.c
+abc-build/src/misc/util/utilFile.c
+abc-build/src/misc/util/utilMem.c
+abc-build/src/misc/util/utilMem.h
+abc-build/src/misc/util/utilNam.c
+abc-build/src/misc/util/utilNam.h
+abc-build/src/misc/util/utilSignal.c
+abc-build/src/misc/util/utilSignal.h
+abc-build/src/misc/util/utilSort.c
+abc-build/src/misc/util/utilTruth.h
+abc-build/src/misc/vec/module.make
+abc-build/src/misc/vec/vec.h
+abc-build/src/misc/vec/vecAtt.h
+abc-build/src/misc/vec/vecBit.h
+abc-build/src/misc/vec/vecFlt.h
+abc-build/src/misc/vec/vecHash.h
+abc-build/src/misc/vec/vecHsh.h
+abc-build/src/misc/vec/vecInt.h
+abc-build/src/misc/vec/vecMem.h
+abc-build/src/misc/vec/vecPtr.h
+abc-build/src/misc/vec/vecQue.h
+abc-build/src/misc/vec/vecSet.h
+abc-build/src/misc/vec/vecStr.h
+abc-build/src/misc/vec/vecVec.h
+abc-build/src/misc/vec/vecWec.h
+abc-build/src/misc/vec/vecWrd.h
+abc-build/src/misc/zlib/adler32.c
+abc-build/src/misc/zlib/algorithm.txt
+abc-build/src/misc/zlib/compress_.c
+abc-build/src/misc/zlib/crc32.c
+abc-build/src/misc/zlib/crc32.h
+abc-build/src/misc/zlib/deflate.c
+abc-build/src/misc/zlib/deflate.h
+abc-build/src/misc/zlib/gzclose.c
+abc-build/src/misc/zlib/gzguts.h
+abc-build/src/misc/zlib/gzlib.c
+abc-build/src/misc/zlib/gzread.c
+abc-build/src/misc/zlib/gzwrite.c
+abc-build/src/misc/zlib/infback.c
+abc-build/src/misc/zlib/inffast.c
+abc-build/src/misc/zlib/inffast.h
+abc-build/src/misc/zlib/inffixed.h
+abc-build/src/misc/zlib/inflate.c
+abc-build/src/misc/zlib/inflate.h
+abc-build/src/misc/zlib/inftrees.c
+abc-build/src/misc/zlib/inftrees.h
+abc-build/src/misc/zlib/license
+abc-build/src/misc/zlib/link.txt
+abc-build/src/misc/zlib/module.make
+abc-build/src/misc/zlib/README
+abc-build/src/misc/zlib/trees.c
+abc-build/src/misc/zlib/trees.h
+abc-build/src/misc/zlib/uncompr.c
+abc-build/src/misc/zlib/zconf.h
+abc-build/src/misc/zlib/zlib.h
+abc-build/src/misc/zlib/zutil.c
+abc-build/src/misc/zlib/zutil.h
+abc-build/src/opt/cgt/cgt.h
+abc-build/src/opt/cgt/cgtAig.c
+abc-build/src/opt/cgt/cgtCore.c
+abc-build/src/opt/cgt/cgtDecide.c
+abc-build/src/opt/cgt/cgtInt.h
+abc-build/src/opt/cgt/cgtMan.c
+abc-build/src/opt/cgt/cgtSat.c
+abc-build/src/opt/cgt/module.make
+abc-build/src/opt/csw/csw.h
+abc-build/src/opt/csw/csw_.c
+abc-build/src/opt/csw/cswCore.c
+abc-build/src/opt/csw/cswCut.c
+abc-build/src/opt/csw/cswInt.h
+abc-build/src/opt/csw/cswMan.c
+abc-build/src/opt/csw/cswTable.c
+abc-build/src/opt/csw/module.make
+abc-build/src/opt/cut/abcCut.c
+abc-build/src/opt/cut/cut.h
+abc-build/src/opt/cut/cutApi.c
+abc-build/src/opt/cut/cutCut.c
+abc-build/src/opt/cut/cutExpand.c
+abc-build/src/opt/cut/cutInt.h
+abc-build/src/opt/cut/cutList.h
+abc-build/src/opt/cut/cutMan.c
+abc-build/src/opt/cut/cutMerge.c
+abc-build/src/opt/cut/cutNode.c
+abc-build/src/opt/cut/cutOracle.c
+abc-build/src/opt/cut/cutPre22.c
+abc-build/src/opt/cut/cutSeq.c
+abc-build/src/opt/cut/cutTruth.c
+abc-build/src/opt/cut/module.make
+abc-build/src/opt/dar/dar.h
+abc-build/src/opt/dar/dar_.c
+abc-build/src/opt/dar/darBalance.c
+abc-build/src/opt/dar/darCore.c
+abc-build/src/opt/dar/darCut.c
+abc-build/src/opt/dar/darData.c
+abc-build/src/opt/dar/darInt.h
+abc-build/src/opt/dar/darLib.c
+abc-build/src/opt/dar/darMan.c
+abc-build/src/opt/dar/darPrec.c
+abc-build/src/opt/dar/darRefact.c
+abc-build/src/opt/dar/darResub.c
+abc-build/src/opt/dar/darScript.c
+abc-build/src/opt/dar/module.make
+abc-build/src/opt/dau/dau.c
+abc-build/src/opt/dau/dau.h
+abc-build/src/opt/dau/dauArray.c
+abc-build/src/opt/dau/dauCanon.c
+abc-build/src/opt/dau/dauCore.c
+abc-build/src/opt/dau/dauDivs.c
+abc-build/src/opt/dau/dauDsd.c
+abc-build/src/opt/dau/dauDsd2.c
+abc-build/src/opt/dau/dauEnum.c
+abc-build/src/opt/dau/dauGia.c
+abc-build/src/opt/dau/dauInt.h
+abc-build/src/opt/dau/dauMerge.c
+abc-build/src/opt/dau/dauNonDsd.c
+abc-build/src/opt/dau/dauTree.c
+abc-build/src/opt/dau/module.make
+abc-build/src/opt/fsim/fsim.h
+abc-build/src/opt/fsim/fsimCore.c
+abc-build/src/opt/fsim/fsimFront.c
+abc-build/src/opt/fsim/fsimInt.h
+abc-build/src/opt/fsim/fsimMan.c
+abc-build/src/opt/fsim/fsimSim.c
+abc-build/src/opt/fsim/fsimSwitch.c
+abc-build/src/opt/fsim/fsimTsim.c
+abc-build/src/opt/fsim/module.make
+abc-build/src/opt/fxu/fxu.c
+abc-build/src/opt/fxu/fxu.h
+abc-build/src/opt/fxu/fxuCreate.c
+abc-build/src/opt/fxu/fxuHeapD.c
+abc-build/src/opt/fxu/fxuHeapS.c
+abc-build/src/opt/fxu/fxuInt.h
+abc-build/src/opt/fxu/fxuList.c
+abc-build/src/opt/fxu/fxuMatrix.c
+abc-build/src/opt/fxu/fxuPair.c
+abc-build/src/opt/fxu/fxuPrint.c
+abc-build/src/opt/fxu/fxuReduce.c
+abc-build/src/opt/fxu/fxuSelect.c
+abc-build/src/opt/fxu/fxuSingle.c
+abc-build/src/opt/fxu/fxuUpdate.c
+abc-build/src/opt/fxu/module.make
+abc-build/src/opt/lpk/lpk.h
+abc-build/src/opt/lpk/lpk_.c
+abc-build/src/opt/lpk/lpkAbcDec.c
+abc-build/src/opt/lpk/lpkAbcDsd.c
+abc-build/src/opt/lpk/lpkAbcMux.c
+abc-build/src/opt/lpk/lpkAbcUtil.c
+abc-build/src/opt/lpk/lpkCore.c
+abc-build/src/opt/lpk/lpkCut.c
+abc-build/src/opt/lpk/lpkInt.h
+abc-build/src/opt/lpk/lpkMan.c
+abc-build/src/opt/lpk/lpkMap.c
+abc-build/src/opt/lpk/lpkMulti.c
+abc-build/src/opt/lpk/lpkMux.c
+abc-build/src/opt/lpk/lpkSets.c
+abc-build/src/opt/lpk/module.make
+abc-build/src/opt/mfs/mfs.h
+abc-build/src/opt/mfs/mfs_.c
+abc-build/src/opt/mfs/mfsCore.c
+abc-build/src/opt/mfs/mfsCore_.c
+abc-build/src/opt/mfs/mfsDiv.c
+abc-build/src/opt/mfs/mfsGia.c
+abc-build/src/opt/mfs/mfsInt.h
+abc-build/src/opt/mfs/mfsInter.c
+abc-build/src/opt/mfs/mfsMan.c
+abc-build/src/opt/mfs/mfsResub.c
+abc-build/src/opt/mfs/mfsResub_.c
+abc-build/src/opt/mfs/mfsSat.c
+abc-build/src/opt/mfs/mfsStrash.c
+abc-build/src/opt/mfs/mfsWin.c
+abc-build/src/opt/mfs/module.make
+abc-build/src/opt/nwk/module.make
+abc-build/src/opt/nwk/ntlnwk.h
+abc-build/src/opt/nwk/nwk.h
+abc-build/src/opt/nwk/nwk_.c
+abc-build/src/opt/nwk/nwkAig.c
+abc-build/src/opt/nwk/nwkBidec.c
+abc-build/src/opt/nwk/nwkCheck.c
+abc-build/src/opt/nwk/nwkDfs.c
+abc-build/src/opt/nwk/nwkFanio.c
+abc-build/src/opt/nwk/nwkFlow.c
+abc-build/src/opt/nwk/nwkFlow_depth.c
+abc-build/src/opt/nwk/nwkMan.c
+abc-build/src/opt/nwk/nwkMap.c
+abc-build/src/opt/nwk/nwkMerge.c
+abc-build/src/opt/nwk/nwkMerge.h
+abc-build/src/opt/nwk/nwkObj.c
+abc-build/src/opt/nwk/nwkSpeedup.c
+abc-build/src/opt/nwk/nwkStrash.c
+abc-build/src/opt/nwk/nwkTiming.c
+abc-build/src/opt/nwk/nwkUtil.c
+abc-build/src/opt/res/module.make
+abc-build/src/opt/res/res.h
+abc-build/src/opt/res/res_.c
+abc-build/src/opt/res/resCore.c
+abc-build/src/opt/res/resDivs.c
+abc-build/src/opt/res/resFilter.c
+abc-build/src/opt/res/resInt.h
+abc-build/src/opt/res/resSat.c
+abc-build/src/opt/res/resSim.c
+abc-build/src/opt/res/resSim_old.c
+abc-build/src/opt/res/resStrash.c
+abc-build/src/opt/res/resWin.c
+abc-build/src/opt/ret/module.make
+abc-build/src/opt/ret/ret_.c
+abc-build/src/opt/ret/retArea.c
+abc-build/src/opt/ret/retCore.c
+abc-build/src/opt/ret/retDelay.c
+abc-build/src/opt/ret/retFlow.c
+abc-build/src/opt/ret/retIncrem.c
+abc-build/src/opt/ret/retInit.c
+abc-build/src/opt/ret/retInt.h
+abc-build/src/opt/ret/retLvalue.c
+abc-build/src/opt/rwr/module.make
+abc-build/src/opt/rwr/rwr.h
+abc-build/src/opt/rwr/rwrDec.c
+abc-build/src/opt/rwr/rwrEva.c
+abc-build/src/opt/rwr/rwrExp.c
+abc-build/src/opt/rwr/rwrLib.c
+abc-build/src/opt/rwr/rwrMan.c
+abc-build/src/opt/rwr/rwrPrint.c
+abc-build/src/opt/rwr/rwrTemp.c
+abc-build/src/opt/rwr/rwrUtil.c
+abc-build/src/opt/rwt/module.make
+abc-build/src/opt/rwt/rwt.h
+abc-build/src/opt/rwt/rwtDec.c
+abc-build/src/opt/rwt/rwtMan.c
+abc-build/src/opt/rwt/rwtUtil.c
+abc-build/src/opt/sfm/module.make
+abc-build/src/opt/sfm/sfm.h
+abc-build/src/opt/sfm/sfmCnf.c
+abc-build/src/opt/sfm/sfmCore.c
+abc-build/src/opt/sfm/sfmInt.h
+abc-build/src/opt/sfm/sfmNtk.c
+abc-build/src/opt/sfm/sfmSat.c
+abc-build/src/opt/sfm/sfmWin.c
+abc-build/src/opt/sim/module.make
+abc-build/src/opt/sim/sim.h
+abc-build/src/opt/sim/simMan.c
+abc-build/src/opt/sim/simSat.c
+abc-build/src/opt/sim/simSeq.c
+abc-build/src/opt/sim/simSupp.c
+abc-build/src/opt/sim/simSwitch.c
+abc-build/src/opt/sim/simSym.c
+abc-build/src/opt/sim/simSymSat.c
+abc-build/src/opt/sim/simSymSim.c
+abc-build/src/opt/sim/simSymStr.c
+abc-build/src/opt/sim/simUtils.c
+abc-build/src/phys/place/hpwl
+abc-build/src/phys/place/libhmetis.h
+abc-build/src/phys/place/Makefile
+abc-build/src/phys/place/module.make
+abc-build/src/phys/place/place_base.c
+abc-build/src/phys/place/place_base.h
+abc-build/src/phys/place/place_bin.c
+abc-build/src/phys/place/place_genqp.c
+abc-build/src/phys/place/place_gordian.c
+abc-build/src/phys/place/place_gordian.h
+abc-build/src/phys/place/place_inc.c
+abc-build/src/phys/place/place_io.c
+abc-build/src/phys/place/place_legalize.c
+abc-build/src/phys/place/place_pads.c
+abc-build/src/phys/place/place_partition.c
+abc-build/src/phys/place/place_qpsolver.c
+abc-build/src/phys/place/place_qpsolver.h
+abc-build/src/phys/place/place_test.c
+abc-build/src/phys/place/README
+abc-build/src/proof/abs/abs.c
+abc-build/src/proof/abs/abs.h
+abc-build/src/proof/abs/absDup.c
+abc-build/src/proof/abs/absGla.c
+abc-build/src/proof/abs/absGlaOld.c
+abc-build/src/proof/abs/absIter.c
+abc-build/src/proof/abs/absOldCex.c
+abc-build/src/proof/abs/absOldRef.c
+abc-build/src/proof/abs/absOldSat.c
+abc-build/src/proof/abs/absOldSim.c
+abc-build/src/proof/abs/absOut.c
+abc-build/src/proof/abs/absPth.c
+abc-build/src/proof/abs/absRef.c
+abc-build/src/proof/abs/absRef.h
+abc-build/src/proof/abs/absRefJ.c
+abc-build/src/proof/abs/absRefJ.h
+abc-build/src/proof/abs/absRefSelect.c
+abc-build/src/proof/abs/absRpm.c
+abc-build/src/proof/abs/absRpmOld.c
+abc-build/src/proof/abs/absUtil.c
+abc-build/src/proof/abs/absVta.c
+abc-build/src/proof/abs/module.make
+abc-build/src/proof/bbr/bbr.h
+abc-build/src/proof/bbr/bbr_.c
+abc-build/src/proof/bbr/bbrCex.c
+abc-build/src/proof/bbr/bbrImage.c
+abc-build/src/proof/bbr/bbrNtbdd.c
+abc-build/src/proof/bbr/bbrReach.c
+abc-build/src/proof/bbr/module.make
+abc-build/src/proof/cec/cec.c
+abc-build/src/proof/cec/cec.h
+abc-build/src/proof/cec/cecCec.c
+abc-build/src/proof/cec/cecChoice.c
+abc-build/src/proof/cec/cecClass.c
+abc-build/src/proof/cec/cecCore.c
+abc-build/src/proof/cec/cecCorr.c
+abc-build/src/proof/cec/cecInt.h
+abc-build/src/proof/cec/cecIso.c
+abc-build/src/proof/cec/cecMan.c
+abc-build/src/proof/cec/cecPat.c
+abc-build/src/proof/cec/cecSeq.c
+abc-build/src/proof/cec/cecSim.c
+abc-build/src/proof/cec/cecSolve.c
+abc-build/src/proof/cec/cecSplit.c
+abc-build/src/proof/cec/cecSweep.c
+abc-build/src/proof/cec/cecSynth.c
+abc-build/src/proof/cec/module.make
+abc-build/src/proof/dch/dch.h
+abc-build/src/proof/dch/dchAig.c
+abc-build/src/proof/dch/dchChoice.c
+abc-build/src/proof/dch/dchClass.c
+abc-build/src/proof/dch/dchCnf.c
+abc-build/src/proof/dch/dchCore.c
+abc-build/src/proof/dch/dchInt.h
+abc-build/src/proof/dch/dchMan.c
+abc-build/src/proof/dch/dchSat.c
+abc-build/src/proof/dch/dchSim.c
+abc-build/src/proof/dch/dchSimSat.c
+abc-build/src/proof/dch/dchSweep.c
+abc-build/src/proof/dch/module.make
+abc-build/src/proof/fra/fra.h
+abc-build/src/proof/fra/fra_.c
+abc-build/src/proof/fra/fraBmc.c
+abc-build/src/proof/fra/fraCec.c
+abc-build/src/proof/fra/fraClass.c
+abc-build/src/proof/fra/fraClau.c
+abc-build/src/proof/fra/fraClaus.c
+abc-build/src/proof/fra/fraCnf.c
+abc-build/src/proof/fra/fraCore.c
+abc-build/src/proof/fra/fraHot.c
+abc-build/src/proof/fra/fraImp.c
+abc-build/src/proof/fra/fraInd.c
+abc-build/src/proof/fra/fraIndVer.c
+abc-build/src/proof/fra/fraLcr.c
+abc-build/src/proof/fra/fraMan.c
+abc-build/src/proof/fra/fraPart.c
+abc-build/src/proof/fra/fraSat.c
+abc-build/src/proof/fra/fraSec.c
+abc-build/src/proof/fra/fraSim.c
+abc-build/src/proof/fra/module.make
+abc-build/src/proof/fraig/fraig.h
+abc-build/src/proof/fraig/fraigApi.c
+abc-build/src/proof/fraig/fraigCanon.c
+abc-build/src/proof/fraig/fraigChoice.c
+abc-build/src/proof/fraig/fraigFanout.c
+abc-build/src/proof/fraig/fraigFeed.c
+abc-build/src/proof/fraig/fraigInt.h
+abc-build/src/proof/fraig/fraigMan.c
+abc-build/src/proof/fraig/fraigMem.c
+abc-build/src/proof/fraig/fraigNode.c
+abc-build/src/proof/fraig/fraigPrime.c
+abc-build/src/proof/fraig/fraigSat.c
+abc-build/src/proof/fraig/fraigTable.c
+abc-build/src/proof/fraig/fraigUtil.c
+abc-build/src/proof/fraig/fraigVec.c
+abc-build/src/proof/fraig/module.make
+abc-build/src/proof/int/int.h
+abc-build/src/proof/int/intCheck.c
+abc-build/src/proof/int/intContain.c
+abc-build/src/proof/int/intCore.c
+abc-build/src/proof/int/intCtrex.c
+abc-build/src/proof/int/intDup.c
+abc-build/src/proof/int/intFrames.c
+abc-build/src/proof/int/intInt.h
+abc-build/src/proof/int/intInter.c
+abc-build/src/proof/int/intM114.c
+abc-build/src/proof/int/intM114p.c
+abc-build/src/proof/int/intMan.c
+abc-build/src/proof/int/intUtil.c
+abc-build/src/proof/int/module.make
+abc-build/src/proof/int2/int2.h
+abc-build/src/proof/int2/int2Bmc.c
+abc-build/src/proof/int2/int2Core.c
+abc-build/src/proof/int2/int2Int.h
+abc-build/src/proof/int2/int2Refine.c
+abc-build/src/proof/int2/int2Util.c
+abc-build/src/proof/int2/module.make
+abc-build/src/proof/live/arenaViolation.c
+abc-build/src/proof/live/combination.c
+abc-build/src/proof/live/disjunctiveMonotone.c
+abc-build/src/proof/live/kLiveConstraints.c
+abc-build/src/proof/live/kliveness.c
+abc-build/src/proof/live/liveness.c
+abc-build/src/proof/live/liveness_sim.c
+abc-build/src/proof/live/ltl_parser.c
+abc-build/src/proof/live/module.make
+abc-build/src/proof/live/monotone.c
+abc-build/src/proof/llb/llb.c
+abc-build/src/proof/llb/llb.h
+abc-build/src/proof/llb/llb1Cluster.c
+abc-build/src/proof/llb/llb1Constr.c
+abc-build/src/proof/llb/llb1Core.c
+abc-build/src/proof/llb/llb1Group.c
+abc-build/src/proof/llb/llb1Hint.c
+abc-build/src/proof/llb/llb1Man.c
+abc-build/src/proof/llb/llb1Matrix.c
+abc-build/src/proof/llb/llb1Pivot.c
+abc-build/src/proof/llb/llb1Reach.c
+abc-build/src/proof/llb/llb1Sched.c
+abc-build/src/proof/llb/llb2Bad.c
+abc-build/src/proof/llb/llb2Core.c
+abc-build/src/proof/llb/llb2Driver.c
+abc-build/src/proof/llb/llb2Dump.c
+abc-build/src/proof/llb/llb2Flow.c
+abc-build/src/proof/llb/llb2Image.c
+abc-build/src/proof/llb/llb3Image.c
+abc-build/src/proof/llb/llb3Nonlin.c
+abc-build/src/proof/llb/llb4Cex.c
+abc-build/src/proof/llb/llb4Cluster.c
+abc-build/src/proof/llb/llb4Image.c
+abc-build/src/proof/llb/llb4Map.c
+abc-build/src/proof/llb/llb4Nonlin.c
+abc-build/src/proof/llb/llb4Sweep.c
+abc-build/src/proof/llb/llbInt.h
+abc-build/src/proof/llb/module.make
+abc-build/src/proof/pdr/module.make
+abc-build/src/proof/pdr/pdr.c
+abc-build/src/proof/pdr/pdr.h
+abc-build/src/proof/pdr/pdrClass.c
+abc-build/src/proof/pdr/pdrCnf.c
+abc-build/src/proof/pdr/pdrCore.c
+abc-build/src/proof/pdr/pdrInt.h
+abc-build/src/proof/pdr/pdrInv.c
+abc-build/src/proof/pdr/pdrMan.c
+abc-build/src/proof/pdr/pdrSat.c
+abc-build/src/proof/pdr/pdrTsim.c
+abc-build/src/proof/pdr/pdrUtil.c
+abc-build/src/proof/ssc/module.make
+abc-build/src/proof/ssc/ssc.h
+abc-build/src/proof/ssc/sscClass.c
+abc-build/src/proof/ssc/sscCore.c
+abc-build/src/proof/ssc/sscInt.h
+abc-build/src/proof/ssc/sscSat.c
+abc-build/src/proof/ssc/sscSim.c
+abc-build/src/proof/ssc/sscUtil.c
+abc-build/src/proof/ssw/module.make
+abc-build/src/proof/ssw/ssw.h
+abc-build/src/proof/ssw/sswAig.c
+abc-build/src/proof/ssw/sswBmc.c
+abc-build/src/proof/ssw/sswClass.c
+abc-build/src/proof/ssw/sswCnf.c
+abc-build/src/proof/ssw/sswConstr.c
+abc-build/src/proof/ssw/sswCore.c
+abc-build/src/proof/ssw/sswDyn.c
+abc-build/src/proof/ssw/sswFilter.c
+abc-build/src/proof/ssw/sswInt.h
+abc-build/src/proof/ssw/sswIslands.c
+abc-build/src/proof/ssw/sswLcorr.c
+abc-build/src/proof/ssw/sswMan.c
+abc-build/src/proof/ssw/sswPairs.c
+abc-build/src/proof/ssw/sswPart.c
+abc-build/src/proof/ssw/sswRarity.c
+abc-build/src/proof/ssw/sswRarity2.c
+abc-build/src/proof/ssw/sswSat.c
+abc-build/src/proof/ssw/sswSemi.c
+abc-build/src/proof/ssw/sswSim.c
+abc-build/src/proof/ssw/sswSimSat.c
+abc-build/src/proof/ssw/sswSweep.c
+abc-build/src/proof/ssw/sswUnique.c
+abc-build/src/python/abc.sh
+abc-build/src/python/abcpy_test.py
+abc-build/src/python/build.txt
+abc-build/src/python/getch.py
+abc-build/src/python/module.make
+abc-build/src/python/package.py
+abc-build/src/python/pyabc.i
+abc-build/src/python/pyabc_split.py
+abc-build/src/python/reachx_cmd.py
+abc-build/src/python/redirect.py
+abc-build/src/python/setup.py
+abc-build/src/sat/bmc/bmc.c
+abc-build/src/sat/bmc/bmc.h
+abc-build/src/sat/bmc/bmcBCore.c
+abc-build/src/sat/bmc/bmcBmc.c
+abc-build/src/sat/bmc/bmcBmc2.c
+abc-build/src/sat/bmc/bmcBmc3.c
+abc-build/src/sat/bmc/bmcBmcAnd.c
+abc-build/src/sat/bmc/bmcBmci.c
+abc-build/src/sat/bmc/bmcCexCare.c
+abc-build/src/sat/bmc/bmcCexCut.c
+abc-build/src/sat/bmc/bmcCexDepth.c
+abc-build/src/sat/bmc/bmcCexMin1.c
+abc-build/src/sat/bmc/bmcCexMin2.c
+abc-build/src/sat/bmc/bmcCexTools.c
+abc-build/src/sat/bmc/bmcEco.c
+abc-build/src/sat/bmc/bmcFault.c
+abc-build/src/sat/bmc/bmcICheck.c
+abc-build/src/sat/bmc/bmcInse.c
+abc-build/src/sat/bmc/bmcLoad.c
+abc-build/src/sat/bmc/bmcMaxi.c
+abc-build/src/sat/bmc/bmcMulti.c
+abc-build/src/sat/bmc/bmcUnroll.c
+abc-build/src/sat/bmc/module.make
+abc-build/src/sat/bsat/license
+abc-build/src/sat/bsat/module.make
+abc-build/src/sat/bsat/satChecker.c
+abc-build/src/sat/bsat/satClause.h
+abc-build/src/sat/bsat/satInter.c
+abc-build/src/sat/bsat/satInterA.c
+abc-build/src/sat/bsat/satInterB.c
+abc-build/src/sat/bsat/satInterP.c
+abc-build/src/sat/bsat/satMem.c
+abc-build/src/sat/bsat/satMem.h
+abc-build/src/sat/bsat/satProof.c
+abc-build/src/sat/bsat/satProof2.h
+abc-build/src/sat/bsat/satSolver.c
+abc-build/src/sat/bsat/satSolver.h
+abc-build/src/sat/bsat/satSolver2.c
+abc-build/src/sat/bsat/satSolver2.h
+abc-build/src/sat/bsat/satSolver2i.c
+abc-build/src/sat/bsat/satStore.c
+abc-build/src/sat/bsat/satStore.h
+abc-build/src/sat/bsat/satTrace.c
+abc-build/src/sat/bsat/satTruth.c
+abc-build/src/sat/bsat/satTruth.h
+abc-build/src/sat/bsat/satUtil.c
+abc-build/src/sat/bsat/satVec.h
+abc-build/src/sat/cnf/cnf.h
+abc-build/src/sat/cnf/cnf_.c
+abc-build/src/sat/cnf/cnfCore.c
+abc-build/src/sat/cnf/cnfCut.c
+abc-build/src/sat/cnf/cnfData.c
+abc-build/src/sat/cnf/cnfFast.c
+abc-build/src/sat/cnf/cnfMan.c
+abc-build/src/sat/cnf/cnfMap.c
+abc-build/src/sat/cnf/cnfPost.c
+abc-build/src/sat/cnf/cnfUtil.c
+abc-build/src/sat/cnf/cnfWrite.c
+abc-build/src/sat/cnf/module.make
+abc-build/src/sat/csat/csat_apis.c
+abc-build/src/sat/csat/csat_apis.h
+abc-build/src/sat/csat/module.make
+abc-build/src/sat/lsat/solver.h
+abc-build/src/sat/msat/module.make
+abc-build/src/sat/msat/msat.h
+abc-build/src/sat/msat/msatActivity.c
+abc-build/src/sat/msat/msatClause.c
+abc-build/src/sat/msat/msatClauseVec.c
+abc-build/src/sat/msat/msatInt.h
+abc-build/src/sat/msat/msatMem.c
+abc-build/src/sat/msat/msatOrderH.c
+abc-build/src/sat/msat/msatOrderJ.c
+abc-build/src/sat/msat/msatQueue.c
+abc-build/src/sat/msat/msatRead.c
+abc-build/src/sat/msat/msatSolverApi.c
+abc-build/src/sat/msat/msatSolverCore.c
+abc-build/src/sat/msat/msatSolverIo.c
+abc-build/src/sat/msat/msatSolverSearch.c
+abc-build/src/sat/msat/msatSort.c
+abc-build/src/sat/msat/msatVec.c
+abc-build/src/sat/proof/pr.c
+abc-build/src/sat/proof/pr.h
+abc-build/src/sat/proof/stats.txt
+abc-build/src/sat/psat/m114p.h
+abc-build/src/sat/psat/m114p_types.h
+abc-build/src/sat/psat/module.make
+abc-build/src/starter.c
+abc-build/src/template.c
diff --git a/scripts/build-abc.sh b/scripts/build-abc.sh
new file mode 100644
--- /dev/null
+++ b/scripts/build-abc.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+# bail out immediately if any command fails
+set -e
+
+ARCH="$1"
+OS="$2"
+
+# Default to do nothing for the REMOVE_CMD
+REMOVE_CMD=true
+
+REMOVE_ARGS="-R .drectve \
+  -R .debug \
+  -R .debug_abbrev \
+  -R .debug_aranges \
+  -R .debug_frame \
+  -R .debug_info \
+  -R .debug_line \
+  -R .debug_loc \
+  -R .debug_pubnames \
+  -R .debug_pubtypes \
+  -R .debug_ranges \
+  -R .debug_str"
+
+# Select architecture-dependent compiler flags
+case "$ARCH" in
+  "I386") A="-m32 -DLIN -DSIZEOF_VOID_P=4 -DSIZEOF_LONG=4 -DSIZEOF_INT=4" ;;
+  "X86_64") A="-m64 -fPIC -DLIN64 -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8 -DSIZEOF_INT=4" ;;
+  *) echo "Unknown architecture: $ARCH" ; exit 2 ;;
+esac
+
+# Set up some OS-dependent flags and actions
+case "$OS" in
+  "Linux") S="" ;;
+  "OSX") S="" ;;
+  "Windows") S="libabc.dll" ; A="-m32 -DWIN32_NO_DLL -DABC_NO_DYNAMIC_LINKING -DLIN -DNT -UWIN32 -DSIZEOF_VOID_P=4 -DSIZEOF_LONG=4 -DSIZEOF_INT=4 -DPTW32_STATIC_LIB -UZLIB_DLL -lmsvcrt -Wl,--undefined=___strtod,--wrap,strtod,--defsym,___wrap_strtod=___strtod" ; REMOVE_CMD="objcopy ${REMOVE_ARGS}" ;;
+  *) echo "Unknown OS: $OS" ; exit 2 ;;
+esac
+
+# Default to no pthreads
+if [ -z "$PTHREADS" ]; then
+  PTHREADS=0
+fi
+
+cd abc-build
+make -j4 ARCHFLAGS="-DABC_LIB $A" REMOVE_DRECTVE="$REMOVE_CMD" READLINE=0 PTHREADS="$PTHREADS" libabc.a $S
+
diff --git a/scripts/clean-abc.sh b/scripts/clean-abc.sh
new file mode 100644
--- /dev/null
+++ b/scripts/clean-abc.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+rm -r abc-build
+rm galois-abcBridge.tar.bz2
+rm scripts/abc-sources.txt
+rm scripts/abc-incl-dirs.txt
diff --git a/scripts/setup-abc.sh b/scripts/setup-abc.sh
new file mode 100644
--- /dev/null
+++ b/scripts/setup-abc.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+# bail out immediately if any command fails
+set -e
+
+ARCH="$1"
+OS="$2"
+
+SRC_TARBALL="https://bitbucket.org/rdockins/abc/get/galois-abcBridge.tar.bz2"
+LOCAL_TARBALL="galois-abcBridge.tar.bz2"
+
+# If the ABC source is not already fetched, download the galois-abcBridge
+# branch of the ABC project and unpack it in the "abc-build" subdirectory
+if [ ! -d abc-build ]; then
+  # Fetch the latest galois-abcBridge branch from BitBucket; use either curl or wget
+  # depending on which is installed
+  [ -e $LOCAL_TARBALL ] || curl -O $SRC_TARBALL || wget --no-check-certificate $SRC_TARBALL
+
+  # Unpack into the abc-build subdirectory
+  # Note: some games are played to strip off the top-level directory name that
+  # is automatically assigned by BitBucket
+  mkdir -p abc-build && (cd abc-build; tar xfj "../$LOCAL_TARBALL" --strip-components=1)
+fi
+
+# Build a list of the files in the ABC subdirectory that we can feed into
+# the Cabal system so that "setup sdist" works correctly. Likewise, setup
+# a list of directories so we can include relevant *.h files
+#
+# Note: fully-qualified 'find' is referenced to work around a problem building
+# under MinGW where unqualified 'find' refers to the Win32 utility of the same name
+
+if [ ! -e scripts/abc-sources.txt ]; then
+  /usr/bin/find abc-build -type f > scripts/abc-sources.txt
+fi
+
+if [ ! -e scripts/abc-incl-dirs.txt ]; then
+  /usr/bin/find abc-build/src -type d > scripts/abc-incl-dirs.txt
+fi
+
+# Make sure the build scripts are executable
+chmod +x abc-build/depends.sh
diff --git a/src/Data/ABC.hs b/src/Data/ABC.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC.hs
@@ -0,0 +1,86 @@
+{- |
+Module      : Data.ABC
+Copyright   : (c) Galois, Inc. 2010-2014
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : experimental
+Portability : portable
+
+Contains main interface to ABC, a system for sequential synthesis
+and verification.
+
+ABC provides many functions for manipulating Boolean networks.
+Internally, ABC provides two different ways of representing them: the
+older "AIG" interface, and a newer "GIA" interface.  This library
+exposes both interfaces, along with a handful of functions for
+manipulating them.
+
+-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+module Data.ABC (
+      -- * Library setup and teardown
+      initialize
+    , unsafeCleanup
+
+      -- * Standard ABC interface
+    , AIG
+    , AIGLit
+    , aigNetwork
+    , AIG.newAIG
+    , readAigerAsAIG
+
+      -- * New style ABC representation
+    , GIA
+    , GIALit
+    , giaNetwork
+    , GIA.newGIA
+    , readAigerAsGIA
+
+    , module Data.AIG
+    ) where
+
+import Data.ABC.Internal.Main
+
+import Data.AIG
+
+import Data.ABC.AIG (AIG)
+import qualified Data.ABC.AIG as AIG
+
+import Data.ABC.GIA (GIA)
+import qualified Data.ABC.GIA as GIA
+
+import Prelude hiding (and, not)
+
+type AIGLit = AIG.Lit
+
+-- | Proxy for AIG interface.
+aigNetwork :: Proxy AIGLit AIG
+aigNetwork = AIG.proxy
+
+type GIALit = GIA.Lit
+
+-- | Proxy for GIA interface.
+giaNetwork :: Proxy GIALit GIA
+giaNetwork = GIA.proxy
+
+-- | Initializes the ABC engine.  This function may be safely called
+-- multiple times.  Higher-level functions will automatically call this
+-- function, so it is only needed if using the FFI interfaces directly.
+initialize :: IO ()
+initialize = abcStart
+
+-- | Deinitializes the ABC engine.  ABC operations may not be run after
+-- this function is called.  Use with care; this may cause ABC datatypes
+-- to stop working.
+unsafeCleanup :: IO ()
+unsafeCleanup = abcStop
+
+
+-- | Read an AIGER file as an AIG network.
+readAigerAsAIG :: FilePath -> IO (Network AIGLit AIG)
+readAigerAsAIG = AIG.readAiger
+
+-- | Read an AIGER file as a GIA network.
+readAigerAsGIA :: FilePath -> IO (Network GIALit GIA)
+readAigerAsGIA = GIA.readAiger
diff --git a/src/Data/ABC/AIG.hs b/src/Data/ABC/AIG.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC/AIG.hs
@@ -0,0 +1,357 @@
+{-# LANGUAGE DoAndIfThenElse #-}
+{-# LANGUAGE EmptyDataDecls #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ViewPatterns #-}
+
+{- |
+Module      : Data.ABC.AIG
+Copyright   : Galois, Inc. 2010-2014
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : stable
+Portability : non-portable (language extensions)
+
+"Data.ABC.AIG" defines a set of higher level functions for manipulating
+and-inverter graph networks ('AIG') directly from ABC.  This module
+should be imported @qualified@, e.g.
+
+> import Data.ABC.AIG (AIG)
+> import qualified Data.ABC.AIG as AIG
+
+-}
+
+module Data.ABC.AIG
+  ( AIG
+  , newAIG
+  , readAiger
+  , proxy
+  , Lit
+  , true
+  , false
+  , writeToCNF
+  , writeAIGManToCNFWithMapping
+  , checkSat'
+    -- * Re-exports
+  , AIG.Network(..)
+  , AIG.networkInputCount
+  , AIG.IsAIG(..)
+  , AIG.IsLit(..)
+  , AIG.SatResult(..)
+  , AIG.VerifyResult(..)
+  , AIG.SomeGraph(..)
+  ) where
+
+import Prelude hiding (and, or, not)
+
+import Foreign
+
+import Control.Applicative
+import Control.Exception
+import Control.Monad
+import qualified Data.Vector.Storable as V
+import qualified Data.Vector.Storable.Mutable as VM
+import System.IO
+import qualified System.IO.Unsafe as Unsafe
+
+
+import Data.ABC.Internal.ABC
+import Data.ABC.Internal.AIG
+import Data.ABC.Internal.CNF
+import Data.ABC.Internal.Field
+import Data.ABC.Internal.FRAIG
+import Data.ABC.Internal.IO
+import Data.ABC.Internal.Main
+import Data.ABC.Internal.Orphan
+import Data.ABC.Internal.VecInt
+import Data.ABC.Internal.VecPtr
+
+import qualified Data.AIG as AIG
+import Data.ABC.Util
+
+newtype AIG s = AIG { _ntkPtr :: ForeignPtr Abc_Ntk_t_ }
+
+newtype Lit s = Lit { unLit :: Abc_Obj_t }
+  deriving (Eq, Storable)
+
+-- | Proxy for building AIG networks
+proxy :: AIG.Proxy Lit AIG
+proxy = AIG.Proxy id
+
+-- | Build a new, empty AIG graph
+newAIG :: IO (AIG.SomeGraph AIG)
+newAIG = do
+  abcStart -- Ensure's ABC has been initialized.
+  bracketOnError (abcNtkAlloc AbcNtkStrash AbcFuncAig True) abcNtkDelete $ \p -> do
+    AIG.SomeGraph . AIG <$> newForeignPtr p_abcNtkDelete p
+
+foreachPo :: Abc_Ntk_t -> (Abc_Obj_t -> IO a) -> IO [a]
+foreachPo ntk f = do
+  v <- abcNtkPos ntk
+  c <- vecPtrSize v
+  forN c $ \i -> do
+    f =<< vecPtrEntry v i
+
+foreachPo_ :: Abc_Ntk_t -> (Abc_Obj_t -> IO ()) -> IO ()
+foreachPo_ ntk f = do
+  v <- abcNtkPos ntk
+  c <- vecPtrSize v
+  forN_ c (f <=< vecPtrEntry v)
+
+
+-- | Delete all primary outputs.
+deletePos :: Abc_Ntk_t -> IO ()
+deletePos p = foreachPo_ p abcNtkDeleteObj
+
+-- | Check that a file can be read.
+-- N.B. We should eventually modify abc to be safe.
+checkReadable :: FilePath -> IO ()
+checkReadable path = withFile path ReadMode (\_ -> return())
+
+-- | Read an AIGER file as an AIG network
+readAiger :: FilePath -> IO (AIG.Network Lit AIG)
+readAiger path = do
+  abcStart
+  checkReadable path
+  bracketOnError (ioReadAiger path True) abcNtkDelete $ \p -> do
+    lc <- abcNtkLatchNum p
+    when (lc > 0) $ fail "Reading networks with latches is not yet supported."
+    -- Clear name man table.
+    nmManFree =<< readAt abcNtkManName p
+    writeAt abcNtkManName p =<< nmManCreate 1
+    -- Delete all primary outputs.
+    outputs <- foreachPo p $ \o -> do
+      i <- vecIntEntry (abcObjFanins o) 0
+      abcNtkDeleteObj o
+      Lit <$> abcNtkObj p (fromIntegral i)
+
+    -- Return new pointer.
+    fp <- newForeignPtr p_abcNtkDelete p
+    return (AIG.Network (AIG fp) outputs)
+
+withAIGPtr :: AIG s -> (Abc_Ntk_t -> IO a) -> IO a
+withAIGPtr (AIG fp) m = withForeignPtr fp m
+
+instance AIG.IsLit Lit where
+  not (Lit l) = Lit (abcObjNot l)
+  Lit x === Lit y = x == y
+
+{-# NOINLINE true #-}
+true :: AIG s -> Lit s
+true a = Unsafe.unsafePerformIO $ do
+  Lit <$> withAIGPtr a abcAigConst1
+
+false :: AIG s -> Lit s
+false a = AIG.not (true a)
+
+-- | Returns true is the literal is satisfiabile.
+checkSat' :: Ptr Abc_Ntk_t -> IO AIG.SatResult
+checkSat' pp = do
+  p <- peek pp
+  ic <- vecPtrSize =<< abcNtkPis p
+  oc <- vecPtrSize =<< abcNtkPos p
+  assert (oc == 1) $ do
+  isConstant <- checkIsConstant p
+  case isConstant of
+    Just True -> return (AIG.Sat (replicate ic False))
+    Just False  -> return AIG.Unsat
+    Nothing -> do
+      let params = proveParamsDefault { nItersMax'Prove_Params = 5 }
+      with params $ \pParams -> do
+        r <- abcNtkIvyProve pp (castPtr pParams)
+        case r of
+          -1 -> fail "Could not decide equivalence."
+          0 -> do
+            p1 <- peek pp
+            pModel <- abcNtkModel p1
+            AIG.Sat . fmap toBool <$> peekArray ic pModel
+          1 -> return AIG.Unsat
+          _ -> error $ "Unrecognized return code " ++ show r ++ " from abcNtkIvyProve"
+
+instance AIG.IsAIG Lit AIG where
+  newGraph _ = newAIG
+  aigerNetwork _ = readAiger
+
+  trueLit = true
+  falseLit = false
+
+  newInput a =
+    withAIGPtr a $ \p -> do
+      Lit <$> abcNtkCreateObj p AbcObjPi
+  and a x y = do
+    withAIGPtr a $ \p -> do
+     manFunc <- castPtr <$> abcNtkManFunc p
+     Lit <$> abcAigAnd manFunc (unLit x) (unLit y)
+  xor a x y = do
+    withAIGPtr a $ \p -> do
+      manFunc <- castPtr <$> abcNtkManFunc p
+      Lit <$> abcAigXor manFunc (unLit x) (unLit y)
+  mux a c t f = do
+    withAIGPtr a $ \p -> do
+      manFunc <- castPtr <$> abcNtkManFunc p
+      Lit <$> abcAigMux manFunc (unLit c) (unLit t) (unLit f)
+
+  inputCount a = withAIGPtr a (vecPtrSize <=< abcNtkPis)
+
+  getInput a i = do
+    withAIGPtr a $ \p -> do
+      v <- abcNtkPis p
+      Lit . castPtr <$> vecPtrEntry v i
+
+  writeAiger path a = do
+    withNetworkPtr a $ \p -> do
+      ioWriteAiger p path True False False
+
+  checkSat g l = do
+    withNetworkPtr (AIG.Network g [l]) $ \p -> do
+      alloca $ \pp -> do
+        poke pp =<< abcNtkDup p
+        flip finally (abcNtkDelete =<< peek pp) $ do
+        checkSat' pp
+
+  cec x y = do
+    ix <- networkInputCount x
+    iy <- networkInputCount y
+    assert (ix == iy) $ do
+    assert (outputCount x == outputCount y) $ do
+    withNetworkPtr x $ \xp -> do
+    withNetworkPtr y $ \yp -> do
+      alloca $ \pp -> do
+        flip finally (abcNtkDelete =<< peek pp) $ do
+          poke pp =<< abcNtkMiter xp yp False 0 False False
+          AIG.toVerifyResult <$> checkSat' pp
+
+  evaluator g inputs_l = do
+    withAIGPtr g $ \ntk -> do
+      -- Get vector with objects.
+      objs <- abcNtkObjs ntk
+      -- Get number of objects
+      var_count <- vecPtrSize objs
+
+      v <- VM.new var_count
+      -- Initialize constant literal value.
+      VM.write v 0 True
+
+      -- Initialize primary input.
+      pis <- abcNtkPis ntk
+      pi_count <- vecPtrSize pis
+      let inputs = V.fromList inputs_l
+      when (V.length inputs /= pi_count) $
+        fail "evaluate given unexpected number of inputs."
+      forI_ pi_count $ \pi_idx -> do
+        o <- vecPtrEntry pis pi_idx
+        idx <- fromIntegral <$> abcObjId o
+        VM.write v idx (inputs V.! pi_idx)
+      -- Initialize and nodes.
+      forI_ var_count $ \i -> do
+        o <- vecPtrEntry objs i
+        is_and <- abcObjIsAnd o
+        when is_and $ do
+          r0 <- evaluateFn v . Lit =<< abcObjLit0 o
+          r1 <- evaluateFn v . Lit =<< abcObjLit1 o
+          VM.write v i (r0 && r1)
+      -- Return evaluation function.
+      pureEvaluateFn <$> V.freeze v
+
+forI_ :: Monad m => Int -> (Int -> m ()) -> m ()
+forI_ = go 0
+  where go i n f | i < n = f i >> go (i+1) n f
+                 | otherwise = return ()
+
+{-# NOINLINE pureEvaluateFn #-}
+pureEvaluateFn :: V.Vector Bool -> Lit s -> Bool
+pureEvaluateFn v (Lit l) = Unsafe.unsafePerformIO $ do
+  let c = abcObjIsComplement l
+  let o = abcObjRegular l
+  i <- fromIntegral <$> abcObjId o
+  let n = V.length v
+  when (i >= n) $ fail "Literal created after evaluator was created."
+  return ((v V.! i) /= c)
+
+evaluateFn :: VM.IOVector Bool
+           -> Lit s
+           -> IO Bool
+evaluateFn v (Lit l) = do
+  let c = abcObjIsComplement l
+  let o = abcObjRegular l
+  i <- fromIntegral <$> abcObjId o
+  let n = VM.length v
+  when (i >= n) $ fail "Literal created after evaluator was created."
+
+  r <- VM.read v i
+  return (r /= c)
+
+networkInputCount :: AIG.Network l g -> IO Int
+networkInputCount (AIG.Network g _) = AIG.inputCount g
+
+outputCount :: AIG.Network l g -> Int
+outputCount (AIG.Network _ o) = length o
+
+withNetworkPtr :: AIG.Network Lit AIG
+               -> (Abc_Ntk_t -> IO a)
+               -> IO a
+withNetworkPtr (AIG.Network x o) m = do
+  withAIGPtr x $ \p -> do
+  flip finally (deletePos p) $ do
+    mapM_ (addPo p) o
+    m p
+
+addPo :: Abc_Ntk_t -> Lit s -> IO ()
+addPo p (Lit ptr) = do
+  po <- abcNtkCreateObj p AbcObjPo
+  abcObjAddFanin po ptr
+
+
+checkIsConstant :: Abc_Ntk_t -> IO (Maybe Bool)
+checkIsConstant p = do
+  c <- abcNtkMiterIsConstant p
+  case c of
+    -1 -> return Nothing
+    0 -> return (Just True)
+    1 -> return (Just False)
+    _ -> error $ "Unrecognized return code " ++ show c ++ " from abcNtkMiterIsConstant"
+
+-- | Run a computation using a handle to a new AIG Manager, and then free
+-- the AIG manager.
+withAbcNtkToDar :: Abc_Ntk_t
+                -> Bool
+                -> Bool
+                -> (Aig_Man_t -> IO a)
+                -> IO a
+withAbcNtkToDar ntk exors registers h = do
+  bracket (abcNtkToDar ntk exors registers)
+          aigManStop
+          h
+
+-- | Write a CNF file to the given path.
+-- Returns vector mapping combinational inputs to CNF Variable numbers.
+writeToCNF :: AIG s -> Lit s -> FilePath -> IO [Int]
+writeToCNF aig l path =
+  withNetworkPtr (AIG.Network aig [l]) $ \pNtk -> do
+    withAbcNtkToDar pNtk False False $ \pMan -> do
+      vars <- writeAIGManToCNFWithMapping pMan path
+      ciCount <- aigManCiNum pMan
+      forM [0..(ciCount - 1)] $ \i -> do
+        ci <- aigManCi pMan (fromIntegral i)
+        ((vars V.!) . fromIntegral) `fmap` (aigObjId ci)
+
+-- | Convert the network referred to by an AIG manager into CNF format
+-- and write to a file, returning a mapping from ABC object IDs to CNF
+-- variable numbers.
+writeAIGManToCNFWithMapping :: Aig_Man_t -> FilePath -> IO (V.Vector Int)
+writeAIGManToCNFWithMapping pMan path =
+  withCnfDerive pMan 0 $ \pCnf -> do
+    cnfDataWriteIntoFile pCnf path 1 nullPtr nullPtr
+    getCNFMapping pMan pCnf
+
+-- | Return the array mapping AIG network objects (indices) to CNF
+-- variable numbers (entries) for a CNF data object derived from the
+-- given AIG manager.
+getCNFMapping :: Aig_Man_t -> Cnf_Dat_t -> IO (V.Vector Int)
+getCNFMapping pMan pCnf = do
+    objCount <- fmap fromIntegral $ aigManObjNumMax pMan
+    varsPtr <- cnfVarNums pCnf
+    V.generateM objCount $ \i -> fromIntegral <$> peekElemOff varsPtr i
diff --git a/src/Data/ABC/GIA.hs b/src/Data/ABC/GIA.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC/GIA.hs
@@ -0,0 +1,379 @@
+{-# LANGUAGE DoAndIfThenElse #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ViewPatterns #-}
+
+{- |
+Module      : Data.ABC.GIA
+Copyright   : Galois, Inc. 2010-2014
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : experimental
+Portability : non-portable (language extensions)
+
+'Data.ABC.GIA' defines a set of functions for manipulating
+scalable and-inverter graph networks directly from ABC.  This module
+should be imported @qualified@, e.g.
+
+> import Data.ABC.GIA (GIA)
+> import qualified Data.ABC.GIA as GIA
+
+Scalable and-inverter graphs are briefly described at the Berkeley
+Verification and Synthesis Research Center's website.
+<http://bvsrc.org/research.html#AIG%20Package>  It is a more memory
+efficient method of storing AIG graphs.
+
+
+-}
+module Data.ABC.GIA
+    ( GIA
+    , newGIA
+      -- * Building lits
+    , Lit
+    , true
+    , false
+    , proxy
+      -- * Inspection
+    , LitView(..)
+    , litView
+      -- * File IO
+    , readAiger
+    , writeCNF
+      -- * QBF
+    , check_exists_forall
+      -- * Re-exports
+    , AIG.Proxy
+    , AIG.SomeGraph(..)
+    , AIG.IsLit(..)
+    , AIG.IsAIG(..)
+    , AIG.Network(..)
+    , AIG.SatResult(..)
+    , AIG.VerifyResult(..)
+    ) where
+
+import Prelude hiding (and, not, or)
+
+import Control.Exception hiding (evaluate)
+import Control.Monad
+import Control.Applicative
+import qualified Data.AIG as AIG
+import qualified Data.Vector.Storable as SV
+import qualified Data.Vector.Unboxed as V
+import qualified Data.Vector.Unboxed.Mutable as VM
+import Foreign hiding (void, xor)
+import System.Directory
+
+import Data.ABC.Internal.ABC
+import Data.ABC.Internal.ABCGlobal
+import Data.ABC.Internal.AIG
+import Data.ABC.Internal.CEC
+import Data.ABC.Internal.Field
+import Data.ABC.Internal.GIA
+import Data.ABC.Internal.GiaAig
+import Data.ABC.Internal.Main
+import Data.ABC.Internal.Orphan
+import Data.ABC.Internal.VecInt
+import qualified Data.ABC.AIG as AIG
+import Data.ABC.Util
+
+enumRange :: (Eq a, Enum a) => a -> a -> [a]
+enumRange i n | i == n = []
+              | otherwise = i : enumRange (succ i) n
+
+
+-- | An and-invertor graph network in GIA form.
+newtype GIA s = GIA { _giaPtr :: ForeignPtr Gia_Man_t_ }
+
+newtype Lit s = L { _unLit :: GiaLit }
+
+proxy :: AIG.Proxy Lit GIA
+proxy = AIG.Proxy id
+
+withGIAPtr :: GIA s -> (Gia_Man_t -> IO a) -> IO a
+withGIAPtr (GIA g) m = withForeignPtr g m
+
+-- | Build a new empty GIA graph
+newGIA :: IO (AIG.SomeGraph GIA)
+newGIA = do
+  abcStart
+  p <- giaManStart 4096
+  giaManHashAlloc p
+  AIG.SomeGraph . GIA <$> newForeignPtr p_giaManStop p
+
+-- | Read an AIGER file into a GIA graph
+readAiger :: FilePath -> IO (AIG.Network Lit GIA)
+readAiger path = do
+  abcStart
+  b <- doesFileExist path
+  unless b $ do
+    fail $ "Data.ABC.GIA.readAiger: file does not exist"
+  let skipStrash = False
+  bracketOnError (giaAigerRead path skipStrash False) giaManStop $ \p -> do
+    rn <- giaManRegNum p
+    when (rn /= 0) $ fail "Networks do not yet support latches."
+
+    cov <- giaManCos p
+
+    co_num <- fromIntegral <$> vecIntSize cov
+    outputs <- forN co_num $ \i -> do
+      idx <- GiaVar <$> vecIntEntry cov (fromIntegral i)
+      o <- giaManObj p idx
+      L <$> fanin0Lit o idx
+
+    -- Delete all Pos
+    clearVecInt cov
+
+    -- Return new pointer.
+    fp <- newForeignPtr p_giaManStop p
+    return (AIG.Network (GIA fp) outputs)
+
+instance AIG.IsLit Lit where
+  not (L x) = L (giaLitNot x)
+  L x === L y = x == y
+
+-- | Constant true node.
+true :: Lit s
+true = L giaManConst1Lit
+
+-- | Constant false node
+false :: Lit s
+false = L giaManConst0Lit
+
+instance AIG.IsAIG Lit GIA where
+
+  newGraph _ = newGIA
+
+  trueLit  _ = true
+  falseLit _ = false
+
+  newInput g = L <$> withGIAPtr g giaManAppendCi
+  and g (L x) (L y) = withGIAPtr g $ \p -> L <$> giaManHashAnd p x y
+  xor g (L x) (L y) = withGIAPtr g $ \p -> L <$> giaManHashXor p x y
+  mux g (L c) (L x) (L y) = withGIAPtr g $ \p -> L <$> giaManHashMux p c x y
+
+  inputCount g = fromIntegral <$> withGIAPtr g giaManCiNum
+  getInput g i = withGIAPtr g $ \p ->
+    L . giaVarLit <$> giaManCiVar p (fromIntegral i)
+
+  aigerNetwork _ = readAiger
+
+  writeAiger path g = do
+    withNetworkPtr g $ \p -> do
+      giaAigerWrite p path False False
+
+  checkSat ntk l = do
+    giaNetworkAsAIGMan (AIG.Network ntk [l]) $ \pMan -> do
+    -- Allocate a pointer to an ABC network.
+    alloca $ \pp -> do
+      flip finally (abcNtkDelete =<< peek pp) $ do
+        poke pp =<< abcNtkFromAigPhase pMan
+        AIG.checkSat' pp
+
+  cec gx gy = do
+    withNetworkPtr gx $ \x -> do
+    withNetworkPtr gy $ \y -> do
+    bracket (giaManMiter x y 0 True False False False) giaManStop $ \m -> do
+    r <- cecManVerify m cecManCecDefaultParams
+    case r of
+      1 -> return AIG.Valid
+      0 -> do
+        pCex <- giaManCexComb m
+        when (pCex == nullPtr) $ error "cec: Generated counter-example was invalid"
+        cex <- peekAbcCex pCex
+        let r2 = pData'inputs'Abc_Cex cex
+        case r2 of
+          [] -> error "cec: Generated counter-example had no inputs"
+          [bs] -> return (AIG.Invalid bs)
+          _ -> error "cec: Generated counter example has too many frames"
+      -1 -> fail "cec: failed"
+      _  -> error "cec: Unrecognized return code"
+
+  evaluator g inputs = do
+    withGIAPtr g $ \p -> do
+    vecSize <- fromIntegral <$> giaManObjNum p
+    vec <- VM.replicate vecSize False
+    input_count <- fromIntegral <$> giaManCiNum p
+    when (length inputs /= input_count) $ do
+      fail $ "evaluate given " ++ show (length inputs)
+          ++ " when " ++ show input_count ++ " expected."
+    -- initialize inputs
+    forM_ ([0..] `zip` inputs) $ \(i, b) -> do
+      cid <- giaVarIndex <$> giaManCiVar p i
+      assert (0 <= cid && cid < vecSize) $ do
+      VM.write vec cid b
+    -- Run and gates
+    forM_ (enumRange 1 vecSize) $ \i -> do
+      let var = GiaVar (fromIntegral i)
+      o <- giaManObj p var
+      isAnd <- giaObjIsAndOrConst0 o
+      when isAnd $ do
+        i0 <- giaVarIndex <$> giaObjFaninId0 o var
+        c0 <- giaObjFaninC0 o
+        i1 <- giaVarIndex <$> giaObjFaninId1 o var
+        c1 <- giaObjFaninC1 o
+        assert (0 <= i0 && i0 < vecSize) $ do
+        b0 <- VM.read vec i0
+        assert (0 <= i1 && i1 < vecSize) $ do
+        b1 <- VM.read vec i1
+        let r = (c0 /= b0) && (c1 /= b1)
+        VM.write vec i r
+    -- return the outputs
+    pureEvaluateFn <$> V.freeze vec
+
+pureEvaluateFn :: V.Vector Bool -> Lit s -> Bool
+pureEvaluateFn v (L l) = assert inRange (c /= (v V.! i))
+  where i = fromIntegral $ unGiaVar $ giaLitVar l
+        c = giaLitIsCompl l
+        inRange = 0 <= i && i < V.length v
+
+-- | Run computation with a Gia_Man_t containing the given network.
+withNetworkPtr :: AIG.Network Lit GIA -> (Gia_Man_t -> IO a) -> IO a
+withNetworkPtr (AIG.Network ntk out) m = do
+  withGIAPtr ntk $ \p -> do
+    -- Get original number of objects
+    orig_oc <- readAt giaManNObjs p
+    let reset = do
+          -- Reset object count.
+          writeAt giaManNObjs p orig_oc
+          -- Clear Cos
+          clearVecInt =<< giaManCos p
+    -- Run computation, then reset.
+    flip finally reset $ do
+      -- Add combinational outputs.
+      mapM_ (\(L o) -> giaManAppendCo p o) out
+      -- Run computation.
+      m p
+
+-- | Run a computation with an AIG man created from a GIA netowrk.
+giaNetworkAsAIGMan :: AIG.Network Lit GIA
+                   -> (Aig_Man_t -> IO a)
+                   -> IO a
+giaNetworkAsAIGMan ntk m = do
+  -- Get a GIA network pointer.
+  withNetworkPtr ntk $ \p -> do
+    -- Convert GIA to AIG.
+    bracket (giaManToAig p 0) aigManStop m
+
+giaVarIndex :: GiaVar -> Int
+giaVarIndex = fromIntegral . unGiaVar
+
+fanin0Lit :: Gia_Obj_t -> GiaVar -> IO GiaLit
+fanin0Lit o v = do
+  v0 <- giaObjFaninId0 o v
+  c0 <- giaObjFaninC0 o
+  return $ giaLitNotCond (giaVarLit v0) c0
+
+fanin1Lit :: Gia_Obj_t -> GiaVar -> IO GiaLit
+fanin1Lit o v = do
+  v0 <- giaObjFaninId1 o v
+  c0 <- giaObjFaninC1 o
+  return $ giaLitNotCond (giaVarLit v0) c0
+
+-- | A representation of a lit's strcture.
+data LitView l
+   = And !l !l
+   | NotAnd !l !l
+   | Input !Int
+   | NotInput !Int
+   | TrueLit
+   | FalseLit
+
+-- | Return a representation of how lit was constructed.
+litView :: GIA s -> Lit s -> IO (LitView (Lit s))
+litView g (L l)
+  | l == giaManConst0Lit = return FalseLit
+  | l == giaManConst1Lit = return TrueLit
+  | otherwise = do
+    let c = giaLitIsCompl l
+    let v = giaLitVar l
+    withGIAPtr g $ \p -> do
+    o <- giaManObj p v
+    t <- giaObjIsTerm o
+    d0 <- giaObjDiff0 o
+    if t && (d0 == gia_none) then do
+      idx <- fromIntegral <$> giaObjDiff1 o
+      return $ if c then NotInput idx else Input idx
+    else if t then do
+      l0 <- L <$> fanin0Lit o v
+      l1 <- L <$> fanin1Lit o v
+      return $ if c then NotAnd l0 l1 else And l0 l1
+    else
+      error $ "Invalid literal"
+
+
+-- | Allocate a vec int array from Boolean list.
+withBoolAsVecInt :: [Bool]
+                 -> (Vec_Int_t -> IO a)
+                 -> IO a
+withBoolAsVecInt l f = do
+  let assign_vals :: [CInt]
+      assign_vals = fromIntegral . fromEnum <$> l
+  withArray assign_vals $ \pval -> do
+  withVecInt (fromIntegral (length l)) pval f
+
+-- | Allocate a vec int array from Boolean list.
+getVecIntAsBool :: Vec_Int_t
+                -> IO [Bool]
+getVecIntAsBool v = do
+  sz <- vecIntSize v
+  forM [0..sz-1] $ \i -> do
+    e <- vecIntEntry v i
+    case e of
+      -1 -> return True
+      0 -> return False
+      1 -> return True
+      _ -> fail $ "getVecAsBool given bad value " ++ show e
+
+-- | Write a CNF file to the given path.
+--   Returns vector mapping combinational inputs to CNF Variable numbers.
+writeCNF :: GIA s -> Lit s -> FilePath -> IO [Int]
+writeCNF ntk l f = do
+  giaNetworkAsAIGMan (AIG.Network ntk [l]) $ \pMan -> do
+    vars <- AIG.writeAIGManToCNFWithMapping pMan f
+    ciCount <- aigManCiNum pMan
+    forM [0..(ciCount - 1)] $ \i -> do
+      ci <- aigManCi pMan (fromIntegral i)
+      ((vars SV.!) . fromIntegral) `fmap` (aigObjId ci)
+
+-- | Check a formula of the form Ex.Ay p(x,y)@.
+-- This function takes a network where input variables are used to
+-- represent both the existentially and the universally quantified variables.
+-- The existentially quantified variables must precede the universally quantified
+-- variables, and the number of extential variables is defined by an extra @Int@
+-- paramter.
+check_exists_forall :: GIA s
+                       -- ^ The GIA network used to store the terms.
+                    -> Int
+                       -- ^ The number of existential variables.
+                    -> Lit s
+                       -- ^ The proposition to verify.
+                    -> [Bool]
+                       -- ^ Initial value to use in search for universal variables.
+                       -- (should equal number of universal variables.).
+                    -> Int
+                       -- ^ Number of iterations to try solver.
+                    -> IO (Either String AIG.SatResult)
+check_exists_forall ntk exists_cnt prop init_assign iter_cnt = do
+  -- Get number of inputs
+  ic <- AIG.inputCount ntk
+  -- Check parameters
+  when (exists_cnt > ic) $ do
+    fail $ "Number of extential variables exceeds number of variables."
+  when (exists_cnt + length init_assign /= ic) $ do
+    fail $ "Mismatch between number of variables and initial assignment."
+  -- Create an AIG manager for network.
+  giaNetworkAsAIGMan (AIG.Network ntk [prop]) $ \pMan -> do
+  -- Allocate a pointer to an ABC network.
+  bracket (abcNtkFromAigPhase pMan) abcNtkDelete $ \p -> do
+  -- Allocate an array storing this information.
+  let elts = replicate exists_cnt False ++ init_assign
+  withBoolAsVecInt elts $ \v -> do
+  -- Call QBF function
+  r <- abcNtkQbf p exists_cnt iter_cnt v
+  case r of
+    1 -> return $ Right AIG.Unsat
+    0 -> Right . AIG.Sat . take exists_cnt <$> getVecIntAsBool v
+    -1 -> return $ Left "Iteration limit reached."
+    -2 -> return $ Left "Solver timeout."
+    _ -> fail "internal: Unexpected value returned by abcNtkQbf."
diff --git a/src/Data/ABC/Internal/ABC.chs b/src/Data/ABC/Internal/ABC.chs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC/Internal/ABC.chs
@@ -0,0 +1,403 @@
+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+{- |
+Module      : Data.ABC.Internal.ABC
+Copyright   : Galois, Inc. 2010-2014
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : experimental
+Portability : non-portable (c2hs, language extensions)
+
+/Incomplete./ Binding of @base\/base\/abc.h@ for manipulating and
+running algorithms on the original ABC datatypes.
+
+This current incomplete binding focuses on functions for manipulating
+and-inverter graphs (AIGs).
+-}
+
+module Data.ABC.Internal.ABC
+    (
+    -- * Types
+    -- ** Enums
+      Abc_NtkType_t(..)
+    , Abc_NtkFunc_t(..)
+    , Abc_ObjType_t(..)
+    -- ** Opague types
+    , Abc_Ntk_t_
+    , Abc_Obj_t_
+
+    -- ** Pointer types
+    , Abc_Ntk_t
+    , Abc_Obj_t
+    -- * Base
+    -- ** Network getters
+    , abcNtkFunc
+    , abcNtkManName
+    , abcNtkObjs
+    , abcNtkPis
+    , abcNtkPos
+    , abcNtkObj
+    , abcNtkManFunc
+    , abcNtkModel
+    , abcNtkExdc
+    -- ** Counting objects
+    , abcNtkPiNum
+    , abcNtkPoNum
+    , abcNtkCiNum
+    , abcNtkCoNum
+    , abcNtkLatchNum
+    -- ** Creating simple objects
+    , abcNtkCreateObj
+    , abcObjNot
+      -- ** Name manager
+    , Nm_Man_t_
+    , Nm_Man_t
+    , nmManCreate
+    , nmManFree
+
+    -- ** Object getters
+    , abcObjIsComplement
+    , abcObjRegular
+    , abcObjId
+    , abcObjType
+    , abcObjFanins
+    , abcObjIsAnd
+    , abcObjLit0
+    , abcObjLit1
+    , abcAigAnd
+    , abcAigXor
+    , abcAigMux
+    , abcAigConst1
+    , abcAigCleanup
+    -- ** abcFanio.c
+    -- | Functions for manipulating fanins and fanouts of a node.
+    , abcObjAddFanin
+    -- ** abcMiter.c
+    -- | Functions for manipulating miters, a combination of two
+    -- circuits that outputs @1@ if the outputs of the two original
+    -- circuits would have been different.
+    , abcNtkMiter
+    , abcNtkMiterIsConstant
+    -- ** abcNames.c
+    -- | Functions for manipulating the names attached to distinguished
+    -- nodes.  Many functions in ABC require that networks being
+    -- combined be named equivalently, so adopting the canonical form
+    -- by 'abcNtkShortNames' helps avoid name mismatch errors.
+    , abcNtkShortNames
+    -- ** abcNtk.c
+    -- | Functions for allocating and deleting networks, each of which
+    -- manages the memory of all nodes and other locations attached to it.
+    , abcNtkAlloc
+    , abcNtkDup
+    , abcNtkDelete
+    , p_abcNtkDelete
+    -- ** abcObj.c
+    -- | Functions for manipulating objects in networks.
+    , abcNtkDeleteObj
+    -- ** abcProve.c
+    -- | Functions for performing SAT solving.
+    , abcNtkIvyProve
+    -- ** abcVerify.c
+    -- | Functions for creating and testing counterexample models.
+    , abcNtkVerifySimulatePattern
+    -- ** abcBrdige_qbf
+    , abcNtkQbf
+    ) where
+
+import Control.Monad
+import Foreign
+import Foreign.C
+
+{#import Data.ABC.Internal.VecInt #}
+{#import Data.ABC.Internal.VecPtr #}
+
+import Data.ABC.Internal.Field
+
+#include "abcbridge.h"
+#include "abc.h"
+
+data Nm_Man_t_
+
+{#pointer *Nm_Man_t->Nm_Man_t_ #}
+
+{#fun Nm_ManCreate as ^
+   { id `CInt' -- nSize
+   } -> `Nm_Man_t' #}
+
+{#fun Nm_ManFree as ^
+   { id `Nm_Man_t' -- p
+   } -> `()' #}
+
+cintEnum :: (Integral a, Enum b) => a -> b
+cintEnum v = toEnum (fromIntegral v)
+
+enumCInt :: Enum a => a -> CInt
+enumCInt v = fromIntegral (fromEnum v)
+
+{#enum Abc_NtkType_t {underscoreToCase} deriving (Show, Eq) #}
+{#enum Abc_NtkFunc_t {underscoreToCase} deriving (Show, Eq) #}
+{#enum Abc_ObjType_t {underscoreToCase} deriving (Show, Eq) #}
+{#enum Abc_InitType_t {underscoreToCase} deriving (Show, Eq) #}
+
+data Abc_Ntk_t_
+data Abc_Obj_t_
+data Abc_Aig_t_
+
+-- | 'Abc_Obj_t' pointer that can have it's lower bit complemented,
+-- and thus needs to be converted into an 'Abc_Obj_t' before you
+-- can dereference it.
+
+{#pointer *Abc_Ntk_t -> Abc_Ntk_t_ #}
+{#pointer *Abc_Obj_t -> Abc_Obj_t_ #}
+{#pointer *Abc_Aig_t -> Abc_Aig_t_ #}
+
+-- | Default foreign pointer constructor that just calls free() on the
+-- pointer when it is no longer being used.
+-- XXX move this somewhere common
+newDefaultForeignPtr :: Ptr a -> IO (ForeignPtr a)
+newDefaultForeignPtr = newForeignPtr p_abcPrimFree
+
+foreign import ccall unsafe "stdlib.h &free"
+    p_abcPrimFree :: FunPtr (Ptr a -> IO ())
+
+abcNtkCreateObj :: Abc_Ntk_t -> Abc_ObjType_t -> IO Abc_Obj_t
+abcNtkCreateObj ntk tp = abcNtkCreateObj' ntk (enumCInt tp)
+
+foreign import ccall unsafe "Abc_NtkCreateObj"
+  abcNtkCreateObj' :: Abc_Ntk_t -> CInt -> IO Abc_Obj_t
+
+-- inline definitions
+
+abcNtkFunc :: Abc_Ntk_t -> IO Abc_NtkFunc_t
+abcNtkFunc ntk = cintEnum `fmap` {#get Abc_Ntk_t->ntkFunc #} ntk
+
+-- | Network name manager.
+abcNtkManName :: Field Abc_Ntk_t Nm_Man_t
+abcNtkManName = fieldFromOffset {#offsetof Abc_Ntk_t->pManName#}
+
+-- | Return array of all objects.
+abcNtkObjs :: Abc_Ntk_t -> IO Vec_Ptr_t
+abcNtkObjs = {#get Abc_Ntk_t->vObjs #}
+
+-- | Return primary inputs.
+abcNtkPis :: Abc_Ntk_t -> IO Vec_Ptr_t
+abcNtkPis = {#get Abc_Ntk_t->vPis #}
+
+-- | Return primary outputs.
+abcNtkPos :: Abc_Ntk_t -> IO Vec_Ptr_t
+abcNtkPos = {#get Abc_Ntk_t->vPos #}
+
+-- | Return combinational inputs (PIs, latches)
+abcNtkCis :: Abc_Ntk_t -> IO Vec_Ptr_t
+abcNtkCis = {#get Abc_Ntk_t->vCis #}
+
+-- | Return combinational outputs (POs, asserts, latches).
+abcNtkCos :: Abc_Ntk_t -> IO Vec_Ptr_t
+abcNtkCos = {#get Abc_Ntk_t->vCos #}
+
+-- | The functionality manager varies between 'AbcNtkFunc'.  In the case
+-- of 'AbcFuncAig', this pointer is guaranteed to be an 'Abc_Aig_t'.
+abcNtkManFunc :: Abc_Ntk_t -> IO (Ptr ())
+abcNtkManFunc = {#get Abc_Ntk_t->pManFunc #}
+
+-- | Return pointer to model associated with network.
+abcNtkModel :: Abc_Ntk_t -> IO (Ptr CInt)
+abcNtkModel = {#get Abc_Ntk_t->pModel #}
+
+-- | The EXDC network.
+abcNtkExdc :: Field Abc_Ntk_t Abc_Ntk_t
+abcNtkExdc = fieldFromOffset {#offsetof Abc_Ntk_t->pExdc #}
+
+abcNtkObj :: Abc_Ntk_t -> Int -> IO Abc_Obj_t
+abcNtkObj ntk i = do
+  v <- abcNtkObjs ntk
+  vecPtrEntry v i
+
+abcNtkPiNum :: Abc_Ntk_t -> IO Int
+abcNtkPiNum = vecPtrSize <=< abcNtkPis
+
+abcNtkPoNum :: Abc_Ntk_t -> IO Int
+abcNtkPoNum = vecPtrSize <=< abcNtkPos
+
+abcNtkCiNum :: Abc_Ntk_t -> IO Int
+abcNtkCiNum = vecPtrSize <=< abcNtkCis
+
+abcNtkCoNum :: Abc_Ntk_t -> IO Int
+abcNtkCoNum = vecPtrSize <=< abcNtkCos
+
+abcNtkObjCounts :: Abc_Ntk_t -> Ptr CInt
+abcNtkObjCounts = (`plusPtr` {#offsetof Abc_Ntk_t->nObjCounts #})
+
+abcNtkObjCount :: Abc_Ntk_t -> Abc_ObjType_t -> IO CInt
+abcNtkObjCount p tp = peekElemOff (abcNtkObjCounts p) (fromEnum tp)
+
+abcNtkLatchNum :: Abc_Ntk_t -> IO CInt
+abcNtkLatchNum = (`abcNtkObjCount` AbcObjLatch)
+
+-- | Object network
+abcObjNtk :: Abc_Obj_t -> IO Abc_Ntk_t
+abcObjNtk = {#get Abc_Obj_t->pNtk #}
+
+-- | Object identifier.
+abcObjId :: Abc_Obj_t -> IO CInt
+abcObjId = {#get Abc_Obj_t->Id #}
+
+-- | Object type.
+abcObjType :: Abc_Obj_t -> IO Abc_ObjType_t
+abcObjType o = cintEnum `fmap` {#get Abc_Obj_t->Type #} o
+
+-- | Indicates if first fanin of object is complemented.
+abcObjCompl0 :: Abc_Obj_t -> IO Bool
+abcObjCompl0 o = cintEnum `fmap` {#get Abc_Obj_t->fCompl0 #} o
+
+-- | Indicates if second fanin of object is complemented.
+abcObjCompl1 :: Abc_Obj_t -> IO Bool
+abcObjCompl1 o = cintEnum `fmap` {#get Abc_Obj_t->fCompl1 #} o
+
+-- | Get object fanins.
+abcObjFanins :: Abc_Obj_t -> Vec_Int_t
+abcObjFanins = (`plusPtr` {#offsetof Abc_Obj_t->vFanins #})
+
+
+abcObjFaninIdx :: Abc_Obj_t -> Int -> IO Int
+abcObjFaninIdx o i = do
+  fromIntegral `fmap` vecIntEntry (abcObjFanins o) (fromIntegral i)
+
+-- | Return true if this an and gate.
+abcObjIsAnd :: Abc_Obj_t -> IO Bool
+abcObjIsAnd o = do
+  fanin_count <- vecIntSize (abcObjFanins o)
+  return (fanin_count == 2)
+
+-- | Return fanin obj at given index.
+abcFaninObj :: Abc_Ntk_t -> Abc_Obj_t -> Int -> IO Abc_Obj_t
+abcFaninObj ntk o i = do
+  objs <- abcNtkObjs ntk
+  idx <- abcObjFaninIdx o i
+  vecPtrEntry objs idx
+
+abcObjNotIf :: Abc_Obj_t -> Bool -> Abc_Obj_t
+abcObjNotIf o b = wordPtrToPtr $ ptrToWordPtr o `xor` (if b then 1 else 0)
+
+abcObjLit0 :: Abc_Obj_t -> IO Abc_Obj_t
+abcObjLit0 o = do
+  ntk <- abcObjNtk o
+  o0 <- abcFaninObj ntk o 0
+  c0 <- abcObjCompl0 o
+  return (o0 `abcObjNotIf` c0)
+
+abcObjLit1 :: Abc_Obj_t -> IO Abc_Obj_t
+abcObjLit1 o = do
+  ntk <- abcObjNtk o
+  o1 <- abcFaninObj ntk o 1
+  c1 <- abcObjCompl1 o
+  return (o1 `abcObjNotIf` c1)
+
+-- | Return true if object is complemented.
+abcObjIsComplement :: Abc_Obj_t -> Bool
+abcObjIsComplement o = ptrToWordPtr o `testBit` 0
+
+-- | Return  normalized object.
+abcObjRegular :: Abc_Obj_t -> Abc_Obj_t
+abcObjRegular o = wordPtrToPtr $ ptrToWordPtr o `clearBit` 0
+
+-- | Negate object.
+abcObjNot :: Abc_Obj_t -> Abc_Obj_t
+abcObjNot o = wordPtrToPtr $ ptrToWordPtr o `xor` 1
+
+-- abcAig.c
+
+foreign import ccall unsafe "Abc_AigAnd"
+  abcAigAnd :: Abc_Aig_t -> Abc_Obj_t -> Abc_Obj_t -> IO Abc_Obj_t
+
+foreign import ccall unsafe "Abc_AigXor"
+  abcAigXor :: Abc_Aig_t -> Abc_Obj_t -> Abc_Obj_t -> IO Abc_Obj_t
+
+foreign import ccall unsafe "Abc_AigMux"
+  abcAigMux :: Abc_Aig_t -> Abc_Obj_t -> Abc_Obj_t -> Abc_Obj_t -> IO Abc_Obj_t
+
+{#fun Abc_AigConst1 as ^
+    { id `Abc_Ntk_t'
+    } -> `Abc_Obj_t' id #}
+
+foreign import ccall unsafe "Abc_AigCleanup"
+  abcAigCleanup :: Abc_Aig_t -> IO CInt
+
+-- abcFanio.c
+
+{#fun Abc_ObjAddFanin as ^
+    { id `Abc_Obj_t' -- pObj
+    , id `Abc_Obj_t' -- pFanin
+    } -> `()' #}
+
+-- abcMiter.c
+
+{#fun Abc_NtkMiter as ^ -- XXX: assume that both Ntks are still usable
+    { id `Abc_Ntk_t'
+    , id `Abc_Ntk_t'
+    , `Bool' -- fComb
+    , `Int'  -- nPartSize
+    , `Bool' -- fImplic
+    , `Bool' -- fMulti
+    } -> `Abc_Ntk_t' id #}
+
+{#fun Abc_NtkMiterIsConstant as ^
+    { id `Abc_Ntk_t'
+    } -> `Int' #}
+
+-- abcNames.c
+
+{#fun Abc_NtkShortNames as ^
+    { id `Abc_Ntk_t'
+    } -> `()' #}
+
+-- abcNtk.c
+
+{#fun Abc_NtkAlloc as ^
+    { enumCInt `Abc_NtkType_t'
+    , enumCInt `Abc_NtkFunc_t'
+    , `Bool' -- fUseMemMan
+    } -> `Abc_Ntk_t' id #}
+
+-- | Duplicate a network, allocating memory for the new network.  This
+-- procedure does not preserve the @Id@ of objects.
+{#fun Abc_NtkDup as ^
+    { id `Abc_Ntk_t'
+    } -> `Abc_Ntk_t' id #}
+
+{#fun Abc_NtkDelete as ^
+    { id `Abc_Ntk_t'
+    } -> `()' #}
+
+
+foreign import ccall unsafe "&Abc_NtkDelete"
+    p_abcNtkDelete :: FunPtr (Abc_Ntk_t -> IO ())
+
+-- abcObj.c
+
+{#fun Abc_NtkDeleteObj as ^
+    { id `Abc_Obj_t'
+    } -> `()' #}
+
+-- abcProve.c
+
+{#fun Abc_NtkIvyProve as ^
+    { id `Ptr Abc_Ntk_t'
+    , id `Ptr ()'
+    } -> `Int' #}
+
+-- abcVerify.c
+
+{#fun Abc_NtkVerifySimulatePattern as ^
+    { id `Abc_Ntk_t'
+    , id `Ptr CInt'
+    } -> `ForeignPtr CInt' newDefaultForeignPtr* #}
+
+-- abcBridge_qbv.c
+
+{#fun AbcBridge_NtkQbf as abcNtkQbf
+    { id `Abc_Ntk_t' -- Network
+    , `Int' -- Number of parameters
+    , `Int' -- Maximum number of iterations.
+    , id `Vec_Int_t' -- Vector for storing result.
+    } -> `Int' #}
diff --git a/src/Data/ABC/Internal/ABCGlobal.chs b/src/Data/ABC/Internal/ABCGlobal.chs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC/Internal/ABCGlobal.chs
@@ -0,0 +1,91 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE EmptyDataDecls #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+{- |
+Module      : Data.ABC.Internal.ABCGlobal
+Copyright   : (c) Galois, Inc. 2010
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : experimental
+Portability : not portable (c2hs, language extensions)
+
+/Incomplete./  Binding of @misc\/util\/abc_global.h@ which contains
+miscellaneous functions for ABC, including a counterexample datastructure
+and error handling mechanisms.
+
+-}
+
+module Data.ABC.Internal.ABCGlobal (
+    -- * Counterexamples
+      Abc_Cex_t_(..)
+    , Abc_Cex_t
+    , peekAbcCex
+    ) where
+
+#include <stdio.h>
+#include "abc_global.h"
+#include "abcbridge.h"
+
+import Control.Applicative
+import Control.Exception (assert)
+import Foreign
+import Foreign.C
+
+divUp :: Integral a => a -> a -> a
+divUp a b = let (d,r) = divMod a b
+            in if r == 0 then d else succ d
+
+-- | @chunksOf n l@ partitions l into length @n@ chunks.  The last chunk
+-- may contain fewer than @n@ elements.
+chunksOf :: Int -> [e] -> [[e]]
+chunksOf n = assert (n > 0) go
+  where go [] = []
+        go l = h : go r
+          where (h,r) = splitAt n l
+
+
+data Abc_Cex_t_ = Abc_Cex_t_
+    { iPo'Abc_Cex :: Int    -- ^ the zero-based number of PO, for which verification failed
+    , iFrame'Abc_Cex :: Int -- ^ the zero-based number of the time-frame, for which verificaiton failed
+    , nRegs'Abc_Cex  :: Int -- ^ the number of registers in the miter
+    , nPis'Abc_Cex   :: Int -- ^ the number of primary inputs in the miter
+    , nBits'Abc_Cex  :: Int -- ^ the number of words of bit data used (ezyang: where by words they actually mean bits)
+
+    -- | The cex bit data (the number of bits: @nRegs + (iFrame+1) * nPis@)
+    -- The format of the data is as such:
+    --
+    --    * First, the initial values for all registers
+    --
+    --    * Then, the @iFrame+1@ sets of inputs, which represent what we
+    --      inputted into the network at each timestep.  For a
+    --      combinational network, this means there is only 1 set.
+    , pData'regs'Abc_Cex :: [Bool]
+    , pData'inputs'Abc_Cex :: [[Bool]] -- ^ outer length: @iFrame+1@; inner length: @nPis@
+    } deriving (Read, Show, Eq)
+
+{#pointer *Abc_Cex_t -> Abc_Cex_t_ #}
+-- Note that we can't write a Storable instance because Abc_Cex_t doesn't have
+-- a fixed size.
+
+-- | Peek into the value of a Abc_Cex_t.
+peekAbcCex :: Abc_Cex_t -> IO Abc_Cex_t_
+peekAbcCex p = do
+    iPo     <- fromIntegral <$> {#get Abc_Cex_t->iPo #} p
+    iFrame  <- fromIntegral <$> {#get Abc_Cex_t->iFrame #} p
+    nRegs   <- fromIntegral <$> {#get Abc_Cex_t->nRegs #} p
+    nPis    <- fromIntegral <$> {#get Abc_Cex_t->nPis #} p
+    nBits   <- fromIntegral <$> {#get Abc_Cex_t->nBits #} p
+    -- read out the data (it's a big bit field, so we'll
+    -- convert it into a flat [Bool] before slicing and dicing);
+    -- there might be a little extra left over
+    ws <- peekArray (nBits `divUp` (sizeOf (undefined :: CUInt)))
+                    (castPtr (plusPtr p {#sizeof Abc_Cex_t#}) :: Ptr CUInt)
+                    :: IO [CUInt]
+    let size = 32 -- this is what the assume in the code!
+        bits = concatMap (\x -> map (testBit x) [0..size-1]) ws :: [Bool]
+        -- slice it up
+        (regs, flatInputs) = splitAt nRegs bits
+        inputs = chunksOf nPis ((take ((iFrame + 1) * nPis)) flatInputs)
+    return $ Abc_Cex_t_ iPo iFrame nRegs nPis nBits regs inputs
diff --git a/src/Data/ABC/Internal/AIG.chs b/src/Data/ABC/Internal/AIG.chs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC/Internal/AIG.chs
@@ -0,0 +1,140 @@
+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+{- |
+Module      : Data.ABC.Internal.AIG
+Copyright   : Galois, Inc. 2010
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : experimental
+Portability : non-portable (c2hs, language extensions)
+
+/Incomplete./ Binding of @aig\/aig\/aig.h@.  This defines the
+next-generation heavy-weight AIG representation (similar to the original
+"Data.ABC.Internal.ABC") which is used in internal versions
+(@base\/abci\/abc.c@) 8D, 8 and occasionally for 9 (during which the GIA
+is temporarily converted into an AIG for some processing.)
+
+-}
+
+module Data.ABC.Internal.AIG (
+    -- * Types
+    -- ** Enums
+      Aig_Type_t(..)
+    -- ** Empty types
+    , Aig_Man_t_
+    , Aig_Obj_t_
+    -- ** Pointer types
+    , Aig_Man_t
+    , Aig_Obj_t
+    -- * Memory management
+    , aigRegular
+    , aigNot
+    , aigNotCond
+    , aigIsComplement
+    , aigManCiNum
+    , aigManCoNum
+    , aigManObjNumMax
+    , aigManConst0
+    , aigManConst1
+    , aigManCi
+    , aigManCo
+    , aigObjId
+      -- * aigMan.c
+    , aigManStart
+    , aigManStop
+    , p_aigManStop
+      -- * aigObj.c
+    , aigObjCreateCi
+    , aigObjCreateCo
+      -- * Re-exports
+    , CInt
+    ) where
+
+#include "aig.h"
+#include "abcbridge.h"
+
+import Control.Applicative
+import Foreign
+import Foreign.C
+
+{#import Data.ABC.Internal.VecPtr #}
+
+{#enum Aig_Type_t {underscoreToCase} deriving (Show, Eq) #}
+
+data Aig_Man_t_
+data Aig_Obj_t_
+
+{#pointer *Aig_Man_t -> Aig_Man_t_ #}
+{#pointer *Aig_Obj_t -> Aig_Obj_t_ #}
+
+aigObjWordPtr :: (WordPtr -> WordPtr) -> (Aig_Obj_t -> Aig_Obj_t)
+aigObjWordPtr f = wordPtrToPtr . f . ptrToWordPtr
+
+aigRegular :: Aig_Obj_t -> Aig_Obj_t
+aigRegular = aigObjWordPtr (`clearBit` 0)
+
+aigNot :: Aig_Obj_t -> Aig_Obj_t
+aigNot = aigObjWordPtr (xor (bit 0))
+
+aigNotCond :: Aig_Obj_t -> Bool -> Aig_Obj_t
+aigNotCond o b = if b then aigNot o else o
+
+aigIsComplement :: Aig_Obj_t -> Bool
+aigIsComplement o = ptrToWordPtr o `testBit` 0
+
+typeCInt :: Aig_Type_t -> CInt
+typeCInt = fromIntegral . fromEnum
+
+{#fun AbcBridge_Aig_ManNObj as aigManNObj
+    { id `Aig_Man_t'
+    , typeCInt `Aig_Type_t'
+    } -> `CInt' id #}
+
+aigManCiNum :: Aig_Man_t -> IO CInt
+aigManCiNum = flip aigManNObj AigObjCi
+
+aigManCoNum :: Aig_Man_t -> IO CInt
+aigManCoNum = flip aigManNObj AigObjCo
+
+aigManObjNumMax :: Aig_Man_t -> IO Int
+aigManObjNumMax man =
+  vecPtrSize =<< {#get Aig_Man_t->vObjs #} man
+
+aigManConst0 :: Aig_Man_t -> IO Aig_Obj_t
+aigManConst0 m = aigNot <$> aigManConst1 m
+
+aigManConst1 :: Aig_Man_t -> IO Aig_Obj_t
+aigManConst1 = {#get Aig_Man_t->pConst1 #}
+
+{#fun AbcBridge_Aig_ManCi as aigManCi
+    { id `Aig_Man_t'
+    , id `CInt'
+    } -> `Aig_Obj_t' id #}
+{#fun AbcBridge_Aig_ManCo as aigManCo
+    { id `Aig_Man_t'
+    , id `CInt'
+    } -> `Aig_Obj_t' id #}
+
+-- Note: We use a function rather rather than just #get, because Aig_Obj_t
+-- is a bitfield, and offsets are computed incorrectly by c2hs.
+{#fun AbcBridge_Aig_ObjId as aigObjId
+    { id `Aig_Obj_t' } -> `CInt' id #}
+
+{-
+newAigManForeignPtr :: Ptr Aig_Man_t_ -> IO (Aig_Man_t)
+newAigManForeignPtr ptr | ptr == nullPtr = throwIO NullPtrError
+                        | otherwise      = newForeignPtr p_aigManStop ptr
+-}
+
+foreign import ccall unsafe "&Aig_ManStop"
+    p_aigManStop :: FunPtr (Aig_Man_t -> IO ())
+
+foreign import ccall unsafe "Aig_ManStop" aigManStop :: Aig_Man_t -> IO ()
+
+{#fun Aig_ManStart as ^ { id `CInt' } -> `Aig_Man_t' id #}
+
+{#fun Aig_ObjCreateCi as ^
+   { id `Aig_Man_t' } -> `Aig_Obj_t' id #}
+{#fun Aig_ObjCreateCo as ^
+   { id `Aig_Man_t', id `Aig_Obj_t' } -> `Aig_Obj_t' id  #}
diff --git a/src/Data/ABC/Internal/CEC.chs b/src/Data/ABC/Internal/CEC.chs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC/Internal/CEC.chs
@@ -0,0 +1,177 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE EmptyDataDecls #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+{- |
+Module      : Data.ABC.Internal.CEC
+Copyright   : Galois, Inc. 2010-2014
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : experimental
+Portability : non-portable (c2hs, language extensions)
+
+Comprehensive binding of @aig\/cec\/cec.h@ for performing combinational
+equivalence checking of scalable and-inverter graphs (GIA).
+
+-}
+
+module Data.ABC.Internal.CEC (
+    -- * Types
+    -- ** Storable types
+      Cec_ParCec_t_(..)
+    , Cec_ParSat_t_(..)
+    -- * Functions
+    -- ** cecCec.c
+    , cecManVerify
+    -- ** cecCore.c
+    , cecManSatDefaultParams
+    , cecManCecDefaultParams
+    , cecManSatSolving
+    , Cec_ManPat_t_
+    , Cec_ManPat_t
+    , cecManPatStart
+    , cecManPatStop
+    , cecManPatPatCount
+    , cecManPatPrintStats
+    , cecManSatSolve
+    ) where
+
+#include "gia.h"
+#include "cec.h"
+#include "cecInt.h"
+
+import Control.Applicative
+import Foreign
+import Foreign.C (CInt(..))
+import qualified System.IO.Unsafe as Unsafe
+
+{#import Data.ABC.Internal.GIA#}
+
+{#pointer *Cec_ParSat_t -> Cec_ParSat_t_ #}
+type Cec_ParCec_t = Ptr Cec_ParCec_t_
+
+data Cec_ManPat_t_
+{#pointer *Cec_ManPat_t -> Cec_ManPat_t_ #}
+
+data Cec_ParSat_t_ = Cec_ParSat_t_
+     { nBTLimit'Cec_ParSat      :: CInt
+     , nSatVarMax'Cec_ParSat    :: CInt
+     , nCallsRecycle'Cec_ParSat :: CInt
+     , fNonChrono'Cec_ParSat  :: Bool
+     , fPolarFlip'Cec_ParSat  :: Bool
+     , fCheckMiter'Cec_ParSat :: Bool
+     , fLearnCls'Cec_ParSat   :: Bool
+     , fVerbose'Cec_ParSat    :: Bool
+     } deriving (Show, Read, Eq)
+
+instance Storable Cec_ParSat_t_ where
+  sizeOf _ = {#sizeof Cec_ParSat_t #}
+  alignment _ = alignment (undefined :: CInt)
+  peek p = Cec_ParSat_t_
+      <$> pInt  {#get Cec_ParSat_t->nBTLimit      #}
+      <*> pInt  {#get Cec_ParSat_t->nSatVarMax    #}
+      <*> pInt  {#get Cec_ParSat_t->nCallsRecycle #}
+      <*> pBool {#get Cec_ParSat_t->fNonChrono  #}
+      <*> pBool {#get Cec_ParSat_t->fPolarFlip  #}
+      <*> pBool {#get Cec_ParSat_t->fCheckMiter #}
+      <*> pBool {#get Cec_ParSat_t->fLearnCls #}
+      <*> pBool {#get Cec_ParSat_t->fVerbose  #}
+    where pInt  :: (Cec_ParSat_t -> IO CInt) -> IO CInt
+          pInt  f = f p
+          pBool :: (Cec_ParSat_t -> IO CInt) -> IO Bool
+          pBool f = (/= 0) <$> f p
+  poke p x = do
+      pokeInt  {#set Cec_ParSat_t->nBTLimit      #} nBTLimit'Cec_ParSat
+      pokeInt  {#set Cec_ParSat_t->nSatVarMax    #} nSatVarMax'Cec_ParSat
+      pokeInt  {#set Cec_ParSat_t->nCallsRecycle #} nCallsRecycle'Cec_ParSat
+      pokeBool {#set Cec_ParSat_t->fNonChrono  #}   fNonChrono'Cec_ParSat
+      pokeBool {#set Cec_ParSat_t->fPolarFlip  #}   fPolarFlip'Cec_ParSat
+      pokeBool {#set Cec_ParSat_t->fCheckMiter #}   fCheckMiter'Cec_ParSat
+      pokeBool {#set Cec_ParSat_t->fLearnCls #}     fLearnCls'Cec_ParSat
+      pokeBool {#set Cec_ParSat_t->fVerbose  #}     fVerbose'Cec_ParSat
+    where pokeInt :: (Cec_ParSat_t -> CInt -> IO ()) -> (Cec_ParSat_t_ -> CInt) -> IO ()
+          pokeInt w f = w p (f x)
+          pokeBool :: (Cec_ParSat_t -> CInt -> IO ()) -> (Cec_ParSat_t_ -> Bool) -> IO ()
+          pokeBool w f = w p (if f x then 1 else 0)
+
+data Cec_ParCec_t_ = Cec_ParCec_t_
+    { nBTLimit'Cec_ParCec :: Int      -- ^ conflict limit at a node
+    , nTimeLimit'Cec_ParCec :: Int    -- ^ the runtime limit in seconds (added prefix @n@)
+    , fUseSmartCnf'Cec_ParCec :: Bool -- ^ use smart CNF computation
+    , fRewriting'Cec_ParCec :: Bool   -- ^ enables AIG rewriting
+    , fVeryVerbose'Cec_ParCec :: Bool -- ^ very verbose stats
+    , fVerbose'Cec_ParCec :: Bool     -- ^ verbose stats
+    , iOutFail'Cec_ParCec :: Int      -- ^ the number of failed output
+    } deriving (Show, Read, Eq)
+
+instance Storable Cec_ParCec_t_ where
+    sizeOf _ = {#sizeof Cec_ParCec_t #}
+    alignment _ = alignment (undefined :: CInt)
+    peek p = Cec_ParCec_t_
+        <$> fmap fromIntegral ({#get Cec_ParCec_t->nBTLimit #} p)
+        <*> fmap fromIntegral ({#get Cec_ParCec_t->TimeLimit #} p)
+        <*> fmap toBool ({#get Cec_ParCec_t->fUseSmartCnf #} p)
+        <*> fmap toBool ({#get Cec_ParCec_t->fRewriting #} p)
+        <*> fmap toBool ({#get Cec_ParCec_t->fVeryVerbose #} p)
+        <*> fmap toBool ({#get Cec_ParCec_t->fVerbose #} p)
+        <*> fmap fromIntegral ({#get Cec_ParCec_t->iOutFail #} p)
+    poke p x = do
+        {#set Cec_ParCec_t.nBTLimit #}      p (fromIntegral $ nBTLimit'Cec_ParCec x)
+        {#set Cec_ParCec_t.TimeLimit #}     p (fromIntegral $ nTimeLimit'Cec_ParCec x)
+        {#set Cec_ParCec_t.fUseSmartCnf #}  p (fromBool $ fUseSmartCnf'Cec_ParCec x)
+        {#set Cec_ParCec_t.fRewriting #}    p (fromBool $ fRewriting'Cec_ParCec x)
+        {#set Cec_ParCec_t.fVeryVerbose #}  p (fromBool $ fVeryVerbose'Cec_ParCec x)
+        {#set Cec_ParCec_t.fVerbose #}      p (fromBool $ fVerbose'Cec_ParCec x)
+        {#set Cec_ParCec_t.iOutFail #}      p (fromIntegral $ iOutFail'Cec_ParCec x)
+
+
+-- cecCore.c
+
+{-# NOINLINE cecManSatDefaultParams #-}
+cecManSatDefaultParams :: Cec_ParSat_t_
+cecManSatDefaultParams = Unsafe.unsafePerformIO $ do
+  alloca $ \p -> do
+    cecManSatSetDefaultParams p
+    peek p
+
+foreign import ccall unsafe "Cec_ManSatSetDefaultParams"
+  cecManSatSetDefaultParams :: Cec_ParSat_t -> IO ()
+
+{-# NOINLINE cecManCecDefaultParams #-}
+cecManCecDefaultParams :: Cec_ParCec_t_
+cecManCecDefaultParams = Unsafe.unsafePerformIO $ do
+  alloca $ \p -> do
+    cecManCecSetDefaultParams p
+    peek p
+
+foreign import ccall unsafe "Cec_ManCecSetDefaultParams"
+  cecManCecSetDefaultParams :: Cec_ParCec_t -> IO ()
+
+{#fun Cec_ManPatStart as ^ { } -> `Cec_ManPat_t' #}
+
+{#fun Cec_ManPatStop as ^ { `Cec_ManPat_t' } -> `()' #}
+
+{#fun Cec_ManPatPrintStats as ^ { `Cec_ManPat_t' } -> `()' #}
+
+cecManPatPatCount :: Cec_ManPat_t -> IO CInt
+cecManPatPatCount = {#get Cec_ManPat_t->nPats#}
+
+{#fun Cec_ManSatSolve as ^
+    { `Cec_ManPat_t' -- pPat
+    , id `Gia_Man_t' -- pAig
+    , `Cec_ParSat_t' -- pPars
+    } -> `()' #}
+
+
+cecManSatSolving :: Gia_Man_t -> Cec_ParSat_t_ -> IO Gia_Man_t
+cecManSatSolving aig pars = do
+  with pars $ \p -> cecManSatSolving' aig p
+
+foreign import ccall unsafe "Cec_ManSatSolving"
+  cecManSatSolving' :: Gia_Man_t -> Cec_ParSat_t -> IO Gia_Man_t
+
+cecManVerify :: Gia_Man_t -> Cec_ParCec_t_ -> IO CInt
+cecManVerify m pars = with pars $ \p -> cecManVerify' m p
+
+foreign import ccall unsafe "Cec_ManVerify"
+  cecManVerify' :: Gia_Man_t -> Cec_ParCec_t -> IO CInt
diff --git a/src/Data/ABC/Internal/CNF.chs b/src/Data/ABC/Internal/CNF.chs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC/Internal/CNF.chs
@@ -0,0 +1,87 @@
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+{- |
+Module      : Data.ABC.Internal.CNF
+Copyright   : Galois, Inc. 2010-2014
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : experimental
+Portability : non-portable (c2hs, language extensions)
+-}
+module Data.ABC.Internal.CNF
+  ( Cnf_Dat_t
+  , cnfVarNums
+  , withCnfDerive
+  , cnfDataWriteIntoFile
+  , Cnf_Man_t
+  , Cnf_Man_t_
+  , cnfManStart
+  , cnfDeriveWithMan
+  , cnfDataFree
+  , cnfDataWriteIntoFileWithHeader
+  ) where
+
+import Control.Exception (bracket)
+import Data.ABC.Internal.AIG
+import Foreign
+import Foreign.C
+
+#include "cnfheader.h"
+
+data Cnf_Man_t_
+
+{#pointer *Aig_Man_t -> Aig_Man_t_ nocode #}
+
+{#pointer *Cnf_Man_t foreign -> Cnf_Man_t_ #}
+
+foreign import ccall unsafe "&Cnf_ManStop"
+    p_cnfManStop :: FunPtr (Ptr Cnf_Man_t_ -> IO ())
+
+newCnfMan :: Ptr Cnf_Man_t_ -> IO Cnf_Man_t
+newCnfMan = newForeignPtr p_cnfManStop
+
+-- | Create a new CNF manager.
+{#fun Cnf_ManStart as ^
+  {} -> `Cnf_Man_t' newCnfMan* #}
+
+data Cnf_Dat_t_
+
+{#pointer *Cnf_Dat_t -> Cnf_Dat_t_ #}
+
+cnfVarNums :: Cnf_Dat_t -> IO (Ptr CInt)
+cnfVarNums = {#get Cnf_Dat_t->pVarNums #}
+
+{#fun Cnf_Derive as ^
+      { id `Aig_Man_t'
+      , id `CInt'
+      }
+      -> `Cnf_Dat_t' id #}
+
+-- | Use results on cnfDerive in a comptuation, then free them.
+withCnfDerive :: Aig_Man_t -> CInt -> (Cnf_Dat_t -> IO a) -> IO a
+withCnfDerive mgr outputCount h =
+  bracket (cnfDerive mgr outputCount) cnfDataFree h
+
+{#fun Cnf_DeriveWithMan as ^ -- output
+    { withForeignPtr* `Cnf_Man_t'
+    , id `Aig_Man_t'
+    , id `CInt'
+    } -> `Cnf_Dat_t' id #}
+
+{#fun Cnf_DataWriteIntoFile as ^
+    { id `Cnf_Dat_t'
+    , `String'
+    , `Int'
+    , id `Ptr ()'
+    , id `Ptr ()'
+    } -> `()' #}
+
+{#fun Cnf_DataWriteIntoFileWithHeader as ^
+    { id `Cnf_Dat_t'
+    , `String' -- Filename
+    , `String' -- Header
+    , `Int'
+    } -> `()' #}
+
+{#fun Cnf_DataFree as ^
+    { id `Cnf_Dat_t'
+    } -> `()' #}
diff --git a/src/Data/ABC/Internal/FRAIG.chs b/src/Data/ABC/Internal/FRAIG.chs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC/Internal/FRAIG.chs
@@ -0,0 +1,125 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE EmptyDataDecls #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+{- |
+Module      : Data.ABC.Internal.FRAIG
+Copyright   : Galois, Inc. 2010-2014
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : experimental
+Portability : non-portable (c2hs, language extensions)
+
+*Incomplete.* Binding of @sat\/fraig\/fraig.h@ for configuring the
+process of generating functionally reduced AIGs.  Fraiging is the
+special sauce that makes ABC outperform many vanilla SAT solvers.
+-}
+
+module Data.ABC.Internal.FRAIG
+    ( Prove_Params_t_(..)
+    , proveParamsDefault
+    ) where
+
+import Control.Applicative
+import Control.Monad
+import Foreign
+import Foreign.C
+import qualified System.IO.Unsafe as Unsafe
+
+#include "abc.h"
+#include "fraig.h"
+
+
+{#pointer *Prove_Params_t -> Prove_Params_t_ #}
+
+data Prove_Params_t_ = Prove_Params_t_
+    {
+    -- general parameters
+      fUseFraiging'Prove_Params :: Bool          -- ^ enables fraiging
+    , fUseRewriting'Prove_Params :: Bool         -- ^ enables rewriting
+    , fUseBdds'Prove_Params :: Bool              -- ^ enables BDD construction when other methods fail
+    , fVerbose'Prove_Params :: Bool              -- ^ prints verbose stats
+
+    -- iterations
+    , nItersMax'Prove_Params :: Int              -- ^ the number of iterations
+
+    -- mitering
+    , nMiteringLimitStart'Prove_Params :: Int    -- ^ starting mitering limit
+    , nMiteringLimitMulti'Prove_Params :: Float  -- ^ multiplicative coefficient to increase the limit in each iteration
+
+    -- rewriting
+    , nRewritingLimitStart'Prove_Params :: Int   -- ^ the number of rewriting iterations
+    , nRewritingLimitMulti'Prove_Params :: Float -- ^ multiplicative coefficient to increase the limit in each iteration
+
+    -- fraiging
+    , nFraigingLimitStart'Prove_Params :: Int    -- ^ starting backtrack(conflict) limit
+    , nFraigingLimitMulti'Prove_Params :: Float  -- ^ multiplicative coefficient to increase the limit in each iteration
+
+    -- last-gasp BDD construction
+    , nBddSizeLimit'Prove_Params :: Int          -- ^ the number of BDD nodes when construction is aborted
+    , fBddReorder'Prove_Params :: Bool           -- ^ enables dynamic BDD variable reordering
+
+    -- last-gasp mitering
+    , nMiteringLimitLast'Prove_Params :: Int     -- ^ final mitering limit
+
+    -- global SAT solver limits
+    , nTotalBacktrackLimit'Prove_Params :: Int64 -- ^ global limit on the number of backtracks
+    , nTotalInspectLimit'Prove_Params :: Int64   -- ^ global limit on the number of clause inspects
+
+    -- global resources applied
+    , nTotalBacktracksMade'Prove_Params :: Int64 -- ^ the total number of backtracks made
+    , nTotalInspectsMade'Prove_Params :: Int64   -- ^ the total number of inspects made
+    } deriving (Read, Show, Eq)
+
+instance Storable Prove_Params_t_ where
+    sizeOf _ = {#sizeof Prove_Params_t #}
+    alignment _ = 4 -- {#alignment Prove_Params_t #}
+    peek p = Prove_Params_t_
+        <$> liftM toBool ({#get Prove_Params_t->fUseFraiging #} p)
+        <*> liftM toBool ({#get Prove_Params_t->fUseRewriting #} p)
+        <*> liftM toBool ({#get Prove_Params_t->fUseBdds #} p)
+        <*> liftM toBool ({#get Prove_Params_t->fVerbose #} p)
+        <*> liftM fromIntegral ({#get Prove_Params_t->nItersMax #} p)
+        <*> liftM fromIntegral ({#get Prove_Params_t->nMiteringLimitStart #} p)
+        <*> liftM realToFrac ({#get Prove_Params_t->nMiteringLimitMulti #} p)
+        <*> liftM fromIntegral ({#get Prove_Params_t->nRewritingLimitStart #} p)
+        <*> liftM realToFrac ({#get Prove_Params_t->nRewritingLimitMulti #} p)
+        <*> liftM fromIntegral ({#get Prove_Params_t->nFraigingLimitStart #} p)
+        <*> liftM realToFrac ({#get Prove_Params_t->nFraigingLimitMulti #} p)
+        <*> liftM fromIntegral ({#get Prove_Params_t->nBddSizeLimit #} p)
+        <*> liftM toBool ({#get Prove_Params_t->fBddReorder #} p)
+        <*> liftM fromIntegral ({#get Prove_Params_t->nMiteringLimitLast #} p)
+        <*> liftM fromIntegral ({#get Prove_Params_t->nTotalBacktrackLimit #} p)
+        <*> liftM fromIntegral ({#get Prove_Params_t->nTotalInspectLimit #} p)
+        <*> liftM fromIntegral ({#get Prove_Params_t->nTotalBacktracksMade #} p)
+        <*> liftM fromIntegral ({#get Prove_Params_t->nTotalInspectsMade #} p)
+    poke p x = do
+        {#set Prove_Params_t.fUseFraiging #}  p (fromBool $ fUseFraiging'Prove_Params x)
+        {#set Prove_Params_t.fUseRewriting #}  p (fromBool $ fUseRewriting'Prove_Params x)
+        {#set Prove_Params_t.fUseBdds #}  p (fromBool $ fUseBdds'Prove_Params x)
+        {#set Prove_Params_t.fVerbose #}  p (fromBool $ fVerbose'Prove_Params x)
+        {#set Prove_Params_t.nItersMax #}  p (fromIntegral $ nItersMax'Prove_Params x)
+        {#set Prove_Params_t.nMiteringLimitStart #}  p (fromIntegral $ nMiteringLimitStart'Prove_Params x)
+        {#set Prove_Params_t.nMiteringLimitMulti #}  p (realToFrac $ nMiteringLimitMulti'Prove_Params x)
+        {#set Prove_Params_t.nRewritingLimitStart #}  p (fromIntegral $ nRewritingLimitStart'Prove_Params x)
+        {#set Prove_Params_t.nRewritingLimitMulti #}  p (realToFrac $ nRewritingLimitMulti'Prove_Params x)
+        {#set Prove_Params_t.nFraigingLimitStart #}  p (fromIntegral $ nFraigingLimitStart'Prove_Params x)
+        {#set Prove_Params_t.nFraigingLimitMulti #}  p (realToFrac $ nFraigingLimitMulti'Prove_Params x)
+        {#set Prove_Params_t.nBddSizeLimit #}  p (fromIntegral $ nBddSizeLimit'Prove_Params x)
+        {#set Prove_Params_t.fBddReorder #}  p (fromBool $ fBddReorder'Prove_Params x)
+        {#set Prove_Params_t.nMiteringLimitLast #}  p (fromIntegral $ nMiteringLimitLast'Prove_Params x)
+        {#set Prove_Params_t.nTotalBacktrackLimit #}  p (fromIntegral $ nTotalBacktrackLimit'Prove_Params x)
+        {#set Prove_Params_t.nTotalInspectLimit #}  p (fromIntegral $ nTotalInspectLimit'Prove_Params x)
+        {#set Prove_Params_t.nTotalBacktracksMade #}  p (fromIntegral $ nTotalBacktracksMade'Prove_Params x)
+        {#set Prove_Params_t.nTotalInspectsMade #}  p (fromIntegral $ nTotalInspectsMade'Prove_Params x)
+
+-- fraigMan.c
+
+{#fun Prove_ParamsSetDefault as ^
+    { alloca- `Prove_Params_t_' peek*
+    } -> `()' #}
+
+
+-- a more appropriate name in a convenient form
+proveParamsDefault :: Prove_Params_t_
+proveParamsDefault = Unsafe.unsafePerformIO proveParamsSetDefault
diff --git a/src/Data/ABC/Internal/Field.hs b/src/Data/ABC/Internal/Field.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC/Internal/Field.hs
@@ -0,0 +1,38 @@
+{- |
+Module      : Data.ABC.GIA
+Copyright   : Galois, Inc. 2010-2014
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : experimental
+Portability : portable
+-}
+module Data.ABC.Internal.Field
+  ( Field(..)
+  , fieldFromOffset
+  , isoFieldTarget
+  , Iso
+  , iso
+  ) where
+
+import Foreign
+
+data Field a b = Field { readAt :: a -> IO b
+                       , writeAt :: a -> b -> IO ()
+                       }
+
+fieldFromOffset :: Storable b => Int -> Field (Ptr a) b
+fieldFromOffset o = Field (`peekByteOff` o) (`pokeByteOff` o)
+
+isoFieldTarget :: Field a b -> Iso b c -> Field a c
+isoFieldTarget (Field r w) (Iso f t) =
+  Field { readAt = fmap f . r
+        , writeAt = \b v -> w b (t v)
+        }
+
+
+-- | An isomorphism view.
+data Iso a b = Iso (a -> b) (b -> a)
+
+-- | Create an isomorphism
+iso :: (a -> b) -> (b -> a) -> Iso a b
+iso = Iso
diff --git a/src/Data/ABC/Internal/GIA.chs b/src/Data/ABC/Internal/GIA.chs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC/Internal/GIA.chs
@@ -0,0 +1,497 @@
+{-# LANGUAGE EmptyDataDecls #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+{- |
+Module      : Data.ABC.Internal.GIA
+Copyright   : Galois, Inc. 2010-2014
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : experimental
+Portability : non-portable (c2hs, language extensions)
+
+Bindings to @aig\/gia\/gia.h@ for manipulating and
+running algorithms on scalable and-inverter graphs (GIA), a
+representation that is optimized for memory-efficiency.  These
+functions power the next-generation of ABC algorithms that have
+not been officially released yet, and can be identified by the
+prefix of an ampersand, as in @&cec@, in the interactive ABC
+interface.
+
+-}
+
+module Data.ABC.Internal.GIA (
+      Gia_Man_t
+    , Gia_Man_t_
+    , giaManNObjs
+    , giaManFanData
+    , Gia_Obj_t
+    , getGiaObjValue
+    , setGiaObjValue
+    , GiaVar(..)
+    , GiaLit(..)
+    , giaManConst0Lit
+    , giaManConst1Lit
+    , giaLitIsCompl
+    , giaLitVar
+    , giaVarLit
+    , giaLitNotCond
+    -- * Memory management
+    -- * Base
+    -- ** Network getters
+    , giaManCexComb
+    , giaManConst0
+    , giaManCis
+    , giaManCos
+    , giaManCiNum
+    , giaManCoNum
+    , giaManPiNum
+    , giaManPoNum
+    , giaManAndNum
+    , giaManRegNum
+
+    , giaManCiVar
+    , giaManCoVar
+    , giaManCi
+    , giaManCo
+    , giaManObj
+    , gia_none
+    , giaObjIsCo
+    , giaObjDiff0
+    , giaObjDiff1
+    , giaObjFaninC0
+    , giaObjFaninC1
+    , giaObjMark0
+    , giaObjMark1
+    , giaObjChild0
+    , giaObjChild1
+    , giaObjFaninId0
+    , giaObjFaninId1
+    , giaObjIsTerm
+    , giaObjIsAndOrConst0
+    , giaObjId
+    , giaManObjNum
+    -- ** Handling literals
+    , giaLitNot
+    , giaRegular
+    , giaIsComplement
+    , giaObjToLit
+    , giaObjFromLit
+    -- ** Iterators
+    , giaManForEachObj1_
+    , giaManForEachCo
+    -- ** Construction
+    , giaManAppendCi
+    , giaManAppendCo
+    , giaManAppendAnd
+    -- * Functions
+    -- ** giaAiger.c
+    , giaAigerRead
+    , giaAigerWrite
+    -- ** giaDup.c
+    , giaManMiter
+    , giaDupLit
+    -- ** giaHash.c
+    , giaManHashAlloc
+    , giaManHashStart
+    , giaManHashStop
+    , giaManHashAnd
+    , giaManHashXor
+    , giaManHashMux
+     -- ** giaMan.c
+    , giaManStart
+    , giaManStop
+    , p_giaManStop
+    , giaManCleanup
+    , giaManFillValue
+    ) where
+
+import Control.Applicative
+import Control.Exception
+import Control.Monad
+import Foreign hiding (void)
+import Foreign.C
+
+{#import Data.ABC.Internal.ABCGlobal #}
+{#import Data.ABC.Internal.VecInt #}
+
+import Data.ABC.Internal.Field
+
+#include "abcbridge.h"
+#include "gia.h"
+
+-- Iterators
+
+enumRange :: (Eq a, Enum a) => a -> a -> [a]
+enumRange i n | i == n = []
+              | otherwise = i : enumRange (succ i) n
+
+lazyAnd :: Monad m => m Bool -> m Bool -> m Bool
+lazyAnd mx my = do
+  x <- mx
+  if x then my else return False
+
+asWordPtr :: (WordPtr -> WordPtr) -> Ptr a -> Ptr b
+asWordPtr f = wordPtrToPtr . f . ptrToWordPtr
+
+------------------------------------------------------------------------
+-- Gia_Obj_t
+
+data Gia_Obj_t_
+
+-- | A pointer to a GIA object.
+-- GIA objects are pointers to structs in ABC, and represent literals
+-- in the AIG.  The low-order bit of the pointer is set to 1 if the
+-- literal has been complemented, and so care must be taken to only
+-- dereference positive pointers.  The object is also a bitfield, so
+-- care must be taken when accessing fields.
+--
+-- Pointers to GIA objects may be invalidated when adding a new
+-- object.
+{#pointer *Gia_Obj_t -> Gia_Obj_t_ #}
+
+sizeOfGiaObj :: Int
+sizeOfGiaObj = {#sizeof Gia_Obj_t #}
+
+-- | Remove negation.
+giaRegular :: Gia_Obj_t -> Gia_Obj_t
+giaRegular = asWordPtr (.&. complement 0x1)
+
+-- | Returns iDiff0 field of object
+-- Note: iDiff0 is a bitfield, so this may be more likely to break on
+-- unexpected compilers.
+giaObjDiff0 :: Gia_Obj_t -> IO CUInt
+giaObjDiff0 = {#get Gia_Obj_t->iDiff0 #}
+
+-- | Get the complement attribute of first fanin
+giaObjFaninC0 :: Gia_Obj_t -> IO Bool
+giaObjFaninC0 o = toBool `fmap` {#get Gia_Obj_t->fCompl0 #} o
+
+-- | Get first user defined mark
+giaObjMark0 :: Gia_Obj_t -> IO Bool
+giaObjMark0 o = toBool `fmap` {#get Gia_Obj_t->fMark0 #} o
+
+giaObjIsTerm :: Gia_Obj_t -> IO Bool
+giaObjIsTerm o = toBool `fmap` {#get Gia_Obj_t->fTerm #} o
+
+-- | Returns iDiff1 field of object
+-- Note: iDiff1 is a bitfield, so this may be more likely to break on
+-- unexpected compilers.
+giaObjDiff1 :: Gia_Obj_t -> IO CUInt
+giaObjDiff1 = {#get Gia_Obj_t->iDiff1 #}
+
+giaObjFaninC1 :: Gia_Obj_t -> IO Bool
+giaObjFaninC1 o = toBool `fmap` {#get Gia_Obj_t->fCompl1 #} o
+
+-- | Get second user defined mark
+giaObjMark1 :: Gia_Obj_t -> IO Bool
+giaObjMark1 o = toBool `fmap` {#get Gia_Obj_t->fMark1 #} o
+
+getGiaObjValue :: Gia_Obj_t -> IO CUInt
+getGiaObjValue = {#get Gia_Obj_t->Value #}
+
+setGiaObjValue :: Gia_Obj_t -> CUInt -> IO ()
+setGiaObjValue = {#set Gia_Obj_t->Value #}
+
+-- GIA_NONE
+gia_none :: CUInt
+gia_none = 0x1FFFFFFF
+
+giaObjIsAndOrConst0 :: Gia_Obj_t -> IO Bool
+giaObjIsAndOrConst0 o = not <$> giaObjIsTerm o
+
+giaObjDiff0Assigned :: Gia_Obj_t -> IO Bool
+giaObjDiff0Assigned o = (/= gia_none) <$> giaObjDiff0 o
+
+giaIsComplement :: Gia_Obj_t -> Bool
+giaIsComplement o = ptrToWordPtr o `testBit` 0
+
+giaNot :: Gia_Obj_t -> Gia_Obj_t
+giaNot = asWordPtr (xor 1)
+
+giaNotCond :: Gia_Obj_t -> Bool -> Gia_Obj_t
+giaNotCond o b = if b then giaNot o else o
+
+-- | Returns true if this is a combinational output (latch or primary output).
+giaObjIsCo :: Gia_Obj_t -> IO Bool
+giaObjIsCo o = lazyAnd (giaObjIsTerm o) (giaObjDiff0Assigned o)
+
+incObjPtr :: Gia_Obj_t -> CInt -> Gia_Obj_t
+incObjPtr o i = o `plusPtr` (sizeOfGiaObj * fromIntegral i)
+
+decObjPtr :: Gia_Obj_t -> CUInt -> Gia_Obj_t
+decObjPtr o i = incObjPtr o (negate (fromIntegral i))
+
+objDiff :: Gia_Obj_t -> Gia_Obj_t -> Int
+objDiff p q = (p `minusPtr` q) `div` sizeOfGiaObj
+
+-- Gia_ObjFanin0
+giaObjFanin0 :: Gia_Obj_t -> IO Gia_Obj_t
+giaObjFanin0 o = decObjPtr o <$> giaObjDiff0 o
+
+-- Gia_ObjFanin1
+giaObjFanin1 :: Gia_Obj_t -> IO Gia_Obj_t
+giaObjFanin1 o = decObjPtr o <$> giaObjDiff1 o
+
+-- Gia_ObjChild0
+giaObjChild0 :: Gia_Obj_t -> IO Gia_Obj_t
+giaObjChild0 o = giaNotCond <$> giaObjFanin0 o <*> giaObjFaninC0 o
+
+-- Gia_ObjChild1
+giaObjChild1 :: Gia_Obj_t -> IO Gia_Obj_t
+giaObjChild1 o = giaNotCond <$> giaObjFanin1 o <*> giaObjFaninC1 o
+
+-- Gia_ObjFaninId0
+giaObjFaninId0 :: Gia_Obj_t -> GiaVar -> IO GiaVar
+giaObjFaninId0 o (GiaVar v) = (\d -> GiaVar (v - fromIntegral d)) <$> giaObjDiff0 o
+
+-- Gia_ObjFaninId1
+giaObjFaninId1 :: Gia_Obj_t -> GiaVar -> IO GiaVar
+giaObjFaninId1 o (GiaVar v) = (\d -> GiaVar (v - fromIntegral d)) <$> giaObjDiff1 o
+
+------------------------------------------------------------------------
+-- GiaVar and GiaLit
+
+-- | Also known as the node's id.  No complement info.
+newtype GiaVar = GiaVar { unGiaVar :: CInt } deriving (Eq, Ord, Storable)
+
+-- | Literals store complement information.
+newtype GiaLit = GiaLit { unGiaLit :: CInt } deriving (Eq, Ord, Storable)
+
+giaManConst0Lit :: GiaLit
+giaManConst0Lit = GiaLit 0
+
+giaManConst1Lit :: GiaLit
+giaManConst1Lit = GiaLit 1
+
+giaLitIsCompl :: GiaLit -> Bool
+giaLitIsCompl l = unGiaLit l `testBit` 0
+
+giaLitVar :: GiaLit -> GiaVar
+giaLitVar (GiaLit l) = GiaVar (l `shiftR` 1)
+
+-- | Returns positive literal associated to var.
+giaVarLit :: GiaVar -> GiaLit
+giaVarLit (GiaVar v) = GiaLit (v `shiftL` 1)
+
+giaLitNot :: GiaLit -> GiaLit
+giaLitNot = GiaLit . xor 1 . unGiaLit
+
+giaLitNotCond :: GiaLit -> Bool -> GiaLit
+giaLitNotCond (GiaLit l) b = GiaLit (l `xor` (if b then 1 else 0))
+
+------------------------------------------------------------------------
+-- Gia_Man_t
+
+data Gia_Man_t_
+{#pointer *Gia_Man_t -> Gia_Man_t_ #}
+
+-- member access
+
+-- this structures are memory managed by Gia_Man_.
+giaManCexComb :: Gia_Man_t -> IO Abc_Cex_t
+giaManCexComb = {#get Gia_Man_t->pCexComb #}
+
+
+giaManNObjs :: Field Gia_Man_t CInt
+giaManNObjs = fieldFromOffset {#offsetof Gia_Man_t->nObjs #}
+
+giaManObjs :: Field Gia_Man_t Gia_Obj_t
+giaManObjs = fieldFromOffset {#offsetof Gia_Man_t->pObjs #}
+
+giaManConst0 :: Gia_Man_t -> IO Gia_Obj_t
+giaManConst0 = readAt giaManObjs
+
+giaManCis :: Gia_Man_t -> IO Vec_Int_t
+giaManCis = {#get Gia_Man_t->vCis #}
+
+giaManCos :: Gia_Man_t -> IO Vec_Int_t
+giaManCos = {#get Gia_Man_t->vCos #}
+
+giaManFanData :: Gia_Man_t -> IO (Ptr CInt)
+giaManFanData = {#get Gia_Man_t->pFanData#}
+
+giaManObjNum :: Gia_Man_t -> IO CInt
+giaManObjNum = readAt giaManNObjs
+
+giaManCiNum :: Gia_Man_t -> IO CInt
+giaManCiNum = vecIntSize <=< giaManCis
+
+giaManCoNum :: Gia_Man_t -> IO CInt
+giaManCoNum = vecIntSize <=< giaManCos
+
+giaManRegNum :: Gia_Man_t -> IO CInt
+giaManRegNum = {#get Gia_Man_t->nRegs #}
+
+giaManPiNum :: Gia_Man_t -> IO CInt
+giaManPiNum m = (-) <$> giaManCiNum m <*> giaManRegNum m
+
+giaManPoNum :: Gia_Man_t -> IO CInt
+giaManPoNum m = (-) <$> giaManCoNum m <*> giaManRegNum m
+
+giaManAndNum :: Gia_Man_t -> IO CInt
+giaManAndNum m = fn <$> giaManObjNum m <*> giaManCiNum m <*> giaManCoNum m
+  where fn t i o = t - i - o - 1
+
+-- XXX refactor
+giaManForEachObj1_ :: Gia_Man_t -> (Gia_Obj_t -> GiaVar -> IO b) -> IO ()
+giaManForEachObj1_ fp action = do
+  nMax <- giaManObjNum fp
+  forM_ (enumRange 1 nMax) $ \i -> do
+    let var = GiaVar (fromIntegral i)
+    pObj <- giaManObj fp var
+    void $ action pObj var
+
+giaManForEachCo :: Gia_Man_t -> (Gia_Obj_t -> Int -> IO b) -> IO [b]
+giaManForEachCo fp action = do
+  nMax <- giaManCoNum fp
+  forM (enumRange 0 nMax) $ \i -> do
+    pObj <- giaManCo fp i
+    action pObj (fromIntegral i)
+
+foreign import ccall unsafe "AbcBridge_Gia_ManAppendCi"
+  giaManAppendCi_ :: Gia_Man_t -> IO CInt
+
+giaManAppendCi :: Gia_Man_t -> IO GiaLit
+giaManAppendCi m = GiaLit <$> giaManAppendCi_ m
+
+foreign import ccall unsafe "AbcBridge_Gia_ManAppendAnd"
+  giaManAppendAnd_ :: Gia_Man_t -> CInt -> CInt -> IO CInt
+
+-- | This directly appends the literal to the GIA bypassing
+-- any hash-consing.
+giaManAppendAnd :: Gia_Man_t -> GiaLit -> GiaLit -> IO GiaLit
+giaManAppendAnd m (GiaLit x) (GiaLit y) =
+  GiaLit <$> giaManAppendAnd_ m x y
+
+foreign import ccall unsafe "AbcBridge_Gia_ManAppendCo"
+  giaManAppendCo_ :: Gia_Man_t -> CInt -> IO CInt
+
+giaManAppendCo :: Gia_Man_t -> GiaLit -> IO GiaLit
+giaManAppendCo m (GiaLit l) = GiaLit <$> giaManAppendCo_ m l
+
+-- | Return object associated with gia var.
+giaManObj :: Gia_Man_t -> GiaVar -> IO Gia_Obj_t
+giaManObj m (GiaVar v) = do
+  cnt <- giaManCiNum m
+  assert (0 <= v && v < cnt) $ do
+    (`incObjPtr` v) <$> giaManConst0 m
+
+-- | Get var index of combinational input at given index.
+giaManCiVar :: Gia_Man_t -> CInt -> IO GiaVar
+giaManCiVar m i = do
+  v <- giaManCis m
+  GiaVar <$> vecIntEntry v i
+
+-- | Get combinational input at given index.
+giaManCi :: Gia_Man_t -> CInt -> IO Gia_Obj_t
+giaManCi m i = giaManObj m =<< giaManCiVar m i
+
+-- | Get combinational output at given index.
+giaManCoVar :: Gia_Man_t -> CInt -> IO GiaVar
+giaManCoVar m i = do
+  v <- giaManCos m
+  GiaVar <$> vecIntEntry v i
+
+-- | Get combinational output at given index.
+giaManCo :: Gia_Man_t -> CInt -> IO Gia_Obj_t
+giaManCo m i = giaManObj m =<< giaManCoVar m i
+
+-- | Returns the variable index associated with the object.
+giaObjId :: Gia_Man_t -> Gia_Obj_t -> IO GiaVar
+giaObjId p pObj = do
+  objs <- giaManConst0 p
+  nObjs <- readAt giaManNObjs p
+  assert (objs <= pObj && pObj < objs `incObjPtr` nObjs) $ do
+    return $ GiaVar $ fromIntegral $ pObj `objDiff` objs
+
+{#fun AbcBridge_Gia_ObjToLit as giaObjToLit
+    { id `Gia_Man_t'
+    , id `Gia_Obj_t'
+    } -> `GiaLit' GiaLit #}
+{#fun AbcBridge_Gia_ObjFromLit as giaObjFromLit
+    { id `Gia_Man_t'
+    , unGiaLit `GiaLit'
+    } -> `Gia_Obj_t' id #}
+
+-- giaAiger.c
+{#fun Gia_AigerRead as ^
+    { `String' -- pFileName
+    , `Bool' -- fSkipStrash
+    , `Bool' -- fCheck (doesn't do anything)
+    } -> `Gia_Man_t' id #}
+
+
+
+{#fun Gia_AigerWrite as giaAigerWrite
+    { id `Gia_Man_t'
+    , `String' -- pFileName
+    , `Bool' -- fWriteSymbols
+    , `Bool' -- fCompact
+    } -> `()' #}
+
+{#fun Gia_ManMiter as giaManMiter
+    { id `Gia_Man_t' -- pAig0cd
+    , id `Gia_Man_t' -- pAig1
+    , `Int'  -- nInsDup
+    , `Bool' -- fDualOut
+    , `Bool' -- fSeq
+    , `Bool' -- fImplic
+    , `Bool' -- fVerbose
+    } -> `Gia_Man_t' id #}
+
+-- | @giaManDupDfsLazyLit pNew p l@ copies a lit @l@ in @p@ to @pNew@
+-- and returns the lit in @pNew@.
+giaDupLit :: Gia_Man_t -> Gia_Man_t -> GiaLit -> IO GiaLit
+giaDupLit pNew p (GiaLit l) = GiaLit <$> giaDupLit' pNew p l
+
+foreign import ccall unsafe "AbcBridge_Gia_DupLit" giaDupLit'
+  :: Gia_Man_t -> Gia_Man_t -> CInt -> IO CInt
+
+-- giaHash.c
+foreign import ccall unsafe "Gia_ManHashAlloc" giaManHashAlloc
+  :: Gia_Man_t -> IO ()
+
+foreign import ccall unsafe "Gia_ManHashStart" giaManHashStart
+  :: Gia_Man_t -> IO ()
+
+foreign import ccall unsafe "Gia_ManHashStop" giaManHashStop
+  :: Gia_Man_t -> IO ()
+
+{#fun Gia_ManHashAnd as ^
+    { id `Gia_Man_t' -- p
+    , unGiaLit `GiaLit' -- iLit0
+    , unGiaLit `GiaLit' -- iLit1
+    } -> `GiaLit' GiaLit #}
+{#fun Gia_ManHashXor as ^
+    { id `Gia_Man_t' -- p
+    , unGiaLit `GiaLit' -- iLit0
+    , unGiaLit `GiaLit' -- iLit1
+    } -> `GiaLit' GiaLit #}
+{#fun Gia_ManHashMux as ^
+    { id `Gia_Man_t' -- p
+    , unGiaLit `GiaLit' -- iCtrl
+    , unGiaLit `GiaLit' -- iData1
+    , unGiaLit `GiaLit' -- iData0
+    } -> `GiaLit' GiaLit #}
+
+-- giaMan.c
+foreign import ccall unsafe "Gia_ManStop"
+    giaManStop :: Gia_Man_t -> IO ()
+
+foreign import ccall unsafe "gia.h &Gia_ManStop"
+    p_giaManStop :: FunPtr (Gia_Man_t -> IO ())
+
+
+{#fun Gia_ManStart as ^ { id `CInt' } -> `Gia_Man_t' id #}
+
+{#fun Gia_ManCleanup as ^
+    { id `Gia_Man_t' -- p
+    } -> `Gia_Man_t' id #}
+
+{#fun Gia_ManFillValue as ^
+    { id `Gia_Man_t' -- p
+    } -> `()' #}
diff --git a/src/Data/ABC/Internal/GiaAig.chs b/src/Data/ABC/Internal/GiaAig.chs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC/Internal/GiaAig.chs
@@ -0,0 +1,52 @@
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+{- |
+Module      : Data.ABC.Internal.GiaAig
+Copyright   : Galois, Inc. 2010
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : experimental
+Portability : non-portable (c2hs, language extensions)
+
+Comprehensive binding of @aig\/gia\/giaAig.h@ for
+converting between AIGs (new-style, not ABC) and GIAs.
+
+-}
+
+module Data.ABC.Internal.GiaAig (
+      Gia_AigMap_t
+    , withGiaAigMap
+    , aigDupGiaLit
+    , giaManToAig
+    ) where
+
+import Control.Exception (bracket)
+import Foreign
+import Foreign.C
+
+{#import Data.ABC.Internal.GIA #}
+{#import Data.ABC.Internal.AIG #}
+
+#include "giaAig.h"
+
+{#fun Gia_ManToAig as ^
+    { `Gia_Man_t'
+    , id `CInt'
+    } -> `Aig_Man_t' #}
+
+type Gia_AigMap_t = Ptr Aig_Obj_t
+
+-- | Create a new map for storing all nodes in GIA
+newGiaAigMap :: Gia_Man_t -> IO Gia_AigMap_t
+newGiaAigMap m = do
+  n <- giaManObjNum m
+  newArray (replicate (fromIntegral n) nullPtr)
+
+withGiaAigMap :: Gia_Man_t -> (Gia_AigMap_t -> IO a) -> IO a
+withGiaAigMap m = bracket (newGiaAigMap m) free
+
+aigDupGiaLit :: Aig_Man_t -> Gia_AigMap_t -> Gia_Man_t -> GiaLit -> IO Aig_Obj_t
+aigDupGiaLit aig m gia l = aigDupGiaLit' aig m gia (unGiaLit l)
+
+foreign import ccall unsafe "AbcBridge_Aig_DupGiaLit"
+  aigDupGiaLit' :: Ptr Aig_Man_t_ -> Gia_AigMap_t -> Gia_Man_t -> CInt -> IO Aig_Obj_t
diff --git a/src/Data/ABC/Internal/IO.chs b/src/Data/ABC/Internal/IO.chs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC/Internal/IO.chs
@@ -0,0 +1,41 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE EmptyDataDecls #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+{- |
+Module      : Data.ABC.Internal.IO
+Copyright   : Galois, Inc. 2010-2014
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : experimental
+Portability : non-portable (c2hs, language extensions)
+
+Binding of @base\/io\/io.h@ for reading and writing
+networks to the file system.  ABC natively supports a variety of
+different file formats.
+-}
+
+module Data.ABC.Internal.IO (
+    -- * abcReadAiger.c
+      ioReadAiger
+    -- * abcWriteAiger.c
+    , ioWriteAiger
+    ) where
+
+import Foreign
+import Foreign.C
+
+{#import Data.ABC.Internal.ABC #}
+
+#include "ioAbc.h"
+
+-- abcReadAiger.c
+{#fun Io_ReadAiger as ^ {`String', `Bool'} -> `Abc_Ntk_t' id #}
+-- abcWriteAiger.c
+{#fun Io_WriteAiger as ^
+    { id `Abc_Ntk_t'
+    , `String'
+    , `Bool' -- fWriteSymbols
+    , `Bool' -- fCompact
+    , `Bool' -- fUnique
+    } -> `()' #}
diff --git a/src/Data/ABC/Internal/Main.chs b/src/Data/ABC/Internal/Main.chs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC/Internal/Main.chs
@@ -0,0 +1,26 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE EmptyDataDecls #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+{- |
+Module      : Data.ABC.Internal.Main
+Copyright   : Galois, Inc. 2010
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : experimental
+Portability : non-portable (c2hs, language extensions)
+
+/Incomplete./ Binding of @base\/main\/main.h@ for managing
+the global state of the ABC library.
+-}
+
+module Data.ABC.Internal.Main (
+    -- * main.c
+      abcStart
+    , abcStop
+    ) where
+
+#include "main.h"
+
+{#fun Abc_Start as ^ {} -> `()' #}
+{#fun Abc_Stop as ^ {} -> `()' #}
diff --git a/src/Data/ABC/Internal/Orphan.chs b/src/Data/ABC/Internal/Orphan.chs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC/Internal/Orphan.chs
@@ -0,0 +1,40 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{- |
+Module      : Data.ABC.Internal.Orphan
+Copyright   : Galois, Inc. 2010
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : experimental
+Portability : non-portable (language extensions)
+
+/Incomplete./ Binding of various orphan functions in ABC:
+functions that are frequently extern'ed into scope but are not
+defined in any header; we've created a new header file @orphan.h@
+to accomodate these.
+
+-}
+
+module Data.ABC.Internal.Orphan
+    ( abcNtkFromAigPhase
+    -- * base\/abci\/abcDar.c
+    , abcNtkToDar
+    ) where
+
+import Foreign (fromBool)
+import Foreign.C
+
+{#import Data.ABC.Internal.ABC#}
+{#import Data.ABC.Internal.AIG#}
+
+#include "abc.h"
+#include "fra.h"
+#include "orphan.h"
+
+abcNtkToDar :: Abc_Ntk_t -> Bool -> Bool -> IO Aig_Man_t
+abcNtkToDar ntk exors rl =
+  abcNtkToDar' ntk (fromBool exors) (fromBool rl)
+
+foreign import ccall unsafe "Abc_NtkToDar"
+  abcNtkToDar' :: Abc_Ntk_t -> CInt -> CInt -> IO Aig_Man_t
+
+{#fun Abc_NtkFromAigPhase as ^ { `Aig_Man_t' } -> `Abc_Ntk_t' #}
diff --git a/src/Data/ABC/Internal/VecInt.chs b/src/Data/ABC/Internal/VecInt.chs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC/Internal/VecInt.chs
@@ -0,0 +1,85 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE EmptyDataDecls #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+{- |
+Module      : Data.ABC.Internal.VecInt
+Copyright   : Galois, Inc. 2010
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : experimental
+Portability : non-portable (c2hs, language extensions)
+
+/Incomplete./ Binding of @misc\/vec\/vecInt.h@ for manipulating
+vectors of integers.
+
+-}
+
+module Data.ABC.Internal.VecInt (
+      Vec_Int_t_
+    , Vec_Int_t
+    , clearVecInt
+    , vecIntSize , setVecIntSize
+    , vecIntCap  , setVecIntCap
+    , vecIntArray, setVecIntArray
+    , vecIntEntry
+    , vecIntWriteEntry
+    , withVecInt
+    ) where
+
+#include <stdio.h>
+#include "vec.h"
+#include "vecInt.h"
+
+import Control.Exception (bracket)
+import Foreign.C
+import Foreign
+import Data.ABC.Internal.Field
+
+data Vec_Int_t_
+
+{#pointer *Vec_Int_t -> Vec_Int_t_ #}
+
+vecIntSizeField :: Field Vec_Int_t CInt
+vecIntSizeField = fieldFromOffset {#offsetof Vec_Int_t->nSize #}
+
+vecIntSize :: Vec_Int_t -> IO CInt
+vecIntSize = readAt vecIntSizeField
+
+setVecIntSize :: Vec_Int_t -> CInt -> IO ()
+setVecIntSize = {#set Vec_Int_t->nSize #}
+
+vecIntCap :: Vec_Int_t -> IO CInt
+vecIntCap = {#get Vec_Int_t->nCap #}
+
+setVecIntCap :: Vec_Int_t -> CInt -> IO ()
+setVecIntCap = {#set Vec_Int_t->nCap #}
+
+clearVecInt :: Vec_Int_t -> IO ()
+clearVecInt v = writeAt vecIntSizeField v 0
+
+vecIntArray :: Vec_Int_t -> IO (Ptr CInt)
+vecIntArray = {#get Vec_Int_t->pArray #}
+
+setVecIntArray :: Vec_Int_t -> Ptr CInt -> IO ()
+setVecIntArray = {#set Vec_Int_t->pArray #}
+
+-- | Get entry in vector at given index.
+vecIntEntry :: Vec_Int_t -> CInt -> IO CInt
+vecIntEntry v i = do
+  a <- vecIntArray v
+  peekElemOff a (fromIntegral i)
+
+-- | Write entry in vector at given index.
+vecIntWriteEntry :: Vec_Int_t -> CInt -> CInt -> IO ()
+vecIntWriteEntry v i u = do
+  a <- vecIntArray v
+  pokeElemOff a (fromIntegral i) u
+
+withVecInt :: CInt -> Ptr CInt -> (Vec_Int_t -> IO a) -> IO a
+withVecInt sz p act = do
+  bracket (mallocBytes {#sizeof Vec_Int_t #}) free $ \v -> do
+    setVecIntSize v sz
+    setVecIntCap  v sz
+    setVecIntArray v p
+    act v
diff --git a/src/Data/ABC/Internal/VecPtr.chs b/src/Data/ABC/Internal/VecPtr.chs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC/Internal/VecPtr.chs
@@ -0,0 +1,60 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE EmptyDataDecls #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches #-}
+
+{- |
+Module      : Data.ABC.Internal.VecPtr
+Copyright   : Galois, Inc. 2010
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : experimental
+Portability : non-portable (c2hs, language extensions)
+
+/Incomplete./ Binding of @misc\/vec\/vecPtr.h@ for manipulating
+vectors of pointers.
+
+-}
+
+module Data.ABC.Internal.VecPtr (
+      Vec_Ptr_t_
+    , Vec_Ptr_t
+    , clearVec
+    , vecPtrSize
+    , vecPtrArray
+    , vecPtrEntry
+    ) where
+
+#include <stdio.h>
+#include "vec.h"
+#include "vecPtr.h"
+
+import Control.Exception (assert)
+import Foreign
+import Foreign.C
+
+import Data.ABC.Internal.Field
+
+data Vec_Ptr_t_
+
+{#pointer *Vec_Ptr_t -> Vec_Ptr_t_ #}
+
+vecSizeField :: Field Vec_Ptr_t CInt
+vecSizeField = fieldFromOffset {#offsetof Vec_Ptr_t->nSize #}
+
+clearVec :: Vec_Ptr_t -> IO ()
+clearVec v = writeAt vecSizeField v 0
+
+vecPtrSize :: Vec_Ptr_t -> IO Int
+vecPtrSize v = fromIntegral `fmap` readAt vecSizeField v
+
+vecPtrArray :: Vec_Ptr_t -> IO (Ptr (Ptr a))
+vecPtrArray v = castPtr `fmap` {#get Vec_Ptr_t->pArray #} v
+
+vecPtrEntry :: Vec_Ptr_t -> Int -> IO (Ptr a)
+vecPtrEntry v i = do
+  assert (i >= 0) $ return ()
+  do sz <- vecPtrSize v
+     assert (i < sz) $ return ()
+  a <- vecPtrArray v
+  peekElemOff a i
+
diff --git a/src/Data/ABC/Util.hs b/src/Data/ABC/Util.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/ABC/Util.hs
@@ -0,0 +1,22 @@
+{- |
+Module      : Data.ABC.Util
+Copyright   : Galois, Inc. 2010-2014
+License     : BSD3
+Maintainer  : jhendrix@galois.com
+Stability   : experimental
+Portability : portable
+-}
+module Data.ABC.Util
+  ( forN_
+  , forN
+  ) where
+
+
+forN_ :: Monad m => Int -> (Int -> m ()) -> m ()
+forN_ i m | i <= 0 = return ()
+          | otherwise = m (i-1) >> forN_ (i-1) m
+
+forN :: Monad m => Int -> (Int -> m a) -> m [a]
+forN i0 m = go [] i0
+  where go l i | i <= 0 = return (reverse l)
+               | otherwise = m (i-1) >>= \e -> go (e:l) (i-1)
diff --git a/tests/Tests/Basic.hs b/tests/Tests/Basic.hs
new file mode 100644
--- /dev/null
+++ b/tests/Tests/Basic.hs
@@ -0,0 +1,118 @@
+module Tests.Basic
+  ( basic_tests
+  ) where
+
+import Control.Applicative
+import Control.Exception
+import Control.Monad
+import System.Directory
+import System.IO
+import Test.Framework
+import Test.Framework.Providers.HUnit
+import Test.Framework.Providers.QuickCheck2
+import Test.HUnit (assertEqual)
+import Test.QuickCheck
+
+import qualified Data.ABC as ABC
+
+tryIO :: IO a -> IO (Either IOException a)
+tryIO = try
+
+basic_tests :: ABC.Proxy l g -> [Test.Framework.Test]
+basic_tests proxy@(ABC.Proxy f) = f $
+  [ testCase "test_true" $ do
+      ABC.SomeGraph g <- ABC.newGraph proxy
+      let n = ABC.Network g [ABC.trueLit g]
+      assertEqual "test_true" [True] =<< ABC.evaluate n []
+  , testCase "test_false" $ do
+      ABC.SomeGraph g <- ABC.newGraph proxy
+      let n = ABC.Network g [ABC.falseLit g]
+      assertEqual "test_false" [False] =<< ABC.evaluate n []
+  , testProperty "test_constant"$ \b -> ioProperty $do
+      ABC.SomeGraph g <- ABC.newGraph proxy
+      let n = ABC.Network g [ABC.constant g b]
+      (==[b]) <$> ABC.evaluate n []
+  , testProperty "test_not" $ \b0 -> ioProperty $ do
+      ABC.SomeGraph g <- ABC.newGraph proxy
+      i0 <- ABC.newInput g
+      let n = ABC.Network g [ABC.not i0]
+      r <- ABC.evaluate n [b0]
+      return $ r == [not b0]
+  , testProperty "test_and" $ \b1 b2 -> ioProperty $ do
+      ABC.SomeGraph g <- ABC.newGraph proxy
+      i0 <- ABC.newInput g
+      i1 <- ABC.newInput g
+      x <- ABC.and g i0 i1
+      let n = ABC.Network g [x]
+      r <- ABC.evaluate n [b1, b2]
+      return $ r == [b1 && b2]
+  , testProperty "test_xor" $ \b1 b2 -> ioProperty $ do
+      ABC.SomeGraph g <- ABC.newGraph proxy
+      i0 <- ABC.newInput g
+      i1 <- ABC.newInput g
+      x <- ABC.xor g i0 i1
+      let n = ABC.Network g [x]
+      r <- ABC.evaluate n [b1, b2]
+      return $ r == [b1 /= b2]
+  , testProperty "test_mux" $ \b0 b1 b2 -> ioProperty $ do
+      ABC.SomeGraph g <- ABC.newGraph proxy
+      i0 <- ABC.newInput g
+      i1 <- ABC.newInput g
+      i2 <- ABC.newInput g
+      o <- ABC.mux g i0 i1 i2
+
+      let n = ABC.Network g [o]
+      r <- ABC.evaluate n [b0, b1, b2]
+      return $ r == [if b0 then b1 else b2]
+  , testCase "test_cec" $ do
+     r <- join $ ABC.cec <$> cecNetwork proxy <*> cecNetwork' proxy
+     assertEqual "test_cec" (ABC.Invalid (toEnum <$> [0,0,0,1,0,0,0])) r
+  , testCase "test_aiger" $ do
+      -- XXX: cwd unfriendly
+      n1 <- ABC.aigerNetwork proxy "tests/eijk.S298.S.aig"
+      tmpdir <- getTemporaryDirectory
+      (path, hndl) <- openTempFile tmpdir "aiger.aig"
+      hClose hndl
+      ABC.writeAiger path n1
+      n2 <- ABC.aigerNetwork proxy path
+      assertEqual "test_aiger" ABC.Valid =<< ABC.cec n1 n2
+      removeFile path
+  , testCase "bad_aiger" $ do
+      me <- tryIO $ ABC.aigerNetwork proxy "Nonexistent AIGER!"
+      case me of
+        Left{} -> return ()
+        Right{} -> fail "Expected error when opening AIGER"
+  , testCase "test_sat" $ do
+     ABC.SomeGraph g <- ABC.newGraph proxy
+     rt <- ABC.checkSat g (ABC.trueLit g)
+     case rt of
+       ABC.Sat{} -> return ()
+       ABC.Unsat{} -> fail "trueLit is unsat"
+     rf <- ABC.checkSat g (ABC.falseLit g)
+     case rf of
+       ABC.Sat{} -> fail "falseLit is sat"
+       ABC.Unsat{} -> return ()
+  ]
+
+cecNetwork :: ABC.IsAIG l g => ABC.Proxy l g -> IO (ABC.Network l g)
+cecNetwork proxy = do
+  ABC.SomeGraph g <- ABC.newGraph proxy
+  [n2, n3, n4, n5, n6, n7, n8] <- replicateM 7 $ ABC.newInput g
+
+  n14 <- ABC.ands g [ ABC.not n2
+                    , ABC.not n3
+                    , ABC.not n4
+                    , n5
+                    , ABC.not n6
+                    , ABC.not n7
+                    , ABC.not n8
+                    ]
+  let r = [n14] ++ replicate 6 (ABC.falseLit g)
+  return (ABC.Network g r)
+
+cecNetwork' :: ABC.IsAIG l g => ABC.Proxy l g -> IO (ABC.Network l g)
+cecNetwork' proxy = do
+  ABC.SomeGraph g <- ABC.newGraph proxy
+  replicateM_ 7 $ ABC.newInput g
+  let r = replicate 7 $ ABC.falseLit g
+  return (ABC.Network g r)
diff --git a/tests/Tests/Operations.hs b/tests/Tests/Operations.hs
new file mode 100644
--- /dev/null
+++ b/tests/Tests/Operations.hs
@@ -0,0 +1,47 @@
+{-# LANGUAGE Rank2Types #-}
+module Tests.Operations
+  ( op_tests
+  ) where
+
+import qualified Data.AIG as AIG
+import Test.Framework
+import Test.Framework.Providers.QuickCheck2
+import Test.QuickCheck
+
+bv :: AIG.IsAIG l g => g s -> Int -> Integer -> AIG.BV (l s)
+bv = AIG.bvFromInteger
+
+bin_test :: String
+         -> AIG.Proxy l g
+            -- ^ Proxy
+         -> (forall s . g s -> AIG.BV (l s) -> AIG.BV (l s) -> IO (AIG.BV (l s)))
+            -- ^ Bitvector operation
+         -> (Integer -> Integer -> Integer)
+            -- ^ Concrete op
+         -> Test.Framework.Test
+bin_test nm proxy@(AIG.Proxy f) bv_op c_op = f $
+  testProperty nm $ \u v -> ioProperty $ do
+    let w = 10
+    AIG.SomeGraph g <- AIG.newGraph proxy
+    z <- bv_op g (bv g w u) (bv g w v)
+    let expected = (c_op u v) `mod` (2^w)
+    return $ Just expected == AIG.asUnsigned g z
+
+op_tests :: AIG.Proxy l g -> [Test.Framework.Test]
+op_tests proxy@(AIG.Proxy f) = f $
+  [ testProperty "test_bv" $ \u -> ioProperty $ do
+      AIG.SomeGraph g <- AIG.newGraph proxy
+      let w = 10
+      let z = (bv g w u)
+      let expected = u `mod` (2^w)
+      return $ Just expected == AIG.asUnsigned g z
+  , bin_test "test_add" proxy AIG.add (+)
+  , bin_test "test_sub" proxy AIG.sub (-)
+  , bin_test "test_mul" proxy AIG.mul (*)
+  , testProperty "test_neg" $ \u -> ioProperty $ do
+      let w = 10
+      AIG.SomeGraph g <- AIG.newGraph proxy
+      z <- AIG.neg g (bv g w u)
+      let expected = (negate u) `mod` (2^w)
+      return $ Just expected == AIG.asUnsigned g z
+  ]
diff --git a/tests/Tests/QBF.hs b/tests/Tests/QBF.hs
new file mode 100644
--- /dev/null
+++ b/tests/Tests/QBF.hs
@@ -0,0 +1,47 @@
+module Tests.QBF
+  ( qbf_tests
+  ) where
+
+import Test.Framework
+import Test.Framework.Providers.HUnit
+
+import qualified Data.ABC as ABC
+import qualified Data.ABC.GIA as GIA
+
+qbf_tests :: [Test.Framework.Test]
+qbf_tests =
+  [ testCase "test_qbf_and" $ do
+      ABC.SomeGraph g <- GIA.newGIA
+      i0 <- ABC.newInput g
+      i1 <- ABC.newInput g
+      x <- ABC.and g i0 i1
+      Right r <- GIA.check_exists_forall g 1 x [False] 1000
+      case r of
+        ABC.Sat{} -> fail "abc returned sat"
+        ABC.Unsat{} -> return ()
+  , testCase "test_qbf_or" $ do
+      ABC.SomeGraph g <- GIA.newGIA
+      i0 <- ABC.newInput g
+      i1 <- ABC.newInput g
+      x <- ABC.or g i0 i1
+      Right r <- GIA.check_exists_forall g 1 x [False] 1000
+      case r of
+        ABC.Sat [True] -> return ()
+        _ -> fail "abc returned bad value."
+  , testCase "test_qbf_implies" $ do
+      ABC.SomeGraph g <- GIA.newGIA
+      i0 <- ABC.newInput g
+      i1 <- ABC.newInput g
+      x <- ABC.implies g i0 i1
+      Right r <- GIA.check_exists_forall g 1 x [False] 1000
+      case r of
+        ABC.Sat [False] -> return ()
+        _ -> fail "abc returned bad value."
+  , testCase "test_qbf_zero_iterations" $ do
+      ABC.SomeGraph g <- GIA.newGIA
+      i0 <- ABC.newInput g
+      i1 <- ABC.newInput g
+      x <- ABC.implies g i0 i1
+      Left _msg <- GIA.check_exists_forall g 1 x [False] 0
+      return ()
+  ]
diff --git a/tests/abc-test.hs b/tests/abc-test.hs
new file mode 100644
--- /dev/null
+++ b/tests/abc-test.hs
@@ -0,0 +1,181 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+module Main (main) where
+
+import Test.Framework
+
+import qualified Data.ABC as ABC
+
+import Tests.Basic
+import Tests.Operations
+import Tests.QBF
+
+------------------------------------------------------------------------
+-- Runner
+------------------------------------------------------------------------
+
+main :: IO ()
+main = do
+  ABC.initialize
+  defaultMain tests
+
+tests :: [Test.Framework.Test]
+tests =
+    [ testGroup "AIG basic" $ basic_tests ABC.aigNetwork
+    , testGroup "AIG operations" $ op_tests ABC.giaNetwork
+    , testGroup "GIA basic" $ basic_tests ABC.giaNetwork
+    , testGroup "GIA operations" $ op_tests ABC.giaNetwork
+    , testGroup "GIA QBF tests" $ qbf_tests
+    ]
+
+{-
+tests :: [Test.Framework.Test]
+tests =
+    [ testGroup "AIG" $ do
+       basic_tests ABC.aigNetwork ++ aig_tests
+    , testGroup "GIA" $ basic_tests ABC.giaNetwork
+    ]
+
+cecNetwork :: ABC.IsAIG l g => ABC.Proxy l g -> IO (ABC.Network l g)
+cecNetwork proxy = do
+  ABC.SomeGraph g <- ABC.newGraph proxy
+  [n2, n3, n4, n5, n6, n7, n8] <- replicateM 7 $ ABC.newInput g
+
+  n14 <- ABC.ands g [ ABC.not n2
+                    , ABC.not n3
+                    , ABC.not n4
+                    , n5
+                    , ABC.not n6
+                    , ABC.not n7
+                    , ABC.not n8
+                    ]
+  let r = [n14] ++ replicate 6 (ABC.falseLit g)
+  return (ABC.Network g r)
+
+cecNetwork' :: ABC.IsAIG l g => ABC.Proxy l g -> IO (ABC.Network l g)
+cecNetwork' proxy = do
+  ABC.SomeGraph g <- ABC.newGraph proxy
+  replicateM_ 7 $ ABC.newInput g
+  let r = replicate 7 $ ABC.falseLit g
+  return (ABC.Network g r)
+
+basic_tests :: ABC.Proxy l g -> [Test.Framework.Test]
+basic_tests proxy@(ABC.Proxy f) = f $
+  [ testCase "test_true" $ do
+      ABC.SomeGraph g <- ABC.newGraph proxy
+      let n = ABC.Network g [ABC.trueLit g]
+      assertEqual "test_true" [True] =<< ABC.evaluate n []
+  , testCase "test_false" $ do
+      ABC.SomeGraph g <- ABC.newGraph proxy
+      let n = ABC.Network g [ABC.falseLit g]
+      assertEqual "test_false" [False] =<< ABC.evaluate n []
+  , testProperty "test_constant"$ \b -> ioProperty $do
+      ABC.SomeGraph g <- ABC.newGraph proxy
+      let n = ABC.Network g [ABC.constant g b]
+      (==[b]) <$> ABC.evaluate n []
+  , testProperty "test_not" $ \b0 -> ioProperty $ do
+      ABC.SomeGraph g <- ABC.newGraph proxy
+      i0 <- ABC.newInput g
+      let n = ABC.Network g [ABC.not i0]
+      r <- ABC.evaluate n [b0]
+      return $ r == [not b0]
+  , testProperty "test_and" $ \b1 b2 -> ioProperty $ do
+      ABC.SomeGraph g <- ABC.newGraph proxy
+      i0 <- ABC.newInput g
+      i1 <- ABC.newInput g
+      x <- ABC.and g i0 i1
+      let n = ABC.Network g [x]
+      r <- ABC.evaluate n [b1, b2]
+      return $ r == [b1 && b2]
+  , testProperty "test_xor" $ \b1 b2 -> ioProperty $ do
+      ABC.SomeGraph g <- ABC.newGraph proxy
+      i0 <- ABC.newInput g
+      i1 <- ABC.newInput g
+      x <- ABC.xor g i0 i1
+      let n = ABC.Network g [x]
+      r <- ABC.evaluate n [b1, b2]
+      return $ r == [b1 /= b2]
+  , testProperty "test_mux" $ \b0 b1 b2 -> ioProperty $ do
+      ABC.SomeGraph g <- ABC.newGraph proxy
+      i0 <- ABC.newInput g
+      i1 <- ABC.newInput g
+      i2 <- ABC.newInput g
+      o <- ABC.mux g i0 i1 i2
+      let n = ABC.Network g [o]
+      r <- ABC.evaluate n [b0, b1, b2]
+      return $ r == [if b0 then b1 else b2]
+  , testCase "test_cec" $ do
+     r <- join $ ABC.cec <$> cecNetwork proxy <*> cecNetwork' proxy
+     assertEqual "test_cec" (ABC.Invalid (toEnum <$> [0,0,0,1,0,0,0])) r
+  , testCase "test_aiger" $ do
+     -- XXX: cwd unfriendly
+     n1 <- ABC.aigerNetwork proxy "tests/eijk.S298.S.aig"
+     tmpdir <- getTemporaryDirectory
+     (path, hndl) <- openTempFile tmpdir "aiger.aig"
+     hClose hndl
+     ABC.writeAiger path n1
+     n2 <- ABC.aigerNetwork proxy path
+     assertEqual "test_aiger" ABC.Valid =<< ABC.cec n1 n2
+     removeFile path
+  , testCase "test_sat" $ do
+     ABC.SomeGraph g <- ABC.newGraph proxy
+     rt <- ABC.checkSat g (ABC.trueLit g)
+     case rt of
+       ABC.Sat{} -> return ()
+       ABC.Unsat{} -> fail "trueLit is unsat"
+     rf <- ABC.checkSat g (ABC.falseLit g)
+     case rf of
+       ABC.Sat{} -> fail "falseLit is sat"
+       ABC.Unsat{} -> return ()
+  , testProperty "test_add" $ \(i0 :: Int8) (i1 :: Int8) -> ioProperty $ do
+      ABC.SomeGraph g <- ABC.newGraph proxy
+      is0 <- replicateM 8 $ ABC.newInput g
+      is1 <- replicateM 8 $ ABC.newInput g
+      os <- Ops.add g (litsToBV is0) (litsToBV is1)
+      let n = ABC.Network g (Ops.bvToList os)
+      r <- ABC.evaluate n (bitsOfInt8 i0 ++ bitsOfInt8 i1)
+      return $ bitsToInt8 r == i0 + i1
+  , testProperty "test_sub" $ \(i0 :: Int8) (i1 :: Int8) -> ioProperty $ do
+      ABC.SomeGraph g <- ABC.newGraph proxy
+      is0 <- replicateM 8 $ ABC.newInput g
+      is1 <- replicateM 8 $ ABC.newInput g
+      os <- Ops.sub g (litsToBV is0) (litsToBV is1)
+      let n = ABC.Network g (Ops.bvToList os)
+      r <- ABC.evaluate n (bitsOfInt8 i0 ++ bitsOfInt8 i1)
+      return $ bitsToInt8 r == i0 - i1
+  , testProperty "test_neg" $ \(i0 :: Int8) -> ioProperty $ do
+      ABC.SomeGraph g <- ABC.newGraph proxy
+      is0 <- replicateM 8 $ ABC.newInput g
+      os <- Ops.neg g (litsToBV is0)
+      let n = ABC.Network g (Ops.bvToList os)
+      r <- ABC.evaluate n (bitsOfInt8 i0)
+      return $ bitsToInt8 r == (- i0)
+  ]
+
+singletonBV :: l -> Ops.BV l
+singletonBV = Ops.replicate 1
+
+litsToBV :: [l] -> Ops.BV l
+litsToBV = Ops.concat . map singletonBV
+
+bitsOfInt8 :: Int8 -> [Bool]
+bitsOfInt8 n = unfoldr f 7
+  where f i | i >= 0 = Just (testBit n i, i - 1)
+            | otherwise = Nothing
+
+bitsToInt8 :: [Bool] -> Int8
+bitsToInt8 = foldr f 0
+  where f b n = (shiftL n 1) .|. fromIntegral (fromEnum b)
+
+tryIO :: IO a -> IO (Either IOException a)
+tryIO = try
+
+aig_tests :: [Test.Framework.Test]
+aig_tests =
+  [ testCase "bad_aiger" $ do
+      me <- tryIO $ ABC.readAigerAsAIG "Nonexistent AIGER!"
+      case me of
+        Left{} -> return ()
+        Right{} -> fail "Expected error when opening AIGER"
+  ]
+
+-}
diff --git a/tests/eijk.S298.S.aig b/tests/eijk.S298.S.aig
new file mode 100644
--- /dev/null
+++ b/tests/eijk.S298.S.aig
@@ -0,0 +1,8563 @@
+aig 257793 214 0 1 257579
+515586
+
+³·£±§¯#Ñ¹ØØ.6áãÓ<8&ÊÊÍÏ6ààUX*"_ûý
+5<>Ó?Õ^ ¡£z¾¾6ÇÉ
+h&­¯]M»½§ÂªÂ©°ì0±Ì¾þþÍÌ¾ùüm¶p¶ÈÛÉÝA°üI¶OÐÔÔÎb([`ææ$úír\ö1¢>Ê¯Ï,Ò,üÕ×á,ä,çéôõùùøöý¡£&¢ ¤¡¦"&²·¹¸Æ½¼;ÆÌAÛÝ ¿àÜÝák]ïñøôö÷üw¡£¡¤
+¬±)¯µ·âµ¹*¿&ÅÇ"ÒüØ×+ÙÜÞéëò(ðó*·âùû,Ü(ª¹¿Á²wµxÃ
+÷µç³»¥°Ã¶Ç§fÏ#Ç		,4		·º:6$				4		SÒVÒ* ]³	µ	
+5:¼	¼	>	?	\°¬³¯xö	ö	6ÿ	
+
+h$å	ç	]Kó	õ	¥ü¨ü§®¥0¯Ê¼¶
+¶
+Ë¯ÊéÆ
+Æ
+÷ÖúÖmî	pî	È	É	A®úI´O³b([`$ø¦r\­1¢¸¸>õ­ÄÄ±Ö´Ö	±Ö´Öª	¡æ³Ê£·È®ÍÇ·DÙÛ&ðµÞÉÎ%ß"&ªïñåªü2¦;Ú¸wA®{¯k]§©Æ_æA´¸1¦wÍÏ/ãÙÛ¡Â	ÓÕ
+Ò	íóáÚ«ìæ±Òýÿ"þô¦ú£¡£
+®»ü	±³,ª§
+ÈÅÇ· ÷ù¸²¯Âµ°ÅÅ
+ùíé³ó§°û¸ÿ©f#ýÊÊ,4ÓÕ¹ð:6$¼¼¿Á4ÒÒSV* ]íï
+5:öö>Å?Ç\²ÁäµÂçx°°6¹»
+h$¡]K­¯¥¶¨¶§®§0¯Ê¼ððË±Êë÷úm¨p¨ÈÍÉÏA®úI´OµÆÆ¡b([`ØØ$ø¨r\¯1¢òò>÷­þþ³
+¶
+ÒÇÉ³¶âÙÛè³Ì¥¹Ê°ÏÉ¹D&òµàÉÐ%á"&¬©«ç¬þ2¨;ÜºwAÍÏ°{±k]áãÈ_èA¶º1¨w/å¡ú
+Ô	ïõãÜ­ì	³·¹"ö¨üÛÛÝ
+°»´ëí,¬©
+ÿ¹Ö±³¹²çúµèýÅ
+ù¥é³«§°³¸·©f¿#µ,4¹¨:6$ööùû4SÆVÆ* ]§©
+5:°°>ÿ?\²ùµúxêê6óõ
+h$ÙÛ]Kçé¥ð¨ð§®§0¯Ê¼ªªË±Êëºº÷ÊúÊmâpâÈÉA®úI´Oµ¡b([`$ø¨r\¯1¢¬¬>÷­¸¸³Ä¶Ä³Ä¶Äè³Ì¥¹Ê°ÏÉ¹DÍÏ&òµàÉÐ%á"&¬ãåç¬þ2¨;ÜºwA°{±k]È_èA¶º1¨wÁÃ/åÍÏ¡²ÇÉ
+Ô	ïõãÜ­ìÔ³Àñó"ö¨ü
+°»ì¥§,¬©
+¸¹»¹ëí¹²²µ µÅ
+ùÝé³ã§°ë¸ï©f÷#í¾¾,4ÇÉ¹à:6$°°³µ4ÆÆSV* ]áã
+5:êê>¹?»\²±Ôµ²×x¤¤6­¯
+h$]K¡£¥ª¨ª§®§0¯Ê¼ääË±Êëôô÷úmpÈÁÉÃA®úI´Oµºº¡b([`ÌÌ$ø¨r\¯1¢ææ>÷­òò³ü¶üÂ»½³ü¶üÒÍÏè³Ì¥¹Ê°ÏÉ¹D&òµàÉÐ%á"&¬ç¬þ2¨;ÜºwAÁÃ°{±k]Õ×È_èA¶º1¨wûý/å¡ê
+Ô	ïõãÜ­ì³ø«­"ö¨üËÏÑ
+°»¤ßá,¬©
+ðóõ¹Æ¥§¹²×êµØíÅ
+ùé³§°£¸§©f¯#¥øø,4¹:6$êêíï4SºVº* ]
+5:¤¤>ó?õ\²éµêxÞÞ6çé
+h$ÍÏ]KÛÝ¥ä¨ä§®§0¯Ê¼  Ë±Êë® ® ÷¾ú¾mÖpÖÈûÉýA®úI´Oµô ô ¡b([`!!$ø¨r\¯1¢ ! !>÷­¬!¬!³´¶´úõ ÷ ³´¶´!!è³Ì¥¹Ê°ÏÉ¹DÁ!Ã!&òµàÉÐ%á"&¬×!Ù!ç¬þ2¨;ÜºwAû!ý!°{±k]""È_èA¶º1¨wµ"·"/åÁ"Ã"¡¢»"½"
+Ô	ïõãÜ­ìÄ³°å"ç""ö¨ü!##
+°»Ü##,¬©
+¨!­#¯#¹þß#á#¹²¢#µ¥#Å
+ùÍ!é³Ó!§°Û!¸ß!©fç!#Ý²$²$,4»$½$¹Ð:6$¤$¤$§$©$4º$º$Sô#Vô#* ]Õ$×$
+5:Þ$Þ$>­$?¯$\²¡Ä#µ¢Ç#x%%6¡%£%
+h$%%]K%%¥$¨$§®§0¯Ê¼Ø%Ø%Ë±Êëè%è%÷ø#úø#m%p%Èµ$É·$A®úI´Oµ®&®&¡b([`À&À&$ø¨r\¯1¢Ú&Ú&>÷­æ&æ&³ì¶ì²$¯&±&³ì ¶ì Â$Á&Ã&è³Ì¥¹Ê°ÏÉ¹Dû&ý&&òµàÉÐ%á"&¬''ç¬þ2¨;ÜºwAµ'·'°{±k]É'Ë'È_èA¶º1¨wï'ñ'/åû'ý'¡Ú$õ'÷'
+Ô	ïõãÜ­ìü³è (¡("ö¨ü»&Ã(Å(
+°»%Ó(Õ(,¬©
+à&ç(é(¹¶!))¹²Ç!Ú(µÈ!Ý(Å
+ù'é³'§°'¸'©f'##ì)ì),4õ)÷)¹":6$Þ)Þ)á)ã)4ô)ô)S®)V®)* ]**
+5:**>ç)?é)\²Ù"ü(µÚ"ÿ(xÒ*Ò*6Û*Ý*
+h$Á*Ã*]KÏ*Ñ*¥Ø)¨Ø)§®§0¯Ê¼++Ë±Êë¢+¢+÷²)ú²)mÊ*pÊ*Èï)Éñ)A®úI´Oµè+è+¡b([`ú+ú+$ø¨r\¯1¢,,>÷­ , ,³¤%¶¤%ê)é+ë+³¤&¶¤&ú)û+ý+è³Ì¥¹Ê°ÏÉ¹Dµ,·,&òµàÉÐ%á"&¬Ë,Í,ç¬þ2¨;ÜºwAï,ñ,°{±k]--È_èA¶º1¨w©-«-/åµ-·-¡*¯-±-
+Ô	ïõãÜ­ì´$³ &Ù-Û-"ö¨üó+ý-ÿ-
+°»Ì*..,¬©
+,¡.£.¹î&Ó.Õ.¹²ÿ&.µ'.Å
+ù½,é³Ã,§°Ë,¸Ï,©f×,#Í(¦/¦/,4¯/±/¹À':6$////4®/®/Sè.Vè.* ]É/Ë/
+5:Ò/Ò/>¡/?£/\²(´.µ(·.x00600
+h$û/ý/]K00¥/¨/§®§0¯Ê¼Ì0Ì0Ë±ÊëÜ0Ü0÷ì.úì.m0p0È©/É«/A®úI´Oµ¢1¢1¡b([`´1´1$ø¨r\¯1¢Î1Î1>÷­Ú1Ú1³Ü*¶Ü*¢/£1¥1³Ü+¶Ü+²/µ1·1è³Ì¥¹Ê°ÏÉ¹Dï1ñ1&òµàÉÐ%á"&¬22ç¬þ2¨;ÜºwA©2«2°{±k]½2¿2È_èA¶º1¨wã2å2/åï2ñ2¡Ê/é2ë2
+Ô	ïõãÜ­ìì)³Ø+33"ö¨ü«1·3¹3
+°»0Ç3É3,¬©
+Ð1Û3Ý3¹¦,44¹²·,Ê3µ¸,Í3Å
+ùõ1é³û1§°2¸2©f2#.à4à4,4é4ë4¹ø,:6$Ò4Ò4Õ4×44è4è4S¢4V¢4* ]55
+5:55>Û4?Ý4\²É-ì3µÊ-ï3xÆ5Æ56Ï5Ñ5
+h$µ5·5]KÃ5Å5¥Ì4¨Ì4§®§0¯Ê¼66Ë±Êë66÷¦4ú¦4m¾5p¾5Èã4Éå4A®úI´OµÜ6Ü6¡b([`î6î6$ø¨r\¯1¢77>÷­77³0¶0Ú4Ý6ß6³1¶1ê4ï6ñ6è³Ì¥¹Ê°ÏÉ¹D©7«7&òµàÉÐ%á"&¬¿7Á7ç¬þ2¨;ÜºwAã7å7°{±k]÷7ù7È_èA¶º1¨w88/å©8«8¡5£8¥8
+Ô	ïõãÜ­ì¤/³1Í8Ï8"ö¨üã6ñ8ó8
+°»¼599,¬©
+799¹Þ1Ç9É9¹²ï19µð19Å
+ù­7é³³7§°»7¸¿7©fÇ7#½3::,4£:¥:¹°2:6$::::4¢:¢:SÜ9VÜ9* ]½:¿:
+5:Æ:Æ:>:?:\²3¤9µ3§9x;;6;;
+h$ï:ñ:]Ký:ÿ:¥:¨:§®§0¯Ê¼À;À;Ë±ÊëÐ;Ð;÷à9úà9mø:pø:È:É:A®úI´Oµ<<¡b([`¨<¨<$ø¨r\¯1¢Â<Â<>÷­Î<Î<³Ì5¶Ì5:<<³Ì6¶Ì6¢:©<«<è³Ì¥¹Ê°ÏÉ¹Dã<å<&òµàÉÐ%á"&¬ù<û<ç¬þ2¨;ÜºwA==°{±k]±=³=È_èA¶º1¨w×=Ù=/åã=å=¡º:Ý=ß=
+Ô	ïõãÜ­ìÜ4³È6>>"ö¨ü<«>­>
+°»ô:»>½>,¬©
+À<Ï>Ñ>¹7??¹²§7º>µ¨7½>Å
+ùå<é³ë<§°ó<¸÷<©fÿ<#õ8Ô?Ô?,4Ý?ß?¹è7:6$Æ?Æ?É?Ë?4Ü?Ü?S?V?* ]÷?ù?
+5:@@>Ï??Ñ?\²¹8Ü>µº8ß>xº@º@6Ã@Å@
+h$©@«@]K·@¹@¥À?¨À?§®§0¯Ê¼ú@ú@Ë±ÊëAA÷?ú?m²@p²@È×?ÉÙ?A®úI´OµÐAÐA¡b([`âAâA$ø¨r\¯1¢üAüA>÷­BB³;¶;Ê?ÑAÓA³<¶<Ú?ãAåAè³Ì¥¹Ê°ÏÉ¹DBB&òµàÉÐ%á"&¬³BµBç¬þ2¨;ÜºwA×BÙB°{±k]ëBíBÈ_èA¶º1¨wCC/åCC¡ò?CC
+Ô	ïõãÜ­ì:³<ÁCÃC"ö¨üÓAåCçC
+°»¬@õC÷C,¬©
+øADD¹Î<»D½D¹²ß<òCµà<õCÅ
+ùBé³£B§°«B¸¯B©f·B#­>EE,4EE¹ =:6$EEEE4EESÐDVÐD* ]±E³E
+5:ºEºE>E?E\²ñ=Dµò=DxôEôE6ýEÿE
+h$ãEåE]KñEóE¥úD¨úD§®§0¯Ê¼´F´FË±ÊëÄFÄF÷ÔDúÔDmìEpìEÈEÉEA®úI´OµGG¡b([`GG$ø¨r\¯1¢¶G¶G>÷­ÂGÂG³¼@¶¼@EGG³¼A¶¼AEGGè³Ì¥¹Ê°ÏÉ¹D×GÙG&òµàÉÐ%á"&¬íGïGç¬þ2¨;ÜºwAHH°{±k]¥H§HÈ_èA¶º1¨wËHÍH/å×HÙH¡ªEÑHÓH
+Ô	ïõãÜ­ìÌ?³¸AûHýH"ö¨üGI¡I
+°»äE¯I±I,¬©
+°GÃIÅI¹BõI÷I¹²BªIµB­IÅ
+ùÕGé³ÛG§°ãG¸çG©fïG#åCÈJÈJ,4ÑJÓJ¹ØB:6$ºJºJ½J¿J4ÐJÐJSJVJ* ]ëJíJ
+5:ôJôJ>ÃJ?ÅJ\²©CÌIµªCÏIx®K®K6·K¹K
+h$KK]K«K­K¥´J¨´J§®§0¯Ê¼îKîKË±ÊëþKþK÷JúJm¦Kp¦KÈËJÉÍJA®úI´OµÄLÄL¡b([`ÖLÖL$ø¨r\¯1¢ðLðL>÷­üLüL³ôE¶ôEºJÅLÇL³ôF¶ôFÊJ×LÙLè³Ì¥¹Ê°ÏÉ¹DMM&òµàÉÐ%á"&¬§M©Mç¬þ2¨;ÜºwAËMÍM°{±k]ßMáMÈ_èA¶º1¨wNN/åNN¡âJNN
+Ô	ïõãÜ­ìE³ðFµN·N"ö¨üÃLÙNÛN
+°»KéNëN,¬©
+èLýNÿN¹¾G¯O±O¹²ÏGâNµÐGåNÅ
+ùMé³M§°M¸M©f§M#IPP,4PP¹H:6$ôOôO÷OùO4PPSÄOVÄO* ]¥P§P
+5:®P®P>ýO?ÿO\²áHOµâHOxèPèP6ñPóP
+h$×PÙP]KåPçP¥îO¨îO§®§0¯Ê¼¨Q¨QË±Êë¸Q¸Q÷ÈOúÈOmàPpàPÈPÉPA®úI´OµþQþQ¡b([`RR$ø¨r\¯1¢ªRªR>÷­¶R¶R³¬K¶¬KòOÿQR³¬L¶¬LPRRè³Ì¥¹Ê°ÏÉ¹DËRÍR&òµàÉÐ%á"&¬áRãRç¬þ2¨;ÜºwASS°{±k]SSÈ_èA¶º1¨w¿SÁS/åËSÍS¡PÅSÇS
+Ô	ïõãÜ­ì¼J³¨LïSñS"ö¨üûQTT
+°»ÔP£T¥T,¬©
+ R·T¹T¹öLéTëT¹²MTµMTÅ
+ùÅRé³ËR§°ÓR¸×R©fßR#ÕN¼U¼U,4ÅUÇU¹ÈM:6$®U®U±U³U4ÄUÄUSþTVþT* ]ßUáU
+5:èUèU>·U?¹U\²N¼TµN¿Tx¢V¢V6«V­V
+h$VV]KV¡V¥¨U¨¨U§®§0¯Ê¼âVâVË±ÊëòVòV÷UúUmVpVÈ¿UÉÁUA®úI´Oµ¸W¸W¡b([`ÊWÊW$ø¨r\¯1¢äWäW>÷­ðWðW³äP¶äPªU¹W»W³äQ¶äQºUËWÍWè³Ì¥¹Ê°ÏÉ¹DXX&òµàÉÐ%á"&¬XXç¬þ2¨;ÜºwA¿XÁX°{±k]ÓXÕXÈ_èA¶º1¨wùXûX/åYY¡ÒUÿXY
+Ô	ïõãÜ­ìôO³àQ©Y«Y"ö¨ü³WÍYÏY
+°»VÝYßY,¬©
+ØWñYóY¹®R£Z¥Z¹²¿RÒYµÀRÕYÅ
+ùýWé³X§°X¸X©fX#TöZöZ,4ÿZ[¹S:6$èZèZëZíZ4þZþZS¸ZV¸Z* ][[
+5:¢[¢[>ñZ?óZ\²ÑSôYµÒS÷YxÜ[Ü[6å[ç[
+h$Ë[Í[]KÙ[Û[¥âZ¨âZ§®§0¯Ê¼\\Ë±Êë¬\¬\÷¼Zú¼ZmÔ[pÔ[ÈùZÉûZA®úI´Oµò\ò\¡b([`]]$ø¨r\¯1¢]]>÷­ª]ª]³V¶VâZó\õ\³W¶WòZ]]è³Ì¥¹Ê°ÏÉ¹D¿]Á]&òµàÉÐ%á"&¬Õ]×]ç¬þ2¨;ÜºwAù]û]°{±k]^^È_èA¶º1¨w³^µ^/å¿^Á^¡[¹^»^
+Ô	ïõãÜ­ì¬U³Wã^å^"ö¨üë\__
+°»Ä[__,¬©
+]«_­_¹æWÝ_ß_¹²÷W_µøW_Å
+ùµ]é³»]§°Ã]¸Ç]©fÏ]#ÅY°`°`,4¹`»`¹¸X:6$¢`¢`¥`§`4¸`¸`Sò_Vò_* ]Ó`Õ`
+5:Ü`Ü`>«`?­`\²Y¬_µY¯_xaa6a¡a
+h$aa]Kaa¥`¨`§®§0¯Ê¼ÖaÖaË±Êëæaæa÷ö_úö_mapaÈ³`Éµ`A®úI´Oµ¬b¬b¡b([`¾b¾b$ø¨r\¯1¢ØbØb>÷­äbäb³Ô[¶Ô[`­b¯b³Ô\¶Ô\ª`¿bÁbè³Ì¥¹Ê°ÏÉ¹Dùbûb&òµàÉÐ%á"&¬ccç¬þ2¨;ÜºwA³cµc°{±k]ÇcÉcÈ_èA¶º1¨wícïc/åùcûc¡Â`ócõc
+Ô	ïõãÜ­ìäZ³Ð\dd"ö¨ü£bÁdÃd
+°»ü`ÑdÓd,¬©
+Èbådçd¹]ee¹²¯]Âdµ°]ÅdÅ
+ùíbé³ób§°ûb¸ÿb©fc#ý^êeêe,4óeõe¹ð]:6$ÜeÜeßeáe4òeòeS¬eV¬e* ]ff
+5:ff>åe?çe\²Á^ädµÂ^çdxÐfÐf6ÙfÛf
+h$¿fÁf]KÍfÏf¥Öe¨Öe§®§0¯Ê¼ggË±Êë g g÷°eú°emÈfpÈfÈíeÉïeA®úI´Oµægæg¡b([`øgøg$ø¨r\¯1¢hh>÷­hh³a¶aÒeçgég³b¶bâeùgûgè³Ì¥¹Ê°ÏÉ¹D³hµh&òµàÉÐ%á"&¬ÉhËhç¬þ2¨;ÜºwAíhïh°{±k]iiÈ_èA¶º1¨w§i©i/å³iµi¡úe­i¯i
+Ô	ïõãÜ­ì`³b×iÙi"ö¨üÛgûiýi
+°»´fjj,¬©
+hj¡j¹ÖbÑjÓj¹²çbúiµèbýiÅ
+ù¥hé³«h§°³h¸·h©f¿h#µd¤k¤k,4­k¯k¹¨c:6$kkkk4¬k¬kSæjVæj* ]ÇkÉk
+5:ÐkÐk>k?¡k\²ùcjµúcjxll6ll
+h$ùkûk]Kll¥k¨k§®§0¯Ê¼ÊlÊlË±ÊëÚlÚl÷êjúêjmlplÈ§kÉ©kA®úI´Oµ m m¡b([`²m²m$ø¨r\¯1¢ÌmÌm>÷­ØmØm³Äf¶Äfk¡m£m³Äg¶Ägk³mµmè³Ì¥¹Ê°ÏÉ¹Dímïm&òµàÉÐ%á"&¬nnç¬þ2¨;ÜºwA§n©n°{±k]»n½nÈ_èA¶º1¨wánãn/åínïn¡²kçnén
+Ô	ïõãÜ­ìÔe³Àgoo"ö¨ümµo·o
+°»ìkÅoÇo,¬©
+¸mÙoÛo¹hpp¹²h²oµ hµoÅ
+ùÝmé³ãm§°ëm¸ïm©f÷m#íiÞpÞp,4çpép¹àh:6$ÐpÐpÓpÕp4æpæpS pV p* ]qq
+5:qq>Ùp?Ûp\²±iÔoµ²i×oxÄqÄq6ÍqÏq
+h$³qµq]KÁqÃq¥Êp¨Êp§®§0¯Ê¼rrË±Êërr÷¤pú¤pm¼qp¼qÈápÉãpA®úI´OµÚrÚr¡b([`ìrìr$ø¨r\¯1¢ss>÷­ss³ük¶ükÂpÛrÝr³ül¶ülÒpírïrè³Ì¥¹Ê°ÏÉ¹D§s©s&òµàÉÐ%á"&¬½s¿sç¬þ2¨;ÜºwAásãs°{±k]õs÷sÈ_èA¶º1¨wtt/å§t©t¡êp¡t£t
+Ô	ïõãÜ­ìk³ølËtÍt"ö¨üËrïtñt
+°»¤qÿtu,¬©
+ðruu¹ÆmÅuÇu¹²×mêtµØmítÅ
+ùsé³s§°£s¸§s©f¯s#¥ovv,4¡v£v¹n:6$vvvv4 v vSÚuVÚu* ]»v½v
+5:ÄvÄv>v?v\²énuµênuxþvþv6ww
+h$ívïv]Kûvýv¥v¨v§®§0¯Ê¼¾w¾wË±ÊëÎwÎw÷ÞuúÞumövpövÈvÉvA®úI´Oµxx¡b([`¦x¦x$ø¨r\¯1¢ÀxÀx>÷­ÌxÌx³´q¶´qúuxx³´r¶´rv§x©xè³Ì¥¹Ê°ÏÉ¹Dáxãx&òµàÉÐ%á"&¬÷xùxç¬þ2¨;ÜºwAyy°{±k]¯y±yÈ_èA¶º1¨wÕy×y/åáyãy¡¢vÛyÝy
+Ô	ïõãÜ­ìÄp³°rzz"ö¨üx©z«z
+°»Üv¹z»z,¬©
+¨xÍzÏz¹þrÿz{¹²s¢zµs¥zÅ
+ùÍxé³Óx§°Ûx¸ßx©fçx#ÝtÒ{Ò{,4Û{Ý{¹Ðs:6$Ä{Ä{Ç{É{4Ú{Ú{S{V{* ]õ{÷{
+5:þ{þ{>Í{?Ï{\²¡tÄzµ¢tÇzx¸|¸|6Á|Ã|
+h$§|©|]Kµ|·|¥¾{¨¾{§®§0¯Ê¼ø|ø|Ë±Êë}}÷{ú{m°|p°|ÈÕ{É×{A®úI´OµÎ}Î}¡b([`à}à}$ø¨r\¯1¢ú}ú}>÷­~~³ìv¶ìv²{Ï}Ñ}³ìw¶ìwÂ{á}ã}è³Ì¥¹Ê°ÏÉ¹D~~&òµàÉÐ%á"&¬±~³~ç¬þ2¨;ÜºwAÕ~×~°{±k]é~ë~È_èA¶º1¨w/å¡Ú{
+Ô	ïõãÜ­ìüu³èw¿Á"ö¨ü»}ãå
+°»|óõ,¬©
+à}¹¶x¹»¹²ÇxÚµÈxÝÅ
+ù~é³~§°~¸~©f~#z,4¹y:6$þþ4SÎVÎ* ]¯±
+5:¸¸>?\²ÙyüµÚyÿxòò6ûý
+h$áã]Kïñ¥ø¨ø§®§0¯Ê¼²²Ë±ÊëÂÂ÷ÒúÒmêpêÈÉA®úI´Oµ¡b([`$ø¨r\¯1¢´´>÷­ÀÀ³¤|¶¤|ê³¤}¶¤}úè³Ì¥¹Ê°ÏÉ¹DÕ×&òµàÉÐ%á"&¬ëíç¬þ2¨;ÜºwA°{±k]£¥È_èA¶º1¨wÉË/åÕ×¡ÏÑ
+Ô	ïõãÜ­ì´{³ }ùû"ö¨üó
+°»Ì­¯,¬©
+ÁÃ¹î}óõ¹²ÿ}µ~Å
+ù½é³Ã§°Ë¸Ï©f×#ÍÆÆ,4ÏÑ¹À~:6$¸¸»½4ÎÎSV* ]éë
+5:òò>Á?Ã\²´µ·x¬¬6µ·
+h$]K©«¥²¨²§®§0¯Ê¼ììË±Êëüü÷úm¤p¤ÈÉÉËA®úI´OµÂÂ¡b([`ÔÔ$ø¨r\¯1¢îî>÷­úú³Ü¶Ü¢ÃÅ³Ü¶Ü²Õ×è³Ì¥¹Ê°ÏÉ¹D&òµàÉÐ%á"&¬¥§ç¬þ2¨;ÜºwAÉË°{±k]ÝßÈ_èA¶º1¨w/å¡Ê
+Ô	ïõãÜ­ìì³Ø³µ"ö¨ü«×Ù
+°»çé,¬©
+Ðûý¹¦­¯¹²·Êµ¸ÍÅ
+ùõé³û§°¸©f#,4¹ø:6$òòõ÷4SÂVÂ* ]£¥
+5:¬¬>û?ý\²ÉìµÊïxææ6ïñ
+h$Õ×]Kãå¥ì¨ì§®§0¯Ê¼¦¦Ë±Êë¶¶÷ÆúÆmÞpÞÈÉA®úI´Oµüü¡b([`$ø¨r\¯1¢¨¨>÷­´´³¶Úýÿ³¶êè³Ì¥¹Ê°ÏÉ¹DÉË&òµàÉÐ%á"&¬ßáç¬þ2¨;ÜºwA°{±k]È_èA¶º1¨w½¿/åÉË¡ÃÅ
+Ô	ïõãÜ­ì¤³íï"ö¨üã
+°»¼¡£,¬©
+µ·¹Þçé¹²ïµðÅ
+ù­é³³§°»¸¿©fÇ#½ºº,4ÃÅ¹°:6$¬¬¯±4ÂÂSüVü* ]Ýß
+5:ææ>µ?·\²¤µ§x  6©«
+h$]K¥¦¨¦§®§0¯Ê¼ààË±Êëðð÷úmpÈ½É¿A®úI´Oµ¶¶¡b([`ÈÈ$ø¨r\¯1¢ââ>÷­îî³Ì¶Ì·¹³Ì¶Ì¢ÉËè³Ì¥¹Ê°ÏÉ¹D&òµàÉÐ%á"&¬ç¬þ2¨;ÜºwA½¿°{±k]ÑÓÈ_èA¶º1¨w÷ù/å¡ºýÿ
+Ô	ïõãÜ­ìÜ³È§©"ö¨üËÍ
+°»ôÛÝ,¬©
+Àïñ¹¡£¹²§ºµ¨½Å
+ùåé³ë§°ó¸÷©fÿ#õôô,4ýÿ¹è:6$ææéë4üüS¶V¶* ]
+5:  >ï?ñ\²¹ÜµºßxÚÚ6ãå
+h$ÉË]K×Ù¥à¨à§®§0¯Ê¼Ë±Êëªª÷ºúºmÒpÒÈ÷ÉùA®úI´Oµðð¡b([`$ø¨r\¯1¢>÷­¨¨³¶Êñó³¶Úè³Ì¥¹Ê°ÏÉ¹D½¿&òµàÉÐ%á"&¬ÓÕç¬þ2¨;ÜºwA÷ù°{±k]È_èA¶º1¨w±³/å½¿¡ò·¹
+Ô	ïõãÜ­ì³áã"ö¨üÓ
+°»¬,¬©
+ø©«¹ÎÛÝ¹²ßòµàõÅ
+ùé³£§°«¸¯©f·#­®®,4·¹¹ :6$  £¥4¶¶SðVð* ]ÑÓ
+5:ÚÚ>©?«\²ñµòx6
+h$]K¥¨§®§0¯Ê¼ÔÔË±Êëää÷ôúômpÈ±É³A®úI´Oµªª¡b([`¼¼$ø¨r\¯1¢ÖÖ>÷­ââ³¼¶¼«­³¼¶¼½¿è³Ì¥¹Ê°ÏÉ¹D÷ù&òµàÉÐ%á"&¬ç¬þ2¨;ÜºwA±³°{±k]ÅÇÈ_èA¶º1¨wëí/å÷ù¡ªñó
+Ô	ïõãÜ­ìÌ³¸  "ö¨ü¿ Á 
+°»äÏ Ñ ,¬©
+°ã å ¹¡¡¹²ª µ­ Å
+ùÕé³Û§°ã¸ç©fï#åè¡è¡,4ñ¡ó¡¹Ø:6$Ú¡Ú¡Ý¡ß¡4ð¡ð¡Sª¡Vª¡* ]¢¢
+5:¢¢>ã¡?å¡\²©Ì µªÏ xÎ¢Î¢6×¢Ù¢
+h$½¢¿¢]KË¢Í¢¥Ô¡¨Ô¡§®§0¯Ê¼££Ë±Êë££÷®¡ú®¡mÆ¢pÆ¢Èë¡Éí¡A®úI´Oµä£ä£¡b([`ö£ö£$ø¨r\¯1¢¤¤>÷­¤¤³ô¶ôº¡å£ç£³ô¶ôÊ¡÷£ù£è³Ì¥¹Ê°ÏÉ¹D±¤³¤&òµàÉÐ%á"&¬Ç¤É¤ç¬þ2¨;ÜºwAë¤í¤°{±k]ÿ¤¥È_èA¶º1¨w¥¥§¥/å±¥³¥¡â¡«¥­¥
+Ô	ïõãÜ­ì³ðÕ¥×¥"ö¨üÃ£ù¥û¥
+°»¢¦¦,¬©
+è£¦¦¹¾Ï¦Ñ¦¹²Ïâ¥µÐå¥Å
+ù¤é³¤§°¤¸¤©f§¤# ¢§¢§,4«§­§¹:6$§§§§4ª§ª§Sä¦Vä¦* ]Å§Ç§
+5:Î§Î§>§?§\²á¦µâ¦x¨¨6¨¨
+h$÷§ù§]K¨¨¥§¨§§®§0¯Ê¼È¨È¨Ë±ÊëØ¨Ø¨÷è¦úè¦m¨p¨È¥§É§§A®úI´Oµ©©¡b([`°©°©$ø¨r\¯1¢Ê©Ê©>÷­Ö©Ö©³¬¢¶¬¢ò¦©¡©³¬£¶¬£§±©³©è³Ì¥¹Ê°ÏÉ¹Dë©í©&òµàÉÐ%á"&¬ªªç¬þ2¨;ÜºwA¥ª§ª°{±k]¹ª»ªÈ_èA¶º1¨wßªáª/åëªíª¡§åªçª
+Ô	ïõãÜ­ì¼¡³¨£««"ö¨üû¨³«µ«
+°»Ô§Ã«Å«,¬©
+ ©×«Ù«¹ö£¬¬¹²¤«µ¤«Å
+ùÅ©é³Ë©§°Ó©¸×©©fß©#Õ¥Ü¬Ü¬,4å¬ç¬¹È¤:6$Î¬Î¬Ñ¬Ó¬4ä¬ä¬S¬V¬* ]ÿ¬­
+5:­­>×¬?Ù¬\²¥¼«µ¥¿«xÂ­Â­6Ë­Í­
+h$±­³­]K¿­Á­¥È¬¨È¬§®§0¯Ê¼®®Ë±Êë®®÷¢¬ú¢¬mº­pº­Èß¬Éá¬A®úI´OµØ®Ø®¡b([`ê®ê®$ø¨r\¯1¢¯¯>÷­¯¯³ä§¶ä§ª¬Ù®Û®³ä¨¶ä¨º¬ë®í®è³Ì¥¹Ê°ÏÉ¹D¥¯§¯&òµàÉÐ%á"&¬»¯½¯ç¬þ2¨;ÜºwAß¯á¯°{±k]ó¯õ¯È_èA¶º1¨w°°/å¥°§°¡Ò¬°¡°
+Ô	ïõãÜ­ìô¦³à¨É°Ë°"ö¨ü³®í°ï°
+°»­ý°ÿ°,¬©
+Ø®±±¹®©Ã±Å±¹²¿©Ò°µÀ©Õ°Å
+ùý®é³¯§°¯¸¯©f¯#«²²,4²¡²¹ª:6$²²²²4²²SØ±VØ±* ]¹²»²
+5:Â²Â²>²?²\²Ñªô°µÒª÷°xü²ü²6³³
+h$ë²í²]Kù²û²¥²¨²§®§0¯Ê¼¼³¼³Ë±ÊëÌ³Ì³÷Ü±úÜ±mô²pô²È²É²A®úI´Oµ´´¡b([`¤´¤´$ø¨r\¯1¢¾´¾´>÷­Ê´Ê´³­¶­â±´´³®¶®ò±¥´§´è³Ì¥¹Ê°ÏÉ¹Dß´á´&òµàÉÐ%á"&¬õ´÷´ç¬þ2¨;ÜºwAµµ°{±k]­µ¯µÈ_èA¶º1¨wÓµÕµ/åßµáµ¡²ÙµÛµ
+Ô	ïõãÜ­ì¬¬³®¶¶"ö¨üë³§¶©¶
+°»Ä²·¶¹¶,¬©
+´Ë¶Í¶¹æ®ý¶ÿ¶¹²÷®¶µø®¶Å
+ùµ´é³»´§°Ã´¸Ç´©fÏ´#Å°Ð·Ð·,4Ù·Û·¹¸¯:6$Â·Â·Å·Ç·4Ø·Ø·S·V·* ]ó·õ·
+5:ü·ü·>Ë·?Í·\²°¬¶µ°¯¶x¶¸¶¸6¿¸Á¸
+h$¥¸§¸]K³¸µ¸¥¼·¨¼·§®§0¯Ê¼ö¸ö¸Ë±Êë¹¹÷·ú·m®¸p®¸ÈÓ·ÉÕ·A®úI´OµÌ¹Ì¹¡b([`Þ¹Þ¹$ø¨r\¯1¢ø¹ø¹>÷­ºº³Ô²¶Ô²·Í¹Ï¹³Ô³¶Ô³ª·ß¹á¹è³Ì¥¹Ê°ÏÉ¹Dºº&òµàÉÐ%á"&¬¯º±ºç¬þ2¨;ÜºwAÓºÕº°{±k]çºéºÈ_èA¶º1¨w»»/å»»¡Â·»»
+Ô	ïõãÜ­ìä±³Ð³½»¿»"ö¨ü£¹á»ã»
+°»ü·ñ»ó»,¬©
+È¹¼¼¹´·¼¹¼¹²¯´Â»µ°´Å»Å
+ùí¹é³ó¹§°û¹¸ÿ¹©fº#ýµ½½,4½½¹ð´:6$ü¼ü¼ÿ¼½4½½SÌ¼VÌ¼* ]­½¯½
+5:¶½¶½>½?½\²Áµä»µÂµç»xð½ð½6ù½û½
+h$ß½á½]Kí½ï½¥ö¼¨ö¼§®§0¯Ê¼°¾°¾Ë±ÊëÀ¾À¾÷Ð¼úÐ¼mè½pè½È½É½A®úI´Oµ¿¿¡b([`¿¿$ø¨r\¯1¢²¿²¿>÷­¾¿¾¿³¸¶¸Ò¼¿¿³¹¶¹â¼¿¿è³Ì¥¹Ê°ÏÉ¹DÓ¿Õ¿&òµàÉÐ%á"&¬é¿ë¿ç¬þ2¨;ÜºwAÀÀ°{±k]¡À£ÀÈ_èA¶º1¨wÇÀÉÀ/åÓÀÕÀ¡ú¼ÍÀÏÀ
+Ô	ïõãÜ­ì·³¹÷ÀùÀ"ö¨üÛ¾ÁÁ
+°»´½«Á­Á,¬©
+¿¿ÁÁÁ¹Ö¹ñÁóÁ¹²ç¹úÀµè¹ýÀÅ
+ù¥¿é³«¿§°³¿¸·¿©f¿¿#µ»ÄÂÄÂ,4ÍÂÏÂ¹¨º:6$¶Â¶Â¹Â»Â4ÌÂÌÂSÂVÂ* ]çÂéÂ
+5:ðÂðÂ>¿Â?ÁÂ\²ùºÁµúºÁxªÃªÃ6³ÃµÃ
+h$ÃÃ]K§Ã©Ã¥°Â¨°Â§®§0¯Ê¼êÃêÃË±ÊëúÃúÃ÷ÂúÂm¢Ãp¢ÃÈÇÂÉÉÂA®úI´OµÀÄÀÄ¡b([`ÒÄÒÄ$ø¨r\¯1¢ìÄìÄ>÷­øÄøÄ³Ä½¶Ä½ÂÁÄÃÄ³Ä¾¶Ä¾ÂÓÄÕÄè³Ì¥¹Ê°ÏÉ¹DÅÅ&òµàÉÐ%á"&¬£Å¥Åç¬þ2¨;ÜºwAÇÅÉÅ°{±k]ÛÅÝÅÈ_èA¶º1¨wÆÆ/åÆÆ¡²ÂÆÆ
+Ô	ïõãÜ­ìÔ¼³À¾±Æ³Æ"ö¨üÄÕÆ×Æ
+°»ìÂåÆçÆ,¬©
+¸ÄùÆûÆ¹¿«Ç­Ç¹²¿²Æµ ¿µÆÅ
+ùÝÄé³ãÄ§°ëÄ¸ïÄ©f÷Ä#íÀþÇþÇ,4ÈÈ¹à¿:6$ðÇðÇóÇõÇ4ÈÈSÀÇVÀÇ* ]¡È£È
+5:ªÈªÈ>ùÇ?ûÇ\²±ÀÔÆµ²À×ÆxäÈäÈ6íÈïÈ
+h$ÓÈÕÈ]KáÈãÈ¥êÇ¨êÇ§®§0¯Ê¼¤É¤ÉË±Êë´É´É÷ÄÇúÄÇmÜÈpÜÈÈÈÉÈA®úI´OµúÉúÉ¡b([`ÊÊ$ø¨r\¯1¢¦Ê¦Ê>÷­²Ê²Ê³üÂ¶üÂÂÇûÉýÉ³üÃ¶üÃÒÇÊÊè³Ì¥¹Ê°ÏÉ¹DÇÊÉÊ&òµàÉÐ%á"&¬ÝÊßÊç¬þ2¨;ÜºwAËË°{±k]ËËÈ_èA¶º1¨w»Ë½Ë/åÇËÉË¡êÇÁËÃË
+Ô	ïõãÜ­ìÂ³øÃëËíË"ö¨üËÉÌÌ
+°»¤ÈÌ¡Ì,¬©
+ðÉ³ÌµÌ¹ÆÄåÌçÌ¹²×ÄêËµØÄíËÅ
+ùÊé³Ê§°£Ê¸§Ê©f¯Ê#¥Æ¸Í¸Í,4ÁÍÃÍ¹Å:6$ªÍªÍ­Í¯Í4ÀÍÀÍSúÌVúÌ* ]ÛÍÝÍ
+5:äÍäÍ>³Í?µÍ\²éÅÌµêÅÌxÎÎ6§Î©Î
+h$ÎÎ]KÎÎ¥¤Í¨¤Í§®§0¯Ê¼ÞÎÞÎË±ÊëîÎîÎ÷þÌúþÌmÎpÎÈ»ÍÉ½ÍA®úI´Oµ´Ï´Ï¡b([`ÆÏÆÏ$ø¨r\¯1¢àÏàÏ>÷­ìÏìÏ³´È¶´ÈúÌµÏ·Ï³´É¶´ÉÍÇÏÉÏè³Ì¥¹Ê°ÏÉ¹DÐÐ&òµàÉÐ%á"&¬ÐÐç¬þ2¨;ÜºwA»Ð½Ð°{±k]ÏÐÑÐÈ_èA¶º1¨wõÐ÷Ð/åÑÑ¡¢ÍûÐýÐ
+Ô	ïõãÜ­ìÄÇ³°É¥Ñ§Ñ"ö¨üÏÉÑËÑ
+°»ÜÍÙÑÛÑ,¬©
+¨ÏíÑïÑ¹þÉÒ¡Ò¹²Ê¢ÑµÊ¥ÑÅ
+ùÍÏé³ÓÏ§°ÛÏ¸ßÏ©fçÏ#ÝËòÒòÒ,4ûÒýÒ¹ÐÊ:6$äÒäÒçÒéÒ4úÒúÒS´ÒV´Ò* ]ÓÓ
+5:ÓÓ>íÒ?ïÒ\²¡ËÄÑµ¢ËÇÑxØÓØÓ6áÓãÓ
+h$ÇÓÉÓ]KÕÓ×Ó¥ÞÒ¨ÞÒ§®§0¯Ê¼ÔÔË±Êë¨Ô¨Ô÷¸Òú¸ÒmÐÓpÐÓÈõÒÉ÷ÒA®úI´OµîÔîÔ¡b([`ÕÕ$ø¨r\¯1¢ÕÕ>÷­¦Õ¦Õ³ìÍ¶ìÍ²ÒïÔñÔ³ìÎ¶ìÎÂÒÕÕè³Ì¥¹Ê°ÏÉ¹D»Õ½Õ&òµàÉÐ%á"&¬ÑÕÓÕç¬þ2¨;ÜºwAõÕ÷Õ°{±k]ÖÖÈ_èA¶º1¨w¯Ö±Ö/å»Ö½Ö¡ÚÒµÖ·Ö
+Ô	ïõãÜ­ìüÌ³èÎßÖáÖ"ö¨ü»Ô××
+°»Ó××,¬©
+àÔ§×©×¹¶ÏÙ×Û×¹²ÇÏÚÖµÈÏÝÖÅ
+ùÕé³Õ§°Õ¸Õ©fÕ#Ñ¬Ø¬Ø,4µØ·Ø¹Ð:6$ØØ¡Ø£Ø4´Ø´ØSî×Vî×* ]ÏØÑØ
+5:ØØØØ>§Ø?©Ø\²ÙÐüÖµÚÐÿÖxÙÙ6ÙÙ
+h$ÙÙ]KÙÙ¥Ø¨Ø§®§0¯Ê¼ÒÙÒÙË±ÊëâÙâÙ÷ò×úò×mÙpÙÈ¯ØÉ±ØA®úI´Oµ¨Ú¨Ú¡b([`ºÚºÚ$ø¨r\¯1¢ÔÚÔÚ>÷­àÚàÚ³¤Ó¶¤Óê×©Ú«Ú³¤Ô¶¤Ôú×»Ú½Úè³Ì¥¹Ê°ÏÉ¹DõÚ÷Ú&òµàÉÐ%á"&¬ÛÛç¬þ2¨;ÜºwA¯Û±Û°{±k]ÃÛÅÛÈ_èA¶º1¨wéÛëÛ/åõÛ÷Û¡ØïÛñÛ
+Ô	ïõãÜ­ì´Ò³ ÔÜÜ"ö¨üóÙ½Ü¿Ü
+°»ÌØÍÜÏÜ,¬©
+ÚáÜãÜ¹îÔÝÝ¹²ÿÔÜµÕÜÅ
+ù½Úé³ÃÚ§°ËÚ¸ÏÚ©f×Ú#ÍÖæÝæÝ,4ïÝñÝ¹ÀÕ:6$ØÝØÝÛÝÝÝ4îÝîÝS¨ÝV¨Ý* ]ÞÞ
+5:ÞÞ>áÝ?ãÝ\²Ö´ÜµÖ·ÜxÌÞÌÞ6ÕÞ×Þ
+h$»Þ½Þ]KÉÞËÞ¥ÒÝ¨ÒÝ§®§0¯Ê¼ßßË±Êëßß÷¬Ýú¬ÝmÄÞpÄÞÈéÝÉëÝA®úI´Oµâßâß¡b([`ôßôß$ø¨r\¯1¢àà>÷­àà³ÜØ¶ÜØ¢Ýãßåß³ÜÙ¶ÜÙ²Ýõß÷ßè³Ì¥¹Ê°ÏÉ¹D¯à±à&òµàÉÐ%á"&¬ÅàÇàç¬þ2¨;ÜºwAéàëà°{±k]ýàÿàÈ_èA¶º1¨w£á¥á/å¯á±á¡ÊÝ©á«á
+Ô	ïõãÜ­ìì×³ØÙÓáÕá"ö¨ü«ß÷áùá
+°»Þââ,¬©
+Ðßââ¹¦ÚÍâÏâ¹²·ÚÊáµ¸ÚÍáÅ
+ùõßé³ûß§°à¸à©fà#Ü ã ã,4©ã«ã¹øÚ:6$ãããã4¨ã¨ãSââVââ* ]ÃãÅã
+5:ÌãÌã>ã?ã\²ÉÛìáµÊÛïáxää6ää
+h$õã÷ã]Kää¥ã¨ã§®§0¯Ê¼ÆäÆäË±ÊëÖäÖä÷æâúæâmþãpþãÈ£ãÉ¥ãA®úI´Oµåå¡b([`®å®å$ø¨r\¯1¢ÈåÈå>÷­ÔåÔå³Þ¶ÞÚâåå³ß¶ßêâ¯å±åè³Ì¥¹Ê°ÏÉ¹Déåëå&òµàÉÐ%á"&¬ÿåæç¬þ2¨;ÜºwA£æ¥æ°{±k]·æ¹æÈ_èA¶º1¨wÝæßæ/åéæëæ¡ããæåæ
+Ô	ïõãÜ­ì¤Ý³ßçç"ö¨üãä±ç³ç
+°»¼ãÁçÃç,¬©
+åÕç×ç¹Þßèè¹²ïßçµðßçÅ
+ù­åé³³å§°»å¸¿å©fÇå#½áÚèÚè,4ãèåè¹°à:6$ÌèÌèÏèÑè4âèâèSèVè* ]ýèÿè
+5:éé>Õè?×è\²á¤çµá§çxÀéÀé6ÉéËé
+h$¯é±é]K½é¿é¥Æè¨Æè§®§0¯Ê¼êêË±Êëêê÷ èú èm¸ép¸éÈÝèÉßèA®úI´OµÖêÖê¡b([`èêèê$ø¨r\¯1¢ëë>÷­ëë³Ìã¶Ìãè×êÙê³Ìä¶Ìä¢èéêëêè³Ì¥¹Ê°ÏÉ¹D£ë¥ë&òµàÉÐ%á"&¬¹ë»ëç¬þ2¨;ÜºwAÝëßë°{±k]ñëóëÈ_èA¶º1¨wìì/å£ì¥ì¡ºèìì
+Ô	ïõãÜ­ìÜâ³ÈäÇìÉì"ö¨üêëìíì
+°»ôèûìýì,¬©
+Àêíí¹åÁíÃí¹²§åºìµ¨å½ìÅ
+ùåêé³ëê§°óê¸÷ê©fÿê#õæîî,4îî¹èå:6$îîîî4îîSÖíVÖí* ]·î¹î
+5:ÀîÀî>î?î\²¹æÜìµºæßìxúîúî6ïï
+h$éîëî]K÷îùî¥î¨î§®§0¯Ê¼ºïºïË±ÊëÊïÊï÷ÚíúÚímòîpòîÈîÉîA®úI´Oµðð¡b([`¢ð¢ð$ø¨r\¯1¢¼ð¼ð>÷­ÈðÈð³é¶éÊíðð³ê¶êÚí£ð¥ðè³Ì¥¹Ê°ÏÉ¹DÝðßð&òµàÉÐ%á"&¬óðõðç¬þ2¨;ÜºwAññ°{±k]«ñ­ñÈ_èA¶º1¨wÑñÓñ/åÝñßñ¡òí×ñÙñ
+Ô	ïõãÜ­ìè³êòò"ö¨üÓï¥ò§ò
+°»¬îµò·ò,¬©
+øïÉòËò¹Îêûòýò¹²ßêòñµàêõñÅ
+ùðé³£ð§°«ð¸¯ð©f·ð#­ìÎóÎó,4×óÙó¹ ë:6$ÀóÀóÃóÅó4ÖóÖóSóVó* ]ñóóó
+5:úóúó>Éó?Ëó\²ñëòµòëòx´ô´ô6½ô¿ô
+h$£ô¥ô]K±ô³ô¥ºó¨ºó§®§0¯Ê¼ôôôôË±Êëõõ÷óúóm¬ôp¬ôÈÑóÉÓóA®úI´OµÊõÊõ¡b([`ÜõÜõ$ø¨r\¯1¢öõöõ>÷­öö³¼î¶¼îóËõÍõ³¼ï¶¼ïóÝõßõè³Ì¥¹Ê°ÏÉ¹Döö&òµàÉÐ%á"&¬­ö¯öç¬þ2¨;ÜºwAÑöÓö°{±k]åöçöÈ_èA¶º1¨w÷÷/å÷÷¡ªó÷÷
+Ô	ïõãÜ­ìÌí³¸ï»÷½÷"ö¨üõß÷á÷
+°»äóï÷ñ÷,¬©
+°õøø¹ðµø·ø¹²ðª÷µð­÷Å
+ùÕõé³Ûõ§°ãõ¸çõ©fïõ#åñùù,4ùù¹Øð:6$úøúøýøÿø4ùùSÊøVÊø* ]«ù­ù
+5:´ù´ù>ù?ù\²©ñÌ÷µªñÏ÷xîùîù6÷ùùù
+h$Ýùßù]Këùíù¥ôø¨ôø§®§0¯Ê¼®ú®úË±Êë¾ú¾ú÷ÎøúÎømæùpæùÈùÉùA®úI´Oµûû¡b([`ûû$ø¨r\¯1¢°û°û>÷­¼û¼û³ôó¶ôóºøûû³ôô¶ôôÊøûûè³Ì¥¹Ê°ÏÉ¹DÑûÓû&òµàÉÐ%á"&¬çûéûç¬þ2¨;ÜºwAüü°{±k]ü¡üÈ_èA¶º1¨wÅüÇü/åÑüÓü¡âøËüÍü
+Ô	ïõãÜ­ìó³ðôõü÷ü"ö¨üÃúýý
+°»ù©ý«ý,¬©
+èú½ý¿ý¹¾õïýñý¹²ÏõâüµÐõåüÅ
+ùûé³û§°û¸û©f§û#÷ÂþÂþ,4ËþÍþ¹ö:6$´þ´þ·þ¹þ4ÊþÊþSþVþ* ]åþçþ
+5:îþîþ>½þ?¿þ\²áöýµâöýx¨ÿ¨ÿ6±ÿ³ÿ
+h$ÿÿ]K¥ÿ§ÿ¥®þ¨®þ§®§0¯Ê¼èÿèÿË±Êëøÿøÿ÷þúþm ÿp ÿÈÅþÉÇþA®úI´Oµ¾¾¡b([`ÐÐ$ø¨r\¯1¢êê>÷­öö³¬ù¶¬ùòý¿Á³¬ú¶¬úþÑÓè³Ì¥¹Ê°ÏÉ¹D&òµàÉÐ%á"&¬¡£ç¬þ2¨;ÜºwAÅÇ°{±k]ÙÛÈ_èA¶º1¨wÿ/å¡þ
+Ô	ïõãÜ­ì¼ø³¨ú¯±"ö¨üûÿÓÕ
+°»Ôþãå,¬©
+ ÷ù¹öú©«¹²ûµûÅ
+ùÅé³Ë§°Ó¸×©fß#Õüüü,4¹Èû:6$îîñó4S¾V¾* ]¡
+5:¨¨>÷?ù\²ü¼µü¿xââ6ëí
+h$ÑÓ]Kßá¥è¨è§®§0¯Ê¼¢¢Ë±Êë²²÷ÂúÂmÚpÚÈÿÉA®úI´Oµøø¡b([`$ø¨r\¯1¢¤¤>÷­°°³äþ¶äþªùû³äÿ¶äÿºè³Ì¥¹Ê°ÏÉ¹DÅÇ&òµàÉÐ%á"&¬ÛÝç¬þ2¨;ÜºwAÿ°{±k]È_èA¶º1¨w¹»/åÅÇ¡Ò¿Á
+Ô	ïõãÜ­ìôý³àÿéë"ö¨ü³
+°»,¬©
+Ø±³¹®ãå¹²¿ÒµÀÕÅ
+ùýé³§°¸©f#¶¶,4¿Á¹:6$¨¨«­4¾¾SøVø* ]ÙÛ
+5:ââ>±?³\²ÑôµÒ÷x6¥§
+h$]K¥¢¨¢§®§0¯Ê¼ÜÜË±Êëìì÷üúümpÈ¹É»A®úI´Oµ²²¡b([`ÄÄ$ø¨r\¯1¢ÞÞ>÷­êê³¶â³µ³¶òÅÇè³Ì¥¹Ê°ÏÉ¹Dÿ&òµàÉÐ%á"&¬ç¬þ2¨;ÜºwA¹»°{±k]ÍÏÈ_èA¶º1¨wóõ/åÿ¡ùû
+Ô	ïõãÜ­ì¬³£¥"ö¨üëÇÉ
+°»Ä×Ù,¬©
+ëí¹æ¹²÷µøÅ
+ùµé³»§°Ã¸Ç©fÏ#Åðð,4ùû¹¸:6$ââåç4øøS²V²* ]
+5:>ë?í\²¬µ¯xÖÖ6ßá
+h$ÅÇ]KÓÕ¥Ü¨Ü§®§0¯Ê¼Ë±Êë¦¦÷¶ú¶mÎpÎÈóÉõA®úI´Oµìì¡b([`þþ$ø¨r\¯1¢>÷­¤¤³Ô¶Ôíï³Ô¶Ôªÿè³Ì¥¹Ê°ÏÉ¹D¹»&òµàÉÐ%á"&¬ÏÑç¬þ2¨;ÜºwAóõ°{±k]È_èA¶º1¨w­¯/å¹»¡Â³µ
+Ô	ïõãÜ­ìä³ÐÝß"ö¨ü£
+°»ü,¬©
+È¥§¹×Ù¹²¯Âµ°ÅÅ
+ùíé³ó§°û¸ÿ©f#ýªª,4³µ¹ð:6$¡4²²SìVì* ]ÍÏ
+5:ÖÖ>¥?§\²ÁäµÂçx6
+h$ÿ]K¥¨§®§0¯Ê¼ÐÐË±Êëàà÷ðúðmpÈ­É¯A®úI´Oµ¦¦¡b([`¸¸$ø¨r\¯1¢ÒÒ>÷­ÞÞ³¶Ò§©³¶â¹»è³Ì¥¹Ê°ÏÉ¹Dóõ&òµàÉÐ%á"&¬ç¬þ2¨;ÜºwA­¯°{±k]ÁÃÈ_èA¶º1¨wçé/åóõ¡úíï
+Ô	ïõãÜ­ì³"ö¨üÛ»½
+°»´ËÍ,¬©
+ßá¹Ö¹²çúµèýÅ
+ù¥é³«§°³¸·©f¿#µää,4íï¹¨:6$ÖÖÙÛ4ììS¦V¦* ]
+5:>ß?á\²ùµúxÊÊ6ÓÕ
+h$¹»]KÇÉ¥Ð¨Ð§®§0¯Ê¼Ë±Êë÷ªúªmÂpÂÈçÉéA®úI´Oµàà¡b([`òò$ø¨r\¯1¢>÷­³Ä¶Äáã³Ä¶Äóõè³Ì¥¹Ê°ÏÉ¹D­¯&òµàÉÐ%á"&¬ÃÅç¬þ2¨;ÜºwAçé°{±k]ûýÈ_èA¶º1¨w¡£/å­¯¡²§©
+Ô	ïõãÜ­ìÔ³ÀÑÓ"ö¨üõ÷
+°»ì,¬©
+¸¹ËÍ¹²²µ µÅ
+ùÝé³ã§°ë¸ï©f÷#í,4§©¹à:6$4¦¦SàVà* ]ÁÃ
+5:ÊÊ>?\²±Ôµ²×x  6  
+h$óõ]K  ¥¨§®§0¯Ê¼Ä Ä Ë±ÊëÔ Ô ÷äúämüpüÈ¡É£A®úI´Oµ¡¡¡b([`¬¡¬¡$ø¨r\¯1¢Æ¡Æ¡>÷­Ò¡Ò¡³ü¶üÂ¡¡³ü¶üÒ­¡¯¡è³Ì¥¹Ê°ÏÉ¹Dç¡é¡&òµàÉÐ%á"&¬ý¡ÿ¡ç¬þ2¨;ÜºwA¡¢£¢°{±k]µ¢·¢È_èA¶º1¨wÛ¢Ý¢/åç¢é¢¡êá¢ã¢
+Ô	ïõãÜ­ì³ø££"ö¨üË ¯£±£
+°»¤¿£Á£,¬©
+ð Ó£Õ£¹Æ¤¤¹²×ê¢µØí¢Å
+ù¡é³¡§°£¡¸§¡©f¯¡#¥Ø¤Ø¤,4á¤ã¤¹:6$Ê¤Ê¤Í¤Ï¤4à¤à¤S¤V¤* ]û¤ý¤
+5:¥¥>Ó¤?Õ¤\²é£µê£x¾¥¾¥6Ç¥É¥
+h$­¥¯¥]K»¥½¥¥Ä¤¨Ä¤§®§0¯Ê¼þ¥þ¥Ë±Êë¦¦÷¤ú¤m¶¥p¶¥ÈÛ¤ÉÝ¤A®úI´OµÔ¦Ô¦¡b([`æ¦æ¦$ø¨r\¯1¢§§>÷­§§³´¶´ú£Õ¦×¦³´ ¶´ ¤ç¦é¦è³Ì¥¹Ê°ÏÉ¹D¡§£§&òµàÉÐ%á"&¬·§¹§ç¬þ2¨;ÜºwAÛ§Ý§°{±k]ï§ñ§È_èA¶º1¨w¨¨/å¡¨£¨¡¢¤¨¨
+Ô	ïõãÜ­ìÄ³° Å¨Ç¨"ö¨ü¦é¨ë¨
+°»Ü¤ù¨û¨,¬©
+¨¦©©¹þ ¿©Á©¹²¡¢¨µ¡¥¨Å
+ùÍ¦é³Ó¦§°Û¦¸ß¦©fç¦#Ý¢ªª,4ªª¹Ð¡:6$ªªªª4ªªSÔ©VÔ©* ]µª·ª
+5:¾ª¾ª>ª?ª\²¡¢Ä¨µ¢¢Ç¨xøªøª6««
+h$çªéª]Kõª÷ª¥þ©¨þ©§®§0¯Ê¼¸«¸«Ë±ÊëÈ«È«÷Ø©úØ©mðªpðªÈªÉªA®úI´Oµ¬¬¡b([` ¬ ¬$ø¨r\¯1¢º¬º¬>÷­Æ¬Æ¬³ì¤¶ì¤²©¬¬³ì¥¶ì¥Â©¡¬£¬è³Ì¥¹Ê°ÏÉ¹DÛ¬Ý¬&òµàÉÐ%á"&¬ñ¬ó¬ç¬þ2¨;ÜºwA­­°{±k]©­«­È_èA¶º1¨wÏ­Ñ­/åÛ­Ý­¡Ú©Õ­×­
+Ô	ïõãÜ­ìü£³è¥ÿ­®"ö¨ü»«£®¥®
+°»ª³®µ®,¬©
+à«Ç®É®¹¶¦ù®û®¹²Ç¦Ú­µÈ¦Ý­Å
+ù¬é³¬§°¬¸¬©f¬#¨Ì¯Ì¯,4Õ¯×¯¹§:6$¾¯¾¯Á¯Ã¯4Ô¯Ô¯S¯V¯* ]ï¯ñ¯
+5:ø¯ø¯>Ç¯?É¯\²Ù§ü­µÚ§ÿ­x²°²°6»°½°
+h$¡°£°]K¯°±°¥¸¯¨¸¯§®§0¯Ê¼ò°ò°Ë±Êë±±÷¯ú¯mª°pª°ÈÏ¯ÉÑ¯A®úI´OµÈ±È±¡b([`Ú±Ú±$ø¨r\¯1¢ô±ô±>÷­²²³¤ª¶¤ªê®É±Ë±³¤«¶¤«ú®Û±Ý±è³Ì¥¹Ê°ÏÉ¹D²²&òµàÉÐ%á"&¬«²­²ç¬þ2¨;ÜºwAÏ²Ñ²°{±k]ã²å²È_èA¶º1¨w³³/å³³¡¯³³
+Ô	ïõãÜ­ì´©³ «¹³»³"ö¨üó°Ý³ß³
+°»Ì¯í³ï³,¬©
+±´´¹î«³´µ´¹²ÿ«³µ¬³Å
+ù½±é³Ã±§°Ë±¸Ï±©f×±#Í­µµ,4µµ¹À¬:6$ø´ø´û´ý´4µµSÈ´VÈ´* ]©µ«µ
+5:²µ²µ>µ?µ\²­´³µ­·³xìµìµ6õµ÷µ
+h$ÛµÝµ]Kéµëµ¥ò´¨ò´§®§0¯Ê¼¬¶¬¶Ë±Êë¼¶¼¶÷Ì´úÌ´mäµpäµÈµÉµA®úI´Oµ··¡b([`··$ø¨r\¯1¢®·®·>÷­º·º·³Ü¯¶Ü¯¢´··³Ü°¶Ü°²´··è³Ì¥¹Ê°ÏÉ¹DÏ·Ñ·&òµàÉÐ%á"&¬å·ç·ç¬þ2¨;ÜºwA¸¸°{±k]¸¸È_èA¶º1¨wÃ¸Å¸/åÏ¸Ñ¸¡Ê´É¸Ë¸
+Ô	ïõãÜ­ìì®³Ø°ó¸õ¸"ö¨ü«¶¹¹
+°»µ§¹©¹,¬©
+Ð¶»¹½¹¹¦±í¹ï¹¹ý°¹±·ø°·ù°¹ï°¹ò°·ú°·û°¹í°¹ð°·¿±»Â±¹ê°·ë°¹ç°¹ê°·¤±·¥±¹×°¹Ú°·Ô°·Õ°¹Ò°·Ó°¹Ð°·Ñ°¹ó±»ö±¹¹°¹¼°·¯°¹²°·¥²»¨²¹±¹±·ö±·÷±¹°¹¢°·°¹°·ÿ¯¹°·ù¯¹ü¯·ò¯·ó¯¹ê¯·ë¯¹Ê¯·Ë¯¹¶¯··¯¹¯·¯¹¯·¯¹ø®·ù®¹î®·ï®¹ê®·ë®¹Î®·Ï®¹¸®·¹®¹¬®·­®¹¢®·£®¹ ®·¡®¹§ë­ó
+î­ñ
+æ­ñ
+ç­ó
+Ý­ó
+à­ñ
+è­ñ
+é­ó
+Û­ó
+Þ­ñ
+­®õ
+°®ó
+Ø­ñ
+Ù­ó
+Õ­ó
+Ø­ñ
+®ñ
+®ó
+Å­ó
+È­ñ
+Â­ñ
+Ã­ó
+À­ñ
+Á­ó
+¾­ñ
+¿­ó
+á®õ
+ä®ó
+§­ó
+ª­ñ
+­ó
+ ­ñ
+¯õ
+¯ó
+®ó
+®ñ
+ä®ñ
+å®ó
+­ó
+­ñ
+­ó
+­ñ
+í¬ó
+ð¬ñ
+ç¬ó
+ê¬ñ
+à¬ñ
+á¬ó
+Ø¬ñ
+Ù¬ó
+¸¬ñ
+¹¬ó
+¤¬ñ
+¥¬ó
+¬ñ
+¬ó
+ú«ñ
+û«ó
+æ«ñ
+ç«ó
+Ü«ñ
+Ý«ó
+Ø«ñ
+Ù«ó
+¼«ñ
+½«ó
+¦«ñ
+§«ó
+«ñ
+«ó
+«ñ
+«ó
+«ñ
+«ó
+§Ùª­Üª«Ôª«Õª­Ëª­Îª«Öª«×ª­Éª­Ìª««¯«­Æª«Çª­Ãª­Æª««««­³ª­¶ª«°ª«±ª­®ª«¯ª­¬ª«­ª­Ï«¯Ò«­ª­ª«ª­ª«¬¯¬­÷ª­úª«Ò««Ó«­û©­þ©«ï©­ò©«Û©­Þ©«Õ©­Ø©«Î©«Ï©­Æ©«Ç©­¦©«§©­©«©­ú¨«û¨­è¨«é¨­Ô¨«Õ¨­Ê¨«Ë¨­Æ¨«Ç¨­ª¨««¨­¨«¨­¨«¨­þ§«ÿ§­ü§«ý§­§Ç§çÊ§åÂ§åÃ§ç¹§ç¼§åÄ§åÅ§ç·§çº§å¨é¨ç´§åµ§ç±§ç´§åî§åï§ç¡§ç¤§å§å§ç§å§ç§å§ç½¨éÀ¨ç§ç§åù¦çü¦åï¨éò¨çå§çè§åÀ¨åÁ¨çé¦çì¦åÝ¦çà¦åÉ¦çÌ¦åÃ¦çÆ¦å¼¦å½¦ç´¦åµ¦ç¦å¦ç¦å¦çè¥åé¥çÖ¥å×¥çÂ¥åÃ¥ç¸¥å¹¥ç´¥åµ¥ç¥å¥ç¥å¥çö¤å÷¤çì¤åí¤çê¤åë¤ç§µ¤¡¸¤°¤±¤¡§¤¡ª¤²¤³¤¡¥¤¡¨¤÷¤£ú¤¡¢¤£¤¡¤¡¢¤Ü¤Ý¤¡¤¡¤¤¤¡¤¤¡¤¤¡«¥£®¥¡ñ£¡ô£ç£¡ê£Ý¥£à¥¡Ó¤¡Ö¤®¥¯¥¡×£¡Ú£Ë£¡Î£·£¡º£±£¡´£ª£«£¡¢£££¡££¡î¢ï¢¡Ö¢×¢¡Ä¢Å¢¡°¢±¢¡¦¢§¢¡¢¢£¢¡¢¢¡ð¡ñ¡¡ä¡å¡¡Ú¡Û¡¡Ø¡Ù¡¡§£¡Û ¦¡Ù ¡Ù ¡Û ¡Û ¡Ù  ¡Ù ¡¡Û ¡Û ¡Ù å¡Ý è¡Û ¡Ù ¡Û ¡Û ¡Ù Ê¡Ù Ë¡Û ý Û ¡Ù ú Ù û Û ø Ù ù Û ö Ù ÷ Û ¢Ý ¢Û ß Û â Ù Õ Û Ø Ù Ë¢Ý Î¢Û Á¡Û Ä¡Ù ¢Ù ¢Û Å Û È Ù ¹ Û ¼ Ù ¥ Û ¨ Ù  Û ¢ Ù  Ù  Û  Ù  Û ðÙ ñÛ ÜÙ ÝÛ ÄÙ ÅÛ ²Ù ³Û Ù Û Ù Û Ù Û ôÙ õÛ ÞÙ ßÛ ÒÙ ÓÛ ÈÙ ÉÛ ÆÙ ÇÛ §&&&&&&&&&&Ó&Ö&þ&ÿ&û&þ&¸&¹&ë&î&è&é&æ&ç&ä&å&&&Í&Ð&Ã&Æ&¹&¼&¯&²&&&³&¶&§&ª&&&&&&&þ&ÿ&Þ&ß&Ê&Ë&²&³& &¡&&&&&þ&ÿ&â&ã&Ì&Í&À&Á&¶&·&´&µ&§ÿÏ+Í+úÍ+ûÏ+ñÏ+ôÍ+üÍ+ýÏ+ïÏ+òÍ+ÁÑ+ÄÏ+ìÍ+íÏ+éÏ+ìÍ+¦Í+§Ï+ÙÏ+ÜÍ+ÖÍ+×Ï+ÔÍ+ÕÏ+ÒÍ+ÓÏ+õÑ+øÏ+»Ï+¾Í+±Ï+´Í+§Ñ+ªÏ+Ï+ Í+øÍ+ùÏ+¡Ï+¤Í+Ï+Í+Ï+Í+ûÏ+þÍ+ôÍ+õÏ+ìÍ+íÏ+ÌÍ+ÍÏ+¸Í+¹Ï+ Í+¡Ï+Í+Ï+úÍ+ûÏ+ðÍ+ñÏ+ìÍ+íÏ+ÐÍ+ÑÏ+ºÍ+»Ï+®Í+¯Ï+¤Í+¥Ï+¢Í+£Ï+§í1ð1è1é1ß1â1ê1ë1Ý1à1¯1²1Ú1Û1×1Ú111Ç1Ê1Ä1Å1Â1Ã1À1Á1ã1æ1©1¬11¢11111æ1ç11111ï1ò1é1ì1â1ã1Ú1Û1º1»1¦1§111ü1ý1è1é1Þ1ß1Ú1Û1¾1¿1¨1©1111111§ÛÃ6ÞÁ6ÖÁ6×Ã6ÍÃ6ÐÁ6ØÁ6ÙÃ6ËÃ6ÎÁ6Å6 Ã6ÈÁ6ÉÃ6ÅÃ6ÈÁ6Á6Ã6µÃ6¸Á6²Á6³Ã6°Á6±Ã6®Á6¯Ã6ÑÅ6ÔÃ6Ã6Á6Ã6Á6Å6Ã6ùÃ6üÁ6ÔÁ6ÕÃ6ýÃ6Á6ñÃ6ôÁ6ÝÃ6àÁ6×Ã6ÚÁ6ÐÁ6ÑÃ6ÈÁ6ÉÃ6¨Á6©Ã6Á6Ã6üÁ6ýÃ6êÁ6ëÃ6ÖÁ6×Ã6ÌÁ6ÍÃ6ÈÁ6ÉÃ6¬Á6­Ã6Á6Ã6Á6Ã6Á6Ã6þÁ6ÿÃ6§Éý;Ìû;Äû;Åý;»ý;¾û;Æû;Çý;¹ý;¼û;ÿ;ý;¶û;·ý;³ý;¶û;ðû;ñý;£ý;¦û; û;¡ý;û;ý;û;ý;¿ÿ;Âý;ý;û;ûý;þû;ñÿ;ôý;çý;êû;Âû;Ãý;ëý;îû;ßý;âû;Ëý;Îû;Åý;Èû;¾û;¿ý;¶û;·ý;û;ý;û;ý;êû;ëý;Øû;Ùý;Äû;Åý;ºû;»ý;¶û;·ý;û;ý;û;ý;øû;ùý;îû;ïý;ìû;íý;§··AºµA²µA³·A©·A¬µA´µAµ·A§·AªµAù¹Aü·A¤µA¥·A¡·A¤µAÞµAß·A·AµAµA·AµA·AµA·A­¹A°·Aó·AöµAé·AìµAß¹Aâ·AÕ·AØµA°µA±·AÙ·AÜµAÍ·AÐµA¹·A¼µA³·A¶µA¬µA­·A¤µA¥·AµA·AðµAñ·AØµAÙ·AÆµAÇ·A²µA³·A¨µA©·A¤µA¥·AµA·AòµAó·AæµAç·AÜµAÝ·AÚµAÛ·A§¥ñF¨ïF ïF¡ñFñFïF¢ïF£ñFñFïFçóFêñFïFñFñFïFÌïFÍñFÿñFïFüïFýñFúïFûñFøïFùñFóFñFáñFäïF×ñFÚïFÍóFÐñFÃñFÆïFïFñFÇñFÊïF»ñF¾ïF§ñFªïF¡ñF¤ïFïFñFïFñFòïFóñFÞïFßñFÆïFÇñF´ïFµñF ïF¡ñFïFñFïFñFöïF÷ñFàïFáñFÔïFÕñFÊïFËñFÈïFÉñF§«L©L©L«L«L©L©L«L«L©LÕ­LØ«L©L«Lý«L©Lº©L»«Lí«Lð©Lê©Lë«Lè©Lé«Læ©Lç«L­L«LÏ«LÒ©LÅ«LÈ©L»­L¾«L±«L´©L©L«Lµ«L¸©L©«L¬©L«L©L«L©L©L«L©L«Là©Lá«LÌ©LÍ«L´©Lµ«L¢©L£«L©L«L©L«L©L«Lä©Lå«LÎ©LÏ«LÂ©LÃ«L¸©L¹«L¶©L·«L§åQãQüãQýåQóåQöãQþãQÿåQñåQôãQÃçQÆåQîãQïåQëåQîãQ¨ãQ©åQÛåQÞãQØãQÙåQÖãQ×åQÔãQÕåQ÷çQúåQ½åQÀãQ³åQ¶ãQ©çQ¬åQåQ¢ãQúãQûåQ£åQ¦ãQåQãQåQãQýåQãQöãQ÷åQîãQïåQÎãQÏåQºãQ»åQ¢ãQ£åQãQåQüãQýåQòãQóåQîãQïåQÒãQÓåQ¼ãQ½åQ°ãQ±åQ¦ãQ§åQ¤ãQ¥åQ§ïWòWêWëWáWäWìWíWßWâW±¡W´WÜWÝWÙWÜWWWÉWÌWÆWÇWÄWÅWÂWÃWå¡WèW«W®W¡W¤W¡WWWWèWéWWWWWñWôWëWîWäWåWÜWÝW¼W½W¨W©WWWþÿWÿÿWêÿWëÿWàÿWáÿWÜÿWÝÿWÀÿWÁÿWªÿW«ÿWÿWÿWÿWÿWÿWÿW§ÝþÙ\àþ×\Øþ×\ÙþÙ\ÏþÙ\Òþ×\Úþ×\ÛþÙ\ÍþÙ\Ðþ×\ÿÛ\¢ÿÙ\Êþ×\ËþÙ\ÇþÙ\Êþ×\ÿ×\ÿÙ\·þÙ\ºþ×\´þ×\µþÙ\²þ×\³þÙ\°þ×\±þÙ\ÓÿÛ\ÖÿÙ\þÙ\þ×\þÙ\þ×\Û\Ù\ûþÙ\þþ×\Öÿ×\×ÿÙ\ÿýÙ\þ×\óýÙ\öý×\ßýÙ\âý×\ÙýÙ\Üý×\Òý×\ÓýÙ\Êý×\ËýÙ\ªý×\«ýÙ\ý×\ýÙ\þü×\ÿüÙ\ìü×\íüÙ\Øü×\ÙüÙ\Îü×\ÏüÙ\Êü×\ËüÙ\®ü×\¯üÙ\ü×\üÙ\ü×\üÙ\ü×\üÙ\ü×\üÙ\§ËûbÎûbÆûbÇûb½ûbÀûbÈûbÉûb»ûb¾ûbübüb¸ûb¹ûbµûb¸ûbòûbóûb¥ûb¨ûb¢ûb£ûb ûb¡ûbûbûbÁübÄübûbûbýúbûbóüböübéûbìûbÄübÅübíúbðúbáúbäúbÍúbÐúbÇúbÊúbÀúbÁúb¸úb¹úbúbúbúbúbìùbíùbÚùbÛùbÆùbÇùb¼ùb½ùb¸ùb¹ùbùbùbùbùbúøbûøbðøbñøbîøbïøb§¹øÍg¼øËg´øËgµøÍg«øÍg®øËg¶øËg·øÍg©øÍg¬øËgûøÏgþøÍg¦øËg§øÍg£øÍg¦øËgàøËgáøÍgøÍgøËgøËgøÍgøËgøÍgøËgøÍg¯ùÏg²ùÍgõ÷Ígø÷Ëgë÷Ígî÷ËgáùÏgäùÍg×øÍgÚøËg²ùËg³ùÍgÛ÷ÍgÞ÷ËgÏ÷ÍgÒ÷Ëg»÷Íg¾÷Ëgµ÷Íg¸÷Ëg®÷Ëg¯÷Íg¦÷Ëg§÷Íg÷Ëg÷ÍgòöËgóöÍgÚöËgÛöÍgÈöËgÉöÍg´öËgµöÍgªöËg«öÍg¦öËg§öÍgöËgöÍgôõËgõõÍgèõËgéõÍgÞõËgßõÍgÜõËgÝõÍg§§õmªõm¢õm£õmõmõm¤õm¥õmõmõméõmìõmõmõmõmõmÎõmÏõmõmõmþômÿômüômýômúômûômöm ömãômæômÙômÜômÏömÒömÅõmÈõm öm¡ömÉômÌôm½ômÀôm©ôm¬ôm£ôm¦ômômômômômôómõómàómáómÈómÉóm¶óm·óm¢óm£ómómómómómøòmùòmâòmãòmÖòm×òmÌòmÍòmÊòmËòm§òÁrò¿rò¿ròÁròÁrò¿rò¿ròÁròÁrò¿r×òÃrÚòÁrò¿ròÁrÿñÁrò¿r¼ò¿r½òÁrïñÁròñ¿rìñ¿ríñÁrêñ¿rëñÁrèñ¿réñÁróÃróÁrÑñÁrÔñ¿rÇñÁrÊñ¿r½óÃrÀóÁr³òÁr¶ò¿ró¿róÁr·ñÁrºñ¿r«ñÁr®ñ¿rñÁrñ¿rñÁrñ¿rñ¿rñÁrñ¿rñÁrâð¿rãðÁrÎð¿rÏðÁr¶ð¿r·ðÁr¤ð¿r¥ðÁrð¿rðÁrð¿rðÁrð¿rðÁræï¿rçïÁrÐï¿rÑïÁrÄï¿rÅïÁrºï¿r»ïÁr¸ï¿r¹ïÁr§ïûwïùwþîùwÿîûwõîûwøîùwïùwïûwóîûwöîùwÅïýwÈïûwðîùwñîûwíîûwðîùwªïùw«ïûwÝîûwàîùwÚîùwÛîûwØîùwÙîûwÖîùw×îûwùïýwüïûw¿îûwÂîùwµîûw¸îùw«ðýw®ðûw¡ïûw¤ïùwüïùwýïûw¥îûw¨îùwîûwîùwîûwîùwÿíûwîùwøíùwùíûwðíùwñíûwÐíùwÑíûw¼íùw½íûw¤íùw¥íûwíùwíûwþìùwÿìûwôìùwõìûwðìùwñìûwÔìùwÕìûw¾ìùw¿ìûw²ìùw³ìûw¨ìùw©ìûw¦ìùw§ìûw§ñëµ}ôë³}ìë³}íëµ}ãëµ}æë³}îë³}ïëµ}áëµ}äë³}³ì·}¶ìµ}Þë³}ßëµ}Ûëµ}Þë³}ì³}ìµ}Ëëµ}Îë³}Èë³}Éëµ}Æë³}Çëµ}Äë³}Åëµ}çì·}êìµ}­ëµ}°ë³}£ëµ}¦ë³}í·}íµ}ìµ}ì³}êì³}ëìµ}ëµ}ë³}ëµ}ë³}óêµ}öê³}íêµ}ðê³}æê³}çêµ}Þê³}ßêµ}¾ê³}¿êµ}ªê³}«êµ}ê³}êµ}ê³}êµ}ìé³}íéµ}âé³}ãéµ}Þé³}ßéµ}Âé³}Ãéµ}¬é³}­éµ} é³}¡éµ}é³}éµ}é³}éµ}§ßèïâèíÚèíÛèïÑèïÔèíÜèíÝèïÏèïÒèí¡éñ¤éïÌèíÍèïÉèïÌèíéíéï¹èï¼èí¶èí·èï´èíµèï²èí³èïÕéñØéïèïèíèïèíêñêïýèïéíØéíÙéïèïèíõçïøçíáçïäçíÛçïÞçíÔçíÕçïÌçíÍçï¬çí­çïçíçïçíçïîæíïæïÚæíÛæïÐæíÑæïÌæíÍæï°æí±æïæíæïæíæïæíæïæíæï§Íå©Ðå§Èå§Éå©¿å©Âå§Êå§Ëå©½å©Àå§æ«æ©ºå§»å©·å©ºå§ôå§õå©§å©ªå§¤å§¥å©¢å§£å© å§¡å©Ãæ«Ææ©å©å§ÿä©å§õæ«øæ©ëå©îå§Ææ§Çæ©ïä©òä§ãä©æä§Ïä©Òä§Éä©Ìä§Âä§Ãä©ºä§»ä©ä§ä©ä§ä©îã§ïã©Üã§Ýã©Èã§Éã©¾ã§¿ã©ºã§»ã©ã§ã©ã§ã©üâ§ýâ©òâ§óâ©ðâ§ñâ©§»âã¾âá¶âá·âã­âã°âá¸âá¹âã«âã®âáýâåãã¨âá©âã¥âã¨âáââáãâãâãâáâáâãâáâãâáâã±ãå´ãã÷áãúááíáãðááããåæããÙâãÜâá´ãáµããÝáãàááÑáãÔáá½áãÀáá·áãºáá°áá±áã¨áá©áãáááãôàáõàãÜàáÝàãÊàáËàã¶àá·àã¬àá­àã¨àá©àãàáàãößá÷ßãêßáëßãàßááßãÞßáßßã§©ß¬ß¤ß¥ßßß¦ß§ßßßëßîßßßßßÐßÑßßßßßþÞÿÞüÞýÞà¢àåÞèÞÛÞÞÞÑàÔàÇßÊß¢à£àËÞÎÞ¿ÞÂÞ«Þ®Þ¥Þ¨ÞÞÞÞÞöÝ÷ÝâÝãÝÊÝËÝ¸Ý¹Ý¤Ý¥ÝÝÝÝÝúÜûÜäÜåÜØÜÙÜÎÜÏÜÌÜÍÜ§Ü×ÜÕÜÕÜ×Ü×ÜÕÜÕÜ×Ü×ÜÕÙÜÙÜÜ×ÜÕÜ×Ü×ÜÕ¾ÜÕ¿Ü×ñÛ×ôÛÕîÛÕïÛ×ìÛÕíÛ×êÛÕëÛ×ÝÙÝ×ÓÛ×ÖÛÕÉÛ×ÌÛÕ¿ÝÙÂÝ×µÜ×¸ÜÕÝÕÝ×¹Û×¼ÛÕ­Û×°ÛÕÛ×ÛÕÛ×ÛÕÛÕÛ×ÛÕÛ×äÚÕåÚ×ÐÚÕÑÚ×¸ÚÕ¹Ú×¦ÚÕ§Ú×ÚÕÚ×ÚÕÚ×ÚÕÚ×èÙÕéÙ×ÒÙÕÓÙ×ÆÙÕÇÙ×¼ÙÕ½Ù×ºÙÕ»Ù×§ÙÙÙÙ÷ØúØÙÙõØøØÇÙÊÙòØóØïØòØ¬Ù­ÙßØâØÜØÝØÚØÛØØØÙØûÙþÙÁØÄØ·ØºØ­Ú°Ú£Ù¦ÙþÙÿÙ§ØªØØØØØØØú×û×ò×ó×Ò×Ó×¾×¿×¦×§×××××öÖ÷ÖòÖóÖÖÖ×ÖÀÖÁÖ´ÖµÖªÖ«Ö¨Ö©Ö§óÕË£öÕÉ£îÕÉ£ïÕË£åÕË£èÕÉ£ðÕÉ£ñÕË£ãÕË£æÕÉ£µÖÍ£¸ÖË£àÕÉ£áÕË£ÝÕË£àÕÉ£ÖÉ£ÖË£ÍÕË£ÐÕÉ£ÊÕÉ£ËÕË£ÈÕÉ£ÉÕË£ÆÕÉ£ÇÕË£éÖÍ£ìÖË£¯ÕË£²ÕÉ£¥ÕË£¨ÕÉ£×Í£×Ë£ÖË£ÖÉ£ìÖÉ£íÖË£ÕË£ÕÉ£ÕË£ÕÉ£õÔË£øÔÉ£ïÔË£òÔÉ£èÔÉ£éÔË£àÔÉ£áÔË£ÀÔÉ£ÁÔË£¬ÔÉ£­ÔË£ÔÉ£ÔË£ÔÉ£ÔË£îÓÉ£ïÓË£äÓÉ£åÓË£àÓÉ£áÓË£ÄÓÉ£ÅÓË£®ÓÉ£¯ÓË£¢ÓÉ££ÓË£ÓÉ£ÓË£ÓÉ£ÓË£§áÒ©äÒ©ÜÒ©ÝÒ©ÓÒ©ÖÒ©ÞÒ©ßÒ©ÑÒ©ÔÒ©£Ó©¦Ó©ÎÒ©ÏÒ©ËÒ©ÎÒ©Ó©Ó©»Ò©¾Ò©¸Ò©¹Ò©¶Ò©·Ò©´Ò©µÒ©×Ó©ÚÓ©Ò© Ò©Ò©Ò©Ô©Ô©ÿÒ©Ó©ÚÓ©ÛÓ©Ò©Ò©÷Ñ©úÑ©ãÑ©æÑ©ÝÑ©àÑ©ÖÑ©×Ñ©ÎÑ©ÏÑ©®Ñ©¯Ñ©Ñ©Ñ©Ñ©Ñ©ðÐ©ñÐ©ÜÐ©ÝÐ©ÒÐ©ÓÐ©ÎÐ©ÏÐ©²Ð©³Ð©Ð©Ð©Ð©Ð©Ð©Ð©Ð©Ð©§ÏÏ¿®ÒÏ½®ÊÏ½®ËÏ¿®ÁÏ¿®ÄÏ½®ÌÏ½®ÍÏ¿®¿Ï¿®ÂÏ½®ÐÁ®Ð¿®¼Ï½®½Ï¿®¹Ï¿®¼Ï½®öÏ½®÷Ï¿®©Ï¿®¬Ï½®¦Ï½®§Ï¿®¤Ï½®¥Ï¿®¢Ï½®£Ï¿®ÅÐÁ®ÈÐ¿®Ï¿®Ï½®Ï¿®Ï½®÷ÐÁ®úÐ¿®íÏ¿®ðÏ½®ÈÐ½®ÉÐ¿®ñÎ¿®ôÎ½®åÎ¿®èÎ½®ÑÎ¿®ÔÎ½®ËÎ¿®ÎÎ½®ÄÎ½®ÅÎ¿®¼Î½®½Î¿®Î½®Î¿®Î½®Î¿®ðÍ½®ñÍ¿®ÞÍ½®ßÍ¿®ÊÍ½®ËÍ¿®ÀÍ½®ÁÍ¿®¼Í½®½Í¿® Í½®¡Í¿®Í½®Í¿®þÌ½®ÿÌ¿®ôÌ½®õÌ¿®òÌ½®óÌ¿®§½Ìù³ÀÌ÷³¸Ì÷³¹Ìù³¯Ìù³²Ì÷³ºÌ÷³»Ìù³­Ìù³°Ì÷³ÿÌû³Íù³ªÌ÷³«Ìù³§Ìù³ªÌ÷³äÌ÷³åÌù³Ìù³Ì÷³Ì÷³Ìù³Ì÷³Ìù³Ì÷³Ìù³³Íû³¶Íù³ùËù³üË÷³ïËù³òË÷³åÍû³èÍù³ÛÌù³ÞÌ÷³¶Í÷³·Íù³ßËù³âË÷³ÓËù³ÖË÷³¿Ëù³ÂË÷³¹Ëù³¼Ë÷³²Ë÷³³Ëù³ªË÷³«Ëù³Ë÷³Ëù³öÊ÷³÷Êù³ÞÊ÷³ßÊù³ÌÊ÷³ÍÊù³¸Ê÷³¹Êù³®Ê÷³¯Êù³ªÊ÷³«Êù³Ê÷³Êù³øÉ÷³ùÉù³ìÉ÷³íÉù³âÉ÷³ãÉù³àÉ÷³áÉù³§«É³¹®É±¹¦É±¹§É³¹É³¹ É±¹¨É±¹©É³¹É³¹É±¹íÉµ¹ðÉ³¹É±¹É³¹É³¹É±¹ÒÉ±¹ÓÉ³¹É³¹É±¹É±¹É³¹É±¹É³¹þÈ±¹ÿÈ³¹¡Êµ¹¤Ê³¹çÈ³¹êÈ±¹ÝÈ³¹àÈ±¹ÓÊµ¹ÖÊ³¹ÉÉ³¹ÌÉ±¹¤Ê±¹¥Ê³¹ÍÈ³¹ÐÈ±¹ÁÈ³¹ÄÈ±¹­È³¹°È±¹§È³¹ªÈ±¹ È±¹¡È³¹È±¹È³¹øÇ±¹ùÇ³¹äÇ±¹åÇ³¹ÌÇ±¹ÍÇ³¹ºÇ±¹»Ç³¹¦Ç±¹§Ç³¹Ç±¹Ç³¹Ç±¹Ç³¹üÆ±¹ýÆ³¹æÆ±¹çÆ³¹ÚÆ±¹ÛÆ³¹ÐÆ±¹ÑÆ³¹ÎÆ±¹ÏÆ³¹§Æí¾Æë¾Æë¾Æí¾Æí¾Æë¾Æë¾Æí¾Æí¾Æë¾ÛÆï¾ÞÆí¾Æë¾Æí¾Æí¾Æë¾ÀÆë¾ÁÆí¾óÅí¾öÅë¾ðÅë¾ñÅí¾îÅë¾ïÅí¾ìÅë¾íÅí¾Çï¾Çí¾ÕÅí¾ØÅë¾ËÅí¾ÎÅë¾ÁÇï¾ÄÇí¾·Æí¾ºÆë¾Çë¾Çí¾»Åí¾¾Åë¾¯Åí¾²Åë¾Åí¾Åë¾Åí¾Åë¾Åë¾Åí¾Åë¾Åí¾æÄë¾çÄí¾ÒÄë¾ÓÄí¾ºÄë¾»Äí¾¨Äë¾©Äí¾Äë¾Äí¾Äë¾Äí¾Äë¾Äí¾êÃë¾ëÃí¾ÔÃë¾ÕÃí¾ÈÃë¾ÉÃí¾¾Ãë¾¿Ãí¾¼Ãë¾½Ãí¾§Ã§ÄÃ¥ÄÃ¥ÄÃ§ÄùÂ§ÄüÂ¥ÄÃ¥ÄÃ§Ä÷Â§ÄúÂ¥ÄÉÃ©ÄÌÃ§ÄôÂ¥ÄõÂ§ÄñÂ§ÄôÂ¥Ä®Ã¥Ä¯Ã§ÄáÂ§ÄäÂ¥ÄÞÂ¥ÄßÂ§ÄÜÂ¥ÄÝÂ§ÄÚÂ¥ÄÛÂ§ÄýÃ©ÄÄ§ÄÃÂ§ÄÆÂ¥Ä¹Â§Ä¼Â¥Ä¯Ä©Ä²Ä§Ä¥Ã§Ä¨Ã¥ÄÄ¥ÄÄ§Ä©Â§Ä¬Â¥ÄÂ§Ä Â¥ÄÂ§ÄÂ¥ÄÂ§ÄÂ¥ÄüÁ¥ÄýÁ§ÄôÁ¥ÄõÁ§ÄÔÁ¥ÄÕÁ§ÄÀÁ¥ÄÁÁ§Ä¨Á¥Ä©Á§ÄÁ¥ÄÁ§ÄÁ¥ÄÁ§ÄøÀ¥ÄùÀ§ÄôÀ¥ÄõÀ§ÄØÀ¥ÄÙÀ§ÄÂÀ¥ÄÃÀ§Ä¶À¥Ä·À§Ä¬À¥Ä­À§ÄªÀ¥Ä«À§Ä§õ¿áÉø¿ßÉð¿ßÉñ¿áÉç¿áÉê¿ßÉò¿ßÉó¿áÉå¿áÉè¿ßÉ·ÀãÉºÀáÉâ¿ßÉã¿áÉß¿áÉâ¿ßÉÀßÉÀáÉÏ¿áÉÒ¿ßÉÌ¿ßÉÍ¿áÉÊ¿ßÉË¿áÉÈ¿ßÉÉ¿áÉëÀãÉîÀáÉ±¿áÉ´¿ßÉ§¿áÉª¿ßÉÁãÉ ÁáÉÀáÉÀßÉîÀßÉïÀáÉ¿áÉ¿ßÉ¿áÉ¿ßÉ÷¾áÉú¾ßÉñ¾áÉô¾ßÉê¾ßÉë¾áÉâ¾ßÉã¾áÉÂ¾ßÉÃ¾áÉ®¾ßÉ¯¾áÉ¾ßÉ¾áÉ¾ßÉ¾áÉð½ßÉñ½áÉæ½ßÉç½áÉâ½ßÉã½áÉÆ½ßÉÇ½áÉ°½ßÉ±½áÉ¤½ßÉ¥½áÉ½ßÉ½áÉ½ßÉ½áÉ§ã¼Ïæ¼ÏÞ¼Ïß¼ÏÕ¼ÏØ¼Ïà¼Ïá¼ÏÓ¼ÏÖ¼Ï¥½Ï¨½ÏÐ¼ÏÑ¼ÏÍ¼ÏÐ¼Ï½Ï½Ï½¼ÏÀ¼Ïº¼Ï»¼Ï¸¼Ï¹¼Ï¶¼Ï·¼ÏÙ½ÏÜ½Ï¼Ï¢¼Ï¼Ï¼Ï¾Ï¾Ï½Ï½ÏÜ½ÏÝ½Ï¼Ï¼Ïù»Ïü»Ïå»Ïè»Ïß»Ïâ»ÏØ»ÏÙ»ÏÐ»ÏÑ»Ï°»Ï±»Ï»Ï»Ï»Ï»ÏòºÏóºÏÞºÏßºÏÔºÏÕºÏÐºÏÑºÏ´ºÏµºÏºÏºÏºÏºÏºÏºÏºÏºÏ§Ñ¹ÕÔÔ¹ÓÔÌ¹ÓÔÍ¹ÕÔÃ¹ÕÔÆ¹ÓÔÎ¹ÓÔÏ¹ÕÔÁ¹ÕÔÄ¹ÓÔº×ÔºÕÔ¾¹ÓÔ¿¹ÕÔ»¹ÕÔ¾¹ÓÔø¹ÓÔù¹ÕÔ«¹ÕÔ®¹ÓÔ¨¹ÓÔ©¹ÕÔ¦¹ÓÔ§¹ÕÔ¤¹ÓÔ¥¹ÕÔÇº×ÔÊºÕÔ¹ÕÔ¹ÓÔ¹ÕÔ¹ÓÔùº×ÔüºÕÔï¹ÕÔò¹ÓÔÊºÓÔËºÕÔó¸ÕÔö¸ÓÔç¸ÕÔê¸ÓÔÓ¸ÕÔÖ¸ÓÔÍ¸ÕÔÐ¸ÓÔÆ¸ÓÔÇ¸ÕÔ¾¸ÓÔ¿¸ÕÔ¸ÓÔ¸ÕÔ¸ÓÔ¸ÕÔò·ÓÔó·ÕÔà·ÓÔá·ÕÔÌ·ÓÔÍ·ÕÔÂ·ÓÔÃ·ÕÔ¾·ÓÔ¿·ÕÔ¢·ÓÔ£·ÕÔ·ÓÔ·ÕÔ·ÓÔ·ÕÔö¶ÓÔ÷¶ÕÔô¶ÓÔõ¶ÕÔ§¿¶ÚÂ¶Úº¶Ú»¶Ú±¶Ú´¶Ú¼¶Ú½¶Ú¯¶Ú²¶Ú·Ú·Ú¬¶Ú­¶Ú©¶Ú¬¶Úæ¶Úç¶Ú¶Ú¶Ú¶Ú¶Ú¶Ú¶Ú¶Ú¶Úµ·Ú¸·ÚûµÚþµÚñµÚôµÚç·Úê·ÚÝ¶Úà¶Ú¸·Ú¹·ÚáµÚäµÚÕµÚØµÚÁµÚÄµÚ»µÚ¾µÚ´µÚµµÚ¬µÚ­µÚµÚµÚø´Úù´Úà´Úá´ÚÎ´ÚÏ´Úº´Ú»´Ú°´Ú±´Ú¬´Ú­´Ú´Ú´Úú³Úû³Úî³Úï³Úä³Úå³Úâ³Úã³Ú§­³Éß°³Çß¨³Çß©³Éß³Éß¢³Çßª³Çß«³Éß³Éß ³Çßï³Ëßò³Éß³Çß³Éß³Éß³ÇßÔ³ÇßÕ³Éß³Éß³Çß³Çß³Éß³Çß³Éß³Çß³Éß£´Ëß¦´Éßé²Éßì²Çßß²Éßâ²ÇßÕ´ËßØ´ÉßË³ÉßÎ³Çß¦´Çß§´ÉßÏ²ÉßÒ²ÇßÃ²ÉßÆ²Çß¯²Éß²²Çß©²Éß¬²Çß¢²Çß£²Éß²Çß²Éßú±Çßû±Éßæ±Çßç±ÉßÎ±ÇßÏ±Éß¼±Çß½±Éß¨±Çß©±Éß±Çß±Éß±Çß±Éßþ°Çßÿ°Éßè°Çßé°ÉßÜ°ÇßÝ°ÉßÒ°ÇßÓ°ÉßÐ°ÇßÑ°Éß§°å°å°å°å°å°å°å°å°å°åÝ°åà°å°å°å°å°åÂ°åÃ°åõ¯åø¯åò¯åó¯åð¯åñ¯åî¯åï¯å±å±å×¯åÚ¯åÍ¯åÐ¯åÃ±åÆ±å¹°å¼°å±å±å½¯åÀ¯å±¯å´¯å¯å ¯å¯å¯å¯å¯å¯å¯åè®åé®åÔ®åÕ®å¼®å½®åª®å«®å®å®å®å®å®å®åì­åí­åÖ­å×­åÊ­åË­åÀ­åÁ­å¾­å¿­å§­½ê­»ê­»ê­½êû¬½êþ¬»ê­»ê­½êù¬½êü¬»êË­¿êÎ­½êö¬»ê÷¬½êó¬½êö¬»ê°­»ê±­½êã¬½êæ¬»êà¬»êá¬½êÞ¬»êß¬½êÜ¬»êÝ¬½êÿ­¿ê®½êÅ¬½êÈ¬»ê»¬½ê¾¬»ê±®¿ê´®½ê§­½êª­»ê®»ê®½ê«¬½ê®¬»ê¬½ê¢¬»ê¬½ê¬»ê¬½ê¬»êþ«»êÿ«½êö«»ê÷«½êÖ«»ê×«½êÂ«»êÃ«½êª«»ê««½ê«»ê«½ê«»ê«½êúª»êûª½êöª»ê÷ª½êÚª»êÛª½êÄª»êÅª½ê¸ª»ê¹ª½ê®ª»ê¯ª½ê¬ª»ê­ª½ê§÷©÷ïú©õïò©õïó©÷ïé©÷ïì©õïô©õïõ©÷ïç©÷ïê©õï¹ªùï¼ª÷ïä©õïå©÷ïá©÷ïä©õïªõïª÷ïÑ©÷ïÔ©õïÎ©õïÏ©÷ïÌ©õïÍ©÷ïÊ©õïË©÷ïíªùïðª÷ï³©÷ï¶©õï©©÷ï¬©õï«ùï¢«÷ïª÷ïªõïðªõïñª÷ï©÷ï©õï©÷ï©õïù¨÷ïü¨õïó¨÷ïö¨õïì¨õïí¨÷ïä¨õïå¨÷ïÄ¨õïÅ¨÷ï°¨õï±¨÷ï¨õï¨÷ï¨õï¨÷ïò§õïó§÷ïè§õïé§÷ïä§õïå§÷ïÈ§õïÉ§÷ï²§õï³§÷ï¦§õï§§÷ï§õï§÷ï§õï§÷ï§å¦±õè¦¯õà¦¯õá¦±õ×¦±õÚ¦¯õâ¦¯õã¦±õÕ¦±õØ¦¯õ§§³õª§±õÒ¦¯õÓ¦±õÏ¦±õÒ¦¯õ§¯õ§±õ¿¦±õÂ¦¯õ¼¦¯õ½¦±õº¦¯õ»¦±õ¸¦¯õ¹¦±õÛ§³õÞ§±õ¡¦±õ¤¦¯õ¦±õ¦¯õ¨³õ¨±õ§±õ§¯õÞ§¯õß§±õ¦±õ¦¯õû¥±õþ¥¯õç¥±õê¥¯õá¥±õä¥¯õÚ¥¯õÛ¥±õÒ¥¯õÓ¥±õ²¥¯õ³¥±õ¥¯õ¥±õ¥¯õ¥±õô¤¯õõ¤±õà¤¯õá¤±õÖ¤¯õ×¤±õÒ¤¯õÓ¤±õ¶¤¯õ·¤±õ ¤¯õ¡¤±õ¤¯õ¤±õ¤¯õ¤±õ¤¯õ¤±õ§Ó£ëúÖ£éúÎ£éúÏ£ëúÅ£ëúÈ£éúÐ£éúÑ£ëúÃ£ëúÆ£éú¤íú¤ëúÀ£éúÁ£ëú½£ëúÀ£éúú£éúû£ëú­£ëú°£éúª£éú«£ëú¨£éú©£ëú¦£éú§£ëúÉ¤íúÌ¤ëú£ëú£éú£ëú£éúû¤íúþ¤ëúñ£ëúô£éúÌ¤éúÍ¤ëúõ¢ëúø¢éúé¢ëúì¢éúÕ¢ëúØ¢éúÏ¢ëúÒ¢éúÈ¢éúÉ¢ëúÀ¢éúÁ¢ëú ¢éú¡¢ëú¢éú¢ëúô¡éúõ¡ëúâ¡éúã¡ëúÎ¡éúÏ¡ëúÄ¡éúÅ¡ëúÀ¡éúÁ¡ëú¤¡éú¥¡ëú¡éú¡ëú¡éú¡ëúø éúù ëúö éú÷ ëú§Á ¥Ä £¼ £½ ¥³ ¥¶ £¾ £¿ ¥± ¥´ £¡§¡¥® £¯ ¥« ¥® £è £é ¥ ¥ £ £ ¥ £ ¥ £ ¥·¡§º¡¥ý¥ £ó¥ö£é¡§ì¡¥ß ¥â £º¡£»¡¥ã¥æ£×¥Ú£Ã¥Æ£½¥À£¶£·¥®£¯¥£¥ú£û¥â£ã¥Ð£Ñ¥¼£½¥²£³¥®£¯¥£¥ü£ý¥ð£ñ¥æ£ç¥ä£å¥§¯ß²ÝªÝ«ß¡ß¤Ý¬Ý­ßß¢ÝñáôßÝßßÝÖÝ×ßßÝÝßÝßÝß¥á¨ßëßîÝáßäÝ×áÚßÍßÐÝ¨Ý©ßÑßÔÝÅßÈÝ±ß´Ý«ß®Ý¤Ý¥ßÝßüÝýßèÝéßÐÝÑß¾Ý¿ßªÝ«ß Ý¡ßÝßÝßêÝëßÞÝßßÔÝÕßÒÝÓß§ ßâÄÅ÷úôõòóðñÙÜÏÒÅÈ»¾¿Â³¶¢êëÖ×¾¿¬­îïØÙÌÍÂÃÀÁ§ÓÑÑÓýÓÑÑÓûÓþÑÍÕÐÓøÑùÓõÓøÑ²Ñ³ÓåÓèÑâÑãÓàÑáÓÞÑßÓÕÓÇÓÊÑ½ÓÀÑ³Õ¶Ó©Ó¬ÑÑÓ­Ó°Ñ¡Ó¤ÑÓÑÓÑÑÓøÑùÓØÑÙÓÄÑÅÓ¬Ñ­ÓÑÓÑÓüÑýÓøÑùÓÜÑÝÓÆÑÇÓºÑ»Ó°Ñ±Ó®Ñ¯Ó§ùüôõëîö÷éì»¾æçãæ ¡ÓÖÐÑÎÏÌÍïòµ¸«®¡¤òóûþõøîïæçÆÇ²³ôõêëæçÊË´µ¨©§çÇêÅâÅãÇÙÇÜÅäÅåÇ×ÇÚÅ©É¬ÇÔÅÕÇÑÇÔÅÅÇÁÇÄÅ¾Å¿Ç¼Å½ÇºÅ»ÇÝÉàÇ£Ç¦ÅÇÅÉÇÇÅàÅáÇÇÅýÇÅéÇìÅãÇæÅÜÅÝÇÔÅÕÇ´ÅµÇ Å¡ÇÅÇöÅ÷ÇâÅãÇØÅÙÇÔÅÕÇ¸Å¹Ç¢Å£ÇÅÇÅÇÅÇ§Õ¡Øÿ Ðÿ Ñ¡Ç¡Êÿ Òÿ Ó¡Å¡Èÿ ¡¡Âÿ Ã¡¿¡Âÿ üÿ ý¡¯¡²ÿ ¬ÿ ­¡ªÿ «¡¨ÿ ©¡Ë¡Î¡¡ÿ ¡ÿ ý¡¡ó¡öÿ Îÿ Ï¡÷¡úÿ ë¡îÿ ×¡Úÿ Ñ¡Ôÿ Êÿ Ë¡Âÿ Ã¡¢ÿ £¡ÿ ¡öÿ ÷¡äÿ å¡Ðÿ Ñ¡Æÿ Ç¡Âÿ Ã¡¦ÿ §¡ÿ ¡ÿ ¡úÿ û¡øÿ ù¡§Ã»¦Æ¹¦¾¹¦¿»¦µ»¦¸¹¦À¹¦Á»¦³»¦¶¹¦½¦»¦°¹¦±»¦­»¦°¹¦ê¹¦ë»¦»¦ ¹¦¹¦»¦¹¦»¦¹¦»¦¹½¦¼»¦ÿ»¦¹¦õ»¦ø¹¦ë½¦î»¦á»¦ä¹¦¼¹¦½»¦å»¦è¹¦Ù»¦Ü¹¦Å»¦È¹¦¿»¦Â¹¦¸¹¦¹»¦°¹¦±»¦¹¦»¦ü¹¦ý»¦ä¹¦å»¦Ò¹¦Ó»¦¾¹¦¿»¦´¹¦µ»¦°¹¦±»¦¹¦»¦þ¹¦ÿ»¦ò¹¦ó»¦è¹¦é»¦æ¹¦ç»¦§±õ«´ó«¬ó«­õ«£õ«¦ó«®ó«¯õ«¡õ«¤ó«ó÷«öõ«ó«õ«õ«ó«Øó«Ùõ«õ«ó«ó«õ«ó«õ«ó«õ«§÷«ªõ«íõ«ðó«ãõ«æó«Ù÷«Üõ«Ïõ«Òó«ªó««õ«Óõ«Öó«Çõ«Êó«³õ«¶ó«­õ«°ó«¦ó«§õ«ó«õ«þó«ÿõ«êó«ëõ«Òó«Óõ«Àó«Áõ«¬ó«­õ«¢ó«£õ«ó«õ«ó«õ«ìó«íõ«àó«áõ«Öó«×õ«Ôó«Õõ«§¯±¢­±­±¯±¯±­±­±¯±¯±­±á±±ä¯±­±¯±¯±­±Æ­±Ç¯±ù¯±ü­±ö­±÷¯±ô­±õ¯±ò­±ó¯±±±¯±Û¯±Þ­±Ñ¯±Ô­±Ç±±Ê¯±½¯±À­±­±¯±Á¯±Ä­±µ¯±¸­±¡¯±¤­±¯±­±­±¯±­±¯±ì­±í¯±Ø­±Ù¯±À­±Á¯±®­±¯¯±­±¯±­±¯±­±¯±ð­±ñ¯±Ú­±Û¯±Î­±Ï¯±Ä­±Å¯±Â­±Ã¯±§­»­¹þ¬¹ÿ¬»õ¬»ø¬¹­¹­»ó¬»ö¬¹Å­»È­¹ð¬¹ñ¬»í¬»ð¬¹ª­¹«­»Ý¬»à¬¹Ú¬¹Û¬»Ø¬¹Ù¬»Ö¬¹×¬»ù­»ü­¹¿¬»Â¬¹µ¬»¸¬¹«®»®®¹¡­»¤­¹ü­¹ý­»¥¬»¨¬¹¬»¬¹¬»¬¹ÿ«»¬¹ø«¹ù«»ð«¹ñ«»Ð«¹Ñ«»¼«¹½«»¤«¹¥«»«¹«»þª¹ÿª»ôª¹õª»ðª¹ñª»Ôª¹Õª»¾ª¹¿ª»²ª¹³ª»¨ª¹©ª»¦ª¹§ª»§ñ©õ
+ô©ó
+ì©ó
+í©õ
+ã©õ
+æ©ó
+î©ó
+ï©õ
+á©õ
+ä©ó
+³ªõ
+¶ªó
+Þ©ó
+ß©õ
+Û©õ
+Þ©ó
+ªó
+ªõ
+Ë©õ
+Î©ó
+È©ó
+É©õ
+Æ©ó
+Ç©õ
+Ä©ó
+Å©õ
+çªõ
+êªó
+­©õ
+°©ó
+£©õ
+¦©ó
+«õ
+«ó
+ªõ
+ªó
+êªó
+ëªõ
+©õ
+©ó
+©õ
+©ó
+ó¨õ
+ö¨ó
+í¨õ
+ð¨ó
+æ¨ó
+ç¨õ
+Þ¨ó
+ß¨õ
+¾¨ó
+¿¨õ
+ª¨ó
+«¨õ
+¨ó
+¨õ
+¨ó
+¨õ
+ì§ó
+í§õ
+â§ó
+ã§õ
+Þ§ó
+ß§õ
+Â§ó
+Ã§õ
+¬§ó
+­§õ
+ §ó
+¡§õ
+§ó
+§õ
+§ó
+§õ
+§ß¦¯â¦­Ú¦­Û¦¯Ñ¦¯Ô¦­Ü¦­Ý¦¯Ï¦¯Ò¦­¡§¯¤§­Ì¦­Í¦¯É¦¯Ì¦­§­§¯¹¦¯¼¦­¶¦­·¦¯´¦­µ¦¯²¦­³¦¯Õ§¯Ø§­¦¯¦­¦¯¦­¨¯¨­ý¦¯§­Ø§­Ù§¯¦¯¦­õ¥¯ø¥­á¥¯ä¥­Û¥¯Þ¥­Ô¥­Õ¥¯Ì¥­Í¥¯¬¥­­¥¯¥­¥¯¥­¥¯î¤­ï¤¯Ú¤­Û¤¯Ð¤­Ñ¤¯Ì¤­Í¤¯°¤­±¤¯¤­¤¯¤­¤¯¤­¤¯¤­¤¯§Í£éÐ£çÈ£çÉ£é¿£éÂ£çÊ£çË£é½£éÀ£ç¤é¤çº£ç»£é·£éº£çô£çõ£é§£éª£ç¤£ç¥£é¢£ç££é £ç¡£éÃ¤éÆ¤ç£é£çÿ¢é£çõ¤éø¤çë£éî£çÆ¤çÇ¤éï¢éò¢çã¢éæ¢çÏ¢éÒ¢çÉ¢éÌ¢çÂ¢çÃ¢éº¢ç»¢é¢ç¢é¢ç¢éî¡çï¡éÜ¡çÝ¡éÈ¡çÉ¡é¾¡ç¿¡éº¡ç»¡é¡ç¡é¡ç¡éü çý éò çó éð çñ é§» £¾ ¡¶ ¡· £­ £° ¡¸ ¡¹ £« £® ¡ý £¡¡¨ ¡© £¥ £¨ ¡â ¡ã £ £ ¡ ¡ £ ¡ £ ¡ £±¡£´¡¡÷£ú¡í£ð¡ã¡£æ¡¡Ù £Ü ¡´¡¡µ¡£Ý£à¡Ñ£Ô¡½£À¡·£º¡°¡±£¨¡©£¡£ô¡õ£Ü¡Ý£Ê¡Ë£¶¡·£¬¡­£¨¡©£¡£ö¡÷£ê¡ë£à¡á£Þ¡ß£§©Ý ¬Û ¤Û ¥Ý Ý Û ¦Û §Ý Ý Û ëÝ îÛ Û Ý Ý Û ÐÛ ÑÝ Ý Û Û Ý þÛ ÿÝ üÛ ýÝ Ý ¢Û åÝ èÛ ÛÝ ÞÛ ÑÝ ÔÛ ÇÝ ÊÛ ¢Û £Ý ËÝ ÎÛ ¿Ý ÂÛ «Ý ®Û ¥Ý ¨Û Û Ý Û Ý öÛ ÷Ý âÛ ãÝ ÊÛ ËÝ ¸Û ¹Ý ¤Û ¥Ý Û Ý Û Ý úÛ ûÝ äÛ åÝ ØÛ ÙÝ ÎÛ ÏÝ ÌÛ ÍÝ §&&&&&&&&&&Ù&Ü&&&&&¾&¿&ñ&ô&î&ï&ì&í&ê&ë&&&Ó&Ö&É&Ì&¿&Â&µ&¸&&&¹&¼&­&°&&&&&&&&&ä&å&Ð&Ñ&¸&¹&¦&§&&&&&&&è&é&Ò&Ó&Æ&Ç&¼&½&º&»&§Ñ+Ï+Ï+Ñ+÷Ñ+úÏ+Ï+Ñ+õÑ+øÏ+ÇÑ+ÊÏ+òÏ+óÑ+ïÑ+òÏ+¬Ï+­Ñ+ßÑ+âÏ+ÜÏ+ÝÑ+ÚÏ+ÛÑ+ØÏ+ÙÑ+ûÑ+þÏ+ÁÑ+ÄÏ+·Ñ+ºÏ+­Ñ+°Ï+£Ñ+¦Ï+þÏ+ÿÑ+§Ñ+ªÏ+Ñ+Ï+Ñ+Ï+Ñ+Ï+úÏ+ûÑ+òÏ+óÑ+ÒÏ+ÓÑ+¾Ï+¿Ñ+¦Ï+§Ñ+Ï+Ñ+Ï+Ñ+öÏ+÷Ñ+òÏ+óÑ+ÖÏ+×Ñ+ÀÏ+ÁÑ+´Ï+µÑ+ªÏ+«Ñ+¨Ï+©Ñ+§ó1ö1î1ï1å1è1ð1ñ1ã1æ1µ1¸1à1á1Ý1à111Í1Ð1Ê1Ë1È1É1Æ1Ç1é1ì1¯1²1¥1¨11111ì1í11111õ1ø1ï1ò1è1é1à1á1À1Á1¬1­11111î1ï1ä1å1à1á1Ä1Å1®1¯1¢1£11111§áÅ6äÃ6ÜÃ6ÝÅ6ÓÅ6ÖÃ6ÞÃ6ßÅ6ÑÅ6ÔÃ6£Å6¦Ã6ÎÃ6ÏÅ6ËÅ6ÎÃ6Ã6Å6»Å6¾Ã6¸Ã6¹Å6¶Ã6·Å6´Ã6µÅ6×Å6ÚÃ6Å6 Ã6Å6Ã6Å6Ã6ÿÅ6Ã6ÚÃ6ÛÅ6Å6Ã6÷Å6úÃ6ãÅ6æÃ6ÝÅ6àÃ6ÖÃ6×Å6ÎÃ6ÏÅ6®Ã6¯Å6Ã6Å6Ã6Å6ðÃ6ñÅ6ÜÃ6ÝÅ6ÒÃ6ÓÅ6ÎÃ6ÏÅ6²Ã6³Å6Ã6Å6Ã6Å6Ã6Å6Ã6Å6§Ïÿ;Òý;Êý;Ëÿ;Áÿ;Äý;Ìý;Íÿ;¿ÿ;Âý;ÿ;ý;¼ý;½ÿ;¹ÿ;¼ý;öý;÷ÿ;©ÿ;¬ý;¦ý;§ÿ;¤ý;¥ÿ;¢ý;£ÿ;Åÿ;Èý;ÿ;ý;ÿ;ý;÷ÿ;úý;íÿ;ðý;Èý;Éÿ;ñÿ;ôý;åÿ;èý;Ñÿ;Ôý;Ëÿ;Îý;Äý;Åÿ;¼ý;½ÿ;ý;ÿ;ý;ÿ;ðý;ñÿ;Þý;ßÿ;Êý;Ëÿ;Àý;Áÿ;¼ý;½ÿ; ý;¡ÿ;ý;ÿ;þý;ÿÿ;ôý;õÿ;òý;óÿ;§½¹AÀ·A¸·A¹¹A¯¹A²·Aº·A»¹A­¹A°·Aÿ¹A·Aª·A«¹A§¹Aª·Aä·Aå¹A¹A·A·A¹A·A¹A·A¹A³¹A¶·Aù¹Aü·Aï¹Aò·Aå¹Aè·AÛ¹AÞ·A¶·A·¹Aß¹Aâ·AÓ¹AÖ·A¿¹AÂ·A¹¹A¼·A²·A³¹Aª·A«¹A·A¹Aö·A÷¹AÞ·Aß¹AÌ·AÍ¹A¸·A¹¹A®·A¯¹Aª·A«¹A·A¹Aø·Aù¹Aì·Aí¹Aâ·Aã¹Aà·Aá¹A§«óF®ñF¦ñF§óFóF ñF¨ñF©óFóFñFíóFðñFñFóFóFñFÒñFÓóFóFñFñFóFñFóFþñFÿóF¡óF¤ñFçóFêñFÝóFàñFÓóFÖñFÉóFÌñF¤ñF¥óFÍóFÐñFÁóFÄñF­óF°ñF§óFªñF ñF¡óFñFóFøñFùóFäñFåóFÌñFÍóFºñF»óF¦ñF§óFñFóFñFóFüñFýóFæñFçóFÚñFÛóFÐñFÑóFÎñFÏóF§­L«L«L­L­L«L«L­L­L«LÛ­LÞ«L«L­L­L«LÀ«LÁ­Ló­Lö«Lð«Lñ­Lî«Lï­Lì«Lí­L­L«LÕ­LØ«LË­LÎ«LÁ­LÄ«L·­Lº«L«L­L»­L¾«L¯­L²«L­L«L­L«L«L­L«L­Læ«Lç­LÒ«LÓ­Lº«L»­L¨«L©­L«L­L«L­L«L­Lê«Lë­LÔ«LÕ­LÈ«LÉ­L¾«L¿­L¼«L½­L§çQåQåQçQùçQüåQåQçQ÷çQúåQÉçQÌåQôåQõçQñçQôåQ®åQ¯çQáçQäåQÞåQßçQÜåQÝçQÚåQÛçQýçQåQÃçQÆåQ¹çQ¼åQ¯çQ²åQ¥çQ¨åQåQçQ©çQ¬åQçQ åQçQåQçQåQüÿåQýÿçQôÿåQõÿçQÔÿåQÕÿçQÀÿåQÁÿçQ¨ÿåQ©ÿçQÿåQÿçQÿåQÿçQøþåQùþçQôþåQõþçQØþåQÙþçQÂþåQÃþçQ¶þåQ·þçQ¬þåQ­þçQªþåQ«þçQ§õý¡WøýWðýWñý¡Wçý¡WêýWòýWóý¡Wåý¡WèýW·þ¡WºþWâýWãý¡Wßý¡WâýWþWþ¡WÏý¡WÒýWÌýWÍý¡WÊýWËý¡WÈýWÉý¡Wëþ¡WîþW±ý¡W´ýW§ý¡WªýWÿ¡W ÿWþ¡WþWîþWïþ¡Wý¡WýWý¡WýW÷ü¡WúüWñü¡WôüWêüWëü¡WâüWãü¡WÂüWÃü¡W®üW¯ü¡WüWü¡WüWü¡WðûWñû¡WæûWçû¡WâûWãû¡WÆûWÇû¡W°ûW±û¡W¤ûW¥û¡WûWû¡WûWû¡W§ãúÛ\æúÙ\ÞúÙ\ßúÛ\ÕúÛ\ØúÙ\àúÙ\áúÛ\ÓúÛ\ÖúÙ\¥ûÛ\¨ûÙ\ÐúÙ\ÑúÛ\ÍúÛ\ÐúÙ\ûÙ\ûÛ\½úÛ\ÀúÙ\ºúÙ\»úÛ\¸úÙ\¹úÛ\¶úÙ\·úÛ\ÙûÛ\ÜûÙ\úÛ\¢úÙ\úÛ\úÙ\üÛ\üÙ\ûÛ\ûÙ\ÜûÙ\ÝûÛ\úÛ\úÙ\ùùÛ\üùÙ\åùÛ\èùÙ\ßùÛ\âùÙ\ØùÙ\ÙùÛ\ÐùÙ\ÑùÛ\°ùÙ\±ùÛ\ùÙ\ùÛ\ùÙ\ùÛ\òøÙ\óøÛ\ÞøÙ\ßøÛ\ÔøÙ\ÕøÛ\ÐøÙ\ÑøÛ\´øÙ\µøÛ\øÙ\øÛ\øÙ\øÛ\øÙ\øÛ\øÙ\øÛ\§Ñ÷bÔ÷bÌ÷bÍ÷bÃ÷bÆ÷bÎ÷bÏ÷bÁ÷bÄ÷bøbøb¾÷b¿÷b»÷b¾÷bø÷bù÷b«÷b®÷b¨÷b©÷b¦÷b§÷b¤÷b¥÷bÇøbÊøb÷b÷b÷b÷bùøbüøbï÷bò÷bÊøbËøbóöbööbçöbêöbÓöbÖöbÍöbÐöbÆöbÇöb¾öb¿öböböböböbòõbóõbàõbáõbÌõbÍõbÂõbÃõb¾õb¿õb¢õb£õbõbõbõbõböôb÷ôbôôbõôb§¿ôÏgÂôÍgºôÍg»ôÏg±ôÏg´ôÍg¼ôÍg½ôÏg¯ôÏg²ôÍgõÏgõÍg¬ôÍg­ôÏg©ôÏg¬ôÍgæôÍgçôÏgôÏgôÍgôÍgôÏgôÍgôÏgôÍgôÏgµõÏg¸õÍgûóÏgþóÍgñóÏgôóÍgçõÏgêõÍgÝôÏgàôÍg¸õÍg¹õÏgáóÏgäóÍgÕóÏgØóÍgÁóÏgÄóÍg»óÏg¾óÍg´óÍgµóÏg¬óÍg­óÏgóÍgóÏgøòÍgùòÏgàòÍgáòÏgÎòÍgÏòÏgºòÍg»òÏg°òÍg±òÏg¬òÍg­òÏgòÍgòÏgúñÍgûñÏgîñÍgïñÏgäñÍgåñÏgâñÍgãñÏg§­ñm°ñm¨ñm©ñmñm¢ñmªñm«ñmñm ñmïñmòñmñmñmñmñmÔñmÕñmñmñmñmñmñmñmñmñm£òm¦òméðmìðmßðmâðmÕòmØòmËñmÎñm¦òm§òmÏðmÒðmÃðmÆðm¯ðm²ðm©ðm¬ðm¢ðm£ðmðmðmúïmûïmæïmçïmÎïmÏïm¼ïm½ïm¨ïm©ïmïmïmïmïmþîmÿîmèîméîmÜîmÝîmÒîmÓîmÐîmÑîm§îÃrîÁrîÁrîÃrîÃrîÁrîÁrîÃrîÃrîÁrÝîÃràîÁrîÁrîÃrîÃrîÁrÂîÁrÃîÃrõíÃrøíÁròíÁróíÃrðíÁrñíÃrîíÁrïíÃrïÃrïÁr×íÃrÚíÁrÍíÃrÐíÁrÃïÃrÆïÁr¹îÃr¼îÁrïÁrïÃr½íÃrÀíÁr±íÃr´íÁríÃr íÁríÃríÁríÁríÃríÁríÃrèìÁréìÃrÔìÁrÕìÃr¼ìÁr½ìÃrªìÁr«ìÃrìÁrìÃrìÁrìÃrìÁrìÃrìëÁríëÃrÖëÁr×ëÃrÊëÁrËëÃrÀëÁrÁëÃr¾ëÁr¿ëÃr§ëýwëûwëûwëýwûêýwþêûwëûwëýwùêýwüêûwËëýwÎëûwöêûw÷êýwóêýwöêûw°ëûw±ëýwãêýwæêûwàêûwáêýwÞêûwßêýwÜêûwÝêýwÿëýwìûwÅêýwÈêûw»êýw¾êûw±ìýw´ìûw§ëýwªëûwìûwìýw«êýw®êûwêýw¢êûwêýwêûwêýwêûwþéûwÿéýwöéûw÷éýwÖéûw×éýwÂéûwÃéýwªéûw«éýwéûwéýwéûwéýwúèûwûèýwöèûw÷èýwÚèûwÛèýwÄèûwÅèýw¸èûw¹èýw®èûw¯èýw¬èûw­èýw§÷ç·}úçµ}òçµ}óç·}éç·}ìçµ}ôçµ}õç·}çç·}êçµ}¹è·}¼èµ}äçµ}åç·}áç·}äçµ}èµ}è·}Ñç·}Ôçµ}Îçµ}Ïç·}Ìçµ}Íç·}Êçµ}Ëç·}íè·}ðèµ}³ç·}¶çµ}©ç·}¬çµ}é·}¢éµ}è·}èµ}ðèµ}ñè·}ç·}çµ}ç·}çµ}ùæ·}üæµ}óæ·}öæµ}ìæµ}íæ·}äæµ}åæ·}Äæµ}Åæ·}°æµ}±æ·}æµ}æ·}æµ}æ·}òåµ}óå·}èåµ}éå·}äåµ}åå·}Èåµ}Éå·}²åµ}³å·}¦åµ}§å·}åµ}å·}åµ}å·}§åäñèäïàäïáäñ×äñÚäïâäïãäñÕäñØäï§åñªåïÒäïÓäñÏäñÒäïåïåñ¿äñÂäï¼äï½äñºäï»äñ¸äï¹äñÛåñÞåï¡äñ¤äïäñäïæñæïåñåïÞåïßåñäñäïûãñþãïçãñêãïáãñäãïÚãïÛãñÒãïÓãñ²ãï³ãñãïãñãïãñôâïõâñàâïáâñÖâï×âñÒâïÓâñ¶âï·âñ âï¡âñâïâñâïâñâïâñ§Óá«Öá©Îá©Ïá«Åá«Èá©Ðá©Ñá«Ãá«Æá©â«â©Àá©Áá«½á«Àá©úá©ûá«­á«°á©ªá©«á«¨á©©á«¦á©§á«Éâ«Ìâ©á«á©á«á©ûâ«þâ©ñá«ôá©Ìâ©Íâ«õà«øà©éà«ìà©Õà«Øà©Ïà«Òà©Èà©Éà«Àà©Áà« à©¡à«à©à«ôß©õß«âß©ãß«Îß©Ïß«Äß©Åß«Àß©Áß«¤ß©¥ß«ß©ß«ß©ß«øÞ©ùÞ«öÞ©÷Þ«§ÁÞåÄÞã¼Þã½Þå³Þå¶Þã¾Þã¿Þå±Þå´Þãßåßã®Þã¯Þå«Þå®ÞãèÞãéÞåÞåÞãÞãÞåÞãÞåÞãÞå·ßåºßãýÝåÞãóÝåöÝãéßåìßãßÞåâÞãºßã»ßåãÝåæÝã×ÝåÚÝãÃÝåÆÝã½ÝåÀÝã¶Ýã·Ýå®Ýã¯ÝåÝãÝåúÜãûÜåâÜããÜåÐÜãÑÜå¼Üã½Üå²Üã³Üå®Üã¯ÜåÜãÜåüÛãýÛåðÛãñÛåæÛãçÛåäÛãåÛå§¯Û²ÛªÛ«Û¡Û¤Û¬Û­ÛÛ¢ÛñÛôÛÛÛÛÛÖÛ×ÛÛÛÛÛÛÛÛÛ¥Ü¨ÜëÚîÚáÚäÚ×ÜÚÜÍÛÐÛ¨Ü©ÜÑÚÔÚÅÚÈÚ±Ú´Ú«Ú®Ú¤Ú¥ÚÚÚüÙýÙèÙéÙÐÙÑÙ¾Ù¿ÙªÙ«Ù Ù¡ÙÙÙÙÙêØëØÞØßØÔØÕØÒØÓØ§ØÙ Ø×Ø×ØÙØÙØ×Ø×ØÙØÙØ×ßØÙâØ×Ø×ØÙØÙØ×ÄØ×ÅØÙ÷×Ùú××ô××õ×Ùò××ó×Ùð××ñ×ÙÙÙÙ×Ù×ÙÜ××Ï×ÙÒ××ÅÙÙÈÙ×»ØÙ¾Ø×Ù×ÙÙ¿×ÙÂ××³×Ù¶×××Ù¢×××Ù×××××Ù×××ÙêÖ×ëÖÙÖÖ××ÖÙ¾Ö×¿ÖÙ¬Ö×­ÖÙÖ×ÖÙÖ×ÖÙÖ×ÖÙîÕ×ïÕÙØÕ×ÙÕÙÌÕ×ÍÕÙÂÕ×ÃÕÙÀÕ×ÁÕÙ§ÕÕÕÕýÔÕÕÕûÔþÔÍÕÐÕøÔùÔõÔøÔ²Õ³ÕåÔèÔâÔãÔàÔáÔÞÔßÔÖÖÇÔÊÔ½ÔÀÔ³Ö¶Ö©Õ¬ÕÖÖ­Ô°Ô¡Ô¤ÔÔÔÔÔÔÔøÓùÓØÓÙÓÄÓÅÓ¬Ó­ÓÓÓÓÓüÒýÒøÒùÒÜÒÝÒÆÒÇÒºÒ»Ò°Ò±Ò®Ò¯Ò§ùÑÍ£üÑË£ôÑË£õÑÍ£ëÑÍ£îÑË£öÑË£÷ÑÍ£éÑÍ£ìÑË£»ÒÍ£¾ÒË£æÑË£çÑÍ£ãÑÍ£æÑË£ ÒË£¡ÒÍ£ÓÑÍ£ÖÑË£ÐÑË£ÑÑÍ£ÎÑË£ÏÑÍ£ÌÑË£ÍÑÍ£ïÒÍ£òÒË£µÑÍ£¸ÑË£«ÑÍ£®ÑË£¡ÓÍ£¤ÓË£ÒÍ£ÒË£òÒË£óÒÍ£ÑÍ£ÑË£ÑÍ£ÑË£ûÐÍ£þÐË£õÐÍ£øÐË£îÐË£ïÐÍ£æÐË£çÐÍ£ÆÐË£ÇÐÍ£²ÐË£³ÐÍ£ÐË£ÐÍ£ÐË£ÐÍ£ôÏË£õÏÍ£êÏË£ëÏÍ£æÏË£çÏÍ£ÊÏË£ËÏÍ£´ÏË£µÏÍ£¨ÏË£©ÏÍ£ÏË£ÏÍ£ÏË£ÏÍ£§çÎ©êÎ©âÎ©ãÎ©ÙÎ©ÜÎ©äÎ©åÎ©×Î©ÚÎ©©Ï©¬Ï©ÔÎ©ÕÎ©ÑÎ©ÔÎ©Ï©Ï©ÁÎ©ÄÎ©¾Î©¿Î©¼Î©½Î©ºÎ©»Î©ÝÏ©àÏ©£Î©¦Î©Î©Î©Ð©Ð©Ï©Ï©àÏ©áÏ©Î©Î©ýÍ©Î©éÍ©ìÍ©ãÍ©æÍ©ÜÍ©ÝÍ©ÔÍ©ÕÍ©´Í©µÍ© Í©¡Í©Í©Í©öÌ©÷Ì©âÌ©ãÌ©ØÌ©ÙÌ©ÔÌ©ÕÌ©¸Ì©¹Ì©¢Ì©£Ì©Ì©Ì©Ì©Ì©Ì©Ì©§ÕËÁ®ØË¿®ÐË¿®ÑËÁ®ÇËÁ®ÊË¿®ÒË¿®ÓËÁ®ÅËÁ®ÈË¿®ÌÁ®Ì¿®ÂË¿®ÃËÁ®¿ËÁ®ÂË¿®üË¿®ýËÁ®¯ËÁ®²Ë¿®¬Ë¿®­ËÁ®ªË¿®«ËÁ®¨Ë¿®©ËÁ®ËÌÁ®ÎÌ¿®ËÁ®Ë¿®ËÁ®Ë¿®ýÌÁ®Í¿®óËÁ®öË¿®ÎÌ¿®ÏÌÁ®÷ÊÁ®úÊ¿®ëÊÁ®îÊ¿®×ÊÁ®ÚÊ¿®ÑÊÁ®ÔÊ¿®ÊÊ¿®ËÊÁ®ÂÊ¿®ÃÊÁ®¢Ê¿®£ÊÁ®Ê¿®ÊÁ®öÉ¿®÷ÉÁ®äÉ¿®åÉÁ®ÐÉ¿®ÑÉÁ®ÆÉ¿®ÇÉÁ®ÂÉ¿®ÃÉÁ®¦É¿®§ÉÁ®É¿®ÉÁ®É¿®ÉÁ®úÈ¿®ûÈÁ®øÈ¿®ùÈÁ®§ÃÈû³ÆÈù³¾Èù³¿Èû³µÈû³¸Èù³ÀÈù³ÁÈû³³Èû³¶Èù³Éû³Éù³°Èù³±Èû³­Èû³°Èù³êÈù³ëÈû³Èû³ Èù³Èù³Èû³Èù³Èû³Èù³Èû³¹Éû³¼Éù³ÿÇû³Èù³õÇû³øÇù³ëÉû³îÉù³áÈû³äÈù³¼Éù³½Éû³åÇû³èÇù³ÙÇû³ÜÇù³ÅÇû³ÈÇù³¿Çû³ÂÇù³¸Çù³¹Çû³°Çù³±Çû³Çù³Çû³üÆù³ýÆû³äÆù³åÆû³ÒÆù³ÓÆû³¾Æù³¿Æû³´Æù³µÆû³°Æù³±Æû³Æù³Æû³þÅù³ÿÅû³òÅù³óÅû³èÅù³éÅû³æÅù³çÅû³§±Åµ¹´Å³¹¬Å³¹­Åµ¹£Åµ¹¦Å³¹®Å³¹¯Åµ¹¡Åµ¹¤Å³¹óÅµ¹öÅ³¹Å³¹Åµ¹Åµ¹Å³¹ØÅ³¹ÙÅµ¹Åµ¹Å³¹Å³¹Åµ¹Å³¹Åµ¹Å³¹Åµ¹§Æµ¹ªÆ³¹íÄµ¹ðÄ³¹ãÄµ¹æÄ³¹ÙÆµ¹ÜÆ³¹ÏÅµ¹ÒÅ³¹ªÆ³¹«Æµ¹ÓÄµ¹ÖÄ³¹ÇÄµ¹ÊÄ³¹³Äµ¹¶Ä³¹­Äµ¹°Ä³¹¦Ä³¹§Äµ¹Ä³¹Äµ¹þÃ³¹ÿÃµ¹êÃ³¹ëÃµ¹ÒÃ³¹ÓÃµ¹ÀÃ³¹ÁÃµ¹¬Ã³¹­Ãµ¹¢Ã³¹£Ãµ¹Ã³¹Ãµ¹Ã³¹Ãµ¹ìÂ³¹íÂµ¹àÂ³¹áÂµ¹ÖÂ³¹×Âµ¹ÔÂ³¹ÕÂµ¹§Âï¾¢Âí¾Âí¾Âï¾Âï¾Âí¾Âí¾Âï¾Âï¾Âí¾áÂï¾äÂí¾Âí¾Âï¾Âï¾Âí¾ÆÂí¾ÇÂï¾ùÁï¾üÁí¾öÁí¾÷Áï¾ôÁí¾õÁï¾òÁí¾óÁï¾Ãï¾Ãí¾ÛÁï¾ÞÁí¾ÑÁï¾ÔÁí¾ÇÃï¾ÊÃí¾½Âï¾ÀÂí¾Ãí¾Ãï¾ÁÁï¾ÄÁí¾µÁï¾¸Áí¾¡Áï¾¤Áí¾Áï¾Áí¾Áí¾Áï¾Áí¾Áï¾ìÀí¾íÀï¾ØÀí¾ÙÀï¾ÀÀí¾ÁÀï¾®Àí¾¯Àï¾Àí¾Àï¾Àí¾Àï¾Àí¾Àï¾ð¿í¾ñ¿ï¾Ú¿í¾Û¿ï¾Î¿í¾Ï¿ï¾Ä¿í¾Å¿ï¾Â¿í¾Ã¿ï¾§¿©Ä¿§Ä¿§Ä¿©Äÿ¾©Ä¿§Ä¿§Ä¿©Äý¾©Ä¿§ÄÏ¿©ÄÒ¿§Äú¾§Äû¾©Ä÷¾©Äú¾§Ä´¿§Äµ¿©Äç¾©Äê¾§Ää¾§Äå¾©Äâ¾§Äã¾©Äà¾§Äá¾©ÄÀ©ÄÀ§ÄÉ¾©ÄÌ¾§Ä¿¾©ÄÂ¾§ÄµÀ©Ä¸À§Ä«¿©Ä®¿§ÄÀ§ÄÀ©Ä¯¾©Ä²¾§Ä£¾©Ä¦¾§Ä¾©Ä¾§Ä¾©Ä¾§Ä¾§Ä¾©Äú½§Äû½©ÄÚ½§ÄÛ½©ÄÆ½§ÄÇ½©Ä®½§Ä¯½©Ä½§Ä½©Ä½§Ä½©Äþ¼§Äÿ¼©Äú¼§Äû¼©ÄÞ¼§Äß¼©ÄÈ¼§ÄÉ¼©Ä¼¼§Ä½¼©Ä²¼§Ä³¼©Ä°¼§Ä±¼©Ä§û»ãÉþ»áÉö»áÉ÷»ãÉí»ãÉð»áÉø»áÉù»ãÉë»ãÉî»áÉ½¼ãÉÀ¼áÉè»áÉé»ãÉå»ãÉè»áÉ¢¼áÉ£¼ãÉÕ»ãÉØ»áÉÒ»áÉÓ»ãÉÐ»áÉÑ»ãÉÎ»áÉÏ»ãÉñ¼ãÉô¼áÉ·»ãÉº»áÉ­»ãÉ°»áÉ£½ãÉ¦½áÉ¼ãÉ¼áÉô¼áÉõ¼ãÉ»ãÉ »áÉ»ãÉ»áÉýºãÉ»áÉ÷ºãÉúºáÉðºáÉñºãÉèºáÉéºãÉÈºáÉÉºãÉ´ºáÉµºãÉºáÉºãÉºáÉºãÉö¹áÉ÷¹ãÉì¹áÉí¹ãÉè¹áÉé¹ãÉÌ¹áÉÍ¹ãÉ¶¹áÉ·¹ãÉª¹áÉ«¹ãÉ ¹áÉ¡¹ãÉ¹áÉ¹ãÉ§é¸Ïì¸Ïä¸Ïå¸ÏÛ¸ÏÞ¸Ïæ¸Ïç¸ÏÙ¸ÏÜ¸Ï«¹Ï®¹ÏÖ¸Ï×¸ÏÓ¸ÏÖ¸Ï¹Ï¹ÏÃ¸ÏÆ¸ÏÀ¸ÏÁ¸Ï¾¸Ï¿¸Ï¼¸Ï½¸Ïß¹Ïâ¹Ï¥¸Ï¨¸Ï¸Ï¸ÏºÏºÏ¹Ï¹Ïâ¹Ïã¹Ï¸Ï¸Ïÿ·Ï¸Ïë·Ïî·Ïå·Ïè·ÏÞ·Ïß·ÏÖ·Ï×·Ï¶·Ï··Ï¢·Ï£·Ï·Ï·Ïø¶Ïù¶Ïä¶Ïå¶ÏÚ¶ÏÛ¶ÏÖ¶Ï×¶Ïº¶Ï»¶Ï¤¶Ï¥¶Ï¶Ï¶Ï¶Ï¶Ï¶Ï¶Ï§×µ×ÔÚµÕÔÒµÕÔÓµ×ÔÉµ×ÔÌµÕÔÔµÕÔÕµ×ÔÇµ×ÔÊµÕÔ¶×Ô¶ÕÔÄµÕÔÅµ×ÔÁµ×ÔÄµÕÔþµÕÔÿµ×Ô±µ×Ô´µÕÔ®µÕÔ¯µ×Ô¬µÕÔ­µ×ÔªµÕÔ«µ×ÔÍ¶×ÔÐ¶ÕÔµ×ÔµÕÔµ×ÔµÕÔÿ¶×Ô·ÕÔõµ×ÔøµÕÔÐ¶ÕÔÑ¶×Ôù´×Ôü´ÕÔí´×Ôð´ÕÔÙ´×ÔÜ´ÕÔÓ´×ÔÖ´ÕÔÌ´ÕÔÍ´×ÔÄ´ÕÔÅ´×Ô¤´ÕÔ¥´×Ô´ÕÔ´×Ôø³ÕÔù³×Ôæ³ÕÔç³×ÔÒ³ÕÔÓ³×ÔÈ³ÕÔÉ³×ÔÄ³ÕÔÅ³×Ô¨³ÕÔ©³×Ô³ÕÔ³×Ô³ÕÔ³×Ôü²ÕÔý²×Ôú²ÕÔû²×Ô§Å²ÚÈ²ÚÀ²ÚÁ²Ú·²Úº²ÚÂ²ÚÃ²Úµ²Ú¸²Ú³Ú³Ú²²Ú³²Ú¯²Ú²²Úì²Úí²Ú²Ú¢²Ú²Ú²Ú²Ú²Ú²Ú²Ú»³Ú¾³Ú²Ú²Ú÷±Úú±Úí³Úð³Úã²Úæ²Ú¾³Ú¿³Úç±Úê±ÚÛ±ÚÞ±ÚÇ±ÚÊ±ÚÁ±ÚÄ±Úº±Ú»±Ú²±Ú³±Ú±Ú±Úþ°Úÿ°Úæ°Úç°ÚÔ°ÚÕ°ÚÀ°ÚÁ°Ú¶°Ú·°Ú²°Ú³°Ú°Ú°Ú°Ú°Úô¯Úõ¯Úê¯Úë¯Úè¯Úé¯Ú§³¯Ëß¶¯Éß®¯Éß¯¯Ëß¥¯Ëß¨¯Éß°¯Éß±¯Ëß£¯Ëß¦¯Éßõ¯Ëßø¯Éß ¯Éß¡¯Ëß¯Ëß ¯ÉßÚ¯ÉßÛ¯Ëß¯Ëß¯Éß¯Éß¯Ëß¯Éß¯Ëß¯Éß¯Ëß©°Ëß¬°Éßï®Ëßò®Éßå®Ëßè®ÉßÛ°ËßÞ°ÉßÑ¯ËßÔ¯Éß¬°Éß­°ËßÕ®ËßØ®ÉßÉ®ËßÌ®Éßµ®Ëß¸®Éß¯®Ëß²®Éß¨®Éß©®Ëß ®Éß¡®Ëß®Éß®Ëßì­Éßí­ËßÔ­ÉßÕ­ËßÂ­ÉßÃ­Ëß®­Éß¯­Ëß¤­Éß¥­Ëß ­Éß¡­Ëß­Éß­Ëßî¬Éßï¬Ëßâ¬Éßã¬ËßØ¬ÉßÙ¬ËßÖ¬Éß×¬Ëß§¡¬å¤¬å¬å¬å¬å¬å¬å¬å¬å¬åã¬åæ¬å¬å¬å¬å¬åÈ¬åÉ¬åû«åþ«åø«åù«åö«å÷«åô«åõ«å­å­åÝ«åà«åÓ«åÖ«åÉ­åÌ­å¿¬åÂ¬å­å­åÃ«åÆ«å·«åº«å£«å¦«å«å «å«å«å«å«åîªåïªåÚªåÛªåÂªåÃªå°ªå±ªåªåªåªåªåªåªåò©åó©åÜ©åÝ©åÐ©åÑ©åÆ©åÇ©åÄ©åÅ©å§©¿ê©½ê©½ê©¿ê©¿ê©½ê©½ê©¿êÿ¨¿ê©½êÑ©¿êÔ©½êü¨½êý¨¿êù¨¿êü¨½ê¶©½ê·©¿êé¨¿êì¨½êæ¨½êç¨¿êä¨½êå¨¿êâ¨½êã¨¿êª¿êª½êË¨¿êÎ¨½êÁ¨¿êÄ¨½ê·ª¿êºª½ê­©¿ê°©½êª½êª¿ê±¨¿ê´¨½ê¥¨¿ê¨¨½ê¨¿ê¨½ê¨¿ê¨½ê¨½ê¨¿êü§½êý§¿êÜ§½êÝ§¿êÈ§½êÉ§¿ê°§½ê±§¿ê§½ê§¿ê§½ê§¿ê§½ê§¿êü¦½êý¦¿êà¦½êá¦¿êÊ¦½êË¦¿ê¾¦½ê¿¦¿ê´¦½êµ¦¿ê²¦½ê³¦¿ê§ý¥ùï¦÷ïø¥÷ïù¥ùïï¥ùïò¥÷ïú¥÷ïû¥ùïí¥ùïð¥÷ï¿¦ùïÂ¦÷ïê¥÷ïë¥ùïç¥ùïê¥÷ï¤¦÷ï¥¦ùï×¥ùïÚ¥÷ïÔ¥÷ïÕ¥ùïÒ¥÷ïÓ¥ùïÐ¥÷ïÑ¥ùïó¦ùïö¦÷ï¹¥ùï¼¥÷ï¯¥ùï²¥÷ï¥§ùï¨§÷ï¦ùï¦÷ïö¦÷ï÷¦ùï¥ùï¢¥÷ï¥ùï¥÷ïÿ¤ùï¥÷ïù¤ùïü¤÷ïò¤÷ïó¤ùïê¤÷ïë¤ùïÊ¤÷ïË¤ùï¶¤÷ï·¤ùï¤÷ï¤ùï¤÷ï¤ùïø£÷ïù£ùïî£÷ïï£ùïê£÷ïë£ùïÎ£÷ïÏ£ùï¸£÷ï¹£ùï¬£÷ï­£ùï¢£÷ï££ùï £÷ï¡£ùï§ë¢³õî¢±õæ¢±õç¢³õÝ¢³õà¢±õè¢±õé¢³õÛ¢³õÞ¢±õ­£³õ°£±õØ¢±õÙ¢³õÕ¢³õØ¢±õ£±õ£³õÅ¢³õÈ¢±õÂ¢±õÃ¢³õÀ¢±õÁ¢³õ¾¢±õ¿¢³õá£³õä£±õ§¢³õª¢±õ¢³õ ¢±õ¤³õ¤±õ£³õ£±õä£±õå£³õ¢³õ¢±õ¢³õ¢±õí¡³õð¡±õç¡³õê¡±õà¡±õá¡³õØ¡±õÙ¡³õ¸¡±õ¹¡³õ¤¡±õ¥¡³õ¡±õ¡³õú ±õû ³õæ ±õç ³õÜ ±õÝ ³õØ ±õÙ ³õ¼ ±õ½ ³õ¦ ±õ§ ³õ ±õ ³õ ±õ ³õ ±õ ³õ§ÙíúÜëúÔëúÕíúËíúÎëúÖëú×íúÉíúÌëú íú ëúÆëúÇíúÃíúÆëú ëú íú³íú¶ëú°ëú±íú®ëú¯íú¬ëú­íúÏ íúÒ ëúíúëúíúëú¡íú¡ëú÷íúúëúÒ ëúÓ íúûíúþëúïíúòëúÛíúÞëúÕíúØëúÎëúÏíúÆëúÇíú¦ëú§íúëúíúúëúûíúèëúéíúÔëúÕíúÊëúËíúÆëúÇíúªëú«íúëúíúëúíúþëúÿíúüëúýíú§Ç§Ê¥Â¥Ã§¹§¼¥Ä¥Å§·§º¥§¥´¥µ§±§´¥î¥ï§¡§¤¥¥§¥§¥§½§À¥§¥ù§ü¥ï§ò¥å§è¥À¥Á§é§ì¥Ý§à¥É§Ì¥Ã§Æ¥¼¥½§´¥µ§¥§¥§è¥é§Ö¥×§Â¥Ã§¸¥¹§´¥µ§¥§¥§ö¥÷§ì¥í§ê¥ë§§µá¸ß°ß±á§áªß²ß³á¥á¨ß÷áúß¢ß£áá¢ßÜßÝááßßáßáßá«á®ßñáôßçáêßÝáàßÓáÖß®ß¯á×áÚßËáÎß·áºß±á´ßªß«á¢ß£áßáîßïáÖß×áÄßÅá°ß±á¦ß§á¢ß£áßáðßñáäßåáÚßÛáØßÙá§£¦ ¡åèÊËýúûøùö÷ßâÕØËÎÁÄÅÈ¹¼¥¨¢ðñÜÝÄÅ²³ôõÞßÒÓÈÉÆÇ§ÕÓÓÕÕÓÓÕÕÓÓÕÖÓþÓÿÕûÕþÓ¸Ó¹ÕëÕîÓèÓéÕæÓçÕäÓåÕÕÓÍÕÐÓÃÕÆÓ¹Õ¼Ó¯Õ²ÓÓÕ³Õ¶Ó§ÕªÓÕÓÕÓÓÕþÓÿÕÞÓßÕÊÓËÕ²Ó³Õ Ó¡ÕÓÕÓÕþÓÿÕâÓãÕÌÓÍÕÀÓÁÕ¶Ó·Õ´ÓµÕ§ÿúûñôüýïòÁÄìíéì¦§ÙÜÖ×ÔÕÒÓõø»¾±´§ª øù¡¤ûþôõìíÌÍ¸¹ ¡úûðñìíÐÑº»®¯¤¥¢£§íÉðÇèÇéÉßÉâÇêÇëÉÝÉàÇ¯É²ÇÚÇÛÉ×ÉÚÇÇÉÇÉÊÇÄÇÅÉÂÇÃÉÀÇÁÉãÉæÇ©É¬ÇÉ¢ÇÉÇÉÇæÇçÉÉÇÉÇïÉòÇéÉìÇâÇãÉÚÇÛÉºÇ»É¦Ç§ÉÇÉüÇýÉèÇéÉÞÇßÉÚÇÛÉ¾Ç¿É¨Ç©ÉÇÉÇÉÇÉ§Û¡Þ¡Ö¡×¡Í¡Ð¡Ø¡Ù¡Ë¡Î¡¡ ¡È¡É¡Å¡È¡¡¡µ¡¸¡²¡³¡°¡±¡®¡¯¡Ñ¡Ô¡¡¡¡¡¡¡ù¡ü¡Ô¡Õ¡ý¡¡ñ¡ô¡Ý¡à¡×¡Ú¡Ð¡Ñ¡È¡É¡¨¡©¡¡¡ü¡ý¡ê¡ë¡Ö¡×¡Ì¡Í¡È¡É¡¬¡­¡¡¡¡¡¡¡þ¡ÿ¡§É½¦Ì»¦Ä»¦Å½¦»½¦¾»¦Æ»¦Ç½¦¹½¦¼»¦½¦»¦¶»¦·½¦³½¦¶»¦ð»¦ñ½¦£½¦¦»¦ »¦¡½¦»¦½¦»¦½¦¿½¦Â»¦½¦»¦û½¦þ»¦ñ½¦ô»¦ç½¦ê»¦Â»¦Ã½¦ë½¦î»¦ß½¦â»¦Ë½¦Î»¦Å½¦È»¦¾»¦¿½¦¶»¦·½¦»¦½¦»¦½¦ê»¦ë½¦Ø»¦Ù½¦Ä»¦Å½¦º»¦»½¦¶»¦·½¦»¦½¦»¦½¦ø»¦ù½¦î»¦ï½¦ì»¦í½¦§·÷«ºõ«²õ«³÷«©÷«¬õ«´õ«µ÷«§÷«ªõ«ù÷«üõ«¤õ«¥÷«¡÷«¤õ«Þõ«ß÷«÷«õ«õ«÷«õ«÷«õ«÷«­÷«°õ«ó÷«öõ«é÷«ìõ«ß÷«âõ«Õ÷«Øõ«°õ«±÷«Ù÷«Üõ«Í÷«Ðõ«¹÷«¼õ«³÷«¶õ«¬õ«­÷«¤õ«¥÷«õ«÷«ðõ«ñ÷«Øõ«Ù÷«Æõ«Ç÷«²õ«³÷«¨õ«©÷«¤õ«¥÷«õ«÷«òõ«ó÷«æõ«ç÷«Üõ«Ý÷«Úõ«Û÷«§á¦»ä¦¹Ü¦¹Ý¦»Ó¦»Ö¦¹Þ¦¹ß¦»Ñ¦»Ô¦¹£§»¦§¹Î¦¹Ï¦»Ë¦»Î¦¹§¹§»»¦»¾¦¹¸¦¹¹¦»¶¦¹·¦»´¦¹µ¦»×§»Ú§¹¦» ¦¹¦»¦¹¨»¨¹ÿ¦»§¹Ú§¹Û§»¦»¦¹÷¥»ú¥¹ã¥»æ¥¹Ý¥»à¥¹Ö¥¹×¥»Î¥¹Ï¥»®¥¹¯¥»¥¹¥»¥¹¥»ð¤¹ñ¤»Ü¤¹Ý¤»Ò¤¹Ó¤»Î¤¹Ï¤»²¤¹³¤»¤¹¤»¤¹¤»¤¹¤»¤¹¤»§Ï£õ
+Ò£ó
+Ê£ó
+Ë£õ
+Á£õ
+Ä£ó
+Ì£ó
+Í£õ
+¿£õ
+Â£ó
+¤õ
+¤ó
+¼£ó
+½£õ
+¹£õ
+¼£ó
+ö£ó
+÷£õ
+©£õ
+¬£ó
+¦£ó
+§£õ
+¤£ó
+¥£õ
+¢£ó
+££õ
+Å¤õ
+È¤ó
+£õ
+£ó
+£õ
+£ó
+÷¤õ
+ú¤ó
+í£õ
+ð£ó
+È¤ó
+É¤õ
+ñ¢õ
+ô¢ó
+å¢õ
+è¢ó
+Ñ¢õ
+Ô¢ó
+Ë¢õ
+Î¢ó
+Ä¢ó
+Å¢õ
+¼¢ó
+½¢õ
+¢ó
+¢õ
+¢ó
+¢õ
+ð¡ó
+ñ¡õ
+Þ¡ó
+ß¡õ
+Ê¡ó
+Ë¡õ
+À¡ó
+Á¡õ
+¼¡ó
+½¡õ
+ ¡ó
+¡¡õ
+¡ó
+¡õ
+þ ó
+ÿ õ
+ô ó
+õ õ
+ò ó
+ó õ
+§½ ¯À ­¸ ­¹ ¯¯ ¯² ­º ­» ¯­ ¯° ­ÿ ¯¡­ª ­« ¯§ ¯ª ­ä ­å ¯ ¯ ­ ­ ¯ ­ ¯ ­ ¯³¡¯¶¡­ù¯ü­ï¯ò­å¡¯è¡­Û ¯Þ ­¶¡­·¡¯ß¯â­Ó¯Ö­¿¯Â­¹¯¼­²­³¯ª­«¯­¯ö­÷¯Þ­ß¯Ì­Í¯¸­¹¯®­¯¯ª­«¯­¯ø­ù¯ì­í¯â­ã¯à­á¯§«é®ç¦ç§éé ç¨ç©ééçíéðççééçÒçÓééççéçéþçÿé¡é¤ççéêçÝéàçÓéÖçÉéÌç¤ç¥éÍéÐçÁéÄç­é°ç§éªç ç¡éçéøçùéäçåéÌçÍéºç»é¦ç§éçéçéüçýéæççéÚçÛéÐçÑéÎçÏé§£¡¡££¡¡££¡Û£Þ¡¡££¡À¡Á£ó£ö¡ð¡ñ£î¡ï£ì¡í££¡Õ£Ø¡Ë£Î¡Á£Ä¡·£º¡¡£»£¾¡¯£²¡£¡£¡¡£¡£æ¡ç£Ò¡Ó£º¡»£¨¡©£¡£¡£¡£ê¡ë£Ô¡Õ£È¡É£¾¡¿£¼¡½£§Ý Û Û Ý ùÝ üÛ Û Ý ÷Ý úÛ ÉÝ ÌÛ ôÛ õÝ ñÝ ôÛ ®Û ¯Ý áÝ äÛ ÞÛ ßÝ ÜÛ ÝÝ ÚÛ ÛÝ ýÝ Û ÃÝ ÆÛ ¹Ý ¼Û ¯Ý ²Û ¥Ý ¨Û Û Ý ©Ý ¬Û Ý  Û Ý Û Ý Û üÛ ýÝ ôÛ õÝ ÔÛ ÕÝ ÀÛ ÁÝ ¨Û ©Ý Û Ý Û Ý øÛ ùÝ ôÛ õÝ ØÛ ÙÝ ÂÛ ÃÝ ¶Û ·Ý ¬Û ­Ý ªÛ «Ý §õ&ø&ð&ñ&ç&ê&ò&ó&å&è&·&º&â&ã&ß&â&&&Ï&Ò&Ì&Í&Ê&Ë&È&É&ë&î&±&´&§&ª&& &&&î&ï&&&&&÷&ú&ñ&ô&ê&ë&â&ã&Â&Ã&®&¯&&&&&ð&ñ&æ&ç&â&ã&Æ&Ç&°&±&¤&¥&&&&&§ãÑ+æÏ+ÞÏ+ßÑ+ÕÑ+ØÏ+àÏ+áÑ+ÓÑ+ÖÏ+¥Ñ+¨Ï+ÐÏ+ÑÑ+ÍÑ+ÐÏ+Ï+Ñ+½Ñ+ÀÏ+ºÏ+»Ñ+¸Ï+¹Ñ+¶Ï+·Ñ+ÙÑ+ÜÏ+Ñ+¢Ï+Ñ+Ï+Ñ+Ï+Ñ+Ï+ÜÏ+ÝÑ+Ñ+Ï+ùÑ+üÏ+åÑ+èÏ+ßÑ+âÏ+ØÏ+ÙÑ+ÐÏ+ÑÑ+°Ï+±Ñ+Ï+Ñ+Ï+Ñ+òÏ+óÑ+ÞÏ+ßÑ+ÔÏ+ÕÑ+ÐÏ+ÑÑ+´Ï+µÑ+Ï+Ñ+Ï+Ñ+Ï+Ñ+Ï+Ñ+§Ñ1Ô1Ì1Í1Ã1Æ1Î1Ï1Á1Ä111¾1¿1»1¾1ø1ù1«1®1¨1©1¦1§1¤1¥1Ç1Ê11111ù1ü1ï1ò1Ê1Ë1ó1ö1ç1ê1Ó1Ö1Í1Ð1Æ1Ç1¾1¿11111ò1ó1à1á1Ì1Í1Â1Ã1¾1¿1¢1£11111ö1÷1ô1õ1§¿Å6ÂÃ6ºÃ6»Å6±Å6´Ã6¼Ã6½Å6¯Å6²Ã6Å6Ã6¬Ã6­Å6©Å6¬Ã6æÃ6çÅ6Å6Ã6Ã6Å6Ã6Å6Ã6Å6µÅ6¸Ã6ûÅ6þÃ6ñÅ6ôÃ6çÅ6êÃ6ÝÅ6àÃ6¸Ã6¹Å6áÅ6äÃ6ÕÅ6ØÃ6ÁÅ6ÄÃ6»Å6¾Ã6´Ã6µÅ6¬Ã6­Å6Ã6Å6øÃ6ùÅ6àÃ6áÅ6ÎÃ6ÏÅ6ºÃ6»Å6°Ã6±Å6¬Ã6­Å6Ã6Å6úÃ6ûÅ6îÃ6ïÅ6äÃ6åÅ6âÃ6ãÅ6§­ÿ;°ý;¨ý;©ÿ;ÿ;¢ý;ªý;«ÿ;ÿ; ý;ïÿ;òý;ý;ÿ;ÿ;ý;Ôý;Õÿ;ÿ;ý;ý;ÿ;ý;ÿ;ý;ÿ;£ÿ;¦ý;éÿ;ìý;ßÿ;âý;Õÿ;Øý;Ëÿ;Îý;¦ý;§ÿ;Ïÿ;Òý;Ãÿ;Æý;¯ÿ;²ý;©ÿ;¬ý;¢ý;£ÿ;ý;ÿ;úý;ûÿ;æý;çÿ;Îý;Ïÿ;¼ý;½ÿ;¨ý;©ÿ;ý;ÿ;ý;ÿ;þý;ÿÿ;èý;éÿ;Üý;Ýÿ;Òý;Óÿ;Ðý;Ñÿ;§¹A·A·A¹A¹A·A·A¹A¹A·AÝ¹Aà·A·A¹A¹A·AÂ·AÃ¹Aõ¹Aø·Aò·Aó¹Að·Añ¹Aî·Aï¹A¹A·A×¹AÚ·AÍ¹AÐ·AÃ¹AÆ·A¹¹A¼·A·A¹A½¹AÀ·A±¹A´·A¹A ·A¹A·A·A¹A·A¹Aè·Aé¹AÔ·AÕ¹A¼·A½¹Aª·A«¹A·A¹A·A¹A·A¹Aì·Aí¹AÖ·A×¹AÊ·AË¹AÀ·AÁ¹A¾·A¿¹A§óFñFñFóFûóFþñFñFóFùóFüñFËóFÎñFöñF÷óFóóFöñF°ñF±óFãóFæñFàñFáóFÞñFßóFÜñFÝóFÿóFñFÅóFÈñF»óF¾ñF±óF´ñF§óFªñFñFóF«óF®ñFóF¢ñFóFñFóFñFþÿñFÿÿóFöÿñF÷ÿóFÖÿñF×ÿóFÂÿñFÃÿóFªÿñF«ÿóFÿñFÿóFÿñFÿóFúþñFûþóFöþñF÷þóFÚþñFÛþóFÄþñFÅþóF¸þñF¹þóF®þñF¯þóF¬þñF­þóF§÷ý­Lúý«Lòý«Lóý­Léý­Lìý«Lôý«Lõý­Lçý­Lêý«L¹þ­L¼þ«Läý«Låý­Láý­Läý«Lþ«Lþ­LÑý­LÔý«LÎý«LÏý­LÌý«LÍý­LÊý«LËý­Líþ­Lðþ«L³ý­L¶ý«L©ý­L¬ý«Lÿ­L¢ÿ«Lþ­Lþ«Lðþ«Lñþ­Lý­Lý«Lý­Lý«Lùü­Lüü«Lóü­Löü«Lìü«Líü­Läü«Låü­LÄü«LÅü­L°ü«L±ü­Lü«Lü­Lü«Lü­Lòû«Lóû­Lèû«Léû­Läû«Låû­LÈû«LÉû­L²û«L³û­L¦û«L§û­Lû«Lû­Lû«Lû­L§åúçQèúåQàúåQáúçQ×úçQÚúåQâúåQãúçQÕúçQØúåQ§ûçQªûåQÒúåQÓúçQÏúçQÒúåQûåQûçQ¿úçQÂúåQ¼úåQ½úçQºúåQ»úçQ¸úåQ¹úçQÛûçQÞûåQ¡úçQ¤úåQúçQúåQüçQüåQûçQûåQÞûåQßûçQúçQúåQûùçQþùåQçùçQêùåQáùçQäùåQÚùåQÛùçQÒùåQÓùçQ²ùåQ³ùçQùåQùçQùåQùçQôøåQõøçQàøåQáøçQÖøåQ×øçQÒøåQÓøçQ¶øåQ·øçQ øåQ¡øçQøåQøçQøåQøçQøåQøçQ§Ó÷¡WÖ÷WÎ÷WÏ÷¡WÅ÷¡WÈ÷WÐ÷WÑ÷¡WÃ÷¡WÆ÷Wø¡WøWÀ÷WÁ÷¡W½÷¡WÀ÷Wú÷Wû÷¡W­÷¡W°÷Wª÷W«÷¡W¨÷W©÷¡W¦÷W§÷¡WÉø¡WÌøW÷¡W÷W÷¡W÷Wûø¡WþøWñ÷¡Wô÷WÌøWÍø¡Wõö¡WøöWéö¡WìöWÕö¡WØöWÏö¡WÒöWÈöWÉö¡WÀöWÁö¡W öW¡ö¡WöWö¡WôõWõõ¡WâõWãõ¡WÎõWÏõ¡WÄõWÅõ¡WÀõWÁõ¡W¤õW¥õ¡WõWõ¡WõWõ¡WøôWùô¡WöôW÷ô¡W§ÁôÛ\ÄôÙ\¼ôÙ\½ôÛ\³ôÛ\¶ôÙ\¾ôÙ\¿ôÛ\±ôÛ\´ôÙ\õÛ\õÙ\®ôÙ\¯ôÛ\«ôÛ\®ôÙ\èôÙ\éôÛ\ôÛ\ôÙ\ôÙ\ôÛ\ôÙ\ôÛ\ôÙ\ôÛ\·õÛ\ºõÙ\ýóÛ\ôÙ\óóÛ\öóÙ\éõÛ\ìõÙ\ßôÛ\âôÙ\ºõÙ\»õÛ\ãóÛ\æóÙ\×óÛ\ÚóÙ\ÃóÛ\ÆóÙ\½óÛ\ÀóÙ\¶óÙ\·óÛ\®óÙ\¯óÛ\óÙ\óÛ\úòÙ\ûòÛ\âòÙ\ãòÛ\ÐòÙ\ÑòÛ\¼òÙ\½òÛ\²òÙ\³òÛ\®òÙ\¯òÛ\òÙ\òÛ\üñÙ\ýñÛ\ðñÙ\ññÛ\æñÙ\çñÛ\äñÙ\åñÛ\§¯ñb²ñbªñb«ñb¡ñb¤ñb¬ñb­ñbñb¢ñbññbôñbñbñbñbñbÖñb×ñbñbñbñbñbñbñbñbñb¥òb¨òbëðbîðbáðbäðb×òbÚòbÍñbÐñb¨òb©òbÑðbÔðbÅðbÈðb±ðb´ðb«ðb®ðb¤ðb¥ðbðbðbüïbýïbèïbéïbÐïbÑïb¾ïb¿ïbªïb«ïb ïb¡ïbïbïbïbïbêîbëîbÞîbßîbÔîbÕîbÒîbÓîb§îÏg îÍgîÍgîÏgîÏgîÍgîÍgîÏgîÏgîÍgßîÏgâîÍgîÍgîÏgîÏgîÍgÄîÍgÅîÏg÷íÏgúíÍgôíÍgõíÏgòíÍgóíÏgðíÍgñíÏgïÏgïÍgÙíÏgÜíÍgÏíÏgÒíÍgÅïÏgÈïÍg»îÏg¾îÍgïÍgïÏg¿íÏgÂíÍg³íÏg¶íÍgíÏg¢íÍgíÏgíÍgíÍgíÏgíÍgíÏgêìÍgëìÏgÖìÍg×ìÏg¾ìÍg¿ìÏg¬ìÍg­ìÏgìÍgìÏgìÍgìÏgìÍgìÏgîëÍgïëÏgØëÍgÙëÏgÌëÍgÍëÏgÂëÍgÃëÏgÀëÍgÁëÏg§ëmëmëmëmýêmëmëmëmûêmþêmÍëmÐëmøêmùêmõêmøêm²ëm³ëmåêmèêmâêmãêmàêmáêmÞêmßêmìmìmÇêmÊêm½êmÀêm³ìm¶ìm©ëm¬ëmìmìm­êm°êm¡êm¤êmêmêmêmêmêmêmøémùémØémÙémÄémÅém¬ém­émémémémémüèmýèmøèmùèmÜèmÝèmÆèmÇèmºèm»èm°èm±èm®èm¯èm§ùçÃrüçÁrôçÁrõçÃrëçÃrîçÁröçÁr÷çÃréçÃrìçÁr»èÃr¾èÁræçÁrççÃrãçÃræçÁr èÁr¡èÃrÓçÃrÖçÁrÐçÁrÑçÃrÎçÁrÏçÃrÌçÁrÍçÃrïèÃròèÁrµçÃr¸çÁr«çÃr®çÁr¡éÃr¤éÁrèÃrèÁròèÁróèÃrçÃrçÁrçÃrçÁrûæÃrþæÁrõæÃrøæÁrîæÁrïæÃrææÁrçæÃrÆæÁrÇæÃr²æÁr³æÃræÁræÃræÁræÃrôåÁrõåÃrêåÁrëåÃræåÁrçåÃrÊåÁrËåÃr´åÁrµåÃr¨åÁr©åÃråÁråÃråÁråÃr§çäýwêäûwâäûwãäýwÙäýwÜäûwääûwåäýw×äýwÚäûw©åýw¬åûwÔäûwÕäýwÑäýwÔäûwåûwåýwÁäýwÄäûw¾äûw¿äýw¼äûw½äýwºäûw»äýwÝåýwàåûw£äýw¦äûwäýwäûwæýwæûwåýwåûwàåûwáåýwäýwäûwýãýwäûwéãýwìãûwããýwæãûwÜãûwÝãýwÔãûwÕãýw´ãûwµãýw ãûw¡ãýwãûwãýwöâûw÷âýwââûwãâýwØâûwÙâýwÔâûwÕâýw¸âûw¹âýw¢âûw£âýwâûwâýwâûwâýwâûwâýw§Õá·}Øáµ}Ðáµ}Ñá·}Çá·}Êáµ}Òáµ}Óá·}Åá·}Èáµ}â·}âµ}Âáµ}Ãá·}¿á·}Âáµ}üáµ}ýá·}¯á·}²áµ}¬áµ}­á·}ªáµ}«á·}¨áµ}©á·}Ëâ·}Îâµ}á·}áµ}á·}áµ}ýâ·}ãµ}óá·}öáµ}Îâµ}Ïâ·}÷à·}úàµ}ëà·}îàµ}×à·}Úàµ}Ñà·}Ôàµ}Êàµ}Ëà·}Âàµ}Ãà·}¢àµ}£à·}àµ}à·}ößµ}÷ß·}äßµ}åß·}Ðßµ}Ñß·}Æßµ}Çß·}Âßµ}Ãß·}¦ßµ}§ß·}ßµ}ß·}ßµ}ß·}úÞµ}ûÞ·}øÞµ}ùÞ·}§ÃÞñÆÞï¾Þï¿ÞñµÞñ¸ÞïÀÞïÁÞñ³Þñ¶Þïßñßï°Þï±Þñ­Þñ°ÞïêÞïëÞñÞñ ÞïÞïÞñÞïÞñÞïÞñ¹ßñ¼ßïÿÝñÞïõÝñøÝïëßñîßïáÞñäÞï¼ßï½ßñåÝñèÝïÙÝñÜÝïÅÝñÈÝï¿ÝñÂÝï¸Ýï¹Ýñ°Ýï±ÝñÝïÝñüÜïýÜñäÜïåÜñÒÜïÓÜñ¾Üï¿Üñ´ÜïµÜñ°Üï±ÜñÜïÜñþÛïÿÛñòÛïóÛñèÛïéÛñæÛïçÛñ§±Û«´Û©¬Û©­Û«£Û«¦Û©®Û©¯Û«¡Û«¤Û©óÛ«öÛ©Û©Û«Û«Û©ØÛ©ÙÛ«Û«Û©Û©Û«Û©Û«Û©Û«§Ü«ªÜ©íÚ«ðÚ©ãÚ«æÚ©ÙÜ«ÜÜ©ÏÛ«ÒÛ©ªÜ©«Ü«ÓÚ«ÖÚ©ÇÚ«ÊÚ©³Ú«¶Ú©­Ú«°Ú©¦Ú©§Ú«Ú©Ú«þÙ©ÿÙ«êÙ©ëÙ«ÒÙ©ÓÙ«ÀÙ©ÁÙ«¬Ù©­Ù«¢Ù©£Ù«Ù©Ù«Ù©Ù«ìØ©íØ«àØ©áØ«ÖØ©×Ø«ÔØ©ÕØ«§Øå¢ØãØãØåØåØãØãØåØåØãáØåäØãØãØåØåØãÆØãÇØåù×åü×ãö×ã÷×åô×ãõ×åò×ãó×åÙåÙãÛ×åÞ×ãÑ×åÔ×ãÇÙåÊÙã½ØåÀØãÙãÙåÁ×åÄ×ãµ×å¸×ã¡×å¤×ã×å×ã×ã×å×ã×åìÖãíÖåØÖãÙÖåÀÖãÁÖå®Öã¯ÖåÖãÖåÖãÖåÖãÖåðÕãñÕåÚÕãÛÕåÎÕãÏÕåÄÕãÅÕåÂÕãÃÕå§ÕÕÕÕÿÔÕÕÕýÔÕÏÕÒÕúÔûÔ÷ÔúÔ´ÕµÕçÔêÔäÔåÔâÔãÔàÔáÔÖÖÉÔÌÔ¿ÔÂÔµÖ¸Ö«Õ®ÕÖÖ¯Ô²Ô£Ô¦ÔÔÔÔÔÔÔúÓûÓÚÓÛÓÆÓÇÓ®Ó¯ÓÓÓÓÓþÒÿÒúÒûÒÞÒßÒÈÒÉÒ¼Ò½Ò²Ò³Ò°Ò±Ò§ûÑÙþÑ×öÑ×÷ÑÙíÑÙðÑ×øÑ×ùÑÙëÑÙîÑ×½ÒÙÀÒ×èÑ×éÑÙåÑÙèÑ×¢Ò×£ÒÙÕÑÙØÑ×ÒÑ×ÓÑÙÐÑ×ÑÑÙÎÑ×ÏÑÙñÒÙôÒ×·ÑÙºÑ×­ÑÙ°Ñ×£ÓÙ¦Ó×ÒÙÒ×ôÒ×õÒÙÑÙ Ñ×ÑÙÑ×ýÐÙÑ×÷ÐÙúÐ×ðÐ×ñÐÙèÐ×éÐÙÈÐ×ÉÐÙ´Ð×µÐÙÐ×ÐÙÐ×ÐÙöÏ×÷ÏÙìÏ×íÏÙèÏ×éÏÙÌÏ×ÍÏÙ¶Ï×·ÏÙªÏ×«ÏÙ Ï×¡ÏÙÏ×ÏÙ§éÎìÎäÎåÎÛÎÞÎæÎçÎÙÎÜÎ«Ï®ÏÖÎ×ÎÓÎÖÎÏÏÃÎÆÎÀÎÁÎ¾Î¿Î¼Î½ÎßÏâÏ¥Î¨ÎÎÎÐÐÏÏâÏãÏÎÎÿÍÎëÍîÍåÍèÍÞÍßÍÖÍ×Í¶Í·Í¢Í£ÍÍÍøÌùÌäÌåÌÚÌÛÌÖÌ×ÌºÌ»Ì¤Ì¥ÌÌÌÌÌÌÌ§×ËÍ£ÚËË£ÒËË£ÓËÍ£ÉËÍ£ÌËË£ÔËË£ÕËÍ£ÇËÍ£ÊËË£ÌÍ£ÌË£ÄËË£ÅËÍ£ÁËÍ£ÄËË£þËË£ÿËÍ£±ËÍ£´ËË£®ËË£¯ËÍ£¬ËË£­ËÍ£ªËË£«ËÍ£ÍÌÍ£ÐÌË£ËÍ£ËË£ËÍ£ËË£ÿÌÍ£ÍË£õËÍ£øËË£ÐÌË£ÑÌÍ£ùÊÍ£üÊË£íÊÍ£ðÊË£ÙÊÍ£ÜÊË£ÓÊÍ£ÖÊË£ÌÊË£ÍÊÍ£ÄÊË£ÅÊÍ£¤ÊË£¥ÊÍ£ÊË£ÊÍ£øÉË£ùÉÍ£æÉË£çÉÍ£ÒÉË£ÓÉÍ£ÈÉË£ÉÉÍ£ÄÉË£ÅÉÍ£¨ÉË£©ÉÍ£ÉË£ÉÍ£ÉË£ÉÍ£üÈË£ýÈÍ£úÈË£ûÈÍ£§ÅÈ©ÈÈ©ÀÈ©ÁÈ©·È©ºÈ©ÂÈ©ÃÈ©µÈ©¸È©É©É©²È©³È©¯È©²È©ìÈ©íÈ©È©¢È©È©È©È©È©È©È©»É©¾É©È©È©÷Ç©úÇ©íÉ©ðÉ©ãÈ©æÈ©¾É©¿É©çÇ©êÇ©ÛÇ©ÞÇ©ÇÇ©ÊÇ©ÁÇ©ÄÇ©ºÇ©»Ç©²Ç©³Ç©Ç©Ç©þÆ©ÿÆ©æÆ©çÆ©ÔÆ©ÕÆ©ÀÆ©ÁÆ©¶Æ©·Æ©²Æ©³Æ©Æ©Æ©Æ©Æ©ôÅ©õÅ©êÅ©ëÅ©èÅ©éÅ©§³ÅÁ®¶Å¿®®Å¿®¯ÅÁ®¥ÅÁ®¨Å¿®°Å¿®±ÅÁ®£ÅÁ®¦Å¿®õÅÁ®øÅ¿® Å¿®¡ÅÁ®ÅÁ® Å¿®ÚÅ¿®ÛÅÁ®ÅÁ®Å¿®Å¿®ÅÁ®Å¿®ÅÁ®Å¿®ÅÁ®©ÆÁ®¬Æ¿®ïÄÁ®òÄ¿®åÄÁ®èÄ¿®ÛÆÁ®ÞÆ¿®ÑÅÁ®ÔÅ¿®¬Æ¿®­ÆÁ®ÕÄÁ®ØÄ¿®ÉÄÁ®ÌÄ¿®µÄÁ®¸Ä¿®¯ÄÁ®²Ä¿®¨Ä¿®©ÄÁ® Ä¿®¡ÄÁ®Ä¿®ÄÁ®ìÃ¿®íÃÁ®ÔÃ¿®ÕÃÁ®ÂÃ¿®ÃÃÁ®®Ã¿®¯ÃÁ®¤Ã¿®¥ÃÁ® Ã¿®¡ÃÁ®Ã¿®ÃÁ®îÂ¿®ïÂÁ®âÂ¿®ãÂÁ®ØÂ¿®ÙÂÁ®ÖÂ¿®×ÂÁ®§¡Âû³¤Âù³Âù³Âû³Âû³Âù³Âù³Âû³Âû³Âù³ãÂû³æÂù³Âù³Âû³Âû³Âù³ÈÂù³ÉÂû³ûÁû³þÁù³øÁù³ùÁû³öÁù³÷Áû³ôÁù³õÁû³Ãû³Ãù³ÝÁû³àÁù³ÓÁû³ÖÁù³ÉÃû³ÌÃù³¿Âû³ÂÂù³Ãù³Ãû³ÃÁû³ÆÁù³·Áû³ºÁù³£Áû³¦Áù³Áû³ Áù³Áù³Áû³Áù³Áû³îÀù³ïÀû³ÚÀù³ÛÀû³ÂÀù³ÃÀû³°Àù³±Àû³Àù³Àû³Àù³Àû³Àù³Àû³ò¿ù³ó¿û³Ü¿ù³Ý¿û³Ð¿ù³Ñ¿û³Æ¿ù³Ç¿û³Ä¿ù³Å¿û³§¿µ¹¿³¹¿³¹¿µ¹¿µ¹¿³¹¿³¹¿µ¹ÿ¾µ¹¿³¹Ñ¿µ¹Ô¿³¹ü¾³¹ý¾µ¹ù¾µ¹ü¾³¹¶¿³¹·¿µ¹é¾µ¹ì¾³¹æ¾³¹ç¾µ¹ä¾³¹å¾µ¹â¾³¹ã¾µ¹Àµ¹À³¹Ë¾µ¹Î¾³¹Á¾µ¹Ä¾³¹·Àµ¹ºÀ³¹­¿µ¹°¿³¹À³¹Àµ¹±¾µ¹´¾³¹¥¾µ¹¨¾³¹¾µ¹¾³¹¾µ¹¾³¹¾³¹¾µ¹ü½³¹ý½µ¹Ü½³¹Ý½µ¹È½³¹É½µ¹°½³¹±½µ¹½³¹½µ¹½³¹½µ¹½³¹½µ¹ü¼³¹ý¼µ¹à¼³¹á¼µ¹Ê¼³¹Ë¼µ¹¾¼³¹¿¼µ¹´¼³¹µ¼µ¹²¼³¹³¼µ¹§ý»ï¾¼í¾ø»í¾ù»ï¾ï»ï¾ò»í¾ú»í¾û»ï¾í»ï¾ð»í¾¿¼ï¾Â¼í¾ê»í¾ë»ï¾ç»ï¾ê»í¾¤¼í¾¥¼ï¾×»ï¾Ú»í¾Ô»í¾Õ»ï¾Ò»í¾Ó»ï¾Ð»í¾Ñ»ï¾ó¼ï¾ö¼í¾¹»ï¾¼»í¾¯»ï¾²»í¾¥½ï¾¨½í¾¼ï¾¼í¾ö¼í¾÷¼ï¾»ï¾¢»í¾»ï¾»í¾ÿºï¾»í¾ùºï¾üºí¾òºí¾óºï¾êºí¾ëºï¾Êºí¾Ëºï¾¶ºí¾·ºï¾ºí¾ºï¾ºí¾ºï¾ø¹í¾ù¹ï¾î¹í¾ï¹ï¾ê¹í¾ë¹ï¾Î¹í¾Ï¹ï¾¸¹í¾¹¹ï¾¬¹í¾­¹ï¾¢¹í¾£¹ï¾ ¹í¾¡¹ï¾§ë¸©Äî¸§Äæ¸§Äç¸©ÄÝ¸©Äà¸§Äè¸§Äé¸©ÄÛ¸©ÄÞ¸§Ä­¹©Ä°¹§ÄØ¸§ÄÙ¸©ÄÕ¸©ÄØ¸§Ä¹§Ä¹©ÄÅ¸©ÄÈ¸§ÄÂ¸§ÄÃ¸©ÄÀ¸§ÄÁ¸©Ä¾¸§Ä¿¸©Äá¹©Ää¹§Ä§¸©Äª¸§Ä¸©Ä ¸§Äº©Äº§Ä¹©Ä¹§Ää¹§Äå¹©Ä¸©Ä¸§Ä¸©Ä¸§Äí·©Äð·§Äç·©Äê·§Äà·§Äá·©ÄØ·§ÄÙ·©Ä¸·§Ä¹·©Ä¤·§Ä¥·©Ä·§Ä·©Äú¶§Äû¶©Äæ¶§Äç¶©ÄÜ¶§ÄÝ¶©ÄØ¶§ÄÙ¶©Ä¼¶§Ä½¶©Ä¦¶§Ä§¶©Ä¶§Ä¶©Ä¶§Ä¶©Ä¶§Ä¶©Ä§ÙµãÉÜµáÉÔµáÉÕµãÉËµãÉÎµáÉÖµáÉ×µãÉÉµãÉÌµáÉ¶ãÉ¶áÉÆµáÉÇµãÉÃµãÉÆµáÉ¶áÉ¶ãÉ³µãÉ¶µáÉ°µáÉ±µãÉ®µáÉ¯µãÉ¬µáÉ­µãÉÏ¶ãÉÒ¶áÉµãÉµáÉµãÉµáÉ·ãÉ·áÉ÷µãÉúµáÉÒ¶áÉÓ¶ãÉû´ãÉþ´áÉï´ãÉò´áÉÛ´ãÉÞ´áÉÕ´ãÉØ´áÉÎ´áÉÏ´ãÉÆ´áÉÇ´ãÉ¦´áÉ§´ãÉ´áÉ´ãÉú³áÉû³ãÉè³áÉé³ãÉÔ³áÉÕ³ãÉÊ³áÉË³ãÉÆ³áÉÇ³ãÉª³áÉ«³ãÉ³áÉ³ãÉ³áÉ³ãÉþ²áÉÿ²ãÉü²áÉý²ãÉ§Ç²ÏÊ²ÏÂ²ÏÃ²Ï¹²Ï¼²ÏÄ²ÏÅ²Ï·²Ïº²Ï³Ï³Ï´²Ïµ²Ï±²Ï´²Ïî²Ïï²Ï¡²Ï¤²Ï²Ï²Ï²Ï²Ï²Ï²Ï½³ÏÀ³Ï²Ï²Ïù±Ïü±Ïï³Ïò³Ïå²Ïè²ÏÀ³ÏÁ³Ïé±Ïì±ÏÝ±Ïà±ÏÉ±ÏÌ±ÏÃ±ÏÆ±Ï¼±Ï½±Ï´±Ïµ±Ï±Ï±Ï±Ï±Ïè°Ïé°ÏÖ°Ï×°ÏÂ°ÏÃ°Ï¸°Ï¹°Ï´°Ïµ°Ï°Ï°Ï°Ï°Ïö¯Ï÷¯Ïì¯Ïí¯Ïê¯Ïë¯Ï§µ¯×Ô¸¯ÕÔ°¯ÕÔ±¯×Ô§¯×Ôª¯ÕÔ²¯ÕÔ³¯×Ô¥¯×Ô¨¯ÕÔ÷¯×Ôú¯ÕÔ¢¯ÕÔ£¯×Ô¯×Ô¢¯ÕÔÜ¯ÕÔÝ¯×Ô¯×Ô¯ÕÔ¯ÕÔ¯×Ô¯ÕÔ¯×Ô¯ÕÔ¯×Ô«°×Ô®°ÕÔñ®×Ôô®ÕÔç®×Ôê®ÕÔÝ°×Ôà°ÕÔÓ¯×ÔÖ¯ÕÔ®°ÕÔ¯°×Ô×®×ÔÚ®ÕÔË®×ÔÎ®ÕÔ·®×Ôº®ÕÔ±®×Ô´®ÕÔª®ÕÔ«®×Ô¢®ÕÔ£®×Ô®ÕÔ®×Ôî­ÕÔï­×ÔÖ­ÕÔ×­×ÔÄ­ÕÔÅ­×Ô°­ÕÔ±­×Ô¦­ÕÔ§­×Ô¢­ÕÔ£­×Ô­ÕÔ­×Ôð¬ÕÔñ¬×Ôä¬ÕÔå¬×ÔÚ¬ÕÔÛ¬×ÔØ¬ÕÔÙ¬×Ô§£¬Ú¦¬Ú¬Ú¬Ú¬Ú¬Ú ¬Ú¡¬Ú¬Ú¬Úå¬Úè¬Ú¬Ú¬Ú¬Ú¬ÚÊ¬ÚË¬Úý«Ú¬Úú«Úû«Úø«Úù«Úö«Ú÷«Ú­Ú­Úß«Úâ«ÚÕ«ÚØ«ÚË­ÚÎ­ÚÁ¬ÚÄ¬Ú­Ú­ÚÅ«ÚÈ«Ú¹«Ú¼«Ú¥«Ú¨«Ú«Ú¢«Ú«Ú«Ú«Ú«ÚðªÚñªÚÜªÚÝªÚÄªÚÅªÚ²ªÚ³ªÚªÚªÚªÚªÚªÚªÚô©Úõ©ÚÞ©Úß©ÚÒ©ÚÓ©ÚÈ©ÚÉ©ÚÆ©ÚÇ©Ú§©Ëß©Éß©Éß©Ëß©Ëß©Éß©Éß©Ëß©Ëß©ÉßÓ©ËßÖ©Éßþ¨Éßÿ¨Ëßû¨Ëßþ¨Éß¸©Éß¹©Ëßë¨Ëßî¨Éßè¨Éßé¨Ëßæ¨Éßç¨Ëßä¨Éßå¨ËßªËßªÉßÍ¨ËßÐ¨ÉßÃ¨ËßÆ¨Éß¹ªËß¼ªÉß¯©Ëß²©ÉßªÉßªËß³¨Ëß¶¨Éß§¨Ëßª¨Éß¨Ëß¨Éß¨Ëß¨Éß¨Éß¨Ëßþ§Éßÿ§ËßÞ§Éßß§ËßÊ§ÉßË§Ëß²§Éß³§Ëß §Éß¡§Ëß§Éß§Ëß§Éß§Ëßþ¦Éßÿ¦Ëßâ¦Éßã¦ËßÌ¦ÉßÍ¦ËßÀ¦ÉßÁ¦Ëß¶¦Éß·¦Ëß´¦Éßµ¦Ëß§ÿ¥å¦åú¥åû¥åñ¥åô¥åü¥åý¥åï¥åò¥åÁ¦åÄ¦åì¥åí¥åé¥åì¥å¦¦å§¦åÙ¥åÜ¥åÖ¥å×¥åÔ¥åÕ¥åÒ¥åÓ¥åõ¦åø¦å»¥å¾¥å±¥å´¥å§§åª§å¦å ¦åø¦åù¦å¡¥å¤¥å¥å¥å¥å¥åû¤åþ¤åô¤åõ¤åì¤åí¤åÌ¤åÍ¤å¸¤å¹¤å ¤å¡¤å¤å¤åú£åû£åð£åñ£åì£åí£åÐ£åÑ£åº£å»£å®£å¯£å¤£å¥£å¢£å££å§í¢¿êð¢½êè¢½êé¢¿êß¢¿êâ¢½êê¢½êë¢¿êÝ¢¿êà¢½ê¯£¿ê²£½êÚ¢½êÛ¢¿ê×¢¿êÚ¢½ê£½ê£¿êÇ¢¿êÊ¢½êÄ¢½êÅ¢¿êÂ¢½êÃ¢¿êÀ¢½êÁ¢¿êã£¿êæ£½ê©¢¿ê¬¢½ê¢¿ê¢¢½ê¤¿ê¤½ê£¿ê£½êæ£½êç£¿ê¢¿ê¢½ê¢¿ê¢½êï¡¿êò¡½êé¡¿êì¡½êâ¡½êã¡¿êÚ¡½êÛ¡¿êº¡½ê»¡¿ê¦¡½ê§¡¿ê¡½ê¡¿êü ½êý ¿êè ½êé ¿êÞ ½êß ¿êÚ ½êÛ ¿ê¾ ½ê¿ ¿ê¨ ½ê© ¿ê ½ê ¿ê ½ê ¿ê ½ê ¿ê§ÛùïÞ÷ïÖ÷ï×ùïÍùïÐ÷ïØ÷ïÙùïËùïÎ÷ï ùï  ÷ïÈ÷ïÉùïÅùïÈ÷ï ÷ï ùïµùï¸÷ï²÷ï³ùï°÷ï±ùï®÷ï¯ùïÑ ùïÔ ÷ïùï÷ïùï÷ï¡ùï¡÷ïùùïü÷ïÔ ÷ïÕ ùïýùï÷ïñùïô÷ïÝùïà÷ï×ùïÚ÷ïÐ÷ïÑùïÈ÷ïÉùï¨÷ï©ùï÷ïùïü÷ïýùïê÷ïëùïÖ÷ï×ùïÌ÷ïÍùïÈ÷ïÉùï¬÷ï­ùï÷ïùï÷ïùï÷ïùïþ÷ïÿùï§É³õÌ±õÄ±õÅ³õ»³õ¾±õÆ±õÇ³õ¹³õ¼±õ³õ±õ¶±õ·³õ³³õ¶±õð±õñ³õ£³õ¦±õ ±õ¡³õ±õ³õ±õ³õ¿³õÂ±õ³õ±õû³õþ±õñ³õô±õç³õê±õÂ±õÃ³õë³õî±õß³õâ±õË³õÎ±õÅ³õÈ±õ¾±õ¿³õ¶±õ·³õ±õ³õ±õ³õê±õë³õØ±õÙ³õÄ±õÅ³õº±õ»³õ¶±õ·³õ±õ³õ±õ³õø±õù³õî±õï³õì±õí³õ§·íúºëú²ëú³íú©íú¬ëú´ëúµíú§íúªëúùíúüëú¤ëú¥íú¡íú¤ëúÞëúßíúíúëúëúíúëúíúëúíú­íú°ëúóíúöëúéíúìëúßíúâëúÕíúØëú°ëú±íúÙíúÜëúÍíúÐëú¹íú¼ëú³íú¶ëú¬ëú­íú¤ëú¥íúëúíúðëúñíúØëúÙíúÆëúÇíú²ëú³íú¨ëú©íú¤ëú¥íúëúíúòëúóíúæëúçíúÜëúÝíúÚëúÛíú§¥§¨¥ ¥¡§§¥¢¥£§§¥ç§ê¥¥§§¥Ì¥Í§ÿ§¥ü¥ý§ú¥û§ø¥ù§§¥á§ä¥×§Ú¥Í§Ð¥Ã§Æ¥¥§Ç§Ê¥»§¾¥§§ª¥¡§¤¥¥§¥§ò¥ó§Þ¥ß§Æ¥Ç§´¥µ§ ¥¡§¥§¥§ö¥÷§à¥á§Ô¥Õ§Ê¥Ë§È¥É§§áßßááßßááßÕáØßßáýáßºß»áíáðßêßëáèßéáæßçááßÏáÒßÅáÈß»á¾ß±á´ßßáµá¸ß©á¬ßáßáßßáßáàßááÌßÍá´ßµá¢ß£áßáßáßáäßåáÎßÏáÂßÃá¸ß¹á¶ß·á§üýóöþÿñôÃÆîïëî¨©ÛÞØÙÖ×ÔÕ÷ú½À³¶©¬¢úû£¦ýö÷îïÎÏº»¢£üýòóîïÒÓ¼½°±¦§¤¥§ïÕòÓêÓëÕáÕäÓìÓíÕßÕâÓ±Õ´ÓÜÓÝÕÙÕÜÓÓÕÉÕÌÓÆÓÇÕÄÓÅÕÂÓÃÕåÕèÓ«Õ®Ó¡Õ¤ÓÕÓÕÓèÓéÕÕÓÕÓñÕôÓëÕîÓäÓåÕÜÓÝÕ¼Ó½Õ¨Ó©ÕÓÕþÓÿÕêÓëÕàÓáÕÜÓÝÕÀÓÁÕªÓ«ÕÓÕÓÕÓÕ§ÝàØÙÏÒÚÛÍÐ¢ÊËÇÊ·º´µ²³°±ÓÖûþÖ×ÿóößâÙÜÒÓÊËª«þÿìíØÙÎÏÊË®¯§ËÉÎÇÆÇÇÉ½ÉÀÇÈÇÉÉ»É¾ÇÉÇ¸Ç¹ÉµÉ¸ÇòÇóÉ¥É¨Ç¢Ç£É Ç¡ÉÇÉÁÉÄÇÉÇýÉÇóÉöÇéÉìÇÄÇÅÉíÉðÇáÉäÇÍÉÐÇÇÉÊÇÀÇÁÉ¸Ç¹ÉÇÉÇÉìÇíÉÚÇÛÉÆÇÇÉ¼Ç½É¸Ç¹ÉÇÉÇÉúÇûÉðÇñÉîÇïÉ§¹¡¼¡´¡µ¡«¡®¡¶¡·¡©¡¬¡û¡þ¡¦¡§¡£¡¦¡à¡á¡¡¡¡¡¡¡¡¡¯¡²¡õ¡ø¡ë¡î¡á¡ä¡×¡Ú¡²¡³¡Û¡Þ¡Ï¡Ò¡»¡¾¡µ¡¸¡®¡¯¡¦¡§¡¡¡ò¡ó¡Ú¡Û¡È¡É¡´¡µ¡ª¡«¡¦¡§¡¡¡ô¡õ¡è¡é¡Þ¡ß¡Ü¡Ý¡§§½¦ª»¦¢»¦£½¦½¦»¦¤»¦¥½¦½¦»¦é½¦ì»¦»¦½¦½¦»¦Î»¦Ï½¦½¦»¦þÿ»¦ÿÿ½¦üÿ»¦ýÿ½¦úÿ»¦ûÿ½¦½¦ »¦ãÿ½¦æÿ»¦Ùÿ½¦Üÿ»¦Ï½¦Ò»¦Å½¦È»¦ »¦¡½¦Éÿ½¦Ìÿ»¦½ÿ½¦Àÿ»¦©ÿ½¦¬ÿ»¦£ÿ½¦¦ÿ»¦ÿ»¦ÿ½¦ÿ»¦ÿ½¦ôþ»¦õþ½¦àþ»¦áþ½¦Èþ»¦Éþ½¦¶þ»¦·þ½¦¢þ»¦£þ½¦þ»¦þ½¦þ»¦þ½¦øý»¦ùý½¦âý»¦ãý½¦Öý»¦×ý½¦Ìý»¦Íý½¦Êý»¦Ëý½¦§»¹¹»»¹¹»»¹Ù»Ü¹¹»»¹¾¹¿»ñ»ô¹î¹ï»ì¹í»ê¹ë»»¹Ó»Ö¹É»Ì¹¿»Â¹µ»¸¹¹»¹»¼¹­»°¹»¹»¹¹»¹»ä¹å»Ð¹Ñ»¸¹¹»¦¹§»¹»¹»¹»è¹é»Ò¹Ó»Æ¹Ç»¼¹½»º¹»»§õ
+ó
+ó
+õ
+÷õ
+úó
+ó
+õ
+õõ
+øó
+Çõ
+Êó
+òó
+óõ
+ïõ
+òó
+¬ó
+­õ
+ßõ
+âó
+Üó
+Ýõ
+Úó
+Ûõ
+Øó
+Ùõ
+ûõ
+þó
+Áõ
+Äó
+·õ
+ºó
+­õ
+°ó
+£õ
+¦ó
+þó
+ÿõ
+§õ
+ªó
+õ
+ó
+õ
+ó
+õ
+ó
+úó
+ûõ
+òó
+óõ
+Òó
+Óõ
+¾ó
+¿õ
+¦ó
+§õ
+ó
+õ
+ó
+õ
+öó
+÷õ
+òó
+óõ
+Öó
+×õ
+Àó
+Áõ
+´ó
+µõ
+ªó
+«õ
+¨ó
+©õ
+§ó¯ö­î­ï¯å¯è­ð­ñ¯ã¯æ­µ¯¸­à­á¯Ý¯à­­¯Í¯Ð­Ê­Ë¯È­É¯Æ­Ç¯é¯ì­¯¯²­¥¯¨­¯­¯­ì­í¯¯­¯­õ¯ø­ï¯ò­è­é¯à­á¯À­Á¯¬­­¯­¯­¯î­ï¯ä­å¯à­á¯Ä­Å¯®­¯¯¢­£¯­¯­¯§áéäçÜçÝéÓéÖçÞçßéÑéÔç£é¦çÎçÏéËéÎççé»é¾ç¸ç¹é¶ç·é´çµé×éÚçé çéçéçÿéçÚçÛééç÷éúçãéæçÝéàçÖç×éÎçÏé®ç¯éçéçéðçñéÜçÝéÒçÓéÎçÏé²ç³éçéçéçéçé§Ï£Ò¡Ê¡Ë£Á£Ä¡Ì¡Í£¿£Â¡£¡¼¡½£¹£¼¡ö¡÷£©£¬¡¦¡§£¤¡¥£¢¡££Å£È¡£¡£¡÷£ú¡í£ð¡È¡É£ñ£ô¡å£è¡Ñ£Ô¡Ë£Î¡Ä¡Å£¼¡½£¡£¡£ð¡ñ£Þ¡ß£Ê¡Ë£À¡Á£¼¡½£ ¡¡£¡£þ¡ÿ£ô¡õ£ò¡ó£§½Ý ÀÛ ¸Û ¹Ý ¯Ý ²Û ºÛ »Ý ­Ý °Û ÿÝ Û ªÛ «Ý §Ý ªÛ äÛ åÝ Ý Û Û Ý Û Ý Û Ý ³Ý ¶Û ùÝ üÛ ïÝ òÛ åÝ èÛ ÛÝ ÞÛ ¶Û ·Ý ßÝ âÛ ÓÝ ÖÛ ¿Ý ÂÛ ¹Ý ¼Û ²Û ³Ý ªÛ «Ý Û Ý öÛ ÷Ý ÞÛ ßÝ ÌÛ ÍÝ ¸Û ¹Ý ®Û ¯Ý ªÛ «Ý Û Ý øÛ ùÝ ìÛ íÝ âÛ ãÝ àÛ áÝ §«&®&¦&§&& &¨&©&&&í&ð&&&&&Ò&Ó&&&&&&&þ&ÿ&¡&¤&ç&ê&Ý&à&Ó&Ö&É&Ì&¤&¥&Í&Ð&Á&Ä&­&°&§&ª& &¡&&&ø&ù&ä&å&Ì&Í&º&»&¦&§&&&&&ü&ý&æ&ç&Ú&Û&Ð&Ñ&Î&Ï&§Ñ+Ï+Ï+Ñ+Ñ+Ï+Ï+Ñ+Ñ+Ï+ÛÑ+ÞÏ+Ï+Ñ+Ñ+Ï+ÀÏ+ÁÑ+óÑ+öÏ+ðÏ+ñÑ+îÏ+ïÑ+ìÏ+íÑ+Ñ+Ï+ÕÑ+ØÏ+ËÑ+ÎÏ+ÁÑ+ÄÏ+·Ñ+ºÏ+Ï+Ñ+»Ñ+¾Ï+¯Ñ+²Ï+Ñ+Ï+Ñ+Ï+Ï+Ñ+Ï+Ñ+æÏ+çÑ+ÒÏ+ÓÑ+ºÏ+»Ñ+¨Ï+©Ñ+Ï+Ñ+Ï+Ñ+Ï+Ñ+êÏ+ëÑ+ÔÏ+ÕÑ+ÈÏ+ÉÑ+¾Ï+¿Ñ+¼Ï+½Ñ+§1111ù1ü111÷1ú1É1Ì1ô1õ1ñ1ô1®1¯1á1ä1Þ1ß1Ü1Ý1Ú1Û1ý11Ã1Æ1¹1¼1¯1²1¥1¨111©1¬11 11111ü1ý1ô1õ1Ô1Õ1À1Á1¨1©11111ø1ù1ô1õ1Ø1Ù1Â1Ã1¶1·1¬1­1ª1«1§õÅ6øÃ6ðÃ6ñÅ6çÅ6êÃ6òÃ6óÅ6åÅ6èÃ6·Å6ºÃ6âÃ6ãÅ6ßÅ6âÃ6Ã6Å6ÏÅ6ÒÃ6ÌÃ6ÍÅ6ÊÃ6ËÅ6ÈÃ6ÉÅ6ëÅ6îÃ6±Å6´Ã6§Å6ªÃ6Å6 Ã6Å6Ã6îÃ6ïÅ6Å6Ã6Å6Ã6÷Å6úÃ6ñÅ6ôÃ6êÃ6ëÅ6âÃ6ãÅ6ÂÃ6ÃÅ6®Ã6¯Å6Ã6Å6Ã6Å6ðÿÃ6ñÿÅ6æÿÃ6çÿÅ6âÿÃ6ãÿÅ6ÆÿÃ6ÇÿÅ6°ÿÃ6±ÿÅ6¤ÿÃ6¥ÿÅ6ÿÃ6ÿÅ6ÿÃ6ÿÅ6§ãþÿ;æþý;Þþý;ßþÿ;Õþÿ;Øþý;àþý;áþÿ;Óþÿ;Öþý;¥ÿÿ;¨ÿý;Ðþý;Ñþÿ;Íþÿ;Ðþý;ÿý;ÿÿ;½þÿ;Àþý;ºþý;»þÿ;¸þý;¹þÿ;¶þý;·þÿ;Ùÿÿ;Üÿý;þÿ;¢þý;þÿ;þý;ÿ;ý;ÿÿ;ÿý;Üÿý;Ýÿÿ;þÿ;þý;ùýÿ;üýý;åýÿ;èýý;ßýÿ;âýý;Øýý;Ùýÿ;Ðýý;Ñýÿ;°ýý;±ýÿ;ýý;ýÿ;ýý;ýÿ;òüý;óüÿ;Þüý;ßüÿ;Ôüý;Õüÿ;Ðüý;Ñüÿ;´üý;µüÿ;üý;üÿ;üý;üÿ;üý;üÿ;üý;üÿ;§Ñû¹AÔû·AÌû·AÍû¹AÃû¹AÆû·AÎû·AÏû¹AÁû¹AÄû·Aü¹Aü·A¾û·A¿û¹A»û¹A¾û·Aøû·Aùû¹A«û¹A®û·A¨û·A©û¹A¦û·A§û¹A¤û·A¥û¹AÇü¹AÊü·Aû¹Aû·Aû¹Aû·Aùü¹Aüü·Aïû¹Aòû·AÊü·AËü¹Aóú¹Aöú·Açú¹Aêú·AÓú¹AÖú·AÍú¹AÐú·AÆú·AÇú¹A¾ú·A¿ú¹Aú·Aú¹Aú·Aú¹Aòù·Aóù¹Aàù·Aáù¹AÌù·AÍù¹AÂù·AÃù¹A¾ù·A¿ù¹A¢ù·A£ù¹Aù·Aù¹Aù·Aù¹Aöø·A÷ø¹Aôø·Aõø¹A§¿øóFÂøñFºøñF»øóF±øóF´øñF¼øñF½øóF¯øóF²øñFùóFùñF¬øñF­øóF©øóF¬øñFæøñFçøóFøóFøñFøñFøóFøñFøóFøñFøóFµùóF¸ùñFû÷óFþ÷ñFñ÷óFô÷ñFçùóFêùñFÝøóFàøñF¸ùñF¹ùóFá÷óFä÷ñFÕ÷óFØ÷ñFÁ÷óFÄ÷ñF»÷óF¾÷ñF´÷ñFµ÷óF¬÷ñF­÷óF÷ñF÷óFøöñFùöóFàöñFáöóFÎöñFÏöóFºöñF»öóF°öñF±öóF¬öñF­öóFöñFöóFúõñFûõóFîõñFïõóFäõñFåõóFâõñFãõóF§­õ­L°õ«L¨õ«L©õ­Lõ­L¢õ«Lªõ«L«õ­Lõ­L õ«Lïõ­Lòõ«Lõ«Lõ­Lõ­Lõ«LÔõ«LÕõ­Lõ­Lõ«Lõ«Lõ­Lõ«Lõ­Lõ«Lõ­L£ö­L¦ö«Léô­Lìô«Lßô­Lâô«LÕö­LØö«LËõ­LÎõ«L¦ö«L§ö­LÏô­LÒô«LÃô­LÆô«L¯ô­L²ô«L©ô­L¬ô«L¢ô«L£ô­Lô«Lô­Lúó«Lûó­Læó«Lçó­LÎó«LÏó­L¼ó«L½ó­L¨ó«L©ó­Ló«Ló­Ló«Ló­Lþò«Lÿò­Lèò«Léò­LÜò«LÝò­LÒò«LÓò­LÐò«LÑò­L§òçQòåQòåQòçQòçQòåQòåQòçQòçQòåQÝòçQàòåQòåQòçQòçQòåQÂòåQÃòçQõñçQøñåQòñåQóñçQðñåQññçQîñåQïñçQóçQóåQ×ñçQÚñåQÍñçQÐñåQÃóçQÆóåQ¹òçQ¼òåQóåQóçQ½ñçQÀñåQ±ñçQ´ñåQñçQ ñåQñçQñåQñåQñçQñåQñçQèðåQéðçQÔðåQÕðçQ¼ðåQ½ðçQªðåQ«ðçQðåQðçQðåQðçQðåQðçQìïåQíïçQÖïåQ×ïçQÊïåQËïçQÀïåQÁïçQ¾ïåQ¿ïçQ§ï¡WïWïWï¡Wûî¡WþîWïWï¡Wùî¡WüîWËï¡WÎïWöîW÷î¡Wóî¡WöîW°ïW±ï¡Wãî¡WæîWàîWáî¡WÞîWßî¡WÜîWÝî¡Wÿï¡WðWÅî¡WÈîW»î¡W¾îW±ð¡W´ðW§ï¡WªïWðWð¡W«î¡W®îWî¡W¢îWî¡WîWî¡WîWþíWÿí¡WöíW÷í¡WÖíW×í¡WÂíWÃí¡WªíW«í¡WíWí¡WíWí¡WúìWûì¡WöìW÷ì¡WÚìWÛì¡WÄìWÅì¡W¸ìW¹ì¡W®ìW¯ì¡W¬ìW­ì¡W§÷ëÛ\úëÙ\òëÙ\óëÛ\éëÛ\ìëÙ\ôëÙ\õëÛ\çëÛ\êëÙ\¹ìÛ\¼ìÙ\äëÙ\åëÛ\áëÛ\äëÙ\ìÙ\ìÛ\ÑëÛ\ÔëÙ\ÎëÙ\ÏëÛ\ÌëÙ\ÍëÛ\ÊëÙ\ËëÛ\íìÛ\ðìÙ\³ëÛ\¶ëÙ\©ëÛ\¬ëÙ\íÛ\¢íÙ\ìÛ\ìÙ\ðìÙ\ñìÛ\ëÛ\ëÙ\ëÛ\ëÙ\ùêÛ\üêÙ\óêÛ\öêÙ\ìêÙ\íêÛ\äêÙ\åêÛ\ÄêÙ\ÅêÛ\°êÙ\±êÛ\êÙ\êÛ\êÙ\êÛ\òéÙ\óéÛ\èéÙ\ééÛ\äéÙ\åéÛ\ÈéÙ\ÉéÛ\²éÙ\³éÛ\¦éÙ\§éÛ\éÙ\éÛ\éÙ\éÛ\§åèbèèbàèbáèb×èbÚèbâèbãèbÕèbØèb§ébªébÒèbÓèbÏèbÒèbébéb¿èbÂèb¼èb½èbºèb»èb¸èb¹èbÛébÞéb¡èb¤èbèbèbêbêbébébÞébßébèbèbûçbþçbççbêçbáçbäçbÚçbÛçbÒçbÓçb²çb³çbçbçbçbçbôæbõæbàæbáæbÖæb×æbÒæbÓæb¶æb·æb æb¡æbæbæbæbæbæbæb§ÓåÏgÖåÍgÎåÍgÏåÏgÅåÏgÈåÍgÐåÍgÑåÏgÃåÏgÆåÍgæÏgæÍgÀåÍgÁåÏg½åÏgÀåÍgúåÍgûåÏg­åÏg°åÍgªåÍg«åÏg¨åÍg©åÏg¦åÍg§åÏgÉæÏgÌæÍgåÏgåÍgåÏgåÍgûæÏgþæÍgñåÏgôåÍgÌæÍgÍæÏgõäÏgøäÍgéäÏgìäÍgÕäÏgØäÍgÏäÏgÒäÍgÈäÍgÉäÏgÀäÍgÁäÏg äÍg¡äÏgäÍgäÏgôãÍgõãÏgâãÍgããÏgÎãÍgÏãÏgÄãÍgÅãÏgÀãÍgÁãÏg¤ãÍg¥ãÏgãÍgãÏgãÍgãÏgøâÍgùâÏgöâÍg÷âÏg§ÁâmÄâm¼âm½âm³âm¶âm¾âm¿âm±âm´âmãmãm®âm¯âm«âm®âmèâméâmâmâmâmâmâmâmâmâm·ãmºãmýámâmóámöáméãmìãmßâmââmºãm»ãmãámæám×ámÚámÃámÆám½ámÀám¶ám·ám®ám¯ámámámúàmûàmâàmãàmÐàmÑàm¼àm½àm²àm³àm®àm¯àmàmàmüßmýßmðßmñßmæßmçßmäßmåßm§¯ßÃr²ßÁrªßÁr«ßÃr¡ßÃr¤ßÁr¬ßÁr­ßÃrßÃr¢ßÁrñßÃrôßÁrßÁrßÃrßÃrßÁrÖßÁr×ßÃrßÃrßÁrßÁrßÃrßÁrßÃrßÁrßÃr¥àÃr¨àÁrëÞÃrîÞÁráÞÃräÞÁr×àÃrÚàÁrÍßÃrÐßÁr¨àÁr©àÃrÑÞÃrÔÞÁrÅÞÃrÈÞÁr±ÞÃr´ÞÁr«ÞÃr®ÞÁr¤ÞÁr¥ÞÃrÞÁrÞÃrüÝÁrýÝÃrèÝÁréÝÃrÐÝÁrÑÝÃr¾ÝÁr¿ÝÃrªÝÁr«ÝÃr ÝÁr¡ÝÃrÝÁrÝÃrÝÁrÝÃrêÜÁrëÜÃrÞÜÁrßÜÃrÔÜÁrÕÜÃrÒÜÁrÓÜÃr§Üýw ÜûwÜûwÜýwÜýwÜûwÜûwÜýwÜýwÜûwßÜýwâÜûwÜûwÜýwÜýwÜûwÄÜûwÅÜýw÷ÛýwúÛûwôÛûwõÛýwòÛûwóÛýwðÛûwñÛýwÝýwÝûwÙÛýwÜÛûwÏÛýwÒÛûwÅÝýwÈÝûw»Üýw¾ÜûwÝûwÝýw¿ÛýwÂÛûw³Ûýw¶ÛûwÛýw¢ÛûwÛýwÛûwÛûwÛýwÛûwÛýwêÚûwëÚýwÖÚûw×Úýw¾Úûw¿Úýw¬Úûw­ÚýwÚûwÚýwÚûwÚýwÚûwÚýwîÙûwïÙýwØÙûwÙÙýwÌÙûwÍÙýwÂÙûwÃÙýwÀÙûwÁÙýw§Ù·}Ùµ}Ùµ}Ù·}ýØ·}Ùµ}Ùµ}Ù·}ûØ·}þØµ}ÍÙ·}ÐÙµ}øØµ}ùØ·}õØ·}øØµ}²Ùµ}³Ù·}åØ·}èØµ}âØµ}ãØ·}àØµ}áØ·}ÞØµ}ßØ·}Ú·}Úµ}ÇØ·}ÊØµ}½Ø·}ÀØµ}³Ú·}¶Úµ}©Ù·}¬Ùµ}Úµ}Ú·}­Ø·}°Øµ}¡Ø·}¤Øµ}Ø·}Øµ}Ø·}Øµ}Øµ}Ø·}ø×µ}ù×·}Ø×µ}Ù×·}Ä×µ}Å×·}¬×µ}­×·}×µ}×·}×µ}×·}üÖµ}ýÖ·}øÖµ}ùÖ·}ÜÖµ}ÝÖ·}ÆÖµ}ÇÖ·}ºÖµ}»Ö·}°Öµ}±Ö·}®Öµ}¯Ö·}§ùÕñüÕïôÕïõÕñëÕñîÕïöÕï÷ÕñéÕñìÕï»Öñ¾ÖïæÕïçÕñãÕñæÕï Öï¡ÖñÓÕñÖÕïÐÕïÑÕñÎÕïÏÕñÌÕïÍÕñïÖñòÖïµÕñ¸Õï«Õñ®Õï¡×ñ¤×ïÖñÖïòÖïóÖñÕñÕïÕñÕïûÔñþÔïõÔñøÔïîÔïïÔñæÔïçÔñÆÔïÇÔñ²Ôï³ÔñÔïÔñÔïÔñôÓïõÓñêÓïëÓñæÓïçÓñÊÓïËÓñ´ÓïµÓñ¨Óï©ÓñÓïÓñÓïÓñ§çÒ«êÒ©âÒ©ãÒ«ÙÒ«ÜÒ©äÒ©åÒ«×Ò«ÚÒ©©Ó«¬Ó©ÔÒ©ÕÒ«ÑÒ«ÔÒ©Ó©Ó«ÁÒ«ÄÒ©¾Ò©¿Ò«¼Ò©½Ò«ºÒ©»Ò«ÝÓ«àÓ©£Ò«¦Ò©Ò«Ò©Ô«Ô©Ó«Ó©àÓ©áÓ«Ò«Ò©ýÑ«Ò©éÑ«ìÑ©ãÑ«æÑ©ÜÑ©ÝÑ«ÔÑ©ÕÑ«´Ñ©µÑ« Ñ©¡Ñ«Ñ©Ñ«öÐ©÷Ð«âÐ©ãÐ«ØÐ©ÙÐ«ÔÐ©ÕÐ«¸Ð©¹Ð«¢Ð©£Ð«Ð©Ð«Ð©Ð«Ð©Ð«§ÕÏåØÏãÐÏãÑÏåÇÏåÊÏãÒÏãÓÏåÅÏåÈÏãÐåÐãÂÏãÃÏå¿ÏåÂÏãüÏãýÏå¯Ïå²Ïã¬Ïã­ÏåªÏã«Ïå¨Ïã©ÏåËÐåÎÐãÏåÏãÏåÏãýÐåÑãóÏåöÏãÎÐãÏÐå÷ÎåúÎãëÎåîÎã×ÎåÚÎãÑÎåÔÎãÊÎãËÎåÂÎãÃÎå¢Îã£ÎåÎãÎåöÍã÷ÍåäÍãåÍåÐÍãÑÍåÆÍãÇÍåÂÍãÃÍå¦Íã§ÍåÍãÍåÍãÍåúÌãûÌåøÌãùÌå§ÃÌÆÌ¾Ì¿ÌµÌ¸ÌÀÌÁÌ³Ì¶ÌÍÍ°Ì±Ì­Ì°ÌêÌëÌÌ ÌÌÌÌÌÌÌ¹Í¼ÍÿËÌõËøËëÍîÍáÌäÌ¼Í½ÍåËèËÙËÜËÅËÈË¿ËÂË¸Ë¹Ë°Ë±ËËËüÊýÊäÊåÊÒÊÓÊ¾Ê¿Ê´ÊµÊ°Ê±ÊÊÊþÉÿÉòÉóÉèÉéÉæÉçÉ§±ÉÙ´É×¬É×­ÉÙ£ÉÙ¦É×®É×¯ÉÙ¡ÉÙ¤É×óÉÙöÉ×É×ÉÙÉÙÉ×ØÉ×ÙÉÙÉÙÉ×É×ÉÙÉ×ÉÙÉ×ÉÙ§ÊÙªÊ×íÈÙðÈ×ãÈÙæÈ×ÙÊÙÜÊ×ÏÉÙÒÉ×ªÊ×«ÊÙÓÈÙÖÈ×ÇÈÙÊÈ×³ÈÙ¶È×­ÈÙ°È×¦È×§ÈÙÈ×ÈÙþÇ×ÿÇÙêÇ×ëÇÙÒÇ×ÓÇÙÀÇ×ÁÇÙ¬Ç×­ÇÙ¢Ç×£ÇÙÇ×ÇÙÇ×ÇÙìÆ×íÆÙàÆ×áÆÙÖÆ××ÆÙÔÆ×ÕÆÙ§Æ¢ÆÆÆÆÆÆÆÆÆáÆäÆÆÆÆÆÆÆÇÆùÅüÅöÅ÷ÅôÅõÅòÅóÅÇÇÛÅÞÅÑÅÔÅÇÇÊÇ½ÆÀÆÇÇÁÅÄÅµÅ¸Å¡Å¤ÅÅÅÅÅÅÅìÄíÄØÄÙÄÀÄÁÄ®Ä¯ÄÄÄÄÄÄÄðÃñÃÚÃÛÃÎÃÏÃÄÃÅÃÂÃÃÃ§ÃÍ£ÃË£ÃË£ÃÍ£ÿÂÍ£ÃË£ÃË£ÃÍ£ýÂÍ£ÃË£ÏÃÍ£ÒÃË£úÂË£ûÂÍ£÷ÂÍ£úÂË£´ÃË£µÃÍ£çÂÍ£êÂË£äÂË£åÂÍ£âÂË£ãÂÍ£àÂË£áÂÍ£ÄÍ£ÄË£ÉÂÍ£ÌÂË£¿ÂÍ£ÂÂË£µÄÍ£¸ÄË£«ÃÍ£®ÃË£ÄË£ÄÍ£¯ÂÍ£²ÂË££ÂÍ£¦ÂË£ÂÍ£ÂË£ÂÍ£ÂË£ÂË£ÂÍ£úÁË£ûÁÍ£ÚÁË£ÛÁÍ£ÆÁË£ÇÁÍ£®ÁË£¯ÁÍ£ÁË£ÁÍ£ÁË£ÁÍ£þÀË£ÿÀÍ£úÀË£ûÀÍ£ÞÀË£ßÀÍ£ÈÀË£ÉÀÍ£¼ÀË£½ÀÍ£²ÀË£³ÀÍ£°ÀË£±ÀÍ£§û¿©þ¿©ö¿©÷¿©í¿©ð¿©ø¿©ù¿©ë¿©î¿©½À©ÀÀ©è¿©é¿©å¿©è¿©¢À©£À©Õ¿©Ø¿©Ò¿©Ó¿©Ð¿©Ñ¿©Î¿©Ï¿©ñÀ©ôÀ©·¿©º¿©­¿©°¿©£Á©¦Á©À©À©ôÀ©õÀ©¿© ¿©¿©¿©ý¾©¿©÷¾©ú¾©ð¾©ñ¾©è¾©é¾©È¾©É¾©´¾©µ¾©¾©¾©¾©¾©ö½©÷½©ì½©í½©è½©é½©Ì½©Í½©¶½©·½©ª½©«½© ½©¡½©½©½©§é¼Á®ì¼¿®ä¼¿®å¼Á®Û¼Á®Þ¼¿®æ¼¿®ç¼Á®Ù¼Á®Ü¼¿®«½Á®®½¿®Ö¼¿®×¼Á®Ó¼Á®Ö¼¿®½¿®½Á®Ã¼Á®Æ¼¿®À¼¿®Á¼Á®¾¼¿®¿¼Á®¼¼¿®½¼Á®ß½Á®â½¿®¥¼Á®¨¼¿®¼Á®¼¿®¾Á®¾¿®½Á®½¿®â½¿®ã½Á®¼Á®¼¿®ÿ»Á®¼¿®ë»Á®î»¿®å»Á®è»¿®Þ»¿®ß»Á®Ö»¿®×»Á®¶»¿®·»Á®¢»¿®£»Á®»¿®»Á®øº¿®ùºÁ®äº¿®åºÁ®Úº¿®ÛºÁ®Öº¿®×ºÁ®ºº¿®»ºÁ®¤º¿®¥ºÁ®º¿®ºÁ®º¿®ºÁ®º¿®ºÁ®§×¹û³Ú¹ù³Ò¹ù³Ó¹û³É¹û³Ì¹ù³Ô¹ù³Õ¹û³Ç¹û³Ê¹ù³ºû³ºù³Ä¹ù³Å¹û³Á¹û³Ä¹ù³þ¹ù³ÿ¹û³±¹û³´¹ù³®¹ù³¯¹û³¬¹ù³­¹û³ª¹ù³«¹û³Íºû³Ðºù³¹û³¹ù³¹û³¹ù³ÿºû³»ù³õ¹û³ø¹ù³Ðºù³Ñºû³ù¸û³ü¸ù³í¸û³ð¸ù³Ù¸û³Ü¸ù³Ó¸û³Ö¸ù³Ì¸ù³Í¸û³Ä¸ù³Å¸û³¤¸ù³¥¸û³¸ù³¸û³ø·ù³ù·û³æ·ù³ç·û³Ò·ù³Ó·û³È·ù³É·û³Ä·ù³Å·û³¨·ù³©·û³·ù³·û³·ù³·û³ü¶ù³ý¶û³ú¶ù³û¶û³§Å¶µ¹È¶³¹À¶³¹Á¶µ¹·¶µ¹º¶³¹Â¶³¹Ã¶µ¹µ¶µ¹¸¶³¹·µ¹·³¹²¶³¹³¶µ¹¯¶µ¹²¶³¹ì¶³¹í¶µ¹¶µ¹¢¶³¹¶³¹¶µ¹¶³¹¶µ¹¶³¹¶µ¹»·µ¹¾·³¹¶µ¹¶³¹÷µµ¹úµ³¹í·µ¹ð·³¹ã¶µ¹æ¶³¹¾·³¹¿·µ¹çµµ¹êµ³¹Ûµµ¹Þµ³¹Çµµ¹Êµ³¹Áµµ¹Äµ³¹ºµ³¹»µµ¹²µ³¹³µµ¹µ³¹µµ¹þ´³¹ÿ´µ¹æ´³¹ç´µ¹Ô´³¹Õ´µ¹À´³¹Á´µ¹¶´³¹·´µ¹²´³¹³´µ¹´³¹´µ¹´³¹´µ¹ô³³¹õ³µ¹ê³³¹ë³µ¹è³³¹é³µ¹§³³ï¾¶³í¾®³í¾¯³ï¾¥³ï¾¨³í¾°³í¾±³ï¾£³ï¾¦³í¾õ³ï¾ø³í¾ ³í¾¡³ï¾³ï¾ ³í¾Ú³í¾Û³ï¾³ï¾³í¾³í¾³ï¾³í¾³ï¾³í¾³ï¾©´ï¾¬´í¾ï²ï¾ò²í¾å²ï¾è²í¾Û´ï¾Þ´í¾Ñ³ï¾Ô³í¾¬´í¾­´ï¾Õ²ï¾Ø²í¾É²ï¾Ì²í¾µ²ï¾¸²í¾¯²ï¾²²í¾¨²í¾©²ï¾ ²í¾¡²ï¾²í¾²ï¾ì±í¾í±ï¾Ô±í¾Õ±ï¾Â±í¾Ã±ï¾®±í¾¯±ï¾¤±í¾¥±ï¾ ±í¾¡±ï¾±í¾±ï¾î°í¾ï°ï¾â°í¾ã°ï¾Ø°í¾Ù°ï¾Ö°í¾×°ï¾§¡°©Ä¤°§Ä°§Ä°©Ä°©Ä°§Ä°§Ä°©Ä°©Ä°§Äã°©Äæ°§Ä°§Ä°©Ä°©Ä°§ÄÈ°§ÄÉ°©Äû¯©Äþ¯§Äø¯§Äù¯©Äö¯§Ä÷¯©Äô¯§Äõ¯©Ä±©Ä±§ÄÝ¯©Äà¯§ÄÓ¯©ÄÖ¯§ÄÉ±©ÄÌ±§Ä¿°©ÄÂ°§Ä±§Ä±©ÄÃ¯©ÄÆ¯§Ä·¯©Äº¯§Ä£¯©Ä¦¯§Ä¯©Ä ¯§Ä¯§Ä¯©Ä¯§Ä¯©Äî®§Äï®©ÄÚ®§ÄÛ®©ÄÂ®§ÄÃ®©Ä°®§Ä±®©Ä®§Ä®©Ä®§Ä®©Ä®§Ä®©Äò­§Äó­©ÄÜ­§ÄÝ­©ÄÐ­§ÄÑ­©ÄÆ­§ÄÇ­©ÄÄ­§ÄÅ­©Ä§­ãÉ­áÉ­áÉ­ãÉ­ãÉ­áÉ­áÉ­ãÉÿ¬ãÉ­áÉÑ­ãÉÔ­áÉü¬áÉý¬ãÉù¬ãÉü¬áÉ¶­áÉ·­ãÉé¬ãÉì¬áÉæ¬áÉç¬ãÉä¬áÉå¬ãÉâ¬áÉã¬ãÉ®ãÉ®áÉË¬ãÉÎ¬áÉÁ¬ãÉÄ¬áÉ·®ãÉº®áÉ­­ãÉ°­áÉ®áÉ®ãÉ±¬ãÉ´¬áÉ¥¬ãÉ¨¬áÉ¬ãÉ¬áÉ¬ãÉ¬áÉ¬áÉ¬ãÉü«áÉý«ãÉÜ«áÉÝ«ãÉÈ«áÉÉ«ãÉ°«áÉ±«ãÉ«áÉ«ãÉ«áÉ«ãÉ«áÉ«ãÉüªáÉýªãÉàªáÉáªãÉÊªáÉËªãÉ¾ªáÉ¿ªãÉ´ªáÉµªãÉ²ªáÉ³ªãÉ§ý©ÏªÏø©Ïù©Ïï©Ïò©Ïú©Ïû©Ïí©Ïð©Ï¿ªÏÂªÏê©Ïë©Ïç©Ïê©Ï¤ªÏ¥ªÏ×©ÏÚ©ÏÔ©ÏÕ©ÏÒ©ÏÓ©ÏÐ©ÏÑ©ÏóªÏöªÏ¹©Ï¼©Ï¯©Ï²©Ï¥«Ï¨«ÏªÏªÏöªÏ÷ªÏ©Ï¢©Ï©Ï©Ïÿ¨Ï©Ïù¨Ïü¨Ïò¨Ïó¨Ïê¨Ïë¨ÏÊ¨ÏË¨Ï¶¨Ï·¨Ï¨Ï¨Ï¨Ï¨Ïø§Ïù§Ïî§Ïï§Ïê§Ïë§ÏÎ§ÏÏ§Ï¸§Ï¹§Ï¬§Ï­§Ï¢§Ï£§Ï §Ï¡§Ï§ë¦×Ôî¦ÕÔæ¦ÕÔç¦×ÔÝ¦×Ôà¦ÕÔè¦ÕÔé¦×ÔÛ¦×ÔÞ¦ÕÔ­§×Ô°§ÕÔØ¦ÕÔÙ¦×ÔÕ¦×ÔØ¦ÕÔ§ÕÔ§×ÔÅ¦×ÔÈ¦ÕÔÂ¦ÕÔÃ¦×ÔÀ¦ÕÔÁ¦×Ô¾¦ÕÔ¿¦×Ôá§×Ôä§ÕÔ§¦×Ôª¦ÕÔ¦×Ô ¦ÕÔ¨×Ô¨ÕÔ§×Ô§ÕÔä§ÕÔå§×Ô¦×Ô¦ÕÔ¦×Ô¦ÕÔí¥×Ôð¥ÕÔç¥×Ôê¥ÕÔà¥ÕÔá¥×ÔØ¥ÕÔÙ¥×Ô¸¥ÕÔ¹¥×Ô¤¥ÕÔ¥¥×Ô¥ÕÔ¥×Ôú¤ÕÔû¤×Ôæ¤ÕÔç¤×ÔÜ¤ÕÔÝ¤×ÔØ¤ÕÔÙ¤×Ô¼¤ÕÔ½¤×Ô¦¤ÕÔ§¤×Ô¤ÕÔ¤×Ô¤ÕÔ¤×Ô¤ÕÔ¤×Ô§Ù£ÚÜ£ÚÔ£ÚÕ£ÚË£ÚÎ£ÚÖ£Ú×£ÚÉ£ÚÌ£Ú¤Ú¤ÚÆ£ÚÇ£ÚÃ£ÚÆ£Ú¤Ú¤Ú³£Ú¶£Ú°£Ú±£Ú®£Ú¯£Ú¬£Ú­£ÚÏ¤ÚÒ¤Ú£Ú£Ú£Ú£Ú¥Ú¥Ú÷£Úú£ÚÒ¤ÚÓ¤Úû¢Úþ¢Úï¢Úò¢ÚÛ¢ÚÞ¢ÚÕ¢ÚØ¢ÚÎ¢ÚÏ¢ÚÆ¢ÚÇ¢Ú¦¢Ú§¢Ú¢Ú¢Úú¡Úû¡Úè¡Úé¡ÚÔ¡ÚÕ¡ÚÊ¡ÚË¡ÚÆ¡ÚÇ¡Úª¡Ú«¡Ú¡Ú¡Ú¡Ú¡Úþ Úÿ Úü Úý Ú§Ç ËßÊ ÉßÂ ÉßÃ Ëß¹ Ëß¼ ÉßÄ ÉßÅ Ëß· Ëßº Éß¡Ëß¡Éß´ Éßµ Ëß± Ëß´ Éßî Éßï Ëß¡ Ëß¤ Éß Éß Ëß Éß Ëß Éß Ëß½¡ËßÀ¡Éß Ëß ÉßùËßüÉßï¡Ëßò¡Éßå Ëßè ÉßÀ¡ÉßÁ¡ËßéËßìÉßÝËßàÉßÉËßÌÉßÃËßÆÉß¼Éß½Ëß´ÉßµËßÉßËßÉßËßèÉßéËßÖÉß×ËßÂÉßÃËß¸Éß¹Ëß´ÉßµËßÉßËßÉßËßöÉß÷ËßìÉßíËßêÉßëËß§µå¸å°å±å§åªå²å³å¥å¨å÷åúå¢å£åå¢åÜåÝååååååååå«å®åñåôåçåêåÝåàåÓåÖå®å¯å×åÚåËåÎå·åºå±å´åªå«å¢å£åååîåïåÖå×åÄåÅå°å±å¦å§å¢å£åååðåñåäåååÚåÛåØåÙå§£¿ê¦½ê½ê¿ê¿ê½ê ½ê¡¿ê¿ê½êå¿êè½ê½ê¿ê¿ê½êÊ½êË¿êý¿ê½êú½êû¿êø½êù¿êö½ê÷¿ê¿ê½êß¿êâ½êÕ¿êØ½êË¿êÎ½êÁ¿êÄ½ê½ê¿êÅ¿êÈ½ê¹¿ê¼½ê¥¿ê¨½ê¿ê¢½ê½ê¿ê½ê¿êð½êñ¿êÜ½êÝ¿êÄ½êÅ¿ê²½ê³¿ê½ê¿ê½ê¿ê½ê¿êô½êõ¿êÞ½êß¿êÒ½êÓ¿êÈ½êÉ¿êÆ½êÇ¿ê§ùï÷ï÷ïùïùï÷ï÷ïùïùï÷ïÓùïÖ÷ïþ÷ïÿùïûùïþ÷ï¸÷ï¹ùïëùïî÷ïè÷ïéùïæ÷ïçùïä÷ïåùïùï÷ïÍùïÐ÷ïÃùïÆ÷ï¹ùï¼÷ï¯ùï²÷ï÷ïùï³ùï¶÷ï§ùïª÷ïùï÷ïùï÷ï÷ïùïþ÷ïÿùïÞ÷ïßùïÊ÷ïËùï²÷ï³ùï ÷ï¡ùï÷ïùï÷ïùïþ÷ïÿùïâ÷ïãùïÌ÷ïÍùïÀ÷ïÁùï¶÷ï·ùï´÷ïµùï§ÿ³õ±õú±õû³õñ³õô±õü±õý³õï³õò±õÁ³õÄ±õì±õí³õé³õì±õ¦±õ§³õÙ³õÜ±õÖ±õ×³õÔ±õÕ³õÒ±õÓ³õõ³õø±õ»³õ¾±õ±³õ´±õ§³õª±õ³õ ±õø±õù³õ¡³õ¤±õ³õ±õ³õ±õû³õþ±õô±õõ³õì±õí³õÌ±õÍ³õ¸±õ¹³õ ±õ¡³õ±õ³õú±õû³õð±õñ³õì±õí³õÐ±õÑ³õº±õ»³õ®±õ¯³õ¤±õ¥³õ¢±õ£³õ§ííúðëúèëúéíúßíúâëúêëúëíúÝíúàëú¯íú²ëúÚëúÛíú×íúÚëúëúíúÇíúÊëúÄëúÅíúÂëúÃíúÀëúÁíúãíúæëú©íú¬ëúíú¢ëúíúëúíúëúæëúçíúíúëúíúëúïíúòëúéíúìëúâëúãíúÚëúÛíúºëú»íú¦ëú§íúëúíúüëúýíúèëúéíúÞëúßíúÚëúÛíú¾ëú¿íú¨ëú©íúëúíúëúíúëúíú§Û§Þ¥Ö¥×§Í§Ð¥Ø¥Ù§Ë§Î¥§ ¥È¥É§Å§È¥¥§µ§¸¥²¥³§°¥±§®¥¯§Ñ§Ô¥§¥§¥§¥ù§ü¥Ô¥Õ§ý§¥ñ§ô¥Ý§à¥×§Ú¥Ð¥Ñ§È¥É§¨¥©§¥§ü¥ý§ê¥ë§Ö¥×§Ì¥Í§È¥É§¬¥­§¥§¥§¥§þ¥ÿ§§ÉáÌßÄßÅá»á¾ßÆßÇá¹á¼ßáß¶ß·á³á¶ßðßñá£á¦ß ß¡áßáßá¿áÂßáßûáþßñáôßçáêßÂßÃáëáîßßáâßËáÎßÅáÈß¾ß¿á¶ß·áßáßáêßëáØßÙáÄßÅáºß»á¶ß·áßáßáøßùáîßïáìßíá§·º²³©¬´µ§ªùü¤¥¡¤Þß­°óöéìßâÕØ°±ÙÜÍÐ¹¼³¶¬­¤¥ðñØÙÆÇ²³¨©¤¥òóæçÜÝÚÛ§¥Õ¨Ó Ó¡ÕÕÓ¢Ó£ÕÕÓçÕêÓÓÕÕÓÌÓÍÕÿÕÓüÓýÕúÓûÕøÓùÕÕÓáÕäÓ×ÕÚÓÍÕÐÓÃÕÆÓÓÕÇÕÊÓ»Õ¾Ó§ÕªÓ¡Õ¤ÓÓÕÓÕòÓóÕÞÓßÕÆÓÇÕ´ÓµÕ Ó¡ÕÓÕÓÕöÓ÷ÕàÓáÕÔÓÕÕÊÓËÕÈÓÉÕ§ÕØýº»íðêëèéæçÏÒÅÈ»¾±´µ¸©¬àÿáÿÌÿÍÿ´ÿµÿ¢ÿ£ÿÿÿÿÿÿÿäþåþÎþÏþÂþÃþ¸þ¹þ¶þ·þ§þÉþÇüýÇýýÉóýÉöýÇþýÇÿýÉñýÉôýÇÃþÉÆþÇîýÇïýÉëýÉîýÇ¨þÇ©þÉÛýÉÞýÇØýÇÙýÉÖýÇ×ýÉÔýÇÕýÉ÷þÉúþÇ½ýÉÀýÇ³ýÉ¶ýÇ©ÿÉ¬ÿÇþÉ¢þÇúþÇûþÉ£ýÉ¦ýÇýÉýÇýÉýÇýüÉýÇöüÇ÷üÉîüÇïüÉÎüÇÏüÉºüÇ»üÉ¢üÇ£üÉüÇüÉüûÇýûÉòûÇóûÉîûÇïûÉÒûÇÓûÉ¼ûÇ½ûÉ°ûÇ±ûÉ¦ûÇ§ûÉ¤ûÇ¥ûÉ§ïú¡òú¡êú¡ëú¡áú¡äú¡ìú¡íú¡ßú¡âú¡±û¡´û¡Üú¡Ýú¡Ùú¡Üú¡û¡û¡Éú¡Ìú¡Æú¡Çú¡Äú¡Åú¡Âú¡Ãú¡åû¡èû¡«ú¡®ú¡¡ú¡¤ú¡ü¡ü¡û¡û¡èû¡éû¡ú¡ú¡ú¡ú¡ñù¡ôù¡ëù¡îù¡äù¡åù¡Üù¡Ýù¡¼ù¡½ù¡¨ù¡©ù¡ù¡ù¡þø¡ÿø¡êø¡ëø¡àø¡áø¡Üø¡Ýø¡Àø¡Áø¡ªø¡«ø¡ø¡ø¡ø¡ø¡ø¡ø¡§¥»¨¹ ¹¡»»¹¢¹£»»¹ç»ê¹¹»»¹Ì¹Í»ÿ»¹ü¹ý»ú¹û»ø¹ù»»¹á»ä¹×»Ú¹Í»Ð¹Ã»Æ¹¹»Ç»Ê¹»»¾¹§»ª¹¡»¤¹¹»¹»ò¹ó»Þ¹ß»Æ¹Ç»´¹µ» ¹¡»¹»¹»ö¹÷»à¹á»Ô¹Õ»Ê¹Ë»È¹É»§õ
+ó
+ó
+õ
+õ
+ó
+ó
+õ
+õ
+ó
+Õõ
+Øó
+ó
+õ
+ýõ
+ó
+ºó
+»õ
+íõ
+ðó
+êó
+ëõ
+èó
+éõ
+æó
+çõ
+õ
+ó
+Ïõ
+Òó
+Åõ
+Èó
+»õ
+¾ó
+±õ
+´ó
+ó
+õ
+µõ
+¸ó
+©õ
+¬ó
+õ
+ó
+õ
+ó
+ó
+õ
+ó
+õ
+àó
+áõ
+Ìó
+Íõ
+´ó
+µõ
+¢ó
+£õ
+ó
+õ
+ó
+õ
+ó
+õ
+äó
+åõ
+Îó
+Ïõ
+Âó
+Ãõ
+¸ó
+¹õ
+¶ó
+·õ
+§¯­ü­ý¯ó¯ö­þ­ÿ¯ñ¯ô­Ã¯Æ­î­ï¯ë¯î­¨­©¯Û¯Þ­Ø­Ù¯Ö­×¯Ô­Õ¯÷¯ú­½¯À­³¯¶­©¯¬­¯¢­ú­û¯£¯¦­¯­¯­ý¯­ö­÷¯î­ï¯Î­Ï¯º­»¯¢­£¯­¯ü­ý¯ò­ó¯î­ï¯Ò­Ó¯¼­½¯°­±¯¦­§¯¤­¥¯§ïéòçêçëéáéäçìçíéßéâç±é´çÜçÝéÙéÜççéÉéÌçÆçÇéÄçÅéÂçÃéåéèç«é®ç¡é¤çéçéçèçéééçéçñéôçëéîçäçåéÜçÝé¼ç½é¨ç©éçéþçÿéêçëéàçáéÜçÝéÀçÁéªç«éçéçéçé§Ý£à¡Ø¡Ù£Ï£Ò¡Ú¡Û£Í£Ð¡£¢¡Ê¡Ë£Ç£Ê¡¡£·£º¡´¡µ£²¡³£°¡±£Ó£Ö¡£¡£¡£¡û£þ¡Ö¡×£ÿ£¡ó£ö¡ß£â¡Ù£Ü¡Ò¡Ó£Ê¡Ë£ª¡«£¡£þ¡ÿ£ì¡í£Ø¡Ù£Î¡Ï£Ê¡Ë£®¡¯£¡£¡£¡£¡£§ËÝ ÎÛ ÆÛ ÇÝ ½Ý ÀÛ ÈÛ ÉÝ »Ý ¾Û Ý Û ¸Û ¹Ý µÝ ¸Û òÛ óÝ ¥Ý ¨Û ¢Û £Ý  Û ¡Ý Û Ý ÁÝ ÄÛ Ý Û ýÝ Û óÝ öÛ éÝ ìÛ ÄÛ ÅÝ íÝ ðÛ áÝ äÛ ÍÝ ÐÛ ÇÝ ÊÛ ÀÛ ÁÝ ¸Û ¹Ý Û Ý Û Ý ìÛ íÝ ÚÛ ÛÝ ÆÛ ÇÝ ¼Û ½Ý ¸Û ¹Ý Û Ý Û Ý úÛ ûÝ ðÛ ñÝ îÛ ïÝ §¹&¼&´&µ&«&®&¶&·&©&¬&û&þ&¦&§&£&¦&à&á&&&&&&&&&¯&²&õÿ&øÿ&ëÿ&îÿ&á&ä&×&Ú&²&³&Ûÿ&Þÿ&Ïÿ&Òÿ&»ÿ&¾ÿ&µÿ&¸ÿ&®ÿ&¯ÿ&¦ÿ&§ÿ&ÿ&ÿ&òþ&óþ&Úþ&Ûþ&Èþ&Éþ&´þ&µþ&ªþ&«þ&¦þ&§þ&þ&þ&ôý&õý&èý&éý&Þý&ßý&Üý&Ýý&§§ýÑ+ªýÏ+¢ýÏ+£ýÑ+ýÑ+ýÏ+¤ýÏ+¥ýÑ+ýÑ+ýÏ+éýÑ+ìýÏ+ýÏ+ýÑ+ýÑ+ýÏ+ÎýÏ+ÏýÑ+ýÑ+ýÏ+þüÏ+ÿüÑ+üüÏ+ýüÑ+úüÏ+ûüÑ+þÑ+ þÏ+ãüÑ+æüÏ+ÙüÑ+ÜüÏ+ÏþÑ+ÒþÏ+ÅýÑ+ÈýÏ+ þÏ+¡þÑ+ÉüÑ+ÌüÏ+½üÑ+ÀüÏ+©üÑ+¬üÏ+£üÑ+¦üÏ+üÏ+üÑ+üÏ+üÑ+ôûÏ+õûÑ+àûÏ+áûÑ+ÈûÏ+ÉûÑ+¶ûÏ+·ûÑ+¢ûÏ+£ûÑ+ûÏ+ûÑ+ûÏ+ûÑ+øúÏ+ùúÑ+âúÏ+ãúÑ+ÖúÏ+×úÑ+ÌúÏ+ÍúÑ+ÊúÏ+ËúÑ+§ú1ú1ú1ú1ú1ú1ú1ú1ú1ú1×ú1Úú1ú1ú1ÿù1ú1¼ú1½ú1ïù1òù1ìù1íù1êù1ëù1èù1éù1û1û1Ñù1Ôù1Çù1Êù1½û1Àû1³ú1¶ú1û1û1·ù1ºù1«ù1®ù1ù1ù1ù1ù1ù1ù1ù1ù1âø1ãø1Îø1Ïø1¶ø1·ø1¤ø1¥ø1ø1ø1ø1ø1ø1ø1æ÷1ç÷1Ð÷1Ñ÷1Ä÷1Å÷1º÷1»÷1¸÷1¹÷1§÷Å6÷Ã6þöÃ6ÿöÅ6õöÅ6øöÃ6÷Ã6÷Å6óöÅ6ööÃ6Å÷Å6È÷Ã6ðöÃ6ñöÅ6íöÅ6ðöÃ6ª÷Ã6«÷Å6ÝöÅ6àöÃ6ÚöÃ6ÛöÅ6ØöÃ6ÙöÅ6ÖöÃ6×öÅ6ù÷Å6ü÷Ã6¿öÅ6ÂöÃ6µöÅ6¸öÃ6«øÅ6®øÃ6¡÷Å6¤÷Ã6ü÷Ã6ý÷Å6¥öÅ6¨öÃ6öÅ6öÃ6öÅ6öÃ6ÿõÅ6öÃ6øõÃ6ùõÅ6ðõÃ6ñõÅ6ÐõÃ6ÑõÅ6¼õÃ6½õÅ6¤õÃ6¥õÅ6õÃ6õÅ6þôÃ6ÿôÅ6ôôÃ6õôÅ6ðôÃ6ñôÅ6ÔôÃ6ÕôÅ6¾ôÃ6¿ôÅ6²ôÃ6³ôÅ6¨ôÃ6©ôÅ6¦ôÃ6§ôÅ6§ñóÿ;ôóý;ìóý;íóÿ;ãóÿ;æóý;îóý;ïóÿ;áóÿ;äóý;³ôÿ;¶ôý;Þóý;ßóÿ;Ûóÿ;Þóý;ôý;ôÿ;Ëóÿ;Îóý;Èóý;Éóÿ;Æóý;Çóÿ;Äóý;Åóÿ;çôÿ;êôý;­óÿ;°óý;£óÿ;¦óý;õÿ;õý;ôÿ;ôý;êôý;ëôÿ;óÿ;óý;óÿ;óý;óòÿ;öòý;íòÿ;ðòý;æòý;çòÿ;Þòý;ßòÿ;¾òý;¿òÿ;ªòý;«òÿ;òý;òÿ;òý;òÿ;ìñý;íñÿ;âñý;ãñÿ;Þñý;ßñÿ;Âñý;Ãñÿ;¬ñý;­ñÿ; ñý;¡ñÿ;ñý;ñÿ;ñý;ñÿ;§ßð¹Aâð·AÚð·AÛð¹AÑð¹AÔð·AÜð·AÝð¹AÏð¹AÒð·A¡ñ¹A¤ñ·AÌð·AÍð¹AÉð¹AÌð·Añ·Añ¹A¹ð¹A¼ð·A¶ð·A·ð¹A´ð·Aµð¹A²ð·A³ð¹AÕñ¹AØñ·Að¹Að·Að¹Að·Aò¹Aò·Aýð¹Añ·AØñ·AÙñ¹Að¹Að·Aõï¹Aøï·Aáï¹Aäï·AÛï¹AÞï·AÔï·AÕï¹AÌï·AÍï¹A¬ï·A­ï¹Aï·Aï¹Aï·Aï¹Aîî·Aïî¹AÚî·AÛî¹AÐî·AÑî¹AÌî·AÍî¹A°î·A±î¹Aî·Aî¹Aî·Aî¹Aî·Aî¹Aî·Aî¹A§ÍíóFÐíñFÈíñFÉíóF¿íóFÂíñFÊíñFËíóF½íóFÀíñFîóFîñFºíñF»íóF·íóFºíñFôíñFõíóF§íóFªíñF¤íñF¥íóF¢íñF£íóF íñF¡íóFÃîóFÆîñFíóFíñFÿìóFíñFõîóFøîñFëíóFîíñFÆîñFÇîóFïìóFòìñFãìóFæìñFÏìóFÒìñFÉìóFÌìñFÂìñFÃìóFºìñF»ìóFìñFìóFìñFìóFîëñFïëóFÜëñFÝëóFÈëñFÉëóF¾ëñF¿ëóFºëñF»ëóFëñFëóFëñFëóFüêñFýêóFòêñFóêóFðêñFñêóF§»ê­L¾ê«L¶ê«L·ê­L­ê­L°ê«L¸ê«L¹ê­L«ê­L®ê«Lýê­Lë«L¨ê«L©ê­L¥ê­L¨ê«Lâê«Lãê­Lê­Lê«Lê«Lê­Lê«Lê­Lê«Lê­L±ë­L´ë«L÷é­Lúé«Líé­Lðé«Lãë­Læë«LÙê­LÜê«L´ë«Lµë­LÝé­Làé«LÑé­LÔé«L½é­LÀé«L·é­Lºé«L°é«L±é­L¨é«L©é­Lé«Lé­Lôè«Lõè­LÜè«LÝè­LÊè«LËè­L¶è«L·è­L¬è«L­è­L¨è«L©è­Lè«Lè­Löç«L÷ç­Lêç«Lëç­Làç«Láç­LÞç«Lßç­L§©ççQ¬çåQ¤çåQ¥ççQççQçåQ¦çåQ§ççQççQçåQëççQîçåQçåQççQççQçåQÐçåQÑççQççQçåQçåQççQþæåQÿæçQüæåQýæçQèçQ¢èåQåæçQèæåQÛæçQÞæåQÑèçQÔèåQÇççQÊçåQ¢èåQ£èçQËæçQÎæåQ¿æçQÂæåQ«æçQ®æåQ¥æçQ¨æåQæåQæçQæåQæçQöååQ÷åçQâååQãåçQÊååQËåçQ¸ååQ¹åçQ¤ååQ¥åçQååQåçQååQåçQúäåQûäçQääåQåäçQØäåQÙäçQÎäåQÏäçQÌäåQÍäçQ§ä¡WäWäWä¡Wä¡WäWäWä¡Wä¡WäWÙä¡WÜäWäWä¡Wä¡WäW¾äW¿ä¡Wñã¡WôãWîãWïã¡WìãWíã¡WêãWëã¡Wå¡WåWÓã¡WÖãWÉã¡WÌãW¿å¡WÂåWµä¡W¸äWåWå¡W¹ã¡W¼ãW­ã¡W°ãWã¡WãWã¡WãWãWã¡WãWã¡WäâWåâ¡WÐâWÑâ¡W¸âW¹â¡W¦âW§â¡WâWâ¡WâWâ¡WâWâ¡WèáWéá¡WÒáWÓá¡WÆáWÇá¡W¼áW½á¡WºáW»á¡W§áÛ\áÙ\áÙ\áÛ\÷àÛ\úàÙ\áÙ\áÛ\õàÛ\øàÙ\ÇáÛ\ÊáÙ\òàÙ\óàÛ\ïàÛ\òàÙ\¬áÙ\­áÛ\ßàÛ\âàÙ\ÜàÙ\ÝàÛ\ÚàÙ\ÛàÛ\ØàÙ\ÙàÛ\ûáÛ\þáÙ\ÁàÛ\ÄàÙ\·àÛ\ºàÙ\­âÛ\°âÙ\£áÛ\¦áÙ\þáÙ\ÿáÛ\§àÛ\ªàÙ\àÛ\àÙ\àÛ\àÙ\àÛ\àÙ\úßÙ\ûßÛ\òßÙ\óßÛ\ÒßÙ\ÓßÛ\¾ßÙ\¿ßÛ\¦ßÙ\§ßÛ\ßÙ\ßÛ\ßÙ\ßÛ\öÞÙ\÷ÞÛ\òÞÙ\óÞÛ\ÖÞÙ\×ÞÛ\ÀÞÙ\ÁÞÛ\´ÞÙ\µÞÛ\ªÞÙ\«ÞÛ\¨ÞÙ\©ÞÛ\§óÝböÝbîÝbïÝbåÝbèÝbðÝbñÝbãÝbæÝbµÞb¸ÞbàÝbáÝbÝÝbàÝbÞbÞbÍÝbÐÝbÊÝbËÝbÈÝbÉÝbÆÝbÇÝbéÞbìÞb¯Ýb²Ýb¥Ýb¨ÝbßbßbÞbÞbìÞbíÞbÝbÝbÝbÝbõÜbøÜbïÜbòÜbèÜbéÜbàÜbáÜbÀÜbÁÜb¬Üb­ÜbÜbÜbÜbÜbîÛbïÛbäÛbåÛbàÛbáÛbÄÛbÅÛb®Ûb¯Ûb¢Ûb£ÛbÛbÛbÛbÛb§áÚÏgäÚÍgÜÚÍgÝÚÏgÓÚÏgÖÚÍgÞÚÍgßÚÏgÑÚÏgÔÚÍg£ÛÏg¦ÛÍgÎÚÍgÏÚÏgËÚÏgÎÚÍgÛÍgÛÏg»ÚÏg¾ÚÍg¸ÚÍg¹ÚÏg¶ÚÍg·ÚÏg´ÚÍgµÚÏg×ÛÏgÚÛÍgÚÏg ÚÍgÚÏgÚÍgÜÏgÜÍgÿÚÏgÛÍgÚÛÍgÛÛÏgÚÏgÚÍg÷ÙÏgúÙÍgãÙÏgæÙÍgÝÙÏgàÙÍgÖÙÍg×ÙÏgÎÙÍgÏÙÏg®ÙÍg¯ÙÏgÙÍgÙÏgÙÍgÙÏgðØÍgñØÏgÜØÍgÝØÏgÒØÍgÓØÏgÎØÍgÏØÏg²ØÍg³ØÏgØÍgØÏgØÍgØÏgØÍgØÏgØÍgØÏg§Ï×mÒ×mÊ×mË×mÁ×mÄ×mÌ×mÍ×m¿×mÂ×mØmØm¼×m½×m¹×m¼×mö×m÷×m©×m¬×m¦×m§×m¤×m¥×m¢×m£×mÅØmÈØm×m×m×m×m÷ØmúØmí×mð×mÈØmÉØmñÖmôÖmåÖmèÖmÑÖmÔÖmËÖmÎÖmÄÖmÅÖm¼Öm½ÖmÖmÖmÖmÖmðÕmñÕmÞÕmßÕmÊÕmËÕmÀÕmÁÕm¼Õm½Õm Õm¡ÕmÕmÕmþÔmÿÔmôÔmõÔmòÔmóÔm§½ÔÃrÀÔÁr¸ÔÁr¹ÔÃr¯ÔÃr²ÔÁrºÔÁr»ÔÃr­ÔÃr°ÔÁrÿÔÃrÕÁrªÔÁr«ÔÃr§ÔÃrªÔÁräÔÁråÔÃrÔÃrÔÁrÔÁrÔÃrÔÁrÔÃrÔÁrÔÃr³ÕÃr¶ÕÁrùÓÃrüÓÁrïÓÃròÓÁråÕÃrèÕÁrÛÔÃrÞÔÁr¶ÕÁr·ÕÃrßÓÃrâÓÁrÓÓÃrÖÓÁr¿ÓÃrÂÓÁr¹ÓÃr¼ÓÁr²ÓÁr³ÓÃrªÓÁr«ÓÃrÓÁrÓÃröÒÁr÷ÒÃrÞÒÁrßÒÃrÌÒÁrÍÒÃr¸ÒÁr¹ÒÃr®ÒÁr¯ÒÃrªÒÁr«ÒÃrÒÁrÒÃrøÑÁrùÑÃrìÑÁríÑÃrâÑÁrãÑÃràÑÁráÑÃr§«Ñýw®Ñûw¦Ñûw§ÑýwÑýw Ñûw¨Ñûw©ÑýwÑýwÑûwíÑýwðÑûwÑûwÑýwÑýwÑûwÒÑûwÓÑýwÑýwÑûwÑûwÑýwÑûwÑýwþÐûwÿÐýw¡Òýw¤ÒûwçÐýwêÐûwÝÐýwàÐûwÓÒýwÖÒûwÉÑýwÌÑûw¤Òûw¥ÒýwÍÐýwÐÐûwÁÐýwÄÐûw­Ðýw°Ðûw§ÐýwªÐûw Ðûw¡ÐýwÐûwÐýwøÏûwùÏýwäÏûwåÏýwÌÏûwÍÏýwºÏûw»Ïýw¦Ïûw§ÏýwÏûwÏýwÏûwÏýwüÎûwýÎýwæÎûwçÎýwÚÎûwÛÎýwÐÎûwÑÎýwÎÎûwÏÎýw§Î·}Îµ}Îµ}Î·}Î·}Îµ}Îµ}Î·}Î·}Îµ}ÛÎ·}ÞÎµ}Îµ}Î·}Î·}Îµ}ÀÎµ}ÁÎ·}óÍ·}öÍµ}ðÍµ}ñÍ·}îÍµ}ïÍ·}ìÍµ}íÍ·}Ï·}Ïµ}ÕÍ·}ØÍµ}ËÍ·}ÎÍµ}ÁÏ·}ÄÏµ}·Î·}ºÎµ}Ïµ}Ï·}»Í·}¾Íµ}¯Í·}²Íµ}Í·}Íµ}Í·}Íµ}Íµ}Í·}Íµ}Í·}æÌµ}çÌ·}ÒÌµ}ÓÌ·}ºÌµ}»Ì·}¨Ìµ}©Ì·}Ìµ}Ì·}Ìµ}Ì·}Ìµ}Ì·}êËµ}ëË·}ÔËµ}ÕË·}ÈËµ}ÉË·}¾Ëµ}¿Ë·}¼Ëµ}½Ë·}§ËñËïËïËñùÊñüÊïËïËñ÷ÊñúÊïÉËñÌËïôÊïõÊññÊñôÊï®Ëï¯ËñáÊñäÊïÞÊïßÊñÜÊïÝÊñÚÊïÛÊñýËñÌïÃÊñÆÊï¹Êñ¼Êï¯Ìñ²Ìï¥Ëñ¨ËïÌïÌñ©Êñ¬ÊïÊñ ÊïÊñÊïÊñÊïüÉïýÉñôÉïõÉñÔÉïÕÉñÀÉïÁÉñ¨Éï©ÉñÉïÉñÉïÉñøÈïùÈñôÈïõÈñØÈïÙÈñÂÈïÃÈñ¶Èï·Èñ¬Èï­ÈñªÈï«Èñ§õÇ«øÇ©ðÇ©ñÇ«çÇ«êÇ©òÇ©óÇ«åÇ«èÇ©·È«ºÈ©âÇ©ãÇ«ßÇ«âÇ©È©È«ÏÇ«ÒÇ©ÌÇ©ÍÇ«ÊÇ©ËÇ«ÈÇ©ÉÇ«ëÈ«îÈ©±Ç«´Ç©§Ç«ªÇ©É« É©È«È©îÈ©ïÈ«Ç«Ç©Ç«Ç©÷Æ«úÆ©ñÆ«ôÆ©êÆ©ëÆ«âÆ©ãÆ«ÂÆ©ÃÆ«®Æ©¯Æ«Æ©Æ«Æ©Æ«ðÅ©ñÅ«æÅ©çÅ«âÅ©ãÅ«ÆÅ©ÇÅ«°Å©±Å«¤Å©¥Å«Å©Å«Å©Å«§ãÄåæÄãÞÄãßÄåÕÄåØÄãàÄãáÄåÓÄåÖÄã¥Åå¨ÅãÐÄãÑÄåÍÄåÐÄãÅãÅå½ÄåÀÄãºÄã»Äå¸Äã¹Äå¶Äã·ÄåÙÅåÜÅãÄå¢ÄãÄåÄãÆåÆãÅåÅãÜÅãÝÅåÄåÄãùÃåüÃãåÃåèÃãßÃåâÃãØÃãÙÃåÐÃãÑÃå°Ãã±ÃåÃãÃåÃãÃåòÂãóÂåÞÂãßÂåÔÂãÕÂåÐÂãÑÂå´ÂãµÂåÂãÂåÂãÂåÂãÂåÂãÂå§ÑÁÔÁÌÁÍÁÃÁÆÁÎÁÏÁÁÁÄÁÂÂ¾Á¿Á»Á¾ÁøÁùÁ«Á®Á¨Á©Á¦Á§Á¤Á¥ÁÇÂÊÂÁÁÁÁùÂüÂïÁòÁÊÂËÂóÀöÀçÀêÀÓÀÖÀÍÀÐÀÆÀÇÀ¾À¿ÀÀÀÀÀò¿ó¿à¿á¿Ì¿Í¿Â¿Ã¿¾¿¿¿¢¿£¿¿¿¿¿ö¾÷¾ô¾õ¾§¿¾ÙÂ¾×º¾×»¾Ù±¾Ù´¾×¼¾×½¾Ù¯¾Ù²¾×¿Ù¿×¬¾×­¾Ù©¾Ù¬¾×æ¾×ç¾Ù¾Ù¾×¾×¾Ù¾×¾Ù¾×¾Ùµ¿Ù¸¿×û½Ùþ½×ñ½Ùô½×ç¿Ùê¿×Ý¾Ùà¾×¸¿×¹¿Ùá½Ùä½×Õ½ÙØ½×Á½ÙÄ½×»½Ù¾½×´½×µ½Ù¬½×­½Ù½×½Ùø¼×ù¼Ùà¼×á¼ÙÎ¼×Ï¼Ùº¼×»¼Ù°¼×±¼Ù¬¼×­¼Ù¼×¼Ùú»×û»Ùî»×ï»Ùä»×å»Ùâ»×ã»Ù§­»°»¨»©»»¢»ª»«»» »ï»ò»»»»»Ô»Õ»»»»»»»»»£¼¦¼éºìºßºâºÕ¼Ø¼Ë»Î»¦¼§¼ÏºÒºÃºÆº¯º²º©º¬º¢º£ºººú¹û¹æ¹ç¹Î¹Ï¹¼¹½¹¨¹©¹¹¹¹¹þ¸ÿ¸è¸é¸Ü¸Ý¸Ò¸Ó¸Ð¸Ñ¸§¸Í£¸Ë£¸Ë£¸Í£¸Í£¸Ë£¸Ë£¸Í£¸Í£¸Ë£Ý¸Í£à¸Ë£¸Ë£¸Í£¸Í£¸Ë£Â¸Ë£Ã¸Í£õ·Í£ø·Ë£ò·Ë£ó·Í£ð·Ë£ñ·Í£î·Ë£ï·Í£¹Í£¹Ë£×·Í£Ú·Ë£Í·Í£Ð·Ë£Ã¹Í£Æ¹Ë£¹¸Í£¼¸Ë£¹Ë£¹Í£½·Í£À·Ë£±·Í£´·Ë£·Í£ ·Ë£·Í£·Ë£·Ë£·Í£·Ë£·Í£è¶Ë£é¶Í£Ô¶Ë£Õ¶Í£¼¶Ë£½¶Í£ª¶Ë£«¶Í£¶Ë£¶Í£¶Ë£¶Í£¶Ë£¶Í£ìµË£íµÍ£ÖµË£×µÍ£ÊµË£ËµÍ£ÀµË£ÁµÍ£¾µË£¿µÍ£§µ©µ©µ©µ©û´©þ´©µ©µ©ù´©ü´©Ëµ©Îµ©ö´©÷´©ó´©ö´©°µ©±µ©ã´©æ´©à´©á´©Þ´©ß´©Ü´©Ý´©ÿµ©¶©Å´©È´©»´©¾´©±¶©´¶©§µ©ªµ©¶©¶©«´©®´©´©¢´©´©´©´©´©þ³©ÿ³©ö³©÷³©Ö³©×³©Â³©Ã³©ª³©«³©³©³©³©³©ú²©û²©ö²©÷²©Ú²©Û²©Ä²©Å²©¸²©¹²©®²©¯²©¬²©­²©§÷±Á®ú±¿®ò±¿®ó±Á®é±Á®ì±¿®ô±¿®õ±Á®ç±Á®ê±¿®¹²Á®¼²¿®ä±¿®å±Á®á±Á®ä±¿®²¿®²Á®Ñ±Á®Ô±¿®Î±¿®Ï±Á®Ì±¿®Í±Á®Ê±¿®Ë±Á®í²Á®ð²¿®³±Á®¶±¿®©±Á®¬±¿®³Á®¢³¿®²Á®²¿®ð²¿®ñ²Á®±Á®±¿®±Á®±¿®ù°Á®ü°¿®ó°Á®ö°¿®ì°¿®í°Á®ä°¿®å°Á®Ä°¿®Å°Á®°°¿®±°Á®°¿®°Á®°¿®°Á®ò¯¿®ó¯Á®è¯¿®é¯Á®ä¯¿®å¯Á®È¯¿®É¯Á®²¯¿®³¯Á®¦¯¿®§¯Á®¯¿®¯Á®¯¿®¯Á®§å®û³è®ù³à®ù³á®û³×®û³Ú®ù³â®ù³ã®û³Õ®û³Ø®ù³§¯û³ª¯ù³Ò®ù³Ó®û³Ï®û³Ò®ù³¯ù³¯û³¿®û³Â®ù³¼®ù³½®û³º®ù³»®û³¸®ù³¹®û³Û¯û³Þ¯ù³¡®û³¤®ù³®û³®ù³°û³°ù³¯û³¯ù³Þ¯ù³ß¯û³®û³®ù³û­û³þ­ù³ç­û³ê­ù³á­û³ä­ù³Ú­ù³Û­û³Ò­ù³Ó­û³²­ù³³­û³­ù³­û³­ù³­û³ô¬ù³õ¬û³à¬ù³á¬û³Ö¬ù³×¬û³Ò¬ù³Ó¬û³¶¬ù³·¬û³ ¬ù³¡¬û³¬ù³¬û³¬ù³¬û³¬ù³¬û³§Ó«µ¹Ö«³¹Î«³¹Ï«µ¹Å«µ¹È«³¹Ð«³¹Ñ«µ¹Ã«µ¹Æ«³¹¬µ¹¬³¹À«³¹Á«µ¹½«µ¹À«³¹ú«³¹û«µ¹­«µ¹°«³¹ª«³¹««µ¹¨«³¹©«µ¹¦«³¹§«µ¹É¬µ¹Ì¬³¹«µ¹«³¹«µ¹«³¹û¬µ¹þ¬³¹ñ«µ¹ô«³¹Ì¬³¹Í¬µ¹õªµ¹øª³¹éªµ¹ìª³¹Õªµ¹Øª³¹Ïªµ¹Òª³¹Èª³¹Éªµ¹Àª³¹Áªµ¹ ª³¹¡ªµ¹ª³¹ªµ¹ô©³¹õ©µ¹â©³¹ã©µ¹Î©³¹Ï©µ¹Ä©³¹Å©µ¹À©³¹Á©µ¹¤©³¹¥©µ¹©³¹©µ¹©³¹©µ¹ø¨³¹ù¨µ¹ö¨³¹÷¨µ¹§Á¨ï¾Ä¨í¾¼¨í¾½¨ï¾³¨ï¾¶¨í¾¾¨í¾¿¨ï¾±¨ï¾´¨í¾©ï¾©í¾®¨í¾¯¨ï¾«¨ï¾®¨í¾è¨í¾é¨ï¾¨ï¾¨í¾¨í¾¨ï¾¨í¾¨ï¾¨í¾¨ï¾·©ï¾º©í¾ý§ï¾¨í¾ó§ï¾ö§í¾é©ï¾ì©í¾ß¨ï¾â¨í¾º©í¾»©ï¾ã§ï¾æ§í¾×§ï¾Ú§í¾Ã§ï¾Æ§í¾½§ï¾À§í¾¶§í¾·§ï¾®§í¾¯§ï¾§í¾§ï¾ú¦í¾û¦ï¾â¦í¾ã¦ï¾Ð¦í¾Ñ¦ï¾¼¦í¾½¦ï¾²¦í¾³¦ï¾®¦í¾¯¦ï¾¦í¾¦ï¾ü¥í¾ý¥ï¾ð¥í¾ñ¥ï¾æ¥í¾ç¥ï¾ä¥í¾å¥ï¾§¯¥©Ä²¥§Äª¥§Ä«¥©Ä¡¥©Ä¤¥§Ä¬¥§Ä­¥©Ä¥©Ä¢¥§Äñ¥©Äô¥§Ä¥§Ä¥©Ä¥©Ä¥§ÄÖ¥§Ä×¥©Ä¥©Ä¥§Ä¥§Ä¥©Ä¥§Ä¥©Ä¥§Ä¥©Ä¥¦©Ä¨¦§Äë¤©Äî¤§Äá¤©Ää¤§Ä×¦©ÄÚ¦§ÄÍ¥©ÄÐ¥§Ä¨¦§Ä©¦©ÄÑ¤©ÄÔ¤§ÄÅ¤©ÄÈ¤§Ä±¤©Ä´¤§Ä«¤©Ä®¤§Ä¤¤§Ä¥¤©Ä¤§Ä¤©Äü£§Äý£©Äè£§Äé£©ÄÐ£§ÄÑ£©Ä¾£§Ä¿£©Äª£§Ä«£©Ä £§Ä¡£©Ä£§Ä£©Ä£§Ä£©Äê¢§Äë¢©ÄÞ¢§Äß¢©ÄÔ¢§ÄÕ¢©ÄÒ¢§ÄÓ¢©Ä§¢ãÉ ¢áÉ¢áÉ¢ãÉ¢ãÉ¢áÉ¢áÉ¢ãÉ¢ãÉ¢áÉß¢ãÉâ¢áÉ¢áÉ¢ãÉ¢ãÉ¢áÉÄ¢áÉÅ¢ãÉ÷¡ãÉú¡áÉô¡áÉõ¡ãÉò¡áÉó¡ãÉð¡áÉñ¡ãÉ£ãÉ£áÉÙ¡ãÉÜ¡áÉÏ¡ãÉÒ¡áÉÅ£ãÉÈ£áÉ»¢ãÉ¾¢áÉ£áÉ£ãÉ¿¡ãÉÂ¡áÉ³¡ãÉ¶¡áÉ¡ãÉ¢¡áÉ¡ãÉ¡áÉ¡áÉ¡ãÉ¡áÉ¡ãÉê áÉë ãÉÖ áÉ× ãÉ¾ áÉ¿ ãÉ¬ áÉ­ ãÉ áÉ ãÉ áÉ ãÉ áÉ ãÉîáÉïãÉØáÉÙãÉÌáÉÍãÉÂáÉÃãÉÀáÉÁãÉ§ÏÏÏÏýÏÏÏÏûÏþÏÍÏÐÏøÏùÏõÏøÏ²Ï³ÏåÏèÏâÏãÏàÏáÏÞÏßÏ Ï ÏÇÏÊÏ½ÏÀÏ³ Ï¶ Ï©Ï¬Ï Ï Ï­Ï°Ï¡Ï¤ÏÏÏÏÏÏÏøÏùÏØÏÙÏÄÏÅÏ¬Ï­ÏÏÏÏÏüÏýÏøÏùÏÜÏÝÏÆÏÇÏºÏ»Ï°Ï±Ï®Ï¯Ï§ù×ÔüÕÔôÕÔõ×Ôë×ÔîÕÔöÕÔ÷×Ôé×ÔìÕÔ»×Ô¾ÕÔæÕÔç×Ôã×ÔæÕÔ ÕÔ¡×ÔÓ×ÔÖÕÔÐÕÔÑ×ÔÎÕÔÏ×ÔÌÕÔÍ×Ôï×ÔòÕÔµ×Ô¸ÕÔ«×Ô®ÕÔ¡×Ô¤ÕÔ×ÔÕÔòÕÔó×Ô×ÔÕÔ×ÔÕÔû×ÔþÕÔõ×ÔøÕÔîÕÔï×ÔæÕÔç×ÔÆÕÔÇ×Ô²ÕÔ³×ÔÕÔ×ÔÕÔ×ÔôÕÔõ×ÔêÕÔë×ÔæÕÔç×ÔÊÕÔË×Ô´ÕÔµ×Ô¨ÕÔ©×ÔÕÔ×ÔÕÔ×Ô§çÚêÚâÚãÚÙÚÜÚäÚåÚ×ÚÚÚ©Ú¬ÚÔÚÕÚÑÚÔÚÚÚÁÚÄÚ¾Ú¿Ú¼Ú½ÚºÚ»ÚÝÚàÚ£Ú¦ÚÚÚÚÚÚÚàÚáÚÚÚýÚÚéÚìÚãÚæÚÜÚÝÚÔÚÕÚ´ÚµÚ Ú¡ÚÚÚöÚ÷ÚâÚãÚØÚÙÚÔÚÕÚ¸Ú¹Ú¢Ú£ÚÚÚÚÚÚÚ§ÕËßØÉßÐÉßÑËßÇËßÊÉßÒÉßÓËßÅËßÈÉßËßÉßÂÉßÃËß¿ËßÂÉßüÉßýËß¯Ëß²Éß¬Éß­ËßªÉß«Ëß¨Éß©ËßËËßÎÉßËßÉßËßÉßýËßÉßóËßöÉßÎÉßÏËß÷ËßúÉßëËßîÉß×ËßÚÉßÑËßÔÉßÊÉßËËßÂÉßÃËß¢Éß£ËßÉßËßöÉß÷ËßäÉßåËßÐÉßÑËßÆÉßÇËßÂÉßÃËß¦Éß§ËßÉßËßÉßËßúÉßûËßøÉßùËß§ÃåÆå¾å¿åµå¸åÀåÁå³å¶ååå°å±å­å°åêåëåå ååååååå¹å¼åÿååõåøåëåîåáåäå¼å½åååèåÙåÜåÅåÈå¿åÂå¸å¹å°å±åååüåýåäåååÒåÓå¾å¿å´åµå°å±åååþåÿåòåóåèåéåæåçå§±¿ê´½ê¬½ê­¿ê£¿ê¦½ê®½ê¯¿ê¡¿ê¤½êó¿êö½ê½ê¿ê¿ê½êØ½êÙ¿ê¿ê½ê½ê¿ê½ê¿ê½ê¿ê§¿êª½êí¿êð½êã¿êæ½êÙ¿êÜ½êÏ¿êÒ½êª½ê«¿êÓ¿êÖ½êÇ¿êÊ½ê³¿ê¶½ê­¿ê°½ê¦½ê§¿ê½ê¿êþ½êÿ¿êê½êë¿êÒ½êÓ¿êÀ½êÁ¿ê¬½ê­¿ê¢½ê£¿ê½ê¿ê½ê¿êì½êí¿êà½êá¿êÖ½ê×¿êÔ½êÕ¿ê§ùï¢÷ï÷ïùïùï÷ï÷ïùïùï÷ïáùïä÷ï÷ïùïùï÷ïÆ÷ïÇùïùùïü÷ïö÷ï÷ùïô÷ïõùïò÷ïóùïùï÷ïÛùïÞ÷ïÑùïÔ÷ïÇùïÊ÷ï½ùïÀ÷ï÷ïùïÁùïÄ÷ïµùï¸÷ï¡ùï¤÷ïùï÷ï÷ïùï÷ïùïì÷ïíùïØ÷ïÙùïÀ÷ïÁùï®÷ï¯ùï÷ïùï÷ïùï÷ïùïð÷ïñùïÚ÷ïÛùïÎ÷ïÏùïÄ÷ïÅùïÂ÷ïÃùï§³õ±õ±õ³õÿ³õ±õ±õ³õý³õ±õÏ³õÒ±õú±õû³õ÷³õú±õ´±õµ³õç³õê±õä±õå³õâ±õã³õà±õá³õ³õ±õÉ³õÌ±õ¿³õÂ±õµ³õ¸±õ«³õ®±õ±õ³õ¯³õ²±õ£³õ¦±õ³õ±õ³õ±õ±õ³õú±õû³õÚ±õÛ³õÆ±õÇ³õ®±õ¯³õ±õ³õ±õ³õþ±õÿ³õú±õû³õÞ±õß³õÈ±õÉ³õ¼±õ½³õ²±õ³³õ°±õ±³õ§ûíúþëúöëú÷íúííúðëúøëúùíúëíúîëú½íúÀëúèëúéíúåíúèëú¢ëú£íúÕíúØëúÒëúÓíúÐëúÑíúÎëúÏíúñíúôëú·íúºëú­íú°ëú£íú¦ëúíúëúôëúõíúíú ëúíúëúýíúëú÷íúúëúðëúñíúèëúéíúÈëúÉíú´ëúµíúëúíúëúíúöëú÷íúìëúííúèëúéíúÌëúÍíú¶ëú·íúªëú«íú ëú¡íúëúíú§é§ì¥ä¥å§Û§Þ¥æ¥ç§Ù§Ü¥«§®¥Ö¥×§Ó§Ö¥¥§Ã§Æ¥À¥Á§¾¥¿§¼¥½§ß§â¥¥§¨¥§¥§¥§¥â¥ã§§¥ÿ§¥ë§î¥å§è¥Þ¥ß§Ö¥×§¶¥·§¢¥£§¥§ø¥ù§ä¥å§Ú¥Û§Ö¥×§º¥»§¤¥¥§¥§¥§¥§§×ÿáÚÿßÒÿßÓÿáÉÿáÌÿßÔÿßÕÿáÇÿáÊÿßáßÄÿßÅÿáÁÿáÄÿßþÿßÿÿá±ÿá´ÿß®ÿß¯ÿá¬ÿß­ÿáªÿß«ÿáÍáÐßÿáÿßÿáÿßÿáßõÿáøÿßÐßÑáùþáüþßíþáðþßÙþáÜþßÓþáÖþßÌþßÍþáÄþßÅþá¤þß¥þáþßþáøýßùýáæýßçýáÒýßÓýáÈýßÉýáÄýßÅýá¨ýß©ýáýßýáýßýáüüßýüáúüßûüá§ÅüÈüÀüÁü·üºüÂüÃüµü¸üýý²ü³ü¯ü²üìüíüü¢üüüüüüü»ý¾ýüü÷ûúûíýðýãüæü¾ý¿ýçûêûÛûÞûÇûÊûÁûÄûºû»û²û³ûûûþúÿúæúçúÔúÕúÀúÁú¶ú·ú²ú³úúúúúôùõùêùëùèùéù§³ùÕ¶ùÓ®ùÓ¯ùÕ¥ùÕ¨ùÓ°ùÓ±ùÕ£ùÕ¦ùÓõùÕøùÓ ùÓ¡ùÕùÕ ùÓÚùÓÛùÕùÕùÓùÓùÕùÓùÕùÓùÕ©úÕ¬úÓïøÕòøÓåøÕèøÓÛúÕÞúÓÑùÕÔùÓ¬úÓ­úÕÕøÕØøÓÉøÕÌøÓµøÕ¸øÓ¯øÕ²øÓ¨øÓ©øÕ øÓ¡øÕøÓøÕì÷Óí÷ÕÔ÷ÓÕ÷ÕÂ÷ÓÃ÷Õ®÷Ó¯÷Õ¤÷Ó¥÷Õ ÷Ó¡÷Õ÷Ó÷ÕîöÓïöÕâöÓãöÕØöÓÙöÕÖöÓ×öÕ§¡ö¤öööööööööãöæöööööÈöÉöûõþõøõùõöõ÷õôõõõ÷÷ÝõàõÓõÖõÉ÷Ì÷¿öÂö÷÷ÃõÆõ·õºõ£õ¦õõ õõõõõîôïôÚôÛôÂôÃô°ô±ôôôôôôôòóóóÜóÝóÐóÑóÆóÇóÄóÅó§óÉóÇóÇóÉóÉóÇóÇóÉÿòÉóÇÑóÉÔóÇüòÇýòÉùòÉüòÇ¶óÇ·óÉéòÉìòÇæòÇçòÉäòÇåòÉâòÇãòÉôÉôÇËòÉÎòÇÁòÉÄòÇ·ôÉºôÇ­óÉ°óÇôÇôÉ±òÉ´òÇ¥òÉ¨òÇòÉòÇòÉòÇòÇòÉüñÇýñÉÜñÇÝñÉÈñÇÉñÉ°ñÇ±ñÉñÇñÉñÇñÉñÇñÉüðÇýðÉàðÇáðÉÊðÇËðÉ¾ðÇ¿ðÉ´ðÇµðÉ²ðÇ³ðÉ§»¹¹»ý»¹¹»û»þ¹Í»Ð¹ø¹ù»õ»ø¹²¹³»å»è¹â¹ã»à¹á»Þ¹ß»»¹Ç»Ê¹½»À¹³»¶¹©»¬¹¹»­»°¹¡»¤¹»¹»¹¹»ø¹ù»Ø¹Ù»Ä¹Å»¬¹­»¹»¹»ü¹ý»ø¹ù»Ü¹Ý»Æ¹Ç»º¹»»°¹±»®¹¯»§ùõ
+üó
+ôó
+õõ
+ëõ
+îó
+öó
+÷õ
+éõ
+ìó
+»õ
+¾ó
+æó
+çõ
+ãõ
+æó
+ ó
+¡õ
+Óõ
+Öó
+Ðó
+Ñõ
+Îó
+Ïõ
+Ìó
+Íõ
+ïõ
+òó
+µõ
+¸ó
+«õ
+®ó
+¡õ
+¤ó
+õ
+ó
+òó
+óõ
+õ
+ó
+õ
+ó
+ûõ
+þó
+õõ
+øó
+îó
+ïõ
+æó
+çõ
+Æó
+Çõ
+²ó
+³õ
+ó
+õ
+ó
+õ
+ôó
+õõ
+êó
+ëõ
+æó
+çõ
+Êó
+Ëõ
+´ó
+µõ
+¨ó
+©õ
+ó
+õ
+ó
+õ
+§çÿ¯êÿ­âÿ­ãÿ¯Ùÿ¯Üÿ­äÿ­åÿ¯×ÿ¯Úÿ­©¯¬­Ôÿ­Õÿ¯Ñÿ¯Ôÿ­­¯Áÿ¯Äÿ­¾ÿ­¿ÿ¯¼ÿ­½ÿ¯ºÿ­»ÿ¯Ý¯à­£ÿ¯¦ÿ­ÿ¯ÿ­¯­¯­à­á¯ÿ¯ÿ­ýþ¯ÿ­éþ¯ìþ­ãþ¯æþ­Üþ­Ýþ¯Ôþ­Õþ¯´þ­µþ¯ þ­¡þ¯þ­þ¯öý­÷ý¯âý­ãý¯Øý­Ùý¯Ôý­Õý¯¸ý­¹ý¯¢ý­£ý¯ý­ý¯ý­ý¯ý­ý¯§ÕüéØüçÐüçÑüéÇüéÊüçÒüçÓüéÅüéÈüçýéýçÂüçÃüé¿üéÂüçüüçýüé¯üé²üç¬üç­üéªüç«üé¨üç©üéËýéÎýçüéüçüéüçýýéþçóüéöüçÎýçÏýé÷ûéúûçëûéîûç×ûéÚûçÑûéÔûçÊûçËûéÂûçÃûé¢ûç£ûéûçûéöúç÷úéäúçåúéÐúçÑúéÆúçÇúéÂúçÃúé¦úç§úéúçúéúçúéúùçûùéøùçùùé§Ãù£Æù¡¾ù¡¿ù£µù£¸ù¡Àù¡Áù£³ù£¶ù¡ú£ú¡°ù¡±ù£­ù£°ù¡êù¡ëù£ù£ ù¡ù¡ù£ù¡ù£ù¡ù£¹ú£¼ú¡ÿø£ù¡õø£øø¡ëú£îú¡áù£äù¡¼ú¡½ú£åø£èø¡Ùø£Üø¡Åø£Èø¡¿ø£Âø¡¸ø¡¹ø£°ø¡±ø£ø¡ø£ü÷¡ý÷£ä÷¡å÷£Ò÷¡Ó÷£¾÷¡¿÷£´÷¡µ÷£°÷¡±÷£÷¡÷£þö¡ÿö£òö¡óö£èö¡éö£æö¡çö£§±öÝ ´öÛ ¬öÛ ­öÝ £öÝ ¦öÛ ®öÛ ¯öÝ ¡öÝ ¤öÛ óöÝ ööÛ öÛ öÝ öÝ öÛ ØöÛ ÙöÝ öÝ öÛ öÛ öÝ öÛ öÝ öÛ öÝ §÷Ý ª÷Û íõÝ ðõÛ ãõÝ æõÛ Ù÷Ý Ü÷Û ÏöÝ ÒöÛ ª÷Û «÷Ý ÓõÝ ÖõÛ ÇõÝ ÊõÛ ³õÝ ¶õÛ ­õÝ °õÛ ¦õÛ §õÝ õÛ õÝ þôÛ ÿôÝ êôÛ ëôÝ ÒôÛ ÓôÝ ÀôÛ ÁôÝ ¬ôÛ ­ôÝ ¢ôÛ £ôÝ ôÛ ôÝ ôÛ ôÝ ìóÛ íóÝ àóÛ áóÝ ÖóÛ ×óÝ ÔóÛ ÕóÝ §ó&¢ó&ó&ó&ó&ó&ó&ó&ó&ó&áó&äó&ó&ó&ó&ó&Æó&Çó&ùò&üò&öò&÷ò&ôò&õò&òò&óò&ô&ô&Ûò&Þò&Ñò&Ôò&Çô&Êô&½ó&Àó&ô&ô&Áò&Äò&µò&¸ò&¡ò&¤ò&ò&ò&ò&ò&ò&ò&ìñ&íñ&Øñ&Ùñ&Àñ&Áñ&®ñ&¯ñ&ñ&ñ&ñ&ñ&ñ&ñ&ðð&ñð&Úð&Ûð&Îð&Ïð&Äð&Åð&Âð&Ãð&§ðÑ+ðÏ+ðÏ+ðÑ+ÿïÑ+ðÏ+ðÏ+ðÑ+ýïÑ+ðÏ+ÏðÑ+ÒðÏ+úïÏ+ûïÑ+÷ïÑ+úïÏ+´ðÏ+µðÑ+çïÑ+êïÏ+äïÏ+åïÑ+âïÏ+ãïÑ+àïÏ+áïÑ+ñÑ+ñÏ+ÉïÑ+ÌïÏ+¿ïÑ+ÂïÏ+µñÑ+¸ñÏ+«ðÑ+®ðÏ+ñÏ+ñÑ+¯ïÑ+²ïÏ+£ïÑ+¦ïÏ+ïÑ+ïÏ+ïÑ+ïÏ+ïÏ+ïÑ+úîÏ+ûîÑ+ÚîÏ+ÛîÑ+ÆîÏ+ÇîÑ+®îÏ+¯îÑ+îÏ+îÑ+îÏ+îÑ+þíÏ+ÿíÑ+úíÏ+ûíÑ+ÞíÏ+ßíÑ+ÈíÏ+ÉíÑ+¼íÏ+½íÑ+²íÏ+³íÑ+°íÏ+±íÑ+§ûì1þì1öì1÷ì1íì1ðì1øì1ùì1ëì1îì1½í1Àí1èì1éì1åì1èì1¢í1£í1Õì1Øì1Òì1Óì1Ðì1Ñì1Îì1Ïì1ñí1ôí1·ì1ºì1­ì1°ì1£î1¦î1í1í1ôí1õí1ì1 ì1ì1ì1ýë1ì1÷ë1úë1ðë1ñë1èë1éë1Èë1Éë1´ë1µë1ë1ë1ë1ë1öê1÷ê1ìê1íê1èê1éê1Ìê1Íê1¶ê1·ê1ªê1«ê1 ê1¡ê1ê1ê1§ééÅ6ìéÃ6äéÃ6åéÅ6ÛéÅ6ÞéÃ6æéÃ6çéÅ6ÙéÅ6ÜéÃ6«êÅ6®êÃ6ÖéÃ6×éÅ6ÓéÅ6ÖéÃ6êÃ6êÅ6ÃéÅ6ÆéÃ6ÀéÃ6ÁéÅ6¾éÃ6¿éÅ6¼éÃ6½éÅ6ßêÅ6âêÃ6¥éÅ6¨éÃ6éÅ6éÃ6ëÅ6ëÃ6êÅ6êÃ6âêÃ6ãêÅ6éÅ6éÃ6ÿèÅ6éÃ6ëèÅ6îèÃ6åèÅ6èèÃ6ÞèÃ6ßèÅ6ÖèÃ6×èÅ6¶èÃ6·èÅ6¢èÃ6£èÅ6èÃ6èÅ6øçÃ6ùçÅ6äçÃ6åçÅ6ÚçÃ6ÛçÅ6ÖçÃ6×çÅ6ºçÃ6»çÅ6¤çÃ6¥çÅ6çÃ6çÅ6çÃ6çÅ6çÃ6çÅ6§×æÿ;Úæý;Òæý;Óæÿ;Éæÿ;Ìæý;Ôæý;Õæÿ;Çæÿ;Êæý;çÿ;çý;Äæý;Åæÿ;Áæÿ;Äæý;þæý;ÿæÿ;±æÿ;´æý;®æý;¯æÿ;¬æý;­æÿ;ªæý;«æÿ;Íçÿ;Ðçý;æÿ;æý;æÿ;æý;ÿçÿ;èý;õæÿ;øæý;Ðçý;Ñçÿ;ùåÿ;üåý;íåÿ;ðåý;Ùåÿ;Üåý;Óåÿ;Öåý;Ìåý;Íåÿ;Äåý;Ååÿ;¤åý;¥åÿ;åý;åÿ;øäý;ùäÿ;æäý;çäÿ;Òäý;Óäÿ;Èäý;Éäÿ;Ääý;Åäÿ;¨äý;©äÿ;äý;äÿ;äý;äÿ;üãý;ýãÿ;úãý;ûãÿ;§Åã¹AÈã·AÀã·AÁã¹A·ã¹Aºã·AÂã·AÃã¹Aµã¹A¸ã·Aä¹Aä·A²ã·A³ã¹A¯ã¹A²ã·Aìã·Aíã¹Aã¹A¢ã·Aã·Aã¹Aã·Aã¹Aã·Aã¹A»ä¹A¾ä·Aã¹Aã·A÷â¹Aúâ·Aíä¹Aðä·Aãã¹Aæã·A¾ä·A¿ä¹Açâ¹Aêâ·AÛâ¹AÞâ·AÇâ¹AÊâ·AÁâ¹AÄâ·Aºâ·A»â¹A²â·A³â¹Aâ·Aâ¹Aþá·Aÿá¹Aæá·Açá¹AÔá·AÕá¹AÀá·AÁá¹A¶á·A·á¹A²á·A³á¹Aá·Aá¹Aá·Aá¹Aôà·Aõà¹Aêà·Aëà¹Aèà·Aéà¹A§³àóF¶àñF®àñF¯àóF¥àóF¨àñF°àñF±àóF£àóF¦àñFõàóFøàñF àñF¡àóFàóF àñFÚàñFÛàóFàóFàñFàñFàóFàñFàóFàñFàóF©áóF¬áñFïßóFòßñFåßóFèßñFÛáóFÞáñFÑàóFÔàñF¬áñF­áóFÕßóFØßñFÉßóFÌßñFµßóF¸ßñF¯ßóF²ßñF¨ßñF©ßóF ßñF¡ßóFßñFßóFìÞñFíÞóFÔÞñFÕÞóFÂÞñFÃÞóF®ÞñF¯ÞóF¤ÞñF¥ÞóF ÞñF¡ÞóFÞñFÞóFîÝñFïÝóFâÝñFãÝóFØÝñFÙÝóFÖÝñF×ÝóF§¡Ý­L¤Ý«LÝ«LÝ­LÝ­LÝ«LÝ«LÝ­LÝ­LÝ«LãÝ­LæÝ«LÝ«LÝ­LÝ­LÝ«LÈÝ«LÉÝ­LûÜ­LþÜ«LøÜ«LùÜ­LöÜ«L÷Ü­LôÜ«LõÜ­LÞ­LÞ«LÝÜ­LàÜ«LÓÜ­LÖÜ«LÉÞ­LÌÞ«L¿Ý­LÂÝ«LÞ«LÞ­LÃÜ­LÆÜ«L·Ü­LºÜ«L£Ü­L¦Ü«LÜ­L Ü«LÜ«LÜ­LÜ«LÜ­LîÛ«LïÛ­LÚÛ«LÛÛ­LÂÛ«LÃÛ­L°Û«L±Û­LÛ«LÛ­LÛ«LÛ­LÛ«LÛ­LòÚ«LóÚ­LÜÚ«LÝÚ­LÐÚ«LÑÚ­LÆÚ«LÇÚ­LÄÚ«LÅÚ­L§ÚçQÚåQÚåQÚçQÚçQÚåQÚåQÚçQÿÙçQÚåQÑÚçQÔÚåQüÙåQýÙçQùÙçQüÙåQ¶ÚåQ·ÚçQéÙçQìÙåQæÙåQçÙçQäÙåQåÙçQâÙåQãÙçQÛçQÛåQËÙçQÎÙåQÁÙçQÄÙåQ·ÛçQºÛåQ­ÚçQ°ÚåQÛåQÛçQ±ÙçQ´ÙåQ¥ÙçQ¨ÙåQÙçQÙåQÙçQÙåQÙåQÙçQüØåQýØçQÜØåQÝØçQÈØåQÉØçQ°ØåQ±ØçQØåQØçQØåQØçQØåQØçQü×åQý×çQà×åQá×çQÊ×åQË×çQ¾×åQ¿×çQ´×åQµ×çQ²×åQ³×çQ§ýÖ¡W×WøÖWùÖ¡WïÖ¡WòÖWúÖWûÖ¡WíÖ¡WðÖW¿×¡WÂ×WêÖWëÖ¡WçÖ¡WêÖW¤×W¥×¡W×Ö¡WÚÖWÔÖWÕÖ¡WÒÖWÓÖ¡WÐÖWÑÖ¡Wó×¡Wö×W¹Ö¡W¼ÖW¯Ö¡W²ÖW¥Ø¡W¨ØW×¡W×Wö×W÷×¡WÖ¡W¢ÖWÖ¡WÖWÿÕ¡WÖWùÕ¡WüÕWòÕWóÕ¡WêÕWëÕ¡WÊÕWËÕ¡W¶ÕW·Õ¡WÕWÕ¡WÕWÕ¡WøÔWùÔ¡WîÔWïÔ¡WêÔWëÔ¡WÎÔWÏÔ¡W¸ÔW¹Ô¡W¬ÔW­Ô¡W¢ÔW£Ô¡W ÔW¡Ô¡W§ëÓÛ\îÓÙ\æÓÙ\çÓÛ\ÝÓÛ\àÓÙ\èÓÙ\éÓÛ\ÛÓÛ\ÞÓÙ\­ÔÛ\°ÔÙ\ØÓÙ\ÙÓÛ\ÕÓÛ\ØÓÙ\ÔÙ\ÔÛ\ÅÓÛ\ÈÓÙ\ÂÓÙ\ÃÓÛ\ÀÓÙ\ÁÓÛ\¾ÓÙ\¿ÓÛ\áÔÛ\äÔÙ\§ÓÛ\ªÓÙ\ÓÛ\ ÓÙ\ÕÛ\ÕÙ\ÔÛ\ÔÙ\äÔÙ\åÔÛ\ÓÛ\ÓÙ\ÓÛ\ÓÙ\íÒÛ\ðÒÙ\çÒÛ\êÒÙ\àÒÙ\áÒÛ\ØÒÙ\ÙÒÛ\¸ÒÙ\¹ÒÛ\¤ÒÙ\¥ÒÛ\ÒÙ\ÒÛ\úÑÙ\ûÑÛ\æÑÙ\çÑÛ\ÜÑÙ\ÝÑÛ\ØÑÙ\ÙÑÛ\¼ÑÙ\½ÑÛ\¦ÑÙ\§ÑÛ\ÑÙ\ÑÛ\ÑÙ\ÑÛ\ÑÙ\ÑÛ\§ÙÐbÜÐbÔÐbÕÐbËÐbÎÐbÖÐb×ÐbÉÐbÌÐbÑbÑbÆÐbÇÐbÃÐbÆÐbÑbÑb³Ðb¶Ðb°Ðb±Ðb®Ðb¯Ðb¬Ðb­ÐbÏÑbÒÑbÐbÐbÐbÐbÒbÒb÷ÐbúÐbÒÑbÓÑbûÏbþÏbïÏbòÏbÛÏbÞÏbÕÏbØÏbÎÏbÏÏbÆÏbÇÏb¦Ïb§ÏbÏbÏbúÎbûÎbèÎbéÎbÔÎbÕÎbÊÎbËÎbÆÎbÇÎbªÎb«ÎbÎbÎbÎbÎbþÍbÿÍbüÍbýÍb§ÇÍÏgÊÍÍgÂÍÍgÃÍÏg¹ÍÏg¼ÍÍgÄÍÍgÅÍÏg·ÍÏgºÍÍgÎÏgÎÍg´ÍÍgµÍÏg±ÍÏg´ÍÍgîÍÍgïÍÏg¡ÍÏg¤ÍÍgÍÍgÍÏgÍÍgÍÏgÍÍgÍÏg½ÎÏgÀÎÍgÍÏgÍÍgùÌÏgüÌÍgïÎÏgòÎÍgåÍÏgèÍÍgÀÎÍgÁÎÏgéÌÏgìÌÍgÝÌÏgàÌÍgÉÌÏgÌÌÍgÃÌÏgÆÌÍg¼ÌÍg½ÌÏg´ÌÍgµÌÏgÌÍgÌÏgÌÍgÌÏgèËÍgéËÏgÖËÍg×ËÏgÂËÍgÃËÏg¸ËÍg¹ËÏg´ËÍgµËÏgËÍgËÏgËÍgËÏgöÊÍg÷ÊÏgìÊÍgíÊÏgêÊÍgëÊÏg§µÊm¸Êm°Êm±Êm§ÊmªÊm²Êm³Êm¥Êm¨Êm÷ÊmúÊm¢Êm£ÊmÊm¢ÊmÜÊmÝÊmÊmÊmÊmÊmÊmÊmÊmÊm«Ëm®ËmñÉmôÉmçÉmêÉmÝËmàËmÓÊmÖÊm®Ëm¯Ëm×ÉmÚÉmËÉmÎÉm·ÉmºÉm±Ém´ÉmªÉm«Ém¢Ém£ÉmÉmÉmîÈmïÈmÖÈm×ÈmÄÈmÅÈm°Èm±Èm¦Èm§Èm¢Èm£ÈmÈmÈmðÇmñÇmäÇmåÇmÚÇmÛÇmØÇmÙÇm§£ÇÃr¦ÇÁrÇÁrÇÃrÇÃrÇÁr ÇÁr¡ÇÃrÇÃrÇÁråÇÃrèÇÁrÇÁrÇÃrÇÃrÇÁrÊÇÁrËÇÃrýÆÃrÇÁrúÆÁrûÆÃrøÆÁrùÆÃröÆÁr÷ÆÃrÈÃrÈÁrßÆÃrâÆÁrÕÆÃrØÆÁrËÈÃrÎÈÁrÁÇÃrÄÇÁrÈÁrÈÃrÅÆÃrÈÆÁr¹ÆÃr¼ÆÁr¥ÆÃr¨ÆÁrÆÃr¢ÆÁrÆÁrÆÃrÆÁrÆÃrðÅÁrñÅÃrÜÅÁrÝÅÃrÄÅÁrÅÅÃr²ÅÁr³ÅÃrÅÁrÅÃrÅÁrÅÃrÅÁrÅÃrôÄÁrõÄÃrÞÄÁrßÄÃrÒÄÁrÓÄÃrÈÄÁrÉÄÃrÆÄÁrÇÄÃr§ÄýwÄûwÄûwÄýwÄýwÄûwÄûwÄýwÄýwÄûwÓÄýwÖÄûwþÃûwÿÃýwûÃýwþÃûw¸Äûw¹ÄýwëÃýwîÃûwèÃûwéÃýwæÃûwçÃýwäÃûwåÃýwÅýwÅûwÍÃýwÐÃûwÃÃýwÆÃûw¹Åýw¼Åûw¯Äýw²ÄûwÅûwÅýw³Ãýw¶Ãûw§ÃýwªÃûwÃýwÃûwÃýwÃûwÃûwÃýwþÂûwÿÂýwÞÂûwßÂýwÊÂûwËÂýw²Âûw³Âýw Âûw¡ÂýwÂûwÂýwÂûwÂýwþÁûwÿÁýwâÁûwãÁýwÌÁûwÍÁýwÀÁûwÁÁýw¶Áûw·Áýw´ÁûwµÁýw§ÿÀ·}Áµ}úÀµ}ûÀ·}ñÀ·}ôÀµ}üÀµ}ýÀ·}ïÀ·}òÀµ}ÁÁ·}ÄÁµ}ìÀµ}íÀ·}éÀ·}ìÀµ}¦Áµ}§Á·}ÙÀ·}ÜÀµ}ÖÀµ}×À·}ÔÀµ}ÕÀ·}ÒÀµ}ÓÀ·}õÁ·}øÁµ}»À·}¾Àµ}±À·}´Àµ}§Â·}ªÂµ}Á·} Áµ}øÁµ}ùÁ·}¡À·}¤Àµ}À·}Àµ}À·}Àµ}û¿·}þ¿µ}ô¿µ}õ¿·}ì¿µ}í¿·}Ì¿µ}Í¿·}¸¿µ}¹¿·} ¿µ}¡¿·}¿µ}¿·}ú¾µ}û¾·}ð¾µ}ñ¾·}ì¾µ}í¾·}Ð¾µ}Ñ¾·}º¾µ}»¾·}®¾µ}¯¾·}¤¾µ}¥¾·}¢¾µ}£¾·}§í½ñð½ïè½ïé½ñß½ñâ½ïê½ïë½ñÝ½ñà½ï¯¾ñ²¾ïÚ½ïÛ½ñ×½ñÚ½ï¾ï¾ñÇ½ñÊ½ïÄ½ïÅ½ñÂ½ïÃ½ñÀ½ïÁ½ñã¾ñæ¾ï©½ñ¬½ï½ñ¢½ï¿ñ¿ï¾ñ¾ïæ¾ïç¾ñ½ñ½ï½ñ½ïï¼ñò¼ïé¼ñì¼ïâ¼ïã¼ñÚ¼ïÛ¼ñº¼ï»¼ñ¦¼ï§¼ñ¼ï¼ñü»ïý»ñè»ïé»ñÞ»ïß»ñÚ»ïÛ»ñ¾»ï¿»ñ¨»ï©»ñ»ï»ñ»ï»ñ»ï»ñ§Ûº«Þº©Öº©×º«Íº«Ðº©Øº©Ùº«Ëº«Îº©»« »©Èº©Éº«Åº«Èº©»©»«µº«¸º©²º©³º«°º©±º«®º©¯º«Ñ»«Ô»©º«º©º«º©¼«¼©ùº«üº©Ô»©Õ»«ý¹«º©ñ¹«ô¹©Ý¹«à¹©×¹«Ú¹©Ð¹©Ñ¹«È¹©É¹«¨¹©©¹«¹©¹«ü¸©ý¸«ê¸©ë¸«Ö¸©×¸«Ì¸©Í¸«È¸©É¸«¬¸©­¸«¸©¸«¸©¸«¸©¸«þ·©ÿ·«§É·åÌ·ãÄ·ãÅ·å»·å¾·ãÆ·ãÇ·å¹·å¼·ã¸å¸ã¶·ã··å³·å¶·ãð·ãñ·å£·å¦·ã ·ã¡·å·ã·å·ã·å¿¸åÂ¸ã·å·ãû¶åþ¶ãñ¸åô¸ãç·åê·ãÂ¸ãÃ¸åë¶åî¶ãß¶åâ¶ãË¶åÎ¶ãÅ¶åÈ¶ã¾¶ã¿¶å¶¶ã·¶å¶ã¶å¶ã¶åêµãëµåØµãÙµåÄµãÅµåºµã»µå¶µã·µåµãµåµãµåø´ãù´åî´ãï´åì´ãí´å§·´º´²´³´©´¬´´´µ´§´ª´ù´ü´¤´¥´¡´¤´Þ´ß´´´´´´´´´­µ°µó³ö³é³ì³ßµâµÕ´Ø´°µ±µÙ³Ü³Í³Ð³¹³¼³³³¶³¬³­³¤³¥³³³ð²ñ²Ø²Ù²Æ²Ç²²²³²¨²©²¤²¥²²²ò±ó±æ±ç±Ü±Ý±Ú±Û±§¥±Ù¨±× ±×¡±Ù±Ù±×¢±×£±Ù±Ù±×ç±Ùê±×±×±Ù±Ù±×Ì±×Í±Ùÿ°Ù±×ü°×ý°Ùú°×û°Ùø°×ù°Ù²Ù²×á°Ùä°××°ÙÚ°×Í²ÙÐ²×Ã±ÙÆ±×²×²ÙÇ°ÙÊ°×»°Ù¾°×§°Ùª°×¡°Ù¤°×°×°Ù°×°Ùò¯×ó¯ÙÞ¯×ß¯ÙÆ¯×Ç¯Ù´¯×µ¯Ù ¯×¡¯Ù¯×¯Ù¯×¯Ùö®×÷®Ùà®×á®ÙÔ®×Õ®ÙÊ®×Ë®ÙÈ®×É®Ù§®®®®®®®®®®Õ®Ø®®®ý­®º®»®í­ð­ê­ë­è­é­æ­ç­¯¯Ï­Ò­Å­È­»¯¾¯±®´®¯¯µ­¸­©­¬­­­­­­­­­à¬á¬Ì¬Í¬´¬µ¬¢¬£¬¬¬¬¬¬¬ä«å«Î«Ï«Â«Ã«¸«¹«¶«·«§«Í£«Ë£üªË£ýªÍ£óªÍ£öªË£þªË£ÿªÍ£ñªÍ£ôªË£Ã«Í£Æ«Ë£îªË£ïªÍ£ëªÍ£îªË£¨«Ë£©«Í£ÛªÍ£ÞªË£ØªË£ÙªÍ£ÖªË£×ªÍ£ÔªË£ÕªÍ£÷«Í£ú«Ë£½ªÍ£ÀªË£³ªÍ£¶ªË£©¬Í£¬¬Ë£«Í£¢«Ë£ú«Ë£û«Í££ªÍ£¦ªË£ªÍ£ªË£ªÍ£ªË£ý©Í£ªË£ö©Ë£÷©Í£î©Ë£ï©Í£Î©Ë£Ï©Í£º©Ë£»©Í£¢©Ë££©Í£©Ë£©Í£ü¨Ë£ý¨Í£ò¨Ë£ó¨Í£î¨Ë£ï¨Í£Ò¨Ë£Ó¨Í£¼¨Ë£½¨Í£°¨Ë£±¨Í£¦¨Ë£§¨Í£¤¨Ë£¥¨Í£§ï§©ò§©ê§©ë§©á§©ä§©ì§©í§©ß§©â§©±¨©´¨©Ü§©Ý§©Ù§©Ü§©¨©¨©É§©Ì§©Æ§©Ç§©Ä§©Å§©Â§©Ã§©å¨©è¨©«§©®§©¡§©¤§©©©©©¨©¨©è¨©é¨©§©§©§©§©ñ¦©ô¦©ë¦©î¦©ä¦©å¦©Ü¦©Ý¦©¼¦©½¦©¨¦©©¦©¦©¦©þ¥©ÿ¥©ê¥©ë¥©à¥©á¥©Ü¥©Ý¥©À¥©Á¥©ª¥©«¥©¥©¥©¥©¥©¥©¥©§Ý¤Á®à¤¿®Ø¤¿®Ù¤Á®Ï¤Á®Ò¤¿®Ú¤¿®Û¤Á®Í¤Á®Ð¤¿®¥Á®¢¥¿®Ê¤¿®Ë¤Á®Ç¤Á®Ê¤¿®¥¿®¥Á®·¤Á®º¤¿®´¤¿®µ¤Á®²¤¿®³¤Á®°¤¿®±¤Á®Ó¥Á®Ö¥¿®¤Á®¤¿®¤Á®¤¿®¦Á®¦¿®û¤Á®þ¤¿®Ö¥¿®×¥Á®ÿ£Á®¤¿®ó£Á®ö£¿®ß£Á®â£¿®Ù£Á®Ü£¿®Ò£¿®Ó£Á®Ê£¿®Ë£Á®ª£¿®«£Á®£¿®£Á®þ¢¿®ÿ¢Á®ì¢¿®í¢Á®Ø¢¿®Ù¢Á®Î¢¿®Ï¢Á®Ê¢¿®Ë¢Á®®¢¿®¯¢Á®¢¿®¢Á®¢¿®¢Á®¢¿®¢Á®¢¿®¢Á®§Ë¡û³Î¡ù³Æ¡ù³Ç¡û³½¡û³À¡ù³È¡ù³É¡û³»¡û³¾¡ù³¢û³¢ù³¸¡ù³¹¡û³µ¡û³¸¡ù³ò¡ù³ó¡û³¥¡û³¨¡ù³¢¡ù³£¡û³ ¡ù³¡¡û³¡ù³¡û³Á¢û³Ä¢ù³¡û³¡ù³ý û³¡ù³ó¢û³ö¢ù³é¡û³ì¡ù³Ä¢ù³Å¢û³í û³ð ù³á û³ä ù³Í û³Ð ù³Ç û³Ê ù³À ù³Á û³¸ ù³¹ û³ ù³ û³ ù³ û³ìù³íû³Úù³Ûû³Æù³Çû³¼ù³½û³¸ù³¹û³ù³û³ù³û³úù³ûû³ðù³ñû³îù³ïû³§¹µ¹¼³¹´³¹µµ¹«µ¹®³¹¶³¹·µ¹©µ¹¬³¹ûµ¹þ³¹¦³¹§µ¹£µ¹¦³¹à³¹áµ¹µ¹³¹³¹µ¹³¹µ¹³¹µ¹¯µ¹²³¹õµ¹ø³¹ëµ¹î³¹áµ¹ä³¹×µ¹Ú³¹²³¹³µ¹Ûµ¹Þ³¹Ïµ¹Ò³¹»µ¹¾³¹µµ¹¸³¹®³¹¯µ¹¦³¹§µ¹³¹µ¹ò³¹óµ¹Ú³¹Ûµ¹È³¹Éµ¹´³¹µµ¹ª³¹«µ¹¦³¹§µ¹³¹µ¹ô³¹õµ¹è³¹éµ¹Þ³¹ßµ¹Ü³¹Ýµ¹§§ï¾ªí¾¢í¾£ï¾ï¾í¾¤í¾¥ï¾ï¾í¾éï¾ìí¾í¾ï¾ï¾í¾Îí¾Ïï¾ï¾í¾þí¾ÿï¾üí¾ýï¾úí¾ûï¾ï¾ í¾ãï¾æí¾Ùï¾Üí¾Ïï¾Òí¾Åï¾Èí¾ í¾¡ï¾Éï¾Ìí¾½ï¾Àí¾©ï¾¬í¾£ï¾¦í¾í¾ï¾í¾ï¾ôí¾õï¾àí¾áï¾Èí¾Éï¾¶í¾·ï¾¢í¾£ï¾í¾ï¾í¾ï¾øí¾ùï¾âí¾ãï¾Öí¾×ï¾Ìí¾Íï¾Êí¾Ëï¾§©Ä§Ä§Ä©Ä©Ä§Ä§Ä©Ä©Ä§Ä×©ÄÚ§Ä§Ä©Äÿ©Ä§Ä¼§Ä½©Äï©Äò§Äì§Äí©Äê§Äë©Äè§Äé©Ä©Ä§ÄÑ©ÄÔ§ÄÇ©ÄÊ§Ä½©ÄÀ§Ä³©Ä¶§Ä§Ä©Ä·©Äº§Ä«©Ä®§Ä©Ä§Ä©Ä§Ä§Ä©Ä§Ä©Äâ§Äã©ÄÎ§ÄÏ©Ä¶§Ä·©Ä¤§Ä¥©Ä§Ä©Ä§Ä©Ä§Ä©Äæ§Äç©ÄÐ§ÄÑ©ÄÄ§ÄÅ©Äº§Ä»©Ä¸§Ä¹©Ä§ãÉáÉþáÉÿãÉõãÉøáÉáÉãÉóãÉöáÉÅãÉÈáÉðáÉñãÉíãÉðáÉªáÉ«ãÉÝãÉàáÉÚáÉÛãÉØáÉÙãÉÖáÉ×ãÉùãÉüáÉ¿ãÉÂáÉµãÉ¸áÉ«ãÉ®áÉ¡ãÉ¤áÉüáÉýãÉ¥ãÉ¨áÉãÉáÉãÉáÉÿãÉáÉøáÉùãÉðáÉñãÉÐáÉÑãÉ¼áÉ½ãÉ¤áÉ¥ãÉáÉãÉþáÉÿãÉôáÉõãÉðáÉñãÉÔáÉÕãÉ¾áÉ¿ãÉ²áÉ³ãÉ¨áÉ©ãÉ¦áÉ§ãÉ§ñÏôÏìÏíÏãÏæÏîÏïÏáÏäÏ³Ï¶ÏÞÏßÏÛÏÞÏÏÏËÏÎÏÈÏÉÏÆÏÇÏÄÏÅÏçÏêÏ­Ï°Ï£Ï¦ÏÏÏÏÏêÏëÏÏÏÏÏóÏöÏíÏðÏæÏçÏÞÏßÏ¾Ï¿ÏªÏ«ÏÏÏÏÏìÏíÏâÏãÏÞÏßÏÂÏÃÏ¬Ï­Ï Ï¡ÏÏÏÏÏ§ß×ÔâÕÔÚÕÔÛ×ÔÑ×ÔÔÕÔÜÕÔÝ×ÔÏ×ÔÒÕÔ¡×Ô¤ÕÔÌÕÔÍ×ÔÉ×ÔÌÕÔÕÔ×Ô¹×Ô¼ÕÔ¶ÕÔ·×Ô´ÕÔµ×Ô²ÕÔ³×ÔÕ×ÔØÕÔ×ÔÕÔ×ÔÕÔ×ÔÕÔý×ÔÕÔØÕÔÙ×Ô×ÔÕÔõ×ÔøÕÔá×ÔäÕÔÛ×ÔÞÕÔÔÕÔÕ×ÔÌÕÔÍ×Ô¬ÕÔ­×ÔÕÔ×ÔÕÔ×ÔîÕÔï×ÔÚÕÔÛ×ÔÐÕÔÑ×ÔÌÕÔÍ×Ô°ÕÔ±×ÔÕÔ×ÔÕÔ×ÔÕÔ×ÔÕÔ×Ô§ÍÚÐÚÈÚÉÚ¿ÚÂÚÊÚËÚ½ÚÀÚÚÚºÚ»Ú·ÚºÚôÚõÚ§ÚªÚ¤Ú¥Ú¢Ú£Ú Ú¡ÚÃÚÆÚÚÚÿÚÚõÚøÚëÚîÚÆÚÇÚïÚòÚãÚæÚÏÚÒÚÉÚÌÚÂÚÃÚºÚ»ÚÚÚÚÚîÚïÚÜÚÝÚÈÚÉÚ¾Ú¿ÚºÚ»ÚÚÚÚÚüÚýÚòÚóÚðÚñÚ§»Ëß¾Éß¶Éß·Ëß­Ëß°Éß¸Éß¹Ëß«Ëß®ÉßýËßÉß¨Éß©Ëß¥Ëß¨ÉßâÉßãËßËßÉßÉßËßÉßËßÉßËß±Ëß´Éß÷ËßúÉßíËßðÉßãËßæÉßÙËßÜÉß´ÉßµËßÝËßàÉßÑËßÔÉß½ËßÀÉß·ËßºÉß°Éß±Ëß¨Éß©ËßÉßËßôÉßõËßÜÉßÝËßÊÉßËËß¶Éß·Ëß¬Éß­Ëß¨Éß©ËßÉßËßöÉß÷ËßêÉßëËßàÉßáËßÞÉßßËß§©å¬å¤å¥ååå¦å§åååëåîåååååÐåÑåååååþåÿåüåýåå¢åååèåÛåÞåÑåÔåÇåÊå¢å£åËåÎå¿åÂå«å®å¥å¨åååååöå÷åâåãåÊåËå¸å¹å¤å¥åååååúåûåäåååØåÙåÎåÏåÌåÍå§¿ê½ê½ê¿ê¿ê½ê½ê¿ê¿ê½êÙ¿êÜ½ê½ê¿ê¿ê½ê¾½ê¿¿êñ¿êô½êî½êï¿êì½êí¿êê½êë¿ê¿ê½êÓ¿êÖ½êÉ¿êÌ½ê¿¿êÂ½êµ¿ê¸½ê½ê¿ê¹¿ê¼½ê­¿ê°½ê¿ê½ê¿ê½ê½ê¿ê½ê¿êä½êå¿êÐ½êÑ¿ê¸½ê¹¿ê¦½ê§¿ê½ê¿ê½ê¿ê½ê¿êèÿ½êéÿ¿êÒÿ½êÓÿ¿êÆÿ½êÇÿ¿ê¼ÿ½ê½ÿ¿êºÿ½ê»ÿ¿ê§ÿùïÿ÷ïÿ÷ïÿùï÷þùïúþ÷ïÿ÷ïÿùïõþùïøþ÷ïÇÿùïÊÿ÷ïòþ÷ïóþùïïþùïòþ÷ï¬ÿ÷ï­ÿùïßþùïâþ÷ïÜþ÷ïÝþùïÚþ÷ïÛþùïØþ÷ïÙþùïûÿùïþÿ÷ïÁþùïÄþ÷ï·þùïºþ÷ï­ùï°÷ï£ÿùï¦ÿ÷ïþÿ÷ïÿÿùï§þùïªþ÷ïþùïþ÷ïþùïþ÷ïþùïþ÷ïúý÷ïûýùïòý÷ïóýùïÒý÷ïÓýùï¾ý÷ï¿ýùï¦ý÷ï§ýùïý÷ïýùïý÷ïýùïöü÷ï÷üùïòü÷ïóüùïÖü÷ï×üùïÀü÷ïÁüùï´ü÷ïµüùïªü÷ï«üùï¨ü÷ï©üùï§óû³õöû±õîû±õïû³õåû³õèû±õðû±õñû³õãû³õæû±õµü³õ¸ü±õàû±õáû³õÝû³õàû±õü±õü³õÍû³õÐû±õÊû±õËû³õÈû±õÉû³õÆû±õÇû³õéü³õìü±õ¯û³õ²û±õ¥û³õ¨û±õý³õý±õü³õü±õìü±õíü³õû³õû±õû³õû±õõú³õøú±õïú³õòú±õèú±õéú³õàú±õáú³õÀú±õÁú³õ¬ú±õ­ú³õú±õú³õú±õú³õîù±õïù³õäù±õåù³õàù±õáù³õÄù±õÅù³õ®ù±õ¯ù³õ¢ù±õ£ù³õù±õù³õù±õù³õ§áøíúäøëúÜøëúÝøíúÓøíúÖøëúÞøëúßøíúÑøíúÔøëú£ùíú¦ùëúÎøëúÏøíúËøíúÎøëúùëúùíú»øíú¾øëú¸øëú¹øíú¶øëú·øíú´øëúµøíú×ùíúÚùëúøíú øëúøíúøëúúíúúëúÿøíúùëúÚùëúÛùíúøíúøëú÷÷íúú÷ëúã÷íúæ÷ëúÝ÷íúà÷ëúÖ÷ëú×÷íúÎ÷ëúÏ÷íú®÷ëú¯÷íú÷ëú÷íú÷ëú÷íúðöëúñöíúÜöëúÝöíúÒöëúÓöíúÎöëúÏöíú²öëú³öíúöëúöíúöëúöíúöëúöíúöëúöíú§Ïõ§Òõ¥Êõ¥Ëõ§Áõ§Äõ¥Ìõ¥Íõ§¿õ§Âõ¥ö§ö¥¼õ¥½õ§¹õ§¼õ¥öõ¥÷õ§©õ§¬õ¥¦õ¥§õ§¤õ¥¥õ§¢õ¥£õ§Åö§Èö¥õ§õ¥õ§õ¥÷ö§úö¥íõ§ðõ¥Èö¥Éö§ñô§ôô¥åô§èô¥Ñô§Ôô¥Ëô§Îô¥Äô¥Åô§¼ô¥½ô§ô¥ô§ô¥ô§ðó¥ñó§Þó¥ßó§Êó¥Ëó§Àó¥Áó§¼ó¥½ó§ ó¥¡ó§ó¥ó§þò¥ÿò§ôò¥õò§òò¥óò§§½òáÀòß¸òß¹òá¯òá²òßºòß»òá­òá°òßÿòáóßªòß«òá§òáªòßäòßåòáòáòßòßòáòßòáòßòá³óá¶óßùñáüñßïñáòñßåóáèóßÛòáÞòß¶óß·óáßñáâñßÓñáÖñß¿ñáÂñß¹ñá¼ñß²ñß³ñáªñß«ñáñßñáöðß÷ðáÞðßßðáÌðßÍðá¸ðß¹ðá®ðß¯ðáªðß«ðáðßðáøïßùïáìïßíïáâïßãïáàïßáïá§«ï®ï¦ï§ïï ï¨ï©ïïïíïðïïïïïÒïÓïïïïïïïþîÿî¡ð¤ðçîêîÝîàîÓðÖðÉïÌï¤ð¥ðÍîÐîÁîÄî­î°î§îªî î¡îîîøíùíäíåíÌíÍíºí»í¦í§íííííüìýìæìçìÚìÛìÐìÑìÎìÏì§ìÕìÓìÓìÕìÕìÓìÓìÕìÕìÓÛìÕÞìÓìÓìÕìÕìÓÀìÓÁìÕóëÕöëÓðëÓñëÕîëÓïëÕìëÓíëÕíÕíÓÕëÕØëÓËëÕÎëÓÁíÕÄíÓ·ìÕºìÓíÓíÕ»ëÕ¾ëÓ¯ëÕ²ëÓëÕëÓëÕëÓëÓëÕëÓëÕæêÓçêÕÒêÓÓêÕºêÓ»êÕ¨êÓ©êÕêÓêÕêÓêÕêÓêÕêéÓëéÕÔéÓÕéÕÈéÓÉéÕ¾éÓ¿éÕ¼éÓ½éÕ§ééééùèüèéé÷èúèÉéÌéôèõèñèôè®é¯éáèäèÞèßèÜèÝèÚèÛèýéêÃèÆè¹è¼è¯ê²ê¥é¨éêê©è¬èè èèèèèüçýçôçõçÔçÕçÀçÁç¨ç©çççççøæùæôæõæØæÙæÂæÃæ¶æ·æ¬æ­æªæ«æ§Éö»Ìö¹Äö¹Åö»»ö»¾ö¹Æö¹Çö»¹ö»¼ö¹÷»÷¹¶ö¹·ö»³ö»¶ö¹ðö¹ñö»£ö»¦ö¹ ö¹¡ö»ö¹ö»ö¹ö»¿÷»Â÷¹ö»ö¹ûõ»þõ¹ñ÷»ô÷¹çö»êö¹Â÷¹Ã÷»ëõ»îõ¹ßõ»âõ¹Ëõ»Îõ¹Åõ»Èõ¹¾õ¹¿õ»¶õ¹·õ»õ¹õ»õ¹õ»êô¹ëô»Øô¹Ùô»Äô¹Åô»ºô¹»ô»¶ô¹·ô»ô¹ô»ô¹ô»øó¹ùó»îó¹ïó»ìó¹íó»§·óõ
+ºóó
+²óó
+³óõ
+©óõ
+¬óó
+´óó
+µóõ
+§óõ
+ªóó
+ùóõ
+üóó
+¤óó
+¥óõ
+¡óõ
+¤óó
+Þóó
+ßóõ
+óõ
+óó
+óó
+óõ
+óó
+óõ
+óó
+óõ
+­ôõ
+°ôó
+óòõ
+öòó
+éòõ
+ìòó
+ßôõ
+âôó
+Õóõ
+Øóó
+°ôó
+±ôõ
+Ùòõ
+Üòó
+Íòõ
+Ðòó
+¹òõ
+¼òó
+³òõ
+¶òó
+¬òó
+­òõ
+¤òó
+¥òõ
+òó
+òõ
+ðñó
+ññõ
+Øñó
+Ùñõ
+Æñó
+Çñõ
+²ñó
+³ñõ
+¨ñó
+©ñõ
+¤ñó
+¥ñõ
+ñó
+ñõ
+òðó
+óðõ
+æðó
+çðõ
+Üðó
+Ýðõ
+Úðó
+Ûðõ
+§¥ð¯¨ð­ ð­¡ð¯ð¯ð­¢ð­£ð¯ð¯ð­çð¯êð­ð­ð¯ð¯ð­Ìð­Íð¯ÿï¯ð­üï­ýï¯úï­ûï¯øï­ùï¯ñ¯ñ­áï¯äï­×ï¯Úï­Íñ¯Ðñ­Ãð¯Æð­ñ­ñ¯Çï¯Êï­»ï¯¾ï­§ï¯ªï­¡ï¯¤ï­ï­ï¯ï­ï¯òî­óî¯Þî­ßî¯Æî­Çî¯´î­µî¯ î­¡î¯î­î¯î­î¯öí­÷í¯àí­áí¯Ôí­Õí¯Êí­Ëí¯Èí­Éí¯§íéíçíçíéíéíçíçíéíéíçÕíéØíçíçíéýìéíçºíç»íéíìéðìçêìçëìéèìçéìéæìççìéîéîçÏìéÒìçÅìéÈìç»îé¾îç±íé´íçîçîéµìé¸ìç©ìé¬ìçìéìçìéìçìçìéìçìéàëçáëéÌëçÍëé´ëçµëé¢ëç£ëéëçëéëçëéëçëéäêçåêéÎêçÏêéÂêçÃêé¸êç¹êé¶êç·êé§ê£ê¡üé¡ýé£óé£öé¡þé¡ÿé£ñé£ôé¡Ãê£Æê¡îé¡ïé£ëé£îé¡¨ê¡©ê£Ûé£Þé¡Øé¡Ùé£Öé¡×é£Ôé¡Õé£÷ê£úê¡½é£Àé¡³é£¶é¡©ë£¬ë¡ê£¢ê¡úê¡ûê££é£¦é¡é£é¡é£é¡ýè£é¡öè¡÷è£îè¡ïè£Îè¡Ïè£ºè¡»è£¢è¡£è£è¡è£üç¡ýç£òç¡óç£îç¡ïç£Òç¡Óç£¼ç¡½ç£°ç¡±ç£¦ç¡§ç£¤ç¡¥ç£§ïæÝ òæÛ êæÛ ëæÝ áæÝ äæÛ ìæÛ íæÝ ßæÝ âæÛ ±çÝ ´çÛ ÜæÛ ÝæÝ ÙæÝ ÜæÛ çÛ çÝ ÉæÝ ÌæÛ ÆæÛ ÇæÝ ÄæÛ ÅæÝ ÂæÛ ÃæÝ åçÝ èçÛ «æÝ ®æÛ ¡æÝ ¤æÛ èÝ èÛ çÝ çÛ èçÛ éçÝ æÝ æÛ æÝ æÛ ñåÝ ôåÛ ëåÝ îåÛ äåÛ ååÝ ÜåÛ ÝåÝ ¼åÛ ½åÝ ¨åÛ ©åÝ åÛ åÝ þäÛ ÿäÝ êäÛ ëäÝ àäÛ áäÝ ÜäÛ ÝäÝ ÀäÛ ÁäÝ ªäÛ «äÝ äÛ äÝ äÛ äÝ äÛ äÝ §Ýã&àã&Øã&Ùã&Ïã&Òã&Úã&Ûã&Íã&Ðã&ä&¢ä&Êã&Ëã&Çã&Êã&ä&ä&·ã&ºã&´ã&µã&²ã&³ã&°ã&±ã&Óä&Öä&ã&ã&ã&ã&å&å&ûã&þã&Öä&×ä&ÿâ&ã&óâ&öâ&ßâ&ââ&Ùâ&Üâ&Òâ&Óâ&Êâ&Ëâ&ªâ&«â&â&â&þá&ÿá&ìá&íá&Øá&Ùá&Îá&Ïá&Êá&Ëá&®á&¯á&á&á&á&á&á&á&á&á&§ËàÑ+ÎàÏ+ÆàÏ+ÇàÑ+½àÑ+ÀàÏ+ÈàÏ+ÉàÑ+»àÑ+¾àÏ+áÑ+áÏ+¸àÏ+¹àÑ+µàÑ+¸àÏ+òàÏ+óàÑ+¥àÑ+¨àÏ+¢àÏ+£àÑ+ àÏ+¡àÑ+àÏ+àÑ+ÁáÑ+ÄáÏ+àÑ+àÏ+ýßÑ+àÏ+óáÑ+öáÏ+éàÑ+ìàÏ+ÄáÏ+ÅáÑ+íßÑ+ðßÏ+áßÑ+äßÏ+ÍßÑ+ÐßÏ+ÇßÑ+ÊßÏ+ÀßÏ+ÁßÑ+¸ßÏ+¹ßÑ+ßÏ+ßÑ+ßÏ+ßÑ+ìÞÏ+íÞÑ+ÚÞÏ+ÛÞÑ+ÆÞÏ+ÇÞÑ+¼ÞÏ+½ÞÑ+¸ÞÏ+¹ÞÑ+ÞÏ+ÞÑ+ÞÏ+ÞÑ+úÝÏ+ûÝÑ+ðÝÏ+ñÝÑ+îÝÏ+ïÝÑ+§¹Ý1¼Ý1´Ý1µÝ1«Ý1®Ý1¶Ý1·Ý1©Ý1¬Ý1ûÝ1þÝ1¦Ý1§Ý1£Ý1¦Ý1àÝ1áÝ1Ý1Ý1Ý1Ý1Ý1Ý1Ý1Ý1¯Þ1²Þ1õÜ1øÜ1ëÜ1îÜ1áÞ1äÞ1×Ý1ÚÝ1²Þ1³Þ1ÛÜ1ÞÜ1ÏÜ1ÒÜ1»Ü1¾Ü1µÜ1¸Ü1®Ü1¯Ü1¦Ü1§Ü1Ü1Ü1òÛ1óÛ1ÚÛ1ÛÛ1ÈÛ1ÉÛ1´Û1µÛ1ªÛ1«Û1¦Û1§Û1Û1Û1ôÚ1õÚ1èÚ1éÚ1ÞÚ1ßÚ1ÜÚ1ÝÚ1§§ÚÅ6ªÚÃ6¢ÚÃ6£ÚÅ6ÚÅ6ÚÃ6¤ÚÃ6¥ÚÅ6ÚÅ6ÚÃ6éÚÅ6ìÚÃ6ÚÃ6ÚÅ6ÚÅ6ÚÃ6ÎÚÃ6ÏÚÅ6ÚÅ6ÚÃ6þÙÃ6ÿÙÅ6üÙÃ6ýÙÅ6úÙÃ6ûÙÅ6ÛÅ6 ÛÃ6ãÙÅ6æÙÃ6ÙÙÅ6ÜÙÃ6ÏÛÅ6ÒÛÃ6ÅÚÅ6ÈÚÃ6 ÛÃ6¡ÛÅ6ÉÙÅ6ÌÙÃ6½ÙÅ6ÀÙÃ6©ÙÅ6¬ÙÃ6£ÙÅ6¦ÙÃ6ÙÃ6ÙÅ6ÙÃ6ÙÅ6ôØÃ6õØÅ6àØÃ6áØÅ6ÈØÃ6ÉØÅ6¶ØÃ6·ØÅ6¢ØÃ6£ØÅ6ØÃ6ØÅ6ØÃ6ØÅ6ø×Ã6ù×Å6â×Ã6ã×Å6Ö×Ã6××Å6Ì×Ã6Í×Å6Ê×Ã6Ë×Å6§×ÿ;×ý;×ý;×ÿ;×ÿ;×ý;×ý;×ÿ;×ÿ;×ý;××ÿ;Ú×ý;×ý;×ÿ;ÿÖÿ;×ý;¼×ý;½×ÿ;ïÖÿ;òÖý;ìÖý;íÖÿ;êÖý;ëÖÿ;èÖý;éÖÿ;Øÿ;Øý;ÑÖÿ;ÔÖý;ÇÖÿ;ÊÖý;½Øÿ;ÀØý;³×ÿ;¶×ý;Øý;Øÿ;·Öÿ;ºÖý;«Öÿ;®Öý;Öÿ;Öý;Öÿ;Öý;Öý;Öÿ;Öý;Öÿ;âÕý;ãÕÿ;ÎÕý;ÏÕÿ;¶Õý;·Õÿ;¤Õý;¥Õÿ;Õý;Õÿ;Õý;Õÿ;Õý;Õÿ;æÔý;çÔÿ;ÐÔý;ÑÔÿ;ÄÔý;ÅÔÿ;ºÔý;»Ôÿ;¸Ôý;¹Ôÿ;§Ô¹AÔ·AþÓ·AÿÓ¹AõÓ¹AøÓ·AÔ·AÔ¹AóÓ¹AöÓ·AÅÔ¹AÈÔ·AðÓ·AñÓ¹AíÓ¹AðÓ·AªÔ·A«Ô¹AÝÓ¹AàÓ·AÚÓ·AÛÓ¹AØÓ·AÙÓ¹AÖÓ·A×Ó¹AùÔ¹AüÔ·A¿Ó¹AÂÓ·AµÓ¹A¸Ó·A«Õ¹A®Õ·A¡Ô¹A¤Ô·AüÔ·AýÔ¹A¥Ó¹A¨Ó·AÓ¹AÓ·AÓ¹AÓ·AÿÒ¹AÓ·AøÒ·AùÒ¹AðÒ·AñÒ¹AÐÒ·AÑÒ¹A¼Ò·A½Ò¹A¤Ò·A¥Ò¹AÒ·AÒ¹AþÑ·AÿÑ¹AôÑ·AõÑ¹AðÑ·AñÑ¹AÔÑ·AÕÑ¹A¾Ñ·A¿Ñ¹A²Ñ·A³Ñ¹A¨Ñ·A©Ñ¹A¦Ñ·A§Ñ¹A§ñÐóFôÐñFìÐñFíÐóFãÐóFæÐñFîÐñFïÐóFáÐóFäÐñF³ÑóF¶ÑñFÞÐñFßÐóFÛÐóFÞÐñFÑñFÑóFËÐóFÎÐñFÈÐñFÉÐóFÆÐñFÇÐóFÄÐñFÅÐóFçÑóFêÑñF­ÐóF°ÐñF£ÐóF¦ÐñFÒóFÒñFÑóFÑñFêÑñFëÑóFÐóFÐñFÐóFÐñFóÏóFöÏñFíÏóFðÏñFæÏñFçÏóFÞÏñFßÏóF¾ÏñF¿ÏóFªÏñF«ÏóFÏñFÏóFÏñFÏóFìÎñFíÎóFâÎñFãÎóFÞÎñFßÎóFÂÎñFÃÎóF¬ÎñF­ÎóF ÎñF¡ÎóFÎñFÎóFÎñFÎóF§ßÍ­LâÍ«LÚÍ«LÛÍ­LÑÍ­LÔÍ«LÜÍ«LÝÍ­LÏÍ­LÒÍ«L¡Î­L¤Î«LÌÍ«LÍÍ­LÉÍ­LÌÍ«LÎ«LÎ­L¹Í­L¼Í«L¶Í«L·Í­L´Í«LµÍ­L²Í«L³Í­LÕÎ­LØÎ«LÍ­LÍ«LÍ­LÍ«LÏ­LÏ«LýÍ­LÎ«LØÎ«LÙÎ­LÍ­LÍ«LõÌ­LøÌ«LáÌ­LäÌ«LÛÌ­LÞÌ«LÔÌ«LÕÌ­LÌÌ«LÍÌ­L¬Ì«L­Ì­LÌ«LÌ­LÌ«LÌ­LîË«LïË­LÚË«LÛË­LÐË«LÑË­LÌË«LÍË­L°Ë«L±Ë­LË«LË­LË«LË­LË«LË­LË«LË­L§ÍÊçQÐÊåQÈÊåQÉÊçQ¿ÊçQÂÊåQÊÊåQËÊçQ½ÊçQÀÊåQËçQËåQºÊåQ»ÊçQ·ÊçQºÊåQôÊåQõÊçQ§ÊçQªÊåQ¤ÊåQ¥ÊçQ¢ÊåQ£ÊçQ ÊåQ¡ÊçQÃËçQÆËåQÊçQÊåQÿÉçQÊåQõËçQøËåQëÊçQîÊåQÆËåQÇËçQïÉçQòÉåQãÉçQæÉåQÏÉçQÒÉåQÉÉçQÌÉåQÂÉåQÃÉçQºÉåQ»ÉçQÉåQÉçQÉåQÉçQîÈåQïÈçQÜÈåQÝÈçQÈÈåQÉÈçQ¾ÈåQ¿ÈçQºÈåQ»ÈçQÈåQÈçQÈåQÈçQüÇåQýÇçQòÇåQóÇçQðÇåQñÇçQ§»Ç¡W¾ÇW¶ÇW·Ç¡W­Ç¡W°ÇW¸ÇW¹Ç¡W«Ç¡W®ÇWýÇ¡WÈW¨ÇW©Ç¡W¥Ç¡W¨ÇWâÇWãÇ¡WÇ¡WÇWÇWÇ¡WÇWÇ¡WÇWÇ¡W±È¡W´ÈW÷Æ¡WúÆWíÆ¡WðÆWãÈ¡WæÈWÙÇ¡WÜÇW´ÈWµÈ¡WÝÆ¡WàÆWÑÆ¡WÔÆW½Æ¡WÀÆW·Æ¡WºÆW°ÆW±Æ¡W¨ÆW©Æ¡WÆWÆ¡WôÅWõÅ¡WÜÅWÝÅ¡WÊÅWËÅ¡W¶ÅW·Å¡W¬ÅW­Å¡W¨ÅW©Å¡WÅWÅ¡WöÄW÷Ä¡WêÄWëÄ¡WàÄWáÄ¡WÞÄWßÄ¡W§©ÄÛ\¬ÄÙ\¤ÄÙ\¥ÄÛ\ÄÛ\ÄÙ\¦ÄÙ\§ÄÛ\ÄÛ\ÄÙ\ëÄÛ\îÄÙ\ÄÙ\ÄÛ\ÄÛ\ÄÙ\ÐÄÙ\ÑÄÛ\ÄÛ\ÄÙ\ÄÙ\ÄÛ\þÃÙ\ÿÃÛ\üÃÙ\ýÃÛ\ÅÛ\¢ÅÙ\åÃÛ\èÃÙ\ÛÃÛ\ÞÃÙ\ÑÅÛ\ÔÅÙ\ÇÄÛ\ÊÄÙ\¢ÅÙ\£ÅÛ\ËÃÛ\ÎÃÙ\¿ÃÛ\ÂÃÙ\«ÃÛ\®ÃÙ\¥ÃÛ\¨ÃÙ\ÃÙ\ÃÛ\ÃÙ\ÃÛ\öÂÙ\÷ÂÛ\âÂÙ\ãÂÛ\ÊÂÙ\ËÂÛ\¸ÂÙ\¹ÂÛ\¤ÂÙ\¥ÂÛ\ÂÙ\ÂÛ\ÂÙ\ÂÛ\úÁÙ\ûÁÛ\äÁÙ\åÁÛ\ØÁÙ\ÙÁÛ\ÎÁÙ\ÏÁÛ\ÌÁÙ\ÍÁÛ\§ÁbÁbÁbÁbÁbÁbÁbÁbÁbÁbÙÁbÜÁbÁbÁbÁbÁb¾Áb¿ÁbñÀbôÀbîÀbïÀbìÀbíÀbêÀbëÀbÂbÂbÓÀbÖÀbÉÀbÌÀb¿ÂbÂÂbµÁb¸ÁbÂbÂb¹Àb¼Àb­Àb°ÀbÀbÀbÀbÀbÀbÀbÀbÀbä¿bå¿bÐ¿bÑ¿b¸¿b¹¿b¦¿b§¿b¿b¿b¿b¿b¿b¿bè¾bé¾bÒ¾bÓ¾bÆ¾bÇ¾b¼¾b½¾bº¾b»¾b§¾Ïg¾Íg¾Íg¾Ïg÷½Ïgú½Íg¾Íg¾Ïgõ½Ïgø½ÍgÇ¾ÏgÊ¾Ígò½Ígó½Ïgï½Ïgò½Íg¬¾Íg­¾Ïgß½Ïgâ½ÍgÜ½ÍgÝ½ÏgÚ½ÍgÛ½ÏgØ½ÍgÙ½Ïgû¾Ïgþ¾ÍgÁ½ÏgÄ½Íg·½Ïgº½Íg­¿Ïg°¿Íg£¾Ïg¦¾Ígþ¾Ígÿ¾Ïg§½Ïgª½Íg½Ïg½Íg½Ïg½Íg½Ïg½Ígú¼Ígû¼Ïgò¼Ígó¼ÏgÒ¼ÍgÓ¼Ïg¾¼Íg¿¼Ïg¦¼Íg§¼Ïg¼Íg¼Ïg¼Íg¼Ïgö»Íg÷»Ïgò»Ígó»ÏgÖ»Íg×»ÏgÀ»ÍgÁ»Ïg´»Ígµ»Ïgª»Íg«»Ïg¨»Íg©»Ïg§óºmöºmîºmïºmåºmèºmðºmñºmãºmæºmµ»m¸»màºmáºmÝºmàºm»m»mÍºmÐºmÊºmËºmÈºmÉºmÆºmÇºmé»mì»m¯ºm²ºm¥ºm¨ºm¼m¼m»m»mì»mí»mºmºmºmºmõ¹mø¹mï¹mò¹mè¹mé¹mà¹má¹mÀ¹mÁ¹m¬¹m­¹m¹m¹m¹m¹mî¸mï¸mä¸må¸mà¸má¸mÄ¸mÅ¸m®¸m¯¸m¢¸m£¸m¸m¸m¸m¸m§á·Ãrä·ÁrÜ·ÁrÝ·ÃrÓ·ÃrÖ·ÁrÞ·Árß·ÃrÑ·ÃrÔ·Ár£¸Ãr¦¸ÁrÎ·ÁrÏ·ÃrË·ÃrÎ·Ár¸Ár¸Ãr»·Ãr¾·Ár¸·Ár¹·Ãr¶·Ár··Ãr´·Árµ·Ãr×¸ÃrÚ¸Ár·Ãr ·Ár·Ãr·Ár¹Ãr¹Árÿ·Ãr¸ÁrÚ¸ÁrÛ¸Ãr·Ãr·Ár÷¶Ãrú¶Árã¶Ãræ¶ÁrÝ¶Ãrà¶ÁrÖ¶Ár×¶ÃrÎ¶ÁrÏ¶Ãr®¶Ár¯¶Ãr¶Ár¶Ãr¶Ár¶ÃrðµÁrñµÃrÜµÁrÝµÃrÒµÁrÓµÃrÎµÁrÏµÃr²µÁr³µÃrµÁrµÃrµÁrµÃrµÁrµÃrµÁrµÃr§Ï´ýwÒ´ûwÊ´ûwË´ýwÁ´ýwÄ´ûwÌ´ûwÍ´ýw¿´ýwÂ´ûwµýwµûw¼´ûw½´ýw¹´ýw¼´ûwö´ûw÷´ýw©´ýw¬´ûw¦´ûw§´ýw¤´ûw¥´ýw¢´ûw£´ýwÅµýwÈµûw´ýw´ûw´ýw´ûw÷µýwúµûwí´ýwð´ûwÈµûwÉµýwñ³ýwô³ûwå³ýwè³ûwÑ³ýwÔ³ûwË³ýwÎ³ûwÄ³ûwÅ³ýw¼³ûw½³ýw³ûw³ýw³ûw³ýwð²ûwñ²ýwÞ²ûwß²ýwÊ²ûwË²ýwÀ²ûwÁ²ýw¼²ûw½²ýw ²ûw¡²ýw²ûw²ýwþ±ûwÿ±ýwô±ûwõ±ýwò±ûwó±ýw§½±·}À±µ}¸±µ}¹±·}¯±·}²±µ}º±µ}»±·}­±·}°±µ}ÿ±·}²µ}ª±µ}«±·}§±·}ª±µ}ä±µ}å±·}±·}±µ}±µ}±·}±µ}±·}±µ}±·}³²·}¶²µ}ù°·}ü°µ}ï°·}ò°µ}å²·}è²µ}Û±·}Þ±µ}¶²µ}·²·}ß°·}â°µ}Ó°·}Ö°µ}¿°·}Â°µ}¹°·}¼°µ}²°µ}³°·}ª°µ}«°·}°µ}°·}ö¯µ}÷¯·}Þ¯µ}ß¯·}Ì¯µ}Í¯·}¸¯µ}¹¯·}®¯µ}¯¯·}ª¯µ}«¯·}¯µ}¯·}ø®µ}ù®·}ì®µ}í®·}â®µ}ã®·}à®µ}á®·}§«®ñ®®ï¦®ï§®ñ®ñ ®ï¨®ï©®ñ®ñ®ïí®ñð®ï®ï®ñ®ñ®ïÒ®ïÓ®ñ®ñ®ï®ï®ñ®ï®ñþ­ïÿ­ñ¡¯ñ¤¯ïç­ñê­ïÝ­ñà­ïÓ¯ñÖ¯ïÉ®ñÌ®ï¤¯ï¥¯ñÍ­ñÐ­ïÁ­ñÄ­ï­­ñ°­ï§­ñª­ï ­ï¡­ñ­ï­ñø¬ïù¬ñä¬ïå¬ñÌ¬ïÍ¬ñº¬ï»¬ñ¦¬ï§¬ñ¬ï¬ñ¬ï¬ñü«ïý«ñæ«ïç«ñÚ«ïÛ«ñÐ«ïÑ«ñÎ«ïÏ«ñ§«««©«©«««««©«©«««««©Û««Þ«©«©«««««©À«©Á««óª«öª©ðª©ñª«îª©ïª«ìª©íª«¬«¬©Õª«Øª©Ëª«Îª©Á¬«Ä¬©·««º«©¬©¬«»ª«¾ª©¯ª«²ª©ª«ª©ª«ª©ª©ª«ª©ª«æ©©ç©«Ò©©Ó©«º©©»©«¨©©©©«©©©«©©©«©©©«ê¨©ë¨«Ô¨©Õ¨«È¨©É¨«¾¨©¿¨«¼¨©½¨«§¨å¨ã¨ã¨åù§åü§ã¨ã¨å÷§åú§ãÉ¨åÌ¨ãô§ãõ§åñ§åô§ã®¨ã¯¨åá§åä§ãÞ§ãß§åÜ§ãÝ§åÚ§ãÛ§åý¨å©ãÃ§åÆ§ã¹§å¼§ã¯©å²©ã¥¨å¨¨ã©ã©å©§å¬§ã§å §ã§å§ã§å§ãü¦ãý¦åô¦ãõ¦åÔ¦ãÕ¦åÀ¦ãÁ¦å¨¦ã©¦å¦ã¦å¦ã¦åø¥ãù¥åô¥ãõ¥åØ¥ãÙ¥åÂ¥ãÃ¥å¶¥ã·¥å¬¥ã­¥åª¥ã«¥å§õ¤ø¤ð¤ñ¤ç¤ê¤ò¤ó¤å¤è¤·¥º¥â¤ã¤ß¤â¤¥¥Ï¤Ò¤Ì¤Í¤Ê¤Ë¤È¤É¤ë¥î¥±¤´¤§¤ª¤¦ ¦¥¥î¥ï¥¤¤¤¤÷£ú£ñ£ô£ê£ë£â£ã£Â£Ã£®£¯£££££ð¢ñ¢æ¢ç¢â¢ã¢Æ¢Ç¢°¢±¢¤¢¥¢¢¢¢¢§ã¡Ùæ¡×Þ¡×ß¡ÙÕ¡ÙØ¡×à¡×á¡ÙÓ¡ÙÖ¡×¥¢Ù¨¢×Ð¡×Ñ¡ÙÍ¡ÙÐ¡×¢×¢Ù½¡ÙÀ¡×º¡×»¡Ù¸¡×¹¡Ù¶¡×·¡ÙÙ¢ÙÜ¢×¡Ù¢¡×¡Ù¡×£Ù£×¢Ù¢×Ü¢×Ý¢Ù¡Ù¡×ù Ùü ×å Ùè ×ß Ùâ ×Ø ×Ù ÙÐ ×Ñ Ù° ×± Ù × Ù × Ùò×óÙÞ×ßÙÔ×ÕÙÐ×ÑÙ´×µÙ×Ù×Ù×Ù×Ù§ÑÔÌÍÃÆÎÏÁÄ¾¿»¾øù«®¨©¦§¤¥ÇÊùüïòÊËóöçêÓÖÍÐÆÇ¾¿òóàáÌÍÂÃ¾¿¢£ö÷ôõ§¿Í£ÂË£ºË£»Í£±Í£´Ë£¼Ë£½Í£¯Í£²Ë£Í£Ë£¬Ë£­Í£©Í£¬Ë£æË£çÍ£Í£Ë£Ë£Í£Ë£Í£Ë£Í£µÍ£¸Ë£ûÍ£þË£ñÍ£ôË£çÍ£êË£ÝÍ£àË£¸Ë£¹Í£áÍ£äË£ÕÍ£ØË£ÁÍ£ÄË£»Í£¾Ë£´Ë£µÍ£¬Ë£­Í£Ë£Í£øË£ùÍ£àË£áÍ£ÎË£ÏÍ£ºË£»Í£°Ë£±Í£¬Ë£­Í£Ë£Í£úË£ûÍ£îË£ïÍ£äË£åÍ£âË£ãÍ£§­©°©¨©©©©¢©ª©«©© ©ï©ò©©©©©Ô©Õ©©©©©©©©©£©¦©é©ì©ß©â©Õ©Ø©Ë©Î©¦©§©Ï©Ò©Ã©Æ©¯©²©©©¬©¢©£©©©ú©û©æ©ç©Î©Ï©¼©½©¨©©©©©©©þ©ÿ©è©é©Ü©Ý©Ò©Ó©Ð©Ñ©§Á®¿®¿®Á®Á®¿®¿®Á®Á®¿®ÝÁ®à¿®¿®Á®Á®¿®Â¿®ÃÁ®õÁ®ø¿®ò¿®óÁ®ð¿®ñÁ®î¿®ïÁ®Á®¿®×Á®Ú¿®ÍÁ®Ð¿®ÃÁ®Æ¿®¹Á®¼¿®¿®Á®½Á®À¿®±Á®´¿®Á® ¿®Á®¿®¿®Á®¿®Á®è¿®éÁ®Ô¿®ÕÁ®¼¿®½Á®ª¿®«Á®¿®Á®¿®Á®¿®Á®ì¿®íÁ®Ö¿®×Á®Ê¿®ËÁ®À¿®ÁÁ®¾¿®¿Á®§û³ù³ù³û³ûû³þù³ù³û³ùû³üù³Ëû³Îù³öù³÷û³óû³öù³°ù³±û³ãû³æù³àù³áû³Þù³ßû³Üù³Ýû³ÿû³ù³Åû³Èù³»û³¾ù³±û³´ù³§û³ªù³ù³û³«û³®ù³û³¢ù³û³ù³û³ù³þù³ÿû³öù³÷û³Öù³×û³Âù³Ãû³ªù³«û³ù³û³ù³û³úù³ûû³öù³÷û³Úù³Ûû³Äù³Åû³¸ù³¹û³®ù³¯û³¬ù³­û³§÷µ¹ú³¹ò³¹óµ¹éµ¹ì³¹ô³¹õµ¹çµ¹ê³¹¹µ¹¼³¹ä³¹åµ¹áµ¹ä³¹³¹µ¹Ñµ¹Ô³¹Î³¹Ïµ¹Ì³¹Íµ¹Ê³¹Ëµ¹íµ¹ð³¹³µ¹¶³¹©µ¹¬³¹µ¹¢³¹µ¹³¹ð³¹ñµ¹µ¹³¹µ¹³¹ùµ¹ü³¹óµ¹ö³¹ì³¹íµ¹ä³¹åµ¹Ä³¹Åµ¹°³¹±µ¹³¹µ¹³¹µ¹ò³¹óµ¹è³¹éµ¹ä³¹åµ¹È³¹Éµ¹²³¹³µ¹¦³¹§µ¹³¹µ¹³¹µ¹§åï¾èí¾àí¾áï¾×ï¾Úí¾âí¾ãï¾Õï¾Øí¾§ï¾ªí¾Òí¾Óï¾Ïï¾Òí¾í¾ï¾¿ï¾Âí¾¼í¾½ï¾ºí¾»ï¾¸í¾¹ï¾Ûï¾Þí¾¡ï¾¤í¾ï¾í¾ï¾í¾ï¾í¾Þí¾ßï¾ï¾í¾ûï¾þí¾çï¾êí¾áï¾äí¾Úí¾Ûï¾Òí¾Óï¾²í¾³ï¾í¾ï¾í¾ï¾ôí¾õï¾àí¾áï¾Öí¾×ï¾Òí¾Óï¾¶í¾·ï¾ í¾¡ï¾í¾ï¾í¾ï¾í¾ï¾§Ó©ÄÖ§ÄÎ§ÄÏ©ÄÅ©ÄÈ§ÄÐ§ÄÑ©ÄÃ©ÄÆ§Ä©Ä§ÄÀ§ÄÁ©Ä½©ÄÀ§Äú§Äû©Ä­©Ä°§Äª§Ä«©Ä¨§Ä©©Ä¦§Ä§©ÄÉ©ÄÌ§Ä©Ä§Ä©Ä§Äû©Äþ§Äñ©Äô§ÄÌ§ÄÍ©Äõ©Äø§Äé©Äì§ÄÕ©ÄØ§ÄÏ©ÄÒ§ÄÈ§ÄÉ©ÄÀ§ÄÁ©Ä §Ä¡©Ä§Ä©Äô§Äõ©Äâ§Äã©ÄÎ§ÄÏ©ÄÄ§ÄÅ©ÄÀ§ÄÁ©Ä¤§Ä¥©Ä§Ä©Ä§Ä©Äø§Äù©Äö§Ä÷©Ä§ÁãÉÄáÉ¼áÉ½ãÉ³ãÉ¶áÉ¾áÉ¿ãÉ±ãÉ´áÉãÉáÉ®áÉ¯ãÉ«ãÉ®áÉèáÉéãÉãÉáÉáÉãÉáÉãÉáÉãÉ·ãÉºáÉýãÉáÉóãÉöáÉéãÉìáÉßãÉâáÉºáÉ»ãÉããÉæáÉ×ãÉÚáÉÃãÉÆáÉ½ãÉÀáÉ¶áÉ·ãÉ®áÉ¯ãÉáÉãÉúáÉûãÉâáÉããÉÐáÉÑãÉ¼áÉ½ãÉ²áÉ³ãÉ®áÉ¯ãÉáÉãÉüáÉýãÉðáÉñãÉæáÉçãÉäáÉåãÉ§¯Ï²ÏªÏ«Ï¡Ï¤Ï¬Ï­ÏÏ¢ÏñÏôÏÏÏÏÏÖÏ×ÏÏÏÏÏÏÏÏÏ¥Ï¨ÏëÏîÏáÏäÏ×ÏÚÏÍÏÐÏ¨Ï©ÏÑÏÔÏÅÏÈÏ±Ï´Ï«Ï®Ï¤Ï¥ÏÏÏüÏýÏèÏéÏÐÏÑÏ¾Ï¿ÏªÏ«Ï Ï¡ÏÏÏÏÏêÿÏëÿÏÞÿÏßÿÏÔÿÏÕÿÏÒÿÏÓÿÏ§ÿ×Ô ÿÕÔÿÕÔÿ×Ôÿ×ÔÿÕÔÿÕÔÿ×Ôÿ×ÔÿÕÔßÿ×ÔâÿÕÔÿÕÔÿ×Ôÿ×ÔÿÕÔÄÿÕÔÅÿ×Ô÷þ×ÔúþÕÔôþÕÔõþ×ÔòþÕÔóþ×ÔðþÕÔñþ×Ô×ÔÕÔÙþ×ÔÜþÕÔÏþ×ÔÒþÕÔÅ×ÔÈÕÔ»ÿ×Ô¾ÿÕÔÕÔ×Ô¿þ×ÔÂþÕÔ³þ×Ô¶þÕÔþ×Ô¢þÕÔþ×ÔþÕÔþÕÔþ×ÔþÕÔþ×ÔêýÕÔëý×ÔÖýÕÔ×ý×Ô¾ýÕÔ¿ý×Ô¬ýÕÔ­ý×ÔýÕÔý×ÔýÕÔý×ÔýÕÔý×ÔîüÕÔïü×ÔØüÕÔÙü×ÔÌüÕÔÍü×ÔÂüÕÔÃü×ÔÀüÕÔÁü×Ô§üÚüÚüÚüÚýûÚüÚüÚüÚûûÚþûÚÍüÚÐüÚøûÚùûÚõûÚøûÚ²üÚ³üÚåûÚèûÚâûÚãûÚàûÚáûÚÞûÚßûÚýÚýÚÇûÚÊûÚ½ûÚÀûÚ³ýÚ¶ýÚ©üÚ¬üÚýÚýÚ­ûÚ°ûÚ¡ûÚ¤ûÚûÚûÚûÚûÚûÚûÚøúÚùúÚØúÚÙúÚÄúÚÅúÚ¬úÚ­úÚúÚúÚúÚúÚüùÚýùÚøùÚùùÚÜùÚÝùÚÆùÚÇùÚºùÚ»ùÚ°ùÚ±ùÚ®ùÚ¯ùÚ§ùøËßüøÉßôøÉßõøËßëøËßîøÉßöøÉß÷øËßéøËßìøÉß»ùËß¾ùÉßæøÉßçøËßãøËßæøÉß ùÉß¡ùËßÓøËßÖøÉßÐøÉßÑøËßÎøÉßÏøËßÌøÉßÍøËßïùËßòùÉßµøËß¸øÉß«øËß®øÉß¡úËß¤úÉßùËßùÉßòùÉßóùËßøËßøÉßøËßøÉßû÷Ëßþ÷Éßõ÷Ëßø÷Éßî÷Éßï÷Ëßæ÷Éßç÷ËßÆ÷ÉßÇ÷Ëß²÷Éß³÷Ëß÷Éß÷Ëß÷Éß÷ËßôöÉßõöËßêöÉßëöËßæöÉßçöËßÊöÉßËöËß´öÉßµöËß¨öÉß©öËßöÉßöËßöÉßöËß§çõåêõåâõåãõåÙõåÜõåäõååõå×õåÚõå©öå¬öåÔõåÕõåÑõåÔõåöåöåÁõåÄõå¾õå¿õå¼õå½õåºõå»õåÝöåàöå£õå¦õåõåõå÷å÷åöåöåàöåáöåõåõåýôåõåéôåìôåãôåæôåÜôåÝôåÔôåÕôå´ôåµôå ôå¡ôåôåôåöóå÷óåâóåãóåØóåÙóåÔóåÕóå¸óå¹óå¢óå£óåóåóåóåóåóåóå§Õò¿êØò½êÐò½êÑò¿êÇò¿êÊò½êÒò½êÓò¿êÅò¿êÈò½êó¿êó½êÂò½êÃò¿ê¿ò¿êÂò½êüò½êýò¿ê¯ò¿ê²ò½ê¬ò½ê­ò¿êªò½ê«ò¿ê¨ò½ê©ò¿êËó¿êÎó½êò¿êò½êò¿êò½êýó¿êô½êóò¿êöò½êÎó½êÏó¿ê÷ñ¿êúñ½êëñ¿êîñ½ê×ñ¿êÚñ½êÑñ¿êÔñ½êÊñ½êËñ¿êÂñ½êÃñ¿ê¢ñ½ê£ñ¿êñ½êñ¿êöð½ê÷ð¿êäð½êåð¿êÐð½êÑð¿êÆð½êÇð¿êÂð½êÃð¿ê¦ð½ê§ð¿êð½êð¿êð½êð¿êúï½êûï¿êøï½êùï¿ê§ÃïùïÆï÷ï¾ï÷ï¿ïùïµïùï¸ï÷ïÀï÷ïÁïùï³ïùï¶ï÷ïðùïð÷ï°ï÷ï±ïùï­ïùï°ï÷ïêï÷ïëïùïïùï ï÷ïï÷ïïùïï÷ïïùïï÷ïïùï¹ðùï¼ð÷ïÿîùïï÷ïõîùïøî÷ïëðùïîð÷ïáïùïäï÷ï¼ð÷ï½ðùïåîùïèî÷ïÙîùïÜî÷ïÅîùïÈî÷ï¿îùïÂî÷ï¸î÷ï¹îùï°î÷ï±îùïî÷ïîùïüí÷ïýíùïäí÷ïåíùïÒí÷ïÓíùï¾í÷ï¿íùï´í÷ïµíùï°í÷ï±íùïí÷ïíùïþì÷ïÿìùïòì÷ïóìùïèì÷ïéìùïæì÷ïçìùï§±ì³õ´ì±õ¬ì±õ­ì³õ£ì³õ¦ì±õ®ì±õ¯ì³õ¡ì³õ¤ì±õóì³õöì±õì±õì³õì³õì±õØì±õÙì³õì³õì±õì±õì³õì±õì³õì±õì³õ§í³õªí±õíë³õðë±õãë³õæë±õÙí³õÜí±õÏì³õÒì±õªí±õ«í³õÓë³õÖë±õÇë³õÊë±õ³ë³õ¶ë±õ­ë³õ°ë±õ¦ë±õ§ë³õë±õë³õþê±õÿê³õêê±õëê³õÒê±õÓê³õÀê±õÁê³õ¬ê±õ­ê³õ¢ê±õ£ê³õê±õê³õê±õê³õìé±õíé³õàé±õáé³õÖé±õ×é³õÔé±õÕé³õ§éíú¢éëúéëúéíúéíúéëúéëúéíúéíúéëúáéíúäéëúéëúéíúéíúéëúÆéëúÇéíúùèíúüèëúöèëú÷èíúôèëúõèíúòèëúóèíúêíúêëúÛèíúÞèëúÑèíúÔèëúÇêíúÊêëú½éíúÀéëúêëúêíúÁèíúÄèëúµèíú¸èëú¡èíú¤èëúèíúèëúèëúèíúèëúèíúìçëúíçíúØçëúÙçíúÀçëúÁçíú®çëú¯çíúçëúçíúçëúçíúçëúçíúðæëúñæíúÚæëúÛæíúÎæëúÏæíúÄæëúÅæíúÂæëúÃæíú§æ§æ¥æ¥æ§ÿå§æ¥æ¥æ§ýå§æ¥Ïæ§Òæ¥úå¥ûå§÷å§úå¥´æ¥µæ§çå§êå¥äå¥åå§âå¥ãå§àå¥áå§ç§ç¥Éå§Ìå¥¿å§Âå¥µç§¸ç¥«æ§®æ¥ç¥ç§¯å§²å¥£å§¦å¥å§å¥å§å¥å¥å§úä¥ûä§Úä¥Ûä§Æä¥Çä§®ä¥¯ä§ä¥ä§ä¥ä§þã¥ÿã§úã¥ûã§Þã¥ßã§Èã¥Éã§¼ã¥½ã§²ã¥³ã§°ã¥±ã§§ûâáþâßöâß÷âáíâáðâßøâßùâáëâáîâß½ãáÀãßèâßéâáåâáèâß¢ãß£ãáÕâáØâßÒâßÓâáÐâßÑâáÎâßÏâáñãáôãß·âáºâß­âá°âß£äá¦äßãáãßôãßõãáâá âßâáâßýááâß÷ááúáßðáßñááèáßéááÈáßÉáá´áßµáááßáááßááöàß÷àáìàßíàáèàßéàáÌàßÍàá¶àß·àáªàß«àá àß¡àáàßàá§éßìßäßåßÛßÞßæßçßÙßÜß«à®àÖß×ßÓßÖßààÃßÆßÀßÁß¾ß¿ß¼ß½ßßàâà¥ß¨ßßßááààâàãàßßÿÞßëÞîÞåÞèÞÞÞßÞÖÞ×Þ¶Þ·Þ¢Þ£ÞÞÞøÝùÝäÝåÝÚÝÛÝÖÝ×ÝºÝ»Ý¤Ý¥ÝÝÝÝÝÝÝ§×ÜÕÚÜÓÒÜÓÓÜÕÉÜÕÌÜÓÔÜÓÕÜÕÇÜÕÊÜÓÝÕÝÓÄÜÓÅÜÕÁÜÕÄÜÓþÜÓÿÜÕ±ÜÕ´ÜÓ®ÜÓ¯ÜÕ¬ÜÓ­ÜÕªÜÓ«ÜÕÍÝÕÐÝÓÜÕÜÓÜÕÜÓÿÝÕÞÓõÜÕøÜÓÐÝÓÑÝÕùÛÕüÛÓíÛÕðÛÓÙÛÕÜÛÓÓÛÕÖÛÓÌÛÓÍÛÕÄÛÓÅÛÕ¤ÛÓ¥ÛÕÛÓÛÕøÚÓùÚÕæÚÓçÚÕÒÚÓÓÚÕÈÚÓÉÚÕÄÚÓÅÚÕ¨ÚÓ©ÚÕÚÓÚÕÚÓÚÕüÙÓýÙÕúÙÓûÙÕ§ßä»âä¹Úä¹Ûä»Ñä»Ôä¹Üä¹Ýä»Ïä»Òä¹¡å»¤å¹Ìä¹Íä»Éä»Ìä¹å¹å»¹ä»¼ä¹¶ä¹·ä»´ä¹µä»²ä¹³ä»Õå»Øå¹ä»ä¹ä»ä¹æ»æ¹ýä»å¹Øå¹Ùå»ä»ä¹õã»øã¹áã»äã¹Ûã»Þã¹Ôã¹Õã»Ìã¹Íã»¬ã¹­ã»ã¹ã»ã¹ã»îâ¹ïâ»Úâ¹Ûâ»Ðâ¹Ñâ»Ìâ¹Íâ»°â¹±â»â¹â»â¹â»â¹â»â¹â»§Íáõ
+Ðáó
+Èáó
+Éáõ
+¿áõ
+Âáó
+Êáó
+Ëáõ
+½áõ
+Àáó
+âõ
+âó
+ºáó
+»áõ
+·áõ
+ºáó
+ôáó
+õáõ
+§áõ
+ªáó
+¤áó
+¥áõ
+¢áó
+£áõ
+ áó
+¡áõ
+Ãâõ
+Æâó
+áõ
+áó
+ÿàõ
+áó
+õâõ
+øâó
+ëáõ
+îáó
+Æâó
+Çâõ
+ïàõ
+òàó
+ãàõ
+æàó
+Ïàõ
+Òàó
+Éàõ
+Ìàó
+Âàó
+Ãàõ
+ºàó
+»àõ
+àó
+àõ
+àó
+àõ
+îßó
+ïßõ
+Üßó
+Ýßõ
+Èßó
+Éßõ
+¾ßó
+¿ßõ
+ºßó
+»ßõ
+ßó
+ßõ
+ßó
+ßõ
+üÞó
+ýÞõ
+òÞó
+óÞõ
+ðÞó
+ñÞõ
+§»Þ¯¾Þ­¶Þ­·Þ¯­Þ¯°Þ­¸Þ­¹Þ¯«Þ¯®Þ­ýÞ¯ß­¨Þ­©Þ¯¥Þ¯¨Þ­âÞ­ãÞ¯Þ¯Þ­Þ­Þ¯Þ­Þ¯Þ­Þ¯±ß¯´ß­÷Ý¯úÝ­íÝ¯ðÝ­ãß¯æß­ÙÞ¯ÜÞ­´ß­µß¯ÝÝ¯àÝ­ÑÝ¯ÔÝ­½Ý¯ÀÝ­·Ý¯ºÝ­°Ý­±Ý¯¨Ý­©Ý¯Ý­Ý¯ôÜ­õÜ¯ÜÜ­ÝÜ¯ÊÜ­ËÜ¯¶Ü­·Ü¯¬Ü­­Ü¯¨Ü­©Ü¯Ü­Ü¯öÛ­÷Û¯êÛ­ëÛ¯àÛ­áÛ¯ÞÛ­ßÛ¯§©Ûé¬Ûç¤Ûç¥ÛéÛéÛç¦Ûç§ÛéÛéÛçëÛéîÛçÛçÛéÛéÛçÐÛçÑÛéÛéÛçÛçÛéþÚçÿÚéüÚçýÚéÜé¢ÜçåÚéèÚçÛÚéÞÚçÑÜéÔÜçÇÛéÊÛç¢Üç£ÜéËÚéÎÚç¿ÚéÂÚç«Úé®Úç¥Úé¨ÚçÚçÚéÚçÚéöÙç÷ÙéâÙçãÙéÊÙçËÙé¸Ùç¹Ùé¤Ùç¥ÙéÙçÙéÙçÙéúØçûØéäØçåØéØØçÙØéÎØçÏØéÌØçÍØé§Ø£Ø¡Ø¡Ø£Ø£Ø¡Ø¡Ø£Ø£Ø¡ÙØ£ÜØ¡Ø¡Ø£Ø£Ø¡¾Ø¡¿Ø£ñ×£ô×¡î×¡ï×£ì×¡í×£ê×¡ë×£Ù£Ù¡Ó×£Ö×¡É×£Ì×¡¿Ù£ÂÙ¡µØ£¸Ø¡Ù¡Ù£¹×£¼×¡­×£°×¡×£×¡×£×¡×¡×£×¡×£äÖ¡åÖ£ÐÖ¡ÑÖ£¸Ö¡¹Ö£¦Ö¡§Ö£Ö¡Ö£Ö¡Ö£Ö¡Ö£èÕ¡éÕ£ÒÕ¡ÓÕ£ÆÕ¡ÇÕ£¼Õ¡½Õ£ºÕ¡»Õ£§ÕÝ ÕÛ ÕÛ ÕÝ ÷ÔÝ úÔÛ ÕÛ ÕÝ õÔÝ øÔÛ ÇÕÝ ÊÕÛ òÔÛ óÔÝ ïÔÝ òÔÛ ¬ÕÛ ­ÕÝ ßÔÝ âÔÛ ÜÔÛ ÝÔÝ ÚÔÛ ÛÔÝ ØÔÛ ÙÔÝ ûÕÝ þÕÛ ÁÔÝ ÄÔÛ ·ÔÝ ºÔÛ ­ÖÝ °ÖÛ £ÕÝ ¦ÕÛ þÕÛ ÿÕÝ §ÔÝ ªÔÛ ÔÝ ÔÛ ÔÝ ÔÛ ÔÝ ÔÛ úÓÛ ûÓÝ òÓÛ óÓÝ ÒÓÛ ÓÓÝ ¾ÓÛ ¿ÓÝ ¦ÓÛ §ÓÝ ÓÛ ÓÝ ÓÛ ÓÝ öÒÛ ÷ÒÝ òÒÛ óÒÝ ÖÒÛ ×ÒÝ ÀÒÛ ÁÒÝ ´ÒÛ µÒÝ ªÒÛ «ÒÝ ¨ÒÛ ©ÒÝ §óÑ&öÑ&îÑ&ïÑ&åÑ&èÑ&ðÑ&ñÑ&ãÑ&æÑ&µÒ&¸Ò&àÑ&áÑ&ÝÑ&àÑ&Ò&Ò&ÍÑ&ÐÑ&ÊÑ&ËÑ&ÈÑ&ÉÑ&ÆÑ&ÇÑ&éÒ&ìÒ&¯Ñ&²Ñ&¥Ñ&¨Ñ&Ó&Ó&Ò&Ò&ìÒ&íÒ&Ñ&Ñ&Ñ&Ñ&õÐ&øÐ&ïÐ&òÐ&èÐ&éÐ&àÐ&áÐ&ÀÐ&ÁÐ&¬Ð&­Ð&Ð&Ð&Ð&Ð&îÏ&ïÏ&äÏ&åÏ&àÏ&áÏ&ÄÏ&ÅÏ&®Ï&¯Ï&¢Ï&£Ï&Ï&Ï&Ï&Ï&§áÎÑ+äÎÏ+ÜÎÏ+ÝÎÑ+ÓÎÑ+ÖÎÏ+ÞÎÏ+ßÎÑ+ÑÎÑ+ÔÎÏ+£ÏÑ+¦ÏÏ+ÎÎÏ+ÏÎÑ+ËÎÑ+ÎÎÏ+ÏÏ+ÏÑ+»ÎÑ+¾ÎÏ+¸ÎÏ+¹ÎÑ+¶ÎÏ+·ÎÑ+´ÎÏ+µÎÑ+×ÏÑ+ÚÏÏ+ÎÑ+ ÎÏ+ÎÑ+ÎÏ+ÐÑ+ÐÏ+ÿÎÑ+ÏÏ+ÚÏÏ+ÛÏÑ+ÎÑ+ÎÏ+÷ÍÑ+úÍÏ+ãÍÑ+æÍÏ+ÝÍÑ+àÍÏ+ÖÍÏ+×ÍÑ+ÎÍÏ+ÏÍÑ+®ÍÏ+¯ÍÑ+ÍÏ+ÍÑ+ÍÏ+ÍÑ+ðÌÏ+ñÌÑ+ÜÌÏ+ÝÌÑ+ÒÌÏ+ÓÌÑ+ÎÌÏ+ÏÌÑ+²ÌÏ+³ÌÑ+ÌÏ+ÌÑ+ÌÏ+ÌÑ+ÌÏ+ÌÑ+ÌÏ+ÌÑ+§ÏË1ÒË1ÊË1ËË1ÁË1ÄË1ÌË1ÍË1¿Ë1ÂË1Ì1Ì1¼Ë1½Ë1¹Ë1¼Ë1öË1÷Ë1©Ë1¬Ë1¦Ë1§Ë1¤Ë1¥Ë1¢Ë1£Ë1ÅÌ1ÈÌ1Ë1Ë1Ë1Ë1÷Ì1úÌ1íË1ðË1ÈÌ1ÉÌ1ñÊ1ôÊ1åÊ1èÊ1ÑÊ1ÔÊ1ËÊ1ÎÊ1ÄÊ1ÅÊ1¼Ê1½Ê1Ê1Ê1Ê1Ê1ðÉ1ñÉ1ÞÉ1ßÉ1ÊÉ1ËÉ1ÀÉ1ÁÉ1¼É1½É1 É1¡É1É1É1þÈ1ÿÈ1ôÈ1õÈ1òÈ1óÈ1§½ÈÅ6ÀÈÃ6¸ÈÃ6¹ÈÅ6¯ÈÅ6²ÈÃ6ºÈÃ6»ÈÅ6­ÈÅ6°ÈÃ6ÿÈÅ6ÉÃ6ªÈÃ6«ÈÅ6§ÈÅ6ªÈÃ6äÈÃ6åÈÅ6ÈÅ6ÈÃ6ÈÃ6ÈÅ6ÈÃ6ÈÅ6ÈÃ6ÈÅ6³ÉÅ6¶ÉÃ6ùÇÅ6üÇÃ6ïÇÅ6òÇÃ6åÉÅ6èÉÃ6ÛÈÅ6ÞÈÃ6¶ÉÃ6·ÉÅ6ßÇÅ6âÇÃ6ÓÇÅ6ÖÇÃ6¿ÇÅ6ÂÇÃ6¹ÇÅ6¼ÇÃ6²ÇÃ6³ÇÅ6ªÇÃ6«ÇÅ6ÇÃ6ÇÅ6öÆÃ6÷ÆÅ6ÞÆÃ6ßÆÅ6ÌÆÃ6ÍÆÅ6¸ÆÃ6¹ÆÅ6®ÆÃ6¯ÆÅ6ªÆÃ6«ÆÅ6ÆÃ6ÆÅ6øÅÃ6ùÅÅ6ìÅÃ6íÅÅ6âÅÃ6ãÅÅ6àÅÃ6áÅÅ6§«Åÿ;®Åý;¦Åý;§Åÿ;Åÿ; Åý;¨Åý;©Åÿ;Åÿ;Åý;íÅÿ;ðÅý;Åý;Åÿ;Åÿ;Åý;ÒÅý;ÓÅÿ;Åÿ;Åý;Åý;Åÿ;Åý;Åÿ;þÄý;ÿÄÿ;¡Æÿ;¤Æý;çÄÿ;êÄý;ÝÄÿ;àÄý;ÓÆÿ;ÖÆý;ÉÅÿ;ÌÅý;¤Æý;¥Æÿ;ÍÄÿ;ÐÄý;ÁÄÿ;ÄÄý;­Äÿ;°Äý;§Äÿ;ªÄý; Äý;¡Äÿ;Äý;Äÿ;øÃý;ùÃÿ;äÃý;åÃÿ;ÌÃý;ÍÃÿ;ºÃý;»Ãÿ;¦Ãý;§Ãÿ;Ãý;Ãÿ;Ãý;Ãÿ;üÂý;ýÂÿ;æÂý;çÂÿ;ÚÂý;ÛÂÿ;ÐÂý;ÑÂÿ;ÎÂý;ÏÂÿ;§Â¹AÂ·AÂ·AÂ¹AÂ¹AÂ·AÂ·AÂ¹AÂ¹AÂ·AÛÂ¹AÞÂ·AÂ·AÂ¹AÂ¹AÂ·AÀÂ·AÁÂ¹AóÁ¹AöÁ·AðÁ·AñÁ¹AîÁ·AïÁ¹AìÁ·AíÁ¹AÃ¹AÃ·AÕÁ¹AØÁ·AËÁ¹AÎÁ·AÁÃ¹AÄÃ·A·Â¹AºÂ·AÃ·AÃ¹A»Á¹A¾Á·A¯Á¹A²Á·AÁ¹AÁ·AÁ¹AÁ·AÁ·AÁ¹AÁ·AÁ¹AæÀ·AçÀ¹AÒÀ·AÓÀ¹AºÀ·A»À¹A¨À·A©À¹AÀ·AÀ¹AÀ·AÀ¹AÀ·AÀ¹Aê¿·Aë¿¹AÔ¿·AÕ¿¹AÈ¿·AÉ¿¹A¾¿·A¿¿¹A¼¿·A½¿¹A§¿óF¿ñF¿ñF¿óFù¾óFü¾ñF¿ñF¿óF÷¾óFú¾ñFÉ¿óFÌ¿ñFô¾ñFõ¾óFñ¾óFô¾ñF®¿ñF¯¿óFá¾óFä¾ñFÞ¾ñFß¾óFÜ¾ñFÝ¾óFÚ¾ñFÛ¾óFý¿óFÀñFÃ¾óFÆ¾ñF¹¾óF¼¾ñF¯ÀóF²ÀñF¥¿óF¨¿ñFÀñFÀóF©¾óF¬¾ñF¾óF ¾ñF¾óF¾ñF¾óF¾ñFü½ñFý½óFô½ñFõ½óFÔ½ñFÕ½óFÀ½ñFÁ½óF¨½ñF©½óF½ñF½óF½ñF½óFø¼ñFù¼óFô¼ñFõ¼óFØ¼ñFÙ¼óFÂ¼ñFÃ¼óF¶¼ñF·¼óF¬¼ñF­¼óFª¼ñF«¼óF§õ»­Lø»«Lð»«Lñ»­Lç»­Lê»«Lò»«Ló»­Lå»­Lè»«L·¼­Lº¼«Lâ»«Lã»­Lß»­Lâ»«L¼«L¼­LÏ»­LÒ»«LÌ»«LÍ»­LÊ»«LË»­LÈ»«LÉ»­Lë¼­Lî¼«L±»­L´»«L§»­Lª»«L½­L ½«L¼­L¼«Lî¼«Lï¼­L»­L»«L»­L»«L÷º­Lúº«Lñº­Lôº«Lêº«Lëº­Lâº«Lãº­LÂº«LÃº­L®º«L¯º­Lº«Lº­Lº«Lº­Lð¹«Lñ¹­Læ¹«Lç¹­Lâ¹«Lã¹­LÆ¹«LÇ¹­L°¹«L±¹­L¤¹«L¥¹­L¹«L¹­L¹«L¹­L§ã¸çQæ¸åQÞ¸åQß¸çQÕ¸çQØ¸åQà¸åQá¸çQÓ¸çQÖ¸åQ¥¹çQ¨¹åQÐ¸åQÑ¸çQÍ¸çQÐ¸åQ¹åQ¹çQ½¸çQÀ¸åQº¸åQ»¸çQ¸¸åQ¹¸çQ¶¸åQ·¸çQÙ¹çQÜ¹åQ¸çQ¢¸åQ¸çQ¸åQºçQºåQ¹çQ¹åQÜ¹åQÝ¹çQ¸çQ¸åQù·çQü·åQå·çQè·åQß·çQâ·åQØ·åQÙ·çQÐ·åQÑ·çQ°·åQ±·çQ·åQ·çQ·åQ·çQò¶åQó¶çQÞ¶åQß¶çQÔ¶åQÕ¶çQÐ¶åQÑ¶çQ´¶åQµ¶çQ¶åQ¶çQ¶åQ¶çQ¶åQ¶çQ¶åQ¶çQ§Ñµ¡WÔµWÌµWÍµ¡WÃµ¡WÆµWÎµWÏµ¡WÁµ¡WÄµW¶¡W¶W¾µW¿µ¡W»µ¡W¾µWøµWùµ¡W«µ¡W®µW¨µW©µ¡W¦µW§µ¡W¤µW¥µ¡WÇ¶¡WÊ¶Wµ¡WµWµ¡WµWù¶¡Wü¶Wïµ¡WòµWÊ¶WË¶¡Wó´¡Wö´Wç´¡Wê´WÓ´¡WÖ´WÍ´¡WÐ´WÆ´WÇ´¡W¾´W¿´¡W´W´¡W´W´¡Wò³Wó³¡Wà³Wá³¡WÌ³WÍ³¡WÂ³WÃ³¡W¾³W¿³¡W¢³W£³¡W³W³¡W³W³¡Wö²W÷²¡Wô²Wõ²¡W§¿²Û\Â²Ù\º²Ù\»²Û\±²Û\´²Ù\¼²Ù\½²Û\¯²Û\²²Ù\³Û\³Ù\¬²Ù\­²Û\©²Û\¬²Ù\æ²Ù\ç²Û\²Û\²Ù\²Ù\²Û\²Ù\²Û\²Ù\²Û\µ³Û\¸³Ù\û±Û\þ±Ù\ñ±Û\ô±Ù\ç³Û\ê³Ù\Ý²Û\à²Ù\¸³Ù\¹³Û\á±Û\ä±Ù\Õ±Û\Ø±Ù\Á±Û\Ä±Ù\»±Û\¾±Ù\´±Ù\µ±Û\¬±Ù\­±Û\±Ù\±Û\ø°Ù\ù°Û\à°Ù\á°Û\Î°Ù\Ï°Û\º°Ù\»°Û\°°Ù\±°Û\¬°Ù\­°Û\°Ù\°Û\ú¯Ù\û¯Û\î¯Ù\ï¯Û\ä¯Ù\å¯Û\â¯Ù\ã¯Û\§­¯b°¯b¨¯b©¯b¯b¢¯bª¯b«¯b¯b ¯bï¯bò¯b¯b¯b¯b¯bÔ¯bÕ¯b¯b¯b¯b¯b¯b¯b¯b¯b£°b¦°bé®bì®bß®bâ®bÕ°bØ°bË¯bÎ¯b¦°b§°bÏ®bÒ®bÃ®bÆ®b¯®b²®b©®b¬®b¢®b£®b®b®bú­bû­bæ­bç­bÎ­bÏ­b¼­b½­b¨­b©­b­b­b­b­bþ¬bÿ¬bè¬bé¬bÜ¬bÝ¬bÒ¬bÓ¬bÐ¬bÑ¬b§¬Ïg¬Íg¬Íg¬Ïg¬Ïg¬Íg¬Íg¬Ïg¬Ïg¬ÍgÝ¬Ïgà¬Íg¬Íg¬Ïg¬Ïg¬ÍgÂ¬ÍgÃ¬Ïgõ«Ïgø«Ígò«Ígó«Ïgð«Ígñ«Ïgî«Ígï«Ïg­Ïg­Íg×«ÏgÚ«ÍgÍ«ÏgÐ«ÍgÃ­ÏgÆ­Íg¹¬Ïg¼¬Íg­Íg­Ïg½«ÏgÀ«Íg±«Ïg´«Íg«Ïg «Íg«Ïg«Íg«Íg«Ïg«Íg«ÏgèªÍgéªÏgÔªÍgÕªÏg¼ªÍg½ªÏgªªÍg«ªÏgªÍgªÏgªÍgªÏgªÍgªÏgì©Ígí©ÏgÖ©Íg×©ÏgÊ©ÍgË©ÏgÀ©ÍgÁ©Ïg¾©Íg¿©Ïg§©m©m©m©mû¨mþ¨m©m©mù¨mü¨mË©mÎ©mö¨m÷¨mó¨mö¨m°©m±©mã¨mæ¨mà¨má¨mÞ¨mß¨mÜ¨mÝ¨mÿ©mªmÅ¨mÈ¨m»¨m¾¨m±ªm´ªm§©mª©mªmªm«¨m®¨m¨m¢¨m¨m¨m¨m¨mþ§mÿ§mö§m÷§mÖ§m×§mÂ§mÃ§mª§m«§m§m§m§m§mú¦mû¦mö¦m÷¦mÚ¦mÛ¦mÄ¦mÅ¦m¸¦m¹¦m®¦m¯¦m¬¦m­¦m§÷¥Ãrú¥Árò¥Áró¥Ãré¥Ãrì¥Árô¥Árõ¥Ãrç¥Ãrê¥Ár¹¦Ãr¼¦Árä¥Árå¥Ãrá¥Ãrä¥Ár¦Ár¦ÃrÑ¥ÃrÔ¥ÁrÎ¥ÁrÏ¥ÃrÌ¥ÁrÍ¥ÃrÊ¥ÁrË¥Ãrí¦Ãrð¦Ár³¥Ãr¶¥Ár©¥Ãr¬¥Ár§Ãr¢§Ár¦Ãr¦Árð¦Árñ¦Ãr¥Ãr¥Ár¥Ãr¥Árù¤Ãrü¤Áró¤Ãrö¤Árì¤Árí¤Ãrä¤Árå¤ÃrÄ¤ÁrÅ¤Ãr°¤Ár±¤Ãr¤Ár¤Ãr¤Ár¤Ãrò£Áró£Ãrè£Áré£Ãrä£Árå£ÃrÈ£ÁrÉ£Ãr²£Ár³£Ãr¦£Ár§£Ãr£Ár£Ãr£Ár£Ãr§å¢ýwè¢ûwà¢ûwá¢ýw×¢ýwÚ¢ûwâ¢ûwã¢ýwÕ¢ýwØ¢ûw§£ýwª£ûwÒ¢ûwÓ¢ýwÏ¢ýwÒ¢ûw£ûw£ýw¿¢ýwÂ¢ûw¼¢ûw½¢ýwº¢ûw»¢ýw¸¢ûw¹¢ýwÛ£ýwÞ£ûw¡¢ýw¤¢ûw¢ýw¢ûw¤ýw¤ûw£ýw£ûwÞ£ûwß£ýw¢ýw¢ûwû¡ýwþ¡ûwç¡ýwê¡ûwá¡ýwä¡ûwÚ¡ûwÛ¡ýwÒ¡ûwÓ¡ýw²¡ûw³¡ýw¡ûw¡ýw¡ûw¡ýwô ûwõ ýwà ûwá ýwÖ ûw× ýwÒ ûwÓ ýw¶ ûw· ýw  ûw¡ ýw ûw ýw ûw ýw ûw ýw§Ó·}Öµ}Îµ}Ï·}Å·}Èµ}Ðµ}Ñ·}Ã·}Æµ} ·} µ}Àµ}Á·}½·}Àµ}úµ}û·}­·}°µ}ªµ}«·}¨µ}©·}¦µ}§·}É ·}Ì µ}·}µ}·}µ}û ·}þ µ}ñ·}ôµ}Ì µ}Í ·}õ·}øµ}é·}ìµ}Õ·}Øµ}Ï·}Òµ}Èµ}É·}Àµ}Á·} µ}¡·}µ}·}ôµ}õ·}âµ}ã·}Îµ}Ï·}Äµ}Å·}Àµ}Á·}¤µ}¥·}µ}·}µ}·}øµ}ù·}öµ}÷·}§ÁñÄï¼ï½ñ³ñ¶ï¾ï¿ñ±ñ´ïñï®ï¯ñ«ñ®ïèïéññïïñïñïñ·ñºïýñïóñöïéñìïßñâïºï»ñãñæï×ñÚïÃñÆï½ñÀï¶ï·ñ®ï¯ñïñúïûñâïãñÐïÑñ¼ï½ñ²ï³ñ®ï¯ñïñüïýñðïññæïçñäïåñ§¯«²©ª©««¡«¤©¬©­««¢©ñ«ô©©««©Ö©×««©©«©«©«¥«¨©ë«î©á«ä©×«Ú©Í«Ð©¨©©«Ñ«Ô©Å«È©±«´©««®©¤©¥«©«ü©ý«è©é«Ð©Ñ«¾©¿«ª©«« ©¡«©«©«ê©ë«Þ©ß«Ô©Õ«Ò©Ó«§å ããååããååãßåâããååãÄãÅå÷åúãôãõåòãóåðãñååãÙåÜãÏåÒãÅåÈã»å¾ããå¿åÂã³å¶ãå¢ãåããåãåêãëåÖã×å¾ã¿å¬ã­åãåãåãåîãïåØãÙåÌãÍåÂãÃåÀãÁå§ýûþÍÐøùõø²³åèâãàáÞßÇÊ½À³¶©¬­°¡¤øùØÙÄÅ¬­üýøùÜÝÆÇº»°±®¯§ùÙü×ô×õÙëÙî×ö×÷ÙéÙì×»Ù¾×æ×çÙãÙæ× ×¡ÙÓÙÖ×Ð×ÑÙÎ×ÏÙÌ×ÍÙïÙò×µÙ¸×«Ù®×¡Ù¤×Ù×ò×óÙÙ×Ù×ûÙþ×õÙø×î×ïÙæ×çÙÆ×ÇÙ²×³Ù×Ù×Ùô×õÙê×ëÙæ×çÙÊ×ËÙ´×µÙ¨×©Ù×Ù×Ù§çêâãÙÜäå×Ú©¬ÔÕÑÔÁÄ¾¿¼½º»Ýà£¦àáýéìãæÜÝÔÕ´µ ¡ö÷âãØÙÔÕ¸¹¢£§ÕÍ£ØË£ÐË£ÑÍ£ÇÍ£ÊË£ÒË£ÓÍ£ÅÍ£ÈË£Í£Ë£ÂË£ÃÍ£¿Í£ÂË£üË£ýÍ£¯Í£²Ë£¬Ë£­Í£ªË£«Í£¨Ë£©Í£ËÍ£ÎË£Í£Ë£Í£Ë£ýÍ£Ë£óÍ£öË£ÎË£ÏÍ£÷Í£úË£ëÍ£îË£×Í£ÚË£ÑÍ£ÔË£ÊË£ËÍ£ÂË£ÃÍ£¢Ë££Í£Ë£Í£öË£÷Í£äË£åÍ£ÐË£ÑÍ£ÆË£ÇÍ£ÂË£ÃÍ£¦Ë£§Í£Ë£Í£Ë£Í£úË£ûÍ£øË£ùÍ£§Ã©Æ©¾©¿©µ©¸©À©Á©³©¶©©©°©±©­©°©ê©ë©© ©©©©©©©¹©¼©ÿ©©õ©ø©ë©î©á©ä©¼©½©å©è©Ù©Ü©Å©È©¿©Â©¸©¹©°©±©©©ü©ý©ä©å©Ò©Ó©¾©¿©´©µ©°©±©©©þ©ÿ©ò©ó©è©é©æ©ç©§±Á®´¿®¬¿®­Á®£Á®¦¿®®¿®¯Á®¡Á®¤¿®óÁ®ö¿®¿®Á®Á®¿®Ø¿®ÙÁ®Á®¿®¿®Á®¿®Á®¿®Á®§Á®ª¿®íÁ®ð¿®ãÁ®æ¿®ÙÁ®Ü¿®ÏÁ®Ò¿®ª¿®«Á®ÓÁ®Ö¿®ÇÁ®Ê¿®³Á®¶¿®­Á®°¿®¦¿®§Á®¿®Á®þ¿®ÿÁ®ê¿®ëÁ®Ò¿®ÓÁ®À¿®ÁÁ®¬¿®­Á®¢¿®£Á®¿®Á®¿®Á®ì¿®íÁ®à¿®áÁ®Ö¿®×Á®Ô¿®ÕÁ®§û³¢ù³ù³û³û³ù³ù³û³û³ù³áû³äù³ù³û³û³ù³Æù³Çû³ùÿû³üÿù³öÿù³÷ÿû³ôÿù³õÿû³òÿù³óÿû³û³ù³Ûÿû³Þÿù³Ñÿû³Ôÿù³Çû³Êù³½û³Àù³ù³û³Áÿû³Äÿù³µÿû³¸ÿù³¡ÿû³¤ÿù³ÿû³ÿù³ÿù³ÿû³ÿù³ÿû³ìþù³íþû³Øþù³Ùþû³Àþù³Áþû³®þù³¯þû³þù³þû³þù³þû³þù³þû³ðýù³ñýû³Úýù³Ûýû³Îýù³Ïýû³Äýù³Åýû³Âýù³Ãýû³§ýµ¹ý³¹ý³¹ýµ¹ÿüµ¹ý³¹ý³¹ýµ¹ýüµ¹ý³¹Ïýµ¹Òý³¹úü³¹ûüµ¹÷üµ¹úü³¹´ý³¹µýµ¹çüµ¹êü³¹äü³¹åüµ¹âü³¹ãüµ¹àü³¹áüµ¹þµ¹þ³¹Éüµ¹Ìü³¹¿üµ¹Âü³¹µþµ¹¸þ³¹«ýµ¹®ý³¹þ³¹þµ¹¯üµ¹²ü³¹£üµ¹¦ü³¹üµ¹ü³¹üµ¹ü³¹ü³¹üµ¹úû³¹ûûµ¹Úû³¹Ûûµ¹Æû³¹Çûµ¹®û³¹¯ûµ¹û³¹ûµ¹û³¹ûµ¹þú³¹ÿúµ¹úú³¹ûúµ¹Þú³¹ßúµ¹Èú³¹Éúµ¹¼ú³¹½úµ¹²ú³¹³úµ¹°ú³¹±úµ¹§ûùï¾þùí¾öùí¾÷ùï¾íùï¾ðùí¾øùí¾ùùï¾ëùï¾îùí¾½úï¾Àúí¾èùí¾éùï¾åùï¾èùí¾¢úí¾£úï¾Õùï¾Øùí¾Òùí¾Óùï¾Ðùí¾Ñùï¾Îùí¾Ïùï¾ñúï¾ôúí¾·ùï¾ºùí¾­ùï¾°ùí¾£ûï¾¦ûí¾úï¾úí¾ôúí¾õúï¾ùï¾ ùí¾ùï¾ùí¾ýøï¾ùí¾÷øï¾úøí¾ðøí¾ñøï¾èøí¾éøï¾Èøí¾Éøï¾´øí¾µøï¾øí¾øï¾øí¾øï¾ö÷í¾÷÷ï¾ì÷í¾í÷ï¾è÷í¾é÷ï¾Ì÷í¾Í÷ï¾¶÷í¾·÷ï¾ª÷í¾«÷ï¾ ÷í¾¡÷ï¾÷í¾÷ï¾§éö©Äìö§Ääö§Äåö©ÄÛö©ÄÞö§Äæö§Äçö©ÄÙö©ÄÜö§Ä«÷©Ä®÷§ÄÖö§Ä×ö©ÄÓö©ÄÖö§Ä÷§Ä÷©ÄÃö©ÄÆö§ÄÀö§ÄÁö©Ä¾ö§Ä¿ö©Ä¼ö§Ä½ö©Äß÷©Äâ÷§Ä¥ö©Ä¨ö§Äö©Äö§Äø©Äø§Ä÷©Ä÷§Äâ÷§Äã÷©Äö©Äö§Äÿõ©Äö§Äëõ©Äîõ§Äåõ©Äèõ§ÄÞõ§Äßõ©ÄÖõ§Ä×õ©Ä¶õ§Ä·õ©Ä¢õ§Ä£õ©Äõ§Äõ©Äøô§Äùô©Ääô§Äåô©ÄÚô§ÄÛô©ÄÖô§Ä×ô©Äºô§Ä»ô©Ä¤ô§Ä¥ô©Äô§Äô©Äô§Äô©Äô§Äô©Ä§×óãÉÚóáÉÒóáÉÓóãÉÉóãÉÌóáÉÔóáÉÕóãÉÇóãÉÊóáÉôãÉôáÉÄóáÉÅóãÉÁóãÉÄóáÉþóáÉÿóãÉ±óãÉ´óáÉ®óáÉ¯óãÉ¬óáÉ­óãÉªóáÉ«óãÉÍôãÉÐôáÉóãÉóáÉóãÉóáÉÿôãÉõáÉõóãÉøóáÉÐôáÉÑôãÉùòãÉüòáÉíòãÉðòáÉÙòãÉÜòáÉÓòãÉÖòáÉÌòáÉÍòãÉÄòáÉÅòãÉ¤òáÉ¥òãÉòáÉòãÉøñáÉùñãÉæñáÉçñãÉÒñáÉÓñãÉÈñáÉÉñãÉÄñáÉÅñãÉ¨ñáÉ©ñãÉñáÉñãÉñáÉñãÉüðáÉýðãÉúðáÉûðãÉ§ÅðÏÈðÏÀðÏÁðÏ·ðÏºðÏÂðÏÃðÏµðÏ¸ðÏñÏñÏ²ðÏ³ðÏ¯ðÏ²ðÏìðÏíðÏðÏ¢ðÏðÏðÏðÏðÏðÏðÏ»ñÏ¾ñÏðÏðÏ÷ïÏúïÏíñÏðñÏãðÏæðÏ¾ñÏ¿ñÏçïÏêïÏÛïÏÞïÏÇïÏÊïÏÁïÏÄïÏºïÏ»ïÏ²ïÏ³ïÏïÏïÏþîÏÿîÏæîÏçîÏÔîÏÕîÏÀîÏÁîÏ¶îÏ·îÏ²îÏ³îÏîÏîÏîÏîÏôíÏõíÏêíÏëíÏèíÏéíÏ§³í×Ô¶íÕÔ®íÕÔ¯í×Ô¥í×Ô¨íÕÔ°íÕÔ±í×Ô£í×Ô¦íÕÔõí×ÔøíÕÔ íÕÔ¡í×Ôí×Ô íÕÔÚíÕÔÛí×Ôí×ÔíÕÔíÕÔí×ÔíÕÔí×ÔíÕÔí×Ô©î×Ô¬îÕÔïì×ÔòìÕÔåì×ÔèìÕÔÛî×ÔÞîÕÔÑí×ÔÔíÕÔ¬îÕÔ­î×ÔÕì×ÔØìÕÔÉì×ÔÌìÕÔµì×Ô¸ìÕÔ¯ì×Ô²ìÕÔ¨ìÕÔ©ì×Ô ìÕÔ¡ì×ÔìÕÔì×ÔìëÕÔíë×ÔÔëÕÔÕë×ÔÂëÕÔÃë×Ô®ëÕÔ¯ë×Ô¤ëÕÔ¥ë×Ô ëÕÔ¡ë×ÔëÕÔë×ÔîêÕÔïê×ÔâêÕÔãê×ÔØêÕÔÙê×ÔÖêÕÔ×ê×Ô§¡êÚ¤êÚêÚêÚêÚêÚêÚêÚêÚêÚãêÚæêÚêÚêÚêÚêÚÈêÚÉêÚûéÚþéÚøéÚùéÚöéÚ÷éÚôéÚõéÚëÚëÚÝéÚàéÚÓéÚÖéÚÉëÚÌëÚ¿êÚÂêÚëÚëÚÃéÚÆéÚ·éÚºéÚ£éÚ¦éÚéÚ éÚéÚéÚéÚéÚîèÚïèÚÚèÚÛèÚÂèÚÃèÚ°èÚ±èÚèÚèÚèÚèÚèÚèÚòçÚóçÚÜçÚÝçÚÐçÚÑçÚÆçÚÇçÚÄçÚÅçÚ§çËßçÉßçÉßçËßçËßçÉßçÉßçËßÿæËßçÉßÑçËßÔçÉßüæÉßýæËßùæËßüæÉß¶çÉß·çËßéæËßìæÉßææÉßçæËßäæÉßåæËßâæÉßãæËßèËßèÉßËæËßÎæÉßÁæËßÄæÉß·èËßºèÉß­çËß°çÉßèÉßèËß±æËß´æÉß¥æËß¨æÉßæËßæÉßæËßæÉßæÉßæËßüåÉßýåËßÜåÉßÝåËßÈåÉßÉåËß°åÉß±åËßåÉßåËßåÉßåËßåÉßåËßüäÉßýäËßàäÉßáäËßÊäÉßËäËß¾äÉß¿äËß´äÉßµäËß²äÉß³äËß§ýãåäåøãåùãåïãåòãåúãåûãåíãåðãå¿äåÂäåêãåëãåçãåêãå¤äå¥äå×ãåÚãåÔãåÕãåÒãåÓãåÐãåÑãåóäåöäå¹ãå¼ãå¯ãå²ãå¥åå¨ååäåäåöäå÷äåãå¢ãåãåãåÿâåãåùâåüâåòâåóâåêâåëâåÊâåËâå¶âå·âåâåâåâåâåøáåùáåîáåïáåêáåëáåÎáåÏáå¸áå¹áå¬áå­áå¢áå£áå áå¡áå§ëà¿êîà½êæà½êçà¿êÝà¿êàà½êèà½êéà¿êÛà¿êÞà½ê­á¿ê°á½êØà½êÙà¿êÕà¿êØà½êá½êá¿êÅà¿êÈà½êÂà½êÃà¿êÀà½êÁà¿ê¾à½ê¿à¿êáá¿êäá½ê§à¿êªà½êà¿ê à½êâ¿êâ½êá¿êá½êäá½êåá¿êà¿êà½êà¿êà½êíß¿êðß½êçß¿êêß½êàß½êáß¿êØß½êÙß¿ê¸ß½ê¹ß¿ê¤ß½ê¥ß¿êß½êß¿êúÞ½êûÞ¿êæÞ½êçÞ¿êÜÞ½êÝÞ¿êØÞ½êÙÞ¿ê¼Þ½ê½Þ¿ê¦Þ½ê§Þ¿êÞ½êÞ¿êÞ½êÞ¿êÞ½êÞ¿ê§ÙÝùïÜÝ÷ïÔÝ÷ïÕÝùïËÝùïÎÝ÷ïÖÝ÷ï×ÝùïÉÝùïÌÝ÷ïÞùïÞ÷ïÆÝ÷ïÇÝùïÃÝùïÆÝ÷ïÞ÷ïÞùï³Ýùï¶Ý÷ï°Ý÷ï±Ýùï®Ý÷ï¯Ýùï¬Ý÷ï­ÝùïÏÞùïÒÞ÷ïÝùïÝ÷ïÝùïÝ÷ïßùïß÷ï÷ÝùïúÝ÷ïÒÞ÷ïÓÞùïûÜùïþÜ÷ïïÜùïòÜ÷ïÛÜùïÞÜ÷ïÕÜùïØÜ÷ïÎÜ÷ïÏÜùïÆÜ÷ïÇÜùï¦Ü÷ï§ÜùïÜ÷ïÜùïúÛ÷ïûÛùïèÛ÷ïéÛùïÔÛ÷ïÕÛùïÊÛ÷ïËÛùïÆÛ÷ïÇÛùïªÛ÷ï«ÛùïÛ÷ïÛùïÛ÷ïÛùïþÚ÷ïÿÚùïüÚ÷ïýÚùï§ÇÚ³õÊÚ±õÂÚ±õÃÚ³õ¹Ú³õ¼Ú±õÄÚ±õÅÚ³õ·Ú³õºÚ±õÛ³õÛ±õ´Ú±õµÚ³õ±Ú³õ´Ú±õîÚ±õïÚ³õ¡Ú³õ¤Ú±õÚ±õÚ³õÚ±õÚ³õÚ±õÚ³õ½Û³õÀÛ±õÚ³õÚ±õùÙ³õüÙ±õïÛ³õòÛ±õåÚ³õèÚ±õÀÛ±õÁÛ³õéÙ³õìÙ±õÝÙ³õàÙ±õÉÙ³õÌÙ±õÃÙ³õÆÙ±õ¼Ù±õ½Ù³õ´Ù±õµÙ³õÙ±õÙ³õÙ±õÙ³õèØ±õéØ³õÖØ±õ×Ø³õÂØ±õÃØ³õ¸Ø±õ¹Ø³õ´Ø±õµØ³õØ±õØ³õØ±õØ³õö×±õ÷×³õì×±õí×³õê×±õë×³õ§µ×íú¸×ëú°×ëú±×íú§×íúª×ëú²×ëú³×íú¥×íú¨×ëú÷×íúú×ëú¢×ëú£×íú×íú¢×ëúÜ×ëúÝ×íú×íú×ëú×ëú×íú×ëú×íú×ëú×íú«Øíú®ØëúñÖíúôÖëúçÖíúêÖëúÝØíúàØëúÓ×íúÖ×ëú®Øëú¯Øíú×ÖíúÚÖëúËÖíúÎÖëú·ÖíúºÖëú±Öíú´ÖëúªÖëú«Öíú¢Öëú£ÖíúÖëúÖíúîÕëúïÕíúÖÕëú×ÕíúÄÕëúÅÕíú°Õëú±Õíú¦Õëú§Õíú¢Õëú£ÕíúÕëúÕíúðÔëúñÔíúäÔëúåÔíúÚÔëúÛÔíúØÔëúÙÔíú§£Ô§¦Ô¥Ô¥Ô§Ô§Ô¥ Ô¥¡Ô§Ô§Ô¥åÔ§èÔ¥Ô¥Ô§Ô§Ô¥ÊÔ¥ËÔ§ýÓ§Ô¥úÓ¥ûÓ§øÓ¥ùÓ§öÓ¥÷Ó§Õ§Õ¥ßÓ§âÓ¥ÕÓ§ØÓ¥ËÕ§ÎÕ¥ÁÔ§ÄÔ¥Õ¥Õ§ÅÓ§ÈÓ¥¹Ó§¼Ó¥¥Ó§¨Ó¥Ó§¢Ó¥Ó¥Ó§Ó¥Ó§ðÒ¥ñÒ§ÜÒ¥ÝÒ§ÄÒ¥ÅÒ§²Ò¥³Ò§Ò¥Ò§Ò¥Ò§Ò¥Ò§ôÑ¥õÑ§ÞÑ¥ßÑ§ÒÑ¥ÓÑ§ÈÑ¥ÉÑ§ÆÑ¥ÇÑ§§ÑáÑßÑßÑáÑáÑßÑßÑáÑáÑßÓÑáÖÑßþÐßÿÐáûÐáþÐß¸Ñß¹ÑáëÐáîÐßèÐßéÐáæÐßçÐáäÐßåÐáÒáÒßÍÐáÐÐßÃÐáÆÐß¹Òá¼Òß¯Ñá²ÑßÒßÒá³Ðá¶Ðß§ÐáªÐßÐáÐßÐáÐßÐßÐáþÏßÿÏáÞÏßßÏáÊÏßËÏá²Ïß³Ïá Ïß¡ÏáÏßÏáÏßÏáþÎßÿÎáâÎßãÎáÌÎßÍÎáÀÎßÁÎá¶Îß·Îá´ÎßµÎá§ÿÍÎúÍûÍñÍôÍüÍýÍïÍòÍÁÎÄÎìÍíÍéÍìÍ¦Î§ÎÙÍÜÍÖÍ×ÍÔÍÕÍÒÍÓÍõÎøÎ»Í¾Í±Í´Í§ÏªÏÎ ÎøÎùÎ¡Í¤ÍÍÍÍÍûÌþÌôÌõÌìÌíÌÌÌÍÌ¸Ì¹Ì Ì¡ÌÌÌúËûËðËñËìËíËÐËÑËºË»Ë®Ë¯Ë¤Ë¥Ë¢Ë£Ë§ÍÐ	»ÐÐ	¹ÈÐ	¹ÉÐ	»¿Ð	»ÂÐ	¹ÊÐ	¹ËÐ	»½Ð	»ÀÐ	¹Ñ	»Ñ	¹ºÐ	¹»Ð	»·Ð	»ºÐ	¹ôÐ	¹õÐ	»§Ð	»ªÐ	¹¤Ð	¹¥Ð	»¢Ð	¹£Ð	» Ð	¹¡Ð	»ÃÑ	»ÆÑ	¹Ð	»Ð	¹ÿÏ	»Ð	¹õÑ	»øÑ	¹ëÐ	»îÐ	¹ÆÑ	¹ÇÑ	»ïÏ	»òÏ	¹ãÏ	»æÏ	¹ÏÏ	»ÒÏ	¹ÉÏ	»ÌÏ	¹ÂÏ	¹ÃÏ	»ºÏ	¹»Ï	»Ï	¹Ï	»Ï	¹Ï	»îÎ	¹ïÎ	»ÜÎ	¹ÝÎ	»ÈÎ	¹ÉÎ	»¾Î	¹¿Î	»ºÎ	¹»Î	»Î	¹Î	»Î	¹Î	»üÍ	¹ýÍ	»òÍ	¹óÍ	»ðÍ	¹ñÍ	»§»Í	õ
+¾Í	ó
+¶Í	ó
+·Í	õ
+­Í	õ
+°Í	ó
+¸Í	ó
+¹Í	õ
+«Í	õ
+®Í	ó
+ýÍ	õ
+Î	ó
+¨Í	ó
+©Í	õ
+¥Í	õ
+¨Í	ó
+âÍ	ó
+ãÍ	õ
+Í	õ
+Í	ó
+Í	ó
+Í	õ
+Í	ó
+Í	õ
+Í	ó
+Í	õ
+±Î	õ
+´Î	ó
+÷Ì	õ
+úÌ	ó
+íÌ	õ
+ðÌ	ó
+ãÎ	õ
+æÎ	ó
+ÙÍ	õ
+ÜÍ	ó
+´Î	ó
+µÎ	õ
+ÝÌ	õ
+àÌ	ó
+ÑÌ	õ
+ÔÌ	ó
+½Ì	õ
+ÀÌ	ó
+·Ì	õ
+ºÌ	ó
+°Ì	ó
+±Ì	õ
+¨Ì	ó
+©Ì	õ
+Ì	ó
+Ì	õ
+ôË	ó
+õË	õ
+ÜË	ó
+ÝË	õ
+ÊË	ó
+ËË	õ
+¶Ë	ó
+·Ë	õ
+¬Ë	ó
+­Ë	õ
+¨Ë	ó
+©Ë	õ
+Ë	ó
+Ë	õ
+öÊ	ó
+÷Ê	õ
+êÊ	ó
+ëÊ	õ
+àÊ	ó
+áÊ	õ
+ÞÊ	ó
+ßÊ	õ
+§©Ê	¯¬Ê	­¤Ê	­¥Ê	¯Ê	¯Ê	­¦Ê	­§Ê	¯Ê	¯Ê	­ëÊ	¯îÊ	­Ê	­Ê	¯Ê	¯Ê	­ÐÊ	­ÑÊ	¯Ê	¯Ê	­Ê	­Ê	¯þÉ	­ÿÉ	¯üÉ	­ýÉ	¯Ë	¯¢Ë	­åÉ	¯èÉ	­ÛÉ	¯ÞÉ	­ÑË	¯ÔË	­ÇÊ	¯ÊÊ	­¢Ë	­£Ë	¯ËÉ	¯ÎÉ	­¿É	¯ÂÉ	­«É	¯®É	­¥É	¯¨É	­É	­É	¯É	­É	¯öÈ	­÷È	¯âÈ	­ãÈ	¯ÊÈ	­ËÈ	¯¸È	­¹È	¯¤È	­¥È	¯È	­È	¯È	­È	¯úÇ	­ûÇ	¯äÇ	­åÇ	¯ØÇ	­ÙÇ	¯ÎÇ	­ÏÇ	¯ÌÇ	­ÍÇ	¯§Ç	éÇ	çÇ	çÇ	éÇ	éÇ	çÇ	çÇ	éÇ	éÇ	çÙÇ	éÜÇ	çÇ	çÇ	éÇ	éÇ	ç¾Ç	ç¿Ç	éñÆ	éôÆ	çîÆ	çïÆ	éìÆ	çíÆ	éêÆ	çëÆ	éÈ	éÈ	çÓÆ	éÖÆ	çÉÆ	éÌÆ	ç¿È	éÂÈ	çµÇ	é¸Ç	çÈ	çÈ	é¹Æ	é¼Æ	ç­Æ	é°Æ	çÆ	éÆ	çÆ	éÆ	çÆ	çÆ	éÆ	çÆ	éäÅ	çåÅ	éÐÅ	çÑÅ	é¸Å	ç¹Å	é¦Å	ç§Å	éÅ	çÅ	éÅ	çÅ	éÅ	çÅ	éèÄ	çéÄ	éÒÄ	çÓÄ	éÆÄ	çÇÄ	é¼Ä	ç½Ä	éºÄ	ç»Ä	é§Ä	£Ä	¡Ä	¡Ä	£÷Ã	£úÃ	¡Ä	¡Ä	£õÃ	£øÃ	¡ÇÄ	£ÊÄ	¡òÃ	¡óÃ	£ïÃ	£òÃ	¡¬Ä	¡­Ä	£ßÃ	£âÃ	¡ÜÃ	¡ÝÃ	£ÚÃ	¡ÛÃ	£ØÃ	¡ÙÃ	£ûÄ	£þÄ	¡ÁÃ	£ÄÃ	¡·Ã	£ºÃ	¡­Å	£°Å	¡£Ä	£¦Ä	¡þÄ	¡ÿÄ	£§Ã	£ªÃ	¡Ã	£Ã	¡Ã	£Ã	¡Ã	£Ã	¡úÂ	¡ûÂ	£òÂ	¡óÂ	£ÒÂ	¡ÓÂ	£¾Â	¡¿Â	£¦Â	¡§Â	£Â	¡Â	£Â	¡Â	£öÁ	¡÷Á	£òÁ	¡óÁ	£ÖÁ	¡×Á	£ÀÁ	¡ÁÁ	£´Á	¡µÁ	£ªÁ	¡«Á	£¨Á	¡©Á	£§óÀ	Ý öÀ	Û îÀ	Û ïÀ	Ý åÀ	Ý èÀ	Û ðÀ	Û ñÀ	Ý ãÀ	Ý æÀ	Û µÁ	Ý ¸Á	Û àÀ	Û áÀ	Ý ÝÀ	Ý àÀ	Û Á	Û Á	Ý ÍÀ	Ý ÐÀ	Û ÊÀ	Û ËÀ	Ý ÈÀ	Û ÉÀ	Ý ÆÀ	Û ÇÀ	Ý éÁ	Ý ìÁ	Û ¯À	Ý ²À	Û ¥À	Ý ¨À	Û Â	Ý Â	Û Á	Ý Á	Û ìÁ	Û íÁ	Ý À	Ý À	Û À	Ý À	Û õ¿	Ý ø¿	Û ï¿	Ý ò¿	Û è¿	Û é¿	Ý à¿	Û á¿	Ý À¿	Û Á¿	Ý ¬¿	Û ­¿	Ý ¿	Û ¿	Ý ¿	Û ¿	Ý î¾	Û ï¾	Ý ä¾	Û å¾	Ý à¾	Û á¾	Ý Ä¾	Û Å¾	Ý ®¾	Û ¯¾	Ý ¢¾	Û £¾	Ý ¾	Û ¾	Ý ¾	Û ¾	Ý §á½	&ä½	&Ü½	&Ý½	&Ó½	&Ö½	&Þ½	&ß½	&Ñ½	&Ô½	&£¾	&¦¾	&Î½	&Ï½	&Ë½	&Î½	&¾	&¾	&»½	&¾½	&¸½	&¹½	&¶½	&·½	&´½	&µ½	&×¾	&Ú¾	&½	& ½	&½	&½	&¿	&¿	&ÿ½	&¾	&Ú¾	&Û¾	&½	&½	&÷¼	&ú¼	&ã¼	&æ¼	&Ý¼	&à¼	&Ö¼	&×¼	&Î¼	&Ï¼	&®¼	&¯¼	&¼	&¼	&¼	&¼	&ð»	&ñ»	&Ü»	&Ý»	&Ò»	&Ó»	&Î»	&Ï»	&²»	&³»	&»	&»	&»	&»	&»	&»	&»	&»	&§Ïº	Ñ+Òº	Ï+Êº	Ï+Ëº	Ñ+Áº	Ñ+Äº	Ï+Ìº	Ï+Íº	Ñ+¿º	Ñ+Âº	Ï+»	Ñ+»	Ï+¼º	Ï+½º	Ñ+¹º	Ñ+¼º	Ï+öº	Ï+÷º	Ñ+©º	Ñ+¬º	Ï+¦º	Ï+§º	Ñ+¤º	Ï+¥º	Ñ+¢º	Ï+£º	Ñ+Å»	Ñ+È»	Ï+º	Ñ+º	Ï+º	Ñ+º	Ï+÷»	Ñ+ú»	Ï+íº	Ñ+ðº	Ï+È»	Ï+É»	Ñ+ñ¹	Ñ+ô¹	Ï+å¹	Ñ+è¹	Ï+Ñ¹	Ñ+Ô¹	Ï+Ë¹	Ñ+Î¹	Ï+Ä¹	Ï+Å¹	Ñ+¼¹	Ï+½¹	Ñ+¹	Ï+¹	Ñ+¹	Ï+¹	Ñ+ð¸	Ï+ñ¸	Ñ+Þ¸	Ï+ß¸	Ñ+Ê¸	Ï+Ë¸	Ñ+À¸	Ï+Á¸	Ñ+¼¸	Ï+½¸	Ñ+ ¸	Ï+¡¸	Ñ+¸	Ï+¸	Ñ+þ·	Ï+ÿ·	Ñ+ô·	Ï+õ·	Ñ+ò·	Ï+ó·	Ñ+§½·	1À·	1¸·	1¹·	1¯·	1²·	1º·	1»·	1­·	1°·	1ÿ·	1¸	1ª·	1«·	1§·	1ª·	1ä·	1å·	1·	1·	1·	1·	1·	1·	1·	1·	1³¸	1¶¸	1ù¶	1ü¶	1ï¶	1ò¶	1å¸	1è¸	1Û·	1Þ·	1¶¸	1·¸	1ß¶	1â¶	1Ó¶	1Ö¶	1¿¶	1Â¶	1¹¶	1¼¶	1²¶	1³¶	1ª¶	1«¶	1¶	1¶	1öµ	1÷µ	1Þµ	1ßµ	1Ìµ	1Íµ	1¸µ	1¹µ	1®µ	1¯µ	1ªµ	1«µ	1µ	1µ	1ø´	1ù´	1ì´	1í´	1â´	1ã´	1à´	1á´	1§«´	Å6®´	Ã6¦´	Ã6§´	Å6´	Å6 ´	Ã6¨´	Ã6©´	Å6´	Å6´	Ã6í´	Å6ð´	Ã6´	Ã6´	Å6´	Å6´	Ã6Ò´	Ã6Ó´	Å6´	Å6´	Ã6´	Ã6´	Å6´	Ã6´	Å6þ³	Ã6ÿ³	Å6¡µ	Å6¤µ	Ã6ç³	Å6ê³	Ã6Ý³	Å6à³	Ã6Óµ	Å6Öµ	Ã6É´	Å6Ì´	Ã6¤µ	Ã6¥µ	Å6Í³	Å6Ð³	Ã6Á³	Å6Ä³	Ã6­³	Å6°³	Ã6§³	Å6ª³	Ã6 ³	Ã6¡³	Å6³	Ã6³	Å6ø²	Ã6ù²	Å6ä²	Ã6å²	Å6Ì²	Ã6Í²	Å6º²	Ã6»²	Å6¦²	Ã6§²	Å6²	Ã6²	Å6²	Ã6²	Å6ü±	Ã6ý±	Å6æ±	Ã6ç±	Å6Ú±	Ã6Û±	Å6Ð±	Ã6Ñ±	Å6Î±	Ã6Ï±	Å6§±	ÿ;±	ý;±	ý;±	ÿ;±	ÿ;±	ý;±	ý;±	ÿ;±	ÿ;±	ý;Û±	ÿ;Þ±	ý;±	ý;±	ÿ;±	ÿ;±	ý;À±	ý;Á±	ÿ;ó°	ÿ;ö°	ý;ð°	ý;ñ°	ÿ;î°	ý;ï°	ÿ;ì°	ý;í°	ÿ;²	ÿ;²	ý;Õ°	ÿ;Ø°	ý;Ë°	ÿ;Î°	ý;Á²	ÿ;Ä²	ý;·±	ÿ;º±	ý;²	ý;²	ÿ;»°	ÿ;¾°	ý;¯°	ÿ;²°	ý;°	ÿ;°	ý;°	ÿ;°	ý;°	ý;°	ÿ;°	ý;°	ÿ;æ¯	ý;ç¯	ÿ;Ò¯	ý;Ó¯	ÿ;º¯	ý;»¯	ÿ;¨¯	ý;©¯	ÿ;¯	ý;¯	ÿ;¯	ý;¯	ÿ;¯	ý;¯	ÿ;ê®	ý;ë®	ÿ;Ô®	ý;Õ®	ÿ;È®	ý;É®	ÿ;¾®	ý;¿®	ÿ;¼®	ý;½®	ÿ;§®	¹A®	·A®	·A®	¹Aù­	¹Aü­	·A®	·A®	¹A÷­	¹Aú­	·AÉ®	¹AÌ®	·Aô­	·Aõ­	¹Añ­	¹Aô­	·A®®	·A¯®	¹Aá­	¹Aä­	·AÞ­	·Aß­	¹AÜ­	·AÝ­	¹AÚ­	·AÛ­	¹Aý®	¹A¯	·AÃ­	¹AÆ­	·A¹­	¹A¼­	·A¯¯	¹A²¯	·A¥®	¹A¨®	·A¯	·A¯	¹A©­	¹A¬­	·A­	¹A ­	·A­	¹A­	·A­	¹A­	·Aü¬	·Aý¬	¹Aô¬	·Aõ¬	¹AÔ¬	·AÕ¬	¹AÀ¬	·AÁ¬	¹A¨¬	·A©¬	¹A¬	·A¬	¹A¬	·A¬	¹Aø«	·Aù«	¹Aô«	·Aõ«	¹AØ«	·AÙ«	¹AÂ«	·AÃ«	¹A¶«	·A·«	¹A¬«	·A­«	¹Aª«	·A««	¹A§õª	óFøª	ñFðª	ñFñª	óFçª	óFêª	ñFòª	ñFóª	óFåª	óFèª	ñF·«	óFº«	ñFâª	ñFãª	óFßª	óFâª	ñF«	ñF«	óFÏª	óFÒª	ñFÌª	ñFÍª	óFÊª	ñFËª	óFÈª	ñFÉª	óFë«	óFî«	ñF±ª	óF´ª	ñF§ª	óFªª	ñF¬	óF ¬	ñF«	óF«	ñFî«	ñFï«	óFª	óFª	ñFª	óFª	ñF÷©	óFú©	ñFñ©	óFô©	ñFê©	ñFë©	óFâ©	ñFã©	óFÂ©	ñFÃ©	óF®©	ñF¯©	óF©	ñF©	óF©	ñF©	óFð¨	ñFñ¨	óFæ¨	ñFç¨	óFâ¨	ñFã¨	óFÆ¨	ñFÇ¨	óF°¨	ñF±¨	óF¤¨	ñF¥¨	óF¨	ñF¨	óF¨	ñF¨	óF§ã§	­Læ§	«LÞ§	«Lß§	­LÕ§	­LØ§	«Là§	«Lá§	­LÓ§	­LÖ§	«L¥¨	­L¨¨	«LÐ§	«LÑ§	­LÍ§	­LÐ§	«L¨	«L¨	­L½§	­LÀ§	«Lº§	«L»§	­L¸§	«L¹§	­L¶§	«L·§	­LÙ¨	­LÜ¨	«L§	­L¢§	«L§	­L§	«L©	­L©	«L¨	­L¨	«LÜ¨	«LÝ¨	­L§	­L§	«Lù¦	­Lü¦	«Lå¦	­Lè¦	«Lß¦	­Lâ¦	«LØ¦	«LÙ¦	­LÐ¦	«LÑ¦	­L°¦	«L±¦	­L¦	«L¦	­L¦	«L¦	­Lò¥	«Ló¥	­LÞ¥	«Lß¥	­LÔ¥	«LÕ¥	­LÐ¥	«LÑ¥	­L´¥	«Lµ¥	­L¥	«L¥	­L¥	«L¥	­L¥	«L¥	­L¥	«L¥	­L§Ñ¤	çQÔ¤	åQÌ¤	åQÍ¤	çQÃ¤	çQÆ¤	åQÎ¤	åQÏ¤	çQÁ¤	çQÄ¤	åQ¥	çQ¥	åQ¾¤	åQ¿¤	çQ»¤	çQ¾¤	åQø¤	åQù¤	çQ«¤	çQ®¤	åQ¨¤	åQ©¤	çQ¦¤	åQ§¤	çQ¤¤	åQ¥¤	çQÇ¥	çQÊ¥	åQ¤	çQ¤	åQ¤	çQ¤	åQù¥	çQü¥	åQï¤	çQò¤	åQÊ¥	åQË¥	çQó£	çQö£	åQç£	çQê£	åQÓ£	çQÖ£	åQÍ£	çQÐ£	åQÆ£	åQÇ£	çQ¾£	åQ¿£	çQ£	åQ£	çQ£	åQ£	çQò¢	åQó¢	çQà¢	åQá¢	çQÌ¢	åQÍ¢	çQÂ¢	åQÃ¢	çQ¾¢	åQ¿¢	çQ¢¢	åQ£¢	çQ¢	åQ¢	çQ¢	åQ¢	çQö¡	åQ÷¡	çQô¡	åQõ¡	çQ§¿¡	¡WÂ¡	Wº¡	W»¡	¡W±¡	¡W´¡	W¼¡	W½¡	¡W¯¡	¡W²¡	W¢	¡W¢	W¬¡	W­¡	¡W©¡	¡W¬¡	Wæ¡	Wç¡	¡W¡	¡W¡	W¡	W¡	¡W¡	W¡	¡W¡	W¡	¡Wµ¢	¡W¸¢	Wû 	¡Wþ 	Wñ 	¡Wô 	Wç¢	¡Wê¢	WÝ¡	¡Wà¡	W¸¢	W¹¢	¡Wá 	¡Wä 	WÕ 	¡WØ 	WÁ 	¡WÄ 	W» 	¡W¾ 	W´ 	Wµ 	¡W¬ 	W­ 	¡W 	W 	¡Wø	Wù	¡Wà	Wá	¡WÎ	WÏ	¡Wº	W»	¡W°	W±	¡W¬	W­	¡W	W	¡Wú	Wû	¡Wî	Wï	¡Wä	Wå	¡Wâ	Wã	¡W§­	Û\°	Ù\¨	Ù\©	Û\	Û\¢	Ù\ª	Ù\«	Û\	Û\ 	Ù\ï	Û\ò	Ù\	Ù\	Û\	Û\	Ù\Ô	Ù\Õ	Û\	Û\	Ù\	Ù\	Û\	Ù\	Û\	Ù\	Û\£	Û\¦	Ù\é	Û\ì	Ù\ß	Û\â	Ù\Õ	Û\Ø	Ù\Ë	Û\Î	Ù\¦	Ù\§	Û\Ï	Û\Ò	Ù\Ã	Û\Æ	Ù\¯	Û\²	Ù\©	Û\¬	Ù\¢	Ù\£	Û\	Ù\	Û\ú	Ù\û	Û\æ	Ù\ç	Û\Î	Ù\Ï	Û\¼	Ù\½	Û\¨	Ù\©	Û\	Ù\	Û\	Ù\	Û\þ	Ù\ÿ	Û\è	Ù\é	Û\Ü	Ù\Ý	Û\Ò	Ù\Ó	Û\Ð	Ù\Ñ	Û\§	b	b	b	b	b	b	b	b	b	bÝ	bà	b	b	b	b	bÂ	bÃ	bõ	bø	bò	bó	bð	bñ	bî	bï	b	b	b×	bÚ	bÍ	bÐ	bÃ	bÆ	b¹	b¼	b	b	b½	bÀ	b±	b´	b	b 	b	b	b	b	b	b	bè	bé	bÔ	bÕ	b¼	b½	bª	b«	b	b	b	b	b	b	bì	bí	bÖ	b×	bÊ	bË	bÀ	bÁ	b¾	b¿	b§	Ïg	Íg	Íg	Ïgû	Ïgþ	Íg	Íg	Ïgù	Ïgü	ÍgË	ÏgÎ	Ígö	Íg÷	Ïgó	Ïgö	Íg°	Íg±	Ïgã	Ïgæ	Ígà	Ígá	ÏgÞ	Ígß	ÏgÜ	ÍgÝ	Ïgÿ	Ïg	ÍgÅ	ÏgÈ	Íg»	Ïg¾	Íg±	Ïg´	Íg§	Ïgª	Íg	Íg	Ïg«	Ïg®	Íg	Ïg¢	Íg	Ïg	Íg	Ïg	Ígþ	Ígÿ	Ïgö	Íg÷	ÏgÖ	Íg×	ÏgÂ	ÍgÃ	Ïgª	Íg«	Ïg	Íg	Ïg	Íg	Ïgú	Ígû	Ïgö	Íg÷	ÏgÚ	ÍgÛ	ÏgÄ	ÍgÅ	Ïg¸	Íg¹	Ïg®	Íg¯	Ïg¬	Íg­	Ïg§÷	mú	mò	mó	mé	mì	mô	mõ	mç	mê	m¹	m¼	mä	må	má	mä	m	m	mÑ	mÔ	mÎ	mÏ	mÌ	mÍ	mÊ	mË	mí	mð	m³	m¶	m©	m¬	m	m¢	m	m	mð	mñ	m	m	m	m	mù	mü	mó	mö	mì	mí	mä	må	mÄ	mÅ	m°	m±	m	m	m	m	mò	mó	mè	mé	mä	må	mÈ	mÉ	m²	m³	m¦	m§	m	m	m	m	m§å	Ãrè	Árà	Árá	Ãr×	ÃrÚ	Árâ	Árã	ÃrÕ	ÃrØ	Ár§	Ãrª	ÁrÒ	ÁrÓ	ÃrÏ	ÃrÒ	Ár	Ár	Ãr¿	ÃrÂ	Ár¼	Ár½	Ãrº	Ár»	Ãr¸	Ár¹	ÃrÛ	ÃrÞ	Ár¡	Ãr¤	Ár	Ãr	Ár	Ãr	Ár	Ãr	ÁrÞ	Árß	Ãr	Ãr	Árû	Ãrþ	Árç	Ãrê	Árá	Ãrä	ÁrÚ	ÁrÛ	ÃrÒ	ÁrÓ	Ãr²	Ár³	Ãr	Ár	Ãr	Ár	Ãrô	Árõ	Ãrà	Árá	ÃrÖ	Ár×	ÃrÒ	ÁrÓ	Ãr¶	Ár·	Ãr 	Ár¡	Ãr	Ár	Ãr	Ár	Ãr	Ár	Ãr§Ó	ýwÖ	ûwÎ	ûwÏ	ýwÅ	ýwÈ	ûwÐ	ûwÑ	ýwÃ	ýwÆ	ûw	ýw	ûwÀ	ûwÁ	ýw½	ýwÀ	ûwú	ûwû	ýw­	ýw°	ûwª	ûw«	ýw¨	ûw©	ýw¦	ûw§	ýwÉ	ýwÌ	ûw	ýw	ûw	ýw	ûwû	ýwþ	ûwñ	ýwô	ûwÌ	ûwÍ	ýwõ	ýwø	ûwé	ýwì	ûwÕ	ýwØ	ûwÏ	ýwÒ	ûwÈ	ûwÉ	ýwÀ	ûwÁ	ýw 	ûw¡	ýw	ûw	ýwô	ûwõ	ýwâ	ûwã	ýwÎ	ûwÏ	ýwÄ	ûwÅ	ýwÀ	ûwÁ	ýw¤	ûw¥	ýw	ûw	ýw	ûw	ýwø	ûwù	ýwö	ûw÷	ýw§Á	·}Ä	µ}¼	µ}½	·}³	·}¶	µ}¾	µ}¿	·}±	·}´	µ}	·}	µ}®	µ}¯	·}«	·}®	µ}è	µ}é	·}	·}	µ}	µ}	·}	µ}	·}	µ}	·}·	·}º	µ}ý	·}	µ}ó	·}ö	µ}é	·}ì	µ}ß	·}â	µ}º	µ}»	·}ã	·}æ	µ}×	·}Ú	µ}Ã	·}Æ	µ}½	·}À	µ}¶	µ}·	·}®	µ}¯	·}	µ}	·}ú	µ}û	·}â	µ}ã	·}Ð	µ}Ñ	·}¼	µ}½	·}²	µ}³	·}®	µ}¯	·}	µ}	·}ü	µ}ý	·}ð	µ}ñ	·}æ	µ}ç	·}ä	µ}å	·}§¯	ñ²	ïª	ï«	ñ¡	ñ¤	ï¬	ï­	ñ	ñ¢	ïñ	ñô	ï	ï	ñ	ñ	ïÖ	ï×	ñ	ñ	ï	ï	ñ	ï	ñ	ï	ñ¥	ñ¨	ïë	ñî	ïá	ñä	ï×	ñÚ	ïÍ	ñÐ	ï¨	ï©	ñÑ	ñÔ	ïÅ	ñÈ	ï±	ñ´	ï«	ñ®	ï¤	ï¥	ñ	ï	ñü	ïý	ñè	ïé	ñÐ	ïÑ	ñ¾	ï¿	ñª	ï«	ñ 	ï¡	ñ	ï	ñ	ï	ñê	ïë	ñÞ	ïß	ñÔ	ïÕ	ñÒ	ïÓ	ñ§	« 	©	©	«	«	©	©	«	«	©ß	«â	©	©	«	«	©Ä	©Å	«÷	«ú	©ô	©õ	«ò	©ó	«ð	©ñ	«	«	©Ù	«Ü	©Ï	«Ò	©Å	«È	©»	«¾	©	©	«¿	«Â	©³	«¶	©	«¢	©	«	©	©	«	©	«ê	©ë	«Ö	©×	«¾	©¿	«¬	©­	«	©	«	©	«	©	«î	©ï	«Ø	©Ù	«Ì	©Í	«Â	©Ã	«À	©Á	«§	å	ã	ã	åý	å	ã	ã	åû	åþ	ãÍ	åÐ	ãø	ãù	åõ	åø	ã²	ã³	åå	åè	ãâ	ãã	åà	ãá	åÞ	ãß	å	å	ãÇ	åÊ	ã½	åÀ	ã³	å¶	ã©	å¬	ã	ã	å­	å°	ã¡	å¤	ã	å	ã	å	ã	ã	åø	ãù	åØ	ãÙ	åÄ	ãÅ	å¬	ã­	å	ã	å	ã	åüÿãýÿåøÿãùÿåÜÿãÝÿåÆÿãÇÿåºÿã»ÿå°ÿã±ÿå®ÿã¯ÿå§ùþüþôþõþëþîþöþ÷þéþìþ»ÿ¾ÿæþçþãþæþ ÿ¡ÿÓþÖþÐþÑþÎþÏþÌþÍþïÿòÿµþ¸þ«þ®þ¡	¤	ÿÿòÿóÿþþþþûýþýõýøýîýïýæýçýÆýÇý²ý³ýýýýýôüõüêüëüæüçüÊüËü´üµü¨ü©üüüüü§çûÙêû×âû×ãûÙÙûÙÜû×äû×åûÙ×ûÙÚû×©üÙ¬ü×Ôû×ÕûÙÑûÙÔû×ü×üÙÁûÙÄû×¾û×¿ûÙ¼û×½ûÙºû×»ûÙÝüÙàü×£ûÙ¦û×ûÙû×ýÙý×üÙü×àü×áüÙûÙû×ýúÙû×éúÙìú×ãúÙæú×Üú×ÝúÙÔú×ÕúÙ´ú×µúÙ ú×¡úÙú×úÙöù×÷ùÙâù×ãùÙØù×ÙùÙÔù×ÕùÙ¸ù×¹ùÙ¢ù×£ùÙù×ùÙù×ùÙù×ùÙ§ÕøØøÐøÑøÇøÊøÒøÓøÅøÈøùùÂøÃø¿øÂøüøýø¯ø²ø¬ø­øªø«ø¨ø©øËùÎùøøøøýùúóøöøÎùÏù÷÷ú÷ë÷î÷×÷Ú÷Ñ÷Ô÷Ê÷Ë÷Â÷Ã÷¢÷£÷÷÷öö÷öäöåöÐöÑöÆöÇöÂöÃö¦ö§öööööúõûõøõùõ§ÃõÍ£ÆõË£¾õË£¿õÍ£µõÍ£¸õË£ÀõË£ÁõÍ£³õÍ£¶õË£öÍ£öË£°õË£±õÍ£­õÍ£°õË£êõË£ëõÍ£õÍ£ õË£õË£õÍ£õË£õÍ£õË£õÍ£¹öÍ£¼öË£ÿôÍ£õË£õôÍ£øôË£ëöÍ£îöË£áõÍ£äõË£¼öË£½öÍ£åôÍ£èôË£ÙôÍ£ÜôË£ÅôÍ£ÈôË£¿ôÍ£ÂôË£¸ôË£¹ôÍ£°ôË£±ôÍ£ôË£ôÍ£üóË£ýóÍ£äóË£åóÍ£ÒóË£ÓóÍ£¾óË£¿óÍ£´óË£µóÍ£°óË£±óÍ£óË£óÍ£þòË£ÿòÍ£òòË£óòÍ£èòË£éòÍ£æòË£çòÍ£§±ò©´ò©¬ò©­ò©£ò©¦ò©®ò©¯ò©¡ò©¤ò©óò©öò©ò©ò©ò©ò©Øò©Ùò©ò©ò©ò©ò©ò©ò©ò©ò©§ó©ªó©íñ©ðñ©ãñ©æñ©Ùó©Üó©Ïò©Òò©ªó©«ó©Óñ©Öñ©Çñ©Êñ©³ñ©¶ñ©­ñ©°ñ©¦ñ©§ñ©ñ©ñ©þð©ÿð©êð©ëð©Òð©Óð©Àð©Áð©¬ð©­ð©¢ð©£ð©ð©ð©ð©ð©ìï©íï©àï©áï©Öï©×ï©Ôï©Õï©§ïÁ®¢ï¿®ï¿®ïÁ®ïÁ®ï¿®ï¿®ïÁ®ïÁ®ï¿®áïÁ®äï¿®ï¿®ïÁ®ïÁ®ï¿®Æï¿®ÇïÁ®ùîÁ®üî¿®öî¿®÷îÁ®ôî¿®õîÁ®òî¿®óîÁ®ðÁ®ð¿®ÛîÁ®Þî¿®ÑîÁ®Ôî¿®ÇðÁ®Êð¿®½ïÁ®Àï¿®ð¿®ðÁ®ÁîÁ®Äî¿®µîÁ®¸î¿®¡îÁ®¤î¿®îÁ®î¿®î¿®îÁ®î¿®îÁ®ìí¿®ííÁ®Øí¿®ÙíÁ®Àí¿®ÁíÁ®®í¿®¯íÁ®í¿®íÁ®í¿®íÁ®í¿®íÁ®ðì¿®ñìÁ®Úì¿®ÛìÁ®Îì¿®ÏìÁ®Äì¿®ÅìÁ®Âì¿®ÃìÁ®§ìû³ìù³ìù³ìû³ÿëû³ìù³ìù³ìû³ýëû³ìù³Ïìû³Òìù³úëù³ûëû³÷ëû³úëù³´ìù³µìû³çëû³êëù³äëù³åëû³âëù³ãëû³àëù³áëû³íû³íù³Éëû³Ìëù³¿ëû³Âëù³µíû³¸íù³«ìû³®ìù³íù³íû³¯ëû³²ëù³£ëû³¦ëù³ëû³ëù³ëû³ëù³ëù³ëû³úêù³ûêû³Úêù³Ûêû³Æêù³Çêû³®êù³¯êû³êù³êû³êù³êû³þéù³ÿéû³úéù³ûéû³Þéù³ßéû³Èéù³Ééû³¼éù³½éû³²éù³³éû³°éù³±éû³§ûèµ¹þè³¹öè³¹÷èµ¹íèµ¹ðè³¹øè³¹ùèµ¹ëèµ¹îè³¹½éµ¹Àé³¹èè³¹éèµ¹åèµ¹èè³¹¢é³¹£éµ¹Õèµ¹Øè³¹Òè³¹Óèµ¹Ðè³¹Ñèµ¹Îè³¹Ïèµ¹ñéµ¹ôé³¹·èµ¹ºè³¹­èµ¹°è³¹£êµ¹¦ê³¹éµ¹é³¹ôé³¹õéµ¹èµ¹ è³¹èµ¹è³¹ýçµ¹è³¹÷çµ¹úç³¹ðç³¹ñçµ¹èç³¹éçµ¹Èç³¹Éçµ¹´ç³¹µçµ¹ç³¹çµ¹ç³¹çµ¹öæ³¹÷æµ¹ìæ³¹íæµ¹èæ³¹éæµ¹Ìæ³¹Íæµ¹¶æ³¹·æµ¹ªæ³¹«æµ¹ æ³¹¡æµ¹æ³¹æµ¹§éåï¾ìåí¾äåí¾ååï¾Ûåï¾Þåí¾æåí¾çåï¾Ùåï¾Üåí¾«æï¾®æí¾Öåí¾×åï¾Óåï¾Öåí¾æí¾æï¾Ãåï¾Æåí¾Àåí¾Áåï¾¾åí¾¿åï¾¼åí¾½åï¾ßæï¾âæí¾¥åï¾¨åí¾åï¾åí¾çï¾çí¾æï¾æí¾âæí¾ãæï¾åï¾åí¾ÿäï¾åí¾ëäï¾îäí¾åäï¾èäí¾Þäí¾ßäï¾Öäí¾×äï¾¶äí¾·äï¾¢äí¾£äï¾äí¾äï¾øãí¾ùãï¾äãí¾åãï¾Úãí¾Ûãï¾Öãí¾×ãï¾ºãí¾»ãï¾¤ãí¾¥ãï¾ãí¾ãï¾ãí¾ãï¾ãí¾ãï¾§×â©ÄÚâ§ÄÒâ§ÄÓâ©ÄÉâ©ÄÌâ§ÄÔâ§ÄÕâ©ÄÇâ©ÄÊâ§Äã©Äã§ÄÄâ§ÄÅâ©ÄÁâ©ÄÄâ§Äþâ§Äÿâ©Ä±â©Ä´â§Ä®â§Ä¯â©Ä¬â§Ä­â©Äªâ§Ä«â©ÄÍã©ÄÐã§Äâ©Äâ§Äâ©Äâ§Äÿã©Ää§Äõâ©Äøâ§ÄÐã§ÄÑã©Äùá©Äüá§Äíá©Äðá§ÄÙá©ÄÜá§ÄÓá©ÄÖá§ÄÌá§ÄÍá©ÄÄá§ÄÅá©Ä¤á§Ä¥á©Äá§Äá©Äøà§Äùà©Äæà§Äçà©ÄÒà§ÄÓà©ÄÈà§ÄÉà©ÄÄà§ÄÅà©Ä¨à§Ä©à©Äà§Äà©Äà§Äà©Äüß§Äýß©Äúß§Äûß©Ä§ÅßãÉÈßáÉÀßáÉÁßãÉ·ßãÉºßáÉÂßáÉÃßãÉµßãÉ¸ßáÉàãÉàáÉ²ßáÉ³ßãÉ¯ßãÉ²ßáÉìßáÉíßãÉßãÉ¢ßáÉßáÉßãÉßáÉßãÉßáÉßãÉ»àãÉ¾àáÉßãÉßáÉ÷ÞãÉúÞáÉíàãÉðàáÉãßãÉæßáÉ¾àáÉ¿àãÉçÞãÉêÞáÉÛÞãÉÞÞáÉÇÞãÉÊÞáÉÁÞãÉÄÞáÉºÞáÉ»ÞãÉ²ÞáÉ³ÞãÉÞáÉÞãÉþÝáÉÿÝãÉæÝáÉçÝãÉÔÝáÉÕÝãÉÀÝáÉÁÝãÉ¶ÝáÉ·ÝãÉ²ÝáÉ³ÝãÉÝáÉÝãÉÝáÉÝãÉôÜáÉõÜãÉêÜáÉëÜãÉèÜáÉéÜãÉ§³ÜÏ¶ÜÏ®ÜÏ¯ÜÏ¥ÜÏ¨ÜÏ°ÜÏ±ÜÏ£ÜÏ¦ÜÏõÜÏøÜÏ ÜÏ¡ÜÏÜÏ ÜÏÚÜÏÛÜÏÜÏÜÏÜÏÜÏÜÏÜÏÜÏÜÏ©ÝÏ¬ÝÏïÛÏòÛÏåÛÏèÛÏÛÝÏÞÝÏÑÜÏÔÜÏ¬ÝÏ­ÝÏÕÛÏØÛÏÉÛÏÌÛÏµÛÏ¸ÛÏ¯ÛÏ²ÛÏ¨ÛÏ©ÛÏ ÛÏ¡ÛÏÛÏÛÏìÚÏíÚÏÔÚÏÕÚÏÂÚÏÃÚÏ®ÚÏ¯ÚÏ¤ÚÏ¥ÚÏ ÚÏ¡ÚÏÚÏÚÏîÙÏïÙÏâÙÏãÙÏØÙÏÙÙÏÖÙÏ×ÙÏ§¡Ù×Ô¤ÙÕÔÙÕÔÙ×ÔÙ×ÔÙÕÔÙÕÔÙ×ÔÙ×ÔÙÕÔãÙ×ÔæÙÕÔÙÕÔÙ×ÔÙ×ÔÙÕÔÈÙÕÔÉÙ×ÔûØ×ÔþØÕÔøØÕÔùØ×ÔöØÕÔ÷Ø×ÔôØÕÔõØ×ÔÚ×ÔÚÕÔÝØ×ÔàØÕÔÓØ×ÔÖØÕÔÉÚ×ÔÌÚÕÔ¿Ù×ÔÂÙÕÔÚÕÔÚ×ÔÃØ×ÔÆØÕÔ·Ø×ÔºØÕÔ£Ø×Ô¦ØÕÔØ×Ô ØÕÔØÕÔØ×ÔØÕÔØ×Ôî×ÕÔï××ÔÚ×ÕÔÛ××ÔÂ×ÕÔÃ××Ô°×ÕÔ±××Ô×ÕÔ××Ô×ÕÔ××Ô×ÕÔ××ÔòÖÕÔóÖ×ÔÜÖÕÔÝÖ×ÔÐÖÕÔÑÖ×ÔÆÖÕÔÇÖ×ÔÄÖÕÔÅÖ×Ô§ÖÚÖÚÖÚÖÚÖÚÖÚÖÚÖÚÿÕÚÖÚÑÖÚÔÖÚüÕÚýÕÚùÕÚüÕÚ¶ÖÚ·ÖÚéÕÚìÕÚæÕÚçÕÚäÕÚåÕÚâÕÚãÕÚ×Ú×ÚËÕÚÎÕÚÁÕÚÄÕÚ·×Úº×Ú­ÖÚ°ÖÚ×Ú×Ú±ÕÚ´ÕÚ¥ÕÚ¨ÕÚÕÚÕÚÕÚÕÚÕÚÕÚüÔÚýÔÚÜÔÚÝÔÚÈÔÚÉÔÚ°ÔÚ±ÔÚÔÚÔÚÔÚÔÚÔÚÔÚüÓÚýÓÚàÓÚáÓÚÊÓÚËÓÚ¾ÓÚ¿ÓÚ´ÓÚµÓÚ²ÓÚ³ÓÚ§ýÒËßÓÉßøÒÉßùÒËßïÒËßòÒÉßúÒÉßûÒËßíÒËßðÒÉß¿ÓËßÂÓÉßêÒÉßëÒËßçÒËßêÒÉß¤ÓÉß¥ÓËß×ÒËßÚÒÉßÔÒÉßÕÒËßÒÒÉßÓÒËßÐÒÉßÑÒËßóÓËßöÓÉß¹ÒËß¼ÒÉß¯ÒËß²ÒÉß¥ÔËß¨ÔÉßÓËßÓÉßöÓÉß÷ÓËßÒËß¢ÒÉßÒËßÒÉßÿÑËßÒÉßùÑËßüÑÉßòÑÉßóÑËßêÑÉßëÑËßÊÑÉßËÑËß¶ÑÉß·ÑËßÑÉßÑËßÑÉßÑËßøÐÉßùÐËßîÐÉßïÐËßêÐÉßëÐËßÎÐÉßÏÐËß¸ÐÉß¹ÐËß¬ÐÉß­ÐËß¢ÐÉß£ÐËß ÐÉß¡ÐËß§ëÏåîÏåæÏåçÏåÝÏåàÏåèÏåéÏåÛÏåÞÏå­Ðå°ÐåØÏåÙÏåÕÏåØÏåÐåÐåÅÏåÈÏåÂÏåÃÏåÀÏåÁÏå¾Ïå¿ÏåáÐåäÐå§ÏåªÏåÏå ÏåÑåÑåÐåÐåäÐååÐåÏåÏåÏåÏåíÎåðÎåçÎåêÎåàÎåáÎåØÎåÙÎå¸Îå¹Îå¤Îå¥ÎåÎåÎåúÍåûÍåæÍåçÍåÜÍåÝÍåØÍåÙÍå¼Íå½Íå¦Íå§ÍåÍåÍåÍåÍåÍåÍå§ÙÌ¿êÜÌ½êÔÌ½êÕÌ¿êËÌ¿êÎÌ½êÖÌ½ê×Ì¿êÉÌ¿êÌÌ½êÍ¿êÍ½êÆÌ½êÇÌ¿êÃÌ¿êÆÌ½êÍ½êÍ¿ê³Ì¿ê¶Ì½ê°Ì½ê±Ì¿ê®Ì½ê¯Ì¿ê¬Ì½ê­Ì¿êÏÍ¿êÒÍ½êÌ¿êÌ½êÌ¿êÌ½êÎ¿êÎ½ê÷Ì¿êúÌ½êÒÍ½êÓÍ¿êûË¿êþË½êïË¿êòË½êÛË¿êÞË½êÕË¿êØË½êÎË½êÏË¿êÆË½êÇË¿ê¦Ë½ê§Ë¿êË½êË¿êúÊ½êûÊ¿êèÊ½êéÊ¿êÔÊ½êÕÊ¿êÊÊ½êËÊ¿êÆÊ½êÇÊ¿êªÊ½ê«Ê¿êÊ½êÊ¿êÊ½êÊ¿êþÉ½êÿÉ¿êüÉ½êýÉ¿ê§ÇÉùïÊÉ÷ïÂÉ÷ïÃÉùï¹Éùï¼É÷ïÄÉ÷ïÅÉùï·ÉùïºÉ÷ïÊùïÊ÷ï´É÷ïµÉùï±Éùï´É÷ïîÉ÷ïïÉùï¡Éùï¤É÷ïÉ÷ïÉùïÉ÷ïÉùïÉ÷ïÉùï½ÊùïÀÊ÷ïÉùïÉ÷ïùÈùïüÈ÷ïïÊùïòÊ÷ïåÉùïèÉ÷ïÀÊ÷ïÁÊùïéÈùïìÈ÷ïÝÈùïàÈ÷ïÉÈùïÌÈ÷ïÃÈùïÆÈ÷ï¼È÷ï½Èùï´È÷ïµÈùïÈ÷ïÈùïÈ÷ïÈùïèÇ÷ïéÇùïÖÇ÷ï×ÇùïÂÇ÷ïÃÇùï¸Ç÷ï¹Çùï´Ç÷ïµÇùïÇ÷ïÇùïÇ÷ïÇùïöÆ÷ï÷ÆùïìÆ÷ïíÆùïêÆ÷ïëÆùï§µÆ³õ¸Æ±õ°Æ±õ±Æ³õ§Æ³õªÆ±õ²Æ±õ³Æ³õ¥Æ³õ¨Æ±õ÷Æ³õúÆ±õ¢Æ±õ£Æ³õÆ³õ¢Æ±õÜÆ±õÝÆ³õÆ³õÆ±õÆ±õÆ³õÆ±õÆ³õÆ±õÆ³õ«Ç³õ®Ç±õñÅ³õôÅ±õçÅ³õêÅ±õÝÇ³õàÇ±õÓÆ³õÖÆ±õ®Ç±õ¯Ç³õ×Å³õÚÅ±õËÅ³õÎÅ±õ·Å³õºÅ±õ±Å³õ´Å±õªÅ±õ«Å³õ¢Å±õ£Å³õÅ±õÅ³õîÄ±õïÄ³õÖÄ±õ×Ä³õÄÄ±õÅÄ³õ°Ä±õ±Ä³õ¦Ä±õ§Ä³õ¢Ä±õ£Ä³õÄ±õÄ³õðÃ±õñÃ³õäÃ±õåÃ³õÚÃ±õÛÃ³õØÃ±õÙÃ³õ§£Ãíú¦ÃëúÃëúÃíúÃíúÃëú Ãëú¡ÃíúÃíúÃëúåÃíúèÃëúÃëúÃíúÃíúÃëúÊÃëúËÃíúýÂíúÃëúúÂëúûÂíúøÂëúùÂíúöÂëú÷ÂíúÄíúÄëúßÂíúâÂëúÕÂíúØÂëúËÄíúÎÄëúÁÃíúÄÃëúÄëúÄíúÅÂíúÈÂëú¹Âíú¼Âëú¥Âíú¨ÂëúÂíú¢ÂëúÂëúÂíúÂëúÂíúðÁëúñÁíúÜÁëúÝÁíúÄÁëúÅÁíú²Áëú³ÁíúÁëúÁíúÁëúÁíúÁëúÁíúôÀëúõÀíúÞÀëúßÀíúÒÀëúÓÀíúÈÀëúÉÀíúÆÀëúÇÀíú§À§À¥À¥À§À§À¥À¥À§À§À¥ÓÀ§ÖÀ¥þ¿¥ÿ¿§û¿§þ¿¥¸À¥¹À§ë¿§î¿¥è¿¥é¿§æ¿¥ç¿§ä¿¥å¿§Á§Á¥Í¿§Ð¿¥Ã¿§Æ¿¥¹Á§¼Á¥¯À§²À¥Á¥Á§³¿§¶¿¥§¿§ª¿¥¿§¿¥¿§¿¥¿¥¿§þ¾¥ÿ¾§Þ¾¥ß¾§Ê¾¥Ë¾§²¾¥³¾§ ¾¥¡¾§¾¥¾§¾¥¾§þ½¥ÿ½§â½¥ã½§Ì½¥Í½§À½¥Á½§¶½¥·½§´½¥µ½§§ÿ¼á½ßú¼ßû¼áñ¼áô¼ßü¼ßý¼áï¼áò¼ßÁ½áÄ½ßì¼ßí¼áé¼áì¼ß¦½ß§½áÙ¼áÜ¼ßÖ¼ß×¼áÔ¼ßÕ¼áÒ¼ßÓ¼áõ½áø½ß»¼á¾¼ß±¼á´¼ß§¾áª¾ß½á ½ßø½ßù½á¡¼á¤¼ß¼á¼ß¼á¼ßû»áþ»ßô»ßõ»áì»ßí»áÌ»ßÍ»á¸»ß¹»á »ß¡»á»ß»áúºßûºáðºßñºáìºßíºáÐºßÑºáººß»ºá®ºß¯ºá¤ºß¥ºá¢ºß£ºá§º
+»º
+¹º
+¹º
+»º
+»º
+¹º
+¹º
+»º
+»º
+¹Õº
+»Øº
+¹º
+¹º
+»ý¹
+»º
+¹ºº
+¹»º
+»í¹
+»ð¹
+¹ê¹
+¹ë¹
+»è¹
+¹é¹
+»æ¹
+¹ç¹
+»»
+»»
+¹Ï¹
+»Ò¹
+¹Å¹
+»È¹
+¹»»
+»¾»
+¹±º
+»´º
+¹»
+¹»
+»µ¹
+»¸¹
+¹©¹
+»¬¹
+¹¹
+»¹
+¹¹
+»¹
+¹¹
+¹¹
+»¹
+¹¹
+»à¸
+¹á¸
+»Ì¸
+¹Í¸
+»´¸
+¹µ¸
+»¢¸
+¹£¸
+»¸
+¹¸
+»¸
+¹¸
+»¸
+¹¸
+»ä·
+¹å·
+»Î·
+¹Ï·
+»Â·
+¹Ã·
+»¸·
+¹¹·
+»¶·
+¹··
+»§·
+õ
+·
+ó
+ü¶
+ó
+ý¶
+õ
+ó¶
+õ
+ö¶
+ó
+þ¶
+ó
+ÿ¶
+õ
+ñ¶
+õ
+ô¶
+ó
+Ã·
+õ
+Æ·
+ó
+î¶
+ó
+ï¶
+õ
+ë¶
+õ
+î¶
+ó
+¨·
+ó
+©·
+õ
+Û¶
+õ
+Þ¶
+ó
+Ø¶
+ó
+Ù¶
+õ
+Ö¶
+ó
+×¶
+õ
+Ô¶
+ó
+Õ¶
+õ
+÷·
+õ
+ú·
+ó
+½¶
+õ
+À¶
+ó
+³¶
+õ
+¶¶
+ó
+©¸
+õ
+¬¸
+ó
+·
+õ
+¢·
+ó
+ú·
+ó
+û·
+õ
+£¶
+õ
+¦¶
+ó
+¶
+õ
+¶
+ó
+¶
+õ
+¶
+ó
+ýµ
+õ
+¶
+ó
+öµ
+ó
+÷µ
+õ
+îµ
+ó
+ïµ
+õ
+Îµ
+ó
+Ïµ
+õ
+ºµ
+ó
+»µ
+õ
+¢µ
+ó
+£µ
+õ
+µ
+ó
+µ
+õ
+ü´
+ó
+ý´
+õ
+ò´
+ó
+ó´
+õ
+î´
+ó
+ï´
+õ
+Ò´
+ó
+Ó´
+õ
+¼´
+ó
+½´
+õ
+°´
+ó
+±´
+õ
+¦´
+ó
+§´
+õ
+¤´
+ó
+¥´
+õ
+§ï³
+¯ò³
+­ê³
+­ë³
+¯á³
+¯ä³
+­ì³
+­í³
+¯ß³
+¯â³
+­±´
+¯´´
+­Ü³
+­Ý³
+¯Ù³
+¯Ü³
+­´
+­´
+¯É³
+¯Ì³
+­Æ³
+­Ç³
+¯Ä³
+­Å³
+¯Â³
+­Ã³
+¯å´
+¯è´
+­«³
+¯®³
+­¡³
+¯¤³
+­µ
+¯µ
+­´
+¯´
+­è´
+­é´
+¯³
+¯³
+­³
+¯³
+­ñ²
+¯ô²
+­ë²
+¯î²
+­ä²
+­å²
+¯Ü²
+­Ý²
+¯¼²
+­½²
+¯¨²
+­©²
+¯²
+­²
+¯þ±
+­ÿ±
+¯ê±
+­ë±
+¯à±
+­á±
+¯Ü±
+­Ý±
+¯À±
+­Á±
+¯ª±
+­«±
+¯±
+­±
+¯±
+­±
+¯±
+­±
+¯§Ý°
+éà°
+çØ°
+çÙ°
+éÏ°
+éÒ°
+çÚ°
+çÛ°
+éÍ°
+éÐ°
+ç±
+é¢±
+çÊ°
+çË°
+éÇ°
+éÊ°
+ç±
+ç±
+é·°
+éº°
+ç´°
+çµ°
+é²°
+ç³°
+é°°
+ç±°
+éÓ±
+éÖ±
+ç°
+é°
+ç°
+é°
+ç²
+é²
+çû°
+éþ°
+çÖ±
+ç×±
+éÿ¯
+é°
+çó¯
+éö¯
+çß¯
+éâ¯
+çÙ¯
+éÜ¯
+çÒ¯
+çÓ¯
+éÊ¯
+çË¯
+éª¯
+ç«¯
+é¯
+ç¯
+éþ®
+çÿ®
+éì®
+çí®
+éØ®
+çÙ®
+éÎ®
+çÏ®
+éÊ®
+çË®
+é®®
+ç¯®
+é®
+ç®
+é®
+ç®
+é®
+ç®
+é®
+ç®
+é§Ë­
+£Î­
+¡Æ­
+¡Ç­
+£½­
+£À­
+¡È­
+¡É­
+£»­
+£¾­
+¡®
+£®
+¡¸­
+¡¹­
+£µ­
+£¸­
+¡ò­
+¡ó­
+£¥­
+£¨­
+¡¢­
+¡£­
+£ ­
+¡¡­
+£­
+¡­
+£Á®
+£Ä®
+¡­
+£­
+¡ý¬
+£­
+¡ó®
+£ö®
+¡é­
+£ì­
+¡Ä®
+¡Å®
+£í¬
+£ð¬
+¡á¬
+£ä¬
+¡Í¬
+£Ð¬
+¡Ç¬
+£Ê¬
+¡À¬
+¡Á¬
+£¸¬
+¡¹¬
+£¬
+¡¬
+£¬
+¡¬
+£ì«
+¡í«
+£Ú«
+¡Û«
+£Æ«
+¡Ç«
+£¼«
+¡½«
+£¸«
+¡¹«
+£«
+¡«
+£«
+¡«
+£úª
+¡ûª
+£ðª
+¡ñª
+£îª
+¡ïª
+£§¹ª
+Ý ¼ª
+Û ´ª
+Û µª
+Ý «ª
+Ý ®ª
+Û ¶ª
+Û ·ª
+Ý ©ª
+Ý ¬ª
+Û ûª
+Ý þª
+Û ¦ª
+Û §ª
+Ý £ª
+Ý ¦ª
+Û àª
+Û áª
+Ý ª
+Ý ª
+Û ª
+Û ª
+Ý ª
+Û ª
+Ý ª
+Û ª
+Ý ¯«
+Ý ²«
+Û õ©
+Ý ø©
+Û ë©
+Ý î©
+Û á«
+Ý ä«
+Û ×ª
+Ý Úª
+Û ²«
+Û ³«
+Ý Û©
+Ý Þ©
+Û Ï©
+Ý Ò©
+Û »©
+Ý ¾©
+Û µ©
+Ý ¸©
+Û ®©
+Û ¯©
+Ý ¦©
+Û §©
+Ý ©
+Û ©
+Ý ò¨
+Û ó¨
+Ý Ú¨
+Û Û¨
+Ý È¨
+Û É¨
+Ý ´¨
+Û µ¨
+Ý ª¨
+Û «¨
+Ý ¦¨
+Û §¨
+Ý ¨
+Û ¨
+Ý ô§
+Û õ§
+Ý è§
+Û é§
+Ý Þ§
+Û ß§
+Ý Ü§
+Û Ý§
+Ý §§§
+&ª§
+&¢§
+&£§
+&§
+&§
+&¤§
+&¥§
+&§
+&§
+&é§
+&ì§
+&§
+&§
+&§
+&§
+&Î§
+&Ï§
+&§
+&§
+&þ¦
+&ÿ¦
+&ü¦
+&ý¦
+&ú¦
+&û¦
+&¨
+& ¨
+&ã¦
+&æ¦
+&Ù¦
+&Ü¦
+&Ï¨
+&Ò¨
+&Å§
+&È§
+& ¨
+&¡¨
+&É¦
+&Ì¦
+&½¦
+&À¦
+&©¦
+&¬¦
+&£¦
+&¦¦
+&¦
+&¦
+&¦
+&¦
+&ô¥
+&õ¥
+&à¥
+&á¥
+&È¥
+&É¥
+&¶¥
+&·¥
+&¢¥
+&£¥
+&¥
+&¥
+&¥
+&¥
+&ø¤
+&ù¤
+&â¤
+&ã¤
+&Ö¤
+&×¤
+&Ì¤
+&Í¤
+&Ê¤
+&Ë¤
+&§¤
+Ñ+¤
+Ï+¤
+Ï+¤
+Ñ+¤
+Ñ+¤
+Ï+¤
+Ï+¤
+Ñ+¤
+Ñ+¤
+Ï+×¤
+Ñ+Ú¤
+Ï+¤
+Ï+¤
+Ñ+ÿ£
+Ñ+¤
+Ï+¼¤
+Ï+½¤
+Ñ+ï£
+Ñ+ò£
+Ï+ì£
+Ï+í£
+Ñ+ê£
+Ï+ë£
+Ñ+è£
+Ï+é£
+Ñ+¥
+Ñ+¥
+Ï+Ñ£
+Ñ+Ô£
+Ï+Ç£
+Ñ+Ê£
+Ï+½¥
+Ñ+À¥
+Ï+³¤
+Ñ+¶¤
+Ï+¥
+Ï+¥
+Ñ+·£
+Ñ+º£
+Ï+«£
+Ñ+®£
+Ï+£
+Ñ+£
+Ï+£
+Ñ+£
+Ï+£
+Ï+£
+Ñ+£
+Ï+£
+Ñ+â¢
+Ï+ã¢
+Ñ+Î¢
+Ï+Ï¢
+Ñ+¶¢
+Ï+·¢
+Ñ+¤¢
+Ï+¥¢
+Ñ+¢
+Ï+¢
+Ñ+¢
+Ï+¢
+Ñ+¢
+Ï+¢
+Ñ+æ¡
+Ï+ç¡
+Ñ+Ð¡
+Ï+Ñ¡
+Ñ+Ä¡
+Ï+Å¡
+Ñ+º¡
+Ï+»¡
+Ñ+¸¡
+Ï+¹¡
+Ñ+§¡
+1¡
+1þ 
+1ÿ 
+1õ 
+1ø 
+1¡
+1¡
+1ó 
+1ö 
+1Å¡
+1È¡
+1ð 
+1ñ 
+1í 
+1ð 
+1ª¡
+1«¡
+1Ý 
+1à 
+1Ú 
+1Û 
+1Ø 
+1Ù 
+1Ö 
+1× 
+1ù¡
+1ü¡
+1¿ 
+1Â 
+1µ 
+1¸ 
+1«¢
+1®¢
+1¡¡
+1¤¡
+1ü¡
+1ý¡
+1¥ 
+1¨ 
+1 
+1 
+1 
+1 
+1ÿ
+1 
+1ø
+1ù
+1ð
+1ñ
+1Ð
+1Ñ
+1¼
+1½
+1¤
+1¥
+1
+1
+1þ
+1ÿ
+1ô
+1õ
+1ð
+1ñ
+1Ô
+1Õ
+1¾
+1¿
+1²
+1³
+1¨
+1©
+1¦
+1§
+1§ñ
+Å6ô
+Ã6ì
+Ã6í
+Å6ã
+Å6æ
+Ã6î
+Ã6ï
+Å6á
+Å6ä
+Ã6³
+Å6¶
+Ã6Þ
+Ã6ß
+Å6Û
+Å6Þ
+Ã6
+Ã6
+Å6Ë
+Å6Î
+Ã6È
+Ã6É
+Å6Æ
+Ã6Ç
+Å6Ä
+Ã6Å
+Å6ç
+Å6ê
+Ã6­
+Å6°
+Ã6£
+Å6¦
+Ã6
+Å6
+Ã6
+Å6
+Ã6ê
+Ã6ë
+Å6
+Å6
+Ã6
+Å6
+Ã6ó
+Å6ö
+Ã6í
+Å6ð
+Ã6æ
+Ã6ç
+Å6Þ
+Ã6ß
+Å6¾
+Ã6¿
+Å6ª
+Ã6«
+Å6
+Ã6
+Å6
+Ã6
+Å6ì
+Ã6í
+Å6â
+Ã6ã
+Å6Þ
+Ã6ß
+Å6Â
+Ã6Ã
+Å6¬
+Ã6­
+Å6 
+Ã6¡
+Å6
+Ã6
+Å6
+Ã6
+Å6§ß
+ÿ;â
+ý;Ú
+ý;Û
+ÿ;Ñ
+ÿ;Ô
+ý;Ü
+ý;Ý
+ÿ;Ï
+ÿ;Ò
+ý;¡
+ÿ;¤
+ý;Ì
+ý;Í
+ÿ;É
+ÿ;Ì
+ý;
+ý;
+ÿ;¹
+ÿ;¼
+ý;¶
+ý;·
+ÿ;´
+ý;µ
+ÿ;²
+ý;³
+ÿ;Õ
+ÿ;Ø
+ý;
+ÿ;
+ý;
+ÿ;
+ý;
+ÿ;
+ý;ý
+ÿ;
+ý;Ø
+ý;Ù
+ÿ;
+ÿ;
+ý;õ
+ÿ;ø
+ý;á
+ÿ;ä
+ý;Û
+ÿ;Þ
+ý;Ô
+ý;Õ
+ÿ;Ì
+ý;Í
+ÿ;¬
+ý;­
+ÿ;
+ý;
+ÿ;
+ý;
+ÿ;î
+ý;ï
+ÿ;Ú
+ý;Û
+ÿ;Ð
+ý;Ñ
+ÿ;Ì
+ý;Í
+ÿ;°
+ý;±
+ÿ;
+ý;
+ÿ;
+ý;
+ÿ;
+ý;
+ÿ;
+ý;
+ÿ;§Í
+¹AÐ
+·AÈ
+·AÉ
+¹A¿
+¹AÂ
+·AÊ
+·AË
+¹A½
+¹AÀ
+·A
+¹A
+·Aº
+·A»
+¹A·
+¹Aº
+·Aô
+·Aõ
+¹A§
+¹Aª
+·A¤
+·A¥
+¹A¢
+·A£
+¹A 
+·A¡
+¹AÃ
+¹AÆ
+·A
+¹A
+·Aÿ
+¹A
+·Aõ
+¹Aø
+·Aë
+¹Aî
+·AÆ
+·AÇ
+¹Aï
+¹Aò
+·Aã
+¹Aæ
+·AÏ
+¹AÒ
+·AÉ
+¹AÌ
+·AÂ
+·AÃ
+¹Aº
+·A»
+¹A
+·A
+¹A
+·A
+¹Aî
+·Aï
+¹AÜ
+·AÝ
+¹AÈ
+·AÉ
+¹A¾
+·A¿
+¹Aº
+·A»
+¹A
+·A
+¹A
+·A
+¹Aü
+·Aý
+¹Aò
+·Aó
+¹Að
+·Añ
+¹A§»
+óF¾
+ñF¶
+ñF·
+óF­
+óF°
+ñF¸
+ñF¹
+óF«
+óF®
+ñFý
+óF
+ñF¨
+ñF©
+óF¥
+óF¨
+ñFâ
+ñFã
+óF
+óF
+ñF
+ñF
+óF
+ñF
+óF
+ñF
+óF±
+óF´
+ñF÷
+óFú
+ñFí
+óFð
+ñFã
+óFæ
+ñFÙ
+óFÜ
+ñF´
+ñFµ
+óFÝ
+óFà
+ñFÑ
+óFÔ
+ñF½
+óFÀ
+ñF·
+óFº
+ñF°
+ñF±
+óF¨
+ñF©
+óF
+ñF
+óFô
+ñFõ
+óFÜ
+ñFÝ
+óFÊ
+ñFË
+óF¶
+ñF·
+óF¬
+ñF­
+óF¨
+ñF©
+óF
+ñF
+óFö
+ñF÷
+óFê
+ñFë
+óFà
+ñFá
+óFÞ
+ñFß
+óF§©
+­L¬
+«L¤
+«L¥
+­L
+­L
+«L¦
+«L§
+­L
+­L
+«Lë
+­Lî
+«L
+«L
+­L
+­L
+«LÐ
+«LÑ
+­L
+­L
+«L
+«L
+­Lþ
+«Lÿ
+­Lü
+«Lý
+­L
+­L¢
+«Lå
+­Lè
+«LÛ
+­LÞ
+«LÑ
+­LÔ
+«LÇ
+­LÊ
+«L¢
+«L£
+­LË
+­LÎ
+«L¿
+­LÂ
+«L«
+­L®
+«L¥
+­L¨
+«L
+«L
+­L
+«L
+­Lö
+«L÷
+­Lâ
+«Lã
+­LÊ
+«LË
+­L¸
+«L¹
+­L¤
+«L¥
+­L
+«L
+­L
+«L
+­Lú
+«Lû
+­Lä
+«Lå
+­LØ
+«LÙ
+­LÎ
+«LÏ
+­LÌ
+«LÍ
+­L§
+çQ
+åQ
+åQ
+çQ
+çQ
+åQ
+åQ
+çQ
+çQ
+åQÙ
+çQÜ
+åQ
+åQ
+çQ
+çQ
+åQ¾
+åQ¿
+çQñ
+çQô
+åQî
+åQï
+çQì
+åQí
+çQê
+åQë
+çQ
+çQ
+åQÓ
+çQÖ
+åQÉ
+çQÌ
+åQ¿
+çQÂ
+åQµ
+çQ¸
+åQ
+åQ
+çQ¹
+çQ¼
+åQ­
+çQ°
+åQ
+çQ
+åQ
+çQ
+åQ
+åQ
+çQ
+åQ
+çQä
+åQå
+çQÐ
+åQÑ
+çQ¸
+åQ¹
+çQ¦
+åQ§
+çQ
+åQ
+çQ
+åQ
+çQ
+åQ
+çQè
+åQé
+çQÒ
+åQÓ
+çQÆ
+åQÇ
+çQ¼
+åQ½
+çQº
+åQ»
+çQ§
+¡W
+W
+W
+¡W÷
+¡Wú
+W
+W
+¡Wõ
+¡Wø
+WÇ
+¡WÊ
+Wò
+Wó
+¡Wï
+¡Wò
+W¬
+W­
+¡Wß
+¡Wâ
+WÜ
+WÝ
+¡WÚ
+WÛ
+¡WØ
+WÙ
+¡Wû
+¡Wþ
+WÁ
+¡WÄ
+W·
+¡Wº
+W­
+¡W°
+W£
+¡W¦
+Wþ
+Wÿ
+¡W§
+¡Wª
+W
+¡W
+W
+¡W
+W
+¡W
+Wú
+Wû
+¡Wò
+Wó
+¡WÒ
+WÓ
+¡W¾
+W¿
+¡W¦
+W§
+¡W
+W
+¡W
+W
+¡Wö
+W÷
+¡Wò
+Wó
+¡WÖ
+W×
+¡WÀ
+WÁ
+¡W´
+Wµ
+¡Wª
+W«
+¡W¨
+W©
+¡W§ó
+Û\ö
+Ù\î
+Ù\ï
+Û\å
+Û\è
+Ù\ð
+Ù\ñ
+Û\ã
+Û\æ
+Ù\µ
+Û\¸
+Ù\à
+Ù\á
+Û\Ý
+Û\à
+Ù\
+Ù\
+Û\Í
+Û\Ð
+Ù\Ê
+Ù\Ë
+Û\È
+Ù\É
+Û\Æ
+Ù\Ç
+Û\é
+Û\ì
+Ù\¯
+Û\²
+Ù\¥
+Û\¨
+Ù\
+Û\
+Ù\
+Û\
+Ù\ì
+Ù\í
+Û\
+Û\
+Ù\
+Û\
+Ù\õ
+Û\ø
+Ù\ï
+Û\ò
+Ù\è
+Ù\é
+Û\à
+Ù\á
+Û\À
+Ù\Á
+Û\¬
+Ù\­
+Û\
+Ù\
+Û\
+Ù\
+Û\î
+Ù\ï
+Û\ä
+Ù\å
+Û\à
+Ù\á
+Û\Ä
+Ù\Å
+Û\®
+Ù\¯
+Û\¢
+Ù\£
+Û\
+Ù\
+Û\
+Ù\
+Û\§á
+bä
+bÜ
+bÝ
+bÓ
+bÖ
+bÞ
+bß
+bÑ
+bÔ
+b£
+b¦
+bÎ
+bÏ
+bË
+bÎ
+b
+b
+b»
+b¾
+b¸
+b¹
+b¶
+b·
+b´
+bµ
+b×
+bÚ
+b
+b 
+b
+b
+b
+b
+bÿ
+b
+bÚ
+bÛ
+b
+b
+b÷
+bú
+bã
+bæ
+bÝ
+bà
+bÖ
+b×
+bÎ
+bÏ
+b®
+b¯
+b
+b
+b
+b
+bð
+bñ
+bÜ
+bÝ
+bÒ
+bÓ
+bÎ
+bÏ
+b²
+b³
+b
+b
+b
+b
+b
+b
+b
+b
+b§Ï
+ÏgÒ
+ÍgÊ
+ÍgË
+ÏgÁ
+ÏgÄ
+ÍgÌ
+ÍgÍ
+Ïg¿
+ÏgÂ
+Íg
+Ïg
+Íg¼
+Íg½
+Ïg¹
+Ïg¼
+Ígö
+Íg÷
+Ïg©
+Ïg¬
+Íg¦
+Íg§
+Ïg¤
+Íg¥
+Ïg¢
+Íg£
+ÏgÅ
+ÏgÈ
+Íg
+Ïg
+Íg
+Ïg
+Íg÷
+Ïgú
+Ígí
+Ïgð
+ÍgÈ
+ÍgÉ
+Ïgñ
+Ïgô
+Ígå
+Ïgè
+ÍgÑ
+ÏgÔ
+ÍgË
+ÏgÎ
+ÍgÄ
+ÍgÅ
+Ïg¼
+Íg½
+Ïg
+Íg
+Ïg
+Íg
+Ïgðÿ	Ígñÿ	ÏgÞÿ	Ígßÿ	ÏgÊÿ	ÍgËÿ	ÏgÀÿ	ÍgÁÿ	Ïg¼ÿ	Íg½ÿ	Ïg ÿ	Íg¡ÿ	Ïgÿ	Ígÿ	Ïgþþ	Ígÿþ	Ïgôþ	Ígõþ	Ïgòþ	Ígóþ	Ïg§½þ	mÀþ	m¸þ	m¹þ	m¯þ	m²þ	mºþ	m»þ	m­þ	m°þ	mÿþ	mÿ	mªþ	m«þ	m§þ	mªþ	mäþ	måþ	mþ	mþ	mþ	mþ	mþ	mþ	mþ	mþ	m³ÿ	m¶ÿ	mùý	müý	mïý	mòý	måÿ	mèÿ	mÛþ	mÞþ	m¶ÿ	m·ÿ	mßý	mâý	mÓý	mÖý	m¿ý	mÂý	m¹ý	m¼ý	m²ý	m³ý	mªý	m«ý	mý	mý	möü	m÷ü	mÞü	mßü	mÌü	mÍü	m¸ü	m¹ü	m®ü	m¯ü	mªü	m«ü	mü	mü	møû	mùû	mìû	míû	mâû	mãû	màû	máû	m§«û	Ãr®û	Ár¦û	Ár§û	Ãrû	Ãr û	Ár¨û	Ár©û	Ãrû	Ãrû	Áríû	Ãrðû	Árû	Árû	Ãrû	Ãrû	ÁrÒû	ÁrÓû	Ãrû	Ãrû	Árû	Árû	Ãrû	Árû	Ãrþú	Árÿú	Ãr¡ü	Ãr¤ü	Árçú	Ãrêú	ÁrÝú	Ãràú	ÁrÓü	ÃrÖü	ÁrÉû	ÃrÌû	Ár¤ü	Ár¥ü	ÃrÍú	ÃrÐú	ÁrÁú	ÃrÄú	Ár­ú	Ãr°ú	Ár§ú	Ãrªú	Ár ú	Ár¡ú	Ãrú	Árú	Ãrøù	Árùù	Ãräù	Áråù	ÃrÌù	ÁrÍù	Ãrºù	Ár»ù	Ãr¦ù	Ár§ù	Ãrù	Árù	Ãrù	Árù	Ãrüø	Árýø	Ãræø	Árçø	ÃrÚø	ÁrÛø	ÃrÐø	ÁrÑø	ÃrÎø	ÁrÏø	Ãr§ø	ýwø	ûwø	ûwø	ýwø	ýwø	ûwø	ûwø	ýwø	ýwø	ûwÛø	ýwÞø	ûwø	ûwø	ýwø	ýwø	ûwÀø	ûwÁø	ýwó÷	ýwö÷	ûwð÷	ûwñ÷	ýwî÷	ûwï÷	ýwì÷	ûwí÷	ýwù	ýwù	ûwÕ÷	ýwØ÷	ûwË÷	ýwÎ÷	ûwÁù	ýwÄù	ûw·ø	ýwºø	ûwù	ûwù	ýw»÷	ýw¾÷	ûw¯÷	ýw²÷	ûw÷	ýw÷	ûw÷	ýw÷	ûw÷	ûw÷	ýw÷	ûw÷	ýwæö	ûwçö	ýwÒö	ûwÓö	ýwºö	ûw»ö	ýw¨ö	ûw©ö	ýwö	ûwö	ýwö	ûwö	ýwö	ûwö	ýwêõ	ûwëõ	ýwÔõ	ûwÕõ	ýwÈõ	ûwÉõ	ýw¾õ	ûw¿õ	ýw¼õ	ûw½õ	ýw§õ	·}õ	µ}õ	µ}õ	·}ùô	·}üô	µ}õ	µ}õ	·}÷ô	·}úô	µ}Éõ	·}Ìõ	µ}ôô	µ}õô	·}ñô	·}ôô	µ}®õ	µ}¯õ	·}áô	·}äô	µ}Þô	µ}ßô	·}Üô	µ}Ýô	·}Úô	µ}Ûô	·}ýõ	·}ö	µ}Ãô	·}Æô	µ}¹ô	·}¼ô	µ}¯ö	·}²ö	µ}¥õ	·}¨õ	µ}ö	µ}ö	·}©ô	·}¬ô	µ}ô	·} ô	µ}ô	·}ô	µ}ô	·}ô	µ}üó	µ}ýó	·}ôó	µ}õó	·}Ôó	µ}Õó	·}Àó	µ}Áó	·}¨ó	µ}©ó	·}ó	µ}ó	·}ó	µ}ó	·}øò	µ}ùò	·}ôò	µ}õò	·}Øò	µ}Ùò	·}Âò	µ}Ãò	·}¶ò	µ}·ò	·}¬ò	µ}­ò	·}ªò	µ}«ò	·}§õñ	ñøñ	ïðñ	ïññ	ñçñ	ñêñ	ïòñ	ïóñ	ñåñ	ñèñ	ï·ò	ñºò	ïâñ	ïãñ	ñßñ	ñâñ	ïò	ïò	ñÏñ	ñÒñ	ïÌñ	ïÍñ	ñÊñ	ïËñ	ñÈñ	ïÉñ	ñëò	ñîò	ï±ñ	ñ´ñ	ï§ñ	ñªñ	ïó	ñ ó	ïò	ñò	ïîò	ïïò	ññ	ññ	ïñ	ññ	ï÷ð	ñúð	ïñð	ñôð	ïêð	ïëð	ñâð	ïãð	ñÂð	ïÃð	ñ®ð	ï¯ð	ñð	ïð	ñð	ïð	ñðï	ïñï	ñæï	ïçï	ñâï	ïãï	ñÆï	ïÇï	ñ°ï	ï±ï	ñ¤ï	ï¥ï	ñï	ïï	ñï	ïï	ñ§ãî	«æî	©Þî	©ßî	«Õî	«Øî	©àî	©áî	«Óî	«Öî	©¥ï	«¨ï	©Ðî	©Ñî	«Íî	«Ðî	©ï	©ï	«½î	«Àî	©ºî	©»î	«¸î	©¹î	«¶î	©·î	«Ùï	«Üï	©î	«¢î	©î	«î	©ð	«ð	©ï	«ï	©Üï	©Ýï	«î	«î	©ùí	«üí	©åí	«èí	©ßí	«âí	©Øí	©Ùí	«Ðí	©Ñí	«°í	©±í	«í	©í	«í	©í	«òì	©óì	«Þì	©ßì	«Ôì	©Õì	«Ðì	©Ñì	«´ì	©µì	«ì	©ì	«ì	©ì	«ì	©ì	«ì	©ì	«§Ñë	åÔë	ãÌë	ãÍë	åÃë	åÆë	ãÎë	ãÏë	åÁë	åÄë	ãì	åì	ã¾ë	ã¿ë	å»ë	å¾ë	ãøë	ãùë	å«ë	å®ë	ã¨ë	ã©ë	å¦ë	ã§ë	å¤ë	ã¥ë	åÇì	åÊì	ãë	åë	ãë	åë	ãùì	åüì	ãïë	åòë	ãÊì	ãËì	åóê	åöê	ãçê	åêê	ãÓê	åÖê	ãÍê	åÐê	ãÆê	ãÇê	å¾ê	ã¿ê	åê	ãê	åê	ãê	åòé	ãóé	åàé	ãáé	åÌé	ãÍé	åÂé	ãÃé	å¾é	ã¿é	å¢é	ã£é	åé	ãé	åé	ãé	åöè	ã÷è	åôè	ãõè	å§¿è	Âè	ºè	»è	±è	´è	¼è	½è	¯è	²è	é	é	¬è	­è	©è	¬è	æè	çè	è	è	è	è	è	è	è	è	µé	¸é	ûç	þç	ñç	ôç	çé	êé	Ýè	àè	¸é	¹é	áç	äç	Õç	Øç	Áç	Äç	»ç	¾ç	´ç	µç	¬ç	­ç	ç	ç	øæ	ùæ	àæ	áæ	Îæ	Ïæ	ºæ	»æ	°æ	±æ	¬æ	­æ	æ	æ	úå	ûå	îå	ïå	äå	åå	âå	ãå	§­å	Ù°å	×¨å	×©å	Ùå	Ù¢å	×ªå	×«å	Ùå	Ù å	×ïå	Ùòå	×å	×å	Ùå	Ùå	×Ôå	×Õå	Ùå	Ùå	×å	×å	Ùå	×å	Ùå	×å	Ù£æ	Ù¦æ	×éä	Ùìä	×ßä	Ùâä	×Õæ	ÙØæ	×Ëå	ÙÎå	×¦æ	×§æ	ÙÏä	ÙÒä	×Ãä	ÙÆä	×¯ä	Ù²ä	×©ä	Ù¬ä	×¢ä	×£ä	Ùä	×ä	Ùúã	×ûã	Ùæã	×çã	ÙÎã	×Ïã	Ù¼ã	×½ã	Ù¨ã	×©ã	Ùã	×ã	Ùã	×ã	Ùþâ	×ÿâ	Ùèâ	×éâ	ÙÜâ	×Ýâ	ÙÒâ	×Óâ	ÙÐâ	×Ñâ	Ù§â	â	â	â	â	â	â	â	â	â	Ýâ	àâ	â	â	â	â	Ââ	Ãâ	õá	øá	òá	óá	ðá	ñá	îá	ïá	ã	ã	×á	Úá	Íá	Ðá	Ãã	Æã	¹â	¼â	ã	ã	½á	Àá	±á	´á	á	 á	á	á	á	á	á	á	èà	éà	Ôà	Õà	¼à	½à	ªà	«à	à	à	à	à	à	à	ìß	íß	Öß	×ß	Êß	Ëß	Àß	Áß	¾ß	¿ß	§ß	Í£ß	Ë£ß	Ë£ß	Í£ûÞ	Í£þÞ	Ë£ß	Ë£ß	Í£ùÞ	Í£üÞ	Ë£Ëß	Í£Îß	Ë£öÞ	Ë£÷Þ	Í£óÞ	Í£öÞ	Ë£°ß	Ë£±ß	Í£ãÞ	Í£æÞ	Ë£àÞ	Ë£áÞ	Í£ÞÞ	Ë£ßÞ	Í£ÜÞ	Ë£ÝÞ	Í£ÿß	Í£à	Ë£ÅÞ	Í£ÈÞ	Ë£»Þ	Í£¾Þ	Ë£±à	Í£´à	Ë£§ß	Í£ªß	Ë£à	Ë£à	Í£«Þ	Í£®Þ	Ë£Þ	Í£¢Þ	Ë£Þ	Í£Þ	Ë£Þ	Í£Þ	Ë£þÝ	Ë£ÿÝ	Í£öÝ	Ë£÷Ý	Í£ÖÝ	Ë£×Ý	Í£ÂÝ	Ë£ÃÝ	Í£ªÝ	Ë£«Ý	Í£Ý	Ë£Ý	Í£Ý	Ë£Ý	Í£úÜ	Ë£ûÜ	Í£öÜ	Ë£÷Ü	Í£ÚÜ	Ë£ÛÜ	Í£ÄÜ	Ë£ÅÜ	Í£¸Ü	Ë£¹Ü	Í£®Ü	Ë£¯Ü	Í£¬Ü	Ë£­Ü	Í£§÷Û	©úÛ	©òÛ	©óÛ	©éÛ	©ìÛ	©ôÛ	©õÛ	©çÛ	©êÛ	©¹Ü	©¼Ü	©äÛ	©åÛ	©áÛ	©äÛ	©Ü	©Ü	©ÑÛ	©ÔÛ	©ÎÛ	©ÏÛ	©ÌÛ	©ÍÛ	©ÊÛ	©ËÛ	©íÜ	©ðÜ	©³Û	©¶Û	©©Û	©¬Û	©Ý	©¢Ý	©Ü	©Ü	©ðÜ	©ñÜ	©Û	©Û	©Û	©Û	©ùÚ	©üÚ	©óÚ	©öÚ	©ìÚ	©íÚ	©äÚ	©åÚ	©ÄÚ	©ÅÚ	©°Ú	©±Ú	©Ú	©Ú	©Ú	©Ú	©òÙ	©óÙ	©èÙ	©éÙ	©äÙ	©åÙ	©ÈÙ	©ÉÙ	©²Ù	©³Ù	©¦Ù	©§Ù	©Ù	©Ù	©Ù	©Ù	©§åØ	Á®èØ	¿®àØ	¿®áØ	Á®×Ø	Á®ÚØ	¿®âØ	¿®ãØ	Á®ÕØ	Á®ØØ	¿®§Ù	Á®ªÙ	¿®ÒØ	¿®ÓØ	Á®ÏØ	Á®ÒØ	¿®Ù	¿®Ù	Á®¿Ø	Á®ÂØ	¿®¼Ø	¿®½Ø	Á®ºØ	¿®»Ø	Á®¸Ø	¿®¹Ø	Á®ÛÙ	Á®ÞÙ	¿®¡Ø	Á®¤Ø	¿®Ø	Á®Ø	¿®Ú	Á®Ú	¿®Ù	Á®Ù	¿®ÞÙ	¿®ßÙ	Á®Ø	Á®Ø	¿®û×	Á®þ×	¿®ç×	Á®ê×	¿®á×	Á®ä×	¿®Ú×	¿®Û×	Á®Ò×	¿®Ó×	Á®²×	¿®³×	Á®×	¿®×	Á®×	¿®×	Á®ôÖ	¿®õÖ	Á®àÖ	¿®áÖ	Á®ÖÖ	¿®×Ö	Á®ÒÖ	¿®ÓÖ	Á®¶Ö	¿®·Ö	Á® Ö	¿®¡Ö	Á®Ö	¿®Ö	Á®Ö	¿®Ö	Á®Ö	¿®Ö	Á®§ÓÕ	û³ÖÕ	ù³ÎÕ	ù³ÏÕ	û³ÅÕ	û³ÈÕ	ù³ÐÕ	ù³ÑÕ	û³ÃÕ	û³ÆÕ	ù³Ö	û³Ö	ù³ÀÕ	ù³ÁÕ	û³½Õ	û³ÀÕ	ù³úÕ	ù³ûÕ	û³­Õ	û³°Õ	ù³ªÕ	ù³«Õ	û³¨Õ	ù³©Õ	û³¦Õ	ù³§Õ	û³ÉÖ	û³ÌÖ	ù³Õ	û³Õ	ù³Õ	û³Õ	ù³ûÖ	û³þÖ	ù³ñÕ	û³ôÕ	ù³ÌÖ	ù³ÍÖ	û³õÔ	û³øÔ	ù³éÔ	û³ìÔ	ù³ÕÔ	û³ØÔ	ù³ÏÔ	û³ÒÔ	ù³ÈÔ	ù³ÉÔ	û³ÀÔ	ù³ÁÔ	û³ Ô	ù³¡Ô	û³Ô	ù³Ô	û³ôÓ	ù³õÓ	û³âÓ	ù³ãÓ	û³ÎÓ	ù³ÏÓ	û³ÄÓ	ù³ÅÓ	û³ÀÓ	ù³ÁÓ	û³¤Ó	ù³¥Ó	û³Ó	ù³Ó	û³Ó	ù³Ó	û³øÒ	ù³ùÒ	û³öÒ	ù³÷Ò	û³§ÁÒ	µ¹ÄÒ	³¹¼Ò	³¹½Ò	µ¹³Ò	µ¹¶Ò	³¹¾Ò	³¹¿Ò	µ¹±Ò	µ¹´Ò	³¹Ó	µ¹Ó	³¹®Ò	³¹¯Ò	µ¹«Ò	µ¹®Ò	³¹èÒ	³¹éÒ	µ¹Ò	µ¹Ò	³¹Ò	³¹Ò	µ¹Ò	³¹Ò	µ¹Ò	³¹Ò	µ¹·Ó	µ¹ºÓ	³¹ýÑ	µ¹Ò	³¹óÑ	µ¹öÑ	³¹éÓ	µ¹ìÓ	³¹ßÒ	µ¹âÒ	³¹ºÓ	³¹»Ó	µ¹ãÑ	µ¹æÑ	³¹×Ñ	µ¹ÚÑ	³¹ÃÑ	µ¹ÆÑ	³¹½Ñ	µ¹ÀÑ	³¹¶Ñ	³¹·Ñ	µ¹®Ñ	³¹¯Ñ	µ¹Ñ	³¹Ñ	µ¹úÐ	³¹ûÐ	µ¹âÐ	³¹ãÐ	µ¹ÐÐ	³¹ÑÐ	µ¹¼Ð	³¹½Ð	µ¹²Ð	³¹³Ð	µ¹®Ð	³¹¯Ð	µ¹Ð	³¹Ð	µ¹üÏ	³¹ýÏ	µ¹ðÏ	³¹ñÏ	µ¹æÏ	³¹çÏ	µ¹äÏ	³¹åÏ	µ¹§¯Ï	ï¾²Ï	í¾ªÏ	í¾«Ï	ï¾¡Ï	ï¾¤Ï	í¾¬Ï	í¾­Ï	ï¾Ï	ï¾¢Ï	í¾ñÏ	ï¾ôÏ	í¾Ï	í¾Ï	ï¾Ï	ï¾Ï	í¾ÖÏ	í¾×Ï	ï¾Ï	ï¾Ï	í¾Ï	í¾Ï	ï¾Ï	í¾Ï	ï¾Ï	í¾Ï	ï¾¥Ð	ï¾¨Ð	í¾ëÎ	ï¾îÎ	í¾áÎ	ï¾äÎ	í¾×Ð	ï¾ÚÐ	í¾ÍÏ	ï¾ÐÏ	í¾¨Ð	í¾©Ð	ï¾ÑÎ	ï¾ÔÎ	í¾ÅÎ	ï¾ÈÎ	í¾±Î	ï¾´Î	í¾«Î	ï¾®Î	í¾¤Î	í¾¥Î	ï¾Î	í¾Î	ï¾üÍ	í¾ýÍ	ï¾èÍ	í¾éÍ	ï¾ÐÍ	í¾ÑÍ	ï¾¾Í	í¾¿Í	ï¾ªÍ	í¾«Í	ï¾ Í	í¾¡Í	ï¾Í	í¾Í	ï¾Í	í¾Í	ï¾êÌ	í¾ëÌ	ï¾ÞÌ	í¾ßÌ	ï¾ÔÌ	í¾ÕÌ	ï¾ÒÌ	í¾ÓÌ	ï¾§Ì	©Ä Ì	§ÄÌ	§ÄÌ	©ÄÌ	©ÄÌ	§ÄÌ	§ÄÌ	©ÄÌ	©ÄÌ	§ÄßÌ	©ÄâÌ	§ÄÌ	§ÄÌ	©ÄÌ	©ÄÌ	§ÄÄÌ	§ÄÅÌ	©Ä÷Ë	©ÄúË	§ÄôË	§ÄõË	©ÄòË	§ÄóË	©ÄðË	§ÄñË	©ÄÍ	©ÄÍ	§ÄÙË	©ÄÜË	§ÄÏË	©ÄÒË	§ÄÅÍ	©ÄÈÍ	§Ä»Ì	©Ä¾Ì	§ÄÍ	§ÄÍ	©Ä¿Ë	©ÄÂË	§Ä³Ë	©Ä¶Ë	§ÄË	©Ä¢Ë	§ÄË	©ÄË	§ÄË	§ÄË	©ÄË	§ÄË	©ÄêÊ	§ÄëÊ	©ÄÖÊ	§Ä×Ê	©Ä¾Ê	§Ä¿Ê	©Ä¬Ê	§Ä­Ê	©ÄÊ	§ÄÊ	©ÄÊ	§ÄÊ	©ÄÊ	§ÄÊ	©ÄîÉ	§ÄïÉ	©ÄØÉ	§ÄÙÉ	©ÄÌÉ	§ÄÍÉ	©ÄÂÉ	§ÄÃÉ	©ÄÀÉ	§ÄÁÉ	©Ä§É	ãÉÉ	áÉÉ	áÉÉ	ãÉýÈ	ãÉÉ	áÉÉ	áÉÉ	ãÉûÈ	ãÉþÈ	áÉÍÉ	ãÉÐÉ	áÉøÈ	áÉùÈ	ãÉõÈ	ãÉøÈ	áÉ²É	áÉ³É	ãÉåÈ	ãÉèÈ	áÉâÈ	áÉãÈ	ãÉàÈ	áÉáÈ	ãÉÞÈ	áÉßÈ	ãÉÊ	ãÉÊ	áÉÇÈ	ãÉÊÈ	áÉ½È	ãÉÀÈ	áÉ³Ê	ãÉ¶Ê	áÉ©É	ãÉ¬É	áÉÊ	áÉÊ	ãÉ­È	ãÉ°È	áÉ¡È	ãÉ¤È	áÉÈ	ãÉÈ	áÉÈ	ãÉÈ	áÉÈ	áÉÈ	ãÉøÇ	áÉùÇ	ãÉØÇ	áÉÙÇ	ãÉÄÇ	áÉÅÇ	ãÉ¬Ç	áÉ­Ç	ãÉÇ	áÉÇ	ãÉÇ	áÉÇ	ãÉüÆ	áÉýÆ	ãÉøÆ	áÉùÆ	ãÉÜÆ	áÉÝÆ	ãÉÆÆ	áÉÇÆ	ãÉºÆ	áÉ»Æ	ãÉ°Æ	áÉ±Æ	ãÉ®Æ	áÉ¯Æ	ãÉ§ùÅ	ÏüÅ	ÏôÅ	ÏõÅ	ÏëÅ	ÏîÅ	ÏöÅ	Ï÷Å	ÏéÅ	ÏìÅ	Ï»Æ	Ï¾Æ	ÏæÅ	ÏçÅ	ÏãÅ	ÏæÅ	Ï Æ	Ï¡Æ	ÏÓÅ	ÏÖÅ	ÏÐÅ	ÏÑÅ	ÏÎÅ	ÏÏÅ	ÏÌÅ	ÏÍÅ	ÏïÆ	ÏòÆ	ÏµÅ	Ï¸Å	Ï«Å	Ï®Å	Ï¡Ç	Ï¤Ç	ÏÆ	ÏÆ	ÏòÆ	ÏóÆ	ÏÅ	ÏÅ	ÏÅ	ÏÅ	ÏûÄ	ÏþÄ	ÏõÄ	ÏøÄ	ÏîÄ	ÏïÄ	ÏæÄ	ÏçÄ	ÏÆÄ	ÏÇÄ	Ï²Ä	Ï³Ä	ÏÄ	ÏÄ	ÏÄ	ÏÄ	ÏôÃ	ÏõÃ	ÏêÃ	ÏëÃ	ÏæÃ	ÏçÃ	ÏÊÃ	ÏËÃ	Ï´Ã	ÏµÃ	Ï¨Ã	Ï©Ã	ÏÃ	ÏÃ	ÏÃ	ÏÃ	Ï§çÂ	×ÔêÂ	ÕÔâÂ	ÕÔãÂ	×ÔÙÂ	×ÔÜÂ	ÕÔäÂ	ÕÔåÂ	×Ô×Â	×ÔÚÂ	ÕÔ©Ã	×Ô¬Ã	ÕÔÔÂ	ÕÔÕÂ	×ÔÑÂ	×ÔÔÂ	ÕÔÃ	ÕÔÃ	×ÔÁÂ	×ÔÄÂ	ÕÔ¾Â	ÕÔ¿Â	×Ô¼Â	ÕÔ½Â	×ÔºÂ	ÕÔ»Â	×ÔÝÃ	×ÔàÃ	ÕÔ£Â	×Ô¦Â	ÕÔÂ	×ÔÂ	ÕÔÄ	×ÔÄ	ÕÔÃ	×ÔÃ	ÕÔàÃ	ÕÔáÃ	×ÔÂ	×ÔÂ	ÕÔýÁ	×ÔÂ	ÕÔéÁ	×ÔìÁ	ÕÔãÁ	×ÔæÁ	ÕÔÜÁ	ÕÔÝÁ	×ÔÔÁ	ÕÔÕÁ	×Ô´Á	ÕÔµÁ	×Ô Á	ÕÔ¡Á	×ÔÁ	ÕÔÁ	×ÔöÀ	ÕÔ÷À	×ÔâÀ	ÕÔãÀ	×ÔØÀ	ÕÔÙÀ	×ÔÔÀ	ÕÔÕÀ	×Ô¸À	ÕÔ¹À	×Ô¢À	ÕÔ£À	×ÔÀ	ÕÔÀ	×ÔÀ	ÕÔÀ	×ÔÀ	ÕÔÀ	×Ô§Õ¿	ÚØ¿	ÚÐ¿	ÚÑ¿	ÚÇ¿	ÚÊ¿	ÚÒ¿	ÚÓ¿	ÚÅ¿	ÚÈ¿	ÚÀ	ÚÀ	ÚÂ¿	ÚÃ¿	Ú¿¿	ÚÂ¿	Úü¿	Úý¿	Ú¯¿	Ú²¿	Ú¬¿	Ú­¿	Úª¿	Ú«¿	Ú¨¿	Ú©¿	ÚËÀ	ÚÎÀ	Ú¿	Ú¿	Ú¿	Ú¿	ÚýÀ	ÚÁ	Úó¿	Úö¿	ÚÎÀ	ÚÏÀ	Ú÷¾	Úú¾	Úë¾	Úî¾	Ú×¾	ÚÚ¾	ÚÑ¾	ÚÔ¾	ÚÊ¾	ÚË¾	ÚÂ¾	ÚÃ¾	Ú¢¾	Ú£¾	Ú¾	Ú¾	Úö½	Ú÷½	Úä½	Úå½	ÚÐ½	ÚÑ½	ÚÆ½	ÚÇ½	ÚÂ½	ÚÃ½	Ú¦½	Ú§½	Ú½	Ú½	Ú½	Ú½	Úú¼	Úû¼	Úø¼	Úù¼	Ú§Ã¼	ËßÆ¼	Éß¾¼	Éß¿¼	Ëßµ¼	Ëß¸¼	ÉßÀ¼	ÉßÁ¼	Ëß³¼	Ëß¶¼	Éß½	Ëß½	Éß°¼	Éß±¼	Ëß­¼	Ëß°¼	Éßê¼	Éßë¼	Ëß¼	Ëß ¼	Éß¼	Éß¼	Ëß¼	Éß¼	Ëß¼	Éß¼	Ëß¹½	Ëß¼½	Éßÿ»	Ëß¼	Éßõ»	Ëßø»	Éßë½	Ëßî½	Éßá¼	Ëßä¼	Éß¼½	Éß½½	Ëßå»	Ëßè»	ÉßÙ»	ËßÜ»	ÉßÅ»	ËßÈ»	Éß¿»	ËßÂ»	Éß¸»	Éß¹»	Ëß°»	Éß±»	Ëß»	Éß»	Ëßüº	Éßýº	Ëßäº	Éßåº	ËßÒº	ÉßÓº	Ëß¾º	Éß¿º	Ëß´º	Éßµº	Ëß°º	Éß±º	Ëßº	Éßº	Ëßþ¹	Éßÿ¹	Ëßò¹	Éßó¹	Ëßè¹	Éßé¹	Ëßæ¹	Éßç¹	Ëß§±¹	å´¹	å¬¹	å­¹	å£¹	å¦¹	å®¹	å¯¹	å¡¹	å¤¹	åó¹	åö¹	å¹	å¹	å¹	å¹	åØ¹	åÙ¹	å¹	å¹	å¹	å¹	å¹	å¹	å¹	å¹	å§º	åªº	åí¸	åð¸	åã¸	åæ¸	åÙº	åÜº	åÏ¹	åÒ¹	åªº	å«º	åÓ¸	åÖ¸	åÇ¸	åÊ¸	å³¸	å¶¸	å­¸	å°¸	å¦¸	å§¸	å¸	å¸	åþ·	åÿ·	åê·	åë·	åÒ·	åÓ·	åÀ·	åÁ·	å¬·	å­·	å¢·	å£·	å·	å·	å·	å·	åì¶	åí¶	åà¶	åá¶	åÖ¶	å×¶	åÔ¶	åÕ¶	å§¶	¿ê¢¶	½ê¶	½ê¶	¿ê¶	¿ê¶	½ê¶	½ê¶	¿ê¶	¿ê¶	½êá¶	¿êä¶	½ê¶	½ê¶	¿ê¶	¿ê¶	½êÆ¶	½êÇ¶	¿êùµ	¿êüµ	½êöµ	½ê÷µ	¿êôµ	½êõµ	¿êòµ	½êóµ	¿ê·	¿ê·	½êÛµ	¿êÞµ	½êÑµ	¿êÔµ	½êÇ·	¿êÊ·	½ê½¶	¿êÀ¶	½ê·	½ê·	¿êÁµ	¿êÄµ	½êµµ	¿ê¸µ	½ê¡µ	¿ê¤µ	½êµ	¿êµ	½êµ	½êµ	¿êµ	½êµ	¿êì´	½êí´	¿êØ´	½êÙ´	¿êÀ´	½êÁ´	¿ê®´	½ê¯´	¿ê´	½ê´	¿ê´	½ê´	¿ê´	½ê´	¿êð³	½êñ³	¿êÚ³	½êÛ³	¿êÎ³	½êÏ³	¿êÄ³	½êÅ³	¿êÂ³	½êÃ³	¿ê§³	ùï³	÷ï³	÷ï³	ùïÿ²	ùï³	÷ï³	÷ï³	ùïý²	ùï³	÷ïÏ³	ùïÒ³	÷ïú²	÷ïû²	ùï÷²	ùïú²	÷ï´³	÷ïµ³	ùïç²	ùïê²	÷ïä²	÷ïå²	ùïâ²	÷ïã²	ùïà²	÷ïá²	ùï´	ùï´	÷ïÉ²	ùïÌ²	÷ï¿²	ùïÂ²	÷ïµ´	ùï¸´	÷ï«³	ùï®³	÷ï´	÷ï´	ùï¯²	ùï²²	÷ï£²	ùï¦²	÷ï²	ùï²	÷ï²	ùï²	÷ï²	÷ï²	ùïú±	÷ïû±	ùïÚ±	÷ïÛ±	ùïÆ±	÷ïÇ±	ùï®±	÷ï¯±	ùï±	÷ï±	ùï±	÷ï±	ùïþ°	÷ïÿ°	ùïú°	÷ïû°	ùïÞ°	÷ïß°	ùïÈ°	÷ïÉ°	ùï¼°	÷ï½°	ùï²°	÷ï³°	ùï°°	÷ï±°	ùï§û¯	³õþ¯	±õö¯	±õ÷¯	³õí¯	³õð¯	±õø¯	±õù¯	³õë¯	³õî¯	±õ½°	³õÀ°	±õè¯	±õé¯	³õå¯	³õè¯	±õ¢°	±õ£°	³õÕ¯	³õØ¯	±õÒ¯	±õÓ¯	³õÐ¯	±õÑ¯	³õÎ¯	±õÏ¯	³õñ°	³õô°	±õ·¯	³õº¯	±õ­¯	³õ°¯	±õ£±	³õ¦±	±õ°	³õ°	±õô°	±õõ°	³õ¯	³õ ¯	±õ¯	³õ¯	±õý®	³õ¯	±õ÷®	³õú®	±õð®	±õñ®	³õè®	±õé®	³õÈ®	±õÉ®	³õ´®	±õµ®	³õ®	±õ®	³õ®	±õ®	³õö­	±õ÷­	³õì­	±õí­	³õè­	±õé­	³õÌ­	±õÍ­	³õ¶­	±õ·­	³õª­	±õ«­	³õ ­	±õ¡­	³õ­	±õ­	³õ§é¬	íúì¬	ëúä¬	ëúå¬	íúÛ¬	íúÞ¬	ëúæ¬	ëúç¬	íúÙ¬	íúÜ¬	ëú«­	íú®­	ëúÖ¬	ëú×¬	íúÓ¬	íúÖ¬	ëú­	ëú­	íúÃ¬	íúÆ¬	ëúÀ¬	ëúÁ¬	íú¾¬	ëú¿¬	íú¼¬	ëú½¬	íúß­	íúâ­	ëú¥¬	íú¨¬	ëú¬	íú¬	ëú®	íú®	ëú­	íú­	ëúâ­	ëúã­	íú¬	íú¬	ëúÿ«	íú¬	ëúë«	íúî«	ëúå«	íúè«	ëúÞ«	ëúß«	íúÖ«	ëú×«	íú¶«	ëú·«	íú¢«	ëú£«	íú«	ëú«	íúøª	ëúùª	íúäª	ëúåª	íúÚª	ëúÛª	íúÖª	ëú×ª	íúºª	ëú»ª	íú¤ª	ëú¥ª	íúª	ëúª	íúª	ëúª	íúª	ëúª	íú§×©	§Ú©	¥Ò©	¥Ó©	§É©	§Ì©	¥Ô©	¥Õ©	§Ç©	§Ê©	¥ª	§ª	¥Ä©	¥Å©	§Á©	§Ä©	¥þ©	¥ÿ©	§±©	§´©	¥®©	¥¯©	§¬©	¥­©	§ª©	¥«©	§Íª	§Ðª	¥©	§©	¥©	§©	¥ÿª	§«	¥õ©	§ø©	¥Ðª	¥Ñª	§ù¨	§ü¨	¥í¨	§ð¨	¥Ù¨	§Ü¨	¥Ó¨	§Ö¨	¥Ì¨	¥Í¨	§Ä¨	¥Å¨	§¤¨	¥¥¨	§¨	¥¨	§ø§	¥ù§	§æ§	¥ç§	§Ò§	¥Ó§	§È§	¥É§	§Ä§	¥Å§	§¨§	¥©§	§§	¥§	§§	¥§	§ü¦	¥ý¦	§ú¦	¥û¦	§§±¡»´¡¹¬¡¹­¡»£¡»¦¡¹®¡¹¯¡»¡¡»¤¡¹ó¡»ö¡¹¡¹¡»¡»¡¹Ø¡¹Ù¡»¡»¡¹¡¹¡»¡¹¡»¡¹¡»§¢»ª¢¹í »ð ¹ã »æ ¹Ù¢»Ü¢¹Ï¡»Ò¡¹ª¢¹«¢»Ó »Ö ¹Ç »Ê ¹³ »¶ ¹­ »° ¹¦ ¹§ » ¹ »þ¹ÿ»ê¹ë»Ò¹Ó»À¹Á»¬¹­»¢¹£»¹»¹»ì¹í»à¹á»Ö¹×»Ô¹Õ»§õ
+¢ó
+ó
+õ
+õ
+ó
+ó
+õ
+õ
+ó
+áõ
+äó
+ó
+õ
+õ
+ó
+Æó
+Çõ
+ùõ
+üó
+öó
+÷õ
+ôó
+õõ
+òó
+óõ
+õ
+ó
+Ûõ
+Þó
+Ñõ
+Ôó
+Çõ
+Êó
+½õ
+Àó
+ó
+õ
+Áõ
+Äó
+µõ
+¸ó
+¡õ
+¤ó
+õ
+ó
+ó
+õ
+ó
+õ
+ìó
+íõ
+Øó
+Ùõ
+Àó
+Áõ
+®ó
+¯õ
+ó
+õ
+ó
+õ
+ó
+õ
+ðó
+ñõ
+Úó
+Ûõ
+Îó
+Ïõ
+Äó
+Åõ
+Âó
+Ãõ
+§¯­­¯ÿ¯­­¯ý¯­Ï¯Ò­ú­û¯÷¯ú­´­µ¯ç¯ê­ä­å¯â­ã¯à­á¯¯­É¯Ì­¿¯Â­µ¯¸­«¯®­­¯¯¯²­£¯¦­¯­¯­­¯ú­û¯Ú­Û¯Æ­Ç¯®­¯¯­¯­¯þ­ÿ¯ú­û¯Þ­ß¯È­É¯¼­½¯²­³¯°­±¯§ûéþçöç÷éíéðçøçùéëéîç½éÀçèçééåéèç¢ç£éÕéØçÒçÓéÐçÑéÎçÏéñéôç·éºç­é°ç£é¦çéçôçõéé çéçýéç÷éúçðçñéèçééÈçÉé´çµéçéçéöç÷éìçíéèçééÌçÍé¶ç·éªç«é ç¡éçé§é£ì¡ä¡å£Û£Þ¡æ¡ç£Ù£Ü¡«£®¡Ö¡×£Ó£Ö¡¡£Ã£Æ¡À¡Á£¾¡¿£¼¡½£ß£â¡¥£¨¡£¡£¡£¡â¡ã££¡ÿ£¡ë£î¡å£è¡Þ¡ß£Ö¡×£¶¡·£¢¡££¡£ø¡ù£ä¡å£Ú¡Û£Ö¡×£º¡»£¤¡¥£¡£¡£¡£§×Ý ÚÛ ÒÛ ÓÝ ÉÝ ÌÛ ÔÛ ÕÝ ÇÝ ÊÛ Ý Û ÄÛ ÅÝ ÁÝ ÄÛ þÛ ÿÝ ±Ý ´Û ®Û ¯Ý ¬Û ­Ý ªÛ «Ý ÍÝ ÐÛ Ý Û Ý Û ÿÝ Û õÝ øÛ ÐÛ ÑÝ ùÝ üÛ íÝ ðÛ ÙÝ ÜÛ ÓÝ ÖÛ ÌÛ ÍÝ ÄÛ ÅÝ ¤Û ¥Ý Û Ý øÛ ùÝ æÛ çÝ ÒÛ ÓÝ ÈÛ ÉÝ ÄÛ ÅÝ ¨Û ©Ý Û Ý Û Ý üÛ ýÝ úÛ ûÝ §Å&È&À&Á&·&º&Â&Ã&µ&¸&&&²&³&¯&²&ì&í&&¢&&&&&&&»&¾&&&÷&ú&í&ð&ã&æ&¾&¿&ç&ê&Û&Þ&Ç&Ê&Á&Ä&º&»&²&³&&&þ&ÿ&æ&ç&Ô&Õ&À&Á&¶&·&²&³&&&&&ô&õ&ê&ë&è&é&§³Ñ+¶Ï+®Ï+¯Ñ+¥Ñ+¨Ï+°Ï+±Ñ+£Ñ+¦Ï+õÑ+øÏ+ Ï+¡Ñ+Ñ+ Ï+ÚÏ+ÛÑ+Ñ+Ï+Ï+Ñ+Ï+Ñ+Ï+Ñ+©Ñ+¬Ï+ïÑ+òÏ+åÑ+èÏ+ÛÑ+ÞÏ+ÑÑ+ÔÏ+¬Ï+­Ñ+ÕÑ+ØÏ+ÉÑ+ÌÏ+µÑ+¸Ï+¯Ñ+²Ï+¨Ï+©Ñ+ Ï+¡Ñ+Ï+Ñ+ìÏ+íÑ+ÔÏ+ÕÑ+ÂÏ+ÃÑ+®Ï+¯Ñ+¤Ï+¥Ñ+ Ï+¡Ñ+Ï+Ñ+îÏ+ïÑ+âÏ+ãÑ+ØÏ+ÙÑ+ÖÏ+×Ñ+§¡1¤111111111ã1æ11111È1É1û1þ1ø1ù1ö1÷1ô1õ111Ý1à1Ó1Ö1É1Ì1¿1Â111Ã1Æ1·1º1£1¦11 11111î1ï1Ú1Û1Â1Ã1°1±1111111ò1ó1Ü1Ý1Ð1Ñ1Æ1Ç1Ä1Å1§Å6Ã6Ã6Å6Å6Ã6Ã6Å6ÿÅ6Ã6ÑÅ6ÔÃ6üÃ6ýÅ6ùÅ6üÃ6¶Ã6·Å6éÅ6ìÃ6æÃ6çÅ6äÃ6åÅ6âÃ6ãÅ6Å6Ã6ËÅ6ÎÃ6ÁÅ6ÄÃ6·Å6ºÃ6­Å6°Ã6Ã6Å6±Å6´Ã6¥Å6¨Ã6Å6Ã6Å6Ã6Ã6Å6üÃ6ýÅ6ÜÃ6ÝÅ6ÈÃ6ÉÅ6°Ã6±Å6Ã6Å6Ã6Å6Ã6Å6üÃ6ýÅ6àÃ6áÅ6ÊÃ6ËÅ6¾Ã6¿Å6´Ã6µÅ6²Ã6³Å6§ýÿ;ý;øý;ùÿ;ïÿ;òý;úý;ûÿ;íÿ;ðý;¿ÿ;Âý;êý;ëÿ;çÿ;êý;¤ý;¥ÿ;×ÿ;Úý;Ôý;Õÿ;Òý;Óÿ;Ðý;Ñÿ;óÿ;öý;¹ÿ;¼ý;¯ÿ;²ý;¥ÿ;¨ý;ÿ;ý;öý;÷ÿ;ÿ;¢ý;ÿ;ý;ÿÿ;ý;ùÿ;üý;òý;óÿ;êý;ëÿ;Êý;Ëÿ;¶ý;·ÿ;ý;ÿ;ý;ÿ;øÿ
+ý;ùÿ
+ÿ;îÿ
+ý;ïÿ
+ÿ;êÿ
+ý;ëÿ
+ÿ;Îÿ
+ý;Ïÿ
+ÿ;¸ÿ
+ý;¹ÿ
+ÿ;¬ÿ
+ý;­ÿ
+ÿ;¢ÿ
+ý;£ÿ
+ÿ; ÿ
+ý;¡ÿ
+ÿ;§ëþ
+¹Aîþ
+·Aæþ
+·Açþ
+¹AÝþ
+¹Aàþ
+·Aèþ
+·Aéþ
+¹AÛþ
+¹AÞþ
+·A­ÿ
+¹A°ÿ
+·AØþ
+·AÙþ
+¹AÕþ
+¹AØþ
+·Aÿ
+·Aÿ
+¹AÅþ
+¹AÈþ
+·AÂþ
+·AÃþ
+¹AÀþ
+·AÁþ
+¹A¾þ
+·A¿þ
+¹Aáÿ
+¹Aäÿ
+·A§þ
+¹Aªþ
+·Aþ
+¹A þ
+·A¹A·Aÿ
+¹Aÿ
+·Aäÿ
+·Aåÿ
+¹Aþ
+¹Aþ
+·Aþ
+¹Aþ
+·Aíý
+¹Aðý
+·Açý
+¹Aêý
+·Aàý
+·Aáý
+¹AØý
+·AÙý
+¹A¸ý
+·A¹ý
+¹A¤ý
+·A¥ý
+¹Aý
+·Aý
+¹Aúü
+·Aûü
+¹Aæü
+·Açü
+¹AÜü
+·AÝü
+¹AØü
+·AÙü
+¹A¼ü
+·A½ü
+¹A¦ü
+·A§ü
+¹Aü
+·Aü
+¹Aü
+·Aü
+¹Aü
+·Aü
+¹A§Ùû
+óFÜû
+ñFÔû
+ñFÕû
+óFËû
+óFÎû
+ñFÖû
+ñF×û
+óFÉû
+óFÌû
+ñFü
+óFü
+ñFÆû
+ñFÇû
+óFÃû
+óFÆû
+ñFü
+ñFü
+óF³û
+óF¶û
+ñF°û
+ñF±û
+óF®û
+ñF¯û
+óF¬û
+ñF­û
+óFÏü
+óFÒü
+ñFû
+óFû
+ñFû
+óFû
+ñFý
+óFý
+ñF÷û
+óFúû
+ñFÒü
+ñFÓü
+óFûú
+óFþú
+ñFïú
+óFòú
+ñFÛú
+óFÞú
+ñFÕú
+óFØú
+ñFÎú
+ñFÏú
+óFÆú
+ñFÇú
+óF¦ú
+ñF§ú
+óFú
+ñFú
+óFúù
+ñFûù
+óFèù
+ñFéù
+óFÔù
+ñFÕù
+óFÊù
+ñFËù
+óFÆù
+ñFÇù
+óFªù
+ñF«ù
+óFù
+ñFù
+óFù
+ñFù
+óFþø
+ñFÿø
+óFüø
+ñFýø
+óF§Çø
+­LÊø
+«LÂø
+«LÃø
+­L¹ø
+­L¼ø
+«LÄø
+«LÅø
+­L·ø
+­Lºø
+«Lù
+­Lù
+«L´ø
+«Lµø
+­L±ø
+­L´ø
+«Lîø
+«Lïø
+­L¡ø
+­L¤ø
+«Lø
+«Lø
+­Lø
+«Lø
+­Lø
+«Lø
+­L½ù
+­LÀù
+«Lø
+­Lø
+«Lù÷
+­Lü÷
+«Lïù
+­Lòù
+«Låø
+­Lèø
+«LÀù
+«LÁù
+­Lé÷
+­Lì÷
+«LÝ÷
+­Là÷
+«LÉ÷
+­LÌ÷
+«LÃ÷
+­LÆ÷
+«L¼÷
+«L½÷
+­L´÷
+«Lµ÷
+­L÷
+«L÷
+­L÷
+«L÷
+­Lèö
+«Léö
+­LÖö
+«L×ö
+­LÂö
+«LÃö
+­L¸ö
+«L¹ö
+­L´ö
+«Lµö
+­Lö
+«Lö
+­Lö
+«Lö
+­Löõ
+«L÷õ
+­Lìõ
+«Líõ
+­Lêõ
+«Lëõ
+­L§µõ
+çQ¸õ
+åQ°õ
+åQ±õ
+çQ§õ
+çQªõ
+åQ²õ
+åQ³õ
+çQ¥õ
+çQ¨õ
+åQ÷õ
+çQúõ
+åQ¢õ
+åQ£õ
+çQõ
+çQ¢õ
+åQÜõ
+åQÝõ
+çQõ
+çQõ
+åQõ
+åQõ
+çQõ
+åQõ
+çQõ
+åQõ
+çQ«ö
+çQ®ö
+åQñô
+çQôô
+åQçô
+çQêô
+åQÝö
+çQàö
+åQÓõ
+çQÖõ
+åQ®ö
+åQ¯ö
+çQ×ô
+çQÚô
+åQËô
+çQÎô
+åQ·ô
+çQºô
+åQ±ô
+çQ´ô
+åQªô
+åQ«ô
+çQ¢ô
+åQ£ô
+çQô
+åQô
+çQîó
+åQïó
+çQÖó
+åQ×ó
+çQÄó
+åQÅó
+çQ°ó
+åQ±ó
+çQ¦ó
+åQ§ó
+çQ¢ó
+åQ£ó
+çQó
+åQó
+çQðò
+åQñò
+çQäò
+åQåò
+çQÚò
+åQÛò
+çQØò
+åQÙò
+çQ§£ò
+¡W¦ò
+Wò
+Wò
+¡Wò
+¡Wò
+W ò
+W¡ò
+¡Wò
+¡Wò
+Wåò
+¡Wèò
+Wò
+Wò
+¡Wò
+¡Wò
+WÊò
+WËò
+¡Wýñ
+¡Wò
+Wúñ
+Wûñ
+¡Wøñ
+Wùñ
+¡Wöñ
+W÷ñ
+¡Wó
+¡Wó
+Wßñ
+¡Wâñ
+WÕñ
+¡WØñ
+WËó
+¡WÎó
+WÁò
+¡WÄò
+Wó
+Wó
+¡WÅñ
+¡WÈñ
+W¹ñ
+¡W¼ñ
+W¥ñ
+¡W¨ñ
+Wñ
+¡W¢ñ
+Wñ
+Wñ
+¡Wñ
+Wñ
+¡Wðð
+Wñð
+¡WÜð
+WÝð
+¡WÄð
+WÅð
+¡W²ð
+W³ð
+¡Wð
+Wð
+¡Wð
+Wð
+¡Wð
+Wð
+¡Wôï
+Wõï
+¡WÞï
+Wßï
+¡WÒï
+WÓï
+¡WÈï
+WÉï
+¡WÆï
+WÇï
+¡W§ï
+Û\ï
+Ù\ï
+Ù\ï
+Û\ï
+Û\ï
+Ù\ï
+Ù\ï
+Û\ï
+Û\ï
+Ù\Óï
+Û\Öï
+Ù\þî
+Ù\ÿî
+Û\ûî
+Û\þî
+Ù\¸ï
+Ù\¹ï
+Û\ëî
+Û\îî
+Ù\èî
+Ù\éî
+Û\æî
+Ù\çî
+Û\äî
+Ù\åî
+Û\ð
+Û\ð
+Ù\Íî
+Û\Ðî
+Ù\Ãî
+Û\Æî
+Ù\¹ð
+Û\¼ð
+Ù\¯ï
+Û\²ï
+Ù\ð
+Ù\ð
+Û\³î
+Û\¶î
+Ù\§î
+Û\ªî
+Ù\î
+Û\î
+Ù\î
+Û\î
+Ù\î
+Ù\î
+Û\þí
+Ù\ÿí
+Û\Þí
+Ù\ßí
+Û\Êí
+Ù\Ëí
+Û\²í
+Ù\³í
+Û\ í
+Ù\¡í
+Û\í
+Ù\í
+Û\í
+Ù\í
+Û\þì
+Ù\ÿì
+Û\âì
+Ù\ãì
+Û\Ìì
+Ù\Íì
+Û\Àì
+Ù\Áì
+Û\¶ì
+Ù\·ì
+Û\´ì
+Ù\µì
+Û\§ÿë
+bì
+búë
+bûë
+bñë
+bôë
+büë
+býë
+bïë
+bòë
+bÁì
+bÄì
+bìë
+bíë
+béë
+bìë
+b¦ì
+b§ì
+bÙë
+bÜë
+bÖë
+b×ë
+bÔë
+bÕë
+bÒë
+bÓë
+bõì
+bøì
+b»ë
+b¾ë
+b±ë
+b´ë
+b§í
+bªí
+bì
+b ì
+bøì
+bùì
+b¡ë
+b¤ë
+bë
+bë
+bë
+bë
+bûê
+bþê
+bôê
+bõê
+bìê
+bíê
+bÌê
+bÍê
+b¸ê
+b¹ê
+b ê
+b¡ê
+bê
+bê
+búé
+bûé
+bðé
+bñé
+bìé
+bíé
+bÐé
+bÑé
+bºé
+b»é
+b®é
+b¯é
+b¤é
+b¥é
+b¢é
+b£é
+b§íè
+Ïgðè
+Ígèè
+Ígéè
+Ïgßè
+Ïgâè
+Ígêè
+Ígëè
+ÏgÝè
+Ïgàè
+Íg¯é
+Ïg²é
+ÍgÚè
+ÍgÛè
+Ïg×è
+ÏgÚè
+Ígé
+Ígé
+ÏgÇè
+ÏgÊè
+ÍgÄè
+ÍgÅè
+ÏgÂè
+ÍgÃè
+ÏgÀè
+ÍgÁè
+Ïgãé
+Ïgæé
+Íg©è
+Ïg¬è
+Ígè
+Ïg¢è
+Ígê
+Ïgê
+Ígé
+Ïgé
+Ígæé
+Ígçé
+Ïgè
+Ïgè
+Ígè
+Ïgè
+Ígïç
+Ïgòç
+Ígéç
+Ïgìç
+Ígâç
+Ígãç
+ÏgÚç
+ÍgÛç
+Ïgºç
+Íg»ç
+Ïg¦ç
+Íg§ç
+Ïgç
+Ígç
+Ïgüæ
+Ígýæ
+Ïgèæ
+Ígéæ
+ÏgÞæ
+Ígßæ
+ÏgÚæ
+ÍgÛæ
+Ïg¾æ
+Íg¿æ
+Ïg¨æ
+Íg©æ
+Ïgæ
+Ígæ
+Ïgæ
+Ígæ
+Ïgæ
+Ígæ
+Ïg§Ûå
+mÞå
+mÖå
+m×å
+mÍå
+mÐå
+mØå
+mÙå
+mËå
+mÎå
+mæ
+m æ
+mÈå
+mÉå
+mÅå
+mÈå
+mæ
+mæ
+mµå
+m¸å
+m²å
+m³å
+m°å
+m±å
+m®å
+m¯å
+mÑæ
+mÔæ
+må
+må
+må
+må
+mç
+mç
+mùå
+müå
+mÔæ
+mÕæ
+mýä
+må
+mñä
+môä
+mÝä
+màä
+m×ä
+mÚä
+mÐä
+mÑä
+mÈä
+mÉä
+m¨ä
+m©ä
+mä
+mä
+müã
+mýã
+mêã
+mëã
+mÖã
+m×ã
+mÌã
+mÍã
+mÈã
+mÉã
+m¬ã
+m­ã
+mã
+mã
+mã
+mã
+mã
+mã
+mþâ
+mÿâ
+m§Éâ
+ÃrÌâ
+ÁrÄâ
+ÁrÅâ
+Ãr»â
+Ãr¾â
+ÁrÆâ
+ÁrÇâ
+Ãr¹â
+Ãr¼â
+Árã
+Ãrã
+Ár¶â
+Ár·â
+Ãr³â
+Ãr¶â
+Árðâ
+Árñâ
+Ãr£â
+Ãr¦â
+Ár â
+Ár¡â
+Ãrâ
+Árâ
+Ãrâ
+Árâ
+Ãr¿ã
+ÃrÂã
+Árâ
+Ãrâ
+Árûá
+Ãrþá
+Árñã
+Ãrôã
+Árçâ
+Ãrêâ
+ÁrÂã
+ÁrÃã
+Ãrëá
+Ãrîá
+Árßá
+Ãrâá
+ÁrËá
+ÃrÎá
+ÁrÅá
+ÃrÈá
+Ár¾á
+Ár¿á
+Ãr¶á
+Ár·á
+Ãrá
+Árá
+Ãrá
+Árá
+Ãrêà
+Árëà
+ÃrØà
+ÁrÙà
+ÃrÄà
+ÁrÅà
+Ãrºà
+Ár»à
+Ãr¶à
+Ár·à
+Ãrà
+Árà
+Ãrà
+Árà
+Ãrøß
+Árùß
+Ãrîß
+Árïß
+Ãrìß
+Áríß
+Ãr§·ß
+ýwºß
+ûw²ß
+ûw³ß
+ýw©ß
+ýw¬ß
+ûw´ß
+ûwµß
+ýw§ß
+ýwªß
+ûwùß
+ýwüß
+ûw¤ß
+ûw¥ß
+ýw¡ß
+ýw¤ß
+ûwÞß
+ûwßß
+ýwß
+ýwß
+ûwß
+ûwß
+ýwß
+ûwß
+ýwß
+ûwß
+ýw­à
+ýw°à
+ûwóÞ
+ýwöÞ
+ûwéÞ
+ýwìÞ
+ûwßà
+ýwâà
+ûwÕß
+ýwØß
+ûw°à
+ûw±à
+ýwÙÞ
+ýwÜÞ
+ûwÍÞ
+ýwÐÞ
+ûw¹Þ
+ýw¼Þ
+ûw³Þ
+ýw¶Þ
+ûw¬Þ
+ûw­Þ
+ýw¤Þ
+ûw¥Þ
+ýwÞ
+ûwÞ
+ýwðÝ
+ûwñÝ
+ýwØÝ
+ûwÙÝ
+ýwÆÝ
+ûwÇÝ
+ýw²Ý
+ûw³Ý
+ýw¨Ý
+ûw©Ý
+ýw¤Ý
+ûw¥Ý
+ýwÝ
+ûwÝ
+ýwòÜ
+ûwóÜ
+ýwæÜ
+ûwçÜ
+ýwÜÜ
+ûwÝÜ
+ýwÚÜ
+ûwÛÜ
+ýw§¥Ü
+·}¨Ü
+µ} Ü
+µ}¡Ü
+·}Ü
+·}Ü
+µ}¢Ü
+µ}£Ü
+·}Ü
+·}Ü
+µ}çÜ
+·}êÜ
+µ}Ü
+µ}Ü
+·}Ü
+·}Ü
+µ}ÌÜ
+µ}ÍÜ
+·}ÿÛ
+·}Ü
+µ}üÛ
+µ}ýÛ
+·}úÛ
+µ}ûÛ
+·}øÛ
+µ}ùÛ
+·}Ý
+·}Ý
+µ}áÛ
+·}äÛ
+µ}×Û
+·}ÚÛ
+µ}ÍÝ
+·}ÐÝ
+µ}ÃÜ
+·}ÆÜ
+µ}Ý
+µ}Ý
+·}ÇÛ
+·}ÊÛ
+µ}»Û
+·}¾Û
+µ}§Û
+·}ªÛ
+µ}¡Û
+·}¤Û
+µ}Û
+µ}Û
+·}Û
+µ}Û
+·}òÚ
+µ}óÚ
+·}ÞÚ
+µ}ßÚ
+·}ÆÚ
+µ}ÇÚ
+·}´Ú
+µ}µÚ
+·} Ú
+µ}¡Ú
+·}Ú
+µ}Ú
+·}Ú
+µ}Ú
+·}öÙ
+µ}÷Ù
+·}àÙ
+µ}áÙ
+·}ÔÙ
+µ}ÕÙ
+·}ÊÙ
+µ}ËÙ
+·}ÈÙ
+µ}ÉÙ
+·}§Ù
+ñÙ
+ïÙ
+ïÙ
+ñÙ
+ñÙ
+ïÙ
+ïÙ
+ñÙ
+ñÙ
+ïÕÙ
+ñØÙ
+ïÙ
+ïÙ
+ñýØ
+ñÙ
+ïºÙ
+ï»Ù
+ñíØ
+ñðØ
+ïêØ
+ïëØ
+ñèØ
+ïéØ
+ñæØ
+ïçØ
+ñÚ
+ñÚ
+ïÏØ
+ñÒØ
+ïÅØ
+ñÈØ
+ï»Ú
+ñ¾Ú
+ï±Ù
+ñ´Ù
+ïÚ
+ïÚ
+ñµØ
+ñ¸Ø
+ï©Ø
+ñ¬Ø
+ïØ
+ñØ
+ïØ
+ñØ
+ïØ
+ïØ
+ñØ
+ïØ
+ñà×
+ïá×
+ñÌ×
+ïÍ×
+ñ´×
+ïµ×
+ñ¢×
+ï£×
+ñ×
+ï×
+ñ×
+ï×
+ñ×
+ï×
+ñäÖ
+ïåÖ
+ñÎÖ
+ïÏÖ
+ñÂÖ
+ïÃÖ
+ñ¸Ö
+ï¹Ö
+ñ¶Ö
+ï·Ö
+ñ§Ö
+«Ö
+©üÕ
+©ýÕ
+«óÕ
+«öÕ
+©þÕ
+©ÿÕ
+«ñÕ
+«ôÕ
+©ÃÖ
+«ÆÖ
+©îÕ
+©ïÕ
+«ëÕ
+«îÕ
+©¨Ö
+©©Ö
+«ÛÕ
+«ÞÕ
+©ØÕ
+©ÙÕ
+«ÖÕ
+©×Õ
+«ÔÕ
+©ÕÕ
+«÷Ö
+«úÖ
+©½Õ
+«ÀÕ
+©³Õ
+«¶Õ
+©©×
+«¬×
+©Ö
+«¢Ö
+©úÖ
+©ûÖ
+«£Õ
+«¦Õ
+©Õ
+«Õ
+©Õ
+«Õ
+©ýÔ
+«Õ
+©öÔ
+©÷Ô
+«îÔ
+©ïÔ
+«ÎÔ
+©ÏÔ
+«ºÔ
+©»Ô
+«¢Ô
+©£Ô
+«Ô
+©Ô
+«üÓ
+©ýÓ
+«òÓ
+©óÓ
+«îÓ
+©ïÓ
+«ÒÓ
+©ÓÓ
+«¼Ó
+©½Ó
+«°Ó
+©±Ó
+«¦Ó
+©§Ó
+«¤Ó
+©¥Ó
+«§ïÒ
+åòÒ
+ãêÒ
+ãëÒ
+åáÒ
+åäÒ
+ãìÒ
+ãíÒ
+åßÒ
+åâÒ
+ã±Ó
+å´Ó
+ãÜÒ
+ãÝÒ
+åÙÒ
+åÜÒ
+ãÓ
+ãÓ
+åÉÒ
+åÌÒ
+ãÆÒ
+ãÇÒ
+åÄÒ
+ãÅÒ
+åÂÒ
+ãÃÒ
+ååÓ
+åèÓ
+ã«Ò
+å®Ò
+ã¡Ò
+å¤Ò
+ãÔ
+åÔ
+ãÓ
+åÓ
+ãèÓ
+ãéÓ
+åÒ
+åÒ
+ãÒ
+åÒ
+ãñÑ
+åôÑ
+ãëÑ
+åîÑ
+ãäÑ
+ãåÑ
+åÜÑ
+ãÝÑ
+å¼Ñ
+ã½Ñ
+å¨Ñ
+ã©Ñ
+åÑ
+ãÑ
+åþÐ
+ãÿÐ
+åêÐ
+ãëÐ
+åàÐ
+ãáÐ
+åÜÐ
+ãÝÐ
+åÀÐ
+ãÁÐ
+åªÐ
+ã«Ð
+åÐ
+ãÐ
+åÐ
+ãÐ
+åÐ
+ãÐ
+å§ÝÏ
+àÏ
+ØÏ
+ÙÏ
+ÏÏ
+ÒÏ
+ÚÏ
+ÛÏ
+ÍÏ
+ÐÏ
+Ð
+¢Ð
+ÊÏ
+ËÏ
+ÇÏ
+ÊÏ
+Ð
+Ð
+·Ï
+ºÏ
+´Ï
+µÏ
+²Ï
+³Ï
+°Ï
+±Ï
+ÓÐ
+ÖÐ
+Ï
+Ï
+Ï
+Ï
+Ñ
+Ñ
+ûÏ
+þÏ
+ÖÐ
+×Ð
+ÿÎ
+Ï
+óÎ
+öÎ
+ßÎ
+âÎ
+ÙÎ
+ÜÎ
+ÒÎ
+ÓÎ
+ÊÎ
+ËÎ
+ªÎ
+«Î
+Î
+Î
+þÍ
+ÿÍ
+ìÍ
+íÍ
+ØÍ
+ÙÍ
+ÎÍ
+ÏÍ
+ÊÍ
+ËÍ
+®Í
+¯Í
+Í
+Í
+Í
+Í
+Í
+Í
+Í
+Í
+§ËÌ
+ÙÎÌ
+×ÆÌ
+×ÇÌ
+Ù½Ì
+ÙÀÌ
+×ÈÌ
+×ÉÌ
+Ù»Ì
+Ù¾Ì
+×Í
+ÙÍ
+×¸Ì
+×¹Ì
+ÙµÌ
+Ù¸Ì
+×òÌ
+×óÌ
+Ù¥Ì
+Ù¨Ì
+×¢Ì
+×£Ì
+Ù Ì
+×¡Ì
+ÙÌ
+×Ì
+ÙÁÍ
+ÙÄÍ
+×Ì
+ÙÌ
+×ýË
+ÙÌ
+×óÍ
+ÙöÍ
+×éÌ
+ÙìÌ
+×ÄÍ
+×ÅÍ
+ÙíË
+ÙðË
+×áË
+ÙäË
+×ÍË
+ÙÐË
+×ÇË
+ÙÊË
+×ÀË
+×ÁË
+Ù¸Ë
+×¹Ë
+ÙË
+×Ë
+ÙË
+×Ë
+ÙìÊ
+×íÊ
+ÙÚÊ
+×ÛÊ
+ÙÆÊ
+×ÇÊ
+Ù¼Ê
+×½Ê
+Ù¸Ê
+×¹Ê
+ÙÊ
+×Ê
+ÙÊ
+×Ê
+ÙúÉ
+×ûÉ
+ÙðÉ
+×ñÉ
+ÙîÉ
+×ïÉ
+Ù§¹É
+¼É
+´É
+µÉ
+«É
+®É
+¶É
+·É
+©É
+¬É
+ûÉ
+þÉ
+¦É
+§É
+£É
+¦É
+àÉ
+áÉ
+É
+É
+É
+É
+É
+É
+É
+É
+¯Ê
+²Ê
+õÈ
+øÈ
+ëÈ
+îÈ
+áÊ
+äÊ
+×É
+ÚÉ
+²Ê
+³Ê
+ÛÈ
+ÞÈ
+ÏÈ
+ÒÈ
+»È
+¾È
+µÈ
+¸È
+®È
+¯È
+¦È
+§È
+È
+È
+òÇ
+óÇ
+ÚÇ
+ÛÇ
+ÈÇ
+ÉÇ
+´Ç
+µÇ
+ªÇ
+«Ç
+¦Ç
+§Ç
+Ç
+Ç
+ôÆ
+õÆ
+èÆ
+éÆ
+ÞÆ
+ßÆ
+ÜÆ
+ÝÆ
+§§Æ
+Í£ªÆ
+Ë£¢Æ
+Ë££Æ
+Í£Æ
+Í£Æ
+Ë£¤Æ
+Ë£¥Æ
+Í£Æ
+Í£Æ
+Ë£éÆ
+Í£ìÆ
+Ë£Æ
+Ë£Æ
+Í£Æ
+Í£Æ
+Ë£ÎÆ
+Ë£ÏÆ
+Í£Æ
+Í£Æ
+Ë£þÅ
+Ë£ÿÅ
+Í£üÅ
+Ë£ýÅ
+Í£úÅ
+Ë£ûÅ
+Í£Ç
+Í£ Ç
+Ë£ãÅ
+Í£æÅ
+Ë£ÙÅ
+Í£ÜÅ
+Ë£ÏÇ
+Í£ÒÇ
+Ë£ÅÆ
+Í£ÈÆ
+Ë£ Ç
+Ë£¡Ç
+Í£ÉÅ
+Í£ÌÅ
+Ë£½Å
+Í£ÀÅ
+Ë£©Å
+Í£¬Å
+Ë££Å
+Í£¦Å
+Ë£Å
+Ë£Å
+Í£Å
+Ë£Å
+Í£ôÄ
+Ë£õÄ
+Í£àÄ
+Ë£áÄ
+Í£ÈÄ
+Ë£ÉÄ
+Í£¶Ä
+Ë£·Ä
+Í£¢Ä
+Ë££Ä
+Í£Ä
+Ë£Ä
+Í£Ä
+Ë£Ä
+Í£øÃ
+Ë£ùÃ
+Í£âÃ
+Ë£ãÃ
+Í£ÖÃ
+Ë£×Ã
+Í£ÌÃ
+Ë£ÍÃ
+Í£ÊÃ
+Ë£ËÃ
+Í£§Ã
+©Ã
+©Ã
+©Ã
+©Ã
+©Ã
+©Ã
+©Ã
+©Ã
+©Ã
+©×Ã
+©ÚÃ
+©Ã
+©Ã
+©ÿÂ
+©Ã
+©¼Ã
+©½Ã
+©ïÂ
+©òÂ
+©ìÂ
+©íÂ
+©êÂ
+©ëÂ
+©èÂ
+©éÂ
+©Ä
+©Ä
+©ÑÂ
+©ÔÂ
+©ÇÂ
+©ÊÂ
+©½Ä
+©ÀÄ
+©³Ã
+©¶Ã
+©Ä
+©Ä
+©·Â
+©ºÂ
+©«Â
+©®Â
+©Â
+©Â
+©Â
+©Â
+©Â
+©Â
+©Â
+©Â
+©âÁ
+©ãÁ
+©ÎÁ
+©ÏÁ
+©¶Á
+©·Á
+©¤Á
+©¥Á
+©Á
+©Á
+©Á
+©Á
+©Á
+©Á
+©æÀ
+©çÀ
+©ÐÀ
+©ÑÀ
+©ÄÀ
+©ÅÀ
+©ºÀ
+©»À
+©¸À
+©¹À
+©§À
+Á®À
+¿®þ¿
+¿®ÿ¿
+Á®õ¿
+Á®ø¿
+¿®À
+¿®À
+Á®ó¿
+Á®ö¿
+¿®ÅÀ
+Á®ÈÀ
+¿®ð¿
+¿®ñ¿
+Á®í¿
+Á®ð¿
+¿®ªÀ
+¿®«À
+Á®Ý¿
+Á®à¿
+¿®Ú¿
+¿®Û¿
+Á®Ø¿
+¿®Ù¿
+Á®Ö¿
+¿®×¿
+Á®ùÀ
+Á®üÀ
+¿®¿¿
+Á®Â¿
+¿®µ¿
+Á®¸¿
+¿®«Á
+Á®®Á
+¿®¡À
+Á®¤À
+¿®üÀ
+¿®ýÀ
+Á®¥¿
+Á®¨¿
+¿®¿
+Á®¿
+¿®¿
+Á®¿
+¿®ÿ¾
+Á®¿
+¿®ø¾
+¿®ù¾
+Á®ð¾
+¿®ñ¾
+Á®Ð¾
+¿®Ñ¾
+Á®¼¾
+¿®½¾
+Á®¤¾
+¿®¥¾
+Á®¾
+¿®¾
+Á®þ½
+¿®ÿ½
+Á®ô½
+¿®õ½
+Á®ð½
+¿®ñ½
+Á®Ô½
+¿®Õ½
+Á®¾½
+¿®¿½
+Á®²½
+¿®³½
+Á®¨½
+¿®©½
+Á®¦½
+¿®§½
+Á®§ñ¼
+û³ô¼
+ù³ì¼
+ù³í¼
+û³ã¼
+û³æ¼
+ù³î¼
+ù³ï¼
+û³á¼
+û³ä¼
+ù³³½
+û³¶½
+ù³Þ¼
+ù³ß¼
+û³Û¼
+û³Þ¼
+ù³½
+ù³½
+û³Ë¼
+û³Î¼
+ù³È¼
+ù³É¼
+û³Æ¼
+ù³Ç¼
+û³Ä¼
+ù³Å¼
+û³ç½
+û³ê½
+ù³­¼
+û³°¼
+ù³£¼
+û³¦¼
+ù³¾
+û³¾
+ù³½
+û³½
+ù³ê½
+ù³ë½
+û³¼
+û³¼
+ù³¼
+û³¼
+ù³ó»
+û³ö»
+ù³í»
+û³ð»
+ù³æ»
+ù³ç»
+û³Þ»
+ù³ß»
+û³¾»
+ù³¿»
+û³ª»
+ù³«»
+û³»
+ù³»
+û³»
+ù³»
+û³ìº
+ù³íº
+û³âº
+ù³ãº
+û³Þº
+ù³ßº
+û³Âº
+ù³Ãº
+û³¬º
+ù³­º
+û³ º
+ù³¡º
+û³º
+ù³º
+û³º
+ù³º
+û³§ß¹
+µ¹â¹
+³¹Ú¹
+³¹Û¹
+µ¹Ñ¹
+µ¹Ô¹
+³¹Ü¹
+³¹Ý¹
+µ¹Ï¹
+µ¹Ò¹
+³¹¡º
+µ¹¤º
+³¹Ì¹
+³¹Í¹
+µ¹É¹
+µ¹Ì¹
+³¹º
+³¹º
+µ¹¹¹
+µ¹¼¹
+³¹¶¹
+³¹·¹
+µ¹´¹
+³¹µ¹
+µ¹²¹
+³¹³¹
+µ¹Õº
+µ¹Øº
+³¹¹
+µ¹¹
+³¹¹
+µ¹¹
+³¹»
+µ¹»
+³¹ý¹
+µ¹º
+³¹Øº
+³¹Ùº
+µ¹¹
+µ¹¹
+³¹õ¸
+µ¹ø¸
+³¹á¸
+µ¹ä¸
+³¹Û¸
+µ¹Þ¸
+³¹Ô¸
+³¹Õ¸
+µ¹Ì¸
+³¹Í¸
+µ¹¬¸
+³¹­¸
+µ¹¸
+³¹¸
+µ¹¸
+³¹¸
+µ¹î·
+³¹ï·
+µ¹Ú·
+³¹Û·
+µ¹Ð·
+³¹Ñ·
+µ¹Ì·
+³¹Í·
+µ¹°·
+³¹±·
+µ¹·
+³¹·
+µ¹·
+³¹·
+µ¹·
+³¹·
+µ¹·
+³¹·
+µ¹§Í¶
+ï¾Ð¶
+í¾È¶
+í¾É¶
+ï¾¿¶
+ï¾Â¶
+í¾Ê¶
+í¾Ë¶
+ï¾½¶
+ï¾À¶
+í¾·
+ï¾·
+í¾º¶
+í¾»¶
+ï¾·¶
+ï¾º¶
+í¾ô¶
+í¾õ¶
+ï¾§¶
+ï¾ª¶
+í¾¤¶
+í¾¥¶
+ï¾¢¶
+í¾£¶
+ï¾ ¶
+í¾¡¶
+ï¾Ã·
+ï¾Æ·
+í¾¶
+ï¾¶
+í¾ÿµ
+ï¾¶
+í¾õ·
+ï¾ø·
+í¾ë¶
+ï¾î¶
+í¾Æ·
+í¾Ç·
+ï¾ïµ
+ï¾òµ
+í¾ãµ
+ï¾æµ
+í¾Ïµ
+ï¾Òµ
+í¾Éµ
+ï¾Ìµ
+í¾Âµ
+í¾Ãµ
+ï¾ºµ
+í¾»µ
+ï¾µ
+í¾µ
+ï¾µ
+í¾µ
+ï¾î´
+í¾ï´
+ï¾Ü´
+í¾Ý´
+ï¾È´
+í¾É´
+ï¾¾´
+í¾¿´
+ï¾º´
+í¾»´
+ï¾´
+í¾´
+ï¾´
+í¾´
+ï¾ü³
+í¾ý³
+ï¾ò³
+í¾ó³
+ï¾ð³
+í¾ñ³
+ï¾§»³
+©Ä¾³
+§Ä¶³
+§Ä·³
+©Ä­³
+©Ä°³
+§Ä¸³
+§Ä¹³
+©Ä«³
+©Ä®³
+§Äý³
+©Ä´
+§Ä¨³
+§Ä©³
+©Ä¥³
+©Ä¨³
+§Äâ³
+§Äã³
+©Ä³
+©Ä³
+§Ä³
+§Ä³
+©Ä³
+§Ä³
+©Ä³
+§Ä³
+©Ä±´
+©Ä´´
+§Ä÷²
+©Äú²
+§Äí²
+©Äð²
+§Äã´
+©Äæ´
+§ÄÙ³
+©ÄÜ³
+§Ä´´
+§Äµ´
+©ÄÝ²
+©Äà²
+§ÄÑ²
+©ÄÔ²
+§Ä½²
+©ÄÀ²
+§Ä·²
+©Äº²
+§Ä°²
+§Ä±²
+©Ä¨²
+§Ä©²
+©Ä²
+§Ä²
+©Äô±
+§Äõ±
+©ÄÜ±
+§ÄÝ±
+©ÄÊ±
+§ÄË±
+©Ä¶±
+§Ä·±
+©Ä¬±
+§Ä­±
+©Ä¨±
+§Ä©±
+©Ä±
+§Ä±
+©Äö°
+§Ä÷°
+©Äê°
+§Äë°
+©Äà°
+§Äá°
+©ÄÞ°
+§Äß°
+©Ä§©°
+ãÉ¬°
+áÉ¤°
+áÉ¥°
+ãÉ°
+ãÉ°
+áÉ¦°
+áÉ§°
+ãÉ°
+ãÉ°
+áÉë°
+ãÉî°
+áÉ°
+áÉ°
+ãÉ°
+ãÉ°
+áÉÐ°
+áÉÑ°
+ãÉ°
+ãÉ°
+áÉ°
+áÉ°
+ãÉþ¯
+áÉÿ¯
+ãÉü¯
+áÉý¯
+ãÉ±
+ãÉ¢±
+áÉå¯
+ãÉè¯
+áÉÛ¯
+ãÉÞ¯
+áÉÑ±
+ãÉÔ±
+áÉÇ°
+ãÉÊ°
+áÉ¢±
+áÉ£±
+ãÉË¯
+ãÉÎ¯
+áÉ¿¯
+ãÉÂ¯
+áÉ«¯
+ãÉ®¯
+áÉ¥¯
+ãÉ¨¯
+áÉ¯
+áÉ¯
+ãÉ¯
+áÉ¯
+ãÉö®
+áÉ÷®
+ãÉâ®
+áÉã®
+ãÉÊ®
+áÉË®
+ãÉ¸®
+áÉ¹®
+ãÉ¤®
+áÉ¥®
+ãÉ®
+áÉ®
+ãÉ®
+áÉ®
+ãÉú­
+áÉû­
+ãÉä­
+áÉå­
+ãÉØ­
+áÉÙ­
+ãÉÎ­
+áÉÏ­
+ãÉÌ­
+áÉÍ­
+ãÉ§­
+Ï­
+Ï­
+Ï­
+Ï­
+Ï­
+Ï­
+Ï­
+Ï­
+Ï­
+ÏÙ­
+ÏÜ­
+Ï­
+Ï­
+Ï­
+Ï­
+Ï¾­
+Ï¿­
+Ïñ¬
+Ïô¬
+Ïî¬
+Ïï¬
+Ïì¬
+Ïí¬
+Ïê¬
+Ïë¬
+Ï®
+Ï®
+ÏÓ¬
+ÏÖ¬
+ÏÉ¬
+ÏÌ¬
+Ï¿®
+ÏÂ®
+Ïµ­
+Ï¸­
+Ï®
+Ï®
+Ï¹¬
+Ï¼¬
+Ï­¬
+Ï°¬
+Ï¬
+Ï¬
+Ï¬
+Ï¬
+Ï¬
+Ï¬
+Ï¬
+Ï¬
+Ïä«
+Ïå«
+ÏÐ«
+ÏÑ«
+Ï¸«
+Ï¹«
+Ï¦«
+Ï§«
+Ï«
+Ï«
+Ï«
+Ï«
+Ï«
+Ï«
+Ïèª
+Ïéª
+ÏÒª
+ÏÓª
+ÏÆª
+ÏÇª
+Ï¼ª
+Ï½ª
+Ïºª
+Ï»ª
+Ï§ª
+×Ôª
+ÕÔª
+ÕÔª
+×Ô÷©
+×Ôú©
+ÕÔª
+ÕÔª
+×Ôõ©
+×Ôø©
+ÕÔÇª
+×ÔÊª
+ÕÔò©
+ÕÔó©
+×Ôï©
+×Ôò©
+ÕÔ¬ª
+ÕÔ­ª
+×Ôß©
+×Ôâ©
+ÕÔÜ©
+ÕÔÝ©
+×ÔÚ©
+ÕÔÛ©
+×ÔØ©
+ÕÔÙ©
+×Ôûª
+×Ôþª
+ÕÔÁ©
+×ÔÄ©
+ÕÔ·©
+×Ôº©
+ÕÔ­«
+×Ô°«
+ÕÔ£ª
+×Ô¦ª
+ÕÔþª
+ÕÔÿª
+×Ô§©
+×Ôª©
+ÕÔ©
+×Ô©
+ÕÔ©
+×Ô©
+ÕÔ©
+×Ô©
+ÕÔú¨
+ÕÔû¨
+×Ôò¨
+ÕÔó¨
+×ÔÒ¨
+ÕÔÓ¨
+×Ô¾¨
+ÕÔ¿¨
+×Ô¦¨
+ÕÔ§¨
+×Ô¨
+ÕÔ¨
+×Ô¨
+ÕÔ¨
+×Ôö§
+ÕÔ÷§
+×Ôò§
+ÕÔó§
+×ÔÖ§
+ÕÔ×§
+×ÔÀ§
+ÕÔÁ§
+×Ô´§
+ÕÔµ§
+×Ôª§
+ÕÔ«§
+×Ô¨§
+ÕÔ©§
+×Ô§ó¦
+Úö¦
+Úî¦
+Úï¦
+Úå¦
+Úè¦
+Úð¦
+Úñ¦
+Úã¦
+Úæ¦
+Úµ§
+Ú¸§
+Úà¦
+Úá¦
+ÚÝ¦
+Úà¦
+Ú§
+Ú§
+ÚÍ¦
+ÚÐ¦
+ÚÊ¦
+ÚË¦
+ÚÈ¦
+ÚÉ¦
+ÚÆ¦
+ÚÇ¦
+Úé§
+Úì§
+Ú¯¦
+Ú²¦
+Ú¥¦
+Ú¨¦
+Ú¨
+Ú¨
+Ú§
+Ú§
+Úì§
+Úí§
+Ú¦
+Ú¦
+Ú¦
+Ú¦
+Úõ¥
+Úø¥
+Úï¥
+Úò¥
+Úè¥
+Úé¥
+Úà¥
+Úá¥
+ÚÀ¥
+ÚÁ¥
+Ú¬¥
+Ú­¥
+Ú¥
+Ú¥
+Ú¥
+Ú¥
+Úî¤
+Úï¤
+Úä¤
+Úå¤
+Úà¤
+Úá¤
+ÚÄ¤
+ÚÅ¤
+Ú®¤
+Ú¯¤
+Ú¢¤
+Ú£¤
+Ú¤
+Ú¤
+Ú¤
+Ú¤
+Ú§á£
+Ëßä£
+ÉßÜ£
+ÉßÝ£
+ËßÓ£
+ËßÖ£
+ÉßÞ£
+Éßß£
+ËßÑ£
+ËßÔ£
+Éß£¤
+Ëß¦¤
+ÉßÎ£
+ÉßÏ£
+ËßË£
+ËßÎ£
+Éß¤
+Éß¤
+Ëß»£
+Ëß¾£
+Éß¸£
+Éß¹£
+Ëß¶£
+Éß·£
+Ëß´£
+Éßµ£
+Ëß×¤
+ËßÚ¤
+Éß£
+Ëß £
+Éß£
+Ëß£
+Éß¥
+Ëß¥
+Éßÿ£
+Ëß¤
+ÉßÚ¤
+ÉßÛ¤
+Ëß£
+Ëß£
+Éß÷¢
+Ëßú¢
+Éßã¢
+Ëßæ¢
+ÉßÝ¢
+Ëßà¢
+ÉßÖ¢
+Éß×¢
+ËßÎ¢
+ÉßÏ¢
+Ëß®¢
+Éß¯¢
+Ëß¢
+Éß¢
+Ëß¢
+Éß¢
+Ëßð¡
+Éßñ¡
+ËßÜ¡
+ÉßÝ¡
+ËßÒ¡
+ÉßÓ¡
+ËßÎ¡
+ÉßÏ¡
+Ëß²¡
+Éß³¡
+Ëß¡
+Éß¡
+Ëß¡
+Éß¡
+Ëß¡
+Éß¡
+Ëß¡
+Éß¡
+Ëß§Ï 
+åÒ 
+åÊ 
+åË 
+åÁ 
+åÄ 
+åÌ 
+åÍ 
+å¿ 
+åÂ 
+å¡
+å¡
+å¼ 
+å½ 
+å¹ 
+å¼ 
+åö 
+å÷ 
+å© 
+å¬ 
+å¦ 
+å§ 
+å¤ 
+å¥ 
+å¢ 
+å£ 
+åÅ¡
+åÈ¡
+å 
+å 
+å 
+å 
+å÷¡
+åú¡
+åí 
+åð 
+åÈ¡
+åÉ¡
+åñ
+åô
+åå
+åè
+åÑ
+åÔ
+åË
+åÎ
+åÄ
+åÅ
+å¼
+å½
+å
+å
+å
+å
+åð
+åñ
+åÞ
+åß
+åÊ
+åË
+åÀ
+åÁ
+å¼
+å½
+å 
+å¡
+å
+å
+åþ
+åÿ
+åô
+åõ
+åò
+åó
+å§½
+¿êÀ
+½ê¸
+½ê¹
+¿ê¯
+¿ê²
+½êº
+½ê»
+¿ê­
+¿ê°
+½êÿ
+¿ê
+½êª
+½ê«
+¿ê§
+¿êª
+½êä
+½êå
+¿ê
+¿ê
+½ê
+½ê
+¿ê
+½ê
+¿ê
+½ê
+¿ê³
+¿ê¶
+½êù
+¿êü
+½êï
+¿êò
+½êå
+¿êè
+½êÛ
+¿êÞ
+½ê¶
+½ê·
+¿êß
+¿êâ
+½êÓ
+¿êÖ
+½ê¿
+¿êÂ
+½ê¹
+¿ê¼
+½ê²
+½ê³
+¿êª
+½ê«
+¿ê
+½ê
+¿êö
+½ê÷
+¿êÞ
+½êß
+¿êÌ
+½êÍ
+¿ê¸
+½ê¹
+¿ê®
+½ê¯
+¿êª
+½ê«
+¿ê
+½ê
+¿êø
+½êù
+¿êì
+½êí
+¿êâ
+½êã
+¿êà
+½êá
+¿ê§«
+ùï®
+÷ï¦
+÷ï§
+ùï
+ùï 
+÷ï¨
+÷ï©
+ùï
+ùï
+÷ïí
+ùïð
+÷ï
+÷ï
+ùï
+ùï
+÷ïÒ
+÷ïÓ
+ùï
+ùï
+÷ï
+÷ï
+ùï
+÷ï
+ùïþ
+÷ïÿ
+ùï¡
+ùï¤
+÷ïç
+ùïê
+÷ïÝ
+ùïà
+÷ïÓ
+ùïÖ
+÷ïÉ
+ùïÌ
+÷ï¤
+÷ï¥
+ùïÍ
+ùïÐ
+÷ïÁ
+ùïÄ
+÷ï­
+ùï°
+÷ï§
+ùïª
+÷ï 
+÷ï¡
+ùï
+÷ï
+ùïø
+÷ïù
+ùïä
+÷ïå
+ùïÌ
+÷ïÍ
+ùïº
+÷ï»
+ùï¦
+÷ï§
+ùï
+÷ï
+ùï
+÷ï
+ùïü
+÷ïý
+ùïæ
+÷ïç
+ùïÚ
+÷ïÛ
+ùïÐ
+÷ïÑ
+ùïÎ
+÷ïÏ
+ùï§
+³õ
+±õ
+±õ
+³õ
+³õ
+±õ
+±õ
+³õ
+³õ
+±õÛ
+³õÞ
+±õ
+±õ
+³õ
+³õ
+±õÀ
+±õÁ
+³õó
+³õö
+±õð
+±õñ
+³õî
+±õï
+³õì
+±õí
+³õ
+³õ
+±õÕ
+³õØ
+±õË
+³õÎ
+±õÁ
+³õÄ
+±õ·
+³õº
+±õ
+±õ
+³õ»
+³õ¾
+±õ¯
+³õ²
+±õ
+³õ
+±õ
+³õ
+±õ
+±õ
+³õ
+±õ
+³õæ
+±õç
+³õÒ
+±õÓ
+³õº
+±õ»
+³õ¨
+±õ©
+³õ
+±õ
+³õ
+±õ
+³õ
+±õ
+³õê
+±õë
+³õÔ
+±õÕ
+³õÈ
+±õÉ
+³õ¾
+±õ¿
+³õ¼
+±õ½
+³õ§
+íú
+ëú
+ëú
+íúù
+íúü
+ëú
+ëú
+íú÷
+íúú
+ëúÉ
+íúÌ
+ëúô
+ëúõ
+íúñ
+íúô
+ëú®
+ëú¯
+íúá
+íúä
+ëúÞ
+ëúß
+íúÜ
+ëúÝ
+íúÚ
+ëúÛ
+íúý
+íú
+ëúÃ
+íúÆ
+ëú¹
+íú¼
+ëú¯
+íú²
+ëú¥
+íú¨
+ëú
+ëú
+íú©
+íú¬
+ëú
+íú 
+ëú
+íú
+ëú
+íú
+ëúü
+ëúý
+íúô
+ëúõ
+íúÔ
+ëúÕ
+íúÀ
+ëúÁ
+íú¨
+ëú©
+íú
+ëú
+íú
+ëú
+íúø
+ëúù
+íúô
+ëúõ
+íúØ
+ëúÙ
+íúÂ
+ëúÃ
+íú¶
+ëú·
+íú¬
+ëú­
+íúª
+ëú«
+íú§§»ª¹¢¹£»»¹¤¹¥»»¹é»ì¹¹»»¹Î¹Ï»»¹þ¹ÿ»ü¹ý»ú¹û»» ¹ã»æ¹Ù»Ü¹Ï»Ò¹Å»È¹ ¹¡»É»Ì¹½»À¹©»¬¹£»¦¹¹»¹»ô¹õ»à¹á»È¹É»¶¹·»¢¹£»¹»¹»ø¹ù»â¹ã»Ö¹×»Ì¹Í»Ê¹Ë»§õ
+ó
+ó
+õ
+õ
+ó
+ó
+õ
+õ
+ó
+×õ
+Úó
+ó
+õ
+ÿõ
+ó
+¼ó
+½õ
+ïõ
+òó
+ìó
+íõ
+êó
+ëõ
+èó
+éõ
+õ
+ó
+Ñõ
+Ôó
+Çõ
+Êó
+½õ
+Àó
+³õ
+¶ó
+ó
+õ
+·õ
+ºó
+«õ
+®ó
+õ
+ó
+õ
+ó
+ó
+õ
+ó
+õ
+âó
+ãõ
+Îó
+Ïõ
+¶ó
+·õ
+¤ó
+¥õ
+ó
+õ
+ó
+õ
+ó
+õ
+æó
+çõ
+Ðó
+Ñõ
+Äó
+Åõ
+ºó
+»õ
+¸ó
+¹õ
+§¯­þÿ­ÿÿ¯õÿ¯øÿ­­¯óÿ¯öÿ­Å¯È­ðÿ­ñÿ¯íÿ¯ðÿ­ª­«¯Ýÿ¯àÿ­Úÿ­Ûÿ¯Øÿ­Ùÿ¯Öÿ­×ÿ¯ù¯ü­¿ÿ¯Âÿ­µÿ¯¸ÿ­«¯®­¡¯¤­ü­ý¯¥ÿ¯¨ÿ­ÿ¯ÿ­ÿ¯ÿ­ÿþ¯ÿ­øþ­ùþ¯ðþ­ñþ¯Ðþ­Ñþ¯¼þ­½þ¯¤þ­¥þ¯þ­þ¯þý­ÿý¯ôý­õý¯ðý­ñý¯Ôý­Õý¯¾ý­¿ý¯²ý­³ý¯¨ý­©ý¯¦ý­§ý¯§ñüéôüçìüçíüéãüéæüçîüçïüéáüéäüç³ýé¶ýçÞüçßüéÛüéÞüçýçýéËüéÎüçÈüçÉüéÆüçÇüéÄüçÅüéçýéêýç­üé°üç£üé¦üçþéþçýéýçêýçëýéüéüçüéüçóûéöûçíûéðûçæûççûéÞûçßûé¾ûç¿ûéªûç«ûéûçûéûçûéìúçíúéâúçãúéÞúçßúéÂúçÃúé¬úç­úé úç¡úéúçúéúçúé§ßù£âù¡Úù¡Ûù£Ñù£Ôù¡Üù¡Ýù£Ïù£Òù¡¡ú£¤ú¡Ìù¡Íù£Éù£Ìù¡ú¡ú£¹ù£¼ù¡¶ù¡·ù£´ù¡µù£²ù¡³ù£Õú£Øú¡ù£ù¡ù£ù¡û£û¡ýù£ú¡Øú¡Ùú£ù£ù¡õø£øø¡áø£äø¡Ûø£Þø¡Ôø¡Õø£Ìø¡Íø£¬ø¡­ø£ø¡ø£ø¡ø£î÷¡ï÷£Ú÷¡Û÷£Ð÷¡Ñ÷£Ì÷¡Í÷£°÷¡±÷£÷¡÷£÷¡÷£÷¡÷£÷¡÷£§ÍöÝ ÐöÛ ÈöÛ ÉöÝ ¿öÝ ÂöÛ ÊöÛ ËöÝ ½öÝ ÀöÛ ÷Ý ÷Û ºöÛ »öÝ ·öÝ ºöÛ ôöÛ õöÝ §öÝ ªöÛ ¤öÛ ¥öÝ ¢öÛ £öÝ  öÛ ¡öÝ Ã÷Ý Æ÷Û öÝ öÛ ÿõÝ öÛ õ÷Ý ø÷Û ëöÝ îöÛ Æ÷Û Ç÷Ý ïõÝ òõÛ ãõÝ æõÛ ÏõÝ ÒõÛ ÉõÝ ÌõÛ ÂõÛ ÃõÝ ºõÛ »õÝ õÛ õÝ õÛ õÝ îôÛ ïôÝ ÜôÛ ÝôÝ ÈôÛ ÉôÝ ¾ôÛ ¿ôÝ ºôÛ »ôÝ ôÛ ôÝ ôÛ ôÝ üóÛ ýóÝ òóÛ óóÝ ðóÛ ñóÝ §»ó&¾ó&¶ó&·ó&­ó&°ó&¸ó&¹ó&«ó&®ó&ýó&ô&¨ó&©ó&¥ó&¨ó&âó&ãó&ó&ó&ó&ó&ó&ó&ó&ó&±ô&´ô&÷ò&úò&íò&ðò&ãô&æô&Ùó&Üó&´ô&µô&Ýò&àò&Ñò&Ôò&½ò&Àò&·ò&ºò&°ò&±ò&¨ò&©ò&ò&ò&ôñ&õñ&Üñ&Ýñ&Êñ&Ëñ&¶ñ&·ñ&¬ñ&­ñ&¨ñ&©ñ&ñ&ñ&öð&÷ð&êð&ëð&àð&áð&Þð&ßð&§©ðÑ+¬ðÏ+¤ðÏ+¥ðÑ+ðÑ+ðÏ+¦ðÏ+§ðÑ+ðÑ+ðÏ+ëðÑ+îðÏ+ðÏ+ðÑ+ðÑ+ðÏ+ÐðÏ+ÑðÑ+ðÑ+ðÏ+ðÏ+ðÑ+þïÏ+ÿïÑ+üïÏ+ýïÑ+ñÑ+¢ñÏ+åïÑ+èïÏ+ÛïÑ+ÞïÏ+ÑñÑ+ÔñÏ+ÇðÑ+ÊðÏ+¢ñÏ+£ñÑ+ËïÑ+ÎïÏ+¿ïÑ+ÂïÏ+«ïÑ+®ïÏ+¥ïÑ+¨ïÏ+ïÏ+ïÑ+ïÏ+ïÑ+öîÏ+÷îÑ+âîÏ+ãîÑ+ÊîÏ+ËîÑ+¸îÏ+¹îÑ+¤îÏ+¥îÑ+îÏ+îÑ+îÏ+îÑ+úíÏ+ûíÑ+äíÏ+åíÑ+ØíÏ+ÙíÑ+ÎíÏ+ÏíÑ+ÌíÏ+ÍíÑ+§í1í1í1í1í1í1í1í1í1í1Ùí1Üí1í1í1í1í1¾í1¿í1ñì1ôì1îì1ïì1ìì1íì1êì1ëì1î1î1Óì1Öì1Éì1Ìì1¿î1Âî1µí1¸í1î1î1¹ì1¼ì1­ì1°ì1ì1ì1ì1ì1ì1ì1ì1ì1äë1åë1Ðë1Ñë1¸ë1¹ë1¦ë1§ë1ë1ë1ë1ë1ë1ë1èê1éê1Òê1Óê1Æê1Çê1¼ê1½ê1ºê1»ê1§êÅ6êÃ6êÃ6êÅ6÷éÅ6úéÃ6êÃ6êÅ6õéÅ6øéÃ6ÇêÅ6ÊêÃ6òéÃ6óéÅ6ïéÅ6òéÃ6¬êÃ6­êÅ6ßéÅ6âéÃ6ÜéÃ6ÝéÅ6ÚéÃ6ÛéÅ6ØéÃ6ÙéÅ6ûêÅ6þêÃ6ÁéÅ6ÄéÃ6·éÅ6ºéÃ6­ëÅ6°ëÃ6£êÅ6¦êÃ6þêÃ6ÿêÅ6§éÅ6ªéÃ6éÅ6éÃ6éÅ6éÃ6éÅ6éÃ6úèÃ6ûèÅ6òèÃ6óèÅ6ÒèÃ6ÓèÅ6¾èÃ6¿èÅ6¦èÃ6§èÅ6èÃ6èÅ6èÃ6èÅ6öçÃ6÷çÅ6òçÃ6óçÅ6ÖçÃ6×çÅ6ÀçÃ6ÁçÅ6´çÃ6µçÅ6ªçÃ6«çÅ6¨çÃ6©çÅ6§óæÿ;öæý;îæý;ïæÿ;åæÿ;èæý;ðæý;ñæÿ;ãæÿ;ææý;µçÿ;¸çý;àæý;áæÿ;Ýæÿ;àæý;çý;çÿ;Íæÿ;Ðæý;Êæý;Ëæÿ;Èæý;Éæÿ;Ææý;Çæÿ;éçÿ;ìçý;¯æÿ;²æý;¥æÿ;¨æý;èÿ;èý;çÿ;çý;ìçý;íçÿ;æÿ;æý;æÿ;æý;õåÿ;øåý;ïåÿ;òåý;èåý;éåÿ;àåý;áåÿ;Àåý;Áåÿ;¬åý;­åÿ;åý;åÿ;åý;åÿ;îäý;ïäÿ;ääý;åäÿ;àäý;áäÿ;Ääý;Åäÿ;®äý;¯äÿ;¢äý;£äÿ;äý;äÿ;äý;äÿ;§áã¹Aäã·AÜã·AÝã¹AÓã¹AÖã·AÞã·Aßã¹AÑã¹AÔã·A£ä¹A¦ä·AÎã·AÏã¹AËã¹AÎã·Aä·Aä¹A»ã¹A¾ã·A¸ã·A¹ã¹A¶ã·A·ã¹A´ã·Aµã¹A×ä¹AÚä·Aã¹A ã·Aã¹Aã·Aå¹Aå·Aÿã¹Aä·AÚä·AÛä¹Aã¹Aã·A÷â¹Aúâ·Aãâ¹Aæâ·AÝâ¹Aàâ·AÖâ·A×â¹AÎâ·AÏâ¹A®â·A¯â¹Aâ·Aâ¹Aâ·Aâ¹Aðá·Añá¹AÜá·AÝá¹AÒá·AÓá¹AÎá·AÏá¹A²á·A³á¹Aá·Aá¹Aá·Aá¹Aá·Aá¹Aá·Aá¹A§ÏàóFÒàñFÊàñFËàóFÁàóFÄàñFÌàñFÍàóF¿àóFÂàñFáóFáñF¼àñF½àóF¹àóF¼àñFöàñF÷àóF©àóF¬àñF¦àñF§àóF¤àñF¥àóF¢àñF£àóFÅáóFÈáñFàóFàñFàóFàñF÷áóFúáñFíàóFðàñFÈáñFÉáóFñßóFôßñFåßóFèßñFÑßóFÔßñFËßóFÎßñFÄßñFÅßóF¼ßñF½ßóFßñFßóFßñFßóFðÞñFñÞóFÞÞñFßÞóFÊÞñFËÞóFÀÞñFÁÞóF¼ÞñF½ÞóF ÞñF¡ÞóFÞñFÞóFþÝñFÿÝóFôÝñFõÝóFòÝñFóÝóF§½Ý­LÀÝ«L¸Ý«L¹Ý­L¯Ý­L²Ý«LºÝ«L»Ý­L­Ý­L°Ý«LÿÝ­LÞ«LªÝ«L«Ý­L§Ý­LªÝ«LäÝ«LåÝ­LÝ­LÝ«LÝ«LÝ­LÝ«LÝ­LÝ«LÝ­L³Þ­L¶Þ«LùÜ­LüÜ«LïÜ­LòÜ«LåÞ­LèÞ«LÛÝ­LÞÝ«L¶Þ«L·Þ­LßÜ­LâÜ«LÓÜ­LÖÜ«L¿Ü­LÂÜ«L¹Ü­L¼Ü«L²Ü«L³Ü­LªÜ«L«Ü­LÜ«LÜ­LöÛ«L÷Û­LÞÛ«LßÛ­LÌÛ«LÍÛ­L¸Û«L¹Û­L®Û«L¯Û­LªÛ«L«Û­LÛ«LÛ­LøÚ«LùÚ­LìÚ«LíÚ­LâÚ«LãÚ­LàÚ«LáÚ­L§«ÚçQ®ÚåQ¦ÚåQ§ÚçQÚçQ ÚåQ¨ÚåQ©ÚçQÚçQÚåQíÚçQðÚåQÚåQÚçQÚçQÚåQÒÚåQÓÚçQÚçQÚåQÚåQÚçQÚåQÚçQþÙåQÿÙçQ¡ÛçQ¤ÛåQçÙçQêÙåQÝÙçQàÙåQÓÛçQÖÛåQÉÚçQÌÚåQ¤ÛåQ¥ÛçQÍÙçQÐÙåQÁÙçQÄÙåQ­ÙçQ°ÙåQ§ÙçQªÙåQ ÙåQ¡ÙçQÙåQÙçQøØåQùØçQäØåQåØçQÌØåQÍØçQºØåQ»ØçQ¦ØåQ§ØçQØåQØçQØåQØçQü×åQý×çQæ×åQç×çQÚ×åQÛ×çQÐ×åQÑ×çQÎ×åQÏ×çQ§×¡W×W×W×¡W×¡W×W×W×¡W×¡W×WÛ×¡WÞ×W×W×¡W×¡W×WÀ×WÁ×¡WóÖ¡WöÖWðÖWñÖ¡WîÖWïÖ¡WìÖWíÖ¡WØ¡WØWÕÖ¡WØÖWËÖ¡WÎÖWÁØ¡WÄØW·×¡Wº×WØWØ¡W»Ö¡W¾ÖW¯Ö¡W²ÖWÖ¡WÖWÖ¡WÖWÖWÖ¡WÖWÖ¡WæÕWçÕ¡WÒÕWÓÕ¡WºÕW»Õ¡W¨ÕW©Õ¡WÕWÕ¡WÕWÕ¡WÕWÕ¡WêÔWëÔ¡WÔÔWÕÔ¡WÈÔWÉÔ¡W¾ÔW¿Ô¡W¼ÔW½Ô¡W§ÔÛ\ÔÙ\ÔÙ\ÔÛ\ùÓÛ\üÓÙ\ÔÙ\ÔÛ\÷ÓÛ\úÓÙ\ÉÔÛ\ÌÔÙ\ôÓÙ\õÓÛ\ñÓÛ\ôÓÙ\®ÔÙ\¯ÔÛ\áÓÛ\äÓÙ\ÞÓÙ\ßÓÛ\ÜÓÙ\ÝÓÛ\ÚÓÙ\ÛÓÛ\ýÔÛ\ÕÙ\ÃÓÛ\ÆÓÙ\¹ÓÛ\¼ÓÙ\¯ÕÛ\²ÕÙ\¥ÔÛ\¨ÔÙ\ÕÙ\ÕÛ\©ÓÛ\¬ÓÙ\ÓÛ\ ÓÙ\ÓÛ\ÓÙ\ÓÛ\ÓÙ\üÒÙ\ýÒÛ\ôÒÙ\õÒÛ\ÔÒÙ\ÕÒÛ\ÀÒÙ\ÁÒÛ\¨ÒÙ\©ÒÛ\ÒÙ\ÒÛ\ÒÙ\ÒÛ\øÑÙ\ùÑÛ\ôÑÙ\õÑÛ\ØÑÙ\ÙÑÛ\ÂÑÙ\ÃÑÛ\¶ÑÙ\·ÑÛ\¬ÑÙ\­ÑÛ\ªÑÙ\«ÑÛ\§õÐbøÐbðÐbñÐbçÐbêÐbòÐbóÐbåÐbèÐb·ÑbºÑbâÐbãÐbßÐbâÐbÑbÑbÏÐbÒÐbÌÐbÍÐbÊÐbËÐbÈÐbÉÐbëÑbîÑb±Ðb´Ðb§ÐbªÐbÒb ÒbÑbÑbîÑbïÑbÐbÐbÐbÐb÷ÏbúÏbñÏbôÏbêÏbëÏbâÏbãÏbÂÏbÃÏb®Ïb¯ÏbÏbÏbÏbÏbðÎbñÎbæÎbçÎbâÎbãÎbÆÎbÇÎb°Îb±Îb¤Îb¥ÎbÎbÎbÎbÎb§ãÍÏgæÍÍgÞÍÍgßÍÏgÕÍÏgØÍÍgàÍÍgáÍÏgÓÍÏgÖÍÍg¥ÎÏg¨ÎÍgÐÍÍgÑÍÏgÍÍÏgÐÍÍgÎÍgÎÏg½ÍÏgÀÍÍgºÍÍg»ÍÏg¸ÍÍg¹ÍÏg¶ÍÍg·ÍÏgÙÎÏgÜÎÍgÍÏg¢ÍÍgÍÏgÍÍgÏÏgÏÍgÎÏgÎÍgÜÎÍgÝÎÏgÍÏgÍÍgùÌÏgüÌÍgåÌÏgèÌÍgßÌÏgâÌÍgØÌÍgÙÌÏgÐÌÍgÑÌÏg°ÌÍg±ÌÏgÌÍgÌÏgÌÍgÌÏgòËÍgóËÏgÞËÍgßËÏgÔËÍgÕËÏgÐËÍgÑËÏg´ËÍgµËÏgËÍgËÏgËÍgËÏgËÍgËÏgËÍgËÏg§ÑÊmÔÊmÌÊmÍÊmÃÊmÆÊmÎÊmÏÊmÁÊmÄÊmËmËm¾Êm¿Êm»Êm¾ÊmøÊmùÊm«Êm®Êm¨Êm©Êm¦Êm§Êm¤Êm¥ÊmÇËmÊËmÊmÊmÊmÊmùËmüËmïÊmòÊmÊËmËËmóÉmöÉmçÉmêÉmÓÉmÖÉmÍÉmÐÉmÆÉmÇÉm¾Ém¿ÉmÉmÉmÉmÉmòÈmóÈmàÈmáÈmÌÈmÍÈmÂÈmÃÈm¾Èm¿Èm¢Èm£ÈmÈmÈmÈmÈmöÇm÷ÇmôÇmõÇm§¿ÇÃrÂÇÁrºÇÁr»ÇÃr±ÇÃr´ÇÁr¼ÇÁr½ÇÃr¯ÇÃr²ÇÁrÈÃrÈÁr¬ÇÁr­ÇÃr©ÇÃr¬ÇÁræÇÁrçÇÃrÇÃrÇÁrÇÁrÇÃrÇÁrÇÃrÇÁrÇÃrµÈÃr¸ÈÁrûÆÃrþÆÁrñÆÃrôÆÁrçÈÃrêÈÁrÝÇÃràÇÁr¸ÈÁr¹ÈÃráÆÃräÆÁrÕÆÃrØÆÁrÁÆÃrÄÆÁr»ÆÃr¾ÆÁr´ÆÁrµÆÃr¬ÆÁr­ÆÃrÆÁrÆÃrøÅÁrùÅÃràÅÁráÅÃrÎÅÁrÏÅÃrºÅÁr»ÅÃr°ÅÁr±ÅÃr¬ÅÁr­ÅÃrÅÁrÅÃrúÄÁrûÄÃrîÄÁrïÄÃräÄÁråÄÃrâÄÁrãÄÃr§­Äýw°Äûw¨Äûw©ÄýwÄýw¢ÄûwªÄûw«ÄýwÄýw ÄûwïÄýwòÄûwÄûwÄýwÄýwÄûwÔÄûwÕÄýwÄýwÄûwÄûwÄýwÄûwÄýwÄûwÄýw£Åýw¦ÅûwéÃýwìÃûwßÃýwâÃûwÕÅýwØÅûwËÄýwÎÄûw¦Åûw§ÅýwÏÃýwÒÃûwÃÃýwÆÃûw¯Ãýw²Ãûw©Ãýw¬Ãûw¢Ãûw£ÃýwÃûwÃýwúÂûwûÂýwæÂûwçÂýwÎÂûwÏÂýw¼Âûw½Âýw¨Âûw©ÂýwÂûwÂýwÂûwÂýwþÁûwÿÁýwèÁûwéÁýwÜÁûwÝÁýwÒÁûwÓÁýwÐÁûwÑÁýw§Á·}Áµ}Áµ}Á·}Á·}Áµ}Áµ}Á·}Á·}Áµ}ÝÁ·}àÁµ}Áµ}Á·}Á·}Áµ}ÂÁµ}ÃÁ·}õÀ·}øÀµ}òÀµ}óÀ·}ðÀµ}ñÀ·}îÀµ}ïÀ·}Â·}Âµ}×À·}ÚÀµ}ÍÀ·}ÐÀµ}ÃÂ·}ÆÂµ}¹Á·}¼Áµ}Âµ}Â·}½À·}ÀÀµ}±À·}´Àµ}À·} Àµ}À·}Àµ}Àµ}À·}Àµ}À·}è¿µ}é¿·}Ô¿µ}Õ¿·}¼¿µ}½¿·}ª¿µ}«¿·}¿µ}¿·}¿µ}¿·}¿µ}¿·}ì¾µ}í¾·}Ö¾µ}×¾·}Ê¾µ}Ë¾·}À¾µ}Á¾·}¾¾µ}¿¾·}§¾ñ¾ï¾ï¾ñû½ñþ½ï¾ï¾ñù½ñü½ïË¾ñÎ¾ïö½ï÷½ñó½ñö½ï°¾ï±¾ñã½ñæ½ïà½ïá½ñÞ½ïß½ñÜ½ïÝ½ñÿ¾ñ¿ïÅ½ñÈ½ï»½ñ¾½ï±¿ñ´¿ï§¾ñª¾ï¿ï¿ñ«½ñ®½ï½ñ¢½ï½ñ½ï½ñ½ïþ¼ïÿ¼ñö¼ï÷¼ñÖ¼ï×¼ñÂ¼ïÃ¼ñª¼ï«¼ñ¼ï¼ñ¼ï¼ñú»ïû»ñö»ï÷»ñÚ»ïÛ»ñÄ»ïÅ»ñ¸»ï¹»ñ®»ï¯»ñ¬»ï­»ñ§÷º«úº©òº©óº«éº«ìº©ôº©õº«çº«êº©¹»«¼»©äº©åº«áº«äº©»©»«Ñº«Ôº©Îº©Ïº«Ìº©Íº«Êº©Ëº«í»«ð»©³º«¶º©©º«¬º©¼«¢¼©»«»©ð»©ñ»«º«º©º«º©ù¹«ü¹©ó¹«ö¹©ì¹©í¹«ä¹©å¹«Ä¹©Å¹«°¹©±¹«¹©¹«¹©¹«ò¸©ó¸«è¸©é¸«ä¸©å¸«È¸©É¸«²¸©³¸«¦¸©§¸«¸©¸«¸©¸«§å·åè·ãà·ãá·å×·åÚ·ãâ·ãã·åÕ·åØ·ã§¸åª¸ãÒ·ãÓ·åÏ·åÒ·ã¸ã¸å¿·åÂ·ã¼·ã½·åº·ã»·å¸·ã¹·åÛ¸åÞ¸ã¡·å¤·ã·å·ã¹å¹ã¸å¸ãÞ¸ãß¸å·å·ãû¶åþ¶ãç¶åê¶ãá¶åä¶ãÚ¶ãÛ¶åÒ¶ãÓ¶å²¶ã³¶å¶ã¶å¶ã¶åôµãõµåàµãáµåÖµã×µåÒµãÓµå¶µã·µå µã¡µåµãµåµãµåµãµå§Ó´Ö´Î´Ï´Å´È´Ð´Ñ´Ã´Æ´µµÀ´Á´½´À´ú´û´­´°´ª´«´¨´©´¦´§´ÉµÌµ´´´´ûµþµñ´ô´ÌµÍµõ³ø³é³ì³Õ³Ø³Ï³Ò³È³É³À³Á³ ³¡³³³ô²õ²â²ã²Î²Ï²Ä²Å²À²Á²¤²¥²²²²²ø±ù±ö±÷±§Á±ÙÄ±×¼±×½±Ù³±Ù¶±×¾±×¿±Ù±±Ù´±×²Ù²×®±×¯±Ù«±Ù®±×è±×é±Ù±Ù±×±×±Ù±×±Ù±×±Ù·²Ùº²×ý°Ù±×ó°Ùö°×é²Ùì²×ß±Ùâ±×º²×»²Ùã°Ùæ°××°ÙÚ°×Ã°ÙÆ°×½°ÙÀ°×¶°×·°Ù®°×¯°Ù°×°Ùú¯×û¯Ùâ¯×ã¯ÙÐ¯×Ñ¯Ù¼¯×½¯Ù²¯×³¯Ù®¯×¯¯Ù¯×¯Ùü®×ý®Ùð®×ñ®Ùæ®×ç®Ùä®×å®Ù§¯®²®ª®«®¡®¤®¬®­®®¢®ñ®ô®®®®®Ö®×®®®®®®®®®¥¯¨¯ë­î­á­ä­×¯Ú¯Í®Ð®¨¯©¯Ñ­Ô­Å­È­±­´­«­®­¤­¥­­­ü¬ý¬è¬é¬Ð¬Ñ¬¾¬¿¬ª¬«¬ ¬¡¬¬¬¬¬ê«ë«Þ«ß«Ô«Õ«Ò«Ó«§«Í£ «Ë£«Ë£«Í£«Í£«Ë£«Ë£«Í£«Í£«Ë£ß«Í£â«Ë£«Ë£«Í£«Í£«Ë£Ä«Ë£Å«Í£÷ªÍ£úªË£ôªË£õªÍ£òªË£óªÍ£ðªË£ñªÍ£¬Í£¬Ë£ÙªÍ£ÜªË£ÏªÍ£ÒªË£Å¬Í£È¬Ë£»«Í£¾«Ë£¬Ë£¬Í£¿ªÍ£ÂªË£³ªÍ£¶ªË£ªÍ£¢ªË£ªÍ£ªË£ªË£ªÍ£ªË£ªÍ£ê©Ë£ë©Í£Ö©Ë£×©Í£¾©Ë£¿©Í£¬©Ë£­©Í£©Ë£©Í£©Ë£©Í£©Ë£©Í£î¨Ë£ï¨Í£Ø¨Ë£Ù¨Í£Ì¨Ë£Í¨Í£Â¨Ë£Ã¨Í£À¨Ë£Á¨Í£§¨©¨©¨©¨©ý§©¨©¨©¨©û§©þ§©Í¨©Ð¨©ø§©ù§©õ§©ø§©²¨©³¨©å§©è§©â§©ã§©à§©á§©Þ§©ß§©©©©©Ç§©Ê§©½§©À§©³©©¶©©©¨©¬¨©©©©©­§©°§©¡§©¤§©§©§©§©§©§©§©ø¦©ù¦©Ø¦©Ù¦©Ä¦©Å¦©¬¦©­¦©¦©¦©¦©¦©ü¥©ý¥©ø¥©ù¥©Ü¥©Ý¥©Æ¥©Ç¥©º¥©»¥©°¥©±¥©®¥©¯¥©§ù¤Á®ü¤¿®ô¤¿®õ¤Á®ë¤Á®î¤¿®ö¤¿®÷¤Á®é¤Á®ì¤¿®»¥Á®¾¥¿®æ¤¿®ç¤Á®ã¤Á®æ¤¿® ¥¿®¡¥Á®Ó¤Á®Ö¤¿®Ð¤¿®Ñ¤Á®Î¤¿®Ï¤Á®Ì¤¿®Í¤Á®ï¥Á®ò¥¿®µ¤Á®¸¤¿®«¤Á®®¤¿®¡¦Á®¤¦¿®¥Á®¥¿®ò¥¿®ó¥Á®¤Á®¤¿®¤Á®¤¿®û£Á®þ£¿®õ£Á®ø£¿®î£¿®ï£Á®æ£¿®ç£Á®Æ£¿®Ç£Á®²£¿®³£Á®£¿®£Á®£¿®£Á®ô¢¿®õ¢Á®ê¢¿®ë¢Á®æ¢¿®ç¢Á®Ê¢¿®Ë¢Á®´¢¿®µ¢Á®¨¢¿®©¢Á®¢¿®¢Á®¢¿®¢Á®§ç¡û³ê¡ù³â¡ù³ã¡û³Ù¡û³Ü¡ù³ä¡ù³å¡û³×¡û³Ú¡ù³©¢û³¬¢ù³Ô¡ù³Õ¡û³Ñ¡û³Ô¡ù³¢ù³¢û³Á¡û³Ä¡ù³¾¡ù³¿¡û³¼¡ù³½¡û³º¡ù³»¡û³Ý¢û³à¢ù³£¡û³¦¡ù³¡û³¡ù³£û³£ù³¢û³¢ù³à¢ù³á¢û³¡û³¡ù³ý û³¡ù³é û³ì ù³ã û³æ ù³Ü ù³Ý û³Ô ù³Õ û³´ ù³µ û³  ù³¡ û³ ù³ û³öù³÷û³âù³ãû³Øù³Ùû³Ôù³Õû³¸ù³¹û³¢ù³£û³ù³û³ù³û³ù³û³§Õµ¹Ø³¹Ð³¹Ñµ¹Çµ¹Ê³¹Ò³¹Óµ¹Åµ¹È³¹µ¹³¹Â³¹Ãµ¹¿µ¹Â³¹ü³¹ýµ¹¯µ¹²³¹¬³¹­µ¹ª³¹«µ¹¨³¹©µ¹Ëµ¹Î³¹µ¹³¹µ¹³¹ýµ¹ ³¹óµ¹ö³¹Î³¹Ïµ¹÷µ¹ú³¹ëµ¹î³¹×µ¹Ú³¹Ñµ¹Ô³¹Ê³¹Ëµ¹Â³¹Ãµ¹¢³¹£µ¹³¹µ¹ö³¹÷µ¹ä³¹åµ¹Ð³¹Ñµ¹Æ³¹Çµ¹Â³¹Ãµ¹¦³¹§µ¹³¹µ¹³¹µ¹ú³¹ûµ¹ø³¹ùµ¹§Ãï¾Æí¾¾í¾¿ï¾µï¾¸í¾Àí¾Áï¾³ï¾¶í¾ï¾í¾°í¾±ï¾­ï¾°í¾êí¾ëï¾ï¾ í¾í¾ï¾í¾ï¾í¾ï¾¹ï¾¼í¾ÿï¾í¾õï¾øí¾ëï¾îí¾áï¾äí¾¼í¾½ï¾åï¾èí¾Ùï¾Üí¾Åï¾Èí¾¿ï¾Âí¾¸í¾¹ï¾°í¾±ï¾í¾ï¾üí¾ýï¾äí¾åï¾Òí¾Óï¾¾í¾¿ï¾´í¾µï¾°í¾±ï¾í¾ï¾þí¾ÿï¾òí¾óï¾èí¾éï¾æí¾çï¾§±©Ä´§Ä¬§Ä­©Ä£©Ä¦§Ä®§Ä¯©Ä¡©Ä¤§Äó©Äö§Ä§Ä©Ä©Ä§ÄØ§ÄÙ©Ä©Ä§Ä§Ä©Ä§Ä©Ä§Ä©Ä§©Äª§Äí©Äð§Äã©Äæ§ÄÙ©ÄÜ§ÄÏ©ÄÒ§Äª§Ä«©ÄÓ©ÄÖ§ÄÇ©ÄÊ§Ä³©Ä¶§Ä­©Ä°§Ä¦§Ä§©Ä§Ä©Äþ§Äÿ©Äê§Äë©ÄÒ§ÄÓ©ÄÀ§ÄÁ©Ä¬§Ä­©Ä¢§Ä£©Ä§Ä©Ä§Ä©Äì§Äí©Äà§Äá©ÄÖ§Ä×©ÄÔ§ÄÕ©Ä§ãÉ¢áÉáÉãÉãÉáÉáÉãÉãÉáÉáãÉäáÉáÉãÉãÉáÉÆáÉÇãÉùãÉüáÉöáÉ÷ãÉôáÉõãÉòáÉóãÉãÉáÉÛãÉÞáÉÑãÉÔáÉÇãÉÊáÉ½ãÉÀáÉáÉãÉÁãÉÄáÉµãÉ¸áÉ¡ãÉ¤áÉãÉáÉáÉãÉáÉãÉìáÉíãÉØáÉÙãÉÀáÉÁãÉ®áÉ¯ãÉáÉãÉáÉãÉáÉãÉðáÉñãÉÚáÉÛãÉÎáÉÏãÉÄáÉÅãÉÂáÉÃãÉ§ÏÏÏÏÿÏÏÏÏýÏÏÏÏÒÏúÏûÏ÷ÏúÏ´ÏµÏçÏêÏäÏåÏâÏãÏàÏáÏÏÏÉÏÌÏ¿ÏÂÏµÏ¸Ï«Ï®ÏÏÏ¯Ï²Ï£Ï¦ÏÏÏÏÏÏÏúÏûÏÚÏÛÏÆÏÇÏ®Ï¯ÏÏÏÏÏþÏÿÏúÏûÏÞÏßÏÈÏÉÏ¼Ï½Ï²Ï³Ï°Ï±Ï§û×ÔþÕÔöÕÔ÷×Ôí×ÔðÕÔøÕÔù×Ôë×ÔîÕÔ½×ÔÀÕÔèÕÔé×Ôå×ÔèÕÔ¢ÕÔ£×ÔÕ×ÔØÕÔÒÕÔÓ×ÔÐÕÔÑ×ÔÎÕÔÏ×Ôñ×ÔôÕÔ·×ÔºÕÔ­×Ô°ÕÔ£×Ô¦ÕÔ×ÔÕÔôÕÔõ×Ô×Ô ÕÔ×ÔÕÔý×ÔÕÔ÷×ÔúÕÔðÕÔñ×ÔèÕÔé×ÔÈÕÔÉ×Ô´ÕÔµ×ÔÕÔ×ÔÕÔ×ÔöÕÔ÷×ÔìÕÔí×ÔèÕÔé×ÔÌÕÔÍ×Ô¶ÕÔ·×ÔªÕÔ«×Ô ÕÔ¡×ÔÕÔ×Ô§éÚìÚäÚåÚÛÚÞÚæÚçÚÙÚÜÚ«Ú®ÚÖÚ×ÚÓÚÖÚÚÚÃÚÆÚÀÚÁÚ¾Ú¿Ú¼Ú½ÚßÚâÚ¥Ú¨ÚÚÚÚÚÚÚâÚãÚÚÚÿÚÚëÚîÚåÚèÚÞÚßÚÖÚ×Ú¶Ú·Ú¢Ú£ÚÚÚøÚùÚäÚåÚÚÚÛÚÖÚ×ÚºÚ»Ú¤Ú¥ÚÚÚÚÚÚÚ§×ËßÚÉßÒÉßÓËßÉËßÌÉßÔÉßÕËßÇËßÊÉßËßÉßÄÉßÅËßÁËßÄÉßþÉßÿËß±Ëß´Éß®Éß¯Ëß¬Éß­ËßªÉß«ËßÍËßÐÉßËßÉßËßÉßÿËßÉßõËßøÉßÐÉßÑËßùËßüÉßíËßðÉßÙËßÜÉßÓËßÖÉßÌÉßÍËßÄÉßÅËß¤Éß¥ËßÉßËßøÉßùËßæÉßçËßÒÉßÓËßÈÉßÉËßÄÉßÅËß¨Éß©ËßÉßËßÉßËßüÉßýËßúÉßûËß§ÅåÈåÀåÁå·åºåÂåÃåµå¸ååå²å³å¯å²åìåíåå¢ååååååå»å¾ååå÷åúåíåðåãåæå¾å¿åçåêåÛåÞåÇåÊåÁåÄåºå»å²å³åååþåÿåæåçåÔåÕåÀåÁå¶å·å²å³åååååôåõåêåëåèåéå§³¿ê¶½ê®½ê¯¿ê¥¿ê¨½ê°½ê±¿ê£¿ê¦½êõ¿êø½ê ½ê¡¿ê¿ê ½êÚ½êÛ¿ê¿ê½ê½ê¿ê½ê¿ê½ê¿ê©¿ê¬½êï¿êò½êå¿êè½êÛ¿êÞ½êÑ¿êÔ½ê¬½ê­¿êÕ¿êØ½êÉ¿êÌ½êµ¿ê¸½ê¯¿ê²½ê¨½ê©¿ê ½ê¡¿ê½ê¿êì½êí¿êÔ½êÕ¿êÂ½êÃ¿ê®½ê¯¿ê¤½ê¥¿ê ½ê¡¿ê½ê¿êîÿ
+½êïÿ
+¿êâÿ
+½êãÿ
+¿êØÿ
+½êÙÿ
+¿êÖÿ
+½ê×ÿ
+¿ê§¡ÿ
+ùï¤ÿ
+÷ïÿ
+÷ïÿ
+ùïÿ
+ùïÿ
+÷ïÿ
+÷ïÿ
+ùïÿ
+ùïÿ
+÷ïãÿ
+ùïæÿ
+÷ïÿ
+÷ïÿ
+ùïÿ
+ùïÿ
+÷ïÈÿ
+÷ïÉÿ
+ùïûþ
+ùïþþ
+÷ïøþ
+÷ïùþ
+ùïöþ
+÷ï÷þ
+ùïôþ
+÷ïõþ
+ùïùï÷ïÝþ
+ùïàþ
+÷ïÓþ
+ùïÖþ
+÷ïÉùïÌ÷ï¿ÿ
+ùïÂÿ
+÷ï÷ïùïÃþ
+ùïÆþ
+÷ï·þ
+ùïºþ
+÷ï£þ
+ùï¦þ
+÷ïþ
+ùï þ
+÷ïþ
+÷ïþ
+ùïþ
+÷ïþ
+ùïîý
+÷ïïý
+ùïÚý
+÷ïÛý
+ùïÂý
+÷ïÃý
+ùï°ý
+÷ï±ý
+ùïý
+÷ïý
+ùïý
+÷ïý
+ùïý
+÷ïý
+ùïòü
+÷ïóü
+ùïÜü
+÷ïÝü
+ùïÐü
+÷ïÑü
+ùïÆü
+÷ïÇü
+ùïÄü
+÷ïÅü
+ùï§ü
+³õü
+±õü
+±õü
+³õü
+³õü
+±õü
+±õü
+³õÿû
+³õü
+±õÑü
+³õÔü
+±õüû
+±õýû
+³õùû
+³õüû
+±õ¶ü
+±õ·ü
+³õéû
+³õìû
+±õæû
+±õçû
+³õäû
+±õåû
+³õâû
+±õãû
+³õý
+³õý
+±õËû
+³õÎû
+±õÁû
+³õÄû
+±õ·ý
+³õºý
+±õ­ü
+³õ°ü
+±õý
+±õý
+³õ±û
+³õ´û
+±õ¥û
+³õ¨û
+±õû
+³õû
+±õû
+³õû
+±õû
+±õû
+³õüú
+±õýú
+³õÜú
+±õÝú
+³õÈú
+±õÉú
+³õ°ú
+±õ±ú
+³õú
+±õú
+³õú
+±õú
+³õú
+±õú
+³õüù
+±õýù
+³õàù
+±õáù
+³õÊù
+±õËù
+³õ¾ù
+±õ¿ù
+³õ´ù
+±õµù
+³õ²ù
+±õ³ù
+³õ§õè»øè¹ðè¹ñè»çè»êè¹òè¹óè»åè»èè¹·é»ºé¹âè¹ãè»ßè»âè¹é¹é»Ïè»Òè¹Ìè¹Íè»Êè¹Ëè»Èè¹Éè»ëé»îé¹±è»´è¹§è»ªè¹ê» ê¹é»é¹îé¹ïé»è»è¹è»è¹÷ç»úç¹ñç»ôç¹êç¹ëç»âç¹ãç»Âç¹Ãç»®ç¹¯ç»ç¹ç»ç¹ç»ðæ¹ñæ»ææ¹çæ»âæ¹ãæ»Ææ¹Çæ»°æ¹±æ»¤æ¹¥æ»æ¹æ»æ¹æ»§ãåõ
+æåó
+Þåó
+ßåõ
+Õåõ
+Øåó
+àåó
+áåõ
+Óåõ
+Öåó
+¥æõ
+¨æó
+Ðåó
+Ñåõ
+Íåõ
+Ðåó
+æó
+æõ
+½åõ
+Àåó
+ºåó
+»åõ
+¸åó
+¹åõ
+¶åó
+·åõ
+Ùæõ
+Üæó
+åõ
+¢åó
+åõ
+åó
+çõ
+çó
+æõ
+æó
+Üæó
+Ýæõ
+åõ
+åó
+ùäõ
+üäó
+åäõ
+èäó
+ßäõ
+âäó
+Øäó
+Ùäõ
+Ðäó
+Ñäõ
+°äó
+±äõ
+äó
+äõ
+äó
+äõ
+òãó
+óãõ
+Þãó
+ßãõ
+Ôãó
+Õãõ
+Ðãó
+Ñãõ
+´ãó
+µãõ
+ãó
+ãõ
+ãó
+ãõ
+ãó
+ãõ
+ãó
+ãõ
+§Ñâ¯Ôâ­Ìâ­Íâ¯Ãâ¯Æâ­Îâ­Ïâ¯Áâ¯Äâ­ã¯ã­¾â­¿â¯»â¯¾â­øâ­ùâ¯«â¯®â­¨â­©â¯¦â­§â¯¤â­¥â¯Çã¯Êã­â¯â­â¯â­ùã¯üã­ïâ¯òâ­Êã­Ëã¯óá¯öá­çá¯êá­Óá¯Öá­Íá¯Ðá­Æá­Çá¯¾á­¿á¯á­á¯á­á¯òà­óà¯àà­áà¯Ìà­Íà¯Âà­Ãà¯¾à­¿à¯¢à­£à¯à­à¯à­à¯öß­÷ß¯ôß­õß¯§¿ßéÂßçºßç»ßé±ßé´ßç¼ßç½ßé¯ßé²ßçàéàç¬ßç­ßé©ßé¬ßçæßççßéßéßçßçßéßçßéßçßéµàé¸àçûÞéþÞçñÞéôÞççàéêàçÝßéàßç¸àç¹àéáÞéäÞçÕÞéØÞçÁÞéÄÞç»Þé¾Þç´ÞçµÞé¬Þç­ÞéÞçÞéøÝçùÝéàÝçáÝéÎÝçÏÝéºÝç»Ýé°Ýç±Ýé¬Ýç­ÝéÝçÝéúÜçûÜéîÜçïÜéäÜçåÜéâÜçãÜé§­Ü£°Ü¡¨Ü¡©Ü£Ü£¢Ü¡ªÜ¡«Ü£Ü£ Ü¡ïÜ£òÜ¡Ü¡Ü£Ü£Ü¡ÔÜ¡ÕÜ£Ü£Ü¡Ü¡Ü£Ü¡Ü£Ü¡Ü££Ý£¦Ý¡éÛ£ìÛ¡ßÛ£âÛ¡ÕÝ£ØÝ¡ËÜ£ÎÜ¡¦Ý¡§Ý£ÏÛ£ÒÛ¡ÃÛ£ÆÛ¡¯Û£²Û¡©Û£¬Û¡¢Û¡£Û£Û¡Û£úÚ¡ûÚ£æÚ¡çÚ£ÎÚ¡ÏÚ£¼Ú¡½Ú£¨Ú¡©Ú£Ú¡Ú£Ú¡Ú£þÙ¡ÿÙ£èÙ¡éÙ£ÜÙ¡ÝÙ£ÒÙ¡ÓÙ£ÐÙ¡ÑÙ£§ÙÝ ÙÛ ÙÛ ÙÝ ÙÝ ÙÛ ÙÛ ÙÝ ÙÝ ÙÛ ÝÙÝ àÙÛ ÙÛ ÙÝ ÙÝ ÙÛ ÂÙÛ ÃÙÝ õØÝ øØÛ òØÛ óØÝ ðØÛ ñØÝ îØÛ ïØÝ ÚÝ ÚÛ ×ØÝ ÚØÛ ÍØÝ ÐØÛ ÃÚÝ ÆÚÛ ¹ÙÝ ¼ÙÛ ÚÛ ÚÝ ½ØÝ ÀØÛ ±ØÝ ´ØÛ ØÝ  ØÛ ØÝ ØÛ ØÛ ØÝ ØÛ ØÝ è×Û é×Ý Ô×Û Õ×Ý ¼×Û ½×Ý ª×Û «×Ý ×Û ×Ý ×Û ×Ý ×Û ×Ý ìÖÛ íÖÝ ÖÖÛ ×ÖÝ ÊÖÛ ËÖÝ ÀÖÛ ÁÖÝ ¾ÖÛ ¿ÖÝ §Ö&Ö&Ö&Ö&ûÕ&þÕ&Ö&Ö&ùÕ&üÕ&ËÖ&ÎÖ&öÕ&÷Õ&óÕ&öÕ&°Ö&±Ö&ãÕ&æÕ&àÕ&áÕ&ÞÕ&ßÕ&ÜÕ&ÝÕ&ÿÖ&×&ÅÕ&ÈÕ&»Õ&¾Õ&±×&´×&§Ö&ªÖ&×&×&«Õ&®Õ&Õ&¢Õ&Õ&Õ&Õ&Õ&þÔ&ÿÔ&öÔ&÷Ô&ÖÔ&×Ô&ÂÔ&ÃÔ&ªÔ&«Ô&Ô&Ô&Ô&Ô&úÓ&ûÓ&öÓ&÷Ó&ÚÓ&ÛÓ&ÄÓ&ÅÓ&¸Ó&¹Ó&®Ó&¯Ó&¬Ó&­Ó&§÷ÒÑ+úÒÏ+òÒÏ+óÒÑ+éÒÑ+ìÒÏ+ôÒÏ+õÒÑ+çÒÑ+êÒÏ+¹ÓÑ+¼ÓÏ+äÒÏ+åÒÑ+áÒÑ+äÒÏ+ÓÏ+ÓÑ+ÑÒÑ+ÔÒÏ+ÎÒÏ+ÏÒÑ+ÌÒÏ+ÍÒÑ+ÊÒÏ+ËÒÑ+íÓÑ+ðÓÏ+³ÒÑ+¶ÒÏ+©ÒÑ+¬ÒÏ+ÔÑ+¢ÔÏ+ÓÑ+ÓÏ+ðÓÏ+ñÓÑ+ÒÑ+ÒÏ+ÒÑ+ÒÏ+ùÑÑ+üÑÏ+óÑÑ+öÑÏ+ìÑÏ+íÑÑ+äÑÏ+åÑÑ+ÄÑÏ+ÅÑÑ+°ÑÏ+±ÑÑ+ÑÏ+ÑÑ+ÑÏ+ÑÑ+òÐÏ+óÐÑ+èÐÏ+éÐÑ+äÐÏ+åÐÑ+ÈÐÏ+ÉÐÑ+²ÐÏ+³ÐÑ+¦ÐÏ+§ÐÑ+ÐÏ+ÐÑ+ÐÏ+ÐÑ+§åÏ1èÏ1àÏ1áÏ1×Ï1ÚÏ1âÏ1ãÏ1ÕÏ1ØÏ1§Ð1ªÐ1ÒÏ1ÓÏ1ÏÏ1ÒÏ1Ð1Ð1¿Ï1ÂÏ1¼Ï1½Ï1ºÏ1»Ï1¸Ï1¹Ï1ÛÐ1ÞÐ1¡Ï1¤Ï1Ï1Ï1Ñ1Ñ1Ð1Ð1ÞÐ1ßÐ1Ï1Ï1ûÎ1þÎ1çÎ1êÎ1áÎ1äÎ1ÚÎ1ÛÎ1ÒÎ1ÓÎ1²Î1³Î1Î1Î1Î1Î1ôÍ1õÍ1àÍ1áÍ1ÖÍ1×Í1ÒÍ1ÓÍ1¶Í1·Í1 Í1¡Í1Í1Í1Í1Í1Í1Í1§ÓÌÅ6ÖÌÃ6ÎÌÃ6ÏÌÅ6ÅÌÅ6ÈÌÃ6ÐÌÃ6ÑÌÅ6ÃÌÅ6ÆÌÃ6ÍÅ6ÍÃ6ÀÌÃ6ÁÌÅ6½ÌÅ6ÀÌÃ6úÌÃ6ûÌÅ6­ÌÅ6°ÌÃ6ªÌÃ6«ÌÅ6¨ÌÃ6©ÌÅ6¦ÌÃ6§ÌÅ6ÉÍÅ6ÌÍÃ6ÌÅ6ÌÃ6ÌÅ6ÌÃ6ûÍÅ6þÍÃ6ñÌÅ6ôÌÃ6ÌÍÃ6ÍÍÅ6õËÅ6øËÃ6éËÅ6ìËÃ6ÕËÅ6ØËÃ6ÏËÅ6ÒËÃ6ÈËÃ6ÉËÅ6ÀËÃ6ÁËÅ6 ËÃ6¡ËÅ6ËÃ6ËÅ6ôÊÃ6õÊÅ6âÊÃ6ãÊÅ6ÎÊÃ6ÏÊÅ6ÄÊÃ6ÅÊÅ6ÀÊÃ6ÁÊÅ6¤ÊÃ6¥ÊÅ6ÊÃ6ÊÅ6ÊÃ6ÊÅ6øÉÃ6ùÉÅ6öÉÃ6÷ÉÅ6§ÁÉÿ;ÄÉý;¼Éý;½Éÿ;³Éÿ;¶Éý;¾Éý;¿Éÿ;±Éÿ;´Éý;Êÿ;Êý;®Éý;¯Éÿ;«Éÿ;®Éý;èÉý;éÉÿ;Éÿ;Éý;Éý;Éÿ;Éý;Éÿ;Éý;Éÿ;·Êÿ;ºÊý;ýÈÿ;Éý;óÈÿ;öÈý;éÊÿ;ìÊý;ßÉÿ;âÉý;ºÊý;»Êÿ;ãÈÿ;æÈý;×Èÿ;ÚÈý;ÃÈÿ;ÆÈý;½Èÿ;ÀÈý;¶Èý;·Èÿ;®Èý;¯Èÿ;Èý;Èÿ;úÇý;ûÇÿ;âÇý;ãÇÿ;ÐÇý;ÑÇÿ;¼Çý;½Çÿ;²Çý;³Çÿ;®Çý;¯Çÿ;Çý;Çÿ;üÆý;ýÆÿ;ðÆý;ñÆÿ;æÆý;çÆÿ;äÆý;åÆÿ;§¯Æ¹A²Æ·AªÆ·A«Æ¹A¡Æ¹A¤Æ·A¬Æ·A­Æ¹AÆ¹A¢Æ·AñÆ¹AôÆ·AÆ·AÆ¹AÆ¹AÆ·AÖÆ·A×Æ¹AÆ¹AÆ·AÆ·AÆ¹AÆ·AÆ¹AÆ·AÆ¹A¥Ç¹A¨Ç·AëÅ¹AîÅ·AáÅ¹AäÅ·A×Ç¹AÚÇ·AÍÆ¹AÐÆ·A¨Ç·A©Ç¹AÑÅ¹AÔÅ·AÅÅ¹AÈÅ·A±Å¹A´Å·A«Å¹A®Å·A¤Å·A¥Å¹AÅ·AÅ¹AüÄ·AýÄ¹AèÄ·AéÄ¹AÐÄ·AÑÄ¹A¾Ä·A¿Ä¹AªÄ·A«Ä¹A Ä·A¡Ä¹AÄ·AÄ¹AÄ·AÄ¹AêÃ·AëÃ¹AÞÃ·AßÃ¹AÔÃ·AÕÃ¹AÒÃ·AÓÃ¹A§ÃóF ÃñFÃñFÃóFÃóFÃñFÃñFÃóFÃóFÃñFßÃóFâÃñFÃñFÃóFÃóFÃñFÄÃñFÅÃóF÷ÂóFúÂñFôÂñFõÂóFòÂñFóÂóFðÂñFñÂóFÄóFÄñFÙÂóFÜÂñFÏÂóFÒÂñFÅÄóFÈÄñF»ÃóF¾ÃñFÄñFÄóF¿ÂóFÂÂñF³ÂóF¶ÂñFÂóF¢ÂñFÂóFÂñFÂñFÂóFÂñFÂóFêÁñFëÁóFÖÁñF×ÁóF¾ÁñF¿ÁóF¬ÁñF­ÁóFÁñFÁóFÁñFÁóFÁñFÁóFîÀñFïÀóFØÀñFÙÀóFÌÀñFÍÀóFÂÀñFÃÀóFÀÀñFÁÀóF§À­LÀ«LÀ«LÀ­Lý¿­LÀ«LÀ«LÀ­Lû¿­Lþ¿«LÍÀ­LÐÀ«Lø¿«Lù¿­Lõ¿­Lø¿«L²À«L³À­Lå¿­Lè¿«Lâ¿«Lã¿­Là¿«Lá¿­LÞ¿«Lß¿­LÁ­LÁ«LÇ¿­LÊ¿«L½¿­LÀ¿«L³Á­L¶Á«L©À­L¬À«LÁ«LÁ­L­¿­L°¿«L¡¿­L¤¿«L¿­L¿«L¿­L¿«L¿«L¿­Lø¾«Lù¾­LØ¾«LÙ¾­LÄ¾«LÅ¾­L¬¾«L­¾­L¾«L¾­L¾«L¾­Lü½«Lý½­Lø½«Lù½­LÜ½«LÝ½­LÆ½«LÇ½­Lº½«L»½­L°½«L±½­L®½«L¯½­L§ù¼çQü¼åQô¼åQõ¼çQë¼çQî¼åQö¼åQ÷¼çQé¼çQì¼åQ»½çQ¾½åQæ¼åQç¼çQã¼çQæ¼åQ ½åQ¡½çQÓ¼çQÖ¼åQÐ¼åQÑ¼çQÎ¼åQÏ¼çQÌ¼åQÍ¼çQï½çQò½åQµ¼çQ¸¼åQ«¼çQ®¼åQ¡¾çQ¤¾åQ½çQ½åQò½åQó½çQ¼çQ¼åQ¼çQ¼åQû»çQþ»åQõ»çQø»åQî»åQï»çQæ»åQç»çQÆ»åQÇ»çQ²»åQ³»çQ»åQ»çQ»åQ»çQôºåQõºçQêºåQëºçQæºåQçºçQÊºåQËºçQ´ºåQµºçQ¨ºåQ©ºçQºåQºçQºåQºçQ§ç¹¡Wê¹Wâ¹Wã¹¡WÙ¹¡WÜ¹Wä¹Wå¹¡W×¹¡WÚ¹W©º¡W¬ºWÔ¹WÕ¹¡WÑ¹¡WÔ¹WºWº¡WÁ¹¡WÄ¹W¾¹W¿¹¡W¼¹W½¹¡Wº¹W»¹¡WÝº¡WàºW£¹¡W¦¹W¹¡W¹W»¡W»Wº¡WºWàºWáº¡W¹¡W¹Wý¸¡W¹Wé¸¡Wì¸Wã¸¡Wæ¸WÜ¸WÝ¸¡WÔ¸WÕ¸¡W´¸Wµ¸¡W ¸W¡¸¡W¸W¸¡Wö·W÷·¡Wâ·Wã·¡WØ·WÙ·¡WÔ·WÕ·¡W¸·W¹·¡W¢·W£·¡W·W·¡W·W·¡W·W·¡W§Õ¶Û\Ø¶Ù\Ð¶Ù\Ñ¶Û\Ç¶Û\Ê¶Ù\Ò¶Ù\Ó¶Û\Å¶Û\È¶Ù\·Û\·Ù\Â¶Ù\Ã¶Û\¿¶Û\Â¶Ù\ü¶Ù\ý¶Û\¯¶Û\²¶Ù\¬¶Ù\­¶Û\ª¶Ù\«¶Û\¨¶Ù\©¶Û\Ë·Û\Î·Ù\¶Û\¶Ù\¶Û\¶Ù\ý·Û\¸Ù\ó¶Û\ö¶Ù\Î·Ù\Ï·Û\÷µÛ\úµÙ\ëµÛ\îµÙ\×µÛ\ÚµÙ\ÑµÛ\ÔµÙ\ÊµÙ\ËµÛ\ÂµÙ\ÃµÛ\¢µÙ\£µÛ\µÙ\µÛ\ö´Ù\÷´Û\ä´Ù\å´Û\Ð´Ù\Ñ´Û\Æ´Ù\Ç´Û\Â´Ù\Ã´Û\¦´Ù\§´Û\´Ù\´Û\´Ù\´Û\ú³Ù\û³Û\ø³Ù\ù³Û\§Ã³bÆ³b¾³b¿³bµ³b¸³bÀ³bÁ³b³³b¶³b´b´b°³b±³b­³b°³bê³bë³b³b ³b³b³b³b³b³b³b¹´b¼´bÿ²b³bõ²bø²bë´bî´bá³bä³b¼´b½´bå²bè²bÙ²bÜ²bÅ²bÈ²b¿²bÂ²b¸²b¹²b°²b±²b²b²bü±bý±bä±bå±bÒ±bÓ±b¾±b¿±b´±bµ±b°±b±±b±b±bþ°bÿ°bò°bó°bè°bé°bæ°bç°b§±°Ïg´°Íg¬°Íg­°Ïg£°Ïg¦°Íg®°Íg¯°Ïg¡°Ïg¤°Ígó°Ïgö°Íg°Íg°Ïg°Ïg°ÍgØ°ÍgÙ°Ïg°Ïg°Íg°Íg°Ïg°Íg°Ïg°Íg°Ïg§±Ïgª±Ígí¯Ïgð¯Ígã¯Ïgæ¯ÍgÙ±ÏgÜ±ÍgÏ°ÏgÒ°Ígª±Íg«±ÏgÓ¯ÏgÖ¯ÍgÇ¯ÏgÊ¯Íg³¯Ïg¶¯Íg­¯Ïg°¯Íg¦¯Íg§¯Ïg¯Íg¯Ïgþ®Ígÿ®Ïgê®Ígë®ÏgÒ®ÍgÓ®ÏgÀ®ÍgÁ®Ïg¬®Íg­®Ïg¢®Íg£®Ïg®Íg®Ïg®Íg®Ïgì­Ígí­Ïgà­Ígá­ÏgÖ­Íg×­ÏgÔ­ÍgÕ­Ïg§­m¢­m­m­m­m­m­m­m­m­má­mä­m­m­m­m­mÆ­mÇ­mù¬mü¬mö¬m÷¬mô¬mõ¬mò¬mó¬m®m®mÛ¬mÞ¬mÑ¬mÔ¬mÇ®mÊ®m½­mÀ­m®m®mÁ¬mÄ¬mµ¬m¸¬m¡¬m¤¬m¬m¬m¬m¬m¬m¬mì«mí«mØ«mÙ«mÀ«mÁ«m®«m¯«m«m«m«m«m«m«mðªmñªmÚªmÛªmÎªmÏªmÄªmÅªmÂªmÃªm§ªÃrªÁrªÁrªÃrÿ©ÃrªÁrªÁrªÃrý©ÃrªÁrÏªÃrÒªÁrú©Árû©Ãr÷©Ãrú©Ár´ªÁrµªÃrç©Ãrê©Árä©Árå©Ãrâ©Árã©Ãrà©Árá©Ãr«Ãr«ÁrÉ©ÃrÌ©Ár¿©ÃrÂ©Árµ«Ãr¸«Ár«ªÃr®ªÁr«Ár«Ãr¯©Ãr²©Ár£©Ãr¦©Ár©Ãr©Ár©Ãr©Ár©Ár©Ãrú¨Árû¨ÃrÚ¨ÁrÛ¨ÃrÆ¨ÁrÇ¨Ãr®¨Ár¯¨Ãr¨Ár¨Ãr¨Ár¨Ãrþ§Árÿ§Ãrú§Árû§ÃrÞ§Árß§ÃrÈ§ÁrÉ§Ãr¼§Ár½§Ãr²§Ár³§Ãr°§Ár±§Ãr§û¦ýwþ¦ûwö¦ûw÷¦ýwí¦ýwð¦ûwø¦ûwù¦ýwë¦ýwî¦ûw½§ýwÀ§ûwè¦ûwé¦ýwå¦ýwè¦ûw¢§ûw£§ýwÕ¦ýwØ¦ûwÒ¦ûwÓ¦ýwÐ¦ûwÑ¦ýwÎ¦ûwÏ¦ýwñ§ýwô§ûw·¦ýwº¦ûw­¦ýw°¦ûw£¨ýw¦¨ûw§ýw§ûwô§ûwõ§ýw¦ýw ¦ûw¦ýw¦ûwý¥ýw¦ûw÷¥ýwú¥ûwð¥ûwñ¥ýwè¥ûwé¥ýwÈ¥ûwÉ¥ýw´¥ûwµ¥ýw¥ûw¥ýw¥ûw¥ýwö¤ûw÷¤ýwì¤ûwí¤ýwè¤ûwé¤ýwÌ¤ûwÍ¤ýw¶¤ûw·¤ýwª¤ûw«¤ýw ¤ûw¡¤ýw¤ûw¤ýw§é£·}ì£µ}ä£µ}å£·}Û£·}Þ£µ}æ£µ}ç£·}Ù£·}Ü£µ}«¤·}®¤µ}Ö£µ}×£·}Ó£·}Ö£µ}¤µ}¤·}Ã£·}Æ£µ}À£µ}Á£·}¾£µ}¿£·}¼£µ}½£·}ß¤·}â¤µ}¥£·}¨£µ}£·}£µ}¥·}¥µ}¤·}¤µ}â¤µ}ã¤·}£·}£µ}ÿ¢·}£µ}ë¢·}î¢µ}å¢·}è¢µ}Þ¢µ}ß¢·}Ö¢µ}×¢·}¶¢µ}·¢·}¢¢µ}£¢·}¢µ}¢·}ø¡µ}ù¡·}ä¡µ}å¡·}Ú¡µ}Û¡·}Ö¡µ}×¡·}º¡µ}»¡·}¤¡µ}¥¡·}¡µ}¡·}¡µ}¡·}¡µ}¡·}§× ñÚ ïÒ ïÓ ñÉ ñÌ ïÔ ïÕ ñÇ ñÊ ï¡ñ¡ïÄ ïÅ ñÁ ñÄ ïþ ïÿ ñ± ñ´ ï® ï¯ ñ¬ ï­ ñª ï« ñÍ¡ñÐ¡ï ñ ï ñ ïÿ¡ñ¢ïõ ñø ïÐ¡ïÑ¡ñùñüïíñðïÙñÜïÓñÖïÌïÍñÄïÅñ¤ï¥ñïñøïùñæïçñÒïÓñÈïÉñÄïÅñ¨ï©ñïñïñüïýñúïûñ§Å«È©À©Á«·«º©Â©Ã«µ«¸©«©²©³«¯«²©ì©í««¢©©«©«©«»«¾©«©÷«ú©í«ð©ã«æ©¾©¿«ç«ê©Û«Þ©Ç«Ê©Á«Ä©º©»«²©³«©«þ©ÿ«æ©ç«Ô©Õ«À©Á«¶©·«²©³«©«©«ô©õ«ê©ë«è©é«§³å¶ã®ã¯å¥å¨ã°ã±å£å¦ãõåøã ã¡åå ãÚãÛååããåãåãå©å¬ãïåòãååèãÛåÞãÑåÔã¬ã­åÕåØãÉåÌãµå¸ã¯å²ã¨ã©å ã¡åãåìãíåÔãÕåÂãÃå®ã¯å¤ã¥å ã¡åãåîãïåâããåØãÙåÖã×å§¡¤ãæÈÉûþøùö÷ôõÝàÓÖÉÌ¿ÂÃÆ·º£¦ îïÚÛÂÃ°±òóÜÝÐÑÆÇÄÅ§Ù××ÙÙ××ÙÿÙ×ÑÙÔ×ü×ýÙùÙü×¶×·ÙéÙì×æ×çÙä×åÙâ×ãÙÙ×ËÙÎ×ÁÙÄ×·Ùº×­Ù°××Ù±Ù´×¥Ù¨×Ù×Ù××Ùü×ýÙÜ×ÝÙÈ×ÉÙ°×±Ù×Ù×Ù×Ùü×ýÙà×áÙÊ×ËÙ¾×¿Ù´×µÙ²×³Ù§ýøùïòúûíð¿Âêëçê¤¥×ÚÔÕÒÓÐÑóö¹¼¯²¥¨ö÷¢ÿùüòóêëÊË¶·øùîïêëÎÏ¸¹¬­¢£ ¡§ëÍ£îË£æË£çÍ£ÝÍ£àË£èË£éÍ£ÛÍ£ÞË£­Í£°Ë£ØË£ÙÍ£ÕÍ£ØË£Ë£Í£ÅÍ£ÈË£ÂË£ÃÍ£ÀË£ÁÍ£¾Ë£¿Í£áÍ£äË£§Í£ªË£Í£ Ë£Í£Ë£Í£Ë£äË£åÍ£Í£Ë£Í£Ë£íÍ£ðË£çÍ£êË£àË£áÍ£ØË£ÙÍ£¸Ë£¹Í£¤Ë£¥Í£Ë£Í£úË£ûÍ£æË£çÍ£ÜË£ÝÍ£ØË£ÙÍ£¼Ë£½Í£¦Ë£§Í£Ë£Í£Ë£Í£Ë£Í£§Ù©Ü©Ô©Õ©Ë©Î©Ö©×©É©Ì©©©Æ©Ç©Ã©Æ©©©³©¶©°©±©®©¯©¬©­©Ï©Ò©©©©©©©÷©ú©Ò©Ó©û©þ©ï©ò©Û©Þ©Õ©Ø©Î©Ï©Æ©Ç©¦©§©©©ú©û©è©é©Ô©Õ©Ê©Ë©Æ©Ç©ª©«©©©©©þ©ÿ©ü©ý©§ÇÁ®Ê¿®Â¿®ÃÁ®¹Á®¼¿®Ä¿®ÅÁ®·Á®º¿®Á®¿®´¿®µÁ®±Á®´¿®î¿®ïÁ®¡Á®¤¿®¿®Á®¿®Á®¿®Á®½Á®À¿®Á®¿®ùÁ®ü¿®ïÁ®ò¿®åÁ®è¿®À¿®ÁÁ®éÁ®ì¿®ÝÁ®à¿®ÉÁ®Ì¿®ÃÁ®Æ¿®¼¿®½Á®´¿®µÁ®¿®Á®¿®Á®è¿®éÁ®Ö¿®×Á®Â¿®ÃÁ®¸¿®¹Á®´¿®µÁ®¿®Á®¿®Á®ö¿®÷Á®ì¿®íÁ®ê¿®ëÁ®§µû³¸ù³°ù³±û³§û³ªù³²ù³³û³¥û³¨ù³÷û³úù³¢ù³£û³û³¢ù³Üù³Ýû³û³ù³ù³û³ù³û³ù³û³«û³®ù³ñû³ôù³çû³êù³Ýû³àù³Óû³Öù³®ù³¯û³×û³Úù³Ëû³Îù³·û³ºù³±û³´ù³ªù³«û³¢ù³£û³ù³û³îù³ïû³Öù³×û³Äù³Åû³°ù³±û³¦ù³§û³¢ù³£û³ù³û³ðù³ñû³äù³åû³Úù³Ûû³Øù³Ùû³§£µ¹¦³¹³¹µ¹µ¹³¹ ³¹¡µ¹µ¹³¹åµ¹è³¹³¹µ¹µ¹³¹Ê³¹Ëµ¹ýµ¹³¹ú³¹ûµ¹ø³¹ùµ¹ö³¹÷µ¹µ¹³¹ßµ¹â³¹Õµ¹Ø³¹Ëµ¹Î³¹Áµ¹Ä³¹³¹µ¹Åµ¹È³¹¹µ¹¼³¹¥µ¹¨³¹µ¹¢³¹³¹µ¹³¹µ¹ðÿ³¹ñÿµ¹Üÿ³¹Ýÿµ¹Äÿ³¹Åÿµ¹²ÿ³¹³ÿµ¹ÿ³¹ÿµ¹ÿ³¹ÿµ¹ÿ³¹ÿµ¹ôþ³¹õþµ¹Þþ³¹ßþµ¹Òþ³¹Óþµ¹Èþ³¹Éþµ¹Æþ³¹Çþµ¹§þï¾þí¾þí¾þï¾þï¾þí¾þí¾þï¾þï¾þí¾Óþï¾Öþí¾þýí¾ÿýï¾ûýï¾þýí¾¸þí¾¹þï¾ëýï¾îýí¾èýí¾éýï¾æýí¾çýï¾äýí¾åýï¾ÿï¾ÿí¾Íýï¾Ðýí¾Ãýï¾Æýí¾¹ÿï¾¼ÿí¾¯þï¾²þí¾ÿí¾ÿï¾³ýï¾¶ýí¾§ýï¾ªýí¾ýï¾ýí¾ýï¾ýí¾ýí¾ýï¾þüí¾ÿüï¾Þüí¾ßüï¾Êüí¾Ëüï¾²üí¾³üï¾ üí¾¡üï¾üí¾üï¾üí¾üï¾þûí¾ÿûï¾âûí¾ãûï¾Ìûí¾Íûï¾Àûí¾Áûï¾¶ûí¾·ûï¾´ûí¾µûï¾§ÿú©Äû§Äúú§Äûú©Äñú©Äôú§Äüú§Äýú©Äïú©Äòú§ÄÁû©ÄÄû§Äìú§Äíú©Äéú©Äìú§Ä¦û§Ä§û©ÄÙú©ÄÜú§ÄÖú§Ä×ú©ÄÔú§ÄÕú©ÄÒú§ÄÓú©Äõû©Äøû§Ä»ú©Ä¾ú§Ä±ú©Ä´ú§Ä§ü©Äªü§Äû©Ä û§Äøû§Äùû©Ä¡ú©Ä¤ú§Äú©Äú§Äú©Äú§Äûù©Äþù§Äôù§Äõù©Äìù§Äíù©ÄÌù§ÄÍù©Ä¸ù§Ä¹ù©Ä ù§Ä¡ù©Äù§Äù©Äúø§Äûø©Äðø§Äñø©Äìø§Äíø©ÄÐø§ÄÑø©Äºø§Ä»ø©Ä®ø§Ä¯ø©Ä¤ø§Ä¥ø©Ä¢ø§Ä£ø©Ä§í÷ãÉð÷áÉè÷áÉé÷ãÉß÷ãÉâ÷áÉê÷áÉë÷ãÉÝ÷ãÉà÷áÉ¯øãÉ²øáÉÚ÷áÉÛ÷ãÉ×÷ãÉÚ÷áÉøáÉøãÉÇ÷ãÉÊ÷áÉÄ÷áÉÅ÷ãÉÂ÷áÉÃ÷ãÉÀ÷áÉÁ÷ãÉãøãÉæøáÉ©÷ãÉ¬÷áÉ÷ãÉ¢÷áÉùãÉùáÉøãÉøáÉæøáÉçøãÉ÷ãÉ÷áÉ÷ãÉ÷áÉïöãÉòöáÉéöãÉìöáÉâöáÉãöãÉÚöáÉÛöãÉºöáÉ»öãÉ¦öáÉ§öãÉöáÉöãÉüõáÉýõãÉèõáÉéõãÉÞõáÉßõãÉÚõáÉÛõãÉ¾õáÉ¿õãÉ¨õáÉ©õãÉõáÉõãÉõáÉõãÉõáÉõãÉ§ÛôÏÞôÏÖôÏ×ôÏÍôÏÐôÏØôÏÙôÏËôÏÎôÏõÏ õÏÈôÏÉôÏÅôÏÈôÏõÏõÏµôÏ¸ôÏ²ôÏ³ôÏ°ôÏ±ôÏ®ôÏ¯ôÏÑõÏÔõÏôÏôÏôÏôÏöÏöÏùôÏüôÏÔõÏÕõÏýóÏôÏñóÏôóÏÝóÏàóÏ×óÏÚóÏÐóÏÑóÏÈóÏÉóÏ¨óÏ©óÏóÏóÏüòÏýòÏêòÏëòÏÖòÏ×òÏÌòÏÍòÏÈòÏÉòÏ¬òÏ­òÏòÏòÏòÏòÏòÏòÏþñÏÿñÏ§Éñ×ÔÌñÕÔÄñÕÔÅñ×Ô»ñ×Ô¾ñÕÔÆñÕÔÇñ×Ô¹ñ×Ô¼ñÕÔò×ÔòÕÔ¶ñÕÔ·ñ×Ô³ñ×Ô¶ñÕÔðñÕÔññ×Ô£ñ×Ô¦ñÕÔ ñÕÔ¡ñ×ÔñÕÔñ×ÔñÕÔñ×Ô¿ò×ÔÂòÕÔñ×ÔñÕÔûð×ÔþðÕÔñò×ÔôòÕÔçñ×ÔêñÕÔÂòÕÔÃò×Ôëð×ÔîðÕÔßð×ÔâðÕÔËð×ÔÎðÕÔÅð×ÔÈðÕÔ¾ðÕÔ¿ð×Ô¶ðÕÔ·ð×ÔðÕÔð×ÔðÕÔð×ÔêïÕÔëï×ÔØïÕÔÙï×ÔÄïÕÔÅï×ÔºïÕÔ»ï×Ô¶ïÕÔ·ï×ÔïÕÔï×ÔïÕÔï×ÔøîÕÔùî×ÔîîÕÔïî×ÔìîÕÔíî×Ô§·îÚºîÚ²îÚ³îÚ©îÚ¬îÚ´îÚµîÚ§îÚªîÚùîÚüîÚ¤îÚ¥îÚ¡îÚ¤îÚÞîÚßîÚîÚîÚîÚîÚîÚîÚîÚîÚ­ïÚ°ïÚóíÚöíÚéíÚìíÚßïÚâïÚÕîÚØîÚ°ïÚ±ïÚÙíÚÜíÚÍíÚÐíÚ¹íÚ¼íÚ³íÚ¶íÚ¬íÚ­íÚ¤íÚ¥íÚíÚíÚðìÚñìÚØìÚÙìÚÆìÚÇìÚ²ìÚ³ìÚ¨ìÚ©ìÚ¤ìÚ¥ìÚìÚìÚòëÚóëÚæëÚçëÚÜëÚÝëÚÚëÚÛëÚ§¥ëËß¨ëÉß ëÉß¡ëËßëËßëÉß¢ëÉß£ëËßëËßëÉßçëËßêëÉßëÉßëËßëËßëÉßÌëÉßÍëËßÿêËßëÉßüêÉßýêËßúêÉßûêËßøêÉßùêËßìËßìÉßáêËßäêÉß×êËßÚêÉßÍìËßÐìÉßÃëËßÆëÉßìÉßìËßÇêËßÊêÉß»êËß¾êÉß§êËßªêÉß¡êËß¤êÉßêÉßêËßêÉßêËßòéÉßóéËßÞéÉßßéËßÆéÉßÇéËß´éÉßµéËß éÉß¡éËßéÉßéËßéÉßéËßöèÉß÷èËßàèÉßáèËßÔèÉßÕèËßÊèÉßËèËßÈèÉßÉèËß§èåèåèåèåèåèåèåèåèåèåÕèåØèåèåèåýçåèåºèå»èåíçåðçåêçåëçåèçåéçåæçåççåéåéåÏçåÒçåÅçåÈçå»éå¾éå±èå´èåéåéåµçå¸çå©çå¬çåçåçåçåçåçåçåçåçåàæåáæåÌæåÍæå´æåµæå¢æå£æåæåæåæåæåæåæåäåååååÎååÏååÂååÃåå¸åå¹åå¶åå·åå§å¿êå½êüä½êýä¿êóä¿êöä½êþä½êÿä¿êñä¿êôä½êÃå¿êÆå½êîä½êïä¿êëä¿êîä½ê¨å½ê©å¿êÛä¿êÞä½êØä½êÙä¿êÖä½ê×ä¿êÔä½êÕä¿ê÷å¿êúå½ê½ä¿êÀä½ê³ä¿ê¶ä½ê©æ¿ê¬æ½êå¿ê¢å½êúå½êûå¿ê£ä¿ê¦ä½êä¿êä½êä¿êä½êýã¿êä½êöã½ê÷ã¿êîã½êïã¿êÎã½êÏã¿êºã½ê»ã¿ê¢ã½ê£ã¿êã½êã¿êüâ½êýâ¿êòâ½êóâ¿êîâ½êïâ¿êÒâ½êÓâ¿ê¼â½ê½â¿ê°â½ê±â¿ê¦â½ê§â¿ê¤â½ê¥â¿ê§ïáùïòá÷ïêá÷ïëáùïááùïäá÷ïìá÷ïíáùïßáùïâá÷ï±âùï´â÷ïÜá÷ïÝáùïÙáùïÜá÷ïâ÷ïâùïÉáùïÌá÷ïÆá÷ïÇáùïÄá÷ïÅáùïÂá÷ïÃáùïåâùïèâ÷ï«áùï®á÷ï¡áùï¤á÷ïãùïã÷ïâùïâ÷ïèâ÷ïéâùïáùïá÷ïáùïá÷ïñàùïôà÷ïëàùïîà÷ïäà÷ïåàùïÜà÷ïÝàùï¼à÷ï½àùï¨à÷ï©àùïà÷ïàùïþß÷ïÿßùïêß÷ïëßùïàß÷ïáßùïÜß÷ïÝßùïÀß÷ïÁßùïªß÷ï«ßùïß÷ïßùïß÷ïßùïß÷ïßùï§É»É¹É¹É»É»É¹É¹É»É»É¹ÝÉ»àÉ¹É¹É»É»É¹ÂÉ¹ÃÉ»õÈ»øÈ¹òÈ¹óÈ»ðÈ¹ñÈ»îÈ¹ïÈ»Ê»Ê¹×È»ÚÈ¹ÍÈ»ÐÈ¹ÃÊ»ÆÊ¹¹É»¼É¹Ê¹Ê»½È»ÀÈ¹±È»´È¹È» È¹È»È¹È¹È»È¹È»èÇ¹éÇ»ÔÇ¹ÕÇ»¼Ç¹½Ç»ªÇ¹«Ç»Ç¹Ç»Ç¹Ç»Ç¹Ç»ìÆ¹íÆ»ÖÆ¹×Æ»ÊÆ¹ËÆ»ÀÆ¹ÁÆ»¾Æ¹¿Æ»§Æõ
+Æó
+Æó
+Æõ
+ûÅõ
+þÅó
+Æó
+Æõ
+ùÅõ
+üÅó
+ËÆõ
+ÎÆó
+öÅó
+÷Åõ
+óÅõ
+öÅó
+°Æó
+±Æõ
+ãÅõ
+æÅó
+àÅó
+áÅõ
+ÞÅó
+ßÅõ
+ÜÅó
+ÝÅõ
+ÿÆõ
+Çó
+ÅÅõ
+ÈÅó
+»Åõ
+¾Åó
+±Çõ
+´Çó
+§Æõ
+ªÆó
+Çó
+Çõ
+«Åõ
+®Åó
+Åõ
+¢Åó
+Åõ
+Åó
+Åõ
+Åó
+þÄó
+ÿÄõ
+öÄó
+÷Äõ
+ÖÄó
+×Äõ
+ÂÄó
+ÃÄõ
+ªÄó
+«Äõ
+Äó
+Äõ
+Äó
+Äõ
+úÃó
+ûÃõ
+öÃó
+÷Ãõ
+ÚÃó
+ÛÃõ
+ÄÃó
+ÅÃõ
+¸Ãó
+¹Ãõ
+®Ãó
+¯Ãõ
+¬Ãó
+­Ãõ
+§÷Â¯úÂ­òÂ­óÂ¯éÂ¯ìÂ­ôÂ­õÂ¯çÂ¯êÂ­¹Ã¯¼Ã­äÂ­åÂ¯áÂ¯äÂ­Ã­Ã¯ÑÂ¯ÔÂ­ÎÂ­ÏÂ¯ÌÂ­ÍÂ¯ÊÂ­ËÂ¯íÃ¯ðÃ­³Â¯¶Â­©Â¯¬Â­Ä¯¢Ä­Ã¯Ã­ðÃ­ñÃ¯Â¯Â­Â¯Â­ùÁ¯üÁ­óÁ¯öÁ­ìÁ­íÁ¯äÁ­åÁ¯ÄÁ­ÅÁ¯°Á­±Á¯Á­Á¯Á­Á¯òÀ­óÀ¯èÀ­éÀ¯äÀ­åÀ¯ÈÀ­ÉÀ¯²À­³À¯¦À­§À¯À­À¯À­À¯§å¿éè¿çà¿çá¿é×¿éÚ¿çâ¿çã¿éÕ¿éØ¿ç§ÀéªÀçÒ¿çÓ¿éÏ¿éÒ¿çÀçÀé¿¿éÂ¿ç¼¿ç½¿éº¿ç»¿é¸¿ç¹¿éÛÀéÞÀç¡¿é¤¿ç¿é¿çÁéÁçÀéÀçÞÀçßÀé¿é¿çû¾éþ¾çç¾éê¾çá¾éä¾çÚ¾çÛ¾éÒ¾çÓ¾é²¾ç³¾é¾ç¾é¾ç¾éô½çõ½éà½çá½éÖ½ç×½éÒ½çÓ½é¶½ç·½é ½ç¡½é½ç½é½ç½é½ç½é§Ó¼£Ö¼¡Î¼¡Ï¼£Å¼£È¼¡Ð¼¡Ñ¼£Ã¼£Æ¼¡½£½¡À¼¡Á¼£½¼£À¼¡ú¼¡û¼£­¼£°¼¡ª¼¡«¼£¨¼¡©¼£¦¼¡§¼£É½£Ì½¡¼£¼¡¼£¼¡û½£þ½¡ñ¼£ô¼¡Ì½¡Í½£õ»£ø»¡é»£ì»¡Õ»£Ø»¡Ï»£Ò»¡È»¡É»£À»¡Á»£ »¡¡»£»¡»£ôº¡õº£âº¡ãº£Îº¡Ïº£Äº¡Åº£Àº¡Áº£¤º¡¥º£º¡º£º¡º£ø¹¡ù¹£ö¹¡÷¹£§Á¹Ý Ä¹Û ¼¹Û ½¹Ý ³¹Ý ¶¹Û ¾¹Û ¿¹Ý ±¹Ý ´¹Û ºÝ ºÛ ®¹Û ¯¹Ý «¹Ý ®¹Û è¹Û é¹Ý ¹Ý ¹Û ¹Û ¹Ý ¹Û ¹Ý ¹Û ¹Ý ·ºÝ ººÛ ý¸Ý ¹Û ó¸Ý ö¸Û éºÝ ìºÛ ß¹Ý â¹Û ººÛ »ºÝ ã¸Ý æ¸Û ×¸Ý Ú¸Û Ã¸Ý Æ¸Û ½¸Ý À¸Û ¶¸Û ·¸Ý ®¸Û ¯¸Ý ¸Û ¸Ý ú·Û û·Ý â·Û ã·Ý Ð·Û Ñ·Ý ¼·Û ½·Ý ²·Û ³·Ý ®·Û ¯·Ý ·Û ·Ý ü¶Û ý¶Ý ð¶Û ñ¶Ý æ¶Û ç¶Ý ä¶Û å¶Ý §¯¶&²¶&ª¶&«¶&¡¶&¤¶&¬¶&­¶&¶&¢¶&ñ¶&ô¶&¶&¶&¶&¶&Ö¶&×¶&¶&¶&¶&¶&¶&¶&¶&¶&¥·&¨·&ëµ&îµ&áµ&äµ&×·&Ú·&Í¶&Ð¶&¨·&©·&Ñµ&Ôµ&Åµ&Èµ&±µ&´µ&«µ&®µ&¤µ&¥µ&µ&µ&ü´&ý´&è´&é´&Ð´&Ñ´&¾´&¿´&ª´&«´& ´&¡´&´&´&´&´&ê³&ë³&Þ³&ß³&Ô³&Õ³&Ò³&Ó³&§³Ñ+ ³Ï+³Ï+³Ñ+³Ñ+³Ï+³Ï+³Ñ+³Ñ+³Ï+ß³Ñ+â³Ï+³Ï+³Ñ+³Ñ+³Ï+Ä³Ï+Å³Ñ+÷²Ñ+ú²Ï+ô²Ï+õ²Ñ+ò²Ï+ó²Ñ+ð²Ï+ñ²Ñ+´Ñ+´Ï+Ù²Ñ+Ü²Ï+Ï²Ñ+Ò²Ï+Å´Ñ+È´Ï+»³Ñ+¾³Ï+´Ï+´Ñ+¿²Ñ+Â²Ï+³²Ñ+¶²Ï+²Ñ+¢²Ï+²Ñ+²Ï+²Ï+²Ñ+²Ï+²Ñ+ê±Ï+ë±Ñ+Ö±Ï+×±Ñ+¾±Ï+¿±Ñ+¬±Ï+­±Ñ+±Ï+±Ñ+±Ï+±Ñ+±Ï+±Ñ+î°Ï+ï°Ñ+Ø°Ï+Ù°Ñ+Ì°Ï+Í°Ñ+Â°Ï+Ã°Ñ+À°Ï+Á°Ñ+§°1°1°1°1ý¯1°1°1°1û¯1þ¯1Í°1Ð°1ø¯1ù¯1õ¯1ø¯1²°1³°1å¯1è¯1â¯1ã¯1à¯1á¯1Þ¯1ß¯1±1±1Ç¯1Ê¯1½¯1À¯1³±1¶±1©°1¬°1±1±1­¯1°¯1¡¯1¤¯1¯1¯1¯1¯1¯1¯1ø®1ù®1Ø®1Ù®1Ä®1Å®1¬®1­®1®1®1®1®1ü­1ý­1ø­1ù­1Ü­1Ý­1Æ­1Ç­1º­1»­1°­1±­1®­1¯­1§ù¬Å6ü¬Ã6ô¬Ã6õ¬Å6ë¬Å6î¬Ã6ö¬Ã6÷¬Å6é¬Å6ì¬Ã6»­Å6¾­Ã6æ¬Ã6ç¬Å6ã¬Å6æ¬Ã6 ­Ã6¡­Å6Ó¬Å6Ö¬Ã6Ð¬Ã6Ñ¬Å6Î¬Ã6Ï¬Å6Ì¬Ã6Í¬Å6ï­Å6ò­Ã6µ¬Å6¸¬Ã6«¬Å6®¬Ã6¡®Å6¤®Ã6­Å6­Ã6ò­Ã6ó­Å6¬Å6¬Ã6¬Å6¬Ã6û«Å6þ«Ã6õ«Å6ø«Ã6î«Ã6ï«Å6æ«Ã6ç«Å6Æ«Ã6Ç«Å6²«Ã6³«Å6«Ã6«Å6«Ã6«Å6ôªÃ6õªÅ6êªÃ6ëªÅ6æªÃ6çªÅ6ÊªÃ6ËªÅ6´ªÃ6µªÅ6¨ªÃ6©ªÅ6ªÃ6ªÅ6ªÃ6ªÅ6§ç©ÿ;ê©ý;â©ý;ã©ÿ;Ù©ÿ;Ü©ý;ä©ý;å©ÿ;×©ÿ;Ú©ý;©ªÿ;¬ªý;Ô©ý;Õ©ÿ;Ñ©ÿ;Ô©ý;ªý;ªÿ;Á©ÿ;Ä©ý;¾©ý;¿©ÿ;¼©ý;½©ÿ;º©ý;»©ÿ;Ýªÿ;àªý;£©ÿ;¦©ý;©ÿ;©ý;«ÿ;«ý;ªÿ;ªý;àªý;áªÿ;©ÿ;©ý;ý¨ÿ;©ý;é¨ÿ;ì¨ý;ã¨ÿ;æ¨ý;Ü¨ý;Ý¨ÿ;Ô¨ý;Õ¨ÿ;´¨ý;µ¨ÿ; ¨ý;¡¨ÿ;¨ý;¨ÿ;ö§ý;÷§ÿ;â§ý;ã§ÿ;Ø§ý;Ù§ÿ;Ô§ý;Õ§ÿ;¸§ý;¹§ÿ;¢§ý;£§ÿ;§ý;§ÿ;§ý;§ÿ;§ý;§ÿ;§Õ¦¹AØ¦·AÐ¦·AÑ¦¹AÇ¦¹AÊ¦·AÒ¦·AÓ¦¹AÅ¦¹AÈ¦·A§¹A§·AÂ¦·AÃ¦¹A¿¦¹AÂ¦·Aü¦·Aý¦¹A¯¦¹A²¦·A¬¦·A­¦¹Aª¦·A«¦¹A¨¦·A©¦¹AË§¹AÎ§·A¦¹A¦·A¦¹A¦·Aý§¹A¨·Aó¦¹Aö¦·AÎ§·AÏ§¹A÷¥¹Aú¥·Aë¥¹Aî¥·A×¥¹AÚ¥·AÑ¥¹AÔ¥·AÊ¥·AË¥¹AÂ¥·AÃ¥¹A¢¥·A£¥¹A¥·A¥¹Aö¤·A÷¤¹Aä¤·Aå¤¹AÐ¤·AÑ¤¹AÆ¤·AÇ¤¹AÂ¤·AÃ¤¹A¦¤·A§¤¹A¤·A¤¹A¤·A¤¹Aú£·Aû£¹Aø£·Aù£¹A§Ã£óFÆ£ñF¾£ñF¿£óFµ£óF¸£ñFÀ£ñFÁ£óF³£óF¶£ñF¤óF¤ñF°£ñF±£óF­£óF°£ñFê£ñFë£óF£óF £ñF£ñF£óF£ñF£óF£ñF£óF¹¤óF¼¤ñFÿ¢óF£ñFõ¢óFø¢ñFë¤óFî¤ñFá£óFä£ñF¼¤ñF½¤óFå¢óFè¢ñFÙ¢óFÜ¢ñFÅ¢óFÈ¢ñF¿¢óFÂ¢ñF¸¢ñF¹¢óF°¢ñF±¢óF¢ñF¢óFü¡ñFý¡óFä¡ñFå¡óFÒ¡ñFÓ¡óF¾¡ñF¿¡óF´¡ñFµ¡óF°¡ñF±¡óF¡ñF¡óFþ ñFÿ óFò ñFó óFè ñFé óFæ ñFç óF§± ­L´ «L¬ «L­ ­L£ ­L¦ «L® «L¯ ­L¡ ­L¤ «Ló ­Lö «L «L ­L ­L «LØ «LÙ ­L ­L «L «L ­L «L ­L «L ­L§¡­Lª¡«Lí­Lð«Lã­Læ«LÙ¡­LÜ¡«LÏ ­LÒ «Lª¡«L«¡­LÓ­LÖ«LÇ­LÊ«L³­L¶«L­­L°«L¦«L§­L«L­Lþ«Lÿ­Lê«Lë­LÒ«LÓ­LÀ«LÁ­L¬«L­­L¢«L£­L«L­L«L­Lì«Lí­Là«Lá­LÖ«L×­LÔ«LÕ­L§çQ¢åQåQçQçQåQåQçQçQåQáçQäåQåQçQçQåQÆåQÇçQùçQüåQöåQ÷çQôåQõçQòåQóçQçQåQÛçQÞåQÑçQÔåQÇçQÊåQ½çQÀåQåQçQÁçQÄåQµçQ¸åQ¡çQ¤åQçQåQåQçQåQçQìåQíçQØåQÙçQÀåQÁçQ®åQ¯çQåQçQåQçQåQçQðåQñçQÚåQÛçQÎåQÏçQÄåQÅçQÂåQÃçQ§¡WWW¡Wÿ¡WWW¡Wý¡WWÏ¡WÒWúWû¡W÷¡WúW´Wµ¡Wç¡WêWäWå¡WâWã¡WàWá¡W¡WWÉ¡WÌW¿¡WÂWµ¡W¸W«¡W®WW¡W¯¡W²W£¡W¦W¡WW¡WWW¡WúWû¡WÚWÛ¡WÆWÇ¡W®W¯¡WW¡WW¡WþWÿ¡WúWû¡WÞWß¡WÈWÉ¡W¼W½¡W²W³¡W°W±¡W§ûÛ\þÙ\öÙ\÷Û\íÛ\ðÙ\øÙ\ùÛ\ëÛ\îÙ\½Û\ÀÙ\èÙ\éÛ\åÛ\èÙ\¢Ù\£Û\ÕÛ\ØÙ\ÒÙ\ÓÛ\ÐÙ\ÑÛ\ÎÙ\ÏÛ\ñÛ\ôÙ\·Û\ºÙ\­Û\°Ù\£Û\¦Ù\Û\Ù\ôÙ\õÛ\Û\ Ù\Û\Ù\ýÛ\Ù\÷Û\úÙ\ðÙ\ñÛ\èÙ\éÛ\ÈÙ\ÉÛ\´Ù\µÛ\Ù\Û\Ù\Û\öÙ\÷Û\ìÙ\íÛ\èÙ\éÛ\ÌÙ\ÍÛ\¶Ù\·Û\ªÙ\«Û\ Ù\¡Û\Ù\Û\§ébìbäbåbÛbÞbæbçbÙbÜb«b®bÖb×bÓbÖbbbÃbÆbÀbÁb¾b¿b¼b½bßbâb¥b¨bbbbbbbâbãbbbÿbbëbîbåbèbÞbßbÖb×b¶b·b¢b£bbbøbùbäbåbÚbÛbÖb×bºb»b¤b¥bbbbbbb§×ÏgÚÍgÒÍgÓÏgÉÏgÌÍgÔÍgÕÏgÇÏgÊÍgÏgÍgÄÍgÅÏgÁÏgÄÍgþÍgÿÏg±Ïg´Íg®Íg¯Ïg¬Íg­ÏgªÍg«ÏgÍÏgÐÍgÏgÍgÏgÍgÿÏgÍgõÏgøÍgÐÍgÑÏgùÏgüÍgíÏgðÍgÙÏgÜÍgÓÏgÖÍgÌÍgÍÏgÄÍgÅÏg¤Íg¥ÏgÍgÏgøÍgùÏgæÍgçÏgÒÍgÓÏgÈÍgÉÏgÄÍgÅÏg¨Íg©ÏgÍgÏgÍgÏgüÍgýÏgúÍgûÏg§ÅmÈmÀmÁm·mºmÂmÃmµm¸mmm²m³m¯m²mìmímm¢mmmmmmm»m¾mmm÷múmímðmãmæm¾m¿mçmêmÛmÞmÇmÊmÁmÄmºm»m²m³mmmþmÿmæmçmÔmÕmÀmÁm¶m·m²m³mmmmmômõmêmëmèmém§³Ãr¶Ár®Ár¯Ãr¥Ãr¨Ár°Ár±Ãr£Ãr¦ÁrõÃrøÁr Ár¡ÃrÃr ÁrÚÁrÛÃrÃrÁrÁrÃrÁrÃrÁrÃr©Ãr¬ÁrïÃròÁråÃrèÁrÛÃrÞÁrÑÃrÔÁr¬Ár­ÃrÕÃrØÁrÉÃrÌÁrµÃr¸Ár¯Ãr²Ár¨Ár©Ãr Ár¡ÃrÁrÃrìÁríÃrÔÁrÕÃrÂÁrÃÃr®Ár¯Ãr¤Ár¥Ãr Ár¡ÃrÁrÃrîÁrïÃrâÁrãÃrØÁrÙÃrÖÁr×Ãr§¡ýw¤ûwûwýwýwûwûwýwýwûwãýwæûwûwýwýwûwÈûwÉýwûýwþûwøûwùýwöûw÷ýwôûwõýwýwûwÝýwàûwÓýwÖûwÉýwÌûw¿ýwÂûwûwýwÃýwÆûw·ýwºûw£ýw¦ûwýw ûwûwýwûwýwîûwïýwÚûwÛýwÂûwÃýw°ûw±ýwûwýwûwýwûwýwòûwóýwÜûwÝýwÐûwÑýwÆûwÇýwÄûwÅýw§·}µ}µ}·}·}µ}µ}·}ÿ·}µ}Ñ·}Ôµ}üµ}ý·}ù·}üµ}¶µ}··}é·}ìµ}æµ}ç·}äµ}å·}âµ}ã·}·}µ}Ë·}Îµ}Á·}Äµ}··}ºµ}­·}°µ}µ}·}±·}´µ}¥·}¨µ}·}µ}·}µ}µ}·}üµ}ý·}Üµ}Ý·}Èµ}É·}°µ}±·}µ}·}µ}·}µ}·}üµ}ý·}àµ}á·}Êµ}Ë·}¾µ}¿·}´µ}µ·}²µ}³·}§ýñïøïùñïñòïúïûñíñðï¿ñÂïêïëñçñêï¤ï¥ñ×ñÚïÔïÕñÒïÓñÐïÑñóñöï¹ñ¼ï¯ñ²ï¥ñ¨ïñïöï÷ññ¢ïñïÿÿñïùÿñüÿïòÿïóÿñêÿïëÿñÊÿïËÿñ¶ÿï·ÿñÿïÿñÿïÿñøþïùþñîþïïþñêþïëþñÎþïÏþñ¸þï¹þñ¬þï­þñ¢þï£þñ þï¡þñ§ëý«îý©æý©çý«Ýý«àý©èý©éý«Ûý«Þý©­þ«°þ©Øý©Ùý«Õý«Øý©þ©þ«Åý«Èý©Âý©Ãý«Àý©Áý«¾ý©¿ý«áþ«äþ©§ý«ªý©ý« ý©ÿ«ÿ©þ«þ©äþ©åþ«ý«ý©ý«ý©íü«ðü©çü«êü©àü©áü«Øü©Ùü«¸ü©¹ü«¤ü©¥ü«ü©ü«úû©ûû«æû©çû«Üû©Ýû«Øû©Ùû«¼û©½û«¦û©§û«û©û«û©û«û©û«§ÙúåÜúãÔúãÕúåËúåÎúãÖúã×úåÉúåÌúãûåûãÆúãÇúåÃúåÆúãûãûå³úå¶úã°úã±úå®úã¯úå¬úã­úåÏûåÒûãúåúãúåúãüåüã÷úåúúãÒûãÓûåûùåþùãïùåòùãÛùåÞùãÕùåØùãÎùãÏùåÆùãÇùå¦ùã§ùåùãùåúøãûøåèøãéøåÔøãÕøåÊøãËøåÆøãÇøåªøã«øåøãøåøãøåþ÷ãÿ÷åü÷ãý÷å§Ç÷Ê÷Â÷Ã÷¹÷¼÷Ä÷Å÷·÷º÷øø´÷µ÷±÷´÷î÷ï÷¡÷¤÷÷÷÷÷÷÷½øÀø÷÷ùöüöïøòøå÷è÷ÀøÁøéöìöÝöàöÉöÌöÃöÆö¼ö½ö´öµöööööèõéõÖõ×õÂõÃõ¸õ¹õ´õµõõõõõöô÷ôìôíôêôëô§µôÙ¸ô×°ô×±ôÙ§ôÙªô×²ô×³ôÙ¥ôÙ¨ô×÷ôÙúô×¢ô×£ôÙôÙ¢ô×Üô×ÝôÙôÙô×ô×ôÙô×ôÙô×ôÙ«õÙ®õ×ñóÙôó×çóÙêó×ÝõÙàõ×ÓôÙÖô×®õ×¯õÙ×óÙÚó×ËóÙÎó×·óÙºó×±óÙ´ó×ªó×«óÙ¢ó×£óÙó×óÙîò×ïòÙÖò××òÙÄò×ÅòÙ°ò×±òÙ¦ò×§òÙ¢ò×£òÙò×òÙðñ×ññÙäñ×åñÙÚñ×ÛñÙØñ×ÙñÙ§£ñ¦ñññññ ñ¡ñññåñèñññññÊñËñýðñúðûðøðùðöð÷ðòòßðâðÕðØðËòÎòÁñÄñòòÅðÈð¹ð¼ð¥ð¨ðð¢ððððððïñïÜïÝïÄïÅï²ï³ïïïïïïïôîõîÞîßîÒîÓîÈîÉîÆîÇî§îÍ£îË£îË£îÍ£îÍ£îË£îË£îÍ£îÍ£îË£ÓîÍ£ÖîË£þíË£ÿíÍ£ûíÍ£þíË£¸îË£¹îÍ£ëíÍ£îíË£èíË£éíÍ£æíË£çíÍ£äíË£åíÍ£ïÍ£ïË£ÍíÍ£ÐíË£ÃíÍ£ÆíË£¹ïÍ£¼ïË£¯îÍ£²îË£ïË£ïÍ£³íÍ£¶íË£§íÍ£ªíË£íÍ£íË£íÍ£íË£íË£íÍ£þìË£ÿìÍ£ÞìË£ßìÍ£ÊìË£ËìÍ£²ìË£³ìÍ£ ìË£¡ìÍ£ìË£ìÍ£ìË£ìÍ£þëË£ÿëÍ£âëË£ãëÍ£ÌëË£ÍëÍ£ÀëË£ÁëÍ£¶ëË£·ëÍ£´ëË£µëÍ£§ÿê©ë©úê©ûê©ñê©ôê©üê©ýê©ïê©òê©Áë©Äë©ìê©íê©éê©ìê©¦ë©§ë©Ùê©Üê©Öê©×ê©Ôê©Õê©Òê©Óê©õë©øë©»ê©¾ê©±ê©´ê©§ì©ªì©ë© ë©øë©ùë©¡ê©¤ê©ê©ê©ê©ê©ûé©þé©ôé©õé©ìé©íé©Ìé©Íé©¸é©¹é© é©¡é©é©é©úè©ûè©ðè©ñè©ìè©íè©Ðè©Ñè©ºè©»è©®è©¯è©¤è©¥è©¢è©£è©§íçÁ®ðç¿®èç¿®éçÁ®ßçÁ®âç¿®êç¿®ëçÁ®ÝçÁ®àç¿®¯èÁ®²è¿®Úç¿®ÛçÁ®×çÁ®Úç¿®è¿®èÁ®ÇçÁ®Êç¿®Äç¿®ÅçÁ®Âç¿®ÃçÁ®Àç¿®ÁçÁ®ãèÁ®æè¿®©çÁ®¬ç¿®çÁ®¢ç¿®éÁ®é¿®èÁ®è¿®æè¿®çèÁ®çÁ®ç¿®çÁ®ç¿®ïæÁ®òæ¿®éæÁ®ìæ¿®âæ¿®ãæÁ®Úæ¿®ÛæÁ®ºæ¿®»æÁ®¦æ¿®§æÁ®æ¿®æÁ®üå¿®ýåÁ®èå¿®éåÁ®Þå¿®ßåÁ®Úå¿®ÛåÁ®¾å¿®¿åÁ®¨å¿®©åÁ®å¿®åÁ®å¿®åÁ®å¿®åÁ®§Ûäû³Þäù³Öäù³×äû³Íäû³Ðäù³Øäù³Ùäû³Ëäû³Îäù³åû³ åù³Èäù³Éäû³Åäû³Èäù³åù³åû³µäû³¸äù³²äù³³äû³°äù³±äû³®äù³¯äû³Ñåû³Ôåù³äû³äù³äû³äù³æû³æù³ùäû³üäù³Ôåù³Õåû³ýãû³äù³ñãû³ôãù³Ýãû³àãù³×ãû³Úãù³Ðãù³Ñãû³Èãù³Éãû³¨ãù³©ãû³ãù³ãû³üâù³ýâû³êâù³ëâû³Öâù³×âû³Ìâù³Íâû³Èâù³Éâû³¬âù³­âû³âù³âû³âù³âû³âù³âû³þáù³ÿáû³§Éáµ¹Ìá³¹Äá³¹Åáµ¹»áµ¹¾á³¹Æá³¹Çáµ¹¹áµ¹¼á³¹âµ¹â³¹¶á³¹·áµ¹³áµ¹¶á³¹ðá³¹ñáµ¹£áµ¹¦á³¹ á³¹¡áµ¹á³¹áµ¹á³¹áµ¹¿âµ¹Ââ³¹áµ¹á³¹ûàµ¹þà³¹ñâµ¹ôâ³¹çáµ¹êá³¹Ââ³¹Ãâµ¹ëàµ¹îà³¹ßàµ¹âà³¹Ëàµ¹Îà³¹Åàµ¹Èà³¹¾à³¹¿àµ¹¶à³¹·àµ¹à³¹àµ¹à³¹àµ¹êß³¹ëßµ¹Øß³¹Ùßµ¹Äß³¹Åßµ¹ºß³¹»ßµ¹¶ß³¹·ßµ¹ß³¹ßµ¹ß³¹ßµ¹øÞ³¹ùÞµ¹îÞ³¹ïÞµ¹ìÞ³¹íÞµ¹§·Þï¾ºÞí¾²Þí¾³Þï¾©Þï¾¬Þí¾´Þí¾µÞï¾§Þï¾ªÞí¾ùÞï¾üÞí¾¤Þí¾¥Þï¾¡Þï¾¤Þí¾ÞÞí¾ßÞï¾Þï¾Þí¾Þí¾Þï¾Þí¾Þï¾Þí¾Þï¾­ßï¾°ßí¾óÝï¾öÝí¾éÝï¾ìÝí¾ßßï¾âßí¾ÕÞï¾ØÞí¾°ßí¾±ßï¾ÙÝï¾ÜÝí¾ÍÝï¾ÐÝí¾¹Ýï¾¼Ýí¾³Ýï¾¶Ýí¾¬Ýí¾­Ýï¾¤Ýí¾¥Ýï¾Ýí¾Ýï¾ðÜí¾ñÜï¾ØÜí¾ÙÜï¾ÆÜí¾ÇÜï¾²Üí¾³Üï¾¨Üí¾©Üï¾¤Üí¾¥Üï¾Üí¾Üï¾òÛí¾óÛï¾æÛí¾çÛï¾ÜÛí¾ÝÛï¾ÚÛí¾ÛÛï¾§¥Û©Ä¨Û§Ä Û§Ä¡Û©ÄÛ©ÄÛ§Ä¢Û§Ä£Û©ÄÛ©ÄÛ§ÄçÛ©ÄêÛ§ÄÛ§ÄÛ©ÄÛ©ÄÛ§ÄÌÛ§ÄÍÛ©ÄÿÚ©ÄÛ§ÄüÚ§ÄýÚ©ÄúÚ§ÄûÚ©ÄøÚ§ÄùÚ©ÄÜ©ÄÜ§ÄáÚ©ÄäÚ§Ä×Ú©ÄÚÚ§ÄÍÜ©ÄÐÜ§ÄÃÛ©ÄÆÛ§ÄÜ§ÄÜ©ÄÇÚ©ÄÊÚ§Ä»Ú©Ä¾Ú§Ä§Ú©ÄªÚ§Ä¡Ú©Ä¤Ú§ÄÚ§ÄÚ©ÄÚ§ÄÚ©ÄòÙ§ÄóÙ©ÄÞÙ§ÄßÙ©ÄÆÙ§ÄÇÙ©Ä´Ù§ÄµÙ©Ä Ù§Ä¡Ù©ÄÙ§ÄÙ©ÄÙ§ÄÙ©ÄöØ§Ä÷Ø©ÄàØ§ÄáØ©ÄÔØ§ÄÕØ©ÄÊØ§ÄËØ©ÄÈØ§ÄÉØ©Ä§ØãÉØáÉØáÉØãÉØãÉØáÉØáÉØãÉØãÉØáÉÕØãÉØØáÉØáÉØãÉý×ãÉØáÉºØáÉ»ØãÉí×ãÉð×áÉê×áÉë×ãÉè×áÉé×ãÉæ×áÉç×ãÉÙãÉÙáÉÏ×ãÉÒ×áÉÅ×ãÉÈ×áÉ»ÙãÉ¾ÙáÉ±ØãÉ´ØáÉÙáÉÙãÉµ×ãÉ¸×áÉ©×ãÉ¬×áÉ×ãÉ×áÉ×ãÉ×áÉ×áÉ×ãÉ×áÉ×ãÉàÖáÉáÖãÉÌÖáÉÍÖãÉ´ÖáÉµÖãÉ¢ÖáÉ£ÖãÉÖáÉÖãÉÖáÉÖãÉÖáÉÖãÉäÕáÉåÕãÉÎÕáÉÏÕãÉÂÕáÉÃÕãÉ¸ÕáÉ¹ÕãÉ¶ÕáÉ·ÕãÉ§ÕÏÕÏüÔÏýÔÏóÔÏöÔÏþÔÏÿÔÏñÔÏôÔÏÃÕÏÆÕÏîÔÏïÔÏëÔÏîÔÏ¨ÕÏ©ÕÏÛÔÏÞÔÏØÔÏÙÔÏÖÔÏ×ÔÏÔÔÏÕÔÏ÷ÕÏúÕÏ½ÔÏÀÔÏ³ÔÏ¶ÔÏ©ÖÏ¬ÖÏÕÏ¢ÕÏúÕÏûÕÏ£ÔÏ¦ÔÏÔÏÔÏÔÏÔÏýÓÏÔÏöÓÏ÷ÓÏîÓÏïÓÏÎÓÏÏÓÏºÓÏ»ÓÏ¢ÓÏ£ÓÏÓÏÓÏüÒÏýÒÏòÒÏóÒÏîÒÏïÒÏÒÒÏÓÒÏ¼ÒÏ½ÒÏ°ÒÏ±ÒÏ¦ÒÏ§ÒÏ¤ÒÏ¥ÒÏ§ïÑ×ÔòÑÕÔêÑÕÔëÑ×ÔáÑ×ÔäÑÕÔìÑÕÔíÑ×ÔßÑ×ÔâÑÕÔ±Ò×Ô´ÒÕÔÜÑÕÔÝÑ×ÔÙÑ×ÔÜÑÕÔÒÕÔÒ×ÔÉÑ×ÔÌÑÕÔÆÑÕÔÇÑ×ÔÄÑÕÔÅÑ×ÔÂÑÕÔÃÑ×ÔåÒ×ÔèÒÕÔ«Ñ×Ô®ÑÕÔ¡Ñ×Ô¤ÑÕÔÓ×ÔÓÕÔÒ×ÔÒÕÔèÒÕÔéÒ×ÔÑ×ÔÑÕÔÑ×ÔÑÕÔñÐ×ÔôÐÕÔëÐ×ÔîÐÕÔäÐÕÔåÐ×ÔÜÐÕÔÝÐ×Ô¼ÐÕÔ½Ð×Ô¨ÐÕÔ©Ð×ÔÐÕÔÐ×ÔþÏÕÔÿÏ×ÔêÏÕÔëÏ×ÔàÏÕÔáÏ×ÔÜÏÕÔÝÏ×ÔÀÏÕÔÁÏ×ÔªÏÕÔ«Ï×ÔÏÕÔÏ×ÔÏÕÔÏ×ÔÏÕÔÏ×Ô§ÝÎÚàÎÚØÎÚÙÎÚÏÎÚÒÎÚÚÎÚÛÎÚÍÎÚÐÎÚÏÚ¢ÏÚÊÎÚËÎÚÇÎÚÊÎÚÏÚÏÚ·ÎÚºÎÚ´ÎÚµÎÚ²ÎÚ³ÎÚ°ÎÚ±ÎÚÓÏÚÖÏÚÎÚÎÚÎÚÎÚÐÚÐÚûÎÚþÎÚÖÏÚ×ÏÚÿÍÚÎÚóÍÚöÍÚßÍÚâÍÚÙÍÚÜÍÚÒÍÚÓÍÚÊÍÚËÍÚªÍÚ«ÍÚÍÚÍÚþÌÚÿÌÚìÌÚíÌÚØÌÚÙÌÚÎÌÚÏÌÚÊÌÚËÌÚ®ÌÚ¯ÌÚÌÚÌÚÌÚÌÚÌÚÌÚÌÚÌÚ§ËËËßÎËÉßÆËÉßÇËËß½ËËßÀËÉßÈËÉßÉËËß»ËËß¾ËÉßÌËßÌÉß¸ËÉß¹ËËßµËËß¸ËÉßòËÉßóËËß¥ËËß¨ËÉß¢ËÉß£ËËß ËÉß¡ËËßËÉßËËßÁÌËßÄÌÉßËËßËÉßýÊËßËÉßóÌËßöÌÉßéËËßìËÉßÄÌÉßÅÌËßíÊËßðÊÉßáÊËßäÊÉßÍÊËßÐÊÉßÇÊËßÊÊÉßÀÊÉßÁÊËß¸ÊÉß¹ÊËßÊÉßÊËßÊÉßÊËßìÉÉßíÉËßÚÉÉßÛÉËßÆÉÉßÇÉËß¼ÉÉß½ÉËß¸ÉÉß¹ÉËßÉÉßÉËßÉÉßÉËßúÈÉßûÈËßðÈÉßñÈËßîÈÉßïÈËß§¹Èå¼Èå´ÈåµÈå«Èå®Èå¶Èå·Èå©Èå¬ÈåûÈåþÈå¦Èå§Èå£Èå¦ÈåàÈåáÈåÈåÈåÈåÈåÈåÈåÈåÈå¯Éå²ÉåõÇåøÇåëÇåîÇåáÉåäÉå×ÈåÚÈå²Éå³ÉåÛÇåÞÇåÏÇåÒÇå»Çå¾ÇåµÇå¸Çå®Çå¯Çå¦Çå§ÇåÇåÇåòÆåóÆåÚÆåÛÆåÈÆåÉÆå´ÆåµÆåªÆå«Æå¦Æå§ÆåÆåÆåôÅåõÅåèÅåéÅåÞÅåßÅåÜÅåÝÅå§§Å¿êªÅ½ê¢Å½ê£Å¿êÅ¿êÅ½ê¤Å½ê¥Å¿êÅ¿êÅ½êéÅ¿êìÅ½êÅ½êÅ¿êÅ¿êÅ½êÎÅ½êÏÅ¿êÅ¿êÅ½êþÄ½êÿÄ¿êüÄ½êýÄ¿êúÄ½êûÄ¿êÆ¿ê Æ½êãÄ¿êæÄ½êÙÄ¿êÜÄ½êÏÆ¿êÒÆ½êÅÅ¿êÈÅ½ê Æ½ê¡Æ¿êÉÄ¿êÌÄ½ê½Ä¿êÀÄ½ê©Ä¿ê¬Ä½ê£Ä¿ê¦Ä½êÄ½êÄ¿êÄ½êÄ¿êôÃ½êõÃ¿êàÃ½êáÃ¿êÈÃ½êÉÃ¿ê¶Ã½ê·Ã¿ê¢Ã½ê£Ã¿êÃ½êÃ¿êÃ½êÃ¿êøÂ½êùÂ¿êâÂ½êãÂ¿êÖÂ½ê×Â¿êÌÂ½êÍÂ¿êÊÂ½êËÂ¿ê§§»§¹§¹§»§»§¹§¹§»§»§¹Û§»Þ§¹§¹§»§»§¹À§¹Á§»ó¦»ö¦¹ð¦¹ñ¦»î¦¹ï¦»ì¦¹í¦»¨»¨¹Õ¦»Ø¦¹Ë¦»Î¦¹Á¨»Ä¨¹·§»º§¹¨¹¨»»¦»¾¦¹¯¦»²¦¹¦»¦¹¦»¦¹¦¹¦»¦¹¦»æ¥¹ç¥»Ò¥¹Ó¥»º¥¹»¥»¨¥¹©¥»¥¹¥»¥¹¥»¥¹¥»ê¤¹ë¤»Ô¤¹Õ¤»È¤¹É¤»¾¤¹¿¤»¼¤¹½¤»§¤õ
+¤ó
+¤ó
+¤õ
+ù£õ
+ü£ó
+¤ó
+¤õ
+÷£õ
+ú£ó
+É¤õ
+Ì¤ó
+ô£ó
+õ£õ
+ñ£õ
+ô£ó
+®¤ó
+¯¤õ
+á£õ
+ä£ó
+Þ£ó
+ß£õ
+Ü£ó
+Ý£õ
+Ú£ó
+Û£õ
+ý¤õ
+¥ó
+Ã£õ
+Æ£ó
+¹£õ
+¼£ó
+¯¥õ
+²¥ó
+¥¤õ
+¨¤ó
+¥ó
+¥õ
+©£õ
+¬£ó
+£õ
+ £ó
+£õ
+£ó
+£õ
+£ó
+ü¢ó
+ý¢õ
+ô¢ó
+õ¢õ
+Ô¢ó
+Õ¢õ
+À¢ó
+Á¢õ
+¨¢ó
+©¢õ
+¢ó
+¢õ
+¢ó
+¢õ
+ø¡ó
+ù¡õ
+ô¡ó
+õ¡õ
+Ø¡ó
+Ù¡õ
+Â¡ó
+Ã¡õ
+¶¡ó
+·¡õ
+¬¡ó
+­¡õ
+ª¡ó
+«¡õ
+§õ ¯ø ­ð ­ñ ¯ç ¯ê ­ò ­ó ¯å ¯è ­·¡¯º¡­â ­ã ¯ß ¯â ­¡­¡¯Ï ¯Ò ­Ì ­Í ¯Ê ­Ë ¯È ­É ¯ë¡¯î¡­± ¯´ ­§ ¯ª ­¢¯ ¢­¡¯¡­î¡­ï¡¯ ¯ ­ ¯ ­÷¯ú­ñ¯ô­ê­ë¯â­ã¯Â­Ã¯®­¯¯­¯­¯ð­ñ¯æ­ç¯â­ã¯Æ­Ç¯°­±¯¤­¥¯­¯­¯§ãéæçÞçßéÕéØçàçáéÓéÖç¥é¨çÐçÑéÍéÐççé½éÀçºç»é¸ç¹é¶ç·éÙéÜçé¢çéçéçéçÜçÝééçùéüçåéèçßéâçØçÙéÐçÑé°ç±éçéçéòçóéÞçßéÔçÕéÐçÑé´çµéçéçéçéçé§Ñ£Ô¡Ì¡Í£Ã£Æ¡Î¡Ï£Á£Ä¡£¡¾¡¿£»£¾¡ø¡ù£«£®¡¨¡©£¦¡§£¤¡¥£Ç£Ê¡£¡£¡ù£ü¡ï£ò¡Ê¡Ë£ó£ö¡ç£ê¡Ó£Ö¡Í£Ð¡Æ¡Ç£¾¡¿£¡£¡£ò¡ó£à¡á£Ì¡Í£Â¡Ã£¾¡¿£¢¡££¡£¡£ö¡÷£ô¡õ£§¿Ý ÂÛ ºÛ »Ý ±Ý ´Û ¼Û ½Ý ¯Ý ²Û Ý Û ¬Û ­Ý ©Ý ¬Û æÛ çÝ Ý Û Û Ý Û Ý Û Ý µÝ ¸Û ûÝ þÛ ñÝ ôÛ çÝ êÛ ÝÝ àÛ ¸Û ¹Ý áÝ äÛ ÕÝ ØÛ ÁÝ ÄÛ »Ý ¾Û ´Û µÝ ¬Û ­Ý Û Ý øÛ ùÝ àÛ áÝ ÎÛ ÏÝ ºÛ »Ý °Û ±Ý ¬Û ­Ý Û Ý úÛ ûÝ îÛ ïÝ äÛ åÝ âÛ ãÝ §­&°&¨&©&&¢&ª&«&& &ï&ò&&&&&Ô&Õ&&&&&&&&&£&¦&é&ì&ß&â&Õ&Ø&Ë&Î&¦&§&Ï&Ò&Ã&Æ&¯&²&©&¬&¢&£&&&ú&û&æ&ç&Î&Ï&¼&½&¨&©&&&&&þ&ÿ&è&é&Ü&Ý&Ò&Ó&Ð&Ñ&§Ñ+Ï+Ï+Ñ+Ñ+Ï+Ï+Ñ+Ñ+Ï+ÝÑ+àÏ+Ï+Ñ+Ñ+Ï+ÂÏ+ÃÑ+õÑ+øÏ+òÏ+óÑ+ðÏ+ñÑ+îÏ+ïÑ+Ñ+Ï+×Ñ+ÚÏ+ÍÑ+ÐÏ+ÃÑ+ÆÏ+¹Ñ+¼Ï+Ï+Ñ+½Ñ+ÀÏ+±Ñ+´Ï+Ñ+ Ï+Ñ+Ï+Ï+Ñ+Ï+Ñ+èÏ+éÑ+ÔÏ+ÕÑ+¼Ï+½Ñ+ªÏ+«Ñ+Ï+Ñ+Ï+Ñ+Ï+Ñ+ìÏ+íÑ+ÖÏ+×Ñ+ÊÏ+ËÑ+ÀÏ+ÁÑ+¾Ï+¿Ñ+§1111û1þ111ù1ü1Ë1Î1ö1÷1ó1ö1°1±1ã1æ1à1á1Þ1ß1Ü1Ý1ÿ11Å1È1»1¾1±1´1§1ª111«1®11¢11111þ1ÿ1ö1÷1Ö1×1Â1Ã1ª1«11111ú1û1ö1÷1Ú1Û1Ä1Å1¸1¹1®1¯1¬1­1§÷Å6úÃ6òÃ6óÅ6éÅ6ìÃ6ôÃ6õÅ6çÅ6êÃ6¹Å6¼Ã6äÃ6åÅ6áÅ6äÃ6Ã6Å6ÑÅ6ÔÃ6ÎÃ6ÏÅ6ÌÃ6ÍÅ6ÊÃ6ËÅ6íÅ6ðÃ6³Å6¶Ã6©Å6¬Ã6Å6¢Ã6Å6Ã6ðÃ6ñÅ6Å6Ã6Å6Ã6ùÅ6üÃ6óÅ6öÃ6ìÃ6íÅ6äÃ6åÅ6ÄÃ6ÅÅ6°Ã6±Å6Ã6Å6Ã6Å6òÃ6óÅ6èÃ6éÅ6äÃ6åÅ6ÈÃ6ÉÅ6²Ã6³Å6¦Ã6§Å6Ã6Å6Ã6Å6§åÿ;èý;àý;áÿ;×ÿ;Úý;âý;ãÿ;Õÿ;Øý;§ÿ;ªý;Òý;Óÿ;Ïÿ;Òý;ý;ÿ;¿ÿ;Âý;¼ý;½ÿ;ºý;»ÿ;¸ý;¹ÿ;Ûÿ;Þý;¡ÿ;¤ý;ÿ;ý;ÿ;ý;ÿ;ý;Þý;ßÿ;ÿ;ý;ûÿ;þý;çÿ;êý;áÿ;äý;Úý;Ûÿ;Òý;Óÿ;²ý;³ÿ;ý;ÿ;ý;ÿ;ôý;õÿ;àý;áÿ;Öý;×ÿ;Òý;Óÿ;¶ý;·ÿ; ý;¡ÿ;ý;ÿ;ý;ÿ;ý;ÿ;§Ó¹AÖ·AÎ·AÏ¹AÅ¹AÈ·AÐ·AÑ¹AÃ¹AÆ·A¹A·AÀ·AÁ¹A½¹AÀ·Aú·Aû¹A­¹A°·Aª·A«¹A¨·A©¹A¦·A§¹AÉ¹AÌ·A¹A·A¹A·Aû¹Aþ·Añ¹Aô·AÌ·AÍ¹Aõ¹Aø·Aé¹Aì·AÕ¹AØ·AÏ¹AÒ·AÈ·AÉ¹AÀ·AÁ¹A ·A¡¹A·A¹Aô·Aõ¹Aâ·Aã¹AÎ·AÏ¹AÄ·AÅ¹AÀ·AÁ¹A¤·A¥¹A·A¹A·A¹Aø·Aù¹Aö·A÷¹A§ÁóFÄñF¼ñF½óF³óF¶ñF¾ñF¿óF±óF´ñFóFñF®ñF¯óF«óF®ñFèñFéóFóFñFñFóFñFóFñFóF·óFºñFýóFñFóóFöñFéóFìñFßóFâñFºñF»óFãóFæñF×óFÚñFÃóFÆñF½óFÀñF¶ñF·óF®ñF¯óFñFóFúÿñFûÿóFâÿñFãÿóFÐÿñFÑÿóF¼ÿñF½ÿóF²ÿñF³ÿóF®ÿñF¯ÿóFÿñFÿóFüþñFýþóFðþñFñþóFæþñFçþóFäþñFåþóF§¯þ­L²þ«Lªþ«L«þ­L¡þ­L¤þ«L¬þ«L­þ­Lþ­L¢þ«Lñþ­Lôþ«Lþ«Lþ­Lþ­Lþ«LÖþ«L×þ­Lþ­Lþ«Lþ«Lþ­Lþ«Lþ­Lþ«Lþ­L¥ÿ­L¨ÿ«Lëý­Lîý«Láý­Läý«L×ÿ­LÚÿ«LÍþ­LÐþ«L¨ÿ«L©ÿ­LÑý­LÔý«LÅý­LÈý«L±ý­L´ý«L«ý­L®ý«L¤ý«L¥ý­Lý«Lý­Lüü«Lýü­Lèü«Léü­LÐü«LÑü­L¾ü«L¿ü­Lªü«L«ü­L ü«L¡ü­Lü«Lü­Lü«Lü­Lêû«Lëû­LÞû«Lßû­LÔû«LÕû­LÒû«LÓû­L§ûçQ ûåQûåQûçQûçQûåQûåQûçQûçQûåQßûçQâûåQûåQûçQûçQûåQÄûåQÅûçQ÷úçQúúåQôúåQõúçQòúåQóúçQðúåQñúçQüçQüåQÙúçQÜúåQÏúçQÒúåQÅüçQÈüåQ»ûçQ¾ûåQüåQüçQ¿úçQÂúåQ³úçQ¶úåQúçQ¢úåQúçQúåQúåQúçQúåQúçQêùåQëùçQÖùåQ×ùçQ¾ùåQ¿ùçQ¬ùåQ­ùçQùåQùçQùåQùçQùåQùçQîøåQïøçQØøåQÙøçQÌøåQÍøçQÂøåQÃøçQÀøåQÁøçQ§ø¡WøWøWø¡Wý÷¡WøWøWø¡Wû÷¡Wþ÷WÍø¡WÐøWø÷Wù÷¡Wõ÷¡Wø÷W²øW³ø¡Wå÷¡Wè÷Wâ÷Wã÷¡Wà÷Wá÷¡WÞ÷Wß÷¡Wù¡WùWÇ÷¡WÊ÷W½÷¡WÀ÷W³ù¡W¶ùW©ø¡W¬øWùWù¡W­÷¡W°÷W¡÷¡W¤÷W÷¡W÷W÷¡W÷W÷W÷¡WøöWùö¡WØöWÙö¡WÄöWÅö¡W¬öW­ö¡WöWö¡WöWö¡WüõWýõ¡WøõWùõ¡WÜõWÝõ¡WÆõWÇõ¡WºõW»õ¡W°õW±õ¡W®õW¯õ¡W§ùôÛ\üôÙ\ôôÙ\õôÛ\ëôÛ\îôÙ\öôÙ\÷ôÛ\éôÛ\ìôÙ\»õÛ\¾õÙ\æôÙ\çôÛ\ãôÛ\æôÙ\ õÙ\¡õÛ\ÓôÛ\ÖôÙ\ÐôÙ\ÑôÛ\ÎôÙ\ÏôÛ\ÌôÙ\ÍôÛ\ïõÛ\òõÙ\µôÛ\¸ôÙ\«ôÛ\®ôÙ\¡öÛ\¤öÙ\õÛ\õÙ\òõÙ\óõÛ\ôÛ\ôÙ\ôÛ\ôÙ\ûóÛ\þóÙ\õóÛ\øóÙ\îóÙ\ïóÛ\æóÙ\çóÛ\ÆóÙ\ÇóÛ\²óÙ\³óÛ\óÙ\óÛ\óÙ\óÛ\ôòÙ\õòÛ\êòÙ\ëòÛ\æòÙ\çòÛ\ÊòÙ\ËòÛ\´òÙ\µòÛ\¨òÙ\©òÛ\òÙ\òÛ\òÙ\òÛ\§çñbêñbâñbãñbÙñbÜñbäñbåñb×ñbÚñb©òb¬òbÔñbÕñbÑñbÔñbòbòbÁñbÄñb¾ñb¿ñb¼ñb½ñbºñb»ñbÝòbàòb£ñb¦ñbñbñbóbóbòbòbàòbáòbñbñbýðbñbéðbìðbãðbæðbÜðbÝðbÔðbÕðb´ðbµðb ðb¡ðbðbðböïb÷ïbâïbãïbØïbÙïbÔïbÕïb¸ïb¹ïb¢ïb£ïbïbïbïbïbïbïb§ÕîÏgØîÍgÐîÍgÑîÏgÇîÏgÊîÍgÒîÍgÓîÏgÅîÏgÈîÍgïÏgïÍgÂîÍgÃîÏg¿îÏgÂîÍgüîÍgýîÏg¯îÏg²îÍg¬îÍg­îÏgªîÍg«îÏg¨îÍg©îÏgËïÏgÎïÍgîÏgîÍgîÏgîÍgýïÏgðÍgóîÏgöîÍgÎïÍgÏïÏg÷íÏgúíÍgëíÏgîíÍg×íÏgÚíÍgÑíÏgÔíÍgÊíÍgËíÏgÂíÍgÃíÏg¢íÍg£íÏgíÍgíÏgöìÍg÷ìÏgäìÍgåìÏgÐìÍgÑìÏgÆìÍgÇìÏgÂìÍgÃìÏg¦ìÍg§ìÏgìÍgìÏgìÍgìÏgúëÍgûëÏgøëÍgùëÏg§ÃëmÆëm¾ëm¿ëmµëm¸ëmÀëmÁëm³ëm¶ëmìmìm°ëm±ëm­ëm°ëmêëmëëmëm ëmëmëmëmëmëmëm¹ìm¼ìmÿêmëmõêmøêmëìmîìmáëmäëm¼ìm½ìmåêmèêmÙêmÜêmÅêmÈêm¿êmÂêm¸êm¹êm°êm±êmêmêmüémýémäémåémÒémÓém¾ém¿ém´émµém°ém±émémémþèmÿèmòèmóèmèèméèmæèmçèm§±èÃr´èÁr¬èÁr­èÃr£èÃr¦èÁr®èÁr¯èÃr¡èÃr¤èÁróèÃröèÁrèÁrèÃrèÃrèÁrØèÁrÙèÃrèÃrèÁrèÁrèÃrèÁrèÃrèÁrèÃr§éÃrªéÁríçÃrðçÁrãçÃræçÁrÙéÃrÜéÁrÏèÃrÒèÁrªéÁr«éÃrÓçÃrÖçÁrÇçÃrÊçÁr³çÃr¶çÁr­çÃr°çÁr¦çÁr§çÃrçÁrçÃrþæÁrÿæÃrêæÁrëæÃrÒæÁrÓæÃrÀæÁrÁæÃr¬æÁr­æÃr¢æÁr£æÃræÁræÃræÁræÃrìåÁríåÃràåÁráåÃrÖåÁr×åÃrÔåÁrÕåÃr§åýw¢åûwåûwåýwåýwåûwåûwåýwåýwåûwáåýwäåûwåûwåýwåýwåûwÆåûwÇåýwùäýwüäûwöäûw÷äýwôäûwõäýwòäûwóäýwæýwæûwÛäýwÞäûwÑäýwÔäûwÇæýwÊæûw½åýwÀåûwæûwæýwÁäýwÄäûwµäýw¸äûw¡äýw¤äûwäýwäûwäûwäýwäûwäýwìãûwíãýwØãûwÙãýwÀãûwÁãýw®ãûw¯ãýwãûwãýwãûwãýwãûwãýwðâûwñâýwÚâûwÛâýwÎâûwÏâýwÄâûwÅâýwÂâûwÃâýw§â·}âµ}âµ}â·}ÿá·}âµ}âµ}â·}ýá·}âµ}Ïâ·}Òâµ}úáµ}ûá·}÷á·}úáµ}´âµ}µâ·}çá·}êáµ}äáµ}åá·}âáµ}ãá·}àáµ}áá·}ã·}ãµ}Éá·}Ìáµ}¿á·}Âáµ}µã·}¸ãµ}«â·}®âµ}ãµ}ã·}¯á·}²áµ}£á·}¦áµ}á·}áµ}á·}áµ}áµ}á·}úàµ}ûà·}Úàµ}Ûà·}Æàµ}Çà·}®àµ}¯à·}àµ}à·}àµ}à·}þßµ}ÿß·}úßµ}ûß·}Þßµ}ßß·}Èßµ}Éß·}¼ßµ}½ß·}²ßµ}³ß·}°ßµ}±ß·}§ûÞñþÞïöÞï÷ÞñíÞñðÞïøÞïùÞñëÞñîÞï½ßñÀßïèÞïéÞñåÞñèÞï¢ßï£ßñÕÞñØÞïÒÞïÓÞñÐÞïÑÞñÎÞïÏÞññßñôßï·ÞñºÞï­Þñ°Þï£àñ¦àïßñßïôßïõßñÞñ ÞïÞñÞïýÝñÞï÷ÝñúÝïðÝïñÝñèÝïéÝñÈÝïÉÝñ´ÝïµÝñÝïÝñÝïÝñöÜï÷ÜñìÜïíÜñèÜïéÜñÌÜïÍÜñ¶Üï·ÜñªÜï«Üñ Üï¡ÜñÜïÜñ§éÛ«ìÛ©äÛ©åÛ«ÛÛ«ÞÛ©æÛ©çÛ«ÙÛ«ÜÛ©«Ü«®Ü©ÖÛ©×Û«ÓÛ«ÖÛ©Ü©Ü«ÃÛ«ÆÛ©ÀÛ©ÁÛ«¾Û©¿Û«¼Û©½Û«ßÜ«âÜ©¥Û«¨Û©Û«Û©Ý«Ý©Ü«Ü©âÜ©ãÜ«Û«Û©ÿÚ«Û©ëÚ«îÚ©åÚ«èÚ©ÞÚ©ßÚ«ÖÚ©×Ú«¶Ú©·Ú«¢Ú©£Ú«Ú©Ú«øÙ©ùÙ«äÙ©åÙ«ÚÙ©ÛÙ«ÖÙ©×Ù«ºÙ©»Ù«¤Ù©¥Ù«Ù©Ù«Ù©Ù«Ù©Ù«§×ØåÚØãÒØãÓØåÉØåÌØãÔØãÕØåÇØåÊØãÙåÙãÄØãÅØåÁØåÄØãþØãÿØå±Øå´Øã®Øã¯Øå¬Øã­ØåªØã«ØåÍÙåÐÙãØåØãØåØãÿÙåÚãõØåøØãÐÙãÑÙåù×åü×ãí×åð×ãÙ×åÜ×ãÓ×åÖ×ãÌ×ãÍ×åÄ×ãÅ×å¤×ã¥×å×ã×åøÖãùÖåæÖãçÖåÒÖãÓÖåÈÖãÉÖåÄÖãÅÖå¨Öã©ÖåÖãÖåÖãÖåüÕãýÕåúÕãûÕå§ÅÕÈÕÀÕÁÕ·ÕºÕÂÕÃÕµÕ¸ÕÖÖ²Õ³Õ¯Õ²ÕìÕíÕÕ¢ÕÕÕÕÕÕÕ»Ö¾ÖÕÕ÷ÔúÔíÖðÖãÕæÕ¾Ö¿ÖçÔêÔÛÔÞÔÇÔÊÔÁÔÄÔºÔ»Ô²Ô³ÔÔÔþÓÿÓæÓçÓÔÓÕÓÀÓÁÓ¶Ó·Ó²Ó³ÓÓÓÓÓôÒõÒêÒëÒèÒéÒ§³ÒÙ¶Ò×®Ò×¯ÒÙ¥ÒÙ¨Ò×°Ò×±ÒÙ£ÒÙ¦Ò×õÒÙøÒ× Ò×¡ÒÙÒÙ Ò×ÚÒ×ÛÒÙÒÙÒ×Ò×ÒÙÒ×ÒÙÒ×ÒÙ©ÓÙ¬Ó×ïÑÙòÑ×åÑÙèÑ×ÛÓÙÞÓ×ÑÒÙÔÒ×¬Ó×­ÓÙÕÑÙØÑ×ÉÑÙÌÑ×µÑÙ¸Ñ×¯ÑÙ²Ñ×¨Ñ×©ÑÙ Ñ×¡ÑÙÑ×ÑÙìÐ×íÐÙÔÐ×ÕÐÙÂÐ×ÃÐÙ®Ð×¯ÐÙ¤Ð×¥ÐÙ Ð×¡ÐÙÐ×ÐÙîÏ×ïÏÙâÏ×ãÏÙØÏ×ÙÏÙÖÏ××ÏÙ§¡Ï¤ÏÏÏÏÏÏÏÏÏãÏæÏÏÏÏÏÈÏÉÏûÎþÎøÎùÎöÎ÷ÎôÎõÎÐÐÝÎàÎÓÎÖÎÉÐÌÐ¿ÏÂÏÐÐÃÎÆÎ·ÎºÎ£Î¦ÎÎ ÎÎÎÎÎîÍïÍÚÍÛÍÂÍÃÍ°Í±ÍÍÍÍÍÍÍòÌóÌÜÌÝÌÐÌÑÌÆÌÇÌÄÌÅÌ§ÌÍ£ÌË£ÌË£ÌÍ£ÌÍ£ÌË£ÌË£ÌÍ£ÿËÍ£ÌË£ÑÌÍ£ÔÌË£üËË£ýËÍ£ùËÍ£üËË£¶ÌË£·ÌÍ£éËÍ£ìËË£æËË£çËÍ£äËË£åËÍ£âËË£ãËÍ£ÍÍ£ÍË£ËËÍ£ÎËË£ÁËÍ£ÄËË£·ÍÍ£ºÍË£­ÌÍ£°ÌË£ÍË£ÍÍ£±ËÍ£´ËË£¥ËÍ£¨ËË£ËÍ£ËË£ËÍ£ËË£ËË£ËÍ£üÊË£ýÊÍ£ÜÊË£ÝÊÍ£ÈÊË£ÉÊÍ£°ÊË£±ÊÍ£ÊË£ÊÍ£ÊË£ÊÍ£ÊË£ÊÍ£üÉË£ýÉÍ£àÉË£áÉÍ£ÊÉË£ËÉÍ£¾ÉË£¿ÉÍ£´ÉË£µÉÍ£²ÉË£³ÉÍ£§ýÈ©É©øÈ©ùÈ©ïÈ©òÈ©úÈ©ûÈ©íÈ©ðÈ©¿É©ÂÉ©êÈ©ëÈ©çÈ©êÈ©¤É©¥É©×È©ÚÈ©ÔÈ©ÕÈ©ÒÈ©ÓÈ©ÐÈ©ÑÈ©óÉ©öÉ©¹È©¼È©¯È©²È©¥Ê©¨Ê©É©É©öÉ©÷É©È©¢È©È©È©ÿÇ©È©ùÇ©üÇ©òÇ©óÇ©êÇ©ëÇ©ÊÇ©ËÇ©¶Ç©·Ç©Ç©Ç©Ç©Ç©øÆ©ùÆ©îÆ©ïÆ©êÆ©ëÆ©ÎÆ©ÏÆ©¸Æ©¹Æ©¬Æ©­Æ©¢Æ©£Æ© Æ©¡Æ©§ëÅÁ®îÅ¿®æÅ¿®çÅÁ®ÝÅÁ®àÅ¿®èÅ¿®éÅÁ®ÛÅÁ®ÞÅ¿®­ÆÁ®°Æ¿®ØÅ¿®ÙÅÁ®ÕÅÁ®ØÅ¿®Æ¿®ÆÁ®ÅÅÁ®ÈÅ¿®ÂÅ¿®ÃÅÁ®ÀÅ¿®ÁÅÁ®¾Å¿®¿ÅÁ®áÆÁ®äÆ¿®§ÅÁ®ªÅ¿®ÅÁ® Å¿®ÇÁ®Ç¿®ÆÁ®Æ¿®äÆ¿®åÆÁ®ÅÁ®Å¿®ÅÁ®Å¿®íÄÁ®ðÄ¿®çÄÁ®êÄ¿®àÄ¿®áÄÁ®ØÄ¿®ÙÄÁ®¸Ä¿®¹ÄÁ®¤Ä¿®¥ÄÁ®Ä¿®ÄÁ®úÃ¿®ûÃÁ®æÃ¿®çÃÁ®ÜÃ¿®ÝÃÁ®ØÃ¿®ÙÃÁ®¼Ã¿®½ÃÁ®¦Ã¿®§ÃÁ®Ã¿®ÃÁ®Ã¿®ÃÁ®Ã¿®ÃÁ®§ÙÂû³ÜÂù³ÔÂù³ÕÂû³ËÂû³ÎÂù³ÖÂù³×Âû³ÉÂû³ÌÂù³Ãû³Ãù³ÆÂù³ÇÂû³ÃÂû³ÆÂù³Ãù³Ãû³³Âû³¶Âù³°Âù³±Âû³®Âù³¯Âû³¬Âù³­Âû³ÏÃû³ÒÃù³Âû³Âù³Âû³Âù³Äû³Äù³÷Âû³úÂù³ÒÃù³ÓÃû³ûÁû³þÁù³ïÁû³òÁù³ÛÁû³ÞÁù³ÕÁû³ØÁù³ÎÁù³ÏÁû³ÆÁù³ÇÁû³¦Áù³§Áû³Áù³Áû³úÀù³ûÀû³èÀù³éÀû³ÔÀù³ÕÀû³ÊÀù³ËÀû³ÆÀù³ÇÀû³ªÀù³«Àû³Àù³Àû³Àù³Àû³þ¿ù³ÿ¿û³ü¿ù³ý¿û³§Ç¿µ¹Ê¿³¹Â¿³¹Ã¿µ¹¹¿µ¹¼¿³¹Ä¿³¹Å¿µ¹·¿µ¹º¿³¹Àµ¹À³¹´¿³¹µ¿µ¹±¿µ¹´¿³¹î¿³¹ï¿µ¹¡¿µ¹¤¿³¹¿³¹¿µ¹¿³¹¿µ¹¿³¹¿µ¹½Àµ¹ÀÀ³¹¿µ¹¿³¹ù¾µ¹ü¾³¹ïÀµ¹òÀ³¹å¿µ¹è¿³¹ÀÀ³¹ÁÀµ¹é¾µ¹ì¾³¹Ý¾µ¹à¾³¹É¾µ¹Ì¾³¹Ã¾µ¹Æ¾³¹¼¾³¹½¾µ¹´¾³¹µ¾µ¹¾³¹¾µ¹¾³¹¾µ¹è½³¹é½µ¹Ö½³¹×½µ¹Â½³¹Ã½µ¹¸½³¹¹½µ¹´½³¹µ½µ¹½³¹½µ¹½³¹½µ¹ö¼³¹÷¼µ¹ì¼³¹í¼µ¹ê¼³¹ë¼µ¹§µ¼ï¾¸¼í¾°¼í¾±¼ï¾§¼ï¾ª¼í¾²¼í¾³¼ï¾¥¼ï¾¨¼í¾÷¼ï¾ú¼í¾¢¼í¾£¼ï¾¼ï¾¢¼í¾Ü¼í¾Ý¼ï¾¼ï¾¼í¾¼í¾¼ï¾¼í¾¼ï¾¼í¾¼ï¾«½ï¾®½í¾ñ»ï¾ô»í¾ç»ï¾ê»í¾Ý½ï¾à½í¾Ó¼ï¾Ö¼í¾®½í¾¯½ï¾×»ï¾Ú»í¾Ë»ï¾Î»í¾·»ï¾º»í¾±»ï¾´»í¾ª»í¾«»ï¾¢»í¾£»ï¾»í¾»ï¾îºí¾ïºï¾Öºí¾×ºï¾Äºí¾Åºï¾°ºí¾±ºï¾¦ºí¾§ºï¾¢ºí¾£ºï¾ºí¾ºï¾ð¹í¾ñ¹ï¾ä¹í¾å¹ï¾Ú¹í¾Û¹ï¾Ø¹í¾Ù¹ï¾§£¹©Ä¦¹§Ä¹§Ä¹©Ä¹©Ä¹§Ä ¹§Ä¡¹©Ä¹©Ä¹§Äå¹©Äè¹§Ä¹§Ä¹©Ä¹©Ä¹§ÄÊ¹§ÄË¹©Äý¸©Ä¹§Äú¸§Äû¸©Äø¸§Äù¸©Äö¸§Ä÷¸©Äº©Äº§Äß¸©Äâ¸§ÄÕ¸©ÄØ¸§ÄËº©ÄÎº§ÄÁ¹©ÄÄ¹§Äº§Äº©ÄÅ¸©ÄÈ¸§Ä¹¸©Ä¼¸§Ä¥¸©Ä¨¸§Ä¸©Ä¢¸§Ä¸§Ä¸©Ä¸§Ä¸©Äð·§Äñ·©ÄÜ·§ÄÝ·©ÄÄ·§ÄÅ·©Ä²·§Ä³·©Ä·§Ä·©Ä·§Ä·©Ä·§Ä·©Äô¶§Äõ¶©ÄÞ¶§Äß¶©ÄÒ¶§ÄÓ¶©ÄÈ¶§ÄÉ¶©ÄÆ¶§ÄÇ¶©Ä§¶ãÉ¶áÉ¶áÉ¶ãÉ¶ãÉ¶áÉ¶áÉ¶ãÉ¶ãÉ¶áÉÓ¶ãÉÖ¶áÉþµáÉÿµãÉûµãÉþµáÉ¸¶áÉ¹¶ãÉëµãÉîµáÉèµáÉéµãÉæµáÉçµãÉäµáÉåµãÉ·ãÉ·áÉÍµãÉÐµáÉÃµãÉÆµáÉ¹·ãÉ¼·áÉ¯¶ãÉ²¶áÉ·áÉ·ãÉ³µãÉ¶µáÉ§µãÉªµáÉµãÉµáÉµãÉµáÉµáÉµãÉþ´áÉÿ´ãÉÞ´áÉß´ãÉÊ´áÉË´ãÉ²´áÉ³´ãÉ ´áÉ¡´ãÉ´áÉ´ãÉ´áÉ´ãÉþ³áÉÿ³ãÉâ³áÉã³ãÉÌ³áÉÍ³ãÉÀ³áÉÁ³ãÉ¶³áÉ·³ãÉ´³áÉµ³ãÉ§ÿ²Ï³Ïú²Ïû²Ïñ²Ïô²Ïü²Ïý²Ïï²Ïò²ÏÁ³ÏÄ³Ïì²Ïí²Ïé²Ïì²Ï¦³Ï§³ÏÙ²ÏÜ²ÏÖ²Ï×²ÏÔ²ÏÕ²ÏÒ²ÏÓ²Ïõ³Ïø³Ï»²Ï¾²Ï±²Ï´²Ï§´Ïª´Ï³Ï ³Ïø³Ïù³Ï¡²Ï¤²Ï²Ï²Ï²Ï²Ïû±Ïþ±Ïô±Ïõ±Ïì±Ïí±ÏÌ±ÏÍ±Ï¸±Ï¹±Ï ±Ï¡±Ï±Ï±Ïú°Ïû°Ïð°Ïñ°Ïì°Ïí°ÏÐ°ÏÑ°Ïº°Ï»°Ï®°Ï¯°Ï¤°Ï¥°Ï¢°Ï£°Ï§í¯×Ôð¯ÕÔè¯ÕÔé¯×Ôß¯×Ôâ¯ÕÔê¯ÕÔë¯×ÔÝ¯×Ôà¯ÕÔ¯°×Ô²°ÕÔÚ¯ÕÔÛ¯×Ô×¯×ÔÚ¯ÕÔ°ÕÔ°×ÔÇ¯×ÔÊ¯ÕÔÄ¯ÕÔÅ¯×ÔÂ¯ÕÔÃ¯×ÔÀ¯ÕÔÁ¯×Ôã°×Ôæ°ÕÔ©¯×Ô¬¯ÕÔ¯×Ô¢¯ÕÔ±×Ô±ÕÔ°×Ô°ÕÔæ°ÕÔç°×Ô¯×Ô¯ÕÔ¯×Ô¯ÕÔï®×Ôò®ÕÔé®×Ôì®ÕÔâ®ÕÔã®×ÔÚ®ÕÔÛ®×Ôº®ÕÔ»®×Ô¦®ÕÔ§®×Ô®ÕÔ®×Ôü­ÕÔý­×Ôè­ÕÔé­×ÔÞ­ÕÔß­×ÔÚ­ÕÔÛ­×Ô¾­ÕÔ¿­×Ô¨­ÕÔ©­×Ô­ÕÔ­×Ô­ÕÔ­×Ô­ÕÔ­×Ô§Û¬ÚÞ¬ÚÖ¬Ú×¬ÚÍ¬ÚÐ¬ÚØ¬ÚÙ¬ÚË¬ÚÎ¬Ú­Ú ­ÚÈ¬ÚÉ¬ÚÅ¬ÚÈ¬Ú­Ú­Úµ¬Ú¸¬Ú²¬Ú³¬Ú°¬Ú±¬Ú®¬Ú¯¬ÚÑ­ÚÔ­Ú¬Ú¬Ú¬Ú¬Ú®Ú®Úù¬Úü¬ÚÔ­ÚÕ­Úý«Ú¬Úñ«Úô«ÚÝ«Úà«Ú×«ÚÚ«ÚÐ«ÚÑ«ÚÈ«ÚÉ«Ú¨«Ú©«Ú«Ú«ÚüªÚýªÚêªÚëªÚÖªÚ×ªÚÌªÚÍªÚÈªÚÉªÚ¬ªÚ­ªÚªÚªÚªÚªÚªÚªÚþ©Úÿ©Ú§É©ËßÌ©ÉßÄ©ÉßÅ©Ëß»©Ëß¾©ÉßÆ©ÉßÇ©Ëß¹©Ëß¼©ÉßªËßªÉß¶©Éß·©Ëß³©Ëß¶©Éßð©Éßñ©Ëß£©Ëß¦©Éß ©Éß¡©Ëß©Éß©Ëß©Éß©Ëß¿ªËßÂªÉß©Ëß©Éßû¨Ëßþ¨ÉßñªËßôªÉßç©Ëßê©ÉßÂªÉßÃªËßë¨Ëßî¨Éßß¨Ëßâ¨ÉßË¨ËßÎ¨ÉßÅ¨ËßÈ¨Éß¾¨Éß¿¨Ëß¶¨Éß·¨Ëß¨Éß¨Ëß¨Éß¨Ëßê§Éßë§ËßØ§ÉßÙ§ËßÄ§ÉßÅ§Ëßº§Éß»§Ëß¶§Éß·§Ëß§Éß§Ëß§Éß§Ëßø¦Éßù¦Ëßî¦Éßï¦Ëßì¦Éßí¦Ëß§·¦åº¦å²¦å³¦å©¦å¬¦å´¦åµ¦å§¦åª¦åù¦åü¦å¤¦å¥¦å¡¦å¤¦åÞ¦åß¦å¦å¦å¦å¦å¦å¦å¦å¦å­§å°§åó¥åö¥åé¥åì¥åß§åâ§åÕ¦åØ¦å°§å±§åÙ¥åÜ¥åÍ¥åÐ¥å¹¥å¼¥å³¥å¶¥å¬¥å­¥å¤¥å¥¥å¥å¥åð¤åñ¤åØ¤åÙ¤åÆ¤åÇ¤å²¤å³¤å¨¤å©¤å¤¤å¥¤å¤å¤åò£åó£åæ£åç£åÜ£åÝ£åÚ£åÛ£å§ï»ò¹ê¹ë»á»ä¹ì¹í»ß»â¹±»´¹Ü¹Ý»Ù»Ü¹¹»É»Ì¹Æ¹Ç»Ä¹Å»Â¹Ã»å»è¹«»®¹¡»¤¹»¹»¹è¹é»»¹»¹ñ»ô¹ë»î¹ä¹å»Ü¹Ý»¼¹½»¨¹©»¹»þ¹ÿ»ê¹ë»à¹á»Ü¹Ý»À¹Á»ª¹«»¹»¹»¹»§Ýÿõ
+àÿó
+Øÿó
+Ùÿõ
+Ïÿõ
+Òÿó
+Úÿó
+Ûÿõ
+Íÿõ
+Ðÿó
+õ
+¢ó
+Êÿó
+Ëÿõ
+Çÿõ
+Êÿó
+ó
+õ
+·ÿõ
+ºÿó
+´ÿó
+µÿõ
+²ÿó
+³ÿõ
+°ÿó
+±ÿõ
+Óõ
+Öó
+ÿõ
+ÿó
+ÿõ
+ÿó
+õ
+ó
+ûÿõ
+þÿó
+Öó
+×õ
+ÿþõ
+ÿó
+óþõ
+öþó
+ßþõ
+âþó
+Ùþõ
+Üþó
+Òþó
+Óþõ
+Êþó
+Ëþõ
+ªþó
+«þõ
+þó
+þõ
+þýó
+ÿýõ
+ìýó
+íýõ
+Øýó
+Ùýõ
+Îýó
+Ïýõ
+Êýó
+Ëýõ
+®ýó
+¯ýõ
+ýó
+ýõ
+ýó
+ýõ
+ýó
+ýõ
+ýó
+ýõ
+§Ëü¯Îü­Æü­Çü¯½ü¯Àü­Èü­Éü¯»ü¯¾ü­ý¯ý­¸ü­¹ü¯µü¯¸ü­òü­óü¯¥ü¯¨ü­¢ü­£ü¯ ü­¡ü¯ü­ü¯Áý¯Äý­ü¯ü­ýû¯ü­óý¯öý­éü¯ìü­Äý­Åý¯íû¯ðû­áû¯äû­Íû¯Ðû­Çû¯Êû­Àû­Áû¯¸û­¹û¯û­û¯û­û¯ìú­íú¯Úú­Ûú¯Æú­Çú¯¼ú­½ú¯¸ú­¹ú¯ú­ú¯ú­ú¯úù­ûù¯ðù­ñù¯îù­ïù¯§¹ùé¼ùç´ùçµùé«ùé®ùç¶ùç·ùé©ùé¬ùçûùéþùç¦ùç§ùé£ùé¦ùçàùçáùéùéùçùçùéùçùéùçùé¯úé²úçõøéøøçëøéîøçáúéäúç×ùéÚùç²úç³úéÛøéÞøçÏøéÒøç»øé¾øçµøé¸øç®øç¯øé¦øç§øéøçøéò÷çó÷éÚ÷çÛ÷éÈ÷çÉ÷é´÷çµ÷éª÷ç«÷é¦÷ç§÷é÷ç÷éôöçõöéèöçéöéÞöçßöéÜöçÝöé§§ö£ªö¡¢ö¡£ö£ö£ö¡¤ö¡¥ö£ö£ö¡éö£ìö¡ö¡ö£ö£ö¡Îö¡Ïö£ö£ö¡þõ¡ÿõ£üõ¡ýõ£úõ¡ûõ£÷£ ÷¡ãõ£æõ¡Ùõ£Üõ¡Ï÷£Ò÷¡Åö£Èö¡ ÷¡¡÷£Éõ£Ìõ¡½õ£Àõ¡©õ£¬õ¡£õ£¦õ¡õ¡õ£õ¡õ£ôô¡õô£àô¡áô£Èô¡Éô£¶ô¡·ô£¢ô¡£ô£ô¡ô£ô¡ô£øó¡ùó£âó¡ãó£Öó¡×ó£Ìó¡Íó£Êó¡Ëó£§óÝ óÛ óÛ óÝ óÝ óÛ óÛ óÝ óÝ óÛ ×óÝ ÚóÛ óÛ óÝ ÿòÝ óÛ ¼óÛ ½óÝ ïòÝ òòÛ ìòÛ íòÝ êòÛ ëòÝ èòÛ éòÝ ôÝ ôÛ ÑòÝ ÔòÛ ÇòÝ ÊòÛ ½ôÝ ÀôÛ ³óÝ ¶óÛ ôÛ ôÝ ·òÝ ºòÛ «òÝ ®òÛ òÝ òÛ òÝ òÛ òÛ òÝ òÛ òÝ âñÛ ãñÝ ÎñÛ ÏñÝ ¶ñÛ ·ñÝ ¤ñÛ ¥ñÝ ñÛ ñÝ ñÛ ñÝ ñÛ ñÝ æðÛ çðÝ ÐðÛ ÑðÝ ÄðÛ ÅðÝ ºðÛ »ðÝ ¸ðÛ ¹ðÝ §ð&ð&þï&ÿï&õï&øï&ð&ð&óï&öï&Åð&Èð&ðï&ñï&íï&ðï&ªð&«ð&Ýï&àï&Úï&Ûï&Øï&Ùï&Öï&×ï&ùð&üð&¿ï&Âï&µï&¸ï&«ñ&®ñ&¡ð&¤ð&üð&ýð&¥ï&¨ï&ï&ï&ï&ï&ÿî&ï&øî&ùî&ðî&ñî&Ðî&Ñî&¼î&½î&¤î&¥î&î&î&þí&ÿí&ôí&õí&ðí&ñí&Ôí&Õí&¾í&¿í&²í&³í&¨í&©í&¦í&§í&§ñìÑ+ôìÏ+ììÏ+íìÑ+ãìÑ+æìÏ+îìÏ+ïìÑ+áìÑ+äìÏ+³íÑ+¶íÏ+ÞìÏ+ßìÑ+ÛìÑ+ÞìÏ+íÏ+íÑ+ËìÑ+ÎìÏ+ÈìÏ+ÉìÑ+ÆìÏ+ÇìÑ+ÄìÏ+ÅìÑ+çíÑ+êíÏ+­ìÑ+°ìÏ+£ìÑ+¦ìÏ+îÑ+îÏ+íÑ+íÏ+êíÏ+ëíÑ+ìÑ+ìÏ+ìÑ+ìÏ+óëÑ+öëÏ+íëÑ+ðëÏ+æëÏ+çëÑ+ÞëÏ+ßëÑ+¾ëÏ+¿ëÑ+ªëÏ+«ëÑ+ëÏ+ëÑ+ëÏ+ëÑ+ìêÏ+íêÑ+âêÏ+ãêÑ+ÞêÏ+ßêÑ+ÂêÏ+ÃêÑ+¬êÏ+­êÑ+ êÏ+¡êÑ+êÏ+êÑ+êÏ+êÑ+§ßé1âé1Úé1Ûé1Ñé1Ôé1Üé1Ýé1Ïé1Òé1¡ê1¤ê1Ìé1Íé1Éé1Ìé1ê1ê1¹é1¼é1¶é1·é1´é1µé1²é1³é1Õê1Øê1é1é1é1é1ë1ë1ýé1ê1Øê1Ùê1é1é1õè1øè1áè1äè1Ûè1Þè1Ôè1Õè1Ìè1Íè1¬è1­è1è1è1è1è1îç1ïç1Úç1Ûç1Ðç1Ñç1Ìç1Íç1°ç1±ç1ç1ç1ç1ç1ç1ç1ç1ç1§ÍæÅ6ÐæÃ6ÈæÃ6ÉæÅ6¿æÅ6ÂæÃ6ÊæÃ6ËæÅ6½æÅ6ÀæÃ6çÅ6çÃ6ºæÃ6»æÅ6·æÅ6ºæÃ6ôæÃ6õæÅ6§æÅ6ªæÃ6¤æÃ6¥æÅ6¢æÃ6£æÅ6 æÃ6¡æÅ6ÃçÅ6ÆçÃ6æÅ6æÃ6ÿåÅ6æÃ6õçÅ6øçÃ6ëæÅ6îæÃ6ÆçÃ6ÇçÅ6ïåÅ6òåÃ6ãåÅ6æåÃ6ÏåÅ6ÒåÃ6ÉåÅ6ÌåÃ6ÂåÃ6ÃåÅ6ºåÃ6»åÅ6åÃ6åÅ6åÃ6åÅ6îäÃ6ïäÅ6ÜäÃ6ÝäÅ6ÈäÃ6ÉäÅ6¾äÃ6¿äÅ6ºäÃ6»äÅ6äÃ6äÅ6äÃ6äÅ6üãÃ6ýãÅ6òãÃ6óãÅ6ðãÃ6ñãÅ6§»ãÿ;¾ãý;¶ãý;·ãÿ;­ãÿ;°ãý;¸ãý;¹ãÿ;«ãÿ;®ãý;ýãÿ;äý;¨ãý;©ãÿ;¥ãÿ;¨ãý;âãý;ããÿ;ãÿ;ãý;ãý;ãÿ;ãý;ãÿ;ãý;ãÿ;±äÿ;´äý;÷âÿ;úâý;íâÿ;ðâý;ãäÿ;æäý;Ùãÿ;Üãý;´äý;µäÿ;Ýâÿ;àâý;Ñâÿ;Ôâý;½âÿ;Àâý;·âÿ;ºâý;°âý;±âÿ;¨âý;©âÿ;âý;âÿ;ôáý;õáÿ;Üáý;Ýáÿ;Êáý;Ëáÿ;¶áý;·áÿ;¬áý;­áÿ;¨áý;©áÿ;áý;áÿ;öàý;÷àÿ;êàý;ëàÿ;ààý;áàÿ;Þàý;ßàÿ;§©à¹A¬à·A¤à·A¥à¹Aà¹Aà·A¦à·A§à¹Aà¹Aà·Aëà¹Aîà·Aà·Aà¹Aà¹Aà·AÐà·AÑà¹Aà¹Aà·Aà·Aà¹Aþß·Aÿß¹Aüß·Aýß¹Aá¹A¢á·Aåß¹Aèß·AÛß¹AÞß·AÑá¹AÔá·AÇà¹AÊà·A¢á·A£á¹AËß¹AÎß·A¿ß¹AÂß·A«ß¹A®ß·A¥ß¹A¨ß·Aß·Aß¹Aß·Aß¹AöÞ·A÷Þ¹AâÞ·AãÞ¹AÊÞ·AËÞ¹A¸Þ·A¹Þ¹A¤Þ·A¥Þ¹AÞ·AÞ¹AÞ·AÞ¹AúÝ·AûÝ¹AäÝ·AåÝ¹AØÝ·AÙÝ¹AÎÝ·AÏÝ¹AÌÝ·AÍÝ¹A§ÝóFÝñFÝñFÝóFÝóFÝñFÝñFÝóFÝóFÝñFÙÝóFÜÝñFÝñFÝóFÝóFÝñF¾ÝñF¿ÝóFñÜóFôÜñFîÜñFïÜóFìÜñFíÜóFêÜñFëÜóFÞóFÞñFÓÜóFÖÜñFÉÜóFÌÜñF¿ÞóFÂÞñFµÝóF¸ÝñFÞñFÞóF¹ÜóF¼ÜñF­ÜóF°ÜñFÜóFÜñFÜóFÜñFÜñFÜóFÜñFÜóFäÛñFåÛóFÐÛñFÑÛóF¸ÛñF¹ÛóF¦ÛñF§ÛóFÛñFÛóFÛñFÛóFÛñFÛóFèÚñFéÚóFÒÚñFÓÚóFÆÚñFÇÚóF¼ÚñF½ÚóFºÚñF»ÚóF§Ú­LÚ«LÚ«LÚ­L÷Ù­LúÙ«LÚ«LÚ­LõÙ­LøÙ«LÇÚ­LÊÚ«LòÙ«LóÙ­LïÙ­LòÙ«L¬Ú«L­Ú­LßÙ­LâÙ«LÜÙ«LÝÙ­LÚÙ«LÛÙ­LØÙ«LÙÙ­LûÚ­LþÚ«LÁÙ­LÄÙ«L·Ù­LºÙ«L­Û­L°Û«L£Ú­L¦Ú«LþÚ«LÿÚ­L§Ù­LªÙ«LÙ­LÙ«LÙ­LÙ«LÙ­LÙ«LúØ«LûØ­LòØ«LóØ­LÒØ«LÓØ­L¾Ø«L¿Ø­L¦Ø«L§Ø­LØ«LØ­LØ«LØ­Lö×«L÷×­Lò×«Ló×­LÖ×«L××­LÀ×«LÁ×­L´×«Lµ×­Lª×«L«×­L¨×«L©×­L§óÖçQöÖåQîÖåQïÖçQåÖçQèÖåQðÖåQñÖçQãÖçQæÖåQµ×çQ¸×åQàÖåQáÖçQÝÖçQàÖåQ×åQ×çQÍÖçQÐÖåQÊÖåQËÖçQÈÖåQÉÖçQÆÖåQÇÖçQé×çQì×åQ¯ÖçQ²ÖåQ¥ÖçQ¨ÖåQØçQØåQ×çQ×åQì×åQí×çQÖçQÖåQÖçQÖåQõÕçQøÕåQïÕçQòÕåQèÕåQéÕçQàÕåQáÕçQÀÕåQÁÕçQ¬ÕåQ­ÕçQÕåQÕçQÕåQÕçQîÔåQïÔçQäÔåQåÔçQàÔåQáÔçQÄÔåQÅÔçQ®ÔåQ¯ÔçQ¢ÔåQ£ÔçQÔåQÔçQÔåQÔçQ§áÓ¡WäÓWÜÓWÝÓ¡WÓÓ¡WÖÓWÞÓWßÓ¡WÑÓ¡WÔÓW£Ô¡W¦ÔWÎÓWÏÓ¡WËÓ¡WÎÓWÔWÔ¡W»Ó¡W¾ÓW¸ÓW¹Ó¡W¶ÓW·Ó¡W´ÓWµÓ¡W×Ô¡WÚÔWÓ¡W ÓWÓ¡WÓWÕ¡WÕWÿÓ¡WÔWÚÔWÛÔ¡WÓ¡WÓW÷Ò¡WúÒWãÒ¡WæÒWÝÒ¡WàÒWÖÒW×Ò¡WÎÒWÏÒ¡W®ÒW¯Ò¡WÒWÒ¡WÒWÒ¡WðÑWñÑ¡WÜÑWÝÑ¡WÒÑWÓÑ¡WÎÑWÏÑ¡W²ÑW³Ñ¡WÑWÑ¡WÑWÑ¡WÑWÑ¡WÑWÑ¡W§ÏÐÛ\ÒÐÙ\ÊÐÙ\ËÐÛ\ÁÐÛ\ÄÐÙ\ÌÐÙ\ÍÐÛ\¿ÐÛ\ÂÐÙ\ÑÛ\ÑÙ\¼ÐÙ\½ÐÛ\¹ÐÛ\¼ÐÙ\öÐÙ\÷ÐÛ\©ÐÛ\¬ÐÙ\¦ÐÙ\§ÐÛ\¤ÐÙ\¥ÐÛ\¢ÐÙ\£ÐÛ\ÅÑÛ\ÈÑÙ\ÐÛ\ÐÙ\ÐÛ\ÐÙ\÷ÑÛ\úÑÙ\íÐÛ\ðÐÙ\ÈÑÙ\ÉÑÛ\ñÏÛ\ôÏÙ\åÏÛ\èÏÙ\ÑÏÛ\ÔÏÙ\ËÏÛ\ÎÏÙ\ÄÏÙ\ÅÏÛ\¼ÏÙ\½ÏÛ\ÏÙ\ÏÛ\ÏÙ\ÏÛ\ðÎÙ\ñÎÛ\ÞÎÙ\ßÎÛ\ÊÎÙ\ËÎÛ\ÀÎÙ\ÁÎÛ\¼ÎÙ\½ÎÛ\ ÎÙ\¡ÎÛ\ÎÙ\ÎÛ\þÍÙ\ÿÍÛ\ôÍÙ\õÍÛ\òÍÙ\óÍÛ\§½ÍbÀÍb¸Íb¹Íb¯Íb²ÍbºÍb»Íb­Íb°ÍbÿÍbÎbªÍb«Íb§ÍbªÍbäÍbåÍbÍbÍbÍbÍbÍbÍbÍbÍb³Îb¶ÎbùÌbüÌbïÌbòÌbåÎbèÎbÛÍbÞÍb¶Îb·ÎbßÌbâÌbÓÌbÖÌb¿ÌbÂÌb¹Ìb¼Ìb²Ìb³ÌbªÌb«ÌbÌbÌböËb÷ËbÞËbßËbÌËbÍËb¸Ëb¹Ëb®Ëb¯ËbªËb«ËbËbËbøÊbùÊbìÊbíÊbâÊbãÊbàÊbáÊb§«ÊÏg®ÊÍg¦ÊÍg§ÊÏgÊÏg ÊÍg¨ÊÍg©ÊÏgÊÏgÊÍgíÊÏgðÊÍgÊÍgÊÏgÊÏgÊÍgÒÊÍgÓÊÏgÊÏgÊÍgÊÍgÊÏgÊÍgÊÏgþÉÍgÿÉÏg¡ËÏg¤ËÍgçÉÏgêÉÍgÝÉÏgàÉÍgÓËÏgÖËÍgÉÊÏgÌÊÍg¤ËÍg¥ËÏgÍÉÏgÐÉÍgÁÉÏgÄÉÍg­ÉÏg°ÉÍg§ÉÏgªÉÍg ÉÍg¡ÉÏgÉÍgÉÏgøÈÍgùÈÏgäÈÍgåÈÏgÌÈÍgÍÈÏgºÈÍg»ÈÏg¦ÈÍg§ÈÏgÈÍgÈÏgÈÍgÈÏgüÇÍgýÇÏgæÇÍgçÇÏgÚÇÍgÛÇÏgÐÇÍgÑÇÏgÎÇÍgÏÇÏg§ÇmÇmÇmÇmÇmÇmÇmÇmÇmÇmÛÇmÞÇmÇmÇmÇmÇmÀÇmÁÇmóÆmöÆmðÆmñÆmîÆmïÆmìÆmíÆmÈmÈmÕÆmØÆmËÆmÎÆmÁÈmÄÈm·ÇmºÇmÈmÈm»Æm¾Æm¯Æm²ÆmÆmÆmÆmÆmÆmÆmÆmÆmæÅmçÅmÒÅmÓÅmºÅm»Åm¨Åm©ÅmÅmÅmÅmÅmÅmÅmêÄmëÄmÔÄmÕÄmÈÄmÉÄm¾Äm¿Äm¼Äm½Äm§ÄÃrÄÁrÄÁrÄÃrùÃÃrüÃÁrÄÁrÄÃr÷ÃÃrúÃÁrÉÄÃrÌÄÁrôÃÁrõÃÃrñÃÃrôÃÁr®ÄÁr¯ÄÃráÃÃräÃÁrÞÃÁrßÃÃrÜÃÁrÝÃÃrÚÃÁrÛÃÃrýÄÃrÅÁrÃÃÃrÆÃÁr¹ÃÃr¼ÃÁr¯ÅÃr²ÅÁr¥ÄÃr¨ÄÁrÅÁrÅÃr©ÃÃr¬ÃÁrÃÃr ÃÁrÃÃrÃÁrÃÃrÃÁrüÂÁrýÂÃrôÂÁrõÂÃrÔÂÁrÕÂÃrÀÂÁrÁÂÃr¨ÂÁr©ÂÃrÂÁrÂÃrÂÁrÂÃrøÁÁrùÁÃrôÁÁrõÁÃrØÁÁrÙÁÃrÂÁÁrÃÁÃr¶ÁÁr·ÁÃr¬ÁÁr­ÁÃrªÁÁr«ÁÃr§õÀýwøÀûwðÀûwñÀýwçÀýwêÀûwòÀûwóÀýwåÀýwèÀûw·ÁýwºÁûwâÀûwãÀýwßÀýwâÀûwÁûwÁýwÏÀýwÒÀûwÌÀûwÍÀýwÊÀûwËÀýwÈÀûwÉÀýwëÁýwîÁûw±Àýw´Àûw§ÀýwªÀûwÂýw ÂûwÁýwÁûwîÁûwïÁýwÀýwÀûwÀýwÀûw÷¿ýwú¿ûwñ¿ýwô¿ûwê¿ûwë¿ýwâ¿ûwã¿ýwÂ¿ûwÃ¿ýw®¿ûw¯¿ýw¿ûw¿ýw¿ûw¿ýwð¾ûwñ¾ýwæ¾ûwç¾ýwâ¾ûwã¾ýwÆ¾ûwÇ¾ýw°¾ûw±¾ýw¤¾ûw¥¾ýw¾ûw¾ýw¾ûw¾ýw§ã½·}æ½µ}Þ½µ}ß½·}Õ½·}Ø½µ}à½µ}á½·}Ó½·}Ö½µ}¥¾·}¨¾µ}Ð½µ}Ñ½·}Í½·}Ð½µ}¾µ}¾·}½½·}À½µ}º½µ}»½·}¸½µ}¹½·}¶½µ}·½·}Ù¾·}Ü¾µ}½·}¢½µ}½·}½µ}¿·}¿µ}¾·}¾µ}Ü¾µ}Ý¾·}½·}½µ}ù¼·}ü¼µ}å¼·}è¼µ}ß¼·}â¼µ}Ø¼µ}Ù¼·}Ð¼µ}Ñ¼·}°¼µ}±¼·}¼µ}¼·}¼µ}¼·}ò»µ}ó»·}Þ»µ}ß»·}Ô»µ}Õ»·}Ð»µ}Ñ»·}´»µ}µ»·}»µ}»·}»µ}»·}»µ}»·}»µ}»·}§ÑºñÔºïÌºïÍºñÃºñÆºïÎºïÏºñÁºñÄºï»ñ»ï¾ºï¿ºñ»ºñ¾ºïøºïùºñ«ºñ®ºï¨ºï©ºñ¦ºï§ºñ¤ºï¥ºñÇ»ñÊ»ïºñºïºñºïù»ñü»ïïºñòºïÊ»ïË»ñó¹ñö¹ïç¹ñê¹ïÓ¹ñÖ¹ïÍ¹ñÐ¹ïÆ¹ïÇ¹ñ¾¹ï¿¹ñ¹ï¹ñ¹ï¹ñò¸ïó¸ñà¸ïá¸ñÌ¸ïÍ¸ñÂ¸ïÃ¸ñ¾¸ï¿¸ñ¢¸ï£¸ñ¸ï¸ñ¸ï¸ñö·ï÷·ñô·ïõ·ñ§¿·«Â·©º·©»·«±·«´·©¼·©½·«¯·«²·©¸«¸©¬·©­·«©·«¬·©æ·©ç·«·«·©·©·«·©·«·©·«µ¸«¸¸©û¶«þ¶©ñ¶«ô¶©ç¸«ê¸©Ý·«à·©¸¸©¹¸«á¶«ä¶©Õ¶«Ø¶©Á¶«Ä¶©»¶«¾¶©´¶©µ¶«¬¶©­¶«¶©¶«øµ©ùµ«àµ©áµ«Îµ©Ïµ«ºµ©»µ«°µ©±µ«¬µ©­µ«µ©µ«ú´©û´«î´©ï´«ä´©å´«â´©ã´«§­´å°´ã¨´ã©´å´å¢´ãª´ã«´å´å ´ãï´åò´ã´ã´å´å´ãÔ´ãÕ´å´å´ã´ã´å´ã´å´ã´å£µå¦µãé³åì³ãß³åâ³ãÕµåØµãË´åÎ´ã¦µã§µåÏ³åÒ³ãÃ³åÆ³ã¯³å²³ã©³å¬³ã¢³ã£³å³ã³åú²ãû²åæ²ãç²åÎ²ãÏ²å¼²ã½²å¨²ã©²å²ã²å²ã²åþ±ãÿ±åè±ãé±åÜ±ãÝ±åÒ±ãÓ±åÐ±ãÑ±å§±±±±±±±±±±Ý±à±±±±±Â±Ã±õ°ø°ò°ó°ð°ñ°î°ï°²²×°Ú°Í°Ð°Ã²Æ²¹±¼±²²½°À°±°´°° °°°°°°°è¯é¯Ô¯Õ¯¼¯½¯ª¯«¯¯¯¯¯¯¯ì®í®Ö®×®Ê®Ë®À®Á®¾®¿®§®Ù®×®×®Ùû­Ùþ­×®×®Ùù­Ùü­×Ë®ÙÎ®×ö­×÷­Ùó­Ùö­×°®×±®Ùã­Ùæ­×à­×á­ÙÞ­×ß­ÙÜ­×Ý­Ùÿ®Ù¯×Å­ÙÈ­×»­Ù¾­×±¯Ù´¯×§®Ùª®×¯×¯Ù«­Ù®­×­Ù¢­×­Ù­×­Ù­×þ¬×ÿ¬Ùö¬×÷¬ÙÖ¬××¬ÙÂ¬×Ã¬Ùª¬×«¬Ù¬×¬Ù¬×¬Ùú«×û«Ùö«×÷«ÙÚ«×Û«ÙÄ«×Å«Ù¸«×¹«Ù®«×¯«Ù¬«×­«Ù§÷ªúªòªóªéªìªôªõªçªêª¹«¼«äªåªáªäª««ÑªÔªÎªÏªÌªÍªÊªËªí«ð«³ª¶ª©ª¬ª¬¢¬««ð«ñ«ªªªªù©ü©ó©ö©ì©í©ä©å©Ä©Å©°©±©©©©©ò¨ó¨è¨é¨ä¨å¨È¨É¨²¨³¨¦¨§¨¨¨¨¨§å§Í£è§Ë£à§Ë£á§Í£×§Í£Ú§Ë£â§Ë£ã§Í£Õ§Í£Ø§Ë£§¨Í£ª¨Ë£Ò§Ë£Ó§Í£Ï§Í£Ò§Ë£¨Ë£¨Í£¿§Í£Â§Ë£¼§Ë£½§Í£º§Ë£»§Í£¸§Ë£¹§Í£Û¨Í£Þ¨Ë£¡§Í£¤§Ë£§Í£§Ë£©Í£©Ë£¨Í£¨Ë£Þ¨Ë£ß¨Í£§Í£§Ë£û¦Í£þ¦Ë£ç¦Í£ê¦Ë£á¦Í£ä¦Ë£Ú¦Ë£Û¦Í£Ò¦Ë£Ó¦Í£²¦Ë£³¦Í£¦Ë£¦Í£¦Ë£¦Í£ô¥Ë£õ¥Í£à¥Ë£á¥Í£Ö¥Ë£×¥Í£Ò¥Ë£Ó¥Í£¶¥Ë£·¥Í£ ¥Ë£¡¥Í£¥Ë£¥Í£¥Ë£¥Í£¥Ë£¥Í£§Ó¤©Ö¤©Î¤©Ï¤©Å¤©È¤©Ð¤©Ñ¤©Ã¤©Æ¤©¥©¥©À¤©Á¤©½¤©À¤©ú¤©û¤©­¤©°¤©ª¤©«¤©¨¤©©¤©¦¤©§¤©É¥©Ì¥©¤©¤©¤©¤©û¥©þ¥©ñ¤©ô¤©Ì¥©Í¥©õ£©ø£©é£©ì£©Õ£©Ø£©Ï£©Ò£©È£©É£©À£©Á£© £©¡£©£©£©ô¢©õ¢©â¢©ã¢©Î¢©Ï¢©Ä¢©Å¢©À¢©Á¢©¤¢©¥¢©¢©¢©¢©¢©ø¡©ù¡©ö¡©÷¡©§Á¡Á®Ä¡¿®¼¡¿®½¡Á®³¡Á®¶¡¿®¾¡¿®¿¡Á®±¡Á®´¡¿®¢Á®¢¿®®¡¿®¯¡Á®«¡Á®®¡¿®è¡¿®é¡Á®¡Á®¡¿®¡¿®¡Á®¡¿®¡Á®¡¿®¡Á®·¢Á®º¢¿®ý Á®¡¿®ó Á®ö ¿®é¢Á®ì¢¿®ß¡Á®â¡¿®º¢¿®»¢Á®ã Á®æ ¿®× Á®Ú ¿®Ã Á®Æ ¿®½ Á®À ¿®¶ ¿®· Á®® ¿®¯ Á® ¿® Á®ú¿®ûÁ®â¿®ãÁ®Ð¿®ÑÁ®¼¿®½Á®²¿®³Á®®¿®¯Á®¿®Á®ü¿®ýÁ®ð¿®ñÁ®æ¿®çÁ®ä¿®åÁ®§¯û³²ù³ªù³«û³¡û³¤ù³¬ù³­û³û³¢ù³ñû³ôù³ù³û³û³ù³Öù³×û³û³ù³ù³û³ù³û³ù³û³¥û³¨ù³ëû³îù³áû³äù³×û³Úù³Íû³Ðù³¨ù³©û³Ñû³Ôù³Åû³Èù³±û³´ù³«û³®ù³¤ù³¥û³ù³û³üù³ýû³èù³éû³Ðù³Ñû³¾ù³¿û³ªù³«û³ ù³¡û³ù³û³ù³û³êù³ëû³Þù³ßû³Ôù³Õû³Òù³Óû³§µ¹ ³¹³¹µ¹µ¹³¹³¹µ¹µ¹³¹ßµ¹â³¹³¹µ¹µ¹³¹Ä³¹Åµ¹÷µ¹ú³¹ô³¹õµ¹ò³¹óµ¹ð³¹ñµ¹µ¹³¹Ùµ¹Ü³¹Ïµ¹Ò³¹Åµ¹È³¹»µ¹¾³¹³¹µ¹¿µ¹Â³¹³µ¹¶³¹µ¹¢³¹µ¹³¹³¹µ¹³¹µ¹ê³¹ëµ¹Ö³¹×µ¹¾³¹¿µ¹¬³¹­µ¹³¹µ¹³¹µ¹³¹µ¹î³¹ïµ¹Ø³¹Ùµ¹Ì³¹Íµ¹Â³¹Ãµ¹À³¹Áµ¹§ï¾í¾í¾ï¾ýï¾í¾í¾ï¾ûï¾þí¾Íï¾Ðí¾øí¾ùï¾õï¾øí¾²í¾³ï¾åï¾èí¾âí¾ãï¾àí¾áï¾Þí¾ßï¾ï¾í¾Çï¾Êí¾½ï¾Àí¾³ï¾¶í¾©ï¾¬í¾í¾ï¾­ï¾°í¾¡ï¾¤í¾ï¾í¾ï¾í¾í¾ï¾øí¾ùï¾Øí¾Ùï¾Äí¾Åï¾¬í¾­ï¾í¾ï¾í¾ï¾üí¾ýï¾øí¾ùï¾Üí¾Ýï¾Æí¾Çï¾ºí¾»ï¾°í¾±ï¾®í¾¯ï¾§ù©Äü§Äô§Äõ©Äë©Äî§Äö§Ä÷©Äé©Äì§Ä»©Ä¾§Äæ§Äç©Äã©Äæ§Ä §Ä¡©ÄÓ©ÄÖ§ÄÐ§ÄÑ©ÄÎ§ÄÏ©ÄÌ§ÄÍ©Äï©Äò§Äµ©Ä¸§Ä«©Ä®§Ä¡©Ä¤§Ä©Ä§Äò§Äó©Ä©Ä§Ä©Ä§Äû©Äþ§Äõ©Äø§Äî§Äï©Äæ§Äç©ÄÆ§ÄÇ©Ä²§Ä³©Ä§Ä©Ä§Ä©Äô§Äõ©Äê§Äë©Äæ§Äç©ÄÊ§ÄË©Ä´§Äµ©Ä¨§Ä©©Ä§Ä©Ä§Ä©Ä§çãÉêáÉâáÉããÉÙãÉÜáÉäáÉåãÉ×ãÉÚáÉ©ãÉ¬áÉÔáÉÕãÉÑãÉÔáÉáÉãÉÁãÉÄáÉ¾áÉ¿ãÉ¼áÉ½ãÉºáÉ»ãÉÝãÉàáÉ£ãÉ¦áÉãÉáÉãÉáÉãÉáÉàáÉáãÉãÉáÉýãÉáÉéãÉìáÉããÉæáÉÜáÉÝãÉÔáÉÕãÉ´áÉµãÉ áÉ¡ãÉáÉãÉöáÉ÷ãÉâáÉããÉØáÉÙãÉÔáÉÕãÉ¸áÉ¹ãÉ¢áÉ£ãÉáÉãÉáÉãÉáÉãÉ§ÕÏØÏÐÏÑÏÇÏÊÏÒÏÓÏÅÏÈÏÏÏÂÏÃÏ¿ÏÂÏüÏýÏ¯Ï²Ï¬Ï­ÏªÏ«Ï¨Ï©ÏËÏÎÏÏÏÏÏýÏÏóÏöÏÎÏÏÏ÷ÏúÏëÏîÏ×ÏÚÏÑÏÔÏÊÏËÏÂÏÃÏ¢Ï£ÏÏÏöÏ÷ÏäÏåÏÐÏÑÏÆÏÇÏÂÏÃÏ¦Ï§ÏÏÏÏÏúÏûÏøÏùÏ§Ã×ÔÆÕÔ¾ÕÔ¿×Ôµ×Ô¸ÕÔÀÕÔÁ×Ô³×Ô¶ÕÔ×ÔÕÔ°ÕÔ±×Ô­×Ô°ÕÔêÕÔë×Ô×Ô ÕÔÕÔ×ÔÕÔ×ÔÕÔ×Ô¹×Ô¼ÕÔÿ×ÔÕÔõ×ÔøÕÔë×ÔîÕÔá×ÔäÕÔ¼ÕÔ½×Ôå×ÔèÕÔÙ×ÔÜÕÔÅ×ÔÈÕÔ¿×ÔÂÕÔ¸ÕÔ¹×Ô°ÕÔ±×ÔÕÔ×ÔüÕÔý×ÔäÕÔå×ÔÒÕÔÓ×Ô¾ÕÔ¿×Ô´ÕÔµ×Ô°ÕÔ±×ÔÕÔ×ÔþÕÔÿ×ÔòÕÔó×ÔèÕÔé×ÔæÕÔç×Ô§±Ú´Ú¬Ú­Ú£Ú¦Ú®Ú¯Ú¡Ú¤ÚóÚöÚÚÚÚÚØÚÙÚÚÚÚÚÚÚÚÚ§ÚªÚíÚðÚãÚæÚÙÚÜÚÏÚÒÚªÚ«ÚÓÚÖÚÇÚÊÚ³Ú¶Ú­Ú°Ú¦Ú§ÚÚÚþÚÿÚêÚëÚÒÚÓÚÀÚÁÚ¬Ú­Ú¢Ú£ÚÚÚÚÚìÚíÚàÚáÚÖÚ×ÚÔÚÕÚ§Ëß¢ÉßÉßËßËßÉßÉßËßËßÉßáËßäÉßÉßËßËßÉßÆÉßÇËßùËßüÉßöÉß÷ËßôÉßõËßòÉßóËßËßÉßÛËßÞÉßÑËßÔÉßÇËßÊÉß½ËßÀÉßÉßËßÁËßÄÉßµËß¸Éß¡Ëß¤ÉßËßÉßÉßËßÉßËßìÉßíËßØÉßÙËßÀÉßÁËß®Éß¯ËßÉßËßÉßËßÉßËßðÉßñËßÚÉßÛËßÎÉßÏËßÄÉßÅËßÂÉßÃËß§Ü» Ü¹Ü¹Ü»Ü»Ü¹Ü¹Ü»Ü»Ü¹ßÜ»âÜ¹Ü¹Ü»Ü»Ü¹ÄÜ¹ÅÜ»÷Û»úÛ¹ôÛ¹õÛ»òÛ¹óÛ»ðÛ¹ñÛ»Ý»Ý¹ÙÛ»ÜÛ¹ÏÛ»ÒÛ¹ÅÝ»ÈÝ¹»Ü»¾Ü¹Ý¹Ý»¿Û»ÂÛ¹³Û»¶Û¹Û»¢Û¹Û»Û¹Û¹Û»Û¹Û»êÚ¹ëÚ»ÖÚ¹×Ú»¾Ú¹¿Ú»¬Ú¹­Ú»Ú¹Ú»Ú¹Ú»Ú¹Ú»îÙ¹ïÙ»ØÙ¹ÙÙ»ÌÙ¹ÍÙ»ÂÙ¹ÃÙ»ÀÙ¹ÁÙ»§Ùõ
+Ùó
+Ùó
+Ùõ
+ýØõ
+Ùó
+Ùó
+Ùõ
+ûØõ
+þØó
+ÍÙõ
+ÐÙó
+øØó
+ùØõ
+õØõ
+øØó
+²Ùó
+³Ùõ
+åØõ
+èØó
+âØó
+ãØõ
+àØó
+áØõ
+ÞØó
+ßØõ
+Úõ
+Úó
+ÇØõ
+ÊØó
+½Øõ
+ÀØó
+³Úõ
+¶Úó
+©Ùõ
+¬Ùó
+Úó
+Úõ
+­Øõ
+°Øó
+¡Øõ
+¤Øó
+Øõ
+Øó
+Øõ
+Øó
+Øó
+Øõ
+ø×ó
+ù×õ
+Ø×ó
+Ù×õ
+Ä×ó
+Å×õ
+¬×ó
+­×õ
+×ó
+×õ
+×ó
+×õ
+üÖó
+ýÖõ
+øÖó
+ùÖõ
+ÜÖó
+ÝÖõ
+ÆÖó
+ÇÖõ
+ºÖó
+»Öõ
+°Öó
+±Öõ
+®Öó
+¯Öõ
+§ùÕ¯üÕ­ôÕ­õÕ¯ëÕ¯îÕ­öÕ­÷Õ¯éÕ¯ìÕ­»Ö¯¾Ö­æÕ­çÕ¯ãÕ¯æÕ­ Ö­¡Ö¯ÓÕ¯ÖÕ­ÐÕ­ÑÕ¯ÎÕ­ÏÕ¯ÌÕ­ÍÕ¯ïÖ¯òÖ­µÕ¯¸Õ­«Õ¯®Õ­¡×¯¤×­Ö¯Ö­òÖ­óÖ¯Õ¯Õ­Õ¯Õ­ûÔ¯þÔ­õÔ¯øÔ­îÔ­ïÔ¯æÔ­çÔ¯ÆÔ­ÇÔ¯²Ô­³Ô¯Ô­Ô¯Ô­Ô¯ôÓ­õÓ¯êÓ­ëÓ¯æÓ­çÓ¯ÊÓ­ËÓ¯´Ó­µÓ¯¨Ó­©Ó¯Ó­Ó¯Ó­Ó¯§çÒéêÒçâÒçãÒéÙÒéÜÒçäÒçåÒé×ÒéÚÒç©Óé¬ÓçÔÒçÕÒéÑÒéÔÒçÓçÓéÁÒéÄÒç¾Òç¿Òé¼Òç½ÒéºÒç»ÒéÝÓéàÓç£Òé¦ÒçÒéÒçÔéÔçÓéÓçàÓçáÓéÒéÒçýÑéÒçéÑéìÑçãÑéæÑçÜÑçÝÑéÔÑçÕÑé´ÑçµÑé Ñç¡ÑéÑçÑéöÐç÷ÐéâÐçãÐéØÐçÙÐéÔÐçÕÐé¸Ðç¹Ðé¢Ðç£ÐéÐçÐéÐçÐéÐçÐé§ÕÏ£ØÏ¡ÐÏ¡ÑÏ£ÇÏ£ÊÏ¡ÒÏ¡ÓÏ£ÅÏ£ÈÏ¡Ð£Ð¡ÂÏ¡ÃÏ£¿Ï£ÂÏ¡üÏ¡ýÏ£¯Ï£²Ï¡¬Ï¡­Ï£ªÏ¡«Ï£¨Ï¡©Ï£ËÐ£ÎÐ¡Ï£Ï¡Ï£Ï¡ýÐ£Ñ¡óÏ£öÏ¡ÎÐ¡ÏÐ£÷Î£úÎ¡ëÎ£îÎ¡×Î£ÚÎ¡ÑÎ£ÔÎ¡ÊÎ¡ËÎ£ÂÎ¡ÃÎ£¢Î¡£Î£Î¡Î£öÍ¡÷Í£äÍ¡åÍ£ÐÍ¡ÑÍ£ÆÍ¡ÇÍ£ÂÍ¡ÃÍ£¦Í¡§Í£Í¡Í£Í¡Í£úÌ¡ûÌ£øÌ¡ùÌ£§ÃÌÝ ÆÌÛ ¾ÌÛ ¿ÌÝ µÌÝ ¸ÌÛ ÀÌÛ ÁÌÝ ³ÌÝ ¶ÌÛ ÍÝ ÍÛ °ÌÛ ±ÌÝ ­ÌÝ °ÌÛ êÌÛ ëÌÝ ÌÝ  ÌÛ ÌÛ ÌÝ ÌÛ ÌÝ ÌÛ ÌÝ ¹ÍÝ ¼ÍÛ ÿËÝ ÌÛ õËÝ øËÛ ëÍÝ îÍÛ áÌÝ äÌÛ ¼ÍÛ ½ÍÝ åËÝ èËÛ ÙËÝ ÜËÛ ÅËÝ ÈËÛ ¿ËÝ ÂËÛ ¸ËÛ ¹ËÝ °ËÛ ±ËÝ ËÛ ËÝ üÊÛ ýÊÝ äÊÛ åÊÝ ÒÊÛ ÓÊÝ ¾ÊÛ ¿ÊÝ ´ÊÛ µÊÝ °ÊÛ ±ÊÝ ÊÛ ÊÝ þÉÛ ÿÉÝ òÉÛ óÉÝ èÉÛ éÉÝ æÉÛ çÉÝ §±É&´É&¬É&­É&£É&¦É&®É&¯É&¡É&¤É&óÉ&öÉ&É&É&É&É&ØÉ&ÙÉ&É&É&É&É&É&É&É&É&§Ê&ªÊ&íÈ&ðÈ&ãÈ&æÈ&ÙÊ&ÜÊ&ÏÉ&ÒÉ&ªÊ&«Ê&ÓÈ&ÖÈ&ÇÈ&ÊÈ&³È&¶È&­È&°È&¦È&§È&È&È&þÇ&ÿÇ&êÇ&ëÇ&ÒÇ&ÓÇ&ÀÇ&ÁÇ&¬Ç&­Ç&¢Ç&£Ç&Ç&Ç&Ç&Ç&ìÆ&íÆ&àÆ&áÆ&ÖÆ&×Æ&ÔÆ&ÕÆ&§ÆÑ+¢ÆÏ+ÆÏ+ÆÑ+ÆÑ+ÆÏ+ÆÏ+ÆÑ+ÆÑ+ÆÏ+áÆÑ+äÆÏ+ÆÏ+ÆÑ+ÆÑ+ÆÏ+ÆÆÏ+ÇÆÑ+ùÅÑ+üÅÏ+öÅÏ+÷ÅÑ+ôÅÏ+õÅÑ+òÅÏ+óÅÑ+ÇÑ+ÇÏ+ÛÅÑ+ÞÅÏ+ÑÅÑ+ÔÅÏ+ÇÇÑ+ÊÇÏ+½ÆÑ+ÀÆÏ+ÇÏ+ÇÑ+ÁÅÑ+ÄÅÏ+µÅÑ+¸ÅÏ+¡ÅÑ+¤ÅÏ+ÅÑ+ÅÏ+ÅÏ+ÅÑ+ÅÏ+ÅÑ+ìÄÏ+íÄÑ+ØÄÏ+ÙÄÑ+ÀÄÏ+ÁÄÑ+®ÄÏ+¯ÄÑ+ÄÏ+ÄÑ+ÄÏ+ÄÑ+ÄÏ+ÄÑ+ðÃÏ+ñÃÑ+ÚÃÏ+ÛÃÑ+ÎÃÏ+ÏÃÑ+ÄÃÏ+ÅÃÑ+ÂÃÏ+ÃÃÑ+§Ã1Ã1Ã1Ã1ÿÂ1Ã1Ã1Ã1ýÂ1Ã1ÏÃ1ÒÃ1úÂ1ûÂ1÷Â1úÂ1´Ã1µÃ1çÂ1êÂ1äÂ1åÂ1âÂ1ãÂ1àÂ1áÂ1Ä1Ä1ÉÂ1ÌÂ1¿Â1ÂÂ1µÄ1¸Ä1«Ã1®Ã1Ä1Ä1¯Â1²Â1£Â1¦Â1Â1Â1Â1Â1Â1Â1úÁ1ûÁ1ÚÁ1ÛÁ1ÆÁ1ÇÁ1®Á1¯Á1Á1Á1Á1Á1þÀ1ÿÀ1úÀ1ûÀ1ÞÀ1ßÀ1ÈÀ1ÉÀ1¼À1½À1²À1³À1°À1±À1§û¿Å6þ¿Ã6ö¿Ã6÷¿Å6í¿Å6ð¿Ã6ø¿Ã6ù¿Å6ë¿Å6î¿Ã6½ÀÅ6ÀÀÃ6è¿Ã6é¿Å6å¿Å6è¿Ã6¢ÀÃ6£ÀÅ6Õ¿Å6Ø¿Ã6Ò¿Ã6Ó¿Å6Ð¿Ã6Ñ¿Å6Î¿Ã6Ï¿Å6ñÀÅ6ôÀÃ6·¿Å6º¿Ã6­¿Å6°¿Ã6£ÁÅ6¦ÁÃ6ÀÅ6ÀÃ6ôÀÃ6õÀÅ6¿Å6 ¿Ã6¿Å6¿Ã6ý¾Å6¿Ã6÷¾Å6ú¾Ã6ð¾Ã6ñ¾Å6è¾Ã6é¾Å6È¾Ã6É¾Å6´¾Ã6µ¾Å6¾Ã6¾Å6¾Ã6¾Å6ö½Ã6÷½Å6ì½Ã6í½Å6è½Ã6é½Å6Ì½Ã6Í½Å6¶½Ã6·½Å6ª½Ã6«½Å6 ½Ã6¡½Å6½Ã6½Å6§é¼ÿ;ì¼ý;ä¼ý;å¼ÿ;Û¼ÿ;Þ¼ý;æ¼ý;ç¼ÿ;Ù¼ÿ;Ü¼ý;«½ÿ;®½ý;Ö¼ý;×¼ÿ;Ó¼ÿ;Ö¼ý;½ý;½ÿ;Ã¼ÿ;Æ¼ý;À¼ý;Á¼ÿ;¾¼ý;¿¼ÿ;¼¼ý;½¼ÿ;ß½ÿ;â½ý;¥¼ÿ;¨¼ý;¼ÿ;¼ý;¾ÿ;¾ý;½ÿ;½ý;â½ý;ã½ÿ;¼ÿ;¼ý;ÿ»ÿ;¼ý;ë»ÿ;î»ý;å»ÿ;è»ý;Þ»ý;ß»ÿ;Ö»ý;×»ÿ;¶»ý;·»ÿ;¢»ý;£»ÿ;»ý;»ÿ;øºý;ùºÿ;äºý;åºÿ;Úºý;Ûºÿ;Öºý;×ºÿ;ººý;»ºÿ;¤ºý;¥ºÿ;ºý;ºÿ;ºý;ºÿ;ºý;ºÿ;§×¹¹AÚ¹·AÒ¹·AÓ¹¹AÉ¹¹AÌ¹·AÔ¹·AÕ¹¹AÇ¹¹AÊ¹·Aº¹Aº·AÄ¹·AÅ¹¹AÁ¹¹AÄ¹·Aþ¹·Aÿ¹¹A±¹¹A´¹·A®¹·A¯¹¹A¬¹·A­¹¹Aª¹·A«¹¹AÍº¹AÐº·A¹¹A¹·A¹¹A¹·Aÿº¹A»·Aõ¹¹Aø¹·AÐº·AÑº¹Aù¸¹Aü¸·Aí¸¹Að¸·AÙ¸¹AÜ¸·AÓ¸¹AÖ¸·AÌ¸·AÍ¸¹AÄ¸·AÅ¸¹A¤¸·A¥¸¹A¸·A¸¹Aø··Aù·¹Aæ··Aç·¹AÒ··AÓ·¹AÈ··AÉ·¹AÄ··AÅ·¹A¨··A©·¹A··A·¹A··A·¹Aü¶·Aý¶¹Aú¶·Aû¶¹A§Å¶óFÈ¶ñFÀ¶ñFÁ¶óF·¶óFº¶ñFÂ¶ñFÃ¶óFµ¶óF¸¶ñF·óF·ñF²¶ñF³¶óF¯¶óF²¶ñFì¶ñFí¶óF¶óF¢¶ñF¶ñF¶óF¶ñF¶óF¶ñF¶óF»·óF¾·ñF¶óF¶ñF÷µóFúµñFí·óFð·ñFã¶óFæ¶ñF¾·ñF¿·óFçµóFêµñFÛµóFÞµñFÇµóFÊµñFÁµóFÄµñFºµñF»µóF²µñF³µóFµñFµóFþ´ñFÿ´óFæ´ñFç´óFÔ´ñFÕ´óFÀ´ñFÁ´óF¶´ñF·´óF²´ñF³´óF´ñF´óF´ñF´óFô³ñFõ³óFê³ñFë³óFè³ñFé³óF§³³­L¶³«L®³«L¯³­L¥³­L¨³«L°³«L±³­L£³­L¦³«Lõ³­Lø³«L ³«L¡³­L³­L ³«LÚ³«LÛ³­L³­L³«L³«L³­L³«L³­L³«L³­L©´­L¬´«Lï²­Lò²«Lå²­Lè²«LÛ´­LÞ´«LÑ³­LÔ³«L¬´«L­´­LÕ²­LØ²«LÉ²­LÌ²«Lµ²­L¸²«L¯²­L²²«L¨²«L©²­L ²«L¡²­L²«L²­Lì±«Lí±­LÔ±«LÕ±­LÂ±«LÃ±­L®±«L¯±­L¤±«L¥±­L ±«L¡±­L±«L±­Lî°«Lï°­Lâ°«Lã°­LØ°«LÙ°­LÖ°«L×°­L§¡°çQ¤°åQ°åQ°çQ°çQ°åQ°åQ°çQ°çQ°åQã°çQæ°åQ°åQ°çQ°çQ°åQÈ°åQÉ°çQû¯çQþ¯åQø¯åQù¯çQö¯åQ÷¯çQô¯åQõ¯çQ±çQ±åQÝ¯çQà¯åQÓ¯çQÖ¯åQÉ±çQÌ±åQ¿°çQÂ°åQ±åQ±çQÃ¯çQÆ¯åQ·¯çQº¯åQ£¯çQ¦¯åQ¯çQ ¯åQ¯åQ¯çQ¯åQ¯çQî®åQï®çQÚ®åQÛ®çQÂ®åQÃ®çQ°®åQ±®çQ®åQ®çQ®åQ®çQ®åQ®çQò­åQó­çQÜ­åQÝ­çQÐ­åQÑ­çQÆ­åQÇ­çQÄ­åQÅ­çQ§­¡W­W­W­¡W­¡W­W­W­¡Wÿ¬¡W­WÑ­¡WÔ­Wü¬Wý¬¡Wù¬¡Wü¬W¶­W·­¡Wé¬¡Wì¬Wæ¬Wç¬¡Wä¬Wå¬¡Wâ¬Wã¬¡W®¡W®WË¬¡WÎ¬WÁ¬¡WÄ¬W·®¡Wº®W­­¡W°­W®W®¡W±¬¡W´¬W¥¬¡W¨¬W¬¡W¬W¬¡W¬W¬W¬¡Wü«Wý«¡WÜ«WÝ«¡WÈ«WÉ«¡W°«W±«¡W«W«¡W«W«¡W«W«¡WüªWýª¡WàªWáª¡WÊªWËª¡W¾ªW¿ª¡W´ªWµª¡W²ªW³ª¡W§ý©Û\ªÙ\ø©Ù\ù©Û\ï©Û\ò©Ù\ú©Ù\û©Û\í©Û\ð©Ù\¿ªÛ\ÂªÙ\ê©Ù\ë©Û\ç©Û\ê©Ù\¤ªÙ\¥ªÛ\×©Û\Ú©Ù\Ô©Ù\Õ©Û\Ò©Ù\Ó©Û\Ð©Ù\Ñ©Û\óªÛ\öªÙ\¹©Û\¼©Ù\¯©Û\²©Ù\¥«Û\¨«Ù\ªÛ\ªÙ\öªÙ\÷ªÛ\©Û\¢©Ù\©Û\©Ù\ÿ¨Û\©Ù\ù¨Û\ü¨Ù\ò¨Ù\ó¨Û\ê¨Ù\ë¨Û\Ê¨Ù\Ë¨Û\¶¨Ù\·¨Û\¨Ù\¨Û\¨Ù\¨Û\ø§Ù\ù§Û\î§Ù\ï§Û\ê§Ù\ë§Û\Î§Ù\Ï§Û\¸§Ù\¹§Û\¬§Ù\­§Û\¢§Ù\£§Û\ §Ù\¡§Û\§ë¦bî¦bæ¦bç¦bÝ¦bà¦bè¦bé¦bÛ¦bÞ¦b­§b°§bØ¦bÙ¦bÕ¦bØ¦b§b§bÅ¦bÈ¦bÂ¦bÃ¦bÀ¦bÁ¦b¾¦b¿¦bá§bä§b§¦bª¦b¦b ¦b¨b¨b§b§bä§bå§b¦b¦b¦b¦bí¥bð¥bç¥bê¥bà¥bá¥bØ¥bÙ¥b¸¥b¹¥b¤¥b¥¥b¥b¥bú¤bû¤bæ¤bç¤bÜ¤bÝ¤bØ¤bÙ¤b¼¤b½¤b¦¤b§¤b¤b¤b¤b¤b¤b¤b§Ù£ÏgÜ£ÍgÔ£ÍgÕ£ÏgË£ÏgÎ£ÍgÖ£Íg×£ÏgÉ£ÏgÌ£Íg¤Ïg¤ÍgÆ£ÍgÇ£ÏgÃ£ÏgÆ£Íg¤Íg¤Ïg³£Ïg¶£Íg°£Íg±£Ïg®£Íg¯£Ïg¬£Íg­£ÏgÏ¤ÏgÒ¤Íg£Ïg£Íg£Ïg£Íg¥Ïg¥Íg÷£Ïgú£ÍgÒ¤ÍgÓ¤Ïgû¢Ïgþ¢Ígï¢Ïgò¢ÍgÛ¢ÏgÞ¢ÍgÕ¢ÏgØ¢ÍgÎ¢ÍgÏ¢ÏgÆ¢ÍgÇ¢Ïg¦¢Íg§¢Ïg¢Íg¢Ïgú¡Ígû¡Ïgè¡Ígé¡ÏgÔ¡ÍgÕ¡ÏgÊ¡ÍgË¡ÏgÆ¡ÍgÇ¡Ïgª¡Íg«¡Ïg¡Íg¡Ïg¡Íg¡Ïgþ Ígÿ Ïgü Ígý Ïg§Ç mÊ mÂ mÃ m¹ m¼ mÄ mÅ m· mº m¡m¡m´ mµ m± m´ mî mï m¡ m¤ m m m m m m m½¡mÀ¡m m mùmümï¡mò¡må mè mÀ¡mÁ¡mémìmÝmàmÉmÌmÃmÆm¼m½m´mµmmmmmèmémÖm×mÂmÃm¸m¹m´mµmmmmmöm÷mìmímêmëm§µÃr¸Ár°Ár±Ãr§ÃrªÁr²Ár³Ãr¥Ãr¨Ár÷ÃrúÁr¢Ár£ÃrÃr¢ÁrÜÁrÝÃrÃrÁrÁrÃrÁrÃrÁrÃr«Ãr®ÁrñÃrôÁrçÃrêÁrÝÃràÁrÓÃrÖÁr®Ár¯Ãr×ÃrÚÁrËÃrÎÁr·ÃrºÁr±Ãr´ÁrªÁr«Ãr¢Ár£ÃrÁrÃrîÁrïÃrÖÁr×ÃrÄÁrÅÃr°Ár±Ãr¦Ár§Ãr¢Ár£ÃrÁrÃrðÁrñÃräÁråÃrÚÁrÛÃrØÁrÙÃr§£ýw¦ûwûwýwýwûw ûw¡ýwýwûwåýwèûwûwýwýwûwÊûwËýwýýwûwúûwûýwøûwùýwöûw÷ýwýwûwßýwâûwÕýwØûwËýwÎûwÁýwÄûwûwýwÅýwÈûw¹ýw¼ûw¥ýw¨ûwýw¢ûwûwýwûwýwðûwñýwÜûwÝýwÄûwÅýw²ûw³ýwûwýwûwýwûwýwôûwõýwÞûwßýwÒûwÓýwÈûwÉýwÆûwÇýw§·}µ}µ}·}·}µ}µ}·}·}µ}Ó·}Öµ}þµ}ÿ·}û·}þµ}¸µ}¹·}ë·}îµ}èµ}é·}æµ}ç·}äµ}å·}·}µ}Í·}Ðµ}Ã·}Æµ}¹·}¼µ}¯·}²µ}µ}·}³·}¶µ}§·}ªµ}·}µ}·}µ}µ}·}þµ}ÿ·}Þµ}ß·}Êµ}Ë·}²µ}³·} µ}¡·}µ}·}µ}·}þµ}ÿ·}âµ}ã·}Ìµ}Í·}Àµ}Á·}¶µ}··}´µ}µ·}§ÿñïúïûñññôïüïýñïñòïÁñÄïìïíñéñìï¦ï§ñÙñÜïÖï×ñÔïÕñÒïÓñõñøï»ñ¾ï±ñ´ï§ñªïñ ïøïùñ¡ñ¤ïñïñïûñþïôïõñìïíñÌïÍñ¸ï¹ñ ï¡ñïñúïûñðïññìïíñÐïÑñºï»ñ®ï¯ñ¤ï¥ñ¢ï£ñ§í«ð©è©é«ß«â©ê©ë«Ý«à©¯«²©Ú©Û«×«Ú©©«Ç«Ê©Ä©Å«Â©Ã«À©Á«ã«æ©©«¬©«¢©«©«©æ©ç««©«©ï«ò©é«ì©â©ã«Ú©Û«º©»«¦©§«©«ü©ý«è©é«Þ©ß«Ú©Û«¾©¿«¨©©«©«©«©«§ÛåÞãÖã×åÍåÐãØãÙåËåÎãå ãÈãÉåÅåÈããåµå¸ã²ã³å°ã±å®ã¯åÑåÔãåãåãåãùåüãÔãÕåýåãñåôãÝåàã×åÚãÐãÑåÈãÉå¨ã©åãåüãýåêãëåÖã×åÌãÍåÈãÉå¬ã­åãåãåãåþãÿå§ÉÌÄÅ»¾ÆÇ¹¼¶·³¶ðñ£¦ ¡¿ÂûþñôçêÂÃëîßâËÎÅÈ¾¿¶·êëØÙÄÅº»¶·øùîïìí§·Ùº×²×³Ù©Ù¬×´×µÙ§Ùª×ùÙü×¤×¥Ù¡Ù¤×Þ×ßÙÙ××Ù×Ù×Ù­Ù°×óÙö×éÙì×ßÙâ×ÕÙØ×°×±ÙÙÙÜ×ÍÙÐ×¹Ù¼×³Ù¶×¬×­Ù¤×¥Ù×Ùð×ñÙØ×ÙÙÆ×ÇÙ²×³Ù¨×©Ù¤×¥Ù×Ùò×óÙæ×çÙÜ×ÝÙÚ×ÛÙ§¥¨ ¡¢£çêÌÍÿüýúûøùáä×ÚÍÐÃÆÇÊ»¾§ª¡¤òóÞßÆÇ´µ ¡ö÷àáÔÕÊËÈÉ§Í£Ë£Ë£Í£Í£Ë£Ë£Í£Í£Ë£ÕÍ£ØË£Ë£Í£ýÍ£Ë£ºË£»Í£íÍ£ðË£êË£ëÍ£èË£éÍ£æË£çÍ£Í£Ë£ÏÍ£ÒË£ÅÍ£ÈË£»Í£¾Ë£±Í£´Ë£Ë£Í£µÍ£¸Ë£©Í£¬Ë£Í£Ë£Í£Ë£Ë£Í£Ë£Í£àÿË£áÿÍ£ÌÿË£ÍÿÍ£´ÿË£µÿÍ£¢ÿË££ÿÍ£ÿË£ÿÍ£ÿË£ÿÍ£ÿË£ÿÍ£äþË£åþÍ£ÎþË£ÏþÍ£ÂþË£ÃþÍ£¸þË£¹þÍ£¶þË£·þÍ£§þ©þ©üý©ýý©óý©öý©þý©ÿý©ñý©ôý©Ãþ©Æþ©îý©ïý©ëý©îý©¨þ©©þ©Ûý©Þý©Øý©Ùý©Öý©×ý©Ôý©Õý©÷þ©úþ©½ý©Àý©³ý©¶ý©©ÿ©¬ÿ©þ©¢þ©úþ©ûþ©£ý©¦ý©ý©ý©ý©ý©ýü©ý©öü©÷ü©îü©ïü©Îü©Ïü©ºü©»ü©¢ü©£ü©ü©ü©üû©ýû©òû©óû©îû©ïû©Òû©Óû©¼û©½û©°û©±û©¦û©§û©¤û©¥û©§ïúÁ®òú¿®êú¿®ëúÁ®áúÁ®äú¿®ìú¿®íúÁ®ßúÁ®âú¿®±ûÁ®´û¿®Üú¿®ÝúÁ®ÙúÁ®Üú¿®û¿®ûÁ®ÉúÁ®Ìú¿®Æú¿®ÇúÁ®Äú¿®ÅúÁ®Âú¿®ÃúÁ®åûÁ®èû¿®«úÁ®®ú¿®¡úÁ®¤ú¿®üÁ®ü¿®ûÁ®û¿®èû¿®éûÁ®úÁ®ú¿®úÁ®ú¿®ñùÁ®ôù¿®ëùÁ®îù¿®äù¿®åùÁ®Üù¿®ÝùÁ®¼ù¿®½ùÁ®¨ù¿®©ùÁ®ù¿®ùÁ®þø¿®ÿøÁ®êø¿®ëøÁ®àø¿®áøÁ®Üø¿®ÝøÁ®Àø¿®ÁøÁ®ªø¿®«øÁ®ø¿®øÁ®ø¿®øÁ®ø¿®øÁ®§Ý÷û³à÷ù³Ø÷ù³Ù÷û³Ï÷û³Ò÷ù³Ú÷ù³Û÷û³Í÷û³Ð÷ù³øû³¢øù³Ê÷ù³Ë÷û³Ç÷û³Ê÷ù³øù³øû³·÷û³º÷ù³´÷ù³µ÷û³²÷ù³³÷û³°÷ù³±÷û³Óøû³Öøù³÷û³÷ù³÷û³÷ù³ùû³ùù³û÷û³þ÷ù³Öøù³×øû³ÿöû³÷ù³óöû³ööù³ßöû³âöù³Ùöû³Üöù³Òöù³Óöû³Êöù³Ëöû³ªöù³«öû³öù³öû³þõù³ÿõû³ìõù³íõû³Øõù³Ùõû³Îõù³Ïõû³Êõù³Ëõû³®õù³¯õû³õù³õû³õù³õû³õù³õû³õù³õû³§Ëôµ¹Îô³¹Æô³¹Çôµ¹½ôµ¹Àô³¹Èô³¹Éôµ¹»ôµ¹¾ô³¹õµ¹õ³¹¸ô³¹¹ôµ¹µôµ¹¸ô³¹òô³¹óôµ¹¥ôµ¹¨ô³¹¢ô³¹£ôµ¹ ô³¹¡ôµ¹ô³¹ôµ¹Áõµ¹Äõ³¹ôµ¹ô³¹ýóµ¹ô³¹óõµ¹öõ³¹éôµ¹ìô³¹Äõ³¹Åõµ¹íóµ¹ðó³¹áóµ¹äó³¹Íóµ¹Ðó³¹Çóµ¹Êó³¹Àó³¹Áóµ¹¸ó³¹¹óµ¹ó³¹óµ¹ó³¹óµ¹ìò³¹íòµ¹Úò³¹Ûòµ¹Æò³¹Çòµ¹¼ò³¹½òµ¹¸ò³¹¹òµ¹ò³¹òµ¹ò³¹òµ¹úñ³¹ûñµ¹ðñ³¹ññµ¹îñ³¹ïñµ¹§¹ñï¾¼ñí¾´ñí¾µñï¾«ñï¾®ñí¾¶ñí¾·ñï¾©ñï¾¬ñí¾ûñï¾þñí¾¦ñí¾§ñï¾£ñï¾¦ñí¾àñí¾áñï¾ñï¾ñí¾ñí¾ñï¾ñí¾ñï¾ñí¾ñï¾¯òï¾²òí¾õðï¾øðí¾ëðï¾îðí¾áòï¾äòí¾×ñï¾Úñí¾²òí¾³òï¾Ûðï¾Þðí¾Ïðï¾Òðí¾»ðï¾¾ðí¾µðï¾¸ðí¾®ðí¾¯ðï¾¦ðí¾§ðï¾ðí¾ðï¾òïí¾óïï¾Úïí¾Ûïï¾Èïí¾Éïï¾´ïí¾µïï¾ªïí¾«ïï¾¦ïí¾§ïï¾ïí¾ïï¾ôîí¾õîï¾èîí¾éîï¾Þîí¾ßîï¾Üîí¾Ýîï¾§§î©Äªî§Ä¢î§Ä£î©Äî©Äî§Ä¤î§Ä¥î©Äî©Äî§Äéî©Äìî§Äî§Äî©Äî©Äî§ÄÎî§ÄÏî©Äî©Äî§Äþí§Äÿí©Äüí§Äýí©Äúí§Äûí©Äï©Ä ï§Äãí©Äæí§ÄÙí©ÄÜí§ÄÏï©ÄÒï§ÄÅî©ÄÈî§Ä ï§Ä¡ï©ÄÉí©ÄÌí§Ä½í©ÄÀí§Ä©í©Ä¬í§Ä£í©Ä¦í§Äí§Äí©Äí§Äí©Äôì§Äõì©Äàì§Äáì©ÄÈì§ÄÉì©Ä¶ì§Ä·ì©Ä¢ì§Ä£ì©Äì§Äì©Äì§Äì©Äøë§Äùë©Äâë§Äãë©ÄÖë§Ä×ë©ÄÌë§ÄÍë©ÄÊë§ÄËë©Ä§ëãÉëáÉëáÉëãÉëãÉëáÉëáÉëãÉëãÉëáÉ×ëãÉÚëáÉëáÉëãÉÿêãÉëáÉ¼ëáÉ½ëãÉïêãÉòêáÉìêáÉíêãÉêêáÉëêãÉèêáÉéêãÉìãÉìáÉÑêãÉÔêáÉÇêãÉÊêáÉ½ìãÉÀìáÉ³ëãÉ¶ëáÉìáÉìãÉ·êãÉºêáÉ«êãÉ®êáÉêãÉêáÉêãÉêáÉêáÉêãÉêáÉêãÉâéáÉãéãÉÎéáÉÏéãÉ¶éáÉ·éãÉ¤éáÉ¥éãÉéáÉéãÉéáÉéãÉéáÉéãÉæèáÉçèãÉÐèáÉÑèãÉÄèáÉÅèãÉºèáÉ»èãÉ¸èáÉ¹èãÉ§èÏèÏþçÏÿçÏõçÏøçÏèÏèÏóçÏöçÏÅèÏÈèÏðçÏñçÏíçÏðçÏªèÏ«èÏÝçÏàçÏÚçÏÛçÏØçÏÙçÏÖçÏ×çÏùèÏüèÏ¿çÏÂçÏµçÏ¸çÏ«éÏ®éÏ¡èÏ¤èÏüèÏýèÏ¥çÏ¨çÏçÏçÏçÏçÏÿæÏçÏøæÏùæÏðæÏñæÏÐæÏÑæÏ¼æÏ½æÏ¤æÏ¥æÏæÏæÏþåÏÿåÏôåÏõåÏðåÏñåÏÔåÏÕåÏ¾åÏ¿åÏ²åÏ³åÏ¨åÏ©åÏ¦åÏ§åÏ§ñä×ÔôäÕÔìäÕÔíä×Ôãä×ÔæäÕÔîäÕÔïä×Ôáä×ÔääÕÔ³å×Ô¶åÕÔÞäÕÔßä×ÔÛä×ÔÞäÕÔåÕÔå×ÔËä×ÔÎäÕÔÈäÕÔÉä×ÔÆäÕÔÇä×ÔÄäÕÔÅä×Ôçå×ÔêåÕÔ­ä×Ô°äÕÔ£ä×Ô¦äÕÔæ×ÔæÕÔå×ÔåÕÔêåÕÔëå×Ôä×ÔäÕÔä×ÔäÕÔóã×ÔöãÕÔíã×ÔðãÕÔæãÕÔçã×ÔÞãÕÔßã×Ô¾ãÕÔ¿ã×ÔªãÕÔ«ã×ÔãÕÔã×ÔãÕÔã×ÔìâÕÔíâ×ÔââÕÔãâ×ÔÞâÕÔßâ×ÔÂâÕÔÃâ×Ô¬âÕÔ­â×Ô âÕÔ¡â×ÔâÕÔâ×ÔâÕÔâ×Ô§ßáÚâáÚÚáÚÛáÚÑáÚÔáÚÜáÚÝáÚÏáÚÒáÚ¡âÚ¤âÚÌáÚÍáÚÉáÚÌáÚâÚâÚ¹áÚ¼áÚ¶áÚ·áÚ´áÚµáÚ²áÚ³áÚÕâÚØâÚáÚáÚáÚáÚãÚãÚýáÚâÚØâÚÙâÚáÚáÚõàÚøàÚáàÚäàÚÛàÚÞàÚÔàÚÕàÚÌàÚÍàÚ¬àÚ­àÚàÚàÚàÚàÚîßÚïßÚÚßÚÛßÚÐßÚÑßÚÌßÚÍßÚ°ßÚ±ßÚßÚßÚßÚßÚßÚßÚßÚßÚ§£³»¦³¹³¹³»³»³¹ ³¹¡³»³»³¹å³»è³¹³¹³»³»³¹Ê³¹Ë³»ý²»³¹ú²¹û²»ø²¹ù²»ö²¹÷²»´»´¹ß²»â²¹Õ²»Ø²¹Ë´»Î´¹Á³»Ä³¹´¹´»Å²»È²¹¹²»¼²¹¥²»¨²¹²»¢²¹²¹²»²¹²»ð±¹ñ±»Ü±¹Ý±»Ä±¹Å±»²±¹³±»±¹±»±¹±»±¹±»ô°¹õ°»Þ°¹ß°»Ò°¹Ó°»È°¹É°»Æ°¹Ç°»§°õ
+°ó
+°ó
+°õ
+°õ
+°ó
+°ó
+°õ
+°õ
+°ó
+Ó°õ
+Ö°ó
+þ¯ó
+ÿ¯õ
+û¯õ
+þ¯ó
+¸°ó
+¹°õ
+ë¯õ
+î¯ó
+è¯ó
+é¯õ
+æ¯ó
+ç¯õ
+ä¯ó
+å¯õ
+±õ
+±ó
+Í¯õ
+Ð¯ó
+Ã¯õ
+Æ¯ó
+¹±õ
+¼±ó
+¯°õ
+²°ó
+±ó
+±õ
+³¯õ
+¶¯ó
+§¯õ
+ª¯ó
+¯õ
+¯ó
+¯õ
+¯ó
+¯ó
+¯õ
+þ®ó
+ÿ®õ
+Þ®ó
+ß®õ
+Ê®ó
+Ë®õ
+²®ó
+³®õ
+ ®ó
+¡®õ
+®ó
+®õ
+®ó
+®õ
+þ­ó
+ÿ­õ
+â­ó
+ã­õ
+Ì­ó
+Í­õ
+À­ó
+Á­õ
+¶­ó
+·­õ
+´­ó
+µ­õ
+§ÿ¬¯­­ú¬­û¬¯ñ¬¯ô¬­ü¬­ý¬¯ï¬¯ò¬­Á­¯Ä­­ì¬­í¬¯é¬¯ì¬­¦­­§­¯Ù¬¯Ü¬­Ö¬­×¬¯Ô¬­Õ¬¯Ò¬­Ó¬¯õ­¯ø­­»¬¯¾¬­±¬¯´¬­§®¯ª®­­¯ ­­ø­­ù­¯¡¬¯¤¬­¬¯¬­¬¯¬­û«¯þ«­ô«­õ«¯ì«­í«¯Ì«­Í«¯¸«­¹«¯ «­¡«¯«­«¯úª­ûª¯ðª­ñª¯ìª­íª¯Ðª­Ñª¯ºª­»ª¯®ª­¯ª¯¤ª­¥ª¯¢ª­£ª¯§í©éð©çè©çé©éß©éâ©çê©çë©éÝ©éà©ç¯ªé²ªçÚ©çÛ©é×©éÚ©çªçªéÇ©éÊ©çÄ©çÅ©éÂ©çÃ©éÀ©çÁ©éãªéæªç©©é¬©ç©é¢©ç«é«çªéªçæªççªé©é©ç©é©çï¨éò¨çé¨éì¨çâ¨çã¨éÚ¨çÛ¨éº¨ç»¨é¦¨ç§¨é¨ç¨éü§çý§éè§çé§éÞ§çß§éÚ§çÛ§é¾§ç¿§é¨§ç©§é§ç§é§ç§é§ç§é§Û¦£Þ¦¡Ö¦¡×¦£Í¦£Ð¦¡Ø¦¡Ù¦£Ë¦£Î¦¡§£ §¡È¦¡É¦£Å¦£È¦¡§¡§£µ¦£¸¦¡²¦¡³¦£°¦¡±¦£®¦¡¯¦£Ñ§£Ô§¡¦£¦¡¦£¦¡¨£¨¡ù¦£ü¦¡Ô§¡Õ§£ý¥£¦¡ñ¥£ô¥¡Ý¥£à¥¡×¥£Ú¥¡Ð¥¡Ñ¥£È¥¡É¥£¨¥¡©¥£¥¡¥£ü¤¡ý¤£ê¤¡ë¤£Ö¤¡×¤£Ì¤¡Í¤£È¤¡É¤£¬¤¡­¤£¤¡¤£¤¡¤£¤¡¤£þ£¡ÿ££§É£Ý Ì£Û Ä£Û Å£Ý »£Ý ¾£Û Æ£Û Ç£Ý ¹£Ý ¼£Û ¤Ý ¤Û ¶£Û ·£Ý ³£Ý ¶£Û ð£Û ñ£Ý ££Ý ¦£Û  £Û ¡£Ý £Û £Ý £Û £Ý ¿¤Ý Â¤Û £Ý £Û û¢Ý þ¢Û ñ¤Ý ô¤Û ç£Ý ê£Û Â¤Û Ã¤Ý ë¢Ý î¢Û ß¢Ý â¢Û Ë¢Ý Î¢Û Å¢Ý È¢Û ¾¢Û ¿¢Ý ¶¢Û ·¢Ý ¢Û ¢Ý ¢Û ¢Ý ê¡Û ë¡Ý Ø¡Û Ù¡Ý Ä¡Û Å¡Ý º¡Û »¡Ý ¶¡Û ·¡Ý ¡Û ¡Ý ¡Û ¡Ý ø Û ù Ý î Û ï Ý ì Û í Ý §· &º &² &³ &© &¬ &´ &µ &§ &ª &ù &ü &¤ &¥ &¡ &¤ &Þ &ß & & & & & & & & &­¡&°¡&ó&ö&é&ì&ß¡&â¡&Õ &Ø &°¡&±¡&Ù&Ü&Í&Ð&¹&¼&³&¶&¬&­&¤&¥&&&ð&ñ&Ø&Ù&Æ&Ç&²&³&¨&©&¤&¥&&&ò&ó&æ&ç&Ü&Ý&Ú&Û&§¥Ñ+¨Ï+ Ï+¡Ñ+Ñ+Ï+¢Ï+£Ñ+Ñ+Ï+çÑ+êÏ+Ï+Ñ+Ñ+Ï+ÌÏ+ÍÑ+ÿÑ+Ï+üÏ+ýÑ+úÏ+ûÑ+øÏ+ùÑ+Ñ+Ï+áÑ+äÏ+×Ñ+ÚÏ+ÍÑ+ÐÏ+ÃÑ+ÆÏ+Ï+Ñ+ÇÑ+ÊÏ+»Ñ+¾Ï+§Ñ+ªÏ+¡Ñ+¤Ï+Ï+Ñ+Ï+Ñ+òÏ+óÑ+ÞÏ+ßÑ+ÆÏ+ÇÑ+´Ï+µÑ+ Ï+¡Ñ+Ï+Ñ+Ï+Ñ+öÏ+÷Ñ+àÏ+áÑ+ÔÏ+ÕÑ+ÊÏ+ËÑ+ÈÏ+ÉÑ+§1111111111Õ1Ø111ý11º1»1í1ð1ê1ë1è1é1æ1ç111Ï1Ò1Å1È1»1¾1±1´111µ1¸1©1¬111111111à1á1Ì1Í1´1µ1¢1£1111111ä1å1Î1Ï1Â1Ã1¸1¹1¶1·1§Å6Ã6üÃ6ýÅ6óÅ6öÃ6þÃ6ÿÅ6ñÅ6ôÃ6ÃÅ6ÆÃ6îÃ6ïÅ6ëÅ6îÃ6¨Ã6©Å6ÛÅ6ÞÃ6ØÃ6ÙÅ6ÖÃ6×Å6ÔÃ6ÕÅ6÷Å6úÃ6½Å6ÀÃ6³Å6¶Ã6©Å6¬Ã6Å6¢Ã6úÃ6ûÅ6£Å6¦Ã6Å6Ã6Å6Ã6ýÅ6Ã6öÃ6÷Å6îÃ6ïÅ6ÎÃ6ÏÅ6ºÃ6»Å6¢Ã6£Å6Ã6Å6üÃ6ýÅ6òÃ6óÅ6îÃ6ïÅ6ÒÃ6ÓÅ6¼Ã6½Å6°Ã6±Å6¦Ã6§Å6¤Ã6¥Å6§ïÿ;òý;êý;ëÿ;áÿ;äý;ìý;íÿ;ßÿ;âý;±ÿ;´ý;Üý;Ýÿ;Ùÿ;Üý;ý;ÿ;Éÿ;Ìý;Æý;Çÿ;Äý;Åÿ;Âý;Ãÿ;åÿ;èý;«ÿ;®ý;¡ÿ;¤ý;ÿ;ý;ÿ;ý;èý;éÿ;ÿ;ý;ÿ;ý;ñÿ;ôý;ëÿ;îý;äý;åÿ;Üý;Ýÿ;¼ý;½ÿ;¨ý;©ÿ;ý;ÿ;þý;ÿÿ;êý;ëÿ;àý;áÿ;Üý;Ýÿ;Àý;Áÿ;ªý;«ÿ;ý;ÿ;ý;ÿ;ý;ÿ;§Ý¹Aà·AØ·AÙ¹AÏ¹AÒ·AÚ·AÛ¹AÍ¹AÐ·A¹A¢·AÊ·AË¹AÇ¹AÊ·A·A¹A·¹Aº·A´·Aµ¹A²·A³¹A°·A±¹AÓ¹AÖ·A¹A·A¹A·A¹A·Aû¹Aþ·AÖ·A×¹Aÿ¹A·Aó¹Aö·Aß¹Aâ·AÙ¹AÜ·AÒ·AÓ¹AÊ·AË¹Aª·A«¹A·A¹Aþ·Aÿ¹Aì·Aí¹AØ·AÙ¹AÎ·AÏ¹AÊ·AË¹A®·A¯¹A·A¹A·A¹A·A¹A·A¹A§ËóFÎñFÆñFÇóF½óFÀñFÈñFÉóF»óF¾ñFóFñF¸ñF¹óFµóF¸ñFòñFóóF¥óF¨ñF¢ñF£óF ñF¡óFñFóFÁóFÄñFóFñFýóFñFóóFöñFéóFìñFÄñFÅóFíóFðñFáóFäñFÍóFÐñFÇóFÊñFÀñFÁóF¸ñF¹óFñFóFñFóFìñFíóFÚñFÛóFÆñFÇóF¼ñF½óF¸ñF¹óFñFóFñFóFúñFûóFðñFñóFîñFïóF§¹­L¼«L´«Lµ­L«­L®«L¶«L·­L©­L¬«Lû­Lþ«L¦«L§­L£­L¦«Là«Lá­L­L«L«L­L«L­L«L­L¯­L²«Lõ­Lø«Lë­Lî«Lá­Lä«L×­LÚ«L²«L³­LÛ­LÞ«LÏ­LÒ«L»­L¾«Lµ­L¸«L®«L¯­L¦«L§­L«L­Lò«Ló­LÚ«LÛ­LÈ«LÉ­L´«Lµ­Lª«L«­L¦«L§­L«L­Lô«Lõ­Lè«Lé­LÞ«Lß­LÜ«LÝ­L§§çQªåQ¢åQ£çQçQåQ¤åQ¥çQçQåQéçQìåQåQçQçQåQÎåQÏçQçQåQþåQÿçQüåQýçQúåQûçQçQ åQãçQæåQÙçQÜåQÏçQÒåQÅçQÈåQ åQ¡çQÉçQÌåQ½çQÀåQ©çQ¬åQ£çQ¦åQåQçQåQçQôåQõçQàåQáçQÈåQÉçQ¶åQ·çQ¢åQ£çQåQçQåQçQøåQùçQâåQãçQÖåQ×çQÌåQÍçQÊåQËçQ§¡WWW¡W¡WWW¡W¡WW×¡WÚWW¡Wÿ¡WW¼W½¡Wï¡WòWìWí¡WêWë¡WèWé¡W¡WWÑ¡WÔWÇ¡WÊW½¡WÀW³¡W¶WW¡W·¡WºW«¡W®W¡WW¡WWW¡WW¡WâWã¡WÎWÏ¡W¶W·¡W¤W¥¡WW¡WW¡WW¡WæWç¡WÐWÑ¡WÄWÅ¡WºW»¡W¸W¹¡W§Û\Ù\þÙ\ÿÛ\õÛ\øÙ\Ù\Û\óÛ\öÙ\ÅÛ\ÈÙ\ðÙ\ñÛ\íÛ\ðÙ\ªÙ\«Û\ÝÛ\àÙ\ÚÙ\ÛÛ\ØÙ\ÙÛ\ÖÙ\×Û\ùÛ\üÙ\¿Û\ÂÙ\µÛ\¸Ù\«Û\®Ù\¡Û\¤Ù\üÙ\ýÛ\¥Û\¨Ù\Û\Ù\Û\Ù\ÿÿÛ\Ù\øÿÙ\ùÿÛ\ðÿÙ\ñÿÛ\ÐÿÙ\ÑÿÛ\¼ÿÙ\½ÿÛ\¤ÿÙ\¥ÿÛ\ÿÙ\ÿÛ\þþÙ\ÿþÛ\ôþÙ\õþÛ\ðþÙ\ñþÛ\ÔþÙ\ÕþÛ\¾þÙ\¿þÛ\²þÙ\³þÛ\¨þÙ\©þÛ\¦þÙ\§þÛ\§ñýbôýbìýbíýbãýbæýbîýbïýbáýbäýb³þb¶þbÞýbßýbÛýbÞýbþbþbËýbÎýbÈýbÉýbÆýbÇýbÄýbÅýbçþbêþb­ýb°ýb£ýb¦ýbÿbÿbþbþbêþbëþbýbýbýbýbóüböübíübðübæübçübÞübßüb¾üb¿übªüb«übübübübübìûbíûbâûbãûbÞûbßûbÂûbÃûb¬ûb­ûb ûb¡ûbûbûbûbûb§ßúÏgâúÍgÚúÍgÛúÏgÑúÏgÔúÍgÜúÍgÝúÏgÏúÏgÒúÍg¡ûÏg¤ûÍgÌúÍgÍúÏgÉúÏgÌúÍgûÍgûÏg¹úÏg¼úÍg¶úÍg·úÏg´úÍgµúÏg²úÍg³úÏgÕûÏgØûÍgúÏgúÍgúÏgúÍgüÏgüÍgýúÏgûÍgØûÍgÙûÏgúÏgúÍgõùÏgøùÍgáùÏgäùÍgÛùÏgÞùÍgÔùÍgÕùÏgÌùÍgÍùÏg¬ùÍg­ùÏgùÍgùÏgùÍgùÏgîøÍgïøÏgÚøÍgÛøÏgÐøÍgÑøÏgÌøÍgÍøÏg°øÍg±øÏgøÍgøÏgøÍgøÏgøÍgøÏgøÍgøÏg§Í÷mÐ÷mÈ÷mÉ÷m¿÷mÂ÷mÊ÷mË÷m½÷mÀ÷mømømº÷m»÷m·÷mº÷mô÷mõ÷m§÷mª÷m¤÷m¥÷m¢÷m£÷m ÷m¡÷mÃømÆøm÷m÷mÿöm÷mõømøømë÷mî÷mÆømÇømïömòömãömæömÏömÒömÉömÌömÂömÃömºöm»ömömömömömîõmïõmÜõmÝõmÈõmÉõm¾õm¿õmºõm»õmõmõmõmõmüômýômòômóômðômñôm§»ôÃr¾ôÁr¶ôÁr·ôÃr­ôÃr°ôÁr¸ôÁr¹ôÃr«ôÃr®ôÁrýôÃrõÁr¨ôÁr©ôÃr¥ôÃr¨ôÁrâôÁrãôÃrôÃrôÁrôÁrôÃrôÁrôÃrôÁrôÃr±õÃr´õÁr÷óÃrúóÁríóÃrðóÁrãõÃræõÁrÙôÃrÜôÁr´õÁrµõÃrÝóÃràóÁrÑóÃrÔóÁr½óÃrÀóÁr·óÃrºóÁr°óÁr±óÃr¨óÁr©óÃróÁróÃrôòÁrõòÃrÜòÁrÝòÃrÊòÁrËòÃr¶òÁr·òÃr¬òÁr­òÃr¨òÁr©òÃròÁròÃröñÁr÷ñÃrêñÁrëñÃràñÁráñÃrÞñÁrßñÃr§©ñýw¬ñûw¤ñûw¥ñýwñýwñûw¦ñûw§ñýwñýwñûwëñýwîñûwñûwñýwñýwñûwÐñûwÑñýwñýwñûwñûwñýwþðûwÿðýwüðûwýðýwòýw¢òûwåðýwèðûwÛðýwÞðûwÑòýwÔòûwÇñýwÊñûw¢òûw£òýwËðýwÎðûw¿ðýwÂðûw«ðýw®ðûw¥ðýw¨ðûwðûwðýwðûwðýwöïûw÷ïýwâïûwãïýwÊïûwËïýw¸ïûw¹ïýw¤ïûw¥ïýwïûwïýwïûwïýwúîûwûîýwäîûwåîýwØîûwÙîýwÎîûwÏîýwÌîûwÍîýw§î·}îµ}îµ}î·}î·}îµ}îµ}î·}î·}îµ}Ùî·}Üîµ}îµ}î·}î·}îµ}¾îµ}¿î·}ñí·}ôíµ}îíµ}ïí·}ìíµ}íí·}êíµ}ëí·}ï·}ïµ}Óí·}Öíµ}Éí·}Ìíµ}¿ï·}Âïµ}µî·}¸îµ}ïµ}ï·}¹í·}¼íµ}­í·}°íµ}í·}íµ}í·}íµ}íµ}í·}íµ}í·}äìµ}åì·}Ðìµ}Ñì·}¸ìµ}¹ì·}¦ìµ}§ì·}ìµ}ì·}ìµ}ì·}ìµ}ì·}èëµ}éë·}Òëµ}Óë·}Æëµ}Çë·}¼ëµ}½ë·}ºëµ}»ë·}§ëñëïëïëñ÷êñúêïëïëñõêñøêïÇëñÊëïòêïóêñïêñòêï¬ëï­ëñßêñâêïÜêïÝêñÚêïÛêñØêïÙêñûëñþëïÁêñÄêï·êñºêï­ìñ°ìï£ëñ¦ëïþëïÿëñ§êñªêïêñêïêñêïêñêïúéïûéñòéïóéñÒéïÓéñ¾éï¿éñ¦éï§éñéïéñéïéñöèï÷èñòèïóèñÖèï×èñÀèïÁèñ´èïµèñªèï«èñ¨èï©èñ§óç«öç©îç©ïç«åç«èç©ðç©ñç«ãç«æç©µè«¸è©àç©áç«Ýç«àç©è©è«Íç«Ðç©Êç©Ëç«Èç©Éç«Æç©Çç«éè«ìè©¯ç«²ç©¥ç«¨ç©é«é©è«è©ìè©íè«ç«ç©ç«ç©õæ«øæ©ïæ«òæ©èæ©éæ«àæ©áæ«Àæ©Áæ«¬æ©­æ«æ©æ«æ©æ«îå©ïå«äå©åå«àå©áå«Äå©Åå«®å©¯å«¢å©£å«å©å«å©å«§áäåääãÜäãÝäåÓäåÖäãÞäãßäåÑäåÔäã£åå¦åãÎäãÏäåËäåÎäãåãåå»äå¾äã¸äã¹äå¶äã·äå´äãµäå×ååÚåãäå äãäåäãæåæãÿäååãÚåãÛååäåäã÷ãåúããããåæããÝãåàããÖãã×ãåÎããÏãå®ãã¯ãåãããåãããåðâãñâåÜâãÝâåÒâãÓâåÎâãÏâå²âã³âåâãâåâãâåâãâåâãâå§ÏáÒáÊáËáÁáÄáÌáÍá¿áÂáââ¼á½á¹á¼áöá÷á©á¬á¦á§á¤á¥á¢á£áÅâÈâáááá÷âúâíáðáÈâÉâñàôàåàèàÑàÔàËàÎàÄàÅà¼à½àààààðßñßÞßßßÊßËßÀßÁß¼ß½ß ß¡ßßßþÞÿÞôÞõÞòÞóÞ§½ÞÙÀÞ×¸Þ×¹ÞÙ¯ÞÙ²Þ×ºÞ×»ÞÙ­ÞÙ°Þ×ÿÞÙß×ªÞ×«ÞÙ§ÞÙªÞ×äÞ×åÞÙÞÙÞ×Þ×ÞÙÞ×ÞÙÞ×ÞÙ³ßÙ¶ß×ùÝÙüÝ×ïÝÙòÝ×åßÙèß×ÛÞÙÞÞ×¶ß×·ßÙßÝÙâÝ×ÓÝÙÖÝ×¿ÝÙÂÝ×¹ÝÙ¼Ý×²Ý×³ÝÙªÝ×«ÝÙÝ×ÝÙöÜ×÷ÜÙÞÜ×ßÜÙÌÜ×ÍÜÙ¸Ü×¹ÜÙ®Ü×¯ÜÙªÜ×«ÜÙÜ×ÜÙøÛ×ùÛÙìÛ×íÛÙâÛ×ãÛÙàÛ×áÛÙ§«Û®Û¦Û§ÛÛ Û¨Û©ÛÛÛíÛðÛÛÛÛÛÒÛÓÛÛÛÛÛÛÛþÚÿÚ¡Ü¤ÜçÚêÚÝÚàÚÓÜÖÜÉÛÌÛ¤Ü¥ÜÍÚÐÚÁÚÄÚ­Ú°Ú§ÚªÚ Ú¡ÚÚÚøÙùÙäÙåÙÌÙÍÙºÙ»Ù¦Ù§ÙÙÙÙÙüØýØæØçØÚØÛØÐØÑØÎØÏØ§ØÍ£ØË£ØË£ØÍ£ØÍ£ØË£ØË£ØÍ£ØÍ£ØË£ÛØÍ£ÞØË£ØË£ØÍ£ØÍ£ØË£ÀØË£ÁØÍ£ó×Í£ö×Ë£ð×Ë£ñ×Í£î×Ë£ï×Í£ì×Ë£í×Í£ÙÍ£ÙË£Õ×Í£Ø×Ë£Ë×Í£Î×Ë£ÁÙÍ£ÄÙË£·ØÍ£ºØË£ÙË£ÙÍ£»×Í£¾×Ë£¯×Í£²×Ë£×Í£×Ë£×Í£×Ë£×Ë£×Í£×Ë£×Í£æÖË£çÖÍ£ÒÖË£ÓÖÍ£ºÖË£»ÖÍ£¨ÖË£©ÖÍ£ÖË£ÖÍ£ÖË£ÖÍ£ÖË£ÖÍ£êÕË£ëÕÍ£ÔÕË£ÕÕÍ£ÈÕË£ÉÕÍ£¾ÕË£¿ÕÍ£¼ÕË£½ÕÍ£§Õ©Õ©Õ©Õ©ùÔ©üÔ©Õ©Õ©÷Ô©úÔ©ÉÕ©ÌÕ©ôÔ©õÔ©ñÔ©ôÔ©®Õ©¯Õ©áÔ©äÔ©ÞÔ©ßÔ©ÜÔ©ÝÔ©ÚÔ©ÛÔ©ýÕ©Ö©ÃÔ©ÆÔ©¹Ô©¼Ô©¯Ö©²Ö©¥Õ©¨Õ©Ö©Ö©©Ô©¬Ô©Ô© Ô©Ô©Ô©Ô©Ô©üÓ©ýÓ©ôÓ©õÓ©ÔÓ©ÕÓ©ÀÓ©ÁÓ©¨Ó©©Ó©Ó©Ó©Ó©Ó©øÒ©ùÒ©ôÒ©õÒ©ØÒ©ÙÒ©ÂÒ©ÃÒ©¶Ò©·Ò©¬Ò©­Ò©ªÒ©«Ò©§õÑÁ®øÑ¿®ðÑ¿®ñÑÁ®çÑÁ®êÑ¿®òÑ¿®óÑÁ®åÑÁ®èÑ¿®·ÒÁ®ºÒ¿®âÑ¿®ãÑÁ®ßÑÁ®âÑ¿®Ò¿®ÒÁ®ÏÑÁ®ÒÑ¿®ÌÑ¿®ÍÑÁ®ÊÑ¿®ËÑÁ®ÈÑ¿®ÉÑÁ®ëÒÁ®îÒ¿®±ÑÁ®´Ñ¿®§ÑÁ®ªÑ¿®ÓÁ® Ó¿®ÒÁ®Ò¿®îÒ¿®ïÒÁ®ÑÁ®Ñ¿®ÑÁ®Ñ¿®÷ÐÁ®úÐ¿®ñÐÁ®ôÐ¿®êÐ¿®ëÐÁ®âÐ¿®ãÐÁ®ÂÐ¿®ÃÐÁ®®Ð¿®¯ÐÁ®Ð¿®ÐÁ®Ð¿®ÐÁ®ðÏ¿®ñÏÁ®æÏ¿®çÏÁ®âÏ¿®ãÏÁ®ÆÏ¿®ÇÏÁ®°Ï¿®±ÏÁ®¤Ï¿®¥ÏÁ®Ï¿®ÏÁ®Ï¿®ÏÁ®§ãÎû³æÎù³ÞÎù³ßÎû³ÕÎû³ØÎù³àÎù³áÎû³ÓÎû³ÖÎù³¥Ïû³¨Ïù³ÐÎù³ÑÎû³ÍÎû³ÐÎù³Ïù³Ïû³½Îû³ÀÎù³ºÎù³»Îû³¸Îù³¹Îû³¶Îù³·Îû³ÙÏû³ÜÏù³Îû³¢Îù³Îû³Îù³Ðû³Ðù³Ïû³Ïù³ÜÏù³ÝÏû³Îû³Îù³ùÍû³üÍù³åÍû³èÍù³ßÍû³âÍù³ØÍù³ÙÍû³ÐÍù³ÑÍû³°Íù³±Íû³Íù³Íû³Íù³Íû³òÌù³óÌû³ÞÌù³ßÌû³ÔÌù³ÕÌû³ÐÌù³ÑÌû³´Ìù³µÌû³Ìù³Ìû³Ìù³Ìû³Ìù³Ìû³Ìù³Ìû³§ÑËµ¹ÔË³¹ÌË³¹ÍËµ¹ÃËµ¹ÆË³¹ÎË³¹ÏËµ¹ÁËµ¹ÄË³¹Ìµ¹Ì³¹¾Ë³¹¿Ëµ¹»Ëµ¹¾Ë³¹øË³¹ùËµ¹«Ëµ¹®Ë³¹¨Ë³¹©Ëµ¹¦Ë³¹§Ëµ¹¤Ë³¹¥Ëµ¹ÇÌµ¹ÊÌ³¹Ëµ¹Ë³¹Ëµ¹Ë³¹ùÌµ¹üÌ³¹ïËµ¹òË³¹ÊÌ³¹ËÌµ¹óÊµ¹öÊ³¹çÊµ¹êÊ³¹ÓÊµ¹ÖÊ³¹ÍÊµ¹ÐÊ³¹ÆÊ³¹ÇÊµ¹¾Ê³¹¿Êµ¹Ê³¹Êµ¹Ê³¹Êµ¹òÉ³¹óÉµ¹àÉ³¹áÉµ¹ÌÉ³¹ÍÉµ¹ÂÉ³¹ÃÉµ¹¾É³¹¿Éµ¹¢É³¹£Éµ¹É³¹Éµ¹É³¹Éµ¹öÈ³¹÷Èµ¹ôÈ³¹õÈµ¹§¿Èï¾ÂÈí¾ºÈí¾»Èï¾±Èï¾´Èí¾¼Èí¾½Èï¾¯Èï¾²Èí¾Éï¾Éí¾¬Èí¾­Èï¾©Èï¾¬Èí¾æÈí¾çÈï¾Èï¾Èí¾Èí¾Èï¾Èí¾Èï¾Èí¾Èï¾µÉï¾¸Éí¾ûÇï¾þÇí¾ñÇï¾ôÇí¾çÉï¾êÉí¾ÝÈï¾àÈí¾¸Éí¾¹Éï¾áÇï¾äÇí¾ÕÇï¾ØÇí¾ÁÇï¾ÄÇí¾»Çï¾¾Çí¾´Çí¾µÇï¾¬Çí¾­Çï¾Çí¾Çï¾øÆí¾ùÆï¾àÆí¾áÆï¾ÎÆí¾ÏÆï¾ºÆí¾»Æï¾°Æí¾±Æï¾¬Æí¾­Æï¾Æí¾Æï¾úÅí¾ûÅï¾îÅí¾ïÅï¾äÅí¾åÅï¾âÅí¾ãÅï¾§­Å©Ä°Å§Ä¨Å§Ä©Å©ÄÅ©Ä¢Å§ÄªÅ§Ä«Å©ÄÅ©Ä Å§ÄïÅ©ÄòÅ§ÄÅ§ÄÅ©ÄÅ©ÄÅ§ÄÔÅ§ÄÕÅ©ÄÅ©ÄÅ§ÄÅ§ÄÅ©ÄÅ§ÄÅ©ÄÅ§ÄÅ©Ä£Æ©Ä¦Æ§ÄéÄ©ÄìÄ§ÄßÄ©ÄâÄ§ÄÕÆ©ÄØÆ§ÄËÅ©ÄÎÅ§Ä¦Æ§Ä§Æ©ÄÏÄ©ÄÒÄ§ÄÃÄ©ÄÆÄ§Ä¯Ä©Ä²Ä§Ä©Ä©Ä¬Ä§Ä¢Ä§Ä£Ä©ÄÄ§ÄÄ©ÄúÃ§ÄûÃ©ÄæÃ§ÄçÃ©ÄÎÃ§ÄÏÃ©Ä¼Ã§Ä½Ã©Ä¨Ã§Ä©Ã©ÄÃ§ÄÃ©ÄÃ§ÄÃ©ÄþÂ§ÄÿÂ©ÄèÂ§ÄéÂ©ÄÜÂ§ÄÝÂ©ÄÒÂ§ÄÓÂ©ÄÐÂ§ÄÑÂ©Ä§ÂãÉÂáÉÂáÉÂãÉÂãÉÂáÉÂáÉÂãÉÂãÉÂáÉÝÂãÉàÂáÉÂáÉÂãÉÂãÉÂáÉÂÂáÉÃÂãÉõÁãÉøÁáÉòÁáÉóÁãÉðÁáÉñÁãÉîÁáÉïÁãÉÃãÉÃáÉ×ÁãÉÚÁáÉÍÁãÉÐÁáÉÃÃãÉÆÃáÉ¹ÂãÉ¼ÂáÉÃáÉÃãÉ½ÁãÉÀÁáÉ±ÁãÉ´ÁáÉÁãÉ ÁáÉÁãÉÁáÉÁáÉÁãÉÁáÉÁãÉèÀáÉéÀãÉÔÀáÉÕÀãÉ¼ÀáÉ½ÀãÉªÀáÉ«ÀãÉÀáÉÀãÉÀáÉÀãÉÀáÉÀãÉì¿áÉí¿ãÉÖ¿áÉ×¿ãÉÊ¿áÉË¿ãÉÀ¿áÉÁ¿ãÉ¾¿áÉ¿¿ãÉ§¿Ï¿Ï¿Ï¿Ïû¾Ïþ¾Ï¿Ï¿Ïù¾Ïü¾ÏË¿ÏÎ¿Ïö¾Ï÷¾Ïó¾Ïö¾Ï°¿Ï±¿Ïã¾Ïæ¾Ïà¾Ïá¾ÏÞ¾Ïß¾ÏÜ¾ÏÝ¾Ïÿ¿ÏÀÏÅ¾ÏÈ¾Ï»¾Ï¾¾Ï±ÀÏ´ÀÏ§¿Ïª¿ÏÀÏÀÏ«¾Ï®¾Ï¾Ï¢¾Ï¾Ï¾Ï¾Ï¾Ïþ½Ïÿ½Ïö½Ï÷½ÏÖ½Ï×½ÏÂ½ÏÃ½Ïª½Ï«½Ï½Ï½Ï½Ï½Ïú¼Ïû¼Ïö¼Ï÷¼ÏÚ¼ÏÛ¼ÏÄ¼ÏÅ¼Ï¸¼Ï¹¼Ï®¼Ï¯¼Ï¬¼Ï­¼Ï§÷»×Ôú»ÕÔò»ÕÔó»×Ôé»×Ôì»ÕÔô»ÕÔõ»×Ôç»×Ôê»ÕÔ¹¼×Ô¼¼ÕÔä»ÕÔå»×Ôá»×Ôä»ÕÔ¼ÕÔ¼×ÔÑ»×ÔÔ»ÕÔÎ»ÕÔÏ»×ÔÌ»ÕÔÍ»×ÔÊ»ÕÔË»×Ôí¼×Ôð¼ÕÔ³»×Ô¶»ÕÔ©»×Ô¬»ÕÔ½×Ô¢½ÕÔ¼×Ô¼ÕÔð¼ÕÔñ¼×Ô»×Ô»ÕÔ»×Ô»ÕÔùº×ÔüºÕÔóº×ÔöºÕÔìºÕÔíº×ÔäºÕÔåº×ÔÄºÕÔÅº×Ô°ºÕÔ±º×ÔºÕÔº×ÔºÕÔº×Ôò¹ÕÔó¹×Ôè¹ÕÔé¹×Ôä¹ÕÔå¹×ÔÈ¹ÕÔÉ¹×Ô²¹ÕÔ³¹×Ô¦¹ÕÔ§¹×Ô¹ÕÔ¹×Ô¹ÕÔ¹×Ô§»¹ü¹ý»ó»ö¹þ¹ÿ»ñ»ô¹Ã»Æ¹î¹ï»ë»î¹¨¹©»Û»Þ¹Ø¹Ù»Ö¹×»Ô¹Õ»÷»ú¹½»À¹³»¶¹©»¬¹»¢¹ú¹û»£»¦¹»¹»¹ý»¹ö¹÷»î¹ï»Î¹Ï»º¹»»¢¹£»¹»ü¹ý»ò¹ó»î¹ï»Ò¹Ó»¼¹½»°¹±»¦¹§»¤¹¥»§ïõ
+òó
+êó
+ëõ
+áõ
+äó
+ìó
+íõ
+ßõ
+âó
+±õ
+´ó
+Üó
+Ýõ
+Ùõ
+Üó
+ó
+õ
+Éõ
+Ìó
+Æó
+Çõ
+Äó
+Åõ
+Âó
+Ãõ
+åõ
+èó
+«õ
+®ó
+¡õ
+¤ó
+õ
+ó
+õ
+ó
+èó
+éõ
+õ
+ó
+õ
+ó
+ñõ
+ôó
+ëõ
+îó
+äó
+åõ
+Üó
+Ýõ
+¼ó
+½õ
+¨ó
+©õ
+ó
+õ
+þó
+ÿõ
+êó
+ëõ
+àó
+áõ
+Üó
+Ýõ
+Àó
+Áõ
+ªó
+«õ
+ó
+õ
+ó
+õ
+ó
+õ
+§Ý¯à­Ø­Ù¯Ï¯Ò­Ú­Û¯Í¯Ð­¯¢­Ê­Ë¯Ç¯Ê­­¯·¯º­´­µ¯²­³¯°­±¯Ó¯Ö­¯­¯­¯­û¯þ­Ö­×¯ÿ¯­ó¯ö­ß¯â­Ù¯Ü­Ò­Ó¯Ê­Ë¯ª­«¯­¯þÿ­ÿÿ¯ìÿ­íÿ¯Øÿ­Ùÿ¯Îÿ­Ïÿ¯Êÿ­Ëÿ¯®ÿ­¯ÿ¯ÿ­ÿ¯ÿ­ÿ¯ÿ­ÿ¯ÿ­ÿ¯§ËþéÎþçÆþçÇþé½þéÀþçÈþçÉþé»þé¾þçÿéÿç¸þç¹þéµþé¸þçòþçóþé¥þé¨þç¢þç£þé þç¡þéþçþéÁÿéÄÿçþéþçýýéþçóÿéöÿçéþéìþçÄÿçÅÿéíýéðýçáýéäýçÍýéÐýçÇýéÊýçÀýçÁýé¸ýç¹ýéýçýéýçýéìüçíüéÚüçÛüéÆüçÇüé¼üç½üé¸üç¹üéüçüéüçüéúûçûûéðûçñûéîûçïûé§¹û£¼û¡´û¡µû£«û£®û¡¶û¡·û£©û£¬û¡ûû£þû¡¦û¡§û££û£¦û¡àû¡áû£û£û¡û¡û£û¡û£û¡û£¯ü£²ü¡õú£øú¡ëú£îú¡áü£äü¡×û£Úû¡²ü¡³ü£Ûú£Þú¡Ïú£Òú¡»ú£¾ú¡µú£¸ú¡®ú¡¯ú£¦ú¡§ú£ú¡ú£òù¡óù£Úù¡Ûù£Èù¡Éù£´ù¡µù£ªù¡«ù£¦ù¡§ù£ù¡ù£ôø¡õø£èø¡éø£Þø¡ßø£Üø¡Ýø£§§øÝ ªøÛ ¢øÛ £øÝ øÝ øÛ ¤øÛ ¥øÝ øÝ øÛ éøÝ ìøÛ øÛ øÝ øÝ øÛ ÎøÛ ÏøÝ øÝ øÛ þ÷Û ÿ÷Ý ü÷Û ý÷Ý ú÷Û û÷Ý ùÝ  ùÛ ã÷Ý æ÷Û Ù÷Ý Ü÷Û ÏùÝ ÒùÛ ÅøÝ ÈøÛ  ùÛ ¡ùÝ É÷Ý Ì÷Û ½÷Ý À÷Û ©÷Ý ¬÷Û £÷Ý ¦÷Û ÷Û ÷Ý ÷Û ÷Ý ôöÛ õöÝ àöÛ áöÝ ÈöÛ ÉöÝ ¶öÛ ·öÝ ¢öÛ £öÝ öÛ öÝ öÛ öÝ øõÛ ùõÝ âõÛ ãõÝ ÖõÛ ×õÝ ÌõÛ ÍõÝ ÊõÛ ËõÝ §õ&õ&õ&õ&õ&õ&õ&õ&õ&õ&×õ&Úõ&õ&õ&ÿô&õ&¼õ&½õ&ïô&òô&ìô&íô&êô&ëô&èô&éô&ö&ö&Ñô&Ôô&Çô&Êô&½ö&Àö&³õ&¶õ&ö&ö&·ô&ºô&«ô&®ô&ô&ô&ô&ô&ô&ô&ô&ô&âó&ãó&Îó&Ïó&¶ó&·ó&¤ó&¥ó&ó&ó&ó&ó&ó&ó&æò&çò&Ðò&Ñò&Äò&Åò&ºò&»ò&¸ò&¹ò&§òÑ+òÏ+þñÏ+ÿñÑ+õñÑ+øñÏ+òÏ+òÑ+óñÑ+öñÏ+ÅòÑ+ÈòÏ+ðñÏ+ññÑ+íñÑ+ðñÏ+ªòÏ+«òÑ+ÝñÑ+àñÏ+ÚñÏ+ÛñÑ+ØñÏ+ÙñÑ+ÖñÏ+×ñÑ+ùòÑ+üòÏ+¿ñÑ+ÂñÏ+µñÑ+¸ñÏ+«óÑ+®óÏ+¡òÑ+¤òÏ+üòÏ+ýòÑ+¥ñÑ+¨ñÏ+ñÑ+ñÏ+ñÑ+ñÏ+ÿðÑ+ñÏ+øðÏ+ùðÑ+ððÏ+ñðÑ+ÐðÏ+ÑðÑ+¼ðÏ+½ðÑ+¤ðÏ+¥ðÑ+ðÏ+ðÑ+þïÏ+ÿïÑ+ôïÏ+õïÑ+ðïÏ+ñïÑ+ÔïÏ+ÕïÑ+¾ïÏ+¿ïÑ+²ïÏ+³ïÑ+¨ïÏ+©ïÑ+¦ïÏ+§ïÑ+§ñî1ôî1ìî1íî1ãî1æî1îî1ïî1áî1äî1³ï1¶ï1Þî1ßî1Ûî1Þî1ï1ï1Ëî1Îî1Èî1Éî1Æî1Çî1Äî1Åî1çï1êï1­î1°î1£î1¦î1ð1ð1ï1ï1êï1ëï1î1î1î1î1óí1öí1íí1ðí1æí1çí1Þí1ßí1¾í1¿í1ªí1«í1í1í1í1í1ìì1íì1âì1ãì1Þì1ßì1Âì1Ãì1¬ì1­ì1 ì1¡ì1ì1ì1ì1ì1§ßëÅ6âëÃ6ÚëÃ6ÛëÅ6ÑëÅ6ÔëÃ6ÜëÃ6ÝëÅ6ÏëÅ6ÒëÃ6¡ìÅ6¤ìÃ6ÌëÃ6ÍëÅ6ÉëÅ6ÌëÃ6ìÃ6ìÅ6¹ëÅ6¼ëÃ6¶ëÃ6·ëÅ6´ëÃ6µëÅ6²ëÃ6³ëÅ6ÕìÅ6ØìÃ6ëÅ6ëÃ6ëÅ6ëÃ6íÅ6íÃ6ýëÅ6ìÃ6ØìÃ6ÙìÅ6ëÅ6ëÃ6õêÅ6øêÃ6áêÅ6äêÃ6ÛêÅ6ÞêÃ6ÔêÃ6ÕêÅ6ÌêÃ6ÍêÅ6¬êÃ6­êÅ6êÃ6êÅ6êÃ6êÅ6îéÃ6ïéÅ6ÚéÃ6ÛéÅ6ÐéÃ6ÑéÅ6ÌéÃ6ÍéÅ6°éÃ6±éÅ6éÃ6éÅ6éÃ6éÅ6éÃ6éÅ6éÃ6éÅ6§Íèÿ;Ðèý;Èèý;Éèÿ;¿èÿ;Âèý;Êèý;Ëèÿ;½èÿ;Àèý;éÿ;éý;ºèý;»èÿ;·èÿ;ºèý;ôèý;õèÿ;§èÿ;ªèý;¤èý;¥èÿ;¢èý;£èÿ; èý;¡èÿ;Ãéÿ;Æéý;èÿ;èý;ÿçÿ;èý;õéÿ;øéý;ëèÿ;îèý;Æéý;Çéÿ;ïçÿ;òçý;ãçÿ;æçý;Ïçÿ;Òçý;Éçÿ;Ìçý;Âçý;Ãçÿ;ºçý;»çÿ;çý;çÿ;çý;çÿ;îæý;ïæÿ;Üæý;Ýæÿ;Èæý;Éæÿ;¾æý;¿æÿ;ºæý;»æÿ;æý;æÿ;æý;æÿ;üåý;ýåÿ;òåý;óåÿ;ðåý;ñåÿ;§»å¹A¾å·A¶å·A·å¹A­å¹A°å·A¸å·A¹å¹A«å¹A®å·Aýå¹Aæ·A¨å·A©å¹A¥å¹A¨å·Aâå·Aãå¹Aå¹Aå·Aå·Aå¹Aå·Aå¹Aå·Aå¹A±æ¹A´æ·A÷ä¹Aúä·Aíä¹Aðä·Aãæ¹Aææ·AÙå¹AÜå·A´æ·Aµæ¹AÝä¹Aàä·AÑä¹AÔä·A½ä¹AÀä·A·ä¹Aºä·A°ä·A±ä¹A¨ä·A©ä¹Aä·Aä¹Aôã·Aõã¹AÜã·AÝã¹AÊã·AËã¹A¶ã·A·ã¹A¬ã·A­ã¹A¨ã·A©ã¹Aã·Aã¹Aöâ·A÷â¹Aêâ·Aëâ¹Aàâ·Aáâ¹AÞâ·Aßâ¹A§©âóF¬âñF¤âñF¥âóFâóFâñF¦âñF§âóFâóFâñFëâóFîâñFâñFâóFâóFâñFÐâñFÑâóFâóFâñFâñFâóFþáñFÿáóFüáñFýáóFãóF¢ãñFåáóFèáñFÛáóFÞáñFÑãóFÔãñFÇâóFÊâñF¢ãñF£ãóFËáóFÎáñF¿áóFÂáñF«áóF®áñF¥áóF¨áñFáñFáóFáñFáóFöàñF÷àóFâàñFãàóFÊàñFËàóF¸àñF¹àóF¤àñF¥àóFàñFàóFàñFàóFúßñFûßóFäßñFåßóFØßñFÙßóFÎßñFÏßóFÌßñFÍßóF§ß­Lß«Lß«Lß­Lß­Lß«Lß«Lß­Lß­Lß«LÙß­LÜß«Lß«Lß­Lß­Lß«L¾ß«L¿ß­LñÞ­LôÞ«LîÞ«LïÞ­LìÞ«LíÞ­LêÞ«LëÞ­Là­Là«LÓÞ­LÖÞ«LÉÞ­LÌÞ«L¿à­LÂà«Lµß­L¸ß«Là«Là­L¹Þ­L¼Þ«L­Þ­L°Þ«LÞ­LÞ«LÞ­LÞ«LÞ«LÞ­LÞ«LÞ­LäÝ«LåÝ­LÐÝ«LÑÝ­L¸Ý«L¹Ý­L¦Ý«L§Ý­LÝ«LÝ­LÝ«LÝ­LÝ«LÝ­LèÜ«LéÜ­LÒÜ«LÓÜ­LÆÜ«LÇÜ­L¼Ü«L½Ü­LºÜ«L»Ü­L§ÜçQÜåQÜåQÜçQ÷ÛçQúÛåQÜåQÜçQõÛçQøÛåQÇÜçQÊÜåQòÛåQóÛçQïÛçQòÛåQ¬ÜåQ­ÜçQßÛçQâÛåQÜÛåQÝÛçQÚÛåQÛÛçQØÛåQÙÛçQûÜçQþÜåQÁÛçQÄÛåQ·ÛçQºÛåQ­ÝçQ°ÝåQ£ÜçQ¦ÜåQþÜåQÿÜçQ§ÛçQªÛåQÛçQÛåQÛçQÛåQÛçQÛåQúÚåQûÚçQòÚåQóÚçQÒÚåQÓÚçQ¾ÚåQ¿ÚçQ¦ÚåQ§ÚçQÚåQÚçQÚåQÚçQöÙåQ÷ÙçQòÙåQóÙçQÖÙåQ×ÙçQÀÙåQÁÙçQ´ÙåQµÙçQªÙåQ«ÙçQ¨ÙåQ©ÙçQ§óØ¡WöØWîØWïØ¡WåØ¡WèØWðØWñØ¡WãØ¡WæØWµÙ¡W¸ÙWàØWáØ¡WÝØ¡WàØWÙWÙ¡WÍØ¡WÐØWÊØWËØ¡WÈØWÉØ¡WÆØWÇØ¡WéÙ¡WìÙW¯Ø¡W²ØW¥Ø¡W¨ØWÚ¡WÚWÙ¡WÙWìÙWíÙ¡WØ¡WØWØ¡WØWõ×¡Wø×Wï×¡Wò×Wè×Wé×¡Wà×Wá×¡WÀ×WÁ×¡W¬×W­×¡W×W×¡W×W×¡WîÖWïÖ¡WäÖWåÖ¡WàÖWáÖ¡WÄÖWÅÖ¡W®ÖW¯Ö¡W¢ÖW£Ö¡WÖWÖ¡WÖWÖ¡W§áÕÛ\äÕÙ\ÜÕÙ\ÝÕÛ\ÓÕÛ\ÖÕÙ\ÞÕÙ\ßÕÛ\ÑÕÛ\ÔÕÙ\£ÖÛ\¦ÖÙ\ÎÕÙ\ÏÕÛ\ËÕÛ\ÎÕÙ\ÖÙ\ÖÛ\»ÕÛ\¾ÕÙ\¸ÕÙ\¹ÕÛ\¶ÕÙ\·ÕÛ\´ÕÙ\µÕÛ\×ÖÛ\ÚÖÙ\ÕÛ\ ÕÙ\ÕÛ\ÕÙ\×Û\×Ù\ÿÕÛ\ÖÙ\ÚÖÙ\ÛÖÛ\ÕÛ\ÕÙ\÷ÔÛ\úÔÙ\ãÔÛ\æÔÙ\ÝÔÛ\àÔÙ\ÖÔÙ\×ÔÛ\ÎÔÙ\ÏÔÛ\®ÔÙ\¯ÔÛ\ÔÙ\ÔÛ\ÔÙ\ÔÛ\ðÓÙ\ñÓÛ\ÜÓÙ\ÝÓÛ\ÒÓÙ\ÓÓÛ\ÎÓÙ\ÏÓÛ\²ÓÙ\³ÓÛ\ÓÙ\ÓÛ\ÓÙ\ÓÛ\ÓÙ\ÓÛ\ÓÙ\ÓÛ\§ÏÒbÒÒbÊÒbËÒbÁÒbÄÒbÌÒbÍÒb¿ÒbÂÒbÓbÓb¼Òb½Òb¹Òb¼ÒböÒb÷Òb©Òb¬Òb¦Òb§Òb¤Òb¥Òb¢Òb£ÒbÅÓbÈÓbÒbÒbÒbÒb÷ÓbúÓbíÒbðÒbÈÓbÉÓbñÑbôÑbåÑbèÑbÑÑbÔÑbËÑbÎÑbÄÑbÅÑb¼Ñb½ÑbÑbÑbÑbÑbðÐbñÐbÞÐbßÐbÊÐbËÐbÀÐbÁÐb¼Ðb½Ðb Ðb¡ÐbÐbÐbþÏbÿÏbôÏbõÏbòÏbóÏb§½ÏÏgÀÏÍg¸ÏÍg¹ÏÏg¯ÏÏg²ÏÍgºÏÍg»ÏÏg­ÏÏg°ÏÍgÿÏÏgÐÍgªÏÍg«ÏÏg§ÏÏgªÏÍgäÏÍgåÏÏgÏÏgÏÍgÏÍgÏÏgÏÍgÏÏgÏÍgÏÏg³ÐÏg¶ÐÍgùÎÏgüÎÍgïÎÏgòÎÍgåÐÏgèÐÍgÛÏÏgÞÏÍg¶ÐÍg·ÐÏgßÎÏgâÎÍgÓÎÏgÖÎÍg¿ÎÏgÂÎÍg¹ÎÏg¼ÎÍg²ÎÍg³ÎÏgªÎÍg«ÎÏgÎÍgÎÏgöÍÍg÷ÍÏgÞÍÍgßÍÏgÌÍÍgÍÍÏg¸ÍÍg¹ÍÏg®ÍÍg¯ÍÏgªÍÍg«ÍÏgÍÍgÍÏgøÌÍgùÌÏgìÌÍgíÌÏgâÌÍgãÌÏgàÌÍgáÌÏg§«Ìm®Ìm¦Ìm§ÌmÌm Ìm¨Ìm©ÌmÌmÌmíÌmðÌmÌmÌmÌmÌmÒÌmÓÌmÌmÌmÌmÌmÌmÌmþËmÿËm¡Ím¤ÍmçËmêËmÝËmàËmÓÍmÖÍmÉÌmÌÌm¤Ím¥ÍmÍËmÐËmÁËmÄËm­Ëm°Ëm§ËmªËm Ëm¡ËmËmËmøÊmùÊmäÊmåÊmÌÊmÍÊmºÊm»Êm¦Êm§ÊmÊmÊmÊmÊmüÉmýÉmæÉmçÉmÚÉmÛÉmÐÉmÑÉmÎÉmÏÉm§ÉÃrÉÁrÉÁrÉÃrÉÃrÉÁrÉÁrÉÃrÉÃrÉÁrÛÉÃrÞÉÁrÉÁrÉÃrÉÃrÉÁrÀÉÁrÁÉÃróÈÃröÈÁrðÈÁrñÈÃrîÈÁrïÈÃrìÈÁríÈÃrÊÃrÊÁrÕÈÃrØÈÁrËÈÃrÎÈÁrÁÊÃrÄÊÁr·ÉÃrºÉÁrÊÁrÊÃr»ÈÃr¾ÈÁr¯ÈÃr²ÈÁrÈÃrÈÁrÈÃrÈÁrÈÁrÈÃrÈÁrÈÃræÇÁrçÇÃrÒÇÁrÓÇÃrºÇÁr»ÇÃr¨ÇÁr©ÇÃrÇÁrÇÃrÇÁrÇÃrÇÁrÇÃrêÆÁrëÆÃrÔÆÁrÕÆÃrÈÆÁrÉÆÃr¾ÆÁr¿ÆÃr¼ÆÁr½ÆÃr§ÆýwÆûwÆûwÆýwùÅýwüÅûwÆûwÆýw÷ÅýwúÅûwÉÆýwÌÆûwôÅûwõÅýwñÅýwôÅûw®Æûw¯ÆýwáÅýwäÅûwÞÅûwßÅýwÜÅûwÝÅýwÚÅûwÛÅýwýÆýwÇûwÃÅýwÆÅûw¹Åýw¼Åûw¯Çýw²Çûw¥Æýw¨ÆûwÇûwÇýw©Åýw¬ÅûwÅýw ÅûwÅýwÅûwÅýwÅûwüÄûwýÄýwôÄûwõÄýwÔÄûwÕÄýwÀÄûwÁÄýw¨Äûw©ÄýwÄûwÄýwÄûwÄýwøÃûwùÃýwôÃûwõÃýwØÃûwÙÃýwÂÃûwÃÃýw¶Ãûw·Ãýw¬Ãûw­ÃýwªÃûw«Ãýw§õÂ·}øÂµ}ðÂµ}ñÂ·}çÂ·}êÂµ}òÂµ}óÂ·}åÂ·}èÂµ}·Ã·}ºÃµ}âÂµ}ãÂ·}ßÂ·}âÂµ}Ãµ}Ã·}ÏÂ·}ÒÂµ}ÌÂµ}ÍÂ·}ÊÂµ}ËÂ·}ÈÂµ}ÉÂ·}ëÃ·}îÃµ}±Â·}´Âµ}§Â·}ªÂµ}Ä·} Äµ}Ã·}Ãµ}îÃµ}ïÃ·}Â·}Âµ}Â·}Âµ}÷Á·}úÁµ}ñÁ·}ôÁµ}êÁµ}ëÁ·}âÁµ}ãÁ·}ÂÁµ}ÃÁ·}®Áµ}¯Á·}Áµ}Á·}Áµ}Á·}ðÀµ}ñÀ·}æÀµ}çÀ·}âÀµ}ãÀ·}ÆÀµ}ÇÀ·}°Àµ}±À·}¤Àµ}¥À·}Àµ}À·}Àµ}À·}§ã¿ñæ¿ïÞ¿ïß¿ñÕ¿ñØ¿ïà¿ïá¿ñÓ¿ñÖ¿ï¥Àñ¨ÀïÐ¿ïÑ¿ñÍ¿ñÐ¿ïÀïÀñ½¿ñÀ¿ïº¿ï»¿ñ¸¿ï¹¿ñ¶¿ï·¿ñÙÀñÜÀï¿ñ¢¿ï¿ñ¿ïÁñÁïÀñÀïÜÀïÝÀñ¿ñ¿ïù¾ñü¾ïå¾ñè¾ïß¾ñâ¾ïØ¾ïÙ¾ñÐ¾ïÑ¾ñ°¾ï±¾ñ¾ï¾ñ¾ï¾ñò½ïó½ñÞ½ïß½ñÔ½ïÕ½ñÐ½ïÑ½ñ´½ïµ½ñ½ï½ñ½ï½ñ½ï½ñ½ï½ñ§Ñ¼«Ô¼©Ì¼©Í¼«Ã¼«Æ¼©Î¼©Ï¼«Á¼«Ä¼©½«½©¾¼©¿¼«»¼«¾¼©ø¼©ù¼««¼«®¼©¨¼©©¼«¦¼©§¼«¤¼©¥¼«Ç½«Ê½©¼«¼©¼«¼©ù½«ü½©ï¼«ò¼©Ê½©Ë½«ó»«ö»©ç»«ê»©Ó»«Ö»©Í»«Ð»©Æ»©Ç»«¾»©¿»«»©»«»©»«òº©óº«àº©áº«Ìº©Íº«Âº©Ãº«¾º©¿º«¢º©£º«º©º«º©º«ö¹©÷¹«ô¹©õ¹«§¿¹åÂ¹ãº¹ã»¹å±¹å´¹ã¼¹ã½¹å¯¹å²¹ãºåºã¬¹ã­¹å©¹å¬¹ãæ¹ãç¹å¹å¹ã¹ã¹å¹ã¹å¹ã¹åµºå¸ºãû¸åþ¸ãñ¸åô¸ãçºåêºãÝ¹åà¹ã¸ºã¹ºåá¸åä¸ãÕ¸åØ¸ãÁ¸åÄ¸ã»¸å¾¸ã´¸ãµ¸å¬¸ã­¸å¸ã¸åø·ãù·åà·ãá·åÎ·ãÏ·åº·ã»·å°·ã±·å¬·ã­·å·ã·åú¶ãû¶åî¶ãï¶åä¶ãå¶åâ¶ãã¶å§­¶°¶¨¶©¶¶¢¶ª¶«¶¶ ¶ï¶ò¶¶¶¶¶Ô¶Õ¶¶¶¶¶¶¶¶¶£·¦·éµìµßµâµÕ·Ø·Ë¶Î¶¦·§·ÏµÒµÃµÆµ¯µ²µ©µ¬µ¢µ£µµµú´û´æ´ç´Î´Ï´¼´½´¨´©´´´´´þ³ÿ³è³é³Ü³Ý³Ò³Ó³Ð³Ñ³§³Ù³×³×³Ù³Ù³×³×³Ù³Ù³×Ý³Ùà³×³×³Ù³Ù³×Â³×Ã³Ùõ²Ùø²×ò²×ó²Ùð²×ñ²Ùî²×ï²Ù´Ù´××²ÙÚ²×Í²ÙÐ²×Ã´ÙÆ´×¹³Ù¼³×´×´Ù½²ÙÀ²×±²Ù´²×²Ù ²×²Ù²×²×²Ù²×²Ùè±×é±ÙÔ±×Õ±Ù¼±×½±Ùª±×«±Ù±×±Ù±×±Ù±×±Ùì°×í°ÙÖ°××°ÙÊ°×Ë°ÙÀ°×Á°Ù¾°×¿°Ù§°°°°û¯þ¯°°ù¯ü¯Ë°Î°ö¯÷¯ó¯ö¯°°±°ã¯æ¯à¯á¯Þ¯ß¯Ü¯Ý¯ÿ°±Å¯È¯»¯¾¯±±´±§°ª°±±«¯®¯¯¢¯¯¯¯¯þ®ÿ®ö®÷®Ö®×®Â®Ã®ª®«®®®®®ú­û­ö­÷­Ú­Û­Ä­Å­¸­¹­®­¯­¬­­­§÷¬Í£ú¬Ë£ò¬Ë£ó¬Í£é¬Í£ì¬Ë£ô¬Ë£õ¬Í£ç¬Í£ê¬Ë£¹­Í£¼­Ë£ä¬Ë£å¬Í£á¬Í£ä¬Ë£­Ë£­Í£Ñ¬Í£Ô¬Ë£Î¬Ë£Ï¬Í£Ì¬Ë£Í¬Í£Ê¬Ë£Ë¬Í£í­Í£ð­Ë£³¬Í£¶¬Ë£©¬Í£¬¬Ë£®Í£¢®Ë£­Í£­Ë£ð­Ë£ñ­Í£¬Í£¬Ë£¬Í£¬Ë£ù«Í£ü«Ë£ó«Í£ö«Ë£ì«Ë£í«Í£ä«Ë£å«Í£Ä«Ë£Å«Í£°«Ë£±«Í£«Ë£«Í£«Ë£«Í£òªË£óªÍ£èªË£éªÍ£äªË£åªÍ£ÈªË£ÉªÍ£²ªË£³ªÍ£¦ªË£§ªÍ£ªË£ªÍ£ªË£ªÍ£§å©©è©©à©©á©©×©©Ú©©â©©ã©©Õ©©Ø©©§ª©ªª©Ò©©Ó©©Ï©©Ò©©ª©ª©¿©©Â©©¼©©½©©º©©»©©¸©©¹©©Ûª©Þª©¡©©¤©©©©©©«©«©ª©ª©Þª©ßª©©©©©û¨©þ¨©ç¨©ê¨©á¨©ä¨©Ú¨©Û¨©Ò¨©Ó¨©²¨©³¨©¨©¨©¨©¨©ô§©õ§©à§©á§©Ö§©×§©Ò§©Ó§©¶§©·§© §©¡§©§©§©§©§©§©§©§Ó¦Á®Ö¦¿®Î¦¿®Ï¦Á®Å¦Á®È¦¿®Ð¦¿®Ñ¦Á®Ã¦Á®Æ¦¿®§Á®§¿®À¦¿®Á¦Á®½¦Á®À¦¿®ú¦¿®û¦Á®­¦Á®°¦¿®ª¦¿®«¦Á®¨¦¿®©¦Á®¦¦¿®§¦Á®É§Á®Ì§¿®¦Á®¦¿®¦Á®¦¿®û§Á®þ§¿®ñ¦Á®ô¦¿®Ì§¿®Í§Á®õ¥Á®ø¥¿®é¥Á®ì¥¿®Õ¥Á®Ø¥¿®Ï¥Á®Ò¥¿®È¥¿®É¥Á®À¥¿®Á¥Á® ¥¿®¡¥Á®¥¿®¥Á®ô¤¿®õ¤Á®â¤¿®ã¤Á®Î¤¿®Ï¤Á®Ä¤¿®Å¤Á®À¤¿®Á¤Á®¤¤¿®¥¤Á®¤¿®¤Á®¤¿®¤Á®ø£¿®ù£Á®ö£¿®÷£Á®§Á£û³Ä£ù³¼£ù³½£û³³£û³¶£ù³¾£ù³¿£û³±£û³´£ù³¤û³¤ù³®£ù³¯£û³«£û³®£ù³è£ù³é£û³£û³£ù³£ù³£û³£ù³£û³£ù³£û³·¤û³º¤ù³ý¢û³£ù³ó¢û³ö¢ù³é¤û³ì¤ù³ß£û³â£ù³º¤ù³»¤û³ã¢û³æ¢ù³×¢û³Ú¢ù³Ã¢û³Æ¢ù³½¢û³À¢ù³¶¢ù³·¢û³®¢ù³¯¢û³¢ù³¢û³ú¡ù³û¡û³â¡ù³ã¡û³Ð¡ù³Ñ¡û³¼¡ù³½¡û³²¡ù³³¡û³®¡ù³¯¡û³¡ù³¡û³ü ù³ý û³ð ù³ñ û³æ ù³ç û³ä ù³å û³§¯ µ¹² ³¹ª ³¹« µ¹¡ µ¹¤ ³¹¬ ³¹­ µ¹ µ¹¢ ³¹ñ µ¹ô ³¹ ³¹ µ¹ µ¹ ³¹Ö ³¹× µ¹ µ¹ ³¹ ³¹ µ¹ ³¹ µ¹ ³¹ µ¹¥¡µ¹¨¡³¹ëµ¹î³¹áµ¹ä³¹×¡µ¹Ú¡³¹Í µ¹Ð ³¹¨¡³¹©¡µ¹Ñµ¹Ô³¹Åµ¹È³¹±µ¹´³¹«µ¹®³¹¤³¹¥µ¹³¹µ¹ü³¹ýµ¹è³¹éµ¹Ð³¹Ñµ¹¾³¹¿µ¹ª³¹«µ¹ ³¹¡µ¹³¹µ¹³¹µ¹ê³¹ëµ¹Þ³¹ßµ¹Ô³¹Õµ¹Ò³¹Óµ¹§ï¾ í¾í¾ï¾ï¾í¾í¾ï¾ï¾í¾ßï¾âí¾í¾ï¾ï¾í¾Äí¾Åï¾÷ï¾úí¾ôí¾õï¾òí¾óï¾ðí¾ñï¾ï¾í¾Ùï¾Üí¾Ïï¾Òí¾Åï¾Èí¾»ï¾¾í¾í¾ï¾¿ï¾Âí¾³ï¾¶í¾ï¾¢í¾ï¾í¾í¾ï¾í¾ï¾êí¾ëï¾Öí¾×ï¾¾í¾¿ï¾¬í¾­ï¾í¾ï¾í¾ï¾í¾ï¾îí¾ïï¾Øí¾Ùï¾Ìí¾Íï¾Âí¾Ãï¾Àí¾Áï¾§©Ä§Ä§Ä©Äý©Ä§Ä§Ä©Äû©Äþ§ÄÍ©ÄÐ§Äø§Äù©Äõ©Äø§Ä²§Ä³©Äå©Äè§Äâ§Äã©Äà§Äá©ÄÞ§Äß©Ä©Ä§ÄÇ©ÄÊ§Ä½©ÄÀ§Ä³©Ä¶§Ä©©Ä¬§Ä§Ä©Ä­©Ä°§Ä¡©Ä¤§Ä©Ä§Ä©Ä§Ä§Ä©Äø§Äù©ÄØ§ÄÙ©ÄÄ§ÄÅ©Ä¬§Ä­©Ä§Ä©Ä§Ä©Äü§Äý©Äø§Äù©ÄÜ§ÄÝ©ÄÆ§ÄÇ©Äº§Ä»©Ä°§Ä±©Ä®§Ä¯©Ä§ùãÉüáÉôáÉõãÉëãÉîáÉöáÉ÷ãÉéãÉìáÉ»ãÉ¾áÉæáÉçãÉããÉæáÉ áÉ¡ãÉÓãÉÖáÉÐáÉÑãÉÎáÉÏãÉÌáÉÍãÉïãÉòáÉµãÉ¸áÉ«ãÉ®áÉ¡ãÉ¤áÉãÉáÉòáÉóãÉãÉáÉãÉáÉûãÉþáÉõãÉøáÉîáÉïãÉæáÉçãÉÆáÉÇãÉ²áÉ³ãÉáÉãÉáÉãÉôáÉõãÉêáÉëãÉæáÉçãÉÊáÉËãÉ´áÉµãÉ¨áÉ©ãÉáÉãÉáÉãÉ§çÏêÏâÏãÏÙÏÜÏäÏåÏ×ÏÚÏ©Ï¬ÏÔÏÕÏÑÏÔÏÏÏÁÏÄÏ¾Ï¿Ï¼Ï½ÏºÏ»ÏÝÏàÏ£Ï¦ÏÏÏÏÏÏÏàÏáÏÏÏýÏÏéÏìÏãÏæÏÜÏÝÏÔÏÕÏ´ÏµÏ Ï¡ÏÏÏöÏ÷ÏâÏãÏØÏÙÏÔÏÕÏ¸Ï¹Ï¢Ï£ÏÏÏÏÏÏÏ§·Ú»ºÚ¹²Ú¹³Ú»©Ú»¬Ú¹´Ú¹µÚ»§Ú»ªÚ¹ùÚ»üÚ¹¤Ú¹¥Ú»¡Ú»¤Ú¹ÞÚ¹ßÚ»Ú»Ú¹Ú¹Ú»Ú¹Ú»Ú¹Ú»­Û»°Û¹óÙ»öÙ¹éÙ»ìÙ¹ßÛ»âÛ¹ÕÚ»ØÚ¹°Û¹±Û»ÙÙ»ÜÙ¹ÍÙ»ÐÙ¹¹Ù»¼Ù¹³Ù»¶Ù¹¬Ù¹­Ù»¤Ù¹¥Ù»Ù¹Ù»ðØ¹ñØ»ØØ¹ÙØ»ÆØ¹ÇØ»²Ø¹³Ø»¨Ø¹©Ø»¤Ø¹¥Ø»Ø¹Ø»ò×¹ó×»æ×¹ç×»Ü×¹Ý×»Ú×¹Û×»§¥×õ
+¨×ó
+ ×ó
+¡×õ
+×õ
+×ó
+¢×ó
+£×õ
+×õ
+×ó
+ç×õ
+ê×ó
+×ó
+×õ
+×õ
+×ó
+Ì×ó
+Í×õ
+ÿÖõ
+×ó
+üÖó
+ýÖõ
+úÖó
+ûÖõ
+øÖó
+ùÖõ
+Øõ
+Øó
+áÖõ
+äÖó
+×Öõ
+ÚÖó
+ÍØõ
+ÐØó
+Ã×õ
+Æ×ó
+Øó
+Øõ
+ÇÖõ
+ÊÖó
+»Öõ
+¾Öó
+§Öõ
+ªÖó
+¡Öõ
+¤Öó
+Öó
+Öõ
+Öó
+Öõ
+òÕó
+óÕõ
+ÞÕó
+ßÕõ
+ÆÕó
+ÇÕõ
+´Õó
+µÕõ
+ Õó
+¡Õõ
+Õó
+Õõ
+Õó
+Õõ
+öÔó
+÷Ôõ
+àÔó
+áÔõ
+ÔÔó
+ÕÔõ
+ÊÔó
+ËÔõ
+ÈÔó
+ÉÔõ
+§Ô¯Ô­Ô­Ô¯Ô¯Ô­Ô­Ô¯Ô¯Ô­ÕÔ¯ØÔ­Ô­Ô¯ýÓ¯Ô­ºÔ­»Ô¯íÓ¯ðÓ­êÓ­ëÓ¯èÓ­éÓ¯æÓ­çÓ¯Õ¯Õ­ÏÓ¯ÒÓ­ÅÓ¯ÈÓ­»Õ¯¾Õ­±Ô¯´Ô­Õ­Õ¯µÓ¯¸Ó­©Ó¯¬Ó­Ó¯Ó­Ó¯Ó­Ó­Ó¯Ó­Ó¯àÒ­áÒ¯ÌÒ­ÍÒ¯´Ò­µÒ¯¢Ò­£Ò¯Ò­Ò¯Ò­Ò¯Ò­Ò¯äÑ­åÑ¯ÎÑ­ÏÑ¯ÂÑ­ÃÑ¯¸Ñ­¹Ñ¯¶Ñ­·Ñ¯§ÑéÑçüÐçýÐéóÐéöÐçþÐçÿÐéñÐéôÐçÃÑéÆÑçîÐçïÐéëÐéîÐç¨Ñç©ÑéÛÐéÞÐçØÐçÙÐéÖÐç×ÐéÔÐçÕÐé÷ÑéúÑç½ÐéÀÐç³Ðé¶Ðç©Òé¬ÒçÑé¢ÑçúÑçûÑé£Ðé¦ÐçÐéÐçÐéÐçýÏéÐçöÏç÷ÏéîÏçïÏéÎÏçÏÏéºÏç»Ïé¢Ïç£ÏéÏçÏéüÎçýÎéòÎçóÎéîÎçïÎéÒÎçÓÎé¼Îç½Îé°Îç±Îé¦Îç§Îé¤Îç¥Îé§ïÍ£òÍ¡êÍ¡ëÍ£áÍ£äÍ¡ìÍ¡íÍ£ßÍ£âÍ¡±Î£´Î¡ÜÍ¡ÝÍ£ÙÍ£ÜÍ¡Î¡Î£ÉÍ£ÌÍ¡ÆÍ¡ÇÍ£ÄÍ¡ÅÍ£ÂÍ¡ÃÍ£åÎ£èÎ¡«Í£®Í¡¡Í£¤Í¡Ï£Ï¡Î£Î¡èÎ¡éÎ£Í£Í¡Í£Í¡ñÌ£ôÌ¡ëÌ£îÌ¡äÌ¡åÌ£ÜÌ¡ÝÌ£¼Ì¡½Ì£¨Ì¡©Ì£Ì¡Ì£þË¡ÿË£êË¡ëË£àË¡áË£ÜË¡ÝË£ÀË¡ÁË£ªË¡«Ë£Ë¡Ë£Ë¡Ë£Ë¡Ë£§ÝÊÝ àÊÛ ØÊÛ ÙÊÝ ÏÊÝ ÒÊÛ ÚÊÛ ÛÊÝ ÍÊÝ ÐÊÛ ËÝ ¢ËÛ ÊÊÛ ËÊÝ ÇÊÝ ÊÊÛ ËÛ ËÝ ·ÊÝ ºÊÛ ´ÊÛ µÊÝ ²ÊÛ ³ÊÝ °ÊÛ ±ÊÝ ÓËÝ ÖËÛ ÊÝ ÊÛ ÊÝ ÊÛ ÌÝ ÌÛ ûÊÝ þÊÛ ÖËÛ ×ËÝ ÿÉÝ ÊÛ óÉÝ öÉÛ ßÉÝ âÉÛ ÙÉÝ ÜÉÛ ÒÉÛ ÓÉÝ ÊÉÛ ËÉÝ ªÉÛ «ÉÝ ÉÛ ÉÝ þÈÛ ÿÈÝ ìÈÛ íÈÝ ØÈÛ ÙÈÝ ÎÈÛ ÏÈÝ ÊÈÛ ËÈÝ ®ÈÛ ¯ÈÝ ÈÛ ÈÝ ÈÛ ÈÝ ÈÛ ÈÝ ÈÛ ÈÝ §ËÇ&ÎÇ&ÆÇ&ÇÇ&½Ç&ÀÇ&ÈÇ&ÉÇ&»Ç&¾Ç&È&È&¸Ç&¹Ç&µÇ&¸Ç&òÇ&óÇ&¥Ç&¨Ç&¢Ç&£Ç& Ç&¡Ç&Ç&Ç&ÁÈ&ÄÈ&Ç&Ç&ýÆ&Ç&óÈ&öÈ&éÇ&ìÇ&ÄÈ&ÅÈ&íÆ&ðÆ&áÆ&äÆ&ÍÆ&ÐÆ&ÇÆ&ÊÆ&ÀÆ&ÁÆ&¸Æ&¹Æ&Æ&Æ&Æ&Æ&ìÅ&íÅ&ÚÅ&ÛÅ&ÆÅ&ÇÅ&¼Å&½Å&¸Å&¹Å&Å&Å&Å&Å&úÄ&ûÄ&ðÄ&ñÄ&îÄ&ïÄ&§¹ÄÑ+¼ÄÏ+´ÄÏ+µÄÑ+«ÄÑ+®ÄÏ+¶ÄÏ+·ÄÑ+©ÄÑ+¬ÄÏ+ûÄÑ+þÄÏ+¦ÄÏ+§ÄÑ+£ÄÑ+¦ÄÏ+àÄÏ+áÄÑ+ÄÑ+ÄÏ+ÄÏ+ÄÑ+ÄÏ+ÄÑ+ÄÏ+ÄÑ+¯ÅÑ+²ÅÏ+õÃÑ+øÃÏ+ëÃÑ+îÃÏ+áÅÑ+äÅÏ+×ÄÑ+ÚÄÏ+²ÅÏ+³ÅÑ+ÛÃÑ+ÞÃÏ+ÏÃÑ+ÒÃÏ+»ÃÑ+¾ÃÏ+µÃÑ+¸ÃÏ+®ÃÏ+¯ÃÑ+¦ÃÏ+§ÃÑ+ÃÏ+ÃÑ+òÂÏ+óÂÑ+ÚÂÏ+ÛÂÑ+ÈÂÏ+ÉÂÑ+´ÂÏ+µÂÑ+ªÂÏ+«ÂÑ+¦ÂÏ+§ÂÑ+ÂÏ+ÂÑ+ôÁÏ+õÁÑ+èÁÏ+éÁÑ+ÞÁÏ+ßÁÑ+ÜÁÏ+ÝÁÑ+§§Á1ªÁ1¢Á1£Á1Á1Á1¤Á1¥Á1Á1Á1éÁ1ìÁ1Á1Á1Á1Á1ÎÁ1ÏÁ1Á1Á1þÀ1ÿÀ1üÀ1ýÀ1úÀ1ûÀ1Â1 Â1ãÀ1æÀ1ÙÀ1ÜÀ1ÏÂ1ÒÂ1ÅÁ1ÈÁ1 Â1¡Â1ÉÀ1ÌÀ1½À1ÀÀ1©À1¬À1£À1¦À1À1À1À1À1ô¿1õ¿1à¿1á¿1È¿1É¿1¶¿1·¿1¢¿1£¿1¿1¿1¿1¿1ø¾1ù¾1â¾1ã¾1Ö¾1×¾1Ì¾1Í¾1Ê¾1Ë¾1§¾Å6¾Ã6¾Ã6¾Å6¾Å6¾Ã6¾Ã6¾Å6¾Å6¾Ã6×¾Å6Ú¾Ã6¾Ã6¾Å6ÿ½Å6¾Ã6¼¾Ã6½¾Å6ï½Å6ò½Ã6ì½Ã6í½Å6ê½Ã6ë½Å6è½Ã6é½Å6¿Å6¿Ã6Ñ½Å6Ô½Ã6Ç½Å6Ê½Ã6½¿Å6À¿Ã6³¾Å6¶¾Ã6¿Ã6¿Å6·½Å6º½Ã6«½Å6®½Ã6½Å6½Ã6½Å6½Ã6½Ã6½Å6½Ã6½Å6â¼Ã6ã¼Å6Î¼Ã6Ï¼Å6¶¼Ã6·¼Å6¤¼Ã6¥¼Å6¼Ã6¼Å6¼Ã6¼Å6¼Ã6¼Å6æ»Ã6ç»Å6Ð»Ã6Ñ»Å6Ä»Ã6Å»Å6º»Ã6»»Å6¸»Ã6¹»Å6§»ÿ;»ý;þºý;ÿºÿ;õºÿ;øºý;»ý;»ÿ;óºÿ;öºý;Å»ÿ;È»ý;ðºý;ñºÿ;íºÿ;ðºý;ª»ý;«»ÿ;Ýºÿ;àºý;Úºý;Ûºÿ;Øºý;Ùºÿ;Öºý;×ºÿ;ù»ÿ;ü»ý;¿ºÿ;Âºý;µºÿ;¸ºý;«¼ÿ;®¼ý;¡»ÿ;¤»ý;ü»ý;ý»ÿ;¥ºÿ;¨ºý;ºÿ;ºý;ºÿ;ºý;ÿ¹ÿ;ºý;ø¹ý;ù¹ÿ;ð¹ý;ñ¹ÿ;Ð¹ý;Ñ¹ÿ;¼¹ý;½¹ÿ;¤¹ý;¥¹ÿ;¹ý;¹ÿ;þ¸ý;ÿ¸ÿ;ô¸ý;õ¸ÿ;ð¸ý;ñ¸ÿ;Ô¸ý;Õ¸ÿ;¾¸ý;¿¸ÿ;²¸ý;³¸ÿ;¨¸ý;©¸ÿ;¦¸ý;§¸ÿ;§ñ·¹Aô··Aì··Aí·¹Aã·¹Aæ··Aî··Aï·¹Aá·¹Aä··A³¸¹A¶¸·AÞ··Aß·¹AÛ·¹AÞ··A¸·A¸¹AË·¹AÎ··AÈ··AÉ·¹AÆ··AÇ·¹AÄ··AÅ·¹Aç¸¹Aê¸·A­·¹A°··A£·¹A¦··A¹¹A¹·A¸¹A¸·Aê¸·Aë¸¹A·¹A··A·¹A··Aó¶¹Aö¶·Aí¶¹Að¶·Aæ¶·Aç¶¹AÞ¶·Aß¶¹A¾¶·A¿¶¹Aª¶·A«¶¹A¶·A¶¹A¶·A¶¹Aìµ·Aíµ¹Aâµ·Aãµ¹AÞµ·Aßµ¹AÂµ·AÃµ¹A¬µ·A­µ¹A µ·A¡µ¹Aµ·Aµ¹Aµ·Aµ¹A§ß´óFâ´ñFÚ´ñFÛ´óFÑ´óFÔ´ñFÜ´ñFÝ´óFÏ´óFÒ´ñF¡µóF¤µñFÌ´ñFÍ´óFÉ´óFÌ´ñFµñFµóF¹´óF¼´ñF¶´ñF·´óF´´ñFµ´óF²´ñF³´óFÕµóFØµñF´óF´ñF´óF´ñF¶óF¶ñFý´óFµñFØµñFÙµóF´óF´ñFõ³óFø³ñFá³óFä³ñFÛ³óFÞ³ñFÔ³ñFÕ³óFÌ³ñFÍ³óF¬³ñF­³óF³ñF³óF³ñF³óFî²ñFï²óFÚ²ñFÛ²óFÐ²ñFÑ²óFÌ²ñFÍ²óF°²ñF±²óF²ñF²óF²ñF²óF²ñF²óF²ñF²óF§Í±­LÐ±«LÈ±«LÉ±­L¿±­LÂ±«LÊ±«LË±­L½±­LÀ±«L²­L²«Lº±«L»±­L·±­Lº±«Lô±«Lõ±­L§±­Lª±«L¤±«L¥±­L¢±«L£±­L ±«L¡±­LÃ²­LÆ²«L±­L±«Lÿ°­L±«Lõ²­Lø²«Lë±­Lî±«LÆ²«LÇ²­Lï°­Lò°«Lã°­Læ°«LÏ°­LÒ°«LÉ°­LÌ°«LÂ°«LÃ°­Lº°«L»°­L°«L°­L°«L°­Lî¯«Lï¯­LÜ¯«LÝ¯­LÈ¯«LÉ¯­L¾¯«L¿¯­Lº¯«L»¯­L¯«L¯­L¯«L¯­Lü®«Lý®­Lò®«Ló®­Lð®«Lñ®­L§»®çQ¾®åQ¶®åQ·®çQ­®çQ°®åQ¸®åQ¹®çQ«®çQ®®åQý®çQ¯åQ¨®åQ©®çQ¥®çQ¨®åQâ®åQã®çQ®çQ®åQ®åQ®çQ®åQ®çQ®åQ®çQ±¯çQ´¯åQ÷­çQú­åQí­çQð­åQã¯çQæ¯åQÙ®çQÜ®åQ´¯åQµ¯çQÝ­çQà­åQÑ­çQÔ­åQ½­çQÀ­åQ·­çQº­åQ°­åQ±­çQ¨­åQ©­çQ­åQ­çQô¬åQõ¬çQÜ¬åQÝ¬çQÊ¬åQË¬çQ¶¬åQ·¬çQ¬¬åQ­¬çQ¨¬åQ©¬çQ¬åQ¬çQö«åQ÷«çQê«åQë«çQà«åQá«çQÞ«åQß«çQ§©«¡W¬«W¤«W¥«¡W«¡W«W¦«W§«¡W«¡W«Wë«¡Wî«W«W«¡W«¡W«WÐ«WÑ«¡W«¡W«W«W«¡WþªWÿª¡WüªWýª¡W¬¡W¢¬Wåª¡WèªWÛª¡WÞªWÑ¬¡WÔ¬WÇ«¡WÊ«W¢¬W£¬¡WËª¡WÎªW¿ª¡WÂªW«ª¡W®ªW¥ª¡W¨ªWªWª¡WªWª¡Wö©W÷©¡Wâ©Wã©¡WÊ©WË©¡W¸©W¹©¡W¤©W¥©¡W©W©¡W©W©¡Wú¨Wû¨¡Wä¨Wå¨¡WØ¨WÙ¨¡WÎ¨WÏ¨¡WÌ¨WÍ¨¡W§¨Û\¨Ù\¨Ù\¨Û\¨Û\¨Ù\¨Ù\¨Û\¨Û\¨Ù\Ù¨Û\Ü¨Ù\¨Ù\¨Û\¨Û\¨Ù\¾¨Ù\¿¨Û\ñ§Û\ô§Ù\î§Ù\ï§Û\ì§Ù\í§Û\ê§Ù\ë§Û\©Û\©Ù\Ó§Û\Ö§Ù\É§Û\Ì§Ù\¿©Û\Â©Ù\µ¨Û\¸¨Ù\©Ù\©Û\¹§Û\¼§Ù\­§Û\°§Ù\§Û\§Ù\§Û\§Ù\§Ù\§Û\§Ù\§Û\ä¦Ù\å¦Û\Ð¦Ù\Ñ¦Û\¸¦Ù\¹¦Û\¦¦Ù\§¦Û\¦Ù\¦Û\¦Ù\¦Û\¦Ù\¦Û\è¥Ù\é¥Û\Ò¥Ù\Ó¥Û\Æ¥Ù\Ç¥Û\¼¥Ù\½¥Û\º¥Ù\»¥Û\§¥b¥b¥b¥b÷¤bú¤b¥b¥bõ¤bø¤bÇ¥bÊ¥bò¤bó¤bï¤bò¤b¬¥b­¥bß¤bâ¤bÜ¤bÝ¤bÚ¤bÛ¤bØ¤bÙ¤bû¥bþ¥bÁ¤bÄ¤b·¤bº¤b­¦b°¦b£¥b¦¥bþ¥bÿ¥b§¤bª¤b¤b¤b¤b¤b¤b¤bú£bû£bò£bó£bÒ£bÓ£b¾£b¿£b¦£b§£b£b£b£b£bö¢b÷¢bò¢bó¢bÖ¢b×¢bÀ¢bÁ¢b´¢bµ¢bª¢b«¢b¨¢b©¢b§ó¡Ïgö¡Ígî¡Ígï¡Ïgå¡Ïgè¡Ígð¡Ígñ¡Ïgã¡Ïgæ¡Ígµ¢Ïg¸¢Ígà¡Ígá¡ÏgÝ¡Ïgà¡Íg¢Íg¢ÏgÍ¡ÏgÐ¡ÍgÊ¡ÍgË¡ÏgÈ¡ÍgÉ¡ÏgÆ¡ÍgÇ¡Ïgé¢Ïgì¢Íg¯¡Ïg²¡Íg¥¡Ïg¨¡Íg£Ïg£Íg¢Ïg¢Ígì¢Ígí¢Ïg¡Ïg¡Íg¡Ïg¡Ígõ Ïgø Ígï Ïgò Ígè Ígé Ïgà Ígá ÏgÀ ÍgÁ Ïg¬ Íg­ Ïg Íg Ïg Íg ÏgîÍgïÏgäÍgåÏgàÍgáÏgÄÍgÅÏg®Íg¯Ïg¢Íg£ÏgÍgÏgÍgÏg§ámämÜmÝmÓmÖmÞmßmÑmÔm£m¦mÎmÏmËmÎmmm»m¾m¸m¹m¶m·m´mµm×mÚmm mmm m mÿmmÚmÛmmm÷múmãmæmÝmàmÖm×mÎmÏm®m¯mmmmmðmñmÜmÝmÒmÓmÎmÏm²m³mmmmmmmmm§ÏÃrÒÁrÊÁrËÃrÁÃrÄÁrÌÁrÍÃr¿ÃrÂÁrÃrÁr¼Ár½Ãr¹Ãr¼ÁröÁr÷Ãr©Ãr¬Ár¦Ár§Ãr¤Ár¥Ãr¢Ár£ÃrÅÃrÈÁrÃrÁrÃrÁr÷ÃrúÁríÃrðÁrÈÁrÉÃrñÃrôÁråÃrèÁrÑÃrÔÁrËÃrÎÁrÄÁrÅÃr¼Ár½ÃrÁrÃrÁrÃrðÁrñÃrÞÁrßÃrÊÁrËÃrÀÁrÁÃr¼Ár½Ãr Ár¡ÃrÁrÃrþÁrÿÃrôÁrõÃròÁróÃr§½ýwÀûw¸ûw¹ýw¯ýw²ûwºûw»ýw­ýw°ûwÿýwûwªûw«ýw§ýwªûwäûwåýwýwûwûwýwûwýwûwýw³ýw¶ûwùýwüûwïýwòûwåýwèûwÛýwÞûw¶ûw·ýwßýwâûwÓýwÖûw¿ýwÂûw¹ýw¼ûw²ûw³ýwªûw«ýwûwýwöûw÷ýwÞûwßýwÌûwÍýw¸ûw¹ýw®ûw¯ýwªûw«ýwûwýwøûwùýwìûwíýwâûwãýwàûwáýw§«·}®µ}¦µ}§·}·} µ}¨µ}©·}·}µ}í·}ðµ}µ}·}·}µ}Òµ}Ó·}·}µ}µ}·}µ}·}þµ}ÿ·}¡·}¤µ}ç·}êµ}Ý·}àµ}Ó·}Öµ}É·}Ìµ}¤µ}¥·}Í·}Ðµ}Á·}Äµ}­·}°µ}§·}ªµ} µ}¡·}µ}·}øµ}ù·}äµ}å·}Ìµ}Í·}ºµ}»·}¦µ}§·}µ}·}µ}·}üµ}ý·}æµ}ç·}Úµ}Û·}Ðµ}Ñ·}Îµ}Ï·}§ñïïññïïññïÛñÞïïññïÀïÁñóñöïðïññîïïñìïíññïÕñØïËñÎïÁñÄï·ñºïïñ»ñ¾ï¯ñ²ïñïñïïñïñæïçñÒïÓñºï»ñ¨ï©ñïñïñïñêïëñÔïÕñÈïÉñ¾ï¿ñ¼ï½ñ§«©©«ù«ü©©«÷«ú©É«Ì©ô©õ«ñ«ô©®©¯«á«ä©Þ©ß«Ü©Ý«Ú©Û«ý«©Ã«Æ©¹«¼©¯«²©¥«¨©©«©«¬©« ©«©«©ü©ý«ô©õ«Ô©Õ«À©Á«¨©©«©«©«ø©ù«ô©õ«Ø©Ù«Â©Ã«¶©·«¬©­«ª©««§õåøãðãñåçåêãòãóåååèã·åºãâããåßåâããåÏåÒãÌãÍåÊãËåÈãÉåëåîã±å´ã§åªãå ãåãîãïååãåã÷åúãñåôãêãëåâããåÂãÃå®ã¯åãåãåðãñåæãçåâããåÆãÇå°ã±å¤ã¥åãåãå§ãæÞßÕØàáÓÖ¥¨ÐÑÍÐ½Àº»¸¹¶·ÙÜ¢ÜÝùüåèßâØÙÐÑ°±òóÞßÔÕÐÑ´µ§ÑÙÔ×Ì×ÍÙÃÙÆ×Î×ÏÙÁÙÄ×Ù×¾×¿Ù»Ù¾×ø×ùÙ«Ù®×¨×©Ù¦×§Ù¤×¥ÙÇÙÊ×Ù×Ù×ùÙü×ïÙò×Ê×ËÙóÙö×çÙê×ÓÙÖ×ÍÙÐ×Æ×ÇÙ¾×¿Ù×Ù×Ùò×óÙà×áÙÌ×ÍÙÂ×ÃÙ¾×¿Ù¢×£Ù×Ù×Ùö×÷Ùô×õÙ§¿Âº»±´¼½¯²¬­©¬æçµ¸ûþñôçêÝà¸¹áäÕØÁÄ»¾´µ¬­øùàáÎÏº»°±¬­úÿûÿîÿïÿäÿåÿâÿãÿ§­ÿÍ£°ÿË£¨ÿË£©ÿÍ£ÿÍ£¢ÿË£ªÿË£«ÿÍ£ÿÍ£ ÿË£ïÿÍ£òÿË£ÿË£ÿÍ£ÿÍ£ÿË£ÔÿË£ÕÿÍ£ÿÍ£ÿË£ÿË£ÿÍ£ÿË£ÿÍ£ÿË£ÿÍ££Í£¦Ë£éþÍ£ìþË£ßþÍ£âþË£ÕÍ£ØË£ËÿÍ£ÎÿË£¦Ë£§Í£ÏþÍ£ÒþË£ÃþÍ£ÆþË£¯þÍ£²þË£©þÍ£¬þË£¢þË££þÍ£þË£þÍ£úýË£ûýÍ£æýË£çýÍ£ÎýË£ÏýÍ£¼ýË£½ýÍ£¨ýË£©ýÍ£ýË£ýÍ£ýË£ýÍ£þüË£ÿüÍ£èüË£éüÍ£ÜüË£ÝüÍ£ÒüË£ÓüÍ£ÐüË£ÑüÍ£§ü©ü©ü©ü©ü©ü©ü©ü©ü©ü©Ýü©àü©ü©ü©ü©ü©Âü©Ãü©õû©øû©òû©óû©ðû©ñû©îû©ïû©ý©ý©×û©Úû©Íû©Ðû©Ãý©Æý©¹ü©¼ü©ý©ý©½û©Àû©±û©´û©û© û©û©û©û©û©û©û©èú©éú©Ôú©Õú©¼ú©½ú©ªú©«ú©ú©ú©ú©ú©ú©ú©ìù©íù©Öù©×ù©Êù©Ëù©Àù©Áù©¾ù©¿ù©§ùÁ®ù¿®ù¿®ùÁ®ûøÁ®þø¿®ù¿®ùÁ®ùøÁ®üø¿®ËùÁ®Îù¿®öø¿®÷øÁ®óøÁ®öø¿®°ù¿®±ùÁ®ãøÁ®æø¿®àø¿®áøÁ®Þø¿®ßøÁ®Üø¿®ÝøÁ®ÿùÁ®ú¿®ÅøÁ®Èø¿®»øÁ®¾ø¿®±úÁ®´ú¿®§ùÁ®ªù¿®ú¿®úÁ®«øÁ®®ø¿®øÁ®¢ø¿®øÁ®ø¿®øÁ®ø¿®þ÷¿®ÿ÷Á®ö÷¿®÷÷Á®Ö÷¿®×÷Á®Â÷¿®Ã÷Á®ª÷¿®«÷Á®÷¿®÷Á®÷¿®÷Á®úö¿®ûöÁ®öö¿®÷öÁ®Úö¿®ÛöÁ®Äö¿®ÅöÁ®¸ö¿®¹öÁ®®ö¿®¯öÁ®¬ö¿®­öÁ®§÷õû³úõù³òõù³óõû³éõû³ìõù³ôõù³õõû³çõû³êõù³¹öû³¼öù³äõù³åõû³áõû³äõù³öù³öû³Ñõû³Ôõù³Îõù³Ïõû³Ìõù³Íõû³Êõù³Ëõû³íöû³ðöù³³õû³¶õù³©õû³¬õù³÷û³¢÷ù³öû³öù³ðöù³ñöû³õû³õù³õû³õù³ùôû³üôù³óôû³öôù³ìôù³íôû³äôù³åôû³Äôù³Åôû³°ôù³±ôû³ôù³ôû³ôù³ôû³òóù³óóû³èóù³éóû³äóù³åóû³Èóù³Éóû³²óù³³óû³¦óù³§óû³óù³óû³óù³óû³§åòµ¹èò³¹àò³¹áòµ¹×òµ¹Úò³¹âò³¹ãòµ¹Õòµ¹Øò³¹§óµ¹ªó³¹Òò³¹Óòµ¹Ïòµ¹Òò³¹ó³¹óµ¹¿òµ¹Âò³¹¼ò³¹½òµ¹ºò³¹»òµ¹¸ò³¹¹òµ¹Ûóµ¹Þó³¹¡òµ¹¤ò³¹òµ¹ò³¹ôµ¹ô³¹óµ¹ó³¹Þó³¹ßóµ¹òµ¹ò³¹ûñµ¹þñ³¹çñµ¹êñ³¹áñµ¹äñ³¹Úñ³¹Ûñµ¹Òñ³¹Óñµ¹²ñ³¹³ñµ¹ñ³¹ñµ¹ñ³¹ñµ¹ôð³¹õðµ¹àð³¹áðµ¹Öð³¹×ðµ¹Òð³¹Óðµ¹¶ð³¹·ðµ¹ ð³¹¡ðµ¹ð³¹ðµ¹ð³¹ðµ¹ð³¹ðµ¹§Óïï¾Öïí¾Îïí¾Ïïï¾Åïï¾Èïí¾Ðïí¾Ñïï¾Ãïï¾Æïí¾ðï¾ðí¾Àïí¾Áïï¾½ïï¾Àïí¾úïí¾ûïï¾­ïï¾°ïí¾ªïí¾«ïï¾¨ïí¾©ïï¾¦ïí¾§ïï¾Éðï¾Ìðí¾ïï¾ïí¾ïï¾ïí¾ûðï¾þðí¾ñïï¾ôïí¾Ìðí¾Íðï¾õîï¾øîí¾éîï¾ìîí¾Õîï¾Øîí¾Ïîï¾Òîí¾Èîí¾Éîï¾Àîí¾Áîï¾ îí¾¡îï¾îí¾îï¾ôíí¾õíï¾âíí¾ãíï¾Îíí¾Ïíï¾Äíí¾Åíï¾Àíí¾Áíï¾¤íí¾¥íï¾íí¾íï¾íí¾íï¾øìí¾ùìï¾öìí¾÷ìï¾§Áì©ÄÄì§Ä¼ì§Ä½ì©Ä³ì©Ä¶ì§Ä¾ì§Ä¿ì©Ä±ì©Ä´ì§Äí©Äí§Ä®ì§Ä¯ì©Ä«ì©Ä®ì§Äèì§Äéì©Äì©Äì§Äì§Äì©Äì§Äì©Äì§Äì©Ä·í©Äºí§Äýë©Äì§Äóë©Äöë§Äéí©Äìí§Äßì©Äâì§Äºí§Ä»í©Äãë©Äæë§Ä×ë©ÄÚë§ÄÃë©ÄÆë§Ä½ë©ÄÀë§Ä¶ë§Ä·ë©Ä®ë§Ä¯ë©Äë§Äë©Äúê§Äûê©Äâê§Äãê©ÄÐê§ÄÑê©Ä¼ê§Ä½ê©Ä²ê§Ä³ê©Ä®ê§Ä¯ê©Äê§Äê©Äüé§Äýé©Äðé§Äñé©Äæé§Äçé©Ääé§Äåé©Ä§¯éãÉ²éáÉªéáÉ«éãÉ¡éãÉ¤éáÉ¬éáÉ­éãÉéãÉ¢éáÉñéãÉôéáÉéáÉéãÉéãÉéáÉÖéáÉ×éãÉéãÉéáÉéáÉéãÉéáÉéãÉéáÉéãÉ¥êãÉ¨êáÉëèãÉîèáÉáèãÉäèáÉ×êãÉÚêáÉÍéãÉÐéáÉ¨êáÉ©êãÉÑèãÉÔèáÉÅèãÉÈèáÉ±èãÉ´èáÉ«èãÉ®èáÉ¤èáÉ¥èãÉèáÉèãÉüçáÉýçãÉèçáÉéçãÉÐçáÉÑçãÉ¾çáÉ¿çãÉªçáÉ«çãÉ çáÉ¡çãÉçáÉçãÉçáÉçãÉêæáÉëæãÉÞæáÉßæãÉÔæáÉÕæãÉÒæáÉÓæãÉ§Åª»Èª¹Àª¹Áª»·ª»ºª¹Âª¹Ãª»µª»¸ª¹«»«¹²ª¹³ª»¯ª»²ª¹ìª¹íª»ª»¢ª¹ª¹ª»ª¹ª»ª¹ª»»«»¾«¹ª»ª¹÷©»ú©¹í«»ð«¹ãª»æª¹¾«¹¿«»ç©»ê©¹Û©»Þ©¹Ç©»Ê©¹Á©»Ä©¹º©¹»©»²©¹³©»©¹©»þ¨¹ÿ¨»æ¨¹ç¨»Ô¨¹Õ¨»À¨¹Á¨»¶¨¹·¨»²¨¹³¨»¨¹¨»¨¹¨»ô§¹õ§»ê§¹ë§»è§¹é§»§³§õ
+¶§ó
+®§ó
+¯§õ
+¥§õ
+¨§ó
+°§ó
+±§õ
+£§õ
+¦§ó
+õ§õ
+ø§ó
+ §ó
+¡§õ
+§õ
+ §ó
+Ú§ó
+Û§õ
+§õ
+§ó
+§ó
+§õ
+§ó
+§õ
+§ó
+§õ
+©¨õ
+¬¨ó
+ï¦õ
+ò¦ó
+å¦õ
+è¦ó
+Û¨õ
+Þ¨ó
+Ñ§õ
+Ô§ó
+¬¨ó
+­¨õ
+Õ¦õ
+Ø¦ó
+É¦õ
+Ì¦ó
+µ¦õ
+¸¦ó
+¯¦õ
+²¦ó
+¨¦ó
+©¦õ
+ ¦ó
+¡¦õ
+¦ó
+¦õ
+ì¥ó
+í¥õ
+Ô¥ó
+Õ¥õ
+Â¥ó
+Ã¥õ
+®¥ó
+¯¥õ
+¤¥ó
+¥¥õ
+ ¥ó
+¡¥õ
+¥ó
+¥õ
+î¤ó
+ï¤õ
+â¤ó
+ã¤õ
+Ø¤ó
+Ù¤õ
+Ö¤ó
+×¤õ
+§¡¤¯¤¤­¤­¤¯¤¯¤­¤­¤¯¤¯¤­ã¤¯æ¤­¤­¤¯¤¯¤­È¤­É¤¯û£¯þ£­ø£­ù£¯ö£­÷£¯ô£­õ£¯¥¯¥­Ý£¯à£­Ó£¯Ö£­É¥¯Ì¥­¿¤¯Â¤­¥­¥¯Ã£¯Æ£­·£¯º£­££¯¦£­£¯ £­£­£¯£­£¯î¢­ï¢¯Ú¢­Û¢¯Â¢­Ã¢¯°¢­±¢¯¢­¢¯¢­¢¯¢­¢¯ò¡­ó¡¯Ü¡­Ý¡¯Ð¡­Ñ¡¯Æ¡­Ç¡¯Ä¡­Å¡¯§¡é¡ç¡ç¡é¡é¡ç¡ç¡éÿ é¡çÑ¡éÔ¡çü çý éù éü ç¶¡ç·¡éé éì çæ çç éä çå éâ çã é¢é¢çË éÎ çÁ éÄ ç·¢éº¢ç­¡é°¡ç¢ç¢é± é´ ç¥ é¨ ç é ç é ç ç éüçýéÜçÝéÈçÉé°ç±éçéçéçéüçýéàçáéÊçËé¾ç¿é´çµé²ç³é§ý£¡ø¡ù£ï£ò¡ú¡û£í£ð¡¿£Â¡ê¡ë£ç£ê¡¤¡¥£×£Ú¡Ô¡Õ£Ò¡Ó£Ð¡Ñ£ó£ö¡¹£¼¡¯£²¡¥£¨¡£¡ö¡÷££¢¡£¡ÿ£¡ù£ü¡ò¡ó£ê¡ë£Ê¡Ë£¶¡·£¡£¡£ø¡ù£î¡ï£ê¡ë£Î¡Ï£¸¡¹£¬¡­£¢¡££ ¡¡£§ëÝ îÛ æÛ çÝ ÝÝ àÛ èÛ éÝ ÛÝ ÞÛ ­Ý °Û ØÛ ÙÝ ÕÝ ØÛ Û Ý ÅÝ ÈÛ ÂÛ ÃÝ ÀÛ ÁÝ ¾Û ¿Ý áÝ äÛ §Ý ªÛ Ý  Û Ý Û Ý Û äÛ åÝ Ý Û Ý Û íÝ ðÛ çÝ êÛ àÛ áÝ ØÛ ÙÝ ¸Û ¹Ý ¤Û ¥Ý Û Ý úÛ ûÝ æÛ çÝ ÜÛ ÝÝ ØÛ ÙÝ ¼Û ½Ý ¦Û §Ý Û Ý Û Ý Û Ý §Ù&Ü&Ô&Õ&Ë&Î&Ö&×&É&Ì&&&Æ&Ç&Ã&Æ&&&³&¶&°&±&®&¯&¬&­&Ï&Ò&&&&&&&÷&ú&Ò&Ó&û&þ&ï&ò&Û&Þ&Õ&Ø&Î&Ï&Æ&Ç&¦&§&&&ú&û&è&é&Ô&Õ&Ê&Ë&Æ&Ç&ª&«&&&&&þ&ÿ&ü&ý&§ÇÑ+ÊÏ+ÂÏ+ÃÑ+¹Ñ+¼Ï+ÄÏ+ÅÑ+·Ñ+ºÏ+Ñ+Ï+´Ï+µÑ+±Ñ+´Ï+îÏ+ïÑ+¡Ñ+¤Ï+Ï+Ñ+Ï+Ñ+Ï+Ñ+½Ñ+ÀÏ+Ñ+Ï+ùÑ+üÏ+ïÑ+òÏ+åÑ+èÏ+ÀÏ+ÁÑ+éÑ+ìÏ+ÝÑ+àÏ+ÉÑ+ÌÏ+ÃÑ+ÆÏ+¼Ï+½Ñ+´Ï+µÑ+Ï+Ñ+Ï+Ñ+èÏ+éÑ+ÖÏ+×Ñ+ÂÏ+ÃÑ+¸Ï+¹Ñ+´Ï+µÑ+Ï+Ñ+Ï+Ñ+öÏ+÷Ñ+ìÏ+íÑ+êÏ+ëÑ+§µ1¸1°1±1§1ª1²1³1¥1¨1÷1ú1¢1£11¢1Ü1Ý111111111«1®1ñ1ô1ç1ê1Ý1à1Ó1Ö1®1¯1×1Ú1Ë1Î1·1º1±1´1ª1«1¢1£111î1ï1Ö1×1Ä1Å1°1±1¦1§1¢1£111ð1ñ1ä1å1Ú1Û1Ø1Ù1§£Å6¦Ã6Ã6Å6Å6Ã6 Ã6¡Å6Å6Ã6åÅ6èÃ6Ã6Å6Å6Ã6ÊÃ6ËÅ6ýÅ6Ã6úÃ6ûÅ6øÃ6ùÅ6öÃ6÷Å6Å6Ã6ßÅ6âÃ6ÕÅ6ØÃ6ËÅ6ÎÃ6ÁÅ6ÄÃ6Ã6Å6ÅÅ6ÈÃ6¹Å6¼Ã6¥Å6¨Ã6Å6¢Ã6Ã6Å6Ã6Å6ðÃ6ñÅ6ÜÃ6ÝÅ6ÄÃ6ÅÅ6²Ã6³Å6Ã6Å6Ã6Å6Ã6Å6ôÃ6õÅ6ÞÃ6ßÅ6ÒÃ6ÓÅ6ÈÃ6ÉÅ6ÆÃ6ÇÅ6§ÿ;ý;ý;ÿ;ÿ;ý;ý;ÿ;ÿ;ý;Óÿ;Öý;þý;ÿÿ;ûÿ;þý;¸ý;¹ÿ;ëÿ;îý;èý;éÿ;æý;çÿ;äý;åÿ;ÿ;ý;Íÿ;Ðý;Ãÿ;Æý;¹ÿ;¼ý;¯ÿ;²ý;ý;ÿ;³ÿ;¶ý;§ÿ;ªý;ÿ;ý;ÿ;ý;ý;ÿ;þý;ÿÿ;Þý;ßÿ;Êý;Ëÿ;²ý;³ÿ; ý;¡ÿ;ý;ÿ;ý;ÿ;þý;ÿÿ;âý;ãÿ;Ìý;Íÿ;Àý;Áÿ;¶ý;·ÿ;´ý;µÿ;§ÿ¹A·Aú·Aû¹Añ¹Aô·Aü·Aý¹Aï¹Aò·AÁ¹AÄ·Aì·Aí¹Aé¹Aì·A¦·A§¹AÙ¹AÜ·AÖ·A×¹AÔ·AÕ¹AÒ·AÓ¹Aõ¹Aø·A»¹A¾·A±¹A´·A§¹Aª·A¹A ·Aø·Aù¹A¡¹A¤·A¹A·A¹A·Aû¹Aþ·Aô·Aõ¹Aì·Aí¹AÌ·AÍ¹A¸·A¹¹A ·A¡¹A·A¹Aú·Aû¹Að·Añ¹Aì·Aí¹AÐ·AÑ¹Aº·A»¹A®·A¯¹A¤·A¥¹A¢·A£¹A§íóFðñFèñFéóFßóFâñFêñFëóFÝóFàñF¯óF²ñFÚñFÛóF×óFÚñFñFóFÇóFÊñFÄñFÅóFÂñFÃóFÀñFÁóFãóFæñF©óF¬ñFóF¢ñFóFñFóFñFæñFçóFóFñFóFñFïóFòñFéóFìñFâñFãóFÚñFÛóFºñF»óF¦ñF§óFñFóFüñFýóFèñFéóFÞñFßóFÚñFÛóF¾ñF¿óF¨ñF©óFñFóFñFóFñFóF§Û­LÞ«LÖ«L×­LÍ­LÐ«LØ«LÙ­LË­LÎ«L­L «LÈ«LÉ­LÅ­LÈ«L«L­Lµ­L¸«L²«L³­L°«L±­L®«L¯­LÑ­LÔ«L­L«L­L«L­L«Lù­Lü«LÔ«LÕ­Lý­L«Lñ­Lô«LÝ­Là«L×­LÚ«LÐ«LÑ­LÈ«LÉ­L¨«L©­L«L­Lüÿ«Lýÿ­Lêÿ«Lëÿ­LÖÿ«L×ÿ­LÌÿ«LÍÿ­LÈÿ«LÉÿ­L¬ÿ«L­ÿ­Lÿ«Lÿ­Lÿ«Lÿ­Lÿ«Lÿ­Lþþ«Lÿþ­L§ÉþçQÌþåQÄþåQÅþçQ»þçQ¾þåQÆþåQÇþçQ¹þçQ¼þåQÿçQÿåQ¶þåQ·þçQ³þçQ¶þåQðþåQñþçQ£þçQ¦þåQ þåQ¡þçQþåQþçQþåQþçQ¿ÿçQÂÿåQþçQþåQûýçQþýåQñÿçQôÿåQçþçQêþåQÂÿåQÃÿçQëýçQîýåQßýçQâýåQËýçQÎýåQÅýçQÈýåQ¾ýåQ¿ýçQ¶ýåQ·ýçQýåQýçQýåQýçQêüåQëüçQØüåQÙüçQÄüåQÅüçQºüåQ»üçQ¶üåQ·üçQüåQüçQüåQüçQøûåQùûçQîûåQïûçQìûåQíûçQ§·û¡WºûW²ûW³û¡W©û¡W¬ûW´ûWµû¡W§û¡WªûWùû¡WüûW¤ûW¥û¡W¡û¡W¤ûWÞûWßû¡Wû¡WûWûWû¡WûWû¡WûWû¡W­ü¡W°üWóú¡WöúWéú¡WìúWßü¡WâüWÕû¡WØûW°üW±ü¡WÙú¡WÜúWÍú¡WÐúW¹ú¡W¼úW³ú¡W¶úW¬úW­ú¡W¤úW¥ú¡WúWú¡WðùWñù¡WØùWÙù¡WÆùWÇù¡W²ùW³ù¡W¨ùW©ù¡W¤ùW¥ù¡WùWù¡WòøWóø¡WæøWçø¡WÜøWÝø¡WÚøWÛø¡W§¥øÛ\¨øÙ\ øÙ\¡øÛ\øÛ\øÙ\¢øÙ\£øÛ\øÛ\øÙ\çøÛ\êøÙ\øÙ\øÛ\øÛ\øÙ\ÌøÙ\ÍøÛ\ÿ÷Û\øÙ\ü÷Ù\ý÷Û\ú÷Ù\û÷Û\ø÷Ù\ù÷Û\ùÛ\ùÙ\á÷Û\ä÷Ù\×÷Û\Ú÷Ù\ÍùÛ\ÐùÙ\ÃøÛ\ÆøÙ\ùÙ\ùÛ\Ç÷Û\Ê÷Ù\»÷Û\¾÷Ù\§÷Û\ª÷Ù\¡÷Û\¤÷Ù\÷Ù\÷Û\÷Ù\÷Û\òöÙ\óöÛ\ÞöÙ\ßöÛ\ÆöÙ\ÇöÛ\´öÙ\µöÛ\ öÙ\¡öÛ\öÙ\öÛ\öÙ\öÛ\öõÙ\÷õÛ\àõÙ\áõÛ\ÔõÙ\ÕõÛ\ÊõÙ\ËõÛ\ÈõÙ\ÉõÛ\§õbõbõbõbõbõbõbõbõbõbÕõbØõbõbõbýôbõbºõb»õbíôbðôbêôbëôbèôbéôbæôbçôböböbÏôbÒôbÅôbÈôb»öb¾öb±õb´õböböbµôb¸ôb©ôb¬ôbôbôbôbôbôbôbôbôbàóbáóbÌóbÍób´óbµób¢ób£óbóbóbóbóbóbóbäòbåòbÎòbÏòbÂòbÃòb¸òb¹òb¶òb·òb§òÏgòÍgüñÍgýñÏgóñÏgöñÍgþñÍgÿñÏgññÏgôñÍgÃòÏgÆòÍgîñÍgïñÏgëñÏgîñÍg¨òÍg©òÏgÛñÏgÞñÍgØñÍgÙñÏgÖñÍg×ñÏgÔñÍgÕñÏg÷òÏgúòÍg½ñÏgÀñÍg³ñÏg¶ñÍg©óÏg¬óÍgòÏg¢òÍgúòÍgûòÏg£ñÏg¦ñÍgñÏgñÍgñÏgñÍgýðÏgñÍgöðÍg÷ðÏgîðÍgïðÏgÎðÍgÏðÏgºðÍg»ðÏg¢ðÍg£ðÏgðÍgðÏgüïÍgýïÏgòïÍgóïÏgîïÍgïïÏgÒïÍgÓïÏg¼ïÍg½ïÏg°ïÍg±ïÏg¦ïÍg§ïÏg¤ïÍg¥ïÏg§ïîmòîmêîmëîmáîmäîmìîmíîmßîmâîm±ïm´ïmÜîmÝîmÙîmÜîmïmïmÉîmÌîmÆîmÇîmÄîmÅîmÂîmÃîmåïmèïm«îm®îm¡îm¤îmðmðmïmïmèïméïmîmîmîmîmñímôímëímîímäímåímÜímÝím¼ím½ím¨ím©ímímímþìmÿìmêìmëìmàìmáìmÜìmÝìmÀìmÁìmªìm«ìmìmìmìmìmìmìm§ÝëÃràëÁrØëÁrÙëÃrÏëÃrÒëÁrÚëÁrÛëÃrÍëÃrÐëÁrìÃr¢ìÁrÊëÁrËëÃrÇëÃrÊëÁrìÁrìÃr·ëÃrºëÁr´ëÁrµëÃr²ëÁr³ëÃr°ëÁr±ëÃrÓìÃrÖìÁrëÃrëÁrëÃrëÁríÃríÁrûëÃrþëÁrÖìÁr×ìÃrÿêÃrëÁróêÃröêÁrßêÃrâêÁrÙêÃrÜêÁrÒêÁrÓêÃrÊêÁrËêÃrªêÁr«êÃrêÁrêÃrþéÁrÿéÃrìéÁríéÃrØéÁrÙéÃrÎéÁrÏéÃrÊéÁrËéÃr®éÁr¯éÃréÁréÃréÁréÃréÁréÃréÁréÃr§ËèýwÎèûwÆèûwÇèýw½èýwÀèûwÈèûwÉèýw»èýw¾èûwéýwéûw¸èûw¹èýwµèýw¸èûwòèûwóèýw¥èýw¨èûw¢èûw£èýw èûw¡èýwèûwèýwÁéýwÄéûwèýwèûwýçýwèûwóéýwöéûwéèýwìèûwÄéûwÅéýwíçýwðçûwáçýwäçûwÍçýwÐçûwÇçýwÊçûwÀçûwÁçýw¸çûw¹çýwçûwçýwçûwçýwìæûwíæýwÚæûwÛæýwÆæûwÇæýw¼æûw½æýw¸æûw¹æýwæûwæýwæûwæýwúåûwûåýwðåûwñåýwîåûwïåýw§¹å·}¼åµ}´åµ}µå·}«å·}®åµ}¶åµ}·å·}©å·}¬åµ}ûå·}þåµ}¦åµ}§å·}£å·}¦åµ}àåµ}áå·}å·}åµ}åµ}å·}åµ}å·}åµ}å·}¯æ·}²æµ}õä·}øäµ}ëä·}îäµ}áæ·}äæµ}×å·}Úåµ}²æµ}³æ·}Ûä·}Þäµ}Ïä·}Òäµ}»ä·}¾äµ}µä·}¸äµ}®äµ}¯ä·}¦äµ}§ä·}äµ}ä·}òãµ}óã·}Úãµ}Ûã·}Èãµ}Éã·}´ãµ}µã·}ªãµ}«ã·}¦ãµ}§ã·}ãµ}ã·}ôâµ}õâ·}èâµ}éâ·}Þâµ}ßâ·}Üâµ}Ýâ·}§§âñªâï¢âï£âñâñâï¤âï¥âñâñâïéâñìâïâïâñâñâïÎâïÏâñâñâïþáïÿáñüáïýáñúáïûáñãñ ãïãáñæáïÙáñÜáïÏãñÒãïÅâñÈâï ãï¡ãñÉáñÌáï½áñÀáï©áñ¬áï£áñ¦áïáïáñáïáñôàïõàñààïáàñÈàïÉàñ¶àï·àñ¢àï£àñàïàñàïàñøßïùßñâßïãßñÖßï×ßñÌßïÍßñÊßïËßñ§ß«ß©ß©ß«ß«ß©ß©ß«ß«ß©×ß«Úß©ß©ß«ÿÞ«ß©¼ß©½ß«ïÞ«òÞ©ìÞ©íÞ«êÞ©ëÞ«èÞ©éÞ«à«à©ÑÞ«ÔÞ©ÇÞ«ÊÞ©½à«Àà©³ß«¶ß©à©à«·Þ«ºÞ©«Þ«®Þ©Þ«Þ©Þ«Þ©Þ©Þ«Þ©Þ«âÝ©ãÝ«ÎÝ©ÏÝ«¶Ý©·Ý«¤Ý©¥Ý«Ý©Ý«Ý©Ý«Ý©Ý«æÜ©çÜ«ÐÜ©ÑÜ«ÄÜ©ÅÜ«ºÜ©»Ü«¸Ü©¹Ü«§ÜåÜãþÛãÿÛåõÛåøÛãÜãÜåóÛåöÛãÅÜåÈÜãðÛãñÛåíÛåðÛãªÜã«ÜåÝÛåàÛãÚÛãÛÛåØÛãÙÛåÖÛã×ÛåùÜåüÜã¿ÛåÂÛãµÛå¸Ûã«Ýå®Ýã¡Üå¤ÜãüÜãýÜå¥Ûå¨ÛãÛåÛãÛåÛãÿÚåÛãøÚãùÚåðÚãñÚåÐÚãÑÚå¼Úã½Úå¤Úã¥ÚåÚãÚåþÙãÿÙåôÙãõÙåðÙãñÙåÔÙãÕÙå¾Ùã¿Ùå²Ùã³Ùå¨Ùã©Ùå¦Ùã§Ùå§ñØôØìØíØãØæØîØïØáØäØ³Ù¶ÙÞØßØÛØÞØÙÙËØÎØÈØÉØÆØÇØÄØÅØçÙêÙ­Ø°Ø£Ø¦ØÚÚÙÙêÙëÙØØØØó×ö×í×ð×æ×ç×Þ×ß×¾×¿×ª×«×××××ìÖíÖâÖãÖÞÖßÖÂÖÃÖ¬Ö­Ö Ö¡ÖÖÖÖÖ§ßÕÙâÕ×ÚÕ×ÛÕÙÑÕÙÔÕ×ÜÕ×ÝÕÙÏÕÙÒÕ×¡ÖÙ¤Ö×ÌÕ×ÍÕÙÉÕÙÌÕ×Ö×ÖÙ¹ÕÙ¼Õ×¶Õ×·ÕÙ´Õ×µÕÙ²Õ×³ÕÙÕÖÙØÖ×ÕÙÕ×ÕÙÕ××Ù××ýÕÙÖ×ØÖ×ÙÖÙÕÙÕ×õÔÙøÔ×áÔÙäÔ×ÛÔÙÞÔ×ÔÔ×ÕÔÙÌÔ×ÍÔÙ¬Ô×­ÔÙÔ×ÔÙÔ×ÔÙîÓ×ïÓÙÚÓ×ÛÓÙÐÓ×ÑÓÙÌÓ×ÍÓÙ°Ó×±ÓÙÓ×ÓÙÓ×ÓÙÓ×ÓÙÓ×ÓÙ§ÍÒÐÒÈÒÉÒ¿ÒÂÒÊÒËÒ½ÒÀÒÓÓºÒ»Ò·ÒºÒôÒõÒ§ÒªÒ¤Ò¥Ò¢Ò£Ò Ò¡ÒÃÓÆÓÒÒÿÑÒõÓøÓëÒîÒÆÓÇÓïÑòÑãÑæÑÏÑÒÑÉÑÌÑÂÑÃÑºÑ»ÑÑÑÑÑîÐïÐÜÐÝÐÈÐÉÐ¾Ð¿ÐºÐ»ÐÐÐÐÐüÏýÏòÏóÏðÏñÏ§»ÏÍ£¾ÏË£¶ÏË£·ÏÍ£­ÏÍ£°ÏË£¸ÏË£¹ÏÍ£«ÏÍ£®ÏË£ýÏÍ£ÐË£¨ÏË£©ÏÍ£¥ÏÍ£¨ÏË£âÏË£ãÏÍ£ÏÍ£ÏË£ÏË£ÏÍ£ÏË£ÏÍ£ÏË£ÏÍ£±ÐÍ£´ÐË£÷ÎÍ£úÎË£íÎÍ£ðÎË£ãÐÍ£æÐË£ÙÏÍ£ÜÏË£´ÐË£µÐÍ£ÝÎÍ£àÎË£ÑÎÍ£ÔÎË£½ÎÍ£ÀÎË£·ÎÍ£ºÎË£°ÎË£±ÎÍ£¨ÎË£©ÎÍ£ÎË£ÎÍ£ôÍË£õÍÍ£ÜÍË£ÝÍÍ£ÊÍË£ËÍÍ£¶ÍË£·ÍÍ£¬ÍË£­ÍÍ£¨ÍË£©ÍÍ£ÍË£ÍÍ£öÌË£÷ÌÍ£êÌË£ëÌÍ£àÌË£áÌÍ£ÞÌË£ßÌÍ£§©Ì©¬Ì©¤Ì©¥Ì©Ì©Ì©¦Ì©§Ì©Ì©Ì©ëÌ©îÌ©Ì©Ì©Ì©Ì©ÐÌ©ÑÌ©Ì©Ì©Ì©Ì©þË©ÿË©üË©ýË©Í©¢Í©åË©èË©ÛË©ÞË©ÑÍ©ÔÍ©ÇÌ©ÊÌ©¢Í©£Í©ËË©ÎË©¿Ë©ÂË©«Ë©®Ë©¥Ë©¨Ë©Ë©Ë©Ë©Ë©öÊ©÷Ê©âÊ©ãÊ©ÊÊ©ËÊ©¸Ê©¹Ê©¤Ê©¥Ê©Ê©Ê©Ê©Ê©úÉ©ûÉ©äÉ©åÉ©ØÉ©ÙÉ©ÎÉ©ÏÉ©ÌÉ©ÍÉ©§ÉÁ®É¿®É¿®ÉÁ®ÉÁ®É¿®É¿®ÉÁ®ÉÁ®É¿®ÙÉÁ®ÜÉ¿®É¿®ÉÁ®ÉÁ®É¿®¾É¿®¿ÉÁ®ñÈÁ®ôÈ¿®îÈ¿®ïÈÁ®ìÈ¿®íÈÁ®êÈ¿®ëÈÁ®ÊÁ®Ê¿®ÓÈÁ®ÖÈ¿®ÉÈÁ®ÌÈ¿®¿ÊÁ®ÂÊ¿®µÉÁ®¸É¿®Ê¿®ÊÁ®¹ÈÁ®¼È¿®­ÈÁ®°È¿®ÈÁ®È¿®ÈÁ®È¿®È¿®ÈÁ®È¿®ÈÁ®äÇ¿®åÇÁ®ÐÇ¿®ÑÇÁ®¸Ç¿®¹ÇÁ®¦Ç¿®§ÇÁ®Ç¿®ÇÁ®Ç¿®ÇÁ®Ç¿®ÇÁ®èÆ¿®éÆÁ®ÒÆ¿®ÓÆÁ®ÆÆ¿®ÇÆÁ®¼Æ¿®½ÆÁ®ºÆ¿®»ÆÁ®§Æû³Æù³Æù³Æû³÷Åû³úÅù³Æù³Æû³õÅû³øÅù³ÇÆû³ÊÆù³òÅù³óÅû³ïÅû³òÅù³¬Æù³­Æû³ßÅû³âÅù³ÜÅù³ÝÅû³ÚÅù³ÛÅû³ØÅù³ÙÅû³ûÆû³þÆù³ÁÅû³ÄÅù³·Åû³ºÅù³­Çû³°Çù³£Æû³¦Æù³þÆù³ÿÆû³§Åû³ªÅù³Åû³Åù³Åû³Åù³Åû³Åù³úÄù³ûÄû³òÄù³óÄû³ÒÄù³ÓÄû³¾Äù³¿Äû³¦Äù³§Äû³Äù³Äû³Äù³Äû³öÃù³÷Ãû³òÃù³óÃû³ÖÃù³×Ãû³ÀÃù³ÁÃû³´Ãù³µÃû³ªÃù³«Ãû³¨Ãù³©Ãû³§óÂµ¹öÂ³¹îÂ³¹ïÂµ¹åÂµ¹èÂ³¹ðÂ³¹ñÂµ¹ãÂµ¹æÂ³¹µÃµ¹¸Ã³¹àÂ³¹áÂµ¹ÝÂµ¹àÂ³¹Ã³¹Ãµ¹ÍÂµ¹ÐÂ³¹ÊÂ³¹ËÂµ¹ÈÂ³¹ÉÂµ¹ÆÂ³¹ÇÂµ¹éÃµ¹ìÃ³¹¯Âµ¹²Â³¹¥Âµ¹¨Â³¹Äµ¹Ä³¹Ãµ¹Ã³¹ìÃ³¹íÃµ¹Âµ¹Â³¹Âµ¹Â³¹õÁµ¹øÁ³¹ïÁµ¹òÁ³¹èÁ³¹éÁµ¹àÁ³¹áÁµ¹ÀÁ³¹ÁÁµ¹¬Á³¹­Áµ¹Á³¹Áµ¹Á³¹Áµ¹îÀ³¹ïÀµ¹äÀ³¹åÀµ¹àÀ³¹áÀµ¹ÄÀ³¹ÅÀµ¹®À³¹¯Àµ¹¢À³¹£Àµ¹À³¹Àµ¹À³¹Àµ¹§á¿ï¾ä¿í¾Ü¿í¾Ý¿ï¾Ó¿ï¾Ö¿í¾Þ¿í¾ß¿ï¾Ñ¿ï¾Ô¿í¾£Àï¾¦Àí¾Î¿í¾Ï¿ï¾Ë¿ï¾Î¿í¾Àí¾Àï¾»¿ï¾¾¿í¾¸¿í¾¹¿ï¾¶¿í¾·¿ï¾´¿í¾µ¿ï¾×Àï¾ÚÀí¾¿ï¾ ¿í¾¿ï¾¿í¾Áï¾Áí¾ÿ¿ï¾Àí¾ÚÀí¾ÛÀï¾¿ï¾¿í¾÷¾ï¾ú¾í¾ã¾ï¾æ¾í¾Ý¾ï¾à¾í¾Ö¾í¾×¾ï¾Î¾í¾Ï¾ï¾®¾í¾¯¾ï¾¾í¾¾ï¾¾í¾¾ï¾ð½í¾ñ½ï¾Ü½í¾Ý½ï¾Ò½í¾Ó½ï¾Î½í¾Ï½ï¾²½í¾³½ï¾½í¾½ï¾½í¾½ï¾½í¾½ï¾½í¾½ï¾§Ï¼©ÄÒ¼§ÄÊ¼§ÄË¼©ÄÁ¼©ÄÄ¼§ÄÌ¼§ÄÍ¼©Ä¿¼©ÄÂ¼§Ä½©Ä½§Ä¼¼§Ä½¼©Ä¹¼©Ä¼¼§Äö¼§Ä÷¼©Ä©¼©Ä¬¼§Ä¦¼§Ä§¼©Ä¤¼§Ä¥¼©Ä¢¼§Ä£¼©ÄÅ½©ÄÈ½§Ä¼©Ä¼§Ä¼©Ä¼§Ä÷½©Äú½§Äí¼©Äð¼§ÄÈ½§ÄÉ½©Äñ»©Äô»§Äå»©Äè»§ÄÑ»©ÄÔ»§ÄË»©ÄÎ»§ÄÄ»§ÄÅ»©Ä¼»§Ä½»©Ä»§Ä»©Ä»§Ä»©Äðº§Äñº©ÄÞº§Äßº©ÄÊº§ÄËº©ÄÀº§ÄÁº©Ä¼º§Ä½º©Ä º§Ä¡º©Äº§Äº©Äþ¹§Äÿ¹©Äô¹§Äõ¹©Äò¹§Äó¹©Ä§«ø»®ø¹¦ø¹§ø»ø» ø¹¨ø¹©ø»ø»ø¹íø»ðø¹ø¹ø»ø»ø¹Òø¹Óø»ø»ø¹ø¹ø»ø¹ø»þ÷¹ÿ÷»¡ù»¤ù¹ç÷»ê÷¹Ý÷»à÷¹Óù»Öù¹Éø»Ìø¹¤ù¹¥ù»Í÷»Ð÷¹Á÷»Ä÷¹­÷»°÷¹§÷»ª÷¹ ÷¹¡÷»÷¹÷»øö¹ùö»äö¹åö»Ìö¹Íö»ºö¹»ö»¦ö¹§ö»ö¹ö»ö¹ö»üõ¹ýõ»æõ¹çõ»Úõ¹Ûõ»Ðõ¹Ñõ»Îõ¹Ïõ»§õõ
+õó
+õó
+õõ
+õõ
+õó
+õó
+õõ
+õõ
+õó
+Ûõõ
+Þõó
+õó
+õõ
+õõ
+õó
+Àõó
+Áõõ
+óôõ
+öôó
+ðôó
+ñôõ
+îôó
+ïôõ
+ìôó
+íôõ
+öõ
+öó
+Õôõ
+Øôó
+Ëôõ
+Îôó
+Áöõ
+Äöó
+·õõ
+ºõó
+öó
+öõ
+»ôõ
+¾ôó
+¯ôõ
+²ôó
+ôõ
+ôó
+ôõ
+ôó
+ôó
+ôõ
+ôó
+ôõ
+æóó
+çóõ
+Òóó
+Óóõ
+ºóó
+»óõ
+¨óó
+©óõ
+óó
+óõ
+óó
+óõ
+óó
+óõ
+êòó
+ëòõ
+Ôòó
+Õòõ
+Èòó
+Éòõ
+¾òó
+¿òõ
+¼òó
+½òõ
+§ò¯ò­ò­ò¯ùñ¯üñ­ò­ò¯÷ñ¯úñ­Éò¯Ìò­ôñ­õñ¯ññ¯ôñ­®ò­¯ò¯áñ¯äñ­Þñ­ßñ¯Üñ­Ýñ¯Úñ­Ûñ¯ýò¯ó­Ãñ¯Æñ­¹ñ¯¼ñ­¯ó¯²ó­¥ò¯¨ò­ó­ó¯©ñ¯¬ñ­ñ¯ ñ­ñ¯ñ­ñ¯ñ­üð­ýð¯ôð­õð¯Ôð­Õð¯Àð­Áð¯¨ð­©ð¯ð­ð¯ð­ð¯øï­ùï¯ôï­õï¯Øï­Ùï¯Âï­Ãï¯¶ï­·ï¯¬ï­­ï¯ªï­«ï¯§õîéøîçðîçñîéçîéêîçòîçóîéåîéèîç·ïéºïçâîçãîéßîéâîçïçïéÏîéÒîçÌîçÍîéÊîçËîéÈîçÉîéëïéîïç±îé´îç§îéªîçðé ðçïéïçîïçïïéîéîçîéîç÷íéúíçñíéôíçêíçëíéâíçãíéÂíçÃíé®íç¯íéíçíéíçíéðìçñìéæìççìéâìçãìéÆìçÇìé°ìç±ìé¤ìç¥ìéìçìéìçìé§ãë£æë¡Þë¡ßë£Õë£Øë¡àë¡áë£Óë£Öë¡¥ì£¨ì¡Ðë¡Ñë£Íë£Ðë¡ì¡ì£½ë£Àë¡ºë¡»ë£¸ë¡¹ë£¶ë¡·ë£Ùì£Üì¡ë£¢ë¡ë£ë¡í£í¡ì£ì¡Üì¡Ýì£ë£ë¡ùê£üê¡åê£èê¡ßê£âê¡Øê¡Ùê£Ðê¡Ñê£°ê¡±ê£ê¡ê£ê¡ê£òé¡óé£Þé¡ßé£Ôé¡Õé£Ðé¡Ñé£´é¡µé£é¡é£é¡é£é¡é£é¡é£§ÑèÝ ÔèÛ ÌèÛ ÍèÝ ÃèÝ ÆèÛ ÎèÛ ÏèÝ ÁèÝ ÄèÛ éÝ éÛ ¾èÛ ¿èÝ »èÝ ¾èÛ øèÛ ùèÝ «èÝ ®èÛ ¨èÛ ©èÝ ¦èÛ §èÝ ¤èÛ ¥èÝ ÇéÝ ÊéÛ èÝ èÛ èÝ èÛ ùéÝ üéÛ ïèÝ òèÛ ÊéÛ ËéÝ óçÝ öçÛ ççÝ êçÛ ÓçÝ ÖçÛ ÍçÝ ÐçÛ ÆçÛ ÇçÝ ¾çÛ ¿çÝ çÛ çÝ çÛ çÝ òæÛ óæÝ àæÛ áæÝ ÌæÛ ÍæÝ ÂæÛ ÃæÝ ¾æÛ ¿æÝ ¢æÛ £æÝ æÛ æÝ æÛ æÝ öåÛ ÷åÝ ôåÛ õåÝ §¿å&Âå&ºå&»å&±å&´å&¼å&½å&¯å&²å&æ&æ&¬å&­å&©å&¬å&æå&çå&å&å&å&å&å&å&å&å&µæ&¸æ&ûä&þä&ñä&ôä&çæ&êæ&Ýå&àå&¸æ&¹æ&áä&ää&Õä&Øä&Áä&Ää&»ä&¾ä&´ä&µä&¬ä&­ä&ä&ä&øã&ùã&àã&áã&Îã&Ïã&ºã&»ã&°ã&±ã&¬ã&­ã&ã&ã&úâ&ûâ&îâ&ïâ&äâ&åâ&ââ&ãâ&§­âÑ+°âÏ+¨âÏ+©âÑ+âÑ+¢âÏ+ªâÏ+«âÑ+âÑ+ âÏ+ïâÑ+òâÏ+âÏ+âÑ+âÑ+âÏ+ÔâÏ+ÕâÑ+âÑ+âÏ+âÏ+âÑ+âÏ+âÑ+âÏ+âÑ+£ãÑ+¦ãÏ+éáÑ+ìáÏ+ßáÑ+âáÏ+ÕãÑ+ØãÏ+ËâÑ+ÎâÏ+¦ãÏ+§ãÑ+ÏáÑ+ÒáÏ+ÃáÑ+ÆáÏ+¯áÑ+²áÏ+©áÑ+¬áÏ+¢áÏ+£áÑ+áÏ+áÑ+úàÏ+ûàÑ+æàÏ+çàÑ+ÎàÏ+ÏàÑ+¼àÏ+½àÑ+¨àÏ+©àÑ+àÏ+àÑ+àÏ+àÑ+þßÏ+ÿßÑ+èßÏ+éßÑ+ÜßÏ+ÝßÑ+ÒßÏ+ÓßÑ+ÐßÏ+ÑßÑ+§ß1ß1ß1ß1ß1ß1ß1ß1ß1ß1Ýß1àß1ß1ß1ß1ß1Âß1Ãß1õÞ1øÞ1òÞ1óÞ1ðÞ1ñÞ1îÞ1ïÞ1à1à1×Þ1ÚÞ1ÍÞ1ÐÞ1Ãà1Æà1¹ß1¼ß1à1à1½Þ1ÀÞ1±Þ1´Þ1Þ1 Þ1Þ1Þ1Þ1Þ1Þ1Þ1èÝ1éÝ1ÔÝ1ÕÝ1¼Ý1½Ý1ªÝ1«Ý1Ý1Ý1Ý1Ý1Ý1Ý1ìÜ1íÜ1ÖÜ1×Ü1ÊÜ1ËÜ1ÀÜ1ÁÜ1¾Ü1¿Ü1§ÜÅ6ÜÃ6ÜÃ6ÜÅ6ûÛÅ6þÛÃ6ÜÃ6ÜÅ6ùÛÅ6üÛÃ6ËÜÅ6ÎÜÃ6öÛÃ6÷ÛÅ6óÛÅ6öÛÃ6°ÜÃ6±ÜÅ6ãÛÅ6æÛÃ6àÛÃ6áÛÅ6ÞÛÃ6ßÛÅ6ÜÛÃ6ÝÛÅ6ÿÜÅ6ÝÃ6ÅÛÅ6ÈÛÃ6»ÛÅ6¾ÛÃ6±ÝÅ6´ÝÃ6§ÜÅ6ªÜÃ6ÝÃ6ÝÅ6«ÛÅ6®ÛÃ6ÛÅ6¢ÛÃ6ÛÅ6ÛÃ6ÛÅ6ÛÃ6þÚÃ6ÿÚÅ6öÚÃ6÷ÚÅ6ÖÚÃ6×ÚÅ6ÂÚÃ6ÃÚÅ6ªÚÃ6«ÚÅ6ÚÃ6ÚÅ6ÚÃ6ÚÅ6úÙÃ6ûÙÅ6öÙÃ6÷ÙÅ6ÚÙÃ6ÛÙÅ6ÄÙÃ6ÅÙÅ6¸ÙÃ6¹ÙÅ6®ÙÃ6¯ÙÅ6¬ÙÃ6­ÙÅ6§÷Øÿ;úØý;òØý;óØÿ;éØÿ;ìØý;ôØý;õØÿ;çØÿ;êØý;¹Ùÿ;¼Ùý;äØý;åØÿ;áØÿ;äØý;Ùý;Ùÿ;ÑØÿ;ÔØý;ÎØý;ÏØÿ;ÌØý;ÍØÿ;ÊØý;ËØÿ;íÙÿ;ðÙý;³Øÿ;¶Øý;©Øÿ;¬Øý;Úÿ;¢Úý;Ùÿ;Ùý;ðÙý;ñÙÿ;Øÿ;Øý;Øÿ;Øý;ù×ÿ;ü×ý;ó×ÿ;ö×ý;ì×ý;í×ÿ;ä×ý;å×ÿ;Ä×ý;Å×ÿ;°×ý;±×ÿ;×ý;×ÿ;×ý;×ÿ;òÖý;óÖÿ;èÖý;éÖÿ;äÖý;åÖÿ;ÈÖý;ÉÖÿ;²Öý;³Öÿ;¦Öý;§Öÿ;Öý;Öÿ;Öý;Öÿ;§åÕ¹AèÕ·AàÕ·AáÕ¹A×Õ¹AÚÕ·AâÕ·AãÕ¹AÕÕ¹AØÕ·A§Ö¹AªÖ·AÒÕ·AÓÕ¹AÏÕ¹AÒÕ·AÖ·AÖ¹A¿Õ¹AÂÕ·A¼Õ·A½Õ¹AºÕ·A»Õ¹A¸Õ·A¹Õ¹AÛÖ¹AÞÖ·A¡Õ¹A¤Õ·AÕ¹AÕ·A×¹A×·AÖ¹AÖ·AÞÖ·AßÖ¹AÕ¹AÕ·AûÔ¹AþÔ·AçÔ¹AêÔ·AáÔ¹AäÔ·AÚÔ·AÛÔ¹AÒÔ·AÓÔ¹A²Ô·A³Ô¹AÔ·AÔ¹AÔ·AÔ¹AôÓ·AõÓ¹AàÓ·AáÓ¹AÖÓ·A×Ó¹AÒÓ·AÓÓ¹A¶Ó·A·Ó¹A Ó·A¡Ó¹AÓ·AÓ¹AÓ·AÓ¹AÓ·AÓ¹A§ÓÒóFÖÒñFÎÒñFÏÒóFÅÒóFÈÒñFÐÒñFÑÒóFÃÒóFÆÒñFÓóFÓñFÀÒñFÁÒóF½ÒóFÀÒñFúÒñFûÒóF­ÒóF°ÒñFªÒñF«ÒóF¨ÒñF©ÒóF¦ÒñF§ÒóFÉÓóFÌÓñFÒóFÒñFÒóFÒñFûÓóFþÓñFñÒóFôÒñFÌÓñFÍÓóFõÑóFøÑñFéÑóFìÑñFÕÑóFØÑñFÏÑóFÒÑñFÈÑñFÉÑóFÀÑñFÁÑóF ÑñF¡ÑóFÑñFÑóFôÐñFõÐóFâÐñFãÐóFÎÐñFÏÐóFÄÐñFÅÐóFÀÐñFÁÐóF¤ÐñF¥ÐóFÐñFÐóFÐñFÐóFøÏñFùÏóFöÏñF÷ÏóF§ÁÏ­LÄÏ«L¼Ï«L½Ï­L³Ï­L¶Ï«L¾Ï«L¿Ï­L±Ï­L´Ï«LÐ­LÐ«L®Ï«L¯Ï­L«Ï­L®Ï«LèÏ«LéÏ­LÏ­LÏ«LÏ«LÏ­LÏ«LÏ­LÏ«LÏ­L·Ð­LºÐ«LýÎ­LÏ«LóÎ­LöÎ«LéÐ­LìÐ«LßÏ­LâÏ«LºÐ«L»Ð­LãÎ­LæÎ«L×Î­LÚÎ«LÃÎ­LÆÎ«L½Î­LÀÎ«L¶Î«L·Î­L®Î«L¯Î­LÎ«LÎ­LúÍ«LûÍ­LâÍ«LãÍ­LÐÍ«LÑÍ­L¼Í«L½Í­L²Í«L³Í­L®Í«L¯Í­LÍ«LÍ­LüÌ«LýÌ­LðÌ«LñÌ­LæÌ«LçÌ­LäÌ«LåÌ­L§¯ÌçQ²ÌåQªÌåQ«ÌçQ¡ÌçQ¤ÌåQ¬ÌåQ­ÌçQÌçQ¢ÌåQñÌçQôÌåQÌåQÌçQÌçQÌåQÖÌåQ×ÌçQÌçQÌåQÌåQÌçQÌåQÌçQÌåQÌçQ¥ÍçQ¨ÍåQëËçQîËåQáËçQäËåQ×ÍçQÚÍåQÍÌçQÐÌåQ¨ÍåQ©ÍçQÑËçQÔËåQÅËçQÈËåQ±ËçQ´ËåQ«ËçQ®ËåQ¤ËåQ¥ËçQËåQËçQüÊåQýÊçQèÊåQéÊçQÐÊåQÑÊçQ¾ÊåQ¿ÊçQªÊåQ«ÊçQ ÊåQ¡ÊçQÊåQÊçQÊåQÊçQêÉåQëÉçQÞÉåQßÉçQÔÉåQÕÉçQÒÉåQÓÉçQ§É¡W ÉWÉWÉ¡WÉ¡WÉWÉWÉ¡WÉ¡WÉWßÉ¡WâÉWÉWÉ¡WÉ¡WÉWÄÉWÅÉ¡W÷È¡WúÈWôÈWõÈ¡WòÈWóÈ¡WðÈWñÈ¡WÊ¡WÊWÙÈ¡WÜÈWÏÈ¡WÒÈWÅÊ¡WÈÊW»É¡W¾ÉWÊWÊ¡W¿È¡WÂÈW³È¡W¶ÈWÈ¡W¢ÈWÈ¡WÈWÈWÈ¡WÈWÈ¡WêÇWëÇ¡WÖÇW×Ç¡W¾ÇW¿Ç¡W¬ÇW­Ç¡WÇWÇ¡WÇWÇ¡WÇWÇ¡WîÆWïÆ¡WØÆWÙÆ¡WÌÆWÍÆ¡WÂÆWÃÆ¡WÀÆWÁÆ¡W§ÆÛ\ÆÙ\ÆÙ\ÆÛ\ýÅÛ\ÆÙ\ÆÙ\ÆÛ\ûÅÛ\þÅÙ\ÍÆÛ\ÐÆÙ\øÅÙ\ùÅÛ\õÅÛ\øÅÙ\²ÆÙ\³ÆÛ\åÅÛ\èÅÙ\âÅÙ\ãÅÛ\àÅÙ\áÅÛ\ÞÅÙ\ßÅÛ\ÇÛ\ÇÙ\ÇÅÛ\ÊÅÙ\½ÅÛ\ÀÅÙ\³ÇÛ\¶ÇÙ\©ÆÛ\¬ÆÙ\ÇÙ\ÇÛ\­ÅÛ\°ÅÙ\¡ÅÛ\¤ÅÙ\ÅÛ\ÅÙ\ÅÛ\ÅÙ\ÅÙ\ÅÛ\øÄÙ\ùÄÛ\ØÄÙ\ÙÄÛ\ÄÄÙ\ÅÄÛ\¬ÄÙ\­ÄÛ\ÄÙ\ÄÛ\ÄÙ\ÄÛ\üÃÙ\ýÃÛ\øÃÙ\ùÃÛ\ÜÃÙ\ÝÃÛ\ÆÃÙ\ÇÃÛ\ºÃÙ\»ÃÛ\°ÃÙ\±ÃÛ\®ÃÙ\¯ÃÛ\§ùÂbüÂbôÂbõÂbëÂbîÂböÂb÷ÂbéÂbìÂb»Ãb¾ÃbæÂbçÂbãÂbæÂb Ãb¡ÃbÓÂbÖÂbÐÂbÑÂbÎÂbÏÂbÌÂbÍÂbïÃbòÃbµÂb¸Âb«Âb®Âb¡Äb¤ÄbÃbÃbòÃbóÃbÂbÂbÂbÂbûÁbþÁbõÁbøÁbîÁbïÁbæÁbçÁbÆÁbÇÁb²Áb³ÁbÁbÁbÁbÁbôÀbõÀbêÀbëÀbæÀbçÀbÊÀbËÀb´ÀbµÀb¨Àb©ÀbÀbÀbÀbÀb§ç¿Ïgê¿Ígâ¿Ígã¿ÏgÙ¿ÏgÜ¿Ígä¿Ígå¿Ïg×¿ÏgÚ¿Íg©ÀÏg¬ÀÍgÔ¿ÍgÕ¿ÏgÑ¿ÏgÔ¿ÍgÀÍgÀÏgÁ¿ÏgÄ¿Íg¾¿Íg¿¿Ïg¼¿Íg½¿Ïgº¿Íg»¿ÏgÝÀÏgàÀÍg£¿Ïg¦¿Íg¿Ïg¿ÍgÁÏgÁÍgÀÏgÀÍgàÀÍgáÀÏg¿Ïg¿Ígý¾Ïg¿Ígé¾Ïgì¾Ígã¾Ïgæ¾ÍgÜ¾ÍgÝ¾ÏgÔ¾ÍgÕ¾Ïg´¾Ígµ¾Ïg ¾Íg¡¾Ïg¾Íg¾Ïgö½Íg÷½Ïgâ½Ígã½ÏgØ½ÍgÙ½ÏgÔ½ÍgÕ½Ïg¸½Íg¹½Ïg¢½Íg£½Ïg½Íg½Ïg½Íg½Ïg½Íg½Ïg§Õ¼mØ¼mÐ¼mÑ¼mÇ¼mÊ¼mÒ¼mÓ¼mÅ¼mÈ¼m½m½mÂ¼mÃ¼m¿¼mÂ¼mü¼mý¼m¯¼m²¼m¬¼m­¼mª¼m«¼m¨¼m©¼mË½mÎ½m¼m¼m¼m¼mý½m¾mó¼mö¼mÎ½mÏ½m÷»mú»më»mî»m×»mÚ»mÑ»mÔ»mÊ»mË»mÂ»mÃ»m¢»m£»m»m»möºm÷ºmäºmåºmÐºmÑºmÆºmÇºmÂºmÃºm¦ºm§ºmºmºmºmºmú¹mû¹mø¹mù¹m§Ã¹ÃrÆ¹Ár¾¹Ár¿¹Ãrµ¹Ãr¸¹ÁrÀ¹ÁrÁ¹Ãr³¹Ãr¶¹ÁrºÃrºÁr°¹Ár±¹Ãr­¹Ãr°¹Árê¹Árë¹Ãr¹Ãr ¹Ár¹Ár¹Ãr¹Ár¹Ãr¹Ár¹Ãr¹ºÃr¼ºÁrÿ¸Ãr¹Árõ¸Ãrø¸ÁrëºÃrîºÁrá¹Ãrä¹Ár¼ºÁr½ºÃrå¸Ãrè¸ÁrÙ¸ÃrÜ¸ÁrÅ¸ÃrÈ¸Ár¿¸ÃrÂ¸Ár¸¸Ár¹¸Ãr°¸Ár±¸Ãr¸Ár¸Ãrü·Árý·Ãrä·Árå·ÃrÒ·ÁrÓ·Ãr¾·Ár¿·Ãr´·Árµ·Ãr°·Ár±·Ãr·Ár·Ãrþ¶Árÿ¶Ãrò¶Áró¶Ãrè¶Áré¶Ãræ¶Árç¶Ãr§±¶ýw´¶ûw¬¶ûw­¶ýw£¶ýw¦¶ûw®¶ûw¯¶ýw¡¶ýw¤¶ûwó¶ýwö¶ûw¶ûw¶ýw¶ýw¶ûwØ¶ûwÙ¶ýw¶ýw¶ûw¶ûw¶ýw¶ûw¶ýw¶ûw¶ýw§·ýwª·ûwíµýwðµûwãµýwæµûwÙ·ýwÜ·ûwÏ¶ýwÒ¶ûwª·ûw«·ýwÓµýwÖµûwÇµýwÊµûw³µýw¶µûw­µýw°µûw¦µûw§µýwµûwµýwþ´ûwÿ´ýwê´ûwë´ýwÒ´ûwÓ´ýwÀ´ûwÁ´ýw¬´ûw­´ýw¢´ûw£´ýw´ûw´ýw´ûw´ýwì³ûwí³ýwà³ûwá³ýwÖ³ûw×³ýwÔ³ûwÕ³ýw§³·}¢³µ}³µ}³·}³·}³µ}³µ}³·}³·}³µ}á³·}ä³µ}³µ}³·}³·}³µ}Æ³µ}Ç³·}ù²·}ü²µ}ö²µ}÷²·}ô²µ}õ²·}ò²µ}ó²·}´·}´µ}Û²·}Þ²µ}Ñ²·}Ô²µ}Ç´·}Ê´µ}½³·}À³µ}´µ}´·}Á²·}Ä²µ}µ²·}¸²µ}¡²·}¤²µ}²·}²µ}²µ}²·}²µ}²·}ì±µ}í±·}Ø±µ}Ù±·}À±µ}Á±·}®±µ}¯±·}±µ}±·}±µ}±·}±µ}±·}ð°µ}ñ°·}Ú°µ}Û°·}Î°µ}Ï°·}Ä°µ}Å°·}Â°µ}Ã°·}§°ñ°ï°ï°ñÿ¯ñ°ï°ï°ñý¯ñ°ïÏ°ñÒ°ïú¯ïû¯ñ÷¯ñú¯ï´°ïµ°ñç¯ñê¯ïä¯ïå¯ñâ¯ïã¯ñà¯ïá¯ñ±ñ±ïÉ¯ñÌ¯ï¿¯ñÂ¯ïµ±ñ¸±ï«°ñ®°ï±ï±ñ¯¯ñ²¯ï£¯ñ¦¯ï¯ñ¯ï¯ñ¯ï¯ï¯ñú®ïû®ñÚ®ïÛ®ñÆ®ïÇ®ñ®®ï¯®ñ®ï®ñ®ï®ñþ­ïÿ­ñú­ïû­ñÞ­ïß­ñÈ­ïÉ­ñ¼­ï½­ñ²­ï³­ñ°­ï±­ñ§û¬«þ¬©ö¬©÷¬«í¬«ð¬©ø¬©ù¬«ë¬«î¬©½­«À­©è¬©é¬«å¬«è¬©¢­©£­«Õ¬«Ø¬©Ò¬©Ó¬«Ð¬©Ñ¬«Î¬©Ï¬«ñ­«ô­©·¬«º¬©­¬«°¬©£®«¦®©­«­©ô­©õ­«¬« ¬©¬«¬©ý««¬©÷««ú«©ð«©ñ««è«©é««È«©É««´«©µ«««©«««©««öª©÷ª«ìª©íª«èª©éª«Ìª©Íª«¶ª©·ª«ªª©«ª« ª©¡ª«ª©ª«§é©åì©ãä©ãå©åÛ©åÞ©ãæ©ãç©åÙ©åÜ©ã«ªå®ªãÖ©ã×©åÓ©åÖ©ãªãªåÃ©åÆ©ãÀ©ãÁ©å¾©ã¿©å¼©ã½©åßªåâªã¥©å¨©ã©å©ã«å«ãªåªãâªããªå©å©ãÿ¨å©ãë¨åî¨ãå¨åè¨ãÞ¨ãß¨åÖ¨ã×¨å¶¨ã·¨å¢¨ã£¨å¨ã¨åø§ãù§åä§ãå§åÚ§ãÛ§åÖ§ã×§åº§ã»§å¤§ã¥§å§ã§å§ã§å§ã§å§×¦Ú¦Ò¦Ó¦É¦Ì¦Ô¦Õ¦Ç¦Ê¦§§Ä¦Å¦Á¦Ä¦þ¦ÿ¦±¦´¦®¦¯¦¬¦­¦ª¦«¦Í§Ð§¦¦¦¦ÿ§¨õ¦ø¦Ð§Ñ§ù¥ü¥í¥ð¥Ù¥Ü¥Ó¥Ö¥Ì¥Í¥Ä¥Å¥¤¥¥¥¥¥ø¤ù¤æ¤ç¤Ò¤Ó¤È¤É¤Ä¤Å¤¨¤©¤¤¤¤¤ü£ý£ú£û£§Å£ÙÈ£×À£×Á£Ù·£Ùº£×Â£×Ã£Ùµ£Ù¸£×¤Ù¤×²£×³£Ù¯£Ù²£×ì£×í£Ù£Ù¢£×£×£Ù£×£Ù£×£Ù»¤Ù¾¤×£Ù£×÷¢Ùú¢×í¤Ùð¤×ã£Ùæ£×¾¤×¿¤Ùç¢Ùê¢×Û¢ÙÞ¢×Ç¢ÙÊ¢×Á¢ÙÄ¢×º¢×»¢Ù²¢×³¢Ù¢×¢Ùþ¡×ÿ¡Ùæ¡×ç¡ÙÔ¡×Õ¡ÙÀ¡×Á¡Ù¶¡×·¡Ù²¡×³¡Ù¡×¡Ù¡×¡Ùô ×õ Ùê ×ë Ùè ×é Ù§³ ¶ ® ¯ ¥ ¨ ° ± £ ¦ õ ø   ¡    Ú Û         ©¡¬¡ïòåèÛ¡Þ¡Ñ Ô ¬¡­¡ÕØÉÌµ¸¯²¨© ¡ìíÔÕÂÃ®¯¤¥ ¡îïâãØÙÖ×§¡Í£¤Ë£Ë£Í£Í£Ë£Ë£Í£Í£Ë£ãÍ£æË£Ë£Í£Í£Ë£ÈË£ÉÍ£ûÍ£þË£øË£ùÍ£öË£÷Í£ôË£õÍ£Í£Ë£ÝÍ£àË£ÓÍ£ÖË£ÉÍ£ÌË£¿Í£ÂË£Ë£Í£ÃÍ£ÆË£·Í£ºË££Í£¦Ë£Í£ Ë£Ë£Í£Ë£Í£îË£ïÍ£ÚË£ÛÍ£ÂË£ÃÍ£°Ë£±Í£Ë£Í£Ë£Í£Ë£Í£òË£óÍ£ÜË£ÝÍ£ÐË£ÑÍ£ÆË£ÇÍ£ÄË£ÅÍ£§©©©©©©©©ÿ©©Ñ©Ô©ü©ý©ù©ü©¶©·©é©ì©æ©ç©ä©å©â©ã©©©Ë©Î©Á©Ä©·©º©­©°©©©±©´©¥©¨©©©©©©©ü©ý©Ü©Ý©È©É©°©±©©©©©©©ü©ý©à©á©Ê©Ë©¾©¿©´©µ©²©³©§ýÁ®¿®ø¿®ùÁ®ïÁ®ò¿®ú¿®ûÁ®íÁ®ð¿®¿Á®Â¿®ê¿®ëÁ®çÁ®ê¿®¤¿®¥Á®×Á®Ú¿®Ô¿®ÕÁ®Ò¿®ÓÁ®Ð¿®ÑÁ®óÁ®ö¿®¹Á®¼¿®¯Á®²¿®¥Á®¨¿®Á®¿®ö¿®÷Á®Á®¢¿®Á®¿®ÿÁ®¿®ùÁ®ü¿®ò¿®óÁ®ê¿®ëÁ®Ê¿®ËÁ®¶¿®·Á®¿®Á®¿®Á®ø¿®ùÁ®î¿®ïÁ®ê¿®ëÁ®Î¿®ÏÁ®¸¿®¹Á®¬¿®­Á®¢¿®£Á® ¿®¡Á®§ëû³îù³æù³çû³Ýû³àù³èù³éû³Ûû³Þù³­û³°ù³Øù³Ùû³Õû³Øù³ù³û³Åû³Èù³Âù³Ãû³Àù³Áû³¾ù³¿û³áû³äù³§û³ªù³û³ ù³û³ù³û³ù³äù³åû³û³ù³û³ù³íû³ðù³çû³êù³àù³áû³Øù³Ùû³¸ù³¹û³¤ù³¥û³ù³û³úù³ûû³æù³çû³Üù³Ýû³Øù³Ùû³¼ù³½û³¦ù³§û³ù³û³ù³û³ù³û³§Ùµ¹Ü³¹Ô³¹Õµ¹Ëµ¹Î³¹Ö³¹×µ¹Éµ¹Ì³¹µ¹³¹Æ³¹Çµ¹Ãµ¹Æ³¹³¹µ¹³µ¹¶³¹°³¹±µ¹®³¹¯µ¹¬³¹­µ¹Ïµ¹Ò³¹µ¹³¹µ¹³¹µ¹³¹÷µ¹ú³¹Ò³¹Óµ¹ûµ¹þ³¹ïµ¹ò³¹Ûµ¹Þ³¹Õµ¹Ø³¹Î³¹Ïµ¹Æ³¹Çµ¹¦³¹§µ¹³¹µ¹ú³¹ûµ¹è³¹éµ¹Ô³¹Õµ¹Ê³¹Ëµ¹Æ³¹Çµ¹ª³¹«µ¹³¹µ¹³¹µ¹þ³¹ÿµ¹ü³¹ýµ¹§Çï¾Êí¾Âí¾Ãï¾¹ï¾¼í¾Äí¾Åï¾·ï¾ºí¾ï¾í¾´í¾µï¾±ï¾´í¾îí¾ïï¾¡ï¾¤í¾í¾ï¾í¾ï¾í¾ï¾½ï¾Àí¾ï¾í¾ùï¾üí¾ïï¾òí¾åï¾èí¾Àí¾Áï¾éï¾ìí¾Ýï¾àí¾Éï¾Ìí¾Ãï¾Æí¾¼í¾½ï¾´í¾µï¾í¾ï¾í¾ï¾èí¾éï¾Öí¾×ï¾Âí¾Ãï¾¸í¾¹ï¾´í¾µï¾í¾ï¾í¾ï¾öí¾÷ï¾ìí¾íï¾êí¾ëï¾§éÃ»ìÃ¹äÃ¹åÃ»ÛÃ»ÞÃ¹æÃ¹çÃ»ÙÃ»ÜÃ¹«Ä»®Ä¹ÖÃ¹×Ã»ÓÃ»ÖÃ¹Ä¹Ä»ÃÃ»ÆÃ¹ÀÃ¹ÁÃ»¾Ã¹¿Ã»¼Ã¹½Ã»ßÄ»âÄ¹¥Ã»¨Ã¹Ã»Ã¹Å»Å¹Ä»Ä¹âÄ¹ãÄ»Ã»Ã¹ÿÂ»Ã¹ëÂ»îÂ¹åÂ»èÂ¹ÞÂ¹ßÂ»ÖÂ¹×Â»¶Â¹·Â»¢Â¹£Â»Â¹Â»øÁ¹ùÁ»äÁ¹åÁ»ÚÁ¹ÛÁ»ÖÁ¹×Á»ºÁ¹»Á»¤Á¹¥Á»Á¹Á»Á¹Á»Á¹Á»§×Àõ
+ÚÀó
+ÒÀó
+ÓÀõ
+ÉÀõ
+ÌÀó
+ÔÀó
+ÕÀõ
+ÇÀõ
+ÊÀó
+Áõ
+Áó
+ÄÀó
+ÅÀõ
+ÁÀõ
+ÄÀó
+þÀó
+ÿÀõ
+±Àõ
+´Àó
+®Àó
+¯Àõ
+¬Àó
+­Àõ
+ªÀó
+«Àõ
+ÍÁõ
+ÐÁó
+Àõ
+Àó
+Àõ
+Àó
+ÿÁõ
+Âó
+õÀõ
+øÀó
+ÐÁó
+ÑÁõ
+ù¿õ
+ü¿ó
+í¿õ
+ð¿ó
+Ù¿õ
+Ü¿ó
+Ó¿õ
+Ö¿ó
+Ì¿ó
+Í¿õ
+Ä¿ó
+Å¿õ
+¤¿ó
+¥¿õ
+¿ó
+¿õ
+ø¾ó
+ù¾õ
+æ¾ó
+ç¾õ
+Ò¾ó
+Ó¾õ
+È¾ó
+É¾õ
+Ä¾ó
+Å¾õ
+¨¾ó
+©¾õ
+¾ó
+¾õ
+¾ó
+¾õ
+ü½ó
+ý½õ
+ú½ó
+û½õ
+§Å½¯È½­À½­Á½¯·½¯º½­Â½­Ã½¯µ½¯¸½­¾¯¾­²½­³½¯¯½¯²½­ì½­í½¯½¯¢½­½­½¯½­½¯½­½¯»¾¯¾¾­½¯½­÷¼¯ú¼­í¾¯ð¾­ã½¯æ½­¾¾­¿¾¯ç¼¯ê¼­Û¼¯Þ¼­Ç¼¯Ê¼­Á¼¯Ä¼­º¼­»¼¯²¼­³¼¯¼­¼¯þ»­ÿ»¯æ»­ç»¯Ô»­Õ»¯À»­Á»¯¶»­·»¯²»­³»¯»­»¯»­»¯ôº­õº¯êº­ëº¯èº­éº¯§³ºé¶ºç®ºç¯ºé¥ºé¨ºç°ºç±ºé£ºé¦ºçõºéøºç ºç¡ºéºé ºçÚºçÛºéºéºçºçºéºçºéºçºé©»é¬»çï¹éò¹çå¹éè¹çÛ»éÞ»çÑºéÔºç¬»ç­»éÕ¹éØ¹çÉ¹éÌ¹çµ¹é¸¹ç¯¹é²¹ç¨¹ç©¹é ¹ç¡¹é¹ç¹éì¸çí¸éÔ¸çÕ¸éÂ¸çÃ¸é®¸ç¯¸é¤¸ç¥¸é ¸ç¡¸é¸ç¸éî·çï·éâ·çã·éØ·çÙ·éÖ·ç×·é§¡·£¤·¡·¡·£·£·¡·¡·£·£·¡ã·£æ·¡·¡·£·£·¡È·¡É·£û¶£þ¶¡ø¶¡ù¶£ö¶¡÷¶£ô¶¡õ¶£¸£¸¡Ý¶£à¶¡Ó¶£Ö¶¡É¸£Ì¸¡¿·£Â·¡¸¡¸£Ã¶£Æ¶¡·¶£º¶¡£¶£¦¶¡¶£ ¶¡¶¡¶£¶¡¶£îµ¡ïµ£Úµ¡Ûµ£Âµ¡Ãµ£°µ¡±µ£µ¡µ£µ¡µ£µ¡µ£ò´¡ó´£Ü´¡Ý´£Ð´¡Ñ´£Æ´¡Ç´£Ä´¡Å´£§´Ý ´Û ´Û ´Ý ´Ý ´Û ´Û ´Ý ÿ³Ý ´Û Ñ´Ý Ô´Û ü³Û ý³Ý ù³Ý ü³Û ¶´Û ·´Ý é³Ý ì³Û æ³Û ç³Ý ä³Û å³Ý â³Û ã³Ý µÝ µÛ Ë³Ý Î³Û Á³Ý Ä³Û ·µÝ ºµÛ ­´Ý °´Û µÛ µÝ ±³Ý ´³Û ¥³Ý ¨³Û ³Ý ³Û ³Ý ³Û ³Û ³Ý ü²Û ý²Ý Ü²Û Ý²Ý È²Û É²Ý °²Û ±²Ý ²Û ²Ý ²Û ²Ý ²Û ²Ý ü±Û ý±Ý à±Û á±Ý Ê±Û Ë±Ý ¾±Û ¿±Ý ´±Û µ±Ý ²±Û ³±Ý §ý°&±&ø°&ù°&ï°&ò°&ú°&û°&í°&ð°&¿±&Â±&ê°&ë°&ç°&ê°&¤±&¥±&×°&Ú°&Ô°&Õ°&Ò°&Ó°&Ð°&Ñ°&ó±&ö±&¹°&¼°&¯°&²°&¥²&¨²&±&±&ö±&÷±&°&¢°&°&°&ÿ¯&°&ù¯&ü¯&ò¯&ó¯&ê¯&ë¯&Ê¯&Ë¯&¶¯&·¯&¯&¯&¯&¯&ø®&ù®&î®&ï®&ê®&ë®&Î®&Ï®&¸®&¹®&¬®&­®&¢®&£®& ®&¡®&§ë­Ñ+î­Ï+æ­Ï+ç­Ñ+Ý­Ñ+à­Ï+è­Ï+é­Ñ+Û­Ñ+Þ­Ï+­®Ñ+°®Ï+Ø­Ï+Ù­Ñ+Õ­Ñ+Ø­Ï+®Ï+®Ñ+Å­Ñ+È­Ï+Â­Ï+Ã­Ñ+À­Ï+Á­Ñ+¾­Ï+¿­Ñ+á®Ñ+ä®Ï+§­Ñ+ª­Ï+­Ñ+ ­Ï+¯Ñ+¯Ï+®Ñ+®Ï+ä®Ï+å®Ñ+­Ñ+­Ï+­Ñ+­Ï+í¬Ñ+ð¬Ï+ç¬Ñ+ê¬Ï+à¬Ï+á¬Ñ+Ø¬Ï+Ù¬Ñ+¸¬Ï+¹¬Ñ+¤¬Ï+¥¬Ñ+¬Ï+¬Ñ+ú«Ï+û«Ñ+æ«Ï+ç«Ñ+Ü«Ï+Ý«Ñ+Ø«Ï+Ù«Ñ+¼«Ï+½«Ñ+¦«Ï+§«Ñ+«Ï+«Ñ+«Ï+«Ñ+«Ï+«Ñ+§Ùª1Üª1Ôª1Õª1Ëª1Îª1Öª1×ª1Éª1Ìª1«1«1Æª1Çª1Ãª1Æª1«1«1³ª1¶ª1°ª1±ª1®ª1¯ª1¬ª1­ª1Ï«1Ò«1ª1ª1ª1ª1¬1¬1÷ª1úª1Ò«1Ó«1û©1þ©1ï©1ò©1Û©1Þ©1Õ©1Ø©1Î©1Ï©1Æ©1Ç©1¦©1§©1©1©1ú¨1û¨1è¨1é¨1Ô¨1Õ¨1Ê¨1Ë¨1Æ¨1Ç¨1ª¨1«¨1¨1¨1¨1¨1þ§1ÿ§1ü§1ý§1§Ç§Å6Ê§Ã6Â§Ã6Ã§Å6¹§Å6¼§Ã6Ä§Ã6Å§Å6·§Å6º§Ã6¨Å6¨Ã6´§Ã6µ§Å6±§Å6´§Ã6î§Ã6ï§Å6¡§Å6¤§Ã6§Ã6§Å6§Ã6§Å6§Ã6§Å6½¨Å6À¨Ã6§Å6§Ã6ù¦Å6ü¦Ã6ï¨Å6ò¨Ã6å§Å6è§Ã6À¨Ã6Á¨Å6é¦Å6ì¦Ã6Ý¦Å6à¦Ã6É¦Å6Ì¦Ã6Ã¦Å6Æ¦Ã6¼¦Ã6½¦Å6´¦Ã6µ¦Å6¦Ã6¦Å6¦Ã6¦Å6è¥Ã6é¥Å6Ö¥Ã6×¥Å6Â¥Ã6Ã¥Å6¸¥Ã6¹¥Å6´¥Ã6µ¥Å6¥Ã6¥Å6¥Ã6¥Å6ö¤Ã6÷¤Å6ì¤Ã6í¤Å6ê¤Ã6ë¤Å6§µ¤ÿ;¸¤ý;°¤ý;±¤ÿ;§¤ÿ;ª¤ý;²¤ý;³¤ÿ;¥¤ÿ;¨¤ý;÷¤ÿ;ú¤ý;¢¤ý;£¤ÿ;¤ÿ;¢¤ý;Ü¤ý;Ý¤ÿ;¤ÿ;¤ý;¤ý;¤ÿ;¤ý;¤ÿ;¤ý;¤ÿ;«¥ÿ;®¥ý;ñ£ÿ;ô£ý;ç£ÿ;ê£ý;Ý¥ÿ;à¥ý;Ó¤ÿ;Ö¤ý;®¥ý;¯¥ÿ;×£ÿ;Ú£ý;Ë£ÿ;Î£ý;·£ÿ;º£ý;±£ÿ;´£ý;ª£ý;«£ÿ;¢£ý;££ÿ;£ý;£ÿ;î¢ý;ï¢ÿ;Ö¢ý;×¢ÿ;Ä¢ý;Å¢ÿ;°¢ý;±¢ÿ;¦¢ý;§¢ÿ;¢¢ý;£¢ÿ;¢ý;¢ÿ;ð¡ý;ñ¡ÿ;ä¡ý;å¡ÿ;Ú¡ý;Û¡ÿ;Ø¡ý;Ù¡ÿ;§£¡¹A¦¡·A¡·A¡¹A¡¹A¡·A ¡·A¡¡¹A¡¹A¡·Aå¡¹Aè¡·A¡·A¡¹A¡¹A¡·AÊ¡·AË¡¹Aý ¹A¡·Aú ·Aû ¹Aø ·Aù ¹Aö ·A÷ ¹A¢¹A¢·Aß ¹Aâ ·AÕ ¹AØ ·AË¢¹AÎ¢·AÁ¡¹AÄ¡·A¢·A¢¹AÅ ¹AÈ ·A¹ ¹A¼ ·A¥ ¹A¨ ·A ¹A¢ ·A ·A ¹A ·A ¹Að·Añ¹AÜ·AÝ¹AÄ·AÅ¹A²·A³¹A·A¹A·A¹A·A¹Aô·Aõ¹AÞ·Aß¹AÒ·AÓ¹AÈ·AÉ¹AÆ·AÇ¹A§óFñFñFóFóFñFñFóFóFñFÓóFÖñFþñFÿóFûóFþñF¸ñF¹óFëóFîñFèñFéóFæñFçóFäñFåóFóFñFÍóFÐñFÃóFÆñF¹óF¼ñF¯óF²ñFñFóF³óF¶ñF§óFªñFóFñFóFñFñFóFþñFÿóFÞñFßóFÊñFËóF²ñF³óF ñF¡óFñFóFñFóFþñFÿóFâñFãóFÌñFÍóFÀñFÁóF¶ñF·óF´ñFµóF§ÿ­L«Lú«Lû­Lñ­Lô«Lü«Lý­Lï­Lò«LÁ­LÄ«Lì«Lí­Lé­Lì«L¦«L§­LÙ­LÜ«LÖ«L×­LÔ«LÕ­LÒ«LÓ­Lõ­Lø«L»­L¾«L±­L´«L§­Lª«L­L «Lø«Lù­L¡­L¤«L­L«L­L«Lû­Lþ«Lô«Lõ­Lì«Lí­LÌ«LÍ­L¸«L¹­L «L¡­L«L­Lú«Lû­Lð«Lñ­Lì«Lí­LÐ«LÑ­Lº«L»­L®«L¯­L¤«L¥­L¢«L£­L§íçQðåQèåQéçQßçQâåQêåQëçQÝçQàåQ¯çQ²åQÚåQÛçQ×çQÚåQåQçQÇçQÊåQÄåQÅçQÂåQÃçQÀåQÁçQãçQæåQ©çQ¬åQçQ¢åQçQåQçQåQæåQççQçQåQçQåQïçQòåQéçQìåQâåQãçQÚåQÛçQºåQ»çQ¦åQ§çQåQçQüåQýçQèåQéçQÞåQßçQÚåQÛçQ¾åQ¿çQ¨åQ©çQåQçQåQçQåQçQ§Û¡WÞWÖW×¡WÍ¡WÐWØWÙ¡WË¡WÎW¡W WÈWÉ¡WÅ¡WÈWW¡Wµ¡W¸W²W³¡W°W±¡W®W¯¡WÑ¡WÔW¡WW¡WW¡WWù¡WüWÔWÕ¡Wý¡WWñ¡WôWÝ¡WàW×¡WÚWÐWÑ¡WÈWÉ¡W¨W©¡WW¡WüWý¡WêWë¡WÖW×¡WÌWÍ¡WÈWÉ¡W¬W­¡WW¡WW¡WW¡WþWÿ¡W§ÉÛ\ÌÙ\ÄÙ\ÅÛ\»Û\¾Ù\ÆÙ\ÇÛ\¹Û\¼Ù\Û\Ù\¶Ù\·Û\³Û\¶Ù\ðÙ\ñÛ\£Û\¦Ù\ Ù\¡Û\Ù\Û\Ù\Û\¿Û\ÂÙ\Û\Ù\ûÛ\þÙ\ñÛ\ôÙ\çÛ\êÙ\ÂÙ\ÃÛ\ëÛ\îÙ\ßÛ\âÙ\ËÛ\ÎÙ\ÅÛ\ÈÙ\¾Ù\¿Û\¶Ù\·Û\Ù\Û\Ù\Û\êÙ\ëÛ\ØÙ\ÙÛ\ÄÙ\ÅÛ\ºÙ\»Û\¶Ù\·Û\Ù\Û\Ù\Û\øÙ\ùÛ\îÙ\ïÛ\ìÙ\íÛ\§·bºb²b³b©b¬b´bµb§bªbùbüb¤b¥b¡b¤bÞbßbbbbbbbbb­b°bóböbébìbßbâbÕbØb°b±bÙbÜbÍbÐb¹b¼b³b¶b¬b­b¤b¥bbbðbñbØbÙbÆbÇb²b³b¨b©b¤b¥bbbòbóbæbçbÜbÝbÚbÛb§¥Ïg¨Íg Íg¡ÏgÏgÍg¢Íg£ÏgÏgÍgçÏgêÍgÍgÏgÏgÍgÌÍgÍÏgÿÏgÍgüÍgýÏgúÍgûÏgøÍgùÏgÏgÍgáÏgäÍg×ÏgÚÍgÍÏgÐÍgÃÏgÆÍgÍgÏgÇÏgÊÍg»Ïg¾Íg§ÏgªÍg¡Ïg¤ÍgÍgÏgÍgÏgòÍgóÏgÞÍgßÏgÆÍgÇÏg´ÍgµÏg Íg¡ÏgÍgÏgÍgÏgöÍg÷ÏgàÍgáÏgÔÍgÕÏgÊÍgËÏgÈÍgÉÏg§mmmmmmmmmmÕmØmmmýmmºm»mímðmêmëmèmémæmçmmmÏmÒmÅmÈm»m¾m±m´mmmµm¸m©m¬mmmmmmmmmàmámÌmÍm´mµm¢m£mmmmmmmämåmÎmÏmÂmÃm¸m¹m¶m·m§ÃrÁrüÁrýÃróÃröÁrþÁrÿÃrñÃrôÁrÃÃrÆÁrîÁrïÃrëÃrîÁr¨Ár©ÃrÛÃrÞÁrØÁrÙÃrÖÁr×ÃrÔÁrÕÃr÷ÃrúÁr½ÃrÀÁr³Ãr¶Ár©Ãr¬ÁrÃr¢ÁrúÁrûÃr£Ãr¦ÁrÃrÁrÃrÁrýÃrÁröÁr÷ÃrîÁrïÃrÎÁrÏÃrºÁr»Ãr¢Ár£ÃrÁrÃrüÁrýÃròÁróÃrîÁrïÃrÒÁrÓÃr¼Ár½Ãr°Ár±Ãr¦Ár§Ãr¤Ár¥Ãr§ïýwòûwêûwëýwáýwäûwìûwíýwßýwâûw±ýw´ûwÜûwÝýwÙýwÜûwûwýwÉýwÌûwÆûwÇýwÄûwÅýwÂûwÃýwåýwèûw«ýw®ûw¡ýw¤ûwýwûwýwûwèûwéýwýwûwýwûwñýwôûwëýwîûwäûwåýwÜûwÝýw¼ûw½ýw¨ûw©ýwûwýwþÿûwÿÿýwêÿûwëÿýwàÿûwáÿýwÜÿûwÝÿýwÀÿûwÁÿýwªÿûw«ÿýwÿûwÿýwÿûwÿýwÿûwÿýw§Ýþ·}àþµ}Øþµ}Ùþ·}Ïþ·}Òþµ}Úþµ}Ûþ·}Íþ·}Ðþµ}ÿ·}¢ÿµ}Êþµ}Ëþ·}Çþ·}Êþµ}ÿµ}ÿ·}·þ·}ºþµ}´þµ}µþ·}²þµ}³þ·}°þµ}±þ·}Óÿ·}Öÿµ}þ·}þµ}þ·}þµ}·}µ}ûþ·}þþµ}Öÿµ}×ÿ·}ÿý·}þµ}óý·}öýµ}ßý·}âýµ}Ùý·}Üýµ}Òýµ}Óý·}Êýµ}Ëý·}ªýµ}«ý·}ýµ}ý·}þüµ}ÿü·}ìüµ}íü·}Øüµ}Ùü·}Îüµ}Ïü·}Êüµ}Ëü·}®üµ}¯ü·}üµ}ü·}üµ}ü·}üµ}ü·}üµ}ü·}§ËûñÎûïÆûïÇûñ½ûñÀûïÈûïÉûñ»ûñ¾ûïüñüï¸ûï¹ûñµûñ¸ûïòûïóûñ¥ûñ¨ûï¢ûï£ûñ ûï¡ûñûïûñÁüñÄüïûñûïýúñûïóüñöüïéûñìûïÄüïÅüñíúñðúïáúñäúïÍúñÐúïÇúñÊúïÀúïÁúñ¸úï¹úñúïúñúïúñìùïíùñÚùïÛùñÆùïÇùñ¼ùï½ùñ¸ùï¹ùñùïùñùïùñúøïûøñðøïñøñîøïïøñ§¹ø«¼ø©´ø©µø««ø«®ø©¶ø©·ø«©ø«¬ø©ûø«þø©¦ø©§ø«£ø«¦ø©àø©áø«ø«ø©ø©ø«ø©ø«ø©ø«¯ù«²ù©õ÷«ø÷©ë÷«î÷©áù«äù©×ø«Úø©²ù©³ù«Û÷«Þ÷©Ï÷«Ò÷©»÷«¾÷©µ÷«¸÷©®÷©¯÷«¦÷©§÷«÷©÷«òö©óö«Úö©Ûö«Èö©Éö«´ö©µö«ªö©«ö«¦ö©§ö«ö©ö«ôõ©õõ«èõ©éõ«Þõ©ßõ«Üõ©Ýõ«§§õåªõã¢õã£õåõåõã¤õã¥õåõåõãéõåìõãõãõåõåõãÎõãÏõåõåõãþôãÿôåüôãýôåúôãûôåöå öããôåæôãÙôåÜôãÏöåÒöãÅõåÈõã öã¡öåÉôåÌôã½ôåÀôã©ôå¬ôã£ôå¦ôãôãôåôãôåôóãõóåàóãáóåÈóãÉóå¶óã·óå¢óã£óåóãóåóãóåøòãùòåâòããòåÖòã×òåÌòãÍòåÊòãËòå§òòòòòòòòòò×òÚòòòÿñò¼ò½òïñòñìñíñêñëñèñéñóóÑñÔñÇñÊñ½óÀó³ò¶òóó·ñºñ«ñ®ñññññññññâðãðÎðÏð¶ð·ð¤ð¥ðððððððæïçïÐïÑïÄïÅïºï»ï¸ï¹ï§ïÙï×þî×ÿîÙõîÙøî×ï×ïÙóîÙöî×ÅïÙÈï×ðî×ñîÙíîÙðî×ªï×«ïÙÝîÙàî×Úî×ÛîÙØî×ÙîÙÖî××îÙùïÙüï×¿îÙÂî×µîÙ¸î×«ðÙ®ð×¡ïÙ¤ï×üï×ýïÙ¥îÙ¨î×îÙî×îÙî×ÿíÙî×øí×ùíÙðí×ñíÙÐí×ÑíÙ¼í×½íÙ¤í×¥íÙí×íÙþì×ÿìÙôì×õìÙðì×ñìÙÔì×ÕìÙ¾ì×¿ìÙ²ì×³ìÙ¨ì×©ìÙ¦ì×§ìÙ§ñëôëìëíëãëæëîëïëáëäë³ì¶ìÞëßëÛëÞëììËëÎëÈëÉëÆëÇëÄëÅëçìêì­ë°ë£ë¦ëííììêìëìëëëëóêöêíêðêæêçêÞêßê¾ê¿êªê«êêêêêìéíéâéãéÞéßéÂéÃé¬é­é é¡ééééé§ßèÍ£âèË£ÚèË£ÛèÍ£ÑèÍ£ÔèË£ÜèË£ÝèÍ£ÏèÍ£ÒèË£¡éÍ£¤éË£ÌèË£ÍèÍ£ÉèÍ£ÌèË£éË£éÍ£¹èÍ£¼èË£¶èË£·èÍ£´èË£µèÍ£²èË£³èÍ£ÕéÍ£ØéË£èÍ£èË£èÍ£èË£êÍ£êË£ýèÍ£éË£ØéË£ÙéÍ£èÍ£èË£õçÍ£øçË£áçÍ£äçË£ÛçÍ£ÞçË£ÔçË£ÕçÍ£ÌçË£ÍçÍ£¬çË£­çÍ£çË£çÍ£çË£çÍ£îæË£ïæÍ£ÚæË£ÛæÍ£ÐæË£ÑæÍ£ÌæË£ÍæÍ£°æË£±æÍ£æË£æÍ£æË£æÍ£æË£æÍ£æË£æÍ£§Íå©Ðå©Èå©Éå©¿å©Âå©Êå©Ëå©½å©Àå©æ©æ©ºå©»å©·å©ºå©ôå©õå©§å©ªå©¤å©¥å©¢å©£å© å©¡å©Ãæ©Ææ©å©å©ÿä©å©õæ©øæ©ëå©îå©Ææ©Çæ©ïä©òä©ãä©æä©Ïä©Òä©Éä©Ìä©Âä©Ãä©ºä©»ä©ä©ä©ä©ä©îã©ïã©Üã©Ýã©Èã©Éã©¾ã©¿ã©ºã©»ã©ã©ã©ã©ã©üâ©ýâ©òâ©óâ©ðâ©ñâ©§»âÁ®¾â¿®¶â¿®·âÁ®­âÁ®°â¿®¸â¿®¹âÁ®«âÁ®®â¿®ýâÁ®ã¿®¨â¿®©âÁ®¥âÁ®¨â¿®ââ¿®ãâÁ®âÁ®â¿®â¿®âÁ®â¿®âÁ®â¿®âÁ®±ãÁ®´ã¿®÷áÁ®úá¿®íáÁ®ðá¿®ããÁ®æã¿®ÙâÁ®Üâ¿®´ã¿®µãÁ®ÝáÁ®àá¿®ÑáÁ®Ôá¿®½áÁ®Àá¿®·áÁ®ºá¿®°á¿®±áÁ®¨á¿®©áÁ®á¿®áÁ®ôà¿®õàÁ®Üà¿®ÝàÁ®Êà¿®ËàÁ®¶à¿®·àÁ®¬à¿®­àÁ®¨à¿®©àÁ®à¿®àÁ®öß¿®÷ßÁ®êß¿®ëßÁ®àß¿®áßÁ®Þß¿®ßßÁ®§©ßû³¬ßù³¤ßù³¥ßû³ßû³ßù³¦ßù³§ßû³ßû³ßù³ëßû³îßù³ßù³ßû³ßû³ßù³Ðßù³Ñßû³ßû³ßù³ßù³ßû³þÞù³ÿÞû³üÞù³ýÞû³àû³¢àù³åÞû³èÞù³ÛÞû³ÞÞù³Ñàû³Ôàù³Çßû³Êßù³¢àù³£àû³ËÞû³ÎÞù³¿Þû³ÂÞù³«Þû³®Þù³¥Þû³¨Þù³Þù³Þû³Þù³Þû³öÝù³÷Ýû³âÝù³ãÝû³ÊÝù³ËÝû³¸Ýù³¹Ýû³¤Ýù³¥Ýû³Ýù³Ýû³Ýù³Ýû³úÜù³ûÜû³äÜù³åÜû³ØÜù³ÙÜû³ÎÜù³ÏÜû³ÌÜù³ÍÜû³§Üµ¹Ü³¹Ü³¹Üµ¹Üµ¹Ü³¹Ü³¹Üµ¹Üµ¹Ü³¹ÙÜµ¹ÜÜ³¹Ü³¹Üµ¹Üµ¹Ü³¹¾Ü³¹¿Üµ¹ñÛµ¹ôÛ³¹îÛ³¹ïÛµ¹ìÛ³¹íÛµ¹êÛ³¹ëÛµ¹Ýµ¹Ý³¹ÓÛµ¹ÖÛ³¹ÉÛµ¹ÌÛ³¹¿Ýµ¹ÂÝ³¹µÜµ¹¸Ü³¹Ý³¹Ýµ¹¹Ûµ¹¼Û³¹­Ûµ¹°Û³¹Ûµ¹Û³¹Ûµ¹Û³¹Û³¹Ûµ¹Û³¹Ûµ¹äÚ³¹åÚµ¹ÐÚ³¹ÑÚµ¹¸Ú³¹¹Úµ¹¦Ú³¹§Úµ¹Ú³¹Úµ¹Ú³¹Úµ¹Ú³¹Úµ¹èÙ³¹éÙµ¹ÒÙ³¹ÓÙµ¹ÆÙ³¹ÇÙµ¹¼Ù³¹½Ùµ¹ºÙ³¹»Ùµ¹§ÿ»¹ú¹û»ñ»ô¹ü¹ý»ï»ò¹Á»Ä¹ì¹í»é»ì¹¦¹§»Ù»Ü¹Ö¹×»Ô¹Õ»Ò¹Ó»õ»ø¹»»¾¹±»´¹§»ª¹» ¹ø¹ù»¡»¤¹»¹»¹û»þ¹ô¹õ»ì¹í»Ì¹Í»¸¹¹» ¹¡»¹»ú¹û»ð¹ñ»ì¹í»Ð¹Ñ»º¹»»®¹¯»¤¹¥»¢¹£»§íõ
+ðó
+èó
+éõ
+ßõ
+âó
+êó
+ëõ
+Ýõ
+àó
+¯õ
+²ó
+Úó
+Ûõ
+×õ
+Úó
+ó
+õ
+Çõ
+Êó
+Äó
+Åõ
+Âó
+Ãõ
+Àó
+Áõ
+ãõ
+æó
+©õ
+¬ó
+õ
+¢ó
+õ
+ó
+õ
+ó
+æó
+çõ
+õ
+ó
+õ
+ó
+ïõ
+òó
+éõ
+ìó
+âó
+ãõ
+Úó
+Ûõ
+ºó
+»õ
+¦ó
+§õ
+ó
+õ
+üó
+ýõ
+èó
+éõ
+Þó
+ßõ
+Úó
+Ûõ
+¾ó
+¿õ
+¨ó
+©õ
+ó
+õ
+ó
+õ
+ó
+õ
+§Û¯Þ­Ö­×¯Í¯Ð­Ø­Ù¯Ë¯Î­¯ ­È­É¯Å¯È­­¯µ¯¸­²­³¯°­±¯®­¯¯Ñ¯Ô­¯­¯­¯­ù¯ü­Ô­Õ¯ý¯­ñ¯ô­Ý¯à­×¯Ú­Ð­Ñ¯È­É¯¨­©¯­¯ü­ý¯ê­ë¯Ö­×¯Ì­Í¯È­É¯¬­­¯­¯­¯­¯þ­ÿ¯§ÉéÌçÄçÅé»é¾çÆçÇé¹é¼çéç¶ç·é³é¶çðçñé£é¦ç ç¡éçéçé¿éÂçéçûéþçñéôççéêçÂçÃéëéîçßéâçËéÎçÅéÈç¾ç¿é¶ç·éçéçéêçëéØçÙéÄçÅéºç»é¶ç·éçéçéøçùéîçïéìçíé§·£º¡²¡³£©£¬¡´¡µ£§£ª¡ù£ü¡¤¡¥£¡£¤¡Þ¡ß££¡¡£¡£¡£­£°¡óÿ£öÿ¡éÿ£ìÿ¡ß£â¡Õ£Ø¡°¡±£Ùÿ£Üÿ¡Íÿ£Ðÿ¡¹ÿ£¼ÿ¡³ÿ£¶ÿ¡¬ÿ¡­ÿ£¤ÿ¡¥ÿ£ÿ¡ÿ£ðþ¡ñþ£Øþ¡Ùþ£Æþ¡Çþ£²þ¡³þ£¨þ¡©þ£¤þ¡¥þ£þ¡þ£òý¡óý£æý¡çý£Üý¡Ýý£Úý¡Ûý£§¥ýÝ ¨ýÛ  ýÛ ¡ýÝ ýÝ ýÛ ¢ýÛ £ýÝ ýÝ ýÛ çýÝ êýÛ ýÛ ýÝ ýÝ ýÛ ÌýÛ ÍýÝ ÿüÝ ýÛ üüÛ ýüÝ úüÛ ûüÝ øüÛ ùüÝ þÝ þÛ áüÝ äüÛ ×üÝ ÚüÛ ÍþÝ ÐþÛ ÃýÝ ÆýÛ þÛ þÝ ÇüÝ ÊüÛ »üÝ ¾üÛ §üÝ ªüÛ ¡üÝ ¤üÛ üÛ üÝ üÛ üÝ òûÛ óûÝ ÞûÛ ßûÝ ÆûÛ ÇûÝ ´ûÛ µûÝ  ûÛ ¡ûÝ ûÛ ûÝ ûÛ ûÝ öúÛ ÷úÝ àúÛ áúÝ ÔúÛ ÕúÝ ÊúÛ ËúÝ ÈúÛ ÉúÝ §ú&ú&ú&ú&ú&ú&ú&ú&ú&ú&Õú&Øú&ú&ú&ýù&ú&ºú&»ú&íù&ðù&êù&ëù&èù&éù&æù&çù&û&û&Ïù&Òù&Åù&Èù&»û&¾û&±ú&´ú&û&û&µù&¸ù&©ù&¬ù&ù&ù&ù&ù&ù&ù&ù&ù&àø&áø&Ìø&Íø&´ø&µø&¢ø&£ø&ø&ø&ø&ø&ø&ø&ä÷&å÷&Î÷&Ï÷&Â÷&Ã÷&¸÷&¹÷&¶÷&·÷&§÷Ñ+÷Ï+üöÏ+ýöÑ+óöÑ+ööÏ+þöÏ+ÿöÑ+ñöÑ+ôöÏ+Ã÷Ñ+Æ÷Ï+îöÏ+ïöÑ+ëöÑ+îöÏ+¨÷Ï+©÷Ñ+ÛöÑ+ÞöÏ+ØöÏ+ÙöÑ+ÖöÏ+×öÑ+ÔöÏ+ÕöÑ+÷÷Ñ+ú÷Ï+½öÑ+ÀöÏ+³öÑ+¶öÏ+©øÑ+¬øÏ+÷Ñ+¢÷Ï+ú÷Ï+û÷Ñ+£öÑ+¦öÏ+öÑ+öÏ+öÑ+öÏ+ýõÑ+öÏ+öõÏ+÷õÑ+îõÏ+ïõÑ+ÎõÏ+ÏõÑ+ºõÏ+»õÑ+¢õÏ+£õÑ+õÏ+õÑ+üôÏ+ýôÑ+òôÏ+óôÑ+îôÏ+ïôÑ+ÒôÏ+ÓôÑ+¼ôÏ+½ôÑ+°ôÏ+±ôÑ+¦ôÏ+§ôÑ+¤ôÏ+¥ôÑ+§ïó1òó1êó1ëó1áó1äó1ìó1íó1ßó1âó1±ô1´ô1Üó1Ýó1Ùó1Üó1ô1ô1Éó1Ìó1Æó1Çó1Äó1Åó1Âó1Ãó1åô1èô1«ó1®ó1¡ó1¤ó1õ1õ1ô1ô1èô1éô1ó1ó1ó1ó1ñò1ôò1ëò1îò1äò1åò1Üò1Ýò1¼ò1½ò1¨ò1©ò1ò1ò1þñ1ÿñ1êñ1ëñ1àñ1áñ1Üñ1Ýñ1Àñ1Áñ1ªñ1«ñ1ñ1ñ1ñ1ñ1ñ1ñ1§ÝðÅ6àðÃ6ØðÃ6ÙðÅ6ÏðÅ6ÒðÃ6ÚðÃ6ÛðÅ6ÍðÅ6ÐðÃ6ñÅ6¢ñÃ6ÊðÃ6ËðÅ6ÇðÅ6ÊðÃ6ñÃ6ñÅ6·ðÅ6ºðÃ6´ðÃ6µðÅ6²ðÃ6³ðÅ6°ðÃ6±ðÅ6ÓñÅ6ÖñÃ6ðÅ6ðÃ6ðÅ6ðÃ6òÅ6òÃ6ûðÅ6þðÃ6ÖñÃ6×ñÅ6ÿïÅ6ðÃ6óïÅ6öïÃ6ßïÅ6âïÃ6ÙïÅ6ÜïÃ6ÒïÃ6ÓïÅ6ÊïÃ6ËïÅ6ªïÃ6«ïÅ6ïÃ6ïÅ6þîÃ6ÿîÅ6ìîÃ6íîÅ6ØîÃ6ÙîÅ6ÎîÃ6ÏîÅ6ÊîÃ6ËîÅ6®îÃ6¯îÅ6îÃ6îÅ6îÃ6îÅ6îÃ6îÅ6îÃ6îÅ6§Ëíÿ;Îíý;Æíý;Çíÿ;½íÿ;Àíý;Èíý;Éíÿ;»íÿ;¾íý;îÿ;îý;¸íý;¹íÿ;µíÿ;¸íý;òíý;óíÿ;¥íÿ;¨íý;¢íý;£íÿ; íý;¡íÿ;íý;íÿ;Áîÿ;Äîý;íÿ;íý;ýìÿ;íý;óîÿ;öîý;éíÿ;ìíý;Äîý;Åîÿ;íìÿ;ðìý;áìÿ;äìý;Íìÿ;Ðìý;Çìÿ;Êìý;Àìý;Áìÿ;¸ìý;¹ìÿ;ìý;ìÿ;ìý;ìÿ;ìëý;íëÿ;Úëý;Ûëÿ;Æëý;Çëÿ;¼ëý;½ëÿ;¸ëý;¹ëÿ;ëý;ëÿ;ëý;ëÿ;úêý;ûêÿ;ðêý;ñêÿ;îêý;ïêÿ;§¹ê¹A¼ê·A´ê·Aµê¹A«ê¹A®ê·A¶ê·A·ê¹A©ê¹A¬ê·Aûê¹Aþê·A¦ê·A§ê¹A£ê¹A¦ê·Aàê·Aáê¹Aê¹Aê·Aê·Aê¹Aê·Aê¹Aê·Aê¹A¯ë¹A²ë·Aõé¹Aøé·Aëé¹Aîé·Aáë¹Aäë·A×ê¹AÚê·A²ë·A³ë¹AÛé¹AÞé·AÏé¹AÒé·A»é¹A¾é·Aµé¹A¸é·A®é·A¯é¹A¦é·A§é¹Aé·Aé¹Aòè·Aóè¹AÚè·AÛè¹AÈè·AÉè¹A´è·Aµè¹Aªè·A«è¹A¦è·A§è¹Aè·Aè¹Aôç·Aõç¹Aèç·Aéç¹AÞç·Aßç¹AÜç·AÝç¹A§§çóFªçñF¢çñF£çóFçóFçñF¤çñF¥çóFçóFçñFéçóFìçñFçñFçóFçóFçñFÎçñFÏçóFçóFçñFþæñFÿæóFüæñFýæóFúæñFûæóFèóF èñFãæóFææñFÙæóFÜæñFÏèóFÒèñFÅçóFÈçñF èñF¡èóFÉæóFÌæñF½æóFÀæñF©æóF¬æñF£æóF¦æñFæñFæóFæñFæóFôåñFõåóFàåñFáåóFÈåñFÉåóF¶åñF·åóF¢åñF£åóFåñFåóFåñFåóFøäñFùäóFâäñFãäóFÖäñF×äóFÌäñFÍäóFÊäñFËäóF§ä­Lä«Lä«Lä­Lä­Lä«Lä«Lä­Lä­Lä«L×ä­LÚä«Lä«Lä­Lÿã­Lä«L¼ä«L½ä­Lïã­Lòã«Lìã«Líã­Lêã«Lëã­Lèã«Léã­Lå­Lå«LÑã­LÔã«LÇã­LÊã«L½å­LÀå«L³ä­L¶ä«Lå«Lå­L·ã­Lºã«L«ã­L®ã«Lã­Lã«Lã­Lã«Lã«Lã­Lã«Lã­Lââ«Lãâ­LÎâ«LÏâ­L¶â«L·â­L¤â«L¥â­Lâ«Lâ­Lâ«Lâ­Lâ«Lâ­Læá«Lçá­LÐá«LÑá­LÄá«LÅá­Lºá«L»á­L¸á«L¹á­L§áçQáåQþàåQÿàçQõàçQøàåQáåQáçQóàçQöàåQÅáçQÈáåQðàåQñàçQíàçQðàåQªáåQ«áçQÝàçQààåQÚàåQÛàçQØàåQÙàçQÖàåQ×àçQùáçQüáåQ¿àçQÂàåQµàçQ¸àåQ«âçQ®âåQ¡áçQ¤áåQüáåQýáçQ¥àçQ¨àåQàçQàåQàçQàåQÿßçQàåQøßåQùßçQðßåQñßçQÐßåQÑßçQ¼ßåQ½ßçQ¤ßåQ¥ßçQßåQßçQþÞåQÿÞçQôÞåQõÞçQðÞåQñÞçQÔÞåQÕÞçQ¾ÞåQ¿ÞçQ²ÞåQ³ÞçQ¨ÞåQ©ÞçQ¦ÞåQ§ÞçQ§ñÝ¡WôÝWìÝWíÝ¡WãÝ¡WæÝWîÝWïÝ¡WáÝ¡WäÝW³Þ¡W¶ÞWÞÝWßÝ¡WÛÝ¡WÞÝWÞWÞ¡WËÝ¡WÎÝWÈÝWÉÝ¡WÆÝWÇÝ¡WÄÝWÅÝ¡WçÞ¡WêÞW­Ý¡W°ÝW£Ý¡W¦ÝWß¡WßWÞ¡WÞWêÞWëÞ¡WÝ¡WÝWÝ¡WÝWóÜ¡WöÜWíÜ¡WðÜWæÜWçÜ¡WÞÜWßÜ¡W¾ÜW¿Ü¡WªÜW«Ü¡WÜWÜ¡WÜWÜ¡WìÛWíÛ¡WâÛWãÛ¡WÞÛWßÛ¡WÂÛWÃÛ¡W¬ÛW­Û¡W ÛW¡Û¡WÛWÛ¡WÛWÛ¡W§ßÚÛ\âÚÙ\ÚÚÙ\ÛÚÛ\ÑÚÛ\ÔÚÙ\ÜÚÙ\ÝÚÛ\ÏÚÛ\ÒÚÙ\¡ÛÛ\¤ÛÙ\ÌÚÙ\ÍÚÛ\ÉÚÛ\ÌÚÙ\ÛÙ\ÛÛ\¹ÚÛ\¼ÚÙ\¶ÚÙ\·ÚÛ\´ÚÙ\µÚÛ\²ÚÙ\³ÚÛ\ÕÛÛ\ØÛÙ\ÚÛ\ÚÙ\ÚÛ\ÚÙ\ÜÛ\ÜÙ\ýÚÛ\ÛÙ\ØÛÙ\ÙÛÛ\ÚÛ\ÚÙ\õÙÛ\øÙÙ\áÙÛ\äÙÙ\ÛÙÛ\ÞÙÙ\ÔÙÙ\ÕÙÛ\ÌÙÙ\ÍÙÛ\¬ÙÙ\­ÙÛ\ÙÙ\ÙÛ\ÙÙ\ÙÛ\îØÙ\ïØÛ\ÚØÙ\ÛØÛ\ÐØÙ\ÑØÛ\ÌØÙ\ÍØÛ\°ØÙ\±ØÛ\ØÙ\ØÛ\ØÙ\ØÛ\ØÙ\ØÛ\ØÙ\ØÛ\§Í×bÐ×bÈ×bÉ×b¿×bÂ×bÊ×bË×b½×bÀ×bØbØbº×b»×b·×bº×bô×bõ×b§×bª×b¤×b¥×b¢×b£×b ×b¡×bÃØbÆØb×b×bÿÖb×bõØbøØbë×bî×bÆØbÇØbïÖbòÖbãÖbæÖbÏÖbÒÖbÉÖbÌÖbÂÖbÃÖbºÖb»ÖbÖbÖbÖbÖbîÕbïÕbÜÕbÝÕbÈÕbÉÕb¾Õb¿ÕbºÕb»ÕbÕbÕbÕbÕbüÔbýÔbòÔbóÔbðÔbñÔb§»ÔÏg¾ÔÍg¶ÔÍg·ÔÏg­ÔÏg°ÔÍg¸ÔÍg¹ÔÏg«ÔÏg®ÔÍgýÔÏgÕÍg¨ÔÍg©ÔÏg¥ÔÏg¨ÔÍgâÔÍgãÔÏgÔÏgÔÍgÔÍgÔÏgÔÍgÔÏgÔÍgÔÏg±ÕÏg´ÕÍg÷ÓÏgúÓÍgíÓÏgðÓÍgãÕÏgæÕÍgÙÔÏgÜÔÍg´ÕÍgµÕÏgÝÓÏgàÓÍgÑÓÏgÔÓÍg½ÓÏgÀÓÍg·ÓÏgºÓÍg°ÓÍg±ÓÏg¨ÓÍg©ÓÏgÓÍgÓÏgôÒÍgõÒÏgÜÒÍgÝÒÏgÊÒÍgËÒÏg¶ÒÍg·ÒÏg¬ÒÍg­ÒÏg¨ÒÍg©ÒÏgÒÍgÒÏgöÑÍg÷ÑÏgêÑÍgëÑÏgàÑÍgáÑÏgÞÑÍgßÑÏg§©Ñm¬Ñm¤Ñm¥ÑmÑmÑm¦Ñm§ÑmÑmÑmëÑmîÑmÑmÑmÑmÑmÐÑmÑÑmÑmÑmÑmÑmþÐmÿÐmüÐmýÐmÒm¢ÒmåÐmèÐmÛÐmÞÐmÑÒmÔÒmÇÑmÊÑm¢Òm£ÒmËÐmÎÐm¿ÐmÂÐm«Ðm®Ðm¥Ðm¨ÐmÐmÐmÐmÐmöÏm÷ÏmâÏmãÏmÊÏmËÏm¸Ïm¹Ïm¤Ïm¥ÏmÏmÏmÏmÏmúÎmûÎmäÎmåÎmØÎmÙÎmÎÎmÏÎmÌÎmÍÎm§ÎÃrÎÁrÎÁrÎÃrÎÃrÎÁrÎÁrÎÃrÎÃrÎÁrÙÎÃrÜÎÁrÎÁrÎÃrÎÃrÎÁr¾ÎÁr¿ÎÃrñÍÃrôÍÁrîÍÁrïÍÃrìÍÁríÍÃrêÍÁrëÍÃrÏÃrÏÁrÓÍÃrÖÍÁrÉÍÃrÌÍÁr¿ÏÃrÂÏÁrµÎÃr¸ÎÁrÏÁrÏÃr¹ÍÃr¼ÍÁr­ÍÃr°ÍÁrÍÃrÍÁrÍÃrÍÁrÍÁrÍÃrÍÁrÍÃräÌÁråÌÃrÐÌÁrÑÌÃr¸ÌÁr¹ÌÃr¦ÌÁr§ÌÃrÌÁrÌÃrÌÁrÌÃrÌÁrÌÃrèËÁréËÃrÒËÁrÓËÃrÆËÁrÇËÃr¼ËÁr½ËÃrºËÁr»ËÃr§ËýwËûwËûwËýw÷ÊýwúÊûwËûwËýwõÊýwøÊûwÇËýwÊËûwòÊûwóÊýwïÊýwòÊûw¬Ëûw­ËýwßÊýwâÊûwÜÊûwÝÊýwÚÊûwÛÊýwØÊûwÙÊýwûËýwþËûwÁÊýwÄÊûw·ÊýwºÊûw­Ìýw°Ìûw£Ëýw¦ËûwþËûwÿËýw§ÊýwªÊûwÊýwÊûwÊýwÊûwÊýwÊûwúÉûwûÉýwòÉûwóÉýwÒÉûwÓÉýw¾Éûw¿Éýw¦Éûw§ÉýwÉûwÉýwÉûwÉýwöÈûw÷ÈýwòÈûwóÈýwÖÈûw×ÈýwÀÈûwÁÈýw´ÈûwµÈýwªÈûw«Èýw¨Èûw©Èýw§óÇ·}öÇµ}îÇµ}ïÇ·}åÇ·}èÇµ}ðÇµ}ñÇ·}ãÇ·}æÇµ}µÈ·}¸Èµ}àÇµ}áÇ·}ÝÇ·}àÇµ}Èµ}È·}ÍÇ·}ÐÇµ}ÊÇµ}ËÇ·}ÈÇµ}ÉÇ·}ÆÇµ}ÇÇ·}éÈ·}ìÈµ}¯Ç·}²Çµ}¥Ç·}¨Çµ}É·}Éµ}È·}Èµ}ìÈµ}íÈ·}Ç·}Çµ}Ç·}Çµ}õÆ·}øÆµ}ïÆ·}òÆµ}èÆµ}éÆ·}àÆµ}áÆ·}ÀÆµ}ÁÆ·}¬Æµ}­Æ·}Æµ}Æ·}Æµ}Æ·}îÅµ}ïÅ·}äÅµ}åÅ·}àÅµ}áÅ·}ÄÅµ}ÅÅ·}®Åµ}¯Å·}¢Åµ}£Å·}Åµ}Å·}Åµ}Å·}§áÄñäÄïÜÄïÝÄñÓÄñÖÄïÞÄïßÄñÑÄñÔÄï£Åñ¦ÅïÎÄïÏÄñËÄñÎÄïÅïÅñ»Äñ¾Äï¸Äï¹Äñ¶Äï·Äñ´ÄïµÄñ×ÅñÚÅïÄñ ÄïÄñÄïÆñÆïÿÄñÅïÚÅïÛÅñÄñÄï÷ÃñúÃïãÃñæÃïÝÃñàÃïÖÃï×ÃñÎÃïÏÃñ®Ãï¯ÃñÃïÃñÃïÃñðÂïñÂñÜÂïÝÂñÒÂïÓÂñÎÂïÏÂñ²Âï³ÂñÂïÂñÂïÂñÂïÂñÂïÂñ§ÏÁ«ÒÁ©ÊÁ©ËÁ«ÁÁ«ÄÁ©ÌÁ©ÍÁ«¿Á«ÂÁ©Â«Â©¼Á©½Á«¹Á«¼Á©öÁ©÷Á«©Á«¬Á©¦Á©§Á«¤Á©¥Á«¢Á©£Á«ÅÂ«ÈÂ©Á«Á©Á«Á©÷Â«úÂ©íÁ«ðÁ©ÈÂ©ÉÂ«ñÀ«ôÀ©åÀ«èÀ©ÑÀ«ÔÀ©ËÀ«ÎÀ©ÄÀ©ÅÀ«¼À©½À«À©À«À©À«ð¿©ñ¿«Þ¿©ß¿«Ê¿©Ë¿«À¿©Á¿«¼¿©½¿« ¿©¡¿«¿©¿«þ¾©ÿ¾«ô¾©õ¾«ò¾©ó¾«§½¾åÀ¾ã¸¾ã¹¾å¯¾å²¾ãº¾ã»¾å­¾å°¾ãÿ¾å¿ãª¾ã«¾å§¾åª¾ãä¾ãå¾å¾å¾ã¾ã¾å¾ã¾å¾ã¾å³¿å¶¿ãù½åü½ãï½åò½ãå¿åè¿ãÛ¾åÞ¾ã¶¿ã·¿åß½åâ½ãÓ½åÖ½ã¿½åÂ½ã¹½å¼½ã²½ã³½åª½ã«½å½ã½åö¼ã÷¼åÞ¼ãß¼åÌ¼ãÍ¼å¸¼ã¹¼å®¼ã¯¼åª¼ã«¼å¼ã¼åø»ãù»åì»ãí»åâ»ãã»åà»ãá»å§«»®»¦»§»» »¨»©»»»í»ð»»»»»Ò»Ó»»»»»»»þºÿº¡¼¤¼çºêºÝºàºÓ¼Ö¼É»Ì»¤¼¥¼ÍºÐºÁºÄº­º°º§ºªº º¡ºººø¹ù¹ä¹å¹Ì¹Í¹º¹»¹¦¹§¹¹¹¹¹ü¸ý¸æ¸ç¸Ú¸Û¸Ð¸Ñ¸Î¸Ï¸§¸Ù¸×¸×¸Ù¸Ù¸×¸×¸Ù¸Ù¸×Û¸ÙÞ¸×¸×¸Ù¸Ù¸×À¸×Á¸Ùó·Ùö·×ð·×ñ·Ùî·×ï·Ùì·×í·Ù¹Ù¹×Õ·ÙØ·×Ë·ÙÎ·×Á¹ÙÄ¹×·¸Ùº¸×¹×¹Ù»·Ù¾·×¯·Ù²·×·Ù·×·Ù·×·×·Ù·×·Ùæ¶×ç¶ÙÒ¶×Ó¶Ùº¶×»¶Ù¨¶×©¶Ù¶×¶Ù¶×¶Ù¶×¶Ùêµ×ëµÙÔµ×ÕµÙÈµ×ÉµÙ¾µ×¿µÙ¼µ×½µÙ§µµµµù´ü´µµ÷´ú´ÉµÌµô´õ´ñ´ô´®µ¯µá´ä´Þ´ß´Ü´Ý´Ú´Û´ýµ¶Ã´Æ´¹´¼´¯¶²¶¥µ¨µ¶¶©´¬´´ ´´´´´ü³ý³ô³õ³Ô³Õ³À³Á³¨³©³³³³³ø²ù²ô²õ²Ø²Ù²Â²Ã²¶²·²¬²­²ª²«²§õ±Í£ø±Ë£ð±Ë£ñ±Í£ç±Í£ê±Ë£ò±Ë£ó±Í£å±Í£è±Ë£·²Í£º²Ë£â±Ë£ã±Í£ß±Í£â±Ë£²Ë£²Í£Ï±Í£Ò±Ë£Ì±Ë£Í±Í£Ê±Ë£Ë±Í£È±Ë£É±Í£ë²Í£î²Ë£±±Í£´±Ë£§±Í£ª±Ë£³Í£ ³Ë£²Í£²Ë£î²Ë£ï²Í£±Í£±Ë£±Í£±Ë£÷°Í£ú°Ë£ñ°Í£ô°Ë£ê°Ë£ë°Í£â°Ë£ã°Í£Â°Ë£Ã°Í£®°Ë£¯°Í£°Ë£°Í£°Ë£°Í£ð¯Ë£ñ¯Í£æ¯Ë£ç¯Í£â¯Ë£ã¯Í£Æ¯Ë£Ç¯Í£°¯Ë£±¯Í£¤¯Ë£¥¯Í£¯Ë£¯Í£¯Ë£¯Í£§ã®©æ®©Þ®©ß®©Õ®©Ø®©à®©á®©Ó®©Ö®©¥¯©¨¯©Ð®©Ñ®©Í®©Ð®©¯©¯©½®©À®©º®©»®©¸®©¹®©¶®©·®©Ù¯©Ü¯©®©¢®©®©®©°©°©¯©¯©Ü¯©Ý¯©®©®©ù­©ü­©å­©è­©ß­©â­©Ø­©Ù­©Ð­©Ñ­©°­©±­©­©­©­©­©ò¬©ó¬©Þ¬©ß¬©Ô¬©Õ¬©Ð¬©Ñ¬©´¬©µ¬©¬©¬©¬©¬©¬©¬©¬©¬©§Ñ«Á®Ô«¿®Ì«¿®Í«Á®Ã«Á®Æ«¿®Î«¿®Ï«Á®Á«Á®Ä«¿®¬Á®¬¿®¾«¿®¿«Á®»«Á®¾«¿®ø«¿®ù«Á®««Á®®«¿®¨«¿®©«Á®¦«¿®§«Á®¤«¿®¥«Á®Ç¬Á®Ê¬¿®«Á®«¿®«Á®«¿®ù¬Á®ü¬¿®ï«Á®ò«¿®Ê¬¿®Ë¬Á®óªÁ®öª¿®çªÁ®êª¿®ÓªÁ®Öª¿®ÍªÁ®Ðª¿®Æª¿®ÇªÁ®¾ª¿®¿ªÁ®ª¿®ªÁ®ª¿®ªÁ®ò©¿®ó©Á®à©¿®á©Á®Ì©¿®Í©Á®Â©¿®Ã©Á®¾©¿®¿©Á®¢©¿®£©Á®©¿®©Á®©¿®©Á®ö¨¿®÷¨Á®ô¨¿®õ¨Á®§¿¨û³Â¨ù³º¨ù³»¨û³±¨û³´¨ù³¼¨ù³½¨û³¯¨û³²¨ù³©û³©ù³¬¨ù³­¨û³©¨û³¬¨ù³æ¨ù³ç¨û³¨û³¨ù³¨ù³¨û³¨ù³¨û³¨ù³¨û³µ©û³¸©ù³û§û³þ§ù³ñ§û³ô§ù³ç©û³ê©ù³Ý¨û³à¨ù³¸©ù³¹©û³á§û³ä§ù³Õ§û³Ø§ù³Á§û³Ä§ù³»§û³¾§ù³´§ù³µ§û³¬§ù³­§û³§ù³§û³ø¦ù³ù¦û³à¦ù³á¦û³Î¦ù³Ï¦û³º¦ù³»¦û³°¦ù³±¦û³¬¦ù³­¦û³¦ù³¦û³ú¥ù³û¥û³î¥ù³ï¥û³ä¥ù³å¥û³â¥ù³ã¥û³§íÓ»ðÓ¹èÓ¹éÓ»ßÓ»âÓ¹êÓ¹ëÓ»ÝÓ»àÓ¹¯Ô»²Ô¹ÚÓ¹ÛÓ»×Ó»ÚÓ¹Ô¹Ô»ÇÓ»ÊÓ¹ÄÓ¹ÅÓ»ÂÓ¹ÃÓ»ÀÓ¹ÁÓ»ãÔ»æÔ¹©Ó»¬Ó¹Ó»¢Ó¹Õ»Õ¹Ô»Ô¹æÔ¹çÔ»Ó»Ó¹Ó»Ó¹ïÒ»òÒ¹éÒ»ìÒ¹âÒ¹ãÒ»ÚÒ¹ÛÒ»ºÒ¹»Ò»¦Ò¹§Ò»Ò¹Ò»üÑ¹ýÑ»èÑ¹éÑ»ÞÑ¹ßÑ»ÚÑ¹ÛÑ»¾Ñ¹¿Ñ»¨Ñ¹©Ñ»Ñ¹Ñ»Ñ¹Ñ»Ñ¹Ñ»§ÛÐõ
+ÞÐó
+ÖÐó
+×Ðõ
+ÍÐõ
+ÐÐó
+ØÐó
+ÙÐõ
+ËÐõ
+ÎÐó
+Ñõ
+ Ñó
+ÈÐó
+ÉÐõ
+ÅÐõ
+ÈÐó
+Ñó
+Ñõ
+µÐõ
+¸Ðó
+²Ðó
+³Ðõ
+°Ðó
+±Ðõ
+®Ðó
+¯Ðõ
+ÑÑõ
+ÔÑó
+Ðõ
+Ðó
+Ðõ
+Ðó
+Òõ
+Òó
+ùÐõ
+üÐó
+ÔÑó
+ÕÑõ
+ýÏõ
+Ðó
+ñÏõ
+ôÏó
+ÝÏõ
+àÏó
+×Ïõ
+ÚÏó
+ÐÏó
+ÑÏõ
+ÈÏó
+ÉÏõ
+¨Ïó
+©Ïõ
+Ïó
+Ïõ
+üÎó
+ýÎõ
+êÎó
+ëÎõ
+ÖÎó
+×Îõ
+ÌÎó
+ÍÎõ
+ÈÎó
+ÉÎõ
+¬Îó
+­Îõ
+Îó
+Îõ
+Îó
+Îõ
+Îó
+Îõ
+þÍó
+ÿÍõ
+§ÉÍ¯ÌÍ­ÄÍ­ÅÍ¯»Í¯¾Í­ÆÍ­ÇÍ¯¹Í¯¼Í­Î¯Î­¶Í­·Í¯³Í¯¶Í­ðÍ­ñÍ¯£Í¯¦Í­ Í­¡Í¯Í­Í¯Í­Í¯¿Î¯ÂÎ­Í¯Í­ûÌ¯þÌ­ñÎ¯ôÎ­çÍ¯êÍ­ÂÎ­ÃÎ¯ëÌ¯îÌ­ßÌ¯âÌ­ËÌ¯ÎÌ­ÅÌ¯ÈÌ­¾Ì­¿Ì¯¶Ì­·Ì¯Ì­Ì¯Ì­Ì¯êË­ëË¯ØË­ÙË¯ÄË­ÅË¯ºË­»Ë¯¶Ë­·Ë¯Ë­Ë¯Ë­Ë¯øÊ­ùÊ¯îÊ­ïÊ¯ìÊ­íÊ¯§·ÊéºÊç²Êç³Êé©Êé¬Êç´ÊçµÊé§ÊéªÊçùÊéüÊç¤Êç¥Êé¡Êé¤ÊçÞÊçßÊéÊéÊçÊçÊéÊçÊéÊçÊé­Ëé°ËçóÉéöÉçéÉéìÉçßËéâËçÕÊéØÊç°Ëç±ËéÙÉéÜÉçÍÉéÐÉç¹Éé¼Éç³Éé¶Éç¬Éç­Éé¤Éç¥ÉéÉçÉéðÈçñÈéØÈçÙÈéÆÈçÇÈé²Èç³Èé¨Èç©Èé¤Èç¥ÈéÈçÈéòÇçóÇéæÇççÇéÜÇçÝÇéÚÇçÛÇé§¥Ç£¨Ç¡ Ç¡¡Ç£Ç£Ç¡¢Ç¡£Ç£Ç£Ç¡çÇ£êÇ¡Ç¡Ç£Ç£Ç¡ÌÇ¡ÍÇ£ÿÆ£Ç¡üÆ¡ýÆ£úÆ¡ûÆ£øÆ¡ùÆ£È£È¡áÆ£äÆ¡×Æ£ÚÆ¡ÍÈ£ÐÈ¡ÃÇ£ÆÇ¡È¡È£ÇÆ£ÊÆ¡»Æ£¾Æ¡§Æ£ªÆ¡¡Æ£¤Æ¡Æ¡Æ£Æ¡Æ£òÅ¡óÅ£ÞÅ¡ßÅ£ÆÅ¡ÇÅ£´Å¡µÅ£ Å¡¡Å£Å¡Å£Å¡Å£öÄ¡÷Ä£àÄ¡áÄ£ÔÄ¡ÕÄ£ÊÄ¡ËÄ£ÈÄ¡ÉÄ£§ÄÝ ÄÛ ÄÛ ÄÝ ÄÝ ÄÛ ÄÛ ÄÝ ÄÝ ÄÛ ÕÄÝ ØÄÛ ÄÛ ÄÝ ýÃÝ ÄÛ ºÄÛ »ÄÝ íÃÝ ðÃÛ êÃÛ ëÃÝ èÃÛ éÃÝ æÃÛ çÃÝ ÅÝ ÅÛ ÏÃÝ ÒÃÛ ÅÃÝ ÈÃÛ »ÅÝ ¾ÅÛ ±ÄÝ ´ÄÛ ÅÛ ÅÝ µÃÝ ¸ÃÛ ©ÃÝ ¬ÃÛ ÃÝ ÃÛ ÃÝ ÃÛ ÃÛ ÃÝ ÃÛ ÃÝ àÂÛ áÂÝ ÌÂÛ ÍÂÝ ´ÂÛ µÂÝ ¢ÂÛ £ÂÝ ÂÛ ÂÝ ÂÛ ÂÝ ÂÛ ÂÝ äÁÛ åÁÝ ÎÁÛ ÏÁÝ ÂÁÛ ÃÁÝ ¸ÁÛ ¹ÁÝ ¶ÁÛ ·ÁÝ §Á&Á&üÀ&ýÀ&óÀ&öÀ&þÀ&ÿÀ&ñÀ&ôÀ&ÃÁ&ÆÁ&îÀ&ïÀ&ëÀ&îÀ&¨Á&©Á&ÛÀ&ÞÀ&ØÀ&ÙÀ&ÖÀ&×À&ÔÀ&ÕÀ&÷Á&úÁ&½À&ÀÀ&³À&¶À&©Â&¬Â&Á&¢Á&úÁ&ûÁ&£À&¦À&À&À&À&À&ý¿&À&ö¿&÷¿&î¿&ï¿&Î¿&Ï¿&º¿&»¿&¢¿&£¿&¿&¿&ü¾&ý¾&ò¾&ó¾&î¾&ï¾&Ò¾&Ó¾&¼¾&½¾&°¾&±¾&¦¾&§¾&¤¾&¥¾&§ï½Ñ+ò½Ï+ê½Ï+ë½Ñ+á½Ñ+ä½Ï+ì½Ï+í½Ñ+ß½Ñ+â½Ï+±¾Ñ+´¾Ï+Ü½Ï+Ý½Ñ+Ù½Ñ+Ü½Ï+¾Ï+¾Ñ+É½Ñ+Ì½Ï+Æ½Ï+Ç½Ñ+Ä½Ï+Å½Ñ+Â½Ï+Ã½Ñ+å¾Ñ+è¾Ï+«½Ñ+®½Ï+¡½Ñ+¤½Ï+¿Ñ+¿Ï+¾Ñ+¾Ï+è¾Ï+é¾Ñ+½Ñ+½Ï+½Ñ+½Ï+ñ¼Ñ+ô¼Ï+ë¼Ñ+î¼Ï+ä¼Ï+å¼Ñ+Ü¼Ï+Ý¼Ñ+¼¼Ï+½¼Ñ+¨¼Ï+©¼Ñ+¼Ï+¼Ñ+þ»Ï+ÿ»Ñ+ê»Ï+ë»Ñ+à»Ï+á»Ñ+Ü»Ï+Ý»Ñ+À»Ï+Á»Ñ+ª»Ï+«»Ñ+»Ï+»Ñ+»Ï+»Ñ+»Ï+»Ñ+§Ýº1àº1Øº1Ùº1Ïº1Òº1Úº1Ûº1Íº1Ðº1»1¢»1Êº1Ëº1Çº1Êº1»1»1·º1ºº1´º1µº1²º1³º1°º1±º1Ó»1Ö»1º1º1º1º1¼1¼1ûº1þº1Ö»1×»1ÿ¹1º1ó¹1ö¹1ß¹1â¹1Ù¹1Ü¹1Ò¹1Ó¹1Ê¹1Ë¹1ª¹1«¹1¹1¹1þ¸1ÿ¸1ì¸1í¸1Ø¸1Ù¸1Î¸1Ï¸1Ê¸1Ë¸1®¸1¯¸1¸1¸1¸1¸1¸1¸1¸1¸1§Ë·Å6Î·Ã6Æ·Ã6Ç·Å6½·Å6À·Ã6È·Ã6É·Å6»·Å6¾·Ã6¸Å6¸Ã6¸·Ã6¹·Å6µ·Å6¸·Ã6ò·Ã6ó·Å6¥·Å6¨·Ã6¢·Ã6£·Å6 ·Ã6¡·Å6·Ã6·Å6Á¸Å6Ä¸Ã6·Å6·Ã6ý¶Å6·Ã6ó¸Å6ö¸Ã6é·Å6ì·Ã6Ä¸Ã6Å¸Å6í¶Å6ð¶Ã6á¶Å6ä¶Ã6Í¶Å6Ð¶Ã6Ç¶Å6Ê¶Ã6À¶Ã6Á¶Å6¸¶Ã6¹¶Å6¶Ã6¶Å6¶Ã6¶Å6ìµÃ6íµÅ6ÚµÃ6ÛµÅ6ÆµÃ6ÇµÅ6¼µÃ6½µÅ6¸µÃ6¹µÅ6µÃ6µÅ6µÃ6µÅ6ú´Ã6û´Å6ð´Ã6ñ´Å6î´Ã6ï´Å6§¹´ÿ;¼´ý;´´ý;µ´ÿ;«´ÿ;®´ý;¶´ý;·´ÿ;©´ÿ;¬´ý;û´ÿ;þ´ý;¦´ý;§´ÿ;£´ÿ;¦´ý;à´ý;á´ÿ;´ÿ;´ý;´ý;´ÿ;´ý;´ÿ;´ý;´ÿ;¯µÿ;²µý;õ³ÿ;ø³ý;ë³ÿ;î³ý;áµÿ;äµý;×´ÿ;Ú´ý;²µý;³µÿ;Û³ÿ;Þ³ý;Ï³ÿ;Ò³ý;»³ÿ;¾³ý;µ³ÿ;¸³ý;®³ý;¯³ÿ;¦³ý;§³ÿ;³ý;³ÿ;ò²ý;ó²ÿ;Ú²ý;Û²ÿ;È²ý;É²ÿ;´²ý;µ²ÿ;ª²ý;«²ÿ;¦²ý;§²ÿ;²ý;²ÿ;ô±ý;õ±ÿ;è±ý;é±ÿ;Þ±ý;ß±ÿ;Ü±ý;Ý±ÿ;§§±¹Aª±·A¢±·A£±¹A±¹A±·A¤±·A¥±¹A±¹A±·Aé±¹Aì±·A±·A±¹A±¹A±·AÎ±·AÏ±¹A±¹A±·Aþ°·Aÿ°¹Aü°·Aý°¹Aú°·Aû°¹A²¹A ²·Aã°¹Aæ°·AÙ°¹AÜ°·AÏ²¹AÒ²·AÅ±¹AÈ±·A ²·A¡²¹AÉ°¹AÌ°·A½°¹AÀ°·A©°¹A¬°·A£°¹A¦°·A°·A°¹A°·A°¹Aô¯·Aõ¯¹Aà¯·Aá¯¹AÈ¯·AÉ¯¹A¶¯·A·¯¹A¢¯·A£¯¹A¯·A¯¹A¯·A¯¹Aø®·Aù®¹Aâ®·Aã®¹AÖ®·A×®¹AÌ®·AÍ®¹AÊ®·AË®¹A§®óF®ñF®ñF®óF®óF®ñF®ñF®óF®óF®ñF×®óFÚ®ñF®ñF®óFÿ­óF®ñF¼®ñF½®óFï­óFò­ñFì­ñFí­óFê­ñFë­óFè­ñFé­óF¯óF¯ñFÑ­óFÔ­ñFÇ­óFÊ­ñF½¯óFÀ¯ñF³®óF¶®ñF¯ñF¯óF·­óFº­ñF«­óF®­ñF­óF­ñF­óF­ñF­ñF­óF­ñF­óFâ¬ñFã¬óFÎ¬ñFÏ¬óF¶¬ñF·¬óF¤¬ñF¥¬óF¬ñF¬óF¬ñF¬óF¬ñF¬óFæ«ñFç«óFÐ«ñFÑ«óFÄ«ñFÅ«óFº«ñF»«óF¸«ñF¹«óF§«­L««Lþª«Lÿª­Lõª­Løª«L««L«­Lóª­Löª«LÅ«­LÈ««Lðª«Lñª­Líª­Lðª«Lª««L««­LÝª­Làª«LÚª«LÛª­LØª«LÙª­LÖª«L×ª­Lù«­Lü««L¿ª­LÂª«Lµª­L¸ª«L«¬­L®¬«L¡«­L¤««Lü««Lý«­L¥ª­L¨ª«Lª­Lª«Lª­Lª«Lÿ©­Lª«Lø©«Lù©­Lð©«Lñ©­LÐ©«LÑ©­L¼©«L½©­L¤©«L¥©­L©«L©­Lþ¨«Lÿ¨­Lô¨«Lõ¨­Lð¨«Lñ¨­LÔ¨«LÕ¨­L¾¨«L¿¨­L²¨«L³¨­L¨¨«L©¨­L¦¨«L§¨­L§ñ§çQô§åQì§åQí§çQã§çQæ§åQî§åQï§çQá§çQä§åQ³¨çQ¶¨åQÞ§åQß§çQÛ§çQÞ§åQ¨åQ¨çQË§çQÎ§åQÈ§åQÉ§çQÆ§åQÇ§çQÄ§åQÅ§çQç¨çQê¨åQ­§çQ°§åQ£§çQ¦§åQ©çQ©åQ¨çQ¨åQê¨åQë¨çQ§çQ§åQ§çQ§åQó¦çQö¦åQí¦çQð¦åQæ¦åQç¦çQÞ¦åQß¦çQ¾¦åQ¿¦çQª¦åQ«¦çQ¦åQ¦çQ¦åQ¦çQì¥åQí¥çQâ¥åQã¥çQÞ¥åQß¥çQÂ¥åQÃ¥çQ¬¥åQ­¥çQ ¥åQ¡¥çQ¥åQ¥çQ¥åQ¥çQ§ß¤¡Wâ¤WÚ¤WÛ¤¡WÑ¤¡WÔ¤WÜ¤WÝ¤¡WÏ¤¡WÒ¤W¡¥¡W¤¥WÌ¤WÍ¤¡WÉ¤¡WÌ¤W¥W¥¡W¹¤¡W¼¤W¶¤W·¤¡W´¤Wµ¤¡W²¤W³¤¡WÕ¥¡WØ¥W¤¡W¤W¤¡W¤W¦¡W¦Wý¤¡W¥WØ¥WÙ¥¡W¤¡W¤Wõ£¡Wø£Wá£¡Wä£WÛ£¡WÞ£WÔ£WÕ£¡WÌ£WÍ£¡W¬£W­£¡W£W£¡W£W£¡Wî¢Wï¢¡WÚ¢WÛ¢¡WÐ¢WÑ¢¡WÌ¢WÍ¢¡W°¢W±¢¡W¢W¢¡W¢W¢¡W¢W¢¡W¢W¢¡W§Í¡Û\Ð¡Ù\È¡Ù\É¡Û\¿¡Û\Â¡Ù\Ê¡Ù\Ë¡Û\½¡Û\À¡Ù\¢Û\¢Ù\º¡Ù\»¡Û\·¡Û\º¡Ù\ô¡Ù\õ¡Û\§¡Û\ª¡Ù\¤¡Ù\¥¡Û\¢¡Ù\£¡Û\ ¡Ù\¡¡Û\Ã¢Û\Æ¢Ù\¡Û\¡Ù\ÿ Û\¡Ù\õ¢Û\ø¢Ù\ë¡Û\î¡Ù\Æ¢Ù\Ç¢Û\ï Û\ò Ù\ã Û\æ Ù\Ï Û\Ò Ù\É Û\Ì Ù\Â Ù\Ã Û\º Ù\» Û\ Ù\ Û\ Ù\ Û\îÙ\ïÛ\ÜÙ\ÝÛ\ÈÙ\ÉÛ\¾Ù\¿Û\ºÙ\»Û\Ù\Û\Ù\Û\üÙ\ýÛ\òÙ\óÛ\ðÙ\ñÛ\§»b¾b¶b·b­b°b¸b¹b«b®býbb¨b©b¥b¨bâbãbbbbbbbbb±b´b÷búbíbðbãbæbÙbÜb´bµbÝbàbÑbÔb½bÀb·bºb°b±b¨b©bbbôbõbÜbÝbÊbËb¶b·b¬b­b¨b©bbböb÷bêbëbàbábÞbßb§©Ïg¬Íg¤Íg¥ÏgÏgÍg¦Íg§ÏgÏgÍgëÏgîÍgÍgÏgÏgÍgÐÍgÑÏgÏgÍgÍgÏgþÍgÿÏgüÍgýÏgÏg¢ÍgåÏgèÍgÛÏgÞÍgÑÏgÔÍgÇÏgÊÍg¢Íg£ÏgËÏgÎÍg¿ÏgÂÍg«Ïg®Íg¥Ïg¨ÍgÍgÏgÍgÏgöÍg÷ÏgâÍgãÏgÊÍgËÏg¸Íg¹Ïg¤Íg¥ÏgÍgÏgÍgÏgúÍgûÏgäÍgåÏgØÍgÙÏgÎÍgÏÏgÌÍgÍÏg§mmmmmmmmmmÙmÜmmmmm¾m¿mñmômîmïmìmímêmëmmmÓmÖmÉmÌm¿mÂmµm¸mmm¹m¼m­m°mmmmmmmmmämåmÐmÑm¸m¹m¦m§mmmmmmmèmémÒmÓmÆmÇm¼m½mºm»m§ÃrÁrÁrÃr÷ÃrúÁrÁrÃrõÃrøÁrÇÃrÊÁròÁróÃrïÃròÁr¬Ár­ÃrßÃrâÁrÜÁrÝÃrÚÁrÛÃrØÁrÙÃrûÃrþÁrÁÃrÄÁr·ÃrºÁr­Ãr°Ár£Ãr¦ÁrþÁrÿÃr§ÃrªÁrÃrÁrÃrÁrÃrÁrúÁrûÃròÁróÃrÒÁrÓÃr¾Ár¿Ãr¦Ár§ÃrÁrÃrÁrÃröÁr÷ÃròÁróÃrÖÁr×ÃrÀÁrÁÃr´ÁrµÃrªÁr«Ãr¨Ár©Ãr§óýwöûwîûwïýwåýwèûwðûwñýwãýwæûwµýw¸ûwàûwáýwÝýwàûwûwýwÍýwÐûwÊûwËýwÈûwÉýwÆûwÇýwéýwìûw¯ýw²ûw¥ýw¨ûwýwûwýwûwìûwíýwýwûwýwûwõýwøûwïýwòûwèûwéýwàûwáýwÀûwÁýw¬ûw­ýwûwýwûwýwîûwïýwäûwåýwàûwáýwÄûwÅýw®ûw¯ýw¢ûw£ýwûwýwûwýw§á·}äµ}Üµ}Ý·}Ó·}Öµ}Þµ}ß·}Ñ·}Ôµ}£·}¦µ}Îµ}Ï·}Ë·}Îµ}µ}·}»·}¾µ}¸µ}¹·}¶µ}··}´µ}µ·}×·}Úµ}·} µ}·}µ}·}µ}ÿ·}µ}Úµ}Û·}·}µ}÷·}úµ}ã·}æµ}Ý·}àµ}Öµ}×·}Îµ}Ï·}®µ}¯·}µ}·}µ}·}ðµ}ñ·}Üµ}Ý·}Òµ}Ó·}Îµ}Ï·}²µ}³·}µ}·}µ}·}µ}·}µ}·}§ÏñÒïÊïËñÁñÄïÌïÍñ¿ñÂïñï¼ï½ñ¹ñ¼ïöï÷ñ©ñ¬ï¦ï§ñ¤ï¥ñ¢ï£ñÅñÈïñïñï÷ñúïíñðïÈïÉñññôïåñèïÑñÔïËñÎïÄïÅñ¼ï½ñïñïñðïññÞïßñÊïËñÀïÁñ¼ï½ñ ï¡ñïñþïÿñôïõñòïóñ§½«À©¸©¹«¯«²©º©»«­«°©ÿ«©ª©««§«ª©ä©å««©©«©«©«³«¶©ù«ü©ï«ò©å«è©Û«Þ©¶©·«ß«â©Ó«Ö©¿«Â©¹«¼©²©³«ª©««©«ö©÷«Þ©ß«Ì©Í«¸©¹«®©¯«ª©««©«ø©ù«ì©í«â©ã«à©á«§«å®ã¦ã§åå ã¨ã©ååãíåðããååãÒãÓååããåãåþãÿå¡å¤ãçåêãÝåàãÓåÖãÉåÌã¤ã¥åÍåÐãÁåÄã­å°ã§åªã ã¡åãåøãùåäãååÌãÍåºã»å¦ã§åãåãåüãýåæãçåÚãÛåÐãÑåÎãÏå§ÛÞÀÁóöðñîïìíÕØËÎÁÄ·º»¾¯²æçÒÓº»¨©êÿëÿÔÿÕÿÈÿÉÿ¾ÿ¿ÿ¼ÿ½ÿ§ÿÙÿ×ÿ×ÿÙùþÙüþ×ÿ×ÿÙ÷þÙúþ×ÉÿÙÌÿ×ôþ×õþÙñþÙôþ×®ÿ×¯ÿÙáþÙäþ×Þþ×ßþÙÜþ×ÝþÙÚþ×ÛþÙýÿÙ×ÃþÙÆþ×¹þÙ¼þ×¯Ù²×¥ÿÙ¨ÿ××Ù©þÙ¬þ×þÙ þ×þÙþ×þÙþ×üý×ýýÙôý×õýÙÔý×ÕýÙÀý×ÁýÙ¨ý×©ýÙý×ýÙý×ýÙøü×ùüÙôü×õüÙØü×ÙüÙÂü×ÃüÙ¶ü×·üÙ¬ü×­üÙªü×«üÙ§õûøûðûñûçûêûòûóûåûèû·üºüâûãûßûâûüüÏûÒûÌûÍûÊûËûÈûÉûëüîü±û´û§ûªûý ýüüîüïüûûûû÷úúúñúôúêúëúâúãúÂúÃú®ú¯úúúúúðùñùæùçùâùãùÆùÇù°ù±ù¤ù¥ùùùùù§ãøÍ£æøË£ÞøË£ßøÍ£ÕøÍ£ØøË£àøË£áøÍ£ÓøÍ£ÖøË£¥ùÍ£¨ùË£ÐøË£ÑøÍ£ÍøÍ£ÐøË£ùË£ùÍ£½øÍ£ÀøË£ºøË£»øÍ£¸øË£¹øÍ£¶øË£·øÍ£ÙùÍ£ÜùË£øÍ£¢øË£øÍ£øË£úÍ£úË£ùÍ£ùË£ÜùË£ÝùÍ£øÍ£øË£ù÷Í£ü÷Ë£å÷Í£è÷Ë£ß÷Í£â÷Ë£Ø÷Ë£Ù÷Í£Ð÷Ë£Ñ÷Í£°÷Ë£±÷Í£÷Ë£÷Í£÷Ë£÷Í£òöË£óöÍ£ÞöË£ßöÍ£ÔöË£ÕöÍ£ÐöË£ÑöÍ£´öË£µöÍ£öË£öÍ£öË£öÍ£öË£öÍ£öË£öÍ£§Ñõ©Ôõ©Ìõ©Íõ©Ãõ©Æõ©Îõ©Ïõ©Áõ©Äõ©ö©ö©¾õ©¿õ©»õ©¾õ©øõ©ùõ©«õ©®õ©¨õ©©õ©¦õ©§õ©¤õ©¥õ©Çö©Êö©õ©õ©õ©õ©ùö©üö©ïõ©òõ©Êö©Ëö©óô©öô©çô©êô©Óô©Öô©Íô©Ðô©Æô©Çô©¾ô©¿ô©ô©ô©ô©ô©òó©óó©àó©áó©Ìó©Íó©Âó©Ãó©¾ó©¿ó©¢ó©£ó©ó©ó©ó©ó©öò©÷ò©ôò©õò©§¿òÁ®Âò¿®ºò¿®»òÁ®±òÁ®´ò¿®¼ò¿®½òÁ®¯òÁ®²ò¿®óÁ®ó¿®¬ò¿®­òÁ®©òÁ®¬ò¿®æò¿®çòÁ®òÁ®ò¿®ò¿®òÁ®ò¿®òÁ®ò¿®òÁ®µóÁ®¸ó¿®ûñÁ®þñ¿®ññÁ®ôñ¿®çóÁ®êó¿®ÝòÁ®àò¿®¸ó¿®¹óÁ®áñÁ®äñ¿®ÕñÁ®Øñ¿®ÁñÁ®Äñ¿®»ñÁ®¾ñ¿®´ñ¿®µñÁ®¬ñ¿®­ñÁ®ñ¿®ñÁ®øð¿®ùðÁ®àð¿®áðÁ®Îð¿®ÏðÁ®ºð¿®»ðÁ®°ð¿®±ðÁ®¬ð¿®­ðÁ®ð¿®ðÁ®úï¿®ûïÁ®îï¿®ïïÁ®äï¿®åïÁ®âï¿®ãïÁ®§³»¶¹®¹¯»¥»¨¹°¹±»£»¦¹õ»ø¹ ¹¡»» ¹Ú¹Û»»¹¹»¹»¹»©»¬¹ï»ò¹å»è¹Û»Þ¹Ñ»Ô¹¬¹­»Õ»Ø¹É»Ì¹µ»¸¹¯»²¹¨¹©» ¹¡»¹»ì¹í»Ô¹Õ»Â¹Ã»®¹¯»¤¹¥» ¹¡»¹»î¹ï»â¹ã»Ø¹Ù»Ö¹×»§¡õ
+¤ó
+ó
+õ
+õ
+ó
+ó
+õ
+õ
+ó
+ãõ
+æó
+ó
+õ
+õ
+ó
+Èó
+Éõ
+ûõ
+þó
+øó
+ùõ
+öó
+÷õ
+ôó
+õõ
+õ
+ó
+Ýõ
+àó
+Óõ
+Öó
+Éõ
+Ìó
+¿õ
+Âó
+ó
+õ
+Ãõ
+Æó
+·õ
+ºó
+£õ
+¦ó
+õ
+ ó
+ó
+õ
+ó
+õ
+îó
+ïõ
+Úó
+Ûõ
+Âó
+Ãõ
+°ó
+±õ
+ó
+õ
+ó
+õ
+ó
+õ
+òó
+óõ
+Üó
+Ýõ
+Ðó
+Ñõ
+Æó
+Çõ
+Äó
+Åõ
+§¯­­¯¯­­¯ÿ¯­Ñ¯Ô­ü­ý¯ù¯ü­¶­·¯é¯ì­æ­ç¯ä­å¯â­ã¯¯­Ë¯Î­Á¯Ä­·¯º­­¯°­­¯±¯´­¥¯¨­¯­¯­­¯ü­ý¯Ü­Ý¯È­É¯°­±¯­¯­¯­¯ü­ý¯à­á¯Ê­Ë¯¾­¿¯´­µ¯²­³¯§ýéçøçùéïéòçúçûéíéðç¿éÂçêçëéçéêç¤ç¥é×éÚçÔçÕéÒçÓéÐçÑéóéöç¹é¼ç¯é²ç¥é¨çéçöç÷éé¢çéçÿéçùéüçòçóéêçëéÊçËé¶ç·éçéçéøçùéîçïéêçëéÎçÏé¸ç¹é¬ç­é¢ç£é ç¡é§ë£î¡æ¡ç£Ý£à¡è¡é£Û£Þ¡­£°¡Ø¡Ù£Õ£Ø¡¡£Å£È¡Â¡Ã£À¡Á£¾¡¿£á£ä¡§£ª¡£ ¡£¡£¡ä¡å££¡£¡í£ð¡ç£ê¡à¡á£Ø¡Ù£¸¡¹£¤¡¥£¡£ú¡û£æ¡ç£Ü¡Ý£Ø¡Ù£¼¡½£¦¡§£¡£¡£¡£§ÙÝ ÜÛ ÔÛ ÕÝ ËÝ ÎÛ ÖÛ ×Ý ÉÝ ÌÛ Ý Û ÆÛ ÇÝ ÃÝ ÆÛ Û Ý ³Ý ¶Û °Û ±Ý ®Û ¯Ý ¬Û ­Ý ÏÝ ÒÛ Ý Û Ý Û Ý Û ÷Ý úÛ ÒÛ ÓÝ ûÝ þÛ ïÝ òÛ ÛÝ ÞÛ ÕÝ ØÛ ÎÛ ÏÝ ÆÛ ÇÝ ¦Û §Ý Û Ý úÛ ûÝ èÛ éÝ ÔÛ ÕÝ ÊÛ ËÝ ÆÛ ÇÝ ªÛ «Ý Û Ý Û Ý þÛ ÿÝ üÛ ýÝ §Ç&Ê&Â&Ã&¹&¼&Ä&Å&·&º&&&´&µ&±&´&î&ï&¡&¤&&&&&&&½&À&&&ù&ü&ï&ò&å&è&À&Á&é&ì&Ý&à&É&Ì&Ã&Æ&¼&½&´&µ&&&&&è&é&Ö&×&Â&Ã&¸&¹&´&µ&&&&&ö&÷&ì&í&ê&ë&§µÑ+¸Ï+°Ï+±Ñ+§Ñ+ªÏ+²Ï+³Ñ+¥Ñ+¨Ï+÷Ñ+úÏ+¢Ï+£Ñ+Ñ+¢Ï+ÜÏ+ÝÑ+Ñ+Ï+Ï+Ñ+Ï+Ñ+Ï+Ñ+«Ñ+®Ï+ñÑ+ôÏ+çÑ+êÏ+ÝÑ+àÏ+ÓÑ+ÖÏ+®Ï+¯Ñ+×Ñ+ÚÏ+ËÑ+ÎÏ+·Ñ+ºÏ+±Ñ+´Ï+ªÏ+«Ñ+¢Ï+£Ñ+Ï+Ñ+îÏ+ïÑ+ÖÏ+×Ñ+ÄÏ+ÅÑ+°Ï+±Ñ+¦Ï+§Ñ+¢Ï+£Ñ+Ï+Ñ+ðÿÏ+ñÿÑ+äÿÏ+åÿÑ+ÚÿÏ+ÛÿÑ+ØÿÏ+ÙÿÑ+§£ÿ1¦ÿ1ÿ1ÿ1ÿ1ÿ1 ÿ1¡ÿ1ÿ1ÿ1åÿ1èÿ1ÿ1ÿ1ÿ1ÿ1Êÿ1Ëÿ1ýþ1ÿ1úþ1ûþ1øþ1ùþ1öþ1÷þ111ßþ1âþ1Õþ1Øþ1Ë1Î1Áÿ1Äÿ111Åþ1Èþ1¹þ1¼þ1¥þ1¨þ1þ1¢þ1þ1þ1þ1þ1ðý1ñý1Üý1Ýý1Äý1Åý1²ý1³ý1ý1ý1ý1ý1ý1ý1ôü1õü1Þü1ßü1Òü1Óü1Èü1Éü1Æü1Çü1§üÅ6üÃ6üÃ6üÅ6üÅ6üÃ6üÃ6üÅ6üÅ6üÃ6ÓüÅ6ÖüÃ6þûÃ6ÿûÅ6ûûÅ6þûÃ6¸üÃ6¹üÅ6ëûÅ6îûÃ6èûÃ6éûÅ6æûÃ6çûÅ6äûÃ6åûÅ6ýÅ6ýÃ6ÍûÅ6ÐûÃ6ÃûÅ6ÆûÃ6¹ýÅ6¼ýÃ6¯üÅ6²üÃ6ýÃ6ýÅ6³ûÅ6¶ûÃ6§ûÅ6ªûÃ6ûÅ6ûÃ6ûÅ6ûÃ6ûÃ6ûÅ6þúÃ6ÿúÅ6ÞúÃ6ßúÅ6ÊúÃ6ËúÅ6²úÃ6³úÅ6 úÃ6¡úÅ6úÃ6úÅ6úÃ6úÅ6þùÃ6ÿùÅ6âùÃ6ãùÅ6ÌùÃ6ÍùÅ6ÀùÃ6ÁùÅ6¶ùÃ6·ùÅ6´ùÃ6µùÅ6§ÿøÿ;ùý;úøý;ûøÿ;ñøÿ;ôøý;üøý;ýøÿ;ïøÿ;òøý;Áùÿ;Äùý;ìøý;íøÿ;éøÿ;ìøý;¦ùý;§ùÿ;Ùøÿ;Üøý;Öøý;×øÿ;Ôøý;Õøÿ;Òøý;Óøÿ;õùÿ;øùý;»øÿ;¾øý;±øÿ;´øý;§úÿ;ªúý;ùÿ; ùý;øùý;ùùÿ;¡øÿ;¤øý;øÿ;øý;øÿ;øý;û÷ÿ;þ÷ý;ô÷ý;õ÷ÿ;ì÷ý;í÷ÿ;Ì÷ý;Í÷ÿ;¸÷ý;¹÷ÿ; ÷ý;¡÷ÿ;÷ý;÷ÿ;úöý;ûöÿ;ðöý;ñöÿ;ìöý;íöÿ;Ðöý;Ñöÿ;ºöý;»öÿ;®öý;¯öÿ;¤öý;¥öÿ;¢öý;£öÿ;§íõ¹Aðõ·Aèõ·Aéõ¹Aßõ¹Aâõ·Aêõ·Aëõ¹AÝõ¹Aàõ·A¯ö¹A²ö·AÚõ·AÛõ¹A×õ¹AÚõ·Aö·Aö¹AÇõ¹AÊõ·AÄõ·AÅõ¹AÂõ·AÃõ¹AÀõ·AÁõ¹Aãö¹Aæö·A©õ¹A¬õ·Aõ¹A¢õ·A÷¹A÷·Aö¹Aö·Aæö·Açö¹Aõ¹Aõ·Aõ¹Aõ·Aïô¹Aòô·Aéô¹Aìô·Aâô·Aãô¹AÚô·AÛô¹Aºô·A»ô¹A¦ô·A§ô¹Aô·Aô¹Aüó·Aýó¹Aèó·Aéó¹AÞó·Aßó¹AÚó·AÛó¹A¾ó·A¿ó¹A¨ó·A©ó¹Aó·Aó¹Aó·Aó¹Aó·Aó¹A§ÛòóFÞòñFÖòñF×òóFÍòóFÐòñFØòñFÙòóFËòóFÎòñFóóF óñFÈòñFÉòóFÅòóFÈòñFóñFóóFµòóF¸òñF²òñF³òóF°òñF±òóF®òñF¯òóFÑóóFÔóñFòóFòñFòóFòñFôóFôñFùòóFüòñFÔóñFÕóóFýñóFòñFññóFôññFÝñóFàññF×ñóFÚññFÐññFÑñóFÈññFÉñóF¨ññF©ñóFññFñóFüðñFýðóFêðñFëðóFÖðñF×ðóFÌðñFÍðóFÈðñFÉðóF¬ðñF­ðóFðñFðóFðñFðóFðñFðóFþïñFÿïóF§Éï­LÌï«LÄï«LÅï­L»ï­L¾ï«LÆï«LÇï­L¹ï­L¼ï«Lð­Lð«L¶ï«L·ï­L³ï­L¶ï«Lðï«Lñï­L£ï­L¦ï«L ï«L¡ï­Lï«Lï­Lï«Lï­L¿ð­LÂð«Lï­Lï«Lûî­Lþî«Lñð­Lôð«Lçï­Lêï«LÂð«LÃð­Lëî­Lîî«Lßî­Lâî«LËî­LÎî«LÅî­LÈî«L¾î«L¿î­L¶î«L·î­Lî«Lî­Lî«Lî­Lêí«Lëí­LØí«LÙí­LÄí«LÅí­Lºí«L»í­L¶í«L·í­Lí«Lí­Lí«Lí­Løì«Lùì­Lîì«Lïì­Lìì«Líì­L§·ìçQºìåQ²ìåQ³ìçQ©ìçQ¬ìåQ´ìåQµìçQ§ìçQªìåQùìçQüìåQ¤ìåQ¥ìçQ¡ìçQ¤ìåQÞìåQßìçQìçQìåQìåQìçQìåQìçQìåQìçQ­íçQ°íåQóëçQöëåQéëçQìëåQßíçQâíåQÕìçQØìåQ°íåQ±íçQÙëçQÜëåQÍëçQÐëåQ¹ëçQ¼ëåQ³ëçQ¶ëåQ¬ëåQ­ëçQ¤ëåQ¥ëçQëåQëçQðêåQñêçQØêåQÙêçQÆêåQÇêçQ²êåQ³êçQ¨êåQ©êçQ¤êåQ¥êçQêåQêçQòéåQóéçQæéåQçéçQÜéåQÝéçQÚéåQÛéçQ§¥é¡W¨éW éW¡é¡Wé¡WéW¢éW£é¡Wé¡WéWçé¡WêéWéWé¡Wé¡WéWÌéWÍé¡Wÿè¡WéWüèWýè¡WúèWûè¡WøèWùè¡Wê¡WêWáè¡WäèW×è¡WÚèWÍê¡WÐêWÃé¡WÆéWêWê¡WÇè¡WÊèW»è¡W¾èW§è¡WªèW¡è¡W¤èWèWè¡WèWè¡WòçWóç¡WÞçWßç¡WÆçWÇç¡W´çWµç¡W çW¡ç¡WçWç¡WçWç¡WöæW÷æ¡WàæWáæ¡WÔæWÕæ¡WÊæWËæ¡WÈæWÉæ¡W§æÛ\æÙ\æÙ\æÛ\æÛ\æÙ\æÙ\æÛ\æÛ\æÙ\ÕæÛ\ØæÙ\æÙ\æÛ\ýåÛ\æÙ\ºæÙ\»æÛ\íåÛ\ðåÙ\êåÙ\ëåÛ\èåÙ\éåÛ\æåÙ\çåÛ\çÛ\çÙ\ÏåÛ\ÒåÙ\ÅåÛ\ÈåÙ\»çÛ\¾çÙ\±æÛ\´æÙ\çÙ\çÛ\µåÛ\¸åÙ\©åÛ\¬åÙ\åÛ\åÙ\åÛ\åÙ\åÙ\åÛ\åÙ\åÛ\àäÙ\áäÛ\ÌäÙ\ÍäÛ\´äÙ\µäÛ\¢äÙ\£äÛ\äÙ\äÛ\äÙ\äÛ\äÙ\äÛ\äãÙ\åãÛ\ÎãÙ\ÏãÛ\ÂãÙ\ÃãÛ\¸ãÙ\¹ãÛ\¶ãÙ\·ãÛ\§ãbãbüâbýâbóâböâbþâbÿâbñâbôâbÃãbÆãbîâbïâbëâbîâb¨ãb©ãbÛâbÞâbØâbÙâbÖâb×âbÔâbÕâb÷ãbúãb½âbÀâb³âb¶âb©äb¬äbãb¢ãbúãbûãb£âb¦âbâbâbâbâbýábâböáb÷ábîábïábÎábÏábºáb»áb¢áb£ábábábüàbýàbòàbóàbîàbïàbÒàbÓàb¼àb½àb°àb±àb¦àb§àb¤àb¥àb§ïßÏgòßÍgêßÍgëßÏgáßÏgäßÍgìßÍgíßÏgßßÏgâßÍg±àÏg´àÍgÜßÍgÝßÏgÙßÏgÜßÍgàÍgàÏgÉßÏgÌßÍgÆßÍgÇßÏgÄßÍgÅßÏgÂßÍgÃßÏgåàÏgèàÍg«ßÏg®ßÍg¡ßÏg¤ßÍgáÏgáÍgàÏgàÍgèàÍgéàÏgßÏgßÍgßÏgßÍgñÞÏgôÞÍgëÞÏgîÞÍgäÞÍgåÞÏgÜÞÍgÝÞÏg¼ÞÍg½ÞÏg¨ÞÍg©ÞÏgÞÍgÞÏgþÝÍgÿÝÏgêÝÍgëÝÏgàÝÍgáÝÏgÜÝÍgÝÝÏgÀÝÍgÁÝÏgªÝÍg«ÝÏgÝÍgÝÏgÝÍgÝÏgÝÍgÝÏg§ÝÜmàÜmØÜmÙÜmÏÜmÒÜmÚÜmÛÜmÍÜmÐÜmÝm¢ÝmÊÜmËÜmÇÜmÊÜmÝmÝm·ÜmºÜm´ÜmµÜm²Üm³Üm°Üm±ÜmÓÝmÖÝmÜmÜmÜmÜmÞmÞmûÜmþÜmÖÝm×ÝmÿÛmÜmóÛmöÛmßÛmâÛmÙÛmÜÛmÒÛmÓÛmÊÛmËÛmªÛm«ÛmÛmÛmþÚmÿÚmìÚmíÚmØÚmÙÚmÎÚmÏÚmÊÚmËÚm®Úm¯ÚmÚmÚmÚmÚmÚmÚmÚmÚm§ËÙÃrÎÙÁrÆÙÁrÇÙÃr½ÙÃrÀÙÁrÈÙÁrÉÙÃr»ÙÃr¾ÙÁrÚÃrÚÁr¸ÙÁr¹ÙÃrµÙÃr¸ÙÁròÙÁróÙÃr¥ÙÃr¨ÙÁr¢ÙÁr£ÙÃr ÙÁr¡ÙÃrÙÁrÙÃrÁÚÃrÄÚÁrÙÃrÙÁrýØÃrÙÁróÚÃröÚÁréÙÃrìÙÁrÄÚÁrÅÚÃríØÃrðØÁráØÃräØÁrÍØÃrÐØÁrÇØÃrÊØÁrÀØÁrÁØÃr¸ØÁr¹ØÃrØÁrØÃrØÁrØÃrì×Árí×ÃrÚ×ÁrÛ×ÃrÆ×ÁrÇ×Ãr¼×Ár½×Ãr¸×Ár¹×Ãr×Ár×Ãr×Ár×ÃrúÖÁrûÖÃrðÖÁrñÖÃrîÖÁrïÖÃr§¹Öýw¼Öûw´ÖûwµÖýw«Öýw®Öûw¶Öûw·Öýw©Öýw¬ÖûwûÖýwþÖûw¦Öûw§Öýw£Öýw¦ÖûwàÖûwáÖýwÖýwÖûwÖûwÖýwÖûwÖýwÖûwÖýw¯×ýw²×ûwõÕýwøÕûwëÕýwîÕûwá×ýwä×ûw×ÖýwÚÖûw²×ûw³×ýwÛÕýwÞÕûwÏÕýwÒÕûw»Õýw¾ÕûwµÕýw¸Õûw®Õûw¯Õýw¦Õûw§ÕýwÕûwÕýwòÔûwóÔýwÚÔûwÛÔýwÈÔûwÉÔýw´ÔûwµÔýwªÔûw«Ôýw¦Ôûw§ÔýwÔûwÔýwôÓûwõÓýwèÓûwéÓýwÞÓûwßÓýwÜÓûwÝÓýw§§Ó·}ªÓµ}¢Óµ}£Ó·}Ó·}Óµ}¤Óµ}¥Ó·}Ó·}Óµ}éÓ·}ìÓµ}Óµ}Ó·}Ó·}Óµ}ÎÓµ}ÏÓ·}Ó·}Óµ}þÒµ}ÿÒ·}üÒµ}ýÒ·}úÒµ}ûÒ·}Ô·} Ôµ}ãÒ·}æÒµ}ÙÒ·}ÜÒµ}ÏÔ·}ÒÔµ}ÅÓ·}ÈÓµ} Ôµ}¡Ô·}ÉÒ·}ÌÒµ}½Ò·}ÀÒµ}©Ò·}¬Òµ}£Ò·}¦Òµ}Òµ}Ò·}Òµ}Ò·}ôÑµ}õÑ·}àÑµ}áÑ·}ÈÑµ}ÉÑ·}¶Ñµ}·Ñ·}¢Ñµ}£Ñ·}Ñµ}Ñ·}Ñµ}Ñ·}øÐµ}ùÐ·}âÐµ}ãÐ·}ÖÐµ}×Ð·}ÌÐµ}ÍÐ·}ÊÐµ}ËÐ·}§ÐñÐïÐïÐñÐñÐïÐïÐñÐñÐï×ÐñÚÐïÐïÐñÿÏñÐï¼Ðï½ÐñïÏñòÏïìÏïíÏñêÏïëÏñèÏïéÏñÑñÑïÑÏñÔÏïÇÏñÊÏï½ÑñÀÑï³Ðñ¶ÐïÑïÑñ·ÏñºÏï«Ïñ®ÏïÏñÏïÏñÏïÏïÏñÏïÏñâÎïãÎñÎÎïÏÎñ¶Îï·Îñ¤Îï¥ÎñÎïÎñÎïÎñÎïÎñæÍïçÍñÐÍïÑÍñÄÍïÅÍñºÍï»Íñ¸Íï¹Íñ§Í«Í©þÌ©ÿÌ«õÌ«øÌ©Í©Í«óÌ«öÌ©ÅÍ«ÈÍ©ðÌ©ñÌ«íÌ«ðÌ©ªÍ©«Í«ÝÌ«àÌ©ÚÌ©ÛÌ«ØÌ©ÙÌ«ÖÌ©×Ì«ùÍ«üÍ©¿Ì«ÂÌ©µÌ«¸Ì©«Î«®Î©¡Í«¤Í©üÍ©ýÍ«¥Ì«¨Ì©Ì«Ì©Ì«Ì©ÿË«Ì©øË©ùË«ðË©ñË«ÐË©ÑË«¼Ë©½Ë«¤Ë©¥Ë«Ë©Ë«þÊ©ÿÊ«ôÊ©õÊ«ðÊ©ñÊ«ÔÊ©ÕÊ«¾Ê©¿Ê«²Ê©³Ê«¨Ê©©Ê«¦Ê©§Ê«§ñÉåôÉãìÉãíÉåãÉåæÉãîÉãïÉåáÉåäÉã³Êå¶ÊãÞÉãßÉåÛÉåÞÉãÊãÊåËÉåÎÉãÈÉãÉÉåÆÉãÇÉåÄÉãÅÉåçÊåêÊã­Éå°Éã£Éå¦ÉãËåËãÊåÊãêÊãëÊåÉåÉãÉåÉãóÈåöÈãíÈåðÈãæÈãçÈåÞÈãßÈå¾Èã¿ÈåªÈã«ÈåÈãÈåÈãÈåìÇãíÇåâÇããÇåÞÇãßÇåÂÇãÃÇå¬Çã­Çå Çã¡ÇåÇãÇåÇãÇå§ßÆâÆÚÆÛÆÑÆÔÆÜÆÝÆÏÆÒÆ¡Ç¤ÇÌÆÍÆÉÆÌÆÇÇ¹Æ¼Æ¶Æ·Æ´ÆµÆ²Æ³ÆÕÇØÇÆÆÆÆÈÈýÆÇØÇÙÇÆÆõÅøÅáÅäÅÛÅÞÅÔÅÕÅÌÅÍÅ¬Å­ÅÅÅÅÅîÄïÄÚÄÛÄÐÄÑÄÌÄÍÄ°Ä±ÄÄÄÄÄÄÄÄÄ§ÍÃÙÐÃ×ÈÃ×ÉÃÙ¿ÃÙÂÃ×ÊÃ×ËÃÙ½ÃÙÀÃ×ÄÙÄ×ºÃ×»ÃÙ·ÃÙºÃ×ôÃ×õÃÙ§ÃÙªÃ×¤Ã×¥ÃÙ¢Ã×£ÃÙ Ã×¡ÃÙÃÄÙÆÄ×ÃÙÃ×ÿÂÙÃ×õÄÙøÄ×ëÃÙîÃ×ÆÄ×ÇÄÙïÂÙòÂ×ãÂÙæÂ×ÏÂÙÒÂ×ÉÂÙÌÂ×ÂÂ×ÃÂÙºÂ×»ÂÙÂ×ÂÙÂ×ÂÙîÁ×ïÁÙÜÁ×ÝÁÙÈÁ×ÉÁÙ¾Á×¿ÁÙºÁ×»ÁÙÁ×ÁÙÁ×ÁÙüÀ×ýÀÙòÀ×óÀÙðÀ×ñÀÙ§»À¾À¶À·À­À°À¸À¹À«À®ÀýÀÁ¨À©À¥À¨ÀâÀãÀÀÀÀÀÀÀÀÀ±Á´Á÷¿ú¿í¿ð¿ãÁæÁÙÀÜÀ´ÁµÁÝ¿à¿Ñ¿Ô¿½¿À¿·¿º¿°¿±¿¨¿©¿¿¿ô¾õ¾Ü¾Ý¾Ê¾Ë¾¶¾·¾¬¾­¾¨¾©¾¾¾ö½÷½ê½ë½à½á½Þ½ß½§©½Í£¬½Ë£¤½Ë£¥½Í£½Í£½Ë£¦½Ë£§½Í£½Í£½Ë£ë½Í£î½Ë£½Ë£½Í£½Í£½Ë£Ð½Ë£Ñ½Í£½Í£½Ë£½Ë£½Í£þ¼Ë£ÿ¼Í£ü¼Ë£ý¼Í£¾Í£¢¾Ë£å¼Í£è¼Ë£Û¼Í£Þ¼Ë£Ñ¾Í£Ô¾Ë£Ç½Í£Ê½Ë£¢¾Ë££¾Í£Ë¼Í£Î¼Ë£¿¼Í£Â¼Ë£«¼Í£®¼Ë£¥¼Í£¨¼Ë£¼Ë£¼Í£¼Ë£¼Í£ö»Ë£÷»Í£â»Ë£ã»Í£Ê»Ë£Ë»Í£¸»Ë£¹»Í£¤»Ë£¥»Í£»Ë£»Í£»Ë£»Í£úºË£ûºÍ£äºË£åºÍ£ØºË£ÙºÍ£ÎºË£ÏºÍ£ÌºË£ÍºÍ£§º©º©º©º©º©º©º©º©º©º©Ùº©Üº©º©º©º©º©¾º©¿º©ñ¹©ô¹©î¹©ï¹©ì¹©í¹©ê¹©ë¹©»©»©Ó¹©Ö¹©É¹©Ì¹©¿»©Â»©µº©¸º©»©»©¹¹©¼¹©­¹©°¹©¹©¹©¹©¹©¹©¹©¹©¹©ä¸©å¸©Ð¸©Ñ¸©¸¸©¹¸©¦¸©§¸©¸©¸©¸©¸©¸©¸©è·©é·©Ò·©Ó·©Æ·©Ç·©¼·©½·©º·©»·©§ÑÚ»ÔÚ¹ÌÚ¹ÍÚ»ÃÚ»ÆÚ¹ÎÚ¹ÏÚ»ÁÚ»ÄÚ¹Û»Û¹¾Ú¹¿Ú»»Ú»¾Ú¹øÚ¹ùÚ»«Ú»®Ú¹¨Ú¹©Ú»¦Ú¹§Ú»¤Ú¹¥Ú»ÇÛ»ÊÛ¹Ú»Ú¹Ú»Ú¹ùÛ»üÛ¹ïÚ»òÚ¹ÊÛ¹ËÛ»óÙ»öÙ¹çÙ»êÙ¹ÓÙ»ÖÙ¹ÍÙ»ÐÙ¹ÆÙ¹ÇÙ»¾Ù¹¿Ù»Ù¹Ù»Ù¹Ù»òØ¹óØ»àØ¹áØ»ÌØ¹ÍØ»ÂØ¹ÃØ»¾Ø¹¿Ø»¢Ø¹£Ø»Ø¹Ø»Ø¹Ø»ö×¹÷×»ô×¹õ×»§¿×õ
+Â×ó
+º×ó
+»×õ
+±×õ
+´×ó
+¼×ó
+½×õ
+¯×õ
+²×ó
+Øõ
+Øó
+¬×ó
+­×õ
+©×õ
+¬×ó
+æ×ó
+ç×õ
+×õ
+×ó
+×ó
+×õ
+×ó
+×õ
+×ó
+×õ
+µØõ
+¸Øó
+ûÖõ
+þÖó
+ñÖõ
+ôÖó
+çØõ
+êØó
+Ý×õ
+à×ó
+¸Øó
+¹Øõ
+áÖõ
+äÖó
+ÕÖõ
+ØÖó
+ÁÖõ
+ÄÖó
+»Öõ
+¾Öó
+´Öó
+µÖõ
+¬Öó
+­Öõ
+Öó
+Öõ
+øÕó
+ùÕõ
+àÕó
+áÕõ
+ÎÕó
+ÏÕõ
+ºÕó
+»Õõ
+°Õó
+±Õõ
+¬Õó
+­Õõ
+Õó
+Õõ
+úÔó
+ûÔõ
+îÔó
+ïÔõ
+äÔó
+åÔõ
+âÔó
+ãÔõ
+§­Ô¯°Ô­¨Ô­©Ô¯Ô¯¢Ô­ªÔ­«Ô¯Ô¯ Ô­ïÔ¯òÔ­Ô­Ô¯Ô¯Ô­ÔÔ­ÕÔ¯Ô¯Ô­Ô­Ô¯Ô­Ô¯Ô­Ô¯£Õ¯¦Õ­éÓ¯ìÓ­ßÓ¯âÓ­ÕÕ¯ØÕ­ËÔ¯ÎÔ­¦Õ­§Õ¯ÏÓ¯ÒÓ­ÃÓ¯ÆÓ­¯Ó¯²Ó­©Ó¯¬Ó­¢Ó­£Ó¯Ó­Ó¯úÒ­ûÒ¯æÒ­çÒ¯ÎÒ­ÏÒ¯¼Ò­½Ò¯¨Ò­©Ò¯Ò­Ò¯Ò­Ò¯þÑ­ÿÑ¯èÑ­éÑ¯ÜÑ­ÝÑ¯ÒÑ­ÓÑ¯ÐÑ­ÑÑ¯§ÑéÑçÑçÑéÑéÑçÑçÑéÑéÑçÝÑéàÑçÑçÑéÑéÑçÂÑçÃÑéõÐéøÐçòÐçóÐéðÐçñÐéîÐçïÐéÒéÒç×ÐéÚÐçÍÐéÐÐçÃÒéÆÒç¹Ñé¼ÑçÒçÒé½ÐéÀÐç±Ðé´ÐçÐé ÐçÐéÐçÐçÐéÐçÐéèÏçéÏéÔÏçÕÏé¼Ïç½ÏéªÏç«ÏéÏçÏéÏçÏéÏçÏéìÎçíÎéÖÎç×ÎéÊÎçËÎéÀÎçÁÎé¾Îç¿Îé§Î£Î¡Î¡Î£ûÍ£þÍ¡Î¡Î£ùÍ£üÍ¡ËÎ£ÎÎ¡öÍ¡÷Í£óÍ£öÍ¡°Î¡±Î£ãÍ£æÍ¡àÍ¡áÍ£ÞÍ¡ßÍ£ÜÍ¡ÝÍ£ÿÎ£Ï¡ÅÍ£ÈÍ¡»Í£¾Í¡±Ï£´Ï¡§Î£ªÎ¡Ï¡Ï£«Í£®Í¡Í£¢Í¡Í£Í¡Í£Í¡þÌ¡ÿÌ£öÌ¡÷Ì£ÖÌ¡×Ì£ÂÌ¡ÃÌ£ªÌ¡«Ì£Ì¡Ì£Ì¡Ì£úË¡ûË£öË¡÷Ë£ÚË¡ÛË£ÄË¡ÅË£¸Ë¡¹Ë£®Ë¡¯Ë£¬Ë¡­Ë£§÷ÊÝ úÊÛ òÊÛ óÊÝ éÊÝ ìÊÛ ôÊÛ õÊÝ çÊÝ êÊÛ ¹ËÝ ¼ËÛ äÊÛ åÊÝ áÊÝ äÊÛ ËÛ ËÝ ÑÊÝ ÔÊÛ ÎÊÛ ÏÊÝ ÌÊÛ ÍÊÝ ÊÊÛ ËÊÝ íËÝ ðËÛ ³ÊÝ ¶ÊÛ ©ÊÝ ¬ÊÛ ÌÝ ¢ÌÛ ËÝ ËÛ ðËÛ ñËÝ ÊÝ ÊÛ ÊÝ ÊÛ ùÉÝ üÉÛ óÉÝ öÉÛ ìÉÛ íÉÝ äÉÛ åÉÝ ÄÉÛ ÅÉÝ °ÉÛ ±ÉÝ ÉÛ ÉÝ ÉÛ ÉÝ òÈÛ óÈÝ èÈÛ éÈÝ äÈÛ åÈÝ ÈÈÛ ÉÈÝ ²ÈÛ ³ÈÝ ¦ÈÛ §ÈÝ ÈÛ ÈÝ ÈÛ ÈÝ §åÇ&èÇ&àÇ&áÇ&×Ç&ÚÇ&âÇ&ãÇ&ÕÇ&ØÇ&§È&ªÈ&ÒÇ&ÓÇ&ÏÇ&ÒÇ&È&È&¿Ç&ÂÇ&¼Ç&½Ç&ºÇ&»Ç&¸Ç&¹Ç&ÛÈ&ÞÈ&¡Ç&¤Ç&Ç&Ç&É&É&È&È&ÞÈ&ßÈ&Ç&Ç&ûÆ&þÆ&çÆ&êÆ&áÆ&äÆ&ÚÆ&ÛÆ&ÒÆ&ÓÆ&²Æ&³Æ&Æ&Æ&Æ&Æ&ôÅ&õÅ&àÅ&áÅ&ÖÅ&×Å&ÒÅ&ÓÅ&¶Å&·Å& Å&¡Å&Å&Å&Å&Å&Å&Å&§ÓÄÑ+ÖÄÏ+ÎÄÏ+ÏÄÑ+ÅÄÑ+ÈÄÏ+ÐÄÏ+ÑÄÑ+ÃÄÑ+ÆÄÏ+ÅÑ+ÅÏ+ÀÄÏ+ÁÄÑ+½ÄÑ+ÀÄÏ+úÄÏ+ûÄÑ+­ÄÑ+°ÄÏ+ªÄÏ+«ÄÑ+¨ÄÏ+©ÄÑ+¦ÄÏ+§ÄÑ+ÉÅÑ+ÌÅÏ+ÄÑ+ÄÏ+ÄÑ+ÄÏ+ûÅÑ+þÅÏ+ñÄÑ+ôÄÏ+ÌÅÏ+ÍÅÑ+õÃÑ+øÃÏ+éÃÑ+ìÃÏ+ÕÃÑ+ØÃÏ+ÏÃÑ+ÒÃÏ+ÈÃÏ+ÉÃÑ+ÀÃÏ+ÁÃÑ+ ÃÏ+¡ÃÑ+ÃÏ+ÃÑ+ôÂÏ+õÂÑ+âÂÏ+ãÂÑ+ÎÂÏ+ÏÂÑ+ÄÂÏ+ÅÂÑ+ÀÂÏ+ÁÂÑ+¤ÂÏ+¥ÂÑ+ÂÏ+ÂÑ+ÂÏ+ÂÑ+øÁÏ+ùÁÑ+öÁÏ+÷ÁÑ+§ÁÁ1ÄÁ1¼Á1½Á1³Á1¶Á1¾Á1¿Á1±Á1´Á1Â1Â1®Á1¯Á1«Á1®Á1èÁ1éÁ1Á1Á1Á1Á1Á1Á1Á1Á1·Â1ºÂ1ýÀ1Á1óÀ1öÀ1éÂ1ìÂ1ßÁ1âÁ1ºÂ1»Â1ãÀ1æÀ1×À1ÚÀ1ÃÀ1ÆÀ1½À1ÀÀ1¶À1·À1®À1¯À1À1À1ú¿1û¿1â¿1ã¿1Ð¿1Ñ¿1¼¿1½¿1²¿1³¿1®¿1¯¿1¿1¿1ü¾1ý¾1ð¾1ñ¾1æ¾1ç¾1ä¾1å¾1§¯¾Å6²¾Ã6ª¾Ã6«¾Å6¡¾Å6¤¾Ã6¬¾Ã6­¾Å6¾Å6¢¾Ã6ñ¾Å6ô¾Ã6¾Ã6¾Å6¾Å6¾Ã6Ö¾Ã6×¾Å6¾Å6¾Ã6¾Ã6¾Å6¾Ã6¾Å6¾Ã6¾Å6¥¿Å6¨¿Ã6ë½Å6î½Ã6á½Å6ä½Ã6×¿Å6Ú¿Ã6Í¾Å6Ð¾Ã6¨¿Ã6©¿Å6Ñ½Å6Ô½Ã6Å½Å6È½Ã6±½Å6´½Ã6«½Å6®½Ã6¤½Ã6¥½Å6½Ã6½Å6ü¼Ã6ý¼Å6è¼Ã6é¼Å6Ð¼Ã6Ñ¼Å6¾¼Ã6¿¼Å6ª¼Ã6«¼Å6 ¼Ã6¡¼Å6¼Ã6¼Å6¼Ã6¼Å6ê»Ã6ë»Å6Þ»Ã6ß»Å6Ô»Ã6Õ»Å6Ò»Ã6Ó»Å6§»ÿ; »ý;»ý;»ÿ;»ÿ;»ý;»ý;»ÿ;»ÿ;»ý;ß»ÿ;â»ý;»ý;»ÿ;»ÿ;»ý;Ä»ý;Å»ÿ;÷ºÿ;úºý;ôºý;õºÿ;òºý;óºÿ;ðºý;ñºÿ;¼ÿ;¼ý;Ùºÿ;Üºý;Ïºÿ;Òºý;Å¼ÿ;È¼ý;»»ÿ;¾»ý;¼ý;¼ÿ;¿ºÿ;Âºý;³ºÿ;¶ºý;ºÿ;¢ºý;ºÿ;ºý;ºý;ºÿ;ºý;ºÿ;ê¹ý;ë¹ÿ;Ö¹ý;×¹ÿ;¾¹ý;¿¹ÿ;¬¹ý;­¹ÿ;¹ý;¹ÿ;¹ý;¹ÿ;¹ý;¹ÿ;î¸ý;ï¸ÿ;Ø¸ý;Ù¸ÿ;Ì¸ý;Í¸ÿ;Â¸ý;Ã¸ÿ;À¸ý;Á¸ÿ;§¸¹A¸·A¸·A¸¹Aý·¹A¸·A¸·A¸¹Aû·¹Aþ··AÍ¸¹AÐ¸·Aø··Aù·¹Aõ·¹Aø··A²¸·A³¸¹Aå·¹Aè··Aâ··Aã·¹Aà··Aá·¹AÞ··Aß·¹A¹¹A¹·AÇ·¹AÊ··A½·¹AÀ··A³¹¹A¶¹·A©¸¹A¬¸·A¹·A¹¹A­·¹A°··A¡·¹A¤··A·¹A··A·¹A··A··A·¹Aø¶·Aù¶¹AØ¶·AÙ¶¹AÄ¶·AÅ¶¹A¬¶·A­¶¹A¶·A¶¹A¶·A¶¹Aüµ·Aýµ¹Aøµ·Aùµ¹AÜµ·AÝµ¹AÆµ·AÇµ¹Aºµ·A»µ¹A°µ·A±µ¹A®µ·A¯µ¹A§ù´óFü´ñFô´ñFõ´óFë´óFî´ñFö´ñF÷´óFé´óFì´ñF»µóF¾µñFæ´ñFç´óFã´óFæ´ñF µñF¡µóFÓ´óFÖ´ñFÐ´ñFÑ´óFÎ´ñFÏ´óFÌ´ñFÍ´óFïµóFòµñFµ´óF¸´ñF«´óF®´ñF¡¶óF¤¶ñFµóFµñFòµñFóµóF´óF´ñF´óF´ñFû³óFþ³ñFõ³óFø³ñFî³ñFï³óFæ³ñFç³óFÆ³ñFÇ³óF²³ñF³³óF³ñF³óF³ñF³óFô²ñFõ²óFê²ñFë²óFæ²ñFç²óFÊ²ñFË²óF´²ñFµ²óF¨²ñF©²óF²ñF²óF²ñF²óF§ç±­Lê±«Lâ±«Lã±­LÙ±­LÜ±«Lä±«Lå±­L×±­LÚ±«L©²­L¬²«LÔ±«LÕ±­LÑ±­LÔ±«L²«L²­LÁ±­LÄ±«L¾±«L¿±­L¼±«L½±­Lº±«L»±­LÝ²­Là²«L£±­L¦±«L±­L±«L³­L³«L²­L²«Là²«Lá²­L±­L±«Lý°­L±«Lé°­Lì°«Lã°­Læ°«LÜ°«LÝ°­LÔ°«LÕ°­L´°«Lµ°­L °«L¡°­L°«L°­Lö¯«L÷¯­Lâ¯«Lã¯­LØ¯«LÙ¯­LÔ¯«LÕ¯­L¸¯«L¹¯­L¢¯«L£¯­L¯«L¯­L¯«L¯­L¯«L¯­L§Õ®çQØ®åQÐ®åQÑ®çQÇ®çQÊ®åQÒ®åQÓ®çQÅ®çQÈ®åQ¯çQ¯åQÂ®åQÃ®çQ¿®çQÂ®åQü®åQý®çQ¯®çQ²®åQ¬®åQ­®çQª®åQ«®çQ¨®åQ©®çQË¯çQÎ¯åQ®çQ®åQ®çQ®åQý¯çQ°åQó®çQö®åQÎ¯åQÏ¯çQ÷­çQú­åQë­çQî­åQ×­çQÚ­åQÑ­çQÔ­åQÊ­åQË­çQÂ­åQÃ­çQ¢­åQ£­çQ­åQ­çQö¬åQ÷¬çQä¬åQå¬çQÐ¬åQÑ¬çQÆ¬åQÇ¬çQÂ¬åQÃ¬çQ¦¬åQ§¬çQ¬åQ¬çQ¬åQ¬çQú«åQû«çQø«åQù«çQ§Ã«¡WÆ«W¾«W¿«¡Wµ«¡W¸«WÀ«WÁ«¡W³«¡W¶«W¬¡W¬W°«W±«¡W­«¡W°«Wê«Wë«¡W«¡W «W«W«¡W«W«¡W«W«¡W¹¬¡W¼¬Wÿª¡W«Wõª¡WøªWë¬¡Wî¬Wá«¡Wä«W¼¬W½¬¡Wåª¡WèªWÙª¡WÜªWÅª¡WÈªW¿ª¡WÂªW¸ªW¹ª¡W°ªW±ª¡WªWª¡Wü©Wý©¡Wä©Wå©¡WÒ©WÓ©¡W¾©W¿©¡W´©Wµ©¡W°©W±©¡W©W©¡Wþ¨Wÿ¨¡Wò¨Wó¨¡Wè¨Wé¨¡Wæ¨Wç¨¡W§±¨Û\´¨Ù\¬¨Ù\­¨Û\£¨Û\¦¨Ù\®¨Ù\¯¨Û\¡¨Û\¤¨Ù\ó¨Û\ö¨Ù\¨Ù\¨Û\¨Û\¨Ù\Ø¨Ù\Ù¨Û\¨Û\¨Ù\¨Ù\¨Û\¨Ù\¨Û\¨Ù\¨Û\§©Û\ª©Ù\í§Û\ð§Ù\ã§Û\æ§Ù\Ù©Û\Ü©Ù\Ï¨Û\Ò¨Ù\ª©Ù\«©Û\Ó§Û\Ö§Ù\Ç§Û\Ê§Ù\³§Û\¶§Ù\­§Û\°§Ù\¦§Ù\§§Û\§Ù\§Û\þ¦Ù\ÿ¦Û\ê¦Ù\ë¦Û\Ò¦Ù\Ó¦Û\À¦Ù\Á¦Û\¬¦Ù\­¦Û\¢¦Ù\£¦Û\¦Ù\¦Û\¦Ù\¦Û\ì¥Ù\í¥Û\à¥Ù\á¥Û\Ö¥Ù\×¥Û\Ô¥Ù\Õ¥Û\§¥b¢¥b¥b¥b¥b¥b¥b¥b¥b¥bá¥bä¥b¥b¥b¥b¥bÆ¥bÇ¥bù¤bü¤bö¤b÷¤bô¤bõ¤bò¤bó¤b¦b¦bÛ¤bÞ¤bÑ¤bÔ¤bÇ¦bÊ¦b½¥bÀ¥b¦b¦bÁ¤bÄ¤bµ¤b¸¤b¡¤b¤¤b¤b¤b¤b¤b¤b¤bì£bí£bØ£bÙ£bÀ£bÁ£b®£b¯£b£b£b£b£b£b£bð¢bñ¢bÚ¢bÛ¢bÎ¢bÏ¢bÄ¢bÅ¢bÂ¢bÃ¢b§¢Ïg¢Íg¢Íg¢Ïgÿ¡Ïg¢Íg¢Íg¢Ïgý¡Ïg¢ÍgÏ¢ÏgÒ¢Ígú¡Ígû¡Ïg÷¡Ïgú¡Íg´¢Ígµ¢Ïgç¡Ïgê¡Ígä¡Ígå¡Ïgâ¡Ígã¡Ïgà¡Ígá¡Ïg£Ïg£ÍgÉ¡ÏgÌ¡Íg¿¡ÏgÂ¡Ígµ£Ïg¸£Íg«¢Ïg®¢Íg£Íg£Ïg¯¡Ïg²¡Íg£¡Ïg¦¡Íg¡Ïg¡Íg¡Ïg¡Íg¡Íg¡Ïgú Ígû ÏgÚ ÍgÛ ÏgÆ ÍgÇ Ïg® Íg¯ Ïg Íg Ïg Íg ÏgþÍgÿÏgúÍgûÏgÞÍgßÏgÈÍgÉÏg¼Íg½Ïg²Íg³Ïg°Íg±Ïg§ûmþmöm÷mímðmømùmëmîm½mÀmèmémåmèm¢m£mÕmØmÒmÓmÐmÑmÎmÏmñmôm·mºm­m°m£ m¦ mmmômõmm mmmýmm÷múmðmñmèmémÈmÉm´mµmmmmmöm÷mìmímèmémÌmÍm¶m·mªm«m m¡mmm§éÃrìÁräÁråÃrÛÃrÞÁræÁrçÃrÙÃrÜÁr«Ãr®ÁrÖÁr×ÃrÓÃrÖÁrÁrÃrÃÃrÆÁrÀÁrÁÃr¾Ár¿Ãr¼Ár½ÃrßÃrâÁr¥Ãr¨ÁrÃrÁrÃrÁrÃrÁrâÁrãÃrÃrÁrÿÃrÁrëÃrîÁråÃrèÁrÞÁrßÃrÖÁr×Ãr¶Ár·Ãr¢Ár£ÃrÁrÃrøÁrùÃräÁråÃrÚÁrÛÃrÖÁr×ÃrºÁr»Ãr¤Ár¥ÃrÁrÃrÁrÃrÁrÃr§×ýwÚûwÒûwÓýwÉýwÌûwÔûwÕýwÇýwÊûwýwûwÄûwÅýwÁýwÄûwþûwÿýw±ýw´ûw®ûw¯ýw¬ûw­ýwªûw«ýwÍýwÐûwýwûwýwûwÿýwûwõýwøûwÐûwÑýwùýwüûwíýwðûwÙýwÜûwÓýwÖûwÌûwÍýwÄûwÅýw¤ûw¥ýwûwýwøûwùýwæûwçýwÒûwÓýwÈûwÉýwÄûwÅýw¨ûw©ýwûwýwûwýwüûwýýwúûwûýw§Å·}Èµ}Àµ}Á·}··}ºµ}Âµ}Ã·}µ·}¸µ}·}µ}²µ}³·}¯·}²µ}ìµ}í·}·}¢µ}µ}·}µ}·}µ}·}»·}¾µ}·}µ}÷·}úµ}í·}ðµ}ã·}æµ}¾µ}¿·}ç·}êµ}Û·}Þµ}Ç·}Êµ}Á·}Äµ}ºµ}»·}²µ}³·}µ}·}þµ}ÿ·}æµ}ç·}Ôµ}Õ·}Àµ}Á·}¶µ}··}²µ}³·}µ}·}µ}·}ôµ}õ·}êµ}ë·}èµ}é·}§³ñ¶ï®ï¯ñ¥ñ¨ï°ï±ñ£ñ¦ïõñøï ï¡ññ ïÚïÛññïïñïñïñ©ñ¬ïïñòïåñèïÛñÞïÑñÔï¬ï­ñÕñØïÉñÌïµñ¸ï¯ñ²ï¨ï©ñ ï¡ñïñìïíñÔïÕñÂïÃñ®ï¯ñ¤ï¥ñ ï¡ñïñîïïñâïãñØïÙñÖï×ñ§¡«¤©©««©©««©ã«æ©©««©È©É«û«þ©ø©ù«ö©÷«ô©õ««©Ý«à©Ó«Ö©É«Ì©¿«Â©©«Ã«Æ©·«º©£«¦©« ©©«©«î©ï«Ú©Û«Â©Ã«°©±«©«©«©«ò©ó«Ü©Ý«Ð©Ñ«Æ©Ç«Ä©Å«§åããååããåÿåãÑåÔãüãýåùåüã¶ã·åéåìãæãçåäãååâããååãËåÎãÁåÄã·åºã­å°ããå±å´ã¥å¨ãåãåããåüãýåÜãÝåÈãÉå°ã±åãåãåãåüãýåàãáåÊãËå¾ã¿å´ãµå²ã³å§ýøùïòúûíð¿Âêëçê¤¥×ÚÔÕÒÓÐÑóö¹¼¯²¥¨ö÷¢ÿùüòóêëÊË¶·øùîïêëÎÏ¸¹¬­¢£ ¡§ëÙî×æ×çÙÝÙà×è×éÙÛÙÞ×­Ù°×Ø×ÙÙÕÙØ××ÙÅÙÈ×Â×ÃÙÀ×ÁÙ¾×¿ÙáÙä×§Ùª×Ù ×Ù×Ù×ä×åÙÙ×Ù×íÙð×çÙê×à×áÙØ×ÙÙ¸×¹Ù¤×¥Ù×Ùú×ûÙæ×çÙÜ×ÝÙØ×ÙÙ¼×½Ù¦×§Ù×Ù×Ù×Ù§ÙÜÔÕËÎÖ×ÉÌÆÇÃÆ³¶°±®¯¬­ÏÒ÷úÒÓûþïòÛÞÕØÎÏÆÇ¦§úûèéÔÕÊËÆÇª«þÿÿÿüÿýÿ§ÇÿÍ£ÊÿË£ÂÿË£ÃÿÍ£¹ÿÍ£¼ÿË£ÄÿË£ÅÿÍ£·ÿÍ£ºÿË£Í£Ë£´ÿË£µÿÍ£±ÿÍ£´ÿË£îÿË£ïÿÍ£¡ÿÍ£¤ÿË£ÿË£ÿÍ£ÿË£ÿÍ£ÿË£ÿÍ£½Í£ÀË£ÿÍ£ÿË£ùþÍ£üþË£ïÍ£òË£åÿÍ£èÿË£ÀË£ÁÍ£éþÍ£ìþË£ÝþÍ£àþË£ÉþÍ£ÌþË£ÃþÍ£ÆþË£¼þË£½þÍ£´þË£µþÍ£þË£þÍ£þË£þÍ£èýË£éýÍ£ÖýË£×ýÍ£ÂýË£ÃýÍ£¸ýË£¹ýÍ£´ýË£µýÍ£ýË£ýÍ£ýË£ýÍ£öüË£÷üÍ£ìüË£íüÍ£êüË£ëüÍ£§Ç»Ê¹Â¹Ã»¹»¼¹Ä¹Å»·»º¹»¹´¹µ»±»´¹î¹ï»¡»¤¹¹»¹»¹»½»À¹»¹ù»ü¹ï»ò¹å»è¹À¹Á»é»ì¹Ý»à¹É»Ì¹Ã»Æ¹¼¹½»´¹µ»¹»¹»è¹é»Ö¹×»Â¹Ã»¸¹¹»´¹µ»¹»¹»ö¹÷»ì¹í»ê¹ë»§µõ
+¸ó
+°ó
+±õ
+§õ
+ªó
+²ó
+³õ
+¥õ
+¨ó
+÷õ
+úó
+¢ó
+£õ
+õ
+¢ó
+Üó
+Ýõ
+õ
+ó
+ó
+õ
+ó
+õ
+ó
+õ
+«õ
+®ó
+ñõ
+ôó
+çõ
+êó
+Ýõ
+àó
+Óõ
+Öó
+®ó
+¯õ
+×õ
+Úó
+Ëõ
+Îó
+·õ
+ºó
+±õ
+´ó
+ªó
+«õ
+¢ó
+£õ
+ó
+õ
+îó
+ïõ
+Öó
+×õ
+Äó
+Åõ
+°ó
+±õ
+¦ó
+§õ
+¢ó
+£õ
+ó
+õ
+ðó
+ñõ
+äó
+åõ
+Úó
+Ûõ
+Øó
+Ùõ
+§£¯¦­­¯¯­ ­¡¯¯­å¯è­­¯¯­Ê­Ë¯ý¯­ú­û¯ø­ù¯ö­÷¯¯­ß¯â­Õ¯Ø­Ë¯Î­Á¯Ä­­¯Å¯È­¹¯¼­¥¯¨­¯¢­­¯­¯ð­ñ¯Ü­Ý¯Ä­Å¯²­³¯­¯­¯­¯ô­õ¯Þ­ß¯Ò­Ó¯È­É¯Æ­Ç¯§éççééççééçÓéÖçþçÿéûéþç¸ç¹éëéîçèçééæççéäçåééçÍéÐçÃéÆç¹é¼ç¯é²ççé³é¶ç§éªçéçéççéþçÿéÞçßéÊçËé²ç³é ç¡éçéçéþçÿéâçãéÌçÍéÀçÁé¶ç·é´çµé§ÿ£¡ú¡û£ñ£ô¡ü¡ý£ï£ò¡Á£Ä¡ì¡í£é£ì¡¦¡§£Ù£Ü¡Ö¡×£Ô¡Õ£Ò¡Ó£õ£ø¡»£¾¡±£´¡§£ª¡£ ¡ø¡ù£¡£¤¡£¡£¡û£þ¡ô¡õ£ì¡í£Ì¡Í£¸¡¹£ ¡¡£¡£ú¡û£ð¡ñ£ì¡í£Ð¡Ñ£º¡»£®¡¯£¤¡¥£¢¡££§íÝ ðÛ èÛ éÝ ßÝ âÛ êÛ ëÝ ÝÝ àÛ ¯Ý ²Û ÚÛ ÛÝ ×Ý ÚÛ Û Ý ÇÝ ÊÛ ÄÛ ÅÝ ÂÛ ÃÝ ÀÛ ÁÝ ãÝ æÛ ©Ý ¬Û Ý ¢Û Ý Û Ý Û æÛ çÝ Ý Û Ý Û ïÝ òÛ éÝ ìÛ âÛ ãÝ ÚÛ ÛÝ ºÛ »Ý ¦Û §Ý Û Ý üÛ ýÝ èÛ éÝ ÞÛ ßÝ ÚÛ ÛÝ ¾Û ¿Ý ¨Û ©Ý Û Ý Û Ý Û Ý §Û&Þ&Ö&×&Í&Ð&Ø&Ù&Ë&Î&& &È&É&Å&È&&&µ&¸&²&³&°&±&®&¯&Ñ&Ô&&&&&&&ù&ü&Ô&Õ&ý&&ñ&ô&Ý&à&×&Ú&Ð&Ñ&È&É&¨&©&&&ü&ý&ê&ë&Ö&×&Ì&Í&È&É&¬&­&&&&&&&þ&ÿ&§ÉÑ+ÌÏ+ÄÏ+ÅÑ+»Ñ+¾Ï+ÆÏ+ÇÑ+¹Ñ+¼Ï+Ñ+Ï+¶Ï+·Ñ+³Ñ+¶Ï+ðÏ+ñÑ+£Ñ+¦Ï+ Ï+¡Ñ+Ï+Ñ+Ï+Ñ+¿Ñ+ÂÏ+Ñ+Ï+ûÑ+þÏ+ñÑ+ôÏ+çÑ+êÏ+ÂÏ+ÃÑ+ëÑ+îÏ+ßÑ+âÏ+ËÑ+ÎÏ+ÅÑ+ÈÏ+¾Ï+¿Ñ+¶Ï+·Ñ+Ï+Ñ+Ï+Ñ+êÏ+ëÑ+ØÏ+ÙÑ+ÄÏ+ÅÑ+ºÏ+»Ñ+¶Ï+·Ñ+Ï+Ñ+Ï+Ñ+øÏ+ùÑ+îÏ+ïÑ+ìÏ+íÑ+§·1º1²1³1©1¬1´1µ1§1ª1ù1ü1¤1¥1¡1¤1Þ1ß111111111­1°1ó1ö1é1ì1ß1â1Õ1Ø1°1±1Ù1Ü1Í1Ð1¹1¼1³1¶1¬1­1¤1¥111ðÿ1ñÿ1Øÿ1Ùÿ1Æÿ1Çÿ1²ÿ1³ÿ1¨ÿ1©ÿ1¤ÿ1¥ÿ1ÿ1ÿ1òþ1óþ1æþ1çþ1Üþ1Ýþ1Úþ1Ûþ1§¥þÅ6¨þÃ6 þÃ6¡þÅ6þÅ6þÃ6¢þÃ6£þÅ6þÅ6þÃ6çþÅ6êþÃ6þÃ6þÅ6þÅ6þÃ6ÌþÃ6ÍþÅ6ÿýÅ6þÃ6üýÃ6ýýÅ6úýÃ6ûýÅ6øýÃ6ùýÅ6ÿÅ6ÿÃ6áýÅ6äýÃ6×ýÅ6ÚýÃ6ÍÿÅ6ÐÿÃ6ÃþÅ6ÆþÃ6ÿÃ6ÿÅ6ÇýÅ6ÊýÃ6»ýÅ6¾ýÃ6§ýÅ6ªýÃ6¡ýÅ6¤ýÃ6ýÃ6ýÅ6ýÃ6ýÅ6òüÃ6óüÅ6ÞüÃ6ßüÅ6ÆüÃ6ÇüÅ6´üÃ6µüÅ6 üÃ6¡üÅ6üÃ6üÅ6üÃ6üÅ6öûÃ6÷ûÅ6àûÃ6áûÅ6ÔûÃ6ÕûÅ6ÊûÃ6ËûÅ6ÈûÃ6ÉûÅ6§ûÿ;ûý;ûý;ûÿ;ûÿ;ûý;ûý;ûÿ;ûÿ;ûý;Õûÿ;Øûý;ûý;ûÿ;ýúÿ;ûý;ºûý;»ûÿ;íúÿ;ðúý;êúý;ëúÿ;èúý;éúÿ;æúý;çúÿ;üÿ;üý;Ïúÿ;Òúý;Åúÿ;Èúý;»üÿ;¾üý;±ûÿ;´ûý;üý;üÿ;µúÿ;¸úý;©úÿ;¬úý;úÿ;úý;úÿ;úý;úý;úÿ;úý;úÿ;àùý;áùÿ;Ìùý;Íùÿ;´ùý;µùÿ;¢ùý;£ùÿ;ùý;ùÿ;ùý;ùÿ;ùý;ùÿ;äøý;åøÿ;Îøý;Ïøÿ;Âøý;Ãøÿ;¸øý;¹øÿ;¶øý;·øÿ;§ø¹Aø·Aü÷·Aý÷¹Aó÷¹Aö÷·Aþ÷·Aÿ÷¹Añ÷¹Aô÷·AÃø¹AÆø·Aî÷·Aï÷¹Aë÷¹Aî÷·A¨ø·A©ø¹AÛ÷¹AÞ÷·AØ÷·AÙ÷¹AÖ÷·A×÷¹AÔ÷·AÕ÷¹A÷ø¹Aúø·A½÷¹AÀ÷·A³÷¹A¶÷·A©ù¹A¬ù·Aø¹A¢ø·Aúø·Aûø¹A£÷¹A¦÷·A÷¹A÷·A÷¹A÷·Aýö¹A÷·Aöö·A÷ö¹Aîö·Aïö¹AÎö·AÏö¹Aºö·A»ö¹A¢ö·A£ö¹Aö·Aö¹Aüõ·Aýõ¹Aòõ·Aóõ¹Aîõ·Aïõ¹AÒõ·AÓõ¹A¼õ·A½õ¹A°õ·A±õ¹A¦õ·A§õ¹A¤õ·A¥õ¹A§ïôóFòôñFêôñFëôóFáôóFäôñFìôñFíôóFßôóFâôñF±õóF´õñFÜôñFÝôóFÙôóFÜôñFõñFõóFÉôóFÌôñFÆôñFÇôóFÄôñFÅôóFÂôñFÃôóFåõóFèõñF«ôóF®ôñF¡ôóF¤ôñFöóFöñFõóFõñFèõñFéõóFôóFôñFôóFôñFñóóFôóñFëóóFîóñFäóñFåóóFÜóñFÝóóF¼óñF½óóF¨óñF©óóFóñFóóFþòñFÿòóFêòñFëòóFàòñFáòóFÜòñFÝòóFÀòñFÁòóFªòñF«òóFòñFòóFòñFòóFòñFòóF§Ýñ­Làñ«LØñ«LÙñ­LÏñ­LÒñ«LÚñ«LÛñ­LÍñ­LÐñ«Lò­L¢ò«LÊñ«LËñ­LÇñ­LÊñ«Lò«Lò­L·ñ­Lºñ«L´ñ«Lµñ­L²ñ«L³ñ­L°ñ«L±ñ­LÓò­LÖò«Lñ­Lñ«Lñ­Lñ«Ló­Ló«Lûñ­Lþñ«LÖò«L×ò­Lÿð­Lñ«Lóð­Löð«Lßð­Lâð«LÙð­LÜð«LÒð«LÓð­LÊð«LËð­Lªð«L«ð­Lð«Lð­Lþï«Lÿï­Lìï«Líï­LØï«LÙï­LÎï«LÏï­LÊï«LËï­L®ï«L¯ï­Lï«Lï­Lï«Lï­Lï«Lï­Lï«Lï­L§ËîçQÎîåQÆîåQÇîçQ½îçQÀîåQÈîåQÉîçQ»îçQ¾îåQïçQïåQ¸îåQ¹îçQµîçQ¸îåQòîåQóîçQ¥îçQ¨îåQ¢îåQ£îçQ îåQ¡îçQîåQîçQÁïçQÄïåQîçQîåQýíçQîåQóïçQöïåQéîçQìîåQÄïåQÅïçQííçQðíåQáíçQäíåQÍíçQÐíåQÇíçQÊíåQÀíåQÁíçQ¸íåQ¹íçQíåQíçQíåQíçQììåQíìçQÚìåQÛìçQÆìåQÇìçQ¼ìåQ½ìçQ¸ìåQ¹ìçQìåQìçQìåQìçQúëåQûëçQðëåQñëçQîëåQïëçQ§¹ë¡W¼ëW´ëWµë¡W«ë¡W®ëW¶ëW·ë¡W©ë¡W¬ëWûë¡WþëW¦ëW§ë¡W£ë¡W¦ëWàëWáë¡Wë¡WëWëWë¡WëWë¡WëWë¡W¯ì¡W²ìWõê¡WøêWëê¡WîêWáì¡WäìW×ë¡WÚëW²ìW³ì¡WÛê¡WÞêWÏê¡WÒêW»ê¡W¾êWµê¡W¸êW®êW¯ê¡W¦êW§ê¡WêWê¡WòéWóé¡WÚéWÛé¡WÈéWÉé¡W´éWµé¡WªéW«é¡W¦éW§é¡WéWé¡WôèWõè¡WèèWéè¡WÞèWßè¡WÜèWÝè¡W§§èÛ\ªèÙ\¢èÙ\£èÛ\èÛ\èÙ\¤èÙ\¥èÛ\èÛ\èÙ\éèÛ\ìèÙ\èÙ\èÛ\èÛ\èÙ\ÎèÙ\ÏèÛ\èÛ\èÙ\þçÙ\ÿçÛ\üçÙ\ýçÛ\úçÙ\ûçÛ\éÛ\ éÙ\ãçÛ\æçÙ\ÙçÛ\ÜçÙ\ÏéÛ\ÒéÙ\ÅèÛ\ÈèÙ\ éÙ\¡éÛ\ÉçÛ\ÌçÙ\½çÛ\ÀçÙ\©çÛ\¬çÙ\£çÛ\¦çÙ\çÙ\çÛ\çÙ\çÛ\ôæÙ\õæÛ\àæÙ\áæÛ\ÈæÙ\ÉæÛ\¶æÙ\·æÛ\¢æÙ\£æÛ\æÙ\æÛ\æÙ\æÛ\øåÙ\ùåÛ\âåÙ\ãåÛ\ÖåÙ\×åÛ\ÌåÙ\ÍåÛ\ÊåÙ\ËåÛ\§åbåbåbåbåbåbåbåbåbåb×åbÚåbåbåbÿäbåb¼åb½åbïäbòäbìäbíäbêäbëäbèäbéäbæbæbÑäbÔäbÇäbÊäb½æbÀæb³åb¶åbæbæb·äbºäb«äb®äbäbäbäbäbäbäbäbäbâãbããbÎãbÏãb¶ãb·ãb¤ãb¥ãbãbãbãbãbãbãbæâbçâbÐâbÑâbÄâbÅâbºâb»âb¸âb¹âb§âÏgâÍgþáÍgÿáÏgõáÏgøáÍgâÍgâÏgóáÏgöáÍgÅâÏgÈâÍgðáÍgñáÏgíáÏgðáÍgªâÍg«âÏgÝáÏgàáÍgÚáÍgÛáÏgØáÍgÙáÏgÖáÍg×áÏgùâÏgüâÍg¿áÏgÂáÍgµáÏg¸áÍg«ãÏg®ãÍg¡âÏg¤âÍgüâÍgýâÏg¥áÏg¨áÍgáÏgáÍgáÏgáÍgÿàÏgáÍgøàÍgùàÏgðàÍgñàÏgÐàÍgÑàÏg¼àÍg½àÏg¤àÍg¥àÏgàÍgàÏgþßÍgÿßÏgôßÍgõßÏgðßÍgñßÏgÔßÍgÕßÏg¾ßÍg¿ßÏg²ßÍg³ßÏg¨ßÍg©ßÏg¦ßÍg§ßÏg§ñÞmôÞmìÞmíÞmãÞmæÞmîÞmïÞmáÞmäÞm³ßm¶ßmÞÞmßÞmÛÞmÞÞmßmßmËÞmÎÞmÈÞmÉÞmÆÞmÇÞmÄÞmÅÞmçßmêßm­Þm°Þm£Þm¦ÞmàmàmßmßmêßmëßmÞmÞmÞmÞmóÝmöÝmíÝmðÝmæÝmçÝmÞÝmßÝm¾Ým¿ÝmªÝm«ÝmÝmÝmÝmÝmìÜmíÜmâÜmãÜmÞÜmßÜmÂÜmÃÜm¬Üm­Üm Üm¡ÜmÜmÜmÜmÜm§ßÛÃrâÛÁrÚÛÁrÛÛÃrÑÛÃrÔÛÁrÜÛÁrÝÛÃrÏÛÃrÒÛÁr¡ÜÃr¤ÜÁrÌÛÁrÍÛÃrÉÛÃrÌÛÁrÜÁrÜÃr¹ÛÃr¼ÛÁr¶ÛÁr·ÛÃr´ÛÁrµÛÃr²ÛÁr³ÛÃrÕÜÃrØÜÁrÛÃrÛÁrÛÃrÛÁrÝÃrÝÁrýÛÃrÜÁrØÜÁrÙÜÃrÛÃrÛÁrõÚÃrøÚÁráÚÃräÚÁrÛÚÃrÞÚÁrÔÚÁrÕÚÃrÌÚÁrÍÚÃr¬ÚÁr­ÚÃrÚÁrÚÃrÚÁrÚÃrîÙÁrïÙÃrÚÙÁrÛÙÃrÐÙÁrÑÙÃrÌÙÁrÍÙÃr°ÙÁr±ÙÃrÙÁrÙÃrÙÁrÙÃrÙÁrÙÃrÙÁrÙÃr§ÍØýwÐØûwÈØûwÉØýw¿ØýwÂØûwÊØûwËØýw½ØýwÀØûwÙýwÙûwºØûw»Øýw·ØýwºØûwôØûwõØýw§ØýwªØûw¤Øûw¥Øýw¢Øûw£Øýw Øûw¡ØýwÃÙýwÆÙûwØýwØûwÿ×ýwØûwõÙýwøÙûwëØýwîØûwÆÙûwÇÙýwï×ýwò×ûwã×ýwæ×ûwÏ×ýwÒ×ûwÉ×ýwÌ×ûwÂ×ûwÃ×ýwº×ûw»×ýw×ûw×ýw×ûw×ýwîÖûwïÖýwÜÖûwÝÖýwÈÖûwÉÖýw¾Öûw¿ÖýwºÖûw»ÖýwÖûwÖýwÖûwÖýwüÕûwýÕýwòÕûwóÕýwðÕûwñÕýw§»Õ·}¾Õµ}¶Õµ}·Õ·}­Õ·}°Õµ}¸Õµ}¹Õ·}«Õ·}®Õµ}ýÕ·}Öµ}¨Õµ}©Õ·}¥Õ·}¨Õµ}âÕµ}ãÕ·}Õ·}Õµ}Õµ}Õ·}Õµ}Õ·}Õµ}Õ·}±Ö·}´Öµ}÷Ô·}úÔµ}íÔ·}ðÔµ}ãÖ·}æÖµ}ÙÕ·}ÜÕµ}´Öµ}µÖ·}ÝÔ·}àÔµ}ÑÔ·}ÔÔµ}½Ô·}ÀÔµ}·Ô·}ºÔµ}°Ôµ}±Ô·}¨Ôµ}©Ô·}Ôµ}Ô·}ôÓµ}õÓ·}ÜÓµ}ÝÓ·}ÊÓµ}ËÓ·}¶Óµ}·Ó·}¬Óµ}­Ó·}¨Óµ}©Ó·}Óµ}Ó·}öÒµ}÷Ò·}êÒµ}ëÒ·}àÒµ}áÒ·}ÞÒµ}ßÒ·}§©Òñ¬Òï¤Òï¥ÒñÒñÒï¦Òï§ÒñÒñÒïëÒñîÒïÒïÒñÒñÒïÐÒïÑÒñÒñÒïÒïÒñþÑïÿÑñüÑïýÑñÓñ¢ÓïåÑñèÑïÛÑñÞÑïÑÓñÔÓïÇÒñÊÒï¢Óï£ÓñËÑñÎÑï¿ÑñÂÑï«Ññ®Ñï¥Ññ¨ÑïÑïÑñÑïÑñöÐï÷ÐñâÐïãÐñÊÐïËÐñ¸Ðï¹Ðñ¤Ðï¥ÐñÐïÐñÐïÐñúÏïûÏñäÏïåÏñØÏïÙÏñÎÏïÏÏñÌÏïÍÏñ§Ï«Ï©Ï©Ï«Ï«Ï©Ï©Ï«Ï«Ï©ÙÏ«ÜÏ©Ï©Ï«Ï«Ï©¾Ï©¿Ï«ñÎ«ôÎ©îÎ©ïÎ«ìÎ©íÎ«êÎ©ëÎ«Ð«Ð©ÓÎ«ÖÎ©ÉÎ«ÌÎ©¿Ð«ÂÐ©µÏ«¸Ï©Ð©Ð«¹Î«¼Î©­Î«°Î©Î«Î©Î«Î©Î©Î«Î©Î«äÍ©åÍ«ÐÍ©ÑÍ«¸Í©¹Í«¦Í©§Í«Í©Í«Í©Í«Í©Í«èÌ©éÌ«ÒÌ©ÓÌ«ÆÌ©ÇÌ«¼Ì©½Ì«ºÌ©»Ì«§ÌåÌãÌãÌå÷ËåúËãÌãÌåõËåøËãÇÌåÊÌãòËãóËåïËåòËã¬Ìã­ÌåßËåâËãÜËãÝËåÚËãÛËåØËãÙËåûÌåþÌãÁËåÄËã·ËåºËã­Íå°Íã£Ìå¦ÌãþÌãÿÌå§ËåªËãËåËãËåËãËåËãúÊãûÊåòÊãóÊåÒÊãÓÊå¾Êã¿Êå¦Êã§ÊåÊãÊåÊãÊåöÉã÷ÉåòÉãóÉåÖÉã×ÉåÀÉãÁÉå´ÉãµÉåªÉã«Éå¨Éã©Éå§óÈöÈîÈïÈåÈèÈðÈñÈãÈæÈµÉ¸ÉàÈáÈÝÈàÈÉÉÍÈÐÈÊÈËÈÈÈÉÈÆÈÇÈéÉìÉ¯È²È¥È¨ÈÊÊÉÉìÉíÉÈÈÈÈõÇøÇïÇòÇèÇéÇàÇáÇÀÇÁÇ¬Ç­ÇÇÇÇÇîÆïÆäÆåÆàÆáÆÄÆÅÆ®Æ¯Æ¢Æ£ÆÆÆÆÆ§áÅÙäÅ×ÜÅ×ÝÅÙÓÅÙÖÅ×ÞÅ×ßÅÙÑÅÙÔÅ×£ÆÙ¦Æ×ÎÅ×ÏÅÙËÅÙÎÅ×Æ×ÆÙ»ÅÙ¾Å×¸Å×¹ÅÙ¶Å×·ÅÙ´Å×µÅÙ×ÆÙÚÆ×ÅÙ Å×ÅÙÅ×ÇÙÇ×ÿÅÙÆ×ÚÆ×ÛÆÙÅÙÅ×÷ÄÙúÄ×ãÄÙæÄ×ÝÄÙàÄ×ÖÄ××ÄÙÎÄ×ÏÄÙ®Ä×¯ÄÙÄ×ÄÙÄ×ÄÙðÃ×ñÃÙÜÃ×ÝÃÙÒÃ×ÓÃÙÎÃ×ÏÃÙ²Ã×³ÃÙÃ×ÃÙÃ×ÃÙÃ×ÃÙÃ×ÃÙ§ÏÂÒÂÊÂËÂÁÂÄÂÌÂÍÂ¿ÂÂÂÃÃ¼Â½Â¹Â¼ÂöÂ÷Â©Â¬Â¦Â§Â¤Â¥Â¢Â£ÂÅÃÈÃÂÂÂÂ÷ÃúÃíÂðÂÈÃÉÃñÁôÁåÁèÁÑÁÔÁËÁÎÁÄÁÅÁ¼Á½ÁÁÁÁÁðÀñÀÞÀßÀÊÀËÀÀÀÁÀ¼À½À À¡ÀÀÀþ¿ÿ¿ô¿õ¿ò¿ó¿§Ø»Ø¹Ø¹Ø»Ø»Ø¹Ø¹Ø»Ø»Ø¹×Ø»ÚØ¹Ø¹Ø»ÿ×»Ø¹¼Ø¹½Ø»ï×»ò×¹ì×¹í×»ê×¹ë×»è×¹é×»Ù»Ù¹Ñ×»Ô×¹Ç×»Ê×¹½Ù»ÀÙ¹³Ø»¶Ø¹Ù¹Ù»·×»º×¹«×»®×¹×»×¹×»×¹×¹×»×¹×»âÖ¹ãÖ»ÎÖ¹ÏÖ»¶Ö¹·Ö»¤Ö¹¥Ö»Ö¹Ö»Ö¹Ö»Ö¹Ö»æÕ¹çÕ»ÐÕ¹ÑÕ»ÄÕ¹ÅÕ»ºÕ¹»Õ»¸Õ¹¹Õ»§Õõ
+Õó
+þÔó
+ÿÔõ
+õÔõ
+øÔó
+Õó
+Õõ
+óÔõ
+öÔó
+ÅÕõ
+ÈÕó
+ðÔó
+ñÔõ
+íÔõ
+ðÔó
+ªÕó
+«Õõ
+ÝÔõ
+àÔó
+ÚÔó
+ÛÔõ
+ØÔó
+ÙÔõ
+ÖÔó
+×Ôõ
+ùÕõ
+üÕó
+¿Ôõ
+ÂÔó
+µÔõ
+¸Ôó
+«Öõ
+®Öó
+¡Õõ
+¤Õó
+üÕó
+ýÕõ
+¥Ôõ
+¨Ôó
+Ôõ
+Ôó
+Ôõ
+Ôó
+ÿÓõ
+Ôó
+øÓó
+ùÓõ
+ðÓó
+ñÓõ
+ÐÓó
+ÑÓõ
+¼Óó
+½Óõ
+¤Óó
+¥Óõ
+Óó
+Óõ
+þÒó
+ÿÒõ
+ôÒó
+õÒõ
+ðÒó
+ñÒõ
+ÔÒó
+ÕÒõ
+¾Òó
+¿Òõ
+²Òó
+³Òõ
+¨Òó
+©Òõ
+¦Òó
+§Òõ
+§ñÑ¯ôÑ­ìÑ­íÑ¯ãÑ¯æÑ­îÑ­ïÑ¯áÑ¯äÑ­³Ò¯¶Ò­ÞÑ­ßÑ¯ÛÑ¯ÞÑ­Ò­Ò¯ËÑ¯ÎÑ­ÈÑ­ÉÑ¯ÆÑ­ÇÑ¯ÄÑ­ÅÑ¯çÒ¯êÒ­­Ñ¯°Ñ­£Ñ¯¦Ñ­Ó¯Ó­Ò¯Ò­êÒ­ëÒ¯Ñ¯Ñ­Ñ¯Ñ­óÐ¯öÐ­íÐ¯ðÐ­æÐ­çÐ¯ÞÐ­ßÐ¯¾Ð­¿Ð¯ªÐ­«Ð¯Ð­Ð¯Ð­Ð¯ìÏ­íÏ¯âÏ­ãÏ¯ÞÏ­ßÏ¯ÂÏ­ÃÏ¯¬Ï­­Ï¯ Ï­¡Ï¯Ï­Ï¯Ï­Ï¯§ßÎéâÎçÚÎçÛÎéÑÎéÔÎçÜÎçÝÎéÏÎéÒÎç¡Ïé¤ÏçÌÎçÍÎéÉÎéÌÎçÏçÏé¹Îé¼Îç¶Îç·Îé´ÎçµÎé²Îç³ÎéÕÏéØÏçÎéÎçÎéÎçÐéÐçýÎéÏçØÏçÙÏéÎéÎçõÍéøÍçáÍéäÍçÛÍéÞÍçÔÍçÕÍéÌÍçÍÍé¬Íç­ÍéÍçÍéÍçÍéîÌçïÌéÚÌçÛÌéÐÌçÑÌéÌÌçÍÌé°Ìç±ÌéÌçÌéÌçÌéÌçÌéÌçÌé§ÍË£ÐË¡ÈË¡ÉË£¿Ë£ÂË¡ÊË¡ËË£½Ë£ÀË¡Ì£Ì¡ºË¡»Ë£·Ë£ºË¡ôË¡õË£§Ë£ªË¡¤Ë¡¥Ë£¢Ë¡£Ë£ Ë¡¡Ë£ÃÌ£ÆÌ¡Ë£Ë¡ÿÊ£Ë¡õÌ£øÌ¡ëË£îË¡ÆÌ¡ÇÌ£ïÊ£òÊ¡ãÊ£æÊ¡ÏÊ£ÒÊ¡ÉÊ£ÌÊ¡ÂÊ¡ÃÊ£ºÊ¡»Ê£Ê¡Ê£Ê¡Ê£îÉ¡ïÉ£ÜÉ¡ÝÉ£ÈÉ¡ÉÉ£¾É¡¿É£ºÉ¡»É£É¡É£É¡É£üÈ¡ýÈ£òÈ¡óÈ£ðÈ¡ñÈ£§»ÈÝ ¾ÈÛ ¶ÈÛ ·ÈÝ ­ÈÝ °ÈÛ ¸ÈÛ ¹ÈÝ «ÈÝ ®ÈÛ ýÈÝ ÉÛ ¨ÈÛ ©ÈÝ ¥ÈÝ ¨ÈÛ âÈÛ ãÈÝ ÈÝ ÈÛ ÈÛ ÈÝ ÈÛ ÈÝ ÈÛ ÈÝ ±ÉÝ ´ÉÛ ÷ÇÝ úÇÛ íÇÝ ðÇÛ ãÉÝ æÉÛ ÙÈÝ ÜÈÛ ´ÉÛ µÉÝ ÝÇÝ àÇÛ ÑÇÝ ÔÇÛ ½ÇÝ ÀÇÛ ·ÇÝ ºÇÛ °ÇÛ ±ÇÝ ¨ÇÛ ©ÇÝ ÇÛ ÇÝ ôÆÛ õÆÝ ÜÆÛ ÝÆÝ ÊÆÛ ËÆÝ ¶ÆÛ ·ÆÝ ¬ÆÛ ­ÆÝ ¨ÆÛ ©ÆÝ ÆÛ ÆÝ öÅÛ ÷ÅÝ êÅÛ ëÅÝ àÅÛ áÅÝ ÞÅÛ ßÅÝ §©Å&¬Å&¤Å&¥Å&Å&Å&¦Å&§Å&Å&Å&ëÅ&îÅ&Å&Å&Å&Å&ÐÅ&ÑÅ&Å&Å&Å&Å&þÄ&ÿÄ&üÄ&ýÄ&Æ&¢Æ&åÄ&èÄ&ÛÄ&ÞÄ&ÑÆ&ÔÆ&ÇÅ&ÊÅ&¢Æ&£Æ&ËÄ&ÎÄ&¿Ä&ÂÄ&«Ä&®Ä&¥Ä&¨Ä&Ä&Ä&Ä&Ä&öÃ&÷Ã&âÃ&ãÃ&ÊÃ&ËÃ&¸Ã&¹Ã&¤Ã&¥Ã&Ã&Ã&Ã&Ã&úÂ&ûÂ&äÂ&åÂ&ØÂ&ÙÂ&ÎÂ&ÏÂ&ÌÂ&ÍÂ&§ÂÑ+ÂÏ+ÂÏ+ÂÑ+ÂÑ+ÂÏ+ÂÏ+ÂÑ+ÂÑ+ÂÏ+ÙÂÑ+ÜÂÏ+ÂÏ+ÂÑ+ÂÑ+ÂÏ+¾ÂÏ+¿ÂÑ+ñÁÑ+ôÁÏ+îÁÏ+ïÁÑ+ìÁÏ+íÁÑ+êÁÏ+ëÁÑ+ÃÑ+ÃÏ+ÓÁÑ+ÖÁÏ+ÉÁÑ+ÌÁÏ+¿ÃÑ+ÂÃÏ+µÂÑ+¸ÂÏ+ÃÏ+ÃÑ+¹ÁÑ+¼ÁÏ+­ÁÑ+°ÁÏ+ÁÑ+ÁÏ+ÁÑ+ÁÏ+ÁÏ+ÁÑ+ÁÏ+ÁÑ+äÀÏ+åÀÑ+ÐÀÏ+ÑÀÑ+¸ÀÏ+¹ÀÑ+¦ÀÏ+§ÀÑ+ÀÏ+ÀÑ+ÀÏ+ÀÑ+ÀÏ+ÀÑ+è¿Ï+é¿Ñ+Ò¿Ï+Ó¿Ñ+Æ¿Ï+Ç¿Ñ+¼¿Ï+½¿Ñ+º¿Ï+»¿Ñ+§¿1¿1¿1¿1÷¾1ú¾1¿1¿1õ¾1ø¾1Ç¿1Ê¿1ò¾1ó¾1ï¾1ò¾1¬¿1­¿1ß¾1â¾1Ü¾1Ý¾1Ú¾1Û¾1Ø¾1Ù¾1û¿1þ¿1Á¾1Ä¾1·¾1º¾1­À1°À1£¿1¦¿1þ¿1ÿ¿1§¾1ª¾1¾1¾1¾1¾1¾1¾1ú½1û½1ò½1ó½1Ò½1Ó½1¾½1¿½1¦½1§½1½1½1½1½1ö¼1÷¼1ò¼1ó¼1Ö¼1×¼1À¼1Á¼1´¼1µ¼1ª¼1«¼1¨¼1©¼1§ó»Å6ö»Ã6î»Ã6ï»Å6å»Å6è»Ã6ð»Ã6ñ»Å6ã»Å6æ»Ã6µ¼Å6¸¼Ã6à»Ã6á»Å6Ý»Å6à»Ã6¼Ã6¼Å6Í»Å6Ð»Ã6Ê»Ã6Ë»Å6È»Ã6É»Å6Æ»Ã6Ç»Å6é¼Å6ì¼Ã6¯»Å6²»Ã6¥»Å6¨»Ã6½Å6½Ã6¼Å6¼Ã6ì¼Ã6í¼Å6»Å6»Ã6»Å6»Ã6õºÅ6øºÃ6ïºÅ6òºÃ6èºÃ6éºÅ6àºÃ6áºÅ6ÀºÃ6ÁºÅ6¬ºÃ6­ºÅ6ºÃ6ºÅ6ºÃ6ºÅ6î¹Ã6ï¹Å6ä¹Ã6å¹Å6à¹Ã6á¹Å6Ä¹Ã6Å¹Å6®¹Ã6¯¹Å6¢¹Ã6£¹Å6¹Ã6¹Å6¹Ã6¹Å6§á¸ÿ;ä¸ý;Ü¸ý;Ý¸ÿ;Ó¸ÿ;Ö¸ý;Þ¸ý;ß¸ÿ;Ñ¸ÿ;Ô¸ý;£¹ÿ;¦¹ý;Î¸ý;Ï¸ÿ;Ë¸ÿ;Î¸ý;¹ý;¹ÿ;»¸ÿ;¾¸ý;¸¸ý;¹¸ÿ;¶¸ý;·¸ÿ;´¸ý;µ¸ÿ;×¹ÿ;Ú¹ý;¸ÿ; ¸ý;¸ÿ;¸ý;ºÿ;ºý;ÿ¸ÿ;¹ý;Ú¹ý;Û¹ÿ;¸ÿ;¸ý;÷·ÿ;ú·ý;ã·ÿ;æ·ý;Ý·ÿ;à·ý;Ö·ý;×·ÿ;Î·ý;Ï·ÿ;®·ý;¯·ÿ;·ý;·ÿ;·ý;·ÿ;ð¶ý;ñ¶ÿ;Ü¶ý;Ý¶ÿ;Ò¶ý;Ó¶ÿ;Î¶ý;Ï¶ÿ;²¶ý;³¶ÿ;¶ý;¶ÿ;¶ý;¶ÿ;¶ý;¶ÿ;¶ý;¶ÿ;§Ïµ¹AÒµ·AÊµ·AËµ¹AÁµ¹AÄµ·AÌµ·AÍµ¹A¿µ¹AÂµ·A¶¹A¶·A¼µ·A½µ¹A¹µ¹A¼µ·Aöµ·A÷µ¹A©µ¹A¬µ·A¦µ·A§µ¹A¤µ·A¥µ¹A¢µ·A£µ¹AÅ¶¹AÈ¶·Aµ¹Aµ·Aµ¹Aµ·A÷¶¹Aú¶·Aíµ¹Aðµ·AÈ¶·AÉ¶¹Añ´¹Aô´·Aå´¹Aè´·AÑ´¹AÔ´·AË´¹AÎ´·AÄ´·AÅ´¹A¼´·A½´¹A´·A´¹A´·A´¹Að³·Añ³¹AÞ³·Aß³¹AÊ³·AË³¹AÀ³·AÁ³¹A¼³·A½³¹A ³·A¡³¹A³·A³¹Aþ²·Aÿ²¹Aô²·Aõ²¹Aò²·Aó²¹A§½²óFÀ²ñF¸²ñF¹²óF¯²óF²²ñFº²ñF»²óF­²óF°²ñFÿ²óF³ñFª²ñF«²óF§²óFª²ñFä²ñFå²óF²óF²ñF²ñF²óF²ñF²óF²ñF²óF³³óF¶³ñFù±óFü±ñFï±óFò±ñFå³óFè³ñFÛ²óFÞ²ñF¶³ñF·³óFß±óFâ±ñFÓ±óFÖ±ñF¿±óFÂ±ñF¹±óF¼±ñF²±ñF³±óFª±ñF«±óF±ñF±óFö°ñF÷°óFÞ°ñFß°óFÌ°ñFÍ°óF¸°ñF¹°óF®°ñF¯°óFª°ñF«°óF°ñF°óFø¯ñFù¯óFì¯ñFí¯óFâ¯ñFã¯óFà¯ñFá¯óF§«¯­L®¯«L¦¯«L§¯­L¯­L ¯«L¨¯«L©¯­L¯­L¯«Lí¯­Lð¯«L¯«L¯­L¯­L¯«LÒ¯«LÓ¯­L¯­L¯«L¯«L¯­L¯«L¯­Lþ®«Lÿ®­L¡°­L¤°«Lç®­Lê®«LÝ®­Là®«LÓ°­LÖ°«LÉ¯­LÌ¯«L¤°«L¥°­LÍ®­LÐ®«LÁ®­LÄ®«L­®­L°®«L§®­Lª®«L ®«L¡®­L®«L®­Lø­«Lù­­Lä­«Lå­­LÌ­«LÍ­­Lº­«L»­­L¦­«L§­­L­«L­­L­«L­­Lü¬«Lý¬­Læ¬«Lç¬­LÚ¬«LÛ¬­LÐ¬«LÑ¬­LÎ¬«LÏ¬­L§¬çQ¬åQ¬åQ¬çQ¬çQ¬åQ¬åQ¬çQ¬çQ¬åQÛ¬çQÞ¬åQ¬åQ¬çQ¬çQ¬åQÀ¬åQÁ¬çQó«çQö«åQð«åQñ«çQî«åQï«çQì«åQí«çQ­çQ­åQÕ«çQØ«åQË«çQÎ«åQÁ­çQÄ­åQ·¬çQº¬åQ­åQ­çQ»«çQ¾«åQ¯«çQ²«åQ«çQ«åQ«çQ«åQ«åQ«çQ«åQ«çQæªåQçªçQÒªåQÓªçQºªåQ»ªçQ¨ªåQ©ªçQªåQªçQªåQªçQªåQªçQê©åQë©çQÔ©åQÕ©çQÈ©åQÉ©çQ¾©åQ¿©çQ¼©åQ½©çQ§©¡W©W©W©¡Wù¨¡Wü¨W©W©¡W÷¨¡Wú¨WÉ©¡WÌ©Wô¨Wõ¨¡Wñ¨¡Wô¨W®©W¯©¡Wá¨¡Wä¨WÞ¨Wß¨¡WÜ¨WÝ¨¡WÚ¨WÛ¨¡Wý©¡WªWÃ¨¡WÆ¨W¹¨¡W¼¨W¯ª¡W²ªW¥©¡W¨©WªWª¡W©¨¡W¬¨W¨¡W ¨W¨¡W¨W¨¡W¨Wü§Wý§¡Wô§Wõ§¡WÔ§WÕ§¡WÀ§WÁ§¡W¨§W©§¡W§W§¡W§W§¡Wø¦Wù¦¡Wô¦Wõ¦¡WØ¦WÙ¦¡WÂ¦WÃ¦¡W¶¦W·¦¡W¬¦W­¦¡Wª¦W«¦¡W§õ¥Û\ø¥Ù\ð¥Ù\ñ¥Û\ç¥Û\ê¥Ù\ò¥Ù\ó¥Û\å¥Û\è¥Ù\·¦Û\º¦Ù\â¥Ù\ã¥Û\ß¥Û\â¥Ù\¦Ù\¦Û\Ï¥Û\Ò¥Ù\Ì¥Ù\Í¥Û\Ê¥Ù\Ë¥Û\È¥Ù\É¥Û\ë¦Û\î¦Ù\±¥Û\´¥Ù\§¥Û\ª¥Ù\§Û\ §Ù\¦Û\¦Ù\î¦Ù\ï¦Û\¥Û\¥Ù\¥Û\¥Ù\÷¤Û\ú¤Ù\ñ¤Û\ô¤Ù\ê¤Ù\ë¤Û\â¤Ù\ã¤Û\Â¤Ù\Ã¤Û\®¤Ù\¯¤Û\¤Ù\¤Û\¤Ù\¤Û\ð£Ù\ñ£Û\æ£Ù\ç£Û\â£Ù\ã£Û\Æ£Ù\Ç£Û\°£Ù\±£Û\¤£Ù\¥£Û\£Ù\£Û\£Ù\£Û\§ã¢bæ¢bÞ¢bß¢bÕ¢bØ¢bà¢bá¢bÓ¢bÖ¢b¥£b¨£bÐ¢bÑ¢bÍ¢bÐ¢b£b£b½¢bÀ¢bº¢b»¢b¸¢b¹¢b¶¢b·¢bÙ£bÜ£b¢b¢¢b¢b¢b¤b¤b£b£bÜ£bÝ£b¢b¢bù¡bü¡bå¡bè¡bß¡bâ¡bØ¡bÙ¡bÐ¡bÑ¡b°¡b±¡b¡b¡b¡b¡bò bó bÞ bß bÔ bÕ bÐ bÑ b´ bµ b b b b b b b b b§ÑÏgÔÍgÌÍgÍÏgÃÏgÆÍgÎÍgÏÏgÁÏgÄÍg Ïg Íg¾Íg¿Ïg»Ïg¾ÍgøÍgùÏg«Ïg®Íg¨Íg©Ïg¦Íg§Ïg¤Íg¥ÏgÇ ÏgÊ ÍgÏgÍgÏgÍgù Ïgü ÍgïÏgòÍgÊ ÍgË ÏgóÏgöÍgçÏgêÍgÓÏgÖÍgÍÏgÐÍgÆÍgÇÏg¾Íg¿ÏgÍgÏgÍgÏgòÍgóÏgàÍgáÏgÌÍgÍÏgÂÍgÃÏg¾Íg¿Ïg¢Íg£ÏgÍgÏgÍgÏgöÍg÷ÏgôÍgõÏg§¿mÂmºm»m±m´m¼m½m¯m²mmm¬m­m©m¬mæmçmmmmmmmmmµm¸mûmþmñmômçmêmÝmàm¸m¹mámämÕmØmÁmÄm»m¾m´mµm¬m­mmmømùmàmámÎmÏmºm»m°m±m¬m­mmmúmûmîmïmämåmâmãm§­Ãr°Ár¨Ár©ÃrÃr¢ÁrªÁr«ÃrÃr ÁrïÃròÁrÁrÃrÃrÁrÔÁrÕÃrÃrÁrÁrÃrÁrÃrÁrÃr£Ãr¦ÁréÃrìÁrßÃrâÁrÕÃrØÁrËÃrÎÁr¦Ár§ÃrÏÃrÒÁrÃÃrÆÁr¯Ãr²Ár©Ãr¬Ár¢Ár£ÃrÁrÃrúÁrûÃræÁrçÃrÎÁrÏÃr¼Ár½Ãr¨Ár©ÃrÁrÃrÁrÃrþÁrÿÃrèÁréÃrÜÁrÝÃrÒÁrÓÃrÐÁrÑÃr§ýwûwûwýwýwûwûwýwýwûwÝýwàûwûwýwýwûwÂûwÃýwõýwøûwòûwóýwðûwñýwîûwïýwýwûw×ýwÚûwÍýwÐûwÃýwÆûw¹ýw¼ûwûwýw½ýwÀûw±ýw´ûwýw ûwýwûwûwýwûwýwèûwéýwÔûwÕýw¼ûw½ýwªûw«ýwûwýwûwýwûwýwìûwíýwÖûw×ýwÊûwËýwÀûwÁýw¾ûw¿ýw§·}µ}µ}·}û·}þµ}µ}·}ù·}üµ}Ë·}Îµ}öµ}÷·}ó·}öµ}°µ}±·}ã·}æµ}àµ}á·}Þµ}ß·}Üµ}Ý·}ÿ·}µ}Å·}Èµ}»·}¾µ}±·}´µ}§·}ªµ}µ}·}«·}®µ}·}¢µ}·}µ}·}µ}þµ}ÿ·}öµ}÷·}Öµ}×·}Âµ}Ã·}ªµ}«·}µ}·}µ}·}úµ}û·}öµ}÷·}Úµ}Û·}Äµ}Å·}¸µ}¹·}®µ}¯·}¬µ}­·}§÷ñúïòïóñéñìïôïõñçñêï¹ñ¼ïäïåñáñäïïñÑñÔïÎïÏñÌïÍñÊïËñíñðï³ñ¶ï©ñ¬ïñ¢ïñïðïñññïñïùñüïóñöïìïíñäïåñÄïÅñ°ï±ñïñïñòïóñèïéñäïåñÈïÉñ²ï³ñ¦ï§ñïñïñ§å«è©à©á«×«Ú©â©ã«Õ«Ø©§«ª©Ò©Ó«Ï«Ò©©«¿«Â©¼©½«º©»«¸©¹«Û«Þ©¡«¤©«©«©«©Þ©ß««©û«þ©ç«ê©á«ä©Ú©Û«Ò©Ó«²©³«©«©«ô©õ«à©á«Ö©×«Ò©Ó«¶©·« ©¡«©«©«©«§ÓåÖãÎãÏåÅåÈãÐãÑåÃåÆãåãÀãÁå½åÀãúãûå­å°ãªã«å¨ã©å¦ã§åÉåÌãåãåãûåþãñåôãÌãÍåõåøãéåìãÕåØãÏåÒãÈãÉåÀãÁå ã¡åãåôãõåâããåÎãÏåÄãÅåÀãÁå¤ã¥åãåãåøãùåöã÷å§ÁÄ¼½³¶¾¿±´®¯«®èé·ºýóöéìßâº»ãæ×ÚÃÆ½À¶·®¯úûâãÐÑ¼½²³®¯üýðñæçäå§¯Ù²×ª×«Ù¡Ù¤×¬×­ÙÙ¢×ñÙô××ÙÙ×Ö××ÙÙ××Ù×Ù×Ù¥Ù¨×ëÙî×áÙä××ÙÚ×ÍÙÐ×¨×©ÙÑÙÔ×ÅÙÈ×±Ù´×«Ù®×¤×¥Ù×Ùü×ýÙè×éÙÐ×ÑÙ¾×¿Ùª×«Ù ×¡Ù×Ù×Ùê×ëÙÞ×ßÙÔ×ÕÙÒ×ÓÙ§»»¾¹¶¹·»­»°¹¸¹¹»«»®¹ý»¹¨¹©»¥»¨¹â¹ã»»¹¹»¹»¹»±»´¹÷»ú¹í»ð¹ã»æ¹Ù»Ü¹´¹µ»Ý»à¹Ñ»Ô¹½»À¹·»º¹°¹±»¨¹©»¹»ô¹õ»Ü¹Ý»Ê¹Ë»¶¹·»¬¹­»¨¹©»¹»ö¹÷»ê¹ë»à¹á»Þ¹ß»§©õ
+¬ó
+¤ó
+¥õ
+õ
+ó
+¦ó
+§õ
+õ
+ó
+ëõ
+îó
+ó
+õ
+õ
+ó
+Ðó
+Ñõ
+õ
+ó
+ó
+õ
+þó
+ÿõ
+üó
+ýõ
+õ
+¢ó
+åõ
+èó
+Ûõ
+Þó
+Ñõ
+Ôó
+Çõ
+Êó
+¢ó
+£õ
+Ëõ
+Îó
+¿õ
+Âó
+«õ
+®ó
+¥õ
+¨ó
+ó
+õ
+ó
+õ
+öó
+÷õ
+âó
+ãõ
+Êó
+Ëõ
+¸ó
+¹õ
+¤ó
+¥õ
+ó
+õ
+ó
+õ
+úó
+ûõ
+äó
+åõ
+Øó
+Ùõ
+Îó
+Ïõ
+Ìó
+Íõ
+§¯­­¯¯­­¯¯­Ù¯Ü­­¯¯­¾­¿¯ñ¯ô­î­ï¯ì­í¯ê­ë¯¯­Ó¯Ö­É¯Ì­¿¯Â­µ¯¸­­¯¹¯¼­­¯°­¯­¯­­¯­¯ä­å¯Ð­Ñ¯¸­¹¯¦­§¯­¯­¯­¯è­é¯Ò­Ó¯Æ­Ç¯¼­½¯º­»¯§éççé÷éúççéõéøçÇéÊçòçóéïéòç¬ç­éßéâçÜçÝéÚçÛéØçÙéûéþçÁéÄç·éºç­é°ç£é¦çþçÿé§éªçéçéçéçúçûéòçóéÒçÓé¾ç¿é¦ç§éçéçéöç÷éòçóéÖç×éÀçÁé´çµéªç«é¨ç©é§ó£ö¡î¡ï£å£è¡ð¡ñ£ã£æ¡µ£¸¡à¡á£Ý£à¡¡£Í£Ð¡Ê¡Ë£È¡É£Æ¡Ç£é£ì¡¯£²¡¥£¨¡£¡£¡ì¡í££¡£¡õ£ø¡ï£ò¡è¡é£à¡á£À¡Á£¬¡­£¡£¡£î¡ï£ä¡å£à¡á£Ä¡Å£®¡¯£¢¡££¡£¡£§áÝ äÛ ÜÛ ÝÝ ÓÝ ÖÛ ÞÛ ßÝ ÑÝ ÔÛ £Ý ¦Û ÎÛ ÏÝ ËÝ ÎÛ Û Ý »Ý ¾Û ¸Û ¹Ý ¶Û ·Ý ´Û µÝ ×Ý ÚÛ Ý  Û Ý Û Ý Û ÿÝ Û ÚÛ ÛÝ Ý Û ÷Ý úÛ ãÝ æÛ ÝÝ àÛ ÖÛ ×Ý ÎÛ ÏÝ ®Û ¯Ý Û Ý Û Ý ðÛ ñÝ ÜÛ ÝÝ ÒÛ ÓÝ ÎÛ ÏÝ ²Û ³Ý Û Ý Û Ý Û Ý Û Ý §Ï&Ò&Ê&Ë&Á&Ä&Ì&Í&¿&Â&&&¼&½&¹&¼&ö&÷&©&¬&¦&§&¤&¥&¢&£&Å&È&&&&&÷&ú&í&ð&È&É&ñÿ&ôÿ&åÿ&èÿ&Ñÿ&Ôÿ&Ëÿ&Îÿ&Äÿ&Åÿ&¼ÿ&½ÿ&ÿ&ÿ&ÿ&ÿ&ðþ&ñþ&Þþ&ßþ&Êþ&Ëþ&Àþ&Áþ&¼þ&½þ& þ&¡þ&þ&þ&þý&ÿý&ôý&õý&òý&óý&§½ýÑ+ÀýÏ+¸ýÏ+¹ýÑ+¯ýÑ+²ýÏ+ºýÏ+»ýÑ+­ýÑ+°ýÏ+ÿýÑ+þÏ+ªýÏ+«ýÑ+§ýÑ+ªýÏ+äýÏ+åýÑ+ýÑ+ýÏ+ýÏ+ýÑ+ýÏ+ýÑ+ýÏ+ýÑ+³þÑ+¶þÏ+ùüÑ+üüÏ+ïüÑ+òüÏ+åþÑ+èþÏ+ÛýÑ+ÞýÏ+¶þÏ+·þÑ+ßüÑ+âüÏ+ÓüÑ+ÖüÏ+¿üÑ+ÂüÏ+¹üÑ+¼üÏ+²üÏ+³üÑ+ªüÏ+«üÑ+üÏ+üÑ+öûÏ+÷ûÑ+ÞûÏ+ßûÑ+ÌûÏ+ÍûÑ+¸ûÏ+¹ûÑ+®ûÏ+¯ûÑ+ªûÏ+«ûÑ+ûÏ+ûÑ+øúÏ+ùúÑ+ìúÏ+íúÑ+âúÏ+ãúÑ+àúÏ+áúÑ+§«ú1®ú1¦ú1§ú1ú1 ú1¨ú1©ú1ú1ú1íú1ðú1ú1ú1ú1ú1Òú1Óú1ú1ú1ú1ú1ú1ú1þù1ÿù1¡û1¤û1çù1êù1Ýù1àù1Óû1Öû1Éú1Ìú1¤û1¥û1Íù1Ðù1Áù1Äù1­ù1°ù1§ù1ªù1 ù1¡ù1ù1ù1øø1ùø1äø1åø1Ìø1Íø1ºø1»ø1¦ø1§ø1ø1ø1ø1ø1ü÷1ý÷1æ÷1ç÷1Ú÷1Û÷1Ð÷1Ñ÷1Î÷1Ï÷1§÷Å6÷Ã6÷Ã6÷Å6÷Å6÷Ã6÷Ã6÷Å6÷Å6÷Ã6Û÷Å6Þ÷Ã6÷Ã6÷Å6÷Å6÷Ã6À÷Ã6Á÷Å6óöÅ6ööÃ6ðöÃ6ñöÅ6îöÃ6ïöÅ6ìöÃ6íöÅ6øÅ6øÃ6ÕöÅ6ØöÃ6ËöÅ6ÎöÃ6ÁøÅ6ÄøÃ6·÷Å6º÷Ã6øÃ6øÅ6»öÅ6¾öÃ6¯öÅ6²öÃ6öÅ6öÃ6öÅ6öÃ6öÃ6öÅ6öÃ6öÅ6æõÃ6çõÅ6ÒõÃ6ÓõÅ6ºõÃ6»õÅ6¨õÃ6©õÅ6õÃ6õÅ6õÃ6õÅ6õÃ6õÅ6êôÃ6ëôÅ6ÔôÃ6ÕôÅ6ÈôÃ6ÉôÅ6¾ôÃ6¿ôÅ6¼ôÃ6½ôÅ6§ôÿ;ôý;ôý;ôÿ;ùóÿ;üóý;ôý;ôÿ;÷óÿ;úóý;Éôÿ;Ìôý;ôóý;õóÿ;ñóÿ;ôóý;®ôý;¯ôÿ;áóÿ;äóý;Þóý;ßóÿ;Üóý;Ýóÿ;Úóý;Ûóÿ;ýôÿ;õý;Ãóÿ;Æóý;¹óÿ;¼óý;¯õÿ;²õý;¥ôÿ;¨ôý;õý;õÿ;©óÿ;¬óý;óÿ; óý;óÿ;óý;óÿ;óý;üòý;ýòÿ;ôòý;õòÿ;Ôòý;Õòÿ;Àòý;Áòÿ;¨òý;©òÿ;òý;òÿ;òý;òÿ;øñý;ùñÿ;ôñý;õñÿ;Øñý;Ùñÿ;Âñý;Ãñÿ;¶ñý;·ñÿ;¬ñý;­ñÿ;ªñý;«ñÿ;§õð¹Aøð·Aðð·Añð¹Açð¹Aêð·Aòð·Aóð¹Aåð¹Aèð·A·ñ¹Aºñ·Aâð·Aãð¹Aßð¹Aâð·Añ·Añ¹AÏð¹AÒð·AÌð·AÍð¹AÊð·AËð¹AÈð·AÉð¹Aëñ¹Aîñ·A±ð¹A´ð·A§ð¹Aªð·Aò¹A ò·Añ¹Añ·Aîñ·Aïñ¹Að¹Að·Að¹Að·A÷ï¹Aúï·Añï¹Aôï·Aêï·Aëï¹Aâï·Aãï¹AÂï·AÃï¹A®ï·A¯ï¹Aï·Aï¹Aï·Aï¹Aðî·Añî¹Aæî·Açî¹Aâî·Aãî¹AÆî·AÇî¹A°î·A±î¹A¤î·A¥î¹Aî·Aî¹Aî·Aî¹A§ãíóFæíñFÞíñFßíóFÕíóFØíñFàíñFáíóFÓíóFÖíñF¥îóF¨îñFÐíñFÑíóFÍíóFÐíñFîñFîóF½íóFÀíñFºíñF»íóF¸íñF¹íóF¶íñF·íóFÙîóFÜîñFíóF¢íñFíóFíñFïóFïñFîóFîñFÜîñFÝîóFíóFíñFùìóFüìñFåìóFèìñFßìóFâìñFØìñFÙìóFÐìñFÑìóF°ìñF±ìóFìñFìóFìñFìóFòëñFóëóFÞëñFßëóFÔëñFÕëóFÐëñFÑëóF´ëñFµëóFëñFëóFëñFëóFëñFëóFëñFëóF§Ñê­LÔê«LÌê«LÍê­LÃê­LÆê«LÎê«LÏê­LÁê­LÄê«Lë­Lë«L¾ê«L¿ê­L»ê­L¾ê«Løê«Lùê­L«ê­L®ê«L¨ê«L©ê­L¦ê«L§ê­L¤ê«L¥ê­LÇë­LÊë«Lê­Lê«Lê­Lê«Lùë­Lüë«Lïê­Lòê«LÊë«LËë­Lóé­Löé«Lçé­Lêé«LÓé­LÖé«LÍé­LÐé«LÆé«LÇé­L¾é«L¿é­Lé«Lé­Lé«Lé­Lòè«Lóè­Làè«Láè­LÌè«LÍè­LÂè«LÃè­L¾è«L¿è­L¢è«L£è­Lè«Lè­Lè«Lè­Löç«L÷ç­Lôç«Lõç­L§¿ççQÂçåQºçåQ»ççQ±ççQ´çåQ¼çåQ½ççQ¯ççQ²çåQèçQèåQ¬çåQ­ççQ©ççQ¬çåQæçåQçççQççQçåQçåQççQçåQççQçåQççQµèçQ¸èåQûæçQþæåQñæçQôæåQçèçQêèåQÝççQàçåQ¸èåQ¹èçQáæçQäæåQÕæçQØæåQÁæçQÄæåQ»æçQ¾æåQ´æåQµæçQ¬æåQ­æçQæåQæçQøååQùåçQàååQáåçQÎååQÏåçQºååQ»åçQ°ååQ±åçQ¬ååQ­åçQååQåçQúäåQûäçQîäåQïäçQääåQåäçQâäåQãäçQ§­ä¡W°äW¨äW©ä¡Wä¡W¢äWªäW«ä¡Wä¡W äWïä¡WòäWäWä¡Wä¡WäWÔäWÕä¡Wä¡WäWäWä¡WäWä¡WäWä¡W£å¡W¦åWéã¡WìãWßã¡WâãWÕå¡WØåWËä¡WÎäW¦åW§å¡WÏã¡WÒãWÃã¡WÆãW¯ã¡W²ãW©ã¡W¬ãW¢ãW£ã¡WãWã¡WúâWûâ¡WæâWçâ¡WÎâWÏâ¡W¼âW½â¡W¨âW©â¡WâWâ¡WâWâ¡WþáWÿá¡WèáWéá¡WÜáWÝá¡WÒáWÓá¡WÐáWÑá¡W§áÛ\áÙ\áÙ\áÛ\áÛ\áÙ\áÙ\áÛ\áÛ\áÙ\ÝáÛ\àáÙ\áÙ\áÛ\áÛ\áÙ\ÂáÙ\ÃáÛ\õàÛ\øàÙ\òàÙ\óàÛ\ðàÙ\ñàÛ\îàÙ\ïàÛ\âÛ\âÙ\×àÛ\ÚàÙ\ÍàÛ\ÐàÙ\ÃâÛ\ÆâÙ\¹áÛ\¼áÙ\âÙ\âÛ\½àÛ\ÀàÙ\±àÛ\´àÙ\àÛ\ àÙ\àÛ\àÙ\àÙ\àÛ\àÙ\àÛ\èßÙ\éßÛ\ÔßÙ\ÕßÛ\¼ßÙ\½ßÛ\ªßÙ\«ßÛ\ßÙ\ßÛ\ßÙ\ßÛ\ßÙ\ßÛ\ìÞÙ\íÞÛ\ÖÞÙ\×ÞÛ\ÊÞÙ\ËÞÛ\ÀÞÙ\ÁÞÛ\¾ÞÙ\¿ÞÛ\§ÞbÞbÞbÞbûÝbþÝbÞbÞbùÝbüÝbËÞbÎÞböÝb÷ÝbóÝböÝb°Þb±ÞbãÝbæÝbàÝbáÝbÞÝbßÝbÜÝbÝÝbÿÞbßbÅÝbÈÝb»Ýb¾Ýb±ßb´ßb§ÞbªÞbßbßb«Ýb®ÝbÝb¢ÝbÝbÝbÝbÝbþÜbÿÜböÜb÷ÜbÖÜb×ÜbÂÜbÃÜbªÜb«ÜbÜbÜbÜbÜbúÛbûÛböÛb÷ÛbÚÛbÛÛbÄÛbÅÛb¸Ûb¹Ûb®Ûb¯Ûb¬Ûb­Ûb§÷ÚÏgúÚÍgòÚÍgóÚÏgéÚÏgìÚÍgôÚÍgõÚÏgçÚÏgêÚÍg¹ÛÏg¼ÛÍgäÚÍgåÚÏgáÚÏgäÚÍgÛÍgÛÏgÑÚÏgÔÚÍgÎÚÍgÏÚÏgÌÚÍgÍÚÏgÊÚÍgËÚÏgíÛÏgðÛÍg³ÚÏg¶ÚÍg©ÚÏg¬ÚÍgÜÏg¢ÜÍgÛÏgÛÍgðÛÍgñÛÏgÚÏgÚÍgÚÏgÚÍgùÙÏgüÙÍgóÙÏgöÙÍgìÙÍgíÙÏgäÙÍgåÙÏgÄÙÍgÅÙÏg°ÙÍg±ÙÏgÙÍgÙÏgÙÍgÙÏgòØÍgóØÏgèØÍgéØÏgäØÍgåØÏgÈØÍgÉØÏg²ØÍg³ØÏg¦ØÍg§ØÏgØÍgØÏgØÍgØÏg§å×mè×mà×má×m××mÚ×mâ×mã×mÕ×mØ×m§ØmªØmÒ×mÓ×mÏ×mÒ×mØmØm¿×mÂ×m¼×m½×mº×m»×m¸×m¹×mÛØmÞØm¡×m¤×m×m×mÙmÙmØmØmÞØmßØm×m×mûÖmþÖmçÖmêÖmáÖmäÖmÚÖmÛÖmÒÖmÓÖm²Öm³ÖmÖmÖmÖmÖmôÕmõÕmàÕmáÕmÖÕm×ÕmÒÕmÓÕm¶Õm·Õm Õm¡ÕmÕmÕmÕmÕmÕmÕm§ÓÔÃrÖÔÁrÎÔÁrÏÔÃrÅÔÃrÈÔÁrÐÔÁrÑÔÃrÃÔÃrÆÔÁrÕÃrÕÁrÀÔÁrÁÔÃr½ÔÃrÀÔÁrúÔÁrûÔÃr­ÔÃr°ÔÁrªÔÁr«ÔÃr¨ÔÁr©ÔÃr¦ÔÁr§ÔÃrÉÕÃrÌÕÁrÔÃrÔÁrÔÃrÔÁrûÕÃrþÕÁrñÔÃrôÔÁrÌÕÁrÍÕÃrõÓÃrøÓÁréÓÃrìÓÁrÕÓÃrØÓÁrÏÓÃrÒÓÁrÈÓÁrÉÓÃrÀÓÁrÁÓÃr ÓÁr¡ÓÃrÓÁrÓÃrôÒÁrõÒÃrâÒÁrãÒÃrÎÒÁrÏÒÃrÄÒÁrÅÒÃrÀÒÁrÁÒÃr¤ÒÁr¥ÒÃrÒÁrÒÃrÒÁrÒÃrøÑÁrùÑÃröÑÁr÷ÑÃr§ÁÑýwÄÑûw¼Ñûw½Ñýw³Ñýw¶Ñûw¾Ñûw¿Ñýw±Ñýw´ÑûwÒýwÒûw®Ñûw¯Ñýw«Ñýw®ÑûwèÑûwéÑýwÑýwÑûwÑûwÑýwÑûwÑýwÑûwÑýw·ÒýwºÒûwýÐýwÑûwóÐýwöÐûwéÒýwìÒûwßÑýwâÑûwºÒûw»ÒýwãÐýwæÐûw×ÐýwÚÐûwÃÐýwÆÐûw½ÐýwÀÐûw¶Ðûw·Ðýw®Ðûw¯ÐýwÐûwÐýwúÏûwûÏýwâÏûwãÏýwÐÏûwÑÏýw¼Ïûw½Ïýw²Ïûw³Ïýw®Ïûw¯ÏýwÏûwÏýwüÎûwýÎýwðÎûwñÎýwæÎûwçÎýwäÎûwåÎýw§¯Î·}²Îµ}ªÎµ}«Î·}¡Î·}¤Îµ}¬Îµ}­Î·}Î·}¢Îµ}ñÎ·}ôÎµ}Îµ}Î·}Î·}Îµ}ÖÎµ}×Î·}Î·}Îµ}Îµ}Î·}Îµ}Î·}Îµ}Î·}¥Ï·}¨Ïµ}ëÍ·}îÍµ}áÍ·}äÍµ}×Ï·}ÚÏµ}ÍÎ·}ÐÎµ}¨Ïµ}©Ï·}ÑÍ·}ÔÍµ}ÅÍ·}ÈÍµ}±Í·}´Íµ}«Í·}®Íµ}¤Íµ}¥Í·}Íµ}Í·}üÌµ}ýÌ·}èÌµ}éÌ·}ÐÌµ}ÑÌ·}¾Ìµ}¿Ì·}ªÌµ}«Ì·} Ìµ}¡Ì·}Ìµ}Ì·}Ìµ}Ì·}êËµ}ëË·}ÞËµ}ßË·}ÔËµ}ÕË·}ÒËµ}ÓË·}§Ëñ ËïËïËñËñËïËïËñËñËïßËñâËïËïËñËñËïÄËïÅËñ÷ÊñúÊïôÊïõÊñòÊïóÊñðÊïñÊñÌñÌïÙÊñÜÊïÏÊñÒÊïÅÌñÈÌï»Ëñ¾ËïÌïÌñ¿ÊñÂÊï³Êñ¶ÊïÊñ¢ÊïÊñÊïÊïÊñÊïÊñêÉïëÉñÖÉï×Éñ¾Éï¿Éñ¬Éï­ÉñÉïÉñÉïÉñÉïÉñîÈïïÈñØÈïÙÈñÌÈïÍÈñÂÈïÃÈñÀÈïÁÈñ§È«È©È©È«ýÇ«È©È©È«ûÇ«þÇ©ÍÈ«ÐÈ©øÇ©ùÇ«õÇ«øÇ©²È©³È«åÇ«èÇ©âÇ©ãÇ«àÇ©áÇ«ÞÇ©ßÇ«É«É©ÇÇ«ÊÇ©½Ç«ÀÇ©³É«¶É©©È«¬È©É©É«­Ç«°Ç©¡Ç«¤Ç©Ç«Ç©Ç«Ç©Ç©Ç«øÆ©ùÆ«ØÆ©ÙÆ«ÄÆ©ÅÆ«¬Æ©­Æ«Æ©Æ«Æ©Æ«üÅ©ýÅ«øÅ©ùÅ«ÜÅ©ÝÅ«ÆÅ©ÇÅ«ºÅ©»Å«°Å©±Å«®Å©¯Å«§ùÄåüÄãôÄãõÄåëÄåîÄãöÄã÷ÄåéÄåìÄã»Åå¾ÅãæÄãçÄåãÄåæÄã Åã¡ÅåÓÄåÖÄãÐÄãÑÄåÎÄãÏÄåÌÄãÍÄåïÅåòÅãµÄå¸Äã«Äå®Äã¡Æå¤ÆãÅåÅãòÅãóÅåÄåÄãÄåÄãûÃåþÃãõÃåøÃãîÃãïÃåæÃãçÃåÆÃãÇÃå²Ãã³ÃåÃãÃåÃãÃåôÂãõÂåêÂãëÂåæÂãçÂåÊÂãËÂå´ÂãµÂå¨Âã©ÂåÂãÂåÂãÂå§çÁêÁâÁãÁÙÁÜÁäÁåÁ×ÁÚÁ©Â¬ÂÔÁÕÁÑÁÔÁÂÂÁÁÄÁ¾Á¿Á¼Á½ÁºÁ»ÁÝÂàÂ£Á¦ÁÁÁÃÃÂÂàÂáÂÁÁýÀÁéÀìÀãÀæÀÜÀÝÀÔÀÕÀ´ÀµÀ À¡ÀÀÀö¿÷¿â¿ã¿Ø¿Ù¿Ô¿Õ¿¸¿¹¿¢¿£¿¿¿¿¿¿¿§¹Ì»¼Ì¹´Ì¹µÌ»«Ì»®Ì¹¶Ì¹·Ì»©Ì»¬Ì¹ûÌ»þÌ¹¦Ì¹§Ì»£Ì»¦Ì¹àÌ¹áÌ»Ì»Ì¹Ì¹Ì»Ì¹Ì»Ì¹Ì»¯Í»²Í¹õË»øË¹ëË»îË¹áÍ»äÍ¹×Ì»ÚÌ¹²Í¹³Í»ÛË»ÞË¹ÏË»ÒË¹»Ë»¾Ë¹µË»¸Ë¹®Ë¹¯Ë»¦Ë¹§Ë»Ë¹Ë»òÊ¹óÊ»ÚÊ¹ÛÊ»ÈÊ¹ÉÊ»´Ê¹µÊ»ªÊ¹«Ê»¦Ê¹§Ê»Ê¹Ê»ôÉ¹õÉ»èÉ¹éÉ»ÞÉ¹ßÉ»ÜÉ¹ÝÉ»§§Éõ
+ªÉó
+¢Éó
+£Éõ
+Éõ
+Éó
+¤Éó
+¥Éõ
+Éõ
+Éó
+éÉõ
+ìÉó
+Éó
+Éõ
+Éõ
+Éó
+ÎÉó
+ÏÉõ
+Éõ
+Éó
+þÈó
+ÿÈõ
+üÈó
+ýÈõ
+úÈó
+ûÈõ
+Êõ
+ Êó
+ãÈõ
+æÈó
+ÙÈõ
+ÜÈó
+ÏÊõ
+ÒÊó
+ÅÉõ
+ÈÉó
+ Êó
+¡Êõ
+ÉÈõ
+ÌÈó
+½Èõ
+ÀÈó
+©Èõ
+¬Èó
+£Èõ
+¦Èó
+Èó
+Èõ
+Èó
+Èõ
+ôÇó
+õÇõ
+àÇó
+áÇõ
+ÈÇó
+ÉÇõ
+¶Çó
+·Çõ
+¢Çó
+£Çõ
+Çó
+Çõ
+Çó
+Çõ
+øÆó
+ùÆõ
+âÆó
+ãÆõ
+ÖÆó
+×Æõ
+ÌÆó
+ÍÆõ
+ÊÆó
+ËÆõ
+§Æ¯Æ­Æ­Æ¯Æ¯Æ­Æ­Æ¯Æ¯Æ­×Æ¯ÚÆ­Æ­Æ¯ÿÅ¯Æ­¼Æ­½Æ¯ïÅ¯òÅ­ìÅ­íÅ¯êÅ­ëÅ¯èÅ­éÅ¯Ç¯Ç­ÑÅ¯ÔÅ­ÇÅ¯ÊÅ­½Ç¯ÀÇ­³Æ¯¶Æ­Ç­Ç¯·Å¯ºÅ­«Å¯®Å­Å¯Å­Å¯Å­Å­Å¯Å­Å¯âÄ­ãÄ¯ÎÄ­ÏÄ¯¶Ä­·Ä¯¤Ä­¥Ä¯Ä­Ä¯Ä­Ä¯Ä­Ä¯æÃ­çÃ¯ÐÃ­ÑÃ¯ÄÃ­ÅÃ¯ºÃ­»Ã¯¸Ã­¹Ã¯§ÃéÃçþÂçÿÂéõÂéøÂçÃçÃéóÂéöÂçÅÃéÈÃçðÂçñÂéíÂéðÂçªÃç«ÃéÝÂéàÂçÚÂçÛÂéØÂçÙÂéÖÂç×ÂéùÃéüÃç¿ÂéÂÂçµÂé¸Âç«Äé®Äç¡Ãé¤ÃçüÃçýÃé¥Âé¨ÂçÂéÂçÂéÂçÿÁéÂçøÁçùÁéðÁçñÁéÐÁçÑÁé¼Áç½Áé¤Áç¥ÁéÁçÁéþÀçÿÀéôÀçõÀéðÀçñÀéÔÀçÕÀé¾Àç¿Àé²Àç³Àé¨Àç©Àé¦Àç§Àé§ñ¿£ô¿¡ì¿¡í¿£ã¿£æ¿¡î¿¡ï¿£á¿£ä¿¡³À£¶À¡Þ¿¡ß¿£Û¿£Þ¿¡À¡À£Ë¿£Î¿¡È¿¡É¿£Æ¿¡Ç¿£Ä¿¡Å¿£çÀ£êÀ¡­¿£°¿¡£¿£¦¿¡Á£Á¡À£À¡êÀ¡ëÀ£¿£¿¡¿£¿¡ó¾£ö¾¡í¾£ð¾¡æ¾¡ç¾£Þ¾¡ß¾£¾¾¡¿¾£ª¾¡«¾£¾¡¾£¾¡¾£ì½¡í½£â½¡ã½£Þ½¡ß½£Â½¡Ã½£¬½¡­½£ ½¡¡½£½¡½£½¡½£§ß¼Ý â¼Û Ú¼Û Û¼Ý Ñ¼Ý Ô¼Û Ü¼Û Ý¼Ý Ï¼Ý Ò¼Û ¡½Ý ¤½Û Ì¼Û Í¼Ý É¼Ý Ì¼Û ½Û ½Ý ¹¼Ý ¼¼Û ¶¼Û ·¼Ý ´¼Û µ¼Ý ²¼Û ³¼Ý Õ½Ý Ø½Û ¼Ý ¼Û ¼Ý ¼Û ¾Ý ¾Û ý¼Ý ½Û Ø½Û Ù½Ý ¼Ý ¼Û õ»Ý ø»Û á»Ý ä»Û Û»Ý Þ»Û Ô»Û Õ»Ý Ì»Û Í»Ý ¬»Û ­»Ý »Û »Ý »Û »Ý îºÛ ïºÝ ÚºÛ ÛºÝ ÐºÛ ÑºÝ ÌºÛ ÍºÝ °ºÛ ±ºÝ ºÛ ºÝ ºÛ ºÝ ºÛ ºÝ ºÛ ºÝ §Í¹&Ð¹&È¹&É¹&¿¹&Â¹&Ê¹&Ë¹&½¹&À¹&º&º&º¹&»¹&·¹&º¹&ô¹&õ¹&§¹&ª¹&¤¹&¥¹&¢¹&£¹& ¹&¡¹&Ãº&Æº&¹&¹&ÿ¸&¹&õº&øº&ë¹&î¹&Æº&Çº&ï¸&ò¸&ã¸&æ¸&Ï¸&Ò¸&É¸&Ì¸&Â¸&Ã¸&º¸&»¸&¸&¸&¸&¸&î·&ï·&Ü·&Ý·&È·&É·&¾·&¿·&º·&»·&·&·&·&·&ü¶&ý¶&ò¶&ó¶&ð¶&ñ¶&§»¶Ñ+¾¶Ï+¶¶Ï+·¶Ñ+­¶Ñ+°¶Ï+¸¶Ï+¹¶Ñ+«¶Ñ+®¶Ï+ý¶Ñ+·Ï+¨¶Ï+©¶Ñ+¥¶Ñ+¨¶Ï+â¶Ï+ã¶Ñ+¶Ñ+¶Ï+¶Ï+¶Ñ+¶Ï+¶Ñ+¶Ï+¶Ñ+±·Ñ+´·Ï+÷µÑ+úµÏ+íµÑ+ðµÏ+ã·Ñ+æ·Ï+Ù¶Ñ+Ü¶Ï+´·Ï+µ·Ñ+ÝµÑ+àµÏ+ÑµÑ+ÔµÏ+½µÑ+ÀµÏ+·µÑ+ºµÏ+°µÏ+±µÑ+¨µÏ+©µÑ+µÏ+µÑ+ô´Ï+õ´Ñ+Ü´Ï+Ý´Ñ+Ê´Ï+Ë´Ñ+¶´Ï+·´Ñ+¬´Ï+­´Ñ+¨´Ï+©´Ñ+´Ï+´Ñ+ö³Ï+÷³Ñ+ê³Ï+ë³Ñ+à³Ï+á³Ñ+Þ³Ï+ß³Ñ+§©³1¬³1¤³1¥³1³1³1¦³1§³1³1³1ë³1î³1³1³1³1³1Ð³1Ñ³1³1³1³1³1þ²1ÿ²1ü²1ý²1´1¢´1å²1è²1Û²1Þ²1Ñ´1Ô´1Ç³1Ê³1¢´1£´1Ë²1Î²1¿²1Â²1«²1®²1¥²1¨²1²1²1²1²1ö±1÷±1â±1ã±1Ê±1Ë±1¸±1¹±1¤±1¥±1±1±1±1±1ú°1û°1ä°1å°1Ø°1Ù°1Î°1Ï°1Ì°1Í°1§°Å6°Ã6°Ã6°Å6°Å6°Ã6°Ã6°Å6°Å6°Ã6Ù°Å6Ü°Ã6°Ã6°Å6°Å6°Ã6¾°Ã6¿°Å6ñ¯Å6ô¯Ã6î¯Ã6ï¯Å6ì¯Ã6í¯Å6ê¯Ã6ë¯Å6±Å6±Ã6Ó¯Å6Ö¯Ã6É¯Å6Ì¯Ã6¿±Å6Â±Ã6µ°Å6¸°Ã6±Ã6±Å6¹¯Å6¼¯Ã6­¯Å6°¯Ã6¯Å6¯Ã6¯Å6¯Ã6¯Ã6¯Å6¯Ã6¯Å6ä®Ã6å®Å6Ð®Ã6Ñ®Å6¸®Ã6¹®Å6¦®Ã6§®Å6®Ã6®Å6®Ã6®Å6®Ã6®Å6è­Ã6é­Å6Ò­Ã6Ó­Å6Æ­Ã6Ç­Å6¼­Ã6½­Å6º­Ã6»­Å6§­ÿ;­ý;­ý;­ÿ;÷¬ÿ;ú¬ý;­ý;­ÿ;õ¬ÿ;ø¬ý;Ç­ÿ;Ê­ý;ò¬ý;ó¬ÿ;ï¬ÿ;ò¬ý;¬­ý;­­ÿ;ß¬ÿ;â¬ý;Ü¬ý;Ý¬ÿ;Ú¬ý;Û¬ÿ;Ø¬ý;Ù¬ÿ;û­ÿ;þ­ý;Á¬ÿ;Ä¬ý;·¬ÿ;º¬ý;­®ÿ;°®ý;£­ÿ;¦­ý;þ­ý;ÿ­ÿ;§¬ÿ;ª¬ý;¬ÿ;¬ý;¬ÿ;¬ý;¬ÿ;¬ý;ú«ý;û«ÿ;ò«ý;ó«ÿ;Ò«ý;Ó«ÿ;¾«ý;¿«ÿ;¦«ý;§«ÿ;«ý;«ÿ;«ý;«ÿ;öªý;÷ªÿ;òªý;óªÿ;Öªý;×ªÿ;Àªý;Áªÿ;´ªý;µªÿ;ªªý;«ªÿ;¨ªý;©ªÿ;§ó©¹Aö©·Aî©·Aï©¹Aå©¹Aè©·Að©·Añ©¹Aã©¹Aæ©·Aµª¹A¸ª·Aà©·Aá©¹AÝ©¹Aà©·Aª·Aª¹AÍ©¹AÐ©·AÊ©·AË©¹AÈ©·AÉ©¹AÆ©·AÇ©¹Aéª¹Aìª·A¯©¹A²©·A¥©¹A¨©·A«¹A«·Aª¹Aª·Aìª·Aíª¹A©¹A©·A©¹A©·Aõ¨¹Aø¨·Aï¨¹Aò¨·Aè¨·Aé¨¹Aà¨·Aá¨¹AÀ¨·AÁ¨¹A¬¨·A­¨¹A¨·A¨¹A¨·A¨¹Aî§·Aï§¹Aä§·Aå§¹Aà§·Aá§¹AÄ§·AÅ§¹A®§·A¯§¹A¢§·A£§¹A§·A§¹A§·A§¹A§á¦óFä¦ñFÜ¦ñFÝ¦óFÓ¦óFÖ¦ñFÞ¦ñFß¦óFÑ¦óFÔ¦ñF£§óF¦§ñFÎ¦ñFÏ¦óFË¦óFÎ¦ñF§ñF§óF»¦óF¾¦ñF¸¦ñF¹¦óF¶¦ñF·¦óF´¦ñFµ¦óF×§óFÚ§ñF¦óF ¦ñF¦óF¦ñF¨óF¨ñFÿ¦óF§ñFÚ§ñFÛ§óF¦óF¦ñF÷¥óFú¥ñFã¥óFæ¥ñFÝ¥óFà¥ñFÖ¥ñF×¥óFÎ¥ñFÏ¥óF®¥ñF¯¥óF¥ñF¥óF¥ñF¥óFð¤ñFñ¤óFÜ¤ñFÝ¤óFÒ¤ñFÓ¤óFÎ¤ñFÏ¤óF²¤ñF³¤óF¤ñF¤óF¤ñF¤óF¤ñF¤óF¤ñF¤óF§Ï£­LÒ£«LÊ£«LË£­LÁ£­LÄ£«LÌ£«LÍ£­L¿£­LÂ£«L¤­L¤«L¼£«L½£­L¹£­L¼£«Lö£«L÷£­L©£­L¬£«L¦£«L§£­L¤£«L¥£­L¢£«L££­LÅ¤­LÈ¤«L£­L£«L£­L£«L÷¤­Lú¤«Lí£­Lð£«LÈ¤«LÉ¤­Lñ¢­Lô¢«Lå¢­Lè¢«LÑ¢­LÔ¢«LË¢­LÎ¢«LÄ¢«LÅ¢­L¼¢«L½¢­L¢«L¢­L¢«L¢­Lð¡«Lñ¡­LÞ¡«Lß¡­LÊ¡«LË¡­LÀ¡«LÁ¡­L¼¡«L½¡­L ¡«L¡¡­L¡«L¡­Lþ «Lÿ ­Lô «Lõ ­Lò «Ló ­L§½ çQÀ åQ¸ åQ¹ çQ¯ çQ² åQº åQ» çQ­ çQ° åQÿ çQ¡åQª åQ« çQ§ çQª åQä åQå çQ çQ åQ åQ çQ åQ çQ åQ çQ³¡çQ¶¡åQùçQüåQïçQòåQå¡çQè¡åQÛ çQÞ åQ¶¡åQ·¡çQßçQâåQÓçQÖåQ¿çQÂåQ¹çQ¼åQ²åQ³çQªåQ«çQåQçQöåQ÷çQÞåQßçQÌåQÍçQ¸åQ¹çQ®åQ¯çQªåQ«çQåQçQøåQùçQìåQíçQâåQãçQàåQáçQ§«¡W®W¦W§¡W¡W W¨W©¡W¡WWí¡WðWW¡W¡WWÒWÓ¡W¡WWW¡WW¡WþWÿ¡W¡¡W¤Wç¡WêWÝ¡WàWÓ¡WÖWÉ¡WÌW¤W¥¡WÍ¡WÐWÁ¡WÄW­¡W°W§¡WªW W¡¡WW¡WøWù¡WäWå¡WÌWÍ¡WºW»¡W¦W§¡WW¡WW¡WüWý¡WæWç¡WÚWÛ¡WÐWÑ¡WÎWÏ¡W§Û\Ù\Ù\Û\Û\Ù\Ù\Û\Û\Ù\ÛÛ\ÞÙ\Ù\Û\Û\Ù\ÀÙ\ÁÛ\óÛ\öÙ\ðÙ\ñÛ\îÙ\ïÛ\ìÙ\íÛ\Û\Ù\ÕÛ\ØÙ\ËÛ\ÎÙ\ÁÛ\ÄÙ\·Û\ºÙ\Ù\Û\»Û\¾Ù\¯Û\²Ù\Û\Ù\Û\Ù\Ù\Û\Ù\Û\æÙ\çÛ\ÒÙ\ÓÛ\ºÙ\»Û\¨Ù\©Û\Ù\Û\Ù\Û\Ù\Û\êÙ\ëÛ\ÔÙ\ÕÛ\ÈÙ\ÉÛ\¾Ù\¿Û\¼Ù\½Û\§bbbbùbübbb÷búbÉbÌbôbõbñbôb®b¯bábäbÞbßbÜbÝbÚbÛbýbbÃbÆb¹b¼b¯b²b¥b¨bbb©b¬bb bbbbbübýbôbõbÔbÕbÀbÁb¨b©bbbbbøbùbôbõbØbÙbÂbÃb¶b·b¬b­bªb«b§õÏgøÍgðÍgñÏgçÏgêÍgòÍgóÏgåÏgèÍg·ÏgºÍgâÍgãÏgßÏgâÍgÍgÏgÏÏgÒÍgÌÍgÍÏgÊÍgËÏgÈÍgÉÏgëÏgîÍg±Ïg´Íg§ÏgªÍgÏg ÍgÏgÍgîÍgïÏgÏgÍgÏgÍg÷ÏgúÍgñÏgôÍgêÍgëÏgâÍgãÏgÂÍgÃÏg®Íg¯ÏgÍgÏgÍgÏgðÍgñÏgæÍgçÏgâÍgãÏgÆÍgÇÏg°Íg±Ïg¤Íg¥ÏgÍgÏgÍgÏg§ãmæmÞmßmÕmØmàmámÓmÖm¥m¨mÐmÑmÍmÐmmm½mÀmºm»m¸m¹m¶m·mÙmÜmm¢mmmmmmmÜmÝmmmùmümåmèmßmâmØmÙmÐmÑm°m±mmmmmòmómÞmßmÔmÕmÐmÑm´mµmmmmmmmmm§ÑÃrÔÁrÌÁrÍÃrÃÃrÆÁrÎÁrÏÃrÁÃrÄÁrÃrÁr¾Ár¿Ãr»Ãr¾ÁrøÁrùÃr«Ãr®Ár¨Ár©Ãr¦Ár§Ãr¤Ár¥ÃrÇÃrÊÁrÃrÁrÃrÁrùÃrüÁrïÃròÁrÊÁrËÃróÃröÁrçÃrêÁrÓÃrÖÁrÍÃrÐÁrÆÁrÇÃr¾Ár¿ÃrÁrÃrÁrÃròÁróÃràÁráÃrÌÁrÍÃrÂÁrÃÃr¾Ár¿Ãr¢Ár£ÃrÁrÃrÁrÃröÁr÷ÃrôÁrõÃr§¿ýwÂûwºûw»ýw±ýw´ûw¼ûw½ýw¯ýw²ûwýwûw¬ûw­ýw©ýw¬ûwæûwçýwýwûwûwýwûwýwûwýwµýw¸ûwûýwþûwñýwôûwçýwêûwÝýwàûw¸ûw¹ýwáýwäûwÕýwØûwÁýwÄûw»ýw¾ûw´ûwµýw¬ûw­ýwûwýwøûwùýwàûwáýwÎûwÏýwºûw»ýw°ûw±ýw¬ûw­ýwûwýwúûwûýwîûwïýwäûwåýwâûwãýw§­·}°µ}¨µ}©·}·}¢µ}ªµ}«·}·} µ}ï·}òµ}µ}·}·}µ}Ôµ}Õ·}·}µ}µ}·}µ}·}µ}·}£·}¦µ}é·}ìµ}ß·}âµ}Õ·}Øµ}Ë·}Îµ}¦µ}§·}Ï·}Òµ}Ã·}Æµ}¯·}²µ}©·}¬µ}¢µ}£·}µ}·}úµ}û·}æµ}ç·}Îµ}Ï·}¼µ}½·}¨µ}©·}µ}·}µ}·}þµ}ÿ·}èµ}é·}Üµ}Ý·}Òµ}Ó·}Ðµ}Ñ·}§ñïïññïïññïÝñàïïññïÂïÃñõñøïòïóñðïññîïïññï×ñÚïÍñÐïÃñÆï¹ñ¼ïïñ½ñÀï±ñ´ïñ ïñïïñïñèïéñÔïÕñ¼ï½ñªï«ñïñïñïñìïíñÖï×ñÊïËñÀïÁñ¾ï¿ñ§«©©«û«þ©©«ù«ü©Ë«Î©ö©÷«ó«ö©°©±«ã«æ©à©á«Þ©ß«Ü©Ý«ÿ«©Å«È©»«¾©±«´©§«ª©©«««®©«¢©«©«©þÿ©ÿÿ«öÿ©÷ÿ«Öÿ©×ÿ«Âÿ©Ãÿ«ªÿ©«ÿ«ÿ©ÿ«ÿ©ÿ«úþ©ûþ«öþ©÷þ«Úþ©Ûþ«Äþ©Åþ«¸þ©¹þ«®þ©¯þ«¬þ©­þ«§÷ýåúýãòýãóýåéýåìýãôýãõýåçýåêýã¹þå¼þãäýãåýåáýåäýãþãþåÑýåÔýãÎýãÏýåÌýãÍýåÊýãËýåíþåðþã³ýå¶ýã©ýå¬ýãÿå¢ÿãþåþãðþãñþåýåýãýåýãùüåüüãóüåöüãìüãíüåäüãåüåÄüãÅüå°üã±üåüãüåüãüåòûãóûåèûãéûåäûãåûåÈûãÉûå²ûã³ûå¦ûã§ûåûãûåûãûå§»¹¹»»¹¹»ÿ»¹Ñ»Ô¹ü¹ý»ù»ü¹¶¹·»é»ì¹æ¹ç»ä¹å»â¹ã»»¹Ë»Î¹Á»Ä¹·»º¹­»°¹¹»±»´¹¥»¨¹»¹»¹¹»ü¹ý»Ü¹Ý»È¹É»°¹±»¹»¹»¹»ü¹ý»à¹á»Ê¹Ë»¾¹¿»´¹µ»²¹³»§ýÿõ
+ó
+øÿó
+ùÿõ
+ïÿõ
+òÿó
+úÿó
+ûÿõ
+íÿõ
+ðÿó
+¿õ
+Âó
+êÿó
+ëÿõ
+çÿõ
+êÿó
+¤ó
+¥õ
+×ÿõ
+Úÿó
+Ôÿó
+Õÿõ
+Òÿó
+Óÿõ
+Ðÿó
+Ñÿõ
+óõ
+öó
+¹ÿõ
+¼ÿó
+¯ÿõ
+²ÿó
+¥õ
+¨ó
+õ
+ó
+öó
+÷õ
+ÿõ
+¢ÿó
+ÿõ
+ÿó
+ÿþõ
+ÿó
+ùþõ
+üþó
+òþó
+óþõ
+êþó
+ëþõ
+Êþó
+Ëþõ
+¶þó
+·þõ
+þó
+þõ
+þó
+þõ
+øýó
+ùýõ
+îýó
+ïýõ
+êýó
+ëýõ
+Îýó
+Ïýõ
+¸ýó
+¹ýõ
+¬ýó
+­ýõ
+¢ýó
+£ýõ
+ ýó
+¡ýõ
+§ëü¯îü­æü­çü¯Ýü¯àü­èü­éü¯Ûü¯Þü­­ý¯°ý­Øü­Ùü¯Õü¯Øü­ý­ý¯Åü¯Èü­Âü­Ãü¯Àü­Áü¯¾ü­¿ü¯áý¯äý­§ü¯ªü­ü¯ ü­þ¯þ­ý¯ý­äý­åý¯ü¯ü­ü¯ü­íû¯ðû­çû¯êû­àû­áû¯Øû­Ùû¯¸û­¹û¯¤û­¥û¯û­û¯úú­ûú¯æú­çú¯Üú­Ýú¯Øú­Ùú¯¼ú­½ú¯¦ú­§ú¯ú­ú¯ú­ú¯ú­ú¯§ÙùéÜùçÔùçÕùéËùéÎùçÖùç×ùéÉùéÌùçúéúçÆùçÇùéÃùéÆùçúçúé³ùé¶ùç°ùç±ùé®ùç¯ùé¬ùç­ùéÏúéÒúçùéùçùéùçûéûç÷ùéúùçÒúçÓúéûøéþøçïøéòøçÛøéÞøçÕøéØøçÎøçÏøéÆøçÇøé¦øç§øéøçøéú÷çû÷éè÷çé÷éÔ÷çÕ÷éÊ÷çË÷éÆ÷çÇ÷éª÷ç«÷é÷ç÷é÷ç÷éþöçÿöéüöçýöé§Çö£Êö¡Âö¡Ãö£¹ö£¼ö¡Äö¡Åö£·ö£ºö¡÷£÷¡´ö¡µö£±ö£´ö¡îö¡ïö£¡ö£¤ö¡ö¡ö£ö¡ö£ö¡ö£½÷£À÷¡ö£ö¡ùõ£üõ¡ï÷£ò÷¡åö£èö¡À÷¡Á÷£éõ£ìõ¡Ýõ£àõ¡Éõ£Ìõ¡Ãõ£Æõ¡¼õ¡½õ£´õ¡µõ£õ¡õ£õ¡õ£èô¡éô£Öô¡×ô£Âô¡Ãô£¸ô¡¹ô£´ô¡µô£ô¡ô£ô¡ô£öó¡÷ó£ìó¡íó£êó¡ëó£§µóÝ ¸óÛ °óÛ ±óÝ §óÝ ªóÛ ²óÛ ³óÝ ¥óÝ ¨óÛ ÷óÝ úóÛ ¢óÛ £óÝ óÝ ¢óÛ ÜóÛ ÝóÝ óÝ óÛ óÛ óÝ óÛ óÝ óÛ óÝ «ôÝ ®ôÛ ñòÝ ôòÛ çòÝ êòÛ ÝôÝ àôÛ ÓóÝ ÖóÛ ®ôÛ ¯ôÝ ×òÝ ÚòÛ ËòÝ ÎòÛ ·òÝ ºòÛ ±òÝ ´òÛ ªòÛ «òÝ ¢òÛ £òÝ òÛ òÝ îñÛ ïñÝ ÖñÛ ×ñÝ ÄñÛ ÅñÝ °ñÛ ±ñÝ ¦ñÛ §ñÝ ¢ñÛ £ñÝ ñÛ ñÝ ððÛ ñðÝ äðÛ åðÝ ÚðÛ ÛðÝ ØðÛ ÙðÝ §£ð&¦ð&ð&ð&ð&ð& ð&¡ð&ð&ð&åð&èð&ð&ð&ð&ð&Êð&Ëð&ýï&ð&úï&ûï&øï&ùï&öï&÷ï&ñ&ñ&ßï&âï&Õï&Øï&Ëñ&Îñ&Áð&Äð&ñ&ñ&Åï&Èï&¹ï&¼ï&¥ï&¨ï&ï&¢ï&ï&ï&ï&ï&ðî&ñî&Üî&Ýî&Äî&Åî&²î&³î&î&î&î&î&î&î&ôí&õí&Þí&ßí&Òí&Óí&Èí&Éí&Æí&Çí&§íÑ+íÏ+íÏ+íÑ+íÑ+íÏ+íÏ+íÑ+íÑ+íÏ+ÓíÑ+ÖíÏ+þìÏ+ÿìÑ+ûìÑ+þìÏ+¸íÏ+¹íÑ+ëìÑ+îìÏ+èìÏ+éìÑ+æìÏ+çìÑ+äìÏ+åìÑ+îÑ+îÏ+ÍìÑ+ÐìÏ+ÃìÑ+ÆìÏ+¹îÑ+¼îÏ+¯íÑ+²íÏ+îÏ+îÑ+³ìÑ+¶ìÏ+§ìÑ+ªìÏ+ìÑ+ìÏ+ìÑ+ìÏ+ìÏ+ìÑ+þëÏ+ÿëÑ+ÞëÏ+ßëÑ+ÊëÏ+ËëÑ+²ëÏ+³ëÑ+ ëÏ+¡ëÑ+ëÏ+ëÑ+ëÏ+ëÑ+þêÏ+ÿêÑ+âêÏ+ãêÑ+ÌêÏ+ÍêÑ+ÀêÏ+ÁêÑ+¶êÏ+·êÑ+´êÏ+µêÑ+§ÿé1ê1úé1ûé1ñé1ôé1üé1ýé1ïé1òé1Áê1Äê1ìé1íé1éé1ìé1¦ê1§ê1Ùé1Üé1Öé1×é1Ôé1Õé1Òé1Óé1õê1øê1»é1¾é1±é1´é1§ë1ªë1ê1 ê1øê1ùê1¡é1¤é1é1é1é1é1ûè1þè1ôè1õè1ìè1íè1Ìè1Íè1¸è1¹è1 è1¡è1è1è1úç1ûç1ðç1ñç1ìç1íç1Ðç1Ñç1ºç1»ç1®ç1¯ç1¤ç1¥ç1¢ç1£ç1§íæÅ6ðæÃ6èæÃ6éæÅ6ßæÅ6âæÃ6êæÃ6ëæÅ6ÝæÅ6àæÃ6¯çÅ6²çÃ6ÚæÃ6ÛæÅ6×æÅ6ÚæÃ6çÃ6çÅ6ÇæÅ6ÊæÃ6ÄæÃ6ÅæÅ6ÂæÃ6ÃæÅ6ÀæÃ6ÁæÅ6ãçÅ6æçÃ6©æÅ6¬æÃ6æÅ6¢æÃ6èÅ6èÃ6çÅ6çÃ6æçÃ6ççÅ6æÅ6æÃ6æÅ6æÃ6ïåÅ6òåÃ6éåÅ6ìåÃ6âåÃ6ãåÅ6ÚåÃ6ÛåÅ6ºåÃ6»åÅ6¦åÃ6§åÅ6åÃ6åÅ6üäÃ6ýäÅ6èäÃ6éäÅ6ÞäÃ6ßäÅ6ÚäÃ6ÛäÅ6¾äÃ6¿äÅ6¨äÃ6©äÅ6äÃ6äÅ6äÃ6äÅ6äÃ6äÅ6§Ûãÿ;Þãý;Öãý;×ãÿ;Íãÿ;Ðãý;Øãý;Ùãÿ;Ëãÿ;Îãý;äÿ; äý;Èãý;Éãÿ;Åãÿ;Èãý;äý;äÿ;µãÿ;¸ãý;²ãý;³ãÿ;°ãý;±ãÿ;®ãý;¯ãÿ;Ñäÿ;Ôäý;ãÿ;ãý;ãÿ;ãý;åÿ;åý;ùãÿ;üãý;Ôäý;Õäÿ;ýâÿ;ãý;ñâÿ;ôâý;Ýâÿ;àâý;×âÿ;Úâý;Ðâý;Ñâÿ;Èâý;Éâÿ;¨âý;©âÿ;âý;âÿ;üáý;ýáÿ;êáý;ëáÿ;Öáý;×áÿ;Ìáý;Íáÿ;Èáý;Éáÿ;¬áý;­áÿ;áý;áÿ;áý;áÿ;áý;áÿ;þàý;ÿàÿ;§Éà¹AÌà·AÄà·AÅà¹A»à¹A¾à·AÆà·AÇà¹A¹à¹A¼à·Aá¹Aá·A¶à·A·à¹A³à¹A¶à·Aðà·Añà¹A£à¹A¦à·A à·A¡à¹Aà·Aà¹Aà·Aà¹A¿á¹AÂá·Aà¹Aà·Aûß¹Aþß·Añá¹Aôá·Açà¹Aêà·AÂá·AÃá¹Aëß¹Aîß·Aßß¹Aâß·AËß¹AÎß·AÅß¹AÈß·A¾ß·A¿ß¹A¶ß·A·ß¹Aß·Aß¹Aß·Aß¹AêÞ·AëÞ¹AØÞ·AÙÞ¹AÄÞ·AÅÞ¹AºÞ·A»Þ¹A¶Þ·A·Þ¹AÞ·AÞ¹AÞ·AÞ¹AøÝ·AùÝ¹AîÝ·AïÝ¹AìÝ·AíÝ¹A§·ÝóFºÝñF²ÝñF³ÝóF©ÝóF¬ÝñF´ÝñFµÝóF§ÝóFªÝñFùÝóFüÝñF¤ÝñF¥ÝóF¡ÝóF¤ÝñFÞÝñFßÝóFÝóFÝñFÝñFÝóFÝñFÝóFÝñFÝóF­ÞóF°ÞñFóÜóFöÜñFéÜóFìÜñFßÞóFâÞñFÕÝóFØÝñF°ÞñF±ÞóFÙÜóFÜÜñFÍÜóFÐÜñF¹ÜóF¼ÜñF³ÜóF¶ÜñF¬ÜñF­ÜóF¤ÜñF¥ÜóFÜñFÜóFðÛñFñÛóFØÛñFÙÛóFÆÛñFÇÛóF²ÛñF³ÛóF¨ÛñF©ÛóF¤ÛñF¥ÛóFÛñFÛóFòÚñFóÚóFæÚñFçÚóFÜÚñFÝÚóFÚÚñFÛÚóF§¥Ú­L¨Ú«L Ú«L¡Ú­LÚ­LÚ«L¢Ú«L£Ú­LÚ­LÚ«LçÚ­LêÚ«LÚ«LÚ­LÚ­LÚ«LÌÚ«LÍÚ­LÿÙ­LÚ«LüÙ«LýÙ­LúÙ«LûÙ­LøÙ«LùÙ­LÛ­LÛ«LáÙ­LäÙ«L×Ù­LÚÙ«LÍÛ­LÐÛ«LÃÚ­LÆÚ«LÛ«LÛ­LÇÙ­LÊÙ«L»Ù­L¾Ù«L§Ù­LªÙ«L¡Ù­L¤Ù«LÙ«LÙ­LÙ«LÙ­LòØ«LóØ­LÞØ«LßØ­LÆØ«LÇØ­L´Ø«LµØ­L Ø«L¡Ø­LØ«LØ­LØ«LØ­Lö×«L÷×­Là×«Lá×­LÔ×«LÕ×­LÊ×«LË×­LÈ×«LÉ×­L§×çQ×åQ×åQ×çQ×çQ×åQ×åQ×çQ×çQ×åQÕ×çQØ×åQ×åQ×çQýÖçQ×åQº×åQ»×çQíÖçQðÖåQêÖåQëÖçQèÖåQéÖçQæÖåQçÖçQØçQØåQÏÖçQÒÖåQÅÖçQÈÖåQ»ØçQ¾ØåQ±×çQ´×åQØåQØçQµÖçQ¸ÖåQ©ÖçQ¬ÖåQÖçQÖåQÖçQÖåQÖåQÖçQÖåQÖçQàÕåQáÕçQÌÕåQÍÕçQ´ÕåQµÕçQ¢ÕåQ£ÕçQÕåQÕçQÕåQÕçQÕåQÕçQäÔåQåÔçQÎÔåQÏÔçQÂÔåQÃÔçQ¸ÔåQ¹ÔçQ¶ÔåQ·ÔçQ§Ô¡WÔWüÓWýÓ¡WóÓ¡WöÓWþÓWÿÓ¡WñÓ¡WôÓWÃÔ¡WÆÔWîÓWïÓ¡WëÓ¡WîÓW¨ÔW©Ô¡WÛÓ¡WÞÓWØÓWÙÓ¡WÖÓW×Ó¡WÔÓWÕÓ¡W÷Ô¡WúÔW½Ó¡WÀÓW³Ó¡W¶ÓW©Õ¡W¬ÕWÔ¡W¢ÔWúÔWûÔ¡W£Ó¡W¦ÓWÓ¡WÓWÓ¡WÓWýÒ¡WÓWöÒW÷Ò¡WîÒWïÒ¡WÎÒWÏÒ¡WºÒW»Ò¡W¢ÒW£Ò¡WÒWÒ¡WüÑWýÑ¡WòÑWóÑ¡WîÑWïÑ¡WÒÑWÓÑ¡W¼ÑW½Ñ¡W°ÑW±Ñ¡W¦ÑW§Ñ¡W¤ÑW¥Ñ¡W§ïÐÛ\òÐÙ\êÐÙ\ëÐÛ\áÐÛ\äÐÙ\ìÐÙ\íÐÛ\ßÐÛ\âÐÙ\±ÑÛ\´ÑÙ\ÜÐÙ\ÝÐÛ\ÙÐÛ\ÜÐÙ\ÑÙ\ÑÛ\ÉÐÛ\ÌÐÙ\ÆÐÙ\ÇÐÛ\ÄÐÙ\ÅÐÛ\ÂÐÙ\ÃÐÛ\åÑÛ\èÑÙ\«ÐÛ\®ÐÙ\¡ÐÛ\¤ÐÙ\ÒÛ\ÒÙ\ÑÛ\ÑÙ\èÑÙ\éÑÛ\ÐÛ\ÐÙ\ÐÛ\ÐÙ\ñÏÛ\ôÏÙ\ëÏÛ\îÏÙ\äÏÙ\åÏÛ\ÜÏÙ\ÝÏÛ\¼ÏÙ\½ÏÛ\¨ÏÙ\©ÏÛ\ÏÙ\ÏÛ\þÎÙ\ÿÎÛ\êÎÙ\ëÎÛ\àÎÙ\áÎÛ\ÜÎÙ\ÝÎÛ\ÀÎÙ\ÁÎÛ\ªÎÙ\«ÎÛ\ÎÙ\ÎÛ\ÎÙ\ÎÛ\ÎÙ\ÎÛ\§ÝÍbàÍbØÍbÙÍbÏÍbÒÍbÚÍbÛÍbÍÍbÐÍbÎb¢ÎbÊÍbËÍbÇÍbÊÍbÎbÎb·ÍbºÍb´ÍbµÍb²Íb³Íb°Íb±ÍbÓÎbÖÎbÍbÍbÍbÍbÏbÏbûÍbþÍbÖÎb×ÎbÿÌbÍbóÌböÌbßÌbâÌbÙÌbÜÌbÒÌbÓÌbÊÌbËÌbªÌb«ÌbÌbÌbþËbÿËbìËbíËbØËbÙËbÎËbÏËbÊËbËËb®Ëb¯ËbËbËbËbËbËbËbËbËb§ËÊÏgÎÊÍgÆÊÍgÇÊÏg½ÊÏgÀÊÍgÈÊÍgÉÊÏg»ÊÏg¾ÊÍgËÏgËÍg¸ÊÍg¹ÊÏgµÊÏg¸ÊÍgòÊÍgóÊÏg¥ÊÏg¨ÊÍg¢ÊÍg£ÊÏg ÊÍg¡ÊÏgÊÍgÊÏgÁËÏgÄËÍgÊÏgÊÍgýÉÏgÊÍgóËÏgöËÍgéÊÏgìÊÍgÄËÍgÅËÏgíÉÏgðÉÍgáÉÏgäÉÍgÍÉÏgÐÉÍgÇÉÏgÊÉÍgÀÉÍgÁÉÏg¸ÉÍg¹ÉÏgÉÍgÉÏgÉÍgÉÏgìÈÍgíÈÏgÚÈÍgÛÈÏgÆÈÍgÇÈÏg¼ÈÍg½ÈÏg¸ÈÍg¹ÈÏgÈÍgÈÏgÈÍgÈÏgúÇÍgûÇÏgðÇÍgñÇÏgîÇÍgïÇÏg§¹Çm¼Çm´ÇmµÇm«Çm®Çm¶Çm·Çm©Çm¬ÇmûÇmþÇm¦Çm§Çm£Çm¦ÇmàÇmáÇmÇmÇmÇmÇmÇmÇmÇmÇm¯Èm²ÈmõÆmøÆmëÆmîÆmáÈmäÈm×ÇmÚÇm²Èm³ÈmÛÆmÞÆmÏÆmÒÆm»Æm¾ÆmµÆm¸Æm®Æm¯Æm¦Æm§ÆmÆmÆmòÅmóÅmÚÅmÛÅmÈÅmÉÅm´ÅmµÅmªÅm«Åm¦Åm§ÅmÅmÅmôÄmõÄmèÄméÄmÞÄmßÄmÜÄmÝÄm§§ÄÃrªÄÁr¢ÄÁr£ÄÃrÄÃrÄÁr¤ÄÁr¥ÄÃrÄÃrÄÁréÄÃrìÄÁrÄÁrÄÃrÄÃrÄÁrÎÄÁrÏÄÃrÄÃrÄÁrþÃÁrÿÃÃrüÃÁrýÃÃrúÃÁrûÃÃrÅÃr ÅÁrãÃÃræÃÁrÙÃÃrÜÃÁrÏÅÃrÒÅÁrÅÄÃrÈÄÁr ÅÁr¡ÅÃrÉÃÃrÌÃÁr½ÃÃrÀÃÁr©ÃÃr¬ÃÁr£ÃÃr¦ÃÁrÃÁrÃÃrÃÁrÃÃrôÂÁrõÂÃràÂÁráÂÃrÈÂÁrÉÂÃr¶ÂÁr·ÂÃr¢ÂÁr£ÂÃrÂÁrÂÃrÂÁrÂÃrøÁÁrùÁÃrâÁÁrãÁÃrÖÁÁr×ÁÃrÌÁÁrÍÁÃrÊÁÁrËÁÃr§ÁýwÁûwÁûwÁýwÁýwÁûwÁûwÁýwÁýwÁûw×ÁýwÚÁûwÁûwÁýwÿÀýwÁûw¼Áûw½ÁýwïÀýwòÀûwìÀûwíÀýwêÀûwëÀýwèÀûwéÀýwÂýwÂûwÑÀýwÔÀûwÇÀýwÊÀûw½ÂýwÀÂûw³Áýw¶ÁûwÂûwÂýw·ÀýwºÀûw«Àýw®ÀûwÀýwÀûwÀýwÀûwÀûwÀýwÀûwÀýwâ¿ûwã¿ýwÎ¿ûwÏ¿ýw¶¿ûw·¿ýw¤¿ûw¥¿ýw¿ûw¿ýw¿ûw¿ýw¿ûw¿ýwæ¾ûwç¾ýwÐ¾ûwÑ¾ýwÄ¾ûwÅ¾ýwº¾ûw»¾ýw¸¾ûw¹¾ýw§¾·}¾µ}þ½µ}ÿ½·}õ½·}ø½µ}¾µ}¾·}ó½·}ö½µ}Å¾·}È¾µ}ð½µ}ñ½·}í½·}ð½µ}ª¾µ}«¾·}Ý½·}à½µ}Ú½µ}Û½·}Ø½µ}Ù½·}Ö½µ}×½·}ù¾·}ü¾µ}¿½·}Â½µ}µ½·}¸½µ}«¿·}®¿µ}¡¾·}¤¾µ}ü¾µ}ý¾·}¥½·}¨½µ}½·}½µ}½·}½µ}ÿ¼·}½µ}ø¼µ}ù¼·}ð¼µ}ñ¼·}Ð¼µ}Ñ¼·}¼¼µ}½¼·}¤¼µ}¥¼·}¼µ}¼·}þ»µ}ÿ»·}ô»µ}õ»·}ð»µ}ñ»·}Ô»µ}Õ»·}¾»µ}¿»·}²»µ}³»·}¨»µ}©»·}¦»µ}§»·}§ñºñôºïìºïíºñãºñæºïîºïïºñáºñäºï³»ñ¶»ïÞºïßºñÛºñÞºï»ï»ñËºñÎºïÈºïÉºñÆºïÇºñÄºïÅºñç»ñê»ï­ºñ°ºï£ºñ¦ºï¼ñ¼ï»ñ»ïê»ïë»ñºñºïºñºïó¹ñö¹ïí¹ñð¹ïæ¹ïç¹ñÞ¹ïß¹ñ¾¹ï¿¹ñª¹ï«¹ñ¹ï¹ñ¹ï¹ñì¸ïí¸ñâ¸ïã¸ñÞ¸ïß¸ñÂ¸ïÃ¸ñ¬¸ï­¸ñ ¸ï¡¸ñ¸ï¸ñ¸ï¸ñ§ß·«â·©Ú·©Û·«Ñ·«Ô·©Ü·©Ý·«Ï·«Ò·©¡¸«¤¸©Ì·©Í·«É·«Ì·©¸©¸«¹·«¼·©¶·©··«´·©µ·«²·©³·«Õ¸«Ø¸©·«·©·«·©¹«¹©ý·«¸©Ø¸©Ù¸«·«·©õ¶«ø¶©á¶«ä¶©Û¶«Þ¶©Ô¶©Õ¶«Ì¶©Í¶«¬¶©­¶«¶©¶«¶©¶«îµ©ïµ«Úµ©Ûµ«Ðµ©Ñµ«Ìµ©Íµ«°µ©±µ«µ©µ«µ©µ«µ©µ«µ©µ«§½·»À·¹¸·¹¹·»¯·»²·¹º·¹»·»­·»°·¹ÿ·»¸¹ª·¹«·»§·»ª·¹ä·¹å·»·»·¹·¹·»·¹·»·¹·»³¸»¶¸¹ù¶»ü¶¹ï¶»ò¶¹å¸»è¸¹Û·»Þ·¹¶¸¹·¸»ß¶»â¶¹Ó¶»Ö¶¹¿¶»Â¶¹¹¶»¼¶¹²¶¹³¶»ª¶¹«¶»¶¹¶»öµ¹÷µ»Þµ¹ßµ»Ìµ¹Íµ»¸µ¹¹µ»®µ¹¯µ»ªµ¹«µ»µ¹µ»ø´¹ù´»ì´¹í´»â´¹ã´»à´¹á´»§«´õ
+®´ó
+¦´ó
+§´õ
+´õ
+ ´ó
+¨´ó
+©´õ
+´õ
+´ó
+í´õ
+ð´ó
+´ó
+´õ
+´õ
+´ó
+Ò´ó
+Ó´õ
+´õ
+´ó
+´ó
+´õ
+´ó
+´õ
+þ³ó
+ÿ³õ
+¡µõ
+¤µó
+ç³õ
+ê³ó
+Ý³õ
+à³ó
+Óµõ
+Öµó
+É´õ
+Ì´ó
+¤µó
+¥µõ
+Í³õ
+Ð³ó
+Á³õ
+Ä³ó
+­³õ
+°³ó
+§³õ
+ª³ó
+ ³ó
+¡³õ
+³ó
+³õ
+ø²ó
+ù²õ
+ä²ó
+å²õ
+Ì²ó
+Í²õ
+º²ó
+»²õ
+¦²ó
+§²õ
+²ó
+²õ
+²ó
+²õ
+ü±ó
+ý±õ
+æ±ó
+ç±õ
+Ú±ó
+Û±õ
+Ð±ó
+Ñ±õ
+Î±ó
+Ï±õ
+§±¯±­±­±¯±¯±­±­±¯±¯±­Û±¯Þ±­±­±¯±¯±­À±­Á±¯ó°¯ö°­ð°­ñ°¯î°­ï°¯ì°­í°¯²¯²­Õ°¯Ø°­Ë°¯Î°­Á²¯Ä²­·±¯º±­²­²¯»°¯¾°­¯°¯²°­°¯°­°¯°­°­°¯°­°¯æ¯­ç¯¯Ò¯­Ó¯¯º¯­»¯¯¨¯­©¯¯¯­¯¯¯­¯¯¯­¯¯ê®­ë®¯Ô®­Õ®¯È®­É®¯¾®­¿®¯¼®­½®¯§®é®ç®ç®éù­éü­ç®ç®é÷­éú­çÉ®éÌ®çô­çõ­éñ­éô­ç®®ç¯®éá­éä­çÞ­çß­éÜ­çÝ­éÚ­çÛ­éý®é¯çÃ­éÆ­ç¹­é¼­ç¯¯é²¯ç¥®é¨®ç¯ç¯é©­é¬­ç­é ­ç­é­ç­é­çü¬çý¬éô¬çõ¬éÔ¬çÕ¬éÀ¬çÁ¬é¨¬ç©¬é¬ç¬é¬ç¬éø«çù«éô«çõ«éØ«çÙ«éÂ«çÃ«é¶«ç·«é¬«ç­«éª«ç««é§õª£øª¡ðª¡ñª£çª£êª¡òª¡óª£åª£èª¡·«£º«¡âª¡ãª£ßª£âª¡«¡«£Ïª£Òª¡Ìª¡Íª£Êª¡Ëª£Èª¡Éª£ë«£î«¡±ª£´ª¡§ª£ªª¡¬£ ¬¡«£«¡î«¡ï«£ª£ª¡ª£ª¡÷©£ú©¡ñ©£ô©¡ê©¡ë©£â©¡ã©£Â©¡Ã©£®©¡¯©£©¡©£©¡©£ð¨¡ñ¨£æ¨¡ç¨£â¨¡ã¨£Æ¨¡Ç¨£°¨¡±¨£¤¨¡¥¨£¨¡¨£¨¡¨£§ã§Ý æ§Û Þ§Û ß§Ý Õ§Ý Ø§Û à§Û á§Ý Ó§Ý Ö§Û ¥¨Ý ¨¨Û Ð§Û Ñ§Ý Í§Ý Ð§Û ¨Û ¨Ý ½§Ý À§Û º§Û »§Ý ¸§Û ¹§Ý ¶§Û ·§Ý Ù¨Ý Ü¨Û §Ý ¢§Û §Ý §Û ©Ý ©Û ¨Ý ¨Û Ü¨Û Ý¨Ý §Ý §Û ù¦Ý ü¦Û å¦Ý è¦Û ß¦Ý â¦Û Ø¦Û Ù¦Ý Ð¦Û Ñ¦Ý °¦Û ±¦Ý ¦Û ¦Ý ¦Û ¦Ý ò¥Û ó¥Ý Þ¥Û ß¥Ý Ô¥Û Õ¥Ý Ð¥Û Ñ¥Ý ´¥Û µ¥Ý ¥Û ¥Ý ¥Û ¥Ý ¥Û ¥Ý ¥Û ¥Ý §Ñ¤&Ô¤&Ì¤&Í¤&Ã¤&Æ¤&Î¤&Ï¤&Á¤&Ä¤&¥&¥&¾¤&¿¤&»¤&¾¤&ø¤&ù¤&«¤&®¤&¨¤&©¤&¦¤&§¤&¤¤&¥¤&Ç¥&Ê¥&¤&¤&¤&¤&ù¥&ü¥&ï¤&ò¤&Ê¥&Ë¥&ó£&ö£&ç£&ê£&Ó£&Ö£&Í£&Ð£&Æ£&Ç£&¾£&¿£&£&£&£&£&ò¢&ó¢&à¢&á¢&Ì¢&Í¢&Â¢&Ã¢&¾¢&¿¢&¢¢&£¢&¢&¢&¢&¢&ö¡&÷¡&ô¡&õ¡&§¿¡Ñ+Â¡Ï+º¡Ï+»¡Ñ+±¡Ñ+´¡Ï+¼¡Ï+½¡Ñ+¯¡Ñ+²¡Ï+¢Ñ+¢Ï+¬¡Ï+­¡Ñ+©¡Ñ+¬¡Ï+æ¡Ï+ç¡Ñ+¡Ñ+¡Ï+¡Ï+¡Ñ+¡Ï+¡Ñ+¡Ï+¡Ñ+µ¢Ñ+¸¢Ï+û Ñ+þ Ï+ñ Ñ+ô Ï+ç¢Ñ+ê¢Ï+Ý¡Ñ+à¡Ï+¸¢Ï+¹¢Ñ+á Ñ+ä Ï+Õ Ñ+Ø Ï+Á Ñ+Ä Ï+» Ñ+¾ Ï+´ Ï+µ Ñ+¬ Ï+­ Ñ+ Ï+ Ñ+øÏ+ùÑ+àÏ+áÑ+ÎÏ+ÏÑ+ºÏ+»Ñ+°Ï+±Ñ+¬Ï+­Ñ+Ï+Ñ+úÏ+ûÑ+îÏ+ïÑ+äÏ+åÑ+âÏ+ãÑ+§­1°1¨1©11¢1ª1«11 1ï1ò11111Ô1Õ111111111£1¦1é1ì1ß1â1Õ1Ø1Ë1Î1¦1§1Ï1Ò1Ã1Æ1¯1²1©1¬1¢1£111ú1û1æ1ç1Î1Ï1¼1½1¨1©11111þ1ÿ1è1é1Ü1Ý1Ò1Ó1Ð1Ñ1§Å6Ã6Ã6Å6Å6Ã6Ã6Å6Å6Ã6ÝÅ6àÃ6Ã6Å6Å6Ã6ÂÃ6ÃÅ6õÅ6øÃ6òÃ6óÅ6ðÃ6ñÅ6îÃ6ïÅ6Å6Ã6×Å6ÚÃ6ÍÅ6ÐÃ6ÃÅ6ÆÃ6¹Å6¼Ã6Ã6Å6½Å6ÀÃ6±Å6´Ã6Å6 Ã6Å6Ã6Ã6Å6Ã6Å6èÃ6éÅ6ÔÃ6ÕÅ6¼Ã6½Å6ªÃ6«Å6Ã6Å6Ã6Å6Ã6Å6ìÃ6íÅ6ÖÃ6×Å6ÊÃ6ËÅ6ÀÃ6ÁÅ6¾Ã6¿Å6§ÿ;ý;ý;ÿ;ûÿ;þý;ý;ÿ;ùÿ;üý;Ëÿ;Îý;öý;÷ÿ;óÿ;öý;°ý;±ÿ;ãÿ;æý;àý;áÿ;Þý;ßÿ;Üý;Ýÿ;ÿÿ;ý;Åÿ;Èý;»ÿ;¾ý;±ÿ;´ý;§ÿ;ªý;ý;ÿ;«ÿ;®ý;ÿ;¢ý;ÿ;ý;ÿ;ý;þý;ÿÿ;öý;÷ÿ;Öý;×ÿ;Âý;Ãÿ;ªý;«ÿ;ý;ÿ;ý;ÿ;úý;ûÿ;öý;÷ÿ;Úý;Ûÿ;Äý;Åÿ;¸ý;¹ÿ;®ý;¯ÿ;¬ý;­ÿ;§÷¹Aú·Aò·Aó¹Aé¹Aì·Aô·Aõ¹Aç¹Aê·A¹¹A¼·Aä·Aå¹Aá¹Aä·A·A¹AÑ¹AÔ·AÎ·AÏ¹AÌ·AÍ¹AÊ·AË¹Aí¹Að·A³¹A¶·A©¹A¬·A¹A¢·A¹A·Að·Añ¹A¹A·A¹A·Aù¹Aü·Aó¹Aö·Aì·Aí¹Aä·Aå¹AÄ·AÅ¹A°·A±¹A·A¹A·A¹Aò·Aó¹Aè·Aé¹Aä·Aå¹AÈ·AÉ¹A²·A³¹A¦·A§¹A·A¹A·A¹A§åóFèñFàñFáóF×óFÚñFâñFãóFÕóFØñF§óFªñFÒñFÓóFÏóFÒñFñFóF¿óFÂñF¼ñF½óFºñF»óF¸ñF¹óFÛóFÞñF¡óF¤ñFóFñFóFñFóFñFÞñFßóFóFñFûóFþñFçóFêñFáóFäñFÚñFÛóFÒñFÓóF²ñF³óFñFóFñFóFôñFõóFàñFáóFÖñF×óFÒñFÓóF¶ñF·óF ñF¡óFñFóFñFóFñFóF§Ó­LÖ«LÎ«LÏ­LÅ­LÈ«LÐ«LÑ­LÃ­LÆ«L­L«LÀ«LÁ­L½­LÀ«Lú«Lû­L­­L°«Lª«L«­L¨«L©­L¦«L§­LÉ­LÌ«L­L«L­L«Lû­Lþ«Lñ­Lô«LÌ«LÍ­Lõ­Lø«Lé­Lì«LÕ­LØ«LÏ­LÒ«LÈ«LÉ­LÀ«LÁ­L «L¡­L«L­Lô«Lõ­Lâ«Lã­LÎ«LÏ­LÄ«LÅ­LÀ«LÁ­L¤«L¥­L«L­L«L­Lø«Lù­Lö«L÷­L§ÁçQÄåQ¼åQ½çQ³çQ¶åQ¾åQ¿çQ±çQ´åQçQåQ®åQ¯çQ«çQ®åQèåQéçQçQåQåQçQåQçQåQçQ·çQºåQýçQåQóçQöåQéçQìåQßçQâåQºåQ»çQãçQæåQ×çQÚåQÃçQÆåQ½çQÀåQ¶åQ·çQ®åQ¯çQåQçQúåQûçQâåQãçQÐåQÑçQ¼åQ½çQ²åQ³çQ®åQ¯çQåQçQüåQýçQðåQñçQæåQççQäåQåçQ§¯¡W²WªW«¡W¡¡W¤W¬W­¡W¡W¢Wñ¡WôWW¡W¡WWÖW×¡W¡WWW¡WW¡WW¡W¥¡W¨Wë¡WîWá¡WäW×¡WÚWÍ¡WÐW¨W©¡WÑ¡WÔWÅ¡WÈW±¡W´W«¡W®W¤W¥¡WW¡WüWý¡WèWé¡WÐWÑ¡W¾W¿¡WªW«¡W W¡¡WW¡WW¡WêWë¡WÞWß¡WÔWÕ¡WÒWÓ¡W§Û\ Ù\Ù\Û\Û\Ù\Ù\Û\Û\Ù\ßÛ\âÙ\Ù\Û\Û\Ù\ÄÙ\ÅÛ\÷Û\úÙ\ôÙ\õÛ\òÙ\óÛ\ðÙ\ñÛ\Û\Ù\ÙÛ\ÜÙ\ÏÛ\ÒÙ\ÅÛ\ÈÙ\»Û\¾Ù\Ù\Û\¿Û\ÂÙ\³Û\¶Ù\Û\¢Ù\Û\Ù\Ù\Û\Ù\Û\êÙ\ëÛ\ÖÙ\×Û\¾Ù\¿Û\¬Ù\­Û\Ù\Û\Ù\Û\Ù\Û\îÙ\ïÛ\ØÙ\ÙÛ\ÌÙ\ÍÛ\ÂÙ\ÃÛ\ÀÙ\ÁÛ\§bbbbýbbbbûbþbÍbÐbøbùbõbøb²b³båbèbâbãbàbábÞbßbbbÇbÊb½bÀb³b¶b©b¬bbb­b°b¡b¤bbbbbbbøbùbØbÙbÄbÅb¬b­bbbbbüÿbýÿbøÿbùÿbÜÿbÝÿbÆÿbÇÿbºÿb»ÿb°ÿb±ÿb®ÿb¯ÿb§ùþÏgüþÍgôþÍgõþÏgëþÏgîþÍgöþÍg÷þÏgéþÏgìþÍg»ÿÏg¾ÿÍgæþÍgçþÏgãþÏgæþÍg ÿÍg¡ÿÏgÓþÏgÖþÍgÐþÍgÑþÏgÎþÍgÏþÏgÌþÍgÍþÏgïÿÏgòÿÍgµþÏg¸þÍg«þÏg®þÍg¡Ïg¤ÍgÿÏgÿÍgòÿÍgóÿÏgþÏgþÍgþÏgþÍgûýÏgþýÍgõýÏgøýÍgîýÍgïýÏgæýÍgçýÏgÆýÍgÇýÏg²ýÍg³ýÏgýÍgýÏgýÍgýÏgôüÍgõüÏgêüÍgëüÏgæüÍgçüÏgÊüÍgËüÏg´üÍgµüÏg¨üÍg©üÏgüÍgüÏgüÍgüÏg§çûmêûmâûmãûmÙûmÜûmäûmåûm×ûmÚûm©üm¬ümÔûmÕûmÑûmÔûmümümÁûmÄûm¾ûm¿ûm¼ûm½ûmºûm»ûmÝümàüm£ûm¦ûmûmûmýmýmümümàümáümûmûmýúmûméúmìúmãúmæúmÜúmÝúmÔúmÕúm´úmµúm úm¡úmúmúmöùm÷ùmâùmãùmØùmÙùmÔùmÕùm¸ùm¹ùm¢ùm£ùmùmùmùmùmùmùm§ÕøÃrØøÁrÐøÁrÑøÃrÇøÃrÊøÁrÒøÁrÓøÃrÅøÃrÈøÁrùÃrùÁrÂøÁrÃøÃr¿øÃrÂøÁrüøÁrýøÃr¯øÃr²øÁr¬øÁr­øÃrªøÁr«øÃr¨øÁr©øÃrËùÃrÎùÁrøÃrøÁrøÃrøÁrýùÃrúÁróøÃröøÁrÎùÁrÏùÃr÷÷Ãrú÷Árë÷Ãrî÷Ár×÷ÃrÚ÷ÁrÑ÷ÃrÔ÷ÁrÊ÷ÁrË÷ÃrÂ÷ÁrÃ÷Ãr¢÷Ár£÷Ãr÷Ár÷ÃrööÁr÷öÃräöÁråöÃrÐöÁrÑöÃrÆöÁrÇöÃrÂöÁrÃöÃr¦öÁr§öÃröÁröÃröÁröÃrúõÁrûõÃrøõÁrùõÃr§ÃõýwÆõûw¾õûw¿õýwµõýw¸õûwÀõûwÁõýw³õýw¶õûwöýwöûw°õûw±õýw­õýw°õûwêõûwëõýwõýw õûwõûwõýwõûwõýwõûwõýw¹öýw¼öûwÿôýwõûwõôýwøôûwëöýwîöûwáõýwäõûw¼öûw½öýwåôýwèôûwÙôýwÜôûwÅôýwÈôûw¿ôýwÂôûw¸ôûw¹ôýw°ôûw±ôýwôûwôýwüóûwýóýwäóûwåóýwÒóûwÓóýw¾óûw¿óýw´óûwµóýw°óûw±óýwóûwóýwþòûwÿòýwòòûwóòýwèòûwéòýwæòûwçòýw§±ò·}´òµ}¬òµ}­ò·}£ò·}¦òµ}®òµ}¯ò·}¡ò·}¤òµ}óò·}öòµ}òµ}ò·}ò·}òµ}Øòµ}Ùò·}ò·}òµ}òµ}ò·}òµ}ò·}òµ}ò·}§ó·}ªóµ}íñ·}ðñµ}ãñ·}æñµ}Ùó·}Üóµ}Ïò·}Òòµ}ªóµ}«ó·}Óñ·}Öñµ}Çñ·}Êñµ}³ñ·}¶ñµ}­ñ·}°ñµ}¦ñµ}§ñ·}ñµ}ñ·}þðµ}ÿð·}êðµ}ëð·}Òðµ}Óð·}Àðµ}Áð·}¬ðµ}­ð·}¢ðµ}£ð·}ðµ}ð·}ðµ}ð·}ìïµ}íï·}àïµ}áï·}Öïµ}×ï·}Ôïµ}Õï·}§ïñ¢ïïïïïñïñïïïïïñïñïïáïñäïïïïïñïñïïÆïïÇïñùîñüîïöîï÷îñôîïõîñòîïóîñðñðïÛîñÞîïÑîñÔîïÇðñÊðï½ïñÀïïðïðñÁîñÄîïµîñ¸îï¡îñ¤îïîñîïîïîñîïîñìíïííñØíïÙíñÀíïÁíñ®íï¯íñíïíñíïíñíïíñðìïñìñÚìïÛìñÎìïÏìñÄìïÅìñÂìïÃìñ§Ãé»Æé¹¾é¹¿é»µé»¸é¹Àé¹Áé»³é»¶é¹ê»ê¹°é¹±é»­é»°é¹êé¹ëé»é» é¹é¹é»é¹é»é¹é»¹ê»¼ê¹ÿè»é¹õè»øè¹ëê»îê¹áé»äé¹¼ê¹½ê»åè»èè¹Ùè»Üè¹Åè»Èè¹¿è»Âè¹¸è¹¹è»°è¹±è»è¹è»üç¹ýç»äç¹åç»Òç¹Óç»¾ç¹¿ç»´ç¹µç»°ç¹±ç»ç¹ç»þæ¹ÿæ»òæ¹óæ»èæ¹éæ»ææ¹çæ»§±æõ
+´æó
+¬æó
+­æõ
+£æõ
+¦æó
+®æó
+¯æõ
+¡æõ
+¤æó
+óæõ
+öæó
+æó
+æõ
+æõ
+æó
+Øæó
+Ùæõ
+æõ
+æó
+æó
+æõ
+æó
+æõ
+æó
+æõ
+§çõ
+ªçó
+íåõ
+ðåó
+ãåõ
+æåó
+Ùçõ
+Üçó
+Ïæõ
+Òæó
+ªçó
+«çõ
+Óåõ
+Öåó
+Çåõ
+Êåó
+³åõ
+¶åó
+­åõ
+°åó
+¦åó
+§åõ
+åó
+åõ
+þäó
+ÿäõ
+êäó
+ëäõ
+Òäó
+Óäõ
+Àäó
+Áäõ
+¬äó
+­äõ
+¢äó
+£äõ
+äó
+äõ
+äó
+äõ
+ìãó
+íãõ
+àãó
+áãõ
+Öãó
+×ãõ
+Ôãó
+Õãõ
+§ã¯¢ã­ã­ã¯ã¯ã­ã­ã¯ã¯ã­áã¯äã­ã­ã¯ã¯ã­Æã­Çã¯ùâ¯üâ­öâ­÷â¯ôâ­õâ¯òâ­óâ¯ä¯ä­Ûâ¯Þâ­Ñâ¯Ôâ­Çä¯Êä­½ã¯Àã­ä­ä¯Áâ¯Äâ­µâ¯¸â­¡â¯¤â­â¯â­â­â¯â­â¯ìá­íá¯Øá­Ùá¯Àá­Áá¯®á­¯á¯á­á¯á­á¯á­á¯ðà­ñà¯Úà­Ûà¯Îà­Ïà¯Äà­Åà¯Âà­Ãà¯§àéàçàçàéÿßéàçàçàéýßéàçÏàéÒàçúßçûßé÷ßéúßç´àçµàéçßéêßçäßçåßéâßçãßéàßçáßéáéáçÉßéÌßç¿ßéÂßçµáé¸áç«àé®àçáçáé¯ßé²ßç£ßé¦ßçßéßçßéßçßçßéúÞçûÞéÚÞçÛÞéÆÞçÇÞé®Þç¯ÞéÞçÞéÞçÞéþÝçÿÝéúÝçûÝéÞÝçßÝéÈÝçÉÝé¼Ýç½Ýé²Ýç³Ýé°Ýç±Ýé§ûÜ£þÜ¡öÜ¡÷Ü£íÜ£ðÜ¡øÜ¡ùÜ£ëÜ£îÜ¡½Ý£ÀÝ¡èÜ¡éÜ£åÜ£èÜ¡¢Ý¡£Ý£ÕÜ£ØÜ¡ÒÜ¡ÓÜ£ÐÜ¡ÑÜ£ÎÜ¡ÏÜ£ñÝ£ôÝ¡·Ü£ºÜ¡­Ü£°Ü¡£Þ£¦Þ¡Ý£Ý¡ôÝ¡õÝ£Ü£ Ü¡Ü£Ü¡ýÛ£Ü¡÷Û£úÛ¡ðÛ¡ñÛ£èÛ¡éÛ£ÈÛ¡ÉÛ£´Û¡µÛ£Û¡Û£Û¡Û£öÚ¡÷Ú£ìÚ¡íÚ£èÚ¡éÚ£ÌÚ¡ÍÚ£¶Ú¡·Ú£ªÚ¡«Ú£ Ú¡¡Ú£Ú¡Ú£§éÙÝ ìÙÛ äÙÛ åÙÝ ÛÙÝ ÞÙÛ æÙÛ çÙÝ ÙÙÝ ÜÙÛ «ÚÝ ®ÚÛ ÖÙÛ ×ÙÝ ÓÙÝ ÖÙÛ ÚÛ ÚÝ ÃÙÝ ÆÙÛ ÀÙÛ ÁÙÝ ¾ÙÛ ¿ÙÝ ¼ÙÛ ½ÙÝ ßÚÝ âÚÛ ¥ÙÝ ¨ÙÛ ÙÝ ÙÛ ÛÝ ÛÛ ÚÝ ÚÛ âÚÛ ãÚÝ ÙÝ ÙÛ ÿØÝ ÙÛ ëØÝ îØÛ åØÝ èØÛ ÞØÛ ßØÝ ÖØÛ ×ØÝ ¶ØÛ ·ØÝ ¢ØÛ £ØÝ ØÛ ØÝ ø×Û ù×Ý ä×Û å×Ý Ú×Û Û×Ý Ö×Û ××Ý º×Û »×Ý ¤×Û ¥×Ý ×Û ×Ý ×Û ×Ý ×Û ×Ý §×Ö&ÚÖ&ÒÖ&ÓÖ&ÉÖ&ÌÖ&ÔÖ&ÕÖ&ÇÖ&ÊÖ&×&×&ÄÖ&ÅÖ&ÁÖ&ÄÖ&þÖ&ÿÖ&±Ö&´Ö&®Ö&¯Ö&¬Ö&­Ö&ªÖ&«Ö&Í×&Ð×&Ö&Ö&Ö&Ö&ÿ×&Ø&õÖ&øÖ&Ð×&Ñ×&ùÕ&üÕ&íÕ&ðÕ&ÙÕ&ÜÕ&ÓÕ&ÖÕ&ÌÕ&ÍÕ&ÄÕ&ÅÕ&¤Õ&¥Õ&Õ&Õ&øÔ&ùÔ&æÔ&çÔ&ÒÔ&ÓÔ&ÈÔ&ÉÔ&ÄÔ&ÅÔ&¨Ô&©Ô&Ô&Ô&Ô&Ô&üÓ&ýÓ&úÓ&ûÓ&§ÅÓÑ+ÈÓÏ+ÀÓÏ+ÁÓÑ+·ÓÑ+ºÓÏ+ÂÓÏ+ÃÓÑ+µÓÑ+¸ÓÏ+ÔÑ+ÔÏ+²ÓÏ+³ÓÑ+¯ÓÑ+²ÓÏ+ìÓÏ+íÓÑ+ÓÑ+¢ÓÏ+ÓÏ+ÓÑ+ÓÏ+ÓÑ+ÓÏ+ÓÑ+»ÔÑ+¾ÔÏ+ÓÑ+ÓÏ+÷ÒÑ+úÒÏ+íÔÑ+ðÔÏ+ãÓÑ+æÓÏ+¾ÔÏ+¿ÔÑ+çÒÑ+êÒÏ+ÛÒÑ+ÞÒÏ+ÇÒÑ+ÊÒÏ+ÁÒÑ+ÄÒÏ+ºÒÏ+»ÒÑ+²ÒÏ+³ÒÑ+ÒÏ+ÒÑ+þÑÏ+ÿÑÑ+æÑÏ+çÑÑ+ÔÑÏ+ÕÑÑ+ÀÑÏ+ÁÑÑ+¶ÑÏ+·ÑÑ+²ÑÏ+³ÑÑ+ÑÏ+ÑÑ+ÑÏ+ÑÑ+ôÐÏ+õÐÑ+êÐÏ+ëÐÑ+èÐÏ+éÐÑ+§³Ð1¶Ð1®Ð1¯Ð1¥Ð1¨Ð1°Ð1±Ð1£Ð1¦Ð1õÐ1øÐ1 Ð1¡Ð1Ð1 Ð1ÚÐ1ÛÐ1Ð1Ð1Ð1Ð1Ð1Ð1Ð1Ð1©Ñ1¬Ñ1ïÏ1òÏ1åÏ1èÏ1ÛÑ1ÞÑ1ÑÐ1ÔÐ1¬Ñ1­Ñ1ÕÏ1ØÏ1ÉÏ1ÌÏ1µÏ1¸Ï1¯Ï1²Ï1¨Ï1©Ï1 Ï1¡Ï1Ï1Ï1ìÎ1íÎ1ÔÎ1ÕÎ1ÂÎ1ÃÎ1®Î1¯Î1¤Î1¥Î1 Î1¡Î1Î1Î1îÍ1ïÍ1âÍ1ãÍ1ØÍ1ÙÍ1ÖÍ1×Í1§¡ÍÅ6¤ÍÃ6ÍÃ6ÍÅ6ÍÅ6ÍÃ6ÍÃ6ÍÅ6ÍÅ6ÍÃ6ãÍÅ6æÍÃ6ÍÃ6ÍÅ6ÍÅ6ÍÃ6ÈÍÃ6ÉÍÅ6ûÌÅ6þÌÃ6øÌÃ6ùÌÅ6öÌÃ6÷ÌÅ6ôÌÃ6õÌÅ6ÎÅ6ÎÃ6ÝÌÅ6àÌÃ6ÓÌÅ6ÖÌÃ6ÉÎÅ6ÌÎÃ6¿ÍÅ6ÂÍÃ6ÎÃ6ÎÅ6ÃÌÅ6ÆÌÃ6·ÌÅ6ºÌÃ6£ÌÅ6¦ÌÃ6ÌÅ6 ÌÃ6ÌÃ6ÌÅ6ÌÃ6ÌÅ6îËÃ6ïËÅ6ÚËÃ6ÛËÅ6ÂËÃ6ÃËÅ6°ËÃ6±ËÅ6ËÃ6ËÅ6ËÃ6ËÅ6ËÃ6ËÅ6òÊÃ6óÊÅ6ÜÊÃ6ÝÊÅ6ÐÊÃ6ÑÊÅ6ÆÊÃ6ÇÊÅ6ÄÊÃ6ÅÊÅ6§Êÿ;Êý;Êý;Êÿ;Êÿ;Êý;Êý;Êÿ;ÿÉÿ;Êý;ÑÊÿ;ÔÊý;üÉý;ýÉÿ;ùÉÿ;üÉý;¶Êý;·Êÿ;éÉÿ;ìÉý;æÉý;çÉÿ;äÉý;åÉÿ;âÉý;ãÉÿ;Ëÿ;Ëý;ËÉÿ;ÎÉý;ÁÉÿ;ÄÉý;·Ëÿ;ºËý;­Êÿ;°Êý;Ëý;Ëÿ;±Éÿ;´Éý;¥Éÿ;¨Éý;Éÿ;Éý;Éÿ;Éý;Éý;Éÿ;üÈý;ýÈÿ;ÜÈý;ÝÈÿ;ÈÈý;ÉÈÿ;°Èý;±Èÿ;Èý;Èÿ;Èý;Èÿ;Èý;Èÿ;üÇý;ýÇÿ;àÇý;áÇÿ;ÊÇý;ËÇÿ;¾Çý;¿Çÿ;´Çý;µÇÿ;²Çý;³Çÿ;§ýÆ¹AÇ·AøÆ·AùÆ¹AïÆ¹AòÆ·AúÆ·AûÆ¹AíÆ¹AðÆ·A¿Ç¹AÂÇ·AêÆ·AëÆ¹AçÆ¹AêÆ·A¤Ç·A¥Ç¹A×Æ¹AÚÆ·AÔÆ·AÕÆ¹AÒÆ·AÓÆ¹AÐÆ·AÑÆ¹AóÇ¹AöÇ·A¹Æ¹A¼Æ·A¯Æ¹A²Æ·A¥È¹A¨È·AÇ¹AÇ·AöÇ·A÷Ç¹AÆ¹A¢Æ·AÆ¹AÆ·AÿÅ¹AÆ·AùÅ¹AüÅ·AòÅ·AóÅ¹AêÅ·AëÅ¹AÊÅ·AËÅ¹A¶Å·A·Å¹AÅ·AÅ¹AÅ·AÅ¹AøÄ·AùÄ¹AîÄ·AïÄ¹AêÄ·AëÄ¹AÎÄ·AÏÄ¹A¸Ä·A¹Ä¹A¬Ä·A­Ä¹A¢Ä·A£Ä¹A Ä·A¡Ä¹A§ëÃóFîÃñFæÃñFçÃóFÝÃóFàÃñFèÃñFéÃóFÛÃóFÞÃñF­ÄóF°ÄñFØÃñFÙÃóFÕÃóFØÃñFÄñFÄóFÅÃóFÈÃñFÂÃñFÃÃóFÀÃñFÁÃóF¾ÃñF¿ÃóFáÄóFäÄñF§ÃóFªÃñFÃóF ÃñFÅóFÅñFÄóFÄñFäÄñFåÄóFÃóFÃñFÃóFÃñFíÂóFðÂñFçÂóFêÂñFàÂñFáÂóFØÂñFÙÂóF¸ÂñF¹ÂóF¤ÂñF¥ÂóFÂñFÂóFúÁñFûÁóFæÁñFçÁóFÜÁñFÝÁóFØÁñFÙÁóF¼ÁñF½ÁóF¦ÁñF§ÁóFÁñFÁóFÁñFÁóFÁñFÁóF§ÙÀ­LÜÀ«LÔÀ«LÕÀ­LËÀ­LÎÀ«LÖÀ«L×À­LÉÀ­LÌÀ«LÁ­LÁ«LÆÀ«LÇÀ­LÃÀ­LÆÀ«LÁ«LÁ­L³À­L¶À«L°À«L±À­L®À«L¯À­L¬À«L­À­LÏÁ­LÒÁ«LÀ­LÀ«LÀ­LÀ«LÂ­LÂ«L÷À­LúÀ«LÒÁ«LÓÁ­Lû¿­Lþ¿«Lï¿­Lò¿«LÛ¿­LÞ¿«LÕ¿­LØ¿«LÎ¿«LÏ¿­LÆ¿«LÇ¿­L¦¿«L§¿­L¿«L¿­Lú¾«Lû¾­Lè¾«Lé¾­LÔ¾«LÕ¾­LÊ¾«LË¾­LÆ¾«LÇ¾­Lª¾«L«¾­L¾«L¾­L¾«L¾­Lþ½«Lÿ½­Lü½«Lý½­L§Ç½çQÊ½åQÂ½åQÃ½çQ¹½çQ¼½åQÄ½åQÅ½çQ·½çQº½åQ¾çQ¾åQ´½åQµ½çQ±½çQ´½åQî½åQï½çQ¡½çQ¤½åQ½åQ½çQ½åQ½çQ½åQ½çQ½¾çQÀ¾åQ½çQ½åQù¼çQü¼åQï¾çQò¾åQå½çQè½åQÀ¾åQÁ¾çQé¼çQì¼åQÝ¼çQà¼åQÉ¼çQÌ¼åQÃ¼çQÆ¼åQ¼¼åQ½¼çQ´¼åQµ¼çQ¼åQ¼çQ¼åQ¼çQè»åQé»çQÖ»åQ×»çQÂ»åQÃ»çQ¸»åQ¹»çQ´»åQµ»çQ»åQ»çQ»åQ»çQöºåQ÷ºçQìºåQíºçQêºåQëºçQ§µº¡W¸ºW°ºW±º¡W§º¡WªºW²ºW³º¡W¥º¡W¨ºW÷º¡WúºW¢ºW£º¡Wº¡W¢ºWÜºWÝº¡Wº¡WºWºWº¡WºWº¡WºWº¡W«»¡W®»Wñ¹¡Wô¹Wç¹¡Wê¹WÝ»¡Wà»WÓº¡WÖºW®»W¯»¡W×¹¡WÚ¹WË¹¡WÎ¹W·¹¡Wº¹W±¹¡W´¹Wª¹W«¹¡W¢¹W£¹¡W¹W¹¡Wî¸Wï¸¡WÖ¸W×¸¡WÄ¸WÅ¸¡W°¸W±¸¡W¦¸W§¸¡W¢¸W£¸¡W¸W¸¡Wð·Wñ·¡Wä·Wå·¡WÚ·WÛ·¡WØ·WÙ·¡W§£·Û\¦·Ù\·Ù\·Û\·Û\·Ù\ ·Ù\¡·Û\·Û\·Ù\å·Û\è·Ù\·Ù\·Û\·Û\·Ù\Ê·Ù\Ë·Û\ý¶Û\·Ù\ú¶Ù\û¶Û\ø¶Ù\ù¶Û\ö¶Ù\÷¶Û\¸Û\¸Ù\ß¶Û\â¶Ù\Õ¶Û\Ø¶Ù\Ë¸Û\Î¸Ù\Á·Û\Ä·Ù\¸Ù\¸Û\Å¶Û\È¶Ù\¹¶Û\¼¶Ù\¥¶Û\¨¶Ù\¶Û\¢¶Ù\¶Ù\¶Û\¶Ù\¶Û\ðµÙ\ñµÛ\ÜµÙ\ÝµÛ\ÄµÙ\ÅµÛ\²µÙ\³µÛ\µÙ\µÛ\µÙ\µÛ\µÙ\µÛ\ô´Ù\õ´Û\Þ´Ù\ß´Û\Ò´Ù\Ó´Û\È´Ù\É´Û\Æ´Ù\Ç´Û\§´b´b´b´b´b´b´b´b´b´bÓ´bÖ´bþ³bÿ³bû³bþ³b¸´b¹´bë³bî³bè³bé³bæ³bç³bä³bå³bµbµbÍ³bÐ³bÃ³bÆ³b¹µb¼µb¯´b²´bµbµb³³b¶³b§³bª³b³b³b³b³b³b³bþ²bÿ²bÞ²bß²bÊ²bË²b²²b³²b ²b¡²b²b²b²b²bþ±bÿ±bâ±bã±bÌ±bÍ±bÀ±bÁ±b¶±b·±b´±bµ±b§ÿ°Ïg±Ígú°Ígû°Ïgñ°Ïgô°Ígü°Ígý°Ïgï°Ïgò°ÍgÁ±ÏgÄ±Ígì°Ígí°Ïgé°Ïgì°Íg¦±Íg§±ÏgÙ°ÏgÜ°ÍgÖ°Íg×°ÏgÔ°ÍgÕ°ÏgÒ°ÍgÓ°Ïgõ±Ïgø±Íg»°Ïg¾°Íg±°Ïg´°Íg§²Ïgª²Íg±Ïg ±Ígø±Ígù±Ïg¡°Ïg¤°Íg°Ïg°Íg°Ïg°Ígû¯Ïgþ¯Ígô¯Ígõ¯Ïgì¯Ígí¯ÏgÌ¯ÍgÍ¯Ïg¸¯Íg¹¯Ïg ¯Íg¡¯Ïg¯Íg¯Ïgú®Ígû®Ïgð®Ígñ®Ïgì®Ígí®ÏgÐ®ÍgÑ®Ïgº®Íg»®Ïg®®Íg¯®Ïg¤®Íg¥®Ïg¢®Íg£®Ïg§í­mð­mè­mé­mß­mâ­mê­më­mÝ­mà­m¯®m²®mÚ­mÛ­m×­mÚ­m®m®mÇ­mÊ­mÄ­mÅ­mÂ­mÃ­mÀ­mÁ­mã®mæ®m©­m¬­m­m¢­m¯m¯m®m®mæ®mç®m­m­m­m­mï¬mò¬mé¬mì¬mâ¬mã¬mÚ¬mÛ¬mº¬m»¬m¦¬m§¬m¬m¬mü«mý«mè«mé«mÞ«mß«mÚ«mÛ«m¾«m¿«m¨«m©«m«m«m«m«m«m«m§ÛªÃrÞªÁrÖªÁr×ªÃrÍªÃrÐªÁrØªÁrÙªÃrËªÃrÎªÁr«Ãr «ÁrÈªÁrÉªÃrÅªÃrÈªÁr«Ár«ÃrµªÃr¸ªÁr²ªÁr³ªÃr°ªÁr±ªÃr®ªÁr¯ªÃrÑ«ÃrÔ«ÁrªÃrªÁrªÃrªÁr¬Ãr¬ÁrùªÃrüªÁrÔ«ÁrÕ«Ãrý©ÃrªÁrñ©Ãrô©ÁrÝ©Ãrà©Ár×©ÃrÚ©ÁrÐ©ÁrÑ©ÃrÈ©ÁrÉ©Ãr¨©Ár©©Ãr©Ár©Ãrü¨Árý¨Ãrê¨Árë¨ÃrÖ¨Ár×¨ÃrÌ¨ÁrÍ¨ÃrÈ¨ÁrÉ¨Ãr¬¨Ár­¨Ãr¨Ár¨Ãr¨Ár¨Ãr¨Ár¨Ãrþ§Árÿ§Ãr§É§ýwÌ§ûwÄ§ûwÅ§ýw»§ýw¾§ûwÆ§ûwÇ§ýw¹§ýw¼§ûw¨ýw¨ûw¶§ûw·§ýw³§ýw¶§ûwð§ûwñ§ýw£§ýw¦§ûw §ûw¡§ýw§ûw§ýw§ûw§ýw¿¨ýwÂ¨ûw§ýw§ûwû¦ýwþ¦ûwñ¨ýwô¨ûwç§ýwê§ûwÂ¨ûwÃ¨ýwë¦ýwî¦ûwß¦ýwâ¦ûwË¦ýwÎ¦ûwÅ¦ýwÈ¦ûw¾¦ûw¿¦ýw¶¦ûw·¦ýw¦ûw¦ýw¦ûw¦ýwê¥ûwë¥ýwØ¥ûwÙ¥ýwÄ¥ûwÅ¥ýwº¥ûw»¥ýw¶¥ûw·¥ýw¥ûw¥ýw¥ûw¥ýwø¤ûwù¤ýwî¤ûwï¤ýwì¤ûwí¤ýw§·¤·}º¤µ}²¤µ}³¤·}©¤·}¬¤µ}´¤µ}µ¤·}§¤·}ª¤µ}ù¤·}ü¤µ}¤¤µ}¥¤·}¡¤·}¤¤µ}Þ¤µ}ß¤·}¤·}¤µ}¤µ}¤·}¤µ}¤·}¤µ}¤·}­¥·}°¥µ}ó£·}ö£µ}é£·}ì£µ}ß¥·}â¥µ}Õ¤·}Ø¤µ}°¥µ}±¥·}Ù£·}Ü£µ}Í£·}Ð£µ}¹£·}¼£µ}³£·}¶£µ}¬£µ}­£·}¤£µ}¥£·}£µ}£·}ð¢µ}ñ¢·}Ø¢µ}Ù¢·}Æ¢µ}Ç¢·}²¢µ}³¢·}¨¢µ}©¢·}¤¢µ}¥¢·}¢µ}¢·}ò¡µ}ó¡·}æ¡µ}ç¡·}Ü¡µ}Ý¡·}Ú¡µ}Û¡·}§¡»¤¹¹»»¹¹»»¹ã»æ¹¹»»¹È¹É»û»þ¹ø¹ù»ö¹÷»ô¹õ»»¹Ý»à¹Ó»Ö¹É»Ì¹¿»Â¹¹»Ã»Æ¹·»º¹£»¦¹» ¹¹»¹»î¹ï»Ú¹Û»Â¹Ã»°¹±»¹»¹»¹»ò¹ó»Ü¹Ý»Ð¹Ñ»Æ¹Ç»Ä¹Å»§õ
+ó
+ó
+õ
+õ
+ó
+ó
+õ
+ÿõ
+ó
+Ñõ
+Ôó
+üó
+ýõ
+ùõ
+üó
+¶ó
+·õ
+éõ
+ìó
+æó
+çõ
+äó
+åõ
+âó
+ãõ
+õ
+ó
+Ëõ
+Îó
+Áõ
+Äó
+·õ
+ºó
+­õ
+°ó
+ó
+õ
+±õ
+´ó
+¥õ
+¨ó
+õ
+ó
+õ
+ó
+ó
+õ
+üó
+ýõ
+Üó
+Ýõ
+Èó
+Éõ
+°ó
+±õ
+ó
+õ
+ó
+õ
+ó
+õ
+üó
+ýõ
+àó
+áõ
+Êó
+Ëõ
+¾ó
+¿õ
+´ó
+µõ
+²ó
+³õ
+§ý¯­ø­ù¯ï¯ò­ú­û¯í¯ð­¿¯Â­ê­ë¯ç¯ê­¤­¥¯×¯Ú­Ô­Õ¯Ò­Ó¯Ð­Ñ¯ó¯ö­¹¯¼­¯¯²­¥¯¨­¯­ö­÷¯¯¢­¯­ÿ¯­ù¯ü­ò­ó¯ê­ë¯Ê­Ë¯¶­·¯­¯­¯ø­ù¯î­ï¯ê­ë¯Î­Ï¯¸­¹¯¬­­¯¢­£¯ ­¡¯§ëéîçæççéÝéàçèçééÛéÞç­é°çØçÙéÕéØççéÅéÈçÂçÃéÀçÁé¾ç¿éáéäç§éªçé çéçéçäçåééçéçíéðççéêçàçáéØçÙé¸ç¹é¤ç¥éçéúçûéæççéÜçÝéØçÙé¼ç½é¦ç§éçéçéçé§Ù£Ü¡Ô¡Õ£Ë£Î¡Ö¡×£É£Ì¡£¡Æ¡Ç£Ã£Æ¡¡£³£¶¡°¡±£®¡¯£¬¡­£Ï£Ò¡£¡£¡£¡÷£ú¡Ò¡Ó£û£þ¡ï£ò¡Û£Þ¡Õ£Ø¡Î¡Ï£Æ¡Ç£¦¡§£¡£ú¡û£è¡é£Ô¡Õ£Ê¡Ë£Æ¡Ç£ª¡«£¡£¡£þ¡ÿ£ü¡ý£§ÇÝ ÊÛ ÂÛ ÃÝ ¹Ý ¼Û ÄÛ ÅÝ ·Ý ºÛ Ý Û ´Û µÝ ±Ý ´Û îÛ ïÝ ¡Ý ¤Û Û Ý Û Ý Û Ý ½Ý ÀÛ Ý Û ùÝ üÛ ïÝ òÛ åÝ èÛ ÀÛ ÁÝ éÝ ìÛ ÝÝ àÛ ÉÝ ÌÛ ÃÝ ÆÛ ¼Û ½Ý ´Û µÝ Û Ý Û Ý èÛ éÝ ÖÛ ×Ý ÂÛ ÃÝ ¸Û ¹Ý ´Û µÝ Û Ý Û Ý öÛ ÷Ý ìÛ íÝ êÛ ëÝ §µ&¸&°&±&§&ª&²&³&¥&¨&÷&ú&¢&£&&¢&Ü&Ý&&&&&&&&&«&®&ñ&ô&ç&ê&Ý&à&Ó&Ö&®&¯&×&Ú&Ë&Î&·&º&±&´&ª&«&¢&£&&&î&ï&Ö&×&Ä&Å&°&±&¦&§&¢&£&&&ð&ñ&ä&å&Ú&Û&Ø&Ù&§£Ñ+¦Ï+Ï+Ñ+Ñ+Ï+ Ï+¡Ñ+Ñ+Ï+åÑ+èÏ+Ï+Ñ+Ñ+Ï+ÊÏ+ËÑ+ýÑ+Ï+úÏ+ûÑ+øÏ+ùÑ+öÏ+÷Ñ+Ñ+Ï+ßÑ+âÏ+ÕÑ+ØÏ+ËÑ+ÎÏ+ÁÑ+ÄÏ+Ï+Ñ+ÅÑ+ÈÏ+¹Ñ+¼Ï+¥Ñ+¨Ï+Ñ+¢Ï+Ï+Ñ+Ï+Ñ+ðÏ+ñÑ+ÜÏ+ÝÑ+ÄÏ+ÅÑ+²Ï+³Ñ+Ï+Ñ+Ï+Ñ+Ï+Ñ+ôÏ+õÑ+ÞÏ+ßÑ+ÒÏ+ÓÑ+ÈÏ+ÉÑ+ÆÏ+ÇÑ+§1111111111Ó1Ö1þÿ1ÿÿ1ûÿ1þÿ1¸1¹1ëÿ1îÿ1èÿ1éÿ1æÿ1çÿ1äÿ1åÿ111Íÿ1Ðÿ1Ãÿ1Æÿ1¹1¼1¯1²111³ÿ1¶ÿ1§ÿ1ªÿ1ÿ1ÿ1ÿ1ÿ1ÿ1ÿ1þþ1ÿþ1Þþ1ßþ1Êþ1Ëþ1²þ1³þ1 þ1¡þ1þ1þ1þ1þ1þý1ÿý1âý1ãý1Ìý1Íý1Àý1Áý1¶ý1·ý1´ý1µý1§ÿüÅ6ýÃ6úüÃ6ûüÅ6ñüÅ6ôüÃ6üüÃ6ýüÅ6ïüÅ6òüÃ6ÁýÅ6ÄýÃ6ìüÃ6íüÅ6éüÅ6ìüÃ6¦ýÃ6§ýÅ6ÙüÅ6ÜüÃ6ÖüÃ6×üÅ6ÔüÃ6ÕüÅ6ÒüÃ6ÓüÅ6õýÅ6øýÃ6»üÅ6¾üÃ6±üÅ6´üÃ6§þÅ6ªþÃ6ýÅ6 ýÃ6øýÃ6ùýÅ6¡üÅ6¤üÃ6üÅ6üÃ6üÅ6üÃ6ûûÅ6þûÃ6ôûÃ6õûÅ6ìûÃ6íûÅ6ÌûÃ6ÍûÅ6¸ûÃ6¹ûÅ6 ûÃ6¡ûÅ6ûÃ6ûÅ6úúÃ6ûúÅ6ðúÃ6ñúÅ6ìúÃ6íúÅ6ÐúÃ6ÑúÅ6ºúÃ6»úÅ6®úÃ6¯úÅ6¤úÃ6¥úÅ6¢úÃ6£úÅ6§íùÿ;ðùý;èùý;éùÿ;ßùÿ;âùý;êùý;ëùÿ;Ýùÿ;àùý;¯úÿ;²úý;Úùý;Ûùÿ;×ùÿ;Úùý;úý;úÿ;Çùÿ;Êùý;Äùý;Åùÿ;Âùý;Ãùÿ;Àùý;Áùÿ;ãúÿ;æúý;©ùÿ;¬ùý;ùÿ;¢ùý;ûÿ;ûý;úÿ;úý;æúý;çúÿ;ùÿ;ùý;ùÿ;ùý;ïøÿ;òøý;éøÿ;ìøý;âøý;ãøÿ;Úøý;Ûøÿ;ºøý;»øÿ;¦øý;§øÿ;øý;øÿ;ü÷ý;ý÷ÿ;è÷ý;é÷ÿ;Þ÷ý;ß÷ÿ;Ú÷ý;Û÷ÿ;¾÷ý;¿÷ÿ;¨÷ý;©÷ÿ;÷ý;÷ÿ;÷ý;÷ÿ;÷ý;÷ÿ;§Ûö¹AÞö·AÖö·A×ö¹AÍö¹AÐö·AØö·AÙö¹AËö¹AÎö·A÷¹A ÷·AÈö·AÉö¹AÅö¹AÈö·A÷·A÷¹Aµö¹A¸ö·A²ö·A³ö¹A°ö·A±ö¹A®ö·A¯ö¹AÑ÷¹AÔ÷·Aö¹Aö·Aö¹Aö·Aø¹Aø·Aùö¹Aüö·AÔ÷·AÕ÷¹Aýõ¹Aö·Añõ¹Aôõ·AÝõ¹Aàõ·A×õ¹AÚõ·AÐõ·AÑõ¹AÈõ·AÉõ¹A¨õ·A©õ¹Aõ·Aõ¹Aüô·Aýô¹Aêô·Aëô¹AÖô·A×ô¹AÌô·AÍô¹AÈô·AÉô¹A¬ô·A­ô¹Aô·Aô¹Aô·Aô¹Aô·Aô¹Aþó·Aÿó¹A§ÉóóFÌóñFÄóñFÅóóF»óóF¾óñFÆóñFÇóóF¹óóF¼óñFôóFôñF¶óñF·óóF³óóF¶óñFðóñFñóóF£óóF¦óñF óñF¡óóFóñFóóFóñFóóF¿ôóFÂôñFóóFóñFûòóFþòñFñôóFôôñFçóóFêóñFÂôñFÃôóFëòóFîòñFßòóFâòñFËòóFÎòñFÅòóFÈòñF¾òñF¿òóF¶òñF·òóFòñFòóFòñFòóFêññFëñóFØññFÙñóFÄññFÅñóFºññF»ñóF¶ññF·ñóFññFñóFññFñóFøðñFùðóFîðñFïðóFìðñFíðóF§·ð­Lºð«L²ð«L³ð­L©ð­L¬ð«L´ð«Lµð­L§ð­Lªð«Lùð­Lüð«L¤ð«L¥ð­L¡ð­L¤ð«LÞð«Lßð­Lð­Lð«Lð«Lð­Lð«Lð­Lð«Lð­L­ñ­L°ñ«Lóï­Löï«Léï­Lìï«Lßñ­Lâñ«LÕð­LØð«L°ñ«L±ñ­LÙï­LÜï«LÍï­LÐï«L¹ï­L¼ï«L³ï­L¶ï«L¬ï«L­ï­L¤ï«L¥ï­Lï«Lï­Lðî«Lñî­LØî«LÙî­LÆî«LÇî­L²î«L³î­L¨î«L©î­L¤î«L¥î­Lî«Lî­Lòí«Lóí­Læí«Lçí­LÜí«LÝí­LÚí«LÛí­L§¥íçQ¨íåQ íåQ¡íçQíçQíåQ¢íåQ£íçQíçQíåQçíçQêíåQíåQíçQíçQíåQÌíåQÍíçQÿìçQíåQüìåQýìçQúìåQûìçQøìåQùìçQîçQîåQáìçQäìåQ×ìçQÚìåQÍîçQÐîåQÃíçQÆíåQîåQîçQÇìçQÊìåQ»ìçQ¾ìåQ§ìçQªìåQ¡ìçQ¤ìåQìåQìçQìåQìçQòëåQóëçQÞëåQßëçQÆëåQÇëçQ´ëåQµëçQ ëåQ¡ëçQëåQëçQëåQëçQöêåQ÷êçQàêåQáêçQÔêåQÕêçQÊêåQËêçQÈêåQÉêçQ§ê¡WêWêWê¡Wê¡WêWêWê¡Wê¡WêWÕê¡WØêWêWê¡Wýé¡WêWºêW»ê¡Wíé¡WðéWêéWëé¡WèéWéé¡WæéWçé¡Wë¡WëWÏé¡WÒéWÅé¡WÈéW»ë¡W¾ëW±ê¡W´êWëWë¡Wµé¡W¸éW©é¡W¬éWé¡WéWé¡WéWéWé¡WéWé¡WàèWáè¡WÌèWÍè¡W´èWµè¡W¢èW£è¡WèWè¡WèWè¡WèWè¡WäçWåç¡WÎçWÏç¡WÂçWÃç¡W¸çW¹ç¡W¶çW·ç¡W§çÛ\çÙ\üæÙ\ýæÛ\óæÛ\öæÙ\þæÙ\ÿæÛ\ñæÛ\ôæÙ\ÃçÛ\ÆçÙ\îæÙ\ïæÛ\ëæÛ\îæÙ\¨çÙ\©çÛ\ÛæÛ\ÞæÙ\ØæÙ\ÙæÛ\ÖæÙ\×æÛ\ÔæÙ\ÕæÛ\÷çÛ\úçÙ\½æÛ\ÀæÙ\³æÛ\¶æÙ\©èÛ\¬èÙ\çÛ\¢çÙ\úçÙ\ûçÛ\£æÛ\¦æÙ\æÛ\æÙ\æÛ\æÙ\ýåÛ\æÙ\öåÙ\÷åÛ\îåÙ\ïåÛ\ÎåÙ\ÏåÛ\ºåÙ\»åÛ\¢åÙ\£åÛ\åÙ\åÛ\üäÙ\ýäÛ\òäÙ\óäÛ\îäÙ\ïäÛ\ÒäÙ\ÓäÛ\¼äÙ\½äÛ\°äÙ\±äÛ\¦äÙ\§äÛ\¤äÙ\¥äÛ\§ïãbòãbêãbëãbáãbäãbìãbíãbßãbâãb±äb´äbÜãbÝãbÙãbÜãbäbäbÉãbÌãbÆãbÇãbÄãbÅãbÂãbÃãbåäbèäb«ãb®ãb¡ãb¤ãbåbåbäbäbèäbéäbãbãbãbãbñâbôâbëâbîâbäâbåâbÜâbÝâb¼âb½âb¨âb©âbâbâbþábÿábêábëábàábáábÜábÝábÀábÁábªáb«ábábábábábábáb§ÝàÏgààÍgØàÍgÙàÏgÏàÏgÒàÍgÚàÍgÛàÏgÍàÏgÐàÍgáÏg¢áÍgÊàÍgËàÏgÇàÏgÊàÍgáÍgáÏg·àÏgºàÍg´àÍgµàÏg²àÍg³àÏg°àÍg±àÏgÓáÏgÖáÍgàÏgàÍgàÏgàÍgâÏgâÍgûàÏgþàÍgÖáÍg×áÏgÿßÏgàÍgóßÏgößÍgßßÏgâßÍgÙßÏgÜßÍgÒßÍgÓßÏgÊßÍgËßÏgªßÍg«ßÏgßÍgßÏgþÞÍgÿÞÏgìÞÍgíÞÏgØÞÍgÙÞÏgÎÞÍgÏÞÏgÊÞÍgËÞÏg®ÞÍg¯ÞÏgÞÍgÞÏgÞÍgÞÏgÞÍgÞÏgÞÍgÞÏg§ËÝmÎÝmÆÝmÇÝm½ÝmÀÝmÈÝmÉÝm»Ým¾ÝmÞmÞm¸Ým¹ÝmµÝm¸ÝmòÝmóÝm¥Ým¨Ým¢Ým£Ým Ým¡ÝmÝmÝmÁÞmÄÞmÝmÝmýÜmÝmóÞmöÞméÝmìÝmÄÞmÅÞmíÜmðÜmáÜmäÜmÍÜmÐÜmÇÜmÊÜmÀÜmÁÜm¸Üm¹ÜmÜmÜmÜmÜmìÛmíÛmÚÛmÛÛmÆÛmÇÛm¼Ûm½Ûm¸Ûm¹ÛmÛmÛmÛmÛmúÚmûÚmðÚmñÚmîÚmïÚm§¹ÚÃr¼ÚÁr´ÚÁrµÚÃr«ÚÃr®ÚÁr¶ÚÁr·ÚÃr©ÚÃr¬ÚÁrûÚÃrþÚÁr¦ÚÁr§ÚÃr£ÚÃr¦ÚÁràÚÁráÚÃrÚÃrÚÁrÚÁrÚÃrÚÁrÚÃrÚÁrÚÃr¯ÛÃr²ÛÁrõÙÃrøÙÁrëÙÃrîÙÁráÛÃräÛÁr×ÚÃrÚÚÁr²ÛÁr³ÛÃrÛÙÃrÞÙÁrÏÙÃrÒÙÁr»ÙÃr¾ÙÁrµÙÃr¸ÙÁr®ÙÁr¯ÙÃr¦ÙÁr§ÙÃrÙÁrÙÃròØÁróØÃrÚØÁrÛØÃrÈØÁrÉØÃr´ØÁrµØÃrªØÁr«ØÃr¦ØÁr§ØÃrØÁrØÃrô×Árõ×Ãrè×Áré×ÃrÞ×Árß×ÃrÜ×ÁrÝ×Ãr§§×ýwª×ûw¢×ûw£×ýw×ýw×ûw¤×ûw¥×ýw×ýw×ûwé×ýwì×ûw×ûw×ýw×ýw×ûwÎ×ûwÏ×ýw×ýw×ûwþÖûwÿÖýwüÖûwýÖýwúÖûwûÖýwØýw ØûwãÖýwæÖûwÙÖýwÜÖûwÏØýwÒØûwÅ×ýwÈ×ûw Øûw¡ØýwÉÖýwÌÖûw½ÖýwÀÖûw©Öýw¬Öûw£Öýw¦ÖûwÖûwÖýwÖûwÖýwôÕûwõÕýwàÕûwáÕýwÈÕûwÉÕýw¶Õûw·Õýw¢Õûw£ÕýwÕûwÕýwÕûwÕýwøÔûwùÔýwâÔûwãÔýwÖÔûw×ÔýwÌÔûwÍÔýwÊÔûwËÔýw§×Æ»ÚÆ¹ÒÆ¹ÓÆ»ÉÆ»ÌÆ¹ÔÆ¹ÕÆ»ÇÆ»ÊÆ¹Ç»Ç¹ÄÆ¹ÅÆ»ÁÆ»ÄÆ¹þÆ¹ÿÆ»±Æ»´Æ¹®Æ¹¯Æ»¬Æ¹­Æ»ªÆ¹«Æ»ÍÇ»ÐÇ¹Æ»Æ¹Æ»Æ¹ÿÇ»È¹õÆ»øÆ¹ÐÇ¹ÑÇ»ùÅ»üÅ¹íÅ»ðÅ¹ÙÅ»ÜÅ¹ÓÅ»ÖÅ¹ÌÅ¹ÍÅ»ÄÅ¹ÅÅ»¤Å¹¥Å»Å¹Å»øÄ¹ùÄ»æÄ¹çÄ»ÒÄ¹ÓÄ»ÈÄ¹ÉÄ»ÄÄ¹ÅÄ»¨Ä¹©Ä»Ä¹Ä»Ä¹Ä»üÃ¹ýÃ»úÃ¹ûÃ»§ÅÃõ
+ÈÃó
+ÀÃó
+ÁÃõ
+·Ãõ
+ºÃó
+ÂÃó
+ÃÃõ
+µÃõ
+¸Ãó
+Äõ
+Äó
+²Ãó
+³Ãõ
+¯Ãõ
+²Ãó
+ìÃó
+íÃõ
+Ãõ
+¢Ãó
+Ãó
+Ãõ
+Ãó
+Ãõ
+Ãó
+Ãõ
+»Äõ
+¾Äó
+Ãõ
+Ãó
+÷Âõ
+úÂó
+íÄõ
+ðÄó
+ãÃõ
+æÃó
+¾Äó
+¿Äõ
+çÂõ
+êÂó
+ÛÂõ
+ÞÂó
+ÇÂõ
+ÊÂó
+ÁÂõ
+ÄÂó
+ºÂó
+»Âõ
+²Âó
+³Âõ
+Âó
+Âõ
+þÁó
+ÿÁõ
+æÁó
+çÁõ
+ÔÁó
+ÕÁõ
+ÀÁó
+ÁÁõ
+¶Áó
+·Áõ
+²Áó
+³Áõ
+Áó
+Áõ
+Áó
+Áõ
+ôÀó
+õÀõ
+êÀó
+ëÀõ
+èÀó
+éÀõ
+§³À¯¶À­®À­¯À¯¥À¯¨À­°À­±À¯£À¯¦À­õÀ¯øÀ­ À­¡À¯À¯ À­ÚÀ­ÛÀ¯À¯À­À­À¯À­À¯À­À¯©Á¯¬Á­ï¿¯ò¿­å¿¯è¿­ÛÁ¯ÞÁ­ÑÀ¯ÔÀ­¬Á­­Á¯Õ¿¯Ø¿­É¿¯Ì¿­µ¿¯¸¿­¯¿¯²¿­¨¿­©¿¯ ¿­¡¿¯¿­¿¯ì¾­í¾¯Ô¾­Õ¾¯Â¾­Ã¾¯®¾­¯¾¯¤¾­¥¾¯ ¾­¡¾¯¾­¾¯î½­ï½¯â½­ã½¯Ø½­Ù½¯Ö½­×½¯§¡½é¤½ç½ç½é½é½ç½ç½é½é½çã½éæ½ç½ç½é½é½çÈ½çÉ½éû¼éþ¼çø¼çù¼éö¼ç÷¼éô¼çõ¼é¾é¾çÝ¼éà¼çÓ¼éÖ¼çÉ¾éÌ¾ç¿½éÂ½ç¾ç¾éÃ¼éÆ¼ç·¼éº¼ç£¼é¦¼ç¼é ¼ç¼ç¼é¼ç¼éî»çï»éÚ»çÛ»éÂ»çÃ»é°»ç±»é»ç»é»ç»é»ç»éòºçóºéÜºçÝºéÐºçÑºéÆºçÇºéÄºçÅºé§º£º¡º¡º£º£º¡º¡º£ÿ¹£º¡Ñº£Ôº¡ü¹¡ý¹£ù¹£ü¹¡¶º¡·º£é¹£ì¹¡æ¹¡ç¹£ä¹¡å¹£â¹¡ã¹£»£»¡Ë¹£Î¹¡Á¹£Ä¹¡·»£º»¡­º£°º¡»¡»£±¹£´¹¡¥¹£¨¹¡¹£¹¡¹£¹¡¹¡¹£ü¸¡ý¸£Ü¸¡Ý¸£È¸¡É¸£°¸¡±¸£¸¡¸£¸¡¸£¸¡¸£ü·¡ý·£à·¡á·£Ê·¡Ë·£¾·¡¿·£´·¡µ·£²·¡³·£§ý¶Ý ·Û ø¶Û ù¶Ý ï¶Ý ò¶Û ú¶Û û¶Ý í¶Ý ð¶Û ¿·Ý Â·Û ê¶Û ë¶Ý ç¶Ý ê¶Û ¤·Û ¥·Ý ×¶Ý Ú¶Û Ô¶Û Õ¶Ý Ò¶Û Ó¶Ý Ð¶Û Ñ¶Ý ó·Ý ö·Û ¹¶Ý ¼¶Û ¯¶Ý ²¶Û ¥¸Ý ¨¸Û ·Ý ·Û ö·Û ÷·Ý ¶Ý ¢¶Û ¶Ý ¶Û ÿµÝ ¶Û ùµÝ üµÛ òµÛ óµÝ êµÛ ëµÝ ÊµÛ ËµÝ ¶µÛ ·µÝ µÛ µÝ µÛ µÝ ø´Û ù´Ý î´Û ï´Ý ê´Û ë´Ý Î´Û Ï´Ý ¸´Û ¹´Ý ¬´Û ­´Ý ¢´Û £´Ý  ´Û ¡´Ý §ë³&î³&æ³&ç³&Ý³&à³&è³&é³&Û³&Þ³&­´&°´&Ø³&Ù³&Õ³&Ø³&´&´&Å³&È³&Â³&Ã³&À³&Á³&¾³&¿³&á´&ä´&§³&ª³&³& ³&µ&µ&´&´&ä´&å´&³&³&³&³&í²&ð²&ç²&ê²&à²&á²&Ø²&Ù²&¸²&¹²&¤²&¥²&²&²&ú±&û±&æ±&ç±&Ü±&Ý±&Ø±&Ù±&¼±&½±&¦±&§±&±&±&±&±&±&±&§Ù°Ñ+Ü°Ï+Ô°Ï+Õ°Ñ+Ë°Ñ+Î°Ï+Ö°Ï+×°Ñ+É°Ñ+Ì°Ï+±Ñ+±Ï+Æ°Ï+Ç°Ñ+Ã°Ñ+Æ°Ï+±Ï+±Ñ+³°Ñ+¶°Ï+°°Ï+±°Ñ+®°Ï+¯°Ñ+¬°Ï+­°Ñ+Ï±Ñ+Ò±Ï+°Ñ+°Ï+°Ñ+°Ï+²Ñ+²Ï+÷°Ñ+ú°Ï+Ò±Ï+Ó±Ñ+û¯Ñ+þ¯Ï+ï¯Ñ+ò¯Ï+Û¯Ñ+Þ¯Ï+Õ¯Ñ+Ø¯Ï+Î¯Ï+Ï¯Ñ+Æ¯Ï+Ç¯Ñ+¦¯Ï+§¯Ñ+¯Ï+¯Ñ+ú®Ï+û®Ñ+è®Ï+é®Ñ+Ô®Ï+Õ®Ñ+Ê®Ï+Ë®Ñ+Æ®Ï+Ç®Ñ+ª®Ï+«®Ñ+®Ï+®Ñ+®Ï+®Ñ+þ­Ï+ÿ­Ñ+ü­Ï+ý­Ñ+§Ç­1Ê­1Â­1Ã­1¹­1¼­1Ä­1Å­1·­1º­1®1®1´­1µ­1±­1´­1î­1ï­1¡­1¤­1­1­1­1­1­1­1½®1À®1­1­1ù¬1ü¬1ï®1ò®1å­1è­1À®1Á®1é¬1ì¬1Ý¬1à¬1É¬1Ì¬1Ã¬1Æ¬1¼¬1½¬1´¬1µ¬1¬1¬1¬1¬1è«1é«1Ö«1×«1Â«1Ã«1¸«1¹«1´«1µ«1«1«1«1«1öª1÷ª1ìª1íª1êª1ëª1§µªÅ6¸ªÃ6°ªÃ6±ªÅ6§ªÅ6ªªÃ6²ªÃ6³ªÅ6¥ªÅ6¨ªÃ6÷ªÅ6úªÃ6¢ªÃ6£ªÅ6ªÅ6¢ªÃ6ÜªÃ6ÝªÅ6ªÅ6ªÃ6ªÃ6ªÅ6ªÃ6ªÅ6ªÃ6ªÅ6««Å6®«Ã6ñ©Å6ô©Ã6ç©Å6ê©Ã6Ý«Å6à«Ã6ÓªÅ6ÖªÃ6®«Ã6¯«Å6×©Å6Ú©Ã6Ë©Å6Î©Ã6·©Å6º©Ã6±©Å6´©Ã6ª©Ã6«©Å6¢©Ã6£©Å6©Ã6©Å6î¨Ã6ï¨Å6Ö¨Ã6×¨Å6Ä¨Ã6Å¨Å6°¨Ã6±¨Å6¦¨Ã6§¨Å6¢¨Ã6£¨Å6¨Ã6¨Å6ð§Ã6ñ§Å6ä§Ã6å§Å6Ú§Ã6Û§Å6Ø§Ã6Ù§Å6§£§ÿ;¦§ý;§ý;§ÿ;§ÿ;§ý; §ý;¡§ÿ;§ÿ;§ý;å§ÿ;è§ý;§ý;§ÿ;§ÿ;§ý;Ê§ý;Ë§ÿ;ý¦ÿ;§ý;ú¦ý;û¦ÿ;ø¦ý;ù¦ÿ;ö¦ý;÷¦ÿ;¨ÿ;¨ý;ß¦ÿ;â¦ý;Õ¦ÿ;Ø¦ý;Ë¨ÿ;Î¨ý;Á§ÿ;Ä§ý;¨ý;¨ÿ;Å¦ÿ;È¦ý;¹¦ÿ;¼¦ý;¥¦ÿ;¨¦ý;¦ÿ;¢¦ý;¦ý;¦ÿ;¦ý;¦ÿ;ð¥ý;ñ¥ÿ;Ü¥ý;Ý¥ÿ;Ä¥ý;Å¥ÿ;²¥ý;³¥ÿ;¥ý;¥ÿ;¥ý;¥ÿ;¥ý;¥ÿ;ô¤ý;õ¤ÿ;Þ¤ý;ß¤ÿ;Ò¤ý;Ó¤ÿ;È¤ý;É¤ÿ;Æ¤ý;Ç¤ÿ;§¤¹A¤·A¤·A¤¹A¤¹A¤·A¤·A¤¹A¤¹A¤·AÓ¤¹AÖ¤·Aþ£·Aÿ£¹Aû£¹Aþ£·A¸¤·A¹¤¹Aë£¹Aî£·Aè£·Aé£¹Aæ£·Aç£¹Aä£·Aå£¹A¥¹A¥·AÍ£¹AÐ£·AÃ£¹AÆ£·A¹¥¹A¼¥·A¯¤¹A²¤·A¥·A¥¹A³£¹A¶£·A§£¹Aª£·A£¹A£·A£¹A£·A£·A£¹Aþ¢·Aÿ¢¹AÞ¢·Aß¢¹AÊ¢·AË¢¹A²¢·A³¢¹A ¢·A¡¢¹A¢·A¢¹A¢·A¢¹Aþ¡·Aÿ¡¹Aâ¡·Aã¡¹AÌ¡·AÍ¡¹AÀ¡·AÁ¡¹A¶¡·A·¡¹A´¡·Aµ¡¹A§ÿ óF¡ñFú ñFû óFñ óFô ñFü ñFý óFï óFò ñFÁ¡óFÄ¡ñFì ñFí óFé óFì ñF¦¡ñF§¡óFÙ óFÜ ñFÖ ñF× óFÔ ñFÕ óFÒ ñFÓ óFõ¡óFø¡ñF» óF¾ ñF± óF´ ñF§¢óFª¢ñF¡óF ¡ñFø¡ñFù¡óF¡ óF¤ ñF óF ñF óF ñFûóFþñFôñFõóFìñFíóFÌñFÍóF¸ñF¹óF ñF¡óFñFóFúñFûóFðñFñóFìñFíóFÐñFÑóFºñF»óF®ñF¯óF¤ñF¥óF¢ñF£óF§í­Lð«Lè«Lé­Lß­Lâ«Lê«Lë­LÝ­Là«L¯­L²«LÚ«LÛ­L×­LÚ«L«L­LÇ­LÊ«LÄ«LÅ­LÂ«LÃ­LÀ«LÁ­Lã­Læ«L©­L¬«L­L¢«L­L«L­L«Læ«Lç­L­L«L­L«Lï­Lò«Lé­Lì«Lâ«Lã­LÚ«LÛ­Lº«L»­L¦«L§­L«L­Lü«Lý­Lè«Lé­LÞ«Lß­LÚ«LÛ­L¾«L¿­L¨«L©­L«L­L«L­L«L­L§ÛçQÞåQÖåQ×çQÍçQÐåQØåQÙçQËçQÎåQçQ åQÈåQÉçQÅçQÈåQåQçQµçQ¸åQ²åQ³çQ°åQ±çQ®åQ¯çQÑçQÔåQçQåQçQåQçQåQùçQüåQÔåQÕçQýçQåQñçQôåQÝçQàåQ×çQÚåQÐåQÑçQÈåQÉçQ¨åQ©çQåQçQüåQýçQêåQëçQÖåQ×çQÌåQÍçQÈåQÉçQ¬åQ­çQåQçQåQçQåQçQþåQÿçQ§É¡WÌWÄWÅ¡W»¡W¾WÆWÇ¡W¹¡W¼W¡WW¶W·¡W³¡W¶WðWñ¡W£¡W¦W W¡¡WW¡WW¡W¿¡WÂW¡WWû¡WþWñ¡WôWç¡WêWÂWÃ¡Wë¡WîWß¡WâWË¡WÎWÅ¡WÈW¾W¿¡W¶W·¡WW¡WW¡WêWë¡WØWÙ¡WÄWÅ¡WºW»¡W¶W·¡WW¡WW¡WøWù¡WîWï¡WìWí¡W§·Û\ºÙ\²Ù\³Û\©Û\¬Ù\´Ù\µÛ\§Û\ªÙ\ùÛ\üÙ\¤Ù\¥Û\¡Û\¤Ù\ÞÙ\ßÛ\Û\Ù\Ù\Û\Ù\Û\Ù\Û\­Û\°Ù\óÛ\öÙ\éÛ\ìÙ\ßÛ\âÙ\ÕÛ\ØÙ\°Ù\±Û\ÙÛ\ÜÙ\ÍÛ\ÐÙ\¹Û\¼Ù\³Û\¶Ù\¬Ù\­Û\¤Ù\¥Û\Ù\Û\ðÙ\ñÛ\ØÙ\ÙÛ\ÆÙ\ÇÛ\²Ù\³Û\¨Ù\©Û\¤Ù\¥Û\Ù\Û\òÙ\óÛ\æÙ\çÛ\ÜÙ\ÝÛ\ÚÙ\ÛÛ\§¥b¨b b¡bbb¢b£bbbçbêbbbbbÌbÍbÿbbübýbúbûbøbùbbbábäb×bÚbÍbÐbÃbÆbbbÇbÊb»b¾b§bªb¡b¤bbbbbòbóbÞbßbÆbÇb´bµb b¡bbbbböb÷bàbábÔbÕbÊbËbÈbÉb§ÏgÍgÍgÏgÏgÍgÍgÏgÏgÍgÕÏgØÍgÍgÏgýÏgÍgºÍg»ÏgíÏgðÍgêÍgëÏgèÍgéÏgæÍgçÏgÏgÍgÏÏgÒÍgÅÏgÈÍg»Ïg¾Íg±Ïg´ÍgÍgÏgµÏg¸Íg©Ïg¬ÍgÏgÍgÏgÍgÍgÏgÍgÏgàÍgáÏgÌÍgÍÏg´ÍgµÏg¢Íg£ÏgÍgÏgÍgÏgÍgÏgäÍgåÏgÎÍgÏÏgÂÍgÃÏg¸Íg¹Ïg¶Íg·Ïg§mmümýmómömþmÿmñmômÃmÆmîmïmëmîm¨m©mÛmÞmØmÙmÖm×mÔmÕm÷múm½mÀm³m¶m©m¬mm¢múmûm£m¦mmmmmýmmöm÷mîmïmÎmÏmºm»m¢m£mmmümýmòmómîmïmÒmÓm¼m½m°m±m¦m§m¤m¥m§ïÃròÁrêÁrëÃráÃräÁrìÁríÃrßÃrâÁr±Ãr´ÁrÜÁrÝÃrÙÃrÜÁrÁrÃrÉÃrÌÁrÆÁrÇÃrÄÁrÅÃrÂÁrÃÃråÃrèÁr«Ãr®Ár¡Ãr¤ÁrÃrÁrÃrÁrèÁréÃrÃrÁrÃrÁrñÃrôÁrëÃrîÁräÁråÃrÜÁrÝÃr¼Ár½Ãr¨Ár©ÃrÁrÃrþÁrÿÃrêÁrëÃràÁráÃrÜÁrÝÃrÀÁrÁÃrªÁr«ÃrÁrÃrÁrÃrÁrÃr§åñ»èñ¹àñ¹áñ»×ñ»Úñ¹âñ¹ãñ»Õñ»Øñ¹§ò»ªò¹Òñ¹Óñ»Ïñ»Òñ¹ò¹ò»¿ñ»Âñ¹¼ñ¹½ñ»ºñ¹»ñ»¸ñ¹¹ñ»Ûò»Þò¹¡ñ»¤ñ¹ñ»ñ¹ó»ó¹ò»ò¹Þò¹ßò»ñ»ñ¹ûð»þð¹çð»êð¹áð»äð¹Úð¹Ûð»Òð¹Óð»²ð¹³ð»ð¹ð»ð¹ð»ôï¹õï»àï¹áï»Öï¹×ï»Òï¹Óï»¶ï¹·ï» ï¹¡ï»ï¹ï»ï¹ï»ï¹ï»§Óîõ
+Öîó
+Îîó
+Ïîõ
+Åîõ
+Èîó
+Ðîó
+Ñîõ
+Ãîõ
+Æîó
+ïõ
+ïó
+Àîó
+Áîõ
+½îõ
+Àîó
+úîó
+ûîõ
+­îõ
+°îó
+ªîó
+«îõ
+¨îó
+©îõ
+¦îó
+§îõ
+Éïõ
+Ìïó
+îõ
+îó
+îõ
+îó
+ûïõ
+þïó
+ñîõ
+ôîó
+Ìïó
+Íïõ
+õíõ
+øíó
+éíõ
+ìíó
+Õíõ
+Øíó
+Ïíõ
+Òíó
+Èíó
+Éíõ
+Àíó
+Áíõ
+ íó
+¡íõ
+íó
+íõ
+ôìó
+õìõ
+âìó
+ãìõ
+Îìó
+Ïìõ
+Äìó
+Åìõ
+Àìó
+Áìõ
+¤ìó
+¥ìõ
+ìó
+ìõ
+ìó
+ìõ
+øëó
+ùëõ
+öëó
+÷ëõ
+§Áë¯Äë­¼ë­½ë¯³ë¯¶ë­¾ë­¿ë¯±ë¯´ë­ì¯ì­®ë­¯ë¯«ë¯®ë­èë­éë¯ë¯ë­ë­ë¯ë­ë¯ë­ë¯·ì¯ºì­ýê¯ë­óê¯öê­éì¯ìì­ßë¯âë­ºì­»ì¯ãê¯æê­×ê¯Úê­Ãê¯Æê­½ê¯Àê­¶ê­·ê¯®ê­¯ê¯ê­ê¯úé­ûé¯âé­ãé¯Ðé­Ñé¯¼é­½é¯²é­³é¯®é­¯é¯é­é¯üè­ýè¯ðè­ñè¯æè­çè¯äè­åè¯§¯èé²èçªèç«èé¡èé¤èç¬èç­èéèé¢èçñèéôèçèçèéèéèçÖèç×èéèéèçèçèéèçèéèçèé¥éé¨éçëçéîççáçéäçç×ééÚéçÍèéÐèç¨éç©ééÑçéÔççÅçéÈçç±çé´çç«çé®çç¤çç¥çéçççéüæçýæéèæçéæéÐæçÑæé¾æç¿æéªæç«æé æç¡æéæçæéæçæéêåçëåéÞåçßåéÔåçÕåéÒåçÓåé§å£ å¡å¡å£å£å¡å¡å£å£å¡ßå£âå¡å¡å£å£å¡Äå¡Åå£÷ä£úä¡ôä¡õä£òä¡óä£ðä¡ñä£æ£æ¡Ùä£Üä¡Ïä£Òä¡Åæ£Èæ¡»å£¾å¡æ¡æ£¿ä£Âä¡³ä£¶ä¡ä£¢ä¡ä£ä¡ä¡ä£ä¡ä£êã¡ëã£Öã¡×ã£¾ã¡¿ã£¬ã¡­ã£ã¡ã£ã¡ã£ã¡ã£îâ¡ïâ£Øâ¡Ùâ£Ìâ¡Íâ£Ââ¡Ãâ£Àâ¡Áâ£§âÝ âÛ âÛ âÝ ýáÝ âÛ âÛ âÝ ûáÝ þáÛ ÍâÝ ÐâÛ øáÛ ùáÝ õáÝ øáÛ ²âÛ ³âÝ åáÝ èáÛ âáÛ ãáÝ àáÛ ááÝ ÞáÛ ßáÝ ãÝ ãÛ ÇáÝ ÊáÛ ½áÝ ÀáÛ ³ãÝ ¶ãÛ ©âÝ ¬âÛ ãÛ ãÝ ­áÝ °áÛ ¡áÝ ¤áÛ áÝ áÛ áÝ áÛ áÛ áÝ øàÛ ùàÝ ØàÛ ÙàÝ ÄàÛ ÅàÝ ¬àÛ ­àÝ àÛ àÝ àÛ àÝ üßÛ ýßÝ øßÛ ùßÝ ÜßÛ ÝßÝ ÆßÛ ÇßÝ ºßÛ »ßÝ °ßÛ ±ßÝ ®ßÛ ¯ßÝ §ùÞ&üÞ&ôÞ&õÞ&ëÞ&îÞ&öÞ&÷Þ&éÞ&ìÞ&»ß&¾ß&æÞ&çÞ&ãÞ&æÞ& ß&¡ß&ÓÞ&ÖÞ&ÐÞ&ÑÞ&ÎÞ&ÏÞ&ÌÞ&ÍÞ&ïß&òß&µÞ&¸Þ&«Þ&®Þ&¡à&¤à&ß&ß&òß&óß&Þ&Þ&Þ&Þ&ûÝ&þÝ&õÝ&øÝ&îÝ&ïÝ&æÝ&çÝ&ÆÝ&ÇÝ&²Ý&³Ý&Ý&Ý&Ý&Ý&ôÜ&õÜ&êÜ&ëÜ&æÜ&çÜ&ÊÜ&ËÜ&´Ü&µÜ&¨Ü&©Ü&Ü&Ü&Ü&Ü&§çÛÑ+êÛÏ+âÛÏ+ãÛÑ+ÙÛÑ+ÜÛÏ+äÛÏ+åÛÑ+×ÛÑ+ÚÛÏ+©ÜÑ+¬ÜÏ+ÔÛÏ+ÕÛÑ+ÑÛÑ+ÔÛÏ+ÜÏ+ÜÑ+ÁÛÑ+ÄÛÏ+¾ÛÏ+¿ÛÑ+¼ÛÏ+½ÛÑ+ºÛÏ+»ÛÑ+ÝÜÑ+àÜÏ+£ÛÑ+¦ÛÏ+ÛÑ+ÛÏ+ÝÑ+ÝÏ+ÜÑ+ÜÏ+àÜÏ+áÜÑ+ÛÑ+ÛÏ+ýÚÑ+ÛÏ+éÚÑ+ìÚÏ+ãÚÑ+æÚÏ+ÜÚÏ+ÝÚÑ+ÔÚÏ+ÕÚÑ+´ÚÏ+µÚÑ+ ÚÏ+¡ÚÑ+ÚÏ+ÚÑ+öÙÏ+÷ÙÑ+âÙÏ+ãÙÑ+ØÙÏ+ÙÙÑ+ÔÙÏ+ÕÙÑ+¸ÙÏ+¹ÙÑ+¢ÙÏ+£ÙÑ+ÙÏ+ÙÑ+ÙÏ+ÙÑ+ÙÏ+ÙÑ+§ÕØ1ØØ1ÐØ1ÑØ1ÇØ1ÊØ1ÒØ1ÓØ1ÅØ1ÈØ1Ù1Ù1ÂØ1ÃØ1¿Ø1ÂØ1üØ1ýØ1¯Ø1²Ø1¬Ø1­Ø1ªØ1«Ø1¨Ø1©Ø1ËÙ1ÎÙ1Ø1Ø1Ø1Ø1ýÙ1Ú1óØ1öØ1ÎÙ1ÏÙ1÷×1ú×1ë×1î×1××1Ú×1Ñ×1Ô×1Ê×1Ë×1Â×1Ã×1¢×1£×1×1×1öÖ1÷Ö1äÖ1åÖ1ÐÖ1ÑÖ1ÆÖ1ÇÖ1ÂÖ1ÃÖ1¦Ö1§Ö1Ö1Ö1Ö1Ö1úÕ1ûÕ1øÕ1ùÕ1§ÃÕÅ6ÆÕÃ6¾ÕÃ6¿ÕÅ6µÕÅ6¸ÕÃ6ÀÕÃ6ÁÕÅ6³ÕÅ6¶ÕÃ6ÖÅ6ÖÃ6°ÕÃ6±ÕÅ6­ÕÅ6°ÕÃ6êÕÃ6ëÕÅ6ÕÅ6 ÕÃ6ÕÃ6ÕÅ6ÕÃ6ÕÅ6ÕÃ6ÕÅ6¹ÖÅ6¼ÖÃ6ÿÔÅ6ÕÃ6õÔÅ6øÔÃ6ëÖÅ6îÖÃ6áÕÅ6äÕÃ6¼ÖÃ6½ÖÅ6åÔÅ6èÔÃ6ÙÔÅ6ÜÔÃ6ÅÔÅ6ÈÔÃ6¿ÔÅ6ÂÔÃ6¸ÔÃ6¹ÔÅ6°ÔÃ6±ÔÅ6ÔÃ6ÔÅ6üÓÃ6ýÓÅ6äÓÃ6åÓÅ6ÒÓÃ6ÓÓÅ6¾ÓÃ6¿ÓÅ6´ÓÃ6µÓÅ6°ÓÃ6±ÓÅ6ÓÃ6ÓÅ6þÒÃ6ÿÒÅ6òÒÃ6óÒÅ6èÒÃ6éÒÅ6æÒÃ6çÒÅ6§±Òÿ;´Òý;¬Òý;­Òÿ;£Òÿ;¦Òý;®Òý;¯Òÿ;¡Òÿ;¤Òý;óÒÿ;öÒý;Òý;Òÿ;Òÿ;Òý;ØÒý;ÙÒÿ;Òÿ;Òý;Òý;Òÿ;Òý;Òÿ;Òý;Òÿ;§Óÿ;ªÓý;íÑÿ;ðÑý;ãÑÿ;æÑý;ÙÓÿ;ÜÓý;ÏÒÿ;ÒÒý;ªÓý;«Óÿ;ÓÑÿ;ÖÑý;ÇÑÿ;ÊÑý;³Ñÿ;¶Ñý;­Ñÿ;°Ñý;¦Ñý;§Ñÿ;Ñý;Ñÿ;þÐý;ÿÐÿ;êÐý;ëÐÿ;ÒÐý;ÓÐÿ;ÀÐý;ÁÐÿ;¬Ðý;­Ðÿ;¢Ðý;£Ðÿ;Ðý;Ðÿ;Ðý;Ðÿ;ìÏý;íÏÿ;àÏý;áÏÿ;ÖÏý;×Ïÿ;ÔÏý;ÕÏÿ;§Ï¹A¢Ï·AÏ·AÏ¹AÏ¹AÏ·AÏ·AÏ¹AÏ¹AÏ·AáÏ¹AäÏ·AÏ·AÏ¹AÏ¹AÏ·AÆÏ·AÇÏ¹AùÎ¹AüÎ·AöÎ·A÷Î¹AôÎ·AõÎ¹AòÎ·AóÎ¹AÐ¹AÐ·AÛÎ¹AÞÎ·AÑÎ¹AÔÎ·AÇÐ¹AÊÐ·A½Ï¹AÀÏ·AÐ·AÐ¹AÁÎ¹AÄÎ·AµÎ¹A¸Î·A¡Î¹A¤Î·AÎ¹AÎ·AÎ·AÎ¹AÎ·AÎ¹AìÍ·AíÍ¹AØÍ·AÙÍ¹AÀÍ·AÁÍ¹A®Í·A¯Í¹AÍ·AÍ¹AÍ·AÍ¹AÍ·AÍ¹AðÌ·AñÌ¹AÚÌ·AÛÌ¹AÎÌ·AÏÌ¹AÄÌ·AÅÌ¹AÂÌ·AÃÌ¹A§ÌóFÌñFÌñFÌóFÿËóFÌñFÌñFÌóFýËóFÌñFÏÌóFÒÌñFúËñFûËóF÷ËóFúËñF´ÌñFµÌóFçËóFêËñFäËñFåËóFâËñFãËóFàËñFáËóFÍóFÍñFÉËóFÌËñF¿ËóFÂËñFµÍóF¸ÍñF«ÌóF®ÌñFÍñFÍóF¯ËóF²ËñF£ËóF¦ËñFËóFËñFËóFËñFËñFËóFúÊñFûÊóFÚÊñFÛÊóFÆÊñFÇÊóF®ÊñF¯ÊóFÊñFÊóFÊñFÊóFþÉñFÿÉóFúÉñFûÉóFÞÉñFßÉóFÈÉñFÉÉóF¼ÉñF½ÉóF²ÉñF³ÉóF°ÉñF±ÉóF§ûÈ­LþÈ«LöÈ«L÷È­LíÈ­LðÈ«LøÈ«LùÈ­LëÈ­LîÈ«L½É­LÀÉ«LèÈ«LéÈ­LåÈ­LèÈ«L¢É«L£É­LÕÈ­LØÈ«LÒÈ«LÓÈ­LÐÈ«LÑÈ­LÎÈ«LÏÈ­LñÉ­LôÉ«L·È­LºÈ«L­È­L°È«L£Ê­L¦Ê«LÉ­LÉ«LôÉ«LõÉ­LÈ­L È«LÈ­LÈ«LýÇ­LÈ«L÷Ç­LúÇ«LðÇ«LñÇ­LèÇ«LéÇ­LÈÇ«LÉÇ­L´Ç«LµÇ­LÇ«LÇ­LÇ«LÇ­LöÆ«L÷Æ­LìÆ«LíÆ­LèÆ«LéÆ­LÌÆ«LÍÆ­L¶Æ«L·Æ­LªÆ«L«Æ­L Æ«L¡Æ­LÆ«LÆ­L§éÅçQìÅåQäÅåQåÅçQÛÅçQÞÅåQæÅåQçÅçQÙÅçQÜÅåQ«ÆçQ®ÆåQÖÅåQ×ÅçQÓÅçQÖÅåQÆåQÆçQÃÅçQÆÅåQÀÅåQÁÅçQ¾ÅåQ¿ÅçQ¼ÅåQ½ÅçQßÆçQâÆåQ¥ÅçQ¨ÅåQÅçQÅåQÇçQÇåQÆçQÆåQâÆåQãÆçQÅçQÅåQÿÄçQÅåQëÄçQîÄåQåÄçQèÄåQÞÄåQßÄçQÖÄåQ×ÄçQ¶ÄåQ·ÄçQ¢ÄåQ£ÄçQÄåQÄçQøÃåQùÃçQäÃåQåÃçQÚÃåQÛÃçQÖÃåQ×ÃçQºÃåQ»ÃçQ¤ÃåQ¥ÃçQÃåQÃçQÃåQÃçQÃåQÃçQ§×Â¡WÚÂWÒÂWÓÂ¡WÉÂ¡WÌÂWÔÂWÕÂ¡WÇÂ¡WÊÂWÃ¡WÃWÄÂWÅÂ¡WÁÂ¡WÄÂWþÂWÿÂ¡W±Â¡W´ÂW®ÂW¯Â¡W¬ÂW­Â¡WªÂW«Â¡WÍÃ¡WÐÃWÂ¡WÂWÂ¡WÂWÿÃ¡WÄWõÂ¡WøÂWÐÃWÑÃ¡WùÁ¡WüÁWíÁ¡WðÁWÙÁ¡WÜÁWÓÁ¡WÖÁWÌÁWÍÁ¡WÄÁWÅÁ¡W¤ÁW¥Á¡WÁWÁ¡WøÀWùÀ¡WæÀWçÀ¡WÒÀWÓÀ¡WÈÀWÉÀ¡WÄÀWÅÀ¡W¨ÀW©À¡WÀWÀ¡WÀWÀ¡Wü¿Wý¿¡Wú¿Wû¿¡W§Å¿Û\È¿Ù\À¿Ù\Á¿Û\·¿Û\º¿Ù\Â¿Ù\Ã¿Û\µ¿Û\¸¿Ù\ÀÛ\ÀÙ\²¿Ù\³¿Û\¯¿Û\²¿Ù\ì¿Ù\í¿Û\¿Û\¢¿Ù\¿Ù\¿Û\¿Ù\¿Û\¿Ù\¿Û\»ÀÛ\¾ÀÙ\¿Û\¿Ù\÷¾Û\ú¾Ù\íÀÛ\ðÀÙ\ã¿Û\æ¿Ù\¾ÀÙ\¿ÀÛ\ç¾Û\ê¾Ù\Û¾Û\Þ¾Ù\Ç¾Û\Ê¾Ù\Á¾Û\Ä¾Ù\º¾Ù\»¾Û\²¾Ù\³¾Û\¾Ù\¾Û\þ½Ù\ÿ½Û\æ½Ù\ç½Û\Ô½Ù\Õ½Û\À½Ù\Á½Û\¶½Ù\·½Û\²½Ù\³½Û\½Ù\½Û\½Ù\½Û\ô¼Ù\õ¼Û\ê¼Ù\ë¼Û\è¼Ù\é¼Û\§³¼b¶¼b®¼b¯¼b¥¼b¨¼b°¼b±¼b£¼b¦¼bõ¼bø¼b ¼b¡¼b¼b ¼bÚ¼bÛ¼b¼b¼b¼b¼b¼b¼b¼b¼b©½b¬½bï»bò»bå»bè»bÛ½bÞ½bÑ¼bÔ¼b¬½b­½bÕ»bØ»bÉ»bÌ»bµ»b¸»b¯»b²»b¨»b©»b »b¡»b»b»bìºbíºbÔºbÕºbÂºbÃºb®ºb¯ºb¤ºb¥ºb ºb¡ºbºbºbî¹bï¹bâ¹bã¹bØ¹bÙ¹bÖ¹b×¹b§¡¹Ïg¤¹Íg¹Íg¹Ïg¹Ïg¹Íg¹Íg¹Ïg¹Ïg¹Ígã¹Ïgæ¹Íg¹Íg¹Ïg¹Ïg¹ÍgÈ¹ÍgÉ¹Ïgû¸Ïgþ¸Ígø¸Ígù¸Ïgö¸Íg÷¸Ïgô¸Ígõ¸ÏgºÏgºÍgÝ¸Ïgà¸ÍgÓ¸ÏgÖ¸ÍgÉºÏgÌºÍg¿¹ÏgÂ¹ÍgºÍgºÏgÃ¸ÏgÆ¸Íg·¸Ïgº¸Íg£¸Ïg¦¸Íg¸Ïg ¸Íg¸Íg¸Ïg¸Íg¸Ïgî·Ígï·ÏgÚ·ÍgÛ·ÏgÂ·ÍgÃ·Ïg°·Íg±·Ïg·Íg·Ïg·Íg·Ïg·Íg·Ïgò¶Ígó¶ÏgÜ¶ÍgÝ¶ÏgÐ¶ÍgÑ¶ÏgÆ¶ÍgÇ¶ÏgÄ¶ÍgÅ¶Ïg§¶m¶m¶m¶m¶m¶m¶m¶mÿµm¶mÑ¶mÔ¶müµmýµmùµmüµm¶¶m·¶méµmìµmæµmçµmäµmåµmâµmãµm·m·mËµmÎµmÁµmÄµm··mº·m­¶m°¶m·m·m±µm´µm¥µm¨µmµmµmµmµmµmµmü´mý´mÜ´mÝ´mÈ´mÉ´m°´m±´m´m´m´m´m´m´mü³mý³mà³má³mÊ³mË³m¾³m¿³m´³mµ³m²³m³³m§Ë»Î¹Æ¹Ç»½»À¹È¹É»»»¾¹»¹¸¹¹»µ»¸¹ò¹ó»¥»¨¹¢¹£» ¹¡»¹»Á»Ä¹»¹ý»¹ó»ö¹é»ì¹Ä¹Å»í»ð¹á»ä¹Í»Ð¹Ç»Ê¹À¹Á»¸¹¹»¹»¹»ì¹í»Ú¹Û»Æ¹Ç»¼¹½»¸¹¹»¹»¹»ú¹û»ð¹ñ»î¹ï»§¹õ
+¼ó
+´ó
+µõ
+«õ
+®ó
+¶ó
+·õ
+©õ
+¬ó
+ûõ
+þó
+¦ó
+§õ
+£õ
+¦ó
+àó
+áõ
+õ
+ó
+ó
+õ
+ó
+õ
+ó
+õ
+¯õ
+²ó
+õõ
+øó
+ëõ
+îó
+áõ
+äó
+×õ
+Úó
+²ó
+³õ
+Ûõ
+Þó
+Ïõ
+Òó
+»õ
+¾ó
+µõ
+¸ó
+®ó
+¯õ
+¦ó
+§õ
+ó
+õ
+òó
+óõ
+Úó
+Ûõ
+Èó
+Éõ
+´ó
+µõ
+ªó
+«õ
+¦ó
+§õ
+ó
+õ
+ôó
+õõ
+èó
+éõ
+Þó
+ßõ
+Üó
+Ýõ
+§§¯ª­¢­£¯¯­¤­¥¯¯­é¯ì­­¯¯­Î­Ï¯¯­þ­ÿ¯ü­ý¯ú­û¯¯ ­ã¯æ­Ù¯Ü­Ï¯Ò­Å¯È­ ­¡¯É¯Ì­½¯À­©¯¬­£¯¦­­¯­¯ô­õ¯à­á¯È­É¯¶­·¯¢­£¯­¯­¯ø­ù¯â­ã¯Ö­×¯Ì­Í¯Ê­Ë¯§éççééççééç×éÚççéÿéç¼ç½éïéòçìçíéêçëéèçéééçÑéÔçÇéÊç½éÀç³é¶ççé·éºç«é®çéçéççéçéâçãéÎçÏé¶ç·é¤ç¥éçéçéçéæççéÐçÑéÄçÅéºç»é¸ç¹é§£¡þ¡ÿ£õ£ø¡¡£ó£ö¡Å£È¡ð¡ñ£í£ð¡ª¡«£Ý£à¡Ú¡Û£Ø¡Ù£Ö¡×£ù£ü¡¿£Â¡µ£¸¡«£®¡¡£¤¡ü¡ý£¥£¨¡£¡£¡ÿ£¡ø¡ù£ð¡ñ£Ð¡Ñ£¼¡½£¤¡¥£¡£þ¡ÿ£ô¡õ£ð¡ñ£Ô¡Õ£¾¡¿£²¡³£¨¡©£¦¡§£§ñÝ ôÛ ìÛ íÝ ãÝ æÛ îÛ ïÝ áÝ äÛ ³Ý ¶Û ÞÛ ßÝ ÛÝ ÞÛ Û Ý ËÝ ÎÛ ÈÛ ÉÝ ÆÛ ÇÝ ÄÛ ÅÝ çÝ êÛ ­Ý °Û £Ý ¦Û Ý Û Ý Û êÛ ëÝ Ý Û Ý Û óÝ öÛ íÝ ðÛ æÛ çÝ ÞÛ ßÝ ¾Û ¿Ý ªÛ «Ý Û Ý Û Ý ìÛ íÝ âÛ ãÝ ÞÛ ßÝ ÂÛ ÃÝ ¬Û ­Ý  Û ¡Ý Û Ý Û Ý §ß&â&Ú&Û&Ñ&Ô&Ü&Ý&Ï&Ò&¡&¤&Ì&Í&É&Ì&&&¹&¼&¶&·&´&µ&²&³&Õ&Ø&&&&&&&ý&&Ø&Ù&&&õ&ø&á&ä&Û&Þ&Ô&Õ&Ì&Í&¬&­&&&&&î&ï&Ú&Û&Ð&Ñ&Ì&Í&°&±&&&&&&&&&§ÍÑ+ÐÏ+ÈÏ+ÉÑ+¿Ñ+ÂÏ+ÊÏ+ËÑ+½Ñ+ÀÏ+Ñ+Ï+ºÏ+»Ñ+·Ñ+ºÏ+ôÏ+õÑ+§Ñ+ªÏ+¤Ï+¥Ñ+¢Ï+£Ñ+ Ï+¡Ñ+ÃÑ+ÆÏ+Ñ+Ï+ÿÑ+Ï+õÑ+øÏ+ëÑ+îÏ+ÆÏ+ÇÑ+ïÑ+òÏ+ãÑ+æÏ+ÏÑ+ÒÏ+ÉÑ+ÌÏ+ÂÏ+ÃÑ+ºÏ+»Ñ+Ï+Ñ+Ï+Ñ+îÏ+ïÑ+ÜÏ+ÝÑ+ÈÏ+ÉÑ+¾Ï+¿Ñ+ºÏ+»Ñ+Ï+Ñ+Ï+Ñ+üÏ+ýÑ+òÏ+óÑ+ðÏ+ñÑ+§»1¾1¶1·1­1°1¸1¹1«1®1ý11¨1©1¥1¨1â1ã111111111±1´1÷1ú1í1ð1ã1æ1Ù1Ü1´1µ1Ý1à1Ñ1Ô1½1À1·1º1°1±1¨1©111ôÿ1õÿ1Üÿ1Ýÿ1Êÿ1Ëÿ1¶ÿ1·ÿ1¬ÿ1­ÿ1¨ÿ1©ÿ1ÿ1ÿ1öþ1÷þ1êþ1ëþ1àþ1áþ1Þþ1ßþ1§©þÅ6¬þÃ6¤þÃ6¥þÅ6þÅ6þÃ6¦þÃ6§þÅ6þÅ6þÃ6ëþÅ6îþÃ6þÃ6þÅ6þÅ6þÃ6ÐþÃ6ÑþÅ6þÅ6þÃ6þÃ6þÅ6þýÃ6ÿýÅ6üýÃ6ýýÅ6ÿÅ6¢ÿÃ6åýÅ6èýÃ6ÛýÅ6ÞýÃ6ÑÿÅ6ÔÿÃ6ÇþÅ6ÊþÃ6¢ÿÃ6£ÿÅ6ËýÅ6ÎýÃ6¿ýÅ6ÂýÃ6«ýÅ6®ýÃ6¥ýÅ6¨ýÃ6ýÃ6ýÅ6ýÃ6ýÅ6öüÃ6÷üÅ6âüÃ6ãüÅ6ÊüÃ6ËüÅ6¸üÃ6¹üÅ6¤üÃ6¥üÅ6üÃ6üÅ6üÃ6üÅ6úûÃ6ûûÅ6äûÃ6åûÅ6ØûÃ6ÙûÅ6ÎûÃ6ÏûÅ6ÌûÃ6ÍûÅ6§ûÿ;ûý;ûý;ûÿ;ûÿ;ûý;ûý;ûÿ;ûÿ;ûý;Ùûÿ;Üûý;ûý;ûÿ;ûÿ;ûý;¾ûý;¿ûÿ;ñúÿ;ôúý;îúý;ïúÿ;ìúý;íúÿ;êúý;ëúÿ;üÿ;üý;Óúÿ;Öúý;Éúÿ;Ìúý;¿üÿ;Âüý;µûÿ;¸ûý;üý;üÿ;¹úÿ;¼úý;­úÿ;°úý;úÿ;úý;úÿ;úý;úý;úÿ;úý;úÿ;äùý;åùÿ;Ðùý;Ñùÿ;¸ùý;¹ùÿ;¦ùý;§ùÿ;ùý;ùÿ;ùý;ùÿ;ùý;ùÿ;èøý;éøÿ;Òøý;Óøÿ;Æøý;Çøÿ;¼øý;½øÿ;ºøý;»øÿ;§ø¹Aø·Aø·Aø¹A÷÷¹Aú÷·Aø·Aø¹Aõ÷¹Aø÷·AÇø¹AÊø·Aò÷·Aó÷¹Aï÷¹Aò÷·A¬ø·A­ø¹Aß÷¹Aâ÷·AÜ÷·AÝ÷¹AÚ÷·AÛ÷¹AØ÷·AÙ÷¹Aûø¹Aþø·AÁ÷¹AÄ÷·A·÷¹Aº÷·A­ù¹A°ù·A£ø¹A¦ø·Aþø·Aÿø¹A§÷¹Aª÷·A÷¹A÷·A÷¹A÷·A÷¹A÷·Aúö·Aûö¹Aòö·Aóö¹AÒö·AÓö¹A¾ö·A¿ö¹A¦ö·A§ö¹Aö·Aö¹Aö·Aö¹Aöõ·A÷õ¹Aòõ·Aóõ¹AÖõ·A×õ¹AÀõ·AÁõ¹A´õ·Aµõ¹Aªõ·A«õ¹A¨õ·A©õ¹A§óôóFöôñFîôñFïôóFåôóFèôñFðôñFñôóFãôóFæôñFµõóF¸õñFàôñFáôóFÝôóFàôñFõñFõóFÍôóFÐôñFÊôñFËôóFÈôñFÉôóFÆôñFÇôóFéõóFìõñF¯ôóF²ôñF¥ôóF¨ôñFöóFöñFõóFõñFìõñFíõóFôóFôñFôóFôñFõóóFøóñFïóóFòóñFèóñFéóóFàóñFáóóFÀóñFÁóóF¬óñF­óóFóñFóóFóñFóóFîòñFïòóFäòñFåòóFàòñFáòóFÄòñFÅòóF®òñF¯òóF¢òñF£òóFòñFòóFòñFòóF§áñ­Läñ«LÜñ«LÝñ­LÓñ­LÖñ«LÞñ«Lßñ­LÑñ­LÔñ«L£ò­L¦ò«LÎñ«LÏñ­LËñ­LÎñ«Lò«Lò­L»ñ­L¾ñ«L¸ñ«L¹ñ­L¶ñ«L·ñ­L´ñ«Lµñ­L×ò­LÚò«Lñ­L ñ«Lñ­Lñ«Ló­Ló«Lÿñ­Lò«LÚò«LÛò­Lñ­Lñ«L÷ð­Lúð«Lãð­Læð«LÝð­Làð«LÖð«L×ð­LÎð«LÏð­L®ð«L¯ð­Lð«Lð­Lð«Lð­Lðï«Lñï­LÜï«LÝï­LÒï«LÓï­LÎï«LÏï­L²ï«L³ï­Lï«Lï­Lï«Lï­Lï«Lï­Lï«Lï­L§ÏîçQÒîåQÊîåQËîçQÁîçQÄîåQÌîåQÍîçQ¿îçQÂîåQïçQïåQ¼îåQ½îçQ¹îçQ¼îåQöîåQ÷îçQ©îçQ¬îåQ¦îåQ§îçQ¤îåQ¥îçQ¢îåQ£îçQÅïçQÈïåQîçQîåQîçQîåQ÷ïçQúïåQíîçQðîåQÈïåQÉïçQñíçQôíåQåíçQèíåQÑíçQÔíåQËíçQÎíåQÄíåQÅíçQ¼íåQ½íçQíåQíçQíåQíçQðìåQñìçQÞìåQßìçQÊìåQËìçQÀìåQÁìçQ¼ìåQ½ìçQ ìåQ¡ìçQìåQìçQþëåQÿëçQôëåQõëçQòëåQóëçQ§½ë¡WÀëW¸ëW¹ë¡W¯ë¡W²ëWºëW»ë¡W­ë¡W°ëWÿë¡WìWªëW«ë¡W§ë¡WªëWäëWåë¡Wë¡WëWëWë¡WëWë¡WëWë¡W³ì¡W¶ìWùê¡WüêWïê¡WòêWåì¡WèìWÛë¡WÞëW¶ìW·ì¡Wßê¡WâêWÓê¡WÖêW¿ê¡WÂêW¹ê¡W¼êW²êW³ê¡WªêW«ê¡WêWê¡WöéW÷é¡WÞéWßé¡WÌéWÍé¡W¸éW¹é¡W®éW¯é¡WªéW«é¡WéWé¡WøèWùè¡WìèWíè¡WâèWãè¡WàèWáè¡W§«èÛ\®èÙ\¦èÙ\§èÛ\èÛ\ èÙ\¨èÙ\©èÛ\èÛ\èÙ\íèÛ\ðèÙ\èÙ\èÛ\èÛ\èÙ\ÒèÙ\ÓèÛ\èÛ\èÙ\èÙ\èÛ\èÙ\èÛ\þçÙ\ÿçÛ\¡éÛ\¤éÙ\ççÛ\êçÙ\ÝçÛ\àçÙ\ÓéÛ\ÖéÙ\ÉèÛ\ÌèÙ\¤éÙ\¥éÛ\ÍçÛ\ÐçÙ\ÁçÛ\ÄçÙ\­çÛ\°çÙ\§çÛ\ªçÙ\ çÙ\¡çÛ\çÙ\çÛ\øæÙ\ùæÛ\äæÙ\åæÛ\ÌæÙ\ÍæÛ\ºæÙ\»æÛ\¦æÙ\§æÛ\æÙ\æÛ\æÙ\æÛ\üåÙ\ýåÛ\æåÙ\çåÛ\ÚåÙ\ÛåÛ\ÐåÙ\ÑåÛ\ÎåÙ\ÏåÛ\§åbåbåbåbåbåbåbåbåbåbÛåbÞåbåbåbåbåbÀåbÁåbóäböäbðäbñäbîäbïäbìäbíäbæbæbÕäbØäbËäbÎäbÁæbÄæb·åbºåbæbæb»äb¾äb¯äb²äbäbäbäbäbäbäbäbäbæãbçãbÒãbÓãbºãb»ãb¨ãb©ãbãbãbãbãbãbãbêâbëâbÔâbÕâbÈâbÉâb¾âb¿âb¼âb½âb§âÏgâÍgâÍgâÏgùáÏgüáÍgâÍgâÏg÷áÏgúáÍgÉâÏgÌâÍgôáÍgõáÏgñáÏgôáÍg®âÍg¯âÏgááÏgäáÍgÞáÍgßáÏgÜáÍgÝáÏgÚáÍgÛáÏgýâÏgãÍgÃáÏgÆáÍg¹áÏg¼áÍg¯ãÏg²ãÍg¥âÏg¨âÍgãÍgãÏg©áÏg¬áÍgáÏg áÍgáÏgáÍgáÏgáÍgüàÍgýàÏgôàÍgõàÏgÔàÍgÕàÏgÀàÍgÁàÏg¨àÍg©àÏgàÍgàÏgàÍgàÏgøßÍgùßÏgôßÍgõßÏgØßÍgÙßÏgÂßÍgÃßÏg¶ßÍg·ßÏg¬ßÍg­ßÏgªßÍg«ßÏg§Á»Á¹Á¹Á»ûÀ»þÀ¹Á¹Á»ùÀ»üÀ¹ËÁ»ÎÁ¹öÀ¹÷À»óÀ»öÀ¹°Á¹±Á»ãÀ»æÀ¹àÀ¹áÀ»ÞÀ¹ßÀ»ÜÀ¹ÝÀ»ÿÁ»Â¹ÅÀ»ÈÀ¹»À»¾À¹±Â»´Â¹§Á»ªÁ¹Â¹Â»«À»®À¹À»¢À¹À»À¹À»À¹þ¿¹ÿ¿»ö¿¹÷¿»Ö¿¹×¿»Â¿¹Ã¿»ª¿¹«¿»¿¹¿»¿¹¿»ú¾¹û¾»ö¾¹÷¾»Ú¾¹Û¾»Ä¾¹Å¾»¸¾¹¹¾»®¾¹¯¾»¬¾¹­¾»§÷½õ
+ú½ó
+ò½ó
+ó½õ
+é½õ
+ì½ó
+ô½ó
+õ½õ
+ç½õ
+ê½ó
+¹¾õ
+¼¾ó
+ä½ó
+å½õ
+á½õ
+ä½ó
+¾ó
+¾õ
+Ñ½õ
+Ô½ó
+Î½ó
+Ï½õ
+Ì½ó
+Í½õ
+Ê½ó
+Ë½õ
+í¾õ
+ð¾ó
+³½õ
+¶½ó
+©½õ
+¬½ó
+¿õ
+¢¿ó
+¾õ
+¾ó
+ð¾ó
+ñ¾õ
+½õ
+½ó
+½õ
+½ó
+ù¼õ
+ü¼ó
+ó¼õ
+ö¼ó
+ì¼ó
+í¼õ
+ä¼ó
+å¼õ
+Ä¼ó
+Å¼õ
+°¼ó
+±¼õ
+¼ó
+¼õ
+¼ó
+¼õ
+ò»ó
+ó»õ
+è»ó
+é»õ
+ä»ó
+å»õ
+È»ó
+É»õ
+²»ó
+³»õ
+¦»ó
+§»õ
+»ó
+»õ
+»ó
+»õ
+§åº¯èº­àº­áº¯×º¯Úº­âº­ãº¯Õº¯Øº­§»¯ª»­Òº­Óº¯Ïº¯Òº­»­»¯¿º¯Âº­¼º­½º¯ºº­»º¯¸º­¹º¯Û»¯Þ»­¡º¯¤º­º¯º­¼¯¼­»¯»­Þ»­ß»¯º¯º­û¹¯þ¹­ç¹¯ê¹­á¹¯ä¹­Ú¹­Û¹¯Ò¹­Ó¹¯²¹­³¹¯¹­¹¯¹­¹¯ô¸­õ¸¯à¸­á¸¯Ö¸­×¸¯Ò¸­Ó¸¯¶¸­·¸¯ ¸­¡¸¯¸­¸¯¸­¸¯¸­¸¯§Ó·éÖ·çÎ·çÏ·éÅ·éÈ·çÐ·çÑ·éÃ·éÆ·ç¸é¸çÀ·çÁ·é½·éÀ·çú·çû·é­·é°·çª·ç«·é¨·ç©·é¦·ç§·éÉ¸éÌ¸ç·é·ç·é·çû¸éþ¸çñ·éô·çÌ¸çÍ¸éõ¶éø¶çé¶éì¶çÕ¶éØ¶çÏ¶éÒ¶çÈ¶çÉ¶éÀ¶çÁ¶é ¶ç¡¶é¶ç¶éôµçõµéâµçãµéÎµçÏµéÄµçÅµéÀµçÁµé¤µç¥µéµçµéµçµéø´çù´éö´ç÷´é§Á´£Ä´¡¼´¡½´£³´£¶´¡¾´¡¿´£±´£´´¡µ£µ¡®´¡¯´£«´£®´¡è´¡é´£´£´¡´¡´£´¡´£´¡´£·µ£ºµ¡ý³£´¡ó³£ö³¡éµ£ìµ¡ß´£â´¡ºµ¡»µ£ã³£æ³¡×³£Ú³¡Ã³£Æ³¡½³£À³¡¶³¡·³£®³¡¯³£³¡³£ú²¡û²£â²¡ã²£Ð²¡Ñ²£¼²¡½²£²²¡³²£®²¡¯²£²¡²£ü±¡ý±£ð±¡ñ±£æ±¡ç±£ä±¡å±£§¯±Ý ²±Û ª±Û «±Ý ¡±Ý ¤±Û ¬±Û ­±Ý ±Ý ¢±Û ñ±Ý ô±Û ±Û ±Ý ±Ý ±Û Ö±Û ×±Ý ±Ý ±Û ±Û ±Ý ±Û ±Ý ±Û ±Ý ¥²Ý ¨²Û ë°Ý î°Û á°Ý ä°Û ×²Ý Ú²Û Í±Ý Ð±Û ¨²Û ©²Ý Ñ°Ý Ô°Û Å°Ý È°Û ±°Ý ´°Û «°Ý ®°Û ¤°Û ¥°Ý °Û °Ý ü¯Û ý¯Ý è¯Û é¯Ý Ð¯Û Ñ¯Ý ¾¯Û ¿¯Ý ª¯Û «¯Ý  ¯Û ¡¯Ý ¯Û ¯Ý ¯Û ¯Ý ê®Û ë®Ý Þ®Û ß®Ý Ô®Û Õ®Ý Ò®Û Ó®Ý §®& ®&®&®&®&®&®&®&®&®&ß®&â®&®&®&®&®&Ä®&Å®&÷­&ú­&ô­&õ­&ò­&ó­&ð­&ñ­&¯&¯&Ù­&Ü­&Ï­&Ò­&Å¯&È¯&»®&¾®&¯&¯&¿­&Â­&³­&¶­&­&¢­&­&­&­&­&­&­&ê¬&ë¬&Ö¬&×¬&¾¬&¿¬&¬¬&­¬&¬&¬&¬&¬&¬&¬&î«&ï«&Ø«&Ù«&Ì«&Í«&Â«&Ã«&À«&Á«&§«Ñ+«Ï+«Ï+«Ñ+ýªÑ+«Ï+«Ï+«Ñ+ûªÑ+þªÏ+Í«Ñ+Ð«Ï+øªÏ+ùªÑ+õªÑ+øªÏ+²«Ï+³«Ñ+åªÑ+èªÏ+âªÏ+ãªÑ+àªÏ+áªÑ+ÞªÏ+ßªÑ+¬Ñ+¬Ï+ÇªÑ+ÊªÏ+½ªÑ+ÀªÏ+³¬Ñ+¶¬Ï+©«Ñ+¬«Ï+¬Ï+¬Ñ+­ªÑ+°ªÏ+¡ªÑ+¤ªÏ+ªÑ+ªÏ+ªÑ+ªÏ+ªÏ+ªÑ+ø©Ï+ù©Ñ+Ø©Ï+Ù©Ñ+Ä©Ï+Å©Ñ+¬©Ï+­©Ñ+©Ï+©Ñ+©Ï+©Ñ+ü¨Ï+ý¨Ñ+ø¨Ï+ù¨Ñ+Ü¨Ï+Ý¨Ñ+Æ¨Ï+Ç¨Ñ+º¨Ï+»¨Ñ+°¨Ï+±¨Ñ+®¨Ï+¯¨Ñ+§ù§1ü§1ô§1õ§1ë§1î§1ö§1÷§1é§1ì§1»¨1¾¨1æ§1ç§1ã§1æ§1 ¨1¡¨1Ó§1Ö§1Ð§1Ñ§1Î§1Ï§1Ì§1Í§1ï¨1ò¨1µ§1¸§1«§1®§1¡©1¤©1¨1¨1ò¨1ó¨1§1§1§1§1û¦1þ¦1õ¦1ø¦1î¦1ï¦1æ¦1ç¦1Æ¦1Ç¦1²¦1³¦1¦1¦1¦1¦1ô¥1õ¥1ê¥1ë¥1æ¥1ç¥1Ê¥1Ë¥1´¥1µ¥1¨¥1©¥1¥1¥1¥1¥1§ç¤Å6ê¤Ã6â¤Ã6ã¤Å6Ù¤Å6Ü¤Ã6ä¤Ã6å¤Å6×¤Å6Ú¤Ã6©¥Å6¬¥Ã6Ô¤Ã6Õ¤Å6Ñ¤Å6Ô¤Ã6¥Ã6¥Å6Á¤Å6Ä¤Ã6¾¤Ã6¿¤Å6¼¤Ã6½¤Å6º¤Ã6»¤Å6Ý¥Å6à¥Ã6£¤Å6¦¤Ã6¤Å6¤Ã6¦Å6¦Ã6¥Å6¥Ã6à¥Ã6á¥Å6¤Å6¤Ã6ý£Å6¤Ã6é£Å6ì£Ã6ã£Å6æ£Ã6Ü£Ã6Ý£Å6Ô£Ã6Õ£Å6´£Ã6µ£Å6 £Ã6¡£Å6£Ã6£Å6ö¢Ã6÷¢Å6â¢Ã6ã¢Å6Ø¢Ã6Ù¢Å6Ô¢Ã6Õ¢Å6¸¢Ã6¹¢Å6¢¢Ã6£¢Å6¢Ã6¢Å6¢Ã6¢Å6¢Ã6¢Å6§Õ¡ÿ;Ø¡ý;Ð¡ý;Ñ¡ÿ;Ç¡ÿ;Ê¡ý;Ò¡ý;Ó¡ÿ;Å¡ÿ;È¡ý;¢ÿ;¢ý;Â¡ý;Ã¡ÿ;¿¡ÿ;Â¡ý;ü¡ý;ý¡ÿ;¯¡ÿ;²¡ý;¬¡ý;­¡ÿ;ª¡ý;«¡ÿ;¨¡ý;©¡ÿ;Ë¢ÿ;Î¢ý;¡ÿ;¡ý;¡ÿ;¡ý;ý¢ÿ;£ý;ó¡ÿ;ö¡ý;Î¢ý;Ï¢ÿ;÷ ÿ;ú ý;ë ÿ;î ý;× ÿ;Ú ý;Ñ ÿ;Ô ý;Ê ý;Ë ÿ;Â ý;Ã ÿ;¢ ý;£ ÿ; ý; ÿ;öý;÷ÿ;äý;åÿ;Ðý;Ñÿ;Æý;Çÿ;Âý;Ãÿ;¦ý;§ÿ;ý;ÿ;ý;ÿ;úý;ûÿ;øý;ùÿ;§Ã¹AÆ·A¾·A¿¹Aµ¹A¸·AÀ·AÁ¹A³¹A¶·A¹A·A°·A±¹A­¹A°·Aê·Aë¹A¹A ·A·A¹A·A¹A·A¹A¹¹A¼·Aÿ¹A·Aõ¹Aø·Aë¹Aî·Aá¹Aä·A¼·A½¹Aå¹Aè·AÙ¹AÜ·AÅ¹AÈ·A¿¹AÂ·A¸·A¹¹A°·A±¹A·A¹Aü·Aý¹Aä·Aå¹AÒ·AÓ¹A¾·A¿¹A´·Aµ¹A°·A±¹A·A¹Aþ·Aÿ¹Aò·Aó¹Aè·Aé¹Aæ·Aç¹A§±óF´ñF¬ñF­óF£óF¦ñF®ñF¯óF¡óF¤ñFóóFöñFñFóFóFñFØñFÙóFóFñFñFóFñFóFñFóF§óFªñFíóFðñFãóFæñFÙóFÜñFÏóFÒñFªñF«óFÓóFÖñFÇóFÊñF³óF¶ñF­óF°ñF¦ñF§óFñFóFþñFÿóFêñFëóFÒñFÓóFÀñFÁóF¬ñF­óF¢ñF£óFñFóFñFóFìñFíóFàñFáóFÖñF×óFÔñFÕóF§­L¢«L«L­L­L«L«L­L­L«Lá­Lä«L«L­L­L«LÆ«LÇ­Lù­Lü«Lö«L÷­Lô«Lõ­Lò«Ló­L­L«LÛ­LÞ«LÑ­LÔ«LÇ­LÊ«L½­LÀ«L«L­LÁ­LÄ«Lµ­L¸«L¡­L¤«L­L«L«L­L«L­Lì«Lí­LØ«LÙ­LÀ«LÁ­L®«L¯­L«L­L«L­L«L­Lð«Lñ­LÚ«LÛ­LÎ«LÏ­LÄ«LÅ­LÂ«LÃ­L§çQåQåQçQÿçQåQåQçQýçQåQÏçQÒåQúåQûçQ÷çQúåQ´åQµçQççQêåQäåQåçQâåQãçQàåQáçQçQåQÉçQÌåQ¿çQÂåQµçQ¸åQ«çQ®åQåQçQ¯çQ²åQ£çQ¦åQçQåQçQåQåQçQúåQûçQÚåQÛçQÆåQÇçQ®åQ¯çQåQçQåQçQþåQÿçQúåQûçQÞåQßçQÈåQÉçQ¼åQ½çQ²åQ³çQ°åQ±çQ§û¡WþWöW÷¡Wí¡WðWøWù¡Wë¡WîW½¡WÀWèWé¡Wå¡WèW¢W£¡WÕ¡WØWÒWÓ¡WÐWÑ¡WÎWÏ¡Wñ¡WôW·¡WºW­¡W°W£¡W¦W¡WWôWõ¡W¡W W¡WWý¡WW÷¡WúWðWñ¡WèWé¡WÈWÉ¡W´Wµ¡WW¡WW¡WöW÷¡WìWí¡WèWé¡WÌWÍ¡W¶W·¡WªW«¡W W¡¡WW¡W§éÛ\ìÙ\äÙ\åÛ\ÛÛ\ÞÙ\æÙ\çÛ\ÙÛ\ÜÙ\«Û\®Ù\ÖÙ\×Û\ÓÛ\ÖÙ\Ù\Û\ÃÛ\ÆÙ\ÀÙ\ÁÛ\¾Ù\¿Û\¼Ù\½Û\ßÛ\âÙ\¥Û\¨Ù\Û\Ù\Û\Ù\Û\Ù\âÙ\ãÛ\Û\Ù\ÿÛ\Ù\ëÛ\îÙ\åÛ\èÙ\ÞÙ\ßÛ\ÖÙ\×Û\¶Ù\·Û\¢Ù\£Û\Ù\Û\øÙ\ùÛ\äÙ\åÛ\ÚÙ\ÛÛ\ÖÙ\×Û\ºÙ\»Û\¤Ù\¥Û\Ù\Û\Ù\Û\Ù\Û\§×bÚbÒbÓbÉbÌbÔbÕbÇbÊbbbÄbÅbÁbÄbþbÿb±b´b®b¯b¬b­bªb«bÍbÐbbbbbÿbbõbøbÐbÑbùbübíbðbÙbÜbÓbÖbÌbÍbÄbÅb¤b¥bbbøbùbæbçbÒbÓbÈbÉbÄbÅb¨b©bbbbbübýbúbûb§å»¢å¹å¹å»å»å¹å¹å»å»å¹áå»äå¹å¹å»å»å¹Æå¹Çå»ùä»üä¹öä¹÷ä»ôä¹õä»òä¹óä»æ»æ¹Ûä»Þä¹Ñä»Ôä¹Çæ»Êæ¹½å»Àå¹æ¹æ»Áä»Ää¹µä»¸ä¹¡ä»¤ä¹ä»ä¹ä¹ä»ä¹ä»ìã¹íã»Øã¹Ùã»Àã¹Áã»®ã¹¯ã»ã¹ã»ã¹ã»ã¹ã»ðâ¹ñâ»Úâ¹Ûâ»Îâ¹Ïâ»Äâ¹Åâ»Ââ¹Ãâ»§âõ
+âó
+âó
+âõ
+ÿáõ
+âó
+âó
+âõ
+ýáõ
+âó
+Ïâõ
+Òâó
+úáó
+ûáõ
+÷áõ
+úáó
+´âó
+µâõ
+çáõ
+êáó
+äáó
+åáõ
+âáó
+ãáõ
+àáó
+ááõ
+ãõ
+ãó
+Éáõ
+Ìáó
+¿áõ
+Âáó
+µãõ
+¸ãó
+«âõ
+®âó
+ãó
+ãõ
+¯áõ
+²áó
+£áõ
+¦áó
+áõ
+áó
+áõ
+áó
+áó
+áõ
+úàó
+ûàõ
+Úàó
+Ûàõ
+Æàó
+Çàõ
+®àó
+¯àõ
+àó
+àõ
+àó
+àõ
+þßó
+ÿßõ
+úßó
+ûßõ
+Þßó
+ßßõ
+Èßó
+Éßõ
+¼ßó
+½ßõ
+²ßó
+³ßõ
+°ßó
+±ßõ
+§ûÞ¯þÞ­öÞ­÷Þ¯íÞ¯ðÞ­øÞ­ùÞ¯ëÞ¯îÞ­½ß¯Àß­èÞ­éÞ¯åÞ¯èÞ­¢ß­£ß¯ÕÞ¯ØÞ­ÒÞ­ÓÞ¯ÐÞ­ÑÞ¯ÎÞ­ÏÞ¯ñß¯ôß­·Þ¯ºÞ­­Þ¯°Þ­£à¯¦à­ß¯ß­ôß­õß¯Þ¯ Þ­Þ¯Þ­ýÝ¯Þ­÷Ý¯úÝ­ðÝ­ñÝ¯èÝ­éÝ¯ÈÝ­ÉÝ¯´Ý­µÝ¯Ý­Ý¯Ý­Ý¯öÜ­÷Ü¯ìÜ­íÜ¯èÜ­éÜ¯ÌÜ­ÍÜ¯¶Ü­·Ü¯ªÜ­«Ü¯ Ü­¡Ü¯Ü­Ü¯§éÛéìÛçäÛçåÛéÛÛéÞÛçæÛççÛéÙÛéÜÛç«Üé®ÜçÖÛç×ÛéÓÛéÖÛçÜçÜéÃÛéÆÛçÀÛçÁÛé¾Ûç¿Ûé¼Ûç½ÛéßÜéâÜç¥Ûé¨ÛçÛéÛçÝéÝçÜéÜçâÜçãÜéÛéÛçÿÚéÛçëÚéîÚçåÚéèÚçÞÚçßÚéÖÚç×Úé¶Úç·Úé¢Úç£ÚéÚçÚéøÙçùÙéäÙçåÙéÚÙçÛÙéÖÙç×ÙéºÙç»Ùé¤Ùç¥ÙéÙçÙéÙçÙéÙçÙé§×Ø£ÚØ¡ÒØ¡ÓØ£ÉØ£ÌØ¡ÔØ¡ÕØ£ÇØ£ÊØ¡Ù£Ù¡ÄØ¡ÅØ£ÁØ£ÄØ¡þØ¡ÿØ£±Ø£´Ø¡®Ø¡¯Ø£¬Ø¡­Ø£ªØ¡«Ø£ÍÙ£ÐÙ¡Ø£Ø¡Ø£Ø¡ÿÙ£Ú¡õØ£øØ¡ÐÙ¡ÑÙ£ù×£ü×¡í×£ð×¡Ù×£Ü×¡Ó×£Ö×¡Ì×¡Í×£Ä×¡Å×£¤×¡¥×£×¡×£øÖ¡ùÖ£æÖ¡çÖ£ÒÖ¡ÓÖ£ÈÖ¡ÉÖ£ÄÖ¡ÅÖ£¨Ö¡©Ö£Ö¡Ö£Ö¡Ö£üÕ¡ýÕ£úÕ¡ûÕ£§ÅÕÝ ÈÕÛ ÀÕÛ ÁÕÝ ·ÕÝ ºÕÛ ÂÕÛ ÃÕÝ µÕÝ ¸ÕÛ ÖÝ ÖÛ ²ÕÛ ³ÕÝ ¯ÕÝ ²ÕÛ ìÕÛ íÕÝ ÕÝ ¢ÕÛ ÕÛ ÕÝ ÕÛ ÕÝ ÕÛ ÕÝ »ÖÝ ¾ÖÛ ÕÝ ÕÛ ÷ÔÝ úÔÛ íÖÝ ðÖÛ ãÕÝ æÕÛ ¾ÖÛ ¿ÖÝ çÔÝ êÔÛ ÛÔÝ ÞÔÛ ÇÔÝ ÊÔÛ ÁÔÝ ÄÔÛ ºÔÛ »ÔÝ ²ÔÛ ³ÔÝ ÔÛ ÔÝ þÓÛ ÿÓÝ æÓÛ çÓÝ ÔÓÛ ÕÓÝ ÀÓÛ ÁÓÝ ¶ÓÛ ·ÓÝ ²ÓÛ ³ÓÝ ÓÛ ÓÝ ÓÛ ÓÝ ôÒÛ õÒÝ êÒÛ ëÒÝ èÒÛ éÒÝ §³Ò&¶Ò&®Ò&¯Ò&¥Ò&¨Ò&°Ò&±Ò&£Ò&¦Ò&õÒ&øÒ& Ò&¡Ò&Ò& Ò&ÚÒ&ÛÒ&Ò&Ò&Ò&Ò&Ò&Ò&Ò&Ò&©Ó&¬Ó&ïÑ&òÑ&åÑ&èÑ&ÛÓ&ÞÓ&ÑÒ&ÔÒ&¬Ó&­Ó&ÕÑ&ØÑ&ÉÑ&ÌÑ&µÑ&¸Ñ&¯Ñ&²Ñ&¨Ñ&©Ñ& Ñ&¡Ñ&Ñ&Ñ&ìÐ&íÐ&ÔÐ&ÕÐ&ÂÐ&ÃÐ&®Ð&¯Ð&¤Ð&¥Ð& Ð&¡Ð&Ð&Ð&îÏ&ïÏ&âÏ&ãÏ&ØÏ&ÙÏ&ÖÏ&×Ï&§¡ÏÑ+¤ÏÏ+ÏÏ+ÏÑ+ÏÑ+ÏÏ+ÏÏ+ÏÑ+ÏÑ+ÏÏ+ãÏÑ+æÏÏ+ÏÏ+ÏÑ+ÏÑ+ÏÏ+ÈÏÏ+ÉÏÑ+ûÎÑ+þÎÏ+øÎÏ+ùÎÑ+öÎÏ+÷ÎÑ+ôÎÏ+õÎÑ+ÐÑ+ÐÏ+ÝÎÑ+àÎÏ+ÓÎÑ+ÖÎÏ+ÉÐÑ+ÌÐÏ+¿ÏÑ+ÂÏÏ+ÐÏ+ÐÑ+ÃÎÑ+ÆÎÏ+·ÎÑ+ºÎÏ+£ÎÑ+¦ÎÏ+ÎÑ+ ÎÏ+ÎÏ+ÎÑ+ÎÏ+ÎÑ+îÍÏ+ïÍÑ+ÚÍÏ+ÛÍÑ+ÂÍÏ+ÃÍÑ+°ÍÏ+±ÍÑ+ÍÏ+ÍÑ+ÍÏ+ÍÑ+ÍÏ+ÍÑ+òÌÏ+óÌÑ+ÜÌÏ+ÝÌÑ+ÐÌÏ+ÑÌÑ+ÆÌÏ+ÇÌÑ+ÄÌÏ+ÅÌÑ+§Ì1Ì1Ì1Ì1Ì1Ì1Ì1Ì1ÿË1Ì1ÑÌ1ÔÌ1üË1ýË1ùË1üË1¶Ì1·Ì1éË1ìË1æË1çË1äË1åË1âË1ãË1Í1Í1ËË1ÎË1ÁË1ÄË1·Í1ºÍ1­Ì1°Ì1Í1Í1±Ë1´Ë1¥Ë1¨Ë1Ë1Ë1Ë1Ë1Ë1Ë1üÊ1ýÊ1ÜÊ1ÝÊ1ÈÊ1ÉÊ1°Ê1±Ê1Ê1Ê1Ê1Ê1Ê1Ê1üÉ1ýÉ1àÉ1áÉ1ÊÉ1ËÉ1¾É1¿É1´É1µÉ1²É1³É1§ýÈÅ6ÉÃ6øÈÃ6ùÈÅ6ïÈÅ6òÈÃ6úÈÃ6ûÈÅ6íÈÅ6ðÈÃ6¿ÉÅ6ÂÉÃ6êÈÃ6ëÈÅ6çÈÅ6êÈÃ6¤ÉÃ6¥ÉÅ6×ÈÅ6ÚÈÃ6ÔÈÃ6ÕÈÅ6ÒÈÃ6ÓÈÅ6ÐÈÃ6ÑÈÅ6óÉÅ6öÉÃ6¹ÈÅ6¼ÈÃ6¯ÈÅ6²ÈÃ6¥ÊÅ6¨ÊÃ6ÉÅ6ÉÃ6öÉÃ6÷ÉÅ6ÈÅ6¢ÈÃ6ÈÅ6ÈÃ6ÿÇÅ6ÈÃ6ùÇÅ6üÇÃ6òÇÃ6óÇÅ6êÇÃ6ëÇÅ6ÊÇÃ6ËÇÅ6¶ÇÃ6·ÇÅ6ÇÃ6ÇÅ6ÇÃ6ÇÅ6øÆÃ6ùÆÅ6îÆÃ6ïÆÅ6êÆÃ6ëÆÅ6ÎÆÃ6ÏÆÅ6¸ÆÃ6¹ÆÅ6¬ÆÃ6­ÆÅ6¢ÆÃ6£ÆÅ6 ÆÃ6¡ÆÅ6§ëÅÿ;îÅý;æÅý;çÅÿ;ÝÅÿ;àÅý;èÅý;éÅÿ;ÛÅÿ;ÞÅý;­Æÿ;°Æý;ØÅý;ÙÅÿ;ÕÅÿ;ØÅý;Æý;Æÿ;ÅÅÿ;ÈÅý;ÂÅý;ÃÅÿ;ÀÅý;ÁÅÿ;¾Åý;¿Åÿ;áÆÿ;äÆý;§Åÿ;ªÅý;Åÿ; Åý;Çÿ;Çý;Æÿ;Æý;äÆý;åÆÿ;Åÿ;Åý;Åÿ;Åý;íÄÿ;ðÄý;çÄÿ;êÄý;àÄý;áÄÿ;ØÄý;ÙÄÿ;¸Äý;¹Äÿ;¤Äý;¥Äÿ;Äý;Äÿ;úÃý;ûÃÿ;æÃý;çÃÿ;ÜÃý;ÝÃÿ;ØÃý;ÙÃÿ;¼Ãý;½Ãÿ;¦Ãý;§Ãÿ;Ãý;Ãÿ;Ãý;Ãÿ;Ãý;Ãÿ;§ÙÂ¹AÜÂ·AÔÂ·AÕÂ¹AËÂ¹AÎÂ·AÖÂ·A×Â¹AÉÂ¹AÌÂ·AÃ¹AÃ·AÆÂ·AÇÂ¹AÃÂ¹AÆÂ·AÃ·AÃ¹A³Â¹A¶Â·A°Â·A±Â¹A®Â·A¯Â¹A¬Â·A­Â¹AÏÃ¹AÒÃ·AÂ¹AÂ·AÂ¹AÂ·AÄ¹AÄ·A÷Â¹AúÂ·AÒÃ·AÓÃ¹AûÁ¹AþÁ·AïÁ¹AòÁ·AÛÁ¹AÞÁ·AÕÁ¹AØÁ·AÎÁ·AÏÁ¹AÆÁ·AÇÁ¹A¦Á·A§Á¹AÁ·AÁ¹AúÀ·AûÀ¹AèÀ·AéÀ¹AÔÀ·AÕÀ¹AÊÀ·AËÀ¹AÆÀ·AÇÀ¹AªÀ·A«À¹AÀ·AÀ¹AÀ·AÀ¹Aþ¿·Aÿ¿¹Aü¿·Aý¿¹A§Ç¿óFÊ¿ñFÂ¿ñFÃ¿óF¹¿óF¼¿ñFÄ¿ñFÅ¿óF·¿óFº¿ñFÀóFÀñF´¿ñFµ¿óF±¿óF´¿ñFî¿ñFï¿óF¡¿óF¤¿ñF¿ñF¿óF¿ñF¿óF¿ñF¿óF½ÀóFÀÀñF¿óF¿ñFù¾óFü¾ñFïÀóFòÀñFå¿óFè¿ñFÀÀñFÁÀóFé¾óFì¾ñFÝ¾óFà¾ñFÉ¾óFÌ¾ñFÃ¾óFÆ¾ñF¼¾ñF½¾óF´¾ñFµ¾óF¾ñF¾óF¾ñF¾óFè½ñFé½óFÖ½ñF×½óFÂ½ñFÃ½óF¸½ñF¹½óF´½ñFµ½óF½ñF½óF½ñF½óFö¼ñF÷¼óFì¼ñFí¼óFê¼ñFë¼óF§µ¼­L¸¼«L°¼«L±¼­L§¼­Lª¼«L²¼«L³¼­L¥¼­L¨¼«L÷¼­Lú¼«L¢¼«L£¼­L¼­L¢¼«LÜ¼«LÝ¼­L¼­L¼«L¼«L¼­L¼«L¼­L¼«L¼­L«½­L®½«Lñ»­Lô»«Lç»­Lê»«LÝ½­Là½«LÓ¼­LÖ¼«L®½«L¯½­L×»­LÚ»«LË»­LÎ»«L·»­Lº»«L±»­L´»«Lª»«L«»­L¢»«L£»­L»«L»­Lîº«Lïº­LÖº«L×º­LÄº«LÅº­L°º«L±º­L¦º«L§º­L¢º«L£º­Lº«Lº­Lð¹«Lñ¹­Lä¹«Lå¹­LÚ¹«LÛ¹­LØ¹«LÙ¹­L§£¹çQ¦¹åQ¹åQ¹çQ¹çQ¹åQ ¹åQ¡¹çQ¹çQ¹åQå¹çQè¹åQ¹åQ¹çQ¹çQ¹åQÊ¹åQË¹çQý¸çQ¹åQú¸åQû¸çQø¸åQù¸çQö¸åQ÷¸çQºçQºåQß¸çQâ¸åQÕ¸çQØ¸åQËºçQÎºåQÁ¹çQÄ¹åQºåQºçQÅ¸çQÈ¸åQ¹¸çQ¼¸åQ¥¸çQ¨¸åQ¸çQ¢¸åQ¸åQ¸çQ¸åQ¸çQð·åQñ·çQÜ·åQÝ·çQÄ·åQÅ·çQ²·åQ³·çQ·åQ·çQ·åQ·çQ·åQ·çQô¶åQõ¶çQÞ¶åQß¶çQÒ¶åQÓ¶çQÈ¶åQÉ¶çQÆ¶åQÇ¶çQ§¶¡W¶W¶W¶¡W¶¡W¶W¶W¶¡W¶¡W¶WÓ¶¡WÖ¶WþµWÿµ¡Wûµ¡WþµW¸¶W¹¶¡Wëµ¡WîµWèµWéµ¡WæµWçµ¡WäµWåµ¡W·¡W·WÍµ¡WÐµWÃµ¡WÆµW¹·¡W¼·W¯¶¡W²¶W·W·¡W³µ¡W¶µW§µ¡WªµWµ¡WµWµ¡WµWµWµ¡Wþ´Wÿ´¡WÞ´Wß´¡WÊ´WË´¡W²´W³´¡W ´W¡´¡W´W´¡W´W´¡Wþ³Wÿ³¡Wâ³Wã³¡WÌ³WÍ³¡WÀ³WÁ³¡W¶³W·³¡W´³Wµ³¡W§ÿ²Û\³Ù\ú²Ù\û²Û\ñ²Û\ô²Ù\ü²Ù\ý²Û\ï²Û\ò²Ù\Á³Û\Ä³Ù\ì²Ù\í²Û\é²Û\ì²Ù\¦³Ù\§³Û\Ù²Û\Ü²Ù\Ö²Ù\×²Û\Ô²Ù\Õ²Û\Ò²Ù\Ó²Û\õ³Û\ø³Ù\»²Û\¾²Ù\±²Û\´²Ù\§´Û\ª´Ù\³Û\ ³Ù\ø³Ù\ù³Û\¡²Û\¤²Ù\²Û\²Ù\²Û\²Ù\û±Û\þ±Ù\ô±Ù\õ±Û\ì±Ù\í±Û\Ì±Ù\Í±Û\¸±Ù\¹±Û\ ±Ù\¡±Û\±Ù\±Û\ú°Ù\û°Û\ð°Ù\ñ°Û\ì°Ù\í°Û\Ð°Ù\Ñ°Û\º°Ù\»°Û\®°Ù\¯°Û\¤°Ù\¥°Û\¢°Ù\£°Û\§»¹¹»ÿ»¹¹»ý»¹Ï»Ò¹ú¹û»÷»ú¹´¹µ»ç»ê¹ä¹å»â¹ã»à¹á»»¹É»Ì¹¿»Â¹µ»¸¹«»®¹¹»¯»²¹£»¦¹»¹»¹¹»ú¹û»Ú¹Û»Æ¹Ç»®¹¯»¹»¹»þ¹ÿ»ú¹û»Þ¹ß»È¹É»¼¹½»²¹³»°¹±»§ûõ
+þó
+öó
+÷õ
+íõ
+ðó
+øó
+ùõ
+ëõ
+îó
+½õ
+Àó
+èó
+éõ
+åõ
+èó
+¢ó
+£õ
+Õõ
+Øó
+Òó
+Óõ
+Ðó
+Ñõ
+Îó
+Ïõ
+ñõ
+ôó
+·õ
+ºó
+­õ
+°ó
+£õ
+¦ó
+õ
+ó
+ôó
+õõ
+õ
+ ó
+õ
+ó
+ýõ
+ó
+÷õ
+úó
+ðó
+ñõ
+èó
+éõ
+Èó
+Éõ
+´ó
+µõ
+ó
+õ
+ó
+õ
+öó
+÷õ
+ìó
+íõ
+èó
+éõ
+Ìó
+Íõ
+¶ó
+·õ
+ªó
+«õ
+ ó
+¡õ
+ó
+õ
+§é¯ì­ä­å¯Û¯Þ­æ­ç¯Ù¯Ü­«¯®­Ö­×¯Ó¯Ö­­¯Ã¯Æ­À­Á¯¾­¿¯¼­½¯ß¯â­¥¯¨­¯­¯­¯­â­ã¯¯­ÿÿ¯­ëÿ¯îÿ­åÿ¯èÿ­Þÿ­ßÿ¯Öÿ­×ÿ¯¶ÿ­·ÿ¯¢ÿ­£ÿ¯ÿ­ÿ¯øþ­ùþ¯äþ­åþ¯Úþ­Ûþ¯Öþ­×þ¯ºþ­»þ¯¤þ­¥þ¯þ­þ¯þ­þ¯þ­þ¯§×ýéÚýçÒýçÓýéÉýéÌýçÔýçÕýéÇýéÊýçþéþçÄýçÅýéÁýéÄýçþýçÿýé±ýé´ýç®ýç¯ýé¬ýç­ýéªýç«ýéÍþéÐþçýéýçýéýçÿþéÿçõýéøýçÐþçÑþéùüéüüçíüéðüçÙüéÜüçÓüéÖüçÌüçÍüéÄüçÅüé¤üç¥üéüçüéøûçùûéæûççûéÒûçÓûéÈûçÉûéÄûçÅûé¨ûç©ûéûçûéûçûéüúçýúéúúçûúé§Åú£Èú¡Àú¡Áú£·ú£ºú¡Âú¡Ãú£µú£¸ú¡û£û¡²ú¡³ú£¯ú£²ú¡ìú¡íú£ú£¢ú¡ú¡ú£ú¡ú£ú¡ú£»û£¾û¡ú£ú¡÷ù£úù¡íû£ðû¡ãú£æú¡¾û¡¿û£çù£êù¡Ûù£Þù¡Çù£Êù¡Áù£Äù¡ºù¡»ù£²ù¡³ù£ù¡ù£þø¡ÿø£æø¡çø£Ôø¡Õø£Àø¡Áø£¶ø¡·ø£²ø¡³ø£ø¡ø£ø¡ø£ô÷¡õ÷£ê÷¡ë÷£è÷¡é÷£§³÷Ý ¶÷Û ®÷Û ¯÷Ý ¥÷Ý ¨÷Û °÷Û ±÷Ý £÷Ý ¦÷Û õ÷Ý ø÷Û  ÷Û ¡÷Ý ÷Ý  ÷Û Ú÷Û Û÷Ý ÷Ý ÷Û ÷Û ÷Ý ÷Û ÷Ý ÷Û ÷Ý ©øÝ ¬øÛ ïöÝ òöÛ åöÝ èöÛ ÛøÝ ÞøÛ Ñ÷Ý Ô÷Û ¬øÛ ­øÝ ÕöÝ ØöÛ ÉöÝ ÌöÛ µöÝ ¸öÛ ¯öÝ ²öÛ ¨öÛ ©öÝ  öÛ ¡öÝ öÛ öÝ ìõÛ íõÝ ÔõÛ ÕõÝ ÂõÛ ÃõÝ ®õÛ ¯õÝ ¤õÛ ¥õÝ  õÛ ¡õÝ õÛ õÝ îôÛ ïôÝ âôÛ ãôÝ ØôÛ ÙôÝ ÖôÛ ×ôÝ §¡ô&¤ô&ô&ô&ô&ô&ô&ô&ô&ô&ãô&æô&ô&ô&ô&ô&Èô&Éô&ûó&þó&øó&ùó&öó&÷ó&ôó&õó&õ&õ&Ýó&àó&Óó&Öó&Éõ&Ìõ&¿ô&Âô&õ&õ&Ãó&Æó&·ó&ºó&£ó&¦ó&ó& ó&ó&ó&ó&ó&îò&ïò&Úò&Ûò&Âò&Ãò&°ò&±ò&ò&ò&ò&ò&ò&ò&òñ&óñ&Üñ&Ýñ&Ðñ&Ññ&Æñ&Çñ&Äñ&Åñ&§ñÑ+ñÏ+ñÏ+ñÑ+ñÑ+ñÏ+ñÏ+ñÑ+ÿðÑ+ñÏ+ÑñÑ+ÔñÏ+üðÏ+ýðÑ+ùðÑ+üðÏ+¶ñÏ+·ñÑ+éðÑ+ìðÏ+æðÏ+çðÑ+äðÏ+åðÑ+âðÏ+ãðÑ+òÑ+òÏ+ËðÑ+ÎðÏ+ÁðÑ+ÄðÏ+·òÑ+ºòÏ+­ñÑ+°ñÏ+òÏ+òÑ+±ðÑ+´ðÏ+¥ðÑ+¨ðÏ+ðÑ+ðÏ+ðÑ+ðÏ+ðÏ+ðÑ+üïÏ+ýïÑ+ÜïÏ+ÝïÑ+ÈïÏ+ÉïÑ+°ïÏ+±ïÑ+ïÏ+ïÑ+ïÏ+ïÑ+ïÏ+ïÑ+üîÏ+ýîÑ+àîÏ+áîÑ+ÊîÏ+ËîÑ+¾îÏ+¿îÑ+´îÏ+µîÑ+²îÏ+³îÑ+§ýí1î1øí1ùí1ïí1òí1úí1ûí1íí1ðí1¿î1Âî1êí1ëí1çí1êí1¤î1¥î1×í1Úí1Ôí1Õí1Òí1Óí1Ðí1Ñí1óî1öî1¹í1¼í1¯í1²í1¥ï1¨ï1î1î1öî1÷î1í1¢í1í1í1ÿì1í1ùì1üì1òì1óì1êì1ëì1Êì1Ëì1¶ì1·ì1ì1ì1ì1ì1øë1ùë1îë1ïë1êë1ëë1Îë1Ïë1¸ë1¹ë1¬ë1­ë1¢ë1£ë1 ë1¡ë1§ëêÅ6îêÃ6æêÃ6çêÅ6ÝêÅ6àêÃ6èêÃ6éêÅ6ÛêÅ6ÞêÃ6­ëÅ6°ëÃ6ØêÃ6ÙêÅ6ÕêÅ6ØêÃ6ëÃ6ëÅ6ÅêÅ6ÈêÃ6ÂêÃ6ÃêÅ6ÀêÃ6ÁêÅ6¾êÃ6¿êÅ6áëÅ6äëÃ6§êÅ6ªêÃ6êÅ6 êÃ6ìÅ6ìÃ6ëÅ6ëÃ6äëÃ6åëÅ6êÅ6êÃ6êÅ6êÃ6íéÅ6ðéÃ6çéÅ6êéÃ6àéÃ6áéÅ6ØéÃ6ÙéÅ6¸éÃ6¹éÅ6¤éÃ6¥éÅ6éÃ6éÅ6úèÃ6ûèÅ6æèÃ6çèÅ6ÜèÃ6ÝèÅ6ØèÃ6ÙèÅ6¼èÃ6½èÅ6¦èÃ6§èÅ6èÃ6èÅ6èÃ6èÅ6èÃ6èÅ6§Ùçÿ;Üçý;Ôçý;Õçÿ;Ëçÿ;Îçý;Öçý;×çÿ;Éçÿ;Ìçý;èÿ;èý;Æçý;Ççÿ;Ãçÿ;Æçý;èý;èÿ;³çÿ;¶çý;°çý;±çÿ;®çý;¯çÿ;¬çý;­çÿ;Ïèÿ;Òèý;çÿ;çý;çÿ;çý;éÿ;éý;÷çÿ;úçý;Òèý;Óèÿ;ûæÿ;þæý;ïæÿ;òæý;Ûæÿ;Þæý;Õæÿ;Øæý;Îæý;Ïæÿ;Ææý;Çæÿ;¦æý;§æÿ;æý;æÿ;úåý;ûåÿ;èåý;éåÿ;Ôåý;Õåÿ;Êåý;Ëåÿ;Æåý;Çåÿ;ªåý;«åÿ;åý;åÿ;åý;åÿ;þäý;ÿäÿ;üäý;ýäÿ;§Çä¹AÊä·AÂä·AÃä¹A¹ä¹A¼ä·AÄä·AÅä¹A·ä¹Aºä·Aå¹Aå·A´ä·Aµä¹A±ä¹A´ä·Aîä·Aïä¹A¡ä¹A¤ä·Aä·Aä¹Aä·Aä¹Aä·Aä¹A½å¹AÀå·Aä¹Aä·Aùã¹Aüã·Aïå¹Aòå·Aåä¹Aèä·AÀå·AÁå¹Aéã¹Aìã·AÝã¹Aàã·AÉã¹AÌã·AÃã¹AÆã·A¼ã·A½ã¹A´ã·Aµã¹Aã·Aã¹Aã·Aã¹Aèâ·Aéâ¹AÖâ·A×â¹AÂâ·AÃâ¹A¸â·A¹â¹A´â·Aµâ¹Aâ·Aâ¹Aâ·Aâ¹Aöá·A÷á¹Aìá·Aíá¹Aêá·Aëá¹A§µáóF¸áñF°áñF±áóF§áóFªáñF²áñF³áóF¥áóF¨áñF÷áóFúáñF¢áñF£áóFáóF¢áñFÜáñFÝáóFáóFáñFáñFáóFáñFáóFáñFáóF«âóF®âñFñàóFôàñFçàóFêàñFÝâóFàâñFÓáóFÖáñF®âñF¯âóF×àóFÚàñFËàóFÎàñF·àóFºàñF±àóF´àñFªàñF«àóF¢àñF£àóFàñFàóFîßñFïßóFÖßñF×ßóFÄßñFÅßóF°ßñF±ßóF¦ßñF§ßóF¢ßñF£ßóFßñFßóFðÞñFñÞóFäÞñFåÞóFÚÞñFÛÞóFØÞñFÙÞóF§£Þ­L¦Þ«LÞ«LÞ­LÞ­LÞ«L Þ«L¡Þ­LÞ­LÞ«LåÞ­LèÞ«LÞ«LÞ­LÞ­LÞ«LÊÞ«LËÞ­LýÝ­LÞ«LúÝ«LûÝ­LøÝ«LùÝ­LöÝ«L÷Ý­Lß­Lß«LßÝ­LâÝ«LÕÝ­LØÝ«LËß­LÎß«LÁÞ­LÄÞ«Lß«Lß­LÅÝ­LÈÝ«L¹Ý­L¼Ý«L¥Ý­L¨Ý«LÝ­L¢Ý«LÝ«LÝ­LÝ«LÝ­LðÜ«LñÜ­LÜÜ«LÝÜ­LÄÜ«LÅÜ­L²Ü«L³Ü­LÜ«LÜ­LÜ«LÜ­LÜ«LÜ­LôÛ«LõÛ­LÞÛ«LßÛ­LÒÛ«LÓÛ­LÈÛ«LÉÛ­LÆÛ«LÇÛ­L§ÛçQÛåQÛåQÛçQÛçQÛåQÛåQÛçQÛçQÛåQÓÛçQÖÛåQþÚåQÿÚçQûÚçQþÚåQ¸ÛåQ¹ÛçQëÚçQîÚåQèÚåQéÚçQæÚåQçÚçQäÚåQåÚçQÜçQÜåQÍÚçQÐÚåQÃÚçQÆÚåQ¹ÜçQ¼ÜåQ¯ÛçQ²ÛåQÜåQÜçQ³ÚçQ¶ÚåQ§ÚçQªÚåQÚçQÚåQÚçQÚåQÚåQÚçQþÙåQÿÙçQÞÙåQßÙçQÊÙåQËÙçQ²ÙåQ³ÙçQ ÙåQ¡ÙçQÙåQÙçQÙåQÙçQþØåQÿØçQâØåQãØçQÌØåQÍØçQÀØåQÁØçQ¶ØåQ·ØçQ´ØåQµØçQ§ÿ×¡WØWú×Wû×¡Wñ×¡Wô×Wü×Wý×¡Wï×¡Wò×WÁØ¡WÄØWì×Wí×¡Wé×¡Wì×W¦ØW§Ø¡WÙ×¡WÜ×WÖ×W××¡WÔ×WÕ×¡WÒ×WÓ×¡WõØ¡WøØW»×¡W¾×W±×¡W´×W§Ù¡WªÙWØ¡W ØWøØWùØ¡W¡×¡W¤×W×¡W×W×¡W×WûÖ¡WþÖWôÖWõÖ¡WìÖWíÖ¡WÌÖWÍÖ¡W¸ÖW¹Ö¡W ÖW¡Ö¡WÖWÖ¡WúÕWûÕ¡WðÕWñÕ¡WìÕWíÕ¡WÐÕWÑÕ¡WºÕW»Õ¡W®ÕW¯Õ¡W¤ÕW¥Õ¡W¢ÕW£Õ¡W§Ó¦»Ö¦¹Î¦¹Ï¦»Å¦»È¦¹Ð¦¹Ñ¦»Ã¦»Æ¦¹§»§¹À¦¹Á¦»½¦»À¦¹ú¦¹û¦»­¦»°¦¹ª¦¹«¦»¨¦¹©¦»¦¦¹§¦»É§»Ì§¹¦»¦¹¦»¦¹û§»þ§¹ñ¦»ô¦¹Ì§¹Í§»õ¥»ø¥¹é¥»ì¥¹Õ¥»Ø¥¹Ï¥»Ò¥¹È¥¹É¥»À¥¹Á¥» ¥¹¡¥»¥¹¥»ô¤¹õ¤»â¤¹ã¤»Î¤¹Ï¤»Ä¤¹Å¤»À¤¹Á¤»¤¤¹¥¤»¤¹¤»¤¹¤»ø£¹ù£»ö£¹÷£»§Á£õ
+Ä£ó
+¼£ó
+½£õ
+³£õ
+¶£ó
+¾£ó
+¿£õ
+±£õ
+´£ó
+¤õ
+¤ó
+®£ó
+¯£õ
+«£õ
+®£ó
+è£ó
+é£õ
+£õ
+£ó
+£ó
+£õ
+£ó
+£õ
+£ó
+£õ
+·¤õ
+º¤ó
+ý¢õ
+£ó
+ó¢õ
+ö¢ó
+é¤õ
+ì¤ó
+ß£õ
+â£ó
+º¤ó
+»¤õ
+ã¢õ
+æ¢ó
+×¢õ
+Ú¢ó
+Ã¢õ
+Æ¢ó
+½¢õ
+À¢ó
+¶¢ó
+·¢õ
+®¢ó
+¯¢õ
+¢ó
+¢õ
+ú¡ó
+û¡õ
+â¡ó
+ã¡õ
+Ð¡ó
+Ñ¡õ
+¼¡ó
+½¡õ
+²¡ó
+³¡õ
+®¡ó
+¯¡õ
+¡ó
+¡õ
+ü ó
+ý õ
+ð ó
+ñ õ
+æ ó
+ç õ
+ä ó
+å õ
+§¯ ¯² ­ª ­« ¯¡ ¯¤ ­¬ ­­ ¯ ¯¢ ­ñ ¯ô ­ ­ ¯ ¯ ­Ö ­× ¯ ¯ ­ ­ ¯ ­ ¯ ­ ¯¥¡¯¨¡­ë¯î­á¯ä­×¡¯Ú¡­Í ¯Ð ­¨¡­©¡¯Ñ¯Ô­Å¯È­±¯´­«¯®­¤­¥¯­¯ü­ý¯è­é¯Ð­Ñ¯¾­¿¯ª­«¯ ­¡¯­¯­¯ê­ë¯Þ­ß¯Ô­Õ¯Ò­Ó¯§é ççééççééçßéâççééçÄçÅé÷éúçôçõéòçóéðçñééçÙéÜçÏéÒçÅéÈç»é¾ççé¿éÂç³é¶çé¢çéççéçéêçëéÖç×é¾ç¿é¬ç­éçéçéçéîçïéØçÙéÌçÍéÂçÃéÀçÁé§£¡¡£ý£¡¡£û£þ¡Í£Ð¡ø¡ù£õ£ø¡²¡³£å£è¡â¡ã£à¡á£Þ¡ß££¡Ç£Ê¡½£À¡³£¶¡©£¬¡¡£­£°¡¡£¤¡£¡£¡¡£ø¡ù£Ø¡Ù£Ä¡Å£¬¡­£¡£¡£ü¡ý£ø¡ù£Ü¡Ý£Æ¡Ç£º¡»£°¡±£®¡¯£§ùÝ üÛ ôÛ õÝ ëÝ îÛ öÛ ÷Ý éÝ ìÛ »Ý ¾Û æÛ çÝ ãÝ æÛ  Û ¡Ý ÓÝ ÖÛ ÐÛ ÑÝ ÎÛ ÏÝ ÌÛ ÍÝ ïÝ òÛ µÝ ¸Û «Ý ®Û ¡Ý ¤Û Ý Û òÛ óÝ Ý Û Ý Û ûÝ þÛ õÝ øÛ îÛ ïÝ æÛ çÝ ÆÛ ÇÝ ²Û ³Ý Û Ý Û Ý ôÛ õÝ êÛ ëÝ æÛ çÝ ÊÛ ËÝ ´Û µÝ ¨Û ©Ý Û Ý Û Ý §ç&ê&â&ã&Ù&Ü&ä&å&×&Ú&©&¬&Ô&Õ&Ñ&Ô&&&Á&Ä&¾&¿&¼&½&º&»&Ý&à&£&¦&&&&&&&à&á&&&ý&&é&ì&ã&æ&Ü&Ý&Ô&Õ&´&µ& &¡&&&ö&÷&â&ã&Ø&Ù&Ô&Õ&¸&¹&¢&£&&&&&&&§ÕÑ+ØÏ+ÐÏ+ÑÑ+ÇÑ+ÊÏ+ÒÏ+ÓÑ+ÅÑ+ÈÏ+Ñ+Ï+ÂÏ+ÃÑ+¿Ñ+ÂÏ+üÏ+ýÑ+¯Ñ+²Ï+¬Ï+­Ñ+ªÏ+«Ñ+¨Ï+©Ñ+ËÑ+ÎÏ+Ñ+Ï+Ñ+Ï+ýÑ+Ï+óÑ+öÏ+ÎÏ+ÏÑ+÷Ñ+úÏ+ëÑ+îÏ+×Ñ+ÚÏ+ÑÑ+ÔÏ+ÊÏ+ËÑ+ÂÏ+ÃÑ+¢Ï+£Ñ+Ï+Ñ+öÏ+÷Ñ+äÏ+åÑ+ÐÏ+ÑÑ+ÆÏ+ÇÑ+ÂÏ+ÃÑ+¦Ï+§Ñ+Ï+Ñ+Ï+Ñ+úÏ+ûÑ+øÏ+ùÑ+§Ã1Æ1¾1¿1µ1¸1À1Á1³1¶111°1±1­1°1ê1ë11 1111111¹1¼1ÿ11õ1ø1ë1î1á1ä1¼1½1å1è1Ù1Ü1Å1È1¿1Â1¸1¹1°1±111ü1ý1ä1å1Ò1Ó1¾1¿1´1µ1°1±111þ1ÿ1ò1ó1è1é1æ1ç1§±Å6´Ã6¬Ã6­Å6£Å6¦Ã6®Ã6¯Å6¡Å6¤Ã6óÅ6öÃ6Ã6Å6Å6Ã6ØÃ6ÙÅ6Å6Ã6Ã6Å6Ã6Å6Ã6Å6§Å6ªÃ6íÅ6ðÃ6ãÅ6æÃ6ÙÅ6ÜÃ6ÏÅ6ÒÃ6ªÃ6«Å6ÓÅ6ÖÃ6ÇÅ6ÊÃ6³Å6¶Ã6­Å6°Ã6¦Ã6§Å6Ã6Å6þÃ6ÿÅ6êÃ6ëÅ6ÒÃ6ÓÅ6ÀÃ6ÁÅ6¬Ã6­Å6¢Ã6£Å6Ã6Å6Ã6Å6ìÃ6íÅ6àÃ6áÅ6ÖÃ6×Å6ÔÃ6ÕÅ6§ÿ;¢ý;ý;ÿ;ÿ;ý;ý;ÿ;ÿ;ý;áÿ;äý;ý;ÿ;ÿ;ý;Æý;Çÿ;ùÿ;üý;öý;÷ÿ;ôý;õÿ;òý;óÿ;ÿ;ý;Ûÿ;Þý;Ñÿ;Ôý;Çÿ;Êý;½ÿ;Àý;ý;ÿ;Áÿ;Äý;µÿ;¸ý;¡ÿ;¤ý;ÿ;ý;ý;ÿ;ý;ÿ;ìý;íÿ;Øý;Ùÿ;Àý;Áÿ;®ý;¯ÿ;ý;ÿ;ý;ÿ;ý;ÿ;ðý;ñÿ;Úý;Ûÿ;Îý;Ïÿ;Äý;Åÿ;Âý;Ãÿ;§¹A·A·A¹Aÿ¹A·A·A¹Aý¹A·AÏ¹AÒ·Aú·Aû¹A÷¹Aú·A´·Aµ¹Aç¹Aê·Aä·Aå¹Aâ·Aã¹Aà·Aá¹A¹A·AÉ¹AÌ·A¿¹AÂ·Aµ¹A¸·A«¹A®·A·A¹A¯¹A²·A£¹A¦·A¹A·A¹A·A·A¹Aú·Aû¹AÚ·AÛ¹AÆ·AÇ¹A®·A¯¹A·A¹A·A¹Aþ·Aÿ¹Aú·Aû¹AÞ·Aß¹AÈ·AÉ¹A¼·A½¹A²·A³¹A°·A±¹A§ûóFþñFöñF÷óFíóFðñFøñFùóFëóFîñF½óFÀñFèñFéóFåóFèñF¢ñF£óFÕóFØñFÒñFÓóFÐñFÑóFÎñFÏóFñóFôñF·óFºñF­óF°ñF£óF¦ñFóFñFôñFõóFóF ñFóFñFýÿóFñF÷ÿóFúÿñFðÿñFñÿóFèÿñFéÿóFÈÿñFÉÿóF´ÿñFµÿóFÿñFÿóFÿñFÿóFöþñF÷þóFìþñFíþóFèþñFéþóFÌþñFÍþóF¶þñF·þóFªþñF«þóF þñF¡þóFþñFþóF§éý­Lìý«Läý«Låý­LÛý­LÞý«Læý«Lçý­LÙý­LÜý«L«þ­L®þ«LÖý«L×ý­LÓý­LÖý«Lþ«Lþ­LÃý­LÆý«LÀý«LÁý­L¾ý«L¿ý­L¼ý«L½ý­Lßþ­Lâþ«L¥ý­L¨ý«Lý­Lý«Lÿ­Lÿ«Lþ­Lþ«Lâþ«Lãþ­Lý­Lý«Lÿü­Lý«Lëü­Lîü«Låü­Lèü«LÞü«Lßü­LÖü«L×ü­L¶ü«L·ü­L¢ü«L£ü­Lü«Lü­Løû«Lùû­Läû«Låû­LÚû«LÛû­LÖû«L×û­Lºû«L»û­L¤û«L¥û­Lû«Lû­Lû«Lû­Lû«Lû­L§×úçQÚúåQÒúåQÓúçQÉúçQÌúåQÔúåQÕúçQÇúçQÊúåQûçQûåQÄúåQÅúçQÁúçQÄúåQþúåQÿúçQ±úçQ´úåQ®úåQ¯úçQ¬úåQ­úçQªúåQ«úçQÍûçQÐûåQúçQúåQúçQúåQÿûçQüåQõúçQøúåQÐûåQÑûçQùùçQüùåQíùçQðùåQÙùçQÜùåQÓùçQÖùåQÌùåQÍùçQÄùåQÅùçQ¤ùåQ¥ùçQùåQùçQøøåQùøçQæøåQçøçQÒøåQÓøçQÈøåQÉøçQÄøåQÅøçQ¨øåQ©øçQøåQøçQøåQøçQü÷åQý÷çQú÷åQû÷çQ§ñÃ»ôÃ¹ìÃ¹íÃ»ãÃ»æÃ¹îÃ¹ïÃ»áÃ»äÃ¹³Ä»¶Ä¹ÞÃ¹ßÃ»ÛÃ»ÞÃ¹Ä¹Ä»ËÃ»ÎÃ¹ÈÃ¹ÉÃ»ÆÃ¹ÇÃ»ÄÃ¹ÅÃ»çÄ»êÄ¹­Ã»°Ã¹£Ã»¦Ã¹Å»Å¹Ä»Ä¹êÄ¹ëÄ»Ã»Ã¹Ã»Ã¹óÂ»öÂ¹íÂ»ðÂ¹æÂ¹çÂ»ÞÂ¹ßÂ»¾Â¹¿Â»ªÂ¹«Â»Â¹Â»Â¹Â»ìÁ¹íÁ»âÁ¹ãÁ»ÞÁ¹ßÁ»ÂÁ¹ÃÁ»¬Á¹­Á» Á¹¡Á»Á¹Á»Á¹Á»§ßÀõ
+âÀó
+ÚÀó
+ÛÀõ
+ÑÀõ
+ÔÀó
+ÜÀó
+ÝÀõ
+ÏÀõ
+ÒÀó
+¡Áõ
+¤Áó
+ÌÀó
+ÍÀõ
+ÉÀõ
+ÌÀó
+Áó
+Áõ
+¹Àõ
+¼Àó
+¶Àó
+·Àõ
+´Àó
+µÀõ
+²Àó
+³Àõ
+ÕÁõ
+ØÁó
+Àõ
+Àó
+Àõ
+Àó
+Âõ
+Âó
+ýÀõ
+Áó
+ØÁó
+ÙÁõ
+Àõ
+Àó
+õ¿õ
+ø¿ó
+á¿õ
+ä¿ó
+Û¿õ
+Þ¿ó
+Ô¿ó
+Õ¿õ
+Ì¿ó
+Í¿õ
+¬¿ó
+­¿õ
+¿ó
+¿õ
+¿ó
+¿õ
+î¾ó
+ï¾õ
+Ú¾ó
+Û¾õ
+Ð¾ó
+Ñ¾õ
+Ì¾ó
+Í¾õ
+°¾ó
+±¾õ
+¾ó
+¾õ
+¾ó
+¾õ
+¾ó
+¾õ
+¾ó
+¾õ
+§Í½¯Ð½­È½­É½¯¿½¯Â½­Ê½­Ë½¯½½¯À½­¾¯¾­º½­»½¯·½¯º½­ô½­õ½¯§½¯ª½­¤½­¥½¯¢½­£½¯ ½­¡½¯Ã¾¯Æ¾­½¯½­ÿ¼¯½­õ¾¯ø¾­ë½¯î½­Æ¾­Ç¾¯ï¼¯ò¼­ã¼¯æ¼­Ï¼¯Ò¼­É¼¯Ì¼­Â¼­Ã¼¯º¼­»¼¯¼­¼¯¼­¼¯î»­ï»¯Ü»­Ý»¯È»­É»¯¾»­¿»¯º»­»»¯»­»¯»­»¯üº­ýº¯òº­óº¯ðº­ñº¯§»ºé¾ºç¶ºç·ºé­ºé°ºç¸ºç¹ºé«ºé®ºçýºé»ç¨ºç©ºé¥ºé¨ºçâºçãºéºéºçºçºéºçºéºçºé±»é´»ç÷¹éú¹çí¹éð¹çã»éæ»çÙºéÜºç´»çµ»éÝ¹éà¹çÑ¹éÔ¹ç½¹éÀ¹ç·¹éº¹ç°¹ç±¹é¨¹ç©¹é¹ç¹éô¸çõ¸éÜ¸çÝ¸éÊ¸çË¸é¶¸ç·¸é¬¸ç­¸é¨¸ç©¸é¸ç¸éö·ç÷·éê·çë·éà·çá·éÞ·çß·é§©·£¬·¡¤·¡¥·£·£·¡¦·¡§·£·£·¡ë·£î·¡·¡·£·£·¡Ð·¡Ñ·£·£·¡·¡·£þ¶¡ÿ¶£ü¶¡ý¶£¸£¢¸¡å¶£è¶¡Û¶£Þ¶¡Ñ¸£Ô¸¡Ç·£Ê·¡¢¸¡£¸£Ë¶£Î¶¡¿¶£Â¶¡«¶£®¶¡¥¶£¨¶¡¶¡¶£¶¡¶£öµ¡÷µ£âµ¡ãµ£Êµ¡Ëµ£¸µ¡¹µ£¤µ¡¥µ£µ¡µ£µ¡µ£ú´¡û´£ä´¡å´£Ø´¡Ù´£Î´¡Ï´£Ì´¡Í´£§´Ý ´Û ´Û ´Ý ´Ý ´Û ´Û ´Ý ´Ý ´Û Ù´Ý Ü´Û ´Û ´Ý ´Ý ´Û ¾´Û ¿´Ý ñ³Ý ô³Û î³Û ï³Ý ì³Û í³Ý ê³Û ë³Ý µÝ µÛ Ó³Ý Ö³Û É³Ý Ì³Û ¿µÝ ÂµÛ µ´Ý ¸´Û µÛ µÝ ¹³Ý ¼³Û ­³Ý °³Û ³Ý ³Û ³Ý ³Û ³Û ³Ý ³Û ³Ý ä²Û å²Ý Ð²Û Ñ²Ý ¸²Û ¹²Ý ¦²Û §²Ý ²Û ²Ý ²Û ²Ý ²Û ²Ý è±Û é±Ý Ò±Û Ó±Ý Æ±Û Ç±Ý ¼±Û ½±Ý º±Û »±Ý §±&±&±&±&÷°&ú°&±&±&õ°&ø°&Ç±&Ê±&ò°&ó°&ï°&ò°&¬±&­±&ß°&â°&Ü°&Ý°&Ú°&Û°&Ø°&Ù°&û±&þ±&Á°&Ä°&·°&º°&­²&°²&£±&¦±&þ±&ÿ±&§°&ª°&°&°&°&°&°&°&ú¯&û¯&ò¯&ó¯&Ò¯&Ó¯&¾¯&¿¯&¦¯&§¯&¯&¯&¯&¯&ö®&÷®&ò®&ó®&Ö®&×®&À®&Á®&´®&µ®&ª®&«®&¨®&©®&§ó­Ñ+ö­Ï+î­Ï+ï­Ñ+å­Ñ+è­Ï+ð­Ï+ñ­Ñ+ã­Ñ+æ­Ï+µ®Ñ+¸®Ï+à­Ï+á­Ñ+Ý­Ñ+à­Ï+®Ï+®Ñ+Í­Ñ+Ð­Ï+Ê­Ï+Ë­Ñ+È­Ï+É­Ñ+Æ­Ï+Ç­Ñ+é®Ñ+ì®Ï+¯­Ñ+²­Ï+¥­Ñ+¨­Ï+¯Ñ+¯Ï+®Ñ+®Ï+ì®Ï+í®Ñ+­Ñ+­Ï+­Ñ+­Ï+õ¬Ñ+ø¬Ï+ï¬Ñ+ò¬Ï+è¬Ï+é¬Ñ+à¬Ï+á¬Ñ+À¬Ï+Á¬Ñ+¬¬Ï+­¬Ñ+¬Ï+¬Ñ+¬Ï+¬Ñ+î«Ï+ï«Ñ+ä«Ï+å«Ñ+à«Ï+á«Ñ+Ä«Ï+Å«Ñ+®«Ï+¯«Ñ+¢«Ï+£«Ñ+«Ï+«Ñ+«Ï+«Ñ+§áª1äª1Üª1Ýª1Óª1Öª1Þª1ßª1Ñª1Ôª1£«1¦«1Îª1Ïª1Ëª1Îª1«1«1»ª1¾ª1¸ª1¹ª1¶ª1·ª1´ª1µª1×«1Ú«1ª1 ª1ª1ª1¬1¬1ÿª1«1Ú«1Û«1ª1ª1÷©1ú©1ã©1æ©1Ý©1à©1Ö©1×©1Î©1Ï©1®©1¯©1©1©1©1©1ð¨1ñ¨1Ü¨1Ý¨1Ò¨1Ó¨1Î¨1Ï¨1²¨1³¨1¨1¨1¨1¨1¨1¨1¨1¨1§Ï§Å6Ò§Ã6Ê§Ã6Ë§Å6Á§Å6Ä§Ã6Ì§Ã6Í§Å6¿§Å6Â§Ã6¨Å6¨Ã6¼§Ã6½§Å6¹§Å6¼§Ã6ö§Ã6÷§Å6©§Å6¬§Ã6¦§Ã6§§Å6¤§Ã6¥§Å6¢§Ã6£§Å6Å¨Å6È¨Ã6§Å6§Ã6§Å6§Ã6÷¨Å6ú¨Ã6í§Å6ð§Ã6È¨Ã6É¨Å6ñ¦Å6ô¦Ã6å¦Å6è¦Ã6Ñ¦Å6Ô¦Ã6Ë¦Å6Î¦Ã6Ä¦Ã6Å¦Å6¼¦Ã6½¦Å6¦Ã6¦Å6¦Ã6¦Å6ð¥Ã6ñ¥Å6Þ¥Ã6ß¥Å6Ê¥Ã6Ë¥Å6À¥Ã6Á¥Å6¼¥Ã6½¥Å6 ¥Ã6¡¥Å6¥Ã6¥Å6þ¤Ã6ÿ¤Å6ô¤Ã6õ¤Å6ò¤Ã6ó¤Å6§½¤ÿ;À¤ý;¸¤ý;¹¤ÿ;¯¤ÿ;²¤ý;º¤ý;»¤ÿ;­¤ÿ;°¤ý;ÿ¤ÿ;¥ý;ª¤ý;«¤ÿ;§¤ÿ;ª¤ý;ä¤ý;å¤ÿ;¤ÿ;¤ý;¤ý;¤ÿ;¤ý;¤ÿ;¤ý;¤ÿ;³¥ÿ;¶¥ý;ù£ÿ;ü£ý;ï£ÿ;ò£ý;å¥ÿ;è¥ý;Û¤ÿ;Þ¤ý;¶¥ý;·¥ÿ;ß£ÿ;â£ý;Ó£ÿ;Ö£ý;¿£ÿ;Â£ý;¹£ÿ;¼£ý;²£ý;³£ÿ;ª£ý;«£ÿ;£ý;£ÿ;ö¢ý;÷¢ÿ;Þ¢ý;ß¢ÿ;Ì¢ý;Í¢ÿ;¸¢ý;¹¢ÿ;®¢ý;¯¢ÿ;ª¢ý;«¢ÿ;¢ý;¢ÿ;ø¡ý;ù¡ÿ;ì¡ý;í¡ÿ;â¡ý;ã¡ÿ;à¡ý;á¡ÿ;§«¡¹A®¡·A¦¡·A§¡¹A¡¹A ¡·A¨¡·A©¡¹A¡¹A¡·Aí¡¹Að¡·A¡·A¡¹A¡¹A¡·AÒ¡·AÓ¡¹A¡¹A¡·A¡·A¡¹A¡·A¡¹Aþ ·Aÿ ¹A¡¢¹A¤¢·Aç ¹Aê ·AÝ ¹Aà ·AÓ¢¹AÖ¢·AÉ¡¹AÌ¡·A¤¢·A¥¢¹AÍ ¹AÐ ·AÁ ¹AÄ ·A­ ¹A° ·A§ ¹Aª ·A  ·A¡ ¹A ·A ¹Aø·Aù¹Aä·Aå¹AÌ·AÍ¹Aº·A»¹A¦·A§¹A·A¹A·A¹Aü·Aý¹Aæ·Aç¹AÚ·AÛ¹AÐ·AÑ¹AÎ·AÏ¹A§óFñFñFóFóFñFñFóFóFñFÛóFÞñFñFóFóFñFÀñFÁóFóóFöñFðñFñóFîñFïóFìñFíóFóFñFÕóFØñFËóFÎñFÁóFÄñF·óFºñFñFóF»óF¾ñF¯óF²ñFóFñFóFñFñFóFñFóFæñFçóFÒñFÓóFºñF»óF¨ñF©óFñFóFñFóFñFóFêñFëóFÔñFÕóFÈñFÉóF¾ñF¿óF¼ñF½óF§­L«L«L­Lù­Lü«L«L­L÷­Lú«LÉ­LÌ«Lô«Lõ­Lñ­Lô«L®«L¯­Lá­Lä«LÞ«Lß­LÜ«LÝ­LÚ«LÛ­Lý­L«LÃ­LÆ«L¹­L¼«L¯­L²«L¥­L¨«L«L­L©­L¬«L­L «L­L«L­L«Lü«Lý­Lô«Lõ­LÔ«LÕ­LÀ«LÁ­L¨«L©­L«L­L«L­Lø«Lù­Lô«Lõ­LØ«LÙ­LÂ«LÃ­L¶«L·­L¬«L­­Lª«L«­L§çÞ»êÞ¹âÞ¹ãÞ»ÙÞ»ÜÞ¹äÞ¹åÞ»×Þ»ÚÞ¹©ß»¬ß¹ÔÞ¹ÕÞ»ÑÞ»ÔÞ¹ß¹ß»ÁÞ»ÄÞ¹¾Þ¹¿Þ»¼Þ¹½Þ»ºÞ¹»Þ»Ýß»àß¹£Þ»¦Þ¹Þ»Þ¹à»à¹ß»ß¹àß¹áß»Þ»Þ¹ýÝ»Þ¹éÝ»ìÝ¹ãÝ»æÝ¹ÜÝ¹ÝÝ»ÔÝ¹ÕÝ»´Ý¹µÝ» Ý¹¡Ý»Ý¹Ý»öÜ¹÷Ü»âÜ¹ãÜ»ØÜ¹ÙÜ»ÔÜ¹ÕÜ»¸Ü¹¹Ü»¢Ü¹£Ü»Ü¹Ü»Ü¹Ü»Ü¹Ü»§ÕÛõ
+ØÛó
+ÐÛó
+ÑÛõ
+ÇÛõ
+ÊÛó
+ÒÛó
+ÓÛõ
+ÅÛõ
+ÈÛó
+Üõ
+Üó
+ÂÛó
+ÃÛõ
+¿Ûõ
+ÂÛó
+üÛó
+ýÛõ
+¯Ûõ
+²Ûó
+¬Ûó
+­Ûõ
+ªÛó
+«Ûõ
+¨Ûó
+©Ûõ
+ËÜõ
+ÎÜó
+Ûõ
+Ûó
+Ûõ
+Ûó
+ýÜõ
+Ýó
+óÛõ
+öÛó
+ÎÜó
+ÏÜõ
+÷Úõ
+úÚó
+ëÚõ
+îÚó
+×Úõ
+ÚÚó
+ÑÚõ
+ÔÚó
+ÊÚó
+ËÚõ
+ÂÚó
+ÃÚõ
+¢Úó
+£Úõ
+Úó
+Úõ
+öÙó
+÷Ùõ
+äÙó
+åÙõ
+ÐÙó
+ÑÙõ
+ÆÙó
+ÇÙõ
+ÂÙó
+ÃÙõ
+¦Ùó
+§Ùõ
+Ùó
+Ùõ
+Ùó
+Ùõ
+úØó
+ûØõ
+øØó
+ùØõ
+§ÃØ¯ÆØ­¾Ø­¿Ø¯µØ¯¸Ø­ÀØ­ÁØ¯³Ø¯¶Ø­Ù¯Ù­°Ø­±Ø¯­Ø¯°Ø­êØ­ëØ¯Ø¯ Ø­Ø­Ø¯Ø­Ø¯Ø­Ø¯¹Ù¯¼Ù­ÿ×¯Ø­õ×¯ø×­ëÙ¯îÙ­áØ¯äØ­¼Ù­½Ù¯å×¯è×­Ù×¯Ü×­Å×¯È×­¿×¯Â×­¸×­¹×¯°×­±×¯×­×¯üÖ­ýÖ¯äÖ­åÖ¯ÒÖ­ÓÖ¯¾Ö­¿Ö¯´Ö­µÖ¯°Ö­±Ö¯Ö­Ö¯þÕ­ÿÕ¯òÕ­óÕ¯èÕ­éÕ¯æÕ­çÕ¯§±Õé´Õç¬Õç­Õé£Õé¦Õç®Õç¯Õé¡Õé¤ÕçóÕéöÕçÕçÕéÕéÕçØÕçÙÕéÕéÕçÕçÕéÕçÕéÕçÕé§ÖéªÖçíÔéðÔçãÔéæÔçÙÖéÜÖçÏÕéÒÕçªÖç«ÖéÓÔéÖÔçÇÔéÊÔç³Ôé¶Ôç­Ôé°Ôç¦Ôç§ÔéÔçÔéþÓçÿÓéêÓçëÓéÒÓçÓÓéÀÓçÁÓé¬Óç­Óé¢Óç£ÓéÓçÓéÓçÓéìÒçíÒéàÒçáÒéÖÒç×ÒéÔÒçÕÒé§Ò£¢Ò¡Ò¡Ò£Ò£Ò¡Ò¡Ò£Ò£Ò¡áÒ£äÒ¡Ò¡Ò£Ò£Ò¡ÆÒ¡ÇÒ£ùÑ£üÑ¡öÑ¡÷Ñ£ôÑ¡õÑ£òÑ¡óÑ£Ó£Ó¡ÛÑ£ÞÑ¡ÑÑ£ÔÑ¡ÇÓ£ÊÓ¡½Ò£ÀÒ¡Ó¡Ó£ÁÑ£ÄÑ¡µÑ£¸Ñ¡¡Ñ£¤Ñ¡Ñ£Ñ¡Ñ¡Ñ£Ñ¡Ñ£ìÐ¡íÐ£ØÐ¡ÙÐ£ÀÐ¡ÁÐ£®Ð¡¯Ð£Ð¡Ð£Ð¡Ð£Ð¡Ð£ðÏ¡ñÏ£ÚÏ¡ÛÏ£ÎÏ¡ÏÏ£ÄÏ¡ÅÏ£ÂÏ¡ÃÏ£§ÏÝ ÏÛ ÏÛ ÏÝ ÿÎÝ ÏÛ ÏÛ ÏÝ ýÎÝ ÏÛ ÏÏÝ ÒÏÛ úÎÛ ûÎÝ ÷ÎÝ úÎÛ ´ÏÛ µÏÝ çÎÝ êÎÛ äÎÛ åÎÝ âÎÛ ãÎÝ àÎÛ áÎÝ ÐÝ ÐÛ ÉÎÝ ÌÎÛ ¿ÎÝ ÂÎÛ µÐÝ ¸ÐÛ «ÏÝ ®ÏÛ ÐÛ ÐÝ ¯ÎÝ ²ÎÛ £ÎÝ ¦ÎÛ ÎÝ ÎÛ ÎÝ ÎÛ ÎÛ ÎÝ úÍÛ ûÍÝ ÚÍÛ ÛÍÝ ÆÍÛ ÇÍÝ ®ÍÛ ¯ÍÝ ÍÛ ÍÝ ÍÛ ÍÝ þÌÛ ÿÌÝ úÌÛ ûÌÝ ÞÌÛ ßÌÝ ÈÌÛ ÉÌÝ ¼ÌÛ ½ÌÝ ²ÌÛ ³ÌÝ °ÌÛ ±ÌÝ §ûË&þË&öË&÷Ë&íË&ðË&øË&ùË&ëË&îË&½Ì&ÀÌ&èË&éË&åË&èË&¢Ì&£Ì&ÕË&ØË&ÒË&ÓË&ÐË&ÑË&ÎË&ÏË&ñÌ&ôÌ&·Ë&ºË&­Ë&°Ë&£Í&¦Í&Ì&Ì&ôÌ&õÌ&Ë& Ë&Ë&Ë&ýÊ&Ë&÷Ê&úÊ&ðÊ&ñÊ&èÊ&éÊ&ÈÊ&ÉÊ&´Ê&µÊ&Ê&Ê&Ê&Ê&öÉ&÷É&ìÉ&íÉ&èÉ&éÉ&ÌÉ&ÍÉ&¶É&·É&ªÉ&«É& É&¡É&É&É&§éÈÑ+ìÈÏ+äÈÏ+åÈÑ+ÛÈÑ+ÞÈÏ+æÈÏ+çÈÑ+ÙÈÑ+ÜÈÏ+«ÉÑ+®ÉÏ+ÖÈÏ+×ÈÑ+ÓÈÑ+ÖÈÏ+ÉÏ+ÉÑ+ÃÈÑ+ÆÈÏ+ÀÈÏ+ÁÈÑ+¾ÈÏ+¿ÈÑ+¼ÈÏ+½ÈÑ+ßÉÑ+âÉÏ+¥ÈÑ+¨ÈÏ+ÈÑ+ÈÏ+ÊÑ+ÊÏ+ÉÑ+ÉÏ+âÉÏ+ãÉÑ+ÈÑ+ÈÏ+ÿÇÑ+ÈÏ+ëÇÑ+îÇÏ+åÇÑ+èÇÏ+ÞÇÏ+ßÇÑ+ÖÇÏ+×ÇÑ+¶ÇÏ+·ÇÑ+¢ÇÏ+£ÇÑ+ÇÏ+ÇÑ+øÆÏ+ùÆÑ+äÆÏ+åÆÑ+ÚÆÏ+ÛÆÑ+ÖÆÏ+×ÆÑ+ºÆÏ+»ÆÑ+¤ÆÏ+¥ÆÑ+ÆÏ+ÆÑ+ÆÏ+ÆÑ+ÆÏ+ÆÑ+§×Å1ÚÅ1ÒÅ1ÓÅ1ÉÅ1ÌÅ1ÔÅ1ÕÅ1ÇÅ1ÊÅ1Æ1Æ1ÄÅ1ÅÅ1ÁÅ1ÄÅ1þÅ1ÿÅ1±Å1´Å1®Å1¯Å1¬Å1­Å1ªÅ1«Å1ÍÆ1ÐÆ1Å1Å1Å1Å1ÿÆ1Ç1õÅ1øÅ1ÐÆ1ÑÆ1ùÄ1üÄ1íÄ1ðÄ1ÙÄ1ÜÄ1ÓÄ1ÖÄ1ÌÄ1ÍÄ1ÄÄ1ÅÄ1¤Ä1¥Ä1Ä1Ä1øÃ1ùÃ1æÃ1çÃ1ÒÃ1ÓÃ1ÈÃ1ÉÃ1ÄÃ1ÅÃ1¨Ã1©Ã1Ã1Ã1Ã1Ã1üÂ1ýÂ1úÂ1ûÂ1§ÅÂÅ6ÈÂÃ6ÀÂÃ6ÁÂÅ6·ÂÅ6ºÂÃ6ÂÂÃ6ÃÂÅ6µÂÅ6¸ÂÃ6ÃÅ6ÃÃ6²ÂÃ6³ÂÅ6¯ÂÅ6²ÂÃ6ìÂÃ6íÂÅ6ÂÅ6¢ÂÃ6ÂÃ6ÂÅ6ÂÃ6ÂÅ6ÂÃ6ÂÅ6»ÃÅ6¾ÃÃ6ÂÅ6ÂÃ6÷ÁÅ6úÁÃ6íÃÅ6ðÃÃ6ãÂÅ6æÂÃ6¾ÃÃ6¿ÃÅ6çÁÅ6êÁÃ6ÛÁÅ6ÞÁÃ6ÇÁÅ6ÊÁÃ6ÁÁÅ6ÄÁÃ6ºÁÃ6»ÁÅ6²ÁÃ6³ÁÅ6ÁÃ6ÁÅ6þÀÃ6ÿÀÅ6æÀÃ6çÀÅ6ÔÀÃ6ÕÀÅ6ÀÀÃ6ÁÀÅ6¶ÀÃ6·ÀÅ6²ÀÃ6³ÀÅ6ÀÃ6ÀÅ6ÀÃ6ÀÅ6ô¿Ã6õ¿Å6ê¿Ã6ë¿Å6è¿Ã6é¿Å6§³¿ÿ;¶¿ý;®¿ý;¯¿ÿ;¥¿ÿ;¨¿ý;°¿ý;±¿ÿ;£¿ÿ;¦¿ý;õ¿ÿ;ø¿ý; ¿ý;¡¿ÿ;¿ÿ; ¿ý;Ú¿ý;Û¿ÿ;¿ÿ;¿ý;¿ý;¿ÿ;¿ý;¿ÿ;¿ý;¿ÿ;©Àÿ;¬Àý;ï¾ÿ;ò¾ý;å¾ÿ;è¾ý;ÛÀÿ;ÞÀý;Ñ¿ÿ;Ô¿ý;¬Àý;­Àÿ;Õ¾ÿ;Ø¾ý;É¾ÿ;Ì¾ý;µ¾ÿ;¸¾ý;¯¾ÿ;²¾ý;¨¾ý;©¾ÿ; ¾ý;¡¾ÿ;¾ý;¾ÿ;ì½ý;í½ÿ;Ô½ý;Õ½ÿ;Â½ý;Ã½ÿ;®½ý;¯½ÿ;¤½ý;¥½ÿ; ½ý;¡½ÿ;½ý;½ÿ;î¼ý;ï¼ÿ;â¼ý;ã¼ÿ;Ø¼ý;Ù¼ÿ;Ö¼ý;×¼ÿ;§¡¼¹A¤¼·A¼·A¼¹A¼¹A¼·A¼·A¼¹A¼¹A¼·Aã¼¹Aæ¼·A¼·A¼¹A¼¹A¼·AÈ¼·AÉ¼¹Aû»¹Aþ»·Aø»·Aù»¹Aö»·A÷»¹Aô»·Aõ»¹A½¹A½·AÝ»¹Aà»·AÓ»¹AÖ»·AÉ½¹AÌ½·A¿¼¹AÂ¼·A½·A½¹AÃ»¹AÆ»·A·»¹Aº»·A£»¹A¦»·A»¹A »·A»·A»¹A»·A»¹Aîº·Aïº¹AÚº·AÛº¹AÂº·AÃº¹A°º·A±º¹Aº·Aº¹Aº·Aº¹Aº·Aº¹Aò¹·Aó¹¹AÜ¹·AÝ¹¹AÐ¹·AÑ¹¹AÆ¹·AÇ¹¹AÄ¹·AÅ¹¹A§¹óF¹ñF¹ñF¹óF¹óF¹ñF¹ñF¹óFÿ¸óF¹ñFÑ¹óFÔ¹ñFü¸ñFý¸óFù¸óFü¸ñF¶¹ñF·¹óFé¸óFì¸ñFæ¸ñFç¸óFä¸ñFå¸óFâ¸ñFã¸óFºóFºñFË¸óFÎ¸ñFÁ¸óFÄ¸ñF·ºóFººñF­¹óF°¹ñFºñFºóF±¸óF´¸ñF¥¸óF¨¸ñF¸óF¸ñF¸óF¸ñF¸ñF¸óFü·ñFý·óFÜ·ñFÝ·óFÈ·ñFÉ·óF°·ñF±·óF·ñF·óF·ñF·óF·ñF·óFü¶ñFý¶óFà¶ñFá¶óFÊ¶ñFË¶óF¾¶ñF¿¶óF´¶ñFµ¶óF²¶ñF³¶óF§µ÷»¸÷¹°÷¹±÷»§÷»ª÷¹²÷¹³÷»¥÷»¨÷¹÷÷»ú÷¹¢÷¹£÷»÷»¢÷¹Ü÷¹Ý÷»÷»÷¹÷¹÷»÷¹÷»÷¹÷»«ø»®ø¹ñö»ôö¹çö»êö¹Ýø»àø¹Ó÷»Ö÷¹®ø¹¯ø»×ö»Úö¹Ëö»Îö¹·ö»ºö¹±ö»´ö¹ªö¹«ö»¢ö¹£ö»ö¹ö»îõ¹ïõ»Öõ¹×õ»Äõ¹Åõ»°õ¹±õ»¦õ¹§õ»¢õ¹£õ»õ¹õ»ðô¹ñô»äô¹åô»Úô¹Ûô»Øô¹Ùô»§£ôõ
+¦ôó
+ôó
+ôõ
+ôõ
+ôó
+ ôó
+¡ôõ
+ôõ
+ôó
+åôõ
+èôó
+ôó
+ôõ
+ôõ
+ôó
+Êôó
+Ëôõ
+ýóõ
+ôó
+úóó
+ûóõ
+øóó
+ùóõ
+öóó
+÷óõ
+õõ
+õó
+ßóõ
+âóó
+Õóõ
+Øóó
+Ëõõ
+Îõó
+Áôõ
+Äôó
+õó
+õõ
+Åóõ
+Èóó
+¹óõ
+¼óó
+¥óõ
+¨óó
+óõ
+¢óó
+óó
+óõ
+óó
+óõ
+ðòó
+ñòõ
+Üòó
+Ýòõ
+Äòó
+Åòõ
+²òó
+³òõ
+òó
+òõ
+òó
+òõ
+òó
+òõ
+ôñó
+õñõ
+Þñó
+ßñõ
+Òñó
+Óñõ
+Èñó
+Éñõ
+Æñó
+Çñõ
+§ñ¯ñ­ñ­ñ¯ñ¯ñ­ñ­ñ¯ñ¯ñ­Óñ¯Öñ­þð­ÿð¯ûð¯þð­¸ñ­¹ñ¯ëð¯îð­èð­éð¯æð­çð¯äð­åð¯ò¯ò­Íð¯Ðð­Ãð¯Æð­¹ò¯¼ò­¯ñ¯²ñ­ò­ò¯³ð¯¶ð­§ð¯ªð­ð¯ð­ð¯ð­ð­ð¯þï­ÿï¯Þï­ßï¯Êï­Ëï¯²ï­³ï¯ ï­¡ï¯ï­ï¯ï­ï¯þî­ÿî¯âî­ãî¯Ìî­Íî¯Àî­Áî¯¶î­·î¯´î­µî¯§ÿíéîçúíçûíéñíéôíçüíçýíéïíéòíçÁîéÄîçìíçííééíéìíç¦îç§îéÙíéÜíçÖíç×íéÔíçÕíéÒíçÓíéõîéøîç»íé¾íç±íé´íç§ïéªïçîé îçøîçùîé¡íé¤íçíéíçíéíçûìéþìçôìçõìéììçíìéÌìçÍìé¸ìç¹ìé ìç¡ìéìçìéúëçûëéðëçñëéìëçíëéÐëçÑëéºëç»ëé®ëç¯ëé¤ëç¥ëé¢ëç£ëé§íê£ðê¡èê¡éê£ßê£âê¡êê¡ëê£Ýê£àê¡¯ë£²ë¡Úê¡Ûê£×ê£Úê¡ë¡ë£Çê£Êê¡Äê¡Åê£Âê¡Ãê£Àê¡Áê£ãë£æë¡©ê£¬ê¡ê£¢ê¡ì£ì¡ë£ë¡æë¡çë£ê£ê¡ê£ê¡ïé£òé¡éé£ìé¡âé¡ãé£Úé¡Ûé£ºé¡»é£¦é¡§é£é¡é£üè¡ýè£èè¡éè£Þè¡ßè£Úè¡Ûè£¾è¡¿è£¨è¡©è£è¡è£è¡è£è¡è£§ÛçÝ ÞçÛ ÖçÛ ×çÝ ÍçÝ ÐçÛ ØçÛ ÙçÝ ËçÝ ÎçÛ èÝ  èÛ ÈçÛ ÉçÝ ÅçÝ ÈçÛ èÛ èÝ µçÝ ¸çÛ ²çÛ ³çÝ °çÛ ±çÝ ®çÛ ¯çÝ ÑèÝ ÔèÛ çÝ çÛ çÝ çÛ éÝ éÛ ùçÝ üçÛ ÔèÛ ÕèÝ ýæÝ çÛ ñæÝ ôæÛ ÝæÝ àæÛ ×æÝ ÚæÛ ÐæÛ ÑæÝ ÈæÛ ÉæÝ ¨æÛ ©æÝ æÛ æÝ üåÛ ýåÝ êåÛ ëåÝ ÖåÛ ×åÝ ÌåÛ ÍåÝ ÈåÛ ÉåÝ ¬åÛ ­åÝ åÛ åÝ åÛ åÝ åÛ åÝ þäÛ ÿäÝ §Éä&Ìä&Ää&Åä&»ä&¾ä&Æä&Çä&¹ä&¼ä&å&å&¶ä&·ä&³ä&¶ä&ðä&ñä&£ä&¦ä& ä&¡ä&ä&ä&ä&ä&¿å&Âå&ä&ä&ûã&þã&ñå&ôå&çä&êä&Âå&Ãå&ëã&îã&ßã&âã&Ëã&Îã&Åã&Èã&¾ã&¿ã&¶ã&·ã&ã&ã&ã&ã&êâ&ëâ&Øâ&Ùâ&Äâ&Åâ&ºâ&»â&¶â&·â&â&â&â&â&øá&ùá&îá&ïá&ìá&íá&§·áÑ+ºáÏ+²áÏ+³áÑ+©áÑ+¬áÏ+´áÏ+µáÑ+§áÑ+ªáÏ+ùáÑ+üáÏ+¤áÏ+¥áÑ+¡áÑ+¤áÏ+ÞáÏ+ßáÑ+áÑ+áÏ+áÏ+áÑ+áÏ+áÑ+áÏ+áÑ+­âÑ+°âÏ+óàÑ+öàÏ+éàÑ+ìàÏ+ßâÑ+ââÏ+ÕáÑ+ØáÏ+°âÏ+±âÑ+ÙàÑ+ÜàÏ+ÍàÑ+ÐàÏ+¹àÑ+¼àÏ+³àÑ+¶àÏ+¬àÏ+­àÑ+¤àÏ+¥àÑ+àÏ+àÑ+ðßÏ+ñßÑ+ØßÏ+ÙßÑ+ÆßÏ+ÇßÑ+²ßÏ+³ßÑ+¨ßÏ+©ßÑ+¤ßÏ+¥ßÑ+ßÏ+ßÑ+òÞÏ+óÞÑ+æÞÏ+çÞÑ+ÜÞÏ+ÝÞÑ+ÚÞÏ+ÛÞÑ+§¥Þ1¨Þ1 Þ1¡Þ1Þ1Þ1¢Þ1£Þ1Þ1Þ1çÞ1êÞ1Þ1Þ1Þ1Þ1ÌÞ1ÍÞ1ÿÝ1Þ1üÝ1ýÝ1úÝ1ûÝ1øÝ1ùÝ1ß1ß1áÝ1äÝ1×Ý1ÚÝ1Íß1Ðß1ÃÞ1ÆÞ1ß1ß1ÇÝ1ÊÝ1»Ý1¾Ý1§Ý1ªÝ1¡Ý1¤Ý1Ý1Ý1Ý1Ý1òÜ1óÜ1ÞÜ1ßÜ1ÆÜ1ÇÜ1´Ü1µÜ1 Ü1¡Ü1Ü1Ü1Ü1Ü1öÛ1÷Û1àÛ1áÛ1ÔÛ1ÕÛ1ÊÛ1ËÛ1ÈÛ1ÉÛ1§ÛÅ6ÛÃ6ÛÃ6ÛÅ6ÛÅ6ÛÃ6ÛÃ6ÛÅ6ÛÅ6ÛÃ6ÕÛÅ6ØÛÃ6ÛÃ6ÛÅ6ýÚÅ6ÛÃ6ºÛÃ6»ÛÅ6íÚÅ6ðÚÃ6êÚÃ6ëÚÅ6èÚÃ6éÚÅ6æÚÃ6çÚÅ6ÜÅ6ÜÃ6ÏÚÅ6ÒÚÃ6ÅÚÅ6ÈÚÃ6»ÜÅ6¾ÜÃ6±ÛÅ6´ÛÃ6ÜÃ6ÜÅ6µÚÅ6¸ÚÃ6©ÚÅ6¬ÚÃ6ÚÅ6ÚÃ6ÚÅ6ÚÃ6ÚÃ6ÚÅ6ÚÃ6ÚÅ6àÙÃ6áÙÅ6ÌÙÃ6ÍÙÅ6´ÙÃ6µÙÅ6¢ÙÃ6£ÙÅ6ÙÃ6ÙÅ6ÙÃ6ÙÅ6ÙÃ6ÙÅ6äØÃ6åØÅ6ÎØÃ6ÏØÅ6ÂØÃ6ÃØÅ6¸ØÃ6¹ØÅ6¶ØÃ6·ØÅ6§Øÿ;Øý;ü×ý;ý×ÿ;ó×ÿ;ö×ý;þ×ý;ÿ×ÿ;ñ×ÿ;ô×ý;ÃØÿ;ÆØý;î×ý;ï×ÿ;ë×ÿ;î×ý;¨Øý;©Øÿ;Û×ÿ;Þ×ý;Ø×ý;Ù×ÿ;Ö×ý;××ÿ;Ô×ý;Õ×ÿ;÷Øÿ;úØý;½×ÿ;À×ý;³×ÿ;¶×ý;©Ùÿ;¬Ùý;Øÿ;¢Øý;úØý;ûØÿ;£×ÿ;¦×ý;×ÿ;×ý;×ÿ;×ý;ýÖÿ;×ý;öÖý;÷Öÿ;îÖý;ïÖÿ;ÎÖý;ÏÖÿ;ºÖý;»Öÿ;¢Öý;£Öÿ;Öý;Öÿ;üÕý;ýÕÿ;òÕý;óÕÿ;îÕý;ïÕÿ;ÒÕý;ÓÕÿ;¼Õý;½Õÿ;°Õý;±Õÿ;¦Õý;§Õÿ;¤Õý;¥Õÿ;§ïÔ¹AòÔ·AêÔ·AëÔ¹AáÔ¹AäÔ·AìÔ·AíÔ¹AßÔ¹AâÔ·A±Õ¹A´Õ·AÜÔ·AÝÔ¹AÙÔ¹AÜÔ·AÕ·AÕ¹AÉÔ¹AÌÔ·AÆÔ·AÇÔ¹AÄÔ·AÅÔ¹AÂÔ·AÃÔ¹AåÕ¹AèÕ·A«Ô¹A®Ô·A¡Ô¹A¤Ô·AÖ¹AÖ·AÕ¹AÕ·AèÕ·AéÕ¹AÔ¹AÔ·AÔ¹AÔ·AñÓ¹AôÓ·AëÓ¹AîÓ·AäÓ·AåÓ¹AÜÓ·AÝÓ¹A¼Ó·A½Ó¹A¨Ó·A©Ó¹AÓ·AÓ¹AþÒ·AÿÒ¹AêÒ·AëÒ¹AàÒ·AáÒ¹AÜÒ·AÝÒ¹AÀÒ·AÁÒ¹AªÒ·A«Ò¹AÒ·AÒ¹AÒ·AÒ¹AÒ·AÒ¹A§Û»Þ¹Ö¹×»Í»Ð¹Ø¹Ù»Ë»Î¹» ¹È¹É»Å»È¹¹»µ»¸¹²¹³»°¹±»®¹¯»Ñ»Ô¹»¹»¹»¹ù»ü¹Ô¹Õ»ý»¹ñ»ô¹Ý»à¹×»Ú¹Ð¹Ñ»È¹É»¨¹©»¹»ü¹ý»ê¹ë»Ö¹×»Ì¹Í»È¹É»¬¹­»¹»¹»¹»þ¹ÿ»§Éõ
+Ìó
+Äó
+Åõ
+»õ
+¾ó
+Æó
+Çõ
+¹õ
+¼ó
+õ
+ó
+¶ó
+·õ
+³õ
+¶ó
+ðó
+ñõ
+£õ
+¦ó
+ ó
+¡õ
+ó
+õ
+ó
+õ
+¿õ
+Âó
+õ
+ó
+ûõ
+þó
+ñõ
+ôó
+çõ
+êó
+Âó
+Ãõ
+ëõ
+îó
+ßõ
+âó
+Ëõ
+Îó
+Åõ
+Èó
+¾ó
+¿õ
+¶ó
+·õ
+ó
+õ
+ó
+õ
+êó
+ëõ
+Øó
+Ùõ
+Äó
+Åõ
+ºó
+»õ
+¶ó
+·õ
+ó
+õ
+ó
+õ
+øó
+ùõ
+îó
+ïõ
+ìó
+íõ
+§·¯º­²­³¯©¯¬­´­µ¯§¯ª­ù¯ü­¤­¥¯¡¯¤­Þ­ß¯¯­­¯­¯­¯­¯°­ó¯ö­é¯ì­ß¯â­Õ¯Ø­°­±¯Ù¯Ü­Í¯Ð­¹¯¼­³¯¶­¬­­¯¤­¥¯­¯ð­ñ¯Ø­Ù¯Æ­Ç¯²­³¯¨­©¯¤­¥¯­¯ò­ó¯æ­ç¯Ü­Ý¯Ú­Û¯§¥é¨ç ç¡ééç¢ç£ééççéêççééçÌçÍéÿéçüçýéúçûéøçùééçáéäç×éÚçÍéÐçÃéÆççéÇéÊç»é¾ç§éªç¡é¤ççéçéòçóéÞçßéÆçÇé´çµé ç¡éçéçéöç÷éàçáéÔçÕéÊçËéÈçÉé§£¡¡££¡¡££¡Õ£Ø¡¡£ý£¡º¡»£í£ð¡ê¡ë£è¡é£æ¡ç££¡Ï£Ò¡Å£È¡»£¾¡±£´¡¡£µ£¸¡©£¬¡£¡£¡¡£¡£àÿ¡áÿ£Ìÿ¡Íÿ£´ÿ¡µÿ£¢ÿ¡£ÿ£ÿ¡ÿ£ÿ¡ÿ£ÿ¡ÿ£äþ¡åþ£Îþ¡Ïþ£Âþ¡Ãþ£¸þ¡¹þ£¶þ¡·þ£§þÝ þÛ üýÛ ýýÝ óýÝ öýÛ þýÛ ÿýÝ ñýÝ ôýÛ ÃþÝ ÆþÛ îýÛ ïýÝ ëýÝ îýÛ ¨þÛ ©þÝ ÛýÝ ÞýÛ ØýÛ ÙýÝ ÖýÛ ×ýÝ ÔýÛ ÕýÝ ÷þÝ úþÛ ½ýÝ ÀýÛ ³ýÝ ¶ýÛ ©ÿÝ ¬ÿÛ þÝ ¢þÛ úþÛ ûþÝ £ýÝ ¦ýÛ ýÝ ýÛ ýÝ ýÛ ýüÝ ýÛ öüÛ ÷üÝ îüÛ ïüÝ ÎüÛ ÏüÝ ºüÛ »üÝ ¢üÛ £üÝ üÛ üÝ üûÛ ýûÝ òûÛ óûÝ îûÛ ïûÝ ÒûÛ ÓûÝ ¼ûÛ ½ûÝ °ûÛ ±ûÝ ¦ûÛ §ûÝ ¤ûÛ ¥ûÝ §ïú&òú&êú&ëú&áú&äú&ìú&íú&ßú&âú&±û&´û&Üú&Ýú&Ùú&Üú&û&û&Éú&Ìú&Æú&Çú&Äú&Åú&Âú&Ãú&åû&èû&«ú&®ú&¡ú&¤ú&ü&ü&û&û&èû&éû&ú&ú&ú&ú&ñù&ôù&ëù&îù&äù&åù&Üù&Ýù&¼ù&½ù&¨ù&©ù&ù&ù&þø&ÿø&êø&ëø&àø&áø&Üø&Ýø&Àø&Áø&ªø&«ø&ø&ø&ø&ø&ø&ø&§Ý÷Ñ+à÷Ï+Ø÷Ï+Ù÷Ñ+Ï÷Ñ+Ò÷Ï+Ú÷Ï+Û÷Ñ+Í÷Ñ+Ð÷Ï+øÑ+¢øÏ+Ê÷Ï+Ë÷Ñ+Ç÷Ñ+Ê÷Ï+øÏ+øÑ+·÷Ñ+º÷Ï+´÷Ï+µ÷Ñ+²÷Ï+³÷Ñ+°÷Ï+±÷Ñ+ÓøÑ+ÖøÏ+÷Ñ+÷Ï+÷Ñ+÷Ï+ùÑ+ùÏ+û÷Ñ+þ÷Ï+ÖøÏ+×øÑ+ÿöÑ+÷Ï+óöÑ+ööÏ+ßöÑ+âöÏ+ÙöÑ+ÜöÏ+ÒöÏ+ÓöÑ+ÊöÏ+ËöÑ+ªöÏ+«öÑ+öÏ+öÑ+þõÏ+ÿõÑ+ìõÏ+íõÑ+ØõÏ+ÙõÑ+ÎõÏ+ÏõÑ+ÊõÏ+ËõÑ+®õÏ+¯õÑ+õÏ+õÑ+õÏ+õÑ+õÏ+õÑ+õÏ+õÑ+§Ëô1Îô1Æô1Çô1½ô1Àô1Èô1Éô1»ô1¾ô1õ1õ1¸ô1¹ô1µô1¸ô1òô1óô1¥ô1¨ô1¢ô1£ô1 ô1¡ô1ô1ô1Áõ1Äõ1ô1ô1ýó1ô1óõ1öõ1éô1ìô1Äõ1Åõ1íó1ðó1áó1äó1Íó1Ðó1Çó1Êó1Àó1Áó1¸ó1¹ó1ó1ó1ó1ó1ìò1íò1Úò1Ûò1Æò1Çò1¼ò1½ò1¸ò1¹ò1ò1ò1ò1ò1úñ1ûñ1ðñ1ññ1îñ1ïñ1§¹ñÅ6¼ñÃ6´ñÃ6µñÅ6«ñÅ6®ñÃ6¶ñÃ6·ñÅ6©ñÅ6¬ñÃ6ûñÅ6þñÃ6¦ñÃ6§ñÅ6£ñÅ6¦ñÃ6àñÃ6áñÅ6ñÅ6ñÃ6ñÃ6ñÅ6ñÃ6ñÅ6ñÃ6ñÅ6¯òÅ6²òÃ6õðÅ6øðÃ6ëðÅ6îðÃ6áòÅ6äòÃ6×ñÅ6ÚñÃ6²òÃ6³òÅ6ÛðÅ6ÞðÃ6ÏðÅ6ÒðÃ6»ðÅ6¾ðÃ6µðÅ6¸ðÃ6®ðÃ6¯ðÅ6¦ðÃ6§ðÅ6ðÃ6ðÅ6òïÃ6óïÅ6ÚïÃ6ÛïÅ6ÈïÃ6ÉïÅ6´ïÃ6µïÅ6ªïÃ6«ïÅ6¦ïÃ6§ïÅ6ïÃ6ïÅ6ôîÃ6õîÅ6èîÃ6éîÅ6ÞîÃ6ßîÅ6ÜîÃ6ÝîÅ6§§îÿ;ªîý;¢îý;£îÿ;îÿ;îý;¤îý;¥îÿ;îÿ;îý;éîÿ;ìîý;îý;îÿ;îÿ;îý;Îîý;Ïîÿ;îÿ;îý;þíý;ÿíÿ;üíý;ýíÿ;úíý;ûíÿ;ïÿ; ïý;ãíÿ;æíý;Ùíÿ;Üíý;Ïïÿ;Òïý;Åîÿ;Èîý; ïý;¡ïÿ;Éíÿ;Ìíý;½íÿ;Àíý;©íÿ;¬íý;£íÿ;¦íý;íý;íÿ;íý;íÿ;ôìý;õìÿ;àìý;áìÿ;Èìý;Éìÿ;¶ìý;·ìÿ;¢ìý;£ìÿ;ìý;ìÿ;ìý;ìÿ;øëý;ùëÿ;âëý;ãëÿ;Öëý;×ëÿ;Ìëý;Íëÿ;Êëý;Ëëÿ;§Ù¡»Ü¡¹Ô¡¹Õ¡»Ë¡»Î¡¹Ö¡¹×¡»É¡»Ì¡¹¢»¢¹Æ¡¹Ç¡»Ã¡»Æ¡¹¢¹¢»³¡»¶¡¹°¡¹±¡»®¡¹¯¡»¬¡¹­¡»Ï¢»Ò¢¹¡»¡¹¡»¡¹£»£¹÷¡»ú¡¹Ò¢¹Ó¢»û »þ ¹ï »ò ¹Û »Þ ¹Õ »Ø ¹Î ¹Ï »Æ ¹Ç »¦ ¹§ » ¹ »ú¹û»è¹é»Ô¹Õ»Ê¹Ë»Æ¹Ç»ª¹«»¹»¹»þ¹ÿ»ü¹ý»§Çõ
+Êó
+Âó
+Ãõ
+¹õ
+¼ó
+Äó
+Åõ
+·õ
+ºó
+õ
+ó
+´ó
+µõ
+±õ
+´ó
+îó
+ïõ
+¡õ
+¤ó
+ó
+õ
+ó
+õ
+ó
+õ
+½õ
+Àó
+õ
+ó
+ùõ
+üó
+ïõ
+òó
+åõ
+èó
+Àó
+Áõ
+éõ
+ìó
+Ýõ
+àó
+Éõ
+Ìó
+Ãõ
+Æó
+¼ó
+½õ
+´ó
+µõ
+ó
+õ
+ó
+õ
+èó
+éõ
+Öó
+×õ
+Âó
+Ãõ
+¸ó
+¹õ
+´ó
+µõ
+ó
+õ
+ó
+õ
+öó
+÷õ
+ìó
+íõ
+êó
+ëõ
+§µ¯¸­°­±¯§¯ª­²­³¯¥¯¨­÷¯ú­¢­£¯¯¢­Ü­Ý¯¯­­¯­¯­¯«¯®­ñ¯ô­ç¯ê­Ý¯à­Ó¯Ö­®­¯¯×¯Ú­Ë¯Î­·¯º­±¯´­ª­«¯¢­£¯­¯î­ï¯Ö­×¯Ä­Å¯°­±¯¦­§¯¢­£¯­¯ð­ñ¯ä­å¯Ú­Û¯Ø­Ù¯§£é¦ççééç ç¡ééçåéèççééçÊçËéýéçúçûéøçùéöç÷ééçßéâçÕéØçËéÎçÁéÄççéÅéÈç¹é¼ç¥é¨çé¢ççéçéðçñéÜçÝéÄçÅé²ç³éçéçéçéôçõéÞçßéÒçÓéÈçÉéÆçÇé§£¡¡££¡¡££¡Ó£Ö¡þ¡ÿ£û£þ¡¸¡¹£ë£î¡è¡é£æ¡ç£ä¡å££¡Í£Ð¡Ã£Æ¡¹£¼¡¯£²¡¡£³£¶¡§£ª¡£¡£¡¡£þ¡ÿ£Þ¡ß£Ê¡Ë£²¡³£ ¡¡£¡£¡£þ¡ÿ£â¡ã£Ì¡Í£À¡Á£¶¡·£´¡µ£§ÿÝ Û úÛ ûÝ ñÝ ôÛ üÛ ýÝ ïÝ òÛ ÁÝ ÄÛ ìÛ íÝ éÝ ìÛ ¦Û §Ý ÙÝ ÜÛ ÖÛ ×Ý ÔÛ ÕÝ ÒÛ ÓÝ õÝ øÛ »Ý ¾Û ±Ý ´Û §Ý ªÛ Ý  Û øÛ ùÝ ¡Ý ¤Û Ý Û Ý Û ûÝ þÛ ôÛ õÝ ìÛ íÝ ÌÛ ÍÝ ¸Û ¹Ý  Û ¡Ý Û Ý úÛ ûÝ ðÛ ñÝ ìÛ íÝ ÐÛ ÑÝ ºÛ »Ý ®Û ¯Ý ¤Û ¥Ý ¢Û £Ý §í&ð&è&é&ß&â&ê&ë&Ý&à&¯&²&Ú&Û&×&Ú&&&Ç&Ê&Ä&Å&Â&Ã&À&Á&ã&æ&©&¬&&¢&&&&&æ&ç&&&&&ï&ò&é&ì&â&ã&Ú&Û&º&»&¦&§&&&ü&ý&è&é&Þ&ß&Ú&Û&¾&¿&¨&©&&&&&&&§ÛÑ+ÞÏ+ÖÏ+×Ñ+ÍÑ+ÐÏ+ØÏ+ÙÑ+ËÑ+ÎÏ+Ñ+ Ï+ÈÏ+ÉÑ+ÅÑ+ÈÏ+Ï+Ñ+µÑ+¸Ï+²Ï+³Ñ+°Ï+±Ñ+®Ï+¯Ñ+ÑÑ+ÔÏ+Ñ+Ï+Ñ+Ï+Ñ+Ï+ùÑ+üÏ+ÔÏ+ÕÑ+ýÑ+Ï+ñÑ+ôÏ+ÝÑ+àÏ+×Ñ+ÚÏ+ÐÏ+ÑÑ+ÈÏ+ÉÑ+¨Ï+©Ñ+Ï+Ñ+üÏ+ýÑ+êÏ+ëÑ+ÖÏ+×Ñ+ÌÏ+ÍÑ+ÈÏ+ÉÑ+¬Ï+­Ñ+Ï+Ñ+Ï+Ñ+Ï+Ñ+þÏ+ÿÑ+§É1Ì1Ä1Å1»1¾1Æ1Ç1¹1¼111¶1·1³1¶1ð1ñ1£1¦1 1¡11111¿1Â111û1þ1ñ1ô1ç1ê1Â1Ã1ë1î1ß1â1Ë1Î1Å1È1¾1¿1¶1·11111ê1ë1Ø1Ù1Ä1Å1º1»1¶1·11111ø1ù1î1ï1ì1í1§·Å6ºÃ6²Ã6³Å6©Å6¬Ã6´Ã6µÅ6§Å6ªÃ6ùÅ6üÃ6¤Ã6¥Å6¡Å6¤Ã6ÞÃ6ßÅ6Å6Ã6Ã6Å6Ã6Å6Ã6Å6­Å6°Ã6óÅ6öÃ6éÅ6ìÃ6ßÅ6âÃ6ÕÅ6ØÃ6°Ã6±Å6ÙÅ6ÜÃ6ÍÅ6ÐÃ6¹Å6¼Ã6³Å6¶Ã6¬Ã6­Å6¤Ã6¥Å6Ã6Å6ðÃ6ñÅ6ØÃ6ÙÅ6ÆÃ6ÇÅ6²Ã6³Å6¨Ã6©Å6¤Ã6¥Å6Ã6Å6òÃ6óÅ6æÃ6çÅ6ÜÃ6ÝÅ6ÚÃ6ÛÅ6§¯³»²³¹ª³¹«³»¡³»¤³¹¬³¹­³»³»¢³¹ñ³»ô³¹³¹³»³»³¹Ö³¹×³»³»³¹³¹³»³¹³»³¹³»¥´»¨´¹ë²»î²¹á²»ä²¹×´»Ú´¹Í³»Ð³¹¨´¹©´»Ñ²»Ô²¹Å²»È²¹±²»´²¹«²»®²¹¤²¹¥²»²¹²»ü±¹ý±»è±¹é±»Ð±¹Ñ±»¾±¹¿±»ª±¹«±» ±¹¡±»±¹±»±¹±»ê°¹ë°»Þ°¹ß°»Ô°¹Õ°»Ò°¹Ó°»§°õ
+ °ó
+°ó
+°õ
+°õ
+°ó
+°ó
+°õ
+°õ
+°ó
+ß°õ
+â°ó
+°ó
+°õ
+°õ
+°ó
+Ä°ó
+Å°õ
+÷¯õ
+ú¯ó
+ô¯ó
+õ¯õ
+ò¯ó
+ó¯õ
+ð¯ó
+ñ¯õ
+±õ
+±ó
+Ù¯õ
+Ü¯ó
+Ï¯õ
+Ò¯ó
+Å±õ
+È±ó
+»°õ
+¾°ó
+±ó
+±õ
+¿¯õ
+Â¯ó
+³¯õ
+¶¯ó
+¯õ
+¢¯ó
+¯õ
+¯ó
+¯ó
+¯õ
+¯ó
+¯õ
+ê®ó
+ë®õ
+Ö®ó
+×®õ
+¾®ó
+¿®õ
+¬®ó
+­®õ
+®ó
+®õ
+®ó
+®õ
+®ó
+®õ
+î­ó
+ï­õ
+Ø­ó
+Ù­õ
+Ì­ó
+Í­õ
+Â­ó
+Ã­õ
+À­ó
+Á­õ
+§­¯­­­­­¯ý¬¯­­­­­¯û¬¯þ¬­Í­¯Ð­­ø¬­ù¬¯õ¬¯ø¬­²­­³­¯å¬¯è¬­â¬­ã¬¯à¬­á¬¯Þ¬­ß¬¯®¯®­Ç¬¯Ê¬­½¬¯À¬­³®¯¶®­©­¯¬­­®­®¯­¬¯°¬­¡¬¯¤¬­¬¯¬­¬¯¬­¬­¬¯ø«­ù«¯Ø«­Ù«¯Ä«­Å«¯¬«­­«¯«­«¯«­«¯üª­ýª¯øª­ùª¯Üª­Ýª¯Æª­Çª¯ºª­»ª¯°ª­±ª¯®ª­¯ª¯§ù©éü©çô©çõ©éë©éî©çö©ç÷©éé©éì©ç»ªé¾ªçæ©çç©éã©éæ©ç ªç¡ªéÓ©éÖ©çÐ©çÑ©éÎ©çÏ©éÌ©çÍ©éïªéòªçµ©é¸©ç«©é®©ç¡«é¤«çªéªçòªçóªé©é©ç©é©çû¨éþ¨çõ¨éø¨çî¨çï¨éæ¨çç¨éÆ¨çÇ¨é²¨ç³¨é¨ç¨é¨ç¨éô§çõ§éê§çë§éæ§çç§éÊ§çË§é´§çµ§é¨§ç©§é§ç§é§ç§é§ç¦£ê¦¡â¦¡ã¦£Ù¦£Ü¦¡ä¦¡å¦£×¦£Ú¦¡©§£¬§¡Ô¦¡Õ¦£Ñ¦£Ô¦¡§¡§£Á¦£Ä¦¡¾¦¡¿¦£¼¦¡½¦£º¦¡»¦£Ý§£à§¡£¦£¦¦¡¦£¦¡¨£¨¡§£§¡à§¡á§£¦£¦¡ý¥£¦¡é¥£ì¥¡ã¥£æ¥¡Ü¥¡Ý¥£Ô¥¡Õ¥£´¥¡µ¥£ ¥¡¡¥£¥¡¥£ö¤¡÷¤£â¤¡ã¤£Ø¤¡Ù¤£Ô¤¡Õ¤£¸¤¡¹¤£¢¤¡£¤£¤¡¤£¤¡¤£¤¡¤£§Õ£Ý Ø£Û Ð£Û Ñ£Ý Ç£Ý Ê£Û Ò£Û Ó£Ý Å£Ý È£Û ¤Ý ¤Û Â£Û Ã£Ý ¿£Ý Â£Û ü£Û ý£Ý ¯£Ý ²£Û ¬£Û ­£Ý ª£Û «£Ý ¨£Û ©£Ý Ë¤Ý Î¤Û £Ý £Û £Ý £Û ý¤Ý ¥Û ó£Ý ö£Û Î¤Û Ï¤Ý ÷¢Ý ú¢Û ë¢Ý î¢Û ×¢Ý Ú¢Û Ñ¢Ý Ô¢Û Ê¢Û Ë¢Ý Â¢Û Ã¢Ý ¢¢Û £¢Ý ¢Û ¢Ý ö¡Û ÷¡Ý ä¡Û å¡Ý Ð¡Û Ñ¡Ý Æ¡Û Ç¡Ý Â¡Û Ã¡Ý ¦¡Û §¡Ý ¡Û ¡Ý ¡Û ¡Ý ú Û û Ý ø Û ù Ý §Ã &Æ &¾ &¿ &µ &¸ &À &Á &³ &¶ &¡&¡&° &± &­ &° &ê &ë & &  & & & & & & &¹¡&¼¡&ÿ& &õ&ø&ë¡&î¡&á &ä &¼¡&½¡&å&è&Ù&Ü&Å&È&¿&Â&¸&¹&°&±&&&ü&ý&ä&å&Ò&Ó&¾&¿&´&µ&°&±&&&þ&ÿ&ò&ó&è&é&æ&ç&§±Ñ+´Ï+¬Ï+­Ñ+£Ñ+¦Ï+®Ï+¯Ñ+¡Ñ+¤Ï+óÑ+öÏ+Ï+Ñ+Ñ+Ï+ØÏ+ÙÑ+Ñ+Ï+Ï+Ñ+Ï+Ñ+Ï+Ñ+§Ñ+ªÏ+íÑ+ðÏ+ãÑ+æÏ+ÙÑ+ÜÏ+ÏÑ+ÒÏ+ªÏ+«Ñ+ÓÑ+ÖÏ+ÇÑ+ÊÏ+³Ñ+¶Ï+­Ñ+°Ï+¦Ï+§Ñ+Ï+Ñ+þÏ+ÿÑ+êÏ+ëÑ+ÒÏ+ÓÑ+ÀÏ+ÁÑ+¬Ï+­Ñ+¢Ï+£Ñ+Ï+Ñ+Ï+Ñ+ìÏ+íÑ+àÏ+áÑ+ÖÏ+×Ñ+ÔÏ+ÕÑ+§1¢111111111á1ä11111Æ1Ç1ù1ü1ö1÷1ô1õ1ò1ó111Û1Þ1Ñ1Ô1Ç1Ê1½1À111Á1Ä1µ1¸1¡1¤1111111ì1í1Ø1Ù1À1Á1®1¯1111111ð1ñ1Ú1Û1Î1Ï1Ä1Å1Â1Ã1§ÝÂ»àÂ¹ØÂ¹ÙÂ»ÏÂ»ÒÂ¹ÚÂ¹ÛÂ»ÍÂ»ÐÂ¹Ã»¢Ã¹ÊÂ¹ËÂ»ÇÂ»ÊÂ¹Ã¹Ã»·Â»ºÂ¹´Â¹µÂ»²Â¹³Â»°Â¹±Â»ÓÃ»ÖÃ¹Â»Â¹Â»Â¹Ä»Ä¹ûÂ»þÂ¹ÖÃ¹×Ã»ÿÁ»Â¹óÁ»öÁ¹ßÁ»âÁ¹ÙÁ»ÜÁ¹ÒÁ¹ÓÁ»ÊÁ¹ËÁ»ªÁ¹«Á»Á¹Á»þÀ¹ÿÀ»ìÀ¹íÀ»ØÀ¹ÙÀ»ÎÀ¹ÏÀ»ÊÀ¹ËÀ»®À¹¯À»À¹À»À¹À»À¹À»À¹À»§Ë¿õ
+Î¿ó
+Æ¿ó
+Ç¿õ
+½¿õ
+À¿ó
+È¿ó
+É¿õ
+»¿õ
+¾¿ó
+Àõ
+Àó
+¸¿ó
+¹¿õ
+µ¿õ
+¸¿ó
+ò¿ó
+ó¿õ
+¥¿õ
+¨¿ó
+¢¿ó
+£¿õ
+ ¿ó
+¡¿õ
+¿ó
+¿õ
+ÁÀõ
+ÄÀó
+¿õ
+¿ó
+ý¾õ
+¿ó
+óÀõ
+öÀó
+é¿õ
+ì¿ó
+ÄÀó
+ÅÀõ
+í¾õ
+ð¾ó
+á¾õ
+ä¾ó
+Í¾õ
+Ð¾ó
+Ç¾õ
+Ê¾ó
+À¾ó
+Á¾õ
+¸¾ó
+¹¾õ
+¾ó
+¾õ
+¾ó
+¾õ
+ì½ó
+í½õ
+Ú½ó
+Û½õ
+Æ½ó
+Ç½õ
+¼½ó
+½½õ
+¸½ó
+¹½õ
+½ó
+½õ
+½ó
+½õ
+ú¼ó
+û¼õ
+ð¼ó
+ñ¼õ
+î¼ó
+ï¼õ
+§¹¼¯¼¼­´¼­µ¼¯«¼¯®¼­¶¼­·¼¯©¼¯¬¼­û¼¯þ¼­¦¼­§¼¯£¼¯¦¼­à¼­á¼¯¼¯¼­¼­¼¯¼­¼¯¼­¼¯¯½¯²½­õ»¯ø»­ë»¯î»­á½¯ä½­×¼¯Ú¼­²½­³½¯Û»¯Þ»­Ï»¯Ò»­»»¯¾»­µ»¯¸»­®»­¯»¯¦»­§»¯»­»¯òº­óº¯Úº­Ûº¯Èº­Éº¯´º­µº¯ªº­«º¯¦º­§º¯º­º¯ô¹­õ¹¯è¹­é¹¯Þ¹­ß¹¯Ü¹­Ý¹¯§§¹éª¹ç¢¹ç£¹é¹é¹ç¤¹ç¥¹é¹é¹çé¹éì¹ç¹ç¹é¹é¹çÎ¹çÏ¹é¹é¹çþ¸çÿ¸éü¸çý¸éú¸çû¸éºé ºçã¸éæ¸çÙ¸éÜ¸çÏºéÒºçÅ¹éÈ¹ç ºç¡ºéÉ¸éÌ¸ç½¸éÀ¸ç©¸é¬¸ç£¸é¦¸ç¸ç¸é¸ç¸éô·çõ·éà·çá·éÈ·çÉ·é¶·ç··é¢·ç£·é·ç·é·ç·éø¶çù¶éâ¶çã¶éÖ¶ç×¶éÌ¶çÍ¶éÊ¶çË¶é§¶£¶¡¶¡¶£¶£¶¡¶¡¶£¶£¶¡×¶£Ú¶¡¶¡¶£ÿµ£¶¡¼¶¡½¶£ïµ£òµ¡ìµ¡íµ£êµ¡ëµ£èµ¡éµ£·£·¡Ñµ£Ôµ¡Çµ£Êµ¡½·£À·¡³¶£¶¶¡·¡·£·µ£ºµ¡«µ£®µ¡µ£µ¡µ£µ¡µ¡µ£µ¡µ£â´¡ã´£Î´¡Ï´£¶´¡·´£¤´¡¥´£´¡´£´¡´£´¡´£æ³¡ç³£Ð³¡Ñ³£Ä³¡Å³£º³¡»³£¸³¡¹³£§³Ý ³Û þ²Û ÿ²Ý õ²Ý ø²Û ³Û ³Ý ó²Ý ö²Û Å³Ý È³Û ð²Û ñ²Ý í²Ý ð²Û ª³Û «³Ý Ý²Ý à²Û Ú²Û Û²Ý Ø²Û Ù²Ý Ö²Û ×²Ý ù³Ý ü³Û ¿²Ý Â²Û µ²Ý ¸²Û «´Ý ®´Û ¡³Ý ¤³Û ü³Û ý³Ý ¥²Ý ¨²Û ²Ý ²Û ²Ý ²Û ÿ±Ý ²Û ø±Û ù±Ý ð±Û ñ±Ý Ð±Û Ñ±Ý ¼±Û ½±Ý ¤±Û ¥±Ý ±Û ±Ý þ°Û ÿ°Ý ô°Û õ°Ý ð°Û ñ°Ý Ô°Û Õ°Ý ¾°Û ¿°Ý ²°Û ³°Ý ¨°Û ©°Ý ¦°Û §°Ý §ñ¯&ô¯&ì¯&í¯&ã¯&æ¯&î¯&ï¯&á¯&ä¯&³°&¶°&Þ¯&ß¯&Û¯&Þ¯&°&°&Ë¯&Î¯&È¯&É¯&Æ¯&Ç¯&Ä¯&Å¯&ç°&ê°&­¯&°¯&£¯&¦¯&±&±&°&°&ê°&ë°&¯&¯&¯&¯&ó®&ö®&í®&ð®&æ®&ç®&Þ®&ß®&¾®&¿®&ª®&«®&®&®&®&®&ì­&í­&â­&ã­&Þ­&ß­&Â­&Ã­&¬­&­­& ­&¡­&­&­&­&­&§ß¬Ñ+â¬Ï+Ú¬Ï+Û¬Ñ+Ñ¬Ñ+Ô¬Ï+Ü¬Ï+Ý¬Ñ+Ï¬Ñ+Ò¬Ï+¡­Ñ+¤­Ï+Ì¬Ï+Í¬Ñ+É¬Ñ+Ì¬Ï+­Ï+­Ñ+¹¬Ñ+¼¬Ï+¶¬Ï+·¬Ñ+´¬Ï+µ¬Ñ+²¬Ï+³¬Ñ+Õ­Ñ+Ø­Ï+¬Ñ+¬Ï+¬Ñ+¬Ï+®Ñ+®Ï+ý¬Ñ+­Ï+Ø­Ï+Ù­Ñ+¬Ñ+¬Ï+õ«Ñ+ø«Ï+á«Ñ+ä«Ï+Û«Ñ+Þ«Ï+Ô«Ï+Õ«Ñ+Ì«Ï+Í«Ñ+¬«Ï+­«Ñ+«Ï+«Ñ+«Ï+«Ñ+îªÏ+ïªÑ+ÚªÏ+ÛªÑ+ÐªÏ+ÑªÑ+ÌªÏ+ÍªÑ+°ªÏ+±ªÑ+ªÏ+ªÑ+ªÏ+ªÑ+ªÏ+ªÑ+ªÏ+ªÑ+§ãÏ»æÏ¹ÞÏ¹ßÏ»ÕÏ»ØÏ¹àÏ¹áÏ»ÓÏ»ÖÏ¹¥Ð»¨Ð¹ÐÏ¹ÑÏ»ÍÏ»ÐÏ¹Ð¹Ð»½Ï»ÀÏ¹ºÏ¹»Ï»¸Ï¹¹Ï»¶Ï¹·Ï»ÙÐ»ÜÐ¹Ï»¢Ï¹Ï»Ï¹Ñ»Ñ¹Ð»Ð¹ÜÐ¹ÝÐ»Ï»Ï¹ùÎ»üÎ¹åÎ»èÎ¹ßÎ»âÎ¹ØÎ¹ÙÎ»ÐÎ¹ÑÎ»°Î¹±Î»Î¹Î»Î¹Î»òÍ¹óÍ»ÞÍ¹ßÍ»ÔÍ¹ÕÍ»ÐÍ¹ÑÍ»´Í¹µÍ»Í¹Í»Í¹Í»Í¹Í»Í¹Í»§ÑÌõ
+ÔÌó
+ÌÌó
+ÍÌõ
+ÃÌõ
+ÆÌó
+ÎÌó
+ÏÌõ
+ÁÌõ
+ÄÌó
+Íõ
+Íó
+¾Ìó
+¿Ìõ
+»Ìõ
+¾Ìó
+øÌó
+ùÌõ
+«Ìõ
+®Ìó
+¨Ìó
+©Ìõ
+¦Ìó
+§Ìõ
+¤Ìó
+¥Ìõ
+ÇÍõ
+ÊÍó
+Ìõ
+Ìó
+Ìõ
+Ìó
+ùÍõ
+üÍó
+ïÌõ
+òÌó
+ÊÍó
+ËÍõ
+óËõ
+öËó
+çËõ
+êËó
+ÓËõ
+ÖËó
+ÍËõ
+ÐËó
+ÆËó
+ÇËõ
+¾Ëó
+¿Ëõ
+Ëó
+Ëõ
+Ëó
+Ëõ
+òÊó
+óÊõ
+àÊó
+áÊõ
+ÌÊó
+ÍÊõ
+ÂÊó
+ÃÊõ
+¾Êó
+¿Êõ
+¢Êó
+£Êõ
+Êó
+Êõ
+Êó
+Êõ
+öÉó
+÷Éõ
+ôÉó
+õÉõ
+§¿É¯ÂÉ­ºÉ­»É¯±É¯´É­¼É­½É¯¯É¯²É­Ê¯Ê­¬É­­É¯©É¯¬É­æÉ­çÉ¯É¯É­É­É¯É­É¯É­É¯µÊ¯¸Ê­ûÈ¯þÈ­ñÈ¯ôÈ­çÊ¯êÊ­ÝÉ¯àÉ­¸Ê­¹Ê¯áÈ¯äÈ­ÕÈ¯ØÈ­ÁÈ¯ÄÈ­»È¯¾È­´È­µÈ¯¬È­­È¯È­È¯øÇ­ùÇ¯àÇ­áÇ¯ÎÇ­ÏÇ¯ºÇ­»Ç¯°Ç­±Ç¯¬Ç­­Ç¯Ç­Ç¯úÆ­ûÆ¯îÆ­ïÆ¯äÆ­åÆ¯âÆ­ãÆ¯§­Æé°Æç¨Æç©ÆéÆé¢ÆçªÆç«ÆéÆé ÆçïÆéòÆçÆçÆéÆéÆçÔÆçÕÆéÆéÆçÆçÆéÆçÆéÆçÆé£Çé¦ÇçéÅéìÅçßÅéâÅçÕÇéØÇçËÆéÎÆç¦Çç§ÇéÏÅéÒÅçÃÅéÆÅç¯Åé²Åç©Åé¬Åç¢Åç£ÅéÅçÅéúÄçûÄéæÄççÄéÎÄçÏÄé¼Äç½Äé¨Äç©ÄéÄçÄéÄçÄéþÃçÿÃéèÃçéÃéÜÃçÝÃéÒÃçÓÃéÐÃçÑÃé§Ã£Ã¡Ã¡Ã£Ã£Ã¡Ã¡Ã£Ã£Ã¡ÝÃ£àÃ¡Ã¡Ã£Ã£Ã¡ÂÃ¡ÃÃ£õÂ£øÂ¡òÂ¡óÂ£ðÂ¡ñÂ£îÂ¡ïÂ£Ä£Ä¡×Â£ÚÂ¡ÍÂ£ÐÂ¡ÃÄ£ÆÄ¡¹Ã£¼Ã¡Ä¡Ä£½Â£ÀÂ¡±Â£´Â¡Â£ Â¡Â£Â¡Â¡Â£Â¡Â£èÁ¡éÁ£ÔÁ¡ÕÁ£¼Á¡½Á£ªÁ¡«Á£Á¡Á£Á¡Á£Á¡Á£ìÀ¡íÀ£ÖÀ¡×À£ÊÀ¡ËÀ£ÀÀ¡ÁÀ£¾À¡¿À£§ÀÝ ÀÛ ÀÛ ÀÝ û¿Ý þ¿Û ÀÛ ÀÝ ù¿Ý ü¿Û ËÀÝ ÎÀÛ ö¿Û ÷¿Ý ó¿Ý ö¿Û °ÀÛ ±ÀÝ ã¿Ý æ¿Û à¿Û á¿Ý Þ¿Û ß¿Ý Ü¿Û Ý¿Ý ÿÀÝ ÁÛ Å¿Ý È¿Û »¿Ý ¾¿Û ±ÁÝ ´ÁÛ §ÀÝ ªÀÛ ÁÛ ÁÝ «¿Ý ®¿Û ¿Ý ¢¿Û ¿Ý ¿Û ¿Ý ¿Û þ¾Û ÿ¾Ý ö¾Û ÷¾Ý Ö¾Û ×¾Ý Â¾Û Ã¾Ý ª¾Û «¾Ý ¾Û ¾Ý ¾Û ¾Ý ú½Û û½Ý ö½Û ÷½Ý Ú½Û Û½Ý Ä½Û Å½Ý ¸½Û ¹½Ý ®½Û ¯½Ý ¬½Û ­½Ý §÷¼&ú¼&ò¼&ó¼&é¼&ì¼&ô¼&õ¼&ç¼&ê¼&¹½&¼½&ä¼&å¼&á¼&ä¼&½&½&Ñ¼&Ô¼&Î¼&Ï¼&Ì¼&Í¼&Ê¼&Ë¼&í½&ð½&³¼&¶¼&©¼&¬¼&¾&¢¾&½&½&ð½&ñ½&¼&¼&¼&¼&ù»&ü»&ó»&ö»&ì»&í»&ä»&å»&Ä»&Å»&°»&±»&»&»&»&»&òº&óº&èº&éº&äº&åº&Èº&Éº&²º&³º&¦º&§º&º&º&º&º&§ÁÚ»ÄÚ¹¼Ú¹½Ú»³Ú»¶Ú¹¾Ú¹¿Ú»±Ú»´Ú¹Û»Û¹®Ú¹¯Ú»«Ú»®Ú¹èÚ¹éÚ»Ú»Ú¹Ú¹Ú»Ú¹Ú»Ú¹Ú»·Û»ºÛ¹ýÙ»Ú¹óÙ»öÙ¹éÛ»ìÛ¹ßÚ»âÚ¹ºÛ¹»Û»ãÙ»æÙ¹×Ù»ÚÙ¹ÃÙ»ÆÙ¹½Ù»ÀÙ¹¶Ù¹·Ù»®Ù¹¯Ù»Ù¹Ù»úØ¹ûØ»âØ¹ãØ»ÐØ¹ÑØ»¼Ø¹½Ø»²Ø¹³Ø»®Ø¹¯Ø»Ø¹Ø»ü×¹ý×»ð×¹ñ×»æ×¹ç×»ä×¹å×»§¯×õ
+²×ó
+ª×ó
+«×õ
+¡×õ
+¤×ó
+¬×ó
+­×õ
+×õ
+¢×ó
+ñ×õ
+ô×ó
+×ó
+×õ
+×õ
+×ó
+Ö×ó
+××õ
+×õ
+×ó
+×ó
+×õ
+×ó
+×õ
+×ó
+×õ
+¥Øõ
+¨Øó
+ëÖõ
+îÖó
+áÖõ
+äÖó
+×Øõ
+ÚØó
+Í×õ
+Ð×ó
+¨Øó
+©Øõ
+ÑÖõ
+ÔÖó
+ÅÖõ
+ÈÖó
+±Öõ
+´Öó
+«Öõ
+®Öó
+¤Öó
+¥Öõ
+Öó
+Öõ
+üÕó
+ýÕõ
+èÕó
+éÕõ
+ÐÕó
+ÑÕõ
+¾Õó
+¿Õõ
+ªÕó
+«Õõ
+ Õó
+¡Õõ
+Õó
+Õõ
+Õó
+Õõ
+êÔó
+ëÔõ
+ÞÔó
+ßÔõ
+ÔÔó
+ÕÔõ
+ÒÔó
+ÓÔõ
+§Ô¯ Ô­Ô­Ô¯Ô¯Ô­Ô­Ô¯Ô¯Ô­ßÔ¯âÔ­Ô­Ô¯Ô¯Ô­ÄÔ­ÅÔ¯÷Ó¯úÓ­ôÓ­õÓ¯òÓ­óÓ¯ðÓ­ñÓ¯Õ¯Õ­ÙÓ¯ÜÓ­ÏÓ¯ÒÓ­ÅÕ¯ÈÕ­»Ô¯¾Ô­Õ­Õ¯¿Ó¯ÂÓ­³Ó¯¶Ó­Ó¯¢Ó­Ó¯Ó­Ó­Ó¯Ó­Ó¯êÒ­ëÒ¯ÖÒ­×Ò¯¾Ò­¿Ò¯¬Ò­­Ò¯Ò­Ò¯Ò­Ò¯Ò­Ò¯îÑ­ïÑ¯ØÑ­ÙÑ¯ÌÑ­ÍÑ¯ÂÑ­ÃÑ¯ÀÑ­ÁÑ¯§ÑéÑçÑçÑéýÐéÑçÑçÑéûÐéþÐçÍÑéÐÑçøÐçùÐéõÐéøÐç²Ñç³ÑéåÐéèÐçâÐçãÐéàÐçáÐéÞÐçßÐéÒéÒçÇÐéÊÐç½ÐéÀÐç³Òé¶Òç©Ñé¬ÑçÒçÒé­Ðé°Ðç¡Ðé¤ÐçÐéÐçÐéÐçÐçÐéøÏçùÏéØÏçÙÏéÄÏçÅÏé¬Ïç­ÏéÏçÏéÏçÏéüÎçýÎéøÎçùÎéÜÎçÝÎéÆÎçÇÎéºÎç»Îé°Îç±Îé®Îç¯Îé§ùÍ£üÍ¡ôÍ¡õÍ£ëÍ£îÍ¡öÍ¡÷Í£éÍ£ìÍ¡»Î£¾Î¡æÍ¡çÍ£ãÍ£æÍ¡ Î¡¡Î£ÓÍ£ÖÍ¡ÐÍ¡ÑÍ£ÎÍ¡ÏÍ£ÌÍ¡ÍÍ£ïÎ£òÎ¡µÍ£¸Í¡«Í£®Í¡¡Ï£¤Ï¡Î£Î¡òÎ¡óÎ£Í£Í¡Í£Í¡ûÌ£þÌ¡õÌ£øÌ¡îÌ¡ïÌ£æÌ¡çÌ£ÆÌ¡ÇÌ£²Ì¡³Ì£Ì¡Ì£Ì¡Ì£ôË¡õË£êË¡ëË£æË¡çË£ÊË¡ËË£´Ë¡µË£¨Ë¡©Ë£Ë¡Ë£Ë¡Ë£§çÊÝ êÊÛ âÊÛ ãÊÝ ÙÊÝ ÜÊÛ äÊÛ åÊÝ ×ÊÝ ÚÊÛ ©ËÝ ¬ËÛ ÔÊÛ ÕÊÝ ÑÊÝ ÔÊÛ ËÛ ËÝ ÁÊÝ ÄÊÛ ¾ÊÛ ¿ÊÝ ¼ÊÛ ½ÊÝ ºÊÛ »ÊÝ ÝËÝ àËÛ £ÊÝ ¦ÊÛ ÊÝ ÊÛ ÌÝ ÌÛ ËÝ ËÛ àËÛ áËÝ ÊÝ ÊÛ ýÉÝ ÊÛ éÉÝ ìÉÛ ãÉÝ æÉÛ ÜÉÛ ÝÉÝ ÔÉÛ ÕÉÝ ´ÉÛ µÉÝ  ÉÛ ¡ÉÝ ÉÛ ÉÝ öÈÛ ÷ÈÝ âÈÛ ãÈÝ ØÈÛ ÙÈÝ ÔÈÛ ÕÈÝ ¸ÈÛ ¹ÈÝ ¢ÈÛ £ÈÝ ÈÛ ÈÝ ÈÛ ÈÝ ÈÛ ÈÝ §÷â»úâ¹òâ¹óâ»éâ»ìâ¹ôâ¹õâ»çâ»êâ¹¹ã»¼ã¹äâ¹åâ»áâ»äâ¹ã¹ã»Ñâ»Ôâ¹Îâ¹Ïâ»Ìâ¹Íâ»Êâ¹Ëâ»íã»ðã¹³â»¶â¹©â»¬â¹ä»¢ä¹ã»ã¹ðã¹ñã»â»â¹â»â¹ùá»üá¹óá»öá¹ìá¹íá»äá¹åá»Äá¹Åá»°á¹±á»á¹á»á¹á»òà¹óà»èà¹éà»äà¹åà»Èà¹Éà»²à¹³à»¦à¹§à»à¹à»à¹à»§åßõ
+èßó
+àßó
+áßõ
+×ßõ
+Úßó
+âßó
+ãßõ
+Õßõ
+Øßó
+§àõ
+ªàó
+Òßó
+Óßõ
+Ïßõ
+Òßó
+àó
+àõ
+¿ßõ
+Âßó
+¼ßó
+½ßõ
+ºßó
+»ßõ
+¸ßó
+¹ßõ
+Ûàõ
+Þàó
+¡ßõ
+¤ßó
+ßõ
+ßó
+áõ
+áó
+àõ
+àó
+Þàó
+ßàõ
+ßõ
+ßó
+ûÞõ
+þÞó
+çÞõ
+êÞó
+áÞõ
+äÞó
+ÚÞó
+ÛÞõ
+ÒÞó
+ÓÞõ
+²Þó
+³Þõ
+Þó
+Þõ
+Þó
+Þõ
+ôÝó
+õÝõ
+àÝó
+áÝõ
+ÖÝó
+×Ýõ
+ÒÝó
+ÓÝõ
+¶Ýó
+·Ýõ
+ Ýó
+¡Ýõ
+Ýó
+Ýõ
+Ýó
+Ýõ
+Ýó
+Ýõ
+§ÓÜ¯ÖÜ­ÎÜ­ÏÜ¯ÅÜ¯ÈÜ­ÐÜ­ÑÜ¯ÃÜ¯ÆÜ­Ý¯Ý­ÀÜ­ÁÜ¯½Ü¯ÀÜ­úÜ­ûÜ¯­Ü¯°Ü­ªÜ­«Ü¯¨Ü­©Ü¯¦Ü­§Ü¯ÉÝ¯ÌÝ­Ü¯Ü­Ü¯Ü­ûÝ¯þÝ­ñÜ¯ôÜ­ÌÝ­ÍÝ¯õÛ¯øÛ­éÛ¯ìÛ­ÕÛ¯ØÛ­ÏÛ¯ÒÛ­ÈÛ­ÉÛ¯ÀÛ­ÁÛ¯ Û­¡Û¯Û­Û¯ôÚ­õÚ¯âÚ­ãÚ¯ÎÚ­ÏÚ¯ÄÚ­ÅÚ¯ÀÚ­ÁÚ¯¤Ú­¥Ú¯Ú­Ú¯Ú­Ú¯øÙ­ùÙ¯öÙ­÷Ù¯§ÁÙéÄÙç¼Ùç½Ùé³Ùé¶Ùç¾Ùç¿Ùé±Ùé´ÙçÚéÚç®Ùç¯Ùé«Ùé®ÙçèÙçéÙéÙéÙçÙçÙéÙçÙéÙçÙé·ÚéºÚçýØéÙçóØéöØçéÚéìÚçßÙéâÙçºÚç»ÚéãØéæØç×ØéÚØçÃØéÆØç½ØéÀØç¶Øç·Øé®Øç¯ØéØçØéú×çû×éâ×çã×éÐ×çÑ×é¼×ç½×é²×ç³×é®×ç¯×é×ç×éüÖçýÖéðÖçñÖéæÖççÖéäÖçåÖé§¯Ö£²Ö¡ªÖ¡«Ö£¡Ö£¤Ö¡¬Ö¡­Ö£Ö£¢Ö¡ñÖ£ôÖ¡Ö¡Ö£Ö£Ö¡ÖÖ¡×Ö£Ö£Ö¡Ö¡Ö£Ö¡Ö£Ö¡Ö£¥×£¨×¡ëÕ£îÕ¡áÕ£äÕ¡××£Ú×¡ÍÖ£ÐÖ¡¨×¡©×£ÑÕ£ÔÕ¡ÅÕ£ÈÕ¡±Õ£´Õ¡«Õ£®Õ¡¤Õ¡¥Õ£Õ¡Õ£üÔ¡ýÔ£èÔ¡éÔ£ÐÔ¡ÑÔ£¾Ô¡¿Ô£ªÔ¡«Ô£ Ô¡¡Ô£Ô¡Ô£Ô¡Ô£êÓ¡ëÓ£ÞÓ¡ßÓ£ÔÓ¡ÕÓ£ÒÓ¡ÓÓ£§é»é¹é¹é»÷è»úè¹é¹é»õè»øè¹Çé»Êé¹òè¹óè»ïè»òè¹¬é¹­é»ßè»âè¹Üè¹Ýè»Úè¹Ûè»Øè¹Ùè»ûé»þé¹Áè»Äè¹·è»ºè¹­ê»°ê¹£é»¦é¹þé¹ÿé»§è»ªè¹è»è¹è»è¹è»è¹úç¹ûç»òç¹óç»Òç¹Óç»¾ç¹¿ç»¦ç¹§ç»ç¹ç»ç¹ç»öæ¹÷æ»òæ¹óæ»Öæ¹×æ»Àæ¹Áæ»´æ¹µæ»ªæ¹«æ»¨æ¹©æ»§óåõ
+öåó
+îåó
+ïåõ
+ååõ
+èåó
+ðåó
+ñåõ
+ãåõ
+æåó
+µæõ
+¸æó
+àåó
+áåõ
+Ýåõ
+àåó
+æó
+æõ
+Íåõ
+Ðåó
+Êåó
+Ëåõ
+Èåó
+Éåõ
+Æåó
+Çåõ
+éæõ
+ìæó
+¯åõ
+²åó
+¥åõ
+¨åó
+çõ
+çó
+æõ
+æó
+ìæó
+íæõ
+åõ
+åó
+åõ
+åó
+õäõ
+øäó
+ïäõ
+òäó
+èäó
+éäõ
+àäó
+áäõ
+Àäó
+Áäõ
+¬äó
+­äõ
+äó
+äõ
+äó
+äõ
+îãó
+ïãõ
+äãó
+åãõ
+àãó
+áãõ
+Äãó
+Åãõ
+®ãó
+¯ãõ
+¢ãó
+£ãõ
+ãó
+ãõ
+ãó
+ãõ
+§áâ¯äâ­Üâ­Ýâ¯Óâ¯Öâ­Þâ­ßâ¯Ñâ¯Ôâ­£ã¯¦ã­Îâ­Ïâ¯Ëâ¯Îâ­ã­ã¯»â¯¾â­¸â­¹â¯¶â­·â¯´â­µâ¯×ã¯Úã­â¯ â­â¯â­ä¯ä­ÿâ¯ã­Úã­Ûã¯â¯â­÷á¯úá­ãá¯æá­Ýá¯àá­Öá­×á¯Îá­Ïá¯®á­¯á¯á­á¯á­á¯ðà­ñà¯Üà­Ýà¯Òà­Óà¯Îà­Ïà¯²à­³à¯à­à¯à­à¯à­à¯à­à¯§ÏßéÒßçÊßçËßéÁßéÄßçÌßçÍßé¿ßéÂßçàéàç¼ßç½ßé¹ßé¼ßçößç÷ßé©ßé¬ßç¦ßç§ßé¤ßç¥ßé¢ßç£ßéÅàéÈàçßéßçßéßç÷àéúàçíßéðßçÈàçÉàéñÞéôÞçåÞéèÞçÑÞéÔÞçËÞéÎÞçÄÞçÅÞé¼Þç½ÞéÞçÞéÞçÞéðÝçñÝéÞÝçßÝéÊÝçËÝéÀÝçÁÝé¼Ýç½Ýé Ýç¡ÝéÝçÝéþÜçÿÜéôÜçõÜéòÜçóÜé§ëì»îì¹æì¹çì»Ýì»àì¹èì¹éì»Ûì»Þì¹­í»°í¹Øì¹Ùì»Õì»Øì¹í¹í»Åì»Èì¹Âì¹Ãì»Àì¹Áì»¾ì¹¿ì»áí»äí¹§ì»ªì¹ì» ì¹î»î¹í»í¹äí¹åí»ì»ì¹ì»ì¹íë»ðë¹çë»êë¹àë¹áë»Øë¹Ùë»¸ë¹¹ë»¤ë¹¥ë»ë¹ë»úê¹ûê»æê¹çê»Üê¹Ýê»Øê¹Ùê»¼ê¹½ê»¦ê¹§ê»ê¹ê»ê¹ê»ê¹ê»§Ùéõ
+Üéó
+Ôéó
+Õéõ
+Ëéõ
+Îéó
+Öéó
+×éõ
+Ééõ
+Ìéó
+êõ
+êó
+Æéó
+Çéõ
+Ãéõ
+Æéó
+êó
+êõ
+³éõ
+¶éó
+°éó
+±éõ
+®éó
+¯éõ
+¬éó
+­éõ
+Ïêõ
+Òêó
+éõ
+éó
+éõ
+éó
+ëõ
+ëó
+÷éõ
+úéó
+Òêó
+Óêõ
+ûèõ
+þèó
+ïèõ
+òèó
+Ûèõ
+Þèó
+Õèõ
+Øèó
+Îèó
+Ïèõ
+Æèó
+Çèõ
+¦èó
+§èõ
+èó
+èõ
+úçó
+ûçõ
+èçó
+éçõ
+Ôçó
+Õçõ
+Êçó
+Ëçõ
+Æçó
+Ççõ
+ªçó
+«çõ
+çó
+çõ
+çó
+çõ
+þæó
+ÿæõ
+üæó
+ýæõ
+§Çæ¯Êæ­Âæ­Ãæ¯¹æ¯¼æ­Äæ­Åæ¯·æ¯ºæ­ç¯ç­´æ­µæ¯±æ¯´æ­îæ­ïæ¯¡æ¯¤æ­æ­æ¯æ­æ¯æ­æ¯½ç¯Àç­æ¯æ­ùå¯üå­ïç¯òç­åæ¯èæ­Àç­Áç¯éå¯ìå­Ýå¯àå­Éå¯Ìå­Ãå¯Æå­¼å­½å¯´å­µå¯å­å¯å­å¯èä­éä¯Öä­×ä¯Âä­Ãä¯¸ä­¹ä¯´ä­µä¯ä­ä¯ä­ä¯öã­÷ã¯ìã­íã¯êã­ëã¯§©î»¬î¹¤î¹¥î»î»î¹¦î¹§î»î»î¹ëî»îî¹î¹î»î»î¹Ðî¹Ñî»î»î¹î¹î»þí¹ÿí»üí¹ýí»ï»¢ï¹åí»èí¹Ûí»Þí¹Ñï»Ôï¹Çî»Êî¹¢ï¹£ï»Ëí»Îí¹¿í»Âí¹«í»®í¹¥í»¨í¹í¹í»í¹í»öì¹÷ì»âì¹ãì»Êì¹Ëì»¸ì¹¹ì»¤ì¹¥ì»ì¹ì»ì¹ì»úë¹ûë»äë¹åë»Øë¹Ùë»Îë¹Ïë»Ìë¹Íë»§ëõ
+ëó
+ëó
+ëõ
+ëõ
+ëó
+ëó
+ëõ
+ëõ
+ëó
+Ùëõ
+Üëó
+ëó
+ëõ
+ëõ
+ëó
+¾ëó
+¿ëõ
+ñêõ
+ôêó
+îêó
+ïêõ
+ìêó
+íêõ
+êêó
+ëêõ
+ìõ
+ìó
+Óêõ
+Öêó
+Éêõ
+Ìêó
+¿ìõ
+Âìó
+µëõ
+¸ëó
+ìó
+ìõ
+¹êõ
+¼êó
+­êõ
+°êó
+êõ
+êó
+êõ
+êó
+êó
+êõ
+êó
+êõ
+äéó
+åéõ
+Ðéó
+Ñéõ
+¸éó
+¹éõ
+¦éó
+§éõ
+éó
+éõ
+éó
+éõ
+éó
+éõ
+èèó
+éèõ
+Òèó
+Óèõ
+Æèó
+Çèõ
+¼èó
+½èõ
+ºèó
+»èõ
+§¿í»Âí¹ºí¹»í»±í»´í¹¼í¹½í»¯í»²í¹î»î¹¬í¹­í»©í»¬í¹æí¹çí»í»í¹í¹í»í¹í»í¹í»µî»¸î¹ûì»þì¹ñì»ôì¹çî»êî¹Ýí»àí¹¸î¹¹î»áì»äì¹Õì»Øì¹Áì»Äì¹»ì»¾ì¹´ì¹µì»¬ì¹­ì»ì¹ì»øë¹ùë»àë¹áë»Îë¹Ïë»ºë¹»ë»°ë¹±ë»¬ë¹­ë»ë¹ë»úê¹ûê»îê¹ïê»äê¹åê»âê¹ãê»§ë_ë÷êëíæëë¡íÎëAë³ëëë¦ë1ë#'ßîáîìë³»ë«ëD4'	²î²î½ëìÔë2þì?®ëDþêìwôëG	¤î¤î ¤ì/ì9"¨î¨îìµìÉöë%ìÀìv4ìîìîJãì´ì{|ÃïÅï¦íó§íõîÀîÀêíÌëíÌªí«íîÈîÈèíÅéíÇóóóõôÀôÀÒóÌÓóÌóóôÈôÈÐóÅÑóÇöøó÷øõîùÀïùÀºùÌ»ùÌúøûøêùÈëùÈ¸ùÅ¹ùÇÞþóßþõÖÿÀ×ÿÀ¢ÿÌ£ÿÌâþãþÒÿÈÓÿÈ ÿÅ¡ÿÇÆóÇõ¾À¿ÀÌÌÊËºÈ»ÈÅÇ®ó¯õ¦À§ÀòÌóÌ²³¢È£ÈðÅñÇóõÀÀÚÌÛÌÈÈØÅÙÇþóÿõöÀ÷ÀÂÌÃÌòÈóÈÀÅÁÇæóçõÞÀßÀªÌ«ÌêëÚÈÛÈ¨Å©ÇÎ¡óÏ¡õÆ¢ÀÇ¢À¢Ì¢ÌÒ¡Ó¡Â¢ÈÃ¢È¢Å¢Ç¶§ó·§õ®¨À¯¨Àú§Ìû§Ìº§»§ª¨È«¨Èø§Åù§Ç­ó­õ®À®Àâ­Ìã­Ì¢­£­®È®Èà­Åá­Ç³ó³õþ³Àÿ³ÀÊ³ÌË³Ì³³ú³Èû³ÈÈ³ÅÉ³Çî¸óï¸õæ¹Àç¹À²¹Ì³¹Ìò¸ó¸â¹Èã¹È°¹Å±¹ÇÖ¾ó×¾õÎ¿ÀÏ¿À¿Ì¿ÌÚ¾Û¾Ê¿ÈË¿È¿Å¿Ç¾Äó¿Äõ¶ÅÀ·ÅÀÅÌÅÌÂÄÃÄ²ÅÈ³ÅÈÅÅÅÇ¦Êó§ÊõËÀËÀêÊÌëÊÌªÊ«ÊËÈËÈèÊÅéÊÇÐóÐõÑÀÑÀÒÐÌÓÐÌÐÐÑÈÑÈÐÐÅÑÐÇöÕó÷ÕõîÖÀïÖÀºÖÌ»ÖÌúÕûÕêÖÈëÖÈ¸ÖÅ¹ÖÇÞÛóßÛõÖÜÀ×ÜÀ¢ÜÌ£ÜÌâÛãÛÒÜÈÓÜÈ ÜÅ¡ÜÇÆáóÇáõ¾âÀ¿âÀâÌâÌÊáËáºâÈ»âÈâÅâÇ®çó¯çõ¦èÀ§èÀòçÌóçÌ²ç³ç¢èÈ£èÈðçÅñçÇíóíõîÀîÀÚíÌÛíÌííîÈîÈØíÅÙíÇþòóÿòõöóÀ÷óÀÂóÌÃóÌóóòóÈóóÈÀóÅÁóÇæøóçøõÞùÀßùÀªùÌ«ùÌêøëøÚùÈÛùÈ¨ùÅ©ùÇÎþóÏþõÆÿÀÇÿÀÿÌÿÌÒþÓþÂÿÈÃÿÈÿÅÿÇ¶ó·õ®À¯ÀúÌûÌº»ªÈ«ÈøÅùÇóõÀÀâÌãÌ¢£ÈÈàÅáÇóõþÀÿÀÊÌËÌúÈûÈÈÅÉÇîóïõæÀçÀ²Ì³ÌòóâÈãÈ°Å±ÇÖó×õÎÀÏÀÌÌÚÛÊÈËÈÅÇ¾¡ó¿¡õ¶¢À·¢À¢Ì¢ÌÂ¡Ã¡²¢È³¢È¢Å¢Ç¦§ó§§õ¨À¨Àê§Ìë§Ìª§«§¨È¨Èè§Åé§Ç­ó­õ®À®ÀÒ­ÌÓ­Ì­­®È®ÈÐ­ÅÑ­Çö²ó÷²õî³Àï³Àº³Ì»³Ìú²û²ê³Èë³È¸³Å¹³ÇÞ¸óß¸õÖ¹À×¹À¢¹Ì£¹Ìâ¸ã¸Ò¹ÈÓ¹È ¹Å¡¹ÇÆ¾óÇ¾õ¾¿À¿¿À¿Ì¿ÌÊ¾Ë¾º¿È»¿È¿Å¿Ç®Äó¯Äõ¦ÅÀ§ÅÀòÄÌóÄÌ²Ä³Ä¢ÅÈ£ÅÈðÄÅñÄÇÊóÊõËÀËÀÚÊÌÛÊÌÊÊËÈËÈØÊÅÙÊÇþÏóÿÏõöÐÀ÷ÐÀÂÐÌÃÐÌÐÐòÐÈóÐÈÀÐÅÁÐÇæÕóçÕõÞÖÀßÖÀªÖÌ«ÖÌêÕëÕÚÖÈÛÖÈ¨ÖÅ©ÖÇÎÛóÏÛõÆÜÀÇÜÀÜÌÜÌÒÛÓÛÂÜÈÃÜÈÜÅÜÇ¶áó·áõ®âÀ¯âÀúáÌûáÌºá»áªâÈ«âÈøáÅùáÇçóçõèÀèÀâçÌãçÌ¢ç£çèÈèÈàçÅáçÇíóíõþíÀÿíÀÊíÌËíÌííúíÈûíÈÈíÅÉíÇîòóïòõæóÀçóÀ²óÌ³óÌòòóòâóÈãóÈ°óÅ±óÇÖøó×øõÎùÀÏùÀùÌùÌÚøÛøÊùÈËùÈùÅùÇ¾þó¿þõ¶ÿÀ·ÿÀÿÌÿÌÂþÃþ²ÿÈ³ÿÈÿÅÿÇ¦ó§õÀÀêÌëÌª«ÈÈèÅéÇóõÀÀÒÌÓÌÈÈÐÅÑÇöó÷õîÀïÀºÌ»ÌúûêÈëÈ¸Å¹ÇÞóßõÖÀ×À¢Ì£ÌâãÒÈÓÈ Å¡ÇÆóÇõ¾À¿ÀÌÌÊËºÈ»ÈÅÇ®¡ó¯¡õ¦¢À§¢Àò¡Ìó¡Ì²¡³¡¢¢È£¢Èð¡Åñ¡Ç§ó§õ¨À¨ÀÚ§ÌÛ§Ì§§¨È¨ÈØ§ÅÙ§Çþ¬ñÿ¬óö­¾÷­¾Â­ÊÃ­Ê­­ò­Æó­ÆÀ­ÃÁ­Åß¹â¹ã¹æ¹é¹ì¹ï¹ò¹õ¹ø¹û¹þ¹³¸³¸´Ù´ÛÖ³×³³×³Ù´ó´õÔ³Õ³.^¾îÎþ®Þ¾îÎþ®Þ¾îÎþ®	Þ	
+¾
+î
+Îþ®Þ¾îÎþ®Þ¾îÎþ®Þ¾îÎþ®Ý
diff --git a/tests/long-test.hs b/tests/long-test.hs
new file mode 100644
--- /dev/null
+++ b/tests/long-test.hs
@@ -0,0 +1,22 @@
+import Control.Monad
+import qualified Data.ABC as ABC
+import Data.ABC.AIG (AIG, Lit, Network)
+import qualified Data.ABC.AIG as AIG
+
+main :: IO ()
+main = do
+
+  ABC.initialize
+
+  n <- AIG.readAiger "tests/eijk.S298.S.aig"
+  c <- AIG.networkInputCount n
+  n2 <- constantNetwork c False
+
+  putStrLn "Calling cec"
+  print =<< AIG.cec n n2
+
+constantNetwork :: Int -> Bool -> IO (Network Lit AIG)
+constantNetwork i b = do
+  ABC.SomeGraph n <- AIG.newAIG
+  replicateM_ i (AIG.newInput n)
+  return (AIG.Network n [AIG.constant n b])
